[
  {
    "path": ".allstar/branch_protection.yaml",
    "content": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\ndismissStale: false\n"
  },
  {
    "path": ".browserslistrc",
    "content": "last 2 Chrome versions\nlast 2 Firefox versions\nlast 2 Safari versions\nlast 2 iOS versions\nlast 2 Edge versions\nlast 2 Opera versions\n"
  },
  {
    "path": ".distignore",
    "content": ".allstar\n.git\n.github\n.husky\n.idea\n.rollup.cache\n.storybook\n.wordpress-org\n__mocks__\n__static__\nassets/testjs\nbin\nbuild\ndocs\nincludes/composer.json\nkarma\nnode_modules\npackages\npatches\nplugin-assets\npublic\nsitemap-generator\nstatic\ntests\nthird-party/composer.json\n/vendor\nweb-stories-scraper\n.browserslistrc\n.DS_Store\n.distignore\n.editorconfig\n.eslintignore\n.eslintrc\n.git-blame-ignore-revs\n.gitattributes\n.gitignore\n.markdownlint.json\n.markdownlintignore\n.npmignore\n.npmpackagejsonlintrc.json\n.npmrc\n.nvmrc\n.oxlintrc.json\n.phpstorm.config.js\n.phpstorm.meta.php\n.phpunit.result.cache\n.prettierignore\n.prettierrc\n.stylelintignore\n.stylelintrc\n.test_artifacts\nbabel.config.cjs\nbun.lockb\ncodecov.yml\ncomposer.lock\nCONTRIBUTING.md\njest-puppeteer.config.cjs\njsconfig.json\nkarma-story-editor.config.cjs\nkarma-dashboard.config.cjs\npackage.json\npackage-lock.json\npercy.config.karma.yml\npercy.config.yml\nphpcs.xml\nphpcs.xml.dist\nphpmd.xml\nphpstan.neon\nphpstan.neon.dist\nphpunit.xml\nphpunit.xml.dist\nphpunit-integration.xml\nphpunit-integration.xml.dist\nphpunit-integration-multisite.xml\nphpunit-integration-multisite.xml.dist\nREADME.md\nrollup.config.js\nscoper.inc.php\ntsconfig.json\ntsconfig.shared.json\nwebpack.config.cjs\nwebpack.config.test.cjs\n"
  },
  {
    "path": ".editorconfig",
    "content": "# WordPress Coding Standards\n# https://make.wordpress.org/core/handbook/coding-standards/\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nindent_style = space\nindent_size = 2\n\n[*.php]\nindent_style = tab\nindent_size = 4\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".eslintignore",
    "content": "**/node_modules/**\n**/vendor/**\n**/dist/**\n**/dist-module/**\n**/dist-types/**\n**/assets/js/*.js\n**/packages/migration/scripts/module.js\nbin/build/*\nbuild/*\n!.storybook\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"root\": true,\n  \"parser\": \"@babel/eslint-parser\",\n  \"extends\": [\n    \"plugin:@wordpress/eslint-plugin/i18n\",\n    \"eslint:recommended\",\n    \"plugin:import/recommended\",\n    \"plugin:@eslint-community/eslint-comments/recommended\",\n    \"plugin:react/recommended\",\n    \"plugin:react-hooks/recommended-latest\",\n    \"plugin:prettier/recommended\",\n    \"plugin:jsx-a11y/recommended\",\n    \"plugin:jsdoc/recommended\",\n    \"plugin:styled-components-a11y/recommended\",\n    \"plugin:oxlint/recommended\"\n  ],\n  \"plugins\": [\n    \"@babel\",\n    \"@wordpress\",\n    \"header\",\n    \"jsdoc\",\n    \"jsx-a11y\",\n    \"markdown\",\n    \"react\",\n    \"react-hooks\",\n    \"styled-components-a11y\"\n  ],\n  \"parserOptions\": {\n    \"ecmaVersion\": \"latest\",\n    \"ecmaFeatures\": {\n      \"jsx\": true\n    }\n  },\n  \"rules\": {\n    \"array-callback-return\": \"error\",\n    \"block-scoped-var\": \"error\",\n    \"complexity\": [\"error\", {\"max\": 20}],\n    \"consistent-return\": \"error\",\n    \"curly\": [\"error\", \"all\"],\n    \"default-case\": \"error\",\n    \"eol-last\": \"error\",\n    \"eqeqeq\": \"error\",\n    \"guard-for-in\": \"error\",\n    \"no-await-in-loop\": \"error\",\n    \"no-constant-binary-expression\": \"error\",\n    \"no-extra-bind\": \"error\",\n    \"no-extra-label\": \"error\",\n    \"no-floating-decimal\": \"error\",\n    \"no-implicit-coercion\": \"error\",\n    \"no-implicit-globals\": \"error\",\n    \"no-implied-eval\": \"error\",\n    \"no-loop-func\": \"error\",\n    \"no-new\": \"error\",\n    \"no-new-func\": \"error\",\n    \"no-new-wrappers\": \"error\",\n    \"no-multiple-empty-lines\": \"error\",\n    \"no-trailing-spaces\": \"error\",\n    \"header/header\": [ \"error\", \"block\", [\n      \"\",\n      {\n        \"pattern\": \" \\\\* Copyright \\\\d{4} Google LLC\",\n        \"template\": \" * Copyright 2025 Google LLC\"\n      },\n      \" *\",\n      \" * Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\",\n      \" * you may not use this file except in compliance with the License.\",\n      \" * You may obtain a copy of the License at\",\n      \" *\",\n      \" *     https://www.apache.org/licenses/LICENSE-2.0\",\n      \" *\",\n      \" * Unless required by applicable law or agreed to in writing, software\",\n      \" * distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\",\n      \" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\",\n      \" * See the License for the specific language governing permissions and\",\n      \" * limitations under the License.\",\n      \" \"\n    ] ],\n    \"import/no-cycle\": \"error\",\n    \"import/no-restricted-paths\": [ \"error\", {\n      \"zones\": [ {\n        \"target\": \"./packages/migration/src/migrations\",\n        \"from\": \"./packages/story-editor/src\",\n        \"except\": [ \"./migration/migrations\" ]\n      }, {\n        \"target\": \"./packages/story-editor/src\",\n        \"from\": \"./packages/story-editor/src/utils/useWhyDidYouUpdate.js\"\n      } ]\n    } ],\n    \"import/dynamic-import-chunkname\": [ \"error\", {\n      \"webpackChunknameFormat\": \"[0-9a-zA-Z-_/.[\\\\]]+\"\n    } ],\n    \"import/no-useless-path-segments\": [\"error\", {\n      \"noUselessIndex\": true\n    }],\n    \"import/no-relative-packages\": \"error\",\n    \"import/no-internal-modules\": [ \"error\", {\n      \"forbid\": [ \"@googleforcreators/**/*\" ]\n    } ],\n    \"jsx-a11y/label-has-for\": \"off\",\n    \"jsx-a11y/media-has-caption\": [ \"error\", {\n      \"audio\": [ \"Audio\" ],\n      \"video\": [ \"Video\", \"FadedVideo\", \"CropVideo\", \"StyledVideo\" ],\n      \"track\": [ \"Track\" ]\n    }],\n    \"no-restricted-properties\": \"error\",\n    \"no-return-assign\": \"error\",\n    \"no-return-await\": \"error\",\n    \"no-sequences\": \"error\",\n    \"no-shadow\": [\"error\",\n      {\n        \"ignoreOnInitialization\": true\n      }\n    ],\n    \"no-template-curly-in-string\": \"error\",\n    \"no-throw-literal\": \"error\",\n    \"no-unmodified-loop-condition\": \"error\",\n    \"no-unused-vars\": [\n      \"error\",\n      {\n        \"ignoreRestSiblings\": true\n      }\n    ],\n    \"no-useless-call\": \"error\",\n    \"jsx-a11y/anchor-has-content\": \"off\",\n    \"no-useless-concat\": \"error\",\n    \"no-console\": \"error\",\n    \"no-duplicate-imports\": \"error\",\n    \"no-var\": \"error\",\n    \"prefer-arrow-callback\": [\n      \"error\",\n      {\n        \"allowNamedFunctions\": true\n      }\n    ],\n    \"prefer-const\": \"error\",\n    \"prefer-object-spread\": \"error\",\n    \"prefer-promise-reject-errors\": \"error\",\n    \"prefer-rest-params\": \"error\",\n    \"prefer-spread\": \"error\",\n    \"radix\": [\"error\", \"as-needed\"],\n    \"require-await\": \"error\",\n    \"rest-spread-spacing\": [\"error\", \"never\"],\n    \"react/forbid-component-props\": [\"error\", {\n      \"forbid\": [\"for\"]\n    }],\n    \"react/jsx-key\": \"error\",\n    \"react/no-array-index-key\": \"error\",\n    \"react/no-unknown-property\": [\n      \"error\",\n      {\n        \"ignore\": [\n          \"amp\",\n          \"amp-boilerplate\",\n          \"amp-custom\",\n          \"animate-in\",\n          \"animate-in-delay\",\n          \"animate-in-duration\",\n          \"custom-element\"\n        ]\n      }\n    ],\n    \"react/prop-types\": \"error\",\n    \"react-hooks/rules-of-hooks\": \"error\",\n    \"react-hooks/exhaustive-deps\": [\n      \"error\",\n      {\n        \"enableDangerousAutofixThisMayCauseInfiniteLoops\": false,\n        \"additionalHooks\": [\n          {\n            \"test\": \"useSelect$\",\n            \"callbackIndex\": 0\n          },\n          {\n            \"test\": \"useBatchingCallback\",\n            \"callbackIndex\": 0\n          },\n          {\n            \"test\": \"useKeyEffectInternal\",\n            \"callbackIndex\": 3\n          },\n          {\n            \"test\": \"useKeyEffect\",\n            \"callbackIndex\": 2\n          },\n          {\n            \"test\": \"useKeyDownEffect\",\n            \"callbackIndex\": 2\n          },\n          {\n            \"test\": \"useKeyUpEffect\",\n            \"callbackIndex\": 2\n          },\n          {\n            \"test\": \"useGlobalKeyDownEffect\",\n            \"callbackIndex\": 1\n          },\n          {\n            \"test\": \"useGlobalKeyUpEffect\",\n            \"callbackIndex\": 1\n          },\n          {\n            \"test\": \"useIntersectionEffect\",\n            \"callbackIndex\": 2\n          },\n          {\n            \"test\": \"useResizeEffect\",\n            \"callbackIndex\": 1\n          }\n        ]\n      }\n    ],\n    \"react/jsx-boolean-value\": \"error\",\n    \"react/jsx-fragments\": \"error\",\n    \"react/jsx-no-literals\": \"error\",\n    \"react/jsx-no-useless-fragment\": \"error\",\n    \"react/no-unused-prop-types\": \"error\",\n    \"react/react-in-jsx-scope\": \"off\",\n    \"react/self-closing-comp\": \"error\",\n    \"react-hooks/config\": \"error\",\n    \"react-hooks/error-boundaries\": \"error\",\n    \"react-hooks/component-hook-factories\": \"error\",\n    \"react-hooks/gating\": \"error\",\n    \"react-hooks/globals\": \"error\",\n    \"react-hooks/immutability\": \"error\",\n    \"react-hooks/preserve-manual-memoization\": \"error\",\n    \"react-hooks/purity\": \"error\",\n    \"react-hooks/refs\": \"error\",\n    \"react-hooks/set-state-in-effect\": \"error\",\n    \"react-hooks/set-state-in-render\": \"error\",\n    \"react-hooks/static-components\": \"error\",\n    \"react-hooks/unsupported-syntax\": \"warn\",\n    \"react-hooks/use-memo\": \"error\",\n    \"react-hooks/incompatible-library\": \"warn\",\n    \"import/no-extraneous-dependencies\": \"error\",\n    \"import/no-unresolved\": \"error\",\n    \"import/order\": [\n      \"error\",\n      {\n        \"groups\": [\n          \"builtin\",\n          [\"external\", \"unknown\"],\n          \"internal\",\n          \"parent\",\n          \"sibling\",\n          \"index\"\n        ]\n      }\n    ],\n    \"jsdoc/check-indentation\": \"error\",\n    \"jsdoc/check-syntax\": \"error\",\n    \"jsdoc/check-tag-names\": [\"error\", {\n      \"definedTags\": [ \"jest-environment\" ]\n    }],\n    \"jsdoc/reject-any-type\": \"off\",\n    \"jsdoc/reject-function-type\": \"off\",\n    \"jsdoc/require-jsdoc\": [\"off\", {\n      \"publicOnly\": true\n    }],\n    \"jsdoc/require-returns\": \"error\",\n    \"jsdoc/require-param-description\": \"error\",\n    \"jsdoc/tag-lines\": [\n      \"error\",\n      \"any\",\n      { \"startLines\": 1 }\n    ],\n    \"jsdoc/valid-types\": \"error\",\n    \"@eslint-community/eslint-comments/no-unused-disable\": \"error\",\n    \"@eslint-community/eslint-comments/require-description\": \"error\",\n    \"@wordpress/dependency-group\": \"error\",\n    \"@wordpress/i18n-no-flanking-whitespace\": \"error\",\n    \"@wordpress/no-unused-vars-before-return\": [\"error\", {\n      \"excludePattern\": \"^use\"\n    }],\n    \"@wordpress/react-no-unsafe-timeout\": \"error\",\n    \"@wordpress/i18n-text-domain\": [\"error\", {\n      \"allowedTextDomain\": \"web-stories\"\n    }],\n    \"@wordpress/valid-sprintf\": \"error\",\n    \"@babel/no-unused-expressions\": [\n      \"error\",\n      {\n        \"allowShortCircuit\": true\n      }\n    ]\n  },\n  \"env\": {\n    \"browser\": true,\n    \"es2020\": true\n  },\n  \"globals\": {\n    \"__webpack_public_path__\": \"writable\",\n    \"WEB_STORIES_CI\": \"readonly\",\n    \"WEB_STORIES_DISABLE_ERROR_BOUNDARIES\": \"readonly\",\n    \"WEB_STORIES_DISABLE_OPTIMIZED_RENDERING\": \"readonly\",\n    \"WEB_STORIES_DISABLE_PREVENT\": \"readonly\",\n    \"WEB_STORIES_DISABLE_QUICK_TIPS\": \"readonly\",\n    \"WEB_STORIES_ENV\": \"readonly\"\n  },\n  \"settings\": {\n    \"import/resolver\": {\n      \"@web-stories-wp/eslint-import-resolver\": {\n        \"mapping\": {\n          \"^@googleforcreators\\\\/(.*)\\\\/(.*)\": \"./packages/$1/src/$2\",\n          \"^@googleforcreators\\\\/(.*)\": \"./packages/$1/src/\",\n          \"^@web-stories-wp\\\\/(.*)\": \"./packages/$1/src/\"\n        },\n        \"extensions\": [ \".js\", \".jsx\", \".ts\", \".tsx\" ]\n      }\n    },\n    \"jsdoc\": {\n      \"mode\": \"typescript\",\n      \"preferredTypes\": {\n        \"object\": \"Object\"\n      },\n      \"tagNamePreference\": {\n        \"returns\": \"return\",\n        \"yields\": \"yield\"\n      }\n    },\n    \"react\": {\n      \"version\": \"detect\"\n    },\n    \"linkComponents\": [\n      \"Link\",\n      {\"name\": \"Plain\", \"linkAttribute\": \"href\"},\n      {\"name\": \"Primary\", \"linkAttribute\": \"href\"},\n      \"PrimaryLink\",\n      \"SecondaryLink\",\n      \"ExternalLink\",\n      \"ScrimAnchor\"\n    ],\n    \"testing-library/custom-renders\": [\n      \"arrange\",\n      \"renderWithTheme\",\n      \"renderWithProviders\",\n      \"renderPanel\",\n      \"setup\"\n    ]\n  },\n  \"overrides\": [\n    {\n      \"files\": [\n        \"**/*.ts\",\n        \"**/*.tsx\"\n      ],\n      \"plugins\": [\n        \"@typescript-eslint\"\n      ],\n      \"extends\": [\n        \"plugin:@typescript-eslint/recommended\",\n        \"plugin:@typescript-eslint/recommended-type-checked\"\n      ],\n      \"parser\": \"@typescript-eslint/parser\",\n      \"parserOptions\": {\n        \"projectService\": true,\n        \"warnOnUnsupportedTypeScriptVersion\": false\n      },\n      \"rules\": {\n        \"@typescript-eslint/no-shadow\": [\"error\",\n          {\n            \"ignoreOnInitialization\": true\n          }\n        ],\n        \"@typescript-eslint/unbound-method\": [\n          \"error\",\n          {\n            \"ignoreStatic\": true\n          }\n        ],\n        \"@typescript-eslint/no-unused-vars\": [\n          \"error\",\n          {\n            \"ignoreRestSiblings\": true\n          }\n        ],\n        \"react/prop-types\": \"off\",\n        \"getter-return\": \"off\",\n        \"jsdoc/check-param-names\": \"off\",\n        \"jsdoc/require-param\": \"off\",\n        \"jsdoc/require-param-type\": \"off\",\n        \"jsdoc/require-returns\": \"off\",\n        \"jsdoc/require-returns-check\": \"off\",\n        \"jsdoc/require-returns-type\": \"off\",\n        \"jsdoc/no-types\": \"error\",\n        \"no-duplicate-imports\": \"off\",\n        \"no-unused-vars\": \"off\",\n        \"no-shadow\": \"off\",\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"prop-types\",\n                \"message\": \"Use TypeScript instead.\"\n              }\n            ]\n          }\n        ],\n        \"import/no-unresolved\": \"off\",\n        \"import/default\": \"off\",\n        \"import/named\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"typings/**/*.ts\",\n        \"**/*.d.ts\"\n      ],\n      \"rules\": {\n        \"no-undef\": \"off\",\n        \"no-unused-vars\": \"off\",\n        \"no-var\": \"off\",\n        \"@wordpress/dependency-group\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"__mocks__/**/*.js\",\n        \"**/test/**/*.js\",\n        \"**/test/**/*.ts\",\n        \"**/testUtils/**/*.js\",\n        \"**/testUtils/**/*.ts\",\n        \"tests/js/**/*.js\"\n      ],\n      \"excludedFiles\": [\n        \"**/karma/**/*.js\",\n        \"**/test/**/*.karma.js\"\n      ],\n      \"extends\": [\n        \"plugin:jest/all\",\n        \"plugin:testing-library/react\",\n        \"plugin:jest-dom/recommended\",\n        \"plugin:jest-extended/all\"\n      ],\n      \"plugins\": [\n        \"jsx-a11y\",\n        \"header\",\n        \"testing-library\",\n        \"jest-dom\"\n      ],\n      \"env\": {\n        \"node\": true\n      },\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"react/prop-types\": \"off\",\n        \"react-hooks/globals\": \"off\",\n        \"react-hooks/immutability\": \"off\",\n        \"jest/no-hooks\": \"off\",\n        \"jest/no-untyped-mock-factory\": \"off\",\n        \"jest/max-expects\": \"off\",\n        \"jest/prefer-expect-assertions\": \"off\",\n        \"jest/prefer-importing-jest-globals\": \"off\",\n        \"jest/prefer-inline-snapshots\": \"off\",\n        \"jest/prefer-lowercase-title\": [\n          \"error\",\n          {\n            \"ignore\": [\"describe\"]\n          }\n        ],\n        \"jest/prefer-mock-promise-shorthand\": \"off\",\n        \"jest/prefer-snapshot-hint\": \"off\",\n        \"jest/unbound-method\": \"off\",\n        \"jest/padding-around-all\": \"off\",\n        \"jest/padding-around-after-each-blocks\": \"off\",\n        \"jest/padding-around-after-all-blocks\": \"off\",\n        \"jest/padding-around-before-all-blocks\": \"off\",\n        \"jest/padding-around-before-each-blocks\": \"off\",\n        \"jest/padding-around-describe-blocks\": \"off\",\n        \"jest/padding-around-expect-groups\": \"off\",\n        \"jest/padding-around-test-blocks\": \"off\",\n        \"jest/prefer-ending-with-an-expect\": \"off\",\n        \"jsdoc/require-jsdoc\": \"off\",\n        \"testing-library/no-await-sync-events\": \"error\",\n        \"testing-library/no-debugging-utils\": \"error\",\n        \"testing-library/no-dom-import\": \"error\"\n      }\n    },\n    {\n      \"files\": [\n        \"**/test/**/*.ts\",\n        \"**/testUtils/**/*.ts\"\n      ],\n      \"rules\": {\n        \"@typescript-eslint/unbound-method\": \"off\",\n        \"jest/unbound-method\": \"error\",\n        \"jest/no-untyped-mock-factory\": \"error\"\n      }\n    },\n    {\n      \"files\": [\n        \"__mocks__/**/*.js\"\n      ],\n      \"rules\": {\n        \"jest/require-hook\":  \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"**/karma/**/*.js\",\n        \"packages/karma-*/**/*.js\"\n      ],\n      \"extends\": [\n        \"plugin:jasmine/recommended\"\n      ],\n      \"plugins\": [\n        \"jsx-a11y\",\n        \"header\",\n        \"testing-library\",\n        \"jasmine\"\n      ],\n      \"env\": {\n        \"jasmine\": true,\n        \"node\": true\n      },\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"testing-library/no-await-sync-events\": \"error\",\n        \"testing-library/no-await-sync-queries\": \"error\",\n        \"testing-library/no-debugging-utils\": \"error\",\n        \"testing-library/no-dom-import\": \"error\",\n        \"jasmine/new-line-before-expect\": \"off\",\n        \"jasmine/no-disabled-tests\": \"error\",\n        \"jasmine/no-spec-dupes\": [\"error\", \"branch\"],\n        \"jasmine/no-suite-dupes\": [\"error\", \"branch\"],\n        \"jsdoc/require-jsdoc\": \"off\",\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"@testing-library/react-hooks\",\n                \"message\": \"Use karma fixtures instead.\"\n              }\n            ]\n          }\n        ]\n      },\n      \"globals\": {\n        \"karmaPuppeteer\": \"readonly\",\n        \"karmaSnapshot\": \"readonly\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/karma-puppeteer-client/**/*.js\"\n      ],\n      \"rules\": {\n        \"no-var\": \"off\",\n        \"prefer-const\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/jest-amp/src/**/*.js\",\n        \"packages/jest-puppeteer-amp/src/**/*.js\"\n      ],\n      \"env\": {\n        \"node\": true\n      }\n    },\n    {\n      \"files\": [\n        \"packages/jest-puppeteer-amp/src/**/*.js\"\n      ],\n      \"globals\": {\n        \"browser\": \"readonly\",\n        \"page\": \"readonly\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/e2e-test-utils/**/*.js\",\n        \"packages/e2e-tests/src/**/*.js\"\n      ],\n      \"extends\": [\n        \"plugin:jest/all\"\n      ],\n      \"env\": {\n        \"node\": true\n      },\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"jest/max-expects\": \"off\",\n        \"jest/no-hooks\": \"off\",\n        \"jest/prefer-ending-with-an-expect\": \"off\",\n        \"jest/prefer-expect-assertions\": \"off\",\n        \"jest/prefer-importing-jest-globals\": \"off\",\n        \"jest/prefer-inline-snapshots\": \"off\",\n        \"jest/prefer-lowercase-title\": [\n          \"error\",\n          {\n            \"ignore\": [\"describe\"]\n          }\n        ],\n        \"jest/require-hook\": [\n          \"error\",\n          {\n            \"allowedFunctionCalls\": [\n              \"minWPVersionRequired\",\n              \"withDisabledToolbarOnFrontend\",\n              \"withExperimentalFeatures\",\n              \"withPlugin\",\n              \"withRTL\",\n              \"withUser\"\n            ]\n          }\n        ],\n        \"jest/prefer-snapshot-hint\": \"off\",\n        \"jest/unbound-method\": \"off\",\n        \"jest/padding-around-all\": \"off\",\n        \"jest/padding-around-after-each-blocks\": \"off\",\n        \"jest/padding-around-after-all-blocks\": \"off\",\n        \"jest/padding-around-before-all-blocks\": \"off\",\n        \"jest/padding-around-before-each-blocks\": \"off\",\n        \"jest/padding-around-describe-blocks\": \"off\",\n        \"jest/padding-around-expect-groups\": \"off\",\n        \"jest/padding-around-test-blocks\": \"off\"\n      },\n      \"globals\": {\n        \"browser\": \"readonly\",\n        \"page\": \"readonly\",\n        \"wp\": \"readonly\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/e2e-test-utils/**/*.js\"\n      ],\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"jest/expect-expect\": \"off\",\n        \"jest/max-expects\": \"off\",\n        \"jest/no-export\": \"off\",\n        \"jest/require-top-level-describe\": \"off\"\n      }\n    },\n    {\n      \"files\": [\"packages/e2e-tests/src/specs/**/*.js\"],\n      \"rules\": {\n        \"jsdoc/require-jsdoc\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/e2e-tests/src/config/**/*.js\",\n        \"**/testUtils/**/*.js\"\n      ],\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"jest/require-hook\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/commander/**/*.ts\",\n        \"packages/fonts/scripts/**/*.ts\",\n        \"packages/migration/scripts/**/*.js\",\n        \"packages/templates/scripts/**/*.js\",\n        \"packages/text-sets/scripts/**/*.js\"\n      ],\n      \"rules\": {\n        \"import/no-useless-path-segments\": [\"error\", {\n          \"noUselessIndex\": false\n        }]\n      }\n    },\n    {\n      \"files\": [\n        \"__mocks__/**/*.js\",\n        \"bin/**/*.js\",\n        \"babel.config.cjs\",\n        \"rollup.config.js\",\n        \"jest-puppeteer.config.cjs\",\n        \"karma-*.config.cjs\",\n        \"webpack.*.cjs\",\n        \".storybook/*.cjs\",\n        \".storybook/*.js\",\n        \"tests/js/*.js\",\n        \"packages/e2e-tests/src/*.js\",\n        \"packages/e2e-tests/src/config/*.js\",\n        \"packages/dashboard/src/karma-tests.cjs\",\n        \"packages/story-editor/src/karma-tests.cjs\",\n        \"packages/eslint-import-resolver/**/*.cjs\",\n        \"packages/jest-resolver/**/*.cjs\",\n        \"packages/fonts/**/*.ts\",\n        \"packages/commander/**/*.ts\",\n        \"packages/migration/scripts/**/*.js\",\n        \"packages/templates/scripts/**/*.js\",\n        \"packages/text-sets/scripts/**/*.js\"\n      ],\n      \"extends\": [\n        \"plugin:n/recommended\",\n        \"plugin:security/recommended-legacy\"\n      ],\n      \"plugins\": [\n        \"security\"\n      ],\n      \"env\": {\n        \"node\": true\n      },\n      \"rules\": {\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"n/no-extraneous-import\": \"off\",\n        \"n/no-missing-import\": \"off\",\n        \"n/no-unpublished-import\": \"off\",\n        \"n/no-unpublished-require\": \"off\",\n        \"security/detect-non-literal-fs-filename\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/commander/src/index.ts\"\n      ],\n      \"rules\": {\n        \"no-console\": \"off\",\n        \"n/hashbang\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/migration/scripts/utils/updateTemplates.js\"\n      ],\n      \"rules\": {\n        \"@eslint-community/eslint-comments/no-unused-disable\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"*.md\",\n        \"**/*.md\"\n      ],\n      \"processor\": \"markdown/markdown\"\n    },\n    {\n      \"files\": [\n        \"**/*.md/*.js\"\n      ],\n      \"parserOptions\": {\n        \"ecmaFeatures\": {\n          \"impliedStrict\": true\n        }\n      },\n      \"rules\": {\n        \"import/no-unresolved\": \"off\",\n        \"import/no-extraneous-dependencies\": \"off\",\n        \"@wordpress/dependency-group\": \"off\",\n        \"no-console\": \"off\",\n        \"no-undef\": \"off\",\n        \"no-unused-vars\": \"off\",\n        \"header/header\": \"off\",\n        \"prettier/prettier\": \"off\",\n        \"@eslint-community/eslint-comments/require-description\": \"off\",\n        \"react/prop-types\" : \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/dashboard/src/**/*.js\",\n        \"packages/story-editor/src/**/*.js\",\n        \"packages/**/*.js\"\n      ],\n      \"excludedFiles\": [\n        \"packages/activation-notice/**/*.tsx\",\n        \"packages/i18n/**/*.js\",\n        \"packages/stories-block/**/*.js\",\n        \"packages/tinymce-button/**/*.js\"\n      ],\n      \"rules\":{\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"@wordpress/i18n\",\n                \"message\": \"Use @googleforcreators/i18n instead.\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"files\": [\n        \"packages/activation-notice/**/*.tsx\",\n        \"packages/stories-block/**/*.js\",\n        \"packages/tinymce-button/**/*.js\"\n      ],\n      \"rules\":{\n        \"@wordpress/data-no-store-string-literals\": \"error\",\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"@googleforcreators/i18n\",\n                \"message\": \"Use @wordpress/i18n instead.\"\n              },\n              {\n                \"name\": \"react\",\n                \"message\": \"Please use React API through `@wordpress/element` instead.\"\n              },\n              {\n                \"name\": \"react-dom\",\n                \"message\": \"Please use React API through `@wordpress/element` instead.\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"files\": [\n        \"packages/**/*.js\"\n      ],\n      \"excludedFiles\": [\n        \".storybook/preview.js\",\n        \"__mocks__/**/*.js\",\n        \"packages/activation-notice/**/*.tsx\",\n        \"packages/react/**/*.js\",\n        \"packages/dashboard/src/karma/fixture.js\",\n        \"packages/story-editor/src/karma/fixture/fixture.js\",\n        \"packages/story-block/**/*.js\",\n        \"packages/tinymce-button/**/*.js\"\n      ],\n      \"rules\":{\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"react\",\n                \"message\": \"Use @googleforcreators/react instead.\"\n              },\n              {\n                \"name\": \"react-dom\",\n                \"message\": \"Use @googleforcreators/react instead.\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"files\": [\n        \"packages/activation-notice/**/*.tsx\"\n      ],\n      \"rules\":{\n        \"no-restricted-imports\": \"off\",\n        \"import/no-named-as-default\": \"off\",\n        \"@typescript-eslint/no-restricted-imports\": [\n          \"error\",\n          {\n            \"paths\": [\n              {\n                \"name\": \"react\",\n                \"message\": \"Use @wordpress/element instead.\",\n                \"allowTypeImports\": true\n              },\n              {\n                \"name\": \"react-dom\",\n                \"message\": \"Use @wordpress/element instead.\",\n                \"allowTypeImports\": true\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"files\": [\n        \"packages/tinymce-button/src/**/*.js\"\n      ],\n      \"globals\": {\n        \"tinymce\": \"readonly\"\n      }\n    },\n    {\n      \"files\": [\n        \"**/stories/*.js\",\n        \".storybook/main.cjs\"\n      ],\n      \"rules\": {\n        \"react/no-array-index-key\" : \"off\",\n        \"react/prop-types\": \"off\",\n        \"@eslint-community/eslint-comments/no-unused-disable\": \"off\",\n        \"@eslint-community/eslint-comments/require-description\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"__mocks__/**/*\",\n        \".storybook/stories/**/*\"\n      ],\n      \"rules\": {\n        \"import/no-extraneous-dependencies\" : \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/story-editor/src/**/*.js\",\n        \"packages/dashboard/src/**/*.js\"\n      ],\n      \"rules\": {\n        \"no-restricted-imports\": [\n          \"error\",\n          {\n            \"patterns\": [\n              {\n                \"group\": [\n                  \"**/*.css\"\n                ],\n                \"message\": \"css import is not allowed in story-editor and dashboard\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"files\": [\n        \"packages/date/src/third_party/**/*\"\n      ],\n      \"rules\": {\n        \"header/header\": \"off\",\n        \"@typescript-eslint/no-explicit-any\": \"off\",\n        \"@typescript-eslint/ban-ts-comment\": \"off\",\n        \"@typescript-eslint/no-unsafe-return\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/story-editor/src/components/canvas/mediaCaptions/cue.js\"\n      ],\n      \"rules\": {\n        \"@eslint-community/eslint-comments/no-unused-disable\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"packages/design-system/src/components/keyboard/keyboard.tsx\",\n        \"packages/element-library/src/media/editCropMoveable.tsx\",\n        \"packages/element-library/src/media/editPanMoveable.tsx\",\n        \"packages/element-library/src/text/edit.tsx\",\n        \"packages/element-library/src/video/playPauseButton.tsx\",\n        \"packages/react/src/useBatchingCallback.ts\",\n        \"packages/react/src/useResizeEffect.ts\",\n        \"packages/story-editor/src/app/helpCenter/provider.tsx\",\n        \"packages/story-editor/src/app/media/media3p/useContextValueProvider.js\",\n        \"packages/story-editor/src/app/media/media3p/useFetchMediaEffect.js\",\n        \"packages/story-editor/src/app/quickActions/useQuickActions.js\",\n        \"packages/story-editor/src/components/canvas/mediaRecordingLayer.js\",\n        \"packages/story-editor/src/components/canvas/multiSelectionMoveable/useDrag.js\",\n        \"packages/story-editor/src/components/canvas/multiSelectionMoveable/useResize.js\",\n        \"packages/story-editor/src/components/canvas/multiSelectionMoveable/useRotate.js\",\n        \"packages/story-editor/src/components/canvas/singleSelectionMoveable/index.js\",\n        \"packages/story-editor/src/components/canvas/singleSelectionMoveable/useDrag.js\",\n        \"packages/story-editor/src/components/canvas/singleSelectionMoveable/useResize.js\",\n        \"packages/story-editor/src/components/canvas/singleSelectionMoveable/useRotate.js\",\n        \"packages/story-editor/src/components/canvas/utils/useUpdateSelectionRectangle.js\",\n        \"packages/story-editor/src/components/colorPicker/editablePreview.js\",\n        \"packages/story-editor/src/components/form/usePresubmitHandler.js\",\n        \"packages/story-editor/src/components/library/panes/shopping/shoppingPane.js\",\n        \"packages/story-editor/src/components/mediaRecording/audio.js\",\n        \"packages/story-editor/src/components/mediaRecording/footer.js\",\n        \"packages/story-editor/src/components/panels/shared/useCommonObjectValue.js\",\n        \"packages/story-editor/src/components/videoTrim/useVideoNode.js\",\n        \"packages/transform/src/useTransformHandler.ts\",\n        \"packages/wp-story-editor/src/components/fontCheck/index.js\"\n      ],\n      \"rules\": {\n        \"react-hooks/refs\": \"off\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "bf0cb0583153e71fcceaee044550ad511b94d470\n1e93c55d2c9e596404646a3bd1785f6249f9945c\nfe28ba3ced458b23fc53574bb25d6d3fbe6a4b3f\ne6594d05a23cbd026f51668adc652fda959febbb\nf459efbc4a2c9546a0ca2fed1301e4f222fa2340\n72c8fa5e2419876f20507240314d0acbb825059d\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.snap linguist-generated=true\n.github export-ignore\n.storybook export-ignore\n.wordpress-org export-ignore\n__mocks__ export-ignore\n__static__ export-ignore\nbin export-ignore\nkarma export-ignore\npatches export-ignore\ntests export-ignore\n.* export-ignore\n*.config.cjs export-ignore\n*.config.test.cjs export-ignore\ncodecov.yml export-ignore\npackage.json export-ignore\npackage-lock.json export-ignore\npercy.config.yml export-ignore\n*.xml.dist export-ignore\npackages/fonts/src/fonts.json linguist-generated=true\nincludes/data/fonts/fonts.json linguist-generated=true\ntests/phpunit/integration/data/schema.json linguist-generated=true\npackages/e2e-tests/src/specs/editor/shopping/schema.json linguist-generated=true\ntsconfig.json linguist-language=jsonc\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug Report\nabout: Create a report to help us improve.\ntitle: ''\nlabels: 'Type: Bug'\nassignees: ''\n---\n\n<!--\nNOTE: For help requests, support questions, or general feedback,\nplease use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/\n-->\n\n## Bug Description\n\n<!-- A clear and concise description of what the bug is. -->\n\n## Expected Behaviour\n\n<!-- Please describe clearly and concisely what the expected behaviour should be. -->\n\n## Steps to Reproduce\n\n<!-- Please provide detailed steps on how to reproduce the bug. -->\n\n## Screenshots\n\n<!--\nIf applicable, please add screenshots to help explain your problem.\nBonus points for videos!\n-->\n\n## Additional Context\n\n<!-- Please complete the following information. -->\n\n- Plugin Version:\n- WordPress Version:\n- Operating System:\n- Browser:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "# todo: disable in future?\nblank_issues_enabled: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enhancement.md",
    "content": "---\nname: Enhancement\nabout: Suggest an idea for this project.\ntitle: ''\nlabels: 'Type: Enhancement'\nassignees: ''\n---\n\n<!-- NOTE: For help requests, support questions, or general feedback, please use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/ -->\n\n## Feature Description\n\n<!-- A clear and concise description of what the problem is and what you want to happen. -->\n\n## Alternatives Considered\n\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\n\n## Additional Context\n\n<!-- Add any other context or screenshots about the feature request. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/epic.md",
    "content": "---\nname: Epic\nabout: A theme of work that contains several issues or sub-tasks.\ntitle: ''\nlabels: 'Epic'\nassignees: ''\n---\n\n## Summary\n\n<!-- A brief description of what this feature or collection of work should accomplish. -->\n\n## References\n\n<!-- List any relevant links here e.g. mocks in Figma, product or engineering briefs, etc. -->\n\n## Alternatives Considered\n\n<!-- What alternative solutions to the proposal have we considered, if any? What were their trade-offs? -->\n\n## Acceptance Criteria\n\n### Does this epic have any performance impact?\n\n<!-- How might this epic affect user-perceived performance? -->\n\n<!-- After implementation, did you verify that there any impact? Was it positive, neutral or regressive? -->\n\n### Does this epic have telemetry?\n\n<!-- Should we collect usage metrics or other instrumentation data for this epic? -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/task.md",
    "content": "---\nname: Task\nabout: Tasks which do not involve engineering.\ntitle: ''\nlabels: 'Type: Task'\nassignees: ''\n---\n\n<!-- NOTE: For help requests, support questions, or general feedback, please use the WordPress.org forums instead: https://wordpress.org/support/plugin/web-stories/ -->\n\n## Task Description\n\n<!-- A clear and concise description of what this task is about. -->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Summary\n\n<!-- A brief description of what this PR does. -->\n\n## User-facing changes\n\n<!--\nPlease describe your changes.\nInclude before/after screenshots or a short video.\n-->\n\n## Testing Instructions\n\n<!--\nHow can the changes in this PR be verified?\nPlease provide step-by-step instructions how to reproduce the issue, if applicable.\nWrite step-by-step test instructions aimed at non-tech-savvy users, even if the PR is not user-facing.\n-->\n\n<!-- ignore-task-list-start -->\n\n- [ ] This is a non-user-facing change and requires no QA\n<!-- ignore-task-list-end -->\n\nThis PR can be tested by following these steps:\n\n1.\n\n## Reviews\n\n### Does this PR have a security-related impact?\n\n<!-- Examples: new APIs, changes to KSES, etc.  -->\n\n### Does this PR change what data or activity we track or use?\n\n<!-- Examples: changes to telemetry, new third-party APIs -->\n\n### Does this PR have a legal-related impact?\n\n<!-- Examples: new images with unknown sources, new production dependencies with incompatible licenses -->\n\n## Checklist\n\n<!-- Check these after PR creation -->\n\n- [ ] This PR addresses an existing issue and I have linked this PR to it\n- [ ] I have tested this code to the best of my abilities\n- [ ] I have verified accessibility to the best of my abilities ([docs](https://github.com/googleforcreators/web-stories-wp/blob/main/docs/accessibility-testing.md))\n- [ ] I have verified i18n and l10n (translation, right-to-left layout) to the best of my abilities\n- [ ] This code is covered by automated tests (unit, integration, and/or e2e) to verify it works as intended ([docs](https://github.com/googleforcreators/web-stories-wp/tree/main/docs#testing))\n- [ ] I have added documentation where necessary\n- [ ] I have added a matching `Type: XYZ` label to the PR\n\n---\n\n<!--\nPlease reference the issue(s) this PR addresses.\nNo URLs, just the issue numbers.\nUse \"Fixes #123\" if it fixes an issue.\n\nNOTE: One reference per line!\n\nExample:\n\nFixes #123\nPartially addresses #456\nSee #789\n-->\n\nFixes #\n"
  },
  {
    "path": ".github/SUPPORT.md",
    "content": "Thank you for being an early adopter of Web Stories for WordPress! We're working around the clock to improve your experience and add editing capabilities. If you find any issues, please reach out by visiting the [support forum](https://wordpress.org/support/plugin/web-stories/) to ask any questions or file feature requests.\n\n[Visit support forums](https://wordpress.org/support/plugin/web-stories/)\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: '/'\n    schedule:\n      interval: quarterly\n    open-pull-requests-limit: 10\n    labels:\n      - Dependencies\n    groups:\n      github-actions:\n        patterns:\n          - '*'\n\n  - package-ecosystem: npm\n    directory: '/'\n    schedule:\n      interval: quarterly\n    open-pull-requests-limit: 15\n    labels:\n      - Dependencies\n      - JavaScript\n    groups:\n      wp-packages:\n        patterns:\n          - '@wordpress/*'\n        exclude-patterns:\n          - '@wordpress/element'\n      storybook:\n        patterns:\n          - 'storybook'\n          - '@storybook/*'\n      typescript-eslint:\n        patterns:\n          - '@typescript-eslint/*'\n      babel:\n        patterns:\n          - 'babel-*'\n          - '@babel/*'\n        exclude-patterns:\n          - 'babel-plugin-react-compiler'\n      oxlint:\n        patterns:\n          - 'oxlint'\n          - 'eslint-plugin-oxlint'\n      react-compiler:\n        patterns:\n          - '*-react-compiler'\n          - 'react-compiler-*'\n    ignore:\n      # styled-components is not yet compatible.\n      - dependency-name: 'stylis-plugin-rtl'\n        versions:\n          - '>= 2'\n\n      # Not all plugins are compatible yet\n      - dependency-name: 'rollup'\n        versions:\n          - '>= 3'\n\n      # We have not yet upgraded to React 18.\n      - dependency-name: 'react'\n        versions:\n          - '>= 18'\n      - dependency-name: 'react-dom'\n        versions:\n          - '>= 18'\n      - dependency-name: '@testing-library/react'\n        versions:\n          - '>= 13'\n\n      # ESM only\n      - dependency-name: 'use-context-selector'\n        versions:\n          - '>= 2'\n      - dependency-name: 'flagged'\n        versions:\n          - '>= 3'\n      - dependency-name: 'mime'\n        versions:\n          - '>= 4'\n\n      # Needs manual update\n      - dependency-name: 'styled-components'\n        versions:\n          - '>= 6'\n\n      # Needs manual update\n      - dependency-name: 'eslint'\n        versions:\n          - '>= 9'\n\n  - package-ecosystem: composer\n    directory: '/'\n    schedule:\n      interval: quarterly\n    open-pull-requests-limit: 10\n    labels:\n      - Dependencies\n      - PHP\n"
  },
  {
    "path": ".github/release.yml",
    "content": "changelog:\n  exclude:\n    authors:\n      - dependabot\n      - github-actions\n      - googleforcreators-bot\n  categories:\n    - title: '🚀 Features'\n      labels:\n        - 'Type: Enhancement'\n    - title: '🐛 Bug Fixes'\n      labels:\n        - 'Type: Bug'\n    - title: '🧰 Maintenance'\n      labels:\n        - 'Type: Infrastructure'\n        - 'Type: Code Quality'\n    - title: ':memo: Documentation'\n      labels:\n        - 'Type: Documentation'\n    - title: 'Other Changes'\n      labels:\n        - '*'\n"
  },
  {
    "path": ".github/workflows/build-and-deploy.yml",
    "content": "name: Build plugin\n\non:\n  push:\n    # Don't run for irrelevant changes.\n    paths-ignore:\n      - 'docs/**'\n      - '.storybook/**'\n      - '.wordpress-org/**'\n      - '__mocks__/**'\n      - '__static__/**'\n      - 'bin/**'\n      - 'packages/e2e-test-utils/**'\n      - 'packages/e2e-tests/**'\n      - 'packages/karma-*/**'\n      - 'tests/**'\n      - '**.md'\n      - '**.yml'\n      - '**.neon.dist'\n      - '**.xml.dist'\n      - '.editorconfig'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.phpstorm.meta.php'\n      - '.prettier*'\n      - '.stylelint*'\n      - '.github/workflows/**'\n      - '!.github/workflows/build-and-deploy.yml'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    types:\n      - opened\n      - reopened\n      - synchronize\n      - ready_for_review\n    # Don't run for irrelevant changes.\n    paths-ignore:\n      - 'docs/**'\n      - '.storybook/**'\n      - '.wordpress-org/**'\n      - '__mocks__/**'\n      - '__static__/**'\n      - 'bin/**'\n      - 'packages/e2e-test-utils/**'\n      - 'packages/e2e-tests/**'\n      - 'packages/karma-*/**'\n      - 'tests/**'\n      - '**.md'\n      - '**.yml'\n      - '**.neon.dist'\n      - '**.xml.dist'\n      - '.editorconfig'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.phpstorm.meta.php'\n      - '.prettier*'\n      - '.stylelint*'\n      - '.github/workflows/**'\n      - '!.github/workflows/build-and-deploy.yml'\n\npermissions:\n  contents: read\n  pull-requests: write\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  bundle-size:\n    name: Bundle size check\n    runs-on: ubuntu-latest\n    timeout-minutes: 15\n    # The action cannot annotate the PR when run from a PR fork or authored by Dependabot.\n    if: >\n      github.event_name == 'pull_request' &&\n      github.event.pull_request.draft == false &&\n      github.event.pull_request.head.repo.fork == false &&\n      github.event.pull_request.user.login != 'dependabot[bot]'\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: block\n          allowed-endpoints: >\n            cloudresourcemanager.googleapis.com:443\n            codeserver.dev.6b7f1eeb-705b-4201-864d-2007030c8372.drush.in:2222\n            dl.google.com:443\n            github.com:443\n            api.github.com:443\n            oauth2.googleapis.com:443\n            objects.githubusercontent.com:443\n            packagist.org:443\n            registry.npmjs.org:443\n            storage.googleapis.com:443\n            54.185.253.63:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Bundle size check\n        uses: preactjs/compressed-size-action@66325aad6443cb7cf89c4bfcd414aea2367cda94\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n          pattern: '{assets/js/*.js,assets/css/*.css}'\n          build-script: 'build:js'\n          minimum-change-threshold: 100\n          # Ignore chunk and module hashes in bundle filenames.\n          strip-hash: '.*-(\\w{20})|^(\\d{2,5})\\.js$'\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "name: CodeQL\n\non:\n  push:\n    # Only run if JS files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if JS files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n    # The branches below must be a subset of the branches above\n    branches:\n      - main\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n    timeout-minutes: 30\n    steps:\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13\n        with:\n          languages: javascript\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13\n"
  },
  {
    "path": ".github/workflows/deploy-storybook.yml",
    "content": "name: Deploy to GH Pages\n\non:\n  push:\n    # Don't run for irrelevant changes.\n    paths-ignore:\n      - 'docs/**'\n      - '!.github/workflows/deploy-storybook.yml'\n      - '.storybook/**'\n      - '.wordpress-org/**'\n      - '__mocks__/**'\n      - '__static__/**'\n      - 'bin/**'\n      - 'tests/**'\n    branches:\n      - main\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build-storybook:\n    name: Build storybook\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write # for Git to git push\n    timeout-minutes: 10\n    steps:\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Build storyook\n        run: npm run storybook:build\n\n      - name: Checkout gh-pages\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          ref: gh-pages\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n          path: gh-pages\n\n      - name: Move storybook assets\n        run: |\n          rm -rf gh-pages/storybook/*\n          mv build/storybook/* gh-pages/storybook/\n\n      - name: Commit updates\n        run: |\n          git add .\n          git status\n          git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 0\n          git commit -m \"Deploy storybook for ${{ github.sha }}\"\n          git pull --rebase --no-edit --quiet\n          git push origin gh-pages\n        env:\n          GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n          GIT_AUTHOR_NAME: googleforcreators-bot\n          GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n          GIT_COMMITTER_NAME: googleforcreators-bot\n        working-directory: ./gh-pages\n"
  },
  {
    "path": ".github/workflows/lint-css-js-md.yml",
    "content": "name: Lint CSS/JS/MD\n\non:\n  push:\n    # Only run if CSS/JS/MD-related files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**.css'\n      - 'docs/**/*.md'\n      - 'packages/**/*.md'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.npmpackagejsonlintrc.json'\n      - '.nvmrc'\n      - '.prettier*'\n      - '.stylelint*'\n      - '**/package.json'\n      - 'package-lock.json'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if CSS/JS/MD-related files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**.css'\n      - 'docs/**/*.md'\n      - 'packages/**/*.md'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.npmpackagejsonlintrc.json'\n      - '.nvmrc'\n      - '.prettier*'\n      - '.stylelint*'\n      - '**/package.json'\n      - 'package-lock.json'\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\njobs:\n  lint:\n    name: Lint\n    runs-on: ubuntu-latest\n    permissions:\n      checks: write # for ataylorme/eslint-annotate-action to create checks\n      contents: read # for actions/checkout to fetch code\n      pull-requests: read # for ataylorme/eslint-annotate-action to get changed PR files\n    timeout-minutes: 20\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-sudo: true\n          disable-file-monitoring: true\n          egress-policy: block\n          allowed-endpoints: >\n            api.github.com:443\n            github.com:443\n            registry.npmjs.org:443\n            bun.sh:443\n            54.185.253.63:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Markdown Lint\n        run: npm run lint:md\n\n      - name: CSS Lint\n        run: npm run lint:css\n\n      - name: package.json Lint\n        run: npm run lint:package-json\n\n      # Do this first so that the types are available to ESLint,\n      # particularly the more sophisticated `@typescript/eslint` rules.\n      - name: Type checking\n        run: npm run workflow:bundle-packages:types\n\n      - name: JS Lint\n        run: npm run lint:js\n        env:\n          NODE_OPTIONS: --max-old-space-size=4096\n        if: >\n          github.event.pull_request.head.repo.fork == true ||\n          github.event.pull_request.user.login == 'dependabot[bot]'\n\n      - name: JS Lint Report\n        run: npm run lint:js:report\n        continue-on-error: true\n        env:\n          NODE_OPTIONS: --max-old-space-size=4096\n        # Prevent generating the ESLint report if PR is from a fork or authored by Dependabot.\n        if: >\n          github.event.pull_request.head.repo.fork == false &&\n          github.event.pull_request.user.login != 'dependabot[bot]'\n\n      - name: Annotate JS Lint Results\n        uses: ataylorme/eslint-annotate-action@3.0.0\n        with:\n          repo-token: '${{ secrets.GITHUB_TOKEN }}'\n          report-json: 'build/lint-js-report.json'\n        # The action cannot annotate the PR when run from a PR fork or authored by Dependabot.\n        if: >\n          github.event.pull_request.head.repo.fork == false &&\n          github.event.pull_request.user.login != 'dependabot[bot]'\n\n      - name: JSON Schema validation\n        run: npm run test:schema\n"
  },
  {
    "path": ".github/workflows/lint-i18n.yml",
    "content": "name: Lint I18N\n\non:\n  push:\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'web-stories.php'\n      - 'includes/**.php'\n      - '.github/workflows/lint-i18n.yml'\n    branches:\n      - main\n  pull_request:\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'web-stories.php'\n      - 'includes/**.php'\n      - '.github/workflows/lint-i18n.yml'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  lint:\n    name: Lint\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          coverage: none\n          tools: wp-cli\n\n      - name: Install latest version of i18n-command\n        run: wp package install wp-cli/i18n-command:@stable\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          coverage: none\n          tools: composer\n\n      - name: Install dependencies\n        run: |\n          npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Build plugin\n        run: bun run build:js\n\n      - name: Bundle regular version\n        run: bun run workflow:build-plugin\n\n      # Check if as many strings as expected were found.\n      # Fail job if `wp i18n make-pot` returns any warnings.\n      # Some false positive warnings are removed due to a bug in the string extraction.\n      # That's why this step is unfortunately a bit more complex.\n      # See https://github.com/wp-cli/i18n-command/issues/154\n      - name: Generate POT file\n        run: |\n          OUTPUT=$((wp i18n make-pot build/web-stories build/web-stories.pot) 2>&1 >/dev/null)\n\n          HAS_ERROR=false\n\n          EXPECTED_NUMBER_OF_STRINGS=1000\n          NUMBER_OF_FOUND_STRINGS=$(grep -o msgstr build/web-stories.pot | wc -l | xargs)\n\n          if (( \"$NUMBER_OF_FOUND_STRINGS\" < \"$EXPECTED_NUMBER_OF_STRINGS\" )); then\n          HAS_ERROR=true\n            echo \"String extraction found only $NUMBER_OF_FOUND_STRINGS translatable strings. Expected at least $EXPECTED_NUMBER_OF_STRINGS.\"\n          fi\n\n          IFS=$'\\n'\n          declare -a WARNINGS=($OUTPUT)\n          unset IFS\n\n          for WARNING in \"${WARNINGS[@]}\"; do\n            # Filter false positives.\n            if [[ $WARNING == *\"translator comment\"* ]] && [[ $WARNING != *\"%s\"* ]]; then\n              continue\n            fi\n\n            HAS_ERROR=true\n\n          \techo $WARNING\n          done\n\n          if [[ \"$HAS_ERROR\" = true ]]; then\n            exit 1\n          fi\n"
  },
  {
    "path": ".github/workflows/lint-php.yml",
    "content": "name: Lint PHP\n\non:\n  push:\n    # Only run if PHP-related files changed.\n    paths:\n      - '**.php'\n      - 'phpcs.xml.dist'\n      - 'phpmd.xml'\n      - 'phpstan.neon.dist'\n      - 'composer.json'\n      - 'composer.lock'\n      - '.github/workflows/lint-php.yml'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if PHP-related files changed.\n    paths:\n      - '**.php'\n      - 'phpcs.xml.dist'\n      - 'phpmd.xml'\n      - 'phpstan.neon.dist'\n      - 'composer.json'\n      - 'composer.lock'\n      - '.github/workflows/lint-php.yml'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  lint:\n    name: Lint\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: block\n          allowed-endpoints: >\n            api.github.com:443\n            github.com:443\n            objects.githubusercontent.com:443\n            packagist.org:443\n            repo.packagist.org:443\n            getcomposer.org:443\n            dl.cloudsmith.io:443\n            54.185.253.63:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          coverage: none\n          tools: composer, cs2pr\n\n      - name: Validate composer.json\n        run: composer --no-interaction validate --no-check-all\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Detect coding standard violations (PHPCS)\n        run: vendor/bin/phpcs -q --report=checkstyle --severity=1 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 | cs2pr --graceful-warnings\n\n      - name: Static Analysis (PHPStan)\n        run: composer phpstan\n\n      - name: Static Analysis (PHPMD)\n        run: composer phpmd\n\n      - name: Normalize composer.json\n        run: composer normalize --no-interaction --dry-run\n"
  },
  {
    "path": ".github/workflows/lint-plugin-check.yml",
    "content": "name: Plugin Check\n\non:\n  push:\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'web-stories.php'\n      - 'includes/**.php'\n      - '.github/workflows/lint-plugin-check.yml'\n    branches:\n      - main\n  pull_request:\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'web-stories.php'\n      - 'includes/**.php'\n      - '.github/workflows/lint-plugin-check.yml'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  lint:\n    name: Lint\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: '8.0'\n          coverage: none\n          tools: composer\n\n      - name: Install dependencies\n        run: |\n          npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Build plugin\n        run: bun run build:js\n\n      - name: Bundle plugin\n        run: bun run workflow:build-plugin\n\n      - name: Run plugin check\n        uses: wordpress/plugin-check-action@v1\n        with:\n          build-dir: './build/web-stories'\n          exclude-directories: 'third-party'\n          exclude-checks: |\n            late_escaping\n            plugin_readme\n            plugin_review_phpcs\n            plugin_updater\n"
  },
  {
    "path": ".github/workflows/npm-release.yml",
    "content": "# npm packages release automation\n\nname: npm Release\n\non:\n  workflow_dispatch:\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\nenv:\n  PRODUCTION_REGISTRY_URL: https://wombat-dressing-room.appspot.com\n  LOCAL_REGISTRY_URL: http://localhost:4873\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n\njobs:\n  dry-run:\n    name: Dry-run release\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    # This step requires additional review\n    # See https://docs.github.com/en/actions/reference/environments\n    environment: Production\n    steps:\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Bundle packages\n        run: bun run workflow:bundle-packages\n        env:\n          NODE_OPTIONS: '--max_old_space_size=4096'\n\n      # Exact format here doesn't matter for the dry-run, it's gonna be done properly later on.\n      - name: Version bumps\n        id: version_bumps\n        run: npm version --no-git-tag-version --workspaces \"0.1.$(date -u +%Y%m%d%H%M)\"\n\n      # Set up a local npm registry with Verdaccio.\n      - name: Set up local registry\n        run: bun run local-registry:start\n\n      # Using Verdaccio\n      - name: Publish packages locally\n        run: npm --registry=$LOCAL_REGISTRY_URL --workspaces publish\n\n      # Undo the version bumps in Git. We only needed them for testing.\n      - name: Clean up local changes\n        run: git checkout .\n\n      # Verifies that packages can be installed without issues.\n      - name: Install published packages\n        run: |\n          PUBLIC_PACKAGES=$(jq -r 'select(.private == false) | .name' $(find packages  -maxdepth 2 -name \"package.json\"))\n          TMPDIR=${TMPDIR-/tmp}\n          TMPDIR=$(echo $TMPDIR | sed -e \"s/\\/$//\")\n          TEST_DIR=${TEST_DIR-$TMPDIR/packages-test}\n\n          mkdir $TEST_DIR\n          cd $TEST_DIR\n\n          npm init --yes\n          npm --registry=$LOCAL_REGISTRY_URL install $PUBLIC_PACKAGES\n\n          npm ls --depth 0\n\n      - name: Stop local registry\n        run: bun run local-registry:stop\n\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write # for Git to git push\n    timeout-minutes: 20\n    needs: [dry-run]\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      # See go/npm-publish\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n          registry-url: ${{ env.PRODUCTION_REGISTRY_URL }}\n          scope: '@googleforcreators'\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Bundle packages\n        run: bun run workflow:bundle-packages\n        env:\n          NODE_OPTIONS: '--max_old_space_size=4096'\n\n      # For the time being, using incremental versions like 0.1.202111302140\n      # `npm version` updates all packages, even the ones we don't intend to publish.\n      # To address this, we undo the version change for private packages.\n      # We're doing the commit ourselves since we only need it later on and\n      # since committing doesn't work properly when using workspaces.\n      # See https://github.com/npm/cli/issues/4017\n      - name: Version bumps\n        id: version_bumps\n        run: |\n          NEW_VERSION_RAW=\"0.1.$(date -u +%Y%m%d%H%M)\";\n          NEW_VERSION=\"v$NEW_VERSION_RAW\"\n          npm version --no-git-tag-version --workspaces $NEW_VERSION_RAW\n\n          # Undo changes to all the private packages.\n          for package_file in ./packages/*/package.json; do\n            if [[ $(cat $package_file | jq '.private') == true ]]; then\n              git checkout --quiet $package_file\n            fi\n          done\n\n          # Updates the lock file.\n          npm install\n\n          git add packages/*/package.json\n          git add package-lock.json\n\n          echo \"Committing version bump\"\n          echo\n\n          git commit -m \"Bumping npm packages version to $NEW_VERSION\"\n\n          echo \"Adding tags\"\n          echo\n\n          # For every public package, this creates a tag in the form \"<package>-v1234\".\n          # Example: templates-v1234\n          for package_file in ./packages/*/package.json; do\n            if [[ $(cat $package_file | jq '.private') == false ]]; then\n              package_name=$(basename $(dirname $package_file))\n              echo \"Adding tag: $package_name-$NEW_VERSION\"\n              git tag \"$package_name-$NEW_VERSION\"\n            fi\n          done\n\n          echo \"Commit details:\"\n          echo\n\n          git status\n          git log -n 1\n\n          echo \"Added tags:\"\n          echo\n\n          git tag --points-at HEAD\n\n          echo \"Changed files:\"\n          echo\n\n          git show --pretty=%gd --stat\n\n          git push origin main --tags\n\n      # Do the actual publishing to npmjs.com via Wombat Dressing Room.\n      - name: Publish packages to production\n        run: npm --registry=$PRODUCTION_REGISTRY_URL --workspaces  publish --workspaces\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/plugin-release.yml",
    "content": "# Plugin release automation\n#\n# Builds the plugin for release candidates and stable releases.\n#\n# Creates the release branch, the actual release on GitHub, and the correct tag.\n#\n# For new major releases, the action should be run from the `main` branch.\n# For patch releases, the action should be run from the corresponding release branch (e.g. `release/1.2.0`)\n\nname: Plugin Release\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'Plugin version (e.g. 1.2.3 or 7.2.0-rc.1)'\n        required: true\n\npermissions:\n  contents: read\n\nenv:\n  PLUGIN_VERSION: ${{ github.event.inputs.version }}\n  TAG_NAME: 'v${{ github.event.inputs.version }}'\n  IS_RC: ${{ contains(github.event.inputs.version, 'rc') }}\n  IS_PATCH_RELEASE: ${{ startsWith(github.ref, 'refs/heads/release/') }}\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n  GITHUB_REPO_ID: 235435637\n\njobs:\n  # Perform some sanity checks at the beginning to avoid surprises.\n  checks:\n    name: Checks\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    # This step requires additional review\n    # See https://docs.github.com/en/actions/reference/environments\n    environment: Production\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Verify semver compatibility\n        run: |\n          if [[ $PLUGIN_VERSION =~ $SEMVER_VERSION_REGEX ]]; then\n            echo \"Given plugin version string is a valid semver version\"\n          else\n            echo \"Given plugin version string is not a valid semver version\"\n            exit 1\n          fi\n        env:\n          SEMVER_VERSION_REGEX: ^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-([0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*))?(\\+[0-9A-Za-z-]+)?$\n\n      - name: Verify release does not exist yet\n        run: |\n          if git describe --abbrev=0 --tags --match \"$TAG_NAME\" &>/dev/null; then\n            echo \"The planned plugin version already exists!\"\n            exit 1\n          fi\n\n      #      - name: Ensure RC exists for stable release\n      #        if: ${{ ! contains(github.event.inputs.version, 'rc') }}\n      #        run: |\n      #          VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}\n      #          BRANCH=release/$VERSION_WITHOUT_SUFFIX\n      #\n      #          if [[ -z $(git ls-remote origin $BRANCH) ]]; then\n      #            echo \"No release branch exists for this planned stable release\"\n      #            exit 1\n      #          fi\n      #\n      #          git checkout --track origin/$BRANCH\n      #\n      #          if ! git describe --abbrev=0 --tags --match \"$TAG_NAME-rc.*\" &>/dev/null; then\n      #            echo \"No RC exists for this planned stable release\"\n      #            exit 1\n      #          fi\n\n      - name: Ensure readme.txt contains changelog\n        run: |\n          VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}\n          CHANGELOG_REGEX=\"= $VERSION_WITHOUT_SUFFIX =\"\n\n          if ! grep -q -P \"$CHANGELOG_REGEX\" readme.txt; then\n            echo \"No changelog found in readme.txt\"\n            exit 1\n          fi\n\n  # Get the current CDN assets version.\n  # If the static assets on the CDN have changed since the last release,\n  # bump the assets version accordingly in the GoogleForCreators/wp.stories.google repo.\n  assets-version:\n    name: Prepare static assets\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    needs: [checks]\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      # TODO: Define behavior for patch releases.\n      #\n      # A patch release is done from a specific release branch instead of `main`\n      #\n      # Patch releases must not necessarily copy assets from `main`.\n      # Given the following assets versions:\n      # main  1  2  3  4 <- next major release\n      #             ^\n      #             |\n      #       current branch\n      #\n      # The patch release should probably get version 3.1 or similar,\n      # since version 4 is already used by the next major release.\n      #\n      # Right now, this is needs to be done manually for patch releases,\n      # otherwise the assets version is left unchanged here.\n\n      # Grab current assets version from `web-stories.php` and pass on to next steps.\n      # - name: Checkout\n      #   uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n      #   with:\n      #     ref:\n\n      # - name: Get current assets version\n      #   id: base_assets_version\n      #   run: |\n      #     BASE_ASSETS_VERSION=main\n      #     if  [[ $(cat web-stories.php) =~ $ASSETS_VERSION_REGEX ]]; then\n      #       BASE_ASSETS_VERSION=${BASH_REMATCH[1]}\n      #     fi\n      #     echo \"BASE_ASSETS_VERSION=$BASE_ASSETS_VERSION\" >> $GITHUB_OUTPUT\n      #     env:\n      #       ASSETS_VERSION_REGEX: \"https://wp.stories.google/static/([^']+)\"\n\n      - name: Checkout wp.stories.google\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          repository: GoogleForCreators/wp.stories.google\n          lfs: true\n          # Needed so the below commits will trigger a website deployment.\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Authenticate\n        uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093\n        with:\n          credentials_json: ${{ secrets.GCP_SA_KEY }}\n\n      - name: Setup Cloud SDK\n        uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db\n        with:\n          project_id: ${{ secrets.GCP_PROJECT_ID }}\n\n      # For release candidates of new major releases:\n      #\n      # 1. Get highest assets version\n      # 2. Compare with `main`\n      # 3. If they differ:\n      # 3.1 Set new_version = version+1\n      # 3.2 Copy `main` to new_version\n      # 3.2 Push new directory\n      # 4. Else, keep currently highest version\n      - name: Prepare assets for RC\n        if: ${{ contains(github.event.inputs.version, 'rc') && ! startsWith(github.ref, 'refs/heads/release/') }}\n        run: |\n          LATEST_ASSETS_VERSION=$(gcloud storage ls gs://web-stories-wp-cdn-assets/ | sed 's/gs:\\/\\/web-stories-wp-cdn-assets\\///' | sed 's/\\///' | sort -n | tail -1)\n          NEW_ASSETS_VERSION=$LATEST_ASSETS_VERSION\n\n          NUMBER_OF_NEW_ASSETS=$(ls main | wc -l)\n\n          if [[ \"0\" -eq NUMBER_OF_NEW_ASSETS ]]; then\n            echo \"No new assets found. Not uploading anything.\"\n          else\n            echo \"New assets found.\"\n            NEW_ASSETS_VERSION=$((LATEST_ASSETS_VERSION+1))\n\n            echo \"Copying existing assets over to new version.\"\n\n            gcloud storage rsync -r gs://web-stories-wp-cdn-assets/$LATEST_ASSETS_VERSION gs://web-stories-wp-cdn-assets/$NEW_ASSETS_VERSION\n\n            echo \"Uploading new assets to new version.\"\n            gcloud storage rsync main gs://web-stories-wp-cdn-assets/$NEW_ASSETS_VERSION --recursive --ignore-symlinks --exclude=\"(^|/)\\.\"\n\n            rm -rf main/*\n\n            echo \"Updating LATEST_ASSETS_VERSION Firebase env variable.\"\n\n            echo \"LATEST_ASSETS_VERSION=$NEW_ASSETS_VERSION\" > ../../packages/functions/.env\n\n            git add ../../packages/functions/.env\n            git add .\n            git status\n            git commit -m \"Preparing assets for plugin release $PLUGIN_VERSION\"\n            git pull --rebase\n            git push origin main\n          fi\n\n          echo \"Assets version for this release: $NEW_ASSETS_VERSION\"\n\n          mkdir -p assets_version\n          echo $NEW_ASSETS_VERSION > assets_version/assets_version.txt\n          echo \"ASSETS_VERSION=${NEW_ASSETS_VERSION}\" >> $GITHUB_ENV\n        working-directory: public/static\n        env:\n          BASE_ASSETS_VERSION: main\n\n      # Uploads an empty file just so we have something to download in the next step\n      # Essentially a no-op.\n      - name: Prepare assets for stable release\n        if: ${{ ! contains(github.event.inputs.version, 'rc') || startsWith(github.ref, 'refs/heads/release/') }}\n        run: |\n          mkdir -p assets_version\n          echo \"\" > assets_version/assets_version.txt\n\n      - name: Upload assets version\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: assets-version\n          path: public/static/assets_version\n\n      - name: Write summary\n        run: |\n          echo \"Preparing assets for release\" >> $GITHUB_STEP_SUMMARY\n          echo \"\" >> $GITHUB_STEP_SUMMARY\n          echo \"Assets version: $ASSETS_VERSION\" >> $GITHUB_STEP_SUMMARY\n        env:\n          ASSETS_VERSION: ${{ env.ASSES_VERSION }}\n\n  build:\n    name: Build new version\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    needs: [assets-version]\n    outputs:\n      release_branch: ${{ steps.release_branch.outputs.release_branch }}\n      release_name: ${{ steps.release_branch.outputs.release_name }}\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          fetch-depth: 0 # 0 indicates all history for all branches and tags.\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Download assets version\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c\n        with:\n          name: assets-version\n        continue-on-error: true\n\n      - name: Retrieve assets version\n        id: assets_version\n        run: |\n          echo \"ASSETS_VERSION=$(cat assets_version.txt)\" >> $GITHUB_ENV\n          rm -rf assets_version.txt\n        continue-on-error: true\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          coverage: none\n          tools: composer\n\n      - name: Install dependencies\n        run: |\n          npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Create release branch\n        id: release_branch\n        run: |\n          VERSION_WITHOUT_SUFFIX=${PLUGIN_VERSION/-rc.*/}\n          BRANCH=release/$VERSION_WITHOUT_SUFFIX\n\n          # Patch releases are already on the correct branch.\n          if $IS_PATCH_RELEASE; then\n            BRANCH=${GITHUB_REF#refs/heads/}\n            echo \"release_branch=${BRANCH}\" >> $GITHUB_OUTPUT\n            exit 0\n          fi\n\n          if [[ -z $(git ls-remote origin $BRANCH) ]]; then\n            git checkout -b $BRANCH\n          else\n            git checkout --track origin/$BRANCH\n          fi\n\n          echo \"release_branch=${BRANCH/-rc./ RC}\" >> $GITHUB_OUTPUT\n\n          RELEASE_NAME=${PLUGIN_VERSION/-rc./ RC}\n          echo \"release_name=${RELEASE_NAME}\" >> $GITHUB_OUTPUT\n\n      - name: Update assets version\n        run: bun run workflow:assets-version $ASSETS_VERSION\n        if: ${{ env.ASSETS_VERSION }}\n        env:\n          ASSETS_VERSION: ${{ env.ASSETS_VERSION }}\n\n      - name: Commit assets version bump\n        run: |\n          git add web-stories.php\n          git status\n          git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 0\n          git commit -m \"Update assets version to $ASSETS_VERSION\"\n          git push -u origin HEAD\n        if: ${{ env.ASSETS_VERSION }}\n        env:\n          ASSETS_VERSION: ${{ env.ASSETS_VERSION }}\n\n      - name: Update plugin version\n        run: bun run workflow:version $PLUGIN_VERSION\n\n      # Commit the plugin version bump if it was successful.\n      # It's also possible that there were no changes, for example if the\n      # workflow was run a second time and the commit has already happened,\n      # but the process later failed.\n      # This allows re-running the workflow again without aborting in this case.\n      - name: Commit plugin version bump\n        id: plugin_version_bump\n        run: |\n          git add web-stories.php\n          git status\n\n          if git diff --cached --exit-code > /dev/null; then\n            git commit -m \"Prepare release $PLUGIN_VERSION\"\n            git push -u origin HEAD\n            echo \"changes=yes\" >> $GITHUB_ENV\n          else\n            echo 'No changes to commit; exiting!'\n            echo \"changes=no\" >> $GITHUB_ENV\n          fi\n\n      # Only non-patch release version bumps should be cherry picked to main\n      # This will cherry-pick the last commit from the release branch, as\n      # we only want the plugin version bump, not the assets version bump.\n      #\n      # Cherry-picking is only done if there actually was\n      # a version bump in the previous step.\n      - name: Cherry-pick to main\n        run: |\n          git checkout main\n          git cherry-pick $BRANCH\n          git pull --rebase\n          git push\n          git checkout $BRANCH\n        if: ${{ ! startsWith(github.ref, 'refs/heads/release/') && env.changes == 'yes' }}\n        env:\n          BRANCH: ${{ steps.release_branch.outputs.release_branch }}\n\n      - name: Build plugin\n        run: bun run build:js\n\n      - name: Bundle regular version\n        run: bun run workflow:build-plugin -- --zip web-stories.zip\n\n      - name: Bundle development version\n        run: |\n          rm -rf assets/css/* assets/js/*\n          npx webpack --env=development\n          bun run workflow:build-plugin -- --zip web-stories-dev.zip\n\n      - name: Prepare release artifacts\n        run: |\n          mkdir -p build/release-assets\n          mv build/*.zip build/release-assets/\n\n      - name: Upload artifacts\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: release-assets\n          path: build/release-assets\n\n  create-release:\n    name: Create Release\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    needs: [build]\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Download release artifacts\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c\n        with:\n          name: release-assets\n          path: build\n\n      - name: Publish Release\n        id: create_release\n        uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe\n        with:\n          tag_name: ${{ env.TAG_NAME }}\n          name: ${{ env.release_name }}\n          target_commitish: ${{ steps.release_branch.outputs.release_branch || github.ref }}\n          prerelease: ${{ env.IS_RC }}\n          generate_release_notes: true\n          files: |\n            build/web-stories.zip\n            build/web-stories-dev.zip\n          fail_on_unmatched_files: true\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n  # Post-release version bumps for non-patch releases.\n  post-release:\n    name: Post-release version bump\n    needs: [create-release]\n    runs-on: ubuntu-latest\n    if: ${{ ! startsWith(github.ref, 'refs/heads/release/') && ! contains(github.event.inputs.version, 'rc') }}\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          ref: main\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      # If we're releasing 1.6.0, bump version on main to 1.7.0-alpha.0.\n      - name: Update plugin version\n        run: npm run workflow:version -- --increment preminor --preid alpha\n\n      - name: Commit changes\n        run: |\n          git add web-stories.php\n          git status\n          git diff --staged --quiet && echo 'No changes to commit; exiting!' && exit 1\n          git commit -m \"Post-release version bump\"\n          git pull --rebase\n          git push -u origin HEAD\n\n  # Stable releases are automatically deployed to WordPress.org.\n  # TODO: Consider also deploying other types of releases (RC, beta), but without bumping the stable tag.\n  # This way we could offer users a way to beta test the plugin.\n  # See http://plugins.svn.wordpress.org/buddypress/tags/ and https://wordpress.org/plugins/bp-beta-tester/ for inspiration.\n  deploy:\n    name: Deploy plugin to WordPress.org\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    needs: [create-release]\n    if: ${{ ! contains(github.event.inputs.version, 'rc') }}\n    env:\n      PLUGIN_REPO_URL: 'https://plugins.svn.wordpress.org/web-stories'\n      STABLE_TAG_REGEX: 'Stable tag:\\s*(.+)'\n      SVN_USERNAME: ${{ secrets.SVN_USERNAME }}\n      SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Download release artifacts\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c\n        with:\n          name: release-assets\n          path: release-assets\n\n      - name: Install svn\n        run: |\n          sudo apt update -y --allow-releaseinfo-change\n          sudo apt install -y subversion\n\n      - name: Check out trunk folder\n        run: svn checkout $PLUGIN_REPO_URL svn --username \"$SVN_USERNAME\"\n\n      - name: Get previous stable tag\n        id: get_previous_stable_tag\n        # Returns the whole matching line.\n        run: echo stable_tag=$(grep -P \"$STABLE_TAG_REGEX\" ./svn/trunk/readme.txt) >> $GITHUB_ENV\n\n      - name: Delete everything in trunk\n        run: find . -maxdepth 1 -not -name \".svn\" -not -name \".\" -not -name \"..\" -exec rm -rf {} +\n        working-directory: ./svn/trunk\n\n      - name: Unzip release asset into trunk\n        run: |\n          unzip release-assets/web-stories.zip\n          mv web-stories/* svn/trunk\n        env:\n          PLUGIN_URL: ${{ github.event.release.assets[0].browser_download_url }}\n\n      - name: Replace stable tag placeholder with pre-existing stable tag\n        run: |\n          sed -r -i \"s/${STABLE_TAG_REGEX}/${STABLE_TAG}/g\" ./readme.txt\n        working-directory: ./svn/trunk\n        env:\n          STABLE_TAG: ${{ env.stable_tag }}\n\n      # Note: Creating the tag trigger an email confirmation that needs to be confirmed by someone with commit access.\n      - name: Commit changes to trunk\n        run: |\n          svn st | grep '^?' | awk '{print $2}' | xargs -r svn add\n          svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm\n          svn commit -m \"Committing version $PLUGIN_VERSION\" \\\n           --no-auth-cache --non-interactive  --username \"$SVN_USERNAME\" --password \"$SVN_PASSWORD\"\n        working-directory: ./svn\n\n      # Copy trunk to the new tag directly on the server.\n      # Not done in the same commit as the changes to trunk in order to reduce number of file operations\n      # and to prevent potential timeouts.\n      # See https://developer.wordpress.org/plugins/wordpress-org/how-to-use-subversion/#create-tags-from-trunk\n      - name: Create the SVN tag\n        run: |\n          svn cp \"$PLUGIN_REPO_URL/trunk\" \"$PLUGIN_REPO_URL/tags/$PLUGIN_VERSION\" \\\n           -m \"Tagging version $PLUGIN_VERSION\" \\\n           --no-auth-cache --non-interactive  --username \"$SVN_USERNAME\" --password \"$SVN_PASSWORD\"\n        working-directory: ./svn\n\n      # It's recommended to run this only after the tag was successfully created.\n      # Otherwise, if there were any errors, we risk changing this to a tag that doesn't exist.\n      # The actual release still needs to be confirmed via email.\n      - name: Update stable tag\n        working-directory: ./svn\n        run: |\n          sed -r -i \"s/${STABLE_TAG_REGEX}/Stable tag:        ${PLUGIN_VERSION}/g\" ./trunk/readme.txt\n          svn commit -m \"Releasing version $PLUGIN_VERSION\" \\\n           --no-auth-cache --non-interactive  --username \"$SVN_USERNAME\" --password \"$SVN_PASSWORD\"\n"
  },
  {
    "path": ".github/workflows/scorecards.yml",
    "content": "name: Scorecards supply-chain security\n\non:\n  # Only the default branch is supported.\n  branch_protection_rule:\n  schedule:\n    - cron: '0 12 1 * *'\n  push:\n    branches: [main]\n\npermissions:\n  contents: read\n\njobs:\n  analysis:\n    name: Scorecards analysis\n    runs-on: ubuntu-latest\n    permissions:\n      # Needed to upload the results to code-scanning dashboard.\n      security-events: write\n      actions: read\n      contents: read\n      # Needed to access OIDC token.\n      id-token: write\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: 'Checkout code'\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          persist-credentials: false\n\n      - name: 'Run analysis'\n        uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a\n        with:\n          results_file: results.sarif\n          results_format: sarif\n          repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}\n          # Publish the results to enable scorecard badges. For more details, see\n          # https://github.com/ossf/scorecard-action#publishing-results.\n          # For private repositories, `publish_results` will automatically be set to `false`,\n          # regardless of the value entered here.\n          publish_results: true\n\n      # Upload the results as artifacts (optional).\n      - name: 'Upload artifact'\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: SARIF file\n          path: results.sarif\n          retention-days: 5\n\n      # Upload the results to GitHub's code scanning dashboard.\n      - name: 'Upload to code-scanning'\n        uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13\n        with:\n          sarif_file: results.sarif\n"
  },
  {
    "path": ".github/workflows/tests-e2e.yml",
    "content": "name: E2E Tests\n\non:\n  push:\n    # Don't run for irrelevant changes.\n    paths-ignore:\n      - 'docs/**'\n      - '.storybook/**'\n      - '.wordpress-org/**'\n      - '__mocks__/**'\n      - '__static__/**'\n      - 'tests/**'\n      - '**.md'\n      - '**.yml'\n      - '**.neon.dist'\n      - '**.xml.dist'\n      - 'readme.txt'\n      - '.editorconfig'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.phpstorm.meta.php'\n      - '.prettier*'\n      - '.stylelint*'\n      - '.github/workflows/**'\n      - '!.github/workflows/tests-e2e.yml'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Don't run for irrelevant changes.\n    paths-ignore:\n      - 'docs/**'\n      - '.storybook/**'\n      - '.wordpress-org/**'\n      - '__mocks__/**'\n      - '__static__/**'\n      - 'tests/**'\n      - '**.md'\n      - '**.yml'\n      - '**.neon.dist'\n      - '**.xml.dist'\n      - 'readme.txt'\n      - '.editorconfig'\n      - '.eslint*'\n      - '.markdownlint*'\n      - '.phpstorm.meta.php'\n      - '.prettier*'\n      - '.stylelint*'\n      - '.github/workflows/**'\n      - '!.github/workflows/tests-e2e.yml'\n    types:\n      - opened\n      - reopened\n      - synchronize\n      - ready_for_review\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  build:\n    name: Build plugin\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          coverage: none\n          tools: composer\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Build plugin\n        run: bun run build:js\n        env:\n          # TODO: remove eventually\n          DISABLE_PREVENT: true\n          DISABLE_QUICK_TIPS: true\n\n      - name: Bundle plugin\n        run: bun run workflow:build-plugin\n\n      - name: Upload bundle\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: web-stories\n          path: build/web-stories\n\n  e2e:\n    name: '${{ matrix.browser }} - WP ${{ matrix.wp }} (${{ matrix.shard }})'\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    continue-on-error: ${{ matrix.experimental == true }}\n    needs: [build]\n    strategy:\n      fail-fast: false\n      matrix:\n        # TODO: add back Firefox once support is more mature.\n        browser: ['chrome']\n        wp: ['6.6']\n        snapshots: [false]\n        experimental: [false]\n        # We want to split up the tests into 2 parts running in parallel.\n        shard: ['1/2', '2/2']\n        include:\n          - browser: 'chrome'\n            wp: 'latest'\n            snapshots: true\n            shard: '1/2'\n          - browser: 'chrome'\n            wp: 'latest'\n            snapshots: true\n            shard: '2/2'\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: audit\n          allowed-endpoints: >\n            github.com:443\n            objects.githubusercontent.com:443\n            packagist.org:443\n            registry.npmjs.org:443\n            storage.googleapis.com:443\n            docker.io:443\n            registry-1.docker.io:443\n            auth.docker.io:443\n            34.104.35.123:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Download bundle\n        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c\n        with:\n          name: web-stories\n\n      # See https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix\n      - name: Install libgbm1\n        run: sudo apt-get install libgbm1\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_PRODUCT: ${{ matrix.browser }}\n\n      - name: Start Docker environment\n        run: npm run env:start\n        env:\n          COMPOSE_INTERACTIVE_NO_CLI: true\n          WP_VERSION: ${{ matrix.wp }}\n\n      # See https://issues.chromium.org/issues/373753919\n      # and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md\n      - name: Disable AppArmor\n        run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns\n\n      - name: Get Chromium executable path\n        id: chromium_path\n        run: |\n          CHROMIUM=$(node -p \"const puppeteer = require('puppeteer'); puppeteer.executablePath();\")\n          echo \"chromium_path=${CHROMIUM}\" >> $GITHUB_ENV\n        if: ( matrix.snapshots ) && ( github.event.pull_request.draft == false )\n\n      - name: Download AMP validator JS\n        id: amp_validator\n        run: |\n          cd $RUNNER_TEMP && curl -O -f -s -S https://cdn.ampproject.org/v0/validator_wasm.js\n          AMP_VALIDATOR_FILE=\"${RUNNER_TEMP}/validator_wasm.js\"\n          echo \"validator_file=$AMP_VALIDATOR_FILE\" >> $GITHUB_ENV\n\n      - name: Run E2E tests\n        run: npm run test:e2e -- --shard=$SHARD\n        env:\n          WP_VERSION: ${{ matrix.wp }}\n          SHARD: ${{ matrix.shard }}\n          AMP_VALIDATOR_FILE: ${{ env.validator_file }}\n\n      - name: Stop Docker environment\n        run: npm run env:stop\n        if: always()\n        env:\n          COMPOSE_INTERACTIVE_NO_CLI: true\n\n      - name: Get artifact name\n        if: always()\n        run: |\n          ARTIFACT_NAME=${ARTIFACT_NAME//\\//-}\n          echo \"ARTIFACT_NAME=${ARTIFACT_NAME}\" >> $GITHUB_ENV\n        env:\n          ARTIFACT_NAME: failures-artifacts-${{ matrix.wp }}-${{ matrix.shard }}\n\n      - name: Upload artifacts\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        if: always()\n        with:\n          name: ${{ env.ARTIFACT_NAME }}\n          path: build/e2e-artifacts\n          if-no-files-found: ignore\n"
  },
  {
    "path": ".github/workflows/tests-karma-dashboard.yml",
    "content": "name: Dashboard Integration Tests\n\non:\n  push:\n    # Only run if dashboard-related files changed.\n    paths:\n      - 'babel.config.cjs'\n      - 'karma-dashboard.config.cjs'\n      - 'webpack.config.cjs'\n      - 'webpack.config.test.cjs'\n      - 'packages/**/*.js'\n      - 'packages/**/*.ts'\n      - 'packages/**/*.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - '__static__/**'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if dashboard-related files changed.\n    paths:\n      - 'babel.config.cjs'\n      - 'karma-dashboard.config.cjs'\n      - 'webpack.config.cjs'\n      - 'webpack.config.test.cjs'\n      - 'packages/**/*.js'\n      - 'packages/**/*.ts'\n      - 'packages/**/*.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - '__static__/**'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  karma:\n    name: Karma\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: block\n          allowed-endpoints: >\n            api.github.com:443\n            codecov.io:443\n            fonts.googleapis.com:443\n            fonts.gstatic.com:443\n            github.com:443\n            registry.npmjs.org:443\n            storage.googleapis.com:443\n            uploader.codecov.io:443\n            www.gravatar.com:443\n            54.185.253.63:443\n            34.104.35.123:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      # TODO: Remove need for `npm install puppeteer`.\n      - name: Install dependencies\n        run: |\n          npm ci\n          npm install puppeteer\n        env:\n          PUPPETEER_PRODUCT: chrome\n\n      # See https://issues.chromium.org/issues/373753919\n      # and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md\n      - name: Disable AppArmor\n        run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns\n\n      # FIXME: https://github.com/googleforcreators/web-stories-wp/issues/4364\n      - name: Increase max number of file watchers\n        run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n\n      - name: Get Chromium executable path\n        id: chromium_path\n        run: |\n          CHROMIUM=$(node -p \"const puppeteer = require('puppeteer'); puppeteer.executablePath();\")\n          echo \"chromium_path=${CHROMIUM}\" >> $GITHUB_ENV\n\n      - name: Run integration tests\n        run: npm run test:karma:dashboard -- --headless --viewport=1600:1000 --coverage || npm run test:karma:dashboard:retry-failed -- --headless --viewport=1600:1000\n        env:\n          DISABLE_ERROR_BOUNDARIES: true\n\n      - name: Upload code coverage report\n        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2\n        with:\n          files: build/logs/karma-coverage/dashboard/lcov.info\n          flags: karmatests\n          token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/tests-karma-editor.yml",
    "content": "name: Editor Integration Tests\n\non:\n  push:\n    # Only run if editor-related files changed.\n    paths:\n      - 'babel.config.cjs'\n      - 'karma-story-editor.config.cjs'\n      - 'webpack.config.cjs'\n      - 'webpack.config.test.cjs'\n      - 'packages/**/*.js'\n      - 'packages/**/*.cjs'\n      - 'packages/**/*.ts'\n      - 'packages/**/*.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - '__static__/**'\n      - '.github/workflows/tests-karma-editor.yml'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if editor-related files changed.\n    paths:\n      - 'babel.config.cjs'\n      - 'karma-story-editor.config.cjs'\n      - 'webpack.config.cjs'\n      - 'webpack.config.test.cjs'\n      - 'packages/**/*.js'\n      - 'packages/**/*.cjs'\n      - 'packages/**/*.ts'\n      - 'packages/**/*.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - '__static__/**'\n      - '.github/workflows/tests-karma-editor.yml'\n    types:\n      - opened\n      - reopened\n      - synchronize\n      - ready_for_review\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  karma:\n    name: Karma (${{ matrix.shard }})\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        # We want to split up the tests into 20 parts running in parallel.\n        shard:\n          [\n            '1/20',\n            '2/20',\n            '3/20',\n            '4/20',\n            '5/20',\n            '6/20',\n            '7/20',\n            '8/20',\n            '9/20',\n            '10/20',\n            '11/20',\n            '12/20',\n            '13/20',\n            '14/20',\n            '15/20',\n            '16/20',\n            '17/20',\n            '18/20',\n            '19/20',\n            '20/20',\n          ]\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: block\n          allowed-endpoints: >\n            api.github.com:443\n            codecov.io:443\n            fonts.googleapis.com:443\n            fonts.gstatic.com:443\n            github.com:443\n            registry.npmjs.org:443\n            storage.googleapis.com:443\n            uploader.codecov.io:443\n            wp.stories.google:443\n            media3p.googleapis.com:443\n            stories.local:80\n            54.185.253.63:443\n            34.104.35.123:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      # TODO: Remove need for `npm install puppeteer`.\n      - name: Install dependencies\n        run: |\n          npm ci\n          npm install puppeteer\n        env:\n          PUPPETEER_PRODUCT: chrome\n\n      # See https://issues.chromium.org/issues/373753919\n      # and https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md\n      - name: Disable AppArmor\n        run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns\n\n      # FIXME: https://github.com/googleforcreators/web-stories-wp/issues/4364\n      - name: Increase max number of file watchers\n        run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n\n      - name: Get Chromium executable path\n        id: chromium_path\n        run: |\n          CHROMIUM=$(node -p \"const puppeteer = require('puppeteer'); puppeteer.executablePath();\")\n          echo \"chromium_path=${CHROMIUM}\" >> $GITHUB_ENV\n\n      - name: Run integration tests\n        run: |\n          npm run test:karma:story-editor -- --headless --viewport=1600:1000 --coverage --shard=$SHARD || \\\n          npm run test:karma:story-editor:retry-failed -- --headless --viewport=1600:1000 --shard=$SHARD\n        env:\n          DISABLE_ERROR_BOUNDARIES: true\n          SHARD: ${{ matrix.shard }}\n\n      - name: Upload code coverage report\n        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2\n        with:\n          files: build/logs/karma-coverage/story-editor/lcov.info\n          flags: karmatests\n          token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/tests-unit-js.yml",
    "content": "name: JavaScript Unit Tests\n\non:\n  push:\n    # Only run if JS-related files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'packages/templates/src/raw/**'\n      - 'packages/text-sets/src/raw/**'\n      - 'patches/**'\n      - 'packages/fonts/src/fonts.json'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if JS-related files changed.\n    paths:\n      - '**.js'\n      - '**.cjs'\n      - '**.ts'\n      - '**.tsx'\n      - '**/package.json'\n      - 'package-lock.json'\n      - 'packages/templates/src/raw/**'\n      - 'packages/text-sets/src/raw/**'\n      - 'patches/**'\n      - 'packages/fonts/src/fonts.json'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  unit-js:\n    name: Unit Tests (${{ matrix.shard }})\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    strategy:\n      matrix:\n        # We want to split up the tests into 2 parts running in parallel.\n        shard: ['1/2', '2/2']\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-sudo: true\n          disable-file-monitoring: true\n          egress-policy: audit\n          allowed-endpoints: >\n            cdn.ampproject.org:443\n            codecov.io:443\n            github.com:443\n            raw.githubusercontent.com:443\n            registry.npmjs.org:443\n            storage.googleapis.com:443\n            uploader.codecov.io:443\n            fonts.gstatic.com:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Setup Jest cache\n        uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7\n        with:\n          path: .jest-cache\n          key: ${{ runner.os }}-${{ env.NVMRC }}-jest\n\n      # Rollup is needed for tests in `packages/migration/src` expecting `module.js`\n      - name: Install dependencies\n        run: |\n          npm ci\n          npx rollup --config packages/migration/rollup.config.js\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Download AMP validator JS\n        id: amp_validator\n        run: |\n          cd $RUNNER_TEMP && curl -O -f -s -S https://cdn.ampproject.org/v0/validator_wasm.js\n          AMP_VALIDATOR_FILE=\"${RUNNER_TEMP}/validator_wasm.js\"\n          echo \"validator_file=$AMP_VALIDATOR_FILE\" >> $GITHUB_ENV\n\n      - name: Run JavaScript unit tests\n        run: npm run test:js -- --runInBand --ci --cacheDirectory=\"$HOME/.jest-cache\" --collectCoverage --shard=$SHARD\n        env:\n          SHARD: ${{ matrix.shard }}\n          AMP_VALIDATOR_FILE: ${{ env.validator_file }}\n\n      - name: Upload code coverage report\n        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2\n        with:\n          files: build/logs/lcov.info\n          flags: unittests\n          token: ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/tests-unit-php.yml",
    "content": "name: PHP Unit Tests\n\non:\n  push:\n    # Only run if PHP-related files changed.\n    paths:\n      - '**.php'\n      - 'phpunit.xml.dist'\n      - 'phpunit-multisite.xml.dist'\n      - 'composer.json'\n      - 'composer.lock'\n      - 'tests/phpunit/**'\n      - 'includes/data/**'\n      - '.github/workflows/tests-unit-php.yml'\n    branches:\n      - main\n      - release/*\n  pull_request:\n    # Only run if PHP-related files changed.\n    paths:\n      - '**.php'\n      - 'phpunit.xml.dist'\n      - 'phpunit-multisite.xml.dist'\n      - 'composer.json'\n      - 'composer.lock'\n      - 'tests/phpunit/**'\n      - 'includes/data/**'\n      - '.github/workflows/tests-unit-php.yml'\n\npermissions:\n  contents: read\n\n# Cancels all previous workflow runs for pull requests that have not completed.\nconcurrency:\n  # The concurrency group contains the workflow name and the (target) branch name.\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  unit-php:\n    name: PHP ${{ matrix.php }} - WP ${{ matrix.wp }}${{ matrix.experimental && ' (experimental)' || '' }}${{ matrix.coverage && ' (with coverage)' || '' }}${{ matrix.random && ' (in random order)' || '' }}\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    services:\n      mysql:\n        image: mariadb:lts\n        env:\n          MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true\n          MARIADB_DATABASE: wordpress_test\n          MARIADB_MYSQL_LOCALHOST_USER: 1\n          MARIADB_MYSQL_LOCALHOST_GRANTS: USAGE\n        ports:\n          - 3306\n        options: --health-cmd=\"healthcheck.sh --su-mysql --connect --innodb_initialized\" --health-interval=10s --health-timeout=5s --health-retries=3\n    continue-on-error: ${{ matrix.experimental }}\n    strategy:\n      matrix:\n        php: ['8.4', '8.3', '8.2', '8.1', '8.0']\n        wp: ['latest']\n        coverage: [false]\n        experimental: [false]\n        include:\n          - php: '8.5'\n            wp: 'latest'\n            coverage: true\n            experimental: false\n\n          - php: '8.5'\n            wp: 'latest'\n            random: true\n            experimental: true\n\n          - php: '7.4'\n            wp: '6.6'\n            experimental: false\n\n          - php: '8.5'\n            wp: 'trunk'\n            experimental: true\n\n          - php: 'nightly'\n            wp: 'trunk'\n            experimental: true\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          disable-file-monitoring: true\n          egress-policy: audit\n          allowed-endpoints: >\n            api.github.com:443\n            api.wordpress.org:80\n            cdn.ampproject.org:443\n            develop.svn.wordpress.org:443\n            example.com:443\n            github.com:443\n            objects.githubusercontent.com:443\n            packagist.org:443\n            raw.github.com:443\n            repo.packagist.org:443\n            wordpress.org:443\n            getcomposer.org:443\n            dl.cloudsmith.io:443\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n\n      # PHP-Scoper only works on PHP 7.4+ and we need to prefix our dependencies to accurately test them.\n      # So we temporarily switch PHP versions, do a full install and then remove the package.\n      # Then switch back to the PHP version we want to test and delete the vendor directory.\n\n      - name: Setup PHP 8.0\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: latest\n          tools: composer\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction'\n\n      - name: Remove prefixed dependencies\n        run: rm -rf vendor/*\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: mysql\n          coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}\n          tools: composer, cs2pr\n\n      - name: Install PHP dependencies\n        uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda\n        with:\n          composer-options: '--prefer-dist --no-progress --no-interaction --no-scripts'\n\n      - name: Composer dump autoload\n        run: composer dump-autoload --no-interaction\n\n      - name: Shutdown default MySQL service\n        run: sudo service mysql stop\n\n      - name: Verify MariaDB connection\n        run: |\n          while ! mysqladmin ping -h\"127.0.0.1\" -P\"${JOB_SERVICES_MYSQL_3307TH_PORTS}\" --silent; do\n            sleep 1\n          done\n        env:\n          JOB_SERVICES_MYSQL_3307TH_PORTS: ${{ job.services.mysql.ports[3306] }}\n\n      - name: Install svn\n        run: |\n          sudo apt update -y --allow-releaseinfo-change\n          sudo apt install -y subversion\n\n      - name: Set up tests\n        run: bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1:${JOB_SERVICES_MYSQL_PORTS_3306} ${{ matrix.wp }} true\n        env:\n          JOB_SERVICES_MYSQL_PORTS_3306: ${{ job.services.mysql.ports['3306'] }}\n\n      - name: Set up problem matchers for PHPUnit\n        run: echo \"::add-matcher::${{ runner.tool_cache }}/phpunit.json\"\n\n      - name: Run tests\n        run: |\n          npm run test:php:unit\n          npm run test:php:integration:single\n          npm run test:php:integration:multisite\n        if: ${{ ! matrix.coverage && ! matrix.random }}\n\n      - name: Run tests with coverage\n        run: |\n          npm run test:php:unit -- --coverage-clover build/logs/php-coverage.xml\n          npm run test:php:integration:single -- --coverage-clover build/logs/php-coverage-integration.xml\n          npm run test:php:integration:multisite -- --coverage-clover build/logs/php-coverage-multisite.xml\n        if: ${{ matrix.coverage && ! matrix.random }}\n\n      - name: Run tests in random order\n        run: |\n          npm run test:php:unit -- --order-by random\n          npm run test:php:integration:single -- --order-by random\n          npm run test:php:integration:multisite -- --order-by random\n        if: ${{ matrix.random }}\n\n      - name: Upload code coverage report\n        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2\n        with:\n          files: build/logs/*.xml\n          token: ${{ secrets.CODECOV_TOKEN }}\n        if: ${{ matrix.coverage }}\n"
  },
  {
    "path": ".github/workflows/update-browserslist.yml",
    "content": "name: Update browserslist db\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 12 1 * *'\n\npermissions:\n  contents: read\n\nenv:\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n\njobs:\n  update-browserslist-db:\n    name: Update browserslist db\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Update db\n        run: npx update-browserslist-db@latest\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n          commit-message: Update browserslist db\n          title: Update browserslist db\n          body: Updates `caniuse-lite` to use the latest browser’s versions and statistics.\n          branch: update/browserslist-db\n          labels: Dependencies\n"
  },
  {
    "path": ".github/workflows/update-google-fonts.yml",
    "content": "name: Update Google Fonts\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 12 1 * *'\n\npermissions:\n  contents: read\n\nenv:\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n\njobs:\n  update-fonts:\n    name: Update Google Fonts\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6\n        with:\n          bun-version: latest\n\n      - name: Update list of Google Fonts\n        env:\n          GOOGLE_FONTS_API_KEY: ${{ secrets.GOOGLE_FONTS_API_KEY }}\n        run: npm run workflow:fonts\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n          commit-message: Update list of Google Fonts\n          title: Update list of Google Fonts\n          body: Fetched the currently available fonts on Google Fonts to update them in the project.\n          branch: update/google-fonts\n          labels: Dependencies\n"
  },
  {
    "path": ".github/workflows/update-product-schema.yml",
    "content": "name: Update Product Schema\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 12 1 * *'\n\npermissions:\n  contents: read\n\nenv:\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n\njobs:\n  update-fonts:\n    name: Update Product Schema\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Update Product Schema\n        run: |\n          curl -O -f https://raw.githubusercontent.com/ampproject/amphtml/main/examples/amp-story/shopping/product.schema.json\n          cp product.schema.json packages/e2e-tests/src/specs/editor/shopping/schema.json\n          mv product.schema.json tests/phpunit/integration/data/schema.json\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n          commit-message: Update Product Schema\n          title: Update Product Schema\n          body: |\n            Fetched the current [product JSON schema](https://github.com/ampproject/amphtml/blob/main/examples/amp-story/shopping/product.schema.json) for `<amp-story-shopping>` to update it in the project.\n          branch: update/product-schema\n          labels: Dependencies\n"
  },
  {
    "path": ".github/workflows/update-templates.yml",
    "content": "name: Migrate Templates\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 12 * * 1'\n\nenv:\n  GIT_AUTHOR_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_AUTHOR_NAME: googleforcreators-bot\n  GIT_COMMITTER_EMAIL: 94923726+googleforcreators-bot@users.noreply.github.com\n  GIT_COMMITTER_NAME: googleforcreators-bot\n\npermissions:\n  contents: read\n\njobs:\n  update-template:\n    name: Migrate templates and text sets\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d\n        with:\n          egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n\n      - name: Setup Node\n        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f\n        with:\n          node-version-file: '.nvmrc'\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n        env:\n          PUPPETEER_SKIP_DOWNLOAD: true\n\n      - name: Update story data (templates, text sets, FTUE)\n        run: npm run workflow:migrate\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0\n        with:\n          token: ${{ secrets.GOOGLEFORCREATORS_BOT_TOKEN }}\n          commit-message: Migrate templates and text sets to latest version\n          title: Migrate templates and text sets\n          body: Update templates and text sets after running through migration\n          branch: update/templates\n          labels: Dependencies\n"
  },
  {
    "path": ".gitignore",
    "content": ".rollup.cache\n.test_artifacts\n.idea/\n.vscode/\n.DS_Store\nnode_modules\n/assets\n/packages/migration/scripts/module.js\n/packages/*/dist\n/packages/*/dist-module\n/packages/*/dist-types\n/build\n/bin/build\n/bin/local-env/data\nbin/local-env/docker-compose.override.yml\n/includes/vendor\n/includes/composer.json\n/plugin-assets\n/public\n/static\n/third-party\n/vendor\nphpcs.xml\nphpunit.xml\n.phpunit.result.cache\n/packages/*/package-lock.json\n*.tsbuildinfo\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n\n# TODO: Move to ~/.huskyrc instead.\n# See https://typicode.github.io/husky/#/?id=command-not-found\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\"\n\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx lint-staged --relative\n"
  },
  {
    "path": ".markdownlint.json",
    "content": "{\n  \"default\": true,\n  \"MD003\": { \"style\": \"atx\" },\n  \"MD007\": { \"indent\": 4 },\n  \"MD013\": { \"line_length\": 9999 },\n  \"no-hard-tabs\": false,\n  \"no-inline-html\": false,\n  \"whitespace\": false\n}\n"
  },
  {
    "path": ".markdownlintignore",
    "content": ".github\n__mocks__\nassets\nbin\nbuild\nnode_modules\ntests\nvendor\n"
  },
  {
    "path": ".npmpackagejsonlintrc.json",
    "content": "{\n  \"rules\": {\n    \"bin-type\": \"error\",\n    \"bundledDependencies-type\": \"error\",\n    \"config-type\": \"error\",\n    \"cpu-type\": \"error\",\n    \"dependencies-type\": \"error\",\n    \"description-type\": \"error\",\n    \"devDependencies-type\": \"error\",\n    \"directories-type\": \"error\",\n    \"engines-type\": \"error\",\n    \"files-type\": \"error\",\n    \"homepage-type\": \"error\",\n    \"keywords-type\": \"error\",\n    \"license-type\": \"error\",\n    \"main-type\": \"error\",\n    \"man-type\": \"error\",\n    \"name-format\": \"error\",\n    \"name-type\": \"error\",\n    \"no-restricted-dependencies\": \"off\",\n    \"no-restricted-devDependencies\": \"off\",\n    \"no-restricted-pre-release-dependencies\": \"off\",\n    \"no-restricted-pre-release-devDependencies\": \"off\",\n    \"optionalDependencies-type\": \"error\",\n    \"os-type\": \"error\",\n    \"peerDependencies-type\": \"error\",\n    \"prefer-absolute-version-dependencies\": \"off\",\n    \"prefer-absolute-version-devDependencies\": \"off\",\n    \"prefer-alphabetical-bundledDependencies\": \"error\",\n    \"prefer-alphabetical-dependencies\": \"error\",\n    \"prefer-alphabetical-devDependencies\": \"error\",\n    \"prefer-alphabetical-optionalDependencies\": \"error\",\n    \"prefer-alphabetical-peerDependencies\": \"error\",\n    \"prefer-caret-version-dependencies\": \"off\",\n    \"prefer-caret-version-devDependencies\": \"off\",\n    \"prefer-no-engineStrict\": \"off\",\n    \"prefer-no-version-zero-dependencies\": \"off\",\n    \"prefer-no-version-zero-devDependencies\": \"off\",\n    \"prefer-property-order\": [\n      \"error\",\n      [\n        \"name\",\n        \"description\",\n        \"private\",\n        \"version\",\n        \"author\",\n        \"license\",\n        \"keywords\",\n        \"homepage\",\n        \"repository\",\n        \"bugs\",\n        \"engines\",\n        \"files\",\n        \"type\",\n        \"workspaces\",\n        \"customExports\",\n        \"exports\",\n        \"main\",\n        \"module\",\n        \"types\",\n        \"source\",\n        \"publishConfig\",\n        \"sideEffects\",\n        \"dependencies\",\n        \"devDependencies\",\n        \"peerDependencies\",\n        \"bin\",\n        \"scripts\"\n      ]\n    ],\n    \"prefer-tilde-version-dependencies\": \"off\",\n    \"prefer-tilde-version-devDependencies\": \"off\",\n    \"preferGlobal-type\": \"error\",\n    \"private-type\": \"error\",\n    \"repository-type\": \"error\",\n    \"require-author\": \"error\",\n    \"require-bin\": \"off\",\n    \"require-bugs\": \"error\",\n    \"require-bundledDependencies\": \"off\",\n    \"require-config\": \"off\",\n    \"require-contributors\": \"off\",\n    \"require-cpu\": \"off\",\n    \"require-dependencies\": \"off\",\n    \"require-description\": \"error\",\n    \"require-devDependencies\": \"off\",\n    \"require-directories\": \"off\",\n    \"require-engines\": \"off\",\n    \"require-files\": \"off\",\n    \"require-homepage\": \"error\",\n    \"require-keywords\": \"error\",\n    \"require-license\": \"error\",\n    \"require-main\": \"off\",\n    \"require-man\": \"off\",\n    \"require-module\": \"off\",\n    \"require-name\": \"error\",\n    \"require-optionalDependencies\": \"off\",\n    \"require-os\": \"off\",\n    \"require-peerDependencies\": \"off\",\n    \"require-preferGlobal\": \"off\",\n    \"require-private\": \"off\",\n    \"require-publishConfig\": \"off\",\n    \"require-repository\": \"error\",\n    \"require-repository-directory\": \"off\",\n    \"require-scripts\": \"off\",\n    \"require-version\": \"off\",\n    \"scripts-type\": \"error\",\n    \"valid-values-author\": [\"error\", [\"Google\"]],\n    \"valid-values-license\": [\"error\", [\"Apache-2.0\"]],\n    \"valid-values-private\": \"off\",\n    \"version-format\": \"error\",\n    \"version-type\": \"error\"\n  }\n}\n"
  },
  {
    "path": ".npmrc",
    "content": "save-exact = false\nlockfile-version=3\n"
  },
  {
    "path": ".nvmrc",
    "content": "24\n"
  },
  {
    "path": ".oxlintrc.json",
    "content": "{\n\t\"$schema\": \"./node_modules/oxlint/configuration_schema.json\",\n\t\"categories\": {\n\t\t\"correctness\": \"error\",\n\t\t\"nursery\": \"error\",\n\t\t\"pedantic\": \"error\",\n\t\t\"perf\": \"off\",\n\t\t\"restriction\": \"error\",\n\t\t\"suspicious\": \"error\"\n\t},\n\t\"plugins\": [\n\t\t\"import\",\n\t\t\"jsdoc\",\n\t\t\"promise\",\n\t\t\"react-perf\"\n\t],\n\t\"ignorePatterns\": [\n\t\t\"@types\"\n\t],\n\t\"settings\": {\n\t\t\"jsdoc\": {\n\t\t\t\"tagNamePreference\": {\n\t\t\t\t\"returns\": \"return\",\n\t\t\t\t\"yields\": \"yield\"\n\t\t\t}\n\t\t}\n\t},\n\t\"rules\": {\n\t\t\"accessor-pairs\": \"off\",\n\t\t\"class-methods-use-this\": \"off\",\n\t\t\"complexity\": \"off\",\n\t\t\"default-case\": \"off\",\n\t\t\"max-classes-per-file\": \"off\",\n\t\t\"max-depth\": \"off\",\n\t\t\"max-lines\": \"off\",\n\t\t\"max-lines-per-function\": \"off\",\n\t\t\"no-alert\": \"off\",\n\t\t\"no-bitwise\": \"off\",\n\t\t\"no-case-declarations\": \"off\",\n\t\t\"no-else-return\": \"off\",\n\t\t\"no-empty-function\": \"off\",\n\t\t\"no-inline-comments\": \"off\",\n\t\t\"no-multiple-resolved\": \"off\",\n\t\t\"no-negated-condition\": \"off\",\n\t\t\"no-param-reassign\": \"off\",\n\t\t\"no-plusplus\": \"off\",\n\t\t\"no-promise-executor-return\": \"off\",\n\t\t\"no-shadow\": \"off\",\n\t\t\"no-undef\": \"off\",\n\t\t\"no-undefined\": \"off\",\n\t\t\"no-unused-expressions\": \"off\",\n\t\t\"no-unused-vars\": \"off\",\n\t\t\"no-useless-return\": \"off\",\n\t\t\"no-void\": [\"error\", { \"allowAsStatement\": true }],\n\t\t\"no-warning-comments\": \"off\",\n\t\t\"radix\": \"off\",\n\t\t\"require-await\": \"off\",\n\t\t\"sort-vars\": \"off\",\n\t\t\"symbol-description\": \"off\",\n\t\t\"import/export\": \"off\",\n\t\t\"import/extensions\": \"off\",\n\t\t\"import/max-dependencies\": \"off\",\n\t\t\"import/named\": \"off\",\n\t\t\"import/no-commonjs\": \"off\",\n\t\t\"import/no-default-export\": \"off\",\n\t\t\"import/no-named-as-default\": \"off\",\n\t\t\"import/no-named-as-default-member\": \"off\",\n\t\t\"import/no-relative-parent-imports\": \"off\",\n\t\t\"import/no-unassigned-import\": \"off\",\n\t\t\"import/unambiguous\": \"off\",\n\t\t\"jest/no-conditional-in-test\": \"off\",\n\t\t\"jsdoc/check-tag-names\": \"off\",\n\t\t\"jsdoc/require-param\": \"off\",\n\t\t\"jsdoc/require-param-description\": \"off\",\n\t\t\"jsdoc/require-param-type\": \"off\",\n\t\t\"jsdoc/require-returns\": \"off\",\n\t\t\"jsdoc/require-returns-type\": \"off\",\n\t\t\"promise/always-return\": \"off\",\n\t\t\"promise/catch-or-return\": \"off\",\n\t\t\"promise/no-callback-in-promise\": \"off\"\n\t},\n  \"overrides\": [\n    {\n      \"files\": [\n        \"packages/commander/**/*.ts\"\n      ],\n      \"rules\": {\n        \"no-console\": \"off\"\n      }\n    },\n    {\n      \"files\": [\n        \"**/*.d.ts\",\n        \"packages/karma-puppeteer-client/**/*.js\",\n        \"packages/karma-puppeteer-launcher/**/*.js\"\n      ],\n      \"rules\": {\n        \"no-var\": \"off\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".phpstorm.config.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// eslint-disable-next-line no-undef -- Special global in IntelliJ.\nSystem.config({\n  paths: {\n    // Published Packages\n    '@googleforcreators/animation': './packages/animation/src',\n    '@googleforcreators/dashboard': './packages/dashboard/src',\n    '@googleforcreators/date': './packages/date/src',\n    '@googleforcreators/design-system': './packages/design-system/src',\n    '@googleforcreators/dom': './packages/dom/src',\n    '@googleforcreators/element-library': './packages/element-library/src',\n    '@googleforcreators/elements': './packages/elements/src',\n    '@googleforcreators/fonts': './packages/fonts/src',\n    '@googleforcreators/i18n': './packages/i18n/src',\n    '@googleforcreators/masks': './packages/masks/src',\n    '@googleforcreators/media': './packages/media/src',\n    '@googleforcreators/migration': './packages/migration/src',\n    '@googleforcreators/moveable': './packages/moveable/src',\n    '@googleforcreators/output': './packages/output/src',\n    '@googleforcreators/patterns': './packages/patterns/src',\n    '@googleforcreators/react': './packages/react/src',\n    '@googleforcreators/rich-text': './packages/rich-text/src',\n    '@googleforcreators/stickers': './packages/stickers/src',\n    '@googleforcreators/story-editor': './packages/story-editor/src',\n    '@googleforcreators/templates': './packages/templates/src',\n    '@googleforcreators/text-sets': './packages/text-sets/src',\n    '@googleforcreators/tracking': './packages/tracking/src',\n    '@googleforcreators/transform': './packages/transform/src',\n    '@googleforcreators/units': './packages/units/src',\n    '@googleforcreators/url': './packages/url/src',\n\n    // Private Packages\n    '@web-stories-wp/e2e-tests': './packages/e2e-tests/src',\n    '@web-stories-wp/activation-notice': './packages/activation-notice/src',\n    '@web-stories-wp/commander': './packages/commander/src',\n    '@web-stories-wp/e2e-test-utils': './packages/e2e-test-utils/src',\n    '@web-stories-wp/eslint-import-resolver': './packages/eslint-import-resolver/src',\n    '@web-stories-wp/glider': './packages/glider/src',\n    '@web-stories-wp/jest-amp': './packages/jest-amp/src',\n    '@web-stories-wp/jest-puppeteer-amp': './packages/jest-puppeteer-amp/src',\n    '@web-stories-wp/jest-resolver': './packages/jest-resolver/src',\n    '@web-stories-wp/karma-failed-tests-reporter': './packages/karma-failed-tests-reporter/src',\n    '@web-stories-wp/karma-puppeteer-client': './packages/karma-puppeteer-client/src',\n    '@web-stories-wp/karma-puppeteer-launcher': './packages/karma-puppeteer-launcher/src',\n    '@web-stories-wp/stories-block': './packages/stories-block/src',\n    '@web-stories-wp/stories-carousel': './packages/stories-carousel/src',\n    '@web-stories-wp/tinymce-button': './packages/tinymce-button/src',\n    '@web-stories-wp/widget': './packages/widget/src',\n    '@web-stories-wp/wp-dashboard': './packages/wp-dashboard/src',\n    '@web-stories-wp/wp-story-editor': './packages/wp-story-editor/src',\n    '@web-stories-wp/wp-utils': './packages/wp-utils/src',\n  },\n});\n"
  },
  {
    "path": ".phpstorm.meta.php",
    "content": "<?php\n\nnamespace PHPSTORM_META {\n\n\toverride(\n\t\t\\Google\\Web_Stories\\Services::get(),\n\n\t\t// TODO: I'd like to use Plugin::SERVICES directly here but it doesn't seem to work.\n\t\tmap( [\n\t\t\t'activation_notice'            => \\Google\\Web_Stories\\Admin\\Activation_Notice::class,\n\t\t\t'admin.google_fonts'           => \\Google\\Web_Stories\\Admin\\Google_Fonts::class,\n\t\t\t'amp_output_buffer'            => \\Google\\Web_Stories\\AMP\\Output_Buffer::class,\n\t\t\t'amp_story_player_assets'      => \\Google\\Web_Stories\\AMP_Story_Player_Assets::class,\n\t\t\t'adsense'                      => \\Google\\Web_Stories\\AdSense::class,\n\t\t\t'ad_manager'                   => \\Google\\Web_Stories\\Ad_Manager::class,\n\t\t\t'mgid'                         => \\Google\\Web_Stories\\Mgid::class,\n\t\t\t'admin'                        => \\Google\\Web_Stories\\Admin\\Admin::class,\n\t\t\t'admin.revisions'              => \\Google\\Web_Stories\\Admin\\Revisions::class,\n\t\t\t'analytics'                    => \\Google\\Web_Stories\\Analytics::class,\n\t\t\t'coi'                          => \\Google\\Web_Stories\\Admin\\Cross_Origin_Isolation::class,\n\t\t\t'customizer'                   => \\Google\\Web_Stories\\Admin\\Customizer::class,\n\t\t\t'dashboard'                    => \\Google\\Web_Stories\\Admin\\Dashboard::class,\n\t\t\t'database_upgrader'            => \\Google\\Web_Stories\\Database_Upgrader::class,\n\t\t\t'discovery'                    => \\Google\\Web_Stories\\Discovery::class,\n\t\t\t'editor'                       => \\Google\\Web_Stories\\Admin\\Editor::class,\n\t\t\t'embed_shortcode'              => \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode::class,\n\t\t\t'experiments'                  => \\Google\\Web_Stories\\Experiments::class,\n\t\t\t'integrations.amp'             => \\Google\\Web_Stories\\Integrations\\AMP::class,\n\t\t\t'integrations.ezoic'           => \\Google\\Web_Stories\\Integrations\\Ezoic::class,\n\t\t\t'integrations.jetpack'         => \\Google\\Web_Stories\\Integrations\\Jetpack::class,\n\t\t\t'integrations.newrelic'        => \\Google\\Web_Stories\\Integrations\\New_Relic::class,\n\t\t\t'integrations.nextgen_gallery' => \\Google\\Web_Stories\\Integrations\\NextGen_Gallery::class,\n\t\t\t'integrations.cfi'             => \\Google\\Web_Stories\\Integrations\\Conditional_Featured_Image::class,\n\t\t\t'integrations.sitekit'         => \\Google\\Web_Stories\\Integrations\\Site_Kit::class,\n\t\t\t'integrations.themes_support'  => \\Google\\Web_Stories\\Integrations\\Core_Themes_Support::class,\n\t\t\t'integrations.shortpixel'      => \\Google\\Web_Stories\\Integrations\\ShortPixel::class,\n\t\t\t'kses'                         => \\Google\\Web_Stories\\KSES::class,\n\t\t\t'media.base_color'             => \\Google\\Web_Stories\\Media\\Base_Color::class,\n\t\t\t'media.blurhash'               => \\Google\\Web_Stories\\Media\\Blurhash::class,\n\t\t\t'media.image_sizes'            => \\Google\\Web_Stories\\Media\\Image_Sizes::class,\n\t\t\t'media.media_source'           => \\Google\\Web_Stories\\Media\\Media_Source_Taxonomy::class,\n\t\t\t'media.video.captions'         => \\Google\\Web_Stories\\Media\\Video\\Captions::class,\n\t\t\t'media.cropping'               => \\Google\\Web_Stories\\Media\\Cropping::class,\n\t\t\t'media.video.muting'           => \\Google\\Web_Stories\\Media\\Video\\Muting::class,\n\t\t\t'media.video.optimization'     => \\Google\\Web_Stories\\Media\\Video\\Optimization::class,\n\t\t\t'media.video.poster'           => \\Google\\Web_Stories\\Media\\Video\\Poster::class,\n\t\t\t'media.video.trimming'         => \\Google\\Web_Stories\\Media\\Video\\Trimming::class,\n\t\t\t'font_post_type'               => \\Google\\Web_Stories\\Font_Post_Type::class,\n\t\t\t'page_template_post_type'      => \\Google\\Web_Stories\\Page_Template_Post_Type::class,\n\t\t\t'plugin_row_meta'              => \\Google\\Web_Stories\\Admin\\PluginRowMeta::class,\n\t\t\t'plugin_action_links'          => \\Google\\Web_Stories\\Admin\\PluginActionLinks::class,\n\t\t\t'product_meta'                 => \\Google\\Web_Stories\\Shopping\\Product_Meta::class,\n\t\t\t'meta_boxes'                   => \\Google\\Web_Stories\\Admin\\Meta_Boxes::class,\n\t\t\t'settings'                     => \\Google\\Web_Stories\\Settings::class,\n\t\t\t'site_health'                  => \\Google\\Web_Stories\\Admin\\Site_Health::class,\n\t\t\t'story_archive'                => \\Google\\Web_Stories\\Story_Archive::class,\n\t\t\t'story_post_type'              => \\Google\\Web_Stories\\Story_Post_Type::class,\n\t\t\t'story_revisions'              => \\Google\\Web_Stories\\Story_Revisions::class,\n\t\t\t'story_shortcode'              => \\Google\\Web_Stories\\Shortcode\\Stories_Shortcode::class,\n\t\t\t'svg'                          => \\Google\\Web_Stories\\Media\\SVG::class,\n\t\t\t'tracking'                     => \\Google\\Web_Stories\\Tracking::class,\n\t\t\t'tinymce'                      => \\Google\\Web_Stories\\Admin\\TinyMCE::class,\n\t\t\t'register.widget'              => \\Google\\Web_Stories\\Register_Widget::class,\n\t\t\t'renderer.archives'            => \\Google\\Web_Stories\\Renderer\\Archives::class,\n\t\t\t'renderer.single'              => \\Google\\Web_Stories\\Renderer\\Single::class,\n\t\t\t'renderer.oembed'              => \\Google\\Web_Stories\\Renderer\\Oembed::class,\n\t\t\t'renderer.feed'                => \\Google\\Web_Stories\\Renderer\\Feed::class,\n\t\t\t'user.capabilities'            => \\Google\\Web_Stories\\User\\Capabilities::class,\n\t\t\t'rest.embed_controller'        => \\Google\\Web_Stories\\REST_API\\Embed_Controller::class,\n\t\t\t'rest.link_controller'         => \\Google\\Web_Stories\\REST_API\\Link_Controller::class,\n\t\t\t'rest.hotlinking_controller'   => \\Google\\Web_Stories\\REST_API\\Hotlinking_Controller::class,\n\t\t\t'rest.publisher_logos'         => \\Google\\Web_Stories\\REST_API\\Publisher_Logos_Controller::class,\n\t\t\t'rest.status_check_controller' => \\Google\\Web_Stories\\REST_API\\Status_Check_Controller::class,\n\t\t\t'rest.stories_autosave'        => \\Google\\Web_Stories\\REST_API\\Stories_Autosaves_Controller::class,\n\t\t\t'rest.stories_lock'            => \\Google\\Web_Stories\\REST_API\\Stories_Lock_Controller::class,\n\t\t\t'rest.media'                   => \\Google\\Web_Stories\\REST_API\\Stories_Media_Controller::class,\n\t\t\t'rest.settings'                => \\Google\\Web_Stories\\REST_API\\Stories_Settings_Controller::class,\n\t\t\t'rest.users'                   => \\Google\\Web_Stories\\REST_API\\Stories_Users_Controller::class,\n\t\t\t'rest.taxonomies'              => \\Google\\Web_Stories\\REST_API\\Stories_Taxonomies_Controller::class,\n\t\t\t'rest.template_autosave'       => \\Google\\Web_Stories\\REST_API\\Template_Autosaves_Controller::class,\n\t\t\t'rest.template_lock'           => \\Google\\Web_Stories\\REST_API\\Template_Lock_Controller::class,\n\t\t\t'taxonomy.category'            => \\Google\\Web_Stories\\Taxonomy\\Category_Taxonomy::class,\n\t\t\t'taxonomy.tag'                 => \\Google\\Web_Stories\\Taxonomy\\Tag_Taxonomy::class,\n\t\t\t'user_preferences'             => \\Google\\Web_Stories\\User\\Preferences::class,\n\t\t\t'remove_transients'            => \\Google\\Web_Stories\\Remove_Transients::class,\n\t\t\t'web_stories_block'            => \\Google\\Web_Stories\\Block\\Web_Stories_Block::class,\n\t\t\t'injector'                     => \\Google\\Web_Stories\\Infrastructure\\Injector::class,\n\t\t] )\n\t);\n\n\t// For the injector, the return type should be the same as what the provided FQCN represents.\n\toverride(\n\t\t\\Google\\Web_Stories\\Infrastructure\\Injector::make(),\n\t\tmap( [ '' => '@' ] )\n\t);\n}\n"
  },
  {
    "path": ".prettierignore",
    "content": "/.idea\n/bin/local-env/uploads.ini\n/bin/local-env/data\n/build\n/docs\n/node_modules\n/vendor\n/assets/css\n/assets/js\n/assets/images\npackages/karma-puppeteer-client/src/client.js\n.browserslistrc\n.distignore\n.editorconfig\n.eslintignore\n.eslintrc\n.gitignore\n.npmrc\n.nvmrc\n.prettierignore\n.prettierrc\n.stylelintignore\n.stylelintrc\n.DS_Store\n*.php\n*.txt\n*.sh\n*.svg\nLICENSE\ncomposer.json\ncomposer.lock\npackage.json\npackage-lock.json\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"plugins\": [\"@prettier/plugin-xml\"],\n  \"printWidth\": 80,\n  \"singleQuote\": true,\n  \"trailingComma\": \"es5\",\n  \"bracketSpacing\": true,\n  \"arrowParens\": \"always\",\n  \"overrides\": [\n    {\n      \"files\": \"*.md\",\n      \"options\": {\n        \"parser\": \"markdown\"\n      }\n    },\n    {\n      \"files\": [\".eslintrc\", \".prettierrc\", \".stylelintrc\", \"*.json\"],\n      \"options\": {\n        \"parser\": \"json\"\n      }\n    },\n    {\n      \"files\": [\"*.yml\", \"*.neon.dist\"],\n      \"options\": {\n        \"parser\": \"yaml\"\n      }\n    },\n    {\n      \"files\": [\"*.xml\", \"*.xml.dist\"],\n      \"options\": {\n        \"parser\": \"xml\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".storybook/main.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst { readFileSync } = require('fs');\nconst webpack = require('webpack');\nconst CircularDependencyPlugin = require('circular-dependency-plugin');\n// eslint-disable-next-line n/no-missing-require\nconst { loadCsf } = require('storybook/internal/csf-tools');\n\n/** @type { import('@storybook/react-webpack5').StorybookConfig } */\nmodule.exports = {\n  stories: [\n    './stories/playground/*/(index|preview).js',\n    '../packages/dashboard/src/**/stories/index.js',\n    '../packages/story-editor/src/**/stories/index.js',\n    '../packages/wp-dashboard/src/**/stories/index.js',\n    '../packages/activation-notice/src/**/stories/index.js',\n    '../packages/design-system/src/**/stories/index.js',\n    '../packages/animation/src/**/stories/*.js',\n  ],\n\n  experimental_indexers: (indexers) => {\n    const createIndex = (fileName, opts) => {\n      const code = readFileSync(fileName, {\n        encoding: 'utf-8',\n      });\n      return loadCsf(code, {\n        ...opts,\n        fileName,\n      }).parse().indexInputs;\n    };\n    return [\n      {\n        test: /stories\\/.*\\.js$/,\n        createIndex,\n      },\n      ...(indexers || []),\n    ];\n  },\n\n  addons: [\n    '@storybook/addon-a11y/register',\n    '@storybook/addon-webpack5-compiler-babel',\n  ],\n\n  framework: {\n    name: '@storybook/react-webpack5',\n    options: {},\n  },\n\n  core: {\n    disableTelemetry: true,\n  },\n\n  docs: {\n    disabled: true,\n  },\n\n  //eslint-disable-next-line require-await -- Negligible.\n  webpackFinal: async (webpackConfig) => {\n    // webpack < 5 used to include polyfills for node.js core modules by default.\n    // Prevent ModuleNotFoundError for this dependency.\n    webpackConfig.resolve = {\n      ...webpackConfig.resolve,\n      // Fixes resolving packages in the monorepo so we use the \"src\" folder, not \"dist\".\n      // This should be sync'd with the config in `webpack.config.cjs`.\n      exportsFields: ['customExports', 'exports'],\n      // To make loading mediainfo.js work.\n      fallback: {\n        fs: false,\n        path: false,\n        url: false,\n        module: false,\n        assert: false,\n        perf_hooks: false,\n        crypto: false,\n        worker_threads: false,\n      },\n    };\n\n    // Avoid having to provide full file extension for imports.\n    // See https://webpack.js.org/configuration/module/#resolvefullyspecified\n\n    webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => ({\n      ...rule,\n      resolve: {\n        ...rule.resolve,\n        fullySpecified: false,\n      },\n    }));\n\n    // These should be sync'd with the config in `webpack.config.cjs`.\n    webpackConfig.plugins.push(\n      new webpack.DefinePlugin({\n        WEB_STORIES_CI: JSON.stringify(process.env.CI),\n        WEB_STORIES_ENV: JSON.stringify(process.env.NODE_ENV),\n        WEB_STORIES_DISABLE_ERROR_BOUNDARIES: JSON.stringify(\n          process.env.DISABLE_ERROR_BOUNDARIES\n        ),\n        WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: JSON.stringify(\n          process.env.DISABLE_OPTIMIZED_RENDERING\n        ),\n        WEB_STORIES_DISABLE_PREVENT: JSON.stringify(\n          process.env.DISABLE_PREVENT\n        ),\n        WEB_STORIES_DISABLE_QUICK_TIPS: JSON.stringify(\n          process.env.DISABLE_QUICK_TIPS\n        ),\n      })\n    );\n\n    // These should be sync'd with the config in `webpack.config.cjs`.\n    webpackConfig.plugins.push(\n      new webpack.DefinePlugin({\n        WEB_STORIES_CI: JSON.stringify(process.env.CI),\n        WEB_STORIES_ENV: JSON.stringify(process.env.NODE_ENV),\n        WEB_STORIES_DISABLE_ERROR_BOUNDARIES: JSON.stringify(\n          process.env.DISABLE_ERROR_BOUNDARIES\n        ),\n        WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: JSON.stringify(\n          process.env.DISABLE_OPTIMIZED_RENDERING\n        ),\n        WEB_STORIES_DISABLE_PREVENT: JSON.stringify(\n          process.env.DISABLE_PREVENT\n        ),\n        WEB_STORIES_DISABLE_QUICK_TIPS: JSON.stringify(\n          process.env.DISABLE_QUICK_TIPS\n        ),\n      })\n    );\n    webpackConfig.plugins.push(\n      new CircularDependencyPlugin({\n        // exclude detection of files based on a RegExp\n        exclude: /a\\.js|node_modules/,\n        // add errors to webpack instead of warnings\n        failOnError: true,\n        // allow import cycles that include an asynchronous import,\n        // e.g. via import(/* webpackMode: \"weak\" */ 'file.js')\n        allowAsyncCycles: false,\n        // set the current working directory for displaying module paths\n        cwd: process.cwd(),\n      })\n    );\n\n    // Ensure SVGR is the only loader used for files with .svg extension.\n    const assetRule = webpackConfig.module.rules.find(({ test }) => {\n      if (!test) {\n        return false;\n      }\n      if (Array.isArray(test)) {\n        return test.every((t) => t.test('.svg'));\n      }\n      return test.test('.svg');\n    });\n    assetRule.exclude = /\\.svg/;\n    webpackConfig.module.rules.unshift(\n      {\n        test: /\\.svg$/,\n        // Use asset SVG and SVGR together.\n        // Not using resourceQuery because it doesn't work well with Rollup.\n        // https://react-svgr.com/docs/webpack/#use-svgr-and-asset-svg-in-the-same-project\n        oneOf: [\n          {\n            type: 'asset/inline',\n            include: [/inline-icons\\/.*\\.svg$/],\n          },\n          {\n            issuer: /\\.[jt]sx?$/,\n            include: [/\\/icons\\/.*\\.svg$/],\n            use: [\n              {\n                loader: '@svgr/webpack',\n                options: {\n                  titleProp: true,\n                  svgo: true,\n                  memo: true,\n                  svgoConfig: {\n                    plugins: [\n                      {\n                        name: 'preset-default',\n                        params: {\n                          overrides: {\n                            removeViewBox: false,\n                            convertColors: {\n                              currentColor: /^(?!url|none)/i,\n                            },\n                          },\n                        },\n                      },\n                      'removeDimensions',\n                    ],\n                  },\n                },\n              },\n            ],\n          },\n          {\n            issuer: /\\.[jt]sx?$/,\n            include: [/images\\/.*\\.svg$/],\n            use: [\n              {\n                loader: '@svgr/webpack',\n                options: {\n                  titleProp: true,\n                  svgo: true,\n                  memo: true,\n                  svgoConfig: {\n                    plugins: [\n                      {\n                        name: 'preset-default',\n                        params: {\n                          overrides: {\n                            removeViewBox: false,\n                            convertColors: {\n                              // See https://github.com/googleforcreators/web-stories-wp/pull/6361\n                              currentColor: false,\n                            },\n                          },\n                        },\n                      },\n                      'removeDimensions',\n                    ],\n                  },\n                },\n              },\n            ],\n          },\n        ],\n      },\n      {\n        test: /\\.(png|jpe?g|gif|webp)$/i,\n        type: 'asset/resource',\n        generator: {\n          outputPath: 'images/',\n        },\n      }\n    );\n    return webpackConfig;\n  },\n\n  features: {\n    actions: true,\n    backgrounds: true,\n    controls: false,\n    viewport: true,\n    toolbars: true,\n  },\n};\n"
  },
  {
    "path": ".storybook/manager-head.html",
    "content": "<style>\n\t#playground-preview {\n\t\tdisplay: none;\n\t}\n</style>\n"
  },
  {
    "path": ".storybook/preview-head.html",
    "content": "<!--\n  ~ Copyright 2020 Google LLC\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~     https://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<link\n  href=\"https://fonts.googleapis.com/css?family=Google+Sans|Google+Sans:b|Google+Sans:500&display=swap\"\n  rel=\"stylesheet\"\n/>\n\n<script async src=\"https://cdn.ampproject.org/v0.js\"></script>\n<script\n  async\n  custom-element=\"amp-story\"\n  src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\"\n></script>\n"
  },
  {
    "path": ".storybook/preview.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ThemeProvider } from 'styled-components';\n// eslint-disable-next-line import/no-unresolved\nimport { INITIAL_VIEWPORTS } from 'storybook/viewport';\nimport {\n  theme as designSystemTheme,\n  lightMode,\n  ThemeGlobals,\n  ModalGlobalStyle,\n} from '@googleforcreators/design-system';\nimport { CropMoveableGlobalStyle } from '@googleforcreators/moveable';\n\n/**\n * Internal dependencies\n */\n// Disable reason:\n// Importing from the dashboard and story editor roots break fast refresh in storybook.\n// Prevented by importing the necessary providers and configs directly.\n/* eslint-disable import/no-relative-packages */\nimport { GlobalStyle as DashboardGlobalStyle } from '../packages/dashboard/src/theme';\nimport DashboardKeyboardOnlyOutline from '../packages/dashboard/src/utils/keyboardOnlyOutline';\nimport DashboardConfigProvider from '../packages/dashboard/src/app/config/configProvider';\nimport ApiProvider from '../packages/dashboard/src/app/api/apiProvider';\nimport EditorConfigProvider from '../packages/story-editor/src/app/config/configProvider';\n/* eslint-enable import/no-relative-packages */\n\n// @todo: Find better way to mock these.\nconst wp = {};\nwindow.wp = window.wp || wp;\nwindow.wp.media = {\n  controller: {\n    Library: {\n      prototype: {\n        defaults: {},\n      },\n    },\n  },\n};\n\nconst { ipad, ipad10p, ipad12p } = INITIAL_VIEWPORTS;\n\n/** @type { import('@storybook/react-webpack5').Preview } */\nconst preview = {\n  parameters: {\n    a11y: {\n      element: '#root',\n      config: {},\n      options: {},\n      manual: true,\n    },\n    viewport: {\n      viewports: {\n        ipad,\n        ipad10p,\n        ipad12p,\n      },\n    },\n    backgrounds: {\n      default: 'Light',\n      values: [\n        { name: 'Light', value: '#fff', default: true },\n        { name: 'Dark', value: 'rgba(0, 0, 0, 0.9)', default: true },\n      ],\n    },\n  },\n\n  decorators: [\n    (Story, context) => {\n      const { id } = context;\n      // TODO(#10380): Replacement add-on for RTL feature\n      const isRTL = false;\n\n      const isDesignSystemStorybook = id.startsWith('designsystem');\n      const isDashboardStorybook = id.startsWith('dashboard');\n\n      if (isDashboardStorybook) {\n        return (\n          <ThemeProvider\n            theme={{\n              ...designSystemTheme,\n              colors: lightMode,\n            }}\n          >\n            <DashboardConfigProvider\n              config={{\n                api: { stories: 'stories' },\n                apiCallbacks: {\n                  getUser: () => Promise.resolve({ id: 1 }),\n                },\n                editStoryURL: 'editStory',\n                isRTL,\n                styleConstants: {\n                  topOffset: 0,\n                },\n              }}\n            >\n              <ApiProvider>\n                <DashboardGlobalStyle />\n                <ModalGlobalStyle />\n                <DashboardKeyboardOnlyOutline />\n                {Story()}\n              </ApiProvider>\n            </DashboardConfigProvider>\n          </ThemeProvider>\n        );\n      }\n\n      if (isDesignSystemStorybook) {\n        // override darkMode colors\n        const dsTheme = { ...designSystemTheme, colors: lightMode };\n        return (\n          <ThemeProvider theme={dsTheme}>\n            <ThemeGlobals.Styles />\n            <ModalGlobalStyle />\n            {Story()}\n          </ThemeProvider>\n        );\n      }\n\n      return (\n        <ThemeProvider theme={designSystemTheme}>\n          <EditorConfigProvider config={{ isRTL }}>\n            <CropMoveableGlobalStyle />\n            <ModalGlobalStyle />\n            {Story()}\n          </EditorConfigProvider>\n        </ThemeProvider>\n      );\n    },\n  ],\n};\n\nexport default preview;\n"
  },
  {
    "path": ".storybook/stories/playground/dashboard/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useEffect } from 'react';\nimport { toId } from '@storybook/csf';\nimport { Dashboard, InterfaceSkeleton } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport { GlobalStyle } from './theme';\n\nexport default {\n  title: 'Playground/Dashboard',\n};\n\nconst linkHrefTo = (title, name) => {\n  const url = new URL(window.parent.location);\n  url.searchParams.set('path', '/story/' + toId(title, name));\n  return decodeURIComponent(url.href);\n};\n\nconst fetchStories = () => {\n  const response = {\n    stories: {\n      1: {\n        id: 1,\n        status: 'publish',\n        title: 'Example story',\n        created: '2021-11-04T10:12:47',\n        createdGmt: '2021-11-04T10:12:47Z',\n        author: {\n          name: 'Author',\n          id: 1,\n        },\n        featuredMediaUrl:\n          'https://wp.stories.google/static/main/images/templates/food-and-stuff/page1_bg.jpg',\n      },\n      2: {\n        id: 2,\n        status: 'publish',\n        title: 'Example story 2',\n        created: '2021-12-04T10:12:47',\n        createdGmt: '2021-12-04T10:12:47Z',\n        author: {\n          name: 'Author',\n          id: 1,\n        },\n        featuredMediaUrl:\n          'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page8_figure.jpg',\n      },\n    },\n    fetchedStoryIds: [1, 2],\n    totalPages: 1,\n    totalStoriesByStatus: {\n      all: 2,\n      publish: 2,\n    },\n  };\n\n  return Promise.resolve(response);\n};\n\n// mock filter api calls\nconst getTaxonomies = () =>\n  Promise.resolve([\n    {\n      restBase: '',\n      restPath: '',\n      labels: {\n        allItems: 'All Categories',\n        notFound: 'No categories found',\n        searchItems: 'Search Categories',\n      },\n    },\n  ]);\nconst getTaxonomyTerms = () => Promise.resolve([{ name: 'Food', id: 1 }]);\nconst getAuthors = () => Promise.resolve([{ name: 'Author', id: 1 }]);\n\n/**\n * Clears url hash ( Required only for storybook )\n * Dashboard uses # for checking route path and story-editor uses #page,\n * when returning from story-editor to dashboard in storybook, currentPath read from history package gets manipulated,\n * which breaks the current path, so this custom hook is used to clear the hash before dashboard app is mounted.\n */\nconst useClearHash = () => {\n  const isHashCleaned = useRef(false);\n\n  useEffect(() => {\n    if (!isHashCleaned.current) {\n      window.location.hash = '/';\n      isHashCleaned.current = true;\n    }\n  }, []);\n};\n\nexport const _default = {\n  render: function Render() {\n    useClearHash();\n\n    const config = {\n      newStoryURL: linkHrefTo('Playground/Stories Editor', 'default'),\n      apiCallbacks: {\n        fetchStories,\n        getTaxonomies,\n        getTaxonomyTerms,\n        getAuthors,\n      },\n    };\n\n    return (\n      <Dashboard config={config}>\n        <GlobalStyle />\n        <InterfaceSkeleton />\n      </Dashboard>\n    );\n  },\n};\n"
  },
  {
    "path": ".storybook/stories/playground/dashboard/theme.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\nexport const GlobalStyle = createGlobalStyle`\n  body.web-story_page_stories-dashboard #wpbody {\n    ${themeHelpers.scrollbarCSS};\n  }\n`;\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/api/fonts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport async function getFonts(params) {\n  let { default: fonts } = await import(\n    /* webpackChunkName: \"chunk-fonts\" */ '@googleforcreators/fonts/fonts.json' // eslint-disable-line import/no-internal-modules -- This is fine here.\n  );\n\n  fonts = fonts.map((font) => ({\n    id: font.family,\n    name: font.family,\n    value: font.family,\n    ...font,\n  }));\n\n  if (params.include) {\n    const include = params.include.split(',');\n    fonts = fonts.filter(({ family }) => include.includes(family));\n  }\n\n  if (params.search) {\n    fonts = fonts.filter(({ family }) =>\n      family.toLowerCase().includes(params.search)\n    );\n  }\n\n  return fonts;\n}\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/api/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Not using \"export * from\" because of https://github.com/storybookjs/storybook/issues/17587\n\nexport { getFonts } from './fonts';\nexport { getMedia } from './media';\nexport { saveStoryById } from './story';\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/api/media.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { getDummyMedia } from '../getDummyMedia';\n\nexport const getMedia = (params) => {\n  const dummyMedia = getDummyMedia();\n  const mediaResponse = {\n    data: dummyMedia,\n    headers: {\n      totalItems: dummyMedia.length,\n      totalPages: 1,\n    },\n  };\n\n  if (params.searchTerm) {\n    mediaResponse.data = dummyMedia.filter((media) => {\n      return media.alt.toLowerCase().includes(params.searchTerm.toLowerCase());\n    });\n    mediaResponse.headers.totalItems = mediaResponse.data.length;\n  }\n\n  return Promise.resolve(mediaResponse);\n};\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/api/story.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { DATA_VERSION } from '@googleforcreators/migration';\n\n/**\n * Internal dependencies\n */\nimport {\n  LOCAL_STORAGE_CONTENT_KEY,\n  LOCAL_STORAGE_PREVIEW_MARKUP_KEY,\n} from '../constants';\n\nexport const saveStoryById = ({\n  pages,\n  globalStoryStyles,\n  autoAdvance,\n  defaultPageDuration,\n  currentStoryStyles,\n  backgroundAudio,\n  content,\n  title,\n  excerpt,\n}) => {\n  const storySaveData = {\n    title: {\n      raw: title,\n    },\n    excerpt: {\n      raw: excerpt,\n    },\n    storyData: {\n      version: DATA_VERSION,\n      pages,\n      autoAdvance,\n      defaultPageDuration,\n      currentStoryStyles,\n      backgroundAudio,\n    },\n    author: {\n      id: 1,\n      name: '',\n    },\n    stylePresets: globalStoryStyles,\n    permalinkTemplate: 'https://example.org/web-stories/%pagename%/',\n  };\n\n  window.localStorage.setItem(\n    LOCAL_STORAGE_CONTENT_KEY,\n    JSON.stringify(storySaveData)\n  );\n  window.localStorage.setItem(LOCAL_STORAGE_PREVIEW_MARKUP_KEY, content);\n\n  return Promise.resolve({});\n};\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const LOCAL_STORAGE_CONTENT_KEY = 'web_stories_json_content';\nexport const LOCAL_STORAGE_PREVIEW_MARKUP_KEY = 'web_stories_preview_markup';\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/getDummyMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createResource } from '@googleforcreators/media';\n\nfunction createDummyImageData({\n  mimeType = 'image/jpeg',\n  src,\n  width,\n  height,\n  id,\n  title,\n}) {\n  return createResource({\n    mimeType,\n    creationDate: '2021-10-29T11:43:38',\n    src,\n    width,\n    height,\n    id,\n    alt: title,\n    sizes: {\n      medium: {\n        file: `${title}-300x84.jpeg`,\n        width: 300,\n        height: 84,\n        mimeType,\n        sourceUrl: src,\n      },\n      large: {\n        file: `${title}-1024x288.jpeg`,\n        width: 1024,\n        height: 288,\n        mimeType,\n        sourceUrl: src,\n      },\n      thumbnail: {\n        file: `${title}-150x150.jpeg`,\n        width: 150,\n        height: 150,\n        mimeType,\n        sourceUrl: src,\n      },\n      medium_large: {\n        file: `${title}-768x216.jpeg`,\n        width: 768,\n        height: 216,\n        mimeType,\n        sourceUrl: src,\n      },\n      '1536x1536': {\n        file: `${title}-1536x432.jpeg`,\n        width: 1536,\n        height: 432,\n        mimeType,\n        sourceUrl: src,\n      },\n      '2048x2048': {\n        file: `${title}-2048x576.jpeg`,\n        width: 2048,\n        height: 576,\n        mimeType,\n        sourceUrl: src,\n      },\n      'post-thumbnail': {\n        file: `${title}-1568x441.jpeg`,\n        width: 1568,\n        height: 441,\n        mimeType,\n        sourceUrl: src,\n      },\n      'web-stories-poster-portrait': {\n        file: `${title}-640x853.jpeg`,\n        width: 640,\n        height: 853,\n        mimeType,\n        sourceUrl: src,\n      },\n      'web-stories-publisher-logo': {\n        file: `${title}-96x96.jpeg`,\n        width: 96,\n        height: 96,\n        mimeType,\n        sourceUrl: src,\n      },\n      'web-stories-thumbnail': {\n        file: `${title}-150x42.jpeg`,\n        width: 150,\n        height: 42,\n        mimeType,\n        sourceUrl: src,\n      },\n      full: {\n        file: title,\n        width,\n        height,\n        mimeType,\n        sourceUrl: src,\n      },\n    },\n  });\n}\n\nfunction createDummyVideoData({\n  mimeType = 'video/mp4',\n  src,\n  mediaDetails,\n  id,\n  title,\n  poster,\n}) {\n  return createResource({\n    mimeType,\n    creationDate: '2021-10-29T11:56:33',\n    src,\n    width: mediaDetails.width,\n    height: mediaDetails.height,\n    poster: poster.src,\n    posterId: 57,\n    id,\n    length: mediaDetails.length,\n    bitsPerSample: mediaDetails.bitsPerSample,\n    alt: title,\n  });\n}\n\nfunction getDummyMedia() {\n  return [\n    createDummyImageData({\n      mimeType: 'image/png',\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page1_bg-alt.png',\n      width: 412,\n      height: 732,\n      id: 1,\n      title: 'Fresh and Bright 1',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page3_figure.jpg',\n      width: 720,\n      height: 844,\n      id: 2,\n      title: 'Fresh and Bright 2',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page4_bg.png',\n      width: 750,\n      height: 1334,\n      id: 3,\n      title: 'Fresh and Bright 3',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page5_figure.jpg',\n      width: 750,\n      height: 1079,\n      id: 4,\n      title: 'Fresh and Bright 4',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page7_product1.jpg',\n      width: 720,\n      height: 900,\n      id: 5,\n      title: 'Fresh and Bright 5',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page8_figure.jpg',\n      width: 408,\n      height: 544,\n      id: 6,\n      title: 'Fresh and Bright 6',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story1.jpg',\n      width: 720,\n      height: 405,\n      id: 7,\n      title: 'Fresh and Bright 7',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story2.jpg',\n      width: 480,\n      height: 720,\n      id: 8,\n      title: 'Fresh and Bright 8',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page9_story3.jpg',\n      width: 480,\n      height: 720,\n      id: 9,\n      title: 'Fresh and Bright 9',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page1_bg.jpg',\n      width: 1080,\n      height: 1620,\n      id: 10,\n      title: 'Fresh and Bright 10',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page3_image1.jpg',\n      width: 1080,\n      height: 720,\n      id: 11,\n      title: 'Food and Stuff 1',\n    }),\n    createDummyImageData({\n      src: 'https://wp.stories.google/static/main/images/templates/food-and-stuff/page5_bg.jpg',\n      width: 731,\n      height: 1300,\n      id: 12,\n      title: 'Food and Stuff 2',\n    }),\n    createDummyVideoData({\n      src: 'https://stream.mux.com/OGTmBYTMkV7Ez601cRNpH6BP10102fQu9C00/high.mp4?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InQ5UHZucm9ZY0hQNjhYSmlRQnRHTEVVSkVSSXJ0UXhKIn0.eyJleHAiOjE2MjYxNzgxMTIsImF1ZCI6InYiLCJzdWIiOiJPR1RtQllUTWtWN0V6NjAxY1JOcEg2QlAxMDEwMmZRdTlDMDAifQ.Jvddeah-XyF0AMmfYND-fFaIfgeDYW_cAuIVIXOrk2so_YalyMMAQ11YXHA1h11yKpLM-xa8xiNXazPqA0Suq1tfxHjJjEqiQOzSlPYd4visiPdTjUgT50FkwYdJrN0IldfXoS19yi3GyAd9McVFoSGCZ6qp8m_hgJ39y8FJJbOrvGtrzEvElpz1M8M1Dat3PF-BSLvFcTvCOlec9dipajxHG_2Xg-EE_vOqww6z81kC09evj5gu_A-Vz58Q-ebd08R47ybNejhE3rzMr1dCKgUikjkkQokPPQyrwVEy8zeZ68elax-ZRvDokZ2mTVPGvKIye6m_CQ-WVlG5XRjw7A',\n      mediaDetails: {\n        filesize: 1867215,\n        mimeType: 'video/mp4',\n        length: 12,\n        lengthFormatted: '0:12',\n        width: 720,\n        height: 406,\n        fileformat: 'mp4',\n        dataformat: 'quicktime',\n        audio: {\n          dataformat: 'mp4',\n          codec: 'ISO/IEC 14496-3 AAC',\n          sampleRate: 48000,\n          channels: 2,\n          bitsPerSample: 16,\n          lossless: false,\n          channelmode: 'stereo',\n        },\n        createdTimestamp: -2082844800,\n        sizes: {},\n      },\n      id: 13,\n      title: 'Story',\n      poster: {\n        src: 'https://image.mux.com/OGTmBYTMkV7Ez601cRNpH6BP10102fQu9C00/thumbnail.jpg?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InQ5UHZucm9ZY0hQNjhYSmlRQnRHTEVVSkVSSXJ0UXhKIn0.eyJ0aW1lIjowLCJleHAiOjMxNzE3MDYwNjg4MSwiYXVkIjoidCIsInN1YiI6Ik9HVG1CWVRNa1Y3RXo2MDFjUk5wSDZCUDEwMTAyZlF1OUMwMCJ9.WxHU2cpFdNqqiWF08KEv1g7barfbE_Nw4JDvVrtrQc9mVKiSZ6pEHpYl14NZeaBOf4Ep9MiomaegCVrD-UANhURlxWuHWFx5h7Msg74-q_ojjuZbLZtFPUdA0NA3_GTq5y0LDAeXijM7oENn_IkuDSY0fbRhRUVh-hYqCzw_OqMx7B1IxoOkkZUCHgkm9VnPdAMQRpmaanCHB8SHVRI_vIJo577DxLd88KBFP3UWK1XTvN5NYr0oPtwc82XMYUW4HrxZZTmxzLSZckxzwB7T5E6zAtXpo-xwd52yB1OUhoihlTqiOPWbntpvt9H4lFVRISLwsT39d1Tw80HF_X02eQ',\n        width: 1920,\n        height: 1080,\n        generated: false,\n      },\n    }),\n    createDummyVideoData({\n      src: 'https://storage.coverr.co/videos/PDolZIrwdONTFJd005VOT4qvFsyxVfB01N/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM0NDQzfQ._6LJb2Ad843im0xV4-2I2vVpDNoPiy8nPc3-3IkSSuw',\n      mediaDetails: {\n        filesize: 1510877,\n        mimeType: 'video/quicktime',\n        length: 18,\n        lengthFormatted: '0:18',\n        width: 640,\n        height: 360,\n        fileformat: 'mp4',\n        dataformat: 'quicktime',\n        createdTimestamp: -2082844800,\n        sizes: {},\n      },\n      id: 14,\n      title: 'Low',\n      poster: {\n        src: 'https://storage.coverr.co/p/PDolZIrwdONTFJd005VOT4qvFsyxVfB01N',\n        width: 2048,\n        height: 1152,\n        generated: false,\n      },\n    }),\n    createDummyVideoData({\n      src: 'https://storage.coverr.co/videos/qMc3OVOA8a6Q9j01T2L3pGfF029UA00OvZJ/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM3NDkwfQ.rHiHdTyik8sDuP8viRbC4ph-qjHHJ81I7kdawP2-1eQ',\n      mediaDetails: {\n        filesize: 456538,\n        mimeType: 'video/mp4',\n        length: 15,\n        lengthFormatted: '0:15',\n        width: 360,\n        height: 640,\n        fileformat: 'mp4',\n        dataformat: 'quicktime',\n        createdTimestamp: -2082844800,\n        sizes: {},\n        audio: {\n          bitsPerSample: 16,\n          channelmode: 'stereo',\n          channels: 2,\n          codec: 'ISO/IEC 14496-3 AAC',\n          dataformat: 'mp4',\n          lossless: false,\n          sampleRate: 48000,\n        },\n      },\n      id: 15,\n      title: 'Mountain Video',\n      poster: {\n        src: 'https://storage.coverr.co/p/qMc3OVOA8a6Q9j01T2L3pGfF029UA00OvZJ',\n        width: 1080,\n        height: 1920,\n        generated: false,\n      },\n    }),\n    createDummyVideoData({\n      src: 'https://storage.coverr.co/videos/XHtOLYGTnHiXVxofSdO8oTcA02vxasheL/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM3NDkwfQ.rHiHdTyik8sDuP8viRbC4ph-qjHHJ81I7kdawP2-1eQ',\n      mediaDetails: {\n        filesize: 2536304,\n        mimeType: 'video/mp4',\n        length: 27,\n        lengthFormatted: '0:27',\n        width: 640,\n        height: 360,\n        fileformat: 'mp4',\n        dataformat: 'quicktime',\n        createdTimestamp: -2082844800,\n        sizes: {},\n        audio: {\n          bitsPerSample: 16,\n          channelmode: 'stereo',\n          channels: 2,\n          codec: 'ISO/IEC 14496-3 AAC',\n          dataformat: 'mp4',\n          lossless: false,\n          sampleRate: 48000,\n        },\n      },\n      id: 16,\n      title: 'Beautiful Cloud Video',\n      poster: {\n        src: 'https://storage.coverr.co/p/XHtOLYGTnHiXVxofSdO8oTcA02vxasheL',\n        width: 1920,\n        height: 1080,\n        generated: false,\n      },\n    }),\n    createDummyVideoData({\n      src: 'https://storage.coverr.co/videos/X4pOA7IG76p95Gl3IcU3oX26S2sbGsc2/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjI2ODM4Mjc3fQ.lIznWsYEFy3abrDbou1mKJivj6GzQnHO6gJ8jdisPW0',\n      mediaDetails: {\n        filesize: 1029136,\n        mimeType: 'video/mp4',\n        length: 10,\n        lengthFormatted: '0:10',\n        width: 640,\n        height: 360,\n        fileformat: 'mp4',\n        dataformat: 'quicktime',\n        createdTimestamp: -2082844800,\n        sizes: {},\n        audio: {\n          bitsPerSample: 16,\n          channelmode: 'stereo',\n          channels: 2,\n          codec: 'ISO/IEC 14496-3 AAC',\n          dataformat: 'mp4',\n          lossless: false,\n          sampleRate: 48000,\n        },\n      },\n      id: 17,\n      title: 'Beautiful Fire Video',\n      poster: {\n        src: 'https://storage.coverr.co/p/X4pOA7IG76p95Gl3IcU3oX26S2sbGsc2',\n        width: 1920,\n        height: 1080,\n        generated: false,\n      },\n    }),\n  ];\n}\n\nexport { getDummyMedia };\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/header/buttons/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useStory } from '@googleforcreators/story-editor';\nimport { CircularProgress } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SaveButton } from './saveButton';\nimport { PreviewButton } from './preview';\n\nconst ButtonList = styled.nav`\n  display: flex;\n  justify-content: flex-end;\n  padding: 1em;\n  height: 100%;\n`;\n\nconst List = styled.div`\n  display: flex;\n  align-items: center;\n`;\n\nconst Space = styled.div`\n  width: 8px;\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  top: 0;\n`;\n\nconst IconWithSpinner = styled.div`\n  position: relative;\n`;\n\nfunction Loading() {\n  return (\n    <Spinner>\n      <CircularProgress size={32} />\n    </Spinner>\n  );\n}\n\nfunction Buttons() {\n  const { isSaving } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n    }) => ({ isSaving })\n  );\n\n  return (\n    <ButtonList>\n      <List>\n        <IconWithSpinner>\n          <PreviewButton />\n          {isSaving && <Loading />}\n        </IconWithSpinner>\n        <Space />\n        <SaveButton />\n      </List>\n    </ButtonList>\n  );\n}\n\nexport { Buttons };\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/header/buttons/preview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { hrefTo } from '@storybook/addon-links';\nimport { Tooltip, useStory } from '@googleforcreators/story-editor';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\n\nfunction PreviewButton() {\n  const { isSaving, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n      actions: { saveStory },\n    }) => ({\n      isSaving,\n      saveStory,\n    })\n  );\n\n  const openPreviewLink = async () => {\n    await saveStory();\n\n    const previewLink = await hrefTo('Playground/preview', 'default');\n\n    // Start a about:blank popup with waiting message until we complete\n    // the saving operation. That way we will not bust the popup timeout.\n    try {\n      const popup = window.open('about:blank', 'story-preview');\n\n      if (popup) {\n        popup.document.write('<!DOCTYPE html><html><head>');\n        popup.document.write('<title>');\n        popup.document.write('Generating the preview…');\n        popup.document.write('</title>');\n        popup.document.write('</head><body>');\n        popup.document.write('Please wait. Generating the preview…'); // Output \"waiting\" message.\n\n        // Force redirect to the preview URL after 5 seconds. The saving tab\n        // might get frozen by the browser.\n        popup.document.write(\n          `<script>\n            setTimeout(function() {\n              location.replace(${JSON.stringify(previewLink)});\n            }, 5000);\n          </script>`\n        );\n      }\n    } catch {\n      // Not interested in the error.\n    }\n  };\n\n  return (\n    <Tooltip title={'Preview'} hasTail>\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        onClick={openPreviewLink}\n        disabled={isSaving}\n      >\n        <Icons.Eye />\n      </Button>\n    </Tooltip>\n  );\n}\n\nexport { PreviewButton };\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/header/buttons/saveButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport { useStory } from '@googleforcreators/story-editor';\n\nfunction SaveButton() {\n  const { isSaving, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n      actions: { saveStory },\n    }) => ({\n      isSaving,\n      saveStory,\n    })\n  );\n\n  const { showSnackbar } = useSnackbar();\n\n  const handleSaveButton = () => {\n    saveStory().then(() => {\n      showSnackbar({\n        message: 'Story Saved',\n      });\n    });\n  };\n\n  // @todo Make the app state persistent.\n  return (\n    <Button\n      variant={ButtonVariant.Rectangle}\n      type={ButtonType.Primary}\n      size={ButtonSize.Small}\n      onClick={handleSaveButton}\n      disabled={isSaving}\n    >\n      {'Save'}\n    </Button>\n  );\n}\n\nexport { SaveButton };\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { HeaderTitle } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport { Buttons } from './buttons';\n\nconst Background = styled.header.attrs({\n  role: 'group',\n  'aria-label': 'Story canvas header',\n})`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Head = styled.div`\n  flex: 1 1 auto;\n  padding: 1em;\n`;\n\nconst ButtonCell = styled.div`\n  grid-area: buttons;\n`;\n\nfunction HeaderLayout() {\n  return (\n    <Background>\n      <Head>\n        <HeaderTitle />\n      </Head>\n      <ButtonCell>\n        <Buttons />\n      </ButtonCell>\n    </Background>\n  );\n}\n\nexport { HeaderLayout };\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from '@googleforcreators/story-editor';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { getMedia, saveStoryById, getFonts } from './api';\nimport { HeaderLayout } from './header';\nimport { LOCAL_STORAGE_CONTENT_KEY } from './constants';\n\nexport default {\n  title: 'Playground/Stories Editor',\n};\n\nexport const _default = {\n  render: function Render() {\n    const content = window.localStorage.getItem(LOCAL_STORAGE_CONTENT_KEY);\n    const story = content ? JSON.parse(content) : {};\n    const apiCallbacks = { saveStoryById, getMedia, getFonts };\n\n    elementTypes.forEach(registerElementType);\n\n    return (\n      <div style={{ height: '100vh' }}>\n        <StoryEditor config={{ apiCallbacks }} initialEdits={{ story }}>\n          <InterfaceSkeleton header={<HeaderLayout />} />\n        </StoryEditor>\n      </div>\n    );\n  },\n};\n"
  },
  {
    "path": ".storybook/stories/playground/story-editor/preview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { LOCAL_STORAGE_PREVIEW_MARKUP_KEY } from './constants';\n\nexport default {\n  title: 'Playground/preview',\n};\n\n// This is a hidden story component ( hidden via manager-head.html ), used for previewing the story-editor. Please do not remove.\nfunction Preview() {\n  useEffect(() => {\n    const content = window.localStorage.getItem(\n      LOCAL_STORAGE_PREVIEW_MARKUP_KEY\n    );\n\n    if (content) {\n      document.open();\n      document.write(content);\n      document.close();\n    }\n  }, []);\n\n  return null;\n}\n\nexport const _default = Preview;\n"
  },
  {
    "path": ".stylelintignore",
    "content": ".github\n.storybook\n.wordpress-org\n__mocks__\n__static__\nassets\nbin\nblocks\nbuild\ndocs\nincludes\nnode_modules\npatches\npublic\ntests\nthird-party\nvendor\n/*.js\n/*.cjs\n"
  },
  {
    "path": ".stylelintrc",
    "content": "{\n  \"extends\": [\n    \"stylelint-config-recommended\"\n  ],\n  \"plugins\": [\"stylelint-prettier\"],\n  \"customSyntax\": \"postcss-syntax\",\n  \"rules\": {\n    \"font-family-name-quotes\": null,\n    \"font-family-no-missing-generic-family-keyword\": null,\n    \"font-weight-notation\": null,\n    \"function-name-case\": null,\n    \"prettier/prettier\": true,\n    \"selector-class-pattern\": null,\n    \"selector-type-no-unknown\": [\n      true,\n      {\n        \"ignore\": [\"custom-elements\"],\n        \"ignoreTypes\": [\"overlay\", \"container\"]\n      }\n    ],\n    \"property-no-vendor-prefix\": [\n      true,\n      {\n        \"ignoreProperties\": [\"clip-path\"]\n      }\n    ],\n    \"unit-no-unknown\": [\n      true,\n      {\n        \"ignoreUnits\": [\"/^`/\", \"/`$/\"]\n      }\n    ],\n    \"value-keyword-case\": null\n  },\n  \"overrides\": [\n    {\n      \"files\": [\"*.js\", \".ts\", \".tsx\"],\n      \"customSyntax\": \"postcss-styled-syntax\",\n      \"rules\": {\n        \"annotation-no-unknown\": null,\n        \"block-no-empty\": null,\n        \"function-no-unknown\": null,\n        \"media-query-no-invalid\": null,\n        \"no-empty-source\": null\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".wordpress-org/README.md",
    "content": "# WordPress.org assets\n\nThese assets are used in the WordPress.org plugin directory. They will need to be synced with the plugin SVN repository whenever they change.\n"
  },
  {
    "path": ".wordpress-org/blueprints/blueprint.json",
    "content": "{\n  \"$schema\": \"https://playground.wordpress.net/blueprint-schema.json\",\n  \"landingPage\": \"/wp-admin/plugins.php\",\n  \"preferredVersions\": {\n    \"php\": \"8.0\",\n    \"wp\": \"latest\"\n  },\n  \"phpExtensionBundles\": [\"kitchen-sink\"],\n  \"features\": {\n    \"networking\": true\n  },\n  \"steps\": [\n    {\n      \"step\": \"installPlugin\",\n      \"pluginZipFile\": {\n        \"resource\": \"url\",\n        \"url\": \"https://downloads.wordpress.org/plugin/web-stories.latest-stable.zip\"\n      },\n      \"options\": {\n        \"activate\": true\n      }\n    },\n    {\n      \"step\": \"login\",\n      \"username\": \"admin\",\n      \"password\": \"password\"\n    }\n  ]\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Contribute\n\nWe'd love to accept your patches and contributions to this project. There are\njust a few small guidelines you need to follow.\n\n## Getting Started\n\nPlease check out our dedicated [Getting Started](./docs/getting-started.md) guide.\n\n## Contributor License Agreement\n\nContributions to this project must be accompanied by a Contributor License\nAgreement. You (or your employer) retain the copyright to your contribution;\nthis simply gives us permission to use and redistribute your contributions as\npart of the project. Head over to <https://cla.developers.google.com/> to see\nyour current agreements on file or to sign a new one.\n\nYou generally only need to submit a CLA once, so if you've already submitted one\n(even if it was for a different project), you probably don't need to do it\nagain.\n\n## Code reviews\n\nAll submissions, including submissions by project members, require review. We\nuse GitHub pull requests for this purpose. Consult\n[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more\ninformation on using pull requests.\n\n## Community Guidelines\n\nThis project follows [Google's Open Source Community\nGuidelines](https://opensource.google/conduct/).\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": "# Web Stories for WordPress\n\nVisual storytelling for WordPress.\n\n[![Latest Release)](https://img.shields.io/github/v/release/googleforcreators/web-stories-wp?include_prereleases)](https://github.com/googleforcreators/web-stories-wp/releases)\n[![Commit activity](https://img.shields.io/github/commit-activity/m/googleforcreators/web-stories-wp)](https://github.com/googleforcreators/web-stories-wp/pulse/monthly)\n[![Code Coverage](https://codecov.io/gh/googleforcreators/web-stories-wp/branch/main/graph/badge.svg)](https://codecov.io/gh/googleforcreators/web-stories-wp)\n[![License](https://img.shields.io/github/license/googleforcreators/web-stories-wp)](https://github.com/googleforcreators/web-stories-wp/blob/main/LICENSE)\n[![Storybook](https://raw.githubusercontent.com/storybooks/brand/master/badge/badge-storybook.svg)](https://googleforcreators.github.io/web-stories-wp/storybook/)\n\n<details>\n<summary>\nBuild Status\n</summary>\n\n[![Build](https://img.shields.io/github/actions/workflow/status/googleforcreators/web-stories-wp/build-and-deploy.yml?branch=main&label=Build)](https://github.com/googleforcreators/web-stories-wp/actions?query=branch%3Amain)\n[![Integration Tests](https://img.shields.io/github/actions/workflow/status/googleforcreators/web-stories-wp/tests-karma-editor.yml?branch=main&label=integration%20tests)](https://github.com/googleforcreators/web-stories-wp/actions?query=branch%3Amain)\n[![E2E Tests](https://img.shields.io/github/actions/workflow/status/googleforcreators/web-stories-wp/tests-e2e.yml?branch=main&label=e2e%20tests)](https://github.com/googleforcreators/web-stories-wp/actions?query=branch%3Amain)\n[![JS Tests](https://img.shields.io/github/actions/workflow/status/googleforcreators/web-stories-wp/tests-unit-js.yml?branch=main&label=js%20tests)](https://github.com/googleforcreators/web-stories-wp/actions?query=branch%3Amain)\n[![PHP Tests](https://img.shields.io/github/actions/workflow/status/googleforcreators/web-stories-wp/tests-unit-php.yml?branch=main&label=php%20tests)](https://github.com/googleforcreators/web-stories-wp/actions?query=branch%3Amain)\n\n</details>\n\n[Web Stories](https://amp.dev/about/stories/) are a free, open-web, visual storytelling format for the web, enabling you to easily create visual narratives with engaging animations and tappable interactions, and immerse your readers in great and fast-loading full-screen experiences.\n\nWith [Web Stories for WordPress](https://wp.stories.google/), we're bringing first-class Web Stories support to WordPress. Use Web Stories for WordPress by installing it directly from the WordPress admin dashboard or manually downloading the plugin from the [WordPress.org plugin directory](https://wordpress.org/plugins/web-stories/).\n\n## Support\n\nIf you find any issues, please reach out by visiting the [support forum](https://wordpress.org/support/plugin/web-stories/) to ask any questions or file feature requests.\n\n## Contributing\n\nWe'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. Please check out our [Contributing documentation](./CONTRIBUTING.md) and the [Getting Started](./docs/getting-started.md) guide.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nWe support the latest stable version of the plugin with security updates.\n\n## Reporting a Vulnerability\n\nTo report a vulnerability in this repository, please contact the Google Security Team at [g.co/vulnz](https://g.co/vulnz).\n"
  },
  {
    "path": "__mocks__/colorthief.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default function () {}\n"
  },
  {
    "path": "__mocks__/node:fs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// see https://jestjs.io/docs/en/manual-mockshttps://jestjs.io/docs/en/manual-mocks\n\n/**\n * External dependencies\n */\n//eslint-disable-next-line no-undef -- TODO: Figure out why this is needed.\nconst path = require('path');\n\nconst fs = jest.createMockFromModule('fs');\n\n/* eslint-disable security/detect-object-injection -- TODO: Figure out why this is needed. */\n\n// This is a custom function that our tests can use during setup to specify\n// what the files on the \"mock\" filesystem should look like when any of the\n// `fs` APIs are used.\nlet mockFiles = Object.create(null);\nfunction __setMockFiles(newMockFiles) {\n  mockFiles = Object.create(null);\n\n  for (const [file, content] of Object.entries(newMockFiles)) {\n    const dir = path.dirname(file);\n    const basename = path.basename(file);\n\n    if (!mockFiles[dir]) {\n      mockFiles[dir] = [];\n    }\n\n    mockFiles[dir][basename] = content;\n  }\n}\n\nfunction readdirSync(directoryPath) {\n  return mockFiles[directoryPath] ? Object.keys(mockFiles[directoryPath]) : [];\n}\n\nfunction existsSync(dirOrFile) {\n  const dirExists = Object.prototype.hasOwnProperty.call(mockFiles, dirOrFile);\n\n  const dirname = path.dirname(dirOrFile);\n  const fileExists =\n    Object.prototype.hasOwnProperty.call(mockFiles, dirname) &&\n    Object.prototype.hasOwnProperty.call(\n      mockFiles[dirname],\n      path.basename(dirOrFile)\n    );\n\n  return dirExists || fileExists;\n}\n\nfunction readFileSync(file) {\n  const dir = path.dirname(file);\n  return mockFiles[dir][path.basename(file)];\n}\n\nfunction writeFileSync(file, content) {\n  const dir = path.dirname(file);\n  if (!mockFiles[dir]) {\n    mockFiles[dir] = [];\n  }\n\n  mockFiles[dir][path.basename(file)] = content;\n}\n\nfunction lstatSync(dirOrFile) {\n  return {\n    isDirectory: () =>\n      Object.prototype.hasOwnProperty.call(mockFiles, dirOrFile),\n  };\n}\n\nfunction rmdirSync(dirname) {\n  if (Object.prototype.hasOwnProperty.call(mockFiles, dirname)) {\n    delete mockFiles[dirname];\n  }\n}\n\nfunction unlinkSync(file) {\n  const dir = path.dirname(file);\n  delete mockFiles[dir][path.basename(file)];\n}\n\nfs.__setMockFiles = __setMockFiles;\nfs.readdirSync = readdirSync;\nfs.readFileSync = readFileSync;\nfs.writeFileSync = writeFileSync;\nfs.existsSync = existsSync;\nfs.lstatSync = lstatSync;\nfs.rmdirSync = rmdirSync;\nfs.unlinkSync = unlinkSync;\n\n// eslint-disable-next-line no-undef -- TODO: Figure out why this is needed.\nmodule.exports = fs;\n\n/* eslint-enable security/detect-object-injection */\n"
  },
  {
    "path": "__mocks__/react-moveable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from 'react';\n\n// eslint-disable-next-line no-unused-vars\nexport const MockMoveable = jest.fn((props, ref) => <div />);\n\nexport default forwardRef(MockMoveable);\n"
  },
  {
    "path": "__static__/README.md",
    "content": "# Static files\n\nThese are static files that can be used for testing.\n"
  },
  {
    "path": "babel.config.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nmodule.exports = function (api) {\n  const isTest = api.env('test');\n  const isProduction = api.env('production');\n\n  const targets = isTest\n    ? {\n        node: 'current',\n      }\n    : undefined;\n\n  return {\n    presets: [\n      [\n        '@babel/preset-env',\n        {\n          shippedProposals: true,\n          targets,\n          useBuiltIns: 'usage',\n          corejs: require('core-js/package.json').version,\n          // Remove some unnecessary polyfills, similar to how Gutenberg is handling that.\n          // See https://github.com/WordPress/gutenberg/blob/e95970d888c309274e24324d593c77c536c9f1d8/packages/babel-preset-default/polyfill-exclusions.js.\n          exclude: [\n            'es.array.push',\n            /^es(next)?\\.set\\./,\n            /^es(next)?\\.iterator\\./,\n          ],\n        },\n      ],\n      [\n        '@babel/preset-react',\n        {\n          // Not fully released yet, see https://github.com/facebook/react/pull/18299#issuecomment-603738136.\n          //runtime: 'automatic',\n          development: !isProduction,\n        },\n      ],\n      '@babel/preset-typescript',\n    ],\n    plugins: [\n      ['babel-plugin-react-compiler', { target: '17' }],\n      '@wordpress/babel-plugin-import-jsx-pragma',\n      [\n        'babel-plugin-styled-components',\n        {\n          meaninglessFileNames: ['index', 'styles', 'components'],\n        },\n      ],\n    ],\n    sourceMaps: true,\n    env: {\n      production: {\n        plugins: ['transform-react-remove-prop-types'],\n      },\n    },\n  };\n};\n"
  },
  {
    "path": "bin/deploy-to-test-environment.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n#\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Custom deployment script for Pantheon environment.\n# Adapted from original version at https://github.com/ampproject/amp-wp/pull/1042.\n\necho \"Initializing deployment to Web Stories test environment\"\n\nPANTHEON_SITE=\"wordpress-amp\"\nPANTHEON_BRANCH=\"stories-new\"\nPANTHEON_UUID=\"6b7f1eeb-705b-4201-864d-2007030c8372\"\n\ncd \"$(dirname \"$0\")/..\"\nproject_dir=\"$(pwd)\"\nrepo_dir=\"$HOME/deployment-targets/$PANTHEON_SITE\"\n\necho \"Setting up SSH configuration\"\n\n# Dynamic hosts through Pantheon mean constantly checking interactively\n# that we mean to connect to an unknown host. We ignore those here.\necho \"StrictHostKeyChecking no\" > ~/.ssh/config\n\nif ! grep -q \"codeserver.dev.$PANTHEON_UUID.drush.in\" ~/.ssh/known_hosts; then\n    ssh-keyscan -p 2222 codeserver.dev.$PANTHEON_UUID.drush.in >> ~/.ssh/known_hosts\nfi\n\nif ! grep -q \"codeserver.dev.$PANTHEON_UUID.drush.in\" ~/.ssh/config; then\n    echo \"\" >> ~/.ssh/config\n    echo \"Host $PANTHEON_SITE\" >> ~/.ssh/config\n    echo \"  Hostname codeserver.dev.$PANTHEON_UUID.drush.in\" >> ~/.ssh/config\n    echo \"  User codeserver.dev.$PANTHEON_UUID\" >> ~/.ssh/config\n    echo \"  Port 2222\" >> ~/.ssh/config\n    echo \"  KbdInteractiveAuthentication no\" >> ~/.ssh/config\nfi\n\necho \"Fetching remote repository\"\n\ngit config --global user.name \"Google for Creators Bot\"\ngit config --global user.email \"94923726+googleforcreators-bot@users.noreply.github.com\"\n\nif [ ! -e \"$repo_dir/.git\" ]; then\n    git clone -v ssh://codeserver.dev.$PANTHEON_UUID@codeserver.dev.$PANTHEON_UUID.drush.in:2222/~/repository.git \"$repo_dir\"\nfi\n\ncd \"$repo_dir\"\ngit fetch\n\nif git rev-parse --verify --quiet \"$PANTHEON_BRANCH\" > /dev/null; then\n    git checkout \"$PANTHEON_BRANCH\"\nelse\n    git checkout -b \"$PANTHEON_BRANCH\"\nfi\n\nif git rev-parse --verify --quiet \"origin/$PANTHEON_BRANCH\" > /dev/null; then\n    git reset --hard \"origin/$PANTHEON_BRANCH\"\nfi\n\ncd \"$project_dir\"\n\necho \"Moving files to repository\"\nrsync -avz --delete ./build/web-stories/ \"$repo_dir/wp-content/plugins/web-stories/\"\ngit --no-pager log -1 --format=\"Build Web Stories plugin at %h: %s\" > /tmp/commit-message.txt\n\necho \"Committing changes\"\n\n# Commit and deploy.\ncd \"$repo_dir\"\ngit add -A \"wp-content/plugins/web-stories/\"\ngit commit -F /tmp/commit-message.txt\n\necho \"Pushing new build to remote repository\"\ngit push origin $PANTHEON_BRANCH\n\necho \"View site at http://$PANTHEON_BRANCH-$PANTHEON_SITE.pantheonsite.io/\"\necho \"Access Pantheon dashboard at https://dashboard.pantheon.io/sites/$PANTHEON_UUID#$PANTHEON_BRANCH\"\n"
  },
  {
    "path": "bin/install-wp-tests.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# See https://raw.githubusercontent.com/wp-cli/scaffold-command/master/templates/install-wp-tests.sh\n\nif [ $# -lt 3 ]; then\n\techo \"usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]\"\n\texit 1\nfi\n\nDB_NAME=$1\nDB_USER=$2\nDB_PASS=$3\nDB_HOST=${4-localhost}\nWP_VERSION=${5-latest}\nSKIP_DB_CREATE=${6-false}\n\nTMPDIR=${TMPDIR-/tmp}\nTMPDIR=$(echo $TMPDIR | sed -e \"s/\\/$//\")\nWP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib}\nWP_TESTS_FILE=\"$WP_TESTS_DIR\"/includes/functions.php\nWP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress/}\nWP_CORE_FILE=\"$WP_CORE_DIR\"/wp-settings.php\n\ndownload() {\n    if [ `which curl` ]; then\n        #curl -s \"$1\" > \"$2\";\n        # WordPress.org seems to block requests without proper user agent.\n        curl -H \"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (K HTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36\" -s \"$1\" > \"$2\";\n    elif [ `which wget` ]; then\n        wget -nv -O \"$2\" \"$1\"\n    fi\n}\n\nif [[ $WP_VERSION =~ ^[0-9]+\\.[0-9]+\\-(beta|RC)[0-9]+$ ]]; then\n\tWP_BRANCH=${WP_VERSION%\\-*}\n\tWP_TESTS_TAG=\"branches/$WP_BRANCH\"\n\nelif [[ $WP_VERSION =~ ^[0-9]+\\.[0-9]+$ ]]; then\n\tWP_TESTS_TAG=\"branches/$WP_VERSION\"\nelif [[ $WP_VERSION =~ [0-9]+\\.[0-9]+\\.[0-9]+ ]]; then\n\tif [[ $WP_VERSION =~ [0-9]+\\.[0-9]+\\.[0] ]]; then\n\t\t# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x\n\t\tWP_TESTS_TAG=\"tags/${WP_VERSION%??}\"\n\telse\n\t\tWP_TESTS_TAG=\"tags/$WP_VERSION\"\n\tfi\nelif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then\n\tWP_TESTS_TAG=\"trunk\"\nelse\n\t# http serves a single offer, whereas https serves multiple. we only want one\n\tdownload http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json\n\tgrep '[0-9]+\\.[0-9]+(\\.[0-9]+)?' /tmp/wp-latest.json\n\tLATEST_VERSION=$(grep -o '\"version\":\"[^\"]*' /tmp/wp-latest.json | sed 's/\"version\":\"//')\n\tif [[ -z \"$LATEST_VERSION\" ]]; then\n\t\techo \"Latest WordPress version could not be found\"\n\t\texit 1\n\tfi\n\tWP_TESTS_TAG=\"tags/$LATEST_VERSION\"\nfi\nset -ex\n\ninstall_wp() {\n\n\tif [ -f $WP_CORE_FILE ]; then\n\t\treturn;\n\tfi\n\n\trm -rf $WP_CORE_DIR\n\tmkdir -p $WP_CORE_DIR\n\n\tif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then\n\t\tmkdir -p $TMPDIR/wordpress-trunk\n\t\tsvn export --quiet https://core.svn.wordpress.org/trunk $TMPDIR/wordpress-trunk/wordpress\n\t\tmv $TMPDIR/wordpress-trunk/wordpress/* $WP_CORE_DIR\n\telse\n\t\tif [ $WP_VERSION == 'latest' ]; then\n\t\t\tlocal ARCHIVE_NAME='latest'\n\t\telif [[ $WP_VERSION =~ [0-9]+\\.[0-9]+ ]]; then\n\t\t\t# https serves multiple offers, whereas http serves single.\n\t\t\tdownload https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json\n\t\t\tif [[ $WP_VERSION =~ [0-9]+\\.[0-9]+\\.[0] ]]; then\n\t\t\t\t# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x\n\t\t\t\tLATEST_VERSION=${WP_VERSION%??}\n\t\t\telse\n\t\t\t\t# otherwise, scan the releases and get the most up to date minor version of the major release\n\t\t\t\tlocal VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\\./\\\\\\\\./g'`\n\t\t\t\tLATEST_VERSION=$(grep -o '\"version\":\"'$VERSION_ESCAPED'[^\"]*' $TMPDIR/wp-latest.json | sed 's/\"version\":\"//' | head -1)\n\t\t\tfi\n\t\t\tif [[ -z \"$LATEST_VERSION\" ]]; then\n\t\t\t\tlocal ARCHIVE_NAME=\"wordpress-$WP_VERSION\"\n\t\t\telse\n\t\t\t\tlocal ARCHIVE_NAME=\"wordpress-$LATEST_VERSION\"\n\t\t\tfi\n\t\telse\n\t\t\tlocal ARCHIVE_NAME=\"wordpress-$WP_VERSION\"\n\t\tfi\n\t\tdownload https://wordpress.org/${ARCHIVE_NAME}.tar.gz  $TMPDIR/wordpress.tar.gz\n\t\ttar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR\n\tfi\n\n\tdownload https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php\n}\n\ninstall_test_suite() {\n\t# portable in-place argument for both GNU sed and Mac OSX sed\n\tif [[ $(uname -s) == 'Darwin' ]]; then\n\t\tlocal ioption='-i.bak'\n\telse\n\t\tlocal ioption='-i'\n\tfi\n\n\t# set up testing suite if it doesn't yet exist or only partially exists\n\tif [ ! -f $WP_TESTS_FILE ]; then\n\t\t# set up testing suite\n\t\trm -rf $WP_TESTS_DIR\n\t\tmkdir -p $WP_TESTS_DIR\n\t\tsvn export --quiet --ignore-externals https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes\n\t\tsvn export --quiet --ignore-externals https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data\n\tfi\n\n\tif [ ! -f wp-tests-config.php ]; then\n\t\tdownload https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php \"$WP_TESTS_DIR\"/wp-tests-config.php\n\t\t# remove all forward slashes in the end\n\t\tWP_CORE_DIR=$(echo $WP_CORE_DIR | sed \"s:/\\+$::\")\n\t\tsed $ioption \"s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':\" \"$WP_TESTS_DIR\"/wp-tests-config.php\n\t\tsed $ioption \"s/youremptytestdbnamehere/$DB_NAME/\" \"$WP_TESTS_DIR\"/wp-tests-config.php\n\t\tsed $ioption \"s/yourusernamehere/$DB_USER/\" \"$WP_TESTS_DIR\"/wp-tests-config.php\n\t\tsed $ioption \"s/yourpasswordhere/$DB_PASS/\" \"$WP_TESTS_DIR\"/wp-tests-config.php\n\t\tsed $ioption \"s|localhost|${DB_HOST}|\" \"$WP_TESTS_DIR\"/wp-tests-config.php\n\tfi\n\n}\n\ninstall_db() {\n\n\tif [ ${SKIP_DB_CREATE} = \"true\" ]; then\n\t\treturn 0\n\tfi\n\n\t# parse DB_HOST for port or socket references\n\tlocal PARTS=(${DB_HOST//\\:/ })\n\tlocal DB_HOSTNAME=${PARTS[0]};\n\tlocal DB_SOCK_OR_PORT=${PARTS[1]};\n\tlocal EXTRA=\"\"\n\n\tif ! [ -z $DB_HOSTNAME ] ; then\n\t\tif [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\\{1,\\}$') ]; then\n\t\t\tEXTRA=\" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp\"\n\t\telif ! [ -z $DB_SOCK_OR_PORT ] ; then\n\t\t\tEXTRA=\" --socket=$DB_SOCK_OR_PORT\"\n\t\telif ! [ -z $DB_HOSTNAME ] ; then\n\t\t\tEXTRA=\" --host=$DB_HOSTNAME --protocol=tcp\"\n\t\tfi\n\tfi\n\n\t# create database\n\tmariadb-admin create $DB_NAME --user=\"$DB_USER\" --password=\"$DB_PASS\"$EXTRA || \\\n\t\tmysqladmin create $DB_NAME --user=\"$DB_USER\" --password=\"$DB_PASS\"$EXTRA\n}\n\ninstall_wp\ninstall_test_suite\ninstall_db\n"
  },
  {
    "path": "bin/local-env/docker-compose.yml",
    "content": "services:\n  wordpress:\n    image: wordpress:php${PHP_VERSION:-8.2}\n    ports:\n      - '127.0.0.1:8899:80'\n    environment:\n      WORDPRESS_DB_HOST: mysql\n      WORDPRESS_DB_USER: root\n      WORDPRESS_DB_PASSWORD: example\n      WORDPRESS_DB_NAME: wordpress\n      WP_ENVIRONMENT_TYPE: local\n      ABSPATH: /usr/src/wordpress/\n      WORDPRESS_DEBUG: 1\n      WORDPRESS_CONFIG_EXTRA: |\n        define( 'SCRIPT_DEBUG', true );\n        define( 'FS_METHOD', 'direct' );\n        define( 'WEBSTORIES_DEV_MODE', true );\n    volumes:\n      - wordpress_data:/var/www/html\n      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini\n      - ../../:/var/www/html/wp-content/plugins/web-stories\n      - ../../packages/e2e-tests/src/plugins:/var/www/html/wp-content/plugins/web-stories-test-plugins\n      - ../../packages/e2e-tests/src/assets:/var/www/html/wp-content/e2e-assets\n    depends_on:\n      - mysql\n\n  cli:\n    image: wordpress:cli-php${PHP_VERSION:-8.2}\n    environment:\n      WORDPRESS_DB_HOST: mysql\n      WORDPRESS_DB_USER: root\n      WORDPRESS_DB_PASSWORD: example\n      WORDPRESS_DB_NAME: wordpress\n    volumes:\n      - wordpress_data:/var/www/html\n      - ../../:/var/www/html/wp-content/plugins/web-stories\n      - ../../packages/e2e-tests/src/plugins:/var/www/html/wp-content/plugins/web-stories-test-plugins\n      - ../../packages/e2e-tests/src/assets:/var/www/html/wp-content/e2e-assets\n    depends_on:\n      - mysql\n      - wordpress\n    command: tail -f /dev/null\n\n  mysql:\n    image: mariadb:lts\n    command: --max-allowed-packet=16777216\n    environment:\n      MYSQL_ROOT_PASSWORD: example\n      MYSQL_DATABASE: wordpress_test\n    volumes:\n      - ./data/mysql:/var/lib/mysql\n\nvolumes:\n  wordpress_data:\n"
  },
  {
    "path": "bin/local-env/includes.sh",
    "content": "#!/usr/bin/env bash\n\n# Common variables.\nDOCKER_COMPOSE_FILE_OPTIONS=\"-f $(dirname \"$0\")/docker-compose.yml\"\n\nif [ -f \"$(dirname \"$0\")/docker-compose.override.yml\" ]; then\n  DOCKER_COMPOSE_FILE_OPTIONS=\"$DOCKER_COMPOSE_FILE_OPTIONS -f $(dirname \"$0\")/docker-compose.override.yml\"\nfi\n\n# These are the containers and values for the development site.\nCLI='cli'\nCONTAINER='wordpress'\nDATABASE='mysql'\nSITE_TITLE='Web Stories Dev'\n\n##\n# Ask a Yes/No question, and way for a reply.\n#\n# This is a general-purpose function to ask Yes/No questions in Bash, either with or without a default\n# answer. It keeps repeating the question until it gets a valid answer.\n#\n# @param {string} prompt    The question to ask the user.\n# @param {string} [default] Optional. \"Y\" or \"N\", for the default option to use if none is entered.\n# @param {int}    [timeout] Optional. The number of seconds to wait before using the default option.\n#\n# @returns {bool} true if the user replies Yes, false if the user replies No.\n##\nask() {\n    # Source: https://djm.me/ask\n    local timeout endtime timediff prompt default reply\n\n    while true; do\n\n\t\ttimeout=\"${3:-}\"\n\n        if [ \"${2:-}\" = \"Y\" ]; then\n            prompt=\"Y/n\"\n            default=Y\n        elif [ \"${2:-}\" = \"N\" ]; then\n            prompt=\"y/N\"\n            default=N\n        else\n            prompt=\"y/n\"\n            default=\n\t\t\ttimeout=\n        fi\n\n\t\tif [ -z \"$timeout\" ]; then\n        \t# Ask the question (not using \"read -p\" as it uses stderr not stdout)\n        \techo -en \"$1 [$prompt] \"\n\n        \t# Read the answer (use /dev/tty in case stdin is redirected from somewhere else)\n        \tread reply </dev/tty\n\t\telse\n\t\t\tendtime=$((`date +%s` + $timeout));\n\t\t\twhile [ \"$endtime\" -ge `date +%s` ]; do\n\t\t\t\ttimediff=$(($endtime - `date +%s`))\n\n\t\t\t\techo -en \"\\r$1 [$prompt] (Default $default in ${timediff}s) \"\n\t\t\t\tread -t 1 reply </dev/tty\n\n\t\t\t\tif [ -n \"$reply\" ]; then\n\t\t\t\t\tbreak\n\t\t\t\tfi\n\t\t\tdone\n\t\tfi\n\n        # Default?\n        if [ -z \"$reply\" ]; then\n            reply=$default\n        fi\n\n        # Check if the reply is valid\n        case \"$reply\" in\n            Y*|y*) return 0 ;;\n            N*|n*) return 1 ;;\n        esac\n\n    done\n}\n\n##\n# Download from a remote source.\n#\n# Checks for the existence of curl and wget, then downloads the remote file using the first available option.\n#\n# @param {string} remote  The remote file to download.\n# @param {string} [local] Optional. The local filename to use. If it isn't passed, STDOUT is used.\n#\n# @return {bool} Whether the download succeeded or not.\n##\ndownload() {\n    if command_exists \"curl\"; then\n        curl -s -o \"${2:--}\" \"$1\"\n    elif command_exists \"wget\"; then\n\t\twget -nv -O \"${2:--}\" \"$1\"\n    fi\n}\n\n##\n# Add error message formatting to a string, and echo it.\n#\n# @param {string} message The string to add formatting to.\n##\nerror_message() {\n\techo -en \"\\033[31mERROR\\033[0m: $1\"\n}\n\n##\n# Add warning message formatting to a string, and echo it.\n#\n# @param {string} message The string to add formatting to.\n##\nwarning_message() {\n\techo -en \"\\033[33mWARNING\\033[0m: $1\"\n}\n\n##\n# Add status message formatting to a string, and echo it.\n#\n# @param {string} message The string to add formatting to.\n##\nstatus_message() {\n\techo -en \"\\033[32mSTATUS\\033[0m: $1\"\n}\n\n##\n# Add formatting to an action string.\n#\n# @param {string} message The string to add formatting to.\n##\naction_format() {\n\techo -en \"\\033[32m$1\\033[0m\"\n}\n\n##\n# Check if the command exists as some sort of executable.\n#\n# The executable form of the command could be an alias, function, builtin, executable file or shell keyword.\n#\n# @param {string} command The command to check.\n#\n# @return {bool} Whether the command exists or not.\n##\ncommand_exists() {\n\ttype -t \"$1\" >/dev/null 2>&1\n}\n\n##\n# Docker Compose helper\n#\n# Calls docker compose with common options.\n##\ndc() {\n\tdocker compose $DOCKER_COMPOSE_FILE_OPTIONS \"$@\"\n}\n\n##\n# WP CLI\n#\n# Executes a WP CLI request in the CLI container.\n##\nwp() {\n\tdc exec -T -u 33:33 $CLI wp \"$@\"\n}\n\n##\n# MySQL CLI.\n#\n# Executes the given MySQL client command in the database container.\n##\nmysql() {\n\tdc exec -T -e MYSQL_PWD=example $DATABASE mariadb \"$@\"\n}\n\n##\n# WordPress Container helper.\n#\n# Executes the given command in the wordpress container.\n##\ncontainer() {\n\tdc exec -T $CONTAINER \"$@\"\n}\n"
  },
  {
    "path": "bin/local-env/install-wordpress.sh",
    "content": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Common variables.\nWP_DEBUG=${WP_DEBUG-true}\nSCRIPT_DEBUG=${SCRIPT_DEBUG-true}\nWEBSTORIES_DEV_MODE=${WEBSTORIES_DEV_MODE-true}\nMEDIA_TRASH=${MEDIA_TRASH-false}\nWP_VERSION=${WP_VERSION-\"latest\"}\n\n# Include useful functions\n. \"$(dirname \"$0\")/includes.sh\"\n\n# Make sure Docker containers are running\ndc up -d >/dev/null 2>&1\n\n# Get the host port for the WordPress container.\nHOST_PORT=$(dc port $CONTAINER 80 | awk -F : '{printf $2}')\n\n# Wait until the WordPress site is responding to requests.\necho -en $(status_message \"Attempting to connect to WordPress...\")\nuntil $(curl -L http://localhost:$HOST_PORT -so - 2>&1 | grep -q \"WordPress\"); do\n\techo -n '.'\n\tsleep 5\ndone\necho ''\n\n# Wait until the database container is ready.\necho -en $(status_message \"Waiting for database connection...\")\nuntil $(container bash -c \"echo -n > /dev/tcp/mysql/3306\" >/dev/null 2>&1); do\n\techo -n '.'\n\tsleep 5\ndone\necho ''\n\n# Create the database if it doesn't exist.\necho -e $(status_message \"Creating the database (if it does not exist)...\")\nmysql -e 'CREATE DATABASE IF NOT EXISTS wordpress;'\n\n# If this is the test site, we reset the database so no posts/comments/etc.\n# dirty up the tests.\nif [ \"$1\" == '--reset-site' ]; then\n\techo -e $(status_message \"Resetting test database...\")\n\twp db reset --yes --quiet\nfi\n\nif [ ! -z \"$WP_VERSION\" ] && [ \"$WP_VERSION\" != \"latest\" ]; then\n\t# Potentially downgrade (or upgrade) WordPress\n\techo -e $(status_message \"Downloading WordPress version $WP_VERSION...\")\n\twp core download --version=${WP_VERSION} --skip-content --force --quiet\nfi\n\n# Install WordPress.\necho -e $(status_message \"Installing WordPress...\")\nwp core install --title=\"$SITE_TITLE\" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:$HOST_PORT --quiet\n\n# Potentially update WordPress\nif [ \"$WP_VERSION\" == \"latest\" ]; then\n\techo -e $(status_message \"Updating WordPress to the latest major\")\n\twp core update --force --quiet\nelse\n  echo -e $(status_message \"Updating WordPress to the latest minor\")\n  wp core update --minor --force --quiet\nfi\n\n# Create additional users.\necho -e $(status_message \"Creating additional users...\")\n\nif [[ $(wp user get editor --field=login 2>&1) != \"editor\" ]]; then\n\twp user create editor editor@example.com --role=editor --user_pass=password\n\techo -e $(status_message \"Editor created! Username: editor Password: password\")\nelse\n echo -e $(status_message \"Editor already exists, skipping...\")\nfi\n\nif [[ $(wp user get author --field=login 2>&1) != \"author\" ]]; then\n\twp user create author author@example.com --role=author --user_pass=password --quiet\n\techo -e $(status_message \"Author created! Username: author Password: password\")\nelse\n echo -e $(status_message \"Author already exists, skipping...\")\nfi\nif [[ $(wp user get contributor --field=login 2>&1) != \"contributor\" ]]; then\n\twp user create contributor contributor@example.com --role=contributor --user_pass=password --quiet\n\techo -e $(status_message \"Contributor created! Username: contributor Password: password\")\nelse\n echo -e $(status_message \"Contributor already exists, skipping...\")\nfi\nif [[ $(wp user get subscriber --field=login 2>&1) != \"subscriber\" ]]; then\n\twp user create subscriber subscriber@example.com --role=subscriber --user_pass=password --quiet\n\techo -e $(status_message \"Subscriber created! Username: subscriber Password: password\")\nelse\n echo -e $(status_message \"Subscriber already exists, skipping...\")\nfi\n\n# Make sure the uploads and upgrade folders exist and we have permissions to add files.\necho -e $(status_message \"Ensuring that files can be uploaded...\")\ncontainer mkdir -p \\\n\t/var/www/html/wp-content/uploads \\\n\t/var/www/html/wp-content/upgrade\ncontainer chmod 767 \\\n\t/var/www/html/wp-content \\\n\t/var/www/html/wp-content/plugins \\\n\t/var/www/html/wp-config.php \\\n\t/var/www/html/wp-settings.php \\\n\t/var/www/html/wp-content/uploads \\\n\t/var/www/html/wp-content/upgrade\n\n\nCURRENT_WP_VERSION=$(wp core version | tr -d '\\r')\necho -e $(status_message \"Current WordPress version: $CURRENT_WP_VERSION...\")\n\nif [ \"$WP_VERSION\" == \"latest\" ]; then\n\t# Check for WordPress updates, to make sure we're running the very latest version.\n\techo -e $(status_message \"Updating WordPress to the latest version...\")\n\twp core update --quiet\n\techo -e $(status_message \"Updating The WordPress Database...\")\n\twp core update-db --quiet\nfi\n\n# If the 'wordpress' volume wasn't during the down/up earlier, but the post port has changed, we need to update it.\necho -e $(status_message \"Checking the site's url...\")\nCURRENT_URL=$(wp option get siteurl)\nif [ \"$CURRENT_URL\" != \"http://localhost:$HOST_PORT\" ]; then\n\twp option update home \"http://localhost:$HOST_PORT\" --quiet\n\twp option update siteurl \"http://localhost:$HOST_PORT\" --quiet\nfi\n\n# Activate Web Stories plugin.\necho -e $(status_message \"Activating Web Stories plugin...\")\nwp plugin activate web-stories --quiet\n\n# Install & activate testing plugins.\n\n# Only install Gutenberg on latest version of WordPress.\nif [ \"$WP_VERSION\" == \"latest\" ]; then\n\techo -e $(status_message \"Installing Gutenberg plugin...\")\n\twp plugin install gutenberg --force --quiet\nfi\n\necho -e $(status_message \"Installing and activating RTL Tester plugin...\")\nwp plugin install rtl-tester --activate --force --quiet\n\necho -e $(status_message \"Installing WordPress importer...\")\nwp plugin install wordpress-importer --activate --force --quiet\n\n# WooCommerce 9.8 is the last version that still supports WordPress 6.6.\necho -e $(status_message \"Installing WooCommerce plugin...\")\nif [ \"$WP_VERSION\" == \"6.6\" ]; then\n  wp plugin install woocommerce --version=9.8.2 --activate --force --quiet\nelse\n  wp plugin install woocommerce --activate --force --quiet\nfi\n\necho -e $(status_message \"Installing AMP plugin...\")\nwp plugin install amp --force --quiet\n\necho -e $(status_message \"Installing Classic editor plugin...\")\nwp plugin install classic-editor --force --quiet\n\necho -e $(status_message \"Installing Classic Widgets plugin...\")\nwp plugin install classic-widgets --force --quiet\n\necho -e $(status_message \"Activating Twenty Twenty theme...\")\nwp theme install twentytwenty --activate --force --quiet\n\necho -e $(status_message \"Disable block directory and remote patterns...\")\nwp plugin activate web-stories-test-plugins/disable-block-directory --quiet\n\necho -e $(status_message \"Disable Gravatar...\")\nwp plugin activate web-stories-test-plugins/disable-gravatar --quiet\n\n# Set pretty permalinks.\necho -e $(status_message \"Setting permalink structure...\")\nwp rewrite structure '%postname%' --hard --quiet\n\n# Configure site constants.\necho -e $(status_message \"Configuring site constants...\")\nWP_DEBUG_CURRENT=$(wp config get --type=constant --format=json WP_DEBUG | tr -d '\\r')\n\nif [[ \"$WP_DEBUG\" != $WP_DEBUG_CURRENT ]]; then\n\twp config set WP_DEBUG $WP_DEBUG --raw --type=constant --quiet --anchor=\"That's all, stop editing\"\n\tWP_DEBUG_RESULT=$(wp config get --type=constant --format=json WP_DEBUG | tr -d '\\r')\n\techo -e $(status_message \"WP_DEBUG: $WP_DEBUG_RESULT...\")\nfi\n\nSCRIPT_DEBUG_CURRENT=$(wp config get --type=constant --format=json SCRIPT_DEBUG | tr -d '\\r')\nif [[ \"$SCRIPT_DEBUG\" != $SCRIPT_DEBUG_CURRENT ]]; then\n\twp config set SCRIPT_DEBUG $SCRIPT_DEBUG --raw --type=constant --quiet --anchor=\"That's all, stop editing\"\n\tSCRIPT_DEBUG_RESULT=$(wp config get --type=constant --format=json SCRIPT_DEBUG | tr -d '\\r')\n\techo -e $(status_message \"SCRIPT_DEBUG: $SCRIPT_DEBUG_RESULT...\")\nfi\n\nWEBSTORIES_DEV_MODE_CURRENT=!$WEBSTORIES_DEV_MODE;\nif [[ \"$(wp config has --type=constant WEBSTORIES_DEV_MODE)\" ]]; then\n  WEBSTORIES_DEV_MODE_CURRENT=$(wp config get --type=constant --format=json WEBSTORIES_DEV_MODE | tr -d '\\r')\nfi\n\nif [[ \"$WEBSTORIES_DEV_MODE\" != $WEBSTORIES_DEV_MODE_CURRENT ]]; then\n  wp config set WEBSTORIES_DEV_MODE $WEBSTORIES_DEV_MODE --raw --type=constant --quiet --anchor=\"That's all, stop editing\"\n  WEBSTORIES_DEV_MODE_RESULT=$(wp config get --type=constant --format=json WEBSTORIES_DEV_MODE | tr -d '\\r')\n  echo -e $(status_message \"WEBSTORIES_DEV_MODE: $WEBSTORIES_DEV_MODE_RESULT...\")\nfi\n\nMEDIA_TRASH_CURRENT=!MEDIA_TRASH;\nif [[ \"$(wp config has --type=constant MEDIA_TRASH)\" ]]; then\n  MEDIA_TRASH_CURRENT=$(wp config get --type=constant --format=json MEDIA_TRASH | tr -d '\\r')\nfi\n\nif [[ \"$MEDIA_TRASH\" != $MEDIA_TRASH_CURRENT ]]; then\n  wp config set MEDIA_TRASH $MEDIA_TRASH --raw --type=constant --quiet --anchor=\"That's all, stop editing\"\n  MEDIA_TRASH_RESULT=$(wp config get --type=constant --format=json MEDIA_TRASH | tr -d '\\r')\n  echo -e $(status_message \"MEDIA_TRASH: $MEDIA_TRASH_RESULT...\")\nfi\n\n# Let's make sure we have some media in the media library to work with.\necho -e $(status_message \"Import default set of media assets...\")\n# TODO: use glob pattern to import items. See https://developer.wordpress.org/cli/commands/media/import/.\n\nWEBM_VIDEO_ID=$(wp media import /var/www/html/wp-content/e2e-assets/small-video.webm --porcelain)\nWEBM_VIDEO_POSTER_ID=$(wp media import /var/www/html/wp-content/e2e-assets/small-video-poster.jpg --post_id=$WEBM_VIDEO_ID --featured_image --porcelain)\n\n# So the poster is marked as such and hidden in the editor.\nwp post term add $WEBM_VIDEO_POSTER_ID web_story_media_source \"poster-generation\" --quiet\nwp post meta add $WEBM_VIDEO_ID web_stories_poster_id $WEBM_VIDEO_POSTER_ID --quiet\n\nwp media import /var/www/html/wp-content/e2e-assets/example-1.jpg --quiet\nwp media import /var/www/html/wp-content/e2e-assets/example-2.jpg --quiet\nwp media import /var/www/html/wp-content/e2e-assets/example-3.png --quiet\n\n# Ensures that the patch command below always works.\nwp option update web_stories_experiments '{}' --format=json\n\nwp option patch insert web_stories_experiments enableSVG 1\nwp media import /var/www/html/wp-content/e2e-assets/video-play.svg\nwp option patch insert web_stories_experiments enableSVG 0\n\nwp user list --format=yaml\nwp post list --post_type=attachment --format=yaml\nwp plugin list --format=yaml\n\necho -e $(status_message \"Import sample WooCommerce products...\")\nwp import /var/www/html/wp-content/plugins/woocommerce/sample-data/sample_products.xml --authors=skip --quiet\n\necho -e $(status_message \"Deactivating WooCommerce again...\")\nwp plugin deactivate woocommerce\n\necho -e $(status_message \"Deactivating WordPress importer again...\")\nwp plugin deactivate wordpress-importer --quiet\n\n"
  },
  {
    "path": "bin/local-env/launch-containers.sh",
    "content": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Include useful functions.\n. \"$(dirname \"$0\")/includes.sh\"\n\n# Check that Docker is installed.\nif ! command_exists \"docker\"; then\n\techo -e $(error_message \"Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format \"https://www.docker.com/products/docker-desktop\")\")\n\texit 1\nfi\n\n# Check that Docker is running.\nif ! docker info >/dev/null 2>&1; then\n\techo -e $(error_message \"Docker isn't running. Please check that you've started your Docker app, and see it in your system tray.\")\n\texit 1\nfi\n\n# Stop existing containers.\necho -e $(status_message \"Stopping Docker containers...\")\ndc down --remove-orphans >/dev/null 2>&1\n\n# Download image updates.\necho -e $(status_message \"Downloading Docker image updates...\")\ndc pull\n\n# Launch the containers.\necho -e $(status_message \"Starting Docker containers...\")\ndc up -d >/dev/null\n"
  },
  {
    "path": "bin/local-env/start.sh",
    "content": "#!/usr/bin/env bash\n\n# Exit if any command fails\nset -e\n\n# Include useful functions\n. \"$(dirname \"$0\")/includes.sh\"\n\n# Change to the expected directory\ncd \"$(dirname \"$0\")/../..\"\n\n# Check whether Docker is installed and running\n. \"$(dirname \"$0\")/launch-containers.sh\"\n\n# Set up WordPress Development site.\n# Note: we don't bother installing the test site right now, because that's\n# done on every time `npm run test-e2e` is run.\n. \"$(dirname \"$0\")/install-wordpress.sh\"\n\n\nCURRENT_URL=$(wp option get siteurl | tr -d '\\r')\n\necho -e \"\\nWelcome to the Web Stories development environment...\\n\"\n\n# Give the user more context to what they should do next: Build the plugin and start testing!\necho -e \"\\nRun $(action_format \"npm run dev\") to build the latest version of the Web Stories plugin,\"\necho -e \"then open $(action_format \"$CURRENT_URL\") to get started!\"\n\necho -e \"\\n\\nAccess the above install using the following credentials:\"\necho -e \"Default username: $(action_format \"admin\"), password: $(action_format \"password\")\"\n\nif [ -z \"$CI\" ]; then\n  if command -v xdg-open > /dev/null; then\n    xdg-open \"$CURRENT_URL\"\n  elif command -v open > /dev/null; then\n    open \"$CURRENT_URL\"\n  elif command -v xdg-open > /dev/null; then\n    xdg-open \"$CURRENT_URL\"\n  fi\nfi\n"
  },
  {
    "path": "bin/local-env/stop.sh",
    "content": "#!/usr/bin/env bash\n\n# Exit if any command fails.\nset -e\n\n# Include useful functions.\n. \"$(dirname \"$0\")/includes.sh\"\n\n# Check that Docker is installed.\nif ! command_exists \"docker\"; then\n\techo -e $(error_message \"Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format \"https://www.docker.com/products/docker-desktop\")\")\n\texit 1\nfi\n\n# Check that Docker is running.\nif ! docker info >/dev/null 2>&1; then\n\techo -e $(error_message \"Docker isn't running. Please check that you've started your Docker app, and see it in your system tray.\")\n\texit 1\nfi\n\n# Stop existing containers.\necho -e $(status_message \"Stopping Docker containers...\")\ndc down --remove-orphans >/dev/null 2>&1\n"
  },
  {
    "path": "bin/local-env/uploads.ini",
    "content": "upload_max_filesize = 100M;\npost_max_size = 100M;\n"
  },
  {
    "path": "bin/schemas/story.json",
    "content": "{\n  \"$id\": \"https://wp.stories.google/schema/story.json\",\n  \"type\": \"object\",\n  \"default\": {},\n  \"title\": \"Web Stories for WordPress Schema\",\n  \"required\": [\"version\", \"pages\"],\n  \"properties\": {\n    \"version\": {\n      \"type\": \"integer\",\n      \"default\": 0,\n      \"minimum\": 0,\n      \"title\": \"The story's data version\",\n      \"description\": \"Used for data migrations\"\n    },\n    \"pages\": {\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"title\": \"Story pages\",\n      \"description\": \"Holds individual pages of a story\",\n      \"items\": {\n        \"$ref\": \"#/$defs/page\"\n      }\n    }\n  },\n  \"$defs\": {\n    \"https\": {\n      \"type\": \"string\",\n      \"format\": \"uri-reference\",\n      \"pattern\": \"^(/|https://|https?://(127.0.0.1|([^/]+\\\\.)?localhost)(:[0-9]+)?/)\"\n    },\n    \"animation\": {\n      \"type\": \"object\",\n      \"title\": \"An animation\",\n      \"required\": [\"id\", \"type\", \"targets\", \"duration\", \"delay\"],\n      \"properties\": {\n        \"id\": {\n          \"type\": \"string\",\n          \"title\": \"Animation ID\",\n          \"format\": \"uuid\"\n        },\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"Animation type\",\n          \"enum\": [\n            \"blinkOn\",\n            \"bounce\",\n            \"effect-background-pan\",\n            \"effect-background-pan-and-zoom\",\n            \"effect-background-zoom\",\n            \"effect-drop\",\n            \"effect-fade-in\",\n            \"effect-fly-in\",\n            \"effect-pan\",\n            \"effect-pulse\",\n            \"effect-rotate-in\",\n            \"effect-twirl-in\",\n            \"effect-whoosh-in\",\n            \"effect-zoom\",\n            \"fade\",\n            \"flip\",\n            \"floatOn\",\n            \"move\",\n            \"pulse\",\n            \"spin\",\n            \"zoom\"\n          ]\n        },\n        \"targets\": {\n          \"type\": \"array\",\n          \"title\": \"Animation targets\",\n          \"items\": {\n            \"type\": \"string\",\n            \"title\": \"Target element ID\"\n          }\n        },\n        \"panDir\": {\n          \"type\": \"string\",\n          \"title\": \"panDir direction\",\n          \"enum\": [\"leftToRight\", \"topToBottom\", \"rightToLeft\", \"bottomToTop\"]\n        },\n        \"duration\": {\n          \"type\": \"integer\",\n          \"title\": \"Duration in ms\",\n          \"minimum\": 0\n        },\n        \"delay\": {\n          \"type\": \"integer\",\n          \"title\": \"Delay in ms\",\n          \"minimum\": 0\n        },\n        \"zoomDirection\": {\n          \"type\": \"string\",\n          \"default\": \"\",\n          \"title\": \"Zoom direction\",\n          \"enum\": [\n            \"dynamicPropertyValue\",\n            \"scaleIn\",\n            \"scaleInBottomRight\",\n            \"scaleInTopLeft\",\n            \"scaleOut\",\n            \"scaleOutTopRight\",\n            \"scaleOutBottomLeft\"\n          ]\n        }\n      }\n    },\n    \"element\": {\n      \"type\": \"object\",\n      \"title\": \"Base element\",\n      \"required\": [\"x\", \"y\", \"width\", \"height\", \"type\", \"id\", \"rotationAngle\"],\n      \"properties\": {\n        \"opacity\": {\n          \"type\": \"integer\",\n          \"minimum\": 0,\n          \"maximum\": 100,\n          \"default\": 100,\n          \"title\": \"Element opacity\",\n          \"$comment\": \"TODO: Set by default and make required\"\n        },\n        \"flip\": {\n          \"type\": \"object\",\n          \"title\": \"Flip setting\",\n          \"$comment\": \"TODO: Move somewhere else since text elements can't be flipped.\",\n          \"required\": [\"vertical\", \"horizontal\"],\n          \"properties\": {\n            \"vertical\": {\n              \"type\": \"boolean\",\n              \"title\": \"Vertical flipping\"\n            },\n            \"horizontal\": {\n              \"type\": \"boolean\",\n              \"title\": \"Horizontal flipping\"\n            }\n          }\n        },\n        \"rotationAngle\": {\n          \"type\": \"integer\",\n          \"title\": \"Rotation angle\",\n          \"$comment\": \"TODO: Set by default and make required\",\n          \"minimum\": -360,\n          \"maximum\": 360\n        },\n        \"lockAspectRatio\": {\n          \"type\": \"boolean\",\n          \"title\": \"Whether aspect ratio is locked\",\n          \"$comment\": \"TODO: Set by default and make required\"\n        },\n        \"backgroundColor\": {\n          \"type\": \"object\",\n          \"title\": \"Background color\",\n          \"$ref\": \"#/$defs/pattern\"\n        },\n        \"x\": {\n          \"type\": \"number\",\n          \"title\": \"X position\"\n        },\n        \"y\": {\n          \"type\": \"number\",\n          \"title\": \"Y position\"\n        },\n        \"width\": {\n          \"type\": \"number\",\n          \"title\": \"Element width\",\n          \"minimum\": 1\n        },\n        \"height\": {\n          \"type\": \"number\",\n          \"title\": \"Element height\",\n          \"minimum\": 1\n        },\n        \"mask\": {\n          \"type\": \"object\",\n          \"title\": \"Element mask\",\n          \"required\": [\"type\"],\n          \"properties\": {\n            \"type\": {\n              \"type\": \"string\",\n              \"title\": \"Mask type\",\n              \"enum\": [\n                \"heart\",\n                \"star\",\n                \"circle\",\n                \"rectangle\",\n                \"triangle\",\n                \"rounded-rectangle\",\n                \"rounded-rectangle-2\",\n                \"pentagon\",\n                \"hexagon\",\n                \"cross\",\n                \"arrow\",\n                \"burst\",\n                \"bullseye\",\n                \"blob-1\",\n                \"blob-2\",\n                \"blob-3\",\n                \"blob-4\",\n                \"blob-5\",\n                \"blob-6\",\n                \"grid-1\",\n                \"grid-2\",\n                \"grid-3\",\n                \"grid-4\",\n                \"grid-5\",\n                \"grid-6\",\n                \"grid-7\",\n                \"grid-8\",\n                \"burst-outline\",\n                \"arrow-1\",\n                \"arrow-2\",\n                \"arrow-3\",\n                \"geography-1\",\n                \"twitter\",\n                \"instagram\",\n                \"facebook\",\n                \"youtube\",\n                \"brush-stroke-1\",\n                \"brush-stroke-2\",\n                \"chat-bubble\",\n                \"check-mark\",\n                \"new-music\",\n                \"music-note\",\n                \"fashion-arrow\",\n                \"fashion-arrow-2\",\n                \"wellbeing-arrow\"\n              ]\n            },\n            \"showInLibrary\": {\n              \"type\": \"boolean\",\n              \"$comment\": \"TODO: Remove / do not store\"\n            },\n            \"name\": {\n              \"type\": \"string\",\n              \"$comment\": \"TODO: Remove / do not store\"\n            },\n            \"path\": {\n              \"type\": \"string\",\n              \"$comment\": \"TODO: Remove / do not store\"\n            },\n            \"ratio\": {\n              \"type\": \"number\",\n              \"$comment\": \"TODO: Remove / do not store\"\n            },\n            \"supportsBorder\": {\n              \"type\": \"boolean\",\n              \"$comment\": \"TODO: Remove / do not store\"\n            }\n          }\n        },\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"The element type\",\n          \"enum\": [\"image\", \"sticker\", \"text\", \"video\", \"shape\", \"gif\"]\n        },\n        \"id\": {\n          \"type\": \"string\",\n          \"title\": \"Element ID\",\n          \"format\": \"uuid\"\n        },\n\n        \"borderRadius\": {\n          \"type\": \"object\",\n          \"title\": \"Element border radius\",\n          \"required\": [\n            \"locked\",\n            \"topLeft\",\n            \"topRight\",\n            \"bottomRight\",\n            \"bottomLeft\"\n          ],\n          \"properties\": {\n            \"locked\": {\n              \"type\": \"boolean\",\n              \"title\": \"Whether padding is locked\"\n            },\n            \"topLeft\": {\n              \"type\": \"integer\",\n              \"title\": \"Top left radius\",\n              \"minimum\": 0\n            },\n            \"topRight\": {\n              \"type\": \"integer\",\n              \"title\": \"Top right radius\",\n              \"minimum\": 0\n            },\n            \"bottomRight\": {\n              \"type\": \"integer\",\n              \"title\": \"Bottom right radius\",\n              \"minimum\": 0\n            },\n            \"bottomLeft\": {\n              \"type\": \"integer\",\n              \"title\": \"Bottom left radius\",\n              \"minimum\": 0\n            }\n          }\n        },\n        \"basedOn\": {\n          \"type\": \"string\",\n          \"default\": \"\",\n          \"title\": \"Reference to the original element if this one was duplicated/copied\",\n          \"$comment\": \"TODO: Remove?\"\n        },\n        \"isBackground\": {\n          \"type\": \"boolean\",\n          \"title\": \"Whether it is the background element\",\n          \"$comment\": \"TODO: Move somewhere else since text elements can't be background.\"\n        },\n        \"groupId\": {\n          \"type\": \"string\",\n          \"title\": \"Layer group ID\"\n        }\n      }\n    },\n    \"textElement\": {\n      \"type\": \"object\",\n      \"title\": \"Text element\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/$defs/element\"\n        }\n      ],\n      \"required\": [\n        \"backgroundTextMode\",\n        \"font\",\n        \"fontSize\",\n        \"lineHeight\",\n        \"textAlign\",\n        \"content\",\n        \"fontWeight\"\n      ],\n      \"properties\": {\n        \"backgroundTextMode\": {\n          \"type\": \"string\",\n          \"title\": \"Text background mode\",\n          \"enum\": [\"NONE\", \"FILL\", \"HIGHLIGHT\"]\n        },\n        \"font\": {\n          \"type\": \"object\",\n          \"title\": \"The font Schema\",\n          \"required\": [\n            \"family\",\n            \"service\",\n            \"fallbacks\",\n            \"weights\",\n            \"styles\",\n            \"variants\",\n            \"metrics\"\n          ],\n          \"properties\": {\n            \"family\": {\n              \"type\": \"string\",\n              \"title\": \"Font family\"\n            },\n            \"service\": {\n              \"type\": \"string\",\n              \"title\": \"Font provider\",\n              \"examples\": [\"fonts.google.com\"]\n            },\n            \"fallbacks\": {\n              \"type\": \"array\",\n              \"title\": \"Fallback fonts\",\n              \"items\": {\n                \"type\": \"string\",\n                \"title\": \"Font family\"\n              },\n              \"examples\": [[\"sans-serif\"], [\"Helvetica\", \"sans-serif\"]]\n            },\n            \"weights\": {\n              \"type\": \"array\",\n              \"title\": \"Supported font weights\",\n              \"minItems\": 1,\n              \"items\": {\n                \"type\": \"integer\",\n                \"title\": \"Font weight\",\n                \"minimum\": 100,\n                \"maximum\": 900\n              }\n            },\n            \"styles\": {\n              \"type\": \"array\",\n              \"title\": \"Support font styles\",\n              \"minItems\": 1,\n              \"items\": {\n                \"type\": \"string\",\n                \"title\": \"Font style\",\n                \"enum\": [\"italic\", \"regular\"]\n              }\n            },\n            \"variants\": {\n              \"type\": \"array\",\n              \"title\": \"Font variants\",\n              \"items\": {\n                \"type\": \"array\",\n                \"title\": \"Font variant tuple\",\n                \"minItems\": 2,\n                \"maxItems\": 2,\n                \"items\": {\n                  \"type\": \"integer\"\n                },\n                \"examples\": [\n                  [0, 100],\n                  [1, 500],\n                  [1, 700]\n                ]\n              }\n            },\n            \"metrics\": {\n              \"type\": \"object\",\n              \"title\": \"Font metrics\",\n              \"required\": [\n                \"upm\",\n                \"asc\",\n                \"des\",\n                \"tAsc\",\n                \"tDes\",\n                \"tLGap\",\n                \"wAsc\",\n                \"wDes\",\n                \"xH\",\n                \"capH\",\n                \"yMin\",\n                \"yMax\",\n                \"hAsc\",\n                \"hDes\",\n                \"lGap\"\n              ],\n              \"properties\": {\n                \"upm\": {\n                  \"type\": \"integer\"\n                },\n                \"asc\": {\n                  \"type\": \"integer\"\n                },\n                \"des\": {\n                  \"type\": \"integer\"\n                },\n                \"tAsc\": {\n                  \"type\": \"integer\"\n                },\n                \"tDes\": {\n                  \"type\": \"integer\"\n                },\n                \"tLGap\": {\n                  \"type\": \"integer\"\n                },\n                \"wAsc\": {\n                  \"type\": \"integer\"\n                },\n                \"wDes\": {\n                  \"type\": \"integer\"\n                },\n                \"xH\": {\n                  \"type\": \"integer\"\n                },\n                \"capH\": {\n                  \"type\": \"integer\"\n                },\n                \"yMin\": {\n                  \"type\": \"integer\"\n                },\n                \"yMax\": {\n                  \"type\": \"integer\"\n                },\n                \"hAsc\": {\n                  \"type\": \"integer\"\n                },\n                \"hDes\": {\n                  \"type\": \"integer\"\n                },\n                \"lGap\": {\n                  \"type\": \"integer\"\n                }\n              }\n            }\n          }\n        },\n        \"fontSize\": {\n          \"type\": \"integer\",\n          \"title\": \"Font size\",\n          \"minimum\": 1\n        },\n        \"lineHeight\": {\n          \"type\": \"number\",\n          \"title\": \"Line height\"\n        },\n        \"textAlign\": {\n          \"type\": \"string\",\n          \"title\": \"Text alignment\",\n          \"enum\": [\"initial\", \"left\", \"center\", \"right\"]\n        },\n        \"content\": {\n          \"type\": \"string\",\n          \"title\": \"The element's content. Can contain HTML.\"\n        },\n        \"padding\": {\n          \"type\": \"object\",\n          \"title\": \"Element padding\",\n          \"required\": [],\n          \"properties\": {\n            \"horizontal\": {\n              \"type\": \"integer\",\n              \"title\": \"Horizontal padding\",\n              \"minimum\": 0\n            },\n            \"vertical\": {\n              \"type\": \"integer\",\n              \"title\": \"Vertical padding\",\n              \"minimum\": 0\n            },\n            \"locked\": {\n              \"type\": \"boolean\",\n              \"title\": \"Whether padding is locked\"\n            },\n            \"hasHiddenPadding\": {\n              \"type\": \"boolean\",\n              \"title\": \"Whether the element has hidden padding\"\n            }\n          }\n        },\n        \"marginOffset\": {\n          \"type\": \"number\",\n          \"title\": \"Margin offset\"\n        }\n      }\n    },\n    \"stickerElement\": {\n      \"type\": \"object\",\n      \"title\": \"Sticker element\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/$defs/element\"\n        }\n      ],\n      \"required\": [\"sticker\"],\n      \"properties\": {\n        \"sticker\": {\n          \"type\": \"object\",\n          \"title\": \"The sticker Schema\",\n          \"required\": [\"type\"],\n          \"properties\": {\n            \"type\": {\n              \"type\": \"string\",\n              \"title\": \"The type Schema\"\n            }\n          }\n        }\n      }\n    },\n    \"mediaElement\": {\n      \"type\": \"object\",\n      \"title\": \"Media element\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/$defs/element\"\n        }\n      ],\n      \"required\": [\"resource\"],\n      \"properties\": {\n        \"resource\": {\n          \"type\": \"object\",\n          \"title\": \"The resource Schema\",\n          \"required\": [\n            \"type\",\n            \"mimeType\",\n            \"src\",\n            \"width\",\n            \"height\",\n            \"id\",\n            \"alt\",\n            \"sizes\"\n          ],\n          \"properties\": {\n            \"type\": {\n              \"type\": \"string\",\n              \"title\": \"Resource type\",\n              \"enum\": [\"image\", \"video\", \"gif\"]\n            },\n            \"mimeType\": {\n              \"type\": \"string\",\n              \"title\": \"Mime type\"\n            },\n            \"src\": {\n              \"type\": \"string\",\n              \"title\": \"Media source\"\n            },\n            \"width\": {\n              \"type\": \"integer\",\n              \"title\": \"Media width\",\n              \"minimum\": 1\n            },\n            \"height\": {\n              \"type\": \"integer\",\n              \"title\": \"Media height\",\n              \"minimum\": 1\n            },\n            \"id\": {\n              \"type\": \"integer\",\n              \"title\": \"Resource ID\"\n            },\n            \"alt\": {\n              \"type\": \"string\",\n              \"title\": \"Alt text\"\n            },\n            \"sizes\": {\n              \"type\": \"array\",\n              \"title\": \"The sizes Schema\",\n              \"items\": {},\n              \"$comment\": \"TODO: Complete schema\"\n            },\n            \"isOptimized\": {\n              \"type\": \"boolean\",\n              \"title\": \"Whether the resource is considered optimized\"\n            },\n            \"baseColor\": {\n              \"type\": \"string\",\n              \"title\": \"Average/Base color\",\n              \"examples\": [\"#99684c\", \"#daa992\"]\n            },\n            \"isExternal\": {\n              \"type\": \"boolean\",\n              \"title\": \"Whether it is an external resource\"\n            },\n            \"creationDate\": {\n              \"type\": \"string\",\n              \"default\": \"\",\n              \"title\": \"Date the media file was uploaded\",\n              \"format\": \"date-time\"\n            },\n            \"posterId\": {\n              \"type\": \"integer\",\n              \"default\": 0,\n              \"title\": \"ID of the resource's poster\"\n            },\n            \"scale\": {\n              \"type\": \"number\",\n              \"title\": \"Scaling\",\n              \"minimum\": 0\n            },\n            \"focalX\": {\n              \"type\": \"number\",\n              \"title\": \"X axis focal point\",\n              \"minimum\": 0\n            },\n            \"focalY\": {\n              \"type\": \"number\",\n              \"title\": \"Y axis focal point\",\n              \"minimum\": 0\n            }\n          }\n        },\n        \"overlay\": {\n          \"type\": \"object\",\n          \"$ref\": \"#/$defs/linearPattern\"\n        }\n      }\n    },\n    \"shapeElement\": {\n      \"type\": \"object\",\n      \"title\": \"Shape element\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/$defs/element\"\n        }\n      ],\n      \"properties\": {\n        \"isDefaultBackground\": {\n          \"type\": \"boolean\",\n          \"title\": \"Whether it is the default background\"\n        }\n      }\n    },\n    \"pattern\": {\n      \"type\": \"object\",\n      \"oneOf\": [\n        { \"$ref\": \"#/$defs/solidPattern\" },\n        { \"$ref\": \"#/$defs/linearPattern\" }\n      ]\n    },\n    \"solidPattern\": {\n      \"type\": \"object\",\n      \"title\": \"Solid pattern\",\n      \"required\": [\"color\"],\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"enum\": [\"none\", \"solid\", \"linear\", \"radial\"]\n        },\n        \"color\": {\n          \"type\": \"object\",\n          \"title\": \"RGB(A) color\",\n          \"required\": [\"r\", \"g\", \"b\"],\n          \"properties\": {\n            \"r\": {\n              \"type\": \"integer\",\n              \"title\": \"Red\",\n              \"minimum\": 0,\n              \"maximum\": 255\n            },\n            \"g\": {\n              \"type\": \"integer\",\n              \"title\": \"Green\",\n              \"minimum\": 0,\n              \"maximum\": 255\n            },\n            \"b\": {\n              \"type\": \"integer\",\n              \"title\": \"Blue\",\n              \"minimum\": 0,\n              \"maximum\": 255\n            },\n            \"a\": {\n              \"type\": \"number\",\n              \"title\": \"Alpha\",\n              \"minimum\": 0,\n              \"maximum\": 1\n            }\n          }\n        }\n      }\n    },\n    \"linearPattern\": {\n      \"type\": \"object\",\n      \"title\": \"Linear color pattern\",\n      \"required\": [\"type\", \"stops\"],\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"enum\": [\"none\", \"solid\", \"linear\", \"radial\"]\n        },\n        \"stops\": {\n          \"type\": \"array\",\n          \"minItems\": 1,\n          \"items\": {\n            \"type\": \"object\",\n            \"allOf\": [\n              {\n                \"$ref\": \"#/$defs/solidPattern\"\n              }\n            ],\n            \"properties\": {\n              \"position\": {\n                \"type\": \"number\",\n                \"minimum\": 0,\n                \"maximum\": 1\n              }\n            }\n          }\n        },\n        \"alpha\": {\n          \"type\": \"number\",\n          \"minimum\": 0,\n          \"maximum\": 1\n        },\n        \"rotation\": {\n          \"type\": \"number\",\n          \"minimum\": -359,\n          \"maximum\": 359\n        }\n      }\n    },\n    \"page\": {\n      \"type\": \"object\",\n      \"title\": \"Individual Page\",\n      \"required\": [\"backgroundColor\", \"elements\", \"id\", \"type\"],\n      \"properties\": {\n        \"animations\": {\n          \"type\": \"array\",\n          \"title\": \"Animations on this page\",\n          \"items\": {\n            \"$ref\": \"#/$defs/animation\"\n          }\n        },\n        \"elements\": {\n          \"type\": \"array\",\n          \"minItems\": 1,\n          \"title\": \"The page's elements\",\n          \"items\": {\n            \"anyOf\": [\n              { \"$ref\": \"#/$defs/element\" },\n              { \"$ref\": \"#/$defs/mediaElement\" },\n              { \"$ref\": \"#/$defs/shapeElement\" },\n              { \"$ref\": \"#/$defs/stickerElement\" },\n              { \"$ref\": \"#/$defs/textElement\" }\n            ]\n          }\n        },\n        \"backgroundColor\": {\n          \"type\": \"object\",\n          \"title\": \"Background color\",\n          \"$ref\": \"#/$defs/pattern\"\n        },\n        \"defaultBackgroundElement\": {\n          \"type\": \"object\",\n          \"title\": \"The default background element\",\n          \"$ref\": \"#/$defs/shapeElement\",\n          \"$comment\": \"TODO: Move to story element or remove?\"\n        },\n        \"id\": {\n          \"type\": \"string\",\n          \"title\": \"Page ID\",\n          \"format\": \"uuid\"\n        },\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"The type Schema\",\n          \"enum\": [\"page\"],\n          \"$comment\": \"TODO: Remove?\"\n        },\n        \"groups\": {\n          \"type\": \"object\",\n          \"title\": \"Layer groups\",\n          \"patternProperties\": {\n            \"^[\\\\w-]+\": {\n              \"type\": \"object\",\n              \"required\": [\"name\", \"isLocked\"],\n              \"properties\": {\n                \"name\": {\n                  \"type\": \"string\"\n                },\n                \"isLocked\": {\n                  \"type\": \"boolean\"\n                },\n                \"isCollapsed\": {\n                  \"type\": \"boolean\"\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "bin/setup-local-npm-registry.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Echo every command being executed\nset -ex\n\nregistry_url=http://localhost:4873\n\necho \"Starting up local npm registry...\"\n\n# Start local registry.\ntmp_registry_log=`mktemp`\n\necho \"Registry output file: $tmp_registry_log\"\n\ncurdir=$(dirname \"$(realpath $0)\")\n\n(cd && nohup npx verdaccio --config \"$curdir/verdaccio-config.yml\" &>$tmp_registry_log &)\n\nnpm i --global verdaccio-memory\n\n# Wait for Verdaccio to boot.\ngrep -q 'http address' <(tail -f $tmp_registry_log)\n\necho \"Local registry up and running! ${registry_url}\"\n\n# Set registry to local registry\nexport NPM_CONFIG_REGISTRY=\"$registry_url\"\n\necho \"Logging in...\"\n\n# Log in to Verdaccio so we can publish packages\nnpx npm-cli-login -u admin -p password -e test@example.com -r $registry_url\n"
  },
  {
    "path": "bin/stop-local-npm-registry.sh",
    "content": "#!/usr/bin/env bash\n\n#\n# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nlsof -nti:4873 | xargs kill -9\n\nunset NPM_CONFIG_REGISTRY\n"
  },
  {
    "path": "bin/verdaccio-config.yml",
    "content": "#\n# This is the default config file. It allows all users to do anything,\n# so don't use it on production systems.\n#\n# Look here for more config file examples:\n# https://github.com/verdaccio/verdaccio/tree/master/conf\n#\n\n# path to a directory with all packages\nstorage: /tmp/verdaccio-workspace/storage\n\nweb:\n  title: Verdaccio\n\nauth:\n  htpasswd:\n    file: /tmp/verdaccio-workspace/htpasswd\n\n# a list of other known repositories we can talk to\nuplinks:\n  npmjs:\n    url: https://registry.npmjs.org/\n\npackages:\n  '@*/*':\n    # scoped packages\n    access: $all\n    publish: $authenticated\n    unpublish: $authenticated\n    proxy: npmjs\n\n  '**':\n    # allow all users (including non-authenticated users) to read and\n    # publish all packages\n    #\n    # you can specify usernames/groupnames (depending on your auth plugin)\n    # and three keywords: \"$all\", \"$anonymous\", \"$authenticated\"\n    access: $all\n\n    # allow all known users to publish/publish packages\n    # (anyone can register by default, remember?)\n    publish: $authenticated\n    unpublish: $authenticated\n\n    # if package is not available locally, proxy requests to 'npmjs' registry\n    proxy: npmjs\n\nserver:\n  # deprecated\n  keepAliveTimeout: 60\n\nmiddlewares:\n  audit:\n    enabled: true\n\n# log settings\nlogs:\n  # Logger as STDOUT\n  { type: stdout, format: pretty, level: warn }\n\n# This affect the web and api (not developed yet)\ni18n:\n  web: en-US\n"
  },
  {
    "path": "blocks/embed/block.json",
    "content": "{\n  \"name\": \"web-stories/embed\",\n  \"title\": \"Web Stories\",\n  \"description\": \"Embed Web Stories.\",\n  \"category\": \"embed\",\n  \"keywords\": [\"embed\", \"web stories\", \"story\", \"stories\"],\n  \"textdomain\": \"web-stories\",\n  \"usesContext\": [\"postId\", \"postType\", \"queryId\"],\n  \"attributes\": {\n    \"blockType\": {\n      \"type\": \"string\"\n    },\n    \"url\": {\n      \"type\": \"string\"\n    },\n    \"title\": {\n      \"type\": \"string\"\n    },\n    \"poster\": {\n      \"type\": \"string\"\n    },\n    \"width\": {\n      \"type\": \"number\",\n      \"default\": 360\n    },\n    \"height\": {\n      \"type\": \"number\",\n      \"default\": 600\n    },\n    \"align\": {\n      \"type\": \"string\",\n      \"default\": \"none\"\n    },\n    \"stories\": {\n      \"type\": \"array\",\n      \"default\": []\n    },\n    \"viewType\": {\n      \"type\": \"string\",\n      \"default\": \"\"\n    },\n    \"numOfStories\": {\n      \"type\": \"number\",\n      \"default\": 5\n    },\n    \"numOfColumns\": {\n      \"type\": \"number\",\n      \"default\": 2\n    },\n    \"circleSize\": {\n      \"type\": \"number\",\n      \"default\": 96\n    },\n    \"imageAlignment\": {\n      \"type\": \"string\",\n      \"default\": \"left\"\n    },\n    \"order\": {\n      \"type\": \"string\",\n      \"default\": \"\"\n    },\n    \"orderby\": {\n      \"type\": \"string\",\n      \"default\": \"\"\n    },\n    \"archiveLinkLabel\": {\n      \"type\": \"string\",\n      \"default\": \"\"\n    },\n    \"authors\": {\n      \"type\": \"array\",\n      \"default\": []\n    },\n    \"fieldState\": {\n      \"type\": \"object\",\n      \"default\": {}\n    },\n    \"taxQuery\": {\n      \"type\": \"object\",\n      \"default\": {}\n    },\n    \"previewOnly\": {\n      \"type\": \"boolean\",\n      \"default\": false\n    }\n  },\n  \"supports\": {\n    \"align\": [\"wide\", \"full\", \"left\", \"right\", \"center\"],\n    \"interactivity\": true\n  },\n  \"viewScriptModule\": \"file:../../assets/js/web-stories-block-view.js\"\n}\n"
  },
  {
    "path": "codecov.yml",
    "content": "# Overall settings for PR integration via codecov.io\n# See https://docs.codecov.io/docs/codecovyml-reference\n\n# Separate PR statuses for project-level and patch-level coverage\n# See https://docs.codecov.io/docs/commit-status\ncoverage:\n  status:\n    # Project-level coverage\n    project:\n      default:\n        base: auto\n        # Disable once code base is more mature.\n        informational: true\n        only_pulls: true\n        target: auto\n        threshold: 1%\n\n      php:\n        paths:\n          - includes\n\n      dashboard:\n        paths:\n          - packages/dashboard/src\n\n      dashboard.unit:\n        paths:\n          - packages/dashboard/src\n        flags:\n          - unittests\n\n      dashboard.karma:\n        paths:\n          - packages/dashboard/src\n        flags:\n          - karmatests\n\n      editor:\n        paths:\n          - packages/story-editor/src\n\n      editor.unit:\n        paths:\n          - packages/story-editor/src\n        flags:\n          - unittests\n\n      editor.karma:\n        paths:\n          - packages/story-editor/src\n        flags:\n          - karmatests\n\n    # Patch-level coverage (how well is the PR tested)\n    patch:\n      default:\n        base: auto\n        # Disable once code base is more mature.\n        informational: true\n        only_pulls: true\n        target: auto\n        threshold: 50%\n\n# Pull request comments\n# See https://docs.codecov.io/docs/pull-request-comments\ncomment: false\n\n# See https://docs.codecov.io/docs/ignoring-paths\nignore:\n  - bin\n  - tests\n  - .phpstorm.meta.php\n  - scoper.inc.php\n  - web-stories.php\n  - uninstall.php\n  - includes/namespace.php\n  - includes/compat\n  - includes/polyfills\n  - includes/templates\n  - includes/AMP/Integration/AMP_Story_Sanitizer.php\n  - includes/REST_API/Stories_Settings_Controller.php\n  - includes/REST_API/Stories_Users_Controller.php\n  - packages/e2e-tests\n  - packages/e2e-test-utils\n  - packages/eslint-import-resolver\n  - packages/fonts/scripts\n  - packages/jest-amp\n  - packages/jest-puppeteer-amp\n  - packages/jest-resolver\n  - packages/karma-failed-tests-reporter\n  - packages/karma-fixture\n  - packages/karma-puppeteer-client\n  - packages/karma-puppeteer-launcher\n  - packages/migration/scripts\n  - packages/templates/scripts\n  - packages/test-utils\n  - '**/storybookUtils'\n  - '**/testUtils'\n"
  },
  {
    "path": "composer.json",
    "content": "{\n  \"name\": \"googleforcreators/web-stories-wp\",\n  \"description\": \"Visual storytelling for WordPress.\",\n  \"license\": \"Apache-2.0\",\n  \"type\": \"wordpress-plugin\",\n  \"homepage\": \"https://github.com/googleforcreators/web-stories-wp\",\n  \"require\": {\n    \"php\": \"^7.4 || ^8.0\",\n    \"ext-dom\": \"*\",\n    \"ext-iconv\": \"*\",\n    \"ext-json\": \"*\",\n    \"ext-libxml\": \"*\",\n    \"ext-mbstring\": \"*\",\n    \"ampproject/amp-toolbox\": \"*\",\n    \"ampproject/amp-wp\": \"dev-develop\",\n    \"enshrined/svg-sanitize\": \"^0.22.0\",\n    \"mcaskill/composer-exclude-files\": \"^4.0\",\n    \"symfony/polyfill-mbstring\": \"^1.18\"\n  },\n  \"require-dev\": {\n    \"automattic/vipwpcs\": \"^3.0.0\",\n    \"dealerdirect/phpcodesniffer-composer-installer\": \"^1.0.0\",\n    \"ergebnis/composer-normalize\": \"^2.28\",\n    \"humbug/php-scoper\": \"^0.17.5\",\n    \"php-stubs/woocommerce-stubs\": \"^10.0\",\n    \"php-stubs/wordpress-tests-stubs\": \"^6.1.1\",\n    \"phpcompatibility/phpcompatibility-wp\": \"^2.1\",\n    \"phpmd/phpmd\": \"^2.9\",\n    \"phpstan/extension-installer\": \"^1.1\",\n    \"phpstan/phpstan-deprecation-rules\": \"^2.0.1\",\n    \"phpstan/phpstan-phpunit\": \"^2.0.1\",\n    \"roave/security-advisories\": \"dev-latest\",\n    \"sirbrillig/phpcs-variable-analysis\": \"^2.8\",\n    \"slevomat/coding-standard\": \"^8.0.0\",\n    \"sniccowp/php-scoper-wordpress-excludes\": \"^6.0\",\n    \"swissspidy/phpstan-no-private\": \"^1.0.0\",\n    \"szepeviktor/phpstan-wordpress\": \"^2.0.0\",\n    \"wp-coding-standards/wpcs\": \"^3.0.0\",\n    \"yoast/wp-test-utils\": \"^1.0.0\"\n  },\n  \"suggest\": {\n    \"ext-curl\": \"Used for modifying cURL requests in CORS proxy\"\n  },\n  \"repositories\": [\n    {\n      \"type\": \"vcs\",\n      \"url\": \"https://github.com/ampproject/amp-wp\",\n      \"no-api\": true\n    }\n  ],\n  \"prefer-stable\": true,\n  \"autoload\": {\n    \"psr-4\": {\n      \"AmpProject\\\\\": \"vendor/ampproject/amp-wp/lib/common/src\",\n      \"AmpProject\\\\Optimizer\\\\\": \"vendor/ampproject/amp-wp/lib/optimizer/src\",\n      \"Google\\\\Web_Stories\\\\\": \"includes\"\n    }\n  },\n  \"autoload-dev\": {\n    \"psr-4\": {\n      \"Google\\\\Web_Stories\\\\PHPStan\\\\\": \"tests/phpstan/src\",\n      \"Google\\\\Web_Stories\\\\Tests\\\\Integration\\\\\": \"tests/phpunit/integration/includes\",\n      \"Google\\\\Web_Stories\\\\Tests\\\\Shared\\\\\": \"tests/phpunit/shared\",\n      \"Google\\\\Web_Stories\\\\Tests\\\\Unit\\\\\": \"tests/phpunit/unit/includes\"\n    }\n  },\n  \"config\": {\n    \"allow-plugins\": {\n      \"civicrm/composer-downloads-plugin\": true,\n      \"composer/installers\": true,\n      \"cweagans/composer-patches\": true,\n      \"dealerdirect/phpcodesniffer-composer-installer\": true,\n      \"ergebnis/composer-normalize\": true,\n      \"mcaskill/composer-exclude-files\": true,\n      \"phpstan/extension-installer\": true\n    },\n    \"discard-changes\": true,\n    \"platform\": {\n      \"php\": \"7.4\"\n    },\n    \"sort-packages\": true\n  },\n  \"extra\": {\n    \"enable-patching\": true,\n    \"exclude-from-files\": [\n      \"ampproject/amp-wp/includes/bootstrap.php\"\n    ],\n    \"installer-disable\": true,\n    \"patches\": {\n      \"humbug/php-scoper\": {\n        \"Fix using null as array key\": \"./patches/humbug-php-scoper-php85.diff\"\n      },\n      \"thecodingmachine/safe\": {\n        \"Fix explicit nullable errors\": \"./patches/thecodingmachine-safe-nullable.diff\"\n      }\n    }\n  },\n  \"scripts\": {\n    \"post-install-cmd\": [\n      \"@prefix-dependencies\"\n    ],\n    \"post-update-cmd\": [\n      \"@prefix-dependencies\"\n    ],\n    \"phpcbf\": \"phpcbf --severity=1\",\n    \"phpcs\": \"phpcs --severity=1\",\n    \"phpmd\": \"phpmd . text phpmd.xml\",\n    \"phpstan\": \"phpstan analyse --memory-limit=2048M\",\n    \"prefix-dependencies\": [\n      \"php-scoper add-prefix --output-dir=./third-party --force --quiet\",\n      \"echo '{ \\\"autoload\\\": { \\\"classmap\\\": [\\\"\\\"] } }' > ./third-party/composer.json\",\n      \"@composer dump-autoload --working-dir ./third-party --no-dev --classmap-authoritative\",\n      \"sed -i'.bak' -e 's/Composer\\\\\\\\Autoload/Google_Web_Stories_Composer\\\\\\\\Autoload/' third-party/vendor/composer/*.php && rm -rf third-party/vendor/composer/*.php.bak\",\n      \"echo '{ \\\"autoload\\\": { \\\"classmap\\\": [\\\"\\\"], \\\"files\\\": [\\\"polyfills/mbstring.php\\\"] } }' > ./includes/composer.json\",\n      \"@composer dump-autoload --working-dir ./includes --no-dev --classmap-authoritative\",\n      \"sed -i'.bak' -e 's/Composer\\\\\\\\Autoload/Google_Web_Stories_Composer\\\\\\\\Autoload/' includes/vendor/composer/*.php && rm -rf includes/vendor/composer/*.php.bak\"\n    ]\n  }\n}\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Technical Documentation\n\n## Introduction\n\n* [Getting Started](./getting-started.md)\n* [Glossary](./glossary.md)\n\n## Contributing\n\n* [Onboarding](./onboarding.md)\n\n## Maintenance\n\n* [CDN Assets](./cdn.md)\n\n## Development\n\n* [Accessibility Guidelines](./accessibility-guidelines.md)\n* [Architecture](./architecture.md)\n* [Browser and device support](./browser-support.md)\n* [Code Style](./code-style.md)\n* [Environment Variables](./environment-variables.md)\n* [Migrations](./migrations.md)\n* [Development Tools](./devtools.md)\n* [Feature Flags](./feature-flags.md)\n* [Design Docs](./design-docs.md)\n* [External Template Creation](./external-template-creation.md)\n* [Page Templates](./page-templates.md)\n\n## Testing\n\n* [Manual Testing (QA)](./testing-qa.md)\n* [Unit Tests](./unit-tests.md)\n* [Integration Tests (Karma)](./integration-tests.md)\n* [End-to-End Tests](./e2e-tests.md)\n* [Accessibility Testing](./accessibility-testing.md)\n* [Testing Environments](./testing-environments.md)\n\n## Tooling & Infrastructure\n\n* [Local Environment](./local-environment.md)\n* [Workflows](./workflows.md)\n\n## WordPress Developers\n\n* [Embeds](./web-stories-embeds.md)\n\n## Third-Party Integrations\n\n### Dashboard\n\n* [Getting Started](./third-party-integration/dashboard/getting-started.md)\n* [API Callbacks](./third-party-integration/dashboard/api-callbacks.md)\n* [Integration Layer](./third-party-integration/dashboard/integration-layer.md)\n* [Tutorial](./third-party-integration/dashboard/tutorial.md)\n\n### Story Editor\n\n* [Getting Started](./third-party-integration/story-editor/getting-started.md)\n* [API Callbacks](./third-party-integration/story-editor/api-callbacks.md)\n* [Integration Layer](./third-party-integration/story-editor/integration-layer.md)\n* [Tutorial](./third-party-integration/story-editor/tutorial.md)\n"
  },
  {
    "path": "docs/accessibility-guidelines.md",
    "content": "# Accessibility Guidelines\n\nThis project follows web accessibility practices and patterns outlined by [WAI-ARIA](https://www.w3.org/WAI/standards-guidelines/aria/) to make the application more accessible to people with disabilities or people using assistive technologies.\n\nPlease submit a ticket if any discrepancies are seen that will be detrimental the accessibility of this application.\n\n## Special Concerns\n\n### Dynamically changing content with Javascript\n\nWhen a portion of a page is updated with JavaScript, the update is usually highlighted with animation and bright colors, and is easy to see. But if you don’t have the ability to see the screen, you don’t know this has happened, unless the updated region is marked as an [ARIA live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions).\n\nThe `useLiveRegion` hook is a simple tool that creates and appends an ARIA live notifications area to the element where developers can dispatch text messages.\n\nAssistive technologies will automatically announce any text change in this area. This ARIA live region has an ARIA role of “status” so it has an implicit aria-live value of polite and an implicit aria-atomic value of true.\n\n**Note**: It’s also possible that all the region content will be announced after an update, if the ARIA live region is too large. Please only provide users with just a simple, concise message.\n\n### Testing Concerns\n\nPlease visit the [accessibility testing](./accessibility-testing.md) documentation for more information.\n"
  },
  {
    "path": "docs/accessibility-testing.md",
    "content": "# Accessibility Testing\n\n## Manual Testing\n\n### Resources\n\n* [Introduction to Keyboard Navigation](https://rianrietveld.com/2016/05/keyboard/)\n\n### Screen Reader\n\n**macOS**: VoiceOver (built-in)\n**Windows**: [NVDA](https://www.nvaccess.org/about-nvda/) (free)\n**ChromeOS**: ChromeVox\n**Browser**: [ChromeVox Classic](https://chrome.google.com/webstore/detail/chromevox-classic-extensi/kgejglhpjiefppelpmljglcjbhoiplfn?hl=en) (no longer supported, so use with care, and perhaps only in combination with NVDA/VoiceOver\n\n### VoiceOver\n\nOn a MacBook, press <kbd><kbd>CMD</kbd><kbd>F5</kbd></kbd> to enable VoiceOver. You can configure VoiceOver using the built-in VoiceOver Utility.\n\nNavigation: Control + Option is the VoiceOver key.\n\nKey | Behavior\n-- | --\nVoiceOver key + left/right arrow | move around the page\nVoiceOver key + command + H | skip to headings\nVoiceOver key + command + J | skip to the next control\nControl | stop verbalization\nVoiceOver key + H > H | display a full list of shortcuts\nVoiceOver key + U | open rotor (which allows you to customize navigation and focus on browser content inside Chrome)\nVoiceOver key + Space | interact with an element\n\nNote: make sure to [enable full keyboard access](http://www.weba11y.com/blog/2014/07/07/keyboard-navigation-in-mac-browsers/) in the macOS system prefs.\n\n### NVDA\n\nTo configure NVDA, press Insert + N or Caps Lock + N and navigate to Preferences.\n\nKey | Behavior\n-- | --\nNVDA key + Arrow | move around the page\nNVDA key + H | skip to headings\nNVDA key + B | skip to buttons\nControl | stop verbalization\n\nMore shortcuts can be found on [WebAIM.org](https://webaim.org/resources/shortcuts/nvda).\n\n### General Info\n\n#### Interaction Modes\n\nThere are two different interaction modes that a screen reader can be navigating in: forms mode and application mode. If keys suddenly stop doing what you expect them to do, you may have unintentionally triggered a mode switch. You likely should restart your screen reader.\n\nSee [Understanding screen reader interaction modes](https://tink.uk/understanding-screen-reader-interaction-modes/) for more information.\n\n#### Accessibility Tree\n\nThe browser converts the DOM tree into an accessibility tree, which is what screen readers interact with. In Chrome, you can view the accessibility tree for easier debugging by going to `chrome://accessibility`.\n\n### Dev Tools\n\nCheck out the [Chrome Dev Tools Accessibility Reference](https://developers.google.com/web/tools/chrome-devtools/accessibility/reference).\n\nThere's also an [aXe extension](https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd) that complements the DevTools built-in feature.\n\n## Unit Tests\n\nUse the `toHaveNoViolations` matcher provided by `jest-axe` to verify that a component does not have any accessibility issues. Example:\n\n```js\nfunction MyAwesomeComponent() {\n  // ...\n}\n\nit('should render with no accessibility issues', async () => {\n    const { container } = render(<MyAwesomeComponent />);\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n});\n```\n\n## Integration Tests\n\nThere's also a `toHaveNoViolations` matcher available in the Karma test suite. Example:\n\n```js\nit('should render with no accessibility issues', async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await expectAsync(fixture.my.custom.element.node).toHaveNoViolations();\n});\n```\n"
  },
  {
    "path": "docs/animations.md",
    "content": "# Animations\n\nAnimations currently reside in `packages/animation`. The top level logic is held in `packages/animation/src/components/provider.js`. This package is responsible for taking a serializable array of animations objects and transforming the objects into WAAPI & AMP animations as well as exposing aggregate animation methods: `pause`, `play`, etc\n\n**Note:** Editing and updating the serializable array of animation objects is considered part of the story editor and held on the page level in the story reducer state.\n\n## Generating an Animation from a Serializable Animation Object\n\nOur serializable animation objects currently have this structure:\n\n```js\n// sample animation object\nconst sampleAnimationObject = {\n  id, // unique identifier for this animation\n  type, // type of animation, `blink`, `bounce` etc.\n  targets, // what elements in the story this animation is targeting\n\n  //...args, whatever args this type of animation takes ie `ease` | `duration`\n  ease,\n  panDir,\n  // etc\n};\n```\n\nThese objects are managed within the story reducer and passed to the animation provider. The animation provider then generates animations by passing this data to the function `AnimationPart(..)` located in `packages/animation/src/parts/index.js`. `AnimationPart(..)` maps the animations instantiation args to a generator function that will generate keyframes, WAAPI animation targets, AMP animation targets, etc.\n\n### Animation Parts & Animation Effects\n\nThere are 2 types of animation generators we have in the editor, the first is an `Animation Part`.\n\n#### Animation Parts\n\nAnimation Parts are more atomic animations that animate one style property and are more configurable. Animation parts are located in `packages/animation/src/parts`. Animation parts are more granular and unopinionated than Animation Effects. \n\ni.e. the `zoom` animation part can animate an elements scale from one value to any other value.\n\n\n#### Animation Effects\n\nThe second type of animations we have are `Effects`. Effects are more complex and opinionated. They are located in `packages/animation/src/effects`. Effects can compose multiple Animation Parts and often take more specified arguments as well as altering keyframe values depending on the element they're being applied to. \n\ni.e. The Background Pan animation effect takes the current offset & zoom of the background image into consideration so the user can't pan the background image past the borders of the page.\n\n#### Utilization of Parts & Effects within the Editor\n\nThe current story editor only uses `Effects` directly. The effects can be seen in the animation selector in the editor when editing an elements style.\n\n#### Deviation in Spec from AMP Story Animation Presets\n\nOur effects roughly mirror [amp_story_animations](https://amp.dev/documentation/examples/visual-effects/amp_story_animations/) but slightly deviate from them. \n\nThe primary deviations in spec come from adding more protection so users don't enter a \"bad\" state with their animation, as well as supporting the concept of background element animations. AMP Stories don't deliniate between background and foreground elements so this behavior is unique to stories created with story editor.\n\n## Parity Between Editor & Output\n\nThe generated animations share common keyframes between two formats, AMP & WAAPI ([Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API)). Parity here is essential so generated amp stories don't deviate from what the user is viewing in the editor when editing & adding animations to a story page.\n\nThe WAAPI animations are used to apply animations to elements within the editor, while the AMP animations are used to apply animations to the generated story. You can view the generated story by clicking `preview` in the editor (next to the `publish` & `save` buttons).\n\n## Integration into the Editor & Output\n\n`packages/animation/src/components` contains the components used to animate elements within the editor. \n\nThe top level logic is contained in the `packages/animation/src/components/provider.js`, which you can see integrated into the story editor at `packages/story-editor/src/components/canvas/displayLayer.js`. `<StoryAnimation.Provider />` takes the story elements & animations, interprets them and applies them to elements.\n\nTarget DOM elements are applied to story element components through animation wrappers. You can see `<StoryAnimation.WAAPIWrapper />` applied to display layer elements in the story editor through `packages/story-editor/src/components/canvas/displayElement.js`. You can see `<StoryAnimation.AMPWrapper />` applied to the generated AMP Story element through `packages/output/src/element.js`.\n\n## Misc Notes & History\n\n### Single Animation Target\n\nIn early specs for animations, we allowed a single animation to have multiple targets (be applied to multiple elements), since then, we have changed this spec to only allow an animation to have a single target element. This new spec is manually enforced in the editor code between the story reducer and the animation effect chooser. \n\nRemnants of this scope change can be seen in the serializable animation objects held in the story reducer state. These animations still take an array of targets even though that array should only ever hold one target while in use in the editor.\n\n### Early Timeline Prototype\n\nFor the initial animation & template implementation we were supporting very complex animations for the templates. Creating these template animations necessitated an internal timeline tool to compose animation parts manually on each template. Since then, we've simplified animations for users and tried to make them parallel the AMP Story Animation presets\n\nIf we do introduce an animation timeline to the editor in the future, here's the reference to the PR where we took out the internal timeline tool:\n[#7067](https://github.com/GoogleForCreators/web-stories-wp/pull/7067)\n\nThe commit hash right before that PR to remove the tool on main is `9b202aa628c6e44`. If you get a local version of that commit hash running, you can view the internal animation timeline tool by opening up the dashboard and navigating to `/story-anim-tool` in the url bar.\n\n"
  },
  {
    "path": "docs/architecture.md",
    "content": "# Architecture\n\n## Design Principles\n\nThe story editor’s architecture follows the following design principles (amongst other more generic ones):\n\n**Whitelabel**:\nThe editor is written from scratch as a modern React codebase, with only thin layers (usually REST endpoints) connecting it to the underlying CMS. This careful design makes it possible to quickly port the editor to subsequent CMS’, beyond WordPress.\n\n**Touch-friendly**:\nThe codebase does not discriminate when it comes to mouse or touch, and uses universal pointer events, touch-friendly tap targets and alternatives for hover UI to work across touch screens, touch pads and mouse.\n\n**Responsive**:\nThe editor does not expect to run full screen, and can adapt to small and very large screen sizes, from iPad to 6K monitors.\n\n**Extensible**:\nThe editor ships with the minimum viable set of media controls, document-level settings, analytics and so on. We’ll produce various integration points to extend the functionality of the editor (media, SEO, …).\n\n**Accessible**:\nMost WYSIWYG editors are not keyboard or screen-reader friendly, and many interactions are not defined in web accessibility specs. This doesn’t stop us from making it a clear goal to provide an excellent experience to the broadest user base possible.\n\n**Smooth**:\nPerformance is not a recommendation, but a hard requirement. All user actions must have a visual response in less  than 100ms, and continuous animation (like scrolling etc.) needs to update at 60fps generally, and 30 fps as fallback (no in-between).\n\n## Browser Support\n\nSee [detailed docs](./browser-support.md) on browser and device support.\n\n## Editor\n\n* [Canvas Layering](./canvas.md)\n"
  },
  {
    "path": "docs/browser-support.md",
    "content": "# Browser and device support\n\nWe support roughly the same set of browsers as the AMP Project to align with the AMP story runtime, with additional form factor limitations. In practice, this means:\n\n* The latest **two versions of all major browsers** (currently Chrome, Firefox, Edge, Safari and Opera)\n* We support **desktop & tablet versions** of these respective browsers\n* We accept fixes for all browsers with market share greater than 1 percent\n\n**Internet Explorer** is explicitly **not** supported.\n"
  },
  {
    "path": "docs/canvas.md",
    "content": "# Canvas\n\n## Layers\n\n![Canvas Layers](https://user-images.githubusercontent.com/726049/72654503-bfffe780-3944-11ea-912c-fc54d68b6100.png)\n"
  },
  {
    "path": "docs/cdn.md",
    "content": "# CDN\n\nLarge assets to be used by the plugin are hosted on the [wp.stories.google](https://wp.stories.google) site instead of being bundled with the plugin.\n\nThis includes, but is not limited to, assets for these areas:\n\n* Plugin activation message\n* Get Started story (FTUE)\n* Templates\n* Help Center (FTUE)\n\nAssets are versioned. Whenever new assets have been added, or existing assets modified, the version will be incremented upon the next release.\n\n## Git LFS\n\nTo keep repository size reasonable, CDN assets are stored with [Git Large File Storage (LFS)](https://docs.github.com/en/github/managing-large-files/about-git-large-file-storage).\n\nIn order to be able to add new assets, you have to [install Git LFS](https://docs.github.com/en/github/managing-large-files/installing-git-large-file-storage) on your machine.\n\nYou can download it from [git-lfs.github.com](https://git-lfs.github.com/) (or use `brew install git-lfs` if you're on Mac).\n\nVerify that the installation was successful:\n\n```bash\n$ git lfs install\n> Git LFS initialized.\n```\n\n**Note:** If the above command prints warning regarding pre-existing Git hooks, run `git lfs update --manual` for instructions on how to merge hooks.\n\n## Adding Assets\n\n**Important:** Make sure Git LFS is installed!\n\nFirst, add the new assets to the CDN by following these steps:\n\n1. Clone the [GoogleForCreators/wp.stories.google](https://github.com/GoogleForCreators/wp.stories.google) repo.\n2. Modify/add assets as desired in the `public/static/main` folder.\n3. Create a new pull request with these changes.\n\n## Usage in the plugin\n\nBy default, the plugin will load assets from the `public/static/main` folder.\n\nOnly production builds released on WordPress.org will reference the versioned folder, e.g. `puiblic/static/123`.\n\n## Plugin Release\n\nUpon release, the `public/static/main` folder is compared against the latest version.\nIf there are changes in `main`, the folder is copied to `public/static/<latest+1>`.\n"
  },
  {
    "path": "docs/checklist.md",
    "content": "# Checklist \n\nThe Prepublish Checklist to help users make the best Stories possible.\n\n## Logic \n\n- On an empty story none of the checklist categories are visible\n- When a story has more than one page the design and accessibility  sections are visible\n- When a story has more than 4 pages the high  priority section is also available. \n- If a user attempts to publish a story that's less than 5 pages they'll get a prompt to review the checklist first. That exposes all of the checklist sections. \n\n## Structure\n\n- All checks are nested in checklist/checks, the logic and requirements for each check are stored here. They render their own component based on the  check and that component is given  to the checklist category to render making the list self contained.\n\n## Adding a new check\n\n- Follow patterning in `checklist/checks`. The logic for the check should be kept internal to the check itself. \n- Give it a unique name when hooking into `useRegisterCheck`, this is what tracks issue counts.\n- Tests for checks are stored in `checklist/checks/test`. \n\n## Context\n\nComes in three sections. You need varying degrees of access depending on where you are in the app. \n\n- CheckpointProvider: Wraps around Layout so that the publish  button also has access to the current checkpoint. If requirements are met then a dialog appears prompting the  user to review the checklist before publishing.\n- ChecklistProvider: Wraps around the carousel so that the toggle buttons in the secondary menu know when the checklist is open and the other popup menus there (help center) can respect it. \n- ChecklistCountProvider, ChecklistCategoryProvider: Wrap around various parts of the checklist itself to provide counts of issues.\n\n## Roles\n\nDepending on the user's `role`, the user may or may not be able to fix specific checklist items. A checklist card will be hidden if the user is unable to fix the issue.\n\nThis is outlined in the table below:\n\n|Story issue/card|Role(s) necessary to resolve the issue|\n|--|--|\n|Story has no poster image attached|`hasUploadMediaAction`|\n|Increase poster image's size|`hasUploadMediaAction`|\n|Increase poster images's aspect ratio|`hasUploadMediaAction`|\n|Increase publisher logo size|`hasUploadMediaAction`|\n|Video missing poster image|`hasUploadMediaAction`|\n|Video not optimized|`hasUploadMediaAction`|\n|Video element resolution too low|`hasUploadMediaAction`|\n|Media element resolution too low|`hasUploadMediaAction`|\n|Video element missing captions|`hasUploadMediaAction`|\n\n## Future  Improvements\n\n- Now that the checklist has self contained checks there's room to improve perf on one off situations. \n- Add role based checks \n"
  },
  {
    "path": "docs/code-style.md",
    "content": "# Code Style\n\n## Formatting\n\nLinting is done through [ESLint](https://eslint.org/), code formatting is handled by [Prettier](https://prettier.io/), but integrated with ESLint.\n\n## Organizing Components\n\nRule of thumb: small components belong to `index.js` file.\nLarger ones should be split up and moved in a folder, where `index.js` exports the public parts of it.\n\n## Naming Conventions\n\n* Use `camelCase` for file names\n* Use `PascalCase` for component names (components should always be named!)\n"
  },
  {
    "path": "docs/design-docs.md",
    "content": "# Design docs\n\nMost of these docs are in Google Docs for ease of modification and commenting.\n\n* [Story Editor e2e Testing Ideas](https://docs.google.com/document/d/1kKu8QRPYNtLjhc3botd4sEIwPnUSemLXFyNPIw8Pf50/edit#)\n"
  },
  {
    "path": "docs/design-panel-push-update-flow.md",
    "content": "# Design Panel Element Update Data Flow\n\nBelow is a rough outline of the data flow following input change updates in the design panel to how they update the element in the top level story provider. Most of this code can be found in `packages/story-editor/src/components/style/designPanel.js` :\n\n```mermaid\nflowchart TB\n    subgraph story_reducer[story reducer]\n        direction LR\n        subgraph ACTION\n            direction TB\n            L[UPDATE_ELEMENTS] --> M[Story Updated]\n        end\n    end\n    subgraph design_panels[StylePanels]\n        subgraph design_panel_state[State]\n            direction TB\n            design_panel_state_el_updates((elementUpdates Array))\n            design_panel_state_el_handlers((presubmitHandlers Array))\n        end\n        subgraph design_panel_callbacks[Callbacks]\n            direction LR\n            subgraph submit_handler[submit handler]\n                subgraph SUBMIT [ ]\n                    direction TB\n                    E[onSubmit] --> F[[internalSubmit]]\n                    F --> G[[apply presubmit element mutations on all staged elementUpdates]]\n                    G --> H[[onSetProperties]]\n                    H --> I[updateElementsById]\n                end\n            end\n            subgraph submit_event[submit event]\n                subgraph DOM EVENT FIRED [ ]\n                    direction TB\n                    K{Dispatch Event - 'submit'}\n                end\n            end\n            subgraph push_update[pushUpdate called]\n                subgraph INPUT ONCHANGE[ ]\n                    direction TB\n                    A[pushUpdate or pushUpdateForObject] --> |update, submit| B[[setElementUpdates - Add update to update queue]]\n                    B -->|submit == false| C[elementUpdates - locally stored updates]\n                    B --> |submit == true| D[submit]\n                    D --> J[[setTimeout to dispatch 'submit' event]]\n                end\n            end\n        end\n    end\n       push_update .-> submit_event\n       submit_event .-> submit_handler\n       design_panels .-> story_reducer\n```\n\n## Current Usage\n\nMost of the time, we are passing `submit` as `true` for the `pushUpdate(update, submit)` or `pushUpdateForObject(...)` callback args. The current setup is mainly used so the presubmit hooks can alter an update to an element before sending the element updates to the story reducer. Most precommit hooks do things like clamp a value within a certain range, or resize the text element depending on updates to text properties.\n\n"
  },
  {
    "path": "docs/design-system.md",
    "content": "# Design System\n\n## Overview\n\nWeb Stories exists as two apps right now, the editor and the dashboard. Both have their own set of components that they are built off of. Now that we have a robust design system [in Figma](https://www.figma.com/file/bMhG3KyrJF8vIAODgmbeqT/Design-System?node-id=1906%3A0), we won't need to duplicate foundational and base components by having separate copies in the editor and dashboard. The idea here is to make this transition as painless as possible, no massive structural changes. This is a consolidation of components and themes.\n\n## What goes in the design system?\n\nThe Design System is **only** for shared basics and components. In [atomic design terms](https://bradfrost.com/blog/post/atomic-web-design) we are sharing atoms, molecules and (some) organisms.  If it is a small pattern that’s repeated in a more complicated structure (like a menu that’s used in a dropDown, a search component and a popover menu) then that structure should exist in the design system. If it’s shared across both the editor and the dashboard, it should exist in the design system - like a button or a dialog.\n\nIf it’s something complex only used by the editor, say the color picker, which uses a slider and some other smaller components in the design system, the color picker would live in the editor because it is not shared by the dashboard. Things that are not easily generalized should not live in the design system.\n\n## Theme\n\nThe design system contains a full new color palette and theme. The structure is changing a little bit to try and keep things more organized. You can dig into the app [packages/design-system/src/theme](../packages/design-system/src/index.js) to see organization. Here’s brief overview of the organization to contextualize what you’re looking at.\n\n1. Colors, Typography, Borders, Breakpoints are in separate files and all added to the [theme index](../packages/design-system/src/theme/index.js) that can be ingested at the root of each app. This file separation makes it easier to find theme values for developers who prefer to look in source code for the value they need.\n2. The new theme provides a dark and a light variant. Dark is the default. All colors are available regardless of variant, but the `theme.colors.bg` and `theme.colors.fg` are what you should gravitate towards using because the light and dark theme colors mirror each other. This will make dark and light mode functionality easier to handle down the road.\n3. Subdirectory called [helpers](../packages/design-system/src/theme/helpers/index.js) - these are styles meant to be quick references for one off components in the editor and dashboard that aren’t in the design system. They’re also used in the design system for continuity.\n4. Subdirectory called [global](../packages/design-system/src/theme/global/index.js) - these are exported as `ThemeGlobals` and should be added to the app root to handle global styles for both the dashboard and editor.\n5. Subdirectory called [constants](../packages/design-system/src/theme/constants/index.js) - these are constants that are used in the dashboard, the editor and across the  design system so that we can have a single source of truth. You can import them via `THEME _CONSTANTS`. These include things like static widths of wordPress menus that all projects reference.\n\nIt’s important to note that this is a living resource - we fully anticipate the need to add to the theme as we begin to use it more robustly. The design system is being created iteratively as we go through implementing new designs. If there’s a new need for a helper, add it! If there’s a color lacking, add it in following the existing patterns. Our goal here was to create a base that we could easily keep updated to avoid needless duplication.\n\n## Components\n\nThe hope here is to make the transition to using the components in the design system straightforward and easy. If a component in the design system already existed in the editor or dashboard, that source code was used as a reference for the new one in almost all cases. Props should be the same or similar for components that were based off of existing code.\n\n### Differences from the editor\n\n- Icon buttons are now a button type where you give the icon to the button instead of specific button components.\n- Button refs are readily available\n- Typography is available in molecules - there’s `Display`, `Headline`, `Text`, and `Link` that match the figma specs for type and can take in a styled component `as` of `forwardedAs` to keep HTML semantic but avoid needlessly styling each text element. If you do need to do that there’s a `themeHelpers.expandPresetStyles` or `themehelpers.expandTextPreset` you can look to.\n\n### How to add components to the design system\n\nThere are going to be things missing from the design system. Designs have been in flux and we’ve been adding things as we need them in the redesign. That said, feel free to add missing components. Components live in [design-system/components](../packages/design-system/src/components/index.js). This directory’s pretty flat so that things are easy to find at 1 level.  The general rule here, as with any shared design system, is that we keep things generic and non-opinionated as much as possible so that the usability remains flexible. All components have storybook demos that allow all props passed to the component to be seen as `controls` as well as dark and light versions so that theme colors can be checked.\n\n### Some caveats\n\nButtons!\n-The designs have 3 types of buttons: Primary, Secondary, Tertiary. The difference between a secondary button and a tertiary button is the active state.\n\n- There’s a 4th type of button in the design system called Plain - this button type has no styles, it’s just a reset button without any outline or background color that can be used when we need something to semantically be a button but the designs disagree. This shouldn’t happen often and should be a bit of an escape hatch.\n- Button variants in the designs are square and rectangle. The additional variants of circle and icon were added because there are occasions in the editor and dashboard where there are no shared button styles but the element is expected to behave as a button. By having a button variant of icon we can eliminate the need of having specific exportable buttons like `ArrowDown`.\n- Button types, sizes, and variants (circle, rectangle, square, icon) are all available as [constants](../packages/design-system/src/components/button/constants.js) and importable via `BUTTON_TYPES`, `BUTTON_SIZES`, `BUTTON_VARIANTS` so that we don’t have to worry about miscellaneous strings.\n- Every button combination has a [demo in storybook](https://googleforcreators.github.io/web-stories-wp/storybook/?path=/story/designsystem-components-button--default).\n\nTypography\n\n- [design-system/typography](../packages/design-system/src/components/typography/index.js) has the only nested content. This follows the foundation set up in the designs of `Display`, `Headline`, `Label`, `Paragraph`, `Link`.\n- Each typography type has a set of presets that are stored in the theme and matching constants ([theme/constants/typography](../packages/design-system/src/theme/constants/typography.js)).\n- The typography components are `<Display />`, `<Headline />`, `<Link />`, `<Text />`, found in [`components/typography`](../packages/design-system/src/components/typography/index.js).\n- Each is a styled component and can be passed whatever element you want it to be with `as` or `forwardedAs` depending on your situation.\n- These are meant to decrease our need to individually style text elements and ensure consistency.\n- There’s a demo for every [type setting in storybook](https://googleforcreators.github.io/web-stories-wp/storybook/?path=/story/designsystem-components-typography-display--default).\n\nCircular dependencies\n\n- If you are adding a component and you need to reference anything in the design-system you’ll need to import it from its nearest location. Do not import it from the top level index.\n- While this works just fine in the app (because you’re outside of the design system), storybook will yell at you because it thinks that imports aren’t loaded in time.\n- As an example, I’m creating this new `<Taco />` and I need a `<Text />` component. I’d need to `import { Text } from ‘../typography’;` not `../` if I’m in `components/taco`.\n\n## Icons\n\nIcons are separated from components and already exported as `ReactComponent` . You can import them via `/theme/icons` or `/theme`.\n\n### How to add icons\n\nIcons are all located directly in the `design-system/icons/` folder. A few things to note:\n\n- All icons are 32x32px and should never be resized or scaled in any way.\n- Icons are named after their symbol, not their function. So a ⚙️  icon is named `Gear`, and not `Settings` or some other function, it might serve.\n- If an icon has several sizes, denote this as a suffix as `GearLarge`, `GearTiny` etc.\n- If an icon has a border, name it either just as `GearOutline` or as the shape of the border - e.g. `GearTriangle` if it's a gear inside a triangular border.\n- Try to group similar icons alphabetically, so name icons e.g. `MagnifierPlus` and `MagnifierMinus` rather than `PlusMagnifier` and `MinusMagnifier`.\n\nThe process for adding an icon is as follows:\n\n1. Export your SVG from Figma by selecting the 32x32px icon boundary box and selecting _\"Export\"_ in the right panel\n2. Add the file to directory [design-system/icons](../packages/design-system/src/icons/index.js)\n3. Export it from the index of that directory as a ReactComponent (please alphabetize the list, thanks!)\n4. Import from the design-system wherever you want to use it.\n"
  },
  {
    "path": "docs/devtools.md",
    "content": "# DevTools\n\nThere is a global shortcut (`Command+Shift+Option+J / Control+Shift+Alt+J`) for the editor DevTools.\n\n## Sharing story data\n\nYou can use DevTools to import/export the story data and optionally replace all media resources with placeholders.\n"
  },
  {
    "path": "docs/e2e-tests.md",
    "content": "# End-to-End Tests\n\nThis project leverages the [local Docker-based environment](./local-environment.md) to facilitate end-to-end (e2e) testing using [Puppeteer](https://github.com/puppeteer/puppeteer).\n\nAs with the [JavaScript unit tests](./unit-tests.md), Jest is used as the task runner.\n\nTests are written using [`jest-puppeteer`](https://github.com/smooth-code/jest-puppeteer).\n\nTests are written using the [Jest API](https://jestjs.io/docs/en/api) in combination with the [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md), facilitated by [`jest-puppeteer`](https://github.com/smooth-code/jest-puppeteer).\n\nTo run the full test suite, you can use the following command:\n\n```bash\nnpm run test:e2e\n```\n\nYou can also watch for any file changes and only run tests that failed or have been modified:\n\n```bash\nnpm run test:e2e:watch\n```\n\nNot using the built-in local environment? Set the `WP_BASE_URL` environment variable to point to your URL of choice.\n\n```bash\nWP_BASE_URL=https://web-stories.local npm run test:e2e\n```\n\n**Note**:\nAll tests run serially in the current process using the `--runInBand` Jest CLI option to avoid conflicts between tests. This is caused by the fact that they share the same WordPress instance.\n\n## Environment Variables\n\nCheck out the [separate document](./environment-variables.md) about supported environment variables for tweaking the E2E tests.\n\n## Debugging\n\nFor debugging purposes, you can also run the E2E tests in non-headless mode:\n\n```bash\nnpm run test:e2e:interactive\n```\n\nNote that this will also slow down all interactions during tests by 80ms. You can control these values individually too:\n\n```bash\nPUPPETEER_HEADLESS=false npm run test:e2e # Interactive mode, normal speed.\nPUPPETEER_SLOWMO=200 npm run test:e2e # Headless mode, slowed down by 200ms.\n```\n\nIt's also possible to enable node's inspector agent for the tests as follows:\n\n```bash\nnpm run test:e2e:debug\n```\n\nSince these tests run both in the node context and the browser context, not all lines of code can have breakpoints set within the inspector client. Only the node context is debugged in the inspector client.\n\nThe code executed in the node context includes all of the test files excluding code within `page.evaluate` functions. This is because the `page.evaluate` functions are executed within the browser context.\n\nTo also debug the browser context, set `PUPPETEER_DEVTOOLS=true` and `PUPPETEER_HEADLESS=false` when running the `test:e2e:debug` script.\nThis will launch the browser with the devtools already open. Breakpoints can then be set in the browser context within devtools. \n\n## Common Mistakes\n\n* Missing `await` on statements/assertions.\n* Not waiting for an element to be present in DOM and to be visible before trying to interacting with it (race conditions).\n\n## Writing Tests\n\n### Useful Resources\n\n* [`jest-puppeteer`](https://github.com/smooth-code/jest-puppeteer#api)\n* [`expect-puppeteer`](https://github.com/smooth-code/jest-puppeteer/blob/master/packages/expect-puppeteer/README.md#api)\n* [Available WordPress-specific test utils](https://www.npmjs.com/package/@wordpress/e2e-test-utils) (e.g. `loginUser`, `visitAdminPage`)\n\n## Test Utilities\n\nSometimes one might want to test additional scenarios that aren't possible in a WordPress installation out of the box. The tests setup allows adding some utility plugins that can be activated during E2E tests.\n\nThese plugins can be added to `packages/e2e-tests/src/plugins` and then activated via the WordPress admin.\n\nTest utilities like `createNewStory()` reside in the `packages/e2e-test-utils/src` folder.\n"
  },
  {
    "path": "docs/environment-variables.md",
    "content": "# Environment Variables\n\nThroughout the project some environment variables are in use:\n\n## Application\n\n**DISABLE_PREVENT** (bool):\nSet this environment variable to disable unwanted `beforeunload` dialogs when reloading or closing the browser. Mostly useful during development. Default: `false`\n\n**DISABLE_OPTIMIZED_RENDERING** (bool):\nSet this environment variable to disable optimized rendering for text sets (it will render the actual components instead of images). Required for text sets images generation script. Default: `false`\n\n**DISABLE_QUICK_TIPS** (bool):\nSet this environment variable to prevent quick tips from automatically opening. Default: `false`\n\n## Bundler\n\n**NODE_ENV** (`production`|`development`|`test`):\nDefines the mode webpack and other tools operate in. Automatically set by tests / build tools, usually no need to override manually.\n\n**BUNDLE_ANALYZER** (bool):\nEnables the `webpack-bundle-analyzer` plugin to analyze the final bundle composition. Default: `false`\n\n**BABEL_CACHE_DIRECTORY** (string):\nBabel uses a directory within local node_modules by default. Use the environment variable option to enable more persistent caching.\n\n## E2E Tests\n\n**PUPPETEER_TIMEOUT** (number):\nSet the default Jest timeout for Puppeteer test. It is already increased because these tests are a bit slow due to the browser overhead. Default: `100000` (ms)\n\n**EXPECT_PUPPETEER_TIMEOUT** (number):\nSet default timeout for individual expect-puppeteer assertions. Default: `500` (ms)\n\n**WP_BASE_URL** (string):\nPoint the E2E tests to a different URL, i.e. when not using the built-in Docker environment. Default: `http://localhost:8899`.\n\n**WP_USERNAME** (string):\nUsername to use for logging in during E2E tests. Default: `admin`\n\n**WP_PASSWORD** (string):\nPassword to use for logging in during E2E tests. Default: `password`\n\n**PUPPETEER_PRODUCT** (string):\nEither `chrome` or `firefox`. Default: `chrome`\n\n**PUPPETEER_HEADLESS** (bool):\nWhether to run Puppeteer in headless mode or not. Default: `true`\n\n**PUPPETEER_SLOWMO** (number):\nSlow down all interactions by a certain time for easier debugging. Useful in combination with `PUPPETEER_HEADLESS`. Default: `0` (ms)\n\n**PUPPETEER_DEVTOOLS** (bool):\nWhether to open dev tools during tests. Default: `false`\n\n## Local Environment\n\n**PHP_VERSION** (string):\nPHP version which local environment runs in. Default: `8.2` \n"
  },
  {
    "path": "docs/external-template-creation.md",
    "content": "# Creating a new template\n\n## Where things are stored\n\n- The **story JSON representation** for each template is stored in [`packages/templates/src/raw/`](https://github.com/googleforcreators/web-stories-wp/tree/main/packages/templates/src/raw) (in the `main` branch).\n- The **SVGs** used in each template are stored in [`packages/stickers/src/`](https://github.com/googleforcreators/web-stories-wp/tree/main/packages/stickers/src) (in the `main` branch).\n- The (non-SVG) **image &amp; video files** used in each template are stored in [`public/static/main/images/templates/`](https://github.com/GoogleForCreators/wp.stories.google/tree/main/public/static/main/images/templates) (in the [GoogleForCreators/wp.stories.google](https://github.com/GoogleForCreators/wp.stories.google) repo, using [Git LFS](https://git-lfs.github.com/)).\n\n## Overview\n\nTo add a new template to the editor:\n\n1. [Engineer] Commit all SVGs used in the template to the codebase as stickers ([details](#adding-svgs-to-the-codebase-as-stickers)).\n2. [Designer] Create a new story in your shared WP environment and replicate the template design.\n    - SVGs should already be available in the Stickers panel from step (1) &mdash; click on a sticker to insert it into the story.\n    - Upload (drag & drop) images and videos into the story to add them.\n3. [Engineer] Commit all images & videos used in the template to the codebase.\n    - Filenames should follow the existing convention e.g. `travel_page9_bg.jpg`.\n    - Make sure images are not too large &mdash; full-width images should be 1080p, large images should be 720p, and small images should be 480p. See [#6485](https://github.com/googleforcreators/web-stories-wp/pull/6485) for an example.\n    - Make sure videos are 720p.\n    - Make sure caption files are also committed along with the videos, when available.\n4. [Engineer] Get the story JSON from your shared WP environment, modify its image & video URLs, and integrate it into the codebase (see [details](#get-the-story-json)).\n5. [Both] Verify that new template shows up in the template library and looks as expected.\n\n## Pitfalls\n\n1. Don't upload SVGs as images. SVGs should only be added as stickers in step (1).\n2. Avoid \"`-<number>`\" suffixes on images and videos e.g. `some_image-1.png`. See [details below](#filenames-for-images-and-videos).\n3. Don't add animations to the first page.  First page animations are not supported by AMP. [More details](https://wp.stories.google/docs/how-to/animations/#First-Page)\n\n## Detailed steps\n\n### Adding SVGs to the codebase as stickers\n\nTo add new stickers to the codebase, obtain the raw svg file, and view it in your code editor. Paste the contents of the raw svg file into a react component in `packages/stickers/src/<template_name>/<sticker_name>.js`.\n\nRemove extraneous attributes on the base `svg` component and make sure your component takes a `style` property that it applies to the base svg element. Also make sure to remove any explicit `height` and `width` attributes and see that they only are applied to the viewbox. Lastly, be sure to add a title for accessibility. By the end, your component should look something like this:\n\n```js\nconst title = __('Some Descriptor', 'web-stories');\nfunction MySticker({ style }) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 <width> <height>\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      {/*Contents*/}\n    </svg>\n  );\n}\n```\n\nAt the bottom of the file, make sure there's one default export that exports the svg component and the aspect ratio based off the viewbox as well as the human readable title:\n\n```js\nexport default {\n  aspectRatio: width / height,\n  svg: MySticker,\n  title,\n};\n```\n\nCreate a new `index.js` file under your `<template_name>` directory and add your new sticker to the export object:\n\n```js\n//...\nexport { default as  mySticker } from './mySticker';\n```\n\nThe last step of this process is navigating to `packages/stickers/src/index.js` and adding your new stickers to the default export object:\n\n```js\n//...\nimport * as myStickers from './<template_name>';\nexport default {\n  //...\n  ...myStickers,\n};\n```\n\nOnce you've completed this step, your new sticker should now appear with the other stickers appended to the bottom of the shapes panel.\n\n### Inserting stickers (SVGs) into a story\n\nTo add stickers to your template story, go to the `Experiments` page (in the left-hand sidebar under the `Stories` section) and check the `Enable Stickers` checkbox.\n\nOnce turned on, all available stickers in the codebase should be available for selection under our base shapes in the shapes library panel.\n\n### Get the story JSON\n\nTo get the JSON representation of a story in the editor:\n\n1. In the editor, open the story.\n2. Press `Command+Shift+Option+J` (Mac) or `Control+Shift+Alt+J` (Windows/Linux) in the editor.\n3. A dialog will appear where you can copy/paste story JSON.\n4. Check the `Template` checkbox that is present at the top of the dialog.\n\n   <img width=\"554\" alt=\"Screenshot of the dev tools with the Templates checkbox\" src=\"https://user-images.githubusercontent.com/6906779/125189481-efe82c80-e255-11eb-93dd-ca875d514f54.png\">\n\n\n#### Alternative\n\nAnother way to get the story JSON is by inspecting the network request that saves the story to the backend.\n\n1. In the editor, open the story.\n2. Open `Chrome DevTools > Network`.\n3. In the editor, click the \"Save draft\" button.\n4. You should see a POST XHR with JSON in the request payload. In that payload JSON, find and right-click the `story_data` field and click `Copy value`.\n5. The story JSON should now be copied to your clipboard and ready to paste into a new file.\n\n### Adding story JSON to the codebase as a new template\n\nOnce you have the story JSON, several code changes are needed to add it to the list of default templates in the editor.\n\n1. In [`packages/templates/src/raw/`](https://github.com/googleforcreators/web-stories-wp/tree/main/packages/templates/src/raw), create a new directory `<template_name>` for your template. Now add your template's story JSON in a new file e.g. `<template_name>/template.json`.\n   - Make following changes to the template JSON,\n      - Reset following extraneous properties,\n        - `current: null`\n        - `selection: []`\n        - `story: {}`\n      - First change all image & video URLs to use `__WEB_STORIES_TEMPLATE_BASE_URL__` as the base, which then will be replaced by the CDN url.\n      - Ensure to also change poster image URLs to use `__WEB_STORIES_TEMPLATE_BASE_URL__`.\n      - Change `posterId` and `id` for all elements of type image and video to `0`, these are the WP media ids that are not used in templates.\n      - Make sure that the images and videos have appropriate title and alt text set for better accessibility.\n\n   - If the story JSON is copied from the devTools dialog as mentioned  in [Get The Story JSON](#get-the-story-json), the JSON will have some of the changes already present.\n     - The 'Template' checkbox does following:\n       - Resets extraneous properties.\n       - Changes resource URLs to use replaceable CDN constant\n       - Resets `sizes` property for images to `[]`.\n       - Resets all `id` and `posterId` to 0 for image and video type resources.\n\n      NOTE: Check all resource URLs and properties are set properly before committing the template.\n      \n2. Create a new file `metaData.js` in your newly created `<template_name>` directory. Your `<template_name>/metaData.js` file would then look something like this with object corresponding to the new template and properties `id`, `title`, `tags`, `colors`, `creationDate`, etc. \n\n    ```javascript\n       //...\n      /**\n       * External dependencies\n       */\n      import { __, _x } from '@googleforcreators/i18n';\n\n      export default {\n        slug: 'template-name',\n        creationDate: '2021-07-12T00:00:00.000Z',\n        title: _x('Your Template Title', 'template name', 'web-stories'),\n        tags: [\n          _x('Tags', 'template keyword', 'web-stories'),\n        ],\n        // Array of color objects with name and hex values.\n        colors: [\n          { label: _x('Blue', 'color', 'web-stories'), color: '#1f2a2e' },\n        ],\n        description: __(\n          'A short text describing your story template.',\n        'web-stories'\n        ),\n        vertical: _x('Vertical name', 'template vertical', 'web-stories'),\n      };\n    ```\n\n3. Create a new file `index.js` in your newly created `<template_name>` directory and import the `template.json` file and `metaData.js` file. Your `<template_name>/index.js` file would then look something like this:\n\n    ```javascript\n      //...\n      /**\n       * Internal dependencies\n       */\n      import { default as template } from './template';\n      import { default as metaData } from './metaData';\n\n      export default {\n        ...metaData,\n        ...template,\n      };\n    ```\n\n4. In [`packages/templates/src/getTemplates.ts`](https://github.com/googleforcreators/web-stories-wp/blob/main/packages/templates/src/getTemplates.ts), add `\"<template_name>\"` to the string array in the `getTemplates()` function.\n5. Verify in your WP environment that the new template is visible in the editor's \"Explore Templates\" section.\n6. Create a single pull request with all of the changes in steps 1-3.\n\n### Adding SVGs to the codebase as shapes\n\nFirst and foremost, shapes aren't complete svgs, just a single normalized path (coordinates should be defined in a 0->1 space). To accommodate for this, there are a few formatting steps that must be taken in an svg editing software (like illustrator), and a few steps within the codebase to get a proper working path in the editor.\n\n#### Getting your svg to be a single path\n\nSince we must have a single path, we can't utilize any other aspects of the svg spec. This means all shapes must be converted to a single path in the svg editing software of your choosing. For the purposes here, we will outline the steps in illustrator because it's what we've used thus far, but these svg operations should be applicable to other programs as well.\n\n- Open svg file in illustrator\n- Select shape\n- (If there's any stroke) Click on `Object -> Path -> Outline Stroke`\n- Make sure your shape is selected and click `Object -> Compound Path -> Make`\n- Open your code editor to any scratch pad svg file (will just be using this file for copy and pasting, won't save it at all)\n- Select svg in illustrator and copy\n- Paste into your code editor\n\nIn your editor, you should see something like this:\n\n```svg\n<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In  -->\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"392px\"\n\t height=\"392px\" viewBox=\"0 0 392 392\" style=\"enable-background:new 0 0 392 392;\" xml:space=\"preserve\">\n<style type=\"text/css\">\n\t.st0{fill:#FFFFFF;}\n</style>\n<defs>\n</defs>\n<path class=\"st0\" d=\"M392,196c0,108.25-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0S392,87.75,392,196z M196,30\n\tc-44.34,0-86.03,17.27-117.38,48.62C47.27,109.97,30,151.66,30,196s17.27,86.03,48.62,117.38C109.97,344.73,151.66,362,196,362\n\ts86.03-17.27,117.38-48.62C344.73,282.03,362,240.34,362,196s-17.27-86.03-48.62-117.38C282.03,47.27,240.34,30,196,30 M196,0\n\tc108.25,0,196,87.75,196,196s-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0L196,0z\"/>\n</svg>\n```\n\nIf your svg markup consists of anything other than a single path, you must go back to your svg editing application and keep playing with it until you can copy the svg into your code editor and it only consists of a single path.\n\nIn the path's `d` attribute you'll see a mix of numbers and letters. The letters are draw commands and the numbers after it specify coordinate arguments for the draw command. Those coordinates are drawn relative to the coordinate space depicted in the `viewBox` attribute. It's important that the path fits nicely in the viewbox. For Illustrator it creates the viewbox & path coordinates based on the bounding box of all selected elements you're copying onto your clipboard. If you need to alter the path to be drawn relative to a slightly larger viewbox, you can always place a square/rectangle (larger than original selected elements) within the selected elements before copying over to your editor to dictate the size of the viewbox and illustrator will update the path coordinates accordingly.\n\n#### Normalizing your svg path\n\nAll the SVG paths in the shapes panel are declared in a 0->1 coordinate space. In theory you could scale down your SVG in illustrator and it would update the path coordinates accordingly, but we found that Illustrator lacks the level of precision needed for large shapes with small details.\nThis can lead to necessary parts of your path getting rounded off. To accommodate for this, we created a little node script you can run your SVG path through and it will normalize the path with a much higher level of precision that won't round off details in your shape.\n\nThis script is available via in `npm run workflow:normalize-path`. You'll need to copy the path and viewbox from your scratchpad svg file and pass them to the command like so:\n\nYou can then run the command like so:\n\n```bash\nnpm run workflow:normalize-path 392 392 \"M392,196c0,108.25-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0S392,87.75,392,196z M196,30 c-44.34,0-86.03,17.27-117.38,48.62C47.27,109.97,30,151.66,30,196s17.27,86.03,48.62,117.38C109.97,344.73,151.66,362,196,362 s86.03-17.27,117.38-48.62C344.73,282.03,362,240.34,362,196s-17.27-86.03-48.62-117.38C282.03,47.27,240.34,30,196,30 M196,0 c108.25,0,196,87.75,196,196s-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0L196,0z\"\n```\n\nIt should output a normalized path like this in the console:\n\n```text\nM 1.000000 , 0.500000 c 0.000000 , 0.276148 -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 S 1.000000 , 0.223852 , 1.000000 , 0.500000 z  M 0.500000 , 0.076531 c -0.113112 , 0.000000 -0.219464 , 0.044056 -0.299439 , 0.124031 C 0.120587 , 0.280536 , 0.076531 , 0.386888 , 0.076531 , 0.500000 s 0.044056 , 0.219464 , 0.124031 , 0.299439 C 0.280536 , 0.879413 , 0.386888 , 0.923469 , 0.500000 , 0.923469 s 0.219464 -0.044056 , 0.299439 -0.124031 C 0.879413 , 0.719464 , 0.923469 , 0.613112 , 0.923469 , 0.500000 s -0.044056 -0.219464 -0.124031 -0.299439 C 0.719464 , 0.120587 , 0.613112 , 0.076531 , 0.500000 , 0.076531 M 0.500000 , 0.000000 c 0.276148 , 0.000000 , 0.500000 , 0.223852 , 0.500000 , 0.500000 s -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 L 0.500000 , 0.000000 z\n```\n\n#### Creating a shape from your normalized path\n\nCopy the outputted path from your terminal and navigate to `packages/story-editor/src/masks/constants.js`. In that file create a new key describing your shape in `MaskTypes`. For the shape shown above an apt description would be something like:\n\n```javascript\nexport const MaskTypes = {\n  // ...,\n  [RING]: 'ring',\n};\n```\n\nThen navigate down to `CLIP_PATHS` and add your normalized path like so:\n\n```javascript\nconst CLIP_PATHS = {\n  // ...,\n  [MaskTypes.RING]: `M 1.000000 , 0.500000 c 0.000000 , 0.276148 -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 S 1.000000 , 0.223852 , 1.000000 , 0.500000 z  M 0.500000 , 0.076531 c -0.113112 , 0.000000 -0.219464 , 0.044056 -0.299439 , 0.124031 C 0.120587 , 0.280536 , 0.076531 , 0.386888 , 0.076531 , 0.500000 s 0.044056 , 0.219464 , 0.124031 , 0.299439 C 0.280536 , 0.879413 , 0.386888 , 0.923469 , 0.500000 , 0.923469 s 0.219464 -0.044056 , 0.299439 -0.124031 C 0.879413 , 0.719464 , 0.923469 , 0.613112 , 0.923469 , 0.500000 s -0.044056 -0.219464 -0.124031 -0.299439 C 0.719464 , 0.120587 , 0.613112 , 0.076531 , 0.500000 , 0.076531 M 0.500000 , 0.000000 c 0.276148 , 0.000000 , 0.500000 , 0.223852 , 0.500000 , 0.500000 s -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 L 0.500000 , 0.000000 z`,\n};\n```\n\nLastly go down to `MASKS` and add an entry for your newly updated mask:\n\n```javascript\nexport const MASKS = [\n  // ...,\n  {\n    type: MaskTypes.RING,\n    showInLibrary: true, // mark this as true if you would like the shape to be user facing\n    name: _x('Ring', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.RING],\n    ratio: 392 / 392, // <Width of svg viewbox copied from illustrator> / <Height>\n  }\n];\n```\n\nThat's it! After you recompile your application you should now see your new shape show up in the shapes panel of the editor.\n\n\n## Appendix\n\n### Filenames for images and videos\n\nWordPress has a naming convention where if you upload an image with the same name multiple times, it adds a `-x` suffix.\n\n**i.e**\nif I upload `some_image.png` 3 times to the WordPress media upload in the story editor, it will store those images as:\n\n1. `some_image.png`\n2. `some_image-1.png`\n3. `some_image-2.png`\n\nBecause of this, our conversion script will strip the `-x` suffix off of the image source so it can point to the correct image stored in our repo.\n\nThis is an important note to make when naming images for upload into a story as **a `-x` suffix will always be stripped**. This naming convention is reserved for WordPress and will break your template creation if you use it in your image naming.\n"
  },
  {
    "path": "docs/feature-flags.md",
    "content": "# Feature flags\n\nThe React apps leverage the [`flagged`](https://www.npmjs.com/package/flagged) library to allow guarding code and components behind flags.\nThis allows hiding unfinished functionality until it is ready to be shown/enabled in the application.\n\n## Adding a feature flag\n\n### PHP changes\n\nIn `includes/Experiments.php`, add a new entry like this in the `get_experiments` method:\n\n```php\n...\n/**\n * Author: @yourGitHubUsername\n * Issue: #12345\n * Creation date: 2020-01-01\n */\n[\n    'name'        => 'showEasterEgg',\n    'label'       => __( 'Easter Egg', 'web-stories' ),\n    'description' => __( 'Show jumping bunnies', 'web-stories' ),\n    'group'       => 'editor',\n],\n...\n```\n\nNotes:\n\n* `group` can be either `dashboard`, `editor`, or `general`, if the feature is used in both places.\n\n### Usage in JavaScript\n\nYou can then use the flag in your code by following the examples in the \n[flagged documentation](https://www.npmjs.com/package/flagged).\n\n\n## Enabling feature flags by default\n\nAt some point, a feature flag will be turned on permanently. To do this, add a `default` field like so:\n\n```php\n...\n/**\n * Author: @yourGitHubUsername\n * Issue: #12345\n * Creation date: 2020-01-01\n */\n[\n    'name'        => 'showEasterEgg',\n    'label'       => __( 'Easter Egg', 'web-stories' ),\n    'description' => __( 'Show jumping bunnies', 'web-stories' ),\n    'group'       => 'editor',\n    'default'     => true,\n],\n...\n```\n\nBefore publishing the next release, all remnants of permanently enabled feature flags shall be removed from the code base.\n\n\n## Turning on/off feature flags with the Experiments tab\n\nFeature flags can be managed via a hidden \"Experiements\" tab within the Stories WordPress nav. There you can turn on/off all experiments defined in `includes/Experiments.php`.\n\nTo turn it on, add the following to your `wp-config.php` file.\n\n```php\ndefine( 'WEBSTORIES_DEV_MODE', true );\n```\n"
  },
  {
    "path": "docs/getting-started.md",
    "content": "# Getting Started\n\n## Requirements\n\nTo contribute to this plugin, you need the following tools installed on your computer:\n\n- [PHP](https://www.php.net/) - version 7.2 or higher, preferably installed via [Homebrew](https://brew.sh/).\n- [Composer](https://getcomposer.org/) (PHP package manager) - version 2.3 or higher, to install PHP dependencies.\n- [Node.js](https://nodejs.org/en/) (current LTS) - to install JavaScript dependencies.\n- [WordPress](https://wordpress.org/download/) - to run the actual plugin.\n- [Docker Desktop](https://www.docker.com/products/docker-desktop) and [Docker Compose](https://docs.docker.com/compose/install/) - for using the local environment\n\nYou should be running a Node version matching the [current active LTS release](https://github.com/nodejs/Release#release-schedule) or newer for this plugin to work correctly.\nYou can check your Node.js version by typing `node -v` in the Terminal prompt.\n\nIf you have an incompatible version of Node in your development environment, you can use [nvm](https://github.com/creationix/nvm) to change node versions on the command line:\n\n```bash\nnvm install\n```\n\n**Note:** Using `nvm` is recommended, as it makes it easier to stay up-to-date with any Node.js version requirement changes in the project.\n\n## Development\n\nFirst, you need to make sure that all PHP and JavaScript dependencies are installed:\n\nInstall Composer by following [installation instructions](https://getcomposer.org/download/).\n\nMake sure to add `composer` to your `$PATH` if it is not already there. The local environment won't run unless `composer` is in your `$PATH`.\n\n**WSL users** may also need to install `make`.  On WSL Ubuntu you should be able to use:\n\n```bash\nsudo apt-get install make\n```\n\nor\n\n```bash\nsudo apt-get install build-essential\n```\n\nTo install all the required composer packages, run:\n\n```bash\ncomposer install\n```\n\n---\n\nTo install all the required npm packages, run:\n\n```bash\nnpm install\n```\n\nWhether you use the pre-existing local environment or a custom one, any PHP code changes will be directly visible during development.\n\nHowever, for JavaScript this involves a build process. To watch for any JavaScript file changes and re-build it when needed, you can run the following command:\n\n```bash\nnpm run dev\n```\n\nThis way you will get a development build of the JavaScript, which makes debugging easier.\n\nFor watching for any JavaScript file changes and automatically refreshing the app in the browser (React Fast Refresh), use:\n\n```bash\nnpm run serve\n```\n\nThis makes for a much better developer experience as you don't have to manually refresh your browser tab every time you make changes.\n\nTo get a production build, run:\n\n```bash\nnpm run build:js\n```\n\n## Local Environment\n\nYou will need a WordPress environment to run the plugin.\nCheck out the [Local Environment](./local-environment.md) document for details on how to set one up.\n"
  },
  {
    "path": "docs/glossary.md",
    "content": "# Glossary\n\n**Checklist**:\nThe checklist is a tab in the Design Panel that represents another, cleaner way of browsing through all current errors, warnings and suggestions that originate via helper mode or the editor itself.\n\n**Dashboard**:\nThe CMS portion of the editor. Includes “Dashboard” dashboard page, Template Gallery, Bookmarks.\n\n**Design Panel**: \nThe right-hand sidebar of the editor. The Design Panel is where you modify the properties of the currently selected element or page.\n\n**Element**: \nA type of content that can be added to a page. The most common elements are text, image, video and shape elements.\n\n**Element Panel**:\nThe left-hand sidebar that features media, shapes, animations and other elements that can be added to a page.\n\n**Helper Mode**:\nSpecial assistive mode that when active, offers design suggestions next to the Workspace area to aid the user in producing a beautiful, functional story.\n\n**Page (Canvas)**:\nThe main ‘canvas’ that shows the current story page. This is where most of the action happens, and the user designs via drag & drop and other actions.\nSee also: [Canvas Layering](./canvas.md)\n\n**Text magic**:\nSpecial assistive mode that when active, makes automatic corrections to things involving text, such as text contrast. Its behavior can be modified with the overlay actions that appear when a text element is selected.\n\n**Workspace**:\nThe entire dark gray area, which includes page thumbnails, page and title and publishing/saving-related buttons.\n"
  },
  {
    "path": "docs/integration-tests.md",
    "content": "# Integration Tests\n\nKarma + Jasmine are used for running integration tests in the browser.\n\nMore details can be found in the `/karma` folder and the corresponding `README`s.\n\n## Running Karma Tests\n\nTo run the full test suite, you can use the following commands:\n\n```bash\nnpm run test:karma:story-editor -- --headless --viewport=1600:1000\nnpm run test:karma:dashboard -- --headless --viewport=1600:1000\n```\n\nTo run Karma once:\n\n```sh\nnpm run test:karma\n```\n\nTo run Karma in the watch mode:\n\n```sh\nnpm run test:karma:watch\n```\n\nTo run Karma in the headless mode:\n\n```sh\nnpm run test:karma -- --headless\n```\n\nor\n\n```sh\nnpm run test:karma:watch -- --headless\n```\n\n## Custom Matchers\n\nThere are a few custom matchers inspired by Jest and `jest-dom`:\n\n* `toBeEmpty`\n* `toHaveFocus`\n* `toHaveStyle`\n* `toHaveTextContent`\n* `toHaveProperty`\n* `toBeOneOf`\n\nPlus another custom async matcher inspired by [`jest-axe`](https://github.com/nickcolley/jest-axe) to test for accessibility violations:\n\n* `toHaveNoViolations`\n\n## Writing Tests\n\nThere will be times when test must wait for an async function or process. The `waitFor` util from react test library may be used to wait for a condition to be satisfied before running the next part of the test.\n\nWhen an `expect` or any other function within the `waitFor` block throws an error, this util will wait `50ms` before trying again. The `waitFor` helper needs to receive an error in order for it to re-poll.\n\n`waitFor` will continue to re-poll until the timeout limit is reached. By default, the timeout is `1000ms`. `timeout`, `interval` and other `waitFor` options are customizable. [More configuration options](https://testing-library.com/docs/dom-testing-library/api-async/);\n\nThe `findBy` query method is preferred, when applicable, since `findBy` is a combination of the `getBy` query and the `waitFor` util. `findBy` accepts the `waitFor` options as the last argument.\n\nIf `findBy` doesn’t fit your use case, throw an error in the body of `waitFor` while waiting for a condition to be met.\nExamples\n\n```javascript\n  const dialogs = await fixture.screen.findAllByRole('dialog', { timeout: 2000 });\n```\n\n```javascript\nawait waitFor(() => {\n  if (!node) {\n    throw new Error('this will make it so that the waitFor polls until no error is thrown');\n  }\n  expect(node).toBeTruthy();\n});\n```\n\n### Useful Resources\n\n* [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro)\n* [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)\n* [\"Which query should I use?\"](https://testing-library.com/docs/guide-which-query)\n* [Common mistakes with React Testing Library](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)\n* [React Hooks Testing Library](https://react-hooks-testing-library.com/)\n\n## Debugging Karma tests\n\nTo debug a Karma test, you can follow the following steps:\n\n1. Focus the test you want to debug by change it's `it` to `fit`.\n2. Add `await karmaPause()` command in a desired place in the test. The test\nwill execute all test steps prior to `karmaPause()` and will block.\n3. Run `npm run test:karma:watch`.\n4. Once the Karma window is opened, click on the \"DEBUG\" button in the header.\nThis will open the debug page at [http://localhost:9876/debug.html](http://localhost:9876/debug.html).\n5. Open DevTools. A tip: you can also run Karma with the `--devtools` option\nto open DevTools automatically.\n6. A test can be unblocked by executing `karmaResume()` in the DevTools console.\nA test can be blocked/resumed any number of times using `karmaPause()` and\n`karmaResume()` during the debugging session.\n\n## Browser support\n\nCurrently, only Puppeeter option is configured. It can run Chrome and Firefox browsers.\nIn the near future this may also be expanded to Playwright to support Safari and other\nbrowsers.\n\nFor details on how to customize browser options, see [karma-puppeteer-launcher](./karma-puppeteer-launcher/README.md).\n\nFor details on exposed native browser APIs, see [karma-puppeteer-client](./karma-puppeteer-client/README.md).\n\n## Common issues\n\n### Annoying firewall question: \"Do you want to the application Chromium.app to accept incoming network connections?\"\n\nSee [Puppeteer issue 4752](https://github.com/puppeteer/puppeteer/issues/4752).\n\n```sh\nsudo codesign --force --deep --sign - ./node_modules/puppeteer/.local-chromium/mac-*/chrome-mac/Chromium.app\n```\n\n### Test failure: ResizeObserver loop limit exceeded\n\nSee [ResizeObserver#observe() firing the callback immediately results in an infinite loop](https://github.com/WICG/resize-observer/issues/38#issuecomment-422126006).\n\nIf you are creating a new `observe()` event using the `resize-observer-polyfill` package, wrapping the body of the function which is provided to the `ResizeObserver` constructor with `window.requestAnimationFrame` will prevent the `ResizeObserver loop limit exceeded` error.\n\ne.g.\n\n```javascript\n      const observer = new ResizeObserver(() => {\n        // requestAnimationFrame prevents the 'ResizeObserver loop limit exceeded' error\n        // https://stackoverflow.com/a/58701523/13078978\n        window.requestAnimationFrame(() => {\n          // handle resize observation\n        });\n      });\n\n      observer.observe(node);\n```\n\nThere is also a `design-system` util called `useResizeEffect` which takes a node ref and a handler function which should be sufficient for resize observation requirements.\n"
  },
  {
    "path": "docs/local-environment.md",
    "content": "# Local Environment\n\nCurrently, the two most common ways for setting up a local environment for working on the Web Stories plugin are:\n\n1. Using the provided Docker container, which is also used for running the e2e tests.\n2. Using [Local](https://localwp.com/) \n\nThe former can be set up using the command line, the latter provides an easy-to-use GUI.\n\nLocal also makes it easy to switch PHP & WordPress versions, and supports HTTPS.\nHTTPS is required for some features like video optimization to work properly.\n\n## Docker Container\n\nSince you need a WordPress environment to run the plugin in, the quickest way to get up and running is to use the provided Docker setup.\n\n**Windows user?** It is highly recommended to use Windows Subsystem for Linux (WSL) 2 before trying to set up Docker on Windows. Setups without WSL have not been tested and might not work.\n\nThe following command will automatically verify whether Docker is configured properly and start the local WordPress instance.\n\n```bash\nnpm run env:start\n```\n\nThe WordPress installation should be available at `http://localhost:8899`.\nTo access the WordPress admin, visit `http://localhost:8899/wp-admin` (**Username**: `admin`, **Password**: `password`).\n\nTo later turn off the local environment, you can run:\n\n```bash\nnpm run env:stop\n```\n\nTo bring it back later, run the previous command:\n\n```bash\nnpm run env:start\n```\n\nAlso, if you need to reset the local environment's database, you can run:\n\n```bash\nnpm run env:reset-site\n```\n\n### Specifying PHP Version\n\nIt is also possible to run the local environment in different PHP versions, like so: \n\n```bash\nPHP_VERSION=8.0 npm run env:start\n```\n\n## Custom Environment\n\nIf you use something like [Local](https://localwp.com/), you can simply clone this repository right into your `wp-content/plugins` directory.\n\n```bash\ncd /path/to/your/local/site/wp-content/plugins && git clone git@github.com:googleforcreators/web-stories-wp.git web-stories\n```\n\nUsing symlinks works too, if you prefer having your Git projects in some other folders or if you want to use the Web Stories plugin on multiple environments.\n"
  },
  {
    "path": "docs/migrations.md",
    "content": "# Migrations\n\nMigration reducers can and should be written whenever the underlying data model is being changed.\n\nThis way, old stories get updated to the newest version once they're loaded.\n\nSee [`migration/migrate.js`](../packages/migration/src/migrate.js) for details.\n\n**Note**: migration functions should be self-contained and not import anything from outside components as they might change and thus affect the migration. \n"
  },
  {
    "path": "docs/onboarding.md",
    "content": "# Onboarding\n\nShort checklist for onboarding of new contributors to the team.\n\nRequirements:\n\n* Email address\n* GitHub username\n\nItems to check:\n\n| Task                                \t| Who    \t| Notes                                                                                                 \t|\n|-------------------------------------\t|--------\t|-------------------------------------------------------------------------------------------------------\t|\n| Add to Slack channel                \t| XWP    \t|                                                                                                       \t|\n| Add to shared calendar and meetings \t| XWP    \t|                                                                                                       \t|\n| GitHub access                       \t| Google \t| Usually done by @swissspidy. \"Write\" access is usually enough. Engineers also need merge permissions. \t|\n| Figma access                        \t| Google \t| Usually done by @samitron7                                                                            \t|\n| Access to [staging site](https://stories-new-wordpress-amp.pantheonsite.io/)              \t| Google \t| Usually done by @swissspidy                                                                           \t|\n| Access to [QA site](https://stories-qa-wordpress-amp.pantheonsite.io/)                   \t| Google \t| Usually done by @swissspidy                                                                           \t|\n| Access to [Percy](https://percy.io/google)                     \t| Google \t|                                                                                                       \t|\n| Add to [mailing lists](https://groups.google.com/g/story-editor-team)                \t| Google \t|                                                                                                       \t|\n"
  },
  {
    "path": "docs/page-templates.md",
    "content": "# Page Templates\n\nPage templates allow people to apply individual pages defined in templates to their story without choosing an entire template. Page templates are based on the same JSON definitions as templates defined in `packages/templates/src/raw`.\n\n## How Page Templates differ from Template Pages\n\nSince page templates are based on the same source files as templates, some customization of raw templates is required for them to work correctly with Page Templates.\n\n### Page Template Types and Naming\n\nIn the page templates pane, pages are labeled and able to be filtered by their page type (Examples: Cover, Section, Quote, ...). These types are defined in the source template's raw JSON.\n\nTo set page template type for a template page, set `pageTemplateType` on the template JSON's page objects to one of the types defined at `packages/story-editor/src/components/library/panes/pageTemplates/constants.js`. If `pageTemplateType` is set to `null`, the page will be omitted from the page templates pane.\n\nPage Templates are named based on their original Template Name + Page Template Type like \"Cooking Cover\".\n\n### All template images are converted to grid placeholders\n\nUnlike templates which come with lots of stock photography when creating a story based on a template, page templates replace all (yes, all) images with a placeholder grid image. In order to make the grid consistent, a single placeholder grid image is scaled to look consistent across many image sizes.\n\nTo preserve images to persist into the page template, they need to be converted to shapes. Shapes will be not be replaced with placeholder grids when rendered as page templates and applied to pages.\n\nThere has been consideration to make it so that some images can be passed through in [Issue #6032](https://github.com/googleforcreators/web-stories-wp/issues/6032).\n\n### Page Template Previews\n\nPage Templates preview using the same mechanisms as browsing templates on the dashboard. Animations are included when applying page templates and are included in previews.\n\n## Applying Page Templates\n\nPage templates are designed to be a page replacement. On application, they will replace the entire page's contents. If the page has changes, a confirmation is required before overwriting existing changes.\n\nApplying page templates copies over grid placeholders and all associated animations from the original template page.\n\n## Technical notes and considerations\n\n### RTL Support\n\nIn order for page templates and templates to render the same as they will when selected and published, they need to bypass some of the default RTL support in the app. All preview pages used for rendering page templates and templates are wrapped in `<StyleSheetManager stylisPlugins={[]}>`.\n\n### Page Templates are Template Pages\n\nIn order to make templates and page templates easier to maintain, page templates are built off of standard templates. Use `\"pageTemplateType\": null` (see above) to omit template pages from being able as page templates.\n\nThere are currently no mechanisms for creating page templates that are not a part of templates.\n"
  },
  {
    "path": "docs/performance.md",
    "content": "# Performance\n\nPerformance for the editor follows the [RAIL model](https://web.dev/rail/). Most of our in app interactions will be categorized by the [Animation](https://web.dev/rail/#animation:-produce-a-frame-in-10-ms) & [Response](https://web.dev/rail/#response:-process-events-in-under-50ms) section of this model. \n\nIt's important to measure the performance of the app with the react production build (`npm run build`) in an incognito window. This imitates what a user will experience and will prevent any chrome extensions from effecting performance times. It's also important to be aware of what machine you're auditing the app on relative to the user base of the application. An M1 macbook pro can perform about twice as fast as an intel macbook pro. This is something you should account for when trying to compare or justify results.\n\n## Existing Performance Work\n\nTo view any prior performance PRs, just search github pulls and issues for anything with the `performance` tag.\n\nThe two main milestone audits exist here:\n\n- [Performance Report: January 2022 ](https://github.com/GoogleForCreators/web-stories-wp/issues/10158)\n- [Performance Report: April 2022](https://github.com/GoogleForCreators/web-stories-wp/issues/11263)\n\n## Chrome DevTools Performance Tab vs React Profiler\n\nTo identify a performance bottleneck in the application, you should use the chrome devtools performance tab in an incognito window, record a sample interaction, and see if it violates the RAIL Model. If there is a violation of the RAIL Model, you should use React Profiler on the development build to guide your architectural decisions.\n\n**Note:** Performance optimizations can often come at the cost of Legibility & Maintainability. They can often also be footguns for performance if used incorrectly. It's important to have documentable proof of a performance bottleneck before altering code for the sake of performance improvements.\n\n### React Profiler\n\nThe React Profiler is beneficial for identifying where and how you can make the application more performant. Once you've recorded an interaction within the application, you can audit the commits and component renders of the application for that interaction.\n\nThere are essentially two things to look for when auditing a flame graph in the React Profiler, extraneous renders & expensive renders.\n\n#### Extraneous Renders\n\nExtraneous renders are categorized as renders that occur, that don't need to, for a particular update. You can think about these the difference between what React diffs for a particular update, and the minimum that needs to be diffed for our UI to visually update for a user. This difference is an extraneous render.\n\nThere's no need to eliminate all extraneous renders, but it is important to be able to identify, and remove, areas that have large amounts of extraneous renders. The classic example within the context of this app is updating an element. If we have 50 elements on a story page, and update the position of 1 element, only 1 element needs a visual update for the user. However, if all 50 elements re-render, and 49 of them are empty re-renders (re-render where nothing actually updated), those 49 re-renders are extraneous re-renders that should be eliminated.\n\nThere are many approaches to eliminate empty re-renders. The use case and existing architecture will dictate whatever approach you take, but ultimately any approach that is verified with the react flame graph should work.\n\nHere is a great article to reference: [When Does React Render Your Component?](https://www.zhenghao.io/posts/react-rerender)\n\n#### Expensive Renders\n\nExpensive renders are components that show up in the react flame graph and take >1ms to re-render. Like extraneous renders, this is not a hard rule, but you should look for components that are eating up a significant amount of your response budget when you identify a bottleneck.\n\nOnce expensive renders are identified in the flame graph from the React Profiling tool, recording the same interaction in the Chrome Dev Tools Performance tab, then inspecting the callstack is best to identify calls are making the components render expensive.\n\n## Using Context Performantly\n\nAll of our context is held using the [use-context-selector](https://github.com/dai-shi/use-context-selector) package, and we have a small layer around it that allows it to use shallow equality vs referential equality to detect if a component should re-render based on the return value of its selector. You can see this code in `packages/react/src/useContextSelector.js`.\n\nAs a general rule of thumb, it is best practice to pull only essential data needed for your component through a selector when using `useContextSelector(...)`. This practice helps eliminate empty/extraneous renders induced from context. [Read more about it here](https://github.com/GoogleForCreators/web-stories-wp/issues/2662#issuecomment-1011372651).\n\n## Main Areas to Identify Performance Regressions\n\nThere is always a chance for performance regressions as features get altered and added. The main regression to watch out for in the story editor is where a component is rendered for every element in state. Examples of this include the Display Layer, the Frames Layer, the Layer Panel. It should be verified that not every instance of said component re-renders when only one or a few of those element components needs updating. All these components are prone to large performance regressions if hooks or props pass data around unwisely.\n\nIt would be beneficial to audit these components from time to time in the react profiler. An audit can be as simple as recording an update to selection, or updating the position of a single element. If the react flame graph indicates that this is causing every element to re-render vs only the effected elements, a large performance regression has occurred.\n\nBe sure to check for this regression on PRs that effect display elements, frame elements, layers in the layers panel, or any story state hooks.\n"
  },
  {
    "path": "docs/quick-actions.md",
    "content": "# Quick Actions\n\nSome actions are cumbersome in the editor as it's difficult to find them in the Design panel. The quick actions menu allows users to perform actions and locate specific panels in the editor.\n\n## Overview\n\nQuick actions hook into the `highlight` api that is used in the pre-publish checklist. Using this, the quick actions can highlight specific panels in the editor.\n\nThe quick action menu is located in the nav layer. This allows users to navigate around using the keyboard in an intuitive way. Clicking the quick action menu should not remove focus from any elements that have focus.\n\nQuick actions have two main functions:\n\n1. Focusing a specific part of the editor\n2. Editing an element in the canvas\n\nQuick actions are not limited to just the above functionality. In the future it may be necessary to add more functionality.\n\n### Action Types\n\nThe actions that are displayed dynamically change depending on which element type is selected. These are outlined below:\n\n| Selected Element Type | Available actions                                                                                         |\n|-----------------------|-----------------------------------------------------------------------------------------------------------|\n| Nothing selected      | - Change background color<br/>- Insert media <br/>- Insert text                                           |\n| Background Image      | - Replace background<br/>- Add animation* <br/>- Clear filters and animation                              |\n| Foreground Image      | - Replace media<br/>- Add animation* <br/>- Add link<br/>- Clear animation                                |\n| Video                 | - Replace media<br/>- Add animation* <br/>- Add link<br/>- Add captions<br/>- Clear filters and animation |\n| Shape                 | - Change color<br/>- Add animation* <br/>- Add link<br/>- Clear filters and animation                     |\n| Text                  | - Change color<br/>- Edit text<br/>- Add animation*<br/>- Add link<br/>- Clear animation                  |\n\n### Action functionality\n\nReference this table when needing to know what a quick action will do when clicked.\n\n| Quick Action                          | Result                                                                                                                                                                                                                        |\n|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Add animation*                        | Open and highlight the `animation` panel in the `design pane`. Focus the effect chooser dropdown.                                                                                                                             |\n| Add caption                           | Open and highlight the `captions and subtitles` panel in the `design pane`. Focus the input.                                                                                                                                  |\n| Add link                              | Open and highlight the `link` panel in the `design pane`. Focus the input.                                                                                                                                                    |\n| Change background color               | Open and highlight the `page background` panel in the `design pane`. Focus the input.                                                                                                                                         |\n| Clear animation/filters and animation | Remove all filters and/or animations as specified. Display a snackbar to the user indicating that they were removed. The snackbar will contain an action button that when clicked will re-apply the styles that were removed. |\n| Edit text                             | Open and highlight the `text` panel in the `design pane`. Focus the first input.                                                                                                                                              |\n| Insert media                          | Open and highlight the `media pane` in the `library`. Focus the media tab button.                                                                                                                                             |\n| Insert text                           | Open and highlight the `text pane` in the `library`. Focus the text tab button.                                                                                                                                               |\n| Replace background/media              | Open and highlight one of the media panes in the `library`. The media pane opened will depend on the type of the element selected. Focus the relevant tab button.                                                             |\n| Trim video                            | Enter video trim mode similar to button in design panel.                                                                                                                                                                      |\n\n> *_Add animation_ action is not available on the first page of a story.\n\n### Visibility\n\nThe quick actions menu is visible when:\n\n1. there are no elements selected or \n2. if a single element is selected (including the background)\n\nThis feature does not support selecting multiple elements, so the menu will be hidden if more than one element is selected.\n\n## Adding new quick actions\n\nQuick actions hook into the highlight api. To add a new quick action, the following steps must be completed. If you are not highlighting, skip the first two steps:\n\n1. If it doesn't already exist, add a key to `packages/story-editor/src/app/highlights/states.js` that will reference the panel/pane/element that you are trying to highlight.\n2. Attach the new highlight state to the panel/pane/element that will be focused with the `useHighlights()` context. See existing usages for an example.\n3. Create the quick action in the `useQuickActions` hook located at `packages/story-editor/src/app/highlights/quickActions/useQuickActions.js`\n\n## Technical notes and considerations\n\n### Focus\n\nClicking the quick action menu should not remove focus from an element. To do this, two things were added:\n\n1. An `onMouseDown` event handler is passed to the buttons. This event handler prevents the mouse down event from unfocusing the canvas element.\n2. The context menu is given an `onMouseDown` event handler to prevent mouse  events on the menu _in between the buttons_ from bubbling up and unfocusing the element in the canvas.\n\nA user should be able to navigate the quick actions menu with their keyboard.\n\n### Highlights\n\nThis feature uses the `highlights` api that was implemented in [this pr: #6150](https://github.com/googleforcreators/web-stories-wp/pull/5965).\n\n### Testing\n\nIn order to prevent regression testing, unit and karma tests have been created. It is recommended to add a karma test for each new quick action to make sure that it behaves properly.\n"
  },
  {
    "path": "docs/right-click-menu.md",
    "content": "# Right Click Menu (Context Menu)\n\nThe Right-click Menu provides additional functionality to the user. The actions displayed on this Menu will change depending on which type of Element the user has selected on the canvas: Page, Text, Media, or Shapes.\n\n## Overview\n\nRight click menu will give the user a right click menu that is intuitive to use in the editor. Using this custom context menu, the user will be able to edit element style properties, store data in the clipboard, and paste data from their clipboard back into the editor.\n\n### Right click menu action types\n\n|Group|Description|\n|--|--|\n|Main actions|These options can apply across any element or media|\n|Layer distribution options/actions|These options help the user move the selected element between the different layers (objects in the canvas)|\n|Element styling options/actions|These options help the user manage the Element's style properties|\n|Page action options|These options help the user manage the different Pages in the story|\n\n### Actions\n\nDifferent actions will be rendered depending on the Element that is right clicked. The actions will do the following:\n\n<details>\n\n<summary>Page element actions</summary>\n\n|Action text|Action description|\n|--|--|\n|Add new page after|Adds a page after the current page.|\n|Add new page before|Adds a page before the current page.|\n|Duplicate page|Creates a new page that is identical to the current page. All animations, styles, and elements should be the same.|\n|Delete page|Deletes the current page (if the page can be deleted).|\n\n</details>\n\n<details>\n\n<summary>Text element actions</summary>\n\n|Action text|Action description|\n|--|--|\n|Send to back|Set the text element behind all other elements on the page.|\n|Send backward|Bring the text element backward one layer.|\n|Bring forward|Bring the text element forward one layer.|\n|Bring to front|Set the text element in front of all elements on the page.|\n|Copy style|The styles of the selected text element are copied to the clipboard. A snackbar is displayed on completion.|\n|Paste style|The styles that are saved to the clipboard are pasted to the currently selected text box. This does not update the text in the textbox. A snackbar is shown on completion.|\n|Add style to \"Saved styles\"|The style of the currently selected textbox is saved to the \"Saved styles\" panel in the style pane. This action opens the design tab, opens the \"Saved styles\" panel, and collapses all other panels in the style pane. The \"Saved styles\" panel should be highlighted when opened.|\n|Add color to \"Saved colors\"|The color(s) of the currently selected textbox is saved to the \"Saved colors\" panel in the style pane. This action opens the design tab, opens the \"Saved colors\" panel, and collapses all other panels in the style pane. The \"Saved colors\" panel should be highlighted when opened. A snackbar is displayed on completion.|\n\n</details>\n\n<details>\n\n<summary>Background media actions</summary>\n\n|Action text|Action description|\n|--|--|\n|Detach image from background|Removes the media from the background of the page and sets it in the foreground.|\n|Scale & crop background image|Show the scale and crop UI so that the user may scale or crop the image to the desired size.|\n\n</details>\n\n<details>\n\n<summary>Foreground media actions</summary>\n\n|Action text|Action description|\n|--|--|\n|Send to back|Place media behind all other elements. Disabled if the layer is all the way back.|\n|Send backward|Bring media one layer backwards. Disabled if the layer is all the way back.|\n|Bring forward|Bring media one layer forwards. Disabled if the layer is all the way forward.|\n|Bring to front|Place media in front of all other elements. Disabled if the element is all the way forward.|\n|Copy image styles|Copy all styles applied to the media to the clipboard. A snackbar is displayed on completion.|\n|Paste image styles|Add all styles in the clipboard to the selected media. A snackbar is displayed on completion.|\n\n</details>\n\n<details>\n\n<summary>Shape element actions</summary>\n\n|Action text|Action description|\n|--|--|\n|Send to back|Place shape behind all other elements. Disabled if the layer is all the way back.|\n|Send backward|Bring shape one layer backwards. Disabled if the layer is all the way back.|\n|Bring forward|Bring shape one layer forwards. Disabled if the layer is all the way forward.|\n|Bring to front|Place shape in front of all other elements. Disabled if the element is all the way forward.|\n|Copy shape styles|Copy styles from the shape to the clipboard. A snackbar is displayed on completion.|\n|Paste shape styles|Add styles from the clipboard to the selected shape. A snackbar is displayed on completion.|\n|Add color to \"Saved colors\"|The color(s) of the currently selected shape is saved to the \"Saved colors\" panel in the style pane. This action opens the design tab, opens the \"Saved colors\" panel, and collapses all other panels in the style pane. The \"Saved colors\" panel should be highlighted when opened. A snackbar is displayed on completion.|\n\n</details>\n\n## Technical notes and considerations\n\n### Copying and pasting styles\n\nWhen a user right clicks elements, they may be given the option to copy an element's styles and paste them to another element of the same type.\n\n**Note**: This does not override all styles of the element. Only styles that are in the table below are able to be copied and pasted:\n\n|Element type|Properties that are copy/paste-able|\n|--|--|\n|Text|- `backgroundColor`<br/>- `backgroundTextMode`<br/>- `border`<br/>- `border-radius`<br/>- `flip`<br/>- `font`<br/>- `fontSize`<br/>- `lineHeight`<br/>- `opacity`<br/>- `padding`<br/>- `rotationAngle`<br/>- `textAlign`|\n|Foreground Media|- `border`<br/>- `border-radius`<br/>- `flip`<br/>- `opacity`<br/>- `overlay`<br/>- `rotationAngle`|\n|Shape|- `backgroundColor`<br/>- `flip`<br/>- `opacity`<br/>- `rotationAngle`|\n\nA user may copy styles from any text, foreground media, and shape element. A user may not copy background media element styles.\n\nOnce styles are copied, a user may select an element of the same type and 'paste' those onto the selected element. The selected element's properties will be overridden by the 'copied' styles.\n\n### Testing \n\nIn order to prevent regression testing, unit and karma tests have been created. It is recommended to add a karma test for each new right click action to make sure that it behaves properly.\n"
  },
  {
    "path": "docs/storybook.md",
    "content": "# Storybook\n\nA living components library is maintained using [Storybook](https://storybook.js.org/).\n\nThe latest version of the project's storybook can be found at [https://googleforcreators.github.io/web-stories-wp/storybook](https://googleforcreators.github.io/web-stories-wp/storybook).\n\nTo run it locally, use the following command:\n\n```bash\nnpm run storybook\n```\n\nIn addition to the components library, the storybook also contains a story editor \"playground\" that can be used to test-drive the editor.\n"
  },
  {
    "path": "docs/svgs.md",
    "content": "# SVGs\n\nSVGs (also known as icons) are needed in different formats across this project.\n\nThis project uses webpack's [asset modules](https://webpack.js.org/guides/asset-modules/) and [SVGR](https://react-svgr.com/) to convert SVGs into different formats.\n\n**Note**: Each raw SVG must be in a separate file that is named with the `.svg` extension.\n\n## SVGs as Inline Assets\n\nSVGs may be embedded as a small file inline by converting the SVG into a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).\n\nTo use an SVG as a data URL, add the SVG in a folder named `/inline-icons`.\n\n## SVGs as React Components or Images\n\nSVGR is used to transform raw SVGs into React Components or Images so that SVGs can be more easily used in the dashboard and editor.\n\n### Using SVG as a React Component\n\nTo use an SVG as React Component, add an SVG in a folder named `/icons`. \n\nWebpack will see the `/icons` folder and process those SVGs through SVGR. The built file will have a default export that is a react component.\n\n### Using SVG as an Image\n\nTo use an SVG as an image, add an SVG in a folder named `/images`. \n\nWebpack will see the `/images` folder and process those SVGs through SVGR. The built file will have a default export that is an image.\n"
  },
  {
    "path": "docs/testing-environments.md",
    "content": "# Testing Environments\n\n## Staging Environment\n\nThe latest version of the plugin (i.e. current master branch) is up and running on [https://stories-new-wordpress-amp.pantheonsite.io/](https://stories-new-wordpress-amp.pantheonsite.io/) and ready for maintainers to test.\n\nPing one of the leads if you need access to the site.\n\n**Purpose**: Reviewing and testing the latest nightly build\n**Release cadence**: automatically\n**Target audience**: Engineering, PM, QA, UX\n\n## QA Environment\n\nThe Web Stories plugin is also active on [https://stories-qa-wordpress-amp.pantheonsite.io/](https://stories-qa-wordpress-amp.pantheonsite.io/) and ready for maintainers to test.\n\nThe [Web Stories Tester](./testing-qa.md) plugin is installed that lets you easily switch between testing the `master` branch and individual PRs.\n\nPing one of the leads if you need access to the site.\n\n**Purpose**: Reviewing new changes before they are merged (QA / UAT)\n**Release cadence**: manually\n**Target audience**: Engineering, PM, QA, UX\n\n## Stories Labs\n\nFor internal testing with a larger audience the [Stories Labs](https://stories-labs.dev/) site is more suitable.\n\nPing one of the leads if you need access to the site.\nPing @swissspidy if the site needs to be updated.\n\n**Purpose**: Test-driving the latest version\n**Release cadence**: manually (every few weeks / when there is a new release)\n**Target audience**: Internal testers\n"
  },
  {
    "path": "docs/testing-qa.md",
    "content": "# Manual Testing (QA)\n\n## ZIP Files\n\nEvery **pull request** automatically has a ZIP file attached to it that can be downloaded and installed on a WordPress site.\n\nTo get the ZIP file:\n\n1. Open pull request\n2. Click on \"Checks\" at the top  \n    ![PR Overview](https://user-images.githubusercontent.com/841956/80692983-a6894280-8ad2-11ea-8c5c-2c30ce89dc5f.png)\n3. Click on \"Continuous Integration\" on the left-hand side  \n    ![Continuous Integration](https://user-images.githubusercontent.com/841956/80693011-b0ab4100-8ad2-11ea-80aa-a1167c25fd14.png)\n4. Download `web-stories.zip`  \n    ![ZIP file list](https://user-images.githubusercontent.com/841956/80693026-b6a12200-8ad2-11ea-8ae0-76dc279f3250.png)\n\nThe same is also possible for the **master** branch. For this, navigate to [the Actions tab](https://github.com/googleforcreators/web-stories-wp/actions?query=workflow%3A%22Continuous+Integration%22+branch%3Amaster) in the repository navigation and click on the latest Continuous Integration run to download the ZIP file.\n\n## Web Stories Tester Plugin\n\nTo make switching between individual PRs easier, there is a Web Stories Tester WordPress plugin that you can install on your site.\n\n1. [Download Web Stories Tester](https://drive.google.com/file/d/1cKR2Yb7oY6JRyGvreVoCTBa_nfWp2Dqr/view?usp=sharing)\n2. Install plugin on your site by uploading it in WordPress\n3. Use the new menu item in the admin toolbar to switch between the master branch and individual PRs.  \n    ![Web Stories Tester plugin in action](https://user-images.githubusercontent.com/841956/81189411-cfb84000-8fb6-11ea-80db-adddebb06ef2.png)\n\n## Sharing story data\n\nYou can use [DevTools](./devtools.md) to share story data for debugging purposes.\n"
  },
  {
    "path": "docs/third-party-integration/dashboard/README.md",
    "content": "# Dashboard\n\n* [Getting Started](./getting-started.md)\n* [API Callbacks](./api-callbacks.md)\n* [Integration Layer](./integration-layer.md)\n* [Tutorial](./tutorial.md)\n"
  },
  {
    "path": "docs/third-party-integration/dashboard/api-callbacks.md",
    "content": "# API Callbacks\n\nSide effects are added to the Dashboard by defining callbacks. One such callback is `fetchStories` which is used to get stories from the backend and is the only required callback.\nOther callbacks can be used to add or handle functionalities for story management.\n\nAll API callbacks are asynchronous and should eventually resolve to their corresponding expected responses.\n\nBelow is a list of available API callbacks categorized in different sections.\n\n## Story Management\n\nA set of callbacks that help in performing create, update, delete and read operations on web stories stored in the CMS.\n\n### `fetchStories`\n\nA callback which fetches stories to be shown in the dashboard.\n\nArguments\n\n- `queryParams`\n    - type: `Object`\n    - description: An object which contains the query parameters.\n        - `status`\n            - type: `string`\n            - description: Status of a story. One of `draft`, `pending`, `public`, `future` or `private`.\n        - `searchTerm`\n            - type: `string`\n            - description: Search string.\n\n        - `sortOption`\n            - type: `string`\n            - description: User selected option from a dropdown. Sort by `title`,`date`,`date` or `story_author`.\n\n        - `sortDirection`\n            - type: `string`\n            - description: Sort order. One of `asc` or `desc`.\n\n        - `author`\n            - type: `string`\n            - description: Author name.\n\nExpected Response:\n\nAn `Object` with the following shape.\n\n`fetchedStoryIds`\n\n- type: `array<number>`\n- required: Yes\n- description: An array of story id's corresponding to the order of the stories to be shown in the dashboard. \n\n`stories`\n\n- type: `Object`\n- required: Yes\n- description:  Object consisting of story details of each story, where story-id is the key and [story object](#story-shape-object) is the value.\n  \n\n`totalPages`\n\n- type: `number`\n- required: Yes\n- description: Total number of pages.\n\n`totalStoriesByStatus`\n\n- type: `Object`\n- required: Yes\n- description: A map with data about how many stories have a particular status.\n\n\n\n### Story Shape Object\n\n- `author`\n    - type: `Object`\n    - required: No\n    - description: Name and id of the author for the web story.\n        - `name` \n            - type: `string`\n            - required: No\n            - description: Name of the author.\n\n        - `id`\n            - type: `number`\n            - required: No\n            - description: Id of the author.\n\n- `bottomTargetAction`\n    - type: `string`\n    - required: No\n    - description: Link to edit the story in story-editor.\n\n- `capabilities`\n    - type: `Object`\n    - required: No\n    - description: Capabilities of user to perform on current story.\n        - `hasEditAction`\n            - type: `boolean`\n            - required: No\n            - description: Defines the capability of user to edit the story.\n\n        - `hasDeleteAction`\n            - type: `boolean`\n            - required: No\n            - description: Defines the capability of user to delete the story.\n- `created`\n    - type: `string`\n    - required: Yes\n    - description: Created date and time of the story without timezone.\n\n- `createdGmt`\n    - type: `string`\n    - required: Yes\n    - description: Created date and time of the story with timezone.\n\n- `editStoryLink`\n    - type: `string`\n    - required: Yes\n    - description: Link to open story in story-editor.\n\n- `featuredMediaUrl`\n    - type: `string`\n    - required: No\n    - description: Link to show the featured media/poster.\n\n- `id`\n    - type: `number`\n    - required: Yes\n    - description: Id of the current story.\n\n- `link`\n    - type: `string`\n    - required: No\n    - description: Link to display the web-story output.\n\n- `modified`\n    - type: `string`\n    - required: Yes\n    - description: Latest modified date and time of the story without timezone.\n\n- `modifiedGmt`\n    - type: `string`\n    - required: Yes\n    - description: Latest modified date and time of the story with timezone.\n\n- `previewLink`\n    - type: `string`\n    - required: No\n    - description: Link to preview the story.\n\n- `status`\n    - type: `string`\n    - required: Yes\n    - description: Publishing status of the web story.\n\n- `title`\n    - type: `string`\n    - required: Yes\n    - description: Title of the web-story.\n\nExample ( Story Object )\n\n```JSON\n{\n    \"author\": {\n        \"name\": \"dev\",\n        \"id\": 1\n    },\n    \"bottomTargetAction\": \"https://example.org/post.php?post=1&action=edit\",\n    \"capabilities\": {\n        \"hasEditAction\": true,\n        \"hasDeleteAction\": true\n    },\n    \"created\": \"2022-01-18T07:36:32\",\n    \"createdGmt\": \"2022-01-18T07:36:32Z\",\n    \"editStoryLink\": \"https://example.org/post.php?post=1&action=edit\",\n    \"featuredMediaUrl\": \"\",\n    \"id\": 1,\n    \"link\": \"https://example.org/?post_type=web-story&p=1\",\n    \"modified\": \"2022-01-18T07:36:32\",\n    \"modifiedGmt\": \"2022-01-18T07:36:32Z\",\n    \"previewLink\": \"https://example.org/?post_type=web-story&p=1&preview=true\",\n    \"status\": \"draft\",\n    \"title\": \"Test Title\",\n}\n```\n\nExample ( Expected response )\n\n```JSON\n{\n    \"fetchedStoryIds\": [],\n    \"stories\":{\n        \"1\":{...},\n        \"2\":{...},\n    },\n    \"totalPages\": 1,\n    \"totalStoriesByStatus\": {...}\n}\n```\n\n### `updateStory`\n\nArguments\n\n- `data`\n    - type: `Object`\n    \n    - description: The Object containing params which contain details to update the story.\n        - `id`\n            - type: `number`\n            - description: The id of the story that needs to be updated\n        - `author`\n            - type: `number`\n            - description: The id of the author.\n        - `title`\n            - type: `number`\n            - description: The changed story title.\n\nResponse:\nAn `Object` of `<Story>` shape.\n\nExample ( Expected response )\n\n```JSON\n{\n    \"id\": 1,\n    \"status\": \"draft\",\n    \"title\": \"Test\",\n    \"created\": \"2022-03-15T08:28:02\",\n    \"createdGmt\": \"2022-03-15T08:28:02Z\",\n    \"modified\": \"2022-03-15T08:28:02\",\n    \"modifiedGmt\": \"2022-03-15T08:28:02Z\",\n    \"author\": {\n        \"name\": \"Dev\",\n        \"id\": 1\n    },\n    \"bottomTargetAction\": \"https://example.org/post.php?post=2247&action=edit\",\n    \"featuredMediaUrl\": \"\",\n    \"editStoryLink\": \"https://example.org/post.php?post=2247&action=edit\",\n    \"previewLink\": \"https://example.org/?post_type=web-story&p=2247&preview=true\",\n    \"link\": \"https://example.org/?post_type=web-story&p=2247\",\n    \"capabilities\": {\n        \"hasEditAction\": true,\n        \"hasDeleteAction\": true\n    }\n}\n```\n\n### `trashStory`\n\nArguments\n\n-  `id`\n    - type: `number`\n    - description: The story id which needs to be trashed.\n\nResponse\n\n- `void`\n\n### `createStoryFromTemplate`\n\nArguments\n\n-  `template`\n    - type: `Object`\n    - description: The details of a template\n        - `id`\n            - type: `number`\n            - description: Id of the template\n        - `createdBy`\n            - type: `string`\n            - description: Name of the creator of the template.\n        - `modified`\n            <!-- Need to find appropriate datatype since whole date is shown as like \"Wed Aug 25 2021 05:30:00 GMT+0530 (India Standard Time)\" -->\n            - type: `string`\n            - description: Date and time of modification of the template.\n        - `slug`\n            - type: `string`\n            - description: Slug of the template.\n        - `creationDate`\n            <!-- Need to find appropriate datatype since whole date is shown as like \"Wed Aug 25 2021 05:30:00 GMT+0530 (India Standard Time)\"-->\n            - type: `string`\n            - description: Date and time of creation of the template.\n        - `title`\n            - type: `string`\n            - description: Title of the template which will be default title for story.\n        - `tags`\n            - type: `Array<string>`            \n            - description: set of words that describe the template.\n        - `colors`\n            - type: `Array<Object>`            \n            - description: Set of colors which are mostly used in template.\n                - `color`\n                    - type: `string`\n                    - description: Hex code of the color.\n                - `family`\n                    - type: `string`\n                    - description: Name of the base color.\n                - `label`\n                    - type: `string`\n                    - description: Name of the color.\n        - `description`\n            - type: `string`\n            - description: A brief description of the template.\n        - `vertical`\n            - type: `string`\n            - description: Category of the template\n        - `version`\n            - type: `number`\n            - description: Version of the template used for migration.\n        - `pages`\n            - type: `array<Page>`\n            - description: Each attay item corresponds to each page in template.[ page object ](../story-editor/integration-layer-api/api-callbacks.md/#page-object-shape)\n        - `postersByPage`\n            - type: `array<Object>`\n            - description: Each object consisting of the URL for the page poster.\n                - `png`\n                    - type: `string`\n                    - description: URL for png image.\n                - `type`\n                    - type: `string` \n                    - description: Type of poster image.\n                - `webp`\n                    - type: `string`\n                    - description: URL for webp image.\n        - `status`\n            - type: `string`\n            - description: String showing the status of template.\n\nExpected Response:\nAn `Object` of the following shape.\n\n`editLink`\n\n- type: `string`\n- required: Yes\n- description: Link to edit the new story created from template.\n\nExample (Template)\n\n```JSON\n{\n    \"id\": 51,\n    \"createdBy\": \"Google\",\n    \"modified\": \"2020-04-21T00:00:00.000Z\",\n    \"slug\": \"celebrity-life-story\",\n    \"creationDate\": \"2021-08-25T00:00:00.000Z\",\n    \"title\": \"Celebrity Life Story\",\n    \"tags\": [\n        \"Entertainment\",\n        \"Celebrity\",\n        \"Pop\",\n        \"Bright\",\n        \"Black\"\n    ],\n    \"colors\": [\n        {\n            \"label\": \"Phantom Black\",\n            \"color\": \"#020202\",\n            \"family\": \"Black\"\n        },\n        {\n            \"label\": \"Gecko Green\",\n            \"color\": \"#80FF44\",\n            \"family\": \"Green\"\n        }\n    ],\n    \"description\": \"With an upbeat neon green color and a powerful headings font, this template is great for creating stories around pop culture, music and the show business.\",\n    \"vertical\": \"Entertainment\",\n    \"version\": 40,\n    \"pages\": [{...}],\n    \"postersByPage\": [{...}],\n    \"status\": \"template\",\n    \"isLocal\": false\n}\n```\n\nExample ( Expected Response )\n\n```JSON\n{\n    \"editLink\":\"https://example.org/post.php?post=1&action=edit\"\n}\n```\n\nNote that when the \"Use template\" button is clicked, it internally needs to know the registered element types.\nTherefore, you need to register them using `elementTypes.forEach(registerElementType)` in the same way as \nit is done for the editor itself (see [Getting Started](./../story-editor/getting-started.md)).\n\n### `duplicateStory`\n\nArguments\n\n- `story`\n    - type: `id`\n    - description: Id of the story which is to be dupilicated\n\nResponse\n\nAn `Object` in `<Story>` shape.\n\nExample ( Expected response )\n\n```JSON\n{\n    \"id\": 1,\n    \"status\": \"draft\",\n    \"title\": \"Test\",\n    \"created\": \"2022-03-15T08:28:02\",\n    \"createdGmt\": \"2022-03-15T08:28:02Z\",\n    \"modified\": \"2022-03-15T08:28:02\",\n    \"modifiedGmt\": \"2022-03-15T08:28:02Z\",\n    \"author\": {\n        \"name\": \"Dev\",\n        \"id\": 1\n    },\n    \"bottomTargetAction\": \"https://example.org/post.php?post=2247&action=edit\",\n    \"featuredMediaUrl\": \"\",\n    \"editStoryLink\": \"https://example.org/post.php?post=2247&action=edit\",\n    \"previewLink\": \"https://example.org/?post_type=web-story&p=2247&preview=true\",\n    \"link\": \"https://example.org/?post_type=web-story&p=2247\",\n    \"capabilities\": {\n        \"hasEditAction\": true,\n        \"hasDeleteAction\": true\n    }\n}\n```\n\n## Filtering stories\n\nA dropdown with a list of all the authors for filtering the stories would be added if the callback below is defined.\n\n### `getAuthors`\n\nA callback used to get all the authors of the CMS. Response from this will be used in a dropdown menu from which selecting a particular author will invoke `fetchStories` with the required arguments to get stories created by this author.\n\nArguments\n\n- `search`\n    - type: `string`\n    - description: Search string entered by the user.\n\nExpected Response:\n\nArray of the `Object` which describes author details.\n\n- `id`\n    - type: `number`\n    - required: Yes\n    - description: User id.\n\n- `name`\n    - type: `string`\n    - required: Yes\n    - description: Name of the author.\n\nExample ( Expected response )\n\n```json\n[\n    {\n    \"id\": 1,\n    \"name\": \"dev\"\n    },\n    {\n    \"id\": 2,\n    \"name\": \"admin\"\n    }\n]\n```\n"
  },
  {
    "path": "docs/third-party-integration/dashboard/getting-started.md",
    "content": "# Dashboard\n\nIf you want a companion dashboard to show stories created by the user or a list of story templates to choose from, you may use `Dashboard` from the `@googleforcreators/dashboard` package.\nThe dashboard can also be used to create a settings page for the story editor.\n\n## Scaffolding a Story Dashboard\n\nYou can quickly spin up a dashboard in a few steps described below.\n\n### Step 1: Set up a React project\n\nThe easiest way of setting up an SPA React project is to use [CRA](https://create-react-app.dev/) or to use templates such as [react-webpack-babel-starter](https://github.com/vikpe/react-webpack-babel-starter).\n\n### Step 2: Install dependencies\n\nFor a minimal story dashboard, you need to install three packages\n\n```sh\nnpm install @googleforcreators/dashboard @googleforcreators/element-library @googleforcreators/elements\n```\n\n### Step 3: Use the `Dashboard` component to render the dashboard\n\n```js\nimport { Dashboard, InterfaceSkeleton } from \"@googleforcreators/dashboard\";\n\nconst EditorDashboard = () => {\n  const apiCallbacks = {\n    fetchStories: () =>\n      Promise.resolve({\n        stories: {},\n        fetchedStoryIds: [],\n        totalPages: 1,\n        totalStoriesByStatus: {\n          all: 0,\n          publish: 0,\n        },\n      }),\n  };\n\n  return (\n    <Dashboard config={{ apiCallbacks }}>\n      <InterfaceSkeleton />\n    </Dashboard>\n  );\n};\n\nexport default EditorDashboard;\n```\n\nBy default, the dashboard looks like this:\n\n![dashboard](https://user-images.githubusercontent.com/841956/159524205-43e27097-9321-487c-b236-28f9414f539e.png)\n\nThe dashboard application can be split into 2 different areas:\n\n![dashboard-labelled](https://user-images.githubusercontent.com/841956/159524265-bf0a117a-2432-469d-8733-d61f1e94b3aa.png)\n\nThe left rail / sidebar (1) provides a list of menu items for different pages configured in the dashboard.\nClicking on a menu item will display the page's content on the right (2).\n\nOut of the box, the left rail only contains a menu item for the main page showing all existing stories.\n"
  },
  {
    "path": "docs/third-party-integration/dashboard/integration-layer.md",
    "content": "# Integration Layer\n\nSimilar to the editor, the Dashboard can be integrated by configuring the `Dashboard` and other components like `InterfaceSkeleton`.\n\nAs seen in the [Getting Started](./getting-started.md) guide, a minimal dashboard can be created by using the two main components  `Dashboard` and `InterfaceSkeleton`  like below.\n\n```js\nimport { Dashboard, InterfaceSkeleton } from \"@googleforcreators/dashboard\";\n\nconst StoriesDashboard = () => {\n  const apiCallbacks = {\n    fetchStories: () =>\n      Promise.resolve({\n        stories: {},\n        fetchedStoryIds: [],\n        totalPages: 1,\n        totalStoriesByStatus: {\n          all: 0,\n          publish: 0,\n        },\n      }),\n  };\n\n  return (\n    <Dashboard config={{ apiCallbacks }}>\n      <InterfaceSkeleton />\n    </Dashboard>\n  );\n};\n\nexport default StoriesDashboard;\n```\n\n## `Dashboard`\n\nThis is the top level component which has all the provider components but doesn't render any UI itself.\n\n**Props:**\n\n- `config`\n    - type: `Object`\n    - required: Yes\n    - description: Used for most of the dashboard configuration. See the [Dashboard Config](#dashboard-config) section below for full detail.\n\n## `InterfaceSkeleton`\n\nThis component is responsible for rendering the story editor interface UI and can be configured by using multiple props. Please look at the `InterfaceSkeleton` section below for detailed documentation of this component.\n\n**Props:**\n\n- `additionalRoutes`\n    - type: `array<Object>`\n    - required: No\n    - description: Used to add additional routes to the left rail.\n        - `path`\n            - type: `string`\n            - required: Yes\n            - description: Unique path to this page. For example - `/editor-settings`.\n        - `component`\n            - type: `React.ReactElement`\n            - required: Yes\n            - description: A component which will be rendered on the page content area if corresponding link is selected\n\n## Dashboard Config\n\nTo configure the dashboard to your needs you can pass various config options to the story dashboard via `config` prop of the `Dashboard` component.\n\n- `isRTL`\n    - type: `boolean`\n    - required: No\n    - description: It defines the direction of the layout of the dashboard.\n\n- `userId`\n    - type: `number`\n    - required: No\n    - description: The id of the user who is currently viewing the dashboard.\n\n- `locale`\n    - type: `Object`\n    - required: No\n    - description: It is a set of parameters that defines the user's language, region and any special variant preferences that the user wants to see in their user interface.\n\n- `newStoryURL`\n    - type: `string`\n    - required: Yes\n    - description: This specifies the exact url to create a new story.\n\n- `archiveURL`\n    - type: `string`\n    - required: No\n    - description: URL to archives page for web story. \n\n- `defaultArchiveURL`\n    - type: `string`\n    - required: No\n    - description: default URL archives page for web stories \n\n- `cdnURL`\n    - type: `string`\n    - required: No\n    - description: URL to dashboard resources.\n\n- `allowedImageMimeTypes`\n    - type: `array<string>`\n    - required: Yes\n    - description: It specifies the allowed Image types that are supported by web stories\n\n- `version`\n    - type: `string`\n    - required: No\n    - description: Shows the current version of web-story \n\n- `encodeMarkup`\n    - type: `boolean`\n    - required: No\n    - description: It specifies whether the markup need to be encoded while making api calls. \n\n- `api`\n    - type: `Object`\n    - required: Yes\n    - description: It specifies the URL for different api calls.\n\n- `maxUpload`\n    - type: `number`\n    - required: No\n    - description: It specifies the maximum size of a file that can be uploaded to the backend.\n\n- `maxUploadFormatted`\n    - type: `string`\n    - required: No\n    - description: It specifies the maximum size of a formatted file that can be uploaded to the backend\n\n- `capabilities`\n    - type: `Object`\n    - required:\n    - description: \n        - `canManageSettings`\n            - type: `boolean`\n            - required: No\n            - description: It specifies the capabilities of the user to manage settings of web story.\n        - `canUploadFiles`\n            - type: `boolean`\n            - required: No\n            - description: It specifies the capabilities of the user to upload files.\n\n- `canViewDefaultTemplates`\n    - type: `boolean`\n    - required: No\n    - description: It specifies ability of user to view default templates. \n\n- `localeData`\n    - type: array\n    - required: Yes\n    - description: Returns the translation of the translatable strings.\n\n- `apiCallbacks`\n    - type: `Object`\n    - required: Yes\n    - description: It consists of functions that are used to make request to API endpoints.\n\n- `leftRailSecondaryNavigation`\n    - type: `array<Object>`\n    - required: No\n    - description: It shows the navigation panel on the left side.\n        - `value`\n            - type: `string`\n            - required: No\n            - description: It specifies the value of its corresponding label in navigation panel.\n        - `label`\n            - type: `string`\n            - required: No\n            - description: It shows the value to be shown to the user for certain links. \n        - `isExternal`\n            - type: `boolean`\n            - required: No\n            - description: Defines the link is external or not. \n        - `trackingEvent`\n            - type: `string`\n            - required: No\n            - description: defines tracking event for the link for google analytics.\n\n- `documentTitleSuffix`\n    - type: `string`\n    - required: No\n    - description: Suffix to be used in the document title.\n\n- `styleConstants`\n    - type: `Object`\n    - required: No\n    - description: This contains various style constants which are used while calculating position for various components in dashboard. \n        - `topOffset`\n            - type: `boolean`\n            - required: No\n            - description: It defines the top bar height, which is used in calculation for placement of components. \n\n- `containerId`\n    - type: `string`\n    - required: No\n    - description: The id of the upper dashboard container which defines the available space for dashboard. If not defined `window.innerWidth` will be used for calculating the space.\n\n- `siteKitStatus`\n    - type: `Object`\n    - required: No\n    - description: It specifies the status of installation of site kit by google.\n        - `installed`\n            - type: `boolean`\n            - required: No\n            - description: It specifies whether site kit is installed. \n        - `active`\n            - type: `boolean`\n            - required: No\n            - description: It specifies whether site kit is active. \n        - `analyticsActive`\n            - type: `boolean`\n            - required: No\n            - description: It specifies whether analytics in site kit is active.\n        - `adsenseActive`\n            - type: `boolean`\n            - required: No\n            - description: It specifies whether adsense in site kit is active.\n        - `analyticsLink`\n            - type: `string`\n            - required: No\n            - description: It specifies the analytics link where analytics data are being recorded.\n        - `adsenseLink`\n            - type: `string`\n            - required: No\n            - description: It specifies adsense link where adsense data are being recorded.\n"
  },
  {
    "path": "docs/third-party-integration/dashboard/tutorial.md",
    "content": "# Tutorial\n\nThis tutorial explains how to create a standalone story dashboard step by step. It covers implementing the following functionalities:\n\n- Fetching hard-coded stories.\n- Adding filters for browsing stories.\n- Adding a custom settings page in the dashboard\n\n## Step 1: Setting up the dashboard with minimum config\n\nInstalling dependencies\n\n```sh\nnpm install @googleforcreators/dashboard\n```\n\nAfter that you can use code block given below to scaffold a minimal story dashboard.\n\n```js\nimport { Dashboard, InterfaceSkeleton } from \"@googleforcreators/dashboard\";\n\nconst CustomDashboard = () => {\n  const apiCallbacks = {\n    fetchStories: () =>\n      Promise.resolve({\n        stories: {},\n        fetchedStoryIds: [],\n        totalPages: 1,\n        totalStoriesByStatus: {\n          all: 3,\n          draft: 0,\n          future: 0,\n          pending: 0,\n          private: 0,\n          publish: 0,\n        },\n      }),\n  };\n\n  return (\n    <Dashboard config={{ apiCallbacks }}>\n      <InterfaceSkeleton />\n    </Dashboard>\n  );\n};\n\nexport default CustomDashboard;\n```\n\nMinimum requirement for a story dashboard is to fetch stories, so the user can browse them go to the editor to update them. The response for `fetchStories` that is shown in the above code sample emulates a CMS having no stories saved. \n\n## Step 2: Adding hard-coded stories and updating `fetchStories` to handle its argument\n\n`fetchStories` callback be updated as shown in the below code sample to serve hard-coded data.\n\n```js\nconst STORIES_RESP = {\n  stories: {\n    1: {\n      id: 1,\n      status: \"publish\",\n      title: \"Example story\",\n      created: \"2021-11-04T10:12:47\",\n      createdGmt: \"2021-11-04T10:12:47Z\",\n      author: {\n        name: \"Author 1\",\n        id: 1,\n      },\n      featuredMediaUrl:\n        \"https://wp.stories.google/static/main/images/templates/food-and-stuff/page1_bg.jpg\",\n    },\n    2: {\n      id: 2,\n      status: \"publish\",\n      title: \"Example story 2\",\n      created: \"2021-12-05T10:12:47\",\n      createdGmt: \"2021-12-05T10:12:47Z\",\n      author: {\n        name: \"Author 2\",\n        id: 2,\n      },\n      featuredMediaUrl:\n        \"https://wp.stories.google/static/main/images/templates/fresh-and-bright/page8_figure.jpg\",\n    },\n    3: {\n        id: 3,\n        status: \"publish\",\n        title: \"Example story 3\",\n        created: \"2021-12-06T10:12:47\",\n        createdGmt: \"2021-12-06T10:12:47Z\",\n        author: {\n          name: \"Author 3\",\n          id: 3,\n        },\n        featuredMediaUrl:\n          \"https://wp.stories.google/static/main/images/templates/fresh-and-bright/page7_product2.jpg\",\n      },\n  },\n  fetchedStoryIds: [1, 2, 3],\n  totalPages: 1,\n  totalStoriesByStatus: {\n    all: 3,\n    publish: 2,\n  },\n};\n\nconst fetchStories = () => Promise.resolve(STORIES_RESP);\n\nexport default fetchStories;\n```\n\nYou can also update `fetchStories` as below to allow basic filtering and ordering stories on the basis of their statuses.\n\n```jsx\n  const fetchStories = ({\n  status,\n  sortDirection,\n}) => {\n  let newFetchedIds = [];\n\n  try {\n    const statusArray = status.split(\",\");\n    if (statusArray.length === 6) {\n      newFetchedIds = STORIES_RESP.fetchedStoryIds;\n    } else {\n      Object.values(STORIES_RESP.stories).forEach(\n        ({ status: storyStatus, id }) => {\n          if (statusArray.includes(storyStatus)) {\n            newFetchedIds.push(id);\n          }\n        }\n      );\n    }\n\n    if (sortDirection && sortDirection === \"desc\") {\n      newFetchedIds = newFetchedIds.reverse();\n    }\n\n    return Promise.resolve({\n      ...STORIES_RESP,\n      fetchedStoryIds: newFetchedIds,\n      //stories: newStories,\n    });\n  } catch (err) {\n    return Promise.reject( err );\n  }\n};\n\nexport default fetchStories;\n```\n\nSimilar to how `status` and `sortOrder` in used in the code sample you can add other filter based on parameters passed to `fetchStories`. See [API callbacks](./api-callbacks.md) for more information.\n\n## Step 4: Adding a custom settings page\n\nYou can add a custom page or an external link to the dashboard's menu by passing required values to `config` and `InterfaceSkeletons`'s prop `additionalRoutes`. Below is a code sample doing just that.\n\n```js\nimport { PageHeading, Layout } from \"@googleforcreators/dashboard\";\n\nexport function EditorSettings() {\n  return (\n    <Layout.Provider>\n      <div>\n        <PageHeading heading={\"Settings\"} />\n        <Layout.Scrollable>\n          <div\n            style={{\n              height: \"300px\",\n              display: \"flex\",\n              alignItems: \"center\",\n              justifyContent: \"center\",\n              backgroundColor:\"#EEE\"\n            }}\n          >\n            {\"Settings\"}\n          </div>\n        </Layout.Scrollable>\n      </div>\n    </Layout.Provider>\n  );\n}\n\nexport const leftRailRoutes = [\n  {\n    value: \"/settings\",\n    label: \"Settings\",\n  },\n  {\n    value: `https://googleforcreators.github.io/web-stories-wp/storybook/iframe.html?id=playground-dashboard--default&args=&viewMode=story#/`,\n    label: \"External link\",\n    isExternal: true,\n  },\n];\n\n```\n\nNow let's pass the required values to `config` and `additionalRoutes`.\n\n```js\nimport { Dashboard, InterfaceSkeleton } from \"@googleforcreators/dashboard\";\nimport fetchStories from \"./fetchStories\";\nimport { leftRailRoutes, EditorSettings } from \"./settings\";\n\nconst CustomDashboard = () => {\n  const apiCallbacks = {\n    fetchStories,\n  };\n\n  return (\n    <Dashboard\n      config={{ apiCallbacks, leftRailSecondaryNavigation: leftRailRoutes }}\n    >\n      <InterfaceSkeleton\n        additionalRoutes={[\n          {\n            path: \"/settings\",\n            component: <EditorSettings />,\n          },\n        ]}\n      />\n    </Dashboard>\n  );\n};\n\nexport default CustomDashboard;\n```\n"
  },
  {
    "path": "docs/third-party-integration/story-editor/README.md",
    "content": "# Story Editor\n\n* [Getting Started](./getting-started.md)\n* [API Callbacks](./api-callbacks.md)\n* [Integration Layer](./integration-layer.md)\n* [Tutorial](./tutorial.md)\n"
  },
  {
    "path": "docs/third-party-integration/story-editor/api-callbacks.md",
    "content": "# API Callbacks\n\nSimilar to the dashboard, side effects are added to the Story Editor by defining callbacks. One such callback is `saveStoryById` which is used to save stories and is the only required callback. Other callbacks can be used to add or handle functionalities like first-party media and custom page templates etc. All API callbacks can be asynchronous and should eventually resolve to their corresponding expected responses.\n\nBelow is a list of available API callbacks categorized in different sections.\n\n## Story Editing\n\n### `saveStoryById`\n\nThe only required callback, that is used for saving stories.\n\nArguments\n\n- `storyState`  :\n    - type: `Object`\n    - description: The current state of the story. The required shape of the object is described in the table below.\n        - `storyId`\n            - type: `number`\n            - description: Unique id for the story.\n\n        - `title`\n            - type: `string`\n            - description:  Tittle of the story.\n\n        - `excerpt`\n            - type: `string`\n            - description:  Short description of the story.\n\n        - `version`\n            - type: `number`\n            - description:  Version of the story saved ( latest is `DATA_VERSION` from @googleforcreators/migration).\n\n        - `currentStoryStyles`\n            - type: `Object`\n            - description:  Saved styles available the current story (`colors`).\n                - `colors`\n                    - type: `array<Object>`\n                        - `r`\n                            - type: `number`\n                            - description: Red value.\n                        - `g`\n                            - type: `number`\n                            - description: Blue value.\n                        - `b`\n                            - type: `number`\n                            - description: Green value.\n\n        - `globalStoryStyles`\n            - type: `Object`\n            - description:  Saved styles available to all stories (`colors` & `textStyles`).\n                - `colors`\n                    - type: `array<Object>`\n                        - `r`\n                            - type: `number`\n                            - description: Red value.\n                        - `g`\n                            - type: `number`\n                            - description: Blue value.\n                        - `b`\n                            - type: `number`\n                            - description: Green value.\n                - `textStyles`\n                    - type: `array<Object>`\n                    - description: Saved text styles. See [text style shape](#text-style-shape) for more detail. \n\n        - `pages`\n            - type: `array<Page>`\n            - description: Array of page objects in the story. See [page object shape](#page-object-shape)\n\n#### Page object shape\n\n- `elements`\n    - type: `array<Element>`\n    - description: Array of elements in this page.\n\n- `backgroundColor`\n    - type: `Object`\n    - description: Background color of this page.\n        - `color`\n            - type: `Object`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n            \n\n- `type`\n    - type: `string`\n    - description: Page type.\n\n- `id`\n    - type: `string`\n    - description: Unique id for this page.\n\n### Text style shape\n\n- `backgroundColor`\n    - type: `Object`\n    - description: Background color of saved text style.\n        - `color`\n            - type: `Object`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n- `backgroundTextMode`\n    - type: `Object`\n    - description: Background text mode.\n\n- `font`\n    - type: `Object`\n    - description: Object defining font style. See [font object](#font-object-shape) shape for more detail.  \n\n- `fontSize`\n    - type: `number`\n    - description: Font size in pixels.\n\n- `lineHeight`\n    - type: `number`\n    - description: Line height in pixels\n\n- `padding`\n    - type: `Object`\n    - description: Data about padding\n    \n    - `locked`\n        - type: `boolean`\n        - description: used to lock padding manipulation other styles\n        \n    - `hasHiddenPadding`\n        - type: `boolean`\n        - description: \n    \n- `textAlign`\n    - type: `string`\n    - description: Text alignment. \n    \n- `color`\n    - type: `Object`\n    - description: Font color.\n        - `color`\n            - type: `Object`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n\n- `fontWeight`\n    - type: `number`\n    - description: Font weight.\n\n- `isItalic`\n    - type: `boolean`\n    - description: Flag to denote the text is italic.\n\n- `isUnderline`\n    - type: `boolean`\n    - description: Flag to denote the text has an underline.\n\n- `letterSpacing`\n    - type: `number`\n    - description: Letter spacing in pixels.\n\nExpected response\n\nAn `Object` with the following shape\n\n- `storyId`\n\n    - type: `number`\n    - required: No\n    - description: Unique id for the story.\n\n- `title`\n\n    - type: `string`\n    - required: No\n    - description: Short description of the story.\n\n- `excerpt`\n\n    - type: `string`\n    - require: No\n    - description: Short description of the story.\n\n- `version`\n\n    - type: `number`\n    - require: No\n    - description: Version of the story saved.\n\n- `currentStoryStyles`\n\n    - type: `Object`\n    - require: No\n    - description: Saved styles available in the current story (`colors`).\n        -  `colors`\n            - type: `array<Object>`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n\n- `globalStoryStyles`\n\n    - type: `Object`\n    - require: No\n    - description: Saved styles available to all stories (`colors` & `textStyles`).\n        - `colors`\n            - type: `array<Object>`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n        - `textStyles`\n            - type: `array<Object>`\n            - description: Saved text styles. See [text style shape](#text-style-shape) for more detail. \n\n- `pages`\n\n- type: `array<Page>`\n- require: No\n- description: Array of page objects in the story. See [page object shape](#page-object-shape) for more details.\n\nExample ( Expected response )\n\n```json\n{\n    \"storyId\": 1,\n    \"title\": \"Epic story\",\n    \"excerpt\": \"A totally epic story\",\n    \"version\" : 39,\n    \"currentStoryStyles\": {\n        \"colors\": []\n    },\n    \"globalStoryStyles\": {\n        \"textStyles\": [],\n        \"colors\": []\n    },\n    \"pages\" :[]\n}\n```\n\n### `getStoryById`\n\nFallback of `initialEdits` prop of `StoryEditor` component. If `initialEdits` prop is undefined, this callback will be used to populate the initial story.\n\nArguments\n\n- `storyId` :\n    - type: `number `\n    - description: Unique id of a story that needs to be loaded.\n\nExpected response\n\n- `title`\n    - type: `Object`\n    - required: No\n    - description: Tittle of the story.\n\n- `excerpt`\n    - type: `Object`\n    - required: No\n    - description: Story description of the story.\n\n- `storyData`\n    - type: `Object`\n    - required: No\n    - description: Story data.\n\n        - `version`\n            - type: `number`\n            - required: Yes\n            - description: Version of the story shape used.\n\n        - `pages`\n            - type: `array<Page>`\n            - require: No\n            - description: Array of page objects in the story. See [page object shape](#page-object-shape) for more details.\n\n        - `autoAdvance`\n            - type: `boolean`\n            - required: No\n            - description: Flag to denote if pages of the story advances automatically.\n\n        - `defaultPageDuration`\n            - type: `number`\n            - required: No\n            - description: Duration after which a page auto advances to a new page in seconds.\n\n        - `currentStoryStyles`\n            - type: `Object`\n            - require: No\n            - description: Saved styles available in the current story (`colors`).\n                -  `colors`\n                    - type: `array<Object>`\n                        - `r`\n                            - type: `number`\n                            - description: Red value.\n                        - `g`\n                            - type: `number`\n                            - description: Blue value.\n                        - `b`\n                            - type: `number`\n                            - description: Green value.\n\n        - `backgroundAudio`\n            - type: `Object`\n            - required: No\n            - description: Details about background audio.\n                - `resource`\n                    - type: `Object`\n                    - required: Yes\n                    - description: Details about background audio.\n                        - `id`\n                            - type: `number`\n                            - required: Yes\n                            - description: Id of the resource.\n                        - `length`\n                            - type: `number`\n                            - required: Yes\n                            - description: Length of the audio file in seconds.\n                        - `lengthFormatted`\n                            - type: `string`\n                            - required: Yes\n                            - description: Length of the audio file formatted as MM:SS.\n                        - `mimeType`\n                            - type: `string`\n                            - required: Yes\n                            - description: Mime type of the audio file.\n                        - `src`\n                            - type: `string`\n                            - required: Yes\n                            - description: URL of the audio file.\n\n- `author`\n    - type: `Object`\n    - required: No\n    - description: Details of author who created the story.\n        - `id`\n            - type: `number`\n            - required: Yes\n            - description: Author id.\n        - `name`\n            - type: `string\n            - required: Yes\n            - description: Author name.\n\n- `stylePresets`\n    - type: `Object`\n    - required: No\n    - description: Saved style Presets.\n\nExample ( Expected response )\n\n```json\n{\n    \"title\": {\n      \"raw\": \"Epic story\"\n    },\n    \"excerpt\": {\n      \"raw\": \"A totally epic story\"\n    },\n    \"storyData\": {\n      \"version\": 39,\n      \"pages\": [],\n      \"autoAdvance\": true,\n      \"defaultPageDuration\": 7,\n      \"currentStoryStyles\": {},\n      \"backgroundAudio\": {}\n    },\n    \"author\": {\n      \"id\": 1,\n      \"name\": \"John Doe\"\n    },\n    \"stylePresets\": {\n        \"colors\": [],\n        \"textStyles\": []\n    }\n}\n```\n\n## Custom Page Templates\n\nIn the element library, there is a section for page templates, by default it only serves pre-built templates. You can enable users to save and use their own custom page templates by defining these 3 callbacks.\n\n### `getCustomPageTemplates`\n\nFor fetching custom page templates.\n\nArguments\n\n- `page` :\n    - type: `number `\n    - description: Page number for a set of template.\n- `searchTerm`\n    - type: `string`\n    - description: Search string entered by the user.\n\n\nExpected response\n\nAn array of the template objects whose shape is described below.\n\n#### Template object shape\n\n- `templateId`\n    - type: `number`\n    - required: Yes\n    - description: Template id.\n\n- `version`\n    - type: `string`\n    - required: Version of the story shape used ( `DATA_VERSION` )\n    - description: Details of author who created the story.\n\n- `elements`\n\n- type: `array<element>`\n- required: Yes\n- description: Array of elements used in the template. See [element object](#element-object-shape).\n\n\n- `backgroundColor`\n    - type: `Object`\n    - required: Yes\n    - description: Background color RGB values.\n        - `color`\n            - type: `Object`\n                - `r`\n                    - type: `number`\n                    - description: Red value.\n                - `g`\n                    - type: `number`\n                    - description: Blue value.\n                - `b`\n                    - type: `number`\n                    - description: Green value.\n\n- `type`\n    - type: `string`\n    - required: Yes\n    - description: Template type.\n\n- `id`\n    - type: `string`\n    - required: Yes\n    - description: Page id.\n\n- `image`\n    - type: `Object`\n    - required: Yes\n    - description: Placeholder image data.\n            -`id`\n                - type: `string`\n                - required: Yes\n                - description: Image id.\n            -`height`\n                - type: `string`\n                - required: Yes\n                - description: Height of the placeholder image.\n            -`width`\n                - type: `string`\n                - required: Yes\n                - description: Width of the placeholder image.\n            -`url`\n                - type: `string`\n                - required: Yes\n                - description: Link to the placeholder image.\n\n#### Element object shape\n\n- `opacity`\n    - type: `number`\n    - description: Opacity of element in percent.\n\n- `flip`\n    - type: `Object`\n    - description: Flip data of the element.\n        - `vertical`\n            - type: `boolean`\n            - description: Vertical flip.\n        - `horizontal`\n            - type: `boolean`\n            - description: horizontal flip.\n\n- `rotationAngle`\n    - type: `number`\n    - description: Rotation angle of the element.\n\n- `lockAspectRatio`\n    - type: `boolean`\n    - description: Flag to lock aspect ratio.\n\n- `scale`\n    - type: `number`\n    - description: Scale of element in percent.\n\n- `focalX`\n    - type: `number`\n    - description: X focal point in percent.\n\n- `focalY`\n    - type: `number`\n    - description: Y focal point in percent.\n\n- `resource`\n    - type: `Object`\n    - description: Element resource data. Same as [media object shape](#media-object-shape)\n\n- `type`\n    - type: `string`\n    - description: Element type.\n\n- `x`\n    - type: `number`\n    - description: X coordinate of the element on canvas in pixels.\n\n- `y`\n    - type: `number`\n    - description: Y coordinate of the element on canvas in pixels.\n\n- `width`\n    - type: `number`\n    - description: Width of the element in pixels.\n\n- `height`\n    - type: `number`\n    - description: Height of the element in pixels.\n\n- `mask`\n    - type: `Object`\n    - description: Details about mask over the element.\n        - `type`\n            - type: `string`\n            - description: Mask type.\n        - `showInLibrary`\n            - type: `boolean`\n            - description: \n        - `name`\n            - type: `string`\n            - description: Mask name.\n        - `path`\n            - type: `string`\n            - description: Mask path.\n        - `ratio`\n            - type: `number`\n            - description: Mask ratio.\n        - `supportsBorder`\n            - type: `boolean`\n            - description: \n\n- `id`\n    - type: `string`\n    - description: Unique id for this element.\n\nExample ( Expected response )\n\n```json\n{\n    \"templateId\": 358,\n    \"version\": 39,\n    \"elements\": [],\n    \"backgroundColor\": {\n        \"color\": {\n            \"r\": 255,\n            \"g\": 255,\n            \"b\": 255\n        }\n    },\n    \"type\": \"page\",\n    \"id\": \"0d009686-a8d7-4cd9-a076-80e3e56efb68\",\n    \"image\": {\n        \"id\": 0,\n        \"height\": 0,\n        \"width\": 0,\n        \"url\": \"https://url-to-image\"\n    }\n}\n```\n\n### `addPageTemplate`\n\nFor adding custom page templates.\n\nArguments\n\n- `template` :\n    - type: `Object`\n    - description: See [Template Object Shape](#template-object-shape) for object shape.\n\nExpected response\n\n- `void`\n\n### `deletePageTemplate`\n\nFor deleting custom page templates.\n\nArguments\n\n- `templateId` :\n    - type: `number`\n    - description: Template Id.\n\nExpected response\n\n- `void`\n\n## First party Media Support\n\nAdding usage of first-party media for the user includes defining a few callbacks listed below and a component `MediaUpload`\n\n### `getMedia`\n\nFetches first-party media in the element library.\n\nArguments\n\n- `params` :\n    - type: `Object`\n    - description: Describes search or filter parameters which includes `mediaType`, `searchTerm`& `pagingNum`\n    - `mediaType`\n        - type: `string`\n        - description: Media type requested by the user. One of `image`, `video` or `gif`\n    - `searchTerm`\n        - type: `string`\n        - description: Search string entered by the user.\n    - `pagingNum`\n        - type: `string`\n        - description: Page number\n\n\nExpected response\n\n- An array of **Media Object**\n\n#### Media Object Shape\n\n- `baseColor` :\n\n    - type: `string`\n    - required: No\n    - description: Dominant color in hexadecimal format.\n\n- `blurHash` :\n\n    - type: `string`\n    - required: No\n    - description: Blur hash string of the media.\n\n- `type` :\n\n    - type: `string`\n    - required: Yes\n    - description: Type of media object. One of `image`, `video` or `gif`.\n\n- `mimeType` :\n\n    - type: `string`\n    - required: Yes\n    - description: Media mime type.\n\n- `creationDate` :\n\n    - type: `string`\n    - required: No\n    - description: Media creation date in UTC format.\n\n- `src` :\n\n    - type: `string`\n    - required: Yes\n    - description: Media source URL.\n\n- `width` :\n\n    - type: `number`\n    - required: Yes\n    - description: Media width in pixels.\n\n- `height` :\n\n    - type: `number`\n    - required: Yes\n    - description: Media height in pixels.\n\n- `id` :\n\n    - type: `number`\n    - required: Yes\n    - description: Media id.\n\n- `alt` :\n\n    - type: `string`\n    - required: No\n    - description: Media Alt text.\n\n- `sizes` :\n\n    - type: `Object`\n    - required: Yes\n    - description: Map of media in various sizes (thumbnail, medium, full).\n        - `file`\n            - type: `string`\n            - required: Yes\n            - description: Width of this particular size.\n        - `width`\n            - type: `number`\n            - required: Yes\n            - description: Width of this particular size.\n        - `height`\n            - type: `number`\n            - required: Yes\n            - description: Height of this particular size.\n        - `mimeType`\n            - type: `string`\n            - required: Yes\n            - description: Mime type of this particular size.\n        - `sourceURL`\n            - type: `string`\n            - required: Yes\n            - description: Link for this particular size.\n\n- `isPlaceholder` :\n\n    - type: `boolean`\n    - required: No\n    - description: Flag to denote if media is placeholder image.\n\n- `isOptimized` :\n\n    - type: `boolean`\n    - required: No\n    - description: Flag to denote if media is optimized.\n\n- `isMuted` :\n\n    - type: `boolean`\n    - required: No\n    - description: Flag to denote if media is muted.\n\n- `isExternal` :\n\n    - type: `boolean`\n    - required: No\n    - description: Flag to denote if media is external.\n\n- `needsProxy` :\n\n    - type: `boolean`\n    - required: No\n    - description: Flag to denote if getting media requires proxy.\n\n\nExample ( Expected response )\n\n```json\n{\n    \"baseColor\": \"#ffffff\",\n    \"blurHash\": \"UmJ*SDxtIVWB~VayRkj[M|Rkj[ofM|WBWBay\",\n    \"type\": \"image\",\n    \"mimeType\": \"image/jpeg\",\n    \"creationDate\": \"2022-02-08T11:13:06\",\n    \"src\": \"http://webstories.local/wp-content/uploads/2022/02/laptop_man.jpg\",\n    \"width\": 367,\n    \"height\": 267,\n    \"id\": 251,\n    \"alt\": \"laptop_man\",\n    \"sizes\": {\n        \"medium\": {\n            \"file\": \"laptop_man-300x218.jpg\",\n            \"width\": 300,\n            \"height\": 218,\n            \"mimeType\": \"image/jpeg\",\n            \"sourceUrl\": \"http://webstories.local/wp-content/uploads/2022/02/laptop_man-300x218.jpg\"\n        },\n        \"thumbnail\": {\n            \"file\": \"laptop_man-150x150.jpg\",\n            \"width\": 150,\n            \"height\": 150,\n            \"mimeType\": \"image/jpeg\",\n            \"sourceUrl\": \"http://webstories.local/wp-content/uploads/2022/02/laptop_man-150x150.jpg\"\n        },\n        \"full\": {\n            \"file\": \"laptop_man.jpg\",\n            \"width\": 367,\n            \"height\": 267,\n            \"mimeType\": \"image/jpeg\",\n            \"sourceUrl\": \"http://webstories.local/wp-content/uploads/2022/02/laptop_man.jpg\"\n        }\n    },\n    \"isPlaceholder\": false,\n    \"isOptimized\": false,\n    \"isMuted\": false,\n    \"isExternal\": false,\n    \"needsProxy\": false\n}\n```\n\n### `getMediaById`\n\nUsed to get media for video trim functionality\n\nArguments\n\n- `id` :\n    - type: `number`\n    - description: Media id.\n\nExpected response\n\n- **Media Object** (see [Media Object Shape](#media-object-shape))\n\n### `getMutedMediaById`\n\nUsed to get muted version of a video\n\nArguments\n\n- `id` :\n    - type: `number`\n    - description: Media id.\n\nExpected response\n\n- **Media Object** (see [Media Object Shape](#media-object-shape))\n\n### `getOptimizedMediaById`\n\nUsed to get optimized version of a video\n\nArguments\n\n- `id` :\n    - type: `number`\n    - description: Media id.\n\nExpected response\n\n- **Media Object** (see [Media Object Shape](#media-object-shape))\n\n### `updateMedia`\n\nThe story editor calculates and updates data about media elements stored in the back-end using these callbacks. Users can also update data if required interface is added. Out of the box users can only update `altText`.\n\nArguments\n\n- `id` :\n    - type: `number`\n    - description: Media id.\n\n- `data` :\n    - type: `Object`\n    - description: Updated data of a media object.\n        - `posterId` :\n            - type: `number`\n            - description: ID of the poster image element of this media element.\n\n        - `storyId` :\n            - type: `number`\n            - description: ID of the story in which a video element's poster was generated.\n\n        - `isMuted` :\n            - type: `boolean`\n            - description: Flag to identify if this element has audio.\n\n        - `mutedId` :\n            - type: `number`\n            - description: ID of the muted version of this media element.\n\n        - `mediaSource` :\n            - type: `string`\n            - description: Source from which the media was uploaded. One of `source-image`, `source-video`.\n\n        - `optimizedId` :\n            - type: `number`\n            - description: ID of optimized version of this media element.\n\n        - `altText` :\n            - type: `string`\n            - description: Alt text for media.\n\n        - `baseColor` :\n            - type: `string`\n            - description: Calculated base color (most prominent color) for media element.\n\n        - `blurHash` :\n            - type: `string`\n            - description: Calculated blur hash string for media element.\n\nExpected response\n\n- `void`\n\n### `uploadMedia`\n\nCalled when editor uploads -\n\n- Poster image for a video.\n- Poster image for a story.\n- Poster image for a template.\n- Altered media (muted, trimmed, optimized or converted to GIF)\n\nAfter uploading altered media Story editor calls `updateMedia` to update original version of altered media.\n\nArguments\n\n- `file` :\n    - type: `blob`\n    - description: Media File to upload.\n\n- `data` :\n    - type: `Object`\n    - description: Updated data of a media object.\n        - `originalId` :\n            - type: `number`\n            - description: ID of a media of which this element is an altered version of.\n\n        - `mediaId` :\n            - type: `number`\n            - description: ID of a video of which this element is a poster.\n\n        - `storyId` :\n            - type: `number`\n            - description: ID of a story of which this element is a poster.\n\n        - `templateId` :\n            - type: `number`\n            - description: ID of a template of which this element is a poster.\n\n        - `isMuted` :\n            - type: `boolean`\n            - description: flag to identify if this element has audio.\n\n        - `mediaSource` :\n            - type: `string`\n            - description: Upload source. One of `video-optimization`, `editor`, `poster-generation`,`gif-conversion`or `page-template`.\n\n        - `trimData` :\n            - type: `Object`\n            - description: `TrimData` data object linking a trimmed video to its original.\n                - `start`\n                    - type: `string`\n                    - description: Start Time stamp of start time of new video. Example '00:01:02.345'.\n                - `end`\n                    - type: `string`\n                    - description: End Time stamp of end time of new video. Example '00:02:00'.\n\n        - `baseColor` :\n            - type: `string`\n            - description: Calculated base color (most prominent color) for media element.\n\n        - `blurHash` :\n            - type: `string`\n            - description: Calculated blur hash string for media element.\n\nExpected response\n\n- `null`\n\n### `deleteMedia`\n\nFor deleting any media\n\nArguments\n\n- `id` :\n    - type: `number`\n    - description: ID of a media element which needs to be deleted.\n\nExpected response\n\n- `null`\n\n### `MediaUpload` component\n\n`MediaUpload` component is a modal rendered which will be used to render media upload button and open a media upload modal when a user instantiates a media upload by clicking previously mentioned button.\nThis modal should provide the user to insert any media already with the CMS or upload new items.\n\n- `title` :\n    - type: `string`\n    - required: No\n    - description: Title for the modal.\n\n- `buttonInsertText` :\n    - type: `string`\n    - required: No\n    - description: Text to use for the \"Insert\" button.\n\n- `onSelect` :\n    - type: `function`\n    - required: Yes\n    - description: Selection callback. Used to process the inserted image.\n\n- `onSelectErrorMessage` :\n    - type: `function`\n    - required: Yes\n    - description: Text displayed when incorrect file type is selected.\n\n- `onClose` :\n    - type: `function`\n    - required: Yes\n    - description: Modal close callback.\n\n- `onPermissionError` :\n    - type: `function`\n    - required: No\n    - description: Callback for when user does not have upload permissions.\n\n- `type` :\n    - type: `array<string>`\n    - required: Yes\n    - description: Array of allowed mime types modal should present or accept when a user uploads a new file.\n\n- `multiple` :\n    - type: `boolean`\n    - required: No\n    - description: Whether multi-selection should be allowed.\n\n- `cropParams` :\n    - type: `Object`\n    - required: No\n    - description: Width and height for cropped images.\n\n- `render` :\n    - type: `function`\n    - required: Yes\n    - description: React functional component responsible for rendering required media upload button. Takes a callback which should instantiate the modal for media upload.\n\n\n```jsx\nfunction MediaUpload({\n  buttonInsertText,\n  onSelect,\n  onSelectErrorMessage,\n  onClose,\n  onPermissionError,\n  type,\n  multiple,\n  cropParams,\n  render,\n}) {\n  const openModal = () =>{\n    // routine to open modal\n    // this modal will call callbacks passed to MediaUpload according to the context.\n  }\n\n  return render(openModal);\n}\n```\n\n\n\n## Adding Custom Fonts\n\nCustomize the Story editor for users to use with custom fonts.\n\n### `getFonts`\n\nUsed to get fonts\n\nArguments\n\n- `params`\n    - type: `Object`\n    - description: Filter parameters for fetching fonts.\n        - `search`\n            - type: `string`\n            - description: Search string entered by the user.\n        - `service`\n            - type: `string`\n            - description: One of `builtin` or `custom`.\n        - `include`\n            - type: `string`\n            - description: Comma separated names for font in the curated list.\n\nExpected response\n\n- Array of **Font Object**\n\n#### Font Object Shape\n\n- `id`\n    - type: `string`\n    - required: No\n    - description: Unique ID of the font.\n\n- `name`\n    - type: `string`\n    - required: No\n    - description: Name of the font.\n\n- `value`\n    - type: `string`\n    - required: No\n    - description: Font value.\n\n- `family`\n    - type: `string`\n    - required: Yes\n    - description: Family of the font.\n\n- `fallbacks`\n    - type: `array<string>`\n    - required: No\n    - description: Array of fallback font names.\n\n- `weights`\n    - type: `array<number>`\n    - required: No\n    - description: Array of available font weight.\n\n- `variants`\n    - type: `array<array<number>>`\n    - required: No\n    - description: Array of variant tuple.\n\n- `service`\n    - type: `string`\n    - required: Yes\n    - description: URL to font service which hosts the font.\n\n- `metrics`\n    - type: `Object`\n    - required: No\n    - description: Font metrics.\n\n\nExample ( Expected response )\n\n```json\n{\n    \"id\": \"Alegreya\",\n    \"name\": \"Alegreya\",\n    \"value\": \"Alegreya\",\n    \"family\": \"Alegreya\",\n    \"fallbacks\": [\n        \"serif\"\n    ],\n    \"weights\": [\n        400\n    ],\n    \"styles\": [\n        \"regular\",\n        \"italic\"\n    ],\n    \"variants\": [\n        [0,400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n        \"upm\": 1000,\n        \"asc\": 1016,\n        \"des\": -345,\n        \"tAsc\": 1016,\n        \"tDes\": -345,\n        \"tLGap\": 0,\n        \"wAsc\": 1123,\n        \"wDes\": 345,\n        \"xH\": 452,\n        \"capH\": 637,\n        \"yMin\": -293,\n        \"yMax\": 962,\n        \"hAsc\": 1016,\n        \"hDes\": -345,\n        \"lGap\": 0\n    }\n}\n```\n\n## Hotlinking media\n\nAdd support for inserting media by URL in addition to or instead of uploading files.\n\n### `getHotlinkInfo`\n\nUsed to get data about links while hot linking media in media pane.\n\nArguments\n\n- `url` \n    - type:`string` \n    - description: External link.\n\nExpected response\n\n- `ext` \n    - type:`string` \n    - required: Yes\n    - description: File extension.\n\n- `mimeType` \n    - type:`string`\n    - required: Yes\n    - description: File mime type.\n\n- `type` \n    - type:`string`\n    - required: Yes \n    - description: File type. One of `image` or `video`.\n\n- `fileName` \n    - type:`string`\n    - required: Yes \n    - description: File name.\n\nExample ( Expected response )\n\n```json\n{\n    \"ext\": \"jpg\",\n    \"mimeType\": \"image/jpeg\",\n    \"type\":\"image\",\n    \"fileName\": \"file_name.jpg\"\n}\n```\n\n## Adding Links to story elements\n\nLinks can be added to any elements in the Story editor through design panel, the only requirement being defining the callback `getLinkMetadata`\n\n### `getLinkMetadata`\n\nArguments\n\n- `url` \n    - type: `string`\n    - description: External Link.\n\n\nExpected response\n\n- `title` \n    - type: `string`\n    - required: Yes\n    - description: OG title.\n\n- `icon` \n    - type: `string`\n    - required: Yes\n    - description: OG image.\n\nExample ( Expected response )\n\n```json\n{\n    \"title\": \"link to external\",\n    \"icon\": \"https://link-to-icon\"\n}\n```\n\n## Adding user capabilities\n\nCaters Story editor with different capabilities on per-user basis\n\n### `getCurrentUser`\n\nFetch details about the current user.\n\nArguments\n\nNone\n\nExpected response\n\n- `id` \n    - type: `number`\n    - required: Yes\n    - description: Current user id.\n\n- `trackingOptin` \n    - type: `boolean`\n    - required: Yes\n    - description: Flag to know if the user has opted in for tracking.\n\n- `onboarding` \n    - type: `boolean`\n    - required: Yes\n    - description: Flag to know if the user needs to be shown onboarding.\n\n- `mediaOptimization` \n    - type: `boolean`\n    - required: Yes\n    - description: Flag to know if the user can upload optimized media.\n\n\nExample ( Expected response )\n\n```json\n{\n    \"id\": 1,\n    \"trackingOptin\": true,\n    \"onboarding\": false,\n    \"mediaOptimization\": true\n}\n```\n\n### `updateCurrentUser`\n\nUpdate details about the current user.\n\nArguments\n\n- `id` \n    - type: `number`\n    - description: User Id.\n\n- `data` \n    - type: `Object`\n    - description: Data to be updated.\n        - `trackingOptin` \n            - type: `boolean`\n            - description: Flag to know if the user has opted in for tracking.\n        - `onboarding` \n            - type: `boolean`\n            - description: Flag to know if the user needs to be shown onboarding.\n        - `mediaOptimization` \n            - type: `boolean`\n            - description: Flag to know if the user can upload optimized media.\n\nExpected response\n\n- `null`\n"
  },
  {
    "path": "docs/third-party-integration/story-editor/getting-started.md",
    "content": "# Getting Started\n\nThe following documentation explains how to integrate the visual story editor with any platform. \n\nThe documentation is divided into 3 sections:\n\n- Getting Started - This current doc provides a setup guide to instantiate a story editor with bare minimum functionality and explains significant UI elements of the editor.\n- [Standalone Editor Tutorial](./tutorial.md) - A tutorial to create a standalone story editor which works without a CMS.\n- [Integration Layer API](./integration-layer.md) - A comprehensive guide on the integration layer of the story editor\n\n## Minimal Setup Guide\n\nYou can quickly spin up a story editor in a few steps described below.\n\n### Step 1: Set up a React project\n\nThe easiest way of setting up a simple React project is by using [Create React App](https://create-react-app.dev/) or templates such as [react-webpack-babel-starter](https://github.com/vikpe/react-webpack-babel-starter).\n\n### Step 2: Install dependencies\n\nFor a minimal story editor, you need to install three packages\n\n```sh\nnpm install @googleforcreators/story-editor @googleforcreators/element-library @googleforcreators/elements\n```\n\n### Step 3: Use the `StoryEditor` component to render the editor\n\nThe code sample given below shows how to scaffold a story editor.\n\n```jsx\nimport { StoryEditor, InterfaceSkeleton } from '@googleforcreators/story-editor';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story: {} }}>\n      <InterfaceSkeleton />\n    </StoryEditor>\n  );\n};\n\nexport default Editor;\n```\n\nNote: You may have to wrap the editor in `<div style={ { height: '100vh' } }>`,  if the parent container doesn't have any height set.\n\nYou should now have a story editor that looks like this:\n\n![editor](https://user-images.githubusercontent.com/841956/159525789-9c669dc1-78a4-473b-a30f-6bf0bd72cc8b.png)\n\nTo learn more about the individual aspects of the story editor UI and the components it's comprised of, check out the [Web Stories for WordPress user documentation](https://wp.stories.google/docs/) as a reference point.\n\nFor a more in-depth example of setting up a custom story editor, check out the more in-depth [Standalone Editor Tutorial](./tutorial.md)\n"
  },
  {
    "path": "docs/third-party-integration/story-editor/integration-layer.md",
    "content": "# Integration Layer\n\nThe story editor can be integrated with any platform by configuring the `StoryEditor` and other components like `InterfaceSkeleton`.\nThis section of the documentation gives a comprehensive guide on what aspects of the story editor can be modified and how to modify them.\n\nAs seen in the [Getting Started](./getting-started.md) guide, a minimal story editor can be created by using the two main components  `StoryEditor` and `InterfaceSkeleton`  like below.\n\n```js\nimport { StoryEditor, InterfaceSkeleton } from '@googleforcreators/story-editor';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story: {} }}>\n      <InterfaceSkeleton />\n    </StoryEditor>\n  );\n};\n```\n\n## `StoryEditor`\n\nThis is the top level component of the story editor which has all the provider components but doesn't render any UI itself.\n\n**Props:**\n\n- `config`\n    - type: `Object`\n    - required: Yes\n    - description: Used for most of the editor configuration. See the [Editor Config](#editor-config) section below for full detail.\n\n- `initialEdits`\n    - type: `Object`\n    - required: Yes\n    - description: The initial edits/state of the story editor. Currently it only supports `story`.\n        - `story`\n            - type: `Object`\n            - required: Yes\n            - description: The story editor needs initial story when it loads. You can either provide the initial story object from this prop or via `getStoryById` API callback. See the [expected response](./api-callbacks.md#getstorybyid) of `getStoryById` for the shape of this object.\n\n## `InterfaceSkeleton`\n\nThis component is responsible for rendering the story editor interface UI and can be configured by using multiple props. Please look at the [InterfaceSkeleton](#interfaceskeleton) section below for detailed documentation of this component.\n\n**Props:**\n\n- `header`\n    - type: `React.ReactElement`\n    - required: No\n    - description: Used for rendering the workspace header.\n\n- `footer`\n    - type: `Object`\n    - required: No\n    - description: Used for rendering some parts of the footer.\n\n- `sidebarTabs`\n    - type: `Object`\n    - required: No\n    - description: Used for rendering the sidebar tabs of the story editor.\n\n## Editor Config\n\nTo configure the editor to your needs you can pass various config options to the story editor via `config` prop of the `StoryEditor` component.\n\n### `apiCallbacks`\n\n- type: `Object`\n- description: Takes various callback functions for story editor's side effects. The only required API callback is `saveStoryById`. For detailed documentation of `apiCallbacks`,  see [API Callbacks](./api-callbacks.md) section.\n\n### `additionalTips` \n\n- type: `array`\n- description: Used to provide additional tips in editor help center. \n- example :\n  \n  ```js\n  const additionalTips = [{\n    title: 'Example Tip Title',\n      figureSrcImg: 'http://link/to/image',\n      figureAlt: 'Figure alt text',\n      description: [\n        'This is an example tip used for testing. <a>Learn more</a>',\n      ],\n      href: 'https://external/link',\n  }]\n  ```\n\nYou can also provide an external link in the description of the tip.\n\n### `allowedMimeTypes` \n\n- type: `Object`\n- description: A map of file mime types accepted by element library.\n- example :\n  \n  ```js\n  const allowedMimeTypes = {\n    audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n    image: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'],\n    caption: ['text/vtt'],\n    vector: ['image/svg+xml']\n  };\n  ```\n\n### `autoSaveInterval`\n\n- type: `number`\n- description: Time Interval (in seconds) after which story editor automatically saves a story by calling `saveStoryById`.\n\n### `localAutoSaveInterval`\n\n- type: `number`\n- description: Time Interval (in seconds) after which story editor automatically saves the story data into sessionStorage.\n\n### `canViewDefaultTemplates`\n\n- type: `boolean`\n- description: Flag to allow for enabling default page template in the editor.\n\n### `capabilities`\n\n- type: `Object`\n- description: Controls story editor's capabilities, currently 2 capabilities can be customized.\n    - `hasMediaUploadAction`\n        - type: `boolean`\n        - description: Allow media upload.\n    - `canManageSettings`\n        - type: `boolean`\n        - description: Allow visiting settings page on the dashboard.\n- example :\n  \n  ```js\n  const capabilities = {\n    \"hasUploadMediaAction\": true,\n    \"canManageSettings\": true\n  }\n  ```\n\n### `cdnURL`\n\n- type: `string`\n- description: URL to element resources.\n\n### `dashboardLink`\n\n- type: `string`\n- description: URL to story editor's dashboard.\n\n### `encodeMarkup`\n\n- type: `boolean`\n- description: Flag to toggle markup generation in story data.\n\n### `ffmpegCoreUrl`\n\n- type: `string`\n- description: URL to `ffmpeg` core required for optimizing uploaded media.\n\n### `flags`\n\n- type: `Object`\n- description: Many experimental features can be enabled/disabled in the story editor. For a current list of existing flags, check out [`Experiments.php`](https://github.com/GoogleForCreators/web-stories-wp/blob/main/includes/Experiments.php).\n\n### `generalSettingsLink`\n\n- type: `string`\n- description: URL for settings page of the dashboard\n\n### `isRTL`\n\n- type: `boolean`\n- description: switches all styles to accommodate RTL languages.\n\n### `locale`\n\n- type: `Object`\n- description: locale data \n    \n    - `locale`\n        - type: `string`\n        - description: Locale code.\n\n    - `dateFormat`\n        - type: `string`\n        - description: Date format used by the editor.\n\n    - `timeFormat`\n        - type: `string`\n        - description: Time format used by the editor.\n\n    - `gmtOffset`\n        - type: `string`\n        - description: GMT offset of user's location\n\n    - `timezone`\n        - type: `string`\n        - description: User's time zone\n\n    - `months`\n        - type: `array<string>`\n        - description: Ordered array of month names.\n\n    - `monthsShort`\n        - type: `array<string>`\n        - description: Ordered array of shortened month names.\n\n    - `weekdays`\n        - type: `array<string>`\n        - description: Ordered array of weekday names.\n\n    - `weekdaysShort`\n        - type: `array<string>`\n        - description: Ordered array of shortened weekday names.\n\n    - `weekdaysInitials`\n        - type: `array<string>`\n        - description: Ordered array of weekday initial.\n\n    - `weekStartsOn`\n        - type: `number`\n        - description: Index of the first day of the week in `weekdays` array\n\n- example :\n\n```js\nconst locale ={\n\t\"locale\": \"en-US\",\n\t\"dateFormat\": \"F j, Y\",\n\t\"timeFormat\": \"g:i a\",\n\t\"gmtOffset\": \"-4\",\n\t\"timezone\": \"America/New_York\",\n\t\"months\": [\n\t\t\"January\",\n\t\t\"February\",\n\t\t\"March\",\n\t\t\"April\",\n\t\t\"May\",\n\t\t\"June\",\n\t\t\"July\",\n\t\t\"August\",\n\t\t\"September\",\n\t\t\"October\",\n\t\t\"November\",\n\t\t\"December\"\n\t],\n\t\"monthsShort\": [\n\t\t\"Jan\",\n\t\t\"Feb\",\n\t\t\"Mar\",\n\t\t\"Apr\",\n\t\t\"May\",\n\t\t\"Jun\",\n\t\t\"Jul\",\n\t\t\"Aug\",\n\t\t\"Sep\",\n\t\t\"Oct\",\n\t\t\"Nov\",\n\t\t\"Dec\"\n\t],\n\t\"weekdays\": [\n\t\t\"Sunday\",\n\t\t\"Monday\",\n\t\t\"Tuesday\",\n\t\t\"Wednesday\",\n\t\t\"Thursday\",\n\t\t\"Friday\",\n\t\t\"Saturday\"\n\t],\n\t\"weekdaysShort\": [\n\t\t\"Sun\",\n\t\t\"Mon\",\n\t\t\"Tue\",\n\t\t\"Wed\",\n\t\t\"Thu\",\n\t\t\"Fri\",\n\t\t\"Sat\"\n\t],\n\t\"weekdaysInitials\": [\n\t\t\"S\",\n\t\t\"M\",\n\t\t\"T\",\n\t\t\"W\",\n\t\t\"T\",\n\t\t\"F\",\n\t\t\"S\"\n\t],\n\t\"weekStartsOn\": 1\n}\n```\n\n### `maxUpload`\n\n- type: `number`\n- description: Size limit on uploaded media in bytes.\n\n### `MediaUpload`\n\n- type: `React.ReactElement`\n- description: React component used for rendering media upload modal. See [First party Media Support](./api-callbacks.md#First-party-Media-Support)\n\n### `showMedia3p`\n\n- type: `boolean`\n- description: Flag used to enable or disable third party media usage.\n\n### `storyId`\n\n- type: `number`\n- description: ID of the current story being rendered by the editor.\n\n### `styleConstants`\n\n- type: `Object`\n- description: Style constants for story editor modals.\n  \n    - `topOffset`\n        - type: `number`\n        - description: Top offset for modal overlay.\n\n    - `leftOffset`\n        - type: `number`\n        - description: Left offset for modal overlay.\n\n## InterfaceSkeleton\n\nMany aspects of the editor can be customized by adding custom components through A component called `InterfaceSkeleton` from `@googleforCreators/story-editor`. This section will give details about what aspects of the story editor can be modified by custom components.\nBefore reading this you might want to check out [Getting Started](./getting-started.md) to know about different visual components of the editor.\n\n## Workspace\n\n### Header \n\nEditor Workspace has reserved space to render a custom header. This can be used to provide custom UI elements for users to interact with. \nAlthough you can use custom UI elements in the header, it is advised to use elements provided in `@googleForCreators/design-system`. That will guarantee design consistency and compatibility with the `RTL` layout.\n\nAn example use case is available in [Standalone Editor Tutorial](./tutorial.md) where a few buttons have been added to the header.\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst CustomHeader = () => (\n  <div style={{ height: `100px`, width: \"100%\", backgroundColor: \"red\" }}>\n    {\" Custom Header \"}\n  </div>\n);\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <div style={{ height: \"100vh\" }}>\n      <StoryEditor config={{ apiCallbacks }} initialEdits={{ story:{} }}>\n        <InterfaceSkeleton header={<CustomHeader />} />\n      </StoryEditor>\n    </div>\n  );\n};\n```\n\n### Footer \n\nEditor workspace also has a footer space, but unlike header space, this can only be partially modified. Modifications include adding a footer to the Help center Menu and adding a pre-publish checklist.\n\n### Adding a footer to Help Center\n\nAdding a footer to the help center is straightforward, just pass a component to the `InterfaceSkeleton` component as shown below.\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst CustomFooter = () => <div>{\" Custom Help Center Footer \"}</div>;\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <div style={{ height: \"100vh\" }}>\n      <StoryEditor config={{ apiCallbacks }} initialEdits={{ story:{} }}>\n        <InterfaceSkeleton\n          footer={{\n            secondaryMenu: {\n              helpCenter: {\n                Footer: CustomFooter,\n              },\n            },\n          }}\n        />\n      </StoryEditor>\n    </div>\n  );\n};\n```\n\n### Adding a pre-publish checklist\n\nYou can also initialize a checklist to assist the user by offering design suggestions. There are many pre-built checks in `@googleForCreators/story-editor` for you to use. It's also possible to add additional checks if needed.\n\nThe application accepts 3 categories of checks, below is the list of all categories with corresponding pre-built checks available for initializing the checklist.\n\nAccessibility Checks :\n\n- `PageBackgroundTextLowContrast`\n- `TextElementFontSizeTooSmall`\n- `VideoElementMissingDescription`\n- `VideoElementMissingCaptions`\n- `ElementLinkTappableRegionTooSmall`\n- `ElementLinkTappableRegionTooBig`\n- `ImageElementMissingAlt`\n\nDesign Checks :\n\n- `StoryPagesCount`\n- `PageTooMuchText`\n- `PageTooLittleText`\n- `PageTooManyLinks`\n- `VideoElementResolution`\n- `ImageElementResolution`\n- `FirstPageAnimation`\n\nPriority Checks :\n\n- `StoryMissingTitle` \n- `StoryMissingPublisherName`\n- `StoryTitleLength` \n- `StoryMissingExcerpt` \n- `StoryPosterAttached`\n- `StoryPosterSize`\n- `PublisherLogoMissing`\n- `PublisherLogoSize`\n- `VideoElementMissingPoster`\n- `VideoOptimization`\n- `StoryAmpValidationErrors`\n\n#### Using pre-built checks\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n  PageBackgroundTextLowContrast,\n  TextElementFontSizeTooSmall,\n  StoryPagesCount,\n  PageTooMuchText,\n  StoryMissingTitle,\n  StoryTitleLength,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst Accessibility = () => (\n  <>\n    <PageBackgroundTextLowContrast />\n    <TextElementFontSizeTooSmall />\n  </>\n);\n\nconst Design = () => (\n  <>\n    <StoryPagesCount />\n    <PageTooMuchText />\n  </>\n);\n\nconst Priority = () => (\n  <>\n    <StoryMissingTitle />\n    <StoryTitleLength />\n  </>\n);\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story:{} }}>\n      <InterfaceSkeleton\n        footer={{\n          secondaryMenu: {\n            checklist: {\n              Priority,\n              Design,\n              Accessibility,\n            },\n          },\n        }}\n      />\n    </StoryEditor>\n  );\n};\n```\n\n#### Implementing a custom check\n\nBelow is an example of a custom check, this check will pop up in the checklist if story has less than 2 pages.\n\n```jsx\nimport {\n  ChecklistCard,\n  DefaultFooterText,\n  useRegisterCheck,\n  useIsChecklistMounted,\n  useStory,\n} from \"@googleforcreators/story-editor\";\n\nconst LessThan2PageCheck = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const { pagesLength } = useStory(({ state: { pages } }) => ({\n    pagesLength: pages.length,\n  }));\n  const hasLessThan2Pages = pagesLength < 2;\n\n  useRegisterCheck(\"LessThan2PageCheck\", hasLessThan2Pages);\n\n  return (\n    LessThan2PageCheck &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={\"Check title\"}\n        footer={\n          <DefaultFooterText>{\"Please add more pages\"}</DefaultFooterText>\n        }\n      />\n    )\n  );\n};\n\nexport { LessThan2PageCheck };\n\n```\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\nimport React, { useState } from \"react\";\nimport { LessThan2PageCheck } from \"./footer/checks\";\n\nconst CustomDesignChecklist = () => (\n  <>\n    <LessThan2PageCheck />\n  </>\n);\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story:{} }}>\n      <InterfaceSkeleton\n        footer={{\n          secondaryMenu: {\n            checklist: {\n              Design: CustomDesignChecklist,\n            },\n          },\n        }}\n      />\n    </StoryEditor>\n  );\n};\n```\n\n## Enabling Shopping Tab\n\nThe shopping tab allows inserting a product attachment with a draggable drawer that links to the product URL. To enable the shopping tab, you need to make a couple of changes.\n\nIn the `StoryEditor` config, add `isShoppingEnabled: true` and `shoppingProvider: 'None'`. If you have a shopping provider like WooCommerce or Shopify you can add 'Woocommerce' or 'Shopify' instead of 'None'.\n\n```jsx\n<StoryEditor\n    config={{\n        apiCallbacks,\n        autoSaveInterval: 10,\n        capabilities: { hasUploadMediaAction:true, \n        canManageSettings: true, },\n        MediaUpload,\n        isShoppingEnabled: true,\n        shoppingProvider: 'None'\n    }}\n    initialEdits={{ story }}>\n    <InterfaceSkeleton header={<StoryEditorHeader />}\n        sidebarTabs={{\n            document: {\n                title: 'Document',\n                Pane: DocumentPane,\n            },\n        }}\n    />\n</StoryEditor>\n```\n\nNext, provide `getProducts` in `apiCallbacks`:\n\n```jsx\nconst getProducts = () => {\n  const products = [\n    {\n      productId: \"1\",\n      productBrand: \"Nike\",\n      productDetails: \"Random Nike sneaker\",\n      productImages: [\n        {\n          alt: \"Image\",\n          url: \"https://static.nike.com/a/images/c_limit,w_592,f_auto/t_product_v1/4f37fca8-6bce-43e7-ad07-f57ae3c13142/air-force-1-07-shoes-WrLlWX.png\",\n        },\n      ],\n      productPrice: 1000,\n      productPriceCurrency: \"INR\",\n      productTitle: \"Nike Sneaker\",\n      productUrl:\n        \"https://www.nike.com/in/t/air-force-1-07-shoes-WrLlWX/315122-111\",\n    },\n  ];\n  return Promise.resolve({ products });\n};\n\nexport default getProducts;\n```\n\nAfter configuring these, you will see a shopping bag icon which will hold products you return from the `getProducts` function. Clicking on the product will insert an attachment.\n\n## Sidebar Tabs\n\n### Document Pane\n\nThe story editor can have an additional Document pane alongside the Insert and Style panes, which is meant to provide UI elements for editing data about the story as a whole.\nThe Document pane can be configured as shown below.\n\n```jsx\nimport {\n\tStoryEditor,\n\tInterfaceSkeleton,\n} from '@googleforcreators/story-editor';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst CustomDocumentPanel = ()=>(\n\t<div>\n\t\t{\" Custom Document Panel \"}\n\t</div>\n)\n\nconst Editor = () =>{\n\n\tconst apiCallbacks = {\n      saveStoryById: () => Promise.resolve({}),\n    };\n\n    elementTypes.forEach(registerElementType);\n\n\treturn (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story }}>\n      <InterfaceSkeleton  \n        sidebarTabs={{\n          document: {\n            title: __('Document', 'web-stories'),\n            Pane: DocumentPane,\n          },\n        }}\n      />\n    </StoryEditor>\n\t)\n}\t\n```\n"
  },
  {
    "path": "docs/third-party-integration/story-editor/tutorial.md",
    "content": "# Standalone Editor Tutorial\n\nThis tutorial explains how to create a standalone story editor using React that works without any CMS. It encompasses saving stories to the browser's local storage as well as previewing created stories.\n\n## Step 1: Setting up the editor with minimum config\n\nYou can bootstrap your React project using something like [Create React App](https://create-react-app.dev/) or similar.\n\nLet's start with installing the required dependencies.\n\n```sh\nnpm install @googleforcreators/story-editor @googleforcreators/design-system @googleforcreators/migration @googleforcreators/elements @googleforcreators/element-library\n```\n\nThe following code block scaffolds a minimal story editor:\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story: {} }}>\n      <InterfaceSkeleton />\n    </StoryEditor>\n  );\n};\n\nexport default Editor;\n```\n\n## Step 2: Saving stories in local storage\n\nWe will now define the API callback `saveStoryById` which is invoked by the editor while saving a story.\n\nFor details about other API callbacks accepted by the story editor, check out the [API Callbacks](./api-callbacks.md) section.\n\nThe following code block is given to show an example of how a story can be saved to the browser's local storage.\n\n```jsx\nimport { DATA_VERSION } from \"@googleforcreators/migration\";\n\nconst saveStoryById = ({\n  pages,\n  globalStoryStyles,\n  currentStoryStyles,\n  content,\n  title,\n}) => {\n  const storySaveData = {\n    title: {\n      raw: title,\n    },\n    storyData: {\n      version: DATA_VERSION,\n      pages,\n      currentStoryStyles,\n    },\n    stylePresets: globalStoryStyles,\n    permalinkTemplate: \"https://example.org/web-stories/%pagename%/\",\n  };\n\n  window.localStorage.setItem(\"STORY_CONTENT\", JSON.stringify(storySaveData));\n  window.localStorage.setItem(\"STORY_MARKUP\", content);\n\n  return Promise.resolve({});\n};\n\nexport default saveStoryById;\n```\n\nThe `saveStoryById` callback expects an object which has data about the story (`pages`, `globalStoryStyles`, `currentStoryStyles`) which will be stored in the local storage. Story editor also creates markup for the story with the key `content`, which will also be saved in the local storage and will be used for creating a preview in later sections of the tutorial.\n\nNow let's pass down this callback to the editor and use the data stored in local storage to hydrate it.\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\nimport saveStoryById from \"./saveStoryById\";\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById,\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  const content = window.localStorage.getItem(\"STORY_CONTENT\");\n  const story = content ? JSON.parse(content) : {};\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story }}>\n      <InterfaceSkeleton />\n    </StoryEditor>\n  );\n};\n\nexport default Editor;\n```\n\n## Step 3: Adding Save Button\n\nNow we can add a Save button which will call the `saveStoryById` callback from the previous step in order to save story data in local storage.\n\nThe following code shows how to accomplish that by using components from `@googleforcreators/design-system`:\n\n```jsx\nimport {\n  Button,\n  BUTTON_SIZES,\n  BUTTON_TYPES,\n  BUTTON_VARIANTS,\n  useSnackbar,\n} from \"@googleforcreators/design-system\";\nimport { useStory } from \"@googleforcreators/story-editor\";\n\nfunction SaveButton() {\n  const { isSaving, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n      actions: { saveStory },\n    }) => ({\n      isSaving,\n      saveStory,\n    }),\n  );\n\n  const { showSnackbar } = useSnackbar();\n\n  const handleSaveButton = () => {\n    saveStory().then(() => {\n      showSnackbar({\n        message: \"Story Saved\",\n      });\n    });\n  };\n\n  return (\n    <Button\n      variant={BUTTON_VARIANTS.RECTANGLE}\n      type={BUTTON_TYPES.PRIMARY}\n      size={BUTTON_SIZES.SMALL}\n      onClick={handleSaveButton}\n      disabled={isSaving}\n    >\n      {\"Save\"}\n    </Button>\n  );\n}\n\nexport default SaveButton;\n\n```\n\nIn the above code, `useStory` is a custom hook that exposes functionality to read and manipulate data of the story currently being edited. A state variable `isSaving` is being used to disable the save button when a story is being saved and the `saveStory` action is being used to actually save the story.\n\nThe `useSnackBar` hook exposes a `showSnackBar` action to display a snackbar message in the editor.\n\n### Header\n\nNow that we have a Save button, we can display it in the editor in a dedicated header area shown at the top of the workspace area.\n\nHere is how such a header component can be passed to the story editor in order to display the Save button:\n\n```jsx\nimport SaveButton from \"./saveButton\";\n\nfunction HeaderLayout() {\n  return (\n    <div>\n      <div\n        style={{\n          display: \"flex\",\n          justifyContent: \"flex-end\",\n          padding: \"1em\",\n          height: \"100%\",\n        }}\n      >\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n          }}\n        >\n          <SaveButton />\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default HeaderLayout;\n\n```\n\nPassing the component to the editor:\n\n```jsx\nimport {\n  StoryEditor,\n  InterfaceSkeleton,\n} from \"@googleforcreators/story-editor\";\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { registerElementType } from '@googleforcreators/elements';\nimport saveStoryById from \"./saveStoryById\";\nimport HeaderLayout from \"./header\";\n\nconst Editor = () => {\n  const apiCallbacks = {\n    saveStoryById,\n  };\n\n  elementTypes.forEach(registerElementType);\n\n  const content = window.localStorage.getItem(\"STORY_CONTENT\");\n  const story = content ? JSON.parse(content) : {};\n\n  return (\n    <StoryEditor config={{ apiCallbacks }} initialEdits={{ story }}>\n      <InterfaceSkeleton header={<HeaderLayout />} />\n    </StoryEditor>\n  );\n};\n\nexport default Editor;\n```\n\n## Step 4: Adding Preview button\n\nSimilar to the Save button in the previous step, we can add a new button that will open a new tab with the preview of a story.\n\n```jsx\nimport { Tooltip, useStory } from \"@googleforcreators/story-editor\";\nimport {\n  Button,\n  BUTTON_SIZES,\n  BUTTON_TYPES,\n  BUTTON_VARIANTS,\n  Icons,\n} from \"@googleforcreators/design-system\";\n\nfunction PreviewButton() {\n  const { isSaving, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n      actions: { saveStory },\n    }) => ({\n      isSaving,\n      saveStory,\n    }),\n  );\n\n  const openPreviewLink = async () => {\n    await saveStory();\n\n    const previewLink = window.origin + \"/preview\";\n\n    // Start a about:blank popup with waiting message until saving operation\n    // is done. That way, we will not bust the popup timeout.\n    try {\n      const popup = window.open(\"about:blank\", \"story-preview\");\n\n      if (popup) {\n        popup.document.write(\"<!DOCTYPE html><html><head>\");\n        popup.document.write(\"<title>\");\n        popup.document.write(\"Generating the preview…\");\n        popup.document.write(\"</title>\");\n        popup.document.write(\"</head><body>\");\n        popup.document.write(\"Please wait. Generating the preview…\"); // Output \"waiting\" message.\n\n        // Force redirect to the preview URL after 5 seconds. The saving tab\n        // might get frozen by the browser.\n        popup.document.write(\n          `<script>\n            setTimeout(function() {\n              location.replace(${JSON.stringify(previewLink)});\n            }, 5000);\n          </script>`,\n        );\n      }\n    } catch (e) {\n      console.log(e);\n    }\n  };\n\n  return (\n    <Tooltip title={\"Preview\"} hasTail>\n      <Button\n        variant={BUTTON_VARIANTS.SQUARE}\n        type={BUTTON_TYPES.QUATERNARY}\n        size={BUTTON_SIZES.SMALL}\n        onClick={openPreviewLink}\n        disabled={isSaving}\n      >\n        <Icons.Eye />\n      </Button>\n    </Tooltip>\n  );\n}\n\nexport default PreviewButton;\n```\n\nThis new button is very similar to the Save button, but it is styled a little differently and uses an icon (`Icons.Eye`) from the component library rather than a text label.\n\nClicking this button will:\n\n1. Store the story data and markup in local storage.\n2. Open a new tab with some loading state text.\n3. Redirect to the preview once the preview has been generated, or after a given timeout is reached.\n\nThis button can then be displayed in the header area next to the Save button.\n\n```jsx\nimport SaveButton from \"./saveButton\";\nimport PreviewButton from \"./previewButton\";\n\nfunction HeaderLayout() {\n  return (\n    <div>\n      <div\n        style={{\n          display: \"flex\",\n          justifyContent: \"flex-end\",\n          padding: \"1em\",\n          height: \"100%\",\n        }}\n      >\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            gap: \"10px\",\n          }}\n        >\n          <PreviewButton />\n          <SaveButton />\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default HeaderLayout;\n```\n\nA new route has to be introduced which will serve a preview of the story, for example using [React Router](https://reactrouter.com/) or a server-side solution. \n\nOn this route, simply display story markup which was previously stored in the browser's local storage using `saveStoryById`.\n\nYou can use the following code sample to describe a component which overrides page's HTML with the one in the local storage.\n\n```jsx\nimport { useEffect } from \"@googleforcreators/react\";\n\nfunction Preview() {\n  useEffect(() => {\n    const content = window.localStorage.getItem(\"STORY_MARKUP\");\n\n    if (content) {\n      document.open();\n      // Note that the use of document.write for replacing the whole page is to quickly set up a preview for demo but may not be ideal for production.\n      document.write(content);\n      document.close();\n    }\n  }, []);\n\n  return null;\n}\n\nexport default Preview;\n```\n\nThis is it! You should now have a working story editor which is capable of saving stories and generating a preview. \n\nCheck out the [Integration Layer API](./integration-layer.md) for a comprehensive documentation of the story editor's integration layer if you want to implement your own custom version.\n"
  },
  {
    "path": "docs/unit-tests.md",
    "content": "# Unit Tests\n\n## PHP\n\nThis project uses the [PHPUnit](https://phpunit.de/) testing framework to write unit and integration tests for the PHP part.   \n\nTests are run against a running WordPress instance through the [WordPress PHPUnit Test Suite](https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/). \nFor improved cross version compatibility for PHPUnit, the [WP Test Utils](https://github.com/Yoast/wp-test-utils) is implemented.\n\nTo run the full test suite, you can use the following command:\n\n```bash\nnpm run test:php\n```\n\nYou can also just run test for a specific function or class by using something like this:\n\n```bash\nnpm run test:php -- --filter=Story_Post_Type\n```\n\nSee `npm run test:php:help` to see all the possible options.\n\n### Writing PHP Tests\n\n#### Useful Resources for PHP Tests\n\n* [Using the WordPress PHPUnit Test Suite](https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/)\n\n## JavaScript\n\n[Jest](https://jestjs.io/) is used as the JavaScript unit testing framework.\n\nTo run the full test suite, you can use the following command:\n\n```bash\nnpm run test:js\n```\n\nYou can also watch for any file changes and only run tests that failed or have been modified:\n\n```bash\nnpm run test:js:watch\n```\n\nSee `npm run test:js:help` to get a list of additional options that can be passed to the test runner.\n\n### API\n\nThe [Jest docs](https://jestjs.io/docs/en/getting-started) have a good introduction into how to write tests using Jest.\n\n[`jest-dom`](https://github.com/testing-library/jest-dom) and [`jest-extended`](https://github.com/jest-community/jest-extended) are used in the project to extend test assertions beyond Jest's defaults.\n\n**Attention**: both these libraries have a `toBeEmpty` assertion. If you want the one from `jest-dom`, use `toBeEmptyNode` instead.\n\nReact components and hooks are tested using [Testing Library](https://testing-library.com/docs/intro).\n\n### Test Utils\n\n* In the project, there are `testUtils` folders with custom test utilities like `renderWithTheme` that can be used to make writing tests easier.\n\n### Custom Matchers\n\nThe following custom matchers exist in the project:\n\n* `toBeValidAMP`\n* `toBeValidAMPStoryPage`\n* `toBeValidAMPStoryElement`\n\n### Writing JavaScript Tests\n\n#### Useful Resources for JavaScript Tests\n\n* [Jest documentation](https://jestjs.io/docs/en/getting-started)\n* [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro)\n* [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)\n* [\"Which query should I use?\"](https://testing-library.com/docs/guide-which-query)\n* [Common mistakes with React Testing Library](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)\n* [React Hooks Testing Library](https://react-hooks-testing-library.com/)\n* [`jest-dom` API](https://github.com/testing-library/jest-dom#custom-matchers)\n* [`jest-extended` API](https://github.com/jest-community/jest-extended#api)\n\n#### Naming Conventions\n\n**File Names**:\nIf a component or function to be tested resides in `foo/bar/baz.js`, it is recommend to place the tests in `foo/bar/tests/baz.js`. There is no need for a `.test.js` file name suffix.\n\n**Test Names**:\nThe test name should be a proper sentence, starting with `it`. This provides more readable test failures. Example:\n\n```js\ndescribe('sum', () => {\n  it('adds 1 + 2 to equal 3', () => {\n    expect(sum(1, 2)).toBe(3);\n  });\n});\n```\n\nThis will be reported as \"sum > (it) adds 1 + 2 to equal 3\".\n\n### Snapshot Testing\n\nTry to avoid using snapshots when rendering components works just as well. If needed, use `toMatchInlineSnapshot`.\n\n### Code Coverage\n\nUse the following command to run code JavaScript tests with code coverage.\n\n```bash\nnpm run test:js:coverage\n```\n\nOne tests ran successfully, the coverage report will automatically open in your browser.\n"
  },
  {
    "path": "docs/web-stories-embeds.md",
    "content": "# Web Stories Embeds\n\nTheme developers can add varying degrees of support for Web Stories based on their requirements.\n\n## Customizer Integration\n\nThis basic integration guide will walk you through the simplest integration steps with which you can integrate web stories in your theme within 5 minutes and a couple of lines of code.\n\n### Add Theme Support for Web Stories\n\nThemes can opt into adding support for Web Stories, which will enable a new Customizer settings panel to control the appearance of stories in the theme.\n\nThis step is mandatory to integrate web stories into the theme via the Customizer.\n\nAdd the following code to the theme’s `functions.php` file to add support:\n\n```php\nfunction mytheme_setup() {\n    add_theme_support( 'web-stories' );\n}\n\nadd_action( 'after_setup_theme', 'mytheme_setup' );\n```\n\nThis is the minimal code which is required to get the \"Web Stories\" panel visible in the Customizer. This will work with the default settings options provided by the plugin, which can be changed.\n\n![Customizer Web Stories Options](https://user-images.githubusercontent.com/6906779/112966823-3793ee00-9168-11eb-850f-aee953814217.png)\n\n### Display Stories in Theme\n\nBased on the Customizer settings, a theme can display stories in appropriate place with the following code:\n\n```php\n<?php\nif( function_exists( '\\Google\\Web_Stories\\render_theme_stories' ) ) {\n   \\Google\\Web_Stories\\render_theme_stories();\n}\n```\n\n### Configuring Theme Support Options\n\nYou can override the default options by passing/overriding the arguments while adding theme support.\n\nBelow is a list of all options with their defaults values.\n\n```php\nadd_theme_support(\n\t'web-stories',\n\t[\n\t\t'customizer' => [\n\t\t\t'view_type'         => [\n\t\t\t\t'enabled' => [ 'circles' ], // possible values: circles, grid, carousel, list.\n\t\t\t\t'default' => 'circles',\n\t\t\t],\n\t\t\t'title'             => [\n\t\t\t\t'enabled' => true,\n\t\t\t\t'default' => true,\n\t\t\t],\n\t\t\t'excerpt'           => [\n\t\t\t\t'enabled' => true,\n\t\t\t\t'default' => false,\n\t\t\t],\n\t\t\t'author'            => [\n\t\t\t\t'enabled' => true,\n\t\t\t\t'default' => true,\n\t\t\t],\n\t\t\t'date'              => [\n\t\t\t\t'enabled' => false,\n\t\t\t\t'default' => true,\n\t\t\t],\n\t\t\t'archive_link'      => [\n\t\t\t\t'enabled' => true,\n\t\t\t\t'default' => true,\n\t\t\t\t'label'   => __( 'View all stories', 'web-stories' ),\n\t\t\t],\n\t\t\t'sharp_corners'     => [\n\t\t\t\t'enabled' => false,\n\t\t\t\t'default' => false,\n\t\t\t],\n\t\t\t'order'             => [\n\t\t\t\t'default' => 'DESC', // or 'ASC'.\n\t\t\t],\n\t\t\t'orderby'           => [\n\t\t\t\t'default' => 'post_date', // or post_title.\n\t\t\t],\n\t\t\t'circle_size'       => [\n\t\t\t\t'default' => 150, // 80 to 200\n\t\t\t],\n\t\t\t'number_of_stories' => [\n\t\t\t\t'default' => 10,\n\t\t\t],\n\t\t\t'number_of_columns' => [\n\t\t\t\t'default' => 2,\n\t\t\t],\n\t\t\t'image_alignment'   => [\n\t\t\t\t'default' => is_rtl() ? 'right' : 'left',\n\t\t\t],\n\t\t],\n\t]\n);\n```\n\n## Displaying Stories\n\n### Template Tag\n\nIf you want to display web stories anywhere in your theme, unrelated to customizer Web Story Option settings, you can use the following template tag. It will display 10 stories in grid format:\n\n```php\n<?php\nif ( function_exists( '\\Google\\Web_Stories\\render_stories' ) ) {\n\t$attrs = [\n\t\t'view_type'          => 'grid', // Possible values: circles, grid, carousel, list.\n\t\t'number_of_columns'  => 2,\n\t\t'show_title'         => false,\n\t\t'show_author'        => false,\n\t\t'show_date'          => false,\n\t\t'show_excerpt'       => false,\n\t\t'show_archive_link'  => false,\n\t\t'sharp_corners'      => false,\n\t\t'archive_link_label' => __( 'View all stories', 'your-theme-slug' ),\n\t\t'class'              => 'your-class-name',\n\t];\n\n\t$args = [\n\t\t'posts_per_page'   => 10,\n\t\t'post_status'      => 'publish',\n\t\t'suppress_filters' => false,\n\t\t'no_found_rows'    => true,\n\t];\n\n\t\\Google\\Web_Stories\\render_stories( $attrs, $args );\n}\n\n```\n\n## Custom Renderers\n\nRenderer classes are primarily responsible for Rendering Stories. Renderer classes must implement the [`Renderer` interface](../includes/Interfaces/Renderer.php).\n\nGenerally, rendering decisions are taken based on the view type.\n\nThe Web Stories plugin has two concrete implementations of `Renderer`:\n\n* **Generic Renderer** - Used for all view types, but Carousel and Circles views.\n* **Carousel Renderer** - Used for displaying stories in Carousel and Circles view mode.\n\nBoth of these classes extend the abstract `Renderer` class which itself implements the `Renderer` interface and takes care of some common operations for those concrete implementations to avoid code repetition.\n\n### Renderer Interface and Methods\n\nThe `Renderer` interface is already depicted in the above section. Following is the description of methods:\n\n1. `init()`  \nThis is used to perform any operations when the Renderer object is created. This method can be used to some essential properties, add hooks etc.\n\n2. `render()`  \nThis method is used to render the stories and its markup.\n\n3. `render_single_story_content()`  \nThis method should be used to return the markup of a single story. This is useful while we iterate over the list of stories to get the accumulative markup.\n\n### Creating your own Renderer Classes\n\nIf needed, you can write your own Renderer class to generate custom markup for stories.\n\nFollowing is an example of such a custom Renderer class.\n\n```php\n<?php\n\nuse Google\\Web_Stories\\Interfaces\\Renderer;\nuse Google\\Web_Stories\\Story_Query;\n\n/**\n * Class ExampleRenderer\n *\n * Custom Renderer implementation.\n */\nclass ExampleRenderer implements Renderer {\n\n\t/**\n\t * Current Story in the loop.\n\t *\n\t * @var array Story data.\n\t */\n\tprivate $current_story = null;\n\n\t/**\n\t * Story posts.\n\t *\n\t * @var array An array of story posts.\n\t */\n\tprotected $stories = [];\n\n\t/**\n\t * Constructor\n\t *\n\t * @param Story_Query $query Story_Query instance.\n\t */\n\tpublic function __construct( Story_Query $query ) {\n\t\t$this->stories = $query->get_stories();\n\t}\n\n\t/**\n\t * Initialization actions.\n\t */\n\tpublic function init(): void {\n\t\tadd_action( 'some_action', [ $this, 'some_callback' ] );\n\t}\n\n\t/**\n\t * Return the stories markup as string which needs to be\n\t * echoed further.\n\t *\n\t * @param array $args Rendering args like height, width etc.\n\t *\n\t * @return string\n\t */\n\tpublic function render( array $args = array() ): string {\n\t\tob_start();\n\t\t?>\n\t\t<div class=\"web-stories\">\n\t\t<div class=\"web-stories__inner-wrapper\">\n\t\t\t<ul class=\"web-stories-list\">\n\t\t\t\t<?php\n\t\t\t\tif ( ! empty( $this->stories ) ) {\n\t\t\t\t\tforeach ( $this->stories as $story ) {\n\t\t\t\t\t\t$this->current_story = $story;\n\t\t\t\t\t\t$this->render_single_story_content();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t?>\n\t\t\t</ul>\n\t\t</div>\n\t\t</div>\n\t\t<?php\n\t\treturn ob_get_clean();\n\n\t}\n\n\t/**\n\t * Render single story markup inside the method itself.\n\t *\n\t * @return void\n\t */\n\tpublic function render_single_story_content(): void {\n\t\tprintf( '<li class=\"web-story\">%s</li>', esc_html( $this->current_story->post_title ) );\n\t}\n}\n```\n\nOnce the Renderer class is ready, you can use this Renderer to display stories as follows.\n\n```php\n$story_query_attrs = [ 'view' => 'circles' ];\n$story_query_args  = [ 'posts_per_page' => 8 ];\n$story_query       = new \\Google\\Web_Stories\\Story_Query( $story_query_attrs, $story_query_args );\n\n$renderer = new ExampleRenderer( $story_query );\necho $renderer->render();\n```\n\n## CSS Guide\n\nWeb Stories use minimal required HTML to render stories based on selected view type. This block has four view types in total, which are as follows:\n\n* Generic View\n    1. Grid View\n    2. List View\n* Carousel View\n    1. Box Carousel\n    2. Circles Carousel\n\nAs mentioned above, these four view types have further been divided into two types of renderers. Following are the general full structure of the rendered web stories for each renderer type. Some of these elements are conditional and will only render if dependent conditions are met, like the excerpt ( ‘.story-content-overlay__excerpt’ ) will only be shown for the list view type and if control to show the excerpt is set to true.\n\n**Generic View:**\n\n```html\n<div class=\"web-stories-list\">\n  <div class=\"web-stories-list__inner-wrapper\">\n    <div class=\"web-stories-list__story\">\n      <div class=\"web-stories-list__story-poster\">\n        <!-- For non-AMP pages. -->\n        <img />\n\n        <!-- or -->\n\n        <!-- For AMP pages. -->\n        <amp-img></amp-img>\n      </div>\n      <div class=\"web-stories-list__story-content-overlay\">\n        <div class=\"story-content-overlay__title\"></div>\n        <div class=\"story-content-overlay__excerpt\"></div>\n        <div class=\"story-content-overlay__author\"></div>\n        <div class=\"story-content-overlay__date\"></div>\n      </div>\n    </div>\n    <div class=\"web-stories-list__archive-link\"></div>\n  </div>\n</div>\n\n<!-- one lightbox wrapper for each instance of web stories on the page, rendered on 'wp_footer' action. -->\n\n<div class=\"web-stories-list__lightbox-wrapper\"></div> <!-- For non-AMP pages. -->\n\n<amp-lightbox></amp-lightbox> <!-- For AMP pages. -->\n```\n\n**Carousel View:**\n\n```html\n<div class=\"web-stories-list\">\n  <div class=\"web-stories-list__inner-wrapper\">\n    <div class=\"web-stories-list__carousel\"> <!-- For AMP requests the carousel wrapper will be <amp-carousel> -->\n      <div class=\"web-stories-list__story\">\n        <div class=\"web-stories-list__story-poster\">\n          <!-- For non-AMP pages. -->\n          <img />\n\n          <!-- or -->\n\n          <!-- For AMP pages. -->\n          <amp-img></amp-img>\n        </div>\n        <div class=\"web-stories-list__story-content-overlay\">\n          <div class=\"story-content-overlay__title\"></div>\n          <div class=\"story-content-overlay__author\"></div>\n          <div class=\"story-content-overlay__date\"></div>\n        </div>\n      </div>\n    </div>\n    <div class=\"web-stories-list__archive-link\"></div>\n  </div>\n</div>\n\n<!-- one lightbox wrapper for each instance of web stories on the page, rendered on 'wp_footer' action. -->\n\n<div class=\"web-stories-list__lightbox-wrapper\"></div> <!-- For non-AMP pages. -->\n\n<amp-lightbox></amp-lightbox> <!-- For AMP pages. -->\n```\n\n## Elements\n\n### Block root classes\n\nFollowing classes are present on the root element.\n\n#### `.web-stories-list`\n\nDefault class added to the block’s main container.\n\n#### `.align{$alignment_option}`\n\nIf the block has alignment set it will add this class with the one of the `[ ‘none’, ‘wide’, ‘full’, ‘left’, ‘center’, ‘right’ ]` values, i.e., if alignment is set to `wide` the class will be `alignwide`. Defaults to `alignnone`.\n\nAlso adds any extra classes passed to the renderer with a story attribute named ‘class’.\n\n#### `.has-archive-link`\n\nIf the block is showing an archive link.\n\n#### View specific classes added to the root\n\n##### `.is-view-type-{$view_type}`\n\n`$view_type` will be one of the four view types i.e., for Circles Carousel the class name will be `is-view-type-circles`.\n\n\n##### `.columns-{$column_number}`\n\n`$column_number` will range from 1-4, i.e., if the block is set to have 2 columns the resulting class will be `columns-2`.\n\n##### `.is-style-squared`\n\nIf showing sharp corners for the story elements.\n\n##### `.is-style-default`\n\nIf showing curved corners for the story elements, default for the block.\n\n##### `.has-title`\n\nThis class is added for the circles carousel view, if it is showing the story titles.\n\n##### `.is-carousel`\n\nAdded for the Carousel view types.\n\n### `Inner wrapper`\n\n#### `.web-stories-list__inner-wrapper`\n\nAdded to the inner container which holds the story elements. For the generic view types, this will have story elements as direct children.\n\nThis element also adds CSS variables as inline styles based on the view type as mentioned here:\n\n* `--ws-circle-size`: Circle size value when using the circle carousel.\n* `--ws-story-max-width`: For the box carousel this adds the max-width for the story items.\n\n### Story element\n\nThis element encompasses the story elements like poster, title, author name etc.\n\n#### `.web-stories-list__story`\n\nStory element root.\n\n#### `.image-align-right`\n\nFor list view show image on right.\n\n### Story poster\n\n#### `.web-stories-list__story-poster`\n\nStory poster elements encapsulate either `<img />` or `<amp-img>` based on the type of request, whether it is AMP or non-AMP.\n\n### Story content overlay\n\n#### `.web-stories-list__story-content-overlay`\n\nContent overlay container.\n\n#### `.story-content-overlay__title`\n\nStory title element.\n\n#### `.story-content-overlay__excerpt`\n\nStory excerpt.\n\n#### `.story-content-overlay__author`\n\nStory author name.\n\n#### `.story-content-overlay__date`\n\nStory publish date.\n\n### Story Lightbox\n\nA story opens in a lightbox upon clicking it. This element contains the `<amp-story-player />` which embeds the story. There will be one lightbox wrapper per instance of Web Stories rendered on the page.\n\nThe lightbox renders a bit differently on AMP vs non-AMP pages. On non-AMP pages it uses a single lightbox container and renders all the stories as links in `<amp-story-player>`. This enables some of the extra features on non-AMP pages like skip through stories, auto-play next story.\n\nWhile on AMP pages it uses one `<amp-lightbox>` component for each story in the block.\n\n#### `.web-stories-list__lightbox-wrapper`\n\nThe lightbox wrapper will have an extra class to identify which instance it relates to. I.e., `ws-lightbox-{$i}` where `$i` is an integer, number of the instance.\n\n#### `.web-stories-list__lightbox`\n\nMain lightbox container.\n\n#### `.story-lightbox__close-button`\n\nOnly present on AMP pages, this is the lightbox close button element.\n"
  },
  {
    "path": "docs/workflows.md",
    "content": "# Workflows\n\n## Create plugin bundle\n\nTo create a build of the plugin for installing in WordPress as a ZIP package, run:\n\n```bash\nnpm run build # Build JS\nnpm run workflow:version [version] # Bump version number\nnpm run workflow:build-plugin -- [--composer] [--cdn  [url]] [--zip [filename] [--clean] # Creates a full build.\n```\n\n## Update list of available fonts\n\nThe project bundles an up-to-date list of available fonts from Google Fonts (plus some system fonts) that can be used in the editor.\n\nA workflow exists that automatically updates the list every time Google Fonts updates its catalogue. However, it can also be done manually if needed.\n\nA [Google Fonts API key](https://developers.google.com/fonts/docs/developer_api) is required to update said list. Check out the [Google fonts docs](https://developers.google.com/fonts/docs/developer_api) to learn how to obtain one.\n\nOnce obtained, follow these steps to configure the project appropriately:\n\n```bash\nexport GOOGLE_FONTS_API_KEY=your-api-key\nnpm run workflow:fonts\n```\n\nThis script does the following:\n\n1. Downloads all available fonts from Google Fonts\n1. Merges font list with a set of system fonts and prepares them for usage in the editor.\n1. Saves changes to `packages/fonts/src/fonts.json`.\n"
  },
  {
    "path": "includes/AMP/Canonical_Sanitizer.php",
    "content": "<?php\n/**\n * Class Canonical_Sanitizer.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse DOMElement;\nuse DOMNode;\nuse DOMNodeList;\nuse Google\\Web_Stories_Dependencies\\AMP_Base_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Attribute;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Tag;\n\n/**\n * Canonical sanitizer class.\n *\n * Ensures link[rel=canonical] exists on the page,\n * as some plugins might have removed it in the meantime\n * or the user might be viewing a draft.\n *\n * Only needed when the AMP plugin is not active, as the plugin\n * handles that already.\n *\n * @since 1.1.0\n *\n * @link https://github.com/googleforcreators/web-stories-wp/issues/4193\n * @link https://github.com/googleforcreators/web-stories-wp/pull/8169\n * @see \\AMP_Theme_Support::ensure_required_markup()\n */\nclass Canonical_Sanitizer extends AMP_Base_Sanitizer {\n\t/**\n\t * Sanitize the HTML contained in the DOMDocument received by the constructor.\n\t *\n\t * @since 1.1.0\n\t */\n\tpublic function sanitize(): void {\n\t\t$canonical_url = $this->args['canonical_url'];\n\n\t\t$query = $this->dom->xpath->query( '//link[@rel=\"canonical\"]', $this->dom->head );\n\n\t\t// Remove any duplicate items first.\n\t\tif ( $query instanceof DOMNodeList && $query->length > 1 ) {\n\t\t\tfor ( $i = 1; $i < $query->length; $i++ ) {\n\t\t\t\t$node = $query->item( $i );\n\t\t\t\tif ( $node ) {\n\t\t\t\t\t// @phpstan-ignore argument.type\n\t\t\t\t\t$this->dom->head->removeChild( $node );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * DOMElement\n\t\t *\n\t\t * @var DOMElement|DOMNode $rel_canonical\n\t\t */\n\t\t$rel_canonical = $query instanceof DOMNodeList ? $query->item( 0 ) : null;\n\n\t\tif ( ! $rel_canonical instanceof DOMElement ) {\n\t\t\t$rel_canonical = $this->dom->createElement( Tag::LINK );\n\n\t\t\tif ( $rel_canonical instanceof DOMElement ) {\n\t\t\t\t$rel_canonical->setAttribute( Attribute::REL, Attribute::REL_CANONICAL );\n\t\t\t\t$this->dom->head->appendChild( $rel_canonical );\n\t\t\t}\n\t\t}\n\n\t\tif ( $rel_canonical instanceof DOMElement ) {\n\t\t\t// Ensure link[rel=canonical] has a non-empty href attribute.\n\t\t\tif ( empty( $rel_canonical->getAttribute( Attribute::HREF ) ) ) {\n\t\t\t\t$rel_canonical->setAttribute( Attribute::HREF, (string) $canonical_url );\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Integration/AMP_Story_Sanitizer.php",
    "content": "<?php\n/**\n * Class AMP_Story_Sanitizer.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP\\Integration;\n\nuse AMP_Base_Sanitizer;\nuse Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils;\n\n/**\n * AMP Story sanitizer.\n *\n * Like Story_Sanitizer, but for use with the AMP WordPress plugin.\n *\n * @since 1.1.0\n *\n * @see Story_Sanitizer\n */\nclass AMP_Story_Sanitizer extends AMP_Base_Sanitizer {\n\tuse Sanitization_Utils;\n\n\t/**\n\t * Sanitize the HTML contained in the DOMDocument received by the constructor.\n\t *\n\t * @since 1.1.0\n\t */\n\tpublic function sanitize(): void {\n\t\t$this->transform_html_start_tag( $this->dom );\n\t\t$this->transform_a_tags( $this->dom );\n\t\t$this->use_semantic_heading_tags( $this->dom );\n\t\t$this->add_publisher_logo( $this->dom, $this->args['publisher_logo'] );\n\t\t$this->add_publisher( $this->dom, $this->args['publisher'] );\n\t\t$this->add_poster_images( $this->dom, $this->args['poster_images'] );\n\t\t// This needs to be called before use_semantic_heading_tags() because it relies on the style attribute.\n\t\t$this->deduplicate_inline_styles( $this->dom );\n\t\t$this->disable_first_page_animations( $this->dom );\n\t\t$this->add_video_cache( $this->dom, $this->args['video_cache'] );\n\t\t$this->remove_blob_urls( $this->dom );\n\t\t$this->sanitize_srcset( $this->dom );\n\t\t$this->sanitize_amp_story_page_outlink( $this->dom );\n\t\t$this->remove_page_template_placeholder_images( $this->dom );\n\t\t$this->sanitize_title_and_meta_description( $this->dom, $this->args['title_tag'], $this->args['description'] );\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Meta_Sanitizer.php",
    "content": "<?php\n/**\n * Class Meta_Sanitizer.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse Google\\Web_Stories_Dependencies\\AMP_Meta_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Attribute;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Tag;\n\n/**\n * Meta sanitizer.\n *\n * Sanitizes meta tags found in the header.\n *\n * This version avoids using amp_get_boilerplate_stylesheets().\n *\n * @since 1.1.0\n *\n * @see amp_get_boilerplate_stylesheets()\n * @see AMP_Meta_Sanitizer\n */\nclass Meta_Sanitizer extends AMP_Meta_Sanitizer {\n\t/**\n\t * Always ensure we have a style[amp-boilerplate] and a noscript>style[amp-boilerplate].\n\t *\n\t * The AMP boilerplate ({@link https://amp.dev/documentation/guides-and-tutorials/stories/learn/spec/amp-boilerplate}) styles should appear at the end of the head:\n\t * \"Finally, specify the AMP boilerplate code. By putting the boilerplate code last, it prevents custom styles from\n\t * accidentally overriding the boilerplate css rules.\"\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/optimize_amp/#optimize-the-amp-runtime-loading\n\t */\n\tprotected function ensure_boilerplate_is_present(): void {\n\t\t$style  = null;\n\t\t$styles = $this->dom->xpath->query( './style[ @amp-boilerplate ]', $this->dom->head );\n\n\t\tif ( $styles ) {\n\t\t\t$style = $styles->item( 0 );\n\t\t}\n\n\t\tif ( ! $style ) {\n\t\t\t$style = $this->dom->createElement( Tag::STYLE );\n\t\t\tif ( $style ) {\n\t\t\t\t$style->setAttribute( Attribute::AMP_BOILERPLATE, '' );\n\t\t\t\t$style->appendChild( $this->dom->createTextNode( $this->get_boilerplate_stylesheets()[0] ) );\n\t\t\t}\n\t\t} elseif ( $style->parentNode ) {\n\t\t\t$style->parentNode->removeChild( $style ); // So we can move it.\n\t\t}\n\t\tif ( $style ) {\n\t\t\t// @phpstan-ignore argument.type\n\t\t\t$this->dom->head->appendChild( $style );\n\t\t}\n\n\t\t$noscript  = null;\n\t\t$noscripts = $this->dom->xpath->query( './noscript[ style[ @amp-boilerplate ] ]', $this->dom->head );\n\n\t\tif ( $noscripts ) {\n\t\t\t$noscript = $noscripts->item( 0 );\n\t\t}\n\n\t\tif ( ! $noscript ) {\n\t\t\t$noscript = $this->dom->createElement( Tag::NOSCRIPT );\n\t\t\t$style    = $this->dom->createElement( Tag::STYLE );\n\t\t\tif ( $style && $noscript ) {\n\t\t\t\t$style->setAttribute( Attribute::AMP_BOILERPLATE, '' );\n\t\t\t\t$style->appendChild( $this->dom->createTextNode( $this->get_boilerplate_stylesheets()[1] ) );\n\t\t\t\t$noscript->appendChild( $style );\n\t\t\t}\n\t\t} elseif ( $noscript->parentNode ) {\n\t\t\t$noscript->parentNode->removeChild( $noscript ); // So we can move it.\n\t\t}\n\n\t\tif ( $noscript ) {\n\t\t\t// @phpstan-ignore argument.type\n\t\t\t$this->dom->head->appendChild( $noscript );\n\t\t}\n\t}\n\n\t/**\n\t * Get AMP boilerplate stylesheets.\n\t *\n\t * Clone of amp_get_boilerplate_stylesheets().\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://www.ampproject.org/docs/reference/spec#boilerplate\n\t * @see amp_get_boilerplate_stylesheets()\n\t *\n\t * @return string[] Stylesheets, where first is contained in style[amp-boilerplate] and the second in noscript>style[amp-boilerplate].\n\t */\n\tprotected function get_boilerplate_stylesheets(): array {\n\t\treturn [\n\t\t\t'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',\n\t\t\t'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Optimization.php",
    "content": "<?php\n/**\n * Class Optimization\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse Google\\Web_Stories_Dependencies\\AmpProject\\AmpWP\\RemoteRequest\\CachedRemoteGetRequest;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\AmpWP\\RemoteRequest\\WpHttpRemoteGetRequest;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Configuration;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Configuration\\AmpStoryCssOptimizerConfiguration;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\DefaultConfiguration;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Error;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\ErrorCollection;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\LocalFallback;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\TransformationEngine;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpRuntimeCss;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpStoryCssOptimizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\MinifyHtml;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\OptimizeAmpBind;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\OptimizeHeroImages;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\RewriteAmpUrls;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\ServerSideRendering;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\TransformedIdentifier;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\RemoteRequest\\FallbackRemoteGetRequest;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\RemoteRequest\\FilesystemRemoteGetRequest;\n\n/**\n * Optimization class.\n *\n * @since 1.1.0\n */\nclass Optimization {\n\t/**\n\t * Optimizes a document.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document $document Document instance.\n\t */\n\tpublic function optimize_document( Document $document ): void {\n\t\t$errors = new ErrorCollection();\n\t\t$this->get_optimizer()->optimizeDom( $document, $errors );\n\t\tif ( \\count( $errors ) > 0 ) {\n\t\t\t/**\n\t\t\t * Error list.\n\t\t\t *\n\t\t\t * @var Error[] $errors_array Error list.\n\t\t\t */\n\t\t\t$errors_array = iterator_to_array( $errors );\n\n\t\t\t$error_messages = array_filter(\n\t\t\t\tarray_map(\n\t\t\t\t\tstatic function ( Error $error ) {\n\t\t\t\t\t\t// Hidden because amp-story is a render-delaying extension.\n\t\t\t\t\t\tif ( 'CannotRemoveBoilerplate' === $error->getCode() ) {\n\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn ' - ' . $error->getCode() . ': ' . $error->getMessage();\n\t\t\t\t\t},\n\t\t\t\t\t$errors_array\n\t\t\t\t)\n\t\t\t);\n\n\t\t\tif ( ! empty( $error_messages ) ) {\n\t\t\t\t$document->head->appendChild(\n\t\t\t\t\t$document->createComment( \"\\n\" . __( 'AMP optimization could not be completed due to the following:', 'web-stories' ) . \"\\n\" . implode( \"\\n\", $error_messages ) . \"\\n\" )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Optimizer instance to use.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/8856284d90fc8558c30acc029becd352ae26e4e1/includes/class-amp-theme-support.php#L2235-L2255\n\t * @see AMP_Theme_Support::get_optimizer\n\t *\n\t * @return TransformationEngine Optimizer transformation engine to use.\n\t */\n\tprivate function get_optimizer(): TransformationEngine {\n\t\t$configuration = self::get_optimizer_configuration();\n\n\t\t$fallback_remote_request_pipeline = new FallbackRemoteGetRequest(\n\t\t\tnew WpHttpRemoteGetRequest(),\n\t\t\tnew FilesystemRemoteGetRequest( LocalFallback::getMappings() )\n\t\t);\n\n\t\t$cached_remote_request = new CachedRemoteGetRequest( $fallback_remote_request_pipeline, WEEK_IN_SECONDS );\n\n\t\treturn new TransformationEngine(\n\t\t\t$configuration,\n\t\t\t$cached_remote_request\n\t\t);\n\t}\n\n\t/**\n\t * Get the AmpProject\\Optimizer configuration object to use.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/5405daa38e65f0ec16ffc920014d0110b03ee773/src/Optimizer/AmpWPConfiguration.php#L43-L78\n\t * @see AmpWPConfiguration::apply_filters()\n\t *\n\t * @return Configuration Optimizer configuration to use.\n\t */\n\tprivate static function get_optimizer_configuration(): Configuration {\n\t\t$transformers = Configuration::DEFAULT_TRANSFORMERS;\n\n\t\t$transformers[] = AmpStoryCssOptimizer::class;\n\n\t\t/**\n\t\t * Filter whether the AMP Optimizer should use server-side rendering or not.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @param bool $enable_ssr Whether the AMP Optimizer should use server-side rendering or not.\n\t\t */\n\t\t$enable_ssr = apply_filters( 'web_stories_enable_ssr', true );\n\n\t\t// In debugging mode, we don't use server-side rendering, as it further obfuscates the HTML markup.\n\t\tif ( ! $enable_ssr ) {\n\t\t\t$transformers = array_diff(\n\t\t\t\t$transformers,\n\t\t\t\t[\n\t\t\t\t\tAmpRuntimeCss::class,\n\t\t\t\t\tOptimizeHeroImages::class,\n\t\t\t\t\tOptimizeAmpBind::class,\n\t\t\t\t\tRewriteAmpUrls::class,\n\t\t\t\t\tServerSideRendering::class,\n\t\t\t\t\tTransformedIdentifier::class,\n\t\t\t\t\tAmpStoryCssOptimizer::class,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\t$configuration = [\n\t\t\tConfiguration::KEY_TRANSFORMERS => $transformers,\n\t\t\tAmpStoryCssOptimizer::class     => [\n\t\t\t\tAmpStoryCssOptimizerConfiguration::OPTIMIZE_AMP_STORY => true,\n\t\t\t],\n\t\t\tMinifyHtml::class               => [\n\t\t\t\t// Prevents issues with rounding floats, relevant for things like shopping (product prices).\n\t\t\t\tConfiguration\\MinifyHtmlConfiguration::MINIFY_JSON => false,\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filter the configuration to be used for the AMP Optimizer.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @param array $configuration Associative array of configuration data.\n\t\t */\n\t\t$configuration = apply_filters( 'web_stories_amp_optimizer_config', $configuration );\n\n\t\treturn new DefaultConfiguration( $configuration );\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Output_Buffer.php",
    "content": "<?php\n/**\n * Class Output_Buffer\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Exception\\SanitizationException;\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse Throwable;\n\n/**\n * Output buffer class.\n *\n * Largely copied from AMP_Theme_Support.\n *\n * @since 1.10.0\n *\n * @see \\AMP_Theme_Support\n */\nclass Output_Buffer extends Service_Base implements Conditional {\n\n\t/**\n\t * Whether output buffering has started.\n\t */\n\tprotected bool $is_output_buffering = false;\n\n\t/**\n\t * Sanitization instance.\n\t *\n\t * @var Sanitization Sanitization instance.\n\t */\n\tprivate Sanitization $sanitization;\n\n\t/**\n\t * Optimization instance.\n\t *\n\t * @var Optimization Optimization instance.\n\t */\n\tprivate Optimization $optimization;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Output_Buffer constructor.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param Sanitization $sanitization Sanitization instance.\n\t * @param Optimization $optimization Optimization instance.\n\t * @param Context      $context Context instance.\n\t */\n\tpublic function __construct( Sanitization $sanitization, Optimization $optimization, Context $context ) {\n\t\t$this->sanitization = $sanitization;\n\t\t$this->optimization = $optimization;\n\t\t$this->context      = $context;\n\t}\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t/*\n\t\t * Start output buffering at very low priority for sake of plugins and themes that use template_redirect\n\t\t * instead of template_include.\n\t\t */\n\t\t$this->start_output_buffering();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'template_redirect';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn PHP_INT_MIN;\n\t}\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * If the AMP plugin is installed and available in a version >= than ours,\n\t * all sanitization and optimization should be delegated to the AMP plugin.\n\t * But ONLY if AMP logic has not been disabled through any of its available filters.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\t$current_post = get_post();\n\n\t\t$has_old_amp_version = ! \\defined( '\\AMP__VERSION' ) || ( \\defined( '\\AMP__VERSION' ) && version_compare( \\AMP__VERSION, WEBSTORIES_AMP_VERSION, '<' ) );\n\t\t$amp_available       = \\function_exists( 'amp_is_available' ) && amp_is_available();\n\n\t\t// @phpstan-ignore function.internal\n\t\t$amp_enabled        = \\function_exists( 'amp_is_enabled' ) && amp_is_enabled();\n\t\t$amp_initialized    = did_action( 'amp_init' ) > 0;\n\t\t$amp_supported_post = \\function_exists( 'amp_is_post_supported' ) && amp_is_post_supported( $current_post->ID ?? 0 );\n\n\t\treturn $has_old_amp_version || ! $amp_available || ! $amp_enabled || ! $amp_initialized || ! $amp_supported_post;\n\t}\n\n\t/**\n\t * Start output buffering.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @see Output_Buffer::finish_output_buffering()\n\t */\n\tpublic function start_output_buffering(): void {\n\t\tif ( ! $this->context->is_web_story() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tob_start( [ $this, 'finish_output_buffering' ] );\n\t\t$this->is_output_buffering = true;\n\t}\n\n\t/**\n\t * Determine whether output buffering has started.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @see Output_Buffer::start_output_buffering()\n\t * @see Output_Buffer::finish_output_buffering()\n\t *\n\t * @return bool Whether output buffering has started.\n\t */\n\tpublic function is_output_buffering(): bool {\n\t\treturn $this->is_output_buffering;\n\t}\n\n\t/**\n\t * Finish output buffering.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @see Output_Buffer::start_output_buffering()\n\t *\n\t * @param string $response Buffered Response.\n\t * @return string Processed Response.\n\t */\n\tpublic function finish_output_buffering( string $response ): string {\n\t\t$this->is_output_buffering = false;\n\n\t\ttry {\n\t\t\t$response = $this->prepare_response( $response );\n\t\t} catch ( \\Error $error ) { // Only PHP 7+.\n\t\t\t$response = $this->render_error_page( $error );\n\t\t} catch ( \\Exception $exception ) {\n\t\t\t$response = $this->render_error_page( $exception );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Process response to ensure AMP validity.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param string $response HTML document response. By default it expects a complete document.\n\t * @return string AMP document response.\n\t */\n\tpublic function prepare_response( string $response ): string {\n\t\t// Enforce UTF-8 encoding as it is a requirement for AMP.\n\t\tif ( ! headers_sent() ) {\n\t\t\theader( 'Content-Type: text/html; charset=utf-8' );\n\t\t}\n\n\t\t$dom = Document::fromHtml( $response );\n\n\t\tif ( ! $dom instanceof Document ) {\n\t\t\treturn $this->render_error_page( SanitizationException::from_document_parse_error() );\n\t\t}\n\n\t\t$this->sanitization->sanitize_document( $dom );\n\t\t$this->optimization->optimize_document( $dom );\n\n\t\treturn $dom->saveHTML();\n\t}\n\n\t/**\n\t * Render error page.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param Throwable $throwable Exception or (as of PHP7) Error.\n\t * @return string Error page.\n\t */\n\tprivate function render_error_page( Throwable $throwable ): string {\n\t\treturn esc_html__( 'There was an error generating the web story, probably because of a server misconfiguration. Try contacting your hosting provider or open a new support request.', 'web-stories' ) .\n\t\t\t\"\\n\" .\n\t\t\t\"\\n\" .\n\t\t\t// translators: 1: error message. 2: location.\n\t\t\t\\sprintf( esc_html__( 'Error message: %1$s (%2$s)', 'web-stories' ), $throwable->getMessage(), $throwable->getFile() . ':' . $throwable->getLine() );\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Sanitization.php",
    "content": "<?php\n/**\n * Class Sanitization\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse DOMElement;\nuse DOMNode;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories_Dependencies\\AMP_Allowed_Tags_Generated;\nuse Google\\Web_Stories_Dependencies\\AMP_Content_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Dev_Mode_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_DOM_Utils;\nuse Google\\Web_Stories_Dependencies\\AMP_Layout_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Script_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Style_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Amp;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Extension;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Attribute;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Html\\Tag;\n\n/**\n * Sanitization class.\n *\n * Largely copied from AMP_Theme_Support.\n *\n * @since 1.1.0\n *\n * @see \\AMP_Theme_Support\n */\nclass Sanitization {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings    Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Sanitizes a document.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document $document Document instance.\n\t */\n\tpublic function sanitize_document( Document $document ): void {\n\t\t$sanitizers = $this->get_sanitizers();\n\n\t\t$result = AMP_Content_Sanitizer::sanitize_document( $document, $sanitizers, [] );\n\n\t\t$this->ensure_required_markup( $document, $result['scripts'] );\n\t}\n\n\t/**\n\t * Validation error callback.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @see AMP_Validation_Error_Taxonomy::get_validation_error_sanitization\n\t *\n\t * @param array{code: string}              $error Error info, especially code.\n\t * @param array{node?: DOMElement|DOMNode} $data Additional data, including the node.\n\t * @return bool Whether the validation error should be sanitized.\n\t */\n\tpublic function validation_error_callback( array $error, array $data = [] ): bool { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed\n\t\t/**\n\t\t * Filters whether the validation error should be sanitized.\n\t\t *\n\t\t * Returning true this indicates that the validation error is acceptable\n\t\t * and should not be considered a blocker to render AMP. Returning null\n\t\t * means that the default status should be used.\n\t\t *\n\t\t * Note that the $node is not passed here to ensure that the filter can be\n\t\t * applied on validation errors that have been stored. Likewise, the $sources\n\t\t * are also omitted because these are only available during an explicit\n\t\t * validation request and so they are not suitable for plugins to vary\n\t\t * sanitization by.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @see AMP_Validation_Manager::is_sanitization_auto_accepted() Which controls whether an error is initially accepted or rejected for sanitization.\n\t\t *\n\t\t * @param bool $sanitized Whether the validation error should be sanitized.\n\t\t * @param array $error Validation error being sanitized.\n\t\t */\n\t\treturn apply_filters( 'web_stories_amp_validation_error_sanitized', true, $error );\n\t}\n\n\t/**\n\t * Adds missing scripts.\n\t *\n\t * @SuppressWarnings(\"PHPMD\")\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/2.1.3/includes/class-amp-theme-support.php#L1381-L1594\n\t * @see \\AMP_Theme_Support::ensure_required_markup\n\t *\n\t * @param Document             $document Document instance.\n\t * @param array<string,string> $scripts  List of found scripts.\n\t */\n\tprotected function ensure_required_markup( Document $document, array $scripts ): void { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\t/**\n\t\t * Link elements.\n\t\t *\n\t\t * @var array{preconnect: \\DOMElement[]|null,dns-prefetch: \\DOMElement[]|null,preload: \\DOMElement[]|null, prerender: \\DOMElement[]|null, prefetch: \\DOMElement[]|null }\n\t\t */\n\t\t$links = [\n\t\t\tAttribute::REL_PRECONNECT => [\n\t\t\t\t// Include preconnect link for AMP CDN for browsers that don't support preload.\n\t\t\t\tAMP_DOM_Utils::create_node(\n\t\t\t\t\t$document,\n\t\t\t\t\tTag::LINK,\n\t\t\t\t\t[\n\t\t\t\t\t\tAttribute::REL  => Attribute::REL_PRECONNECT,\n\t\t\t\t\t\tAttribute::HREF => 'https://cdn.ampproject.org',\n\t\t\t\t\t]\n\t\t\t\t),\n\t\t\t],\n\t\t];\n\n\t\t// Obtain the existing AMP scripts.\n\t\t$amp_scripts     = [];\n\t\t$ordered_scripts = [];\n\t\t$head_scripts    = [];\n\t\t$runtime_src     = 'https://cdn.ampproject.org/v0.js';\n\n\t\t/**\n\t\t * Script element.\n\t\t *\n\t\t * @var DOMElement $script\n\t\t */\n\t\tforeach ( $document->head->getElementsByTagName( Tag::SCRIPT ) as $script ) {\n\t\t\t$head_scripts[] = $script;\n\t\t}\n\n\t\tforeach ( $head_scripts as $script ) {\n\t\t\t$src = $script->getAttribute( Attribute::SRC );\n\n\t\t\tif ( ! $src || ! str_starts_with( $src, 'https://cdn.ampproject.org/' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( 'v0.js' === substr( $src, - \\strlen( 'v0.js' ) ) ) {\n\t\t\t\t$amp_scripts[ Amp::RUNTIME ] = $script;\n\t\t\t} elseif ( $script->hasAttribute( Attribute::CUSTOM_ELEMENT ) ) {\n\t\t\t\t$amp_scripts[ $script->getAttribute( Attribute::CUSTOM_ELEMENT ) ] = $script;\n\t\t\t} elseif ( $script->hasAttribute( Attribute::CUSTOM_TEMPLATE ) ) {\n\t\t\t\t$amp_scripts[ $script->getAttribute( Attribute::CUSTOM_TEMPLATE ) ] = $script;\n\t\t\t}\n\n\t\t\t// It will be added back further down.\n\t\t\t$document->head->removeChild( $script );\n\t\t}\n\n\t\t$specs = $this->get_extension_sources();\n\n\t\t// Create scripts for any components discovered from output buffering that are missing.\n\t\tforeach ( array_diff( array_keys( $scripts ), array_keys( $amp_scripts ) ) as $missing_script_handle ) {\n\t\t\t$attrs = [\n\t\t\t\tAttribute::SRC   => $specs[ $missing_script_handle ],\n\t\t\t\tAttribute::ASYNC => '',\n\t\t\t];\n\t\t\tif ( Extension::MUSTACHE === $missing_script_handle ) {\n\t\t\t\t$attrs[ Attribute::CUSTOM_TEMPLATE ] = (string) $missing_script_handle;\n\t\t\t} else {\n\t\t\t\t$attrs[ Attribute::CUSTOM_ELEMENT ] = (string) $missing_script_handle;\n\t\t\t}\n\n\t\t\t$amp_scripts[ $missing_script_handle ] = AMP_DOM_Utils::create_node( $document, Tag::SCRIPT, $attrs );\n\t\t}\n\n\t\t// Remove scripts that had already been added but couldn't be detected from output buffering.\n\t\t$extension_specs            = AMP_Allowed_Tags_Generated::get_extension_specs();\n\t\t$superfluous_script_handles = array_diff(\n\t\t\tarray_keys( $amp_scripts ),\n\t\t\t[ ...array_keys( $scripts ), Amp::RUNTIME ]\n\t\t);\n\n\t\tforeach ( $superfluous_script_handles as $superfluous_script_handle ) {\n\t\t\tif ( ! empty( $extension_specs[ $superfluous_script_handle ]['requires_usage'] ) ) {\n\t\t\t\tunset( $amp_scripts[ $superfluous_script_handle ] );\n\t\t\t}\n\t\t}\n\n\t\t/* phpcs:ignore Squiz.PHP.CommentedOutCode.Found\n\t\t *\n\t\t * \"2. Next, preload the AMP runtime v0.js <script> tag with <link as=script href=https://cdn.ampproject.org/v0.js rel=preload>.\n\t\t * The AMP runtime should start downloading as soon as possible because the AMP boilerplate hides the document via body { visibility:hidden }\n\t\t * until the AMP runtime has loaded. Preloading the AMP runtime tells the browser to download the script with a higher priority.\"\n\t\t * {@link https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/optimize_amp/ Optimize the AMP Runtime loading}\n\t\t */\n\t\t$prioritized_preloads = [];\n\t\tif ( ! isset( $links[ Attribute::REL_PRELOAD ] ) ) {\n\t\t\t$links[ Attribute::REL_PRELOAD ] = [];\n\t\t}\n\n\t\t$prioritized_preloads[] = AMP_DOM_Utils::create_node(\n\t\t\t$document,\n\t\t\tTag::LINK,\n\t\t\t[\n\t\t\t\tAttribute::REL  => Attribute::REL_PRELOAD,\n\t\t\t\t'as'            => Tag::SCRIPT,\n\t\t\t\tAttribute::HREF => $runtime_src,\n\t\t\t]\n\t\t);\n\n\t\t/*\n\t\t * \"3. If your page includes render-delaying extensions (e.g., amp-experiment, amp-dynamic-css-classes, amp-story),\n\t\t * preload those extensions as they're required by the AMP runtime for rendering the page.\"\n\t\t */\n\t\t$amp_script_handles = array_keys( $amp_scripts );\n\t\tforeach ( array_intersect( Amp::RENDER_DELAYING_EXTENSIONS, $amp_script_handles ) as $script_handle ) {\n\t\t\tif ( ! \\in_array( $script_handle, Amp::RENDER_DELAYING_EXTENSIONS, true ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * AMP script element.\n\t\t\t *\n\t\t\t * @var DOMElement $script_element\n\t\t\t */\n\t\t\t$script_element = $amp_scripts[ $script_handle ];\n\n\t\t\t$prioritized_preloads[] = AMP_DOM_Utils::create_node(\n\t\t\t\t$document,\n\t\t\t\tTag::LINK,\n\t\t\t\t[\n\t\t\t\t\tAttribute::REL  => Attribute::REL_PRELOAD,\n\t\t\t\t\t'as'            => Tag::SCRIPT,\n\t\t\t\t\tAttribute::HREF => $script_element->getAttribute( Attribute::SRC ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\t\t$links[ Attribute::REL_PRELOAD ] = array_merge( $prioritized_preloads, $links[ Attribute::REL_PRELOAD ] );\n\n\t\t// Store the last meta tag as the previous node to append to.\n\t\t$meta_tags     = $document->head->getElementsByTagName( Tag::META );\n\t\t$previous_node = $meta_tags->length > 0 ? $meta_tags->item( $meta_tags->length - 1 ) : $document->head->firstChild;\n\n\t\t/*\n\t\t * \"4. Use preconnect to speedup the connection to other origin where the full resource URL is not known ahead of time,\n\t\t * for example, when using Google Fonts.\"\n\t\t *\n\t\t * Note that \\AMP_Style_Sanitizer::process_link_element() will ensure preconnect links for Google Fonts are present.\n\t\t */\n\t\t$link_relations = [ Attribute::REL_PRECONNECT, Attribute::REL_DNS_PREFETCH, Attribute::REL_PRELOAD, Attribute::REL_PRERENDER, Attribute::REL_PREFETCH ];\n\t\tforeach ( $link_relations as $rel ) {\n\t\t\tif ( ! isset( $links[ $rel ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Link node.\n\t\t\t *\n\t\t\t * @var DOMElement $link\n\t\t\t */\n\t\t\tforeach ( $links[ $rel ] as $link ) {\n\t\t\t\tif ( $link->parentNode ) {\n\t\t\t\t\t$link->parentNode->removeChild( $link ); // So we can move it.\n\t\t\t\t}\n\t\t\t\tif ( $previous_node && $previous_node->nextSibling ) {\n\t\t\t\t\t$document->head->insertBefore( $link, $previous_node->nextSibling );\n\t\t\t\t\t$previous_node = $link;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// \"5. Load the AMP runtime.\"\n\t\tif ( isset( $amp_scripts[ Amp::RUNTIME ] ) ) {\n\t\t\t$ordered_scripts[ Amp::RUNTIME ] = $amp_scripts[ Amp::RUNTIME ];\n\t\t\tunset( $amp_scripts[ Amp::RUNTIME ] );\n\t\t} else {\n\t\t\t$script = $document->createElement( Tag::SCRIPT );\n\t\t\tif ( $script ) {\n\t\t\t\t$script->setAttribute( Attribute::ASYNC, '' );\n\t\t\t\t$script->setAttribute( Attribute::SRC, $runtime_src );\n\t\t\t\t$ordered_scripts[ Amp::RUNTIME ] = $script;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * \"6. Specify the <script> tags for render-delaying extensions (e.g., amp-experiment amp-dynamic-css-classes and amp-story\"\n\t\t *\n\t\t * {@link https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/optimize_amp/ AMP Hosting Guide}\n\t\t */\n\t\tforeach ( Amp::RENDER_DELAYING_EXTENSIONS as $extension ) {\n\t\t\tif ( isset( $amp_scripts[ $extension ] ) ) {\n\t\t\t\t$ordered_scripts[ $extension ] = $amp_scripts[ $extension ];\n\t\t\t\tunset( $amp_scripts[ $extension ] );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * \"7. Specify the <script> tags for remaining extensions (e.g., amp-bind ...). These extensions are not render-delaying\n\t\t * and therefore should not be preloaded as they might take away important bandwidth for the initial render.\"\n\t\t */\n\t\tksort( $amp_scripts );\n\t\t$ordered_scripts = array_merge( $ordered_scripts, $amp_scripts );\n\n\t\t/**\n\t\t * Script element.\n\t\t *\n\t\t * @var DOMElement $ordered_script\n\t\t */\n\t\tforeach ( $ordered_scripts as $ordered_script ) {\n\t\t\tif ( $previous_node && $previous_node->nextSibling ) {\n\t\t\t\t$document->head->insertBefore( $ordered_script, $previous_node->nextSibling );\n\t\t\t\t$previous_node = $ordered_script;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns AMP extension URLs, keyed by extension name.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/2.1.3/includes/amp-helper-functions.php#L876-L941\n\t * @see amp_register_default_scripts\n\t *\n\t * @return array<string,string> List of extensions and their URLs.\n\t */\n\tprotected function get_extension_sources(): array {\n\t\t$specs = [];\n\t\t// Register all AMP components as defined in the spec.\n\t\tforeach ( AMP_Allowed_Tags_Generated::get_extension_specs() as $extension_name => $extension_spec ) {\n\t\t\t$src = \\sprintf(\n\t\t\t\t'https://cdn.ampproject.org/v0/%s-%s.js',\n\t\t\t\t$extension_name,\n\t\t\t\t$extension_spec['latest']\n\t\t\t);\n\n\t\t\t$specs[ $extension_name ] = $src;\n\t\t}\n\n\t\treturn $specs;\n\t}\n\n\t/**\n\t * Determine whether AMP dev mode is enabled.\n\t *\n\t * When enabled, the <html> element will get the data-ampdevmode attribute and the plugin will add the same attribute\n\t * to elements associated with the admin bar and other elements that are provided by the `amp_dev_mode_element_xpaths`\n\t * filter.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/2.1.3/includes/amp-helper-functions.php#L1296-L1330\n\t * @see amp_is_dev_mode\n\t *\n\t * @return bool Whether AMP dev mode is enabled.\n\t */\n\tprotected function is_amp_dev_mode(): bool {\n\t\t// For the few sites that forcibly show the admin bar even when the user is logged out, only enable dev\n\t\t// mode if the user is actually logged in. This prevents the dev mode from being served to crawlers\n\t\t// when they index the AMP version.\n\t\t$dev_mode_enabled = ( is_admin_bar_showing() && is_user_logged_in() );\n\n\t\t/**\n\t\t * Filters whether AMP dev mode is enabled.\n\t\t *\n\t\t * When enabled, the data-ampdevmode attribute will be added to the document element and it will allow the\n\t\t * attributes to be added to the admin bar. It will also add the attribute to all elements which match the\n\t\t * queries for the expressions returned by the 'web_stories_amp_dev_mode_element_xpaths' filter.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @param bool $dev_mode_enabled Whether AMP dev mode is enabled.\n\t\t */\n\t\treturn apply_filters( 'web_stories_amp_dev_mode_enabled', $dev_mode_enabled );\n\t}\n\n\t/**\n\t * Returns a list of sanitizers to use.\n\t *\n\t * This is replica of amp_get_content_sanitizers() to avoid\n\t * loading amp-helper-functions.php due to side-effects like\n\t * accessing options from the database, requiring AMP__VERSION,\n\t * and causing conflicts with our own amp_is_request() compat shim.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.1.0\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/2.1.3/includes/amp-helper-functions.php#L1332-L1521\n\t * @link https://github.com/ampproject/amp-wp/blob/2.1.3/includes/validation/class-amp-validation-manager.php#L1691-L1730\n\t * @see amp_get_content_sanitizers\n\t * @see AMP_Validation_Manager::filter_sanitizer_args\n\t *\n\t * @return array<string,array<string,bool|string[]|string>> Sanitizers.\n\t */\n\tprotected function get_sanitizers(): array {\n\t\t// This fallback to get_permalink() ensures that there's a canonical link\n\t\t// even when previewing drafts.\n\t\t$canonical_url = wp_get_canonical_url();\n\t\tif ( ! $canonical_url ) {\n\t\t\t$canonical_url = get_permalink();\n\t\t}\n\n\t\t$sanitizers = [\n\t\t\tAMP_Script_Sanitizer::class        => [\n\t\t\t\t'sanitize_js_scripts' => true,\n\t\t\t],\n\t\t\tAMP_Style_Sanitizer::class         => [\n\n\t\t\t\t/*\n\t\t\t\t * @todo Enable by default and allow filtering once AMP_Style_Sanitizer does not call AMP_Options_Manager\n\t\t\t\t *       which in turn requires AMP__VERSION to be defined.\n\t\t\t\t */\n\t\t\t\t'allow_transient_caching'   => false,\n\t\t\t\t'use_document_element'      => true,\n\t\t\t\t'dynamic_element_selectors' => [\n\t\t\t\t\t'amp-story-captions',\n\t\t\t\t],\n\t\t\t],\n\t\t\tMeta_Sanitizer::class              => [],\n\t\t\tAMP_Layout_Sanitizer::class        => [],\n\t\t\tCanonical_Sanitizer::class         => [\n\t\t\t\t'canonical_url' => $canonical_url,\n\t\t\t],\n\t\t\tTag_And_Attribute_Sanitizer::class => [],\n\t\t];\n\n\t\t$post = get_queried_object();\n\n\t\tif ( $post instanceof \\WP_Post && Story_Post_Type::POST_TYPE_SLUG === get_post_type( $post ) ) {\n\t\t\t$video_cache_enabled = (bool) $this->settings->get_setting( $this->settings::SETTING_NAME_VIDEO_CACHE );\n\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $post );\n\n\t\t\t$poster_images = [\n\t\t\t\t'poster-portrait-src' => esc_url_raw( $story->get_poster_portrait() ),\n\t\t\t];\n\n\t\t\t$sanitizers[ Story_Sanitizer::class ] = [\n\t\t\t\t'publisher_logo' => (string) $story->get_publisher_logo_url(),\n\t\t\t\t'publisher'      => $story->get_publisher_name(),\n\t\t\t\t'poster_images'  => array_filter( $poster_images ),\n\t\t\t\t'video_cache'    => $video_cache_enabled,\n\t\t\t\t'title_tag'      => wp_get_document_title(),\n\t\t\t\t'description'    => wp_strip_all_tags( get_the_excerpt() ),\n\t\t\t];\n\t\t}\n\n\t\t/**\n\t\t * Filters the content sanitizers.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @param array  $sanitizers Sanitizers.\n\t\t */\n\t\t$sanitizers = apply_filters( 'web_stories_amp_sanitizers', $sanitizers );\n\n\t\tif ( $this->is_amp_dev_mode() ) {\n\t\t\t/**\n\t\t\t * Filters the XPath queries for elements that should be enabled for dev mode.\n\t\t\t *\n\t\t\t * By supplying XPath queries to this filter, the data-ampdevmode attribute will automatically be added to the\n\t\t\t * root HTML element as well as to any elements that match the expressions. The attribute is added to the\n\t\t\t * elements prior to running any of the sanitizers.\n\t\t\t *\n\t\t\t * @since 1.3\n\t\t\t *\n\t\t\t * @param string[] $element_xpaths XPath element queries. Context is the root element.\n\t\t\t */\n\t\t\t$dev_mode_xpaths = apply_filters( 'web_stories_amp_dev_mode_element_xpaths', [] );\n\n\t\t\tif ( is_admin_bar_showing() ) {\n\t\t\t\t$dev_mode_xpaths[] = '//*[ @id = \"wpadminbar\" ]';\n\t\t\t\t$dev_mode_xpaths[] = '//*[ @id = \"wpadminbar\" ]//*';\n\t\t\t\t$dev_mode_xpaths[] = '//style[ @id = \"admin-bar-inline-css\" ]';\n\t\t\t}\n\n\t\t\t$sanitizers = array_merge(\n\t\t\t\t[\n\t\t\t\t\tAMP_Dev_Mode_Sanitizer::class => [\n\t\t\t\t\t\t'element_xpaths' => $dev_mode_xpaths,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t$sanitizers\n\t\t\t);\n\t\t}\n\n\t\t// Force certain sanitizers to be at end.\n\t\t// AMP_Style_Sanitizer needs to catch any CSS changes from previous sanitizers.\n\t\t// Tag_And_Attribute_Sanitizer must come at the end to clean up any remaining issues the other sanitizers didn't catch.\n\t\tforeach ( [\n\t\t\tAMP_Layout_Sanitizer::class,\n\t\t\tAMP_Style_Sanitizer::class,\n\t\t\tMeta_Sanitizer::class,\n\t\t\tTag_And_Attribute_Sanitizer::class,\n\t\t] as $class_name ) {\n\t\t\tif ( isset( $sanitizers[ $class_name ] ) ) {\n\t\t\t\t$sanitizer = $sanitizers[ $class_name ];\n\t\t\t\tunset( $sanitizers[ $class_name ] );\n\t\t\t\t$sanitizers[ $class_name ] = $sanitizer;\n\t\t\t}\n\t\t}\n\n\t\tforeach ( $sanitizers as &$sanitizer ) {\n\t\t\t$sanitizer['validation_error_callback'] = [ $this, 'validation_error_callback' ];\n\t\t}\n\n\t\tunset( $sanitizer );\n\n\t\treturn $sanitizers;\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Story_Sanitizer.php",
    "content": "<?php\n/**\n * Class Story_Sanitizer.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils;\nuse Google\\Web_Stories_Dependencies\\AMP_Base_Sanitizer;\n\n/**\n * Story sanitizer.\n *\n * Sanitizer for Web Stories related features.\n *\n * @since 1.1.0\n */\nclass Story_Sanitizer extends AMP_Base_Sanitizer {\n\tuse Sanitization_Utils;\n\n\t/**\n\t * Sanitize the HTML contained in the DOMDocument received by the constructor.\n\t *\n\t * @since 1.1.0\n\t */\n\tpublic function sanitize(): void {\n\t\t$this->transform_html_start_tag( $this->dom );\n\t\t$this->transform_a_tags( $this->dom );\n\t\t$this->use_semantic_heading_tags( $this->dom );\n\t\t$this->add_publisher_logo( $this->dom, $this->args['publisher_logo'] );\n\t\t$this->add_publisher( $this->dom, $this->args['publisher'] );\n\t\t$this->add_poster_images( $this->dom, $this->args['poster_images'] );\n\t\t// This needs to be called before use_semantic_heading_tags() because it relies on the style attribute.\n\t\t$this->deduplicate_inline_styles( $this->dom );\n\t\t$this->disable_first_page_animations( $this->dom );\n\t\t$this->add_video_cache( $this->dom, $this->args['video_cache'] );\n\t\t$this->remove_blob_urls( $this->dom );\n\t\t$this->sanitize_srcset( $this->dom );\n\t\t$this->sanitize_amp_story_page_outlink( $this->dom );\n\t\t$this->remove_page_template_placeholder_images( $this->dom );\n\t\t$this->sanitize_title_and_meta_description( $this->dom, $this->args['title_tag'], $this->args['description'] );\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Tag_And_Attribute_Sanitizer.php",
    "content": "<?php\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP;\n\nuse Google\\Web_Stories_Dependencies\\AMP_Tag_And_Attribute_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * Strips the tags and attributes from the content that are not allowed by the AMP spec.\n *\n * @since 1.28.0\n *\n * @see AMP_Tag_And_Attribute_Sanitizer\n */\nclass Tag_And_Attribute_Sanitizer extends AMP_Tag_And_Attribute_Sanitizer {\n\t/**\n\t * AMP_Tag_And_Attribute_Sanitizer constructor.\n\t *\n\t * @since 1.28.0\n\t *\n\t * @param Document             $dom  DOM.\n\t * @param array<string, mixed> $args args.\n\t */\n\tpublic function __construct( Document $dom, array $args = [] ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod.Found\n\t\tparent::__construct( $dom, $args );\n\t}\n}\n"
  },
  {
    "path": "includes/AMP/Traits/Sanitization_Utils.php",
    "content": "<?php\n/**\n * Trait Sanitization_Utils.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\AMP\\Traits;\n\nuse AmpProject\\Dom\\Document as AMP_Document;\nuse DOMAttr;\nuse DOMElement;\nuse DOMNode;\nuse DOMNodeList;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * Trait Sanitization_Utils\n *\n * @since 1.1.0\n */\ntrait Sanitization_Utils {\n\t/**\n\t * Replaces the HTML start tag to make the language attributes dynamic.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function transform_html_start_tag( $document ): void {\n\t\t$document->html->setAttribute( 'amp', '' );\n\n\t\t// See get_language_attributes().\n\t\tif ( is_rtl() ) {\n\t\t\t$document->html->setAttribute( 'dir', 'rtl' );\n\t\t}\n\n\t\t$lang = get_bloginfo( 'language' );\n\t\tif ( $lang ) {\n\t\t\t$document->html->setAttribute( 'lang', $lang );\n\t\t}\n\t}\n\n\t/**\n\t * Transform all hyperlinks to ensure they're always valid.\n\t *\n\t * Adds target=\"_blank\" and rel=\"noreferrer\" attributes.\n\t * Does not add rel=\"noreferrer\" for same-origin links.\n\t *\n\t * Removes empty data-tooltip-icon and data-tooltip-text attributes\n\t * to prevent validation issues.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function transform_a_tags( $document ): void {\n\t\t$links = $document->getElementsByTagName( 'a' );\n\n\t\t/**\n\t\t * The <a> element\n\t\t *\n\t\t * @var DOMElement $link The <a> element\n\t\t */\n\t\tforeach ( $links as $link ) {\n\t\t\t$url = $link->getAttribute( 'href' );\n\n\t\t\t$is_relative_link = str_starts_with( $url, '#' );\n\n\t\t\tif ( ! $is_relative_link && ! $link->getAttribute( 'target' ) ) {\n\t\t\t\t$link->setAttribute( 'target', '_blank' );\n\t\t\t}\n\n\t\t\t$is_link_to_same_origin = str_starts_with( $url, home_url() ) || $is_relative_link;\n\n\t\t\t$rel = $link->getAttribute( 'rel' );\n\n\t\t\t// Links to the same site should not have \"noreferrer\".\n\t\t\t// Other rel values should not be modified.\n\t\t\t// See https://github.com/googleforcreators/web-stories-wp/issues/9494.\n\t\t\t$rel = str_replace( 'noreferrer', '', $rel );\n\t\t\tif ( ! $is_link_to_same_origin ) {\n\t\t\t\t$rel .= ' noreferrer';\n\t\t\t}\n\n\t\t\tif ( empty( $rel ) ) {\n\t\t\t\t$link->removeAttribute( 'rel' );\n\t\t\t} else {\n\t\t\t\t$link->setAttribute( 'rel', trim( $rel ) );\n\t\t\t}\n\n\t\t\tif ( ! $link->getAttribute( 'data-tooltip-icon' ) ) {\n\t\t\t\t$link->removeAttribute( 'data-tooltip-icon' );\n\t\t\t}\n\n\t\t\tif ( ! $link->getAttribute( 'data-tooltip-text' ) ) {\n\t\t\t\t$link->removeAttribute( 'data-tooltip-text' );\n\t\t\t}\n\n\t\t\t// Extra hardening to catch links without a proper protocol.\n\t\t\t// Matches withProtocol() util in the editor.\n\t\t\tif (\n\t\t\t\t! $is_relative_link &&\n\t\t\t\t! str_starts_with( $url, 'http://' ) &&\n\t\t\t\t! str_starts_with( $url, 'https://' ) &&\n\t\t\t\t! str_starts_with( $url, 'tel:' ) &&\n\t\t\t\t! str_starts_with( $url, 'mailto:' )\n\t\t\t) {\n\t\t\t\t$link->setAttribute( 'href', 'https://' . $url );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Transforms all paragraphs in a story to use semantic heading tags if needed.\n\t *\n\t * This logic here mirrors the getTextElementTagNames() function in the editor\n\t * in order to change simple <p> tags into <h1>, <h2> or <h3>, depending on font size.\n\t *\n\t * It is only relevant for older stories that haven't been updated in a while,\n\t * so we bail early if we find any existing headings in the story.\n\t *\n\t * Caveat: if a user forces *all* text elements to be paragraphs,\n\t * this sanitizer would still run and thus turn some paragraphs into headings.\n\t * This seems rather unlikely though.\n\t *\n\t * @since 1.18.0\n\t *\n\t * @link https://github.com/GoogleForCreators/web-stories-wp/issues/12850\n\t *\n\t * @param Document|AMP_Document $document   Document instance.\n\t */\n\tprivate function use_semantic_heading_tags( $document ): void {\n\t\t$h1 = $document->getElementsByTagName( 'h1' );\n\t\t$h2 = $document->getElementsByTagName( 'h2' );\n\t\t$h3 = $document->getElementsByTagName( 'h3' );\n\n\t\t// When a story already contains any headings, we don't need to do anything further.\n\t\tif ( $h1->count() || $h2->count() || $h3->count() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$pages = $document->getElementsByTagName( 'amp-story-page' );\n\n\t\t/**\n\t\t * The <amp-story-page> element\n\t\t *\n\t\t * @var DOMElement $page The <amp-story-page> element\n\t\t */\n\t\tforeach ( $pages as $page ) {\n\t\t\t$text_elements = $document->xpath->query( './/p[ contains( @class, \"text-wrapper\" ) ]', $page );\n\n\t\t\tif ( ! $text_elements ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$this->use_semantic_heading_tags_for_elements( $text_elements );\n\t\t}\n\t}\n\n\t/**\n\t * Transforms a list of elements to use semantic heading tags if needed.\n\t *\n\t * @since 1.18.0\n\t *\n\t * @param DOMNodeList $text_elements List of text elements.\n\t */\n\tprivate function use_semantic_heading_tags_for_elements( DOMNodeList $text_elements ): void {\n\t\t// Matches PAGE_HEIGHT in the editor, as also seen in amp-story-grid-layer[aspect-ratio].\n\t\t$page_height = 618;\n\n\t\t$has_h1 = false;\n\n\t\t/**\n\t\t * The individual text element.\n\t\t *\n\t\t * @var DOMElement $text_el The text element.\n\t\t */\n\t\tforeach ( $text_elements as $text_el ) {\n\t\t\t$style   = $text_el->getAttribute( 'style' );\n\t\t\t$matches = [];\n\n\t\t\t// See https://github.com/GoogleForCreators/web-stories-wp/issues/10726.\n\t\t\tif ( \\strlen( trim( $text_el->textContent ) ) <= 3 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! preg_match( '/font-size:([^em]+)em/', $style, $matches ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Contains the font-size in em.\n\t\t\t// This is basically reversing the dataToFontSizeY() logic. Example:\n\t\t\t// 0.582524em roughly equals 36 editor pixels: 0.582524 * 618 / 10 = 35.9999px.\n\t\t\t$font_size_in_em = (float) $matches[1];\n\t\t\t$font_size_in_px = round( $font_size_in_em * $page_height / 10 );\n\n\t\t\tif ( $font_size_in_px >= 36 && ! $has_h1 ) {\n\t\t\t\t$this->change_tag_name( $text_el, 'h1' );\n\t\t\t\t$has_h1 = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( $font_size_in_px >= 27 ) {\n\t\t\t\t$this->change_tag_name( $text_el, 'h2' );\n\t\t\t} elseif ( $font_size_in_px >= 21 ) {\n\t\t\t\t$this->change_tag_name( $text_el, 'h3' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Changes an element's tag name.\n\t *\n\t * @since 1.18.0\n\t *\n\t * @param DOMElement $node     Element whose tag name should be changed.\n\t * @param string     $tag_name Desired new tag name, e.g. h1 or h2.\n\t */\n\tprivate function change_tag_name( DOMElement $node, string $tag_name ): void {\n\t\t/**\n\t\t * Owner document.\n\t\t *\n\t\t * @var Document|AMP_Document Owner document.\n\t\t */\n\t\t$document = $node->ownerDocument;\n\n\t\t$new_node = $document->createElement( $tag_name );\n\n\t\tif ( ! $new_node instanceof DOMElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Copy over all children first.\n\t\tforeach ( $node->childNodes as $child ) {\n\t\t\t/**\n\t\t\t * Child node.\n\t\t\t *\n\t\t\t * @var DOMNode $child Child node.\n\t\t\t */\n\n\t\t\t$new_node->appendChild( $document->importNode( $child->cloneNode( true ), true ) );\n\t\t}\n\n\t\t// Then, copy over all attributes.\n\n\t\t// @phpstan-ignore foreach.nonIterable (false positive)\n\t\tforeach ( $node->attributes as $attr ) {\n\t\t\t/**\n\t\t\t * Attribute.\n\t\t\t *\n\t\t\t * @var DOMAttr $attr Attribute.\n\t\t\t */\n\t\t\t$new_node->setAttribute( $attr->nodeName, $attr->nodeValue ?? '' );\n\t\t}\n\n\t\tif ( $node->parentNode ) {\n\t\t\t$node->parentNode->replaceChild( $new_node, $node );\n\t\t}\n\t}\n\n\t/**\n\t * Sanitizes <amp-story-page-outlink> elements to ensure they're always valid.\n\t *\n\t * Removes empty `cta-image` attributes.\n\t * Ensures the element is always the last child of <amp-story-page>.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function sanitize_amp_story_page_outlink( $document ): void {\n\t\t$outlink_elements = $document->getElementsByTagName( 'amp-story-page-outlink' );\n\n\t\t/**\n\t\t * The <amp-story-page-outlink> element\n\t\t *\n\t\t * @var DOMElement $element The <amp-story-page-outlink> element\n\t\t */\n\t\tforeach ( $outlink_elements as $element ) {\n\t\t\tif ( ! $element->getAttribute( 'cta-image' ) ) {\n\t\t\t\t$element->removeAttribute( 'cta-image' );\n\t\t\t}\n\n\t\t\t$amp_story_page = $element->parentNode;\n\n\t\t\tif ( $amp_story_page && $element !== $amp_story_page->lastChild ) {\n\t\t\t\t$amp_story_page->removeChild( $element );\n\t\t\t\t$amp_story_page->appendChild( $element );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Replaces the placeholder of publisher logo in the content.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document|AMP_Document $document       Document instance.\n\t * @param string                $publisher_logo Publisher logo.\n\t */\n\tprivate function add_publisher_logo( $document, string $publisher_logo ): void {\n\t\t/**\n\t\t * The <amp-story> element.\n\t\t *\n\t\t * @var DOMElement|DOMNode $story_element The <amp-story> element.\n\t\t */\n\t\t$story_element = $document->body->getElementsByTagName( 'amp-story' )->item( 0 );\n\n\t\tif ( ! $story_element instanceof DOMElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add a publisher logo if missing or just a placeholder.\n\t\t$existing_publisher_logo = $story_element->getAttribute( 'publisher-logo-src' );\n\n\t\t// Backward compatibility for when fallback-wordpress-publisher-logo.png was provided by the plugin.\n\t\tif ( ! $existing_publisher_logo || str_contains( $existing_publisher_logo, 'fallback-wordpress-publisher-logo.png' ) ) {\n\t\t\t$story_element->setAttribute( 'publisher-logo-src', $publisher_logo );\n\t\t}\n\n\t\tif ( ! $story_element->getAttribute( 'publisher-logo-src' ) ) {\n\t\t\t$story_element->setAttribute( 'publisher-logo-src', $publisher_logo );\n\t\t}\n\t}\n\n\t/**\n\t * Replaces the placeholder of publisher in the content.\n\t *\n\t * Ensures the `publisher` attribute exists if missing.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param Document|AMP_Document $document  Document instance.\n\t * @param string                $publisher Publisher logo.\n\t */\n\tprivate function add_publisher( $document, string $publisher ): void {\n\t\t/**\n\t\t * The <amp-story> element.\n\t\t *\n\t\t * @var DOMElement|DOMNode $story_element The <amp-story> element.\n\t\t */\n\t\t$story_element = $document->body->getElementsByTagName( 'amp-story' )->item( 0 );\n\n\t\tif ( ! $story_element instanceof DOMElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( $publisher || ! $story_element->hasAttribute( 'publisher' ) ) {\n\t\t\t$story_element->setAttribute( 'publisher', $publisher );\n\t\t}\n\t}\n\n\t/**\n\t * Adds square, and landscape poster images to the <amp-story>.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param Document|AMP_Document $document      Document instance.\n\t * @param string[]              $poster_images List of poster images, keyed by type.\n\t */\n\tprivate function add_poster_images( $document, array $poster_images ): void {\n\t\t/**\n\t\t * The <amp-story> element.\n\t\t *\n\t\t * @var DOMElement|DOMNode $story_element The <amp-story> element.\n\t\t */\n\t\t$story_element = $document->body->getElementsByTagName( 'amp-story' )->item( 0 );\n\n\t\tif ( ! $story_element instanceof DOMElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The story sanitizer only passes valid, non-empty URLs that are already escaped.\n\t\t// That means we don't need to do any additional checks here or worry about accidentally overriding\n\t\t// an existing poster-portrait-src attribute value with an empty one.\n\t\tforeach ( $poster_images as $attr => $url ) {\n\t\t\t$story_element->setAttribute( $attr, $url );\n\t\t}\n\n\t\tif ( ! $story_element->getAttribute( 'poster-portrait-src' ) ) {\n\t\t\t$story_element->setAttribute( 'poster-portrait-src', '' );\n\t\t}\n\t}\n\n\t/**\n\t * De-duplicate inline styles in the story.\n\t *\n\t * Greatly reduce the amount of `style[amp-custom]` CSS for stories by de-duplicating inline styles\n\t * and moving to simple class selector style rules, avoiding the specificity hack\n\t * that the AMP plugin's style sanitizer employs.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function deduplicate_inline_styles( $document ): void {\n\t\t$elements_by_inline_style = [];\n\n\t\t// Gather all elements based on their common inline styles.\n\t\t$elements_with_style = $document->xpath->query( '//*[ @style ]' );\n\n\t\tif ( $elements_with_style instanceof DOMNodeList && $elements_with_style->length > 0 ) {\n\t\t\t/**\n\t\t\t * The element with inline styles.\n\t\t\t *\n\t\t\t * @var DOMElement $styled_element The element.\n\t\t\t */\n\t\t\tforeach ( $elements_with_style as $styled_element ) {\n\t\t\t\t$value = $styled_element->getAttribute( 'style' );\n\t\t\t\t$styled_element->removeAttribute( 'style' );\n\t\t\t\t$elements_by_inline_style[ $value ][] = $styled_element;\n\t\t\t}\n\t\t}\n\n\t\tif ( empty( $elements_by_inline_style ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$style_element = $document->createElement( 'style' );\n\n\t\tif ( ! $style_element ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$document->head->appendChild( $style_element );\n\n\t\t// Create style rule for each inline style and add class name to each element.\n\t\tforeach ( $elements_by_inline_style as $inline_style => $styled_elements ) {\n\t\t\t$inline_style_class_name = '_' . substr( md5( (string) $inline_style ), 0, 7 );\n\n\t\t\t$style_rule = $document->createTextNode( \\sprintf( '.%s{%s}', $inline_style_class_name, $inline_style ) );\n\t\t\t$style_element->appendChild( $style_rule );\n\n\t\t\t/**\n\t\t\t * The element with inline styles.\n\t\t\t *\n\t\t\t * @var DOMElement $styled_element The element.\n\t\t\t */\n\t\t\tforeach ( $styled_elements as $styled_element ) {\n\t\t\t\t$class_name = $inline_style_class_name;\n\t\t\t\tif ( $styled_element->hasAttribute( 'class' ) ) {\n\t\t\t\t\t$class_name .= ' ' . $styled_element->getAttribute( 'class' );\n\t\t\t\t}\n\t\t\t\t$styled_element->setAttribute( 'class', $class_name );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds CSS to reset animations for elements on the first page.\n\t *\n\t * Animations on the first page of a story are not allowed,\n\t * and removed at both the creation & serialization level (in the output package),\n\t * as well as the renderer (in AMP itself).\n\t *\n\t * This inline CSS adds another layer of defense, especially for older stories\n\t * that might still have some animation data on the first page.\n\t *\n\t * @since 1.43.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function disable_first_page_animations( $document ): void {\n\t\t$animated_elements = $document->xpath->query( './/div[ contains( @class, \"animation-wrapper\" ) ]' );\n\n\t\tif ( ! $animated_elements || 0 === $animated_elements->length ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$style_element = $document->createElement( 'style' );\n\n\t\tif ( ! $style_element ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$style_rule = $document->createTextNode( 'amp-story-page:first-of-type .animation-wrapper { --initial-opacity: 1; --initial-transform: none; }' );\n\t\t$style_element->appendChild( $style_rule );\n\n\t\t$document->head->appendChild( $style_element );\n\t}\n\n\t/**\n\t * Enables using video cache by adding the necessary attribute to `<amp-video>`\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t * @param bool                  $video_cache_enabled Whether video cache is enabled.\n\t */\n\tprivate function add_video_cache( $document, bool $video_cache_enabled ): void {\n\t\tif ( ! $video_cache_enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$videos = $document->body->getElementsByTagName( 'amp-video' );\n\n\t\t/**\n\t\t * The <amp-video> element\n\t\t *\n\t\t * @var DOMElement $video The <amp-video> element\n\t\t */\n\t\tforeach ( $videos as $video ) {\n\t\t\t$video->setAttribute( 'cache', 'google' );\n\t\t}\n\t}\n\n\t/**\n\t * Determines whether a URL is a `blob:` URL.\n\t *\n\t * @since 1.9.0\n\t *\n\t * @param string $url URL.\n\t * @return bool Whether it's a blob URL.\n\t */\n\tprivate function is_blob_url( string $url ): bool {\n\t\treturn str_starts_with( $url, 'blob:' );\n\t}\n\n\t/**\n\t * Remove `blob:` URLs from videos and images that might have slipped through.\n\t *\n\t * @since 1.9.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function remove_blob_urls( $document ): void {\n\t\t/**\n\t\t * List of <amp-video> elements.\n\t\t *\n\t\t * @var DOMElement[] $videos Video elements.\n\t\t */\n\t\t$videos = $document->body->getElementsByTagName( 'amp-video' );\n\n\t\tforeach ( $videos as $video ) {\n\t\t\tif ( $this->is_blob_url( $video->getAttribute( 'poster' ) ) ) {\n\t\t\t\t$video->setAttribute( 'poster', '' );\n\t\t\t}\n\n\t\t\tif ( $this->is_blob_url( $video->getAttribute( 'artwork' ) ) ) {\n\t\t\t\t$video->setAttribute( 'artwork', '' );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * List of <source> child elements.\n\t\t\t *\n\t\t\t * @var DOMElement[] $video_sources Video source elements.\n\t\t\t */\n\t\t\t$video_sources = $video->getElementsByTagName( 'source' );\n\n\t\t\tforeach ( $video_sources as $source ) {\n\t\t\t\tif ( $this->is_blob_url( $source->getAttribute( 'src' ) ) ) {\n\t\t\t\t\t$source->setAttribute( 'src', '' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * List of <amp-img> elements.\n\t\t *\n\t\t * @var DOMElement[] $images Image elements.\n\t\t */\n\t\t$images = $document->body->getElementsByTagName( 'amp-img' );\n\n\t\tforeach ( $images as $image ) {\n\t\t\tif ( $this->is_blob_url( $image->getAttribute( 'src' ) ) ) {\n\t\t\t\t$image->setAttribute( 'src', '' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sanitize amp-img[srcset] attributes to remove duplicates.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function sanitize_srcset( $document ): void {\n\t\t/**\n\t\t * List of <amp-img> elements.\n\t\t *\n\t\t * @var DOMElement[] $images Image elements.\n\t\t */\n\t\t$images = $document->body->getElementsByTagName( 'amp-img' );\n\n\t\tforeach ( $images as $image ) {\n\t\t\t$srcset = $image->getAttribute( 'srcset' );\n\t\t\tif ( ! $srcset ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$matches = [];\n\n\t\t\t// Matches every srcset entry (consisting of a URL and a width descriptor) within `srcset=\"\"`.\n\t\t\t// Not using explode(',') to not break with URLs containing commas.\n\t\t\t// Given \"foo1,2/image.png 123w, foo2,3/image.png 456w\", the named capture group \"entry\"\n\t\t\t// will contain \"foo1,2/image.png 123w\" and \"foo2,3/image.png 456w\", without the trailing commas.\n\t\t\tpreg_match_all( '/((?<entry>[^ ]+ [\\d]+w),?)/', $srcset, $matches );\n\n\t\t\t$entries_by_widths = [];\n\n\t\t\tforeach ( $matches['entry'] as $entry ) {\n\t\t\t\t$entry_data = explode( ' ', $entry );\n\t\t\t\tif ( ! isset( $entries_by_widths[ $entry_data[1] ] ) ) {\n\t\t\t\t\t$entries_by_widths[ $entry_data[1] ] = $entry;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$image->setAttribute( 'srcset', implode( ', ', $entries_by_widths ) );\n\t\t}\n\t}\n\n\t/**\n\t * Remove images referencing the grid-placeholder.png file which has since been removed.\n\t *\n\t * Prevents 404 errors for non-existent image files when creators forget to replace/remove\n\t * the placeholder image.\n\t *\n\t * The placeholder functionality was removed in v1.14.0, nevertheless older stories could still\n\t * reference the files.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @link https://github.com/googleforcreators/web-stories-wp/issues/9530\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t */\n\tprivate function remove_page_template_placeholder_images( $document ): void {\n\t\t// Catches \"assets/images/editor/grid-placeholder.png\" as well as\n\t\t// \"web-stories/assets/images/adde98ae406d6b5c95d111a934487252.png\" (v1.14.0)\n\t\t// and potentially other variants.\n\t\t$placeholder_img = 'plugins/web-stories/assets/images';\n\n\t\t/**\n\t\t * List of <amp-img> elements.\n\t\t *\n\t\t * @var DOMElement[] $images Image elements.\n\t\t */\n\t\t$images = $document->body->getElementsByTagName( 'amp-img' );\n\n\t\tforeach ( $images as $image ) {\n\t\t\t$src = $image->getAttribute( 'src' );\n\n\t\t\tif ( $image->parentNode && str_contains( $src, $placeholder_img ) ) {\n\t\t\t\t$image->parentNode->removeChild( $image );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sanitizes <title> tags and meta descriptions.\n\t *\n\t * Ensures there's always just exactly one of each present.\n\t *\n\t * @since 1.28.0\n\t *\n\t * @link https://github.com/googleforcreators/web-stories-wp/issues/12655\n\t *\n\t * @param Document|AMP_Document $document Document instance.\n\t * @param string                $title_tag   Title text to use if it's missing.\n\t * @param string                $description Description to use if it's missing.\n\t */\n\tprivate function sanitize_title_and_meta_description( $document, string $title_tag, string $description ): void {\n\t\t/**\n\t\t * List of <title> elements.\n\t\t *\n\t\t * @var DOMNodeList<DOMElement> $titles Title elements.\n\t\t */\n\t\t$titles = $document->head->getElementsByTagName( 'title' );\n\n\t\tif ( $titles->length > 1 ) {\n\t\t\tforeach ( $titles as $index => $title ) {\n\t\t\t\tif ( 0 === $index ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$document->head->removeChild( $title );\n\t\t\t}\n\t\t}\n\n\t\tif ( 0 === $titles->length && ! empty( $title_tag ) ) {\n\t\t\t/**\n\t\t\t * New title tag element.\n\t\t\t *\n\t\t\t * @var DOMElement $new_title\n\t\t\t */\n\t\t\t$new_title = $document->createElement( 'title' );\n\n\t\t\t/**\n\t\t\t * Title text node.\n\t\t\t *\n\t\t\t * @var \\DOMText $text_node\n\t\t\t */\n\t\t\t$text_node = $document->createTextNode( $title_tag );\n\n\t\t\t$new_title->appendChild( $text_node );\n\t\t\t$document->head->appendChild( $new_title );\n\t\t}\n\n\t\t/**\n\t\t * List of meta descriptions.\n\t\t *\n\t\t * @var DOMNodeList<DOMElement> $meta_descriptions Meta descriptions.\n\t\t */\n\t\t$meta_descriptions = $document->xpath->query( './/meta[@name=\"description\"]' );\n\n\t\tif ( $meta_descriptions->length > 1 ) {\n\t\t\tforeach ( $meta_descriptions as $index => $meta_description ) {\n\t\t\t\tif ( 0 === $index ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$document->head->removeChild( $meta_description );\n\t\t\t}\n\t\t}\n\n\t\tif ( 0 === $meta_descriptions->length && ! empty( $description ) ) {\n\t\t\t/**\n\t\t\t * New meta description element.\n\t\t\t *\n\t\t\t * @var DOMElement $new_description\n\t\t\t */\n\t\t\t$new_description = $document->createElement( 'meta' );\n\n\t\t\t$new_description->setAttribute( 'name', 'description' );\n\t\t\t$new_description->setAttribute( 'content', $description );\n\t\t\t$document->head->appendChild( $new_description );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/AMP_Story_Player_Assets.php",
    "content": "<?php\n/**\n * Class AMP_Story_Player_Assets.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse WP_Scripts;\nuse WP_Styles;\n\n/**\n * Class AMP_Story_Player_Assets\n */\nclass AMP_Story_Player_Assets implements Service, Registerable {\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'standalone-amp-story-player';\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.8.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'wp_default_styles', [ $this, 'register_style' ] );\n\t\tadd_action( 'wp_default_scripts', [ $this, 'register_script' ] );\n\t}\n\n\t/**\n\t * Registers the amp player style.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param WP_Styles $wp_styles WP_Styles instance.\n\t */\n\tpublic function register_style( WP_Styles $wp_styles ): void {\n\t\t$wp_styles->add(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'https://cdn.ampproject.org/amp-story-player-v0.css',\n\t\t\t[],\n\t\t\t'v0'\n\t\t);\n\t}\n\n\t/**\n\t * Registers the amp player script.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param WP_Scripts $wp_scripts WP_Scripts instance.\n\t */\n\tpublic function register_script( WP_Scripts $wp_scripts ): void {\n\t\t$wp_scripts->add(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'https://cdn.ampproject.org/amp-story-player-v0.js',\n\t\t\t[],\n\t\t\t'v0',\n\t\t\tfalse\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/AdSense.php",
    "content": "<?php\n/**\n * Class AdSense\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\n\n/**\n * Class AdSense\n */\nclass AdSense extends Service_Base implements HasRequirements {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'web_stories_print_analytics', [ $this, 'print_adsense_tag' ] );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Prints the <amp-story-auto-ads> tag for single stories.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic function print_adsense_tag(): void {\n\t\t$publisher = $this->get_publisher_id();\n\t\t$slot      = $this->get_slot_id();\n\t\t$enabled   = $this->is_enabled();\n\n\t\tif ( ! $enabled || ! $publisher || ! $slot ) {\n\t\t\treturn;\n\t\t}\n\t\t?>\n\t\t<amp-story-auto-ads>\n\t\t\t<script type=\"application/json\">\n\t\t\t\t{\n\t\t\t\t\t\"ad-attributes\": {\n\t\t\t\t\t\t\"type\": \"adsense\",\n\t\t\t\t\t\t\"data-ad-client\": \"<?php echo esc_js( $publisher ); ?>\",\n\t\t\t\t\t\t\"data-ad-slot\": \"<?php echo esc_js( $slot ); ?>\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</script>\n\t\t</amp-story-auto-ads>\n\t\t<?php\n\t}\n\n\t/**\n\t * Returns the Google AdSense publisher ID.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @return string Publisher ID.\n\t */\n\tprivate function get_publisher_id(): string {\n\t\t/**\n\t\t * Publisher ID.\n\t\t *\n\t\t * @var string $publisher_id\n\t\t */\n\t\t$publisher_id = $this->settings->get_setting( $this->settings::SETTING_NAME_ADSENSE_PUBLISHER_ID );\n\t\treturn $publisher_id;\n\t}\n\n\t/**\n\t * Returns the Google AdSense slot ID.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @return string Slot ID.\n\t */\n\tprivate function get_slot_id(): string {\n\t\t/**\n\t\t * Slot ID.\n\t\t *\n\t\t * @var string\n\t\t */\n\t\treturn $this->settings->get_setting( $this->settings::SETTING_NAME_ADSENSE_SLOT_ID );\n\t}\n\n\t/**\n\t * Returns if Google AdSense is enabled.\n\t *\n\t * @since 1.3.0\n\t */\n\tprivate function is_enabled(): bool {\n\t\treturn ( 'adsense' === $this->settings->get_setting( $this->settings::SETTING_NAME_AD_NETWORK, 'none' ) );\n\t}\n}\n"
  },
  {
    "path": "includes/Ad_Manager.php",
    "content": "<?php\n/**\n * Class Ad_Manager\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\n\n/**\n * Class Ad_Manager\n */\nclass Ad_Manager extends Service_Base implements HasRequirements {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'web_stories_print_analytics', [ $this, 'print_ad_manager_tag' ] );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Prints the <amp-story-auto-ads> tag for single stories.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic function print_ad_manager_tag(): void {\n\t\t$slot    = $this->get_slot_id();\n\t\t$enabled = $this->is_enabled();\n\n\t\tif ( ! $enabled || ! $slot ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$configuration = [\n\t\t\t'ad-attributes' => [\n\t\t\t\t'type'      => 'doubleclick',\n\t\t\t\t'data-slot' => $slot,\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filters Google Ad Manager configuration passed to `<amp-story-auto-ads>`.\n\t\t *\n\t\t * @since 1.10.0\n\t\t *\n\t\t * @param array $settings Ad Manager configuration.\n\t\t * @param string $slot Google Ad_Manager slot ID.\n\t\t */\n\t\t$configuration = apply_filters( 'web_stories_ad_manager_configuration', $configuration, $slot );\n\n\t\t?>\n\t\t<amp-story-auto-ads>\n\t\t\t<script type=\"application/json\">\n\t\t\t\t<?php echo wp_json_encode( $configuration, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); ?>\n\t\t\t</script>\n\t\t</amp-story-auto-ads>\n\t\t<?php\n\t}\n\n\t/**\n\t * Returns the Google Ad_Manager slot ID.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @return string Slot ID.\n\t */\n\tprivate function get_slot_id(): string {\n\t\t/**\n\t\t * Slot ID.\n\t\t *\n\t\t * @var string\n\t\t */\n\t\treturn $this->settings->get_setting( $this->settings::SETTING_NAME_AD_MANAGER_SLOT_ID );\n\t}\n\n\t/**\n\t * Returns if Google manager is enabled.\n\t *\n\t * @since 1.3.0\n\t */\n\tprivate function is_enabled(): bool {\n\t\treturn ( 'admanager' === $this->settings->get_setting( $this->settings::SETTING_NAME_AD_NETWORK, 'none' ) );\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Activation_Notice.php",
    "content": "<?php\n/**\n * Class Activation_Notice.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Infrastructure\\PluginActivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginDeactivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service as ServiceInterface;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tracking;\n\n/**\n * Class Activation_Notice.\n */\nclass Activation_Notice implements ServiceInterface, Registerable, PluginActivationAware, PluginDeactivationAware, PluginUninstallAware {\n\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-activation-notice';\n\n\t/**\n\t * Option name.\n\t */\n\tpublic const OPTION_SHOW_ACTIVATION_NOTICE = 'web_stories_show_activation_notice';\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Assets $assets Assets instance.\n\t */\n\tpublic function __construct( Assets $assets ) {\n\t\t$this->assets = $assets;\n\t}\n\n\t/**\n\t * Initializes the plugin activation notice.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );\n\t\tadd_action( 'admin_notices', [ $this, 'render_notice' ] );\n\t\tadd_action( 'network_admin_notices', [ $this, 'render_notice' ] );\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->set_activation_flag( $network_wide );\n\t}\n\n\t/**\n\t * Act on plugin deactivation.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool $network_wide Whether the deactivation was done network-wide.\n\t */\n\tpublic function on_plugin_deactivation( bool $network_wide ): void {\n\t\t$this->delete_activation_flag( $network_wide );\n\t}\n\n\t/**\n\t * Enqueues assets for the plugin activation notice.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $hook_suffix The current admin page.\n\t */\n\tpublic function enqueue_assets( string $hook_suffix ): void {\n\t\tif ( ! $this->is_plugins_page( $hook_suffix ) || ! $this->get_activation_flag( is_network_admin() ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Prevent the default WordPress \"Plugin Activated\" notice from rendering.\n\t\t *\n\t\t * @link https://github.com/WordPress/WordPress/blob/e1996633228749cdc2d92bc04cc535d45367bfa4/wp-admin/plugins.php#L569-L570\n\t\t */\n\t\tunset( $_GET['activate'] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.VIP.SuperGlobalInputUsage\n\n\t\t$this->assets->enqueue_style( Google_Fonts::SCRIPT_HANDLE );\n\n\t\t$this->assets->enqueue_script_asset( self::SCRIPT_HANDLE, [ Tracking::SCRIPT_HANDLE ] );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStoriesActivationSettings',\n\t\t\t$this->get_script_settings()\n\t\t);\n\t}\n\n\t/**\n\t * Renders the plugin activation notice.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function render_notice(): void {\n\t\tglobal $hook_suffix;\n\n\t\tif ( ! $this->is_plugins_page( $hook_suffix ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$network_wide = is_network_admin();\n\t\t$flag         = $this->get_activation_flag( $network_wide );\n\n\t\tif ( ! $flag ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Unset the flag so that the notice only shows once.\n\t\t$this->delete_activation_flag( $network_wide );\n\n\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/admin/activation-notice.php';\n\t}\n\n\t/**\n\t * Deletes the flag that the plugin has just been uninstalled.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tif ( is_multisite() ) {\n\t\t\tdelete_site_option( self::OPTION_SHOW_ACTIVATION_NOTICE );\n\t\t}\n\t\tdelete_option( self::OPTION_SHOW_ACTIVATION_NOTICE );\n\t}\n\n\t/**\n\t * Returns script settings as an array.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array{id: string, config: array<string, bool|string>,publicPath: string} Script settings.\n\t */\n\tprotected function get_script_settings(): array {\n\t\t$new_story_url = admin_url(\n\t\t\tadd_query_arg(\n\t\t\t\t[\n\t\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t],\n\t\t\t\t'post-new.php'\n\t\t\t)\n\t\t);\n\n\t\t$dashboard_url = admin_url(\n\t\t\tadd_query_arg(\n\t\t\t\t[\n\t\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t\t'page'      => 'stories-dashboard',\n\t\t\t\t],\n\t\t\t\t'edit.php'\n\t\t\t)\n\t\t);\n\n\t\t$demo_story_url = admin_url(\n\t\t\tadd_query_arg(\n\t\t\t\t[\n\t\t\t\t\t'post_type'        => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t\t'web-stories-demo' => 1,\n\t\t\t\t],\n\t\t\t\t'post-new.php'\n\t\t\t)\n\t\t);\n\n\t\treturn [\n\t\t\t'id'         => 'web-stories-plugin-activation-notice',\n\t\t\t'config'     => [\n\t\t\t\t'isRTL'        => is_rtl(),\n\t\t\t\t'cdnURL'       => trailingslashit( WEBSTORIES_CDN_URL ),\n\t\t\t\t'demoStoryURL' => $demo_story_url,\n\t\t\t\t'newStoryURL'  => $new_story_url,\n\t\t\t\t'dashboardURL' => $dashboard_url,\n\t\t\t],\n\t\t\t'publicPath' => $this->assets->get_base_url( 'assets/js/' ),\n\t\t];\n\t}\n\n\t/**\n\t * Determines whether we're currently on the Plugins page or not.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param mixed $hook_suffix Current hook_suffix.\n\t * @return bool Whether we're on the Plugins page.\n\t */\n\tprotected function is_plugins_page( $hook_suffix ): bool {\n\t\treturn ( ! empty( $hook_suffix ) && 'plugins.php' === $hook_suffix );\n\t}\n\n\t/**\n\t * Sets the flag that the plugin has just been activated.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool $network_wide Whether the plugin is being activated network-wide.\n\t */\n\tprotected function set_activation_flag( bool $network_wide = false ): bool {\n\t\tif ( $network_wide ) {\n\t\t\treturn update_site_option( self::OPTION_SHOW_ACTIVATION_NOTICE, '1' );\n\t\t}\n\n\t\treturn update_option( self::OPTION_SHOW_ACTIVATION_NOTICE, '1', false );\n\t}\n\n\t/**\n\t * Gets the flag that the plugin has just been activated.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool $network_wide Whether to check the flag network-wide.\n\t * @return bool True if just activated, false otherwise.\n\t */\n\tprotected function get_activation_flag( bool $network_wide = false ): bool {\n\t\tif ( $network_wide ) {\n\t\t\treturn (bool) get_site_option( self::OPTION_SHOW_ACTIVATION_NOTICE, false );\n\t\t}\n\n\t\treturn (bool) get_option( self::OPTION_SHOW_ACTIVATION_NOTICE, false );\n\t}\n\n\t/**\n\t * Deletes the flag that the plugin has just been activated.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool $network_wide Whether the plugin is being deactivated network-wide.\n\t * @return bool True if flag deletion is successful, false otherwise.\n\t */\n\tprotected function delete_activation_flag( bool $network_wide = false ): bool {\n\t\tif ( $network_wide ) {\n\t\t\treturn delete_site_option( self::OPTION_SHOW_ACTIVATION_NOTICE );\n\t\t}\n\n\t\treturn delete_option( self::OPTION_SHOW_ACTIVATION_NOTICE );\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Admin.php",
    "content": "<?php\n/**\n * Admin class.\n *\n * Responsible for WordPress admin integration.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Image;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Admin class.\n */\nclass Admin extends Service_Base {\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Single constructor.\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @param Context  $context Context instance.\n\t */\n\tpublic function __construct( Settings $settings, Context $context ) {\n\t\t$this->settings = $settings;\n\t\t$this->context  = $context;\n\t}\n\n\t/**\n\t * Initialize admin-related functionality.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'admin_body_class', [ $this, 'admin_body_class' ], 99 );\n\t\tadd_filter( 'default_content', [ $this, 'prefill_post_content' ], 10, 2 );\n\t\tadd_filter( 'default_title', [ $this, 'prefill_post_title' ] );\n\t\tadd_filter( 'display_media_states', [ $this, 'media_states' ], 10, 2 );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'admin_init';\n\t}\n\n\t/**\n\t * Filter the list of admin classes.\n\t *\n\t * Makes sure the admin menu is collapsed when accessing\n\t * the dashboard and the editor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $class_name Current classes.\n\t * @return string|mixed List of Classes.\n\t */\n\tpublic function admin_body_class( $class_name ) {\n\t\tif ( ! \\is_string( $class_name ) ) {\n\t\t\treturn $class_name;\n\t\t}\n\n\t\tif ( ! $this->context->is_story_editor() ) {\n\t\t\treturn $class_name;\n\t\t}\n\n\t\t// Default WordPress posts list table screen and dashboard.\n\t\tif ( 'post' !== $this->context->get_screen_base() ) {\n\t\t\treturn $class_name;\n\t\t}\n\n\t\t$class_name .= ' edit-story';\n\n\t\t// Overrides regular WordPress behavior by collapsing the admin menu by default.\n\t\tif ( ! str_contains( $class_name, 'folded' ) ) {\n\t\t\t$class_name .= ' folded';\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n\t/**\n\t * Pre-fills post content with a web-story/embed block.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $content Default post content.\n\t * @param WP_Post|null $post    Post object.\n\t * @return string|mixed Pre-filled post content if applicable, or the default content otherwise.\n\t */\n\tpublic function prefill_post_content( $content, ?WP_Post $post ) {\n\t\tif ( ! $post ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\tif ( ! isset( $_GET['from-web-story'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended\n\t\t\treturn $content;\n\t\t}\n\n\t\t/**\n\t\t * Story ID.\n\t\t *\n\t\t * @var string $from_web_story\n\t\t */\n\t\t$from_web_story = $_GET['from-web-story']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\n\t\t$post_id = absint( sanitize_text_field( (string) wp_unslash( $from_web_story ) ) );\n\n\t\tif ( ! $post_id || Story_Post_Type::POST_TYPE_SLUG !== get_post_type( $post_id ) ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\tif ( ! current_user_can( 'read_post', $post_id ) ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\t$story = new Story();\n\t\tif ( ! $story->load_from_post( $post_id ) ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\tif ( ! $story->get_title() ) {\n\t\t\t$story->set_title( __( 'Web Story', 'web-stories' ) );\n\t\t}\n\n\t\t$args = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\n\t\tif ( ! use_block_editor_for_post( $post ) ) {\n\t\t\t$content = '[web_stories_embed url=\"%1$s\" title=\"%2$s\" poster=\"%3$s\" width=\"%4$s\" height=\"%5$s\" align=\"%6$s\"]';\n\n\t\t\treturn \\sprintf(\n\t\t\t\t$content,\n\t\t\t\tesc_url( $story->get_url() ),\n\t\t\t\tesc_attr( $story->get_title() ),\n\t\t\t\tesc_url( $story->get_poster_portrait() ),\n\t\t\t\tabsint( $args['width'] ),\n\t\t\t\tabsint( $args['height'] ),\n\t\t\t\tesc_attr( $args['align'] )\n\t\t\t);\n\t\t}\n\n\t\t$story->set_poster_sizes( '' );\n\t\t$story->set_poster_srcset( '' );\n\t\t$renderer = new Image( $story );\n\t\t$html     = $renderer->render( $args );\n\n\t\t$content = '<!-- wp:web-stories/embed {\"blockType\":\"url\",\"url\":\"%1$s\",\"title\":\"%2$s\",\"poster\":\"%3$s\",\"width\":\"%4$s\",\"height\":\"%5$s\",\"align\":\"%6$s\",\"stories\": [%7$s]} -->%8$s<!-- /wp:web-stories/embed -->';\n\t\t// note $story->get_url should not be escaped here (esc_url()) see https://github.com/GoogleForCreators/web-stories-wp/issues/11371.\n\t\treturn \\sprintf(\n\t\t\t$content,\n\t\t\t$story->get_url(),\n\t\t\tesc_js( $story->get_title() ),\n\t\t\tesc_url( $story->get_poster_portrait() ),\n\t\t\tabsint( $args['width'] ),\n\t\t\tabsint( $args['height'] ),\n\t\t\tesc_js( $args['align'] ),\n\t\t\tabsint( $post_id ),\n\t\t\t$html\n\t\t);\n\t}\n\n\t/**\n\t * Pre-fills post title with the story title.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $title Default post title.\n\t * @return string|mixed Pre-filled post title if applicable, or the default title otherwise.\n\t */\n\tpublic function prefill_post_title( $title ) {\n\t\tif ( ! isset( $_GET['from-web-story'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended\n\t\t\treturn $title;\n\t\t}\n\n\t\t/**\n\t\t * Story ID.\n\t\t *\n\t\t * @var string $from_web_story\n\t\t */\n\t\t$from_web_story = $_GET['from-web-story']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\n\t\t$post_id = absint( sanitize_text_field( (string) wp_unslash( $from_web_story ) ) );\n\n\t\tif ( ! $post_id ) {\n\t\t\treturn $title;\n\t\t}\n\n\t\tif ( ! current_user_can( 'read_post', $post_id ) ) {\n\t\t\treturn $title;\n\t\t}\n\n\t\t$post = get_post( $post_id );\n\n\t\tif ( ! $post instanceof WP_Post || Story_Post_Type::POST_TYPE_SLUG !== $post->post_type ) {\n\t\t\treturn $title;\n\t\t}\n\n\t\t// Not using get_the_title() because we need the raw title.\n\t\t// Otherwise it runs through wptexturize() and the like, which we want to avoid.\n\t\treturn $post->post_title;\n\t}\n\n\t/**\n\t * Adds active publisher logo to media state output.\n\t *\n\t * @since 1.23.0\n\t *\n\t * @param mixed   $media_states Array of media states.\n\t * @param WP_Post $post         Post object.\n\t * @return mixed Filtered media states.\n\t */\n\tpublic function media_states( $media_states, WP_Post $post ) {\n\t\tif ( ! \\is_array( $media_states ) ) {\n\t\t\treturn $media_states;\n\t\t}\n\n\t\t$active_publisher_logo_id = absint( $this->settings->get_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO ) );\n\n\t\tif ( $post->ID === $active_publisher_logo_id ) {\n\t\t\t$media_states[] = __( 'Web Stories Publisher Logo', 'web-stories' );\n\t\t}\n\t\treturn $media_states;\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Cross_Origin_Isolation.php",
    "content": "<?php\n/**\n * Class Cross_Origin_Isolation.\n *\n * Check if editor screen, add cross origin header and add crossorigin attribute to tags.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\User\\Preferences;\n\n/**\n * Class Cross_Origin_Isolation\n */\nclass Cross_Origin_Isolation extends Service_Base implements HasRequirements {\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Preferences instance.\n\t *\n\t * @var Preferences Preferences instance.\n\t */\n\tprivate Preferences $preferences;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param Preferences $preferences Preferences instance.\n\t * @param Context     $context     Context instance.\n\t */\n\tpublic function __construct( Preferences $preferences, Context $context ) {\n\t\t$this->preferences = $preferences;\n\t\t$this->context     = $context;\n\t}\n\n\t/**\n\t * Init\n\t */\n\tpublic function register(): void {\n\t\tif ( ! $this->context->is_story_editor() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tadd_action( 'load-post.php', [ $this, 'admin_header' ] );\n\t\tadd_action( 'load-post-new.php', [ $this, 'admin_header' ] );\n\t\tadd_filter( 'style_loader_tag', [ $this, 'style_loader_tag' ], 10, 3 );\n\t\tadd_filter( 'script_loader_tag', [ $this, 'script_loader_tag' ], 10, 3 );\n\t\tadd_filter( 'get_avatar', [ $this, 'get_avatar' ], 10, 6 );\n\t\tadd_action( 'wp_enqueue_media', [ $this, 'override_media_templates' ] );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'current_screen';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 11;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'user_preferences' ];\n\t}\n\n\t/**\n\t * Start output buffer to add headers and `crossorigin` attribute everywhere.\n\t *\n\t * @since 1.6.0\n\t */\n\tpublic function admin_header(): void {\n\t\tif ( $this->needs_isolation() ) {\n\t\t\theader( 'Cross-Origin-Opener-Policy: same-origin' );\n\t\t\theader( 'Cross-Origin-Embedder-Policy: require-corp' );\n\t\t}\n\n\t\tob_start( [ $this, 'replace_in_dom' ] );\n\t}\n\n\t/**\n\t * Filters the HTML link tag of an enqueued style.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param mixed  $tag    The link tag for the enqueued style.\n\t * @param string $handle The style's registered handle.\n\t * @param string $href   The stylesheet's source URL.\n\t * @return string|mixed\n\t */\n\tpublic function style_loader_tag( $tag, string $handle, string $href ) {\n\t\treturn $this->add_attribute( $tag, 'href', $href );\n\t}\n\n\t/**\n\t * Filters the HTML script tag of an enqueued script.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param mixed  $tag    The `<script>` tag for the enqueued script.\n\t * @param string $handle The script's registered handle.\n\t * @param string $src    The script's source URL.\n\t * @return string|mixed The filtered script tag.\n\t */\n\tpublic function script_loader_tag( $tag, string $handle, string $src ) {\n\t\treturn $this->add_attribute( $tag, 'src', $src );\n\t}\n\n\t/**\n\t * Filter the avatar tag.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string|mixed        $avatar      HTML for the user's avatar.\n\t * @param mixed               $id_or_email The avatar to retrieve. Accepts a user_id, Gravatar MD5 hash,\n\t *                                         user email, WP_User object, WP_Post object, or WP_Comment object.\n\t * @param mixed               $size        Square avatar width and height in pixels to retrieve.\n\t * @param mixed               $default_url URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',\n\t *                                         'wavatar', 'indenticon', 'mystery', 'mm', 'mysteryman', 'blank', or\n\t *                                         'gravatar_default'. Default is the value of the 'avatar_default' option, with a\n\t *                                         fallback of 'mystery'.\n\t * @param mixed               $alt         Alternative text to use in the avatar image tag. Default empty.\n\t * @param array<string,mixed> $args        Arguments passed to get_avatar_data(), after processing.\n\t * @return string|mixed Filtered avatar tag.\n\t */\n\tpublic function get_avatar( $avatar, $id_or_email, $size, $default_url, $alt, array $args ) {\n\t\treturn $this->add_attribute( $avatar, 'src', $args['url'] );\n\t}\n\n\t/**\n\t * Unhook wp_print_media_templates and replace with custom media templates.\n\t *\n\t * @since 1.8.0\n\t */\n\tpublic function override_media_templates(): void {\n\t\tremove_action( 'admin_footer', 'wp_print_media_templates' );\n\t\tadd_action( 'admin_footer', [ $this, 'custom_print_media_templates' ] );\n\t}\n\n\t/**\n\t * Add crossorigin attribute to all tags that could have assets loaded from a different domain.\n\t *\n\t * @since 1.8.0\n\t */\n\tpublic function custom_print_media_templates(): void {\n\t\tob_start();\n\t\twp_print_media_templates();\n\t\t$html = (string) ob_get_clean();\n\n\t\t$tags = [\n\t\t\t'audio',\n\t\t\t'img',\n\t\t\t'video',\n\t\t];\n\t\tforeach ( $tags as $tag ) {\n\t\t\t$html = (string) str_replace( '<' . $tag, '<' . $tag . ' crossorigin=\"anonymous\"', $html );\n\t\t}\n\n\t\techo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t}\n\n\t/**\n\t * Determines whether \"full\" cross-origin isolation is needed.\n\t *\n\t * By default, `crossorigin=\"anonymous\"` attributes are added to all external\n\t * resources to make sure they can be accessed programmatically (e.g. by html-to-image).\n\t *\n\t * However, actual cross-origin isolation by sending COOP and COEP headers is only\n\t * needed when video optimization is enabled\n\t *\n\t * @since 1.14.0\n\t *\n\t * @link https://github.com/googleforcreators/web-stories-wp/issues/9327\n\t * @link https://web.dev/coop-coep/\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tprivate function needs_isolation(): bool {\n\t\t$user_id = get_current_user_id();\n\t\tif ( ! $user_id ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Cross-origin isolation is not needed if users can't upload files anyway.\n\t\tif ( ! user_can( $user_id, 'upload_files' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t/**\n\t\t * Whether the user has opted in to video optimization.\n\t\t *\n\t\t * @var string|bool $preference\n\t\t */\n\t\t$preference = $this->preferences->get_preference( $user_id, $this->preferences::MEDIA_OPTIMIZATION_META_KEY );\n\n\t\treturn rest_sanitize_boolean( $preference );\n\t}\n\n\t/**\n\t * Process a html string and add attribute attributes to required tags.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $html HTML document as string.\n\t * @return string Processed HTML document.\n\t */\n\tprotected function replace_in_dom( string $html ): string { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\t$site_url = site_url();\n\n\t\t// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin.\n\t\t$tags = [\n\t\t\t'audio',\n\t\t\t'img',\n\t\t\t'link',\n\t\t\t'script',\n\t\t\t'video',\n\t\t];\n\n\t\t$tags      = implode( '|', $tags );\n\t\t$matches   = [];\n\t\t$processed = [];\n\n\t\tif ( preg_match_all( '#<(?P<tag>' . $tags . ')[^<]*?(?:>[\\s\\S]*?</(?P=tag)>|\\s*/>)#', $html, $matches ) ) {\n\n\t\t\t/**\n\t\t\t * Single match.\n\t\t\t *\n\t\t\t * @var string $match\n\t\t\t */\n\t\t\tforeach ( $matches[0] as $index => $match ) {\n\t\t\t\t$tag = $matches['tag'][ $index ];\n\n\t\t\t\tif ( str_contains( $match, ' crossorigin=' ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$match_value = [];\n\t\t\t\tif ( ! preg_match( '/(src|href)=(\"([^\"]+)\"|\\'([^\\']+)\\')/', $match, $match_value ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$attribute = $match_value[1];\n\t\t\t\t$value     = $match_value[4] ?? $match_value[3] ?? '';\n\t\t\t\t$cache_key = 'video' === $tag || 'audio' === $tag ? $tag : $attribute;\n\n\t\t\t\t// If already processed tag/attribute and value before, skip.\n\t\t\t\tif ( isset( $processed[ $cache_key ] ) && \\in_array( $value, $processed[ $cache_key ], true ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$processed[ $cache_key ][] = $value;\n\n\t\t\t\t// The only tags that can have <source> children.\n\t\t\t\tif ( 'video' === $tag || 'audio' === $tag ) {\n\t\t\t\t\tif ( ! str_starts_with( $value, $site_url ) && ! str_starts_with( $value, '/' ) ) {\n\t\t\t\t\t\t$html = str_replace( $match, str_replace( '<' . $tag, '<' . $tag . ' crossorigin=\"anonymous\"', $match ), $html );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/**\n\t\t\t\t\t * Modified HTML.\n\t\t\t\t\t *\n\t\t\t\t\t * @var string $html\n\t\t\t\t\t */\n\t\t\t\t\t$html = $this->add_attribute( $html, $attribute, $value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $html;\n\t}\n\n\t/**\n\t * Do replacement to add crossorigin attribute.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string|mixed      $html HTML string.\n\t * @param string            $attribute Attribute to check for.\n\t * @param string|null|mixed $url URL.\n\t * @return string|mixed Filtered HTML string.\n\t */\n\tprotected function add_attribute( $html, string $attribute, $url ) {\n\t\t/**\n\t\t * URL.\n\t\t *\n\t\t * @var string $url\n\t\t */\n\t\tif ( ! $url || ! \\is_string( $html ) ) {\n\t\t\treturn $html;\n\t\t}\n\n\t\t$site_url = site_url();\n\t\t$url      = esc_url( $url );\n\n\t\tif ( str_starts_with( $url, $site_url ) ) {\n\t\t\treturn $html;\n\t\t}\n\n\t\tif ( str_starts_with( $url, '/' ) ) {\n\t\t\treturn $html;\n\t\t}\n\n\t\treturn str_replace(\n\t\t\t[\n\t\t\t\t$attribute . '=\"' . $url . '\"',\n\t\t\t\t\"{$attribute}='{$url}'\",\n\t\t\t],\n\t\t\t[\n\t\t\t\t'crossorigin=\"anonymous\" ' . $attribute . '=\"' . $url . '\"',\n\t\t\t\t\"crossorigin='anonymous' {$attribute}='{$url}'\",\n\t\t\t],\n\t\t\t$html\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Customizer.php",
    "content": "<?php\n/**\n * Class Customizer\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Stories_Script_Data;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse WP_Customize_Manager;\nuse WP_Customize_Setting;\nuse WP_Error;\n\n/**\n * Class customizer settings.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type ThemeSupport array{\n *   customizer: array{\n *     view_type: array{default: string, enabled: string[]},\n *     title: array{default: bool, enabled: bool},\n *     excerpt: array{default: bool, enabled: bool},\n *     author: array{default: bool, enabled: bool},\n *     date: array{default: bool, enabled: bool},\n *     show_archive_link: array{default: bool, enabled: bool},\n *     archive_link: array{default: bool|string, enabled: bool|string, label: string},\n *     sharp_corners: array{default: bool, enabled: bool},\n *     order: array{default: string},\n *     orderby: array{default: string},\n *     circle_size: array{default: int},\n *     number_of_stories: array{default: int},\n *     number_of_columns: array{default: int},\n *     image_alignment: array{default: string}\n *   }\n * }\n *\n * @phpstan-type StoryAttributes array{\n *   view_type?: string,\n *   number_of_columns?: int,\n *   show_title?: bool,\n *   show_author?: bool,\n *   show_date?: bool,\n *   show_archive_link?: bool|string,\n *   show_excerpt?: bool,\n *   image_alignment?: string,\n *   class?: string,\n *   show_stories?: bool|string,\n *   archive_link_label?: string,\n *   circle_size?: int,\n *   sharp_corners?: bool,\n *   order?: string,\n *   orderby?: string,\n *   number_of_stories?: int\n * }\n */\nclass Customizer extends Service_Base implements Conditional {\n\n\t/**\n\t * Customizer section slug.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic const SECTION_SLUG = 'web_story_options';\n\n\t/**\n\t * Customizer web stories options key.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic const STORY_OPTION = 'web_stories_customizer_settings';\n\n\t/**\n\t * WP_Customize_Manager instance.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @var WP_Customize_Manager $wp_customize WP_Customize_Manager instance.\n\t */\n\tprivate WP_Customize_Manager $wp_customize;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Stories_Script_Data instance.\n\t *\n\t * @var Stories_Script_Data Stories_Script_Data instance.\n\t */\n\tprotected Stories_Script_Data $stories_script_data;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Story_Post_Type     $story_post_type     Story_Post_Type instance.\n\t * @param Stories_Script_Data $stories_script_data Stories_Script_Data instance.\n\t * @return void\n\t */\n\tpublic function __construct(\n\t\tStory_Post_Type $story_post_type,\n\t\tStories_Script_Data $stories_script_data\n\t) {\n\t\t$this->story_post_type     = $story_post_type;\n\t\t$this->stories_script_data = $stories_script_data;\n\t}\n\n\t/**\n\t * Initializes the customizer logic.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'customize_register', [ $this, 'register_customizer_settings' ] );\n\t}\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\treturn ! \\function_exists( 'wp_is_block_theme' ) || ! wp_is_block_theme();\n\t}\n\n\t/**\n\t * Registers web stories customizer settings.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param WP_Customize_Manager $wp_customize WP_Customize_Manager instance.\n\t */\n\tpublic function register_customizer_settings( WP_Customize_Manager $wp_customize ): void {\n\t\t$this->wp_customize = $wp_customize;\n\n\t\t$theme_support = $this->get_stories_theme_support()['customizer'];\n\n\t\t$active_callback = fn() => $this->is_option_enabled( 'show_stories' );\n\n\t\t$wp_customize->add_section(\n\t\t\tself::SECTION_SLUG,\n\t\t\t[\n\t\t\t\t'title'          => esc_html__( 'Web Stories', 'web-stories' ),\n\t\t\t\t'theme_supports' => 'web-stories',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[show_stories]',\n\t\t\t[\n\t\t\t\t'default' => false,\n\t\t\t\t'type'    => 'option',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[show_stories]',\n\t\t\t[\n\t\t\t\t'type'    => 'checkbox',\n\t\t\t\t'section' => self::SECTION_SLUG,\n\t\t\t\t'label'   => __( 'Display stories', 'web-stories' ),\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[view_type]',\n\t\t\t[\n\t\t\t\t'default' => $theme_support['view_type']['default'],\n\t\t\t\t'type'    => 'option',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[view_type]',\n\t\t\t[\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => _x( 'View Type', 'noun', 'web-stories' ),\n\t\t\t\t'type'            => 'select',\n\t\t\t\t'choices'         => $this->get_view_type_choices( $theme_support['view_type']['enabled'] ),\n\t\t\t\t'active_callback' => $active_callback,\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[number_of_stories]',\n\t\t\t[\n\t\t\t\t'default'           => $theme_support['number_of_stories']['default'],\n\t\t\t\t'type'              => 'option',\n\t\t\t\t'validate_callback' => [ $this, 'validate_number_of_stories' ],\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[number_of_stories]',\n\t\t\t[\n\t\t\t\t'type'            => 'number',\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Number of Stories', 'web-stories' ),\n\t\t\t\t'input_attrs'     => [\n\t\t\t\t\t'min' => 1,\n\t\t\t\t\t'max' => 20,\n\t\t\t\t],\n\t\t\t\t'active_callback' => $active_callback,\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[number_of_columns]',\n\t\t\t[\n\t\t\t\t'default'           => $theme_support['number_of_columns']['default'],\n\t\t\t\t'type'              => 'option',\n\t\t\t\t'validate_callback' => [ $this, 'validate_number_of_columns' ],\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[number_of_columns]',\n\t\t\t[\n\t\t\t\t'type'            => 'number',\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Number of Columns', 'web-stories' ),\n\t\t\t\t'input_attrs'     => [\n\t\t\t\t\t'min' => 1,\n\t\t\t\t\t'max' => 4,\n\t\t\t\t],\n\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && $this->is_view_type( 'grid' ) ),\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[orderby]',\n\t\t\t[\n\t\t\t\t'default' => $theme_support['orderby']['default'],\n\t\t\t\t'type'    => 'option',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[orderby]',\n\t\t\t[\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Order By', 'web-stories' ),\n\t\t\t\t'type'            => 'select',\n\t\t\t\t'choices'         => [\n\t\t\t\t\t'post_title' => __( 'Title', 'web-stories' ),\n\t\t\t\t\t'post_date'  => __( 'Date', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'active_callback' => $active_callback,\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[order]',\n\t\t\t[\n\t\t\t\t'default' => $theme_support['order']['default'],\n\t\t\t\t'type'    => 'option',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[order]',\n\t\t\t[\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Order', 'web-stories' ),\n\t\t\t\t'type'            => 'select',\n\t\t\t\t'choices'         => [\n\t\t\t\t\t'ASC'  => __( 'Ascending', 'web-stories' ),\n\t\t\t\t\t'DESC' => __( 'Descending', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'active_callback' => $active_callback,\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[circle_size]',\n\t\t\t[\n\t\t\t\t'default' => $theme_support['circle_size']['default'],\n\t\t\t\t'type'    => 'option',\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[circle_size]',\n\t\t\t[\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Circle Size', 'web-stories' ),\n\t\t\t\t'type'            => 'number',\n\t\t\t\t'input_attrs'     => [\n\t\t\t\t\t'min'  => 80,\n\t\t\t\t\t'max'  => 200,\n\t\t\t\t\t'step' => 5,\n\t\t\t\t],\n\t\t\t\t'active_callback' => fn() => $this->is_option_enabled( 'show_stories' ) && $this->is_view_type( 'circles' ),\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_setting(\n\t\t\tself::STORY_OPTION . '[image_alignment]',\n\t\t\t[\n\t\t\t\t'type'    => 'option',\n\t\t\t\t'default' => $theme_support['image_alignment']['default'],\n\t\t\t]\n\t\t);\n\n\t\t$wp_customize->add_control(\n\t\t\tself::STORY_OPTION . '[image_alignment]',\n\t\t\t[\n\t\t\t\t'type'            => 'radio',\n\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t'label'           => __( 'Image Alignment', 'web-stories' ),\n\t\t\t\t'choices'         => [\n\t\t\t\t\t'left'  => __( 'Left', 'web-stories' ),\n\t\t\t\t\t'right' => __( 'Right', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && $this->is_view_type( 'list' ) ),\n\t\t\t]\n\t\t);\n\n\t\tif ( $theme_support['title']['enabled'] ) {\n\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[show_title]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['title']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[show_title]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Display Title', 'web-stories' ),\n\t\t\t\t\t'active_callback' => $active_callback,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tif ( $theme_support['excerpt']['enabled'] ) {\n\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[show_excerpt]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['excerpt']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[show_excerpt]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Display Excerpt', 'web-stories' ),\n\t\t\t\t\t'active_callback' => fn() => $this->is_option_enabled( 'show_stories' ) && $this->is_view_type( 'list' ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tif ( $theme_support['author']['enabled'] ) {\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[show_author]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['author']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[show_author]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Display Author', 'web-stories' ),\n\t\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && ! $this->is_view_type( 'circles' ) ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tif ( $theme_support['date']['enabled'] ) {\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[show_date]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['date']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[show_date]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Display Date', 'web-stories' ),\n\t\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && ! $this->is_view_type( 'circles' ) ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tif ( $theme_support['sharp_corners']['enabled'] ) {\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[sharp_corners]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['sharp_corners']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[sharp_corners]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Sharp Corners', 'web-stories' ),\n\t\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && ! $this->is_view_type( 'circles' ) ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tif ( $theme_support['archive_link']['enabled'] ) {\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[show_archive_link]',\n\t\t\t\t[\n\t\t\t\t\t'default' => $theme_support['archive_link']['default'],\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[show_archive_link]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'checkbox',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Display Archive Link', 'web-stories' ),\n\t\t\t\t\t'active_callback' => $active_callback,\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_setting(\n\t\t\t\tself::STORY_OPTION . '[archive_link_label]',\n\t\t\t\t[\n\t\t\t\t\t'type'    => 'option',\n\t\t\t\t\t'default' => $theme_support['archive_link']['label'],\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$wp_customize->add_control(\n\t\t\t\tself::STORY_OPTION . '[archive_link_label]',\n\t\t\t\t[\n\t\t\t\t\t'type'            => 'text',\n\t\t\t\t\t'section'         => self::SECTION_SLUG,\n\t\t\t\t\t'label'           => __( 'Archive Link Label', 'web-stories' ),\n\t\t\t\t\t'active_callback' => fn() => ( $this->is_option_enabled( 'show_stories' ) && $this->is_option_enabled( 'show_archive_link' ) ),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Validates the number of story setting value.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param WP_Error $validity WP_Error object.\n\t * @param int      $value    Value to be validated.\n\t */\n\tpublic function validate_number_of_stories( WP_Error $validity, int $value ): WP_Error {\n\t\t$value = (int) $value;\n\n\t\tif ( $value <= 0 || $value > 20 ) {\n\t\t\t$validity->add( 'invalid_number', __( 'The number of stories must be between 1 and 20.', 'web-stories' ) );\n\t\t}\n\t\treturn $validity;\n\t}\n\n\t/**\n\t * Validates the number of columns setting value.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param WP_Error $validity WP_Error object.\n\t * @param int      $value Value to be validated.\n\t */\n\tpublic function validate_number_of_columns( WP_Error $validity, int $value ): WP_Error {\n\t\t$value = (int) $value;\n\n\t\tif ( $value <= 0 || $value > 5 ) {\n\t\t\t$validity->add( 'invalid_number', __( 'The number of columns must be between 1 and 4.', 'web-stories' ) );\n\t\t}\n\t\treturn $validity;\n\t}\n\n\t/**\n\t * Renders web stories based on the customizer selected options.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function render_stories(): string {\n\t\t// Not using Settings::get_setting() to avoid calling rest_sanitize_value_from_schema().\n\n\t\t/**\n\t\t * Render options.\n\t\t *\n\t\t * @var array<string,string|bool> $options\n\t\t * @phpstan-var StoryAttributes\n\t\t */\n\t\t$options = (array) get_option( self::STORY_OPTION );\n\n\t\tif ( empty( $options['show_stories'] ) || true !== $options['show_stories'] ) {\n\t\t\treturn '';\n\t\t}\n\n\t\t$theme_support = $this->get_stories_theme_support()['customizer'];\n\n\t\t$story_attributes = [\n\t\t\t'view_type'          => $options['view_type'] ?? $theme_support['view_type']['default'],\n\t\t\t'show_title'         => isset( $options['show_title'] ) ? (bool) $options['show_title'] : $theme_support['title']['default'],\n\t\t\t'show_excerpt'       => isset( $options['show_excerpt'] ) ? (bool) $options['show_excerpt'] : $theme_support['excerpt']['default'],\n\t\t\t'show_author'        => isset( $options['show_author'] ) ? (bool) $options['show_author'] : $theme_support['author']['default'],\n\t\t\t'show_date'          => isset( $options['show_date'] ) ? (bool) $options['show_date'] : $theme_support['date']['default'],\n\t\t\t'show_archive_link'  => isset( $options['show_archive_link'] ) ? (bool) $options['show_archive_link'] : $theme_support['archive_link']['default'],\n\t\t\t'archive_link_label' => isset( $options['archive_link_label'] ) ? (string) $options['archive_link_label'] : $theme_support['archive_link']['label'],\n\t\t\t'circle_size'        => isset( $options['circle_size'] ) ? (int) $options['circle_size'] : $theme_support['circle_size']['default'],\n\t\t\t'sharp_corners'      => isset( $options['sharp_corners'] ) ? (bool) $options['sharp_corners'] : $theme_support['sharp_corners']['default'],\n\t\t\t'image_alignment'    => isset( $options['image_alignment'] ) ? (string) $options['image_alignment'] : $theme_support['image_alignment']['default'],\n\t\t\t'number_of_columns'  => isset( $options['number_of_columns'] ) ? (int) $options['number_of_columns'] : $theme_support['number_of_columns']['default'],\n\t\t\t'class'              => 'web-stories-list--customizer',\n\t\t];\n\n\t\t$query_arguments = [\n\t\t\t'posts_per_page' => isset( $options['number_of_stories'] ) ? (int) $options['number_of_stories'] : $theme_support['number_of_stories']['default'], // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page\n\t\t\t'orderby'        => isset( $options['orderby'] ) ? (string) $options['orderby'] : $theme_support['orderby']['default'],\n\t\t\t'order'          => isset( $options['order'] ) ? (string) $options['order'] : $theme_support['order']['default'],\n\t\t];\n\n\t\treturn ( new Story_Query( $story_attributes, $query_arguments ) )->render();\n\t}\n\n\t/**\n\t * Get theme support configuration.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return array Theme support configuration\n\t *\n\t * @phpstan-return ThemeSupport\n\t */\n\tpublic function get_stories_theme_support(): array {\n\t\t/**\n\t\t * Theme support configuration.\n\t\t *\n\t\t * @var ThemeSupport[]|array<int, false> $support\n\t\t */\n\t\t$support = get_theme_support( 'web-stories' );\n\t\t$support = isset( $support[0] ) && \\is_array( $support[0] ) ? $support[0] : [];\n\n\t\t$has_archive = (bool) $this->story_post_type->get_has_archive();\n\n\t\t$default_support = [\n\t\t\t'customizer' => [\n\t\t\t\t'view_type'         => [\n\t\t\t\t\t'enabled' => [ 'circles' ],\n\t\t\t\t\t'default' => 'circles',\n\t\t\t\t],\n\t\t\t\t'title'             => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => true,\n\t\t\t\t],\n\t\t\t\t'excerpt'           => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'author'            => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => true,\n\t\t\t\t],\n\t\t\t\t'date'              => [\n\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'archive_link'      => [\n\t\t\t\t\t'enabled' => $has_archive,\n\t\t\t\t\t'default' => $has_archive,\n\t\t\t\t\t'label'   => __( 'View all stories', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'sharp_corners'     => [\n\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'order'             => [\n\t\t\t\t\t'default' => 'DESC',\n\t\t\t\t],\n\t\t\t\t'orderby'           => [\n\t\t\t\t\t'default' => 'post_date',\n\t\t\t\t],\n\t\t\t\t'circle_size'       => [\n\t\t\t\t\t'default' => 150,\n\t\t\t\t],\n\t\t\t\t'number_of_stories' => [\n\t\t\t\t\t'default' => 10,\n\t\t\t\t],\n\t\t\t\t'number_of_columns' => [\n\t\t\t\t\t'default' => 2,\n\t\t\t\t],\n\t\t\t\t'image_alignment'   => [\n\t\t\t\t\t'default' => is_rtl() ? 'right' : 'left',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Theme support config.\n\t\t *\n\t\t * @var ThemeSupport $support\n\t\t */\n\t\t$support = $this->parse_args( $support, $default_support );\n\n\t\treturn $support;\n\t}\n\n\t/**\n\t * Gets the view type choices.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string> $view_type View type to check.\n\t * @return array<string,string> An array of view type choices.\n\t */\n\tprivate function get_view_type_choices( array $view_type ): array {\n\t\t$view_type_choices = $this->stories_script_data->get_layouts();\n\n\t\tif ( empty( $view_type ) ) {\n\t\t\treturn $view_type_choices;\n\t\t}\n\n\t\treturn array_intersect_key( $view_type_choices, array_fill_keys( $view_type, true ) );\n\t}\n\n\t/**\n\t * Checks whether the given option is enabled or not.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string $option_name The name of the option to check.\n\t * @return bool Returns true if the given option is enabled otherwise false.\n\t */\n\tprivate function is_option_enabled( string $option_name ): bool {\n\t\t$setting = $this->wp_customize->get_setting( self::STORY_OPTION . \"[{$option_name}]\" );\n\t\treturn ( $setting instanceof WP_Customize_Setting && true === $setting->value() );\n\t}\n\n\t/**\n\t * Verifies the current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string $view_type View type to check.\n\t * @return bool Whether or not current view type matches the one passed.\n\t */\n\tprivate function is_view_type( string $view_type ): bool {\n\t\t$setting = $this->wp_customize->get_setting( self::STORY_OPTION . '[view_type]' );\n\t\treturn ( $setting instanceof WP_Customize_Setting && $view_type === $setting->value() );\n\t}\n\n\t/**\n\t * Merges user defined arguments into defaults array.\n\t *\n\t * Like wp_parse_args(), but recursive.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @see wp_parse_args()\n\t *\n\t * @param array<string, mixed>                                                           $args     Value to merge with $defaults.\n\t * @param array<string, array<string, array<string, array<int,string>|bool|int|string>>> $defaults Optional. Array that serves as the defaults. Default empty array.\n\t * @return array<string, mixed> Merged user defined values with defaults.\n\t */\n\tprivate function parse_args( array $args, array $defaults = [] ): array {\n\t\t$parsed_args = $defaults;\n\n\t\tforeach ( $args as $key => $value ) {\n\t\t\tif ( \\is_array( $value ) && isset( $parsed_args[ $key ] ) ) {\n\t\t\t\t/**\n\t\t\t\t * Default value.\n\t\t\t\t *\n\t\t\t\t * @var array<string, array<string, array<string, array<int,string>|bool|int|string>>> $def\n\t\t\t\t */\n\t\t\t\t$def = $parsed_args[ $key ];\n\n\t\t\t\t// @phpstan-ignore argument.type (TODO: improve type for recursion)\n\t\t\t\t$parsed_args[ $key ] = $this->parse_args( $value, $def );\n\t\t\t} else {\n\t\t\t\t$parsed_args[ $key ] = $value;\n\t\t\t}\n\t\t}\n\n\t\treturn $parsed_args;\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Dashboard.php",
    "content": "<?php\n/**\n * Dashboard class.\n *\n * Responsible for adding the stories dashboard to WordPress admin.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Decoder;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Integrations\\Site_Kit;\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\Locale;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tracking;\n\n/**\n * Dashboard class.\n */\nclass Dashboard extends Service_Base {\n\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-dashboard';\n\n\t/**\n\t * Admin page hook suffixes.\n\t *\n\t * @var array<string,string|bool> List of the admin pages' hook_suffix values.\n\t */\n\tprivate array $hook_suffix = [];\n\n\t/**\n\t * Experiments instance.\n\t *\n\t * @var Experiments Experiments instance.\n\t */\n\tprivate Experiments $experiments;\n\n\t/**\n\t * Site_Kit instance.\n\t *\n\t * @var Site_Kit Site_Kit instance.\n\t */\n\tprivate Site_Kit $site_kit;\n\n\t/**\n\t * Decoder instance.\n\t *\n\t * @var Decoder Decoder instance.\n\t */\n\tprivate Decoder $decoder;\n\n\t/**\n\t * Locale instance.\n\t *\n\t * @var Locale Locale instance.\n\t */\n\tprivate Locale $locale;\n\n\t/**\n\t * Google_Fonts instance.\n\t *\n\t * @var Google_Fonts Google_Fonts instance.\n\t */\n\tprivate Google_Fonts $google_fonts;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Font_Post_Type instance.\n\t *\n\t * @var Font_Post_Type Font_Post_Type instance.\n\t */\n\tprivate Font_Post_Type $font_post_type;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Types instance.\n\t *\n\t * @var Types Types instance.\n\t */\n\tprivate Types $types;\n\n\t/**\n\t * Shopping_Vendors instance.\n\t *\n\t * @var Shopping_Vendors Shopping_Vendors instance.\n\t */\n\tprivate Shopping_Vendors $shopping_vendors;\n\n\t/**\n\t * WooCommerce instance.\n\t *\n\t * @var WooCommerce WooCommerce instance.\n\t */\n\tprivate WooCommerce $woocommerce;\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Dashboard constructor.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveParameterList\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Experiments      $experiments      Experiments instance.\n\t * @param Site_Kit         $site_kit         Site_Kit instance.\n\t * @param Decoder          $decoder          Decoder instance.\n\t * @param Locale           $locale           Locale instance.\n\t * @param Google_Fonts     $google_fonts     Google_Fonts instance.\n\t * @param Assets           $assets           Assets instance.\n\t * @param Font_Post_Type   $font_post_type   Font_Post_Type instance.\n\t * @param Story_Post_Type  $story_post_type  Story_Post_Type instance.\n\t * @param Context          $context          Context instance.\n\t * @param Types            $types            Types instance.\n\t * @param Shopping_Vendors $shopping_vendors Shopping_Vendors instance.\n\t * @param WooCommerce      $woocommerce      WooCommerce instance.\n\t * @param Settings         $settings         Settings instance.\n\t */\n\tpublic function __construct(\n\t\tExperiments $experiments,\n\t\tSite_Kit $site_kit,\n\t\tDecoder $decoder,\n\t\tLocale $locale,\n\t\tGoogle_Fonts $google_fonts,\n\t\tAssets $assets,\n\t\tFont_Post_Type $font_post_type,\n\t\tStory_Post_Type $story_post_type,\n\t\tContext $context,\n\t\tTypes $types,\n\t\tShopping_Vendors $shopping_vendors,\n\t\tWooCommerce $woocommerce,\n\t\tSettings $settings\n\t) {\n\t\t$this->experiments      = $experiments;\n\t\t$this->decoder          = $decoder;\n\t\t$this->site_kit         = $site_kit;\n\t\t$this->locale           = $locale;\n\t\t$this->google_fonts     = $google_fonts;\n\t\t$this->assets           = $assets;\n\t\t$this->font_post_type   = $font_post_type;\n\t\t$this->story_post_type  = $story_post_type;\n\t\t$this->context          = $context;\n\t\t$this->types            = $types;\n\t\t$this->shopping_vendors = $shopping_vendors;\n\t\t$this->woocommerce      = $woocommerce;\n\t\t$this->settings         = $settings;\n\t}\n\n\t/**\n\t * Initializes the dashboard logic.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'admin_menu', [ $this, 'add_menu_page' ] );\n\t\tadd_action( 'admin_init', [ $this, 'redirect_menu_page' ] );\n\t\tadd_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );\n\t\tadd_action( 'admin_notices', [ $this, 'display_link_to_dashboard' ] );\n\t\tadd_action( 'load-web-story_page_stories-dashboard', [ $this, 'load_stories_dashboard' ] );\n\t}\n\n\t/**\n\t * Returns the admin page's hook suffix.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $key The current admin page key.\n\t * @return bool|string The dashboard page's hook_suffix, or false if the user does not have the capability required.\n\t */\n\tpublic function get_hook_suffix( string $key ) {\n\t\treturn $this->hook_suffix[ $key ] ?? false;\n\t}\n\n\t/**\n\t * Registers the dashboard admin menu page.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function add_menu_page(): void {\n\t\t$parent = 'edit.php?post_type=' . $this->story_post_type->get_slug();\n\n\t\t// Not using get_dashboard_settings() to avoid an extra database query.\n\n\t\t$settings = [\n\t\t\t'canViewDefaultTemplates' => true,\n\t\t];\n\n\t\t/** This filter is documented in includes/Admin/Dashboard.php */\n\t\t$settings = apply_filters( 'web_stories_dashboard_settings', $settings );\n\n\t\t/**\n\t\t * The edit_posts capability.\n\t\t *\n\t\t * @var string $edit_posts\n\t\t */\n\t\t$edit_posts = $this->story_post_type->get_cap_name( 'edit_posts' );\n\n\t\t$this->hook_suffix['stories-dashboard'] = add_submenu_page(\n\t\t\t$parent,\n\t\t\t__( 'Dashboard', 'web-stories' ),\n\t\t\t__( 'Dashboard', 'web-stories' ),\n\t\t\t$edit_posts, // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t'stories-dashboard',\n\t\t\t[ $this, 'render' ],\n\t\t\t0\n\t\t);\n\n\t\tif ( isset( $settings['canViewDefaultTemplates'] ) && $settings['canViewDefaultTemplates'] ) {\n\t\t\t$this->hook_suffix['stories-dashboard-explore'] = add_submenu_page(\n\t\t\t\t$parent,\n\t\t\t\t__( 'Explore Templates', 'web-stories' ),\n\t\t\t\t__( 'Explore Templates', 'web-stories' ),\n\t\t\t\t$edit_posts, // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t\t'stories-dashboard#/templates-gallery',\n\t\t\t\t'__return_null',\n\t\t\t\t1\n\t\t\t);\n\t\t}\n\n\t\t$this->hook_suffix['stories-dashboard-settings'] = add_submenu_page(\n\t\t\t$parent,\n\t\t\t__( 'Settings', 'web-stories' ),\n\t\t\t__( 'Settings', 'web-stories' ),\n\t\t\t$edit_posts, // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t'stories-dashboard#/editor-settings',\n\t\t\t'__return_null',\n\t\t\t20\n\t\t);\n\t}\n\n\t/**\n\t * Redirects to the correct Dashboard page when clicking on the top-level \"Stories\" menu item.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function redirect_menu_page(): void {\n\t\tglobal $pagenow;\n\n\t\tif ( ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Page slug.\n\t\t *\n\t\t * @var string $page\n\t\t */\n\t\t$page = $_GET['page']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\t\t$page = sanitize_text_field( (string) wp_unslash( $page ) );\n\n\t\tif ( 'admin.php' === $pagenow && 'stories-dashboard' === $page ) {\n\t\t\twp_safe_redirect(\n\t\t\t\tadd_query_arg(\n\t\t\t\t\t[\n\t\t\t\t\t\t'post_type' => $this->story_post_type->get_slug(),\n\t\t\t\t\t\t'page'      => 'stories-dashboard',\n\t\t\t\t\t],\n\t\t\t\t\tadmin_url( 'edit.php' )\n\t\t\t\t)\n\t\t\t);\n\t\t\texit;\n\t\t}\n\t}\n\n\t/**\n\t * Preload API requests in the dashboard.\n\t *\n\t * Important: keep in sync with usage & definition in React app.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function load_stories_dashboard(): void {\n\t\t$rest_url = trailingslashit( $this->story_post_type->get_rest_url() );\n\n\t\t$preload_paths = [\n\t\t\t'/web-stories/v1/settings/',\n\t\t\t'/web-stories/v1/publisher-logos/',\n\t\t\t'/web-stories/v1/users/me/',\n\t\t\t'/web-stories/v1/taxonomies/?' . build_query(\n\t\t\t\t[\n\t\t\t\t\t'type'         => $this->story_post_type->get_slug(),\n\t\t\t\t\t'context'      => 'edit',\n\t\t\t\t\t'hierarchical' => 'true',\n\t\t\t\t\t'show_ui'      => 'true',\n\t\t\t\t]\n\t\t\t),\n\t\t\t$rest_url . '?' . build_query(\n\t\t\t\t[\n\t\t\t\t\t'_embed'                => rawurlencode(\n\t\t\t\t\t\timplode(\n\t\t\t\t\t\t\t',',\n\t\t\t\t\t\t\t[ 'wp:lock', 'author' ]\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t\t'context'               => 'edit',\n\t\t\t\t\t'order'                 => 'desc',\n\t\t\t\t\t'orderby'               => 'modified',\n\t\t\t\t\t'page'                  => 1,\n\t\t\t\t\t'per_page'              => 24,\n\t\t\t\t\t'status'                => rawurlencode(\n\t\t\t\t\t\timplode(\n\t\t\t\t\t\t\t',',\n\t\t\t\t\t\t\t[ 'draft', 'future', 'pending', 'publish', 'private' ]\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t\t'_web_stories_envelope' => 'true',\n\t\t\t\t\t'_fields'               => rawurlencode(\n\t\t\t\t\t\timplode(\n\t\t\t\t\t\t\t',',\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'id',\n\t\t\t\t\t\t\t\t'title',\n\t\t\t\t\t\t\t\t'status',\n\t\t\t\t\t\t\t\t'date',\n\t\t\t\t\t\t\t\t'date_gmt',\n\t\t\t\t\t\t\t\t'modified',\n\t\t\t\t\t\t\t\t'modified_gmt',\n\t\t\t\t\t\t\t\t'story_poster',\n\t\t\t\t\t\t\t\t'link',\n\t\t\t\t\t\t\t\t'preview_link',\n\t\t\t\t\t\t\t\t'edit_link',\n\t\t\t\t\t\t\t\t'_links', // Needed for WP 6.1+.\n\t\t\t\t\t\t\t\t'_embedded',\n\t\t\t\t\t\t\t\t// _web_stories_envelope will add these fields, we need them too.\n\t\t\t\t\t\t\t\t'body',\n\t\t\t\t\t\t\t\t'status',\n\t\t\t\t\t\t\t\t'headers',\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t),\n\t\t];\n\n\t\t/**\n\t\t * Preload common data by specifying an array of REST API paths that will be preloaded.\n\t\t *\n\t\t * Filters the array of paths that will be preloaded.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param string[] $preload_paths Array of paths to preload.\n\t\t */\n\t\t$preload_paths = apply_filters( 'web_stories_dashboard_preload_paths', $preload_paths );\n\n\t\t$preload_data = array_reduce(\n\t\t\t$preload_paths,\n\t\t\t'\\Google\\Web_Stories\\rest_preload_api_request',\n\t\t\t[]\n\t\t);\n\n\t\twp_add_inline_script(\n\t\t\t'wp-api-fetch',\n\t\t\t\\sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload_data ) ),\n\t\t\t'after'\n\t\t);\n\t}\n\n\t/**\n\t * Renders the dashboard page.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function render(): void {\n\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/admin/dashboard.php';\n\t}\n\n\t/**\n\t * Enqueues dashboard scripts and styles.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $hook_suffix The current admin page.\n\t */\n\tpublic function enqueue_assets( string $hook_suffix ): void {\n\t\tif ( $this->get_hook_suffix( 'stories-dashboard' ) !== $hook_suffix ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->assets->enqueue_script_asset( self::SCRIPT_HANDLE, [ Tracking::SCRIPT_HANDLE ], false );\n\n\t\t$this->assets->enqueue_style_asset( self::SCRIPT_HANDLE, [ $this->google_fonts::SCRIPT_HANDLE ] );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStories',\n\t\t\t[\n\t\t\t\t'publicPath' => $this->assets->get_base_url( 'assets/js/' ), // Required before the editor script is enqueued.\n\t\t\t\t'localeData' => $this->assets->get_translations( self::SCRIPT_HANDLE ), // Required for i18n setLocaleData.\n\t\t\t]\n\t\t);\n\n\t\t// Dequeue forms.css, see https://github.com/googleforcreators/web-stories-wp/issues/349 .\n\t\t$this->assets->remove_admin_style( [ 'forms' ] );\n\t}\n\n\t/**\n\t * Get dashboard settings as an array.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string,bool|string|int|array<string,mixed>>\n\t */\n\tpublic function get_dashboard_settings(): array {\n\t\t$new_story_url = admin_url(\n\t\t\tadd_query_arg(\n\t\t\t\t[\n\t\t\t\t\t'post_type' => $this->story_post_type->get_slug(),\n\t\t\t\t],\n\t\t\t\t'post-new.php'\n\t\t\t)\n\t\t);\n\n\t\t// Media settings.\n\t\t$max_upload_size = wp_max_upload_size();\n\t\tif ( ! $max_upload_size ) {\n\t\t\t$max_upload_size = 0;\n\t\t}\n\t\t$mime_types               = $this->types->get_allowed_mime_types();\n\t\t$allowed_image_mime_types = $mime_types['image'];\n\t\t$vendors                  = wp_list_pluck( $this->shopping_vendors->get_vendors(), 'label' );\n\n\t\t$auto_advance  = $this->settings->get_setting( $this->settings::SETTING_NAME_AUTO_ADVANCE );\n\t\t$page_duration = $this->settings->get_setting( $this->settings::SETTING_NAME_DEFAULT_PAGE_DURATION );\n\n\t\t$plugin_file          = plugin_basename( WEBSTORIES_PLUGIN_FILE );\n\t\t$auto_updates         = (array) get_site_option( 'auto_update_plugins', [] );\n\t\t$auto_updates_enabled = \\in_array( $plugin_file, $auto_updates, true );\n\t\t$plugin_updates       = get_site_transient( 'update_plugins' );\n\t\t$needs_update         = \\is_object( $plugin_updates ) &&\n\t\t\t\t\t\t\t\tproperty_exists( $plugin_updates, 'response' ) &&\n\t\t\t\t\t\t\t\t\\is_array( $plugin_updates->response ) &&\n\t\t\t\t\t\t\t\t! empty( $plugin_updates->response[ $plugin_file ] );\n\t\t$can_update           = current_user_can( 'update_plugins' );\n\n\t\t$settings = [\n\t\t\t'isRTL'                   => is_rtl(),\n\t\t\t'userId'                  => get_current_user_id(),\n\t\t\t'locale'                  => $this->locale->get_locale_settings(),\n\t\t\t'newStoryURL'             => $new_story_url,\n\t\t\t'archiveURL'              => $this->story_post_type->get_archive_link(),\n\t\t\t'defaultArchiveURL'       => $this->story_post_type->get_archive_link( true ),\n\t\t\t'cdnURL'                  => trailingslashit( WEBSTORIES_CDN_URL ),\n\t\t\t'allowedImageMimeTypes'   => $allowed_image_mime_types,\n\t\t\t'version'                 => WEBSTORIES_VERSION,\n\t\t\t'encodeMarkup'            => $this->decoder->supports_decoding(),\n\t\t\t'api'                     => [\n\t\t\t\t'stories'        => trailingslashit( $this->story_post_type->get_rest_url() ),\n\t\t\t\t'media'          => '/web-stories/v1/media/',\n\t\t\t\t'currentUser'    => '/web-stories/v1/users/me/',\n\t\t\t\t'fonts'          => trailingslashit( $this->font_post_type->get_rest_url() ),\n\t\t\t\t'users'          => '/web-stories/v1/users/',\n\t\t\t\t'settings'       => '/web-stories/v1/settings/',\n\t\t\t\t'pages'          => '/wp/v2/pages/',\n\t\t\t\t'publisherLogos' => '/web-stories/v1/publisher-logos/',\n\t\t\t\t'taxonomies'     => '/web-stories/v1/taxonomies/',\n\t\t\t\t'products'       => '/web-stories/v1/products/',\n\t\t\t],\n\t\t\t'vendors'                 => $vendors,\n\t\t\t'maxUpload'               => $max_upload_size,\n\t\t\t'maxUploadFormatted'      => size_format( $max_upload_size ),\n\t\t\t'editPostsCapabilityName' => $this->story_post_type->get_cap_name( 'edit_posts' ),\n\t\t\t'capabilities'            => [\n\t\t\t\t'canManageSettings' => current_user_can( 'manage_options' ),\n\t\t\t\t'canUploadFiles'    => current_user_can( 'upload_files' ),\n\t\t\t],\n\t\t\t'canViewDefaultTemplates' => true,\n\t\t\t'plugins'                 => [\n\t\t\t\t'siteKit'     => $this->site_kit->get_plugin_status(),\n\t\t\t\t'woocommerce' => $this->woocommerce->get_plugin_status(),\n\t\t\t\t'web-stories' => [\n\t\t\t\t\t'needsUpdate' => $needs_update && ! $auto_updates_enabled,\n\t\t\t\t\t'updateLink'  => $can_update ? admin_url( 'plugins.php' ) : null,\n\t\t\t\t],\n\t\t\t],\n\t\t\t'flags'                   => array_merge(\n\t\t\t\t$this->experiments->get_experiment_statuses( 'general' ),\n\t\t\t\t$this->experiments->get_experiment_statuses( 'dashboard' ),\n\t\t\t),\n\t\t\t'globalAutoAdvance'       => (bool) $auto_advance,\n\t\t\t'globalPageDuration'      => (float) $page_duration,\n\t\t];\n\n\t\t/**\n\t\t * Filters settings passed to the web stories dashboard.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array $settings Array of settings passed to web stories dashboard.\n\t\t */\n\t\treturn apply_filters( 'web_stories_dashboard_settings', $settings );\n\t}\n\n\t/**\n\t * Displays a link to the Web Stories dashboard on the WordPress list table view.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function display_link_to_dashboard(): void {\n\t\tif ( ! $this->context->is_story_editor() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( 'edit' !== $this->context->get_screen_base() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$dashboard_url = add_query_arg(\n\t\t\t[\n\t\t\t\t'post_type' => $this->story_post_type->get_slug(),\n\t\t\t\t'page'      => 'stories-dashboard',\n\t\t\t],\n\t\t\tadmin_url( 'edit.php' )\n\t\t)\n\t\t?>\n\t\t<div style=\"margin-top: 20px;\">\n\t\t\t<a href=\"<?php echo esc_url( $dashboard_url ); ?>\">\n\t\t\t\t<?php esc_html_e( '&larr; Return to Web Stories Dashboard', 'web-stories' ); ?>\n\t\t\t</a>\n\t\t</div>\n\t\t<?php\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Editor.php",
    "content": "<?php\n/**\n * Class Editor\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Decoder;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Locale;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Page_Template_Post_Type;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tracking;\nuse WP_Post;\n\n/**\n * Class Editor\n */\nclass Editor extends Service_Base implements HasRequirements {\n\n\t/**\n\t * Web Stories editor script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-editor';\n\n\t/**\n\t * AMP validator script handle.\n\t */\n\tpublic const AMP_VALIDATOR_SCRIPT_HANDLE = 'amp-validator';\n\n\t/**\n\t * The libheif script handle.\n\t */\n\tpublic const LIBHEIF_SCRIPT_HANDLE = 'web-stories-libheif';\n\n\t/**\n\t * Experiments instance.\n\t *\n\t * @var Experiments Experiments instance.\n\t */\n\tprivate Experiments $experiments;\n\n\t/**\n\t * Decoder instance.\n\t *\n\t * @var Decoder Decoder instance.\n\t */\n\tprivate Decoder $decoder;\n\n\t/**\n\t * Meta boxes instance.\n\t *\n\t * @var Meta_Boxes Meta_Boxes instance.\n\t */\n\tprivate Meta_Boxes $meta_boxes;\n\n\t/**\n\t * Locale instance.\n\t *\n\t * @var Locale Locale instance.\n\t */\n\tprivate Locale $locale;\n\n\t/**\n\t * Google_Fonts instance.\n\t *\n\t * @var Google_Fonts Google_Fonts instance.\n\t */\n\tprivate Google_Fonts $google_fonts;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Page_Template_Post_Type instance.\n\t *\n\t * @var Page_Template_Post_Type Page_Template_Post_Type instance.\n\t */\n\tprivate Page_Template_Post_Type $page_template_post_type;\n\n\t/**\n\t * Font_Post_Type instance.\n\t *\n\t * @var Font_Post_Type Font_Post_Type instance.\n\t */\n\tprivate Font_Post_Type $font_post_type;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Types instance.\n\t *\n\t * @var Types Types instance.\n\t */\n\tprivate Types $types;\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Dashboard constructor.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveParameterList\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Experiments             $experiments             Experiments instance.\n\t * @param Meta_Boxes              $meta_boxes              Meta_Boxes instance.\n\t * @param Decoder                 $decoder                 Decoder instance.\n\t * @param Locale                  $locale                  Locale instance.\n\t * @param Google_Fonts            $google_fonts            Google_Fonts instance.\n\t * @param Assets                  $assets                  Assets instance.\n\t * @param Story_Post_Type         $story_post_type         Story_Post_Type instance.\n\t * @param Page_Template_Post_Type $page_template_post_type Page_Template_Post_Type instance.\n\t * @param Font_Post_Type          $font_post_type          Font_Post_Type instance.\n\t * @param Context                 $context                 Context instance.\n\t * @param Types                   $types                   Types instance.\n\t * @param Settings                $settings                Settings instance.\n\t */\n\tpublic function __construct(\n\t\tExperiments $experiments,\n\t\tMeta_Boxes $meta_boxes,\n\t\tDecoder $decoder,\n\t\tLocale $locale,\n\t\tGoogle_Fonts $google_fonts,\n\t\tAssets $assets,\n\t\tStory_Post_Type $story_post_type,\n\t\tPage_Template_Post_Type $page_template_post_type,\n\t\tFont_Post_Type $font_post_type,\n\t\tContext $context,\n\t\tTypes $types,\n\t\tSettings $settings\n\t) {\n\t\t$this->experiments             = $experiments;\n\t\t$this->meta_boxes              = $meta_boxes;\n\t\t$this->decoder                 = $decoder;\n\t\t$this->locale                  = $locale;\n\t\t$this->google_fonts            = $google_fonts;\n\t\t$this->assets                  = $assets;\n\t\t$this->story_post_type         = $story_post_type;\n\t\t$this->page_template_post_type = $page_template_post_type;\n\t\t$this->font_post_type          = $font_post_type;\n\t\t$this->context                 = $context;\n\t\t$this->types                   = $types;\n\t\t$this->settings                = $settings;\n\t}\n\n\t/**\n\t * Initializes the Editor logic.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );\n\t\tadd_filter( 'replace_editor', [ $this, 'replace_editor' ], 10, 2 );\n\t\tadd_filter( 'use_block_editor_for_post_type', [ $this, 'filter_use_block_editor_for_post_type' ], 10, 2 );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story and page template post types need to be registered first.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'page_template_post_type', 'story_post_type' ];\n\t}\n\n\t/**\n\t * Replace default post editor with our own implementation.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param bool|mixed $replace Bool if to replace editor or not.\n\t * @param WP_Post    $post    Current post object.\n\t * @return bool|mixed Whether the editor has been replaced.\n\t */\n\tpublic function replace_editor( $replace, WP_Post $post ) {\n\t\tif ( $this->story_post_type->get_slug() === get_post_type( $post ) ) {\n\n\t\t\t$script_dependencies = [\n\t\t\t\tTracking::SCRIPT_HANDLE,\n\t\t\t\t'postbox',\n\t\t\t\tself::AMP_VALIDATOR_SCRIPT_HANDLE,\n\t\t\t\tself::LIBHEIF_SCRIPT_HANDLE,\n\t\t\t];\n\n\t\t\t// Registering here because the script handle is required for wp_add_inline_script in edit-story.php.\n\t\t\t$this->assets->register_script_asset( self::SCRIPT_HANDLE, $script_dependencies, false );\n\n\t\t\t// Since the 'replace_editor' filter can be run multiple times, only load the\n\t\t\t// custom editor after the 'current_screen' action and when we can be certain the\n\t\t\t// $post_type, $post_type_object, $post globals are all set by WordPress.\n\t\t\tif ( isset( $GLOBALS['post'] ) && $post === $GLOBALS['post'] && did_action( 'current_screen' ) ) {\n\t\t\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/admin/edit-story.php';\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn $replace;\n\t}\n\n\t/**\n\t * Filters whether post type supports the block editor.\n\t *\n\t * Disables the block editor and associated logic (like enqueueing assets)\n\t * for the story post type.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param bool|mixed $use_block_editor Whether the post type can be edited or not. Default true.\n\t * @param mixed      $post_type        The post type being checked.\n\t * @return false|mixed Whether to use the block editor.\n\t */\n\tpublic function filter_use_block_editor_for_post_type( $use_block_editor, $post_type ) {\n\t\tif ( $this->story_post_type->get_slug() === $post_type ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $use_block_editor;\n\t}\n\n\t/**\n\t * Enqueue scripts for the element editor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $hook The current admin page.\n\t */\n\tpublic function admin_enqueue_scripts( string $hook ): void {\n\t\tif ( ! $this->context->is_story_editor() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Only output scripts and styles where in edit screens.\n\t\tif ( ! \\in_array( $hook, [ 'post.php', 'post-new.php' ], true ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Force media model to load.\n\t\twp_enqueue_media();\n\n\t\twp_enqueue_script(\n\t\t\tself::AMP_VALIDATOR_SCRIPT_HANDLE,\n\t\t\t'https://cdn.ampproject.org/v0/validator_wasm.js',\n\t\t\t[],\n\t\t\tWEBSTORIES_VERSION,\n\t\t\ttrue\n\t\t);\n\n\n\t\twp_enqueue_script(\n\t\t\tself::LIBHEIF_SCRIPT_HANDLE,\n\t\t\ttrailingslashit( WEBSTORIES_CDN_URL ) . 'js/libheif-js@1.17.1/libheif.js',\n\t\t\t[],\n\t\t\tWEBSTORIES_VERSION,\n\t\t\ttrue\n\t\t);\n\n\t\twp_enqueue_script( self::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_style_asset( self::SCRIPT_HANDLE, [ $this->google_fonts::SCRIPT_HANDLE ] );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStories',\n\t\t\t[\n\t\t\t\t'publicPath' => $this->assets->get_base_url( 'assets/js/' ), // Required before the editor script is enqueued.\n\t\t\t\t'localeData' => $this->assets->get_translations( self::SCRIPT_HANDLE ), // Required for i18n setLocaleData.\n\t\t\t]\n\t\t);\n\n\t\t// Dequeue forms.css, see https://github.com/googleforcreators/web-stories-wp/issues/349 .\n\t\t$this->assets->remove_admin_style( [ 'forms' ] );\n\t}\n\n\t/**\n\t * Get editor settings as an array.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string,mixed> Editor settings.\n\t */\n\tpublic function get_editor_settings(): array {\n\t\t$post                 = get_post();\n\t\t$story_id             = $post->ID ?? null;\n\t\t$general_settings_url = admin_url( 'options-general.php' );\n\n\t\tif ( $story_id ) {\n\t\t\t$this->setup_lock( $story_id );\n\t\t}\n\n\t\t// Media settings.\n\t\t$max_upload_size = wp_max_upload_size();\n\t\tif ( ! $max_upload_size ) {\n\t\t\t$max_upload_size = 0;\n\t\t}\n\n\t\t$dashboard_url = add_query_arg(\n\t\t\t[\n\t\t\t\t'post_type' => $this->story_post_type->get_slug(),\n\t\t\t\t'page'      => 'stories-dashboard',\n\t\t\t],\n\t\t\tadmin_url( 'edit.php' )\n\t\t);\n\n\t\t$revision_url = admin_url( 'revision.php' );\n\n\t\t$dashboard_settings_url = add_query_arg(\n\t\t\t[\n\t\t\t\t'post_type' => $this->story_post_type->get_slug(),\n\t\t\t\t'page'      => 'stories-dashboard#/editor-settings',\n\t\t\t],\n\t\t\tadmin_url( 'edit.php' )\n\t\t);\n\n\t\t$user = wp_get_current_user();\n\n\t\t/** This filter is documented in wp-admin/includes/post.php */\n\t\t$show_locked_dialog = apply_filters( 'show_post_locked_dialog', true, $post, $user );\n\t\t$nonce              = wp_create_nonce( 'wp_rest' );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t// Explicitly setting these flags which became the default in PHP 8.1.\n\t\t// Needed for correct single quotes in the editor & output.\n\t\t// See https://github.com/GoogleForCreators/web-stories-wp/issues/10809.\n\t\t$publisher_name = html_entity_decode( $story->get_publisher_name(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );\n\n\t\t$shopping_provider = $this->settings->get_setting( $this->settings::SETTING_NAME_SHOPPING_PROVIDER );\n\n\t\t$auto_advance = $this->settings->get_setting( $this->settings::SETTING_NAME_AUTO_ADVANCE );\n\n\t\t$page_duration = $this->settings->get_setting( $this->settings::SETTING_NAME_DEFAULT_PAGE_DURATION );\n\n\t\t$auto_save_link = '';\n\n\t\tif ( isset( $story_id ) ) {\n\n\t\t\t$auto_save = wp_get_post_autosave( $story_id );\n\n\t\t\tif ( $auto_save && $post ) {\n\t\t\t\tif ( mysql2date( 'U', $auto_save->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) {\n\t\t\t\t\t$auto_save_link = get_edit_post_link( $auto_save->ID );\n\t\t\t\t} else {\n\t\t\t\t\twp_delete_post_revision( $auto_save->ID );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/**\n\t\t * Revision.\n\t\t *\n\t\t * @var string|int $revision\n\t\t */\n\t\t$revision = $_GET['revision'] ?? 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\t\t$revision = absint( $revision );\n\n\t\t$revision_message = ! empty( $revision ) ?\n\t\t\t\\sprintf(\n\t\t\t\t/* translators: %s: Date and time of the revision. */\n\t\t\t\t__( 'Story restored to revision from %s.', 'web-stories' ),\n\t\t\t\twp_post_revision_title( $revision, false )\n\t\t\t)\n\t\t\t: false;\n\n\t\t$settings = [\n\t\t\t'autoSaveInterval'        => \\defined( 'AUTOSAVE_INTERVAL' ) ? AUTOSAVE_INTERVAL : null,\n\t\t\t'localAutoSaveInterval'   => 15,\n\t\t\t'autoSaveLink'            => $auto_save_link,\n\t\t\t'isRTL'                   => is_rtl(),\n\t\t\t'locale'                  => $this->locale->get_locale_settings(),\n\t\t\t'allowedMimeTypes'        => $this->types->get_allowed_mime_types(),\n\t\t\t'postType'                => $this->story_post_type->get_slug(),\n\t\t\t'storyId'                 => $story_id,\n\t\t\t'dashboardLink'           => $dashboard_url,\n\t\t\t'revisionLink'            => $revision_url,\n\t\t\t'revisionMessage'         => $revision_message,\n\t\t\t'dashboardSettingsLink'   => $dashboard_settings_url,\n\t\t\t'generalSettingsLink'     => $general_settings_url,\n\t\t\t'cdnURL'                  => trailingslashit( WEBSTORIES_CDN_URL ),\n\t\t\t'maxUpload'               => $max_upload_size,\n\t\t\t'editPostsCapabilityName' => $this->story_post_type->get_cap_name( 'edit_posts' ),\n\t\t\t'capabilities'            => [\n\t\t\t\t'hasUploadMediaAction' => current_user_can( 'upload_files' ),\n\t\t\t\t'canManageSettings'    => current_user_can( 'manage_options' ),\n\t\t\t],\n\t\t\t'api'                     => [\n\t\t\t\t'users'          => '/web-stories/v1/users/',\n\t\t\t\t'currentUser'    => '/web-stories/v1/users/me/',\n\t\t\t\t'stories'        => trailingslashit( $this->story_post_type->get_rest_url() ),\n\t\t\t\t'pageTemplates'  => trailingslashit( $this->page_template_post_type->get_rest_url() ),\n\t\t\t\t'media'          => '/web-stories/v1/media/',\n\t\t\t\t'hotlink'        => '/web-stories/v1/hotlink/validate/',\n\t\t\t\t'publisherLogos' => '/web-stories/v1/publisher-logos/',\n\t\t\t\t'products'       => '/web-stories/v1/products/',\n\t\t\t\t'proxy'          => rest_url( '/web-stories/v1/hotlink/proxy/' ),\n\t\t\t\t'link'           => '/web-stories/v1/link/',\n\t\t\t\t'statusCheck'    => '/web-stories/v1/status-check/',\n\t\t\t\t'taxonomies'     => '/web-stories/v1/taxonomies/',\n\t\t\t\t'fonts'          => trailingslashit( $this->font_post_type->get_rest_url() ),\n\t\t\t\t'metaBoxes'      => $this->meta_boxes->get_meta_box_url( (int) $story_id ),\n\t\t\t\t'storyLocking'   => rest_url( \\sprintf( '%s/%s/lock/', $this->story_post_type->get_rest_url(), $story_id ) ),\n\t\t\t],\n\t\t\t'metadata'                => [\n\t\t\t\t'publisher' => $publisher_name,\n\t\t\t],\n\t\t\t'postLock'                => [\n\t\t\t\t'interval'         => 60,\n\t\t\t\t'showLockedDialog' => $show_locked_dialog,\n\t\t\t],\n\t\t\t'canViewDefaultTemplates' => true,\n\t\t\t'version'                 => WEBSTORIES_VERSION,\n\t\t\t'nonce'                   => $nonce,\n\t\t\t'showMedia3p'             => true,\n\t\t\t'globalAutoAdvance'       => (bool) $auto_advance,\n\t\t\t'globalPageDuration'      => (float) $page_duration,\n\t\t\t'shoppingProvider'        => $shopping_provider,\n\t\t\t'encodeMarkup'            => $this->decoder->supports_decoding(),\n\t\t\t'metaBoxes'               => $this->meta_boxes->get_meta_boxes_per_location(),\n\t\t\t'ffmpegCoreUrl'           => trailingslashit( WEBSTORIES_CDN_URL ) . 'js/@ffmpeg/core@0.11.0/dist/ffmpeg-core.js',\n\t\t\t'mediainfoUrl'            => trailingslashit( WEBSTORIES_CDN_URL ) . 'js/mediainfo.js@0.1.9/dist/MediaInfoModule.wasm',\n\t\t\t'flags'                   => array_merge(\n\t\t\t\t$this->experiments->get_experiment_statuses( 'general' ),\n\t\t\t\t$this->experiments->get_experiment_statuses( 'editor' ),\n\t\t\t),\n\t\t];\n\n\t\t/**\n\t\t * Filters settings passed to the web stories editor.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array $settings Array of settings passed to web stories editor.\n\t\t */\n\t\treturn apply_filters( 'web_stories_editor_settings', $settings );\n\t}\n\n\t/**\n\t * Setup up post lock.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param int $story_id Post id of story.\n\t */\n\tprotected function setup_lock( int $story_id ): void {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure these functions are loaded.\n\t\tif (\n\t\t\t! \\function_exists( '\\wp_check_post_lock' ) ||\n\t\t\t! \\function_exists( '\\wp_set_post_lock' )\n\t\t) {\n\t\t\trequire_once ABSPATH . 'wp-admin/includes/post.php';\n\t\t}\n\n\t\t// Check current lock.\n\t\t$lock_user_id = wp_check_post_lock( $story_id );\n\t\tif ( ! $lock_user_id ) {\n\t\t\t// If no lock set, create new lock.\n\t\t\twp_set_post_lock( $story_id );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Google_Fonts.php",
    "content": "<?php\n/**\n * Class Google_Fonts.\n *\n * Registers Google fonts for admin screens.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse WP_Styles;\n\n/**\n * Class Google_Fonts\n *\n * Enqueue Google Fonts stylesheet.\n */\nclass Google_Fonts implements Conditional, Service, Registerable {\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-fonts';\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\treturn is_admin() && ! wp_doing_ajax();\n\t}\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.8.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'wp_default_styles', [ $this, 'register_style' ] );\n\t}\n\n\t/**\n\t * Registers the google font style.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param WP_Styles $wp_styles WP_Styles instance.\n\t */\n\tpublic function register_style( WP_Styles $wp_styles ): void {\n\t\t// so we need to avoid specifying a version at all.\n\t\t$wp_styles->add(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'https://fonts.googleapis.com/css?family=Google+Sans|Google+Sans:b|Google+Sans:500&display=swap',\n\t\t\t[],\n\t\t\tWEBSTORIES_VERSION\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Meta_Boxes.php",
    "content": "<?php\n/**\n * Class Meta_Boxes.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Meta_Boxes.\n */\nclass Meta_Boxes extends Service_Base {\n\t/**\n\t * Supported meta box locations.\n\t */\n\tpublic const LOCATIONS = [ 'normal', 'advanced', 'side' ];\n\n\t/**\n\t * Meta box priorities.\n\t */\n\tpublic const PRIORITIES = [ 'high', 'sorted', 'core', 'default', 'low' ];\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'add_meta_boxes_' . Story_Post_Type::POST_TYPE_SLUG, [ $this, 'remove_meta_boxes' ], PHP_INT_MAX );\n\t}\n\n\t/**\n\t * Removes all meta boxes with '__back_compat_meta_box' set to 'true'.\n\t *\n\t * This removes things like the post author meta box, as this feature is\n\t * already included in the editor.\n\t *\n\t * Mimics what do_meta_boxes() does for the block editor.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see do_meta_boxes()\n\t */\n\tpublic function remove_meta_boxes(): void {\n\t\tglobal $wp_meta_boxes;\n\n\t\t$screen = get_current_screen();\n\n\t\tif ( ! $screen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ( self::LOCATIONS as $context ) {\n\t\t\tif ( ! isset( $wp_meta_boxes[ $screen->id ][ $context ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tforeach ( self::PRIORITIES as $priority ) {\n\t\t\t\tif ( ! isset( $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tforeach ( (array) $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] as $meta_box ) {\n\t\t\t\t\tif ( false === $meta_box || ! $meta_box['title'] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t// We don't currently support the 'Custom Fields' meta box.\n\t\t\t\t\t\t'postcustom' === $meta_box['id'] ||\n\t\t\t\t\t\t( \\is_array( $meta_box['args'] ) && ! empty( $meta_box['args']['__back_compat_meta_box'] ) )\n\t\t\t\t\t) {\n\t\t\t\t\t\tremove_meta_box( $meta_box['id'], $screen, $context );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the admin URL for handling meta boxes.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param int $story_id Story ID.\n\t * @return string Meta box URL.\n\t */\n\tpublic function get_meta_box_url( int $story_id ): string {\n\t\t$meta_box_url = admin_url( 'post.php' );\n\t\t$meta_box_url = add_query_arg(\n\t\t\t[\n\t\t\t\t'post'                  => $story_id,\n\t\t\t\t'action'                => 'edit',\n\t\t\t\t'meta-box-loader'       => true,\n\t\t\t\t'meta-box-loader-nonce' => wp_create_nonce( 'meta-box-loader' ),\n\t\t\t],\n\t\t\t$meta_box_url\n\t\t);\n\n\t\treturn $meta_box_url;\n\t}\n\n\t/**\n\t * Returns list of custom meta boxes per location.\n\t *\n\t * Used to disable empty meta boxes in the editor.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see the_block_editor_meta_boxes()\n\t *\n\t * @return array<string, array<int, array{id: string, title: string}>> List of meta boxes per location.\n\t */\n\tpublic function get_meta_boxes_per_location(): array {\n\t\tglobal $wp_meta_boxes;\n\n\t\t$screen = get_current_screen();\n\n\t\tif ( ! $screen ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t$_wp_meta_boxes = $wp_meta_boxes ?? [];\n\n\t\t/**\n\t\t * Filters meta box data before making it available to the editor.\n\t\t *\n\t\t * This allows for the modifications of meta boxes that are already\n\t\t * present by this point. Do not use as a means of adding meta box data.\n\t\t *\n\t\t * @since 1.3.0\n\t\t *\n\t\t * @param array $wp_meta_boxes Global meta box state.\n\t\t */\n\t\t$_wp_meta_boxes = apply_filters( 'web_stories_editor_meta_boxes', $_wp_meta_boxes );\n\n\t\t$meta_boxes_per_location = [];\n\t\tforeach ( self::LOCATIONS as $context ) {\n\t\t\t$meta_boxes_per_location[ $context ] = [];\n\n\t\t\tif ( ! isset( $_wp_meta_boxes[ $screen->id ][ $context ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tforeach ( self::PRIORITIES as $priority ) {\n\t\t\t\tif ( ! isset( $_wp_meta_boxes[ $screen->id ][ $context ][ $priority ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$meta_boxes = (array) $_wp_meta_boxes[ $screen->id ][ $context ][ $priority ];\n\t\t\t\tforeach ( $meta_boxes as $meta_box ) {\n\t\t\t\t\tif ( false === $meta_box || ! $meta_box['title'] ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$meta_boxes_per_location[ $context ][] = [\n\t\t\t\t\t\t'id'    => $meta_box['id'],\n\t\t\t\t\t\t'title' => $meta_box['title'],\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $meta_boxes_per_location;\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/PluginActionLinks.php",
    "content": "<?php\n/**\n * PluginActionLinks class.\n *\n * Updates the plugin action links for the plugin.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Updates the plugin action links for the plugin.\n */\nclass PluginActionLinks extends Service_Base {\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.6.0\n\t */\n\tpublic function register(): void {\n\t\t$basename = plugin_basename( WEBSTORIES_PLUGIN_FILE );\n\t\tadd_filter( 'plugin_action_links_' . $basename, [ $this, 'action_links' ] );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'admin_init';\n\t}\n\n\t/**\n\t * Add action link to plugin settings page.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param  array|mixed $links Plugin action links.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($links is array<T> ? array<T> : mixed)\n\t */\n\tpublic function action_links( $links ) {\n\t\tif ( ! \\is_array( $links ) ) {\n\t\t\treturn $links;\n\t\t}\n\t\t$slug    = \\sprintf( 'edit.php?post_type=%s&page=stories-dashboard#/editor-settings', Story_Post_Type::POST_TYPE_SLUG );\n\t\t$url     = get_admin_url( null, $slug );\n\t\t$links[] = \\sprintf(\n\t\t\t'<a href=\"%s\">%s</a>',\n\t\t\tesc_url( $url ),\n\t\t\tesc_html__( 'Settings', 'web-stories' )\n\t\t);\n\n\t\treturn $links;\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/PluginRowMeta.php",
    "content": "<?php\n/**\n * PluginRowMeta class.\n *\n * Updates the plugin row meta for the plugin.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Updates the plugin row meta for the plugin.\n */\nclass PluginRowMeta extends Service_Base {\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.6.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'plugin_row_meta', [ $this, 'get_plugin_row_meta' ], 10, 2 );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'admin_init';\n\t}\n\n\t/**\n\t * Updates the plugin row meta with links to review plugin and get support.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string[]|mixed $meta        An array of the plugin's metadata, including the version, author, author URI,\n\t *                              and plugin URI.\n\t * @param string         $plugin_file Path to the plugin file relative to the plugins directory.\n\t * @return string[]|mixed Plugin row meta.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($meta is array<T> ? array<T> : mixed)\n\t */\n\tpublic function get_plugin_row_meta( $meta, string $plugin_file ) {\n\t\tif ( plugin_basename( WEBSTORIES_PLUGIN_FILE ) !== $plugin_file ) {\n\t\t\treturn $meta;\n\t\t}\n\t\tif ( ! \\is_array( $meta ) ) {\n\t\t\treturn $meta;\n\t\t}\n\t\t$additional_meta = [\n\t\t\t'<a href=\"https://wordpress.org/support/plugin/web-stories/\" target=\"_blank\" rel=\"noreferrer\">' . esc_html__( 'Contact support', 'web-stories' ) . '</a>',\n\t\t\t'<a href=\"https://wordpress.org/support/plugin/web-stories/reviews/#new-post\" target=\"_blank\" rel=\"noreferrer\">' . esc_html__( 'Leave review', 'web-stories' ) . '</a>',\n\t\t];\n\n\t\treturn [ ...$meta, ...$additional_meta ];\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/Site_Health.php",
    "content": "<?php\n/**\n * Site Health Class.\n *\n * Adds tests and debugging information for Site Health.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Site_Health\n */\nclass Site_Health extends Service_Base implements Conditional {\n\t/**\n\t * Experiments instance.\n\t *\n\t * @var Experiments Experiments instance.\n\t */\n\tprivate Experiments $experiments;\n\n\t/**\n\t * Site_Health constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Experiments $experiments Experiments instance.\n\t * @return void\n\t */\n\tpublic function __construct( Experiments $experiments ) {\n\t\t$this->experiments = $experiments;\n\t}\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\treturn is_admin() && ! wp_doing_ajax();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'wp_loaded';\n\t}\n\n\t/**\n\t * Adds the filters.\n\t *\n\t * @since 1.8.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'debug_information', [ $this, 'add_debug_information' ] );\n\t\tadd_filter( 'site_status_test_php_modules', [ $this, 'add_extensions' ] );\n\t\tadd_filter( 'site_status_test_result', [ $this, 'modify_test_result' ] );\n\t}\n\n\t/**\n\t * Adds debug information for Web stories.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param array|mixed $debugging_information The debugging information from Core.\n\t * @return array|mixed The debugging information, with added information for Web stories.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($debugging_information is array<T> ? array<T> : mixed)\n\t */\n\tpublic function add_debug_information( $debugging_information ) {\n\t\t$enabled_experiments = [];\n\t\tforeach ( $this->experiments->get_experiments() as $experiment ) {\n\t\t\t$enabled = $this->experiments->is_experiment_enabled( $experiment['name'] );\n\t\t\tif ( $enabled ) {\n\t\t\t\t$enabled_experiments[ $experiment['label'] ] = $this->get_formatted_output( $enabled );\n\t\t\t}\n\t\t}\n\t\tif ( ! $enabled_experiments ) {\n\t\t\t$enabled_experiments = __( 'No experiments enabled', 'web-stories' );\n\t\t}\n\t\tif ( ! \\is_array( $debugging_information ) ) {\n\t\t\treturn $debugging_information;\n\t\t}\n\t\t$extra_data = [\n\t\t\t'web_stories' => [\n\t\t\t\t'label'       => esc_html__( 'Web Stories', 'web-stories' ),\n\t\t\t\t'description' => esc_html__( 'Debugging information for the Web Stories plugin.', 'web-stories' ),\n\t\t\t\t'fields'      => [\n\t\t\t\t\t'web_stories_version'             => [\n\t\t\t\t\t\t'label'   => 'WEBSTORIES_VERSION',\n\t\t\t\t\t\t'value'   => WEBSTORIES_VERSION,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_db_version'          => [\n\t\t\t\t\t\t'label'   => 'WEBSTORIES_DB_VERSION',\n\t\t\t\t\t\t'value'   => WEBSTORIES_DB_VERSION,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_amp_version'         => [\n\t\t\t\t\t\t'label'   => 'WEBSTORIES_AMP_VERSION',\n\t\t\t\t\t\t'value'   => WEBSTORIES_AMP_VERSION,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_cdn_url'             => [\n\t\t\t\t\t\t'label'   => 'WEBSTORIES_CDN_URL',\n\t\t\t\t\t\t'value'   => WEBSTORIES_CDN_URL,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_dev_mode'            => [\n\t\t\t\t\t\t'label'   => 'WEBSTORIES_DEV_MODE',\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t\t'value'   => $this->get_formatted_output( WEBSTORIES_DEV_MODE ),\n\t\t\t\t\t\t'debug'   => WEBSTORIES_DEV_MODE,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_theme_support'       => [\n\t\t\t\t\t\t'label'   => 'Theme supports',\n\t\t\t\t\t\t'value'   => $this->get_formatted_output( current_theme_supports( 'web-stories' ) ),\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_enabled_experiments' => [\n\t\t\t\t\t\t'label'   => 'Experiments',\n\t\t\t\t\t\t'value'   => $enabled_experiments,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'web_stories_libxml_version'      => [\n\t\t\t\t\t\t'label'   => 'libxml Version',\n\t\t\t\t\t\t'value'   => LIBXML_DOTTED_VERSION,\n\t\t\t\t\t\t'private' => false,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\treturn array_merge( $debugging_information, $extra_data );\n\t}\n\n\t/**\n\t * Adds suggested PHP extensions to those that Core depends on.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param array|mixed $core_extensions The existing extensions from Core.\n\t * @return array|mixed The extensions, including those for Web Stories.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($core_extensions is array<T> ? array<T> : mixed)\n\t */\n\tpublic function add_extensions( $core_extensions ) {\n\t\tif ( ! \\is_array( $core_extensions ) ) {\n\t\t\treturn $core_extensions;\n\t\t}\n\t\t$extensions = [\n\t\t\t'json'     => [\n\t\t\t\t'extension' => 'json',\n\t\t\t\t'function'  => 'json_encode',\n\t\t\t\t'required'  => false,\n\t\t\t],\n\t\t\t'libxml'   => [\n\t\t\t\t'extension' => 'libxml',\n\t\t\t\t'function'  => 'libxml_use_internal_errors',\n\t\t\t\t'required'  => false,\n\n\t\t\t],\n\t\t\t'date'     => [\n\t\t\t\t'extension' => 'date',\n\t\t\t\t'class'     => 'DateTimeImmutable',\n\t\t\t\t'required'  => false,\n\t\t\t],\n\t\t\t'dom'      => [\n\t\t\t\t'extension' => 'dom',\n\t\t\t\t'class'     => 'DOMNode',\n\t\t\t\t'required'  => false,\n\t\t\t],\n\t\t\t'mbstring' => [\n\t\t\t\t'extension' => 'mbstring',\n\t\t\t\t'required'  => false,\n\t\t\t],\n\t\t\t'spl'      => [\n\t\t\t\t'function' => 'spl_autoload_register',\n\t\t\t\t'required' => false,\n\t\t\t],\n\t\t];\n\n\t\treturn array_merge( $core_extensions, $extensions );\n\t}\n\n\t/**\n\t * Modify test results.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param array|mixed $test_result Site Health test result.\n\t * @return array|mixed Modified test result.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($test_result is array<T> ? array<T> : mixed)\n\t */\n\tpublic function modify_test_result( $test_result ) {\n\t\tif ( ! \\is_array( $test_result ) ) {\n\t\t\treturn $test_result;\n\t\t}\n\t\t// Set the `https_status` test status to critical if its current status is recommended, along with adding to the\n\t\t// description for why its required for Web Stories.\n\t\tif ( isset( $test_result['test'], $test_result['status'], $test_result['description'] ) && 'https_status' === $test_result['test'] && 'recommended' === $test_result['status'] ) {\n\t\t\t$test_result['status'] = 'critical';\n\t\t\t// @phpstan-ignore assignOp.invalid (False positive.)\n\t\t\t$test_result['description'] .= '<p>' . __( 'Additionally, Web Stories requires HTTPS for most components to work properly, including iframes and videos.', 'web-stories' ) . '</p>';\n\t\t}\n\n\t\treturn $test_result;\n\t}\n\n\t/**\n\t * Format the value as enabled or disabled.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param mixed $value Value to formatted.\n\t */\n\tprotected function get_formatted_output( $value ): string {\n\t\treturn $value ? __( 'Enabled', 'web-stories' ) : __( 'Disabled', 'web-stories' );\n\t}\n}\n"
  },
  {
    "path": "includes/Admin/TinyMCE.php",
    "content": "<?php\n/**\n * TinyMCE Class.\n *\n * Necessary operations for classic editor compatibility.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Admin;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Stories_Script_Data;\n\n/**\n * Class TinyMCE\n */\nclass TinyMCE extends Service_Base {\n\t/**\n\t * Web Stories tinymce script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-tinymce-button';\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Stories_Script_Data instance.\n\t *\n\t * @var Stories_Script_Data Stories_Script_Data instance.\n\t */\n\tprotected Stories_Script_Data $stories_script_data;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Tinymce constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Assets              $assets              Assets instance.\n\t * @param Stories_Script_Data $stories_script_data Stories_Script_Data instance.\n\t * @param Context             $context             Context instance.\n\t */\n\tpublic function __construct( Assets $assets, Stories_Script_Data $stories_script_data, Context $context ) {\n\t\t$this->assets              = $assets;\n\t\t$this->stories_script_data = $stories_script_data;\n\t\t$this->context             = $context;\n\t}\n\n\t/**\n\t * Initialization actions.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register(): void {\n\t\tif ( $this->context->is_block_editor() || $this->context->is_story_editor() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->register_assets();\n\n\t\tadd_action( 'wp_enqueue_editor', [ $this, 'enqueue_assets' ] );\n\t\tadd_filter( 'mce_buttons', [ $this, 'tinymce_web_stories_button' ] );\n\t\tadd_filter( 'mce_external_plugins', [ $this, 'web_stories_mce_plugin' ] );\n\t\tadd_action( 'admin_footer', [ $this, 'web_stories_tinymce_root_element' ] );\n\t\tadd_filter( 'script_loader_tag', [ $this, 'script_loader_tag' ], 10, 3 );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'admin_enqueue_scripts';\n\t}\n\n\t/**\n\t * Add web stories button in TinyMCE editor.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array|mixed $buttons Array of TinyMCE buttons.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($buttons is array<T> ? array<T> : mixed)\n\t */\n\tpublic function tinymce_web_stories_button( $buttons ) {\n\t\tif ( ! \\is_array( $buttons ) ) {\n\t\t\treturn $buttons;\n\t\t}\n\t\t$buttons[] = 'web_stories';\n\n\t\treturn $buttons;\n\t}\n\n\t/**\n\t * Register web stories plugin for tinycemce editor.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array|mixed $plugins Array of TinyMCE plugin scripts.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($plugins is array<T> ? array<T> : mixed)\n\t */\n\tpublic function web_stories_mce_plugin( $plugins ) {\n\t\tif ( ! \\is_array( $plugins ) ) {\n\t\t\treturn $plugins;\n\t\t}\n\t\t$plugins['web_stories'] = $this->assets->get_base_url( \\sprintf( 'assets/js/%s.js', self::SCRIPT_HANDLE ) );\n\n\t\treturn $plugins;\n\t}\n\n\t/**\n\t * Enqueue related scripts.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register_assets(): void {\n\t\t$this->assets->enqueue_style( 'wp-components' );\n\n\t\t$this->assets->enqueue_script_asset( self::SCRIPT_HANDLE );\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStoriesData',\n\t\t\t$this->stories_script_data->get_script_data()\n\t\t);\n\t}\n\n\t/**\n\t * Hijack the button's script to render an empty script tag.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string|mixed $tag    The `<script>` tag for the enqueued script.\n\t * @param string       $handle The script's registered handle.\n\t * @param string       $src    The script's source URL.\n\t * @return string|mixed The filtered script tag.\n\t */\n\tpublic function script_loader_tag( $tag, string $handle, string $src ) {\n\t\tif ( ! \\is_string( $tag ) ) {\n\t\t\treturn $tag;\n\t\t}\n\n\t\tif ( self::SCRIPT_HANDLE === $handle ) {\n\t\t\t$tag = str_replace( $src, '', $tag );\n\t\t\t// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript -- False positive.\n\t\t\t$tag = (string) preg_replace( '#<script src=\\'\\'(.*?)>(.*?)</script>#is', '', $tag );\n\t\t}\n\n\t\treturn $tag;\n\t}\n\n\t/**\n\t * Enqueue related scripts.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function enqueue_assets(): void {\n\t\t$this->assets->enqueue_style( 'wp-components' );\n\t\t$this->assets->enqueue_script_asset( self::SCRIPT_HANDLE );\n\t}\n\n\t/**\n\t * Root element for tinymce editor.\n\t * This is useful for performing some react operations.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function web_stories_tinymce_root_element(): void {\n\t\t?>\n\t\t<div id=\"web-stories-tinymce\"></div>\n\t\t<?php\n\t}\n}\n"
  },
  {
    "path": "includes/Analytics.php",
    "content": "<?php\n/**\n * Class Analytics\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\n/**\n * Class Analytics\n */\nclass Analytics extends Service_Base {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'web_stories_print_analytics', [ $this, 'print_analytics_tag' ] );\n\t}\n\n\t/**\n\t * Returns the  Google Analytics tracking ID.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return string Tracking ID.\n\t */\n\tpublic function get_tracking_id(): string {\n\t\t/**\n\t\t * Tracking ID.\n\t\t *\n\t\t * @var string $tracking_id\n\t\t */\n\t\t$tracking_id = $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_ID );\n\n\t\t// For some reasons, some sites use the plugin's own tracking ID (as used in the admin)\n\t\t// for their stories. Prevent accidental erroneous tracking in such a case.\n\t\tif ( Tracking::TRACKING_ID === $tracking_id ) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $tracking_id;\n\t}\n\n\t/**\n\t * Returns the default analytics configuration.\n\t *\n\t * Note: variables in single quotes will be substituted by <amp-analytics>.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @see https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-var-substitutions.md\n\t *\n\t * @param string $tracking_id Tracking ID.\n\t * @return array<string, array<string, mixed>> <amp-analytics> configuration.\n\t */\n\tpublic function get_default_configuration( string $tracking_id ): array {\n\t\t$config = [\n\t\t\t'vars'     => [\n\t\t\t\t'gtag_id' => $tracking_id,\n\t\t\t\t'config'  => [\n\t\t\t\t\t$tracking_id => [ 'groups' => 'default' ],\n\t\t\t\t],\n\t\t\t],\n\t\t\t'triggers' => [\n\t\t\t\t// Fired when a story page becomes visible.\n\t\t\t\t'storyProgress'       => [\n\t\t\t\t\t'on'      => 'story-page-visible',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_progress',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'event_label'    => '${storyPageIndex}',\n\t\t\t\t\t\t'event_value'    => '${storyProgress}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when the last page in the story is shown to the user.\n\t\t\t\t// This can be used to measure completion rate.\n\t\t\t\t'storyEnd'            => [\n\t\t\t\t\t'on'      => 'story-last-page-visible',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_complete',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'event_label'    => '${storyPageCount}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when clicking an element that opens a tooltip (<a> or <amp-twitter>).\n\t\t\t\t'trackFocusState'     => [\n\t\t\t\t\t'on'      => 'story-focus',\n\t\t\t\t\t'tagName' => 'a',\n\t\t\t\t\t'request' => 'click ',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_focus',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when clicking on a tooltip.\n\t\t\t\t'trackClickThrough'   => [\n\t\t\t\t\t'on'      => 'story-click-through',\n\t\t\t\t\t'tagName' => 'a',\n\t\t\t\t\t'request' => 'click ',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_click_through',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when opening a drawer or dialog inside a story (e.g. page attachment).\n\t\t\t\t'storyOpen'           => [\n\t\t\t\t\t'on'      => 'story-open',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_open',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when closing a drawer or dialog inside a story (e.g. page attachment).\n\t\t\t\t'storyClose'          => [\n\t\t\t\t\t'on'      => 'story-close',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_close',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when the user initiates an interaction to mute the audio for the current story.\n\t\t\t\t'audioMuted'          => [\n\t\t\t\t\t'on'      => 'story-audio-muted',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_audio_muted',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when the user initiates an interaction to unmute the audio for the current story.\n\t\t\t\t'audioUnmuted'        => [\n\t\t\t\t\t'on'      => 'story-audio-unmuted',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_audio_unmuted',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when a page attachment is opened by the user.\n\t\t\t\t'pageAttachmentEnter' => [\n\t\t\t\t\t'on'      => 'story-page-attachment-enter',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_page_attachment_enter',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// Fired when a page attachment is dismissed by the user.\n\t\t\t\t'pageAttachmentExit'  => [\n\t\t\t\t\t'on'      => 'story-page-attachment-exit',\n\t\t\t\t\t'request' => 'event',\n\t\t\t\t\t'vars'    => [\n\t\t\t\t\t\t'event_name'     => 'custom',\n\t\t\t\t\t\t'event_action'   => 'story_page_attachment_exit',\n\t\t\t\t\t\t'event_category' => '${title}',\n\t\t\t\t\t\t'send_to'        => $tracking_id,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filters the Web Stories Google Analytics configuration.\n\t\t *\n\t\t * Only used when not using <amp-story-auto-analytics>, which is the default.\n\t\t *\n\t\t * @param array $config Analytics configuration.\n\t\t */\n\t\treturn apply_filters( 'web_stories_analytics_configuration', $config );\n\t}\n\n\t/**\n\t * Prints the analytics tag for single stories.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function print_analytics_tag(): void {\n\t\t$tracking_id = $this->get_tracking_id();\n\n\t\tif ( ! $tracking_id ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( $this->settings->get_setting( $this->settings::SETTING_NAME_USING_LEGACY_ANALYTICS ) ) {\n\t\t\t$this->print_amp_analytics_tag( $tracking_id );\n\t\t} else {\n\t\t\t$this->print_amp_story_auto_analytics_tag( $tracking_id );\n\t\t}\n\t}\n\n\t/**\n\t * Prints the legacy <amp-analytics> tag for single stories.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param string $tracking_id Tracking ID.\n\t */\n\tprivate function print_amp_analytics_tag( string $tracking_id ): void {\n\t\t?>\n\t\t<amp-analytics type=\"gtag\" data-credentials=\"include\">\n\t\t\t<script type=\"application/json\">\n\t\t\t\t<?php echo wp_json_encode( $this->get_default_configuration( $tracking_id ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>\n\t\t\t</script>\n\t\t</amp-analytics>\n\t\t<?php\n\t}\n\n\t/**\n\t * Prints the <amp-story-auto-analytics> tag for single stories.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param string $tracking_id Tracking ID.\n\t */\n\tprivate function print_amp_story_auto_analytics_tag( string $tracking_id ): void {\n\t\t?>\n\t\t<amp-story-auto-analytics gtag-id=\"<?php echo esc_attr( $tracking_id ); ?>\"></amp-story-auto-analytics>\n\t\t<?php\n\t}\n}\n"
  },
  {
    "path": "includes/Assets.php",
    "content": "<?php\n/**\n * Class Assets\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\n/**\n * Class Assets\n *\n * @phpstan-type AssetMetadata array{\n *   version: string,\n *   dependencies: string[],\n *   js: string[],\n *   css: string[],\n *   chunks: string[],\n * }\n */\nclass Assets {\n\t/**\n\t * An array of registered styles.\n\t *\n\t * @var array<string, bool>\n\t */\n\tprotected array $register_styles = [];\n\n\t/**\n\t * An array of registered scripts.\n\t *\n\t * @var array<string, bool>\n\t */\n\tprotected array $register_scripts = [];\n\n\t/**\n\t * Get path to file and directory.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string $path Path.\n\t */\n\tpublic function get_base_path( string $path ): string {\n\t\treturn WEBSTORIES_PLUGIN_DIR_PATH . $path;\n\t}\n\n\t/**\n\t * Get url of file and directory.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string $path Path.\n\t */\n\tpublic function get_base_url( string $path ): string {\n\t\treturn WEBSTORIES_PLUGIN_DIR_URL . $path;\n\t}\n\n\t/**\n\t * Get asset metadata.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string $handle Script handle.\n\t * @return array Array containing combined contents of \"<$handle>.asset.php\" and \"<$handle>.chunks.php\".\n\t *\n\t * @phpstan-return AssetMetadata\n\t */\n\tpublic function get_asset_metadata( string $handle ): array {\n\t\t$base_path = $this->get_base_path( 'assets/js/' );\n\n\t\t// *.asset.php is generated by DependencyExtractionWebpackPlugin.\n\t\t// *.chunks.php is generated by HtmlWebpackPlugin with a custom template.\n\t\t$asset_file  = $base_path . $handle . '.asset.php';\n\t\t$chunks_file = $base_path . $handle . '.chunks.php';\n\n\t\t// phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable\n\t\t$asset = is_readable( $asset_file ) ? require $asset_file : [];\n\t\t// phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable\n\t\t$chunks = is_readable( $chunks_file ) ? require $chunks_file : [];\n\n\t\t// A hash calculated based on the file content of the entry point bundle at <$handle>.js.\n\t\t$asset['version'] ??= WEBSTORIES_VERSION;\n\n\t\t$asset['dependencies'] ??= [];\n\t\t$asset['js']             = $chunks['js'] ?? [];\n\t\t$asset['css']            = $chunks['css'] ?? [];\n\t\t$asset['chunks']         = $chunks['chunks'] ?? [];\n\n\t\treturn $asset;\n\t}\n\n\t/**\n\t * Register script using handle.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string   $script_handle Handle of script.\n\t * @param string[] $script_dependencies Array of extra dependencies.\n\t * @param bool     $with_i18n Optional. Whether to setup i18n for this asset. Default true.\n\t */\n\tpublic function register_script_asset( string $script_handle, array $script_dependencies = [], bool $with_i18n = true ): void {\n\t\tif ( isset( $this->register_scripts[ $script_handle ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$base_script_path = $this->get_base_url( 'assets/js/' );\n\t\t$in_footer        = true;\n\n\t\t$asset         = $this->get_asset_metadata( $script_handle );\n\t\t$entry_version = $asset['version'];\n\t\t// Register any chunks of $script_handle first.\n\t\t// `$asset['js']` are preloaded chunks, `$asset['chunks']` dynamically imported ones.\n\t\tforeach ( $asset['js'] as $chunk ) {\n\t\t\t$this->register_script(\n\t\t\t\t$chunk,\n\t\t\t\t$base_script_path . $chunk . '.js',\n\t\t\t\t[],\n\t\t\t\t$entry_version,\n\t\t\t\t$in_footer,\n\t\t\t\t$with_i18n\n\t\t\t);\n\t\t}\n\n\t\t// Dynamically imported chunks MUST NOT be added as dependencies here.\n\t\t$dependencies = [ ...$asset['dependencies'], ...$script_dependencies, ...$asset['js'] ];\n\n\t\t$this->register_script(\n\t\t\t$script_handle,\n\t\t\t$base_script_path . $script_handle . '.js',\n\t\t\t$dependencies,\n\t\t\t$entry_version,\n\t\t\t$in_footer,\n\t\t\t$with_i18n\n\t\t);\n\n\t\t// \"Save\" all the script's chunks so we can later manually fetch them and their translations if needed.\n\t\twp_script_add_data( $script_handle, 'chunks', $asset['chunks'] );\n\n\t\t// Register every dynamically imported chunk as a script, just so\n\t\t// that we can print their translations whenever the main script is enqueued.\n\t\t// The actual enqueueing of these chunks is done by the main script via dynamic imports.\n\t\tforeach ( $asset['chunks'] as $dynamic_chunk ) {\n\t\t\t$this->register_script(\n\t\t\t\t$dynamic_chunk,\n\t\t\t\t$base_script_path . $dynamic_chunk . '.js',\n\t\t\t\t[],\n\t\t\t\t$entry_version, // Not actually used / relevant, since enqueueing is done by webpack.\n\t\t\t\t$in_footer, // Ditto.\n\t\t\t\t$with_i18n\n\t\t\t);\n\n\t\t\tif ( $with_i18n ) {\n\t\t\t\twp_add_inline_script( $script_handle, (string) wp_scripts()->print_translations( $dynamic_chunk, false ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Enqueue script using handle.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string   $script_handle Handle of script.\n\t * @param string[] $script_dependencies Array of extra dependencies.\n\t * @param bool     $with_i18n Optional. Whether to setup i18n for this asset. Default true.\n\t */\n\tpublic function enqueue_script_asset( string $script_handle, array $script_dependencies = [], bool $with_i18n = true ): void {\n\t\t$this->register_script_asset( $script_handle, $script_dependencies, $with_i18n );\n\t\t$this->enqueue_script( $script_handle );\n\t}\n\n\t/**\n\t * Register style using handle.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string   $style_handle Handle of style.\n\t * @param string[] $style_dependencies Array of extra dependencies.\n\t */\n\tpublic function register_style_asset( string $style_handle, array $style_dependencies = [] ): void {\n\t\tif ( isset( $this->register_styles[ $style_handle ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$base_style_url  = $this->get_base_url( 'assets/css/' );\n\t\t$base_style_path = $this->get_base_path( 'assets/css/' );\n\t\t$ext             = is_rtl() ? '-rtl.css' : '.css';\n\n\t\t// Register any chunks of $style_handle first.\n\t\t$asset = $this->get_asset_metadata( $style_handle );\n\t\t// Webpack appends \"-[contenthash]\" to filenames of chunks, so omit the `?ver=` query param.\n\t\t$chunk_version = null;\n\t\tforeach ( $asset['css'] as $style_chunk ) {\n\t\t\t$this->register_style(\n\t\t\t\t$style_chunk,\n\t\t\t\t$base_style_url . $style_chunk . '.css',\n\t\t\t\t[],\n\t\t\t\t$chunk_version\n\t\t\t);\n\n\t\t\twp_style_add_data( $style_chunk, 'path', $base_style_path . $style_chunk . $ext );\n\t\t}\n\t\t$style_dependencies = [ ...$style_dependencies, ...$asset['css'] ];\n\n\t\t$entry_version = $asset['version'];\n\t\t$this->register_style(\n\t\t\t$style_handle,\n\t\t\t$base_style_url . $style_handle . '.css',\n\t\t\t$style_dependencies,\n\t\t\t$entry_version\n\t\t);\n\n\t\twp_style_add_data( $style_handle, 'rtl', 'replace' );\n\t\twp_style_add_data( $style_handle, 'path', $base_style_path . $style_handle . $ext );\n\t}\n\n\t/**\n\t * Enqueue style using handle.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string   $style_handle Handle of style.\n\t * @param string[] $style_dependencies Array of extra dependencies.\n\t */\n\tpublic function enqueue_style_asset( string $style_handle, array $style_dependencies = [] ): void {\n\t\t$this->register_style_asset( $style_handle, $style_dependencies );\n\t\t$this->enqueue_style( $style_handle );\n\t}\n\n\t/**\n\t * Register a CSS stylesheet.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string           $style_handle Name of the stylesheet. Should be unique.\n\t * @param string|false     $src    Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.\n\t *                                 If source is set to false, stylesheet is an alias of other stylesheets it depends on.\n\t * @param string[]         $deps   Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.\n\t * @param string|bool|null $ver    Optional. String specifying stylesheet version number, if it has one, which is added to the URL\n\t *                                 as a query string for cache busting purposes. If version is set to false, a version\n\t *                                 number is automatically added equal to current installed WordPress version.\n\t *                                 If set to null, no version is added.\n\t * @param string           $media  Optional. The media for which this stylesheet has been defined.\n\t *                                 Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like\n\t *                                 '(orientation: portrait)' and '(max-width: 640px)'.\n\t * @return bool Whether the style has been registered. True on success, false on failure.\n\t */\n\tpublic function register_style( string $style_handle, $src, array $deps = [], $ver = false, string $media = 'all' ): bool {\n\t\tif ( ! isset( $this->register_styles[ $style_handle ] ) ) {\n\t\t\t$this->register_styles[ $style_handle ] = wp_register_style( $style_handle, $src, $deps, $ver, $media );\n\t\t}\n\n\t\treturn $this->register_styles[ $style_handle ];\n\t}\n\n\t/**\n\t * Register a new script.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string           $script_handle    Name of the script. Should be unique.\n\t * @param string|false     $src       Full URL of the script, or path of the script relative to the WordPress root directory.\n\t *                                    If source is set to false, script is an alias of other scripts it depends on.\n\t * @param string[]         $deps      Optional. An array of registered script handles this script depends on. Default empty array.\n\t * @param string|bool|null $ver       Optional. String specifying script version number, if it has one, which is added to the URL\n\t *                                    as a query string for cache busting purposes. If version is set to false, a version\n\t *                                    number is automatically added equal to current installed WordPress version.\n\t *                                    If set to null, no version is added.\n\t * @param bool             $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.\n\t *                                    Default 'false'.\n\t * @param bool             $with_i18n Optional. Whether to setup i18n for this asset. Default true.\n\t * @return bool Whether the script has been registered. True on success, false on failure.\n\t */\n\tpublic function register_script( string $script_handle, $src, array $deps = [], $ver = false, bool $in_footer = false, bool $with_i18n = true ): bool {\n\t\tif ( ! isset( $this->register_scripts[ $script_handle ] ) ) {\n\t\t\t$this->register_scripts[ $script_handle ] = wp_register_script(\n\t\t\t\t$script_handle,\n\t\t\t\t$src,\n\t\t\t\t$deps,\n\t\t\t\t$ver,\n\t\t\t\t[\n\t\t\t\t\t'in_footer' => $in_footer,\n\t\t\t\t]\n\t\t\t);\n\n\t\t\tif ( $src && $with_i18n ) {\n\t\t\t\twp_set_script_translations( $script_handle, 'web-stories' );\n\t\t\t}\n\t\t}\n\n\t\treturn $this->register_scripts[ $script_handle ];\n\t}\n\n\t/**\n\t * Enqueue a style.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string           $style_handle Name of the stylesheet. Should be unique.\n\t * @param string           $src    Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.\n\t *                                 Default empty.\n\t * @param string[]         $deps   Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.\n\t * @param string|bool|null $ver    Optional. String specifying stylesheet version number, if it has one, which is added to the URL\n\t *                                 as a query string for cache busting purposes. If version is set to false, a version\n\t *                                 number is automatically added equal to current installed WordPress version.\n\t *                                 If set to null, no version is added.\n\t * @param string           $media  Optional. The media for which this stylesheet has been defined.\n\t *                                 Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like\n\t *                                 '(orientation: portrait)' and '(max-width: 640px)'.\n\t */\n\tpublic function enqueue_style( string $style_handle, string $src = '', array $deps = [], $ver = false, string $media = 'all' ): void {\n\t\t$this->register_style( $style_handle, $src, $deps, $ver, $media );\n\t\twp_enqueue_style( $style_handle, $src, $deps, $ver, $media );\n\t}\n\n\t/**\n\t * Enqueue a script.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string           $script_handle    Name of the script. Should be unique.\n\t * @param string           $src       Full URL of the script, or path of the script relative to the WordPress root directory.\n\t *                                    Default empty.\n\t * @param string[]         $deps      Optional. An array of registered script handles this script depends on. Default empty array.\n\t * @param string|bool|null $ver       Optional. String specifying script version number, if it has one, which is added to the URL\n\t *                                    as a query string for cache busting purposes. If version is set to false, a version\n\t *                                    number is automatically added equal to current installed WordPress version.\n\t *                                    If set to null, no version is added.\n\t * @param bool             $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.\n\t *                                    Default 'false'.\n\t * @param bool             $with_i18n Optional. Whether to setup i18n for this asset. Default true.\n\t */\n\tpublic function enqueue_script( string $script_handle, string $src = '', array $deps = [], $ver = false, bool $in_footer = false, bool $with_i18n = false ): void {\n\t\t$this->register_script( $script_handle, $src, $deps, $ver, $in_footer, $with_i18n );\n\t\twp_enqueue_script( $script_handle, $src, $deps, $ver, $in_footer );\n\t}\n\n\t/**\n\t * Register a new script module.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.40.1\n\t *\n\t * @param string $script_handle Name of the script module. Should be unique.\n\t * @param string $src           Full URL of the script module.\n\t */\n\tpublic function enqueue_script_module( string $script_handle, string $src ): void {\n\t\t$asset = $this->get_asset_metadata( $script_handle );\n\n\t\twp_enqueue_script_module(\n\t\t\t$script_handle,\n\t\t\t$src,\n\t\t\t$asset['dependencies'], // @phpstan-ignore argument.type\n\t\t\t$asset['version'],\n\t\t);\n\t}\n\n\t/**\n\t * Remove admin styles.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param string[] $styles Array of styles to be removed.\n\t */\n\tpublic function remove_admin_style( array $styles ): void {\n\t\twp_styles()->registered['wp-admin']->deps = array_diff( wp_styles()->registered['wp-admin']->deps, $styles );\n\t}\n\n\t/**\n\t * Returns the translations for a script and all of its chunks.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param string $script_handle Name of the script. Should be unique.\n\t * @return array<int, mixed> Script translations.\n\t */\n\tpublic function get_translations( string $script_handle ): array {\n\t\t/**\n\t\t * List of script chunks.\n\t\t *\n\t\t * @var false|string[]\n\t\t */\n\t\t$chunks = wp_scripts()->get_data( $script_handle, 'chunks' );\n\n\t\tif ( ! \\is_array( $chunks ) ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t$translations = [\n\t\t\t(string) load_script_textdomain( $script_handle, 'web-stories' ),\n\t\t];\n\n\t\t/**\n\t\t * Dynamic chunk name.\n\t\t *\n\t\t * @var string $dynamic_chunk\n\t\t */\n\t\tforeach ( $chunks as $dynamic_chunk ) {\n\t\t\t$translations[] = (string) load_script_textdomain( $dynamic_chunk, 'web-stories' );\n\t\t}\n\n\t\treturn array_values(\n\t\t\tarray_map(\n\t\t\t\tstatic fn( $translations ) => json_decode( $translations, true ),\n\t\t\t\tarray_filter( $translations )\n\t\t\t)\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Block/Web_Stories_Block.php",
    "content": "<?php\n/**\n * Class Web_Stories_Block.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Block;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Embed_Base;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Stories_Script_Data;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse Google\\Web_Stories\\Tracking;\nuse WP_Block;\n\n/**\n * Latest Stories block class.\n *\n * @phpstan-import-type StoryAttributes from \\Google\\Web_Stories\\Story_Query\n * @phpstan-type BlockAttributes array{\n *   blockType?: string,\n *   url?: string,\n *   title?: string,\n *   poster?: string,\n *   width?: int,\n *   height?: int,\n *   align?: string,\n *   stories?: int[],\n *   viewType?: string,\n *   numOfStories?: int,\n *   numOfColumns?: int,\n *   circleSize?: int,\n *   imageAlignment?: string,\n *   orderby?: string,\n *   order?: string,\n *   archiveLinkLabel?: string,\n *   authors?: int[],\n *   fieldState?: array<string, mixed>,\n *   previewOnly?: bool,\n *   taxQuery?: array<string, int[]>\n * }\n * @phpstan-type BlockAttributesWithDefaults array{\n *   blockType?: string,\n *   url?: string,\n *   title?: string,\n *   poster?: string,\n *   width?: int,\n *   height?: int,\n *   align: string,\n *   stories?: int[],\n *   viewType?: string,\n *   numOfStories?: int,\n *   numOfColumns?: int,\n *   circleSize?: int,\n *   imageAlignment?: string,\n *   orderby?: string,\n *   order?: string,\n *   archiveLinkLabel?: string,\n *   authors?: int[],\n *   fieldState?: array<string, mixed>,\n *   previewOnly?: bool\n * }\n */\nclass Web_Stories_Block extends Embed_Base {\n\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-block';\n\n\t/**\n\t * Maximum number of stories users can select\n\t */\n\tpublic const MAX_NUM_OF_STORIES = 20;\n\n\t/**\n\t * Current block's block attributes.\n\t *\n\t * @var array<string, mixed> Block Attributes.\n\t * @phpstan-var BlockAttributes\n\t */\n\tprotected array $block_attributes;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprotected Story_Post_Type $story_post_type;\n\n\t/**\n\t * Stories_Script_Data instance.\n\t *\n\t * @var Stories_Script_Data Stories_Script_Data instance.\n\t */\n\tprotected Stories_Script_Data $stories_script_data;\n\n\t/**\n\t * Embed Base constructor.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param Assets              $assets              Assets instance.\n\t * @param Story_Post_Type     $story_post_type     Story_Post_Type instance.\n\t * @param Stories_Script_Data $stories_script_data Stories_Script_Data instance.\n\t * @param Context             $context             Context instance.\n\t */\n\tpublic function __construct(\n\t\tAssets $assets,\n\t\tStory_Post_Type $story_post_type,\n\t\tStories_Script_Data $stories_script_data,\n\t\tContext $context\n\t) {\n\t\tparent::__construct( $assets, $context );\n\n\t\t$this->story_post_type     = $story_post_type;\n\t\t$this->stories_script_data = $stories_script_data;\n\t}\n\n\t/**\n\t * Initializes the Web Stories embed block.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register(): void {\n\t\tparent::register();\n\t\t$this->assets->register_script_asset( self::SCRIPT_HANDLE, [ AMP_Story_Player_Assets::SCRIPT_HANDLE, Tracking::SCRIPT_HANDLE ] );\n\t\t$this->assets->register_style_asset( self::SCRIPT_HANDLE, [ AMP_Story_Player_Assets::SCRIPT_HANDLE, parent::SCRIPT_HANDLE ] );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStoriesBlockSettings',\n\t\t\t$this->get_script_settings()\n\t\t);\n\n\t\t$this->register_block_type();\n\t}\n\n\t/**\n\t * Renders the block type output for given attributes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string, mixed> $attributes Block attributes.\n\t * @param string               $content    Block content.\n\t * @param WP_Block             $block      Block instance.\n\t * @return string Rendered block type output.\n\t *\n\t * @phpstan-param BlockAttributesWithDefaults $attributes\n\t */\n\tpublic function render_block( array $attributes, string $content, WP_Block $block ): string {\n\t\tif ( false === $this->initialize_block_attributes( $attributes ) ) {\n\t\t\treturn '';\n\t\t}\n\n\t\tif ( isset( $block->context['postType'], $block->context['postId'] ) && 'web-story' === $block->context['postType'] && ! empty( $block->context['postId'] ) ) {\n\t\t\t$attributes = wp_parse_args( $attributes, $this->default_attrs() );\n\n\t\t\t$attributes['class'] = 'wp-block-web-stories-embed';\n\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( get_post( $block->context['postId'] ) );\n\n\t\t\treturn $this->render_story( $story, $attributes );\n\t\t}\n\n\t\tif ( ! empty( $attributes['blockType'] )\n\t\t\t&& ( 'latest-stories' === $attributes['blockType'] || 'selected-stories' === $attributes['blockType'] ) ) {\n\n\t\t\t$story_attributes = [\n\t\t\t\t'align'              => $attributes['align'],\n\t\t\t\t'view_type'          => $attributes['viewType']         ??= '',\n\t\t\t\t'archive_link_label' => $attributes['archiveLinkLabel'] ??= __( 'View all stories', 'web-stories' ),\n\t\t\t\t'circle_size'        => $attributes['circleSize']       ??= 96,\n\t\t\t\t'image_alignment'    => $attributes['imageAlignment']   ??= 96,\n\t\t\t\t'number_of_columns'  => $attributes['numOfColumns']     ??= 2,\n\t\t\t];\n\n\t\t\t/**\n\t\t\t * Story Attributes.\n\t\t\t *\n\t\t\t * @phpstan-var StoryAttributes $story_attributes\n\t\t\t */\n\t\t\t$story_attributes = array_merge( $story_attributes, $this->get_mapped_field_states() );\n\n\t\t\treturn ( new Story_Query( $story_attributes, $this->get_query_args() ) )->render();\n\t\t}\n\n\t\t// Embedding a single story by URL.\n\t\t$attributes = wp_parse_args( $attributes, $this->default_attrs() );\n\n\t\t$attributes['class'] = 'wp-block-web-stories-embed';\n\n\t\treturn $this->render( $attributes );\n\t}\n\n\t/**\n\t * Maps fields to the story params.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string, mixed>\n\t */\n\tpublic function get_mapped_field_states(): array {\n\t\t$controls = [\n\t\t\t'show_title'        => 'title',\n\t\t\t'show_author'       => 'author',\n\t\t\t'show_excerpt'      => 'excerpt',\n\t\t\t'show_date'         => 'date',\n\t\t\t'show_archive_link' => 'archive_link',\n\t\t\t'sharp_corners'     => 'sharp_corners',\n\t\t];\n\n\t\t$controls_state = [];\n\n\t\tforeach ( $controls as $control => $field ) {\n\t\t\t$key = 'show_' . $field;\n\n\t\t\t$controls_state[ $control ] = $this->block_attributes['fieldState'][ $key ] ?? false;\n\t\t}\n\n\t\treturn $controls_state;\n\t}\n\n\t/**\n\t * Registers a block type from metadata stored in the `block.json` file.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function register_block_type(): void {\n\t\t$base_path = $this->assets->get_base_path( 'blocks/embed/block.json' );\n\t\t// Note: does not use 'script' and 'style' args, and instead uses 'render_callback'\n\t\t// to enqueue these assets only when needed.\n\t\tregister_block_type_from_metadata(\n\t\t\t$base_path,\n\t\t\t[\n\t\t\t\t'attributes'      => [\n\t\t\t\t\t'blockType'        => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t\t'url'              => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t\t'title'            => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => __( 'Web Story', 'web-stories' ),\n\t\t\t\t\t],\n\t\t\t\t\t'poster'           => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t\t'width'            => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 360,\n\t\t\t\t\t],\n\t\t\t\t\t'height'           => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 600,\n\t\t\t\t\t],\n\t\t\t\t\t'align'            => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => 'none',\n\t\t\t\t\t],\n\t\t\t\t\t'stories'          => [\n\t\t\t\t\t\t'type'    => 'array',\n\t\t\t\t\t\t'default' => [],\n\t\t\t\t\t],\n\t\t\t\t\t'viewType'         => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => '',\n\t\t\t\t\t],\n\t\t\t\t\t'numOfStories'     => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 5,\n\t\t\t\t\t],\n\t\t\t\t\t'numOfColumns'     => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 2,\n\t\t\t\t\t],\n\t\t\t\t\t'circleSize'       => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 96,\n\t\t\t\t\t],\n\t\t\t\t\t'imageAlignment'   => [\n\t\t\t\t\t\t'type'    => 'number',\n\t\t\t\t\t\t'default' => 96,\n\t\t\t\t\t],\n\t\t\t\t\t'orderby'          => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => '',\n\t\t\t\t\t],\n\t\t\t\t\t'order'            => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => '',\n\t\t\t\t\t],\n\t\t\t\t\t'archiveLinkLabel' => [\n\t\t\t\t\t\t'type'    => 'string',\n\t\t\t\t\t\t'default' => __( 'View all stories', 'web-stories' ),\n\t\t\t\t\t],\n\t\t\t\t\t'authors'          => [\n\t\t\t\t\t\t'type'    => 'array',\n\t\t\t\t\t\t'default' => [],\n\t\t\t\t\t],\n\t\t\t\t\t'fieldState'       => [\n\t\t\t\t\t\t'type'    => 'object',\n\t\t\t\t\t\t'default' => [],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'render_callback' => [ $this, 'render_block' ],\n\t\t\t\t'editor_script'   => self::SCRIPT_HANDLE,\n\t\t\t\t'editor_style'    => self::SCRIPT_HANDLE,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Returns script settings.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string, mixed> Script settings.\n\t */\n\tprivate function get_script_settings(): array {\n\t\t$settings = [\n\t\t\t'publicPath' => $this->assets->get_base_url( 'assets/js/' ),\n\t\t\t'config'     => [\n\t\t\t\t'maxNumOfStories' => self::MAX_NUM_OF_STORIES,\n\t\t\t\t'archiveURL'      => get_post_type_archive_link( $this->story_post_type->get_slug() ),\n\t\t\t\t'api'             => [\n\t\t\t\t\t'stories' => trailingslashit( $this->story_post_type->get_rest_url() ),\n\t\t\t\t\t'users'   => '/web-stories/v1/users/',\n\t\t\t\t],\n\t\t\t\t'fieldStates'     => $this->stories_script_data->fields_states(),\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filters settings passed to the web stories block.\n\t\t *\n\t\t * @param array<string, mixed> $settings Array of settings passed to web stories block.\n\t\t */\n\t\treturn apply_filters( 'web_stories_block_settings', $settings );\n\t}\n\n\t/**\n\t * Initializes class variable $block_attributes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array $block_attributes Array containing block attributes.\n\t * @return bool Whether or not block attributes have been initialized with given value.\n\t *\n\t * @phpstan-param BlockAttributes $block_attributes\n\t */\n\tprotected function initialize_block_attributes( array $block_attributes = [] ): bool {\n\t\tif ( ! empty( $block_attributes ) ) {\n\t\t\t$this->block_attributes = $block_attributes;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Returns arguments to be passed to the WP_Query object initialization.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string, mixed> Query arguments.\n\t */\n\tprotected function get_query_args(): array {\n\t\t$attributes = $this->block_attributes;\n\n\t\t$query_args = [\n\t\t\t'post_type'        => $this->story_post_type->get_slug(),\n\t\t\t'post_status'      => 'publish',\n\t\t\t'suppress_filters' => false,\n\t\t\t'no_found_rows'    => true,\n\t\t];\n\n\t\tif ( ! empty( $attributes['taxQuery'] ) ) {\n\t\t\t// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\t\t\t$query_args['tax_query'] = [];\n\t\t\tforeach ( $attributes['taxQuery'] as $taxonomy => $terms ) {\n\t\t\t\tif ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {\n\t\t\t\t\t// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\t\t\t\t\t$query_args['tax_query'][] = [\n\t\t\t\t\t\t'taxonomy'         => $taxonomy,\n\t\t\t\t\t\t'terms'            => array_filter( array_map( '\\intval', $terms ) ),\n\t\t\t\t\t\t'include_children' => false,\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if block type is 'selected-tories'.\n\t\tif ( ! empty( $attributes['blockType'] )\n\t\t\t&& 'selected-stories' === $attributes['blockType']\n\t\t\t&& ! empty( $attributes['stories'] )\n\t\t) {\n\t\t\t$query_args['post__in'] = $attributes['stories'];\n\t\t\t$query_args['orderby']  = 'post__in';\n\n\t\t\treturn $query_args;\n\t\t}\n\n\t\tif ( ! empty( $attributes['numOfStories'] ) ) {\n\t\t\t$query_args['posts_per_page'] = $attributes['numOfStories'];\n\t\t}\n\n\t\tif ( ! empty( $attributes['order'] ) ) {\n\t\t\t$query_args['order'] = strtoupper( $attributes['order'] );\n\t\t}\n\n\t\tif ( ! empty( $attributes['orderby'] ) ) {\n\t\t\t$query_args['orderby'] = 'title' === $attributes['orderby'] ? 'post_title' : 'post_date';\n\t\t}\n\n\t\tif ( ! empty( $attributes['authors'] ) ) {\n\t\t\t$query_args['author__in'] = $attributes['authors'];\n\t\t}\n\n\t\treturn $query_args;\n\t}\n}\n"
  },
  {
    "path": "includes/Context.php",
    "content": "<?php\n/**\n * Class Context\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\n/**\n * Class Context\n */\nclass Context {\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Context constructor.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Determine whether the current response is a single web story.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return bool Whether it is singular story post (and thus an AMP endpoint).\n\t */\n\tpublic function is_web_story(): bool {\n\t\treturn is_singular( $this->story_post_type->get_slug() ) && ! is_embed() && ! post_password_required();\n\t}\n\n\t/**\n\t * Determine whether the current response being served as AMP.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return bool Whether it is singular story post (and thus an AMP endpoint).\n\t */\n\tpublic function is_amp(): bool {\n\t\tif ( $this->is_web_story() ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check for `amp_is_request()` first since `is_amp_endpoint()` is deprecated.\n\t\tif ( \\function_exists( '\\amp_is_request' ) ) {\n\t\t\treturn amp_is_request();\n\t\t}\n\n\t\tif ( \\function_exists( '\\is_amp_endpoint' ) ) {\n\t\t\treturn is_amp_endpoint();\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Determines whether we're currently on the story editor screen.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return bool Whether we're currently on the story editor screen.\n\t */\n\tpublic function is_story_editor(): bool {\n\t\t$screen = \\function_exists( 'get_current_screen' ) ? get_current_screen() : null;\n\n\t\treturn $screen && $this->story_post_type->get_slug() === $screen->post_type && 'post' === $screen->base;\n\t}\n\n\t/**\n\t * Determines whether we're currently on the media upload screen.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return bool Whether we're currently on the media upload screen\n\t */\n\tpublic function is_upload_screen(): bool {\n\t\t$screen = \\function_exists( 'get_current_screen' ) ? get_current_screen() : null;\n\n\t\treturn $screen && 'upload' === $screen->id;\n\t}\n\n\t/**\n\t * Whether we're currently on a block editor screen.\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function is_block_editor(): bool {\n\t\t$screen = \\function_exists( 'get_current_screen' ) ? get_current_screen() : null;\n\n\t\treturn $screen && $screen->is_block_editor();\n\t}\n\n\t/**\n\t * Returns the current screen base if available.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return string|null Current screen base if available.\n\t */\n\tpublic function get_screen_base(): ?string {\n\t\t$screen = \\function_exists( 'get_current_screen' ) ? get_current_screen() : null;\n\n\t\treturn $screen->base ?? null;\n\t}\n\n\t/**\n\t * Returns the current screen post type if available.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return string|null Current screen post type if available.\n\t */\n\tpublic function get_screen_post_type(): ?string {\n\t\t$screen = \\function_exists( 'get_current_screen' ) ? get_current_screen() : null;\n\n\t\treturn $screen->post_type ?? null;\n\t}\n}\n"
  },
  {
    "path": "includes/Database_Upgrader.php",
    "content": "<?php\n/**\n * Class Database_Upgrader\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\PluginActivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\SiteInitializationAware;\nuse Google\\Web_Stories\\Interfaces\\Migration;\nuse WP_Site;\n\n/**\n * Class Database_Upgrader\n */\nclass Database_Upgrader implements Service, Registerable, PluginActivationAware, SiteInitializationAware, PluginUninstallAware {\n\n\t/**\n\t * The slug of database option.\n\t */\n\tpublic const OPTION = 'web_stories_db_version';\n\n\t/**\n\t * The slug of database option.\n\t */\n\tpublic const PREVIOUS_OPTION = 'web_stories_previous_db_version';\n\n\t/**\n\t * Array of classes to run migration routines.\n\t */\n\tpublic const ROUTINES = [\n\t\t'1.0.0'  => Migrations\\Update_1::class,\n\t\t'2.0.0'  => Migrations\\Replace_Conic_Style_Presets::class,\n\t\t'2.0.1'  => Migrations\\Add_Media_Source_Editor::class,\n\t\t'2.0.2'  => Migrations\\Remove_Broken_Text_Styles::class,\n\t\t'2.0.3'  => Migrations\\Unify_Color_Presets::class,\n\t\t'2.0.4'  => Migrations\\Update_Publisher_Logos::class,\n\t\t'3.0.0'  => Migrations\\Add_Stories_Caps::class,\n\t\t'3.0.1'  => Migrations\\Rewrite_Flush::class,\n\t\t'3.0.2'  => Migrations\\Rewrite_Flush::class,\n\t\t'3.0.4'  => Migrations\\Add_Poster_Generation_Media_Source::class,\n\t\t'3.0.5'  => Migrations\\Remove_Unneeded_Attachment_Meta::class,\n\t\t'3.0.6'  => Migrations\\Add_Media_Source_Video_Optimization::class,\n\t\t'3.0.7'  => Migrations\\Add_Media_Source_Source_Video::class,\n\t\t'3.0.8'  => Migrations\\Rewrite_Flush::class,\n\t\t'3.0.9'  => Migrations\\Add_VideoPress_Poster_Generation_Media_Source::class,\n\t\t'3.0.10' => Migrations\\Add_Media_Source_Gif_Conversion::class,\n\t\t'3.0.11' => Migrations\\Add_Media_Source_Source_Image::class,\n\t\t'3.0.12' => Migrations\\Set_Legacy_Analytics_Usage_Flag::class,\n\t\t'3.0.13' => Migrations\\Add_Stories_Caps::class,\n\t\t'3.0.14' => Migrations\\Add_Media_Source_Page_Template::class,\n\t\t'3.0.15' => Migrations\\Add_Media_Source_Recording::class,\n\t\t'3.0.16' => Migrations\\Remove_Incorrect_Tracking_Id::class,\n\t];\n\n\t/**\n\t * Injector instance.\n\t *\n\t * @var Injector Injector instance.\n\t */\n\tprivate Injector $injector;\n\n\t/**\n\t * Database_Upgrader constructor.\n\t *\n\t * @param Injector $injector Injector instance.\n\t */\n\tpublic function __construct( Injector $injector ) {\n\t\t$this->injector = $injector;\n\t}\n\n\t/**\n\t * Hooked into admin_init and walks through an array of upgrade methods.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'admin_init', [ $this, 'run_upgrades' ], 5 );\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->run_upgrades();\n\t}\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\t$this->run_upgrades();\n\t}\n\n\t/**\n\t * Run all upgrade routines in order.\n\t *\n\t * @since 1.11.0\n\t */\n\tpublic function run_upgrades(): void {\n\t\t/**\n\t\t * Current database version.\n\t\t *\n\t\t * @var string $version\n\t\t */\n\t\t$version = get_option( self::OPTION, '0.0.0' );\n\n\t\tif ( '0.0.0' === $version ) {\n\t\t\t$this->finish_up( $version );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( version_compare( WEBSTORIES_DB_VERSION, $version, '=' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$routines = self::ROUTINES;\n\t\tarray_walk( $routines, [ $this, 'run_upgrade_routine' ], $version );\n\t\t$this->finish_up( $version );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_option( self::PREVIOUS_OPTION );\n\t\tdelete_option( self::OPTION );\n\t}\n\n\t/**\n\t * Runs the upgrade routine.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param class-string $class_name The Class to call.\n\t * @param string       $version         The new version.\n\t * @param string       $current_version The current set version.\n\t */\n\tprotected function run_upgrade_routine( string $class_name, string $version, string $current_version ): void {\n\t\tif ( version_compare( $current_version, $version, '<' ) ) {\n\t\t\t/**\n\t\t\t * Instance of a migration class.\n\t\t\t *\n\t\t\t * @var Migration $routine\n\t\t\t */\n\t\t\t$routine = $this->injector->make( $class_name );\n\t\t\t$routine->migrate();\n\t\t}\n\t}\n\n\t/**\n\t * Runs the needed cleanup after an update, setting the DB version to latest version, flushing caches etc.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $previous_version The previous version.\n\t */\n\tprotected function finish_up( string $previous_version ): void {\n\t\tupdate_option( self::PREVIOUS_OPTION, $previous_version );\n\t\tupdate_option( self::OPTION, WEBSTORIES_DB_VERSION );\n\t}\n}\n"
  },
  {
    "path": "includes/Decoder.php",
    "content": "<?php\n/**\n * Class Decoder\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\n/**\n * Decoder class.\n *\n * @since 1.1.0\n */\nclass Decoder {\n\t/**\n\t * Determines whether encoding and decoding of story markup is supported.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @return bool Whether decoding is supported.\n\t */\n\tpublic function supports_decoding(): bool {\n\t\t/**\n\t\t * Filter whether the encoding requests.\n\t\t *\n\t\t * @since 1.2.0\n\t\t *\n\t\t * @param bool $enable_decoding Enable disable encoding.\n\t\t */\n\t\treturn apply_filters( 'web_stories_enable_decoding', true );\n\t}\n\n\t/**\n\t * Decodes string if encoded.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param string $content String to decode.\n\t * @return string Decoded string.\n\t */\n\tpublic function base64_decode( string $content ): string {\n\t\tif ( str_starts_with( $content, '__WEB_STORIES_ENCODED__' ) ) {\n\t\t\t$content = str_replace( '__WEB_STORIES_ENCODED__', '', $content );\n\n\t\t\treturn urldecode( base64_decode( $content ) );\n\t\t}\n\n\t\treturn $content;\n\t}\n}\n"
  },
  {
    "path": "includes/Demo_Content.php",
    "content": "<?php\n/**\n * Demo_Content class.\n *\n * Used for getting demo content.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\n/**\n * Demo_Content class.\n */\nclass Demo_Content {\n\t/**\n\t * Returns the title for the demo story.\n\t */\n\tpublic function get_title(): string {\n\t\treturn __( 'Tips to make the most of Web Stories', 'web-stories' );\n\t}\n\n\t/**\n\t * Returns the content for the demo story.\n\t */\n\tpublic function get_content(): string {\n\t\t$content = $this->load_demo_content_from_file();\n\t\t$content = $this->localize_texts( $content );\n\t\t$content = $this->update_assets_urls( $content );\n\n\t\t// Quick sanity check to see if the JSON is still valid.\n\t\tif ( null === json_decode( $content, true ) ) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $content;\n\t}\n\n\t/**\n\t * Updates URLs to media assets in demo content.\n\t *\n\t * @param string $content Original content.\n\t * @return string Modified content.\n\t */\n\tprivate function update_assets_urls( string $content ): string {\n\t\treturn str_replace(\n\t\t\t'https://replaceme.com/',\n\t\t\ttrailingslashit( WEBSTORIES_CDN_URL ),\n\t\t\t$content\n\t\t);\n\t}\n\n\t/**\n\t * Localizes demo content.\n\t *\n\t * @param string $content Original content.\n\t * @return string Localized text.\n\t */\n\tprivate function localize_texts( string $content ): string {\n\t\t$replacements = [\n\t\t\t// Page 1.\n\t\t\t'L10N_PLACEHOLDER_1_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Tips to make the most of the Web Stories Editor', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 2.\n\n\t\t\t'L10N_PLACEHOLDER_2_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Set a page background', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_2_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Drag your image or video to the edge of the page to set as page background.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 3.\n\n\t\t\t'L10N_PLACEHOLDER_3_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Media Edit Mode', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_3_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Double-click the image/video to resize, re-center or crop. Note: media set as page background cannot be cropped.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 4.\n\n\t\t\t'L10N_PLACEHOLDER_4_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Background Overlay', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_4_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Once you\\'ve set a page bg, add a solid, linear or radial gradient overlay to increase text contrast or add visual styling.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 5.\n\n\t\t\t'L10N_PLACEHOLDER_5_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Safe Zone', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_5_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Add your designs to the page, keeping crucial elements inside the safe zone to ensure they are visible across most devices.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 6.\n\n\t\t\t'L10N_PLACEHOLDER_6_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Story System Layer', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_6_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'The system layer is docked at the top. Preview your story to ensure system layer icons are not blocking crucial elements.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 7.\n\n\t\t\t'L10N_PLACEHOLDER_7_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Shapes and Masks', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_7_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Our shapes are quite basic for now but they act as masks. Drag an image or video into the mask.', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 8.\n\n\t\t\t'L10N_PLACEHOLDER_8_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Embed Visual Stories', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_8_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Embed stories into your blog post. Open the block menu & select the Web Stories block. Insert the story link to embed your story. That\\'s it!', 'demo content', 'web-stories' ),\n\n\t\t\t// Page 9.\n\n\t\t\t'L10N_PLACEHOLDER_9_1' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Read about best practices for creating successful Web Stories', 'demo content', 'web-stories' ),\n\n\t\t\t'L10N_PLACEHOLDER_9_2' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_url( _x( 'https://amp.dev/documentation/guides-and-tutorials/start/create_successful_stories/', 'demo content', 'web-stories' ) ),\n\n\t\t\t'L10N_PLACEHOLDER_9_3' => /* translators: demo content used in the \"Get Started\" story */\n\t\t\t\tesc_html_x( 'Best Practices', 'demo content', 'web-stories' ),\n\t\t];\n\n\t\tforeach ( $replacements as $search => $replacement ) {\n\t\t\t$content = str_replace( $search, $replacement, $content );\n\t\t}\n\n\t\treturn $content;\n\t}\n\n\t/**\n\t * Loads demo content from JSON file.\n\t */\n\tprivate function load_demo_content_from_file(): string {\n\t\t$file = WEBSTORIES_PLUGIN_DIR_PATH . 'includes/data/stories/demo.json';\n\n\t\tif ( ! is_readable( $file ) ) {\n\t\t\treturn '';\n\t\t}\n\n\t\t$content = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown\n\n\t\tif ( ! $content ) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $content;\n\t}\n}\n"
  },
  {
    "path": "includes/Discovery.php",
    "content": "<?php\n/**\n * Class Discovery.\n *\n * Responsible for improved discovery of stories on the web.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Shopping\\Product;\nuse WP_Post;\n\n/**\n * Discovery class.\n */\nclass Discovery extends Service_Base implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type', 'product_meta' ];\n\t}\n\n\t/**\n\t * Initialize discovery functionality.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_document_title' ] );\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_metadata' ] );\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_schemaorg_metadata' ] );\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_open_graph_metadata' ] );\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_twitter_metadata' ] );\n\n\t\tadd_action( 'web_stories_story_head', [ $this, 'print_feed_link' ], 4 );\n\t\tadd_action( 'wp_head', [ $this, 'print_feed_link' ], 4 );\n\n\t\t// @todo Check if there's something to skip in the new version.\n\t\tadd_action( 'web_stories_story_head', 'rest_output_link_wp_head', 10, 0 );\n\t\tadd_action( 'web_stories_story_head', 'wp_resource_hints', 2 );\n\t\tadd_action( 'web_stories_story_head', 'feed_links', 2 );\n\t\tadd_action( 'web_stories_story_head', 'feed_links_extra', 3 );\n\t\tadd_action( 'web_stories_story_head', 'rsd_link' );\n\t\tadd_action( 'web_stories_story_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );\n\t\tadd_action( 'web_stories_story_head', 'wp_generator' );\n\t\tadd_action( 'web_stories_story_head', 'rel_canonical' );\n\t\tadd_action( 'web_stories_story_head', 'wp_shortlink_wp_head', 10, 0 );\n\t\tadd_action( 'web_stories_story_head', 'wp_site_icon', 99 );\n\t\tadd_action( 'web_stories_story_head', 'wp_oembed_add_discovery_links' );\n\t\tadd_action( 'web_stories_story_head', 'wp_robots', 1 );\n\t}\n\n\t/**\n\t * Prints document title for stories.\n\t *\n\t * Adds the title regardless of theme support.\n\t *\n\t * AMP sanitization will ensure there is always just exactly one title tag present.\n\t *\n\t * @since 1.25.0\n\t *\n\t * @link https://github.com/GoogleForCreators/web-stories-wp/issues/12139\n\t * @link https://github.com/GoogleForCreators/web-stories-wp/issues/12487\n\t * @link https://github.com/GoogleForCreators/web-stories-wp/issues/12655\n\t */\n\tpublic function print_document_title(): void {\n\t\t/**\n\t\t * Filters whether to print the document title.\n\t\t *\n\t\t * @since 1.25.0\n\t\t *\n\t\t * @param bool $enable_open_graph Whether to print the document title. Default to true.\n\t\t */\n\t\t$enable_metadata = apply_filters( 'web_stories_enable_document_title', true );\n\t\tif ( ! $enable_metadata ) {\n\t\t\treturn;\n\t\t}\n\t\t?>\n\t\t<title><?php echo esc_html( wp_get_document_title() ); ?></title>\n\t\t<?php\n\t}\n\n\t/**\n\t * Prints the meta description on the single story template.\n\t *\n\t * Adds the meta mescription regardless of theme support.\n\t *\n\t * AMP sanitization will ensure there is always just exactly one meta description present.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @see _wp_render_title_tag().\n\t */\n\tpublic function print_metadata(): void {\n\t\t/**\n\t\t * Filters whether to print the meta description.\n\t\t *\n\t\t * @since 1.2.0\n\t\t *\n\t\t * @param bool $enable_open_graph Whether to print the meta description. Default to true.\n\t\t */\n\t\t$enable_metadata = apply_filters( 'web_stories_enable_metadata', true );\n\t\tif ( ! $enable_metadata ) {\n\t\t\treturn;\n\t\t}\n\t\t?>\n\t\t<meta name=\"description\" content=\"<?php echo esc_attr( wp_strip_all_tags( get_the_excerpt() ) ); ?>\" />\n\t\t<?php\n\t}\n\n\t/**\n\t * Prints the schema.org metadata on the single story template.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function print_schemaorg_metadata(): void {\n\t\t/**\n\t\t * Filters filter to enable / disable schemaorg metadata.\n\t\t *\n\t\t * @since 1.2.0\n\t\t *\n\t\t * @param bool $enable_schemaorg_metadata Enable / disable schemaorg metadata. Default to true.\n\t\t */\n\t\t$enable_schemaorg_metadata = apply_filters( 'web_stories_enable_schemaorg_metadata', true );\n\t\tif ( ! $enable_schemaorg_metadata ) {\n\t\t\treturn;\n\t\t}\n\t\t$metadata = $this->get_schemaorg_metadata();\n\n\t\t?>\n\t\t<script type=\"application/ld+json\"><?php echo wp_json_encode( $metadata, JSON_UNESCAPED_UNICODE ); ?></script>\n\t\t<?php\n\t}\n\n\t/**\n\t * Prints Open Graph metadata.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function print_open_graph_metadata(): void {\n\t\t/**\n\t\t * Filters filter to enable / disable open graph metadata.\n\t\t *\n\t\t * @since 1.2.0\n\t\t *\n\t\t * @param bool $enable_open_graph_metadata Enable / disable open graph metadata. Default to true.\n\t\t */\n\t\t$enable_open_graph_metadata = apply_filters( 'web_stories_enable_open_graph_metadata', true );\n\t\tif ( ! $enable_open_graph_metadata ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$metadata = $this->get_open_graph_metadata();\n\n\t\tforeach ( $metadata as $name => $value ) {\n\t\t\tprintf( '<meta property=\"%s\" content=\"%s\" />', esc_attr( $name ), esc_attr( (string) $value ) );\n\t\t}\n\t}\n\n\t/**\n\t * Prints Twitter card metadata.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function print_twitter_metadata(): void {\n\t\t/**\n\t\t * Filters filter to enable / disable twitter metadata.\n\t\t *\n\t\t * @since 1.2.0\n\t\t *\n\t\t * @param bool $enable_twitter_metadata Enable / disable twitter metadata. Default to true.\n\t\t */\n\t\t$enable_twitter_metadata = apply_filters( 'web_stories_enable_twitter_metadata', true );\n\t\tif ( ! $enable_twitter_metadata ) {\n\t\t\treturn;\n\t\t}\n\t\t$metadata = $this->get_twitter_metadata();\n\n\t\tforeach ( $metadata as $name => $value ) {\n\t\t\tprintf( '<meta name=\"%s\" content=\"%s\" />', esc_attr( $name ), esc_attr( $value ) );\n\t\t}\n\t}\n\n\t/**\n\t * Add RSS feed link for stories, if theme supports automatic-feed-links.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function print_feed_link(): void {\n\t\t$enable_print_feed_link = current_theme_supports( 'automatic-feed-links' ) && ! is_post_type_archive( $this->story_post_type->get_slug() );\n\n\t\t/**\n\t\t * Filters filter to enable / disable printing feed links.\n\t\t *\n\t\t * @since 1.29.0\n\t\t *\n\t\t * @param bool $enable_print_feed_link Enable / disable printing feed links. Default to if automatic-feed-links is enabled.\n\t\t */\n\t\t$enable_print_feed_link = apply_filters( 'web_stories_enable_print_feed_link', $enable_print_feed_link );\n\n\t\tif ( ! $enable_print_feed_link ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$name = $this->story_post_type->get_label( 'name' );\n\t\tif ( ! $name ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$feed = get_post_type_archive_feed_link( $this->story_post_type->get_slug() );\n\t\tif ( ! $feed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t/* translators: Separator between blog name and feed type in feed links. */\n\t\t$separator = _x( '&raquo;', 'feed link', 'web-stories' );\n\t\t/* translators: 1: Blog name, 2: Separator (raquo), 3: Post type name. */\n\t\t$post_type_title = esc_html__( '%1$s %2$s %3$s Feed', 'web-stories' );\n\n\t\t$title = \\sprintf( $post_type_title, get_bloginfo( 'name' ), $separator, $name );\n\n\t\tprintf(\n\t\t\t'<link rel=\"alternate\" type=\"%s\" title=\"%s\" href=\"%s\">',\n\t\t\tesc_attr( feed_content_type() ),\n\t\t\tesc_attr( $title ),\n\t\t\tesc_url( $feed )\n\t\t);\n\t}\n\n\t/**\n\t * Get schema.org metadata for the current query.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @see https://developers.google.com/search/docs/guides/enable-web-stories\n\t *\n\t * @return array<string,mixed> $metadata All schema.org metadata for the post.\n\t */\n\tprotected function get_schemaorg_metadata(): array {\n\t\t/**\n\t\t * We're expecting a post object.\n\t\t *\n\t\t * @var WP_Post|null $post\n\t\t */\n\t\t$post = get_queried_object();\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$metadata = [\n\t\t\t'@context'  => 'http://schema.org',\n\t\t\t'publisher' => [\n\t\t\t\t'@type' => 'Organization',\n\t\t\t\t'name'  => $story->get_publisher_name(),\n\t\t\t],\n\t\t];\n\n\t\tif ( $post instanceof WP_Post ) {\n\t\t\t$url  = $story->get_publisher_logo_url();\n\t\t\t$size = $story->get_publisher_logo_size();\n\t\t\tif ( ! empty( $url ) && ! empty( $size ) ) {\n\t\t\t\t$metadata['publisher']['logo'] = [\n\t\t\t\t\t'@type'  => 'ImageObject',\n\t\t\t\t\t'url'    => $url,\n\t\t\t\t\t'width'  => $size[0],\n\t\t\t\t\t'height' => $size[1],\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t$poster      = $story->get_poster_portrait();\n\t\t\t$poster_size = $story->get_poster_portrait_size();\n\t\t\tif ( $poster && $poster_size ) {\n\t\t\t\t$metadata['image'] = [\n\t\t\t\t\t'@type'  => 'ImageObject',\n\t\t\t\t\t'url'    => $poster,\n\t\t\t\t\t'width'  => $poster_size[0],\n\t\t\t\t\t'height' => $poster_size[1],\n\t\t\t\t];\n\n\t\t\t}\n\n\t\t\t$metadata = array_merge(\n\t\t\t\t$metadata,\n\t\t\t\t[\n\t\t\t\t\t'@type'            => 'Article',\n\t\t\t\t\t'mainEntityOfPage' => $story->get_url(),\n\t\t\t\t\t'headline'         => $story->get_title(),\n\t\t\t\t\t'datePublished'    => mysql2date( 'c', $post->post_date_gmt, false ),\n\t\t\t\t\t'dateModified'     => mysql2date( 'c', $post->post_modified_gmt, false ),\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$post_author = get_userdata( (int) $post->post_author );\n\n\t\t\tif ( $post_author ) {\n\t\t\t\t$metadata['author'] = [\n\t\t\t\t\t'@type' => 'Person',\n\t\t\t\t\t'name'  => html_entity_decode( $post_author->display_name, ENT_QUOTES, get_bloginfo( 'charset' ) ),\n\t\t\t\t];\n\t\t\t}\n\n\n\t\t\t/**\n\t\t\t * List of products.\n\t\t\t *\n\t\t\t * @phpstan-var Product[] $products\n\t\t\t */\n\t\t\t$products         = $story->get_products();\n\t\t\t$product_metadata = $this->get_product_data( $products );\n\t\t\tif ( $product_metadata ) {\n\t\t\t\t$metadata = array_merge( $product_metadata, $metadata );\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Filters the schema.org metadata for a given story.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array        $metadata The structured data.\n\t\t * @param WP_Post|null $post     The current post object if available.\n\t\t */\n\t\treturn apply_filters( 'web_stories_story_schema_metadata', $metadata, $post );\n\t}\n\n\t/**\n\t * Get product schema data.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param Product[] $products Array of products.\n\t * @return array<string, array<string, array<int, array<string, mixed>>|string>>\n\t *\n\t * @phpstan-param Product[] $products\n\t */\n\tprotected function get_product_data( array $products ): array {\n\t\tif ( ! $products ) {\n\t\t\treturn [];\n\t\t}\n\t\t$product_data = [];\n\t\tforeach ( $products as $product ) {\n\t\t\t$data = [\n\t\t\t\t'@type'       => 'Product',\n\t\t\t\t'brand'       => $product->get_brand(),\n\t\t\t\t'productID'   => $product->get_id(),\n\t\t\t\t'url'         => $product->get_url(),\n\t\t\t\t'name'        => $product->get_title(),\n\t\t\t\t'description' => $product->get_details(),\n\t\t\t\t'offers'      => [\n\t\t\t\t\t[\n\t\t\t\t\t\t'@type'         => 'Offer',\n\t\t\t\t\t\t'price'         => $product->get_price(),\n\t\t\t\t\t\t'priceCurrency' => $product->get_price_currency(),\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t];\n\t\t\tif ( $product->get_images() ) {\n\t\t\t\t$data['image'] = $product->get_images()[0]['url'];\n\t\t\t}\n\n\t\t\t$aggregate_rating = $product->get_aggregate_rating();\n\t\t\tif ( ! empty( $aggregate_rating['review_count'] ) ) {\n\t\t\t\t$data['aggregateRating'] = [\n\t\t\t\t\t'@type'       => 'AggregateRating',\n\t\t\t\t\t'ratingValue' => $aggregate_rating['rating_value'] ??= 0,\n\t\t\t\t\t'reviewCount' => $aggregate_rating['review_count'],\n\t\t\t\t\t'url'         => $aggregate_rating['review_url']   ??= '',\n\t\t\t\t];\n\t\t\t}\n\t\t\t$product_data[] = $data;\n\t\t}\n\n\t\treturn [\n\t\t\t'mainEntity' => [\n\t\t\t\t'@type'           => 'ItemList',\n\t\t\t\t'numberOfItems'   => (string) \\count( $products ),\n\t\t\t\t'itemListElement' => $product_data,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Get Open Graph metadata.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @return array<string, string|int>\n\t */\n\tprotected function get_open_graph_metadata(): array {\n\t\t$metadata = [\n\t\t\t'og:locale'    => get_bloginfo( 'language' ),\n\t\t\t'og:site_name' => get_bloginfo( 'name' ),\n\t\t];\n\n\t\t/**\n\t\t * We're expecting a post object.\n\t\t *\n\t\t * @var WP_Post|null $post\n\t\t */\n\t\t$post = get_queried_object();\n\n\t\tif ( $post instanceof WP_Post ) {\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $post );\n\n\t\t\t$metadata['og:type']                = 'article';\n\t\t\t$metadata['og:title']               = $story->get_title();\n\t\t\t$metadata['og:url']                 = $story->get_url();\n\t\t\t$metadata['og:description']         = wp_strip_all_tags( get_the_excerpt( $post ) );\n\t\t\t$metadata['article:published_time'] = (string) get_the_date( 'c', $post );\n\t\t\t$metadata['article:modified_time']  = (string) get_the_modified_date( 'c', $post );\n\n\t\t\t$poster_url   = $story->get_poster_portrait();\n\t\t\t$poster_sizes = $story->get_poster_portrait_size();\n\t\t\tif ( $poster_url && $poster_sizes ) {\n\t\t\t\t$metadata['og:image']        = esc_url( $poster_url );\n\t\t\t\t$metadata['og:image:width']  = $poster_sizes[0];\n\t\t\t\t$metadata['og:image:height'] = $poster_sizes[1];\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Filters the open graph metadata for a given story.\n\t\t *\n\t\t * @since 1.3.0\n\t\t *\n\t\t * @param array        $metadata The structured data.\n\t\t * @param WP_Post|null $post     The current post object if available.\n\t\t */\n\t\treturn apply_filters( 'web_stories_story_open_graph_metadata', $metadata, $post );\n\t}\n\n\t/**\n\t * Get Twitter card metadata.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @return array<string, string> Twitter card metadata.\n\t */\n\tprotected function get_twitter_metadata(): array {\n\t\t$metadata = [\n\t\t\t'twitter:card' => 'summary_large_image',\n\t\t];\n\n\t\t/**\n\t\t * We're expecting a post object.\n\t\t *\n\t\t * @var WP_Post|null $post\n\t\t */\n\t\t$post = get_queried_object();\n\n\t\tif ( $post instanceof WP_Post ) {\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $post );\n\t\t\t$poster = $story->get_poster_portrait();\n\t\t\tif ( $poster ) {\n\t\t\t\t$metadata['twitter:image']     = esc_url( $poster );\n\t\t\t\t$metadata['twitter:image:alt'] = $story->get_title();\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Filters the twitter metadata for a given story.\n\t\t *\n\t\t * @since 1.3.0\n\t\t *\n\t\t * @param array        $metadata The structured data.\n\t\t * @param WP_Post|null $post     The current post object if available.\n\t\t */\n\t\treturn apply_filters( 'web_stories_story_twitter_metadata', $metadata, $post );\n\t}\n}\n"
  },
  {
    "path": "includes/Embed_Base.php",
    "content": "<?php\n/**\n * Class Embed_Block.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Embed;\nuse Google\\Web_Stories\\Renderer\\Story\\Image;\nuse Google\\Web_Stories\\Renderer\\Story\\Singleton;\n\n/**\n * Embed block class.\n */\nabstract class Embed_Base extends Service_Base {\n\t/**\n\t * Script handle for frontend assets.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-embed';\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprotected Assets $assets;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprotected Context $context;\n\n\t/**\n\t * Embed Base constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Assets  $assets  Assets instance.\n\t * @param Context $context Context instance.\n\t */\n\tpublic function __construct( Assets $assets, Context $context ) {\n\t\t$this->assets  = $assets;\n\t\t$this->context = $context;\n\t}\n\n\t/**\n\t * Initializes the Web Stories embed block.\n\t *\n\t * @since 1.1.0\n\t */\n\tpublic function register(): void {\n\t\tif ( wp_style_is( self::SCRIPT_HANDLE, 'registered' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->assets->register_style_asset( self::SCRIPT_HANDLE );\n\n\t\tif ( \\defined( 'AMPFORWP_VERSION' ) ) {\n\t\t\tadd_action( 'amp_post_template_css', [ $this, 'add_amp_post_template_css' ] );\n\t\t}\n\n\t\tadd_filter( 'wp_kses_allowed_html', [ $this, 'filter_kses_allowed_html' ] );\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 11;\n\t}\n\n\t/**\n\t * Prints required inline CSS when using the AMP for WP plugin.\n\t *\n\t * @since 1.13.0\n\t */\n\tpublic function add_amp_post_template_css(): void {\n\t\t$path = $this->assets->get_base_path( \\sprintf( 'assets/css/%s%s.css', self::SCRIPT_HANDLE, is_rtl() ? '-rtl' : '' ) );\n\n\t\tif ( is_readable( $path ) ) {\n\t\t\t$css = file_get_contents( $path ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown\n\t\t\techo $css; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t}\n\t}\n\n\t/**\n\t * Filter the allowed tags for KSES to allow for amp-story children.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string, array<string,bool>>|mixed $allowed_tags Allowed tags.\n\t * @return array<string, array<string,bool>>|mixed Allowed tags.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($allowed_tags is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_kses_allowed_html( $allowed_tags ) {\n\t\tif ( ! \\is_array( $allowed_tags ) ) {\n\t\t\treturn $allowed_tags;\n\t\t}\n\n\t\t$story_player_components = [\n\t\t\t'amp-story-player' => [],\n\t\t];\n\n\t\t$allowed_tags = array_merge( $allowed_tags, $story_player_components );\n\n\t\treturn $allowed_tags;\n\t}\n\n\t/**\n\t * Renders a story with given attributes.\n\t *\n\t * @since 1.30.0\n\t *\n\t * @param Story                     $story      Story instance.\n\t * @param array<string, string|int> $attributes Embed render attributes.\n\t * @return string Rendered embed output.\n\t */\n\tpublic function render_story( Story $story, array $attributes ): string {\n\t\tif ( is_feed() ) {\n\t\t\t$renderer = new Image( $story );\n\t\t} elseif ( ! empty( $attributes['previewOnly'] ) ) {\n\t\t\t$renderer = new Singleton( $story, $this->assets );\n\t\t} else {\n\t\t\t$renderer = new Embed( $story, $this->assets, $this->context );\n\t\t}\n\n\t\treturn $renderer->render( $attributes );\n\t}\n\n\t/**\n\t * Renders an embed with given attributes.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param array<string, string|int> $attributes Embed render attributes.\n\t * @return string Rendered embed output.\n\t */\n\tpublic function render( array $attributes ): string {\n\t\t// The only mandatory attribute.\n\t\tif ( empty( $attributes['url'] ) && empty( $attributes['previewOnly'] ) ) {\n\t\t\treturn '';\n\t\t}\n\n\t\tif ( empty( $attributes['title'] ) ) {\n\t\t\t$attributes['title'] = __( 'Web Story', 'web-stories' );\n\t\t}\n\n\t\t$data = [\n\t\t\t'title'           => $attributes['title'],\n\t\t\t'url'             => $attributes['url'],\n\t\t\t'poster_portrait' => $attributes['poster'],\n\t\t];\n\n\t\t$story = new Story( $data );\n\n\t\treturn $this->render_story( $story, $attributes );\n\t}\n\n\t/**\n\t * Return an array of default attributes.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @return array<string, string|int> Default attributes.\n\t */\n\tprotected function default_attrs(): array {\n\t\t$attrs = [\n\t\t\t'align'       => 'none',\n\t\t\t'height'      => 600,\n\t\t\t'poster'      => '',\n\t\t\t'url'         => '',\n\t\t\t'title'       => '',\n\t\t\t'width'       => 360,\n\t\t\t'previewOnly' => false,\n\t\t];\n\n\t\t/**\n\t\t * Filters settings passed to the web stories embed.\n\t\t *\n\t\t * @since 1.1.0\n\t\t *\n\t\t * @param array $attrs Array of settings passed to web stories embed.\n\t\t */\n\t\treturn apply_filters( 'web_stories_embed_default_attributes', $attrs );\n\t}\n}\n"
  },
  {
    "path": "includes/Exception/FailedToMakeInstance.php",
    "content": "<?php\n/**\n * Exception FailedToMakeInstance.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Exception;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector\\InjectionChain;\nuse RuntimeException;\n\n/**\n * Exception thrown when the injector couldn't instantiate a given class or\n * interface.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class FailedToMakeInstance extends RuntimeException implements WebStoriesException {\n\n\t// These constants are public so you can use them to find out what exactly\n\t// happened when you catch a \"FailedToMakeInstance\" exception.\n\tpublic const CIRCULAR_REFERENCE             = 100;\n\tpublic const UNRESOLVED_INTERFACE           = 200;\n\tpublic const UNREFLECTABLE_CLASS            = 300;\n\tpublic const UNRESOLVED_ARGUMENT            = 400;\n\tpublic const UNINSTANTIATED_SHARED_INSTANCE = 500;\n\tpublic const INVALID_DELEGATE               = 600;\n\n\t/**\n\t * Create a new instance of the exception for an interface or class that\n\t * created a circular reference.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string         $interface_or_class         Interface or class name that\n\t *                                                   generated the circular\n\t *                                                   reference.\n\t * @param InjectionChain $injection_chain    Injection chain that led to the\n\t *                                           circular reference.\n\t */\n\tpublic static function for_circular_reference(\n\t\tstring $interface_or_class,\n\t\tInjectionChain $injection_chain\n\t): self {\n\t\t$message = \\sprintf(\n\t\t\t'Circular reference detected while trying to resolve the interface or class \"%s\".',\n\t\t\t$interface_or_class\n\t\t);\n\n\t\t$message .= \"\\nInjection chain:\\n\";\n\t\tforeach ( $injection_chain->get_chain() as $link ) {\n\t\t\t$message .= \"{$link}\\n\";\n\t\t}\n\n\t\treturn new self( $message, self::CIRCULAR_REFERENCE );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for an interface that could not\n\t * be resolved to an instantiable class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_name Interface that was left unresolved.\n\t */\n\tpublic static function for_unresolved_interface( string $interface_name ): self {\n\t\t$message = \\sprintf(\n\t\t\t'Could not resolve the interface \"%s\" to an instantiable class, probably forgot to bind an implementation.',\n\t\t\t$interface_name\n\t\t);\n\n\t\treturn new self( $message, self::UNRESOLVED_INTERFACE );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for an interface or class that\n\t * could not be reflected upon.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_or_class Interface or class that could not be\n\t *                                   reflected upon.\n\t */\n\tpublic static function for_unreflectable_class( string $interface_or_class ): self {\n\t\t$message = \\sprintf(\n\t\t\t'Could not reflect on the interface or class \"%s\", probably not a valid FQCN.',\n\t\t\t$interface_or_class\n\t\t);\n\n\t\treturn new self( $message, self::UNREFLECTABLE_CLASS );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for an argument that could not be\n\t * resolved.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $argument_name Name of the argument that could not be\n\t *                              resolved.\n\t * @param string $class_name    Class that had the argument in its\n\t *                              constructor.\n\t */\n\tpublic static function for_unresolved_argument( string $argument_name, string $class_name ): self {\n\t\t$message = \\sprintf(\n\t\t\t'Could not resolve the argument \"%s\" while trying to instantiate the class \"%s\".',\n\t\t\t$argument_name,\n\t\t\t$class_name\n\t\t);\n\n\t\treturn new self( $message, self::UNRESOLVED_ARGUMENT );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for a class that was meant to be\n\t * reused but was not yet instantiated.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class that was not yet instantiated.\n\t */\n\tpublic static function for_uninstantiated_shared_instance( string $class_name ): self {\n\t\t$message = \\sprintf(\n\t\t\t'Could not retrieve the shared instance for \"%s\" as it was not instantiated yet.',\n\t\t\t$class_name\n\t\t);\n\n\t\treturn new self( $message, self::UNINSTANTIATED_SHARED_INSTANCE );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for a delegate that was requested\n\t * for a class that doesn't have one.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class for which there is no delegate.\n\t */\n\tpublic static function for_invalid_delegate( string $class_name ): self {\n\t\t$message = \\sprintf(\n\t\t\t'Could not retrieve a delegate for \"%s\", none was defined.',\n\t\t\t$class_name\n\t\t);\n\n\t\treturn new self( $message, self::INVALID_DELEGATE );\n\t}\n}\n"
  },
  {
    "path": "includes/Exception/InvalidEventProperties.php",
    "content": "<?php\n/**\n * Exception InvalidEventProperties.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Exception;\n\nuse InvalidArgumentException;\n\n/**\n * Exception thrown when an invalid properties are added to an Event.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class InvalidEventProperties extends InvalidArgumentException implements WebStoriesException {\n\n\t/**\n\t * Create a new instance of the exception for a properties value that has\n\t * the wrong type.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param mixed $properties Properties value that has the wrong type.\n\t */\n\tpublic static function from_invalid_type( $properties ): self {\n\t\t$type = \\is_object( $properties )\n\t\t\t? \\get_class( $properties )\n\t\t\t: \\gettype( $properties );\n\n\t\t$message = \\sprintf(\n\t\t\t'The properties argument for adding properties to an event needs to be an array, but is of type %s',\n\t\t\t$type\n\t\t);\n\n\t\treturn new self( $message );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for a properties value that has\n\t * the wrong key type for one or more of its elements.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param mixed $property Property element that has the wrong type.\n\t */\n\tpublic static function from_invalid_element_key_type( $property ): self {\n\t\t$type = \\is_object( $property )\n\t\t\t? \\get_class( $property )\n\t\t\t: \\gettype( $property );\n\n\t\t$message = \\sprintf(\n\t\t\t'Each property element key for adding properties to an event needs to of type string, but found an element key of type %s',\n\t\t\t$type\n\t\t);\n\n\t\treturn new self( $message );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for a properties value that has\n\t * the wrong value type for one or more of its elements.\n\t *\n\t * @param mixed $property Property element that has the wrong type.\n\t */\n\tpublic static function from_invalid_element_value_type( $property ): self {\n\t\t$type = \\is_object( $property )\n\t\t\t? \\get_class( $property )\n\t\t\t: \\gettype( $property );\n\n\t\t$message = \\sprintf(\n\t\t\t'Each property element value for adding properties to an event needs to be a scalar value, but found an element value of type %s',\n\t\t\t$type\n\t\t);\n\n\t\treturn new self( $message );\n\t}\n}\n"
  },
  {
    "path": "includes/Exception/InvalidService.php",
    "content": "<?php\n/**\n * Exception InvalidService.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Exception;\n\nuse InvalidArgumentException;\n\n/**\n * Exception thrown when an invalid service was requested.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class InvalidService extends InvalidArgumentException implements WebStoriesException {\n\n\t/**\n\t * Create a new instance of the exception for a service class name that is\n\t * not recognized.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string|object $service Class name of the service that was not\n\t *                               recognized.\n\t */\n\tpublic static function from_service( $service ): self {\n\t\t$message = \\sprintf(\n\t\t\t'The service \"%s\" is not recognized and cannot be registered.',\n\t\t\t\\is_object( $service )\n\t\t\t\t? \\get_class( $service )\n\t\t\t\t: (string) $service\n\t\t);\n\n\t\treturn new self( $message );\n\t}\n\n\t/**\n\t * Create a new instance of the exception for a service identifier that is\n\t * not recognized.\n\t *\n\t * @param string $service_id Identifier of the service that is not being\n\t *                           recognized.\n\t */\n\tpublic static function from_service_id( string $service_id ): self {\n\t\t$message = \\sprintf(\n\t\t\t'The service ID \"%s\" is not recognized and cannot be retrieved.',\n\t\t\t$service_id\n\t\t);\n\n\t\treturn new self( $message );\n\t}\n}\n"
  },
  {
    "path": "includes/Exception/SanitizationException.php",
    "content": "<?php\n/**\n * Exception SanitizationException.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Exception;\n\nuse RuntimeException;\n\n/**\n * Exception thrown when AMP sanitization errors.\n *\n * @internal\n *\n * @since 1.10.0\n */\nfinal class SanitizationException extends RuntimeException implements WebStoriesException {\n\n\t/**\n\t * Create a new instance of the exception for a document that cannot be parsed.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic static function from_document_parse_error(): self {\n\t\treturn new self( 'The markup could not be parsed into a DOMDocument.' );\n\t}\n}\n"
  },
  {
    "path": "includes/Exception/WebStoriesException.php",
    "content": "<?php\n/**\n * Interface WebStoriesException.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Exception;\n\n/**\n * This is a \"marker interface\" to mark all the exceptions that come with this\n * plugin with this one interface.\n *\n * This allows you to not only catch individual exceptions, but also catch \"all\n * exceptions from the Web_Stories plugin\".\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface WebStoriesException {\n\n}\n"
  },
  {
    "path": "includes/Experiments.php",
    "content": "<?php\n/**\n * Class Experiments\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\n\n/**\n * Experiments class.\n *\n * Allows turning flags on/off via the admin UI.\n *\n * @phpstan-type Experiment array{\n *   name: string,\n *   label: string,\n *   description: string,\n *   group: string,\n *   default?: bool\n * }\n */\nclass Experiments extends Service_Base implements HasRequirements {\n\t/**\n\t * Settings page name.\n\t */\n\tpublic const PAGE_NAME = 'web-stories-experiments';\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Experiments constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Initializes experiments\n\t */\n\tpublic function register(): void {\n\t\tif ( WEBSTORIES_DEV_MODE ) {\n\t\t\tadd_action( 'admin_menu', [ $this, 'add_menu_page' ], 25 );\n\t\t\tadd_action( 'admin_init', [ $this, 'initialize_settings' ] );\n\t\t}\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Registers the experiments admin menu page.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function add_menu_page(): void {\n\t\tadd_submenu_page(\n\t\t\t'edit.php?post_type=' . Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t__( 'Experiments', 'web-stories' ),\n\t\t\t__( 'Experiments', 'web-stories' ),\n\t\t\t'manage_options',\n\t\t\t'web-stories-experiments',\n\t\t\t[ $this, 'render' ],\n\t\t\t25\n\t\t);\n\t}\n\n\t/**\n\t * Renders the experiments page.\n\t *\n\t * @codeCoverageIgnore\n\t */\n\tpublic function render(): void {\n\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/admin/experiments.php';\n\t}\n\n\t/**\n\t * Initializes the experiments settings page.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function initialize_settings(): void {\n\t\tadd_settings_section(\n\t\t\t'web_stories_experiments_section',\n\t\t\t// The empty string ensures the render function won't output a h2.\n\t\t\t'',\n\t\t\t[ $this, 'display_experiment_section' ],\n\t\t\tself::PAGE_NAME\n\t\t);\n\n\t\tforeach ( $this->get_experiment_groups() as $group => $label ) {\n\t\t\tadd_settings_section(\n\t\t\t\t$group,\n\t\t\t\t$label,\n\t\t\t\t'__return_empty_string',\n\t\t\t\tself::PAGE_NAME\n\t\t\t);\n\t\t}\n\n\t\t$experiments = $this->get_experiments();\n\n\t\tforeach ( $experiments as $experiment ) {\n\t\t\tadd_settings_field(\n\t\t\t\t$experiment['name'],\n\t\t\t\t$experiment['label'],\n\t\t\t\t[ $this, 'display_experiment_field' ],\n\t\t\t\tself::PAGE_NAME,\n\t\t\t\t$experiment['group'],\n\t\t\t\t[\n\t\t\t\t\t'label'   => $experiment['description'],\n\t\t\t\t\t'id'      => $experiment['name'],\n\t\t\t\t\t'default' => \\array_key_exists( 'default', $experiment ) && $experiment['default'],\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Display a checkbox field for a single experiment.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array $args {\n\t *     Array of arguments for displaying a single field.\n\t *\n\t *     @type string $id      Experiment ID.\n\t *     @type string $label   Experiment label.\n\t *     @type bool   $default Whether the experiment is enabled by default.\n\t * }\n\t *\n\t * @phpstan-param array{id: string, label: string, default: bool} $args\n\t */\n\tpublic function display_experiment_field( array $args ): void {\n\t\t$is_enabled_by_default = ! empty( $args['default'] );\n\t\t$checked               = $is_enabled_by_default || $this->is_experiment_enabled( $args['id'] );\n\t\t$disabled              = $is_enabled_by_default ? 'disabled' : '';\n\t\t?>\n\t\t<label for=\"<?php echo esc_attr( $args['id'] ); ?>\">\n\t\t\t<input\n\t\t\t\ttype=\"checkbox\"\n\t\t\t\tname=\"<?php echo esc_attr( \\sprintf( '%1$s[%2$s]', $this->settings::SETTING_NAME_EXPERIMENTS, $args['id'] ) ); ?>\"\n\t\t\t\tid=\"<?php echo esc_attr( $args['id'] ); ?>\"\n\t\t\t\tvalue=\"1\"\n\t\t\t\t<?php echo esc_attr( $disabled ); ?>\n\t\t\t\t<?php checked( $checked ); ?>\n\t\t\t/>\n\t\t\t<?php echo esc_html( $args['label'] ); ?>\n\t\t</label>\n\t\t<?php\n\t}\n\n\t/**\n\t * Display the experiments section.\n\t *\n\t * @codeCoverageIgnore\n\t */\n\tpublic function display_experiment_section(): void {\n\t\t?>\n\t\t<p>\n\t\t\t<?php\n\t\t\tesc_html_e( \"The Web Stories editor includes experimental features that are useable while they're in development. Select the ones you'd like to enable. These features are likely to change, so avoid using them in production.\", 'web-stories' );\n\t\t\t?>\n\t\t</p>\n\t\t<?php\n\t}\n\n\t/**\n\t * Returns all available experiment groups.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string,string> List of experiment groups\n\t */\n\tpublic function get_experiment_groups(): array {\n\t\treturn [\n\t\t\t'general'   => __( 'General', 'web-stories' ),\n\t\t\t'dashboard' => __( 'Dashboard', 'web-stories' ),\n\t\t\t'editor'    => __( 'Editor', 'web-stories' ),\n\t\t];\n\t}\n\n\t/**\n\t * Returns a list of all experiments.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array List of experiments by group.\n\t *\n\t * @phpstan-return Experiment[]\n\t */\n\tpublic function get_experiments(): array {\n\t\treturn [\n\t\t\t/**\n\t\t\t * Author: @brittanyirl\n\t\t\t * Issue: 2381\n\t\t\t * Creation date: 2020-06-11\n\t\t\t */\n\t\t\t[\n\t\t\t\t'name'        => 'enableInProgressTemplateActions',\n\t\t\t\t'label'       => __( 'Template actions', 'web-stories' ),\n\t\t\t\t'description' => __( 'Enable in-progress template actions', 'web-stories' ),\n\t\t\t\t'group'       => 'dashboard',\n\t\t\t],\n\t\t\t/**\n\t\t\t * Author: @spacedmonkey\n\t\t\t * Issue: #798\n\t\t\t * Creation date: 2020-11-02\n\t\t\t */\n\t\t\t[\n\t\t\t\t'name'        => 'enableSVG',\n\t\t\t\t'label'       => __( 'SVG upload', 'web-stories' ),\n\t\t\t\t'description' => __( 'Enable SVG upload', 'web-stories' ),\n\t\t\t\t'group'       => 'general',\n\t\t\t],\n\t\t\t/**\n\t\t\t * Author: @timarney\n\t\t\t * Issue: #12093\n\t\t\t * Creation date: 2022-08-18\n\t\t\t */\n\t\t\t[\n\t\t\t\t'name'        => 'offScreenVideoCropping',\n\t\t\t\t'label'       => __( 'Crop off-screen video parts', 'web-stories' ),\n\t\t\t\t'description' => __( 'Enable support for cropping cut off-screen parts of videos', 'web-stories' ),\n\t\t\t\t'group'       => 'editor',\n\t\t\t],\n\t\t\t/**\n\t\t\t * Author: @spacedmonkey\n\t\t\t * Issue: #12211\n\t\t\t * Creation date: 2022-09-07\n\t\t\t */\n\t\t\t[\n\t\t\t\t'name'        => 'videoVolume',\n\t\t\t\t'label'       => __( 'Video Volume', 'web-stories' ),\n\t\t\t\t'description' => __( 'Enable setting video volume', 'web-stories' ),\n\t\t\t\t'group'       => 'editor',\n\t\t\t],\n\t\t\t/**\n\t\t\t * Author: @timarney\n\t\t\t * Issue: #12164\n\t\t\t * Creation date: 2022-09-19\n\t\t\t */\n\t\t\t[\n\t\t\t\t'name'        => 'segmentVideo',\n\t\t\t\t'label'       => __( 'Segment video', 'web-stories' ),\n\t\t\t\t'description' => __( 'Enable support for segmenting video files', 'web-stories' ),\n\t\t\t\t'group'       => 'editor',\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Returns the experiment statuses for a given group.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $group Experiments group name.\n\t * @return array<string,bool> Experiment statuses with name as key and status as value.\n\t */\n\tpublic function get_experiment_statuses( string $group ): array {\n\t\t/**\n\t\t * List of experiments.\n\t\t *\n\t\t * @phpstan-var Experiment[]\n\t\t */\n\t\t$experiments = wp_list_filter( $this->get_experiments(), [ 'group' => $group ] );\n\n\t\tif ( empty( $experiments ) ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t$result = [];\n\n\t\tforeach ( $experiments as $experiment ) {\n\t\t\t$result[ $experiment['name'] ] = $this->is_experiment_enabled( $experiment['name'] );\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t/**\n\t * Checks whether an experiment is enabled.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $name Experiment name.\n\t * @return bool Whether the experiment is enabled.\n\t */\n\tpublic function is_experiment_enabled( string $name ): bool {\n\t\t$experiment = $this->get_experiment( $name );\n\n\t\tif ( ! $experiment ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( \\array_key_exists( 'default', $experiment ) ) {\n\t\t\treturn (bool) $experiment['default'];\n\t\t}\n\n\t\t/**\n\t\t * List of enabled experiments.\n\t\t *\n\t\t * @var array<string, array> $experiments\n\t\t * @phpstan-var Experiment[]\n\t\t */\n\t\t$experiments = $this->settings->get_setting( $this->settings::SETTING_NAME_EXPERIMENTS, [] );\n\t\treturn ! empty( $experiments[ $name ] );\n\t}\n\n\t/**\n\t * Returns the names of all enabled experiments.\n\t *\n\t * @since 1.4.0\n\t *\n\t * @return string[] List of all enabled experiments.\n\t */\n\tpublic function get_enabled_experiments(): array {\n\t\treturn array_filter(\n\t\t\twp_list_pluck( $this->get_experiments(), 'name' ),\n\t\t\t[ $this, 'is_experiment_enabled' ]\n\t\t);\n\t}\n\n\t/**\n\t * Returns an experiment by name.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $name Experiment name.\n\t * @return array|null Experiment if found, null otherwise.\n\t *\n\t * @phpstan-return Experiment|null\n\t */\n\tprotected function get_experiment( string $name ): ?array {\n\t\t$experiment = wp_list_filter( $this->get_experiments(), [ 'name' => $name ] );\n\t\treturn ! empty( $experiment ) ? array_shift( $experiment ) : null;\n\t}\n}\n"
  },
  {
    "path": "includes/Font_Post_Type.php",
    "content": "<?php\n/**\n * Class Font_Post_Type.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\REST_API\\Font_Controller;\n\n/**\n * Class Font_Post_Type.\n *\n * @phpstan-import-type PostTypeArgs from \\Google\\Web_Stories\\Post_Type_Base\n */\nclass Font_Post_Type extends Post_Type_Base implements HasRequirements {\n\n\t/**\n\t * The slug of the font post type.\n\t */\n\tpublic const POST_TYPE_SLUG = 'web-story-font';\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Font_Post_Type constructor.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Get post type slug.\n\t *\n\t * @since 1.16.0\n\t */\n\tpublic function get_slug(): string {\n\t\treturn self::POST_TYPE_SLUG;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers the post type for fonts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return array<string, mixed> Post type args.\n\t *\n\t * @phpstan-return PostTypeArgs\n\t */\n\tprotected function get_args(): array {\n\t\t/**\n\t\t * The edit_posts capability.\n\t\t *\n\t\t * @var string $edit_posts\n\t\t */\n\t\t$edit_posts = $this->story_post_type->get_cap_name( 'edit_posts' );\n\n\t\t// Only admins are allowed to modify custom fonts,\n\t\t// but anyone who can create stories should be able to use them.\n\t\t$capabilities = [\n\t\t\t'edit_post'              => 'manage_options',\n\t\t\t'read_post'              => $edit_posts,\n\t\t\t'delete_post'            => 'manage_options',\n\t\t\t'edit_posts'             => 'manage_options',\n\t\t\t'edit_others_posts'      => 'manage_options',\n\t\t\t'delete_posts'           => 'manage_options',\n\t\t\t'publish_posts'          => 'manage_options',\n\t\t\t'read_private_posts'     => 'manage_options',\n\t\t\t'delete_private_posts'   => 'manage_options',\n\t\t\t'delete_published_posts' => 'manage_options',\n\t\t\t'delete_others_posts'    => 'manage_options',\n\t\t\t'edit_private_posts'     => 'manage_options',\n\t\t\t'edit_published_posts'   => 'manage_options',\n\t\t\t'create_posts'           => 'manage_options',\n\t\t];\n\n\t\treturn [\n\t\t\t'supports'              => [\n\t\t\t\t'title',\n\t\t\t],\n\t\t\t'capabilities'          => $capabilities,\n\t\t\t'rewrite'               => false,\n\t\t\t'public'                => false,\n\t\t\t'show_ui'               => false,\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t\t'rest_base'             => 'fonts',\n\t\t\t'rest_controller_class' => Font_Controller::class,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/Conditional.php",
    "content": "<?php\n/**\n * Interface Conditional.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that can be instantiated conditionally.\n *\n * A class marked as being conditionally can be asked whether it should be\n * instantiated through a static method. An example would be a service that is\n * only available on the admin backend.\n *\n * This allows for a more systematic and automated optimization of how the\n * different parts of the plugin are enabled or disabled.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface Conditional {\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool;\n}\n"
  },
  {
    "path": "includes/Infrastructure/Delayed.php",
    "content": "<?php\n/**\n * Interface Delayed.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that is delayed to a later point in the execution flow.\n *\n * A class marked as being delayed can return the action at which it requires\n * to be registered.\n *\n * This can be used to only register a given object after certain contextual\n * requirements are met, like registering a frontend rendering service only\n * after the loop has been set up.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface Delayed {\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string;\n\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int;\n}\n"
  },
  {
    "path": "includes/Infrastructure/HasMeta.php",
    "content": "<?php\n/**\n * Interface HasMeta.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Class registers meta.\n *\n * @internal\n *\n * @since 1.15.0\n */\ninterface HasMeta {\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function register_meta(): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/HasRequirements.php",
    "content": "<?php\n/**\n * Interface HasRequirements.\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that requires other services to be registered before it can be registered.\n *\n * A class marked as having requirements can return the list of services it requires\n * to be available before it can be registered.\n *\n * @internal\n *\n * @since 1.10.0\n */\ninterface HasRequirements {\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array;\n}\n"
  },
  {
    "path": "includes/Infrastructure/Injector/FallbackInstantiator.php",
    "content": "<?php\n/**\n * Final class FallbackInstantiator.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure\\Injector;\n\nuse Google\\Web_Stories\\Infrastructure\\Instantiator;\n\n/**\n * Fallback instantiator to use in case none was provided.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class FallbackInstantiator implements Instantiator {\n\n\t/**\n\t * Make an object instance out of an interface or class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param class-string      $class_name   Class to make an object instance out of.\n\t * @param array<int, mixed> $dependencies Optional. Dependencies of the class.\n\t * @return T Instantiated object.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-param class-string<T> $class_name Class to make an object instance out of.\n\t */\n\tpublic function instantiate( string $class_name, array $dependencies = [] ) {\n\t\treturn new $class_name( ...$dependencies );\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/Injector/InjectionChain.php",
    "content": "<?php\n/**\n * Final class InjectionChain.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure\\Injector;\n\n/**\n * The injection chain is similar to a trace, keeping track of what we have done\n * so far and at what depth within the auto-wiring we currently are.\n *\n * It is used to detect circular dependencies, and can also be dumped for\n * debugging information.\n *\n * @internal\n *\n * @since 1.6.0\n *\n * @template T\n */\nfinal class InjectionChain {\n\n\t/**\n\t * Chain.\n\t *\n\t * @var string[]\n\t * @phpstan-var class-string<T>[]\n\t */\n\tprivate array $chain = [];\n\n\t/**\n\t * Resolutions.\n\t *\n\t * @var array<bool>\n\t * @phpstan-var array<class-string, bool>\n\t */\n\tprivate array $resolutions = [];\n\n\t/**\n\t * Add class to injection chain.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class to add to injection chain.\n\t * @return self Modified injection chain.\n\t *\n\t * @phpstan-param class-string<T> $class_name\n\t */\n\tpublic function add_to_chain( string $class_name ): self {\n\t\t$new_chain          = clone $this;\n\t\t$new_chain->chain[] = $class_name;\n\n\t\treturn $new_chain;\n\t}\n\n\t/**\n\t * Add resolution for circular reference detection.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $resolution Resolution to add.\n\t * @return self Modified injection chain.\n\t *\n\t * @phpstan-param class-string $resolution\n\t */\n\tpublic function add_resolution( string $resolution ): self {\n\t\t$new_chain                             = clone $this;\n\t\t$new_chain->resolutions[ $resolution ] = true;\n\n\t\treturn $new_chain;\n\t}\n\n\t/**\n\t * Get the last class that was pushed to the injection chain.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws \\LogicException If the injection chain is accessed too early.\n\t *\n\t * @return string Last class pushed to the injection chain.\n\t *\n\t * @phpstan-return class-string<T>\n\t */\n\tpublic function get_class(): string {\n\t\tif ( empty( $this->chain ) ) {\n\t\t\tthrow new \\LogicException(\n\t\t\t\t'Access to injection chain before any resolution was made.'\n\t\t\t);\n\t\t}\n\n\t\treturn \\end( $this->chain ) ?: '';\n\t}\n\n\t/**\n\t * Get the injection chain.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string[] Chain of injections.\n\t *\n\t * @phpstan-return class-string[]\n\t */\n\tpublic function get_chain(): array {\n\t\treturn \\array_reverse( $this->chain );\n\t}\n\n\t/**\n\t * Check whether the injection chain already has a given resolution.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $resolution Resolution to check for.\n\t * @return bool Whether the resolution was found.\n\t *\n\t * @phpstan-param class-string<T> $resolution\n\t */\n\tpublic function has_resolution( string $resolution ): bool {\n\t\treturn \\array_key_exists( $resolution, $this->resolutions );\n\t}\n\n\t/**\n\t * Check whether the injection chain already encountered a class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class to check.\n\t * @return bool Whether the given class is already part of the chain.\n\t */\n\tpublic function is_in_chain( string $class_name ): bool {\n\t\treturn \\in_array( $class_name, $this->chain, true );\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/Injector/SimpleInjector.php",
    "content": "<?php\n/**\n * Final class SimpleInjector.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure\\Injector;\n\nuse Google\\Web_Stories\\Exception\\FailedToMakeInstance;\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\Instantiator;\nuse ReflectionClass;\nuse ReflectionNamedType;\nuse ReflectionParameter;\nuse function array_map;\n\n/**\n * A simplified implementation of a dependency injector.\n *\n * @internal\n *\n * @since 1.6.0\n *\n * @template T\n */\nfinal class SimpleInjector implements Injector {\n\t/**\n\t * Mappings.\n\t *\n\t * @var string[]\n\t * @phpstan-var class-string<T>[]\n\t */\n\tprivate array $mappings = [];\n\n\t/**\n\t * Shared instances\n\t *\n\t * @var array<T|null>\n\t */\n\tprivate array $shared_instances = [];\n\n\t/**\n\t * Delegates.\n\t *\n\t * @var callable[]\n\t */\n\tprivate array $delegates = [];\n\n\t/**\n\t * Argument mappings.\n\t *\n\t * @var array<string, array<mixed>>\n\t */\n\tprivate array $argument_mappings = [];\n\n\t/**\n\t * Instantiator.\n\t *\n\t * @var Instantiator<T>\n\t */\n\tprivate Instantiator $instantiator;\n\n\t/**\n\t * Instantiate a SimpleInjector object.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param Instantiator|null $instantiator Optional. Instantiator to use.\n\t */\n\tpublic function __construct( ?Instantiator $instantiator = null ) {\n\t\t$this->instantiator = $instantiator ?? new FallbackInstantiator();\n\t}\n\n\t/**\n\t * Make an object instance out of an interface or class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string               $interface_or_class Interface or class to make an object instance out of.\n\t * @param array<string, mixed> $arguments    Optional. Additional arguments to pass to the constructor.\n\t *                                    Defaults to an empty array.\n\t * @return T Instantiated object.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to make an object instance out of.\n\t * @phpstan-param array<string, mixed>  $arguments          Optional. Additional arguments to pass to the constructor.\n\t */\n\tpublic function make( string $interface_or_class, array $arguments = [] ) {\n\t\t$injection_chain = $this->resolve(\n\t\t\tnew InjectionChain(),\n\t\t\t$interface_or_class\n\t\t);\n\n\t\t$class = $injection_chain->get_class();\n\n\t\tif ( $this->has_shared_instance( $class ) ) {\n\t\t\treturn $this->get_shared_instance( $class );\n\t\t}\n\n\t\tif ( $this->has_delegate( $class ) ) {\n\t\t\t$delegate = $this->get_delegate( $class );\n\t\t\t$object   = $delegate( $class );\n\t\t} else {\n\t\t\t$reflection = $this->get_class_reflection( $class );\n\t\t\t$this->ensure_is_instantiable( $reflection );\n\n\t\t\t$dependencies = $this->get_dependencies_for(\n\t\t\t\t$injection_chain,\n\t\t\t\t$reflection,\n\t\t\t\t$arguments\n\t\t\t);\n\n\t\t\t$object = $this->instantiator->instantiate( $class, $dependencies );\n\t\t}\n\n\t\tif ( \\array_key_exists( $class, $this->shared_instances ) ) {\n\t\t\t$this->shared_instances[ $class ] = $object;\n\t\t}\n\n\t\treturn $object;\n\t}\n\n\t/**\n\t * Bind a given interface or class to an implementation.\n\t *\n\t * Note: The implementation can be an interface as well, as long as it can\n\t * be resolved to an instantiatable class at runtime.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $from Interface or class to bind an implementation to.\n\t * @param string $to Interface or class that provides the implementation.\n\t *\n\t * @phpstan-param class-string<T> $from Interface or class to bind an implementation to.\n\t * @phpstan-param class-string<T> $to   Interface or class that provides the implementation.\n\t */\n\tpublic function bind( string $from, string $to ): Injector {\n\t\t$this->mappings[ $from ] = $to;\n\n\t\treturn $this;\n\t}\n\n\t/**\n\t * Bind an argument for a class to a specific value.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_or_class Interface or class to bind an argument for.\n\t * @param string $argument_name Argument name to bind a value to.\n\t * @param mixed  $value Value to bind the argument to.\n\t */\n\tpublic function bind_argument(\n\t\tstring $interface_or_class,\n\t\tstring $argument_name,\n\t\t$value\n\t): Injector {\n\t\t$this->argument_mappings[ $interface_or_class ][ $argument_name ] = $value;\n\n\t\treturn $this;\n\t}\n\n\t/**\n\t * Always reuse and share the same instance for the provided interface or\n\t * class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_or_class Interface or class to reuse.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to reuse.\n\t */\n\tpublic function share( string $interface_or_class ): Injector {\n\t\t$this->shared_instances[ $interface_or_class ] = null;\n\n\t\treturn $this;\n\t}\n\n\t/**\n\t * Delegate instantiation of an interface or class to a callable.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string   $interface_or_class Interface or class to delegate the instantiation of.\n\t * @param callable $callback           Callable to use for instantiation.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to delegate the instantiation of.\n\t */\n\tpublic function delegate( string $interface_or_class, callable $callback ): Injector {\n\t\t$this->delegates[ $interface_or_class ] = $callback;\n\n\t\treturn $this;\n\t}\n\n\t/**\n\t * Make an object instance out of an interface or class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param InjectionChain $injection_chain    Injection chain to track resolutions.\n\t * @param string         $interface_or_class Interface or class to make an object instance out of.\n\t * @return T Instantiated object.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to make an object instance out of.\n\t */\n\tprivate function make_dependency(\n\t\tInjectionChain $injection_chain,\n\t\tstring $interface_or_class\n\t) {\n\t\t$injection_chain = $this->resolve(\n\t\t\t$injection_chain,\n\t\t\t$interface_or_class\n\t\t);\n\n\t\t$class = $injection_chain->get_class();\n\n\t\tif ( $this->has_shared_instance( $class ) ) {\n\t\t\treturn $this->get_shared_instance( $class );\n\t\t}\n\n\t\tif ( $this->has_delegate( $class ) ) {\n\t\t\t$delegate = $this->get_delegate( $class );\n\t\t\treturn $delegate( $class );\n\t\t}\n\n\t\t$reflection = $this->get_class_reflection( $class );\n\t\t$this->ensure_is_instantiable( $reflection );\n\n\t\t$dependencies = $this->get_dependencies_for(\n\t\t\t$injection_chain,\n\t\t\t$reflection\n\t\t);\n\n\t\t$object = $this->instantiator->instantiate( $class, $dependencies );\n\n\t\tif ( \\array_key_exists( $class, $this->shared_instances ) ) {\n\t\t\t$this->shared_instances[ $class ] = $object;\n\t\t}\n\n\t\treturn $object;\n\t}\n\n\t/**\n\t * Recursively resolve an interface to the class it should be bound to.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If a circular reference was detected.\n\t *\n\t * @param InjectionChain $injection_chain    Injection chain to track resolutions.\n\t * @param string         $interface_or_class Interface or class to resolve.\n\t * @return InjectionChain Modified Injection chain\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to resolve.\n\t */\n\tprivate function resolve(\n\t\tInjectionChain $injection_chain,\n\t\tstring $interface_or_class\n\t): InjectionChain {\n\t\tif ( $injection_chain->is_in_chain( $interface_or_class ) ) {\n\t\t\t// Circular reference detected, aborting.\n\t\t\tthrow FailedToMakeInstance::for_circular_reference(\n\t\t\t\t$interface_or_class, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t\t\t$injection_chain // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t\t);\n\t\t}\n\n\t\t$injection_chain = $injection_chain->add_resolution( $interface_or_class );\n\n\t\tif ( \\array_key_exists( $interface_or_class, $this->mappings ) ) {\n\t\t\treturn $this->resolve(\n\t\t\t\t$injection_chain,\n\t\t\t\t$this->mappings[ $interface_or_class ]\n\t\t\t);\n\t\t}\n\n\t\treturn $injection_chain->add_to_chain( $interface_or_class );\n\t}\n\n\t/**\n\t * Get the array of constructor dependencies for a given reflected class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param InjectionChain       $injection_chain Injection chain to track resolutions.\n\t * @param ReflectionClass      $reflection      Reflected class to get the dependencies for.\n\t * @param array<string, mixed> $arguments       Associative array of directly provided arguments.\n\t * @return array<int, mixed> Array of dependencies that represent the arguments for the class' constructor.\n\t */\n\tprivate function get_dependencies_for(\n\t\tInjectionChain $injection_chain,\n\t\tReflectionClass $reflection,\n\t\tarray $arguments = []\n\t): array {\n\t\t$constructor = $reflection->getConstructor();\n\t\t$class       = $reflection->getName();\n\n\t\tif ( null === $constructor ) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn array_map(\n\t\t\tfn( ReflectionParameter $parameter ) => $this->resolve_argument(\n\t\t\t\t$injection_chain,\n\t\t\t\t$class,\n\t\t\t\t$parameter,\n\t\t\t\t$arguments\n\t\t\t),\n\t\t\t$constructor->getParameters()\n\t\t);\n\t}\n\n\t/**\n\t * Ensure that a given reflected class is instantiable.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If the interface could not be resolved.\n\t *\n\t * @param ReflectionClass $reflection Reflected class to check.\n\t */\n\tprivate function ensure_is_instantiable( ReflectionClass $reflection ): void {\n\t\tif ( ! $reflection->isInstantiable() ) {\n\t\t\tthrow FailedToMakeInstance::for_unresolved_interface( $reflection->getName() ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\t}\n\n\t/**\n\t * Resolve a given reflected argument.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param InjectionChain       $injection_chain Injection chain to track resolutions.\n\t * @param string               $class_name      Name of the class to resolve the arguments for.\n\t * @param ReflectionParameter  $parameter       Parameter to resolve.\n\t * @param array<string, mixed> $arguments       Associative array of directly provided arguments.\n\t * @return mixed Resolved value of the argument.\n\t */\n\tprivate function resolve_argument(\n\t\tInjectionChain $injection_chain,\n\t\tstring $class_name,\n\t\tReflectionParameter $parameter,\n\t\tarray $arguments\n\t) {\n\t\tif ( ! $parameter->hasType() ) {\n\t\t\treturn $this->resolve_argument_by_name(\n\t\t\t\t$class_name,\n\t\t\t\t$parameter,\n\t\t\t\t$arguments\n\t\t\t);\n\t\t}\n\n\t\t$type = $parameter->getType();\n\n\t\t// In PHP 8.0, the isBuiltin method was removed from the parent {@see ReflectionType} class.\n\n\t\t// @phpstan-ignore identical.alwaysFalse\n\t\tif ( null === $type || ( $type instanceof ReflectionNamedType && $type->isBuiltin() ) ) {\n\t\t\treturn $this->resolve_argument_by_name(\n\t\t\t\t$class_name,\n\t\t\t\t$parameter,\n\t\t\t\t$arguments\n\t\t\t);\n\t\t}\n\n\t\t/**\n\t\t * Interface or class.\n\t\t *\n\t\t * @var class-string<T> $type\n\t\t */\n\t\t$type = $type instanceof ReflectionNamedType\n\t\t\t? $type->getName()\n\t\t\t: (string) $type;\n\n\t\treturn $this->make_dependency( $injection_chain, $type );\n\t}\n\n\t/**\n\t * Resolve a given reflected argument by its name.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If the argument could not be resolved.\n\t *\n\t * @param string               $class_name Class to resolve the argument for.\n\t * @param ReflectionParameter  $parameter  Argument to resolve by name.\n\t * @param array<string, mixed> $arguments  Associative array of directly provided arguments.\n\t * @return mixed Resolved value of the argument.\n\t */\n\tprivate function resolve_argument_by_name(\n\t\tstring $class_name,\n\t\tReflectionParameter $parameter,\n\t\tarray $arguments\n\t) {\n\t\t$name = $parameter->getName();\n\n\t\t// The argument was directly provided to the make() call.\n\t\tif ( \\array_key_exists( $name, $arguments ) ) {\n\t\t\treturn $arguments[ $name ];\n\t\t}\n\n\t\t// Check if we have mapped this argument for the specific class.\n\t\tif ( \\array_key_exists( $class_name, $this->argument_mappings )\n\t\t\t&& \\array_key_exists( $name, $this->argument_mappings[ $class_name ] ) ) {\n\t\t\t$value = $this->argument_mappings[ $class_name ][ $name ];\n\n\t\t\t// Closures are immediately resolved, to provide lazy resolution.\n\t\t\tif ( \\is_callable( $value ) ) {\n\t\t\t\t$value = $value( $class_name, $parameter, $arguments );\n\t\t\t}\n\n\t\t\treturn $value;\n\t\t}\n\n\t\t// No provided argument found, check if it has a default value.\n\t\ttry {\n\t\t\tif ( $parameter->isDefaultValueAvailable() ) {\n\t\t\t\treturn $parameter->getDefaultValue();\n\t\t\t}\n\t\t} catch ( \\Exception $exception ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch\n\t\t\t// Just fall through into the FailedToMakeInstance exception.\n\t\t}\n\n\t\t// Out of options, fail with an exception.\n\t\tthrow FailedToMakeInstance::for_unresolved_argument( $name, $class_name ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t}\n\n\t/**\n\t * Check whether a shared instance exists for a given class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class to check for a shared instance.\n\t * @return bool Whether a shared instance exists.\n\t */\n\tprivate function has_shared_instance( string $class_name ): bool {\n\t\treturn \\array_key_exists( $class_name, $this->shared_instances )\n\t\t\t&& null !== $this->shared_instances[ $class_name ];\n\t}\n\n\t/**\n\t * Get the shared instance for a given class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If an uninstantiated shared instance is requested.\n\t *\n\t * @param string $class_name Class to get the shared instance for.\n\t * @return T Shared instance.\n\t *\n\t * @phpstan-param class-string<T> $class_name Class to get the shared instance for.\n\t * @phpstan-return T Shared instance.\n\t */\n\tprivate function get_shared_instance( string $class_name ) {\n\t\tif ( ! $this->has_shared_instance( $class_name ) ) {\n\t\t\tthrow FailedToMakeInstance::for_uninstantiated_shared_instance( $class_name ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\n\t\t/**\n\t\t * Shared instance.\n\t\t *\n\t\t * @var T $instance\n\t\t */\n\t\t$instance = $this->shared_instances[ $class_name ];\n\n\t\treturn $instance;\n\t}\n\n\t/**\n\t * Check whether a delegate exists for a given class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $class_name Class to check for a delegate.\n\t * @return bool Whether a delegate exists.\n\t */\n\tprivate function has_delegate( string $class_name ): bool {\n\t\treturn \\array_key_exists( $class_name, $this->delegates );\n\t}\n\n\t/**\n\t * Get the delegate for a given class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If an invalid delegate is requested.\n\t *\n\t * @param string $class_name Class to get the delegate for.\n\t * @return callable Delegate.\n\t */\n\tprivate function get_delegate( string $class_name ): callable {\n\t\tif ( ! $this->has_delegate( $class_name ) ) {\n\t\t\tthrow FailedToMakeInstance::for_invalid_delegate( $class_name ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\t\treturn $this->delegates[ $class_name ];\n\t}\n\n\t/**\n\t * Get the reflection for a class or throw an exception.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws FailedToMakeInstance If the class could not be reflected.\n\t *\n\t * @param string|class-string $class_name Class to get the reflection for.\n\t * @return ReflectionClass Class reflection.\n\t */\n\tprivate function get_class_reflection( string $class_name ): ReflectionClass {\n\t\tif ( ! class_exists( $class_name ) ) {\n\t\t\tthrow FailedToMakeInstance::for_unreflectable_class( $class_name ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\t\t// There should be no ReflectionException happening because of the class existence check above.\n\t\treturn new ReflectionClass( $class_name );\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/Injector.php",
    "content": "<?php\n/**\n * Interface Injector.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * The dependency injector should be the only piece of code doing actual\n * instantiations, with the following exceptions:\n *  - Factories can instantiate directly.\n *  - Value objects should be instantiated directly where they are being used.\n *\n * Through technical features like \"binding\" interfaces to classes or\n * \"auto-wiring\" to resolve all dependency of a class to be instantiated\n * automatically, the dependency injector allows for the largest part of the\n * code to adhere to the \"Code against Interfaces, not Implementations\"\n * principle.\n *\n * Finally, the dependency injector should be the only one to decide what\n * objects to \"share\" (always handing out the same instance) or not to share\n * (always returning a fresh new instance on each subsequent call). This\n * effectively gets rid of the dreaded Singletons.\n *\n * @internal\n *\n * @since 1.6.0\n *\n * @template T\n */\ninterface Injector extends Service {\n\n\t/**\n\t * Make an object instance out of an interface or class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string   $interface_or_class Interface or class to make an object instance out of.\n\t * @param string[] $arguments          Optional. Additional arguments to pass to the constructor.\n\t *                                           Defaults to an empty array.\n\t * @return C Instantiated object.\n\t *\n\t * @phpstan-param class-string<C> $interface_or_class Interface or class to make an object instance out of.\n\t * @phpstan-param class-string[]  $arguments          Optional. Additional arguments to pass to the constructor.\n\t *                                                    Defaults to an empty array.\n\t *\n\t * @phpstan-return C\n\t *\n\t * @template C\n\t */\n\tpublic function make( string $interface_or_class, array $arguments = [] );\n\n\t/**\n\t * Bind a given interface or class to an implementation.\n\t *\n\t * Note: The implementation can be an interface as well, as long as it can\n\t * be resolved to an instantiatable class at runtime.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $from Interface or class to bind an implementation to.\n\t * @param string $to   Interface or class that provides the implementation.\n\t *\n\t * @phpstan-param class-string<T> $from Interface or class to bind an implementation to.\n\t * @phpstan-param class-string<T> $to   Interface or class that provides the implementation.\n\t */\n\tpublic function bind( string $from, string $to ): Injector;\n\n\t/**\n\t * Bind an argument for a class to a specific value.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_or_class Interface or class to bind an argument\n\t *                                      for.\n\t * @param string $argument_name      Argument name to bind a value to.\n\t * @param mixed  $value              Value to bind the argument to.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to bind an argument\n\t */\n\tpublic function bind_argument(\n\t\tstring $interface_or_class,\n\t\tstring $argument_name,\n\t\t$value\n\t): Injector;\n\n\t/**\n\t * Always reuse and share the same instance for the provided interface or\n\t * class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $interface_or_class Interface or class to reuse.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to reuse.\n\t */\n\tpublic function share( string $interface_or_class ): Injector;\n\n\t/**\n\t * Delegate instantiation of an interface or class to a callable.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string   $interface_or_class Interface or class to delegate the\n\t *                                     instantiation of.\n\t * @param callable $callback           Callable to use for instantiation.\n\t *\n\t * @phpstan-param class-string<T> $interface_or_class Interface or class to delegate the\n\t *                                                    instantiation of.\n\t */\n\tpublic function delegate( string $interface_or_class, callable $callback ): Injector;\n}\n"
  },
  {
    "path": "includes/Infrastructure/Instantiator.php",
    "content": "<?php\n/**\n * Interface Instantiator.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Interface to make the act of instantiation extensible/replaceable.\n *\n * This way, a more elaborate mechanism can be plugged in, like using\n * ProxyManager to instantiate proxies instead of actual objects.\n *\n * @internal\n *\n * @since 1.6.0\n *\n * @template T\n */\ninterface Instantiator {\n\t/**\n\t * Make an object instance out of an interface or class.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string            $class_name   Class to make an object instance out of.\n\t * @param array<int, mixed> $dependencies Optional. Dependencies of the class.\n\t * @return T Instantiated object.\n\t *\n\t * @phpstan-param class-string<T> $class_name Class to make an object instance out of.\n\t */\n\tpublic function instantiate( string $class_name, array $dependencies = [] );\n}\n"
  },
  {
    "path": "includes/Infrastructure/Plugin.php",
    "content": "<?php\n/**\n * Interface Plugin\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * A plugin is basically nothing more than a convention on how manage the\n * lifecycle of a modular piece of code, so that you can:\n *  1. activate it,\n *  2. register it with the framework, and\n *  3. deactivate it again.\n *\n * This is what this interface represents, by assembling the separate,\n * segregated interfaces for each of these lifecycle actions.\n *\n * Additionally, we provide a means to get access to the plugin's container that\n * collects all the services it is made up of. This allows direct access to the\n * services to outside code if needed.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface Plugin extends PluginActivationAware, PluginDeactivationAware, Registerable, SiteInitializationAware, SiteRemovalAware {\n\n\t/**\n\t * Get the service container that contains the services that make up the\n\t * plugin.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return ServiceContainer<Service> Service container of the plugin.\n\t */\n\tpublic function get_container(): ServiceContainer;\n}\n"
  },
  {
    "path": "includes/Infrastructure/PluginActivationAware.php",
    "content": "<?php\n/**\n * Interface PluginActivationAware.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that can be activated.\n *\n * By tagging a service with this interface, the system will automatically hook\n * it up to the WordPress activation hook.\n *\n * This way, we can just add the simple interface marker and not worry about how\n * to wire up the code to reach that part during the static activation hook.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface PluginActivationAware {\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/PluginDeactivationAware.php",
    "content": "<?php\n/**\n * Interface PluginDeactivationAware.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that can be deactivated.\n *\n * By tagging a service with this interface, the system will automatically hook\n * it up to the WordPress deactivation hook.\n *\n * This way, we can just add the simple interface marker and not worry about how\n * to wire up the code to reach that part during the static deactivation hook.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface PluginDeactivationAware {\n\n\t/**\n\t * Act on plugin deactivation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the deactivation was done network-wide.\n\t */\n\tpublic function on_plugin_deactivation( bool $network_wide ): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/PluginUninstallAware.php",
    "content": "<?php\n/**\n * Interface PluginUninstallAware.\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that can be uninstalled.\n *\n * By tagging a service with this interface, the system will automatically hook\n * it up to the WordPress uninstall hook.\n *\n * This way, we can just add the simple interface marker and not worry about how\n * to wire up the code to reach that part during the static uninstall hook.\n *\n * @internal\n *\n * @since 1.26.0\n */\ninterface PluginUninstallAware {\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/Registerable.php",
    "content": "<?php\n/**\n * Interface Registerable.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * Something that can be registered.\n *\n * For a clean code base, a class instantiation should never have side-effects,\n * only initialize the internals of the object so that it is ready to be used.\n *\n * This means, though, that the system does not have any knowledge of the\n * objects when they are merely instantiated.\n *\n * Registering such an object is the explicit act of making it known to the\n * overarching system.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface Registerable {\n\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.6.0\n\t */\n\tpublic function register(): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/Service.php",
    "content": "<?php\n/**\n * Interface Service.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\n/**\n * A conceptual service.\n *\n * Splitting the logic up into independent services makes the approach of\n * assembling a plugin more systematic and scalable and lowers the cognitive\n * load when the code base increases in size.\n *\n * @internal\n *\n * @since 1.6.0\n */\ninterface Service {\n\n}\n"
  },
  {
    "path": "includes/Infrastructure/ServiceBasedPlugin.php",
    "content": "<?php\n/**\n * Class ServiceBasedPlugin.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer\\LazilyInstantiatedService;\nuse WP_Site;\nuse function add_action;\nuse function apply_filters;\nuse function did_action;\nuse const WPCOM_IS_VIP_ENV;\n\n/**\n * This abstract base plugin provides all the boilerplate code for working with\n * the dependency injector and the service container.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @template C of Conditional\n * @template D of Delayed\n * @template H of HasRequirements\n * @template R of Registerable\n * @template S of Service\n */\nabstract class ServiceBasedPlugin implements Plugin {\n\n\t// Main filters to control the flow of the plugin from outside code.\n\tpublic const SERVICES_FILTER         = 'services';\n\tpublic const BINDINGS_FILTER         = 'bindings';\n\tpublic const ARGUMENTS_FILTER        = 'arguments';\n\tpublic const SHARED_INSTANCES_FILTER = 'shared_instances';\n\tpublic const DELEGATIONS_FILTER      = 'delegations';\n\n\t// Service identifier for the injector.\n\tpublic const INJECTOR_ID = 'injector';\n\n\t// WordPress action to trigger the service registration on.\n\t// Use false to register as soon as the code is loaded.\n\tpublic const REGISTRATION_ACTION = false;\n\n\t// Whether to enable filtering by default or not.\n\tpublic const ENABLE_FILTERS_DEFAULT = true;\n\n\t// Prefixes to use.\n\tpublic const HOOK_PREFIX    = '';\n\tpublic const SERVICE_PREFIX = '';\n\n\t// Pattern used for detecting capitals to turn PascalCase into snake_case.\n\tpublic const DETECT_CAPITALS_REGEX_PATTERN = '/[A-Z]([A-Z](?![a-z]))*/';\n\n\t/**\n\t * Enable filters.\n\t */\n\tprotected bool $enable_filters;\n\n\t/**\n\t * Injector.\n\t */\n\tprotected Injector $injector;\n\n\t/**\n\t * ServiceContainer.\n\t *\n\t * @var ServiceContainer<Service>\n\t */\n\tprotected ServiceContainer $service_container;\n\n\t/**\n\t * Instantiate a Theme object.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool|null                      $enable_filters    Optional. Whether to enable filtering of the injector configuration.\n\t * @param Injector|null                  $injector          Optional. Injector instance to use.\n\t * @param ServiceContainer<Service>|null $service_container Optional. Service container instance to use.\n\t */\n\tpublic function __construct(\n\t\t?bool $enable_filters = null,\n\t\t?Injector $injector = null,\n\t\t?ServiceContainer $service_container = null\n\t) {\n\t\t/*\n\t\t * We use what is commonly referred to as a \"poka-yoke\" here.\n\t\t *\n\t\t * We need an injector and a container. We make them injectable so that\n\t\t * we can easily provide overrides for testing, but we also make them\n\t\t * optional and provide default implementations for easy regular usage.\n\t\t */\n\n\t\t$this->enable_filters = $enable_filters ?? static::ENABLE_FILTERS_DEFAULT;\n\n\t\t$this->injector = $injector ?? new Injector\\SimpleInjector();\n\n\t\t$this->injector = $this->configure_injector( $this->injector );\n\n\t\t$this->service_container = $service_container ?? new ServiceContainer\\SimpleServiceContainer();\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->register_services();\n\n\t\t/**\n\t\t * Service ID.\n\t\t *\n\t\t * @var string $id\n\t\t */\n\t\tforeach ( $this->service_container as $id => $service ) {\n\t\t\t// Using ->get() here to instantiate LazilyInstantiatedService too.\n\t\t\t$service = $this->service_container->get( $id );\n\n\t\t\tif ( $service instanceof PluginActivationAware ) {\n\t\t\t\t$service->on_plugin_activation( $network_wide );\n\t\t\t}\n\t\t}\n\n\t\tif ( ! \\defined( '\\WPCOM_IS_VIP_ENV' ) || false === WPCOM_IS_VIP_ENV ) {\n\t\t\tflush_rewrite_rules( false );\n\t\t}\n\t}\n\n\t/**\n\t * Act on plugin deactivation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the deactivation was done network-wide.\n\t */\n\tpublic function on_plugin_deactivation( bool $network_wide ): void {\n\t\t$this->register_services();\n\n\t\t/**\n\t\t * Service ID.\n\t\t *\n\t\t * @var string $id\n\t\t */\n\t\tforeach ( $this->service_container as $id => $service ) {\n\t\t\t// Using ->get() here to instantiate LazilyInstantiatedService too.\n\t\t\t$service = $this->service_container->get( $id );\n\n\t\t\tif ( $service instanceof PluginDeactivationAware ) {\n\t\t\t\t$service->on_plugin_deactivation( $network_wide );\n\t\t\t}\n\t\t}\n\n\t\tif ( ! \\defined( '\\WPCOM_IS_VIP_ENV' ) || false === WPCOM_IS_VIP_ENV ) {\n\t\t\tflush_rewrite_rules( false );\n\t\t}\n\t}\n\n\t/**\n\t * Act on site initialization on Multisite.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\t$this->register_services();\n\n\t\t$site_id = (int) $site->blog_id;\n\n\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog\n\t\tswitch_to_blog( $site_id );\n\n\t\t/**\n\t\t * Service ID.\n\t\t *\n\t\t * @var string $id\n\t\t */\n\t\tforeach ( $this->service_container as $id => $service ) {\n\t\t\t// Using ->get() here to instantiate LazilyInstantiatedService too.\n\t\t\t$service = $this->service_container->get( $id );\n\n\t\t\tif ( $service instanceof SiteInitializationAware ) {\n\t\t\t\t$service->on_site_initialization( $site );\n\t\t\t}\n\t\t}\n\n\t\tif ( ! \\defined( '\\WPCOM_IS_VIP_ENV' ) || false === WPCOM_IS_VIP_ENV ) {\n\t\t\tflush_rewrite_rules( false );\n\t\t}\n\n\t\trestore_current_blog();\n\t}\n\n\t/**\n\t * Act on site removal on Multisite.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being removed.\n\t */\n\tpublic function on_site_removal( WP_Site $site ): void {\n\t\t$this->register_services();\n\n\t\t$site_id = (int) $site->blog_id;\n\n\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog\n\t\tswitch_to_blog( $site_id );\n\n\t\t/**\n\t\t * Service ID.\n\t\t *\n\t\t * @var string $id\n\t\t */\n\t\tforeach ( $this->service_container as $id => $service ) {\n\t\t\t// Using ->get() here to instantiate LazilyInstantiatedService too.\n\t\t\t$service = $this->service_container->get( $id );\n\n\t\t\tif ( $service instanceof SiteRemovalAware ) {\n\t\t\t\t$service->on_site_removal( $site );\n\t\t\t}\n\t\t}\n\n\t\trestore_current_blog();\n\t}\n\n\t/**\n\t * Act on site is uninstalled.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_site_uninstall(): void {\n\t\t$this->register_services();\n\n\t\t/**\n\t\t * Service ID.\n\t\t *\n\t\t * @var string $id\n\t\t */\n\t\tforeach ( $this->service_container as $id => $service ) {\n\t\t\t// Using ->get() here to instantiate LazilyInstantiatedService too.\n\t\t\t$service = $this->service_container->get( $id );\n\n\t\t\tif ( $service instanceof PluginUninstallAware ) {\n\t\t\t\t$service->on_plugin_uninstall();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Register the plugin with the WordPress system.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If a service is not valid.\n\t */\n\tpublic function register(): void {\n\t\tif ( false !== static::REGISTRATION_ACTION ) {\n\t\t\tadd_action(\n\t\t\t\tstatic::REGISTRATION_ACTION,\n\t\t\t\t[ $this, 'register_services' ]\n\t\t\t);\n\t\t} else {\n\t\t\t$this->register_services();\n\t\t}\n\t}\n\n\t/**\n\t * Register the individual services of this plugin.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If a service is not valid.\n\t */\n\tpublic function register_services(): void {\n\t\t// Bail early so we don't instantiate services twice.\n\t\tif ( \\count( $this->service_container ) > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add the injector as the very first service.\n\t\t$this->service_container->put(\n\t\t\tstatic::SERVICE_PREFIX . static::INJECTOR_ID,\n\t\t\t$this->injector\n\t\t);\n\n\t\t$services = $this->get_service_classes();\n\n\t\tif ( $this->enable_filters ) {\n\t\t\t/**\n\t\t\t * Filter the default services that make up this plugin.\n\t\t\t *\n\t\t\t * This can be used to add services to the service container for\n\t\t\t * this plugin.\n\t\t\t *\n\t\t\t * @param array<string, string> $services Associative array of identifier =>\n\t\t\t *                                        class mappings. The provided\n\t\t\t *                                        classes need to implement the\n\t\t\t *                                        Service interface.\n\t\t\t */\n\t\t\t$filtered_services = apply_filters(\n\t\t\t\tstatic::HOOK_PREFIX . static::SERVICES_FILTER,\n\t\t\t\t$services\n\t\t\t);\n\n\t\t\t$services = $this->validate_services( $filtered_services );\n\t\t}\n\n\t\twhile ( null !== key( $services ) ) {\n\t\t\t$id = $this->maybe_resolve( key( $services ) );\n\n\t\t\t$curr = current( $services );\n\n\t\t\tif ( ! $curr ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$class = $this->maybe_resolve( $curr );\n\n\t\t\t// Delay registering the service until all requirements are met.\n\t\t\tif (\n\t\t\t\t// @phpstan-ignore function.alreadyNarrowedType\n\t\t\t\tis_a( $class, HasRequirements::class, true )\n\t\t\t) {\n\t\t\t\tif ( ! $this->requirements_are_met( $id, $class, $services ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->schedule_potential_service_registration( $id, $class );\n\n\t\t\tnext( $services );\n\t\t}\n\t}\n\n\t/**\n\t * Get the service container that contains the services that make up the\n\t * plugin.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return ServiceContainer<Service> Service container of the plugin.\n\t */\n\tpublic function get_container(): ServiceContainer {\n\t\treturn $this->service_container;\n\t}\n\n\t/**\n\t * Returns the priority for a given service based on its requirements.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @throws InvalidService If the required service is not recognized.\n\t *\n\t * @param class-string                   $class_name    Service FQCN of the service with requirements.\n\t * @param array<string, class-string<S>> $services      List of services to be registered.\n\t * @return int The registration action priority for the service.\n\t *\n\t * @phpstan-param class-string<S> $class_name Service FQCN of the service with requirements.\n\t */\n\tprotected function get_registration_action_priority( string $class_name, array &$services ): int {\n\t\t$priority = 10;\n\n\t\tif ( is_a( $class_name, Delayed::class, true ) ) {\n\t\t\t$priority = $class_name::get_registration_action_priority();\n\t\t}\n\n\t\tif ( ! is_a( $class_name, HasRequirements::class, true ) ) {\n\t\t\treturn $priority;\n\t\t}\n\n\t\t/**\n\t\t * Service class.\n\t\t *\n\t\t * @phpstan-var class-string<H&S> $class_name\n\t\t */\n\t\t$missing_requirements = $this->collect_missing_requirements( $class_name, $services );\n\n\t\tforeach ( $missing_requirements as $missing_requirement ) {\n\t\t\tif ( is_a( $missing_requirement, Delayed::class, true ) ) {\n\t\t\t\t$action = $missing_requirement::get_registration_action();\n\n\t\t\t\tif ( did_action( $action ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Missing requirement.\n\t\t\t\t *\n\t\t\t\t * @phpstan-var class-string<D&S> $missing_requirement\n\t\t\t\t */\n\t\t\t\t$requirement_priority = $this->get_registration_action_priority( $missing_requirement, $services );\n\n\t\t\t\t$priority = max( $priority, $requirement_priority + 1 );\n\t\t\t}\n\t\t}\n\n\t\treturn $priority;\n\t}\n\n\t/**\n\t * Determine if the requirements for a service to be registered are met.\n\t *\n\t * This also hooks up another check in the future to the registration action(s) of its requirements.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @throws InvalidService If the required service is not recognized.\n\t *\n\t * @param string                         $id         Service ID of the service with requirements.\n\t * @param class-string                   $class_name Service FQCN of the service with requirements.\n\t * @param array<string, class-string<S>> $services   List of services to be registered.\n\t * @return bool Whether the requirements for the service has been met.\n\t *\n\t * @phpstan-param class-string<H&S> $class_name Service FQCN of the service with requirements.\n\t */\n\tprotected function requirements_are_met( string $id, string $class_name, array &$services ): bool {\n\t\t$missing_requirements = $this->collect_missing_requirements( $class_name, $services );\n\n\t\tif ( empty( $missing_requirements ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tforeach ( $missing_requirements as $missing_requirement ) {\n\t\t\tif ( is_a( $missing_requirement, Delayed::class, true ) ) {\n\t\t\t\t$action = $missing_requirement::get_registration_action();\n\n\t\t\t\tif ( did_action( $action ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * If this service (A) has priority 10 but depends on another service (B) with same priority,\n\t\t\t\t * which itself depends on service (C) also with priority 10, this will ensure correct\n\t\t\t\t * order of registration by increasing priority for each step.\n\t\t\t\t *\n\t\t\t\t * The result will be:\n\t\t\t\t *\n\t\t\t\t * C: priority 10\n\t\t\t\t * B: priority 11\n\t\t\t\t * A: priority 12\n\t\t\t\t */\n\n\t\t\t\t$priority = $this->get_registration_action_priority( $class_name, $services );\n\n\t\t\t\t/*\n\t\t\t\t * The current service depends on another service that is Delayed and hasn't been registered yet\n\t\t\t\t * and for which the registration action has not yet passed.\n\t\t\t\t *\n\t\t\t\t * Therefore, we postpone the registration of the current service up until the requirement's\n\t\t\t\t * action has passed.\n\t\t\t\t *\n\t\t\t\t * We don't register the service right away, though, we will first check whether at that point,\n\t\t\t\t * the requirements have been met.\n\t\t\t\t *\n\t\t\t\t * Note that badly configured requirements can lead to services that will never register at all.\n\t\t\t\t */\n\n\t\t\t\tadd_action(\n\t\t\t\t\t$action,\n\t\t\t\t\tfunction () use ( $id, $class_name, $services ): void {\n\t\t\t\t\t\tif ( ! $this->requirements_are_met( $id, $class_name, $services ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this->schedule_potential_service_registration( $id, $class_name );\n\t\t\t\t\t},\n\t\t\t\t\t$priority\n\t\t\t\t);\n\n\t\t\t\tnext( $services );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * The registration actions from all of the requirements were already processed. This means that the missing\n\t\t * requirement(s) are about to be registered, they just weren't encountered yet while traversing the services\n\t\t * map. Therefore, we skip registration for now and move this particular service to the end of the service map.\n\t\t *\n\t\t * Note: Moving the service to the end of the service map advances the internal array pointer to the next service.\n\t\t */\n\t\tunset( $services[ $id ] );\n\t\t$services[ $id ] = $class_name;\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Collect the list of missing requirements for a service which has requirements.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @throws InvalidService If the required service is not recognized.\n\t *\n\t * @param class-string                   $class_name    Service FQCN of the service with requirements.\n\t * @param array<string, class-string<S>> $services      List of services to register.\n\t * @return array<string, class-string<S>> List of missing requirements as a $service_id => $service_class mapping.\n\t *\n\t * @phpstan-param class-string<H&S> $class_name Service FQCN of the service with requirements.\n\t */\n\tprotected function collect_missing_requirements( string $class_name, array $services ): array {\n\t\t/**\n\t\t * Requirements.\n\t\t *\n\t\t * @var string[] $requirements\n\t\t */\n\t\t$requirements = $class_name::get_requirements();\n\n\t\t/**\n\t\t * Missing requirements.\n\t\t *\n\t\t * @var array<string, class-string<S>>\n\t\t */\n\t\t$missing = [];\n\n\t\tforeach ( $requirements as $requirement ) {\n\t\t\t// Bail if it requires a service that is not recognized.\n\t\t\tif ( ! \\array_key_exists( $requirement, $services ) ) {\n\t\t\t\tthrow InvalidService::from_service_id( $requirement ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t\t}\n\n\t\t\tif ( $this->get_container()->has( $requirement ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$missing[ $requirement ] = $services[ $requirement ];\n\t\t}\n\n\t\treturn $missing;\n\t}\n\n\t/**\n\t * Validates the services array to make sure it is in a usable shape.\n\t *\n\t * As the array of services could be filtered, we need to ensure it is\n\t * always in a state where it doesn't throw PHP warnings or errors.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param array<int|string, string|class-string> $services Services to validate.\n\t * @return array<string, class-string<S>> Validated array of service mappings.\n\t */\n\tprotected function validate_services( array $services ): array {\n\t\t// Make a copy so we can safely mutate while iterating.\n\t\t$services_to_check = $services;\n\n\t\tforeach ( $services_to_check as $identifier => $fqcn ) {\n\t\t\t// Ensure we have valid identifiers we can refer to.\n\t\t\t// If not, generate them from the FQCN.\n\t\t\tif ( empty( $identifier ) || ! \\is_string( $identifier ) ) {\n\t\t\t\tunset( $services[ $identifier ] );\n\t\t\t\t$identifier              = $this->get_identifier_from_fqcn( $fqcn );\n\t\t\t\t$services[ $identifier ] = $fqcn;\n\t\t\t}\n\n\t\t\t// Verify that the FQCN is valid and points to an existing class.\n\t\t\t// If not, skip this service.\n\t\t\tif ( empty( $fqcn ) || ! class_exists( $fqcn ) ) {\n\t\t\t\tunset( $services[ $identifier ] );\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Validated services.\n\t\t *\n\t\t * @phpstan-var array<string, class-string<S>> $services\n\t\t */\n\t\treturn $services;\n\t}\n\n\t/**\n\t * Generate a valid identifier for a provided FQCN.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $fqcn FQCN to use as base to generate an identifier.\n\t * @return string Identifier to use for the provided FQCN.\n\t */\n\tprotected function get_identifier_from_fqcn( string $fqcn ): string {\n\t\t// Retrieve the short name from the FQCN first.\n\t\t$short_name = substr( $fqcn, strrpos( $fqcn, '\\\\' ) + 1 );\n\n\t\t// Turn camelCase or PascalCase into snake_case.\n\t\treturn strtolower(\n\t\t\ttrim(\n\t\t\t\t(string) preg_replace( self::DETECT_CAPITALS_REGEX_PATTERN, '_$0', $short_name ),\n\t\t\t\t'_'\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * Schedule the potential registration of a single service.\n\t *\n\t * This takes into account whether the service registration needs to be delayed or not.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param string       $id ID of the service to register.\n\t * @param class-string $class_name Class of the service to register.\n\t *\n\t * @phpstan-param class-string<(D&S)|S> $class_name Class of the service to register.\n\t */\n\tprotected function schedule_potential_service_registration( string $id, string $class_name ): void {\n\t\tif ( is_a( $class_name, Delayed::class, true ) ) {\n\t\t\t$action   = $class_name::get_registration_action();\n\t\t\t$priority = $class_name::get_registration_action_priority();\n\n\t\t\tif ( did_action( $action ) ) {\n\t\t\t\t$this->maybe_register_service( $id, $class_name );\n\t\t\t} else {\n\t\t\t\tadd_action(\n\t\t\t\t\t$action,\n\t\t\t\t\tfunction () use ( $id, $class_name ): void {\n\t\t\t\t\t\t$this->maybe_register_service( $id, $class_name );\n\t\t\t\t\t},\n\t\t\t\t\t$priority\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t$this->maybe_register_service( $id, $class_name );\n\t\t}\n\t}\n\n\t/**\n\t * Register a single service, provided its conditions are met.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $id         ID of the service to register.\n\t * @param string $class_name Class of the service to register.\n\t *\n\t * @phpstan-param class-string<S> $class_name Class of the service to register.\n\t */\n\tprotected function maybe_register_service( string $id, string $class_name ): void {\n\t\t// Ensure we don't register the same service more than once.\n\t\tif ( $this->service_container->has( $id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Only instantiate services that are actually needed.\n\t\tif ( is_a( $class_name, Conditional::class, true )\n\t\t\t&& ! $class_name::is_needed() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$service = $this->instantiate_service( $class_name );\n\n\t\t$this->service_container->put( $id, $service );\n\n\t\tif ( $service instanceof Registerable ) {\n\t\t\t$service->register();\n\t\t}\n\t}\n\n\t/**\n\t * Instantiate a single service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If the service could not be properly instantiated.\n\t *\n\t * @param class-string|object $class_name Service class to instantiate.\n\t * @return Service Instantiated service.\n\t *\n\t * @phpstan-param class-string<S> $class_name Service class to instantiate.\n\t */\n\tprotected function instantiate_service( $class_name ): Service {\n\t\t/*\n\t\t * If the service is not registerable, we default to lazily instantiated\n\t\t * services here for some basic optimization.\n\t\t *\n\t\t * The services will be properly instantiated once they are retrieved\n\t\t * from the service container.\n\t\t */\n\t\tif ( ! is_a( $class_name, Registerable::class, true ) ) {\n\t\t\treturn new LazilyInstantiatedService(\n\t\t\t\tfn() => $this->injector->make( $class_name )\n\t\t\t);\n\t\t}\n\n\t\t// The service needs to be registered, so instantiate right away.\n\t\t$service = $this->injector->make( $class_name );\n\n\t\t// @phpstan-ignore instanceof.alwaysTrue\n\t\tif ( ! $service instanceof Service ) {\n\t\t\tthrow InvalidService::from_service( $service ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\t\treturn $service;\n\t}\n\n\t/**\n\t * Configure the provided injector.\n\t *\n\t * This method defines the mappings that the injector knows about, and the\n\t * logic it requires to make more complex instantiations work.\n\t *\n\t * For more complex plugins, this should be extracted into a separate\n\t * object\n\t * or into configuration files.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param Injector $injector Injector instance to configure.\n\t * @return Injector Configured injector instance.\n\t */\n\tprotected function configure_injector( Injector $injector ): Injector {\n\t\t$bindings         = $this->get_bindings();\n\t\t$shared_instances = $this->get_shared_instances();\n\t\t$arguments        = $this->get_arguments();\n\t\t$delegations      = $this->get_delegations();\n\n\t\tif ( $this->enable_filters ) {\n\t\t\t/**\n\t\t\t * Filter the default bindings that are provided by the plugin.\n\t\t\t *\n\t\t\t * This can be used to swap implementations out for alternatives.\n\t\t\t *\n\t\t\t * @param array<string> $bindings Associative array of interface =>\n\t\t\t *                                implementation bindings. Both\n\t\t\t *                                should be FQCNs.\n\t\t\t */\n\t\t\t$bindings = apply_filters(\n\t\t\t\tstatic::HOOK_PREFIX . static::BINDINGS_FILTER,\n\t\t\t\t$bindings\n\t\t\t);\n\n\t\t\t/**\n\t\t\t * Filter the default argument bindings that are provided by the\n\t\t\t * plugin.\n\t\t\t *\n\t\t\t * This can be used to override scalar values.\n\t\t\t *\n\t\t\t * @param array<class-string, mixed> $arguments Associative array of class =>\n\t\t\t *                                              arguments mappings. The arguments\n\t\t\t *                                              array maps argument names to\n\t\t\t *                                              values.\n\t\t\t */\n\t\t\t$arguments = apply_filters(\n\t\t\t\tstatic::HOOK_PREFIX . static::ARGUMENTS_FILTER,\n\t\t\t\t$arguments\n\t\t\t);\n\n\t\t\t/**\n\t\t\t * Filter the instances that are shared by default by the plugin.\n\t\t\t *\n\t\t\t * This can be used to turn objects that were added externally into\n\t\t\t * shared instances.\n\t\t\t *\n\t\t\t * @param array<string> $shared_instances Array of FQCNs to turn\n\t\t\t *                                        into shared objects.\n\t\t\t */\n\t\t\t$shared_instances = apply_filters(\n\t\t\t\tstatic::HOOK_PREFIX . static::SHARED_INSTANCES_FILTER,\n\t\t\t\t$shared_instances\n\t\t\t);\n\n\t\t\t/**\n\t\t\t * Filter the instances that are shared by default by the plugin.\n\t\t\t *\n\t\t\t * This can be used to turn objects that were added externally into\n\t\t\t * shared instances.\n\t\t\t *\n\t\t\t * @param array<string, callable> $delegations Associative array of class =>\n\t\t\t *                                   callable mappings.\n\t\t\t */\n\t\t\t$delegations = apply_filters(\n\t\t\t\tstatic::HOOK_PREFIX . static::DELEGATIONS_FILTER,\n\t\t\t\t$delegations\n\t\t\t);\n\t\t}\n\n\t\tforeach ( $bindings as $from => $to ) {\n\t\t\t$from = $this->maybe_resolve( $from );\n\t\t\t$to   = $this->maybe_resolve( $to );\n\n\t\t\t$injector = $injector->bind( $from, $to );\n\t\t}\n\n\t\t/**\n\t\t * Argument map.\n\t\t *\n\t\t * @var array<class-string, array<string|callable|class-string>> $arguments\n\t\t */\n\t\tforeach ( $arguments as $class => $argument_map ) {\n\t\t\t$class = $this->maybe_resolve( $class );\n\n\t\t\tforeach ( $argument_map as $name => $value ) {\n\t\t\t\t// We don't try to resolve the $value here, as we might want to\n\t\t\t\t// pass a callable as-is.\n\t\t\t\t$name = $this->maybe_resolve( $name );\n\n\t\t\t\t$injector = $injector->bind_argument( $class, $name, $value );\n\t\t\t}\n\t\t}\n\n\t\tforeach ( $shared_instances as $shared_instance ) {\n\t\t\t$shared_instance = $this->maybe_resolve( $shared_instance );\n\n\t\t\t$injector = $injector->share( $shared_instance );\n\t\t}\n\n\t\t/**\n\t\t * Callable.\n\t\t *\n\t\t * @var callable $callable\n\t\t */\n\t\tforeach ( $delegations as $class => $callable ) {\n\t\t\t// We don't try to resolve the $callable here, as we want to pass it\n\t\t\t// on as-is.\n\t\t\t$class = $this->maybe_resolve( $class );\n\n\t\t\t$injector = $injector->delegate( $class, $callable );\n\t\t}\n\n\t\treturn $injector;\n\t}\n\n\t/**\n\t * Get the list of services to register.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string, class-string<S>> Associative array of identifiers mapped to fully\n\t *                                        qualified class names.\n\t */\n\tprotected function get_service_classes(): array {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Get the bindings for the dependency injector.\n\t *\n\t * The bindings let you map interfaces (or classes) to the classes that\n\t * should be used to implement them.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string, class-string<S>> Associative array of fully qualified class names.\n\t */\n\tprotected function get_bindings(): array {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Get the argument bindings for the dependency injector.\n\t *\n\t * The argument bindings let you map specific argument values for specific\n\t * classes.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<class-string, mixed> Associative array of arrays mapping argument names\n\t *                                    to argument values.\n\t */\n\tprotected function get_arguments(): array {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Get the shared instances for the dependency injector.\n\t *\n\t * These classes will only be instantiated once by the injector and then\n\t * reused on subsequent requests.\n\t *\n\t * This effectively turns them into singletons, without any of the\n\t * drawbacks of the actual Singleton anti-pattern.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string> Array of fully qualified class names.\n\t */\n\tprotected function get_shared_instances(): array {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Get the delegations for the dependency injector.\n\t *\n\t * These are basically factories to provide custom instantiation logic for\n\t * classes.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<callable> Associative array of callables.\n\t *\n\t * @phpstan-return array<class-string<S|H|C>, callable> Associative array of callables.\n\t */\n\tprotected function get_delegations(): array {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Maybe resolve a value that is a callable instead of a scalar.\n\t *\n\t * Values that are passed through this method can optionally be provided as\n\t * callables instead of direct values and will be evaluated when needed.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string|callable|class-string $value Value to potentially resolve.\n\t * @return string|class-string Resolved or unchanged value.\n\t *\n\t * @phpstan-return class-string<C&D&H&R&S> Resolved or unchanged value.\n\t */\n\tprotected function maybe_resolve( $value ): string {\n\t\tif ( ! ( \\is_string( $value ) && \\function_exists( $value ) ) && \\is_callable( $value ) ) {\n\t\t\t$value = $value( $this->injector, $this->service_container );\n\t\t}\n\n\t\treturn $value;\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/ServiceContainer/LazilyInstantiatedService.php",
    "content": "<?php\n/**\n * Final class LazilyInstantiatedService.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure\\ServiceContainer;\n\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\n/**\n * A service that only gets properly instantiated when it is actually being\n * retrieved from the container.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class LazilyInstantiatedService implements Service {\n\n\t/**\n\t * Instantiation of Class.\n\t *\n\t * @var callable\n\t */\n\tprivate $instantiation;\n\n\t/**\n\t * Instantiate a LazilyInstantiatedService object.\n\t *\n\t * @param callable $instantiation Instantiation callable to use.\n\t */\n\tpublic function __construct( callable $instantiation ) {\n\t\t$this->instantiation = $instantiation;\n\t}\n\n\t/**\n\t * Do the actual service instantiation and return the real service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If the service could not be properly instantiated.\n\t *\n\t * @return Service Properly instantiated service.\n\t */\n\tpublic function instantiate(): Service {\n\t\t$instantiation = $this->instantiation; // Because uniform variable syntax not supported in PHP 5.6.\n\t\t$service       = $instantiation();\n\n\t\tif ( ! $service instanceof Service ) {\n\t\t\tthrow InvalidService::from_service( $service ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\t\treturn $service;\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/ServiceContainer/SimpleServiceContainer.php",
    "content": "<?php\n/**\n * Final class SimpleServiceContainer.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure\\ServiceContainer;\n\nuse ArrayObject;\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer;\n\n/**\n * A simplified implementation of a service container.\n *\n * We extend ArrayObject so we have default implementations for iterators and\n * array access.\n *\n * @internal\n *\n * @since 1.6.0\n */\nfinal class SimpleServiceContainer extends ArrayObject implements ServiceContainer {\n\n\t/**\n\t * Find a service of the container by its identifier and return it.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If the service could not be found.\n\t *\n\t * @param string $id Identifier of the service to look for.\n\t * @return Service Service that was requested.\n\t */\n\tpublic function get( string $id ): Service {\n\t\tif ( ! $this->has( $id ) ) {\n\t\t\tthrow InvalidService::from_service_id( $id ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped\n\t\t}\n\n\t\t/**\n\t\t * Service.\n\t\t *\n\t\t * @var Service $service Service.\n\t\t */\n\t\t$service = $this->offsetGet( $id );\n\n\t\t// Instantiate actual services if they were stored lazily.\n\t\tif ( $service instanceof LazilyInstantiatedService ) {\n\t\t\t$service = $service->instantiate();\n\t\t\t$this->put( $id, $service );\n\t\t}\n\n\t\treturn $service;\n\t}\n\n\t/**\n\t * Check whether the container can return a service for the given\n\t * identifier.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $id Identifier of the service to look for.\n\t */\n\tpublic function has( string $id ): bool {\n\t\treturn $this->offsetExists( $id );\n\t}\n\n\t/**\n\t * Put a service into the container for later retrieval.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string  $id      Identifier of the service to put into the\n\t *                         container.\n\t * @param Service $service Service to put into the container.\n\t */\n\tpublic function put( string $id, Service $service ): void {\n\t\t$this->offsetSet( $id, $service );\n\t}\n}\n"
  },
  {
    "path": "includes/Infrastructure/ServiceContainer.php",
    "content": "<?php\n/**\n * Interface ServiceContainer.\n *\n * @link      https://www.mwpd.io/\n *\n * @copyright 2019 Alain Schlesser\n * @license   MIT\n */\n\n/**\n * Original code modified for this project.\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\nuse ArrayAccess;\nuse Countable;\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Traversable;\n\n/**\n * The service container collects all services to manage them.\n *\n * This is based on PSR-11 and should extend that one if Composer dependencies\n * are being used. Relying on a standardized interface like PSR-11 means you'll\n * be able to easily swap out the implementation for something else later on.\n *\n * @internal\n *\n * @since 1.6.0\n *\n * @see https://www.php-fig.org/psr/psr-11/\n */\ninterface ServiceContainer extends Traversable, Countable, ArrayAccess {\n\n\t/**\n\t * Find a service of the container by its identifier and return it.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @throws InvalidService If the service could not be found.\n\t *\n\t * @param string $id Identifier of the service to look for.\n\t * @return Service Service that was requested.\n\t */\n\tpublic function get( string $id ): Service;\n\n\t/**\n\t * Check whether the container can return a service for the given\n\t * identifier.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $id Identifier of the service to look for.\n\t */\n\tpublic function has( string $id ): bool;\n\n\t/**\n\t * Put a service into the container for later retrieval.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string  $id      Identifier of the service to put into the\n\t *                         container.\n\t * @param Service $service Service to put into the container.\n\t */\n\tpublic function put( string $id, Service $service ): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/SiteInitializationAware.php",
    "content": "<?php\n/**\n * Interface SiteInitializationAware.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\nuse WP_Site;\n\n/**\n * Something that acts on site creation on Multisite.\n *\n * By tagging a service with this interface, the system will automatically hook\n * it up to the 'wp_initialize_site' WordPress action.\n *\n * @internal\n *\n * @since 1.11.0\n */\ninterface SiteInitializationAware {\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void;\n}\n"
  },
  {
    "path": "includes/Infrastructure/SiteRemovalAware.php",
    "content": "<?php\n/**\n * Interface SiteRemovalAware.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Infrastructure;\n\nuse WP_Site;\n\n/**\n * Something that acts on site removal on Multisite.\n *\n * By tagging a service with this interface, the system will automatically hook\n * it up to the 'wp_validate_site_deletion' WordPress action.\n *\n * @internal\n *\n * @since 1.11.0\n */\ninterface SiteRemovalAware {\n\n\t/**\n\t * Act on site removal.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being removed.\n\t */\n\tpublic function on_site_removal( WP_Site $site ): void;\n}\n"
  },
  {
    "path": "includes/Integrations/AMP.php",
    "content": "<?php\n/**\n * Class AMP\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse DOMElement;\nuse Google\\Web_Stories\\AMP\\Integration\\AMP_Story_Sanitizer;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Class AMP.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type AMPOptions array{\n *   theme_support?: string,\n *   supported_post_types?: string[],\n *   supported_templates?: string[]\n * }\n *\n * @phpstan-type AMPSanitizers array{\n *   AMP_Style_Sanitizer?: array{\n *     dynamic_element_selectors?: string[]\n *   }\n * }\n */\nclass AMP extends Service_Base implements HasRequirements {\n\t/**\n\t * Slug of the AMP validated URL post type.\n\t */\n\tpublic const AMP_VALIDATED_URL_POST_TYPE = 'amp_validated_url';\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings        $settings        Settings instance.\n\t * @param Story_Post_Type $story_post_type Experiments instance.\n\t * @param Context         $context         Context instance.\n\t * @return void\n\t */\n\tpublic function __construct(\n\t\tSettings $settings,\n\t\tStory_Post_Type $story_post_type,\n\t\tContext $context\n\t) {\n\t\t$this->settings        = $settings;\n\t\t$this->story_post_type = $story_post_type;\n\t\t$this->context         = $context;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'option_amp-options', [ $this, 'filter_amp_options' ] );\n\t\tadd_filter( 'amp_supportable_post_types', [ $this, 'filter_supportable_post_types' ] );\n\t\tadd_filter( 'amp_to_amp_linking_element_excluded', [ $this, 'filter_amp_to_amp_linking_element_excluded' ], 10, 4 );\n\t\tadd_filter( 'amp_content_sanitizers', [ $this, 'add_amp_content_sanitizers' ] );\n\t\tadd_filter( 'amp_validation_error_sanitized', [ $this, 'filter_amp_validation_error_sanitized' ], 10, 2 );\n\t\tadd_filter( 'amp_skip_post', [ $this, 'filter_amp_skip_post' ], 10, 2 );\n\n\t\t// This filter is actually used in this plugin's `Sanitization` class.\n\t\tadd_filter( 'web_stories_amp_validation_error_sanitized', [ $this, 'filter_amp_validation_error_sanitized' ], 10, 2 );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Filter AMP options to force Standard mode (AMP-first) when a web story is being requested.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param array|false $options Options.\n\t * @return array|mixed Filtered options.\n\t *\n\t * @phpstan-param AMPOptions|false $options\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($options is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_amp_options( $options ) {\n\t\tif ( ! \\is_array( $options ) ) {\n\t\t\treturn $options;\n\t\t}\n\t\tif ( $this->get_request_post_type() === $this->story_post_type->get_slug() ) {\n\t\t\t$options['theme_support']          = 'standard';\n\t\t\t$options['supported_post_types'][] = $this->story_post_type->get_slug();\n\t\t\t$options['supported_templates'][]  = 'is_singular';\n\t\t}\n\t\treturn $options;\n\t}\n\n\t/**\n\t * Filter the post types which are supportable.\n\t *\n\t * Remove web-stories from the list unless the currently requested post type is for a web-story. This is done in\n\t * order to hide stories from the list of supportable post types on the AMP Settings screen.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param string[]|false $post_types Supportable post types.\n\t * @return string[]|false Supportable post types.\n\t *\n\t * @phpstan-return ($post_types is string[] ? string[] : false)\n\t */\n\tpublic function filter_supportable_post_types( $post_types ) {\n\t\tif ( ! \\is_array( $post_types ) ) {\n\t\t\treturn $post_types;\n\t\t}\n\n\t\t$story_post_type = $this->story_post_type->get_slug();\n\n\t\t$post_types = array_diff( $post_types, [ $story_post_type ] );\n\n\t\tif ( $this->get_request_post_type() === $story_post_type ) {\n\t\t\t$post_types = [ ...$post_types, $story_post_type ];\n\t\t}\n\n\t\treturn array_unique( array_values( $post_types ) );\n\t}\n\n\t/**\n\t * Filters the AMP plugin's sanitizers.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param array|mixed $sanitizers Sanitizers.\n\t * @return array|mixed Sanitizers.\n\t *\n\t * @phpstan-param AMPSanitizers|mixed $sanitizers\n\t * @phpstan-return AMPSanitizers|mixed\n\t */\n\tpublic function add_amp_content_sanitizers( $sanitizers ) {\n\t\tif ( ! $this->context->is_web_story() ) {\n\t\t\treturn $sanitizers;\n\t\t}\n\n\t\t$post = get_queried_object();\n\t\tif ( ! ( $post instanceof WP_Post ) ) {\n\t\t\treturn $sanitizers;\n\t\t}\n\n\t\tif ( ! \\is_array( $sanitizers ) ) {\n\t\t\treturn $sanitizers;\n\t\t}\n\n\t\t/**\n\t\t * AMP sanitizer configuration.\n\t\t *\n\t\t * @phpstan-var AMPSanitizers $sanitizers\n\t\t */\n\n\t\t$video_cache_enabled = (bool) $this->settings->get_setting( $this->settings::SETTING_NAME_VIDEO_CACHE );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$poster_images = [\n\t\t\t'poster-portrait-src' => esc_url_raw( $story->get_poster_portrait() ),\n\t\t];\n\n\t\tif ( isset( $sanitizers['AMP_Style_Sanitizer'] ) ) {\n\t\t\tif ( ! isset( $sanitizers['AMP_Style_Sanitizer']['dynamic_element_selectors'] ) ) {\n\t\t\t\t$sanitizers['AMP_Style_Sanitizer']['dynamic_element_selectors'] = [];\n\t\t\t}\n\n\t\t\t$sanitizers['AMP_Style_Sanitizer']['dynamic_element_selectors'][] = 'amp-story-captions';\n\t\t}\n\n\t\t$sanitizers[ AMP_Story_Sanitizer::class ] = [\n\t\t\t'publisher_logo' => (string) $story->get_publisher_logo_url(),\n\t\t\t'publisher'      => $story->get_publisher_name(),\n\t\t\t'poster_images'  => array_filter( $poster_images ),\n\t\t\t'video_cache'    => $video_cache_enabled,\n\t\t\t'title_tag'      => wp_get_document_title(),\n\t\t\t'description'    => wp_strip_all_tags( get_the_excerpt() ),\n\t\t];\n\n\t\treturn $sanitizers;\n\t}\n\n\t/**\n\t * Filter amp_validation_error_sanitized to prevent invalid markup removal for Web Stories.\n\t *\n\t * Since the amp-story element requires the poster-portrait-src attribute to be valid, when this attribute is absent\n\t * the AMP plugin will try to remove the amp-story element altogether. This is not the preferred resolution! So\n\t * instead, this will force the invalid markup to be kept. When this is done, the AMP plugin in Standard mode\n\t * (which Web Stories enforces while serving singular web-story posts) will remove the amp attribute from the html\n\t * element so that the page will not be advertised as AMP. This prevents GSC from complaining about a validation\n\t * issue which we already know about.\n\t *\n\t * The same is done for <amp-video> elements, for example when they have missing poster images.\n\t *\n\t * @since 1.1.1\n\t *\n\t * @link https://github.com/ampproject/amp-wp/blob/c6aed8f/includes/validation/class-amp-validation-manager.php#L1777-L1809\n\t *\n\t * @param null|bool                                                        $sanitized Whether sanitized. Null means sanitization is not overridden.\n\t * @param array{node_type?: int, node_name?: string, parent_name?: string} $error     Validation error being sanitized.\n\t * @return null|bool Whether sanitized.\n\t */\n\tpublic function filter_amp_validation_error_sanitized( ?bool $sanitized, array $error ): ?bool {\n\t\t// Skip sanitization for missing publisher logos and poster portrait images.\n\t\tif (\n\t\t\tisset( $error['node_type'], $error['node_name'], $error['parent_name'] ) &&\n\t\t\t(\n\t\t\t\t( XML_ELEMENT_NODE === $error['node_type'] && 'amp-story' === $error['node_name'] && 'body' === $error['parent_name'] ) ||\n\t\t\t\t( XML_ATTRIBUTE_NODE === $error['node_type'] && 'poster-portrait-src' === $error['node_name'] && 'amp-story' === $error['parent_name'] ) ||\n\t\t\t\t( XML_ATTRIBUTE_NODE === $error['node_type'] && 'publisher-logo-src' === $error['node_name'] && 'amp-story' === $error['parent_name'] )\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Skip sanitization for missing video posters.\n\t\tif ( isset( $error['node_name'] ) && 'amp-video' === $error['node_name'] ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Skip sanitization for amp-video > source with invalid src.\n\t\tif ( isset( $error['parent_name'] ) && 'source' === $error['parent_name'] ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $sanitized;\n\t}\n\n\t/**\n\t * Filters whether AMP-to-AMP is excluded for an element.\n\t *\n\t * The element may be either a link (`a` or `area`) or a `form`.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param bool|mixed      $excluded Excluded. Default value is whether element already has a `noamphtml` link relation or the URL is among `excluded_urls`.\n\t * @param string          $url      URL considered for exclusion.\n\t * @param string[]        $rel      Link relations.\n\t * @param DOMElement|null $element  The element considered for excluding from AMP-to-AMP linking. May be instance of `a`, `area`, or `form`.\n\t * @return bool|mixed Whether AMP-to-AMP is excluded.\n\t */\n\tpublic function filter_amp_to_amp_linking_element_excluded( $excluded, string $url, array $rel, ?DOMElement $element ) {\n\t\tif ( $element instanceof DOMElement && $element->parentNode instanceof DOMElement && 'amp-story-player' === $element->parentNode->tagName ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn $excluded;\n\t}\n\n\t/**\n\t * Filters whether to skip the post from AMP.\n\t *\n\t * Skips the post if the AMP plugin's version is lower than what is bundled in this plugin.\n\t * Prevents issues where this plugin uses newer features that the plugin doesn't know about yet,\n\t * causing false positives with validation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @link https://github.com/googleforcreators/web-stories-wp/issues/7131\n\t *\n\t * @param bool|mixed $skipped Whether the post should be skipped from AMP.\n\t * @param int        $post    Post ID.\n\t * @return bool|mixed Whether post should be skipped from AMP.\n\t */\n\tpublic function filter_amp_skip_post( $skipped, int $post ) {\n\t\t// This is the opposite to the `AMP__VERSION >= WEBSTORIES_AMP_VERSION` check in the HTML renderer.\n\t\tif (\n\t\t\t$this->story_post_type->get_slug() === get_post_type( $post )\n\t\t\t&&\n\t\t\t\\defined( '\\AMP__VERSION' )\n\t\t\t&&\n\t\t\tversion_compare( WEBSTORIES_AMP_VERSION, AMP__VERSION, '>' )\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn $skipped;\n\t}\n\n\t/**\n\t * Get the post type for the current request.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.2.0\n\t */\n\tprotected function get_request_post_type(): ?string {\n\t\t// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\n\t\tif ( did_action( 'wp' ) && is_singular() ) {\n\t\t\t$post_type = get_post_type( get_queried_object_id() );\n\t\t\treturn $post_type ?: null;\n\t\t}\n\n\t\tif (\n\t\t\tisset( $_GET['action'], $_GET['post'] ) &&\n\t\t\t'amp_validate' === $_GET['action'] &&\n\t\t\tis_admin()\n\t\t) {\n\t\t\t/**\n\t\t\t * Post ID.\n\t\t\t *\n\t\t\t * @var string|int $post_id\n\t\t\t */\n\t\t\t$post_id = $_GET['post'];\n\n\t\t\tif ( get_post_type( (int) $post_id ) === self::AMP_VALIDATED_URL_POST_TYPE ) {\n\t\t\t\treturn $this->get_validated_url_post_type( (int) $post_id );\n\t\t\t}\n\t\t}\n\n\t\t$current_screen_post_type = $this->context->get_screen_post_type();\n\n\t\tif ( $current_screen_post_type ) {\n\t\t\t$current_post = get_post();\n\n\t\t\tif ( self::AMP_VALIDATED_URL_POST_TYPE === $current_screen_post_type && $current_post instanceof WP_Post && $current_post->post_type === $current_screen_post_type ) {\n\t\t\t\t$validated_url_post_type = $this->get_validated_url_post_type( $current_post->ID );\n\t\t\t\tif ( $validated_url_post_type ) {\n\t\t\t\t\treturn $validated_url_post_type;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $current_screen_post_type;\n\t\t}\n\n\t\tif ( isset( $_SERVER['REQUEST_URI'] ) ) {\n\t\t\t/**\n\t\t\t * Request URI.\n\t\t\t *\n\t\t\t * @var string $request_uri\n\t\t\t */\n\t\t\t$request_uri = $_SERVER['REQUEST_URI'];\n\t\t\tif ( str_contains( (string) wp_unslash( $request_uri ), $this->story_post_type->get_rest_url() ) ) {\n\t\t\t\treturn $this->story_post_type->get_slug();\n\t\t\t}\n\t\t}\n\n\t\t// phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get the singular post type which is the queried object for the given validated URL post.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param int $post_id Post ID for Validated URL Post.\n\t * @return string|null Post type or null if validated URL is not for a singular post.\n\t */\n\tprotected function get_validated_url_post_type( int $post_id ): ?string {\n\t\tif ( empty( $post_id ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t$post = get_post( $post_id );\n\t\tif ( ! $post instanceof WP_Post ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( self::AMP_VALIDATED_URL_POST_TYPE !== $post->post_type ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t/**\n\t\t * AMP queried object.\n\t\t *\n\t\t * @var array{type?: string, id?: int|string}|string $queried_object\n\t\t */\n\t\t$queried_object = get_post_meta( $post->ID, '_amp_queried_object', true );\n\n\t\tif ( ! \\is_array( $queried_object ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( isset( $queried_object['id'], $queried_object['type'] ) && 'post' === $queried_object['type'] ) {\n\t\t\t/**\n\t\t\t * Post ID.\n\t\t\t *\n\t\t\t * @var int|string $post_id\n\t\t\t */\n\t\t\t$post_id = $queried_object['id'];\n\n\t\t\t$post_type = get_post_type( (int) $post_id );\n\t\t\tif ( $post_type ) {\n\t\t\t\treturn $post_type;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Conditional_Featured_Image.php",
    "content": "<?php\n/**\n * Class Conditional_Featured_Image\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Conditional_Featured_Image.\n */\nclass Conditional_Featured_Image extends Service_Base {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Conditional_Featured_Image constructor.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.16.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'cybocfi_enabled_for_post_type', [ $this, 'cybocfi_enabled_for_post_type' ], 99, 2 );\n\t}\n\n\t/**\n\t * Filter the conditional-featured-image plugin.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param mixed  $enabled   If enabled or not.\n\t * @param string $post_type Post type slug.\n\t * @return mixed Filter value.\n\t */\n\tpublic function cybocfi_enabled_for_post_type( $enabled, string $post_type ) {\n\t\tif ( $this->story_post_type->get_slug() === $post_type ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $enabled;\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Core_Themes_Support.php",
    "content": "<?php\n/**\n * Class Core_Themes_Support\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Admin\\Customizer;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Service_Base;\nuse function Google\\Web_Stories\\render_theme_stories;\n\n/**\n * Class Core_Themes_Support.\n */\nclass Core_Themes_Support extends Service_Base {\n\n\t/**\n\t * Default array of core themes to add support to.\n\t *\n\t * @var string[]\n\t */\n\tprotected static array $supported_themes = [\n\t\t'twentytwentyone',\n\t\t'twentytwenty',\n\t\t'twentynineteen',\n\t\t'twentyseventeen',\n\t\t'twentysixteen',\n\t\t'twentyfifteen',\n\t\t'twentyfourteen',\n\t\t'twentythirteen',\n\t\t'twentytwelve',\n\t\t'twentyeleven',\n\t\t'twentyten',\n\t];\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Core theme supports constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Assets $assets Assets instance.\n\t */\n\tpublic function __construct( Assets $assets ) {\n\t\t$this->assets = $assets;\n\t}\n\n\t/**\n\t * Adds theme support for Web Stories.\n\t *\n\t * This will enable add_theme_support with predefined\n\t * options supported themes.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function extend_theme_support(): void {\n\t\tadd_theme_support( 'web-stories' );\n\t}\n\n\t/**\n\t * Embed Webstories.\n\t *\n\t * Embeds web stories with default customizer settings.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function embed_web_stories(): void {\n\t\t$stylesheet = get_stylesheet();\n\t\tif ( is_readable( \\sprintf( '%sassets/css/web-stories-theme-style-%s.css', WEBSTORIES_PLUGIN_DIR_PATH, $stylesheet ) ) ) {\n\t\t\t$this->assets->enqueue_style_asset( 'web-stories-theme-style-' . $stylesheet, [] );\n\t\t}\n\t\t?>\n\t\t<div class=\"web-stories-theme-header-section\">\n\t\t\t<?php render_theme_stories(); ?>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Add a class if it is one of supported core themes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array|mixed $classes Array of body classes.\n\t * @return array|mixed Updated array of classes.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($classes is array<T> ? array<T> : mixed)\n\t */\n\tpublic function add_core_theme_classes( $classes ) {\n\t\tif ( ! \\is_array( $classes ) ) {\n\t\t\treturn $classes;\n\t\t}\n\t\t$classes[] = 'has-web-stories';\n\n\t\treturn $classes;\n\t}\n\n\t/**\n\t * Adds theme support and hook to embed the web stories.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register(): void {\n\t\tif ( ! \\in_array( get_stylesheet(), self::$supported_themes, true ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->extend_theme_support();\n\n\t\t// Not using Settings::get_setting() to avoid calling rest_sanitize_value_from_schema().\n\n\t\t/**\n\t\t * Customizer options.\n\t\t *\n\t\t * @var array<string, mixed> $options\n\t\t */\n\t\t$options = get_option( Customizer::STORY_OPTION, [] );\n\n\t\t// Load theme specific styles and render function only if selected to show stories.\n\t\tif ( empty( $options['show_stories'] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tadd_filter( 'body_class', [ $this, 'add_core_theme_classes' ] );\n\t\tadd_action( 'wp_body_open', [ $this, 'embed_web_stories' ] );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'wp_head';\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Ezoic.php",
    "content": "<?php\n/**\n * Class Ezoic\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\AMP\\Optimization;\nuse Google\\Web_Stories\\AMP\\Sanitization;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Exception\\SanitizationException;\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse Throwable;\n\n/**\n * Class Ezoic.\n */\nclass Ezoic extends Service_Base implements Conditional {\n\t/**\n\t * Sanitization instance.\n\t *\n\t * @var Sanitization Sanitization instance.\n\t */\n\tprivate Sanitization $sanitization;\n\n\t/**\n\t * Optimization instance.\n\t *\n\t * @var Optimization Optimization instance.\n\t */\n\tprivate Optimization $optimization;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Constructor.\n\t * \n\t * @since 1.33.0\n\t *\n\t * @param Sanitization $sanitization Sanitization instance.\n\t * @param Optimization $optimization Optimization instance.\n\t * @param Context      $context Context instance.\n\t */\n\tpublic function __construct( Sanitization $sanitization, Optimization $optimization, Context $context ) {\n\t\t$this->sanitization = $sanitization;\n\t\t$this->optimization = $optimization;\n\t\t$this->context      = $context;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.33.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'ez_buffered_final_content', [ $this, 'process_ez_buffered_final_content' ] );\n\t}\n\n\t/**\n\t * Check whether the Ezoic integration is currently needed.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @return bool Whether Ezoic integration is currently needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\treturn \\defined( 'EZOIC_INTEGRATION_VERSION' );\n\t}\n\n\t/**\n\t * Optimizes and Sanitizes Ezoic's final prepared content.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @param string $content HTML document response collected by Ezoic Output Buffer.\n\t * @return string AMP document response.\n\t */\n\tpublic function process_ez_buffered_final_content( string $content ): string {\n\t\tif ( $this->context->is_web_story() ) {\n\t\t\t// Enforce UTF-8 encoding as it is a requirement for AMP.\n\t\t\tif ( ! headers_sent() ) {\n\t\t\t\theader( 'Content-Type: text/html; charset=utf-8' );\n\t\t\t}\n\n\t\t\t$dom = Document::fromHtml( $content );\n\n\t\t\tif ( ! $dom instanceof Document ) {\n\t\t\t\treturn $this->render_error_page( SanitizationException::from_document_parse_error() );\n\t\t\t}\n\n\t\t\t$this->sanitization->sanitize_document( $dom );\n\t\t\t$this->optimization->optimize_document( $dom );\n\n\t\t\treturn $dom->saveHTML();\n\t\t}\n\t\treturn $content;\n\t}\n\n\t/**\n\t * Render error page.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @param Throwable $throwable Exception or (as of PHP7) Error.\n\t * @return string Error page.\n\t */\n\tprivate function render_error_page( Throwable $throwable ): string {\n\t\treturn esc_html__( 'There was an error generating the web story, probably because of a server misconfiguration. Try contacting your hosting provider or open a new support request.', 'web-stories' ) .\n\t\t\t\"\\n\" .\n\t\t\t\"\\n\" .\n\t\t\t// translators: 1: error message. 2: location.\n\t\t\t\\sprintf( esc_html__( 'Error message: %1$s (%2$s)', 'web-stories' ), $throwable->getMessage(), $throwable->getFile() . ':' . $throwable->getLine() );\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Jetpack.php",
    "content": "<?php\n/**\n * Class Jetpack\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Media\\Media_Source_Taxonomy;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\nuse WP_REST_Response;\n\n/**\n * Class Jetpack.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type AttachmentData array{\n *   media_details?: array{\n *     length?: int,\n *     length_formatted?: string\n *   },\n *   url?: string,\n *   featured_media_src?: string\n * }\n *\n * @phpstan-type EnhancedAttachmentMetadata array{\n *   width: int,\n *   height: int,\n *   file: string,\n *   sizes: mixed,\n *   image_meta: mixed,\n *   videopress?: array{\n *     duration: int,\n *     poster: string,\n *     width: int,\n *     height: int,\n *     file_url_base?: array{\n *       https: string\n *     },\n *     files?: array{\n *       hd?: array{\n *         mp4?: string\n *       }\n *     }\n *   }\n * }\n */\nclass Jetpack extends Service_Base {\n\n\t/**\n\t * VideoPress Mime type.\n\t *\n\t * @since 1.7.2\n\t */\n\tpublic const VIDEOPRESS_MIME_TYPE = 'video/videopress';\n\n\t/**\n\t * VideoPress poster meta key.\n\t *\n\t * @since 1.7.2\n\t */\n\tpublic const VIDEOPRESS_POSTER_META_KEY = 'videopress_poster_image';\n\n\t/**\n\t * Media_Source_Taxonomy instance.\n\t *\n\t * @var Media_Source_Taxonomy Experiments instance.\n\t */\n\tprotected Media_Source_Taxonomy $media_source_taxonomy;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Jetpack constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Media_Source_Taxonomy $media_source_taxonomy Media_Source_Taxonomy instance.\n\t * @param Context               $context               Context instance.\n\t */\n\tpublic function __construct( Media_Source_Taxonomy $media_source_taxonomy, Context $context ) {\n\t\t$this->media_source_taxonomy = $media_source_taxonomy;\n\t\t$this->context               = $context;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function register(): void {\n\t\t// See https://github.com/Automattic/jetpack/blob/4b85be883b3c584c64eeb2fb0f3fcc15dabe2d30/modules/custom-post-types/portfolios.php#L80.\n\t\tif ( \\defined( 'IS_WPCOM' ) && IS_WPCOM ) {\n\t\t\tadd_filter( 'wpcom_sitemap_post_types', [ $this, 'add_to_jetpack_sitemap' ] );\n\t\t} else {\n\t\t\tadd_filter( 'jetpack_sitemap_post_types', [ $this, 'add_to_jetpack_sitemap' ] );\n\t\t}\n\n\t\tadd_filter( 'jetpack_is_amp_request', [ $this, 'force_amp_request' ] );\n\t\tadd_filter( 'web_stories_allowed_mime_types', [ $this, 'add_videopress' ] );\n\t\tadd_filter( 'web_stories_rest_prepare_attachment', [ $this, 'filter_rest_api_response' ], 10, 2 );\n\t\tadd_filter( 'ajax_query_attachments_args', [ $this, 'filter_ajax_query_attachments_args' ] );\n\t\tadd_action( 'added_post_meta', [ $this, 'add_term' ], 10, 3 );\n\t}\n\n\t/**\n\t * Adds the web-story post type to Jetpack / WordPress.com sitemaps.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see https://github.com/Automattic/jetpack/blob/4b85be883b3c584c64eeb2fb0f3fcc15dabe2d30/modules/custom-post-types/portfolios.php#L80\n\t *\n\t * @param array|mixed $post_types Array of post types.\n\t * @return array|mixed Modified list of post types.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($post_types is array<T> ? array<T> : mixed)\n\t */\n\tpublic function add_to_jetpack_sitemap( $post_types ) {\n\t\tif ( ! \\is_array( $post_types ) ) {\n\t\t\treturn $post_types;\n\t\t}\n\t\t$post_types[] = Story_Post_Type::POST_TYPE_SLUG;\n\n\t\treturn $post_types;\n\t}\n\n\t/**\n\t * Add VideoPress to allowed mime types.\n\t *\n\t * If the site does not support VideoPress, this will be filtered out.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param array{video?: string[]}|mixed $mime_types Associative array of allowed mime types per media type (image, audio, video).\n\t * @return array{video?: string[]}|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($mime_types is array<T> ? array<T> : mixed)\n\t */\n\tpublic function add_videopress( $mime_types ) {\n\t\tif ( ! \\is_array( $mime_types ) ) {\n\t\t\treturn $mime_types;\n\t\t}\n\n\t\t/**\n\t\t * Mime types config.\n\t\t *\n\t\t * @var array{video?: string[]} $mime_types\n\t\t */\n\t\t$mime_types['video'][] = self::VIDEOPRESS_MIME_TYPE;\n\n\t\treturn $mime_types;\n\t}\n\n\n\t/**\n\t * Filter ajax query attachments args when accessed from the Web Stories editor.\n\t *\n\t * Only filters the response if the mime type matches exactly what Web Stories is looking for.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param array|mixed $args Query args.\n\t * @return array|mixed Filtered query args.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($args is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_ajax_query_attachments_args( $args ) {\n\t\tif ( ! \\is_array( $args ) || ! isset( $args['post_mime_type'] ) || ! \\is_array( $args['post_mime_type'] ) ) {\n\t\t\treturn $args;\n\t\t}\n\n\t\tif ( \\in_array( self::VIDEOPRESS_MIME_TYPE, $args['post_mime_type'], true ) ) {\n\t\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'filter_admin_ajax_response' ], 15, 2 );\n\t\t}\n\n\t\treturn $args;\n\t}\n\n\t/**\n\t * Filter admin ajax responses for VideoPress videos.\n\t *\n\t * Changes the video/videopress type back to mp4\n\t * and ensures MP4 source URLs are returned.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param array|mixed $data   Array of prepared attachment data. @see wp_prepare_attachment_for_js().\n\t * @param WP_Post     $attachment Attachment object.\n\t * @return array|mixed\n\t *\n\t * @phpstan-param AttachmentData|mixed $data\n\t * @phpstan-return AttachmentData|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($data is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_admin_ajax_response( $data, WP_Post $attachment ) {\n\t\tif ( self::VIDEOPRESS_MIME_TYPE !== $attachment->post_mime_type ) {\n\t\t\treturn $data;\n\t\t}\n\n\t\tif ( ! \\is_array( $data ) ) {\n\t\t\treturn $data;\n\t\t}\n\n\t\t// Reset mime type back to mp4, as this is the correct value.\n\t\t$data['mime']    = 'video/mp4';\n\t\t$data['subtype'] = 'mp4';\n\n\t\t// Mark video as optimized.\n\t\t$data[ $this->media_source_taxonomy::MEDIA_SOURCE_KEY ] = 'video-optimization';\n\n\t\t/**\n\t\t * Jetpack adds an additional field to regular attachment metadata.\n\t\t *\n\t\t * @var array $metadata\n\t\t * @phpstan-var EnhancedAttachmentMetadata|false $metadata\n\t\t */\n\t\t$metadata = wp_get_attachment_metadata( $attachment->ID );\n\n\t\tif ( $metadata && isset( $metadata['videopress']['duration'], $data['media_details'] ) && \\is_array( $data['media_details'] ) ) {\n\t\t\t$data['media_details']['length_formatted'] = $this->format_milliseconds( $metadata['videopress']['duration'] );\n\t\t\t$data['media_details']['length']           = (int) floor( $metadata['videopress']['duration'] / 1000 );\n\t\t}\n\n\t\tif ( $metadata && isset( $data['url'], $metadata['videopress']['file_url_base']['https'], $metadata['videopress']['files']['hd']['mp4'] ) ) {\n\t\t\t$data['url'] = $metadata['videopress']['file_url_base']['https'] . $metadata['videopress']['files']['hd']['mp4'];\n\t\t}\n\n\t\t// Get the correct poster with matching dimensions from VideoPress.\n\t\tif ( $metadata && isset( $data['featured_media_src'], $metadata['videopress']['poster'], $metadata['videopress']['width'], $metadata['videopress']['height'] ) ) {\n\t\t\t$data['featured_media_src'] = [\n\t\t\t\t'src'       => $metadata['videopress']['poster'],\n\t\t\t\t'width'     => $metadata['videopress']['width'],\n\t\t\t\t'height'    => $metadata['videopress']['height'],\n\t\t\t\t'generated' => true,\n\t\t\t];\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t/**\n\t * Filter REST API responses for VideoPress videos.\n\t *\n\t * Changes the video/videopress type back to mp4\n\t * and ensures MP4 source URLs are returned.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param WP_REST_Response $response The response object.\n\t * @param WP_Post          $post     The original attachment post.\n\t */\n\tpublic function filter_rest_api_response( WP_REST_Response $response, WP_Post $post ): WP_REST_Response {\n\t\tif ( self::VIDEOPRESS_MIME_TYPE !== $post->post_mime_type ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string, string|array<string, int|string>|bool> $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\t// Reset mime type back to mp4, as this is the correct value.\n\t\t$data['mime_type'] = 'video/mp4';\n\n\t\t// Mark video as optimized.\n\t\t$data[ $this->media_source_taxonomy::MEDIA_SOURCE_KEY ] = 'video-optimization';\n\n\t\t/**\n\t\t * Jetpack adds an additional field to regular attachment metadata.\n\t\t *\n\t\t * @var EnhancedAttachmentMetadata|false $metadata\n\t\t */\n\t\t$metadata = wp_get_attachment_metadata( $post->ID );\n\n\t\tif ( $metadata && isset( $metadata['videopress']['duration'], $data['media_details'] ) && \\is_array( $data['media_details'] ) ) {\n\t\t\t$data['media_details']['length_formatted'] = $this->format_milliseconds( $metadata['videopress']['duration'] );\n\t\t\t$data['media_details']['length']           = (int) floor( $metadata['videopress']['duration'] / 1000 );\n\t\t}\n\n\t\tif ( $metadata && isset( $data['source_url'], $metadata['videopress']['file_url_base']['https'], $metadata['videopress']['files']['hd']['mp4'] ) ) {\n\t\t\t$data['source_url'] = $metadata['videopress']['file_url_base']['https'] . $metadata['videopress']['files']['hd']['mp4'];\n\t\t}\n\n\t\t// Get the correct poster with matching dimensions from VideoPress.\n\t\tif ( $metadata && isset( $data['featured_media_src'], $metadata['videopress']['poster'], $metadata['videopress']['width'], $metadata['videopress']['height'] ) ) {\n\t\t\t$data['featured_media_src'] = [\n\t\t\t\t'src'       => $metadata['videopress']['poster'],\n\t\t\t\t'width'     => $metadata['videopress']['width'],\n\t\t\t\t'height'    => $metadata['videopress']['height'],\n\t\t\t\t'generated' => true,\n\t\t\t];\n\t\t}\n\n\t\t$response->set_data( $data );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Hook into added_post_meta.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param int    $mid         The meta ID after successful update.\n\t * @param int    $object_id   ID of the object metadata is for.\n\t * @param string $meta_key    Metadata key.\n\t */\n\tpublic function add_term( int $mid, int $object_id, string $meta_key ): void {\n\t\tif ( self::VIDEOPRESS_POSTER_META_KEY !== $meta_key ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( 'attachment' !== get_post_type( $object_id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\twp_set_object_terms( (int) $object_id, $this->media_source_taxonomy::TERM_POSTER_GENERATION, $this->media_source_taxonomy->get_taxonomy_slug() );\n\t}\n\n\t/**\n\t * Force Jetpack to see Web Stories as AMP.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param bool $is_amp_request Is the request supposed to return valid AMP content.\n\t * @return bool Whether the current request is an AMP request.\n\t */\n\tpublic function force_amp_request( bool $is_amp_request ): bool {\n\t\tif ( ! $this->context->is_web_story() ) {\n\t\t\treturn (bool) $is_amp_request;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Format milliseconds into seconds.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param int $milliseconds Milliseconds to converted to minutes and seconds.\n\t */\n\tprotected function format_milliseconds( int $milliseconds ): string {\n\t\t$seconds = floor( $milliseconds / 1000 );\n\n\t\tif ( $seconds >= 1 ) {\n\t\t\t$minutes  = floor( $seconds / 60 );\n\t\t\t$seconds %= 60;\n\t\t} else {\n\t\t\t$seconds = 0;\n\t\t\t$minutes = 0;\n\t\t}\n\n\t\treturn \\sprintf( '%d:%02u', $minutes, $seconds );\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/New_Relic.php",
    "content": "<?php\n/**\n * Class New_Relic\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Infrastructure\\Conditional;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * New Relic integration class.\n *\n * @since 1.10.0\n */\nclass New_Relic extends Service_Base implements Conditional {\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Single constructor.\n\t *\n\t * @param Context $context Context instance.\n\t */\n\tpublic function __construct( Context $context ) {\n\t\t$this->context = $context;\n\t}\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t$this->disable_autorum();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'template_redirect';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\t// Run at the same time as the output buffering.\n\t\treturn PHP_INT_MIN;\n\t}\n\n\t/**\n\t * Check whether the conditional object is currently needed.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return bool Whether the conditional object is needed.\n\t */\n\tpublic static function is_needed(): bool {\n\t\treturn \\function_exists( '\\newrelic_disable_autorum' );\n\t}\n\n\t/**\n\t * Disable the New Relic Browser agent on AMP responses.\n\t *\n\t * This prevents the New Relic from causing invalid AMP responses due the NREUM script it injects after the meta charset:\n\t *\n\t * https://docs.newrelic.com/docs/browser/new-relic-browser/troubleshooting/google-amp-validator-fails-due-3rd-party-script\n\t *\n\t * Sites with New Relic will need to specially configure New Relic for AMP:\n\t * https://docs.newrelic.com/docs/browser/new-relic-browser/installation/monitor-amp-pages-new-relic-browser\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function disable_autorum(): void {\n\t\tif ( ! $this->context->is_web_story() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t\\newrelic_disable_autorum();\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/NextGen_Gallery.php",
    "content": "<?php\n/**\n * Class NextGen_Gallery\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class NextGen_Gallery.\n */\nclass NextGen_Gallery extends Service_Base {\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'run_ngg_resource_manager', [ $this, 'filter_run_ngg_resource_manager' ], PHP_INT_MAX );\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn -2;\n\t}\n\n\t/**\n\t * Filters NextGEN Gallery's resource manager behavior.\n\t *\n\t * Disables output buffering for Web Stories.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see https://github.com/imagely/nextgen-gallery/blob/9736cc05e63b6b4cceb10b8a9a1de276f5c1ad4b/non_pope/class.photocrati_resource_manager.php\n\t *\n\t * @param bool|mixed $valid_request Whether NextGEN Gallery's output buffer should run.\n\t * @return bool|mixed Whether the output buffer should run.\n\t */\n\tpublic function filter_run_ngg_resource_manager( $valid_request ) {\n\t\t$request_uri_path = $this->get_request_uri_path();\n\n\t\tif (\n\t\t\t// Plain permalinks.\n\t\t\t// phpcs:ignore WordPress.Security.NonceVerification.Recommended\n\t\t\t! empty( $_GET[ Story_Post_Type::POST_TYPE_SLUG ] ) ||\n\t\t\t// Pretty permalinks.\n\t\t\t(\n\t\t\t\t$request_uri_path &&\n\t\t\t\tpreg_match(\n\t\t\t\t\t'#/' . preg_quote( Story_Post_Type::REWRITE_SLUG, '#' ) . '/.*?$#',\n\t\t\t\t\t// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\t\t\t\t\t$request_uri_path\n\t\t\t\t)\n\t\t\t)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $valid_request;\n\t}\n\n\t/**\n\t * Returns the current request path.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @return string|null Request URI path on success, null on failure.\n\t */\n\tprivate function get_request_uri_path(): ?string {\n\t\t// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\t\tif ( ! isset( $_SERVER['REQUEST_URI'] ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( ! \\is_string( $_SERVER['REQUEST_URI'] ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t/**\n\t\t * Request URI.\n\t\t *\n\t\t * @var string $request_uri\n\t\t */\n\t\t$request_uri = $_SERVER['REQUEST_URI'];\n\n\t\t// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized\n\n\t\t/**\n\t\t * Request URI path.\n\t\t *\n\t\t * @var string|null|false $path\n\t\t */\n\t\t$path = wp_parse_url( $request_uri, PHP_URL_PATH );\n\n\t\tif ( ! $path ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn $path;\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Plugin_Status.php",
    "content": "<?php\n/**\n * Class Plugin_Status\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2023 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\n/**\n * Class Plugin_Status.\n */\nclass Plugin_Status {\n\t/**\n\t * Array of arrays of plugin data, keyed by plugin file name.\n\t *\n\t * @see get_plugin_data()\n\t *\n\t * @var array<string, array<string, string|bool>>\n\t */\n\tprotected array $plugins = [];\n\n\t/**\n\t * Constructor.\n\t */\n\tpublic function __construct() {\n\t\tif ( ! \\function_exists( '\\get_plugins' ) ) {\n\t\t\trequire_once ABSPATH . 'wp-admin/includes/plugin.php';\n\t\t}\n\n\t\t$this->plugins = get_plugins();\n\t}\n\n\t/**\n\t * Retrieves all plugin files with plugin data.\n\t *\n\t * @since 1.30.0\n\t *\n\t * @return array<string, array<string, string|bool>>\n\t */\n\tpublic function get_plugins(): array {\n\t\treturn $this->plugins;\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/ShortPixel.php",
    "content": "<?php\n/**\n * Class ShortPixel.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class ShortPixel\n */\nclass ShortPixel extends Service_Base {\n\n\t/**\n\t * Runs on instantiation.\n\t *\n\t * @since 1.23.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'shortpixel_image_urls', [ $this, 'image_urls' ] );\n\t}\n\n\t/**\n\t * Ensures page template urls bypass optimisation.\n\t *\n\t * @since 1.23.0\n\t *\n\t * @param string[] $urls  Urls that will be sent to optimisation.\n\t * @return string[] The filtered Urls.\n\t */\n\tpublic function image_urls( array $urls ): array {\n\t\treturn array_filter(\n\t\t\t$urls,\n\t\t\tstatic fn( $url ) => ! str_contains( $url, 'web-stories-page-template' )\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/Site_Kit.php",
    "content": "<?php\n/**\n * Class Site_Kit\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\nuse Google\\Web_Stories\\Analytics;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Settings;\n\n/**\n * Class Site_Kit.\n *\n * @phpstan-type GtagOpt array{\n *   vars: array{\n *     gtag_id?: string\n *   },\n *   triggers?: array<string, mixed>\n * }\n */\nclass Site_Kit extends Service_Base {\n\t/**\n\t * Analytics instance.\n\t *\n\t * @var Analytics Analytics instance.\n\t */\n\tprotected Analytics $analytics;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Plugin_Status instance.\n\t *\n\t * @var Plugin_Status Plugin_Status instance.\n\t */\n\tprivate Plugin_Status $plugin_status;\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Analytics     $analytics     Analytics instance.\n\t * @param Context       $context       Context instance.\n\t * @param Plugin_Status $plugin_status Plugin_Status instance.\n\t * @param Settings      $settings      Settings instance.\n\t */\n\tpublic function __construct( Analytics $analytics, Context $context, Plugin_Status $plugin_status, Settings $settings ) {\n\t\t$this->analytics     = $analytics;\n\t\t$this->context       = $context;\n\t\t$this->plugin_status = $plugin_status;\n\t\t$this->settings      = $settings;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'googlesitekit_amp_gtag_opt', [ $this, 'filter_site_kit_gtag_opt' ] );\n\n\t\tadd_filter(\n\t\t\t'googlesitekit_analytics-4_tag_amp_blocked',\n\t\t\tfunction ( $blocked ) {\n\t\t\t\t$handler = $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_HANDLER );\n\n\t\t\t\tif ( 'web-stories' === $handler && $this->context->is_web_story() ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn $blocked;\n\t\t\t}\n\t\t);\n\n\t\tadd_action(\n\t\t\t'web_stories_print_analytics',\n\t\t\tfunction (): void {\n\t\t\t\t$handler = $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_HANDLER );\n\t\t\t\tif ( 'site-kit' === $handler && $this->is_analytics_module_active() ) {\n\t\t\t\t\tremove_action( 'web_stories_print_analytics', [ $this->analytics, 'print_analytics_tag' ] );\n\t\t\t\t}\n\t\t\t},\n\t\t\t5\n\t\t);\n\t}\n\n\t/**\n\t * Filters Site Kit's Google Analytics configuration.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param array|mixed $gtag_opt Array of gtag configuration options.\n\t * @return array|mixed Modified configuration options.\n\t *\n\t * @phpstan-param GtagOpt|mixed $gtag_opt\n\t */\n\tpublic function filter_site_kit_gtag_opt( $gtag_opt ) {\n\t\tif (\n\t\t\t! \\is_array( $gtag_opt ) ||\n\t\t\t! \\is_array( $gtag_opt['vars'] ) ||\n\t\t\t! isset( $gtag_opt['vars']['gtag_id'] ) ||\n\t\t\t! \\is_string( $gtag_opt['vars']['gtag_id'] ) ||\n\t\t\t! $this->context->is_web_story()\n\t\t) {\n\t\t\treturn $gtag_opt;\n\t\t}\n\n\t\t$default_config             = $this->analytics->get_default_configuration( $gtag_opt['vars']['gtag_id'] );\n\t\t$default_config['triggers'] = $default_config['triggers'] ?? [];\n\n\t\t$gtag_opt['triggers'] ??= [];\n\t\t// @phpstan-ignore argument.type\n\t\t$gtag_opt['triggers'] = array_merge( $default_config['triggers'], $gtag_opt['triggers'] );\n\n\t\treturn $gtag_opt;\n\t}\n\n\t/**\n\t * Returns the Site Kit plugin status.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return array{installed: bool, active: bool, analyticsActive: bool, adsenseActive: bool, analyticsLink: string, adsenseLink: string} Plugin status.\n\t */\n\tpublic function get_plugin_status(): array {\n\t\t$is_installed        = \\array_key_exists( 'google-site-kit/google-site-kit.php', $this->plugin_status->get_plugins() );\n\t\t$is_active           = $this->is_plugin_active();\n\t\t$is_analytics_active = $this->is_analytics_module_active();\n\t\t$is_adsense_active   = $this->is_adsense_module_active();\n\n\t\t$analytics_link = __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' );\n\t\t$adsense_link   = __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' );\n\t\t$dashboard      = admin_url( 'admin.php?page=googlesitekit-dashboard' );\n\t\t$settings       = admin_url( 'admin.php?page=googlesitekit-settings' );\n\n\t\tif ( $is_active ) {\n\t\t\t$dashboard_capability = current_user_can( 'googlesitekit_view_dashboard' ); // phpcs:ignore WordPress.WP.Capabilities.Unknown\n\t\t\t$settings_capability  = current_user_can( 'googlesitekit_manage_options' ); // phpcs:ignore WordPress.WP.Capabilities.Unknown\n\n\t\t\t// If analytics is active and current user can view dashboard.\n\t\t\tif ( $is_analytics_active && $dashboard_capability ) {\n\t\t\t\t$analytics_link = $dashboard;\n\t\t\t} elseif ( $settings_capability ) {\n\t\t\t\t$analytics_link = $settings;\n\t\t\t} elseif ( $dashboard_capability ) {\n\t\t\t\t$analytics_link = $dashboard;\n\t\t\t}\n\n\t\t\t// If adsense is active and current user can view dashboard.\n\t\t\tif ( $is_adsense_active && $dashboard_capability ) {\n\t\t\t\t$adsense_link = $dashboard;\n\t\t\t} elseif ( $settings_capability ) {\n\t\t\t\t$adsense_link = $settings;\n\t\t\t} elseif ( $dashboard_capability ) {\n\t\t\t\t$adsense_link = $dashboard;\n\t\t\t}\n\t\t} elseif ( $is_installed ) {\n\t\t\tif ( current_user_can( 'activate_plugin', 'google-site-kit/google-site-kit.php' ) ) {\n\t\t\t\t$analytics_link = admin_url( 'plugins.php' );\n\t\t\t\t$adsense_link   = $analytics_link;\n\t\t\t}\n\t\t} elseif ( current_user_can( 'install_plugins' ) ) {\n\t\t\t$analytics_link = admin_url(\n\t\t\t\tadd_query_arg(\n\t\t\t\t\t[\n\t\t\t\t\t\t's'   => rawurlencode( __( 'Site Kit by Google', 'web-stories' ) ),\n\t\t\t\t\t\t'tab' => 'search',\n\t\t\t\t\t],\n\t\t\t\t\t'plugin-install.php'\n\t\t\t\t)\n\t\t\t);\n\t\t\t$adsense_link   = $analytics_link;\n\t\t}\n\n\t\treturn [\n\t\t\t'installed'       => $is_active || $is_installed,\n\t\t\t'active'          => $is_active,\n\t\t\t'analyticsActive' => $is_analytics_active,\n\t\t\t'adsenseActive'   => $is_adsense_active,\n\t\t\t'analyticsLink'   => $analytics_link,\n\t\t\t'adsenseLink'     => $adsense_link,\n\t\t];\n\t}\n\n\t/**\n\t * Determines whether Site Kit is active.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool Whether Site Kit is active.\n\t */\n\tprotected function is_plugin_active(): bool {\n\t\treturn \\defined( 'GOOGLESITEKIT_VERSION' );\n\t}\n\n\n\t/**\n\t * Determines whether the built-in adsense module in Site Kit is active.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @return bool Whether Site Kit's analytics module is active.\n\t */\n\tprotected function is_adsense_module_active(): bool {\n\t\t$adsense_module_active       = \\in_array( 'adsense', $this->get_site_kit_active_modules_option(), true );\n\t\t$adsense_options             = (array) get_option( 'googlesitekit_adsense_settings' );\n\t\t$adsense_options_client_id   = ! empty( $adsense_options['clientID'] );\n\t\t$adsense_options_use_snippet = ! empty( $adsense_options['useSnippet'] );\n\t\t$adsense_web_stories_ad_unit = ! empty( $adsense_options['webStoriesAdUnit'] );\n\n\t\treturn $adsense_module_active && $adsense_options_use_snippet && $adsense_web_stories_ad_unit && $adsense_options_client_id;\n\t}\n\n\t/**\n\t * Determines whether the built-in Analytics module in Site Kit is active.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool Whether Site Kit's analytics module is active.\n\t */\n\tprotected function is_analytics_module_active(): bool {\n\t\t$analytics_module_active = \\in_array( 'analytics', $this->get_site_kit_active_modules_option(), true );\n\t\t$analytics_options       = (array) get_option( 'googlesitekit_analytics_settings' );\n\t\t$analytics_use_snippet   = ! empty( $analytics_options['useSnippet'] );\n\n\t\treturn $analytics_module_active && $analytics_use_snippet;\n\t}\n\n\t/**\n\t * Gets the option containing the active Site Kit modules.\n\t *\n\t * Checks two options as it was renamed at some point in Site Kit.\n\t *\n\t * Bails early if the Site Kit plugin itself is not active.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see \\Google\\Site_Kit\\Core\\Modules\\Modules::get_active_modules_option\n\t *\n\t * @return string[] List of active module slugs.\n\t */\n\tprotected function get_site_kit_active_modules_option(): array {\n\t\tif ( ! $this->is_plugin_active() ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t/**\n\t\t * Option value.\n\t\t *\n\t\t * @var string[]|false $option\n\t\t */\n\t\t$option = get_option( 'googlesitekit_active_modules' );\n\n\t\tif ( \\is_array( $option ) ) {\n\t\t\treturn $option;\n\t\t}\n\n\t\t/**\n\t\t * Legacy option value.\n\t\t *\n\t\t * @var string[]|false $legacy_option\n\t\t */\n\t\t$legacy_option = get_option( 'googlesitekit-active-modules' );\n\n\t\tif ( \\is_array( $legacy_option ) ) {\n\t\t\treturn $legacy_option;\n\t\t}\n\n\t\treturn [];\n\t}\n}\n"
  },
  {
    "path": "includes/Integrations/WooCommerce.php",
    "content": "<?php\n/**\n * Class WooCommerce\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Integrations;\n\n/**\n * Class WooCommerce.\n */\nclass WooCommerce {\n\t/**\n\t * Main plugin file.\n\t */\n\tprotected const PLUGIN = 'woocommerce/woocommerce.php';\n\n\t/**\n\t * Plugin_Status instance.\n\t *\n\t * @var Plugin_Status Plugin_Status instance.\n\t */\n\tprivate Plugin_Status $plugin_status;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Plugin_Status $plugin_status Plugin_Status instance.\n\t */\n\tpublic function __construct( Plugin_Status $plugin_status ) {\n\t\t$this->plugin_status = $plugin_status;\n\t}\n\n\t/**\n\t * Returns the WooCommerce plugin status.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return array{installed: bool, active: bool, canManage: bool, link: string} Plugin status.\n\t */\n\tpublic function get_plugin_status(): array {\n\t\t$is_installed = \\array_key_exists( self::PLUGIN, $this->plugin_status->get_plugins() );\n\t\t$is_active    = $this->is_plugin_active();\n\t\t$can_manage   = false;\n\t\t$link         = '';\n\n\t\tif ( $is_active ) {\n\t\t\t$can_manage = current_user_can( 'manage_woocommerce' ); // phpcs:ignore WordPress.WP.Capabilities.Unknown\n\t\t\tif ( $can_manage ) {\n\t\t\t\t$link = admin_url( 'admin.php?page=wc-admin' );\n\t\t\t}\n\t\t} elseif ( $is_installed ) {\n\t\t\tif ( current_user_can( 'activate_plugin', self::PLUGIN ) ) {\n\t\t\t\t$link = admin_url( 'plugins.php' );\n\t\t\t}\n\t\t} elseif ( current_user_can( 'install_plugins' ) ) {\n\t\t\t$link = admin_url(\n\t\t\t\tadd_query_arg(\n\t\t\t\t\t[\n\t\t\t\t\t\t's'   => rawurlencode( __( 'WooCommerce', 'web-stories' ) ),\n\t\t\t\t\t\t'tab' => 'search',\n\t\t\t\t\t],\n\t\t\t\t\t'plugin-install.php'\n\t\t\t\t)\n\t\t\t);\n\t\t} else {\n\t\t\t$link = __( 'https://wordpress.org/plugins/woocommerce/', 'web-stories' );\n\t\t}\n\n\t\treturn [\n\t\t\t'installed' => $is_active || $is_installed,\n\t\t\t'active'    => $is_active,\n\t\t\t'canManage' => $can_manage,\n\t\t\t'link'      => $link,\n\t\t];\n\t}\n\n\t/**\n\t * Determines whether WooCommerce is active.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return bool Whether WooCommerce is active.\n\t */\n\tprotected function is_plugin_active(): bool {\n\t\treturn class_exists( 'WooCommerce', false );\n\t}\n}\n"
  },
  {
    "path": "includes/Interfaces/Field.php",
    "content": "<?php\n/**\n * Field Interface.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\n/**\n * Interface Field.\n */\ninterface Field {\n\n\t/**\n\t * Whether to display the field.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function show(): bool;\n\n\t/**\n\t * Label for current field.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function label(): string;\n\n\t/**\n\t * Whether the field is hidden.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function hidden(): bool;\n}\n"
  },
  {
    "path": "includes/Interfaces/FieldState.php",
    "content": "<?php\n/**\n * Field State Interface\n *\n * Renderer fields will change state based on view types.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\n/**\n * Interface FieldState.\n */\ninterface FieldState {\n\n\t/**\n\t * Get title field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function title();\n\n\t/**\n\t * Get excerpt field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function excerpt();\n\n\t/**\n\t * Get image alignment field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function image_alignment();\n\n\t/**\n\t * Get author field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function author();\n\n\t/**\n\t * Get date field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function date();\n\n\t/**\n\t * Get archive link field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function archive_link();\n\n\t/**\n\t * Get sharp corner field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function sharp_corners();\n\n\t/**\n\t * Get circle size field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.40.0\n\t *\n\t * @return Field\n\t */\n\tpublic function circle_size();\n\n\t/**\n\t * Get number of columns field along with its state for\n\t * current view type.\n\t *\n\t * @since 1.40.0\n\t *\n\t * @return Field\n\t */\n\tpublic function number_of_columns();\n}\n"
  },
  {
    "path": "includes/Interfaces/FieldStateFactory.php",
    "content": "<?php\n/**\n * Field State Factory Interface\n *\n * Factory for field state types.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\n/**\n * Interface FieldState.\n */\ninterface FieldStateFactory {\n\n\t/**\n\t * Get field state by title.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return FieldState\n\t */\n\tpublic function get_field();\n}\n"
  },
  {
    "path": "includes/Interfaces/Migration.php",
    "content": "<?php\n/**\n * Migration Interface.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\n/**\n * Interface Migration\n */\ninterface Migration {\n\n\t/**\n\t * Migrate\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void;\n}\n"
  },
  {
    "path": "includes/Interfaces/Product_Query.php",
    "content": "<?php\n/**\n * Interface Product_Query\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\nuse Google\\Web_Stories\\Shopping\\Product;\nuse WP_Error;\n\n/**\n * Interface Product_Query.\n */\ninterface Product_Query {\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort collection by product attribute.\n\t * @param string $order       Order sort attribute ascending or descending.\n\t * @return array{products: array<Product>, has_next_page: bool}|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' );\n}\n"
  },
  {
    "path": "includes/Interfaces/Renderer.php",
    "content": "<?php\n/**\n * Renderer Interface.\n *\n * Stories renderers should conform to this interface,\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Interfaces;\n\n/**\n * Interface Renderer.\n */\ninterface Renderer {\n\n\t/**\n\t * Initial actions to setup the renderer like,\n\t * adding hooks and setting up states.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function init(): void;\n\n\t/**\n\t * Render the markup for story.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Array of rendering related arguments.\n\t * @return string Rendering markup.\n\t */\n\tpublic function render( array $args = [] ): string;\n\n\t/**\n\t * Render a single story markup.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return mixed\n\t */\n\tpublic function render_single_story_content();\n}\n"
  },
  {
    "path": "includes/KSES.php",
    "content": "<?php\n/**\n * Class KSES.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\AMP\\Meta_Sanitizer;\nuse Google\\Web_Stories\\AMP\\Tag_And_Attribute_Sanitizer;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories_Dependencies\\AMP_Content_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Script_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * KSES class.\n *\n * Provides KSES utility methods to override the ones from core.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type PostData array{\n *   post_parent: int|string|null,\n *   post_type: string,\n *   post_content?: string,\n *   post_content_filtered?: string\n * }\n */\nclass KSES extends Service_Base implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Page_Template_Post_Type instance.\n\t *\n\t * @var Page_Template_Post_Type Page_Template_Post_Type instance.\n\t */\n\tprivate Page_Template_Post_Type $page_template_post_type;\n\n\t/**\n\t * KSES constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Story_Post_Type         $story_post_type         Story_Post_Type instance.\n\t * @param Page_Template_Post_Type $page_template_post_type Page_Template_Post_Type instance.\n\t */\n\tpublic function __construct(\n\t\tStory_Post_Type $story_post_type,\n\t\tPage_Template_Post_Type $page_template_post_type\n\t) {\n\t\t$this->story_post_type         = $story_post_type;\n\t\t$this->page_template_post_type = $page_template_post_type;\n\t}\n\n\t/**\n\t * Initializes KSES filters for stories.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'wp_insert_post_data', [ $this, 'filter_insert_post_data' ], 10, 3 );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type', 'page_template_post_type' ];\n\t}\n\n\t/**\n\t * Filters slashed post data just before it is inserted into the database.\n\t *\n\t * Used to run story HTML markup through full AMP sanitization instead of just KSES.\n\t *\n\t * This allows storing full, valid AMP HTML documents in post_content for stories, which require\n\t * more allowed HTML tags.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param mixed $data                An array of slashed, sanitized, and processed post data.\n\t * @param mixed $postarr             An array of sanitized (and slashed) but otherwise unmodified post data.\n\t * @param mixed $unsanitized_postarr An array of slashed yet *unsanitized* and unprocessed post data as\n\t *                                   originally passed to wp_insert_post().\n\t * @return array<string,mixed>|mixed Filtered post data.\n\t *\n\t * @phpstan-param PostData|mixed $data\n\t * @phpstan-param PostData|mixed $unsanitized_postarr\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($data is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_insert_post_data( $data, $postarr, $unsanitized_postarr ) {\n\t\tif ( current_user_can( 'unfiltered_html' ) ) {\n\t\t\treturn $data;\n\t\t}\n\n\t\tif ( ! \\is_array( $data ) || ! \\is_array( $postarr ) || ! \\is_array( $unsanitized_postarr ) ) {\n\t\t\treturn $data;\n\t\t}\n\n\t\tif (\n\t\t\t! \\is_string( $data['post_type'] ) ||\n\t\t\t// @phpstan-ignore argument.type\n\t\t\t! $this->is_allowed_post_type( $data['post_type'], $data['post_parent'] )\n\t\t) {\n\t\t\treturn $data;\n\t\t}\n\n\t\tif (\n\t\t\tisset( $unsanitized_postarr['post_content_filtered'] ) &&\n\t\t\t\\is_string( $unsanitized_postarr['post_content_filtered'] )\n\t\t) {\n\t\t\t$data['post_content_filtered'] = $this->filter_story_data( $unsanitized_postarr['post_content_filtered'] );\n\t\t}\n\n\t\tif ( isset( $unsanitized_postarr['post_content'] ) ) {\n\t\t\t// @phpstan-ignore argument.type\n\t\t\t$data['post_content'] = wp_slash( $this->sanitize_content( wp_unslash( $unsanitized_postarr['post_content'] ) ) );\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t/**\n\t * Sanitizes post content.\n\t *\n\t * @since 1.37.0\n\t *\n\t * @param string $content Unsanitized post content.\n\t */\n\tprivate function sanitize_content( string $content ): string {\n\t\t$dom = Document::fromHtml( $content );\n\t\tif ( $dom instanceof Document ) {\n\t\t\t$sanitizers = $this->get_sanitizers();\n\t\t\tAMP_Content_Sanitizer::sanitize_document( $dom, $sanitizers, [] );\n\t\t\treturn trim( $dom->saveHTML() );\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t/**\n\t * Returns a list of sanitizers to use.\n\t *\n\t * This is replica of the Sanitization class implementation\n\t * to have a minimal AMP sanitization for user-provided input.\n\t *\n\t * @since 1.37.0\n\t *\n\t * @see Sanitization\n\t *\n\t * @return array<string,array<string,bool|string[]|string>> Sanitizers.\n\t */\n\tprivate function get_sanitizers(): array {\n\t\t$sanitizers = [\n\t\t\tAMP_Script_Sanitizer::class        => [\n\t\t\t\t'sanitize_js_scripts' => true,\n\t\t\t],\n\t\t\tMeta_Sanitizer::class              => [],\n\t\t\tTag_And_Attribute_Sanitizer::class => [],\n\t\t];\n\n\t\tforeach ( $sanitizers as &$sanitizer ) {\n\t\t\t$sanitizer['validation_error_callback'] = static fn( array $error, array $data = [] ): bool => apply_filters( 'web_stories_amp_validation_error_sanitized', true, $error ); // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed\n\t\t}\n\n\t\tunset( $sanitizer );\n\n\t\treturn $sanitizers;\n\t}\n\n\t/**\n\t * Checks whether the post type is correct and user has capability to edit it.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param string          $post_type   Post type slug.\n\t * @param int|string|null $post_parent Parent post ID.\n\t * @return bool Whether the user can edit the provided post type.\n\t */\n\tprivate function is_allowed_post_type( string $post_type, $post_parent ): bool {\n\t\tif ( $this->story_post_type->get_slug() === $post_type && $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( $this->page_template_post_type->get_slug() === $post_type && $this->page_template_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// For story autosaves.\n\t\tif (\n\t\t\t(\n\t\t\t\t'revision' === $post_type &&\n\t\t\t\t! empty( $post_parent ) &&\n\t\t\t\tget_post_type( (int) $post_parent ) === $this->story_post_type->get_slug()\n\t\t\t) &&\n\t\t\t$this->story_post_type->has_cap( 'edit_posts' )\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Filters story data.\n\t *\n\t * Provides simple sanity check to ensure story data is valid JSON.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param string $story_data JSON-encoded story data.\n\t * @return string Sanitized & slashed story data.\n\t */\n\tprivate function filter_story_data( string $story_data ): string {\n\t\t$decoded = json_decode( (string) wp_unslash( $story_data ), true );\n\t\treturn null === $decoded ? '' : wp_slash( (string) wp_json_encode( $decoded ) );\n\t}\n}\n"
  },
  {
    "path": "includes/Locale.php",
    "content": "<?php\n/**\n * Locale class.\n *\n * Locale-related functionality.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse DateTime;\nuse DateTimeZone;\n\n/**\n * Locale class.\n */\nclass Locale {\n\t/**\n\t * Returns locale settings for use on the client side.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @return array<string,mixed> Locale settings.\n\t */\n\tpublic function get_locale_settings(): array {\n\t\tglobal $wp_locale;\n\n\t\t/* translators: Date format, see https://www.php.net/manual/en/datetime.format.php */\n\t\t$default_date_format = __( 'd/m/Y', 'web-stories' );\n\n\t\t/* translators: Date format, see https://www.php.net/manual/en/datetime.format.php */\n\t\t$default_time_format = __( 'g:i a', 'web-stories' );\n\n\t\t/**\n\t\t * Date format value.\n\t\t *\n\t\t * @var string $date_format\n\t\t */\n\t\t$date_format = get_option( 'date_format', $default_date_format );\n\t\tif ( empty( trim( $date_format ) ) ) {\n\t\t\t$date_format = $default_date_format;\n\t\t}\n\n\t\t/**\n\t\t * Time format value.\n\t\t *\n\t\t * @var string $time_format\n\t\t */\n\t\t$time_format = get_option( 'time_format', $default_time_format );\n\t\tif ( empty( trim( $time_format ) ) ) {\n\t\t\t$time_format = $default_time_format;\n\t\t}\n\n\t\t/**\n\t\t * Time zone string.\n\t\t *\n\t\t * @var string $timezone_string\n\t\t */\n\t\t$timezone_string = get_option( 'timezone_string', 'UTC' );\n\t\t$timezone_abbr   = '';\n\n\t\tif ( ! empty( $timezone_string ) ) {\n\t\t\t$timezone_date = new DateTime( 'now', new DateTimeZone( $timezone_string ) );\n\t\t\t$timezone_abbr = $timezone_date->format( 'T' );\n\t\t}\n\n\t\t/**\n\t\t * Start of week value.\n\t\t *\n\t\t * @var int|string $start_of_week\n\t\t */\n\t\t$start_of_week = get_option( 'start_of_week', 0 );\n\n\t\t/**\n\t\t * GMT Offset.\n\t\t *\n\t\t * @var int $gmt_offset\n\t\t */\n\t\t$gmt_offset = get_option( 'gmt_offset', 0 );\n\n\t\treturn [\n\t\t\t'locale'           => str_replace( '_', '-', get_user_locale() ),\n\t\t\t'dateFormat'       => $date_format,\n\t\t\t'timeFormat'       => $time_format,\n\t\t\t'gmtOffset'        => (float) $gmt_offset,\n\t\t\t'timezone'         => $timezone_string,\n\t\t\t'timezoneAbbr'     => $timezone_abbr,\n\t\t\t'months'           => array_values( $wp_locale->month ),\n\t\t\t'monthsShort'      => array_values( $wp_locale->month_abbrev ),\n\t\t\t'weekdays'         => array_values( $wp_locale->weekday ),\n\t\t\t'weekdaysShort'    => array_values( $wp_locale->weekday_abbrev ),\n\t\t\t'weekdaysInitials' => array_values( $wp_locale->weekday_initial ),\n\t\t\t'weekStartsOn'     => (int) $start_of_week,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Base_Color.php",
    "content": "<?php\n/**\n * Class Image_Size\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Base_Color\n */\nclass Base_Color extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * The base color meta key.\n\t */\n\tpublic const BASE_COLOR_POST_META_KEY = 'web_stories_base_color';\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ] );\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::BASE_COLOR_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'type'           => 'string',\n\t\t\t\t'description'    => __( 'Attachment base color', 'web-stories' ),\n\t\t\t\t'show_in_rest'   => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type'   => 'string',\n\t\t\t\t\t\t'format' => 'hex-color',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'single'         => true,\n\t\t\t\t'object_subtype' => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param array|mixed $response   Array of prepared attachment data.\n\t * @return array|mixed $response;\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t/**\n\t\t * Attachment ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $response['id'];\n\n\t\t$response[ self::BASE_COLOR_POST_META_KEY ] = get_post_meta( $post_id, self::BASE_COLOR_POST_META_KEY, true );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::BASE_COLOR_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Blurhash.php",
    "content": "<?php\n/**\n * Class Blurhash\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Blurhash\n */\nclass Blurhash extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * The blurhash meta key.\n\t */\n\tpublic const BLURHASH_POST_META_KEY = 'web_stories_blurhash';\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.16.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ] );\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.16.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::BLURHASH_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'type'           => 'string',\n\t\t\t\t'description'    => __( 'Attachment BlurHash', 'web-stories' ),\n\t\t\t\t'show_in_rest'   => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'single'         => true,\n\t\t\t\t'object_subtype' => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param array|mixed $response Array of prepared attachment data.\n\t * @return array|mixed Response data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $response['id'];\n\n\t\t$response[ self::BLURHASH_POST_META_KEY ] = get_post_meta( $post_id, self::BLURHASH_POST_META_KEY, true );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::BLURHASH_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Cropping.php",
    "content": "<?php\n/**\n * Class Cropping\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Cropping\n */\nclass Cropping extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * The cropped video id post meta key.\n\t */\n\tpublic const CROPPED_ID_POST_META_KEY = 'web_stories_cropped_origin_id';\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t\tadd_action( 'delete_attachment', [ $this, 'delete_video' ] );\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::CROPPED_ID_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'absint',\n\t\t\t\t'type'              => 'integer',\n\t\t\t\t'description'       => __( 'Parent ID if this is a cropped attachment', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => 0,\n\t\t\t\t'single'            => true,\n\t\t\t\t'object_subtype'    => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Deletes associated meta data when a video is deleted.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param int $attachment_id ID of the attachment to be deleted.\n\t */\n\tpublic function delete_video( int $attachment_id ): void {\n\t\tdelete_metadata( 'post', 0, self::CROPPED_ID_POST_META_KEY, $attachment_id, true );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::CROPPED_ID_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Image_Sizes.php",
    "content": "<?php\n/**\n * Class Image_Size\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse Google\\Web_Stories\\Service_Base;\nuse WP_Post;\n\n/**\n * Class Image_Sizes\n */\nclass Image_Sizes extends Service_Base {\n\t/**\n\t * The image size for the poster-portrait-src.\n\t */\n\tpublic const POSTER_PORTRAIT_IMAGE_SIZE = 'web-stories-poster-portrait';\n\n\t/**\n\t * The image dimensions for the poster-portrait-src.\n\t */\n\tpublic const POSTER_PORTRAIT_IMAGE_DIMENSIONS = [ 640, 853 ];\n\n\t/**\n\t * Name of size used in media library.\n\t */\n\tpublic const STORY_THUMBNAIL_IMAGE_SIZE = 'web-stories-thumbnail';\n\n\t/**\n\t * The image dimensions for media library thumbnails.\n\t */\n\tpublic const STORY_THUMBNAIL_IMAGE_DIMENSIONS = [ 150, 9999 ];\n\n\t/**\n\t * The image size for the publisher logo.\n\t */\n\tpublic const PUBLISHER_LOGO_IMAGE_SIZE = 'web-stories-publisher-logo';\n\n\t/**\n\t * The image dimensions for the publisher logo.\n\t */\n\tpublic const PUBLISHER_LOGO_IMAGE_DIMENSIONS = [ 96, 96 ];\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\t$this->add_image_sizes();\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ], 10, 2 );\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array|mixed $response   Array of prepared attachment data.\n\t * @param WP_Post     $attachment Attachment object.\n\t * @return array|mixed $response;\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response, WP_Post $attachment ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\t\t// See https://github.com/WordPress/wordpress-develop/blob/d28766f8f2ecf2be02c2520cdf0cc3b51deb9e1b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php#L753-L791 .\n\t\t$response['media_details'] = wp_get_attachment_metadata( $attachment->ID );\n\n\t\t// Ensure empty details is an empty object.\n\t\tif ( empty( $response['media_details'] ) ) {\n\t\t\t$response['media_details'] = [];\n\t\t} elseif ( ! empty( $response['media_details']['sizes'] ) ) {\n\t\t\tforeach ( $response['media_details']['sizes'] as $size => &$size_data ) {\n\n\t\t\t\tif ( isset( $size_data['mime-type'] ) ) {\n\t\t\t\t\t$size_data['mime_type'] = $size_data['mime-type'];\n\t\t\t\t\tunset( $size_data['mime-type'] );\n\t\t\t\t}\n\n\t\t\t\t// Use the same method image_downsize() does.\n\t\t\t\t$image = wp_get_attachment_image_src( $attachment->ID, $size );\n\t\t\t\tif ( ! $image ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t[ $image_src ]           = $image;\n\t\t\t\t$size_data['source_url'] = $image_src;\n\t\t\t}\n\n\t\t\t$img_src = wp_get_attachment_image_src( $attachment->ID, 'full' );\n\n\t\t\tif ( $img_src ) {\n\t\t\t\t[ $src, $width, $height ] = $img_src;\n\n\t\t\t\t$response['media_details']['sizes']['full'] = [\n\t\t\t\t\t'file'       => wp_basename( $src ),\n\t\t\t\t\t'width'      => $width,\n\t\t\t\t\t'height'     => $height,\n\t\t\t\t\t'mime_type'  => $attachment->post_mime_type,\n\t\t\t\t\t'source_url' => $src,\n\t\t\t\t];\n\t\t\t}\n\t\t} else {\n\t\t\t$response['media_details']['sizes'] = [];\n\t\t}\n\n\n\t\treturn $response;\n\t}\n\n\n\t/**\n\t * Add image sizes.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @link https://amp.dev/documentation/components/amp-story/#poster-guidelines-for-poster-portrait-src-poster-landscape-src-and-poster-square-src.\n\t */\n\tprotected function add_image_sizes(): void {\n\t\t// Used for amp-story[poster-portrait-src]: The story poster in portrait format (3x4 aspect ratio).\n\t\tadd_image_size(\n\t\t\tself::POSTER_PORTRAIT_IMAGE_SIZE,\n\t\t\tself::POSTER_PORTRAIT_IMAGE_DIMENSIONS[0],\n\t\t\tself::POSTER_PORTRAIT_IMAGE_DIMENSIONS[1],\n\t\t\ttrue\n\t\t);\n\n\t\t// As per https://amp.dev/documentation/components/amp-story/#publisher-logo-src-guidelines.\n\t\tadd_image_size(\n\t\t\tself::PUBLISHER_LOGO_IMAGE_SIZE,\n\t\t\tself::PUBLISHER_LOGO_IMAGE_DIMENSIONS[0],\n\t\t\tself::PUBLISHER_LOGO_IMAGE_DIMENSIONS[1],\n\t\t\ttrue\n\t\t);\n\n\t\t// Used in the editor.\n\t\tadd_image_size(\n\t\t\tself::STORY_THUMBNAIL_IMAGE_SIZE,\n\t\t\tself::STORY_THUMBNAIL_IMAGE_DIMENSIONS[0],\n\t\t\tself::STORY_THUMBNAIL_IMAGE_DIMENSIONS[1],\n\t\t\tfalse\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Media_Source_Taxonomy.php",
    "content": "<?php\n/**\n * Class Media_Source_Taxonomy\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\REST_API\\Stories_Terms_Controller;\nuse Google\\Web_Stories\\Taxonomy\\Taxonomy_Base;\nuse ReflectionClass;\nuse WP_Post;\nuse WP_Query;\nuse WP_Site;\n\n/**\n * Class Media_Source_Taxonomy\n *\n * @phpstan-import-type TaxonomyArgs from \\Google\\Web_Stories\\Taxonomy\\Taxonomy_Base\n */\nclass Media_Source_Taxonomy extends Taxonomy_Base {\n\tpublic const TERM_EDITOR             = 'editor';\n\tpublic const TERM_POSTER_GENERATION  = 'poster-generation';\n\tpublic const TERM_SOURCE_VIDEO       = 'source-video';\n\tpublic const TERM_SOURCE_IMAGE       = 'source-image';\n\tpublic const TERM_VIDEO_OPTIMIZATION = 'video-optimization';\n\tpublic const TERM_PAGE_TEMPLATE      = 'page-template';\n\tpublic const TERM_GIF_CONVERSION     = 'gif-conversion';\n\tpublic const TERM_RECORDING          = 'recording';\n\n\t/**\n\t * Media Source key.\n\t */\n\tpublic const MEDIA_SOURCE_KEY = 'web_stories_media_source';\n\n\t/**\n\t * Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Single constructor.\n\t *\n\t * @param Context $context      Context instance.\n\t */\n\tpublic function __construct( Context $context ) {\n\t\t$this->context            = $context;\n\t\t$this->taxonomy_slug      = 'web_story_media_source';\n\t\t$this->taxonomy_post_type = 'attachment';\n\t}\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_taxonomy();\n\n\t\tadd_action( 'rest_api_init', [ $this, 'rest_api_init' ] );\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ] );\n\n\t\t// Hide video posters from Media grid view.\n\t\tadd_filter( 'ajax_query_attachments_args', [ $this, 'filter_ajax_query_attachments_args' ], PHP_INT_MAX );\n\t\t// Hide video posters from Media list view.\n\t\tadd_action( 'pre_get_posts', [ $this, 'filter_generated_media_attachments' ], PHP_INT_MAX );\n\t\t// Hide video posters from web-stories/v1/media REST API requests.\n\t\tadd_filter( 'web_stories_rest_attachment_query', [ $this, 'filter_rest_generated_media_attachments' ], PHP_INT_MAX );\n\t}\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\tparent::on_site_initialization( $site );\n\n\t\t$this->add_missing_terms();\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\tparent::on_plugin_activation( $network_wide );\n\n\t\t$this->add_missing_terms();\n\t}\n\n\t/**\n\t * Returns all defined media source term names.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @return string[] Media sources\n\t */\n\tpublic function get_all_terms(): array {\n\t\t$consts = ( new ReflectionClass( $this ) )->getConstants();\n\n\t\t/**\n\t\t * List of terms.\n\t\t *\n\t\t * @var string[] $terms\n\t\t */\n\t\t$terms = array_values(\n\t\t\tarray_filter(\n\t\t\t\t$consts,\n\t\t\t\tstatic fn( $key ) => str_starts_with( $key, 'TERM_' ),\n\t\t\t\tARRAY_FILTER_USE_KEY\n\t\t\t)\n\t\t);\n\n\t\treturn $terms;\n\t}\n\n\t/**\n\t * Registers additional REST API fields upon API initialization.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function rest_api_init(): void {\n\t\t// Custom field, as built in term update require term id and not slug.\n\t\tregister_rest_field(\n\t\t\t$this->taxonomy_post_type,\n\t\t\tself::MEDIA_SOURCE_KEY,\n\t\t\t[\n\n\t\t\t\t'get_callback'    => [ $this, 'get_callback_media_source' ],\n\t\t\t\t'schema'          => [\n\t\t\t\t\t'description' => __( 'Media source.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'enum'        => $this->get_all_terms(),\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'update_callback' => [ $this, 'update_callback_media_source' ],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string, mixed>|mixed $response   Array of prepared attachment data.\n\t * @return array|mixed $response Filtered attachment data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t// @phpstan-ignore argument.type (TODO: improve type)\n\t\t$response[ self::MEDIA_SOURCE_KEY ] = $this->get_callback_media_source( $response );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Force media attachment as string instead of the default array.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string, mixed> $prepared Prepared data before response.\n\t */\n\tpublic function get_callback_media_source( array $prepared ): string {\n\t\t/**\n\t\t * Taxonomy ID.\n\t\t *\n\t\t * @var int $id\n\t\t */\n\t\t$id = $prepared['id'];\n\n\t\t$terms = get_the_terms( $id, $this->taxonomy_slug );\n\t\tif ( \\is_array( $terms ) && ! empty( $terms ) ) {\n\t\t\treturn array_shift( $terms )->slug;\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t/**\n\t * Update rest field callback.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string  $value Value to update.\n\t * @param WP_Post $post  Object to update on.\n\t * @return true|\\WP_Error\n\t */\n\tpublic function update_callback_media_source( string $value, WP_Post $post ) {\n\t\t$check = wp_set_object_terms( $post->ID, $value, $this->taxonomy_slug );\n\t\tif ( is_wp_error( $check ) ) {\n\t\t\treturn $check;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Filters the attachment query args to hide generated video poster images.\n\t *\n\t * Reduces unnecessary noise in the Media grid view.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array<string, mixed>|mixed $args Query args.\n\t * @return array<string, mixed>|mixed Filtered query args.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($args is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_ajax_query_attachments_args( $args ) {\n\t\tif ( ! \\is_array( $args ) ) {\n\t\t\treturn $args;\n\t\t}\n\n\t\t// @phpstan-ignore argument.type (TODO: improve type)\n\t\t$args['tax_query'] = $this->get_exclude_tax_query( $args ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\n\t\treturn $args;\n\t}\n\n\t/**\n\t * Filters the current query to hide generated video poster images and source video.\n\t *\n\t * Reduces unnecessary noise in the Media list view.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param WP_Query $query WP_Query instance, passed by reference.\n\t */\n\tpublic function filter_generated_media_attachments( WP_Query $query ): void {\n\t\tif ( is_admin() && $query->is_main_query() && $this->context->is_upload_screen() ) {\n\t\t\t$tax_query = $query->get( 'tax_query' );\n\n\t\t\t$query->set( 'tax_query', $this->get_exclude_tax_query( [ 'tax_query' => $tax_query ] ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\t\t}\n\t}\n\n\t/**\n\t * Filters the current query to hide generated video poster images.\n\t *\n\t * Reduces unnecessary noise in media REST API requests.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array<string, mixed>|mixed $args Query args.\n\t * @return array<string, mixed>|mixed Filtered query args.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($args is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_rest_generated_media_attachments( $args ) {\n\t\tif ( ! \\is_array( $args ) ) {\n\t\t\treturn $args;\n\t\t}\n\n\t\t// @phpstan-ignore argument.type (TODO: improve type)\n\t\t$args['tax_query'] = $this->get_exclude_tax_query( $args ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\n\t\treturn $args;\n\t}\n\n\t/**\n\t * Adds missing terms to the taxonomy.\n\t *\n\t * @since 1.29.0\n\t */\n\tprivate function add_missing_terms(): void {\n\t\t$existing_terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t\t'fields'     => 'slugs',\n\t\t\t]\n\t\t);\n\n\t\tif ( is_wp_error( $existing_terms ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$missing_terms = array_diff( $this->get_all_terms(), $existing_terms );\n\n\t\tforeach ( $missing_terms as $term ) {\n\t\t\twp_insert_term( $term, $this->get_taxonomy_slug() );\n\t\t}\n\t}\n\n\t/**\n\t * Taxonomy args.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string,mixed> Taxonomy args.\n\t *\n\t * @phpstan-return TaxonomyArgs\n\t */\n\tprotected function taxonomy_args(): array {\n\t\treturn [\n\t\t\t'label'                 => __( 'Source', 'web-stories' ),\n\t\t\t'public'                => false,\n\t\t\t'rewrite'               => false,\n\t\t\t'hierarchical'          => false,\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t\t'rest_controller_class' => Stories_Terms_Controller::class,\n\t\t];\n\t}\n\n\t/**\n\t * Returns the tax query needed to exclude generated video poster images and source videos.\n\t *\n\t * @param array<string, mixed> $args Existing WP_Query args.\n\t * @return array<int|string, mixed> Tax query arg.\n\t */\n\tprivate function get_exclude_tax_query( array $args ): array {\n\t\t/**\n\t\t * Tax query.\n\t\t *\n\t\t * @var array<int|string, mixed> $tax_query\n\t\t */\n\t\t$tax_query = ! empty( $args['tax_query'] ) ? $args['tax_query'] : [];\n\n\t\t/**\n\t\t * Filter whether generated attachments should be hidden in the media library.\n\t\t *\n\t\t * @since 1.16.0\n\t\t *\n\t\t * @param bool  $enabled Whether the taxonomy check should be applied.\n\t\t * @param array $args    Existing WP_Query args.\n\t\t */\n\t\t$enabled = apply_filters( 'web_stories_hide_auto_generated_attachments', true, $args );\n\t\tif ( true !== $enabled ) {\n\t\t\treturn $tax_query;\n\t\t}\n\n\t\t/**\n\t\t * Merge with existing tax query if needed,\n\t\t * in a nested way so WordPress will run them\n\t\t * with an 'AND' relation. Example:\n\t\t *\n\t\t * [\n\t\t *   'relation' => 'AND', // implicit.\n\t\t *   [ this query ],\n\t\t *   [ [ any ], [ existing ], [ tax queries] ]\n\t\t * ]\n\t\t */\n\t\t$new_tax_query = [\n\t\t\t'relation' => 'AND',\n\t\t\t[\n\t\t\t\t'taxonomy' => $this->taxonomy_slug,\n\t\t\t\t'field'    => 'slug',\n\t\t\t\t'terms'    => [\n\t\t\t\t\tself::TERM_POSTER_GENERATION,\n\t\t\t\t\tself::TERM_SOURCE_VIDEO,\n\t\t\t\t\tself::TERM_SOURCE_IMAGE,\n\t\t\t\t\tself::TERM_PAGE_TEMPLATE,\n\t\t\t\t],\n\t\t\t\t'operator' => 'NOT IN',\n\t\t\t],\n\t\t];\n\n\t\tif ( ! empty( $tax_query ) ) {\n\t\t\t$new_tax_query[] = [ $tax_query ];\n\t\t}\n\n\t\treturn $new_tax_query;\n\t}\n}\n"
  },
  {
    "path": "includes/Media/SVG.php",
    "content": "<?php\n/**\n * Class SVG.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\nuse DOMDocument;\nuse DOMElement;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories_Dependencies\\enshrined\\svgSanitize\\Sanitizer;\nuse WP_Error;\n\n/**\n * Class SVG\n *\n * @since 1.3.0\n */\nclass SVG extends Service_Base {\n\t/**\n\t * File extension.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic const EXT = 'svg';\n\n\t/**\n\t * Mime type.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic const MIME_TYPE = 'image/svg+xml';\n\n\t/**\n\t * Cached list of SVG files and their contents.\n\t * Speeds up access during the same request.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @var string[]\n\t */\n\tprotected array $svgs = [];\n\n\t/**\n\t * Experiments instance.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @var Experiments Experiments instance.\n\t */\n\tprivate Experiments $experiments;\n\n\t/**\n\t * SVG constructor.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param Experiments $experiments Experiments instance.\n\t * @return void\n\t */\n\tpublic function __construct( Experiments $experiments ) {\n\t\t$this->experiments = $experiments;\n\t}\n\n\t/**\n\t * Register filters and actions.\n\t *\n\t * @since 1.3.0\n\t */\n\tpublic function register(): void {\n\t\tif ( ! $this->experiments->is_experiment_enabled( 'enableSVG' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tadd_filter( 'web_stories_allowed_mime_types', [ $this, 'web_stories_allowed_mime_types' ] );\n\n\t\t// Check if svg uploads, already enabled.\n\t\tif ( $this->svg_already_enabled() ) {\n\t\t\tadd_filter( 'mime_types', [ $this, 'mime_types_add_svg' ] );\n\t\t\treturn;\n\t\t}\n\n\t\tadd_filter( 'upload_mimes', [ $this, 'upload_mimes_add_svg' ] ); // phpcs:ignore WordPressVIPMinimum.Hooks.RestrictedHooks.upload_mimes\n\t\tadd_filter( 'mime_types', [ $this, 'mime_types_add_svg' ] );\n\t\tadd_filter( 'wp_handle_upload_prefilter', [ $this, 'wp_handle_upload' ] );\n\t\tadd_filter( 'wp_generate_attachment_metadata', [ $this, 'wp_generate_attachment_metadata' ], 10, 3 );\n\t\tadd_filter( 'wp_check_filetype_and_ext', [ $this, 'wp_check_filetype_and_ext' ], 10, 5 );\n\t\tadd_filter( 'site_option_upload_filetypes', [ $this, 'filter_list_of_allowed_filetypes' ] );\n\t}\n\n\t/**\n\t * Enable SVG upload.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param array<string, string> $mime_types Mime types keyed by the file extension regex corresponding to those types.\n\t * @return array<string, string>\n\t */\n\tpublic function upload_mimes_add_svg( array $mime_types ): array {\n\t\t// allow SVG file upload.\n\t\t$mime_types['svg']  = self::MIME_TYPE;\n\t\t$mime_types['svgz'] = self::MIME_TYPE;\n\n\t\treturn $mime_types;\n\t}\n\n\t/**\n\t * Adds SVG to list of mime types and file extensions\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string[] $mime_types Mime types keyed by the file extension regex\n\t *                             corresponding to those types.\n\t * @return array<string, string>\n\t */\n\tpublic function mime_types_add_svg( array $mime_types ): array {\n\t\t// allow SVG files.\n\t\t$mime_types['svg'] = self::MIME_TYPE;\n\n\t\treturn array_unique( $mime_types );\n\t}\n\n\t/**\n\t * Add SVG to allowed mime types.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param array<string, string[]> $mime_types Associative array of allowed mime types per media type (image, audio, video).\n\t * @return array<string, string[]>\n\t */\n\tpublic function web_stories_allowed_mime_types( array $mime_types ): array {\n\t\t$mime_types['vector'][] = self::MIME_TYPE;\n\n\t\treturn $mime_types;\n\t}\n\n\t/**\n\t * Add svg file type to allow file in multisite.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $value List of allowed file types.\n\t * @return string List of allowed file types.\n\t */\n\tpublic function filter_list_of_allowed_filetypes( string $value ): string {\n\t\t$filetypes = explode( ' ', $value );\n\t\tif ( ! \\in_array( self::EXT, $filetypes, true ) ) {\n\t\t\t$filetypes[] = self::EXT;\n\t\t\t$value       = implode( ' ', $filetypes );\n\t\t}\n\n\t\treturn $value;\n\t}\n\n\t/**\n\t * Hook into metadata generation and get height and width for SVG file.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param array<string,mixed> $metadata      An array of attachment meta data.\n\t * @param int                 $attachment_id Current attachment ID.\n\t * @param string              $context       Additional context. Can be 'create' when metadata\n\t *                                           was initially created for new attachment.\n\t * @return array<string,mixed> Filtered metadata.\n\t */\n\tpublic function wp_generate_attachment_metadata( array $metadata, int $attachment_id, string $context ): array {\n\t\tif ( 'create' !== $context ) {\n\t\t\treturn $metadata;\n\t\t}\n\t\t$attachment = get_post( $attachment_id );\n\t\t$mime_type  = get_post_mime_type( $attachment );\n\n\t\tif ( self::MIME_TYPE !== $mime_type ) {\n\t\t\treturn $metadata;\n\t\t}\n\t\t$file = get_attached_file( $attachment_id );\n\t\tif ( false === $file ) {\n\t\t\treturn $metadata;\n\t\t}\n\n\t\t$size = $this->get_svg_size( $file );\n\t\t// Check if image size failed to generate and return if so.\n\t\tif ( is_wp_error( $size ) ) {\n\t\t\treturn $metadata;\n\t\t}\n\n\t\treturn [\n\t\t\t'width'    => (int) $size['width'],\n\t\t\t'height'   => (int) $size['height'],\n\t\t\t'file'     => _wp_relative_upload_path( $file ),\n\t\t\t'filesize' => (int) filesize( $file ),\n\t\t\t'sizes'    => [],\n\t\t];\n\t}\n\n\t/**\n\t * Hook into upload and error if size could not be generated.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param array $upload {\n\t *      Array of upload data.\n\t *\n\t *      @type string $file     Filename of the newly-uploaded file.\n\t *      @type string $url      URL of the newly-uploaded file.\n\t *      @type string $type     Mime type of the newly-uploaded file.\n\t *      @type string $tmp_name Temporary file name.\n\t * }\n\t * @return string[]\n\t *\n\t * @phpstan-param array{file: string, url: string, type: string, tmp_name: string} $upload\n\t */\n\tpublic function wp_handle_upload( array $upload ): array {\n\t\tif ( self::MIME_TYPE !== $upload['type'] ) {\n\t\t\treturn $upload;\n\t\t}\n\n\t\t$sanitized = $this->sanitize( $upload['tmp_name'] );\n\t\tif ( is_wp_error( $sanitized ) ) {\n\t\t\treturn [ 'error' => $sanitized->get_error_message() ];\n\t\t}\n\n\t\t$size = $this->get_svg_size( $upload['tmp_name'] );\n\t\tif ( is_wp_error( $size ) ) {\n\t\t\treturn [ 'error' => $size->get_error_message() ];\n\t\t}\n\n\t\treturn $upload;\n\t}\n\n\t/**\n\t * Work around for incorrect mime type.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param array               $wp_check_filetype_and_ext {\n\t *                                                       Values for the extension, mime type, and corrected filename.\n\t *\n\t * @type string|false         $ext                       File extension, or false if the file doesn't match a mime type.\n\t * @type string|false         $type                      File mime type, or false if the file doesn't match a mime type.\n\t * @type string|false         $proper_filename           File name with its correct extension, or false if it cannot be\n\t *       determined.\n\t * }\n\t * @param string              $file                      Full path to the file.\n\t * @param string              $filename                  The name of the file (may differ from $file due to\n\t *                                                       $file being in a tmp directory).\n\t * @param string[]|null|false $mimes                     Array of mime types keyed by their file extension regex.\n\t * @param string|bool         $real_mime                 The actual mime type or false if the type cannot be determined.\n\t * @return array{ext?: string, type?: string, proper_filename?: bool}\n\t *\n\t * @phpstan-param array{ext?: string, type?: string, proper_filename?: bool} $wp_check_filetype_and_ext\n\t */\n\tpublic function wp_check_filetype_and_ext( array $wp_check_filetype_and_ext, string $file, string $filename, $mimes, $real_mime ): array {\n\t\tif ( 'image/svg' === $real_mime ) {\n\t\t\t$wp_check_filetype_and_ext = [\n\t\t\t\t'ext'             => self::EXT,\n\t\t\t\t'type'            => self::MIME_TYPE,\n\t\t\t\t'proper_filename' => false,\n\t\t\t];\n\t\t}\n\n\t\treturn $wp_check_filetype_and_ext;\n\t}\n\n\t/**\n\t * Helper function to check if svg uploads are already enabled.\n\t *\n\t * @since 1.3.0\n\t */\n\tprivate function svg_already_enabled(): bool {\n\t\t$allowed_mime_types = get_allowed_mime_types();\n\t\t$mime_types         = array_values( $allowed_mime_types );\n\n\t\treturn \\in_array( self::MIME_TYPE, $mime_types, true );\n\t}\n\n\n\t/**\n\t * Get SVG image size.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $file Path to SVG file.\n\t * @return array|WP_Error\n\t *\n\t * @phpstan-return array{width: int, height: int}|WP_Error\n\t */\n\tprotected function get_svg_size( string $file ) {\n\t\t$svg = $this->get_svg_data( $file );\n\t\t$xml = $this->get_xml( $svg );\n\n\t\tif ( false === $xml ) {\n\t\t\treturn new \\WP_Error( 'invalid_xml_svg', __( 'Invalid XML in SVG.', 'web-stories' ) );\n\t\t}\n\n\t\t$width  = (int) $xml->getAttribute( 'width' );\n\t\t$height = (int) $xml->getAttribute( 'height' );\n\n\t\t// If height and width are not set, try the viewport attribute.\n\t\tif ( ! $width || ! $height ) {\n\t\t\t$view_box = $xml->getAttribute( 'viewBox' );\n\t\t\tif ( empty( $view_box ) ) {\n\t\t\t\t$view_box = $xml->getAttribute( 'viewbox' );\n\t\t\t}\n\t\t\t$pieces = explode( ' ', $view_box );\n\t\t\tif ( 4 === \\count( $pieces ) ) {\n\t\t\t\t[, , $width, $height] = $pieces;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $width || ! $height ) {\n\t\t\treturn new \\WP_Error( 'invalid_svg_size', __( 'Unable to generate SVG image size.', 'web-stories' ) );\n\t\t}\n\n\t\treturn array_map( 'absint', compact( 'width', 'height' ) );\n\t}\n\n\t/**\n\t * Sanitize the SVG\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $file File path.\n\t * @return true|WP_Error\n\t */\n\tprotected function sanitize( string $file ) {\n\t\t$dirty     = $this->get_svg_data( $file );\n\t\t$sanitizer = new Sanitizer();\n\t\t$clean     = $sanitizer->sanitize( $dirty );\n\n\t\tif ( empty( $clean ) ) {\n\t\t\treturn new \\WP_Error( 'invalid_xml_svg', __( 'Invalid XML in SVG.', 'web-stories' ) );\n\t\t}\n\n\t\t$errors = $sanitizer->getXmlIssues();\n\t\tif ( \\count( $errors ) > 1 ) {\n\t\t\treturn new \\WP_Error( 'insecure_svg_file', __( \"Sorry, this file couldn't be sanitized so for security reasons wasn't uploaded.\", 'web-stories' ) );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get xml document.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $svg String of xml.\n\t * @return DOMElement|false\n\t */\n\tprotected function get_xml( string $svg ) {\n\t\t$dom                      = new DOMDocument();\n\t\t$dom->preserveWhiteSpace  = false;\n\t\t$dom->strictErrorChecking = false;\n\n\t\t$errors = libxml_use_internal_errors( true );\n\t\t$loaded = $dom->loadXML( $svg );\n\t\tif ( ! $loaded ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$node = $dom->getElementsByTagName( 'svg' )->item( 0 );\n\n\t\tlibxml_clear_errors();\n\t\tlibxml_use_internal_errors( $errors );\n\n\t\tif ( ! $node ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $node;\n\t}\n\n\t/**\n\t * Get SVG data.\n\t *\n\t * @since 1.3.0\n\t *\n\t * @param string $file File path.\n\t * @return string File contents.\n\t */\n\tprotected function get_svg_data( string $file ): string {\n\t\t$key = md5( $file );\n\t\tif ( ! isset( $this->svgs[ $key ] ) ) {\n\t\t\tif ( is_readable( $file ) ) {\n\t\t\t\t$this->svgs[ $key ] = (string) file_get_contents( $file ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown\n\t\t\t} else {\n\t\t\t\t$this->svgs[ $key ] = '';\n\t\t\t}\n\t\t}\n\n\t\treturn $this->svgs[ $key ];\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Types.php",
    "content": "<?php\n/**\n * Class Types\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media;\n\n/**\n * Class Types\n */\nclass Types {\n\t/**\n\t * Returns a list of allowed file types.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string[] $mime_types Array of mime types.\n\t * @return string[]\n\t */\n\tpublic function get_file_type_exts( array $mime_types = [] ): array {\n\t\t$allowed_file_types = [];\n\t\t$all_mime_types     = get_allowed_mime_types();\n\n\t\tforeach ( $all_mime_types as $ext => $mime ) {\n\t\t\tif ( \\in_array( $mime, $mime_types, true ) ) {\n\t\t\t\tarray_push( $allowed_file_types, ...explode( '|', $ext ) );\n\t\t\t}\n\t\t}\n\t\tsort( $allowed_file_types );\n\n\t\treturn $allowed_file_types;\n\t}\n\n\t/**\n\t * Returns a list of allowed mime types per media type (image, audio, video).\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string, string[]> List of allowed mime types.\n\t */\n\tpublic function get_allowed_mime_types(): array {\n\t\t$default_allowed_mime_types = [\n\t\t\t'image'   => [\n\t\t\t\t'image/webp',\n\t\t\t\t'image/png',\n\t\t\t\t'image/jpeg',\n\t\t\t\t'image/jpg',\n\t\t\t\t'image/gif',\n\t\t\t\t'image/avif',\n\t\t\t],\n\t\t\t'audio'   => [\n\t\t\t\t'audio/mpeg',\n\t\t\t\t'audio/aac',\n\t\t\t\t'audio/wav',\n\t\t\t\t'audio/ogg',\n\t\t\t],\n\t\t\t'caption' => [ 'text/vtt' ],\n\t\t\t'vector'  => [],\n\t\t\t'video'   => [\n\t\t\t\t'video/mp4',\n\t\t\t\t'video/webm',\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filter list of allowed mime types.\n\t\t *\n\t\t * This can be used to add additionally supported formats, for example by plugins\n\t\t * that do video transcoding.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array<string, string[]> $default_allowed_mime_types Associative array of allowed mime types per media type (image, audio, video).\n\t\t */\n\t\t$allowed_mime_types = apply_filters( 'web_stories_allowed_mime_types', $default_allowed_mime_types );\n\n\t\t/**\n\t\t * Media type.\n\t\t *\n\t\t * @var string $media_type\n\t\t */\n\t\tforeach ( array_keys( $default_allowed_mime_types ) as $media_type ) {\n\t\t\tif ( ! isset( $allowed_mime_types[ $media_type ] ) || empty( $allowed_mime_types[ $media_type ] ) ) {\n\t\t\t\t$allowed_mime_types[ $media_type ] = $default_allowed_mime_types[ $media_type ];\n\t\t\t}\n\n\t\t\t// Only add currently supported mime types.\n\t\t\t$allowed_mime_types[ $media_type ] = array_values( array_intersect( $allowed_mime_types[ $media_type ], get_allowed_mime_types() ) );\n\t\t}\n\n\t\treturn $allowed_mime_types;\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Captions.php",
    "content": "<?php\n/**\n * Class Captions\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Captions\n */\nclass Captions extends Service_Base {\n\t/**\n\t * Initializes the File_Type logic.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'site_option_upload_filetypes', [ $this, 'filter_list_of_allowed_filetypes' ] );\n\t}\n\n\t/**\n\t * Add VTT file type to allow file in multisite.\n\t *\n\t * @param string|mixed $value List of allowed file types.\n\t * @return string|mixed List of allowed file types.\n\t */\n\tpublic function filter_list_of_allowed_filetypes( $value ) {\n\t\tif ( ! \\is_string( $value ) ) {\n\t\t\treturn $value;\n\t\t}\n\n\t\t$filetypes = explode( ' ', $value );\n\t\tif ( ! \\in_array( 'vtt', $filetypes, true ) ) {\n\t\t\t$filetypes[] = 'vtt';\n\t\t\t$value       = implode( ' ', $filetypes );\n\t\t}\n\n\t\treturn $value;\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Is_Gif.php",
    "content": "<?php\n/**\n * Class Is_Gif\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Is_Gif\n */\nclass Is_Gif extends Service_Base implements HasMeta, PluginUninstallAware {\n\t/**\n\t * The post meta key.\n\t */\n\tpublic const IS_GIF_POST_META_KEY = 'web_stories_is_gif';\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.23.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t}\n\n\t/**\n\t * Register post meta\n\t *\n\t * @since 1.23.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_post_meta(\n\t\t\t'attachment',\n\t\t\tself::IS_GIF_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'rest_sanitize_boolean',\n\t\t\t\t'type'              => 'boolean',\n\t\t\t\t'description'       => __( 'Whether the video is to be considered a GIF', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => false,\n\t\t\t\t'single'            => true,\n\t\t\t\t'object_subtype'    => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.23.0\n\t *\n\t * @param array|mixed $response Array of prepared attachment data.\n\t * @return array|mixed Response data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $response['id'];\n\n\t\t$response[ self::IS_GIF_POST_META_KEY ] = get_post_meta( $post_id, self::IS_GIF_POST_META_KEY, true );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::IS_GIF_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Muting.php",
    "content": "<?php\n/**\n * Class Muting\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\nuse WP_Error;\nuse WP_Post;\n\n/**\n * Class Muting\n */\nclass Muting extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * Is muted.\n\t */\n\tpublic const IS_MUTED_POST_META_KEY = 'web_stories_is_muted';\n\n\t/**\n\t * The muted video id post meta key.\n\t */\n\tpublic const MUTED_ID_POST_META_KEY = 'web_stories_muted_id';\n\n\t/**\n\t * Is muted.\n\t */\n\tpublic const IS_MUTED_REST_API_KEY = 'web_stories_is_muted';\n\n\t/**\n\t * Register.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\n\t\tadd_action( 'delete_attachment', [ $this, 'delete_video' ] );\n\t\tadd_action( 'rest_api_init', [ $this, 'rest_api_init' ] );\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ] );\n\t}\n\n\t/**\n\t * Register meta for attachment post type.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::IS_MUTED_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'type'           => 'boolean',\n\t\t\t\t'description'    => __( 'Whether the video is muted', 'web-stories' ),\n\t\t\t\t'default'        => false,\n\t\t\t\t'single'         => true,\n\t\t\t\t'object_subtype' => 'attachment',\n\t\t\t]\n\t\t);\n\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::MUTED_ID_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'absint',\n\t\t\t\t'type'              => 'integer',\n\t\t\t\t'description'       => __( 'ID of muted video.', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => 0,\n\t\t\t\t'single'            => true,\n\t\t\t\t'object_subtype'    => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Registers additional REST API fields upon API initialization.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function rest_api_init(): void {\n\t\tregister_rest_field(\n\t\t\t'attachment',\n\t\t\tself::IS_MUTED_REST_API_KEY,\n\t\t\t[\n\t\t\t\t'get_callback'    => [ $this, 'get_callback_is_muted' ],\n\t\t\t\t'schema'          => [\n\t\t\t\t\t'type'        => [ 'boolean', 'null' ],\n\t\t\t\t\t'description' => __( 'Whether the video is muted', 'web-stories' ),\n\t\t\t\t\t'default'     => null,\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'arg_options' => [\n\t\t\t\t\t\t'sanitize_callback' => 'rest_sanitize_boolean',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'update_callback' => [ $this, 'update_callback_is_muted' ],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array|mixed $response Array of prepared attachment data.\n\t * @return array|mixed Response data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\t\tif ( 'video' === $response['type'] ) {\n\t\t\t// @phpstan-ignore argument.type\n\t\t\t$response[ self::IS_MUTED_REST_API_KEY ] = $this->get_callback_is_muted( $response );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Get the attachment's post meta.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array<string, mixed> $prepared Array of data to add to.\n\t */\n\tpublic function get_callback_is_muted( array $prepared ): ?bool {\n\t\t/**\n\t\t * Attachment ID.\n\t\t *\n\t\t * @var int $id\n\t\t */\n\t\t$id = $prepared['id'];\n\n\t\t/**\n\t\t * Muted value.\n\t\t *\n\t\t * @var bool|null $value\n\t\t */\n\t\t$value = get_metadata_raw( 'post', $id, self::IS_MUTED_POST_META_KEY, true );\n\n\t\tif ( null === $value ) {\n\t\t\treturn $value;\n\t\t}\n\n\t\treturn rest_sanitize_boolean( $value );\n\t}\n\n\t/**\n\t * Update the attachment's post meta.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param mixed   $value  Value to updated.\n\t * @param WP_Post $post   Post object to be updated.\n\t * @return true|WP_Error\n\t */\n\tpublic function update_callback_is_muted( $value, WP_Post $post ) {\n\t\t$object_id = $post->ID;\n\t\t$name      = self::IS_MUTED_REST_API_KEY;\n\t\t$meta_key  = self::IS_MUTED_POST_META_KEY;\n\n\t\tif ( ! current_user_can( 'edit_post_meta', $object_id, $meta_key ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_cannot_update',\n\t\t\t\t/* translators: %s: Custom field key.**/\n\t\t\t\t\\sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.', 'web-stories' ), $name ),\n\t\t\t\t[\n\t\t\t\t\t'key'    => $name,\n\t\t\t\t\t'status' => rest_authorization_required_code(),\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\tupdate_post_meta( $object_id, $meta_key, $value );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Deletes associated meta data when a video is deleted.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param int $attachment_id ID of the attachment to be deleted.\n\t */\n\tpublic function delete_video( int $attachment_id ): void {\n\t\tdelete_metadata( 'post', 0, self::MUTED_ID_POST_META_KEY, $attachment_id, true );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::MUTED_ID_POST_META_KEY );\n\t\tdelete_post_meta_by_key( self::IS_MUTED_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Optimization.php",
    "content": "<?php\n/**\n * Class Optimization\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Optimization\n */\nclass Optimization extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * The optimized video id post meta key.\n\t */\n\tpublic const OPTIMIZED_ID_POST_META_KEY = 'web_stories_optimized_id';\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t\tadd_action( 'delete_attachment', [ $this, 'delete_video' ] );\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::OPTIMIZED_ID_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'absint',\n\t\t\t\t'type'              => 'integer',\n\t\t\t\t'description'       => __( 'ID of optimized video.', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => 0,\n\t\t\t\t'single'            => true,\n\t\t\t\t'object_subtype'    => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Deletes associated meta data when a video is deleted.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param int $attachment_id ID of the attachment to be deleted.\n\t */\n\tpublic function delete_video( int $attachment_id ): void {\n\t\tdelete_metadata( 'post', 0, self::OPTIMIZED_ID_POST_META_KEY, $attachment_id, true );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::OPTIMIZED_ID_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Poster.php",
    "content": "<?php\n/**\n * Class Poster\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Media\\Media_Source_Taxonomy;\nuse Google\\Web_Stories\\Service_Base;\nuse WP_Post;\n\n/**\n * Class Poster\n */\nclass Poster extends Service_Base implements HasMeta, PluginUninstallAware {\n\t/**\n\t * The poster post meta key.\n\t */\n\tpublic const POSTER_POST_META_KEY = 'web_stories_is_poster';\n\n\t/**\n\t * The poster id post meta key.\n\t */\n\tpublic const POSTER_ID_POST_META_KEY = 'web_stories_poster_id';\n\n\t/**\n\t * Media_Source_Taxonomy instance.\n\t *\n\t * @var Media_Source_Taxonomy Experiments instance.\n\t */\n\tprotected Media_Source_Taxonomy $media_source_taxonomy;\n\n\t/**\n\t * Poster constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Media_Source_Taxonomy $media_source_taxonomy Media_Source_Taxonomy instance.\n\t */\n\tpublic function __construct( Media_Source_Taxonomy $media_source_taxonomy ) {\n\t\t$this->media_source_taxonomy = $media_source_taxonomy;\n\t}\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t\tadd_action( 'rest_api_init', [ $this, 'rest_api_init' ] );\n\t\tadd_action( 'delete_attachment', [ $this, 'delete_video_poster' ] );\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ], 10, 2 );\n\t}\n\n\t/**\n\t * Register meta for attachment post type.\n\t *\n\t * @since 1.10.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::POSTER_ID_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'absint',\n\t\t\t\t'type'              => 'integer',\n\t\t\t\t'description'       => __( 'Attachment id of generated poster image.', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => 0,\n\t\t\t\t'single'            => true,\n\t\t\t\t'object_subtype'    => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Registers additional REST API fields upon API initialization.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function rest_api_init(): void {\n\t\tregister_rest_field(\n\t\t\t'attachment',\n\t\t\t'featured_media',\n\t\t\t[\n\t\t\t\t'schema' => [\n\t\t\t\t\t'description' => __( 'The ID of the featured media for the object.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tregister_rest_field(\n\t\t\t'attachment',\n\t\t\t'featured_media_src',\n\t\t\t[\n\t\t\t\t'get_callback' => [ $this, 'get_callback_featured_media_src' ],\n\t\t\t\t'schema'       => [\n\t\t\t\t\t'description' => __( 'URL, width and height.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'object',\n\t\t\t\t\t'properties'  => [\n\t\t\t\t\t\t'src'       => [\n\t\t\t\t\t\t\t'type'   => 'string',\n\t\t\t\t\t\t\t'format' => 'uri',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'width'     => [\n\t\t\t\t\t\t\t'type' => 'integer',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'height'    => [\n\t\t\t\t\t\t\t'type' => 'integer',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'generated' => [\n\t\t\t\t\t\t\t'type' => 'boolean',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Get attachment source for featured media.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string, mixed> $prepared Prepared data before response.\n\t * @return array<string, mixed>\n\t */\n\tpublic function get_callback_featured_media_src( array $prepared ): array {\n\t\t/**\n\t\t * Featured media ID.\n\t\t *\n\t\t * @var int|null $id\n\t\t */\n\t\t$id    = $prepared['featured_media'] ?? null;\n\t\t$image = [];\n\t\tif ( $id ) {\n\t\t\t$image = $this->get_thumbnail_data( $id );\n\t\t}\n\n\t\treturn $image;\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string, mixed>|mixed $response   Array of prepared attachment data.\n\t * @param WP_Post                    $attachment Attachment object.\n\t * @return array<string, mixed>|mixed $response\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response, WP_Post $attachment ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\t\tif ( 'video' === $response['type'] ) {\n\t\t\t$thumbnail_id = (int) get_post_thumbnail_id( $attachment );\n\t\t\t$image        = '';\n\t\t\tif ( 0 !== $thumbnail_id ) {\n\t\t\t\t$image = $this->get_thumbnail_data( $thumbnail_id );\n\t\t\t}\n\n\t\t\t$response['featured_media']     = $thumbnail_id;\n\t\t\t$response['featured_media_src'] = $image;\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Get poster image data.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param int $thumbnail_id Attachment ID.\n\t * @return array{src?: string, width?: int, height?: int, generated?: bool}\n\t */\n\tpublic function get_thumbnail_data( int $thumbnail_id ): array {\n\t\t$img_src = wp_get_attachment_image_src( $thumbnail_id, 'full' );\n\n\t\tif ( ! $img_src ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t[ $src, $width, $height ] = $img_src;\n\t\t$generated                = $this->is_poster( $thumbnail_id );\n\t\treturn compact( 'src', 'width', 'height', 'generated' );\n\t}\n\n\t/**\n\t * Deletes associated poster image when a video is deleted.\n\t *\n\t * This prevents the poster image from becoming an orphan because it is not\n\t * displayed anywhere in WordPress or the story editor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param int $attachment_id ID of the attachment to be deleted.\n\t */\n\tpublic function delete_video_poster( int $attachment_id ): void {\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int|string $post_id\n\t\t */\n\t\t$post_id = get_post_meta( $attachment_id, self::POSTER_ID_POST_META_KEY, true );\n\n\t\tif ( empty( $post_id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Used in favor of slow meta queries.\n\t\t$is_poster = $this->is_poster( (int) $post_id );\n\t\tif ( $is_poster ) {\n\t\t\twp_delete_attachment( (int) $post_id, true );\n\t\t}\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::POSTER_ID_POST_META_KEY );\n\t\tdelete_post_meta_by_key( self::POSTER_POST_META_KEY );\n\t}\n\n\t/**\n\t * Helper util to check if attachment is a poster.\n\t *\n\t * @since 1.2.1\n\t *\n\t * @param int $post_id Attachment ID.\n\t */\n\tprotected function is_poster( int $post_id ): bool {\n\t\t$terms = get_the_terms( $post_id, $this->media_source_taxonomy->get_taxonomy_slug() );\n\t\tif ( \\is_array( $terms ) && ! empty( $terms ) ) {\n\t\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\n\t\t\treturn \\in_array( $this->media_source_taxonomy::TERM_POSTER_GENERATION, $slugs, true );\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "includes/Media/Video/Trimming.php",
    "content": "<?php\n/**\n * Class Trimming\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Media\\Video;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Trimming\n */\nclass Trimming extends Service_Base implements HasMeta, PluginUninstallAware {\n\n\t/**\n\t * The trim video post meta key.\n\t */\n\tpublic const TRIM_POST_META_KEY = 'web_stories_trim_data';\n\n\t/**\n\t * Is trim.\n\t */\n\tpublic const TRIM_DATA_KEY = 'trim_data';\n\n\t/**\n\t * Register.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\n\t\tadd_filter( 'wp_prepare_attachment_for_js', [ $this, 'wp_prepare_attachment_for_js' ] );\n\t}\n\n\t/**\n\t * Register meta for attachment post type.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'post',\n\t\t\tself::TRIM_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'type'           => 'object',\n\t\t\t\t'description'    => __( 'Video trim data.', 'web-stories' ),\n\t\t\t\t'show_in_rest'   => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'properties' => [\n\t\t\t\t\t\t\t'original' => [\n\t\t\t\t\t\t\t\t'description' => __( 'Original attachment id', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'start'    => [\n\t\t\t\t\t\t\t\t'description' => __( 'Start time.', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'end'      => [\n\t\t\t\t\t\t\t\t'description' => __( 'End time.', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'default'        => [\n\t\t\t\t\t'original' => 0,\n\t\t\t\t],\n\t\t\t\t'single'         => true,\n\t\t\t\t'object_subtype' => 'attachment',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the attachment data prepared for JavaScript.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param array|mixed $response Array of prepared attachment data.\n\t * @return array|mixed Response data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($response is array<T> ? array<T> : mixed)\n\t */\n\tpublic function wp_prepare_attachment_for_js( $response ) {\n\t\tif ( ! \\is_array( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\t\tif ( 'video' === $response['type'] ) {\n\t\t\t/**\n\t\t\t * Post ID.\n\t\t\t *\n\t\t\t * @var int $post_id\n\t\t\t */\n\t\t\t$post_id = $response['id'];\n\n\t\t\t$response[ self::TRIM_DATA_KEY ] = get_post_meta( $post_id, self::TRIM_POST_META_KEY, true );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::TRIM_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Mgid.php",
    "content": "<?php\n/**\n * Class Mgid\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2023 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\n\n/**\n * Class MGID\n */\nclass Mgid extends Service_Base implements HasRequirements {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Initializes all hooks.\n\t *\n\t * @since 1.33.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'web_stories_print_analytics', [ $this, 'print_mgid_tag' ] );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Prints the <amp-story-auto-ads> tag for single stories.\n\t *\n\t * @since 1.33.0\n\t */\n\tpublic function print_mgid_tag(): void {\n\t\t$widget  = $this->get_widget_id();\n\t\t$enabled = $this->is_enabled();\n\n\t\tif ( ! $enabled || ! $widget ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$configuration = [\n\t\t\t'ad-attributes' => [\n\t\t\t\t'type'        => 'mgid',\n\t\t\t\t'data-widget' => $widget,\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filters MGID configuration passed to `<amp-story-auto-ads>`.\n\t\t *\n\t\t * @since 1.33.0\n\t\t *\n\t\t * @param array $settings MGID configuration.\n\t\t * @param string $widget MGID Widget ID.\n\t\t */\n\t\t$configuration = apply_filters( 'web_stories_mgid_configuration', $configuration, $widget );\n\n\t\t?>\n\t\t<amp-story-auto-ads>\n\t\t\t<script type=\"application/json\">\n\t\t\t\t<?php echo wp_json_encode( $configuration, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); ?>\n\t\t\t</script>\n\t\t</amp-story-auto-ads>\n\t\t<?php\n\t}\n\n\t/**\n\t * Returns the MGID Widget ID.\n\t *\n\t * @since 1.33.0\n\t *\n\t * @return string Widget ID.\n\t */\n\tprivate function get_widget_id(): string {\n\t\t/**\n\t\t * Widget ID.\n\t\t *\n\t\t * @var string\n\t\t */\n\t\treturn $this->settings->get_setting( $this->settings::SETTING_NAME_MGID_WIDGET_ID );\n\t}\n\n\t/**\n\t * Returns if MGID is enabled.\n\t *\n\t * @since 1.33.0\n\t */\n\tprivate function is_enabled(): bool {\n\t\treturn ( 'mgid' === $this->settings->get_setting( $this->settings::SETTING_NAME_AD_NETWORK, 'none' ) );\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Editor\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Media_Source_Taxonomy;\n\n/**\n * Class Add_Media_Source\n */\nabstract class Add_Media_Source extends Migrate_Base {\n\t/**\n\t * Media_Source_Taxonomy instance.\n\t *\n\t * @var Media_Source_Taxonomy Experiments instance.\n\t */\n\tprotected Media_Source_Taxonomy $media_source_taxonomy;\n\n\t/**\n\t * Add_Media_Source constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Media_Source_Taxonomy $media_source_taxonomy Media_Source_Taxonomy instance.\n\t */\n\tpublic function __construct( Media_Source_Taxonomy $media_source_taxonomy ) {\n\t\t$this->media_source_taxonomy = $media_source_taxonomy;\n\t}\n\n\t/**\n\t * Add the editor term, to make sure it exists.\n\t *\n\t * @since 1.9.0\n\t */\n\tpublic function migrate(): void {\n\t\twp_insert_term( $this->get_term(), $this->media_source_taxonomy->get_taxonomy_slug() );\n\t}\n\n\t/**\n\t * Override this method.\n\t *\n\t * @since 1.9.0\n\t */\n\tabstract protected function get_term(): string;\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Editor.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Editor\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Editor\n */\nclass Add_Media_Source_Editor extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_EDITOR;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Gif_Conversion.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Gif_Conversion\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Gif_Conversion\n */\nclass Add_Media_Source_Gif_Conversion extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_GIF_CONVERSION;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Page_Template.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Page_Template\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Page_Template\n */\nclass Add_Media_Source_Page_Template extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.14.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_PAGE_TEMPLATE;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Recording.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Recording\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Recording\n */\nclass Add_Media_Source_Recording extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.23.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_RECORDING;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Source_Image.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Source_Video\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Source_Video\n */\nclass Add_Media_Source_Source_Image extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_SOURCE_IMAGE;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Source_Video.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Source_Video\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Source_Video\n */\nclass Add_Media_Source_Source_Video extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_SOURCE_VIDEO;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Media_Source_Video_Optimization.php",
    "content": "<?php\n/**\n * Class Add_Media_Source_Video_Optimization\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Add_Media_Source_Video_Optimization\n */\nclass Add_Media_Source_Video_Optimization extends Add_Media_Source {\n\t/**\n\t * Term name.\n\t *\n\t * @since 1.9.0\n\t */\n\tprotected function get_term(): string {\n\t\treturn $this->media_source_taxonomy::TERM_VIDEO_OPTIMIZATION;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Poster_Generation_Media_Source.php",
    "content": "<?php\n/**\n * Class Add_Poster_Generation_Media_Source\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Video\\Poster;\n\n/**\n * Class Add_Poster_Generation_Media_Source\n */\nclass Add_Poster_Generation_Media_Source extends Migration_Meta_To_Term {\n\n\t/**\n\t * Migration media post meta to taxonomy term.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\twp_insert_term( $this->get_term_name(), $this->media_source_taxonomy->get_taxonomy_slug() );\n\t\tparent::migrate();\n\t}\n\n\t/**\n\t * Get name of meta key to be used in migration.\n\t *\n\t * @since 1.7.2\n\t */\n\tprotected function get_post_meta_key(): string {\n\t\treturn Poster::POSTER_POST_META_KEY;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_Stories_Caps.php",
    "content": "<?php\n/**\n * Class Add_Stories_Caps\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\User\\Capabilities;\n\n/**\n * Class Add_Stories_Caps\n */\nclass Add_Stories_Caps extends Migrate_Base {\n\t/**\n\t * Capabilities instance.\n\t *\n\t * @var Capabilities Experiments instance.\n\t */\n\tprivate Capabilities $capabilities;\n\n\t/**\n\t * Add_Stories_Caps constructor.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param Capabilities $capabilities Capabilities instance.\n\t */\n\tpublic function __construct( Capabilities $capabilities ) {\n\t\t$this->capabilities = $capabilities;\n\t}\n\n\t/**\n\t * Adds story capabilities to default user roles.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t$this->capabilities->add_caps_to_roles();\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Add_VideoPress_Poster_Generation_Media_Source.php",
    "content": "<?php\n/**\n * Class Add_VideoPress_Poster_Generation_Media_Source\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Integrations\\Jetpack;\n\n/**\n * Class Add_VideoPress_Poster_Generation_Media_Source\n */\nclass Add_VideoPress_Poster_Generation_Media_Source extends Migration_Meta_To_Term {\n\t/**\n\t * Get name of meta key to be used in migration.\n\t *\n\t * @since 1.7.2\n\t */\n\tprotected function get_post_meta_key(): string {\n\t\treturn Jetpack::VIDEOPRESS_POSTER_META_KEY;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Migrate_Base.php",
    "content": "<?php\n/**\n * Class Migrate_Base\n *\n * Base class for other classes to extend.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Interfaces\\Migration;\n\n/**\n * Class Migrate_Base\n */\nabstract class Migrate_Base implements Migration {\n\n}\n"
  },
  {
    "path": "includes/Migrations/Migration_Meta_To_Term.php",
    "content": "<?php\n/**\n * Class Migration_Meta_To_Term\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Media_Source_Taxonomy;\n\n/**\n * Class Migration_Meta_To_Term\n */\nabstract class Migration_Meta_To_Term extends Migrate_Base {\n\n\t/**\n\t * Media_Source_Taxonomy instance.\n\t *\n\t * @var Media_Source_Taxonomy Experiments instance.\n\t */\n\tprotected Media_Source_Taxonomy $media_source_taxonomy;\n\n\t/**\n\t * Migration_Meta_To_Term constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Media_Source_Taxonomy $media_source_taxonomy Media_Source_Taxonomy instance.\n\t */\n\tpublic function __construct( Media_Source_Taxonomy $media_source_taxonomy ) {\n\t\t$this->media_source_taxonomy = $media_source_taxonomy;\n\t}\n\n\t/**\n\t * Migration media post meta to taxonomy term.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @global \\wpdb $wpdb WordPress database abstraction object.\n\t */\n\tpublic function migrate(): void {\n\t\tglobal $wpdb;\n\n\t\t$post_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery\n\t\t\t$wpdb->prepare(\n\t\t\t\t\"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s\",\n\t\t\t\t$this->get_post_meta_key()\n\t\t\t)\n\t\t);\n\n\t\tif ( \\is_array( $post_ids ) && ! empty( $post_ids ) ) {\n\t\t\t/**\n\t\t\t * Post ID.\n\t\t\t *\n\t\t\t * @var int|string $post_id\n\t\t\t */\n\t\t\tforeach ( $post_ids as $post_id ) {\n\t\t\t\twp_set_object_terms( (int) $post_id, $this->get_term_name(), $this->media_source_taxonomy->get_taxonomy_slug() );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get name of meta key to be used in migration.\n\t * This method is designed for overridden.\n\t *\n\t * @since 1.7.2\n\t */\n\tabstract protected function get_post_meta_key(): string;\n\n\t/**\n\t * Get name of term to be used in migration.\n\t * This method is designed for overridden.\n\t *\n\t * @since 1.7.2\n\t */\n\tprotected function get_term_name(): string {\n\t\treturn $this->media_source_taxonomy::TERM_POSTER_GENERATION;\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Remove_Broken_Text_Styles.php",
    "content": "<?php\n/**\n * Class Remove_Broken_Text_Styles\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Remove_Broken_Text_Styles\n *\n * @phpstan-type Color array{\n *   type?: string,\n *   r?: int,\n *   g?: int,\n *   b?: int\n * }\n * @phpstan-type StylePresets array{\n *   fillColors: Color[],\n *   textStyles: array<int, array{\n *     backgroundColor?: Color,\n *     color?: Color\n *   }>,\n *   textColors: mixed,\n * }\n */\nclass Remove_Broken_Text_Styles extends Migrate_Base {\n\t/**\n\t * Removes broken text styles (with color.r|g|b structure).\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t/**\n\t\t * List of style presets.\n\t\t *\n\t\t * @phpstan-var StylePresets|false\n\t\t */\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION, false );\n\n\t\t// Nothing to do if style presets don't exist.\n\t\tif ( ! \\is_array( $style_presets ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$text_styles = [];\n\t\tif ( ! empty( $style_presets['textStyles'] ) ) {\n\t\t\tforeach ( $style_presets['textStyles'] as $preset ) {\n\t\t\t\tif ( isset( $preset['color']['r'] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$text_styles[] = $preset;\n\t\t\t}\n\t\t}\n\n\t\t$updated_style_presets = [\n\t\t\t'fillColors' => $style_presets['fillColors'],\n\t\t\t'textColors' => $style_presets['textColors'],\n\t\t\t'textStyles' => $text_styles,\n\t\t];\n\t\tupdate_option( Story_Post_Type::STYLE_PRESETS_OPTION, $updated_style_presets );\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Remove_Incorrect_Tracking_Id.php",
    "content": "<?php\n/**\n * Class Remove_Incorrect_Tracking_Id\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2023 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tracking;\n\n/**\n * Class Remove_Incorrect_Tracking_Id\n */\nclass Remove_Incorrect_Tracking_Id extends Migrate_Base {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @since 1.30.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Remove incorrect tracking ID.\n\t *\n\t * @since 1.30.0\n\t */\n\tpublic function migrate(): void {\n\t\t$tracking_id = $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_ID );\n\n\t\tif ( Tracking::TRACKING_ID === $tracking_id ) {\n\t\t\t$this->settings->update_setting(\n\t\t\t\t$this->settings::SETTING_NAME_TRACKING_ID,\n\t\t\t\t''\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Remove_Unneeded_Attachment_Meta.php",
    "content": "<?php\n/**\n * Class Remove_Unneeded_Attachment_Meta\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Video\\Poster;\n\n/**\n * Class Remove_Unneeded_Attachment_Meta\n */\nclass Remove_Unneeded_Attachment_Meta extends Migrate_Base {\n\t/**\n\t * Delete old attachment post meta.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @global \\wpdb $wpdb WordPress database abstraction object.\n\t */\n\tpublic function migrate(): void {\n\t\tdelete_post_meta_by_key( Poster::POSTER_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Replace_Conic_Style_Presets.php",
    "content": "<?php\n/**\n * Class Replace_Conic_Style_Presets\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Replace_Conic_Style_Presets\n *\n * @phpstan-type Color array{\n *   type?: string\n * }\n * @phpstan-type StylePresets array{\n *   fillColors: Color[],\n *   textStyles: array<int, array{\n *     backgroundColor?: Color\n *   }>,\n *   textColors: mixed,\n * }\n */\nclass Replace_Conic_Style_Presets extends Migrate_Base {\n\t/**\n\t * Replaces conic color type with linear.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t/**\n\t\t * List of style presets.\n\t\t *\n\t\t * @var array|null $style_presets\n\t\t * @phpstan-var StylePresets|null $style_presets\n\t\t */\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION, false );\n\n\t\t// Nothing to do if style presets don't exist.\n\t\tif ( ! \\is_array( $style_presets ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$fill_colors = [];\n\t\t$text_styles = [];\n\t\tif ( ! empty( $style_presets['fillColors'] ) ) {\n\t\t\tforeach ( $style_presets['fillColors'] as $color ) {\n\t\t\t\tif ( ! isset( $color['type'] ) || 'conic' !== $color['type'] ) {\n\t\t\t\t\t$text_styles[] = $color;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$updated_preset         = $color;\n\t\t\t\t$updated_preset['type'] = 'linear';\n\t\t\t\t$fill_colors[]          = $updated_preset;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty( $style_presets['textStyles'] ) ) {\n\t\t\tforeach ( $style_presets['textStyles'] as $preset ) {\n\t\t\t\tif ( empty( $preset['backgroundColor'] ) ) {\n\t\t\t\t\t$text_styles[] = $preset;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$bg_color = $preset['backgroundColor'];\n\t\t\t\tif ( 'conic' !== $bg_color['type'] ) {\n\t\t\t\t\t$text_styles[] = $preset;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$updated_preset                            = $preset;\n\t\t\t\t$updated_preset['backgroundColor']['type'] = 'linear';\n\t\t\t\t$text_styles[]                             = $updated_preset;\n\t\t\t}\n\t\t}\n\n\t\t$updated_style_presets = [\n\t\t\t'fillColors' => $fill_colors,\n\t\t\t'textColors' => $style_presets['textColors'],\n\t\t\t'textStyles' => $text_styles,\n\t\t];\n\t\tupdate_option( Story_Post_Type::STYLE_PRESETS_OPTION, $updated_style_presets );\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Rewrite_Flush.php",
    "content": "<?php\n/**\n * Class Rewrite_Flush\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse const WPCOM_IS_VIP_ENV;\n\n/**\n * Class Rewrite_Flush\n */\nclass Rewrite_Flush extends Migrate_Base {\n\n\t/**\n\t * Flush rewrite rules.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\tif ( ! \\defined( '\\WPCOM_IS_VIP_ENV' ) || false === WPCOM_IS_VIP_ENV ) {\n\t\t\tflush_rewrite_rules( false );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Set_Legacy_Analytics_Usage_Flag.php",
    "content": "<?php\n/**\n * Class Set_Legacy_Analytics_Usage_Flag\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * Class Set_Legacy_Analytics_Usage_Flag\n */\nclass Set_Legacy_Analytics_Usage_Flag extends Migrate_Base {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Migration constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Set legacy analytics usage flag.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function migrate(): void {\n\t\t$this->settings->update_setting(\n\t\t\t$this->settings::SETTING_NAME_USING_LEGACY_ANALYTICS,\n\t\t\t! empty( $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_ID ) )\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Unify_Color_Presets.php",
    "content": "<?php\n/**\n * Class Unify_Color_Presets\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Unify_Color_Presets\n */\nclass Unify_Color_Presets extends Migrate_Base {\n\n\t/**\n\t * Migration for version 2.0.3.\n\t *\n\t * Color presets: Removes fillColor and textColor and unifies to one color.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION, false );\n\t\t// Nothing to do if style presets don't exist.\n\t\tif ( ! $style_presets || ! \\is_array( $style_presets ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If either of these is not an array, something is incorrect.\n\t\tif ( ! \\is_array( $style_presets['fillColors'] ) || ! \\is_array( $style_presets['textColors'] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$colors = [ ...$style_presets['fillColors'], ...$style_presets['textColors'] ];\n\n\t\t// Use only one array of colors for now.\n\t\t$updated_style_presets = [\n\t\t\t'colors' => $colors,\n\t\t];\n\t\tupdate_option( Story_Post_Type::STYLE_PRESETS_OPTION, $updated_style_presets );\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Update_1.php",
    "content": "<?php\n/**\n * Class Update_1\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\n/**\n * Class Update_1\n */\nclass Update_1 extends Migrate_Base {\n\t/**\n\t * First database migration.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t// Do nothing.\n\t}\n}\n"
  },
  {
    "path": "includes/Migrations/Update_Publisher_Logos.php",
    "content": "<?php\n/**\n * Class Update_Publisher_Logos\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * Class Update_Publisher_Logos\n */\nclass Update_Publisher_Logos extends Migrate_Base {\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Split publisher logos into two options.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function migrate(): void {\n\t\t$publisher_logo_id       = 0;\n\t\t$publisher_logo_settings = (array) get_option( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, [] );\n\n\t\tif ( ! empty( $publisher_logo_settings['active'] ) ) {\n\t\t\t$publisher_logo_id = $publisher_logo_settings['active'];\n\t\t}\n\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, $publisher_logo_id );\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, array_filter( [ $publisher_logo_id ] ) );\n\t}\n}\n"
  },
  {
    "path": "includes/Model/Story.php",
    "content": "<?php\n/**\n * Class Story\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Model;\n\nuse Google\\Web_Stories\\Media\\Image_Sizes;\nuse Google\\Web_Stories\\Shopping\\Product;\nuse Google\\Web_Stories\\Shopping\\Product_Meta;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Class Story\n *\n * @phpstan-import-type ProductData from \\Google\\Web_Stories\\Shopping\\Product\n */\nclass Story {\n\t/**\n\t * Story ID.\n\t */\n\tprotected int $id = 0;\n\n\t/**\n\t * Title.\n\t */\n\tprotected string $title = '';\n\n\t/**\n\t * Excerpt.\n\t */\n\tprotected string $excerpt = '';\n\n\t/**\n\t * URL.\n\t */\n\tprotected string $url = '';\n\n\t/**\n\t * Markup.\n\t */\n\tprotected string $markup = '';\n\n\t/**\n\t * Publisher name.\n\t */\n\tprotected string $publisher_name = '';\n\n\t/**\n\t * Publisher logo.\n\t */\n\tprotected string $publisher_logo = '';\n\n\t/**\n\t * Poster source set sizes.\n\t */\n\tprotected string $poster_sizes = '';\n\n\t/**\n\t * Poster source set.\n\t */\n\tprotected string $poster_srcset = '';\n\n\t/**\n\t * Publisher logo size.\n\t *\n\t * @var int[]\n\t * @phpstan-var array{0: int, 1: int}|array{}\n\t */\n\tprotected array $publisher_logo_size = [];\n\n\t/**\n\t * Poster portrait logo size.\n\t *\n\t * @var int[]\n\t * @phpstan-var array{0: int, 1: int}|array{}\n\t */\n\tprotected array $poster_portrait_size = [];\n\n\t/**\n\t * Array of product data.\n\t *\n\t * @var Product[]\n\t */\n\tprotected array $products = [];\n\n\t/**\n\t * Poster url - portrait.\n\t */\n\tprotected string $poster_portrait = '';\n\n\t/**\n\t * Date for the story.\n\t */\n\tprotected string $date = '';\n\n\t/**\n\t * Author of story.\n\t */\n\tprotected string $author = '';\n\n\t/**\n\t * Story constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string,mixed> $story Array of attributes.\n\t */\n\tpublic function __construct( array $story = [] ) {\n\t\tforeach ( $story as $key => $value ) {\n\t\t\tif ( property_exists( $this, $key ) ) {\n\t\t\t\t$this->$key = $value;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Load story from post.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param int|null|WP_Post $_post Post id or Post object.\n\t */\n\tpublic function load_from_post( $_post ): bool {\n\t\t/**\n\t\t * Filters the publisher's name\n\t\t *\n\t\t * @since 1.7.0\n\t\t *\n\t\t * @param string $name Publisher Name.\n\t\t */\n\t\t$this->publisher_name = apply_filters( 'web_stories_publisher_name', get_bloginfo( 'name' ) );\n\n\t\t$post = get_post( $_post );\n\t\tif ( ! $post instanceof WP_Post ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// At this point we assume being passed a legit web-story post or perhaps a web-story revision.\n\n\t\t$this->id      = $post->ID;\n\t\t$this->title   = get_the_title( $post );\n\t\t$this->excerpt = $post->post_excerpt;\n\t\t$this->markup  = $post->post_content;\n\t\t$this->url     = (string) get_permalink( $post );\n\n\t\t$thumbnail_id = (int) get_post_thumbnail_id( $post );\n\n\t\tif ( 0 !== $thumbnail_id ) {\n\t\t\t$poster_src = wp_get_attachment_image_src( $thumbnail_id, Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS );\n\n\t\t\tif ( $poster_src ) {\n\t\t\t\t[ $poster_url, $width, $height ] = $poster_src;\n\t\t\t\t$this->poster_portrait           = $poster_url;\n\t\t\t\t$this->poster_portrait_size      = [ (int) $width, (int) $height ];\n\n\t\t\t\t$image_meta = wp_get_attachment_metadata( $thumbnail_id );\n\t\t\t\tif ( $image_meta ) {\n\t\t\t\t\t$size_array          = [ $image_meta['width'], $image_meta['height'] ];\n\t\t\t\t\t$this->poster_sizes  = (string) wp_calculate_image_sizes( $size_array, $poster_url, $image_meta, $thumbnail_id );\n\t\t\t\t\t$this->poster_srcset = (string) wp_calculate_image_srcset( $size_array, $poster_url, $image_meta, $thumbnail_id );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/**\n\t\t\t * Poster.\n\t\t\t *\n\t\t\t * @var array{url:string, width: int, height: int}|false $poster\n\t\t\t */\n\t\t\t$poster = get_post_meta( $post->ID, Story_Post_Type::POSTER_META_KEY, true );\n\t\t\tif ( ! empty( $poster ) ) {\n\t\t\t\t$this->poster_portrait      = $poster['url'];\n\t\t\t\t$this->poster_portrait_size = [ (int) $poster['width'], (int) $poster['height'] ];\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Publisher logo ID.\n\t\t *\n\t\t * @var string|int $publisher_logo_id\n\t\t */\n\t\t$publisher_logo_id = get_post_meta( $this->id, Story_Post_Type::PUBLISHER_LOGO_META_KEY, true );\n\n\t\tif ( ! empty( $publisher_logo_id ) ) {\n\t\t\t$img_src = wp_get_attachment_image_src( (int) $publisher_logo_id, Image_Sizes::PUBLISHER_LOGO_IMAGE_DIMENSIONS );\n\n\t\t\tif ( $img_src ) {\n\t\t\t\t[ $src, $width, $height ]  = $img_src;\n\t\t\t\t$this->publisher_logo_size = [ $width, $height ];\n\t\t\t\t$this->publisher_logo      = $src;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Product data.\n\t\t *\n\t\t * @var ProductData[]|false $products\n\t\t */\n\t\t$products = get_post_meta( $this->id, Product_Meta::PRODUCTS_POST_META_KEY, true );\n\n\t\tif ( \\is_array( $products ) ) {\n\t\t\t$product_objects = [];\n\t\t\tforeach ( $products as $product ) {\n\t\t\t\t$product_objects[] = Product::load_from_array( $product );\n\t\t\t}\n\t\t\t$this->products = $product_objects;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Setter for poster set sizes.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $poster_sizes Poster sizes.\n\t */\n\tpublic function set_poster_sizes( string $poster_sizes ): void {\n\t\t$this->poster_sizes = $poster_sizes;\n\t}\n\n\t/**\n\t * Setter for poster source set.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $poster_srcset Poster source set.\n\t */\n\tpublic function set_poster_srcset( string $poster_srcset ): void {\n\t\t$this->poster_srcset = $poster_srcset;\n\t}\n\n\t/**\n\t * Setter for title.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $title Title.\n\t */\n\tpublic function set_title( string $title ): void {\n\t\t$this->title = $title;\n\t}\n\n\t/**\n\t * Getter for poster source set sizes.\n\t *\n\t * @since 1.18.0\n\t */\n\tpublic function get_poster_sizes(): string {\n\t\treturn $this->poster_sizes;\n\t}\n\n\t/**\n\t * Getter for poster source set.\n\t *\n\t * @since 1.18.0\n\t */\n\tpublic function get_poster_srcset(): string {\n\t\treturn $this->poster_srcset;\n\t}\n\n\t/**\n\t * Getter for title attribute.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function get_title(): string {\n\t\treturn $this->title;\n\t}\n\n\t/**\n\t * Getter for excerpt attribute.\n\t */\n\tpublic function get_excerpt(): string {\n\t\treturn $this->excerpt;\n\t}\n\n\t/**\n\t * Getter for url attribute.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function get_url(): string {\n\t\treturn $this->url;\n\t}\n\n\t/**\n\t * Getter for markup attribute.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function get_markup(): string {\n\t\treturn $this->markup;\n\t}\n\n\t/**\n\t * Getter for poster portrait attribute.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function get_poster_portrait(): string {\n\t\treturn $this->poster_portrait;\n\t}\n\n\t/**\n\t * Get the story ID.\n\t */\n\tpublic function get_id(): int {\n\t\treturn $this->id;\n\t}\n\n\t/**\n\t * Get author of the story.\n\t */\n\tpublic function get_author(): string {\n\t\treturn $this->author;\n\t}\n\n\t/**\n\t * Date for the story.\n\t */\n\tpublic function get_date(): string {\n\t\treturn $this->date;\n\t}\n\n\t/**\n\t * Returns the publisher name.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return string Publisher Name.\n\t */\n\tpublic function get_publisher_name(): string {\n\t\treturn $this->publisher_name;\n\t}\n\n\t/**\n\t * Returns the story's publisher logo URL.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return string|null Publisher logo URL or null if not set.\n\t */\n\tpublic function get_publisher_logo_url(): ?string {\n\t\t/**\n\t\t * Filters the publisher logo URL.\n\t\t *\n\t\t * @since 1.0.0\n\t\t * @since 1.1.0 The second parameter was deprecated.\n\t\t * @since 1.12.0 The second parameter was repurposed to provide the current story ID.\n\t\t *\n\t\t * @param string|null  $url  Publisher logo URL or null if not set.\n\t\t * @param int|null     $id   Story ID if available.\n\t\t */\n\t\treturn apply_filters( 'web_stories_publisher_logo', $this->publisher_logo, $this->id );\n\t}\n\n\t/**\n\t * Returns the story's publisher logo size.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array {\n\t *     Publisher logo size.\n\t *\n\t *     Array of image data, or empty array if no image is available.\n\t *\n\t *     @type int    $1 Image width in pixels.\n\t *     @type int    $2 Image height in pixels.\n\t * }\n\t *\n\t * @phpstan-return array{0: int, 1: int}|array{}\n\t */\n\tpublic function get_publisher_logo_size(): array {\n\t\t/**\n\t\t * Filters the publisher logo size.\n\t\t *\n\t\t * @since 1.12.0\n\t\t *\n\t\t * @param array   $size {\n\t\t *     Publisher logo size.\n\t\t *\n\t\t *     Array of image data, or empty array if no image is available.\n\t\t *\n\t\t *     @type int    $1 Image width in pixels.\n\t\t *     @type int    $2 Image height in pixels.\n\t\t * }\n\t\t * @param int|null $id   Story ID if available.\n\t\t */\n\t\treturn apply_filters( 'web_stories_publisher_logo_size', $this->publisher_logo_size, $this->id );\n\t}\n\n\t/**\n\t * Get poster portrait size.\n\t *\n\t * @since 1.23.0\n\t *\n\t * @return array {\n\t *     Poster portrait logo size.\n\t *\n\t *     Array of image data, or empty array if no image is available.\n\t *\n\t *     @type int    $1 Image width in pixels.\n\t *     @type int    $2 Image height in pixels.\n\t * }\n\t *\n\t * @phpstan-return array{0: int, 1: int}|array{}\n\t */\n\tpublic function get_poster_portrait_size(): array {\n\t\treturn $this->poster_portrait_size;\n\t}\n\n\t/**\n\t * Get product data.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @return Product[]\n\t */\n\tpublic function get_products(): array {\n\t\treturn $this->products;\n\t}\n}\n"
  },
  {
    "path": "includes/Page_Template_Post_Type.php",
    "content": "<?php\n/**\n * Class Page_Template_Post_Type.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\REST_API\\Page_Template_Controller;\n\n/**\n * Class Page_Template_Post_Type.\n *\n * @phpstan-import-type PostTypeArgs from \\Google\\Web_Stories\\Post_Type_Base\n */\nclass Page_Template_Post_Type extends Post_Type_Base implements HasRequirements {\n\n\t/**\n\t * The slug of the page template post type.\n\t * Limited to web-story-page as web-story-page-template goes over character limit.\n\t */\n\tpublic const POST_TYPE_SLUG = 'web-story-page';\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Page_Template_Post_Type constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Init\n\t */\n\tpublic function register(): void {\n\t\tparent::register();\n\n\t\tadd_action( 'delete_post', [ $this, 'delete_poster_image' ] );\n\t}\n\n\t/**\n\t * Get post type slug.\n\t *\n\t * @since 1.14.0\n\t */\n\tpublic function get_slug(): string {\n\t\treturn self::POST_TYPE_SLUG;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Deletes the associated featured image when a page template is deleted.\n\t *\n\t * This prevents the featured image from becoming an orphan because it is not\n\t * displayed anywhere in WordPress or the story editor.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param int $post_id Post ID.\n\t */\n\tpublic function delete_poster_image( int $post_id ): void {\n\t\tif ( get_post_type( $post_id ) !== $this->get_slug() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$thumbnail_id = get_post_thumbnail_id( $post_id );\n\n\t\tif ( $thumbnail_id ) {\n\t\t\twp_delete_attachment( $thumbnail_id, true );\n\t\t}\n\t}\n\n\t/**\n\t * Registers the post type for page templates.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return array<string, mixed> Post type args.\n\t *\n\t * @phpstan-return PostTypeArgs\n\t */\n\tprotected function get_args(): array {\n\t\t/**\n\t\t * The edit_posts capability.\n\t\t *\n\t\t * @var string $edit_posts\n\t\t */\n\t\t$edit_posts = $this->story_post_type->get_cap_name( 'edit_posts' );\n\n\t\t/**\n\t\t * The delete_posts capability.\n\t\t *\n\t\t * @var string $delete_posts\n\t\t */\n\t\t$delete_posts = $this->story_post_type->get_cap_name( 'delete_posts' );\n\n\t\t$capabilities = [\n\t\t\t'edit_post'              => $edit_posts,\n\t\t\t'read_post'              => $edit_posts,\n\t\t\t'delete_post'            => $delete_posts,\n\t\t\t'edit_posts'             => $edit_posts,\n\t\t\t'edit_others_posts'      => $edit_posts,\n\t\t\t'delete_posts'           => $delete_posts,\n\t\t\t'publish_posts'          => $edit_posts,\n\t\t\t'read_private_posts'     => $edit_posts,\n\t\t\t'delete_private_posts'   => $delete_posts,\n\t\t\t'delete_published_posts' => $delete_posts,\n\t\t\t'delete_others_posts'    => $delete_posts,\n\t\t\t'edit_private_posts'     => $edit_posts,\n\t\t\t'edit_published_posts'   => $edit_posts,\n\t\t\t'create_posts'           => $edit_posts,\n\t\t];\n\n\t\treturn [\n\t\t\t'labels'                => [\n\t\t\t\t'name'                     => _x( 'Page Templates', 'post type general name', 'web-stories' ),\n\t\t\t\t'singular_name'            => _x( 'Page Template', 'post type singular name', 'web-stories' ),\n\t\t\t\t'add_new'                  => __( 'Add New Page Template', 'web-stories' ),\n\t\t\t\t'add_new_item'             => __( 'Add New Page Template', 'web-stories' ),\n\t\t\t\t'edit_item'                => __( 'Edit Page Template', 'web-stories' ),\n\t\t\t\t'new_item'                 => __( 'New Page Template', 'web-stories' ),\n\t\t\t\t'view_item'                => __( 'View Page Template', 'web-stories' ),\n\t\t\t\t'view_items'               => __( 'View Page Templates', 'web-stories' ),\n\t\t\t\t'search_items'             => __( 'Search Page Templates', 'web-stories' ),\n\t\t\t\t'not_found'                => __( 'No page templates found.', 'web-stories' ),\n\t\t\t\t'not_found_in_trash'       => __( 'No page templates found in Trash.', 'web-stories' ),\n\t\t\t\t'all_items'                => __( 'All Page Templates', 'web-stories' ),\n\t\t\t\t'archives'                 => __( 'Page Template Archives', 'web-stories' ),\n\t\t\t\t'attributes'               => __( 'Page Template Attributes', 'web-stories' ),\n\t\t\t\t'insert_into_item'         => __( 'Insert into page template', 'web-stories' ),\n\t\t\t\t'uploaded_to_this_item'    => __( 'Uploaded to this page template', 'web-stories' ),\n\t\t\t\t'featured_image'           => _x( 'Featured Image', 'page template', 'web-stories' ),\n\t\t\t\t'set_featured_image'       => _x( 'Set featured image', 'page template', 'web-stories' ),\n\t\t\t\t'remove_featured_image'    => _x( 'Remove featured image', 'page template', 'web-stories' ),\n\t\t\t\t'use_featured_image'       => _x( 'Use as featured image', 'page template', 'web-stories' ),\n\t\t\t\t'filter_by_date'           => __( 'Filter by date', 'web-stories' ),\n\t\t\t\t'filter_items_list'        => __( 'Filter page templates list', 'web-stories' ),\n\t\t\t\t'items_list_navigation'    => __( 'Page Templates list navigation', 'web-stories' ),\n\t\t\t\t'items_list'               => __( 'Page Templates list', 'web-stories' ),\n\t\t\t\t'item_published'           => __( 'Page Template published.', 'web-stories' ),\n\t\t\t\t'item_published_privately' => __( 'Page Template published privately.', 'web-stories' ),\n\t\t\t\t'item_reverted_to_draft'   => __( 'Page Template reverted to draft.', 'web-stories' ),\n\t\t\t\t'item_scheduled'           => __( 'Page Template scheduled', 'web-stories' ),\n\t\t\t\t'item_updated'             => __( 'Page Template updated.', 'web-stories' ),\n\t\t\t\t'menu_name'                => _x( 'Page Templates', 'admin menu', 'web-stories' ),\n\t\t\t\t'name_admin_bar'           => _x( 'Page Template', 'add new on admin bar', 'web-stories' ),\n\t\t\t\t'item_link'                => _x( 'Page Template Link', 'navigation link block title', 'web-stories' ),\n\t\t\t\t'item_link_description'    => _x( 'A link to a page template.', 'navigation link block description', 'web-stories' ),\n\t\t\t\t'item_trashed'             => __( 'Page Template trashed.', 'web-stories' ),\n\t\t\t],\n\t\t\t'supports'              => [\n\t\t\t\t'title',\n\t\t\t\t'thumbnail', // Used for preview images in the editor.\n\t\t\t],\n\t\t\t'capabilities'          => $capabilities,\n\t\t\t'rewrite'               => false,\n\t\t\t'public'                => false,\n\t\t\t'show_ui'               => false,\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t\t'rest_controller_class' => Page_Template_Controller::class,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Plugin.php",
    "content": "<?php\n/**\n * Main Plugin class.\n *\n * Responsible for initializing the plugin.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\AMP\\Output_Buffer;\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\ServiceBasedPlugin;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\n\n/**\n * Plugin class.\n */\nclass Plugin extends ServiceBasedPlugin {\n\n\t/**\n\t * The \"plugin\" is only a tool to hook arbitrary code up to the WordPress\n\t * execution flow.\n\t *\n\t * The main structure we use to modularize our code is \"services\". These are\n\t * what makes up the actual plugin, and they provide self-contained pieces\n\t * of code that can work independently.\n\t */\n\tpublic const ENABLE_FILTERS_DEFAULT = false;\n\n\t/**\n\t * Prefix to use for all actions and filters.\n\t *\n\t * This is used to make the filters for the dependency injector unique.\n\t */\n\tpublic const HOOK_PREFIX = 'web_stories_';\n\n\t/**\n\t * List of services.\n\t *\n\t * The services array contains a map of <identifier> => <service class name>\n\t * associations.\n\t */\n\tpublic const SERVICES = [\n\t\t'activation_notice'            => Admin\\Activation_Notice::class,\n\t\t'admin.google_fonts'           => Admin\\Google_Fonts::class,\n\t\t'amp_output_buffer'            => Output_Buffer::class,\n\t\t'amp_story_player_assets'      => AMP_Story_Player_Assets::class,\n\t\t'adsense'                      => AdSense::class,\n\t\t'ad_manager'                   => Ad_Manager::class,\n\t\t'mgid'                         => Mgid::class,\n\t\t'admin'                        => Admin\\Admin::class,\n\t\t'analytics'                    => Analytics::class,\n\t\t'coi'                          => Admin\\Cross_Origin_Isolation::class,\n\t\t'customizer'                   => Admin\\Customizer::class,\n\t\t'dashboard'                    => Admin\\Dashboard::class,\n\t\t'database_upgrader'            => Database_Upgrader::class,\n\t\t'discovery'                    => Discovery::class,\n\t\t'editor'                       => Admin\\Editor::class,\n\t\t'embed_shortcode'              => Shortcode\\Embed_Shortcode::class,\n\t\t'experiments'                  => Experiments::class,\n\t\t'integrations.amp'             => Integrations\\AMP::class,\n\t\t'integrations.ezoic'           => Integrations\\Ezoic::class,\n\t\t'integrations.jetpack'         => Integrations\\Jetpack::class,\n\t\t'integrations.newrelic'        => Integrations\\New_Relic::class,\n\t\t'integrations.nextgen_gallery' => Integrations\\NextGen_Gallery::class,\n\t\t'integrations.cfi'             => Integrations\\Conditional_Featured_Image::class,\n\t\t'integrations.sitekit'         => Integrations\\Site_Kit::class,\n\t\t'integrations.themes_support'  => Integrations\\Core_Themes_Support::class,\n\t\t'integrations.shortpixel'      => Integrations\\ShortPixel::class,\n\t\t'kses'                         => KSES::class,\n\t\t'font_post_type'               => Font_Post_Type::class,\n\t\t'page_template_post_type'      => Page_Template_Post_Type::class,\n\t\t'plugin_row_meta'              => Admin\\PluginRowMeta::class,\n\t\t'plugin_action_links'          => Admin\\PluginActionLinks::class,\n\t\t'product_meta'                 => Shopping\\Product_Meta::class,\n\t\t'media.base_color'             => Media\\Base_Color::class,\n\t\t'media.blurhash'               => Media\\Blurhash::class,\n\t\t'media.image_sizes'            => Media\\Image_Sizes::class,\n\t\t'media.media_source'           => Media\\Media_Source_Taxonomy::class,\n\t\t'media.video.captions'         => Media\\Video\\Captions::class,\n\t\t'media.cropping'               => Media\\Cropping::class,\n\t\t'media.video.muting'           => Media\\Video\\Muting::class,\n\t\t'media.video.optimization'     => Media\\Video\\Optimization::class,\n\t\t'media.video.poster'           => Media\\Video\\Poster::class,\n\t\t'media.video.trimming'         => Media\\Video\\Trimming::class,\n\t\t'media.video.is_gif'           => Media\\Video\\Is_Gif::class,\n\t\t'meta_boxes'                   => Admin\\Meta_Boxes::class,\n\t\t'settings'                     => Settings::class,\n\t\t'site_health'                  => Admin\\Site_Health::class,\n\t\t'story_archive'                => Story_Archive::class,\n\t\t'story_post_type'              => Story_Post_Type::class,\n\t\t'story_revisions'              => Story_Revisions::class,\n\t\t'story_shortcode'              => Shortcode\\Stories_Shortcode::class,\n\t\t'svg'                          => Media\\SVG::class,\n\t\t'tracking'                     => Tracking::class,\n\t\t'tinymce'                      => Admin\\TinyMCE::class,\n\t\t'register.widget'              => Register_Widget::class,\n\t\t'renderer.archives'            => Renderer\\Archives::class,\n\t\t'renderer.single'              => Renderer\\Single::class,\n\t\t'renderer.oembed'              => Renderer\\Oembed::class,\n\t\t'renderer.feed'                => Renderer\\Feed::class,\n\t\t'user.capabilities'            => User\\Capabilities::class,\n\t\t'rest.embed_controller'        => REST_API\\Embed_Controller::class,\n\t\t'rest.link_controller'         => REST_API\\Link_Controller::class,\n\t\t'rest.hotlinking_controller'   => REST_API\\Hotlinking_Controller::class,\n\t\t'rest.products'                => REST_API\\Products_Controller::class,\n\t\t'rest.publisher_logos'         => REST_API\\Publisher_Logos_Controller::class,\n\t\t'rest.status_check_controller' => REST_API\\Status_Check_Controller::class,\n\t\t'rest.stories_lock'            => REST_API\\Stories_Lock_Controller::class,\n\t\t'rest.media'                   => REST_API\\Stories_Media_Controller::class,\n\t\t'rest.settings'                => REST_API\\Stories_Settings_Controller::class,\n\t\t'rest.users'                   => REST_API\\Stories_Users_Controller::class,\n\t\t'rest.taxonomies'              => REST_API\\Stories_Taxonomies_Controller::class,\n\t\t'taxonomy.category'            => Taxonomy\\Category_Taxonomy::class,\n\t\t'taxonomy.tag'                 => Taxonomy\\Tag_Taxonomy::class,\n\t\t'user_preferences'             => User\\Preferences::class,\n\t\t'remove_transients'            => Remove_Transients::class,\n\t\t'web_stories_block'            => Block\\Web_Stories_Block::class,\n\t];\n\n\t/**\n\t * Get the list of services to register.\n\t *\n\t * The services array contains a map of <identifier> => <service class name>\n\t * associations.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string, string> Associative array of identifiers mapped to fully\n\t *                               qualified class names.\n\t */\n\tprotected function get_service_classes(): array {\n\t\treturn self::SERVICES;\n\t}\n\n\t/**\n\t * Get the shared instances for the dependency injector.\n\t *\n\t * The shared instances array contains a list of FQCNs that are meant to be\n\t * reused. For multiple \"make()\" requests, the injector will return the same\n\t * instance reference for these, instead of always returning a new one.\n\t *\n\t * This effectively turns these FQCNs into a \"singleton\", without incurring\n\t * all the drawbacks of the Singleton design anti-pattern.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string> Array of fully qualified class names.\n\t */\n\tprotected function get_shared_instances(): array {\n\t\treturn [\n\t\t\tAdmin\\Customizer::class,\n\t\t\tAdmin\\Google_Fonts::class,\n\t\t\tAdmin\\Meta_Boxes::class,\n\t\t\tAnalytics::class,\n\t\t\tAssets::class,\n\t\t\tContext::class,\n\t\t\tDecoder::class,\n\t\t\tExperiments::class,\n\t\t\tStory_Post_Type::class,\n\t\t\tInjector::class,\n\t\t\tIntegrations\\Plugin_Status::class,\n\t\t\tIntegrations\\Site_Kit::class,\n\t\t\tIntegrations\\WooCommerce::class,\n\t\t\tMedia\\Types::class,\n\t\t\tShopping_Vendors::class,\n\t\t\tLocale::class,\n\t\t\tSettings::class,\n\t\t\tStories_Script_Data::class,\n\t\t\tUser\\Preferences::class,\n\t\t];\n\t}\n\n\t/**\n\t * Get the delegations for the dependency injector.\n\t *\n\t * The delegations array contains a map of <class> => <callable>\n\t * mappings.\n\t *\n\t * The <callable> is basically a factory to provide custom instantiation\n\t * logic for the given <class>.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<callable> Associative array of callables.\n\t */\n\tprotected function get_delegations(): array {\n\t\treturn [\n\t\t\tInjector::class => static fn() => Services::get( 'injector' ),\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/PluginFactory.php",
    "content": "<?php\n/**\n * PluginFactory class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\ServiceBasedPlugin;\n\n/**\n * PluginFactory class.\n *\n * The plugin factory is responsible for instantiating the plugin and returning\n * that instance.\n *\n * It can decide whether to return a shared or a fresh instance as needed.\n *\n * To read more about why this is preferable to a Singleton,\n *\n * @since 1.11.0\n *\n * @see https://www.alainschlesser.com/singletons-shared-instances/\n */\nclass PluginFactory extends ServiceBasedPlugin {\n\n\t/**\n\t * Create and return an instance of the plugin.\n\t *\n\t * This always returns a shared instance. This way, outside code can always\n\t * get access to the object instance of the plugin.\n\t *\n\t * @return Plugin Plugin instance.\n\t */\n\tpublic static function create(): Plugin {\n\t\tstatic $plugin = null;\n\n\t\tif ( null === $plugin ) {\n\t\t\t$plugin = new Plugin();\n\t\t}\n\n\t\treturn $plugin;\n\t}\n}\n"
  },
  {
    "path": "includes/Post_Type_Base.php",
    "content": "<?php\n/**\n * Class Post_Type_Base\n *\n * Base class for registering and handling post types.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\PluginActivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginDeactivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\SiteInitializationAware;\nuse WP_Error;\nuse WP_Post_Type;\nuse WP_REST_Controller;\nuse WP_REST_Posts_Controller;\nuse WP_Rewrite;\nuse WP_Site;\n\n/**\n * Class Post_Type_Base.\n *\n * @phpstan-type PostTypeArgs array{\n *   label?: string,\n *   labels?: string[],\n *   description?: string,\n *   public?: bool,\n *   hierarchical?: bool,\n *   exclude_from_search?: bool,\n *   publicly_queryable?: bool,\n *   show_ui?: bool,\n *   show_in_menu?: bool|string,\n *   show_in_nav_menus?: bool,\n *   show_in_admin_bar?: bool,\n *   show_in_rest?: bool,\n *   rest_base?: string,\n *   rest_namespace?: string,\n *   rest_controller_class?: string,\n *   menu_position?: int,\n *   menu_icon?: string,\n *   capability_type?: string|array{0: string, 1: string},\n *   capabilities?: array<string, string>,\n *   map_meta_cap?: bool,\n *   supports?: array<int, string|array<string, mixed>>,\n *   register_meta_box_cb?: callable,\n *   taxonomies?: string[],\n *   has_archive?: bool|string,\n *   rewrite?: bool|array{\n *     slug?: string,\n *     with_front?: bool,\n *     feeds?: bool,\n *     pages?: bool,\n *     ep_mask?: int\n *   },\n *   query_var?: string|bool,\n *   can_export?: bool,\n *   delete_with_user?: bool,\n *   template?: array<int, array{\n *     name: string,\n *     attributes?: array<string, mixed>\n *   }>,\n *   template_lock?: string|false,\n *   _builtin?: bool,\n *   _edit_link?: string\n * }\n */\nabstract class Post_Type_Base extends Service_Base implements PluginActivationAware, PluginDeactivationAware, SiteInitializationAware, PluginUninstallAware {\n\n\t/**\n\t * Default REST Namespace.\n\t */\n\tpublic const REST_NAMESPACE = 'web-stories/v1';\n\n\t/**\n\t * Registers the post type.\n\t *\n\t * @since 1.14.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_post_type();\n\t}\n\n\t/**\n\t * Register post type.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return WP_Post_Type|WP_Error\n\t */\n\tpublic function register_post_type() {\n\t\treturn register_post_type( $this->get_slug(), $this->get_args() );\n\t}\n\n\t/**\n\t * Unregister post type.\n\t *\n\t * @since 1.14.0\n\t */\n\tpublic function unregister_post_type(): void {\n\t\tunregister_post_type( $this->get_slug() );\n\t}\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\t$this->register_post_type();\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->register_post_type();\n\t}\n\n\t/**\n\t * Act on plugin deactivation.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param bool $network_wide Whether the deactivation was done network-wide.\n\t */\n\tpublic function on_plugin_deactivation( bool $network_wide ): void {\n\t\t$this->unregister_post_type();\n\t}\n\n\t/**\n\t * Post type slug.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @phpstan-return lowercase-string&non-empty-string\n\t */\n\tabstract public function get_slug(): string;\n\n\t/**\n\t * Get REST base name based on the post type.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return string REST base.\n\t */\n\tpublic function get_rest_base(): string {\n\t\t$post_type_object = $this->get_object();\n\t\t$rest_base        = $this->get_slug();\n\t\tif ( $post_type_object instanceof WP_Post_Type ) {\n\t\t\t$rest_base = ! empty( $post_type_object->rest_base ) && \\is_string( $post_type_object->rest_base ) ?\n\t\t\t\t$post_type_object->rest_base :\n\t\t\t\t$post_type_object->name;\n\t\t}\n\n\t\treturn (string) $rest_base;\n\t}\n\n\t/**\n\t * Get REST namespace on the post type.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return string REST base.\n\t */\n\tpublic function get_rest_namespace(): string {\n\t\t$post_type_object = $this->get_object();\n\t\t$rest_namespace   = isset( $post_type_object, $post_type_object->rest_namespace ) && \\is_string( $post_type_object->rest_namespace ) ?\n\t\t\t$post_type_object->rest_namespace :\n\t\t\tself::REST_NAMESPACE;\n\n\t\treturn (string) $rest_namespace;\n\t}\n\n\t/**\n\t * Get REST url for post type.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return string REST base.\n\t */\n\tpublic function get_rest_url(): string {\n\t\treturn rest_get_route_for_post_type_items( $this->get_slug() );\n\t}\n\n\t/**\n\t * Returns all capabilities for the post type.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @return string[] The post type capabilities.\n\t */\n\tpublic function get_caps(): array {\n\t\t$post_type_obj = $this->get_object();\n\n\t\tif ( ! $post_type_obj instanceof WP_Post_Type ) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn (array) $post_type_obj->cap;\n\t}\n\n\t/**\n\t * Determines whether the current user has a specific capability for this post type.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param string $cap Capability name.\n\t * @return bool Whether the user has the capability.\n\t */\n\tpublic function has_cap( string $cap ): bool {\n\t\t$capability_name = $this->get_cap_name( $cap );\n\t\t$capability      = false;\n\t\tif ( $capability_name ) {\n\t\t\t$capability = current_user_can( $capability_name ); // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t}\n\n\t\treturn $capability;\n\t}\n\n\t/**\n\t * Returns a specific post type capability name.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param string $cap Capability name.\n\t * @return string|false Capability name if found, false otherwise.\n\t */\n\tpublic function get_cap_name( string $cap ) {\n\t\t$post_type_obj   = $this->get_object();\n\t\t$capability_name = false;\n\n\t\tif ( ! $post_type_obj instanceof WP_Post_Type ) {\n\t\t\treturn $capability_name;\n\t\t}\n\n\t\tif ( property_exists( $post_type_obj->cap, $cap ) ) {\n\t\t\t$capability_name = $post_type_obj->cap->$cap;\n\t\t}\n\n\t\treturn $capability_name;\n\t}\n\n\t/**\n\t * Get Label on the post type slug and name.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param string $label Label name.\n\t */\n\tpublic function get_label( string $label ): string {\n\t\t$post_type_obj = $this->get_object();\n\t\t$name          = '';\n\n\t\tif ( ! $post_type_obj instanceof WP_Post_Type ) {\n\t\t\treturn $name;\n\t\t}\n\n\t\tif ( property_exists( $post_type_obj->labels, $label ) ) {\n\t\t\t$name = $post_type_obj->labels->$label;\n\t\t}\n\n\t\treturn $name;\n\t}\n\n\t/**\n\t * Get rest controller on the post type slug.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return WP_REST_Posts_Controller|WP_REST_Controller\n\t */\n\tpublic function get_parent_controller(): WP_REST_Controller {\n\t\t$post_type_obj     = $this->get_object();\n\t\t$parent_controller = null;\n\n\t\tif ( $post_type_obj instanceof WP_Post_Type ) {\n\t\t\t$parent_controller = $post_type_obj->get_rest_controller();\n\t\t}\n\n\t\tif ( ! $parent_controller ) {\n\t\t\t$parent_controller = new WP_REST_Posts_Controller( $this->get_slug() );\n\t\t}\n\n\t\treturn $parent_controller;\n\t}\n\n\t/**\n\t * Retrieves the permalink for a post type archive.\n\t *\n\t * Identical to {@see get_post_type_archive_link()}, but also returns a URL\n\t * if the archive page has been disabled.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.14.0\n\t *\n\t * @global WP_Rewrite $wp_rewrite WordPress rewrite component.\n\t *\n\t * @param  bool $ignore_has_archive Ignore 'has_archive' value to get default permalink.\n\t * @return string|false The post type archive permalink. False if the post type does not exist.\n\t */\n\tpublic function get_archive_link( bool $ignore_has_archive = false ) {\n\t\tglobal $wp_rewrite;\n\n\t\t$post_type_obj = $this->get_object();\n\t\tif ( ! $post_type_obj instanceof WP_Post_Type ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( get_option( 'permalink_structure' ) && \\is_array( $post_type_obj->rewrite ) ) {\n\t\t\t$struct = true === $post_type_obj->has_archive || $ignore_has_archive ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;\n\t\t\tif ( $post_type_obj->rewrite['with_front'] ) {\n\t\t\t\t$struct = $wp_rewrite->front . $struct;\n\t\t\t} else {\n\t\t\t\t$struct = $wp_rewrite->root . $struct;\n\t\t\t}\n\t\t\t$link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );\n\t\t} else {\n\t\t\t$link = home_url( '?post_type=' . $this->get_slug() );\n\t\t}\n\n\t\t/** This filter is documented in wp-includes/link-template.php */\n\t\treturn apply_filters( 'post_type_archive_link', $link, $this->get_slug() );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n        // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.get_posts_get_posts -- False positive.\n\t\t$cpt_posts = get_posts(\n\t\t\t[\n\t\t\t\t'fields'           => 'ids',\n\t\t\t\t'suppress_filters' => false,\n\t\t\t\t'post_status'      => 'any',\n\t\t\t\t'post_type'        => $this->get_slug(),\n\t\t\t\t'posts_per_page'   => -1,\n\t\t\t]\n\t\t);\n\n\t\tforeach ( $cpt_posts as $post_id ) {\n\t\t\twp_delete_post( (int) $post_id, true );\n\t\t}\n\t}\n\n\t/**\n\t * Post type args.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return array<string, mixed> Post type args.\n\t *\n\t * @phpstan-return PostTypeArgs\n\t */\n\tabstract protected function get_args(): array;\n\n\t/**\n\t * Get post type object.\n\t *\n\t * @since 1.14.0\n\t */\n\tprotected function get_object(): ?WP_Post_Type {\n\t\treturn get_post_type_object( $this->get_slug() );\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Embed_Controller.php",
    "content": "<?php\n/**\n * Class Embed_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse DOMElement;\nuse DOMNode;\nuse DOMNodeList;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse WP_Error;\nuse WP_Http;\nuse WP_Network;\nuse WP_Post;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Embed controller class.\n *\n * API endpoint to facilitate embedding web stories.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n *\n * @phpstan-type Schema array{\n *   properties: array<string, SchemaEntry>\n * }\n */\nclass Embed_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'embed';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for links.\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_proxy_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'get_proxy_item_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'url' => [\n\t\t\t\t\t\t\t'description' => __( 'The URL for which to fetch embed data.', 'web-stories' ),\n\t\t\t\t\t\t\t'required'    => true,\n\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Callback for the Web Stories embed endpoints.\n\t *\n\t * Returns information about the given story.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Full data about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function get_proxy_item( $request ) {\n\t\t/**\n\t\t * Requested URL.\n\t\t *\n\t\t * @var string $url\n\t\t */\n\t\t$url = $request['url'];\n\t\t$url = urldecode( untrailingslashit( $url ) );\n\n\t\tif ( empty( $url ) ) {\n\t\t\treturn new \\WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t/**\n\t\t * Filters the link data TTL value.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param int $time Time to live (in seconds). Default is 1 day.\n\t\t * @param string $url The attempted URL.\n\t\t */\n\t\t$cache_ttl = apply_filters( 'web_stories_embed_data_cache_ttl', DAY_IN_SECONDS, $url );\n\t\t$cache_key = 'web_stories_embed_data_' . md5( $url );\n\n\t\t$data = get_transient( $cache_key );\n\n\t\tif ( \\is_string( $data ) && ! empty( $data ) ) {\n\t\t\t/**\n\t\t\t * Decoded cached embed data.\n\t\t\t *\n\t\t\t * @var array<string,mixed>|null $embed\n\t\t\t */\n\t\t\t$embed = json_decode( $data, true );\n\n\t\t\tif ( $embed ) {\n\t\t\t\t$response = $this->prepare_item_for_response( $embed, $request );\n\t\t\t\treturn rest_ensure_response( $response );\n\t\t\t}\n\t\t}\n\n\t\t$data = $this->get_data_from_post( $url );\n\t\tif ( $data ) {\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\t$args = [\n\t\t\t'limit_response_size' => 153_600, // 150 KB.\n\t\t\t'timeout'             => 7, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout\n\t\t];\n\n\t\t/**\n\t\t * Filters the HTTP request args for link data retrieval.\n\t\t *\n\t\t * Can be used to adjust timeout and response size limit.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array<string,mixed> $args Arguments used for the HTTP request\n\t\t * @param string $url The attempted URL.\n\t\t *\n\t\t * @phpstan-param array{\n\t\t *   method?: string,\n\t\t *   timeout?: float,\n\t\t *   redirection?: int,\n\t\t *   httpversion?: string,\n\t\t *   user-agent?: string,\n\t\t *   reject_unsafe_urls?: bool,\n\t\t *   blocking?: bool,\n\t\t *   headers?: string|array,\n\t\t *   cookies?: array,\n\t\t *   body?: string|array,\n\t\t *   compress?: bool,\n\t\t *   decompress?: bool,\n\t\t *   sslverify?: bool,\n\t\t *   sslcertificates?: string,\n\t\t *   stream?: bool,\n\t\t *   filename?: string,\n\t\t *   limit_response_size?: int,\n\t\t * } $args\n\t\t */\n\t\t$args = apply_filters( 'web_stories_embed_data_request_args', $args, $url );\n\n\t\t$response = wp_safe_remote_get( $url, $args );\n\n\t\tif ( WP_Http::OK !== wp_remote_retrieve_response_code( $response ) ) {\n\t\t\t// Not saving the error response to cache since the error might be temporary.\n\t\t\treturn new \\WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$html = wp_remote_retrieve_body( $response );\n\n\t\tif ( ! $html ) {\n\t\t\treturn new \\WP_Error( 'rest_invalid_story', __( 'URL is not a story', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$data = $this->get_data_from_document( $html );\n\n\t\tif ( ! $data ) {\n\t\t\treturn new \\WP_Error( 'rest_invalid_story', __( 'URL is not a story', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\n\t\treturn rest_ensure_response( $response );\n\t}\n\n\t/**\n\t * Prepares a single embed output for response.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array<string, mixed>|false $embed Embed value, default to false is not set.\n\t * @param WP_REST_Request            $request Request object.\n\t * @return WP_REST_Response|WP_Error Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $embed, $request ) {\n\t\t$fields = $this->get_fields_for_response( $request );\n\t\t$schema = $this->get_item_schema();\n\n\t\t$data = [];\n\n\t\tif ( \\is_array( $embed ) ) {\n\t\t\t$check_fields = array_keys( $embed );\n\t\t\tforeach ( $check_fields as $check_field ) {\n\t\t\t\tif ( ! empty( $schema['properties'][ $check_field ] ) && rest_is_field_included( $check_field, $fields ) ) {\n\t\t\t\t\t$data[ $check_field ] = rest_sanitize_value_from_schema( $embed[ $check_field ], $schema['properties'][ $check_field ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\treturn rest_ensure_response( $data );\n\t}\n\n\n\t/**\n\t * Retrieves the link's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'embed',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'title'  => [\n\t\t\t\t\t'description' => __( 'Embed\\'s title', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'poster' => [\n\t\t\t\t\t'description' => __( 'Embed\\'s image', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Checks if current user can process links.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function get_proxy_item_permissions_check() {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new \\WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to make proxied embed requests.', 'web-stories' ), [ 'status' => rest_authorization_required_code() ] );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Retrieves the story metadata for a given URL on the current site.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $url The URL that should be inspected for metadata.\n\t * @return array{title: string, poster: string}|false Story metadata if the URL does belong to the current site. False otherwise.\n\t */\n\tprivate function get_data_from_post( string $url ) {\n\t\t$post = $this->url_to_post( $url );\n\n\t\tif ( ! $post || $this->story_post_type->get_slug() !== $post->post_type ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $this->get_data_from_document( $post->post_content );\n\t}\n\n\t/**\n\t * Examines a URL and try to determine the post it represents.\n\t *\n\t * Checks are supposedly from the hosted site blog.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.2.0\n\t *\n\t * @see get_oembed_response_data_for_url\n\t * @see url_to_postid\n\t *\n\t * @param string $url Permalink to check.\n\t * @return WP_Post|null Post object on success, null otherwise.\n\t */\n\tprivate function url_to_post( $url ): ?WP_Post {\n\t\t$post          = null;\n\t\t$switched_blog = $this->maybe_switch_site( $url );\n\n\n\t\tif ( \\function_exists( 'wpcom_vip_url_to_postid' ) ) {\n\t\t\t$post_id = wpcom_vip_url_to_postid( $url );\n\t\t} else {\n\t\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions\n\t\t\t$post_id = url_to_postid( $url );\n\t\t}\n\n\t\tif ( $post_id ) {\n\t\t\t$post = get_post( $post_id );\n\t\t}\n\n\t\tif ( ! $post_id ) {\n\t\t\t// url_to_postid() does not recognize plain permalinks like https://example.com/?web-story=my-story.\n\t\t\t// Let's check for that ourselves.\n\n\t\t\t/**\n\t\t\t * The URL's hostname.\n\t\t\t *\n\t\t\t * @var string|false|null $url_host\n\t\t\t */\n\t\t\t$url_host = wp_parse_url( $url, PHP_URL_HOST );\n\t\t\tif ( $url_host ) {\n\t\t\t\t$url_host = str_replace( 'www.', '', $url_host );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * The home URL's hostname.\n\t\t\t *\n\t\t\t * @var string|false|null $home_url_host\n\t\t\t */\n\t\t\t$home_url_host = wp_parse_url( home_url(), PHP_URL_HOST );\n\t\t\tif ( $home_url_host ) {\n\t\t\t\t$home_url_host = str_replace( 'www.', '', $home_url_host );\n\t\t\t}\n\n\t\t\tif ( $url_host && $home_url_host && $url_host === $home_url_host ) {\n\t\t\t\t$values = [];\n\t\t\t\tif (\n\t\t\t\tpreg_match(\n\t\t\t\t\t'#[?&](' . preg_quote( $this->story_post_type->get_slug(), '#' ) . ')=([^&]+)#',\n\t\t\t\t\t$url,\n\t\t\t\t\t$values\n\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t$slug = $values[2];\n\n\t\t\t\t\tif ( \\function_exists( 'wpcom_vip_get_page_by_path' ) ) {\n\t\t\t\t\t\t$post = wpcom_vip_get_page_by_path( $slug, OBJECT, $this->story_post_type->get_slug() );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions\n\t\t\t\t\t\t$post = get_page_by_path( $slug, OBJECT, $this->story_post_type->get_slug() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( $switched_blog ) {\n\t\t\trestore_current_blog();\n\t\t}\n\n\t\tif ( ! $post instanceof WP_Post ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn $post;\n\t}\n\n\t/**\n\t * Maybe switch to site.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @param string $url Permalink to check.\n\t */\n\tprivate function maybe_switch_site( $url ): bool {\n\t\tif ( ! is_multisite() ) {\n\t\t\treturn false;\n\t\t}\n\t\t$switched_blog = false;\n\n\t\t/**\n\t\t * URL parts.\n\t\t *\n\t\t * @var array<string, string>|false $url_parts\n\t\t */\n\t\t$url_parts = wp_parse_url( $url );\n\t\tif ( ! $url_parts ) {\n\t\t\t$url_parts = [];\n\t\t}\n\n\t\t$url_parts = wp_parse_args(\n\t\t\t$url_parts,\n\t\t\t[\n\t\t\t\t'host' => '',\n\t\t\t\t'path' => '/',\n\t\t\t]\n\t\t);\n\n\t\t$qv = [\n\t\t\t'domain'                 => $url_parts['host'],\n\t\t\t'path'                   => '/',\n\t\t\t'number'                 => 1,\n\t\t\t'update_site_cache'      => false,\n\t\t\t'update_site_meta_cache' => false,\n\t\t];\n\n\t\t// In case of subdirectory configs, set the path.\n\t\tif ( ! is_subdomain_install() ) {\n\t\t\t// Get \"sub-site\" part of \"http://example.org/sub-site/web-stories/my-story/\".\n\t\t\t// But given just \"http://example.org/web-stories/my-story/\", don't treat \"web-stories\" as site path.\n\t\t\t// This differs from the logic in get_oembed_response_data_for_url() which does not do this.\n\t\t\t// TODO: Investigate possible core bug in get_oembed_response_data_for_url()?\n\t\t\t$path    = explode( '/', ltrim( $url_parts['path'], '/' ) );\n\t\t\t$path    = \\count( $path ) > 2 ? reset( $path ) : false;\n\t\t\t$network = get_network();\n\t\t\tif ( $path && $network instanceof WP_Network ) {\n\t\t\t\t$qv['path'] = $network->path . $path . '/';\n\t\t\t}\n\t\t}\n\n\t\t$sites = (array) get_sites( $qv );\n\t\t$site  = reset( $sites );\n\n\t\tif ( $site && get_current_blog_id() !== (int) $site->blog_id ) {\n\t\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog\n\t\t\tswitch_to_blog( (int) $site->blog_id );\n\n\t\t\t$switched_blog = true;\n\t\t}\n\n\t\treturn $switched_blog;\n\t}\n\n\t/**\n\t * Parses an HTML document to and returns the story's title and poster.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $html HTML document markup.\n\t * @return array{title: string, poster: string}|false Response data or false if document is not a story.\n\t */\n\tprivate function get_data_from_document( string $html ) {\n\t\ttry {\n\t\t\t$doc = Document::fromHtml( $html );\n\t\t} catch ( \\DOMException $exception ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( ! $doc ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t/**\n\t\t * List of <amp-story> elements.\n\t\t *\n\t\t * @var DOMNodeList<DOMElement>|false $amp_story\n\t\t */\n\t\t$amp_story = $doc->xpath->query( '//amp-story' );\n\n\t\tif ( ! $amp_story instanceof DOMNodeList || 0 === $amp_story->length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$title  = $this->get_dom_attribute_content( $amp_story, 'title' );\n\t\t$poster = $this->get_dom_attribute_content( $amp_story, 'poster-portrait-src' );\n\n\t\treturn [\n\t\t\t'title'  => $title ?: '',\n\t\t\t'poster' => $poster ?: '',\n\t\t];\n\t}\n\n\t/**\n\t * Retrieve content of a given DOM node attribute.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param DOMNodeList<DOMElement>|false $query     XPath query result.\n\t * @param string                        $attribute Attribute name.\n\t * @return string|false Attribute content on success, false otherwise.\n\t */\n\tprotected function get_dom_attribute_content( $query, string $attribute ) {\n\t\tif ( ! $query instanceof DOMNodeList || 0 === $query->length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t/**\n\t\t * DOMElement\n\t\t *\n\t\t * @var DOMElement|DOMNode $node\n\t\t */\n\t\t$node = $query->item( 0 );\n\n\t\tif ( ! $node instanceof DOMElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $node->getAttribute( $attribute );\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Font_Controller.php",
    "content": "<?php\n/**\n * Class Font_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse stdClass;\nuse WP_Error;\nuse WP_Post;\nuse WP_Query;\nuse WP_REST_Posts_Controller;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Font_Controller class.\n *\n * @phpstan-type Font array{\n *   family: string,\n *   fallbacks?: string[],\n *   weights?: array<int, array{0: int, 1: int}>,\n *   styles?: string[],\n *   variants?: string[],\n *   service?: string,\n *   metrics?: mixed,\n *   id?: string,\n *   url?: string\n * }\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n * @phpstan-type Schema array{\n *   properties: array{\n *     family?: SchemaEntry,\n *     fallbacks?: SchemaEntry,\n *     weights?: SchemaEntry,\n *     styles?: SchemaEntry,\n *     variants?: SchemaEntry,\n *     service?: SchemaEntry,\n *     metrics?: SchemaEntry,\n *     id?: SchemaEntry,\n *     url?: SchemaEntry\n *   }\n * }\n */\nclass Font_Controller extends WP_REST_Posts_Controller {\n\t/**\n\t * Registers the routes for posts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_items' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'get_items_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_collection_params(),\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::CREATABLE,\n\t\t\t\t\t'callback'            => [ $this, 'create_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'create_item_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),\n\t\t\t\t],\n\t\t\t\t'schema' => [ $this, 'get_public_item_schema' ],\n\t\t\t]\n\t\t);\n\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base . '/(?P<id>[\\d]+)',\n\t\t\t[\n\t\t\t\t'args'   => [\n\t\t\t\t\t'id' => [\n\t\t\t\t\t\t'description' => __( 'Unique identifier for the font.', 'web-stories' ),\n\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::DELETABLE,\n\t\t\t\t\t'callback'            => [ $this, 'delete_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'delete_item_permissions_check' ],\n\t\t\t\t],\n\t\t\t\t'schema' => [ $this, 'get_public_item_schema' ],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Retrieves a collection of fonts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{search?: string, service?: string, include?: string[]}> $request\n\t */\n\tpublic function get_items( $request ) {\n\t\t/**\n\t\t * Fonts list.\n\t\t *\n\t\t * @phpstan-var Font[] $fonts\n\t\t */\n\t\t$fonts = [];\n\n\t\t// Retrieve the list of registered collection query parameters.\n\t\t$registered = $this->get_collection_params();\n\n\t\tif ( isset( $registered['service'], $request['service'] ) ) {\n\t\t\tif ( 'all' === $request['service'] || 'builtin' === $request['service'] ) {\n\t\t\t\tarray_push( $fonts, ...$this->get_builtin_fonts() );\n\n\t\t\t\t// For custom fonts the searching will be done in WP_Query already.\n\t\t\t\tif ( isset( $registered['search'], $request['search'] ) && ! empty( $request['search'] ) ) {\n\t\t\t\t\t$fonts = array_values(\n\t\t\t\t\t\tarray_filter(\n\t\t\t\t\t\t\t$fonts,\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Font data.\n\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t * @param array{family: string} $font\n\t\t\t\t\t\t\t * @return bool\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tstatic fn( array $font ) => false !== stripos( $font['family'], $request['search'] )\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( 'all' === $request['service'] || 'custom' === $request['service'] ) {\n\t\t\t\tarray_push( $fonts, ...$this->get_custom_fonts( $request ) );\n\t\t\t}\n\n\t\t\t// Filter before doing any sorting.\n\t\t\tif ( isset( $registered['include'], $request['include'] ) && ! empty( $request['include'] ) ) {\n\t\t\t\t$include_list = array_map( 'strtolower', $request['include'] );\n\n\t\t\t\t$fonts = array_values(\n\t\t\t\t\tarray_filter(\n\t\t\t\t\t\t$fonts,\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Font data.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * @param array{family: string} $font\n\t\t\t\t\t\t * @return bool\n\t\t\t\t\t\t */\n\t\t\t\t\t\tstatic fn( array $font ): bool => \\in_array( strtolower( $font['family'] ), $include_list, true )\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( 'all' === $request['service'] ) {\n\t\t\t\t// Since the built-in fonts and custom fonts both are already sorted,\n\t\t\t\t// we only need to sort when including both.\n\t\t\t\tusort(\n\t\t\t\t\t$fonts,\n\t\t\t\t\t/**\n\t\t\t\t\t * Font A and Font B.\n\t\t\t\t\t *\n\t\t\t\t\t * @phpstan-param Font $a\n\t\t\t\t\t * @phpstan-param Font $b\n\t\t\t\t\t * @return int\n\t\t\t\t\t */\n\t\t\t\t\tstatic fn( array $a, array $b ): int => strnatcasecmp( $a['family'], $b['family'] )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn rest_ensure_response( $fonts );\n\t}\n\n\t/**\n\t * Checks if a given request has access to read posts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function get_items_permissions_check( $request ) {\n\t\t$post_type = get_post_type_object( $this->post_type );\n\n\t\tif (\n\t\t\t! $post_type ||\n\t\t\t! current_user_can( $post_type->cap->read_post ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden',\n\t\t\t\t__( 'Sorry, you are not allowed to list fonts.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Force-deletes a single font.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function delete_item( $request ) {\n\t\t$request->set_param( 'force', true );\n\n\t\treturn parent::delete_item( $request );\n\t}\n\n\t/**\n\t * Prepares a single post output for response.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_Post         $item    Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $item, $request ): WP_REST_Response {\n\t\t// Restores the more descriptive, specific name for use within this method.\n\t\t$post            = $item;\n\t\t$GLOBALS['post'] = $post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited\n\n\t\tsetup_postdata( $post );\n\n\t\t$fields = $this->get_fields_for_response( $request );\n\n\t\t$data = [];\n\n\t\tif ( rest_is_field_included( 'id', $fields ) ) {\n\t\t\t$data['id'] = $post->ID;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'family', $fields ) ) {\n\t\t\t$data['family'] = $post->post_title;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'service', $fields ) ) {\n\t\t\t$data['service'] = 'custom';\n\t\t}\n\n\t\t/**\n\t\t * Font data.\n\t\t *\n\t\t * @var array<string, mixed>|null $font_data\n\t\t */\n\t\t$font_data = json_decode( $post->post_content, true );\n\n\t\tif ( $font_data ) {\n\t\t\tforeach ( $font_data as $key => $value ) {\n\t\t\t\tif ( rest_is_field_included( $key, $fields ) ) {\n\t\t\t\t\t$data[ $key ] = $value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\t/**\n\t\t * Response object.\n\t\t *\n\t\t * @var WP_REST_Response $response\n\t\t */\n\t\t$response = rest_ensure_response( $data );\n\n\t\tif ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {\n\t\t\t$links = $this->prepare_links( $post );\n\t\t\t$response->add_links( $links );\n\n\t\t\tif ( ! empty( $links['self']['href'] ) ) {\n\t\t\t\t$actions = $this->get_available_actions( $post, $request );\n\n\t\t\t\t$self = $links['self']['href'];\n\n\t\t\t\tforeach ( $actions as $rel ) {\n\t\t\t\t\t$response->add_link( $rel, $self );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the query params for the fonts collection.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['context']['default'] = 'view';\n\n\t\t$query_params['search'] = [\n\t\t\t'description'       => __( 'Limit results to those matching a string.', 'web-stories' ),\n\t\t\t'type'              => 'string',\n\t\t\t'sanitize_callback' => 'sanitize_text_field',\n\t\t\t'validate_callback' => 'rest_validate_request_arg',\n\t\t];\n\n\t\t$query_params['include'] = [\n\t\t\t'description' => __( 'Limit result set to specific fonts.', 'web-stories' ),\n\t\t\t'type'        => 'array',\n\t\t\t'items'       => [\n\t\t\t\t'type' => 'string',\n\t\t\t],\n\t\t\t'default'     => [],\n\t\t];\n\n\t\t$query_params['service'] = [\n\t\t\t'description'       => __( 'Filter fonts by service.', 'web-stories' ),\n\t\t\t'type'              => 'string',\n\t\t\t'sanitize_callback' => 'sanitize_text_field',\n\t\t\t'default'           => 'all',\n\t\t\t'enum'              => [\n\t\t\t\t'all',\n\t\t\t\t'custom',\n\t\t\t\t'builtin', // system + fonts.google.com.\n\t\t\t],\n\t\t];\n\n\t\t/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */\n\t\treturn apply_filters( \"rest_{$this->post_type}_collection_params\", $query_params, $this->post_type );\n\t}\n\n\t/**\n\t * Retrieves the font's schema, conforming to JSON Schema.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => $this->post_type,\n\t\t\t'type'       => 'object',\n\t\t\t// Base properties for every font.\n\t\t\t'properties' => [\n\t\t\t\t'family'    => [\n\t\t\t\t\t'description' => __( 'The font family', 'web-stories' ),\n\t\t\t\t\t'type'        => [ 'string', 'null' ],\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'fallbacks' => [\n\t\t\t\t\t'description' => __( 'Fallback fonts', 'web-stories' ),\n\t\t\t\t\t'type'        => 'array',\n\t\t\t\t\t'items'       => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'weights'   => [\n\t\t\t\t\t'description' => __( 'Font weights', 'web-stories' ),\n\t\t\t\t\t'type'        => 'array',\n\t\t\t\t\t'items'       => [\n\t\t\t\t\t\t'type'    => 'integer',\n\t\t\t\t\t\t'minimum' => 0,\n\t\t\t\t\t\t'maximum' => 900,\n\t\t\t\t\t],\n\t\t\t\t\t'minimum'     => 1,\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'styles'    => [\n\t\t\t\t\t'description' => __( 'Font styles', 'web-stories' ),\n\t\t\t\t\t'type'        => 'array',\n\t\t\t\t\t'items'       => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t],\n\t\t\t\t\t'minimum'     => 1,\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'variants'  => [\n\t\t\t\t\t'description' => __( 'Font variants', 'web-stories' ),\n\t\t\t\t\t'type'        => 'array',\n\t\t\t\t\t'items'       => [\n\t\t\t\t\t\t'type'    => 'array',\n\t\t\t\t\t\t'items'   => [\n\t\t\t\t\t\t\t'type'    => 'integer',\n\t\t\t\t\t\t\t'minimum' => 0,\n\t\t\t\t\t\t\t'maximum' => 900,\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'minimum' => 2,\n\t\t\t\t\t\t'maximum' => 2,\n\t\t\t\t\t],\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'service'   => [\n\t\t\t\t\t'description' => __( 'Font service', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'metrics'   => [\n\t\t\t\t\t'description' => __( 'Font metrics', 'web-stories' ),\n\t\t\t\t\t'type'        => 'object',\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t\t'id'        => [\n\t\t\t\t\t'description' => __( 'Unique identifier for the font.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'url'       => [\n\t\t\t\t\t'description' => __( 'Font URL.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'required'    => true,\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Returns a list of Google fonts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @return array<int, mixed> List of Google fonts.\n\t *\n\t * @phpstan-return Font[]\n\t */\n\tprotected function get_builtin_fonts(): array {\n\t\t$file = WEBSTORIES_PLUGIN_DIR_PATH . 'includes/data/fonts/fonts.json';\n\n\t\tif ( ! is_readable( $file ) ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t$content = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown\n\n\t\tif ( ! $content ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t/**\n\t\t * List of Google Fonts.\n\t\t *\n\t\t * @var array|null $fonts\n\t\t * @phpstan-var Font[]|null $fonts\n\t\t */\n\t\t$fonts = json_decode( $content, true );\n\n\t\tif ( ! $fonts ) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn $fonts;\n\t}\n\n\t/**\n\t * Returns a list of custom fonts.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return array<int, mixed> List of custom fonts.\n\t *\n\t * @phpstan-return Font[]\n\t */\n\tprotected function get_custom_fonts( $request ): array {\n\t\t// Retrieve the list of registered collection query parameters.\n\t\t$registered = $this->get_collection_params();\n\t\t$args       = [\n\t\t\t'orderby' => 'title',\n\t\t\t'order'   => 'ASC',\n\t\t];\n\n\t\t/*\n\t\t * This array defines mappings between public API query parameters whose\n\t\t * values are accepted as-passed, and their internal WP_Query parameter\n\t\t * name equivalents (some are the same). Only values which are also\n\t\t * present in $registered will be set.\n\t\t */\n\t\t$parameter_mappings = [\n\t\t\t'search' => 's',\n\t\t];\n\n\t\t/*\n\t\t * For each known parameter which is both registered and present in the request,\n\t\t * set the parameter's value on the query $args.\n\t\t */\n\t\tforeach ( $parameter_mappings as $api_param => $wp_param ) {\n\t\t\tif ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {\n\t\t\t\t$args[ $wp_param ] = $request[ $api_param ];\n\t\t\t}\n\t\t}\n\n\t\t// Ensure our per_page parameter overrides any provided posts_per_page filter.\n\t\tif ( isset( $registered['per_page'] ) ) {\n\t\t\t$args['posts_per_page'] = $request['per_page'];\n\t\t}\n\n\t\t// Force search to be case-insensitive.\n\n\t\t// Force the post_type argument, since it's not a user input variable.\n\t\t$args['post_type'] = $this->post_type;\n\t\t$query_args        = $this->prepare_items_query( $args, $request );\n\n\t\t$posts_query  = new WP_Query();\n\t\t$query_result = $posts_query->query( $query_args );\n\n\t\t/**\n\t\t * List of custom fonts.\n\t\t *\n\t\t * @var array $posts\n\t\t * @phpstan-var Font[] $posts\n\t\t */\n\t\t$posts = [];\n\n\t\t/**\n\t\t * We're expecting a post object.\n\t\t *\n\t\t * @var WP_Post $post\n\t\t */\n\t\tforeach ( $query_result as $post ) {\n\t\t\tif ( ! $this->check_read_permission( $post ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$data    = $this->prepare_item_for_response( $post, $request );\n\t\t\t$posts[] = $this->prepare_response_for_collection( $data );\n\t\t}\n\n\t\t// Reset filter.\n\t\tif ( 'edit' === $request['context'] ) {\n\t\t\tremove_filter( 'post_password_required', [ $this, 'check_password_required' ] );\n\t\t}\n\n\t\t/**\n\t\t * List of custom fonts.\n\t\t *\n\t\t * @phpstan-var Font[] $posts\n\t\t */\n\n\t\treturn $posts;\n\t}\n\n\t/**\n\t * Prepares a single post for create.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param WP_REST_Request $request Request object.\n\t * @return stdClass|WP_Error Post object or WP_Error.\n\t */\n\tprotected function prepare_item_for_database( $request ) {\n\t\t$prepared_post              = new stdClass();\n\t\t$prepared_post->post_status = 'publish';\n\n\t\t$font_data = [];\n\n\t\t$fields = [\n\t\t\t'family',\n\t\t\t'fallbacks',\n\t\t\t'weights',\n\t\t\t'styles',\n\t\t\t'variants',\n\t\t\t'metrics',\n\t\t\t'url',\n\t\t];\n\n\t\t$schema = $this->get_item_schema();\n\n\t\tforeach ( $fields as $field ) {\n\t\t\tif ( ! empty( $schema['properties'][ $field ] ) && ! empty( $request[ $field ] ) ) {\n\t\t\t\t$font_data[ $field ] = $request[ $field ];\n\n\t\t\t\tif ( 'family' === $field ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Request data.\n\t\t\t\t\t *\n\t\t\t\t\t * @var array{family: string} $request\n\t\t\t\t\t */\n\t\t\t\t\t$font_family = trim( $request['family'] );\n\n\t\t\t\t\t$prepared_post->post_title = $font_family;\n\n\t\t\t\t\tif ( $this->font_exists( $font_family ) ) {\n\t\t\t\t\t\treturn new \\WP_Error(\n\t\t\t\t\t\t\t'rest_invalid_field',\n\t\t\t\t\t\t\t__( 'A font with this name already exists', 'web-stories' ),\n\t\t\t\t\t\t\t[ 'status' => 400 ]\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$prepared_post->post_content = wp_json_encode( $font_data );\n\n\t\treturn $prepared_post;\n\t}\n\n\t/**\n\t * Determines whether a font with the same name already exists.\n\t *\n\t * Performs a case-insensitive comparison.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param string $font_family Font family.\n\t * @return bool Whether a font with this exact name already exists.\n\t */\n\tprivate function font_exists( string $font_family ): bool {\n\t\t/**\n\t\t * A custom request to perform the lookup.\n\t\t *\n\t\t * @phpstan-var WP_REST_Request<array{search?: string, service?: string, include?: array<string>}> $request\n\t\t */\n\t\t$request = new WP_REST_Request(\n\t\t\tWP_REST_Server::READABLE,\n\t\t\t$this->namespace .\n\t\t\t'/' . $this->rest_base\n\t\t);\n\t\t$request->set_param( 'include', [ $font_family ] );\n\t\t$request->set_param( 'service', 'all' );\n\n\t\t/**\n\t\t * Response object.\n\t\t *\n\t\t * @var WP_REST_Response $response\n\t\t */\n\t\t$response = $this->get_items( $request );\n\n\t\treturn ! empty( $response->get_data() );\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Hotlinking_Controller.php",
    "content": "<?php\n/**\n * Class Hotlinking_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_Http;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Hotlinking_Controller class.\n *\n * API endpoint for pinging and hotlinking media URLs.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type LinkData array{\n *   ext?: string,\n *   file_name?: string,\n *   file_size?: int,\n *   mime_type?: string,\n *   type?: string\n * }\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n *   enum?: string[]\n * }\n *\n * @phpstan-type Schema array{\n *   properties: array{\n *     ext?: SchemaEntry,\n *     file_name?: SchemaEntry,\n *     file_size?: SchemaEntry,\n *     mime_type?: SchemaEntry,\n *     type?: SchemaEntry\n *   }\n * }\n * @phpstan-type HttpArgs array{\n *   method?: string,\n *   timeout?: float,\n *   redirection?: int,\n *   httpversion?: string,\n *   user-agent?: string,\n *   reject_unsafe_urls?: bool,\n *   blocking?: bool,\n *   headers?: string|array<string, string|null>,\n *   cookies?: array<string, string>,\n *   body?: string|string[],\n *   compress?: bool,\n *   decompress?: bool,\n *   sslverify?: bool,\n *   sslcertificates?: string,\n *   stream?: bool,\n *   filename?: string,\n *   limit_response_size?: int\n * }\n */\nclass Hotlinking_Controller extends REST_Controller implements HasRequirements {\n\tpublic const PROXY_HEADERS_ALLOWLIST = [\n\t\t'Content-Type',\n\t\t'Cache-Control',\n\t\t'Etag',\n\t\t'Last-Modified',\n\t\t'Content-Range',\n\t];\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Types instance.\n\t *\n\t * @var Types Types instance.\n\t */\n\tprivate Types $types;\n\n\t/**\n\t * File pointer resource.\n\t *\n\t * @var resource\n\t */\n\tprotected $stream_handle;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t * @param Types           $types Types instance.\n\t * @return void\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type, Types $types ) {\n\t\t$this->story_post_type = $story_post_type;\n\t\t$this->types           = $types;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'hotlink';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for urls.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base . '/validate',\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'parse_url' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'parse_url_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'url' => [\n\t\t\t\t\t\t\t'description'       => __( 'The URL to process.', 'web-stories' ),\n\t\t\t\t\t\t\t'required'          => true,\n\t\t\t\t\t\t\t'type'              => 'string',\n\t\t\t\t\t\t\t'format'            => 'uri',\n\t\t\t\t\t\t\t'validate_callback' => [ $this, 'validate_callback' ],\n\t\t\t\t\t\t\t'sanitize_callback' => 'esc_url_raw',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base . '/proxy',\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'proxy_url' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'parse_url_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'url' => [\n\t\t\t\t\t\t\t'description'       => __( 'The URL to process.', 'web-stories' ),\n\t\t\t\t\t\t\t'required'          => true,\n\t\t\t\t\t\t\t'type'              => 'string',\n\t\t\t\t\t\t\t'format'            => 'uri',\n\t\t\t\t\t\t\t'validate_callback' => [ $this, 'validate_callback' ],\n\t\t\t\t\t\t\t'sanitize_callback' => 'esc_url_raw',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Parses a URL to return some metadata for inserting external media.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_REST_Request $request Full data about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function parse_url( WP_REST_Request $request ) {\n\t\t/**\n\t\t * Requested URL.\n\t\t *\n\t\t * @var string $raw_url\n\t\t */\n\t\t$raw_url = $request['url'];\n\t\t$raw_url = untrailingslashit( $raw_url );\n\n\t\t$url_or_ip = $this->validate_url( $raw_url );\n\n\t\t$host = wp_parse_url( $raw_url, PHP_URL_HOST );\n\n\t\tif ( ! $url_or_ip || ! $host ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t/**\n\t\t * Filters the hotlinking data TTL value.\n\t\t *\n\t\t * @since 1.11.0\n\t\t *\n\t\t * @param int    $time Time to live (in seconds). Default is 1 day.\n\t\t * @param string $url  The attempted URL.\n\t\t */\n\t\t$cache_ttl = apply_filters( 'web_stories_hotlinking_url_data_cache_ttl', DAY_IN_SECONDS, $raw_url );\n\t\t$cache_key = 'web_stories_url_data_' . md5( $raw_url );\n\n\t\t$data = get_transient( $cache_key );\n\t\tif ( \\is_string( $data ) && ! empty( $data ) ) {\n\t\t\t/**\n\t\t\t * Decoded cached link data.\n\t\t\t *\n\t\t\t * @var array|null $link\n\t\t\t * @phpstan-var LinkData|null $link\n\t\t\t */\n\t\t\t$link = json_decode( $data, true );\n\n\t\t\tif ( $link ) {\n\t\t\t\t$response = $this->prepare_item_for_response( $link, $request );\n\t\t\t\treturn rest_ensure_response( $response );\n\t\t\t}\n\t\t}\n\n\t\t$callback = $this->get_curl_resolve_callback( $raw_url, $url_or_ip );\n\t\tadd_action( 'http_api_curl', $callback );\n\n\t\t$response = wp_safe_remote_head(\n\t\t\t$raw_url,\n\t\t\t[\n\t\t\t\t'redirection' => 0, // No redirects allowed.\n\t\t\t\t'headers'     => [\n\t\t\t\t\t'Host' => $host,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tremove_action( 'http_api_curl', $callback );\n\n\t\tif ( is_wp_error( $response ) && 'http_request_failed' === $response->get_error_code() ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\tif ( WP_Http::OK !== wp_remote_retrieve_response_code( $response ) ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$headers   = wp_remote_retrieve_headers( $response );\n\t\t$mime_type = $headers['content-type'];\n\t\tif ( $mime_type && str_contains( $mime_type, ';' ) ) {\n\t\t\t$pieces    = explode( ';', $mime_type );\n\t\t\t$mime_type = array_shift( $pieces );\n\t\t}\n\t\t$file_size = (int) $headers['content-length'];\n\n\t\t$path = wp_parse_url( $raw_url, PHP_URL_PATH );\n\n\t\tif ( ! \\is_string( $path ) ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$file_name = basename( $path );\n\n\t\t$exts = $this->types->get_file_type_exts( [ $mime_type ] );\n\t\t$ext  = '';\n\t\tif ( $exts ) {\n\t\t\t$ext = end( $exts );\n\t\t}\n\n\t\t$allowed_mime_types = $this->get_allowed_mime_types();\n\t\t$type               = '';\n\t\tforeach ( $allowed_mime_types as $key => $mime_types ) {\n\t\t\tif ( \\in_array( $mime_type, $mime_types, true ) ) {\n\t\t\t\t$type = $key;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t$data = [\n\t\t\t'ext'       => $ext,\n\t\t\t'file_name' => $file_name,\n\t\t\t'file_size' => $file_size,\n\t\t\t'mime_type' => $mime_type,\n\t\t\t'type'      => $type,\n\t\t];\n\n\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\n\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\treturn rest_ensure_response( $response );\n\t}\n\n\t/**\n\t * Parses a URL to return proxied file.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ErrorControlOperator\")\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param WP_REST_Request $request Full data about the request.\n\t * @return WP_Error|void Proxied data on success, error otherwise.\n\t */\n\tpublic function proxy_url( WP_REST_Request $request ) {\n\t\t/**\n\t\t * Requested URL.\n\t\t *\n\t\t * @var string $raw_url\n\t\t */\n\t\t$raw_url = $request['url'];\n\t\t$raw_url = untrailingslashit( $raw_url );\n\n\t\t$url_or_ip = $this->validate_url( $raw_url );\n\n\t\t$host = wp_parse_url( $raw_url, PHP_URL_HOST );\n\n\t\tif ( ! $url_or_ip || ! $host ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t// Remove any relevant headers already set by WP_REST_Server::serve_request() // wp_get_nocache_headers().\n\t\tif ( ! headers_sent() ) {\n\t\t\theader_remove( 'Cache-Control' );\n\t\t\theader_remove( 'Content-Type' );\n\t\t\theader_remove( 'Expires' );\n\t\t\theader_remove( 'Last Modified' );\n\t\t}\n\n\t\theader( 'Cache-Control: max-age=3600' );\n\t\theader( 'Accept-Ranges: bytes' );\n\n\t\t$args = [\n\t\t\t'timeout'     => 60, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout\n\t\t\t'blocking'    => false,\n\t\t\t'headers'     => [\n\t\t\t\t'Range' => $request->get_header( 'Range' ),\n\t\t\t\t'Host'  => $host,\n\t\t\t],\n\t\t\t'redirection' => 0, // No redirects allowed.\n\t\t];\n\n\t\t$callback = $this->get_curl_resolve_callback( $raw_url, $url_or_ip );\n\t\tadd_action( 'http_api_curl', $callback );\n\n\t\t$http      = _wp_http_get_object();\n\t\t$transport = $http->_get_first_available_transport( $args, $raw_url );\n\n\t\t// When cURL is available, we might be able to use it together with fopen().\n\t\tif ( 'WP_Http_Curl' === $transport ) {\n\t\t\t// php://temp is a read-write streams that allows temporary data to be stored in a file-like wrapper.\n\t\t\t// Other than php://memory, php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB).\n\t\t\t// The location of this temporary file is determined in the same way as the {@see sys_get_temp_dir()} function.\n\t\t\tif ( WP_DEBUG ) {\n\t\t\t\t$stream_handle = fopen( 'php://memory', 'wb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen\n\t\t\t} else {\n\t\t\t\t$stream_handle = @fopen( 'php://memory', 'wb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.PHP.NoSilencedErrors.Discouraged, Generic.PHP.NoSilencedErrors.Forbidden\n\t\t\t}\n\n\t\t\tif ( $stream_handle ) {\n\t\t\t\t$this->stream_handle = $stream_handle;\n\t\t\t\t$this->proxy_url_curl( $raw_url, $args );\n\t\t\t\texit;\n\t\t\t}\n\t\t}\n\n\t\t// If either cURL is not available or fopen() did not succeed,\n\t\t// fall back to using whatever else is set up on the site,\n\t\t// presumably WP_Http_Streams or still WP_Http_Curl but without streams.\n\t\tunset( $args['blocking'] );\n\t\t$this->proxy_url_fallback( $raw_url, $args );\n\n\t\texit;\n\t}\n\n\t/**\n\t * Prepares response asset response.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param LinkData|false  $link    URL data value, default to false is not set.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response|WP_Error Response object.\n\t *\n\t * @phpstan-param LinkData                                $link\n\t * @phpstan-param WP_REST_Request<array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $link, $request ) {\n\t\t$fields = $this->get_fields_for_response( $request );\n\t\t$schema = $this->get_item_schema();\n\n\t\t$data = [];\n\n\t\t$error = new WP_Error();\n\t\tforeach ( $schema['properties'] as $field => $args ) {\n\t\t\tif ( ! isset( $link[ $field ] ) || ! rest_is_field_included( $field, $fields ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$check = rest_validate_value_from_schema( $link[ $field ], $args, $field );\n\t\t\tif ( is_wp_error( $check ) ) {\n\t\t\t\t$error->add( 'rest_invalid_' . $field, $check->get_error_message(), [ 'status' => 400 ] );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$data[ $field ] = rest_sanitize_value_from_schema( $link[ $field ], $args, $field );\n\t\t}\n\n\t\tif ( $error->get_error_codes() ) {\n\t\t\treturn $error;\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\treturn rest_ensure_response( $data );\n\t}\n\n\t/**\n\t * Retrieves the link's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$allowed_mime_types = $this->get_allowed_mime_types();\n\t\t$types              = array_keys( $allowed_mime_types );\n\t\t$allowed_mime_types = array_merge( ...array_values( $allowed_mime_types ) );\n\t\t$exts               = $this->types->get_file_type_exts( $allowed_mime_types );\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'link',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'ext'       => [\n\t\t\t\t\t'description' => __( 'File extension', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'enum'        => $exts,\n\t\t\t\t],\n\t\t\t\t'file_name' => [\n\t\t\t\t\t'description' => __( 'File name', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'file_size' => [\n\t\t\t\t\t'description' => __( 'File size', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'mime_type' => [\n\t\t\t\t\t'description' => __( 'Mime type', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'enum'        => $allowed_mime_types,\n\t\t\t\t],\n\t\t\t\t'type'      => [\n\t\t\t\t\t'description' => __( 'Type', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'enum'        => $types,\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Checks if current user can process urls.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function parse_url_permissions_check() {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new WP_Error(\n\t\t\t\t'rest_forbidden',\n\t\t\t\t__( 'Sorry, you are not allowed to insert external media.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Callback to validate urls.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param string $value Value to be validated.\n\t * @return true|WP_Error\n\t */\n\tpublic function validate_callback( $value ) {\n\t\t$url = untrailingslashit( $value );\n\n\t\tif ( empty( $url ) || ! $this->validate_url( $url ) ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t$path = wp_parse_url( $url, PHP_URL_PATH );\n\n\t\tif ( ! $path ) {\n\t\t\treturn new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns a callback to modify the cURL configuration before the request is executed.\n\t *\n\t * @since 1.22.1\n\t *\n\t * @param string $url       URL.\n\t * @param string $url_or_ip URL or IP address.\n\t */\n\tpublic function get_curl_resolve_callback( string $url, string $url_or_ip ): callable {\n\t\t/**\n\t\t * CURL configuration callback.\n\t\t *\n\t\t * @param resource $handle The cURL handle returned by curl_init() (passed by reference).\n\t\t */\n\t\treturn static function ( $handle ) use ( $url, $url_or_ip ): void {\n\t\t\t// Just some safeguard in case cURL is not really available,\n\t\t\t// despite this method being run in the context of WP_Http_Curl.\n\t\t\tif ( ! \\function_exists( '\\curl_setopt' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( $url === $url_or_ip ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$host   = wp_parse_url( $url, PHP_URL_HOST );\n\t\t\t$scheme = wp_parse_url( $url, PHP_URL_SCHEME ) ?? 'http';\n\t\t\t$port   = wp_parse_url( $url, PHP_URL_PORT ) ?? 'http' === $scheme ? 80 : 443;\n\n            // phpcs:disable WordPress.WP.AlternativeFunctions.curl_curl_setopt\n\n\t\t\tcurl_setopt(\n\t\t\t\t$handle,\n\t\t\t\tCURLOPT_RESOLVE,\n\t\t\t\t[\n\t\t\t\t\t\"$host:$port:$url_or_ip\",\n\t\t\t\t]\n\t\t\t);\n\n            // phpcs:enable WordPress.WP.AlternativeFunctions.curl_curl_setopt\n\t\t};\n\t}\n\n\t/**\n\t * Modifies the cURL configuration before the request is executed.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param resource $handle The cURL handle returned by {@see curl_init()} (passed by reference).\n\t */\n\tpublic function modify_curl_configuration( $handle ): void {\n\t\t// Just some safeguard in case cURL is not really available,\n\t\t// despite this method being run in the context of WP_Http_Curl.\n\t\tif ( ! \\function_exists( '\\curl_setopt' ) ) {\n\t\t\treturn;\n\t\t}\n\n        // phpcs:disable WordPress.WP.AlternativeFunctions.curl_curl_setopt\n\n\t\tcurl_setopt(\n\t\t\t$handle,\n\t\t\tCURLOPT_FILE,\n\t\t\t$this->stream_handle\n\t\t);\n\n\t\tcurl_setopt( $handle, CURLOPT_HEADERFUNCTION, [ $this, 'stream_headers' ] );\n\n        // phpcs:enable WordPress.WP.AlternativeFunctions.curl_curl_setopt\n\t}\n\n\t/**\n\t * Grabs the headers of the cURL request.\n\t *\n\t * Each header is sent individually to this callback,\n\t * so we take a look at each one to see if we should \"forward\" it.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param resource $handle  cURL handle.\n\t * @param string   $header cURL header.\n\t * @return int Header length.\n\t */\n\tpublic function stream_headers( $handle, $header ): int {\n\t\t// Parse Status-Line, the first component in the HTTP response, e.g. HTTP/1.1 200 OK.\n\t\t// Extract the status code to re-send that here.\n\t\tif ( str_starts_with( $header, 'HTTP/' ) ) {\n\t\t\t$status = explode( ' ', $header );\n\t\t\thttp_response_code( (int) $status[1] );\n\t\t\treturn \\strlen( $header );\n\t\t}\n\n\t\tforeach ( self::PROXY_HEADERS_ALLOWLIST as $_header ) {\n\t\t\tif ( str_starts_with( strtolower( $header ), strtolower( $_header ) . ': ' ) ) {\n\t\t\t\theader( $header, true );\n\t\t\t}\n\t\t}\n\n\t\treturn \\strlen( $header );\n\t}\n\n\t/**\n\t * Proxy a given URL via a PHP read-write stream.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param string $url  Request URL.\n\t * @param array  $args Request args.\n\t *\n\t * @phpstan-param HttpArgs $args\n\t */\n\tprivate function proxy_url_curl( string $url, array $args ): void {\n\t\tadd_action( 'http_api_curl', [ $this, 'modify_curl_configuration' ] );\n\t\twp_safe_remote_get( $url, $args );\n\t\tremove_action( 'http_api_curl', [ $this, 'modify_curl_configuration' ] );\n\n\t\trewind( $this->stream_handle );\n\t\twhile ( ! feof( $this->stream_handle ) ) {\n\t\t\techo fread( $this->stream_handle, 1024 * 1024 ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped, WordPress.WP.AlternativeFunctions.file_system_operations_fread\n\t\t}\n\n\t\tfclose( $this->stream_handle );\n\t}\n\n\t/**\n\t * Proxy a given URL by storing in memory.\n\t *\n\t * @since 1.15.0\n\t *\n\t * @param string $url  Request URL.\n\t * @param array  $args Request args.\n\t *\n\t * @phpstan-param HttpArgs $args\n\t */\n\tprivate function proxy_url_fallback( string $url, array $args ): void {\n\t\t$response = wp_safe_remote_get( $url, $args );\n\t\t$status   = wp_remote_retrieve_response_code( $response );\n\n\t\tif ( ! $status ) {\n\t\t\thttp_response_code( 404 );\n\t\t\treturn;\n\t\t}\n\n\t\thttp_response_code( (int) $status );\n\n\t\t$headers = wp_remote_retrieve_headers( $response );\n\n\t\tforeach ( self::PROXY_HEADERS_ALLOWLIST as $_header ) {\n\t\t\tif ( isset( $headers[ $_header ] ) ) {\n\t\t\t\theader( $_header . ': ' . $headers[ $_header ] );\n\t\t\t}\n\t\t}\n\n\t\techo wp_remote_retrieve_body( $response ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t}\n\n\t/**\n\t * Validate a URL for safe use in the HTTP API.\n\t *\n\t * Like {@see wp_http_validate_url} in core, but with extra hardening\n\t * to avoid DNS rebinding issues.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param string $url Request URL.\n\t * @return string|false Original URL, resolved IP address, or false on failure.\n\t */\n\tprivate function validate_url( string $url ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\tif ( '' === $url || is_numeric( $url ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$original_url = $url;\n\t\t$url          = wp_kses_bad_protocol( $url, [ 'http', 'https' ] );\n\t\tif ( ! $url || strtolower( $url ) !== strtolower( $original_url ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$parsed_url = wp_parse_url( $url );\n\t\tif ( ! $parsed_url || ! isset( $parsed_url['host'], $parsed_url['scheme'] ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( false !== strpbrk( $parsed_url['host'], ':#?[]' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t/**\n\t\t * Home URL.\n\t\t *\n\t\t * @var string\n\t\t */\n\t\t$home_url = get_option( 'home' );\n\n\t\t$parsed_home = wp_parse_url( $home_url );\n\n\t\tif ( ! $parsed_home ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$same_host = isset( $parsed_home['host'] ) && strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );\n\t\t$host      = trim( $parsed_url['host'], '.' );\n\n\t\t$validated_url = $url;\n\n\t\tif ( ! $same_host ) {\n\t\t\tif ( preg_match( '#^(([1-9]?\\d|1\\d\\d|25[0-5]|2[0-4]\\d)\\.){3}([1-9]?\\d|1\\d\\d|25[0-5]|2[0-4]\\d)$#', $host ) ) {\n\t\t\t\t$ip = $host;\n\t\t\t} else {\n\t\t\t\t$ip = gethostbyname( $host );\n\t\t\t\tif ( $ip === $host ) { // Error condition for gethostbyname().\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$parts = array_map( 'intval', explode( '.', $ip ) );\n\t\t\tif (\n\t\t\t\t0 === $parts[0] // 0.0.0.0/8.\n\t\t\t\t||\n\t\t\t\t127 === $parts[0] // 127.0.0.0/8.\n\t\t\t\t||\n\t\t\t\t10 === $parts[0] // 10.0.0.0/8.\n\t\t\t\t||\n\t\t\t\t( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] ) // 172.16.0.0/12.\n\t\t\t\t||\n\t\t\t\t( 192 === $parts[0] && 168 === $parts[1] ) // 192.168.0.0/16.\n\t\t\t\t||\n\t\t\t\t( 169 === $parts[0] && 254 === $parts[1] ) // 169.254.0.0/16.\n\t\t\t\t||\n\t\t\t\t// phpcs:ignore Squiz.PHP.CommentedOutCode.Found\n\t\t\t\t( 100 === $parts[0] && 64 <= $parts[1] && 127 >= $parts[1] ) // Private: 100.64.0.0/10.\n\t\t\t) {\n\t\t\t\t// If host appears local, reject.\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Use resolved IP address to avoid DNS rebinding issues.\n\t\t\t$validated_url = $ip;\n\t\t}\n\n\t\t/** This filter is documented in wp-includes/http.php */\n\t\t$allowed_ports = apply_filters( 'http_allowed_safe_ports', [ 80, 443, 8080 ], $host, $url );\n\t\tif (\n\t\t\t! isset( $parsed_url['port'] ) ||\n\t\t\t( \\is_array( $allowed_ports ) && \\in_array( $parsed_url['port'], $allowed_ports, true ) )\n\t\t) {\n\t\t\treturn $validated_url;\n\t\t}\n\n\t\tif ( $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $parsed_url['port'] ) {\n\t\t\treturn $validated_url;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Returns a list of allowed mime types per media type (image, audio, video).\n\t *\n\t * @since 1.19.0\n\t *\n\t * @return array<string, string[]> List of allowed mime types.\n\t */\n\tprotected function get_allowed_mime_types(): array {\n\t\t$mime_type = $this->types->get_allowed_mime_types();\n\n\t\t// Do not support hotlinking SVGs for security reasons.\n\t\tunset( $mime_type['vector'] );\n\n\t\treturn $mime_type;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Link_Controller.php",
    "content": "<?php\n/**\n * Class Link_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse DOMElement;\nuse DOMNode;\nuse DOMNodeList;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse WP_Error;\nuse WP_Http;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * API endpoint to allow parsing of metadata from a URL\n *\n * Class Link_Controller\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n * @phpstan-type Schema array{\n *   properties: array<string, SchemaEntry>\n * }\n */\nclass Link_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'link';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for links.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'parse_link' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'parse_link_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'url' => [\n\t\t\t\t\t\t\t'description'       => __( 'The URL to process.', 'web-stories' ),\n\t\t\t\t\t\t\t'required'          => true,\n\t\t\t\t\t\t\t'type'              => 'string',\n\t\t\t\t\t\t\t'format'            => 'uri',\n\t\t\t\t\t\t\t'validate_callback' => [ $this, 'validate_url' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Parses a URL to return some metadata for inserting links.\n\t *\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Full data about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function parse_link( $request ) {\n\t\t/**\n\t\t * Requested URL.\n\t\t *\n\t\t * @var string $url\n\t\t */\n\t\t$url = $request['url'];\n\t\t$url = untrailingslashit( $url );\n\n\t\t/**\n\t\t * Filters the link data TTL value.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param int $time Time to live (in seconds). Default is 1 day.\n\t\t * @param string $url The attempted URL.\n\t\t */\n\t\t$cache_ttl = apply_filters( 'web_stories_link_data_cache_ttl', DAY_IN_SECONDS, $url );\n\t\t$cache_key = 'web_stories_link_data_' . md5( $url );\n\n\t\t$data = get_transient( $cache_key );\n\t\tif ( \\is_string( $data ) && ! empty( $data ) ) {\n\t\t\t/**\n\t\t\t * Decoded cached link data.\n\t\t\t *\n\t\t\t * @var array{title: string, image: string, description: string}|null $link\n\t\t\t */\n\t\t\t$link = json_decode( $data, true );\n\n\t\t\tif ( $link ) {\n\t\t\t\t$response = $this->prepare_item_for_response( $link, $request );\n\t\t\t\treturn rest_ensure_response( $response );\n\t\t\t}\n\t\t}\n\n\t\t$data = [\n\t\t\t'title'       => '',\n\t\t\t'image'       => '',\n\t\t\t'description' => '',\n\t\t];\n\n\t\t// Do not request instagram.com, as it redirects to a login page.\n\t\t// See https://github.com/GoogleForCreators/web-stories-wp/issues/10451.\n\t\t$matches      = [];\n\t\t$query_string = wp_parse_url( $url, PHP_URL_QUERY );\n\t\t$check_url    = \\is_string( $query_string ) ? str_replace( \"?$query_string\", '', $url ) : $url;\n\t\tif ( preg_match( '~^https?://(www\\.)?instagram\\.com/([^/]+)/?$~', $check_url, $matches ) ) {\n\t\t\t$data['title'] = \\sprintf(\n\t\t\t\t/* translators: %s: Instagram username. */\n\t\t\t\t__( 'Instagram - @%s', 'web-stories' ),\n\t\t\t\t$matches[2]\n\t\t\t);\n\t\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\t$args = [\n\t\t\t'limit_response_size' => 153_600, // 150 KB.\n\t\t\t'timeout'             => 7, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout\n\t\t];\n\n\t\t/**\n\t\t * Filters the HTTP request args for link data retrieval.\n\t\t *\n\t\t * Can be used to adjust timeout and response size limit.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array $args Arguments used for the HTTP request\n\t\t * @param string $url The attempted URL.\n\t\t */\n\t\t$args = apply_filters( 'web_stories_link_data_request_args', $args, $url );\n\n\t\t$response = wp_safe_remote_get( $url, $args );\n\n\t\tif ( is_wp_error( $response ) && 'http_request_failed' === $response->get_error_code() ) {\n\t\t\treturn new \\WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\tif ( WP_Http::OK !== wp_remote_retrieve_response_code( $response ) ) {\n\t\t\t// Not saving to cache since the error might be temporary.\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\t$html = wp_remote_retrieve_body( $response );\n\n\t\t// Strip <body>.\n\t\t$html_head_end = stripos( $html, '</head>' );\n\t\tif ( $html_head_end ) {\n\t\t\t$html = substr( $html, 0, $html_head_end );\n\t\t}\n\n\t\tif ( ! $html ) {\n\t\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\ttry {\n\t\t\t$doc = Document::fromHtml( $html );\n\t\t} catch ( \\DOMException $exception ) {\n\t\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\tif ( ! $doc ) {\n\t\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\t\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\t$xpath = $doc->xpath;\n\n\t\t// Link title.\n\n\t\t$title       = '';\n\t\t$title_query = $xpath->query( '//title' );\n\n\t\tif ( $title_query instanceof DOMNodeList && $title_query->length > 0 ) {\n\t\t\t$title_node = $title_query->item( 0 );\n\n\t\t\tif ( $title_node instanceof DOMElement ) {\n\t\t\t\t$title = $title_node->textContent;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $title ) {\n\t\t\t/**\n\t\t\t * List of found elements.\n\t\t\t *\n\t\t\t * @var DOMNodeList<DOMElement> $og_title_query\n\t\t\t */\n\t\t\t$og_title_query = $xpath->query( '//meta[@property=\"og:title\"]' );\n\t\t\t$title          = $this->get_dom_attribute_content( $og_title_query, 'content' );\n\t\t}\n\n\t\tif ( ! $title ) {\n\t\t\t/**\n\t\t\t * List of found elements.\n\t\t\t *\n\t\t\t * @var DOMNodeList<DOMElement> $og_site_name_query\n\t\t\t */\n\t\t\t$og_site_name_query = $xpath->query( '//meta[@property=\"og:site_name\"]' );\n\t\t\t$title              = $this->get_dom_attribute_content( $og_site_name_query, 'content' );\n\t\t}\n\n\t\t// Site icon.\n\n\t\t/**\n\t\t * List of found elements.\n\t\t *\n\t\t * @var DOMNodeList<DOMElement> $og_image_query\n\t\t */\n\t\t$og_image_query = $xpath->query( '//meta[@property=\"og:image\"]' );\n\t\t$image          = $this->get_dom_attribute_content( $og_image_query, 'content' );\n\n\t\tif ( ! $image ) {\n\t\t\t/**\n\t\t\t * List of found elements.\n\t\t\t *\n\t\t\t * @var DOMNodeList<DOMElement> $icon_query\n\t\t\t */\n\t\t\t$icon_query = $xpath->query( '//link[contains(@rel, \"icon\")]' );\n\t\t\t$image      = $this->get_dom_attribute_content( $icon_query, 'content' );\n\t\t}\n\n\t\tif ( ! $image ) {\n\t\t\t/**\n\t\t\t * List of found elements.\n\t\t\t *\n\t\t\t * @var DOMNodeList<DOMElement> $touch_icon_query\n\t\t\t */\n\t\t\t$touch_icon_query = $xpath->query( '//link[contains(@rel, \"apple-touch-icon\")]' );\n\t\t\t$image            = $this->get_dom_attribute_content( $touch_icon_query, 'href' );\n\t\t}\n\n\t\t// Link description.\n\n\t\t/**\n\t\t * List of found elements.\n\t\t *\n\t\t * @var DOMNodeList<DOMElement> $description_query\n\t\t */\n\t\t$description_query = $xpath->query( '//meta[@name=\"description\"]' );\n\t\t$description       = $this->get_dom_attribute_content( $description_query, 'content' );\n\n\t\tif ( ! $description ) {\n\t\t\t/**\n\t\t\t * List of found elements.\n\t\t\t *\n\t\t\t * @var DOMNodeList<DOMElement> $og_description_query\n\t\t\t */\n\t\t\t$og_description_query = $xpath->query( '//meta[@property=\"og:description\"]' );\n\t\t\t$description          = $this->get_dom_attribute_content( $og_description_query, 'content' );\n\t\t}\n\n\t\t$data = [\n\t\t\t'title'       => $title ?: '',\n\t\t\t'image'       => $image ?: '',\n\t\t\t'description' => $description ?: '',\n\t\t];\n\n\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\tset_transient( $cache_key, wp_json_encode( $data ), $cache_ttl );\n\n\t\treturn rest_ensure_response( $response );\n\t}\n\n\n\t/**\n\t * Prepares a single lock output for response.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array           $link    Link value, default to false is not set.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response|WP_Error Response object.\n\t *\n\t * @phpstan-param array{title: string, image: string, description: string} $link\n\t * @phpstan-param WP_REST_Request<array{context: string}>                  $request\n\t */\n\tpublic function prepare_item_for_response( $link, $request ) {\n\t\t$fields = $this->get_fields_for_response( $request );\n\t\t$schema = $this->get_item_schema();\n\n\t\t$data = [];\n\n\t\t$check_fields = array_keys( $link );\n\t\tforeach ( $check_fields as $check_field ) {\n\t\t\tif ( ! empty( $schema['properties'][ $check_field ] ) && rest_is_field_included( $check_field, $fields ) ) {\n\t\t\t\t$data[ $check_field ] = rest_sanitize_value_from_schema( $link[ $check_field ], $schema['properties'][ $check_field ] );\n\t\t\t}\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\t// Wrap the data in a response object.\n\t\treturn rest_ensure_response( $data );\n\t}\n\n\t/**\n\t * Retrieves the link's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'link',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'title'       => [\n\t\t\t\t\t'description' => __( 'Link\\'s title', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'image'       => [\n\t\t\t\t\t'description' => __( 'Link\\'s image', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'description' => [\n\t\t\t\t\t'description' => __( 'Link\\'s description', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Checks if current user can process links.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function parse_link_permissions_check() {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new \\WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to process links.', 'web-stories' ), [ 'status' => rest_authorization_required_code() ] );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Callback to validate urls.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param string $value Value to be validated.\n\t * @return true|WP_Error\n\t */\n\tpublic function validate_url( $value ) {\n\t\t$url = untrailingslashit( $value );\n\n\t\tif ( empty( $url ) || ! wp_http_validate_url( $url ) ) {\n\t\t\treturn new \\WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Retrieve content of a given DOM node attribute.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param DOMNodeList<DOMElement>|false $query XPath query result.\n\t * @param string                        $attribute Attribute name.\n\t * @return string|false Attribute content on success, false otherwise.\n\t */\n\tprotected function get_dom_attribute_content( $query, string $attribute ) {\n\t\tif ( ! $query instanceof DOMNodeList || 0 === $query->length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t/**\n\t\t * DOMElement\n\t\t *\n\t\t * @var DOMElement|DOMNode $node\n\t\t */\n\t\t$node = $query->item( 0 );\n\n\t\tif ( ! $node instanceof DOMElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn $node->getAttribute( $attribute );\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Page_Template_Controller.php",
    "content": "<?php\n/**\n * Class Page_Template_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Response;\n\n/**\n * Page_Template_Controller class.\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n * @phpstan-type Schema array{\n *   properties: array{\n *     permalink_template?: SchemaEntry,\n *     generated_slug?: SchemaEntry\n *   }\n * }\n */\nclass Page_Template_Controller extends Stories_Base_Controller {\n\t/**\n\t * Retrieves a collection of page templates.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function get_items( $request ) {\n\t\t$response = parent::get_items( $request );\n\n\t\tif ( is_wp_error( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\tif ( $request['_web_stories_envelope'] ) {\n\t\t\t/**\n\t\t\t * Embed directive.\n\t\t\t *\n\t\t\t * @var string|string[] $embed\n\t\t\t */\n\t\t\t$embed    = $request['_embed'] ?? false;\n\t\t\t$embed    = $embed ? rest_parse_embed_param( $embed ) : false;\n\t\t\t$response = rest_get_server()->envelope_response( $response, $embed );\n\t\t}\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the query params for the posts collection.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['_web_stories_envelope'] = [\n\t\t\t'description' => __( 'Envelope request for preloading.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t\t'default'     => false,\n\t\t];\n\n\t\treturn $query_params;\n\t}\n\n\t/**\n\t * Retrieves the attachment's schema, conforming to JSON Schema.\n\t *\n\t * Removes some unneeded fields to improve performance by\n\t * avoiding some expensive database queries.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = parent::get_item_schema();\n\n\t\tunset(\n\t\t\t$schema['properties']['permalink_template'],\n\t\t\t$schema['properties']['generated_slug']\n\t\t);\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Checks if a given request has access to read posts.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function get_items_permissions_check( $request ) {\n\t\t$ret = parent::get_items_permissions_check( $request );\n\n\t\tif ( is_wp_error( $ret ) ) {\n\t\t\treturn $ret;\n\t\t}\n\n\t\t$post_type = get_post_type_object( $this->post_type );\n\n\t\tif (\n\t\t\t! $post_type ||\n\t\t\t! current_user_can( $post_type->cap->edit_posts ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden_context',\n\t\t\t\t__( 'Sorry, you are not allowed to edit page templates.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if a given request has access to read a post.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.\n\t */\n\tpublic function get_item_permissions_check( $request ) {\n\t\t$ret = parent::get_item_permissions_check( $request );\n\n\t\tif ( is_wp_error( $ret ) ) {\n\t\t\treturn $ret;\n\t\t}\n\n\t\t$post_type = get_post_type_object( $this->post_type );\n\n\t\tif (\n\t\t\t! $post_type ||\n\t\t\t! current_user_can( $post_type->cap->edit_posts ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden_context',\n\t\t\t\t__( 'Sorry, you are not allowed to edit page templates.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Products_Controller.php",
    "content": "<?php\n/**\n * Class Products_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Shopping\\Product;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Class to access products via the REST API.\n *\n * @since 1.20.0\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n *\n * @phpstan-type Schema array{\n *   properties: array{\n *     productId?: SchemaEntry,\n *     productUrl?: SchemaEntry,\n *     productTitle?: SchemaEntry,\n *     productBrand?: SchemaEntry,\n *     productPrice?: SchemaEntry,\n *     productPriceCurrency?: SchemaEntry,\n *     productImages?: SchemaEntry,\n *     aggregateRating?: SchemaEntry,\n *     productDetails?: SchemaEntry\n *   }\n * }\n */\nclass Products_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\n\t/**\n\t * Shopping_Vendors instance.\n\t *\n\t * @var Shopping_Vendors Shopping_Vendors instance.\n\t */\n\tprivate Shopping_Vendors $shopping_vendors;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Settings         $settings Settings instance.\n\t * @param Story_Post_Type  $story_post_type Story_Post_Type instance.\n\t * @param Shopping_Vendors $shopping_vendors Shopping_Vendors instance.\n\t */\n\tpublic function __construct( Settings $settings, Story_Post_Type $story_post_type, Shopping_Vendors $shopping_vendors ) {\n\t\t$this->settings         = $settings;\n\t\t$this->story_post_type  = $story_post_type;\n\t\t$this->shopping_vendors = $shopping_vendors;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'products';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.20.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings', 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for links.\n\t *\n\t * @since 1.20.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_items' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'get_items_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_collection_params(),\n\t\t\t\t],\n\t\t\t\t'schema' => [ $this, 'get_public_item_schema' ],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Checks if a given request has access to get and create items.\n\t *\n\t * @since 1.20.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function get_items_permissions_check( $request ) {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden',\n\t\t\t\t__( 'Sorry, you are not allowed to manage products.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Retrieves all products.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.20.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string, search?: string, orderby?: string, page?: int, per_page?: int, order?: string, _web_stories_envelope?: bool, _embed?: string|string[]}> $request\n\t */\n\tpublic function get_items( $request ) {\n\t\t/**\n\t\t * Shopping provider.\n\t\t *\n\t\t * @var string $shopping_provider\n\t\t */\n\t\t$shopping_provider = $this->settings->get_setting( Settings::SETTING_NAME_SHOPPING_PROVIDER );\n\t\t$query             = $this->shopping_vendors->get_vendor_class( $shopping_provider );\n\n\t\tif ( 'none' === $shopping_provider ) {\n\t\t\treturn new WP_Error( 'rest_shopping_provider', __( 'No shopping provider set up.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\tif ( ! $query ) {\n\t\t\treturn new WP_Error( 'rest_shopping_provider_not_found', __( 'Unable to find shopping integration.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t$search_term = ! empty( $request['search'] ) ? $request['search'] : '';\n\t\t$orderby     = ! empty( $request['orderby'] ) ? $request['orderby'] : 'date';\n\t\t$page        = ! empty( $request['page'] ) ? $request['page'] : 1;\n\t\t$per_page    = ! empty( $request['per_page'] ) ? $request['per_page'] : 100;\n\t\t$order       = ! empty( $request['order'] ) ? $request['order'] : 'desc';\n\n\t\t$query_result = $query->get_search( $search_term, $page, $per_page, $orderby, $order );\n\t\tif ( is_wp_error( $query_result ) ) {\n\t\t\treturn $query_result;\n\t\t}\n\n\t\t$products = [];\n\t\tforeach ( $query_result['products'] as $product ) {\n\t\t\t$data       = $this->prepare_item_for_response( $product, $request );\n\t\t\t$products[] = $this->prepare_response_for_collection( $data );\n\t\t}\n\n\t\t/**\n\t\t * Response object.\n\t\t *\n\t\t * @var WP_REST_Response $response\n\t\t */\n\t\t$response = rest_ensure_response( $products );\n\n\t\t$response->header( 'X-WP-HasNextPage', $query_result['has_next_page'] ? 'true' : 'false' );\n\n\t\tif ( $request['_web_stories_envelope'] ) {\n\t\t\t$embed    = $request['_embed'] ?? false;\n\t\t\t$embed    = $embed ? rest_parse_embed_param( $embed ) : false;\n\t\t\t$response = rest_get_server()->envelope_response( $response, $embed );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Prepares a single post output for response.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t *\n\t * @since 1.20.0\n\t *\n\t * @param Product         $item    Project object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string, search?: string, orderby?: string, page?: int, per_page?: int, order?: string, _web_stories_envelope?: bool, _embed?: string|string[]}> $request\n\t */\n\tpublic function prepare_item_for_response( $item, $request ): WP_REST_Response { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\t$product = $item;\n\t\t$fields  = $this->get_fields_for_response( $request );\n\n\t\t$data = [];\n\n\t\tif ( rest_is_field_included( 'productId', $fields ) ) {\n\t\t\t$data['productId'] = $product->get_id();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productUrl', $fields ) ) {\n\t\t\t$data['productUrl'] = $product->get_url();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productTitle', $fields ) ) {\n\t\t\t$data['productTitle'] = $product->get_title();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productBrand', $fields ) ) {\n\t\t\t$data['productBrand'] = $product->get_brand();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productPrice', $fields ) ) {\n\t\t\t$data['productPrice'] = $product->get_price();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productPriceCurrency', $fields ) ) {\n\t\t\t$data['productPriceCurrency'] = $product->get_price_currency();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productDetails', $fields ) ) {\n\t\t\t$data['productDetails'] = $product->get_details();\n\t\t}\n\n\t\tif ( rest_is_field_included( 'productImages', $fields ) ) {\n\t\t\t$data['productImages'] = [];\n\n\t\t\tforeach ( $product->get_images() as $image ) {\n\t\t\t\t$image_data = [];\n\t\t\t\tif ( rest_is_field_included( 'productImages.url', $fields ) ) {\n\t\t\t\t\t$image_data['url'] = $image['url'];\n\t\t\t\t}\n\t\t\t\tif ( rest_is_field_included( 'productImages.alt', $fields ) ) {\n\t\t\t\t\t$image_data['alt'] = $image['alt'];\n\t\t\t\t}\n\t\t\t\t$data['productImages'][] = $image_data;\n\t\t\t}\n\t\t}\n\n\t\t$rating = $product->get_aggregate_rating();\n\n\t\tif ( $rating ) {\n\t\t\tif ( rest_is_field_included( 'aggregateRating', $fields ) ) {\n\t\t\t\t$data['aggregateRating'] = [];\n\t\t\t}\n\n\t\t\tif ( rest_is_field_included( 'aggregateRating.ratingValue', $fields ) ) {\n\t\t\t\t$data['aggregateRating']['ratingValue'] = isset( $rating['rating_value'] ) ? (float) $rating['rating_value'] : 0;\n\t\t\t}\n\n\t\t\tif ( rest_is_field_included( 'aggregateRating.reviewCount', $fields ) ) {\n\t\t\t\t$data['aggregateRating']['reviewCount'] = isset( $rating['review_count'] ) ? (int) $rating['review_count'] : 0;\n\t\t\t}\n\n\t\t\tif ( rest_is_field_included( 'aggregateRating.reviewUrl', $fields ) ) {\n\t\t\t\t$data['aggregateRating']['reviewUrl'] = $rating['review_url'] ?? null;\n\t\t\t}\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\t/**\n\t\t * Response object.\n\t\t *\n\t\t * @var WP_REST_Response $response\n\t\t */\n\t\t$response = rest_ensure_response( $data );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the product schema, conforming to JSON Schema.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.20.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t// This must not be an actually existing post type like \"product\".\n\t\t\t// See https://github.com/GoogleForCreators/web-stories-wp/issues/12735.\n\t\t\t'title'      => 'web-story-product',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'productId'            => [\n\t\t\t\t\t'description' => __( 'Product ID.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productUrl'           => [\n\t\t\t\t\t'description' => __( 'Product URL.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productTitle'         => [\n\t\t\t\t\t'description' => __( 'Product title.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productBrand'         => [\n\t\t\t\t\t'description' => __( 'Product brand.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productPrice'         => [\n\t\t\t\t\t'description' => __( 'Product price.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productPriceCurrency' => [\n\t\t\t\t\t'description' => __( 'Product currency.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productImages'        => [\n\t\t\t\t\t'description' => __( 'Product brand.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'array',\n\t\t\t\t\t'items'       => [\n\t\t\t\t\t\t'type'       => 'object',\n\t\t\t\t\t\t'properties' => [\n\t\t\t\t\t\t\t'url' => [\n\t\t\t\t\t\t\t\t'description' => __( 'Product image URL', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'alt' => [\n\t\t\t\t\t\t\t\t'description' => __( 'Product image alt text', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'aggregateRating'      => [\n\t\t\t\t\t'description' => __( 'Product rating.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'object',\n\t\t\t\t\t'properties'  => [\n\t\t\t\t\t\t'ratingValue' => [\n\t\t\t\t\t\t\t'description' => __( 'Average rating.', 'web-stories' ),\n\t\t\t\t\t\t\t'type'        => 'number',\n\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'reviewCount' => [\n\t\t\t\t\t\t\t'description' => __( 'Number of reviews.', 'web-stories' ),\n\t\t\t\t\t\t\t'type'        => 'number',\n\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'reviewUrl'   => [\n\t\t\t\t\t\t\t'description' => __( 'Product review URL.', 'web-stories' ),\n\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'productDetails'       => [\n\t\t\t\t\t'description' => __( 'Product description.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Retrieves the query params for the products collection.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['per_page']['default'] = 100;\n\n\t\t$query_params['orderby'] = [\n\t\t\t'description' => __( 'Sort collection by product attribute.', 'web-stories' ),\n\t\t\t'type'        => 'string',\n\t\t\t'default'     => 'date',\n\t\t\t'enum'        => [\n\t\t\t\t'date',\n\t\t\t\t'price',\n\t\t\t\t'title',\n\t\t\t],\n\t\t];\n\n\t\t$query_params['order'] = [\n\t\t\t'description' => __( 'Order sort attribute ascending or descending.', 'web-stories' ),\n\t\t\t'type'        => 'string',\n\t\t\t'default'     => 'desc',\n\t\t\t'enum'        => [ 'asc', 'desc' ],\n\t\t];\n\n\t\t$query_params['_web_stories_envelope'] = [\n\t\t\t'description' => __( 'Envelope request for preloading.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t\t'default'     => false,\n\t\t];\n\n\t\treturn $query_params;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Publisher_Logos_Controller.php",
    "content": "<?php\n/**\n * Class Publisher_Logos_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_Post;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Class to access publisher logos via the REST API.\n *\n * @since 1.12.0\n *\n * @phpstan-import-type Links from \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller\n */\nclass Publisher_Logos_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Settings        $settings Settings instance.\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Settings $settings, Story_Post_Type $story_post_type ) {\n\t\t$this->settings        = $settings;\n\t\t$this->story_post_type = $story_post_type;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'publisher-logos';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings', 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for links.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_items' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'permissions_check' ],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::CREATABLE,\n\t\t\t\t\t'callback'            => [ $this, 'create_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),\n\t\t\t\t],\n\t\t\t\t'schema' => [ $this, 'get_public_item_schema' ],\n\t\t\t]\n\t\t);\n\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base . '/(?P<id>[\\d]+)',\n\t\t\t[\n\t\t\t\t'args' => [\n\t\t\t\t\t'id' => [\n\t\t\t\t\t\t'description' => __( 'Publisher logo ID.', 'web-stories' ),\n\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::EDITABLE,\n\t\t\t\t\t'callback'            => [ $this, 'update_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'update_item_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::DELETABLE,\n\t\t\t\t\t'callback'            => [ $this, 'delete_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'permissions_check' ],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Checks if a given request has access to get and create items.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function permissions_check() {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden',\n\t\t\t\t__( 'Sorry, you are not allowed to manage publisher logos.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if a given request has access to manage a single item.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.\n\t */\n\tpublic function update_item_permissions_check( $request ) {\n\t\tif ( ! current_user_can( 'manage_options' ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_forbidden',\n\t\t\t\t__( 'Sorry, you are not allowed to manage publisher logos.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Retrieves all active publisher logos.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function get_items( $request ) {\n\t\t/**\n\t\t * Publisher logo IDs.\n\t\t *\n\t\t * @var int[] $publisher_logos_ids\n\t\t */\n\t\t$publisher_logos_ids = $this->settings->get_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, [] );\n\t\t_prime_post_caches( $publisher_logos_ids );\n\t\t$publisher_logos = $this->filter_publisher_logos( $publisher_logos_ids );\n\t\t$results         = [];\n\n\t\tforeach ( $publisher_logos as $logo ) {\n\t\t\t/**\n\t\t\t * We're expecting a post object after the filtering above.\n\t\t\t *\n\t\t\t * @var WP_Post $post\n\t\t\t */\n\t\t\t$post = get_post( $logo );\n\n\t\t\t$data      = $this->prepare_item_for_response( $post, $request );\n\t\t\t$results[] = $this->prepare_response_for_collection( $data );\n\t\t}\n\n\t\t// Ensure the default publisher logo is first in the list.\n\t\t$active = array_column( $results, 'active' );\n\t\tarray_multisort( $active, SORT_DESC, $results );\n\n\t\treturn rest_ensure_response( $results );\n\t}\n\n\t/**\n\t * Adds a new publisher logo to the collection.\n\t *\n\t * Supports adding multiple logos at once.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function create_item( $request ) {\n\t\t/**\n\t\t * List of publisher logos.\n\t\t *\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = $this->settings->get_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, [] );\n\t\t$publisher_logos = $this->filter_publisher_logos( $publisher_logos );\n\n\t\t/**\n\t\t * Publisher logo ID(s).\n\t\t *\n\t\t * Could be a single attachment ID or an array of attachment IDs.\n\t\t *\n\t\t * @var int|int[] $logo_id\n\t\t */\n\t\t$logo_id = $request['id'];\n\n\t\t$posts = (array) $logo_id;\n\n\t\tif ( empty( $posts ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_invalid_id',\n\t\t\t\t__( 'Invalid ID', 'web-stories' ),\n\t\t\t\t[ 'status' => 400 ]\n\t\t\t);\n\t\t}\n\n\t\tforeach ( $posts as $post_id ) {\n\t\t\t$post = get_post( $post_id );\n\n\t\t\tif ( ! $post || 'attachment' !== $post->post_type ) {\n\t\t\t\treturn new \\WP_Error(\n\t\t\t\t\t'rest_invalid_id',\n\t\t\t\t\t__( 'Invalid ID', 'web-stories' ),\n\t\t\t\t\t[ 'status' => 400 ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( \\in_array( $post->ID, $publisher_logos, true ) ) {\n\t\t\t\treturn new \\WP_Error(\n\t\t\t\t\t'rest_publisher_logo_exists',\n\t\t\t\t\t__( 'Publisher logo already exists', 'web-stories' ),\n\t\t\t\t\t[ 'status' => 400 ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t$publisher_logos[] = $post->ID;\n\t\t}\n\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, $publisher_logos );\n\n\t\t$active_publisher_logo_id = absint( $this->settings->get_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO ) );\n\n\t\tif ( 1 === \\count( $publisher_logos ) || ! \\in_array( $active_publisher_logo_id, $publisher_logos, true ) ) {\n\t\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, $posts[0] );\n\t\t}\n\n\t\t$results = [];\n\n\t\tforeach ( $posts as $post ) {\n\t\t\t/**\n\t\t\t * Post object.\n\t\t\t *\n\t\t\t * @var WP_Post $post\n\t\t\t */\n\t\t\t$post = get_post( $post );\n\n\t\t\t$data = $this->prepare_item_for_response( $post, $request );\n\n\t\t\tif ( 1 === \\count( $posts ) ) {\n\t\t\t\treturn $data;\n\t\t\t}\n\n\t\t\t$results[] = $this->prepare_response_for_collection( $data );\n\t\t}\n\n\t\treturn rest_ensure_response( $results );\n\t}\n\n\t/**\n\t * Removes a publisher logo from the collection.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function delete_item( $request ) {\n\t\t/**\n\t\t * Publisher logo ID.\n\t\t *\n\t\t * @var int $logo_id\n\t\t */\n\t\t$logo_id = $request['id'];\n\n\t\t$post = $this->get_publisher_logo( $logo_id );\n\n\t\tif ( is_wp_error( $post ) ) {\n\t\t\treturn $post;\n\t\t}\n\n\t\t$prepared = $this->prepare_item_for_response( $post, $request );\n\n\t\t/**\n\t\t * List of publisher logos.\n\t\t *\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = $this->settings->get_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, [] );\n\t\t$publisher_logos = $this->filter_publisher_logos( $publisher_logos );\n\t\t$publisher_logos = array_values( array_diff( $publisher_logos, [ $post->ID ] ) );\n\n\t\t$active_publisher_logo_id = absint( $this->settings->get_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO ) );\n\n\t\tif ( $post->ID === $active_publisher_logo_id || ! \\in_array( $active_publisher_logo_id, $publisher_logos, true ) ) {\n\t\t\t// Mark the first available publisher logo as the new default.\n\t\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, ! empty( $publisher_logos[0] ) ? $publisher_logos[0] : 0 );\n\t\t}\n\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, $publisher_logos );\n\n\t\treturn new WP_REST_Response(\n\t\t\t[\n\t\t\t\t'deleted'  => true,\n\t\t\t\t'previous' => $prepared->get_data(),\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Updates a publisher logo in the collection.\n\t *\n\t * Can only be used to make it the \"active\" one.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function update_item( $request ) {\n\t\t/**\n\t\t * Publisher logo ID.\n\t\t *\n\t\t * @var int $logo_id\n\t\t */\n\t\t$logo_id = $request['id'];\n\n\t\t$post = $this->get_publisher_logo( $logo_id );\n\n\t\tif ( is_wp_error( $post ) ) {\n\t\t\treturn $post;\n\t\t}\n\n\t\tif ( $request['active'] ) {\n\t\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, $post->ID );\n\t\t}\n\n\t\treturn $this->prepare_item_for_response( $post, $request );\n\t}\n\n\t/**\n\t * Prepares a single publisher logo output for response.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_Post         $post    Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t */\n\tpublic function prepare_item_for_response( $post, $request ): WP_REST_Response {\n\t\t$fields = $this->get_fields_for_response( $request );\n\n\t\t// Base fields for every post.\n\t\t$data = [];\n\n\t\tif ( rest_is_field_included( 'id', $fields ) ) {\n\t\t\t$data['id'] = $post->ID;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'title', $fields ) ) {\n\t\t\t$data['title'] = get_the_title( $post->ID );\n\t\t}\n\n\t\tif ( rest_is_field_included( 'active', $fields ) ) {\n\t\t\t$active_publisher_logo_id = absint( $this->settings->get_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO ) );\n\t\t\t$data['active']           = $post->ID === $active_publisher_logo_id;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'url', $fields ) ) {\n\t\t\t$data['url'] = wp_get_attachment_url( $post->ID );\n\t\t}\n\n\t\t/**\n\t\t * Wrapped response object.\n\t\t *\n\t\t * @var WP_REST_Response $response Response object.\n\t\t */\n\t\t$response = rest_ensure_response( $data );\n\n\t\tif ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {\n\t\t\t$response->add_links( $this->prepare_links( $post ) );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the publisher logo's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string, array<string, array<string, array<int, string>|bool|string>>|string> Item schema data.\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t\t}\n\n\t\treturn [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'publisher-logo',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'id'     => [\n\t\t\t\t\t'description' => __( 'Publisher logo ID.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'title'  => [\n\t\t\t\t\t'description' => __( 'Publisher logo title.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'url'    => [\n\t\t\t\t\t'description' => __( 'Publisher logo URL.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t\t'active' => [\n\t\t\t\t\t'description' => __( 'Whether the publisher logo is the default one.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'boolean',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t'readonly'    => true,\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Get an existing publisher logo's post object, if valid.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param int $id Supplied ID.\n\t * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.\n\t */\n\tprotected function get_publisher_logo( $id ) {\n\t\t/**\n\t\t * List of publisher logos.\n\t\t *\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = $this->settings->get_setting( $this->settings::SETTING_NAME_PUBLISHER_LOGOS, [] );\n\t\t$publisher_logos = $this->filter_publisher_logos( $publisher_logos );\n\n\t\t$post = get_post( $id );\n\n\t\tif ( ! $post || ! \\in_array( $post->ID, $publisher_logos, true ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_invalid_id',\n\t\t\t\t__( 'Invalid ID', 'web-stories' ),\n\t\t\t\t[ 'status' => 400 ]\n\t\t\t);\n\t\t}\n\n\t\treturn $post;\n\t}\n\n\t/**\n\t * Filters publisher logos to remove non-existent or invalid ones.\n\t *\n\t * @param int[] $publisher_logos List of publisher logos.\n\t * @return int[] Filtered list of publisher logos.\n\t */\n\tprotected function filter_publisher_logos( $publisher_logos ): array {\n\t\treturn array_filter( $publisher_logos, 'wp_attachment_is_image' );\n\t}\n\n\t/**\n\t * Prepares links for the request.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_Post $post Post object.\n\t * @return array Links for the given post.\n\t *\n\t * @phpstan-return Links\n\t */\n\tprotected function prepare_links( $post ): array {\n\t\t$base = \\sprintf( '%s/%s', $this->namespace, $this->rest_base );\n\n\t\t// Entity meta.\n\t\treturn [\n\t\t\t'self'       => [\n\t\t\t\t'href' => rest_url( trailingslashit( $base ) . $post->ID ),\n\t\t\t],\n\t\t\t'collection' => [\n\t\t\t\t'href' => rest_url( $base ),\n\t\t\t],\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/REST_Controller.php",
    "content": "<?php\n/**\n * Class REST_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse WP_REST_Controller;\n\n/**\n * Class REST_Controller\n */\nabstract class REST_Controller extends WP_REST_Controller implements Service, Delayed, Registerable {\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_routes();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'rest_api_init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 100;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Status_Check_Controller.php",
    "content": "<?php\n/**\n * Class Status_Check_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * API endpoint check status.\n *\n * Class Status_Check_Controller\n *\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n * @phpstan-type Schema array{\n *   properties: array{\n *     success?: SchemaEntry,\n *   }\n * }\n */\nclass Status_Check_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->rest_base = 'status-check';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers routes for links.\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::ALLMETHODS,\n\t\t\t\t\t'callback'            => [ $this, 'status_check' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'status_check_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'content' => [\n\t\t\t\t\t\t\t'description' => __( 'Test HTML content.', 'web-stories' ),\n\t\t\t\t\t\t\t'required'    => true,\n\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Status check, return true for now.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param WP_REST_Request $request Full data about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function status_check( $request ) {\n\t\t$data = [\n\t\t\t'success' => true,\n\t\t];\n\n\t\t$response = $this->prepare_item_for_response( $data, $request );\n\n\t\treturn rest_ensure_response( $response );\n\t}\n\n\t/**\n\t * Prepares a status data output for response.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param array{success: bool} $item    Status array.\n\t * @param WP_REST_Request      $request Request object.\n\t * @return WP_REST_Response|WP_Error Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $item, $request ) {\n\t\t$fields = $this->get_fields_for_response( $request );\n\t\t$schema = $this->get_item_schema();\n\n\t\t$data = [];\n\n\t\tif ( ! empty( $schema['properties']['success'] ) && rest_is_field_included( 'success', $fields ) ) {\n\t\t\t$data['success'] = rest_sanitize_value_from_schema( $item['success'], $schema['properties']['success'] );\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\treturn rest_ensure_response( $data );\n\t}\n\n\t/**\n\t * Retrieves the status schema, conforming to JSON Schema.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'status',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'success' => [\n\t\t\t\t\t'description' => __( 'Whether check was successful', 'web-stories' ),\n\t\t\t\t\t'type'        => 'boolean',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Checks if current user can process status.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @return true|WP_Error True if the request has read access, WP_Error object otherwise.\n\t */\n\tpublic function status_check_permissions_check() {\n\t\tif ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {\n\t\t\treturn new \\WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed run status check.', 'web-stories' ), [ 'status' => rest_authorization_required_code() ] );\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Autosaves_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Autosaves_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse WP_Post;\nuse WP_REST_Autosaves_Controller;\nuse WP_REST_Controller;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Stories_Autosaves_Controller class.\n *\n * @phpstan-import-type Schema from \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller\n */\nclass Stories_Autosaves_Controller extends WP_REST_Autosaves_Controller {\n\n\t/**\n\t * Parent post controller.\n\t */\n\tprotected WP_REST_Controller $parent_controller;\n\n\t/**\n\t * The base of the parent controller's route.\n\t */\n\tprotected string $parent_base;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $parent_post_type Post type of the parent.\n\t */\n\tpublic function __construct( string $parent_post_type ) {\n\t\tparent::__construct( $parent_post_type );\n\n\t\t/**\n\t\t * Post type instance.\n\t\t *\n\t\t * @var \\WP_Post_Type $post_type_object\n\t\t */\n\t\t$post_type_object = get_post_type_object( $parent_post_type );\n\n\t\t/**\n\t\t * Parent controller instance.\n\t\t *\n\t\t * @var WP_REST_Controller $parent_controller\n\t\t */\n\t\t$parent_controller = $post_type_object->get_rest_controller();\n\n\t\t$this->parent_controller = $parent_controller;\n\t\t$this->parent_base       = ! empty( $post_type_object->rest_base ) ? (string) $post_type_object->rest_base : $post_type_object->name;\n\t\t$this->namespace         = ! empty( $post_type_object->rest_namespace ) ? (string) $post_type_object->rest_namespace : 'wp/v2';\n\t}\n\n\t/**\n\t * Registers the routes for autosaves.\n\t *\n\t * Used to override the create_item() callback.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tparent::register_routes();\n\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->parent_base . '/(?P<id>[\\d]+)/' . $this->rest_base,\n\t\t\t[\n\t\t\t\t'args'   => [\n\t\t\t\t\t'parent' => [\n\t\t\t\t\t\t'description' => __( 'The ID for the parent of the object.', 'web-stories' ),\n\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_items' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'get_items_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_collection_params(),\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::CREATABLE,\n\t\t\t\t\t'callback'            => [ $this, 'create_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'create_item_permissions_check' ],\n\t\t\t\t\t'args'                => $this->parent_controller->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),\n\t\t\t\t],\n\t\t\t\t'schema' => [ $this, 'get_public_item_schema' ],\n\t\t\t],\n\t\t\ttrue // required so that the existing route is overridden.\n\t\t);\n\t}\n\n\t/**\n\t * Prepares a single template output for response.\n\t *\n\t * Adds post_content_filtered field to output.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_Post         $post Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t * @phpstan-param WP_REST_Request<array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $post, $request ): WP_REST_Response {\n\t\t$response = parent::prepare_item_for_response( $post, $request );\n\t\t$fields   = $this->get_fields_for_response( $request );\n\t\t$schema   = $this->get_item_schema();\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string,mixed> $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\tif ( ! empty( $schema['properties']['story_data'] ) && rest_is_field_included( 'story_data', $fields ) ) {\n\t\t\t$post_story_data    = json_decode( $post->post_content_filtered, true );\n\t\t\t$data['story_data'] = rest_sanitize_value_from_schema( $post_story_data, $schema['properties']['story_data'] );\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\t\t$links   = $response->get_links();\n\n\t\t// Wrap the data in a response object.\n\t\t$response = new WP_REST_Response( $data );\n\t\tforeach ( $links as $rel => $rel_links ) {\n\t\t\tforeach ( $rel_links as $link ) {\n\t\t\t\t$response->add_link( $rel, $link['href'], $link['attributes'] );\n\t\t\t}\n\t\t}\n\n\t\t/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php */\n\t\treturn apply_filters( 'rest_prepare_autosave', $response, $post, $request );\n\t}\n\n\t/**\n\t * Retrieves the story's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$autosaves_schema = parent::get_item_schema();\n\t\t$stories_schema   = $this->parent_controller->get_item_schema();\n\n\t\t$autosaves_schema['properties']['story_data'] = $stories_schema['properties']['story_data'];\n\n\t\t$this->schema = $autosaves_schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Base_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Base_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Decoder;\nuse Google\\Web_Stories\\Services;\nuse stdClass;\nuse WP_Error;\nuse WP_Post;\nuse WP_REST_Posts_Controller;\nuse WP_REST_Request;\nuse WP_REST_Response;\n\n/**\n * Stories_Base_Controller class.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * Override the WP_REST_Posts_Controller class to add `post_content_filtered` to REST request.\n *\n * @phpstan-type Link array{\n *   href?: string,\n *   embeddable?: bool,\n *   taxonomy?: string\n * }\n * @phpstan-type Links array<string, Link|Link[]>\n * @phpstan-type SchemaEntry array{\n *   description: string,\n *   type: string,\n *   context: string[],\n *   default?: mixed,\n * }\n * @phpstan-type Schema array{\n *   properties: array{\n *     content?: SchemaEntry,\n *     story_data?: SchemaEntry\n *   }\n * }\n * @phpstan-type RegisteredMetadata array{\n *   type: string,\n *   description: string,\n *   single: bool,\n *   sanitize_callback?: callable,\n *   auth_callback: callable,\n *   show_in_rest: bool|array{schema: array<string, mixed>},\n *   default?: mixed\n * }\n */\nclass Stories_Base_Controller extends WP_REST_Posts_Controller {\n\t/**\n\t * Decoder instance.\n\t *\n\t * @var Decoder Decoder instance.\n\t */\n\tprivate Decoder $decoder;\n\n\t/**\n\t * Constructor.\n\t *\n\t * Override the namespace.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $post_type Post type.\n\t */\n\tpublic function __construct( $post_type ) {\n\t\tparent::__construct( $post_type );\n\n\t\t$injector = Services::get_injector();\n\t\t/**\n\t\t * Decoder instance.\n\t\t *\n\t\t * @var Decoder $decoder Decoder instance.\n\t\t */\n\t\t$decoder = $injector->make( Decoder::class );\n\n\t\t$this->decoder = $decoder;\n\t}\n\n\t/**\n\t * Prepares a single template output for response.\n\t *\n\t * Adds post_content_filtered field to output.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_Post         $post Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<covariant array{context: string}> $request\n\t */\n\tpublic function prepare_item_for_response( $post, $request ): WP_REST_Response {\n\t\t$response = parent::prepare_item_for_response( $post, $request );\n\t\t$fields   = $this->get_fields_for_response( $request );\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->get_item_schema();\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string,mixed> $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\tif ( ! empty( $schema['properties']['story_data'] ) && rest_is_field_included( 'story_data', $fields ) ) {\n\t\t\t$post_story_data    = json_decode( $post->post_content_filtered, true );\n\t\t\t$data['story_data'] = post_password_required( $post ) ? (object) [] : rest_sanitize_value_from_schema( $post_story_data, $schema['properties']['story_data'] );\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\t\t$links   = $response->get_links();\n\n\t\t// Wrap the data in a response object.\n\t\t$response = new WP_REST_Response( $data );\n\t\tforeach ( $links as $rel => $rel_links ) {\n\t\t\tforeach ( $rel_links as $link ) {\n\t\t\t\t$response->add_link( $rel, $link['href'], $link['attributes'] );\n\t\t\t}\n\t\t}\n\n\t\t/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */\n\t\treturn apply_filters( \"rest_prepare_{$this->post_type}\", $response, $post, $request );\n\t}\n\n\t/**\n\t * Retrieves the story's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array Item schema data.\n\t *\n\t * @phpstan-return Schema\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\t/**\n\t\t\t * Schema.\n\t\t\t *\n\t\t\t * @phpstan-var Schema $schema\n\t\t\t */\n\t\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\t\treturn $schema;\n\t\t}\n\n\t\t$schema = parent::get_item_schema();\n\n\t\t$schema['properties']['story_data'] = [\n\t\t\t'description' => __( 'Story data', 'web-stories' ),\n\t\t\t'type'        => 'object',\n\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t'default'     => [],\n\t\t];\n\n\t\t$schema['properties']['original_id'] = [\n\t\t\t'description' => __( 'Unique identifier for original story id.', 'web-stories' ),\n\t\t\t'type'        => 'integer',\n\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->add_additional_fields_schema( $this->schema );\n\t\treturn $schema;\n\t}\n\n\t/**\n\t * Prepares a single story for create or update. Add post_content_filtered field to save/insert.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Request object.\n\t * @return stdClass|WP_Error Post object or WP_Error.\n\t */\n\tprotected function prepare_item_for_database( $request ) {\n\t\t$prepared_post = parent::prepare_item_for_database( $request );\n\n\t\tif ( is_wp_error( $prepared_post ) ) {\n\t\t\treturn $prepared_post;\n\t\t}\n\n\t\t/**\n\t\t * Schema.\n\t\t *\n\t\t * @phpstan-var Schema $schema\n\t\t */\n\t\t$schema = $this->get_item_schema();\n\n\t\t// Post content.\n\t\tif ( ! empty( $schema['properties']['content'] ) ) {\n\n\t\t\t// Ensure that content and story_data are updated together.\n\t\t\t// Exception: new auto-draft created from a template.\n\t\t\tif (\n\t\t\t\t(\n\t\t\t\t( ! empty( $request['story_data'] ) && empty( $request['content'] ) ) ||\n\t\t\t\t( ! empty( $request['content'] ) && empty( $request['story_data'] ) )\n\t\t\t\t) && ( 'auto-draft' !== $prepared_post->post_status )\n\t\t\t) {\n\t\t\t\treturn new \\WP_Error(\n\t\t\t\t\t'rest_empty_content',\n\t\t\t\t\t\\sprintf(\n\t\t\t\t\t\t/* translators: 1: content, 2: story_data */\n\t\t\t\t\t\t__( '%1$s and %2$s should always be updated together.', 'web-stories' ),\n\t\t\t\t\t\t'content',\n\t\t\t\t\t\t'story_data'\n\t\t\t\t\t),\n\t\t\t\t\t[ 'status' => 412 ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( isset( $request['content'] ) ) {\n\t\t\t\t$prepared_post->post_content = $this->decoder->base64_decode( $prepared_post->post_content );\n\t\t\t}\n\t\t}\n\n\t\t// If the request is updating the content as well, let's make sure the JSON representation of the story is saved, too.\n\t\tif ( ! empty( $schema['properties']['story_data'] ) && isset( $request['story_data'] ) ) {\n\t\t\t$prepared_post->post_content_filtered = wp_json_encode( $request['story_data'] );\n\t\t}\n\n\t\treturn $prepared_post;\n\t}\n\n\t/**\n\t * Get registered post meta.\n\t *\n\t * @since 1.23.0\n\t *\n\t * @param WP_Post $original_post Post Object.\n\t * @return array<string, mixed> $meta\n\t */\n\tprotected function get_registered_meta( WP_Post $original_post ): array {\n\t\t$meta_keys = get_registered_meta_keys( 'post', $this->post_type );\n\t\t$meta      = [];\n\t\t/**\n\t\t * Meta key settings.\n\t\t *\n\t\t * @var array $settings\n\t\t * @phpstan-var RegisteredMetadata $settings\n\t\t */\n\t\tforeach ( $meta_keys as $key => $settings ) {\n\t\t\tif ( $settings['show_in_rest'] ) {\n\t\t\t\t$meta[ $key ] = get_post_meta( $original_post->ID, $key, $settings['single'] );\n\t\t\t}\n\t\t}\n\n\t\treturn $meta;\n\t}\n\n\t/**\n\t * Prepares links for the request.\n\t *\n\t * Ensures that {@see Stories_Users_Controller} is used for author embeds.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param WP_Post $post Post object.\n\t * @return array Links for the given post.\n\t *\n\t * @phpstan-return Links\n\t */\n\tprotected function prepare_links( $post ): array {\n\t\t$links = parent::prepare_links( $post );\n\n\t\tif ( ! empty( $post->post_author ) && post_type_supports( $post->post_type, 'author' ) ) {\n\t\t\t$links['author'] = [\n\t\t\t\t'href'       => rest_url( \\sprintf( '%s/%s/%s', $this->namespace, 'users', $post->post_author ) ),\n\t\t\t\t'embeddable' => true,\n\t\t\t];\n\t\t}\n\n\t\t// If we have a featured media, add that.\n\t\t$featured_media = get_post_thumbnail_id( $post->ID );\n\t\tif ( $featured_media ) {\n\t\t\t$image_url = rest_url( \\sprintf( '%s/%s/%s', $this->namespace, 'media', $featured_media ) );\n\n\t\t\t$links['https://api.w.org/featuredmedia'] = [\n\t\t\t\t'href'       => $image_url,\n\t\t\t\t'embeddable' => true,\n\t\t\t];\n\t\t}\n\n\t\tif ( ! \\in_array( $post->post_type, [ 'attachment', 'nav_menu_item', 'revision' ], true ) ) {\n\t\t\t$attachments_url = rest_url( \\sprintf( '%s/%s', $this->namespace, 'media' ) );\n\t\t\t$attachments_url = add_query_arg( 'parent', $post->ID, $attachments_url );\n\n\t\t\t$links['https://api.w.org/attachment'] = [\n\t\t\t\t'href' => $attachments_url,\n\t\t\t];\n\t\t}\n\n\t\treturn $links;\n\t}\n\n\t/**\n\t * Get the link relations available for the post and current user.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param WP_Post         $post    Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return string[] List of link relations.\n\t */\n\tprotected function get_available_actions( $post, $request ): array {\n\t\t$rels = parent::get_available_actions( $post, $request );\n\n\t\tif ( $this->check_delete_permission( $post ) ) {\n\t\t\t$rels[] = 'https://api.w.org/action-delete';\n\t\t}\n\n\t\tif ( $this->check_update_permission( $post ) ) {\n\t\t\t$rels[] = 'https://api.w.org/action-edit';\n\t\t}\n\n\t\treturn $rels;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Demo_Content;\nuse Google\\Web_Stories\\Media\\Image_Sizes;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_Post;\nuse WP_Post_Type;\nuse WP_Query;\nuse WP_REST_Request;\nuse WP_REST_Response;\n\n/**\n * Stories_Controller class.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type QueryArgs array{\n *   posts_per_page?: int,\n *   post_status?: string[],\n *   tax_query?: array<int|'relation', mixed>\n * }\n * @phpstan-import-type Links from \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller\n */\nclass Stories_Controller extends Stories_Base_Controller {\n\n\t/**\n\t * Default style presets to pass if not set.\n\t */\n\tpublic const EMPTY_STYLE_PRESETS = [\n\t\t'colors'     => [],\n\t\t'textStyles' => [],\n\t];\n\n\t/**\n\t * Query args.\n\t *\n\t * @var array<string,mixed>\n\t * @phpstan-var QueryArgs\n\t */\n\tprivate array $args = [];\n\n\t/**\n\t * Prepares a single story output for response. Add post_content_filtered field to output.\n\t *\n\t * @SuppressWarnings(\"PHPMD.CyclomaticComplexity\")\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_Post         $post Post object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<covariant array{context: string, web_stories_demo?: bool}> $request\n\t */\n\tpublic function prepare_item_for_response( $post, $request ): WP_REST_Response { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\n\t\tif ( 'auto-draft' === $post->post_status && wp_validate_boolean( $request['web_stories_demo'] ) ) {\n\t\t\t$demo         = new Demo_Content();\n\t\t\t$demo_content = $demo->get_content();\n\t\t\tif ( ! empty( $demo_content ) ) {\n\t\t\t\t$post->post_title            = $demo->get_title();\n\t\t\t\t$post->post_content_filtered = $demo_content;\n\t\t\t}\n\t\t}\n\n\t\t$response = parent::prepare_item_for_response( $post, $request );\n\t\t$fields   = $this->get_fields_for_response( $request );\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string,mixed> $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\tif ( rest_is_field_included( 'style_presets', $fields ) ) {\n\t\t\t$style_presets         = get_option( Story_Post_Type::STYLE_PRESETS_OPTION, self::EMPTY_STYLE_PRESETS );\n\t\t\t$data['style_presets'] = \\is_array( $style_presets ) ? $style_presets : self::EMPTY_STYLE_PRESETS;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'preview_link', $fields ) ) {\n\t\t\t// Based on https://github.com/WordPress/wordpress-develop/blob/8153c8ba020c4aec0b9d94243cd39c689a0730f7/src/wp-admin/includes/post.php#L1445-L1457.\n\t\t\tif ( 'draft' === $post->post_status || empty( $post->post_name ) ) {\n\t\t\t\t$view_link = get_preview_post_link( $post );\n\t\t\t} elseif ( 'publish' === $post->post_status ) {\n\t\t\t\t$view_link = get_permalink( $post );\n\t\t\t} else {\n\t\t\t\tif ( ! \\function_exists( 'get_sample_permalink' ) ) {\n\t\t\t\t\trequire_once ABSPATH . 'wp-admin/includes/post.php';\n\t\t\t\t}\n\n\t\t\t\t[ $permalink ] = get_sample_permalink( $post->ID, $post->post_title, '' );\n\n\t\t\t\t// Allow non-published (private, future) to be viewed at a pretty permalink, in case $post->post_name is set.\n\t\t\t\t$view_link = str_replace( [ '%pagename%', '%postname%' ], $post->post_name, $permalink );\n\t\t\t}\n\n\t\t\t$data['preview_link'] = $view_link;\n\t\t}\n\n\t\tif ( rest_is_field_included( 'edit_link', $fields ) ) {\n\t\t\t$edit_link = get_edit_post_link( $post, 'rest-api' );\n\t\t\tif ( $edit_link ) {\n\t\t\t\t$data['edit_link'] = $edit_link;\n\t\t\t}\n\t\t}\n\n\t\tif ( rest_is_field_included( 'embed_post_link', $fields ) && current_user_can( 'edit_posts' ) ) {\n\t\t\t$data['embed_post_link'] = add_query_arg( [ 'from-web-story' => $post->ID ], admin_url( 'post-new.php' ) );\n\t\t}\n\n\t\tif ( rest_is_field_included( 'story_poster', $fields ) ) {\n\t\t\t$story_poster = $this->get_story_poster( $post );\n\t\t\tif ( $story_poster ) {\n\t\t\t\t$data['story_poster'] = $story_poster;\n\t\t\t}\n\t\t}\n\n\t\t$data  = $this->filter_response_by_context( $data, $context );\n\t\t$links = $response->get_links();\n\n\t\t$response = new WP_REST_Response( $data );\n\t\tforeach ( $links as $rel => $rel_links ) {\n\t\t\tforeach ( $rel_links as $link ) {\n\t\t\t\t$response->add_link( $rel, $link['href'], $link['attributes'] );\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Filters the post data for a response.\n\t\t *\n\t\t * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param WP_REST_Response $response The response object.\n\t\t * @param WP_Post $post Post object.\n\t\t * @param WP_REST_Request $request Request object.\n\t\t */\n\t\treturn apply_filters( \"rest_prepare_{$this->post_type}\", $response, $post, $request );\n\t}\n\n\t/**\n\t * Creates a single story.\n\t *\n\t * Override the existing method so we can set parent id.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{original_id?: int}> $request\n\t */\n\tpublic function create_item( $request ) {\n\t\t$original_id = ! empty( $request['original_id'] ) ? $request['original_id'] : null;\n\t\tif ( ! $original_id ) {\n\t\t\treturn parent::create_item( $request );\n\t\t}\n\n\t\t$original_post = $this->get_post( $original_id );\n\t\tif ( is_wp_error( $original_post ) ) {\n\t\t\treturn $original_post;\n\t\t}\n\n\t\tif ( ! $this->check_update_permission( $original_post ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_cannot_create',\n\t\t\t\t__( 'Sorry, you are not allowed to duplicate this story.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\t$request['content'] = $original_post->post_content;\n\t\t$request['excerpt'] = $original_post->post_excerpt;\n\n\t\t$title = \\sprintf(\n\t\t/* translators: %s: story title. */\n\t\t\t__( '%s (Copy)', 'web-stories' ),\n\t\t\t$original_post->post_title\n\t\t);\n\n\t\t$request['title'] = $title;\n\n\t\t$story_data = json_decode( $original_post->post_content_filtered, true );\n\t\tif ( $story_data ) {\n\t\t\t$request['story_data'] = $story_data;\n\t\t}\n\n\t\t$thumbnail_id = get_post_thumbnail_id( $original_post );\n\t\tif ( $thumbnail_id ) {\n\t\t\t$request['featured_media'] = $thumbnail_id;\n\t\t}\n\n\t\t$meta = $this->get_registered_meta( $original_post );\n\t\tif ( $meta ) {\n\t\t\t$request['meta'] = $meta;\n\t\t}\n\n\t\treturn parent::create_item( $request );\n\t}\n\n\t/**\n\t * Updates a single post.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function update_item( $request ) {\n\t\t$response = parent::update_item( $request );\n\n\t\tif ( is_wp_error( $response ) ) {\n\t\t\treturn rest_ensure_response( $response );\n\t\t}\n\n\t\t// If style presets are set.\n\t\t$style_presets = $request->get_param( 'style_presets' );\n\t\tif ( \\is_array( $style_presets ) ) {\n\t\t\tupdate_option( Story_Post_Type::STYLE_PRESETS_OPTION, $style_presets );\n\t\t}\n\n\t\treturn rest_ensure_response( $response );\n\t}\n\n\t/**\n\t * Retrieves the story's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string, string|array<string, array<string,string|string[]>>> Item schema data.\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t\t}\n\n\t\t$schema = parent::get_item_schema();\n\n\t\t$schema['properties']['style_presets'] = [\n\t\t\t'description' => __( 'Style presets used by all stories', 'web-stories' ),\n\t\t\t'type'        => 'object',\n\t\t\t'context'     => [ 'edit' ],\n\t\t];\n\n\t\t$schema['properties']['preview_link'] = [\n\t\t\t'description' => __( 'Preview Link.', 'web-stories' ),\n\t\t\t'type'        => 'string',\n\t\t\t'context'     => [ 'edit' ],\n\t\t\t'format'      => 'uri',\n\t\t\t'default'     => '',\n\t\t];\n\n\t\t$schema['properties']['edit_link'] = [\n\t\t\t'description' => _x( 'Edit Link', 'compound noun', 'web-stories' ),\n\t\t\t'type'        => 'string',\n\t\t\t'context'     => [ 'edit' ],\n\t\t\t'format'      => 'uri',\n\t\t\t'default'     => '',\n\t\t];\n\n\t\t$schema['properties']['embed_post_link'] = [\n\t\t\t'description' => __( 'Embed Post Edit Link.', 'web-stories' ),\n\t\t\t'type'        => 'string',\n\t\t\t'context'     => [ 'edit' ],\n\t\t\t'format'      => 'uri',\n\t\t\t'default'     => '',\n\t\t];\n\n\t\t$schema['properties']['story_poster'] = [\n\t\t\t'description' => __( 'Story poster image.', 'web-stories' ),\n\t\t\t'type'        => 'object',\n\t\t\t'properties'  => [\n\t\t\t\t'id'         => [\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'description' => __( 'Poster ID', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'needsProxy' => [\n\t\t\t\t\t'description' => __( 'If poster needs to be proxied', 'web-stories' ),\n\t\t\t\t\t'type'        => 'boolean',\n\t\t\t\t],\n\t\t\t\t'height'     => [\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t'description' => __( 'Poster height', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'url'        => [\n\t\t\t\t\t'description' => __( 'Poster URL.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t],\n\t\t\t\t'width'      => [\n\t\t\t\t\t'description' => __( 'Poster width.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'default'     => null,\n\t\t];\n\n\t\t$schema['properties']['status']['enum'][] = 'auto-draft';\n\n\t\t$this->schema = $schema;\n\n\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t}\n\n\t/**\n\t * Filters query clauses to sort posts by the author's display name.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string[] $clauses Associative array of the clauses for the query.\n\t * @param WP_Query $query   The WP_Query instance.\n\t * @return string[] Filtered query clauses.\n\t */\n\tpublic function filter_posts_clauses( $clauses, WP_Query $query ): array {\n\t\tglobal $wpdb;\n\n\t\tif ( $this->post_type !== $query->get( 'post_type' ) ) {\n\t\t\treturn $clauses;\n\t\t}\n\t\tif ( 'story_author' !== $query->get( 'orderby' ) ) {\n\t\t\treturn $clauses;\n\t\t}\n\n\t\t/**\n\t\t * Order value.\n\t\t *\n\t\t * @var string $order\n\t\t */\n\t\t$order = $query->get( 'order' );\n\n\t\t// phpcs:disable WordPressVIPMinimum.Variables.RestrictedVariables.user_meta__wpdb__users\n\t\t$clauses['join']   .= \" LEFT JOIN {$wpdb->users} ON {$wpdb->posts}.post_author={$wpdb->users}.ID\";\n\t\t$clauses['orderby'] = \"{$wpdb->users}.display_name $order, \" . $clauses['orderby'];\n\t\t// phpcs:enable WordPressVIPMinimum.Variables.RestrictedVariables.user_meta__wpdb__users\n\n\t\treturn $clauses;\n\t}\n\n\t/**\n\t * Prime post caches for attachments and parents.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param WP_Post[] $posts Array of post objects.\n\t * @return WP_Post[] Array of posts.\n\t */\n\tpublic function prime_post_caches( array $posts ): array {\n\t\t$post_ids = $this->get_attached_post_ids( $posts );\n\t\tif ( ! empty( $post_ids ) ) {\n\t\t\t_prime_post_caches( $post_ids );\n\t\t}\n\n\t\treturn $posts;\n\t}\n\n\t/**\n\t * Filter the query to cache the value to a class property.\n\t *\n\t * @param array<string, mixed> $args    WP_Query arguments.\n\t * @return array<string, mixed> Current args.\n\t *\n\t * @phpstan-param QueryArgs $args\n\t */\n\tpublic function filter_query( $args ): array {\n\t\t$this->args = $args;\n\n\t\treturn $args;\n\t}\n\t/**\n\t * Retrieves a collection of web stories.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string, _embed?: string|string[], _web_stories_envelope?: bool}> $request\n\t */\n\tpublic function get_items( $request ) {\n\t\tadd_filter( \"rest_{$this->post_type}_query\", [ $this, 'filter_query' ], 100, 1 );\n\t\tadd_filter( 'posts_clauses', [ $this, 'filter_posts_clauses' ], 10, 2 );\n\t\tadd_filter( 'posts_results', [ $this, 'prime_post_caches' ] );\n\t\t$response = parent::get_items( $request );\n\t\tremove_filter( 'posts_results', [ $this, 'prime_post_caches' ] );\n\t\tremove_filter( 'posts_clauses', [ $this, 'filter_posts_clauses' ], 10 );\n\t\tremove_filter( \"rest_{$this->post_type}_query\", [ $this, 'filter_query' ], 100 );\n\n\t\tif ( is_wp_error( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\tif ( 'edit' !== $request['context'] ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t$response = $this->add_response_headers( $response, $request );\n\t\tif ( is_wp_error( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\tif ( $request['_web_stories_envelope'] ) {\n\t\t\t$embed    = $request['_embed'];\n\t\t\t$embed    = $embed ? rest_parse_embed_param( $embed ) : false;\n\t\t\t$response = rest_get_server()->envelope_response( $response, $embed );\n\t\t}\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the query params for the posts collection.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['_web_stories_envelope'] = [\n\t\t\t'description' => __( 'Envelope request for preloading.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t\t'default'     => false,\n\t\t];\n\n\t\t$query_params['web_stories_demo'] = [\n\t\t\t'description' => __( 'Load demo data.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t\t'default'     => false,\n\t\t];\n\n\t\tif ( ! empty( $query_params['orderby'] ) ) {\n\t\t\t$query_params['orderby']['enum'][] = 'story_author';\n\t\t}\n\n\t\treturn $query_params;\n\t}\n\n\t/**\n\t * Get an array of attached post objects.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param WP_Post[] $posts Array of post objects.\n\t * @return int[] Array of post ids.\n\t */\n\tprotected function get_attached_post_ids( array $posts ): array {\n\t\treturn array_unique( array_filter( array_map( [ $this, 'get_publisher_logo_id' ], $posts ) ) );\n\t}\n\n\t/**\n\t * Add response headers, with post counts.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_REST_Response $response Response object.\n\t * @param WP_REST_Request  $request Request object.\n\t * @return WP_REST_Response|WP_Error\n\t */\n\tprotected function add_response_headers( WP_REST_Response $response, WP_REST_Request $request ) {\n\t\t// Add counts for other statuses.\n\t\t$statuses = [\n\t\t\t'publish' => 'publish',\n\t\t];\n\n\t\t$post_type = get_post_type_object( $this->post_type );\n\n\t\tif ( ! ( $post_type instanceof WP_Post_Type ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\tif ( current_user_can( $post_type->cap->edit_posts ) ) { // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t$statuses['draft']   = 'draft';\n\t\t\t$statuses['future']  = 'future';\n\t\t\t$statuses['pending'] = 'pending';\n\t\t}\n\n\t\tif ( current_user_can( $post_type->cap->publish_posts ) ) { // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t$statuses['private'] = 'private';\n\t\t}\n\n\t\t$edit_others_posts  = current_user_can( $post_type->cap->edit_others_posts ); // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t$edit_private_posts = current_user_can( $post_type->cap->edit_private_posts ); // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\n\t\t$statuses_count = [ 'all' => 0 ];\n\t\t$total_posts    = 0;\n\n\t\t$query_args = $this->prepare_items_query( $this->args, $request );\n\n\t\t// Strip down query for speed.\n\t\t$query_args['fields']                 = 'ids';\n\t\t$query_args['posts_per_page']         = 1;\n\t\t$query_args['paged']                  = 1;\n\t\t$query_args['update_post_meta_cache'] = false;\n\t\t$query_args['update_post_term_cache'] = false;\n\n\t\tforeach ( $statuses as $key => $status ) {\n\t\t\t$posts_query               = new WP_Query();\n\t\t\t$query_args['post_status'] = $status;\n\t\t\tif ( \\in_array( $status, [ 'draft', 'future', 'pending' ], true ) && ! $edit_others_posts ) {\n\t\t\t\t$query_args['author'] = get_current_user_id();\n\t\t\t}\n\t\t\tif ( 'private' === $status && ! $edit_private_posts ) {\n\t\t\t\t$query_args['author'] = get_current_user_id();\n\t\t\t}\n\t\t\t$posts_query->query( $query_args );\n\t\t\t$statuses_count[ $key ] = absint( $posts_query->found_posts );\n\t\t\t$statuses_count['all'] += $statuses_count[ $key ];\n\t\t\tif ( \\in_array( $status, $this->args['post_status'] ?? [], true ) ) {\n\t\t\t\t$total_posts += $statuses_count[ $key ] ?? 0;\n\t\t\t}\n\t\t}\n\n\t\t// Encode the array as headers do not support passing an array.\n\t\t$encoded_statuses = wp_json_encode( $statuses_count );\n\t\tif ( $encoded_statuses ) {\n\t\t\t$response->header( 'X-WP-TotalByStatus', $encoded_statuses );\n\t\t}\n\n\t\t$page      = (int) $posts_query->query_vars['paged'];\n\t\t$max_pages = ceil( $total_posts / (int) ( $this->args['posts_per_page'] ?? 10 ) );\n\n\t\tif ( $page > $max_pages && $total_posts > 0 ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_post_invalid_page_number',\n\t\t\t\t__( 'The page number requested is larger than the number of pages available.', 'web-stories' ),\n\t\t\t\t[ 'status' => 400 ]\n\t\t\t);\n\t\t}\n\n\t\t$response->header( 'X-WP-Total', (string) $total_posts );\n\t\t$response->header( 'X-WP-TotalPages', (string) $max_pages );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Prepares links for the request.\n\t *\n\t * @param WP_Post $post Post object.\n\t * @return array Links for the given post.\n\t *\n\t * @phpstan-return Links\n\t */\n\tprotected function prepare_links( $post ): array {\n\t\t$links = parent::prepare_links( $post );\n\n\t\t$links = $this->add_post_locking_link( $links, $post );\n\t\t$links = $this->add_publisher_logo_link( $links, $post );\n\n\t\treturn $links;\n\t}\n\n\t/**\n\t * Adds a REST API link if the story is locked.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param array   $links Links for the given post.\n\t * @param WP_Post $post  Post object.\n\t * @return array Modified list of links.\n\t *\n\t * @phpstan-param Links $links\n\t * @phpstan-return Links\n\t */\n\tprivate function add_post_locking_link( array $links, WP_Post $post ): array {\n\t\t$base     = \\sprintf( '%s/%s', $this->namespace, $this->rest_base );\n\t\t$lock_url = rest_url( trailingslashit( $base ) . $post->ID . '/lock' );\n\n\t\t$links['https://api.w.org/lock'] = [\n\t\t\t'href'       => $lock_url,\n\t\t\t'embeddable' => true,\n\t\t];\n\n\t\t/**\n\t\t * Lock data.\n\t\t *\n\t\t * @var string|false $lock\n\t\t */\n\t\t$lock = get_post_meta( $post->ID, '_edit_lock', true );\n\n\t\tif ( ! empty( $lock ) ) {\n\t\t\t[ $time, $user ] = explode( ':', $lock );\n\n\t\t\t/** This filter is documented in wp-admin/includes/ajax-actions.php */\n\t\t\t$time_window = apply_filters( 'wp_check_post_lock_window', 150 );\n\n\t\t\tif ( $time && $time > time() - $time_window ) {\n\t\t\t\t$links['https://api.w.org/lockuser'] = [\n\t\t\t\t\t'href'       => rest_url( \\sprintf( '%s/%s', $this->namespace, 'users/' ) . $user ),\n\t\t\t\t\t'embeddable' => true,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\treturn $links;\n\t}\n\n\t/**\n\t * Helper method to get publisher logo id.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param WP_Post $post Post Object.\n\t * @return int ID of attachment for publisher logo.\n\t */\n\tprivate function get_publisher_logo_id( WP_Post $post ): int {\n\t\t/**\n\t\t * Publisher logo ID.\n\t\t *\n\t\t * @var string|int $publisher_logo_id\n\t\t */\n\t\t$publisher_logo_id = get_post_meta( $post->ID, Story_Post_Type::PUBLISHER_LOGO_META_KEY, true );\n\n\t\treturn (int) $publisher_logo_id;\n\t}\n\n\t/**\n\t * Adds a REST API link for the story's publisher logo.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param array   $links Links for the given post.\n\t * @param WP_Post $post Post object.\n\t * @return array Modified list of links.\n\t *\n\t * @phpstan-param Links $links\n\t * @phpstan-return Links\n\t */\n\tprivate function add_publisher_logo_link( array $links, WP_Post $post ): array {\n\t\t$publisher_logo_id = $this->get_publisher_logo_id( $post );\n\n\t\tif ( $publisher_logo_id ) {\n\t\t\t$links['https://api.w.org/publisherlogo'] = [\n\t\t\t\t'href'       => rest_url( \\sprintf( '%s/%s/%s', $this->namespace, 'media', $publisher_logo_id ) ),\n\t\t\t\t'embeddable' => true,\n\t\t\t];\n\t\t}\n\n\t\treturn $links;\n\t}\n\n\n\t/**\n\t * Helper method to get the story poster.\n\t *\n\t * Checks for the regular featured image as well as a hotlinked image.\n\t *\n\t * @since 1.23.2\n\t *\n\t * @param WP_Post $post Post Object.\n\t * @return array{url:string, width: int, height: int, needsProxy: bool, id?: int}|null Story poster data.\n\t */\n\tprivate function get_story_poster( WP_Post $post ): ?array {\n\t\t$thumbnail_id = (int) get_post_thumbnail_id( $post );\n\n\t\tif ( 0 !== $thumbnail_id ) {\n\t\t\t$poster_src = wp_get_attachment_image_src( $thumbnail_id, Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS );\n\t\t\tif ( $poster_src ) {\n\t\t\t\t[$url, $width, $height] = $poster_src;\n\n\t\t\t\treturn [\n\t\t\t\t\t'id'         => $thumbnail_id,\n\t\t\t\t\t'url'        => $url,\n\t\t\t\t\t'width'      => $width,\n\t\t\t\t\t'height'     => $height,\n\t\t\t\t\t'needsProxy' => false,\n\t\t\t\t];\n\t\t\t}\n\t\t} else {\n\n\t\t\t/**\n\t\t\t * Poster.\n\t\t\t *\n\t\t\t * @var array{url:string, width: int, height: int, needsProxy: bool}|false $poster\n\t\t\t */\n\t\t\t$poster = get_post_meta( $post->ID, Story_Post_Type::POSTER_META_KEY, true );\n\n\t\t\tif ( ! empty( $poster ) ) {\n\t\t\t\treturn $poster;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Lock_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Lock_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_REST_Controller;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\n\n/**\n * Class Stories_Lock_Controller\n */\nclass Stories_Lock_Controller extends REST_Controller implements HasRequirements {\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Parent post controller.\n\t *\n\t * @var WP_REST_Controller WP_REST_Controller instance.\n\t */\n\tprivate WP_REST_Controller $parent_controller;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\n\t\t$this->parent_controller = $story_post_type->get_parent_controller();\n\t\t$this->rest_base         = $story_post_type->get_rest_base();\n\t\t$this->namespace         = $story_post_type->get_rest_namespace();\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Registers the routes for the objects of the controller.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @see register_rest_route()\n\t */\n\tpublic function register_routes(): void {\n\t\tregister_rest_route(\n\t\t\t$this->namespace,\n\t\t\t'/' . $this->rest_base . '/(?P<id>[\\d]+)/lock',\n\t\t\t[\n\t\t\t\t'args' => [\n\t\t\t\t\t'id' => [\n\t\t\t\t\t\t'description' => __( 'Unique identifier for the object.', 'web-stories' ),\n\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => [ $this, 'get_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'get_item_permissions_check' ],\n\t\t\t\t\t'args'                => [\n\t\t\t\t\t\t'context' => $this->get_context_param( [ 'default' => 'view' ] ),\n\t\t\t\t\t],\n\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::EDITABLE,\n\t\t\t\t\t'callback'            => [ $this, 'update_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'update_item_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'methods'             => WP_REST_Server::DELETABLE,\n\t\t\t\t\t'callback'            => [ $this, 'delete_item' ],\n\t\t\t\t\t'permission_callback' => [ $this, 'delete_item_permissions_check' ],\n\t\t\t\t\t'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::DELETABLE ),\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Get post lock\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success.\n\t */\n\tpublic function get_item( $request ) {\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $request['id'];\n\n\t\t$lock = $this->get_lock( $post_id );\n\n\t\treturn $this->prepare_item_for_response( $lock, $request );\n\t}\n\n\t/**\n\t * Update post lock\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success.\n\t */\n\tpublic function update_item( $request ) {\n\t\tif ( ! \\function_exists( '\\wp_set_post_lock' ) ) {\n\t\t\trequire_once ABSPATH . 'wp-admin/includes/post.php';\n\t\t}\n\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $request['id'];\n\n\t\twp_set_post_lock( $post_id );\n\t\t$lock = $this->get_lock( $post_id );\n\n\t\treturn $this->prepare_item_for_response( $lock, $request );\n\t}\n\n\t/**\n\t * Delete post lock\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response Response object on success.\n\t */\n\tpublic function delete_item( $request ): WP_REST_Response {\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $request['id'];\n\n\t\t$lock     = $this->get_lock( $post_id );\n\t\t$previous = $this->prepare_item_for_response( $lock, $request );\n\t\t$result   = delete_post_meta( $post_id, '_edit_lock' );\n\t\t$data     = [];\n\t\tif ( ! is_wp_error( $previous ) ) {\n\t\t\t$data = $previous->get_data();\n\t\t}\n\t\t$response = new WP_REST_Response();\n\t\t$response->set_data(\n\t\t\t[\n\t\t\t\t'deleted'  => $result,\n\t\t\t\t'previous' => $data,\n\t\t\t]\n\t\t);\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Checks if a given request has access to read a lock.\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.\n\t */\n\tpublic function get_item_permissions_check( $request ) {\n\t\treturn $this->parent_controller->update_item_permissions_check( $request );\n\t}\n\n\t/**\n\t * Checks if a given request has access to update a lock.\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.\n\t */\n\tpublic function update_item_permissions_check( $request ) {\n\t\treturn $this->parent_controller->update_item_permissions_check( $request );\n\t}\n\n\t/**\n\t * Checks if a given request has access to delete a lock.\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.\n\t */\n\tpublic function delete_item_permissions_check( $request ) {\n\t\t$result = $this->parent_controller->update_item_permissions_check( $request );\n\t\tif ( is_wp_error( $result ) ) {\n\t\t\treturn $result;\n\t\t}\n\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $request['id'];\n\n\t\t$lock = $this->get_lock( $post_id );\n\t\tif ( \\is_array( $lock ) && isset( $lock['user'] ) && get_current_user_id() !== (int) $lock['user'] ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_cannot_delete_others_lock',\n\t\t\t\t__( 'Sorry, you are not allowed delete others lock.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Prepares a single lock output for response.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param array{time?: int, user?: int}|false $item Lock value, default to false is not set.\n\t * @param WP_REST_Request                     $request Request object.\n\t * @return WP_REST_Response|WP_Error Response object.\n\t *\n\t * @phpstan-param WP_REST_Request<array{context: string, id: int}> $request\n\t */\n\tpublic function prepare_item_for_response( $item, $request ) { // phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh\n\t\t$fields = $this->get_fields_for_response( $request );\n\t\t$schema = $this->get_item_schema();\n\n\t\t$nonce     = wp_create_nonce( 'wp_rest' );\n\t\t$lock_data = [\n\t\t\t'locked' => false,\n\t\t\t'time'   => '',\n\t\t\t'user'   => [\n\t\t\t\t'name' => '',\n\t\t\t\t'id'   => 0,\n\t\t\t],\n\t\t\t'nonce'  => $nonce,\n\t\t];\n\n\t\tif ( get_option( 'show_avatars' ) ) {\n\t\t\t$lock_data['user']['avatar'] = [];\n\t\t}\n\n\t\tif ( ! empty( $item ) ) {\n\t\t\t/** This filter is documented in wp-admin/includes/ajax-actions.php */\n\t\t\t$time_window = apply_filters( 'wp_check_post_lock_window', 150 );\n\n\t\t\tif ( isset( $item['time'] ) && $item['time'] > time() - $time_window ) {\n\t\t\t\t$lock_data = [\n\t\t\t\t\t'locked' => true,\n\t\t\t\t\t'time'   => $item['time'],\n\t\t\t\t\t'user'   => isset( $item['user'] ) ? (int) $item['user'] : 0,\n\t\t\t\t\t'nonce'  => $nonce,\n\t\t\t\t];\n\t\t\t\tif ( isset( $item['user'] ) ) {\n\t\t\t\t\t$user = get_user_by( 'id', $item['user'] );\n\t\t\t\t\tif ( $user ) {\n\t\t\t\t\t\t$lock_data['user'] = [\n\t\t\t\t\t\t\t'name' => $user->display_name,\n\t\t\t\t\t\t\t'id'   => $item['user'],\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\tif ( get_option( 'show_avatars' ) ) {\n\t\t\t\t\t\t\t$lock_data['user']['avatar'] = rest_get_avatar_urls( $user );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$data         = [];\n\t\t$check_fields = array_keys( $lock_data );\n\t\tforeach ( $check_fields as $check_field ) {\n\t\t\tif ( ! empty( $schema['properties'][ $check_field ] ) && rest_is_field_included( $check_field, $fields ) ) {\n\t\t\t\t$data[ $check_field ] = rest_sanitize_value_from_schema( $lock_data[ $check_field ], $schema['properties'][ $check_field ] );\n\t\t\t}\n\t\t}\n\n\t\t$context = ! empty( $request['context'] ) ? $request['context'] : 'view';\n\t\t$data    = $this->add_additional_fields_to_object( $data, $request );\n\t\t$data    = $this->filter_response_by_context( $data, $context );\n\n\t\t/**\n\t\t * Response object.\n\t\t *\n\t\t * @var WP_REST_Response $response\n\t\t */\n\t\t$response = rest_ensure_response( $data );\n\n\t\tif ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {\n\t\t\tif ( $request['id'] ) {\n\t\t\t\t$response->add_links( $this->prepare_links( $item, $request['id'] ) );\n\t\t\t}\n\t\t}\n\n\t\t$post_type = $this->story_post_type->get_slug();\n\n\t\t/**\n\t\t * Filters the lock data for a response.\n\t\t *\n\t\t * The dynamic portion of the hook name, `$post_type`, refers to the post type slug.\n\t\t *\n\t\t * @since 1.6.0\n\t\t *\n\t\t * @param WP_REST_Response $response The response object.\n\t\t * @param array|false      $item     Lock array if available.\n\t\t * @param WP_REST_Request  $request  Request object.\n\t\t */\n\t\treturn apply_filters( \"rest_prepare_{$post_type}_lock\", $response, $item, $request );\n\t}\n\n\t/**\n\t * Retrieves the post's schema, conforming to JSON Schema.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return array<string, string|array<string, array<string,string|string[]>>> Item schema data.\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t\t}\n\n\t\t$schema = [\n\t\t\t'$schema'    => 'http://json-schema.org/draft-04/schema#',\n\t\t\t'title'      => 'lock',\n\t\t\t'type'       => 'object',\n\t\t\t'properties' => [\n\t\t\t\t'time'   => [\n\t\t\t\t\t'description' => __( 'Unix time of lock', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'nonce'  => [\n\t\t\t\t\t'description' => __( 'Nonce value', 'web-stories' ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'context'     => [ 'view', 'edit' ],\n\t\t\t\t],\n\t\t\t\t'locked' => [\n\t\t\t\t\t'description' => __( 'If the current object is locked or not.', 'web-stories' ),\n\t\t\t\t\t'type'        => 'boolean',\n\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t],\n\t\t\t\t'user'   => [\n\t\t\t\t\t'description' => __( 'User', 'web-stories' ),\n\t\t\t\t\t'type'        => 'object',\n\t\t\t\t\t'properties'  => [\n\t\t\t\t\t\t'id'   => [\n\t\t\t\t\t\t\t'description' => __( 'The ID for the author of the lock.', 'web-stories' ),\n\t\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t\t\t'readonly'    => true,\n\t\t\t\t\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'name' => [\n\t\t\t\t\t\t\t'description' => __( 'Display name for the user.', 'web-stories' ),\n\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t'readonly'    => true,\n\t\t\t\t\t\t\t'context'     => [ 'embed', 'view', 'edit' ],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\tif ( get_option( 'show_avatars' ) ) {\n\t\t\t$avatar_properties = [];\n\n\t\t\t$avatar_sizes = rest_get_avatar_sizes();\n\n\t\t\tforeach ( $avatar_sizes as $size ) {\n\t\t\t\t$avatar_properties[ $size ] = [\n\t\t\t\t\t/* translators: %d: Avatar image size in pixels. */\n\t\t\t\t\t'description' => \\sprintf( __( 'Avatar URL with image size of %d pixels.', 'web-stories' ), $size ),\n\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t'context'     => [ 'embed', 'view', 'edit' ],\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t$schema['properties']['user']['properties']['avatar'] = [\n\t\t\t\t'description' => __( 'Avatar URLs for the user.', 'web-stories' ),\n\t\t\t\t'type'        => 'object',\n\t\t\t\t'context'     => [ 'embed', 'view', 'edit' ],\n\t\t\t\t'readonly'    => true,\n\t\t\t\t'properties'  => $avatar_properties,\n\t\t\t];\n\t\t}\n\n\t\t$this->schema = $schema;\n\n\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t}\n\n\t/**\n\t * Get the lock, if the ID is valid.\n\t *\n\t * @param int $post_id Supplied ID.\n\t * @return array{time?: int, user?: int}|false Lock data or false.\n\t */\n\tprotected function get_lock( int $post_id ) {\n\t\t/**\n\t\t * Lock data.\n\t\t *\n\t\t * @var string|false $lock\n\t\t */\n\t\t$lock = get_post_meta( $post_id, '_edit_lock', true );\n\n\t\tif ( ! empty( $lock ) ) {\n\t\t\t[ $time, $user ] = explode( ':', $lock );\n\t\t\tif ( $time && $user ) {\n\t\t\t\treturn [\n\t\t\t\t\t'time' => (int) $time,\n\t\t\t\t\t'user' => (int) $user,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Prepares links for the request.\n\t *\n\t * @param array{time?: int, user?: int}|false $lock Lock state.\n\t * @param int                                 $post_id Post object ID.\n\t * @return array{self: array{href?: string}, author?: array{href: string, embeddable: true}} Links for the given term.\n\t */\n\tprotected function prepare_links( $lock, int $post_id ): array {\n\t\t$base  = $this->namespace . '/' . $this->rest_base;\n\t\t$links = [\n\t\t\t'self' => [\n\t\t\t\t'href' => rest_url( trailingslashit( $base ) . $post_id . '/lock' ),\n\t\t\t],\n\t\t];\n\n\t\tif ( ! empty( $lock ) ) {\n\t\t\t/** This filter is documented in wp-admin/includes/ajax-actions.php */\n\t\t\t$time_window = apply_filters( 'wp_check_post_lock_window', 150 );\n\n\t\t\tif ( isset( $lock['time'] ) && $lock['time'] > time() - $time_window && isset( $lock['user'] ) ) {\n\t\t\t\t$links['author'] = [\n\t\t\t\t\t'href'       => rest_url( \\sprintf( '%s/%s/%s', $this->namespace, 'users', $lock['user'] ) ),\n\t\t\t\t\t'embeddable' => true,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\treturn $links;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Media_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Media_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Media\\Base_Color;\nuse Google\\Web_Stories\\Media\\Types;\nuse WP_Error;\nuse WP_Post;\nuse WP_REST_Attachments_Controller;\nuse WP_REST_Request;\nuse WP_REST_Response;\n\n/**\n * Stories_Media_Controller class.\n *\n * @phpstan-import-type Links from \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller\n * @phpstan-type ResponseData array{\n *   media_details: array{\n *     width?: int,\n *     height?: int,\n *   }\n * }\n */\nclass Stories_Media_Controller extends WP_REST_Attachments_Controller implements Service, Delayed, Registerable {\n\t/**\n\t * Types instance.\n\t *\n\t * @var Types Types instance.\n\t */\n\tprivate Types $types;\n\n\t/**\n\t * Constructor.\n\t *\n\t * Override the namespace.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Types $types Types instance.\n\t */\n\tpublic function __construct( Types $types ) {\n\t\tparent::__construct( 'attachment' );\n\t\t$this->namespace = 'web-stories/v1';\n\t\t$this->types     = $types;\n\t}\n\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_routes();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'rest_api_init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 100;\n\t}\n\n\t/**\n\t * Retrieves a collection of media.\n\t *\n\t * Read _web_stories_envelope param to envelope response.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{_embed?: string|string[], _web_stories_envelope?: bool}> $request\n\t */\n\tpublic function get_items( $request ) {\n\t\t$response = parent::get_items( $request );\n\n\t\tif ( $request['_web_stories_envelope'] && ! is_wp_error( $response ) ) {\n\t\t\t$embed    = $request['_embed'] ?? false;\n\t\t\t$embed    = $embed ? rest_parse_embed_param( $embed ) : false;\n\t\t\t$response = rest_get_server()->envelope_response( $response, $embed );\n\t\t}\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Creates a single attachment.\n\t *\n\t * Override the existing method so we can set parent id.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{post?: int, original_id?: int}> $request\n\t */\n\tpublic function create_item( $request ) {\n\t\t// WP_REST_Attachments_Controller doesn't allow setting an attachment as the parent post.\n\t\t// Hence we are working around this here.\n\n\t\t$parent_post = ! empty( $request['post'] ) ? $request['post'] : null;\n\n\t\t$original_id = ! empty( $request['original_id'] ) ? $request['original_id'] : null;\n\n\t\tunset( $request['post'] );\n\n\t\t$response = parent::create_item( $request );\n\t\tif ( ( ! $parent_post && ! $original_id ) || is_wp_error( $response ) ) {\n\t\t\treturn $response;\n\t\t}\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string,mixed> $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\t/**\n\t\t * Post ID.\n\t\t *\n\t\t * @var int $post_id\n\t\t */\n\t\t$post_id = $data['id'];\n\n\t\t$attachment = $this->process_post( $post_id, $parent_post, $original_id );\n\t\tif ( is_wp_error( $attachment ) ) {\n\t\t\treturn $attachment;\n\t\t}\n\n\t\t$new_response = $this->prepare_item_for_response( $attachment, $request );\n\n\t\t$data = $new_response->get_data();\n\t\t$response->set_data( $data );\n\n\t\treturn $response;\n\t}\n\n\t/**\n\t * Retrieves the query params for the posts collection.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['_web_stories_envelope'] = [\n\t\t\t'description' => __( 'Envelope request for preloading.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t\t'default'     => false,\n\t\t];\n\n\t\treturn $query_params;\n\t}\n\n\t/**\n\t * Prepares a single attachment output for response.\n\t *\n\t * @since 1.7.2\n\t *\n\t * @param WP_Post         $post    Attachment object.\n\t * @param WP_REST_Request $request Request object.\n\t * @return WP_REST_Response Response object.\n\t */\n\tpublic function prepare_item_for_response( $post, $request ): WP_REST_Response {\n\t\t$response = parent::prepare_item_for_response( $post, $request );\n\n\t\t/**\n\t\t * Response data.\n\t\t *\n\t\t * @var array<string, string|array<string, int|string>|bool> $data\n\t\t * @phpstan-var ResponseData $data\n\t\t */\n\t\t$data = $response->get_data();\n\n\t\t$fields = $this->get_fields_for_response( $request );\n\n\t\tif ( rest_is_field_included( 'media_details', $fields ) ) {\n\t\t\t// Could also be a stdClass if empty.\n\t\t\t$data['media_details'] = (array) $data['media_details'];\n\n\t\t\tif ( empty( $data['media_details']['width'] ) ) {\n\t\t\t\t$data['media_details']['width'] = 150;\n\t\t\t}\n\n\t\t\tif ( empty( $data['media_details']['height'] ) ) {\n\t\t\t\t$data['media_details']['height'] = 150;\n\t\t\t}\n\t\t}\n\n\t\t$response->set_data( $data );\n\n\t\t/**\n\t\t * Filters an attachment returned from the REST API.\n\t\t *\n\t\t * Allows modification of the attachment right before it is returned.\n\t\t *\n\t\t * Note the filter is run after rest_prepare_attachment is run. This filter is designed to only target web stories rest api requests.\n\t\t *\n\t\t * @since 1.7.2\n\t\t *\n\t\t * @param WP_REST_Response $response The response object.\n\t\t * @param WP_Post          $post     The original attachment post.\n\t\t * @param WP_REST_Request  $request  Request used to generate the response.\n\t\t */\n\t\treturn apply_filters( 'web_stories_rest_prepare_attachment', $response, $post, $request );\n\t}\n\n\t/**\n\t * Retrieves the attachment's schema, conforming to JSON Schema.\n\t *\n\t * Removes some unneeded fields to improve performance by\n\t * avoiding some expensive database queries.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @return array<string, string|array<string, array<string,string|string[]>>> Item schema data.\n\t */\n\tpublic function get_item_schema(): array {\n\t\tif ( $this->schema ) {\n\t\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t\t}\n\n\t\t$schema = parent::get_item_schema();\n\n\t\tunset(\n\t\t\t$schema['properties']['permalink_template'],\n\t\t\t$schema['properties']['generated_slug'],\n\t\t\t$schema['properties']['description']\n\t\t);\n\n\t\t$schema['properties']['original_id'] = [\n\t\t\t'description' => __( 'Unique identifier for original attachment id.', 'web-stories' ),\n\t\t\t'type'        => 'integer',\n\t\t\t'context'     => [ 'view', 'edit', 'embed' ],\n\t\t];\n\n\t\t$this->schema = $schema;\n\n\t\treturn $this->add_additional_fields_schema( $this->schema );\n\t}\n\n\n\t/**\n\t * Process post to update attribute.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param int      $post_id Post id.\n\t * @param int|null $parent_post New post parent. Default null.\n\t * @param int|null $original_id Original id to copy data from. Default null.\n\t * @return WP_Post|WP_Error\n\t */\n\tprotected function process_post( $post_id, $parent_post, $original_id ) {\n\t\t$args = [ 'ID' => $post_id ];\n\n\t\tif ( $parent_post ) {\n\t\t\t$args['post_parent'] = $parent_post;\n\t\t}\n\n\t\tif ( $original_id ) {\n\t\t\t$attachment_post = $this->get_post( (int) $original_id );\n\t\t\tif ( is_wp_error( $attachment_post ) ) {\n\t\t\t\treturn $attachment_post;\n\t\t\t}\n\t\t\t$args['post_content'] = $attachment_post->post_content;\n\t\t\t$args['post_excerpt'] = $attachment_post->post_excerpt;\n\t\t\t$args['post_title']   = $attachment_post->post_title;\n\n\t\t\t$meta_fields = [ '_wp_attachment_image_alt', Base_Color::BASE_COLOR_POST_META_KEY ];\n\t\t\tforeach ( $meta_fields as $meta_field ) {\n\t\t\t\t/**\n\t\t\t\t * Meta value.\n\t\t\t\t *\n\t\t\t\t * @var string $value\n\t\t\t\t */\n\t\t\t\t$value = get_post_meta( $original_id, $meta_field, true );\n\n\t\t\t\tif ( ! empty( $value ) ) {\n\t\t\t\t\t// update_post_meta() expects slashed.\n\t\t\t\t\tupdate_post_meta( $post_id, $meta_field, wp_slash( $value ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$attachment_id = wp_update_post( $args, true );\n\t\tif ( is_wp_error( $attachment_id ) ) {\n\t\t\tif ( 'db_update_error' === $attachment_id->get_error_code() ) {\n\t\t\t\t$attachment_id->add_data( [ 'status' => 500 ] );\n\t\t\t} else {\n\t\t\t\t$attachment_id->add_data( [ 'status' => 400 ] );\n\t\t\t}\n\n\t\t\treturn $attachment_id;\n\t\t}\n\n\t\treturn $this->get_post( $attachment_id );\n\t}\n\n\t/**\n\t * Filter request by allowed mime types.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param array<string,mixed> $prepared_args Optional. Array of prepared arguments. Default empty array.\n\t * @param WP_REST_Request     $request       Optional. Request to prepare items for.\n\t * @return array<string, mixed> Array of query arguments.\n\t */\n\tprotected function prepare_items_query( $prepared_args = [], $request = null ): array {\n\t\t$query_args = parent::prepare_items_query( $prepared_args, $request );\n\n\t\tif ( empty( $request['mime_type'] ) && empty( $request['media_type'] ) ) {\n\t\t\t$media_types      = $this->get_media_types();\n\t\t\t$media_type_mimes = array_values( $media_types );\n\t\t\t$media_type_mimes = array_filter( $media_type_mimes );\n\t\t\t$media_type_mimes = array_merge( ...$media_type_mimes );\n\n\t\t\t$query_args['post_mime_type'] = $media_type_mimes;\n\t\t}\n\n\t\t/**\n\t\t * Filters WP_Query arguments when querying posts via the REST API.\n\t\t *\n\t\t * @since 1.10.0\n\t\t *\n\t\t * @see WP_Query\n\t\t *\n\t\t * @param array                $args    Array of arguments for WP_Query.\n\t\t * @param WP_REST_Request|null $request The REST API request.\n\t\t */\n\t\treturn apply_filters( 'web_stories_rest_attachment_query', $query_args, $request );\n\t}\n\n\t/**\n\t * Retrieves the supported media types.\n\t *\n\t * Media types are considered the MIME type category.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return array<string, string[]> Array of supported media types.\n\t */\n\tprotected function get_media_types(): array {\n\t\t$mime_type = $this->types->get_allowed_mime_types();\n\t\t// TODO: Update once audio elements are supported.\n\t\t$mime_type['audio'] = [];\n\t\tunset( $mime_type['caption'] );\n\n\t\treturn $mime_type;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Settings_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Settings_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse WP_REST_Settings_Controller;\n\n/**\n * Stories_Settings_Controller class.\n */\nclass Stories_Settings_Controller extends WP_REST_Settings_Controller implements Service, Delayed, Registerable {\n\t/**\n\t * Constructor.\n\t *\n\t * Override the namespace.\n\t *\n\t * @since 1.2.0\n\t */\n\tpublic function __construct() {\n\t\tparent::__construct();\n\t\t$this->namespace = 'web-stories/v1';\n\t}\n\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_routes();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'rest_api_init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 100;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Taxonomies_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Taxonomies_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Taxonomies_Controller;\nuse WP_Taxonomy;\n\n/**\n * Stories_Taxonomies_Controller class.\n *\n * @phpstan-import-type Links from \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller\n */\nclass Stories_Taxonomies_Controller extends WP_REST_Taxonomies_Controller implements Service, Delayed, Registerable {\n\t/**\n\t * Constructor.\n\t *\n\t * Override the namespace.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function __construct() {\n\t\tparent::__construct();\n\t\t$this->namespace = 'web-stories/v1';\n\t}\n\n\t/**\n\t * Retrieves all public taxonomies.\n\t *\n\t * Adds support for filtering by the hierarchical attribute.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t *\n\t * @phpstan-param WP_REST_Request<array{type?: string, hierarchical?: bool, show_ui?: bool, context: string}> $request\n\t */\n\tpublic function get_items( $request ) {\n\t\t// Retrieve the list of registered collection query parameters.\n\t\t$registered = $this->get_collection_params();\n\n\t\tif ( isset( $registered['type'] ) && ! empty( $request['type'] ) ) {\n\t\t\t$type = $request['type'];\n\n\t\t\t$taxonomies = get_object_taxonomies( $type, 'objects' );\n\t\t} else {\n\t\t\t$taxonomies = get_taxonomies( [], 'objects' );\n\t\t}\n\n\t\t$filters = [ 'hierarchical', 'show_ui' ];\n\t\tforeach ( $filters as $filter ) {\n\t\t\tif ( isset( $registered[ $filter ], $request[ $filter ] ) ) {\n\t\t\t\t$taxonomies = wp_filter_object_list( $taxonomies, [ $filter => (bool) $request[ $filter ] ] );\n\t\t\t}\n\t\t}\n\t\t$data = [];\n\n\t\t/**\n\t\t * Taxonomy.\n\t\t *\n\t\t * @var WP_Taxonomy $value\n\t\t */\n\t\tforeach ( $taxonomies as $tax_type => $value ) {\n\t\t\tif (\n\t\t\t\tempty( $value->show_in_rest ) ||\n\t\t\t\t( 'edit' === $request['context'] && ! current_user_can( $value->cap->assign_terms ) ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$tax               = $this->prepare_item_for_response( $value, $request );\n\t\t\t$tax               = $this->prepare_response_for_collection( $tax );\n\t\t\t$data[ $tax_type ] = $tax;\n\t\t}\n\n\t\tif ( empty( $data ) ) {\n\t\t\t// Response should still be returned as a JSON object when it is empty.\n\t\t\t$data = (object) $data;\n\t\t}\n\n\t\treturn rest_ensure_response( $data );\n\t}\n\n\t/**\n\t * Retrieves the query params for collections.\n\t *\n\t * Adds support for filtering by the hierarchical attribute.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @return array<string, array<string, mixed>> Collection parameters.\n\t */\n\tpublic function get_collection_params(): array {\n\t\t$query_params = parent::get_collection_params();\n\n\t\t$query_params['per_page']['default'] = 100;\n\n\t\t$query_params['hierarchical'] = [\n\t\t\t'description' => __( 'Whether to show only hierarchical taxonomies.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t];\n\n\t\t$query_params['show_ui'] = [\n\t\t\t'description' => __( 'Whether to show only show taxonomies that allow a UI in the admin.', 'web-stories' ),\n\t\t\t'type'        => 'boolean',\n\t\t];\n\n\t\treturn $query_params;\n\t}\n\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_routes();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'rest_api_init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 100;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Terms_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Terms_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse WP_REST_Terms_Controller;\nuse WP_Term;\n\n/**\n * Stories_Terms_Controller class.\n */\nclass Stories_Terms_Controller extends WP_REST_Terms_Controller {\n\t/**\n\t * Override the existing prepare_links to ensure that all links have the correct namespace.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_Term $term Term object.\n\t * @return array<string, array{href?: string, taxonomy?: string, embeddable?: bool}> Links for the given term.\n\t */\n\tprotected function prepare_links( $term ): array {\n\t\t$links          = parent::prepare_links( $term );\n\t\t$links['about'] = [\n\t\t\t'href' => rest_url( \\sprintf( '%s/taxonomies/%s', $this->namespace, $this->taxonomy ) ),\n\t\t];\n\n\t\treturn $links;\n\t}\n}\n"
  },
  {
    "path": "includes/REST_API/Stories_Users_Controller.php",
    "content": "<?php\n/**\n * Class Stories_Users_Controller\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\REST_API;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Users_Controller;\n\n/**\n * Stories_Users_Controller class.\n */\nclass Stories_Users_Controller extends WP_REST_Users_Controller implements Service, Delayed, Registerable {\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * Override the namespace.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\tparent::__construct();\n\t\t$this->namespace = 'web-stories/v1';\n\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Register the service.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_routes();\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'rest_api_init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 100;\n\t}\n\n\t/**\n\t * Permissions check for getting all users.\n\t *\n\t * Allows edit_posts capabilities queries for stories if the user has the same cap,\n\t * enabling them to see the users dropdown.\n\t *\n\t * @since 1.28.1\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access, otherwise WP_Error object.\n\t */\n\tpublic function get_items_permissions_check( $request ) {\n\t\t/**\n\t\t * The edit_posts capability.\n\t\t *\n\t\t * @var string $edit_posts\n\t\t */\n\t\t$edit_posts = $this->story_post_type->get_cap_name( 'edit_posts' );\n\n\t\tif (\n\t\t\t! empty( $request['capabilities'] ) &&\n\t\t\t[ $edit_posts ] === $request['capabilities'] &&\n\t\t\tcurrent_user_can( $edit_posts ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t) {\n\t\t\tunset( $request['capabilities'] );\n\t\t}\n\n\t\treturn parent::get_items_permissions_check( $request );\n\t}\n\n\t/**\n\t * Retrieves all users.\n\t *\n\t * Includes a workaround for a shortcoming in WordPress core where\n\t * only users with published posts are returned if not an admin\n\t * and not using a 'who' -> 'authors' query, since we're using\n\t * the recommended capabilities queries instead.\n\t *\n\t * @since 1.28.1\n\t *\n\t * @link https://github.com/WordPress/wordpress-develop/blob/008277583be15ee1738fba51ad235af5bbc5d721/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php#L308-L312\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.\n\t */\n\tpublic function get_items( $request ) {\n\t\t/**\n\t\t * The edit_posts capability.\n\t\t *\n\t\t * @var string $edit_posts\n\t\t */\n\t\t$edit_posts = $this->story_post_type->get_cap_name( 'edit_posts' );\n\n\t\tif (\n\t\t\t! isset( $request['has_published_posts'] ) &&\n\t\t\t! empty( $request['capabilities'] ) &&\n\t\t\t[ $edit_posts ] === $request['capabilities'] &&\n\t\t\tcurrent_user_can( $edit_posts ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined\n\t\t) {\n\t\t\tadd_filter( 'rest_user_query', [ $this, 'filter_query_args' ] );\n\t\t\t$response = parent::get_items( $request );\n\t\t\tremove_filter( 'rest_user_query', [ $this, 'filter_query_args' ] );\n\n\t\t\treturn $response;\n\t\t}\n\n\t\treturn parent::get_items( $request );\n\t}\n\n\t/**\n\t * Filters WP_User_Query arguments when querying users via the REST API.\n\t *\n\t * Removes 'has_published_posts' query argument.\n\t *\n\t * @since 1.28.1\n\t *\n\t * @param array<string,mixed> $prepared_args Array of arguments for WP_User_Query.\n\t * @return array<string,mixed> Filtered query args.\n\t */\n\tpublic function filter_query_args( array $prepared_args ): array {\n\t\tunset( $prepared_args['has_published_posts'] );\n\n\t\treturn $prepared_args;\n\t}\n\n\t/**\n\t * Checks if a given request has access to read a user.\n\t *\n\t * Same as the parent function but with using a cached version of {@see count_user_posts()}.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @see WP_REST_Users_Controller::get_item_permissions_check()\n\t *\n\t * @param WP_REST_Request $request Full details about the request.\n\t * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object.\n\t */\n\tpublic function get_item_permissions_check( $request ) {\n\t\t/**\n\t\t * User ID.\n\t\t *\n\t\t * @var int $user_id\n\t\t */\n\t\t$user_id = $request['id'];\n\n\t\t$user = $this->get_user( $user_id );\n\t\tif ( is_wp_error( $user ) ) {\n\t\t\treturn $user;\n\t\t}\n\n\t\tif ( get_current_user_id() === $user->ID ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_user_cannot_view',\n\t\t\t\t__( 'Sorry, you are not allowed to list users.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\tif ( ! $this->user_posts_count_public( $user->ID, $this->story_post_type->get_slug() ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) {\n\t\t\treturn new \\WP_Error(\n\t\t\t\t'rest_user_cannot_view',\n\t\t\t\t__( 'Sorry, you are not allowed to list users.', 'web-stories' ),\n\t\t\t\t[ 'status' => rest_authorization_required_code() ]\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Number of posts user has written.\n\t *\n\t * Wraps {@see count_user_posts()} results in a cache.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.10.0\n\t *\n\t * @link https://core.trac.wordpress.org/ticket/39242\n\t *\n\t * @param int    $userid      User ID.\n\t * @param string $post_type   Optional. Single post type or array of post types to count the number of posts for. Default 'post'.\n\t * @return int Number of posts the user has written in this post type.\n\t */\n\tprotected function user_posts_count_public( int $userid, string $post_type = 'post' ): int {\n\t\t$cache_key   = \"count_user_{$post_type}_{$userid}\";\n\t\t$cache_group = 'user_posts_count';\n\n\t\t/**\n\t\t * Post count.\n\t\t *\n\t\t * @var string|false $count\n\t\t */\n\t\t$count = wp_cache_get( $cache_key, $cache_group );\n\t\tif ( false === $count ) {\n\t\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.count_user_posts_count_user_posts\n\t\t\t$count = count_user_posts( $userid, $post_type, true );\n\t\t\twp_cache_add( $cache_key, $count, $cache_group );\n\t\t}\n\n\t\treturn (int) $count;\n\t}\n}\n"
  },
  {
    "path": "includes/Register_Widget.php",
    "content": "<?php\n/**\n * Class Register_Widget.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Widgets\\Stories;\n\n/**\n * Class RegisterWidget\n */\nclass Register_Widget extends Service_Base {\n\t/**\n\t * Stories instance.\n\t *\n\t * @var Stories Stories instance.\n\t */\n\tprivate Stories $stories;\n\n\t/**\n\t * Register_Widget constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Stories $stories Stories instance.\n\t */\n\tpublic function __construct( Stories $stories ) {\n\t\t$this->stories = $stories;\n\t}\n\n\t/**\n\t * Register Widgets.\n\t *\n\t * @since 1.6.0\n\t */\n\tpublic function register(): void {\n\t\tadd_action( 'widgets_init', [ $this, 'register_widgets' ] );\n\t\tadd_filter( 'widget_types_to_hide_from_legacy_widget_block', [ $this, 'hide_widget' ] );\n\t\tadd_filter( 'body_class', [ $this, 'body_class' ] );\n\t}\n\n\t/**\n\t * Register widget.\n\t *\n\t * @since 1.9.0\n\t */\n\tpublic function register_widgets(): void {\n\t\tregister_widget( $this->stories );\n\t}\n\n\t/**\n\t * Hide widget stories from legacy widget list.\n\t *\n\t * @since 1.9.0\n\t *\n\t * @param array|mixed $widget_types An array of excluded widget-type IDs.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($widget_types is array<T> ? array<T> : mixed)\n\t */\n\tpublic function hide_widget( $widget_types ) {\n\t\tif ( ! \\is_array( $widget_types ) ) {\n\t\t\treturn $widget_types;\n\t\t}\n\t\t$widget_types[] = $this->stories->id_base;\n\n\t\treturn $widget_types;\n\t}\n\n\t/**\n\t * Filters the list of CSS body class names for embedded iframes to add a class.\n\t *\n\t * @since 1.9.0\n\t *\n\t * @param string[]|mixed $classes An array of body class names.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($classes is array<T> ? array<T> : mixed)\n\t */\n\tpublic function body_class( $classes ) {\n\t\tif ( ! \\is_array( $classes ) ) {\n\t\t\treturn $classes;\n\t\t}\n\t\tif ( is_admin() && \\defined( 'IFRAME_REQUEST' ) && IFRAME_REQUEST ) {\n\t\t\t$classes[] = 'ws-legacy-widget-preview';\n\t\t}\n\n\t\treturn $classes;\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.38.1\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\t// Because wp_widgets_init() runs on priority 1.\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "includes/Remove_Transients.php",
    "content": "<?php\n/**\n * Remove Transients class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\n/**\n * Remove Transients class.\n */\nclass Remove_Transients implements Service, PluginUninstallAware {\n\tprotected const PREFIX = 'web_stories\\_%';\n\n\t/**\n\t * Delete network and site transients.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tif ( wp_using_ext_object_cache() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! is_multisite() ) {\n\t\t\t$this->delete_transients();\n\t\t\treturn;\n\t\t}\n\n\t\t$this->delete_network_transients();\n\t\t$site_ids = get_sites(\n\t\t\t[\n\t\t\t\t'fields'                 => 'ids',\n\t\t\t\t'number'                 => 0,\n\t\t\t\t'update_site_cache'      => false,\n\t\t\t\t'update_site_meta_cache' => false,\n\t\t\t]\n\t\t);\n\n\t\tforeach ( $site_ids as $site_id ) {\n\t\t\t// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog\n\t\t\tswitch_to_blog( $site_id );\n\n\t\t\t$this->delete_transients();\n\t\t}\n\n\t\trestore_current_blog();\n\t}\n\n\t/**\n\t * Delete transients.\n\t *\n\t * @since 1.26.0\n\t */\n\tprotected function delete_transients(): void {\n\t\tglobal $wpdb;\n\n\t\t// phpcs:ignore WordPress.DB.DirectDatabaseQuery\n\t\t$transients = $wpdb->get_col(\n\t\t\t$wpdb->prepare(\n\t\t\t\t\"SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s OR option_name LIKE %s\",\n\t\t\t\t'_transient_' . self::PREFIX,\n\t\t\t\t'_transient_timeout_' . self::PREFIX\n\t\t\t)\n\t\t);\n\n\t\tif ( ! empty( $transients ) ) {\n\t\t\tarray_map( 'delete_option', (array) $transients );\n\t\t}\n\t}\n\n\t/**\n\t * Delete transients on multisite.\n\t *\n\t * @since 1.26.0\n\t */\n\tprotected function delete_network_transients(): void {\n\t\tglobal $wpdb;\n\n\t\t// phpcs:ignore WordPress.DB.DirectDatabaseQuery\n\t\t$transients = $wpdb->get_col(\n\t\t\t$wpdb->prepare(\n\t\t\t\t\"SELECT meta_key FROM $wpdb->sitemeta WHERE meta_key LIKE %s OR meta_key LIKE %s\",\n\t\t\t\t'_site_transient_' . self::PREFIX,\n\t\t\t\t'_site_transient_timeout_' . self::PREFIX\n\t\t\t)\n\t\t);\n\n\t\tif ( ! empty( $transients ) ) {\n\t\t\tarray_map( 'delete_site_option', (array) $transients );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Archives.php",
    "content": "<?php\n/**\n * Class Archives\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Embed;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Class Archives\n */\nclass Archives extends Service_Base {\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprotected Assets $assets;\n\n\t/**\n\t * AMP_Story_Player_Assets instance.\n\t *\n\t * @var AMP_Story_Player_Assets AMP_Story_Player_Assets instance.\n\t */\n\tprotected AMP_Story_Player_Assets $amp_story_player_assets;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprotected Context $context;\n\n\t/**\n\t * Archives constructor.\n\t *\n\t * @since 1.8.0\n\t *\n\t * @param Assets                  $assets            Assets instance.\n\t * @param AMP_Story_Player_Assets $amp_story_player_assets AMP_Story_Player_Assets instance.\n\t * @param Context                 $context                 Context instance.\n\t */\n\tpublic function __construct( Assets $assets, AMP_Story_Player_Assets $amp_story_player_assets, Context $context ) {\n\t\t$this->assets                  = $assets;\n\t\t$this->amp_story_player_assets = $amp_story_player_assets;\n\t\t$this->context                 = $context;\n\t}\n\n\t/**\n\t * Filter content and excerpt for search and post type archive.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'the_content', [ $this, 'embed_player' ], PHP_INT_MAX );\n\t\tadd_filter( 'the_excerpt', [ $this, 'embed_player' ], PHP_INT_MAX );\n\t}\n\n\t/**\n\t * Change the content to an embedded player\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $content Current content of filter.\n\t * @return string|mixed\n\t */\n\tpublic function embed_player( $content ) {\n\t\t$post = get_post();\n\n\t\tif ( is_feed() ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\tif ( ! is_search() && ! is_post_type_archive( Story_Post_Type::POST_TYPE_SLUG ) ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\tif ( $post instanceof WP_Post && Story_Post_Type::POST_TYPE_SLUG === $post->post_type ) {\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $post );\n\n\t\t\t$embed   = new Embed( $story, $this->assets, $this->context );\n\t\t\t$content = $embed->render();\n\t\t}\n\n\t\treturn $content;\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Feed.php",
    "content": "<?php\n/**\n * Class Feed\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Image;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Class Feed\n */\nclass Feed extends Service_Base {\n\n\t/**\n\t * Filter RSS content fields.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'the_content_feed', [ $this, 'embed_image' ] );\n\t\tadd_filter( 'the_excerpt_rss', [ $this, 'embed_image' ] );\n\t}\n\n\t/**\n\t * Filter feed content for stories to render as an image.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $content Feed content.\n\t * @return string|mixed\n\t */\n\tpublic function embed_image( $content ) {\n\t\t$post = get_post();\n\n\t\tif ( $post instanceof WP_Post && Story_Post_Type::POST_TYPE_SLUG === $post->post_type ) {\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $post );\n\n\t\t\t$image   = new Image( $story );\n\t\t\t$content = $image->render();\n\t\t}\n\n\t\treturn $content;\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Oembed.php",
    "content": "<?php\n/**\n * Class Oembed\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_Post;\n\n/**\n * Class Oembed\n */\nclass Oembed extends Service_Base {\n\n\t/**\n\t * Filter to render oembed.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'embed_template', [ $this, 'filter_embed_template' ] );\n\t\tadd_filter( 'embed_html', [ $this, 'filter_embed_html' ], 10, 4 );\n\t\t// So it runs after get_oembed_response_data_rich().\n\t\tadd_filter( 'oembed_response_data', [ $this, 'filter_oembed_response_data' ], 20, 3 );\n\t}\n\n\t/**\n\t * Filters the path of the queried template by type.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param string|mixed $template  Path to the template. See locate_template().\n\t * @return string|mixed $template\n\t */\n\tpublic function filter_embed_template( $template ) {\n\t\tif ( get_post_type() === Story_Post_Type::POST_TYPE_SLUG ) {\n\t\t\t$template = WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/frontend/embed-web-story.php';\n\t\t}\n\n\t\treturn $template;\n\t}\n\n\t/**\n\t * Filters the embed code for a specific post.\n\t *\n\t * For stories, changes the aspect ratio from 16/9 to 3/5.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param string|mixed $output Embed code.\n\t * @param WP_Post      $post Post object.\n\t * @param int          $width  The width for the response.\n\t * @param int          $height The height for the response.\n\t * @return string|mixed Filtered embed code.\n\t *\n\t * @phpstan-return ($output is string ? string : mixed)\n\t */\n\tpublic function filter_embed_html( $output, WP_Post $post, int $width, int $height ) {\n\t\tif ( ! \\is_string( $output ) ) {\n\t\t\treturn $output;\n\t\t}\n\n\t\tif ( Story_Post_Type::POST_TYPE_SLUG !== $post->post_type ) {\n\t\t\treturn $output;\n\t\t}\n\n\t\tif ( ! has_post_thumbnail( $post ) ) {\n\t\t\treturn $output;\n\t\t}\n\n\t\t$new_data = $this->get_embed_height_width( $width );\n\n\t\t$new_width  = $new_data['width'];\n\t\t$new_height = $new_data['height'];\n\n\t\treturn str_replace(\n\t\t\t[ \"width=\\\"$width\\\"\", \"height=\\\"$height\\\"\" ],\n\t\t\t[\n\t\t\t\t\"width=\\\"$new_width\\\"\",\n\t\t\t\t\"height=\\\"$new_height\\\"\",\n\t\t\t],\n\t\t\t$output\n\t\t);\n\t}\n\n\t/**\n\t * Filters the oEmbed response data for a specific post.\n\t *\n\t * For stories, changes the aspect ratio from 16/9 to 3/5.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param array|mixed $data   The response data.\n\t * @param WP_Post     $post   The post object.\n\t * @param int         $width  The requested width.\n\t * @return array|mixed The modified response data.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($data is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_oembed_response_data( $data, WP_Post $post, int $width ) {\n\t\tif ( Story_Post_Type::POST_TYPE_SLUG !== $post->post_type ) {\n\t\t\treturn $data;\n\t\t}\n\n\t\tif ( ! has_post_thumbnail( $post ) ) {\n\t\t\treturn $data;\n\t\t}\n\t\tif ( ! \\is_array( $data ) ) {\n\t\t\treturn $data;\n\t\t}\n\t\t$new_data = $this->get_embed_height_width( $width );\n\n\t\treturn array_merge( $data, $new_data );\n\t}\n\n\t/**\n\t * Generate new height and width for embed.\n\t *\n\t * @since 1.7.0\n\t *\n\t * @param int $old_width Old width, used to generate new height and width.\n\t * @return array{width: int, height: int}\n\t */\n\tprotected function get_embed_height_width( int $old_width ): array {\n\t\t/** This filter is documented in wp-includes/embed.php */\n\t\t$min_max_width = apply_filters(\n\t\t\t'oembed_min_max_width',\n\t\t\t[\n\t\t\t\t'min' => 200,\n\t\t\t\t'max' => 360,\n\t\t\t]\n\t\t);\n\n\t\t$width  = (int) min( max( $min_max_width['min'], $old_width ), $min_max_width['max'] );\n\t\t$height = (int) max( ceil( $width / 3 * 5 ), 330 );\n\n\t\treturn compact( 'width', 'height' );\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Single.php",
    "content": "<?php\n/**\n * Class Single\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer;\n\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * Class Single\n */\nclass Single extends Service_Base {\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Single constructor.\n\t *\n\t * @param Context $context Context instance.\n\t */\n\tpublic function __construct( Context $context ) {\n\t\t$this->context = $context;\n\t}\n\n\t/**\n\t * Initializes the Single logic.\n\t *\n\t * @since 1.7.0\n\t */\n\tpublic function register(): void {\n\t\t// This is hooked to both the `template_include` and the `single_template` filters,\n\t\t// as an additional measure to improve compatibility with themes\n\t\t// overriding the template hierarchy in an unusual way, like the Sage theme does.\n\t\tadd_filter( 'single_template', [ $this, 'filter_template_include' ], PHP_INT_MAX );\n\t\tadd_filter( 'template_include', [ $this, 'filter_template_include' ], PHP_INT_MAX );\n\n\t\tadd_filter( 'show_admin_bar', [ $this, 'show_admin_bar' ] ); // phpcs:ignore WordPressVIPMinimum.UserExperience.AdminBarRemoval.RemovalDetected\n\t}\n\n\t/**\n\t * Filters the path of the queried template for single stories.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string|mixed $template Absolute path to template file.\n\t * @return string|mixed Filtered template file path.\n\t */\n\tpublic function filter_template_include( $template ) {\n\t\tif ( $this->context->is_web_story() ) {\n\t\t\treturn WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/frontend/single-web-story.php';\n\t\t}\n\n\t\treturn $template;\n\t}\n\n\t/**\n\t * Filter if show admin bar on single post type.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param bool|mixed $show Current value of filter.\n\t * @return bool|mixed\n\t */\n\tpublic function show_admin_bar( $show ) {\n\t\tif ( $this->context->is_web_story() ) {\n\t\t\t$show = false;\n\t\t}\n\n\t\treturn $show;\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/Carousel_Renderer.php",
    "content": "<?php\n/**\n * Carousel_Renderer class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories;\n\n/**\n * Carousel_Renderer class.\n *\n * Note: This class is useful to render stories in carousel view type.\n * Do not instantiate this class directly, pass `view_type` argument\n * to `Story_Query` which will handle the instantiation of the class.\n */\nclass Carousel_Renderer extends Renderer {\n\n\t/**\n\t * Script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-carousel';\n\n\t/**\n\t * Perform initial setup for object.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function init(): void {\n\n\t\tparent::init();\n\n\t\t$this->load_assets();\n\t}\n\n\t/**\n\t * Enqueue assets.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function load_assets(): void {\n\t\tparent::load_assets();\n\n\t\t$this->assets->register_script_asset( self::SCRIPT_HANDLE, [], false );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStoriesCarouselSettings',\n\t\t\t$this->get_carousel_settings()\n\t\t);\n\t}\n\n\t/**\n\t * Renders the stories output for given attributes.\n\t *\n\t * @SuppressWarnings(\"PHPMD.UnusedLocalVariable\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Array of rendering arguments.\n\t * @return string Rendered stories output.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\tif ( ! $this->valid() ) {\n\t\t\treturn '';\n\t\t}\n\n\t\tparent::render( $args );\n\t\t$container_classes = $this->get_container_classes();\n\t\t$container_styles  = $this->get_container_styles();\n\n\t\tob_start();\n\t\t?>\n\t\t<div class=\"<?php echo esc_attr( $container_classes ); ?>\" data-id=\"<?php echo esc_attr( (string) $this->instance_id ); ?>\">\n\t\t\t<div\n\t\t\tclass=\"web-stories-list__inner-wrapper <?php echo esc_attr( 'carousel-' . $this->instance_id ); ?>\"\n\t\t\tstyle=\"<?php echo esc_attr( $container_styles ); ?>\"\n\t\t\t>\n\t\t\t\t<?php\n\t\t\t\t$this->maybe_render_archive_link();\n\n\t\t\t\tif ( ! $this->context->is_amp() ) {\n\t\t\t\t\t$this->assets->enqueue_script( self::SCRIPT_HANDLE );\n\t\t\t\t\t?>\n\t\t\t\t\t<div\n\t\t\t\t\tclass=\"web-stories-list__carousel <?php echo esc_attr( $this->get_view_type() ); ?>\"\n\t\t\t\t\tdata-id=\"<?php echo esc_attr( 'carousel-' . $this->instance_id ); ?>\"\n\t\t\t\t\tdata-prev=\"<?php esc_attr_e( 'Previous', 'web-stories' ); ?>\"\n\t\t\t\t\tdata-next=\"<?php esc_attr_e( 'Next', 'web-stories' ); ?>\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<?php\n\t\t\t\t\t\tarray_map(\n\t\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\t\t$this->render_single_story_content();\n\t\t\t\t\t\t\t\t$this->next();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t$this->stories\n\t\t\t\t\t\t);\n\t\t\t\t\t\t?>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div tabindex=\"0\" aria-label=\"<?php esc_attr_e( 'Previous', 'web-stories' ); ?>\" class=\"glider-prev\"></div>\n\t\t\t\t\t<div tabindex=\"0\" aria-label=\"<?php esc_attr_e( 'Next', 'web-stories' ); ?>\" class=\"glider-next\"></div>\n\t\t\t\t\t<?php\n\t\t\t\t} else {\n\t\t\t\t\t?>\n\t\t\t\t\t<amp-carousel\n\t\t\t\t\t\twidth=\"1\"\n\t\t\t\t\t\theight=\"1\"\n\t\t\t\t\t\tlayout=\"intrinsic\"\n\t\t\t\t\t\ttype=\"carousel\"\n\t\t\t\t\t\trole=\"region\"\n\t\t\t\t\t\taria-label=\"<?php esc_attr_e( 'Web Stories', 'web-stories' ); ?>\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<?php\n\t\t\t\t\t\tarray_map(\n\t\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\t\t$this->render_single_story_content();\n\t\t\t\t\t\t\t\t$this->next();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t$this->stories\n\t\t\t\t\t\t);\n\t\t\t\t\t\t?>\n\t\t\t\t\t</amp-carousel>\n\t\t\t\t\t<?php\n\t\t\t\t}\n\t\t\t\t?>\n\t\t\t</div>\n\t\t</div>\n\t\t<?php\n\t\t$content = (string) ob_get_clean();\n\n\t\t$content = wp_interactivity_process_directives( $content );\n\n\t\t/**\n\t\t * Filters the Carousel renderer stories content.\n\t\t *\n\t\t * @since 1.5.0\n\t\t *\n\t\t * @param string $content Stories content.\n\t\t */\n\t\treturn apply_filters( 'web_stories_carousel_renderer_stories_content', $content );\n\t}\n\n\t/**\n\t * Get Carousel settings.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string,array<string,bool>|string> Carousel settings.\n\t */\n\tprotected function get_carousel_settings(): array {\n\t\treturn [\n\t\t\t'config'     => [\n\t\t\t\t'isRTL' => is_rtl(),\n\t\t\t],\n\t\t\t'publicPath' => $this->assets->get_base_url( 'assets/js/' ),\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldState/BaseFieldState.php",
    "content": "<?php\n/**\n * Class BaseFieldState.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldState;\n\nuse Google\\Web_Stories\\Interfaces\\Field;\nuse Google\\Web_Stories\\Interfaces\\FieldState;\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class BaseFieldState.\n */\nclass BaseFieldState implements FieldState {\n\n\t/**\n\t * Post type has archive.\n\t */\n\tprotected bool $has_archive = false;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->has_archive = (bool) $story_post_type->get_has_archive();\n\t}\n\n\t/**\n\t * Image alignment FieldState.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function image_alignment() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Image Alignment', 'web-stories' ),\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Excerpt FieldState.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function excerpt() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Display Excerpt', 'web-stories' ),\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Author Field State.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function author() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Display Author', 'web-stories' ),\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Date field state.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function date() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Display Date', 'web-stories' ),\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Archive link field state.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function archive_link() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Display Archive Link', 'web-stories' ),\n\t\t\t\t'show'   => $this->has_archive,\n\t\t\t\t'hidden' => ! $this->has_archive,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Title field state.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function title() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Display Title', 'web-stories' ),\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Sharp corners field state.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Field\n\t */\n\tpublic function sharp_corners() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label'  => __( 'Use Sharp Corners', 'web-stories' ),\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Circle size field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return BaseField\n\t */\n\tpublic function circle_size() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label' => __( 'Circle Size', 'web-stories' ),\n\t\t\t\t'show'  => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Number of columns field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return BaseField\n\t */\n\tpublic function number_of_columns() {\n\t\treturn new BaseField(\n\t\t\t[\n\t\t\t\t'label' => __( 'Number of Columns', 'web-stories' ),\n\t\t\t\t'show'  => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Prepare a field object.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,bool|string> $args Arguments to build field.\n\t * @return BaseField\n\t */\n\tprotected function prepare_field( array $args ): BaseField {\n\t\treturn new BaseField( $args );\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldState/CarouselView.php",
    "content": "<?php\n/**\n * Carousel view based controls state.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldState;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField;\n\n/**\n * Class CarouselView.\n */\nfinal class CarouselView extends BaseFieldState {\n\n\t/**\n\t * Author field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function author() {\n\t\t$label = parent::author()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldState/CircleView.php",
    "content": "<?php\n/**\n * Circle view based controls state.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldState;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField;\n\n/**\n * Class CircleView.\n */\nfinal class CircleView extends BaseFieldState {\n\n\t/**\n\t * Title field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function title() {\n\t\t$label = parent::title()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Author field.\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function author() {\n\t\t$label = parent::author()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Date field.\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function date() {\n\t\t$label = parent::date()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Sharp corners field.\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function sharp_corners() {\n\t\t$label = parent::sharp_corners()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => false,\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Circle size field.\n\t *\n\t * @return BaseField\n\t */\n\tpublic function circle_size() {\n\t\t$label = parent::circle_size()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldState/GridView.php",
    "content": "<?php\n/**\n * List view based controls state.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldState;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField;\n\n/**\n * Class GridView.\n */\nfinal class GridView extends BaseFieldState {\n\t/**\n\t * Number of columns field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function number_of_columns() {\n\t\t$label = parent::number_of_columns()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldState/ListView.php",
    "content": "<?php\n/**\n * List view based controls state.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldState;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField;\n\n/**\n * Class ListView.\n */\nfinal class ListView extends BaseFieldState {\n\n\t/**\n\t * Excerpt field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function excerpt() {\n\t\t$label = parent::excerpt()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Author field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function date() {\n\t\t$label = parent::date()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Image alignment field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return \\Google\\Web_Stories\\Interfaces\\Field|BaseField\n\t */\n\tpublic function image_alignment() {\n\t\t$label = parent::image_alignment()->label();\n\n\t\treturn $this->prepare_field(\n\t\t\t[\n\t\t\t\t'label'  => $label,\n\t\t\t\t'show'   => true,\n\t\t\t\t'hidden' => false,\n\t\t\t]\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/FieldStateFactory/Factory.php",
    "content": "<?php\n/**\n * Field state factory.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\FieldStateFactory;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Interfaces\\FieldState;\nuse Google\\Web_Stories\\Interfaces\\FieldStateFactory;\nuse Google\\Web_Stories\\Renderer\\Stories\\FieldState\\CarouselView;\nuse Google\\Web_Stories\\Renderer\\Stories\\FieldState\\CircleView;\nuse Google\\Web_Stories\\Renderer\\Stories\\FieldState\\GridView;\nuse Google\\Web_Stories\\Renderer\\Stories\\FieldState\\ListView;\n\n/**\n * Class Factory\n */\nclass Factory implements FieldStateFactory {\n\n\t/**\n\t * Injector instance.\n\t *\n\t * @var Injector Injector instance.\n\t */\n\tprivate Injector $injector;\n\n\t/**\n\t * Factory constructor.\n\t *\n\t * @param Injector $injector Injector instance.\n\t */\n\tpublic function __construct( Injector $injector ) {\n\t\t$this->injector = $injector;\n\t}\n\n\t/**\n\t * Returns field state for the provided view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string $view View Type.\n\t * @return FieldState\n\t */\n\tpublic function get_field( $view = 'grid' ) {\n\t\tswitch ( $view ) {\n\t\t\tcase 'grid':\n\t\t\t\t/**\n\t\t\t\t * GridView instance.\n\t\t\t\t *\n\t\t\t\t * @var FieldState\n\t\t\t\t */\n\t\t\t\t$field_state = $this->injector->make( GridView::class );\n\t\t\t\tbreak;\n\t\t\tcase 'list':\n\t\t\t\t/**\n\t\t\t\t * ListView instance.\n\t\t\t\t *\n\t\t\t\t * @var FieldState\n\t\t\t\t */\n\t\t\t\t$field_state = $this->injector->make( ListView::class );\n\t\t\t\tbreak;\n\t\t\tcase 'circles':\n\t\t\t\t/**\n\t\t\t\t * CircleView instance.\n\t\t\t\t *\n\t\t\t\t * @var FieldState\n\t\t\t\t */\n\t\t\t\t$field_state = $this->injector->make( CircleView::class );\n\t\t\t\tbreak;\n\t\t\tcase 'carousel':\n\t\t\t\t/**\n\t\t\t\t * CarouselView instance.\n\t\t\t\t *\n\t\t\t\t * @var FieldState\n\t\t\t\t */\n\t\t\t\t$field_state = $this->injector->make( CarouselView::class );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t/**\n\t\t\t\t * CircleView instance.\n\t\t\t\t *\n\t\t\t\t * @var FieldState $default_field_state\n\t\t\t\t */\n\t\t\t\t$default_field_state = $this->injector->make( CircleView::class );\n\n\t\t\t\t/**\n\t\t\t\t * Filters the field state object.\n\t\t\t\t *\n\t\t\t\t * This depicts\n\t\t\t\t *\n\t\t\t\t * @since 1.5.0\n\t\t\t\t *\n\t\t\t\t * @param FieldState $default_field_state Field state object.\n\t\t\t\t */\n\t\t\t\t$field_state = apply_filters( 'web_stories_default_field_state', $default_field_state );\n\t\t}\n\n\t\treturn $field_state;\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/Fields/BaseField.php",
    "content": "<?php\n/**\n * Base field class.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories\\Fields;\n\nuse Google\\Web_Stories\\Interfaces\\Field;\n\n/**\n * Class BaseField.\n */\nclass BaseField implements Field {\n\t/**\n\t * Field label.\n\t */\n\tprivate string $label;\n\n\t/**\n\t * Whether the field is enabled.\n\t */\n\tprivate bool $hidden;\n\n\t/**\n\t * Whether to display the field.\n\t */\n\tprivate bool $show;\n\n\t/**\n\t * BaseField constructor.\n\t *\n\t * @param array<string,string|bool> $args Arguments.\n\t */\n\tpublic function __construct( array $args ) {\n\t\t$this->label  = isset( $args['label'] ) ? (string) $args['label'] : '';\n\t\t$this->hidden = ! isset( $args['hidden'] ) || $args['hidden'];\n\t\t$this->show   = ! isset( $args['show'] ) || $args['show'];\n\t}\n\n\t/**\n\t * Label for the field.\n\t *\n\t * @return string\n\t */\n\tpublic function label(): string {\n\t\treturn $this->label;\n\t}\n\n\t/**\n\t * Flag for field display.\n\t *\n\t * @return bool\n\t */\n\tpublic function show(): bool {\n\t\treturn $this->show;\n\t}\n\n\t/**\n\t * Whether the field is hidden.\n\t *\n\t * @return bool\n\t */\n\tpublic function hidden(): bool {\n\t\treturn $this->hidden;\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/Generic_Renderer.php",
    "content": "<?php\n/**\n * Generic_Renderer class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories;\n\n/**\n * Generic_Renderer class.\n *\n * This is named as `Generic` as this renderer class\n * will be used to output multiple view types, like:\n *\n * 1. Circle\n * 2. Grid\n * 3. List\n *\n * Since, markup for all these views type is similar, Generic Renderer\n * can be used to render the stories.\n */\nclass Generic_Renderer extends Renderer {\n\n\t/**\n\t * Perform initial setup for object.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function init(): void {\n\n\t\tparent::init();\n\n\t\t$this->load_assets();\n\t}\n\n\t/**\n\t * Renders the stories output for given attributes.\n\t *\n\t * @SuppressWarnings(\"PHPMD.UnusedLocalVariable\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Array of rendering arguments.\n\t * @return string Rendered stories output.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\tif ( ! $this->valid() ) {\n\t\t\treturn '';\n\t\t}\n\n\t\tparent::render( $args );\n\t\t$container_classes = $this->get_container_classes();\n\t\t$container_styles  = $this->get_container_styles();\n\n\t\tob_start();\n\t\t?>\n\t\t<div class=\"<?php echo esc_attr( $container_classes ); ?>\" data-id=\"<?php echo esc_attr( (string) $this->instance_id ); ?>\">\n\t\t\t<div class=\"web-stories-list__inner-wrapper\" style=\"<?php echo esc_attr( $container_styles ); ?>\">\n\t\t\t\t<?php\n\t\t\t\tarray_map(\n\t\t\t\t\tfunction () {\n\t\t\t\t\t\t$this->render_single_story_content();\n\t\t\t\t\t\t$this->next();\n\t\t\t\t\t},\n\t\t\t\t\t$this->stories\n\t\t\t\t);\n\t\t\t\t$this->maybe_render_archive_link();\n\t\t\t\t?>\n\t\t\t</div>\n\t\t</div>\n\t\t<?php\n\t\t$view_type = $this->get_view_type();\n\t\t$content   = (string) ob_get_clean();\n\n\t\t$content = wp_interactivity_process_directives( $content );\n\n\t\t/**\n\t\t * Filters the Generic renderer stories content.\n\t\t *\n\t\t * The dynamic portion of the hook `$this->get_view_type()` refers to the story view type.\n\t\t *\n\t\t * @since 1.5.0\n\t\t *\n\t\t * @param string $content Stories content.\n\t\t */\n\t\treturn apply_filters( \"web_stories_{$view_type}_renderer_stories_content\", $content );\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Stories/Renderer.php",
    "content": "<?php\n/**\n * Stories Renderer Base class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Stories;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Interfaces\\Renderer as RenderingInterface;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Services;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse Iterator;\nuse WP_Post;\n\n/**\n * Renderer class.\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n * @SuppressWarnings(\"PHPMD.TooManyPublicMethods\")\n *\n * @phpstan-import-type StoryAttributes from \\Google\\Web_Stories\\Story_Query\n *\n * @implements Iterator<int, Story>\n */\nabstract class Renderer implements RenderingInterface, Iterator {\n\t/**\n\t * Web Stories stylesheet handle.\n\t */\n\tpublic const STYLE_HANDLE = 'web-stories-list-styles';\n\n\t/**\n\t * Number of instances invoked. Kept it static to keep track.\n\t */\n\tprotected static int $instances = 0;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprotected Assets $assets;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprotected Context $context;\n\n\t/**\n\t * Object ID for the Renderer class.\n\t * To enable support for multiple carousels and lightboxes\n\t * on the same page, we needed to identify each Renderer instance.\n\t *\n\t * This variable is used to add appropriate class to the Web Stories\n\t * wrapper.\n\t */\n\tprotected int $instance_id = 0;\n\n\t/**\n\t * Story_Query instance.\n\t *\n\t * @var Story_Query Story_Query instance.\n\t */\n\tprotected Story_Query $query;\n\n\t/**\n\t * Story attributes\n\t *\n\t * @var array<string, string|int|bool> An array of story attributes.\n\t * @phpstan-var StoryAttributes\n\t */\n\tprotected array $attributes = [];\n\n\t/**\n\t * Story posts.\n\t *\n\t * @var Story[] An array of story posts.\n\t */\n\tprotected array $stories = [];\n\n\t/**\n\t * Holds required html for the lightbox.\n\t *\n\t * @var string A string of lightbox markup.\n\t */\n\tprotected string $lightbox_html = '';\n\n\t/**\n\t * Pointer to iterate over stories.\n\t */\n\tprivate int $position = 0;\n\n\t/**\n\t * Height for displaying story.\n\t */\n\tprotected int $height = 308;\n\n\t/**\n\t * Width for displaying story.\n\t */\n\tprotected int $width = 185;\n\n\t/**\n\t * Whether content overlay is enabled for story.\n\t */\n\tprotected bool $content_overlay;\n\n\t/**\n\t * Constructor\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param Story_Query $query Story_Query instance.\n\t */\n\tpublic function __construct( Story_Query $query ) {\n\t\t$this->query           = $query;\n\t\t$this->attributes      = $this->query->get_story_attributes();\n\t\t$this->content_overlay = $this->attributes['show_title'] || $this->attributes['show_date'] || $this->attributes['show_author'] || $this->attributes['show_excerpt'];\n\n\t\t// TODO, find a way to inject this a cleaner way.\n\t\t$injector = Services::get_injector();\n\n\t\t/**\n\t\t * Assets instance.\n\t\t *\n\t\t * @var Assets $assets Assets instance.\n\t\t */\n\t\t$assets = $injector->make( Assets::class );\n\n\t\t/**\n\t\t * Context instance.\n\t\t *\n\t\t * @var Context $context Context instance.\n\t\t */\n\t\t$context = $injector->make( Context::class );\n\n\t\t$this->assets  = $assets;\n\t\t$this->context = $context;\n\t}\n\n\t/**\n\t * Output markup for amp stories.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Array of rendering arguments.\n\t * @return string\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\t++self::$instances;\n\t\t$this->instance_id = self::$instances;\n\n\t\tforeach ( $args as $key => $val ) {\n\t\t\tif ( property_exists( $this, $key ) ) {\n\t\t\t\t$this->{$key} = $val;\n\t\t\t}\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t/**\n\t * Retrieve current story.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Story|null\n\t */\n\tpublic function current(): ?Story {\n\t\treturn $this->stories[ $this->position ] ?? null;\n\t}\n\n\t/**\n\t * Retrieve next story.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function next(): void {\n\t\t++$this->position;\n\t}\n\n\t/**\n\t * Retrieve the key for current node in list.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return bool|float|int|string|void|null\n\t */\n\t#[\\ReturnTypeWillChange]\n\tpublic function key() {\n\t\treturn $this->position;\n\t}\n\n\t/**\n\t * Check if current position is valid.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return bool\n\t */\n\tpublic function valid(): bool {\n\t\treturn isset( $this->stories[ $this->position ] );\n\t}\n\n\t/**\n\t * Reset pointer to start of the list.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function rewind(): void {\n\t\t$this->position = 0;\n\t}\n\n\t/**\n\t * Perform initial setup for object.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function init(): void {\n\t\t$this->stories = array_filter( array_map( [ $this, 'prepare_stories' ], $this->query->get_stories() ) );\n\n\t\tadd_action( 'wp_footer', [ $this, 'render_stories_lightbox' ] );\n\t\tadd_action( 'amp_post_template_footer', [ $this, 'render_stories_lightbox' ] );\n\t}\n\n\t/**\n\t * Initializes renderer functionality.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function load_assets(): void {\n\t\tif ( wp_style_is( self::STYLE_HANDLE, 'registered' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Web Stories styles for AMP and non-AMP pages.\n\t\t$this->assets->register_style_asset( self::STYLE_HANDLE );\n\n\t\tif ( \\defined( 'AMPFORWP_VERSION' ) ) {\n\t\t\tadd_action( 'amp_post_template_css', [ $this, 'add_amp_post_template_css' ] );\n\t\t}\n\t}\n\n\t/**\n\t * Prints required inline CSS when using the AMP for WP plugin.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return void\n\t */\n\tpublic function add_amp_post_template_css(): void {\n\t\t$path = $this->assets->get_base_path( \\sprintf( 'assets/css/%s%s.css', self::STYLE_HANDLE, is_rtl() ? '-rtl' : '' ) );\n\n\t\tif ( is_readable( $path ) ) {\n\t\t\t$css = file_get_contents( $path ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown\n\t\t\techo $css; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t}\n\t}\n\n\t/**\n\t * Returns story item data.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param object $post Array of post objects.\n\t * @return Story|null Story object or null if given post\n\t */\n\tpublic function prepare_stories( $post ): ?Story {\n\t\tif ( ! $post instanceof WP_Post ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t$story_data = [];\n\n\t\t// TODO: get from field state instead.\n\t\tif ( ! $this->is_view_type( 'circles' ) ) {\n\t\t\tif ( isset( $this->attributes['show_author'] ) && true === $this->attributes['show_author'] ) {\n\t\t\t\t$author_id = absint( get_post_field( 'post_author', $post->ID ) );\n\n\t\t\t\t$story_data['author'] = get_the_author_meta( 'display_name', $author_id );\n\t\t\t}\n\n\t\t\tif ( isset( $this->attributes['show_date'] ) && true === $this->attributes['show_date'] ) {\n\t\t\t\t/* translators: Date format, see https://www.php.net/manual/en/datetime.format.php */\n\t\t\t\t$story_data['date'] = get_the_date( __( 'M j, Y', 'web-stories' ), $post->ID );\n\t\t\t}\n\t\t}\n\n\t\t$story_data['classes'] = $this->get_single_story_classes();\n\n\t\t$story = new Story( $story_data );\n\t\t$story->load_from_post( $post );\n\n\t\treturn $story;\n\t}\n\n\t/**\n\t * Render story markup.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function render_single_story_content(): void {\n\t\t/**\n\t\t * Story object.\n\t\t *\n\t\t * @var Story $story\n\t\t */\n\t\t$story = $this->current();\n\n\t\t$single_story_classes = $this->get_single_story_classes();\n\t\t$lightbox_state       = 'lightbox' . $story->get_id() . $this->instance_id;\n\t\t// No need to load these styles on admin as editor styles are being loaded by the block.\n\t\tif ( ! is_admin() || ( \\defined( 'IFRAME_REQUEST' ) && IFRAME_REQUEST ) ) {\n\t\t\t// Web Stories Styles for AMP and non-AMP pages.\n\t\t\t$this->assets->enqueue_style_asset( self::STYLE_HANDLE );\n\t\t}\n\n\t\t$this->assets->enqueue_script_module(\n\t\t\t'web-stories-embed-view-script-module',\n\t\t\t$this->assets->get_base_url( 'assets/js/web-stories-block-view.js' )\n\t\t);\n\n\t\tif ( $this->context->is_amp() ) {\n\t\t\t?>\n\t\t\t<div\n\t\t\t\tclass=\"<?php echo esc_attr( $single_story_classes ); ?>\"\n\t\t\t\ton=\"<?php echo esc_attr( \\sprintf( 'tap:AMP.setState({%1$s: ! %1$s})', $lightbox_state ) ); ?>\"\n\t\t\t\ttabindex=\"0\"\n\t\t\t\trole=\"button\"\n\t\t\t>\n\t\t\t\t<?php $this->render_story_with_poster(); ?>\n\t\t\t</div>\n\t\t\t<?php\n\t\t} else {\n\t\t\t$this->assets->enqueue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t\t$this->assets->enqueue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t\t?>\n\t\t\t<div\n\t\t\t\tclass=\"<?php echo esc_attr( $single_story_classes ); ?>\"\n\t\t\t\tdata-wp-interactive=\"web-stories-block\"\n\t\t\t\t<?php\n\t\t\t\t\t// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t\t\t\techo wp_interactivity_data_wp_context(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'instanceId' => $this->instance_id,\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t\t\t?>\n\t\t\t\tdata-wp-on--click=\"actions.open\"\n\t\t\t\tdata-wp-on-window--popstate=\"actions.onPopstate\"\n\t\t\t\t>\n\t\t\t\t<?php $this->render_story_with_poster(); ?>\n\t\t\t</div>\n\t\t\t<?php\n\t\t}\n\t}\n\n\t/**\n\t * Renders the lightbox markup for non-amp pages.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function render_stories_with_lightbox(): void {\n\t\t$data = [\n\t\t\t'controls' => [\n\t\t\t\t[\n\t\t\t\t\t'name'     => 'close',\n\t\t\t\t\t'position' => 'start',\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'name' => 'skip-next',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'behavior' => [\n\t\t\t\t'autoplay' => false,\n\t\t\t],\n\t\t];\n\t\t?>\n\t\t<div class=\"web-stories-list__lightbox\">\n\t\t\t<amp-story-player\n\t\t\t\twidth=\"3.6\"\n\t\t\t\theight=\"6\"\n\t\t\t\tlayout=\"responsive\"\n\t\t\t\tdata-wp-interactive=\"web-stories-block\"\n\t\t\t\tdata-wp-on--amp-story-player-close=\"actions.close\"\n\t\t\t\tdata-wp-on--navigation=\"actions.navigation\"\n\t\t\t\t>\n\t\t\t\t<script type=\"application/json\">\n\t\t\t\t\t<?php echo wp_json_encode( $data ); ?>\n\t\t\t\t</script>\n\t\t\t\t<?php echo wp_kses_post( $this->lightbox_html ); ?>\n\t\t\t</amp-story-player>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Renders the lightbox markup for non-amp pages.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tpublic function render_stories_with_lightbox_amp(): void {\n\t\t// Have to ignore this as the escaping functions are stripping off 'amp-bind' custom attribute '[class]'.\n\t\techo $this->lightbox_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Generated with properly escaped data.\n\t}\n\n\t/**\n\t * Renders stories lightbox on 'wp_footer'.\n\t *\n\t * @return void\n\t */\n\tpublic function render_stories_lightbox(): void {\n\t\t// Return if we don't have anything to render.\n\t\tif ( empty( $this->lightbox_html ) ) {\n\t\t\treturn;\n\t\t}\n\t\t?>\n\t\t<div class=\"web-stories-list__lightbox-wrapper <?php echo esc_attr( 'ws-lightbox-' . $this->instance_id ); ?>\">\n\t\t\t<?php\n\t\t\tif ( $this->context->is_amp() ) {\n\t\t\t\t$this->render_stories_with_lightbox_amp();\n\t\t\t} else {\n\t\t\t\t$this->render_stories_with_lightbox();\n\t\t\t}\n\t\t\t?>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Verifies the current view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param string $view_type View type to check.\n\t * @return bool Whether or not current view type matches the one passed.\n\t */\n\tprotected function is_view_type( $view_type ): bool {\n\t\treturn ( ! empty( $this->attributes['view_type'] ) && $view_type === $this->attributes['view_type'] );\n\t}\n\n\t/**\n\t * Get view type for stories.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return string\n\t */\n\tprotected function get_view_type(): string {\n\t\treturn ! empty( $this->attributes['view_type'] ) ? $this->attributes['view_type'] : 'circles';\n\t}\n\n\t/**\n\t * Renders stories archive link if the 'show_archive_link' attribute is set to true.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tprotected function maybe_render_archive_link(): void {\n\t\tif (\n\t\t\tempty( $this->attributes['show_archive_link'] ) ||\n\t\t\ttrue !== $this->attributes['show_archive_link'] ||\n\t\t\tempty( $this->attributes['archive_link_label'] )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t$web_stories_archive = get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\tif ( empty( $web_stories_archive ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t?>\n\t\t<div class=\"web-stories-list__archive-link\">\n\t\t\t<a href=\"<?php echo esc_url( $web_stories_archive ); ?>\">\n\t\t\t\t<?php echo esc_html( $this->attributes['archive_link_label'] ); ?>\n\t\t\t</a>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Gets the classes for renderer container.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return string\n\t */\n\tprotected function get_view_classes(): string {\n\t\t$view_classes   = [];\n\t\t$view_classes[] = ! empty( $this->attributes['view_type'] ) ? \\sprintf( 'is-view-type-%1$s', $this->attributes['view_type'] ) : 'is-view-type-circles';\n\n\t\tif ( $this->is_view_type( 'grid' ) && ! empty( $this->attributes['number_of_columns'] ) ) {\n\t\t\t$view_classes[] = \\sprintf( 'columns-%1$d', $this->attributes['number_of_columns'] );\n\t\t}\n\n\t\tif ( ! $this->is_view_type( 'circles' ) && ! empty( $this->attributes['sharp_corners'] ) ) {\n\t\t\t$view_classes[] = 'is-style-squared';\n\t\t} else {\n\t\t\t$view_classes[] = 'is-style-default';\n\t\t}\n\n\t\tif ( $this->is_view_type( 'circles' ) && ! empty( $this->attributes['show_title'] ) ) {\n\t\t\t$view_classes[] = 'has-title';\n\t\t}\n\n\t\tif ( $this->is_view_type( 'circles' ) || $this->is_view_type( 'carousel' ) ) {\n\t\t\t$view_classes[] = 'is-carousel';\n\t\t}\n\n\t\treturn implode( ' ', $view_classes );\n\t}\n\n\t/**\n\t * Gets the classes for renderer container.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return string\n\t */\n\tprotected function get_container_classes(): string {\n\t\t$container_classes   = [];\n\t\t$container_classes[] = 'web-stories-list';\n\t\t$container_classes[] = ! empty( $this->attributes['align'] ) ? \\sprintf( 'align%1$s', $this->attributes['align'] ) : 'alignnone';\n\t\t$container_classes[] = ! empty( $this->attributes['class'] ) ? $this->attributes['class'] : '';\n\n\t\tif ( ! empty( $this->attributes['show_archive_link'] ) ) {\n\t\t\t$container_classes[] = 'has-archive-link';\n\t\t}\n\n\t\t$container_classes = array_filter( $container_classes );\n\n\t\t$view_type_classes = $this->get_view_classes();\n\n\t\treturn \\sprintf( '%1$s %2$s', implode( ' ', $container_classes ), $view_type_classes );\n\t}\n\n\t/**\n\t * Gets the single story container classes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return string\n\t */\n\tprotected function get_single_story_classes(): string {\n\t\t$single_story_classes   = [];\n\t\t$single_story_classes[] = 'web-stories-list__story';\n\n\t\tif ( $this->context->is_amp() ) {\n\t\t\t$single_story_classes[] = 'web-stories-list__story--amp';\n\t\t}\n\n\t\tif ( ! empty( $this->attributes['image_alignment'] ) && ( 'right' === $this->attributes['image_alignment'] ) ) {\n\t\t\t$single_story_classes[] = 'image-align-right';\n\t\t}\n\n\t\t$classes = implode( ' ', $single_story_classes );\n\n\t\t/**\n\t\t * Filters the web stories renderer single story classes.\n\t\t *\n\t\t * @since 1.5.0\n\t\t *\n\t\t * @param string $classes Single story classes.\n\t\t */\n\t\treturn apply_filters( 'web_stories_renderer_single_story_classes', $classes );\n\t}\n\n\t/**\n\t * Gets the single story container styles.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return string Style string.\n\t */\n\tprotected function get_container_styles(): string {\n\t\t$story_styles  = ! empty( $this->attributes['circle_size'] ) && $this->is_view_type( 'circles' ) ?\n\t\t\t\\sprintf( '--ws-circle-size:%1$dpx', $this->attributes['circle_size'] ) :\n\t\t\t'';\n\t\t$story_styles .= $this->is_view_type( 'carousel' ) ? \\sprintf( '--ws-story-max-width:%1$dpx', $this->width ) : '';\n\n\t\t/**\n\t\t * Filters the web stories renderer single story classes.\n\t\t *\n\t\t * @since 1.5.0\n\t\t *\n\t\t * @param string $story_styles Single story classes.\n\t\t */\n\t\treturn apply_filters( 'web_stories_renderer_container_styles', $story_styles );\n\t}\n\n\t/**\n\t * Renders a story with story's poster image.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tprotected function render_story_with_poster(): void {\n\t\t/**\n\t\t * Story object.\n\t\t *\n\t\t * @var Story $story\n\t\t */\n\t\t$story = $this->current();\n\n\t\t$poster_url    = $story->get_poster_portrait();\n\t\t$poster_srcset = $story->get_poster_srcset();\n\t\t$poster_sizes  = $story->get_poster_sizes();\n\n\t\tif ( ! $poster_url ) {\n\t\t\t?>\n\t\t\t<div class=\"web-stories-list__story-poster\">\n\t\t\t\t<div class=\"web-stories-list__story-poster-placeholder\">\n\t\t\t\t\t<a href=\"<?php echo esc_url( $story->get_url() ); ?>\" <?php $this->render_link_attributes(); ?>>\n\t\t\t\t\t\t<?php echo esc_html( $story->get_title() ); ?>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<?php\n\t\t} else {\n\t\t\t?>\n\t\t\t<div class=\"web-stories-list__story-poster\">\n\t\t\t\t<a href=\"<?php echo esc_url( $story->get_url() ); ?>\" <?php $this->render_link_attributes(); ?>>\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc=\"<?php echo esc_url( $poster_url ); ?>\"\n\t\t\t\t\t\talt=\"<?php echo esc_attr( $story->get_title() ); ?>\"\n\t\t\t\t\t\twidth=\"<?php echo absint( $this->width ); ?>\"\n\t\t\t\t\t\theight=\"<?php echo absint( $this->height ); ?>\"\n\t\t\t\t\t\t<?php if ( ! empty( $poster_srcset ) ) { ?>\n\t\t\t\t\t\t\tsrcset=\"<?php echo esc_attr( $poster_srcset ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t<?php if ( ! empty( $poster_sizes ) ) { ?>\n\t\t\t\t\t\t\tsizes=\"<?php echo esc_attr( $poster_sizes ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t>\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t\t<?php\n\t\t}\n\t\t$this->get_content_overlay();\n\n\t\tif ( ! $this->context->is_amp() ) {\n\t\t\t$this->generate_lightbox_html( $story );\n\t\t} else {\n\t\t\t$this->generate_amp_lightbox_html_amp( $story );\n\t\t}\n\t}\n\n\t/**\n\t * Render additional link attributes.\n\t *\n\t * Allows customization of html attributes in the web stories widget anchor tag loop\n\t * Converts array into escaped inline html attributes.\n\t *\n\t * @since 1.17.0\n\t *\n\t * @return void\n\t */\n\tprotected function render_link_attributes(): void {\n\t\t/**\n\t\t * The current story.\n\t\t *\n\t\t * @var Story $story\n\t\t */\n\t\t$story = $this->current();\n\n\t\t/**\n\t\t * Filters the link attributes added to a story's <a> tag.\n\t\t *\n\t\t * @since 1.17.0\n\t\t *\n\t\t * @param array  $attributes Key value array of attribute name to attribute value.\n\t\t * @param Story  $story      The current story instance.\n\t\t * @param int    $position   The current story's position within the list.\n\t\t * @param string $view_type  The current view type.\n\t\t */\n\t\t$attributes = apply_filters( 'web_stories_renderer_link_attributes', [], $story, $this->position, $this->get_view_type() );\n\n\t\t$attrs = [];\n\n\t\tif ( ! empty( $attributes ) ) {\n\t\t\tforeach ( $attributes as $attribute => $value ) {\n\t\t\t\t$attrs[] = wp_kses_one_attr( $attribute . '=\"' . esc_attr( $value ) . '\"', 'a' );\n\t\t\t}\n\t\t}\n\n\t\t$attrs = array_filter( $attrs ); // Filter out empty values rejected by KSES.\n\n\t\t//phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\techo implode( ' ', $attrs );\n\t}\n\n\t/**\n\t * Renders the content overlay markup.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return void\n\t */\n\tprotected function get_content_overlay(): void {\n\t\t/**\n\t\t * Story object.\n\t\t *\n\t\t * @var Story $story\n\t\t */\n\t\t$story = $this->current();\n\n\t\tif ( empty( $this->content_overlay ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t?>\n\t\t<div class=\"web-stories-list__story-content-overlay\">\n\t\t\t<?php if ( ! empty( $this->attributes['show_title'] ) ) { ?>\n\t\t\t\t<div class=\"story-content-overlay__title\">\n\t\t\t\t\t<?php echo esc_html( $story->get_title() ); ?>\n\t\t\t\t</div>\n\t\t\t<?php } ?>\n\n\t\t\t<?php if ( ! empty( $this->attributes['show_excerpt'] ) ) { ?>\n\t\t\t\t<div class=\"story-content-overlay__excerpt\">\n\t\t\t\t\t<?php echo esc_html( $story->get_excerpt() ); ?>\n\t\t\t\t</div>\n\t\t\t<?php } ?>\n\n\t\t\t<?php if ( ! empty( $story->get_author() ) ) { ?>\n\t\t\t\t<div class=\"story-content-overlay__author\">\n\t\t\t\t\t<?php\n\t\t\t\t\t\t/* translators: byline. %s: author name. */\n\t\t\t\t\t\techo esc_html( \\sprintf( __( 'By %s', 'web-stories' ), $story->get_author() ) );\n\t\t\t\t\t?>\n\t\t\t\t</div>\n\t\t\t<?php } ?>\n\n\t\t\t<?php if ( ! empty( $story->get_date() ) ) { ?>\n\t\t\t\t<time class=\"story-content-overlay__date\">\n\t\t\t\t\t<?php\n\t\t\t\t\t\t/* translators: %s: publish date. */\n\t\t\t\t\t\techo esc_html( \\sprintf( __( 'On %s', 'web-stories' ), $story->get_date() ) );\n\t\t\t\t\t?>\n\t\t\t\t</time>\n\t\t\t<?php } ?>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Generate HTML for the non-AMP page request.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param Story $story Current Story.\n\t * @return void\n\t */\n\tprotected function generate_lightbox_html( $story ): void {\n\t\t// Start collecting markup for the lightbox stories. This way we don't have to re-run the loop.\n\t\tob_start();\n\n\t\t// Collect story links to fill-in non-AMP lightbox 'amp-story-player'.\n\t\t?>\n\t\t\t<a href=\"<?php echo esc_url( $story->get_url() ); ?>\" <?php $this->render_link_attributes(); ?>><?php echo esc_html( $story->get_title() ); ?></a>\n\t\t<?php\n\n\t\t$this->lightbox_html .= ob_get_clean();\n\t}\n\n\t/**\n\t * Markup for the lightbox used on AMP pages.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param Story $story Current Story.\n\t * @return void\n\t */\n\tprotected function generate_amp_lightbox_html_amp( $story ): void {\n\t\t// Start collecting markup for the lightbox stories. This way we don't have to re-run the loop.\n\t\tob_start();\n\t\t$lightbox_state = 'lightbox' . $story->get_id() . $this->instance_id;\n\t\t$lightbox_id    = 'lightbox-' . $story->get_id() . $this->instance_id;\n\t\t?>\n\t\t<amp-lightbox\n\t\t\tid=\"<?php echo esc_attr( $lightbox_id ); ?>\"\n\t\t\t[open]=\"<?php echo esc_attr( $lightbox_state ); ?>\"\n\t\t\tlayout=\"nodisplay\"\n\t\t\ton=\"lightboxClose:AMP.setState({<?php echo esc_attr( $lightbox_state ); ?>: false})\"\n\t\t\trole=\"button\"\n\t\t\ttabindex=\"0\"\n\t\t>\n\t\t\t<div class=\"web-stories-list__lightbox show\">\n\t\t\t\t<button type=\"button\"\n\t\t\t\t\tclass=\"story-lightbox__close-button\"\n\t\t\t\t\ton=\"tap:<?php echo esc_attr( $lightbox_id ); ?>.close\"\n\t\t\t\t\taria-label=\"<?php esc_attr_e( 'Close', 'web-stories' ); ?>\"\n\t\t\t\t>\n\t\t\t\t\t<span class=\"story-lightbox__close-button--stick\"></span>\n\t\t\t\t\t<span class=\"story-lightbox__close-button--stick\"></span>\n\t\t\t\t</button>\n\t\t\t\t<amp-story-player\n\t\t\t\t\twidth=\"3.6\"\n\t\t\t\t\theight=\"6\"\n\t\t\t\t\tlayout=\"responsive\"\n\t\t\t\t\tdata-wp-interactive=\"web-stories-block\"\n\t\t\t\t\tdata-wp-on--amp-story-player-close=\"actions.close\"\n\t\t\t\t\tdata-wp-on--navigation=\"actions.navigation\"\n\t\t\t\t>\n\t\t\t\t\t<a href=\"<?php echo esc_url( $story->get_url() ); ?>\" <?php $this->render_link_attributes(); ?>><?php echo esc_html( $story->get_title() ); ?></a>\n\t\t\t\t</amp-story-player>\n\t\t\t</div>\n\t\t</amp-lightbox>\n\t\t<?php\n\t\t$this->lightbox_html .= ob_get_clean();\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Story/Embed.php",
    "content": "<?php\n/**\n * Class Embed\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Story;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Embed_Base;\nuse Google\\Web_Stories\\Model\\Story;\n\n/**\n * Class Embed\n */\nclass Embed {\n\t/**\n\t * Current post.\n\t *\n\t * @var Story Post object.\n\t */\n\tprotected Story $story;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Embed constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Story   $story   Story instance.\n\t * @param Assets  $assets  Assets instance.\n\t * @param Context $context Context instance.\n\t */\n\tpublic function __construct( Story $story, Assets $assets, Context $context ) {\n\t\t$this->assets  = $assets;\n\t\t$this->story   = $story;\n\t\t$this->context = $context;\n\t}\n\n\t/**\n\t * Renders the block output in default context.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string,string|int> $args Array of Argument to render.\n\t * @return string Rendered block type output.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\t$defaults = [\n\t\t\t'align'  => 'none',\n\t\t\t'class'  => 'wp-block-web-stories-embed',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\n\t\t$args          = wp_parse_args( $args, $defaults );\n\t\t$align         = \\sprintf( 'align%s', $args['align'] );\n\t\t$class         = $args['class'];\n\t\t$url           = $this->story->get_url();\n\t\t$title         = $this->story->get_title();\n\t\t$poster        = $this->story->get_poster_portrait();\n\t\t$poster_srcset = $this->story->get_poster_srcset();\n\t\t$poster_sizes  = $this->story->get_poster_sizes();\n\n\t\t$wrapper_style = \\sprintf(\n\t\t\t'--aspect-ratio: %F; --width: %dpx; --height: %dpx',\n\t\t\t0 !== $args['height'] ? $args['width'] / $args['height'] : 1,\n\t\t\t(int) $args['width'],\n\t\t\t(int) $args['height']\n\t\t);\n\n\t\t// This CSS is used for AMP and non-AMP.\n\t\t$this->assets->enqueue_style_asset( Embed_Base::SCRIPT_HANDLE );\n\n\t\tif ( $this->context->is_amp() ) {\n\t\t\tob_start();\n\t\t\t?>\n\t\t\t<div class=\"<?php echo esc_attr( \"$class web-stories-embed web-stories-embed-amp $align\" ); ?>\">\n\t\t\t\t<div class=\"wp-block-embed__wrapper\" style=\"<?php echo esc_attr( $wrapper_style ); ?>\">\n\t\t\t\t\t<amp-story-player\n\t\t\t\t\t\twidth=\"<?php echo esc_attr( $args['width'] ); ?>\"\n\t\t\t\t\t\theight=\"<?php echo esc_attr( $args['height'] ); ?>\"\n\t\t\t\t\t\tlayout=\"intrinsic\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<a href=\"<?php echo esc_url( $url ); ?>\">\n\t\t\t\t\t\t\t<?php if ( $poster ) { ?>\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc=\"<?php echo esc_url( $poster ); ?>\"\n\t\t\t\t\t\t\t\t\twidth=\"<?php echo esc_attr( $args['width'] ); ?>\"\n\t\t\t\t\t\t\t\t\theight=\"<?php echo esc_attr( $args['height'] ); ?>\"\n\t\t\t\t\t\t\t\t\talt=\"<?php echo esc_attr( $title ); ?>\"\n\t\t\t\t\t\t\t\t\t<?php if ( ! empty( $poster_srcset ) ) { ?>\n\t\t\t\t\t\t\t\t\t\tsrcset=\"<?php echo esc_attr( $poster_srcset ); ?>\"\n\t\t\t\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t\t\t\t<?php if ( ! empty( $poster_sizes ) ) { ?>\n\t\t\t\t\t\t\t\t\t\tsizes=\"<?php echo esc_attr( $poster_sizes ); ?>\"\n\t\t\t\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t\t\t\t\tdata-amp-story-player-poster-img\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<?php\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\techo esc_html( $title );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t?>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</amp-story-player>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<?php\n\n\t\t\treturn (string) ob_get_clean();\n\t\t}\n\t\t$this->assets->enqueue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\n\t\tob_start();\n\t\t?>\n\t\t<div class=\"<?php echo esc_attr( \"$class web-stories-embed $align\" ); ?>\">\n\t\t\t<div class=\"wp-block-embed__wrapper\" style=\"<?php echo esc_attr( $wrapper_style ); ?>\">\n\t\t\t\t<amp-story-player>\n\t\t\t\t\t<a href=\"<?php echo esc_url( $url ); ?>\">\n\t\t\t\t\t\t<?php if ( $poster ) { ?>\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc=\"<?php echo esc_url( $poster ); ?>\"\n\t\t\t\t\t\t\t\twidth=\"<?php echo esc_attr( $args['width'] ); ?>\"\n\t\t\t\t\t\t\t\theight=\"<?php echo esc_attr( $args['height'] ); ?>\"\n\t\t\t\t\t\t\t\talt=\"<?php echo esc_attr( $title ); ?>\"\n\t\t\t\t\t\t\t\t<?php if ( ! empty( $poster_srcset ) ) { ?>\n\t\t\t\t\t\t\t\t\tsrcset=\"<?php echo esc_attr( $poster_srcset ); ?>\"\n\t\t\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t\t\t<?php if ( ! empty( $poster_sizes ) ) { ?>\n\t\t\t\t\t\t\t\t\tsizes=\"<?php echo esc_attr( $poster_sizes ); ?>\"\n\t\t\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t\t\t\tdata-amp-story-player-poster-img\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<?php\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\techo esc_html( $title );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t?>\n\t\t\t\t\t</a>\n\t\t\t\t</amp-story-player>\n\t\t\t</div>\n\t\t</div>\n\t\t<?php\n\n\t\treturn (string) ob_get_clean();\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Story/HTML.php",
    "content": "<?php\n/**\n * Class HTML\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Story;\n\nuse Google\\Web_Stories\\Model\\Story;\n\n/**\n * Class HTML\n */\nclass HTML {\n\t/**\n\t * Current post.\n\t *\n\t * @var Story Post object.\n\t */\n\tprotected Story $story;\n\n\t/**\n\t * HTML constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Story $story Story object.\n\t */\n\tpublic function __construct( Story $story ) {\n\t\t$this->story = $story;\n\t}\n\n\t/**\n\t * Renders the story.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return string The complete HTML markup for the story.\n\t */\n\tpublic function render(): string {\n\t\t$markup = $this->story->get_markup();\n\t\t$markup = $this->fix_incorrect_charset( $markup );\n\t\t$markup = $this->fix_malformed_script_link_tags( $markup );\n\t\t$markup = $this->replace_html_head( $markup );\n\t\t$markup = wp_replace_insecure_home_url( $markup );\n\t\t$markup = $this->print_analytics( $markup );\n\t\t$markup = $this->print_social_share( $markup );\n\n\t\treturn $markup;\n\t}\n\n\t/**\n\t * Fix incorrect <meta charset> tags.\n\t *\n\t * React/JSX outputs the charset attribute name as \"charSet\",\n\t * but libdom and the AMP toolbox only recognize lowercase \"charset\"\n\t *\n\t * @since 1.28.0\n\t *\n\t * @param string $content Story markup.\n\t * @return string Filtered content\n\t */\n\tpublic function fix_incorrect_charset( string $content ): string {\n\t\treturn (string) preg_replace( '/<meta charSet=\"utf-8\"\\s?\\/>/i', '<meta charset=\"utf-8\"/>', $content );\n\t}\n\n\t/**\n\t * Fix malformed <a> tags in the <head>.\n\t *\n\t * On certain environments like WordPress.com VIP, there is additional KSES\n\t * hardening that prevents saving `<script>` tags to the database, despite\n\t * this plugin allowing them ({@see KSES}).\n\t *\n\t * There, script tags somehow get transformed to `<a>` tags before saving\n\t * to the database.\n\t * This of course breaks the markup completely as `<a>` is not allowed in the `<head>`,\n\t * thus the  DOMDocument parser moves them to the `<body>`, breaking the DOM structure.\n\t *\n\t * Since we cannot prevent the broken `<a>`/`<script>` tags upon saving\n\t * and not during sanitization, this method is an attempt to fix them\n\t * *before* they're sanitized.\n\t *\n\t * Turns `<a href=\"https://cdn.ampproject.org/v0.js\">https://cdn.ampproject.org/v0.js</a>`\n\t * into `<script async src=\"https://cdn.ampproject.org/v0.js\"></script>`\n\t * and `<a href=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\">https://cdn.ampproject.org/v0/amp-story-1.0.js</a>`\n\t * into `<script async src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>`.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param string $content Story markup.\n\t * @return string Filtered content\n\t */\n\tprotected function fix_malformed_script_link_tags( string $content ): string {\n\t\t$replaced_content = preg_replace_callback(\n\t\t\t'/<a[^>]+href=\"(?P<href>[^\"]+)\"[^>]*>\\1<\\/a>/m',\n\t\t\tstatic function ( $matches ) {\n\t\t\t\tif ( str_starts_with( $matches['href'], 'https://cdn.ampproject.org/' ) ) {\n\t\t\t\t\t$script_url = $matches['href'];\n\n\t\t\t\t\t// Turns `<a href=\"https://cdn.ampproject.org/v0.js\">https://cdn.ampproject.org/v0.js</a>`\n\t\t\t\t\t// into `<script async src=\"https://cdn.ampproject.org/v0.js\"></script>`.\n\t\t\t\t\tif ( 'https://cdn.ampproject.org/v0.js' === $script_url ) {\n\t\t\t\t\t\treturn \"<script async src=\\\"$script_url\\\"></script>\"; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript\n\t\t\t\t\t}\n\n\t\t\t\t\t// Extract 'amp-story' from 'https://cdn.ampproject.org/v0/amp-story-1.0.js'.\n\t\t\t\t\t$sub_matches = [];\n\t\t\t\t\tpreg_match( '/v0\\/(?P<custom_element>[\\w-]+)-[\\d.]+\\.js/', $script_url, $sub_matches );\n\n\t\t\t\t\tif ( isset( $sub_matches['custom_element'] ) ) {\n\t\t\t\t\t\t$custom_element = $sub_matches['custom_element'];\n\n\t\t\t\t\t\t// Turns `<a href=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\">https://cdn.ampproject.org/v0/amp-story-1.0.js</a>`\n\t\t\t\t\t\t// into <script async src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>.\n\t\t\t\t\t\treturn \"<script async src=\\\"$script_url\\\" custom-element=\\\"$custom_element\\\"></script>\"; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn $matches[0];\n\t\t\t},\n\t\t\t$content\n\t\t);\n\n\t\t// On errors the return value of preg_replace_callback() is null.\n\t\treturn $replaced_content ?: $content;\n\t}\n\n\t/**\n\t * Returns the full HTML <head> markup for a given story besides boilerplate.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return string Filtered content.\n\t */\n\tprotected function get_html_head_markup(): string {\n\t\tob_start();\n\t\t?>\n\t\t<meta name=\"amp-story-generator-name\" content=\"Web Stories for WordPress\" />\n\t\t<meta name=\"amp-story-generator-version\" content=\"<?php echo esc_attr( WEBSTORIES_VERSION ); ?>\" />\n\t\t<?php\n\n\t\t/**\n\t\t * Prints scripts or data in the head tag on the front end.\n\t\t */\n\t\tdo_action( 'web_stories_story_head' );\n\n\t\treturn (string) ob_get_clean();\n\t}\n\n\t/**\n\t * Replaces markers in HTML <head> with dynamic content.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param string $content Story markup.\n\t * @return string Filtered content.\n\t */\n\tprotected function replace_html_head( string $content ): string {\n\t\t$start_tag = '<meta name=\"web-stories-replace-head-start\"/>';\n\t\t$end_tag   = '<meta name=\"web-stories-replace-head-end\"/>';\n\n\t\t// Replace malformed meta tags with correct tags.\n\t\t$content = (string) preg_replace( '/<meta name=\"web-stories-replace-head-start\\s?\"\\s?\\/?>/i', $start_tag, $content );\n\t\t$content = (string) preg_replace( '/<meta name=\"web-stories-replace-head-end\\s?\"\\s?\\/?>/i', $end_tag, $content );\n\n\t\t$start_tag_pos = strpos( $content, $start_tag );\n\t\t$end_tag_pos   = strpos( $content, $end_tag );\n\n\t\tif ( false !== $start_tag_pos && false !== $end_tag_pos ) {\n\t\t\t$end_tag_pos += \\strlen( $end_tag );\n\t\t\t$content      = substr_replace( $content, $this->get_html_head_markup(), $start_tag_pos, $end_tag_pos - $start_tag_pos );\n\t\t}\n\n\t\treturn $content;\n\t}\n\n\t/**\n\t * Print analytics code before closing `</amp-story>`.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param string $content String to replace.\n\t */\n\tprotected function print_analytics( string $content ): string {\n\t\tob_start();\n\n\t\t/**\n\t\t * Fires before the closing <amp-story> tag.\n\t\t *\n\t\t * Can be used to print <amp-analytics> configuration.\n\t\t *\n\t\t * @since 1.1.0\n\t\t */\n\t\tdo_action( 'web_stories_print_analytics' );\n\n\t\t$output = (string) ob_get_clean();\n\n\t\treturn str_replace( '</amp-story>', $output . '</amp-story>', $content );\n\t}\n\n\t/**\n\t * Print amp-story-social-share before closing `</amp-story>`.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $content String to replace.\n\t */\n\tprotected function print_social_share( string $content ): string {\n\t\t$share_providers = [\n\t\t\t[\n\t\t\t\t'provider' => 'twitter',\n\t\t\t],\n\t\t\t[\n\t\t\t\t'provider' => 'linkedin',\n\t\t\t],\n\t\t\t[\n\t\t\t\t'provider' => 'email',\n\t\t\t],\n\t\t\t[\n\t\t\t\t'provider' => 'system',\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filters the list of sharing providers in the Web Stories sharing dialog.\n\t\t *\n\t\t * @since 1.3.0\n\t\t *\n\t\t * @link https://amp.dev/documentation/components/amp-social-share/?format=stories#pre-configured-providers\n\t\t *\n\t\t * @param array[] $share_providers List of sharing providers.\n\t\t */\n\t\t$share_providers = apply_filters( 'web_stories_share_providers', $share_providers );\n\n\t\tif ( empty( $share_providers ) ) {\n\t\t\treturn $content;\n\t\t}\n\n\t\t$config       = [\n\t\t\t'shareProviders' => $share_providers,\n\t\t];\n\t\t$social_share = \\sprintf(\n\t\t\t'<amp-story-social-share layout=\"nodisplay\"><script type=\"application/json\">%s</script></amp-story-social-share>',\n\t\t\twp_json_encode( $config )\n\t\t);\n\n\n\t\treturn str_replace( '</amp-story>', $social_share . '</amp-story>', $content );\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Story/Image.php",
    "content": "<?php\n/**\n * Class Image\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Story;\n\nuse Google\\Web_Stories\\Model\\Story;\n\n/**\n * Class Image\n */\nclass Image {\n\t/**\n\t * Current post.\n\t *\n\t * @var Story Post object.\n\t */\n\tprotected Story $story;\n\n\n\t/**\n\t * Image constructor.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param Story $story   Story Object.\n\t */\n\tpublic function __construct( Story $story ) {\n\t\t$this->story = $story;\n\t}\n\n\t/**\n\t * Renders the block as an image.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array<string,string|int> $args Array of Argument to render.\n\t * @return string Rendered block type output.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\t$defaults = [\n\t\t\t'align'  => 'none',\n\t\t\t'class'  => 'wp-block-web-stories-embed',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$args     = wp_parse_args( $args, $defaults );\n\t\t$align    = \\sprintf( 'align%s', $args['align'] );\n\t\t$class    = $args['class'];\n\n\t\t$url           = $this->story->get_url();\n\t\t$title         = $this->story->get_title();\n\t\t$poster        = $this->story->get_poster_portrait();\n\t\t$poster_srcset = $this->story->get_poster_srcset();\n\t\t$poster_sizes  = $this->story->get_poster_sizes();\n\n\t\tob_start();\n\t\t?>\n\t\t<div class=\"<?php echo esc_attr( $class ); ?> <?php echo esc_attr( $align ); ?>\">\n\t\t\t<a href=\"<?php echo esc_url( $url ); ?>\">\n\t\t\t\t<?php if ( ! empty( $poster ) ) { ?>\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc=\"<?php echo esc_url( $poster ); ?>\"\n\t\t\t\t\t\twidth=\"<?php echo esc_attr( $args['width'] ); ?>\"\n\t\t\t\t\t\theight=\"<?php echo esc_attr( $args['height'] ); ?>\"\n\t\t\t\t\t\talt=\"<?php echo esc_attr( $title ); ?>\"\n\t\t\t\t\t\t<?php if ( ! empty( $poster_srcset ) ) { ?>\n\t\t\t\t\t\t\tsrcset=\"<?php echo esc_attr( $poster_srcset ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t<?php if ( ! empty( $poster_sizes ) ) { ?>\n\t\t\t\t\t\t\tsizes=\"<?php echo esc_attr( $poster_sizes ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t/>\n\t\t\t\t\t<?php\n\t\t\t\t} else {\n\t\t\t\t\techo esc_html( $title );\n\t\t\t\t}\n\t\t\t\t?>\n\t\t\t</a>\n\t\t</div>\n\t\t<?php\n\n\t\treturn (string) ob_get_clean();\n\t}\n}\n"
  },
  {
    "path": "includes/Renderer/Story/Singleton.php",
    "content": "<?php\n/**\n * Class Singleton\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Renderer\\Story;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Embed_Base;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Stories\\Renderer;\n\n/**\n * Class Singleton\n */\nclass Singleton {\n\t/**\n\t * Number of instances invoked. Kept it static to keep track.\n\t */\n\tprotected static int $instances = 0;\n\n\t/**\n\t * Current post.\n\t *\n\t * @var Story Post object.\n\t */\n\tprotected Story $story;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Object ID for the Renderer class.\n\t * To enable support for multiple carousels and lightboxes\n\t * on the same page, we needed to identify each Renderer instance.\n\t *\n\t * This variable is used to add appropriate class to the Web Stories\n\t * wrapper.\n\t */\n\tprotected int $instance_id = 0;\n\n\t/**\n\t * Singleton constructor.\n\t *\n\t * @since 1.30.0\n\t *\n\t * @param Story  $story   Story instance.\n\t * @param Assets $assets  Assets instance.\n\t */\n\tpublic function __construct( Story $story, Assets $assets ) {\n\t\t$this->assets = $assets;\n\t\t$this->story  = $story;\n\t}\n\n\t/**\n\t * Renders the block output in default context.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.30.0\n\t *\n\t * @param array<string,string|int> $args Array of Argument to render.\n\t * @return string Rendered block type output.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\t++self::$instances;\n\t\t$this->instance_id = self::$instances;\n\n\t\t$defaults = [\n\t\t\t'align'  => 'none',\n\t\t\t'class'  => 'wp-block-web-stories-embed',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\n\t\t$args = wp_parse_args( $args, $defaults );\n\n\t\t$args['align'] = ! empty( $args['align'] ) ? $args['align'] : 'none';\n\t\t$align         = \\sprintf( 'align%s', $args['align'] );\n\t\t$class         = $args['class'];\n\t\t$wrapper_style = \\sprintf(\n\t\t\t'--aspect-ratio: %F; --width: %dpx; --height: %dpx',\n\t\t\t0 !== $args['height'] ? $args['width'] / $args['height'] : 1,\n\t\t\t(int) $args['width'],\n\t\t\t(int) $args['height']\n\t\t);\n\n\t\t$this->assets->enqueue_style_asset( Renderer::STYLE_HANDLE ); // For the lightbox styles.\n\t\t$this->assets->enqueue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_style_asset( Embed_Base::SCRIPT_HANDLE );\n\n\t\t$this->assets->enqueue_script_module(\n\t\t\t'web-stories-embed-view-script-module',\n\t\t\t$this->assets->get_base_url( 'assets/js/web-stories-block-view.js' )\n\t\t);\n\n\t\tob_start();\n\t\t?>\n\t\t<div\n\t\tclass=\"<?php echo esc_attr( \"$class web-stories-singleton $align\" ); ?>\"\n\t\tdata-id=\"<?php echo esc_attr( 'singleton-' . $this->instance_id ); ?>\"\n\t\tdata-wp-interactive=\"web-stories-block\"\n\t\t<?php\n\t\t\t// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t\techo wp_interactivity_data_wp_context(\n\t\t\t\t[\n\t\t\t\t\t'instanceId' => $this->instance_id,\n\t\t\t\t]\n\t\t\t);\n\t\t?>\n\t\t>\n\t\t\t<div\n\t\t\tclass=\"wp-block-embed__wrapper\"\n\t\t\tstyle=\"<?php echo esc_attr( $wrapper_style ); ?>\"\n\t\t\tdata-wp-on--click=\"actions.open\"\n\t\t\t>\n\t\t\t<?php $this->render_story_with_poster( $args ); ?>\n\t\t\t</div>\n\t\t\t<?php\n\n\t\t\t$data = [\n\t\t\t\t'controls' => [\n\t\t\t\t\t[\n\t\t\t\t\t\t'name'     => 'close',\n\t\t\t\t\t\t'position' => 'start',\n\t\t\t\t\t],\n\t\t\t\t\t[\n\t\t\t\t\t\t'name' => 'skip-next',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'behavior' => [\n\t\t\t\t\t'autoplay' => false,\n\t\t\t\t],\n\t\t\t];\n\n\t\t\t?>\n\t\t\t<div class=\"web-stories-singleton__lightbox-wrapper <?php echo esc_attr( 'ws-lightbox-singleton-' . $this->instance_id ); ?>\">\n\t\t\t\t<div\n\t\t\t\tclass=\"web-stories-singleton__lightbox\"\n\t\t\t\tid=\"<?php echo esc_attr( 'ws-lightbox-singleton-' . $this->instance_id ); ?>\"\n\t\t\t\t>\n\t\t\t\t\t<amp-story-player\n\t\t\t\t\t\twidth=\"3.6\"\n\t\t\t\t\t\theight=\"6\"\n\t\t\t\t\t\tlayout=\"responsive\"\n\t\t\t\t\t\tdata-wp-on--amp-story-player-close=\"actions.close\"\n\t\t\t\t\t\tdata-wp-on--navigation=\"actions.navigation\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<script type=\"application/json\">\n\t\t\t\t\t\t\t<?php echo wp_json_encode( $data ); ?>\n\t\t\t\t\t\t</script>\n\t\t\t\t\t\t<a href=\"<?php echo esc_url( $this->story->get_url() ); ?>\"><?php echo esc_html( $this->story->get_title() ); ?></a>\n\t\t\t\t\t</amp-story-player>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<?php\n\t\treturn (string) ob_get_clean();\n\t}\n\n\t/**\n\t * Renders a story with story's poster image.\n\t *\n\t * @since 1.30.0\n\t *\n\t * @param array<string,string|int> $args Array of Argument to render.\n\t */\n\tprotected function render_story_with_poster( array $args ): void {\n\t\t$poster_url    = $this->story->get_poster_portrait();\n\t\t$poster_srcset = $this->story->get_poster_srcset();\n\t\t$poster_sizes  = $this->story->get_poster_sizes();\n\n\t\tif ( ! $poster_url ) {\n\t\t\t?>\n\t\t\t<div class=\"web-stories-singleton-poster\">\n\t\t\t\t<div class=\"web-stories-singleton-poster-placeholder\">\n\t\t\t\t\t<a href=\"<?php echo esc_url( $this->story->get_url() ); ?>\">\n\t\t\t\t\t\t<?php echo esc_html( $this->story->get_title() ); ?>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<?php\n\t\t} else {\n\t\t\t?>\n\t\t\t<div class=\"web-stories-singleton-poster\">\n\t\t\t\t<a href=\"<?php echo esc_url( $this->story->get_url() ); ?>\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc=\"<?php echo esc_url( $poster_url ); ?>\"\n\t\t\t\t\t\talt=\"<?php echo esc_attr( $this->story->get_title() ); ?>\"\n\t\t\t\t\t\twidth=\"<?php echo absint( $args['width'] ); ?>\"\n\t\t\t\t\t\theight=\"<?php echo absint( $args['height'] ); ?>\"\n\t\t\t\t\t\t<?php if ( ! empty( $poster_srcset ) ) { ?>\n\t\t\t\t\t\t\tsrcset=\"<?php echo esc_attr( $poster_srcset ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\t<?php if ( ! empty( $poster_sizes ) ) { ?>\n\t\t\t\t\t\t\tsizes=\"<?php echo esc_attr( $poster_sizes ); ?>\"\n\t\t\t\t\t\t<?php } ?>\n\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\tdecoding=\"async\"\n\t\t\t\t\t>\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t\t<?php\n\t\t}\n\t\t$this->render_content_overlay();\n\t}\n\n\t/**\n\t * Renders the content overlay markup.\n\t *\n\t * @since 1.30.0\n\t */\n\tprotected function render_content_overlay(): void {\n\t\t?>\n\t\t<div class=\"web-stories-singleton-overlay\">\n\t\t\t<div class=\"web-stories-singleton-overlay__title\">\n\t\t\t\t\t<?php echo esc_html( $this->story->get_title() ); ?>\n\t\t\t\t</div>\n\t\t</div>\n\t\t<?php\n\t}\n}\n"
  },
  {
    "path": "includes/Service_Base.php",
    "content": "<?php\n/**\n * Service abstract class.\n *\n * Abstract class the define a service and add some defaults.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Registerable;\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\n/**\n * Class Service\n */\nabstract class Service_Base implements Service, Delayed, Registerable {\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 10;\n\t}\n}\n"
  },
  {
    "path": "includes/Services.php",
    "content": "<?php\n/**\n * Class Services.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer;\n\n/**\n * Convenience class to get easy access to the service container.\n *\n * Using this should always be the last resort.\n * Always prefer to use constructor injection instead.\n */\nfinal class Services {\n\n\t/**\n\t * Plugin object instance.\n\t */\n\tprivate static ?Plugin $plugin = null;\n\n\t/**\n\t * Service container object instance.\n\t *\n\t * @var ServiceContainer<Service>\n\t */\n\tprivate static ?ServiceContainer $container = null;\n\n\t/**\n\t * Dependency injector object instance.\n\t */\n\tprivate static ?Injector $injector = null;\n\n\t/**\n\t * Get a particular service out of the service container.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $service Service ID to retrieve.\n\t */\n\tpublic static function get( string $service ): Service {\n\t\treturn self::get_container()->get( $service );\n\t}\n\n\t/**\n\t * Check if a particular service has been registered in the service container.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param string $service Service ID to retrieve.\n\t */\n\tpublic static function has( string $service ): bool {\n\t\treturn self::get_container()->has( $service );\n\t}\n\n\t/**\n\t * Get an instance of the plugin.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return Plugin Plugin object instance.\n\t */\n\tpublic static function get_plugin(): Plugin {\n\t\tif ( null === self::$plugin ) {\n\t\t\tself::$plugin = PluginFactory::create();\n\t\t}\n\n\t\treturn self::$plugin;\n\t}\n\n\t/**\n\t * Get an instance of the service container.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return ServiceContainer<Service> Service container object instance.\n\t */\n\tpublic static function get_container(): ServiceContainer {\n\t\tif ( null === self::$container ) {\n\t\t\tself::$container = self::get_plugin()->get_container();\n\t\t}\n\n\t\treturn self::$container;\n\t}\n\n\t/**\n\t * Get an instance of the dependency injector.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return Injector Dependency injector object instance.\n\t */\n\tpublic static function get_injector(): Injector {\n\t\tif ( null === self::$injector ) {\n\t\t\tself::$injector = self::get_container()->get( 'injector' );\n\t\t}\n\n\t\treturn self::$injector;\n\t}\n}\n"
  },
  {
    "path": "includes/Settings.php",
    "content": "<?php\n/**\n * Settings class.\n *\n * Responsible for adding the stories Settings to WordPress admin.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\n\n/**\n * Settings class.\n */\nclass Settings extends Service_Base implements PluginUninstallAware {\n\t/**\n\t * Settings group.\n\t */\n\tpublic const SETTING_GROUP = 'web-stories';\n\n\t/**\n\t * Experiments settings group.\n\t */\n\tpublic const SETTING_GROUP_EXPERIMENTS = 'web-stories-experiments';\n\n\t/**\n\t * Experiments setting name.\n\t */\n\tpublic const SETTING_NAME_EXPERIMENTS = 'web_stories_experiments';\n\n\t/**\n\t * GA Tracking ID setting name.\n\t */\n\tpublic const SETTING_NAME_TRACKING_ID = 'web_stories_ga_tracking_id';\n\n\t/**\n\t * Legacy analytics usage flag.\n\t */\n\tpublic const SETTING_NAME_USING_LEGACY_ANALYTICS = 'web_stories_using_legacy_analytics';\n\n\t/**\n\t * Type of adloader.\n\t */\n\tpublic const SETTING_NAME_AD_NETWORK = 'web_stories_ad_network';\n\n\t/**\n\t * AdSense Publisher ID setting name.\n\t */\n\tpublic const SETTING_NAME_ADSENSE_PUBLISHER_ID = 'web_stories_adsense_publisher_id';\n\n\t/**\n\t * AdSense Slot ID setting name.\n\t */\n\tpublic const SETTING_NAME_ADSENSE_SLOT_ID = 'web_stories_adsense_slot_id';\n\n\t/**\n\t * Ad Manager Slot ID setting name.\n\t */\n\tpublic const SETTING_NAME_AD_MANAGER_SLOT_ID = 'web_stories_ad_manager_slot_id';\n\n\t/**\n\t * MGID Widget ID setting name.\n\t */\n\tpublic const SETTING_NAME_MGID_WIDGET_ID = 'web_stories_mgid_widget_id';\n\n\t/**\n\t * Active publisher logo setting name.\n\t */\n\tpublic const SETTING_NAME_ACTIVE_PUBLISHER_LOGO = 'web_stories_active_publisher_logo';\n\n\t/**\n\t * Publisher logos setting name.\n\t */\n\tpublic const SETTING_NAME_PUBLISHER_LOGOS = 'web_stories_publisher_logos';\n\n\t/**\n\t * Video cache setting name.\n\t */\n\tpublic const SETTING_NAME_VIDEO_CACHE = 'web_stories_video_cache';\n\n\t/**\n\t * Data removal setting name.\n\t */\n\tpublic const SETTING_NAME_DATA_REMOVAL = 'web_stories_data_removal';\n\n\t/**\n\t * Web Stories archive setting name.\n\t */\n\tpublic const SETTING_NAME_ARCHIVE = 'web_stories_archive';\n\n\t/**\n\t * Web Stories archive page ID setting name.\n\t */\n\tpublic const SETTING_NAME_ARCHIVE_PAGE_ID = 'web_stories_archive_page_id';\n\n\t/**\n\t * Shopping provider, e.g. woocommerce or shopify\n\t */\n\tpublic const SETTING_NAME_SHOPPING_PROVIDER = 'web_stories_shopping_provider';\n\n\t/**\n\t * Shopify store URL, e.g. acme-store.myshopify.com.\n\t */\n\tpublic const SETTING_NAME_SHOPIFY_HOST = 'web_stories_shopify_host';\n\n\t/**\n\t * Shopify Storefront API access token.\n\t */\n\tpublic const SETTING_NAME_SHOPIFY_ACCESS_TOKEN = 'web_stories_shopify_access_token';\n\n\t/**\n\t * Auto-advance setting, `true` means advancing automatically.\n\t */\n\tpublic const SETTING_NAME_AUTO_ADVANCE = 'web_stories_auto_advance';\n\n\t/**\n\t * Default Page Duration in seconds.\n\t */\n\tpublic const SETTING_NAME_DEFAULT_PAGE_DURATION = 'web_stories_default_page_duration';\n\n\t/**\n\t * GA Tracking Handler.\n\t */\n\tpublic const SETTING_NAME_TRACKING_HANDLER = 'web_stories_ga_tracking_handler';\n\n\t/**\n\t * Customizer settings.\n\t */\n\tpublic const SETTING_NAME_CUSTOMIZER_SETTINGS = 'web_stories_customizer_settings';\n\n\t/**\n\t * Shopping_Vendors instance.\n\t *\n\t * @var Shopping_Vendors Shopping_Vendors instance.\n\t */\n\tprivate Shopping_Vendors $shopping_vendors;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Shopping_Vendors $shopping_vendors Shopping_Vendors instance.\n\t */\n\tpublic function __construct( Shopping_Vendors $shopping_vendors ) {\n\t\t$this->shopping_vendors = $shopping_vendors;\n\t}\n\n\t/**\n\t * Primes option caches for specified groups if the function exists.\n\t *\n\t * @since 1.37.0\n\t */\n\tpublic function prime_option_caches(): void {\n\t\twp_prime_option_caches_by_group( self::SETTING_GROUP );\n\t\twp_prime_option_caches_by_group( self::SETTING_GROUP_EXPERIMENTS );\n\t}\n\n\t/**\n\t * Register settings.\n\t *\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_TRACKING_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Google Analytics Tracking ID', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_USING_LEGACY_ANALYTICS,\n\t\t\t[\n\t\t\t\t'description'       => __( 'Using legacy analytics configuration', 'web-stories' ),\n\t\t\t\t'type'              => 'boolean',\n\t\t\t\t'default'           => false,\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'sanitize_callback' => 'rest_sanitize_boolean',\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_AD_NETWORK,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Ad Network', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => 'none',\n\t\t\t\t'enum'         => [ 'none', 'adsense', 'admanager', 'mgid' ],\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_ADSENSE_PUBLISHER_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Google AdSense Publisher ID', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_ADSENSE_SLOT_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Google AdSense Slot ID', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_AD_MANAGER_SLOT_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Google Ad Manager Slot ID', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_MGID_WIDGET_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'MGID Widget ID', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_ACTIVE_PUBLISHER_LOGO,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Default Publisher Logo', 'web-stories' ),\n\t\t\t\t'type'         => 'integer',\n\t\t\t\t'default'      => 0,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_PUBLISHER_LOGOS,\n\t\t\t[\n\t\t\t\t'description'     => __( 'Publisher Logos', 'web-stories' ),\n\t\t\t\t'type'            => 'array',\n\t\t\t\t'default'         => [],\n\t\t\t\t'show_in_rest'    => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'items' => [\n\t\t\t\t\t\t\t'type' => 'integer',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t// WPGraphQL errors when encountering array or object types.\n\t\t\t\t// See https://github.com/wp-graphql/wp-graphql/issues/2065.\n\t\t\t\t'show_in_graphql' => false,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_VIDEO_CACHE,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Video Cache', 'web-stories' ),\n\t\t\t\t'type'         => 'boolean',\n\t\t\t\t'default'      => false,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_DATA_REMOVAL,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Data Removal', 'web-stories' ),\n\t\t\t\t'type'         => 'boolean',\n\t\t\t\t'default'      => false,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_ARCHIVE,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Web Stories Archive', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => 'default',\n\t\t\t\t'show_in_rest' => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t\t'enum' => [ 'default', 'disabled', 'custom' ],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_ARCHIVE_PAGE_ID,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Web Stories Archive Page ID', 'web-stories' ),\n\t\t\t\t'type'         => 'integer',\n\t\t\t\t'default'      => 0,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP_EXPERIMENTS,\n\t\t\tself::SETTING_NAME_EXPERIMENTS,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Experiments', 'web-stories' ),\n\t\t\t\t'type'         => 'object',\n\t\t\t\t'default'      => [],\n\t\t\t\t'show_in_rest' => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'properties'           => [],\n\t\t\t\t\t\t'additionalProperties' => true,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$vendors        = $this->shopping_vendors->get_vendors();\n\t\t$vendor_options = array_keys( $vendors );\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_SHOPPING_PROVIDER,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Shopping provider', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => 'none',\n\t\t\t\t'enum'         => $vendor_options,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_SHOPIFY_HOST,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Shopify Host', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_SHOPIFY_ACCESS_TOKEN,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Shopify API Access Token', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => '',\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_AUTO_ADVANCE,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Auto-advance', 'web-stories' ),\n\t\t\t\t'type'         => 'boolean',\n\t\t\t\t'default'      => true,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_DEFAULT_PAGE_DURATION,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Default Page Duration', 'web-stories' ),\n\t\t\t\t'type'         => 'number',\n\t\t\t\t'default'      => 7,\n\t\t\t\t'show_in_rest' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_TRACKING_HANDLER,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Tracking Handler', 'web-stories' ),\n\t\t\t\t'type'         => 'string',\n\t\t\t\t'default'      => 'site-kit',\n\t\t\t\t'show_in_rest' => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type' => 'string',\n\t\t\t\t\t\t'enum' => [ 'site-kit', 'web-stories', 'both' ],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tregister_setting(\n\t\t\tself::SETTING_GROUP,\n\t\t\tself::SETTING_NAME_CUSTOMIZER_SETTINGS,\n\t\t\t[\n\t\t\t\t'description'  => __( 'Customizer settings', 'web-stories' ),\n\t\t\t\t'type'         => 'array',\n\t\t\t\t'default'      => [],\n\t\t\t\t'show_in_rest' => false,\n\t\t\t]\n\t\t);\n\n\t\tadd_action( 'init', [ $this, 'prime_option_caches' ] );\n\t}\n\n\t/**\n\t * Returns the value for a given setting.\n\t *\n\t * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param string $key           Setting key.\n\t * @param mixed  $default_value Optional. Default value to return if the option does not exist.\n\t * @return string|array<int|string,mixed>|bool|int Setting value.\n\t */\n\tpublic function get_setting( string $key, $default_value = false ) {\n\t\t// Distinguish between `false` as a default, and not passing one, just like WordPress.\n\t\t$passed_default = \\func_num_args() > 1;\n\n\t\tif ( $passed_default ) {\n\t\t\t/**\n\t\t\t * Setting value.\n\t\t\t *\n\t\t\t * @var string|array<int|string,mixed>|bool\n\t\t\t */\n\t\t\t$option = get_option( $key, $default_value );\n\t\t\tif ( $option === $default_value ) {\n\t\t\t\treturn $option;\n\t\t\t}\n\t\t} else {\n\t\t\t/**\n\t\t\t * Setting value.\n\t\t\t *\n\t\t\t * @var string|array<int|string,mixed>|bool\n\t\t\t */\n\t\t\t$option = get_option( $key );\n\t\t}\n\n\t\t$settings = $this->get_registered_options();\n\t\tif ( isset( $settings[ $key ] ) ) {\n\t\t\t$value = rest_sanitize_value_from_schema( $option, $settings[ $key ] );\n\t\t\tif ( is_wp_error( $value ) ) {\n\t\t\t\treturn $option;\n\t\t\t}\n\t\t\t/**\n\t\t\t * Setting value.\n\t\t\t *\n\t\t\t * @var string|array<int|string,mixed>|bool\n\t\t\t */\n\t\t\t$option = $value;\n\t\t}\n\n\t\treturn $option;\n\t}\n\n\t/**\n\t * Updates the given setting with a new value.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param string $key Setting key.\n\t * @param mixed  $value Setting value.\n\t * @return mixed Setting value.\n\t */\n\tpublic function update_setting( string $key, $value ) {\n\t\treturn update_option( $key, $value );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_option( self::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( self::SETTING_NAME_EXPERIMENTS );\n\t\tdelete_option( self::SETTING_NAME_TRACKING_ID );\n\t\tdelete_option( self::SETTING_NAME_USING_LEGACY_ANALYTICS );\n\t\tdelete_option( self::SETTING_NAME_AD_NETWORK );\n\t\tdelete_option( self::SETTING_NAME_ADSENSE_PUBLISHER_ID );\n\t\tdelete_option( self::SETTING_NAME_ADSENSE_SLOT_ID );\n\t\tdelete_option( self::SETTING_NAME_AD_MANAGER_SLOT_ID );\n\t\tdelete_option( self::SETTING_NAME_MGID_WIDGET_ID );\n\t\tdelete_option( self::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\t\tdelete_option( self::SETTING_NAME_PUBLISHER_LOGOS );\n\t\tdelete_option( self::SETTING_NAME_VIDEO_CACHE );\n\t\tdelete_option( self::SETTING_NAME_DATA_REMOVAL );\n\t\tdelete_option( self::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( self::SETTING_NAME_ARCHIVE_PAGE_ID );\n\t\tdelete_option( self::SETTING_NAME_SHOPPING_PROVIDER );\n\t\tdelete_option( self::SETTING_NAME_SHOPIFY_HOST );\n\t\tdelete_option( self::SETTING_NAME_SHOPIFY_ACCESS_TOKEN );\n\t\tdelete_option( self::SETTING_NAME_DEFAULT_PAGE_DURATION );\n\t\tdelete_option( self::SETTING_NAME_AUTO_ADVANCE );\n\t\tdelete_option( self::SETTING_NAME_TRACKING_HANDLER );\n\t}\n\n\t/**\n\t * Retrieves all of the registered options for the Settings API.\n\t * Inspired by get_registered_options method found in WordPress. But also get settings that are registered without `show_in_rest` property.\n\t *\n\t * @since 1.28.0\n\t *\n\t * @link https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php#L211-L267\n\t *\n\t * @return array<string, array<string,string>> Array of registered options.\n\t */\n\tprotected function get_registered_options(): array {\n\t\t$rest_options = [];\n\n\t\tforeach ( get_registered_settings() as $name => $args ) {\n\t\t\t$rest_args = [];\n\n\t\t\tif ( ! empty( $args['show_in_rest'] ) && \\is_array( $args['show_in_rest'] ) ) {\n\t\t\t\t$rest_args = $args['show_in_rest'];\n\t\t\t}\n\n\t\t\t$defaults = [\n\t\t\t\t'name'   => ! empty( $rest_args['name'] ) ? $rest_args['name'] : $name,\n\t\t\t\t'schema' => [],\n\t\t\t];\n\n\t\t\t$rest_args = array_merge( $defaults, $rest_args );\n\n\t\t\t$default_schema = [\n\t\t\t\t'type'        => empty( $args['type'] ) ? null : $args['type'],\n\t\t\t\t'description' => empty( $args['description'] ) ? '' : $args['description'],\n\t\t\t\t'default'     => $args['default'] ?? null,\n\t\t\t];\n\n\t\t\t$schema = array_merge( $default_schema, $rest_args['schema'] );\n\t\t\t$schema = rest_default_additional_properties_to_false( $schema );\n\n\t\t\t$rest_options[ (string) $name ] = $schema;\n\t\t}\n\n\t\treturn $rest_options;\n\t}\n}\n"
  },
  {
    "path": "includes/Shopping/Product.php",
    "content": "<?php\n/**\n * Class Product\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shopping;\n\nuse JsonSerializable;\n\n/**\n * Class Product\n *\n * @phpstan-type ProductImage array{\n *   url: string,\n *   alt: string\n * }\n * @phpstan-type ProductData array{\n *   productId?: string,\n *   productTitle?: string,\n *   productDetails?: string,\n *   productBrand?: string,\n *   productUrl?: string,\n *   productImages?: ProductImage[],\n *   productPrice?: float,\n *   productPriceCurrency?: string,\n *   aggregateRating?: array{\n *     ratingValue?: float,\n *     reviewCount?: int,\n *     reviewUrl?: string\n *   }\n * }\n */\nclass Product implements JsonSerializable {\n\t/**\n\t * Product id.\n\t */\n\tprotected string $id = '';\n\t/**\n\t * Product title.\n\t */\n\tprotected string $title = '';\n\t/**\n\t * Product brand.\n\t */\n\tprotected string $brand = '';\n\t/**\n\t * Product Price.\n\t */\n\tprotected float $price = 0.0;\n\t/**\n\t * Product's price currency.\n\t */\n\tprotected string $price_currency = '';\n\n\t/**\n\t * Product images as an array.\n\t *\n\t * @var array{url: string, alt: string}[]\n\t * @phpstan-var ProductImage[]\n\t */\n\tprotected array $images = [];\n\n\t/**\n\t * Product Details.\n\t */\n\tprotected string $details = '';\n\n\t/**\n\t * Product url.\n\t */\n\tprotected string $url = '';\n\n\t/**\n\t * Product rating.\n\t *\n\t * @var array{rating_value?: float, review_count?: int, review_url?: string}\n\t */\n\tprotected array $aggregate_rating = [];\n\n\t/**\n\t * Product constructor.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param array<string,mixed> $product Array of attributes.\n\t */\n\tpublic function __construct( array $product = [] ) {\n\t\tforeach ( $product as $key => $value ) {\n\t\t\tif ( property_exists( $this, $key ) && ! \\is_null( $value ) ) {\n\t\t\t\t$this->$key = $value;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get id.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_id(): string {\n\t\treturn $this->id;\n\t}\n\n\t/**\n\t * Get title.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_title(): string {\n\t\treturn $this->title;\n\t}\n\n\t/**\n\t * Get brand.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_brand(): string {\n\t\treturn $this->brand;\n\t}\n\n\t/**\n\t * Get price.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_price(): float {\n\t\treturn $this->price;\n\t}\n\n\t/**\n\t * Get currency.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_price_currency(): string {\n\t\treturn $this->price_currency;\n\t}\n\n\t/**\n\t * Get images property.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return array{url: string, alt: string}[]\n\t */\n\tpublic function get_images(): array {\n\t\treturn $this->images;\n\t}\n\n\t/**\n\t * Get details.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_details(): string {\n\t\treturn $this->details;\n\t}\n\n\t/**\n\t * Get url.\n\t *\n\t * @since 1.21.0\n\t */\n\tpublic function get_url(): string {\n\t\treturn $this->url;\n\t}\n\n\t/**\n\t * Get rating.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return array{rating_value?: float, review_count?: int, review_url?: string}\n\t */\n\tpublic function get_aggregate_rating(): ?array {\n\t\treturn $this->aggregate_rating;\n\t}\n\n\t/**\n\t * Retrieves the response data for JSON serialization.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return mixed Any JSON-serializable value.\n\t */\n\t#[\\ReturnTypeWillChange]\n\tpublic function jsonSerialize() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid\n\t\t$rating = $this->get_aggregate_rating();\n\n\t\t$data = [\n\t\t\t'productId'            => $this->get_id(),\n\t\t\t'productTitle'         => $this->get_title(),\n\t\t\t'productDetails'       => $this->get_details(),\n\t\t\t'productBrand'         => $this->get_brand(),\n\t\t\t'productUrl'           => $this->get_url(),\n\t\t\t'productImages'        => $this->get_images(),\n\t\t\t'productPrice'         => $this->get_price(),\n\t\t\t'productPriceCurrency' => $this->get_price_currency(),\n\t\t];\n\n\t\tif ( $rating ) {\n\t\t\t$data['aggregateRating'] = [\n\t\t\t\t'ratingValue' => $rating['rating_value'] ?? null,\n\t\t\t\t'reviewCount' => $rating['review_count'] ?? null,\n\t\t\t\t'reviewUrl'   => $rating['review_url'] ?? null,\n\t\t\t];\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t/**\n\t * Convert array to object properties.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param array<string, mixed> $product Array of product.\n\t * @return Product Product.\n\t *\n\t * @phpstan-param ProductData $product\n\t */\n\tpublic static function load_from_array( array $product ): Product {\n\t\t$product_object = new self();\n\t\t$product_object->set_id( $product['productId'] ?? '' );\n\t\t$product_object->set_title( $product['productTitle'] ?? '' );\n\t\t$product_object->set_details( $product['productDetails'] ?? '' );\n\t\t$product_object->set_brand( $product['productBrand'] ?? '' );\n\t\t$product_object->set_url( $product['productUrl'] ?? '' );\n\t\t$product_object->set_images( $product['productImages'] ?? [] );\n\t\t$product_object->set_price( $product['productPrice'] ?? 0 );\n\t\t$product_object->set_price_currency( $product['productPriceCurrency'] ?? '' );\n\n\n\t\tif ( isset( $product['aggregateRating'] ) ) {\n\t\t\t$product_object->set_aggregate_rating(\n\t\t\t\t[\n\t\t\t\t\t'rating_value' => $product['aggregateRating']['ratingValue'] ?? 0,\n\t\t\t\t\t'review_count' => $product['aggregateRating']['reviewCount'] ?? 0,\n\t\t\t\t\t'review_url'   => $product['aggregateRating']['reviewUrl'] ?? '',\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\treturn $product_object;\n\t}\n\n\t/**\n\t * Set id.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $id ID.\n\t */\n\tprotected function set_id( string $id ): void {\n\t\t$this->id = $id;\n\t}\n\n\t/**\n\t * Set title.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $title Title.\n\t */\n\tprotected function set_title( string $title ): void {\n\t\t$this->title = $title;\n\t}\n\n\t/**\n\t * Set brand.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $brand Brand.\n\t */\n\tprotected function set_brand( string $brand ): void {\n\t\t$this->brand = $brand;\n\t}\n\n\t/**\n\t * Set price.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param float $price Price.\n\t */\n\tprotected function set_price( float $price ): void {\n\t\t$this->price = $price;\n\t}\n\n\t/**\n\t * Set Price currency.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $price_currency Price Currency.\n\t */\n\tprotected function set_price_currency( string $price_currency ): void {\n\t\t$this->price_currency = $price_currency;\n\t}\n\n\t/**\n\t * Set Images.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param array{url: string, alt: string}[] $images Images.\n\t */\n\tprotected function set_images( array $images ): void {\n\t\t$this->images = $images;\n\t}\n\n\t/**\n\t * Set Details.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $details Details.\n\t */\n\tprotected function set_details( string $details ): void {\n\t\t$this->details = $details;\n\t}\n\n\t/**\n\t * Set url.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param string $url URL.\n\t */\n\tprotected function set_url( string $url ): void {\n\t\t$this->url = $url;\n\t}\n\n\t/**\n\t * Set aggregate rating.\n\t *\n\t * @since 1.26.0\n\t *\n\t * @param array{rating_value: float, review_count: int, review_url: string} $aggregate_rating Rating data in array.\n\t */\n\tprotected function set_aggregate_rating( array $aggregate_rating ): void {\n\t\t$this->aggregate_rating = $aggregate_rating;\n\t}\n}\n"
  },
  {
    "path": "includes/Shopping/Product_Meta.php",
    "content": "<?php\n/**\n * Class Product_Meta\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shopping;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Class Product_Meta.\n */\nclass Product_Meta extends Service_Base implements HasMeta, PluginUninstallAware, HasRequirements {\n\t/**\n\t * The products meta key.\n\t */\n\tpublic const PRODUCTS_POST_META_KEY = 'web_stories_products';\n\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Init.\n\t *\n\t * @since 1.22.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.22.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_post_meta(\n\t\t\t$this->story_post_type::POST_TYPE_SLUG,\n\t\t\tself::PRODUCTS_POST_META_KEY,\n\t\t\t[\n\t\t\t\t'type'              => 'object',\n\t\t\t\t'description'       => __( 'Products', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type'                 => 'object',\n\t\t\t\t\t\t'properties'           => [],\n\t\t\t\t\t\t'additionalProperties' => true,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'default'           => [],\n\t\t\t\t'single'            => true,\n\t\t\t\t'revisions_enabled' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::PRODUCTS_POST_META_KEY );\n\t}\n}\n"
  },
  {
    "path": "includes/Shopping/Shopify_Query.php",
    "content": "<?php\n/**\n * Class Shopify_Query\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shopping;\n\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\nuse Google\\Web_Stories\\Settings;\nuse WP_Error;\nuse WP_Http;\n\n/**\n * Class Shopify_Query\n *\n * @phpstan-type ShopifyGraphQLError array{\n *   message: string,\n *   extensions: array{code: string, requestId: string}\n * }[]\n * @phpstan-type ShopifyGraphQLPriceRange array{\n *   minVariantPrice: array{\n *     amount: int,\n *     currencyCode: string\n *   }\n * }\n * @phpstan-type ShopifyGraphQLProductImage array{\n *   url: string,\n *   altText?: string\n * }\n * @phpstan-type ShopifyGraphQLProduct array{\n *   id: string,\n *   handle: string,\n *   title: string,\n *   vendor: string,\n *   description: string,\n *   onlineStoreUrl?: string,\n *   images: array{\n *     edges: array{\n *       node: ShopifyGraphQLProductImage\n *     }[]\n *   },\n *   priceRange: ShopifyGraphQLPriceRange\n * }\n * @phpstan-type ShopifyGraphQLResponse array{\n *   errors?: ShopifyGraphQLError,\n *   data: array{\n *     products: array{\n *       edges: array{\n *         node: ShopifyGraphQLProduct\n *       }[],\n *       pageInfo: array{\n *         hasNextPage: bool,\n *         endCursor: string\n *       }\n *     }\n *   }\n * }\n */\nclass Shopify_Query implements Product_Query {\n\tprotected const API_VERSION = '2022-04';\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param Settings $settings Settings instance.\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort retrieved products by parameter. Default 'date'.\n\t * @param string $order       Whether to order products in ascending or descending order.\n\t *                            Accepts 'asc' (ascending) or 'desc' (descending). Default 'desc'.\n\t * @return array{products: array<Product>, has_next_page: bool}|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' ) {\n\t\t$result = $this->fetch_remote_products( $search_term, $page, $per_page, $orderby, $order );\n\t\tif ( is_wp_error( $result ) ) {\n\t\t\treturn $result;\n\t\t}\n\n\t\t$products = [];\n\n\t\t$has_next_page = $result['data']['products']['pageInfo']['hasNextPage'];\n\n\t\tforeach ( $result['data']['products']['edges'] as $edge ) {\n\t\t\t$product = $edge['node'];\n\n\t\t\t$images = [];\n\n\t\t\tforeach ( $product['images']['edges'] as $image_edge ) {\n\t\t\t\t$image    = $image_edge['node'];\n\t\t\t\t$images[] = [\n\t\t\t\t\t'url' => $image['url'],\n\t\t\t\t\t'alt' => $image['altText'] ?? '',\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t// URL is null if the resource is currently not published to the Online Store sales channel,\n\t\t\t// or if the shop is password-protected.\n\t\t\t// In this case, we can fall back to a manually constructed product URL.\n\t\t\t$product_url = $product['onlineStoreUrl'] ?? \\sprintf( 'https://%1$s/products/%2$s/', $this->get_host(), $product['handle'] );\n\n\t\t\t$products[] = new Product(\n\t\t\t\t[\n\t\t\t\t\t'id'             => $product['id'],\n\t\t\t\t\t'title'          => $product['title'],\n\t\t\t\t\t'brand'          => $product['vendor'],\n\t\t\t\t\t// TODO: Maybe eventually provide full price range.\n\t\t\t\t\t// See https://github.com/ampproject/amphtml/issues/37957.\n\t\t\t\t\t'price'          => (float) $product['priceRange']['minVariantPrice']['amount'],\n\t\t\t\t\t'price_currency' => $product['priceRange']['minVariantPrice']['currencyCode'],\n\t\t\t\t\t'images'         => $images,\n\t\t\t\t\t'details'        => $product['description'],\n\t\t\t\t\t// URL is null if the resource is currently not published to the Online Store sales channel,\n\t\t\t\t\t// or if the shop is password-protected.\n\t\t\t\t\t'url'            => $product_url,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\treturn compact( 'products', 'has_next_page' );\n\t}\n\n\t/**\n\t * Returns the Shopify host name.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return string Shopify host.\n\t */\n\tprotected function get_host(): string {\n\t\t/**\n\t\t * Host name.\n\t\t *\n\t\t * @var string $host\n\t\t */\n\t\t$host = $this->settings->get_setting( Settings::SETTING_NAME_SHOPIFY_HOST );\n\t\treturn $host;\n\t}\n\n\t/**\n\t * Returns the Shopify access token.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return string Shopify access token.\n\t */\n\tprotected function get_access_token(): string {\n\t\t/**\n\t\t * Access token.\n\t\t *\n\t\t * @var string $access_token\n\t\t */\n\t\t$access_token = $this->settings->get_setting( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN );\n\t\treturn $access_token;\n\t}\n\n\t/**\n\t * Remotely executes a GraphQL query.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $query GraphQL query to execute.\n\t * @return string|WP_Error Query result or error object on failure.\n\t */\n\tprotected function execute_query( string $query ) {\n\t\t$host         = $this->get_host();\n\t\t$access_token = $this->get_access_token();\n\n\t\tif ( empty( $host ) || empty( $access_token ) ) {\n\t\t\treturn new WP_Error( 'rest_missing_credentials', __( 'Missing API credentials.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\tif ( ! preg_match( '/^[\\w-]+\\.myshopify\\.com$/i', $host ) ) {\n\t\t\treturn new WP_Error( 'rest_invalid_hostname', __( 'Invalid Shopify hostname.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t$url = esc_url_raw(\n\t\t\t\\sprintf(\n\t\t\t\t'https://%1$s/api/%2$s/graphql.json',\n\t\t\t\t$host,\n\t\t\t\tself::API_VERSION\n\t\t\t)\n\t\t);\n\n\t\t$response = wp_remote_post(\n\t\t\t$url,\n\t\t\t[\n\t\t\t\t'headers' => [\n\t\t\t\t\t'Content-Type'                      => 'application/graphql',\n\t\t\t\t\t'X-Shopify-Storefront-Access-Token' => $access_token,\n\t\t\t\t],\n\t\t\t\t'body'    => $query,\n\t\t\t]\n\t\t);\n\n\t\t$status_code = wp_remote_retrieve_response_code( $response );\n\n\t\tif ( WP_Http::UNAUTHORIZED === $status_code || WP_Http::NOT_FOUND === $status_code ) {\n\t\t\treturn new WP_Error( 'rest_invalid_credentials', __( 'Invalid API credentials.', 'web-stories' ), [ 'status' => $status_code ] );\n\t\t}\n\n\t\tif ( WP_Http::OK !== $status_code ) {\n\t\t\treturn new WP_Error( 'rest_unknown', __( 'Error fetching products', 'web-stories' ), [ 'status' => $status_code ] );\n\t\t}\n\n\t\treturn wp_remote_retrieve_body( $response );\n\t}\n\n\t/**\n\t * Returns the GraphQL query for getting all products from the store.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term  Search term to filter products by.\n\t * @param string $after        The cursor to retrieve nodes after in the connection.\n\t * @param int    $per_page     Number of products to be fetched.\n\t * @param string $orderby      Sort collection by product attribute.\n\t * @param string $order        Order sort attribute ascending or descending.\n\t * @return string              The assembled GraphQL query.\n\t */\n\tprotected function get_products_query( string $search_term, string $after, int $per_page, string $orderby, string $order ): string {\n\t\t$search_string = empty( $search_term ) ? '*' : '*' . $search_term . '*';\n\t\t$sortkey       = 'date' === $orderby ? 'CREATED_AT' : strtoupper( $orderby );\n\t\t$reverse       = 'asc' === $order ? 'false' : 'true';\n\t\t$after         = empty( $after ) ? 'null' : \\sprintf( '\"%s\"', $after );\n\n\t\treturn <<<QUERY\n{\n  products(first: $per_page, after: $after, sortKey: $sortkey, reverse: $reverse, query: \"title:$search_string\") {\n    edges {\n      node {\n        id\n        handle\n        title\n        vendor\n        description\n        priceRange {\n          minVariantPrice {\n            amount\n            currencyCode\n          }\n        }\n        onlineStoreUrl\n        images(first: 10) {\n          edges {\n            node {\n              url(transform:{maxWidth:1000,maxHeight:1000})\n              altText\n            }\n          }\n        }\n      }\n    }\n    pageInfo {\n       hasNextPage\n       endCursor\n    }\n  }\n}\nQUERY;\n\t}\n\n\t/**\n\t * Remotely fetches all products from the store.\n\t *\n\t * Retrieves cached data if available.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term  Search term to filter products by.\n\t * @param string $after        The cursor to retrieve nodes after in the connection.\n\t * @param int    $per_page     Number of products to be fetched.\n\t * @param string $orderby      Sort retrieved products by parameter.\n\t * @param string $order        Whether to order products in ascending or descending order.\n\t *                             Accepts 'asc' (ascending) or 'desc' (descending).\n\t * @return array|WP_Error      Response data or error object on failure.\n\t *\n\t * @phpstan-return ShopifyGraphQLResponse|WP_Error\n\t */\n\tprotected function get_remote_products( string $search_term, string $after, int $per_page, string $orderby, string $order ) {\n\t\t/**\n\t\t * Filters the Shopify products data TTL value.\n\t\t *\n\t\t * @since 1.21.0\n\t\t *\n\t\t * @param int $time Time to live (in seconds). Default is 5 minutes.\n\t\t */\n\t\t$cache_ttl = apply_filters( 'web_stories_shopify_data_cache_ttl', 5 * MINUTE_IN_SECONDS );\n\t\t$cache_key = $this->get_cache_key( $search_term, $after, $per_page, $orderby, $order );\n\n\t\t$data = get_transient( $cache_key );\n\n\t\tif ( \\is_string( $data ) && ! empty( $data ) ) {\n\t\t\t/**\n\t\t\t * Cached response.\n\t\t\t *\n\t\t\t * @phpstan-var ShopifyGraphQLResponse $cached_result\n\t\t\t */\n\t\t\t$cached_result = (array) json_decode( $data, true );\n\t\t\treturn $cached_result;\n\t\t}\n\n\t\t$query = $this->get_products_query( $search_term, $after, $per_page, $orderby, $order );\n\t\t$body  = $this->execute_query( $query );\n\t\tif ( is_wp_error( $body ) ) {\n\t\t\treturn $body;\n\t\t}\n\n\t\t/**\n\t\t * Shopify GraphQL API response.\n\t\t *\n\t\t * @var array $result\n\t\t * @phpstan-var ShopifyGraphQLResponse $result\n\t\t */\n\t\t$result = json_decode( $body, true );\n\t\tif ( isset( $result['errors'] ) ) {\n\t\t\t$wp_error = new WP_Error();\n\t\t\tforeach ( $result['errors'] as $error ) {\n\t\t\t\t$error_code = $error['extensions']['code'];\n\t\t\t\t// https://shopify.dev/api/storefront#status_and_error_codes.\n\t\t\t\tswitch ( $error_code ) {\n\t\t\t\t\tcase 'THROTTLED':\n\t\t\t\t\t\t$wp_error->add( 'rest_throttled', __( 'Shopify API rate limit exceeded. Try again later.', 'web-stories' ), [ 'status' => 429 ] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'ACCESS_DENIED':\n\t\t\t\t\t\t$wp_error->add( 'rest_invalid_credentials', __( 'Invalid Shopify API credentials provided.', 'web-stories' ), [ 'status' => 401 ] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'SHOP_INACTIVE':\n\t\t\t\t\t\t$wp_error->add( 'rest_inactive_shop', __( 'Inactive Shopify shop.', 'web-stories' ), [ 'status' => 403 ] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'INTERNAL_SERVER_ERROR':\n\t\t\t\t\t\t$wp_error->add( 'rest_internal_error', __( 'Shopify experienced an internal server error.', 'web-stories' ), [ 'status' => 500 ] );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$wp_error->add( 'rest_unknown', __( 'Error fetching products from Shopify.', 'web-stories' ), [ 'status' => 500 ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $wp_error;\n\t\t}\n\n\t\t// TODO: Maybe cache errors too?\n\t\tset_transient( $cache_key, $body, $cache_ttl );\n\n\t\treturn $result;\n\t}\n\n\t/**\n\t * Get cache key for properties.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param string $search_term  Search term to filter products by.\n\t * @param string $after        The cursor to retrieve nodes after in the connection.\n\t * @param int    $per_page     Number of products to be fetched.\n\t * @param string $orderby      Sort retrieved products by parameter.\n\t * @param string $order        Whether to order products in ascending or descending order.\n\t *                             Accepts 'asc' (ascending) or 'desc' (descending).\n\t */\n\tprotected function get_cache_key( string $search_term, string $after, int $per_page, string $orderby, string $order ): string {\n\t\t$cache_args = (string) wp_json_encode( compact( 'search_term', 'after', 'per_page', 'orderby', 'order' ) );\n\n\t\treturn 'web_stories_shopify_data_' . md5( $cache_args );\n\t}\n\n\t/**\n\t * Remotely fetches all products from the store.\n\t *\n\t * @since 1.22.0\n\t *\n\t * @param string $search_term Search term to filter products by.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort retrieved products by parameter.\n\t * @param string $order       Whether to order products in ascending or descending order.\n\t *                            Accepts 'asc' (ascending) or 'desc' (descending).\n\t * @return array|WP_Error Response data or error object on failure.\n\t *\n\t * @phpstan-return ShopifyGraphQLResponse|WP_Error\n\t */\n\tprotected function fetch_remote_products( string $search_term, int $page, int $per_page, string $orderby, string $order ) {\n\t\t$after = '';\n\t\tif ( $page > 1 ) {\n\t\t\t// Loop around all the pages, getting the endCursor of each page, until you get the last one.\n\t\t\tfor ( $i = 1; $i < $page; $i++ ) {\n\t\t\t\t$result = $this->get_remote_products( $search_term, $after, $per_page, $orderby, $order );\n\t\t\t\tif ( is_wp_error( $result ) ) {\n\t\t\t\t\treturn $result;\n\t\t\t\t}\n\n\t\t\t\t$has_next_page = $result['data']['products']['pageInfo']['hasNextPage'];\n\t\t\t\tif ( ! $has_next_page ) {\n\t\t\t\t\treturn new WP_Error( 'rest_no_page', __( 'Error fetching products from Shopify.', 'web-stories' ), [ 'status' => 404 ] );\n\t\t\t\t}\n\t\t\t\t$after = (string) $result['data']['products']['pageInfo']['endCursor'];\n\t\t\t}\n\t\t}\n\n\t\treturn $this->get_remote_products( $search_term, $after, $per_page, $orderby, $order );\n\t}\n}\n"
  },
  {
    "path": "includes/Shopping/Shopping_Vendors.php",
    "content": "<?php\n/**\n * Shopping vendors class.\n *\n * A central class to register shopping vendors.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shopping;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\n\n/**\n * Class Shopping_Vendors.\n */\nclass Shopping_Vendors {\n\n\t/**\n\t * Injector instance.\n\t *\n\t * @var Injector Injector instance.\n\t */\n\tprivate Injector $injector;\n\n\t/**\n\t * Shopping_Vendors constructor.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param Injector $injector Injector instance.\n\t */\n\tpublic function __construct( Injector $injector ) {\n\t\t$this->injector = $injector;\n\t}\n\n\t/**\n\t * Get an instance of product query class by vendor's name.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $name Name of vendor.\n\t */\n\tpublic function get_vendor_class( string $name ): ?Product_Query {\n\t\t$vendors = $this->get_vendors();\n\n\t\tif ( ! isset( $vendors[ $name ]['class'] ) || ! class_exists( $vendors[ $name ]['class'] ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t$query = $this->injector->make( $vendors[ $name ]['class'] );\n\n\t\tif ( ! $query instanceof Product_Query ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn $query;\n\t}\n\n\t/**\n\t * Get an array of registered vendors.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @return array<string,array{label: string, class?: class-string}> Array of vendors.\n\t */\n\tpublic function get_vendors(): array {\n\t\t$vendors = [\n\t\t\t'none'        => [\n\t\t\t\t'label' => __( 'None', 'web-stories' ),\n\t\t\t],\n\t\t\t'shopify'     => [\n\t\t\t\t'label' => __( 'Shopify', 'web-stories' ),\n\t\t\t\t'class' => Shopify_Query::class,\n\t\t\t],\n\t\t\t'woocommerce' => [\n\t\t\t\t'label' => __( 'WooCommerce', 'web-stories' ),\n\t\t\t\t'class' => WooCommerce_Query::class,\n\t\t\t],\n\t\t];\n\n\t\t/**\n\t\t * Filter the array of vendors.\n\t\t *\n\t\t * @since 1.21.0\n\t\t *\n\t\t * @param array $vendors Associative array of vendor, including label and class.\n\t\t */\n\t\t$vendors = apply_filters( 'web_stories_shopping_vendors', $vendors );\n\n\t\treturn $vendors;\n\t}\n}\n"
  },
  {
    "path": "includes/Shopping/WooCommerce_Query.php",
    "content": "<?php\n/**\n * Class WooCommerce_Query\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shopping;\n\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\nuse WC_Product;\nuse WC_Query;\nuse WP_Error;\n\n/**\n * Class WooCommerce_Query.\n */\nclass WooCommerce_Query implements Product_Query {\n\t/**\n\t * WooCommerce instance.\n\t *\n\t * @var WooCommerce WooCommerce instance.\n\t */\n\tprivate WooCommerce $woocommerce;\n\n\t/**\n\t * Constructor.\n\t *\n\t * @param WooCommerce $woocommerce WooCommerce instance.\n\t */\n\tpublic function __construct( WooCommerce $woocommerce ) {\n\t\t$this->woocommerce = $woocommerce;\n\t}\n\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort collection by product attribute.\n\t * @param string $order       Order sort attribute ascending or descending.\n\t * @return array{products: array<Product>, has_next_page: bool}|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' ) {\n\t\t$status = $this->woocommerce->get_plugin_status();\n\n\t\tif ( ! $status['installed'] ) {\n\t\t\treturn new WP_Error( 'rest_woocommerce_not_installed', __( 'WooCommerce is not installed.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\tif ( ! $status['active'] ) {\n\t\t\treturn new WP_Error( 'rest_woocommerce_not_activated', __( 'WooCommerce is not activated. Please activate it again try again.', 'web-stories' ), [ 'status' => 400 ] );\n\t\t}\n\n\t\t$args = [\n\t\t\t'status'   => 'publish',\n\t\t\t'page'     => $page,\n\t\t\t'limit'    => $per_page,\n\t\t\t's'        => $search_term,\n\t\t\t'orderby'  => $orderby,\n\t\t\t'order'    => $order,\n\t\t\t'paginate' => true,\n\t\t];\n\t\tif ( 'price' === $orderby ) {\n\t\t\t$wc_query = new WC_Query();\n\t\t\t$wc_args  = $wc_query->get_catalog_ordering_args( $orderby, strtoupper( $order ) );\n\t\t\t$args     = array_merge( $args, $wc_args );\n\t\t}\n\n\t\t/**\n\t\t * Product query object.\n\t\t *\n\t\t * @var \\stdClass $product_query\n\t\t */\n\t\t$product_query = wc_get_products( $args );\n\n\t\t$has_next_page = ( $product_query->max_num_pages > $page );\n\n\t\t/**\n\t\t * Products.\n\t\t *\n\t\t * @var WC_Product[] $wc_products\n\t\t */\n\t\t$wc_products = $product_query->products;\n\n\t\t$product_image_ids = [];\n\t\tforeach ( $wc_products as $product ) {\n\t\t\t$product_image_ids[] = $this->get_product_image_ids( $product );\n\t\t}\n\t\t$products_image_ids = array_merge( [], ...$product_image_ids );\n\n\t\t/**\n\t\t * Warm the object cache with post and meta information for all found\n\t\t * images to avoid making individual database calls.\n\t\t */\n\t\t_prime_post_caches( $products_image_ids, false, true );\n\n\t\t$products = [];\n\t\tforeach ( $wc_products as $product ) {\n\n\t\t\t$images = array_map(\n\t\t\t\t[ $this, 'get_product_image' ],\n\t\t\t\t$this->get_product_image_ids( $product )\n\t\t\t);\n\n\t\t\t$product_object = new Product(\n\t\t\t\t[\n\t\t\t\t\t// amp-story-shopping requires non-numeric IDs.\n\t\t\t\t\t'id'               => 'wc-' . $product->get_id(),\n\t\t\t\t\t'title'            => $product->get_title(),\n\t\t\t\t\t'brand'            => '', // TODO: Figure out how to best provide that.\n\t\t\t\t\t'price'            => (float) $product->get_price(),\n\t\t\t\t\t'price_currency'   => get_woocommerce_currency(),\n\t\t\t\t\t'images'           => $images,\n\t\t\t\t\t'aggregate_rating' => [\n\t\t\t\t\t\t'rating_value' => (float) $product->get_average_rating(),\n\t\t\t\t\t\t'review_count' => $product->get_rating_count(),\n\t\t\t\t\t\t'review_url'   => $product->get_permalink(),\n\t\t\t\t\t],\n\t\t\t\t\t'details'          => wp_strip_all_tags( $product->get_short_description() ),\n\t\t\t\t\t'url'              => $product->get_permalink(),\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$products[] = $product_object;\n\t\t}\n\n\t\treturn compact( 'products', 'has_next_page' );\n\t}\n\n\t/**\n\t * Get all product image ids (feature image + gallery_images).\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param WC_Product $product Product.\n\t * @return int[]\n\t */\n\tprotected function get_product_image_ids( WC_Product $product ): array {\n\t\t$product_image_ids = $product->get_gallery_image_ids();\n\t\tarray_unshift( $product_image_ids, $product->get_image_id() );\n\t\t$product_image_ids = array_map( 'absint', $product_image_ids );\n\t\treturn array_unique( array_filter( $product_image_ids ) );\n\t}\n\n\t/**\n\t * Get product image, url and alt.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param int $image_id Attachment ID.\n\t * @return array{url?: string, alt?: string}\n\t */\n\tprotected function get_product_image( int $image_id ): array {\n\t\t$url = wp_get_attachment_image_url( $image_id, 'large' );\n\n\t\tif ( ! $url ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t/**\n\t\t * Alt text.\n\t\t *\n\t\t * @var string $alt\n\t\t */\n\t\t$alt = get_post_meta( $image_id, '_wp_attachment_image_alt', true );\n\n\t\tif ( empty( $alt ) ) {\n\t\t\t$alt = '';\n\t\t}\n\n\t\treturn compact( 'url', 'alt' );\n\t}\n}\n"
  },
  {
    "path": "includes/Shortcode/Embed_Shortcode.php",
    "content": "<?php\n/**\n * Class Embed_Shortcode.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shortcode;\n\nuse Google\\Web_Stories\\Embed_Base;\n\n/**\n * Embed shortcode class.\n */\nclass Embed_Shortcode extends Embed_Base {\n\t/**\n\t * Shortcode name.\n\t */\n\tpublic const SHORTCODE_NAME = 'web_stories_embed';\n\n\t/**\n\t * Initializes the Web Stories embed shortcode.\n\t *\n\t * @since 1.1.0\n\t */\n\tpublic function register(): void {\n\t\tadd_shortcode( self::SHORTCODE_NAME, [ $this, 'render_shortcode' ] );\n\t}\n\n\t/**\n\t * Renders the shortcode  for given attributes.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param array<string, string|int>|string $attributes Shortcode attributes.\n\t * @param string|null                      $content    Shortcode content.\n\t * @return string Rendered Shortcode\n\t */\n\tpublic function render_shortcode( $attributes, ?string $content ): string { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable\n\t\t// Initialize '$attrs' when not an array OR is an empty string.\n\t\tif ( empty( $attributes ) || ! \\is_array( $attributes ) ) {\n\t\t\t$attributes = [];\n\t\t}\n\n\t\t$attributes = shortcode_atts( $this->default_attrs(), $attributes, self::SHORTCODE_NAME );\n\n\t\t$attributes['class'] = 'wp-shortcode-web-stories-embed';\n\n\t\treturn $this->render( $attributes );\n\t}\n}\n"
  },
  {
    "path": "includes/Shortcode/Stories_Shortcode.php",
    "content": "<?php\n/**\n * Class Stories_Shortcode.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Shortcode;\n\nuse Google\\Web_Stories\\Service_Base;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query as Stories;\n\n/**\n * Class Stories_Shortcode\n *\n * @phpstan-import-type StoryAttributes from \\Google\\Web_Stories\\Story_Query\n */\nclass Stories_Shortcode extends Service_Base {\n\n\t/**\n\t * Shortcode name.\n\t */\n\tpublic const SHORTCODE_NAME = 'web_stories';\n\n\t/**\n\t * Initializes the Stories shortcode.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function register(): void {\n\t\tadd_shortcode( self::SHORTCODE_NAME, [ $this, 'render_stories' ] );\n\t}\n\n\t/**\n\t * Callback for the shortcode.\n\t *\n\t * This will render the stories according to given\n\t * shortcode attributes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string|int>|string $attrs Shortcode attributes.\n\t * @return string Story markup.\n\t */\n\tpublic function render_stories( $attrs ): string {\n\t\t$default_pairs = [\n\t\t\t'view'               => 'circles',\n\t\t\t'number_of_columns'  => 1,\n\t\t\t'title'              => 'false',\n\t\t\t'excerpt'            => 'false',\n\t\t\t'author'             => 'false',\n\t\t\t'date'               => 'false',\n\t\t\t'archive_link'       => 'false',\n\t\t\t'archive_link_label' => __( 'View all stories', 'web-stories' ),\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'class'              => '',\n\t\t\t'circle_size'        => 150,\n\t\t\t'number_of_stories'  => 10,\n\t\t\t'order'              => 'DESC',\n\t\t\t'orderby'            => 'post_date',\n\t\t\t'sharp_corners'      => 'false',\n\t\t];\n\n\t\t$taxonomies = get_object_taxonomies( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\tforeach ( $taxonomies as $taxonomy ) {\n\t\t\t$default_pairs[ $taxonomy ] = '';\n\t\t}\n\n\t\t// Initialize '$attrs' when not an array OR is an empty string.\n\t\tif ( empty( $attrs ) || ! \\is_array( $attrs ) ) {\n\t\t\t$attrs = [];\n\t\t}\n\t\t\n\t\t$attributes = shortcode_atts(\n\t\t\t$default_pairs,\n\t\t\t$attrs,\n\t\t\tself::SHORTCODE_NAME\n\t\t);\n\n\t\t$stories = new Stories( $this->prepare_story_attrs( $attributes ), $this->prepare_story_args( $attributes ) );\n\n\t\treturn $stories->render();\n\t}\n\n\t/**\n\t * Prepare story attributes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string|int> $attributes Shortcode attributes.\n\t * @return array<string,string|int> Attributes to pass to Story_Query class.\n\t *\n\t * @phpstan-return StoryAttributes\n\t */\n\tprivate function prepare_story_attrs( array $attributes ): array {\n\t\treturn [\n\t\t\t'view_type'          => (string) $attributes['view'],\n\t\t\t'number_of_columns'  => (int) $attributes['number_of_columns'],\n\t\t\t'show_title'         => ( 'true' === $attributes['title'] ),\n\t\t\t'show_author'        => ( 'true' === $attributes['author'] ),\n\t\t\t'show_date'          => ( 'true' === $attributes['date'] ),\n\t\t\t'show_excerpt'       => ( 'true' === $attributes['excerpt'] ),\n\t\t\t'show_archive_link'  => ( 'true' === $attributes['archive_link'] ),\n\t\t\t'archive_link_label' => (string) $attributes['archive_link_label'],\n\t\t\t'image_alignment'    => (string) $attributes['image_alignment'],\n\t\t\t'class'              => (string) $attributes['class'],\n\t\t\t'circle_size'        => (int) $attributes['circle_size'],\n\t\t\t'sharp_corners'      => ( 'true' === $attributes['sharp_corners'] ),\n\t\t];\n\t}\n\n\t/**\n\t * Prepare story arguments.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,int|string> $attributes Array of arguments for Story Query.\n\t * @return array<string,mixed> Array of story arguments to pass to Story_Query.\n\t */\n\tprivate function prepare_story_args( array $attributes ): array {\n\t\t$args = [\n\t\t\t// Show 100 stories at most to avoid 500 errors.\n\t\t\t'posts_per_page' => min( (int) $attributes['number_of_stories'], 100 ), // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page\n\t\t\t'order'          => 'ASC' === $attributes['order'] ? 'ASC' : 'DESC',\n\t\t\t'orderby'        => $attributes['orderby'],\n\t\t];\n\n\t\t$taxonomies           = get_object_taxonomies( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$should_add_tax_query = false;\n\n\t\tforeach ( $taxonomies as $taxonomy ) {\n\t\t\tif ( '' !== $attributes[ $taxonomy ] ) {\n\t\t\t\t$should_add_tax_query = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( $should_add_tax_query ) {\n\t\t\t$tax_query = [\n\t\t\t\t'relation' => 'OR',\n\t\t\t];\n\n\t\t\tforeach ( $taxonomies as $taxonomy ) {\n\t\t\t\t$tax_query[] = [\n\t\t\t\t\t'taxonomy' => $taxonomy,\n\t\t\t\t\t'field'    => 'name',\n\t\t\t\t\t'terms'    => $attributes[ $taxonomy ] ? array_map( 'trim', explode( ',', (string) $attributes[ $taxonomy ] ) ) : [],\n\t\t\t\t];\n\t\t\t}\n\t\t\t// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query\n\t\t\t$args['tax_query'] = $tax_query;\n\t\t}\n\t\treturn $args;\n\t}\n}\n"
  },
  {
    "path": "includes/Stories_Script_Data.php",
    "content": "<?php\n/**\n * Stories script data class.\n *\n * Stories data which will be required by various JS scripts.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Renderer\\Stories\\FieldStateFactory\\Factory;\n\n/**\n * Class Stories_Script_Data.\n */\nclass Stories_Script_Data {\n\n\t/**\n\t * Injector instance.\n\t *\n\t * @var Injector Injector instance.\n\t */\n\tprivate Injector $injector;\n\n\t/**\n\t * Factory constructor.\n\t *\n\t * @param Injector $injector Injector instance.\n\t */\n\tpublic function __construct( Injector $injector ) {\n\t\t$this->injector = $injector;\n\t}\n\n\t/**\n\t * Returns data array for use in inline script.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string,array<string|int,array<string, mixed>>> Script data.\n\t */\n\tpublic function get_script_data(): array {\n\t\t$views      = $this->get_layouts();\n\t\t$view_types = [];\n\n\t\tforeach ( $views as $view_key => $view_label ) {\n\t\t\t$view_types[] = [\n\t\t\t\t'label' => $view_label,\n\t\t\t\t'value' => $view_key,\n\t\t\t];\n\t\t}\n\n\t\t$field_states = $this->fields_states();\n\n\t\treturn [\n\t\t\t'views'  => $view_types,\n\t\t\t'fields' => $field_states,\n\t\t];\n\t}\n\n\t/**\n\t * Wrapper function for fetching field states\n\t * based on the view types.\n\t *\n\t * Mainly uses FieldState and Fields classes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string,array<string,array<string,string|bool>>> Field states.\n\t */\n\tpublic function fields_states(): array {\n\t\t$field_states = [];\n\t\t/**\n\t\t * Factory instance.\n\t\t *\n\t\t * @var Factory\n\t\t */\n\t\t$factory = $this->injector->make( Factory::class );\n\n\t\t$views = $this->get_layouts();\n\n\t\t$fields = [\n\t\t\t'title',\n\t\t\t'author',\n\t\t\t'date',\n\t\t\t'image_alignment',\n\t\t\t'excerpt',\n\t\t\t'sharp_corners',\n\t\t\t'archive_link',\n\t\t\t'circle_size',\n\t\t\t'number_of_columns',\n\t\t];\n\n\t\tforeach ( array_keys( $views ) as $view_type ) {\n\t\t\t$field_state = $factory->get_field( (string) $view_type );\n\t\t\tforeach ( $fields as $field ) {\n\t\t\t\t$field_states[ $view_type ][ $field ] = [\n\t\t\t\t\t'show'   => $field_state->$field()->show(),\n\t\t\t\t\t'label'  => $field_state->$field()->label(),\n\t\t\t\t\t'hidden' => $field_state->$field()->hidden(),\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\treturn $field_states;\n\t}\n\n\t/**\n\t * Get supported layouts for web stories.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @return array<string,string>\n\t */\n\tpublic function get_layouts(): array {\n\t\treturn [\n\t\t\t'carousel' => __( 'Box Carousel', 'web-stories' ),\n\t\t\t'circles'  => __( 'Circle Carousel', 'web-stories' ),\n\t\t\t'grid'     => __( 'Grid', 'web-stories' ),\n\t\t\t'list'     => __( 'List', 'web-stories' ),\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Story_Archive.php",
    "content": "<?php\n/**\n * Class Story_Archive.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse WP_Post;\nuse WP_Query;\nuse WP_Rewrite;\n\n/**\n * Class Story_Archive.\n */\nclass Story_Archive extends Service_Base {\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Analytics constructor.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param Settings        $settings        Settings instance.\n\t * @param Story_Post_Type $story_post_type Experiments instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings, Story_Post_Type $story_post_type ) {\n\t\t$this->settings        = $settings;\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Registers Filters and actions\n\t *\n\t * @since 1.13.0\n\t */\n\tpublic function register(): void {\n\t\tadd_filter( 'pre_handle_404', [ $this, 'redirect_post_type_archive_urls' ], 10, 2 );\n\n\t\tadd_action( 'add_option_' . $this->settings::SETTING_NAME_ARCHIVE, [ $this, 'update_archive_setting' ] );\n\t\tadd_action( 'update_option_' . $this->settings::SETTING_NAME_ARCHIVE, [ $this, 'update_archive_setting' ] );\n\t\tadd_action( 'add_option_' . $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, [ $this, 'update_archive_setting' ] );\n\t\tadd_action( 'update_option_' . $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, [ $this, 'update_archive_setting' ] );\n\n\t\tadd_filter( 'display_post_states', [ $this, 'filter_display_post_states' ], 10, 2 );\n\t\tadd_action( 'pre_get_posts', [ $this, 'pre_get_posts' ] );\n\t\tadd_action( 'wp_trash_post', [ $this, 'on_remove_archive_page' ] );\n\t\tadd_action( 'delete_post', [ $this, 'on_remove_archive_page' ] );\n\t}\n\n\t/**\n\t * Handles redirects to the post type archive.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param bool|mixed $bypass Pass-through of the pre_handle_404 filter value.\n\t * @param \\WP_Query  $query  The WP_Query object.\n\t * @return bool|mixed Whether to pass-through or not.\n\t */\n\tpublic function redirect_post_type_archive_urls( $bypass, WP_Query $query ) {\n\t\tglobal $wp_rewrite;\n\n\t\tif ( $bypass || ! \\is_string( $this->story_post_type->get_has_archive() ) || ( ! $wp_rewrite instanceof WP_Rewrite || ! $wp_rewrite->using_permalinks() ) ) {\n\t\t\treturn $bypass;\n\t\t}\n\n\t\t// 'pagename' is for most permalink types, name is for when the %postname% is used as a top-level field.\n\t\tif ( $this->story_post_type::REWRITE_SLUG === $query->get( 'pagename' ) || $this->story_post_type::REWRITE_SLUG === $query->get( 'name' ) ) {\n\t\t\t$redirect_url = get_post_type_archive_link( $this->story_post_type->get_slug() );\n\n\t\t\tif ( ! $redirect_url ) {\n\t\t\t\treturn $bypass;\n\t\t\t}\n\n\t\t\t// Only exit if there was actually a location to redirect to.\n\t\t\t// Allows filtering location in tests to verify behavior.\n\t\t\tif ( wp_safe_redirect( $redirect_url, 301 ) ) {\n\t\t\t\texit;\n\t\t\t}\n\t\t}\n\n\t\treturn $bypass;\n\t}\n\n\t/**\n\t * Clear rewrite rules on update on setting.\n\t *\n\t * @since 1.13.0\n\t */\n\tpublic function update_archive_setting(): void {\n\t\t$this->story_post_type->unregister_post_type();\n\t\t$this->story_post_type->register_post_type();\n\n\t\tif ( ! \\defined( '\\WPCOM_IS_VIP_ENV' ) || false === \\WPCOM_IS_VIP_ENV ) {\n\t\t\tflush_rewrite_rules( false );\n\t\t}\n\t}\n\n\t/**\n\t * Modifies the current query to set up the custom archive page.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param WP_Query $query Current query instance, passed by reference.\n\t */\n\tpublic function pre_get_posts( WP_Query $query ): void {\n\t\tif ( ! \\is_string( $this->story_post_type->get_has_archive() ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( $query->is_admin || ! $query->is_main_query() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! $query->is_post_type_archive( $this->story_post_type->get_slug() ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$query->set( 'page_id', $custom_archive_page_id );\n\t\t$query->set( 'post_type', 'page' );\n\t\t$query->is_post_type_archive = false;\n\t\t$query->is_archive           = false;\n\t\t$query->is_singular          = true;\n\t\t$query->is_page              = true;\n\t}\n\n\t/**\n\t * Resets archive settings when the custom archive page is trashed.\n\t *\n\t * @since 1.14.0\n\t *\n\t * @param int $postid Post ID.\n\t */\n\tpublic function on_remove_archive_page( int $postid ): void {\n\t\tif ( 'page' !== get_post_type( $postid ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\tif ( $custom_archive_page_id !== $postid ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ARCHIVE, 'default' );\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, 0 );\n\t}\n\n\t/**\n\t * Filters the default post display states used in the posts list table.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @param string[]|mixed $post_states An array of post display states.\n\t * @param WP_Post|null   $post        The current post object.\n\t * @return string[]|mixed Filtered post display states.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($post_states is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_display_post_states( $post_states, ?WP_Post $post ) {\n\t\tif ( ! \\is_array( $post_states ) || ! $post ) {\n\t\t\treturn $post_states;\n\t\t}\n\n\t\tif ( ! \\is_string( $this->story_post_type->get_has_archive() ) ) {\n\t\t\treturn $post_states;\n\t\t}\n\n\t\t$custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\tif ( $post->ID === $custom_archive_page_id ) {\n\t\t\t$post_states['web_stories_archive_page'] = __( 'Web Stories Archive Page', 'web-stories' );\n\t\t}\n\n\t\treturn $post_states;\n\t}\n}\n"
  },
  {
    "path": "includes/Story_Post_Type.php",
    "content": "<?php\n/**\n * Class Story_Post_Type.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\REST_API\\Stories_Autosaves_Controller;\nuse Google\\Web_Stories\\REST_API\\Stories_Controller;\nuse WP_Post;\n\n/**\n * Class Story_Post_Type.\n *\n * @phpstan-import-type PostTypeArgs from \\Google\\Web_Stories\\Post_Type_Base\n */\nclass Story_Post_Type extends Post_Type_Base implements HasRequirements, HasMeta {\n\n\t/**\n\t * The slug of the stories post type.\n\t */\n\tpublic const POST_TYPE_SLUG = 'web-story';\n\n\t/**\n\t * The rewrite slug for this post type.\n\t */\n\tpublic const REWRITE_SLUG = 'web-stories';\n\n\t/**\n\t * Style Present options name.\n\t */\n\tpublic const STYLE_PRESETS_OPTION = 'web_stories_style_presets';\n\n\t/**\n\t * Publisher logo meta key.\n\t */\n\tpublic const PUBLISHER_LOGO_META_KEY = 'web_stories_publisher_logo';\n\n\t/**\n\t * Poster meta key.\n\t */\n\tpublic const POSTER_META_KEY = 'web_stories_poster';\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\n\t/**\n\t * Story post type constructor.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param Settings $settings Settings instance.\n\t * @return void\n\t */\n\tpublic function __construct( Settings $settings ) {\n\t\t$this->settings = $settings;\n\t}\n\n\t/**\n\t * Registers the post type for stories.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @todo  refactor\n\t */\n\tpublic function register(): void {\n\t\t$this->register_post_type();\n\t\t$this->register_meta();\n\n\t\tadd_filter( 'wp_insert_post_data', [ $this, 'change_default_title' ] );\n\t\tadd_filter( 'wp_insert_post_empty_content', [ $this, 'filter_empty_content' ], 10, 2 );\n\t\tadd_filter( 'bulk_post_updated_messages', [ $this, 'bulk_post_updated_messages' ], 10, 2 );\n\t\tadd_action( 'clean_post_cache', [ $this, 'clear_user_posts_count' ], 10, 2 );\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because settings needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'settings' ];\n\t}\n\n\t/**\n\t * Get post type slug.\n\t *\n\t * @since 1.14.0\n\t */\n\tpublic function get_slug(): string {\n\t\treturn self::POST_TYPE_SLUG;\n\t}\n\n\t/**\n\t * Register post meta.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register_meta(): void {\n\t\t$active_publisher_logo_id = absint( $this->settings->get_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, 0 ) );\n\n\t\tregister_post_meta(\n\t\t\t$this->get_slug(),\n\t\t\tself::PUBLISHER_LOGO_META_KEY,\n\t\t\t[\n\t\t\t\t'sanitize_callback' => 'absint',\n\t\t\t\t'type'              => 'integer',\n\t\t\t\t'description'       => __( 'Publisher logo ID.', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'default'           => $active_publisher_logo_id,\n\t\t\t\t'single'            => true,\n\t\t\t\t'revisions_enabled' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_post_meta(\n\t\t\t$this->get_slug(),\n\t\t\tself::POSTER_META_KEY,\n\t\t\t[\n\t\t\t\t'type'              => 'object',\n\t\t\t\t'description'       => __( 'Poster object', 'web-stories' ),\n\t\t\t\t'show_in_rest'      => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'type'       => 'object',\n\t\t\t\t\t\t'properties' => [\n\t\t\t\t\t\t\t'needsProxy' => [\n\t\t\t\t\t\t\t\t'description' => __( 'If poster needs to be proxied', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'boolean',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'height'     => [\n\t\t\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t\t\t\t'description' => __( 'Poster height', 'web-stories' ),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'url'        => [\n\t\t\t\t\t\t\t\t'description' => __( 'Poster URL.', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'string',\n\t\t\t\t\t\t\t\t'format'      => 'uri',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t'width'      => [\n\t\t\t\t\t\t\t\t'description' => __( 'Poster width.', 'web-stories' ),\n\t\t\t\t\t\t\t\t'type'        => 'integer',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'default'           => [],\n\t\t\t\t'single'            => true,\n\t\t\t\t'revisions_enabled' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Filters the bulk action updated messages.\n\t *\n\t * @since 1.1.0\n\t *\n\t * @param array[]|mixed     $bulk_messages Arrays of messages, each keyed by the corresponding post type. Messages are\n\t *                                         keyed with 'updated', 'locked', 'deleted', 'trashed', and 'untrashed'.\n\t * @param array<string,int> $bulk_counts   Array of item counts for each message, used to build internationalized\n\t *                                         strings.\n\t * @return array|mixed Bulk counts.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($bulk_messages is array<T> ? array<T> : mixed)\n\t */\n\tpublic function bulk_post_updated_messages( $bulk_messages, array $bulk_counts ) {\n\t\tif ( ! \\is_array( $bulk_messages ) ) {\n\t\t\treturn $bulk_messages;\n\t\t}\n\t\t$bulk_messages[ $this->get_slug() ] = [\n\t\t\t/* translators: %s: Number of stories. */\n\t\t\t'updated'   => _n( '%s story updated.', '%s stories updated.', $bulk_counts['updated'], 'web-stories' ),\n\t\t\t'locked'    => 1 === $bulk_counts['locked'] ? __( 'Story not updated, somebody is editing it.', 'web-stories' ) :\n\t\t\t\t/* translators: %s: Number of stories. */\n\t\t\t\t_n( '%s story not updated, somebody is editing it.', '%s stories not updated, somebody is editing them.', $bulk_counts['locked'], 'web-stories' ),\n\t\t\t/* translators: %s: Number of stories. */\n\t\t\t'deleted'   => _n( '%s story permanently deleted.', '%s stories permanently deleted.', $bulk_counts['deleted'], 'web-stories' ),\n\t\t\t/* translators: %s: Number of stories. */\n\t\t\t'trashed'   => _n( '%s story moved to the Trash.', '%s stories moved to the Trash.', $bulk_counts['trashed'], 'web-stories' ),\n\t\t\t/* translators: %s: Number of stories. */\n\t\t\t'untrashed' => _n( '%s story restored from the Trash.', '%s stories restored from the Trash.', $bulk_counts['untrashed'], 'web-stories' ),\n\t\t];\n\n\t\treturn $bulk_messages;\n\t}\n\n\t/**\n\t * Reset default title to empty string for auto-drafts.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array|mixed $data Array of data to save.\n\t * @return array|mixed\n\t *\n\t * @template T\n\t *\n\t * @phpstan-return ($data is array<T> ? array<T> : mixed)\n\t */\n\tpublic function change_default_title( $data ) {\n\t\tif ( ! \\is_array( $data ) ) {\n\t\t\treturn $data;\n\t\t}\n\t\tif ( $this->get_slug() === $data['post_type'] && 'auto-draft' === $data['post_status'] ) {\n\t\t\t$data['post_title'] = '';\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t/**\n\t * Filters whether the post should be considered \"empty\".\n\t *\n\t * Takes into account post_content_filtered for stories.\n\t *\n\t * @since 1.25.1\n\t *\n\t * @param bool|mixed $maybe_empty Whether the post should be considered \"empty\".\n\t * @param array      $data        Array of post data.\n\t * @return bool Whether the post should be considered \"empty\".\n\t *\n\t * @phpstan-param array{post_type: string, post_content_filtered: string} $data\n\t */\n\tpublic function filter_empty_content( $maybe_empty, array $data ): bool {\n\t\tif ( $this->get_slug() === $data['post_type'] ) {\n\t\t\treturn $maybe_empty && ! $data['post_content_filtered'];\n\t\t}\n\n\t\treturn (bool) $maybe_empty;\n\t}\n\n\t/**\n\t * Invalid cache.\n\t *\n\t * @since 1.10.0\n\t *\n\t * @param int     $post_id Post ID.\n\t * @param WP_Post $post    Post object.\n\t */\n\tpublic function clear_user_posts_count( int $post_id, WP_Post $post ): void {\n\t\tif ( $this->get_slug() !== $post->post_type ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$cache_key   = \"count_user_{$post->post_type}_{$post->post_author}\";\n\t\t$cache_group = 'user_posts_count';\n\t\twp_cache_delete( $cache_key, $cache_group );\n\t}\n\n\t/**\n\t * Determines whether the post type should have an archive or not.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return bool|string Whether the post type should have an archive, or archive slug.\n\t */\n\tpublic function get_has_archive() {\n\t\t$archive_page_option = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE );\n\t\t$has_archive         = true;\n\n\t\tif ( 'disabled' === $archive_page_option ) {\n\t\t\t$has_archive = false;\n\t\t} elseif ( 'custom' === $archive_page_option ) {\n\t\t\t$custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\t\t\tif ( $custom_archive_page_id && 'publish' === get_post_status( $custom_archive_page_id ) ) {\n\t\t\t\t$uri = get_page_uri( $custom_archive_page_id );\n\t\t\t\tif ( $uri ) {\n\t\t\t\t\t$has_archive = urldecode( $uri );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $has_archive;\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_post_meta_by_key( self::POSTER_META_KEY );\n\t\tdelete_post_meta_by_key( self::PUBLISHER_LOGO_META_KEY );\n\n\t\tdelete_option( self::STYLE_PRESETS_OPTION );\n\t\tparent::on_plugin_uninstall();\n\t}\n\n\t/**\n\t * Register post type.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string, mixed> Post type args.\n\t *\n\t * @phpstan-return PostTypeArgs\n\t */\n\tprotected function get_args(): array {\n\t\treturn [\n\t\t\t'labels'                         => [\n\t\t\t\t'name'                     => _x( 'Stories', 'post type general name', 'web-stories' ),\n\t\t\t\t'singular_name'            => _x( 'Story', 'post type singular name', 'web-stories' ),\n\t\t\t\t'add_new'                  => __( 'Add New Story', 'web-stories' ),\n\t\t\t\t'add_new_item'             => __( 'Add New Story', 'web-stories' ),\n\t\t\t\t'edit_item'                => __( 'Edit Story', 'web-stories' ),\n\t\t\t\t'new_item'                 => __( 'New Story', 'web-stories' ),\n\t\t\t\t'view_item'                => __( 'View Story', 'web-stories' ),\n\t\t\t\t'view_items'               => __( 'View Stories', 'web-stories' ),\n\t\t\t\t'search_items'             => __( 'Search Stories', 'web-stories' ),\n\t\t\t\t'not_found'                => __( 'No stories found.', 'web-stories' ),\n\t\t\t\t'not_found_in_trash'       => __( 'No stories found in Trash.', 'web-stories' ),\n\t\t\t\t'all_items'                => __( 'All Stories', 'web-stories' ),\n\t\t\t\t'archives'                 => __( 'Story Archives', 'web-stories' ),\n\t\t\t\t'attributes'               => __( 'Story Attributes', 'web-stories' ),\n\t\t\t\t'insert_into_item'         => __( 'Insert into story', 'web-stories' ),\n\t\t\t\t'uploaded_to_this_item'    => __( 'Uploaded to this story', 'web-stories' ),\n\t\t\t\t'featured_image'           => _x( 'Featured Image', 'story', 'web-stories' ),\n\t\t\t\t'set_featured_image'       => _x( 'Set featured image', 'story', 'web-stories' ),\n\t\t\t\t'remove_featured_image'    => _x( 'Remove featured image', 'story', 'web-stories' ),\n\t\t\t\t'use_featured_image'       => _x( 'Use as featured image', 'story', 'web-stories' ),\n\t\t\t\t'filter_items_list'        => __( 'Filter stories list', 'web-stories' ),\n\t\t\t\t'filter_by_date'           => __( 'Filter by date', 'web-stories' ),\n\t\t\t\t'items_list_navigation'    => __( 'Stories list navigation', 'web-stories' ),\n\t\t\t\t'items_list'               => __( 'Stories list', 'web-stories' ),\n\t\t\t\t'item_published'           => __( 'Story published.', 'web-stories' ),\n\t\t\t\t'item_published_privately' => __( 'Story published privately.', 'web-stories' ),\n\t\t\t\t'item_reverted_to_draft'   => __( 'Story reverted to draft.', 'web-stories' ),\n\t\t\t\t'item_scheduled'           => __( 'Story scheduled', 'web-stories' ),\n\t\t\t\t'item_updated'             => __( 'Story updated.', 'web-stories' ),\n\t\t\t\t'menu_name'                => _x( 'Stories', 'admin menu', 'web-stories' ),\n\t\t\t\t'name_admin_bar'           => _x( 'Story', 'add new on admin bar', 'web-stories' ),\n\t\t\t\t'item_link'                => _x( 'Story Link', 'navigation link block title', 'web-stories' ),\n\t\t\t\t'item_link_description'    => _x( 'A link to a story.', 'navigation link block description', 'web-stories' ),\n\t\t\t\t'item_trashed'             => __( 'Story trashed.', 'web-stories' ),\n\t\t\t],\n\t\t\t'menu_icon'                      => $this->get_post_type_icon(),\n\t\t\t'supports'                       => [\n\t\t\t\t'title', // Used for amp-story[title].\n\t\t\t\t'author',\n\t\t\t\t'editor',\n\t\t\t\t'excerpt',\n\t\t\t\t'thumbnail', // Used for poster images.\n\t\t\t\t'revisions', // Without this, the REST API will return 404 for an autosave request.\n\t\t\t\t'custom-fields',\n\t\t\t],\n\t\t\t'rewrite'                        => [\n\t\t\t\t'slug'       => self::REWRITE_SLUG,\n\t\t\t\t'with_front' => false,\n\t\t\t\t'feeds'      => true,\n\t\t\t],\n\t\t\t'public'                         => true,\n\t\t\t'has_archive'                    => $this->get_has_archive(),\n\t\t\t'exclude_from_search'            => true,\n\t\t\t'show_ui'                        => true,\n\t\t\t'show_in_rest'                   => true,\n\t\t\t'rest_namespace'                 => self::REST_NAMESPACE,\n\t\t\t'rest_controller_class'          => Stories_Controller::class,\n\t\t\t'autosave_rest_controller_class' => Stories_Autosaves_Controller::class,\n\t\t\t'capability_type'                => [ 'web-story', 'web-stories' ],\n\t\t\t'map_meta_cap'                   => true,\n\t\t];\n\t}\n\n\t/**\n\t * Base64 encoded svg icon.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return string Base64-encoded SVG icon.\n\t */\n\tprotected function get_post_type_icon(): string {\n\t\treturn 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMCAyMGM1LjUyMyAwIDEwLTQuNDc3IDEwLTEwUzE1LjUyMyAwIDEwIDAgMCA0LjQ3NyAwIDEwczQuNDc3IDEwIDEwIDEwek01LjUgNmExIDEgMCAwMTEtMUgxMWExIDEgMCAwMTEgMXY4YTEgMSAwIDAxLTEgMUg2LjVhMSAxIDAgMDEtMS0xVjZ6TTEzIDZhMSAxIDAgMDExIDF2NmExIDEgMCAwMS0xIDFWNnptMi43NSAxLjc1QS43NS43NSAwIDAwMTUgN3Y2YS43NS43NSAwIDAwLjc1LS43NXYtNC41eiIgZmlsbD0iI2EwYTVhYSIvPjwvc3ZnPg==';\n\t}\n}\n"
  },
  {
    "path": "includes/Story_Query.php",
    "content": "<?php\n/**\n * Stories class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Carousel_Renderer;\nuse Google\\Web_Stories\\Renderer\\Stories\\Generic_Renderer;\nuse Google\\Web_Stories\\Renderer\\Stories\\Renderer;\nuse WP_Post;\nuse WP_Query;\n\n/**\n * Stories class.\n *\n * @phpstan-type StoryAttributes array{\n *   view_type?: string,\n *   number_of_columns?: int,\n *   show_title?: bool,\n *   show_author?: bool,\n *   show_date?: bool,\n *   show_archive_link?: bool|string,\n *   show_excerpt?: bool,\n *   image_alignment?: string,\n *   class?: string,\n *   archive_link_label?: string,\n *   circle_size?: int,\n *   sharp_corners?: bool,\n *   order?: string,\n *   orderby?: string,\n *   align?: string\n * }\n * @phpstan-type StoryAttributesWithDefaults array{\n *   view_type: string,\n *   number_of_columns: int,\n *   show_title: bool,\n *   show_author: bool,\n *   show_date: bool,\n *   show_archive_link: bool|string,\n *   show_excerpt: bool,\n *   image_alignment: string,\n *   class: string,\n *   archive_link_label: string,\n *   circle_size: int,\n *   sharp_corners: bool,\n *   order?: string,\n *   orderby?: string,\n *   align?: string\n * }\n */\nclass Story_Query {\n\t/**\n\t * Story attributes\n\t *\n\t * @since 1.5.0\n\t *\n\t * @var array<string, mixed> An array of story attributes.\n\t */\n\tprotected array $story_attributes = [];\n\n\t/**\n\t * Story query arguments.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @var array<string, mixed> An array of query arguments.\n\t */\n\tprotected array $query_args = [];\n\n\t/**\n\t * Renderer object.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic Renderer $renderer;\n\n\t/**\n\t * Class constructor\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array                $story_attributes {\n\t *                   An array of story attributes.\n\t *\n\t *     @type string $view_type          Stories View type. Default circles.\n\t *     @type int    $number_of_columns  Number of columns to show in grid view. Default 2.\n\t *     @type bool   $show_title         Whether to show story title or not. Default false.\n\t *     @type bool   $show_author        Whether to show story author or not. Default false.\n\t *     @type bool   $show_date          Whether to show story date or not. Default false.\n\t *     @type bool   $show_archive_link  Whether to show view all link or not. Default false.\n\t *     @type string $archive_link_label The label for view all link. Default 'View all stories'.\n\t *     @type string $image_alignment    The list mode image alignment. Default 'left'.\n\t *     @type string $class              Additional CSS classes for the container. Default empty string.\n\t * }\n\t * @param array<string, mixed> $query_args An array of query arguments for story. {@see WP_Query::parse_query()} for\n\t *                          all available arguments.\n\t *\n\t * @phpstan-param StoryAttributes $story_attributes\n\t */\n\tpublic function __construct( array $story_attributes = [], array $query_args = [] ) {\n\t\t$this->story_attributes = $story_attributes;\n\n\t\t$default_query_args = [\n\t\t\t'post_type'        => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t'posts_per_page'   => 10,\n\t\t\t'post_status'      => 'publish',\n\t\t\t'suppress_filters' => false,\n\t\t\t'no_found_rows'    => true,\n\t\t];\n\n\t\t$this->query_args = wp_parse_args( $query_args, $default_query_args );\n\t}\n\n\t/**\n\t * Retrieves an array of the latest stories, or Stories matching the given criteria.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return WP_Post[] List of Story posts.\n\t */\n\tpublic function get_stories(): array {\n\t\t$stories_query = new WP_Query();\n\n\t\t/**\n\t\t * List of story posts.\n\t\t *\n\t\t * @var WP_Post[] $result\n\t\t */\n\t\t$result = $stories_query->query( $this->query_args );\n\n\t\tupdate_post_thumbnail_cache( $stories_query );\n\n\t\treturn $result;\n\t}\n\n\t/**\n\t * Instantiates the renderer classes based on the view type.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return Renderer Renderer Instance.\n\t */\n\tpublic function get_renderer(): Renderer {\n\t\t$story_attributes = $this->get_story_attributes();\n\t\t$view_type        = ! empty( $story_attributes['view_type'] ) ? $story_attributes['view_type'] : '';\n\n\t\tswitch ( $view_type ) {\n\t\t\tcase 'carousel':\n\t\t\tcase 'circles':\n\t\t\t\t$renderer = new Carousel_Renderer( $this );\n\t\t\t\tbreak;\n\t\t\tcase 'list':\n\t\t\tcase 'grid':\n\t\t\tdefault:\n\t\t\t\t$renderer = new Generic_Renderer( $this );\n\t\t}\n\n\t\t$renderer->init();\n\n\t\treturn $renderer;\n\t}\n\n\t/**\n\t * Renders the stories output.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function render(): string {\n\t\t$this->renderer = $this->get_renderer();\n\n\t\treturn $this->renderer->render();\n\t}\n\n\t/**\n\t * Gets an array of story attributes.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string, string|int|bool> An array of story attributes.\n\t *\n\t * @phpstan-return StoryAttributesWithDefaults\n\t */\n\tpublic function get_story_attributes(): array {\n\t\t$default_attributes = [\n\t\t\t'view_type'          => 'circles',\n\t\t\t'number_of_columns'  => 2,\n\t\t\t'show_title'         => false,\n\t\t\t'show_author'        => false,\n\t\t\t'show_date'          => false,\n\t\t\t'show_excerpt'       => false,\n\t\t\t'show_archive_link'  => false,\n\t\t\t'sharp_corners'      => false,\n\t\t\t'archive_link_label' => __( 'View all stories', 'web-stories' ),\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'class'              => '',\n\t\t\t'circle_size'        => 150,\n\t\t];\n\n\t\t/**\n\t\t * Attributes with defaults applied.\n\t\t *\n\t\t * @phpstan-var StoryAttributesWithDefaults $attributes\n\t\t */\n\t\t$attributes = wp_parse_args( $this->story_attributes, $default_attributes );\n\n\t\treturn $attributes;\n\t}\n}\n"
  },
  {
    "path": "includes/Story_Revisions.php",
    "content": "<?php\n/**\n * Story_Revisions class.\n *\n * Responsible for WordPress revisions integration.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse WP_Post;\n\n/**\n * Revisions class.\n *\n * @phpstan-type RevisionField array{\n *   id: string,\n *   name: string,\n *   diff: string\n * }\n * @phpstan-type PostData array{\n *   post_parent: int,\n *   post_type: string,\n *   post_content?: string,\n *   post_content_filtered?: string\n * }\n */\nclass Story_Revisions extends Service_Base {\n\n\t/**\n\t * Story post type instance.\n\t *\n\t * @var Story_Post_Type Story post type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Single constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story post type instance.\n\t * @param Assets          $assets  Assets instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type, Assets $assets ) {\n\t\t$this->story_post_type = $story_post_type;\n\t\t$this->assets          = $assets;\n\t}\n\n\t/**\n\t * Initialize admin-related functionality.\n\t *\n\t * @since 1.25.0\n\t */\n\tpublic function register(): void {\n\t\t$post_type = $this->story_post_type->get_slug();\n\t\tadd_filter( \"wp_{$post_type}_revisions_to_keep\", [ $this, 'revisions_to_keep' ] );\n\t\tadd_filter( '_wp_post_revision_fields', [ $this, 'filter_revision_fields' ], 10, 2 );\n\t\tadd_filter( 'wp_get_revision_ui_diff', [ $this, 'filter_revision_ui_diff' ], 10, 3 );\n\n\t\tadd_action( 'admin_print_footer_scripts-revision.php', [ $this, 'enqueue_player_script' ] );\n\t}\n\n\t/**\n\t * Force WordPress to only keep 10 revisions for the web stories post type.\n\t *\n\t * @since 1.25.0\n\t *\n\t * @param int|bool|string $num Number of revisions to store.\n\t * @return int Number of revisions to store.\n\t */\n\tpublic function revisions_to_keep( $num ): int {\n\t\t$num = (int) $num;\n\t\treturn $num >= 0 && $num < 10 ? $num : 10;\n\t}\n\n\t/**\n\t * Filters the revision fields to ensure that JSON representation gets saved to Story revisions.\n\t *\n\t * @since 1.25.0\n\t *\n\t * @param array|mixed         $fields Array of allowed revision fields.\n\t * @param array<string,mixed> $story  Story post array.\n\t * @return array|mixed Array of allowed fields.\n\t *\n\t * @template T\n\t *\n\t * @phpstan-param PostData $story\n\t * @phpstan-return ($fields is array<T> ? array<T> : mixed)\n\t */\n\tpublic function filter_revision_fields( $fields, array $story ) {\n\t\tif ( ! \\is_array( $fields ) ) {\n\t\t\treturn $fields;\n\t\t}\n\n\t\tif (\n\t\t\t$this->story_post_type->get_slug() === $story['post_type'] ||\n\t\t\t(\n\t\t\t\t'revision' === $story['post_type'] &&\n\t\t\t\t! empty( $story['post_parent'] ) &&\n\t\t\t\tget_post_type( $story['post_parent'] ) === $this->story_post_type->get_slug()\n\t\t\t)\n\t\t) {\n\t\t\t$fields['post_content_filtered'] = __( 'Story data', 'web-stories' );\n\t\t}\n\n\t\treturn $fields;\n\t}\n\n\t/**\n\t * Filters the fields displayed in the post revision diff UI.\n\t *\n\t * @since 1.25.0\n\t *\n\t * @param array[]|mixed $fields       Array of revision UI fields. Each item is an array of id, name, and diff.\n\t * @param WP_Post|false $compare_from The revision post to compare from or false if dealing with the first revision.\n\t * @param WP_Post       $compare_to   The revision post to compare to.\n\t * @return array[]|mixed Filtered array of revision UI fields.\n\t *\n\t * @phpstan-return array<int, RevisionField[]>|mixed\n\t */\n\tpublic function filter_revision_ui_diff( $fields, $compare_from, WP_Post $compare_to ) {\n\t\tif ( ! \\is_array( $fields ) ) {\n\t\t\treturn $fields;\n\t\t}\n\n\t\t$parent = get_post_parent( $compare_to );\n\n\t\tif (\n\t\t\t! $parent instanceof WP_Post ||\n\t\t\t$this->story_post_type->get_slug() !== $parent->post_type\n\t\t) {\n\t\t\treturn $fields;\n\t\t}\n\n\t\t$player_from = '';\n\n\t\tif ( $compare_from instanceof WP_Post ) {\n\t\t\t$player_from = $this->get_story_player( $compare_from );\n\t\t}\n\n\t\t$player_to = $this->get_story_player( $compare_to );\n\n\t\t$args = [\n\t\t\t'show_split_view' => true,\n\t\t\t'title_left'      => __( 'Removed' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain\n\t\t\t'title_right'     => __( 'Added' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain\n\t\t];\n\n\t\t/** This filter is documented in wp-admin/includes/revision.php */\n\t\t$args = apply_filters( 'revision_text_diff_options', $args, 'post_content', $compare_from, $compare_to );\n\n\t\t$fields_to_return = [];\n\n\t\t/**\n\t\t * Revision field.\n\t\t *\n\t\t * @phpstan-var RevisionField $field\n\t\t * @var array $field\n\t\t */\n\t\tforeach ( $fields as $field ) {\n\t\t\tif ( 'post_title' === $field['id'] ) {\n\t\t\t\t$fields_to_return[] = $field;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t'post_content' === $field['id'] ||\n\t\t\t\t'post_content_filtered' === $field['id']\n\t\t\t) {\n\t\t\t\t$field['title'] = __( 'Content', 'web-stories' );\n\n\t\t\t\t$diff = '<table class=\"diff\"><colgroup><col class=\"content diffsplit left\"><col class=\"content diffsplit middle\"><col class=\"content diffsplit right\"></colgroup><tbody><tr>';\n\n\t\t\t\t// In split screen mode, show the title before/after side by side.\n\t\t\t\tif ( true === $args['show_split_view'] ) {\n\t\t\t\t\t$diff .= '<td>' . $player_from . '</td><td></td><td>' . $player_to . '</td>';\n\t\t\t\t} else {\n\t\t\t\t\t$diff .= '<td>' . $player_from . '</td></tr><tr><td>' . $player_to . '</td>';\n\t\t\t\t}\n\n\t\t\t\t$diff .= '</tr></tbody>';\n\t\t\t\t$diff .= '</table>';\n\n\t\t\t\t$field['diff'] = $diff;\n\n\t\t\t\t$fields_to_return[] = $field;\n\t\t\t\treturn $fields_to_return;\n\t\t\t}\n\t\t}\n\n\t\treturn $fields;\n\t}\n\n\t/**\n\t * Enqueues amp-story-player assets on the revisions screen.\n\t *\n\t * @since 1.25.0\n\t */\n\tpublic function enqueue_player_script(): void {\n\t\t$this->assets->enqueue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\n\t\twp_add_inline_script(\n\t\t\tAMP_Story_Player_Assets::SCRIPT_HANDLE,\n\t\t\t<<<'JS'\n\t\t\t\tconst loadPlayers = () => document.querySelectorAll('amp-story-player').forEach(playerEl => (new AmpStoryPlayer(window, playerEl)).load());\n\t\t\t\tconst originalFrame = wp.revisions.view.Frame;\n\t\t\t\twp.revisions.view.Frame = originalFrame.extend({\n\t\t\t\t\trender: function() {\n\t\t\t\t\t\toriginalFrame.prototype.render.apply(this, arguments);\n\t\t\t\t\t\tloadPlayers();\n\t\t\t\t\t\tthis.listenTo( this.model, 'update:diff', () => loadPlayers() );\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\tJS\n\t\t);\n\t}\n\n\t/**\n\t * Returns the story player markup for a given post.\n\t *\n\t * @since 1.25.0\n\t *\n\t * @param WP_Post $post Post instance.\n\t * @return string Story player markup.\n\t */\n\tprotected function get_story_player( WP_Post $post ): string {\n\t\t$url   = esc_url(\n\t\t\twp_nonce_url(\n\t\t\t\tadd_query_arg( 'rev_id', $post->ID, get_permalink( $post->post_parent ) ),\n\t\t\t\t'web_stories_revision_for_' . $post->post_parent\n\t\t\t)\n\t\t);\n\t\t$title = esc_html( get_the_title( $post ) );\n\t\treturn <<<Player\n\t\t\t\t<amp-story-player style=\"width: 300px; height: 500px; display: flex;\"><a href=\"$url\">$title</a></amp-story-player>\n\t\t\t\tPlayer;\n\t}\n}\n"
  },
  {
    "path": "includes/Taxonomy/Category_Taxonomy.php",
    "content": "<?php\n/**\n * Class Category_Taxonomy.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Taxonomy;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\REST_API\\Stories_Terms_Controller;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Category_Taxonomy class.\n *\n * @phpstan-import-type TaxonomyArgs from \\Google\\Web_Stories\\Taxonomy\\Taxonomy_Base\n */\nclass Category_Taxonomy extends Taxonomy_Base implements HasRequirements {\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->taxonomy_post_type = $story_post_type->get_slug();\n\t\t$this->taxonomy_slug      = 'web_story_category';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Category args.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string,mixed> Taxonomy args.\n\t *\n\t * @phpstan-return TaxonomyArgs\n\t */\n\tprotected function taxonomy_args(): array {\n\t\t$labels = [\n\t\t\t'name'                  => _x( 'Categories', 'taxonomy general name', 'web-stories' ),\n\t\t\t'singular_name'         => _x( 'Category', 'taxonomy singular name', 'web-stories' ),\n\t\t\t'search_items'          => __( 'Search Categories', 'web-stories' ),\n\t\t\t'all_items'             => __( 'All Categories', 'web-stories' ),\n\t\t\t'parent_item'           => __( 'Parent Category', 'web-stories' ),\n\t\t\t'parent_item_colon'     => __( 'Parent Category:', 'web-stories' ),\n\t\t\t'edit_item'             => __( 'Edit Category', 'web-stories' ),\n\t\t\t'view_item'             => __( 'View Category', 'web-stories' ),\n\t\t\t'update_item'           => __( 'Update Category', 'web-stories' ),\n\t\t\t'add_new_item'          => __( 'Add New Category', 'web-stories' ),\n\t\t\t'new_item_name'         => __( 'New Category Name', 'web-stories' ),\n\t\t\t'not_found'             => __( 'No categories found.', 'web-stories' ),\n\t\t\t'no_terms'              => __( 'No categories', 'web-stories' ),\n\t\t\t'filter_by_item'        => __( 'Filter by category', 'web-stories' ),\n\t\t\t'items_list_navigation' => __( 'Categories list navigation', 'web-stories' ),\n\t\t\t'items_list'            => __( 'Categories list', 'web-stories' ),\n\t\t\t/* translators: Tab heading when selecting from the most used terms. */\n\t\t\t'most_used'             => _x( 'Most Used', 'Categories', 'web-stories' ),\n\t\t\t'back_to_items'         => __( '&larr; Go to Categories', 'web-stories' ),\n\t\t\t'item_link'             => _x( 'Category Link', 'navigation link block title', 'web-stories' ),\n\t\t\t'item_link_description' => _x( 'A link to a category.', 'navigation link block description', 'web-stories' ),\n\t\t];\n\t\treturn [\n\t\t\t'labels'                => $labels,\n\t\t\t'hierarchical'          => true,\n\t\t\t'public'                => false,\n\t\t\t'publicly_queryable'    => true,\n\t\t\t'show_ui'               => true,\n\t\t\t'show_admin_column'     => true,\n\t\t\t'rewrite'               => true,\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t\t'capabilities'          => self::DEFAULT_CAPABILITIES,\n\t\t\t'rest_controller_class' => Stories_Terms_Controller::class,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Taxonomy/Tag_Taxonomy.php",
    "content": "<?php\n/**\n * Class Tag_Taxonomy.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Taxonomy;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\REST_API\\Stories_Terms_Controller;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Tag_Taxonomy class.\n *\n * @phpstan-import-type TaxonomyArgs from \\Google\\Web_Stories\\Taxonomy\\Taxonomy_Base\n */\nclass Tag_Taxonomy extends Taxonomy_Base implements HasRequirements {\n\t/**\n\t * Constructor.\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->taxonomy_post_type = $story_post_type->get_slug();\n\t\t$this->taxonomy_slug      = 'web_story_tag';\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.13.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Taxonomy args.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string,mixed> Taxonomy args.\n\t *\n\t * @phpstan-return TaxonomyArgs\n\t */\n\tprotected function taxonomy_args(): array {\n\t\t$labels = [\n\t\t\t'name'                       => _x( 'Tags', 'taxonomy general name', 'web-stories' ),\n\t\t\t'singular_name'              => _x( 'Tag', 'taxonomy singular name', 'web-stories' ),\n\t\t\t'search_items'               => __( 'Search Tags', 'web-stories' ),\n\t\t\t'popular_items'              => __( 'Popular Tags', 'web-stories' ),\n\t\t\t'all_items'                  => __( 'All Tags', 'web-stories' ),\n\t\t\t'edit_item'                  => __( 'Edit Tag', 'web-stories' ),\n\t\t\t'view_item'                  => __( 'View Tag', 'web-stories' ),\n\t\t\t'update_item'                => __( 'Update Tag', 'web-stories' ),\n\t\t\t'add_new_item'               => __( 'Add New Tag', 'web-stories' ),\n\t\t\t'new_item_name'              => __( 'New Tag Name', 'web-stories' ),\n\t\t\t'separate_items_with_commas' => __( 'Separate tags with commas', 'web-stories' ),\n\t\t\t'add_or_remove_items'        => __( 'Add or remove tags', 'web-stories' ),\n\t\t\t'choose_from_most_used'      => __( 'Choose from the most used tags', 'web-stories' ),\n\t\t\t'not_found'                  => __( 'No tags found.', 'web-stories' ),\n\t\t\t'no_terms'                   => __( 'No tags', 'web-stories' ),\n\t\t\t'items_list_navigation'      => __( 'Tags list navigation', 'web-stories' ),\n\t\t\t'items_list'                 => __( 'Tags list', 'web-stories' ),\n\t\t\t/* translators: Tab heading when selecting from the most used terms. */\n\t\t\t'most_used'                  => _x( 'Most Used', 'Tags', 'web-stories' ),\n\t\t\t'back_to_items'              => __( '&larr; Go to Tags', 'web-stories' ),\n\t\t\t'item_link'                  => _x( 'Tag Link', 'navigation link block title', 'web-stories' ),\n\t\t\t'item_link_description'      => _x( 'A link to a tag.', 'navigation link block description', 'web-stories' ),\n\t\t];\n\t\treturn [\n\t\t\t'labels'                => $labels,\n\t\t\t'hierarchical'          => false,\n\t\t\t'public'                => false,\n\t\t\t'publicly_queryable'    => true,\n\t\t\t'show_ui'               => true,\n\t\t\t'show_admin_column'     => true,\n\t\t\t'rewrite'               => true,\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t\t'capabilities'          => self::DEFAULT_CAPABILITIES,\n\t\t\t'rest_controller_class' => Stories_Terms_Controller::class,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/Taxonomy/Taxonomy_Base.php",
    "content": "<?php\n/**\n * Class Taxonomy_Base.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Taxonomy;\n\nuse Google\\Web_Stories\\Infrastructure\\PluginActivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginDeactivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\SiteInitializationAware;\nuse Google\\Web_Stories\\Service_Base;\nuse WP_Site;\nuse WP_Term;\nuse WP_Term_Query;\n\n/**\n * Taxonomy_Base class\n *\n * @phpstan-type TaxonomyArgs array{\n *   labels?: string[],\n *   description?: string,\n *   public?: bool,\n *   publicly_queryable?: bool,\n *   hierarchical?: bool,\n *   show_ui?: bool,\n *   show_in_menu?: bool,\n *   show_in_nav_menus?: bool,\n *   show_in_rest?: bool,\n *   rest_base?: string,\n *   rest_namespace?: string,\n *   rest_controller_class?: string,\n *   show_tagcloud?: bool,\n *   show_in_quick_edit?: bool,\n *   show_admin_column?: bool,\n *   meta_box_cb?: bool|callable,\n *   meta_box_sanitize_cb?: callable,\n *   capabilities?: string[],\n *   rewrite?: bool|array{\n *     slug?: string,\n *     with_front?: bool,\n *     hierarchical?: bool,\n *     ep_mask?: int\n *   },\n *   query_var?: string|bool,\n *   update_count_callback?: callable,\n *   default_term?: string|array{\n *     name?: string,\n *     slug?: string,\n *     description?: string\n *   },\n *   sort?: bool,\n *   args?: array<string, mixed>,\n *   _builtin?: bool,\n * }\n */\nabstract class Taxonomy_Base extends Service_Base implements PluginActivationAware, PluginDeactivationAware, SiteInitializationAware, PluginUninstallAware {\n\n\tpublic const DEFAULT_CAPABILITIES = [\n\t\t'manage_terms' => 'manage_terms_web-stories',\n\t\t'edit_terms'   => 'edit_terms_web-stories',\n\t\t'delete_terms' => 'delete_terms_web-stories',\n\t\t'assign_terms' => 'assign_terms_web-stories',\n\t];\n\n\t/**\n\t * Default REST Namespace.\n\t */\n\tpublic const REST_NAMESPACE = 'web-stories/v1';\n\n\t/**\n\t * Taxonomy key, must not exceed 32 characters.\n\t */\n\tprotected string $taxonomy_slug;\n\n\t/**\n\t * Object type which the taxonomy should be associated.\n\t */\n\tprotected string $taxonomy_post_type;\n\n\t/**\n\t * Register taxonomy on register service.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_taxonomy();\n\t}\n\n\t/**\n\t * Register taxonomy.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function register_taxonomy(): void {\n\t\tregister_taxonomy( $this->taxonomy_slug, $this->taxonomy_post_type, $this->taxonomy_args() );\n\t}\n\n\t/**\n\t * Unregister taxonomy.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function unregister_taxonomy(): void {\n\t\tunregister_taxonomy( $this->taxonomy_slug );\n\t}\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\t$this->register_taxonomy();\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->register_taxonomy();\n\t}\n\n\t/**\n\t * Act on plugin deactivation.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param bool $network_wide Whether the deactivation was done network-wide.\n\t */\n\tpublic function on_plugin_deactivation( bool $network_wide ): void {\n\t\t$this->unregister_taxonomy();\n\t}\n\n\t/**\n\t * Get taxonomy slug.\n\t *\n\t * @since 1.12.0\n\t */\n\tpublic function get_taxonomy_slug(): string {\n\t\treturn $this->taxonomy_slug;\n\t}\n\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tclean_taxonomy_cache( $this->get_taxonomy_slug() );\n\n\t\t$term_query = new WP_Term_Query();\n\t\t$terms      = $term_query->query(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\tif ( empty( $terms ) || ! \\is_array( $terms ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ( $terms as $term ) {\n\t\t\tif ( $term instanceof WP_Term ) {\n\t\t\t\twp_delete_term( $term->term_id, $term->taxonomy );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Taxonomy args.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return TaxonomyArgs Taxonomy args.\n\t */\n\tabstract protected function taxonomy_args(): array;\n}\n"
  },
  {
    "path": "includes/Tracking.php",
    "content": "<?php\n/**\n * Tracking class.\n *\n * Used for setting up telemetry.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Integrations\\Site_Kit;\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\User\\Preferences;\nuse WP_User;\n\n/**\n * Tracking class.\n */\nclass Tracking extends Service_Base {\n\t/**\n\t * Web Stories tracking script handle.\n\t */\n\tpublic const SCRIPT_HANDLE = 'web-stories-tracking';\n\n\t/**\n\t * Google Analytics property ID.\n\t */\n\tpublic const TRACKING_ID = 'UA-168571240-1';\n\n\t/**\n\t * Google Analytics 4 measurement ID.\n\t */\n\tpublic const TRACKING_ID_GA4 = 'G-T88C9951CM';\n\n\t/**\n\t * Experiments instance.\n\t *\n\t * @var Experiments Experiments instance.\n\t */\n\tprivate Experiments $experiments;\n\n\t/**\n\t * Site_Kit instance.\n\t *\n\t * @var Site_Kit Site_Kit instance.\n\t */\n\tprivate Site_Kit $site_kit;\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprivate Assets $assets;\n\n\t/**\n\t * Settings instance.\n\t *\n\t * @var Settings Settings instance.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Preferences instance.\n\t *\n\t * @var Preferences Preferences instance.\n\t */\n\tprivate Preferences $preferences;\n\n\t/**\n\t * WooCommerce instance.\n\t *\n\t * @var WooCommerce WooCommerce instance.\n\t */\n\tprivate WooCommerce $woocommerce;\n\n\t/**\n\t * Context instance.\n\t *\n\t * @var Context Context instance.\n\t */\n\tprivate Context $context;\n\n\t/**\n\t * Tracking constructor.\n\t *\n\t * @since 1.4.0\n\t *\n\t * @param Experiments $experiments Experiments instance.\n\t * @param Site_Kit    $site_kit    Site_Kit instance.\n\t * @param Assets      $assets      Assets instance.\n\t * @param Settings    $settings    Settings instance.\n\t * @param Preferences $preferences Preferences instance.\n\t * @param WooCommerce $woocommerce WooCommerce instance.\n\t * @param Context     $context     Context instance.\n\t */\n\tpublic function __construct(\n\t\tExperiments $experiments,\n\t\tSite_Kit $site_kit,\n\t\tAssets $assets,\n\t\tSettings $settings,\n\t\tPreferences $preferences,\n\t\tWooCommerce $woocommerce,\n\t\tContext $context\n\t) {\n\t\t$this->assets      = $assets;\n\t\t$this->experiments = $experiments;\n\t\t$this->site_kit    = $site_kit;\n\t\t$this->settings    = $settings;\n\t\t$this->preferences = $preferences;\n\t\t$this->woocommerce = $woocommerce;\n\t\t$this->context     = $context;\n\t}\n\n\t/**\n\t * Initializes tracking.\n\t *\n\t * Registers the script in WordPress.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\t// By not passing an actual script src we can print only the inline script.\n\t\t$this->assets->register_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\tfalse,\n\t\t\t[],\n\t\t\tWEBSTORIES_VERSION,\n\t\t\tfalse\n\t\t);\n\n\t\tadd_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );\n\t}\n\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'init';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @since 1.43.0\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 1;\n\t}\n\n\t/**\n\t * Enqueues tracking scripts\n\t *\n\t * @since 1.43.0\n\t *\n\t * @param string $hook_suffix The current admin page.\n\t */\n\tpublic function enqueue_assets( string $hook_suffix ): void {\n\t\tif ( ! $this->context->is_story_editor() && 'web-story' !== $this->context->get_screen_post_type() ) {\n\t\t\treturn;\n\t\t}\n\n\t\twp_add_inline_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'window.webStoriesTrackingSettings = ' . wp_json_encode( $this->get_settings() ) . ';'\n\t\t);\n\t}\n\n\t/**\n\t * Returns tracking settings to pass to the inline script.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array<string, array<string, bool|int|string>|bool|string> Tracking settings.\n\t */\n\tpublic function get_settings(): array {\n\t\treturn [\n\t\t\t'trackingAllowed' => $this->is_active(),\n\t\t\t'trackingId'      => self::TRACKING_ID,\n\t\t\t'trackingIdGA4'   => self::TRACKING_ID_GA4,\n\t\t\t// This doesn't seem to be fully working for web properties.\n\t\t\t// So we send it as both app_version and a user property.\n\t\t\t// See https://support.google.com/analytics/answer/9268042.\n\t\t\t'appVersion'      => WEBSTORIES_VERSION,\n\t\t\t'userProperties'  => $this->get_user_properties(),\n\t\t];\n\t}\n\n\t/**\n\t * Is tracking active for the current user?\n\t *\n\t * @return bool True if tracking enabled, and False if not.\n\t */\n\tpublic function is_active(): bool {\n\t\treturn (bool) $this->preferences->get_preference( get_current_user_id(), Preferences::OPTIN_META_KEY );\n\t}\n\n\t/**\n\t * Returns a list of user properties.\n\t *\n\t * @since 1.4.0\n\t *\n\t * @return array<string, string|int|bool> User properties.\n\t */\n\tprivate function get_user_properties(): array {\n\t\t/**\n\t\t * Current user.\n\t\t *\n\t\t * @var null|WP_User $current_user\n\t\t */\n\t\t$current_user = wp_get_current_user();\n\t\t$roles        = $current_user instanceof WP_User ? array_values( $current_user->roles ) : [];\n\t\t$role         = ! empty( $roles ) ? array_shift( $roles ) : '';\n\t\t$experiments  = implode( ',', $this->experiments->get_enabled_experiments() );\n\n\t\t$active_plugins = [];\n\n\t\t$woocommerce_status = $this->woocommerce->get_plugin_status();\n\t\tif ( $woocommerce_status['active'] ) {\n\t\t\t$active_plugins[] = 'woocommerce';\n\t\t}\n\n\t\t$site_kit_status = $this->site_kit->get_plugin_status();\n\t\t$analytics       = $site_kit_status['analyticsActive'] ? 'google-site-kit' : ! empty( $this->settings->get_setting( $this->settings::SETTING_NAME_TRACKING_ID ) );\n\t\tif ( $site_kit_status['active'] ) {\n\t\t\t$active_plugins[] = 'google-site-kit';\n\t\t}\n\n\t\t/**\n\t\t * Ad network type.\n\t\t *\n\t\t * @var string $ad_network\n\t\t */\n\t\t$ad_network = $this->settings->get_setting( $this->settings::SETTING_NAME_AD_NETWORK, 'none' );\n\n\t\treturn [\n\t\t\t'siteLocale'         => get_locale(),\n\t\t\t'userLocale'         => get_user_locale(),\n\t\t\t'userRole'           => $role,\n\t\t\t'enabledExperiments' => $experiments,\n\t\t\t'wpVersion'          => (string) get_bloginfo( 'version' ),\n\t\t\t'phpVersion'         => (string) PHP_VERSION,\n\t\t\t'isMultisite'        => (int) is_multisite(),\n\t\t\t'serverEnvironment'  => wp_get_environment_type(),\n\t\t\t'adNetwork'          => $ad_network,\n\t\t\t'analytics'          => $analytics,\n\t\t\t'activePlugins'      => implode( ',', $active_plugins ),\n\t\t\t// This doesn't seem to be fully working for web properties.\n\t\t\t// So we send it as both app_version and a user property.\n\t\t\t// See https://support.google.com/analytics/answer/9268042.\n\t\t\t'pluginVersion'      => WEBSTORIES_VERSION,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "includes/User/Capabilities.php",
    "content": "<?php\n/**\n * Class Capabilities\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\User;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Infrastructure\\PluginActivationAware;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\SiteInitializationAware;\nuse Google\\Web_Stories\\Infrastructure\\SiteRemovalAware;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Taxonomy\\Taxonomy_Base;\nuse WP_Role;\nuse WP_Site;\n\n/**\n * Class Capabilities\n */\nclass Capabilities implements Service, PluginActivationAware, SiteInitializationAware, SiteRemovalAware, PluginUninstallAware, HasRequirements {\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Font_Post_Type constructor.\n\t *\n\t * @since 1.16.0\n\t *\n\t * @param Story_Post_Type $story_post_type Story_Post_Type instance.\n\t */\n\tpublic function __construct( Story_Post_Type $story_post_type ) {\n\t\t$this->story_post_type = $story_post_type;\n\t}\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * Needed because the story post type needs to be registered first.\n\t *\n\t * @since 1.29.0\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'story_post_type' ];\n\t}\n\n\t/**\n\t * Act on plugin activation.\n\t *\n\t * @since 1.6.0\n\t *\n\t * @param bool $network_wide Whether the activation was done network-wide.\n\t */\n\tpublic function on_plugin_activation( bool $network_wide ): void {\n\t\t$this->add_caps_to_roles();\n\t}\n\n\t/**\n\t * Act on site initialization.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being initialized.\n\t */\n\tpublic function on_site_initialization( WP_Site $site ): void {\n\t\t$this->add_caps_to_roles();\n\t}\n\n\t/**\n\t * Act on site removal.\n\t *\n\t * @since 1.11.0\n\t *\n\t * @param WP_Site $site The site being removed.\n\t */\n\tpublic function on_site_removal( WP_Site $site ): void {\n\t\t$this->remove_caps_from_roles();\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\t$this->remove_caps_from_roles();\n\t}\n\n\t/**\n\t * Adds story capabilities to default user roles.\n\t *\n\t * This gives WordPress site owners more granular control over story management,\n\t * as they can customize this to their liking.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function add_caps_to_roles(): void {\n\t\t$all_capabilities_raw = $this->get_all_capabilities();\n\t\t$all_capabilities     = array_values( $all_capabilities_raw );\n\n\t\t$administrator = get_role( 'administrator' );\n\t\t$editor        = get_role( 'editor' );\n\t\t$author        = get_role( 'author' );\n\t\t$contributor   = get_role( 'contributor' );\n\n\t\tif ( $administrator instanceof WP_Role ) {\n\t\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t\t$administrator->add_cap( $cap );\n\t\t\t}\n\t\t}\n\n\t\tif ( $editor instanceof WP_Role ) {\n\t\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t\t$editor->add_cap( $cap );\n\t\t\t}\n\t\t}\n\n\t\tif ( $author instanceof WP_Role ) {\n\t\t\t$author->add_cap( $all_capabilities_raw['edit_posts'] );\n\t\t\t$author->add_cap( $all_capabilities_raw['edit_published_posts'] );\n\t\t\t$author->add_cap( $all_capabilities_raw['delete_posts'] );\n\t\t\t$author->add_cap( $all_capabilities_raw['delete_published_posts'] );\n\t\t\t$author->add_cap( $all_capabilities_raw['publish_posts'] );\n\t\t\t$author->add_cap( $all_capabilities_raw['assign_terms'] );\n\t\t}\n\n\t\tif ( $contributor instanceof WP_Role ) {\n\t\t\t$contributor->add_cap( $all_capabilities_raw['edit_posts'] );\n\t\t\t$contributor->add_cap( $all_capabilities_raw['delete_posts'] );\n\t\t\t$contributor->add_cap( $all_capabilities_raw['assign_terms'] );\n\t\t}\n\n\t\t/**\n\t\t * Fires when adding the custom capabilities to existing roles.\n\t\t *\n\t\t * Can be used to add the capabilities to other, custom roles.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array $all_capabilities List of all post type capabilities, for reference.\n\t\t */\n\t\tdo_action( 'web_stories_add_capabilities', $all_capabilities );\n\t}\n\n\t/**\n\t * Removes story capabilities from all user roles.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function remove_caps_from_roles(): void {\n\t\t$all_capabilities_raw = $this->get_all_capabilities();\n\t\t$all_capabilities     = array_values( $all_capabilities_raw );\n\t\t$all_capabilities     = array_filter(\n\t\t\t$all_capabilities,\n\t\t\tstatic fn( $value ) => 'read' !== $value\n\t\t);\n\t\t$all_roles            = wp_roles();\n\t\t$roles                = array_values( $all_roles->role_objects );\n\t\tforeach ( $roles as $role ) {\n\t\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t\t$role->remove_cap( $cap );\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Fires when removing the custom capabilities from existing roles.\n\t\t *\n\t\t * Can be used to remove the capabilities from other, custom roles.\n\t\t *\n\t\t * @since 1.0.0\n\t\t *\n\t\t * @param array $all_capabilities List of all post type capabilities, for reference.\n\t\t */\n\t\tdo_action( 'web_stories_remove_capabilities', $all_capabilities );\n\t}\n\n\t/**\n\t * Get a array of capability for post types and taxonomies.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @return array<string,string> Capabilities.\n\t */\n\tprotected function get_all_capabilities(): array {\n\t\treturn array_merge(\n\t\t\tTaxonomy_Base::DEFAULT_CAPABILITIES,\n\t\t\t$this->story_post_type->get_caps(),\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "includes/User/Preferences.php",
    "content": "<?php\n/**\n * User Preferences class.\n *\n * Register user meta.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\User;\n\nuse Google\\Web_Stories\\Infrastructure\\HasMeta;\nuse Google\\Web_Stories\\Infrastructure\\PluginUninstallAware;\nuse Google\\Web_Stories\\Service_Base;\n\n/**\n * User Preferences class.\n */\nclass Preferences extends Service_Base implements HasMeta, PluginUninstallAware {\n\t/**\n\t * Name of the user meta key used for opt-in.\n\t */\n\tpublic const OPTIN_META_KEY = 'web_stories_tracking_optin';\n\n\t/**\n\t * Name of the user meta key used for onboarding.\n\t */\n\tpublic const ONBOARDING_META_KEY = 'web_stories_onboarding';\n\n\t/**\n\t * Name of the user meta key used for media optimization.\n\t */\n\tpublic const MEDIA_OPTIMIZATION_META_KEY = 'web_stories_media_optimization';\n\n\t/**\n\t * Initializes User_Preferences.\n\t *\n\t * Registers the setting in WordPress.\n\t *\n\t * @since 1.0.0\n\t */\n\tpublic function register(): void {\n\t\t$this->register_meta();\n\t}\n\n\t/**\n\t * Register meta\n\t *\n\t * @since 1.15.0\n\t */\n\tpublic function register_meta(): void {\n\t\tregister_meta(\n\t\t\t'user',\n\t\t\tstatic::OPTIN_META_KEY,\n\t\t\t[\n\t\t\t\t'type'              => 'boolean',\n\t\t\t\t'sanitize_callback' => 'rest_sanitize_boolean',\n\t\t\t\t'default'           => false,\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'auth_callback'     => [ $this, 'can_edit_current_user' ],\n\t\t\t\t'single'            => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_meta(\n\t\t\t'user',\n\t\t\tstatic::MEDIA_OPTIMIZATION_META_KEY,\n\t\t\t[\n\t\t\t\t'type'              => 'boolean',\n\t\t\t\t'sanitize_callback' => 'rest_sanitize_boolean',\n\t\t\t\t'default'           => true,\n\t\t\t\t'show_in_rest'      => true,\n\t\t\t\t'auth_callback'     => [ $this, 'can_edit_current_user' ],\n\t\t\t\t'single'            => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_meta(\n\t\t\t'user',\n\t\t\tstatic::ONBOARDING_META_KEY,\n\t\t\t[\n\t\t\t\t'type'          => 'object',\n\t\t\t\t'default'       => [],\n\t\t\t\t'show_in_rest'  => [\n\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t'properties'           => [],\n\t\t\t\t\t\t'additionalProperties' => true,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'auth_callback' => [ $this, 'can_edit_current_user' ],\n\t\t\t\t'single'        => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Auth callback.\n\t *\n\t * @since 1.4.0\n\t *\n\t * @param bool   $allowed Unused. Whether the user can add the object meta.\n\t * @param string $meta_key Unused. The meta key.\n\t * @param int    $user_id ID of the user being edited.\n\t * @param int    $current_user_id The currently editing user's ID.\n\t */\n\tpublic function can_edit_current_user( bool $allowed, string $meta_key, int $user_id, int $current_user_id ): bool {\n\t\treturn user_can( $current_user_id, 'edit_user', $user_id );\n\t}\n\n\t/**\n\t * Returns the specific preference for a givern user.\n\t *\n\t * @since 1.12.0\n\t *\n\t * @param int    $user_id User ID.\n\t * @param string $key Preference key.\n\t * @return mixed User preference value.\n\t */\n\tpublic function get_preference( int $user_id, string $key ) {\n\t\treturn get_user_meta( $user_id, $key, true );\n\t}\n\n\t/**\n\t * Act on plugin uninstall.\n\t *\n\t * @since 1.26.0\n\t */\n\tpublic function on_plugin_uninstall(): void {\n\t\tdelete_metadata( 'user', 0, self::OPTIN_META_KEY, '', true );\n\t\tdelete_metadata( 'user', 0, self::ONBOARDING_META_KEY, '', true );\n\t\tdelete_metadata( 'user', 0, self::MEDIA_OPTIMIZATION_META_KEY, '', true );\n\t}\n}\n"
  },
  {
    "path": "includes/Widgets/Stories.php",
    "content": "<?php\n/**\n * Stories Widgets.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Widgets;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Stories_Script_Data;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse WP_Widget;\n\n/**\n * Class Stories\n *\n * @SuppressWarnings(\"PHPMD.ExcessiveClassComplexity\")\n *\n * @phpstan-type InputArgs array{\n *   type?: string,\n *   id?: string,\n *   name?: string,\n *   label?: string,\n *   value?: string|bool|int,\n *   classname?: string,\n *   wrapper_class?: string,\n *   label_before?: bool,\n *   attributes?: array<string,string|int>\n * }\n */\nclass Stories extends WP_Widget {\n\n\tpublic const SCRIPT_HANDLE = 'web-stories-widget';\n\n\t/**\n\t * Widget args.\n\t *\n\t * @var array<string,string>\n\t */\n\tpublic array $args = [\n\t\t'before_title'  => '<h4 class=\"widgettitle web-stories-widget-title\">',\n\t\t'after_title'   => '</h4>',\n\t\t'before_widget' => '<div class=\"widget-wrap web-stories-widget-wrapper\">',\n\t\t'after_widget'  => '</div>',\n\t];\n\n\t/**\n\t * Assets instance.\n\t *\n\t * @var Assets Assets instance.\n\t */\n\tprotected Assets $assets;\n\n\t/**\n\t * Story_Post_Type instance.\n\t *\n\t * @var Story_Post_Type Story_Post_Type instance.\n\t */\n\tprivate Story_Post_Type $story_post_type;\n\n\t/**\n\t * Stories_Script_Data instance.\n\t *\n\t * @var Stories_Script_Data Stories_Script_Data instance.\n\t */\n\tprotected Stories_Script_Data $stories_script_data;\n\n\t/**\n\t * Stories constructor.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param Assets              $assets Assets instance.\n\t * @param Story_Post_Type     $story_post_type Story_Post_Type instance.\n\t * @param Stories_Script_Data $stories_script_data Stories_Script_Data instance.\n\t * @return void\n\t */\n\tpublic function __construct( Assets $assets, Story_Post_Type $story_post_type, Stories_Script_Data $stories_script_data ) {\n\t\t$this->assets              = $assets;\n\t\t$this->story_post_type     = $story_post_type;\n\t\t$this->stories_script_data = $stories_script_data;\n\t\t$id_base                   = 'web_stories_widget';\n\t\t$name                      = __( 'Web Stories', 'web-stories' );\n\t\t$widget_options            = [\n\t\t\t'description'           => __( 'Display Web Stories in sidebar section.', 'web-stories' ),\n\t\t\t'classname'             => 'web-stories-widget',\n\t\t\t'show_instance_in_rest' => true,\n\t\t];\n\n\t\tparent::__construct( $id_base, $name, $widget_options );\n\t}\n\n\t/**\n\t * Output widget.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string>          $args Widget args.\n\t * @param array<string,string|int|bool> $instance Widget instance.\n\t */\n\tpublic function widget( $args, $instance ): void {\n\t\t// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\techo $args['before_widget'];\n\n\t\t$instance = wp_parse_args( $instance, $this->default_values() );\n\n\t\t$title = $instance['title'];\n\n\t\t/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */\n\t\t$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );\n\n\t\tif ( ! empty( $title ) ) {\n\t\t\techo $args['before_title'] . $title . $args['after_title'];\n\t\t}\n\n\t\t$instance['number_of_columns'] = (int) $instance['number_of_columns'];\n\t\t$instance['number_of_stories'] = (int) $instance['number_of_stories'];\n\t\t$instance['circle_size']       = (int) $instance['circle_size'];\n\n\t\t$story_attrs = [\n\t\t\t'view_type'          => $instance['view_type'],\n\t\t\t'show_title'         => (bool) $instance['show_title'],\n\t\t\t'show_excerpt'       => (bool) $instance['show_excerpt'],\n\t\t\t'show_author'        => (bool) $instance['show_author'],\n\t\t\t'show_date'          => (bool) $instance['show_date'],\n\t\t\t'show_archive_link'  => (bool) $instance['show_archive_link'],\n\t\t\t'archive_link_label' => (string) $instance['archive_link_label'],\n\t\t\t'circle_size'        => min( absint( $instance['circle_size'] ), 150 ),\n\t\t\t'sharp_corners'      => (bool) $instance['sharp_corners'],\n\t\t\t'image_alignment'    => (string) $instance['image_alignment'],\n\t\t\t'number_of_columns'  => min( absint( $instance['number_of_columns'] ), 4 ),\n\t\t\t'class'              => 'web-stories-list--widget',\n\t\t];\n\n\t\t$story_args = [\n\t\t\t'posts_per_page' => min( absint( $instance['number_of_stories'] ), 20 ), // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page\n\t\t\t'orderby'        => $instance['orderby'],\n\t\t\t'order'          => $instance['order'],\n\t\t];\n\n\t\t$story_query = new Story_Query( $story_attrs, $story_args );\n\t\techo $story_query->render();\n\n\t\techo $args['after_widget'];\n\n\t\t// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped\n\t}\n\n\t/**\n\t * Display widget form.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t * @SuppressWarnings(\"PHPMD.ExcessiveMethodLength\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string|int|bool> $instance Widget instance.\n\t */\n\tpublic function form( $instance ): string {\n\t\t$this->enqueue_scripts();\n\n\t\t$instance = wp_parse_args( $instance, $this->default_values() );\n\n\t\t$title              = (string) $instance['title'];\n\t\t$view_types         = $this->stories_script_data->get_layouts();\n\t\t$current_view_type  = (string) $instance['view_type'];\n\t\t$show_title         = ! empty( $instance['show_title'] );\n\t\t$show_author        = ! empty( $instance['show_author'] );\n\t\t$show_date          = ! empty( $instance['show_date'] );\n\t\t$show_excerpt       = ! empty( $instance['show_excerpt'] );\n\t\t$show_archive_link  = ! empty( $instance['show_archive_link'] );\n\t\t$archive_link_label = (string) $instance['archive_link_label'];\n\t\t$circle_size        = (int) $instance['circle_size'];\n\t\t$sharp_corners      = (int) $instance['sharp_corners'];\n\t\t$image_alignment    = (string) $instance['image_alignment'];\n\t\t$number_of_columns  = (int) $instance['number_of_columns'];\n\t\t$number_of_stories  = (int) $instance['number_of_stories'];\n\t\t$orderby            = (string) $instance['orderby'];\n\t\t$order              = (string) $instance['order'];\n\n\t\t$has_archive = $this->story_post_type->get_has_archive();\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'           => 'title',\n\t\t\t\t'name'         => 'title',\n\t\t\t\t'label'        => __( 'Widget Title', 'web-stories' ),\n\t\t\t\t'type'         => 'text',\n\t\t\t\t'value'        => $title,\n\t\t\t\t'label_before' => true,\n\t\t\t]\n\t\t);\n\n\t\t$this->dropdown(\n\t\t\t[\n\t\t\t\t'options'   => $view_types,\n\t\t\t\t'selected'  => $current_view_type,\n\t\t\t\t'name'      => 'view_type',\n\t\t\t\t'id'        => 'view_type',\n\t\t\t\t'label'     => __( 'Select Layout', 'web-stories' ),\n\t\t\t\t'classname' => 'widefat view_type stories-widget-field',\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'number_of_stories',\n\t\t\t\t'name'          => 'number_of_stories',\n\t\t\t\t'label'         => __( 'Number of Stories', 'web-stories' ),\n\t\t\t\t'type'          => 'number',\n\t\t\t\t'classname'     => 'widefat number_of_stories stories-widget-field',\n\t\t\t\t'wrapper_class' => 'number_of_stories_wrapper',\n\t\t\t\t'value'         => $number_of_stories,\n\t\t\t\t'label_before'  => true,\n\t\t\t\t'attributes'    => [\n\t\t\t\t\t'min' => 1,\n\t\t\t\t\t'max' => 20,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->dropdown(\n\t\t\t[\n\t\t\t\t'options'   => [\n\t\t\t\t\t'post_title' => __( 'Title', 'web-stories' ),\n\t\t\t\t\t'post_date'  => __( 'Date', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'selected'  => $orderby,\n\t\t\t\t'name'      => 'orderby',\n\t\t\t\t'id'        => 'orderby',\n\t\t\t\t'label'     => __( 'Order By', 'web-stories' ),\n\t\t\t\t'classname' => 'widefat orderby stories-widget-field',\n\t\t\t]\n\t\t);\n\n\t\t$this->dropdown(\n\t\t\t[\n\t\t\t\t'options'   => [\n\t\t\t\t\t'ASC'  => __( 'Ascending', 'web-stories' ),\n\t\t\t\t\t'DESC' => __( 'Descending', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'selected'  => $order,\n\t\t\t\t'name'      => 'order',\n\t\t\t\t'id'        => 'order',\n\t\t\t\t'label'     => __( 'Order', 'web-stories' ),\n\t\t\t\t'classname' => 'widefat order stories-widget-field',\n\t\t\t]\n\t\t);\n\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'circle-size',\n\t\t\t\t'name'          => 'circle_size',\n\t\t\t\t'label'         => __( 'Circle Size', 'web-stories' ),\n\t\t\t\t'type'          => 'number',\n\t\t\t\t'classname'     => 'widefat circle_size stories-widget-field',\n\t\t\t\t'wrapper_class' => 'circle_size_wrapper',\n\t\t\t\t'value'         => $circle_size,\n\t\t\t\t'label_before'  => true,\n\t\t\t\t'attributes'    => [\n\t\t\t\t\t'min'  => 80,\n\t\t\t\t\t'max'  => 200,\n\t\t\t\t\t'step' => 5,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'number_of_columns',\n\t\t\t\t'name'          => 'number_of_columns',\n\t\t\t\t'label'         => __( 'Number of Columns', 'web-stories' ),\n\t\t\t\t'type'          => 'number',\n\t\t\t\t'classname'     => 'widefat number_of_columns stories-widget-field',\n\t\t\t\t'wrapper_class' => 'number_of_columns_wrapper',\n\t\t\t\t'value'         => $number_of_columns,\n\t\t\t\t'label_before'  => true,\n\t\t\t\t'attributes'    => [\n\t\t\t\t\t'min' => 1,\n\t\t\t\t\t'max' => 4,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'show_title',\n\t\t\t\t'name'          => 'show_title',\n\t\t\t\t'label'         => __( 'Display Title', 'web-stories' ),\n\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t'classname'     => 'widefat title stories-widget-field',\n\t\t\t\t'wrapper_class' => 'title_wrapper',\n\t\t\t\t'value'         => $show_title,\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'show_excerpt',\n\t\t\t\t'name'          => 'show_excerpt',\n\t\t\t\t'label'         => __( 'Display Excerpt', 'web-stories' ),\n\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t'classname'     => 'widefat excerpt stories-widget-field',\n\t\t\t\t'wrapper_class' => 'excerpt_wrapper',\n\t\t\t\t'value'         => $show_excerpt,\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'show_author',\n\t\t\t\t'name'          => 'show_author',\n\t\t\t\t'label'         => __( 'Display Author', 'web-stories' ),\n\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t'classname'     => 'widefat author stories-widget-field',\n\t\t\t\t'wrapper_class' => 'author_wrapper',\n\t\t\t\t'value'         => $show_author,\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'show_date',\n\t\t\t\t'name'          => 'show_date',\n\t\t\t\t'label'         => __( 'Display Date', 'web-stories' ),\n\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t'classname'     => 'widefat date stories-widget-field',\n\t\t\t\t'wrapper_class' => 'date_wrapper',\n\t\t\t\t'value'         => $show_date,\n\t\t\t]\n\t\t);\n\n\t\t$this->radio(\n\t\t\t[\n\t\t\t\t'options'       => [\n\t\t\t\t\t'left'  => __( 'Left', 'web-stories' ),\n\t\t\t\t\t'right' => __( 'Right', 'web-stories' ),\n\t\t\t\t],\n\t\t\t\t'selected'      => $image_alignment,\n\t\t\t\t'id'            => 'image_alignment',\n\t\t\t\t'name'          => 'image_alignment',\n\t\t\t\t'label'         => __( 'Image Alignment', 'web-stories' ),\n\t\t\t\t'classname'     => 'widefat image_alignment stories-widget-field',\n\t\t\t\t'wrapper_class' => 'image_alignment_wrapper',\n\t\t\t]\n\t\t);\n\n\t\t$this->input(\n\t\t\t[\n\t\t\t\t'id'            => 'sharp_corners',\n\t\t\t\t'name'          => 'sharp_corners',\n\t\t\t\t'label'         => __( 'Use Sharp Corners', 'web-stories' ),\n\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t'classname'     => 'widefat sharp_corners stories-widget-field',\n\t\t\t\t'wrapper_class' => 'sharp_corners_wrapper',\n\t\t\t\t'value'         => $sharp_corners,\n\t\t\t]\n\t\t);\n\n\t\tif ( $has_archive ) {\n\t\t\t$this->input(\n\t\t\t\t[\n\t\t\t\t\t'id'            => 'show_archive_link',\n\t\t\t\t\t'name'          => 'show_archive_link',\n\t\t\t\t\t'label'         => __( 'Display Archive Link', 'web-stories' ),\n\t\t\t\t\t'type'          => 'checkbox',\n\t\t\t\t\t'classname'     => 'widefat show_archive_link stories-widget-field',\n\t\t\t\t\t'wrapper_class' => 'archive_link_wrapper',\n\t\t\t\t\t'value'         => $show_archive_link,\n\t\t\t\t]\n\t\t\t);\n\n\t\t\t$this->input(\n\t\t\t\t[\n\t\t\t\t\t'id'            => 'archive_link_label',\n\t\t\t\t\t'name'          => 'archive_link_label',\n\t\t\t\t\t'label'         => __( 'Archive Link Label', 'web-stories' ),\n\t\t\t\t\t'type'          => 'text',\n\t\t\t\t\t'classname'     => 'widefat archive_link_label stories-widget-field',\n\t\t\t\t\t'wrapper_class' => 'archive_link_label_wrapper',\n\t\t\t\t\t'value'         => $archive_link_label,\n\t\t\t\t\t'label_before'  => true,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t/**\n\t * Update widget settings.\n\t *\n\t * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string|int|bool> $new_instance New instance.\n\t * @param array<string,string|int|bool> $old_instance Old instance.\n\t * @return array<string,string|int|bool>\n\t */\n\tpublic function update( $new_instance, $old_instance ): array {\n\t\t$instance = [];\n\n\t\t$new_instance = wp_parse_args( $new_instance, $this->default_values() );\n\n\t\t$instance['title']              = wp_strip_all_tags( $new_instance['title'] );\n\t\t$instance['view_type']          = $new_instance['view_type'];\n\t\t$instance['show_title']         = $new_instance['show_title'];\n\t\t$instance['show_excerpt']       = $new_instance['show_excerpt'];\n\t\t$instance['show_author']        = $new_instance['show_author'];\n\t\t$instance['show_date']          = $new_instance['show_date'];\n\t\t$instance['show_archive_link']  = $new_instance['show_archive_link'];\n\t\t$instance['image_alignment']    = $new_instance['image_alignment'];\n\t\t$instance['number_of_columns']  = min( absint( $new_instance['number_of_columns'] ), 4 );\n\t\t$instance['number_of_stories']  = min( absint( $new_instance['number_of_stories'] ), 20 );\n\t\t$instance['circle_size']        = min( absint( $new_instance['circle_size'] ), 150 );\n\t\t$instance['archive_link_label'] = $new_instance['archive_link_label'];\n\t\t$instance['sharp_corners']      = $new_instance['sharp_corners'];\n\t\t$instance['orderby']            = $new_instance['orderby'];\n\t\t$instance['order']              = $new_instance['order'];\n\n\t\treturn $instance;\n\t}\n\n\t/**\n\t * Enqueue widget script.\n\t *\n\t * @since 1.5.0\n\t */\n\tpublic function enqueue_scripts(): void {\n\t\tif ( wp_script_is( self::SCRIPT_HANDLE ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$this->assets->enqueue_style_asset( self::SCRIPT_HANDLE );\n\t\t$this->assets->enqueue_script_asset( self::SCRIPT_HANDLE, [ 'jquery' ] );\n\n\t\twp_localize_script(\n\t\t\tself::SCRIPT_HANDLE,\n\t\t\t'webStoriesData',\n\t\t\t$this->stories_script_data->get_script_data()\n\t\t);\n\t}\n\n\t/**\n\t * Default values of an instance.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @return array<string,string|int> Default values.\n\t */\n\tprivate function default_values(): array {\n\t\treturn [\n\t\t\t'title'              => esc_html__( 'Web Stories', 'web-stories' ),\n\t\t\t'view_type'          => 'circles',\n\t\t\t'show_title'         => '',\n\t\t\t'show_excerpt'       => '',\n\t\t\t'show_author'        => '',\n\t\t\t'show_date'          => '',\n\t\t\t'show_archive_link'  => '',\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'number_of_columns'  => 1,\n\t\t\t'number_of_stories'  => 5,\n\t\t\t'circle_size'        => 100,\n\t\t\t'archive_link_label' => __( 'View all stories', 'web-stories' ),\n\t\t\t'sharp_corners'      => '',\n\t\t\t'orderby'            => 'post_date',\n\t\t\t'order'              => 'DESC',\n\t\t];\n\t}\n\n\t/**\n\t * Display dropdown.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,string|array<string,string>> $args Field args.\n\t */\n\tprivate function dropdown( array $args ): void {\n\t\t$args = wp_parse_args(\n\t\t\t$args,\n\t\t\t[\n\t\t\t\t'options'       => [],\n\t\t\t\t'selected'      => '',\n\t\t\t\t'id'            => wp_generate_uuid4(),\n\t\t\t\t'name'          => wp_generate_uuid4(),\n\t\t\t\t'label'         => '',\n\t\t\t\t'classname'     => 'widefat',\n\t\t\t\t'wrapper_class' => 'web-stories-field-wrapper',\n\t\t\t]\n\t\t);\n\t\t?>\n\t<p class=\"<?php echo esc_attr( $args['wrapper_class'] ); ?>\">\n\t\t<?php echo $this->label( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>\n\n\t\t<select\n\t\t\tclass=\"<?php echo esc_attr( (string) $args['classname'] ); ?>\"\n\t\t\tid=\"<?php echo esc_attr( $this->get_field_id( $args['id'] ) ); ?>\"\n\t\t\tname=\"<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>\"\n\t\t>\n\t\t\t<?php\n\n\t\t\tforeach ( $args['options'] as $key => $type ) {\n\t\t\t\t?>\n\t\t\t\t<option value=\"<?php echo esc_attr( $key ); ?>\"\n\t\t\t\t\t<?php selected( $key, $args['selected'], true ); ?>\n\t\t\t\t>\n\t\t\t\t\t<?php echo esc_attr( $type ); ?>\n\t\t\t\t</option>\n\t\t\t\t<?php\n\t\t\t}\n\t\t\t?>\n\t\t</select>\n\t\t</p>\n\t\t<?php\n\t}\n\n\t/**\n\t * Display radio buttons.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Field args.\n\t */\n\tprivate function radio( array $args ): void {\n\t\t$args = wp_parse_args(\n\t\t\t$args,\n\t\t\t[\n\t\t\t\t'options'       => [],\n\t\t\t\t'selected'      => '',\n\t\t\t\t'id'            => wp_generate_uuid4(),\n\t\t\t\t'name'          => wp_generate_uuid4(),\n\t\t\t\t'label'         => '',\n\t\t\t\t'classname'     => 'widefat',\n\t\t\t\t'wrapper_class' => 'web-stories-field-wrapper',\n\t\t\t]\n\t\t);\n\t\t?>\n\t\t<div class=\"<?php echo esc_attr( $args['wrapper_class'] ); ?>\">\n\t\t\t<?php echo $this->label( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>\n\t\t\t<p>\n\t\t\t\t<?php\n\t\t\t\tforeach ( $args['options'] as $key => $type ) {\n\t\t\t\t\t?>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tclass=\"<?php echo esc_attr( (string) $args['classname'] ); ?>\"\n\t\t\t\t\t\t\tid=\"<?php echo esc_attr( $this->get_field_id( $args['id'] . '-' . $key ) ); ?>\"\n\t\t\t\t\t\t\tname=\"<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>\"\n\t\t\t\t\t\t\tvalue=\"<?php echo esc_attr( $key ); ?>\"\n\t\t\t\t\t\t\t<?php checked( $key, $args['selected'], true ); ?>\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<?php echo esc_attr( $type ); ?>\n\t\t\t\t\t</label>\n\t\t\t\t\t<br>\n\t\t\t\t\t<?php\n\t\t\t\t}\n\t\t\t\t?>\n\t\t\t</p>\n\t\t</div>\n\t\t<?php\n\t}\n\n\t/**\n\t * Display an input field.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array $args Field args.\n\t *\n\t * @phpstan-param InputArgs $args\n\t */\n\tprivate function input( array $args ): void {\n\t\t$args = wp_parse_args(\n\t\t\t$args,\n\t\t\t[\n\t\t\t\t'type'          => 'text',\n\t\t\t\t'id'            => wp_generate_uuid4(),\n\t\t\t\t'name'          => wp_generate_uuid4(),\n\t\t\t\t'label'         => '',\n\t\t\t\t'value'         => '',\n\t\t\t\t'classname'     => 'widefat',\n\t\t\t\t'wrapper_class' => 'web-stories-field-wrapper',\n\t\t\t\t'label_before'  => false,\n\t\t\t\t'attributes'    => [],\n\t\t\t]\n\t\t);\n\n\t\t?>\n\t\t<p class=\"<?php echo esc_attr( (string) $args['wrapper_class'] ); ?>\">\n\n\t\t\t<?php\n\t\t\tif ( $args['label_before'] ) {\n\t\t\t\techo $this->label( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t\t}\n\n\t\t\t$extra_attrs = '';\n\n\t\t\tif ( ! empty( $args['attributes'] ) && \\is_array( $args['attributes'] ) ) {\n\t\t\t\t/**\n\t\t\t\t * Value.\n\t\t\t\t *\n\t\t\t\t * @var string $attr_val\n\t\t\t\t */\n\t\t\t\tforeach ( $args['attributes'] as $attr_key => $attr_val ) {\n\t\t\t\t\t$extra_attrs .= \\sprintf( ' %1s=%2s', $attr_key, esc_attr( $attr_val ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\t?>\n\n\t\t\t<input\n\t\t\t\tclass=\"<?php echo esc_attr( (string) $args['classname'] ); ?>\"\n\t\t\t\ttype=\"<?php echo esc_attr( (string) $args['type'] ); ?>\"\n\t\t\t\tid=\"<?php echo esc_attr( $this->get_field_id( $args['id'] ) ); ?>\"\n\t\t\t\tname=\"<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>\"\n\t\t\t\tvalue=\"<?php echo esc_attr( 'checkbox' === $args['type'] ? 1 : $args['value'] ); ?>\"\n\t\t\t\t<?php\n\t\t\t\tif ( 'checkbox' === $args['type'] ) {\n\t\t\t\t\tchecked( 1, $args['value'], true );\n\t\t\t\t}\n\t\t\t\t?>\n\t\t\t\t<?php echo $extra_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>\n\t\t\t/>\n\n\t\t\t<?php\n\t\t\tif ( ! $args['label_before'] ) {\n\t\t\t\techo $this->label( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t\t}\n\t\t\t?>\n\n\t\t</p>\n\t\t<?php\n\t}\n\n\t/**\n\t * Display an label.\n\t *\n\t * @since 1.5.0\n\t *\n\t * @param array<string,mixed> $args Label args.\n\t */\n\tprivate function label( array $args ): string {\n\t\t$args = wp_parse_args(\n\t\t\t$args,\n\t\t\t[\n\t\t\t\t'id'    => '',\n\t\t\t\t'label' => '',\n\t\t\t]\n\t\t);\n\t\tob_start();\n\t\t?>\n\t\t<label for=\"<?php echo esc_attr( $this->get_field_id( $args['id'] ) ); ?>\">\n\t\t\t<?php echo esc_html( (string) $args['label'] ); ?>\n\t\t</label>\n\t\t<?php\n\n\t\treturn (string) ob_get_clean();\n\t}\n}\n"
  },
  {
    "path": "includes/compat/Web_Stories_Compatibility.php",
    "content": "<?php\n/**\n * Class Compatibility\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Class Compatibility\n *\n * @since 1.2.0\n */\nclass Web_Stories_Compatibility {\n\n\t/**\n\t * WP_Error object passed back.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @var WP_Error\n\t */\n\tprotected $error;\n\n\t/**\n\t * WordPress version.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @var string\n\t */\n\tprotected $wp_version;\n\n\t/**\n\t * PHP version.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @var string\n\t */\n\tprotected $php_version;\n\n\t/**\n\t * Array of extensions.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @var array<string, array{functions?: string[], classes?: string[]}>\n\t */\n\tprotected $extensions = array();\n\n\t/**\n\t * Array of required files.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @var string[]\n\t */\n\tprotected $required_files = array();\n\n\t/**\n\t * Compatibility constructor.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param WP_Error $error       WP_Error object passed back.\n\t */\n\tpublic function __construct( WP_Error $error ) { // phpcs:ignore SlevomatCodingStandard.Namespaces.FullyQualifiedExceptions.NonFullyQualifiedException\n\t\t$this->error = $error;\n\t}\n\n\t/**\n\t * Check to see if PHP version check passes.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_php_version() {\n\t\tif ( version_compare( PHP_VERSION, $this->get_php_version(), '<' ) ) {\n\t\t\t/* translators: %s: PHP version number */\n\t\t\t$message = esc_html( sprintf( __( 'Web Stories requires PHP %s or higher.', 'web-stories' ), $this->get_php_version() ) );\n\t\t\t$data    = array(\n\t\t\t\t'title' => $message,\n\t\t\t);\n\t\t\t$this->add_to_error( 'failed_check_php_version', $message, $data );\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check to see if WordPress version check passes.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_wp_version() {\n\t\tif ( version_compare( get_bloginfo( 'version' ), $this->get_wp_version(), '<' ) ) {\n\t\t\t/* translators: %s: WordPress version number */\n\t\t\t$message = esc_html( sprintf( __( 'Web Stories requires WordPress %s or higher.', 'web-stories' ), $this->get_wp_version() ) );\n\t\t\t$data    = array(\n\t\t\t\t'title' => $message,\n\t\t\t);\n\t\t\t$this->add_to_error( 'failed_check_wp_version', $message, $data );\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check if required files.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_required_files() {\n\t\t$required_files = $this->get_required_files();\n\t\tif ( $required_files ) {\n\t\t\tforeach ( $required_files as $required_file ) {\n\t\t\t\tif ( ! is_readable( $required_file ) ) {\n\t\t\t\t\t$message =\n\t\t\t\t\t\tsprintf(\n\t\t\t\t\t\t/* translators: %s: build commands. */\n\t\t\t\t\t\t\t__( 'You appear to be running an incomplete version of the plugin. Please run %s to finish installation.', 'web-stories' ),\n\t\t\t\t\t\t\t'<code>composer install &amp;&amp; npm install &amp;&amp; npm run build</code>'\n\t\t\t\t\t\t);\n\t\t\t\t\t$data = array(\n\t\t\t\t\t\t'title' => esc_html__( 'Web Stories plugin could not be initialized.', 'web-stories' ),\n\t\t\t\t\t);\n\t\t\t\t\t$this->add_to_error( 'failed_check_required_files', $message, $data );\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check to see if all required PHP extensions are installed.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_extensions() {\n\t\t$missing_extensions = array();\n\t\tforeach ( array_keys( $this->get_extensions() ) as $required_extension ) {\n\t\t\tif ( ! extension_loaded( $required_extension ) ) {\n\t\t\t\t$missing_extensions[] = \"<code>$required_extension</code>\";\n\t\t\t}\n\t\t}\n\n\t\tif ( count( $missing_extensions ) > 0 ) {\n\t\t\t$this->add_to_error(\n\t\t\t\t'missing_extension',\n\t\t\t\tsprintf(\n\t\t\t\t\t/* translators: %s is list of missing extensions */\n\t\t\t\t\t_n(\n\t\t\t\t\t\t'The following PHP extension is missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\t'The following PHP extensions are missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\tcount( $missing_extensions ),\n\t\t\t\t\t\t'web-stories'\n\t\t\t\t\t),\n\t\t\t\t\timplode( ', ', $missing_extensions )\n\t\t\t\t)\n\t\t\t);\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check to see if classes exist.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_classes() {\n\t\t$missing_classes = array();\n\t\tforeach ( $this->get_extensions() as $required_constructs ) {\n\t\t\tforeach ( $required_constructs as $construct_type => $constructs ) {\n\t\t\t\tif ( 'classes' !== $construct_type ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tforeach ( $constructs as $construct ) {\n\t\t\t\t\tif ( ! class_exists( $construct ) ) {\n\t\t\t\t\t\t$missing_classes[] = \"<code>$construct</code>\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( count( $missing_classes ) > 0 ) {\n\t\t\t$this->add_to_error(\n\t\t\t\t'missing_class',\n\t\t\t\tsprintf(\n\t\t\t\t\t/* translators: %s is list of missing extensions */\n\t\t\t\t\t_n(\n\t\t\t\t\t\t'The following PHP class is missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\t'The following PHP classes are missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\tcount( $missing_classes ),\n\t\t\t\t\t\t'web-stories'\n\t\t\t\t\t),\n\t\t\t\t\timplode( ', ', $missing_classes )\n\t\t\t\t)\n\t\t\t);\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Check to see if all require functions exist.\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return bool\n\t */\n\tpublic function check_functions() {\n\t\t$missing_functions = array();\n\t\tforeach ( $this->get_extensions() as $required_constructs ) {\n\t\t\tforeach ( $required_constructs as $construct_type => $constructs ) {\n\t\t\t\tif ( 'functions' !== $construct_type ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tforeach ( $constructs as $construct ) {\n\t\t\t\t\tif ( ! function_exists( $construct ) ) {\n\t\t\t\t\t\t$missing_functions[] = \"<code>$construct</code>\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( count( $missing_functions ) > 0 ) {\n\t\t\t$this->add_to_error(\n\t\t\t\t'missing_function',\n\t\t\t\tsprintf(\n\t\t\t\t/* translators: %s is list of missing extensions */\n\t\t\t\t\t_n(\n\t\t\t\t\t\t'The following PHP function is missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\t'The following PHP functions are missing: %s. Please contact your host to finish installation.',\n\t\t\t\t\t\tcount( $missing_functions ),\n\t\t\t\t\t\t'web-stories'\n\t\t\t\t\t),\n\t\t\t\t\timplode( ', ', $missing_functions )\n\t\t\t\t)\n\t\t\t);\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Run checks in admin.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return void\n\t */\n\tpublic function run_checks() {\n\t\t$this->check_php_version();\n\t\t$this->check_wp_version();\n\t\t$this->check_required_files();\n\t\t$this->check_extensions();\n\t\t$this->check_classes();\n\t\t$this->check_functions();\n\t}\n\n\t/**\n\t * Get min WP version.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @return string\n\t */\n\tpublic function get_wp_version() {\n\t\treturn $this->wp_version;\n\t}\n\n\t/**\n\t * Get min PHP version.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return string\n\t */\n\tpublic function get_php_version() {\n\t\treturn $this->php_version;\n\t}\n\n\t/**\n\t * Array of extensions.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return array<string, array{functions?: string[], classes?: string[]}>\n\t */\n\tpublic function get_extensions() {\n\t\treturn $this->extensions;\n\t}\n\n\t/**\n\t * Get JavaScript path.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return string[]\n\t */\n\tpublic function get_required_files() {\n\t\treturn $this->required_files;\n\t}\n\n\t/**\n\t * Getter to get the error object.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @return WP_Error\n\t */\n\tpublic function get_error() {\n\t\treturn $this->error;\n\t}\n\n\t/**\n\t * Set WordPress version.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param string $wp_version WordPress version.\n\t * @return void\n\t */\n\tpublic function set_wp_version( $wp_version ) {\n\t\t$this->wp_version = $wp_version;\n\t}\n\n\t/**\n\t * Set PHP version.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param string $php_version PHP version.\n\t * @return void\n\t */\n\tpublic function set_php_version( $php_version ) {\n\t\t$this->php_version = $php_version;\n\t}\n\n\t/**\n\t * Set extensions.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param array<string, array{functions?: string[], classes?: string[]}> $extensions Array of extensions.\n\t * @return void\n\t */\n\tpublic function set_extensions( array $extensions ) {\n\t\t$this->extensions = $extensions;\n\t}\n\n\t/**\n\t * Array of require files.\n\t *\n\t * @codeCoverageIgnore\n\t *\n\t * @since 1.2.0\n\t *\n\t * @param string[] $required_files Array of require files.\n\t * @return void\n\t */\n\tpublic function set_required_files( array $required_files ) {\n\t\t$this->required_files = $required_files;\n\t}\n\n\t/**\n\t * Helper to add error code to WP_Error object.\n\t *\n\t * @param string|int $code    Error code.\n\t * @param string     $message Error message.\n\t * @param mixed      $data    Optional. Error data.\n\t * @return void\n\t */\n\tprotected function add_to_error( $code, $message, $data = '' ) {\n\t\tif ( ! in_array( $code, $this->error->get_error_codes(), true ) ) {\n\t\t\t$this->error->add( $code, $message, $data );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "includes/compat/amp.php",
    "content": "<?php\n/**\n * AMP plugin compatibility functionality.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\nif ( ! function_exists( '\\is_amp_endpoint' ) ) {\n\t/**\n\t * Determine whether the current response being served as AMP.\n\t *\n\t * Polyfill to ensure compatibility with plugins checking for AMP\n\t * when the AMP plugin itself is not available.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return bool Whether it is singular story post (and thus an AMP endpoint).\n\t */\n\tfunction is_amp_endpoint(): bool {\n\t\t// Not using Context class because it's not available yet at this point.\n\t\treturn is_singular( Story_Post_Type::POST_TYPE_SLUG ) && ! is_embed() && ! post_password_required();\n\t}\n}\n\nif ( ! function_exists( '\\amp_is_request' ) ) {\n\t/**\n\t * Determine whether the current response being served as AMP.\n\t *\n\t * Polyfill to ensure compatibility with plugins checking for AMP\n\t * when the AMP plugin itself is not available.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return bool Whether it is singular story post (and thus an AMP endpoint).\n\t */\n\tfunction amp_is_request(): bool {\n\t\treturn is_amp_endpoint();\n\t}\n}\n"
  },
  {
    "path": "includes/data/fonts/fonts.json",
    "content": "[\n  {\n    \"family\": \"ABeeZee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -262,\n      \"tAsc\": 920,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 263,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -262,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abel\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2006,\n      \"des\": -604,\n      \"tAsc\": 2006,\n      \"tDes\": -604,\n      \"tLGap\": 0,\n      \"wAsc\": 2006,\n      \"wDes\": 604,\n      \"xH\": 1044,\n      \"capH\": 1434,\n      \"yMin\": -604,\n      \"yMax\": 2005,\n      \"hAsc\": 2006,\n      \"hDes\": -604,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abhaya Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 860,\n      \"des\": -348,\n      \"tAsc\": 860,\n      \"tDes\": -348,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 348,\n      \"yMin\": -340,\n      \"yMax\": 856,\n      \"hAsc\": 860,\n      \"hDes\": -348,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aboreto\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -230,\n      \"tAsc\": 930,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 924,\n      \"wDes\": 256,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -256,\n      \"yMax\": 924,\n      \"hAsc\": 930,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abril Fatface\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1058,\n      \"des\": -291,\n      \"tAsc\": 1058,\n      \"tDes\": -291,\n      \"tLGap\": 0,\n      \"wAsc\": 1058,\n      \"wDes\": 291,\n      \"xH\": 476,\n      \"capH\": 700,\n      \"yMin\": -291,\n      \"yMax\": 1058,\n      \"hAsc\": 1058,\n      \"hDes\": -291,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abyssinica SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2034,\n      \"des\": -682,\n      \"tAsc\": 2034,\n      \"tDes\": -682,\n      \"tLGap\": 0,\n      \"wAsc\": 2034,\n      \"wDes\": 682,\n      \"xH\": 983,\n      \"capH\": 1108,\n      \"yMin\": -682,\n      \"yMax\": 2034,\n      \"hAsc\": 2034,\n      \"hDes\": -682,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aclonica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1687,\n      \"des\": -533,\n      \"tAsc\": 1687,\n      \"tDes\": -533,\n      \"tLGap\": 101,\n      \"wAsc\": 1687,\n      \"wDes\": 533,\n      \"xH\": 1155,\n      \"capH\": 1440,\n      \"yMin\": -607,\n      \"yMax\": 2141,\n      \"hAsc\": 1687,\n      \"hDes\": -533,\n      \"lGap\": 101\n    }\n  },\n  {\n    \"family\": \"Acme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -307,\n      \"tAsc\": 959,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 307,\n      \"xH\": 107,\n      \"capH\": 695,\n      \"yMin\": -307,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Actor\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 941,\n      \"des\": -262,\n      \"tAsc\": 941,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 941,\n      \"wDes\": 262,\n      \"xH\": 503,\n      \"capH\": 682,\n      \"yMin\": -262,\n      \"yMax\": 941,\n      \"hAsc\": 941,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Adamina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1072,\n      \"des\": -290,\n      \"tAsc\": 1072,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 290,\n      \"xH\": 534,\n      \"capH\": 796,\n      \"yMin\": -290,\n      \"yMax\": 1072,\n      \"hAsc\": 1072,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ADLaM Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2140,\n      \"des\": -532,\n      \"tAsc\": 2140,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 2140,\n      \"wDes\": 532,\n      \"xH\": 1118,\n      \"capH\": 1434,\n      \"yMin\": -526,\n      \"yMax\": 2034,\n      \"hAsc\": 2140,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Advent Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -232,\n      \"tAsc\": 962,\n      \"tDes\": -232,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 232,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 962,\n      \"hAsc\": 964,\n      \"hDes\": -232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Afacad\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1440,\n      \"asc\": 1440,\n      \"des\": -480,\n      \"tAsc\": 1440,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 480,\n      \"xH\": 600,\n      \"capH\": 900,\n      \"yMin\": -433,\n      \"yMax\": 1368,\n      \"hAsc\": 1440,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Afacad Flux\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1440,\n      \"asc\": 1440,\n      \"des\": -480,\n      \"tAsc\": 1440,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 480,\n      \"xH\": 600,\n      \"capH\": 900,\n      \"yMin\": -433,\n      \"yMax\": 1368,\n      \"hAsc\": 1440,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agbalumo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -280,\n      \"tAsc\": 1200,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 600,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -335,\n      \"yMax\": 1173,\n      \"hAsc\": 1200,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agdasima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -410,\n      \"tAsc\": 1565,\n      \"tDes\": -369,\n      \"tLGap\": 164,\n      \"wAsc\": 1889,\n      \"wDes\": 410,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -371,\n      \"yMax\": 1766,\n      \"hAsc\": 2015,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agu Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1190,\n      \"des\": -310,\n      \"tAsc\": 1190,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 1186,\n      \"hAsc\": 1190,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aguafina Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -581,\n      \"tAsc\": 966,\n      \"tDes\": -581,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 581,\n      \"xH\": 356,\n      \"capH\": 780,\n      \"yMin\": -581,\n      \"yMax\": 966,\n      \"hAsc\": 966,\n      \"hDes\": -581,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akatab\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2093,\n      \"des\": -713,\n      \"tAsc\": 2093,\n      \"tDes\": -713,\n      \"tLGap\": 0,\n      \"wAsc\": 2093,\n      \"wDes\": 713,\n      \"xH\": 1024,\n      \"capH\": 1393,\n      \"yMin\": -713,\n      \"yMax\": 2033,\n      \"hAsc\": 2093,\n      \"hDes\": -713,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akaya Kanadaka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -276,\n      \"tAsc\": 920,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 834,\n      \"xH\": 396,\n      \"capH\": 634,\n      \"yMin\": -834,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akaya Telivigala\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -276,\n      \"tAsc\": 920,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 834,\n      \"xH\": 450,\n      \"capH\": 613,\n      \"yMin\": -805,\n      \"yMax\": 1011,\n      \"hAsc\": 920,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akronim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 785,\n      \"des\": -314,\n      \"tAsc\": 785,\n      \"tDes\": -314,\n      \"tLGap\": 43,\n      \"wAsc\": 989,\n      \"wDes\": 404,\n      \"xH\": 486,\n      \"capH\": 730,\n      \"yMin\": -404,\n      \"yMax\": 989,\n      \"hAsc\": 785,\n      \"hDes\": -314,\n      \"lGap\": 43\n    }\n  },\n  {\n    \"family\": \"Akshar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -390,\n      \"tAsc\": 990,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 390,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -317,\n      \"yMax\": 991,\n      \"hAsc\": 990,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aladin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -321,\n      \"tAsc\": 905,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 905,\n      \"wDes\": 321,\n      \"xH\": 337,\n      \"capH\": 387,\n      \"yMin\": -321,\n      \"yMax\": 905,\n      \"hAsc\": 905,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alan Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 212,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -212,\n      \"yMax\": 912,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -280,\n      \"tAsc\": 1100,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 350,\n      \"xH\": 459,\n      \"capH\": 735,\n      \"yMin\": -302,\n      \"yMax\": 1254,\n      \"hAsc\": 1100,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alatsi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 3000,\n      \"wDes\": 700,\n      \"xH\": 996,\n      \"capH\": 1394,\n      \"yMin\": -650,\n      \"yMax\": 2344,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Albert Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -264,\n      \"yMax\": 958,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aldrich\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1475,\n      \"des\": -430,\n      \"tAsc\": 1475,\n      \"tDes\": -430,\n      \"tLGap\": 98,\n      \"wAsc\": 1872,\n      \"wDes\": 586,\n      \"xH\": 1065,\n      \"capH\": 1434,\n      \"yMin\": -809,\n      \"yMax\": 2120,\n      \"hAsc\": 1475,\n      \"hDes\": -430,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Alef\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2067,\n      \"des\": -722,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 2067,\n      \"wDes\": 722,\n      \"xH\": 1040,\n      \"capH\": 1438,\n      \"yMin\": -682,\n      \"yMax\": 2067,\n      \"hAsc\": 2067,\n      \"hDes\": -722,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -345,\n      \"tAsc\": 1016,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 345,\n      \"xH\": 452,\n      \"capH\": 637,\n      \"yMin\": -293,\n      \"yMax\": 962,\n      \"hAsc\": 1016,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1126,\n      \"wDes\": 312,\n      \"xH\": 458,\n      \"capH\": 641,\n      \"yMin\": -262,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1131,\n      \"wDes\": 312,\n      \"xH\": 458,\n      \"capH\": 641,\n      \"yMin\": -262,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -345,\n      \"tAsc\": 1016,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 345,\n      \"xH\": 452,\n      \"capH\": 636,\n      \"yMin\": -293,\n      \"yMax\": 1025,\n      \"hAsc\": 1016,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aleo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -295,\n      \"tAsc\": 905,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 372,\n      \"xH\": 507,\n      \"capH\": 737,\n      \"yMin\": -335,\n      \"yMax\": 1140,\n      \"hAsc\": 905,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alex Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 825,\n      \"des\": -425,\n      \"tAsc\": 825,\n      \"tDes\": -425,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 430,\n      \"xH\": 320,\n      \"capH\": 700,\n      \"yMin\": -425,\n      \"yMax\": 962,\n      \"hAsc\": 825,\n      \"hDes\": -425,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alexandria\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1166,\n      \"wDes\": 566,\n      \"xH\": 531,\n      \"capH\": 700,\n      \"yMin\": -566,\n      \"yMax\": 1146,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alfa Slab One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -333,\n      \"tAsc\": 1036,\n      \"tDes\": -333,\n      \"tLGap\": 0,\n      \"wAsc\": 1238,\n      \"wDes\": 327,\n      \"xH\": 556,\n      \"capH\": 778,\n      \"yMin\": -327,\n      \"yMax\": 1238,\n      \"hAsc\": 1036,\n      \"hDes\": -333,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alice\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 909,\n      \"des\": -234,\n      \"tAsc\": 909,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 868,\n      \"wDes\": 323,\n      \"xH\": 453,\n      \"capH\": 631,\n      \"yMin\": -323,\n      \"yMax\": 849,\n      \"hAsc\": 909,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alike\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -270,\n      \"tAsc\": 984,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 335,\n      \"xH\": 505,\n      \"capH\": 705,\n      \"yMin\": -335,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alike Angular\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -270,\n      \"tAsc\": 984,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 335,\n      \"xH\": 505,\n      \"capH\": 705,\n      \"yMin\": -335,\n      \"yMax\": 977,\n      \"hAsc\": 984,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alkalami\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -857,\n      \"tAsc\": 1035,\n      \"tDes\": -857,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 1200,\n      \"xH\": 430,\n      \"capH\": 660,\n      \"yMin\": -1056,\n      \"yMax\": 1372,\n      \"hAsc\": 1035,\n      \"hDes\": -857,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alkatra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -589,\n      \"tAsc\": 1095,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 1121,\n      \"wDes\": 606,\n      \"xH\": 475,\n      \"capH\": 680,\n      \"yMin\": -606,\n      \"yMax\": 1121,\n      \"hAsc\": 1095,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allan\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1928,\n      \"des\": -412,\n      \"tAsc\": 1928,\n      \"tDes\": -412,\n      \"tLGap\": 0,\n      \"wAsc\": 1928,\n      \"wDes\": 412,\n      \"xH\": 1040,\n      \"capH\": 1483,\n      \"yMin\": -418,\n      \"yMax\": 1929,\n      \"hAsc\": 1928,\n      \"hDes\": -412,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allerta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1057,\n      \"des\": -252,\n      \"tAsc\": 1057,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 252,\n      \"xH\": 564,\n      \"capH\": 737,\n      \"yMin\": -252,\n      \"yMax\": 1057,\n      \"hAsc\": 1057,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allerta Stencil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1057,\n      \"des\": -252,\n      \"tAsc\": 1057,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 252,\n      \"xH\": 564,\n      \"capH\": 737,\n      \"yMin\": -252,\n      \"yMax\": 1055,\n      \"hAsc\": 1057,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allison\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -380,\n      \"tAsc\": 890,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 396,\n      \"xH\": 220,\n      \"capH\": 630,\n      \"yMin\": -396,\n      \"yMax\": 916,\n      \"hAsc\": 890,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allkin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1200,\n      \"des\": 0,\n      \"tAsc\": 1200,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 0,\n      \"xH\": 500,\n      \"capH\": 1180,\n      \"yMin\": 0,\n      \"yMax\": 1180,\n      \"hAsc\": 1200,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allura\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 615,\n      \"xH\": 295,\n      \"capH\": 590,\n      \"yMin\": -612,\n      \"yMax\": 1101,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almarai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -211,\n      \"tAsc\": 905,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 1108,\n      \"wDes\": 453,\n      \"xH\": 514,\n      \"capH\": 716,\n      \"yMin\": -396,\n      \"yMax\": 1090,\n      \"hAsc\": 905,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -345,\n      \"tAsc\": 951,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 345,\n      \"xH\": 514,\n      \"capH\": 666,\n      \"yMin\": -227,\n      \"yMax\": 939,\n      \"hAsc\": 951,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -345,\n      \"tAsc\": 951,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 345,\n      \"xH\": 505,\n      \"capH\": 666,\n      \"yMin\": -233,\n      \"yMax\": 879,\n      \"hAsc\": 951,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 939,\n      \"des\": -251,\n      \"tAsc\": 939,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 939,\n      \"wDes\": 251,\n      \"xH\": 193,\n      \"capH\": 271,\n      \"yMin\": -219,\n      \"yMax\": 885,\n      \"hAsc\": 939,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -292,\n      \"yMax\": 829,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Collegiate One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -284,\n      \"yMax\": 908,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Inline One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -302,\n      \"yMax\": 891,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Pinstripe\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -286,\n      \"yMax\": 810,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -292,\n      \"yMax\": 829,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alyamama\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -530,\n      \"tAsc\": 900,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 1132,\n      \"wDes\": 530,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -468,\n      \"yMax\": 998,\n      \"hAsc\": 900,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amarante\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1010,\n      \"capH\": 1530,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amaranth\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -236,\n      \"tAsc\": 976,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 236,\n      \"xH\": 498,\n      \"capH\": 677,\n      \"yMin\": -223,\n      \"yMax\": 928,\n      \"hAsc\": 976,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amarna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -350,\n      \"tAsc\": 1025,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 350,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -331,\n      \"yMax\": 1000,\n      \"hAsc\": 1025,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amatic SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -245,\n      \"tAsc\": 1016,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 265,\n      \"xH\": 659,\n      \"capH\": 754,\n      \"yMin\": -234,\n      \"yMax\": 1093,\n      \"hAsc\": 1016,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amethysta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2022,\n      \"des\": -563,\n      \"tAsc\": 2022,\n      \"tDes\": -563,\n      \"tLGap\": 0,\n      \"wAsc\": 2022,\n      \"wDes\": 563,\n      \"xH\": 1024,\n      \"capH\": 1475,\n      \"yMin\": -563,\n      \"yMax\": 1952,\n      \"hAsc\": 2022,\n      \"hDes\": -563,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -406,\n      \"tAsc\": 928,\n      \"tDes\": -406,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 406,\n      \"xH\": 522,\n      \"capH\": 696,\n      \"yMin\": -406,\n      \"yMax\": 929,\n      \"hAsc\": 928,\n      \"hDes\": -406,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiri\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1124,\n      \"des\": -634,\n      \"tAsc\": 1124,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1850,\n      \"wDes\": 910,\n      \"xH\": 433,\n      \"capH\": 646,\n      \"yMin\": -900,\n      \"yMax\": 1815,\n      \"hAsc\": 1124,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiri Quran\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1815,\n      \"des\": -634,\n      \"tAsc\": 1815,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1864,\n      \"wDes\": 910,\n      \"xH\": 433,\n      \"capH\": 646,\n      \"yMin\": -835,\n      \"yMax\": 1864,\n      \"hAsc\": 1815,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amita\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1292,\n      \"des\": -650,\n      \"tAsc\": 1292,\n      \"tDes\": -650,\n      \"tLGap\": 0,\n      \"wAsc\": 1292,\n      \"wDes\": 650,\n      \"xH\": 495,\n      \"capH\": 720,\n      \"yMin\": -619,\n      \"yMax\": 1292,\n      \"hAsc\": 1292,\n      \"hDes\": -650,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anaheim\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1968,\n      \"des\": -672,\n      \"tAsc\": 1968,\n      \"tDes\": -672,\n      \"tLGap\": 0,\n      \"wAsc\": 2452,\n      \"wDes\": 723,\n      \"xH\": 985,\n      \"capH\": 1284,\n      \"yMin\": -467,\n      \"yMax\": 2166,\n      \"hAsc\": 1968,\n      \"hDes\": -672,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ancizar Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 851,\n      \"wDes\": 271,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -272,\n      \"yMax\": 858,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ancizar Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 904,\n      \"wDes\": 277,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -277,\n      \"yMax\": 902,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Andada Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -235,\n      \"tAsc\": 942,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 390,\n      \"xH\": 494,\n      \"capH\": 705,\n      \"yMin\": -382,\n      \"yMax\": 1068,\n      \"hAsc\": 942,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Andika\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -800,\n      \"tAsc\": 2500,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 800,\n      \"xH\": 1040,\n      \"capH\": 1485,\n      \"yMin\": -1148,\n      \"yMax\": 2620,\n      \"hAsc\": 2500,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Bangla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2500,\n      \"des\": -1232,\n      \"tAsc\": 2500,\n      \"tDes\": -1232,\n      \"tLGap\": 0,\n      \"wAsc\": 2659,\n      \"wDes\": 1232,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1118,\n      \"yMax\": 2214,\n      \"hAsc\": 2500,\n      \"hDes\": -1232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2026,\n      \"des\": -1385,\n      \"tAsc\": 2026,\n      \"tDes\": -1385,\n      \"tLGap\": 0,\n      \"wAsc\": 2026,\n      \"wDes\": 1385,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1036,\n      \"yMax\": 1936,\n      \"hAsc\": 2026,\n      \"hDes\": -1385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Gujarati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1975,\n      \"des\": -1064,\n      \"tAsc\": 1975,\n      \"tDes\": -1064,\n      \"tLGap\": 0,\n      \"wAsc\": 2217,\n      \"wDes\": 1344,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1054,\n      \"yMax\": 1956,\n      \"hAsc\": 1975,\n      \"hDes\": -1064,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Gurmukhi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1500,\n      \"des\": -900,\n      \"tAsc\": 1500,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 2120,\n      \"wDes\": 1376,\n      \"xH\": 494,\n      \"capH\": 660,\n      \"yMin\": -1093,\n      \"yMax\": 2024,\n      \"hAsc\": 1500,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Kannada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2030,\n      \"des\": -1310,\n      \"tAsc\": 2030,\n      \"tDes\": -1310,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 1320,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1098,\n      \"yMax\": 1858,\n      \"hAsc\": 2030,\n      \"hDes\": -1310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Latin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -400,\n      \"tAsc\": 1800,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2136,\n      \"wDes\": 550,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -465,\n      \"yMax\": 1994,\n      \"hAsc\": 1800,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Malayalam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2035,\n      \"des\": -830,\n      \"tAsc\": 2035,\n      \"tDes\": -830,\n      \"tLGap\": 0,\n      \"wAsc\": 2005,\n      \"wDes\": 1060,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -676,\n      \"yMax\": 1770,\n      \"hAsc\": 2035,\n      \"hDes\": -830,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Odia\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1960,\n      \"des\": -1400,\n      \"tAsc\": 1960,\n      \"tDes\": -1400,\n      \"tLGap\": 0,\n      \"wAsc\": 2161,\n      \"wDes\": 1982,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1923,\n      \"yMax\": 2131,\n      \"hAsc\": 1960,\n      \"hDes\": -1400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Tamil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1963,\n      \"des\": -853,\n      \"tAsc\": 1963,\n      \"tDes\": -853,\n      \"tLGap\": 0,\n      \"wAsc\": 1963,\n      \"wDes\": 853,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -835,\n      \"yMax\": 1913,\n      \"hAsc\": 1963,\n      \"hDes\": -853,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Telugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -1200,\n      \"tAsc\": 1800,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2286,\n      \"wDes\": 1942,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1761,\n      \"yMax\": 2120,\n      \"hAsc\": 1800,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Angkor\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1130,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1130,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Annapurna SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1939,\n      \"des\": -984,\n      \"tAsc\": 1939,\n      \"tDes\": -984,\n      \"tLGap\": 0,\n      \"wAsc\": 2879,\n      \"wDes\": 1033,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -1007,\n      \"yMax\": 2866,\n      \"hAsc\": 1939,\n      \"hDes\": -984,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Annie Use Your Telescope\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1049,\n      \"des\": -419,\n      \"tAsc\": 1049,\n      \"tDes\": -419,\n      \"tLGap\": 0,\n      \"wAsc\": 1049,\n      \"wDes\": 419,\n      \"xH\": 427,\n      \"capH\": 730,\n      \"yMin\": -419,\n      \"yMax\": 1049,\n      \"hAsc\": 1049,\n      \"hDes\": -419,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anonymous Pro\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1675,\n      \"des\": -373,\n      \"tAsc\": 1675,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 1675,\n      \"wDes\": 373,\n      \"xH\": 932,\n      \"capH\": 1305,\n      \"yMin\": -395,\n      \"yMax\": 1854,\n      \"hAsc\": 1675,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -534,\n      \"tAsc\": 1966,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 534,\n      \"xH\": 1049,\n      \"capH\": 1422,\n      \"yMin\": -534,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -251,\n      \"tAsc\": 940,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 251,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic Didone\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anton\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2409,\n      \"des\": -674,\n      \"tAsc\": 2409,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 2876,\n      \"wDes\": 674,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -667,\n      \"yMax\": 2874,\n      \"hAsc\": 2409,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anton SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2409,\n      \"des\": -674,\n      \"tAsc\": 2409,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 2876,\n      \"wDes\": 674,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -667,\n      \"yMax\": 2874,\n      \"hAsc\": 2409,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antonio\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2365,\n      \"des\": -285,\n      \"tAsc\": 2365,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 2365,\n      \"wDes\": 689,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -637,\n      \"yMax\": 2326,\n      \"hAsc\": 2365,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anuphan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1119,\n      \"wDes\": 324,\n      \"xH\": 570,\n      \"capH\": 698,\n      \"yMin\": -324,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anybody\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1590,\n      \"des\": -480,\n      \"tAsc\": 1590,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2190,\n      \"wDes\": 685,\n      \"xH\": 1186,\n      \"capH\": 1350,\n      \"yMin\": -505,\n      \"yMax\": 1896,\n      \"hAsc\": 1590,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aoboshi One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 460,\n      \"capH\": 750,\n      \"yMin\": -348,\n      \"yMax\": 993,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"AR One Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -300,\n      \"tAsc\": 1060,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 300,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -236,\n      \"yMax\": 1050,\n      \"hAsc\": 1060,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arapey\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 868,\n      \"des\": -228,\n      \"tAsc\": 868,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 868,\n      \"wDes\": 228,\n      \"xH\": 438,\n      \"capH\": 639,\n      \"yMin\": -228,\n      \"yMax\": 868,\n      \"hAsc\": 868,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arbutus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 234,\n      \"capH\": 103,\n      \"yMin\": -550,\n      \"yMax\": 2010,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arbutus Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 1014,\n      \"capH\": 1500,\n      \"yMin\": -550,\n      \"yMax\": 2010,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Architects Daughter\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -413,\n      \"tAsc\": 1010,\n      \"tDes\": -413,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 413,\n      \"xH\": 439,\n      \"capH\": 675,\n      \"yMin\": -431,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -413,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -210,\n      \"tAsc\": 878,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 410,\n      \"xH\": 526,\n      \"capH\": 686,\n      \"yMin\": -394,\n      \"yMax\": 1083,\n      \"hAsc\": 878,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo Black\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -210,\n      \"tAsc\": 878,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1035,\n      \"wDes\": 312,\n      \"xH\": 528,\n      \"capH\": 688,\n      \"yMin\": -267,\n      \"yMax\": 957,\n      \"hAsc\": 878,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -312,\n      \"tAsc\": 1035,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 303,\n      \"xH\": 526,\n      \"capH\": 686,\n      \"yMin\": -303,\n      \"yMax\": 1050,\n      \"hAsc\": 1035,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Are You Serious\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -320,\n      \"tAsc\": 880,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 601,\n      \"xH\": 300,\n      \"capH\": 660,\n      \"yMin\": -601,\n      \"yMax\": 931,\n      \"hAsc\": 880,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aref Ruqaa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1221,\n      \"des\": -244,\n      \"tAsc\": 1221,\n      \"tDes\": -244,\n      \"tLGap\": 98,\n      \"wAsc\": 1221,\n      \"wDes\": 439,\n      \"xH\": 462,\n      \"capH\": 683,\n      \"yMin\": -379,\n      \"yMax\": 1028,\n      \"hAsc\": 1221,\n      \"hDes\": -244,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Aref Ruqaa Ink\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1221,\n      \"des\": -244,\n      \"tAsc\": 1221,\n      \"tDes\": -244,\n      \"tLGap\": 98,\n      \"wAsc\": 1221,\n      \"wDes\": 439,\n      \"xH\": 462,\n      \"capH\": 683,\n      \"yMin\": -376,\n      \"yMax\": 1028,\n      \"hAsc\": 1221,\n      \"hDes\": -244,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Arial\",\n    \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -434,\n      \"tAsc\": 1491,\n      \"tDes\": -431,\n      \"tLGap\": 307,\n      \"wAsc\": 1854,\n      \"wDes\": 1854,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -665,\n      \"yMax\": 2060,\n      \"hAsc\": 1854,\n      \"hDes\": -434,\n      \"lGap\": 67\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arial Black\",\n    \"fallbacks\": [\"Arial Black\", \"Arial Bold\", \"Gadget\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2254,\n      \"des\": -634,\n      \"tAsc\": 1466,\n      \"tDes\": 434,\n      \"tLGap\": 291,\n      \"wAsc\": 2254,\n      \"wDes\": 2254,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -628,\n      \"yMax\": 2219,\n      \"hAsc\": 2254,\n      \"hDes\": -634,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arial Narrow\",\n    \"fallbacks\": [\"Arial\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1916,\n      \"des\": -434,\n      \"tAsc\": 1491,\n      \"tDes\": -431,\n      \"tLGap\": 269,\n      \"wAsc\": 1888,\n      \"wDes\": 1888,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -628,\n      \"yMax\": 2224,\n      \"hAsc\": 1916,\n      \"hDes\": -434,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arima\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1073,\n      \"des\": -560,\n      \"tAsc\": 1073,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 1073,\n      \"wDes\": 560,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -535,\n      \"yMax\": 1024,\n      \"hAsc\": 1073,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arimo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -434,\n      \"tAsc\": 1854,\n      \"tDes\": -434,\n      \"tLGap\": 67,\n      \"wAsc\": 2136,\n      \"wDes\": 797,\n      \"xH\": 1082,\n      \"capH\": 1409,\n      \"yMin\": -797,\n      \"yMax\": 2136,\n      \"hAsc\": 1854,\n      \"hDes\": -434,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Arizonia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 355,\n      \"xH\": 280,\n      \"capH\": 660,\n      \"yMin\": -354,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Armata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1190,\n      \"capH\": 1530,\n      \"yMin\": -560,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arsenal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -254,\n      \"tAsc\": 1000,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 339,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -288,\n      \"yMax\": 1012,\n      \"hAsc\": 1000,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arsenal SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -254,\n      \"tAsc\": 1000,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 339,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -288,\n      \"yMax\": 1012,\n      \"hAsc\": 1000,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Artifika\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -508,\n      \"tAsc\": 1984,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 1984,\n      \"wDes\": 508,\n      \"xH\": 1045,\n      \"capH\": 1433,\n      \"yMin\": -508,\n      \"yMax\": 1984,\n      \"hAsc\": 1984,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arvo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1968,\n      \"des\": -506,\n      \"tAsc\": 1556,\n      \"tDes\": -471,\n      \"tLGap\": 110,\n      \"wAsc\": 1968,\n      \"wDes\": 506,\n      \"xH\": 1036,\n      \"capH\": 1516,\n      \"yMin\": -506,\n      \"yMax\": 1969,\n      \"hAsc\": 1968,\n      \"hDes\": -506,\n      \"lGap\": 55\n    }\n  },\n  {\n    \"family\": \"Arya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1265,\n      \"des\": -544,\n      \"tAsc\": 1265,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1265,\n      \"wDes\": 544,\n      \"xH\": 392,\n      \"capH\": 579,\n      \"yMin\": -544,\n      \"yMax\": 1265,\n      \"hAsc\": 1265,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asap\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -212,\n      \"tAsc\": 934,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 264,\n      \"xH\": 523,\n      \"capH\": 700,\n      \"yMin\": -225,\n      \"yMax\": 1044,\n      \"hAsc\": 934,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asap Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -212,\n      \"tAsc\": 934,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 264,\n      \"xH\": 523,\n      \"capH\": 700,\n      \"yMin\": -225,\n      \"yMax\": 1044,\n      \"hAsc\": 934,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1196,\n      \"des\": -557,\n      \"tAsc\": 1196,\n      \"tDes\": -557,\n      \"tLGap\": 0,\n      \"wAsc\": 1196,\n      \"wDes\": 557,\n      \"xH\": 484,\n      \"capH\": 680,\n      \"yMin\": -555,\n      \"yMax\": 1194,\n      \"hAsc\": 1196,\n      \"hDes\": -557,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asimovian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 342,\n      \"xH\": 535,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 1131,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asset\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1971,\n      \"des\": -589,\n      \"tAsc\": 1971,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 2449,\n      \"wDes\": 888,\n      \"xH\": 1047,\n      \"capH\": 1291,\n      \"yMin\": -888,\n      \"yMax\": 2449,\n      \"hAsc\": 1971,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Assistant\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1021,\n      \"des\": -287,\n      \"tAsc\": 1021,\n      \"tDes\": -287,\n      \"tLGap\": 200,\n      \"wAsc\": 1021,\n      \"wDes\": 287,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -259,\n      \"yMax\": 1021,\n      \"hAsc\": 1021,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asta Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -241,\n      \"tAsc\": 952,\n      \"tDes\": -241,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 241,\n      \"xH\": 505,\n      \"capH\": 707,\n      \"yMin\": -241,\n      \"yMax\": 959,\n      \"hAsc\": 952,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Astloch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1948,\n      \"des\": -526,\n      \"tAsc\": 1696,\n      \"tDes\": -352,\n      \"tLGap\": 106,\n      \"wAsc\": 1948,\n      \"wDes\": 526,\n      \"xH\": 1200,\n      \"capH\": 1567,\n      \"yMin\": -376,\n      \"yMax\": 1934,\n      \"hAsc\": 1948,\n      \"hDes\": -526,\n      \"lGap\": 53\n    }\n  },\n  {\n    \"family\": \"Asul\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 949,\n      \"des\": -264,\n      \"tAsc\": 949,\n      \"tDes\": -264,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 264,\n      \"xH\": 488,\n      \"capH\": 703,\n      \"yMin\": -264,\n      \"yMax\": 949,\n      \"hAsc\": 949,\n      \"hDes\": -264,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Athiti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -450,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 450,\n      \"xH\": 468,\n      \"capH\": 614,\n      \"yMin\": -437,\n      \"yMax\": 1080,\n      \"hAsc\": 1150,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -290,\n      \"tAsc\": 950,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 290,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -250,\n      \"yMax\": 888,\n      \"hAsc\": 950,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -316,\n      \"tAsc\": 984,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 411,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -237,\n      \"yMax\": 892,\n      \"hAsc\": 984,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible Next\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -316,\n      \"tAsc\": 984,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 411,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -250,\n      \"yMax\": 903,\n      \"hAsc\": 984,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atma\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1101,\n      \"des\": -518,\n      \"tAsc\": 1101,\n      \"tDes\": -518,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 518,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -441,\n      \"yMax\": 990,\n      \"hAsc\": 1101,\n      \"hDes\": -518,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atomic Age\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2091,\n      \"des\": -656,\n      \"tAsc\": 2091,\n      \"tDes\": -656,\n      \"tLGap\": 0,\n      \"wAsc\": 2091,\n      \"wDes\": 656,\n      \"xH\": 1047,\n      \"capH\": 1516,\n      \"yMin\": -656,\n      \"yMax\": 2091,\n      \"hAsc\": 2091,\n      \"hDes\": -656,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aubrey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -212,\n      \"tAsc\": 830,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 830,\n      \"wDes\": 211,\n      \"xH\": 450,\n      \"capH\": 616,\n      \"yMin\": -211,\n      \"yMax\": 830,\n      \"hAsc\": 830,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Audiowide\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2027,\n      \"des\": -584,\n      \"tAsc\": 2027,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2027,\n      \"wDes\": 584,\n      \"xH\": 1083,\n      \"capH\": 1434,\n      \"yMin\": -584,\n      \"yMax\": 2027,\n      \"hAsc\": 2027,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Autour One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 1190,\n      \"capH\": 1561,\n      \"yMin\": -550,\n      \"yMax\": 2012,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Average\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -263,\n      \"tAsc\": 953,\n      \"tDes\": -263,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 265,\n      \"xH\": 456,\n      \"capH\": 691,\n      \"yMin\": -265,\n      \"yMax\": 1077,\n      \"hAsc\": 953,\n      \"hDes\": -263,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Average Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1027,\n      \"des\": -269,\n      \"tAsc\": 1027,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 1027,\n      \"wDes\": 269,\n      \"xH\": 456,\n      \"capH\": 691,\n      \"yMin\": -269,\n      \"yMax\": 1027,\n      \"hAsc\": 1027,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Gruesa Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1952,\n      \"des\": -492,\n      \"tAsc\": 1952,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1952,\n      \"wDes\": 492,\n      \"yMin\": -460,\n      \"yMax\": 1884,\n      \"hAsc\": 1952,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1952,\n      \"des\": -492,\n      \"tAsc\": 1952,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1952,\n      \"wDes\": 492,\n      \"yMin\": -458,\n      \"yMax\": 1891,\n      \"hAsc\": 1952,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Sans Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2035,\n      \"des\": -499,\n      \"tAsc\": 2035,\n      \"tDes\": -499,\n      \"tLGap\": 0,\n      \"wAsc\": 2035,\n      \"wDes\": 499,\n      \"yMin\": -467,\n      \"yMax\": 1954,\n      \"hAsc\": 2035,\n      \"hDes\": -499,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Serif Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1828,\n      \"des\": -465,\n      \"tAsc\": 1622,\n      \"tDes\": -426,\n      \"tLGap\": 184,\n      \"wAsc\": 1828,\n      \"wDes\": 465,\n      \"yMin\": -465,\n      \"yMax\": 1828,\n      \"hAsc\": 1828,\n      \"hDes\": -465,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Azeret Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -230,\n      \"tAsc\": 937,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 230,\n      \"xH\": 544,\n      \"capH\": 698,\n      \"yMin\": -221,\n      \"yMax\": 1106,\n      \"hAsc\": 937,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"B612\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1934,\n      \"wDes\": 712,\n      \"xH\": 1100,\n      \"capH\": 1500,\n      \"yMin\": -710,\n      \"yMax\": 1920,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"B612 Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 712,\n      \"xH\": 1100,\n      \"capH\": 1500,\n      \"yMin\": -710,\n      \"yMax\": 1924,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Babylonica\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -450,\n      \"tAsc\": 875,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 672,\n      \"xH\": 220,\n      \"capH\": 630,\n      \"yMin\": -671,\n      \"yMax\": 948,\n      \"hAsc\": 875,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bacasime Antique\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1536,\n      \"des\": -512,\n      \"tAsc\": 1408,\n      \"tDes\": -366,\n      \"tLGap\": 417,\n      \"wAsc\": 1805,\n      \"wDes\": 531,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -413,\n      \"yMax\": 1557,\n      \"hAsc\": 1536,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bad Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -648,\n      \"tAsc\": 1324,\n      \"tDes\": -648,\n      \"tLGap\": 0,\n      \"wAsc\": 1455,\n      \"wDes\": 648,\n      \"xH\": 505,\n      \"capH\": 960,\n      \"yMin\": -648,\n      \"yMax\": 1455,\n      \"hAsc\": 1324,\n      \"hDes\": -648,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Badeen Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -250,\n      \"tAsc\": 1150,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 300,\n      \"xH\": 600,\n      \"capH\": 700,\n      \"yMin\": -300,\n      \"yMax\": 959,\n      \"hAsc\": 1150,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bagel Fat One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 523,\n      \"capH\": 726,\n      \"yMin\": -220,\n      \"yMax\": 1005,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bahiana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 250,\n      \"xH\": 492,\n      \"capH\": 710,\n      \"yMin\": -250,\n      \"yMax\": 900,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bahianita\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -238,\n      \"tAsc\": 962,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 1007,\n      \"wDes\": 330,\n      \"xH\": 582,\n      \"capH\": 710,\n      \"yMin\": -330,\n      \"yMax\": 1007,\n      \"hAsc\": 962,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bai Jamjuree\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1225,\n      \"wDes\": 561,\n      \"xH\": 499,\n      \"capH\": 700,\n      \"yMin\": -488,\n      \"yMax\": 1206,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bakbak One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 602,\n      \"xH\": 500,\n      \"capH\": 607,\n      \"yMin\": -602,\n      \"yMax\": 970,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ballet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -770,\n      \"tAsc\": 1130,\n      \"tDes\": -770,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 920,\n      \"xH\": 339,\n      \"capH\": 1209,\n      \"yMin\": -913,\n      \"yMax\": 1152,\n      \"hAsc\": 1130,\n      \"hDes\": -770,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -524,\n      \"tAsc\": 1078,\n      \"tDes\": -524,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 524,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -470,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -524,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhai 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -544,\n      \"tAsc\": 1078,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 544,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -459,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhaijaan 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1080,\n      \"des\": -632,\n      \"tAsc\": 1080,\n      \"tDes\": -632,\n      \"tLGap\": 0,\n      \"wAsc\": 1080,\n      \"wDes\": 632,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -533,\n      \"yMax\": 1017,\n      \"hAsc\": 1080,\n      \"hDes\": -632,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhaina 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1185,\n      \"des\": -827,\n      \"tAsc\": 1185,\n      \"tDes\": -827,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 827,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -721,\n      \"yMax\": 1023,\n      \"hAsc\": 1185,\n      \"hDes\": -827,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Chettan 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -392,\n      \"tAsc\": 1078,\n      \"tDes\": -392,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 390,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -349,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -392,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Da 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -589,\n      \"tAsc\": 1095,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 589,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -579,\n      \"yMax\": 1029,\n      \"hAsc\": 1095,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Paaji 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1157,\n      \"des\": -614,\n      \"tAsc\": 1157,\n      \"tDes\": -614,\n      \"tLGap\": 0,\n      \"wAsc\": 1157,\n      \"wDes\": 614,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -523,\n      \"yMax\": 1018,\n      \"hAsc\": 1157,\n      \"hDes\": -614,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Tamma 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -673,\n      \"tAsc\": 1078,\n      \"tDes\": -673,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 757,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -739,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -673,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Tammudu 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1177,\n      \"des\": -1119,\n      \"tAsc\": 1177,\n      \"tDes\": -1119,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 1065,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -1065,\n      \"yMax\": 1071,\n      \"hAsc\": 1177,\n      \"hDes\": -1119,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Thambi 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -486,\n      \"tAsc\": 1078,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 486,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -432,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Balsamiq Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1220,\n      \"wDes\": 420,\n      \"xH\": 520,\n      \"capH\": 715,\n      \"yMin\": -347,\n      \"yMax\": 1136,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Balthazar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 796,\n      \"des\": -222,\n      \"tAsc\": 796,\n      \"tDes\": -222,\n      \"tLGap\": 0,\n      \"wAsc\": 796,\n      \"wDes\": 222,\n      \"xH\": 399,\n      \"capH\": 605,\n      \"yMin\": -222,\n      \"yMax\": 796,\n      \"hAsc\": 796,\n      \"hDes\": -222,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bangers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 883,\n      \"des\": -181,\n      \"tAsc\": 883,\n      \"tDes\": -181,\n      \"tLGap\": 0,\n      \"wAsc\": 1401,\n      \"wDes\": 356,\n      \"xH\": 721,\n      \"capH\": 721,\n      \"yMin\": -356,\n      \"yMax\": 1392,\n      \"hAsc\": 883,\n      \"hDes\": -181,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 249,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -209,\n      \"yMax\": 1084,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 274,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -209,\n      \"yMax\": 1074,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1089,\n      \"wDes\": 261,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -212,\n      \"yMax\": 1079,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barriecito\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -238,\n      \"tAsc\": 962,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 1041,\n      \"wDes\": 346,\n      \"xH\": 582,\n      \"capH\": 710,\n      \"yMin\": -346,\n      \"yMax\": 1041,\n      \"hAsc\": 962,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barrio\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -247,\n      \"tAsc\": 880,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 880,\n      \"wDes\": 247,\n      \"xH\": 492,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 880,\n      \"hAsc\": 880,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Basic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -511,\n      \"tAsc\": 2066,\n      \"tDes\": -511,\n      \"tLGap\": 0,\n      \"wAsc\": 2066,\n      \"wDes\": 511,\n      \"xH\": 1022,\n      \"capH\": 1358,\n      \"yMin\": -507,\n      \"yMax\": 1960,\n      \"hAsc\": 2066,\n      \"hDes\": -511,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baskerville\",\n    \"fallbacks\": [\n      \"Baskerville Old Face\",\n      \"Hoefler Text\",\n      \"Garamond\",\n      \"Times New Roman\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1839,\n      \"des\": -504,\n      \"tAsc\": 1376,\n      \"tDes\": -504,\n      \"tLGap\": 311,\n      \"wAsc\": 1839,\n      \"wDes\": 1839,\n      \"xH\": 819,\n      \"capH\": 1356,\n      \"yMin\": -504,\n      \"yMax\": 1869,\n      \"hAsc\": 1839,\n      \"hDes\": -504,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Baskervville\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -295,\n      \"tAsc\": 998,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 300,\n      \"xH\": 436,\n      \"capH\": 710,\n      \"yMin\": -300,\n      \"yMax\": 1150,\n      \"hAsc\": 998,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baskervville SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -295,\n      \"tAsc\": 998,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 300,\n      \"xH\": 436,\n      \"capH\": 710,\n      \"yMin\": -300,\n      \"yMax\": 1150,\n      \"hAsc\": 998,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Battambang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2197,\n      \"wDes\": 1051,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1050,\n      \"yMax\": 2181,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baumans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -240,\n      \"tAsc\": 942,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 240,\n      \"xH\": 480,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bayon\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Bartle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -201,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Bogle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Hegarty\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Be Vietnam Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -265,\n      \"tAsc\": 1000,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1261,\n      \"wDes\": 265,\n      \"xH\": 530,\n      \"capH\": 740,\n      \"yMin\": -263,\n      \"yMax\": 1199,\n      \"hAsc\": 1000,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beau Rivage\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -400,\n      \"tAsc\": 940,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 445,\n      \"xH\": 350,\n      \"capH\": 700,\n      \"yMin\": -441,\n      \"yMax\": 1116,\n      \"hAsc\": 940,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bebas Neue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 350,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 912,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beiruti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 936,\n      \"wDes\": 450,\n      \"xH\": 390,\n      \"capH\": 605,\n      \"yMin\": -449,\n      \"yMax\": 921,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belanosima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1835,\n      \"des\": -416,\n      \"tAsc\": 1835,\n      \"tDes\": -416,\n      \"tLGap\": 190,\n      \"wAsc\": 1827,\n      \"wDes\": 416,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -504,\n      \"yMax\": 1938,\n      \"hAsc\": 1835,\n      \"hDes\": -416,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belgrano\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -278,\n      \"tAsc\": 990,\n      \"tDes\": -278,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 278,\n      \"xH\": 499,\n      \"capH\": 706,\n      \"yMin\": -279,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -278,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellefair\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -277,\n      \"tAsc\": 869,\n      \"tDes\": -277,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 277,\n      \"xH\": 364,\n      \"capH\": 688,\n      \"yMin\": -277,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -277,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belleza\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -224,\n      \"tAsc\": 928,\n      \"tDes\": -224,\n      \"tLGap\": 0,\n      \"wAsc\": 1171,\n      \"wDes\": 312,\n      \"xH\": 452,\n      \"capH\": 662,\n      \"yMin\": -312,\n      \"yMax\": 1171,\n      \"hAsc\": 928,\n      \"hDes\": -224,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellota\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -290,\n      \"tAsc\": 968,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 325,\n      \"xH\": 500,\n      \"capH\": 684,\n      \"yMin\": -317,\n      \"yMax\": 1147,\n      \"hAsc\": 968,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellota Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -290,\n      \"tAsc\": 968,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 325,\n      \"xH\": 500,\n      \"capH\": 684,\n      \"yMin\": -317,\n      \"yMax\": 1147,\n      \"hAsc\": 968,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BenchNine\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -720,\n      \"tAsc\": 2020,\n      \"tDes\": -720,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 720,\n      \"xH\": 1006,\n      \"capH\": 1438,\n      \"yMin\": -683,\n      \"yMax\": 2018,\n      \"hAsc\": 2020,\n      \"hDes\": -720,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Benne\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 630,\n      \"des\": -370,\n      \"tAsc\": 630,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 742,\n      \"xH\": 404,\n      \"capH\": 655,\n      \"yMin\": -742,\n      \"yMax\": 1105,\n      \"hAsc\": 630,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bentham\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 879,\n      \"des\": -260,\n      \"tAsc\": 768,\n      \"tDes\": -256,\n      \"tLGap\": 92,\n      \"wAsc\": 879,\n      \"wDes\": 260,\n      \"yMin\": -260,\n      \"yMax\": 878,\n      \"hAsc\": 879,\n      \"hDes\": -260,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Berkshire Swash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2007,\n      \"des\": -537,\n      \"tAsc\": 2007,\n      \"tDes\": -537,\n      \"tLGap\": 0,\n      \"wAsc\": 2007,\n      \"wDes\": 537,\n      \"xH\": 1038,\n      \"capH\": 1858,\n      \"yMin\": -537,\n      \"yMax\": 2007,\n      \"hAsc\": 2007,\n      \"hDes\": -537,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Besley\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2500,\n      \"des\": -850,\n      \"tAsc\": 2500,\n      \"tDes\": -850,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 850,\n      \"xH\": 1040,\n      \"capH\": 1500,\n      \"yMin\": -623,\n      \"yMax\": 2159,\n      \"hAsc\": 2500,\n      \"hDes\": -850,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1048,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos GDL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos In\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos In GDL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beth Ellen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 3250,\n      \"des\": -1190,\n      \"tAsc\": 3250,\n      \"tDes\": -1190,\n      \"tLGap\": 0,\n      \"wAsc\": 3224,\n      \"wDes\": 946,\n      \"xH\": 1208,\n      \"capH\": 2248,\n      \"yMin\": -946,\n      \"yMax\": 3224,\n      \"hAsc\": 3250,\n      \"hDes\": -1190,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bevan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2366,\n      \"des\": -925,\n      \"tAsc\": 2366,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 2689,\n      \"wDes\": 870,\n      \"xH\": 1072,\n      \"capH\": 1592,\n      \"yMin\": -705,\n      \"yMax\": 2470,\n      \"hAsc\": 2366,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BhuTuka Expanded One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 826,\n      \"des\": -182,\n      \"tAsc\": 826,\n      \"tDes\": -182,\n      \"tLGap\": 0,\n      \"wAsc\": 844,\n      \"wDes\": 464,\n      \"xH\": 357,\n      \"capH\": 520,\n      \"yMin\": -464,\n      \"yMax\": 844,\n      \"hAsc\": 826,\n      \"hDes\": -182,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1971,\n      \"des\": -429,\n      \"tAsc\": 1971,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 2614,\n      \"wDes\": 730,\n      \"xH\": 1200,\n      \"capH\": 1600,\n      \"yMin\": -417,\n      \"yMax\": 2310,\n      \"hAsc\": 1971,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4000,\n      \"asc\": 3942,\n      \"des\": -858,\n      \"tAsc\": 3942,\n      \"tDes\": -858,\n      \"tLGap\": 0,\n      \"wAsc\": 5228,\n      \"wDes\": 1460,\n      \"xH\": 2400,\n      \"capH\": 3200,\n      \"yMin\": -860,\n      \"yMax\": 4688,\n      \"hAsc\": 3942,\n      \"hDes\": -858,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1971,\n      \"des\": -429,\n      \"tAsc\": 1971,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 2614,\n      \"wDes\": 730,\n      \"xH\": 1200,\n      \"capH\": 1600,\n      \"yMin\": -415,\n      \"yMax\": 2310,\n      \"hAsc\": 1971,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bigelow Rules\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1857,\n      \"des\": -516,\n      \"tAsc\": 1857,\n      \"tDes\": -516,\n      \"tLGap\": 0,\n      \"wAsc\": 1857,\n      \"wDes\": 516,\n      \"xH\": 1227,\n      \"capH\": 1528,\n      \"yMin\": -516,\n      \"yMax\": 1857,\n      \"hAsc\": 1857,\n      \"hDes\": -516,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bigshot One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -179,\n      \"tAsc\": 869,\n      \"tDes\": -179,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 179,\n      \"xH\": 449,\n      \"capH\": 615,\n      \"yMin\": -179,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -179,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bilbo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 630,\n      \"xH\": 375,\n      \"capH\": 650,\n      \"yMin\": -627,\n      \"yMax\": 1024,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bilbo Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 400,\n      \"xH\": 327,\n      \"capH\": 542,\n      \"yMin\": -400,\n      \"yMax\": 850,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BioRhyme\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1127,\n      \"des\": -422,\n      \"tAsc\": 1127,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1127,\n      \"wDes\": 422,\n      \"xH\": 471,\n      \"capH\": 686,\n      \"yMin\": -370,\n      \"yMax\": 1117,\n      \"hAsc\": 1127,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BioRhyme Expanded\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1127,\n      \"des\": -422,\n      \"tAsc\": 1127,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1127,\n      \"wDes\": 422,\n      \"xH\": 471,\n      \"capH\": 686,\n      \"yMin\": -398,\n      \"yMax\": 1120,\n      \"hAsc\": 1127,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Birthstone\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 685,\n      \"xH\": 320,\n      \"capH\": 880,\n      \"yMin\": -648,\n      \"yMax\": 1052,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Birthstone Bounce\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 685,\n      \"xH\": 390,\n      \"capH\": 700,\n      \"yMin\": -643,\n      \"yMax\": 1046,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Biryani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1109,\n      \"des\": -656,\n      \"tAsc\": 1109,\n      \"tDes\": -656,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 656,\n      \"xH\": 563,\n      \"capH\": 758,\n      \"yMin\": -592,\n      \"yMax\": 1109,\n      \"hAsc\": 1109,\n      \"hDes\": -656,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Double\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Double Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Double\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Double Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitter\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1255,\n      \"wDes\": 376,\n      \"xH\": 528,\n      \"capH\": 698,\n      \"yMin\": -275,\n      \"yMax\": 1073,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDGothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -246,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDMincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -262,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDPGothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -246,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDPMincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -262,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BJCree\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2080,\n      \"des\": -400,\n      \"tAsc\": 2080,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2080,\n      \"wDes\": 450,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -450,\n      \"yMax\": 2000,\n      \"hAsc\": 2080,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Black And White Picture\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 297,\n      \"xH\": 442,\n      \"capH\": 648,\n      \"yMin\": -297,\n      \"yMax\": 802,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Black Han Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 250,\n      \"wAsc\": 810,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -198,\n      \"yMax\": 810,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Black Ops One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1871,\n      \"des\": -689,\n      \"tAsc\": 1871,\n      \"tDes\": -689,\n      \"tLGap\": 0,\n      \"wAsc\": 2232,\n      \"wDes\": 689,\n      \"xH\": 1062,\n      \"capH\": 1327,\n      \"yMin\": -638,\n      \"yMax\": 2232,\n      \"hAsc\": 1871,\n      \"hDes\": -689,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka Hollow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blinker\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 240,\n      \"xH\": 494,\n      \"capH\": 627,\n      \"yMin\": -223,\n      \"yMax\": 838,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bodoni Moda\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2250,\n      \"des\": -800,\n      \"tAsc\": 2250,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 800,\n      \"xH\": 920,\n      \"capH\": 1500,\n      \"yMin\": -627,\n      \"yMax\": 2095,\n      \"hAsc\": 2250,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bodoni Moda SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2250,\n      \"des\": -800,\n      \"tAsc\": 2250,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 800,\n      \"xH\": 920,\n      \"capH\": 1500,\n      \"yMin\": -627,\n      \"yMax\": 2095,\n      \"hAsc\": 2250,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bokor\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2594,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2594,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Boldonse\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1520,\n      \"des\": -400,\n      \"tAsc\": 1520,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1600,\n      \"wDes\": 458,\n      \"xH\": 870,\n      \"capH\": 1190,\n      \"yMin\": -458,\n      \"yMax\": 1600,\n      \"hAsc\": 1520,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bona Nova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -268,\n      \"tAsc\": 932,\n      \"tDes\": -268,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 500,\n      \"xH\": 440,\n      \"capH\": 665,\n      \"yMin\": -456,\n      \"yMax\": 1090,\n      \"hAsc\": 932,\n      \"hDes\": -268,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bona Nova SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -268,\n      \"tAsc\": 932,\n      \"tDes\": -268,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 500,\n      \"xH\": 440,\n      \"capH\": 665,\n      \"yMin\": -456,\n      \"yMax\": 1090,\n      \"hAsc\": 932,\n      \"hDes\": -268,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bonbon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 845,\n      \"des\": -330,\n      \"tAsc\": 845,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 845,\n      \"wDes\": 330,\n      \"xH\": 504,\n      \"capH\": 644,\n      \"yMin\": -330,\n      \"yMax\": 845,\n      \"hAsc\": 845,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bonheur Royale\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 780,\n      \"des\": -380,\n      \"tAsc\": 780,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 440,\n      \"xH\": 280,\n      \"capH\": 620,\n      \"yMin\": -440,\n      \"yMax\": 923,\n      \"hAsc\": 780,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Boogaloo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 943,\n      \"des\": -246,\n      \"tAsc\": 943,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 943,\n      \"wDes\": 246,\n      \"xH\": 338,\n      \"capH\": 469,\n      \"yMin\": -246,\n      \"yMax\": 943,\n      \"hAsc\": 943,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Borel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -1014,\n      \"tAsc\": 986,\n      \"tDes\": -1014,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1014,\n      \"xH\": 472,\n      \"capH\": 722,\n      \"yMin\": -514,\n      \"yMax\": 1203,\n      \"hAsc\": 986,\n      \"hDes\": -1014,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bowlby One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2276,\n      \"des\": -932,\n      \"tAsc\": 2276,\n      \"tDes\": -932,\n      \"tLGap\": 0,\n      \"wAsc\": 2276,\n      \"wDes\": 932,\n      \"xH\": 1196,\n      \"capH\": 1520,\n      \"yMin\": -932,\n      \"yMax\": 2276,\n      \"hAsc\": 2276,\n      \"hDes\": -932,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bowlby One SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2248,\n      \"des\": -876,\n      \"tAsc\": 2248,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 2248,\n      \"wDes\": 876,\n      \"xH\": 1392,\n      \"capH\": 1520,\n      \"yMin\": -876,\n      \"yMax\": 2248,\n      \"hAsc\": 2248,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Huninn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 273,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -242,\n      \"yMax\": 1008,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Iansui\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 273,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -202,\n      \"yMax\": 1048,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Zihi Kai Std\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 278,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -278,\n      \"yMax\": 2042,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Braah One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -382,\n      \"tAsc\": 1018,\n      \"tDes\": -382,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 650,\n      \"xH\": 512,\n      \"capH\": 636,\n      \"yMin\": -619,\n      \"yMax\": 1120,\n      \"hAsc\": 1018,\n      \"hDes\": -382,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Brawler\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 971,\n      \"des\": -248,\n      \"tAsc\": 971,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 275,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 971,\n      \"hAsc\": 971,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bree Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -281,\n      \"tAsc\": 1077,\n      \"tDes\": -281,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 281,\n      \"xH\": 503,\n      \"capH\": 665,\n      \"yMin\": -281,\n      \"yMax\": 1077,\n      \"hAsc\": 1077,\n      \"hDes\": -281,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bricolage Grotesque\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -270,\n      \"tAsc\": 930,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 400,\n      \"xH\": 517,\n      \"capH\": 660,\n      \"yMin\": -343,\n      \"yMax\": 1137,\n      \"hAsc\": 930,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bruno Ace\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -253,\n      \"tAsc\": 953,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 253,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bruno Ace SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -253,\n      \"tAsc\": 953,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 253,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 908,\n      \"hAsc\": 953,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Brush Script MT\",\n    \"fallbacks\": [\"cursive\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -692,\n      \"tAsc\": 1229,\n      \"tDes\": -506,\n      \"tLGap\": 456,\n      \"wAsc\": 1820,\n      \"wDes\": 1820,\n      \"yMin\": -692,\n      \"yMax\": 1983,\n      \"hAsc\": 1820,\n      \"hDes\": -692,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Brygada 1918\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -250,\n      \"tAsc\": 920,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 440,\n      \"xH\": 460,\n      \"capH\": 670,\n      \"yMin\": -436,\n      \"yMax\": 1049,\n      \"hAsc\": 920,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bubblegum Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 852,\n      \"des\": -311,\n      \"tAsc\": 852,\n      \"tDes\": -311,\n      \"tLGap\": 0,\n      \"wAsc\": 852,\n      \"wDes\": 311,\n      \"xH\": 410,\n      \"capH\": 470,\n      \"yMin\": -311,\n      \"yMax\": 852,\n      \"hAsc\": 852,\n      \"hDes\": -311,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bubbler One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -263,\n      \"tAsc\": 900,\n      \"tDes\": -263,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 263,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 900,\n      \"hAsc\": 900,\n      \"hDes\": -263,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Buda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300],\n    \"styles\": [],\n    \"variants\": [[0, 300]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1836,\n      \"des\": -724,\n      \"tAsc\": 1519,\n      \"tDes\": -529,\n      \"tLGap\": 512,\n      \"wAsc\": 1836,\n      \"wDes\": 724,\n      \"yMin\": -446,\n      \"yMax\": 1862,\n      \"hAsc\": 1836,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Buenard\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1031,\n      \"des\": -270,\n      \"tAsc\": 1031,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 1009,\n      \"hAsc\": 1031,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Hairline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 894,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -894,\n      \"yMax\": 1614,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -924,\n      \"yMax\": 1644,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Shade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Spice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Tint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Butcherman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2600,\n      \"des\": -1363,\n      \"tAsc\": 2600,\n      \"tDes\": -1363,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 1363,\n      \"xH\": 1521,\n      \"capH\": 1509,\n      \"yMin\": -1363,\n      \"yMax\": 2600,\n      \"hAsc\": 2600,\n      \"hDes\": -1363,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Butterfly Kids\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 917,\n      \"des\": -304,\n      \"tAsc\": 917,\n      \"tDes\": -304,\n      \"tLGap\": 0,\n      \"wAsc\": 917,\n      \"wDes\": 304,\n      \"xH\": 338,\n      \"capH\": 802,\n      \"yMin\": -304,\n      \"yMax\": 917,\n      \"hAsc\": 917,\n      \"hDes\": -304,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bytesized\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 16,\n      \"asc\": 12,\n      \"des\": -8,\n      \"tAsc\": 12,\n      \"tDes\": -8,\n      \"tLGap\": 0,\n      \"wAsc\": 10,\n      \"wDes\": 6,\n      \"xH\": 8,\n      \"capH\": 11,\n      \"yMin\": -6,\n      \"yMax\": 10,\n      \"hAsc\": 12,\n      \"hDes\": -8,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 630,\n      \"xH\": 980,\n      \"capH\": 1400,\n      \"yMin\": -608,\n      \"yMax\": 2276,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -250,\n      \"tAsc\": 965,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 314,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -284,\n      \"yMax\": 1124,\n      \"hAsc\": 965,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin Sketch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -298,\n      \"tAsc\": 873,\n      \"tDes\": -298,\n      \"tLGap\": 0,\n      \"wAsc\": 873,\n      \"wDes\": 298,\n      \"xH\": 505,\n      \"capH\": 652,\n      \"yMin\": -249,\n      \"yMax\": 865,\n      \"hAsc\": 873,\n      \"hDes\": -298,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cactus Classical Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -229,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 229,\n      \"xH\": 501,\n      \"capH\": 761,\n      \"yMin\": -545,\n      \"yMax\": 2017,\n      \"hAsc\": 995,\n      \"hDes\": -229,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caesar Dressing\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1017,\n      \"des\": -226,\n      \"tAsc\": 1017,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 231,\n      \"xH\": 772,\n      \"capH\": 773,\n      \"yMin\": -226,\n      \"yMax\": 1017,\n      \"hAsc\": 1017,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cagliostro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -355,\n      \"tAsc\": 998,\n      \"tDes\": -355,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 355,\n      \"xH\": 444,\n      \"capH\": 700,\n      \"yMin\": -355,\n      \"yMax\": 998,\n      \"hAsc\": 998,\n      \"hDes\": -355,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cairo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -571,\n      \"tAsc\": 1303,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1312,\n      \"wDes\": 571,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -430,\n      \"yMax\": 1084,\n      \"hAsc\": 1303,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cairo Play\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -571,\n      \"tAsc\": 1303,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1312,\n      \"wDes\": 571,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -430,\n      \"yMax\": 1084,\n      \"hAsc\": 1303,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cal Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 222,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -221,\n      \"yMax\": 1139,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caladea\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 250,\n      \"xH\": 467,\n      \"capH\": 667,\n      \"yMin\": -222,\n      \"yMax\": 936,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Calistoga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 400,\n      \"xH\": 530,\n      \"capH\": 698,\n      \"yMin\": -396,\n      \"yMax\": 1199,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Calligraffitti\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 986,\n      \"des\": -607,\n      \"tAsc\": 866,\n      \"tDes\": -457,\n      \"tLGap\": 28,\n      \"wAsc\": 986,\n      \"wDes\": 607,\n      \"xH\": 819,\n      \"capH\": 841,\n      \"yMin\": -607,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -607,\n      \"lGap\": 14\n    }\n  },\n  {\n    \"family\": \"Cambay\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 800,\n      \"asc\": 800,\n      \"des\": -503,\n      \"tAsc\": 800,\n      \"tDes\": -503,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 503,\n      \"xH\": 384,\n      \"capH\": 550,\n      \"yMin\": -499,\n      \"yMax\": 760,\n      \"hAsc\": 800,\n      \"hDes\": -503,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cambo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 879,\n      \"des\": -243,\n      \"tAsc\": 879,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 879,\n      \"wDes\": 243,\n      \"xH\": 506,\n      \"capH\": 676,\n      \"yMin\": -243,\n      \"yMax\": 879,\n      \"hAsc\": 879,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Candal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2226,\n      \"des\": -432,\n      \"tAsc\": 2226,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 432,\n      \"xH\": 1079,\n      \"capH\": 1414,\n      \"yMin\": -997,\n      \"yMax\": 2226,\n      \"hAsc\": 2226,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantarell\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2240,\n      \"des\": -660,\n      \"tAsc\": 2240,\n      \"tDes\": -660,\n      \"tLGap\": 0,\n      \"wAsc\": 2157,\n      \"wDes\": 585,\n      \"yMin\": -555,\n      \"yMax\": 2137,\n      \"hAsc\": 2240,\n      \"hDes\": -660,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantata One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -560,\n      \"tAsc\": 2040,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 560,\n      \"xH\": 1023,\n      \"capH\": 1530,\n      \"yMin\": -560,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantora One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caprasimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1880,\n      \"des\": -469,\n      \"tAsc\": 1376,\n      \"tDes\": -395,\n      \"tLGap\": 0,\n      \"wAsc\": 1880,\n      \"wDes\": 469,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -520,\n      \"yMax\": 1916,\n      \"hAsc\": 1880,\n      \"hDes\": -469,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Capriola\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1992,\n      \"des\": -568,\n      \"tAsc\": 1992,\n      \"tDes\": -568,\n      \"tLGap\": 0,\n      \"wAsc\": 1992,\n      \"wDes\": 568,\n      \"xH\": 1128,\n      \"capH\": 1533,\n      \"yMin\": -568,\n      \"yMax\": 1994,\n      \"hAsc\": 1992,\n      \"hDes\": -568,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caramel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 335,\n      \"xH\": 270,\n      \"capH\": 650,\n      \"yMin\": -335,\n      \"yMax\": 923,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carattere\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -350,\n      \"tAsc\": 800,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 568,\n      \"xH\": 350,\n      \"capH\": 690,\n      \"yMin\": -568,\n      \"yMax\": 1011,\n      \"hAsc\": 800,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cardo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2028,\n      \"des\": -745,\n      \"tAsc\": 2028,\n      \"tDes\": -745,\n      \"tLGap\": 0,\n      \"wAsc\": 2028,\n      \"wDes\": 745,\n      \"xH\": 900,\n      \"capH\": 1410,\n      \"yMin\": -745,\n      \"yMax\": 2336,\n      \"hAsc\": 2028,\n      \"hDes\": -745,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carlito\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1950,\n      \"des\": -550,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 452,\n      \"wAsc\": 1950,\n      \"wDes\": 550,\n      \"xH\": 978,\n      \"capH\": 1314,\n      \"yMin\": -529,\n      \"yMax\": 2078,\n      \"hAsc\": 1950,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1946,\n      \"des\": -513,\n      \"tAsc\": 1946,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1946,\n      \"wDes\": 513,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -513,\n      \"yMax\": 1946,\n      \"hAsc\": 1946,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carrois Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -270,\n      \"tAsc\": 922,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carrois Gothic SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -270,\n      \"tAsc\": 922,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carter One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2264,\n      \"des\": -890,\n      \"tAsc\": 2264,\n      \"tDes\": -890,\n      \"tLGap\": 0,\n      \"wAsc\": 2264,\n      \"wDes\": 890,\n      \"xH\": 473,\n      \"capH\": 1481,\n      \"yMin\": -891,\n      \"yMax\": 2264,\n      \"hAsc\": 2264,\n      \"hDes\": -890,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cascadia Code\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -480,\n      \"tAsc\": 1900,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 480,\n      \"xH\": 1060,\n      \"capH\": 1420,\n      \"yMin\": -989,\n      \"yMax\": 2304,\n      \"hAsc\": 1900,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cascadia Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -480,\n      \"tAsc\": 1900,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 480,\n      \"xH\": 1060,\n      \"capH\": 1420,\n      \"yMin\": -989,\n      \"yMax\": 2304,\n      \"hAsc\": 1900,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Castoro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Castoro Titling\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 455,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Catamaran\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -540,\n      \"tAsc\": 1100,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 540,\n      \"xH\": 485,\n      \"capH\": 680,\n      \"yMin\": -377,\n      \"yMax\": 1100,\n      \"hAsc\": 1100,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caudex\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2034,\n      \"des\": -606,\n      \"tAsc\": 2034,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2034,\n      \"wDes\": 606,\n      \"yMin\": -606,\n      \"yMax\": 2034,\n      \"hAsc\": 2034,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cause\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 930,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caveat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 315,\n      \"xH\": 400,\n      \"capH\": 610,\n      \"yMin\": -299,\n      \"yMax\": 960,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caveat Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 300,\n      \"xH\": 420,\n      \"capH\": 660,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cedarville Cursive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1279,\n      \"des\": -663,\n      \"tAsc\": 1279,\n      \"tDes\": -663,\n      \"tLGap\": 0,\n      \"wAsc\": 1279,\n      \"wDes\": 663,\n      \"xH\": 400,\n      \"capH\": 775,\n      \"yMin\": -663,\n      \"yMax\": 1279,\n      \"hAsc\": 1279,\n      \"hDes\": -663,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Century Gothic\",\n    \"fallbacks\": [\"CenturyGothic\", \"AppleGothic\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -451,\n      \"tAsc\": 1536,\n      \"tDes\": -426,\n      \"tLGap\": 229,\n      \"wAsc\": 1989,\n      \"wDes\": 1989,\n      \"yMin\": -628,\n      \"yMax\": 2170,\n      \"hAsc\": 2060,\n      \"hDes\": -451,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Ceviche One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 806,\n      \"des\": -237,\n      \"tAsc\": 806,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 806,\n      \"wDes\": 237,\n      \"xH\": 451,\n      \"capH\": 425,\n      \"yMin\": -237,\n      \"yMax\": 806,\n      \"hAsc\": 806,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chakra Petch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -308,\n      \"tAsc\": 992,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 1248,\n      \"wDes\": 566,\n      \"xH\": 498,\n      \"capH\": 700,\n      \"yMin\": -533,\n      \"yMax\": 1236,\n      \"hAsc\": 992,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Changa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1227,\n      \"des\": -613,\n      \"tAsc\": 1227,\n      \"tDes\": -613,\n      \"tLGap\": 0,\n      \"wAsc\": 1368,\n      \"wDes\": 680,\n      \"xH\": 500,\n      \"capH\": 625,\n      \"yMin\": -553,\n      \"yMax\": 1223,\n      \"hAsc\": 1227,\n      \"hDes\": -613,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Changa One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 882,\n      \"des\": -180,\n      \"tAsc\": 882,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 882,\n      \"wDes\": 180,\n      \"xH\": 500,\n      \"capH\": 625,\n      \"yMin\": -180,\n      \"yMax\": 882,\n      \"hAsc\": 882,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chango\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -216,\n      \"tAsc\": 995,\n      \"tDes\": -216,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 216,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 995,\n      \"hAsc\": 995,\n      \"hDes\": -216,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charis SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2450,\n      \"des\": -900,\n      \"tAsc\": 2450,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 2450,\n      \"wDes\": 900,\n      \"xH\": 987,\n      \"capH\": 1374,\n      \"yMin\": -1092,\n      \"yMax\": 2600,\n      \"hAsc\": 2450,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charm\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -434,\n      \"tAsc\": 1115,\n      \"tDes\": -434,\n      \"tLGap\": 0,\n      \"wAsc\": 1639,\n      \"wDes\": 714,\n      \"xH\": 466,\n      \"capH\": 684,\n      \"yMin\": -692,\n      \"yMax\": 1597,\n      \"hAsc\": 1115,\n      \"hDes\": -434,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charmonman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -700,\n      \"tAsc\": 1200,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 1630,\n      \"wDes\": 937,\n      \"xH\": 420,\n      \"capH\": 700,\n      \"yMin\": -919,\n      \"yMax\": 1562,\n      \"hAsc\": 1200,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chathura\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -602,\n      \"tAsc\": 1020,\n      \"tDes\": -602,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 602,\n      \"xH\": 294,\n      \"capH\": 404,\n      \"yMin\": -602,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -602,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chau Philomene One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1033,\n      \"des\": -334,\n      \"tAsc\": 1033,\n      \"tDes\": -334,\n      \"tLGap\": 0,\n      \"wAsc\": 1033,\n      \"wDes\": 334,\n      \"xH\": 512,\n      \"capH\": 752,\n      \"yMin\": -334,\n      \"yMax\": 1033,\n      \"hAsc\": 1033,\n      \"hDes\": -334,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chela One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -235,\n      \"tAsc\": 942,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 235,\n      \"xH\": 534,\n      \"capH\": 721,\n      \"yMin\": -235,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chelsea Market\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1029,\n      \"des\": -274,\n      \"tAsc\": 1029,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 274,\n      \"xH\": 608,\n      \"capH\": 796,\n      \"yMin\": -274,\n      \"yMax\": 1029,\n      \"hAsc\": 1029,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chenla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Cherish\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -320,\n      \"tAsc\": 850,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 465,\n      \"xH\": 330,\n      \"capH\": 600,\n      \"yMin\": -465,\n      \"yMax\": 981,\n      \"hAsc\": 850,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cherry Bomb One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -272,\n      \"yMax\": 1054,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cherry Cream Soda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1006,\n      \"des\": -247,\n      \"tAsc\": 738,\n      \"tDes\": -247,\n      \"tLGap\": 57,\n      \"wAsc\": 1006,\n      \"wDes\": 247,\n      \"xH\": 502,\n      \"capH\": 741,\n      \"yMin\": -247,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -247,\n      \"lGap\": 29\n    }\n  },\n  {\n    \"family\": \"Cherry Swash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -301,\n      \"tAsc\": 1025,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 301,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -301,\n      \"yMax\": 1000,\n      \"hAsc\": 1025,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chewy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1003,\n      \"des\": -310,\n      \"tAsc\": 801,\n      \"tDes\": -308,\n      \"tLGap\": 49,\n      \"wAsc\": 1003,\n      \"wDes\": 310,\n      \"xH\": 577,\n      \"capH\": 768,\n      \"yMin\": -310,\n      \"yMax\": 1003,\n      \"hAsc\": 1003,\n      \"hDes\": -310,\n      \"lGap\": 25\n    }\n  },\n  {\n    \"family\": \"Chicle\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -294,\n      \"tAsc\": 915,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 294,\n      \"xH\": 277,\n      \"capH\": 513,\n      \"yMin\": -294,\n      \"yMax\": 915,\n      \"hAsc\": 915,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chilanka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -750,\n      \"tAsc\": 1500,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 1914,\n      \"wDes\": 1282,\n      \"xH\": 999,\n      \"capH\": 1448,\n      \"yMin\": -1282,\n      \"yMax\": 1914,\n      \"hAsc\": 1500,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron GoRound TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron Hei HK\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron Sung HK\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chivo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 413,\n      \"xH\": 511,\n      \"capH\": 686,\n      \"yMin\": -314,\n      \"yMax\": 1104,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chivo Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 413,\n      \"xH\": 511,\n      \"capH\": 686,\n      \"yMin\": -314,\n      \"yMax\": 1104,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chocolate Classical Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -549,\n      \"yMax\": 1323,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chokokutai\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 486,\n      \"capH\": 774,\n      \"yMin\": -239,\n      \"yMax\": 1141,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chonburi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -401,\n      \"yMax\": 1072,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cinzel\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -372,\n      \"tAsc\": 976,\n      \"tDes\": -372,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 372,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -372,\n      \"yMax\": 976,\n      \"hAsc\": 976,\n      \"hDes\": -372,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cinzel Decorative\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -372,\n      \"tAsc\": 976,\n      \"tDes\": -372,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 372,\n      \"xH\": 714,\n      \"capH\": 700,\n      \"yMin\": -284,\n      \"yMax\": 945,\n      \"hAsc\": 976,\n      \"hDes\": -372,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Clicker Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -807,\n      \"tAsc\": 1898,\n      \"tDes\": -807,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 807,\n      \"xH\": 621,\n      \"capH\": 1358,\n      \"yMin\": -807,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -807,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Climate Crisis\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -260,\n      \"tAsc\": 1070,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 320,\n      \"xH\": 620,\n      \"capH\": 750,\n      \"yMin\": -308,\n      \"yMax\": 1292,\n      \"hAsc\": 1070,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -784,\n      \"tAsc\": 2124,\n      \"tDes\": -784,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 784,\n      \"yMin\": -691,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -784,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Codystar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 953,\n      \"des\": -255,\n      \"tAsc\": 953,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 255,\n      \"xH\": 753,\n      \"capH\": 761,\n      \"yMin\": -255,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coiny\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": 250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 600,\n      \"wAsc\": 750,\n      \"wDes\": 250,\n      \"yMin\": -466,\n      \"yMax\": 1311,\n      \"hAsc\": 750,\n      \"hDes\": 250,\n      \"lGap\": 600\n    }\n  },\n  {\n    \"family\": \"Combo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 907,\n      \"des\": -269,\n      \"tAsc\": 907,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 907,\n      \"wDes\": 269,\n      \"xH\": 516,\n      \"capH\": 670,\n      \"yMin\": -269,\n      \"yMax\": 907,\n      \"hAsc\": 907,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comfortaa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 881,\n      \"des\": -234,\n      \"tAsc\": 881,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 1285,\n      \"wDes\": 332,\n      \"xH\": 547,\n      \"capH\": 781,\n      \"yMin\": -289,\n      \"yMax\": 1264,\n      \"hAsc\": 881,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comforter\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -480,\n      \"tAsc\": 930,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 739,\n      \"xH\": 400,\n      \"capH\": 750,\n      \"yMin\": -654,\n      \"yMax\": 1119,\n      \"hAsc\": 930,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comforter Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -480,\n      \"tAsc\": 930,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 739,\n      \"xH\": 400,\n      \"capH\": 750,\n      \"yMin\": -661,\n      \"yMax\": 1114,\n      \"hAsc\": 930,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comic Neue\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 350,\n      \"xH\": 487,\n      \"capH\": 670,\n      \"yMin\": -215,\n      \"yMax\": 928,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comic Relief\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2160,\n      \"des\": -697,\n      \"tAsc\": 2160,\n      \"tDes\": -697,\n      \"tLGap\": 0,\n      \"wAsc\": 2257,\n      \"wDes\": 641,\n      \"xH\": 1105,\n      \"capH\": 1554,\n      \"yMin\": -641,\n      \"yMax\": 2257,\n      \"hAsc\": 2160,\n      \"hDes\": -697,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coming Soon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1053,\n      \"des\": -498,\n      \"tAsc\": 792,\n      \"tDes\": -444,\n      \"tLGap\": 42,\n      \"wAsc\": 1053,\n      \"wDes\": 498,\n      \"xH\": 569,\n      \"capH\": 763,\n      \"yMin\": -498,\n      \"yMax\": 1053,\n      \"hAsc\": 1053,\n      \"hDes\": -498,\n      \"lGap\": 21\n    }\n  },\n  {\n    \"family\": \"Comme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1957,\n      \"des\": -501,\n      \"tAsc\": 1957,\n      \"tDes\": -501,\n      \"tLGap\": 0,\n      \"wAsc\": 2519,\n      \"wDes\": 632,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -523,\n      \"yMax\": 2399,\n      \"hAsc\": 1957,\n      \"hDes\": -501,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Commissioner\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2034,\n      \"des\": -412,\n      \"tAsc\": 2034,\n      \"tDes\": -412,\n      \"tLGap\": 0,\n      \"wAsc\": 2424,\n      \"wDes\": 586,\n      \"xH\": 992,\n      \"capH\": 1426,\n      \"yMin\": -570,\n      \"yMax\": 2321,\n      \"hAsc\": 2034,\n      \"hDes\": -412,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Concert One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2005,\n      \"des\": -410,\n      \"tAsc\": 2005,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 2005,\n      \"wDes\": 410,\n      \"xH\": 1004,\n      \"capH\": 1400,\n      \"yMin\": -400,\n      \"yMax\": 1958,\n      \"hAsc\": 2005,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Condiment\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 882,\n      \"des\": -641,\n      \"tAsc\": 882,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 882,\n      \"wDes\": 641,\n      \"xH\": 317,\n      \"capH\": 327,\n      \"yMin\": -641,\n      \"yMax\": 882,\n      \"hAsc\": 882,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Content\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Contrail One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1939,\n      \"des\": -625,\n      \"tAsc\": 1939,\n      \"tDes\": -625,\n      \"tLGap\": 0,\n      \"wAsc\": 1939,\n      \"wDes\": 625,\n      \"xH\": 255,\n      \"capH\": 421,\n      \"yMin\": -625,\n      \"yMax\": 1939,\n      \"hAsc\": 1939,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Convergence\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 943,\n      \"des\": -230,\n      \"tAsc\": 943,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 943,\n      \"wDes\": 230,\n      \"xH\": 541,\n      \"capH\": 727,\n      \"yMin\": -230,\n      \"yMax\": 943,\n      \"hAsc\": 943,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cookie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 789,\n      \"des\": -320,\n      \"tAsc\": 789,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 789,\n      \"wDes\": 320,\n      \"xH\": 115,\n      \"capH\": 312,\n      \"yMin\": -320,\n      \"yMax\": 789,\n      \"hAsc\": 789,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Copperplate\",\n    \"fallbacks\": [\"Copperplate Gothic Light\", \"fantasy\"],\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 763,\n      \"des\": -248,\n      \"tAsc\": 763,\n      \"tDes\": -250,\n      \"tLGap\": 20,\n      \"wAsc\": 763,\n      \"wDes\": 763,\n      \"xH\": 440,\n      \"capH\": 526,\n      \"yMin\": -248,\n      \"yMax\": 924,\n      \"hAsc\": 763,\n      \"hDes\": -248,\n      \"lGap\": 19\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Copse\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1991,\n      \"des\": -483,\n      \"tAsc\": 1583,\n      \"tDes\": -439,\n      \"tLGap\": 113,\n      \"wAsc\": 1991,\n      \"wDes\": 483,\n      \"xH\": 1001,\n      \"capH\": 1505,\n      \"yMin\": -483,\n      \"yMax\": 1991,\n      \"hAsc\": 1991,\n      \"hDes\": -483,\n      \"lGap\": 57\n    }\n  },\n  {\n    \"family\": \"Coral Pixels\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -346,\n      \"tAsc\": 1039,\n      \"tDes\": -346,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 385,\n      \"xH\": 539,\n      \"capH\": 693,\n      \"yMin\": -231,\n      \"yMax\": 924,\n      \"hAsc\": 1039,\n      \"hDes\": -346,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Corben\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2826,\n      \"des\": -969,\n      \"tAsc\": 2826,\n      \"tDes\": -969,\n      \"tLGap\": 0,\n      \"wAsc\": 2826,\n      \"wDes\": 969,\n      \"xH\": 958,\n      \"capH\": 1404,\n      \"yMin\": -495,\n      \"yMax\": 2202,\n      \"hAsc\": 2826,\n      \"hDes\": -969,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Corinthia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 760,\n      \"des\": -440,\n      \"tAsc\": 760,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 863,\n      \"wDes\": 447,\n      \"xH\": 240,\n      \"capH\": 535,\n      \"yMin\": -420,\n      \"yMax\": 843,\n      \"hAsc\": 760,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Garamond\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Infant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Unicase\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Upright\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 937,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -281,\n      \"yMax\": 904,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cossette Texte\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -210,\n      \"tAsc\": 1000,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -210,\n      \"yMax\": 975,\n      \"hAsc\": 1000,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cossette Titre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -210,\n      \"tAsc\": 1000,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -210,\n      \"yMax\": 905,\n      \"hAsc\": 1000,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Courgette\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 112,\n      \"capH\": 301,\n      \"yMin\": -560,\n      \"yMax\": 2005,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Courier New\",\n    \"fallbacks\": [\n      \"Courier\",\n      \"Lucida Sans Typewriter\",\n      \"Lucida Typewriter\",\n      \"monospace\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1705,\n      \"des\": -615,\n      \"tAsc\": 1255,\n      \"tDes\": -386,\n      \"tLGap\": 0,\n      \"wAsc\": 1705,\n      \"wDes\": 1705,\n      \"xH\": 866,\n      \"capH\": 1170,\n      \"yMin\": -1392,\n      \"yMax\": 2091,\n      \"hAsc\": 1705,\n      \"hDes\": -615,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Courier Prime\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1600,\n      \"des\": -700,\n      \"tAsc\": 1600,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 800,\n      \"xH\": 924,\n      \"capH\": 1187,\n      \"yMin\": -526,\n      \"yMax\": 1827,\n      \"hAsc\": 1600,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cousine\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1705,\n      \"des\": -615,\n      \"tAsc\": 1255,\n      \"tDes\": -386,\n      \"tLGap\": 0,\n      \"wAsc\": 1705,\n      \"wDes\": 615,\n      \"xH\": 1082,\n      \"capH\": 1349,\n      \"yMin\": -615,\n      \"yMax\": 2009,\n      \"hAsc\": 1705,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coustard\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -781,\n      \"tAsc\": 2095,\n      \"tDes\": -781,\n      \"tLGap\": 0,\n      \"wAsc\": 2097,\n      \"wDes\": 780,\n      \"xH\": 1067,\n      \"capH\": 1489,\n      \"yMin\": -629,\n      \"yMax\": 2097,\n      \"hAsc\": 2095,\n      \"hDes\": -781,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Covered By Your Grace\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 995,\n      \"des\": -384,\n      \"tAsc\": 995,\n      \"tDes\": -384,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 384,\n      \"xH\": 500,\n      \"capH\": 795,\n      \"yMin\": -384,\n      \"yMax\": 1021,\n      \"hAsc\": 995,\n      \"hDes\": -384,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crafty Girls\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1001,\n      \"des\": -461,\n      \"tAsc\": 761,\n      \"tDes\": -327,\n      \"tLGap\": 40,\n      \"wAsc\": 1001,\n      \"wDes\": 461,\n      \"xH\": 548,\n      \"capH\": 772,\n      \"yMin\": -461,\n      \"yMax\": 999,\n      \"hAsc\": 1001,\n      \"hDes\": -461,\n      \"lGap\": 21\n    }\n  },\n  {\n    \"family\": \"Creepster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 974,\n      \"des\": -223,\n      \"tAsc\": 974,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 223,\n      \"xH\": 751,\n      \"capH\": 751,\n      \"yMin\": -223,\n      \"yMax\": 971,\n      \"hAsc\": 974,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crete Round\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -286,\n      \"tAsc\": 990,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 286,\n      \"xH\": 495,\n      \"capH\": 679,\n      \"yMin\": -277,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crimson Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 918,\n      \"des\": -220,\n      \"tAsc\": 918,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 295,\n      \"xH\": 430,\n      \"capH\": 587,\n      \"yMin\": -286,\n      \"yMax\": 984,\n      \"hAsc\": 918,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crimson Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 972,\n      \"des\": -359,\n      \"tAsc\": 972,\n      \"tDes\": -359,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 297,\n      \"xH\": 430,\n      \"capH\": 656,\n      \"yMin\": -297,\n      \"yMax\": 1038,\n      \"hAsc\": 972,\n      \"hDes\": -359,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Croissant One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1071,\n      \"des\": -344,\n      \"tAsc\": 1071,\n      \"tDes\": -344,\n      \"tLGap\": 0,\n      \"wAsc\": 1071,\n      \"wDes\": 344,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -344,\n      \"yMax\": 1071,\n      \"hAsc\": 1071,\n      \"hDes\": -344,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crushed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -483,\n      \"tAsc\": 1374,\n      \"tDes\": -115,\n      \"tLGap\": 100,\n      \"wAsc\": 1820,\n      \"wDes\": 483,\n      \"xH\": 958,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1820,\n      \"hAsc\": 1820,\n      \"hDes\": -483,\n      \"lGap\": 51\n    }\n  },\n  {\n    \"family\": \"Cuprum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 895,\n      \"des\": -260,\n      \"tAsc\": 895,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 1057,\n      \"hAsc\": 895,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cute Font\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 710,\n      \"des\": -290,\n      \"tAsc\": 710,\n      \"tDes\": -290,\n      \"tLGap\": 250,\n      \"wAsc\": 708,\n      \"wDes\": 290,\n      \"xH\": 312,\n      \"capH\": 429,\n      \"yMin\": -291,\n      \"yMax\": 708,\n      \"hAsc\": 710,\n      \"hDes\": -290,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Cutive\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1580,\n      \"des\": -666,\n      \"tAsc\": 1580,\n      \"tDes\": -666,\n      \"tLGap\": 0,\n      \"wAsc\": 2470,\n      \"wDes\": 804,\n      \"xH\": 1160,\n      \"capH\": 1714,\n      \"yMin\": -778,\n      \"yMax\": 2470,\n      \"hAsc\": 1580,\n      \"hDes\": -666,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cutive Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1697,\n      \"des\": -558,\n      \"tAsc\": 1697,\n      \"tDes\": -558,\n      \"tLGap\": 0,\n      \"wAsc\": 1697,\n      \"wDes\": 558,\n      \"xH\": 774,\n      \"capH\": 1171,\n      \"yMin\": -558,\n      \"yMax\": 1697,\n      \"hAsc\": 1697,\n      \"hDes\": -558,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dai Banna SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1685,\n      \"des\": -638,\n      \"tAsc\": 1685,\n      \"tDes\": -638,\n      \"tLGap\": 0,\n      \"wAsc\": 1685,\n      \"wDes\": 638,\n      \"xH\": 906,\n      \"capH\": 1355,\n      \"yMin\": -627,\n      \"yMax\": 1635,\n      \"hAsc\": 1685,\n      \"hDes\": -638,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Damion\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -746,\n      \"tAsc\": 2068,\n      \"tDes\": -746,\n      \"tLGap\": 0,\n      \"wAsc\": 2122,\n      \"wDes\": 747,\n      \"xH\": 720,\n      \"capH\": 1440,\n      \"yMin\": -747,\n      \"yMax\": 2068,\n      \"hAsc\": 2068,\n      \"hDes\": -746,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dancing Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1096,\n      \"wDes\": 306,\n      \"xH\": 332,\n      \"capH\": 720,\n      \"yMin\": -284,\n      \"yMax\": 1095,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Danfo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 716,\n      \"yMin\": -288,\n      \"yMax\": 1065,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dangrek\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2353,\n      \"wDes\": 1130,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1130,\n      \"yMax\": 2353,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Darker Grotesque\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -296,\n      \"tAsc\": 1060,\n      \"tDes\": -296,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 295,\n      \"xH\": 406,\n      \"capH\": 563,\n      \"yMin\": -204,\n      \"yMax\": 871,\n      \"hAsc\": 1060,\n      \"hDes\": -296,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Darumadrop One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 435,\n      \"capH\": 590,\n      \"yMin\": -279,\n      \"yMax\": 860,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Datatype\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 251,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 976,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"David Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1599,\n      \"des\": -449,\n      \"tAsc\": 1599,\n      \"tDes\": -449,\n      \"tLGap\": 0,\n      \"wAsc\": 2207,\n      \"wDes\": 733,\n      \"xH\": 989,\n      \"capH\": 1360,\n      \"yMin\": -725,\n      \"yMax\": 2169,\n      \"hAsc\": 1599,\n      \"hDes\": -449,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dawning of a New Day\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1151,\n      \"des\": -500,\n      \"tAsc\": 1151,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 500,\n      \"xH\": 218,\n      \"capH\": 818,\n      \"yMin\": -462,\n      \"yMax\": 1151,\n      \"hAsc\": 1151,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Days One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -567,\n      \"tAsc\": 2040,\n      \"tDes\": -568,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 567,\n      \"xH\": 1096,\n      \"capH\": 1434,\n      \"yMin\": -567,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -567,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dekko\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 910,\n      \"des\": -519,\n      \"tAsc\": 910,\n      \"tDes\": -519,\n      \"tLGap\": 0,\n      \"wAsc\": 910,\n      \"wDes\": 519,\n      \"xH\": 432,\n      \"capH\": 556,\n      \"yMin\": -519,\n      \"yMax\": 909,\n      \"hAsc\": 910,\n      \"hDes\": -519,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dela Gothic One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 726,\n      \"yMin\": -288,\n      \"yMax\": 1150,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delicious Handrawn\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 357,\n      \"xH\": 500,\n      \"capH\": 850,\n      \"yMin\": -357,\n      \"yMax\": 1062,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -270,\n      \"tAsc\": 986,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 270,\n      \"xH\": 85,\n      \"capH\": 195,\n      \"yMin\": -270,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -270,\n      \"tAsc\": 986,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 270,\n      \"xH\": 113,\n      \"capH\": 282,\n      \"yMin\": -270,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius Unicase\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -236,\n      \"tAsc\": 1016,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 236,\n      \"xH\": 320,\n      \"capH\": 195,\n      \"yMin\": -236,\n      \"yMax\": 1016,\n      \"hAsc\": 1016,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Della Respira\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2196,\n      \"des\": -607,\n      \"tAsc\": 2196,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 2196,\n      \"wDes\": 607,\n      \"yMin\": -632,\n      \"yMax\": 2207,\n      \"hAsc\": 2196,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Denk One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2118,\n      \"des\": -442,\n      \"tAsc\": 2118,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 2631,\n      \"wDes\": 609,\n      \"xH\": 1202,\n      \"capH\": 1690,\n      \"yMin\": -609,\n      \"yMax\": 2631,\n      \"hAsc\": 2118,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Devonshire\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 981,\n      \"des\": -433,\n      \"tAsc\": 981,\n      \"tDes\": -433,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 433,\n      \"xH\": 405,\n      \"capH\": 664,\n      \"yMin\": -433,\n      \"yMax\": 981,\n      \"hAsc\": 981,\n      \"hDes\": -433,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dhurjati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 870,\n      \"asc\": 1101,\n      \"des\": -509,\n      \"tAsc\": 1101,\n      \"tDes\": -509,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 509,\n      \"xH\": 314,\n      \"capH\": 419,\n      \"yMin\": -509,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -509,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Didact Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -265,\n      \"tAsc\": 1046,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 267,\n      \"xH\": 468,\n      \"capH\": 682,\n      \"yMin\": -267,\n      \"yMax\": 1127,\n      \"hAsc\": 1046,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diphylleia\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 476,\n      \"capH\": 674,\n      \"yMin\": -238,\n      \"yMax\": 925,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diplomata\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -287,\n      \"tAsc\": 930,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 396,\n      \"xH\": 558,\n      \"capH\": 650,\n      \"yMin\": -396,\n      \"yMax\": 1003,\n      \"hAsc\": 930,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diplomata SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -287,\n      \"tAsc\": 930,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 396,\n      \"xH\": 558,\n      \"capH\": 650,\n      \"yMin\": -396,\n      \"yMax\": 1003,\n      \"hAsc\": 930,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 992,\n      \"wDes\": 310,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -270,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 310,\n      \"xH\": 504,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Serif Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 335,\n      \"xH\": 481,\n      \"capH\": 660,\n      \"yMin\": -265,\n      \"yMax\": 916,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Serif Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 335,\n      \"xH\": 480,\n      \"capH\": 661,\n      \"yMin\": -263,\n      \"yMax\": 918,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Do Hyeon\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 636,\n      \"capH\": 851,\n      \"yMin\": -174,\n      \"yMax\": 761,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Dokdo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 696,\n      \"des\": -304,\n      \"tAsc\": 696,\n      \"tDes\": -304,\n      \"tLGap\": 250,\n      \"wAsc\": 696,\n      \"wDes\": 394,\n      \"xH\": 272,\n      \"capH\": 475,\n      \"yMin\": -394,\n      \"yMax\": 695,\n      \"hAsc\": 696,\n      \"hDes\": -304,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Domine\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -240,\n      \"tAsc\": 900,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 240,\n      \"xH\": 540,\n      \"capH\": 720,\n      \"yMin\": -240,\n      \"yMax\": 908,\n      \"hAsc\": 900,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Donegal One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1020,\n      \"capH\": 1530,\n      \"yMin\": -537,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dongle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -598,\n      \"tAsc\": 570,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 598,\n      \"xH\": 280,\n      \"capH\": 395,\n      \"yMin\": -460,\n      \"yMax\": 712,\n      \"hAsc\": 850,\n      \"hDes\": -598,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Doppio One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -500,\n      \"tAsc\": 2060,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2060,\n      \"wDes\": 500,\n      \"xH\": 1055,\n      \"capH\": 1427,\n      \"yMin\": -500,\n      \"yMax\": 2060,\n      \"hAsc\": 2060,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dorsa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 857,\n      \"des\": -200,\n      \"tAsc\": 857,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 857,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 857,\n      \"hAsc\": 857,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dosis\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1027,\n      \"des\": -237,\n      \"tAsc\": 1027,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 237,\n      \"xH\": 472,\n      \"capH\": 731,\n      \"yMin\": -237,\n      \"yMax\": 1074,\n      \"hAsc\": 1027,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DotGothic16\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 787,\n      \"yMin\": -120,\n      \"yMax\": 880,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Doto\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dr Sugiyama\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1009,\n      \"des\": -450,\n      \"tAsc\": 1009,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 450,\n      \"xH\": 235,\n      \"capH\": 710,\n      \"yMin\": -450,\n      \"yMax\": 1009,\n      \"hAsc\": 1009,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Duru Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1157,\n      \"capH\": 1554,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dynalight\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1840,\n      \"des\": -645,\n      \"tAsc\": 1840,\n      \"tDes\": -645,\n      \"tLGap\": 0,\n      \"wAsc\": 1840,\n      \"wDes\": 645,\n      \"xH\": 723,\n      \"capH\": 1441,\n      \"yMin\": -645,\n      \"yMax\": 1840,\n      \"hAsc\": 1840,\n      \"hDes\": -645,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DynaPuff\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -235,\n      \"tAsc\": 965,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 985,\n      \"wDes\": 279,\n      \"xH\": 620,\n      \"capH\": 730,\n      \"yMin\": -279,\n      \"yMax\": 985,\n      \"hAsc\": 965,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Eagle Lake\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2420,\n      \"des\": -925,\n      \"tAsc\": 2420,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 2420,\n      \"wDes\": 925,\n      \"xH\": 1094,\n      \"capH\": 1518,\n      \"yMin\": -926,\n      \"yMax\": 2420,\n      \"hAsc\": 2420,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"East Sea Dokdo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 706,\n      \"des\": -294,\n      \"tAsc\": 706,\n      \"tDes\": -294,\n      \"tLGap\": 250,\n      \"wAsc\": 707,\n      \"wDes\": 297,\n      \"xH\": 239,\n      \"capH\": 418,\n      \"yMin\": -297,\n      \"yMax\": 707,\n      \"hAsc\": 706,\n      \"hDes\": -294,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Eater\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2898,\n      \"des\": -919,\n      \"tAsc\": 2898,\n      \"tDes\": -919,\n      \"tLGap\": 0,\n      \"wAsc\": 2898,\n      \"wDes\": 919,\n      \"xH\": 1706,\n      \"capH\": 1729,\n      \"yMin\": -919,\n      \"yMax\": 2898,\n      \"hAsc\": 2898,\n      \"hDes\": -919,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"EB Garamond\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1007,\n      \"des\": -298,\n      \"tAsc\": 1007,\n      \"tDes\": -298,\n      \"tLGap\": 0,\n      \"wAsc\": 1047,\n      \"wDes\": 390,\n      \"xH\": 400,\n      \"capH\": 650,\n      \"yMin\": -324,\n      \"yMax\": 985,\n      \"hAsc\": 1007,\n      \"hDes\": -298,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Economica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 949,\n      \"des\": -200,\n      \"tAsc\": 949,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 200,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -200,\n      \"yMax\": 927,\n      \"hAsc\": 949,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Eczar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1143,\n      \"des\": -634,\n      \"tAsc\": 1143,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1143,\n      \"wDes\": 634,\n      \"xH\": 468,\n      \"capH\": 650,\n      \"yMin\": -473,\n      \"yMax\": 1021,\n      \"hAsc\": 1143,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Arrows\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -857,\n      \"yMax\": 2002,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2002,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -865,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Cursive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2642,\n      \"des\": -926,\n      \"tAsc\": 2642,\n      \"tDes\": -926,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 945,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -940,\n      \"yMax\": 2777,\n      \"hAsc\": 2642,\n      \"hDes\": -926,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Foundation\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Hand Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2642,\n      \"des\": -926,\n      \"tAsc\": 2642,\n      \"tDes\": -926,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 945,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -940,\n      \"yMax\": 2777,\n      \"hAsc\": 2642,\n      \"hDes\": -926,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu QLD Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -364,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu QLD Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2727,\n      \"des\": -1143,\n      \"tAsc\": 2727,\n      \"tDes\": -1143,\n      \"tLGap\": 0,\n      \"wAsc\": 3409,\n      \"wDes\": 1143,\n      \"xH\": 1055,\n      \"capH\": 1958,\n      \"yMin\": -1143,\n      \"yMax\": 3158,\n      \"hAsc\": 2727,\n      \"hDes\": -1143,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu SA Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu SA Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 946,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -946,\n      \"yMax\": 2777,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu TAS Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -356,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Hand Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -860,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"El Messiri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1019,\n      \"des\": -544,\n      \"tAsc\": 1019,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 544,\n      \"xH\": 480,\n      \"capH\": 660,\n      \"yMin\": -437,\n      \"yMax\": 993,\n      \"hAsc\": 1019,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Electrolize\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 911,\n      \"des\": -275,\n      \"tAsc\": 911,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 911,\n      \"wDes\": 275,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 911,\n      \"hAsc\": 911,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elms Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1230,\n      \"wDes\": 330,\n      \"xH\": 480,\n      \"capH\": 700,\n      \"yMin\": -330,\n      \"yMax\": 1156,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elsie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -274,\n      \"tAsc\": 878,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 878,\n      \"wDes\": 274,\n      \"xH\": 511,\n      \"capH\": 650,\n      \"yMin\": -238,\n      \"yMax\": 872,\n      \"hAsc\": 878,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elsie Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -274,\n      \"tAsc\": 878,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 878,\n      \"wDes\": 274,\n      \"xH\": 511,\n      \"capH\": 650,\n      \"yMin\": -235,\n      \"yMax\": 872,\n      \"hAsc\": 878,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Emblema One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -546,\n      \"tAsc\": 1898,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 546,\n      \"xH\": 1002,\n      \"capH\": 1361,\n      \"yMin\": -546,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Emilys Candy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 996,\n      \"des\": -286,\n      \"tAsc\": 996,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 293,\n      \"xH\": 529,\n      \"capH\": 762,\n      \"yMin\": -286,\n      \"yMax\": 996,\n      \"hAsc\": 996,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1080,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2142,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2149,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2146,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1080,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2142,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -465,\n      \"yMax\": 2141,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Semi Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -467,\n      \"yMax\": 2143,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Engagement\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1843,\n      \"des\": -684,\n      \"tAsc\": 1843,\n      \"tDes\": -684,\n      \"tLGap\": 0,\n      \"wAsc\": 1843,\n      \"wDes\": 684,\n      \"xH\": 653,\n      \"capH\": 1500,\n      \"yMin\": -684,\n      \"yMax\": 1843,\n      \"hAsc\": 1843,\n      \"hDes\": -684,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Englebert\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2064,\n      \"des\": -598,\n      \"tAsc\": 2064,\n      \"tDes\": -598,\n      \"tLGap\": 0,\n      \"wAsc\": 1954,\n      \"wDes\": 637,\n      \"xH\": 1077,\n      \"capH\": 1466,\n      \"yMin\": -637,\n      \"yMax\": 1954,\n      \"hAsc\": 2064,\n      \"hDes\": -598,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Enriqueta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -261,\n      \"tAsc\": 1077,\n      \"tDes\": -261,\n      \"tLGap\": 0,\n      \"wAsc\": 1053,\n      \"wDes\": 295,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -257,\n      \"yMax\": 1031,\n      \"hAsc\": 1077,\n      \"hDes\": -261,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ephesis\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -400,\n      \"tAsc\": 900,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 646,\n      \"xH\": 300,\n      \"capH\": 670,\n      \"yMin\": -618,\n      \"yMax\": 953,\n      \"hAsc\": 900,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epilogue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1580,\n      \"des\": -470,\n      \"tAsc\": 1580,\n      \"tDes\": -470,\n      \"tLGap\": 0,\n      \"wAsc\": 2310,\n      \"wDes\": 520,\n      \"xH\": 1062,\n      \"capH\": 1475,\n      \"yMin\": -467,\n      \"yMax\": 2133,\n      \"hAsc\": 1580,\n      \"hDes\": -470,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epunda Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -316,\n      \"tAsc\": 985,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -293,\n      \"yMax\": 1012,\n      \"hAsc\": 985,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epunda Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -316,\n      \"tAsc\": 985,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -293,\n      \"yMax\": 900,\n      \"hAsc\": 985,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Erica One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1153,\n      \"des\": -339,\n      \"tAsc\": 1153,\n      \"tDes\": -339,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 339,\n      \"xH\": 591,\n      \"capH\": 691,\n      \"yMin\": -339,\n      \"yMax\": 1153,\n      \"hAsc\": 1153,\n      \"hDes\": -339,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Esteban\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -290,\n      \"tAsc\": 984,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 290,\n      \"xH\": 127,\n      \"capH\": 137,\n      \"yMin\": -290,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Estonia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -340,\n      \"tAsc\": 900,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 789,\n      \"xH\": 261,\n      \"capH\": 447,\n      \"yMin\": -789,\n      \"yMax\": 1003,\n      \"hAsc\": 900,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Euphoria Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1250,\n      \"asc\": 1014,\n      \"des\": -442,\n      \"tAsc\": 1013,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 442,\n      \"xH\": 344,\n      \"capH\": 274,\n      \"yMin\": -442,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ewert\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -299,\n      \"tAsc\": 944,\n      \"tDes\": -299,\n      \"tLGap\": 0,\n      \"wAsc\": 944,\n      \"wDes\": 299,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -299,\n      \"yMax\": 944,\n      \"hAsc\": 944,\n      \"hDes\": -299,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exile\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -350,\n      \"tAsc\": 1000,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 482,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -360,\n      \"yMax\": 1099,\n      \"hAsc\": 1000,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1002,\n      \"des\": -327,\n      \"tAsc\": 1002,\n      \"tDes\": -327,\n      \"tLGap\": 0,\n      \"wAsc\": 1134,\n      \"wDes\": 270,\n      \"xH\": 531,\n      \"capH\": 732,\n      \"yMin\": -270,\n      \"yMax\": 1102,\n      \"hAsc\": 1002,\n      \"hDes\": -327,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exo 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 999,\n      \"des\": -201,\n      \"tAsc\": 999,\n      \"tDes\": -201,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 311,\n      \"xH\": 487,\n      \"capH\": 690,\n      \"yMin\": -275,\n      \"yMax\": 1051,\n      \"hAsc\": 999,\n      \"hDes\": -201,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Expletus Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2066,\n      \"des\": -612,\n      \"tAsc\": 2066,\n      \"tDes\": -612,\n      \"tLGap\": 0,\n      \"wAsc\": 1798,\n      \"wDes\": 586,\n      \"xH\": 1034,\n      \"capH\": 1454,\n      \"yMin\": -586,\n      \"yMax\": 1798,\n      \"hAsc\": 2066,\n      \"hDes\": -612,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Explora\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 580,\n      \"xH\": 325,\n      \"capH\": 542,\n      \"yMin\": -580,\n      \"yMax\": 938,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faculty Glyphic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1037,\n      \"des\": -262,\n      \"tAsc\": 1037,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 280,\n      \"xH\": 550,\n      \"capH\": 775,\n      \"yMin\": -276,\n      \"yMax\": 1010,\n      \"hAsc\": 1037,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fahkwang\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -292,\n      \"tAsc\": 1008,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1258,\n      \"wDes\": 456,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -452,\n      \"yMax\": 1203,\n      \"hAsc\": 1008,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Familjen Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1230,\n      \"des\": -270,\n      \"tAsc\": 1230,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1230,\n      \"wDes\": 270,\n      \"xH\": 600,\n      \"capH\": 780,\n      \"yMin\": -265,\n      \"yMax\": 1200,\n      \"hAsc\": 1230,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fanwood Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3761,\n      \"des\": -1609,\n      \"tAsc\": 3761,\n      \"tDes\": -1609,\n      \"tLGap\": 0,\n      \"wAsc\": 3761,\n      \"wDes\": 1609,\n      \"xH\": 1606,\n      \"capH\": 1282,\n      \"yMin\": -1601,\n      \"yMax\": 3687,\n      \"hAsc\": 3761,\n      \"hDes\": -1609,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Farro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 306,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -285,\n      \"yMax\": 1014,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Farsan\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 711,\n      \"des\": -289,\n      \"tAsc\": 711,\n      \"tDes\": -289,\n      \"tLGap\": 200,\n      \"wAsc\": 993,\n      \"wDes\": 391,\n      \"xH\": 441,\n      \"capH\": 664,\n      \"yMin\": -391,\n      \"yMax\": 993,\n      \"hAsc\": 711,\n      \"hDes\": -289,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Fascinate\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2125,\n      \"des\": -591,\n      \"tAsc\": 2125,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 2125,\n      \"wDes\": 591,\n      \"xH\": 1024,\n      \"capH\": 1436,\n      \"yMin\": -591,\n      \"yMax\": 2125,\n      \"hAsc\": 2125,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fascinate Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2125,\n      \"des\": -591,\n      \"tAsc\": 2125,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 2125,\n      \"wDes\": 591,\n      \"xH\": 1024,\n      \"capH\": 1436,\n      \"yMin\": -591,\n      \"yMax\": 2125,\n      \"hAsc\": 2125,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faster One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 898,\n      \"des\": -165,\n      \"tAsc\": 898,\n      \"tDes\": -165,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 372,\n      \"xH\": 529,\n      \"capH\": 625,\n      \"yMin\": -372,\n      \"yMax\": 999,\n      \"hAsc\": 898,\n      \"hDes\": -165,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fasthand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2502,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2502,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fauna One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 987,\n      \"des\": -243,\n      \"tAsc\": 987,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 281,\n      \"xH\": 572,\n      \"capH\": 730,\n      \"yMin\": -281,\n      \"yMax\": 1043,\n      \"hAsc\": 987,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faustina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1043,\n      \"des\": -217,\n      \"tAsc\": 1043,\n      \"tDes\": -217,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 215,\n      \"xH\": 494,\n      \"capH\": 648,\n      \"yMin\": -212,\n      \"yMax\": 1014,\n      \"hAsc\": 1043,\n      \"hDes\": -217,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Federant\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -284,\n      \"tAsc\": 942,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 284,\n      \"xH\": 516,\n      \"capH\": 714,\n      \"yMin\": -377,\n      \"yMax\": 949,\n      \"hAsc\": 942,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Federo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1883,\n      \"des\": -530,\n      \"tAsc\": 1883,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 1883,\n      \"wDes\": 530,\n      \"xH\": 942,\n      \"capH\": 1487,\n      \"yMin\": -530,\n      \"yMax\": 1883,\n      \"hAsc\": 1883,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Felipa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -319,\n      \"tAsc\": 966,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 319,\n      \"xH\": 501,\n      \"capH\": 752,\n      \"yMin\": -319,\n      \"yMax\": 966,\n      \"hAsc\": 966,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fenix\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 879,\n      \"des\": -238,\n      \"tAsc\": 879,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 879,\n      \"wDes\": 238,\n      \"xH\": 450,\n      \"capH\": 650,\n      \"yMin\": -238,\n      \"yMax\": 879,\n      \"hAsc\": 879,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Festive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -590,\n      \"tAsc\": 1100,\n      \"tDes\": -590,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 590,\n      \"xH\": 360,\n      \"capH\": 800,\n      \"yMin\": -587,\n      \"yMax\": 1055,\n      \"hAsc\": 1100,\n      \"hDes\": -590,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Figtree\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 222,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -220,\n      \"yMax\": 917,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Finger Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1097,\n      \"des\": -377,\n      \"tAsc\": 1097,\n      \"tDes\": -377,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 377,\n      \"xH\": 540,\n      \"capH\": 720,\n      \"yMin\": -377,\n      \"yMax\": 1097,\n      \"hAsc\": 1097,\n      \"hDes\": -377,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Finlandica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 331,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -322,\n      \"yMax\": 1000,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1980,\n      \"des\": -644,\n      \"tAsc\": 1980,\n      \"tDes\": -644,\n      \"tLGap\": 0,\n      \"wAsc\": 2164,\n      \"wDes\": 1000,\n      \"xH\": 1053,\n      \"capH\": 1377,\n      \"yMin\": -1000,\n      \"yMax\": 2400,\n      \"hAsc\": 1980,\n      \"hDes\": -644,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -500,\n      \"yMax\": 1050,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -353,\n      \"yMax\": 1104,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 526,\n      \"capH\": 688,\n      \"yMin\": -350,\n      \"yMax\": 1101,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -352,\n      \"yMax\": 1101,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fjalla One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -508,\n      \"tAsc\": 2066,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 2702,\n      \"wDes\": 608,\n      \"xH\": 1377,\n      \"capH\": 1708,\n      \"yMin\": -531,\n      \"yMax\": 2702,\n      \"hAsc\": 2066,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fjord One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1940,\n      \"des\": -620,\n      \"tAsc\": 1940,\n      \"tDes\": -620,\n      \"tLGap\": 0,\n      \"wAsc\": 1940,\n      \"wDes\": 620,\n      \"xH\": 950,\n      \"capH\": 1448,\n      \"yMin\": -620,\n      \"yMax\": 1940,\n      \"hAsc\": 1940,\n      \"hDes\": -620,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flamenco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -231,\n      \"tAsc\": 800,\n      \"tDes\": -231,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 231,\n      \"xH\": 385,\n      \"capH\": 608,\n      \"yMin\": -229,\n      \"yMax\": 800,\n      \"hAsc\": 800,\n      \"hDes\": -231,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flavors\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1015,\n      \"des\": -293,\n      \"tAsc\": 1015,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 300,\n      \"xH\": 845,\n      \"capH\": 801,\n      \"yMin\": -293,\n      \"yMax\": 1014,\n      \"hAsc\": 1015,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fleur De Leah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -450,\n      \"tAsc\": 920,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 549,\n      \"xH\": 324,\n      \"capH\": 620,\n      \"yMin\": -549,\n      \"yMax\": 913,\n      \"hAsc\": 920,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Block\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 320,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Circular\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 320,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Rounded\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 470,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Foldit\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -342,\n      \"yMax\": 965,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fondamento\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -774,\n      \"tAsc\": 2060,\n      \"tDes\": -774,\n      \"tLGap\": 0,\n      \"wAsc\": 2060,\n      \"wDes\": 774,\n      \"xH\": 953,\n      \"capH\": 1439,\n      \"yMin\": -774,\n      \"yMax\": 2060,\n      \"hAsc\": 2060,\n      \"hDes\": -774,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fontdiner Swanky\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1047,\n      \"des\": -510,\n      \"tAsc\": 879,\n      \"tDes\": -251,\n      \"tLGap\": 40,\n      \"wAsc\": 1047,\n      \"wDes\": 510,\n      \"xH\": 579,\n      \"capH\": 805,\n      \"yMin\": -510,\n      \"yMax\": 1047,\n      \"hAsc\": 1047,\n      \"hDes\": -510,\n      \"lGap\": 20\n    }\n  },\n  {\n    \"family\": \"Forum\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -248,\n      \"tAsc\": 856,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 248,\n      \"xH\": 420,\n      \"capH\": 660,\n      \"yMin\": -248,\n      \"yMax\": 856,\n      \"hAsc\": 856,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fragment Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 265,\n      \"xH\": 524,\n      \"capH\": 699,\n      \"yMin\": -265,\n      \"yMax\": 945,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Francois One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1089,\n      \"des\": -329,\n      \"tAsc\": 1089,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1351,\n      \"wDes\": 332,\n      \"xH\": 563,\n      \"capH\": 750,\n      \"yMin\": -332,\n      \"yMax\": 1351,\n      \"hAsc\": 1089,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Frank Ruhl Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 957,\n      \"des\": -334,\n      \"tAsc\": 957,\n      \"tDes\": -334,\n      \"tLGap\": 0,\n      \"wAsc\": 957,\n      \"wDes\": 334,\n      \"xH\": 468,\n      \"capH\": 660,\n      \"yMin\": -289,\n      \"yMax\": 947,\n      \"hAsc\": 957,\n      \"hDes\": -334,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fraunces\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1956,\n      \"des\": -510,\n      \"tAsc\": 1956,\n      \"tDes\": -510,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 609,\n      \"xH\": 964,\n      \"capH\": 1400,\n      \"yMin\": -523,\n      \"yMax\": 2176,\n      \"hAsc\": 1956,\n      \"hDes\": -510,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freckle Face\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1946,\n      \"des\": -571,\n      \"tAsc\": 1946,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1946,\n      \"wDes\": 571,\n      \"xH\": 1147,\n      \"capH\": 1563,\n      \"yMin\": -571,\n      \"yMax\": 1946,\n      \"hAsc\": 1946,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fredericka the Great\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1001,\n      \"des\": -254,\n      \"tAsc\": 1001,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1001,\n      \"wDes\": 254,\n      \"xH\": 519,\n      \"capH\": 772,\n      \"yMin\": -254,\n      \"yMax\": 1001,\n      \"hAsc\": 1001,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fredoka\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -236,\n      \"tAsc\": 974,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 252,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 962,\n      \"hAsc\": 974,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freehand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freeman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -280,\n      \"tAsc\": 1050,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1195,\n      \"wDes\": 350,\n      \"xH\": 564,\n      \"capH\": 750,\n      \"yMin\": -349,\n      \"yMax\": 1188,\n      \"hAsc\": 1050,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fresca\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -285,\n      \"tAsc\": 869,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 285,\n      \"xH\": 484,\n      \"capH\": 648,\n      \"yMin\": -285,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Frijole\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1075,\n      \"des\": -337,\n      \"tAsc\": 1075,\n      \"tDes\": -7,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 337,\n      \"xH\": 712,\n      \"capH\": 788,\n      \"yMin\": -337,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -337,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fruktur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2726,\n      \"wDes\": 558,\n      \"xH\": 1182,\n      \"capH\": 1529,\n      \"yMin\": -558,\n      \"yMax\": 2557,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fugaz One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -422,\n      \"tAsc\": 1046,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1046,\n      \"wDes\": 422,\n      \"xH\": 488,\n      \"capH\": 720,\n      \"yMin\": -422,\n      \"yMax\": 1046,\n      \"hAsc\": 1046,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fuggles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -351,\n      \"tAsc\": 850,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 555,\n      \"xH\": 400,\n      \"capH\": 667,\n      \"yMin\": -552,\n      \"yMax\": 781,\n      \"hAsc\": 850,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Funnel Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1200,\n      \"des\": -300,\n      \"tAsc\": 1200,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 330,\n      \"xH\": 600,\n      \"capH\": 810,\n      \"yMin\": -336,\n      \"yMax\": 1132,\n      \"hAsc\": 1200,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Funnel Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1200,\n      \"des\": -300,\n      \"tAsc\": 1200,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 330,\n      \"xH\": 600,\n      \"capH\": 810,\n      \"yMin\": -336,\n      \"yMax\": 1132,\n      \"hAsc\": 1200,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fustat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -420,\n      \"tAsc\": 1000,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -518,\n      \"yMax\": 1007,\n      \"hAsc\": 1000,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fuzzy Bubbles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1196,\n      \"wDes\": 362,\n      \"xH\": 520,\n      \"capH\": 670,\n      \"yMin\": -362,\n      \"yMax\": 1147,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ga Maamli\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1154,\n      \"wDes\": 347,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -306,\n      \"yMax\": 1154,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gabarito\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 295,\n      \"xH\": 488,\n      \"capH\": 681,\n      \"yMin\": -292,\n      \"yMax\": 960,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gabriela\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -295,\n      \"tAsc\": 986,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 580,\n      \"xH\": 497,\n      \"capH\": 718,\n      \"yMin\": -580,\n      \"yMax\": 1045,\n      \"hAsc\": 986,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gaegu\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 760,\n      \"des\": -240,\n      \"tAsc\": 760,\n      \"tDes\": -240,\n      \"tLGap\": 250,\n      \"wAsc\": 762,\n      \"wDes\": 242,\n      \"xH\": 340,\n      \"capH\": 525,\n      \"yMin\": -240,\n      \"yMax\": 760,\n      \"hAsc\": 760,\n      \"hDes\": -240,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Gafata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 921,\n      \"des\": -202,\n      \"tAsc\": 921,\n      \"tDes\": -202,\n      \"tLGap\": 0,\n      \"wAsc\": 921,\n      \"wDes\": 202,\n      \"xH\": 492,\n      \"capH\": 648,\n      \"yMin\": -202,\n      \"yMax\": 921,\n      \"hAsc\": 921,\n      \"hDes\": -202,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gajraj One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -400,\n      \"tAsc\": 1065,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 515,\n      \"xH\": 500,\n      \"capH\": 665,\n      \"yMin\": -505,\n      \"yMax\": 1051,\n      \"hAsc\": 1065,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -592,\n      \"tAsc\": 1035,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 1035,\n      \"wDes\": 592,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -592,\n      \"yMax\": 1035,\n      \"hAsc\": 1035,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galdeano\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 820,\n      \"des\": -230,\n      \"tAsc\": 820,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 820,\n      \"wDes\": 230,\n      \"xH\": 166,\n      \"capH\": 605,\n      \"yMin\": -230,\n      \"yMax\": 820,\n      \"hAsc\": 820,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galindo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2014,\n      \"des\": -883,\n      \"tAsc\": 2014,\n      \"tDes\": -883,\n      \"tLGap\": 0,\n      \"wAsc\": 2014,\n      \"wDes\": 883,\n      \"xH\": 1096,\n      \"capH\": 1505,\n      \"yMin\": -883,\n      \"yMax\": 2014,\n      \"hAsc\": 2014,\n      \"hDes\": -883,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gamja Flower\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 800,\n      \"des\": -224,\n      \"tAsc\": 800,\n      \"tDes\": -224,\n      \"tLGap\": 256,\n      \"wAsc\": 800,\n      \"wDes\": 258,\n      \"xH\": 311,\n      \"capH\": 526,\n      \"yMin\": -258,\n      \"yMax\": 799,\n      \"hAsc\": 800,\n      \"hDes\": -224,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Gantari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 261,\n      \"xH\": 470,\n      \"capH\": 668,\n      \"yMin\": -260,\n      \"yMax\": 976,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Garamond\",\n    \"fallbacks\": [\n      \"Baskerville\",\n      \"Baskerville Old Face\",\n      \"Hoefler Text\",\n      \"Times New Roman\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1765,\n      \"des\": -539,\n      \"tAsc\": 1339,\n      \"tDes\": -539,\n      \"tLGap\": 313,\n      \"wAsc\": 1765,\n      \"wDes\": 1765,\n      \"yMin\": -762,\n      \"yMax\": 2040,\n      \"hAsc\": 1765,\n      \"hDes\": -539,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Gasoek One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 620,\n      \"capH\": 770,\n      \"yMin\": -226,\n      \"yMax\": 1015,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gayathri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -1000,\n      \"tAsc\": 1500,\n      \"tDes\": -1000,\n      \"tLGap\": 0,\n      \"wAsc\": 2038,\n      \"wDes\": 1234,\n      \"xH\": 1000,\n      \"capH\": 1385,\n      \"yMin\": -1173,\n      \"yMax\": 2036,\n      \"hAsc\": 1500,\n      \"hDes\": -1000,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geist\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 262,\n      \"xH\": 530,\n      \"capH\": 710,\n      \"yMin\": -240,\n      \"yMax\": 940,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geist Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 262,\n      \"xH\": 530,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 1012,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gelasio\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -700,\n      \"tAsc\": 1900,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 800,\n      \"xH\": 986,\n      \"capH\": 1419,\n      \"yMin\": -620,\n      \"yMax\": 2593,\n      \"hAsc\": 1900,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gemunu Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 884,\n      \"des\": -200,\n      \"tAsc\": 884,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 311,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -311,\n      \"yMax\": 863,\n      \"hAsc\": 884,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Genos\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 300,\n      \"xH\": 400,\n      \"capH\": 460,\n      \"yMin\": -201,\n      \"yMax\": 757,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gentium Book Plus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2250,\n      \"des\": -750,\n      \"tAsc\": 2250,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 750,\n      \"xH\": 930,\n      \"capH\": 1260,\n      \"yMin\": -950,\n      \"yMax\": 2600,\n      \"hAsc\": 2250,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gentium Plus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2250,\n      \"des\": -750,\n      \"tAsc\": 2250,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 750,\n      \"xH\": 930,\n      \"capH\": 1260,\n      \"yMin\": -950,\n      \"yMax\": 2600,\n      \"hAsc\": 2250,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 821,\n      \"des\": -225,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 92,\n      \"wAsc\": 821,\n      \"wDes\": 225,\n      \"xH\": 451,\n      \"capH\": 573,\n      \"yMin\": -225,\n      \"yMax\": 821,\n      \"hAsc\": 821,\n      \"hDes\": -225,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Geologica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1950,\n      \"des\": -550,\n      \"tAsc\": 1950,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2518,\n      \"wDes\": 895,\n      \"xH\": 990,\n      \"capH\": 1400,\n      \"yMin\": -722,\n      \"yMax\": 2441,\n      \"hAsc\": 1950,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geom\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -235,\n      \"tAsc\": 1015,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 315,\n      \"xH\": 536,\n      \"capH\": 712,\n      \"yMin\": -263,\n      \"yMax\": 988,\n      \"hAsc\": 1015,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Georama\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -226,\n      \"tAsc\": 968,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 1184,\n      \"wDes\": 420,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -328,\n      \"yMax\": 1132,\n      \"hAsc\": 968,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Georgia\",\n    \"fallbacks\": [\"Times\", \"Times New Roman\", \"serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1878,\n      \"des\": -449,\n      \"tAsc\": 1549,\n      \"tDes\": -444,\n      \"tLGap\": 198,\n      \"wAsc\": 1878,\n      \"wDes\": 1878,\n      \"xH\": 986,\n      \"capH\": 1419,\n      \"yMin\": -621,\n      \"yMax\": 2201,\n      \"hAsc\": 1878,\n      \"hDes\": -449,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Geostar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -226,\n      \"tAsc\": 922,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 226,\n      \"xH\": 469,\n      \"capH\": 695,\n      \"yMin\": -226,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geostar Fill\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -226,\n      \"tAsc\": 922,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 226,\n      \"xH\": 469,\n      \"capH\": 695,\n      \"yMin\": -226,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Germania One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 911,\n      \"des\": -250,\n      \"tAsc\": 911,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 911,\n      \"wDes\": 250,\n      \"xH\": 539,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 911,\n      \"hAsc\": 911,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"GFS Didot\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 947,\n      \"des\": -277,\n      \"tAsc\": 703,\n      \"tDes\": -271,\n      \"tLGap\": 50,\n      \"wAsc\": 947,\n      \"wDes\": 277,\n      \"xH\": 456,\n      \"capH\": 689,\n      \"yMin\": -336,\n      \"yMax\": 1145,\n      \"hAsc\": 947,\n      \"hDes\": -277,\n      \"lGap\": 25\n    }\n  },\n  {\n    \"family\": \"GFS Neohellenic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -245,\n      \"tAsc\": 600,\n      \"tDes\": -222,\n      \"tLGap\": 47,\n      \"wAsc\": 873,\n      \"wDes\": 245,\n      \"xH\": 387,\n      \"capH\": 623,\n      \"yMin\": -286,\n      \"yMax\": 1051,\n      \"hAsc\": 873,\n      \"hDes\": -245,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Gideon Roman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 398,\n      \"xH\": 475,\n      \"capH\": 660,\n      \"yMin\": -398,\n      \"yMax\": 1018,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gidole\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1960,\n      \"des\": -560,\n      \"tAsc\": 1960,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2274,\n      \"wDes\": 717,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -717,\n      \"yMax\": 2274,\n      \"hAsc\": 1960,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gidugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1124,\n      \"asc\": 1294,\n      \"des\": -790,\n      \"tAsc\": 1294,\n      \"tDes\": -790,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 790,\n      \"xH\": 410,\n      \"capH\": 596,\n      \"yMin\": -790,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -790,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gilda Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 892,\n      \"des\": -285,\n      \"tAsc\": 892,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 290,\n      \"xH\": 473,\n      \"capH\": 700,\n      \"yMin\": -290,\n      \"yMax\": 989,\n      \"hAsc\": 892,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gill Sans\",\n    \"fallbacks\": [\"Gill Sans MT\", \"Calibri\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1880,\n      \"des\": -472,\n      \"tAsc\": 1415,\n      \"tDes\": -471,\n      \"tLGap\": 305,\n      \"wAsc\": 1880,\n      \"wDes\": 1880,\n      \"xH\": 920,\n      \"capH\": 1397,\n      \"yMin\": -473,\n      \"yMax\": 1896,\n      \"hAsc\": 1880,\n      \"hDes\": -472,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Girassol\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -250,\n      \"tAsc\": 944,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 326,\n      \"xH\": 540,\n      \"capH\": 750,\n      \"yMin\": -326,\n      \"yMax\": 1070,\n      \"hAsc\": 944,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Give You Glory\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1020,\n      \"des\": -625,\n      \"tAsc\": 1020,\n      \"tDes\": -627,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 621,\n      \"xH\": 551,\n      \"capH\": 747,\n      \"yMin\": -619,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glass Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 835,\n      \"des\": -200,\n      \"tAsc\": 835,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 200,\n      \"xH\": 480,\n      \"capH\": 638,\n      \"yMin\": -200,\n      \"yMax\": 834,\n      \"hAsc\": 835,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glegoo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1267,\n      \"des\": -526,\n      \"tAsc\": 1267,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 1267,\n      \"wDes\": 526,\n      \"yMin\": -518,\n      \"yMax\": 1267,\n      \"hAsc\": 1267,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gloock\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -225,\n      \"tAsc\": 975,\n      \"tDes\": -225,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 363,\n      \"xH\": 508,\n      \"capH\": 750,\n      \"yMin\": -363,\n      \"yMax\": 1004,\n      \"hAsc\": 975,\n      \"hDes\": -225,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gloria Hallelujah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1439,\n      \"des\": -591,\n      \"tAsc\": 1439,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 1439,\n      \"wDes\": 591,\n      \"xH\": 580,\n      \"capH\": 904,\n      \"yMin\": -591,\n      \"yMax\": 1439,\n      \"hAsc\": 1439,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glory\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -220,\n      \"tAsc\": 900,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 280,\n      \"xH\": 472,\n      \"capH\": 672,\n      \"yMin\": -242,\n      \"yMax\": 974,\n      \"hAsc\": 900,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gluten\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1290,\n      \"des\": -475,\n      \"tAsc\": 1290,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 2395,\n      \"wDes\": 550,\n      \"xH\": 833,\n      \"capH\": 1167,\n      \"yMin\": -470,\n      \"yMax\": 2064,\n      \"hAsc\": 1290,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goblin One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -640,\n      \"tAsc\": 1920,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 640,\n      \"xH\": 1107,\n      \"capH\": 1434,\n      \"yMin\": -640,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gochi Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1579,\n      \"des\": -835,\n      \"tAsc\": 1579,\n      \"tDes\": -835,\n      \"tLGap\": 0,\n      \"wAsc\": 1579,\n      \"wDes\": 835,\n      \"xH\": 765,\n      \"capH\": 975,\n      \"yMin\": -835,\n      \"yMax\": 1579,\n      \"hAsc\": 1579,\n      \"hDes\": -835,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goldman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 700,\n      \"xH\": 448,\n      \"capH\": 588,\n      \"yMin\": -680,\n      \"yMax\": 1054,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Golos Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -220,\n      \"tAsc\": 980,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 980,\n      \"wDes\": 230,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -230,\n      \"yMax\": 955,\n      \"hAsc\": 980,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -286,\n      \"tAsc\": 966,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1323,\n      \"wDes\": 1079,\n      \"xH\": 510,\n      \"capH\": 716,\n      \"yMin\": -989,\n      \"yMax\": 1263,\n      \"hAsc\": 966,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1932,\n      \"des\": -572,\n      \"tAsc\": 1932,\n      \"tDes\": -572,\n      \"tLGap\": 0,\n      \"wAsc\": 2377,\n      \"wDes\": 930,\n      \"xH\": 1047,\n      \"capH\": 1432,\n      \"yMin\": -811,\n      \"yMax\": 2303,\n      \"hAsc\": 1932,\n      \"hDes\": -572,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans Flex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1932,\n      \"des\": -572,\n      \"tAsc\": 1932,\n      \"tDes\": -572,\n      \"tLGap\": 0,\n      \"wAsc\": 2452,\n      \"wDes\": 999,\n      \"xH\": 1020,\n      \"capH\": 1432,\n      \"yMin\": -605,\n      \"yMax\": 2210,\n      \"hAsc\": 1932,\n      \"hDes\": -572,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gorditas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 954,\n      \"des\": -259,\n      \"tAsc\": 954,\n      \"tDes\": -259,\n      \"tLGap\": 0,\n      \"wAsc\": 954,\n      \"wDes\": 259,\n      \"xH\": 274,\n      \"capH\": 380,\n      \"yMin\": -250,\n      \"yMax\": 948,\n      \"hAsc\": 954,\n      \"hDes\": -259,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gothic A1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 817,\n      \"des\": -207,\n      \"tAsc\": 817,\n      \"tDes\": -207,\n      \"tLGap\": 256,\n      \"wAsc\": 1238,\n      \"wDes\": 378,\n      \"xH\": 538,\n      \"capH\": 749,\n      \"yMin\": -329,\n      \"yMax\": 1137,\n      \"hAsc\": 817,\n      \"hDes\": -207,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Gotu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -545,\n      \"tAsc\": 1115,\n      \"tDes\": -545,\n      \"tLGap\": 0,\n      \"wAsc\": 1124,\n      \"wDes\": 545,\n      \"xH\": 514,\n      \"capH\": 713,\n      \"yMin\": -543,\n      \"yMax\": 1124,\n      \"hAsc\": 1115,\n      \"hDes\": -545,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goudy Bookletter 1911\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 983,\n      \"des\": -318,\n      \"tAsc\": 755,\n      \"tDes\": -269,\n      \"tLGap\": 92,\n      \"wAsc\": 983,\n      \"wDes\": 318,\n      \"xH\": 458,\n      \"capH\": 691,\n      \"yMin\": -319,\n      \"yMax\": 983,\n      \"hAsc\": 983,\n      \"hDes\": -318,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Gowun Batang\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 775,\n      \"yMin\": -170,\n      \"yMax\": 1155,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gowun Dodum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 775,\n      \"yMin\": -170,\n      \"yMax\": 1158,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Graduate\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -186,\n      \"tAsc\": 953,\n      \"tDes\": -186,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 186,\n      \"xH\": 650,\n      \"capH\": 750,\n      \"yMin\": -186,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -186,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grand Hotel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1938,\n      \"des\": -844,\n      \"tAsc\": 1938,\n      \"tDes\": -844,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 844,\n      \"xH\": 803,\n      \"capH\": 1434,\n      \"yMin\": -844,\n      \"yMax\": 1938,\n      \"hAsc\": 1938,\n      \"hDes\": -844,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grandiflora One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 407,\n      \"capH\": 687,\n      \"yMin\": -357,\n      \"yMax\": 1013,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grandstander\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1465,\n      \"des\": -530,\n      \"tAsc\": 1465,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2395,\n      \"wDes\": 915,\n      \"xH\": 1063,\n      \"capH\": 1291,\n      \"yMin\": -579,\n      \"yMax\": 2247,\n      \"hAsc\": 1465,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grape Nuts\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -325,\n      \"tAsc\": 900,\n      \"tDes\": -325,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 402,\n      \"xH\": 365,\n      \"capH\": 590,\n      \"yMin\": -319,\n      \"yMax\": 928,\n      \"hAsc\": 900,\n      \"hDes\": -325,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gravitas One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1937,\n      \"des\": -668,\n      \"tAsc\": 1937,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 1937,\n      \"wDes\": 668,\n      \"xH\": 1113,\n      \"capH\": 1417,\n      \"yMin\": -668,\n      \"yMax\": 1937,\n      \"hAsc\": 1937,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Great Vibes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 851,\n      \"des\": -401,\n      \"tAsc\": 851,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 590,\n      \"xH\": 328,\n      \"capH\": 750,\n      \"yMin\": -556,\n      \"yMax\": 1153,\n      \"hAsc\": 851,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grechen Fuemen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -320,\n      \"tAsc\": 900,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 304,\n      \"xH\": 317,\n      \"capH\": 580,\n      \"yMin\": -304,\n      \"yMax\": 1032,\n      \"hAsc\": 900,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grenze\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -380,\n      \"tAsc\": 1100,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 380,\n      \"xH\": 448,\n      \"capH\": 603,\n      \"yMin\": -252,\n      \"yMax\": 1017,\n      \"hAsc\": 1100,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grenze Gotisch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -380,\n      \"tAsc\": 1100,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 380,\n      \"xH\": 448,\n      \"capH\": 603,\n      \"yMin\": -271,\n      \"yMax\": 984,\n      \"hAsc\": 1100,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grey Qo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -360,\n      \"tAsc\": 900,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 493,\n      \"xH\": 265,\n      \"capH\": 540,\n      \"yMin\": -473,\n      \"yMax\": 793,\n      \"hAsc\": 900,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Griffy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 984,\n      \"des\": -399,\n      \"tAsc\": 984,\n      \"tDes\": -399,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 399,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -399,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -399,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gruppo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1639,\n      \"des\": -340,\n      \"tAsc\": 1639,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1639,\n      \"wDes\": 372,\n      \"xH\": 766,\n      \"capH\": 1114,\n      \"yMin\": -354,\n      \"yMax\": 1588,\n      \"hAsc\": 1639,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gudea\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -264,\n      \"tAsc\": 972,\n      \"tDes\": -264,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 264,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -264,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gugi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -142,\n      \"tAsc\": 858,\n      \"tDes\": -142,\n      \"tLGap\": 250,\n      \"wAsc\": 869,\n      \"wDes\": 169,\n      \"xH\": 602,\n      \"capH\": 794,\n      \"yMin\": -169,\n      \"yMax\": 866,\n      \"hAsc\": 858,\n      \"hDes\": -142,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Gulzar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1500,\n      \"des\": -1200,\n      \"tAsc\": 1500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 1494,\n      \"wDes\": 900,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -900,\n      \"yMax\": 1494,\n      \"hAsc\": 1500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gupter\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 400,\n      \"xH\": 450,\n      \"capH\": 622,\n      \"yMin\": -235,\n      \"yMax\": 837,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gurajada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1070,\n      \"asc\": 1294,\n      \"des\": -810,\n      \"tAsc\": 1294,\n      \"tDes\": -810,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 810,\n      \"xH\": 358,\n      \"capH\": 482,\n      \"yMin\": -810,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -810,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gveret Levin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1221,\n      \"wDes\": 418,\n      \"xH\": 510,\n      \"capH\": 680,\n      \"yMin\": -418,\n      \"yMax\": 1221,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gwendolyn\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -320,\n      \"tAsc\": 880,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 903,\n      \"wDes\": 641,\n      \"xH\": 290,\n      \"capH\": 618,\n      \"yMin\": -641,\n      \"yMax\": 892,\n      \"hAsc\": 880,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Habibi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 989,\n      \"capH\": 1508,\n      \"yMin\": -562,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hachi Maru Pop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -271,\n      \"yMax\": 812,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hahmlet\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 492,\n      \"capH\": 742,\n      \"yMin\": -265,\n      \"yMax\": 1116,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Halant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1089,\n      \"des\": -486,\n      \"tAsc\": 1089,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1089,\n      \"wDes\": 486,\n      \"xH\": 504,\n      \"capH\": 660,\n      \"yMin\": -422,\n      \"yMax\": 1009,\n      \"hAsc\": 1089,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hammersmith One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1844,\n      \"des\": -716,\n      \"tAsc\": 1844,\n      \"tDes\": -716,\n      \"tLGap\": 0,\n      \"wAsc\": 1844,\n      \"wDes\": 716,\n      \"xH\": 1045,\n      \"capH\": 1330,\n      \"yMin\": -716,\n      \"yMax\": 1843,\n      \"hAsc\": 1844,\n      \"hDes\": -716,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanalei\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -541,\n      \"tAsc\": 2124,\n      \"tDes\": -541,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 541,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -541,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -541,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanalei Fill\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -541,\n      \"tAsc\": 2124,\n      \"tDes\": -541,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 541,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -541,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -541,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Handjet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 8160,\n      \"asc\": 7200,\n      \"des\": -1920,\n      \"tAsc\": 7200,\n      \"tDes\": -1920,\n      \"tLGap\": 0,\n      \"wAsc\": 9840,\n      \"wDes\": 3840,\n      \"xH\": 3840,\n      \"capH\": 5280,\n      \"yMin\": -3840,\n      \"yMax\": 9840,\n      \"hAsc\": 7200,\n      \"hDes\": -1920,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Handlee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -401,\n      \"tAsc\": 933,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 401,\n      \"xH\": 331,\n      \"capH\": 438,\n      \"yMin\": -400,\n      \"yMax\": 934,\n      \"hAsc\": 934,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanken Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -303,\n      \"tAsc\": 1000,\n      \"tDes\": -303,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 303,\n      \"xH\": 493,\n      \"capH\": 697,\n      \"yMin\": -257,\n      \"yMax\": 993,\n      \"hAsc\": 1000,\n      \"hDes\": -303,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanuman\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -1000,\n      \"tAsc\": 2000,\n      \"tDes\": -1000,\n      \"tLGap\": 0,\n      \"wAsc\": 2150,\n      \"wDes\": 900,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -900,\n      \"yMax\": 2150,\n      \"hAsc\": 2000,\n      \"hDes\": -1000,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Happy Monkey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -255,\n      \"tAsc\": 950,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 255,\n      \"xH\": 500,\n      \"capH\": 699,\n      \"yMin\": -255,\n      \"yMax\": 950,\n      \"hAsc\": 950,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Harmattan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2166,\n      \"des\": -1323,\n      \"tAsc\": 2166,\n      \"tDes\": -1323,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 1750,\n      \"xH\": 778,\n      \"capH\": 1111,\n      \"yMin\": -1308,\n      \"yMax\": 2133,\n      \"hAsc\": 2166,\n      \"hDes\": -1323,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Headland One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2043,\n      \"des\": -522,\n      \"tAsc\": 2043,\n      \"tDes\": -522,\n      \"tLGap\": 0,\n      \"wAsc\": 2043,\n      \"wDes\": 522,\n      \"xH\": 1189,\n      \"capH\": 1530,\n      \"yMin\": -522,\n      \"yMax\": 2043,\n      \"hAsc\": 2043,\n      \"hDes\": -522,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hedvig Letters Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 320,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -257,\n      \"yMax\": 947,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hedvig Letters Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 320,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -257,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Heebo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -862,\n      \"tAsc\": 2146,\n      \"tDes\": -862,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 862,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -687,\n      \"yMax\": 1994,\n      \"hAsc\": 2146,\n      \"hDes\": -862,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Henny Penny\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2324,\n      \"des\": -1305,\n      \"tAsc\": 2324,\n      \"tDes\": -1305,\n      \"tLGap\": 0,\n      \"wAsc\": 2324,\n      \"wDes\": 1305,\n      \"xH\": 1264,\n      \"capH\": 1794,\n      \"yMin\": -1305,\n      \"yMax\": 2324,\n      \"hAsc\": 2324,\n      \"hDes\": -1305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hepta Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1976,\n      \"des\": -526,\n      \"tAsc\": 1976,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2800,\n      \"wDes\": 660,\n      \"xH\": 1052,\n      \"capH\": 1504,\n      \"yMin\": -545,\n      \"yMax\": 2556,\n      \"hAsc\": 1976,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Herr Von Muellerhoff\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -497,\n      \"tAsc\": 925,\n      \"tDes\": -497,\n      \"tLGap\": 0,\n      \"wAsc\": 925,\n      \"wDes\": 497,\n      \"xH\": 269,\n      \"capH\": 644,\n      \"yMin\": -497,\n      \"yMax\": 925,\n      \"hAsc\": 925,\n      \"hDes\": -497,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hi Melody\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 679,\n      \"des\": -345,\n      \"tAsc\": 679,\n      \"tDes\": -345,\n      \"tLGap\": 256,\n      \"wAsc\": 679,\n      \"wDes\": 345,\n      \"xH\": 321,\n      \"capH\": 512,\n      \"yMin\": -345,\n      \"yMax\": 679,\n      \"hAsc\": 679,\n      \"hDes\": -345,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Hina Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 380,\n      \"capH\": 700,\n      \"yMin\": -321,\n      \"yMax\": 1035,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1055,\n      \"des\": -546,\n      \"tAsc\": 1055,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 546,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -440,\n      \"yMax\": 1003,\n      \"hAsc\": 1055,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Guntur\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -773,\n      \"tAsc\": 1115,\n      \"tDes\": -773,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 773,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -682,\n      \"yMax\": 1045,\n      \"hAsc\": 1115,\n      \"hDes\": -773,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Madurai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -398,\n      \"tAsc\": 982,\n      \"tDes\": -398,\n      \"tLGap\": 0,\n      \"wAsc\": 982,\n      \"wDes\": 398,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -388,\n      \"yMax\": 930,\n      \"hAsc\": 982,\n      \"hDes\": -398,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Mysuru\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 989,\n      \"des\": -725,\n      \"tAsc\": 989,\n      \"tDes\": -725,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 725,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -673,\n      \"yMax\": 930,\n      \"hAsc\": 989,\n      \"hDes\": -725,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Siliguri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -501,\n      \"tAsc\": 1116,\n      \"tDes\": -501,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 501,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -499,\n      \"yMax\": 1033,\n      \"hAsc\": 1116,\n      \"hDes\": -501,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Vadodara\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -373,\n      \"tAsc\": 1125,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 373,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -371,\n      \"yMax\": 1037,\n      \"hAsc\": 1125,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Holtwood One SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2457,\n      \"des\": -876,\n      \"tAsc\": 2457,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 2470,\n      \"wDes\": 976,\n      \"xH\": 1408,\n      \"capH\": 1536,\n      \"yMin\": -976,\n      \"yMax\": 2470,\n      \"hAsc\": 2457,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Homemade Apple\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1327,\n      \"des\": -866,\n      \"tAsc\": 989,\n      \"tDes\": -662,\n      \"tLGap\": 35,\n      \"wAsc\": 1327,\n      \"wDes\": 866,\n      \"xH\": 600,\n      \"capH\": 1022,\n      \"yMin\": -866,\n      \"yMax\": 1327,\n      \"hAsc\": 1327,\n      \"hDes\": -866,\n      \"lGap\": 18\n    }\n  },\n  {\n    \"family\": \"Homenaje\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 892,\n      \"des\": -204,\n      \"tAsc\": 892,\n      \"tDes\": -204,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 163,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -204,\n      \"yMax\": 892,\n      \"hAsc\": 892,\n      \"hDes\": -204,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Honk\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -640,\n      \"tAsc\": 1800,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1800,\n      \"wDes\": 640,\n      \"xH\": 970,\n      \"capH\": 1200,\n      \"yMin\": -418,\n      \"yMax\": 1597,\n      \"hAsc\": 1800,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Host Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 977,\n      \"wDes\": 372,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 968,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hubballi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 765,\n      \"des\": -191,\n      \"tAsc\": 765,\n      \"tDes\": -191,\n      \"tLGap\": 0,\n      \"wAsc\": 816,\n      \"wDes\": 580,\n      \"xH\": 392,\n      \"capH\": 535,\n      \"yMin\": -580,\n      \"yMax\": 816,\n      \"hAsc\": 765,\n      \"hDes\": -191,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hubot Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -320,\n      \"tAsc\": 1090,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 320,\n      \"xH\": 525,\n      \"capH\": 729,\n      \"yMin\": -267,\n      \"yMax\": 1057,\n      \"hAsc\": 1090,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Huninn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 273,\n      \"xH\": 717,\n      \"capH\": 684,\n      \"yMin\": -251,\n      \"yMax\": 1031,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hurricane\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -430,\n      \"tAsc\": 950,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 982,\n      \"wDes\": 609,\n      \"xH\": 326,\n      \"capH\": 610,\n      \"yMin\": -609,\n      \"yMax\": 982,\n      \"hAsc\": 950,\n      \"hDes\": -430,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iansui\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 273,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -273,\n      \"yMax\": 1066,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ibarra Real Nova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 400,\n      \"xH\": 426,\n      \"capH\": 673,\n      \"yMin\": -260,\n      \"yMax\": 881,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -350,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -245,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1085,\n      \"des\": -415,\n      \"tAsc\": 1085,\n      \"tDes\": -415,\n      \"tLGap\": 0,\n      \"wAsc\": 1128,\n      \"wDes\": 601,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -568,\n      \"yMax\": 1075,\n      \"hAsc\": 1085,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 780,\n      \"tDes\": -220,\n      \"tLGap\": 300,\n      \"wAsc\": 1025,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -246,\n      \"yMax\": 1126,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -460,\n      \"tAsc\": 1070,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1099,\n      \"wDes\": 488,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -421,\n      \"yMax\": 1021,\n      \"hAsc\": 1070,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Hebrew\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 365,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -314,\n      \"yMax\": 976,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -440,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 440,\n      \"xH\": 541,\n      \"capH\": 733,\n      \"yMin\": -223,\n      \"yMax\": 1091,\n      \"hAsc\": 1060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans KR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1085,\n      \"des\": -415,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1085,\n      \"wDes\": 415,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -757,\n      \"yMax\": 1367,\n      \"hAsc\": 1085,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Thai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -534,\n      \"tAsc\": 1116,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 534,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -533,\n      \"yMax\": 1076,\n      \"hAsc\": 1116,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Thai Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -534,\n      \"tAsc\": 1116,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 534,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -533,\n      \"yMax\": 1159,\n      \"hAsc\": 1116,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 286,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -246,\n      \"yMax\": 1122,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iceberg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 936,\n      \"des\": -284,\n      \"tAsc\": 936,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 936,\n      \"wDes\": 284,\n      \"xH\": 519,\n      \"capH\": 691,\n      \"yMin\": -284,\n      \"yMax\": 936,\n      \"hAsc\": 936,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iceland\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -220,\n      \"tAsc\": 750,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 750,\n      \"wDes\": 220,\n      \"xH\": 350,\n      \"capH\": 490,\n      \"yMin\": -220,\n      \"yMax\": 750,\n      \"hAsc\": 750,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Idiqlat\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2233,\n      \"des\": -1109,\n      \"tAsc\": 2233,\n      \"tDes\": -1109,\n      \"tLGap\": 0,\n      \"wAsc\": 2310,\n      \"wDes\": 1326,\n      \"xH\": 991,\n      \"capH\": 1399,\n      \"yMin\": -1109,\n      \"yMax\": 2308,\n      \"hAsc\": 2233,\n      \"hDes\": -1109,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Double Pica\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1924,\n      \"des\": -643,\n      \"tAsc\": 1485,\n      \"tDes\": -593,\n      \"tLGap\": 489,\n      \"wAsc\": 1924,\n      \"wDes\": 643,\n      \"xH\": 926,\n      \"capH\": 1509,\n      \"yMin\": -617,\n      \"yMax\": 1937,\n      \"hAsc\": 1924,\n      \"hDes\": -643,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Double Pica SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1924,\n      \"des\": -643,\n      \"tAsc\": 1485,\n      \"tDes\": -593,\n      \"tLGap\": 489,\n      \"wAsc\": 1924,\n      \"wDes\": 643,\n      \"xH\": 946,\n      \"capH\": 1509,\n      \"yMin\": -595,\n      \"yMax\": 1926,\n      \"hAsc\": 1924,\n      \"hDes\": -643,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell DW Pica\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -692,\n      \"tAsc\": 1548,\n      \"tDes\": -640,\n      \"tLGap\": 372,\n      \"wAsc\": 1868,\n      \"wDes\": 692,\n      \"xH\": 903,\n      \"capH\": 1438,\n      \"yMin\": -645,\n      \"yMax\": 1915,\n      \"hAsc\": 1868,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell DW Pica SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -692,\n      \"tAsc\": 1548,\n      \"tDes\": -640,\n      \"tLGap\": 372,\n      \"wAsc\": 1868,\n      \"wDes\": 692,\n      \"xH\": 903,\n      \"capH\": 1438,\n      \"yMin\": -578,\n      \"yMax\": 1868,\n      \"hAsc\": 1868,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell English\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -744,\n      \"tAsc\": 1519,\n      \"tDes\": -637,\n      \"tLGap\": 442,\n      \"wAsc\": 1854,\n      \"wDes\": 744,\n      \"xH\": 962,\n      \"capH\": 1417,\n      \"yMin\": -588,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -744,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell English SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -744,\n      \"tAsc\": 1519,\n      \"tDes\": -637,\n      \"tLGap\": 442,\n      \"wAsc\": 1854,\n      \"wDes\": 744,\n      \"xH\": 901,\n      \"capH\": 1417,\n      \"yMin\": -588,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -744,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell French Canon\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -530,\n      \"tAsc\": 1501,\n      \"tDes\": -508,\n      \"tLGap\": 389,\n      \"wAsc\": 1868,\n      \"wDes\": 530,\n      \"xH\": 981,\n      \"capH\": 1465,\n      \"yMin\": -530,\n      \"yMax\": 1873,\n      \"hAsc\": 1868,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell French Canon SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -530,\n      \"tAsc\": 1501,\n      \"tDes\": -508,\n      \"tLGap\": 389,\n      \"wAsc\": 1868,\n      \"wDes\": 530,\n      \"xH\": 984,\n      \"capH\": 1465,\n      \"yMin\": -523,\n      \"yMax\": 1873,\n      \"hAsc\": 1868,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Great Primer\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1942,\n      \"des\": -562,\n      \"tAsc\": 1500,\n      \"tDes\": -505,\n      \"tLGap\": 499,\n      \"wAsc\": 1942,\n      \"wDes\": 562,\n      \"xH\": 962,\n      \"capH\": 1488,\n      \"yMin\": -562,\n      \"yMax\": 1943,\n      \"hAsc\": 1942,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Great Primer SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1942,\n      \"des\": -562,\n      \"tAsc\": 1500,\n      \"tDes\": -505,\n      \"tLGap\": 499,\n      \"wAsc\": 1942,\n      \"wDes\": 562,\n      \"xH\": 957,\n      \"capH\": 1488,\n      \"yMin\": -562,\n      \"yMax\": 1943,\n      \"hAsc\": 1942,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imbue\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1046,\n      \"capH\": 1400,\n      \"yMin\": -502,\n      \"yMax\": 2025,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imperial Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -330,\n      \"tAsc\": 880,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 854,\n      \"wDes\": 524,\n      \"xH\": 325,\n      \"capH\": 620,\n      \"yMin\": -524,\n      \"yMax\": 854,\n      \"hAsc\": 880,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imprima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 919,\n      \"des\": -239,\n      \"tAsc\": 919,\n      \"tDes\": -239,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 265,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -265,\n      \"yMax\": 999,\n      \"hAsc\": 919,\n      \"hDes\": -239,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inclusive Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -338,\n      \"yMax\": 1149,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inconsolata\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -190,\n      \"tAsc\": 859,\n      \"tDes\": -190,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 454,\n      \"xH\": 457,\n      \"capH\": 623,\n      \"yMin\": -400,\n      \"yMax\": 1000,\n      \"hAsc\": 859,\n      \"hDes\": -190,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inder\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -520,\n      \"tAsc\": 2040,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 520,\n      \"xH\": 1032,\n      \"capH\": 1392,\n      \"yMin\": -520,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Indie Flower\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 994,\n      \"des\": -500,\n      \"tAsc\": 994,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 994,\n      \"wDes\": 500,\n      \"xH\": 374,\n      \"capH\": 587,\n      \"yMin\": -500,\n      \"yMax\": 994,\n      \"hAsc\": 994,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ingrid Darling\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -380,\n      \"tAsc\": 860,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 630,\n      \"xH\": 300,\n      \"capH\": 640,\n      \"yMin\": -626,\n      \"yMax\": 928,\n      \"hAsc\": 860,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inika\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -297,\n      \"tAsc\": 1006,\n      \"tDes\": -297,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 297,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -289,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -297,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inknut Antiqua\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1703,\n      \"des\": -876,\n      \"tAsc\": 1703,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 1703,\n      \"wDes\": 876,\n      \"xH\": 531,\n      \"capH\": 786,\n      \"yMin\": -846,\n      \"yMax\": 1566,\n      \"hAsc\": 1703,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inria Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -223,\n      \"tAsc\": 976,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 256,\n      \"xH\": 495,\n      \"capH\": 680,\n      \"yMin\": -248,\n      \"yMax\": 990,\n      \"hAsc\": 976,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inria Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -223,\n      \"tAsc\": 976,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 248,\n      \"xH\": 495,\n      \"capH\": 680,\n      \"yMin\": -242,\n      \"yMax\": 974,\n      \"hAsc\": 976,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inspiration\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -400,\n      \"tAsc\": 870,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 420,\n      \"xH\": 340,\n      \"capH\": 680,\n      \"yMin\": -420,\n      \"yMax\": 1055,\n      \"hAsc\": 870,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Instrument Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -250,\n      \"tAsc\": 970,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 350,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -296,\n      \"yMax\": 986,\n      \"hAsc\": 970,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Instrument Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 310,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -309,\n      \"yMax\": 986,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Intel One Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -290,\n      \"tAsc\": 1090,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1122,\n      \"wDes\": 420,\n      \"xH\": 465,\n      \"capH\": 655,\n      \"yMin\": -420,\n      \"yMax\": 1098,\n      \"hAsc\": 1090,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -494,\n      \"tAsc\": 1984,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 2269,\n      \"wDes\": 660,\n      \"xH\": 1118,\n      \"capH\": 1490,\n      \"yMin\": -660,\n      \"yMax\": 2269,\n      \"hAsc\": 1984,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inter Tight\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -494,\n      \"tAsc\": 1984,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 654,\n      \"xH\": 1118,\n      \"capH\": 1490,\n      \"yMin\": -654,\n      \"yMax\": 2234,\n      \"hAsc\": 1984,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iosevka Charon\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -265,\n      \"tAsc\": 1015,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1198,\n      \"wDes\": 604,\n      \"xH\": 520,\n      \"capH\": 735,\n      \"yMin\": -597,\n      \"yMax\": 1190,\n      \"hAsc\": 1015,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iosevka Charon Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -265,\n      \"tAsc\": 1015,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1198,\n      \"wDes\": 604,\n      \"xH\": 520,\n      \"capH\": 735,\n      \"yMin\": -597,\n      \"yMax\": 1190,\n      \"hAsc\": 1015,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Irish Grover\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 965,\n      \"des\": -246,\n      \"tAsc\": 780,\n      \"tDes\": -180,\n      \"tLGap\": 54,\n      \"wAsc\": 965,\n      \"wDes\": 246,\n      \"xH\": 573,\n      \"capH\": 731,\n      \"yMin\": -246,\n      \"yMax\": 965,\n      \"hAsc\": 965,\n      \"hDes\": -246,\n      \"lGap\": 27\n    }\n  },\n  {\n    \"family\": \"Island Moments\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -400,\n      \"tAsc\": 750,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 857,\n      \"wDes\": 535,\n      \"xH\": 270,\n      \"capH\": 480,\n      \"yMin\": -535,\n      \"yMax\": 857,\n      \"hAsc\": 750,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Istok Web\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2061,\n      \"des\": -887,\n      \"tAsc\": 2061,\n      \"tDes\": -887,\n      \"tLGap\": 0,\n      \"wAsc\": 2061,\n      \"wDes\": 887,\n      \"xH\": 1050,\n      \"capH\": 1434,\n      \"yMin\": -887,\n      \"yMax\": 2052,\n      \"hAsc\": 2061,\n      \"hDes\": -887,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Italiana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -250,\n      \"tAsc\": 928,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 928,\n      \"hAsc\": 928,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Italianno\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 560,\n      \"xH\": 273,\n      \"capH\": 577,\n      \"yMin\": -556,\n      \"yMax\": 876,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Itim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 474,\n      \"capH\": 635,\n      \"yMin\": -452,\n      \"yMax\": 978,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 12\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1260,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 720,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -720,\n      \"yMax\": 1020,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 12 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1260,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 720,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -720,\n      \"yMax\": 1020,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 24\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1290,\n      \"asc\": 1020,\n      \"des\": -270,\n      \"tAsc\": 1020,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 750,\n      \"xH\": 510,\n      \"capH\": 750,\n      \"yMin\": -750,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 24 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1290,\n      \"asc\": 1020,\n      \"des\": -270,\n      \"tAsc\": 1020,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 750,\n      \"xH\": 510,\n      \"capH\": 750,\n      \"yMin\": -750,\n      \"yMax\": 1022,\n      \"hAsc\": 1020,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquarda Bastarda 9\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 1045,\n      \"des\": -320,\n      \"tAsc\": 1045,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 320,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -320,\n      \"yMax\": 1040,\n      \"hAsc\": 1045,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquarda Bastarda 9 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 1045,\n      \"des\": -320,\n      \"tAsc\": 1045,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 320,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -320,\n      \"yMax\": 1045,\n      \"hAsc\": 1045,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacques Francois\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -606,\n      \"tAsc\": 2095,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2095,\n      \"wDes\": 606,\n      \"xH\": 879,\n      \"capH\": 1464,\n      \"yMin\": -565,\n      \"yMax\": 2054,\n      \"hAsc\": 2095,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacques Francois Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -606,\n      \"tAsc\": 2095,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2095,\n      \"wDes\": 606,\n      \"xH\": 930,\n      \"capH\": 1513,\n      \"yMin\": -606,\n      \"yMax\": 2095,\n      \"hAsc\": 2095,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaini\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -266,\n      \"tAsc\": 1048,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 266,\n      \"xH\": 494,\n      \"capH\": 639,\n      \"yMin\": -266,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaini Purva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -266,\n      \"tAsc\": 1048,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 266,\n      \"xH\": 494,\n      \"capH\": 639,\n      \"yMin\": -266,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaldi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2350,\n      \"des\": -1111,\n      \"tAsc\": 2350,\n      \"tDes\": -1111,\n      \"tLGap\": 0,\n      \"wAsc\": 2350,\n      \"wDes\": 1111,\n      \"xH\": 930,\n      \"capH\": 1243,\n      \"yMin\": -972,\n      \"yMax\": 2350,\n      \"hAsc\": 2350,\n      \"hDes\": -1111,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2000,\n      \"des\": -500,\n      \"tAsc\": 2000,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 673,\n      \"xH\": 1100,\n      \"capH\": 1333,\n      \"yMin\": -500,\n      \"yMax\": 1960,\n      \"hAsc\": 2000,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 10\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1400,\n      \"asc\": 1125,\n      \"des\": -375,\n      \"tAsc\": 1125,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 375,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -375,\n      \"yMax\": 1125,\n      \"hAsc\": 1125,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 10 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1400,\n      \"asc\": 1125,\n      \"des\": -375,\n      \"tAsc\": 1125,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 375,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -375,\n      \"yMax\": 1130,\n      \"hAsc\": 1125,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 15\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1350,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1054,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -300,\n      \"yMax\": 1050,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 15 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1350,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1054,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -300,\n      \"yMax\": 1054,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 20\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1292,\n      \"asc\": 1026,\n      \"des\": -266,\n      \"tAsc\": 1026,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 266,\n      \"xH\": 570,\n      \"capH\": 760,\n      \"yMin\": -266,\n      \"yMax\": 1026,\n      \"hAsc\": 1026,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 20 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1292,\n      \"asc\": 1026,\n      \"des\": -266,\n      \"tAsc\": 1026,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 266,\n      \"xH\": 570,\n      \"capH\": 760,\n      \"yMin\": -266,\n      \"yMax\": 1029,\n      \"hAsc\": 1026,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 25\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1230,\n      \"asc\": 988,\n      \"des\": -242,\n      \"tAsc\": 988,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 276,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -276,\n      \"yMax\": 990,\n      \"hAsc\": 988,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 25 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1230,\n      \"asc\": 988,\n      \"des\": -242,\n      \"tAsc\": 988,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 276,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -242,\n      \"yMax\": 990,\n      \"hAsc\": 988,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"JetBrains Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 730,\n      \"yMin\": -300,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jim Nightshade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1852,\n      \"des\": -1050,\n      \"tAsc\": 1852,\n      \"tDes\": -1050,\n      \"tLGap\": 0,\n      \"wAsc\": 1852,\n      \"wDes\": 1050,\n      \"xH\": 930,\n      \"capH\": 1234,\n      \"yMin\": -1050,\n      \"yMax\": 1852,\n      \"hAsc\": 1852,\n      \"hDes\": -1050,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Joan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -292,\n      \"tAsc\": 1000,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1117,\n      \"wDes\": 615,\n      \"xH\": 456,\n      \"capH\": 707,\n      \"yMin\": -615,\n      \"yMax\": 1117,\n      \"hAsc\": 1000,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jockey One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1079,\n      \"des\": -319,\n      \"tAsc\": 1079,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 319,\n      \"xH\": 511,\n      \"capH\": 700,\n      \"yMin\": -319,\n      \"yMax\": 1079,\n      \"hAsc\": 1079,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jolly Lodger\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 988,\n      \"des\": -257,\n      \"tAsc\": 988,\n      \"tDes\": -257,\n      \"tLGap\": 0,\n      \"wAsc\": 988,\n      \"wDes\": 263,\n      \"xH\": 642,\n      \"capH\": 757,\n      \"yMin\": -257,\n      \"yMax\": 988,\n      \"hAsc\": 988,\n      \"hDes\": -257,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jomhuria\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 3000,\n      \"asc\": 1840,\n      \"des\": -1160,\n      \"tAsc\": 1840,\n      \"tDes\": -1160,\n      \"tLGap\": 0,\n      \"wAsc\": 3083,\n      \"wDes\": 1575,\n      \"xH\": 850,\n      \"capH\": 1172,\n      \"yMin\": -1575,\n      \"yMax\": 3083,\n      \"hAsc\": 1840,\n      \"hDes\": -1160,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jomolhari\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1248,\n      \"des\": -392,\n      \"tAsc\": 1248,\n      \"tDes\": -392,\n      \"tLGap\": 0,\n      \"wAsc\": 1302,\n      \"wDes\": 610,\n      \"xH\": 360,\n      \"capH\": 756,\n      \"yMin\": -610,\n      \"yMax\": 1302,\n      \"hAsc\": 1248,\n      \"hDes\": -392,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Josefin Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1242,\n      \"wDes\": 324,\n      \"xH\": 378,\n      \"capH\": 702,\n      \"yMin\": -237,\n      \"yMax\": 1183,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Josefin Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 932,\n      \"wDes\": 250,\n      \"xH\": 375,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 931,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jost\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -375,\n      \"tAsc\": 1070,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 375,\n      \"xH\": 460,\n      \"capH\": 700,\n      \"yMin\": -350,\n      \"yMax\": 1030,\n      \"hAsc\": 1070,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Joti One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1003,\n      \"des\": -331,\n      \"tAsc\": 1003,\n      \"tDes\": -331,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 331,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -331,\n      \"yMax\": 1003,\n      \"hAsc\": 1003,\n      \"hDes\": -331,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jua\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 874,\n      \"wDes\": 239,\n      \"xH\": 432,\n      \"capH\": 711,\n      \"yMin\": -242,\n      \"yMax\": 867,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Judson\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 902,\n      \"des\": -248,\n      \"tAsc\": 902,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 902,\n      \"wDes\": 248,\n      \"xH\": 440,\n      \"capH\": 585,\n      \"yMin\": -248,\n      \"yMax\": 902,\n      \"hAsc\": 902,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Julee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -284,\n      \"tAsc\": 894,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 973,\n      \"wDes\": 345,\n      \"xH\": 153,\n      \"capH\": 206,\n      \"yMin\": -345,\n      \"yMax\": 973,\n      \"hAsc\": 894,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Julius Sans One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 863,\n      \"des\": -228,\n      \"tAsc\": 863,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 863,\n      \"wDes\": 228,\n      \"xH\": 649,\n      \"capH\": 715,\n      \"yMin\": -228,\n      \"yMax\": 863,\n      \"hAsc\": 863,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Junge\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1901,\n      \"des\": -588,\n      \"tAsc\": 1901,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1901,\n      \"wDes\": 588,\n      \"xH\": 1010,\n      \"capH\": 1444,\n      \"yMin\": -588,\n      \"yMax\": 1901,\n      \"hAsc\": 1901,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jura\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -436,\n      \"tAsc\": 1930,\n      \"tDes\": -436,\n      \"tLGap\": 0,\n      \"wAsc\": 2203,\n      \"wDes\": 456,\n      \"xH\": 922,\n      \"capH\": 1266,\n      \"yMin\": -427,\n      \"yMax\": 2154,\n      \"hAsc\": 1930,\n      \"hDes\": -436,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Just Another Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1842,\n      \"wDes\": 755,\n      \"xH\": 880,\n      \"capH\": 1436,\n      \"yMin\": -755,\n      \"yMax\": 1842,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Just Me Again Down Here\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -429,\n      \"tAsc\": 1069,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 429,\n      \"xH\": 289,\n      \"capH\": 600,\n      \"yMin\": -429,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"K2D\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -252,\n      \"tAsc\": 1048,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1339,\n      \"wDes\": 577,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -513,\n      \"yMax\": 1262,\n      \"hAsc\": 1048,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kablammo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2078,\n      \"des\": -506,\n      \"tAsc\": 2078,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 2368,\n      \"wDes\": 730,\n      \"xH\": 1100,\n      \"capH\": 1400,\n      \"yMin\": -730,\n      \"yMax\": 2294,\n      \"hAsc\": 2078,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kadwa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2691,\n      \"des\": -1421,\n      \"tAsc\": 2691,\n      \"tDes\": -1421,\n      \"tLGap\": 0,\n      \"wAsc\": 2691,\n      \"wDes\": 1421,\n      \"xH\": 1085,\n      \"capH\": 1434,\n      \"yMin\": -1233,\n      \"yMax\": 2464,\n      \"hAsc\": 2691,\n      \"hDes\": -1421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Decol\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei HarunoUmi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Opti\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Tokumin\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalam\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1063,\n      \"des\": -531,\n      \"tAsc\": 1063,\n      \"tDes\": -531,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 531,\n      \"xH\": 526,\n      \"capH\": 739,\n      \"yMin\": -471,\n      \"yMax\": 1031,\n      \"hAsc\": 1063,\n      \"hDes\": -531,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalnia\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -300,\n      \"tAsc\": 1045,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 708,\n      \"yMin\": -225,\n      \"yMax\": 939,\n      \"hAsc\": 1045,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalnia Glaze\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -300,\n      \"tAsc\": 1045,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 708,\n      \"yMin\": -225,\n      \"yMax\": 939,\n      \"hAsc\": 1045,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kameron\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1823,\n      \"des\": -608,\n      \"tAsc\": 1823,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1823,\n      \"wDes\": 608,\n      \"xH\": 895,\n      \"capH\": 1290,\n      \"yMin\": -608,\n      \"yMax\": 1823,\n      \"hAsc\": 1823,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kanchenjunga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -800,\n      \"tAsc\": 2500,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 800,\n      \"xH\": 1040,\n      \"capH\": 1485,\n      \"yMin\": -800,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kanit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -395,\n      \"tAsc\": 1100,\n      \"tDes\": -395,\n      \"tLGap\": 0,\n      \"wAsc\": 1180,\n      \"wDes\": 400,\n      \"xH\": 474,\n      \"capH\": 644,\n      \"yMin\": -351,\n      \"yMax\": 1061,\n      \"hAsc\": 1100,\n      \"hDes\": -395,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kantumruy Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -260,\n      \"tAsc\": 920,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 468,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -468,\n      \"yMax\": 960,\n      \"hAsc\": 920,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kapakana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 680,\n      \"des\": -320,\n      \"tAsc\": 680,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 680,\n      \"wDes\": 320,\n      \"xH\": 250,\n      \"capH\": 535,\n      \"yMin\": -310,\n      \"yMax\": 690,\n      \"hAsc\": 680,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karantina\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -153,\n      \"tAsc\": 859,\n      \"tDes\": -153,\n      \"tLGap\": 0,\n      \"wAsc\": 859,\n      \"wDes\": 228,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -206,\n      \"yMax\": 845,\n      \"hAsc\": 859,\n      \"hDes\": -153,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1834,\n      \"des\": -504,\n      \"tAsc\": 1834,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 2062,\n      \"wDes\": 545,\n      \"xH\": 956,\n      \"capH\": 1256,\n      \"yMin\": -492,\n      \"yMax\": 1952,\n      \"hAsc\": 1834,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karla Tamil Inclined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 796,\n      \"des\": -345,\n      \"tAsc\": 796,\n      \"tDes\": -345,\n      \"tLGap\": 34,\n      \"wAsc\": 796,\n      \"wDes\": 345,\n      \"xH\": 499,\n      \"capH\": 717,\n      \"yMin\": -351,\n      \"yMax\": 819,\n      \"hAsc\": 796,\n      \"hDes\": -345,\n      \"lGap\": 17\n    }\n  },\n  {\n    \"family\": \"Karla Tamil Upright\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 749,\n      \"wDes\": 215,\n      \"xH\": 503,\n      \"capH\": 727,\n      \"yMin\": -349,\n      \"yMax\": 813,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 9\n    }\n  },\n  {\n    \"family\": \"Karma\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -508,\n      \"tAsc\": 945,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 508,\n      \"xH\": 489,\n      \"capH\": 677,\n      \"yMin\": -508,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Katibeh\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 490,\n      \"des\": -510,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -637,\n      \"yMax\": 1094,\n      \"hAsc\": 490,\n      \"hDes\": -510,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Kaushan Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1084,\n      \"des\": -367,\n      \"tAsc\": 1084,\n      \"tDes\": -367,\n      \"tLGap\": 0,\n      \"wAsc\": 1084,\n      \"wDes\": 367,\n      \"xH\": 452,\n      \"capH\": 714,\n      \"yMin\": -367,\n      \"yMax\": 1084,\n      \"hAsc\": 1084,\n      \"hDes\": -367,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kavivanar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -417,\n      \"tAsc\": 1065,\n      \"tDes\": -417,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 417,\n      \"yMin\": -417,\n      \"yMax\": 1065,\n      \"hAsc\": 1065,\n      \"hDes\": -417,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kavoon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1185,\n      \"capH\": 1530,\n      \"yMin\": -524,\n      \"yMax\": 2365,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kay Pho Du\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1944,\n      \"des\": -525,\n      \"tAsc\": 1944,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1969,\n      \"wDes\": 525,\n      \"xH\": 1050,\n      \"capH\": 1563,\n      \"yMin\": -525,\n      \"yMax\": 1944,\n      \"hAsc\": 1944,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kdam Thmor Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1146,\n      \"des\": -400,\n      \"tAsc\": 1146,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1146,\n      \"wDes\": 550,\n      \"xH\": 612,\n      \"capH\": 793,\n      \"yMin\": -550,\n      \"yMax\": 1146,\n      \"hAsc\": 1146,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Keania One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 989,\n      \"des\": -228,\n      \"tAsc\": 989,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 228,\n      \"xH\": 500,\n      \"capH\": 723,\n      \"yMin\": -228,\n      \"yMax\": 989,\n      \"hAsc\": 989,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kedebideri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 668,\n      \"capH\": 668,\n      \"yMin\": -247,\n      \"yMax\": 976,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kelly Slab\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -250,\n      \"tAsc\": 962,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -250,\n      \"yMax\": 962,\n      \"hAsc\": 962,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kenia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 330,\n      \"xH\": 512,\n      \"capH\": 727,\n      \"yMin\": -330,\n      \"yMax\": 958,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khand\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -479,\n      \"tAsc\": 1050,\n      \"tDes\": -479,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 479,\n      \"xH\": 569,\n      \"capH\": 672,\n      \"yMin\": -394,\n      \"yMax\": 933,\n      \"hAsc\": 1050,\n      \"hDes\": -479,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khmer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2300,\n      \"des\": -1200,\n      \"tAsc\": 2300,\n      \"tDes\": -1200,\n      \"tLGap\": 132,\n      \"wAsc\": 2300,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2283,\n      \"hAsc\": 2300,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khula\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1978,\n      \"asc\": 1978,\n      \"des\": -1198,\n      \"tAsc\": 1978,\n      \"tDes\": -1198,\n      \"tLGap\": 0,\n      \"wAsc\": 1978,\n      \"wDes\": 1198,\n      \"xH\": 986,\n      \"capH\": 1316,\n      \"yMin\": -1021,\n      \"yMax\": 1883,\n      \"hAsc\": 1978,\n      \"hDes\": -1198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kings\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -450,\n      \"tAsc\": 950,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1344,\n      \"wDes\": 508,\n      \"xH\": 460,\n      \"capH\": 630,\n      \"yMin\": -508,\n      \"yMax\": 1344,\n      \"hAsc\": 950,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kirang Haerang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 250,\n      \"wAsc\": 800,\n      \"wDes\": 300,\n      \"xH\": 337,\n      \"capH\": 558,\n      \"yMin\": -300,\n      \"yMax\": 800,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Kite One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1094,\n      \"des\": -351,\n      \"tAsc\": 1094,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 351,\n      \"xH\": 493,\n      \"capH\": 860,\n      \"yMin\": -351,\n      \"yMax\": 1190,\n      \"hAsc\": 1094,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kiwi Maru\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 506,\n      \"capH\": 727,\n      \"yMin\": -259,\n      \"yMax\": 980,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Klee One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 600],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -211,\n      \"yMax\": 942,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Knewave\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1169,\n      \"des\": -385,\n      \"tAsc\": 1169,\n      \"tDes\": -385,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 385,\n      \"xH\": 497,\n      \"capH\": 780,\n      \"yMin\": -365,\n      \"yMax\": 1146,\n      \"hAsc\": 1169,\n      \"hDes\": -385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kodchasan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1024,\n      \"des\": -276,\n      \"tAsc\": 1024,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1249,\n      \"wDes\": 539,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -510,\n      \"yMax\": 1192,\n      \"hAsc\": 1024,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kode Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -300,\n      \"tAsc\": 980,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1034,\n      \"wDes\": 500,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -500,\n      \"yMax\": 1000,\n      \"hAsc\": 980,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Koh Santepheap\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2050,\n      \"des\": -550,\n      \"tAsc\": 2050,\n      \"tDes\": -550,\n      \"tLGap\": 132,\n      \"wAsc\": 2320,\n      \"wDes\": 909,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -900,\n      \"yMax\": 2290,\n      \"hAsc\": 2050,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"KoHo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -255,\n      \"tAsc\": 1045,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1187,\n      \"wDes\": 479,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -461,\n      \"yMax\": 1135,\n      \"hAsc\": 1045,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kolker Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -350,\n      \"tAsc\": 750,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 822,\n      \"wDes\": 350,\n      \"xH\": 205,\n      \"capH\": 480,\n      \"yMin\": -295,\n      \"yMax\": 822,\n      \"hAsc\": 750,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Konkhmer Sleokchher\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1503,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1503,\n      \"yMax\": 2487,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kosugi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 901,\n      \"des\": -123,\n      \"tAsc\": 901,\n      \"tDes\": -123,\n      \"tLGap\": 0,\n      \"wAsc\": 901,\n      \"wDes\": 123,\n      \"xH\": 539,\n      \"capH\": 774,\n      \"yMin\": -123,\n      \"yMax\": 901,\n      \"hAsc\": 901,\n      \"hDes\": -123,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kosugi Maru\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 901,\n      \"des\": -123,\n      \"tAsc\": 901,\n      \"tDes\": -123,\n      \"tLGap\": 0,\n      \"wAsc\": 901,\n      \"wDes\": 123,\n      \"xH\": 546,\n      \"capH\": 781,\n      \"yMin\": -123,\n      \"yMax\": 901,\n      \"hAsc\": 901,\n      \"hDes\": -123,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kotta One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -288,\n      \"tAsc\": 915,\n      \"tDes\": -288,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 288,\n      \"xH\": 76,\n      \"capH\": 212,\n      \"yMin\": -288,\n      \"yMax\": 915,\n      \"hAsc\": 915,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Koulen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1126,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1126,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kranky\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 977,\n      \"des\": -294,\n      \"tAsc\": 744,\n      \"tDes\": -221,\n      \"tLGap\": 55,\n      \"wAsc\": 977,\n      \"wDes\": 294,\n      \"xH\": 432,\n      \"capH\": 777,\n      \"yMin\": -294,\n      \"yMax\": 977,\n      \"hAsc\": 977,\n      \"hDes\": -294,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Kreon\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -286,\n      \"tAsc\": 974,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 326,\n      \"xH\": 481,\n      \"capH\": 691,\n      \"yMin\": -297,\n      \"yMax\": 1102,\n      \"hAsc\": 974,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kristi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1836,\n      \"des\": -724,\n      \"tAsc\": 1272,\n      \"tDes\": -776,\n      \"tLGap\": 512,\n      \"wAsc\": 1836,\n      \"wDes\": 724,\n      \"yMin\": -1035,\n      \"yMax\": 1613,\n      \"hAsc\": 1836,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Krona One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 1180,\n      \"capH\": 1563,\n      \"yMin\": -530,\n      \"yMax\": 2030,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Krub\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1007,\n      \"des\": -293,\n      \"tAsc\": 1007,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1232,\n      \"wDes\": 507,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -498,\n      \"yMax\": 1201,\n      \"hAsc\": 1007,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kufam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -400,\n      \"tAsc\": 900,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1252,\n      \"wDes\": 1050,\n      \"xH\": 544,\n      \"capH\": 720,\n      \"yMin\": -1008,\n      \"yMax\": 1228,\n      \"hAsc\": 900,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kulim Park\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 931,\n      \"des\": -204,\n      \"tAsc\": 931,\n      \"tDes\": -204,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 238,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -220,\n      \"yMax\": 918,\n      \"hAsc\": 931,\n      \"hDes\": -204,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumar One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1137,\n      \"des\": -642,\n      \"tAsc\": 1137,\n      \"tDes\": -642,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 642,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -642,\n      \"yMax\": 1137,\n      \"hAsc\": 1137,\n      \"hDes\": -642,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumar One Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1137,\n      \"des\": -642,\n      \"tAsc\": 1137,\n      \"tDes\": -642,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 642,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -642,\n      \"yMax\": 1137,\n      \"hAsc\": 1137,\n      \"hDes\": -642,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumbh Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -520,\n      \"tAsc\": 2020,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 520,\n      \"xH\": 1000,\n      \"capH\": 1500,\n      \"yMin\": -520,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kurale\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -383,\n      \"tAsc\": 1095,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 1108,\n      \"wDes\": 383,\n      \"xH\": 450,\n      \"capH\": 650,\n      \"yMin\": -383,\n      \"yMax\": 1108,\n      \"hAsc\": 1095,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"La Belle Aurore\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1103,\n      \"des\": -794,\n      \"tAsc\": 1103,\n      \"tDes\": -796,\n      \"tLGap\": 0,\n      \"wAsc\": 1103,\n      \"wDes\": 794,\n      \"xH\": 377,\n      \"capH\": 688,\n      \"yMin\": -794,\n      \"yMax\": 1235,\n      \"hAsc\": 1103,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Labrada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -300,\n      \"tAsc\": 1145,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 300,\n      \"xH\": 450,\n      \"capH\": 640,\n      \"yMin\": -269,\n      \"yMax\": 1063,\n      \"hAsc\": 1145,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lacquer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 557,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -557,\n      \"yMax\": 1150,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Laila\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1098,\n      \"des\": -452,\n      \"tAsc\": 1098,\n      \"tDes\": -452,\n      \"tLGap\": 0,\n      \"wAsc\": 1098,\n      \"wDes\": 452,\n      \"xH\": 517,\n      \"capH\": 717,\n      \"yMin\": -390,\n      \"yMax\": 1027,\n      \"hAsc\": 1098,\n      \"hDes\": -452,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lakki Reddy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -765,\n      \"tAsc\": 938,\n      \"tDes\": -765,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 765,\n      \"xH\": 529,\n      \"capH\": 718,\n      \"yMin\": -765,\n      \"yMax\": 965,\n      \"hAsc\": 938,\n      \"hDes\": -765,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lalezar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 979,\n      \"des\": -588,\n      \"tAsc\": 979,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 588,\n      \"xH\": 186,\n      \"capH\": 570,\n      \"yMin\": -588,\n      \"yMax\": 979,\n      \"hAsc\": 979,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lancelot\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1595,\n      \"des\": -668,\n      \"tAsc\": 1595,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 1595,\n      \"wDes\": 668,\n      \"xH\": 804,\n      \"capH\": 1190,\n      \"yMin\": -668,\n      \"yMax\": 1595,\n      \"hAsc\": 1595,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Langar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 739,\n      \"des\": -200,\n      \"tAsc\": 739,\n      \"tDes\": -200,\n      \"tLGap\": 455,\n      \"wAsc\": 1085,\n      \"wDes\": 390,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -390,\n      \"yMax\": 1085,\n      \"hAsc\": 739,\n      \"hDes\": -200,\n      \"lGap\": 455\n    }\n  },\n  {\n    \"family\": \"Lateef\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1937,\n      \"des\": -1024,\n      \"tAsc\": 1937,\n      \"tDes\": -1024,\n      \"tLGap\": 0,\n      \"wAsc\": 2742,\n      \"wDes\": 1488,\n      \"xH\": 690,\n      \"capH\": 1022,\n      \"yMin\": -998,\n      \"yMax\": 2151,\n      \"hAsc\": 1937,\n      \"hDes\": -1024,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lato\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1974,\n      \"des\": -426,\n      \"tAsc\": 1610,\n      \"tDes\": -390,\n      \"tLGap\": 400,\n      \"wAsc\": 1974,\n      \"wDes\": 426,\n      \"xH\": 1013,\n      \"capH\": 1433,\n      \"yMin\": -365,\n      \"yMax\": 1837,\n      \"hAsc\": 1974,\n      \"hDes\": -426,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lavishly Yours\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -500,\n      \"tAsc\": 1100,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1142,\n      \"wDes\": 530,\n      \"xH\": 244,\n      \"capH\": 780,\n      \"yMin\": -524,\n      \"yMax\": 1142,\n      \"hAsc\": 1100,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1935,\n      \"des\": -465,\n      \"tAsc\": 1935,\n      \"tDes\": -465,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 500,\n      \"xH\": 1094,\n      \"capH\": 1470,\n      \"yMin\": -500,\n      \"yMax\": 2103,\n      \"hAsc\": 1935,\n      \"hDes\": -465,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1536,\n      \"asc\": 1100,\n      \"des\": -600,\n      \"tAsc\": 1100,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 600,\n      \"xH\": 542,\n      \"capH\": 936,\n      \"yMin\": -598,\n      \"yMax\": 1315,\n      \"hAsc\": 1100,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Spartan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1400,\n      \"des\": -440,\n      \"tAsc\": 1400,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2305,\n      \"wDes\": 675,\n      \"xH\": 821,\n      \"capH\": 1320,\n      \"yMin\": -488,\n      \"yMax\": 2176,\n      \"hAsc\": 1400,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Leckerli One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1032,\n      \"des\": -313,\n      \"tAsc\": 1032,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 313,\n      \"xH\": 300,\n      \"capH\": 521,\n      \"yMin\": -313,\n      \"yMax\": 1032,\n      \"hAsc\": 1032,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ledger\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1062,\n      \"des\": -329,\n      \"tAsc\": 1062,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 329,\n      \"xH\": 487,\n      \"capH\": 750,\n      \"yMin\": -329,\n      \"yMax\": 1062,\n      \"hAsc\": 1062,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lekton\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 585,\n      \"xH\": 475,\n      \"capH\": 655,\n      \"yMin\": -585,\n      \"yMax\": 1112,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lemon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1019,\n      \"des\": -287,\n      \"tAsc\": 1019,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 424,\n      \"xH\": 575,\n      \"capH\": 710,\n      \"yMin\": -424,\n      \"yMax\": 1129,\n      \"hAsc\": 1019,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lemonada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1345,\n      \"des\": -653,\n      \"tAsc\": 1345,\n      \"tDes\": -653,\n      \"tLGap\": 0,\n      \"wAsc\": 1346,\n      \"wDes\": 651,\n      \"xH\": 575,\n      \"capH\": 710,\n      \"yMin\": -566,\n      \"yMax\": 1345,\n      \"hAsc\": 1345,\n      \"hDes\": -653,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1080,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Deca\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1080,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Exa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1112,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Giga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1125,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Mega\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1131,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Peta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1138,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Tera\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1144,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Zetta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1160,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Keyboard\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 894,\n      \"wDes\": 246,\n      \"xH\": 754,\n      \"capH\": 754,\n      \"yMin\": -243,\n      \"yMax\": 754,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Math\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 3813,\n      \"wDes\": 1641,\n      \"xH\": 429,\n      \"capH\": 658,\n      \"yMin\": -1641,\n      \"yMax\": 3813,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 895,\n      \"wDes\": 288,\n      \"xH\": 495,\n      \"capH\": 613,\n      \"yMin\": -288,\n      \"yMax\": 895,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 268,\n      \"xH\": 460,\n      \"capH\": 658,\n      \"yMin\": -268,\n      \"yMax\": 893,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 328,\n      \"xH\": 429,\n      \"capH\": 658,\n      \"yMin\": -256,\n      \"yMax\": 1125,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Serif Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1052,\n      \"wDes\": 249,\n      \"xH\": 409,\n      \"capH\": 658,\n      \"yMin\": -249,\n      \"yMax\": 1052,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 128\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 128 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Extended\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Extended Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode EAN13 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 840,\n      \"des\": -120,\n      \"tAsc\": 840,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 840,\n      \"wDes\": 120,\n      \"xH\": 420,\n      \"capH\": 840,\n      \"yMin\": -120,\n      \"yMax\": 840,\n      \"hAsc\": 840,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Baskerville\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -270,\n      \"tAsc\": 970,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 270,\n      \"xH\": 530,\n      \"capH\": 770,\n      \"yMin\": -270,\n      \"yMax\": 1182,\n      \"hAsc\": 970,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Bodoni\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -326,\n      \"tAsc\": 924,\n      \"tDes\": -326,\n      \"tLGap\": 0,\n      \"wAsc\": 1204,\n      \"wDes\": 326,\n      \"xH\": 450,\n      \"capH\": 754,\n      \"yMin\": -326,\n      \"yMax\": 1146,\n      \"hAsc\": 924,\n      \"hDes\": -326,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Caslon Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -266,\n      \"tAsc\": 970,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 963,\n      \"wDes\": 254,\n      \"xH\": 424,\n      \"capH\": 690,\n      \"yMin\": -254,\n      \"yMax\": 963,\n      \"hAsc\": 970,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Caslon Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -260,\n      \"tAsc\": 970,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 260,\n      \"xH\": 530,\n      \"capH\": 770,\n      \"yMin\": -260,\n      \"yMax\": 970,\n      \"hAsc\": 970,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Franklin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -246,\n      \"tAsc\": 966,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 246,\n      \"xH\": 530,\n      \"capH\": 742,\n      \"yMin\": -239,\n      \"yMax\": 1151,\n      \"hAsc\": 966,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Licorice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 452,\n      \"xH\": 400,\n      \"capH\": 720,\n      \"yMin\": -452,\n      \"yMax\": 1043,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Life Savers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -250,\n      \"tAsc\": 972,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 251,\n      \"xH\": 436,\n      \"capH\": 821,\n      \"yMin\": -250,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lilex\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 999,\n      \"des\": -301,\n      \"tAsc\": 999,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 427,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -350,\n      \"yMax\": 1119,\n      \"hAsc\": 999,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lilita One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 923,\n      \"des\": -220,\n      \"tAsc\": 922,\n      \"tDes\": -219,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 220,\n      \"xH\": 506,\n      \"capH\": 704,\n      \"yMin\": -220,\n      \"yMax\": 923,\n      \"hAsc\": 923,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lily Script One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1017,\n      \"des\": -359,\n      \"tAsc\": 1017,\n      \"tDes\": -359,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 359,\n      \"xH\": 762,\n      \"capH\": 762,\n      \"yMin\": -359,\n      \"yMax\": 1017,\n      \"hAsc\": 1017,\n      \"hDes\": -359,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Limelight\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1864,\n      \"des\": -629,\n      \"tAsc\": 1864,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1864,\n      \"wDes\": 629,\n      \"xH\": 1068,\n      \"capH\": 1415,\n      \"yMin\": -636,\n      \"yMax\": 1864,\n      \"hAsc\": 1864,\n      \"hDes\": -629,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Linden Hill\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3633,\n      \"des\": -1888,\n      \"tAsc\": 3633,\n      \"tDes\": -1888,\n      \"tLGap\": 0,\n      \"wAsc\": 3633,\n      \"wDes\": 1081,\n      \"xH\": 1606,\n      \"capH\": 2732,\n      \"yMin\": -1081,\n      \"yMax\": 3633,\n      \"hAsc\": 3633,\n      \"hDes\": -1888,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LINE Seed JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -168,\n      \"tAsc\": 932,\n      \"tDes\": -168,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 317,\n      \"xH\": 509,\n      \"capH\": 751,\n      \"yMin\": -466,\n      \"yMax\": 1112,\n      \"hAsc\": 932,\n      \"hDes\": -168,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Linefont\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -200,\n      \"tAsc\": 1200,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1274,\n      \"yMax\": 1320,\n      \"hAsc\": 1200,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lisu Bosa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 230,\n      \"xH\": 425,\n      \"capH\": 530,\n      \"yMin\": -230,\n      \"yMax\": 834,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Liter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -396,\n      \"tAsc\": 1030,\n      \"tDes\": -396,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 396,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -396,\n      \"yMax\": 979,\n      \"hAsc\": 1030,\n      \"hDes\": -396,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Literata\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1177,\n      \"des\": -308,\n      \"tAsc\": 1177,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 308,\n      \"xH\": 507,\n      \"capH\": 701,\n      \"yMin\": -268,\n      \"yMax\": 1136,\n      \"hAsc\": 1177,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Liu Jian Mao Cao\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 615,\n      \"xH\": 420,\n      \"capH\": 600,\n      \"yMin\": -615,\n      \"yMax\": 888,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Livvic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -250,\n      \"tAsc\": 1005,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1171,\n      \"wDes\": 285,\n      \"xH\": 497,\n      \"capH\": 710,\n      \"yMin\": -270,\n      \"yMax\": 1101,\n      \"hAsc\": 1005,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lobster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 490,\n      \"xH\": 500,\n      \"capH\": 748,\n      \"yMin\": -490,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lobster Two\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 754,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 215,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -215,\n      \"yMax\": 940,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 238,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -238,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Sketch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 217,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -217,\n      \"yMax\": 935,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Solid\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 300, 400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 941,\n      \"wDes\": 215,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -208,\n      \"yMax\": 937,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Long Cang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 318,\n      \"xH\": 512,\n      \"capH\": 684,\n      \"yMin\": -318,\n      \"yMax\": 868,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lora\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -274,\n      \"tAsc\": 1006,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1206,\n      \"wDes\": 294,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -271,\n      \"yMax\": 1114,\n      \"hAsc\": 1006,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Love Light\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -500,\n      \"tAsc\": 900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 531,\n      \"xH\": 320,\n      \"capH\": 700,\n      \"yMin\": -531,\n      \"yMax\": 1020,\n      \"hAsc\": 900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Love Ya Like A Sister\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 942,\n      \"des\": -333,\n      \"tAsc\": 942,\n      \"tDes\": -333,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 333,\n      \"xH\": 510,\n      \"capH\": 674,\n      \"yMin\": -333,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -333,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Loved by the King\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2398,\n      \"des\": -1137,\n      \"tAsc\": 2398,\n      \"tDes\": -1137,\n      \"tLGap\": 0,\n      \"wAsc\": 2398,\n      \"wDes\": 1137,\n      \"xH\": 1111,\n      \"capH\": 1774,\n      \"yMin\": -1024,\n      \"yMax\": 2157,\n      \"hAsc\": 2398,\n      \"hDes\": -1137,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lovers Quarrel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 726,\n      \"des\": -401,\n      \"tAsc\": 726,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 810,\n      \"wDes\": 420,\n      \"xH\": 274,\n      \"capH\": 609,\n      \"yMin\": -402,\n      \"yMax\": 777,\n      \"hAsc\": 726,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lucida Bright\",\n    \"fallbacks\": [\"Georgia\", \"serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1980,\n      \"des\": -432,\n      \"tAsc\": 1579,\n      \"tDes\": -420,\n      \"tLGap\": 49,\n      \"wAsc\": 1900,\n      \"wDes\": 1900,\n      \"yMin\": -432,\n      \"yMax\": 1900,\n      \"hAsc\": 1980,\n      \"hDes\": -432,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Lucida Sans Typewriter\",\n    \"fallbacks\": [\n      \"Lucida Console\",\n      \"monaco\",\n      \"Bitstream Vera Sans Mono\",\n      \"monospace\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1974,\n      \"des\": -432,\n      \"tAsc\": 1579,\n      \"tDes\": 420,\n      \"tLGap\": 49,\n      \"wAsc\": 1900,\n      \"wDes\": 1900,\n      \"yMin\": -420,\n      \"yMax\": 1900,\n      \"hAsc\": 1974,\n      \"hDes\": -432,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Luckiest Guy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 2006,\n      \"wDes\": 504,\n      \"xH\": 1400,\n      \"capH\": 1424,\n      \"yMin\": -716,\n      \"yMax\": 2045,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lugrasimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2122,\n      \"des\": -666,\n      \"tAsc\": 1752,\n      \"tDes\": -666,\n      \"tLGap\": -370,\n      \"wAsc\": 1900,\n      \"wDes\": 666,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -670,\n      \"yMax\": 2122,\n      \"hAsc\": 2122,\n      \"hDes\": -666,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lumanosimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2098,\n      \"des\": -727,\n      \"tAsc\": 1752,\n      \"tDes\": -666,\n      \"tLGap\": -370,\n      \"wAsc\": 1964,\n      \"wDes\": 666,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -461,\n      \"yMax\": 2060,\n      \"hAsc\": 2098,\n      \"hDes\": -727,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lunasima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1980,\n      \"des\": -432,\n      \"tAsc\": 1604,\n      \"tDes\": -419,\n      \"tLGap\": 168,\n      \"wAsc\": 1980,\n      \"wDes\": 432,\n      \"xH\": 1086,\n      \"capH\": 1480,\n      \"yMin\": -832,\n      \"yMax\": 2134,\n      \"hAsc\": 1980,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lusitana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -341,\n      \"tAsc\": 956,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 341,\n      \"xH\": 139,\n      \"capH\": 714,\n      \"yMin\": -337,\n      \"yMax\": 933,\n      \"hAsc\": 956,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lustria\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -327,\n      \"tAsc\": 955,\n      \"tDes\": -227,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 327,\n      \"xH\": 504,\n      \"capH\": 704,\n      \"yMin\": -327,\n      \"yMax\": 955,\n      \"hAsc\": 955,\n      \"hDes\": -327,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Luxurious Roman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 402,\n      \"xH\": 480,\n      \"capH\": 665,\n      \"yMin\": -402,\n      \"yMax\": 1017,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Luxurious Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 515,\n      \"xH\": 330,\n      \"capH\": 565,\n      \"yMin\": -515,\n      \"yMax\": 934,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW Marker Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -198,\n      \"tAsc\": 982,\n      \"tDes\": -198,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 510,\n      \"capH\": 760,\n      \"yMin\": -267,\n      \"yMax\": 1240,\n      \"hAsc\": 982,\n      \"hDes\": -198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW WenKai Mono TC\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -241,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 241,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -306,\n      \"yMax\": 1103,\n      \"hAsc\": 928,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW WenKai TC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1032,\n      \"des\": -285,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 285,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -285,\n      \"yMax\": 1102,\n      \"hAsc\": 1032,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1189,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1 Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -235,\n      \"tAsc\": 1000,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1235,\n      \"wDes\": 270,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1213,\n      \"hAsc\": 1000,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1p\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -320,\n      \"tAsc\": 860,\n      \"tDes\": -140,\n      \"tLGap\": 90,\n      \"wAsc\": 1075,\n      \"wDes\": 320,\n      \"yMin\": -343,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -320,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"M PLUS 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1189,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS Code Latin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -235,\n      \"tAsc\": 1000,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1235,\n      \"wDes\": 270,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1213,\n      \"hAsc\": 1000,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS Rounded 1c\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -320,\n      \"tAsc\": 860,\n      \"tDes\": -140,\n      \"tLGap\": 90,\n      \"wAsc\": 1075,\n      \"wDes\": 320,\n      \"yMin\": -343,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -320,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Ma Shan Zheng\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 373,\n      \"xH\": 506,\n      \"capH\": 760,\n      \"yMin\": -373,\n      \"yMax\": 915,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Macondo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 888,\n      \"des\": -292,\n      \"tAsc\": 888,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 888,\n      \"wDes\": 292,\n      \"xH\": 24,\n      \"capH\": 53,\n      \"yMin\": -292,\n      \"yMax\": 888,\n      \"hAsc\": 888,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Macondo Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 888,\n      \"des\": -292,\n      \"tAsc\": 888,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 888,\n      \"wDes\": 292,\n      \"xH\": 24,\n      \"capH\": 696,\n      \"yMin\": -292,\n      \"yMax\": 888,\n      \"hAsc\": 888,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -350,\n      \"tAsc\": 950,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 420,\n      \"xH\": 486,\n      \"capH\": 656,\n      \"yMin\": -403,\n      \"yMax\": 1088,\n      \"hAsc\": 950,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Madimi One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1010,\n      \"des\": -310,\n      \"tAsc\": 1010,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Magra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -247,\n      \"tAsc\": 968,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 968,\n      \"wDes\": 247,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -247,\n      \"yMax\": 941,\n      \"hAsc\": 968,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maiden Orange\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1832,\n      \"wDes\": 506,\n      \"xH\": 1056,\n      \"capH\": 1406,\n      \"yMin\": -635,\n      \"yMax\": 1848,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maitree\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -500,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 500,\n      \"xH\": 489,\n      \"capH\": 695,\n      \"yMin\": -463,\n      \"yMax\": 1111,\n      \"hAsc\": 1150,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Major Mono Display\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -100,\n      \"tAsc\": 900,\n      \"tDes\": -100,\n      \"tLGap\": 0,\n      \"wAsc\": 1152,\n      \"wDes\": 223,\n      \"xH\": 696,\n      \"capH\": 696,\n      \"yMin\": -223,\n      \"yMax\": 1152,\n      \"hAsc\": 900,\n      \"hDes\": -100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mako\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2141,\n      \"des\": -538,\n      \"tAsc\": 2141,\n      \"tDes\": -538,\n      \"tLGap\": 0,\n      \"wAsc\": 2141,\n      \"wDes\": 538,\n      \"xH\": 1031,\n      \"capH\": 1437,\n      \"yMin\": -538,\n      \"yMax\": 2093,\n      \"hAsc\": 2141,\n      \"hDes\": -538,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mali\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1523,\n      \"wDes\": 599,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -516,\n      \"yMax\": 1410,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mallanna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 870,\n      \"asc\": 1105,\n      \"des\": -504,\n      \"tAsc\": 1105,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 504,\n      \"xH\": 379,\n      \"capH\": 546,\n      \"yMin\": -504,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maname\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": 0,\n      \"tAsc\": 1200,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 342,\n      \"xH\": 424,\n      \"capH\": 578,\n      \"yMin\": -307,\n      \"yMax\": 1110,\n      \"hAsc\": 1200,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mandali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 790,\n      \"asc\": 1087,\n      \"des\": -475,\n      \"tAsc\": 1087,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 1087,\n      \"wDes\": 475,\n      \"xH\": 382,\n      \"capH\": 550,\n      \"yMin\": -475,\n      \"yMax\": 1087,\n      \"hAsc\": 1087,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manjari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -750,\n      \"tAsc\": 1500,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2076,\n      \"wDes\": 1285,\n      \"xH\": 1024,\n      \"capH\": 1385,\n      \"yMin\": -1231,\n      \"yMax\": 1978,\n      \"hAsc\": 1500,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manrope\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2132,\n      \"des\": -600,\n      \"tAsc\": 2132,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2132,\n      \"wDes\": 600,\n      \"xH\": 1080,\n      \"capH\": 1440,\n      \"yMin\": -550,\n      \"yMax\": 2241,\n      \"hAsc\": 2132,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mansalva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1112,\n      \"des\": -466,\n      \"tAsc\": 1112,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 435,\n      \"xH\": 384,\n      \"capH\": 702,\n      \"yMin\": -435,\n      \"yMax\": 1112,\n      \"hAsc\": 1112,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manuale\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -236,\n      \"tAsc\": 980,\n      \"tDes\": -236,\n      \"tLGap\": 221,\n      \"wAsc\": 980,\n      \"wDes\": 236,\n      \"xH\": 491,\n      \"capH\": 611,\n      \"yMin\": -236,\n      \"yMax\": 980,\n      \"hAsc\": 980,\n      \"hDes\": -236,\n      \"lGap\": 221\n    }\n  },\n  {\n    \"family\": \"Manufacturing Consent\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1100,\n      \"des\": -340,\n      \"tAsc\": 1100,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 415,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -415,\n      \"yMax\": 1079,\n      \"hAsc\": 1100,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marcellus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1995,\n      \"des\": -573,\n      \"tAsc\": 1995,\n      \"tDes\": -573,\n      \"tLGap\": 0,\n      \"wAsc\": 1995,\n      \"wDes\": 573,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -573,\n      \"yMax\": 1995,\n      \"hAsc\": 1995,\n      \"hDes\": -573,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marcellus SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1995,\n      \"des\": -573,\n      \"tAsc\": 1995,\n      \"tDes\": -573,\n      \"tLGap\": 0,\n      \"wAsc\": 1995,\n      \"wDes\": 573,\n      \"xH\": 1075,\n      \"capH\": 1434,\n      \"yMin\": -573,\n      \"yMax\": 1995,\n      \"hAsc\": 1995,\n      \"hDes\": -573,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marck Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -385,\n      \"tAsc\": 864,\n      \"tDes\": -385,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 385,\n      \"xH\": 263,\n      \"capH\": 638,\n      \"yMin\": -385,\n      \"yMax\": 864,\n      \"hAsc\": 864,\n      \"hDes\": -385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Margarine\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2075,\n      \"des\": -678,\n      \"tAsc\": 2075,\n      \"tDes\": -678,\n      \"tLGap\": 0,\n      \"wAsc\": 2075,\n      \"wDes\": 678,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -678,\n      \"yMax\": 2075,\n      \"hAsc\": 2075,\n      \"hDes\": -678,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marhey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -640,\n      \"tAsc\": 1100,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 700,\n      \"xH\": 450,\n      \"capH\": 750,\n      \"yMin\": -700,\n      \"yMax\": 1097,\n      \"hAsc\": 1100,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Markazi Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1718,\n      \"des\": -740,\n      \"tAsc\": 1718,\n      \"tDes\": -740,\n      \"tLGap\": 0,\n      \"wAsc\": 1695,\n      \"wDes\": 963,\n      \"xH\": 746,\n      \"capH\": 990,\n      \"yMin\": -893,\n      \"yMax\": 1664,\n      \"hAsc\": 1718,\n      \"hDes\": -740,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marko One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2019,\n      \"des\": -727,\n      \"tAsc\": 2019,\n      \"tDes\": -727,\n      \"tLGap\": 0,\n      \"wAsc\": 2019,\n      \"wDes\": 727,\n      \"xH\": 713,\n      \"capH\": 1475,\n      \"yMin\": -727,\n      \"yMax\": 2019,\n      \"hAsc\": 2019,\n      \"hDes\": -727,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marmelad\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -221,\n      \"tAsc\": 972,\n      \"tDes\": -221,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 252,\n      \"xH\": 502,\n      \"capH\": 709,\n      \"yMin\": -252,\n      \"yMax\": 1106,\n      \"hAsc\": 972,\n      \"hDes\": -221,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martel\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -562,\n      \"tAsc\": 1125,\n      \"tDes\": -562,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 562,\n      \"xH\": 546,\n      \"capH\": 758,\n      \"yMin\": -542,\n      \"yMax\": 1050,\n      \"hAsc\": 1125,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martel Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -674,\n      \"tAsc\": 1150,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 674,\n      \"xH\": 534,\n      \"capH\": 680,\n      \"yMin\": -519,\n      \"yMax\": 1071,\n      \"hAsc\": 1150,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martian Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 250,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -251,\n      \"yMax\": 1088,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marvel\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -259,\n      \"tAsc\": 951,\n      \"tDes\": -259,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 259,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -259,\n      \"yMax\": 951,\n      \"hAsc\": 951,\n      \"hDes\": -259,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Matangi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -360,\n      \"tAsc\": 1200,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 702,\n      \"xH\": 840,\n      \"capH\": 948,\n      \"yMin\": -740,\n      \"yMax\": 1332,\n      \"hAsc\": 1200,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mate\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -262,\n      \"tAsc\": 958,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1041,\n      \"wDes\": 307,\n      \"xH\": 456,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 1039,\n      \"hAsc\": 958,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mate SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -262,\n      \"tAsc\": 958,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 262,\n      \"xH\": 473,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 1039,\n      \"hAsc\": 958,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Matemasie\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -230,\n      \"tAsc\": 1250,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1273,\n      \"wDes\": 241,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 1272,\n      \"hAsc\": 1250,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -3,\n      \"yMax\": 515,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Outlined\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Round\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Sharp\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Two Tone\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 961,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Outlined\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 961,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Rounded\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 962,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Sharp\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 985,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maven Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -210,\n      \"tAsc\": 965,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 233,\n      \"xH\": 499,\n      \"capH\": 667,\n      \"yMin\": -217,\n      \"yMax\": 1030,\n      \"hAsc\": 965,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"McLaren\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2216,\n      \"des\": -722,\n      \"tAsc\": 2216,\n      \"tDes\": -722,\n      \"tLGap\": 0,\n      \"wAsc\": 2216,\n      \"wDes\": 722,\n      \"xH\": 1042,\n      \"capH\": 1445,\n      \"yMin\": -729,\n      \"yMax\": 2216,\n      \"hAsc\": 2216,\n      \"hDes\": -722,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mea Culpa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -400,\n      \"tAsc\": 1000,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1098,\n      \"wDes\": 593,\n      \"xH\": 300,\n      \"capH\": 800,\n      \"yMin\": -593,\n      \"yMax\": 1098,\n      \"hAsc\": 1000,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meddon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2860,\n      \"des\": -1457,\n      \"tAsc\": 2860,\n      \"tDes\": -1457,\n      \"tLGap\": 0,\n      \"wAsc\": 2860,\n      \"wDes\": 1457,\n      \"xH\": 756,\n      \"capH\": 2177,\n      \"yMin\": -1457,\n      \"yMax\": 3565,\n      \"hAsc\": 2860,\n      \"hDes\": -1457,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MedievalSharp\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1771,\n      \"des\": -543,\n      \"tAsc\": 1771,\n      \"tDes\": -543,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 543,\n      \"xH\": 224,\n      \"capH\": 201,\n      \"yMin\": -467,\n      \"yMax\": 1951,\n      \"hAsc\": 1771,\n      \"hDes\": -543,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Medula One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 846,\n      \"des\": -162,\n      \"tAsc\": 846,\n      \"tDes\": -162,\n      \"tLGap\": 0,\n      \"wAsc\": 846,\n      \"wDes\": 162,\n      \"xH\": 490,\n      \"capH\": 650,\n      \"yMin\": -162,\n      \"yMax\": 846,\n      \"hAsc\": 846,\n      \"hDes\": -162,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meera Inimai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1986,\n      \"des\": -1200,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1986,\n      \"wDes\": 1200,\n      \"xH\": 1056,\n      \"capH\": 1460,\n      \"yMin\": -1200,\n      \"yMax\": 1986,\n      \"hAsc\": 1986,\n      \"hDes\": -1200,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Megrim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 90,\n      \"wAsc\": 880,\n      \"wDes\": 200,\n      \"xH\": 580,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 880,\n      \"hAsc\": 880,\n      \"hDes\": -200,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Meie Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1814,\n      \"des\": -780,\n      \"tAsc\": 1814,\n      \"tDes\": -780,\n      \"tLGap\": 0,\n      \"wAsc\": 1814,\n      \"wDes\": 780,\n      \"xH\": 354,\n      \"capH\": 862,\n      \"yMin\": -780,\n      \"yMax\": 1814,\n      \"hAsc\": 1814,\n      \"hDes\": -780,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Menbere\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1229,\n      \"des\": -338,\n      \"tAsc\": 1229,\n      \"tDes\": -338,\n      \"tLGap\": 0,\n      \"wAsc\": 1340,\n      \"wDes\": 380,\n      \"xH\": 570,\n      \"capH\": 758,\n      \"yMin\": -341,\n      \"yMax\": 1288,\n      \"hAsc\": 1229,\n      \"hDes\": -338,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meow Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -370,\n      \"tAsc\": 830,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 947,\n      \"wDes\": 662,\n      \"xH\": 320,\n      \"capH\": 560,\n      \"yMin\": -622,\n      \"yMax\": 947,\n      \"hAsc\": 830,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merienda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1102,\n      \"des\": -342,\n      \"tAsc\": 1102,\n      \"tDes\": -342,\n      \"tLGap\": 0,\n      \"wAsc\": 1436,\n      \"wDes\": 418,\n      \"xH\": 599,\n      \"capH\": 847,\n      \"yMin\": -347,\n      \"yMax\": 1403,\n      \"hAsc\": 1102,\n      \"hDes\": -342,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merriweather\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1968,\n      \"des\": -546,\n      \"tAsc\": 1968,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 2476,\n      \"wDes\": 988,\n      \"xH\": 1111,\n      \"capH\": 1486,\n      \"yMin\": -969,\n      \"yMax\": 2429,\n      \"hAsc\": 1968,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merriweather Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1968,\n      \"des\": -546,\n      \"tAsc\": 1968,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 2580,\n      \"wDes\": 660,\n      \"xH\": 1114,\n      \"capH\": 1486,\n      \"yMin\": -567,\n      \"yMax\": 2472,\n      \"hAsc\": 1968,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metal\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2600,\n      \"des\": -1600,\n      \"tAsc\": 2600,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 3166,\n      \"wDes\": 1600,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1600,\n      \"yMax\": 3166,\n      \"hAsc\": 2600,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metal Mania\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 965,\n      \"des\": -303,\n      \"tAsc\": 965,\n      \"tDes\": -303,\n      \"tLGap\": 0,\n      \"wAsc\": 965,\n      \"wDes\": 303,\n      \"xH\": 620,\n      \"capH\": 820,\n      \"yMin\": -303,\n      \"yMax\": 965,\n      \"hAsc\": 965,\n      \"hDes\": -303,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metamorphous\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1972,\n      \"des\": -588,\n      \"tAsc\": 1972,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1972,\n      \"wDes\": 588,\n      \"xH\": 1208,\n      \"capH\": 1530,\n      \"yMin\": -588,\n      \"yMax\": 1972,\n      \"hAsc\": 1972,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metrophobic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2065,\n      \"des\": -460,\n      \"tAsc\": 2065,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 2284,\n      \"wDes\": 597,\n      \"xH\": 1011,\n      \"capH\": 1441,\n      \"yMin\": -597,\n      \"yMax\": 2284,\n      \"hAsc\": 2065,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Michroma\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2368,\n      \"des\": -544,\n      \"tAsc\": 2368,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 3040,\n      \"wDes\": 576,\n      \"xH\": 1152,\n      \"capH\": 1536,\n      \"yMin\": -576,\n      \"yMax\": 3040,\n      \"hAsc\": 2368,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Micro 5\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1650,\n      \"asc\": 1190,\n      \"des\": -460,\n      \"tAsc\": 1190,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1350,\n      \"wDes\": 460,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -450,\n      \"yMax\": 1350,\n      \"hAsc\": 1190,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Micro 5 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1650,\n      \"asc\": 1190,\n      \"des\": -460,\n      \"tAsc\": 1190,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1350,\n      \"wDes\": 460,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -460,\n      \"yMax\": 1350,\n      \"hAsc\": 1190,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Milonga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -260,\n      \"tAsc\": 990,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 260,\n      \"xH\": 458,\n      \"capH\": 809,\n      \"yMin\": -260,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miltonian\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -274,\n      \"tAsc\": 918,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 274,\n      \"xH\": 454,\n      \"capH\": 689,\n      \"yMin\": -274,\n      \"yMax\": 918,\n      \"hAsc\": 918,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miltonian Tattoo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -274,\n      \"tAsc\": 918,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 274,\n      \"xH\": 454,\n      \"capH\": 689,\n      \"yMin\": -274,\n      \"yMax\": 918,\n      \"hAsc\": 918,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mina\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -515,\n      \"tAsc\": 1075,\n      \"tDes\": -515,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 539,\n      \"yMin\": -487,\n      \"yMax\": 1002,\n      \"hAsc\": 1075,\n      \"hDes\": -515,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mingzat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1427,\n      \"des\": -670,\n      \"tAsc\": 1427,\n      \"tDes\": -670,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 670,\n      \"xH\": 705,\n      \"capH\": 1100,\n      \"yMin\": -670,\n      \"yMax\": 1530,\n      \"hAsc\": 1427,\n      \"hDes\": -670,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miniver\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -474,\n      \"tAsc\": 1019,\n      \"tDes\": -474,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 474,\n      \"xH\": 501,\n      \"capH\": 782,\n      \"yMin\": -474,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -474,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miranda Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -240,\n      \"tAsc\": 990,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 240,\n      \"xH\": 520,\n      \"capH\": 720,\n      \"yMin\": -230,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miriam Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 969,\n      \"des\": -344,\n      \"tAsc\": 969,\n      \"tDes\": -344,\n      \"tLGap\": 0,\n      \"wAsc\": 969,\n      \"wDes\": 344,\n      \"xH\": 566,\n      \"capH\": 695,\n      \"yMin\": -335,\n      \"yMax\": 952,\n      \"hAsc\": 969,\n      \"hDes\": -344,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mirza\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 547,\n      \"des\": -453,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -571,\n      \"yMax\": 1088,\n      \"hAsc\": 547,\n      \"hDes\": -453,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Miss Fajardose\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -389,\n      \"tAsc\": 859,\n      \"tDes\": -389,\n      \"tLGap\": 0,\n      \"wAsc\": 859,\n      \"wDes\": 389,\n      \"xH\": 158,\n      \"capH\": 658,\n      \"yMin\": -389,\n      \"yMax\": 859,\n      \"hAsc\": 859,\n      \"hDes\": -389,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mitr\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -420,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 420,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1079,\n      \"hAsc\": 1150,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mochiy Pop One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -295,\n      \"yMax\": 1142,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mochiy Pop P One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -295,\n      \"yMax\": 1142,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Modak\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2035,\n      \"des\": -1049,\n      \"tAsc\": 2035,\n      \"tDes\": -1049,\n      \"tLGap\": 0,\n      \"wAsc\": 2035,\n      \"wDes\": 1049,\n      \"xH\": 1099,\n      \"capH\": 1290,\n      \"yMin\": -1049,\n      \"yMax\": 2035,\n      \"hAsc\": 2035,\n      \"hDes\": -1049,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Modern Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1815,\n      \"des\": -508,\n      \"tAsc\": 1815,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 1815,\n      \"wDes\": 508,\n      \"xH\": 1089,\n      \"capH\": 1511,\n      \"yMin\": -435,\n      \"yMax\": 1950,\n      \"hAsc\": 1815,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moderustic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1067,\n      \"wDes\": 401,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -401,\n      \"yMax\": 1067,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mogra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 850,\n      \"wDes\": 350,\n      \"xH\": 565,\n      \"capH\": 705,\n      \"yMin\": -574,\n      \"yMax\": 1063,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Mohave\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1980,\n      \"des\": -806,\n      \"tAsc\": 1980,\n      \"tDes\": -806,\n      \"tLGap\": 0,\n      \"wAsc\": 1980,\n      \"wDes\": 806,\n      \"xH\": 1080,\n      \"capH\": 1500,\n      \"yMin\": -806,\n      \"yMax\": 1975,\n      \"hAsc\": 1980,\n      \"hDes\": -806,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moirai One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 488,\n      \"capH\": 778,\n      \"yMin\": -343,\n      \"yMax\": 984,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Molengo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1928,\n      \"des\": -522,\n      \"tAsc\": 1928,\n      \"tDes\": -522,\n      \"tLGap\": 0,\n      \"wAsc\": 1928,\n      \"wDes\": 522,\n      \"xH\": 938,\n      \"capH\": 1391,\n      \"yMin\": -522,\n      \"yMax\": 1928,\n      \"hAsc\": 1928,\n      \"hDes\": -522,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Molle\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"italic\"],\n    \"variants\": [[1, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1852,\n      \"des\": -701,\n      \"tAsc\": 1852,\n      \"tDes\": -701,\n      \"tLGap\": 0,\n      \"wAsc\": 1852,\n      \"wDes\": 701,\n      \"xH\": 910,\n      \"capH\": 1588,\n      \"yMin\": -701,\n      \"yMax\": 1852,\n      \"hAsc\": 1852,\n      \"hDes\": -701,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Signature\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -285,\n      \"tAsc\": 1145,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1345,\n      \"wDes\": 380,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -379,\n      \"yMax\": 1344,\n      \"hAsc\": 1145,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Trust Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 555,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -554,\n      \"yMax\": 1165,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Trust Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1228,\n      \"wDes\": 554,\n      \"xH\": 530,\n      \"capH\": 750,\n      \"yMin\": -536,\n      \"yMax\": 1227,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mona Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -320,\n      \"tAsc\": 1090,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 320,\n      \"xH\": 525,\n      \"capH\": 729,\n      \"yMin\": -242,\n      \"yMax\": 1047,\n      \"hAsc\": 1090,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monda\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2461,\n      \"des\": -875,\n      \"tAsc\": 2461,\n      \"tDes\": -875,\n      \"tLGap\": 0,\n      \"wAsc\": 2480,\n      \"wDes\": 875,\n      \"xH\": 1060,\n      \"capH\": 1446,\n      \"yMin\": -770,\n      \"yMax\": 2383,\n      \"hAsc\": 2461,\n      \"hDes\": -875,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monofett\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2001,\n      \"des\": -315,\n      \"tAsc\": 2001,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 2001,\n      \"wDes\": 315,\n      \"xH\": 1370,\n      \"capH\": 1370,\n      \"yMin\": -315,\n      \"yMax\": 1983,\n      \"hAsc\": 2001,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monomakh\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -341,\n      \"tAsc\": 932,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 334,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -334,\n      \"yMax\": 984,\n      \"hAsc\": 932,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monomaniac One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 518,\n      \"capH\": 676,\n      \"yMin\": -274,\n      \"yMax\": 876,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monoton\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2366,\n      \"des\": -822,\n      \"tAsc\": 2366,\n      \"tDes\": -822,\n      \"tLGap\": 0,\n      \"wAsc\": 2366,\n      \"wDes\": 822,\n      \"xH\": 1440,\n      \"capH\": 1656,\n      \"yMin\": -822,\n      \"yMax\": 2366,\n      \"hAsc\": 2366,\n      \"hDes\": -822,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monsieur La Doulaise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -513,\n      \"tAsc\": 1048,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 513,\n      \"xH\": 164,\n      \"capH\": 729,\n      \"yMin\": -513,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montaga\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 978,\n      \"des\": -254,\n      \"tAsc\": 978,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 978,\n      \"wDes\": 254,\n      \"xH\": 466,\n      \"capH\": 700,\n      \"yMin\": -254,\n      \"yMax\": 978,\n      \"hAsc\": 978,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montagu Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -300,\n      \"tAsc\": 982,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1136,\n      \"wDes\": 318,\n      \"xH\": 518,\n      \"capH\": 682,\n      \"yMin\": -262,\n      \"yMax\": 1113,\n      \"hAsc\": 982,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MonteCarlo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -500,\n      \"tAsc\": 1200,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1795,\n      \"wDes\": 1290,\n      \"xH\": 315,\n      \"capH\": 750,\n      \"yMin\": -1293,\n      \"yMax\": 1794,\n      \"hAsc\": 1200,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montez\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1831,\n      \"des\": -848,\n      \"tAsc\": 1831,\n      \"tDes\": -848,\n      \"tLGap\": 0,\n      \"wAsc\": 1831,\n      \"wDes\": 848,\n      \"xH\": 766,\n      \"capH\": 1456,\n      \"yMin\": -848,\n      \"yMax\": 1831,\n      \"hAsc\": 1831,\n      \"hDes\": -848,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 453,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -459,\n      \"yMax\": 1018,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat Alternates\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 270,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -262,\n      \"yMax\": 1043,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat Underline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 453,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -370,\n      \"yMax\": 1043,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moo Lah Lah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -300,\n      \"tAsc\": 920,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1253,\n      \"wDes\": 367,\n      \"xH\": 565,\n      \"capH\": 650,\n      \"yMin\": -367,\n      \"yMax\": 1253,\n      \"hAsc\": 920,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mooli\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1928,\n      \"des\": -472,\n      \"tAsc\": 1928,\n      \"tDes\": -472,\n      \"tLGap\": 0,\n      \"wAsc\": 1960,\n      \"wDes\": 625,\n      \"xH\": 1026,\n      \"capH\": 1456,\n      \"yMin\": -625,\n      \"yMax\": 1960,\n      \"hAsc\": 1928,\n      \"hDes\": -472,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moon Dance\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -370,\n      \"tAsc\": 970,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 1128,\n      \"wDes\": 595,\n      \"xH\": 350,\n      \"capH\": 605,\n      \"yMin\": -595,\n      \"yMax\": 1128,\n      \"hAsc\": 970,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moul\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1201,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moulpali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2900,\n      \"des\": -1600,\n      \"tAsc\": 2900,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 2950,\n      \"wDes\": 1600,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1600,\n      \"yMax\": 2950,\n      \"hAsc\": 2900,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mountains of Christmas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1066,\n      \"des\": -354,\n      \"tAsc\": 1066,\n      \"tDes\": -354,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 354,\n      \"xH\": 515,\n      \"capH\": 743,\n      \"yMin\": -347,\n      \"yMax\": 1066,\n      \"hAsc\": 1066,\n      \"hDes\": -354,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mouse Memoirs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1917,\n      \"des\": -428,\n      \"tAsc\": 1917,\n      \"tDes\": -428,\n      \"tLGap\": 0,\n      \"wAsc\": 1917,\n      \"wDes\": 428,\n      \"xH\": 1044,\n      \"capH\": 1448,\n      \"yMin\": -428,\n      \"yMax\": 1917,\n      \"hAsc\": 1917,\n      \"hDes\": -428,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mozilla Headline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1323,\n      \"wDes\": 213,\n      \"xH\": 534,\n      \"capH\": 690,\n      \"yMin\": -213,\n      \"yMax\": 1110,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mozilla Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1339,\n      \"wDes\": 229,\n      \"xH\": 534,\n      \"capH\": 690,\n      \"yMin\": -229,\n      \"yMax\": 1110,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr Bedfort\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -661,\n      \"tAsc\": 1015,\n      \"tDes\": -661,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 661,\n      \"xH\": 245,\n      \"capH\": 770,\n      \"yMin\": -661,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -661,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr Dafoe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 981,\n      \"des\": -416,\n      \"tAsc\": 981,\n      \"tDes\": -416,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 416,\n      \"xH\": 313,\n      \"capH\": 622,\n      \"yMin\": -416,\n      \"yMax\": 981,\n      \"hAsc\": 981,\n      \"hDes\": -416,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr De Haviland\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -442,\n      \"tAsc\": 875,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 875,\n      \"wDes\": 442,\n      \"xH\": 217,\n      \"capH\": 557,\n      \"yMin\": -442,\n      \"yMax\": 891,\n      \"hAsc\": 875,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mrs Saint Delafield\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 906,\n      \"des\": -619,\n      \"tAsc\": 906,\n      \"tDes\": -619,\n      \"tLGap\": 0,\n      \"wAsc\": 906,\n      \"wDes\": 619,\n      \"xH\": 224,\n      \"capH\": 708,\n      \"yMin\": -619,\n      \"yMax\": 906,\n      \"hAsc\": 906,\n      \"hDes\": -619,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mrs Sheppards\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -378,\n      \"tAsc\": 959,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 378,\n      \"xH\": 285,\n      \"capH\": 662,\n      \"yMin\": -378,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ms Madi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -420,\n      \"tAsc\": 900,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 975,\n      \"wDes\": 535,\n      \"xH\": 335,\n      \"capH\": 640,\n      \"yMin\": -535,\n      \"yMax\": 973,\n      \"hAsc\": 900,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -508,\n      \"yMax\": 1130,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Mahee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -541,\n      \"yMax\": 956,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Malar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -351,\n      \"yMax\": 935,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Vaani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -494,\n      \"yMax\": 935,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mulish\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -250,\n      \"tAsc\": 1005,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 297,\n      \"xH\": 500,\n      \"capH\": 705,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1005,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Murecho\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 728,\n      \"yMin\": -291,\n      \"yMax\": 939,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MuseoModerno\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -445,\n      \"tAsc\": 1145,\n      \"tDes\": -445,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 445,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -381,\n      \"yMax\": 1109,\n      \"hAsc\": 1145,\n      \"hDes\": -445,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"My Soul\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -350,\n      \"tAsc\": 975,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1170,\n      \"wDes\": 515,\n      \"xH\": 360,\n      \"capH\": 760,\n      \"yMin\": -513,\n      \"yMax\": 1167,\n      \"hAsc\": 975,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mynerve\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -380,\n      \"tAsc\": 930,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 469,\n      \"xH\": 420,\n      \"capH\": 670,\n      \"yMin\": -469,\n      \"yMax\": 985,\n      \"hAsc\": 930,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mystery Quest\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 989,\n      \"des\": -409,\n      \"tAsc\": 989,\n      \"tDes\": -409,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 419,\n      \"xH\": 626,\n      \"capH\": 769,\n      \"yMin\": -409,\n      \"yMax\": 989,\n      \"hAsc\": 989,\n      \"hDes\": -409,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nabla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1263,\n      \"des\": -380,\n      \"tAsc\": 1263,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1263,\n      \"wDes\": 380,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -380,\n      \"yMax\": 1263,\n      \"hAsc\": 1263,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Namdhinggo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1600,\n      \"des\": -550,\n      \"tAsc\": 1600,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1778,\n      \"wDes\": 550,\n      \"xH\": 500,\n      \"capH\": 1150,\n      \"yMin\": -534,\n      \"yMax\": 1728,\n      \"hAsc\": 1600,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Brush Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 630,\n      \"des\": -370,\n      \"tAsc\": 630,\n      \"tDes\": -370,\n      \"tLGap\": 250,\n      \"wAsc\": 635,\n      \"wDes\": 372,\n      \"xH\": 300,\n      \"capH\": 460,\n      \"yMin\": -370,\n      \"yMax\": 632,\n      \"hAsc\": 630,\n      \"hDes\": -370,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Nanum Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 844,\n      \"des\": -156,\n      \"tAsc\": 856,\n      \"tDes\": -144,\n      \"tLGap\": 250,\n      \"wAsc\": 885,\n      \"wDes\": 198,\n      \"xH\": 542,\n      \"capH\": 743,\n      \"yMin\": -198,\n      \"yMax\": 844,\n      \"hAsc\": 844,\n      \"hDes\": -156,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Gothic Coding\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 498,\n      \"capH\": 699,\n      \"yMin\": -200,\n      \"yMax\": 801,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Myeongjo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 819,\n      \"des\": -205,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 256,\n      \"wAsc\": 932,\n      \"wDes\": 247,\n      \"xH\": 480,\n      \"capH\": 755,\n      \"yMin\": -237,\n      \"yMax\": 929,\n      \"hAsc\": 819,\n      \"hDes\": -205,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Nanum Pen Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 809,\n      \"wDes\": 202,\n      \"xH\": 476,\n      \"capH\": 674,\n      \"yMin\": -200,\n      \"yMax\": 801,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Narnoor\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1314,\n      \"des\": -237,\n      \"tAsc\": 1314,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1314,\n      \"wDes\": 237,\n      \"xH\": 553,\n      \"capH\": 735,\n      \"yMin\": -237,\n      \"yMax\": 939,\n      \"hAsc\": 1314,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nata Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 419,\n      \"xH\": 500,\n      \"capH\": 660,\n      \"yMin\": -288,\n      \"yMax\": 1014,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"National Park\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -300,\n      \"tAsc\": 1030,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1194,\n      \"wDes\": 300,\n      \"xH\": 515,\n      \"capH\": 700,\n      \"yMin\": -217,\n      \"yMax\": 1194,\n      \"hAsc\": 1030,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Neonderthaw\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1152,\n      \"wDes\": 534,\n      \"xH\": 350,\n      \"capH\": 750,\n      \"yMin\": -534,\n      \"yMax\": 1152,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nerko One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -317,\n      \"tAsc\": 894,\n      \"tDes\": -317,\n      \"tLGap\": 0,\n      \"wAsc\": 937,\n      \"wDes\": 319,\n      \"xH\": 426,\n      \"capH\": 586,\n      \"yMin\": -319,\n      \"yMax\": 937,\n      \"hAsc\": 894,\n      \"hDes\": -317,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Neucha\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 787,\n      \"des\": -292,\n      \"tAsc\": 787,\n      \"tDes\": -292,\n      \"tLGap\": 49,\n      \"wAsc\": 954,\n      \"wDes\": 296,\n      \"xH\": 523,\n      \"capH\": 720,\n      \"yMin\": -296,\n      \"yMax\": 981,\n      \"hAsc\": 787,\n      \"hDes\": -292,\n      \"lGap\": 49\n    }\n  },\n  {\n    \"family\": \"Neuton\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2106,\n      \"des\": -485,\n      \"tAsc\": 2106,\n      \"tDes\": -485,\n      \"tLGap\": 0,\n      \"wAsc\": 2106,\n      \"wDes\": 485,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -418,\n      \"yMax\": 1710,\n      \"hAsc\": 2106,\n      \"hDes\": -485,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Amsterdam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 820,\n      \"wDes\": 212,\n      \"xH\": 649,\n      \"capH\": 650,\n      \"yMin\": -212,\n      \"yMax\": 820,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Rocker\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 946,\n      \"des\": -283,\n      \"tAsc\": 946,\n      \"tDes\": -283,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 283,\n      \"xH\": 465,\n      \"capH\": 733,\n      \"yMin\": -283,\n      \"yMax\": 946,\n      \"hAsc\": 946,\n      \"hDes\": -283,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Tegomin\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 438,\n      \"capH\": 635,\n      \"yMin\": -281,\n      \"yMax\": 914,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"News Cycle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2574,\n      \"des\": -794,\n      \"tAsc\": 2574,\n      \"tDes\": -794,\n      \"tLGap\": 0,\n      \"wAsc\": 2574,\n      \"wDes\": 794,\n      \"yMin\": -794,\n      \"yMax\": 2510,\n      \"hAsc\": 2574,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Newsreader\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1470,\n      \"des\": -530,\n      \"tAsc\": 1470,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2326,\n      \"wDes\": 531,\n      \"xH\": 852,\n      \"capH\": 1340,\n      \"yMin\": -519,\n      \"yMax\": 2131,\n      \"hAsc\": 1470,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Niconne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -585,\n      \"tAsc\": 1898,\n      \"tDes\": -585,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 585,\n      \"xH\": 218,\n      \"capH\": 1442,\n      \"yMin\": -585,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -585,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Niramit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1105,\n      \"des\": -195,\n      \"tAsc\": 1105,\n      \"tDes\": -195,\n      \"tLGap\": 0,\n      \"wAsc\": 1246,\n      \"wDes\": 513,\n      \"xH\": 485,\n      \"capH\": 700,\n      \"yMin\": -476,\n      \"yMax\": 1205,\n      \"hAsc\": 1105,\n      \"hDes\": -195,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nixie One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -210,\n      \"tAsc\": 926,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 926,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 920,\n      \"hAsc\": 926,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nobile\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1731,\n      \"des\": -578,\n      \"tAsc\": 1614,\n      \"tDes\": -502,\n      \"tLGap\": 0,\n      \"wAsc\": 1731,\n      \"wDes\": 578,\n      \"xH\": 1169,\n      \"capH\": 1579,\n      \"yMin\": -617,\n      \"yMax\": 2353,\n      \"hAsc\": 1731,\n      \"hDes\": -578,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nokora\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1907,\n      \"des\": -800,\n      \"tAsc\": 1907,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 810,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -810,\n      \"yMax\": 1900,\n      \"hAsc\": 1907,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Norican\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -791,\n      \"tAsc\": 2095,\n      \"tDes\": -791,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 791,\n      \"xH\": 810,\n      \"capH\": 1518,\n      \"yMin\": -791,\n      \"yMax\": 2097,\n      \"hAsc\": 2095,\n      \"hDes\": -791,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nosifer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2236,\n      \"des\": -1328,\n      \"tAsc\": 2236,\n      \"tDes\": -1328,\n      \"tLGap\": 0,\n      \"wAsc\": 2236,\n      \"wDes\": 1328,\n      \"xH\": 925,\n      \"capH\": 854,\n      \"yMin\": -1328,\n      \"yMax\": 2236,\n      \"hAsc\": 2236,\n      \"hDes\": -1328,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Notable\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1143,\n      \"des\": -157,\n      \"tAsc\": 1143,\n      \"tDes\": -157,\n      \"tLGap\": 0,\n      \"wAsc\": 1275,\n      \"wDes\": 300,\n      \"xH\": 356,\n      \"capH\": 700,\n      \"yMin\": -213,\n      \"yMax\": 907,\n      \"hAsc\": 1143,\n      \"hDes\": -157,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nothing You Could Do\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 959,\n      \"des\": -407,\n      \"tAsc\": 962,\n      \"tDes\": -407,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 407,\n      \"xH\": 462,\n      \"capH\": 758,\n      \"yMin\": -407,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -407,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noticia Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2202,\n      \"des\": -593,\n      \"tAsc\": 2202,\n      \"tDes\": -593,\n      \"tLGap\": 0,\n      \"wAsc\": 2202,\n      \"wDes\": 593,\n      \"xH\": 1085,\n      \"capH\": 1353,\n      \"yMin\": -593,\n      \"yMax\": 2167,\n      \"hAsc\": 2202,\n      \"hDes\": -593,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Color Emoji\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 512,\n      \"capH\": 717,\n      \"yMin\": -250,\n      \"yMax\": 950,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Emoji\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 500,\n      \"xH\": 0,\n      \"capH\": 1900,\n      \"yMin\": -415,\n      \"yMax\": 1815,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Kufi Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1282,\n      \"des\": -615,\n      \"tAsc\": 1282,\n      \"tDes\": -615,\n      \"tLGap\": 0,\n      \"wAsc\": 1507,\n      \"wDes\": 650,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -650,\n      \"yMax\": 1507,\n      \"hAsc\": 1282,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Music\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1389,\n      \"des\": -398,\n      \"tAsc\": 1389,\n      \"tDes\": -398,\n      \"tLGap\": 0,\n      \"wAsc\": 1645,\n      \"wDes\": 709,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -709,\n      \"yMax\": 1645,\n      \"hAsc\": 1389,\n      \"hDes\": -398,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Naskh Arabic\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -634,\n      \"tAsc\": 1069,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1405,\n      \"wDes\": 634,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -590,\n      \"yMax\": 1405,\n      \"hAsc\": 1069,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Nastaliq Urdu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1904,\n      \"des\": -596,\n      \"tAsc\": 1904,\n      \"tDes\": -596,\n      \"tLGap\": 0,\n      \"wAsc\": 1904,\n      \"wDes\": 596,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1382,\n      \"yMax\": 1808,\n      \"hAsc\": 1904,\n      \"hDes\": -596,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Rashi Hebrew\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -290,\n      \"tAsc\": 896,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 290,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 896,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1124,\n      \"wDes\": 395,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -508,\n      \"yMax\": 1067,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Adlam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 575,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1004,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Adlam Unjoined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 575,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1004,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Anatolian Hieroglyphs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1153,\n      \"des\": -253,\n      \"tAsc\": 1153,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 253,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 1148,\n      \"hAsc\": 1153,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1374,\n      \"des\": -738,\n      \"tAsc\": 1374,\n      \"tDes\": -738,\n      \"tLGap\": 0,\n      \"wAsc\": 1431,\n      \"wDes\": 738,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -548,\n      \"yMax\": 1431,\n      \"hAsc\": 1374,\n      \"hDes\": -738,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Armenian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -245,\n      \"yMax\": 995,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Avestan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 652,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Balinese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1363,\n      \"des\": -838,\n      \"tAsc\": 1363,\n      \"tDes\": -838,\n      \"tLGap\": 0,\n      \"wAsc\": 1363,\n      \"wDes\": 838,\n      \"xH\": 536,\n      \"capH\": 700,\n      \"yMin\": -830,\n      \"yMax\": 1289,\n      \"hAsc\": 1363,\n      \"hDes\": -838,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bamum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1035,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bassa Vah\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 674,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Batak\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 319,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -319,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bengali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -408,\n      \"tAsc\": 917,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -408,\n      \"yMax\": 995,\n      \"hAsc\": 917,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bhaiksuki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -460,\n      \"tAsc\": 960,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 630,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -630,\n      \"yMax\": 995,\n      \"hAsc\": 960,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Brahmi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -306,\n      \"tAsc\": 1069,\n      \"tDes\": -306,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 306,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -303,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -306,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Buginese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Buhid\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Canadian Aboriginal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 500,\n      \"capH\": 714,\n      \"yMin\": -267,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Carian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Caucasian Albanian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -274,\n      \"tAsc\": 976,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1071,\n      \"wDes\": 274,\n      \"xH\": 410,\n      \"capH\": 714,\n      \"yMin\": -271,\n      \"yMax\": 1071,\n      \"hAsc\": 976,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Chakma\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1140,\n      \"des\": -320,\n      \"tAsc\": 1140,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 467,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -467,\n      \"yMax\": 1107,\n      \"hAsc\": 1140,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1117,\n      \"des\": -351,\n      \"tAsc\": 1117,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 1368,\n      \"wDes\": 645,\n      \"xH\": 536,\n      \"capH\": 594,\n      \"yMin\": -494,\n      \"yMax\": 1242,\n      \"hAsc\": 1117,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cherokee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 535,\n      \"capH\": 714,\n      \"yMin\": -269,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Chorasmian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 550,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Coptic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1044,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cuneiform\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1596,\n      \"des\": -690,\n      \"tAsc\": 1596,\n      \"tDes\": -690,\n      \"tLGap\": 0,\n      \"wAsc\": 1596,\n      \"wDes\": 690,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -690,\n      \"yMax\": 1596,\n      \"hAsc\": 1596,\n      \"hDes\": -690,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cypriot\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 736,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cypro Minoan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Deseret\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 558,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -530,\n      \"yMax\": 1347,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1072,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Duployan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1729,\n      \"wDes\": 833,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -833,\n      \"yMax\": 1672,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Egyptian Hieroglyphs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -326,\n      \"tAsc\": 1324,\n      \"tDes\": -326,\n      \"tLGap\": 0,\n      \"wAsc\": 1324,\n      \"wDes\": 326,\n      \"xH\": 536,\n      \"capH\": 900,\n      \"yMin\": -326,\n      \"yMax\": 1324,\n      \"hAsc\": 1324,\n      \"hDes\": -326,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Elbasan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 847,\n      \"des\": -270,\n      \"tAsc\": 847,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 714,\n      \"yMin\": -267,\n      \"yMax\": 995,\n      \"hAsc\": 847,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Elymaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 290,\n      \"xH\": 570,\n      \"capH\": 570,\n      \"yMin\": -290,\n      \"yMax\": 995,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ethiopic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Georgian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1086,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 995,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Glagolitic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 646,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Grantha\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1290,\n      \"des\": -534,\n      \"tAsc\": 1290,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1755,\n      \"xH\": 566,\n      \"capH\": 714,\n      \"yMin\": -1755,\n      \"yMax\": 1135,\n      \"hAsc\": 1290,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gujarati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 1076,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 592,\n      \"yMin\": -394,\n      \"yMax\": 995,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gunjala Gondi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1014,\n      \"des\": -252,\n      \"tAsc\": 1014,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 286,\n      \"xH\": 561,\n      \"capH\": 622,\n      \"yMin\": -255,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gurmukhi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 896,\n      \"wDes\": 408,\n      \"xH\": 622,\n      \"capH\": 622,\n      \"yMin\": -398,\n      \"yMax\": 995,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hanifi Rohingya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 293,\n      \"xH\": 525,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1089,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hanunoo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hatran\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 560,\n      \"capH\": 763,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hebrew\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -292,\n      \"yMax\": 1068,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans HK\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Imperial Aramaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -276,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Indic Siyaq Numbers\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1215,\n      \"des\": -347,\n      \"tAsc\": 1215,\n      \"tDes\": -347,\n      \"tLGap\": 0,\n      \"wAsc\": 1215,\n      \"wDes\": 347,\n      \"xH\": 553,\n      \"capH\": 964,\n      \"yMin\": -303,\n      \"yMax\": 1210,\n      \"hAsc\": 1215,\n      \"hDes\": -347,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Inscriptional Pahlavi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -352,\n      \"tAsc\": 1069,\n      \"tDes\": -352,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 352,\n      \"xH\": 536,\n      \"capH\": 760,\n      \"yMin\": -352,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -352,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Inscriptional Parthian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -301,\n      \"tAsc\": 1069,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 301,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -301,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Javanese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1120,\n      \"des\": -916,\n      \"tAsc\": 1120,\n      \"tDes\": -916,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 916,\n      \"xH\": 536,\n      \"capH\": 750,\n      \"yMin\": -916,\n      \"yMax\": 1044,\n      \"hAsc\": 1120,\n      \"hDes\": -916,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kaithi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -425,\n      \"tAsc\": 1077,\n      \"tDes\": -425,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 425,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -425,\n      \"yMax\": 1024,\n      \"hAsc\": 1077,\n      \"hDes\": -425,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kannada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 809,\n      \"des\": -540,\n      \"tAsc\": 809,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 540,\n      \"xH\": 551,\n      \"capH\": 690,\n      \"yMin\": -532,\n      \"yMax\": 995,\n      \"hAsc\": 809,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kawi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -900,\n      \"tAsc\": 1100,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 1411,\n      \"wDes\": 1034,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1034,\n      \"yMax\": 1266,\n      \"hAsc\": 1100,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kayah Li\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kharoshthi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -301,\n      \"tAsc\": 1069,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 301,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -301,\n      \"yMax\": 1046,\n      \"hAsc\": 1069,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khmer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1155,\n      \"wDes\": 707,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -691,\n      \"yMax\": 1155,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khojki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1409,\n      \"des\": -447,\n      \"tAsc\": 1409,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1409,\n      \"wDes\": 447,\n      \"xH\": 545,\n      \"capH\": 714,\n      \"yMin\": -445,\n      \"yMax\": 1404,\n      \"hAsc\": 1409,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khudawadi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -373,\n      \"tAsc\": 944,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 373,\n      \"xH\": 536,\n      \"capH\": 620,\n      \"yMin\": -370,\n      \"yMax\": 995,\n      \"hAsc\": 944,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans KR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lao\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1183,\n      \"des\": -462,\n      \"tAsc\": 1183,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1183,\n      \"wDes\": 462,\n      \"xH\": 548,\n      \"capH\": 714,\n      \"yMin\": -438,\n      \"yMax\": 1107,\n      \"hAsc\": 1183,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lao Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -350,\n      \"tAsc\": 1250,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1380,\n      \"wDes\": 620,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -433,\n      \"yMax\": 1182,\n      \"hAsc\": 1250,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lepcha\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -450,\n      \"tAsc\": 1069,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 450,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -425,\n      \"yMax\": 1028,\n      \"hAsc\": 1069,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Limbu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Linear A\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Linear B\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 1020,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lisu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lycian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -16,\n      \"yMax\": 729,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lydian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mahajani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 757,\n      \"des\": -243,\n      \"tAsc\": 757,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 243,\n      \"xH\": 536,\n      \"capH\": 600,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 757,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Malayalam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -383,\n      \"tAsc\": 864,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 383,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -367,\n      \"yMax\": 995,\n      \"hAsc\": 864,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mandaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 724,\n      \"des\": -423,\n      \"tAsc\": 724,\n      \"tDes\": -423,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 423,\n      \"xH\": 536,\n      \"capH\": 694,\n      \"yMin\": -403,\n      \"yMax\": 995,\n      \"hAsc\": 724,\n      \"hDes\": -423,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Manichaean\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -340,\n      \"tAsc\": 790,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 340,\n      \"xH\": 439,\n      \"capH\": 625,\n      \"yMin\": -337,\n      \"yMax\": 995,\n      \"hAsc\": 790,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Marchen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1107,\n      \"des\": -534,\n      \"tAsc\": 1107,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1107,\n      \"wDes\": 1025,\n      \"xH\": 678,\n      \"capH\": 678,\n      \"yMin\": -1025,\n      \"yMax\": 995,\n      \"hAsc\": 1107,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Masaram Gondi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 357,\n      \"capH\": 630,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Math\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -423,\n      \"tAsc\": 1069,\n      \"tDes\": -423,\n      \"tLGap\": 0,\n      \"wAsc\": 3105,\n      \"wDes\": 2550,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -2548,\n      \"yMax\": 3104,\n      \"hAsc\": 1069,\n      \"hDes\": -423,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mayan Numerals\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Medefaidrin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 713,\n      \"yMin\": -408,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Meetei Mayek\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -321,\n      \"tAsc\": 1069,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 321,\n      \"xH\": 536,\n      \"capH\": 659,\n      \"yMin\": -318,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mende Kikakui\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -237,\n      \"tAsc\": 1030,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1017,\n      \"hAsc\": 1030,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Meroitic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -415,\n      \"tAsc\": 928,\n      \"tDes\": -415,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 415,\n      \"xH\": 536,\n      \"capH\": 680,\n      \"yMin\": -412,\n      \"yMax\": 995,\n      \"hAsc\": 928,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Miao\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1142,\n      \"des\": -350,\n      \"tAsc\": 1142,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1268,\n      \"wDes\": 553,\n      \"xH\": 341,\n      \"capH\": 714,\n      \"yMin\": -553,\n      \"yMax\": 1268,\n      \"hAsc\": 1142,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Modi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 891,\n      \"des\": -463,\n      \"tAsc\": 891,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 463,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -460,\n      \"yMax\": 995,\n      \"hAsc\": 891,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mongolian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1457,\n      \"des\": -293,\n      \"tAsc\": 1457,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1642,\n      \"wDes\": 388,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -388,\n      \"yMax\": 1642,\n      \"hAsc\": 1457,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1229,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1229,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Multani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 510,\n      \"capH\": 630,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Myanmar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -860,\n      \"tAsc\": 1324,\n      \"tDes\": -860,\n      \"tLGap\": 0,\n      \"wAsc\": 1324,\n      \"wDes\": 860,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -690,\n      \"yMax\": 1252,\n      \"hAsc\": 1324,\n      \"hDes\": -860,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nabataean\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 550,\n      \"capH\": 640,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nag Mundari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1073,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nandinagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -560,\n      \"tAsc\": 900,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 560,\n      \"xH\": 558,\n      \"capH\": 622,\n      \"yMin\": -524,\n      \"yMax\": 995,\n      \"hAsc\": 900,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans New Tai Lue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 474,\n      \"xH\": 510,\n      \"capH\": 714,\n      \"yMin\": -457,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Newa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -396,\n      \"tAsc\": 1036,\n      \"tDes\": -396,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 396,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -394,\n      \"yMax\": 1036,\n      \"hAsc\": 1036,\n      \"hDes\": -396,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans NKo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 513,\n      \"capH\": 714,\n      \"yMin\": -272,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans NKo Unjoined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 293,\n      \"xH\": 513,\n      \"capH\": 714,\n      \"yMin\": -272,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nushu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -321,\n      \"tAsc\": 1069,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 321,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ogham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 695,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ol Chiki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Hungarian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -177,\n      \"tAsc\": 859,\n      \"tDes\": -177,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 600,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 859,\n      \"hDes\": -177,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Italic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old North Arabian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 665,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Permic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 638,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Persian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 724,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Sogdian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old South Arabian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 859,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Turkic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Oriya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 658,\n      \"capH\": 714,\n      \"yMin\": -292,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Osage\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Osmanya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Pahawh Hmong\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1055,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Palmyrene\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 640,\n      \"capH\": 778,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Pau Cin Hau\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans PhagsPa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 670,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Phoenician\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 719,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Psalter Pahlavi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 737,\n      \"des\": -554,\n      \"tAsc\": 737,\n      \"tDes\": -554,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 554,\n      \"xH\": 469,\n      \"capH\": 625,\n      \"yMin\": -551,\n      \"yMax\": 995,\n      \"hAsc\": 737,\n      \"hDes\": -554,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Rejang\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Runic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Samaritan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 659,\n      \"yMin\": -241,\n      \"yMax\": 1064,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Saurashtra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1021,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sharada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -455,\n      \"tAsc\": 925,\n      \"tDes\": -455,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 455,\n      \"xH\": 536,\n      \"capH\": 625,\n      \"yMin\": -402,\n      \"yMax\": 995,\n      \"hAsc\": 925,\n      \"hDes\": -455,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Shavian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 771,\n      \"yMin\": -245,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Siddham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -1030,\n      \"tAsc\": 1000,\n      \"tDes\": -1030,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 1030,\n      \"xH\": 683,\n      \"capH\": 714,\n      \"yMin\": -1025,\n      \"yMax\": 995,\n      \"hAsc\": 1000,\n      \"hDes\": -1030,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans SignWriting\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 802,\n      \"des\": -200,\n      \"tAsc\": 802,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 802,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sinhala\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -293,\n      \"tAsc\": 1011,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 612,\n      \"yMin\": -271,\n      \"yMax\": 995,\n      \"hAsc\": 1011,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sogdian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -313,\n      \"tAsc\": 1069,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 313,\n      \"xH\": 382,\n      \"capH\": 674,\n      \"yMin\": -310,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sora Sompeng\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 433,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Soyombo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1239,\n      \"des\": -357,\n      \"tAsc\": 1239,\n      \"tDes\": -357,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 357,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -354,\n      \"yMax\": 1234,\n      \"hAsc\": 1239,\n      \"hDes\": -357,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sundanese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -368,\n      \"tAsc\": 1069,\n      \"tDes\": -368,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 385,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -368,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -368,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sunuwar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syloti Nagri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 679,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Symbols\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1480,\n      \"des\": -570,\n      \"tAsc\": 1480,\n      \"tDes\": -570,\n      \"tLGap\": 0,\n      \"wAsc\": 1480,\n      \"wDes\": 570,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -565,\n      \"yMax\": 1471,\n      \"hAsc\": 1480,\n      \"hDes\": -570,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Symbols 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -630,\n      \"tAsc\": 1069,\n      \"tDes\": -630,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 630,\n      \"xH\": 536,\n      \"capH\": 945,\n      \"yMin\": -422,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -630,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -442,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac Eastern\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -392,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac Western\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -405,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tagalog\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tagbanwa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Le\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Tham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -520,\n      \"tAsc\": 1069,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 520,\n      \"xH\": 534,\n      \"capH\": 700,\n      \"yMin\": -520,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Viet\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1055,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Takri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -307,\n      \"tAsc\": 955,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 307,\n      \"xH\": 575,\n      \"capH\": 625,\n      \"yMin\": -304,\n      \"yMax\": 995,\n      \"hAsc\": 955,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tamil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -370,\n      \"tAsc\": 870,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 870,\n      \"wDes\": 370,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -321,\n      \"yMax\": 995,\n      \"hAsc\": 870,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tamil Supplement\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -370,\n      \"tAsc\": 870,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 451,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -451,\n      \"yMax\": 995,\n      \"hAsc\": 870,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tangsa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Telugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -483,\n      \"tAsc\": 869,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 620,\n      \"yMin\": -476,\n      \"yMax\": 995,\n      \"hAsc\": 869,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thaana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -424,\n      \"tAsc\": 1069,\n      \"tDes\": -424,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 424,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -300,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -424,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1061,\n      \"des\": -450,\n      \"tAsc\": 1061,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1061,\n      \"wDes\": 450,\n      \"xH\": 556,\n      \"capH\": 714,\n      \"yMin\": -433,\n      \"yMax\": 1009,\n      \"hAsc\": 1061,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thai Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -350,\n      \"tAsc\": 1250,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 490,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -474,\n      \"yMax\": 1108,\n      \"hAsc\": 1250,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tifinagh\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 1190,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tirhuta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1026,\n      \"des\": -519,\n      \"tAsc\": 1026,\n      \"tDes\": -519,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 519,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -516,\n      \"yMax\": 1021,\n      \"hAsc\": 1026,\n      \"hDes\": -519,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ugaritic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 743,\n      \"des\": -381,\n      \"tAsc\": 743,\n      \"tDes\": -381,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 381,\n      \"xH\": 536,\n      \"capH\": 723,\n      \"yMin\": -381,\n      \"yMax\": 995,\n      \"hAsc\": 743,\n      \"hDes\": -381,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Vai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Vithkuqi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Wancho\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1096,\n      \"des\": -161,\n      \"tAsc\": 1096,\n      \"tDes\": -161,\n      \"tLGap\": 0,\n      \"wAsc\": 1096,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 710,\n      \"yMin\": -241,\n      \"yMax\": 1078,\n      \"hAsc\": 1096,\n      \"hDes\": -161,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Warang Citi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -100,\n      \"tAsc\": 1042,\n      \"tDes\": -100,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 241,\n      \"xH\": 561,\n      \"capH\": 710,\n      \"yMin\": -241,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Yi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Zanabazar Square\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1621,\n      \"des\": -821,\n      \"tAsc\": 1621,\n      \"tDes\": -821,\n      \"tLGap\": 0,\n      \"wAsc\": 1621,\n      \"wDes\": 821,\n      \"xH\": 536,\n      \"capH\": 678,\n      \"yMin\": -821,\n      \"yMax\": 1621,\n      \"hAsc\": 1621,\n      \"hDes\": -821,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1048,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ahom\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -675,\n      \"tAsc\": 980,\n      \"tDes\": -675,\n      \"tLGap\": 0,\n      \"wAsc\": 980,\n      \"wDes\": 675,\n      \"xH\": 550,\n      \"capH\": 680,\n      \"yMin\": -672,\n      \"yMax\": 979,\n      \"hAsc\": 980,\n      \"hDes\": -675,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Armenian\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -268,\n      \"yMax\": 979,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Balinese\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -726,\n      \"tAsc\": 1069,\n      \"tDes\": -726,\n      \"tLGap\": 0,\n      \"wAsc\": 1249,\n      \"wDes\": 1005,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1005,\n      \"yMax\": 1249,\n      \"hAsc\": 1069,\n      \"hDes\": -726,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Bengali\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1092,\n      \"des\": -502,\n      \"tAsc\": 1092,\n      \"tDes\": -502,\n      \"tLGap\": 0,\n      \"wAsc\": 1213,\n      \"wDes\": 502,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -408,\n      \"yMax\": 1213,\n      \"hAsc\": 1092,\n      \"hDes\": -502,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Devanagari\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -625,\n      \"tAsc\": 930,\n      \"tDes\": -625,\n      \"tLGap\": 0,\n      \"wAsc\": 1407,\n      \"wDes\": 792,\n      \"xH\": 623,\n      \"capH\": 715,\n      \"yMin\": -524,\n      \"yMax\": 1397,\n      \"hAsc\": 930,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1048,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Dives Akuru\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -710,\n      \"tAsc\": 1069,\n      \"tDes\": -710,\n      \"tLGap\": 0,\n      \"wAsc\": 1551,\n      \"wDes\": 764,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -764,\n      \"yMax\": 1551,\n      \"hAsc\": 1069,\n      \"hDes\": -710,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Dogra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -364,\n      \"tAsc\": 1130,\n      \"tDes\": -364,\n      \"tLGap\": 0,\n      \"wAsc\": 1214,\n      \"wDes\": 445,\n      \"xH\": 554,\n      \"capH\": 625,\n      \"yMin\": -445,\n      \"yMax\": 1214,\n      \"hAsc\": 1130,\n      \"hDes\": -364,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ethiopic\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -240,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Georgian\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1086,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -252,\n      \"yMax\": 1046,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Grantha\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1290,\n      \"des\": -534,\n      \"tAsc\": 1290,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1757,\n      \"xH\": 566,\n      \"capH\": 714,\n      \"yMin\": -1757,\n      \"yMax\": 1151,\n      \"hAsc\": 1290,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Gujarati\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -450,\n      \"tAsc\": 997,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 682,\n      \"xH\": 536,\n      \"capH\": 592,\n      \"yMin\": -588,\n      \"yMax\": 1036,\n      \"hAsc\": 997,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Gurmukhi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -428,\n      \"tAsc\": 1006,\n      \"tDes\": -428,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 428,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -579,\n      \"yMax\": 979,\n      \"hAsc\": 1006,\n      \"hDes\": -428,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Hebrew\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -290,\n      \"tAsc\": 896,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 290,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 896,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Hentaigana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 1151,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 880,\n      \"capH\": 880,\n      \"yMin\": -286,\n      \"yMax\": 1151,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif HK\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif JP\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Kannada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 910,\n      \"des\": -710,\n      \"tAsc\": 910,\n      \"tDes\": -710,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 710,\n      \"xH\": 547,\n      \"capH\": 690,\n      \"yMin\": -710,\n      \"yMax\": 979,\n      \"hAsc\": 910,\n      \"hDes\": -710,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khitan Small Script\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 2300,\n      \"des\": -1700,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 1700,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1681,\n      \"yMax\": 2277,\n      \"hAsc\": 2300,\n      \"hDes\": -1700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khmer\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 839,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -839,\n      \"yMax\": 1255,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khojki\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1409,\n      \"des\": -447,\n      \"tAsc\": 1409,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1613,\n      \"wDes\": 447,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -384,\n      \"yMax\": 1117,\n      \"hAsc\": 1409,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif KR\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Lao\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1174,\n      \"des\": -482,\n      \"tAsc\": 1174,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1174,\n      \"wDes\": 482,\n      \"xH\": 550,\n      \"capH\": 714,\n      \"yMin\": -447,\n      \"yMax\": 1162,\n      \"hAsc\": 1174,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Makasar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Malayalam\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -383,\n      \"tAsc\": 864,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 383,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -383,\n      \"yMax\": 979,\n      \"hAsc\": 864,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Myanmar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1239,\n      \"des\": -1260,\n      \"tAsc\": 1239,\n      \"tDes\": -1260,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 1260,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1210,\n      \"yMax\": 1212,\n      \"hAsc\": 1239,\n      \"hDes\": -1260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif NP Hmong\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -240,\n      \"yMax\": 1039,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Old Uyghur\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -313,\n      \"tAsc\": 1069,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 504,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -504,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Oriya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -492,\n      \"tAsc\": 917,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 917,\n      \"wDes\": 492,\n      \"xH\": 657,\n      \"capH\": 657,\n      \"yMin\": -492,\n      \"yMax\": 979,\n      \"hAsc\": 917,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ottoman Siyaq\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -634,\n      \"tAsc\": 1069,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 634,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -634,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Sinhala\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -307,\n      \"tAsc\": 997,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 997,\n      \"wDes\": 307,\n      \"xH\": 536,\n      \"capH\": 612,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 997,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tamil\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -492,\n      \"tAsc\": 1069,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 492,\n      \"xH\": 554,\n      \"capH\": 829,\n      \"yMin\": -547,\n      \"yMax\": 1107,\n      \"hAsc\": 1069,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tangut\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -150,\n      \"tAsc\": 856,\n      \"tDes\": -150,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 150,\n      \"xH\": 502,\n      \"capH\": 712,\n      \"yMin\": -240,\n      \"yMax\": 979,\n      \"hAsc\": 856,\n      \"hDes\": -150,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif TC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Telugu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -483,\n      \"tAsc\": 869,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 620,\n      \"yMin\": -477,\n      \"yMax\": 979,\n      \"hAsc\": 869,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Thai\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1064,\n      \"des\": -534,\n      \"tAsc\": 1064,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1064,\n      \"wDes\": 534,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -472,\n      \"yMax\": 1056,\n      \"hAsc\": 1064,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tibetan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1466,\n      \"des\": -1349,\n      \"tAsc\": 1466,\n      \"tDes\": -1349,\n      \"tLGap\": 0,\n      \"wAsc\": 1466,\n      \"wDes\": 1349,\n      \"xH\": 678,\n      \"capH\": 714,\n      \"yMin\": -995,\n      \"yMax\": 1401,\n      \"hAsc\": 1466,\n      \"hDes\": -1349,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Todhri\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -270,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Toto\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -378,\n      \"tAsc\": 925,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 378,\n      \"xH\": 622,\n      \"capH\": 720,\n      \"yMin\": -375,\n      \"yMax\": 979,\n      \"hAsc\": 925,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Vithkuqi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Yezidi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 979,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Traditional Nushu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1055,\n      \"des\": -117,\n      \"tAsc\": 860,\n      \"tDes\": -117,\n      \"tLGap\": 90,\n      \"wAsc\": 1055,\n      \"wDes\": 118,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -241,\n      \"yMax\": 1000,\n      \"hAsc\": 1055,\n      \"hDes\": -117,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Znamenny Musical Notation\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -292,\n      \"tAsc\": 995,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 292,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -292,\n      \"yMax\": 995,\n      \"hAsc\": 995,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Cut\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1140,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Flat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2215,\n      \"des\": -639,\n      \"tAsc\": 2215,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 2215,\n      \"wDes\": 639,\n      \"xH\": 1120,\n      \"capH\": 1509,\n      \"yMin\": -567,\n      \"yMax\": 2215,\n      \"hAsc\": 2215,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Oval\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Round\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Slim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Square\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1100,\n      \"capH\": 1510,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"NTR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1294,\n      \"des\": -877,\n      \"tAsc\": 1294,\n      \"tDes\": -877,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 877,\n      \"xH\": 422,\n      \"capH\": 572,\n      \"yMin\": -877,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -877,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Numans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -553,\n      \"tAsc\": 1853,\n      \"tDes\": -553,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 553,\n      \"xH\": 1096,\n      \"capH\": 1434,\n      \"yMin\": -553,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -553,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nunito\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -353,\n      \"tAsc\": 1011,\n      \"tDes\": -353,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 300,\n      \"xH\": 484,\n      \"capH\": 705,\n      \"yMin\": -277,\n      \"yMax\": 1047,\n      \"hAsc\": 1011,\n      \"hDes\": -353,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nunito Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -353,\n      \"tAsc\": 1011,\n      \"tDes\": -353,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 327,\n      \"xH\": 486,\n      \"capH\": 705,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1011,\n      \"hDes\": -353,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nuosu SIL\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2200,\n      \"des\": -500,\n      \"tAsc\": 2200,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2200,\n      \"wDes\": 500,\n      \"xH\": 1000,\n      \"capH\": 1800,\n      \"yMin\": -462,\n      \"yMax\": 2150,\n      \"hAsc\": 2200,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Odibee Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -250,\n      \"tAsc\": 858,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 858,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 858,\n      \"hAsc\": 858,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Odor Mean Chey\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1210,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1210,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Offside\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 996,\n      \"des\": -265,\n      \"tAsc\": 996,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 265,\n      \"xH\": 605,\n      \"capH\": 740,\n      \"yMin\": -265,\n      \"yMax\": 1044,\n      \"hAsc\": 996,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -510,\n      \"tAsc\": 1070,\n      \"tDes\": -510,\n      \"tLGap\": 0,\n      \"wAsc\": 1141,\n      \"wDes\": 510,\n      \"xH\": 696,\n      \"capH\": 760,\n      \"yMin\": -507,\n      \"yMax\": 1141,\n      \"hAsc\": 1070,\n      \"hDes\": -510,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ojuju\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -276,\n      \"tAsc\": 1130,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 276,\n      \"xH\": 483,\n      \"capH\": 700,\n      \"yMin\": -270,\n      \"yMax\": 1035,\n      \"hAsc\": 1130,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Old Standard TT\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 762,\n      \"des\": -238,\n      \"tAsc\": 762,\n      \"tDes\": -238,\n      \"tLGap\": 236,\n      \"wAsc\": 948,\n      \"wDes\": 282,\n      \"xH\": 456,\n      \"capH\": 712,\n      \"yMin\": -294,\n      \"yMax\": 1100,\n      \"hAsc\": 762,\n      \"hDes\": -238,\n      \"lGap\": 236\n    }\n  },\n  {\n    \"family\": \"Oldenburg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 482,\n      \"capH\": 1555,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 9\n    }\n  },\n  {\n    \"family\": \"Ole\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -380,\n      \"tAsc\": 880,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 880,\n      \"wDes\": 446,\n      \"xH\": 270,\n      \"capH\": 510,\n      \"yMin\": -446,\n      \"yMax\": 829,\n      \"hAsc\": 880,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oleo Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -379,\n      \"tAsc\": 1004,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 379,\n      \"xH\": 443,\n      \"capH\": 710,\n      \"yMin\": -279,\n      \"yMax\": 938,\n      \"hAsc\": 1004,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oleo Script Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -379,\n      \"tAsc\": 1004,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 379,\n      \"xH\": 443,\n      \"capH\": 747,\n      \"yMin\": -369,\n      \"yMax\": 938,\n      \"hAsc\": 1004,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Onest\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -305,\n      \"tAsc\": 970,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1212,\n      \"wDes\": 334,\n      \"xH\": 527,\n      \"capH\": 707,\n      \"yMin\": -304,\n      \"yMax\": 960,\n      \"hAsc\": 970,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oooh Baby\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -325,\n      \"tAsc\": 900,\n      \"tDes\": -325,\n      \"tLGap\": 0,\n      \"wAsc\": 1007,\n      \"wDes\": 351,\n      \"xH\": 365,\n      \"capH\": 695,\n      \"yMin\": -351,\n      \"yMax\": 1007,\n      \"hAsc\": 900,\n      \"hDes\": -325,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Open Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2189,\n      \"des\": -600,\n      \"tAsc\": 2189,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2302,\n      \"wDes\": 651,\n      \"xH\": 1096,\n      \"capH\": 1462,\n      \"yMin\": -557,\n      \"yMax\": 2146,\n      \"hAsc\": 2189,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oranienbaum\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 895,\n      \"des\": -260,\n      \"tAsc\": 895,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 895,\n      \"wDes\": 260,\n      \"xH\": 475,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 895,\n      \"hAsc\": 895,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orbit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 710,\n      \"yMin\": -278,\n      \"yMax\": 1003,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orbitron\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -243,\n      \"tAsc\": 1011,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 243,\n      \"xH\": 580,\n      \"capH\": 720,\n      \"yMin\": -250,\n      \"yMax\": 974,\n      \"hAsc\": 1011,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oregano\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1975,\n      \"des\": -669,\n      \"tAsc\": 1975,\n      \"tDes\": -669,\n      \"tLGap\": 0,\n      \"wAsc\": 1975,\n      \"wDes\": 669,\n      \"xH\": 864,\n      \"capH\": 1460,\n      \"yMin\": -669,\n      \"yMax\": 1975,\n      \"hAsc\": 1975,\n      \"hDes\": -669,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orelega One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3296,\n      \"des\": -801,\n      \"tAsc\": 3296,\n      \"tDes\": -801,\n      \"tLGap\": 369,\n      \"wAsc\": 3480,\n      \"wDes\": 801,\n      \"xH\": 1840,\n      \"capH\": 2480,\n      \"yMin\": -801,\n      \"yMax\": 3480,\n      \"hAsc\": 3296,\n      \"hDes\": -801,\n      \"lGap\": 369\n    }\n  },\n  {\n    \"family\": \"Orienta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -235,\n      \"tAsc\": 960,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 301,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -301,\n      \"yMax\": 1030,\n      \"hAsc\": 960,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Original Surfer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2036,\n      \"des\": -526,\n      \"tAsc\": 2036,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2036,\n      \"wDes\": 526,\n      \"xH\": 987,\n      \"capH\": 1497,\n      \"yMin\": -526,\n      \"yMax\": 2036,\n      \"hAsc\": 2036,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oswald\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1193,\n      \"des\": -289,\n      \"tAsc\": 1193,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1325,\n      \"wDes\": 377,\n      \"xH\": 578,\n      \"capH\": 810,\n      \"yMin\": -287,\n      \"yMax\": 1297,\n      \"hAsc\": 1193,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Outfit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -260,\n      \"tAsc\": 1000,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 260,\n      \"xH\": 475,\n      \"capH\": 694,\n      \"yMin\": -338,\n      \"yMax\": 988,\n      \"hAsc\": 1000,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Over the Rainbow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1412,\n      \"des\": -677,\n      \"tAsc\": 1412,\n      \"tDes\": -677,\n      \"tLGap\": 0,\n      \"wAsc\": 1412,\n      \"wDes\": 677,\n      \"xH\": 636,\n      \"capH\": 812,\n      \"yMin\": -677,\n      \"yMax\": 1410,\n      \"hAsc\": 1412,\n      \"hDes\": -677,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overlock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -254,\n      \"tAsc\": 966,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 254,\n      \"xH\": 125,\n      \"capH\": 154,\n      \"yMin\": -253,\n      \"yMax\": 899,\n      \"hAsc\": 966,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overlock SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -254,\n      \"tAsc\": 966,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 254,\n      \"xH\": 159,\n      \"capH\": 154,\n      \"yMin\": -253,\n      \"yMax\": 899,\n      \"hAsc\": 966,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overpass\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1766,\n      \"des\": -766,\n      \"tAsc\": 1766,\n      \"tDes\": -766,\n      \"tLGap\": 0,\n      \"wAsc\": 2316,\n      \"wDes\": 756,\n      \"xH\": 1022,\n      \"capH\": 1400,\n      \"yMin\": -756,\n      \"yMax\": 2298,\n      \"hAsc\": 1766,\n      \"hDes\": -766,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overpass Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1766,\n      \"des\": -766,\n      \"tAsc\": 1766,\n      \"tDes\": -766,\n      \"tLGap\": 0,\n      \"wAsc\": 2316,\n      \"wDes\": 756,\n      \"xH\": 1022,\n      \"capH\": 1400,\n      \"yMin\": -756,\n      \"yMax\": 2316,\n      \"hAsc\": 1766,\n      \"hDes\": -766,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ovo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1770,\n      \"des\": -534,\n      \"tAsc\": 1770,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1770,\n      \"wDes\": 534,\n      \"xH\": 356,\n      \"capH\": 210,\n      \"yMin\": -534,\n      \"yMax\": 1770,\n      \"hAsc\": 1770,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oxanium\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 250,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 515,\n      \"capH\": 690,\n      \"yMin\": -208,\n      \"yMax\": 969,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Oxygen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2103,\n      \"des\": -483,\n      \"tAsc\": 2103,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 483,\n      \"yMin\": -672,\n      \"yMax\": 2131,\n      \"hAsc\": 2103,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oxygen Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -672,\n      \"tAsc\": 2015,\n      \"tDes\": -672,\n      \"tLGap\": 0,\n      \"wAsc\": 2015,\n      \"wDes\": 672,\n      \"xH\": 1097,\n      \"capH\": 1491,\n      \"yMin\": -678,\n      \"yMax\": 2104,\n      \"hAsc\": 2015,\n      \"hDes\": -672,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pacifico\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -453,\n      \"tAsc\": 1303,\n      \"tDes\": -453,\n      \"tLGap\": 0,\n      \"wAsc\": 1478,\n      \"wDes\": 457,\n      \"xH\": 460,\n      \"capH\": 840,\n      \"yMin\": -457,\n      \"yMax\": 1478,\n      \"hAsc\": 1303,\n      \"hDes\": -453,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Padauk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -500,\n      \"tAsc\": 1010,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 500,\n      \"xH\": 459,\n      \"capH\": 903,\n      \"yMin\": -600,\n      \"yMax\": 955,\n      \"hAsc\": 1010,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Padyakke Expanded One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 813,\n      \"des\": -628,\n      \"tAsc\": 813,\n      \"tDes\": -628,\n      \"tLGap\": 0,\n      \"wAsc\": 843,\n      \"wDes\": 628,\n      \"xH\": 357,\n      \"capH\": 520,\n      \"yMin\": -628,\n      \"yMax\": 843,\n      \"hAsc\": 813,\n      \"hDes\": -628,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palanquin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1320,\n      \"des\": -491,\n      \"tAsc\": 770,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1320,\n      \"wDes\": 491,\n      \"xH\": 485,\n      \"capH\": 680,\n      \"yMin\": -432,\n      \"yMax\": 1320,\n      \"hAsc\": 1320,\n      \"hDes\": -491,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palanquin Dark\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1320,\n      \"des\": -491,\n      \"tAsc\": 770,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1320,\n      \"wDes\": 491,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -491,\n      \"yMax\": 1320,\n      \"hAsc\": 1320,\n      \"hDes\": -491,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palatino\",\n    \"fallbacks\": [\n      \"Palatino Linotype\",\n      \"Palatino LT STD\",\n      \"Book Antiqua\",\n      \"Georgia\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1491,\n      \"des\": -600,\n      \"tAsc\": 1491,\n      \"tDes\": -580,\n      \"tLGap\": 0,\n      \"wAsc\": 2322,\n      \"wDes\": 2322,\n      \"yMin\": -580,\n      \"yMax\": 2322,\n      \"hAsc\": 1491,\n      \"hDes\": -600,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Palette Mosaic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 465,\n      \"capH\": 790,\n      \"yMin\": -251,\n      \"yMax\": 876,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pangolin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1259,\n      \"wDes\": 255,\n      \"xH\": 555,\n      \"capH\": 720,\n      \"yMin\": -256,\n      \"yMax\": 1259,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Paprika\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -274,\n      \"tAsc\": 1145,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1225,\n      \"wDes\": 326,\n      \"xH\": 689,\n      \"capH\": 889,\n      \"yMin\": -326,\n      \"yMax\": 1225,\n      \"hAsc\": 1145,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Papyrus\",\n    \"fallbacks\": [\"fantasy\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1925,\n      \"des\": -1235,\n      \"tAsc\": 1913,\n      \"tDes\": -780,\n      \"tLGap\": -502,\n      \"wAsc\": 1925,\n      \"wDes\": 1925,\n      \"xH\": 910,\n      \"capH\": 1351,\n      \"yMin\": -1235,\n      \"yMax\": 1935,\n      \"hAsc\": 1925,\n      \"hDes\": -1235,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Parastoo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2727,\n      \"asc\": 2635,\n      \"des\": -1200,\n      \"tAsc\": 2635,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2782,\n      \"wDes\": 1200,\n      \"xH\": 1082,\n      \"capH\": 1638,\n      \"yMin\": -1012,\n      \"yMax\": 2782,\n      \"hAsc\": 2635,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Parisienne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1875,\n      \"des\": -915,\n      \"tAsc\": 1875,\n      \"tDes\": -915,\n      \"tLGap\": 0,\n      \"wAsc\": 1875,\n      \"wDes\": 915,\n      \"xH\": 723,\n      \"capH\": 1558,\n      \"yMin\": -915,\n      \"yMax\": 1875,\n      \"hAsc\": 1875,\n      \"hDes\": -915,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Parkinsans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 350,\n      \"xH\": 549,\n      \"capH\": 693,\n      \"yMin\": -275,\n      \"yMax\": 975,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passero One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -618,\n      \"tAsc\": 1820,\n      \"tDes\": -618,\n      \"tLGap\": 0,\n      \"wAsc\": 1820,\n      \"wDes\": 618,\n      \"xH\": 983,\n      \"capH\": 1323,\n      \"yMin\": -618,\n      \"yMax\": 1820,\n      \"hAsc\": 1820,\n      \"hDes\": -618,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passion One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 835,\n      \"des\": -266,\n      \"tAsc\": 835,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 266,\n      \"xH\": 479,\n      \"capH\": 621,\n      \"yMin\": -198,\n      \"yMax\": 835,\n      \"hAsc\": 835,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passions Conflict\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -350,\n      \"tAsc\": 750,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 771,\n      \"wDes\": 350,\n      \"xH\": 170,\n      \"capH\": 475,\n      \"yMin\": -346,\n      \"yMax\": 769,\n      \"hAsc\": 750,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pathway Extreme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -286,\n      \"tAsc\": 1070,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 286,\n      \"xH\": 540,\n      \"capH\": 700,\n      \"yMin\": -233,\n      \"yMax\": 1159,\n      \"hAsc\": 1070,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pathway Gothic One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 954,\n      \"des\": -198,\n      \"tAsc\": 954,\n      \"tDes\": -198,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 222,\n      \"xH\": 540,\n      \"capH\": 700,\n      \"yMin\": -222,\n      \"yMax\": 1004,\n      \"hAsc\": 954,\n      \"hDes\": -198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patrick Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -312,\n      \"tAsc\": 1024,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 312,\n      \"xH\": 467,\n      \"capH\": 661,\n      \"yMin\": -312,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patrick Hand SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -312,\n      \"tAsc\": 1024,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 312,\n      \"xH\": 464,\n      \"capH\": 661,\n      \"yMin\": -307,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pattaya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2065,\n      \"des\": -777,\n      \"tAsc\": 2065,\n      \"tDes\": -777,\n      \"tLGap\": 0,\n      \"wAsc\": 2065,\n      \"wDes\": 777,\n      \"xH\": 1024,\n      \"capH\": 1532,\n      \"yMin\": -777,\n      \"yMax\": 2065,\n      \"hAsc\": 2065,\n      \"hDes\": -777,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patua One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -247,\n      \"tAsc\": 972,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 247,\n      \"xH\": 500,\n      \"capH\": 690,\n      \"yMin\": -247,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pavanam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -339,\n      \"tAsc\": 693,\n      \"tDes\": -162,\n      \"tLGap\": 59,\n      \"wAsc\": 952,\n      \"wDes\": 339,\n      \"yMin\": -322,\n      \"yMax\": 952,\n      \"hAsc\": 952,\n      \"hDes\": -339,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Paytone One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1113,\n      \"des\": -283,\n      \"tAsc\": 1113,\n      \"tDes\": -283,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 380,\n      \"xH\": 501,\n      \"capH\": 688,\n      \"yMin\": -371,\n      \"yMax\": 1213,\n      \"hAsc\": 1113,\n      \"hDes\": -283,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Peddana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 703,\n      \"des\": -518,\n      \"tAsc\": 703,\n      \"tDes\": -518,\n      \"tLGap\": 0,\n      \"wAsc\": 703,\n      \"wDes\": 518,\n      \"xH\": 241,\n      \"capH\": 329,\n      \"yMin\": -518,\n      \"yMax\": 703,\n      \"hAsc\": 703,\n      \"hDes\": -518,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Peralta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2004,\n      \"des\": -647,\n      \"tAsc\": 2004,\n      \"tDes\": -647,\n      \"tLGap\": 0,\n      \"wAsc\": 2004,\n      \"wDes\": 647,\n      \"xH\": 1036,\n      \"capH\": 1479,\n      \"yMin\": -647,\n      \"yMax\": 2004,\n      \"hAsc\": 2004,\n      \"hDes\": -647,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Permanent Marker\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1136,\n      \"des\": -325,\n      \"tAsc\": 622,\n      \"tDes\": -61,\n      \"tLGap\": 61,\n      \"wAsc\": 1136,\n      \"wDes\": 325,\n      \"xH\": 625,\n      \"capH\": 758,\n      \"yMin\": -325,\n      \"yMax\": 1136,\n      \"hAsc\": 1136,\n      \"hDes\": -325,\n      \"lGap\": 31\n    }\n  },\n  {\n    \"family\": \"Petemoss\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 774,\n      \"wDes\": 335,\n      \"xH\": 305,\n      \"capH\": 480,\n      \"yMin\": -335,\n      \"yMax\": 774,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Petit Formal Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2033,\n      \"des\": -527,\n      \"tAsc\": 2033,\n      \"tDes\": -527,\n      \"tLGap\": 0,\n      \"wAsc\": 2033,\n      \"wDes\": 527,\n      \"xH\": 1185,\n      \"capH\": 1609,\n      \"yMin\": -527,\n      \"yMax\": 2033,\n      \"hAsc\": 2033,\n      \"hDes\": -527,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Petrona\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -270,\n      \"tAsc\": 858,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 342,\n      \"xH\": 443,\n      \"capH\": 641,\n      \"yMin\": -270,\n      \"yMax\": 1076,\n      \"hAsc\": 858,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Phetsarath\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2123,\n      \"des\": -857,\n      \"tAsc\": 2123,\n      \"tDes\": -857,\n      \"tLGap\": 0,\n      \"wAsc\": 2123,\n      \"wDes\": 857,\n      \"yMin\": -857,\n      \"yMax\": 2123,\n      \"hAsc\": 2123,\n      \"hDes\": -857,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Philosopher\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -220,\n      \"tAsc\": 900,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 330,\n      \"xH\": 470,\n      \"capH\": 660,\n      \"yMin\": -325,\n      \"yMax\": 975,\n      \"hAsc\": 900,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Phudu\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -200,\n      \"tAsc\": 1025,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 1025,\n      \"hAsc\": 1025,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Piazzolla\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1110,\n      \"des\": -310,\n      \"tAsc\": 1110,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 310,\n      \"xH\": 478,\n      \"capH\": 644,\n      \"yMin\": -232,\n      \"yMax\": 980,\n      \"hAsc\": 1110,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Piedra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 973,\n      \"des\": -328,\n      \"tAsc\": 973,\n      \"tDes\": -328,\n      \"tLGap\": 0,\n      \"wAsc\": 973,\n      \"wDes\": 328,\n      \"xH\": 437,\n      \"capH\": 655,\n      \"yMin\": -328,\n      \"yMax\": 973,\n      \"hAsc\": 973,\n      \"hDes\": -328,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pinyon Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1768,\n      \"des\": -787,\n      \"tAsc\": 1768,\n      \"tDes\": -787,\n      \"tLGap\": 0,\n      \"wAsc\": 2207,\n      \"wDes\": 963,\n      \"xH\": 760,\n      \"capH\": 1388,\n      \"yMin\": -963,\n      \"yMax\": 2147,\n      \"hAsc\": 1768,\n      \"hDes\": -787,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pirata One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -279,\n      \"tAsc\": 1006,\n      \"tDes\": -279,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 279,\n      \"xH\": 594,\n      \"capH\": 793,\n      \"yMin\": -279,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -279,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pixelify Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 289,\n      \"xH\": 450,\n      \"capH\": 700,\n      \"yMin\": -248,\n      \"yMax\": 919,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Plaster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1020,\n      \"capH\": 1361,\n      \"yMin\": -560,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Platypi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -251,\n      \"tAsc\": 1125,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 342,\n      \"xH\": 484,\n      \"capH\": 690,\n      \"yMin\": -301,\n      \"yMax\": 1042,\n      \"hAsc\": 1125,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Play\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -220,\n      \"tAsc\": 937,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1052,\n      \"wDes\": 224,\n      \"xH\": 484,\n      \"capH\": 649,\n      \"yMin\": -220,\n      \"yMax\": 1035,\n      \"hAsc\": 937,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playball\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 400,\n      \"xH\": 403,\n      \"capH\": 706,\n      \"yMin\": -359,\n      \"yMax\": 1031,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1240,\n      \"asc\": 1098,\n      \"des\": -390,\n      \"tAsc\": 1098,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 271,\n      \"xH\": 513,\n      \"capH\": 708,\n      \"yMin\": -262,\n      \"yMax\": 1110,\n      \"hAsc\": 1098,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1082,\n      \"des\": -251,\n      \"tAsc\": 1082,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1159,\n      \"wDes\": 251,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -241,\n      \"yMax\": 1159,\n      \"hAsc\": 1082,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair Display SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1082,\n      \"des\": -251,\n      \"tAsc\": 1082,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1201,\n      \"wDes\": 251,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -241,\n      \"yMax\": 1156,\n      \"hAsc\": 1082,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1170,\n      \"des\": -340,\n      \"tAsc\": 1170,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 502,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -486,\n      \"yMax\": 1238,\n      \"hAsc\": 1170,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Arabic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -550,\n      \"tAsc\": 1100,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1224,\n      \"wDes\": 604,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -539,\n      \"yMax\": 1224,\n      \"hAsc\": 1100,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Deva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -750,\n      \"tAsc\": 1280,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 1382,\n      \"wDes\": 1040,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -708,\n      \"yMax\": 1270,\n      \"hAsc\": 1280,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Hebrew\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -460,\n      \"tAsc\": 1070,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 432,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -392,\n      \"yMax\": 1224,\n      \"hAsc\": 1070,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Thai\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1363,\n      \"des\": -380,\n      \"tAsc\": 1363,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1363,\n      \"wDes\": 432,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -392,\n      \"yMax\": 1278,\n      \"hAsc\": 1363,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1508,\n      \"des\": -571,\n      \"tAsc\": 1508,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 588,\n      \"xH\": 500,\n      \"capH\": 1065,\n      \"yMin\": -584,\n      \"yMax\": 1541,\n      \"hAsc\": 1508,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1508,\n      \"des\": -571,\n      \"tAsc\": 1508,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 588,\n      \"xH\": 500,\n      \"capH\": 1065,\n      \"yMin\": -584,\n      \"yMax\": 1521,\n      \"hAsc\": 1508,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AT\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU NSW\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU NSW Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU QLD\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU QLD Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU SA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1413,\n      \"des\": -492,\n      \"tAsc\": 1413,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1473,\n      \"wDes\": 512,\n      \"xH\": 500,\n      \"capH\": 988,\n      \"yMin\": -507,\n      \"yMax\": 1461,\n      \"hAsc\": 1413,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU SA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1413,\n      \"des\": -492,\n      \"tAsc\": 1413,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1473,\n      \"wDes\": 512,\n      \"xH\": 500,\n      \"capH\": 988,\n      \"yMin\": -507,\n      \"yMax\": 1430,\n      \"hAsc\": 1413,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU TAS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU TAS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU VIC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU VIC Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE VLG\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE VLG Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE WAL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1924,\n      \"des\": -922,\n      \"tAsc\": 1924,\n      \"tDes\": -922,\n      \"tLGap\": 0,\n      \"wAsc\": 1935,\n      \"wDes\": 926,\n      \"xH\": 500,\n      \"capH\": 1405,\n      \"yMin\": -925,\n      \"yMax\": 1889,\n      \"hAsc\": 1924,\n      \"hDes\": -922,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE WAL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1924,\n      \"des\": -922,\n      \"tAsc\": 1924,\n      \"tDes\": -922,\n      \"tLGap\": 0,\n      \"wAsc\": 1935,\n      \"wDes\": 926,\n      \"xH\": 500,\n      \"capH\": 1405,\n      \"yMin\": -925,\n      \"yMax\": 1873,\n      \"hAsc\": 1924,\n      \"hDes\": -922,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1588,\n      \"des\": -639,\n      \"tAsc\": 1588,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 1631,\n      \"wDes\": 654,\n      \"xH\": 500,\n      \"capH\": 1131,\n      \"yMin\": -650,\n      \"yMax\": 1608,\n      \"hAsc\": 1588,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1588,\n      \"des\": -639,\n      \"tAsc\": 1588,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 1631,\n      \"wDes\": 654,\n      \"xH\": 500,\n      \"capH\": 1131,\n      \"yMin\": -650,\n      \"yMax\": 1589,\n      \"hAsc\": 1588,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1423,\n      \"des\": -500,\n      \"tAsc\": 1423,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1482,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 996,\n      \"yMin\": -515,\n      \"yMax\": 1469,\n      \"hAsc\": 1423,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1423,\n      \"des\": -500,\n      \"tAsc\": 1423,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1482,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 996,\n      \"yMin\": -515,\n      \"yMax\": 1437,\n      \"hAsc\": 1423,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1591,\n      \"des\": -641,\n      \"tAsc\": 1591,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 1634,\n      \"wDes\": 656,\n      \"xH\": 500,\n      \"capH\": 1133,\n      \"yMin\": -652,\n      \"yMax\": 1610,\n      \"hAsc\": 1591,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1591,\n      \"des\": -641,\n      \"tAsc\": 1591,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 1634,\n      \"wDes\": 656,\n      \"xH\": 500,\n      \"capH\": 1133,\n      \"yMin\": -652,\n      \"yMax\": 1591,\n      \"hAsc\": 1591,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1452,\n      \"des\": -525,\n      \"tAsc\": 1452,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1509,\n      \"wDes\": 544,\n      \"xH\": 500,\n      \"capH\": 1020,\n      \"yMin\": -540,\n      \"yMax\": 1493,\n      \"hAsc\": 1452,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1452,\n      \"des\": -525,\n      \"tAsc\": 1452,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1509,\n      \"wDes\": 544,\n      \"xH\": 500,\n      \"capH\": 1020,\n      \"yMin\": -539,\n      \"yMax\": 1461,\n      \"hAsc\": 1452,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CU\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1569,\n      \"des\": -623,\n      \"tAsc\": 1569,\n      \"tDes\": -623,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 638,\n      \"xH\": 500,\n      \"capH\": 1115,\n      \"yMin\": -635,\n      \"yMax\": 1588,\n      \"hAsc\": 1569,\n      \"hDes\": -623,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CU Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1569,\n      \"des\": -623,\n      \"tAsc\": 1569,\n      \"tDes\": -623,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 638,\n      \"xH\": 500,\n      \"capH\": 1115,\n      \"yMin\": -634,\n      \"yMax\": 1562,\n      \"hAsc\": 1569,\n      \"hDes\": -623,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -505,\n      \"yMax\": 1458,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -504,\n      \"yMax\": 1425,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE Grund\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1393,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE Grund Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1371,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE LA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1393,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE LA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1357,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE SAS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1291,\n      \"des\": -388,\n      \"tAsc\": 1291,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 413,\n      \"xH\": 500,\n      \"capH\": 888,\n      \"yMin\": -407,\n      \"yMax\": 1361,\n      \"hAsc\": 1291,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE SAS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1291,\n      \"des\": -388,\n      \"tAsc\": 1291,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 413,\n      \"xH\": 500,\n      \"capH\": 888,\n      \"yMin\": -407,\n      \"yMax\": 1326,\n      \"hAsc\": 1291,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE VA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1402,\n      \"des\": -482,\n      \"tAsc\": 1402,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1463,\n      \"wDes\": 503,\n      \"xH\": 500,\n      \"capH\": 979,\n      \"yMin\": -498,\n      \"yMax\": 1452,\n      \"hAsc\": 1402,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE VA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1402,\n      \"des\": -482,\n      \"tAsc\": 1402,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1463,\n      \"wDes\": 503,\n      \"xH\": 500,\n      \"capH\": 979,\n      \"yMin\": -498,\n      \"yMax\": 1425,\n      \"hAsc\": 1402,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Loopet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Loopet Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Uloopet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Uloopet Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Deco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Deco Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Moderne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1550,\n      \"des\": -607,\n      \"tAsc\": 1550,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1597,\n      \"wDes\": 623,\n      \"xH\": 500,\n      \"capH\": 1100,\n      \"yMin\": -619,\n      \"yMax\": 1577,\n      \"hAsc\": 1550,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Moderne Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1550,\n      \"des\": -607,\n      \"tAsc\": 1550,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1597,\n      \"wDes\": 623,\n      \"xH\": 500,\n      \"capH\": 1100,\n      \"yMin\": -619,\n      \"yMax\": 1557,\n      \"hAsc\": 1550,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1927,\n      \"des\": -925,\n      \"tAsc\": 1927,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 929,\n      \"xH\": 500,\n      \"capH\": 1408,\n      \"yMin\": -928,\n      \"yMax\": 1892,\n      \"hAsc\": 1927,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1927,\n      \"des\": -925,\n      \"tAsc\": 1927,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 929,\n      \"xH\": 500,\n      \"capH\": 1408,\n      \"yMin\": -928,\n      \"yMax\": 1876,\n      \"hAsc\": 1927,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB J\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB J Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB S\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB S Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -399,\n      \"yMax\": 1352,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1315,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Lijeva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1351,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Lijeva Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1328,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HU\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1362,\n      \"des\": -448,\n      \"tAsc\": 1362,\n      \"tDes\": -448,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 470,\n      \"xH\": 500,\n      \"capH\": 946,\n      \"yMin\": -465,\n      \"yMax\": 1419,\n      \"hAsc\": 1362,\n      \"hDes\": -448,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HU Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1362,\n      \"des\": -448,\n      \"tAsc\": 1362,\n      \"tDes\": -448,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 470,\n      \"xH\": 500,\n      \"capH\": 946,\n      \"yMin\": -465,\n      \"yMax\": 1398,\n      \"hAsc\": 1362,\n      \"hDes\": -448,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ID\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1964,\n      \"des\": -956,\n      \"tAsc\": 1964,\n      \"tDes\": -956,\n      \"tLGap\": 0,\n      \"wAsc\": 1971,\n      \"wDes\": 959,\n      \"xH\": 500,\n      \"capH\": 1438,\n      \"yMin\": -958,\n      \"yMax\": 1924,\n      \"hAsc\": 1964,\n      \"hDes\": -956,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ID Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1964,\n      \"des\": -956,\n      \"tAsc\": 1964,\n      \"tDes\": -956,\n      \"tLGap\": 0,\n      \"wAsc\": 1971,\n      \"wDes\": 959,\n      \"xH\": 500,\n      \"capH\": 1438,\n      \"yMin\": -958,\n      \"yMax\": 1907,\n      \"hAsc\": 1964,\n      \"hDes\": -956,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IE\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1405,\n      \"des\": -484,\n      \"tAsc\": 1405,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1465,\n      \"wDes\": 505,\n      \"xH\": 500,\n      \"capH\": 981,\n      \"yMin\": -501,\n      \"yMax\": 1454,\n      \"hAsc\": 1405,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IE Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1405,\n      \"des\": -484,\n      \"tAsc\": 1405,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1465,\n      \"wDes\": 505,\n      \"xH\": 500,\n      \"capH\": 981,\n      \"yMin\": -500,\n      \"yMax\": 1421,\n      \"hAsc\": 1405,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IN\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1456,\n      \"des\": -528,\n      \"tAsc\": 1456,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 1512,\n      \"wDes\": 547,\n      \"xH\": 500,\n      \"capH\": 1023,\n      \"yMin\": -542,\n      \"yMax\": 1496,\n      \"hAsc\": 1456,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IN Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1456,\n      \"des\": -528,\n      \"tAsc\": 1456,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 1512,\n      \"wDes\": 547,\n      \"xH\": 500,\n      \"capH\": 1023,\n      \"yMin\": -542,\n      \"yMax\": 1465,\n      \"hAsc\": 1456,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1313,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Moderna\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Moderna Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1378,\n      \"des\": -462,\n      \"tAsc\": 1378,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1441,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 959,\n      \"yMin\": -478,\n      \"yMax\": 1433,\n      \"hAsc\": 1378,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1378,\n      \"des\": -462,\n      \"tAsc\": 1378,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1441,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 959,\n      \"yMin\": -478,\n      \"yMax\": 1411,\n      \"hAsc\": 1378,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite MX\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite MX Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NG Modern\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NG Modern Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1762,\n      \"des\": -786,\n      \"tAsc\": 1762,\n      \"tDes\": -786,\n      \"tLGap\": 0,\n      \"wAsc\": 1789,\n      \"wDes\": 795,\n      \"xH\": 500,\n      \"capH\": 1273,\n      \"yMin\": -793,\n      \"yMax\": 1751,\n      \"hAsc\": 1762,\n      \"hDes\": -786,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1762,\n      \"des\": -786,\n      \"tAsc\": 1762,\n      \"tDes\": -786,\n      \"tLGap\": 0,\n      \"wAsc\": 1789,\n      \"wDes\": 795,\n      \"xH\": 500,\n      \"capH\": 1273,\n      \"yMin\": -793,\n      \"yMax\": 1728,\n      \"hAsc\": 1762,\n      \"hDes\": -786,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1391,\n      \"des\": -473,\n      \"tAsc\": 1391,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 1453,\n      \"wDes\": 494,\n      \"xH\": 500,\n      \"capH\": 970,\n      \"yMin\": -490,\n      \"yMax\": 1443,\n      \"hAsc\": 1391,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1391,\n      \"des\": -473,\n      \"tAsc\": 1391,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 1453,\n      \"wDes\": 494,\n      \"xH\": 500,\n      \"capH\": 970,\n      \"yMin\": -489,\n      \"yMax\": 1409,\n      \"hAsc\": 1391,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Basic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Basic Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1317,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PE\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PE Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1411,\n      \"des\": -490,\n      \"tAsc\": 1411,\n      \"tDes\": -490,\n      \"tLGap\": 0,\n      \"wAsc\": 1471,\n      \"wDes\": 510,\n      \"xH\": 500,\n      \"capH\": 986,\n      \"yMin\": -505,\n      \"yMax\": 1460,\n      \"hAsc\": 1411,\n      \"hDes\": -490,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1411,\n      \"des\": -490,\n      \"tAsc\": 1411,\n      \"tDes\": -490,\n      \"tLGap\": 0,\n      \"wAsc\": 1471,\n      \"wDes\": 510,\n      \"xH\": 500,\n      \"capH\": 986,\n      \"yMin\": -505,\n      \"yMax\": 1439,\n      \"hAsc\": 1411,\n      \"hDes\": -490,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PT\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1527,\n      \"des\": -588,\n      \"tAsc\": 1527,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1576,\n      \"wDes\": 604,\n      \"xH\": 500,\n      \"capH\": 1081,\n      \"yMin\": -600,\n      \"yMax\": 1557,\n      \"hAsc\": 1527,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1527,\n      \"des\": -588,\n      \"tAsc\": 1527,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1576,\n      \"wDes\": 604,\n      \"xH\": 500,\n      \"capH\": 1081,\n      \"yMin\": -600,\n      \"yMax\": 1537,\n      \"hAsc\": 1527,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite RO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite RO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite SK\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -505,\n      \"yMax\": 1458,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite SK Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -504,\n      \"yMax\": 1425,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite TZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite TZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Modern\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1352,\n      \"des\": -440,\n      \"tAsc\": 1352,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 1418,\n      \"wDes\": 463,\n      \"xH\": 500,\n      \"capH\": 938,\n      \"yMin\": -457,\n      \"yMax\": 1411,\n      \"hAsc\": 1352,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Modern Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1352,\n      \"des\": -440,\n      \"tAsc\": 1352,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 1418,\n      \"wDes\": 463,\n      \"xH\": 500,\n      \"capH\": 938,\n      \"yMin\": -457,\n      \"yMax\": 1390,\n      \"hAsc\": 1352,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite VN\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1743,\n      \"des\": -769,\n      \"tAsc\": 1743,\n      \"tDes\": -769,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 779,\n      \"xH\": 500,\n      \"capH\": 1257,\n      \"yMin\": -777,\n      \"yMax\": 1737,\n      \"hAsc\": 1743,\n      \"hDes\": -769,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite VN Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1743,\n      \"des\": -769,\n      \"tAsc\": 1743,\n      \"tDes\": -769,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 779,\n      \"xH\": 500,\n      \"capH\": 1257,\n      \"yMin\": -777,\n      \"yMax\": 1720,\n      \"hAsc\": 1743,\n      \"hDes\": -769,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ZA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1474,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ZA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1446,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Plus Jakarta Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -222,\n      \"tAsc\": 1038,\n      \"tDes\": -222,\n      \"tLGap\": 0,\n      \"wAsc\": 1296,\n      \"wDes\": 356,\n      \"xH\": 536,\n      \"capH\": 745,\n      \"yMin\": -240,\n      \"yMax\": 1189,\n      \"hAsc\": 1038,\n      \"hDes\": -222,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pochaevsk\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1051,\n      \"des\": -400,\n      \"tAsc\": 1051,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1051,\n      \"wDes\": 433,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -433,\n      \"yMax\": 1051,\n      \"hAsc\": 1051,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Podkova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -249,\n      \"tAsc\": 859,\n      \"tDes\": -249,\n      \"tLGap\": 0,\n      \"wAsc\": 1091,\n      \"wDes\": 343,\n      \"xH\": 429,\n      \"capH\": 589,\n      \"yMin\": -301,\n      \"yMax\": 969,\n      \"hAsc\": 859,\n      \"hDes\": -249,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poetsen One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 550,\n      \"capH\": 710,\n      \"yMin\": -200,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poiret One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -208,\n      \"tAsc\": 962,\n      \"tDes\": -208,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 208,\n      \"xH\": 450,\n      \"capH\": 750,\n      \"yMin\": -208,\n      \"yMax\": 962,\n      \"hAsc\": 962,\n      \"hDes\": -208,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poller One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -514,\n      \"tAsc\": 1920,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 514,\n      \"xH\": 991,\n      \"capH\": 1486,\n      \"yMin\": -514,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -514,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poltawski Nowy\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 400,\n      \"xH\": 440,\n      \"capH\": 700,\n      \"yMin\": -362,\n      \"yMax\": 1098,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poly\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -224,\n      \"tAsc\": 964,\n      \"tDes\": -224,\n      \"tLGap\": 0,\n      \"wAsc\": 964,\n      \"wDes\": 224,\n      \"xH\": 473,\n      \"capH\": 693,\n      \"yMin\": -223,\n      \"yMax\": 919,\n      \"hAsc\": 964,\n      \"hDes\": -224,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pompiere\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1918,\n      \"des\": -543,\n      \"tAsc\": 1919,\n      \"tDes\": -543,\n      \"tLGap\": 0,\n      \"wAsc\": 1918,\n      \"wDes\": 543,\n      \"xH\": 616,\n      \"capH\": 1315,\n      \"yMin\": -543,\n      \"yMax\": 1918,\n      \"hAsc\": 1918,\n      \"hDes\": -543,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ponnala\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -861,\n      \"tAsc\": 938,\n      \"tDes\": -861,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 861,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -861,\n      \"yMax\": 938,\n      \"hAsc\": 938,\n      \"hDes\": -861,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ponomar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -460,\n      \"tAsc\": 1150,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1430,\n      \"wDes\": 460,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -460,\n      \"yMax\": 1080,\n      \"hAsc\": 1150,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pontano Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2025,\n      \"des\": -599,\n      \"tAsc\": 2025,\n      \"tDes\": -599,\n      \"tLGap\": 0,\n      \"wAsc\": 2190,\n      \"wDes\": 599,\n      \"xH\": 1023,\n      \"capH\": 1464,\n      \"yMin\": -599,\n      \"yMax\": 2120,\n      \"hAsc\": 2025,\n      \"hDes\": -599,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poor Story\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 819,\n      \"des\": -205,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 256,\n      \"wAsc\": 819,\n      \"wDes\": 205,\n      \"xH\": 389,\n      \"capH\": 641,\n      \"yMin\": -205,\n      \"yMax\": 819,\n      \"hAsc\": 819,\n      \"hDes\": -205,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Poppins\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 100,\n      \"wAsc\": 1135,\n      \"wDes\": 627,\n      \"xH\": 548,\n      \"capH\": 698,\n      \"yMin\": -572,\n      \"yMax\": 1065,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 100\n    }\n  },\n  {\n    \"family\": \"Port Lligat Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -211,\n      \"tAsc\": 860,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 211,\n      \"xH\": 178,\n      \"capH\": 125,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Port Lligat Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -211,\n      \"tAsc\": 860,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 211,\n      \"xH\": 155,\n      \"capH\": 99,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Potta One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 565,\n      \"capH\": 780,\n      \"yMin\": -290,\n      \"yMax\": 1160,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pragati Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1158,\n      \"des\": -534,\n      \"tAsc\": 1158,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 534,\n      \"xH\": 484,\n      \"capH\": 630,\n      \"yMin\": -534,\n      \"yMax\": 1158,\n      \"hAsc\": 1158,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Praise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1023,\n      \"wDes\": 544,\n      \"xH\": 425,\n      \"capH\": 600,\n      \"yMin\": -544,\n      \"yMax\": 1023,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prata\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 993,\n      \"des\": -362,\n      \"tAsc\": 993,\n      \"tDes\": -362,\n      \"tLGap\": 0,\n      \"wAsc\": 1201,\n      \"wDes\": 362,\n      \"xH\": 518,\n      \"capH\": 800,\n      \"yMin\": -362,\n      \"yMax\": 1201,\n      \"hAsc\": 993,\n      \"hDes\": -362,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Preahvihear\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Press Start 2P\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": 0,\n      \"tAsc\": 1000,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 374,\n      \"xH\": 750,\n      \"capH\": 1000,\n      \"yMin\": -374,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pridi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -450,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1100,\n      \"wDes\": 450,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -411,\n      \"yMax\": 1049,\n      \"hAsc\": 1100,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Princess Sofia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -574,\n      \"tAsc\": 1010,\n      \"tDes\": -574,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 588,\n      \"xH\": 670,\n      \"capH\": 858,\n      \"yMin\": -574,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -574,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prociono\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -212,\n      \"tAsc\": 1008,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1008,\n      \"wDes\": 212,\n      \"xH\": 203,\n      \"capH\": 738,\n      \"yMin\": -212,\n      \"yMax\": 1008,\n      \"hAsc\": 1008,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prompt\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -422,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1090,\n      \"wDes\": 422,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -368,\n      \"yMax\": 1061,\n      \"hAsc\": 1090,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prosto One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -295,\n      \"tAsc\": 940,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 295,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -295,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Guerrilla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 204,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -204,\n      \"yMax\": 1140,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Revolution\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1254,\n      \"wDes\": 303,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -303,\n      \"yMax\": 1254,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Riot\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1206,\n      \"wDes\": 251,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -251,\n      \"yMax\": 1206,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Strike\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 204,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -204,\n      \"yMax\": 1140,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Proza Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1996,\n      \"des\": -800,\n      \"tAsc\": 1996,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 1996,\n      \"wDes\": 800,\n      \"xH\": 1060,\n      \"capH\": 1465,\n      \"yMin\": -558,\n      \"yMax\": 1962,\n      \"hAsc\": 1996,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -235,\n      \"tAsc\": 885,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 235,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 915,\n      \"hAsc\": 885,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 993,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans Caption\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 999,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 993,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -286,\n      \"tAsc\": 1039,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 286,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -272,\n      \"yMax\": 1003,\n      \"hAsc\": 1039,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Serif Caption\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -286,\n      \"tAsc\": 1039,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 286,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -280,\n      \"yMax\": 1002,\n      \"hAsc\": 1039,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Public Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -450,\n      \"tAsc\": 1900,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 2315,\n      \"wDes\": 495,\n      \"xH\": 1034,\n      \"capH\": 1446,\n      \"yMin\": -480,\n      \"yMax\": 2125,\n      \"hAsc\": 1900,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Puppies Play\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 810,\n      \"wDes\": 280,\n      \"xH\": 260,\n      \"capH\": 530,\n      \"yMin\": -278,\n      \"yMax\": 809,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Puritan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 881,\n      \"des\": -256,\n      \"tAsc\": 881,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 881,\n      \"wDes\": 238,\n      \"xH\": 507,\n      \"capH\": 655,\n      \"yMin\": -238,\n      \"yMax\": 881,\n      \"hAsc\": 881,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Purple Purse\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1870,\n      \"des\": -690,\n      \"tAsc\": 1870,\n      \"tDes\": -690,\n      \"tLGap\": 0,\n      \"wAsc\": 1870,\n      \"wDes\": 690,\n      \"xH\": 856,\n      \"capH\": 1419,\n      \"yMin\": -690,\n      \"yMax\": 1869,\n      \"hAsc\": 1870,\n      \"hDes\": -690,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qahiri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 600,\n      \"des\": -250,\n      \"tAsc\": 600,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 250,\n      \"xH\": 230,\n      \"capH\": 560,\n      \"yMin\": -250,\n      \"yMax\": 560,\n      \"hAsc\": 600,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quando\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 1200,\n      \"capH\": 1533,\n      \"yMin\": -514,\n      \"yMax\": 2029,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quantico\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1063,\n      \"des\": -367,\n      \"tAsc\": 1063,\n      \"tDes\": -367,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 367,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -335,\n      \"yMax\": 1033,\n      \"hAsc\": 1063,\n      \"hDes\": -367,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quattrocento\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -260,\n      \"tAsc\": 848,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 848,\n      \"wDes\": 260,\n      \"xH\": 459,\n      \"capH\": 660,\n      \"yMin\": -260,\n      \"yMax\": 849,\n      \"hAsc\": 848,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quattrocento Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -260,\n      \"tAsc\": 848,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 848,\n      \"wDes\": 260,\n      \"xH\": 460,\n      \"capH\": 660,\n      \"yMin\": -260,\n      \"yMax\": 848,\n      \"hAsc\": 848,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Questrial\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 820,\n      \"des\": -210,\n      \"tAsc\": 820,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 440,\n      \"xH\": 500,\n      \"capH\": 662,\n      \"yMin\": -439,\n      \"yMax\": 1028,\n      \"hAsc\": 820,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quicksand\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1183,\n      \"wDes\": 303,\n      \"xH\": 503,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 1133,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quintessential\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2341,\n      \"des\": -799,\n      \"tAsc\": 2341,\n      \"tDes\": -799,\n      \"tLGap\": 0,\n      \"wAsc\": 2341,\n      \"wDes\": 799,\n      \"xH\": 1057,\n      \"capH\": 1489,\n      \"yMin\": -799,\n      \"yMax\": 2340,\n      \"hAsc\": 2341,\n      \"hDes\": -799,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qwigley\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -500,\n      \"tAsc\": 750,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 805,\n      \"wDes\": 500,\n      \"xH\": 300,\n      \"capH\": 460,\n      \"yMin\": -470,\n      \"yMax\": 780,\n      \"hAsc\": 750,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qwitcher Grypen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 802,\n      \"wDes\": 350,\n      \"xH\": 220,\n      \"capH\": 500,\n      \"yMin\": -332,\n      \"yMax\": 786,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Racing Sans One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -284,\n      \"tAsc\": 976,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 284,\n      \"xH\": 430,\n      \"capH\": 635,\n      \"yMin\": -284,\n      \"yMax\": 976,\n      \"hAsc\": 976,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radio Canada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1193,\n      \"wDes\": 448,\n      \"xH\": 515,\n      \"capH\": 690,\n      \"yMin\": -288,\n      \"yMax\": 1152,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radio Canada Big\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -305,\n      \"tAsc\": 995,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 275,\n      \"xH\": 530,\n      \"capH\": 690,\n      \"yMin\": -275,\n      \"yMax\": 1035,\n      \"hAsc\": 995,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radley\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1973,\n      \"des\": -615,\n      \"tAsc\": 1973,\n      \"tDes\": -615,\n      \"tLGap\": 0,\n      \"wAsc\": 1980,\n      \"wDes\": 615,\n      \"xH\": 899,\n      \"capH\": 1302,\n      \"yMin\": -615,\n      \"yMax\": 1980,\n      \"hAsc\": 1973,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rajdhani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -346,\n      \"tAsc\": 930,\n      \"tDes\": -346,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 346,\n      \"xH\": 510,\n      \"capH\": 643,\n      \"yMin\": -314,\n      \"yMax\": 888,\n      \"hAsc\": 930,\n      \"hDes\": -346,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rakkas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -445,\n      \"tAsc\": 1046,\n      \"tDes\": -445,\n      \"tLGap\": 0,\n      \"wAsc\": 1046,\n      \"wDes\": 445,\n      \"xH\": 450,\n      \"capH\": 670,\n      \"yMin\": -445,\n      \"yMax\": 1046,\n      \"hAsc\": 1046,\n      \"hDes\": -445,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Raleway\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -234,\n      \"tAsc\": 940,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 1154,\n      \"wDes\": 234,\n      \"xH\": 519,\n      \"capH\": 710,\n      \"yMin\": -224,\n      \"yMax\": 1141,\n      \"hAsc\": 940,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Raleway Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -213,\n      \"tAsc\": 918,\n      \"tDes\": -213,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 213,\n      \"xH\": 520,\n      \"capH\": 710,\n      \"yMin\": -218,\n      \"yMax\": 940,\n      \"hAsc\": 918,\n      \"hDes\": -213,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramabhadra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 830,\n      \"asc\": 1101,\n      \"des\": -474,\n      \"tAsc\": 1101,\n      \"tDes\": -474,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 474,\n      \"xH\": 439,\n      \"capH\": 571,\n      \"yMin\": -474,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -474,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramaraja\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 741,\n      \"des\": -544,\n      \"tAsc\": 741,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 741,\n      \"wDes\": 544,\n      \"xH\": 293,\n      \"capH\": 439,\n      \"yMin\": -544,\n      \"yMax\": 741,\n      \"hAsc\": 741,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rambla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 929,\n      \"des\": -295,\n      \"tAsc\": 929,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 929,\n      \"wDes\": 295,\n      \"xH\": 506,\n      \"capH\": 668,\n      \"yMin\": -255,\n      \"yMax\": 929,\n      \"hAsc\": 929,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rammetto One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2437,\n      \"des\": -1022,\n      \"tAsc\": 2437,\n      \"tDes\": -1022,\n      \"tLGap\": 0,\n      \"wAsc\": 2453,\n      \"wDes\": 1022,\n      \"xH\": 1243,\n      \"capH\": 1622,\n      \"yMin\": -1022,\n      \"yMax\": 2453,\n      \"hAsc\": 2437,\n      \"hDes\": -1022,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rampart One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 555,\n      \"capH\": 764,\n      \"yMin\": -276,\n      \"yMax\": 1076,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramsina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1560,\n      \"des\": -689,\n      \"tAsc\": 1560,\n      \"tDes\": -689,\n      \"tLGap\": 0,\n      \"wAsc\": 1560,\n      \"wDes\": 689,\n      \"xH\": 612,\n      \"capH\": 864,\n      \"yMin\": -688,\n      \"yMax\": 1425,\n      \"hAsc\": 1560,\n      \"hDes\": -689,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ranchers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -205,\n      \"tAsc\": 1045,\n      \"tDes\": -205,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 205,\n      \"xH\": 598,\n      \"capH\": 818,\n      \"yMin\": -205,\n      \"yMax\": 1045,\n      \"hAsc\": 1045,\n      \"hDes\": -205,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rancho\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 919,\n      \"des\": -329,\n      \"tAsc\": 681,\n      \"tDes\": -259,\n      \"tLGap\": 48,\n      \"wAsc\": 919,\n      \"wDes\": 329,\n      \"xH\": 407,\n      \"capH\": 705,\n      \"yMin\": -329,\n      \"yMax\": 919,\n      \"hAsc\": 919,\n      \"hDes\": -329,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Ranga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2218,\n      \"asc\": 2218,\n      \"des\": -1027,\n      \"tAsc\": 2218,\n      \"tDes\": -1027,\n      \"tLGap\": 0,\n      \"wAsc\": 2218,\n      \"wDes\": 1027,\n      \"xH\": 1040,\n      \"capH\": 1483,\n      \"yMin\": -901,\n      \"yMax\": 2168,\n      \"hAsc\": 2218,\n      \"hDes\": -1027,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rasa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 728,\n      \"des\": -272,\n      \"tAsc\": 728,\n      \"tDes\": -272,\n      \"tLGap\": 218,\n      \"wAsc\": 971,\n      \"wDes\": 422,\n      \"xH\": 413,\n      \"capH\": 568,\n      \"yMin\": -395,\n      \"yMax\": 925,\n      \"hAsc\": 728,\n      \"hDes\": -272,\n      \"lGap\": 218\n    }\n  },\n  {\n    \"family\": \"Rationale\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 903,\n      \"des\": -250,\n      \"tAsc\": 903,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 903,\n      \"wDes\": 250,\n      \"xH\": 508,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 903,\n      \"hAsc\": 903,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ravi Prakash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -684,\n      \"tAsc\": 938,\n      \"tDes\": -684,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 684,\n      \"xH\": 410,\n      \"capH\": 552,\n      \"yMin\": -684,\n      \"yMax\": 938,\n      \"hAsc\": 938,\n      \"hDes\": -684,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Readex Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 555,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -514,\n      \"yMax\": 1134,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Recursive\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1207,\n      \"wDes\": 271,\n      \"xH\": 532,\n      \"capH\": 700,\n      \"yMin\": -362,\n      \"yMax\": 1121,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -264,\n      \"yMax\": 1004,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 488,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 1006,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 488,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 1006,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Rose\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 690,\n      \"xH\": 468,\n      \"capH\": 600,\n      \"yMin\": -680,\n      \"yMax\": 1086,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redacted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -200,\n      \"yMax\": 800,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redacted Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 439,\n      \"capH\": 702,\n      \"yMin\": -30,\n      \"yMax\": 285,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1060,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1060,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1080,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redressed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1907,\n      \"des\": -494,\n      \"tAsc\": 1907,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 1907,\n      \"wDes\": 494,\n      \"xH\": 834,\n      \"capH\": 1495,\n      \"yMin\": -494,\n      \"yMax\": 2353,\n      \"hAsc\": 1907,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi Fun\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi Ink\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reenie Beanie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -314,\n      \"yMax\": 835,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reggae One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 557,\n      \"capH\": 780,\n      \"yMin\": -229,\n      \"yMax\": 1066,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"REM\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -270,\n      \"tAsc\": 980,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 225,\n      \"xH\": 503,\n      \"capH\": 700,\n      \"yMin\": -217,\n      \"yMax\": 1072,\n      \"hAsc\": 980,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rethink Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 992,\n      \"wDes\": 310,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -259,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Revalia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": 382,\n      \"tAsc\": 2146,\n      \"tDes\": 382,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 382,\n      \"xH\": 1140,\n      \"capH\": 879,\n      \"yMin\": -382,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": 382,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rhodium Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -610,\n      \"tAsc\": 1100,\n      \"tDes\": -610,\n      \"tLGap\": 705,\n      \"wAsc\": 1100,\n      \"wDes\": 610,\n      \"xH\": 502,\n      \"capH\": 680,\n      \"yMin\": -532,\n      \"yMax\": 1152,\n      \"hAsc\": 1100,\n      \"hDes\": -610,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ribeye\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2130,\n      \"des\": -668,\n      \"tAsc\": 2130,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 2130,\n      \"wDes\": 668,\n      \"xH\": 1061,\n      \"capH\": 1491,\n      \"yMin\": -668,\n      \"yMax\": 2130,\n      \"hAsc\": 2130,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ribeye Marrow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2130,\n      \"des\": -668,\n      \"tAsc\": 2130,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 2130,\n      \"wDes\": 668,\n      \"xH\": 1061,\n      \"capH\": 1460,\n      \"yMin\": -668,\n      \"yMax\": 2130,\n      \"hAsc\": 2130,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Righteous\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2017,\n      \"des\": -526,\n      \"tAsc\": 2017,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2017,\n      \"wDes\": 526,\n      \"xH\": 1077,\n      \"capH\": 1434,\n      \"yMin\": -526,\n      \"yMax\": 2017,\n      \"hAsc\": 2017,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Risque\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -514,\n      \"tAsc\": 1853,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 514,\n      \"xH\": 1016,\n      \"capH\": 1413,\n      \"yMin\": -514,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -514,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Road Rage\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -250,\n      \"tAsc\": 850,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 965,\n      \"wDes\": 253,\n      \"xH\": 450,\n      \"capH\": 600,\n      \"yMin\": -253,\n      \"yMax\": 965,\n      \"hAsc\": 850,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 102,\n      \"wAsc\": 1946,\n      \"wDes\": 512,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2163,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 102,\n      \"wAsc\": 1946,\n      \"wDes\": 512,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2163,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Flex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2461,\n      \"wDes\": 600,\n      \"xH\": 1052,\n      \"capH\": 1456,\n      \"yMin\": -600,\n      \"yMax\": 2461,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -555,\n      \"tAsc\": 2146,\n      \"tDes\": -555,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 555,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": -555,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 927,\n      \"des\": -244,\n      \"tAsc\": 927,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 251,\n      \"xH\": 518,\n      \"capH\": 710,\n      \"yMin\": -325,\n      \"yMax\": 1193,\n      \"hAsc\": 927,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -555,\n      \"tAsc\": 2146,\n      \"tDes\": -555,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 618,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": -555,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rochester\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2109,\n      \"des\": -528,\n      \"tAsc\": 2109,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 2109,\n      \"wDes\": 528,\n      \"xH\": 192,\n      \"capH\": 326,\n      \"yMin\": -528,\n      \"yMax\": 2109,\n      \"hAsc\": 2109,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rock 3D\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 530,\n      \"capH\": 780,\n      \"yMin\": -246,\n      \"yMax\": 956,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rock Salt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1623,\n      \"des\": -788,\n      \"tAsc\": 824,\n      \"tDes\": -240,\n      \"tLGap\": 63,\n      \"wAsc\": 1623,\n      \"wDes\": 788,\n      \"xH\": 833,\n      \"capH\": 1154,\n      \"yMin\": -787,\n      \"yMax\": 1623,\n      \"hAsc\": 1623,\n      \"hDes\": -788,\n      \"lGap\": 32\n    }\n  },\n  {\n    \"family\": \"RocknRoll One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 572,\n      \"capH\": 800,\n      \"yMin\": -212,\n      \"yMax\": 1034,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rokkitt\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 817,\n      \"des\": -320,\n      \"tAsc\": 817,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 324,\n      \"xH\": 399,\n      \"capH\": 583,\n      \"yMin\": -229,\n      \"yMax\": 937,\n      \"hAsc\": 817,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Romanesco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1866,\n      \"des\": -483,\n      \"tAsc\": 1866,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1866,\n      \"wDes\": 483,\n      \"xH\": 780,\n      \"capH\": 1393,\n      \"yMin\": -483,\n      \"yMax\": 1866,\n      \"hAsc\": 1866,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ropa Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 841,\n      \"des\": -231,\n      \"tAsc\": 841,\n      \"tDes\": -231,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 231,\n      \"xH\": 488,\n      \"capH\": 655,\n      \"yMin\": -231,\n      \"yMax\": 865,\n      \"hAsc\": 841,\n      \"hDes\": -231,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rosario\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 977,\n      \"des\": -235,\n      \"tAsc\": 977,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 292,\n      \"xH\": 497,\n      \"capH\": 728,\n      \"yMin\": -286,\n      \"yMax\": 1139,\n      \"hAsc\": 977,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rosarivo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 979,\n      \"des\": -424,\n      \"tAsc\": 979,\n      \"tDes\": -424,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 424,\n      \"xH\": 170,\n      \"capH\": 757,\n      \"yMin\": -424,\n      \"yMax\": 979,\n      \"hAsc\": 979,\n      \"hDes\": -424,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rouge Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1250,\n      \"asc\": 1050,\n      \"des\": -419,\n      \"tAsc\": 1050,\n      \"tDes\": -419,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 419,\n      \"xH\": 534,\n      \"capH\": 385,\n      \"yMin\": -419,\n      \"yMax\": 1050,\n      \"hAsc\": 1050,\n      \"hDes\": -419,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rowdies\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -245,\n      \"tAsc\": 997,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 700,\n      \"xH\": 473,\n      \"capH\": 708,\n      \"yMin\": -680,\n      \"yMax\": 1228,\n      \"hAsc\": 997,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rozha One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -422,\n      \"tAsc\": 998,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 422,\n      \"xH\": 460,\n      \"capH\": 560,\n      \"yMin\": -422,\n      \"yMax\": 998,\n      \"hAsc\": 998,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 466,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -478,\n      \"yMax\": 1076,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik 80s Fade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -294,\n      \"yMax\": 942,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Beastly\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -374,\n      \"yMax\": 1040,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Broken Fax\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 308,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 938,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Bubbles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -327,\n      \"yMax\": 971,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Burned\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 978,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Dirt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -312,\n      \"yMax\": 950,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Distressed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 962,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Doodle Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 967,\n      \"wDes\": 340,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -340,\n      \"yMax\": 967,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Doodle Triangles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 963,\n      \"wDes\": 324,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -324,\n      \"yMax\": 963,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Gemstones\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -319,\n      \"yMax\": 959,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Glitch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Glitch Pop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 360,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -305,\n      \"yMax\": 946,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Iso\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -315,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Lines\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 307,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -304,\n      \"yMax\": 952,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Maps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 307,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 946,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Marker Hatch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Maze\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -313,\n      \"yMax\": 931,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Microbe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -312,\n      \"yMax\": 954,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Mono One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -306,\n      \"tAsc\": 932,\n      \"tDes\": -306,\n      \"tLGap\": 0,\n      \"wAsc\": 932,\n      \"wDes\": 306,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 932,\n      \"hDes\": -306,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Moonrocks\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Pixels\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -287,\n      \"yMax\": 955,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Puddles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -399,\n      \"yMax\": 1067,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Scribble\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 321,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -321,\n      \"yMax\": 959,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Spray Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -331,\n      \"yMax\": 990,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Storm\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -336,\n      \"yMax\": 957,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Vinyl\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -361,\n      \"yMax\": 983,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Wet Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -490,\n      \"yMax\": 947,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruda\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -295,\n      \"tAsc\": 922,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 295,\n      \"xH\": 582,\n      \"capH\": 695,\n      \"yMin\": -233,\n      \"yMax\": 1030,\n      \"hAsc\": 922,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rufina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -290,\n      \"tAsc\": 945,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 290,\n      \"xH\": 488,\n      \"capH\": 668,\n      \"yMin\": -290,\n      \"yMax\": 939,\n      \"hAsc\": 945,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruge Boogie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -375,\n      \"tAsc\": 875,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 504,\n      \"xH\": 390,\n      \"capH\": 640,\n      \"yMin\": -504,\n      \"yMax\": 1026,\n      \"hAsc\": 875,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruluko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 914,\n      \"des\": -241,\n      \"tAsc\": 914,\n      \"tDes\": -241,\n      \"tLGap\": 0,\n      \"wAsc\": 914,\n      \"wDes\": 241,\n      \"xH\": 470,\n      \"capH\": 690,\n      \"yMin\": -241,\n      \"yMax\": 914,\n      \"hAsc\": 914,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rum Raisin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2013,\n      \"des\": -629,\n      \"tAsc\": 2013,\n      \"tDes\": -629,\n      \"tLGap\": 0,\n      \"wAsc\": 2013,\n      \"wDes\": 629,\n      \"xH\": 1118,\n      \"capH\": 1466,\n      \"yMin\": -629,\n      \"yMax\": 2013,\n      \"hAsc\": 2013,\n      \"hDes\": -629,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruslan Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 688,\n      \"des\": -397,\n      \"tAsc\": 688,\n      \"tDes\": -397,\n      \"tLGap\": 0,\n      \"wAsc\": 704,\n      \"wDes\": 397,\n      \"xH\": 500,\n      \"capH\": 500,\n      \"yMin\": -397,\n      \"yMax\": 704,\n      \"hAsc\": 688,\n      \"hDes\": -397,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Russo One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -279,\n      \"tAsc\": 926,\n      \"tDes\": -279,\n      \"tLGap\": 0,\n      \"wAsc\": 926,\n      \"wDes\": 279,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -279,\n      \"yMax\": 926,\n      \"hAsc\": 926,\n      \"hDes\": -279,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruthie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 524,\n      \"xH\": 315,\n      \"capH\": 701,\n      \"yMin\": -524,\n      \"yMax\": 938,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruwudu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 867,\n      \"des\": -741,\n      \"tAsc\": 867,\n      \"tDes\": -741,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 1200,\n      \"xH\": 430,\n      \"capH\": 660,\n      \"yMin\": -840,\n      \"yMax\": 1223,\n      \"hAsc\": 867,\n      \"hDes\": -741,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rye\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 387,\n      \"capH\": 363,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sacramento\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1905,\n      \"des\": -1084,\n      \"tAsc\": 1905,\n      \"tDes\": -1084,\n      \"tLGap\": 0,\n      \"wAsc\": 1905,\n      \"wDes\": 1084,\n      \"xH\": 627,\n      \"capH\": 1550,\n      \"yMin\": -1084,\n      \"yMax\": 1905,\n      \"hAsc\": 1905,\n      \"hDes\": -1084,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sahitya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1106,\n      \"des\": -447,\n      \"tAsc\": 1106,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 447,\n      \"xH\": 452,\n      \"capH\": 637,\n      \"yMin\": -412,\n      \"yMax\": 1053,\n      \"hAsc\": 1106,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sail\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -294,\n      \"tAsc\": 860,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 294,\n      \"xH\": 435,\n      \"capH\": 666,\n      \"yMin\": -294,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -398,\n      \"yMax\": 1167,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -351,\n      \"yMax\": 1090,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -348,\n      \"yMax\": 1088,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -359,\n      \"yMax\": 1095,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -398,\n      \"yMax\": 1160,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Stencil One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1163,\n      \"wDes\": 360,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -354,\n      \"yMax\": 1163,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Salsa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -252,\n      \"tAsc\": 974,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 252,\n      \"xH\": 113,\n      \"capH\": 82,\n      \"yMin\": -252,\n      \"yMax\": 974,\n      \"hAsc\": 974,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sanchez\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -274,\n      \"tAsc\": 1004,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 274,\n      \"xH\": 492,\n      \"capH\": 718,\n      \"yMin\": -274,\n      \"yMax\": 1004,\n      \"hAsc\": 1004,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sancreek\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2104,\n      \"des\": -738,\n      \"tAsc\": 2104,\n      \"tDes\": -738,\n      \"tLGap\": 0,\n      \"wAsc\": 2104,\n      \"wDes\": 738,\n      \"xH\": 402,\n      \"capH\": 281,\n      \"yMin\": -738,\n      \"yMax\": 2104,\n      \"hAsc\": 2104,\n      \"hDes\": -738,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sankofa Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1081,\n      \"wDes\": 315,\n      \"xH\": 450,\n      \"capH\": 700,\n      \"yMin\": -267,\n      \"yMax\": 1018,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansation\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -438,\n      \"tAsc\": 1854,\n      \"tDes\": -438,\n      \"tLGap\": 0,\n      \"wAsc\": 1854,\n      \"wDes\": 438,\n      \"yMin\": -434,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -438,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansita\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -180,\n      \"tAsc\": 1020,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 284,\n      \"xH\": 510,\n      \"capH\": 660,\n      \"yMin\": -256,\n      \"yMax\": 920,\n      \"hAsc\": 1020,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansita Swashed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -180,\n      \"tAsc\": 1020,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1134,\n      \"wDes\": 337,\n      \"xH\": 510,\n      \"capH\": 660,\n      \"yMin\": -299,\n      \"yMax\": 1111,\n      \"hAsc\": 1020,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarabun\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -232,\n      \"tAsc\": 1068,\n      \"tDes\": -232,\n      \"tLGap\": 0,\n      \"wAsc\": 1286,\n      \"wDes\": 567,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -535,\n      \"yMax\": 1265,\n      \"hAsc\": 1068,\n      \"hDes\": -232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarala\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2398,\n      \"des\": -941,\n      \"tAsc\": 2398,\n      \"tDes\": -941,\n      \"tLGap\": 0,\n      \"wAsc\": 2398,\n      \"wDes\": 941,\n      \"xH\": 1053,\n      \"capH\": 1450,\n      \"yMin\": -829,\n      \"yMax\": 2300,\n      \"hAsc\": 2398,\n      \"hDes\": -941,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarina\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1916,\n      \"des\": -644,\n      \"tAsc\": 1916,\n      \"tDes\": -644,\n      \"tLGap\": 0,\n      \"wAsc\": 1916,\n      \"wDes\": 644,\n      \"xH\": 1022,\n      \"capH\": 1530,\n      \"yMin\": -664,\n      \"yMax\": 1916,\n      \"hAsc\": 1916,\n      \"hDes\": -644,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarpanch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 350,\n      \"xH\": 485,\n      \"capH\": 622,\n      \"yMin\": -483,\n      \"yMax\": 996,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sassy Frass\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 300,\n      \"xH\": 220,\n      \"capH\": 550,\n      \"yMin\": -285,\n      \"yMax\": 759,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Satisfy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 957,\n      \"des\": -501,\n      \"tAsc\": 724,\n      \"tDes\": -465,\n      \"tLGap\": 34,\n      \"wAsc\": 957,\n      \"wDes\": 501,\n      \"xH\": 417,\n      \"capH\": 767,\n      \"yMin\": -501,\n      \"yMax\": 957,\n      \"hAsc\": 957,\n      \"hDes\": -501,\n      \"lGap\": 17\n    }\n  },\n  {\n    \"family\": \"Savate\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -285,\n      \"tAsc\": 1015,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 551,\n      \"capH\": 730,\n      \"yMin\": -348,\n      \"yMax\": 1137,\n      \"hAsc\": 1015,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sawarabi Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1110,\n      \"des\": -272,\n      \"tAsc\": 834,\n      \"tDes\": -166,\n      \"tLGap\": 90,\n      \"wAsc\": 1110,\n      \"wDes\": 292,\n      \"xH\": 524,\n      \"capH\": 725,\n      \"yMin\": -282,\n      \"yMax\": 1100,\n      \"hAsc\": 1110,\n      \"hDes\": -272,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Sawarabi Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -319,\n      \"tAsc\": 834,\n      \"tDes\": -165,\n      \"tLGap\": 90,\n      \"wAsc\": 1071,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -320,\n      \"yMax\": 1070,\n      \"hAsc\": 1070,\n      \"hDes\": -319,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Scada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -289,\n      \"tAsc\": 955,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 289,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 930,\n      \"hAsc\": 955,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Scheherazade New\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2750,\n      \"des\": -1427,\n      \"tAsc\": 2750,\n      \"tDes\": -1427,\n      \"tLGap\": 0,\n      \"wAsc\": 2884,\n      \"wDes\": 2100,\n      \"xH\": 684,\n      \"capH\": 1034,\n      \"yMin\": -1509,\n      \"yMax\": 2694,\n      \"hAsc\": 2750,\n      \"hDes\": -1427,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Schibsted Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -528,\n      \"tAsc\": 2000,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 2502,\n      \"wDes\": 568,\n      \"xH\": 1080,\n      \"capH\": 1440,\n      \"yMin\": -485,\n      \"yMax\": 2427,\n      \"hAsc\": 2000,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Schoolbell\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -383,\n      \"tAsc\": 794,\n      \"tDes\": -326,\n      \"tLGap\": 48,\n      \"wAsc\": 1019,\n      \"wDes\": 383,\n      \"xH\": 485,\n      \"capH\": 770,\n      \"yMin\": -383,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -383,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Science Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2176,\n      \"des\": -776,\n      \"tAsc\": 2176,\n      \"tDes\": -776,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 708,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -619,\n      \"yMax\": 2173,\n      \"hAsc\": 2176,\n      \"hDes\": -776,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Scope One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -455,\n      \"tAsc\": 928,\n      \"tDes\": -455,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 455,\n      \"xH\": 500,\n      \"capH\": 645,\n      \"yMin\": -455,\n      \"yMax\": 928,\n      \"hAsc\": 928,\n      \"hDes\": -455,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Seaweed Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 969,\n      \"des\": -421,\n      \"tAsc\": 969,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 969,\n      \"wDes\": 431,\n      \"xH\": 380,\n      \"capH\": 765,\n      \"yMin\": -420,\n      \"yMax\": 969,\n      \"hAsc\": 969,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Secular One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1022,\n      \"des\": -433,\n      \"tAsc\": 1022,\n      \"tDes\": -433,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 433,\n      \"xH\": 515,\n      \"capH\": 666,\n      \"yMin\": -433,\n      \"yMax\": 1022,\n      \"hAsc\": 1022,\n      \"hDes\": -433,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 407,\n      \"xH\": 438,\n      \"capH\": 675,\n      \"yMin\": -407,\n      \"yMax\": 989,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedan SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 407,\n      \"xH\": 438,\n      \"capH\": 675,\n      \"yMin\": -407,\n      \"yMax\": 989,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedgwick Ave\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 2555,\n      \"wDes\": 551,\n      \"xH\": 660,\n      \"capH\": 950,\n      \"yMin\": -521,\n      \"yMax\": 1361,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedgwick Ave Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 2555,\n      \"wDes\": 551,\n      \"xH\": 650,\n      \"capH\": 950,\n      \"yMin\": -551,\n      \"yMax\": 2555,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sekuya\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 971,\n      \"wDes\": 277,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 971,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 962,\n      \"des\": -270,\n      \"tAsc\": 962,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 342,\n      \"xH\": 500,\n      \"capH\": 670,\n      \"yMin\": -255,\n      \"yMax\": 940,\n      \"hAsc\": 962,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Send Flowers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -350,\n      \"tAsc\": 975,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 480,\n      \"xH\": 395,\n      \"capH\": 710,\n      \"yMin\": -473,\n      \"yMax\": 1068,\n      \"hAsc\": 975,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sevillana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2062,\n      \"des\": -717,\n      \"tAsc\": 2062,\n      \"tDes\": -717,\n      \"tLGap\": 0,\n      \"wAsc\": 2062,\n      \"wDes\": 717,\n      \"xH\": 860,\n      \"capH\": 1679,\n      \"yMin\": -717,\n      \"yMax\": 2062,\n      \"hAsc\": 2062,\n      \"hDes\": -717,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Seymour One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -559,\n      \"tAsc\": 2015,\n      \"tDes\": -559,\n      \"tLGap\": 0,\n      \"wAsc\": 2202,\n      \"wDes\": 890,\n      \"xH\": 1026,\n      \"capH\": 1465,\n      \"yMin\": -887,\n      \"yMax\": 2182,\n      \"hAsc\": 2015,\n      \"hDes\": -559,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shadows Into Light\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1203,\n      \"des\": -442,\n      \"tAsc\": 1203,\n      \"tDes\": -443,\n      \"tLGap\": 0,\n      \"wAsc\": 1203,\n      \"wDes\": 440,\n      \"xH\": 616,\n      \"capH\": 648,\n      \"yMin\": -434,\n      \"yMax\": 1203,\n      \"hAsc\": 1203,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shadows Into Light Two\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1145,\n      \"des\": -341,\n      \"tAsc\": 1145,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 341,\n      \"xH\": 610,\n      \"capH\": 848,\n      \"yMin\": -341,\n      \"yMax\": 1145,\n      \"hAsc\": 1145,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shafarik\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1080,\n      \"des\": -462,\n      \"tAsc\": 1080,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1080,\n      \"wDes\": 462,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -462,\n      \"yMax\": 1080,\n      \"hAsc\": 1080,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shalimar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -420,\n      \"tAsc\": 800,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 994,\n      \"wDes\": 645,\n      \"xH\": 315,\n      \"capH\": 560,\n      \"yMin\": -642,\n      \"yMax\": 994,\n      \"hAsc\": 800,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shantell Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1215,\n      \"wDes\": 515,\n      \"xH\": 491,\n      \"capH\": 700,\n      \"yMin\": -509,\n      \"yMax\": 1134,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shanti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2012,\n      \"des\": -599,\n      \"tAsc\": 2012,\n      \"tDes\": -599,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 639,\n      \"xH\": 984,\n      \"capH\": 1412,\n      \"yMin\": -569,\n      \"yMax\": 2026,\n      \"hAsc\": 2012,\n      \"hDes\": -599,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 707,\n      \"yMin\": -240,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share Tech\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share Tech Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Antique\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 524,\n      \"capH\": 733,\n      \"yMin\": -336,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Antique B1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 524,\n      \"capH\": 733,\n      \"yMin\": -336,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 480,\n      \"capH\": 726,\n      \"yMin\": -266,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Mincho B1\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 480,\n      \"capH\": 726,\n      \"yMin\": -266,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shizuru\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 400,\n      \"capH\": 700,\n      \"yMin\": -288,\n      \"yMax\": 898,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shojumaru\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -692,\n      \"tAsc\": 2020,\n      \"tDes\": -692,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 692,\n      \"xH\": 1206,\n      \"capH\": 1534,\n      \"yMin\": -692,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Short Stack\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1913,\n      \"des\": -609,\n      \"tAsc\": 1913,\n      \"tDes\": -609,\n      \"tLGap\": 0,\n      \"wAsc\": 1913,\n      \"wDes\": 609,\n      \"xH\": 758,\n      \"capH\": 1367,\n      \"yMin\": -609,\n      \"yMax\": 1913,\n      \"hAsc\": 1913,\n      \"hDes\": -609,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shrikhand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1026,\n      \"des\": -432,\n      \"tAsc\": 1026,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 432,\n      \"xH\": 520,\n      \"capH\": 669,\n      \"yMin\": -432,\n      \"yMax\": 1026,\n      \"hAsc\": 1026,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Siemreap\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2502,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Sigmar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -466,\n      \"tAsc\": 1172,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1275,\n      \"wDes\": 477,\n      \"xH\": 578,\n      \"capH\": 655,\n      \"yMin\": -477,\n      \"yMax\": 1275,\n      \"hAsc\": 1172,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sigmar One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -466,\n      \"tAsc\": 1172,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 466,\n      \"xH\": 578,\n      \"capH\": 676,\n      \"yMin\": -375,\n      \"yMax\": 1182,\n      \"hAsc\": 1172,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Signika\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1880,\n      \"des\": -584,\n      \"tAsc\": 1880,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2307,\n      \"wDes\": 592,\n      \"xH\": 996,\n      \"capH\": 1366,\n      \"yMin\": -532,\n      \"yMax\": 2175,\n      \"hAsc\": 1880,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Signika Negative\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1880,\n      \"des\": -584,\n      \"tAsc\": 1880,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2307,\n      \"wDes\": 592,\n      \"xH\": 980,\n      \"capH\": 1370,\n      \"yMin\": -526,\n      \"yMax\": 2162,\n      \"hAsc\": 1880,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Silkscreen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -250,\n      \"tAsc\": 1030,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1030,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Simonetta\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1970,\n      \"des\": -594,\n      \"tAsc\": 1970,\n      \"tDes\": -594,\n      \"tLGap\": 0,\n      \"wAsc\": 1970,\n      \"wDes\": 594,\n      \"xH\": 897,\n      \"capH\": 1391,\n      \"yMin\": -545,\n      \"yMax\": 1927,\n      \"hAsc\": 1970,\n      \"hDes\": -594,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Single Day\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 779,\n      \"des\": -245,\n      \"tAsc\": 779,\n      \"tDes\": -245,\n      \"tLGap\": 256,\n      \"wAsc\": 779,\n      \"wDes\": 245,\n      \"xH\": 390,\n      \"capH\": 582,\n      \"yMin\": -241,\n      \"yMax\": 773,\n      \"hAsc\": 779,\n      \"hDes\": -245,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Sintony\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -308,\n      \"tAsc\": 995,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 308,\n      \"xH\": 572,\n      \"capH\": 730,\n      \"yMin\": -301,\n      \"yMax\": 988,\n      \"hAsc\": 995,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sirin Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2380,\n      \"des\": -604,\n      \"tAsc\": 2380,\n      \"tDes\": -604,\n      \"tLGap\": 0,\n      \"wAsc\": 2380,\n      \"wDes\": 604,\n      \"xH\": 1055,\n      \"capH\": 1423,\n      \"yMin\": -604,\n      \"yMax\": 2380,\n      \"hAsc\": 2380,\n      \"hDes\": -604,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sirivennela\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 927,\n      \"des\": -513,\n      \"tAsc\": 927,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1091,\n      \"wDes\": 982,\n      \"xH\": 419,\n      \"capH\": 661,\n      \"yMin\": -868,\n      \"yMax\": 878,\n      \"hAsc\": 927,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Six Caps\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2263,\n      \"des\": -432,\n      \"tAsc\": 2263,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 432,\n      \"yMin\": -506,\n      \"yMax\": 2281,\n      \"hAsc\": 2263,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sixtyfour\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sixtyfour Convergence\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Skranji\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1008,\n      \"des\": -383,\n      \"tAsc\": 1008,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 1008,\n      \"wDes\": 383,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -327,\n      \"yMax\": 1008,\n      \"hAsc\": 1008,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slabo 13px\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 780,\n      \"asc\": 720,\n      \"des\": -240,\n      \"tAsc\": 720,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 720,\n      \"wDes\": 240,\n      \"xH\": 420,\n      \"capH\": 540,\n      \"yMin\": -180,\n      \"yMax\": 750,\n      \"hAsc\": 720,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slabo 27px\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 810,\n      \"asc\": 750,\n      \"des\": -240,\n      \"tAsc\": 750,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 750,\n      \"wDes\": 240,\n      \"xH\": 390,\n      \"capH\": 540,\n      \"yMin\": -190,\n      \"yMax\": 740,\n      \"hAsc\": 750,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slackey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1078,\n      \"des\": -351,\n      \"tAsc\": 769,\n      \"tDes\": -74,\n      \"tLGap\": 55,\n      \"wAsc\": 1078,\n      \"wDes\": 351,\n      \"xH\": 691,\n      \"capH\": 772,\n      \"yMin\": -351,\n      \"yMax\": 1078,\n      \"hAsc\": 1078,\n      \"hDes\": -351,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Slackside One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 255,\n      \"capH\": 513,\n      \"yMin\": -286,\n      \"yMax\": 770,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smokum\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1986,\n      \"des\": -512,\n      \"tAsc\": 1986,\n      \"tDes\": -512,\n      \"tLGap\": 0,\n      \"wAsc\": 1986,\n      \"wDes\": 512,\n      \"xH\": 1024,\n      \"capH\": 1536,\n      \"yMin\": -512,\n      \"yMax\": 1986,\n      \"hAsc\": 1986,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smooch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -450,\n      \"tAsc\": 950,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1159,\n      \"wDes\": 563,\n      \"xH\": 375,\n      \"capH\": 640,\n      \"yMin\": -563,\n      \"yMax\": 1159,\n      \"hAsc\": 950,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smooch Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 300,\n      \"xH\": 470,\n      \"capH\": 620,\n      \"yMin\": -257,\n      \"yMax\": 930,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smythe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1883,\n      \"des\": -480,\n      \"tAsc\": 1883,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1883,\n      \"wDes\": 480,\n      \"xH\": 963,\n      \"capH\": 1317,\n      \"yMin\": -527,\n      \"yMax\": 1883,\n      \"hAsc\": 1883,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SN Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -315,\n      \"tAsc\": 985,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 670,\n      \"yMin\": -277,\n      \"yMax\": 1049,\n      \"hAsc\": 985,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sniglet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -289,\n      \"tAsc\": 956,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 289,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 952,\n      \"hAsc\": 956,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Snippet\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -261,\n      \"tAsc\": 890,\n      \"tDes\": -261,\n      \"tLGap\": 0,\n      \"wAsc\": 890,\n      \"wDes\": 261,\n      \"xH\": 498,\n      \"capH\": 684,\n      \"yMin\": -261,\n      \"yMax\": 890,\n      \"hAsc\": 890,\n      \"hDes\": -261,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Snowburst One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2134,\n      \"des\": -454,\n      \"tAsc\": 2134,\n      \"tDes\": -454,\n      \"tLGap\": 0,\n      \"wAsc\": 2134,\n      \"wDes\": 454,\n      \"xH\": 1347,\n      \"capH\": 1635,\n      \"yMin\": -454,\n      \"yMax\": 2134,\n      \"hAsc\": 2134,\n      \"hDes\": -454,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofadi One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -310,\n      \"tAsc\": 856,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 856,\n      \"hAsc\": 856,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1138,\n      \"des\": -438,\n      \"tAsc\": 1138,\n      \"tDes\": -438,\n      \"tLGap\": 0,\n      \"wAsc\": 1138,\n      \"wDes\": 438,\n      \"xH\": 441,\n      \"capH\": 700,\n      \"yMin\": -438,\n      \"yMax\": 1138,\n      \"hAsc\": 1138,\n      \"hDes\": -438,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 488,\n      \"capH\": 655,\n      \"yMin\": -243,\n      \"yMax\": 904,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 655,\n      \"yMin\": -227,\n      \"yMax\": 871,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 486,\n      \"capH\": 655,\n      \"yMin\": -225,\n      \"yMax\": 867,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 655,\n      \"yMin\": -231,\n      \"yMax\": 895,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Solitreo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -550,\n      \"tAsc\": 880,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 600,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -528,\n      \"yMax\": 989,\n      \"hAsc\": 880,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Solway\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 954,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sometype Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 929,\n      \"wDes\": 295,\n      \"xH\": 470,\n      \"capH\": 650,\n      \"yMin\": -293,\n      \"yMax\": 923,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Song Myung\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -152,\n      \"tAsc\": 848,\n      \"tDes\": -152,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 235,\n      \"xH\": 457,\n      \"capH\": 635,\n      \"yMin\": -230,\n      \"yMax\": 848,\n      \"hAsc\": 848,\n      \"hDes\": -152,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1824,\n      \"des\": -576,\n      \"tAsc\": 1824,\n      \"tDes\": -576,\n      \"tLGap\": 0,\n      \"wAsc\": 2122,\n      \"wDes\": 522,\n      \"xH\": 952,\n      \"capH\": 1238,\n      \"yMin\": -496,\n      \"yMax\": 1997,\n      \"hAsc\": 1824,\n      \"hDes\": -576,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sonsie One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2050,\n      \"des\": -600,\n      \"tAsc\": 2050,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2050,\n      \"wDes\": 600,\n      \"xH\": 272,\n      \"capH\": 506,\n      \"yMin\": -600,\n      \"yMax\": 2050,\n      \"hAsc\": 2050,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sora\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -290,\n      \"tAsc\": 970,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1220,\n      \"wDes\": 320,\n      \"xH\": 534,\n      \"capH\": 730,\n      \"yMin\": -284,\n      \"yMax\": 1180,\n      \"hAsc\": 970,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sorts Mill Goudy\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -478,\n      \"tAsc\": 960,\n      \"tDes\": -478,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 478,\n      \"xH\": 442,\n      \"capH\": 713,\n      \"yMin\": -438,\n      \"yMax\": 960,\n      \"hAsc\": 960,\n      \"hDes\": -478,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sour Gummy\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 996,\n      \"des\": -296,\n      \"tAsc\": 996,\n      \"tDes\": -296,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 508,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 866,\n      \"hAsc\": 996,\n      \"hDes\": -296,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Code Pro\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -273,\n      \"tAsc\": 984,\n      \"tDes\": -273,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 454,\n      \"xH\": 486,\n      \"capH\": 660,\n      \"yMin\": -454,\n      \"yMax\": 1060,\n      \"hAsc\": 984,\n      \"hDes\": -273,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Sans 3\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1024,\n      \"des\": -400,\n      \"tAsc\": 1024,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 288,\n      \"xH\": 486,\n      \"capH\": 660,\n      \"yMin\": -295,\n      \"yMax\": 958,\n      \"hAsc\": 1024,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Serif 4\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 324,\n      \"xH\": 475,\n      \"capH\": 670,\n      \"yMin\": -328,\n      \"yMax\": 998,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Space Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -292,\n      \"tAsc\": 984,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 292,\n      \"xH\": 486,\n      \"capH\": 700,\n      \"yMin\": -277,\n      \"yMax\": 1096,\n      \"hAsc\": 984,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Space Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1120,\n      \"des\": -361,\n      \"tAsc\": 1120,\n      \"tDes\": -361,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 361,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 1085,\n      \"hAsc\": 1120,\n      \"hDes\": -361,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Elite\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 608,\n      \"xH\": 528,\n      \"capH\": 713,\n      \"yMin\": -659,\n      \"yMax\": 1962,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 504,\n      \"capH\": 710,\n      \"yMin\": -242,\n      \"yMax\": 913,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic Condensed One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 509,\n      \"capH\": 710,\n      \"yMin\": -254,\n      \"yMax\": 927,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic Expanded One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 514,\n      \"capH\": 710,\n      \"yMin\": -298,\n      \"yMax\": 956,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spectral\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1059,\n      \"des\": -463,\n      \"tAsc\": 1059,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 1059,\n      \"wDes\": 463,\n      \"xH\": 450,\n      \"capH\": 660,\n      \"yMin\": -250,\n      \"yMax\": 1057,\n      \"hAsc\": 1059,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spectral SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1059,\n      \"des\": -463,\n      \"tAsc\": 1059,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 1059,\n      \"wDes\": 463,\n      \"xH\": 450,\n      \"capH\": 660,\n      \"yMin\": -250,\n      \"yMax\": 1057,\n      \"hAsc\": 1059,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spicy Rice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2091,\n      \"des\": -733,\n      \"tAsc\": 2091,\n      \"tDes\": -733,\n      \"tLGap\": 0,\n      \"wAsc\": 2091,\n      \"wDes\": 733,\n      \"xH\": 1208,\n      \"capH\": 1481,\n      \"yMin\": -733,\n      \"yMax\": 2091,\n      \"hAsc\": 2091,\n      \"hDes\": -733,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spinnaker\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -487,\n      \"tAsc\": 1920,\n      \"tDes\": -487,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 487,\n      \"xH\": 1000,\n      \"capH\": 1416,\n      \"yMin\": -487,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -487,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spirax\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 947,\n      \"des\": -288,\n      \"tAsc\": 947,\n      \"tDes\": -288,\n      \"tLGap\": 0,\n      \"wAsc\": 947,\n      \"wDes\": 288,\n      \"xH\": 463,\n      \"capH\": 696,\n      \"yMin\": -288,\n      \"yMax\": 947,\n      \"hAsc\": 947,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Splash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -580,\n      \"tAsc\": 1050,\n      \"tDes\": -580,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 976,\n      \"xH\": 440,\n      \"capH\": 700,\n      \"yMin\": -976,\n      \"yMax\": 1299,\n      \"hAsc\": 1050,\n      \"hDes\": -580,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spline Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1927,\n      \"des\": -473,\n      \"tAsc\": 1927,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 2024,\n      \"wDes\": 605,\n      \"xH\": 1091,\n      \"capH\": 1454,\n      \"yMin\": -503,\n      \"yMax\": 1978,\n      \"hAsc\": 1927,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spline Sans Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1927,\n      \"des\": -473,\n      \"tAsc\": 1927,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 2160,\n      \"wDes\": 622,\n      \"xH\": 1091,\n      \"capH\": 1454,\n      \"yMin\": -548,\n      \"yMax\": 1993,\n      \"hAsc\": 1927,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Squada One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 861,\n      \"des\": -196,\n      \"tAsc\": 861,\n      \"tDes\": -196,\n      \"tLGap\": 0,\n      \"wAsc\": 861,\n      \"wDes\": 196,\n      \"xH\": 498,\n      \"capH\": 647,\n      \"yMin\": -196,\n      \"yMax\": 861,\n      \"hAsc\": 861,\n      \"hDes\": -196,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Square Peg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -400,\n      \"tAsc\": 920,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 410,\n      \"xH\": 260,\n      \"capH\": 600,\n      \"yMin\": -409,\n      \"yMax\": 1012,\n      \"hAsc\": 920,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sree Krushnadevaraya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 720,\n      \"asc\": 1105,\n      \"des\": -378,\n      \"tAsc\": 1105,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 378,\n      \"xH\": 273,\n      \"capH\": 408,\n      \"yMin\": -378,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sriracha\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1220,\n      \"des\": -550,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1220,\n      \"wDes\": 550,\n      \"xH\": 474,\n      \"capH\": 656,\n      \"yMin\": -562,\n      \"yMax\": 1220,\n      \"hAsc\": 1220,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Srisakdi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1484,\n      \"wDes\": 664,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -664,\n      \"yMax\": 1484,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Staatliches\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 306,\n      \"xH\": 500,\n      \"capH\": 696,\n      \"yMin\": -306,\n      \"yMax\": 1006,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Headline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Notch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stalemate\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1837,\n      \"des\": -1165,\n      \"tAsc\": 1837,\n      \"tDes\": -1165,\n      \"tLGap\": 0,\n      \"wAsc\": 1837,\n      \"wDes\": 1165,\n      \"xH\": 539,\n      \"capH\": 1501,\n      \"yMin\": -1165,\n      \"yMax\": 1837,\n      \"hAsc\": 1837,\n      \"hDes\": -1165,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stalinist One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1037,\n      \"des\": -439,\n      \"tAsc\": 1037,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1037,\n      \"wDes\": 439,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -439,\n      \"yMax\": 1037,\n      \"hAsc\": 1037,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stardos Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1994,\n      \"des\": -831,\n      \"tAsc\": 1994,\n      \"tDes\": -831,\n      \"tLGap\": 0,\n      \"wAsc\": 1994,\n      \"wDes\": 831,\n      \"xH\": 981,\n      \"capH\": 1421,\n      \"yMin\": -808,\n      \"yMax\": 1970,\n      \"hAsc\": 1994,\n      \"hDes\": -831,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stick\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 715,\n      \"yMin\": -274,\n      \"yMax\": 1160,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stick No Bills\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -312,\n      \"tAsc\": 940,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1237,\n      \"wDes\": 622,\n      \"xH\": 515,\n      \"capH\": 700,\n      \"yMin\": -311,\n      \"yMax\": 946,\n      \"hAsc\": 940,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stint Ultra Condensed\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1829,\n      \"des\": -483,\n      \"tAsc\": 1829,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1829,\n      \"wDes\": 483,\n      \"xH\": 952,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1829,\n      \"hAsc\": 1829,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stint Ultra Expanded\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -483,\n      \"tAsc\": 1853,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 483,\n      \"xH\": 952,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"STIX Two Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 762,\n      \"des\": -238,\n      \"tAsc\": 762,\n      \"tDes\": -238,\n      \"tLGap\": 250,\n      \"wAsc\": 1047,\n      \"wDes\": 441,\n      \"xH\": 473,\n      \"capH\": 657,\n      \"yMin\": -373,\n      \"yMax\": 1047,\n      \"hAsc\": 762,\n      \"hDes\": -238,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Stoke\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 479,\n      \"capH\": 683,\n      \"yMin\": -526,\n      \"yMax\": 2027,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Story Script\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -340,\n      \"tAsc\": 959,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 365,\n      \"xH\": 438,\n      \"capH\": 617,\n      \"yMin\": -363,\n      \"yMax\": 1022,\n      \"hAsc\": 959,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Strait\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 901,\n      \"des\": -194,\n      \"tAsc\": 901,\n      \"tDes\": -194,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 265,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -265,\n      \"yMax\": 958,\n      \"hAsc\": 901,\n      \"hDes\": -194,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Style Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -520,\n      \"tAsc\": 1000,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 800,\n      \"xH\": 434,\n      \"capH\": 700,\n      \"yMin\": -799,\n      \"yMax\": 1113,\n      \"hAsc\": 1000,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stylish\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 821,\n      \"des\": -179,\n      \"tAsc\": 821,\n      \"tDes\": -179,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 235,\n      \"xH\": 410,\n      \"capH\": 600,\n      \"yMin\": -196,\n      \"yMax\": 820,\n      \"hAsc\": 821,\n      \"hDes\": -179,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sue Ellen Francisco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1362,\n      \"des\": -634,\n      \"tAsc\": 1362,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 634,\n      \"xH\": 439,\n      \"capH\": 1085,\n      \"yMin\": -571,\n      \"yMax\": 1362,\n      \"hAsc\": 1362,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suez One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 987,\n      \"des\": -319,\n      \"tAsc\": 987,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 987,\n      \"wDes\": 319,\n      \"xH\": 523,\n      \"capH\": 674,\n      \"yMin\": -319,\n      \"yMax\": 987,\n      \"hAsc\": 987,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sulphur Point\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 369,\n      \"wAsc\": 893,\n      \"wDes\": 224,\n      \"xH\": 500,\n      \"capH\": 665,\n      \"yMin\": -224,\n      \"yMax\": 892,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sumana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1922,\n      \"des\": -1005,\n      \"tAsc\": 1922,\n      \"tDes\": -1005,\n      \"tLGap\": 0,\n      \"wAsc\": 1922,\n      \"wDes\": 1005,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -493,\n      \"yMax\": 961,\n      \"hAsc\": 1922,\n      \"hDes\": -1005,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sunflower\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 500, 700],\n    \"styles\": [],\n    \"variants\": [\n      [0, 300],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 782,\n      \"des\": -218,\n      \"tAsc\": 782,\n      \"tDes\": -218,\n      \"tLGap\": 250,\n      \"wAsc\": 810,\n      \"wDes\": 235,\n      \"xH\": 500,\n      \"capH\": 692,\n      \"yMin\": -235,\n      \"yMax\": 798,\n      \"hAsc\": 782,\n      \"hDes\": -218,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sunshiney\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -306,\n      \"tAsc\": 626,\n      \"tDes\": -190,\n      \"tLGap\": 53,\n      \"wAsc\": 1019,\n      \"wDes\": 306,\n      \"xH\": 391,\n      \"capH\": 759,\n      \"yMin\": -306,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -306,\n      \"lGap\": 27\n    }\n  },\n  {\n    \"family\": \"Supermercado One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1925,\n      \"des\": -527,\n      \"tAsc\": 1925,\n      \"tDes\": -527,\n      \"tLGap\": 0,\n      \"wAsc\": 1925,\n      \"wDes\": 527,\n      \"xH\": 1066,\n      \"capH\": 1359,\n      \"yMin\": -526,\n      \"yMax\": 1925,\n      \"hAsc\": 1925,\n      \"hDes\": -527,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sura\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2359,\n      \"des\": -872,\n      \"tAsc\": 2359,\n      \"tDes\": -872,\n      \"tLGap\": 0,\n      \"wAsc\": 2359,\n      \"wDes\": 872,\n      \"xH\": 1022,\n      \"capH\": 1464,\n      \"yMin\": -780,\n      \"yMax\": 2257,\n      \"hAsc\": 2359,\n      \"hDes\": -872,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suranna\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 780,\n      \"asc\": 1101,\n      \"des\": -607,\n      \"tAsc\": 1101,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 607,\n      \"xH\": 319,\n      \"capH\": 492,\n      \"yMin\": -607,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suravaram\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 980,\n      \"asc\": 1295,\n      \"des\": -794,\n      \"tAsc\": 1295,\n      \"tDes\": -794,\n      \"tLGap\": 0,\n      \"wAsc\": 1295,\n      \"wDes\": 794,\n      \"xH\": 344,\n      \"capH\": 482,\n      \"yMin\": -794,\n      \"yMax\": 1295,\n      \"hAsc\": 1295,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SUSE\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -280,\n      \"tAsc\": 980,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 410,\n      \"xH\": 481,\n      \"capH\": 700,\n      \"yMin\": -379,\n      \"yMax\": 1084,\n      \"hAsc\": 980,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SUSE Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -280,\n      \"tAsc\": 980,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 410,\n      \"xH\": 481,\n      \"capH\": 700,\n      \"yMin\": -379,\n      \"yMax\": 1084,\n      \"hAsc\": 980,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suwannaphum\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2230,\n      \"wDes\": 910,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -910,\n      \"yMax\": 2202,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Swanky and Moo Moo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 995,\n      \"des\": -507,\n      \"tAsc\": 995,\n      \"tDes\": -507,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 507,\n      \"xH\": 341,\n      \"capH\": 424,\n      \"yMin\": -507,\n      \"yMax\": 955,\n      \"hAsc\": 995,\n      \"hDes\": -507,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syncopate\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1556,\n      \"des\": -426,\n      \"tAsc\": 1556,\n      \"tDes\": -426,\n      \"tLGap\": 150,\n      \"wAsc\": 1853,\n      \"wDes\": 483,\n      \"xH\": 958,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1853,\n      \"hAsc\": 1556,\n      \"hDes\": -426,\n      \"lGap\": 150\n    }\n  },\n  {\n    \"family\": \"Syne\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -254,\n      \"yMax\": 952,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syne Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -253,\n      \"yMax\": 917,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syne Tactile\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -493,\n      \"yMax\": 920,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tac One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -200,\n      \"tAsc\": 830,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 280,\n      \"xH\": 400,\n      \"capH\": 554,\n      \"yMin\": -280,\n      \"yMax\": 859,\n      \"hAsc\": 830,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tagesschrift\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -289,\n      \"yMax\": 1065,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tahoma\",\n    \"fallbacks\": [\"Verdana\", \"Segoe\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2049,\n      \"des\": -423,\n      \"tAsc\": 1566,\n      \"tDes\": -423,\n      \"tLGap\": 59,\n      \"wAsc\": 2049,\n      \"wDes\": 2049,\n      \"xH\": 1117,\n      \"capH\": 1489,\n      \"yMin\": -442,\n      \"yMax\": 2118,\n      \"hAsc\": 2049,\n      \"hDes\": -423,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Tai Heritage Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2700,\n      \"des\": -1600,\n      \"tAsc\": 2700,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 2700,\n      \"wDes\": 1600,\n      \"xH\": 1150,\n      \"capH\": 1700,\n      \"yMin\": -1546,\n      \"yMax\": 2775,\n      \"hAsc\": 2700,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tajawal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 643,\n      \"des\": -357,\n      \"tAsc\": 643,\n      \"tDes\": -357,\n      \"tLGap\": 200,\n      \"wAsc\": 1016,\n      \"wDes\": 375,\n      \"xH\": 454,\n      \"capH\": 633,\n      \"yMin\": -375,\n      \"yMax\": 995,\n      \"hAsc\": 643,\n      \"hDes\": -357,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Tangerine\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 765,\n      \"wDes\": 286,\n      \"xH\": 255,\n      \"capH\": 644,\n      \"yMin\": -286,\n      \"yMax\": 765,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tapestry\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 300,\n      \"xH\": 454,\n      \"capH\": 640,\n      \"yMin\": -286,\n      \"yMax\": 1016,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Taprom\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TASA Explorer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -250,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TASA Orbiter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -250,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tauri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -520,\n      \"tAsc\": 2040,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 520,\n      \"xH\": 1135,\n      \"capH\": 1571,\n      \"yMin\": -520,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Taviraj\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -534,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1172,\n      \"wDes\": 534,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -489,\n      \"yMax\": 1131,\n      \"hAsc\": 1172,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Teachers\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 273,\n      \"xH\": 440,\n      \"capH\": 680,\n      \"yMin\": -273,\n      \"yMax\": 930,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Teko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -475,\n      \"tAsc\": 958,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 475,\n      \"xH\": 485,\n      \"capH\": 626,\n      \"yMin\": -394,\n      \"yMax\": 857,\n      \"hAsc\": 958,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tektur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 300,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Telex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -260,\n      \"tAsc\": 945,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 260,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -260,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tenali Ramakrishna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 661,\n      \"des\": -512,\n      \"tAsc\": 661,\n      \"tDes\": -512,\n      \"tLGap\": 0,\n      \"wAsc\": 661,\n      \"wDes\": 512,\n      \"xH\": 268,\n      \"capH\": 367,\n      \"yMin\": -512,\n      \"yMax\": 661,\n      \"hAsc\": 661,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tenor Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -250,\n      \"tAsc\": 920,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Text Me One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -269,\n      \"tAsc\": 952,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 269,\n      \"xH\": 502,\n      \"capH\": 700,\n      \"yMin\": -269,\n      \"yMax\": 952,\n      \"hAsc\": 952,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Texturina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1260,\n      \"des\": -300,\n      \"tAsc\": 1260,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1260,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 704,\n      \"yMin\": -280,\n      \"yMax\": 1192,\n      \"hAsc\": 1260,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Thasadith\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 494,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -464,\n      \"yMax\": 1140,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"The Girl Next Door\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1139,\n      \"des\": -748,\n      \"tAsc\": 1139,\n      \"tDes\": -748,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 748,\n      \"xH\": 519,\n      \"capH\": 627,\n      \"yMin\": -673,\n      \"yMax\": 1025,\n      \"hAsc\": 1139,\n      \"hDes\": -748,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"The Nautigal\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -330,\n      \"tAsc\": 870,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 417,\n      \"xH\": 265,\n      \"capH\": 600,\n      \"yMin\": -417,\n      \"yMax\": 939,\n      \"hAsc\": 870,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tienne\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -724,\n      \"tAsc\": 2030,\n      \"tDes\": -724,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 724,\n      \"xH\": 363,\n      \"capH\": 1437,\n      \"yMin\": -724,\n      \"yMax\": 2030,\n      \"hAsc\": 2030,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TikTok Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1118,\n      \"wDes\": 242,\n      \"xH\": 526,\n      \"capH\": 705,\n      \"yMin\": -236,\n      \"yMax\": 1086,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tillana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1158,\n      \"des\": -484,\n      \"tAsc\": 1158,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 484,\n      \"xH\": 546,\n      \"capH\": 732,\n      \"yMin\": -312,\n      \"yMax\": 1041,\n      \"hAsc\": 1158,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Neon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -395,\n      \"yMax\": 1174,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Prism\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -274,\n      \"yMax\": 1186,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Warp\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -422,\n      \"yMax\": 1177,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Times New Roman\",\n    \"fallbacks\": [\n      \"Times New Roman\",\n      \"Times\",\n      \"Baskerville\",\n      \"Georgia\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1825,\n      \"des\": -443,\n      \"tAsc\": 1420,\n      \"tDes\": -442,\n      \"tLGap\": 307,\n      \"wAsc\": 1825,\n      \"wDes\": 1825,\n      \"xH\": 916,\n      \"capH\": 1356,\n      \"yMin\": -628,\n      \"yMax\": 2062,\n      \"hAsc\": 1825,\n      \"hDes\": -443,\n      \"lGap\": 87\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Timmana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 668,\n      \"des\": -554,\n      \"tAsc\": 668,\n      \"tDes\": -554,\n      \"tLGap\": 0,\n      \"wAsc\": 668,\n      \"wDes\": 554,\n      \"xH\": 354,\n      \"capH\": 454,\n      \"yMin\": -554,\n      \"yMax\": 668,\n      \"hAsc\": 668,\n      \"hDes\": -554,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tinos\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1825,\n      \"des\": -443,\n      \"tAsc\": 1420,\n      \"tDes\": -442,\n      \"tLGap\": 307,\n      \"wAsc\": 1825,\n      \"wDes\": 443,\n      \"xH\": 940,\n      \"capH\": 1341,\n      \"yMin\": -621,\n      \"yMax\": 2010,\n      \"hAsc\": 1825,\n      \"hDes\": -443,\n      \"lGap\": 87\n    }\n  },\n  {\n    \"family\": \"Tiny5\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -256,\n      \"tAsc\": 896,\n      \"tDes\": -256,\n      \"tLGap\": 0,\n      \"wAsc\": 1408,\n      \"wDes\": 384,\n      \"xH\": 512,\n      \"capH\": 640,\n      \"yMin\": -384,\n      \"yMax\": 1408,\n      \"hAsc\": 896,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tiro Bangla\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Hindi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 501,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -501,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Marathi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 501,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -501,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Sanskrit\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 545,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -545,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Gurmukhi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 250,\n      \"wAsc\": 1447,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1447,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Tiro Kannada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 794,\n      \"wAsc\": 1091,\n      \"wDes\": 694,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -694,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 794\n    }\n  },\n  {\n    \"family\": \"Tiro Tamil\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 436,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 436\n    }\n  },\n  {\n    \"family\": \"Tiro Telugu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 794,\n      \"wAsc\": 1189,\n      \"wDes\": 563,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -563,\n      \"yMax\": 1189,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 794\n    }\n  },\n  {\n    \"family\": \"Tirra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2093,\n      \"des\": -713,\n      \"tAsc\": 2093,\n      \"tDes\": -713,\n      \"tLGap\": 0,\n      \"wAsc\": 2093,\n      \"wDes\": 713,\n      \"xH\": 1024,\n      \"capH\": 1393,\n      \"yMin\": -713,\n      \"yMax\": 1860,\n      \"hAsc\": 2093,\n      \"hDes\": -713,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Titan One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -175,\n      \"tAsc\": 970,\n      \"tDes\": -175,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 175,\n      \"xH\": 580,\n      \"capH\": 710,\n      \"yMin\": -175,\n      \"yMax\": 970,\n      \"hAsc\": 970,\n      \"hDes\": -175,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Titillium Web\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1133,\n      \"des\": -388,\n      \"tAsc\": 1133,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1133,\n      \"wDes\": 388,\n      \"xH\": 500,\n      \"capH\": 692,\n      \"yMin\": -285,\n      \"yMax\": 1082,\n      \"hAsc\": 1133,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tomorrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1233,\n      \"wDes\": 279,\n      \"xH\": 523,\n      \"capH\": 737,\n      \"yMin\": -232,\n      \"yMax\": 1166,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tourney\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -400,\n      \"tAsc\": 1800,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2160,\n      \"wDes\": 540,\n      \"xH\": 1080,\n      \"capH\": 1400,\n      \"yMin\": -533,\n      \"yMax\": 2116,\n      \"hAsc\": 1800,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trade Winds\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -469,\n      \"tAsc\": 1019,\n      \"tDes\": -469,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 469,\n      \"xH\": 576,\n      \"capH\": 814,\n      \"yMin\": -469,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -469,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Train One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 557,\n      \"capH\": 780,\n      \"yMin\": -221,\n      \"yMax\": 1061,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trebuchet MS\",\n    \"fallbacks\": [\n      \"Lucida Grande\",\n      \"Lucida Sans Unicode\",\n      \"Lucida Sans\",\n      \"Tahoma\",\n      \"sans-serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1923,\n      \"des\": -455,\n      \"tAsc\": 1510,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 1923,\n      \"wDes\": 1923,\n      \"yMin\": -537,\n      \"yMax\": 1931,\n      \"hAsc\": 1923,\n      \"hDes\": -455,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Triodion\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1126,\n      \"des\": -511,\n      \"tAsc\": 1126,\n      \"tDes\": -511,\n      \"tLGap\": 0,\n      \"wAsc\": 1126,\n      \"wDes\": 511,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -511,\n      \"yMax\": 1126,\n      \"hAsc\": 1126,\n      \"hDes\": -511,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trirong\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -534,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1200,\n      \"wDes\": 534,\n      \"xH\": 498,\n      \"capH\": 700,\n      \"yMin\": -487,\n      \"yMax\": 1133,\n      \"hAsc\": 1200,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trispace\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1830,\n      \"des\": -430,\n      \"tAsc\": 1830,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 2355,\n      \"wDes\": 630,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -547,\n      \"yMax\": 2258,\n      \"hAsc\": 1830,\n      \"hDes\": -430,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trocchi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2085,\n      \"des\": -576,\n      \"tAsc\": 2085,\n      \"tDes\": -576,\n      \"tLGap\": 0,\n      \"wAsc\": 2085,\n      \"wDes\": 580,\n      \"xH\": 1073,\n      \"capH\": 1505,\n      \"yMin\": -580,\n      \"yMax\": 2085,\n      \"hAsc\": 2085,\n      \"hDes\": -576,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trochut\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 967,\n      \"des\": -210,\n      \"tAsc\": 967,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 967,\n      \"wDes\": 210,\n      \"xH\": 470,\n      \"capH\": 690,\n      \"yMin\": -210,\n      \"yMax\": 922,\n      \"hAsc\": 967,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Truculenta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -340,\n      \"tAsc\": 1050,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 340,\n      \"xH\": 515,\n      \"capH\": 693,\n      \"yMin\": -288,\n      \"yMax\": 982,\n      \"hAsc\": 1050,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trykker\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2022,\n      \"des\": -538,\n      \"tAsc\": 2022,\n      \"tDes\": -538,\n      \"tLGap\": 0,\n      \"wAsc\": 2022,\n      \"wDes\": 538,\n      \"xH\": 1013,\n      \"capH\": 1492,\n      \"yMin\": -539,\n      \"yMax\": 2027,\n      \"hAsc\": 2022,\n      \"hDes\": -538,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tsukimi Rounded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 800,\n      \"yMin\": -288,\n      \"yMax\": 1055,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tuffy\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2340,\n      \"des\": -697,\n      \"tAsc\": 2340,\n      \"tDes\": -697,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 697,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -648,\n      \"yMax\": 2023,\n      \"hAsc\": 2340,\n      \"hDes\": -697,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tulpen One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1767,\n      \"des\": -465,\n      \"tAsc\": 1767,\n      \"tDes\": -465,\n      \"tLGap\": 0,\n      \"wAsc\": 1767,\n      \"wDes\": 465,\n      \"xH\": 1018,\n      \"capH\": 1393,\n      \"yMin\": -465,\n      \"yMax\": 1767,\n      \"hAsc\": 1767,\n      \"hDes\": -465,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Turret Road\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -243,\n      \"tAsc\": 850,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 246,\n      \"xH\": 478,\n      \"capH\": 700,\n      \"yMin\": -234,\n      \"yMax\": 924,\n      \"hAsc\": 850,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Twinkle Star\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -350,\n      \"tAsc\": 930,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 426,\n      \"xH\": 470,\n      \"capH\": 705,\n      \"yMin\": -426,\n      \"yMax\": 1112,\n      \"hAsc\": 930,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -189,\n      \"tAsc\": 776,\n      \"tDes\": -185,\n      \"tLGap\": 56,\n      \"wAsc\": 932,\n      \"wDes\": 189,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -189,\n      \"yMax\": 962,\n      \"hAsc\": 932,\n      \"hDes\": -189,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Ubuntu Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -189,\n      \"tAsc\": 776,\n      \"tDes\": -185,\n      \"tLGap\": 56,\n      \"wAsc\": 932,\n      \"wDes\": 189,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -195,\n      \"yMax\": 973,\n      \"hAsc\": 932,\n      \"hDes\": -189,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Ubuntu Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -170,\n      \"tAsc\": 693,\n      \"tDes\": -165,\n      \"tLGap\": 49,\n      \"wAsc\": 830,\n      \"wDes\": 170,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -170,\n      \"yMax\": 830,\n      \"hAsc\": 830,\n      \"hDes\": -170,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 223,\n      \"xH\": 518,\n      \"capH\": 693,\n      \"yMin\": -195,\n      \"yMax\": 958,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu Sans Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 223,\n      \"xH\": 518,\n      \"capH\": 693,\n      \"yMin\": -205,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Uchen\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1248,\n      \"des\": -660,\n      \"tAsc\": 1248,\n      \"tDes\": -660,\n      \"tLGap\": 0,\n      \"wAsc\": 1361,\n      \"wDes\": 909,\n      \"xH\": 485,\n      \"capH\": 744,\n      \"yMin\": -909,\n      \"yMax\": 1361,\n      \"hAsc\": 1248,\n      \"hDes\": -660,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ultra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -561,\n      \"tAsc\": 2066,\n      \"tDes\": -561,\n      \"tLGap\": 0,\n      \"wAsc\": 2066,\n      \"wDes\": 561,\n      \"xH\": 1102,\n      \"capH\": 1473,\n      \"yMin\": -561,\n      \"yMax\": 2066,\n      \"hAsc\": 2066,\n      \"hDes\": -561,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unbounded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -245,\n      \"tAsc\": 995,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1262,\n      \"wDes\": 286,\n      \"xH\": 566,\n      \"capH\": 750,\n      \"yMin\": -286,\n      \"yMax\": 1173,\n      \"hAsc\": 995,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Uncial Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2019,\n      \"des\": -676,\n      \"tAsc\": 2019,\n      \"tDes\": -676,\n      \"tLGap\": 0,\n      \"wAsc\": 2019,\n      \"wDes\": 676,\n      \"xH\": 1079,\n      \"capH\": 1841,\n      \"yMin\": -676,\n      \"yMax\": 2019,\n      \"hAsc\": 2019,\n      \"hDes\": -676,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Underdog\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 909,\n      \"des\": -247,\n      \"tAsc\": 909,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 909,\n      \"wDes\": 247,\n      \"xH\": 520,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 915,\n      \"hAsc\": 909,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unica One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -265,\n      \"tAsc\": 917,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 265,\n      \"xH\": 650,\n      \"capH\": 650,\n      \"yMin\": -265,\n      \"yMax\": 1041,\n      \"hAsc\": 917,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UnifrakturCook\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [700],\n    \"styles\": [],\n    \"variants\": [[0, 700]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2110,\n      \"des\": -570,\n      \"tAsc\": 2110,\n      \"tDes\": -570,\n      \"tLGap\": 0,\n      \"wAsc\": 2110,\n      \"wDes\": 570,\n      \"xH\": 319,\n      \"capH\": 485,\n      \"yMin\": -570,\n      \"yMax\": 2110,\n      \"hAsc\": 2110,\n      \"hDes\": -570,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UnifrakturMaguntia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1607,\n      \"des\": -513,\n      \"tAsc\": 1607,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1607,\n      \"wDes\": 512,\n      \"xH\": 1095,\n      \"capH\": 1409,\n      \"yMin\": -496,\n      \"yMax\": 1906,\n      \"hAsc\": 1607,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unkempt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 977,\n      \"des\": -246,\n      \"tAsc\": 695,\n      \"tDes\": -226,\n      \"tLGap\": 55,\n      \"wAsc\": 977,\n      \"wDes\": 246,\n      \"xH\": 482,\n      \"capH\": 753,\n      \"yMin\": -246,\n      \"yMax\": 977,\n      \"hAsc\": 977,\n      \"hDes\": -246,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Unlock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -195,\n      \"tAsc\": 873,\n      \"tDes\": -195,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 295,\n      \"xH\": 550,\n      \"capH\": 635,\n      \"yMin\": -295,\n      \"yMax\": 958,\n      \"hAsc\": 873,\n      \"hDes\": -195,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unna\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 883,\n      \"des\": -269,\n      \"tAsc\": 883,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 269,\n      \"xH\": 420,\n      \"capH\": 597,\n      \"yMin\": -269,\n      \"yMax\": 878,\n      \"hAsc\": 883,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UoqMunThenKhung\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 941,\n      \"des\": -187,\n      \"tAsc\": 941,\n      \"tDes\": -187,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 213,\n      \"xH\": 541,\n      \"capH\": 732,\n      \"yMin\": -213,\n      \"yMax\": 949,\n      \"hAsc\": 941,\n      \"hDes\": -187,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Updock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 910,\n      \"wDes\": 500,\n      \"xH\": 350,\n      \"capH\": 630,\n      \"yMin\": -497,\n      \"yMax\": 906,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Urbanist\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2120,\n      \"wDes\": 500,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -500,\n      \"yMax\": 2011,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vampiro One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -294,\n      \"tAsc\": 956,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 294,\n      \"xH\": 534,\n      \"capH\": 705,\n      \"yMin\": -294,\n      \"yMax\": 956,\n      \"hAsc\": 956,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varela\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -285,\n      \"tAsc\": 1015,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 285,\n      \"xH\": 510,\n      \"capH\": 698,\n      \"yMin\": -285,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varela Round\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -286,\n      \"tAsc\": 918,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 286,\n      \"xH\": 510,\n      \"capH\": 698,\n      \"yMin\": -286,\n      \"yMax\": 1025,\n      \"hAsc\": 918,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1902,\n      \"des\": -1068,\n      \"tAsc\": 1902,\n      \"tDes\": -1068,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 1450,\n      \"xH\": 990,\n      \"capH\": 1346,\n      \"yMin\": -514,\n      \"yMax\": 1966,\n      \"hAsc\": 1902,\n      \"hDes\": -1068,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vast Shadow\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1875,\n      \"des\": -685,\n      \"tAsc\": 1875,\n      \"tDes\": -685,\n      \"tLGap\": 0,\n      \"wAsc\": 1875,\n      \"wDes\": 683,\n      \"xH\": 965,\n      \"capH\": 1245,\n      \"yMin\": -685,\n      \"yMax\": 1875,\n      \"hAsc\": 1875,\n      \"hDes\": -685,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vazirmatn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2100,\n      \"des\": -1100,\n      \"tAsc\": 2100,\n      \"tDes\": -1100,\n      \"tLGap\": 0,\n      \"wAsc\": 2200,\n      \"wDes\": 1300,\n      \"xH\": 1082,\n      \"capH\": 1638,\n      \"yMin\": -1142,\n      \"yMax\": 2163,\n      \"hAsc\": 2100,\n      \"hDes\": -1100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vend Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -390,\n      \"tAsc\": 1090,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 380,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -273,\n      \"yMax\": 1030,\n      \"hAsc\": 1090,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Verdana\",\n    \"fallbacks\": [\"Geneva\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2059,\n      \"des\": -430,\n      \"tAsc\": 1566,\n      \"tDes\": -423,\n      \"tLGap\": 202,\n      \"wAsc\": 2059,\n      \"wDes\": 2059,\n      \"xH\": 1117,\n      \"capH\": 1489,\n      \"yMin\": -621,\n      \"yMax\": 2049,\n      \"hAsc\": 2059,\n      \"hDes\": -430,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Vesper Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2330,\n      \"des\": -1550,\n      \"tAsc\": 2330,\n      \"tDes\": -1550,\n      \"tLGap\": 0,\n      \"wAsc\": 2330,\n      \"wDes\": 1550,\n      \"xH\": 950,\n      \"capH\": 1384,\n      \"yMin\": -1345,\n      \"yMax\": 2097,\n      \"hAsc\": 2330,\n      \"hDes\": -1550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Viaoda Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1051,\n      \"des\": -360,\n      \"tAsc\": 1051,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1051,\n      \"wDes\": 360,\n      \"xH\": 467,\n      \"capH\": 740,\n      \"yMin\": -360,\n      \"yMax\": 1051,\n      \"hAsc\": 1051,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vibes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1105,\n      \"des\": -680,\n      \"tAsc\": 1105,\n      \"tDes\": -680,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 680,\n      \"xH\": 500,\n      \"capH\": 38,\n      \"yMin\": -680,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -680,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vibur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1960,\n      \"des\": -792,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1960,\n      \"wDes\": 792,\n      \"yMin\": -792,\n      \"yMax\": 1960,\n      \"hAsc\": 1960,\n      \"hDes\": -792,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Victor Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -250,\n      \"tAsc\": 1100,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1306,\n      \"wDes\": 529,\n      \"xH\": 618,\n      \"capH\": 800,\n      \"yMin\": -529,\n      \"yMax\": 1306,\n      \"hAsc\": 1100,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vidaloka\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1927,\n      \"des\": -560,\n      \"tAsc\": 1927,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 1927,\n      \"wDes\": 560,\n      \"xH\": 1004,\n      \"capH\": 1427,\n      \"yMin\": -560,\n      \"yMax\": 1927,\n      \"hAsc\": 1927,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Viga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -329,\n      \"tAsc\": 1015,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 329,\n      \"xH\": 571,\n      \"capH\": 712,\n      \"yMin\": -329,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vina Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -170,\n      \"tAsc\": 1045,\n      \"tDes\": -170,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 1063,\n      \"hAsc\": 1045,\n      \"hDes\": -170,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Voces\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1014,\n      \"des\": -335,\n      \"tAsc\": 1014,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 335,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -335,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Volkhov\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 971,\n      \"des\": -319,\n      \"tAsc\": 971,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 971,\n      \"wDes\": 319,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -306,\n      \"yMax\": 970,\n      \"hAsc\": 971,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vollkorn\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -441,\n      \"tAsc\": 952,\n      \"tDes\": -441,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 489,\n      \"xH\": 458,\n      \"capH\": 676,\n      \"yMin\": -280,\n      \"yMax\": 1078,\n      \"hAsc\": 952,\n      \"hDes\": -441,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vollkorn SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -441,\n      \"tAsc\": 952,\n      \"tDes\": -441,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 489,\n      \"xH\": 458,\n      \"capH\": 676,\n      \"yMin\": -280,\n      \"yMax\": 1078,\n      \"hAsc\": 952,\n      \"hDes\": -441,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Voltaire\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -531,\n      \"tAsc\": 2020,\n      \"tDes\": -531,\n      \"tLGap\": 0,\n      \"wAsc\": 2571,\n      \"wDes\": 580,\n      \"xH\": 1062,\n      \"capH\": 1593,\n      \"yMin\": -572,\n      \"yMax\": 2412,\n      \"hAsc\": 2020,\n      \"hDes\": -531,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"VT323\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 240,\n      \"xH\": 400,\n      \"capH\": 560,\n      \"yMin\": -240,\n      \"yMax\": 1040,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vujahday Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1144,\n      \"wDes\": 678,\n      \"xH\": 360,\n      \"capH\": 640,\n      \"yMin\": -678,\n      \"yMax\": 1144,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Waiting for the Sunrise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1146,\n      \"des\": -547,\n      \"tAsc\": 1146,\n      \"tDes\": -547,\n      \"tLGap\": 0,\n      \"wAsc\": 1146,\n      \"wDes\": 547,\n      \"xH\": 570,\n      \"capH\": 755,\n      \"yMin\": -547,\n      \"yMax\": 1146,\n      \"hAsc\": 1146,\n      \"hDes\": -547,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wallpoet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 806,\n      \"des\": -196,\n      \"tAsc\": 806,\n      \"tDes\": -196,\n      \"tLGap\": 0,\n      \"wAsc\": 806,\n      \"wDes\": 196,\n      \"xH\": 440,\n      \"capH\": 575,\n      \"yMin\": -196,\n      \"yMax\": 806,\n      \"hAsc\": 806,\n      \"hDes\": -196,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Walter Turncoat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1078,\n      \"des\": -323,\n      \"tAsc\": 544,\n      \"tDes\": -64,\n      \"tLGap\": 57,\n      \"wAsc\": 1078,\n      \"wDes\": 323,\n      \"xH\": 559,\n      \"capH\": 752,\n      \"yMin\": -322,\n      \"yMax\": 1078,\n      \"hAsc\": 1078,\n      \"hDes\": -323,\n      \"lGap\": 29\n    }\n  },\n  {\n    \"family\": \"Warnes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 994,\n      \"des\": -310,\n      \"tAsc\": 994,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 359,\n      \"xH\": 540,\n      \"capH\": 710,\n      \"yMin\": -359,\n      \"yMax\": 1095,\n      \"hAsc\": 994,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Water Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -450,\n      \"tAsc\": 1000,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 475,\n      \"xH\": 375,\n      \"capH\": 750,\n      \"yMin\": -472,\n      \"yMax\": 1152,\n      \"hAsc\": 1000,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Waterfall\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -280,\n      \"tAsc\": 880,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 858,\n      \"wDes\": 563,\n      \"xH\": 215,\n      \"capH\": 580,\n      \"yMin\": -563,\n      \"yMax\": 858,\n      \"hAsc\": 880,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wavefont\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -200,\n      \"tAsc\": 1200,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -90,\n      \"yMax\": 1270,\n      \"hAsc\": 1200,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont JP N\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wellfleet\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 747,\n      \"capH\": 1535,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wendy One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 819,\n      \"des\": -236,\n      \"tAsc\": 819,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 819,\n      \"wDes\": 236,\n      \"xH\": 474,\n      \"capH\": 606,\n      \"yMin\": -236,\n      \"yMax\": 819,\n      \"hAsc\": 819,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Whisper\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -400,\n      \"tAsc\": 880,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 407,\n      \"xH\": 300,\n      \"capH\": 620,\n      \"yMin\": -407,\n      \"yMax\": 923,\n      \"hAsc\": 880,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WindSong\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -515,\n      \"tAsc\": 890,\n      \"tDes\": -515,\n      \"tLGap\": 0,\n      \"wAsc\": 1930,\n      \"wDes\": 745,\n      \"xH\": 268,\n      \"capH\": 705,\n      \"yMin\": -745,\n      \"yMax\": 1297,\n      \"hAsc\": 890,\n      \"hDes\": -515,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Winky Rough\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -247,\n      \"yMax\": 935,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Winky Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -249,\n      \"yMax\": 941,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wire One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -210,\n      \"tAsc\": 890,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 890,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 889,\n      \"hAsc\": 890,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wittgenstein\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -435,\n      \"tAsc\": 1065,\n      \"tDes\": -435,\n      \"tLGap\": 0,\n      \"wAsc\": 1180,\n      \"wDes\": 435,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1019,\n      \"hAsc\": 1065,\n      \"hDes\": -435,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wix Madefor Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -252,\n      \"tAsc\": 1008,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1176,\n      \"wDes\": 307,\n      \"xH\": 492,\n      \"capH\": 715,\n      \"yMin\": -270,\n      \"yMax\": 1109,\n      \"hAsc\": 1008,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wix Madefor Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -252,\n      \"tAsc\": 1008,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1176,\n      \"wDes\": 307,\n      \"xH\": 492,\n      \"capH\": 715,\n      \"yMin\": -270,\n      \"yMax\": 1109,\n      \"hAsc\": 1008,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Work Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -243,\n      \"tAsc\": 930,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 343,\n      \"xH\": 500,\n      \"capH\": 660,\n      \"yMin\": -337,\n      \"yMax\": 1100,\n      \"hAsc\": 930,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Workbench\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Xanh Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -220,\n      \"tAsc\": 970,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 220,\n      \"xH\": 540,\n      \"capH\": 740,\n      \"yMin\": -213,\n      \"yMax\": 1100,\n      \"hAsc\": 970,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yaldevi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -256,\n      \"tAsc\": 1060,\n      \"tDes\": -256,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 450,\n      \"xH\": 570,\n      \"capH\": 769,\n      \"yMin\": -323,\n      \"yMax\": 1086,\n      \"hAsc\": 1060,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yanone Kaffeesatz\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 735,\n      \"des\": -200,\n      \"tAsc\": 735,\n      \"tDes\": -200,\n      \"tLGap\": 57,\n      \"wAsc\": 1063,\n      \"wDes\": 279,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 1072,\n      \"hAsc\": 735,\n      \"hDes\": -200,\n      \"lGap\": 57\n    }\n  },\n  {\n    \"family\": \"Yantramanav\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1923,\n      \"des\": -733,\n      \"tAsc\": 1923,\n      \"tDes\": -733,\n      \"tLGap\": 0,\n      \"wAsc\": 1923,\n      \"wDes\": 733,\n      \"xH\": 986,\n      \"capH\": 1279,\n      \"yMin\": -676,\n      \"yMax\": 1911,\n      \"hAsc\": 1923,\n      \"hDes\": -733,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 12\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 910,\n      \"des\": -130,\n      \"tAsc\": 910,\n      \"tDes\": -130,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": 0,\n      \"yMax\": 780,\n      \"hAsc\": 910,\n      \"hDes\": -130,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 12 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 910,\n      \"des\": -130,\n      \"tAsc\": 910,\n      \"tDes\": -130,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -130,\n      \"yMax\": 915,\n      \"hAsc\": 910,\n      \"hDes\": -130,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 20\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 880,\n      \"des\": -80,\n      \"tAsc\": 880,\n      \"tDes\": -80,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": 0,\n      \"yMax\": 800,\n      \"hAsc\": 880,\n      \"hDes\": -80,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 20 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 880,\n      \"des\": -80,\n      \"tAsc\": 880,\n      \"tDes\": -80,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -80,\n      \"yMax\": 883,\n      \"hAsc\": 880,\n      \"hDes\": -80,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yatra One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 991,\n      \"des\": -487,\n      \"tAsc\": 991,\n      \"tDes\": -487,\n      \"tLGap\": 0,\n      \"wAsc\": 991,\n      \"wDes\": 487,\n      \"xH\": 460,\n      \"capH\": 679,\n      \"yMin\": -487,\n      \"yMax\": 991,\n      \"hAsc\": 991,\n      \"hDes\": -487,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yellowtail\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1990,\n      \"des\": -617,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1990,\n      \"wDes\": 617,\n      \"yMin\": -617,\n      \"yMax\": 1990,\n      \"hAsc\": 1990,\n      \"hDes\": -617,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Yeon Sung\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 830,\n      \"wDes\": 323,\n      \"xH\": 446,\n      \"capH\": 659,\n      \"yMin\": -323,\n      \"yMax\": 830,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Yeseva One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -240,\n      \"tAsc\": 915,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1079,\n      \"hAsc\": 915,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yesteryear\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2001,\n      \"des\": -1004,\n      \"tAsc\": 2001,\n      \"tDes\": -1004,\n      \"tLGap\": 0,\n      \"wAsc\": 2001,\n      \"wDes\": 1004,\n      \"xH\": 625,\n      \"capH\": 1581,\n      \"yMin\": -1004,\n      \"yMax\": 2001,\n      \"hAsc\": 2001,\n      \"hDes\": -1004,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yomogi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 475,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Young Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -366,\n      \"tAsc\": 1046,\n      \"tDes\": -366,\n      \"tLGap\": 0,\n      \"wAsc\": 1302,\n      \"wDes\": 366,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -304,\n      \"yMax\": 1302,\n      \"hAsc\": 1046,\n      \"hDes\": -366,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yrsa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 728,\n      \"des\": -272,\n      \"tAsc\": 728,\n      \"tDes\": -272,\n      \"tLGap\": 218,\n      \"wAsc\": 971,\n      \"wDes\": 422,\n      \"xH\": 413,\n      \"capH\": 568,\n      \"yMin\": -211,\n      \"yMax\": 925,\n      \"hAsc\": 728,\n      \"hDes\": -272,\n      \"lGap\": 218\n    }\n  },\n  {\n    \"family\": \"Ysabeau\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau Infant\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau Office\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -290,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Boku\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -334,\n      \"yMax\": 936,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Hentaigana Akari\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -232,\n      \"yMax\": 970,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Hentaigana Akebono\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -232,\n      \"yMax\": 970,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Mai\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -255,\n      \"yMax\": 936,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Syuku\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -190,\n      \"yMax\": 881,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yusei Magic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 510,\n      \"capH\": 760,\n      \"yMin\": -233,\n      \"yMax\": 1047,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zain\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 800,\n      \"asc\": 869,\n      \"des\": -459,\n      \"tAsc\": 869,\n      \"tDes\": -459,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 459,\n      \"xH\": 480,\n      \"capH\": 699,\n      \"yMin\": -459,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -459,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans SemiExpanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL KuaiLe\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 913,\n      \"wDes\": 152,\n      \"xH\": 512,\n      \"capH\": 700,\n      \"yMin\": -152,\n      \"yMax\": 913,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL QingKe HuangYou\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 884,\n      \"wDes\": 187,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -187,\n      \"yMax\": 884,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL XiaoWei\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 470,\n      \"capH\": 660,\n      \"yMin\": -210,\n      \"yMax\": 859,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Antique\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 473,\n      \"capH\": 726,\n      \"yMin\": -283,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Antique Soft\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 473,\n      \"capH\": 726,\n      \"yMin\": -283,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -270,\n      \"tAsc\": 930,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 300,\n      \"xH\": 515,\n      \"capH\": 715,\n      \"yMin\": -225,\n      \"yMax\": 960,\n      \"hAsc\": 930,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kaku Gothic Antique\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kaku Gothic New\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kurenaido\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 406,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 959,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Loop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -275,\n      \"tAsc\": 850,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 275,\n      \"xH\": 477,\n      \"capH\": 690,\n      \"yMin\": -271,\n      \"yMax\": 835,\n      \"hAsc\": 850,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Maru Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Old Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 430,\n      \"capH\": 726,\n      \"yMin\": -303,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Tokyo Zoo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 250,\n      \"xH\": 402,\n      \"capH\": 804,\n      \"yMin\": -230,\n      \"yMax\": 1074,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zeyada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 934,\n      \"des\": -680,\n      \"tAsc\": 934,\n      \"tDes\": -680,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 680,\n      \"xH\": 312,\n      \"capH\": 602,\n      \"yMin\": -680,\n      \"yMax\": 934,\n      \"hAsc\": 934,\n      \"hDes\": -680,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zhi Mang Xing\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 383,\n      \"xH\": 496,\n      \"capH\": 750,\n      \"yMin\": -383,\n      \"yMax\": 912,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zilla Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -256,\n      \"tAsc\": 787,\n      \"tDes\": -213,\n      \"tLGap\": 200,\n      \"wAsc\": 944,\n      \"wDes\": 256,\n      \"xH\": 445,\n      \"capH\": 650,\n      \"yMin\": -231,\n      \"yMax\": 883,\n      \"hAsc\": 944,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zilla Slab Highlight\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -256,\n      \"tAsc\": 787,\n      \"tDes\": -213,\n      \"tLGap\": 200,\n      \"wAsc\": 944,\n      \"wDes\": 256,\n      \"xH\": 445,\n      \"capH\": 650,\n      \"yMin\": -252,\n      \"yMax\": 918,\n      \"hAsc\": 944,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  }\n]\n"
  },
  {
    "path": "includes/data/stories/demo.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f94c1f56-1c4e-461b-94b1-71919a5561d4\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-09-22T08:23:37\",\n            \"src\": \"https://replaceme.com/images/demo-story/image-1.png\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 12755,\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #fff\\\">L10N_PLACEHOLDER_1_1</span>\",\n          \"width\": 334,\n          \"height\": 220,\n          \"id\": \"103b0de3-c269-4dbc-bd68-568ef5b7dbd3\",\n          \"x\": 62,\n          \"y\": 373,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-09-22T08:25:46\",\n            \"src\": \"https://replaceme.com/images/demo-story/web-stories-logo.png\",\n            \"width\": 194,\n            \"height\": 194,\n            \"posterId\": 0,\n            \"id\": 12757,\n            \"title\": \"\",\n            \"alt\": \"Web Stories\",\n            \"sizes\": [],\n            \"isExternal\": false\n          },\n          \"type\": \"image\",\n          \"x\": 53,\n          \"y\": 280,\n          \"width\": 83,\n          \"height\": 83,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"1f6c6ae7-01b2-4edb-9626-dac1cb0e5e91\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"cf91578e-22d6-424d-928a-8e0917cfa48d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ceeacb28-f8c6-45b4-aa80-46ab655a7c45\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -16,\n          \"y\": 5,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"ceed60ed-294a-4adb-a28a-2a285b2a320d\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-1.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-1-poster.jpeg\",\n            \"posterId\": 12831,\n            \"id\": 12830,\n            \"length\": 4,\n            \"lengthFormatted\": \"0:04\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"004a2890-04b2-4cea-aa73-961f2450507f\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_2_2</span>\",\n          \"width\": 328,\n          \"height\": 78,\n          \"type\": \"text\",\n          \"marginOffset\": 0\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_2_1</span>\",\n          \"width\": 316,\n          \"height\": 24,\n          \"id\": \"68b0dbfc-c986-4267-b96e-b2bc025d56c9\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"266aff79-1125-4ffd-a4e5-9100541c1b5f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"d9915c74-6777-4322-aedc-0f5998f82781\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -40,\n          \"y\": 13,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"20c8b7f3-ef75-4f02-b4b3-6e272167f84b\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-2.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-2-poster.jpeg\",\n            \"posterId\": 12833,\n            \"id\": 12832,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"color: #fff\\\">L10N_PLACEHOLDER_3_2</span>\",\n          \"width\": 328,\n          \"height\": 104,\n          \"type\": \"text\",\n          \"id\": \"8352409b-8d75-45b1-8a56-bd2f57c81a7f\",\n          \"x\": 42,\n          \"y\": 501\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_3_1</span>\",\n          \"width\": 327,\n          \"height\": 24,\n          \"type\": \"text\",\n          \"id\": \"2619d1cc-3328-4683-a5ea-3e6f07f9b5ba\",\n          \"x\": 43,\n          \"y\": 462\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"9d8b64c3-5692-4e4c-ae46-785e23613db1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e9ddfe89-4c10-43cf-8892-bc49d52a90a5\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -12,\n          \"y\": 8,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4b1780d0-1edf-4e1c-a3a0-77d91fb5243d\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-3.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-3-poster.jpeg\",\n            \"posterId\": 12806,\n            \"id\": 12805,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"f8b4a07c-1f1b-4140-945c-66a729bd77ae\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_4_2</span>\",\n          \"width\": 328,\n          \"height\": 104,\n          \"type\": \"text\",\n          \"marginOffset\": 0\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_4_1</span>\",\n          \"width\": 310,\n          \"height\": 24,\n          \"id\": \"00b5e9e3-1134-4407-974c-8f0f0770eb19\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 74, \"g\": 64, \"b\": 177 } },\n      \"type\": \"page\",\n      \"id\": \"f3d54fcf-e8ae-4232-b400-465c81953282\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e8eb4129-84a9-4e15-b9f9-611e2ef238da\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -33,\n          \"y\": 8,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c412199f-d6f5-45cc-8ad8-c4020c3968ad\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-4.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-4-poster.jpeg\",\n            \"posterId\": 12809,\n            \"id\": 12808,\n            \"length\": 6,\n            \"lengthFormatted\": \"0:06\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"8abc8e46-48f4-4a57-8396-3a74d5fa0790\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_5_2</span>\",\n          \"width\": 326,\n          \"height\": 104,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_5_1</span>\",\n          \"width\": 230,\n          \"height\": 24,\n          \"id\": \"8f0b5de9-1252-4dab-9596-d1bc7dd45e1c\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"6728de08-eedb-40a2-9a3a-604ff4c87214\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f9a4110f-8c26-41cc-b36f-3144ae5570c7\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -29,\n          \"y\": 15,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c412199f-d6f5-45cc-8ad8-c4020c3968ad\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-5.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-5-poster.jpeg\",\n            \"posterId\": 12813,\n            \"id\": 12812,\n            \"length\": 3,\n            \"lengthFormatted\": \"0:03\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"3cdc3e2c-80b9-4946-b0c6-5d473ffe127d\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_6_2</span>\",\n          \"width\": 322,\n          \"height\": 104,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_6_1</span>\",\n          \"width\": 281,\n          \"height\": 24,\n          \"id\": \"7d453d81-a14d-4420-b143-6a39854dceea\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"87eb274d-a2dd-495f-add0-ad681cf757f5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e730f3df-a4f3-4415-9dea-820aa8cde222\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -3,\n          \"y\": 15,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c412199f-d6f5-45cc-8ad8-c4020c3968ad\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-6.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-6-poster.jpeg\",\n            \"posterId\": 12816,\n            \"id\": 12815,\n            \"length\": 22,\n            \"lengthFormatted\": \"0:22\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"0108f423-121e-41e7-8fb9-68da265caaba\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_7_2</span>\",\n          \"width\": 318,\n          \"height\": 104,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_7_1</span>\",\n          \"width\": 282,\n          \"height\": 24,\n          \"id\": \"bee50053-183a-43dc-95cd-dcfa6817f4e6\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"f79a3e34-81ab-4165-a2aa-83da192b1e9d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"a5b02ad2-9692-4794-a206-0da280de8e11\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -16,\n          \"y\": 11,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"1c6ec285-92e7-41f8-b140-722e3a2fab3b\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"https://replaceme.com/images/demo-story/video-7.mp4\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"poster\": \"https://replaceme.com/images/demo-story/video-7-poster.jpeg\",\n            \"posterId\": 12819,\n            \"id\": 12818,\n            \"length\": 10,\n            \"lengthFormatted\": \"0:10\",\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"x\": 42,\n          \"y\": 501,\n          \"id\": \"5542ba59-9388-49fc-b7e1-f2ec50c047a9\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">L10N_PLACEHOLDER_8_2</span>\",\n          \"width\": 330,\n          \"height\": 96,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 84,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_8_1</span>\",\n          \"width\": 321,\n          \"height\": 24,\n          \"id\": \"86baa049-1a48-44ae-a82c-08ba93244754\",\n          \"x\": 42,\n          \"y\": 461,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"4cbf7ec8-cf12-4ff2-bfb0-3bef7f3d76cb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"d82bbd0e-7539-48df-9cc5-158424a4a3d1\",\n        \"type\": \"shape\"\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 538,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c412199f-d6f5-45cc-8ad8-c4020c3968ad\",\n          \"type\": \"image\",\n          \"scale\": 124,\n          \"focalX\": 38.51180131399874,\n          \"focalY\": 51.981874424803884,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-09-22T04:07:58\",\n            \"src\": \"https://replaceme.com/images/demo-story/image-2.png\",\n            \"width\": 330,\n            \"height\": 538,\n            \"posterId\": 0,\n            \"id\": 12730,\n            \"title\": \"\",\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": false\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"initial\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"title\": \"\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">L10N_PLACEHOLDER_9_1</span>\",\n          \"width\": 313,\n          \"height\": 190,\n          \"id\": \"0106c119-e3d1-416f-92e4-b3f5b7e6c2c5\",\n          \"x\": 49,\n          \"y\": 292\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 117, \"b\": 52 } },\n          \"type\": \"shape\",\n          \"width\": 30,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9acf6b79-00a8-4264-854d-63a465f0a8c7\",\n          \"x\": 48.5,\n          \"y\": 518\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ]\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"initial\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"id\": \"e59aa680-9a49-439a-98fd-18660d8dfa21\",\n          \"content\": \"<span style=\\\"color: #fff\\\">bit.ly/storybestpractices</span>\",\n          \"x\": 49,\n          \"y\": 536,\n          \"width\": 226,\n          \"height\": 23,\n          \"link\": {\n            \"url\": \"L10N_PLACEHOLDER_9_2\",\n            \"icon\": \"https://amp.dev/static/img/sharing/docs-guide-600x314.png\",\n            \"desc\": \"L10N_PLACEHOLDER_9_3\"\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 22, \"b\": 22 } },\n      \"type\": \"page\",\n      \"id\": \"17fc30f7-8968-41a2-aaef-c7a1be1b753c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b37b1843-756e-48e4-b497-2680412c1381\",\n        \"type\": \"shape\"\n      }\n    }\n  ],\n  \"autoAdvance\": false,\n  \"defaultPageDuration\": 7\n}\n"
  },
  {
    "path": "includes/functions.php",
    "content": "<?php\n/**\n * Miscellaneous functions.\n * These are mostly utility or wrapper functions.\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse Google\\Web_Stories\\Admin\\Customizer;\nuse WP_Post;\n\n/**\n * Render stories based on the passed arguments.\n *\n * @since 1.5.0\n *\n * @param array<string, string|int|bool> $attrs Arguments for displaying stories.\n * @param array<string, string|int|bool> $query_args Query arguments for stories.\n *\n * @phpstan-param array{view_type?: string, number_of_columns?: int, show_title?: bool, show_author?: bool, show_date?: bool, show_archive_link?: bool|string, show_excerpt?: bool, image_alignment?: string, class?: string, archive_link_label?: string, circle_size?: int, sharp_corners?: bool, order?: string, orderby?: string} $attrs\n */\nfunction render_stories( array $attrs = [], array $query_args = [] ): void {\n\t$stories_obj = new Story_Query( $attrs, $query_args );\n\t//phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped\n\techo $stories_obj->render();\n}\n\n/**\n * Returns list of stories based on the arguments passed to it.\n *\n * @since 1.5.0\n *\n * @param array<string, string|int|bool> $attrs Arguments for displaying stories.\n * @param array<string, string|int|bool> $query_args Query arguments for stories.\n * @return WP_Post[]\n *\n * @phpstan-param array{view_type?: string, number_of_columns?: int, show_title?: bool, show_author?: bool, show_date?: bool, show_archive_link?: bool|string, show_excerpt?: bool, image_alignment?: string, class?: string, archive_link_label?: string, circle_size?: int, sharp_corners?: bool, order?: string, orderby?: string} $attrs\n */\nfunction get_stories( array $attrs = [], array $query_args = [] ): array {\n\treturn ( new Story_Query( $attrs, $query_args ) )->get_stories();\n}\n\n/**\n * Render stories based on customizer settings.\n *\n * @since 1.5.0\n */\nfunction render_theme_stories(): void {\n\t$injector = Services::get_injector();\n\n\t/**\n\t * Customizer instance.\n\t *\n\t * @var Customizer $customizer Customizer instance.\n\t */\n\t$customizer = $injector->make( Customizer::class );\n\t//phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped\n\techo $customizer->render_stories();\n}\n"
  },
  {
    "path": "includes/namespace.php",
    "content": "<?php\n/**\n * Plugin initialization file.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories;\n\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_Site;\n\n/**\n * Handles plugin activation.\n *\n * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n *\n * @since 1.0.0\n *\n * @param bool $network_wide Whether to activate network-wide.\n */\nfunction activate( ?bool $network_wide = false ): void {\n\t$network_wide = (bool) $network_wide;\n\n\t// Runs all PluginActivationAware services.\n\t// This will also flush rewrite rules.\n\tPluginFactory::create()->on_plugin_activation( $network_wide );\n\n\t/**\n\t * Fires after plugin activation.\n\t *\n\t * @param bool $network_wide Whether to activate network-wide.\n\t */\n\tdo_action( 'web_stories_activation', $network_wide );\n}\n\nregister_activation_hook( WEBSTORIES_PLUGIN_FILE, __NAMESPACE__ . '\\activate' );\n\n/**\n * Hook into new site creation on Multisite.\n *\n * @since 1.0.0\n *\n * @param int|WP_Site $site Site ID or object.\n */\nfunction new_site( $site ): void {\n\tif ( ! is_multisite() ) {\n\t\treturn;\n\t}\n\n\t$site = get_site( $site );\n\n\tif ( ! $site ) {\n\t\treturn;\n\t}\n\n\t// Runs all SiteInitializationAware services.\n\t// This will also flush rewrite rules.\n\tPluginFactory::create()->on_site_initialization( $site );\n}\n\nadd_action( 'wp_initialize_site', __NAMESPACE__ . '\\new_site', PHP_INT_MAX );\n\n/**\n * Hook into site removal on Multisite.\n *\n * @since 1.1.0\n *\n * @param WP_Error    $error Unused.\n * @param int|WP_Site $site Site ID or object.\n */\nfunction remove_site( WP_Error $error, $site ): void {\n\tif ( ! is_multisite() ) {\n\t\treturn;\n\t}\n\n\t$site = get_site( $site );\n\n\tif ( ! $site ) {\n\t\treturn;\n\t}\n\n\tPluginFactory::create()->on_site_removal( $site );\n}\n\nadd_action( 'wp_validate_site_deletion', __NAMESPACE__ . '\\remove_site', PHP_INT_MAX, 2 );\n\n/**\n * Handles plugin deactivation.\n *\n * @SuppressWarnings(\"PHPMD.BooleanArgumentFlag\")\n *\n * @since 1.0.0\n *\n * @param bool $network_wide Whether to deactivate network-wide.\n */\nfunction deactivate( ?bool $network_wide = false ): void {\n\t$network_wide = (bool) $network_wide;\n\n\t// Runs all PluginDeactivationAware services.\n\t// This will also flush rewrite rules.\n\tPluginFactory::create()->on_plugin_deactivation( $network_wide );\n\n\t/**\n\t * Fires after plugin deactivation.\n\t *\n\t * @param bool $network_wide Whether to deactivate network-wide.\n\t */\n\tdo_action( 'web_stories_deactivation', $network_wide );\n}\n\nregister_deactivation_hook( WEBSTORIES_PLUGIN_FILE, __NAMESPACE__ . '\\deactivate' );\n\n/**\n * Initializes functionality to improve compatibility with the AMP plugin.\n *\n * Loads a separate PHP file that allows defining functions in the global namespace.\n *\n * Runs on the 'wp' hook to ensure the WP environment has been fully set up,\n */\nfunction load_amp_plugin_compat(): void {\n\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/compat/amp.php';\n}\n\nadd_action( 'wp', __NAMESPACE__ . '\\load_amp_plugin_compat' );\n\n/**\n * Load functions for use by plugin developers.\n *\n * @todo Move to autoloader\n */\nfunction load_functions(): void {\n\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/functions.php';\n}\n\nadd_action( 'init', __NAMESPACE__ . '\\load_functions' );\n\n/**\n * Append result of internal request to REST API for purpose of preloading data to be attached to a page.\n * Expected to be called in the context of `array_reduce`.\n *\n * Like rest_preload_api_request() in core, but embeds links and removes trailing slashes.\n *\n * @SuppressWarnings(\"PHPMD.NPathComplexity\")\n *\n * @since 1.2.0\n *\n * @link https://core.trac.wordpress.org/ticket/51722\n * @link https://core.trac.wordpress.org/ticket/51636\n * @see \\rest_preload_api_request\n *\n * @param array<string, array{body: string, headers: array<string,string>}|array<string, array{body: string, headers: array<string,string>}>> $memo Reduce accumulator.\n * @param string|array<int, string>                                                                                                           $path REST API path to preload.\n * @return array<string, array{body: string, headers: array<string,string>}|array<string, array{body: string, headers: array<string,string>}>> Modified reduce accumulator.\n */\nfunction rest_preload_api_request( array $memo, $path ): array {\n\tif ( empty( $path ) ) {\n\t\treturn $memo;\n\t}\n\n\t$method = 'GET';\n\tif ( \\is_array( $path ) ) {\n\t\tif ( 2 !== \\count( $path ) ) {\n\t\t\treturn $memo;\n\t\t}\n\n\t\t$method = end( $path );\n\t\t$path   = (string) reset( $path );\n\n\t\tif ( ! \\in_array( $method, [ 'GET', 'OPTIONS' ], true ) ) {\n\t\t\t$method = 'GET';\n\t\t}\n\t}\n\n\t/**\n\t * URL parts.\n\t *\n\t * @var array{path:string, query?: string}|false $path_parts\n\t */\n\t$path_parts = wp_parse_url( (string) $path );\n\tif ( ! \\is_array( $path_parts ) ) {\n\t\treturn $memo;\n\t}\n\n\t// This line is different from code. Adds untrailingslashit. See https://core.trac.wordpress.org/ticket/57048.\n\t$request = new WP_REST_Request( $method, untrailingslashit( $path_parts['path'] ) );\n\tif ( ! empty( $path_parts['query'] ) ) {\n\t\t$query_params = [];\n\t\tparse_str( $path_parts['query'], $query_params );\n\t\t$request->set_query_params( $query_params );\n\t}\n\n\t$response = rest_do_request( $request );\n\tif ( 200 === $response->status ) {\n\t\t$server = rest_get_server();\n\t\t/**\n\t\t * Embed directive.\n\t\t *\n\t\t * @var string|string[] $embed\n\t\t */\n\t\t$embed = $request['_embed'] ?? false;\n\t\t$embed = $embed ? rest_parse_embed_param( $embed ) : false;\n\t\t$data  = $server->response_to_data( $response, $embed );\n\n\t\tif ( 'OPTIONS' === $method ) {\n\t\t\t$response = rest_send_allow_header( $response, $server, $request );\n\n\t\t\t$memo[ $method ][ $path ] = [\n\t\t\t\t'body'    => $data,\n\t\t\t\t'headers' => $response->headers,\n\t\t\t];\n\t\t} else {\n\t\t\t$memo[ $path ] = [\n\t\t\t\t'body'    => $data,\n\t\t\t\t'headers' => $response->headers,\n\t\t\t];\n\t\t}\n\t}\n\n\treturn $memo;\n}\n\n/**\n * Returns the Web stories plugin instance.\n *\n * Can be used by other plugins to integrate with the plugin\n * or to simply detect whether the plugin is active.\n */\nfunction get_plugin_instance(): Plugin {\n\treturn PluginFactory::create();\n}\n\n/**\n * Bootstrap the plugin.\n *\n * @since 1.11.0\n */\nfunction bootstrap_plugin(): void {\n\tPluginFactory::create()->register();\n}\n\nadd_action( 'plugins_loaded', __NAMESPACE__ . '\\bootstrap_plugin' );\n"
  },
  {
    "path": "includes/polyfills/mbstring.php",
    "content": "<?php\n/*\n * Adapted from the polyfill-mbstring Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\n// This is is a copy of symfony/polyfill-mbstring/bootstrap.php.\n// The file is not used directly because after running through PHP-Scoper\n// it won't be in the global scope anymore.\n\nuse Google\\Web_Stories_Dependencies\\Symfony\\Polyfill\\Mbstring as Google_Web_Stories_Mbstring;\n\nif ( ! function_exists( 'mb_convert_encoding' ) ) {\n\tfunction mb_convert_encoding( $s, $to, $from = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_convert_encoding( $s, $to, $from );\n\t}\n}\nif ( ! function_exists( 'mb_decode_mimeheader' ) ) {\n\tfunction mb_decode_mimeheader( $s ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_decode_mimeheader( $s );\n\t}\n}\nif ( ! function_exists( 'mb_encode_mimeheader' ) ) {\n\tfunction mb_encode_mimeheader( $s, $charset = null, $transferEnc = null, $lf = null, $indent = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_encode_mimeheader( $s, $charset, $transferEnc, $lf, $indent );\n\t}\n}\nif ( ! function_exists( 'mb_decode_numericentity' ) ) {\n\tfunction mb_decode_numericentity( $s, $convmap, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_decode_numericentity( $s, $convmap, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_encode_numericentity' ) ) {\n\tfunction mb_encode_numericentity( $s, $convmap, $enc = null, $is_hex = false ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_encode_numericentity( $s, $convmap, $enc, $is_hex );\n\t}\n}\nif ( ! function_exists( 'mb_convert_case' ) ) {\n\tfunction mb_convert_case( $s, $mode, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_convert_case( $s, $mode, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_internal_encoding' ) ) {\n\tfunction mb_internal_encoding( $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_internal_encoding( $enc );\n\t}\n}\nif ( ! function_exists( 'mb_language' ) ) {\n\tfunction mb_language( $lang = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_language( $lang );\n\t}\n}\nif ( ! function_exists( 'mb_list_encodings' ) ) {\n\tfunction mb_list_encodings() {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_list_encodings();\n\t}\n}\nif ( ! function_exists( 'mb_encoding_aliases' ) ) {\n\tfunction mb_encoding_aliases( $encoding ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_encoding_aliases( $encoding );\n\t}\n}\nif ( ! function_exists( 'mb_check_encoding' ) ) {\n\tfunction mb_check_encoding( $var = null, $encoding = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_check_encoding( $var, $encoding );\n\t}\n}\nif ( ! function_exists( 'mb_detect_encoding' ) ) {\n\tfunction mb_detect_encoding( $str, $encodingList = null, $strict = false ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_detect_encoding( $str, $encodingList, $strict );\n\t}\n}\nif ( ! function_exists( 'mb_detect_order' ) ) {\n\tfunction mb_detect_order( $encodingList = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_detect_order( $encodingList );\n\t}\n}\nif ( ! function_exists( 'mb_parse_str' ) ) {\n\tfunction mb_parse_str( $s, &$result = [] ) {\n\t\tparse_str( $s, $result );\n\t}\n}\nif ( ! function_exists( 'mb_strlen' ) ) {\n\tfunction mb_strlen( $s, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strlen( $s, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strpos' ) ) {\n\tfunction mb_strpos( $s, $needle, $offset = 0, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strpos( $s, $needle, $offset, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strtolower' ) ) {\n\tfunction mb_strtolower( $s, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strtolower( $s, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strtoupper' ) ) {\n\tfunction mb_strtoupper( $s, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strtoupper( $s, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_substitute_character' ) ) {\n\tfunction mb_substitute_character( $char = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_substitute_character( $char );\n\t}\n}\nif ( ! function_exists( 'mb_substr' ) ) {\n\tfunction mb_substr( $s, $start, $length = 2147483647, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_substr( $s, $start, $length, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_stripos' ) ) {\n\tfunction mb_stripos( $s, $needle, $offset = 0, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_stripos( $s, $needle, $offset, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_stristr' ) ) {\n\tfunction mb_stristr( $s, $needle, $part = false, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_stristr( $s, $needle, $part, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strrchr' ) ) {\n\tfunction mb_strrchr( $s, $needle, $part = false, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strrchr( $s, $needle, $part, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strrichr' ) ) {\n\tfunction mb_strrichr( $s, $needle, $part = false, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strrichr( $s, $needle, $part, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strripos' ) ) {\n\tfunction mb_strripos( $s, $needle, $offset = 0, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strripos( $s, $needle, $offset, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strrpos' ) ) {\n\tfunction mb_strrpos( $s, $needle, $offset = 0, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strrpos( $s, $needle, $offset, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strstr' ) ) {\n\tfunction mb_strstr( $s, $needle, $part = false, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strstr( $s, $needle, $part, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_get_info' ) ) {\n\tfunction mb_get_info( $type = 'all' ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_get_info( $type );\n\t}\n}\nif ( ! function_exists( 'mb_http_output' ) ) {\n\tfunction mb_http_output( $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_http_output( $enc );\n\t}\n}\nif ( ! function_exists( 'mb_strwidth' ) ) {\n\tfunction mb_strwidth( $s, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_strwidth( $s, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_substr_count' ) ) {\n\tfunction mb_substr_count( $haystack, $needle, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_substr_count( $haystack, $needle, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_output_handler' ) ) {\n\tfunction mb_output_handler( $contents, $status ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_output_handler( $contents, $status );\n\t}\n}\nif ( ! function_exists( 'mb_http_input' ) ) {\n\tfunction mb_http_input( $type = '' ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_http_input( $type );\n\t}\n}\nif ( ! function_exists( 'mb_convert_variables' ) ) {\n\tfunction mb_convert_variables( $toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_convert_variables( $toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f );\n\t}\n}\nif ( ! function_exists( 'mb_ord' ) ) {\n\tfunction mb_ord( $s, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_ord( $s, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_chr' ) ) {\n\tfunction mb_chr( $code, $enc = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_chr( $code, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_scrub' ) ) {\n\tfunction mb_scrub( $s, $enc = null ) {\n\t\t$enc = $enc ?? mb_internal_encoding();\n\t\treturn mb_convert_encoding( $s, $enc, $enc );\n\t}\n}\nif ( ! function_exists( 'mb_str_split' ) ) {\n\tfunction mb_str_split( $string, $split_length = 1, $encoding = null ) {\n\t\treturn Google_Web_Stories_Mbstring\\Mbstring::mb_str_split( $string, $split_length, $encoding );\n\t}\n}\nif ( extension_loaded( 'mbstring' ) ) {\n\treturn;\n}\nif ( ! defined( 'MB_CASE_UPPER' ) ) {\n\tdefine( 'MB_CASE_UPPER', 0 );\n}\nif ( ! defined( 'MB_CASE_LOWER' ) ) {\n\tdefine( 'MB_CASE_LOWER', 1 );\n}\nif ( ! defined( 'MB_CASE_TITLE' ) ) {\n\tdefine( 'MB_CASE_TITLE', 2 );\n}\n"
  },
  {
    "path": "includes/templates/admin/activation-notice.php",
    "content": "<?php\n/**\n * Activation notice.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// don't load directly.\nif ( ! defined( 'ABSPATH' ) ) {\n\tdie( '-1' );\n}\n?>\n<div id=\"web-stories-plugin-activation-notice\" class=\"notice notice-success is-dismissible\">\n\n</div>\n"
  },
  {
    "path": "includes/templates/admin/dashboard.php",
    "content": "<?php\n/**\n * Stories dashboard.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nuse Google\\Web_Stories\\Admin\\Dashboard;\nuse Google\\Web_Stories\\Services;\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// don't load directly.\nif ( ! defined( 'ABSPATH' ) ) {\n\tdie( '-1' );\n}\n\n$dashboard_settings = Services::get( 'dashboard' )->get_dashboard_settings();\n\n$init_script = <<<'JS'\n\twp.domReady( function() {\n\t  webStories.initializeStoryDashboard( 'web-stories-dashboard', %s );\n\t} );\nJS;\n\n$script = sprintf( $init_script, wp_json_encode( $dashboard_settings ) );\n\nwp_add_inline_script( Dashboard::SCRIPT_HANDLE, $script );\n\n?>\n\n<div class=\"web-stories-wp\">\n\t<h1 class=\"screen-reader-text hide-if-no-js\"><?php esc_html_e( 'Web Stories', 'web-stories' ); ?></h1>\n\t<div id=\"web-stories-dashboard\" class=\"web-stories-dashboard-app-container hide-if-no-js\">\n\t\t<h1 class=\"loading-message\"><?php esc_html_e( 'Please wait...', 'web-stories' ); ?></h1>\n\t</div>\n\n\t<?php // JavaScript is disabled. ?>\n\t<div class=\"wrap hide-if-js web-stories-wp-no-js\">\n\t\t<h1 class=\"wp-heading-inline\"><?php esc_html_e( 'Web Stories', 'web-stories' ); ?></h1>\n\t\t<div class=\"notice notice-error notice-alt\">\n\t\t\t<p><?php esc_html_e( 'Web Stories for WordPress requires JavaScript. Please enable JavaScript in your browser settings.', 'web-stories' ); ?></p>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "includes/templates/admin/edit-story.php",
    "content": "<?php\n/**\n * The story editor.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nuse Google\\Web_Stories\\Admin\\Editor;\nuse Google\\Web_Stories\\Services;\nuse function Google\\Web_Stories\\rest_preload_api_request;\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// don't load directly.\nif ( ! defined( 'ABSPATH' ) ) {\n\tdie( '-1' );\n}\n\nglobal $post_type, $post_type_object, $post;\n\n$stories_rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;\n$initial_edits     = [ 'story' => null ];\n\n\n// Preload common data.\n// Important: keep in sync with usage & definition in React app.\n$preload_paths = [\n\t'/web-stories/v1/media/?' . build_query(\n\t\t[\n\t\t\t'context'               => 'view',\n\t\t\t'per_page'              => 50,\n\t\t\t'page'                  => 1,\n\t\t\t'_web_stories_envelope' => 'true',\n\t\t\t'_fields'               => rawurlencode(\n\t\t\t\timplode(\n\t\t\t\t\t',',\n\t\t\t\t\t[\n\t\t\t\t\t\t'id',\n\t\t\t\t\t\t'date_gmt',\n\t\t\t\t\t\t'media_details',\n\t\t\t\t\t\t'mime_type',\n\t\t\t\t\t\t'featured_media',\n\t\t\t\t\t\t'featured_media_src',\n\t\t\t\t\t\t'alt_text',\n\t\t\t\t\t\t'source_url',\n\t\t\t\t\t\t'meta',\n\t\t\t\t\t\t'web_stories_media_source',\n\t\t\t\t\t\t'web_stories_is_muted',\n\t\t\t\t\t\t// _web_stories_envelope will add these fields, we need them too.\n\t\t\t\t\t\t'body',\n\t\t\t\t\t\t'status',\n\t\t\t\t\t\t'headers',\n\t\t\t\t\t]\n\t\t\t\t)\n\t\t\t),\n\t\t]\n\t),\n\t'/web-stories/v1/media/?' . build_query(\n\t\t[\n\t\t\t'context'  => 'view',\n\t\t\t'per_page' => 10,\n\t\t\t'_fields'  => 'source_url',\n\t\t]\n\t),\n\t'/web-stories/v1/users/me/',\n\t'/web-stories/v1/taxonomies/?' . build_query(\n\t\t[\n\t\t\t'context' => 'edit',\n\t\t\t'show_ui' => 'true',\n\t\t\t'type'    => $post_type_object->name,\n\t\t]\n\t),\n];\n\n$story_initial_path = \"/web-stories/v1/$stories_rest_base/{$post->ID}/?\";\n$story_query_params = [\n\t'_embed'  => rawurlencode(\n\t\timplode(\n\t\t\t',',\n\t\t\t[ 'wp:lock', 'author', 'wp:publisherlogo', 'wp:term' ]\n\t\t)\n\t),\n\t'context' => 'edit',\n\t'_fields' => rawurlencode(\n\t\timplode(\n\t\t\t',',\n\t\t\t[\n\t\t\t\t'id',\n\t\t\t\t'title',\n\t\t\t\t'status',\n\t\t\t\t'slug',\n\t\t\t\t'date',\n\t\t\t\t'modified',\n\t\t\t\t'excerpt',\n\t\t\t\t'link',\n\t\t\t\t'story_poster',\n\t\t\t\t'story_data',\n\t\t\t\t'preview_link',\n\t\t\t\t'edit_link',\n\t\t\t\t'embed_post_link',\n\t\t\t\t'permalink_template',\n\t\t\t\t'style_presets',\n\t\t\t\t'password',\n\t\t\t\t'_links',\n\t\t\t\t'_embedded',\n\t\t\t]\n\t\t)\n\t),\n];\n\n/*\n * Ensure the global $post remains the same after API data is preloaded.\n * Because API preloading can call the_content and other filters, plugins\n * can unexpectedly modify $post.\n */\n$backup_global_post = $post;\n\nif ( empty( $_GET['web-stories-demo'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended\n\t$preload_paths[] = $story_initial_path . build_query( $story_query_params );\n} else {\n\t$story_query_params['web_stories_demo'] = 'true';\n\n\t$story_path             = $story_initial_path . build_query( $story_query_params );\n\t$story_data             = rest_preload_api_request( [], $story_path );\n\t$initial_edits['story'] = ! empty( $story_data[ $story_path ]['body'] ) ? $story_data[ $story_path ]['body'] : [];\n}\n\n/**\n * Preload common data by specifying an array of REST API paths that will be preloaded.\n *\n * Filters the array of paths that will be preloaded.\n *\n * @param string[] $preload_paths Array of paths to preload.\n * @param WP_Post  $post          Post being edited.\n */\n$preload_paths = apply_filters( 'web_stories_editor_preload_paths', $preload_paths, $post );\n\n$preload_data = array_reduce(\n\t$preload_paths,\n\t'\\Google\\Web_Stories\\rest_preload_api_request',\n\t[]\n);\n\n// Restore the global $post as it was before API preloading.\n$post = $backup_global_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited\n\n// In order to duplicate classic meta box behaviour, we need to run the classic meta box actions.\nrequire_once ABSPATH . 'wp-admin/includes/meta-boxes.php';\nregister_and_do_post_meta_boxes( $post );\n\n$editor_settings = Services::get( 'editor' )->get_editor_settings();\n\nwp_add_inline_script(\n\t'wp-api-fetch',\n\tsprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', wp_json_encode( $preload_data ) ),\n\t'after'\n);\n\n$init_script = <<<'JS'\n\twp.domReady( function() {\n\t  webStories.initializeStoryEditor( 'web-stories-editor', %s, %s );\n\t} );\nJS;\n\n$script = sprintf( $init_script, wp_json_encode( $editor_settings ), wp_json_encode( $initial_edits ) );\n\nwp_add_inline_script( Editor::SCRIPT_HANDLE, $script );\n\nrequire_once ABSPATH . 'wp-admin/admin-header.php';\n\n// TODO: Use custom version of the_block_editor_meta_boxes() without the block editor specifics?\n?>\n\n<div class=\"web-stories-wp\">\n\t<h1 class=\"screen-reader-text hide-if-no-js\"><?php esc_html_e( 'Web Stories', 'web-stories' ); ?></h1>\n\t<div id=\"web-stories-editor\" class=\"web-stories-editor-app-container hide-if-no-js\">\n\t\t<h1 class=\"loading-message\"><?php esc_html_e( 'Please wait...', 'web-stories' ); ?></h1>\n\t</div>\n\n\t<div id=\"metaboxes\" class=\"hidden\">\n\t\t<?php the_block_editor_meta_boxes(); ?>\n\t</div>\n\n\t<?php // JavaScript is disabled. ?>\n\t<div class=\"wrap hide-if-js web-stories-wp-no-js\">\n\t\t<h1 class=\"wp-heading-inline\"><?php esc_html_e( 'Web Stories', 'web-stories' ); ?></h1>\n\t\t<div class=\"notice notice-error notice-alt\">\n\t\t\t<p><?php esc_html_e( 'Web Stories for WordPress requires JavaScript. Please enable JavaScript in your browser settings.', 'web-stories' ); ?></p>\n\t\t</div>\n\t</div>\n</div>\n"
  },
  {
    "path": "includes/templates/admin/experiments.php",
    "content": "<?php\n/**\n * Experiments page.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Settings;\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// don't load directly.\nif ( ! defined( 'ABSPATH' ) ) {\n\tdie( '-1' );\n}\n\n?>\n\t<div id=\"web-stories-experiments\" class=\"wrap\">\n\t\t<h1><?php esc_html_e( 'Experimental Settings', 'web-stories' ); ?></h1>\n\t\t<?php settings_errors(); ?>\n\t\t<form method=\"post\" action=\"options.php\">\n\t\t\t<?php settings_fields( Settings::SETTING_GROUP_EXPERIMENTS ); ?>\n\t\t\t<?php do_settings_sections( Experiments::PAGE_NAME ); ?>\n\t\t\t<?php submit_button(); ?>\n\t\t</form>\n\t</div>\n<?php\n"
  },
  {
    "path": "includes/templates/frontend/embed-web-story.php",
    "content": "<?php\n/**\n * Template for embedded web-story.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Image;\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nget_header( 'embed' );\n\nif ( have_posts() ) :\n\twhile ( have_posts() ) :\n\t\tthe_post();\n\t\t$current_post = get_post();\n\n\t\tif ( $current_post instanceof WP_Post && has_post_thumbnail( $current_post ) ) {\n\t\t\t$story = new Story();\n\t\t\t$story->load_from_post( $current_post );\n\t\t\t$renderer = new Image( $story );\n\t\t\techo $renderer->render(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t} else {\n\t\t\tget_template_part( 'embed', 'content' );\n\t\t}\n\tendwhile;\nelse :\n\tget_template_part( 'embed', '404' );\nendif;\n\nget_footer( 'embed' );\n"
  },
  {
    "path": "includes/templates/frontend/single-web-story.php",
    "content": "<?php\n/**\n * Template for web-story post type.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\HTML;\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nthe_post();\n\n$current_post = get_post();\n\nif ( $current_post instanceof WP_Post ) {\n\t$story = new Story();\n\n\t// Support displaying revisions of a story for logged-in users on the\n\t// wp-admin/revision.php page.\n\tif (\n\t\tisset( $_GET['rev_id'], $_GET['_wpnonce'] ) &&\n\t\tis_string( $_GET['_wpnonce'] ) &&\n\t\tis_string( $_GET['rev_id'] ) &&\n\t\twp_verify_nonce(\n\t\t\tsanitize_text_field( (string) wp_unslash( $_GET['_wpnonce'] ) ),\n\t\t\t'web_stories_revision_for_' . $current_post->ID\n\t\t)\n\t) {\n\t\t$rev_id        = absint( sanitize_text_field( (string) wp_unslash( $_GET['rev_id'] ) ) );\n\t\t$revision_post = get_post( $rev_id );\n\n\t\tif ( $revision_post instanceof WP_Post && $revision_post->post_parent === $current_post->ID ) {\n\t\t\t$current_post = $revision_post;\n\t\t}\n\t}\n\n\t$story->load_from_post( $current_post );\n\t$renderer = new HTML( $story );\n\techo $renderer->render(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n}\n\n// Some themes like the Sage theme override the WordPress template hierarchy in an unusual way,\n// which the Single Renderer tries to work around with filters.\n// However, that means this template potentially gets loaded twice when using such a theme, causing duplicate markup.\n// Exiting here avoids that, while still guaranteeing the output buffer to function properly.\nexit;\n"
  },
  {
    "path": "jest-puppeteer.config.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Environment variables\n */\nconst {\n  PUPPETEER_DEVTOOLS = false,\n  PUPPETEER_HEADLESS = true,\n  PUPPETEER_PRODUCT = 'chrome',\n  PUPPETEER_SLOWMO = 0,\n} = process.env;\n\nmodule.exports = {\n  launch: {\n    devtools: PUPPETEER_DEVTOOLS === 'true',\n    headless: Boolean(PUPPETEER_HEADLESS),\n    slowMo: Number(PUPPETEER_SLOWMO) || 0,\n    product: PUPPETEER_PRODUCT,\n    args: ['--window-size=1600,1000'], // Same as in percy.config.yml.\n  },\n  exitOnPageError: false,\n};\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@googleforcreators/*\": [\"./packages/*/src\"],\n      \"@web-stories-wp/*\": [\"./packages/*/src\"]\n    }\n  },\n  \"exclude\": [\n    \"dist\",\n    \"dist-module\",\n    \"node_modules\",\n    \"packages/e2e-tests/src/plugins\",\n    \"vendor\"\n  ]\n}\n"
  },
  {
    "path": "karma-dashboard.config.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use strict';\n\n/**\n * External dependencies\n */\nconst { readFileSync, existsSync } = require('fs');\n\n/**\n * Internal dependencies\n */\nconst getWebpackConfig = require('./webpack.config.test.cjs');\n\nmodule.exports = function (config) {\n  let specsToRetry;\n  if (\n    config.retryFailed &&\n    existsSync('build/karma-dashboard-failed-tests.txt')\n  ) {\n    // Loads names of failed specs and prepares them for use in a regex.\n    specsToRetry = readFileSync(\n      'build/karma-dashboard-failed-tests.txt',\n      'utf-8'\n    )\n      .replace(/\\s+$/g, '')\n      .replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&')\n      .replace(/-/g, '\\\\x2d')\n      .split('\\n')\n      .join('|');\n  }\n\n  config.set({\n    plugins: [\n      'karma-chrome-launcher',\n      'karma-jasmine',\n      'karma-sourcemap-loader',\n      'karma-webpack',\n      'karma-coverage-istanbul-reporter',\n      require('@web-stories-wp/karma-puppeteer-launcher'),\n      require('@web-stories-wp/karma-puppeteer-client'),\n      require('@web-stories-wp/karma-failed-tests-reporter'),\n    ],\n\n    // Frameworks to use.\n    // Available frameworks: https://npmjs.org/browse/keyword/karma-adapter\n    frameworks: [\n      'jasmine',\n      '@web-stories-wp/karma-puppeteer-client',\n      'webpack',\n    ],\n\n    // list of files / patterns to load in the browser\n    files: [\n      { pattern: 'packages/dashboard/src/**/karma/**/*.js', watched: false },\n      { pattern: 'packages/karma-fixture/src/init.js', watched: false },\n      {\n        pattern: '__static__/**/*',\n        watched: false,\n        included: false,\n        served: true,\n        nocache: false,\n      },\n      'node_modules/axe-core/axe.js',\n    ],\n\n    // list of files / patterns to exclude\n    exclude: ['**/test/**/*.js', '**/*.test.js'],\n\n    // preprocess matching files before serving them to the browser\n    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor\n    preprocessors: {\n      'packages/dashboard/src/**/karma/**/*.js': ['webpack', 'sourcemap'],\n    },\n\n    proxies: {\n      '/__static__/': '/base/__static__/',\n    },\n\n    webpack: getWebpackConfig('web-stories-dashboard', config),\n\n    webpackMiddleware: {\n      // webpack-dev-middleware configuration\n      // i. e.\n      stats: 'errors-only',\n    },\n\n    webpackServer: {\n      noInfo: true,\n    },\n\n    // test results reporter to use\n    // possible values: 'dots', 'progress'\n    // available reporters: https://npmjs.org/browse/keyword/karma-reporter\n    reporters: [\n      'dots',\n      '@web-stories-wp/karma-failed-tests-reporter',\n      config.coverage && 'coverage-istanbul',\n    ].filter(Boolean),\n\n    // web server port\n    port: 9876,\n\n    // enable / disable colors in the output (reporters and logs)\n    colors: true,\n\n    // level of logging\n    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG\n    logLevel: config.LOG_INFO,\n\n    // enable / disable watching file and executing tests whenever any file changes\n    autoWatch: true,\n\n    // start these browsers\n    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher\n    browsers: ['karma-puppeteer-launcher'], // @web-stories-wp/karma-puppeteer-launcher package\n\n    puppeteerLauncher: {\n      puppeteer: {\n        headless: Boolean(config.headless),\n        slowMo: config.slowMo || 0,\n        devtools: config.devtools || false,\n        snapshots: config.snapshots || false,\n        defaultViewport: getViewport(config.viewport),\n      },\n    },\n    client: {\n      args: [\n        specsToRetry && '--grep',\n        specsToRetry && `/${specsToRetry}/`,\n      ].filter(Boolean),\n      jasmine: {\n        timeoutInterval: 20000,\n      },\n      useIframe: false,\n      runInParent: true,\n    },\n\n    coverageIstanbulReporter: {\n      dir: 'build/logs/karma-coverage/dashboard',\n      reports: ['text-summary', 'lcovonly'],\n    },\n\n    failedTestsReporter: {\n      outputFile: 'build/karma-dashboard-failed-tests.txt',\n    },\n\n    // Continuous Integration mode\n    // if true, Karma captures browsers, runs the tests and exits\n    singleRun: false,\n\n    // Concurrency level\n    // how many browsers should be started simultaneously\n    concurrency: Infinity,\n\n    // Allow not having any tests\n    failOnEmptyTestSuite: false,\n\n    // Prevent duplicate logging to console\n    browserConsoleLogOptions: {\n      terminal: false,\n    },\n\n    // Bump browserNoActivityTimeout to 100s to prevent Github Actions timeout\n    browserNoActivityTimeout: 100000,\n\n    // Wait a bit longer for browser to reconnect.\n    browserDisconnectTimeout: 10000,\n\n    // Custom context file.\n    customClientContextFile:\n      'packages/karma-fixture/src/client_with_context.html',\n  });\n};\n\n/**\n * Returns a viewport object for  a given flag.\n *\n * The following viewports are supported:\n * - default: no special viewport is used.\n * - 1600:1000: empirical laptop size. Also used for screenshots.\n *\n * A custom W:H viewport is intentionally not supported to reduce number of\n * test variations.\n *\n * Todo: Support the viewport sizes from Figma:\n * - 1920:1080: the canonical desktop size.\n * - 1024:680: the canonical iPad size.\n *\n * @param {string} flag Viewport flag.\n * @return {{width: number, height: number}|null} Viewport.\n */\nfunction getViewport(flag) {\n  if (!flag) {\n    // @todo: switch to 1600:1000 default once Percy is fully launched.\n    return null;\n  }\n  if (flag === '1600:1000') {\n    return { width: 1600, height: 1000 };\n  }\n  throw new Error(`Unsupported viewport: \"${flag}\"`);\n}\n"
  },
  {
    "path": "karma-story-editor.config.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use strict';\n\n/**\n * External dependencies\n */\nconst { readFileSync } = require('fs');\n\n/**\n * Internal dependencies\n */\nconst getWebpackConfig = require('./webpack.config.test.cjs');\n\nmodule.exports = function (config) {\n  let specsToRetry;\n  if (config.retryFailed) {\n    // Loads names of failed specs and prepares them for use in a regex.\n    specsToRetry = readFileSync(\n      'build/karma-story-editor-failed-tests.txt',\n      'utf-8'\n    )\n      .replace(/\\s+$/g, '')\n      .replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&')\n      .replace(/-/g, '\\\\x2d')\n      .split('\\n')\n      .join('|');\n  }\n\n  let totalShards = 1;\n  let shardNumber = 1;\n  if (config.shard) {\n    [shardNumber, totalShards] = config.shard.split('/');\n  }\n  const shardIndex = shardNumber - 1;\n\n  const enableParallelRuns = config.shard || config.parallel;\n  // Default is number of CPU cores minus 1.\n  const parallelExecutors =\n    config.parallel && true !== config.parallel\n      ? Number(config.parallel)\n      : undefined;\n\n  config.set({\n    plugins: [\n      'karma-chrome-launcher',\n      'karma-jasmine',\n      'karma-sourcemap-loader',\n      'karma-webpack',\n      'karma-coverage-istanbul-reporter',\n      'karma-parallel',\n      require('@web-stories-wp/karma-puppeteer-launcher'),\n      require('@web-stories-wp/karma-puppeteer-client'),\n      require('@web-stories-wp/karma-failed-tests-reporter'),\n    ],\n\n    // Frameworks to use.\n    // Available frameworks: https://npmjs.org/browse/keyword/karma-adapter\n    frameworks: [\n      enableParallelRuns && 'parallel',\n      'jasmine',\n      '@web-stories-wp/karma-puppeteer-client',\n      'webpack',\n    ].filter(Boolean),\n\n    // list of files / patterns to load in the browser\n    files: [\n      { pattern: 'packages/story-editor/src/**/karma/**/*.js', watched: false },\n      { pattern: 'packages/karma-fixture/src/init.js', watched: false },\n      {\n        pattern: '__static__/**/*',\n        watched: false,\n        included: false,\n        served: true,\n        nocache: false,\n      },\n      'node_modules/axe-core/axe.js',\n    ],\n    // list of files / patterns to exclude\n    exclude: ['**/test/**/*.js', '**/*.test.js'],\n\n    // preprocess matching files before serving them to the browser\n    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor\n    preprocessors: {\n      'packages/story-editor/src/**/karma/**/*.js': ['webpack', 'sourcemap'],\n    },\n\n    proxies: {\n      '/__static__/': '/base/__static__/',\n    },\n\n    webpack: getWebpackConfig('web-stories-editor', config),\n\n    webpackMiddleware: {\n      // webpack-dev-middleware configuration\n      // i. e.\n      stats: 'errors-only',\n    },\n\n    webpackServer: {\n      noInfo: true,\n    },\n\n    // test results reporter to use\n    // possible values: 'dots', 'progress'\n    // available reporters: https://npmjs.org/browse/keyword/karma-reporter\n    reporters: [\n      'dots',\n      '@web-stories-wp/karma-failed-tests-reporter',\n      config.coverage && 'coverage-istanbul',\n    ].filter(Boolean),\n\n    // web server port\n    port: 9876,\n\n    // enable / disable colors in the output (reporters and logs)\n    colors: true,\n\n    // level of logging\n    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG\n    logLevel: config.LOG_INFO,\n\n    // enable / disable watching file and executing tests whenever any file changes\n    autoWatch: true,\n\n    // start these browsers\n    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher\n    browsers: ['karma-puppeteer-launcher'], // @web-stories-wp/karma-puppeteer-launcher package\n\n    puppeteerLauncher: {\n      puppeteer: {\n        headless: Boolean(config.headless),\n        slowMo: config.slowMo || 0,\n        devtools: config.devtools || false,\n        snapshots: config.snapshots || false,\n        snapshotsDir: '.test_artifacts/karma_snapshots',\n        defaultViewport: getViewport(config.viewport),\n        args: config.headless ? undefined : ['--window-size=1600,1000'],\n      },\n    },\n    client: {\n      args: [\n        specsToRetry && '--grep',\n        specsToRetry && `/${specsToRetry}/`,\n      ].filter(Boolean),\n      jasmine: {\n        timeoutInterval: 20000,\n      },\n      useIframe: false,\n      runInParent: true,\n    },\n\n    coverageIstanbulReporter: {\n      dir: 'build/logs/karma-coverage/story-editor',\n      reports: ['text-summary', 'lcovonly'],\n    },\n\n    failedTestsReporter: {\n      outputFile: 'build/karma-story-editor-failed-tests.txt',\n    },\n\n    // Continuous Integration mode\n    // if true, Karma captures browsers, runs the tests and exits\n    singleRun: false,\n\n    // Concurrency level\n    // how many browsers should be started simultaneously\n    concurrency: Infinity,\n\n    // Sharding configuration for CI.\n    // We trick karma-parallel into using only 1 browser (parallelOptions.executors === 1)\n    // while using a custom strategy that splits up the tests into multiple shards (config.executors > 1).\n    // This allows us to run only a subset of the tests like so:\n    // npm run test:karma:story-editor -- --headless --shard=1/3 # Run the first of 3 desired shards.\n    parallelOptions: {\n      shardStrategy: config.shard ? 'custom' : 'round-robin',\n      // If we're using custom sharding, just spin up 1 browser,\n      // but do the splitting in the custom strategy below.\n      executors: config.shard ? 1 : parallelExecutors,\n      // Re-implements a round-robin strategy, but with a custom shardIndex.\n      // Need to use the Function constructor here so we have access to the outer shardIndex and totalShards vars,\n      // because karma-parallel serializes this function.\n      // eslint-disable-next-line no-new-func -- karma-test\n      customShardStrategy: new Function(\n        'parallelOptions',\n        `\n        window.parallelDescribeCount = window.parallelDescribeCount || 0;\n        window.parallelDescribeCount++;\n        const shouldRunThisTest = (window.parallelDescribeCount % ${totalShards} === ${shardIndex});\n        return shouldRunThisTest;\n      `\n      ),\n    },\n\n    // Allow not having any tests\n    failOnEmptyTestSuite: false,\n\n    // Prevent duplicate logging to console\n    browserConsoleLogOptions: {\n      terminal: false,\n    },\n\n    // When a browser crashes,try to relaunch more than just 2 times (which is the default)\n    retryLimit: 5,\n\n    // Bump browserNoActivityTimeout to 100s to prevent Github Actions timeout\n    browserNoActivityTimeout: 100000,\n\n    // Wait a bit longer for browser to reconnect.\n    browserDisconnectTimeout: 10000,\n\n    // Custom context file.\n    customClientContextFile:\n      'packages/karma-fixture/src/client_with_context.html',\n  });\n};\n\n/**\n * Returns a viewport object for  a given flag.\n *\n * The following viewports are supported:\n * - default: no special viewport is used.\n * - 1600:1000: empirical laptop size. Also used for screenshots.\n *\n * A custom W:H viewport is intentionally not supported to reduce number of\n * test variations.\n *\n * Todo: Support the viewport sizes from Figma:\n * - 1920:1080: the canonical desktop size.\n * - 1024:680: the canonical iPad size.\n *\n * @param {string} flag Viewport flag.\n * @return {{width: number, height: number}|null} Viewport.\n */\nfunction getViewport(flag) {\n  if (!flag) {\n    // @todo: switch to 1600:1000 default once Percy is fully launched.\n    return null;\n  }\n  if (flag === '1600:1000') {\n    return { width: 1600, height: 1000 };\n  }\n  throw new Error(`Unsupported viewport: \"${flag}\"`);\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"web-stories-wp\",\n  \"description\": \"Visual storytelling for WordPress.\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"amp\",\n    \"stories\",\n    \"storytelling\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/googleforcreators/web-stories-wp/\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 24\",\n    \"npm\": \">= 10\"\n  },\n  \"type\": \"module\",\n  \"workspaces\": {\n    \"packages\": [\n      \"packages/*\"\n    ]\n  },\n  \"devDependencies\": {\n    \"@ampproject/toolbox-optimizer\": \"^2.10.1\",\n    \"@babel/core\": \"^7.29.0\",\n    \"@babel/eslint-parser\": \"^7.28.6\",\n    \"@babel/eslint-plugin\": \"^7.27.1\",\n    \"@babel/preset-env\": \"^7.29.2\",\n    \"@babel/preset-react\": \"^7.28.5\",\n    \"@babel/preset-typescript\": \"^7.28.5\",\n    \"@eslint-community/eslint-plugin-eslint-comments\": \"^4.5.0\",\n    \"@googleforcreators/dashboard\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/fonts\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/migration\": \"*\",\n    \"@googleforcreators/moveable\": \"*\",\n    \"@googleforcreators/story-editor\": \"*\",\n    \"@jest/types\": \"^30.2.0\",\n    \"@jsdevtools/coverage-istanbul-loader\": \"^3.0.5\",\n    \"@manypkg/get-packages\": \"^2.2.2\",\n    \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.6.1\",\n    \"@prettier/plugin-xml\": \"^3.4.2\",\n    \"@rollup/plugin-babel\": \"^6.0.4\",\n    \"@rollup/plugin-commonjs\": \"^29.0.0\",\n    \"@rollup/plugin-dynamic-import-vars\": \"^2.1.5\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.3\",\n    \"@rollup/plugin-terser\": \"^1.0.0\",\n    \"@rollup/plugin-url\": \"^8.0.2\",\n    \"@storybook/addon-a11y\": \"^9.1.10\",\n    \"@storybook/addon-docs\": \"^9.1.10\",\n    \"@storybook/addon-links\": \"^9.1.10\",\n    \"@storybook/addon-webpack5-compiler-babel\": \"^3.0.6\",\n    \"@storybook/csf\": \"^0.1.13\",\n    \"@storybook/react-webpack5\": \"^9.1.10\",\n    \"@stylelint/postcss-css-in-js\": \"^0.38.0\",\n    \"@svgr/rollup\": \"^8.0.1\",\n    \"@svgr/webpack\": \"^8.0.1\",\n    \"@testing-library/dom\": \"^10.4.1\",\n    \"@testing-library/jest-dom\": \"^6.9.1\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"@types/jest\": \"^29.5.14\",\n    \"@types/jsdom\": \"^27.0.0\",\n    \"@types/node\": \"^24.7.1\",\n    \"@types/styled-components\": \"^5.1.26\",\n    \"@types/uuid\": \"^10.0.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^8.58.0\",\n    \"@typescript-eslint/parser\": \"^8.58.0\",\n    \"@web-stories-wp/e2e-tests\": \"*\",\n    \"@web-stories-wp/eslint-import-resolver\": \"*\",\n    \"@web-stories-wp/jest-amp\": \"*\",\n    \"@web-stories-wp/jest-resolver\": \"*\",\n    \"@web-stories-wp/karma-failed-tests-reporter\": \"*\",\n    \"@web-stories-wp/karma-puppeteer-client\": \"*\",\n    \"@web-stories-wp/karma-puppeteer-launcher\": \"*\",\n    \"@wordpress/babel-plugin-import-jsx-pragma\": \"^5.43.0\",\n    \"@wordpress/dependency-extraction-webpack-plugin\": \"^6.43.0\",\n    \"@wordpress/eslint-plugin\": \"^24.5.0\",\n    \"ajv-cli\": \"^5.0.0\",\n    \"ajv-formats\": \"^3.0.1\",\n    \"babel-jest\": \"^30.3.0\",\n    \"babel-loader\": \"^10.1.1\",\n    \"babel-plugin-react-compiler\": \"19.1.0-rc.3\",\n    \"babel-plugin-styled-components\": \"^2.1.4\",\n    \"babel-plugin-transform-react-remove-prop-types\": \"^0.4.24\",\n    \"browserslist\": \"^4.27.0\",\n    \"circular-dependency-plugin\": \"^5.2.2\",\n    \"core-js\": \"^3.46.0\",\n    \"cross-env\": \"^10.1.0\",\n    \"css-loader\": \"^7.1.2\",\n    \"css-minimizer-webpack-plugin\": \"^8.0.0\",\n    \"cssnano\": \"^7.1.2\",\n    \"eslint\": \"^8.57.1\",\n    \"eslint-config-prettier\": \"^10.1.8\",\n    \"eslint-plugin-header\": \"^3.1.0\",\n    \"eslint-plugin-import\": \"^2.32.0\",\n    \"eslint-plugin-jasmine\": \"^4.2.2\",\n    \"eslint-plugin-jest\": \"^29.0.1\",\n    \"eslint-plugin-jest-dom\": \"^5.5.0\",\n    \"eslint-plugin-jest-extended\": \"^3.0.1\",\n    \"eslint-plugin-jsdoc\": \"^61.0.1\",\n    \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n    \"eslint-plugin-markdown\": \"^5.1.0\",\n    \"eslint-plugin-n\": \"^17.23.1\",\n    \"eslint-plugin-oxlint\": \"^1.48.0\",\n    \"eslint-plugin-prettier\": \"^5.5.4\",\n    \"eslint-plugin-react\": \"^7.37.5\",\n    \"eslint-plugin-react-hooks\": \"^7.0.1\",\n    \"eslint-plugin-security\": \"^3.0.1\",\n    \"eslint-plugin-styled-components-a11y\": \"^2.2.1\",\n    \"eslint-plugin-testing-library\": \"^7.16.0\",\n    \"html-webpack-plugin\": \"^5.6.6\",\n    \"husky\": \"^9.1.7\",\n    \"jest\": \"^29.7.0\",\n    \"jest-axe\": \"^9.0.0\",\n    \"jest-canvas-mock\": \"^2.5.2\",\n    \"jest-environment-jsdom\": \"^30.3.0\",\n    \"jest-extended\": \"^6.0.0\",\n    \"jest-fetch-mock\": \"^3.0.3\",\n    \"jest-matcher-deep-close-to\": \"^3.0.2\",\n    \"jest-silent-reporter\": \"^0.6.0\",\n    \"jest-styled-components\": \"^7.2.0\",\n    \"karma\": \"^6.4.4\",\n    \"karma-chrome-launcher\": \"^3.2.0\",\n    \"karma-coverage-istanbul-reporter\": \"^3.0.3\",\n    \"karma-jasmine\": \"^5.1.0\",\n    \"karma-parallel\": \"^0.3.1\",\n    \"karma-sourcemap-loader\": \"^0.4.0\",\n    \"karma-webpack\": \"^5.0.1\",\n    \"lint-staged\": \"^16.2.3\",\n    \"markdownlint-cli\": \"^0.45.0\",\n    \"mini-css-extract-plugin\": \"^2.9.4\",\n    \"mockdate\": \"^3.0.5\",\n    \"npm-package-json-lint\": \"^9.0.0\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"oxlint\": \"^1.48.0\",\n    \"patch-package\": \"^8.0.1\",\n    \"postcss-jsx\": \"^0.36.4\",\n    \"postcss-styled-syntax\": \"^0.7.1\",\n    \"postcss-syntax\": \"^0.36.2\",\n    \"prettier\": \"^3.8.1\",\n    \"puppeteer\": \"^24.37.3\",\n    \"react-compiler-runtime\": \"19.1.0-rc.3\",\n    \"react-refresh\": \"^0.18.0\",\n    \"react-test-renderer\": \"^17.0.2\",\n    \"rollup\": \"^2.80.0\",\n    \"rollup-plugin-copy\": \"^3.5.0\",\n    \"rollup-plugin-delete\": \"^3.0.2\",\n    \"rollup-plugin-web-worker-loader\": \"^1.7.0\",\n    \"rtlcss-webpack-plugin\": \"^4.0.7\",\n    \"source-map-loader\": \"^5.0.0\",\n    \"storybook\": \"^9.1.20\",\n    \"styled-components\": \"^5.3.11\",\n    \"stylelint\": \"^16.25.0\",\n    \"stylelint-config-recommended\": \"^16.0.0\",\n    \"stylelint-prettier\": \"^5.0.3\",\n    \"stylis-plugin-rtl\": \"^1.0.0\",\n    \"terser-webpack-plugin\": \"^5.4.0\",\n    \"typescript\": \"^5.9.3\",\n    \"webpack\": \"^5.99.7\",\n    \"webpack-bundle-analyzer\": \"^5.3.0\",\n    \"webpack-cli\": \"^6.0.1\",\n    \"webpack-dev-server\": \"^5.2.3\",\n    \"webpackbar\": \"^7.0.0\",\n    \"worker-loader\": \"^3.0.8\"\n  },\n  \"overrides\": {\n    \"@axe-core/puppeteer\": {\n      \"puppeteer\": \"$puppeteer\"\n    },\n    \"@typescript-eslint/parser\": \"$@typescript-eslint/parser\",\n    \"@typescript-eslint/eslint-plugin\": \"$@typescript-eslint/eslint-plugin\",\n    \"braces\": \"3.0.3\",\n    \"date-fns\": \"^2.30.0\",\n    \"eslint-plugin-jsdoc\": \"$eslint-plugin-jsdoc\",\n    \"eslint-plugin-prettier\": \"$eslint-plugin-prettier\",\n    \"fast-json-patch\": \"3.1.1\",\n    \"terser\": \"5.37.0\",\n    \"ua-parser-js\": \"0.7.38\",\n    \"postcss\": \"8.5.1\",\n    \"webpack\": \"$webpack\",\n    \"storybook\": \"$storybook\"\n  },\n  \"scripts\": {\n    \"build\": \"npm-run-all build:*\",\n    \"prebuild:js\": \"rm -rf assets/css/* assets/js/*\",\n    \"build:js\": \"cross-env NODE_ENV=production webpack --config webpack.config.cjs\",\n    \"postbuild:js\": \"rm -rf assets/js/web-stories-list-styles* assets/js/web-stories-theme-style*\",\n    \"predev\": \"rm -rf assets/css/* assets/js/*\",\n    \"dev\": \"webpack --config webpack.config.cjs --watch\",\n    \"postdev\": \"rm -rf assets/js/web-stories-list-styles* assets/js/web-stories-theme-style*\",\n    \"preserve\": \"rm -rf assets/css/* assets/js/*\",\n    \"serve\": \"webpack serve --config webpack.config.cjs\",\n    \"postserve\": \"rm -rf assets/js/web-stories-list-styles* assets/js/web-stories-theme-style*\",\n    \"env:start\": \"bash ./bin/local-env/start.sh\",\n    \"env:stop\": \"bash ./bin/local-env/stop.sh\",\n    \"env:reset-site\": \"bash ./bin/local-env/install-wordpress.sh --reset-site\",\n    \"format\": \"npm-run-all --parallel format:*\",\n    \"format:css\": \"npm run lint:css:css:fix\",\n    \"format:css-in-js\": \"npm run lint:css:js:fix\",\n    \"format:js\": \"npm run lint:js:fix\",\n    \"format:md\": \"prettier --write '**/*.md'\",\n    \"format:php\": \"npm run lint:php:fix\",\n    \"format:xml\": \"prettier --write '**/*.{xml,xml.dist}'\",\n    \"format:yml\": \"prettier --write '**/*.yml'\",\n    \"lint\": \"npm-run-all --parallel lint:*\",\n    \"lint:css\": \"npm-run-all --parallel --continue-on-error lint:css:*\",\n    \"lint:css:js\": \"stylelint \\\"**/*.js\\\"\",\n    \"lint:css:js:fix\": \"stylelint \\\"**/*.js\\\" --fix\",\n    \"lint:css:css\": \"stylelint \\\"**/*.css\\\"\",\n    \"lint:css:css:fix\": \"stylelint \\\"**/*.css\\\" --fix\",\n    \"lint:js\": \"oxlint && eslint .\",\n    \"lint:js:fix\": \"oxlint --fix && eslint --fix .\",\n    \"lint:js:report\": \"oxlint -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint --output-file build/lint-js-report.json --format json .\",\n    \"lint:package-json\": \"npmPkgJsonLint .\",\n    \"lint:php\": \"composer phpcs\",\n    \"lint:php:fix\": \"composer phpcbf\",\n    \"lint:phpstan\": \"composer phpstan\",\n    \"lint:phpmd\": \"composer phpmd\",\n    \"lint:md\": \"markdownlint .\",\n    \"postinstall\": \"patch-package\",\n    \"storybook\": \"storybook dev --quiet\",\n    \"storybook:build\": \"storybook build -c .storybook -o build/storybook --quiet\",\n    \"test\": \"npm-run-all --parallel test:*\",\n    \"pretest:js\": \"if [ -z $AMP_VALIDATOR_FILE ]; then curl --output-dir $TMPDIR -O -f https://cdn.ampproject.org/v0/validator_wasm.js; fi\",\n    \"test:js\": \"jest --config=tests/js/jest.config.js\",\n    \"test:js:coverage\": \"npm run test:js -- --collectCoverage; open build/logs/lcov-report/index.html\",\n    \"test:js:debug\": \"node --inspect-brk node_modules/.bin/jest --config=tests/js/jest.config.js\",\n    \"test:js:help\": \"npm run test:js -- --help\",\n    \"test:js:watch\": \"npm run test:js -- --watch\",\n    \"test:karma\": \"npm-run-all --parallel test:karma:*\",\n    \"pretest:karma:story-editor\": \"rm -rf build/karma-story-editor-failed-tests.txt\",\n    \"test:karma:story-editor\": \"karma start karma-story-editor.config.cjs --single-run\",\n    \"test:karma:story-editor:retry-failed\": \"karma start karma-story-editor.config.cjs --single-run --retry-failed\",\n    \"test:karma:story-editor:watch\": \"karma start karma-story-editor.config.cjs\",\n    \"pretest:karma:dashboard\": \"rm -rf build/karma-dashboard-failed-tests.txt\",\n    \"test:karma:dashboard\": \"karma start karma-dashboard.config.cjs --single-run\",\n    \"test:karma:dashboard:retry-failed\": \"karma start karma-dashboard.config.cjs --single-run --retry-failed\",\n    \"test:karma:dashboard:watch\": \"karma start karma-dashboard.config.cjs --debug\",\n    \"test:php\": \"npm-run-all test:php:*\",\n    \"test:php:unit\": \"vendor/bin/phpunit\",\n    \"test:php:integration\": \"npm-run-all test:php:integration:*\",\n    \"test:php:integration:single\": \"vendor/bin/phpunit -c phpunit-integration.xml.dist\",\n    \"test:php:integration:multisite\": \"vendor/bin/phpunit -c phpunit-integration-multisite.xml.dist\",\n    \"test:php:unit:help\": \"npm run test:php -- --help\",\n    \"pretest:e2e\": \"if [ -z $AMP_VALIDATOR_FILE ]; then curl --output-dir $TMPDIR -O -f https://cdn.ampproject.org/v0/validator_wasm.js; fi\",\n    \"test:e2e\": \"cross-env JEST_PUPPETEER_CONFIG=jest-puppeteer.config.cjs jest --runInBand --config=packages/e2e-tests/src/jest.config.js\",\n    \"test:e2e:help\": \"npm run test:e2e -- --help\",\n    \"test:e2e:percy\": \"percy exec --quiet --parallel --config=percy.config.yml -- npm run test:e2e\",\n    \"test:e2e:watch\": \"npm run test:e2e -- --watch\",\n    \"test:e2e:interactive\": \"cross-env PUPPETEER_HEADLESS=false PUPPETEER_SLOWMO=80 npm run test:e2e\",\n    \"test:e2e:debug\": \"cross-env PUPPETEER_HEADLESS=false PUPPETEER_DEVTOOLS=true JEST_PUPPETEER_CONFIG=jest-puppeteer.config.cjs node --inspect-brk node_modules/.bin/jest --runInBand --config=packages/e2e-tests/src/jest.config.js\",\n    \"test:e2e:firefox\": \"cross-env PUPPETEER_PRODUCT=firefox npm run test:e2e\",\n    \"test:e2e:firefox:interactive\": \"cross-env PUPPETEER_PRODUCT=firefox npm run test:e2e:interactive\",\n    \"test:e2e:firefox:debug\": \"cross-env PUPPETEER_PRODUCT=firefox PUPPETEER_HEADLESS=false PUPPETEER_DEVTOOLS=true node --inspect-brk node_modules/.bin/jest --runInBand --config=packages/e2e-tests/src/jest.config.js\",\n    \"test:schema\": \"npm-run-all --parallel test:schema:*\",\n    \"test:schema:templates\": \"ls -1 packages/templates/src/raw/*/template.json | xargs -I% npx ajv validate -s bin/schemas/story.json -d % -c ajv-formats\",\n    \"test:schema:text-sets\": \"ls -1 packages/text-sets/src/raw/*.json | xargs -I% npx ajv validate -s bin/schemas/story.json -d % -c ajv-formats\",\n    \"test:schema:ftue-story\": \"npx ajv validate -s bin/schemas/story.json -d includes/data/stories/demo.json -c ajv-formats\",\n    \"percy\": \"percy snapshot --config=percy.config.yml .test_artifacts/karma_snapshots/\",\n    \"local-registry:start\": \"bash ./bin/setup-local-npm-registry.sh\",\n    \"local-registry:stop\": \"bash ./bin/stop-local-npm-registry.sh\",\n    \"workflow:assets-version\": \"commander assets-version\",\n    \"workflow:version\": \"commander version\",\n    \"workflow:build-plugin\": \"commander build-plugin\",\n    \"workflow:bundle-packages\": \"npm-run-all --parallel workflow:bundle-packages:*\",\n    \"workflow:bundle-packages:code\": \"rollup -c\",\n    \"workflow:bundle-packages:types\": \"tsc --build\",\n    \"workflow:fonts\": \"npm run update-fonts --workspace packages/fonts\",\n    \"postworkflow:fonts\": \"npx prettier --write packages/fonts/src/fonts.json; cp packages/fonts/src/fonts.json includes/data/fonts/fonts.json\",\n    \"workflow:render-text-sets\": \"npm run render-text-sets --workspace packages/text-sets\",\n    \"workflow:render-template-posters\": \"npm run render-template-posters --workspace=packages/templates\",\n    \"preworkflow:migrate\": \"[ -f packages/migration/scripts/module.js ] || npx rollup --config packages/migration/rollup.config.js\",\n    \"workflow:migrate\": \"npm-run-all --parallel workflow:migrate:*\",\n    \"workflow:migrate:text-sets\": \"npm run migration --workspace packages/migration packages/text-sets/src/raw\",\n    \"postworkflow:migrate:text-sets\": \"npx prettier --write packages/text-sets/src/raw\",\n    \"workflow:migrate:templates\": \"npm run migration --workspace packages/migration packages/templates/src/raw\",\n    \"postworkflow:migrate:templates\": \"npx prettier --write packages/templates/src/raw\",\n    \"workflow:migrate:ftue-story\": \"npm run migration --workspace packages/migration includes/data/stories\",\n    \"postworkflow:migrate:ftue-story\": \"npx prettier --write includes/data/stories\",\n    \"workflow:normalize-path\": \"commander normalize-path\"\n  },\n  \"lint-staged\": {\n    \"*.(cjs|js|ts|tsx)\": [\n      \"eslint --fix\"\n    ],\n    \"*.(js|tsx)\": [\n      \"stylelint --fix --allow-empty-input\"\n    ],\n    \"*.json\": [\n      \"prettier --write\"\n    ],\n    \"*.css\": \"stylelint --fix --allow-empty-input\",\n    \"*.md\": [\n      \"eslint --fix\",\n      \"markdownlint -f\"\n    ],\n    \"*.php\": \"npm run lint:php:fix\",\n    \"*.(xml|xml.dist)\": \"prettier --write\",\n    \"*.yml\": \"prettier --write\"\n  },\n  \"changelog\": {\n    \"labels\": {\n      \"Type: Enhancement\": \"🚀 Features\",\n      \"Type: Bug\": \"🐛 Bug Fixes\",\n      \"Type: Infrastructure\": \"🧰 Maintenance\",\n      \"Type: Documentation\": \":memo: Documentation\"\n    },\n    \"ignoreCommitters\": [\n      \"dependabot\",\n      \"github-actions\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/activation-notice/README.md",
    "content": "# Activation Notice\n\nWordPress plugin activation notice.\n"
  },
  {
    "path": "packages/activation-notice/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/activation-notice\",\n  \"description\": \"Web Stories for WordPress plugin activation notice\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/activation-notice/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/activation-notice\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.tsx\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"dependencies\": {\n    \"@emotion/is-prop-valid\": \"^1.4.0\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@wordpress/element\": \"^6.32.0\",\n    \"@wordpress/i18n\": \"^6.16.0\",\n    \"flagged\": \"^2.0.10\",\n    \"polished\": \"^4.3.1\",\n    \"styled-components\": \"^6.0.7\",\n    \"stylis-plugin-rtl\": \"^2.1.1\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^16.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/dismiss.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { useEffect } from '@wordpress/element';\n\n/**\n * Renders a Dismiss button as required/used by WordPress.\n *\n * Does not actually *render* the button itself, but emits an event so that\n * WordPress detects the notice and registers a click handler.\n *\n * @return Rendered component.\n */\nfunction Dismiss() {\n  useEffect(() => {\n    document.dispatchEvent(new Event('wp-updates-notice-added'));\n  }, []);\n\n  return null;\n}\n\nexport default Dismiss;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/image.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\ninterface ImgProps {\n  $rotationAngle: string;\n}\n\ninterface ImageProps {\n  name: string;\n  name2x: string;\n  width: number;\n  height: number;\n}\n\nconst Img = styled.img<ImgProps>`\n  transform: rotate(${(props) => props.$rotationAngle});\n  margin-top: 60px;\n`;\n\nfunction Image({ name, name2x, ...props }: ImageProps) {\n  const { cdnURL, isRTL } = useConfig();\n  return (\n    <Img\n      src={`${cdnURL}images/plugin-activation/${name}`}\n      srcSet={`${cdnURL}images/plugin-activation/${name}, ${cdnURL}images/plugin-activation/${name2x} 2x`}\n      alt=\"\"\n      $rotationAngle={isRTL ? '-30deg' : '30deg'}\n      {...props}\n    />\n  );\n}\n\nexport default Image;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/link.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\nconst Link = styled.a`\n  font-family: ${({ theme }) => theme.fonts.body.family};\n  font-size: ${({ theme }) => theme.fonts.body.size};\n  line-height: ${({ theme }) => theme.fonts.body.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.body.fontWeight};\n  color: ${({ theme }) => theme.colors.link.fg};\n  text-decoration: none;\n  cursor: pointer;\n  display: block;\n  &:focus,\n  &:hover {\n    color: ${({ theme }) => theme.colors.link.hover.fg};\n  }\n`;\n\nexport default Link;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/messageContent.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\n\n/**\n * Internal dependencies\n */\nimport SuccessMessage from './successMessage';\nimport Dismiss from './dismiss';\nimport Step1 from './step1';\nimport Step2 from './step2';\nimport Step3 from './step3';\n\nconst Wrapper = styled.div`\n  font-family: ${({ theme }) => theme.fonts.body.family};\n  font-size: ${({ theme }) => theme.fonts.body.size};\n  line-height: ${({ theme }) => theme.fonts.body.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.body.fontWeight};\n  color: ${({ theme }) => theme.colors.primary};\n\n  background: ${({ theme }) => `linear-gradient(\n      115.54deg,\n      ${rgba(theme.colors.bg.start, 0.2)} 9.27%,\n      ${rgba(theme.colors.bg.end, 0.2)} 47.82%,\n      ${rgba(theme.colors.bg.end, 0)} 66.64%\n    ),\n    linear-gradient(\n      158.59deg,\n      ${rgba(theme.colors.bg.start, 0.3)} 13.24%,\n      ${rgba(theme.colors.bg.end, 0.3)} 86.01%\n    ),\n    linear-gradient(\n      115.54deg,\n      ${rgba(theme.colors.bg.start, 0.2)} 9.27%,\n      ${rgba(theme.colors.bg.end, 0.2)} 47.82%,\n      ${rgba(theme.colors.bg.end, 0)} 66.64%\n    ),\n    linear-gradient(70.23deg, #010218 -28.03%, #1b0418 95.56%)`};\n\n  box-sizing: border-box;\n  display: flex;\n  overflow: hidden;\n  padding: 0 30px 0 45px;\n  justify-content: center;\n\n  @media ${({ theme }) => theme.breakpoint.tabletSmall} {\n    max-height: 245px;\n  }\n\n  @media ${({ theme }) => theme.breakpoint.tabletLarge} {\n    justify-content: space-around;\n  }\n`;\n\nfunction MessageContent() {\n  return (\n    <Wrapper>\n      <Dismiss />\n      <SuccessMessage />\n      <Step1 />\n      <Step2 />\n      <Step3 />\n    </Wrapper>\n  );\n}\n\nexport default MessageContent;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/number.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\nconst Number = styled.span`\n  font-family: ${({ theme }) => theme.fonts.stepNumber.family};\n  font-size: ${({ theme }) => theme.fonts.stepNumber.size};\n  line-height: ${({ theme }) => theme.fonts.stepNumber.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.stepNumber.fontWeight};\n  color: ${({ theme }) => theme.colors.tertiary};\n`;\n\nexport default Number;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/paragraph.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\ninterface ParagraphProps {\n  $secondary?: boolean;\n}\n\nconst Paragraph = styled.p<ParagraphProps>`\n  font-family: ${({ theme }) => theme.fonts.body.family};\n  font-size: ${({ theme }) => theme.fonts.body.size};\n  line-height: ${({ theme }) => theme.fonts.body.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.body.fontWeight};\n  color: ${({ theme, $secondary }) =>\n    $secondary ? theme.colors.secondary : theme.colors.primary};\n  margin: 0 !important;\n`;\n\nexport default Paragraph;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/step1.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { trackClick } from '@googleforcreators/tracking';\nimport type { MouseEventHandler, MouseEvent } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { createInterpolateElement, useCallback } from '@wordpress/element';\nimport { __, _x } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\nimport Paragraph from './paragraph';\nimport Link from './link';\nimport Number from './number';\nimport Image from './image';\n\nconst Wrapper = styled.div`\n  display: none;\n  min-width: 300px;\n  justify-content: center;\n\n  @media ${({ theme }) => theme.breakpoint.tabletSmall} {\n    display: flex;\n  }\n`;\n\nconst ParagraphWrapper = styled.div`\n  align-self: flex-start;\n  margin: 20px 0 0 70px;\n  text-align: right;\n  min-width: 100px;\n\n  @media ${({ theme }) => theme.breakpoint.desktop} {\n    margin-left: 30px;\n  }\n`;\n\nfunction Step1() {\n  const { demoStoryURL } = useConfig();\n\n  const onClick: MouseEventHandler<HTMLAnchorElement> = useCallback(\n    (evt: MouseEvent<HTMLAnchorElement>) => {\n      void trackClick(evt, 'open_demo_story');\n    },\n    []\n  );\n\n  // createInterpolateElement doesn't support br tags.\n  const translatedString = createInterpolateElement(\n    __('Read the <a>Get Started story</a>', 'web-stories'),\n    {\n      a: <Link href={demoStoryURL} onClick={onClick} rel=\"noreferrer\" />,\n    }\n  );\n\n  return (\n    <Wrapper>\n      <Link href={demoStoryURL} onClick={onClick} rel=\"noreferrer\">\n        <Image name=\"tips.png\" name2x=\"tips-2x.png\" width={150} height={245} />\n      </Link>\n      <ParagraphWrapper>\n        <Number>\n          {\n            /* translators: Number of the step displayed in plugin activation message. */\n            _x('1', 'Step number', 'web-stories')\n          }\n        </Number>\n        <Paragraph $secondary>{translatedString}</Paragraph>\n      </ParagraphWrapper>\n    </Wrapper>\n  );\n}\n\nexport default Step1;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/step2.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { trackClick } from '@googleforcreators/tracking';\nimport type { MouseEventHandler, MouseEvent } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { __, _x } from '@wordpress/i18n';\nimport { createInterpolateElement, useCallback } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\nimport Paragraph from './paragraph';\nimport Link from './link';\nimport Number from './number';\nimport Image from './image';\n\nconst Wrapper = styled.div`\n  display: none;\n  margin-left: 20px;\n  justify-content: center;\n\n  @media ${({ theme }) => theme.breakpoint.tabletLarge} {\n    display: flex;\n  }\n`;\n\nconst ParagraphWrapper = styled.div`\n  align-self: flex-start;\n  margin: 20px 0 0 -50px;\n  min-width: 100px;\n`;\n\nfunction Step2() {\n  const { dashboardURL } = useConfig();\n\n  const onClick: MouseEventHandler<HTMLAnchorElement> = useCallback(\n    (evt: MouseEvent<HTMLAnchorElement>) => {\n      void trackClick(evt, 'open_dashboard');\n    },\n    []\n  );\n\n  // createInterpolateElement doesn't support br tags.\n  const translatedString = createInterpolateElement(\n    __('Head to the <a>Dashboard</a>', 'web-stories'),\n    {\n      a: <Link href={dashboardURL} onClick={onClick} />,\n    }\n  );\n\n  return (\n    <Wrapper>\n      <Link href={dashboardURL} onClick={onClick}>\n        <Image\n          name=\"dashboard.png\"\n          name2x=\"dashboard-2x.png\"\n          width={420}\n          height={246}\n        />\n      </Link>\n      <ParagraphWrapper>\n        <Number>\n          {\n            /* translators: Number of the step displayed in plugin activation message. */\n            _x('2', 'Step number', 'web-stories')\n          }\n        </Number>\n        <Paragraph $secondary>{translatedString}</Paragraph>\n      </ParagraphWrapper>\n    </Wrapper>\n  );\n}\n\nexport default Step2;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/step3.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { trackClick } from '@googleforcreators/tracking';\n\n/**\n * WordPress dependencies\n */\nimport { __, _x } from '@wordpress/i18n';\nimport { useCallback, createInterpolateElement } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport type { MouseEventHandler, MouseEvent } from 'react';\nimport { useConfig } from '../config';\n\nimport Paragraph from './paragraph';\nimport Link from './link';\nimport Number from './number';\nimport Image from './image';\n\nconst Wrapper = styled.div`\n  display: none;\n  margin-left: 30px;\n  justify-content: center;\n\n  @media ${({ theme }) => theme.breakpoint.desktop} {\n    display: flex;\n  }\n`;\n\nconst ParagraphWrapper = styled.div`\n  align-self: flex-start;\n  margin: 20px 0 0 -50px;\n`;\n\nfunction Step3() {\n  const { newStoryURL } = useConfig();\n\n  const onClick: MouseEventHandler<HTMLAnchorElement> = useCallback(\n    (event: MouseEvent<HTMLAnchorElement>) => {\n      void trackClick(event, 'open_story_editor');\n    },\n    []\n  );\n\n  // createInterpolateElement doesn't support br tags.\n  const translatedString = createInterpolateElement(\n    __('Jump into the <a>Editor</a>', 'web-stories'),\n    {\n      a: <Link href={newStoryURL} onClick={onClick} />,\n    }\n  );\n\n  return (\n    <Wrapper>\n      <Link href={newStoryURL} onClick={onClick}>\n        <Image\n          name=\"editor.png\"\n          name2x=\"editor-2x.png\"\n          width={430}\n          height={251}\n        />\n      </Link>\n      <ParagraphWrapper>\n        <Number>\n          {\n            /* translators: Number of the step displayed in plugin activation message. */\n            _x('3', 'Step number', 'web-stories')\n          }\n        </Number>\n        <Paragraph>{translatedString}</Paragraph>\n      </ParagraphWrapper>\n    </Wrapper>\n  );\n}\n\nexport default Step3;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/successMessage.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { trackClick } from '@googleforcreators/tracking';\nimport type { MouseEventHandler, MouseEvent } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useCallback } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\nimport Paragraph from './paragraph';\nimport SecondaryLink from './link';\n\nconst Message = styled.div`\n  min-width: 260px;\n  padding: 30px 0 30px;\n\n  ${SecondaryLink} {\n    @media ${({ theme }) => theme.breakpoint.tabletSmall} {\n      display: none;\n    }\n  }\n`;\n\nconst Title = styled.h2`\n  font-family: ${({ theme }) => theme.fonts.title.family};\n  font-size: ${({ theme }) => theme.fonts.title.size};\n  line-height: ${({ theme }) => theme.fonts.title.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.title.fontWeight};\n  color: ${({ theme }) => theme.colors.primary};\n  margin: 0 0 10px;\n`;\n\nconst PrimaryLink = styled.a`\n  font-family: ${({ theme }) => theme.fonts.button.family};\n  font-size: ${({ theme }) => theme.fonts.button.size};\n  line-height: ${({ theme }) => theme.fonts.button.lineHeight};\n  font-weight: ${({ theme }) => theme.fonts.button.fontWeight};\n  background: ${({ theme }) => theme.colors.action.bg};\n  color: ${({ theme }) => theme.colors.action.fg};\n  padding: 5px 8px;\n  cursor: pointer;\n  text-decoration: none;\n  border-radius: 2px;\n\n  &:focus,\n  &:hover {\n    background: ${({ theme }) => theme.colors.action.hover.bg};\n    color: ${({ theme }) => theme.colors.action.fg};\n  }\n`;\n\nconst ParagraphWithSpace = styled(Paragraph)`\n  margin-bottom: 15px !important;\n`;\n\nfunction SuccessMessage() {\n  const { dashboardURL, demoStoryURL } = useConfig();\n\n  const onClickPrimary: MouseEventHandler<HTMLAnchorElement> = useCallback(\n    (evt: MouseEvent<HTMLAnchorElement>) => {\n      void trackClick(evt, 'open_dashboard');\n    },\n    []\n  );\n  const onClickSecondary: MouseEventHandler<HTMLAnchorElement> = useCallback(\n    (evt: MouseEvent<HTMLAnchorElement>) => {\n      void trackClick(evt, 'open_demo_story');\n    },\n    []\n  );\n\n  return (\n    <Message>\n      <Title>\n        {__(\"You're all set!\", 'web-stories')}\n        <br />\n        {__('Tell some stories.', 'web-stories')}\n      </Title>\n      <ParagraphWithSpace $secondary>\n        {__('Welcome to Web Stories for WordPress.', 'web-stories')}\n      </ParagraphWithSpace>\n      <ParagraphWithSpace>\n        <PrimaryLink href={dashboardURL} onClick={onClickPrimary}>\n          {__('Go to Stories Dashboard', 'web-stories')}\n        </PrimaryLink>\n      </ParagraphWithSpace>\n      <Paragraph>\n        <SecondaryLink href={demoStoryURL} onClick={onClickSecondary}>\n          {__('Read the Get Started story', 'web-stories')}\n        </SecondaryLink>\n      </Paragraph>\n    </Message>\n  );\n}\n\nexport default SuccessMessage;\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/test/dismiss.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { renderWithTheme } from '../../../testUtils';\n\nimport Dismiss from '../dismiss';\n\ndescribe('Dismiss', () => {\n  it('should render nothing', () => {\n    const { container } = renderWithTheme(<Dismiss />);\n    expect(container).toBeEmptyDOMElement();\n  });\n});\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/test/step1.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithTheme } from '../../../testUtils';\n\nimport Step1 from '../step1';\nimport { ConfigProvider } from '../../config';\n\nfunction render() {\n  const config = {\n    demoStoryURL: 'bar',\n  };\n\n  return renderWithTheme(\n    <ConfigProvider config={config}>\n      <Step1 />\n    </ConfigProvider>\n  );\n}\n\ndescribe('Step 1', () => {\n  it('should render', () => {\n    render();\n\n    expect(screen.getByText(/Get Started story/i)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/test/step2.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithTheme } from '../../../testUtils';\n\nimport Step2 from '../step2';\nimport { ConfigProvider } from '../../config';\n\nfunction render() {\n  const config = {\n    dashboardURL: 'foo',\n  };\n\n  return renderWithTheme(\n    <ConfigProvider config={config}>\n      <Step2 />\n    </ConfigProvider>\n  );\n}\n\ndescribe('Step 2', () => {\n  it('should render', () => {\n    render();\n\n    expect(screen.getByText(/Dashboard/i)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/test/step3.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithTheme } from '../../../testUtils';\n\nimport Step3 from '../step3';\nimport { ConfigProvider } from '../../config';\n\nfunction render() {\n  const config = {\n    newStoryURL: 'foo',\n    demoStoryURL: 'bar',\n  };\n\n  return renderWithTheme(\n    <ConfigProvider config={config}>\n      <Step3 />\n    </ConfigProvider>\n  );\n}\n\ndescribe('Step 3', () => {\n  it('should render', () => {\n    render();\n\n    expect(screen.getByText(/Jump into/i)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/activation-notice/src/app/components/test/successMessage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithTheme } from '../../../testUtils';\n\nimport SuccessMessage from '../successMessage';\nimport { ConfigProvider } from '../../config';\n\nfunction render() {\n  const config = {\n    dashboardURL: 'foo',\n    demoStoryURL: 'bar',\n  };\n\n  return renderWithTheme(\n    <ConfigProvider config={config}>\n      <SuccessMessage />\n    </ConfigProvider>\n  );\n}\n\ndescribe('SuccessMessage', () => {\n  it('should render', () => {\n    render();\n\n    expect(screen.getByText(/Tell some stories/i)).toBeInTheDocument();\n    expect(screen.getByText(/Go to Stories Dashboard/i)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/activation-notice/src/app/config/configProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context, { type ContextState } from './context';\n\ninterface ConfigProviderProps {\n  config: ContextState;\n  children: ReactNode;\n}\n\nfunction ConfigProvider({ config, children }: ConfigProviderProps) {\n  return <Context.Provider value={config}>{children}</Context.Provider>;\n}\n\nexport default ConfigProvider;\n"
  },
  {
    "path": "packages/activation-notice/src/app/config/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { createContext } from '@wordpress/element';\n\nconst INITIAL_STATE = {};\n\nexport interface ContextState {\n  isRTL: boolean;\n  cdnURL: string;\n  demoStoryURL: string;\n  newStoryURL: string;\n  dashboardURL: string;\n}\n\nexport default createContext(INITIAL_STATE);\n"
  },
  {
    "path": "packages/activation-notice/src/app/config/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ConfigProvider } from './configProvider';\nexport { default as useConfig } from './useConfig';\n"
  },
  {
    "path": "packages/activation-notice/src/app/config/useConfig.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport Context, { type ContextState } from './context';\n\nfunction useConfig(): ContextState {\n  return useContext(Context) as ContextState;\n}\n\nexport default useConfig;\n"
  },
  {
    "path": "packages/activation-notice/src/app/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport isPropValid from '@emotion/is-prop-valid';\nimport { StyleSheetManager, ThemeProvider } from 'styled-components';\nimport stylisRTLPlugin from 'stylis-plugin-rtl';\nObject.defineProperty(stylisRTLPlugin, 'name', { value: 'stylisRTLPlugin' });\n\n/**\n * Internal dependencies\n */\nimport { theme, GlobalStyle } from '../theme';\nimport MessageContent from './components/messageContent';\nimport { ConfigProvider } from './config';\nimport type { ContextState } from './config/context';\n\ninterface AppProps {\n  config: ContextState;\n}\n\nfunction App({ config }: AppProps) {\n  const { isRTL } = config;\n\n  return (\n    <StyleSheetManager\n      stylisPlugins={isRTL ? [stylisRTLPlugin] : []}\n      shouldForwardProp={isPropValid}\n    >\n      <ThemeProvider theme={theme}>\n        <ConfigProvider config={config}>\n          <GlobalStyle />\n          <MessageContent />\n        </ConfigProvider>\n      </ThemeProvider>\n    </StyleSheetManager>\n  );\n}\n\nexport default App;\n"
  },
  {
    "path": "packages/activation-notice/src/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FlagsProvider } from 'flagged';\nimport { initializeTracking } from '@googleforcreators/tracking';\n\n/**\n * WordPress dependencies\n */\nimport { StrictMode, createRoot } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport App from './app';\nimport type { ContextState } from './app/config/context';\n\ninterface ActivationNoticeSettings {\n  publicPath: string;\n  id: string;\n  config: ContextState;\n  flags: Record<string, boolean>;\n}\n\ndeclare global {\n  let __webpack_public_path__: string;\n\n  interface Window {\n    webStoriesActivationSettings: ActivationNoticeSettings;\n  }\n}\n\n__webpack_public_path__ = window.webStoriesActivationSettings.publicPath;\n\n/**\n * Initializes the Web Stories dashboard screen.\n *\n * @param id       ID of the root element to render the screen in.\n * @param config   Story editor settings.\n * @param flags    The flags for the application.\n */\nconst initialize = (\n  id: string,\n  config: ContextState,\n  flags: Record<string, boolean>\n) => {\n  const appElement = document.getElementById(id);\n\n  if (!appElement) {\n    return;\n  }\n\n  void initializeTracking('Plugin Activation');\n\n  const root = createRoot(appElement);\n\n  root.render(\n    <FlagsProvider features={flags}>\n      <StrictMode>\n        <App config={config} />\n      </StrictMode>\n    </FlagsProvider>\n  );\n};\n\nconst initializeWithConfig = () => {\n  const { id, config, flags } = window.webStoriesActivationSettings;\n  initialize(id, config, flags);\n};\n\nif ('loading' === document.readyState) {\n  document.addEventListener('DOMContentLoaded', initializeWithConfig);\n} else {\n  initializeWithConfig();\n}\n"
  },
  {
    "path": "packages/activation-notice/src/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport App from '../app';\n\nexport default {\n  title: 'WordPress/Plugin Activation',\n  args: {\n    cdnURL: 'https://wp.stories.google/static/main/',\n    demoStoryURL: 'https://example:com',\n    dashboardURL: 'https://example:com',\n    isRTL: false,\n  },\n};\n\n// TODO (#10380): Support RTL using something like @pxblue/storybook-rtl-addon;\nexport const _default = {\n  render: function Render(args) {\n    return <App config={args} {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/activation-notice/src/testUtils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as renderWithTheme } from './renderWithTheme';\n"
  },
  {
    "path": "packages/activation-notice/src/testUtils/renderWithTheme.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { theme } from '../theme';\n\nconst WithThemeProvider = ({ children }) => {\n  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;\n};\n\nconst renderWithTheme = (ui, options) =>\n  render(ui, {\n    wrapper: WithThemeProvider,\n    ...options,\n  });\n\nexport default renderWithTheme;\n"
  },
  {
    "path": "packages/activation-notice/src/theme.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle, ThemeContext } from 'styled-components';\nimport type { DefaultTheme } from 'styled-components';\n\n/**\n * WordPress dependencies\n */\nimport { useContext } from '@wordpress/element';\n\nexport const GlobalStyle = createGlobalStyle`\n  #web-stories-plugin-activation-notice {\n    padding: 0;\n    border: none;\n  }\n`;\n\nexport function useTheme(): DefaultTheme {\n  return useContext(ThemeContext);\n}\n\nexport const theme: DefaultTheme = {\n  colors: {\n    bg: {\n      start: '#CBACFF',\n      end: '#79B3FF',\n    },\n    primary: 'rgba(255, 255, 255, 0.84)',\n    secondary: 'rgba(255, 255, 255, 0.64)',\n    tertiary: 'rgba(255, 255, 255, 0.54)',\n    link: {\n      fg: '#B99DEA',\n      hover: {\n        fg: 'rgba(255, 255, 255, 0.84)',\n      },\n    },\n    action: {\n      bg: '#619CE8',\n      fg: '#ffffff',\n      hover: {\n        bg: '#010218',\n      },\n    },\n  },\n  fonts: {\n    body: {\n      family: \"'Google Sans', sans-serif\",\n      size: '16px',\n      lineHeight: '24px',\n      fontWeight: 400,\n    },\n    title: {\n      family: \"'Google Sans', sans-serif\",\n      size: '32px',\n      lineHeight: '40px',\n      fontWeight: 400,\n    },\n    button: {\n      family: \"'Google Sans', sans-serif\",\n      size: '16px',\n      lineHeight: '32px',\n      fontWeight: 400,\n    },\n    stepNumber: {\n      family: \"'Google Sans', sans-serif\",\n      size: '80px',\n      lineHeight: '80px',\n      fontWeight: 900,\n    },\n  },\n  breakpoint: {\n    tabletSmall: 'screen and (min-width: 700px)',\n    tabletLarge: 'screen and (min-width: 1300px)',\n    desktop: 'screen and (min-width: 1800px)',\n  },\n};\n"
  },
  {
    "path": "packages/activation-notice/src/typings/styled-components.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport 'styled-components';\n\ninterface Font {\n  family: string;\n  size: string;\n  lineHeight: string;\n  fontWeight: number;\n}\n\ndeclare module 'styled-components' {\n  export interface DefaultTheme {\n    colors: {\n      bg: {\n        [key: string]: string;\n      };\n      primary: string;\n      secondary: string;\n      tertiary: string;\n      link: {\n        fg: string;\n        hover: {\n          [key: string]: string;\n        };\n      };\n      action: {\n        bg: string;\n        fg: string;\n        hover: {\n          [key: string]: string;\n        };\n      };\n    };\n    fonts: {\n      [key: string]: Font;\n    };\n    breakpoint: {\n      [key: string]: string;\n    };\n  }\n}\n"
  },
  {
    "path": "packages/activation-notice/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../tracking\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/animation/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/animation/README.md",
    "content": "# Animation\n\nLibrary for rendering animations in web stories.\n"
  },
  {
    "path": "packages/animation/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/animation\",\n  \"description\": \"Web Stories editor animation library.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"animations\",\n    \"web animations\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/animation/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/animation\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"flagged\": \"^2.0.10\",\n    \"prop-types\": \"^15.8.1\",\n    \"styled-components\": \"^5.3.11\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@types/styled-components\": \"^5.1.26\",\n    \"@types/web-animations-js\": \"^2.2.16\"\n  }\n}\n"
  },
  {
    "path": "packages/animation/src/components/AMPAnimations.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport useStoryAnimationContext from './useStoryAnimationContext';\n\nfunction AMPAnimations() {\n  const {\n    state: { providerId, animationTargets },\n    actions: { getAnimationParts },\n  } = useStoryAnimationContext();\n\n  return (\n    <>\n      {animationTargets\n        .map((target) => [\n          getAnimationParts(target).map(({ id, AMPAnimation }) => (\n            <AMPAnimation key={id} prefixId={providerId} />\n          )),\n        ])\n        .flat(2)}\n    </>\n  );\n}\n\nexport default AMPAnimations;\n"
  },
  {
    "path": "packages/animation/src/components/AMPKeyframes.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { KeyframesOutput } from '../outputs';\nimport useStoryAnimationContext from './useStoryAnimationContext';\nimport generateKeyframesMap from './generateKeyframesMap';\n\nfunction AMPKeyframes() {\n  const {\n    state: { providerId, animationTargets },\n    actions: { getAnimationParts },\n  } = useStoryAnimationContext();\n\n  const keyframesMap = useMemo(\n    () => generateKeyframesMap(animationTargets, getAnimationParts),\n    [animationTargets, getAnimationParts]\n  );\n\n  return Object.keys(keyframesMap).map((animationName) => (\n    <KeyframesOutput\n      key={animationName}\n      id={`${providerId}-${animationName}`}\n      keyframes={keyframesMap[animationName]}\n    />\n  ));\n}\n\nexport default AMPKeyframes;\n"
  },
  {
    "path": "packages/animation/src/components/AMPWrapper.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport type { FunctionComponent, PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from '../parts';\nimport type { WrapperProps } from './types';\nimport useStoryAnimationContext from './useStoryAnimationContext';\n\nconst fullSizeAbsoluteStyles = {\n  width: '100%',\n  height: '100%',\n  display: 'block',\n  position: 'absolute',\n  top: 0,\n  left: 0,\n} as const;\n\ntype ComposableWrapperProps = PropsWithChildren<{\n  animationParts: AnimationPart[];\n}>;\n\ntype Composed = PropsWithChildren<unknown>;\n\nfunction ComposableWrapper({\n  animationParts,\n  children,\n}: ComposableWrapperProps) {\n  const root: FunctionComponent = (props: Composed) =>\n    props.children as React.ReactElement;\n  const ComposedWrapper = useMemo(\n    () =>\n      animationParts.reduce<FunctionComponent>(\n        (Composable: FunctionComponent, animationPart: AnimationPart) => {\n          const { AMPTarget } = animationPart;\n          const Composed = (props: Composed) => {\n            return (\n              <Composable>\n                <AMPTarget style={fullSizeAbsoluteStyles}>\n                  {props.children}\n                </AMPTarget>\n              </Composable>\n            );\n          };\n          return Composed;\n        },\n        root\n      ),\n    [animationParts]\n  );\n\n  // eslint-disable-next-line react-hooks/static-components -- FIXME\n  return <ComposedWrapper>{children}</ComposedWrapper>;\n}\nfunction AMPWrapper({ target, children }: WrapperProps) {\n  const {\n    actions: { getAnimationParts },\n  } = useStoryAnimationContext();\n\n  return (\n    <ComposableWrapper animationParts={getAnimationParts(target)}>\n      {children}\n    </ComposableWrapper>\n  );\n}\n\nexport default AMPWrapper;\n"
  },
  {
    "path": "packages/animation/src/components/WAAPIWrapper.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useRef, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport createKeyframeEffect from '../utils/createKeyframeEffect';\nimport FullSizeAbsolute from './fullSizeAbsolute';\nimport type { WAAPIAnimationWrapperProps, WrapperProps } from './types';\nimport useStoryAnimationContext from './useStoryAnimationContext';\n\nfunction WAAPIAnimationWrapper({\n  children,\n  hoistAnimation,\n  keyframes,\n  timings,\n  targetLeafElement = false,\n}: WAAPIAnimationWrapperProps) {\n  const target = useRef<HTMLDivElement | null>(null);\n\n  useEffect(() => {\n    if (!keyframes) {\n      return () => undefined;\n    }\n\n    const targetEl = targetLeafElement\n      ? target.current?.querySelector('[data-leaf-element=\"true\"]')\n      : target.current;\n\n    if (!targetEl) {\n      return () => undefined;\n    }\n    const effect = createKeyframeEffect(targetEl, keyframes, timings);\n    return hoistAnimation(new Animation(effect, document.timeline));\n  }, [hoistAnimation, keyframes, targetLeafElement, timings]);\n\n  return <FullSizeAbsolute ref={target}>{children}</FullSizeAbsolute>;\n}\n\nfunction WAAPIWrapper({ children, target }: WrapperProps) {\n  const { hoistWAAPIAnimation, animationParts } = useStoryAnimationContext(\n    ({ actions }) => ({\n      hoistWAAPIAnimation: actions.hoistWAAPIAnimation,\n      animationParts: actions.getAnimationParts(target),\n    })\n  );\n  const WAAPIAnimationParts = animationParts?.map(\n    (anim) => anim.WAAPIAnimation\n  );\n\n  const hoistAnimation = useCallback(\n    (animation: Animation) =>\n      hoistWAAPIAnimation({ animation, elementId: target }),\n    [target, hoistWAAPIAnimation]\n  );\n\n  // Parents/Wrappers need to stay consistent here and only have prop changes\n  // to allow react's reconcilliation algorithm to function properly\n  // and not generate a new subtree of DOM nodes:\n  // https://github.com/facebook/react/issues/3965\n  //\n  // To Accommodate for this, we're setting a max of 3 levels deep. All stories built recently should\n  // only have 1 animation per element, however this allows for backward compatibility with old stories\n  // created from legacy templates that use stacked animation parts on single elements\n  return (\n    <WAAPIAnimationWrapper\n      hoistAnimation={hoistAnimation}\n      {...WAAPIAnimationParts[0]}\n    >\n      <WAAPIAnimationWrapper\n        hoistAnimation={hoistAnimation}\n        {...WAAPIAnimationParts[1]}\n      >\n        <WAAPIAnimationWrapper\n          hoistAnimation={hoistAnimation}\n          {...WAAPIAnimationParts[2]}\n        >\n          {children}\n        </WAAPIAnimationWrapper>\n      </WAAPIAnimationWrapper>\n    </WAAPIAnimationWrapper>\n  );\n}\n\nexport default WAAPIWrapper;\n"
  },
  {
    "path": "packages/animation/src/components/animationMachine.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReducer } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { AnimationMachineState, AnimationMachineTransition } from './types';\n\nconst AnimationMachine: Record<\n  AnimationMachineState,\n  Partial<Record<AnimationMachineTransition, AnimationMachineState>>\n> = {\n  [AnimationMachineState.Idle]: {\n    [AnimationMachineTransition.Complete]: AnimationMachineState.Complete,\n  },\n  [AnimationMachineState.Complete]: {\n    [AnimationMachineTransition.Reset]: AnimationMachineState.Idle,\n  },\n};\n\nconst animationStateReducer = (\n  state: AnimationMachineState,\n  action: AnimationMachineTransition\n) => {\n  return AnimationMachine[state][action] || state;\n};\n\nfunction useAnimationMachine() {\n  const [animationState, dispatchWAAPIAnimationState] = useReducer(\n    animationStateReducer,\n    AnimationMachineState.Idle\n  );\n  const reset = useCallback(\n    () => dispatchWAAPIAnimationState(AnimationMachineTransition.Reset),\n    []\n  );\n  const complete = useCallback(\n    () => dispatchWAAPIAnimationState(AnimationMachineTransition.Complete),\n    []\n  );\n\n  return { animationState, reset, complete };\n}\nexport default useAnimationMachine;\n"
  },
  {
    "path": "packages/animation/src/components/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationProviderState } from './types';\n\nconst AnimationContext = createContext<AnimationProviderState>({\n  state: {\n    providerId: '',\n    animationTargets: [],\n  },\n  actions: {\n    getAnimationParts: () => [],\n    hoistWAAPIAnimation: () => () => undefined,\n    WAAPIAnimationMethods: {\n      play: () => undefined,\n      pause: () => undefined,\n      setCurrentTime: () => undefined,\n      reset: () => undefined,\n    },\n  },\n});\n\nexport default AnimationContext;\n"
  },
  {
    "path": "packages/animation/src/components/fullSizeAbsolute.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\nexport default styled.div<{ overflowHidden?: boolean }>`\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  transform-origin: 50% 50%;\n\n  ${({ overflowHidden }) =>\n    overflowHidden &&\n    css`\n      overflow: hidden;\n    `};\n`;\n"
  },
  {
    "path": "packages/animation/src/components/generateKeyframesMap.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AnimationProviderState, ElementId } from './types';\n\nfunction generateKeyframesMap(\n  targets: ElementId[],\n  getAnimationParts: AnimationProviderState['actions']['getAnimationParts']\n) {\n  const allKeyframeEntries = targets\n    .map((target) =>\n      getAnimationParts(target).map((part) =>\n        Object.entries(part.generatedKeyframes)\n      )\n    )\n    .flat(2);\n  const keyframesAsMap = new Map(allKeyframeEntries);\n  return Object.fromEntries(keyframesAsMap);\n}\n\nexport default generateKeyframesMap;\n"
  },
  {
    "path": "packages/animation/src/components/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as AnimationProvider } from './provider';\nexport { default as WAAPIWrapper } from './WAAPIWrapper';\nexport { default as AMPWrapper } from './AMPWrapper';\nexport { default as AMPKeyframes } from './AMPKeyframes';\nexport { default as AMPAnimations } from './AMPAnimations';\nexport { default as useStoryAnimationContext } from './useStoryAnimationContext';\n"
  },
  {
    "path": "packages/animation/src/components/provider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { clamp } from '@googleforcreators/units';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { type AnimationPart, createAnimationPart } from '../parts';\nimport type { Element, StoryAnimation } from '../types';\nimport type {\n  ElementId,\n  ElementMap,\n  ElementAnimationPartsMap,\n  AnimationProviderProps,\n  WAAPIElementAnimation,\n  WAAPIElementAnimationMap,\n  StoryAnimationMap,\n} from './types';\nimport Context from './context';\nimport { AnimationMachineState } from './types';\nimport useAnimationMachine from './animationMachine';\n\nconst createOnFinishPromise = (animation: Animation) => {\n  return new Promise((resolve) => {\n    animation.onfinish = resolve;\n  });\n};\n\nconst filterWAAPIAnimations = (\n  animations: WAAPIElementAnimation[],\n  selectedElementIds: ElementId[]\n) =>\n  selectedElementIds.length > 0\n    ? animations.filter(({ elementId }) =>\n        selectedElementIds.includes(elementId)\n      )\n    : animations;\n\nconst STABLE: unknown[] = [];\n\nfunction mapHasReferentialEntry<K, V>(\n  map: null | Map<K, V>,\n  [key, val]: [K, V]\n) {\n  return map?.has(key) && map.get(key) === val;\n}\n\nfunction Provider({\n  animations = STABLE as StoryAnimation[],\n  elements = STABLE as Element[],\n  children,\n  onWAAPIFinish,\n  selectedElementIds = [],\n}: AnimationProviderProps) {\n  const elementsInstanceMapRef = useRef<ElementMap | null>(null);\n  const elementsInstanceMap: ElementMap = useMemo(\n    () => new Map(elements.map((element) => [element.id, element])),\n    [elements]\n  );\n\n  const animationsInstanceMapRef = useRef<StoryAnimationMap | null>(null);\n  const animationsInstanceMap: StoryAnimationMap = useMemo(\n    () => new Map(animations.map((animation) => [animation.id, animation])),\n    [animations]\n  );\n\n  const animationPartsMapRef = useRef<ElementAnimationPartsMap | null>(null);\n  const animationPartsMap = useMemo(() => {\n    // Keeping track of maps from previous renders to be able to persist\n    // referentially stable generated animations that need no update.\n    const { current: oldAnimationsInstanceMap } = animationsInstanceMapRef;\n    const { current: oldElementsInstanceMap } = elementsInstanceMapRef;\n    const { current: oldAnimationPartsMap } = animationPartsMapRef;\n\n    const _animationPartsMap: ElementAnimationPartsMap = new Map();\n    for (const [animationId, animation] of animationsInstanceMap.entries()) {\n      // See if animationPart needs an update from last animation update\n      const isAnimationRefentiallyStable = mapHasReferentialEntry(\n        oldAnimationsInstanceMap,\n        [animationId, animation]\n      );\n\n      // See if animationPart needs an update from any target elements updating\n      // (animations only have 1 target element, so this may look O(n) but it's\n      // really O(1) in actuality)\n      const areAnimationTargetElementsReferentiallyStable =\n        animation.targets.every((elementId) =>\n          mapHasReferentialEntry(oldElementsInstanceMap, [\n            elementId,\n            elementsInstanceMap.get(elementId),\n          ])\n        );\n\n      // Persist last generated animation if neither animation nor targets have updated\n      if (\n        isAnimationRefentiallyStable &&\n        areAnimationTargetElementsReferentiallyStable &&\n        oldAnimationPartsMap !== null\n      ) {\n        animation.targets.forEach((elementId) => {\n          const element = elementsInstanceMap.get(elementId);\n          if (!element?.isHidden) {\n            _animationPartsMap.set(\n              elementId,\n              oldAnimationPartsMap.get(elementId) || []\n            );\n          }\n        });\n      } else {\n        // Generate new animationPart if input has changed.\n        const { targets } = animation;\n\n        (targets || []).forEach((elementId) => {\n          const generatedParts = _animationPartsMap.get(elementId) || [];\n          const element = elementsInstanceMap.get(elementId);\n\n          if (!element) {\n            // This should not happen.\n            return;\n          }\n\n          if (!element.isHidden) {\n            _animationPartsMap.set(elementId, [\n              ...generatedParts,\n              createAnimationPart(animation, element),\n            ]);\n          }\n        });\n      }\n    }\n\n    // Sync up map refs to reference on next generation of animationPartsMap\n    animationsInstanceMapRef.current = animationsInstanceMap;\n    elementsInstanceMapRef.current = elementsInstanceMap;\n    animationPartsMapRef.current = _animationPartsMap;\n\n    return _animationPartsMap;\n  }, [animationsInstanceMap, elementsInstanceMap]);\n\n  const providerId = useMemo(() => uuidv4(), []);\n\n  const animationTargets = useMemo(\n    () => Array.from(animationPartsMap.keys() || []),\n    [animationPartsMap]\n  );\n\n  const getAnimationParts = useCallback(\n    (target: ElementId) =>\n      animationPartsMap.get(target) || (STABLE as AnimationPart[]),\n    [animationPartsMap]\n  );\n\n  /**\n   * WAAPI interface\n   */\n  const onWAAPIFinishRef = useRef(onWAAPIFinish);\n  const { animationState, reset, complete } = useAnimationMachine();\n  const WAAPIAnimationRef = useRef<WAAPIElementAnimationMap>(new Map());\n  const [WAAPIAnimations, setWAAPIAnimations] = useState<\n    WAAPIElementAnimation[]\n  >([]);\n  const filteredWAAPIAnimations = useMemo(\n    () => filterWAAPIAnimations(WAAPIAnimations, selectedElementIds),\n    [selectedElementIds, WAAPIAnimations]\n  );\n\n  const hoistWAAPIAnimation = useCallback(\n    ({ animation, elementId }: WAAPIElementAnimation) => {\n      const symbol = Symbol();\n      WAAPIAnimationRef.current.set(symbol, {\n        animation,\n        elementId,\n      });\n      setWAAPIAnimations(Array.from(WAAPIAnimationRef.current.values()));\n      return () => {\n        animation?.cancel();\n        WAAPIAnimationRef.current.delete(symbol);\n        setWAAPIAnimations(Array.from(WAAPIAnimationRef.current.values()));\n      };\n    },\n    []\n  );\n\n  const WAAPIAnimationMethods = useMemo(() => {\n    const play = () =>\n      filteredWAAPIAnimations.forEach(({ animation }) => {\n        // Sometimes an animation part can get into a\n        // stuck state where executing `play` doesn't\n        // trigger the animation. A workaround to avoid\n        // this is to first `cancel` the animation\n        // before playing.\n        animation?.cancel();\n\n        animation?.play();\n      });\n    const pause = () =>\n      filteredWAAPIAnimations.forEach(({ animation }) => animation?.pause());\n    const setCurrentTime = (time: number | 'end') =>\n      filteredWAAPIAnimations.forEach(({ animation }) => {\n        const { duration = 0, delay = 0 } = animation.effect?.getTiming() ?? {};\n        // The duration can be \"auto\", which we must treat as 0 in this instance\n        // @see https://w3c.github.io/csswg-drafts/web-animations-1/#dictdef-effecttiming\n        // Note that we could use `getComputedTiming` above instead, but the typings\n        // in @types/web-animations-js aren't completely correct for that return.\n        const actualDuration = typeof duration === 'string' ? 0 : duration;\n        // TODO: Address case where duration can be of type CSSNumericValue.\n\n        const animationEndTime = delay + (actualDuration as number);\n        animation.currentTime =\n          time === 'end'\n            ? animationEndTime\n            : clamp(time, { MIN: 0, MAX: animationEndTime });\n      });\n\n    return {\n      play,\n      pause,\n      setCurrentTime,\n      reset: () => {\n        pause();\n        requestAnimationFrame(() => {\n          setCurrentTime('end');\n        });\n      },\n    };\n  }, [filteredWAAPIAnimations]);\n\n  /**\n   * Browser support for `animation.finished` is no good.\n   * https://developer.mozilla.org/en-US/docs/Web/API/Animation/finished\n   *\n   * So we're mimicking the spec by creating a new promise everytime all\n   * animations complete.\n   */\n  useEffect(() => {\n    let cancel: () => void = () => undefined;\n    if (\n      AnimationMachineState.Idle === animationState &&\n      filteredWAAPIAnimations.length\n    ) {\n      new Promise<void>((resolve, reject) => {\n        cancel = reject;\n        void Promise.all(\n          filteredWAAPIAnimations.map(({ animation }) =>\n            createOnFinishPromise(animation)\n          )\n        ).then(() => {\n          cancel = () => undefined;\n          resolve();\n        });\n      })\n        .then(complete)\n        /* needed if promise gets canceled to swallow the error */\n        .catch(() => undefined);\n    }\n    return cancel;\n  }, [filteredWAAPIAnimations, animationState, complete]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  onWAAPIFinishRef.current = onWAAPIFinish;\n  useEffect(() => {\n    if (AnimationMachineState.Complete === animationState) {\n      onWAAPIFinishRef.current?.();\n      reset();\n    }\n  }, [animationState, reset]);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        providerId,\n        animationTargets,\n      },\n      actions: {\n        getAnimationParts,\n        hoistWAAPIAnimation,\n        WAAPIAnimationMethods,\n      },\n    }),\n    [\n      providerId,\n      getAnimationParts,\n      animationTargets,\n      hoistWAAPIAnimation,\n      WAAPIAnimationMethods,\n    ]\n  );\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport default Provider;\n"
  },
  {
    "path": "packages/animation/src/components/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useState } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '..';\nimport { PlayButton } from '../../storybookUtils';\nimport { AnimationType } from '../../types';\n\nexport default {\n  title: 'Dashboard/Components/StoryAnimation',\n  component: StoryAnimation,\n};\n\nfunction ColorSquare({ color, ...rest }) {\n  return (\n    <div\n      style={{\n        position: 'absolute',\n        top: 0,\n        right: 0,\n        bottom: 0,\n        left: 0,\n        backgroundColor: color,\n      }}\n      {...rest}\n    />\n  );\n}\nColorSquare.propTypes = {\n  color: PropTypes.string,\n};\n\nfunction SquareWrapper({ children }) {\n  return (\n    <div\n      style={{\n        position: 'relative',\n        marginTop: 20,\n        height: 50,\n        width: 50,\n      }}\n    >\n      {children}\n    </div>\n  );\n}\nSquareWrapper.propTypes = {\n  children: PropTypes.node,\n};\n\nconst animations = [\n  { id: '1', targets: ['some-id'], type: AnimationType.Fade },\n  { id: '2', targets: ['some-id'], type: AnimationType.Flip },\n  { id: '3', targets: ['some-id'], type: AnimationType.Spin },\n  {\n    id: '4',\n    targets: ['some-id'],\n    type: AnimationType.FloatOn,\n    duration: 1000,\n  },\n];\n\nexport const _default = {\n  render: function Render() {\n    const [state, setState] = useState(0);\n    return (\n      <StoryAnimation.AnimationProvider\n        animations={animations}\n        onWAAPIFinish={() => {\n          setState((v) => v + 1);\n        }}\n      >\n        <PlayButton />\n        <SquareWrapper>\n          <StoryAnimation.WAAPIWrapper target=\"some-id\">\n            <ColorSquare id=\"some-id\" color={state % 2 ? 'tomato' : 'green'} />\n          </StoryAnimation.WAAPIWrapper>\n        </SquareWrapper>\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const AMPStory = {\n  render: function Render() {\n    const pages = [\n      {\n        id: 'first-page',\n        animations: [\n          {\n            id: 'ir',\n            targets: ['el1'],\n            type: AnimationType.Bounce,\n            duration: 1000,\n          },\n        ],\n      },\n      {\n        id: 'second-page',\n        animations: [\n          {\n            id: 'a5',\n            targets: ['el2'],\n            type: AnimationType.Bounce,\n            duration: 2000,\n          },\n        ],\n      },\n      {\n        id: 'third-page',\n        animations: [\n          { id: 'a1', targets: ['el3'], type: AnimationType.Bounce },\n          {\n            id: 'a2',\n            targets: ['el4'],\n            type: AnimationType.Bounce,\n            delay: 100,\n          },\n          {\n            id: 'a3',\n            targets: ['el5'],\n            type: AnimationType.Bounce,\n            delay: 300,\n          },\n          {\n            id: 'a4',\n            targets: ['el6'],\n            type: AnimationType.Bounce,\n            delay: 500,\n          },\n        ],\n        elements: [\n          { id: 'el3', color: 'red', width: '50px' },\n          { id: 'el4', color: 'orange', width: '100px' },\n          { id: 'el5', color: 'blue', width: '200px' },\n          { id: 'el6', color: 'green', width: '150px' },\n        ],\n      },\n    ];\n\n    return (\n      <div style={{ width: '100%', height: '640px' }}>\n        <amp-story\n          standalone\n          title=\"My Story\"\n          publisher=\"The AMP Team\"\n          publisher-logo-src=\"https://example.com/logo/1x1.png\"\n          poster-portrait-src=\"https://example.com/my-story/poster/3x4.jpg\"\n        >\n          <amp-story-page id={'p0'}>\n            <amp-img\n              src=\"https://picsum.photos/id/58/300\"\n              width=\"300\"\n              height=\"300\"\n            />\n          </amp-story-page>\n          <amp-story-page id={pages[0].id}>\n            <StoryAnimation.AnimationProvider animations={pages[0].animations}>\n              <StoryAnimation.AMPKeyframes />\n              <StoryAnimation.AMPAnimations />\n\n              <StoryAnimation.AMPWrapper\n                target=\"el1\"\n                style={{ width: '300px', height: '300px' }}\n              >\n                <amp-img\n                  src=\"https://picsum.photos/id/237/300\"\n                  width=\"300\"\n                  height=\"300\"\n                />\n              </StoryAnimation.AMPWrapper>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n          <amp-story-page id={pages[1].id}>\n            <StoryAnimation.AnimationProvider animations={pages[1].animations}>\n              <StoryAnimation.AMPKeyframes />\n              <StoryAnimation.AMPAnimations />\n\n              <div\n                style={{\n                  display: 'flex',\n                  flexDirection: 'column',\n                  alignItems: 'center',\n                  justifyContent: 'center',\n                  height: '100%',\n                }}\n              >\n                <StoryAnimation.AMPWrapper\n                  target=\"el2\"\n                  style={{ width: '300px', height: '300px' }}\n                >\n                  <amp-img\n                    src=\"https://picsum.photos/id/17/300\"\n                    width=\"300\"\n                    height=\"300\"\n                  />\n                </StoryAnimation.AMPWrapper>\n              </div>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n          <amp-story-page id={pages[2].id}>\n            <StoryAnimation.AnimationProvider animations={pages[2].animations}>\n              <StoryAnimation.AMPKeyframes />\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"vertical\">\n                {pages[2].elements.map((element) => (\n                  <StoryAnimation.AMPWrapper\n                    key={element.id}\n                    target={element.id}\n                    style={{\n                      width: element.width,\n                      height: '50px',\n                      marginBottom: '10px',\n                    }}\n                  >\n                    <div\n                      style={{\n                        width: '100%',\n                        height: '100%',\n                        backgroundColor: element.color,\n                      }}\n                    />\n                  </StoryAnimation.AMPWrapper>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        </amp-story>\n      </div>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/components/test/WAAPIWrapper.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport { render, act } from '@testing-library/react';\nimport type { FunctionComponent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { AnimationType } from '../../types';\nimport type { Element, ElementId, StoryAnimation } from '../../types';\nimport Provider from '../provider';\nimport WAAPIWrapper from '../WAAPIWrapper';\n\ntype Tracker = FunctionComponent<{ target: string }>;\ntype TrackersProps = {\n  ElOneWAAPIInvocationTracker: Tracker;\n  ElTwoWAAPIInvocationTracker: Tracker;\n};\ntype ElementsWithWrapperProps = {\n  animations: StoryAnimation[];\n  elements: Element[];\n  ElOneWAAPIInvocationTracker: Tracker;\n  ElTwoWAAPIInvocationTracker: Tracker;\n};\nfunction Trackers({\n  ElOneWAAPIInvocationTracker,\n  ElTwoWAAPIInvocationTracker,\n}: TrackersProps) {\n  return useMemo(\n    () => (\n      <div>\n        <ElOneWAAPIInvocationTracker target={'elOne'}>\n          <div />\n        </ElOneWAAPIInvocationTracker>\n        <ElTwoWAAPIInvocationTracker target={'elTwo'}>\n          <div />\n        </ElTwoWAAPIInvocationTracker>\n      </div>\n    ),\n    [ElOneWAAPIInvocationTracker, ElTwoWAAPIInvocationTracker]\n  );\n}\n\ndescribe('StoryAnimation.WAAPIWrapper', () => {\n  describe('tracking necessary rerenders', () => {\n    // Create mock data\n    const createMockAnim = (\n      id: string,\n      targets: ElementId[]\n    ): StoryAnimation => ({\n      type: AnimationType.EffectPulse,\n      delay: 0,\n      duration: 350,\n      iterations: 1,\n      scale: 0.5,\n      id,\n      targets,\n    });\n    const createMockElement = (partial: Partial<Element>): Element => ({\n      id: '2e04154c-bc58-4969-bb4d-c69d32da0eac',\n      x: 0,\n      y: 0,\n      width: 0,\n      height: 0,\n      rotationAngle: 0,\n      ...partial,\n    });\n    const initialAnimations = [\n      createMockAnim('animOne', ['elOne']),\n      createMockAnim('animTwo', ['elTwo']),\n    ];\n    const initialElements = [\n      createMockElement({ id: 'elOne' }),\n      createMockElement({ id: 'elTwo' }),\n    ];\n\n    const ElementsWithWrapper = ({\n      animations,\n      elements,\n      ElOneWAAPIInvocationTracker,\n      ElTwoWAAPIInvocationTracker,\n    }: ElementsWithWrapperProps) => (\n      <Provider animations={animations} elements={elements}>\n        <Trackers\n          ElOneWAAPIInvocationTracker={ElOneWAAPIInvocationTracker}\n          ElTwoWAAPIInvocationTracker={ElTwoWAAPIInvocationTracker}\n        />\n      </Provider>\n    );\n\n    it('doesnt rerender wrappers uneffected by animation updates', () => {\n      // Render with mock methods\n      const ElOneWAAPIInvocationTracker = jest.fn(WAAPIWrapper);\n      const ElTwoWAAPIInvocationTracker = jest.fn(WAAPIWrapper);\n      const { rerender } = render(\n        <ElementsWithWrapper\n          animations={initialAnimations}\n          elements={initialElements}\n          ElOneWAAPIInvocationTracker={ElOneWAAPIInvocationTracker}\n          ElTwoWAAPIInvocationTracker={ElTwoWAAPIInvocationTracker}\n        />\n      );\n\n      // See that mock methods were called on mount\n      expect(ElOneWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n      expect(ElTwoWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n\n      // Update animations with one new animation and one\n      // previous animation instance\n      act(() => {\n        rerender(\n          <ElementsWithWrapper\n            animations={[\n              { ...initialAnimations[0], duration: 500 },\n              initialAnimations[1],\n            ]}\n            elements={initialElements}\n            ElOneWAAPIInvocationTracker={ElOneWAAPIInvocationTracker}\n            ElTwoWAAPIInvocationTracker={ElTwoWAAPIInvocationTracker}\n          />\n        );\n      });\n\n      // See that only the element effected by the animation update rerendered\n      // See that mock methods were called on mount\n      expect(ElOneWAAPIInvocationTracker).toHaveBeenCalledTimes(2);\n      expect(ElTwoWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n    });\n\n    it('doesnt rerender wrappers uneffected by element updates', () => {\n      // Render with mock methods\n      const ElOneWAAPIInvocationTracker = jest.fn(WAAPIWrapper);\n      const ElTwoWAAPIInvocationTracker = jest.fn(WAAPIWrapper);\n      const { rerender } = render(\n        <ElementsWithWrapper\n          animations={initialAnimations}\n          elements={initialElements}\n          ElOneWAAPIInvocationTracker={ElOneWAAPIInvocationTracker}\n          ElTwoWAAPIInvocationTracker={ElTwoWAAPIInvocationTracker}\n        />\n      );\n\n      // See that mock methods were called on mount\n      expect(ElOneWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n      expect(ElTwoWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n\n      // Update animations with one new element and one\n      // previous element instance\n      act(() => {\n        rerender(\n          <ElementsWithWrapper\n            animations={initialAnimations}\n            elements={[{ ...initialElements[0] }, initialElements[1]]}\n            ElOneWAAPIInvocationTracker={ElOneWAAPIInvocationTracker}\n            ElTwoWAAPIInvocationTracker={ElTwoWAAPIInvocationTracker}\n          />\n        );\n      });\n\n      // See that only the element effected by the animation update rerendered\n      expect(ElOneWAAPIInvocationTracker).toHaveBeenCalledTimes(2);\n      expect(ElTwoWAAPIInvocationTracker).toHaveBeenCalledTimes(1);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/components/test/animationProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useFeature } from 'flagged';\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { createAnimationPart } from '../../parts';\nimport { AnimationType, type Element, type StoryAnimation } from '../../types';\nimport { AnimationProvider, useStoryAnimationContext } from '..';\n\njest.mock('flagged');\njest.mock('../../parts', () => ({\n  createAnimationPart: jest.fn().mockImplementation(() => ({\n    id: '',\n    keyframes: {},\n    WAAPIAnimation: { keyframes: {}, timings: {} },\n    AMPTarget: () => null,\n    AMPAnimation: () => null,\n    generatedKeyframes: {},\n  })),\n}));\nconst mockedUseFeature = jest.mocked(useFeature);\nconst mockedCreateAnimationPart = jest.mocked(createAnimationPart);\n\nfunction flushPromiseQueue() {\n  return Promise.resolve();\n}\n\nfunction createWrapperWithProps<T>(\n  Wrapper: React.FunctionComponent<T>,\n  props: T\n) {\n  const WrapperWithProps = ({ children }: PropsWithChildren<T>) => (\n    <Wrapper {...props}>{children}</Wrapper>\n  );\n  return WrapperWithProps;\n}\n\nconst mockWAAPIAnimation = (overrides = {}) => ({\n  ...new Animation(),\n  ...overrides,\n});\n\ntype MockAnimation = Animation & {\n  play: (this: void) => void;\n  pause: (this: void) => void;\n};\n\ndescribe('AnimationProvider', () => {\n  beforeAll(() => {\n    mockedUseFeature.mockImplementation(() => true);\n  });\n\n  afterEach(() => {\n    mockedCreateAnimationPart.mockReset();\n  });\n\n  describe('getAnimationParts(target)', () => {\n    it('gets all generated parts for a target', () => {\n      const target = 'id1';\n      const otherTarget = 'id2';\n      const animations = [\n        {\n          id: '1',\n          targets: [target],\n          type: AnimationType.Move as const,\n          duration: 1000,\n        },\n        {\n          id: '2',\n          targets: [target],\n          type: AnimationType.Spin as const,\n          duration: 1000,\n        },\n        {\n          id: '3',\n          targets: [otherTarget],\n          type: AnimationType.Move as const,\n          duration: 1000,\n        },\n        {\n          id: '4',\n          targets: [target, otherTarget],\n          type: AnimationType.Zoom as const,\n          duration: 1000,\n        },\n      ];\n      const elements: Element[] = [\n        { id: target, x: 0, y: 0, width: 0, height: 0, rotationAngle: 0 },\n        { id: otherTarget, x: 0, y: 0, width: 0, height: 0, rotationAngle: 0 },\n      ];\n\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations,\n          elements,\n        }),\n      });\n\n      const {\n        actions: { getAnimationParts },\n      } = result.current;\n\n      expect(getAnimationParts(target)).toHaveLength(3);\n      expect(getAnimationParts(otherTarget)).toHaveLength(2);\n      expect(getAnimationParts('id3')).toHaveLength(0);\n    });\n\n    it('calls generators for a target in ascending order', () => {\n      const target = 'id1';\n      const targets = [target];\n      const args = { someProp: 1, duration: 1000 };\n      const types = [\n        AnimationType.Move as const,\n        AnimationType.Spin as const,\n        AnimationType.Zoom as const,\n      ];\n      const animations = [\n        { id: '1', targets, type: types[0], ...args },\n        { id: '2', targets, type: types[1], ...args },\n        { id: '3', targets, type: types[2], ...args },\n      ];\n      const elements: Element[] = [\n        { id: target, x: 0, y: 0, width: 0, height: 0, rotationAngle: 0 },\n      ];\n\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations,\n          elements,\n        }),\n      });\n\n      const {\n        actions: { getAnimationParts },\n      } = result.current;\n\n      getAnimationParts(target);\n\n      animations.forEach((animation) => {\n        expect(createAnimationPart).toHaveBeenCalledWith(\n          animation,\n          elements[0]\n        );\n      });\n    });\n\n    it('calls generators for a target with proper args', () => {\n      const target = 'some-target';\n      const target2 = 'that-target';\n      const element1 = {\n        id: target,\n        type: 'text',\n        x: 0,\n        y: 0,\n        width: 0,\n        height: 0,\n        rotationAngle: 0,\n      };\n      const element2 = {\n        id: target2,\n        type: 'text',\n        x: 0,\n        y: 0,\n        width: 0,\n        height: 0,\n        rotationAngle: 0,\n      };\n      const elements = [element1, element2];\n      const animType = AnimationType.Move;\n      const args = [\n        { bounces: 3, duration: 1000 },\n        { blinks: 2, offset: 20, blarks: 6, duration: 1000 },\n        { columns: 4, duration: 400 },\n      ];\n      const animations: StoryAnimation[] = [\n        { id: '1', targets: [target], type: animType, ...args[0] },\n        { id: '2', targets: [target], type: animType, ...args[1] },\n        { id: '3', targets: [target2], type: animType, ...args[2] },\n      ];\n\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations,\n          elements,\n        }),\n      });\n\n      const {\n        actions: { getAnimationParts },\n      } = result.current;\n\n      getAnimationParts(target);\n      animations\n        .filter(({ targets }) => targets.includes(target))\n        .forEach(({ type, ...rest }) => {\n          expect(mockedCreateAnimationPart).toHaveBeenCalledWith(\n            { type, ...rest },\n            element1\n          );\n        });\n\n      getAnimationParts(target2);\n      animations\n        .filter(({ targets }) => targets.includes(target2))\n        .forEach(({ type, ...rest }) => {\n          expect(mockedCreateAnimationPart).toHaveBeenCalledWith(\n            { type, ...rest },\n            element2\n          );\n        });\n    });\n  });\n\n  describe('hoistWAAPIAnimation(WAAPIAnimation)', () => {\n    it('returns a cleanup function when called', () => {\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations: [],\n        }),\n      });\n\n      let unhoist;\n      act(() => {\n        unhoist = result.current.actions.hoistWAAPIAnimation({\n          animation: mockWAAPIAnimation(),\n          elementId: '',\n        });\n      });\n      expect(typeof unhoist).toBe('function');\n    });\n\n    /**\n     * Animation.cancel()**\n     *\n     * Clears all KeyframeEffects caused by this animation\n     * and aborts its playback.\n     *\n     * https://developer.mozilla.org/en-US/docs/Web/API/Animation/cancel\n     */\n    it('calls Animation.cancel() method on hoisted animation when cleanup performed', () => {\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations: [],\n        }),\n      });\n\n      const cancel = jest.fn();\n      act(() => {\n        const unhoist = result.current.actions.hoistWAAPIAnimation({\n          animation: mockWAAPIAnimation({ cancel }),\n          elementId: '',\n        });\n        unhoist();\n      });\n      expect(cancel).toHaveBeenCalledWith();\n    });\n  });\n\n  describe('WAAPIAnimationMethods', () => {\n    it('calls all hoisted Animation methods when called', () => {\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations: [],\n        }),\n      });\n\n      const numCalls = 10;\n      const play = jest.fn();\n      const pause = jest.fn();\n      const cancel = jest.fn();\n      const animations = Array.from({ length: numCalls }, () => {\n        const animation = mockWAAPIAnimation({\n          play,\n          pause,\n          cancel,\n          currentTime: 0,\n          effect: {\n            getTiming: () => ({\n              duration: 300,\n              delay: 0,\n            }),\n          },\n        });\n        act(() => {\n          result.current.actions.hoistWAAPIAnimation({\n            animation,\n            elementId: '',\n          });\n        });\n        return animation;\n      });\n\n      act(() => result.current.actions.WAAPIAnimationMethods.play());\n      act(() => result.current.actions.WAAPIAnimationMethods.pause());\n      act(() =>\n        result.current.actions.WAAPIAnimationMethods.setCurrentTime(200)\n      );\n\n      expect(play).toHaveBeenCalledTimes(numCalls);\n      expect(pause).toHaveBeenCalledTimes(numCalls);\n      animations.forEach((animation) => {\n        expect(animation.currentTime).toBe(200);\n      });\n    });\n\n    it('calls all selectedElement hoisted Animation methods when called and passed selected elements', () => {\n      const selectedElementIds = ['a', 'b', 'c'];\n      const allElementIds = [...selectedElementIds, 'd', 'e'];\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations: [],\n          selectedElementIds,\n        }),\n      });\n\n      const animationsWithIds = allElementIds.map((elementId) => {\n        const animation: MockAnimation = mockWAAPIAnimation({\n          play: jest.fn(),\n          pause: jest.fn(),\n          cancel: jest.fn(),\n          currentTime: 0,\n          effect: {\n            getTiming: () => ({\n              duration: 300,\n              delay: 0,\n            }),\n          },\n        });\n        const animationWithElementId = { animation, elementId };\n        act(() => {\n          result.current.actions.hoistWAAPIAnimation({ animation, elementId });\n        });\n        return animationWithElementId;\n      });\n\n      act(() => result.current.actions.WAAPIAnimationMethods.play());\n      act(() => result.current.actions.WAAPIAnimationMethods.pause());\n      act(() =>\n        result.current.actions.WAAPIAnimationMethods.setCurrentTime(200)\n      );\n\n      animationsWithIds.forEach(({ animation, elementId }) => {\n        expect(animation.currentTime).toStrictEqual(\n          selectedElementIds.includes(elementId) ? 200 : 0\n        );\n        expect(animation.play).toHaveBeenCalledTimes(\n          selectedElementIds.includes(elementId) ? 1 : 0\n        );\n        expect(animation.pause).toHaveBeenCalledTimes(\n          selectedElementIds.includes(elementId) ? 1 : 0\n        );\n      });\n    });\n\n    it('excludes cleaned up animation methods when called', () => {\n      const { result } = renderHook(() => useStoryAnimationContext(), {\n        wrapper: createWrapperWithProps(AnimationProvider, {\n          animations: [],\n        }),\n      });\n\n      const initialTime = 0;\n      const newTime = 200;\n\n      const numAnims = 10;\n      const unhoistIndex = numAnims / 2;\n      const animations = Array.from(\n        { length: numAnims },\n        (): MockAnimation =>\n          mockWAAPIAnimation({\n            play: jest.fn(),\n            pause: jest.fn(),\n            cancel: jest.fn(),\n            currentTime: initialTime,\n            effect: {\n              getTiming: () => ({\n                duration: 300,\n                delay: 0,\n              }),\n            },\n          })\n      );\n\n      const unhoists = animations.map((animation) => {\n        let unhoist: () => void = () => undefined;\n        act(() => {\n          unhoist = result.current.actions.hoistWAAPIAnimation({\n            animation,\n            elementId: '',\n          });\n        });\n        return unhoist;\n      });\n      act(() => {\n        unhoists[unhoistIndex]();\n      });\n\n      act(() => result.current.actions.WAAPIAnimationMethods.play());\n      act(() => result.current.actions.WAAPIAnimationMethods.pause());\n      act(() =>\n        result.current.actions.WAAPIAnimationMethods.setCurrentTime(newTime)\n      );\n\n      animations.forEach((animation, i) => {\n        if (i === unhoistIndex) {\n          expect(animation.play).toHaveBeenCalledTimes(0);\n          expect(animation.pause).toHaveBeenCalledTimes(0);\n          expect(animation.currentTime).toStrictEqual(initialTime);\n        } else {\n          expect(animation.play).toHaveBeenCalledTimes(1);\n          expect(animation.pause).toHaveBeenCalledTimes(1);\n          expect(animation.currentTime).toStrictEqual(newTime);\n        }\n      });\n    });\n  });\n\n  describe('events', () => {\n    describe('onWAAPIFinish', () => {\n      it('fires once each time all animations complete', async () => {\n        const onWAAPIFinish = jest.fn();\n        const { result } = renderHook(() => useStoryAnimationContext(), {\n          wrapper: createWrapperWithProps(AnimationProvider, {\n            animations: [],\n            onWAAPIFinish,\n          }),\n        });\n\n        const animations = Array.from({ length: 10 }, () =>\n          mockWAAPIAnimation()\n        );\n        animations.forEach((animation) => {\n          act(() => {\n            result.current.actions.hoistWAAPIAnimation({\n              animation,\n              elementId: '',\n            });\n          });\n        });\n\n        const completeAllAnimations = async () => {\n          animations.forEach((animation) => {\n            animation?.onfinish?.(new AnimationPlaybackEvent('finish'));\n          });\n          /**\n           * Needed to flush all promises and\n           * trigger dispatch from resolved promise\n           */\n          await act(async () => {\n            await flushPromiseQueue();\n          });\n        };\n\n        await completeAllAnimations();\n        expect(onWAAPIFinish).toHaveBeenCalledTimes(1);\n        await completeAllAnimations();\n        expect(onWAAPIFinish).toHaveBeenCalledTimes(2);\n        await completeAllAnimations();\n        expect(onWAAPIFinish).toHaveBeenCalledTimes(3);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/components/test/generateKeyframesMap.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from '../../parts';\nimport type { ElementId, Keyframes } from '../../types';\nimport generateKeyframesMap from '../generateKeyframesMap';\n\ntype AnimationParts = Record<string, AnimationPart[]>;\n\nconst mockGetAnimationParts = (src: AnimationParts) => (target: ElementId) =>\n  src[target];\n\nconst mockCreateAnimationPart = (\n  id: string,\n  keyframes: Keyframes\n): AnimationPart => ({\n  id,\n  keyframes,\n  WAAPIAnimation: { keyframes, timings: {} },\n  AMPAnimation: () => null,\n  AMPTarget: () => null,\n  generatedKeyframes: { [id]: keyframes },\n});\n\ndescribe('generateKeyframesMap', () => {\n  it('should flatten keyframes into a single map', () => {\n    const targets = ['target1', 'target2', 'target3'];\n    const parts: AnimationParts = {\n      [targets[0]]: [\n        mockCreateAnimationPart('a', { transform: [1, 3, 4] }),\n        mockCreateAnimationPart('b', { transform: [5, 7, 9] }),\n      ],\n      [targets[1]]: [mockCreateAnimationPart('c', { transform: [2, 5, 8] })],\n      [targets[2]]: [mockCreateAnimationPart('d', { opacity: [0, 1, 0, 1] })],\n    };\n\n    const getAnimationParts = mockGetAnimationParts(parts);\n\n    expect(generateKeyframesMap(targets, getAnimationParts)).toStrictEqual({\n      a: { transform: [1, 3, 4] },\n      b: { transform: [5, 7, 9] },\n      c: { transform: [2, 5, 8] },\n      d: { opacity: [0, 1, 0, 1] },\n    });\n  });\n\n  it('should consolidate duplicate keyframes', () => {\n    const targets = ['target1', 'target2', 'target3'];\n    const parts = {\n      [targets[0]]: [\n        mockCreateAnimationPart('a', { transform: [1, 3, 4] }),\n        mockCreateAnimationPart('b', { transform: [5, 7, 9] }),\n      ],\n      [targets[1]]: [mockCreateAnimationPart('a', { transform: [1, 3, 4] })],\n      [targets[2]]: [\n        mockCreateAnimationPart('a', { transform: [1, 3, 4] }),\n        mockCreateAnimationPart('c', { opacity: [0, 1, 0, 1] }),\n      ],\n    };\n\n    const getAnimationParts = mockGetAnimationParts(parts);\n\n    expect(generateKeyframesMap(targets, getAnimationParts)).toStrictEqual({\n      a: { transform: [1, 3, 4] },\n      b: { transform: [5, 7, 9] },\n      c: { opacity: [0, 1, 0, 1] },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/components/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from '../parts';\nimport type {\n  AMPEffectTiming,\n  Element,\n  ElementId,\n  Keyframes,\n  StoryAnimation,\n} from '../types';\n\n// We can't depend on the elements package, but we also don't actually need to.\n// The only thing we need concerning elements is the fact, that they're an object\n// with a string id, so this will suffice.\n\nexport type { ElementId };\n\nexport type ElementAnimationHoister = (\n  elementAnimation: WAAPIElementAnimation\n) => () => void;\n\nexport type AnimationHoister = (animation: Animation) => () => void;\n\nexport interface AnimationProviderState {\n  state: {\n    providerId: string;\n    animationTargets: ElementId[];\n  };\n  actions: {\n    getAnimationParts: (target: ElementId) => AnimationPart[];\n    hoistWAAPIAnimation: ElementAnimationHoister;\n    WAAPIAnimationMethods: {\n      play: () => void;\n      pause: () => void;\n      setCurrentTime: (time: number | 'end') => void;\n      reset: () => void;\n    };\n  };\n}\n\nexport type AnimationProviderProps = PropsWithChildren<{\n  animations?: StoryAnimation[];\n  elements?: Element[];\n  onWAAPIFinish?: () => void;\n  selectedElementIds?: string[];\n}>;\n\nexport type StoryAnimationMap = Map<StoryAnimation['id'], StoryAnimation>;\nexport type ElementAnimationPartsMap = Map<ElementId, AnimationPart[]>;\n\nexport interface WAAPIElementAnimation {\n  animation: Animation;\n  elementId: ElementId;\n}\nexport type WAAPIElementAnimationMap = Map<symbol, WAAPIElementAnimation>;\nexport type ElementMap = Map<ElementId, Element>;\n\nexport type WAAPIAnimationWrapperProps = PropsWithChildren<{\n  keyframes: Keyframes;\n  timings: AMPEffectTiming;\n  hoistAnimation: AnimationHoister;\n  targetLeafElement?: boolean;\n}>;\n\nexport type WrapperProps = PropsWithChildren<{\n  target: ElementId;\n}>;\n\nexport enum AnimationMachineState {\n  Idle = 'idle',\n  Complete = 'complete',\n}\n\nexport enum AnimationMachineTransition {\n  Complete = 'complete',\n  Reset = 'reset',\n}\n"
  },
  {
    "path": "packages/animation/src/components/useStoryAnimationContext.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { AnimationProviderState } from './types';\n\nfunction useStoryAnimationContext(): AnimationProviderState;\nfunction useStoryAnimationContext<T>(\n  selector: (state: AnimationProviderState) => T\n): T;\nfunction useStoryAnimationContext<T>(\n  selector: (\n    state: AnimationProviderState\n  ) => T | AnimationProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useStoryAnimationContext;\n"
  },
  {
    "path": "packages/animation/src/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AnimationType, ScaleDirection } from './types';\n\nexport const BEZIER = {\n  linear: 'linear',\n  in: 'ease-in',\n  out: 'ease-out',\n  inOut: 'ease-in-out',\n  inQuad: 'cubic-bezier(0.55, 0.085, 0.68, 0.53)',\n  outQuad: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n  inOutQuad: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)',\n  inCubic: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)',\n  outCubic: 'cubic-bezier(0.215, 0.61, 0.355, 1)',\n  inOutCubic: 'cubic-bezier(0.645, 0.045, 0.355, 1)',\n  inQuart: 'cubic-bezier(0.895, 0.03, 0.685, 0.22)',\n  outQuart: 'cubic-bezier(0.165, 0.84, 0.44, 1)',\n  inOutQuart: 'cubic-bezier(0.77, 0, 0.175, 1)',\n  inQuint: 'cubic-bezier(0.755, 0.05, 0.855, 0.06)',\n  outQuint: 'cubic-bezier(0.23, 1, 0.32, 1)',\n  inOutQuint: 'cubic-bezier(0.86, 0, 0.07, 1)',\n  inSine: 'cubic-bezier(0.47, 0, 0.745, 0.715)',\n  outSine: 'cubic-bezier(0.39, 0.575, 0.565, 1)',\n  inOutSine: 'cubic-bezier(0.445, 0.05, 0.55, 0.95)',\n  inExpo: 'cubic-bezier(0.95, 0.05, 0.795, 0.035)',\n  outExpo: 'cubic-bezier(0.19, 1, 0.22, 1)',\n  inOutExpo: 'cubic-bezier(1, 0, 0, 1)',\n  inCirc: 'cubic-bezier(0.6, 0.04, 0.98, 0.335)',\n  outCirc: 'cubic-bezier(0.075, 0.82, 0.165, 1)',\n  inOutCirc: 'cubic-bezier(0.785, 0.135, 0.15, 0.86)',\n  default: 'cubic-bezier(0.4, 0.4, 0.0, 1)',\n} as const;\n\nexport type BezierType = keyof typeof BEZIER;\n\nexport const ANIMATION_EFFECTS = {\n  DROP: {\n    value: AnimationType.EffectDrop,\n    name: _x('Drop', 'animation effect', 'web-stories'),\n  },\n  FADE_IN: {\n    value: AnimationType.EffectFadeIn,\n    name: _x('Fade In', 'animation effect', 'web-stories'),\n  },\n  FLY_IN: {\n    value: AnimationType.EffectFlyIn,\n    name: _x('Fly In', 'animation effect', 'web-stories'),\n  },\n  PAN: {\n    value: AnimationType.EffectPan,\n    name: _x('Pan', 'animation effect', 'web-stories'),\n  },\n  PULSE: {\n    value: AnimationType.EffectPulse,\n    name: _x('Pulse', 'animation effect', 'web-stories'),\n  },\n  TWIRL_IN: {\n    value: AnimationType.EffectTwirlIn,\n    name: _x('Twirl In', 'animation effect', 'web-stories'),\n  },\n  WHOOSH_IN: {\n    value: AnimationType.EffectWhooshIn,\n    name: _x('Whoosh In', 'animation effect', 'web-stories'),\n  },\n  ZOOM: {\n    value: AnimationType.EffectZoom,\n    name: _x('Scale', 'animation effect', 'web-stories'),\n  },\n  ROTATE_IN: {\n    value: AnimationType.EffectRotateIn,\n    name: _x('Rotate In', 'animation effect', 'web-stories'),\n  },\n};\n\nexport const BACKGROUND_ANIMATION_EFFECTS = {\n  ZOOM: {\n    value: AnimationType.EffectBackgroundZoom,\n    name: _x('Zoom', 'animation effect', 'web-stories'),\n  },\n  PAN: {\n    value: AnimationType.EffectBackgroundPan,\n    name: ANIMATION_EFFECTS.PAN.name,\n  },\n  PAN_AND_ZOOM: {\n    value: AnimationType.EffectBackgroundPanAndZoom,\n    name: _x('Pan and Zoom', 'animation effect', 'web-stories'),\n  },\n};\n\nexport const ANIMATION_PARTS = {\n  BLINK_ON: {\n    value: AnimationType.BlinkOn,\n    name: _x('Blink On', 'animation effect', 'web-stories'),\n  },\n  BOUNCE: {\n    value: AnimationType.Bounce,\n    name: _x('Bounce', 'animation effect', 'web-stories'),\n  },\n  FADE: {\n    value: AnimationType.Fade,\n    name: _x('Fade', 'animation effect', 'web-stories'),\n  },\n  FLIP: {\n    value: AnimationType.Flip,\n    name: _x('Flip', 'animation effect', 'web-stories'),\n  },\n  FLOAT_ON: {\n    value: AnimationType.FloatOn,\n    name: _x('Float On', 'animation effect', 'web-stories'),\n  },\n  MOVE: {\n    value: AnimationType.Move,\n    name: _x('Move', 'animation effect', 'web-stories'),\n  },\n  PULSE: {\n    value: AnimationType.Pulse,\n    name: _x('Pulse', 'animation effect', 'web-stories'),\n  },\n  SPIN: {\n    value: AnimationType.Spin,\n    name: _x('Spin', 'animation effect', 'web-stories'),\n  },\n  ZOOM: {\n    value: AnimationType.Zoom,\n    name: _x('Zoom', 'animation effect', 'web-stories'),\n  },\n};\n\nexport const SCALE_DIRECTIONS = {\n  IN: [ScaleDirection.ScaleInTopLeft, ScaleDirection.ScaleInBottomRight],\n  OUT: [ScaleDirection.ScaleOutTopRight, ScaleDirection.ScaleOutBottomLeft],\n} as const;\n\nexport const BG_MIN_SCALE = 100;\nexport const BG_MAX_SCALE = 400;\n"
  },
  {
    "path": "packages/animation/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './components';\nexport * from './constants';\nexport * from './parts';\nexport * from './outputs';\nexport * from './utils';\nexport * from './types';\n"
  },
  {
    "path": "packages/animation/src/outputs/animationOutput.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AnimationOutputProps } from './types';\n\nfunction AnimationOutput({ config }: AnimationOutputProps) {\n  const configs = Array.isArray(config) ? config : [config];\n\n  return (\n    <amp-story-animation layout=\"nodisplay\" trigger=\"visibility\">\n      <script\n        type=\"application/json\"\n        dangerouslySetInnerHTML={{\n          __html: JSON.stringify(\n            // Only print the actual items needed for the animations,\n            // as defined by the prop types.\n            // Prevents printing the `element` prop which `config` can have.\n            configs.map(\n              ({\n                selector,\n                animation,\n                keyframes,\n                delay,\n                direction,\n                duration,\n                easing,\n                endDelay,\n                fill,\n                iterationStart,\n                iterations,\n              }) => ({\n                selector,\n                animation,\n                keyframes,\n                delay,\n                direction,\n                duration,\n                easing,\n                endDelay,\n                fill,\n                iterationStart,\n                iterations,\n              })\n            )\n          ),\n        }}\n      />\n    </amp-story-animation>\n  );\n}\n\nexport default AnimationOutput;\n"
  },
  {
    "path": "packages/animation/src/outputs/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as AnimationOutput } from './animationOutput';\nexport { default as KeyframesOutput } from './keyframesOutput';\nexport { default as WithAnimation } from './output';\nexport * from './types';\n"
  },
  {
    "path": "packages/animation/src/outputs/keyframesOutput.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { KeyframesOutputProps } from './types';\n\nfunction KeyframesOutput({ id, keyframes, ...options }: KeyframesOutputProps) {\n  return (\n    <amp-animation id={id} layout=\"nodisplay\">\n      <script\n        type=\"application/json\"\n        dangerouslySetInnerHTML={{\n          __html: JSON.stringify({\n            keyframes,\n            ...options,\n          }),\n        }}\n      />\n    </amp-animation>\n  );\n}\n\nexport default KeyframesOutput;\n"
  },
  {
    "path": "packages/animation/src/outputs/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { WithAnimationProps } from './types';\n\nfunction WithAnimation({\n  id,\n  className,\n  style,\n  animationStyle,\n  useClippingContainer,\n  children,\n}: WithAnimationProps) {\n  return useClippingContainer ? (\n    <div\n      style={{\n        clipPath: 'inset(0)',\n        ...style,\n      }}\n    >\n      <div\n        id={id}\n        className={className}\n        style={{ width: '100%', height: '100%', ...animationStyle }}\n      >\n        {children}\n      </div>\n    </div>\n  ) : (\n    <div id={id} className={className} style={{ ...style, ...animationStyle }}>\n      {children}\n    </div>\n  );\n}\n\nexport default WithAnimation;\n"
  },
  {
    "path": "packages/animation/src/outputs/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { CSSProperties, PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming, Keyframes } from '../types';\n\nexport interface AnimationConfig extends AMPEffectTiming {\n  selector: string;\n  animation?: string;\n  keyframes?: Keyframes;\n}\n\nexport interface AnimationOutputProps {\n  config: AnimationConfig | AnimationConfig[];\n}\n\nexport type WithAnimationProps = PropsWithChildren<{\n  id?: string;\n  className?: string;\n  style?: CSSProperties;\n  animationStyle?: CSSProperties;\n  useClippingContainer?: boolean;\n}>;\n\nexport interface KeyframesOutputProps extends AMPEffectTiming {\n  id: string;\n  keyframes: Keyframes;\n}\n"
  },
  {
    "path": "packages/animation/src/parts/createAnimation.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { VoidFunctionComponent } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { AnimationOutput, WithAnimation } from '../outputs';\nimport type { AMPEffectTiming, Keyframes } from '../types';\nimport getInitialStyleFromKeyframes from '../utils/getInitialStyleFromKeyframes';\nimport sanitizeTimings from '../utils/sanitizeTimings';\nimport type { AMPAnimationProps, WAAPIAnimation, AnimationPart } from './types';\n\nfunction createAnimation<T extends Keyframes>(\n  keyframes: T,\n  timings: AMPEffectTiming,\n  withClippingContainer = false,\n  targetLeafElement = false\n): AnimationPart<T> {\n  const id = `anim-${uuidv4()}`;\n\n  const WAAPIAnimation: WAAPIAnimation = {\n    timings: sanitizeTimings(timings),\n    keyframes,\n    targetLeafElement,\n    useClippingContainer: withClippingContainer,\n  };\n\n  const animationStyle = targetLeafElement\n    ? {}\n    : getInitialStyleFromKeyframes(keyframes);\n\n  const AMPTarget: VoidFunctionComponent<AMPAnimationProps> = ({\n    children,\n    style = {},\n  }) => (\n    <WithAnimation\n      id={id}\n      className=\"animation-wrapper\"\n      useClippingContainer={withClippingContainer}\n      style={style}\n      animationStyle={animationStyle}\n    >\n      {children}\n    </WithAnimation>\n  );\n\n  const selector = targetLeafElement\n    ? `#${id} [data-leaf-element=\"true\"]`\n    : `#${id}`;\n\n  const AMPAnimation: VoidFunctionComponent = () => (\n    <AnimationOutput config={{ selector, keyframes, ...timings }} />\n  );\n\n  return {\n    id,\n    keyframes,\n    generatedKeyframes: { [id]: keyframes },\n    WAAPIAnimation,\n    AMPTarget,\n    AMPAnimation,\n  };\n}\n\nexport default createAnimation;\n"
  },
  {
    "path": "packages/animation/src/parts/createAnimationPart.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { BEZIER } from '../constants';\nimport {\n  type AnimationInput,\n  type AnimationInputWithPreset,\n  AnimationType,\n  type Element,\n} from '../types';\nimport { EffectDrop } from './effects/drop';\nimport { EffectFadeIn } from './effects/fadeIn';\nimport { EffectFlyIn } from './effects/flyIn';\nimport { EffectPan } from './effects/pan';\nimport { EffectPulse } from './effects/pulse';\nimport { EffectTwirlIn } from './effects/twirlIn';\nimport { EffectWhooshIn } from './effects/whooshIn';\nimport { EffectZoom } from './effects/zoom';\nimport { EffectRotateIn } from './effects/rotateIn';\nimport { EffectBackgroundZoom } from './effects/backgroundZoom';\nimport { EffectBackgroundPan } from './effects/backgroundPan';\nimport { EffectBackgroundPanAndZoom } from './effects/backgroundPanAndZoom';\n\nimport { AnimationBounce } from './simple/bounce';\nimport { AnimationBlinkOn } from './simple/blinkOn';\nimport { AnimationFade } from './simple/fade';\nimport { AnimationFlip } from './simple/flip';\nimport { AnimationFloatOn } from './simple/floatOn';\nimport { AnimationMove } from './simple/move';\nimport { AnimationPulse } from './simple/pulse';\nimport { AnimationSpin } from './simple/spin';\nimport { AnimationZoom } from './simple/zoom';\n\nimport type { AnimationPart } from './types';\nimport emptyAnimationPart from './emptyAnimationPart';\n\nfunction convertEasingPreset({\n  easingPreset,\n  easing,\n  ...rest\n}: AnimationInputWithPreset): AnimationInput {\n  return {\n    ...rest,\n    easing: easing ? easing : easingPreset ? BEZIER[easingPreset] : undefined,\n  };\n}\n\n// eslint-disable-next-line complexity -- Just a large switch\nfunction createAnimationPart(\n  animationWithPreset: AnimationInputWithPreset,\n  element: Element\n): AnimationPart {\n  const animation = convertEasingPreset(animationWithPreset);\n\n  switch (animation.type) {\n    case AnimationType.BlinkOn:\n      return AnimationBlinkOn(animation);\n    case AnimationType.Bounce:\n      return AnimationBounce(animation);\n    case AnimationType.Fade:\n      return AnimationFade(animation);\n    case AnimationType.Flip:\n      return AnimationFlip(animation);\n    case AnimationType.FloatOn:\n      return AnimationFloatOn(animation);\n    case AnimationType.Move:\n      return AnimationMove(animation, element);\n    case AnimationType.Pulse:\n      return AnimationPulse(animation);\n    case AnimationType.Spin:\n      return AnimationSpin(animation, element);\n    case AnimationType.Zoom:\n      return AnimationZoom(animation);\n    case AnimationType.EffectDrop:\n      return EffectDrop(animation, element);\n    case AnimationType.EffectFadeIn:\n      return EffectFadeIn(animation);\n    case AnimationType.EffectFlyIn:\n      return EffectFlyIn(animation, element);\n    case AnimationType.EffectPan:\n      return EffectPan(animation, element);\n    case AnimationType.EffectPulse:\n      return EffectPulse(animation);\n    case AnimationType.EffectRotateIn:\n      return EffectRotateIn(animation, element);\n    case AnimationType.EffectTwirlIn:\n      return EffectTwirlIn(animation, element);\n    case AnimationType.EffectWhooshIn:\n      return EffectWhooshIn(animation, element);\n    case AnimationType.EffectZoom:\n      return EffectZoom(animation);\n    case AnimationType.EffectBackgroundPan:\n      return EffectBackgroundPan(animation, element);\n    case AnimationType.EffectBackgroundPanAndZoom:\n      return EffectBackgroundPanAndZoom(animation, element);\n    case AnimationType.EffectBackgroundZoom:\n      return EffectBackgroundZoom(animation, element);\n    default:\n      return emptyAnimationPart();\n  }\n}\n\nexport default createAnimationPart;\n"
  },
  {
    "path": "packages/animation/src/parts/defaultFields.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { BEZIER } from '../constants';\nimport { FieldType, NonBackgroundAnimationType } from '../types';\n\nexport const basicAnimationFields = {\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 1000,\n  },\n  delay: {\n    label: __('Delay', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 0,\n  },\n};\n\nexport const allFields = {\n  id: {\n    type: FieldType.Hidden,\n  },\n  type: {\n    label: __('Animation Type', 'web-stories'),\n    type: FieldType.Dropdown,\n    values: [NonBackgroundAnimationType],\n  },\n  ...basicAnimationFields,\n  direction: {\n    type: FieldType.Dropdown,\n    values: ['normal', 'reverse', 'alternate', 'alternate-reverse'],\n    defaultValue: 'normal',\n  },\n  easingPreset: {\n    label: __('Easing Presets', 'web-stories'),\n    type: FieldType.Dropdown,\n    values: ['Use Default', ...Object.keys(BEZIER)],\n    defaultValue: Object.keys(BEZIER)[0],\n  },\n  easing: {\n    type: FieldType.Text,\n  },\n  fill: {\n    type: FieldType.Dropdown,\n    values: ['backwards', 'forwards', 'both', 'none'],\n    defaultValue: 'forwards',\n  },\n  iterations: {\n    tooltip: __(\n      'Valid values are numerical or the word \"infinity\"',\n      'web-stories'\n    ),\n    type: FieldType.Text,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/backgroundPan.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport createAnimation from '../createAnimation';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  type AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport { getElementOffsets } from '../../utils';\n\nexport interface PanBackgroundEffect extends AMPEffectTiming {\n  panDir?: AnimationDirection;\n  type: AnimationType.EffectBackgroundPan;\n}\n\nexport function EffectBackgroundPan(\n  {\n    panDir = AnimationDirection.RightToLeft,\n    duration = 2000,\n    easing = 'cubic-bezier(.3,0,.55,1)',\n    type,\n    ...args\n  }: PanBackgroundEffect,\n  element: Element\n) {\n  const timings: AMPEffectTiming = {\n    fill: 'both',\n    duration,\n    easing,\n    ...args,\n  };\n\n  const translateToOriginX = 'translate3d(0%, 0, 0)';\n  const translateToOriginY = 'translate3d(0, 0%, 0)';\n  const offsets = element\n    ? getElementOffsets(element)\n    : { top: 0, right: 0, bottom: 0, left: 0 };\n  const translate = {\n    from: {\n      [AnimationDirection.RightToLeft]: `translate3d(${offsets.left}%, 0, 0)`,\n      [AnimationDirection.LeftToRight]: `translate3d(${offsets.right}%, 0, 0)`,\n      [AnimationDirection.BottomToTop]: `translate3d(0, ${offsets.top}%, 0)`,\n      [AnimationDirection.TopToBottom]: `translate3d(0, ${offsets.bottom}%, 0)`,\n    },\n    to: {\n      [AnimationDirection.RightToLeft]: translateToOriginX,\n      [AnimationDirection.LeftToRight]: translateToOriginX,\n      [AnimationDirection.BottomToTop]: translateToOriginY,\n      [AnimationDirection.TopToBottom]: translateToOriginY,\n    },\n  };\n\n  const keyframes = {\n    transform: [translate.from[panDir], translate.to[panDir]],\n  };\n\n  return createAnimation(keyframes, timings, false, true);\n}\n\nexport const fields = {\n  panDir: {\n    label: __('Direction', 'web-stories'),\n    tooltip: sprintf(\n      /* translators: 1: scaleIn. 2: scaleOut */\n      __('Valid values are %1$s or %2$s', 'web-stories'),\n      'scaleIn',\n      'scaleOut'\n    ),\n    type: FieldType.DirectionPicker,\n    values: [\n      AnimationDirection.TopToBottom,\n      AnimationDirection.BottomToTop,\n      AnimationDirection.LeftToRight,\n      AnimationDirection.RightToLeft,\n    ],\n    defaultValue: AnimationDirection.RightToLeft,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 2000,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/backgroundPanAndZoom.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createAnimation from '../createAnimation';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  AnimationType,\n  type Element,\n  ScaleDirection,\n} from '../../types';\nimport { getElementOrigin, getElementOffsets } from '../../utils';\nimport { EffectBackgroundPan } from './backgroundPan';\nimport { EffectBackgroundZoom } from './backgroundZoom';\n\nconst defaults: AMPEffectTiming = {\n  fill: 'forwards',\n  duration: 2000,\n  easing: 'cubic-bezier(.14,.34,.47,.9)',\n};\n\nexport interface PanAndZoomBackgroundEffect extends AMPEffectTiming {\n  zoomDirection?: ScaleDirection;\n  panDir?: AnimationDirection;\n  type: AnimationType.EffectBackgroundPanAndZoom;\n}\n\nexport function EffectBackgroundPanAndZoom(\n  {\n    zoomDirection = ScaleDirection.ScaleIn,\n    panDir = AnimationDirection.RightToLeft,\n    type,\n    ...args\n  }: PanAndZoomBackgroundEffect,\n  element: Element\n) {\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n\n  // We have to move the origin with respect to the pan\n  // direction and the current element position relative to\n  // the frame. This prevents area from ever being shown\n  // where the element does't fill the frame during scaling\n  const origin = getElementOrigin(element && getElementOffsets(element));\n  const transformOrigin =\n    {\n      [AnimationDirection.RightToLeft]: {\n        horizontal: 0,\n        vertical: origin.vertical,\n      },\n      [AnimationDirection.LeftToRight]: {\n        horizontal: 100,\n        vertical: origin.vertical,\n      },\n      [AnimationDirection.BottomToTop]: {\n        horizontal: origin.horizontal,\n        vertical: 0,\n      },\n      [AnimationDirection.TopToBottom]: {\n        horizontal: origin.horizontal,\n        vertical: 100,\n      },\n    }[panDir] || [];\n\n  // Background animations aren't really composable through element nesting\n  // because they all target the same dom node. To accommomdate for this we\n  // manually compose the keyframes and use those to generate a new animation.\n  const bgZoom = EffectBackgroundZoom(\n    {\n      zoomDirection,\n      transformOrigin,\n      type: AnimationType.EffectBackgroundZoom,\n      ...args,\n    },\n    element\n  );\n  const bgPan = EffectBackgroundPan(\n    {\n      panDir,\n      type: AnimationType.EffectBackgroundPan,\n      ...args,\n    },\n    element\n  );\n\n  const startTransform = `${bgPan.keyframes.transform[0]} ${bgZoom.keyframes.transform[0]}`;\n  const zoomLastTransformIndex = (bgZoom.keyframes.transform.length || 1) - 1;\n  const panLastTransformIndex = (bgPan.keyframes.transform.length || 1) - 1;\n  const endTransform = `${bgPan.keyframes.transform[zoomLastTransformIndex]} ${bgZoom.keyframes.transform[panLastTransformIndex]}`;\n\n  const keyframes = { transform: [startTransform, endTransform] };\n\n  return createAnimation(keyframes, timings, false, true);\n}\n\nexport { fields } from './backgroundPan';\n"
  },
  {
    "path": "packages/animation/src/parts/effects/backgroundZoom.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { clamp, progress, lerp } from '@googleforcreators/units';\nimport { sprintf, _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { BG_MIN_SCALE, BG_MAX_SCALE } from '../../constants';\nimport { getElementOffsets, getElementOrigin } from '../../utils';\nimport { AnimationZoom } from '../simple/zoom';\nimport {\n  type AMPEffectTiming,\n  AnimationType,\n  type Element,\n  FieldType,\n  isScaledElement,\n  ScaleDirection,\n} from '../../types';\n\ntype TransformOrigin = {\n  vertical: number;\n  horizontal: number;\n};\n\nexport interface ZoomBackgroundEffect extends AMPEffectTiming {\n  type: AnimationType.EffectBackgroundZoom;\n  zoomDirection?: ScaleDirection;\n  transformOrigin?: TransformOrigin;\n}\n\nexport function EffectBackgroundZoom(\n  {\n    zoomDirection = ScaleDirection.ScaleOut,\n    transformOrigin,\n    duration = 2000,\n    delay = 0,\n    easing = 'cubic-bezier(.3,0,.55,1)',\n  }: ZoomBackgroundEffect,\n  element: Element\n) {\n  // Define the min/max range based off the element scale\n  // at element scale 400, the range should be [1/4, 1]\n  // at element scale 100, the range should be [1, 4]\n  if (!isScaledElement(element)) {\n    throw new Error('Should not happen');\n  }\n\n  const range = {\n    MIN: BG_MIN_SCALE / (element.scale || 1),\n    MAX: BG_MAX_SCALE / (element.scale || 1),\n  };\n\n  // Compute what a 50% difference is relative to [0%, 400%]\n  const normalizedDelta = progress(50, { MIN: 0, MAX: BG_MAX_SCALE });\n  // Interpret the normalized delta into the compounded scale coordinate space.\n  const delta = lerp(normalizedDelta, { MIN: 0, MAX: range.MAX });\n  // Apply the interpreted fixed delta to the elements scale\n  const zoomFrom =\n    1 + (zoomDirection === ScaleDirection.ScaleOut ? 1 : -1) * delta;\n\n  return AnimationZoom({\n    type: AnimationType.Zoom,\n    // make sure we stay within min/max range so image always fills canvas\n    zoomFrom: clamp(zoomFrom, range),\n    zoomTo: 1,\n    duration,\n    delay,\n    easing,\n    targetLeafElement: true,\n    // Account for moving bg element relative to frame\n    transformOrigin:\n      transformOrigin ||\n      getElementOrigin(element && getElementOffsets(element)),\n  });\n}\n\nexport const fields = {\n  zoomDirection: {\n    label: __('Direction', 'web-stories'),\n    tooltip: sprintf(\n      /* translators: 1: scaleIn. 2: scaleOut */\n      __('Valid values are %1$s or %2$s', 'web-stories'),\n      'scaleIn',\n      'scaleOut'\n    ),\n    type: FieldType.DirectionPicker,\n    values: [ScaleDirection.ScaleIn, ScaleDirection.ScaleOut],\n    defaultValue: ScaleDirection.ScaleOut,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 2000,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/drop.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x, __ } from '@googleforcreators/i18n';\nimport type { DimensionableElement } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport createAnimation from '../createAnimation';\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  type Element,\n  FieldType,\n  type Keyframes,\n} from '../../types';\nimport { getGlobalSpace, getOffPageOffset } from '../../utils';\n\nfunction getMinTopOffset(element: DimensionableElement) {\n  return getOffPageOffset({ ...element, y: 160 }).offsetTop;\n}\n\nfunction getDropKeyframes(element: DimensionableElement): Keyframes {\n  const minTop = getMinTopOffset(element);\n  const { offsetTop } = getOffPageOffset(element);\n  const global = getGlobalSpace(element);\n  const maxBounceHeight = -Math.max(Math.abs(minTop), Math.abs(offsetTop));\n  return [\n    {\n      offset: 0,\n      transform: global`translate3d(0, ${maxBounceHeight}%, 0)`,\n      easing: 'cubic-bezier(.5, 0, 1, 1)',\n    },\n    {\n      offset: 0.29,\n      transform: global`translate3d(0, 0%, 0)`,\n      easing: 'cubic-bezier(0, 0, .5, 1)',\n    },\n    {\n      offset: 0.45,\n      transform: global`translate3d(0, ${0.2812 * maxBounceHeight}%, 0)`,\n      easing: 'cubic-bezier(.5, 0, 1, 1)',\n    },\n    {\n      offset: 0.61,\n      transform: global`translate3d(0, 0%, 0)`,\n      easing: 'cubic-bezier(0, 0, .5, 1)',\n    },\n    {\n      offset: 0.71,\n      transform: global`translate3d(0, ${0.0956 * maxBounceHeight}%, 0)`,\n      easing: 'cubic-bezier(.5, 0, 1, 1)',\n    },\n    {\n      offset: 0.8,\n      transform: global`translate3d(0, 0%, 0)`,\n      easing: 'cubic-bezier(0, 0, .5, 1)',\n    },\n    {\n      offset: 0.85,\n      transform: global`translate3d(0, ${0.0359 * maxBounceHeight}%, 0)`,\n      easing: 'cubic-bezier(.5, 0, 1, 1)',\n    },\n    {\n      offset: 0.92,\n      transform: global`translate3d(0, 0%, 0)`,\n      easing: 'cubic-bezier(0, 0, .5, 1)',\n    },\n    {\n      offset: 0.96,\n      transform: global`translate3d(0, ${0.0156 * maxBounceHeight}%, 0)`,\n      easing: 'cubic-bezier(.5, 0, 1, 1)',\n    },\n    {\n      offset: 1,\n      transform: global`translate3d(0, 0%, 0)`,\n      easing: 'cubic-bezier(0, 0, .5, 1)',\n    },\n  ];\n}\n\nexport interface DropEffect extends AMPEffectTiming {\n  type: AnimationType.EffectDrop;\n}\n\nexport function EffectDrop(\n  { fill = 'both', duration = 1600, delay = 0 }: DropEffect,\n  element: Element\n) {\n  const timings: AMPEffectTiming = { fill, duration, delay };\n  const keyframes = getDropKeyframes(element);\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  duration: {\n    tooltip: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 600,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/fadeIn.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AnimationFade } from '../simple/fade';\nimport { type AMPEffectTiming, AnimationType, FieldType } from '../../types';\n\nexport interface FadeInEffect extends AMPEffectTiming {\n  type: AnimationType.EffectFadeIn;\n}\nexport function EffectFadeIn({\n  duration = 600,\n  delay = 0,\n  easing = 'cubic-bezier(0.4, 0.4, 0.0, 1)',\n}: FadeInEffect) {\n  return AnimationFade({\n    fadeFrom: 0,\n    fadeTo: 1,\n    duration,\n    delay,\n    easing,\n    type: AnimationType.Fade,\n  });\n}\n\nexport const fields = {\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 600,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/flyIn.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport type { CSSProperties, PropsWithChildren } from 'react';\nimport { _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AnimationMove } from '../simple/move';\nimport { AnimationFade } from '../simple/fade';\nimport { getOffPageOffset } from '../../utils';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport type { AnimationPart } from '../types';\n\nexport interface FlyInEffect extends AMPEffectTiming {\n  flyInDir?: AnimationDirection;\n  type: AnimationType.EffectFlyIn;\n}\n\nexport function EffectFlyIn(\n  {\n    flyInDir = AnimationDirection.TopToBottom,\n    duration = 600,\n    delay = 0,\n    easing = 'cubic-bezier(0.2, 0.6, 0.0, 1)',\n  }: FlyInEffect,\n  element: Element\n): AnimationPart {\n  const id = uuidv4();\n  const { offsetTop, offsetLeft, offsetRight, offsetBottom } =\n    getOffPageOffset(element);\n\n  const offsetLookup = {\n    [AnimationDirection.TopToBottom]: {\n      offsetY: `${offsetTop}%`,\n    },\n    [AnimationDirection.BottomToTop]: {\n      offsetY: `${offsetBottom}%`,\n    },\n    [AnimationDirection.LeftToRight]: {\n      offsetX: `${offsetLeft}%`,\n    },\n    [AnimationDirection.RightToLeft]: {\n      offsetX: `${offsetRight}%`,\n    },\n  };\n\n  const fade = AnimationFade({\n    fadeFrom: 0,\n    fadeTo: 1,\n    duration: duration,\n    delay,\n    easing,\n    type: AnimationType.Fade,\n  });\n\n  const move = AnimationMove(\n    {\n      ...offsetLookup[flyInDir],\n      duration,\n      delay,\n      easing,\n      type: AnimationType.Move,\n    },\n    element\n  );\n\n  const keyframes = {\n    ...move.keyframes,\n    ...fade.keyframes,\n  };\n\n  return {\n    id,\n    keyframes,\n    WAAPIAnimation: {\n      ...move.WAAPIAnimation,\n      keyframes,\n    },\n    AMPTarget: function AMPTarget({\n      children,\n      style,\n    }: PropsWithChildren<{ style?: CSSProperties }>) {\n      return (\n        <fade.AMPTarget style={style}>\n          <move.AMPTarget style={style}>{children}</move.AMPTarget>\n        </fade.AMPTarget>\n      );\n    },\n    AMPAnimation: function AMPAnimation() {\n      return (\n        <>\n          <fade.AMPAnimation />\n          <move.AMPAnimation />\n        </>\n      );\n    },\n    generatedKeyframes: {\n      ...fade.generatedKeyframes,\n      ...move.generatedKeyframes,\n    },\n  };\n}\n\nexport const fields = {\n  flyInDir: {\n    label: __('Direction', 'web-stories'),\n    type: FieldType.DirectionPicker,\n    values: [\n      AnimationDirection.TopToBottom,\n      AnimationDirection.BottomToTop,\n      AnimationDirection.LeftToRight,\n      AnimationDirection.RightToLeft,\n    ],\n    defaultValue: AnimationDirection.BottomToTop,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 600,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/pan.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  PAGE_WIDTH,\n  FULLBLEED_HEIGHT,\n  DANGER_ZONE_HEIGHT,\n  dataToEditorY,\n  getBox,\n  type ElementBox,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport createAnimation from '../createAnimation';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  type AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\n\nfunction getTargetScale({ width, height }: ElementBox) {\n  if (width < PAGE_WIDTH || height < FULLBLEED_HEIGHT) {\n    const scaleFactor = 1.25;\n\n    const widthScale = width < PAGE_WIDTH ? PAGE_WIDTH / width : 1;\n    const heightScale =\n      height < FULLBLEED_HEIGHT ? FULLBLEED_HEIGHT / height : 1;\n\n    return Math.max(widthScale, heightScale) * scaleFactor;\n  }\n\n  return 1;\n}\n\nexport interface PanEffect extends AMPEffectTiming {\n  panDir?: AnimationDirection;\n  type: AnimationType.EffectPan;\n}\n\nexport function EffectPan(\n  {\n    panDir = AnimationDirection.RightToLeft,\n    duration = 1000,\n    delay,\n    easing,\n  }: PanEffect,\n  element: Element\n) {\n  const timings: AMPEffectTiming = {\n    fill: 'both',\n    duration,\n    delay,\n    easing,\n  };\n\n  const scale = getTargetScale(element);\n  const scaledElement: ElementBox = {\n    x: element.x,\n    y: element.y,\n    width: element.width * scale,\n    height: element.height * scale,\n    rotationAngle: element.rotationAngle,\n  };\n\n  const { x, y, width, height } = getBox(scaledElement, 100, 100);\n  const dangerZoneOffset = dataToEditorY(DANGER_ZONE_HEIGHT, 100);\n\n  const alignTop = -((dangerZoneOffset + y) / height) * 100.0;\n  const alignRight = ((100 - (x + width)) / width) * 100.0;\n  const alignLeft = -(x / width) * 100.0;\n  const alignBottom =\n    ((100 - (y + height) + dangerZoneOffset) / height) * 100.0;\n\n  let startX, startY, endX, endY;\n\n  switch (panDir) {\n    case AnimationDirection.TopToBottom:\n      startX = (alignLeft + alignRight) / 2;\n      startY = alignTop;\n      endX = (alignLeft + alignRight) / 2;\n      endY = alignBottom;\n      break;\n    case AnimationDirection.BottomToTop:\n      startX = (alignLeft + alignRight) / 2;\n      startY = alignBottom;\n      endX = (alignLeft + alignRight) / 2;\n      endY = alignTop;\n      break;\n    case AnimationDirection.LeftToRight:\n      startX = alignLeft;\n      startY = alignTop;\n      endX = alignRight;\n      endY = alignTop;\n      break;\n    case AnimationDirection.RightToLeft:\n    default:\n      startX = alignRight;\n      startY = alignTop;\n      endX = alignLeft;\n      endY = alignTop;\n  }\n\n  const keyframes = {\n    transform: [\n      `translate(${startX}%, ${startY}%) scale(${scale})`,\n      `translate(${endX}%, ${endY}%) scale(${scale})`,\n    ],\n    'transform-origin': 'left top',\n  };\n\n  return createAnimation(keyframes, timings, false);\n}\n\nexport const fields = {\n  panDir: {\n    label: __('Direction', 'web-stories'),\n    type: FieldType.DirectionPicker,\n    values: [\n      AnimationDirection.TopToBottom,\n      AnimationDirection.BottomToTop,\n      AnimationDirection.LeftToRight,\n      AnimationDirection.RightToLeft,\n    ],\n    defaultValue: AnimationDirection.BottomToTop,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/pulse.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AnimationPulse } from '../simple/pulse';\nimport { type AMPEffectTiming, AnimationType, FieldType } from '../../types';\n\nexport interface PulseEffect extends AMPEffectTiming {\n  scale?: number;\n  type: AnimationType.EffectPulse;\n}\n\nexport function EffectPulse({\n  iterations = 1,\n  scale = 0.5,\n  duration = 1450,\n  delay,\n  easing = 'ease-in-out',\n}: PulseEffect) {\n  return AnimationPulse({\n    scale,\n    duration,\n    delay,\n    easing,\n    iterations,\n    type: AnimationType.Pulse,\n  });\n}\n\nexport const fields = {\n  scale: {\n    label: __('Scale', 'web-stories'),\n    tooltip: 'Valid values are greater than or equal to 0',\n    type: FieldType.Float,\n    defaultValue: 0.5,\n  },\n  iterations: {\n    label: _x('Pulses', 'number of pulses', 'web-stories'),\n    type: FieldType.Float,\n    defaultValue: 1,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 1450,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/rotateIn.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { CSSProperties, PropsWithChildren } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from '../types';\nimport { AnimationMove } from '../simple/move';\nimport { AnimationSpin } from '../simple/spin';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport { getOffPageOffset } from '../../utils';\n\nconst numberOfRotations = 1;\nconst stopAngle = 0;\n\nexport interface RotateInEffect extends AMPEffectTiming {\n  rotateInDir?: AnimationDirection;\n  type: AnimationType.EffectRotateIn;\n}\n\nexport function EffectRotateIn(\n  {\n    rotateInDir = AnimationDirection.LeftToRight,\n    duration = 1000,\n    easing = 'cubic-bezier(.2, 0, .8, 1)',\n    delay,\n  }: RotateInEffect,\n  element: Element\n): AnimationPart {\n  const id = uuidv4();\n\n  const { offsetLeft, offsetRight } = getOffPageOffset(element);\n\n  const offsetX =\n    rotateInDir === AnimationDirection.RightToLeft\n      ? `${offsetRight}%`\n      : `${offsetLeft}%`;\n\n  const move = AnimationMove(\n    {\n      offsetX,\n      duration,\n      delay,\n      easing,\n      type: AnimationType.Move,\n    },\n    element\n  );\n\n  const spin = AnimationSpin(\n    {\n      rotation: `${\n        (rotateInDir === AnimationDirection.LeftToRight ? -1 : 1) *\n        180 *\n        numberOfRotations\n      }`,\n      stopAngle,\n      duration,\n      delay,\n      easing: 'cubic-bezier(.2, 0, .5, 1)',\n      type: AnimationType.Spin,\n    },\n    element\n  );\n\n  const [moveTransformStart, moveTransformEnd] = move.keyframes.transform;\n  const [spinTransformStart, spinTransformEnd] = spin.keyframes.transform;\n  const keyframes = {\n    transform: [\n      `${moveTransformStart} ${spinTransformStart}`,\n      `${moveTransformEnd} ${spinTransformEnd}`,\n    ],\n  };\n\n  return {\n    id,\n    keyframes,\n    WAAPIAnimation: {\n      ...spin.WAAPIAnimation,\n      keyframes,\n    },\n    AMPTarget: function AMPTarget({\n      children,\n      style,\n    }: PropsWithChildren<{ style?: CSSProperties }>) {\n      return (\n        <move.AMPTarget style={style}>\n          <spin.AMPTarget style={style}>{children}</spin.AMPTarget>\n        </move.AMPTarget>\n      );\n    },\n    AMPAnimation: function AMPAnimation() {\n      return (\n        <>\n          <move.AMPAnimation />\n          <spin.AMPAnimation />\n        </>\n      );\n    },\n    generatedKeyframes: {\n      ...move.generatedKeyframes,\n      ...spin.generatedKeyframes,\n    },\n  };\n}\n\nexport const fields = {\n  rotateInDir: {\n    label: __('Direction', 'web-stories'),\n    type: FieldType.DirectionPicker,\n    values: [AnimationDirection.LeftToRight, AnimationDirection.RightToLeft],\n    defaultValue: AnimationDirection.LeftToRight,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/drop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PAGE_HEIGHT, PAGE_WIDTH, getBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport {\n  AMPStoryWrapper,\n  AMP_STORY_ASPECT_RATIO,\n} from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Drop',\n};\n\nconst elements = [\n  {\n    id: 'e1',\n    color: 'red',\n    x: (PAGE_WIDTH - 50) / 2,\n    y: PAGE_HEIGHT - 50,\n    width: 50,\n    height: 50,\n  },\n];\n\nconst animations = [\n  { id: '1', targets: ['e1'], type: AnimationType.EffectDrop },\n];\n\nexport const _default = {\n  render: function Render() {\n    const elementBoxes = elements.map((element) => ({\n      ...element,\n      ...getBox(element, 100, 100),\n    }));\n\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id=\"page-1\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'AMP Drop Effect'}\n          </p>\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ration={AMP_STORY_ASPECT_RATIO}\n          >\n            <div\n              animate-in=\"drop\"\n              style={{\n                position: 'absolute',\n                height: '50px',\n                width: '50px',\n                top: 'calc(100% - 50px)',\n                left: 'calc(50% - 25px)',\n                backgroundColor: 'red',\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id=\"page-2\">\n          <StoryAnimation.AnimationProvider\n            animations={animations}\n            elements={elements}\n          >\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Drop Effect'}\n            </p>\n\n            <amp-story-grid-layer\n              template=\"vertical\"\n              aspect-ration={AMP_STORY_ASPECT_RATIO}\n            >\n              <div className=\"page-fullbleed-area\">\n                <div className=\"page-safe-area\">\n                  {elementBoxes.map((elem) => (\n                    <div\n                      key={elem.id}\n                      style={{\n                        position: 'absolute',\n                        top: `${elem.y}%`,\n                        left: `${elem.x}%`,\n                        width: `${elem.width}%`,\n                        height: `${elem.height}%`,\n                      }}\n                    >\n                      <StoryAnimation.AMPWrapper target={elem.id}>\n                        <div\n                          style={{\n                            height: '100%',\n                            width: '100%',\n                            backgroundColor: elem.color,\n                          }}\n                        />\n                      </StoryAnimation.AMPWrapper>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/fadeIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Fade-In',\n};\n\nconst animations = [\n  { id: '1', targets: ['e1'], type: AnimationType.EffectFade, duration: 1000 },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Fade,\n    duration: 2500,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red' },\n  { id: 'e2', color: 'orange' },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>{'AMP Fade In'}</p>\n\n          <amp-story-grid-layer template=\"horizontal\">\n            <div\n              animate-in=\"fade-in\"\n              animate-in-duration=\"1s\"\n              style={{\n                backgroundColor: 'red',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"fade-in\"\n              animate-in-duration=\"2.5s\"\n              style={{\n                backgroundColor: 'orange',\n                ...defaultStyles,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider animations={animations}>\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Fade In Effect'}\n            </p>\n\n            <amp-story-grid-layer template=\"horizontal\">\n              {elements.map(({ id, color }) => (\n                <div key={id} style={defaultStyles}>\n                  <StoryAnimation.AMPWrapper target={id}>\n                    <div\n                      style={{\n                        width: '100%',\n                        height: '100%',\n                        backgroundColor: color,\n                      }}\n                    />\n                  </StoryAnimation.AMPWrapper>\n                </div>\n              ))}\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/flyIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, AnimationDirection } from '../../../types';\nimport {\n  AMPStoryWrapper,\n  AMP_STORY_ASPECT_RATIO,\n} from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Fly-In',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectFlyIn,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.EffectFlyIn,\n    delay: 500,\n    flyInDir: AnimationDirection.LeftToRight,\n  },\n  {\n    id: '3',\n    targets: ['e3'],\n    type: AnimationType.EffectFlyIn,\n    delay: 1000,\n    flyInDir: AnimationDirection.RightToLeft,\n  },\n  {\n    id: '4',\n    targets: ['e4'],\n    type: AnimationType.EffectFlyIn,\n    delay: 1500,\n    flyInDir: AnimationDirection.BottomToTop,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', x: 50, y: 100, width: 50, height: 50 },\n  { id: 'e2', color: 'orange', x: 50, y: 175, width: 50, height: 50 },\n  { id: 'e3', color: 'blue', x: 50, y: 250, width: 50, height: 50 },\n  { id: 'e4', color: 'yellow', x: 50, y: 325, width: 50, height: 50 },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    const elementBoxes = elements.map((element) => ({\n      ...element,\n      ...getBox(element, 100, 100),\n    }));\n\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>{'AMP Fly In'}</p>\n\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ratio={AMP_STORY_ASPECT_RATIO}\n          >\n            <div\n              animate-in=\"fly-in-top\"\n              style={{\n                backgroundColor: 'red',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"fly-in-left\"\n              animate-in-delay=\"0.5s\"\n              style={{\n                backgroundColor: 'orange',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"fly-in-right\"\n              animate-in-delay=\"1.0s\"\n              style={{\n                backgroundColor: 'blue',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"fly-in-bottom\"\n              animate-in-delay=\"1.5s\"\n              style={{\n                backgroundColor: 'yellow',\n                ...defaultStyles,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider\n            animations={animations}\n            elements={elements}\n          >\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Fly In Effect'}\n            </p>\n\n            <amp-story-grid-layer\n              template=\"vertical\"\n              aspect-ratio={AMP_STORY_ASPECT_RATIO}\n            >\n              <div className=\"page-fullbleed-area\">\n                <div className=\"page-safe-area\">\n                  {elementBoxes.map(({ id, color, x, y, width, height }) => (\n                    <div\n                      key={id}\n                      style={{\n                        position: 'absolute',\n                        top: `${y}%`,\n                        left: `${x}%`,\n                        width: `${width}%`,\n                        height: `${height}%`,\n                      }}\n                    >\n                      <StoryAnimation.AMPWrapper target={id}>\n                        <div\n                          style={{\n                            width: '100%',\n                            height: '100%',\n                            backgroundColor: color,\n                          }}\n                        />\n                      </StoryAnimation.AMPWrapper>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/pan.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, AnimationDirection } from '../../../types';\nimport {\n  AMPStoryWrapper,\n  AMP_STORY_ASPECT_RATIO,\n} from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Pan',\n};\n\nconst SAMPLE_SRC_1 = 'https://picsum.photos/1120/746?image=1025';\n\nconst animations = [\n  {\n    id: '2',\n    targets: ['e1'],\n    type: AnimationType.EffectPan,\n    panDir: AnimationDirection.TopToBottom,\n    duration: 5000,\n  },\n  {\n    id: '3',\n    targets: ['e1'],\n    type: AnimationType.EffectPan,\n    panDir: AnimationDirection.BottomToTop,\n    duration: 5000,\n  },\n  {\n    id: '4',\n    targets: ['e1'],\n    type: AnimationType.EffectPan,\n    panDir: AnimationDirection.LeftToRight,\n    duration: 5000,\n  },\n  {\n    id: '5',\n    targets: ['e1'],\n    type: AnimationType.EffectPan,\n    panDir: AnimationDirection.RightToLeft,\n    duration: 5000,\n  },\n];\n\nconst elements = [{ id: 'e1', x: 50, y: 100, width: 296, height: 198 }];\n\nexport const _default = {\n  render: function Render() {\n    const elementBoxes = elements.map((element) => ({\n      ...element,\n      ...getBox(element, 100, 100),\n    }));\n\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>{'AMP PAN'}</p>\n\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ratio={AMP_STORY_ASPECT_RATIO}\n          >\n            <amp-img\n              animate-in=\"pan-left\"\n              animate-in-duration=\"5s\"\n              src={SAMPLE_SRC_1}\n              width=\"296px\"\n              height=\"198px\"\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        {animations.map((animation) => (\n          <amp-story-page key={animation.id} id={`page-${animation.id}`}>\n            <StoryAnimation.AnimationProvider\n              animations={[animation]}\n              elements={elements}\n            >\n              <StoryAnimation.AMPAnimations />\n              <p style={{ textAlign: 'center', color: '#fff' }}>\n                {'Custom Pan Effect'}\n              </p>\n\n              <amp-story-grid-layer\n                template=\"vertical\"\n                aspect-ratio={AMP_STORY_ASPECT_RATIO}\n              >\n                <div className=\"page-fullbleed-area\">\n                  <div className=\"page-safe-area\">\n                    {elementBoxes.map(({ id, x, y, width, height }) => (\n                      <div\n                        key={id}\n                        style={{\n                          position: 'absolute',\n                          top: `${y}%`,\n                          left: `${x}%`,\n                          width: `${width}%`,\n                          height: `${height}%`,\n                        }}\n                      >\n                        <StoryAnimation.AMPWrapper target={id}>\n                          <img alt=\"\" src={SAMPLE_SRC_1} width=\"100%\" />\n                        </StoryAnimation.AMPWrapper>\n                      </div>\n                    ))}\n                  </div>\n                </div>\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/pulse.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Pulse',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectPulse,\n    delay: 500,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.EffectPulse,\n    iterations: 2,\n    scale: 1,\n    delay: 1000,\n  },\n  {\n    id: '3',\n    targets: ['e3'],\n    type: AnimationType.EffectPulse,\n    iterations: 3,\n    scale: 1.5,\n    delay: 2000,\n  },\n  {\n    id: '4',\n    targets: ['e4'],\n    type: AnimationType.EffectPulse,\n    iterations: 4,\n    scale: 2,\n    delay: 3500,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red' },\n  { id: 'e2', color: 'orange' },\n  { id: 'e3', color: 'blue' },\n  { id: 'e4', color: 'yellow' },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>{'AMP Pulse'}</p>\n\n          <amp-story-grid-layer template=\"vertical\">\n            <div\n              animate-in=\"pulse\"\n              animate-in-delay=\"0.5s\"\n              style={{\n                backgroundColor: 'red',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"pulse\"\n              animate-in-delay=\"1.0s\"\n              style={{\n                backgroundColor: 'orange',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"pulse\"\n              animate-in-delay=\"1.5s\"\n              style={{\n                backgroundColor: 'blue',\n                ...defaultStyles,\n              }}\n            />\n            <div\n              animate-in=\"pulse\"\n              animate-in-delay=\"2.0s\"\n              style={{\n                backgroundColor: 'yellow',\n                ...defaultStyles,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider animations={animations}>\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Pulse Effect'}\n            </p>\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {\n                'Only first element reflects amp-story preset, rest highlight greater configurability'\n              }\n            </p>\n\n            <amp-story-grid-layer template=\"vertical\">\n              {elements.map(({ id, color }) => (\n                <div key={id} style={defaultStyles}>\n                  <StoryAnimation.AMPWrapper target={id}>\n                    <div\n                      style={{\n                        width: '100%',\n                        height: '100%',\n                        backgroundColor: color,\n                      }}\n                    />\n                  </StoryAnimation.AMPWrapper>\n                </div>\n              ))}\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/rotateIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, AnimationDirection } from '../../../types';\nimport {\n  AMPStoryWrapper,\n  AMP_STORY_ASPECT_RATIO,\n} from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Rotate-In',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectRotateIn,\n    delay: 500,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.EffectRotateIn,\n    delay: 1000,\n    rotateInDir: AnimationDirection.RightToLeft,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', x: 315, y: 100, width: 50, height: 50 },\n  { id: 'e2', color: 'orange', x: 50, y: 175, width: 50, height: 50 },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    const elementBoxes = elements.map((element) => ({\n      ...element,\n      ...getBox(element, 100, 100),\n    }));\n\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'AMP Rotate-In'}\n          </p>\n\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ratio={AMP_STORY_ASPECT_RATIO}\n          >\n            <div\n              animate-in=\"rotate-in-left\"\n              animate-in-delay=\"0.5s\"\n              style={{\n                backgroundColor: 'red',\n                ...defaultStyles,\n                left: '250px',\n              }}\n            />\n            <div\n              animate-in=\"rotate-in-right\"\n              animate-in-delay=\"1.0s\"\n              style={{\n                backgroundColor: 'orange',\n                ...defaultStyles,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider\n            animations={animations}\n            elements={elements}\n          >\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Rotate-In Effect'}\n            </p>\n\n            <amp-story-grid-layer\n              template=\"vertical\"\n              aspect-ratio={AMP_STORY_ASPECT_RATIO}\n            >\n              <div className=\"page-fullbleed-area\">\n                <div className=\"page-safe-area\">\n                  {elementBoxes.map(({ id, color, x, y, width, height }) => (\n                    <div\n                      key={id}\n                      style={{\n                        position: 'absolute',\n                        top: `${y}%`,\n                        left: `${x}%`,\n                        width: `${width}%`,\n                        height: `${height}%`,\n                      }}\n                    >\n                      <StoryAnimation.AMPWrapper target={id}>\n                        <div\n                          style={{\n                            width: '100%',\n                            height: '100%',\n                            backgroundColor: color,\n                          }}\n                        />\n                      </StoryAnimation.AMPWrapper>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/twirlIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Twirl-In',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectTwirlIn,\n  },\n];\n\nconst element = {\n  id: 'e1',\n  color: 'red',\n  width: 50,\n  height: 50,\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>{'AMP Twirl In'}</p>\n\n          <amp-story-grid-layer template=\"vertical\">\n            <div\n              animate-in=\"twirl-in\"\n              style={{\n                position: 'absolute',\n                top: `calc(50% - ${element.height / 2}px)`,\n                left: `calc(50% - ${element.width / 2}px)`,\n                width: element.width,\n                height: element.height,\n                backgroundColor: element.color,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider animations={animations}>\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Twirl In Effect'}\n            </p>\n\n            <amp-story-grid-layer template=\"vertical\">\n              <div className=\"page-fullbleed-area\">\n                <div className=\"page-safe-area\">\n                  <div\n                    key={element.id}\n                    style={{\n                      position: 'absolute',\n                      top: `calc(50% - ${element.height / 2}px)`,\n                      left: `calc(50% - ${element.width / 2}px)`,\n                      width: element.width,\n                      height: element.height,\n                    }}\n                  >\n                    <StoryAnimation.AMPWrapper target={element.id}>\n                      <div\n                        style={{\n                          width: '100%',\n                          height: '100%',\n                          backgroundColor: element.color,\n                        }}\n                      />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                </div>\n              </div>\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/whooshIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, AnimationDirection } from '../../../types';\nimport {\n  AMPStoryWrapper,\n  AMP_STORY_ASPECT_RATIO,\n} from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Whoosh-In',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectWhooshIn,\n    delay: 500,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.EffectWhooshIn,\n    delay: 1000,\n    whooshInDir: AnimationDirection.RightToLeft,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', x: 315, y: 100, width: 50, height: 50 },\n  { id: 'e2', color: 'orange', x: 50, y: 175, width: 50, height: 50 },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    const elementBoxes = elements.map((element) => ({\n      ...element,\n      ...getBox(element, 100, 100),\n    }));\n\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'AMP Whoosh-In'}\n          </p>\n\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ratio={AMP_STORY_ASPECT_RATIO}\n          >\n            <div\n              animate-in=\"whoosh-in-left\"\n              animate-in-delay=\"0.5s\"\n              style={{\n                backgroundColor: 'red',\n                ...defaultStyles,\n                left: '250px',\n              }}\n            />\n            <div\n              animate-in=\"whoosh-in-right\"\n              animate-in-delay=\"1.0s\"\n              style={{\n                backgroundColor: 'orange',\n                ...defaultStyles,\n              }}\n            />\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider\n            animations={animations}\n            elements={elements}\n          >\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Whoosh-In Effect'}\n            </p>\n\n            <amp-story-grid-layer\n              template=\"vertical\"\n              aspect-ratio={AMP_STORY_ASPECT_RATIO}\n            >\n              <div className=\"page-fullbleed-area\">\n                <div className=\"page-safe-area\">\n                  {elementBoxes.map(({ id, color, x, y, width, height }) => (\n                    <div\n                      key={id}\n                      style={{\n                        position: 'absolute',\n                        top: `${y}%`,\n                        left: `${x}%`,\n                        width: `${width}%`,\n                        height: `${height}%`,\n                      }}\n                    >\n                      <StoryAnimation.AMPWrapper target={id}>\n                        <div\n                          style={{\n                            width: '100%',\n                            height: '100%',\n                            backgroundColor: color,\n                          }}\n                        />\n                      </StoryAnimation.AMPWrapper>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/stories/zoom.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, ScaleDirection } from '../../../types';\nimport { AMPStoryWrapper } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Effects/Zoom',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.EffectZoom,\n    scaleDirection: ScaleDirection.ScaleIn,\n    duration: 4000,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.EffectZoom,\n    scaleDirection: ScaleDirection.ScaleOut,\n    duration: 4000,\n  },\n];\n\nconst elements = [\n  {\n    id: 'e1',\n  },\n  {\n    id: 'e2',\n  },\n];\n\nconst defaultStyles = {\n  position: 'absolute',\n  left: `0%`,\n  top: `0%`,\n  width: '720px',\n  height: '320px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        <amp-story-page id={`page-1`}>\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'AMP Zoom In/Out'}\n          </p>\n\n          <amp-story-grid-layer template=\"vertical\">\n            <div style={defaultStyles}>\n              <amp-img\n                animate-in=\"zoom-in\"\n                scale-start=\"0.25\"\n                scale-end=\"1\"\n                animate-in-duration=\"4s\"\n                layout=\"fixed\"\n                src=\"https://picsum.photos/720/320?image=1026\"\n                width=\"720\"\n                height=\"320\"\n              />\n            </div>\n\n            <div\n              style={{\n                ...defaultStyles,\n                top: '50%',\n              }}\n            >\n              <amp-img\n                animate-in=\"zoom-out\"\n                scale-start=\"1\"\n                scale-end=\"0.25\"\n                animate-in-duration=\"4s\"\n                src=\"https://picsum.photos/720/320?image=1026\"\n                width=\"720\"\n                height=\"320\"\n              />\n            </div>\n          </amp-story-grid-layer>\n        </amp-story-page>\n        <amp-story-page id={`page-2`}>\n          <StoryAnimation.AnimationProvider animations={animations}>\n            <StoryAnimation.AMPAnimations />\n            <p style={{ textAlign: 'center', color: '#fff' }}>\n              {'Custom Zoom In/Out Effect'}\n            </p>\n\n            <amp-story-grid-layer template=\"vertical\">\n              {elements.map(({ id }, index) => (\n                <div\n                  key={id}\n                  style={{\n                    ...defaultStyles,\n                    top: `${index * 50}%`,\n                  }}\n                >\n                  <StoryAnimation.AMPWrapper target={id}>\n                    <amp-img\n                      src=\"https://picsum.photos/720/320?image=1026\"\n                      width=\"720\"\n                      height=\"320\"\n                    />\n                  </StoryAnimation.AMPWrapper>\n                </div>\n              ))}\n            </amp-story-grid-layer>\n          </StoryAnimation.AnimationProvider>\n        </amp-story-page>\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/twirlIn.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createAnimation from '../createAnimation';\nimport type { AMPEffectTiming, AnimationType, Element } from '../../types';\nimport { getGlobalSpace } from '../../utils';\n\nconst defaultTimings: AMPEffectTiming = {\n  delay: 0,\n  duration: 1000,\n  fill: 'both',\n  iterations: 1,\n  easing: 'cubic-bezier(0.4, 0.4, 0.0, 1)',\n};\n\nexport interface TwirlInEffect extends AMPEffectTiming {\n  type: AnimationType.EffectTwirlIn;\n}\n\nexport function EffectTwirlIn(\n  { type, ...args }: TwirlInEffect,\n  element: Element\n) {\n  const global = getGlobalSpace(element);\n  const keyframes = {\n    transform: [global`rotate(-540deg) scale(0.1)`, 'none'],\n    opacity: [0, 1],\n  };\n  const timings = { ...defaultTimings, ...args };\n  return createAnimation(keyframes, timings);\n}\n"
  },
  {
    "path": "packages/animation/src/parts/effects/whooshIn.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x, __ } from '@googleforcreators/i18n';\nimport type { CSSProperties, PropsWithChildren } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from '../types';\nimport { AnimationFade } from '../simple/fade';\nimport { AnimationMove } from '../simple/move';\nimport { AnimationZoom } from '../simple/zoom';\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport getOffPageOffset from '../../utils/getOffPageOffset';\n\nexport interface WhooshInEffect extends AMPEffectTiming {\n  whooshInDir?: AnimationDirection;\n  type: AnimationType.EffectWhooshIn;\n}\n\nexport function EffectWhooshIn(\n  {\n    whooshInDir = AnimationDirection.LeftToRight,\n    duration = 600,\n    easing = 'cubic-bezier(0.4, 0.4, 0.0, 1)',\n    delay,\n  }: WhooshInEffect,\n  element: Element\n): AnimationPart {\n  const id = uuidv4();\n\n  const { offsetLeft, offsetRight } = getOffPageOffset(element);\n\n  const offsetX =\n    whooshInDir === AnimationDirection.RightToLeft\n      ? `${offsetRight}%`\n      : `${offsetLeft}%`;\n\n  const move = AnimationMove(\n    {\n      offsetX,\n      duration,\n      delay,\n      easing,\n      type: AnimationType.Move,\n    },\n    element\n  );\n\n  const fade = AnimationFade({\n    fadeFrom: 0,\n    fadeTo: 1,\n    duration,\n    delay,\n    easing,\n    type: AnimationType.Fade,\n  });\n\n  const zoom = AnimationZoom({\n    zoomFrom: 0.15,\n    zoomTo: 1,\n    duration,\n    delay,\n    easing,\n    type: AnimationType.Zoom,\n  });\n\n  const [moveTransformStart, moveTransformEnd] = move.keyframes.transform;\n  const [zoomTransformStart, zoomTransformEnd] = zoom.keyframes.transform;\n  const keyframes = {\n    transform: [\n      `${moveTransformStart} ${zoomTransformStart}`,\n      `${moveTransformEnd} ${zoomTransformEnd}`,\n    ],\n    opacity: fade.keyframes.opacity,\n  };\n\n  return {\n    id,\n    keyframes,\n    WAAPIAnimation: {\n      ...zoom.WAAPIAnimation,\n      keyframes,\n    },\n    AMPTarget: function AMPTarget({\n      children,\n      style,\n    }: PropsWithChildren<{ style?: CSSProperties }>) {\n      return (\n        <move.AMPTarget style={style}>\n          <fade.AMPTarget style={style}>\n            <zoom.AMPTarget style={style}>{children}</zoom.AMPTarget>\n          </fade.AMPTarget>\n        </move.AMPTarget>\n      );\n    },\n    AMPAnimation: function AMPAnimation() {\n      return (\n        <>\n          <move.AMPAnimation />\n          <fade.AMPAnimation />\n          <zoom.AMPAnimation />\n        </>\n      );\n    },\n    generatedKeyframes: {\n      ...move.generatedKeyframes,\n      ...fade.generatedKeyframes,\n      ...zoom.generatedKeyframes,\n    },\n  };\n}\n\nexport const fields = {\n  whooshInDir: {\n    label: __('Direction', 'web-stories'),\n    type: FieldType.DirectionPicker,\n    values: [AnimationDirection.LeftToRight, AnimationDirection.RightToLeft],\n    defaultValue: AnimationDirection.LeftToRight,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 600,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/effects/zoom.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport type { CSSProperties, PropsWithChildren } from 'react';\nimport { sprintf, _x, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { AnimationZoom } from '../simple/zoom';\nimport { AnimationFade } from '../simple/fade';\nimport {\n  type AMPEffectTiming,\n  AnimationType,\n  FieldType,\n  ScaleDirection,\n} from '../../types';\nimport type { AnimationPart } from '../types';\n\nexport interface ZoomEffect extends AMPEffectTiming {\n  scaleDirection?: ScaleDirection;\n  type: AnimationType.EffectZoom;\n}\n\nexport function EffectZoom({\n  scaleDirection = ScaleDirection.ScaleIn,\n  duration = 1000,\n  delay = 0,\n  easing = 'cubic-bezier(.3,0,.55,1)',\n}: ZoomEffect): AnimationPart {\n  const id = uuidv4();\n\n  const zoom = AnimationZoom({\n    zoomFrom: scaleDirection === ScaleDirection.ScaleOut ? 3 : 1 / 3,\n    zoomTo: 1,\n    duration,\n    delay,\n    easing,\n    type: AnimationType.Zoom,\n  });\n\n  const fade = AnimationFade({\n    fadeFrom: scaleDirection === ScaleDirection.ScaleOut ? 1 : 0,\n    fadeTo: 1,\n    duration: duration,\n    delay,\n    easing,\n    type: AnimationType.Fade,\n  });\n\n  const keyframes = {\n    transform: zoom.keyframes.transform,\n    opacity: fade.keyframes.opacity,\n  };\n\n  return {\n    id,\n    keyframes,\n    WAAPIAnimation: {\n      ...zoom.WAAPIAnimation,\n      keyframes,\n    },\n    AMPTarget: function AMPTarget({\n      children,\n      style,\n    }: PropsWithChildren<{ style?: CSSProperties }>) {\n      return (\n        <fade.AMPTarget style={style}>\n          <zoom.AMPTarget style={style}>{children}</zoom.AMPTarget>\n        </fade.AMPTarget>\n      );\n    },\n    AMPAnimation: function AMPAnimation() {\n      return (\n        <>\n          <fade.AMPAnimation />\n          <zoom.AMPAnimation />\n        </>\n      );\n    },\n    generatedKeyframes: {\n      ...fade.generatedKeyframes,\n      ...zoom.generatedKeyframes,\n    },\n  };\n}\n\nexport const fields = {\n  scaleDirection: {\n    label: __('Direction', 'web-stories'),\n    tooltip: sprintf(\n      /* translators: 1: scaleIn. 2: scaleOut */\n      __('Valid values are %1$s or %2$s', 'web-stories'),\n      'scaleIn',\n      'scaleOut'\n    ),\n    type: FieldType.DirectionPicker,\n    values: [ScaleDirection.ScaleIn, ScaleDirection.ScaleOut],\n    defaultValue: ScaleDirection.ScaleIn,\n  },\n  duration: {\n    label: __('Duration', 'web-stories'),\n    type: FieldType.Number,\n    unit: _x('ms', 'Time in milliseconds', 'web-stories'),\n    defaultValue: 2000,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/emptyAnimationPart.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren, HTMLAttributes } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationPart } from './types';\n\nfunction EmptyAMPTarget({\n  children,\n  ...rest\n}: PropsWithChildren<HTMLAttributes<HTMLDivElement>>) {\n  return <div {...rest}>{children}</div>;\n}\n\nfunction emptyAnimationPart(): AnimationPart {\n  return {\n    id: '-1',\n    keyframes: {},\n    generatedKeyframes: {},\n    WAAPIAnimation: { keyframes: {}, timings: {} },\n    AMPTarget: EmptyAMPTarget,\n    AMPAnimation: () => null,\n  };\n}\n\nexport default emptyAnimationPart;\n"
  },
  {
    "path": "packages/animation/src/parts/getAnimationEffectFields.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AnimationType } from '../types';\nimport { orderByKeys } from '../utils';\nimport getDefaultFieldValue from '../utils/getDefaultFieldValue';\nimport { fields as dropFields } from './effects/drop';\nimport { fields as fadeFields } from './effects/fadeIn';\nimport { fields as flyInFields } from './effects/flyIn';\nimport { fields as panFields } from './effects/pan';\nimport { fields as pulseFields } from './effects/pulse';\nimport { fields as whooshInFields } from './effects/whooshIn';\nimport { fields as zoomFields } from './effects/zoom';\nimport { fields as rotateInFields } from './effects/rotateIn';\nimport { fields as bgZoomFields } from './effects/backgroundZoom';\nimport { fields as bgPanFields } from './effects/backgroundPan';\nimport { fields as bgPanZoomFields } from './effects/backgroundPanAndZoom';\n\nimport { basicAnimationFields } from './defaultFields';\n\nexport function getAnimationEffectFields(type?: AnimationType) {\n  const customFieldsByType: Partial<Record<AnimationType, unknown>> = {\n    [AnimationType.EffectFadeIn]: fadeFields,\n    [AnimationType.EffectFlyIn]: flyInFields,\n    [AnimationType.EffectPan]: panFields,\n    [AnimationType.EffectPulse]: pulseFields,\n    [AnimationType.EffectWhooshIn]: whooshInFields,\n    [AnimationType.EffectZoom]: zoomFields,\n    [AnimationType.EffectDrop]: dropFields,\n    [AnimationType.EffectRotateIn]: rotateInFields,\n    [AnimationType.EffectBackgroundZoom]: bgZoomFields,\n    [AnimationType.EffectBackgroundPan]: bgPanFields,\n    [AnimationType.EffectBackgroundPanAndZoom]: bgPanZoomFields,\n  };\n\n  const customFields = (type && customFieldsByType[type]) || {};\n  const allFields = {\n    ...basicAnimationFields,\n    ...customFields,\n  };\n  const allFieldsOrder = {\n    ...customFields,\n    ...basicAnimationFields,\n  };\n  let fieldOrder = Object.keys(allFieldsOrder);\n\n  // ZoomAndPand design deviates from the normal input order by putting\n  // a custom field (zoom direction) at the end. This accommodates for that.\n  const zoomField = 'zoomDirection';\n  if (\n    type === AnimationType.EffectBackgroundPanAndZoom &&\n    fieldOrder.includes(zoomField)\n  ) {\n    fieldOrder = fieldOrder\n      .filter((field) => field !== zoomField)\n      .concat([zoomField]);\n  }\n\n  // This order is important.\n  // We want custom fields to appear above default fields, but we\n  // also want custom fields to override any same-named default fields\n  const fields = orderByKeys(allFields, fieldOrder);\n  return fields;\n}\n\nexport function getAnimationEffectDefaults(type: AnimationType) {\n  const fields = getAnimationEffectFields(type);\n  return Object.fromEntries(\n    Object.entries(fields).map(([key, value]) => [\n      key,\n      value.defaultValue ?? getDefaultFieldValue(value.type),\n    ])\n  );\n}\n"
  },
  {
    "path": "packages/animation/src/parts/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as createAnimationPart } from './createAnimationPart';\nexport * from './getAnimationEffectFields';\nexport * from './types';\n"
  },
  {
    "path": "packages/animation/src/parts/simple/blinkOn.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport generateLookupMap from '../../utils/generateLookupMap';\nimport padArray from '../../utils/padArray';\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  FieldType,\n} from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst DEFAULT_BLINKS = 10;\nconst AVAILABLE_OPACITY = [0, 0.25, 0.75, 1];\n\nconst defaults: AMPEffectTiming = { fill: 'forwards' };\n\nfunction range(i: number) {\n  return Array<number>(i)\n    .fill(0)\n    .map((_v, k) => k);\n}\n\nfunction generateOpacityFrames(blinkCount: number = DEFAULT_BLINKS) {\n  const lookup = generateLookupMap(AVAILABLE_OPACITY);\n\n  let lastOpacity: number | null = null;\n  const opacityFrames = range(blinkCount - 2).map(() => {\n    const opacities: number[] =\n      lastOpacity !== null ? lookup[lastOpacity] : AVAILABLE_OPACITY;\n    const opacity = opacities[Math.floor(Math.random() * opacities.length)];\n    lastOpacity = opacity;\n    return opacity;\n  });\n\n  return padArray(opacityFrames, 3);\n}\n\nexport interface BlinkOnAnimation extends AMPEffectTiming {\n  blinkCount?: number;\n  type: AnimationType.BlinkOn;\n}\n\nexport function AnimationBlinkOn({\n  blinkCount = DEFAULT_BLINKS,\n  type,\n  ...args\n}: BlinkOnAnimation) {\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n  const keyframes = { opacity: [0, ...generateOpacityFrames(blinkCount), 1] };\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  blinkCount: { type: FieldType.Number, defaultValue: DEFAULT_BLINKS },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/bounce.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming, AnimationType } from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst keyframes = [\n  { transform: 'scale(0)', offset: 0.0 },\n  { transform: 'scale(1.27)', offset: 0.18 },\n  { transform: 'scale(0.84)', offset: 0.28 },\n  { transform: 'scale(0.84)', offset: 0.29 },\n  { transform: 'scale(1.1)', offset: 0.4 },\n  { transform: 'scale(1.1)', offset: 0.41 },\n  { transform: 'scale(0.95)', offset: 0.52 },\n  { transform: 'scale(0.95)', offset: 0.53 },\n  { transform: 'scale(1.03)', offset: 0.6 },\n  { transform: 'scale(1.03)', offset: 0.61 },\n  { transform: 'scale(0.98)', offset: 0.7 },\n  { transform: 'scale(0.98)', offset: 0.71 },\n  { transform: 'scale(1.02)', offset: 0.8 },\n  { transform: 'scale(1.02)', offset: 0.81 },\n  { transform: 'scale(0.99)', offset: 0.9 },\n  { transform: 'scale(0.99)', offset: 0.91 },\n  { transform: 'scale(1)', offset: 1 },\n];\n\nconst defaults: AMPEffectTiming = { fill: 'both', duration: 1500 };\n\nexport interface BounceAnimation extends AMPEffectTiming {\n  type: AnimationType.Bounce;\n}\n\nexport function AnimationBounce({ type, ...args }: BounceAnimation) {\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n  return createAnimation(keyframes, timings);\n}\n"
  },
  {
    "path": "packages/animation/src/parts/simple/fade.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  FieldType,\n} from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = {\n  fill: 'both',\n  duration: 1000,\n};\n\nexport interface FadeAnimation extends AMPEffectTiming {\n  type: AnimationType.Fade;\n  fadeFrom?: number;\n  fadeTo?: number;\n}\n\nexport function AnimationFade({\n  fadeFrom = 0,\n  fadeTo = 1,\n  type,\n  ...args\n}: FadeAnimation) {\n  const timings = { ...defaults, ...args };\n  const keyframes = { opacity: [fadeFrom, fadeTo] };\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  fadeFrom: {\n    tooltip: 'Valid values range from 0 to 1',\n    type: FieldType.Float,\n    defaultValue: 0,\n  },\n  fadeTo: {\n    tooltip: 'Valid values range from 0 to 1',\n    type: FieldType.Float,\n    defaultValue: 1,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/flip.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  Axis,\n  FieldType,\n  Rotation,\n} from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = { fill: 'both', duration: 1000 };\n\nconst keyframesLookup = {\n  [Rotation.Clockwise]: {\n    [Axis.X]: {\n      transform: ['rotateX(90deg)', 'rotateX(0deg)'],\n    },\n    [Axis.Y]: {\n      transform: ['rotateY(90deg)', 'rotateY(0deg)'],\n    },\n  },\n  [Rotation.CounterClockwise]: {\n    [Axis.X]: {\n      transform: ['rotateX(-90deg)', 'rotateX(0deg)'],\n    },\n    [Axis.Y]: {\n      transform: ['rotateY(-90deg)', 'rotateY(0deg)'],\n    },\n  },\n  [Rotation.PingPong]: {\n    [Axis.X]: {\n      transform: [],\n    },\n    [Axis.Y]: {\n      transform: [],\n    },\n  },\n};\n\nexport interface FlipAnimation extends AMPEffectTiming {\n  axis: Axis;\n  rotation: Rotation;\n  type: AnimationType.Flip;\n}\n\nexport function AnimationFlip({\n  axis = Axis.Y,\n  rotation = Rotation.Clockwise,\n  type,\n  ...args\n}: FlipAnimation) {\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n  const keyframes = keyframesLookup[rotation][axis];\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  axis: {\n    type: FieldType.Dropdown,\n    values: [Axis.X, Axis.Y],\n    defaultValue: Axis.Y,\n  },\n  rotation: {\n    type: FieldType.Dropdown,\n    values: [Rotation.Clockwise, Rotation.CounterClockwise],\n    defaultValue: Rotation.Clockwise,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/floatOn.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  AnimationDirection,\n  type AnimationType,\n  FieldType,\n} from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = { fill: 'both', duration: 1000 };\n\nconst keyframesLookup: Record<\n  AnimationDirection,\n  { transform: [string, string] }\n> = {\n  [AnimationDirection.TopToBottom]: {\n    transform: ['translateY(-100%)', 'translateY(0%)'],\n  },\n  [AnimationDirection.BottomToTop]: {\n    transform: ['translateY(100%)', 'translateY(0%)'],\n  },\n  [AnimationDirection.LeftToRight]: {\n    transform: ['translateX(-100%)', 'translateX(0%)'],\n  },\n  [AnimationDirection.RightToLeft]: {\n    transform: ['translateX(100%)', 'translateX(0%)'],\n  },\n};\n\nexport interface FloatOnAnimation extends AMPEffectTiming {\n  floatOnDir?: AnimationDirection;\n  type: AnimationType.FloatOn;\n}\n\nexport function AnimationFloatOn({\n  floatOnDir = AnimationDirection.BottomToTop,\n  type,\n  ...args\n}: FloatOnAnimation) {\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n  const keyframes = keyframesLookup[floatOnDir];\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  floatOnDir: {\n    type: FieldType.Dropdown,\n    values: [\n      AnimationDirection.TopToBottom,\n      AnimationDirection.BottomToTop,\n      AnimationDirection.LeftToRight,\n      AnimationDirection.RightToLeft,\n    ],\n    defaultValue: AnimationDirection.BottomToTop,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/move.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport { defaultUnit, getGlobalSpace } from '../../utils';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = { fill: 'both', duration: 1000 };\n\nexport interface MoveAnimation extends AMPEffectTiming {\n  type: AnimationType.Move;\n  overflowHidden?: boolean;\n  offsetX?: string | number;\n  offsetY?: string | number;\n}\n\nexport function AnimationMove(\n  {\n    overflowHidden = false,\n    offsetX = 0,\n    offsetY = 0,\n    type,\n    ...args\n  }: MoveAnimation,\n  element: Element\n) {\n  const global = getGlobalSpace(element);\n  const timings: AMPEffectTiming = { ...defaults, ...args };\n  const keyframes = {\n    transform: [\n      global`translate3d(${defaultUnit(offsetX, 'px')}, ${defaultUnit(\n        offsetY,\n        'px'\n      )}, 0)`,\n      global`translate3d(${defaultUnit(0, 'px')}, ${defaultUnit(0, 'px')}, 0)`,\n    ],\n  };\n\n  return createAnimation(keyframes, timings, overflowHidden);\n}\n\nexport const fields = {\n  overflowHidden: { type: FieldType.Checkbox, defaultValue: false },\n  offsetX: { type: FieldType.Text, defaultValue: 0 },\n  offsetY: { type: FieldType.Text, defaultValue: 0 },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/pulse.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming, AnimationType } from '../../types';\nimport createAnimation from '../createAnimation';\n\nexport function generatePulseKeyframes(scale: number) {\n  const baseScale = 1.0;\n  const intensity = scale;\n\n  return {\n    transform: [\n      `scale(${baseScale})`,\n      `scale(${baseScale + intensity})`,\n      `scale(${baseScale - intensity / 10})`,\n      `scale(${baseScale})`,\n    ],\n    offset: [0.0, 0.33, 0.66, 1.0],\n  };\n}\n\nconst defaults: AMPEffectTiming = { fill: 'both', duration: 400 };\n\nexport interface PulseAnimation extends AMPEffectTiming {\n  type: AnimationType.Pulse;\n  scale?: number;\n}\n\nexport function AnimationPulse({\n  iterations = 1,\n  scale = 0.5,\n  easing = 'cubic-bezier(0.3, 0.0, 0.0, 1)',\n  type,\n  ...args\n}: PulseAnimation) {\n  const timings: AMPEffectTiming = {\n    ...defaults,\n    ...args,\n    iterations,\n    easing,\n  };\n  const keyframes = generatePulseKeyframes(scale);\n  return createAnimation(keyframes, timings);\n}\n"
  },
  {
    "path": "packages/animation/src/parts/simple/spin.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  type Element,\n  FieldType,\n} from '../../types';\nimport { defaultUnit, getGlobalSpace } from '../../utils';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = { fill: 'forwards', duration: 1000 };\n\nexport interface SpinAnimation extends AMPEffectTiming {\n  rotation?: string | number;\n  stopAngle?: number;\n  type: AnimationType.Spin;\n}\n\nexport function AnimationSpin(\n  { rotation = 0, stopAngle = 0, type, ...args }: SpinAnimation,\n  element: Element\n) {\n  const global = getGlobalSpace(element);\n  const timings = { ...defaults, ...args };\n  const keyframes = {\n    transform: [\n      global`rotateZ(${defaultUnit(rotation, 'deg')})`,\n      global`rotateZ(${defaultUnit(stopAngle, 'deg')})`,\n    ],\n  };\n  return createAnimation(keyframes, timings);\n}\n\nexport const fields = {\n  rotation: { type: FieldType.Text, defaultValue: '0' },\n  stopAngle: { type: FieldType.Text, defaultValue: '0' },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/blinkOn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/BlinkOn',\n};\n\nconst animations = [\n  { id: '1', targets: ['e1'], type: AnimationType.BlinkOn, duration: 3000 },\n  { id: '2', targets: ['e2'], type: AnimationType.BlinkOn, duration: 3000 },\n  { id: '3', targets: ['e3'], type: AnimationType.BlinkOn, duration: 3000 },\n  { id: '4', targets: ['e4'], type: AnimationType.BlinkOn, duration: 3000 },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red' },\n  { id: 'e2', color: 'orange' },\n  { id: 'e3', color: 'blue' },\n  { id: 'e4', color: 'green' },\n];\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        <div\n          style={{\n            display: 'flex',\n            width: '220px',\n            justifyContent: 'space-between',\n            marginTop: '20px',\n          }}\n        >\n          {elements.map(({ id, color }) => (\n            <div\n              key={id}\n              style={{ position: 'relative', width: '50px', height: '50px' }}\n            >\n              <StoryAnimation.WAAPIWrapper target={id}>\n                <div\n                  style={{\n                    width: '100%',\n                    height: '100%',\n                    backgroundColor: color,\n                  }}\n                />\n              </StoryAnimation.WAAPIWrapper>\n            </div>\n          ))}\n        </div>\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"horizontal\">\n                {elements.map(({ id, color }) => (\n                  <div\n                    key={id}\n                    style={{\n                      position: 'relative',\n                      width: '50px',\n                      height: '50px',\n                    }}\n                  >\n                    <StoryAnimation.AMPWrapper target={id}>\n                      <div\n                        style={{\n                          width: '100%',\n                          height: '100%',\n                          backgroundColor: color,\n                        }}\n                      />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/bounce.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Bounce',\n};\n\nconst animations = [\n  { id: '1', targets: ['e1'], type: AnimationType.Bounce, duration: 1000 },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Bounce,\n    duration: 1000,\n    delay: 100,\n  },\n  {\n    id: '3',\n    targets: ['e3'],\n    type: AnimationType.Bounce,\n    duration: 1000,\n    delay: 300,\n  },\n  {\n    id: '4',\n    targets: ['e4'],\n    type: AnimationType.Bounce,\n    duration: 1000,\n    delay: 500,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', width: '50px' },\n  { id: 'e2', color: 'orange', width: '100px' },\n  { id: 'e3', color: 'blue', width: '200px' },\n  { id: 'e4', color: 'green', width: '150px' },\n];\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, color, width }) => (\n          <div key={id} style={{ position: 'relative', width, height: '50px' }}>\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <div\n                style={{\n                  width: '100%',\n                  height: '100%',\n                  backgroundColor: color,\n                }}\n              />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"vertical\">\n                {elements.map(({ id, color, width }) => (\n                  <div\n                    key={id}\n                    style={{\n                      position: 'relative',\n                      height: '50px',\n                      width,\n                    }}\n                  >\n                    <StoryAnimation.AMPWrapper target={id}>\n                      <div\n                        style={{\n                          width: '100%',\n                          height: '100%',\n                          backgroundColor: color,\n                        }}\n                      />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/fade.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Fade',\n};\n\nconst animations = [\n  { id: '1', targets: ['e1'], type: AnimationType.Fade, duration: 1000 },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Fade,\n    duration: 1000,\n    fadeFrom: 1,\n    fadeTo: 0,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red' },\n  { id: 'e2', color: 'orange' },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, color }) => (\n          <div key={id} style={{ position: 'relative', ...defaultStyles }}>\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <div\n                style={{\n                  width: '100%',\n                  height: '100%',\n                  backgroundColor: color,\n                }}\n              />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"horizontal\">\n                {elements.map(({ id, color }) => (\n                  <div key={id} style={defaultStyles}>\n                    <StoryAnimation.AMPWrapper target={id}>\n                      <div\n                        style={{\n                          width: '100%',\n                          height: '100%',\n                          backgroundColor: color,\n                        }}\n                      />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/flip.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, Axis, Rotation } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Flip',\n};\n\nconst duration = 600;\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.Flip,\n    duration,\n    axis: Axis.X,\n    rotaton: Rotation.Clockwise,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Flip,\n    duration,\n    delay: duration,\n    axis: Axis.X,\n    rotaton: Rotation.CounterClockwise,\n  },\n  {\n    id: '3',\n    targets: ['e3'],\n    type: AnimationType.Flip,\n    duration,\n    delay: duration * 2,\n    axis: Axis.Y,\n    rotaton: Rotation.Clockwise,\n  },\n  {\n    id: '4',\n    targets: ['e4'],\n    type: AnimationType.Flip,\n    duration,\n    delay: duration * 3,\n    axis: Axis.Y,\n    rotaton: Rotation.CounterClockwise,\n  },\n];\n\nconst elements = [\n  { id: 'e1', text: 'CLOCKWISE-X' },\n  { id: 'e2', text: 'COUNTER-CLOCKWISE-X' },\n  { id: 'e3', text: 'CLOCKWISE-Y' },\n  { id: 'e4', text: 'COUNTER-CLOCKWISE-Y' },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '200px',\n  height: '20px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, text }) => (\n          <div\n            key={id}\n            style={{\n              position: 'relative',\n              ...defaultStyles,\n              marginBottom: '20px',\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              {text}\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"vertical\">\n                {elements.map(({ id, text }) => (\n                  <div key={id} style={defaultStyles}>\n                    <StoryAnimation.AMPWrapper target={id}>\n                      {text}\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/floatOn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType, AnimationDirection } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/FloatOn',\n};\n\nconst duration = 600;\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.FloatOn,\n    duration,\n    floatOnDir: AnimationDirection.TopToBottom,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.FloatOn,\n    duration,\n    delay: duration,\n    floatOnDir: AnimationDirection.BottomToTop,\n  },\n  {\n    id: '3',\n    targets: ['e3'],\n    type: AnimationType.FloatOn,\n    duration,\n    delay: duration * 2,\n    floatOnDir: AnimationDirection.LeftToRight,\n  },\n  {\n    id: '4',\n    targets: ['e4'],\n    type: AnimationType.FloatOn,\n    duration,\n    delay: duration * 3,\n    floatOnDir: AnimationDirection.RightToLeft,\n  },\n];\n\nconst elements = [\n  { id: 'e1', text: 'TOP-TO-BOTTOM' },\n  { id: 'e2', text: 'BOTTOM-TO-TOP' },\n  { id: 'e3', text: 'LEFT-TO-RIGHT' },\n  { id: 'e4', text: 'RIGHT-TO-LEFT' },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '200px',\n  height: '100px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, text }) => (\n          <div\n            key={id}\n            style={{\n              position: 'relative',\n              ...defaultStyles,\n              marginBottom: '20px',\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              {text}\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"vertical\">\n                {elements.map(({ id, text }) => (\n                  <div key={id} style={defaultStyles}>\n                    <StoryAnimation.AMPWrapper target={id}>\n                      {text}\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/move.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { PlayButton, AMPStoryWrapper } from '../../../storybookUtils';\nimport { AnimationType } from '../../../types';\n\nexport default {\n  title: 'Animations/Parts/Move',\n};\n\nconst duration = 600;\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.Move,\n    duration,\n    offsetX: -200,\n    offsetY: 500,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Move,\n    duration,\n    offsetX: 200,\n    offsetY: 500,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', top: '20px', left: '250px' },\n  { id: 'e2', color: 'green', top: '20px', left: '50px' },\n];\n\nconst defaultStyles = {\n  position: 'absolute',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, color, ...styles }) => (\n          <div\n            key={id}\n            style={{\n              ...defaultStyles,\n              ...styles,\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <div\n                style={{\n                  width: '100%',\n                  height: '100%',\n                  backgroundColor: color,\n                }}\n              />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n              {elements.map(({ id, color, ...styles }) => (\n                <div\n                  key={id}\n                  style={{\n                    ...defaultStyles,\n                    ...styles,\n                  }}\n                >\n                  <StoryAnimation.AMPWrapper target={id}>\n                    <div\n                      style={{\n                        width: '100%',\n                        height: '100%',\n                        backgroundColor: color,\n                      }}\n                    />\n                  </StoryAnimation.AMPWrapper>\n                </div>\n              ))}\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/pulse.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Pulse',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.Pulse,\n    iterations: 2,\n    delay: 500,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Pulse,\n    iterations: 4,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red', top: '40px', left: '150px' },\n  { id: 'e2', color: 'green', top: '40px', left: '50px' },\n];\n\nconst defaultStyles = {\n  position: 'absolute',\n  width: '50px',\n  height: '50px',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, color, ...styles }) => (\n          <div\n            key={id}\n            style={{\n              ...defaultStyles,\n              ...styles,\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <div\n                style={{\n                  width: '100%',\n                  height: '100%',\n                  backgroundColor: color,\n                }}\n              />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n              {elements.map(({ id, color, ...styles }) => (\n                <div\n                  key={id}\n                  style={{\n                    ...defaultStyles,\n                    ...styles,\n                  }}\n                >\n                  <StoryAnimation.AMPWrapper target={id}>\n                    <div\n                      style={{\n                        width: '100%',\n                        height: '100%',\n                        backgroundColor: color,\n                      }}\n                    />\n                  </StoryAnimation.AMPWrapper>\n                </div>\n              ))}\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/spin.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Spin',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.Spin,\n    delay: 2000,\n    duration: 8000,\n    iterations: 'infinity',\n    rotation: 360,\n  },\n  {\n    id: '2',\n    targets: ['e1'],\n    type: AnimationType.Spin,\n    duration: 2000,\n    easing: 'cubic-bezier(0.02, 0.49, 0.46, 0.84)',\n    rotation: 360,\n  },\n  {\n    id: '3',\n    targets: ['e2'],\n    type: AnimationType.Spin,\n    duration: 8000,\n    iterations: 'infinity',\n    rotation: 360,\n  },\n  {\n    id: '4',\n    targets: ['e3'],\n    type: AnimationType.Spin,\n    duration: 8000,\n    iterations: 'infinity',\n    rotation: -360,\n  },\n  {\n    id: '5',\n    targets: ['e4'],\n    type: AnimationType.Spin,\n    duration: 2000,\n    iterations: 'infinity',\n    direction: 'alternate',\n    rotation: 90,\n  },\n];\n\nconst elements = [\n  { id: 'e1', color: 'red' },\n  { id: 'e2', color: 'orange' },\n  { id: 'e3', color: 'green' },\n  { id: 'e4', color: 'blue' },\n];\n\nconst defaultStyles = {\n  width: '50px',\n  height: '50px',\n};\n\nconst SimpleStar = ({ color }) => {\n  const rotations = [0, 45, 20, 70];\n  return (\n    <div>\n      {rotations.map((rotation) => (\n        <div\n          key={rotation}\n          style={{\n            position: 'absolute',\n            width: '100%',\n            height: '100%',\n            backgroundColor: color,\n            transform: `rotateZ(${rotation}deg)`,\n          }}\n        />\n      ))}\n    </div>\n  );\n};\n\nSimpleStar.propTypes = {\n  color: PropTypes.string.isRequired,\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, color }) => (\n          <div\n            key={id}\n            style={{\n              position: 'relative',\n              margin: '20px',\n              ...defaultStyles,\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <SimpleStar color={color} />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const _AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n              <amp-story-grid-layer template=\"vertical\">\n                {elements.map(({ id, color }) => (\n                  <div\n                    key={id}\n                    style={{\n                      position: 'relative',\n                      marginBottom: '20px',\n                      ...defaultStyles,\n                    }}\n                  >\n                    <StoryAnimation.AMPWrapper target={id}>\n                      <SimpleStar color={color} />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/stories/zoom.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as StoryAnimation from '../../../components';\nimport { AnimationType } from '../../../types';\nimport { AMPStoryWrapper, PlayButton } from '../../../storybookUtils';\n\nexport default {\n  title: 'Animations/Parts/Zoom',\n};\n\nconst animations = [\n  {\n    id: '1',\n    targets: ['e1'],\n    type: AnimationType.Zoom,\n    duration: 10000,\n    zoomFrom: 1,\n    zoomTo: 2,\n  },\n  {\n    id: '2',\n    targets: ['e2'],\n    type: AnimationType.Zoom,\n    duration: 10000,\n    zoomFrom: 2,\n    zoomTo: 1,\n  },\n];\n\nconst elements = [\n  {\n    id: 'e1',\n    src: 'https://i.picsum.photos/id/1025/4951/3301.jpg?hmac=_aGh5AtoOChip_iaMo8ZvvytfEojcgqbCH7dzaz-H8Y',\n    transform: 'translate(0px, 100px) scale(2)',\n  },\n  {\n    id: 'e2',\n    src: 'https://i.picsum.photos/id/1062/5092/3395.jpg?hmac=o9m7qeU51uOLfXvepXcTrk2ZPiSBJEkiiOp-Qvxja-k',\n  },\n];\n\nconst defaultStyles = {\n  position: 'relative',\n  width: '300px',\n  height: '200px',\n  overflow: 'hidden',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryAnimation.AnimationProvider animations={animations}>\n        <PlayButton />\n        {elements.map(({ id, src, ...style }) => (\n          <div\n            key={id}\n            style={{\n              marginBottom: '20px',\n              ...defaultStyles,\n            }}\n          >\n            <StoryAnimation.WAAPIWrapper target={id}>\n              <img\n                alt=\"\"\n                style={{\n                  width: '100%',\n                  height: '100%',\n                  ...style,\n                }}\n                src={src}\n              />\n            </StoryAnimation.WAAPIWrapper>\n          </div>\n        ))}\n      </StoryAnimation.AnimationProvider>\n    );\n  },\n};\n\nexport const AMPStory = {\n  render: function Render() {\n    return (\n      <AMPStoryWrapper>\n        <amp-story-page id=\"page-0\">\n          <p style={{ textAlign: 'center', color: '#fff' }}>\n            {'Empty first page'}\n          </p>\n        </amp-story-page>\n        {[1, 2].map((pageId) => (\n          <amp-story-page key={pageId} id={`page-${pageId}`}>\n            <StoryAnimation.AnimationProvider animations={animations}>\n              <StoryAnimation.AMPAnimations />\n\n              <amp-story-grid-layer template=\"vertical\">\n                {elements.map(({ id, src, ...style }) => (\n                  <div key={id} style={defaultStyles}>\n                    <StoryAnimation.AMPWrapper target={id}>\n                      <img\n                        alt=\"\"\n                        style={{\n                          width: '100%',\n                          height: '100%',\n                          ...style,\n                        }}\n                        src={src}\n                      />\n                    </StoryAnimation.AMPWrapper>\n                  </div>\n                ))}\n              </amp-story-grid-layer>\n            </StoryAnimation.AnimationProvider>\n          </amp-story-page>\n        ))}\n      </AMPStoryWrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/simple/test/pulse.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { generatePulseKeyframes } from '../pulse';\n\ndescribe('Pulse Effect', () => {\n  describe('generatePulseKeyframes', () => {\n    it('should return correct keyframes based on scale', () => {\n      // scale > 1\n      let scale = 2;\n      let expand = 1 + scale;\n      let shrink = 1 - scale / 10;\n\n      expect(generatePulseKeyframes(scale)).toStrictEqual({\n        transform: [\n          `scale(1)`,\n          `scale(${expand})`,\n          `scale(${shrink})`,\n          `scale(1)`,\n        ],\n        offset: [0.0, 0.33, 0.66, 1.0],\n      });\n\n      // scale < 1\n      scale = 0.5;\n      expand = 1 + scale;\n      shrink = 1 - scale / 10;\n\n      expect(generatePulseKeyframes(scale)).toStrictEqual({\n        transform: [\n          `scale(1)`,\n          `scale(${expand})`,\n          `scale(${shrink})`,\n          `scale(1)`,\n        ],\n        offset: [0.0, 0.33, 0.66, 1.0],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/parts/simple/zoom.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type AMPEffectTiming,\n  type AnimationType,\n  FieldType,\n} from '../../types';\nimport createAnimation from '../createAnimation';\n\nconst defaults: AMPEffectTiming = { fill: 'forwards', duration: 1000 };\n\nexport interface ZoomAnimation extends AMPEffectTiming {\n  type: AnimationType.Zoom;\n  zoomFrom?: number;\n  zoomTo?: number;\n  targetLeafElement?: boolean;\n  transformOrigin?: {\n    horizontal: number;\n    vertical: number;\n  };\n}\n\nexport function AnimationZoom({\n  zoomFrom = 0,\n  zoomTo = 1,\n  targetLeafElement = false,\n  transformOrigin,\n  type,\n  ...args\n}: ZoomAnimation) {\n  const timings = { ...defaults, ...args };\n  const keyframes = { transform: [`scale(${zoomFrom})`, `scale(${zoomTo})`] };\n\n  // If supplied a transformOrigin, AMP doesn't allow us to set\n  // the transformOrigin property from the keyframes since it is\n  // an unanimatable property. To account for this we calculate a\n  // counter translate based off the scale change that mimics the\n  // element scaling from a particular origin.\n  if (transformOrigin) {\n    // transformOrigin default is `50% 50%` so we account for\n    // that here in our calculations.\n    const originRelativeToCenter = {\n      x: 50 - transformOrigin.horizontal,\n      y: 50 - transformOrigin.vertical,\n    };\n    const counterScaleTranslate = {\n      x: (zoomFrom - 1) * originRelativeToCenter.x,\n      y: (zoomFrom - 1) * originRelativeToCenter.y,\n    };\n    keyframes.transform = [\n      `translate(${counterScaleTranslate.x}%, ${counterScaleTranslate.y}%) ${keyframes.transform[0]}`,\n      `translate(0%, 0%) ${keyframes.transform[1]}`,\n    ];\n  }\n\n  return createAnimation(keyframes, timings, false, targetLeafElement);\n}\n\nexport const fields = {\n  zoomFrom: {\n    tooltip: 'Valid values range from 0 to 1',\n    type: FieldType.Float,\n    defaultValue: 0,\n  },\n  zoomTo: {\n    tooltip: 'Valid values range from 0 to 1',\n    type: FieldType.Float,\n    defaultValue: 1,\n  },\n};\n"
  },
  {
    "path": "packages/animation/src/parts/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  CSSProperties,\n  HTMLAttributes,\n  PropsWithChildren,\n  VoidFunctionComponent,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming, Keyframes } from '../types';\n\nexport type AMPAnimationProps = PropsWithChildren<{\n  className?: string;\n  style?: CSSProperties;\n  prefixId?: string;\n}>;\n\nexport interface WAAPIAnimation {\n  keyframes: Keyframes;\n  timings: AMPEffectTiming;\n  useClippingContainer?: boolean;\n  targetLeafElement?: boolean;\n}\n\n// This generic seems weird, but is very important. It allows complex effects\n// to reach into the keyframes of their constituent animation parts and\n// recompose them into combined keyframes.\n// See how e.g. RotateIn is able to compose the move and spin keyframes.\n// This is only possible because the keyframes property of each part isn't\n// generically types as Keyframes but as a specific simple object.\nexport interface AnimationPart<T extends Keyframes = Keyframes> {\n  id: string;\n  keyframes: T;\n  WAAPIAnimation: WAAPIAnimation;\n  AMPTarget: VoidFunctionComponent<PropsWithChildren<HTMLAttributes<Element>>>;\n  AMPAnimation: VoidFunctionComponent<{ prefixId?: string }>;\n  generatedKeyframes: Record<string, Keyframes>;\n}\n"
  },
  {
    "path": "packages/animation/src/storybookUtils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { PAGE_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useStoryAnimationContext } from '../components';\nimport Boilerplate from './utils/ampBoilerplate';\n\nexport const AMP_STORY_ASPECT_RATIO = `${PAGE_WIDTH}:${PAGE_HEIGHT}`;\n\nexport function AMPStoryWrapper({ children }) {\n  return (\n    <div style={{ width: '100%', height: '640px' }}>\n      <Boilerplate />\n      <amp-story\n        standalone\n        title=\"My Story\"\n        publisher=\"The AMP Team\"\n        publisher-logo-src=\"https://example.com/logo/1x1.png\"\n        poster-portrait-src=\"https://example.com/my-story/poster/3x4.jpg\"\n      >\n        {children}\n      </amp-story>\n    </div>\n  );\n}\n\nAMPStoryWrapper.propTypes = {\n  children: PropTypes.node,\n};\n\nexport const PlayButton = () => {\n  const {\n    actions: { WAAPIAnimationMethods },\n  } = useStoryAnimationContext();\n\n  const label = {\n    play: 'play',\n    pause: 'pause',\n    reset: 'reset',\n  };\n  return (\n    <>\n      <button onClick={WAAPIAnimationMethods.play}>{label.play}</button>\n      <button onClick={WAAPIAnimationMethods.pause}>{label.pause}</button>\n      <button onClick={WAAPIAnimationMethods.reset}>{label.reset}</button>\n    </>\n  );\n};\n\nexport default PlayButton;\n"
  },
  {
    "path": "packages/animation/src/storybookUtils/utils/ampBoilerplate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Renders AMP boilerplate\n *\n * @see https://amp.dev/documentation/guides-and-tutorials/learn/spec/amp-boilerplate/\n * @see https://amp.dev/documentation/components/amp-story/#boilerplate\n * @return {Element} AMP boilerplate.\n */\nfunction Boilerplate() {\n  return (\n    <>\n      <style\n        amp-boilerplate=\"\"\n        dangerouslySetInnerHTML={{\n          __html:\n            'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',\n        }}\n      />\n      <noscript>\n        <style\n          amp-boilerplate=\"\"\n          dangerouslySetInnerHTML={{\n            __html:\n              'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',\n          }}\n        />\n      </noscript>\n    </>\n  );\n}\n\nexport default Boilerplate;\n"
  },
  {
    "path": "packages/animation/src/types/animation.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/// <reference types=\"@types/web-animations-js\" />\n\n/**\n * Internal dependencies\n */\nimport type { BezierType } from '../constants';\nimport type { PanBackgroundEffect } from '../parts/effects/backgroundPan';\nimport type { PanAndZoomBackgroundEffect } from '../parts/effects/backgroundPanAndZoom';\nimport type { ZoomBackgroundEffect } from '../parts/effects/backgroundZoom';\nimport type { DropEffect } from '../parts/effects/drop';\nimport type { FadeInEffect } from '../parts/effects/fadeIn';\nimport type { FlyInEffect } from '../parts/effects/flyIn';\nimport type { PanEffect } from '../parts/effects/pan';\nimport type { PulseEffect } from '../parts/effects/pulse';\nimport type { RotateInEffect } from '../parts/effects/rotateIn';\nimport type { TwirlInEffect } from '../parts/effects/twirlIn';\nimport type { WhooshInEffect } from '../parts/effects/whooshIn';\nimport type { ZoomEffect } from '../parts/effects/zoom';\nimport type { BlinkOnAnimation } from '../parts/simple/blinkOn';\nimport type { BounceAnimation } from '../parts/simple/bounce';\nimport type { FadeAnimation } from '../parts/simple/fade';\nimport type { FlipAnimation } from '../parts/simple/flip';\nimport type { FloatOnAnimation } from '../parts/simple/floatOn';\nimport type { MoveAnimation } from '../parts/simple/move';\nimport type { PulseAnimation } from '../parts/simple/pulse';\nimport type { SpinAnimation } from '../parts/simple/spin';\nimport type { ZoomAnimation } from '../parts/simple/zoom';\nimport type { ElementId } from './element';\n\nexport enum AnimationType {\n  BlinkOn = 'blinkOn',\n  Bounce = 'bounce',\n  Fade = 'fade',\n  Flip = 'flip',\n  FloatOn = 'floatOn',\n  Move = 'move',\n  Pulse = 'pulse',\n  Spin = 'spin',\n  Zoom = 'zoom',\n\n  EffectDrop = 'effect-drop',\n  EffectFadeIn = 'effect-fade-in',\n  EffectFlyIn = 'effect-fly-in',\n  EffectPan = 'effect-pan',\n  EffectPulse = 'effect-pulse',\n  EffectRotateIn = 'effect-rotate-in',\n  EffectTwirlIn = 'effect-twirl-in',\n  EffectWhooshIn = 'effect-whoosh-in',\n  EffectZoom = 'effect-zoom',\n\n  EffectBackgroundPan = 'effect-background-pan',\n  EffectBackgroundPanAndZoom = 'effect-background-pan-and-zoom',\n  EffectBackgroundZoom = 'effect-background-zoom',\n}\n\nconst {\n  EffectBackgroundPan,\n  EffectBackgroundPanAndZoom,\n  EffectBackgroundZoom,\n  ...NonBackgroundAnimationType\n} = { ...AnimationType };\nexport { NonBackgroundAnimationType };\n\nexport type ZoomDirection =\n  | 'dynamicPropertyValue'\n  | 'scaleIn'\n  | 'scaleInBottomRight'\n  | 'scaleInTopLeft'\n  | 'scaleOut'\n  | 'scaleOutTopRight'\n  | 'scaleOutBottomLeft';\n\nexport enum AnimationDirection {\n  LeftToRight = 'leftToRight',\n  TopToBottom = 'topToBottom',\n  RightToLeft = 'rightToLeft',\n  BottomToTop = 'bottomToTop',\n}\n\nexport type AnimationInput =\n  | PanAndZoomBackgroundEffect\n  | PanBackgroundEffect\n  | ZoomBackgroundEffect\n  | DropEffect\n  | FadeInEffect\n  | FlyInEffect\n  | PanEffect\n  | PulseEffect\n  | RotateInEffect\n  | TwirlInEffect\n  | WhooshInEffect\n  | ZoomEffect\n  | BlinkOnAnimation\n  | BounceAnimation\n  | FadeAnimation\n  | FlipAnimation\n  | FloatOnAnimation\n  | MoveAnimation\n  | PulseAnimation\n  | SpinAnimation\n  | ZoomAnimation;\n\nexport type AnimationInputWithPreset = AnimationInput & {\n  easingPreset?: BezierType;\n};\n\n// Renamed this from just Animation to StoryAnimation to avoid a clash with the\n// imported Animation interface from `@types/web-animations-js` that we cannot\n// rename due to how we have to import it at the top of this file.\nexport type StoryAnimation = AnimationInputWithPreset & {\n  id: string;\n  targets: ElementId[];\n};\n"
  },
  {
    "path": "packages/animation/src/types/effects.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ScaleDirection {\n  DynamicPropertyValue = 'dynamicPropertyValue',\n  ScaleIn = 'scaleIn',\n  ScaleOut = 'scaleOut',\n  ScaleOutTopRight = 'scaleOutTopRight',\n  ScaleOutBottomLeft = 'scaleOutBottomLeft',\n  ScaleInTopLeft = 'scaleInTopLeft',\n  ScaleInBottomRight = 'scaleInBottomRight',\n}\n\nexport enum Rotation {\n  Clockwise = 'clockwise',\n  CounterClockwise = 'counterClockwise',\n  PingPong = 'pingPong',\n}\n\nexport enum Axis {\n  X = 'x',\n  Y = 'y',\n}\n\nexport enum FieldType {\n  Dropdown = 'dropdown',\n  Hidden = 'hidden',\n  RotationPicker = 'rotation_picker',\n  DirectionPicker = 'direction_picker',\n  Number = 'number',\n  Float = 'float',\n  Text = 'text',\n  Checkbox = 'checkbox',\n  Range = 'range',\n}\n\nexport interface AMPEffectTiming extends Omit<\n  EffectTiming,\n  'iterations' | 'duration'\n> {\n  iterations?: number | 'infinity';\n  duration?: number;\n}\n"
  },
  {
    "path": "packages/animation/src/types/element.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DimensionableElement } from '@googleforcreators/units';\n\nexport type ElementId = string;\n\nexport interface Element extends DimensionableElement {\n  id: ElementId;\n  isHidden?: boolean;\n}\n\nexport interface ScaledElement extends Element {\n  scale?: number;\n}\n\nexport function isScaledElement(e: Element): e is ScaledElement {\n  return 'scale' in e;\n}\n"
  },
  {
    "path": "packages/animation/src/types/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './animation';\nexport * from './storyAnimationState';\nexport * from './effects';\nexport * from './element';\nexport * from './keyframes';\nexport * from './propTypes';\n"
  },
  {
    "path": "packages/animation/src/types/keyframes.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type Keyframes = Keyframe[] | PropertyIndexedKeyframes;\n"
  },
  {
    "path": "packages/animation/src/types/propTypes.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n/* eslint-disable no-restricted-imports -- Still used by other packages. */\nimport * as PropTypes from 'prop-types';\n/* eslint-enable no-restricted-imports -- Still used by other packages. */\n\n/**\n * Internal dependencies\n */\nimport { AnimationType } from './animation';\n\n// This one did once include all the specs for the different possible fields\n// in the animation panel, but we don't want to create those anymore.\nexport const AnimationFormPropTypes = PropTypes.object;\n\nexport const GeneralAnimationPropTypes = {\n  delay: PropTypes.number,\n  direction: PropTypes.oneOf([\n    'normal',\n    'reverse',\n    'alternate',\n    'alternate-reverse',\n  ]),\n  duration: PropTypes.number,\n  easing: PropTypes.string,\n  easingPreset: PropTypes.string,\n  endDelay: PropTypes.number,\n  fill: PropTypes.oneOf(['backwards', 'forwards', 'both', 'none']),\n  iterationStart: PropTypes.number,\n  iterations: PropTypes.oneOfType([\n    PropTypes.number,\n    PropTypes.oneOf(['infinity', '']),\n  ]),\n};\n\nexport const AnimationProps = {\n  id: PropTypes.string.isRequired,\n  type: PropTypes.oneOf(Object.values(AnimationType)),\n  targets: PropTypes.arrayOf(PropTypes.string),\n  ...GeneralAnimationPropTypes,\n};\n"
  },
  {
    "path": "packages/animation/src/types/storyAnimationState.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum StoryAnimationState {\n  Reset = 'reset',\n  Paused = 'paused',\n  Scrubbing = 'scrubbing',\n  Playing = 'playing',\n  PlayingSelected = 'playing-selected',\n}\n"
  },
  {
    "path": "packages/animation/src/typings/global.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { PropsWithChildren } from 'react';\n\ndeclare global {\n  namespace JSX {\n    interface IntrinsicElements {\n      'amp-story-animation': PropsWithChildren<{\n        layout: string;\n        trigger: string;\n      }>;\n      'amp-animation': PropsWithChildren<{\n        id: string;\n        layout: string;\n      }>;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/animation/src/utils/createKeyframeEffect.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Keyframes, AMPEffectTiming } from '../types';\n\nfunction createKeyframeEffect(\n  target: Element,\n  keyframes: Keyframes,\n  timings: AMPEffectTiming\n) {\n  // Translate AMP timings to Web API timings\n  const convertedTimings: EffectTiming = {\n    ...timings,\n    iterations:\n      timings.iterations === 'infinity'\n        ? Number.POSITIVE_INFINITY\n        : timings.iterations,\n  };\n\n  return new KeyframeEffect(target, keyframes, convertedTimings);\n}\n\nexport default createKeyframeEffect;\n"
  },
  {
    "path": "packages/animation/src/utils/defaultUnit.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const defaultUnit = (input: string | number, unit: string) =>\n  /\\d$/.test(String(input)) ? `${input}${unit}` : input;\n"
  },
  {
    "path": "packages/animation/src/utils/generateLookupMap.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction generateLookupMap(values: number[]) {\n  return values.reduce<Record<number, number[]>>(\n    (acc, currentValue) => ({\n      ...acc,\n      [currentValue]: values.filter((opacity) => opacity !== currentValue),\n    }),\n    {}\n  );\n}\n\nexport default generateLookupMap;\n"
  },
  {
    "path": "packages/animation/src/utils/getDefaultFieldValue.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { FieldType } from '../types';\n\nconst getDefaultFieldValue = (fieldType: FieldType) => {\n  switch (fieldType) {\n    case FieldType.Checkbox:\n      return false;\n    case FieldType.Number:\n    case FieldType.Float:\n    case FieldType.Range:\n      return 0;\n    default:\n      return '';\n  }\n};\n\nexport default getDefaultFieldValue;\n"
  },
  {
    "path": "packages/animation/src/utils/getElementOffsets.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  getMediaSizePositionProps,\n  type Resource,\n} from '@googleforcreators/media';\nimport {\n  getBox,\n  FULLBLEED_HEIGHT,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n  type DimensionableElement,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport type { ScaledElement } from '../types';\n\n// This type also exists in the elements package, but it doesn't\n// really make sense to reuse this one there. This is only for internal\n// use in this file.\ninterface MediaElement extends ScaledElement {\n  resource: Resource;\n  focalX?: number;\n  focalY?: number;\n}\n\nconst PRECISION = 1;\n\nfunction isMediaElement(e: DimensionableElement): e is MediaElement {\n  return 'resource' in e;\n}\n\nexport function getElementOffsets(element: DimensionableElement) {\n  if (!isMediaElement(element)) {\n    return { top: 0, bottom: 0, left: 0, right: 0 };\n  }\n\n  // Get elements box based on a given page size with proper ratio.\n  const box = getBox(element, PAGE_WIDTH, PAGE_HEIGHT);\n  // Calculate media offsets based off given box, focal point\n  const media = getMediaSizePositionProps(\n    element.resource,\n    box.width,\n    box.height,\n    element.scale ?? 1,\n    element.focalX ?? 50,\n    element.focalY ?? 50\n  );\n\n  return {\n    top: (media.offsetY / media.height) * 100,\n    right:\n      -1 * ((media.width - (media.offsetX + PAGE_WIDTH)) / media.width) * 100,\n    left: (media.offsetX / media.width) * 100,\n    bottom:\n      -1 *\n      ((media.height - (media.offsetY + FULLBLEED_HEIGHT)) / media.height) *\n      100,\n  };\n}\n\nexport const DEFAULT_HAS_OFFSETS = {\n  top: false,\n  bottom: false,\n  left: false,\n  right: false,\n};\n\nexport function getHasElementOffsets(element: DimensionableElement) {\n  const offsets = getElementOffsets(element);\n  return Object.fromEntries(\n    Object.entries(offsets).map(([key, offset]) => [\n      key,\n      Math.abs(offset) > PRECISION,\n    ])\n  );\n}\n\n/**\n * Given a media element, calculates where the origin is on the media\n * relative to it's frame, such that scaling the media up or down\n * (with the given transform-origin) most optimistically tries to\n * fill the frame\n *\n * @param offsets Media element offsets\n * @return object containing horizontal and vertical transform origin percentages\n */\nexport function getElementOrigin(\n  offsets = {\n    top: 0,\n    right: 0,\n    bottom: 0,\n    left: 0,\n  }\n) {\n  // If both offsets are 0, we want the origin to be in the middle.\n  // Otherwise we want the percentage of one offset relative to the\n  // other\n  const progress = {\n    vertical: 50,\n    horizontal: 50,\n  };\n  const absOffsets = Object.fromEntries(\n    Object.entries(offsets).map(([key, val]) => [key, Math.abs(val)])\n  );\n  const isSignificant = (val: number) => val >= 0.01;\n  if ([absOffsets.top, absOffsets.bottom].some(isSignificant)) {\n    progress.vertical =\n      (100 * absOffsets.top) / (absOffsets.top + absOffsets.bottom);\n  }\n  if ([absOffsets.left, absOffsets.right].some(isSignificant)) {\n    progress.horizontal =\n      (100 * absOffsets.left) / (absOffsets.left + absOffsets.right);\n  }\n\n  return progress;\n}\n"
  },
  {
    "path": "packages/animation/src/utils/getGlobalSpace.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Element } from '../types';\n\ntype Stringable = string | number | boolean | null | undefined;\ntype ElementWithRotation = Partial<Pick<Element, 'rotationAngle'>>;\n\n/**\n * Just the functional equivalent of your baseline template literal.\n *\n * ```js\n * const args = ['am', 'dog'];\n * literal(['I ', ' a '], ...args)  === `I ${args[0]} a ${args[1]}`; // true\n * ```\n *\n * @param strings strings in template tag\n * @param args arguments in template tag\n * @return string result\n */\nexport function literal(\n  strings: ReadonlyArray<string>,\n  ...args: Stringable[]\n): string {\n  return strings\n    .reduce<Stringable[]>((accum, str, i) => accum.concat([str, args[i]]), [])\n    .join('');\n}\n\n/**\n * Given an element, this function returns a template tag\n * that wraps any given string in a counter transform to reset the\n * global coordinate space, then reapplies the original element\n * transform to retain visual consistency.\n *\n * ```js\n * const glabal = getGlobalSpace(element);\n * const keyframes = [\n *   transform: global`translate3d(0, ${pageHeightInElementPercent}%, 0)`,\n *   transform: 'none'\n * ];\n * ```\n *\n * @param element story element to derive counter transforms off of.\n * @return template string tag that resets transform space.\n */\nexport function getGlobalSpace(element: ElementWithRotation = {}) {\n  const angle = element?.rotationAngle || 0;\n  function global(strings: TemplateStringsArray, ...args: Stringable[]) {\n    return `rotate(${-1 * angle}deg) ${literal(\n      strings,\n      ...args\n    )} rotate(${angle}deg)`;\n  }\n  return angle !== 0 ? global : literal;\n}\n"
  },
  {
    "path": "packages/animation/src/utils/getInitialStyleFromKeyframes.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Keyframes } from '../types';\n\nconst ALLOWLIST = ['opacity', 'transform'];\n\ntype CSSProperty = string | number | null | undefined;\ninterface CSSVariables {\n  [key: `--${string}`]: CSSProperty;\n}\n\n/**\n * Get a key-value pair of custom CSS properties based on keyframes.\n *\n * The styles are used in the output's style[amp-custom].\n *\n * @param keyframes Keyframes.\n * @return Key value pair of initial styles.\n */\nfunction getInitialStyleFromKeyframes(keyframes: Keyframes) {\n  const initialStyle: CSSVariables = {};\n  let frame: Keyframe | null = null;\n\n  if (Array.isArray(keyframes)) {\n    frame = keyframes[0];\n  } else if (typeof keyframes === 'object') {\n    frame = keyframes as Keyframe;\n  }\n\n  if (!frame) {\n    return initialStyle;\n  }\n\n  // Set initial opacity and transforms so that\n  // unspecified opacity & transforms aren't inherited\n  initialStyle['--initial-opacity'] = 1;\n  initialStyle[`--initial-transform`] = 'none';\n\n  Object.entries(frame).forEach(([key, value]) => {\n    if (ALLOWLIST.includes(key.toLowerCase())) {\n      if (Array.isArray(value)) {\n        initialStyle[`--initial-${key}`] = value[0] as CSSProperty;\n      } else {\n        initialStyle[`--initial-${key}`] = value as CSSProperty;\n      }\n    }\n  });\n\n  return initialStyle;\n}\n\nexport default getInitialStyleFromKeyframes;\n"
  },
  {
    "path": "packages/animation/src/utils/getOffPageOffset.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  dataToEditorY,\n  getBox,\n  DANGER_ZONE_HEIGHT,\n  type ElementBox,\n  type DimensionableElement,\n} from '@googleforcreators/units';\n\nfunction calcTopOffset(box: ElementBox, dangerZoneOffset: number): number {\n  const { y, height } = box;\n  const toTop = dangerZoneOffset + y;\n  return -Number(Number((toTop / height) * 100.0 + 100.0).toFixed(5));\n}\n\nfunction calcBottomOffset(box: ElementBox, dangerZoneOffset: number): number {\n  const { y, height } = box;\n  const toBottom = 100 - y + dangerZoneOffset;\n  return Number(Number((toBottom / height) * 100.0).toFixed(5));\n}\n\nfunction calcLeftOffset(box: ElementBox): number {\n  const { x, width } = box;\n  return -Number(Number((x / width) * 100.0 + 100.0).toFixed(5));\n}\n\nfunction calcRightOffset(box: ElementBox): number {\n  const { x, width } = box;\n  const toRight = 100 - x;\n  return Number(Number((toRight / width) * 100.0).toFixed(5));\n}\n\nfunction getOffPageOffset(element: DimensionableElement) {\n  const box = getBox(element, 100, 100);\n  const dangerZoneOffset = dataToEditorY(DANGER_ZONE_HEIGHT, 100);\n\n  return {\n    offsetTop: calcTopOffset(box, dangerZoneOffset),\n    offsetBottom: calcBottomOffset(box, dangerZoneOffset),\n    offsetLeft: calcLeftOffset(box),\n    offsetRight: calcRightOffset(box),\n  };\n}\n\nexport default getOffPageOffset;\n"
  },
  {
    "path": "packages/animation/src/utils/getTotalDuration.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { StoryAnimation } from '../types';\n\nexport function getTotalDuration(animations: StoryAnimation[] = []) {\n  return animations.reduce(\n    (total, { duration = 0, delay = 0 }) => Math.max(total, duration + delay),\n    0\n  );\n}\n"
  },
  {
    "path": "packages/animation/src/utils/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { defaultUnit } from './defaultUnit';\nexport { getGlobalSpace, literal } from './getGlobalSpace';\nexport { default as getOffPageOffset } from './getOffPageOffset';\nexport { getTotalDuration } from './getTotalDuration';\nexport { orderByKeys } from './orderByKeys';\nexport * from './getElementOffsets';\n"
  },
  {
    "path": "packages/animation/src/utils/orderByKeys.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Takes an object and an array of keys that specify how to order\n * properties.\n *\n * If the keys don't appear in the input object, they\n * won't appear in the resulting object.\n *\n * Any properties absent from the keys input will appear in same order\n * as original object properties, but after specified order keys.\n *\n * @param obj Object with keys to be sorted\n * @param keys Keys to prioritize in order\n * @return Input object with ordered keys\n */\nexport function orderByKeys<T>(\n  obj: Record<string, T> = {},\n  keys: string[] = []\n) {\n  const entries = Object.entries(obj);\n  const pos = (s: string) =>\n    keys.includes(s) ? keys.indexOf(s) : Number.MAX_SAFE_INTEGER;\n  entries.sort(([a], [b]) => pos(a) - pos(b));\n  return Object.fromEntries(entries);\n}\n"
  },
  {
    "path": "packages/animation/src/utils/padArray.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction padArray(values: number[], padCount: number) {\n  return values.flatMap((val) => Array<number>(padCount).fill(val));\n}\n\nexport default padArray;\n"
  },
  {
    "path": "packages/animation/src/utils/sanitizeTimings.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming } from '../types';\n\nfunction sanitizeTimings({\n  easing,\n  duration,\n  delay,\n  ...rest\n}: AMPEffectTiming): AMPEffectTiming {\n  return {\n    easing: easing || 'linear',\n    duration: typeof duration === 'number' ? Math.max(duration, 0) : 0,\n    delay: typeof delay === 'number' ? Math.max(delay, 0) : 0,\n    ...rest,\n  };\n}\n\nexport default sanitizeTimings;\n"
  },
  {
    "path": "packages/animation/src/utils/test/createKeyframeEffect.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { AMPEffectTiming } from '../../types';\nimport createKeyframeEffect from '../createKeyframeEffect';\n\ndescribe('createKeyframeEffect', () => {\n  const element = document.createElement('div');\n  const keyframes: Keyframe[] = [];\n  describe('iteration property', () => {\n    it('should swap \"infinity\" with Infinity', () => {\n      const timings: AMPEffectTiming = {\n        iterations: 'infinity',\n      };\n\n      const mockKeyframeEffect = jest.fn();\n      window.KeyframeEffect = mockKeyframeEffect;\n\n      createKeyframeEffect(element, keyframes, timings);\n      expect(mockKeyframeEffect).toHaveBeenCalledWith(element, keyframes, {\n        iterations: Number.POSITIVE_INFINITY,\n      });\n    });\n\n    it('should pass through numbers', () => {\n      const timings = {\n        iterations: 3,\n      };\n\n      const mockKeyframeEffect = jest.fn();\n      window.KeyframeEffect = mockKeyframeEffect;\n\n      createKeyframeEffect(element, keyframes, timings);\n      expect(mockKeyframeEffect).toHaveBeenCalledWith(\n        element,\n        keyframes,\n        timings\n      );\n    });\n\n    it('should pass through other properties', () => {\n      const timings: AMPEffectTiming = {\n        duration: 1000,\n        delay: 500,\n        iterations: 3,\n        easing: 'ease-out',\n        direction: 'normal',\n      };\n\n      const mockKeyframeEffect = jest.fn();\n      window.KeyframeEffect = mockKeyframeEffect;\n\n      createKeyframeEffect(element, keyframes, timings);\n      expect(mockKeyframeEffect).toHaveBeenCalledWith(\n        element,\n        keyframes,\n        timings\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/defaultUnit.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { defaultUnit } from '../defaultUnit';\n\ndescribe('defaultUnit(input, unit)', () => {\n  it('appends the default unit if the input value ends in a digit', () => {\n    const input = 123456;\n    const unit = 'px';\n    expect(defaultUnit(input, unit)).toBe(`${input}${unit}`);\n  });\n\n  it('doesnt append the default unit if the input value ends in a non-digit', () => {\n    const input = '123456%';\n    const unit = 'px';\n    expect(defaultUnit(input, unit)).toStrictEqual(input);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/generateLookupMap.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport generateLookupMap from '../generateLookupMap';\n\ndescribe('generateLookupMap', () => {\n  it('should generate a correct mapping from array', () => {\n    const values = [3, 45, 6, 89, 90];\n    const result = generateLookupMap(values);\n\n    expect(result).toStrictEqual({\n      3: [45, 6, 89, 90],\n      45: [3, 6, 89, 90],\n      6: [3, 45, 89, 90],\n      89: [3, 45, 6, 90],\n      90: [3, 45, 6, 89],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/getElementOffsets.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { getElementOrigin } from '../getElementOffsets';\n\ndescribe('getElementOrigin', () => {\n  it.each([\n    [\n      { top: 1, right: 0, bottom: -1, left: -1 },\n      { horizontal: 100, vertical: 50 },\n    ],\n    [\n      { top: 1, right: 1, bottom: -1, left: 0 },\n      { horizontal: 0, vertical: 50 },\n    ],\n    [\n      { top: 1, right: 1, bottom: 0, left: -1 },\n      { horizontal: 50, vertical: 100 },\n    ],\n    [\n      { top: 0, right: 1, bottom: -1, left: -1 },\n      { horizontal: 50, vertical: 0 },\n    ],\n    [\n      { top: 1, right: 1, bottom: -1, left: -1 },\n      { horizontal: 50, vertical: 50 },\n    ],\n    [\n      { top: 0, right: 0, bottom: 0, left: 0 },\n      { horizontal: 50, vertical: 50 },\n    ],\n  ])('given %p returns %p', (offset, origin) => {\n    expect(getElementOrigin(offset)).toStrictEqual(origin);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/getGlobalSpace.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getGlobalSpace, literal } from '..';\n\ndescribe('literal', () => {\n  it('interpolates the same as a template literal given an empty string', () => {\n    expect(literal([''])).toBe(``);\n  });\n\n  it('interpolates the same as a template literal given some args', () => {\n    const args = ['am', 'dog'];\n    expect(literal(['I ', ' a '], ...args)).toBe(`I ${args[0]} a ${args[1]}`);\n  });\n});\n\ndescribe('getGlobalSpace', () => {\n  it('returns original transform if no element rotation present', () => {\n    const global = getGlobalSpace({});\n    expect(global`translate(3px)`).toBe('translate(3px)');\n  });\n\n  it('wraps the transform in a counter/original transform if rotation present on element', () => {\n    const rotationAngle = 34;\n    const global = getGlobalSpace({\n      rotationAngle,\n    });\n    expect(global`translate(3px)`).toBe(\n      'rotate(-34deg) translate(3px) rotate(34deg)'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/getInitialStyleFromKeyframes.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getInitialStyleFromKeyframes from '../getInitialStyleFromKeyframes';\n\ndescribe('getInitialStyleFromKeyframes', () => {\n  it('should generate initial styles from keyframes array', () => {\n    const keyframes = [\n      { opacity: 1 },\n      { opacity: 0.1, offset: 0.7 },\n      { opacity: 0 },\n    ];\n\n    expect(getInitialStyleFromKeyframes(keyframes)).toStrictEqual({\n      '--initial-opacity': 1,\n      '--initial-transform': 'none',\n    });\n  });\n\n  it('should generate initial styles from keyframes object', () => {\n    const keyframes = {\n      opacity: [0, 1],\n      color: ['#fff', '#000'],\n    };\n\n    expect(getInitialStyleFromKeyframes(keyframes)).toStrictEqual({\n      '--initial-opacity': 0,\n      '--initial-transform': 'none',\n    });\n  });\n\n  it('should ignore special attributes', () => {\n    // easing\n    const easingSample = [\n      { transform: 'scale(0)', easing: 'linear' },\n      { transform: 'scale(0.5)', offset: 0.7 },\n      { transform: 'scale(1)' },\n    ];\n\n    expect(getInitialStyleFromKeyframes(easingSample)).toStrictEqual({\n      '--initial-transform': 'scale(0)',\n      '--initial-opacity': 1,\n    });\n\n    // offset\n    const offsetSample = {\n      opacity: [0, 0.5, 1],\n      transform: ['scale(0.25)', 'scale(3)', 'scale(1)'],\n      offset: [0, 0.25, 1],\n    };\n\n    expect(getInitialStyleFromKeyframes(offsetSample)).toStrictEqual({\n      '--initial-opacity': 0,\n      '--initial-transform': 'scale(0.25)',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/getOffPageOffset.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n  DANGER_ZONE_HEIGHT,\n} from '@googleforcreators/units';\n/**\n * Internal dependencies\n */\nimport getOffPageOffset from '../getOffPageOffset';\n\ndescribe('getOffPageOffset', () => {\n  const element = {\n    x: 20,\n    y: 100,\n    width: 75,\n    height: 50,\n    rotationAngle: 0,\n  };\n\n  it('returns the correct offset to place element on top of page', () => {\n    const { offsetTop } = getOffPageOffset(element);\n    const offset = element.y + element.height + DANGER_ZONE_HEIGHT;\n\n    expect((offsetTop / 100.0) * element.height).toBeCloseTo(-offset);\n  });\n\n  it('returns the correct offset to place element below page', () => {\n    const { offsetBottom } = getOffPageOffset(element);\n    const offset = PAGE_HEIGHT - element.y + DANGER_ZONE_HEIGHT;\n\n    expect((Number(offsetBottom) / 100) * element.height).toBeCloseTo(offset);\n  });\n\n  it('returns the correct offset to place element to the left of the page', () => {\n    const { offsetLeft } = getOffPageOffset(element);\n    const offset = element.x + element.width;\n\n    expect((Number(offsetLeft) / 100.0) * element.width).toBeCloseTo(-offset);\n  });\n\n  it('returns the correct offset to place element to the right of the page', () => {\n    const { offsetRight } = getOffPageOffset(element);\n    const offset = PAGE_WIDTH - element.x;\n\n    expect((Number(offsetRight) / 100.0) * element.width).toBeCloseTo(offset);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/getTotalDuration.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AnimationType } from '../../types';\nimport { getTotalDuration } from '..';\n\nconst BASE_ANIMATION = {\n  id: '1',\n  targets: [],\n};\nconst type = AnimationType.BlinkOn;\n\ndescribe('getTotalDuration', () => {\n  it('returns 0 if no animations supplied', () => {\n    expect(getTotalDuration()).toBe(0);\n  });\n\n  it('calculates the longest duration properly', () => {\n    expect(\n      getTotalDuration([\n        { ...BASE_ANIMATION, type, duration: 20, delay: 10 },\n        { ...BASE_ANIMATION, type, duration: 90, delay: 110 },\n        { ...BASE_ANIMATION, type, duration: 50, delay: 5 },\n      ])\n    ).toBe(200);\n  });\n\n  it('calculates properly if missing duration or delay on animation', () => {\n    expect(\n      getTotalDuration([\n        { ...BASE_ANIMATION, type, duration: 50, delay: 10 },\n        { ...BASE_ANIMATION, type },\n        { ...BASE_ANIMATION, type, duration: 40 },\n      ])\n    ).toBe(60);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/orderByKeys.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { orderByKeys } from '..';\n\ndescribe('orderByKeys', () => {\n  it('reorders properties by keys', () => {\n    const propertyOrder = ['a', 'c', 'b'];\n    const input = {\n      b: 0,\n      a: '',\n      c: false,\n    };\n    const result = orderByKeys(input, propertyOrder);\n\n    expect(result).toStrictEqual(input);\n    expect(Object.keys(result)).toStrictEqual(propertyOrder);\n  });\n\n  it('maintains object equality if keys include property outside of object', () => {\n    const propertyOrder = ['a', 'b', 'c', 'd', 'e'];\n    const input = {\n      b: 0,\n      a: '',\n      c: false,\n    };\n    const result = orderByKeys(input, propertyOrder);\n\n    expect(result).toStrictEqual(input);\n  });\n\n  it('maintains object equality if keys exclude property inside of object', () => {\n    const propertyOrder = ['a'];\n    const input = {\n      b: 0,\n      a: '',\n      c: false,\n    };\n    const result = orderByKeys(input, propertyOrder);\n\n    expect(result).toStrictEqual(input);\n  });\n\n  it('retains order of unspecified keys and orders them after specified keys', () => {\n    const propertyOrder = ['a'];\n    const input = {\n      b: 0,\n      a: '',\n      c: false,\n    };\n    const result = orderByKeys(input, propertyOrder);\n\n    expect(Object.keys(result)).toStrictEqual(['a', 'b', 'c']);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/padArray.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport padArray from '../padArray';\n\ndescribe('padArray', () => {\n  it('should return array with additional padded items', () => {\n    const values = [0, 4, 67, 89.5, 23, 5];\n\n    expect(padArray(values, 2)).toStrictEqual([\n      0, 0, 4, 4, 67, 67, 89.5, 89.5, 23, 23, 5, 5,\n    ]);\n\n    expect(padArray(values, 3)).toStrictEqual([\n      0, 0, 0, 4, 4, 4, 67, 67, 67, 89.5, 89.5, 89.5, 23, 23, 23, 5, 5, 5,\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/animation/src/utils/test/sanitizeTimings.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport sanitizeTimings from '../sanitizeTimings';\n\ndescribe('sanitizeTimings', () => {\n  it.each([\n    [-1, 0],\n    [-0, 0],\n    [0, 0],\n    [1, 1],\n    [12, 12],\n    [51, 51],\n    [500, 500],\n    [2000, 2000],\n  ])(\n    'should sanitize values of `duration` and `delay` animation properties',\n    (value, output) => {\n      const { duration, delay } = sanitizeTimings({\n        duration: value,\n        delay: value,\n      });\n      expect(duration).toBe(output);\n      expect(delay).toBe(output);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/animation/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../media\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../units\" }\n  ],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/commander/README.md",
    "content": "# Commander\n\nBuild/Release Tool for the Web Stories for WordPress plugin.\n"
  },
  {
    "path": "packages/commander/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/commander\",\n  \"description\": \"CLI tool for building the Web Stories WordPress plugin\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"cli\",\n    \"commander\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/commander/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/commander\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"commander\": \"^14.0.1\",\n    \"semver\": \"^7.7.3\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.7.1\",\n    \"@types/semver\": \"^7.7.1\"\n  },\n  \"bin\": {\n    \"commander\": \"./src/index.ts\"\n  }\n}\n"
  },
  {
    "path": "packages/commander/src/index.ts",
    "content": "#!/usr/bin/env bun\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { mkdirSync, rmSync, existsSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport { Command } from 'commander';\nimport { inc as semverInc, type ReleaseType } from 'semver';\n\n/**\n * Internal dependencies\n */\nimport {\n  bundlePlugin,\n  createBuild,\n  getCurrentVersionNumber,\n  updateVersionNumbers,\n  updateCdnUrl,\n  resizeSvgPath,\n} from './utils';\n\nconst PLUGIN_DIR = process.cwd();\nconst PLUGIN_FILE = 'web-stories.php';\nconst BUILD_DIR = 'build/web-stories';\n\nconst program = new Command();\n\nprogram\n  .command('version')\n  .description('Bump the version of the plugin')\n  .argument('[version]', 'The desired version number.')\n  .option(\n    '--nightly',\n    'Whether this is a nightly build and thus should append the current revision to the version number.'\n  )\n  .option(\n    '--increment <level>',\n    `Increment a version by the specified level. Level can\nbe one of: major, minor, patch, premajor, preminor,\nprepatch, or prerelease. Only one version may be specified.`\n  )\n  .option(\n    '--preid <identifier>',\n    `Identifier to be used to prefix premajor, preminor, prepatch or prerelease version increments.`,\n    'alpha'\n  )\n  .on('--help', () => {\n    console.log('');\n    console.log('Examples:');\n    console.log('  # Prepare stable release');\n    console.log('  $ index.js version 1.2.3');\n    console.log('');\n    console.log('  # Nightly build');\n    console.log('  $ index.js version --nightly');\n  })\n  .action(\n    (\n      version: string,\n      {\n        nightly,\n        increment,\n        preid,\n      }: { nightly: boolean; increment: ReleaseType; preid: string }\n    ) => {\n      const pluginFilePath = `${PLUGIN_DIR}/${PLUGIN_FILE}`;\n\n      const currentVersion = getCurrentVersionNumber(pluginFilePath);\n      let newVersion: string | null = version || currentVersion;\n\n      if (increment) {\n        newVersion = semverInc(\n          currentVersion,\n          increment,\n          undefined,\n          preid\n        ) as string;\n      }\n\n      updateVersionNumbers(pluginFilePath, newVersion, nightly);\n      const constantVersion = getCurrentVersionNumber(pluginFilePath, true);\n\n      console.log(\n        `Version number successfully updated! New version: ${constantVersion}`\n      );\n    }\n  );\n\nprogram\n  .command('build-plugin')\n  .option(\n    '--composer',\n    'Create Composer-ready build. Does not contain PHP autoloader.'\n  )\n  .option(\n    '--zip [filename]',\n    'Generate a ready-to-use ZIP file. Optionally specify a file name.'\n  )\n  .option(\n    '--clean',\n    'Delete existing ZIP files in the build/ folder prior to bundling.'\n  )\n  .description('Build Web Stories plugin')\n  .on('--help', () => {\n    console.log('');\n    console.log('Examples:');\n    console.log('  # Create a ZIP-file ready to install in WordPress');\n    console.log('  $ index.js build-plugin --zip');\n    console.log('');\n    console.log('  # Remove existing ZIP files before creating one');\n    console.log('  $ index.js build-plugin --zip --clean');\n    console.log('');\n    console.log(\n      '  # Create a custom-named ZIP-file ready to use with Composer'\n    );\n    console.log('  $ index.js build-plugin --composer --zip web-stories.zip');\n  })\n  .action(\n    ({\n      composer,\n      zip,\n      clean,\n    }: {\n      composer: boolean;\n      zip: string | boolean;\n      clean: boolean;\n    }) => {\n      const buildDirPath = `${PLUGIN_DIR}/${BUILD_DIR}`;\n\n      // Make sure build directory exists and is empty.\n      if (existsSync(BUILD_DIR)) {\n        rmSync(BUILD_DIR, { recursive: true, force: true });\n      }\n      mkdirSync(BUILD_DIR, { recursive: true });\n\n      createBuild(PLUGIN_DIR, buildDirPath, composer);\n\n      let build = BUILD_DIR;\n\n      if (zip) {\n        build = bundlePlugin(buildDirPath, composer, zip, clean);\n      }\n\n      console.log(\n        `Plugin successfully built! Location: ${relative(process.cwd(), build)}`\n      );\n    }\n  );\n\nprogram\n  .command('assets-version')\n  .description('Change the CDN assets version used by the plugin')\n  .argument('<version>', 'Assets version. Either `main` or an integer.')\n  .on('--help', () => {\n    console.log('');\n    console.log('Examples:');\n    console.log(\n      '  # Change assets version to `main` (default, for development builds)'\n    );\n    console.log('  $ commander.js assets-version main');\n    console.log('');\n    console.log('  # Change assets version for stable release');\n    console.log('  $ commander.js assets-version 7');\n  })\n  .action((version: string) => {\n    const pluginFilePath = `${PLUGIN_DIR}/${PLUGIN_FILE}`;\n    updateCdnUrl(\n      pluginFilePath,\n      version === 'main' ? version : Number.parseInt(version)\n    );\n\n    console.log(`Assets CDN URL successfully updated!`);\n  });\n\nprogram\n  .command('normalize-path')\n  .description('Normalize SVG paths for shapes')\n  .argument('<width>', 'Viewbox width')\n  .argument('<height>', 'Viewbox height')\n  .argument('<path>', 'Path to normalize')\n  .on('--help', () => {\n    console.log('');\n    console.log('Example:');\n    console.log('  $ commander.js normalize-path 392 392 \"M10 10\"');\n  })\n  .action((width: string, height: string, path: string) => {\n    console.log(resizeSvgPath(Number(width), Number(height), path));\n  });\n\nprogram.parse(process.argv);\n"
  },
  {
    "path": "packages/commander/src/utils/appendRevisionToVersion.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { execSync } from 'node:child_process';\n\n/**\n * Appends the current revision to the version number for nightly builds.\n *\n * Follows semantic versioning guidelines to denote build metadata by\n * appending a plus sign.\n *\n * @see https://semver.org/\n * @param version Version number.\n * @return Modified version.\n */\nfunction appendRevisionToVersion(version: string): string {\n  // Get the current commit hash. Used for pre-releases.\n  // GITHUB_SHA is available during the GitHub Actions workflow.\n  const currentCommitHash = process.env.GITHUB_SHA\n    ? process.env.GITHUB_SHA.slice(0, 7)\n    : execSync('git rev-parse --short=7 HEAD').toString().trim();\n\n  return `${version}+${currentCommitHash}`;\n}\n\nexport default appendRevisionToVersion;\n"
  },
  {
    "path": "packages/commander/src/utils/bundlePlugin.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { dirname } from 'node:path';\n\n/**\n * Internal dependencies\n */\nimport generateZipFile from './generateZipFile';\nimport deleteExistingZipFiles from './deleteExistingZipFiles';\nimport getCurrentVersionNumber from './getCurrentVersionNumber';\n\n/**\n * Main function to bundle the plugin.\n *\n * @param source Path to the source directory.\n * @param [composer] Create Composer-ready ZIP file without PHP autoloader.\n * @param zip Whether a ZIP file should be generated. Pass a string to set a custom file name.\n * @param [clean] Whether to delete existing ZIP file.\n * @return Path to the build directory or ZIP file.\n */\nfunction bundlePlugin(\n  source: string,\n  composer = false,\n  zip: boolean | string = true,\n  clean = false\n): string {\n  const pluginFile = `${source}/web-stories.php`;\n\n  if (clean) {\n    deleteExistingZipFiles(dirname(source));\n  }\n\n  const currentVersion = getCurrentVersionNumber(pluginFile, true);\n  const defaultZipName = !composer\n    ? `web-stories-${currentVersion}.zip`\n    : `web-stories-${currentVersion}-composer.zip`;\n  const zipName = typeof zip === 'string' ? zip : defaultZipName;\n  generateZipFile(source, zipName);\n  return `${dirname(source)}/${zipName}`;\n}\n\nexport default bundlePlugin;\n"
  },
  {
    "path": "packages/commander/src/utils/copyFiles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { execFileSync } from 'node:child_process';\n\n/**\n * Copies all files minuses ignored ones from source to target directory.\n *\n * @param source Path to source directory.\n * @param target Path to target directory.\n * @param ignoredFiles List of ignored files.\n */\nfunction copyFiles(source: string, target: string, ignoredFiles: string[]) {\n  const excludeList = ignoredFiles.reduce((acc: string[], file) => {\n    acc.push('--exclude');\n    acc.push(file);\n    return acc;\n  }, []);\n\n  // Copy plugin folder to temporary location.\n  const args = ['-a', ...excludeList, `${source}/`, `${target}/`];\n  execFileSync('rsync', args, {\n    stdio: ['pipe', 'pipe', 'ignore'],\n  });\n}\n\nexport default copyFiles;\n"
  },
  {
    "path": "packages/commander/src/utils/createBuild.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport copyFiles from './copyFiles';\nimport getIgnoredFiles from './getIgnoredFiles';\n\n/**\n * Main function to bundle the plugin.\n *\n * @param source Path to the source directory.\n * @param target Path to target directory.\n * @param [composer] Create Composer-ready ZIP file without PHP autoloader.\n */\nfunction createBuild(source: string, target: string, composer = false) {\n  const ignoredFiles = getIgnoredFiles(source);\n\n  if (composer) {\n    ignoredFiles.push('includes/vendor/');\n  } else {\n    ignoredFiles.push('composer.json');\n  }\n\n  copyFiles(source, target, ignoredFiles);\n}\n\nexport default createBuild;\n"
  },
  {
    "path": "packages/commander/src/utils/deleteExistingZipFiles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readdirSync, unlinkSync } from 'node:fs';\n\n/**\n * Removes all existing ZIP files in the build folder.\n *\n * @param buildDir Path to the build directory.\n */\nfunction deleteExistingZipFiles(buildDir: string) {\n  const fileNamePattern = /^.*\\.zip$/;\n  const zipFiles = readdirSync(buildDir).filter((file) =>\n    fileNamePattern.test(file)\n  );\n\n  for (const file of zipFiles) {\n    unlinkSync(`${buildDir}/${file}`);\n  }\n}\n\nexport default deleteExistingZipFiles;\n"
  },
  {
    "path": "packages/commander/src/utils/generateZipFile.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { dirname, basename, join } from 'node:path';\nimport { execFileSync } from 'node:child_process';\nimport { existsSync, unlinkSync } from 'node:fs';\n\n/**\n * Generates a ZIP file.\n *\n * Ensures the folder in the final ZIP file is always named \"web-stories\".\n *\n * @param source Full path to the directory that should be zipped.\n * @param zipName Desired file name.\n */\nfunction generateZipFile(source: string, zipName: string) {\n  const cwd = dirname(source); // /full/path/to/build\n  const fullPath = join(source, zipName);\n\n  if (existsSync(fullPath)) {\n    unlinkSync(fullPath);\n  }\n\n  const args = ['-rT', zipName, basename(source)];\n  execFileSync('zip', args, {\n    cwd,\n    stdio: ['pipe', 'pipe', 'ignore'],\n  });\n}\n\nexport default generateZipFile;\n"
  },
  {
    "path": "packages/commander/src/utils/getCurrentVersionNumber.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readFileSync } from 'node:fs';\n\nconst VERSION_REGEX = /\\* Version:(.+)/;\nconst VERSION_CONSTANT_REGEX =\n  /define\\(\\s*'WEBSTORIES_VERSION',\\s*'([^']*)'\\s*\\);/;\n\n/**\n * Returns the current version number as found in the main plugin file's header.\n *\n * @param pluginFile Path to the main plugin file.\n * @param constant Whether to extract the version from the WEBSTORIES_VERSION constant instead.\n * @return Version number\n */\nfunction getCurrentVersionNumber(pluginFile: string, constant = false): string {\n  const pluginFileContent = readFileSync(pluginFile, 'utf8');\n\n  if (!constant) {\n    return pluginFileContent.match(VERSION_REGEX)?.[1]?.trim() as string;\n  }\n\n  return pluginFileContent.match(VERSION_CONSTANT_REGEX)?.[1]?.trim() as string;\n}\n\nexport default getCurrentVersionNumber;\n"
  },
  {
    "path": "packages/commander/src/utils/getIgnoredFiles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { existsSync, lstatSync, readFileSync } from 'node:fs';\n\n/**\n * Returns a list of files that should be ignored based on the .distignore file.\n *\n * @param source Path to the plugin root folder where the .distignore file is expected.\n * @return List of files.\n */\nfunction getIgnoredFiles(source: string): string[] {\n  const distignore = source + '/.distignore';\n\n  if (!existsSync(distignore)) {\n    return [];\n  }\n\n  const maybeIgnoredFiles = readFileSync(distignore, 'utf8').split('\\n');\n  const ignoredFiles: string[] = [];\n\n  for (const line of maybeIgnoredFiles) {\n    const file = line.trim();\n\n    if (file === '') {\n      continue;\n    }\n\n    if (file.startsWith('#')) {\n      continue;\n    }\n\n    const fileFromRoot = `${source}/${file}`;\n\n    if (!existsSync(fileFromRoot)) {\n      continue;\n    }\n\n    if (lstatSync(fileFromRoot).isDirectory()) {\n      ignoredFiles.push(`${file}/`);\n    } else {\n      ignoredFiles.push(file);\n    }\n  }\n\n  return ignoredFiles;\n}\n\nexport default getIgnoredFiles;\n"
  },
  {
    "path": "packages/commander/src/utils/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as bundlePlugin } from './bundlePlugin';\nexport { default as createBuild } from './createBuild';\nexport { default as getCurrentVersionNumber } from './getCurrentVersionNumber';\nexport { default as updateVersionNumbers } from './updateVersionNumbers';\nexport { default as updateCdnUrl } from './updateCdnUrl';\nexport { default as resizeSvgPath } from './resizeSvgPath';\n"
  },
  {
    "path": "packages/commander/src/utils/resizeSvgPath.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default function resizeSvgPath(x: number, y: number, path: string) {\n  const coords = path\n    .replace(/\\s*(-)/g, ' $1')\n    .replace(/\\s*([A-Za-z,])\\s*/g, ' $1 ')\n    .split(' ');\n  let coordIndex = 0;\n  return coords.reduce((acc, value) => {\n    const parsed = Number.parseFloat(value);\n    if (!isNaN(parsed)) {\n      const scaled = coordIndex % 2 === 0 ? parsed / x : parsed / y;\n      return `${acc} ${scaled.toFixed(6)}`;\n    }\n    coordIndex = 0;\n    return `${acc} ${value}`;\n  }, '');\n}\n"
  },
  {
    "path": "packages/commander/src/utils/test/appendRevisionToVersion.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport appendRevisionToVersion from '../appendRevisionToVersion';\n\njest.mock('node:child_process', () => {\n  return {\n    execSync: () => '1234567',\n  };\n});\n\ndescribe('appendRevisionToVersion', () => {\n  it('should get the current git commit hash', () => {\n    const orig = process.env.GITHUB_SHA;\n    delete process.env.GITHUB_SHA;\n    const result = appendRevisionToVersion('1.2.3');\n    expect(result).toBe('1.2.3+1234567');\n    process.env.GITHUB_SHA = orig;\n  });\n\n  it('should use the provided git commit hash', () => {\n    process.env.GITHUB_SHA = 'abc1234';\n    const result = appendRevisionToVersion('1.2.3');\n    expect(result).toBe('1.2.3+abc1234');\n    delete process.env.GITHUB_SHA;\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/bundlePlugin.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport bundlePlugin from '../bundlePlugin';\nimport generateZipFile from '../generateZipFile';\nimport getCurrentVersionNumber from '../getCurrentVersionNumber';\nimport deleteExistingZipFiles from '../deleteExistingZipFiles';\n\njest.mock('node:fs');\njest.mock('node:child_process');\n\njest.mock('../generateZipFile');\njest.mock('../getCurrentVersionNumber');\njest.mock('../deleteExistingZipFiles');\n\ndescribe('bundlePlugin', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/web-stories/plugin.php': '',\n    '/foo/web-stories/readme.txt': '',\n    '/foo/web-stories/.distignore': 'example.txt',\n  };\n\n  beforeEach(() => {\n    getCurrentVersionNumber.mockImplementation(() => 'foobar');\n\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  it('should create ZIP file with automatically determined file name', () => {\n    const result = bundlePlugin('/foo/web-stories', false, true);\n    expect(result).toBe('/foo/web-stories-foobar.zip');\n    expect(generateZipFile).toHaveBeenCalledWith(\n      '/foo/web-stories',\n      'web-stories-foobar.zip'\n    );\n  });\n\n  it('should create ZIP file with automatically determined file name for composer build', () => {\n    const result = bundlePlugin('/foo/web-stories', true, true);\n    expect(result).toBe('/foo/web-stories-foobar-composer.zip');\n    expect(generateZipFile).toHaveBeenCalledWith(\n      '/foo/web-stories',\n      'web-stories-foobar-composer.zip'\n    );\n  });\n\n  it('should create ZIP file with custom file name', () => {\n    const result = bundlePlugin('/foo/web-stories', false, 'my-plugin.zip');\n    expect(result).toBe('/foo/my-plugin.zip');\n    expect(generateZipFile).toHaveBeenCalledWith(\n      '/foo/web-stories',\n      'my-plugin.zip'\n    );\n    expect(deleteExistingZipFiles).toHaveBeenCalledTimes(0);\n  });\n\n  it('should delete existing ZIP files if asked', () => {\n    bundlePlugin('/foo', false, true, true);\n    expect(deleteExistingZipFiles).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/copyFiles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { execFileSync } from 'node:child_process';\n\n/**\n * Internal dependencies\n */\nimport copyFiles from '../copyFiles';\n\njest.mock('node:child_process');\n\ndescribe('copyFiles', () => {\n  it('should sync source files to target', () => {\n    copyFiles('foo', 'foo/target', ['bar.txt', 'baz/']);\n    expect(execFileSync).toHaveBeenLastCalledWith(\n      'rsync',\n      [\n        '-a',\n        '--exclude',\n        'bar.txt',\n        '--exclude',\n        'baz/',\n        'foo/',\n        'foo/target/',\n      ],\n      expect.anything()\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/createBuild.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport createBuild from '../createBuild';\nimport copyFiles from '../copyFiles';\n\njest.mock('node:fs');\n\njest.mock('../getIgnoredFiles', () => jest.fn(() => ['bar.txt', 'baz/']));\njest.mock('../copyFiles');\n\ndescribe('createBuild', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/plugin.php': '',\n    '/foo/readme.txt': '',\n    '/foo/.distignore': 'example.txt',\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  it('should copy files to build directory', () => {\n    createBuild('/foo', '/foo/build/web-stories');\n    expect(copyFiles).toHaveBeenCalledWith('/foo', '/foo/build/web-stories', [\n      'bar.txt',\n      'baz/',\n      'composer.json',\n    ]);\n  });\n\n  it('should ignore third-party folder for composer builds', () => {\n    createBuild('/foo', '/foo/build/web-stories', true);\n    expect(copyFiles).toHaveBeenCalledWith('/foo', '/foo/build/web-stories', [\n      'bar.txt',\n      'baz/',\n      'includes/vendor/',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/deleteExistingZipFiles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles, readdirSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport deleteExistingZipFiles from '../deleteExistingZipFiles';\n\njest.mock('node:fs');\n\ndescribe('deleteExistingZipFiles', () => {\n  const MOCK_FILE_INFO = {\n    '/build/web-stories.zip': '',\n    '/build/web-stories-1.0.0.zip': '',\n    '/build/web-stories-1.0.0+1234567.zip': '',\n    '/build/unrelated.zip': '',\n    '/build/notazipfile.txt': '',\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should delete all existing ZIP files', () => {\n    const filesBefore = readdirSync('/build');\n    deleteExistingZipFiles('/build');\n    const filesAfter = readdirSync('/build');\n\n    expect(filesBefore).toIncludeAllMembers([\n      'web-stories.zip',\n      'web-stories-1.0.0.zip',\n      'web-stories-1.0.0+1234567.zip',\n      'notazipfile.txt',\n      'unrelated.zip',\n    ]);\n\n    expect(filesAfter).toIncludeAllMembers(['notazipfile.txt']);\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/generateZipFile.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { execFileSync } from 'node:child_process';\n\n/**\n * Internal dependencies\n */\nimport generateZipFile from '../generateZipFile';\n\njest.mock('node:child_process');\n\ndescribe('generateZipFile', () => {\n  it('should ZIP the web-stories directory', () => {\n    generateZipFile(\n      '/full/path/to/build/web-stories',\n      'web-stories-stable.zip'\n    );\n    expect(execFileSync).toHaveBeenLastCalledWith(\n      'zip',\n      ['-rT', 'web-stories-stable.zip', 'web-stories'],\n      expect.objectContaining({\n        cwd: '/full/path/to/build',\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/getCurrentVersionNumber.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport getCurrentVersionNumber from '../getCurrentVersionNumber';\n\njest.mock('node:fs');\n\nconst PLUGIN_FILE_CONTENT = `\n<?php\n/**\n * Main plugin file.\n\n * Plugin Name: Web Stories\n * Description: Visual storytelling for WordPress.\n * Plugin URI: https://github.com/googleforcreators/web-stories-wp\n * Author: Google\n * Author URI: https://opensource.google.com/\n * Version: 1.0.0-alpha\n * Requires at least: 5.3\n * Requires PHP: 5.6\n * Text Domain: web-stories\n * Domain Path: /languages/\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n */\n\n define( 'WEBSTORIES_VERSION', '1.0.0-alpha+1234567' );\n`;\n\ndescribe('getCurrentVersionNumber', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/plugin.php': PLUGIN_FILE_CONTENT,\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should read the plugin version from the file header', () => {\n    expect(getCurrentVersionNumber('/foo/plugin.php')).toBe('1.0.0-alpha');\n  });\n\n  it('should read the plugin version from the WEBSTORIES_VERSION constant', () => {\n    expect(getCurrentVersionNumber('/foo/plugin.php', true)).toBe(\n      '1.0.0-alpha+1234567'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/getIgnoredFiles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport getIgnoredFiles from '../getIgnoredFiles';\n\njest.mock('node:fs');\n\ndescribe('getIgnoredFiles', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/.distignore': `\n      example.txt\n\n      # somefile.php\n\n      doesnotexist.txt\n\n      sub\n    `,\n    '/foo/example.txt': '',\n    '/foo/somefile.php': '',\n    '/foo/someotherfile.js': '',\n    '/foo/baz/example.txt': '',\n    '/foo/sub/folder.txt': '',\n    '/bar/example.txt': '',\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should return empty array if there is no .distignore file', () => {\n    expect(getIgnoredFiles('/bar')).toStrictEqual([]);\n  });\n\n  it('should ignore commented out lines', () => {\n    expect(getIgnoredFiles('/foo')).not.toContain('somefile.php');\n  });\n\n  it('should ignore non-existent files', () => {\n    expect(getIgnoredFiles('/foo')).not.toContain('doesnotexist.txt');\n  });\n\n  it('should add trailing slashes to directories', () => {\n    expect(getIgnoredFiles('/foo')).toContain('sub/');\n  });\n\n  it('should return all ignored files', () => {\n    expect(getIgnoredFiles('/foo')).toIncludeSameMembers([\n      'example.txt',\n      'sub/',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/resizeSvgPaths.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport resizeSvgPath from '../resizeSvgPath';\n\ndescribe('resizeSvgPaths', () => {\n  it('should resize paths', () => {\n    const actual = resizeSvgPath(\n      // viewbox width\n      392,\n      // viewbox height\n      392,\n      // path to normalize\n      `M392,196c0,108.25-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0S392,87.75,392,196z M196,30\n\tc-44.34,0-86.03,17.27-117.38,48.62C47.27,109.97,30,151.66,30,196s17.27,86.03,48.62,117.38C109.97,344.73,151.66,362,196,362\n\ts86.03-17.27,117.38-48.62C344.73,282.03,362,240.34,362,196s-17.27-86.03-48.62-117.38C282.03,47.27,240.34,30,196,30 M196,0\n\tc108.25,0,196,87.75,196,196s-87.75,196-196,196S0,304.25,0,196S87.75,0,196,0L196,0z`\n    );\n\n    expect(actual).toBe(\n      '  M 1.000000 , 0.500000 c 0.000000 , 0.276148 -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 S 1.000000 , 0.223852 , 1.000000 , 0.500000 z  M 0.500000 , 0.076531 c -0.113112 , 0.000000 -0.219464 , 0.044056 -0.299439 , 0.124031 C 0.120587 , 0.280536 , 0.076531 , 0.386888 , 0.076531 , 0.500000 s 0.044056 , 0.219464 , 0.124031 , 0.299439 C 0.280536 , 0.879413 , 0.386888 , 0.923469 , 0.500000 , 0.923469 s 0.219464 -0.044056 , 0.299439 -0.124031 C 0.879413 , 0.719464 , 0.923469 , 0.613112 , 0.923469 , 0.500000 s -0.044056 -0.219464 -0.124031 -0.299439 C 0.719464 , 0.120587 , 0.613112 , 0.076531 , 0.500000 , 0.076531 M 0.500000 , 0.000000 c 0.276148 , 0.000000 , 0.500000 , 0.223852 , 0.500000 , 0.500000 s -0.223852 , 0.500000 -0.500000 , 0.500000 S 0.000000 , 0.776148 , 0.000000 , 0.500000 S 0.223852 , 0.000000 , 0.500000 , 0.000000 L 0.500000 , 0.000000 z '\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/updateCdnUrl.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles, readFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport updateCdnUrl from '../updateCdnUrl';\n\njest.mock('node:fs');\n\nconst PLUGIN_FILE_CONTENT = `\n<?php\n/**\n * Main plugin file.\n\n * Plugin Name: Web Stories\n * Description: Visual storytelling for WordPress.\n * Plugin URI: https://github.com/googleforcreators/web-stories-wp\n * Author: Google\n * Author URI: https://opensource.google.com/\n * Version: 1.0.0-alpha\n * Requires at least: 5.3\n * Requires PHP: 5.6\n * Text Domain: web-stories\n * Domain Path: /languages/\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n */\n\n define( 'WEBSTORIES_CDN_URL', 'https://wp.stories.google/static/main' );\n`;\n\ndescribe('updateCdnUrl', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/plugin.php': PLUGIN_FILE_CONTENT,\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should update CDN  URL', () => {\n    updateCdnUrl('/foo/plugin.php', '7.8.9');\n    const pluginFile = readFileSync('/foo/plugin.php');\n\n    expect(pluginFile).toContain(\n      `define( 'WEBSTORIES_CDN_URL', 'https://wp.stories.google/static/7.8.9' );`\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/test/updateVersionNumbers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles, readFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport updateVersionNumbers from '../updateVersionNumbers';\n\njest.mock('node:fs');\njest.mock('../appendRevisionToVersion', () =>\n  jest.fn(() => '1.0.0-alpha+1234567')\n);\n\nconst PLUGIN_FILE_CONTENT = `\n<?php\n/**\n * Main plugin file.\n\n * Plugin Name: Web Stories\n * Description: Visual storytelling for WordPress.\n * Plugin URI: https://github.com/googleforcreators/web-stories-wp\n * Author: Google\n * Author URI: https://opensource.google.com/\n * Version: 1.0.0-alpha\n * Requires at least: 5.3\n * Requires PHP: 5.6\n * Text Domain: web-stories\n * Domain Path: /languages/\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n */\n\n define( 'WEBSTORIES_VERSION', '1.0.0-alpha' );\n`;\n\ndescribe('updateVersionNumbers', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/plugin.php': PLUGIN_FILE_CONTENT,\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should use provided version number', () => {\n    updateVersionNumbers('/foo/plugin.php', '7.8.9');\n    const pluginFile = readFileSync('/foo/plugin.php');\n\n    expect(pluginFile).toContain('* Version: 7.8.9');\n    expect(pluginFile).toContain(`define( 'WEBSTORIES_VERSION', '7.8.9' );`);\n  });\n\n  it('should update plugin header for pre-release', () => {\n    updateVersionNumbers('/foo/plugin.php', '7.8.9-alpha');\n    const pluginFile = readFileSync('/foo/plugin.php');\n\n    expect(pluginFile).toContain('* Version: 7.8.9-alpha');\n    expect(pluginFile).toContain(\n      `define( 'WEBSTORIES_VERSION', '7.8.9-alpha' );`\n    );\n  });\n\n  it('should not update plugin header for nightly build', () => {\n    updateVersionNumbers('/foo/plugin.php', '1.0.0-alpha', true);\n    const pluginFile = readFileSync('/foo/plugin.php');\n\n    expect(pluginFile).toContain('* Version: 1.0.0');\n    expect(pluginFile).not.toContain('* Version: 7.8.9-alpha');\n    expect(pluginFile).toContain(\n      `define( 'WEBSTORIES_VERSION', '1.0.0-alpha+1234567' );`\n    );\n  });\n});\n"
  },
  {
    "path": "packages/commander/src/utils/updateCdnUrl.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readFileSync, writeFileSync } from 'node:fs';\n\nconst CDN_BASE_URL = 'https://wp.stories.google/static/';\nconst CDN_URL_CONSTANT_REGEX =\n  /define\\(\\s*'WEBSTORIES_CDN_URL',\\s*'([^']*)'\\s*\\);/;\n\n/**\n * Updates CDN URL in the main plugin file.\n *\n * Namely, this updates the `WEBSTORIES_CDN_URL` constant in the main plugin file.\n *\n * @param pluginFile Path to the plugin file.\n * @param version Desired version number. Either 'main' or an integer.\n */\nfunction updateCdnURL(pluginFile: string, version: string | number) {\n  let pluginFileContent = readFileSync(pluginFile, 'utf8');\n\n  pluginFileContent = pluginFileContent.replace(CDN_URL_CONSTANT_REGEX, () => {\n    return `define( 'WEBSTORIES_CDN_URL', '${CDN_BASE_URL}${version}' );`;\n  });\n\n  writeFileSync(pluginFile, pluginFileContent);\n}\n\nexport default updateCdnURL;\n"
  },
  {
    "path": "packages/commander/src/utils/updateVersionNumbers.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readFileSync, writeFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport appendRevisionToVersion from './appendRevisionToVersion';\n\nconst VERSION_REGEX = /\\* Version:(.+)/;\nconst VERSION_CONSTANT_REGEX =\n  /define\\(\\s*'WEBSTORIES_VERSION',\\s*'([^']*)'\\s*\\);/;\n\n/**\n * Updates version numbers in plugin files.\n *\n * Namely, this updates the 'Version' header in the main plugin file\n * and the `WEBSTORIES_VERSION` constant in the same file\n *\n * If a specific version is provided, uses that version to update the constant.\n *\n * @param pluginFile Path to the plugin file.\n * @param version Desired version number.\n * @param [nightly] Whether this is a nightly build or not.\n */\nfunction updateVersionNumbers(\n  pluginFile: string,\n  version: string,\n  nightly = false\n) {\n  let pluginFileContent = readFileSync(pluginFile, 'utf8');\n\n  if (!nightly) {\n    // 'Version' plugin header must not include anything else beyond the version number,\n    // i.e. no suffixes or similar.\n    pluginFileContent = pluginFileContent.replace(\n      VERSION_REGEX,\n      `* Version: ${version}`\n    );\n  }\n\n  const newVersion = nightly ? appendRevisionToVersion(version) : version;\n\n  pluginFileContent = pluginFileContent.replace(VERSION_CONSTANT_REGEX, () => {\n    return `define( 'WEBSTORIES_VERSION', '${newVersion}' );`;\n  });\n\n  writeFileSync(pluginFile, pluginFileContent);\n}\n\nexport default updateVersionNumbers;\n"
  },
  {
    "path": "packages/commander/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/dashboard/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/dashboard/README.md",
    "content": "# Dashboard\n\nWeb stories core dashboard.\n"
  },
  {
    "path": "packages/dashboard/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/dashboard\",\n  \"description\": \"The core Web Stories dashboard web application, which is platform-agnostic.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/dashboard/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/dashboard\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.js\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.js\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/animation\": \"*\",\n    \"@googleforcreators/date\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/element-library\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/migration\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/templates\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"flagged\": \"^2.0.10\",\n    \"history\": \"^5.3.0\",\n    \"prop-types\": \"^15.8.1\",\n    \"styled-components\": \"^5.3.11\",\n    \"stylis-plugin-rtl\": \"^1.0.0\"\n  },\n  \"devDependencies\": {\n    \"@googleforcreators/karma-fixture\": \"*\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"jest\": \"^29.6.1\",\n    \"react\": \"^17.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/api/apiProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport useStoryApi from './useStoryApi';\nimport useTemplateApi from './useTemplateApi';\nimport useUsersApi from './useUsersApi';\nimport useTaxonomyApi from './useTaxonomyApi';\nimport ApiContext from './context';\n\nexport default function ApiProvider({ children }) {\n  const { api: usersApi } = useUsersApi();\n  const { api: taxonomyApi } = useTaxonomyApi();\n  const { templates, api: templateApi } = useTemplateApi();\n  const { stories, api: storyApi } = useStoryApi();\n\n  const value = {\n    state: {\n      stories,\n      templates,\n    },\n    actions: {\n      storyApi,\n      templateApi,\n      usersApi,\n      taxonomyApi,\n    },\n  };\n\n  return <ApiContext.Provider value={value}>{children}</ApiContext.Provider>;\n}\n\nApiProvider.propTypes = {\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/api/context.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nconst ApiContext = createContext({ state: {}, actions: {} });\n\nexport default ApiContext;\n"
  },
  {
    "path": "packages/dashboard/src/app/api/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as ApiProvider } from './apiProvider';\n"
  },
  {
    "path": "packages/dashboard/src/app/api/test/apiProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport ApiProvider from '../apiProvider';\nimport { ConfigProvider } from '../../config';\nimport useApi from '../useApi';\n\nconst fetchStories = () => {\n  return Promise.resolve({\n    stories: {\n      123: {\n        id: 123,\n        status: 'publish',\n        title: 'Carlos',\n        created: '1970-01-01T00:00:00.000',\n        createdGmt: '1970-01-01T00:00:00.000Z',\n        modified: '1970-01-01T00:00:00.000',\n        modifiedGmt: '1970-01-01T00:00:00.000Z',\n        author: {\n          name: 'admin',\n          id: 1,\n        },\n        locked: false,\n        lockUser: {\n          id: 0,\n          name: '',\n          avatar: null,\n        },\n        bottomTargetAction:\n          'https://www.story-link.com/wp-admin/post.php?id=123',\n        featuredMediaUrl: 'https://www.featured-media-123',\n        editStoryLink: 'https://www.story-link.com/wp-admin/post.php?id=123',\n        previewLink: 'https://www.story-link.com/?preview=true',\n        link: 'https://www.story-link.com',\n        capabilities: {\n          hasEditAction: false,\n          hasDeleteAction: false,\n        },\n      },\n    },\n    fetchedStoryIds: [5],\n    totalPages: 1,\n    totalStoriesByStatus: {\n      all: 1,\n      publish: 1,\n      draft: 0,\n    },\n  });\n};\n\nconst storyResponse = (story) => {\n  let title = '';\n  let id = story.id || 456;\n  if (story?.original_id) {\n    id = 456;\n    title = 'Carlos (Copy)';\n  } else {\n    title = typeof story.title === 'string' ? story.title : story.title.raw;\n  }\n\n  return Promise.resolve({\n    id,\n    status: 'publish',\n    title,\n    created: '1970-01-01T00:00:00.000',\n    createdGmt: '1970-01-01T00:00:00.000Z',\n    modified: '1970-01-01T00:00:00.000',\n    modifiedGmt: '1970-01-01T00:00:00.000Z',\n    author: {\n      name: 'admin',\n      id: 1,\n    },\n    locked: false,\n    lockUser: {\n      id: 0,\n      name: '',\n      avatar: null,\n    },\n    bottomTargetAction: `https://www.story-link.com/wp-admin/post.php?id=${id}`,\n    featuredMediaUrl: `https://www.featured-media-${id}`,\n    editStoryLink: `https://www.story-link.com/wp-admin/post.php?id=${id}`,\n    previewLink: 'https://www.story-link.com/?preview=true',\n    link: 'https://www.story-link.com',\n    capabilities: {\n      hasEditAction: false,\n      hasDeleteAction: false,\n    },\n  });\n};\n\nconst updateStory = (story) => {\n  return storyResponse(story);\n};\n\nconst duplicateStory = (story) => {\n  story.original_id = story.id;\n\n  return storyResponse(story);\n};\n\nconst trashStory = ({ id }) => {\n  return Promise.resolve({\n    id,\n    status: 'publish',\n    title: { raw: 'Carlos', rendered: 'Carlos' },\n    modified: '1970-01-01T00:00:00.000',\n    modifiedGmt: '1970-01-01T00:00:00.000',\n    date: '1970-01-01T00:00:00.000',\n    dateGmt: '1970-01-01T00:00:00.000',\n    link: 'https://www.story-link.com',\n    editLink: 'https://www.story-link.com/wp-admin/post.php?id=' + id,\n  });\n};\n\ndescribe('ApiProvider', () => {\n  it('should return a story in state data when the API request is fired', async () => {\n    const { result } = renderHook(() => useApi(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            apiCallbacks: { fetchStories },\n          }}\n        >\n          <ApiProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    expect(result.current.state.stories.stories).toStrictEqual({\n      123: {\n        bottomTargetAction:\n          'https://www.story-link.com/wp-admin/post.php?id=123',\n        capabilities: {\n          hasDeleteAction: false,\n          hasEditAction: false,\n        },\n        editStoryLink: 'https://www.story-link.com/wp-admin/post.php?id=123',\n        id: 123,\n        modified: '1970-01-01T00:00:00.000',\n        modifiedGmt: '1970-01-01T00:00:00.000Z',\n        featuredMediaUrl: 'https://www.featured-media-123',\n        created: '1970-01-01T00:00:00.000',\n        createdGmt: '1970-01-01T00:00:00.000Z',\n        author: {\n          name: 'admin',\n          id: 1,\n        },\n        link: 'https://www.story-link.com',\n        lockUser: {\n          avatar: null,\n          id: 0,\n          name: '',\n        },\n        locked: false,\n        previewLink: 'https://www.story-link.com/?preview=true',\n        status: 'publish',\n        title: 'Carlos',\n      },\n    });\n  });\n\n  it('should return an updated story in state data when the API request is fired', async () => {\n    const { result } = renderHook(() => useApi(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            apiCallbacks: { fetchStories, updateStory },\n          }}\n        >\n          <ApiProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.updateStory({\n        id: 123,\n        modified: undefined,\n        status: 'publish',\n        title: { raw: 'New Title' },\n        link: 'https://www.story-link.com',\n        editLink: 'https://www.story-link.com/wp-admin/post.php?id=123',\n      });\n    });\n\n    expect(result.current.state.stories.stories).toStrictEqual({\n      123: {\n        bottomTargetAction:\n          'https://www.story-link.com/wp-admin/post.php?id=123',\n        capabilities: {\n          hasDeleteAction: false,\n          hasEditAction: false,\n        },\n        featuredMediaUrl: 'https://www.featured-media-123',\n        editStoryLink: 'https://www.story-link.com/wp-admin/post.php?id=123',\n        id: 123,\n        modified: '1970-01-01T00:00:00.000',\n        modifiedGmt: '1970-01-01T00:00:00.000Z',\n        created: '1970-01-01T00:00:00.000',\n        createdGmt: '1970-01-01T00:00:00.000Z',\n        author: {\n          name: 'admin',\n          id: 1,\n        },\n        link: 'https://www.story-link.com',\n        lockUser: {\n          avatar: null,\n          id: 0,\n          name: '',\n        },\n        locked: false,\n        previewLink: 'https://www.story-link.com/?preview=true',\n        status: 'publish',\n        title: 'New Title',\n      },\n    });\n  });\n\n  it('should return a duplicated story in state data when the duplicate method is called.', async () => {\n    const { result } = renderHook(() => useApi(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            apiCallbacks: { fetchStories, duplicateStory },\n          }}\n        >\n          <ApiProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.duplicateStory({\n        id: 123,\n      });\n    });\n\n    expect(result.current.state.stories.stories).toStrictEqual({\n      123: {\n        bottomTargetAction:\n          'https://www.story-link.com/wp-admin/post.php?id=123',\n        capabilities: {\n          hasDeleteAction: false,\n          hasEditAction: false,\n        },\n        featuredMediaUrl: 'https://www.featured-media-123',\n        editStoryLink: 'https://www.story-link.com/wp-admin/post.php?id=123',\n        id: 123,\n        modified: '1970-01-01T00:00:00.000',\n        modifiedGmt: '1970-01-01T00:00:00.000Z',\n        created: '1970-01-01T00:00:00.000',\n        createdGmt: '1970-01-01T00:00:00.000Z',\n        author: {\n          name: 'admin',\n          id: 1,\n        },\n        link: 'https://www.story-link.com',\n        lockUser: {\n          avatar: null,\n          id: 0,\n          name: '',\n        },\n        locked: false,\n        previewLink: 'https://www.story-link.com/?preview=true',\n        status: 'publish',\n        title: 'Carlos',\n      },\n      456: {\n        bottomTargetAction:\n          'https://www.story-link.com/wp-admin/post.php?id=456',\n        capabilities: {\n          hasDeleteAction: false,\n          hasEditAction: false,\n        },\n        editStoryLink: 'https://www.story-link.com/wp-admin/post.php?id=456',\n        featuredMediaUrl: 'https://www.featured-media-456',\n        id: 456,\n        modified: '1970-01-01T00:00:00.000',\n        modifiedGmt: '1970-01-01T00:00:00.000Z',\n        created: '1970-01-01T00:00:00.000',\n        createdGmt: '1970-01-01T00:00:00.000Z',\n        author: {\n          name: 'admin',\n          id: 1,\n        },\n        link: 'https://www.story-link.com',\n        lockUser: {\n          avatar: null,\n          id: 0,\n          name: '',\n        },\n        locked: false,\n        previewLink: 'https://www.story-link.com/?preview=true',\n        status: 'publish',\n        title: 'Carlos (Copy)',\n      },\n    });\n  });\n\n  it('should delete a story when the trash story method is called.', async () => {\n    const { result } = renderHook(() => useApi(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            apiCallbacks: { fetchStories, trashStory },\n          }}\n        >\n          <ApiProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.trashStory({\n        id: 123,\n      });\n    });\n\n    expect(result.current.state.stories.stories).toStrictEqual({});\n  });\n\n  it('should call initialFetch listeners once when first storystatuses returned', async () => {\n    const listenerMock = jest.fn();\n    const { result } = renderHook(() => useApi(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            apiCallbacks: { fetchStories },\n          }}\n        >\n          <ApiProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    act(() => {\n      result.current.actions.storyApi.addInitialFetchListener(listenerMock);\n    });\n\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    expect(listenerMock).toHaveBeenCalledOnce();\n    expect(listenerMock).toHaveBeenCalledWith({ all: 1, draft: 0, publish: 1 });\n\n    // Run again just to make sure it doesn't call the listeners more than once\n    await act(async () => {\n      await result.current.actions.storyApi.fetchStories({});\n    });\n\n    expect(listenerMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport ApiContext from './context';\n\nexport default function useApi(selector = identity) {\n  return useContextSelector(ApiContext, selector);\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useApiAlerts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useDebouncedCallback } from '@googleforcreators/react';\nimport { useSnackbar } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport useApi from './useApi';\n\nfunction useApiAlerts() {\n  const { storyError, templateError } = useApi(\n    ({\n      state: {\n        stories: { error: storyError },\n        templates: { error: templateError },\n      },\n    }) => ({\n      storyError,\n      templateError,\n    })\n  );\n  const { showSnackbar } = useSnackbar();\n\n  const debouncedShowSnackbar = useDebouncedCallback((message) => {\n    return showSnackbar({ message, dismissible: true });\n  }, 200);\n  // if there is an API error, display a snackbar\n  useEffect(() => {\n    if (storyError?.id) {\n      debouncedShowSnackbar(storyError.message);\n    }\n  }, [storyError, debouncedShowSnackbar]);\n\n  useEffect(() => {\n    if (templateError?.id) {\n      debouncedShowSnackbar(templateError.message);\n    }\n  }, [templateError, debouncedShowSnackbar]);\n}\nexport default useApiAlerts;\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useStoryApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useReducer,\n  useRef,\n} from '@googleforcreators/react';\nimport { getTimeTracker } from '@googleforcreators/tracking';\nimport {\n  SESSION_STORAGE_PREFIX,\n  sessionStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  storyReducer,\n  defaultStoriesState,\n  ACTION_TYPES as STORY_ACTION_TYPES,\n} from '../reducer/story';\nimport { ERRORS } from '../textContent';\nimport { useConfig } from '../config';\n\n// The format here is taken from the `getSessionStorageKey` util.\n// See https://github.com/GoogleForCreators/web-stories-wp/blob/d62ed358d069b3cd8586bc5f6949f50cdc0a39e6/packages/story-editor/src/utils/getSessionStorageKey.js\nconst DRAFT_STORAGE_KEY = `${SESSION_STORAGE_PREFIX.LOCAL_AUTOSAVE_PREFIX}_auto-draft`;\n\nconst useStoryApi = () => {\n  const isInitialFetch = useRef(true);\n  const initialFetchListeners = useMemo(() => new Map(), []);\n  const [state, dispatch] = useReducer(storyReducer, defaultStoriesState);\n  const { apiCallbacks } = useConfig();\n\n  const isMountedRef = useRef(false);\n\n  useEffect(() => {\n    isMountedRef.current = true;\n\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  const fetchStories = useCallback(\n    async (queryParams) => {\n      dispatch({\n        type: STORY_ACTION_TYPES.LOADING_STORIES,\n        payload: true,\n      });\n\n      // eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_stories');\n\n      try {\n        // Maybe not making a lot of sense to expect fetchedStoryIds from the api callbacks response.\n        // However the order of ids get changed if we try to create that array here\n        // which may ( or may not ) cause some regression. @todo Reflect on fetchedStoryIds again in next phase.\n        const { stories, fetchedStoryIds, totalPages, totalStoriesByStatus } =\n          await apiCallbacks.fetchStories(queryParams);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        // Hook into first fetch of story statuses.\n        if (isInitialFetch.current) {\n          initialFetchListeners.forEach((listener) => {\n            listener(totalStoriesByStatus);\n          });\n        }\n\n        isInitialFetch.current = false;\n\n        dispatch({\n          type: STORY_ACTION_TYPES.FETCH_STORIES_SUCCESS,\n          payload: {\n            stories,\n            totalPages,\n            totalStoriesByStatus,\n            fetchedStoryIds,\n            page: queryParams.page,\n          },\n        });\n      } catch (err) {\n        dispatch({\n          type: STORY_ACTION_TYPES.FETCH_STORIES_FAILURE,\n          payload: {\n            message: ERRORS.LOAD_STORIES.MESSAGE,\n            code: err.code,\n          },\n        });\n      } finally {\n        dispatch({\n          type: STORY_ACTION_TYPES.LOADING_STORIES,\n          payload: false,\n        });\n        trackTiming();\n      }\n    },\n    [apiCallbacks, initialFetchListeners]\n  );\n\n  const updateStory = useCallback(\n    async (story) => {\n      const trackTiming = getTimeTracker('load_update_story');\n\n      try {\n        const response = await apiCallbacks.updateStory(story);\n\n        dispatch({\n          type: STORY_ACTION_TYPES.UPDATE_STORY,\n          payload: response,\n        });\n      } catch (err) {\n        dispatch({\n          type: STORY_ACTION_TYPES.UPDATE_STORY_FAILURE,\n          payload: {\n            message: ERRORS.UPDATE_STORY.MESSAGE,\n            code: err.code,\n          },\n        });\n      } finally {\n        trackTiming();\n      }\n    },\n    [apiCallbacks]\n  );\n\n  const trashStory = useCallback(\n    async (story) => {\n      const trackTiming = getTimeTracker('load_trash_story');\n\n      try {\n        await apiCallbacks.trashStory(story.id);\n        dispatch({\n          type: STORY_ACTION_TYPES.TRASH_STORY,\n          payload: { id: story.id, storyStatus: story.status },\n        });\n      } catch (err) {\n        dispatch({\n          type: STORY_ACTION_TYPES.TRASH_STORY_FAILURE,\n          payload: {\n            message: ERRORS.DELETE_STORY.MESSAGE,\n            code: err.code,\n          },\n        });\n      } finally {\n        trackTiming();\n      }\n    },\n    [apiCallbacks]\n  );\n\n  const createStoryFromTemplate = useCallback(\n    async (template) => {\n      dispatch({\n        type: STORY_ACTION_TYPES.CREATING_STORY_FROM_TEMPLATE,\n        payload: true,\n      });\n\n      try {\n        const response = await apiCallbacks.createStoryFromTemplate(template);\n        sessionStore.deleteItemByKey(DRAFT_STORAGE_KEY);\n        dispatch({\n          type: STORY_ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_SUCCESS,\n        });\n\n        window.location = response.editLink;\n      } catch (err) {\n        dispatch({\n          type: STORY_ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_FAILURE,\n          payload: {\n            message: ERRORS.CREATE_STORY_FROM_TEMPLATE.MESSAGE,\n            code: err.code,\n          },\n        });\n      } finally {\n        dispatch({\n          type: STORY_ACTION_TYPES.CREATING_STORY_FROM_TEMPLATE,\n          payload: false,\n        });\n      }\n    },\n    [apiCallbacks]\n  );\n\n  const duplicateStory = useCallback(\n    async (story) => {\n      const trackTiming = getTimeTracker('load_duplicate_story');\n\n      try {\n        const response = await apiCallbacks.duplicateStory(story);\n\n        dispatch({\n          type: STORY_ACTION_TYPES.DUPLICATE_STORY,\n          payload: response,\n        });\n      } catch (err) {\n        dispatch({\n          type: STORY_ACTION_TYPES.DUPLICATE_STORY_FAILURE,\n          payload: {\n            message: ERRORS.DUPLICATE_STORY.MESSAGE,\n            code: err.code,\n          },\n        });\n      } finally {\n        trackTiming();\n      }\n    },\n    [apiCallbacks]\n  );\n\n  const addInitialFetchListener = useCallback(\n    (listener) => {\n      const key = Symbol();\n      initialFetchListeners.set(key, listener);\n      return () => {\n        initialFetchListeners.delete(key);\n      };\n    },\n    [initialFetchListeners]\n  );\n\n  return {\n    stories: state,\n    api: {\n      duplicateStory,\n      fetchStories,\n      createStoryFromTemplate,\n      trashStory,\n      updateStory,\n      addInitialFetchListener,\n    },\n  };\n};\n\nexport default useStoryApi;\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useTaxonomyApi.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\nfunction useTaxonomyApi() {\n  const {\n    apiCallbacks: { getTaxonomies, getTaxonomyTerms },\n  } = useConfig();\n\n  return {\n    api: {\n      getTaxonomies,\n      getTaxonomyTerms,\n    },\n  };\n}\n\nexport default useTaxonomyApi;\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useTemplateApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReducer } from '@googleforcreators/react';\nimport { compareDesc } from '@googleforcreators/date';\n\n/**\n * Internal dependencies\n */\nimport {\n  templateReducer,\n  defaultTemplatesState,\n  ACTION_TYPES as TEMPLATE_ACTION_TYPES,\n} from '../reducer/templates';\nimport { reshapeTemplateObject } from '../serializers';\nimport { useConfig } from '../config';\n\nconst useTemplateApi = () => {\n  const [state, dispatch] = useReducer(templateReducer, defaultTemplatesState);\n  const { cdnURL } = useConfig();\n\n  const fetchExternalTemplates = useCallback(async () => {\n    dispatch({\n      type: TEMPLATE_ACTION_TYPES.LOADING_TEMPLATES,\n      payload: true,\n    });\n\n    const templatesByTag = {};\n\n    const { getAllTemplates } = await import(\n      /* webpackChunkName: \"chunk-web-stories-templates\" */ '@googleforcreators/templates'\n    );\n\n    const reshapedTemplates = (await getAllTemplates({ cdnURL }))\n      .map((template) => {\n        const reshapedTemplate = reshapeTemplateObject(template);\n\n        reshapedTemplate.tags.forEach((tag) => {\n          if (templatesByTag[tag]) {\n            templatesByTag[tag].push(reshapedTemplate.id);\n          } else {\n            templatesByTag[tag] = [reshapedTemplate.id];\n          }\n        });\n\n        return reshapedTemplate;\n      })\n      .sort((a, b) => compareDesc(a.creationDate, b.creationDate));\n    dispatch({\n      type: TEMPLATE_ACTION_TYPES.FETCH_TEMPLATES_SUCCESS,\n      payload: {\n        page: 1,\n        templates: reshapedTemplates,\n        totalPages: 1,\n        totalTemplates: reshapedTemplates.length,\n        templatesByTag,\n      },\n    });\n  }, [cdnURL]);\n\n  const fetchExternalTemplateById = useCallback(\n    (templateId) => {\n      if (state.templates[templateId]) {\n        return Promise.resolve(state.templates[templateId]);\n      }\n      return Promise.reject(new Error());\n    },\n    [state]\n  );\n\n  return {\n    templates: state,\n    api: {\n      fetchExternalTemplates,\n      fetchExternalTemplateById,\n    },\n  };\n};\n\nexport default useTemplateApi;\n"
  },
  {
    "path": "packages/dashboard/src/app/api/useUsersApi.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\n\nfunction useUsersApi() {\n  const {\n    apiCallbacks: { getAuthors },\n  } = useConfig();\n\n  return {\n    api: {\n      getAuthors,\n    },\n  };\n}\n\nexport default useUsersApi;\n"
  },
  {
    "path": "packages/dashboard/src/app/config/configProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { DashboardConfig } from '../../types/configProvider';\nimport Context from './context';\n\nexport interface ConfigProviderProps {\n  children: ReactNode;\n  config: DashboardConfig;\n}\nfunction ConfigProvider({ config, children }: ConfigProviderProps) {\n  return <Context.Provider value={config}>{children}</Context.Provider>;\n}\n\nexport default ConfigProvider;\n"
  },
  {
    "path": "packages/dashboard/src/app/config/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { Navigation } from '../../types/configProvider';\n\nexport default createContext({\n  isRTL: false,\n  userId: 0,\n  locale: {},\n  newStoryURL: '',\n  cdnURL: '',\n  version: '',\n  capabilities: {},\n  canViewDefaultTemplates: false,\n  flags: {},\n  apiCallbacks: {},\n  leftRailSecondaryNavigation: [] as Navigation[],\n  styleConstants: {\n    topOffset: 0,\n    leftOffset: 0,\n  },\n  containerId: '',\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/config/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ConfigProvider } from './configProvider';\nexport { default as useConfig } from './useConfig';\n"
  },
  {
    "path": "packages/dashboard/src/app/config/useConfig.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { DashboardConfig } from '../../types/configProvider';\nimport Context from './context';\n\nfunction useConfig(): DashboardConfig;\nfunction useConfig<T>(\n  selector: (state: DashboardConfig) => T | DashboardConfig = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useConfig;\n"
  },
  {
    "path": "packages/dashboard/src/app/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './api';\nexport * from './config';\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/story/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const ACTION_TYPES = {\n  CREATING_STORY_FROM_TEMPLATE: 'creating_story_from_template',\n  CREATE_STORY_FROM_TEMPLATE_SUCCESS: 'create_story_from_template_success',\n  CREATE_STORY_FROM_TEMPLATE_FAILURE: 'create_story_from_template_failure',\n  LOADING_STORIES: 'loading_stories',\n  FETCH_STORIES_SUCCESS: 'fetch_stories_success',\n  FETCH_STORIES_FAILURE: 'fetch_stories_failure',\n  UPDATE_STORY: 'update_story',\n  UPDATE_STORY_FAILURE: 'update_story_failure',\n  TRASH_STORY: 'trash_story',\n  TRASH_STORY_FAILURE: 'trash_story_failure',\n  DUPLICATE_STORY: 'duplicate_story',\n  DUPLICATE_STORY_FAILURE: 'duplicate_story_failure',\n};\n\nexport const defaultStoriesState = {\n  error: {},\n  isLoading: false,\n  stories: {},\n  storiesOrderById: [],\n  totalStoriesByStatus: {},\n  totalPages: null,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/story/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\nexport { default as storyReducer } from './storyReducer';\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/story/storyReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { STORY_STATUS } from '../../../constants';\nimport { ACTION_TYPES } from './constants';\n\nfunction storyReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.LOADING_STORIES:\n    case ACTION_TYPES.CREATING_STORY_FROM_TEMPLATE: {\n      return {\n        ...state,\n        isLoading: action.payload,\n      };\n    }\n\n    case ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_FAILURE:\n    case ACTION_TYPES.FETCH_STORIES_FAILURE:\n    case ACTION_TYPES.UPDATE_STORY_FAILURE:\n    case ACTION_TYPES.TRASH_STORY_FAILURE:\n    case ACTION_TYPES.DUPLICATE_STORY_FAILURE: {\n      return {\n        ...state,\n        error: { ...action.payload, id: Date.now() },\n      };\n    }\n\n    case ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_SUCCESS: {\n      return {\n        ...state,\n        error: {},\n      };\n    }\n\n    case ACTION_TYPES.UPDATE_STORY:\n      return {\n        ...state,\n        error: {},\n        stories: {\n          ...state.stories,\n          [action.payload.id]: action.payload,\n        },\n      };\n\n    case ACTION_TYPES.TRASH_STORY: {\n      const storyGroupStatus =\n        action.payload.storyStatus === STORY_STATUS.DRAFT\n          ? STORY_STATUS.DRAFT\n          : STORY_STATUS.PUBLISH;\n\n      return {\n        ...state,\n        error: {},\n        storiesOrderById: state.storiesOrderById.filter(\n          (id) => id !== action.payload.id\n        ),\n        totalStoriesByStatus: {\n          ...state.totalStoriesByStatus,\n          all: state.totalStoriesByStatus.all - 1,\n          [storyGroupStatus]: state.totalStoriesByStatus[storyGroupStatus] - 1,\n        },\n        stories: Object.keys(state.stories).reduce((memo, storyId) => {\n          if (Number.parseInt(storyId) !== action.payload.id) {\n            memo[storyId] = state.stories[storyId];\n          }\n          return memo;\n        }, {}),\n      };\n    }\n\n    case ACTION_TYPES.DUPLICATE_STORY:\n      return {\n        ...state,\n        error: {},\n        storiesOrderById: [action.payload.id, ...state.storiesOrderById],\n        totalStoriesByStatus: {\n          ...state.totalStoriesByStatus,\n          all: state.totalStoriesByStatus.all + 1,\n          [action.payload.status]:\n            state.totalStoriesByStatus[action.payload.status] + 1,\n        },\n        stories: {\n          ...state.stories,\n          [action.payload.id]: action.payload,\n        },\n      };\n\n    case ACTION_TYPES.FETCH_STORIES_SUCCESS: {\n      const {\n        fetchedStoryIds,\n        totalStoriesByStatus,\n        totalPages,\n        page,\n        stories: payloadStories,\n      } = action.payload;\n      const { storiesOrderById, stories } = state;\n\n      const combinedStoryIds =\n        page === 1\n          ? fetchedStoryIds\n          : [...storiesOrderById, ...fetchedStoryIds];\n\n      const uniqueStoryIds = [...new Set(combinedStoryIds)];\n\n      return {\n        ...state,\n        error: {},\n        storiesOrderById: uniqueStoryIds,\n        stories: {\n          ...stories,\n          ...payloadStories,\n        },\n        totalPages: totalPages || 1,\n        totalStoriesByStatus: totalStoriesByStatus,\n        allPagesFetched: page >= totalPages,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default storyReducer;\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/templates/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ACTION_TYPES = {\n  LOADING_TEMPLATES: 'loading_templates',\n  FETCH_TEMPLATES_SUCCESS: 'fetch_templates_success',\n  FETCH_TEMPLATES_FAILURE: 'fetch_templates_failure',\n  PLACEHOLDER: 'placeholder',\n};\n\nexport const defaultTemplatesState = {\n  allPagesFetched: false,\n  error: {},\n  isLoading: false,\n  templates: {},\n  templatesByTag: {},\n  templatesOrderById: [],\n  totalTemplates: null,\n  totalPages: null,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/templates/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\nexport { default as templateReducer } from './templateReducer';\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/templates/templateReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport groupBy from '../../../utils/groupBy';\nimport { ACTION_TYPES, defaultTemplatesState } from './constants';\n\nfunction templateReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.LOADING_TEMPLATES: {\n      return {\n        ...state,\n        isLoading: action.payload,\n      };\n    }\n\n    case ACTION_TYPES.FETCH_TEMPLATES_FAILURE:\n      return {\n        ...state,\n        error: { ...action.payload, id: Date.now() },\n      };\n\n    case ACTION_TYPES.FETCH_TEMPLATES_SUCCESS: {\n      const fetchedTemplatesById = action.payload.templates.map(({ id }) => id);\n\n      const combinedTemplateIds =\n        action.payload.page === 1\n          ? fetchedTemplatesById\n          : [...state.templatesOrderById, ...fetchedTemplatesById];\n\n      const uniqueTemplateIds = [...new Set(combinedTemplateIds)];\n\n      return {\n        ...state,\n        error: {},\n        templatesOrderById: uniqueTemplateIds,\n        templates: {\n          ...state.templates,\n          ...groupBy(action.payload.templates, 'id'),\n        },\n        isLoading: false,\n        totalPages: action.payload.totalPages,\n        totalTemplates: action.payload.totalTemplates,\n        allPagesFetched: action.payload.page >= action.payload.totalPages,\n        templatesByTag: action.payload.templatesByTag,\n      };\n    }\n    case ACTION_TYPES.PLACEHOLDER:\n      return defaultTemplatesState;\n\n    default:\n      return state;\n  }\n}\n\nexport default templateReducer;\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/test/story.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { storyReducer, ACTION_TYPES } from '../story';\nimport { STORY_STATUS } from '../../../constants';\nimport { ERRORS } from '../../textContent';\n\ndescribe('storyReducer', () => {\n  const initialState = {\n    error: {},\n    isLoading: false,\n    stories: {},\n    storiesOrderById: [],\n    totalStoriesByStatus: {},\n    totalPages: null,\n  };\n\n  const MOCK_ERROR_ID = Date.now();\n\n  beforeAll(() => {\n    jest.spyOn(Date, 'now').mockImplementation(() => MOCK_ERROR_ID);\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.TRASH_STORY} is called`, () => {\n    const result = storyReducer(\n      {\n        ...initialState,\n        storiesOrderById: [94, 65, 78, 12],\n        stories: {\n          94: { id: 94, status: 'draft', title: 'my test story 1' },\n          65: { id: 65, status: 'publish', title: 'my test story 2' },\n          78: { id: 78, status: 'draft', title: 'my test story 3' },\n          12: { id: 12, status: 'draft', title: 'my test story 4' },\n        },\n        totalStoriesByStatus: {\n          all: 44,\n          [STORY_STATUS.DRAFT]: 40,\n          [STORY_STATUS.PUBLISH]: 4,\n        },\n        totalPages: 4,\n      },\n      {\n        type: ACTION_TYPES.TRASH_STORY,\n        payload: {\n          id: 65,\n          storyStatus: 'publish',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {},\n      storiesOrderById: [94, 78, 12],\n      stories: {\n        94: { id: 94, status: 'draft', title: 'my test story 1' },\n        78: { id: 78, status: 'draft', title: 'my test story 3' },\n        12: { id: 12, status: 'draft', title: 'my test story 4' },\n      },\n      totalStoriesByStatus: {\n        all: 43,\n        [STORY_STATUS.DRAFT]: 40,\n        [STORY_STATUS.PUBLISH]: 3,\n      },\n      totalPages: 4,\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.TRASH_STORY_FAILURE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.TRASH_STORY_FAILURE,\n        payload: {\n          message: ERRORS.DELETE_STORY.MESSAGE,\n          code: 'my_error_code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.DELETE_STORY.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.DUPLICATE_STORY} is called`, () => {\n    const result = storyReducer(\n      {\n        ...initialState,\n        storiesOrderById: [94, 65, 78, 12],\n        stories: {\n          94: { id: 94, status: 'draft', title: 'my test story 1' },\n          65: { id: 65, status: 'publish', title: 'my test story 2' },\n          78: { id: 78, status: 'draft', title: 'my test story 3' },\n          12: { id: 12, status: 'draft', title: 'my test story 4' },\n        },\n        totalStoriesByStatus: {\n          all: 44,\n          [STORY_STATUS.DRAFT]: 40,\n          [STORY_STATUS.PUBLISH]: 4,\n        },\n        totalPages: 4,\n      },\n      {\n        type: ACTION_TYPES.DUPLICATE_STORY,\n        payload: { id: 95, status: 'draft', title: 'my test story 1 - copy' },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {},\n      storiesOrderById: [95, 94, 65, 78, 12],\n      stories: {\n        94: { id: 94, status: 'draft', title: 'my test story 1' },\n        95: { id: 95, status: 'draft', title: 'my test story 1 - copy' },\n        65: { id: 65, status: 'publish', title: 'my test story 2' },\n        78: { id: 78, status: 'draft', title: 'my test story 3' },\n        12: { id: 12, status: 'draft', title: 'my test story 4' },\n      },\n      totalStoriesByStatus: {\n        all: 45,\n        [STORY_STATUS.DRAFT]: 41,\n        [STORY_STATUS.PUBLISH]: 4,\n      },\n      totalPages: 4,\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.DUPLICATE_STORY_FAILURE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.DUPLICATE_STORY_FAILURE,\n        payload: {\n          message: ERRORS.DUPLICATE_STORY.MESSAGE,\n          code: 'my_error_code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.DUPLICATE_STORY.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.FETCH_STORIES_SUCCESS} is called`, () => {\n    const result = storyReducer(initialState, {\n      type: ACTION_TYPES.FETCH_STORIES_SUCCESS,\n      payload: {\n        page: 1,\n        stories: {\n          94: { id: 94, status: 'draft', title: 'my test story 1' },\n          65: { id: 65, status: 'publish', title: 'my test story 2' },\n          78: { id: 78, status: 'draft', title: 'my test story 3' },\n          12: { id: 12, status: 'draft', title: 'my test story 4' },\n        },\n        totalStoriesByStatus: {\n          all: 44,\n          [STORY_STATUS.DRAFT]: 40,\n          [STORY_STATUS.PUBLISH]: 4,\n        },\n        totalPages: 4,\n        fetchedStoryIds: [94, 65, 78, 12],\n      },\n    });\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {},\n      storiesOrderById: [94, 65, 78, 12],\n      stories: {\n        94: { id: 94, status: 'draft', title: 'my test story 1' },\n        65: { id: 65, status: 'publish', title: 'my test story 2' },\n        78: { id: 78, status: 'draft', title: 'my test story 3' },\n        12: { id: 12, status: 'draft', title: 'my test story 4' },\n      },\n      totalStoriesByStatus: {\n        all: 44,\n        [STORY_STATUS.DRAFT]: 40,\n        [STORY_STATUS.PUBLISH]: 4,\n      },\n      totalPages: 4,\n      allPagesFetched: false,\n    });\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.FETCH_STORIES_SUCCESS} is called and maintain order from existing state`, () => {\n    const result = storyReducer(\n      { ...initialState, storiesOrderById: [55, 99, 10, 3] },\n      {\n        type: ACTION_TYPES.FETCH_STORIES_SUCCESS,\n        payload: {\n          page: 2,\n          stories: {\n            94: { id: 94, status: 'draft', title: 'my test story 1' },\n            65: { id: 65, status: 'publish', title: 'my test story 2' },\n            78: { id: 78, status: 'draft', title: 'my test story 3' },\n            12: { id: 12, status: 'draft', title: 'my test story 4' },\n          },\n          totalStoriesByStatus: {\n            all: 18,\n            [STORY_STATUS.DRAFT]: 14,\n            [STORY_STATUS.PUBLISH]: 4,\n          },\n          totalPages: 2,\n          fetchedStoryIds: [94, 65, 78, 12],\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      storiesOrderById: [55, 99, 10, 3, 94, 65, 78, 12],\n      stories: {\n        94: { id: 94, status: 'draft', title: 'my test story 1' },\n        65: { id: 65, status: 'publish', title: 'my test story 2' },\n        78: { id: 78, status: 'draft', title: 'my test story 3' },\n        12: { id: 12, status: 'draft', title: 'my test story 4' },\n      },\n      totalStoriesByStatus: {\n        all: 18,\n        [STORY_STATUS.DRAFT]: 14,\n        [STORY_STATUS.PUBLISH]: 4,\n      },\n      totalPages: 2,\n      allPagesFetched: true,\n    });\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.FETCH_STORIES_SUCCESS} is called and set totalPages to at least one`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.FETCH_STORIES_SUCCESS,\n        payload: {\n          page: 1,\n          stories: {},\n          totalStoriesByStatus: {\n            all: 0,\n            [STORY_STATUS.DRAFT]: 0,\n            [STORY_STATUS.PUBLISH]: 0,\n            [STORY_STATUS.FUTURE]: 0,\n            [STORY_STATUS.PENDING]: 0,\n            [STORY_STATUS.PRIVATE]: 0,\n            [STORY_STATUS.PUBLISH]: 0,\n          },\n          totalPages: 0,\n          fetchedStoryIds: [],\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      storiesOrderById: [],\n      stories: {},\n      totalStoriesByStatus: {\n        all: 0,\n        [STORY_STATUS.DRAFT]: 0,\n        [STORY_STATUS.PUBLISH]: 0,\n        [STORY_STATUS.FUTURE]: 0,\n        [STORY_STATUS.PENDING]: 0,\n        [STORY_STATUS.PRIVATE]: 0,\n        [STORY_STATUS.PUBLISH]: 0,\n      },\n      totalPages: 1,\n      allPagesFetched: true,\n    });\n  });\n\n  it(`should update isLoading when ${ACTION_TYPES.LOADING_STORIES} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.LOADING_STORIES,\n        payload: true,\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      isLoading: true,\n    });\n  });\n\n  it(`should update isLoading when ${ACTION_TYPES.CREATING_STORY_FROM_TEMPLATE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.CREATING_STORY_FROM_TEMPLATE,\n        payload: true,\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      isLoading: true,\n    });\n  });\n\n  it(`should update error to empty object when ${ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_SUCCESS} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_SUCCESS,\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {},\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.FETCH_STORIES_FAILURE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.FETCH_STORIES_FAILURE,\n        payload: {\n          message: ERRORS.LOAD_STORIES.MESSAGE,\n          code: 'my_error_code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.LOAD_STORIES.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_FAILURE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.CREATE_STORY_FROM_TEMPLATE_FAILURE,\n        payload: {\n          message: ERRORS.CREATE_STORY_FROM_TEMPLATE.MESSAGE,\n          code: 'my_error_code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.CREATE_STORY_FROM_TEMPLATE.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update stories state when ${ACTION_TYPES.UPDATE_STORY} is called`, () => {\n    const result = storyReducer(\n      {\n        ...initialState,\n        stories: {\n          94: { id: 94, status: 'draft', title: 'my test story 1' },\n          65: { id: 65, status: 'publish', title: 'my test story 2' },\n          78: { id: 78, status: 'draft', title: 'my test story 3' },\n          12: { id: 12, status: 'draft', title: 'my test story 4' },\n        },\n      },\n      {\n        type: ACTION_TYPES.UPDATE_STORY,\n        payload: { id: 65, status: 'publish', title: 'new title for story' },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      stories: {\n        94: { id: 94, status: 'draft', title: 'my test story 1' },\n        65: { id: 65, status: 'publish', title: 'new title for story' },\n        78: { id: 78, status: 'draft', title: 'my test story 3' },\n        12: { id: 12, status: 'draft', title: 'my test story 4' },\n      },\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.UPDATE_STORY_FAILURE} is called`, () => {\n    const result = storyReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.UPDATE_STORY_FAILURE,\n        payload: {\n          message: ERRORS.UPDATE_STORY.MESSAGE,\n          code: 'my_error_code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.UPDATE_STORY.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/reducer/test/templates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ERRORS } from '../../textContent';\nimport {\n  templateReducer,\n  ACTION_TYPES,\n  defaultTemplatesState as initialState,\n} from '../templates';\n\ndescribe('templateReducer', () => {\n  const MOCK_ERROR_ID = Date.now();\n\n  beforeAll(() => {\n    jest.spyOn(Date, 'now').mockImplementation(() => MOCK_ERROR_ID);\n  });\n\n  it(`should update templates state when ${ACTION_TYPES.FETCH_TEMPLATES_SUCCESS} is called`, () => {\n    const result = templateReducer(initialState, {\n      type: ACTION_TYPES.FETCH_TEMPLATES_SUCCESS,\n      payload: {\n        page: 1,\n        templates: [\n          {\n            id: 1,\n            title: 'Beauty',\n          },\n          {\n            id: 2,\n            title: 'Cooking',\n          },\n          {\n            id: 3,\n            title: 'DIY',\n          },\n          {\n            id: 4,\n            title: 'Cooking',\n          },\n          {\n            id: 5,\n            title: 'Entertainment',\n          },\n        ],\n        totalTemplates: 33,\n        totalPages: 4,\n      },\n    });\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {},\n      templatesOrderById: [1, 2, 3, 4, 5],\n      templates: {\n        1: {\n          id: 1,\n          title: 'Beauty',\n        },\n        2: {\n          id: 2,\n          title: 'Cooking',\n        },\n        3: {\n          id: 3,\n          title: 'DIY',\n        },\n        4: {\n          id: 4,\n          title: 'Cooking',\n        },\n        5: {\n          id: 5,\n          title: 'Entertainment',\n        },\n      },\n      totalTemplates: 33,\n      totalPages: 4,\n      allPagesFetched: false,\n    });\n  });\n\n  it(`should update templates state when ${ACTION_TYPES.FETCH_TEMPLATES_SUCCESS} is called and maintain order from existing state`, () => {\n    const result = templateReducer(\n      { ...initialState, templatesOrderById: [1, 2, 3, 8, 9] },\n      {\n        type: ACTION_TYPES.FETCH_TEMPLATES_SUCCESS,\n        payload: {\n          page: 2,\n          templates: [\n            {\n              id: 7,\n              title: 'Beauty',\n            },\n            {\n              id: 2,\n              title: 'Cooking',\n            },\n            {\n              id: 3,\n              title: 'DIY',\n            },\n            {\n              id: 4,\n              title: 'Cooking',\n            },\n            {\n              id: 5,\n              title: 'Entertainment',\n            },\n          ],\n          totalTemplates: 8,\n          totalPages: 2,\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      templatesOrderById: [1, 2, 3, 8, 9, 7, 4, 5],\n      templates: {\n        7: {\n          id: 7,\n          title: 'Beauty',\n        },\n        2: {\n          id: 2,\n          title: 'Cooking',\n        },\n        3: {\n          id: 3,\n          title: 'DIY',\n        },\n        4: {\n          id: 4,\n          title: 'Cooking',\n        },\n        5: {\n          id: 5,\n          title: 'Entertainment',\n        },\n      },\n      totalTemplates: 8,\n      totalPages: 2,\n      allPagesFetched: true,\n    });\n  });\n\n  it(`should update isLoading when ${ACTION_TYPES.LOADING_TEMPLATES} is called`, () => {\n    const result = templateReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.LOADING_TEMPLATES,\n        payload: true,\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      isLoading: true,\n    });\n  });\n\n  it(`should update error when ${ACTION_TYPES.FETCH_TEMPLATES_FAILURE} is called`, () => {\n    const result = templateReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.FETCH_TEMPLATES_FAILURE,\n        payload: {\n          message: ERRORS.LOAD_TEMPLATES.MESSAGE,\n          code: 'test-error-code',\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      ...initialState,\n      error: {\n        message: ERRORS.LOAD_TEMPLATES.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'test-error-code',\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/router/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { RouterProviderState } from '../../types';\n\nexport default createContext<RouterProviderState>({\n  state: {\n    activeRoute: '',\n    currentPath: '',\n    queryParams: {},\n    availableRoutes: [],\n    defaultRoute: '',\n  },\n  actions: {\n    push: () => undefined,\n    replace: () => undefined,\n    setAvailableRoutes: () => [],\n  },\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/router/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nexport { default as RouterProvider } from './routerProvider';\nexport { default as useRouteHistory } from './useRouteHistory';\nexport { default as Route, matchPath, resolveRoute } from './route';\n"
  },
  {
    "path": "packages/dashboard/src/app/router/route.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport useRouteHistory from './useRouteHistory';\n\nexport function parentRoute() {\n  const potentialParent = window.location.hash\n    .split('/')\n    .slice(0, -1)\n    .join('/');\n  if (potentialParent.startsWith('#')) {\n    return potentialParent;\n  } else {\n    return '#/';\n  }\n}\n\nexport function resolveRoute(route: string) {\n  if (\n    route.toLowerCase().startsWith('http://') ||\n    route.toLowerCase().startsWith('https://')\n  ) {\n    /**\n     * If the url starts with a protocol assume it's a full path and\n     * visit it normally.\n     */\n    return route;\n  } else if (route.startsWith('/')) {\n    /**\n     * If the url starts with a backslash visit it as a root view\n     * within the context of the dashboard app.\n     */\n    return `#${route}`;\n  } else if (route === '') {\n    /**\n     * If the url is empty visit it as a root view\n     * within the context of the dashboard app.\n     */\n    return '#/';\n  } else {\n    /**\n     * If the url has no root append it to the current route and create\n     * a nested root within the context of the dashboard app.\n     */\n    return `${window.location.hash}/${route}`;\n  }\n}\n\ninterface MatchPathProps {\n  currentPath: string;\n  path: string;\n  availableRoutes: string[];\n  defaultRoute: string;\n  isDefault?: boolean;\n  exact?: boolean;\n}\nexport function matchPath({\n  currentPath,\n  path,\n  availableRoutes,\n  defaultRoute,\n  isDefault = false,\n  exact = false,\n}: MatchPathProps) {\n  const match = new RegExp(`^${path}`).exec(currentPath);\n\n  // allow paths through that don't match if they are default, not narrowed out yet.\n  if (!match && !isDefault) {\n    return null;\n  }\n\n  // Find all available url matches\n  const matchUrl = match?.[0];\n\n  // Check if there is a default before looking for more exact matches\n  // If there is and the current path fits 1 or less\n  // of the available routes then render it as default\n  if (isDefault) {\n    const isValidDefaultRoute =\n      availableRoutes.filter((route) => currentPath.startsWith(route)).length <=\n      1;\n\n    if (isValidDefaultRoute) {\n      return defaultRoute;\n    }\n  }\n\n  const isExactMatch = currentPath === matchUrl;\n  if (exact && !isExactMatch) {\n    return null;\n  }\n  return matchUrl;\n}\n\ninterface RouteProps {\n  component: React.Component;\n  path: string;\n  exact?: boolean;\n  isDefault?: boolean;\n}\nfunction Route({\n  component,\n  path,\n  exact = false,\n  isDefault = false,\n}: RouteProps) {\n  const { availableRoutes, currentPath, defaultRoute } = useRouteHistory(\n    ({ state }) => state\n  );\n\n  const match = matchPath({\n    currentPath,\n    availableRoutes,\n    defaultRoute,\n    path,\n    exact,\n    isDefault,\n  });\n\n  if (!match) {\n    return null;\n  }\n  return component;\n}\n\nexport default Route;\n"
  },
  {
    "path": "packages/dashboard/src/app/router/routerProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useMemo, useEffect, useState } from '@googleforcreators/react';\nimport { createHashHistory } from 'history';\nimport type { History } from 'history';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { APP_ROUTES } from '../../constants';\nimport Context from './context';\n\ninterface ActiveRouteProps {\n  availableRoutes: string[];\n  currentPath: string;\n  defaultRoute: string;\n}\nexport const getActiveRoute = ({\n  availableRoutes,\n  currentPath,\n  defaultRoute,\n}: ActiveRouteProps) => {\n  const matchingRoutes = availableRoutes.filter((route) =>\n    currentPath.startsWith(route)\n  );\n  // this assumes that we have a route that's just the root path (/)\n  return matchingRoutes.length <= 1 ? defaultRoute : currentPath;\n};\n\nfunction RouterProvider({\n  children,\n  ...props\n}: PropsWithChildren<{ history: History }>) {\n  const history = useRef<History>(props.history || createHashHistory());\n  const [currentPath, setCurrentPath] = useState(\n    history.current.location.pathname\n  );\n  const [availableRoutes, setAvailableRoutes] = useState<string[]>([]);\n  const defaultRoute = APP_ROUTES.DASHBOARD;\n\n  const activeRoute = useMemo(\n    () => getActiveRoute({ availableRoutes, currentPath, defaultRoute }),\n    [availableRoutes, currentPath, defaultRoute]\n  );\n\n  const parse = (search: string) => {\n    const params = new URLSearchParams(search);\n    return Object.fromEntries(params);\n  };\n\n  const [queryParams, setQueryParams] = useState(\n    parse(history.current.location.search)\n  );\n\n  useEffect(() => {\n    return history.current.listen(({ location }) => {\n      setQueryParams(parse(location.search));\n      setCurrentPath(location.pathname);\n    });\n  }, []);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        activeRoute,\n        currentPath,\n        queryParams,\n        availableRoutes,\n        defaultRoute,\n      },\n      actions: {\n        push: (path: string) => history.current.push(path),\n        replace: (path: string) => history.current.replace(path),\n        setAvailableRoutes,\n      },\n    }),\n    [activeRoute, availableRoutes, currentPath, defaultRoute, queryParams]\n  );\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport default RouterProvider;\n"
  },
  {
    "path": "packages/dashboard/src/app/router/test/route.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { parentRoute, resolveRoute } from '../route';\n\ndescribe('Route', () => {\n  afterEach(() => {\n    window.location.hash = '';\n  });\n\n  it('should return the parent route from the path.', () => {\n    window.location.hash = '#/parent/child';\n    expect(parentRoute()).toBe('#/parent');\n  });\n\n  it('should return the root hash if the hash only has one level.', () => {\n    window.location.hash = 'parent';\n    expect(parentRoute()).toBe('#/');\n  });\n\n  it('should the full URL if it has a http or https protocol.', () => {\n    expect(resolveRoute('http://www.google.com')).toBe('http://www.google.com');\n    expect(resolveRoute('https://www.google.com')).toBe(\n      'https://www.google.com'\n    );\n  });\n\n  it('should append a nested route to the current hash when the path is relative', () => {\n    window.location.hash = '#/templates-gallery';\n    expect(resolveRoute('template-detail')).toBe(\n      '#/templates-gallery/template-detail'\n    );\n  });\n\n  it('should create a route hash when the path is a backslash', () => {\n    expect(resolveRoute('/')).toBe('#/');\n  });\n\n  it('should create a route hash when the path is empty', () => {\n    expect(resolveRoute('')).toBe('#/');\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/router/test/router.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, fireEvent, screen } from '@testing-library/react';\nimport { createBrowserHistory } from 'history';\n\n/**\n * Internal dependencies\n */\nimport { RouterProvider, Route, useRouteHistory } from '..';\nimport Context from '../context';\n\ndescribe('RouterProvider', () => {\n  it('should render the first route by default', () => {\n    render(\n      <RouterProvider>\n        <Route path=\"/\" exact component={<div>{'Home'}</div>} />\n        <Route path=\"/second-route\" component={<div>{'Second Route'}</div>} />\n      </RouterProvider>\n    );\n\n    expect(screen.getByText('Home')).toBeInTheDocument();\n    expect(screen.queryByText('Second Route')).not.toBeInTheDocument();\n  });\n\n  it('should render the default route if currentPath has no matching route of its own', () => {\n    render(\n      <Context.Provider\n        value={{\n          state: {\n            currentPath: 'wpbody-content',\n            availableRoutes: ['/', '/second-route'],\n            defaultRoute: '/',\n          },\n        }}\n      >\n        <Route path=\"/\" exact isDefault component={<div>{'Home'}</div>} />\n        <Route path=\"/second-route\" component={<div>{'Second Route'}</div>} />\n      </Context.Provider>\n    );\n\n    expect(screen.getByText('Home')).toBeInTheDocument();\n    expect(screen.queryByText('Second Route')).not.toBeInTheDocument();\n  });\n\n  it('should render secondary route on a partial match', () => {\n    render(\n      <Context.Provider\n        value={{\n          state: {\n            currentPath: '/second-route123',\n            availableRoutes: ['/', '/second-route'],\n            defaultRoute: '/',\n          },\n        }}\n      >\n        <Route path=\"/\" exact isDefault component={<div>{'Home'}</div>} />\n        <Route path=\"/second-route\" component={<div>{'Second Route'}</div>} />\n      </Context.Provider>\n    );\n\n    expect(screen.queryByText('Home')).not.toBeInTheDocument();\n    expect(screen.getByText('Second Route')).toBeInTheDocument();\n  });\n\n  it('should render the second route when navigated to', async () => {\n    const history = createBrowserHistory();\n    const listeners = [];\n\n    jest.spyOn(history, 'listen').mockImplementation((callback) => {\n      listeners.push(callback);\n      return () => {};\n    });\n\n    jest.spyOn(history, 'push').mockImplementation((sender) => {\n      listeners.forEach((l) => {\n        l({ location: { search: '', pathname: sender } });\n      });\n    });\n\n    const Button = () => {\n      const { actions } = useRouteHistory();\n      return (\n        <button onClick={() => actions.push('/second-route')}>\n          {'Visit Second Page'}\n        </button>\n      );\n    };\n\n    render(\n      <RouterProvider history={history}>\n        <Button />\n        <Route path=\"/\" exact component={<div>{'Home'}</div>} />\n        <Route path=\"/second-route\" component={<div>{'Second Route'}</div>} />\n      </RouterProvider>\n    );\n\n    const link = await screen.findByText('Visit Second Page');\n    fireEvent.click(link);\n    expect(screen.queryByText('Home')).not.toBeInTheDocument();\n    expect(screen.getByText('Second Route')).toBeInTheDocument();\n  });\n\n  it('should render the parent and sub-route when navigated to', async () => {\n    const history = createBrowserHistory();\n    const listeners = [];\n\n    jest.spyOn(history, 'listen').mockImplementation((callback) => {\n      listeners.push(callback);\n      return () => {};\n    });\n\n    jest.spyOn(history, 'push').mockImplementation((sender) => {\n      listeners.forEach((l) => {\n        l({ location: { search: '', pathname: sender } });\n      });\n    });\n\n    const Button = () => {\n      const { actions } = useRouteHistory();\n      return (\n        <button onClick={() => actions.push('/second-route/sub-entity')}>\n          {'Visit Sub Entity on Second Page'}\n        </button>\n      );\n    };\n\n    render(\n      <RouterProvider history={history}>\n        <Button />\n        <Route path=\"/\" exact component={<div>{'Home'}</div>} />\n        <Route\n          path=\"/second-route\"\n          component={\n            <div>\n              {'Second Route'}\n              <Route\n                path=\"/second-route/sub-entity\"\n                component={<div>{'Sub Entity Route'}</div>}\n              />\n            </div>\n          }\n        />\n      </RouterProvider>\n    );\n\n    const link = await screen.findByText('Visit Sub Entity on Second Page');\n    fireEvent.click(link);\n    expect(screen.queryByText('Home')).not.toBeInTheDocument();\n    expect(screen.getByText('Second Route')).toBeInTheDocument();\n    expect(screen.getByText('Sub Entity Route')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/router/test/routerProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport RouterProvider, { getActiveRoute } from '../routerProvider';\nimport useRouteHistory from '../useRouteHistory';\n\nconst DEFAULT_ROUTE = '/';\nconst ROUTE_LIST = ['/templates-gallery', '/settings', '/custom-route'];\nconst AVAILABLE_ROUTES = [...ROUTE_LIST, DEFAULT_ROUTE];\n\ndescribe('routerProvider', () => {\n  it('should set available and default routes', async () => {\n    const { result } = renderHook(() => useRouteHistory(), {\n      wrapper: (props) => <RouterProvider {...props} />,\n    });\n\n    await act(async () => {\n      await result.current.actions.setAvailableRoutes(AVAILABLE_ROUTES);\n    });\n\n    expect(result.current.state.availableRoutes).toStrictEqual(\n      AVAILABLE_ROUTES\n    );\n  });\n\n  it.each`\n    currentPath             | result\n    ${'/'}                  | ${'/'}\n    ${'/templates-gallery'} | ${'/templates-gallery'}\n    ${'wpbody-content'}     | ${'/'}\n    ${'/jafklajdfslkjl'}    | ${'/'}\n  `(\n    'should return proper active route if available otherwise the default route',\n    ({ currentPath, result }) => {\n      expect(\n        getActiveRoute({\n          currentPath,\n          defaultRoute: DEFAULT_ROUTE,\n          availableRoutes: AVAILABLE_ROUTES,\n        })\n      ).toStrictEqual(result);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/router/useRouteHistory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { RouterProviderState } from '../../types';\nimport Context from './context';\n\nfunction useRouteHistory(): RouterProviderState;\nfunction useRouteHistory<T>(selector: (state: RouterProviderState) => T): T;\nfunction useRouteHistory<T>(\n  selector: (state: RouterProviderState) => T | RouterProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useRouteHistory;\n"
  },
  {
    "path": "packages/dashboard/src/app/serializers/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as reshapeTemplateObject } from './templates';\n"
  },
  {
    "path": "packages/dashboard/src/app/serializers/templates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { toUTCDate, toDate, getOptions } from '@googleforcreators/date';\n\nexport default function reshapeTemplateObject(\n  originalTemplateData,\n  isLocal = false\n) {\n  const { id, slug, modified, creationDate } = originalTemplateData;\n  if (!id || !slug) {\n    return null;\n  }\n\n  return {\n    ...originalTemplateData,\n    id,\n    slug,\n    creationDate: toDate(creationDate, getOptions()),\n    status: 'template',\n    modified: toUTCDate(modified),\n    isLocal,\n  };\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/serializers/test/templates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { toDate } from '@googleforcreators/date';\n\n/**\n * Internal dependencies\n */\nimport reshapeTemplateObject from '../templates';\n\ndescribe('reshapeTemplateObject', () => {\n  it('should return the template object', () => {\n    const responseObj = {\n      id: 1,\n      slug: 'template-1-slug',\n      pages: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],\n      creationDate: '2020-03-26T20:57:24',\n      modified: '2020-03-26T20:57:24',\n      status: 'template',\n    };\n\n    const reshapedObj = reshapeTemplateObject(responseObj, false);\n\n    expect(reshapedObj).toMatchObject({\n      id: 1,\n      slug: 'template-1-slug',\n      creationDate: toDate('2020-03-26T20:57:24.000Z'),\n      status: 'template',\n      modified: toDate('2020-03-26T20:57:24.000Z'),\n    });\n  });\n\n  it('should not return the template object', () => {\n    const reshapedObj = reshapeTemplateObject(\n      {\n        pages: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],\n        creationDate: '2020-03-26T20:57:24',\n      },\n      true\n    );\n\n    expect(reshapedObj).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/textContent/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const ERRORS = {\n  LOAD_STORIES: {\n    MESSAGE: __('Unable to load stories', 'web-stories'),\n  },\n  UPDATE_STORY: {\n    MESSAGE: __('Unable to update story', 'web-stories'),\n  },\n  DELETE_STORY: {\n    MESSAGE: __('Unable to delete story', 'web-stories'),\n  },\n  CREATE_STORY_FROM_TEMPLATE: {\n    MESSAGE: __('Unable to create story from template', 'web-stories'),\n  },\n  DUPLICATE_STORY: {\n    MESSAGE: __('Unable to duplicate story', 'web-stories'),\n  },\n  LOAD_TEMPLATES: {\n    DEFAULT_MESSAGE: __('Cannot connect to data source', 'web-stories'),\n    MESSAGE: __('Unable to load templates', 'web-stories'),\n  },\n  RENDER_PREVIEW: {\n    MESSAGE: __('Unable to render preview', 'web-stories'),\n  },\n  LOAD_TEMPLATE: {\n    DEFAULT_MESSAGE: __('Could not load the template', 'web-stories'),\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/apiAlerts/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonType,\n  SnackbarProvider,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport ApiContext from '../../../api/context';\nimport useApiAlerts from '../../../api/useApiAlerts';\n\nconst SnackbarView = () => {\n  useApiAlerts();\n  return <div />;\n};\n\nexport default {\n  title: 'Dashboard/Views/DashboardSnackbar',\n  component: SnackbarView,\n};\n\nconst storyErrors = [\n  { message: 'I am an error about loading stories.' },\n  { message: 'I am another error about loading stories.' },\n  { message: 'Error updating story.' },\n  { message: 'Something is really not working!' },\n  { message: 'I am the last preloaded error for stories in this storybook.' },\n];\n\nconst templateErrors = [\n  { message: 'I am a template error.' },\n  { message: 'I am another template error.' },\n  { message: 'I am the third template error.' },\n  { message: 'Something is really not working (still)!' },\n  { message: 'I am the last preloaded error for templates in this storybook.' },\n];\n\nexport const _default = {\n  render: function Render() {\n    const [storyError, setStoryError] = useState();\n    const [storyErrorIndexToAdd, setStoryErrorIndexToAdd] = useState(0);\n    const [templateError, setTemplateError] = useState();\n    const [templateErrorIndexToAdd, setTemplateErrorIndexToAdd] = useState(0);\n\n    return (\n      <ApiContext.Provider\n        value={{\n          state: {\n            stories: { error: storyError },\n            templates: { error: templateError },\n            settings: { error: {} },\n            media: { error: {} },\n          },\n        }}\n      >\n        <Button\n          type={ButtonType.Primary}\n          onClick={() => {\n            setStoryErrorIndexToAdd(storyErrorIndexToAdd + 1);\n            setStoryError({\n              ...storyErrors[storyErrorIndexToAdd],\n              id: Date.now(),\n            });\n          }}\n          isDisabled={storyErrorIndexToAdd > storyErrors.length - 1}\n        >\n          {storyErrorIndexToAdd > storyErrors.length - 1\n            ? 'No more practice story alerts'\n            : 'Add practice story alert'}\n        </Button>\n        <br />\n        <Button\n          type={ButtonType.Primary}\n          onClick={() => {\n            setTemplateErrorIndexToAdd(templateErrorIndexToAdd + 1);\n            setTemplateError({\n              ...templateErrors[templateErrorIndexToAdd],\n              id: Date.now(),\n            });\n          }}\n          isDisabled={templateErrorIndexToAdd > templateErrors.length - 1}\n        >\n          {templateErrorIndexToAdd > templateErrors.length - 1\n            ? 'No more practice template alerts'\n            : 'Add practice template alert'}\n        </Button>\n        <SnackbarProvider>\n          <SnackbarView />\n        </SnackbarProvider>\n      </ApiContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const TEMPLATE_META_DATA_TYPES = {\n  VERTICAL: 'VERTICAL',\n  COLOR: 'COLOR',\n  TAG: 'TAG',\n  TITLE: 'TITLE',\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Gradient, Scrim, Poster } from '../../shared/grid/components';\n\n// Allows grid item contents to overlay in a set space\nexport const CardWrapper = styled.div`\n  position: absolute;\n  height: 100%;\n  width: 100%;\n\n  transition: opacity ease-in-out 300ms;\n\n  &:hover {\n    ${Gradient}, ${Scrim} {\n      opacity: 1;\n    }\n  }\n\n  ${Gradient}, ${Scrim} {\n    opacity: ${({ $isSelected }) => ($isSelected ? 1 : 0)};\n  }\n`;\n\nexport const TemplateDisplayContent = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: space-between;\n  height: 100%;\n  padding-bottom: 16px;\n\n  a,\n  button {\n    margin: auto auto 0;\n  }\n`;\n\nexport const PicturePoster = styled(Poster).attrs({ as: 'picture' })`\n  display: block;\n  & > img {\n    height: 100%;\n    width: 100%;\n    object-fit: fill;\n    border-radius: ${({ theme }) => theme.borders.radius.medium};\n  }\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  Headline,\n  LoadingSpinner,\n  TextSize,\n  InfiniteScroller,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../config';\nimport {\n  Layout,\n  StandardViewContentGutter,\n  LoadingContainer,\n} from '../../../../components';\nimport {\n  ViewPropTypes,\n  PagePropTypes,\n} from '../../../../utils/useTemplateView';\nimport {\n  TemplatesPropType,\n  TemplateActionsPropType,\n} from '../../../../propTypes';\nimport { EmptyContentMessage } from '../../shared';\nimport TemplateGridView from './templateGridView';\n\nfunction Content({\n  allPagesFetched,\n  isLoading,\n  page,\n  templates,\n  view,\n  totalTemplates,\n  search,\n  templateActions,\n}) {\n  const { newStoryURL } = useConfig();\n\n  const pageContent = useMemo(() => {\n    if (isLoading) {\n      return (\n        <LoadingContainer>\n          <LoadingSpinner />\n        </LoadingContainer>\n      );\n    }\n    return totalTemplates > 0 ? (\n      <>\n        <TemplateGridView\n          templates={templates}\n          pageSize={view.pageSize}\n          templateActions={templateActions}\n        />\n        <InfiniteScroller\n          canLoadMore={!allPagesFetched}\n          isLoading={isLoading}\n          allDataLoadedMessage={__('No more templates', 'web-stories')}\n          allDataLoadedAriaMessage={__(\n            'All templates are loaded',\n            'web-stories'\n          )}\n          loadingAriaMessage={__('Loading more templates', 'web-stories')}\n          onLoadMore={page.requestNextPage}\n        />\n      </>\n    ) : (\n      <EmptyContentMessage>\n        <Headline size={TextSize.Small} as=\"h3\">\n          {search\n            ? sprintf(\n                /* translators: %s: search term. */\n                __(\n                  'Sorry, we couldn\\'t find any results matching \"%s\"',\n                  'web-stories'\n                ),\n                search\n              )\n            : __('No templates currently available.', 'web-stories')}\n        </Headline>\n        {!search && (\n          <ButtonAsLink\n            type={ButtonType.Primary}\n            size={ButtonSize.Medium}\n            href={newStoryURL}\n          >\n            {__('Create New Story', 'web-stories')}\n          </ButtonAsLink>\n        )}\n      </EmptyContentMessage>\n    );\n  }, [\n    allPagesFetched,\n    isLoading,\n    newStoryURL,\n    page.requestNextPage,\n    templateActions,\n    search,\n    templates,\n    totalTemplates,\n    view.pageSize,\n  ]);\n\n  return (\n    <Layout.Scrollable>\n      <StandardViewContentGutter>{pageContent}</StandardViewContentGutter>\n    </Layout.Scrollable>\n  );\n}\n\nContent.propTypes = {\n  allPagesFetched: PropTypes.bool,\n  isLoading: PropTypes.bool,\n  page: PagePropTypes,\n  templates: TemplatesPropType,\n  totalTemplates: PropTypes.number,\n  search: PropTypes.string,\n  templateActions: TemplateActionsPropType,\n  view: ViewPropTypes,\n};\nexport default Content;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Layout } from '../../../../../components';\nimport { VIEW_STYLE } from '../../../../../constants';\nimport { formattedTemplatesArray } from '../../../../../storybookUtils';\nimport { usePagePreviewSize } from '../../../../../utils';\nimport Content from '..';\n\nconst StorybookLayoutContainer = styled.div`\n  margin-top: 40px;\n  height: 100vh;\n`;\n\nexport default {\n  title: 'Dashboard/Views/ExploreTemplates/Content',\n  component: Content,\n  args: {\n    allPagesFetched: false,\n    isLoading: false,\n    pageValue: 1,\n    searchKeyword: '',\n    templates: formattedTemplatesArray,\n    viewStyle: VIEW_STYLE.GRID,\n    totalTemplates: 3,\n  },\n  argTypes: {\n    handleDetailsToggle: { action: 'modal was toggled' },\n    switchToTemplateByOffset: { action: 'switched to prev/next template' },\n    set: { action: 'set page number' },\n    requestNextPage: { action: 'request next page clicked' },\n    setKeyword: { action: 'set search' },\n    viewStyle: { options: VIEW_STYLE, control: 'radio' },\n  },\n  parameters: {\n    controls: {\n      exclude: [\n        'pageValue',\n        'templates',\n        'page',\n        'search',\n        'view',\n        'templateActions',\n      ],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const { pageSize } = usePagePreviewSize({\n      isGrid: true,\n    });\n    const templateActions = {\n      handleDetailsToggle: args.handleDetailsToggle,\n      switchToTemplateByOffset: args.switchToTemplateByOffset,\n    };\n    const page = {\n      set: args.set,\n      requestNextPage: args.requestNextPage,\n      value: args.pageValue,\n    };\n    const search = {\n      setKeyword: args.setKeyword,\n      keyword: args.searchKeyword,\n    };\n    const view = {\n      pageSize,\n      style: args.viewStyle,\n    };\n\n    const defaultNestedProps = {\n      templateActions,\n      page,\n      search,\n      view,\n    };\n\n    return (\n      <Layout.Provider>\n        <StorybookLayoutContainer>\n          <Content {...args} {...defaultNestedProps} />\n        </StorybookLayoutContainer>\n      </Layout.Provider>\n    );\n  },\n};\n\nexport const NoSearchResults = {\n  render: _default,\n\n  args: {\n    allPagesFetched: true,\n    totalTemplates: 0,\n    searchKeyword: 'polar bears',\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/templateGridItem.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  noop,\n} from '@googleforcreators/design-system';\nimport { forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport {\n  DEFAULT_GRID_IMG_HEIGHT,\n  DEFAULT_GRID_IMG_WIDTH,\n  TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS,\n} from '../../../../constants';\nimport { CardGridItem } from '../../../../components';\nimport { Container, Gradient, Scrim } from '../../shared/grid/components';\nimport {\n  TemplateDisplayContent,\n  CardWrapper,\n  PicturePoster,\n} from './components';\n\nexport const FOCUS_TEMPLATE_CLASS = 'focus_template';\n\nconst SeeDetailsButton = styled(Button).attrs({\n  type: ButtonType.Tertiary,\n  size: ButtonSize.Small,\n})`\n  background-color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nconst TemplateGridItem = forwardRef(\n  (\n    {\n      onCreateStory,\n      onFocus,\n      height,\n      id,\n      isActive,\n      posterSrc,\n      slug,\n      title,\n      status,\n      onSeeDetailsClick = noop,\n    },\n    ref\n  ) => {\n    const tabIndex = isActive ? 0 : -1;\n    const posterAltText = sprintf(\n      /* translators: %s: Template title. */\n      __('First page of %s template', 'web-stories'),\n      title\n    );\n\n    return (\n      <CardGridItem\n        ref={ref}\n        id={`template-grid-item-${id}`}\n        className=\"templateGridItem\"\n        data-testid={`template-grid-item-${id}`}\n        $posterHeight={height}\n        onFocus={onFocus}\n      >\n        <Container>\n          <CardWrapper $isSelected={isActive}>\n            <PicturePoster>\n              <source srcSet={posterSrc?.webp} type=\"image/webp\" />\n              <source srcSet={posterSrc?.png} type=\"image/png\" />\n              <img\n                src={posterSrc?.png}\n                alt={posterAltText}\n                decoding=\"async\"\n                width={DEFAULT_GRID_IMG_WIDTH}\n                height={DEFAULT_GRID_IMG_HEIGHT}\n              />\n            </PicturePoster>\n            <Gradient />\n            <Scrim\n              data-testid=\"card-action-container\"\n              data-template-slug={slug}\n            >\n              <TemplateDisplayContent>\n                <SeeDetailsButton\n                  ariaLabel={sprintf(\n                    /* translators: %s: template title.*/\n                    __('Go to detail view of %s', 'web-stories'),\n                    title\n                  )}\n                  onClick={() => onSeeDetailsClick(id, title)}\n                  className={FOCUS_TEMPLATE_CLASS}\n                  tabIndex={tabIndex}\n                >\n                  {TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS[status]}\n                </SeeDetailsButton>\n\n                {onCreateStory && (\n                  <Button\n                    size={ButtonSize.Small}\n                    type={ButtonType.Primary}\n                    onClick={onCreateStory}\n                    tabIndex={tabIndex}\n                    ariaLabel={sprintf(\n                      /* translators: %s: template title.*/\n                      __('Create new story from %s', 'web-stories'),\n                      title\n                    )}\n                  >\n                    {__('Use template', 'web-stories')}\n                  </Button>\n                )}\n              </TemplateDisplayContent>\n            </Scrim>\n          </CardWrapper>\n        </Container>\n      </CardGridItem>\n    );\n  }\n);\n\nTemplateGridItem.displayName = 'TemplateGridItem';\n\nTemplateGridItem.propTypes = {\n  detailLink: PropTypes.string,\n  onCreateStory: PropTypes.func,\n  onFocus: PropTypes.func.isRequired,\n  onSeeDetailsClick: PropTypes.func,\n  height: PropTypes.number.isRequired,\n  id: PropTypes.number.isRequired,\n  isActive: PropTypes.bool,\n  posterSrc: PropTypes.shape({\n    webp: PropTypes.string.isRequired,\n    png: PropTypes.string.isRequired,\n  }),\n  slug: PropTypes.string.isRequired,\n  status: PropTypes.string.isRequired,\n  title: PropTypes.string.isRequired,\n};\nexport default TemplateGridItem;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useRef,\n  useFocusOut,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { useGridViewKeys } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { CardGrid } from '../../../../components';\nimport {\n  PageSizePropType,\n  TemplatesPropType,\n  TemplateActionsPropType,\n} from '../../../../propTypes';\nimport { useConfig } from '../../../config';\nimport { noop } from '../../../../utils';\nimport TemplateGridItem, { FOCUS_TEMPLATE_CLASS } from './templateGridItem';\n\nfunction TemplateGridView({\n  pageSize,\n  templates: filteredTemplates,\n  templateActions,\n}) {\n  const { isRTL, apiCallbacks } = useConfig();\n  const containerRef = useRef();\n  const gridRef = useRef();\n  const itemsRef = useRef({});\n  const [activeGridItemId, setActiveGridItemId] = useState(null);\n  const { handleDetailsToggle, createStoryFromTemplate } =\n    templateActions || {};\n\n  const canCreateStory = Boolean(apiCallbacks?.createStoryFromTemplate);\n\n  useGridViewKeys({\n    containerRef,\n    gridRef,\n    itemRefs: itemsRef,\n    isRTL,\n    currentItemId: activeGridItemId,\n    items: filteredTemplates,\n  });\n\n  // when keyboard focus changes and updated activeGridItemId\n  // immediately focus the first interactive element in the grid item\n  // for legibility, it's based on the FOCUS_TEMPLATE_CLASS\n  useEffect(() => {\n    if (activeGridItemId) {\n      itemsRef.current?.[activeGridItemId]\n        ?.querySelector(`.${FOCUS_TEMPLATE_CLASS}`)\n        ?.focus();\n    }\n  }, [activeGridItemId]);\n\n  useFocusOut(containerRef, () => setActiveGridItemId(null), []);\n\n  const memoizedTemplateItems = useMemo(\n    () =>\n      filteredTemplates.map(({ id, slug, status, title, postersByPage }) => {\n        const isActive = activeGridItemId === id;\n        const posterSrc = postersByPage?.[0];\n        return (\n          <TemplateGridItem\n            onCreateStory={\n              canCreateStory ? () => createStoryFromTemplate(id) : noop\n            }\n            onFocus={() => {\n              setActiveGridItemId(id);\n            }}\n            onSeeDetailsClick={handleDetailsToggle}\n            height={pageSize.height}\n            id={id}\n            isActive={isActive}\n            key={slug}\n            posterSrc={posterSrc}\n            ref={(el) => {\n              itemsRef.current[id] = el;\n            }}\n            slug={slug}\n            status={status}\n            title={title}\n          />\n        );\n      }),\n    [\n      filteredTemplates,\n      activeGridItemId,\n      canCreateStory,\n      handleDetailsToggle,\n      pageSize.height,\n      createStoryFromTemplate,\n    ]\n  );\n\n  return (\n    <div ref={containerRef}>\n      <CardGrid\n        pageSize={pageSize}\n        role=\"list\"\n        ref={gridRef}\n        ariaLabel={__('Viewing available templates', 'web-stories')}\n      >\n        {memoizedTemplateItems}\n      </CardGrid>\n    </div>\n  );\n}\n\nTemplateGridView.propTypes = {\n  pageSize: PageSizePropType,\n  templates: TemplatesPropType,\n  templateActions: TemplateActionsPropType,\n};\nexport default TemplateGridView;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/content/test/content.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n  TEMPLATES_GALLERY_STATUS,\n  VIEW_STYLE,\n} from '../../../../../constants';\nimport { renderWithProviders } from '../../../../../testUtils';\nimport LayoutProvider from '../../../../../components/layout/provider';\nimport Content from '..';\nimport { ConfigProvider } from '../../../../config';\nimport useTemplateFilters from '../../filters/useTemplateFilters';\n\nconst fakeTemplates = [\n  {\n    id: 1,\n    slug: 'beauty',\n    title: 'Beauty',\n    createdBy: 'Google',\n    description:\n      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consectetur mauris sodales magna elementum maximus.',\n    status: 'template',\n    bottomTargetAction: () => {},\n  },\n  {\n    id: 2,\n    slug: 'cooking',\n    title: 'Cooking',\n    createdBy: 'Google',\n    description:\n      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consectetur mauris sodales magna elementum maximus.',\n    status: 'template',\n    bottomTargetAction: () => {},\n  },\n  {\n    id: 3,\n    slug: 'fitness',\n    title: 'Fitness',\n    createdBy: 'Google',\n    description:\n      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus consectetur mauris sodales magna elementum maximus.',\n    status: 'template',\n    bottomTargetAction: () => {},\n  },\n];\n\njest.mock('../../filters/useTemplateFilters', () => ({\n  ...jest.requireActual('../../filters/useTemplateFilters'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\nconst mockUseTemplateFilters = useTemplateFilters;\n\nconst updateSort = jest.fn();\nconst updateFilter = jest.fn();\n\nconst mockFilterState = {\n  filters: [\n    {\n      key: 'search',\n      filterId: null,\n    },\n    {\n      key: 'status',\n      filterId: TEMPLATES_GALLERY_STATUS.ALL,\n    },\n  ],\n  filtersObject: {\n    status: TEMPLATES_GALLERY_STATUS.ALL,\n  },\n  sortObject: {\n    orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n  },\n  registerFilters: () => {},\n  updateFilter,\n  updateSort,\n};\n\ndescribe('Explore Templates <Content />', () => {\n  beforeEach(() => {\n    mockUseTemplateFilters.mockImplementation(() => mockFilterState);\n  });\n\n  it('should render the content grid with the correct template count.', () => {\n    renderWithProviders(\n      <ConfigProvider config={{ cdnURL: 'cdn.example.com' }}>\n        <LayoutProvider>\n          <Content\n            templates={fakeTemplates}\n            totalTemplates={3}\n            page={{\n              requestNextPage: jest.fn,\n            }}\n            view={{\n              style: VIEW_STYLE.GRID,\n              pageSize: { width: 200, height: 300 },\n            }}\n          />\n        </LayoutProvider>\n      </ConfigProvider>\n    );\n\n    const useButtons = screen.getAllByTestId(/^template-grid-item/);\n\n    expect(useButtons).toHaveLength(fakeTemplates.length);\n  });\n\n  it('should show \"No templates currently available.\" if no templates are present.', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Content\n          templates={[]}\n          totalTemplates={0}\n          page={{\n            requestNextPage: jest.fn,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n        />\n      </LayoutProvider>\n    );\n    expect(\n      screen.getByText('No templates currently available.')\n    ).toBeInTheDocument();\n  });\n\n  it('should show \"Sorry, we couldn\\'t find any results matching \"scooby dooby doo\" if no templates are found for a search query are present.', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Content\n          search={'scooby dooby doo'}\n          templates={[]}\n          totalTemplates={0}\n          page={{\n            requestNextPage: jest.fn,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n        />\n      </LayoutProvider>\n    );\n\n    expect(\n      screen.getByText(\n        'Sorry, we couldn\\'t find any results matching \"scooby dooby doo\"'\n      )\n    ).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/filters/TemplateFiltersProvider/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createContext,\n  useReducer,\n  useCallback,\n  useMemo,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_TEMPLATE_FILTERS } from '../../../../../constants/templates';\nimport reducer from '../../../filters/reducer';\nimport * as types from '../../../filters/types';\n\nexport const filterContext = createContext({\n  state: {},\n  actions: {},\n});\n\nconst { filters: defaultTemplateFilters, sort: defaultTemplateSort } =\n  DEFAULT_TEMPLATE_FILTERS;\n\nexport default function TemplateFiltersProvider({ children }) {\n  const [state, dispatch] = useReducer(reducer, {\n    filters: [],\n    filtersObject: defaultTemplateFilters,\n    sortObject: defaultTemplateSort,\n  });\n\n  /**\n   * Dispatch UPDATE_FILTER with new data for a given filter\n   *\n   * @param {string} key key property on one of the filter objects\n   * @param {Object} value the properties with updated values\n   * @return {void}\n   */\n  const updateFilter = useCallback((key, value) => {\n    dispatch({ type: types.UPDATE_FILTER, payload: { key, value } });\n  }, []);\n\n  /**\n   * Dispatch UPDATE_SORT with new data to update sort\n   *\n   * @param {string} key key property on one of the sort objects\n   * @param {Object} value the properties with updated values\n   * @return {void}\n   */\n  const updateSort = useCallback((values) => {\n    dispatch({\n      type: types.UPDATE_SORT,\n      payload: { type: 'template', values },\n    });\n  }, []);\n\n  /**\n   * Dispatch REGISTER_FILTERS with all the filters data\n   *\n   * @param {Array} payload array of filters data\n   * @return {void}\n   */\n  const registerFilters = useCallback((value) => {\n    dispatch({ type: types.REGISTER_FILTERS, payload: { value } });\n  }, []);\n\n  const contextValue = useMemo(() => {\n    return { state, actions: { updateSort, updateFilter, registerFilters } };\n  }, [state, updateSort, updateFilter, registerFilters]);\n\n  return (\n    <filterContext.Provider value={contextValue}>\n      {children}\n    </filterContext.Provider>\n  );\n}\n\nTemplateFiltersProvider.propTypes = {\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/filters/test/templateFiltersProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport TemplateFiltersProvider from '../TemplateFiltersProvider';\nimport { TEMPLATE_SORT_KEYS } from '../../../../../constants/templates';\nimport useTemplateFilters from '../useTemplateFilters';\n\ndescribe('provider', () => {\n  it('should register filters and update filters', () => {\n    const wrapper = ({ children }) => (\n      <TemplateFiltersProvider>{children}</TemplateFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useTemplateFilters(), { wrapper });\n    const filterKey = 'color';\n\n    // register filter\n    act(() => {\n      result.current.actions.registerFilters([\n        { key: filterKey, filterId: null },\n      ]);\n    });\n\n    // shouldn't be able to register filters with the same key\n    act(() => {\n      result.current.actions.registerFilters([{ key: filterKey, filterId: 1 }]);\n    });\n    expect(result.current.state.filters).toHaveLength(1);\n\n    let filter = result.current.state.filters.find((f) => f.key === filterKey);\n    let filterObj = result.current.state.filtersObject;\n\n    expect(filter).toBeDefined();\n    expect(filter.filterId).toBeNull();\n\n    // filters with falsy filterId's should not be in the filters object\n    expect(filterObj).toMatchObject({});\n\n    // update the filter\n    act(() => {\n      result.current.actions.updateFilter(filterKey, {\n        filterId: 1,\n      });\n    });\n\n    filter = result.current.state.filters.find((f) => f.key === filterKey);\n    filterObj = result.current.state.filtersObject;\n\n    expect(filter).toMatchObject({\n      filterId: 1,\n    });\n    expect(filterObj).toMatchObject({\n      [filterKey]: 1,\n    });\n\n    // should unset filterId if the current filterId is given\n    act(() => {\n      result.current.actions.updateFilter(filterKey, {\n        filterId: 1,\n      });\n    });\n    filter = result.current.state.filters.find((f) => f.key === filterKey);\n    filterObj = result.current.state.filtersObject;\n    expect(filter).toMatchObject({\n      filterId: null,\n    });\n    expect(filterObj[filterKey]).toBeUndefined();\n  });\n\n  it('should not unset \"search\" and \"status\" if the same filterId is given', () => {\n    const wrapper = ({ children }) => (\n      <TemplateFiltersProvider>{children}</TemplateFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useTemplateFilters(), { wrapper });\n\n    // register search and status filter\n    act(() => {\n      result.current.actions.registerFilters([\n        { key: 'search' },\n        { key: 'status' },\n      ]);\n    });\n    let searchFilter = result.current.state.filters.find(\n      ({ key }) => key === 'search'\n    );\n    let statusFilter = result.current.state.filters.find(\n      ({ key }) => key === 'status'\n    );\n    expect(searchFilter).toBeDefined();\n    expect(statusFilter).toBeDefined();\n\n    // update the 'search' filter\n    act(() => {\n      result.current.actions.updateFilter('search', { filterId: 'Blue' });\n    });\n\n    // update the 'search' filter with the same current 'filterId'\n    act(() => {\n      result.current.actions.updateFilter('search', { filterId: 'Blue' });\n    });\n\n    searchFilter = result.current.state.filters.find(\n      ({ key }) => key === 'search'\n    );\n    expect(searchFilter.filterId).toBe('Blue');\n\n    // update the 'status' filter\n    act(() => {\n      result.current.actions.updateFilter('status', { filterId: 'New' });\n    });\n\n    // update the 'status' filter with the same current 'filterId'\n    act(() => {\n      result.current.actions.updateFilter('status', { filterId: 'New' });\n    });\n\n    statusFilter = result.current.state.filters.find(\n      ({ key }) => key === 'status'\n    );\n    expect(statusFilter.filterId).toBe('New');\n  });\n\n  it('should be able to update the sortObject if the acceptable keys are used', () => {\n    const wrapper = ({ children }) => (\n      <TemplateFiltersProvider>{children}</TemplateFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useTemplateFilters(), { wrapper });\n\n    for (const key of Object.keys(TEMPLATE_SORT_KEYS)) {\n      for (const value of Object.values(TEMPLATE_SORT_KEYS[key])) {\n        act(() => {\n          result.current.actions.updateSort({ [key]: value });\n        });\n        expect(result.current.state.sortObject).toMatchObject({ [key]: value });\n      }\n    }\n  });\n\n  it('should not be able to update the sortObject with arbitrary key value pairs', () => {\n    const wrapper = ({ children }) => (\n      <TemplateFiltersProvider>{children}</TemplateFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useTemplateFilters(), { wrapper });\n\n    const unacceptableSortValues = {\n      orderby: 'valueNotInSortKeyOrderby',\n      order: 'up',\n    };\n\n    const unacceptableSortKeys = {\n      sortby: 'popular',\n      sortorder: 'asc',\n    };\n\n    act(() => {\n      result.current.actions.updateSort(unacceptableSortValues);\n    });\n    expect(result.current.state.sortObject).toMatchObject({});\n\n    act(() => {\n      result.current.actions.updateSort(unacceptableSortKeys);\n    });\n    expect(result.current.state.sortObject).toMatchObject({});\n  });\n\n  it('should not return sortObject if nothing changes', () => {\n    const wrapper = ({ children }) => (\n      <TemplateFiltersProvider>{children}</TemplateFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useTemplateFilters(), { wrapper });\n\n    const acceptableSortObject = {\n      orderby: 'popular',\n      order: 'asc',\n    };\n\n    const unacceptableSortKeys = {\n      sortby: 'popular',\n      sortorder: 'asc',\n    };\n\n    act(() => {\n      // set the sortObject to an acceptable sortObject\n      result.current.actions.updateSort(acceptableSortObject);\n      // try to set the sortObject to an unacceptable sortObject\n      result.current.actions.updateSort(unacceptableSortKeys);\n    });\n    // the state shouldn't be updated if given an unacceptable sortObject\n    expect(result.current.state.sortObject).toMatchObject(acceptableSortObject);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/filters/useTemplateFilters.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { filterContext } from './TemplateFiltersProvider';\n\nexport default function useTemplateFilters(selector = identity) {\n  return useContextSelector(filterContext, selector);\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * External dependencies\n */\nimport {\n  useDebouncedCallback,\n  useCallback,\n  useMemo,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { useFeature } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport {\n  DASHBOARD_VIEWS,\n  DEFAULT_TEMPLATE_FILTERS,\n  TEMPLATES_GALLERY_SORT_MENU_ITEMS,\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n  TEXT_INPUT_DEBOUNCE,\n} from '../../../../constants';\nimport { ViewPropTypes } from '../../../../utils/useTemplateView';\nimport useTemplateFilters from '../filters/useTemplateFilters';\nimport { useDashboardResultsLabel } from '../../../../utils';\nimport { PageHeading, BodyViewOptions } from '../../shared';\n\nfunction Header({ isLoading, totalTemplates, view, searchOptions = [] }) {\n  const enableInProgressTemplateActions = useFeature(\n    'enableInProgressTemplateActions'\n  );\n\n  const { filters, sortObject, updateFilter, updateSort, registerFilters } =\n    useTemplateFilters(\n      ({\n        state: { filters, sortObject },\n        actions: { updateFilter, updateSort, registerFilters },\n      }) => ({\n        filters,\n        sortObject,\n        updateFilter,\n        updateSort,\n        registerFilters,\n      })\n    );\n\n  const [statusFilterValue, searchFilterValue] = useMemo(() => {\n    const status = filters.find(({ key }) => key === 'status');\n    const search = filters.find(({ key }) => key === 'search');\n    return [status?.filterId, search?.filterId];\n  }, [filters]);\n\n  const debouncedSearchChange = useDebouncedCallback((value) => {\n    updateFilter('search', { filterId: value });\n  }, TEXT_INPUT_DEBOUNCE);\n\n  useEffect(() => {\n    registerFilters([{ key: 'search' }]);\n    registerFilters([\n      { key: 'status', filterId: DEFAULT_TEMPLATE_FILTERS.filters.status },\n    ]);\n  }, [registerFilters]);\n\n  const clearSearch = useCallback(\n    () => updateFilter('search', { filterId: null }),\n    [updateFilter]\n  );\n\n  const resultsLabel = useDashboardResultsLabel({\n    totalResults: totalTemplates,\n    currentFilter: statusFilterValue,\n    view: DASHBOARD_VIEWS.TEMPLATES_GALLERY,\n  });\n\n  return (\n    <>\n      <PageHeading\n        heading={__('Explore Templates', 'web-stories')}\n        searchPlaceholder={__('Search Templates', 'web-stories')}\n        showSearch\n        searchOptions={searchOptions}\n        searchValue={searchFilterValue}\n        handleSearchChange={debouncedSearchChange}\n        onClear={clearSearch}\n      />\n      <BodyViewOptions\n        resultsLabel={resultsLabel}\n        layoutStyle={view.style}\n        handleLayoutSelect={view.toggleStyle}\n        isLoading={isLoading}\n        pageSortOptions={TEMPLATES_GALLERY_SORT_MENU_ITEMS}\n        pageSortDefaultOption={TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR}\n        currentSort={sortObject}\n        handleSortChange={updateSort}\n        showSortDropdown={enableInProgressTemplateActions}\n        sortDropdownAriaLabel={__(\n          'Choose sort option for display',\n          'web-stories'\n        )}\n      />\n    </>\n  );\n}\n\nHeader.propTypes = {\n  isLoading: PropTypes.bool,\n  totalTemplates: PropTypes.number,\n  view: ViewPropTypes.isRequired,\n  searchOptions: PropTypes.arrayOf(PropTypes.object),\n};\n\nexport default Header;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/header/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FlagsProvider } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport { Layout } from '../../../../../components';\nimport {\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n  VIEW_STYLE,\n  TEMPLATES_GALLERY_STATUS,\n} from '../../../../../constants';\nimport Header from '..';\nimport formattedTemplatesArray from '../../../../../dataUtils/formattedTemplatesArray';\n\nexport default {\n  title: 'Dashboard/Views/ExploreTemplates/Header',\n  component: Header,\n  args: {\n    style: VIEW_STYLE.GRID,\n    sortValue: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n    filterValue: TEMPLATES_GALLERY_STATUS.ALL,\n    keyword: '',\n    enableInProgressTemplateActions: true,\n  },\n  argTypes: {\n    style: { options: VIEW_STYLE, control: 'radio' },\n    sortValue: { options: TEMPLATES_GALLERY_SORT_OPTIONS, control: 'radio' },\n    filterValue: { options: TEMPLATES_GALLERY_STATUS, control: 'radio' },\n    setSort: { action: 'set Sort' },\n    setKeyword: { action: 'set keyword' },\n    setPage: { action: 'set page' },\n    requestNextPage: { action: 'request next page clicked' },\n  },\n  parameters: {\n    controls: {\n      include: ['setKeyword'],\n      hideNoControlsWarning: true,\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const filter = {\n      value: args.filterValue,\n    };\n    const sort = {\n      value: args.sortValue,\n      set: args.setSort,\n    };\n    const search = {\n      keyword: args.keyword,\n      setKeyword: args.setKeyword,\n    };\n    const view = {\n      style: args.style,\n      pageSize: { width: 210, height: 316 },\n    };\n    const page = {\n      value: 1,\n      set: args.setPage,\n      requestNextPage: args.requestNextPage,\n    };\n\n    const defaultProps = {\n      allPagesFetched: false,\n      isLoading: false,\n      page: page,\n      search: search,\n      templates: formattedTemplatesArray,\n      sort: sort,\n      filter: filter,\n      view: view,\n      totalTemplates: 3,\n    };\n    return (\n      <FlagsProvider features={args.enableInProgressTemplateActions}>\n        <Layout.Provider>\n          <Header {...args} {...defaultProps} />\n        </Layout.Provider>\n      </FlagsProvider>\n    );\n  },\n};\n\nexport const ActiveSearch = {\n  render: _default,\n\n  args: {\n    keyword: 'demo search',\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/header/test/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  TEMPLATES_GALLERY_STATUS,\n  VIEW_STYLE,\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n} from '../../../../../constants';\nimport { renderWithProviders } from '../../../../../testUtils';\nimport LayoutProvider from '../../../../../components/layout/provider';\nimport useTemplateFilters from '../../filters/useTemplateFilters';\nimport Header from '..';\n\njest.mock('../../filters/useTemplateFilters', () => ({\n  ...jest.requireActual('../../filters/useTemplateFilters'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\nconst mockUseTemplateFilters = useTemplateFilters;\n\nconst updateSort = jest.fn();\nconst updateFilter = jest.fn();\n\nconst mockFilterState = {\n  filters: [\n    {\n      key: 'search',\n      filterId: null,\n    },\n    {\n      key: 'status',\n      filterId: TEMPLATES_GALLERY_STATUS.ALL,\n    },\n  ],\n  filtersObject: {\n    status: TEMPLATES_GALLERY_STATUS.ALL,\n  },\n  sortObject: {\n    orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n  },\n  registerFilters: () => {},\n  updateFilter,\n  updateSort,\n};\n\ndescribe('Explore Templates <Header />', () => {\n  beforeEach(() => {\n    mockUseTemplateFilters.mockImplementation(() => mockFilterState);\n  });\n\n  it('should have results label that says \"Viewing all templates\" on initial page view', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          totalTemplates={3}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n        />\n      </LayoutProvider>,\n      { features: { enableInProgressTemplateActions: false } }\n    );\n\n    expect(screen.getByText('Viewing all templates')).toBeInTheDocument();\n  });\n\n  it('should call the set sort function when a new sort is selected', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          totalTemplates={8}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n        />\n      </LayoutProvider>,\n      { features: { enableInProgressTemplateActions: true } }\n    );\n    fireEvent.click(screen.getByLabelText('Choose sort option for display'));\n    fireEvent.click(screen.getByText('Recent'));\n\n    expect(updateSort).toHaveBeenCalledWith({ orderby: 'recent' });\n  });\n\n  it('should not render with search when features:{enableInProgressTemplateActions is false}', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          totalTemplates={8}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n        />\n      </LayoutProvider>,\n      { features: { enableInProgressTemplateActions: false } }\n    );\n    expect(screen.queryByRole('textbox')).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  useMemo,\n  useEffect,\n  useCallback,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport { trackEvent, trackScreenView } from '@googleforcreators/tracking';\nimport {\n  uniqueEntriesByKey,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Layout, ScrollToTop } from '../../../components';\nimport { useTemplateView } from '../../../utils';\n\nimport useApi from '../../api/useApi';\nimport useRouteHistory from '../../router/useRouteHistory';\nimport { getTemplateFilters, composeTemplateFilter } from '../utils';\nimport useTemplateFilters from './filters/useTemplateFilters';\nimport Content from './content';\nimport Header from './header';\nimport TemplateDetailsModal from './modal';\nimport TemplateFiltersProvider from './filters/TemplateFiltersProvider';\n\nfunction ExploreTemplatesView() {\n  const speak = useLiveRegion();\n  const [isDetailsViewOpen, setIsDetailsViewOpen] = useState(false);\n  const [activeTemplate, setActiveTemplate] = useState(null);\n  const [activeTemplateIndex, setActiveTemplateIndex] = useState(0);\n\n  const { templateIdParam, replace } = useRouteHistory(\n    ({ actions, state }) => ({\n      templateIdParam: state.queryParams.id,\n      replace: actions.replace,\n    })\n  );\n\n  const idRef = useRef(templateIdParam);\n\n  const {\n    allPagesFetched,\n    isLoading,\n    templates,\n    templatesOrderById,\n    totalPages,\n    totalTemplates,\n    createStoryFromTemplate,\n    fetchExternalTemplates,\n  } = useApi(\n    ({\n      state: {\n        templates: {\n          allPagesFetched,\n          isLoading,\n          templates,\n          templatesOrderById,\n          totalPages,\n          totalTemplates,\n        },\n      },\n      actions: {\n        storyApi: { createStoryFromTemplate },\n        templateApi: { fetchExternalTemplates },\n      },\n    }) => ({\n      allPagesFetched,\n      isLoading,\n      templates,\n      templatesOrderById,\n      totalPages,\n      totalTemplates,\n      createStoryFromTemplate,\n      fetchExternalTemplates,\n    })\n  );\n\n  const { filters, sortObject, filtersObject } = useTemplateFilters(\n    ({ state: { filters, sortObject, filtersObject } }) => ({\n      filters,\n      sortObject,\n      filtersObject,\n    })\n  );\n\n  const { page, view } = useTemplateView({\n    filtersObject,\n    sortObject,\n    totalPages,\n  });\n\n  const [searchFilterValue] = useMemo(() => {\n    const search = filters.find(({ key }) => key === 'search');\n    return [search?.filterId];\n  }, [filters]);\n\n  // extract templateFilters from template meta data\n  const templateFilters = useMemo(\n    () => getTemplateFilters(templates),\n    [templates]\n  );\n\n  // refine templateFilters by search term\n  const selectFilters = useMemo(\n    () =>\n      searchFilterValue\n        ? templateFilters.filter((opt) =>\n            opt.label.toLowerCase().includes(searchFilterValue.toLowerCase())\n          )\n        : templateFilters,\n    [templateFilters, searchFilterValue]\n  );\n\n  // filter templates by the refined templateFilters\n  const orderedTemplates = useMemo(() => {\n    return templatesOrderById\n      .map((templateId) => templates[templateId])\n      .filter(composeTemplateFilter(selectFilters));\n  }, [templatesOrderById, templates, selectFilters]);\n\n  const totalVisibleTemplates = useMemo(\n    () =>\n      totalTemplates !== orderedTemplates.length\n        ? orderedTemplates.length\n        : totalTemplates,\n    [orderedTemplates, totalTemplates]\n  );\n\n  // Although we may want to filter templates based on\n  // repeat meta data of differing types, we only want\n  // the auto-complete to show unique labels\n  const searchOptions = useMemo(\n    () => uniqueEntriesByKey(selectFilters, 'label'),\n    [selectFilters]\n  );\n\n  const handleCreateStoryFromTemplate = useCallback(\n    (templateId) => {\n      const template = templates[templateId];\n      trackEvent('use_template', {\n        name: template.title,\n        template_id: template.id,\n      });\n\n      createStoryFromTemplate(template);\n    },\n    [createStoryFromTemplate, templates]\n  );\n\n  const updateTemplateView = useCallback(\n    (id) => {\n      const currentTemplate = orderedTemplates.find(\n        (templateItem) => templateItem.id === id\n      );\n      setActiveTemplate(currentTemplate);\n      setActiveTemplateIndex(\n        orderedTemplates.findIndex((template) => template.id === id)\n      );\n      if (idRef.current) {\n        idRef.current = undefined;\n      }\n\n      replace(`?id=${currentTemplate.id}&isLocal=${currentTemplate.isLocal}`);\n    },\n    [replace, orderedTemplates]\n  );\n\n  const handleDetailsToggle = useCallback(\n    (id, title) => {\n      setIsDetailsViewOpen((prevIsOpen) => {\n        const newIsOpen = !prevIsOpen;\n        title && trackScreenView(title);\n\n        if (newIsOpen && id) {\n          updateTemplateView(id);\n        }\n\n        if (!newIsOpen) {\n          replace('');\n          speak(__('Exit detail templates view', 'web-stories'));\n        }\n\n        return newIsOpen;\n      });\n    },\n    [replace, speak, updateTemplateView]\n  );\n\n  const switchToTemplateByOffset = useCallback(\n    (offset) => {\n      const newTemplate = orderedTemplates[offset];\n      setActiveTemplate(newTemplate);\n      setActiveTemplateIndex(offset);\n      replace(`?id=${newTemplate.id}&isLocal=${newTemplate.isLocal}`);\n      speak(\n        sprintf(\n          /* translators: %s: template title */\n          __('Viewing %s', 'web-stories'),\n          newTemplate.title\n        )\n      );\n    },\n    [orderedTemplates, replace, speak]\n  );\n\n  const templateActions = useMemo(\n    () => ({\n      createStoryFromTemplate: handleCreateStoryFromTemplate,\n      handleDetailsToggle,\n      switchToTemplateByOffset,\n    }),\n    [\n      handleCreateStoryFromTemplate,\n      handleDetailsToggle,\n      switchToTemplateByOffset,\n    ]\n  );\n\n  useEffect(() => {\n    fetchExternalTemplates();\n  }, [fetchExternalTemplates]);\n\n  useEffect(() => {\n    if (idRef.current && orderedTemplates.length) {\n      const isValidId = orderedTemplates.some(\n        (template) => template.id === Number.parseInt(idRef.current)\n      );\n      if (!isValidId) {\n        replace('');\n        return;\n      }\n\n      setIsDetailsViewOpen(true);\n      updateTemplateView(Number.parseInt(idRef.current));\n    }\n  }, [orderedTemplates, replace, updateTemplateView]);\n\n  return (\n    <Layout.Provider>\n      <Header\n        isLoading={isLoading && !totalTemplates}\n        totalTemplates={totalVisibleTemplates}\n        searchOptions={searchOptions}\n        view={view}\n      />\n      <Content\n        isLoading={isLoading}\n        allPagesFetched={allPagesFetched}\n        page={page}\n        templates={orderedTemplates}\n        totalTemplates={totalVisibleTemplates}\n        search={searchFilterValue}\n        view={view}\n        templateActions={templateActions}\n      />\n      <Layout.Fixed>\n        <ScrollToTop />\n      </Layout.Fixed>\n      <TemplateDetailsModal\n        activeTemplate={activeTemplate}\n        activeTemplateIndex={activeTemplateIndex}\n        isDetailsViewOpen={isDetailsViewOpen}\n        templateActions={templateActions}\n        filteredTemplatesLength={orderedTemplates.length}\n      />\n    </Layout.Provider>\n  );\n}\n\nexport default function ExploreTemplates() {\n  return (\n    <TemplateFiltersProvider>\n      <ExploreTemplatesView />\n    </TemplateFiltersProvider>\n  );\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/karma/exploreTemplates.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Fixture from '../../../../karma/fixture';\nimport { TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS } from '../../../../constants';\nimport useApi from '../../../api/useApi';\n\ndescribe('Grid view', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await navigateToExploreTemplates();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  function navigateToExploreTemplates() {\n    const navigation = fixture.screen.queryByRole('navigation');\n    const utils = within(navigation);\n\n    const exploreTemplatesMenuItem = utils.getByText(/^Explore Templates/);\n\n    return fixture.events.click(exploreTemplatesMenuItem);\n  }\n\n  function getTemplateElementById(id) {\n    const template = fixture.screen.getByTestId(`template-grid-item-${id}`);\n\n    return template;\n  }\n\n  async function getTemplatesState() {\n    const {\n      state: { templates },\n    } = await fixture.renderHook(() => useApi());\n    return templates;\n  }\n\n  async function focusOnGridByKeyboard() {\n    let limit = 0;\n    const gridContainer = fixture.screen.getByTestId('dashboard-grid-list');\n\n    while (!gridContainer.contains(document.activeElement) && limit < 8) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('tab');\n      limit++;\n    }\n\n    return gridContainer.contains(document.activeElement)\n      ? Promise.resolve()\n      : Promise.reject(new Error('could not focus on grid'));\n  }\n\n  it('should pass accessibility tests', async () => {\n    const viewTemplates = fixture.screen.queryByText('Viewing all templates');\n    expect(viewTemplates).toBeTruthy();\n    await expectAsync(viewTemplates).toHaveNoViolations();\n  });\n\n  it('should navigate to Dashboard', async () => {\n    const DashboardMenuItem = fixture.screen.queryByRole('link', {\n      name: /^Dashboard$/,\n    });\n\n    await fixture.events.click(DashboardMenuItem);\n\n    const viewStories = fixture.screen.queryByText('Viewing all stories');\n\n    expect(viewStories).toBeTruthy();\n  });\n\n  describe('CUJ: Creator can browse templates in grid view: Browse all templates', () => {\n    it('should display \"See Details\" and \"Use Template\" controls when hovering over a template', async () => {\n      const { templatesOrderById } = await getTemplatesState();\n      const firstTemplate = getTemplateElementById(templatesOrderById[0]);\n\n      const utils = within(firstTemplate);\n\n      await fixture.events.hover(firstTemplate);\n\n      const seeDetailsButton = utils.getByText(\n        new RegExp(`^${TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS.template}$`)\n      );\n\n      expect(seeDetailsButton).toBeTruthy();\n\n      const useTemplate = utils.getByText(/^Use template$/);\n\n      expect(useTemplate).toBeTruthy();\n    });\n\n    it('should change focus as the user presses tab', async () => {\n      const { templatesOrderById } = await getTemplatesState();\n      // focus on first template\n      await focusOnGridByKeyboard();\n\n      await fixture.events.keyboard.press('right');\n\n      const firstTemplate = getTemplateElementById(templatesOrderById[0]);\n      expect(firstTemplate.contains(document.activeElement)).toBeTrue();\n\n      await fixture.events.keyboard.press('right');\n\n      const secondTemplate = getTemplateElementById(templatesOrderById[1]);\n      expect(secondTemplate.contains(document.activeElement)).toBeTrue();\n\n      await fixture.events.keyboard.press('right');\n\n      await fixture.events.keyboard.press('right');\n\n      const fourthTemplate = getTemplateElementById(templatesOrderById[3]);\n      expect(fourthTemplate.contains(document.activeElement)).toBeTrue();\n\n      await fixture.events.keyboard.press('left');\n\n      const thirdTemplate = getTemplateElementById(templatesOrderById[2]);\n      expect(thirdTemplate.contains(document.activeElement)).toBeTrue();\n    });\n  });\n\n  describe('CUJ: Creator can browse templates in grid view: See template details modal', () => {\n    it('should open modal to view individual template details', async () => {\n      const { templatesOrderById } = await getTemplatesState();\n      const firstTemplate = getTemplateElementById(templatesOrderById[0]);\n\n      const utils = within(firstTemplate);\n\n      await fixture.events.hover(firstTemplate);\n\n      const seeDetailsButton = utils.getByText(\n        new RegExp(`^${TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS.template}$`)\n      );\n\n      await fixture.events.click(seeDetailsButton);\n\n      const closeBtn = fixture.screen.getByRole('button', {\n        name: /^Close$/,\n      });\n\n      expect(closeBtn).toBeTruthy();\n    });\n  });\n\n  describe('Creator can search explore templates by meta data', () => {\n    async function getTemplateIdByTitle(title) {\n      const { templates } = await getTemplatesState();\n      return Object.values(templates).find(\n        (template) => template.title === title\n      )?.id;\n    }\n\n    it('should filter templates using the search input', async () => {\n      // Get original 8 templates\n      const originalTemplates =\n        fixture.screen.getAllByTestId(/^template-grid-item-/);\n      expect(originalTemplates.length).toBe(8);\n\n      // Get the template Search component\n      const searchInput =\n        fixture.screen.getByPlaceholderText('Search Templates');\n      expect(searchInput).toBeTruthy();\n\n      // Template Data formatted to have meta data:\n      // {\n      //   [metaDataType]: `Test ${metaDataType}`\n      //   title: `Filterable By ${metaDataType}`\n      //   ...\n      // }\n\n      // Filter by Tag\n      await fixture.events.focus(searchInput);\n      await fixture.events.keyboard.type('Test Tag');\n      // Wait for the debounce\n      await fixture.events.sleep(500);\n      // See that grid updates\n      const testTagGridItems =\n        fixture.screen.getAllByTestId(/^template-grid-item-/);\n      expect(testTagGridItems.length).toBe(1);\n      // See that we have the right grid item\n      const filterableTagTemplateId =\n        await getTemplateIdByTitle('Filterable By Tag');\n      const filterableTagTemplate = fixture.screen.getByTestId(\n        new RegExp(`^template-grid-item-${filterableTagTemplateId}$`)\n      );\n      expect(filterableTagTemplate).toBeDefined();\n\n      // As per PR#13301, it is required to edit search-input to get clearInput to be active\n      await fixture.events.focus(searchInput);\n      await fixture.events.keyboard.type('Test Tag...');\n\n      // Clear input\n      const clearInput = fixture.screen.getByLabelText('Clear Search');\n      await fixture.events.click(clearInput);\n\n      // Filter by Color\n      await fixture.events.focus(searchInput);\n      await fixture.events.keyboard.type('Test Color');\n      // Wait for the debounce\n      await fixture.events.sleep(500);\n      // See that grid updates\n      const testColorGridItems =\n        fixture.screen.getAllByTestId(/^template-grid-item-/);\n      expect(testColorGridItems.length).toBe(1);\n      // See that we have the right grid item\n      const filterableColorTemplateId = await getTemplateIdByTitle(\n        'Filterable By Color'\n      );\n      const filterableColorTemplate = fixture.screen.getByTestId(\n        new RegExp(`^template-grid-item-${filterableColorTemplateId}$`)\n      );\n      expect(filterableColorTemplate).toBeDefined();\n\n      // Clear input\n      await fixture.events.click(clearInput);\n\n      // Filter by Vertical\n      await fixture.events.focus(searchInput);\n      await fixture.events.keyboard.type('Test Vertical');\n      // Wait for the debounce\n      await fixture.events.sleep(500);\n      // See that grid updates\n      const testVerticalGridItems =\n        fixture.screen.getAllByTestId(/^template-grid-item-/);\n      expect(testVerticalGridItems.length).toBe(1);\n      // See that we have the right grid item\n      const filterableVerticalTemplateId = await getTemplateIdByTitle(\n        'Filterable By Vertical'\n      );\n      const filterableVerticalTemplate = fixture.screen.getByTestId(\n        new RegExp(`^template-grid-item-${filterableVerticalTemplateId}$`)\n      );\n      expect(filterableVerticalTemplate).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { Modal, theme } from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../config';\nimport {\n  TemplatePropType,\n  TemplateActionsPropType,\n} from '../../../../propTypes';\nimport Header from './templateDetails/header';\nimport DetailsContent from './templateDetails/content';\n\nfunction TemplateDetailsModal({\n  activeTemplateIndex,\n  activeTemplate,\n  filteredTemplatesLength,\n  isDetailsViewOpen,\n  templateActions,\n}) {\n  const { isRTL, apiCallbacks } = useConfig();\n  const canCreateStory = Boolean(apiCallbacks?.createStoryFromTemplate);\n\n  const { handleDetailsToggle, switchToTemplateByOffset } =\n    templateActions || {};\n\n  return (\n    <Modal\n      isOpen={isDetailsViewOpen}\n      onClose={handleDetailsToggle}\n      contentLabel={sprintf(\n        /* translators: %s: template title */\n        __('Template Details for %s', 'web-stories'),\n        activeTemplate?.title\n      )}\n      overlayStyles={{\n        backgroundColor: `${theme.colors.opacity.overlayDark}`,\n      }}\n      contentStyles={{\n        display: 'block',\n        height: '90vh',\n        width: '90vw',\n        backgroundColor: `${theme.colors.standard.white}`,\n      }}\n    >\n      <Header\n        templateTitle={activeTemplate?.title}\n        templateId={activeTemplate?.id}\n        templateActions={templateActions}\n        canCreateStory={canCreateStory}\n      />\n      <DetailsContent\n        activeTemplateIndex={activeTemplateIndex}\n        isRTL={isRTL}\n        filteredTemplatesLength={filteredTemplatesLength}\n        switchToTemplateByOffset={switchToTemplateByOffset}\n        template={activeTemplate}\n      />\n    </Modal>\n  );\n}\nTemplateDetailsModal.propTypes = {\n  activeTemplateIndex: PropTypes.number,\n  activeTemplate: TemplatePropType,\n  filteredTemplatesLength: PropTypes.number,\n  isDetailsViewOpen: PropTypes.bool,\n  templateActions: TemplateActionsPropType,\n};\nexport default TemplateDetailsModal;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\nexport const Panel = styled.section`\n  padding: 16vh 0 14vh 0;\n`;\n\nexport const Container = styled.div`\n  position: relative;\n  width: 76%;\n  max-width: ${0.76 * 1920}px;\n  margin: 0 auto;\n`;\n\nexport const Inner = styled.div`\n  display: flex;\n  align-items: start;\n`;\n\nexport const DetailContainer = styled.section.attrs({\n  'aria-label': __('Template Details', 'web-stories'),\n})`\n  padding: 0 0 0 60px;\n  margin-right: auto;\n`;\n\nexport const TemplateDetails = styled.div`\n  position: relative;\n  display: flex;\n  width: 500px;\n`;\n\nexport const RowContainer = styled.section.attrs({\n  'aria-label': __('Related Templates', 'web-stories'),\n})`\n  display: flex;\n  flex-wrap: wrap;\n  padding-bottom: 40px;\n  margin: 0 80px 0;\n  & > h3 {\n    padding-bottom: 32px;\n  }\n  & > div {\n    width: 100%;\n  }\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/content/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useEffect, useMemo, useState } from '@googleforcreators/react';\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Chip,\n  Display,\n  Icons,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { CardGallery, ColorList } from '../../../../../../components';\nimport { TemplatePropType } from '../../../../../../propTypes';\nimport {\n  Container,\n  Panel,\n  DetailContainer,\n  TemplateDetails,\n  Inner,\n} from '../components';\n\nconst StyledPanel = styled(Panel)`\n  padding: 0 0 48px 0;\n`;\n\nconst ByLineText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  margin: 8px 0 24px;\n`;\n\nconst DescriptionText = styled(Text.Paragraph)`\n  margin-bottom: 24px;\n`;\n\nconst PaginationContainer = styled.div`\n  position: absolute;\n  top: ${470 / 2}px;\n  ${({ alignLeft }) =>\n    alignLeft\n      ? `\n          left: 0;\n          transform: translate(-187.5%, -50%);\n        `\n      : `\n          right: 0;\n          transform: translate(187.5%, -50%);\n        `}\n`;\n\nconst TemplateTag = styled(Chip).attrs({ forwardedAs: 'li' })`\n  margin-right: 12px;\n  margin-bottom: 12px;\n  > span {\n    color: ${({ theme }) => theme.colors.fg.primary} !important;\n  }\n`;\n\nconst MetadataContainer = styled.div`\n  margin-bottom: 24px;\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n`;\n\nfunction DetailsContent({\n  activeTemplateIndex,\n  isRTL,\n  filteredTemplatesLength,\n  switchToTemplateByOffset,\n  template,\n}) {\n  const { postersByPage, title, description, tags, colors } = template || {};\n  const [galleryPosters, setGalleryPosters] = useState([]);\n\n  useEffect(() => {\n    if (postersByPage) {\n      setGalleryPosters(\n        Object.values(postersByPage).map((poster, index) => ({\n          id: index,\n          ...poster,\n        }))\n      );\n    }\n    return undefined;\n  }, [postersByPage]);\n\n  const { NextButton, PrevButton } = useMemo(() => {\n    const nextIndex = isRTL ? activeTemplateIndex - 1 : activeTemplateIndex + 1;\n    const previousIndex = isRTL\n      ? activeTemplateIndex + 1\n      : activeTemplateIndex - 1;\n\n    const disablePrevious = isRTL\n      ? !filteredTemplatesLength ||\n        activeTemplateIndex === filteredTemplatesLength - 1\n      : !filteredTemplatesLength || activeTemplateIndex === 0;\n\n    const disableNext = isRTL\n      ? !filteredTemplatesLength || activeTemplateIndex === 0\n      : !filteredTemplatesLength ||\n        activeTemplateIndex === filteredTemplatesLength - 1;\n\n    const Previous = (\n      <Button\n        type={ButtonType.Tertiary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        aria-label={__('View previous template', 'web-stories')}\n        onClick={() => {\n          switchToTemplateByOffset(previousIndex);\n          setGalleryPosters([]);\n        }}\n        disabled={disablePrevious}\n      >\n        <Icons.ArrowLeftLarge height={32} width={32} />\n      </Button>\n    );\n\n    const Next = (\n      <Button\n        type={ButtonType.Tertiary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        aria-label={__('View next template', 'web-stories')}\n        onClick={() => {\n          switchToTemplateByOffset(nextIndex);\n          setGalleryPosters([]);\n        }}\n        disabled={disableNext}\n      >\n        <Icons.ArrowRightLarge height={32} width={32} />\n      </Button>\n    );\n\n    return isRTL\n      ? {\n          NextButton: Previous,\n          PrevButton: Next,\n        }\n      : {\n          NextButton: Next,\n          PrevButton: Previous,\n        };\n  }, [\n    filteredTemplatesLength,\n    activeTemplateIndex,\n    isRTL,\n    switchToTemplateByOffset,\n  ]);\n\n  const byLine = template\n    ? sprintf(\n        /* translators: byline. %s: author name. */\n        __('By %s', 'web-stories'),\n        template.createdBy\n      )\n    : null;\n\n  return (\n    <StyledPanel>\n      <Container>\n        <PaginationContainer alignLeft>{PrevButton}</PaginationContainer>\n        <Inner>\n          <CardGallery\n            galleryPosters={galleryPosters}\n            isRTL={isRTL}\n            galleryLabel={__('Template details by page', 'web-stories')}\n          />\n          <TemplateDetails>\n            <DetailContainer>\n              <Display\n                size={TextSize.Small}\n                as=\"h3\"\n                data-testid=\"template-details-title\"\n              >\n                {title}\n              </Display>\n              <ByLineText size={TextSize.Medium}>{byLine}</ByLineText>\n              <DescriptionText size={TextSize.Medium}>\n                {description}\n              </DescriptionText>\n\n              <MetadataContainer\n                role=\"list\"\n                aria-label={__('Template tags', 'web-stories')}\n              >\n                {tags.map((tag) => (\n                  <TemplateTag key={tag} disabled>\n                    {tag}\n                  </TemplateTag>\n                ))}\n              </MetadataContainer>\n              <MetadataContainer>\n                <ColorList\n                  colors={colors}\n                  size={32}\n                  aria-label={__('Template colors', 'web-stories')}\n                />\n              </MetadataContainer>\n            </DetailContainer>\n          </TemplateDetails>\n        </Inner>\n        <PaginationContainer>{NextButton}</PaginationContainer>\n      </Container>\n    </StyledPanel>\n  );\n}\n\nDetailsContent.propTypes = {\n  activeTemplateIndex: PropTypes.number,\n  isRTL: PropTypes.bool,\n  filteredTemplatesLength: PropTypes.number,\n  switchToTemplateByOffset: PropTypes.func,\n  template: TemplatePropType,\n};\n\nexport default DetailsContent;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/content/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { formattedTemplatesArray } from '../../../../../../../storybookUtils';\nimport DetailsContent from '..';\n\nexport default {\n  title: 'Dashboard/Views/TemplateDetails/Content/DetailsContent',\n  argTypes: {\n    switchToTemplateByOffset: {\n      action: 'switch to template by offset clicked',\n    },\n  },\n  parameters: {\n    controls: {\n      include: ['switchToTemplateByOffset'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <DetailsContent\n        activeTemplateIndex={8}\n        isRTL={false}\n        filteredTemplatesLength={12}\n        template={formattedTemplatesArray[1]}\n        {...args}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { TemplateActionsPropType } from '../../../../../../propTypes';\n\nconst Nav = styled.nav`\n  justify-content: space-between;\n  align-items: center;\n  display: flex;\n  margin: 48px auto;\n  /* line the close and cta buttons up with navigation arrow*/\n  width: calc(76% + 121px);\n`;\n\nconst CTAButton = styled(Button).attrs({\n  type: ButtonType.Primary,\n  size: ButtonSize.Small,\n})`\n  /* Use Template button should be same height as Close button.*/\n  padding: 10px 16px;\n`;\nfunction Header({\n  templateTitle,\n  templateId,\n  templateActions,\n  canCreateStory,\n}) {\n  const { createStoryFromTemplate, handleDetailsToggle } =\n    templateActions || {};\n  return (\n    <Nav>\n      <Button\n        type={ButtonType.Tertiary}\n        variant={ButtonVariant.Square}\n        size={ButtonSize.Small}\n        aria-label={__('Close', 'web-stories')}\n        onClick={handleDetailsToggle}\n      >\n        <Icons.CrossLarge />\n      </Button>\n      {canCreateStory && (\n        <CTAButton\n          onClick={() => createStoryFromTemplate(templateId)}\n          aria-label={sprintf(\n            /* translators: %s: template title */\n            __('Use %s template to create new story', 'web-stories'),\n            templateTitle\n          )}\n        >\n          {__('Use template', 'web-stories')}\n        </CTAButton>\n      )}\n    </Nav>\n  );\n}\n\nHeader.propTypes = {\n  canCreateStory: PropTypes.bool,\n  templateActions: TemplateActionsPropType,\n  templateId: PropTypes.number,\n  templateTitle: PropTypes.string,\n};\n\nexport default Header;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/header/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Header from '..';\nimport { Layout } from '../../../../../../../components';\n\nexport default {\n  title: 'Dashboard/Views/TemplateDetails/Header',\n  component: Header,\n  argTypes: {\n    createStoryFromTemplate: { action: 'create story from template clicked' },\n    handleDetailsToggle: { action: 'modal was toggled' },\n  },\n};\n\nconst StorybookLayoutContainer = styled.div`\n  margin-top: 40px;\n  height: 100vh;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Layout.Provider>\n        <StorybookLayoutContainer>\n          <Header templateActions={{ ...args }} canCreateStory />\n        </StorybookLayoutContainer>\n      </Layout.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/header/test/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Header from '..';\nimport { renderWithProviders } from '../../../../../../../testUtils';\nimport LayoutProvider from '../../../../../../../components/layout/provider';\n\ndescribe('Template Details <Header />', () => {\n  const mockHandleCtaClick = jest.fn();\n\n  it('should render nav bar for detail template view', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          templateActions={{ createStoryFromTemplate: mockHandleCtaClick }}\n          canCreateStory\n        />\n      </LayoutProvider>\n    );\n    const nav = screen.getByRole('navigation');\n\n    expect(nav).toBeInTheDocument();\n  });\n\n  it('should trigger mockHandleCtaClick when cta is clicked', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          templateActions={{ createStoryFromTemplate: mockHandleCtaClick }}\n          canCreateStory\n        />\n      </LayoutProvider>\n    );\n    const cta = screen.getByText('Use template');\n\n    expect(cta).toBeInTheDocument();\n\n    fireEvent.click(cta);\n\n    expect(mockHandleCtaClick).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/modal/templateDetails/karma/templateDetails.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { within, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Fixture from '../../../../../../karma/fixture';\nimport { TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS } from '../../../../../../constants';\nimport useApi from '../../../../../api/useApi';\n\ndescribe('See template details modal', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n\n    await navigateToFirstTemplate();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function navigateToFirstTemplate() {\n    const navigation = fixture.screen.queryByRole('navigation');\n    let utils = within(navigation);\n\n    const exploreTemplatesMenuItem = utils.getByText(/^Explore Templates/);\n\n    await fixture.events.click(exploreTemplatesMenuItem);\n\n    const { templatesOrderById } = await getTemplatesState();\n\n    const firstTemplate = getTemplateElementById(templatesOrderById[0]);\n\n    utils = within(firstTemplate);\n\n    await fixture.events.hover(firstTemplate);\n\n    const seeDetailsButton = utils.getByText(\n      new RegExp(`^${TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS.template}$`)\n    );\n\n    await fixture.events.click(seeDetailsButton);\n  }\n\n  function getTemplateElementById(id) {\n    return fixture.screen.getByTestId(`template-grid-item-${id}`);\n  }\n\n  async function focusOnCardGallery() {\n    let limit = 0;\n    const cardGallery = fixture.screen.getByTestId('mini-cards-container');\n\n    while (!cardGallery.contains(document.activeElement) && limit < 5) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('tab');\n      limit++;\n    }\n\n    return cardGallery.contains(document.activeElement)\n      ? Promise.resolve()\n      : Promise.reject(new Error('could not focus on page list'));\n  }\n\n  async function getTemplatesState() {\n    const {\n      state: { templates },\n    } = await fixture.renderHook(() => useApi());\n    return templates;\n  }\n\n  async function getTemplateTitle(index) {\n    const { templates, templatesOrderById } = await getTemplatesState();\n    return templates[templatesOrderById[index]].title;\n  }\n\n  async function expectModalClose() {\n    const { templatesOrderById } = await getTemplatesState();\n    const firstTemplate = getTemplateElementById(templatesOrderById[0]);\n    const utils = within(firstTemplate);\n\n    const seeDetailsButton = await utils.findByText(\n      new RegExp(`^${TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS.template}$`)\n    );\n    await expect(seeDetailsButton).toEqual(document.activeElement);\n  }\n\n  describe('Action: Navigate template details modal', () => {\n    it('should pass accessibility tests', async () => {\n      const templateDetails = fixture.screen.queryByRole('dialog');\n      expect(templateDetails).toBeTruthy();\n      await expectAsync(templateDetails).toHaveNoViolations();\n    });\n\n    it('should update current template', async () => {\n      const firstTemplateTitle = await getTemplateTitle(0);\n      const templateTitle = fixture.screen.getByTestId(\n        `template-details-title`\n      );\n\n      await expect(templateTitle).toHaveTextContent(firstTemplateTitle);\n\n      const previousArrow = fixture.screen.getByRole('button', {\n        name: /View previous template/,\n      });\n      const nextArrow = fixture.screen.getByRole('button', {\n        name: /View next template/,\n      });\n\n      await nextArrow.click();\n      await expect(templateTitle).toHaveTextContent(await getTemplateTitle(1));\n      await expect(templateTitle).not.toHaveTextContent(firstTemplateTitle);\n\n      await previousArrow.click();\n      await expect(templateTitle).toHaveTextContent(firstTemplateTitle);\n      await expect(templateTitle).not.toHaveTextContent(\n        await getTemplateTitle(1)\n      );\n    });\n\n    it('should update url param for template id', async () => {\n      const { templatesOrderById } = await getTemplatesState();\n\n      const firstTemplateId = templatesOrderById[0];\n      // Parse the current template id from the id query param\n      let urlHashParams = window.location.hash;\n      expect(urlHashParams).toBe(\n        `#/templates-gallery?id=${firstTemplateId}&isLocal=false`\n      );\n\n      // Click the view next button to cycle to the next template\n      const viewNextBtn = fixture.screen.getByRole('button', {\n        name: /View next template/,\n      });\n      await fixture.events.click(viewNextBtn);\n\n      const nextTemplateId = templatesOrderById[1];\n      // Re-parse the current template id from the id query param and assert it's different\n      urlHashParams = window.location.hash;\n      await expect(urlHashParams).toBe(\n        `#/templates-gallery?id=${nextTemplateId}&isLocal=false`\n      );\n    });\n\n    it('should update current template via keyboard', async () => {\n      //close button should be in focus\n      await fixture.events.keyboard.press('tab');\n      const closeBtn = fixture.screen.getByRole('button', {\n        name: /^Close$/,\n      });\n      expect(closeBtn).toEqual(document.activeElement);\n\n      // enter should close modal\n      await waitFor(async () => {\n        await fixture.events.keyboard.press('Enter');\n        // let modal close\n        await fixture.events.sleep(500);\n        await expectModalClose();\n      });\n\n      // open first template in modal\n      await fixture.events.keyboard.press('Enter');\n\n      // escape should close modal\n      await waitFor(async () => {\n        await fixture.events.keyboard.press('Escape');\n        // let modal close\n        await fixture.events.sleep(500);\n        await expectModalClose();\n      });\n\n      // open first template in modal\n      await fixture.events.keyboard.press('Enter');\n      // navigate to 'Use Template' button\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('tab');\n      const useTemplateBtn = fixture.screen.getByRole('button', {\n        name: /to create new story/,\n      });\n      expect(useTemplateBtn).toEqual(document.activeElement);\n\n      // navigate to gallery thumbnail\n      await fixture.events.keyboard.press('tab');\n      const page1 = fixture.screen.getByRole('button', { name: /Page 1/ });\n      expect(page1).toEqual(document.activeElement);\n\n      // Check current template\n      const firstTemplateTitle = await getTemplateTitle(0);\n      await expect(\n        fixture.screen.getByTestId(`template-details-title`)\n      ).toHaveTextContent(firstTemplateTitle);\n\n      //navigate to next template arrow\n      await fixture.events.keyboard.press('tab');\n      const nextArrow = fixture.screen.getByRole('button', {\n        name: /View next template/,\n      });\n      expect(nextArrow).toEqual(document.activeElement);\n\n      // navigate to next template\n      await fixture.events.keyboard.press('Enter');\n      await expect(\n        fixture.screen.getByTestId(`template-details-title`)\n      ).not.toHaveTextContent(firstTemplateTitle);\n      await expect(\n        fixture.screen.getByTestId(`template-details-title`)\n      ).toHaveTextContent(await getTemplateTitle(1));\n\n      //navigate back to previous template\n      await fixture.events.keyboard.shortcut('shift+tab');\n      await fixture.events.keyboard.shortcut('shift+tab');\n      const previousArrow = fixture.screen.getByRole('button', {\n        name: /View previous template/,\n      });\n      expect(previousArrow).toEqual(document.activeElement);\n      await fixture.events.keyboard.press('Enter');\n      await expect(\n        fixture.screen.getByTestId(`template-details-title`)\n      ).toHaveTextContent(firstTemplateTitle);\n      await expect(\n        fixture.screen.getByTestId(`template-details-title`)\n      ).not.toHaveTextContent(await getTemplateTitle(1));\n    });\n  });\n\n  describe('Action: See template details modal', () => {\n    it('should update the \"Active Preview Page\" when clicking on a \"Thumbnail Preview Page\"', async () => {\n      const firstPage = fixture.screen.getByRole('button', { name: /Page 1/ });\n\n      expect(firstPage).toBeTruthy();\n\n      const activePage = fixture.screen.getByRole('img', {\n        name: 'Active Page Preview - Page 1',\n      });\n\n      expect(activePage).toBeTruthy();\n\n      const secondPage = fixture.screen.getByRole('button', { name: /Page 2/ });\n\n      expect(secondPage).toBeTruthy();\n\n      await fixture.events.click(secondPage);\n\n      fixture.screen.getByRole('img', {\n        name: 'Active Page Preview - Page 2',\n      });\n\n      expect(activePage).toBeTruthy();\n    });\n\n    it('should update the \"Active Preview Page\" when using keyboard to navigate gallery', async () => {\n      await focusOnCardGallery();\n      const page1 = fixture.screen.getByRole('button', { name: /Page 1/ });\n      expect(page1).toEqual(document.activeElement);\n\n      // go right by 1\n      await fixture.events.keyboard.press('right');\n      const page2 = fixture.screen.getByRole('button', { name: /Page 2/ });\n      expect(page2).toEqual(document.activeElement);\n\n      // go left 1\n      await fixture.events.keyboard.press('left');\n      expect(page1).toEqual(document.activeElement);\n\n      // go left 1 (focus should remain on page 1)\n      await fixture.events.keyboard.press('left');\n      expect(page1).toEqual(document.activeElement);\n\n      const page4 = fixture.screen.getByRole('button', { name: /Page 4/ });\n      await fixture.events.keyboard.seq(({ press }) => [\n        press('right'),\n        press('right'),\n        press('right'),\n      ]);\n\n      expect(page4).toEqual(document.activeElement);\n\n      await fixture.events.keyboard.press('Enter');\n\n      const activePreviewPage = fixture.screen.getByRole('img', {\n        name: 'Active Page Preview - Page 4',\n      });\n\n      expect(activePreviewPage).toBeTruthy();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/templateFilters.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport {\n  TEMPLATE_CATEGORY_ITEMS,\n  TEMPLATE_COLOR_ITEMS,\n} from '../../../constants';\n\nexport function updateSelectedItems(items, setter) {\n  return (sender) => {\n    const newSelectedItems = items.map((item) => {\n      if (item.value === sender) {\n        return { ...item, selected: !item.selected };\n      }\n      return item;\n    });\n\n    setter(newSelectedItems);\n  };\n}\n\nexport function clearAllSelectedItems(items, setter) {\n  return () => {\n    const newSelectedItems = items.map((item) => {\n      return { ...item, selected: false };\n    });\n\n    setter(newSelectedItems);\n  };\n}\n\nexport default function useTemplateFilters() {\n  const [selectedCategories, setSelectedCategories] = useState(\n    TEMPLATE_CATEGORY_ITEMS\n  );\n\n  const [selectedColors, setSelectedColors] = useState(TEMPLATE_COLOR_ITEMS);\n\n  return useMemo(\n    () => ({\n      selectedCategories,\n      selectedColors,\n      onNewCategorySelected: updateSelectedItems(\n        selectedCategories,\n        setSelectedCategories\n      ),\n      onNewColorSelected: updateSelectedItems(\n        selectedColors,\n        setSelectedColors\n      ),\n      clearAllCategories: clearAllSelectedItems(\n        selectedCategories,\n        setSelectedCategories\n      ),\n      clearAllColors: clearAllSelectedItems(selectedColors, setSelectedColors),\n    }),\n    [selectedColors, selectedCategories]\n  );\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/views/exploreTemplates/test/templateFilters.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useTemplateFilters from '../templateFilters';\nimport { TEMPLATE_CATEGORIES, TEMPLATE_COLORS } from '../../../../constants';\n\ndescribe('templateFilters', () => {\n  it('should select a color when the value is passed to the color selected method', () => {\n    const { result } = renderHook(() => useTemplateFilters());\n\n    act(() => {\n      result.current.onNewColorSelected(TEMPLATE_COLORS.YELLOW);\n    });\n\n    const yellow = result.current.selectedColors.find(\n      (color) => color.value === TEMPLATE_COLORS.YELLOW\n    );\n\n    expect(yellow.selected).toBeTrue();\n  });\n\n  it('should select a category when the value is passed to the category selected method', () => {\n    const { result } = renderHook(() => useTemplateFilters());\n\n    act(() => {\n      result.current.onNewCategorySelected(TEMPLATE_CATEGORIES.SPORTS);\n    });\n\n    const sports = result.current.selectedCategories.find(\n      (category) => category.value === TEMPLATE_CATEGORIES.SPORTS\n    );\n\n    expect(sports.selected).toBeTrue();\n  });\n\n  it('should clear the category selection when the clear method is called', () => {\n    const { result } = renderHook(() => useTemplateFilters());\n\n    act(() => {\n      result.current.onNewCategorySelected(TEMPLATE_CATEGORIES.SPORTS);\n    });\n\n    expect(\n      result.current.selectedCategories.find(\n        (category) => category.value === TEMPLATE_CATEGORIES.SPORTS\n      ).selected\n    ).toBeTrue();\n\n    act(() => {\n      result.current.clearAllCategories();\n    });\n\n    expect(\n      result.current.selectedCategories.find(\n        (category) => category.value === TEMPLATE_CATEGORIES.SPORTS\n      ).selected\n    ).toBeFalse();\n  });\n\n  it('should clear the color selection when the clear method is called', () => {\n    const { result } = renderHook(() => useTemplateFilters());\n\n    act(() => {\n      result.current.onNewColorSelected(TEMPLATE_COLORS.BLUE);\n    });\n\n    expect(\n      result.current.selectedColors.find(\n        (color) => color.value === TEMPLATE_COLORS.BLUE\n      ).selected\n    ).toBeTrue();\n\n    act(() => {\n      result.current.clearAllColors();\n    });\n\n    expect(\n      result.current.selectedColors.find(\n        (color) => color.value === TEMPLATE_COLORS.BLUE\n      ).selected\n    ).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/filters/reducer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { STORY_SORT_KEYS } from '../../../constants/stories';\nimport { TEMPLATE_SORT_KEYS } from '../../../constants/templates';\nimport * as types from './types';\n\n/**\n * @typedef {Object} Payload\n * @property {string} key Key for associated filter.\n * @property {Object} value Value to set on the filter.\n */\n\n/**\n * Update the filters state\n *\n * TODO: May need updating to handle all filter types within the dashboard.\n *\n * @param {Object} state Current state\n * @param {Object} args Arguments\n * @param {Object} args.type type Action type.\n * @param {Payload} args.payload Action payload\n * @return {Object} New state\n */\nconst reducer = (state, { type, payload = {} }) => {\n  switch (type) {\n    case types.UPDATE_FILTER: {\n      const ALLOW_SAME_FILTERID = ['search', 'status'];\n      const { key, value } = payload;\n      const _filter = state.filters.find((filter) => filter.key === key);\n\n      if (!_filter) {\n        return state;\n      }\n\n      // remove 'filter-by' value\n      if (value.filterId && _filter?.filterId === value.filterId) {\n        if (ALLOW_SAME_FILTERID.includes(key)) {\n          return state;\n        }\n        value.filterId = null;\n      }\n\n      // replace old filter\n      const idx = state.filters.indexOf(_filter);\n      const filters = [...state.filters];\n      filters[idx] = { ..._filter, ...value };\n\n      // update filtersObject\n      const filtersObject = {};\n      for (const filter of filters) {\n        if (filter.filterId) {\n          filtersObject[filter.key] = filter.filterId;\n        }\n      }\n\n      return {\n        ...state,\n        filters,\n        filtersObject,\n      };\n    }\n\n    case types.UPDATE_SORT: {\n      const { type: sortType, values } = payload;\n\n      const sortObject = {};\n\n      const ACCEPTABLE_KEYS =\n        sortType === 'story' ? STORY_SORT_KEYS : TEMPLATE_SORT_KEYS;\n\n      // only use acceptable key value pairs\n      for (const key in values) {\n        if (\n          key in ACCEPTABLE_KEYS &&\n          Object.values(ACCEPTABLE_KEYS[key]).includes(values[key]) &&\n          state.sortObject[key] !== values[key]\n        ) {\n          sortObject[key] = values[key];\n        }\n      }\n\n      // nothing changed no need for an update\n      if (Object.entries(sortObject).length === 0) {\n        return state;\n      }\n\n      return {\n        ...state,\n        sortObject: { ...state.sortObject, ...sortObject },\n      };\n    }\n\n    case types.REGISTER_FILTERS: {\n      const { value } = payload;\n      const currentFilters = state.filters.map((filter) => filter.key);\n      const newFilters = value.filter(\n        (filter) => !currentFilters.includes(filter.key)\n      );\n      if (!newFilters.length) {\n        return state;\n      }\n      return {\n        ...state,\n        filters: [...newFilters, ...state.filters],\n      };\n    }\n    default:\n      return state;\n  }\n};\n\nexport default reducer;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/filters/test/reducer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport reducer from '../reducer';\nimport * as types from '../types';\nimport { TEMPLATES_GALLERY_SORT_OPTIONS } from '../../../../constants/templates';\n\ndescribe('reducer', () => {\n  it('should update the state', () => {\n    const initial_state = {\n      filters: [\n        {\n          key: 'officers',\n          filterId: 117,\n          name: 'John',\n        },\n      ],\n    };\n\n    const args = {\n      type: types.UPDATE_FILTER,\n      payload: {\n        key: 'officers',\n        value: { filterId: 112 },\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    const filter = state.filters.find((f) => f.key === 'officers');\n    expect(filter.filterId).toBe(112);\n  });\n\n  it('should update set the filterId to null if the same filterId is given', () => {\n    const initial_state = {\n      filters: [\n        {\n          key: 'officers',\n          filterId: 117,\n          name: 'John',\n        },\n      ],\n    };\n\n    const args = {\n      type: types.UPDATE_FILTER,\n      payload: {\n        key: 'officers',\n        value: { filterId: 117 },\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    const filter = state.filters.find((f) => f.key === 'officers');\n    expect(filter.filterId).toBeNull();\n  });\n\n  it('should not reset the filterId for \"search\" if the same filterId is given', () => {\n    const initial_state = {\n      filters: [{ key: 'search', filterId: 'John' }],\n    };\n    // search\n    const args = {\n      type: types.UPDATE_FILTER,\n      payload: {\n        key: 'search',\n        value: 'John',\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    const filter = state.filters.find((f) => f.key === 'search');\n    expect(filter.filterId).toBe('John');\n  });\n\n  it('should not reset the filterId for \"status\" if the same filterId is given', () => {\n    const initial_state = {\n      filters: [{ key: 'status', filterId: 'New' }],\n    };\n    const args = {\n      type: types.UPDATE_FILTER,\n      payload: {\n        key: 'status',\n        value: 'New',\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    const filter = state.filters.find((f) => f.key === 'status');\n    expect(filter.filterId).toBe('New');\n  });\n\n  it('should register filters in state', () => {\n    const initial_state = {\n      filters: [],\n    };\n\n    const args = {\n      type: types.REGISTER_FILTERS,\n      payload: {\n        value: [\n          {\n            key: 'officers',\n            filterId: null,\n          },\n          {\n            key: 'teams',\n            filterId: null,\n          },\n        ],\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    expect(state.filters).toHaveLength(2);\n  });\n\n  it('should return the state if dispatching an action thats not supported', () => {\n    const initial_state = {\n      filters: [\n        {\n          key: 'teams',\n          filterId: 6,\n          name: 'Noble',\n        },\n      ],\n    };\n\n    const args = {\n      type: 'RENAME_TEAM',\n      payload: {\n        key: 'teams',\n        name: 'Banished',\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    const filter = state.filters.find((f) => f.key === 'teams');\n    expect(filter).toMatchObject({\n      filterId: 6,\n      name: 'Noble',\n    });\n  });\n\n  it('should return the state if no filter is found with the key', () => {\n    const initial_state = {\n      filters: [\n        {\n          key: 'teams',\n          filterId: 6,\n          name: 'Noble',\n        },\n      ],\n    };\n\n    const args = {\n      type: 'UPDATE_FILTER',\n      payload: {\n        key: 'officers',\n        name: 'Banished',\n      },\n    };\n\n    const state = reducer(initial_state, args);\n    expect(state).toMatchObject(initial_state);\n  });\n\n  it('should update sort based on \"type\" and acceptable keys', () => {\n    const initial_state = {\n      sortObject: {},\n    };\n\n    let args = {\n      type: 'UPDATE_SORT',\n      payload: {\n        type: 'template',\n        values: { orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR },\n      },\n    };\n\n    let state = reducer(initial_state, args);\n    expect(state.sortObject).toMatchObject({\n      orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n    });\n\n    args = {\n      type: 'UPDATE_SORT',\n      payload: { type: 'template', values: { orderby: 'non-popular' } },\n    };\n\n    state = reducer(state, args);\n    // state shouldn't change because 'non-popular' is not an acceptable value\n    // for 'template' sort 'orderby'\n    expect(state.sortObject).toMatchObject({\n      orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/filters/types.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const UPDATE_FILTER = 'UPDATE_FILTER';\nexport const UPDATE_SORT = 'UPDATE_SORT';\nexport const REGISTER_FILTERS = 'REGISTER_FILTERS';\n"
  },
  {
    "path": "packages/dashboard/src/app/views/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as MyStoriesView } from './myStories';\nexport { default as ExploreTemplatesView } from './exploreTemplates';\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  ButtonSize,\n  ButtonType,\n  Headline,\n  TextSize,\n  InfiniteScroller,\n  ButtonAsLink,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { resolveRoute } from '../../../router';\nimport { APP_ROUTES } from '../../../../constants';\nimport { Layout, StandardViewContentGutter } from '../../../../components';\nimport { StoriesPropType, StoryActionsPropType } from '../../../../propTypes';\nimport {\n  ViewPropTypes,\n  PagePropTypes,\n  ShowStoriesWhileLoadingPropType,\n} from '../../../../utils/useStoryView';\nimport { EmptyContentMessage } from '../../shared';\nimport StoriesView from './storiesView';\n\nfunction NoAvailableContent({ filtersObject }) {\n  const { search } = filtersObject;\n  if (search) {\n    return sprintf(\n      /* translators: %s: search term. */\n      __('Sorry, we couldn\\'t find any results matching \"%s\"', 'web-stories'),\n      search\n    );\n  } else if (Object.keys(filtersObject).length !== 0) {\n    return __(\"Sorry, we couldn't find any results\", 'web-stories');\n  } else {\n    return __('Start telling Stories.', 'web-stories');\n  }\n}\nNoAvailableContent.propTypes = {\n  filtersObject: PropTypes.object,\n};\n\nfunction Content({\n  allPagesFetched,\n  canViewDefaultTemplates,\n  filtersObject = {},\n  loading,\n  page,\n  stories,\n  storyActions,\n  view,\n}) {\n  return (\n    <Layout.Scrollable>\n      <StandardViewContentGutter>\n        {stories.length > 0 ? (\n          <>\n            <StoriesView\n              storyActions={storyActions}\n              stories={stories}\n              view={view}\n              loading={loading}\n            />\n            <InfiniteScroller\n              canLoadMore={!allPagesFetched}\n              isLoading={loading?.isLoading}\n              allDataLoadedMessage={__('No more stories', 'web-stories')}\n              allDataLoadedAriaMessage={__(\n                'All stories are loaded',\n                'web-stories'\n              )}\n              loadingAriaMessage={__('Loading more stories', 'web-stories')}\n              onLoadMore={page.requestNextPage}\n            />\n          </>\n        ) : (\n          !loading?.isLoading && (\n            <EmptyContentMessage>\n              <Headline size={TextSize.Small} as=\"h3\">\n                <NoAvailableContent filtersObject={filtersObject} />\n              </Headline>\n              {Object.keys(filtersObject).length === 0 &&\n                canViewDefaultTemplates && (\n                  <ButtonAsLink\n                    type={ButtonType.Primary}\n                    size={ButtonSize.Medium}\n                    href={resolveRoute(APP_ROUTES.TEMPLATES_GALLERY)}\n                  >\n                    {__('Explore Templates', 'web-stories')}\n                  </ButtonAsLink>\n                )}\n            </EmptyContentMessage>\n          )\n        )}\n      </StandardViewContentGutter>\n    </Layout.Scrollable>\n  );\n}\nContent.propTypes = {\n  allPagesFetched: PropTypes.bool,\n  canViewDefaultTemplates: PropTypes.bool,\n  filtersObject: PropTypes.object,\n  loading: PropTypes.shape({\n    isLoading: PropTypes.bool,\n    showStoriesWhileLoading: ShowStoriesWhileLoadingPropType,\n  }),\n  page: PagePropTypes,\n  stories: StoriesPropType,\n  storyActions: StoryActionsPropType,\n  view: ViewPropTypes,\n};\n\nexport default Content;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/listView/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { Text, themeHelpers } from '@googleforcreators/design-system';\n\nconst { focusableOutlineCSS } = themeHelpers;\n\nexport const ListView = styled.div`\n  width: 100%;\n`;\n\nexport const ArrowIcon = styled.div`\n  width: 32px;\n  height: 100%;\n  display: inline-grid;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  vertical-align: middle;\n\n  svg {\n    visibility: ${({ active }) => (active ? 'visible' : 'hidden')};\n    transition: transform 0.15s;\n\n    ${({ asc }) =>\n      asc &&\n      css`\n        transform: rotate(180deg);\n      `};\n  }\n`;\n\nexport const EmptyIconSpace = styled.div`\n  height: 32px;\n  width: 32px;\n`;\n\nexport const ArrowIconWithTitle = styled(ArrowIcon)`\n  ${({ active }) => !active && 'display: none;'}\n  position: absolute;\n  top: 16px;\n\n  @media ${({ theme }) => theme.breakpoint.mobile} {\n    margin-left: 4px;\n  }\n`;\n\nexport const SelectableTitle = styled(Text.Span).attrs({\n  tabIndex: 0,\n  isBold: true,\n})`\n  color: ${({ theme }) => theme.colors.blue[70]};\n  cursor: pointer;\n\n  ${({ theme }) =>\n    focusableOutlineCSS(theme.colors.border.focus, theme.colors.bg.secondary)};\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/listView/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons, Text, TextSize } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport {\n  StoriesPropType,\n  RenameStoryPropType,\n  StoryMenuPropType,\n} from '../../../../../propTypes';\nimport {\n  Table,\n  TableAuthorHeaderCell,\n  TableBody,\n  TableDateHeaderCell,\n  StickyTableHeader,\n  TablePreviewHeaderCell,\n  TableRow,\n  TableStatusHeaderCell,\n  TableTitleHeaderCell,\n} from '../../../../../components';\nimport {\n  ORDER_BY_SORT,\n  SORT_DIRECTION,\n  STORY_SORT_OPTIONS,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport { useConfig } from '../../../../config';\nimport useStoryFilters from '../../filters/useStoryFilters';\nimport { StoryListItem } from '../storyListItem';\nimport {\n  ArrowIcon,\n  ArrowIconWithTitle,\n  EmptyIconSpace,\n  ListView,\n  SelectableTitle,\n} from './components';\n\nconst toggleSortLookup = {\n  [SORT_DIRECTION.DESC]: SORT_DIRECTION.ASC,\n  [SORT_DIRECTION.ASC]: SORT_DIRECTION.DESC,\n};\n\nexport default function StoryListView({\n  hideStoryList,\n  renameStory,\n  stories,\n  storyMenu,\n}) {\n  const {\n    userId,\n    styleConstants: { topOffset },\n  } = useConfig();\n\n  const { filters, sortObject, updateSort } = useStoryFilters(\n    ({ state: { filters, sortObject }, actions: { updateSort } }) => ({\n      filters,\n      sortObject,\n      updateSort,\n    })\n  );\n\n  const [storySort, sortDirection] = useMemo(() => {\n    return [sortObject?.orderby, sortObject?.order];\n  }, [sortObject]);\n\n  const statusFilterValue = useMemo(() => {\n    const statusFilter = filters.filter(({ key }) => key === 'status');\n    return statusFilter.filterId;\n  }, [filters]);\n\n  const onSortTitleSelected = useCallback(\n    (orderby) => {\n      if (orderby !== storySort) {\n        updateSort({ orderby, order: ORDER_BY_SORT[orderby] });\n      } else {\n        updateSort({ order: toggleSortLookup[sortDirection] });\n      }\n    },\n    [updateSort, storySort, sortDirection]\n  );\n\n  const onKeyDownSort = useCallback(\n    ({ key }, sortBy) => {\n      if (key === 'Enter') {\n        onSortTitleSelected(sortBy);\n      }\n    },\n    [onSortTitleSelected]\n  );\n\n  const tableContents = useMemo(() => {\n    return (\n      !hideStoryList &&\n      stories.map((story) => (\n        <StoryListItem\n          key={`story-${story.id}`}\n          story={story}\n          userId={userId}\n          renameStory={renameStory}\n          storyStatus={statusFilterValue}\n          storyMenu={storyMenu}\n        />\n      ))\n    );\n  }, [\n    hideStoryList,\n    renameStory,\n    stories,\n    statusFilterValue,\n    storyMenu,\n    userId,\n  ]);\n\n  return (\n    <ListView data-testid=\"story-list-view\">\n      <Table aria-label={__('List view of created stories', 'web-stories')}>\n        <StickyTableHeader topOffset={topOffset}>\n          <TableRow>\n            <TablePreviewHeaderCell\n              onClick={() => onSortTitleSelected(STORY_SORT_OPTIONS.NAME)}\n              onKeyDown={(e) => onKeyDownSort(e, STORY_SORT_OPTIONS.NAME)}\n            >\n              <SelectableTitle\n                aria-label={__(\n                  'Title, select to sort table by story title',\n                  'web-stories'\n                )}\n                size={TextSize.Small}\n                isBold\n              >\n                {__('Title', 'web-stories')}\n              </SelectableTitle>\n            </TablePreviewHeaderCell>\n            <TableTitleHeaderCell\n              onClick={() => onSortTitleSelected(STORY_SORT_OPTIONS.NAME)}\n              onKeyDown={(e) => onKeyDownSort(e, STORY_SORT_OPTIONS.NAME)}\n            >\n              <SelectableTitle\n                aria-hidden\n                active={storySort === STORY_SORT_OPTIONS.NAME}\n                size={TextSize.Small}\n                isBold\n              >\n                {__('Title', 'web-stories')}\n              </SelectableTitle>\n              <ArrowIcon\n                active={storySort === STORY_SORT_OPTIONS.NAME}\n                asc={sortDirection === SORT_DIRECTION.ASC}\n              >\n                {<Icons.ArrowDown />}\n              </ArrowIcon>\n            </TableTitleHeaderCell>\n            <TableAuthorHeaderCell>\n              <SelectableTitle\n                aria-label={__(\n                  'Author, select to sort table by story author',\n                  'web-stories'\n                )}\n                onClick={() =>\n                  onSortTitleSelected(STORY_SORT_OPTIONS.CREATED_BY)\n                }\n                onKeyDown={(e) =>\n                  onKeyDownSort(e, STORY_SORT_OPTIONS.CREATED_BY)\n                }\n                active={storySort === STORY_SORT_OPTIONS.CREATED_BY}\n                size={TextSize.Small}\n                isBold\n              >\n                {__('Author', 'web-stories')}\n              </SelectableTitle>\n              <ArrowIconWithTitle\n                aria-hidden\n                active={storySort === STORY_SORT_OPTIONS.CREATED_BY}\n                asc={sortDirection === SORT_DIRECTION.ASC}\n              >\n                {storySort === STORY_SORT_OPTIONS.CREATED_BY ? (\n                  <Icons.ArrowDown />\n                ) : (\n                  <EmptyIconSpace />\n                )}\n              </ArrowIconWithTitle>\n            </TableAuthorHeaderCell>\n            <TableDateHeaderCell>\n              <SelectableTitle\n                aria-label={__(\n                  'Creation date, select to sort table by date story was created',\n                  'web-stories'\n                )}\n                onClick={() =>\n                  onSortTitleSelected(STORY_SORT_OPTIONS.DATE_CREATED)\n                }\n                onKeyDown={(e) =>\n                  onKeyDownSort(e, STORY_SORT_OPTIONS.DATE_CREATED)\n                }\n                active={storySort === STORY_SORT_OPTIONS.DATE_CREATED}\n                size={TextSize.Small}\n                isBold\n              >\n                {__('Date Created', 'web-stories')}\n              </SelectableTitle>\n              <ArrowIconWithTitle\n                aria-hidden\n                active={storySort === STORY_SORT_OPTIONS.DATE_CREATED}\n                asc={sortDirection === SORT_DIRECTION.ASC}\n              >\n                <Icons.ArrowDown />\n              </ArrowIconWithTitle>\n            </TableDateHeaderCell>\n            <TableDateHeaderCell>\n              <SelectableTitle\n                aria-label={__(\n                  'Modification date, select to sort table by date story was last modified',\n                  'web-stories'\n                )}\n                onClick={() =>\n                  onSortTitleSelected(STORY_SORT_OPTIONS.LAST_MODIFIED)\n                }\n                onKeyDown={(e) =>\n                  onKeyDownSort(e, STORY_SORT_OPTIONS.LAST_MODIFIED)\n                }\n                active={storySort === STORY_SORT_OPTIONS.LAST_MODIFIED}\n                size={TextSize.Small}\n                isBold\n              >\n                {__('Last Modified', 'web-stories')}\n              </SelectableTitle>\n              <ArrowIconWithTitle\n                aria-hidden\n                active={storySort === STORY_SORT_OPTIONS.LAST_MODIFIED}\n                asc={sortDirection === SORT_DIRECTION.ASC}\n              >\n                <Icons.ArrowDown />\n              </ArrowIconWithTitle>\n            </TableDateHeaderCell>\n            {statusFilterValue !== STORY_STATUS.DRAFT && (\n              <TableStatusHeaderCell>\n                <Text.Span isBold size={TextSize.Small}>\n                  {__('Publish State', 'web-stories')}\n                </Text.Span>\n              </TableStatusHeaderCell>\n            )}\n          </TableRow>\n        </StickyTableHeader>\n        <TableBody>{tableContents}</TableBody>\n      </Table>\n    </ListView>\n  );\n}\n\nStoryListView.propTypes = {\n  hideStoryList: PropTypes.bool,\n  renameStory: RenameStoryPropType,\n  storyMenu: StoryMenuPropType.isRequired,\n  stories: StoriesPropType,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { SnackbarProvider } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { Layout } from '../../../../../components';\nimport {\n  STORY_SORT_OPTIONS,\n  SORT_DIRECTION,\n  VIEW_STYLE,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport { formattedStoriesArray } from '../../../../../storybookUtils';\nimport { usePagePreviewSize } from '../../../../../utils';\nimport Content from '..';\n\n// Prevents storybook from shouting a bunch of console warnings about duplicate ids\nfunction forceUniqueIds(stories) {\n  return stories.map((story, index) => {\n    const id = Math.floor(Math.random() * 500 * index);\n    return { ...story, id };\n  });\n}\nconst longerListOfStories = forceUniqueIds(\n  formattedStoriesArray\n    .concat(formattedStoriesArray)\n    .concat(formattedStoriesArray)\n);\n\nexport default {\n  title: 'Dashboard/Views/MyStories/Content',\n  component: Content,\n  args: {\n    filterStatus: 'all',\n    statusValue: STORY_STATUS.ALL,\n    sortValue: STORY_SORT_OPTIONS.NAME,\n    direction: SORT_DIRECTION.ASC,\n    keyword: '',\n    style: VIEW_STYLE.GRID,\n    stories: longerListOfStories,\n    allPagesFetched: false,\n    thumbnailMode: false,\n    isGrid: true,\n    isLoading: false,\n    canViewDefaultTemplates: true,\n  },\n  argTypes: {\n    setFilter: { action: 'set filter' },\n    setSort: { action: 'set sort' },\n    setDirection: { action: 'set sort direction' },\n    setKeyword: { action: 'set search' },\n    toggleStyle: { action: 'toggle view style' },\n    statusValue: { options: STORY_STATUS, control: 'select' },\n    sortValue: {\n      options: STORY_SORT_OPTIONS,\n      control: 'radio',\n      name: 'Story sort options',\n    },\n    direction: { options: SORT_DIRECTION, control: 'radio' },\n    style: { options: VIEW_STYLE, control: 'radio' },\n    setPage: { action: 'set page number' },\n    requestNextPage: { action: 'request next page clicked' },\n    duplicateStory: { action: 'duplicate story clicked' },\n    trashStory: { action: 'trash story clicked' },\n    updateStory: { action: 'update story clicked' },\n  },\n  parameters: {\n    controls: {\n      include: [\n        'style',\n        'requestNextPage',\n        'duplicateStory',\n        'updateStory',\n        'trashStory',\n        'isGrid',\n        'isThumbnailMode',\n        'isLoading',\n        'Story sort options',\n        'direction',\n        'allPagesFetched',\n        'statusValue',\n        'canViewDefaultTemplates',\n      ],\n    },\n  },\n};\n\nconst StorybookLayoutContainer = styled.div`\n  margin-top: 40px;\n  height: 100vh;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const { pageSize } = usePagePreviewSize({\n      isGrid: args.isGrid,\n      thumbnailMode: args.thumbnailMode,\n    });\n    const filter = {\n      status: args.filterStatus,\n      value: args.statusValue,\n      set: args.setFilter,\n    };\n    const sort = {\n      value: args.sortValue,\n      direction: args.direction,\n      set: args.setSort,\n      setDirection: args.setDirection,\n    };\n    const search = {\n      keyword: args.keyword,\n      setKeyword: args.setKeyword,\n    };\n    const view = {\n      style: args.style,\n      toggleStyle: args.toggleStyle,\n      pageSize,\n    };\n    const page = {\n      value: 1,\n      set: args.setPage,\n      requestNextPage: args.requestNextPage,\n    };\n    const storyActions = {\n      duplicateStory: args.duplicateStory,\n      trashStory: args.trashStory,\n      updateStory: args.updateStory,\n    };\n\n    const defaultProps = {\n      allPagesFetched: args.allPagesFetched,\n      filter: filter,\n      isLoading: args.isLoading,\n      page: page,\n      search: search,\n      sort: sort,\n      stories: args.stories,\n      storyActions: storyActions,\n      view: view,\n    };\n    return (\n      <SnackbarProvider>\n        <Layout.Provider>\n          <StorybookLayoutContainer>\n            <Content {...args} {...defaultProps} />\n          </StorybookLayoutContainer>\n        </Layout.Provider>\n      </SnackbarProvider>\n    );\n  },\n};\n\nexport const NoStories = {\n  render: _default,\n\n  args: {\n    stories: [],\n  },\n};\n\nexport const NoSearchResult = {\n  render: _default,\n\n  args: {\n    stories: [],\n    keyword: 'koalas',\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storiesView/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useState,\n  useCallback,\n  useMemo,\n  useEffect,\n} from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  LoadingSpinner,\n  useSnackbar,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  StoriesPropType,\n  StoryActionsPropType,\n} from '../../../../../propTypes';\nimport { titleFormatted } from '../../../../../utils';\nimport {\n  ViewPropTypes,\n  ShowStoriesWhileLoadingPropType,\n} from '../../../../../utils/useStoryView';\nimport { Dialog, LoadingContainer } from '../../../../../components';\nimport {\n  VIEW_STYLE,\n  STORY_CONTEXT_MENU_ACTIONS,\n  STORY_CONTEXT_MENU_ITEMS,\n} from '../../../../../constants';\nimport ListView from '../listView';\nimport StoryGridView from '../storyGridView';\n\nconst ACTIVE_DIALOG_DELETE_STORY = 'DELETE_STORY';\nfunction StoriesView({ loading, storyActions, stories, view }) {\n  const [contextMenuId, setContextMenuId] = useState(-1);\n  const [titleRenameId, setTitleRenameId] = useState(-1);\n\n  const [activeDialog, setActiveDialog] = useState('');\n  const [activeStory, setActiveStory] = useState(null);\n  const [focusedStory, setFocusedStory] = useState({});\n  const [returnStoryFocusId, setReturnStoryFocusId] = useState(null);\n\n  const { showSnackbar } = useSnackbar();\n\n  const isActiveDeleteStoryDialog =\n    activeDialog === ACTIVE_DIALOG_DELETE_STORY && activeStory;\n\n  const storiesById = useMemo(() => stories.map(({ id }) => id), [stories]);\n\n  useEffect(() => {\n    // if a dialog is opened and the keyboard used we need to return the focus of the proper grid item to ease keyboard usage\n    // focusedStory is set when activeDialog is removed\n    // then we use storiesById to find the proper index of the interacted with item and use that to decide where to move focus\n    if (focusedStory.id && !returnStoryFocusId) {\n      const storyArrayIndex = storiesById.indexOf(focusedStory.id);\n      const isDeletedAdjustmentDirection = storyArrayIndex > 0 ? -1 : +1;\n      const adjustedIndex = focusedStory.isDeleted\n        ? isDeletedAdjustmentDirection\n        : 0;\n      const focusIndex = storyArrayIndex + adjustedIndex;\n      const storyIdToFocus = storiesById[focusIndex];\n      storyIdToFocus && setReturnStoryFocusId(storyIdToFocus);\n    }\n  }, [focusedStory, returnStoryFocusId, storiesById]);\n\n  useEffect(() => {\n    if (!activeDialog) {\n      setActiveStory(null);\n    }\n  }, [activeDialog, setActiveStory]);\n\n  useEffect(() => {\n    // every time the activeDialog is truthy we want to reset our state that helps determine where to send focus back to when the dialog is closed\n    if (activeDialog) {\n      setFocusedStory({});\n      setReturnStoryFocusId(null);\n    }\n  }, [activeDialog]);\n\n  const handleOnRenameStory = useCallback(\n    (story, newTitle) => {\n      setTitleRenameId(-1);\n      trackEvent('rename_story');\n      storyActions.updateStory({ ...story, title: { raw: newTitle } });\n    },\n    [storyActions]\n  );\n\n  const handleOnDeleteStory = useCallback(() => {\n    trackEvent('delete_story');\n    storyActions.trashStory(activeStory);\n    setFocusedStory({ id: activeStory?.id, isDeleted: true });\n    setActiveDialog('');\n  }, [storyActions, activeStory]);\n\n  // menu item actions\n  const handleOpenStoryInEditor = useCallback(() => {\n    setContextMenuId(-1);\n    trackEvent('open_in_editor');\n  }, []);\n\n  const handleRenameStory = useCallback((story) => {\n    setContextMenuId(-1);\n    setTitleRenameId(story.id);\n  }, []);\n\n  const handleDuplicateStory = useCallback(\n    (story) => {\n      setContextMenuId(-1);\n      trackEvent('duplicate_story');\n      storyActions.duplicateStory(story);\n      setFocusedStory({ id: story.id });\n    },\n    [storyActions]\n  );\n\n  const handleDeleteStory = useCallback((story) => {\n    setContextMenuId(-1);\n    setActiveStory(story);\n    setActiveDialog(ACTIVE_DIALOG_DELETE_STORY);\n  }, []);\n\n  const handleCopyStoryLink = useCallback(\n    (story) => {\n      setContextMenuId(-1);\n      window.navigator.clipboard.writeText(story.link);\n\n      showSnackbar({\n        message: sprintf(\n          /* translators: %s: story title. */\n          __('%s has been copied to your clipboard.', 'web-stories'),\n          titleFormatted(story.title)\n        ),\n        dismissible: true,\n      });\n      setFocusedStory({ id: story.id });\n    },\n    [showSnackbar]\n  );\n\n  const handleCloseConfirmDialog = useCallback(() => {\n    setFocusedStory({ id: activeStory?.id });\n    setActiveDialog('');\n  }, [activeStory]);\n\n  const menuItems = STORY_CONTEXT_MENU_ITEMS.map((item) => {\n    switch (item?.value) {\n      case STORY_CONTEXT_MENU_ACTIONS.COPY_STORY_LINK:\n        item.action = handleCopyStoryLink;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.DELETE:\n        item.action = handleDeleteStory;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.DUPLICATE:\n        item.action = handleDuplicateStory;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.OPEN_STORY_LINK:\n        item.action = handleOpenStoryInEditor;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.RENAME:\n        item.action = handleRenameStory;\n        break;\n      default:\n        item.action = () => setContextMenuId(-1);\n        break;\n    }\n    return item;\n  });\n\n  const storyMenu = useMemo(() => {\n    return {\n      handleMenuToggle: setContextMenuId,\n      contextMenuId,\n      menuItems,\n    };\n  }, [contextMenuId, menuItems, setContextMenuId]);\n\n  const renameStory = useMemo(() => {\n    return {\n      id: titleRenameId,\n      handleOnRenameStory,\n      handleCancelRename: () => setTitleRenameId(-1),\n    };\n  }, [handleOnRenameStory, setTitleRenameId, titleRenameId]);\n\n  const ActiveView = useMemo(() => {\n    // Stories should be shown when we trigger a fetch from `InfiniteScroll`.\n    // Stories should be hidden when a filter is changed.\n    if (view.style === VIEW_STYLE.LIST) {\n      // StoryListView needs to show the table header when loading stories\n      // when filtering.\n      return (\n        <ListView\n          hideStoryList={\n            loading?.isLoading && !loading?.showStoriesWhileLoading.current\n          }\n          pageSize={view.pageSize}\n          renameStory={renameStory}\n          stories={stories}\n          storyMenu={storyMenu}\n        />\n      );\n    }\n\n    if (\n      !loading?.isLoading ||\n      (loading?.isLoading && loading?.showStoriesWhileLoading.current)\n    ) {\n      return (\n        <StoryGridView\n          isLoading={loading?.isLoading}\n          pageSize={view.pageSize}\n          renameStory={renameStory}\n          storyMenu={storyMenu}\n          stories={stories}\n          returnStoryFocusId={{\n            value: returnStoryFocusId,\n            set: setReturnStoryFocusId,\n          }}\n        />\n      );\n    }\n\n    // Hide all stories when filter is triggered.\n    return null;\n  }, [loading, renameStory, returnStoryFocusId, stories, storyMenu, view]);\n\n  return (\n    <>\n      {ActiveView}\n      {loading?.isLoading && !loading?.showStoriesWhileLoading.current && (\n        <LoadingContainer>\n          <LoadingSpinner />\n        </LoadingContainer>\n      )}\n      {isActiveDeleteStoryDialog && (\n        <Dialog\n          isOpen\n          contentLabel={__('Dialog to confirm deleting a story', 'web-stories')}\n          title={__('Delete Story', 'web-stories')}\n          onClose={handleCloseConfirmDialog}\n          secondaryText={__('Cancel', 'web-stories')}\n          secondaryRest={{\n            ['aria-label']: sprintf(\n              /* translators: %s: story title. */\n              __('Cancel deleting story \"%s\"', 'web-stories'),\n              titleFormatted(activeStory.title)\n            ),\n          }}\n          primaryText={__('Delete', 'web-stories')}\n          onPrimary={handleOnDeleteStory}\n          primaryRest={{\n            ['aria-label']: sprintf(\n              /* translators: %s: story title. */\n              __('Confirm deleting story \"%s\"', 'web-stories'),\n              titleFormatted(activeStory.title)\n            ),\n          }}\n        >\n          <Text.Paragraph size={TextSize.Small}>\n            {sprintf(\n              /* translators: %s: story title. */\n              __('Are you sure you want to delete \"%s\"?', 'web-stories'),\n              titleFormatted(activeStory.title)\n            )}\n          </Text.Paragraph>\n        </Dialog>\n      )}\n    </>\n  );\n}\n\nStoriesView.propTypes = {\n  loading: PropTypes.shape({\n    isLoading: PropTypes.bool,\n    showStoriesWhileLoading: ShowStoriesWhileLoadingPropType,\n  }),\n  storyActions: StoryActionsPropType,\n  stories: StoriesPropType,\n  view: ViewPropTypes,\n};\nexport default StoriesView;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyGridItem/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Headline,\n  Icons,\n  TextSize,\n  Text,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { CardGridItem } from '../../../../../components';\n\nexport const CustomCardGridItem = styled(CardGridItem)`\n  display: grid;\n  grid-template-columns: 100%;\n  grid-template-rows: ${({ $posterHeight }) => `${$posterHeight}px auto`};\n`;\nCustomCardGridItem.propTypes = {\n  $posterHeight: PropTypes.number,\n};\n\n// Allows grid item contents to overlay in a set space\nexport const CardWrapper = styled.div`\n  position: absolute;\n  height: 100%;\n  width: 100%;\n`;\n\nexport const ScrimAnchor = styled.a`\n  position: absolute;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  box-sizing: border-box;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n\n  &:hover,\n  &:focus {\n    box-shadow: none;\n    border: ${({ theme }) => `4px solid ${theme.colors.interactiveBg.active}`};\n  }\n`;\n// Components that create the content to display on top of a poster\n// Set guidance for how content should display on top of a poster\nexport const StyledStoryDisplayContent = styled.div`\n  padding: 20px 12px 8px 12px;\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n`;\n\n// Generic row to vertically center grid item contents\nexport const Row = styled.div`\n  width: 100%;\n  display: flex;\n  align-items: flex-end;\n  flex-wrap: wrap;\n`;\nexport const LockedRow = styled(Row)`\n  position: absolute;\n  top: 8px;\n  right: 8px;\n  justify-content: flex-end;\n  align-items: center;\n`;\n\n// Interior grid for details to allow context menu space without jostling copy\nexport const CardDetailsGrid = styled.div`\n  display: grid;\n  grid-template-columns: 80% auto;\n  margin-top: 4px;\n`;\nexport const CardDetailsColumn = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-self: flex-end;\n`;\n\n// Story Title\n// Overriding stylelint for the sake of line clamping the title to be 3 lines.\n// This is supported by all major browsers except IE 11.\n// If it fails, max-height will catch so that really long titles\n// don't leave their designated space, just no ellipsis.\nexport const Title = styled(Headline).attrs({\n  as: 'h3',\n  size: TextSize.XSmall,\n})`\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  margin: 0;\n  max-height: calc(1.2em * 3);\n  /* stylelint-disable-next-line */\n  display: -webkit-box;\n  -webkit-line-clamp: 3;\n  /* stylelint-disable-next-line */\n  -webkit-box-orient: vertical;\n`;\n\n// All body text\nexport const DetailCopy = styled(Text.Span).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  margin: 0;\n`;\n\n// specifications for exposing a locked story\nexport const LockAvatar = styled.img`\n  height: 40px;\n  width: 40px;\n  border: ${({ theme }) =>\n    `2px solid ${theme.colors.interactiveBg.brandNormal}`};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  z-index: 3;\n`;\n\nexport const LockIcon = styled(Icons.LockClosed)`\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  display: inline;\n  height: 36px;\n  width: 36px;\n  margin: -4px -4px -4px -10px;\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyGridItem/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { VisuallyHidden } from '@googleforcreators/design-system';\nimport { getRelativeDisplayDate } from '@googleforcreators/date';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { useMemo, forwardRef } from '@googleforcreators/react';\nimport { css } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { StoryMenu } from '../../../../../components';\nimport { generateStoryMenu } from '../../../../../components/popoverMenu/story-menu-generator';\nimport {\n  DEFAULT_GRID_IMG_HEIGHT,\n  DEFAULT_GRID_IMG_WIDTH,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport {\n  PageSizePropType,\n  RenameStoryPropType,\n  StoryMenuPropType,\n  StoryPropType,\n} from '../../../../../propTypes';\nimport { titleFormatted } from '../../../../../utils';\nimport { useConfig } from '../../../../config';\nimport {\n  Container,\n  Poster,\n  Gradient,\n  Scrim,\n} from '../../../shared/grid/components';\nimport { CardWrapper, CustomCardGridItem, ScrimAnchor } from './components';\nimport StoryDisplayContent from './storyDisplayContent';\n\nconst StoryGridItem = forwardRef(\n  ({ onFocus, isActive, pageSize, renameStory, story, storyMenu }, ref) => {\n    const { userId } = useConfig();\n    const tabIndex = isActive ? 0 : -1;\n    const titleRenameProps = renameStory\n      ? {\n          editMode: renameStory?.id === story?.id,\n          onEditComplete: (newTitle) =>\n            renameStory?.handleOnRenameStory(story, newTitle),\n          onEditCancel: renameStory?.handleCancelRename,\n        }\n      : {};\n\n    const isLocked = useMemo(\n      () => story?.locked && userId !== story?.lockUser.id,\n      [story, userId]\n    );\n\n    const generatedMenuItems = useMemo(\n      () =>\n        generateStoryMenu({\n          menuItems: storyMenu.menuItems,\n          story,\n          isLocked,\n        }),\n      [storyMenu, story, isLocked]\n    );\n\n    const storyDate = getRelativeDisplayDate(\n      story?.status === STORY_STATUS.DRAFT\n        ? story?.modifiedGmt\n        : story?.createdGmt\n    );\n\n    const formattedTitle = titleFormatted(story.title);\n\n    const memoizedStoryMenu = useMemo(\n      () =>\n        generatedMenuItems.length ? (\n          <StoryMenu\n            menuLabel={\n              isLocked\n                ? sprintf(\n                    /* translators: 1: story title. 2: user currently editing the story. */\n                    __('Context menu for %1$s (locked by %2$s)', 'web-stories'),\n                    formattedTitle,\n                    story?.lockUser.name\n                  )\n                : sprintf(\n                    /* translators: %s: story title.*/\n                    __('Context menu for %s', 'web-stories'),\n                    formattedTitle\n                  )\n            }\n            itemActive={isActive}\n            tabIndex={tabIndex}\n            onMoreButtonSelected={storyMenu.handleMenuToggle}\n            contextMenuId={storyMenu.contextMenuId}\n            storyId={story.id}\n            isInverted\n            menuItems={generatedMenuItems}\n            menuStyleOverrides={css`\n              /* force menu position to bottom corner */\n              margin: 0 0 0 auto;\n            `}\n          />\n        ) : null,\n      [\n        isLocked,\n        formattedTitle,\n        story?.lockUser?.name,\n        story.id,\n        isActive,\n        tabIndex,\n        storyMenu,\n        generatedMenuItems,\n      ]\n    );\n\n    return (\n      <CustomCardGridItem\n        data-testid={`story-grid-item-${story.id}`}\n        onFocus={onFocus}\n        $posterHeight={pageSize.height}\n        ref={ref}\n        aria-label={sprintf(\n          /* translators: %s: story title.*/\n          __('Details about %s', 'web-stories'),\n          formattedTitle\n        )}\n      >\n        <Container>\n          <CardWrapper>\n            <Poster\n              {...(story.featuredMediaUrl\n                ? {\n                    alt: sprintf(\n                      /* translators: %s: Story title. */\n                      __('%s Poster image', 'web-stories'),\n                      formattedTitle\n                    ),\n                    as: 'img',\n                    src: story.featuredMediaUrl,\n                    decoding: 'async',\n                  }\n                : null)}\n              width={DEFAULT_GRID_IMG_WIDTH}\n              height={DEFAULT_GRID_IMG_HEIGHT}\n            />\n            <Gradient />\n            <Scrim>\n              {story?.capabilities?.hasEditAction && (\n                <ScrimAnchor\n                  className=\"grid-item-anchor\"\n                  data-testid=\"story-editor-grid-link\"\n                  tabIndex={tabIndex}\n                  href={story.editStoryLink}\n                >\n                  <VisuallyHidden>\n                    {sprintf(\n                      /* translators: %s: Story title. */\n                      __('Open %s in Editor', 'web-stories'),\n                      formattedTitle\n                    )}\n                  </VisuallyHidden>\n                </ScrimAnchor>\n              )}\n              <StoryDisplayContent\n                author={story.author}\n                contextMenu={memoizedStoryMenu}\n                displayDate={storyDate}\n                formattedTitle={formattedTitle}\n                id={story.id}\n                isLocked={isLocked}\n                lockUser={story?.lockUser}\n                status={story?.status}\n                title={story.title}\n                {...titleRenameProps}\n              />\n            </Scrim>\n          </CardWrapper>\n        </Container>\n      </CustomCardGridItem>\n    );\n  }\n);\n\nStoryGridItem.displayName = 'StoryGridItem';\n\nStoryGridItem.propTypes = {\n  onFocus: PropTypes.func,\n  isActive: PropTypes.bool,\n  pageSize: PageSizePropType,\n  renameStory: RenameStoryPropType,\n  storyMenu: StoryMenuPropType,\n  story: StoryPropType,\n};\n\nexport default StoryGridItem;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyGridItem/storyDisplayContent.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { Placement } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { STORY_STATUS } from '../../../../../constants';\nimport { InlineInputForm, Tooltip } from '../../../../../components';\nimport { DashboardStatusesPropType } from '../../../../../propTypes';\nimport {\n  StyledStoryDisplayContent,\n  CardDetailsGrid,\n  CardDetailsColumn,\n  Row,\n  Title,\n  DetailCopy,\n  LockAvatar,\n  LockedRow,\n  LockIcon,\n} from './components';\n\nconst StoryDisplayContent = ({\n  author,\n  contextMenu,\n  displayDate,\n  editMode,\n  formattedTitle,\n  id,\n  isLocked,\n  lockUser = {},\n  onEditComplete,\n  onEditCancel,\n  status,\n  title,\n}) => {\n  const displayDateText = useMemo(() => {\n    if (!displayDate) {\n      return null;\n    }\n\n    switch (status) {\n      case STORY_STATUS.PUBLISH:\n        return sprintf(\n          /* translators: %s: published date */\n          __('Published %s', 'web-stories'),\n          displayDate\n        );\n      case STORY_STATUS.FUTURE:\n        return sprintf(\n          /* translators: %s: future publish date */\n          __('Scheduled %s', 'web-stories'),\n          displayDate\n        );\n\n      default:\n        return sprintf(\n          /* translators: %s: last modified date */\n          __('Modified %s', 'web-stories'),\n          displayDate\n        );\n    }\n  }, [status, displayDate]);\n\n  const { name, avatar } = lockUser;\n\n  const storyLockedTitle = isLocked && avatar && (\n    <LockedRow>\n      <Tooltip\n        position={Placement.BottomStart}\n        title={\n          name &&\n          sprintf(\n            /* translators: %s: user name */\n            __('%s is currently editing this story', 'web-stories'),\n            name\n          )\n        }\n      >\n        <LockAvatar\n          src={avatar}\n          alt={name}\n          decoding=\"async\"\n          height={24}\n          width={24}\n          data-test-id=\"lock-user-avatar\"\n        />\n      </Tooltip>\n    </LockedRow>\n  );\n  return (\n    <StyledStoryDisplayContent>\n      {storyLockedTitle}\n      {editMode ? (\n        <InlineInputForm\n          onEditComplete={onEditComplete}\n          onEditCancel={onEditCancel}\n          value={title}\n          id={id}\n          label={__('Rename story', 'web-stories')}\n          isInverted\n        />\n      ) : (\n        <Row>\n          {isLocked && <LockIcon />}\n          <Title>{formattedTitle}</Title>\n        </Row>\n      )}\n      <CardDetailsGrid>\n        <CardDetailsColumn>\n          {status === STORY_STATUS.DRAFT && (\n            <DetailCopy isBold>{__('Draft', 'web-stories')}</DetailCopy>\n          )}\n          {status === STORY_STATUS.PENDING && (\n            <DetailCopy isBold>{__('Pending', 'web-stories')}</DetailCopy>\n          )}\n          {author?.name && <DetailCopy>{author?.name}</DetailCopy>}\n          <DetailCopy className=\"dashboard-grid-item-date\">\n            {displayDateText}\n          </DetailCopy>\n        </CardDetailsColumn>\n        <CardDetailsColumn>{contextMenu}</CardDetailsColumn>\n      </CardDetailsGrid>\n    </StyledStoryDisplayContent>\n  );\n};\n\nStoryDisplayContent.propTypes = {\n  author: PropTypes.object,\n  contextMenu: PropTypes.node,\n  displayDate: PropTypes.string,\n  editMode: PropTypes.bool,\n  formattedTitle: PropTypes.string.isRequired,\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n  isLocked: PropTypes.bool,\n  lockUser: PropTypes.object,\n  onEditComplete: PropTypes.func,\n  onEditCancel: PropTypes.func,\n  title: PropTypes.string.isRequired,\n  status: DashboardStatusesPropType,\n};\n\nexport default StoryDisplayContent;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyGridView/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useRef,\n  useEffect,\n  useState,\n  useMemo,\n  useCallback,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport { useGridViewKeys } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { CardGrid } from '../../../../../components';\nimport {\n  StoriesPropType,\n  StoryMenuPropType,\n  PageSizePropType,\n  RenameStoryPropType,\n} from '../../../../../propTypes';\nimport {\n  PAGE_WRAPPER,\n  STORY_CONTEXT_MENU_ACTIONS,\n} from '../../../../../constants';\nimport { useConfig } from '../../../../config';\nimport StoryGridItem from '../storyGridItem';\n\nconst StoryGrid = styled(CardGrid)`\n  width: calc(100% - ${PAGE_WRAPPER.GUTTER}px);\n`;\n\nconst StoryGridView = ({\n  stories,\n  pageSize,\n  storyMenu,\n  renameStory,\n  returnStoryFocusId,\n}) => {\n  const { isRTL } = useConfig();\n  const containerRef = useRef();\n  const gridRef = useRef();\n  const itemsRef = useRef({});\n  const [activeGridItemId, setActiveGridItemId] = useState();\n  const activeGridItemIdRef = useRef();\n  const gridItemIds = useMemo(() => stories.map(({ id }) => id), [stories]);\n\n  useGridViewKeys({\n    containerRef,\n    gridRef,\n    itemRefs: itemsRef,\n    isRTL,\n    currentItemId: activeGridItemId,\n    items: stories,\n  });\n\n  // We only want to force focus when returning to the grid from a dialog\n  // By checking to see if the active grid item no longer exists\n  // in tandem with the returnStoryFocusId being present from the parent\n  // AND that the activeGridItemIdRef.current is null we know that\n  // the user is coming from a dialog not just moving grid items\n  useEffect(() => {\n    if (\n      !activeGridItemId &&\n      returnStoryFocusId?.value &&\n      !activeGridItemIdRef.current\n    ) {\n      const newFocusId = returnStoryFocusId?.value;\n      setActiveGridItemId(newFocusId);\n      // grab the menu button and refocus\n      const firstFocusableElement = itemsRef.current?.[\n        newFocusId\n      ]?.querySelectorAll(['button', 'a'])?.[0];\n\n      firstFocusableElement?.focus();\n    }\n  }, [activeGridItemId, returnStoryFocusId]);\n\n  // when keyboard focus changes through FocusableGridItem\n  // immediately focus the edit preview layer on top of preview\n  useEffect(() => {\n    if (activeGridItemId) {\n      activeGridItemIdRef.current = activeGridItemId;\n    }\n  }, [activeGridItemId]);\n\n  // Additional functionality needed when closing context menus to maintain grid item focus\n  const handleMenuToggle = useCallback(\n    (evt, id) => {\n      storyMenu.handleMenuToggle(id);\n      // Conditionally return the focus to the grid when menu is closed using `tab`\n      if (id < 0 && evt?.keyCode === 9) {\n        // Menu is closing.\n        const isNext = !evt?.shiftKey;\n        const idToFocus = isNext\n          ? gridItemIds[gridItemIds.indexOf(activeGridItemId) + 1]\n          : activeGridItemId;\n        returnStoryFocusId.set(idToFocus);\n        activeGridItemIdRef.current = null;\n        setActiveGridItemId(null);\n      }\n    },\n    [activeGridItemId, gridItemIds, returnStoryFocusId, storyMenu]\n  );\n\n  // if keyboard is used instead of mouse the useFocusOut doesn't get triggered\n  // that is where we are setting active grid item ID to null\n  // by doing this here as well we are ensuring consistent functionality\n  const manuallySetFocusOut = useCallback(() => {\n    activeGridItemIdRef.current = null;\n    setActiveGridItemId(null);\n    returnStoryFocusId.set(null);\n  }, [returnStoryFocusId]);\n\n  useFocusOut(containerRef, () => setActiveGridItemId(null), []);\n\n  const modifiedStoryMenu = useMemo(() => {\n    const actions = [\n      STORY_CONTEXT_MENU_ACTIONS.DELETE,\n      STORY_CONTEXT_MENU_ACTIONS.RENAME,\n      STORY_CONTEXT_MENU_ACTIONS.DUPLICATE,\n    ];\n\n    const menuItems = storyMenu.menuItems.map((item) => {\n      const _item = { ...item };\n\n      if (actions.includes(item?.value)) {\n        _item.action = (story) => {\n          manuallySetFocusOut();\n          item.action(story);\n        };\n      }\n\n      return _item;\n    });\n\n    return {\n      ...storyMenu,\n      handleMenuToggle,\n      menuItems,\n    };\n  }, [handleMenuToggle, storyMenu, manuallySetFocusOut]);\n\n  const memoizedStoryGrid = useMemo(\n    () =>\n      stories.map((story) => {\n        return (\n          <StoryGridItem\n            onFocus={() => setActiveGridItemId(story.id)}\n            isActive={activeGridItemId === story.id}\n            ref={(el) => {\n              itemsRef.current[story.id] = el;\n            }}\n            key={story.id}\n            pageSize={pageSize}\n            renameStory={renameStory}\n            story={story}\n            storyMenu={modifiedStoryMenu}\n          />\n        );\n      }),\n    [activeGridItemId, modifiedStoryMenu, pageSize, renameStory, stories]\n  );\n\n  return (\n    <div ref={containerRef}>\n      <StoryGrid\n        pageSize={pageSize}\n        ref={gridRef}\n        role=\"list\"\n        ariaLabel={__('Viewing stories', 'web-stories')}\n      >\n        {memoizedStoryGrid}\n      </StoryGrid>\n    </div>\n  );\n};\n\nStoryGridView.propTypes = {\n  stories: StoriesPropType,\n  pageSize: PageSizePropType.isRequired,\n  storyMenu: StoryMenuPropType,\n  renameStory: RenameStoryPropType,\n  returnStoryFocusId: PropTypes.shape({\n    value: PropTypes.number,\n    set: PropTypes.func,\n  }),\n};\n\nexport default StoryGridView;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyGridView/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nimport {\n  formattedStoriesArray,\n  STORYBOOK_PAGE_SIZE,\n} from '../../../../../../storybookUtils';\nimport { STORY_CONTEXT_MENU_ITEMS } from '../../../../../../constants';\nimport StoryGridView from '..';\n\nexport default {\n  title: 'Dashboard/Views/MyStories/Content/GridView',\n  component: StoryGridView,\n  args: {\n    bottomActionLabel: 'MY CTA',\n  },\n  argTypes: {\n    handleMenuToggle: {\n      action: 'handleMenuToggle',\n    },\n    handleMenuItemSelected: {\n      action: 'handleMenuItemSelected',\n    },\n  },\n  parameters: {\n    controls: {\n      include: [\n        'bottomActionLabel',\n        'handleMenuToggle',\n        'handleMenuItemSelected',\n      ],\n    },\n  },\n};\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <StoryGridView\n        stories={formattedStoriesArray}\n        storyMenu={{\n          handleMenuToggle: args.handleMenuToggle,\n          contextMenuId: -1,\n          menuItems: STORY_CONTEXT_MENU_ITEMS,\n          handleMenuItemSelected: args.handleMenuItemSelected,\n        }}\n        pageSize={STORYBOOK_PAGE_SIZE}\n        {...args}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyListItem/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  STORY_PREVIEW_WIDTH,\n  VIEWPORT_BREAKPOINT,\n} from '../../../../../constants';\nimport { TableRow, MoreVerticalButton } from '../../../../../components';\n\nexport const PreviewImage = styled.div`\n  display: inline-block;\n  background: ${({ theme }) => theme.colors.gradient.placeholder};\n  width: ${STORY_PREVIEW_WIDTH[VIEWPORT_BREAKPOINT.THUMBNAIL]}px;\n  height: ${STORY_PREVIEW_WIDTH[VIEWPORT_BREAKPOINT.THUMBNAIL] / (3 / 4)}px;\n  object-fit: contain;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n`;\nexport const PreviewWrapper = styled.div`\n  position: relative;\n`;\n\nexport const LockIcon = styled(Icons.LockClosed)`\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  height: 24px;\n  display: block;\n  margin: auto;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n  color: ${({ theme }) => theme.colors.standard.white};\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n`;\n\nexport const StyledTableRow = styled(TableRow)`\n  &:hover ${MoreVerticalButton}, &:focus-within ${MoreVerticalButton} {\n    opacity: 1;\n  }\n`;\n\nexport const TitleTableCellContainer = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n\n  ${MoreVerticalButton} {\n    margin: 10px auto;\n  }\n\n  &:hover ${MoreVerticalButton}, &:active ${MoreVerticalButton} {\n    opacity: 1;\n  }\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/storyListItem/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { getRelativeDisplayDate } from '@googleforcreators/date';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { Headline, Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineInputForm,\n  StoryMenu,\n  TableCell,\n  TablePreviewCell,\n  TableStatusCell,\n  Tooltip,\n} from '../../../../../components';\nimport { generateStoryMenu } from '../../../../../components/popoverMenu/story-menu-generator';\nimport { DISPLAY_STATUS, STORY_STATUS } from '../../../../../constants';\nimport {\n  RenameStoryPropType,\n  StoryMenuPropType,\n  StoryPropType,\n} from '../../../../../propTypes';\nimport { titleFormatted } from '../../../../../utils';\n\nimport {\n  LockIcon,\n  PreviewWrapper,\n  PreviewImage,\n  StyledTableRow,\n  TitleTableCellContainer,\n} from './components';\n\nfunction onFocusSelectAll(e) {\n  window.getSelection().selectAllChildren(e.target);\n}\n\nfunction onBlurDeselectAll() {\n  window.getSelection().removeAllRanges();\n}\n\nexport const StoryListItem = ({\n  story,\n  renameStory,\n  userId,\n  storyMenu,\n  storyStatus,\n}) => {\n  const isLocked = useMemo(\n    () => story?.locked && userId !== story?.lockUser.id,\n    [story, userId]\n  );\n\n  const formattedTitle = titleFormatted(story.title);\n\n  const generatedMenuItems = useMemo(\n    () =>\n      generateStoryMenu({\n        menuItems: storyMenu.menuItems,\n        story,\n        isLocked,\n      }),\n    [storyMenu, story, isLocked]\n  );\n\n  const memoizedStoryMenu = useMemo(\n    () =>\n      generatedMenuItems.length ? (\n        <StoryMenu\n          menuLabel={sprintf(\n            /* translators: %s: story title.*/\n            __('Context menu for %s', 'web-stories'),\n            formattedTitle\n          )}\n          onMoreButtonSelected={(_, id) => storyMenu.handleMenuToggle(id)}\n          contextMenuId={storyMenu.contextMenuId}\n          storyId={story.id}\n          menuItems={generatedMenuItems}\n          verticalAlign=\"center\"\n        />\n      ) : null,\n    [generatedMenuItems, formattedTitle, storyMenu, story]\n  );\n\n  return (\n    <StyledTableRow data-testid={`story-list-item-${story.id}`}>\n      <TablePreviewCell>\n        <Tooltip\n          title={\n            isLocked && story?.lockUser.name\n              ? sprintf(\n                  /* translators: %s: user name */\n                  __('%s is currently editing this story', 'web-stories'),\n                  story?.lockUser.name\n                )\n              : ''\n          }\n        >\n          <PreviewWrapper>\n            <PreviewImage\n              {...(story.featuredMediaUrl\n                ? {\n                    src: story.featuredMediaUrl,\n                    alt: sprintf(\n                      /* translators: %s: Story title. */\n                      __('%s Poster image', 'web-stories'),\n                      formattedTitle\n                    ),\n                    as: 'img',\n                    decoding: 'async',\n                  }\n                : null)}\n            />\n            {isLocked && <LockIcon />}\n          </PreviewWrapper>\n        </Tooltip>\n      </TablePreviewCell>\n      <TableCell>\n        <TitleTableCellContainer>\n          {renameStory.id === story.id ? (\n            <InlineInputForm\n              onEditComplete={(newTitle) =>\n                renameStory.handleOnRenameStory(story, newTitle)\n              }\n              onEditCancel={renameStory.handleCancelRename}\n              value={story.title}\n              id={story.id}\n              label={__('Rename story', 'web-stories')}\n            />\n          ) : (\n            <>\n              <Headline\n                tabIndex={0}\n                onFocus={onFocusSelectAll}\n                onBlur={onBlurDeselectAll}\n                size={TextSize.XXXSmall}\n                as=\"h3\"\n                aria-label={\n                  isLocked\n                    ? sprintf(\n                        /* translators: 1: story title. 2: user currently editing the story. */\n                        __('%1$s (locked by %2$s)', 'web-stories'),\n                        formattedTitle,\n                        story?.lockUser.name\n                      )\n                    : formattedTitle\n                }\n              >\n                {formattedTitle}\n              </Headline>\n              {memoizedStoryMenu}\n            </>\n          )}\n        </TitleTableCellContainer>\n      </TableCell>\n      <TableCell>\n        <Text.Span size={TextSize.Small}>{story.author?.name || '—'}</Text.Span>\n      </TableCell>\n      <TableCell>\n        <Text.Span size={TextSize.Small}>\n          {getRelativeDisplayDate(story.createdGmt)}\n        </Text.Span>\n      </TableCell>\n      <TableCell>\n        <Text.Span size={TextSize.Small}>\n          {getRelativeDisplayDate(story.modifiedGmt)}\n        </Text.Span>\n      </TableCell>\n      {storyStatus !== STORY_STATUS.DRAFT && (\n        <TableStatusCell>\n          <Text.Span size={TextSize.Small}>\n            {DISPLAY_STATUS[story?.status]}\n          </Text.Span>\n        </TableStatusCell>\n      )}\n    </StyledTableRow>\n  );\n};\n\nStoryListItem.propTypes = {\n  story: StoryPropType.isRequired,\n  renameStory: RenameStoryPropType,\n  userId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),\n  storyMenu: StoryMenuPropType.isRequired,\n  storyStatus: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/test/content.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { SnackbarProvider } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../../../testUtils';\nimport { VIEW_STYLE, STORY_STATUSES } from '../../../../../constants';\nimport LayoutProvider from '../../../../../components/layout/provider';\nimport Content from '..';\n\nconst fakeStories = [\n  {\n    id: 1,\n    status: 'publish',\n    title: 'Story A',\n    pages: [{ id: '10', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    capabilities: {\n      hasDeleteAction: false,\n      hasEditAction: false,\n    },\n  },\n  {\n    id: 2,\n    status: 'draft',\n    title: 'Story B',\n    pages: [{ id: '20', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    capabilities: {\n      hasDeleteAction: false,\n      hasEditAction: false,\n    },\n  },\n  {\n    id: 3,\n    status: 'publish',\n    title: 'Story C',\n    pages: [{ id: '30', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    capabilities: {\n      hasDeleteAction: false,\n      hasEditAction: false,\n    },\n  },\n];\nconst pageSize = {\n  width: 200,\n  height: 300,\n};\n\ndescribe('Dashboard <Content />', () => {\n  afterEach(() => {\n    jest.resetAllMocks();\n  });\n\n  it('should render the content grid with the correct story count.', () => {\n    renderWithProviders(\n      <SnackbarProvider>\n        <LayoutProvider>\n          <Content\n            stories={fakeStories}\n            page={{\n              requestNextPage: jest.fn,\n            }}\n            view={{\n              style: VIEW_STYLE.GRID,\n              pageSize,\n            }}\n            storyActions={{\n              duplicateStory: jest.fn,\n              trashStory: jest.fn,\n              updateStory: jest.fn,\n            }}\n          />\n        </LayoutProvider>\n      </SnackbarProvider>\n    );\n\n    expect(screen.getAllByTestId(/^story-grid-item/)).toHaveLength(\n      fakeStories.length\n    );\n  });\n\n  it('should show \"Start telling Stories.\" if no stories are present.', () => {\n    renderWithProviders(\n      <SnackbarProvider>\n        <LayoutProvider>\n          <Content\n            stories={[]}\n            page={{\n              requestNextPage: jest.fn,\n            }}\n            view={{\n              style: VIEW_STYLE.GRID,\n              pageSize,\n            }}\n            storyActions={{\n              duplicateStory: jest.fn,\n              trashStory: jest.fn,\n              updateStory: jest.fn,\n            }}\n          />\n        </LayoutProvider>\n      </SnackbarProvider>\n    );\n\n    expect(screen.getByText('Start telling Stories.')).toBeInTheDocument();\n  });\n\n  it('should show \"Sorry, we couldn\\'t find any results matching \"scooby dooby doo\" if no stories are found for a search query are present.', () => {\n    renderWithProviders(\n      <SnackbarProvider>\n        <LayoutProvider>\n          <Content\n            filtersObject={{\n              search: 'scooby dooby doo',\n              status: STORY_STATUSES[0],\n            }}\n            stories={[]}\n            page={{\n              requestNextPage: jest.fn,\n            }}\n            view={{\n              style: VIEW_STYLE.GRID,\n              pageSize,\n            }}\n            storyActions={{\n              duplicateStory: jest.fn,\n              trashStory: jest.fn,\n              updateStory: jest.fn,\n            }}\n          />\n        </LayoutProvider>\n      </SnackbarProvider>\n    );\n\n    expect(\n      screen.getByText(\n        'Sorry, we couldn\\'t find any results matching \"scooby dooby doo\"'\n      )\n    ).toBeInTheDocument();\n  });\n\n  it('should show \"Sorry, we couldn\\'t find any results if no stories are found for a filter query are present.', () => {\n    renderWithProviders(\n      <SnackbarProvider>\n        <LayoutProvider>\n          <Content\n            stories={[]}\n            filtersObject={{\n              sports: 2,\n            }}\n            page={{\n              requestNextPage: jest.fn,\n            }}\n            view={{\n              style: VIEW_STYLE.GRID,\n              pageSize,\n            }}\n            storyActions={{\n              duplicateStory: jest.fn,\n              trashStory: jest.fn,\n              updateStory: jest.fn,\n            }}\n          />\n        </LayoutProvider>\n      </SnackbarProvider>\n    );\n\n    expect(\n      screen.getByText(\"Sorry, we couldn't find any results\")\n    ).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/content/test/storiesView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../../../testUtils';\nimport {\n  STORY_SORT_OPTIONS,\n  SORT_DIRECTION,\n  VIEW_STYLE,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport StoriesView from '../storiesView';\nimport useStoryFilters from '../../filters/useStoryFilters';\n\nconst fakeStories = [\n  {\n    id: 1,\n    status: 'publish',\n    title: 'Story A',\n    pages: [{ id: '10', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-1.png',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n  },\n  {\n    id: 2,\n    status: 'draft',\n    title: 'Story B',\n    pages: [{ id: '20', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-2.png',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n  },\n  {\n    id: 3,\n    status: 'publish',\n    title: 'Story C',\n    pages: [{ id: '30', elements: [] }],\n    bottomTargetAction: 'https://example.com',\n    link: 'https://example.com',\n    editStoryLink: 'https://example.com',\n    previewLink: 'https://example.com',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-3.png',\n    locked: true,\n    lockUser: {\n      name: 'Batgirl',\n      id: 898978979879,\n    },\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n  },\n];\n\njest.mock('../../filters/useStoryFilters', () => ({\n  ...jest.requireActual('../../filters/useStoryFilters'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\nconst mockUseStoryFilters = useStoryFilters;\n\nconst updateSort = jest.fn();\n\nconst mockFilterState = {\n  filters: [\n    {\n      key: 'status',\n      filterId: STORY_STATUS.ALL,\n    },\n  ],\n  filtersObject: {},\n  sortObject: {\n    orderby: STORY_SORT_OPTIONS.NAME,\n    order: SORT_DIRECTION.ASC,\n  },\n  updateSort,\n};\n\ndescribe('Dashboard <StoriesView />', () => {\n  beforeEach(() => {\n    mockUseStoryFilters.mockImplementation(() => mockFilterState);\n  });\n\n  it(`should render stories as a grid when view is ${VIEW_STYLE.GRID}`, () => {\n    renderWithProviders(\n      <StoriesView\n        storyActions={{\n          duplicateStory: jest.fn,\n          trashStory: jest.fn,\n          updateStory: jest.fn,\n        }}\n        stories={fakeStories}\n        view={{\n          style: VIEW_STYLE.GRID,\n          pageSize: {\n            width: 210,\n            height: 316,\n          },\n        }}\n      />,\n      {}\n    );\n\n    expect(screen.getAllByTestId(/^story-grid-item/)).toHaveLength(\n      fakeStories.length\n    );\n  });\n\n  describe('Loading stories', () => {\n    beforeEach(() => {\n      mockUseStoryFilters.mockImplementation(() => mockFilterState);\n    });\n    it('should be able to hide the grid while the stories are loading', () => {\n      renderWithProviders(\n        <StoriesView\n          storyActions={{\n            duplicateStory: jest.fn,\n            trashStory: jest.fn,\n            updateStory: jest.fn,\n          }}\n          stories={fakeStories}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: {\n              width: 210,\n              height: 316,\n            },\n          }}\n          loading={{\n            isLoading: true,\n            showStoriesWhileLoading: { current: false },\n          }}\n        />,\n        {}\n      );\n\n      expect(screen.queryByTestId(/^story-grid-item/)).not.toBeInTheDocument();\n    });\n\n    it('should be able to show the grid while stories are loading', () => {\n      renderWithProviders(\n        <StoriesView\n          storyActions={{\n            duplicateStory: jest.fn,\n            trashStory: jest.fn,\n            updateStory: jest.fn,\n          }}\n          stories={fakeStories}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: {\n              width: 210,\n              height: 316,\n            },\n          }}\n          loading={{\n            isLoading: true,\n            showStoriesWhileLoading: { current: true },\n          }}\n        />,\n        {}\n      );\n\n      expect(screen.queryAllByTestId(/^story-grid-item/)).toHaveLength(\n        fakeStories.length\n      );\n    });\n\n    it('should hide stories in the list view when stories are loading', () => {\n      renderWithProviders(\n        <StoriesView\n          storyActions={{\n            duplicateStory: jest.fn,\n            trashStory: jest.fn,\n            updateStory: jest.fn,\n          }}\n          stories={fakeStories}\n          view={{\n            style: VIEW_STYLE.LIST,\n            pageSize: {\n              width: 210,\n              height: 316,\n            },\n          }}\n          loading={{\n            isLoading: true,\n            showStoriesWhileLoading: { current: false },\n          }}\n        />,\n        {}\n      );\n\n      expect(screen.queryByTestId(/^story-list-item/)).not.toBeInTheDocument();\n    });\n\n    it('should be able to show the list while stories are loading', () => {\n      renderWithProviders(\n        <StoriesView\n          storyActions={{\n            duplicateStory: jest.fn,\n            trashStory: jest.fn,\n            updateStory: jest.fn,\n          }}\n          stories={fakeStories}\n          view={{\n            style: VIEW_STYLE.LIST,\n            pageSize: {\n              width: 210,\n              height: 316,\n            },\n          }}\n          loading={{\n            isLoading: true,\n            showStoriesWhileLoading: { current: true },\n          }}\n        />,\n        {}\n      );\n\n      expect(screen.queryAllByTestId(/^story-list-item/)).toHaveLength(\n        fakeStories.length\n      );\n    });\n  });\n\n  describe('Locked story', () => {\n    beforeEach(() => {\n      mockUseStoryFilters.mockImplementation(() => mockFilterState);\n    });\n    it('should show a lock icon and helpful tooltip and aria text in list view when a story is being edited by another user', () => {\n      renderWithProviders(\n        <StoriesView\n          storyActions={{\n            duplicateStory: jest.fn,\n            trashStory: jest.fn,\n            updateStory: jest.fn,\n          }}\n          stories={fakeStories}\n          view={{\n            style: VIEW_STYLE.LIST,\n            pageSize: {\n              width: 210,\n              height: 316,\n            },\n          }}\n        />,\n        {\n          features: {},\n        },\n        {}\n      );\n\n      expect(screen.getAllByTestId(/^story-list-item/)).toHaveLength(\n        fakeStories.length\n      );\n\n      const lockedStoryTitle = screen.getByText('Story C');\n      expect(lockedStoryTitle).toContainHTML(\n        `${fakeStories[2].title} (locked by ${fakeStories[2].lockUser.name})`\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/author/useAuthorFilter.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport useApi from '../../../../../api/useApi';\n\nlet cachedPrimaryOptions = null;\n\n/**\n * Hook used for Author filter logic.\n * Initializes the author filters data.\n *\n * @return {Function} initializeAuthorFilter function to shape the author filter data.\n */\n\nfunction useAuthorFilter() {\n  const { getAuthors } = useApi(\n    ({\n      actions: {\n        usersApi: { getAuthors },\n      },\n    }) => ({\n      getAuthors,\n    })\n  );\n\n  /**\n   * Query all the authors.\n   * Initializes the primaryOptions and used to search and set queriedOptions.\n   *\n   * @param {string} search Search term for author names.\n   * @return {Array} author data\n   */\n  const queryAuthors = useCallback(\n    async (search) => {\n      const data = await getAuthors(search);\n      return data.map(({ id, name }) => ({\n        id,\n        name,\n      }));\n    },\n    [getAuthors]\n  );\n\n  /**\n   * Get author filters primaryOptions. Cache for later use.\n   * This is needed to initialize the primaryOptions.\n   * See design-system/src/component/datalist\n   *\n   * @see queryAuthors\n   * @return {Promise<Array>} cached authors terms\n   */\n  const getPrimaryOptions = useCallback(async () => {\n    if (!cachedPrimaryOptions) {\n      cachedPrimaryOptions = await queryAuthors();\n    }\n    return cachedPrimaryOptions;\n  }, [queryAuthors]);\n\n  /**\n   * Sets up the shape of the author filter data.\n   *\n   * @return {Object} author filter data\n   */\n  const initializeAuthorFilter = useCallback(() => {\n    return {\n      key: 'author',\n      ariaLabel: __('Filter stories by author', 'web-stories'),\n      placeholder: __('All Authors', 'web-stories'),\n      searchPlaceholder: __('Search Authors', 'web-stories'),\n      noMatchesFoundLabel: __('No authors found', 'web-stories'),\n      query: queryAuthors,\n      getPrimaryOptions,\n    };\n  }, [queryAuthors, getPrimaryOptions]);\n\n  return initializeAuthorFilter;\n}\n\nexport default useAuthorFilter;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createContext,\n  useReducer,\n  useEffect,\n  useCallback,\n  useMemo,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/** @typedef {import('react')} Node */\n\n/**\n * Internal dependencies\n */\nimport reducer from '../../../filters/reducer';\nimport * as types from '../../../filters/types';\nimport useTaxonomyFilters from './taxonomy/useTaxonomyFilters';\nimport useAuthorFilter from './author/useAuthorFilter';\n\nexport const filterContext = createContext({\n  state: {},\n  actions: {},\n});\n\n/**\n * Keeps track of the current filters state.\n *\n * Each filter will have its own logic associated with\n * initialization and how to query terms.\n *\n * state.filters should be used for UI.\n * state.filtersObject should hold the key value pairs associated with filtering query params\n * eg {author: 44} where 'author' is whats being filtered on and '44' is the authors ID\n * thats being filtered for.\n *\n * @param {Object} root0 props for the provider\n * @param {Node} root0.children the children to be rendered\n * @return {Node} React node\n */\n\nexport default function StoryFiltersProvider({ children }) {\n  // each filter type will have its own logic for initializing and querying\n  const initializeTaxonomyFilters = useTaxonomyFilters();\n  const initializeAuthorFilter = useAuthorFilter();\n\n  const [state, dispatch] = useReducer(reducer, {\n    filters: [],\n    filtersObject: {},\n    sortObject: {},\n  });\n\n  /**\n   * Dispatch UPDATE_SORT with new data to update sort\n   *\n   * @param {string} key key property on one of the sort objects\n   * @param {Object} value the properties with updated values\n   * @return {void}\n   */\n  const updateSort = useCallback((values) => {\n    dispatch({ type: types.UPDATE_SORT, payload: { type: 'story', values } });\n  }, []);\n\n  /**\n   * Dispatch UPDATE_FILTER with new data for a given filter\n   *\n   * @param {string} key key property on one of the filter objects\n   * @param {Object} value the properties with updated values\n   * @return {void}\n   */\n  const updateFilter = useCallback((key, value) => {\n    dispatch({ type: types.UPDATE_FILTER, payload: { key, value } });\n  }, []);\n\n  /**\n   * Dispatch REGISTER_FILTERS with all the filters data\n   *\n   * @param {Array} payload array of filters data\n   * @return {void}\n   */\n  const registerFilters = useCallback((value) => {\n    dispatch({ type: types.REGISTER_FILTERS, payload: { value } });\n  }, []);\n\n  /**\n   * Sets up the shape of the filters data\n   * and calls registerFilters with all filters.\n   *\n   * @return {void}\n   */\n  const initializeStoryFilters = useCallback(async () => {\n    const taxonomies = await initializeTaxonomyFilters();\n    const author = initializeAuthorFilter();\n\n    const filters = [...taxonomies, author].filter((filter) => Boolean(filter));\n\n    if (filters.length) {\n      registerFilters(filters);\n    }\n  }, [registerFilters, initializeAuthorFilter, initializeTaxonomyFilters]);\n\n  const contextValue = useMemo(() => {\n    return {\n      state,\n      actions: { updateFilter, updateSort, registerFilters },\n    };\n  }, [state, updateFilter, updateSort, registerFilters]);\n\n  useEffect(() => {\n    initializeStoryFilters();\n  }, [initializeStoryFilters]);\n\n  return (\n    <filterContext.Provider value={contextValue}>\n      {children}\n    </filterContext.Provider>\n  );\n}\n\nStoryFiltersProvider.propTypes = {\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/StoryFiltersProvider/taxonomy/useTaxonomyFilters.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useApi from '../../../../../api/useApi';\n\nconst cachedPrimaryOptions = {};\n\n/**\n * Hook used for taxonomy filters logic.\n * Initializes the taxonomy filters data.\n *\n * @return {Object} initializeTaxonomyFilters taxonomies and a function to shape the taxonoimes filter data.\n */\n\nfunction useTaxonomyFilters() {\n  const { getTaxonomies, getTaxonomyTerms } = useApi(\n    ({\n      actions: {\n        taxonomyApi: { getTaxonomies, getTaxonomyTerms },\n      },\n    }) => ({\n      getTaxonomies,\n      getTaxonomyTerms,\n    })\n  );\n\n  /**\n   * Query individual taxonomy data.\n   * This is needed to initialize the primaryOptions and needed to search and set queriedOptions.\n   *\n   * @param {Object} taxonomy object holding taxonomy data,\n   * including restBase and restPath used to fetch individual taxonomy terms\n   * @param {string} search string use to query taxonomy by name\n   * @return {Array} taxonomy terms\n   */\n  const queryTaxonomyTerms = useCallback(\n    async (taxonomy, search) => {\n      const { restBase, restPath } = taxonomy;\n      const terms = await getTaxonomyTerms(restPath, { search, per_page: -1 });\n      return terms.map((t) => ({\n        ...t,\n        restBase,\n        restPath,\n      }));\n    },\n    [getTaxonomyTerms]\n  );\n\n  /**\n   * Get taxonomy terms for a given taxonomy. Cache for later use.\n   * This is needed to initialize the primaryOptions.\n   * See design-system/src/component/datalist\n   *\n   * @see queryTaxonomyTerms\n   * @param {Object} taxonomy object holding taxonomy data,\n   * including restBase and restPath used to fetch individual taxonomy terms\n   * @return {Promise<Array>} cached taxonomy terms\n   */\n  const getPrimaryOptions = useCallback(\n    async (taxonomy) => {\n      const { restBase } = taxonomy;\n      if (!cachedPrimaryOptions[restBase]) {\n        cachedPrimaryOptions[restBase] = await queryTaxonomyTerms(taxonomy);\n      }\n      return cachedPrimaryOptions[restBase];\n    },\n    [queryTaxonomyTerms]\n  );\n\n  /**\n   * Query all the taxonomies.\n   * Sets up the shape of the taxonomy filters data\n   *\n   * @return {Promise<Array>} taxonomies filter data\n   */\n  const initializeTaxonomyFilters = useCallback(async () => {\n    const taxonomies = await getTaxonomies({\n      hierarchical: true,\n      show_ui: true,\n    });\n    return taxonomies.map((taxonomy) => ({\n      key: taxonomy.restBase,\n      restPath: taxonomy.restPath,\n      placeholder: taxonomy.labels.allItems,\n      ariaLabel: taxonomy.labels.filterByItem,\n      noMatchesFoundLabel: taxonomy.labels.notFound,\n      searchPlaceholder: taxonomy.labels.searchItems,\n      query: (search) => queryTaxonomyTerms(taxonomy, search),\n      getPrimaryOptions: () => getPrimaryOptions(taxonomy),\n    }));\n  }, [queryTaxonomyTerms, getPrimaryOptions, getTaxonomies]);\n\n  return initializeTaxonomyFilters;\n}\n\nexport default useTaxonomyFilters;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/test/storyFiltersProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport StoryFiltersProvider from '../StoryFiltersProvider';\nimport useStoryFilters from '../useStoryFilters';\nimport { STORY_SORT_KEYS } from '../../../../../constants/stories';\n\njest.mock('../StoryFiltersProvider/taxonomy/useTaxonomyFilters', () => {\n  const initializeTaxonomyFilters = () => Promise.resolve([]);\n  return {\n    __esModule: true,\n    default: function useTaxonomyFilter() {\n      return initializeTaxonomyFilters;\n    },\n  };\n});\n\njest.mock('../StoryFiltersProvider/author/useAuthorFilter', () => {\n  const initializeAuthorFilter = () => null;\n  return {\n    __esModule: true,\n    default: function useAuthorFilter() {\n      return initializeAuthorFilter;\n    },\n  };\n});\n\ndescribe('provider', () => {\n  it('should register filters and update filters', () => {\n    const wrapper = ({ children }) => (\n      <StoryFiltersProvider>{children}</StoryFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useStoryFilters(), { wrapper });\n    const filterKey = 'web_story_category';\n\n    // register filter\n    act(() => {\n      result.current.actions.registerFilters([\n        { key: filterKey, filterId: null },\n      ]);\n    });\n\n    // shouldn't be able to register filters with the same key\n    act(() => {\n      result.current.actions.registerFilters([{ key: filterKey, filterId: 1 }]);\n    });\n\n    expect(result.current.state.filters).toHaveLength(1);\n    let filter = result.current.state.filters.find((f) => f.key === filterKey);\n    expect(filter).toBeDefined();\n    expect(filter.filterId).toBeNull();\n\n    // filters with falsy filterId's should not be in the filters object\n    let filterObj = result.current.state.filtersObject;\n    expect(filterObj).toMatchObject({});\n\n    // update the filter\n    act(() => {\n      result.current.actions.updateFilter(filterKey, {\n        filterId: 1,\n      });\n    });\n\n    filter = result.current.state.filters.find((f) => f.key === filterKey);\n    expect(filter).toMatchObject({\n      filterId: 1,\n    });\n\n    filterObj = result.current.state.filtersObject;\n    expect(filterObj).toMatchObject({\n      [filterKey]: 1,\n    });\n  });\n\n  it('should be able to update the sortObject if the acceptable keys are use', () => {\n    const wrapper = ({ children }) => (\n      <StoryFiltersProvider>{children}</StoryFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useStoryFilters(), { wrapper });\n\n    for (const key of Object.keys(STORY_SORT_KEYS)) {\n      for (const value of Object.values(STORY_SORT_KEYS[key])) {\n        act(() => {\n          result.current.actions.updateSort({ [key]: value });\n        });\n        expect(result.current.state.sortObject).toMatchObject({ [key]: value });\n      }\n    }\n  });\n\n  it('should not be able to update the sortObject with arbitrary key value pairs', () => {\n    const wrapper = ({ children }) => (\n      <StoryFiltersProvider>{children}</StoryFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useStoryFilters(), { wrapper });\n\n    const unacceptableSortValues = {\n      orderby: 'valueNotInSortKeyOrderby',\n      order: 'up',\n    };\n\n    const unacceptableSortKeys = {\n      sortby: 'title',\n      sortorder: 'asc',\n    };\n\n    act(() => {\n      result.current.actions.updateSort(unacceptableSortValues);\n    });\n    expect(result.current.state.sortObject).toMatchObject({});\n\n    act(() => {\n      result.current.actions.updateSort(unacceptableSortKeys);\n    });\n    expect(result.current.state.sortObject).toMatchObject({});\n  });\n\n  it('should not return sortObject if nothing changes', () => {\n    const wrapper = ({ children }) => (\n      <StoryFiltersProvider>{children}</StoryFiltersProvider>\n    );\n\n    const { result } = renderHook(() => useStoryFilters(), { wrapper });\n\n    const acceptableSortObject = {\n      orderby: 'title',\n      order: 'asc',\n    };\n\n    const unacceptableSortKeys = {\n      sortby: 'title',\n      sortorder: 'asc',\n    };\n\n    act(() => {\n      // set the sortObject to an acceptable sortObject\n      result.current.actions.updateSort(acceptableSortObject);\n      // try to set the sortObject to an unacceptable sortObject\n      result.current.actions.updateSort(unacceptableSortKeys);\n    });\n    // the state shouldn't be updated if given an unacceptable sortObject\n    expect(result.current.state.sortObject).toMatchObject(acceptableSortObject);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/test/useAuthorFilter.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useAuthorFilter from '../StoryFiltersProvider/author/useAuthorFilter';\n\njest.mock('../../../../api/useApi', () => {\n  const getAuthors = () => {\n    return Promise.resolve([\n      {\n        id: 1,\n        name: 'admin',\n      },\n    ]);\n  };\n  return {\n    __esModule: true,\n    default: function useApi() {\n      return {\n        getAuthors,\n      };\n    },\n  };\n});\n\ndescribe('useAuthorFilter', () => {\n  it('should set authors to return value of getAuthors', async () => {\n    const {\n      result: { current: initializeAuthorFilter },\n    } = renderHook(() => useAuthorFilter());\n    // flush promise queue\n    await act(() => Promise.resolve());\n    const filter = initializeAuthorFilter();\n    const authors = await filter.getPrimaryOptions();\n    expect(authors).toHaveLength(1);\n    expect(authors.at(0)).toMatchObject({\n      id: 1,\n      name: 'admin',\n    });\n  });\n\n  describe('initializeAuthorFilter', () => {\n    it('should initialize author filter data', async () => {\n      const {\n        result: { current: initializeAuthorFilter },\n      } = renderHook(() => useAuthorFilter());\n      // flush promise queue\n      await act(() => Promise.resolve());\n\n      // initialize filter\n      act(() => {\n        const filter = initializeAuthorFilter();\n        expect(filter.placeholder).toBe('All Authors');\n        expect(filter.ariaLabel).toBe(`Filter stories by author`);\n        expect(filter.noMatchesFoundLabel).toBe('No authors found');\n        expect(filter.searchPlaceholder).toBe('Search Authors');\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/test/useTaxonomyFilter.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useTaxonomyFilters from '../StoryFiltersProvider/taxonomy/useTaxonomyFilters';\n\njest.mock('../../../../api/useApi', () => {\n  const getTaxonomies = (args) => {\n    const taxonomies = [\n      {\n        slug: 'tax1',\n        hierarchical: true,\n        restBase: 'tax1_Base',\n        restPath: 'tax1/path',\n        labels: {\n          filterByItem: 'Filter by tax1',\n          allItems: 'All Tax1',\n          searchItems: 'Search Tax1',\n          notFound: 'No tax1s found',\n        },\n      },\n      {\n        slug: 'tax2',\n        hierarchical: false,\n        restBase: 'tax2_Base',\n        restPath: 'tax2/path',\n      },\n      {\n        slug: 'tax3',\n        hierarchical: true,\n        restBase: 'tax3_Base',\n        restPath: 'tax3/path',\n        labels: {\n          filterByItem: 'Filter by tax3',\n          allItems: 'All Tax3',\n          searchItems: 'Search Tax3',\n          notFound: 'No tax3s found',\n        },\n      },\n    ];\n    return Promise.resolve(\n      args.hierarchical\n        ? taxonomies.filter((taxonomy) => taxonomy.hierarchical)\n        : taxonomies\n    );\n  };\n  const getTaxonomyTerms = (restPath, args) => {\n    const fakeAPI = {\n      'tax1/path': [{ id: 1, name: 'tax1_term1' }],\n      'tax3/path': [\n        { id: 3, name: 'tax3_term1' },\n        { id: 4, name: 'tax3_term2' },\n      ],\n    };\n    let terms = fakeAPI[restPath];\n    if (args.search) {\n      terms = terms.filter((term) => term.name.includes(args.search));\n    }\n\n    return Promise.resolve(terms);\n  };\n  return {\n    __esModule: true,\n    default: function useApi() {\n      return {\n        getTaxonomies,\n        getTaxonomyTerms,\n      };\n    },\n  };\n});\n\ndescribe('useTaxonomyFilters', () => {\n  it('should initialize the hierarchial taxonomy filters data only', async () => {\n    const {\n      result: { current: initializeTaxonomyFilters },\n    } = renderHook(() => useTaxonomyFilters());\n    // flush promise queue\n    await act(() => Promise.resolve());\n\n    // taxonomy filters should only be hierarchical\n    const filters = await initializeTaxonomyFilters();\n    expect(filters).toHaveLength(2);\n\n    // should correctly set restPath\n    const filter3 = filters.find((f) => f.key === 'tax3_Base');\n    expect(filter3).toMatchObject({\n      restPath: 'tax3/path',\n    });\n\n    const filter1 = filters.find((f) => f.key === 'tax1_Base');\n    expect(filter1).toMatchObject({\n      restPath: 'tax1/path',\n    });\n  });\n\n  describe('initializeTaxonomyFilters', () => {\n    let initialize;\n    beforeEach(async () => {\n      const {\n        result: { current: initializeTaxonomyFilters },\n      } = renderHook(() => useTaxonomyFilters());\n\n      initialize = initializeTaxonomyFilters;\n\n      // flush promise queue\n      await act(() => Promise.resolve());\n    });\n\n    it('should initialize taxonomy filters data', async () => {\n      // initialize filters\n      const filters = await initialize();\n      expect(filters).toHaveLength(2);\n\n      const filter1 = filters.at(0);\n      expect(filter1.placeholder).toBe('All Tax1');\n      expect(filter1.ariaLabel).toBe(`Filter by tax1`);\n      expect(filter1.noMatchesFoundLabel).toBe('No tax1s found');\n      expect(filter1.searchPlaceholder).toBe('Search Tax1');\n    });\n\n    it('should use the correct taxonomy for getPrimaryOptions and query', async () => {\n      const filters = await initialize();\n      const filter1 = filters.at(0);\n      const filter2 = filters.at(1);\n\n      // should call getPrimaryOptions with tax1 taxonomy\n      const primaryOptions1 = await filter1.getPrimaryOptions.call();\n      expect(primaryOptions1).toStrictEqual([\n        {\n          id: 1,\n          name: 'tax1_term1',\n          restBase: 'tax1_Base',\n          restPath: 'tax1/path',\n        },\n      ]);\n      // should call query with tax1 taxonomy and search term\n      const query1 = await filter1.query('m1');\n      expect(query1).toStrictEqual([\n        {\n          id: 1,\n          name: 'tax1_term1',\n          restBase: 'tax1_Base',\n          restPath: 'tax1/path',\n        },\n      ]);\n\n      // should call getPrimaryOptions with tax3 taxonomy\n      const primaryOptions2 = await filter2.getPrimaryOptions.call();\n      expect(primaryOptions2).toStrictEqual([\n        {\n          id: 3,\n          name: 'tax3_term1',\n          restBase: 'tax3_Base',\n          restPath: 'tax3/path',\n        },\n        {\n          id: 4,\n          name: 'tax3_term2',\n          restBase: 'tax3_Base',\n          restPath: 'tax3/path',\n        },\n      ]);\n\n      // should call query with tax3 taxonomy and search term\n      const query2 = await filter2.query('m1');\n      expect(query2).toStrictEqual([\n        {\n          id: 3,\n          name: 'tax3_term1',\n          restBase: 'tax3_Base',\n          restPath: 'tax3/path',\n        },\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/filters/useStoryFilters.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { filterContext } from './StoryFiltersProvider';\n\nexport default function useStoryFilters(selector = identity) {\n  return useContextSelector(filterContext, selector);\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useMemo,\n  memo,\n  useCallback,\n  useDebouncedCallback,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport {\n  DASHBOARD_VIEWS,\n  STORY_SORT_MENU_ITEMS,\n  STORY_SORT_OPTIONS,\n  TEXT_INPUT_DEBOUNCE,\n} from '../../../../constants';\nimport {\n  StoriesPropType,\n  TotalStoriesByStatusPropType,\n} from '../../../../propTypes';\nimport { ViewPropTypes } from '../../../../utils/useStoryView';\nimport { useDashboardResultsLabel } from '../../../../utils';\nimport { BodyViewOptions, PageHeading } from '../../shared';\nimport { getSearchOptions } from '../../utils';\nimport useStoryFilters from '../filters/useStoryFilters';\nimport StoryStatusToggle from './storyStatusToggle';\n\nfunction Header({ initialPageReady, stories, totalStoriesByStatus, view }) {\n  const searchOptions = useMemo(() => getSearchOptions(stories), [stories]);\n\n  const { filters, sortObject, updateFilter, updateSort, registerFilters } =\n    useStoryFilters(\n      ({\n        state: { filters, sortObject },\n        actions: { updateFilter, updateSort, registerFilters },\n      }) => ({\n        filters,\n        updateFilter,\n        sortObject,\n        updateSort,\n        registerFilters,\n      })\n    );\n  const [dropDownFilters, statusFilterValue, searchFilterValue] =\n    useMemo(() => {\n      const status = filters.find(({ key }) => key === 'status');\n      const search = filters.find(({ key }) => key === 'search');\n      const rest = filters.filter(\n        ({ key }) => !['status', 'search'].includes(key)\n      );\n\n      return [rest, status?.filterId, search?.filterId];\n    }, [filters]);\n\n  const totalResults = useMemo(\n    () =>\n      (statusFilterValue?.split(',') || []).reduce(\n        (total, filterKey) => (total += totalStoriesByStatus[filterKey] || 0),\n        0\n      ),\n    [statusFilterValue, totalStoriesByStatus]\n  );\n\n  const resultsLabel = useDashboardResultsLabel({\n    currentFilter: statusFilterValue,\n    isActiveSearch: Boolean(searchFilterValue),\n    totalResults,\n    view: DASHBOARD_VIEWS.DASHBOARD,\n  });\n\n  const debouncedSearchChange = useDebouncedCallback(async (value) => {\n    await trackEvent('search', {\n      search_type: 'dashboard',\n      search_term: value,\n    });\n    updateFilter('search', { filterId: value });\n  }, TEXT_INPUT_DEBOUNCE);\n\n  useEffect(() => {\n    registerFilters([{ key: 'search' }]);\n  }, [registerFilters]);\n\n  const clearSearch = useCallback(\n    () => updateFilter('search', { filterId: null }),\n    [updateFilter]\n  );\n\n  return (\n    <>\n      <PageHeading\n        heading={__('Dashboard', 'web-stories')}\n        searchPlaceholder={__('Search Stories', 'web-stories')}\n        searchOptions={searchOptions}\n        handleSearchChange={debouncedSearchChange}\n        showSearch={initialPageReady}\n        searchValue={searchFilterValue}\n        onClear={clearSearch}\n      >\n        <StoryStatusToggle\n          initialPageReady={initialPageReady}\n          totalStoriesByStatus={totalStoriesByStatus}\n          currentStatus={statusFilterValue}\n        />\n      </PageHeading>\n\n      <BodyViewOptions\n        showGridToggle\n        filters={dropDownFilters}\n        showSortDropdown\n        resultsLabel={resultsLabel}\n        layoutStyle={view.style}\n        handleLayoutSelect={view.toggleStyle}\n        pageSortOptions={STORY_SORT_MENU_ITEMS}\n        pageSortDefaultOption={STORY_SORT_OPTIONS.LAST_MODIFIED}\n        handleSortChange={updateSort}\n        currentSort={sortObject}\n      />\n    </>\n  );\n}\n\nHeader.propTypes = {\n  initialPageReady: PropTypes.bool,\n  stories: StoriesPropType,\n  totalStoriesByStatus: TotalStoriesByStatusPropType,\n  view: ViewPropTypes.isRequired,\n};\n\nexport default memo(Header);\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/header/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport Header from '..';\nimport {\n  STORY_SORT_OPTIONS,\n  SORT_DIRECTION,\n  VIEW_STYLE,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport formattedStoriesArray from '../../../../../dataUtils/formattedStoriesArray';\nimport { Layout } from '../../../../../components';\n\nexport default {\n  title: 'Dashboard/Views/MyStories/Header',\n  component: Header,\n  args: {\n    status: 'all',\n    statusValue: STORY_STATUS.ALL,\n    value: STORY_SORT_OPTIONS.NAME,\n    direction: SORT_DIRECTION.ASC,\n    keyword: '',\n    style: VIEW_STYLE.GRID,\n    all: 32,\n    draft: 19,\n    publish: 13,\n  },\n  argTypes: {\n    setFilter: { action: 'set filter' },\n    setSort: { action: 'set sort' },\n    setDirection: { action: 'set sort direction' },\n    setKeyword: { action: 'set search' },\n    toggleStyle: { action: 'toggle view style' },\n    statusValue: { options: STORY_STATUS, control: 'select' },\n    value: {\n      options: STORY_SORT_OPTIONS,\n      control: 'radio',\n      name: 'Story sort options',\n    },\n    direction: { options: SORT_DIRECTION, control: 'radio' },\n    style: { options: VIEW_STYLE, control: 'radio' },\n  },\n  parameters: {\n    controls: {\n      include: [\n        'statusValue',\n        'Story sort options',\n        'direction',\n        'style',\n        'draft',\n        'publish',\n        'setSort',\n        'toggleStyle',\n        'keyword',\n      ],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const filter = {\n      status: args.status,\n      value: args.statusValue,\n      set: args.setFilter,\n    };\n    const sort = {\n      value: args.value,\n      direction: args.direction,\n      set: args.setSort,\n      setDirection: args.setDirection,\n    };\n    const search = {\n      keyword: args.keyword,\n      setKeyword: args.setKeyword,\n    };\n    const view = {\n      style: args.style,\n      toggleStyle: args.toggleStyle,\n      pageSize: { width: 309, height: 206 },\n    };\n    const totalStoriesByStatus = {\n      all: args.all,\n      draft: args.draft,\n      publish: args.publish,\n    };\n\n    const defaultProps = {\n      filter,\n      view,\n      search,\n      stories: formattedStoriesArray,\n      sort,\n      totalStoriesByStatus,\n    };\n    return (\n      <Layout.Provider>\n        <Header {...args} {...defaultProps} />\n      </Layout.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/header/storyStatusToggle.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useMemo } from '@googleforcreators/react';\nimport { Pill } from '@googleforcreators/design-system';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport useStoryFilters from '../filters/useStoryFilters';\nimport { DEFAULT_FILTERS, STORY_STATUSES } from '../../../../constants';\nimport { TotalStoriesByStatusPropType } from '../../../../propTypes';\n\nconst StyledPill = styled(Pill)`\n  margin: 0 2px;\n  white-space: nowrap;\n\n  & > span {\n    padding-left: 8px;\n    color: ${({ theme, isActive }) =>\n      isActive ? theme.colors.gray[20] : theme.colors.fg.tertiary};\n  }\n`;\n\nfunction StoryStatusToggle({\n  initialPageReady,\n  totalStoriesByStatus,\n  currentStatus,\n}) {\n  const { updateFilter, registerFilters } = useStoryFilters(\n    ({ actions: { updateFilter, registerFilters } }) => ({\n      updateFilter,\n      registerFilters,\n    })\n  );\n\n  const handleStatusChange = useCallback(\n    (value) => {\n      updateFilter('status', { filterId: value });\n    },\n    [updateFilter]\n  );\n\n  useEffect(() => {\n    registerFilters([\n      {\n        key: 'status',\n        filterId: DEFAULT_FILTERS.filters.status,\n      },\n    ]);\n  }, [registerFilters]);\n\n  /**\n   * The total stories based on the given filters\n   */\n  const totalStories = useMemo(\n    () =>\n      Object.keys(totalStoriesByStatus).reduce(\n        (prev, cur) => prev + totalStoriesByStatus[cur],\n        0\n      ),\n    [totalStoriesByStatus]\n  );\n\n  /**\n   * Set up the status data for the UI.\n   * Only show statuses that correlate to the filtered stories, and the current status.\n   */\n  const statuses = useMemo(() => {\n    return STORY_STATUSES.filter(({ status }) => {\n      return (\n        (Boolean(status in totalStoriesByStatus) &&\n          totalStoriesByStatus[status] > 0) ||\n        status === currentStatus\n      );\n    }).map(({ label, status, value }) => {\n      const count = totalStoriesByStatus[status];\n      const disabled = Boolean(!count);\n      const ariaLabel = sprintf(\n        /* translators: %s is story status */\n        __('Filter stories by %s', 'web-stories'),\n        label\n      );\n      const isActive = currentStatus === value;\n      return { ariaLabel, disabled, isActive, value, label, count };\n    });\n  }, [totalStoriesByStatus, currentStatus]);\n\n  if (\n    !initialPageReady ||\n    !totalStories ||\n    (totalStoriesByStatus && Object.keys(totalStoriesByStatus).length === 0)\n  ) {\n    return null;\n  }\n\n  return (\n    <>\n      {statuses.map(\n        ({ ariaLabel, disabled, isActive, value, label, count }) => {\n          return (\n            <StyledPill\n              key={value}\n              onClick={() => handleStatusChange(value)}\n              isActive={isActive}\n              disabled={disabled}\n              aria-label={ariaLabel}\n            >\n              {label}\n              <span>{count}</span>\n            </StyledPill>\n          );\n        }\n      )}\n    </>\n  );\n}\n\nStoryStatusToggle.propTypes = {\n  initialPageReady: PropTypes.bool,\n  totalStoriesByStatus: TotalStoriesByStatusPropType,\n  currentStatus: PropTypes.string,\n};\n\nexport default StoryStatusToggle;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/header/test/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  STORY_SORT_OPTIONS,\n  VIEW_STYLE,\n  STORY_STATUS,\n} from '../../../../../constants';\nimport LayoutProvider from '../../../../../components/layout/provider';\nimport { renderWithProviders } from '../../../../../testUtils';\nimport Header from '..';\nimport useStoryFilters from '../../filters/useStoryFilters';\n\njest.mock('../../filters/useStoryFilters', () => ({\n  ...jest.requireActual('../../filters/useStoryFilters'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\nconst mockUseStoryFilters = useStoryFilters;\n\nconst fakeStories = [\n  {\n    id: 1,\n    status: 'publish',\n    title: 'Story A',\n    pages: [{ id: '10' }],\n    bottomTargetAction: 'https://example.com',\n    editStoryLink: () => {},\n  },\n  {\n    id: 2,\n    status: 'draft',\n    title: 'Story B',\n    pages: [{ id: '20' }],\n    bottomTargetAction: 'https://example.com',\n    editStoryLink: () => {},\n  },\n  {\n    id: 3,\n    status: 'publish',\n    title: 'Story C',\n    pages: [{ id: '30' }],\n    bottomTargetAction: 'https://example.com',\n    editStoryLink: () => {},\n  },\n];\n\njest.mock('../../../../api/useApi', () => {\n  const getTaxonomies = () => {\n    return Promise.resolve([]);\n  };\n  const getTaxonomyTerms = () => {\n    return Promise.resolve([]);\n  };\n  return {\n    __esModule: true,\n    default: function useApi() {\n      return {\n        getTaxonomies,\n        getTaxonomyTerms,\n      };\n    },\n  };\n});\n\nconst updateSort = jest.fn();\nconst updateFilter = jest.fn();\n\nconst mockFilterState = {\n  filters: [\n    {\n      key: 'status',\n      filterId: STORY_STATUS.ALL,\n    },\n  ],\n  filtersObject: {},\n  sortObject: {\n    orderby: STORY_SORT_OPTIONS.DATE_CREATED,\n  },\n  registerFilters: () => {},\n  updateFilter,\n  updateSort,\n};\n\ndescribe('Dashboard <Header />', () => {\n  beforeEach(() => {\n    mockUseStoryFilters.mockImplementation(() => mockFilterState);\n  });\n\n  it('should have results label that says \"Viewing all stories\" on initial page view', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n    expect(screen.getByText('Viewing all stories')).toBeInTheDocument();\n  });\n\n  it('should have results label that says \"Viewing drafts\" when filter is set to drafts', () => {\n    mockUseStoryFilters.mockImplementation(() => ({\n      ...mockFilterState,\n      filters: [{ key: 'status', filterId: STORY_STATUS.DRAFT }],\n    }));\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n    expect(screen.getByText('Viewing drafts')).toBeInTheDocument();\n  });\n\n  it('should have 3 toggle buttons, one for each status that say how many items belong to that status', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          totalStoriesByStatus={{\n            all: 19,\n            [STORY_STATUS.DRAFT]: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n            [STORY_STATUS.FUTURE]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n\n    const allStoriesButton = screen.getByRole('button', {\n      name: /Filter stories by All Stories/,\n    });\n\n    const draftsButton = screen.getByRole('button', {\n      name: /Filter stories by Drafts/,\n    });\n    const publishedButton = screen.getByRole('button', {\n      name: /Filter stories by Published/,\n    });\n\n    const scheduledButton = screen.getByRole('button', {\n      name: /Filter stories by Scheduled/,\n    });\n\n    expect(allStoriesButton).toHaveTextContent('All Stories19');\n    expect(draftsButton).toHaveTextContent('Drafts9');\n    expect(publishedButton).toHaveTextContent('Published10');\n    expect(scheduledButton).toHaveTextContent('Scheduled10');\n\n    expect(screen.queryByText('Private')).not.toBeInTheDocument();\n  });\n\n  it('should show the private tab only when there are private stories.', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          sort={{ value: STORY_SORT_OPTIONS.NAME, set: jest.fn() }}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            private: 2,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n\n    const allStoriesButton = screen.getByRole('button', {\n      name: /Filter stories by All Stories/,\n    });\n\n    const draftsButton = screen.getByRole('button', {\n      name: /Filter stories by Drafts/,\n    });\n    const publishedButton = screen.getByRole('button', {\n      name: /Filter stories by Published/,\n    });\n    const privateButton = screen.getByRole('button', {\n      name: /Filter stories by Private/,\n    });\n\n    expect(allStoriesButton).toHaveTextContent('All Stories19');\n    expect(draftsButton).toHaveTextContent('Drafts9');\n    expect(publishedButton).toHaveTextContent('Published10');\n    expect(privateButton).toHaveTextContent('Private2');\n  });\n\n  it('should not show the private tab even if there are private stories when the user does not have permission.', () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          sort={{ value: STORY_SORT_OPTIONS.NAME, set: jest.fn() }}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n    const allStoriesButton = screen.getByRole('button', {\n      name: /Filter stories by All Stories/,\n    });\n\n    const draftsButton = screen.getByRole('button', {\n      name: /Filter stories by Drafts/,\n    });\n    const publishedButton = screen.getByRole('button', {\n      name: /Filter stories by Published/,\n    });\n    expect(allStoriesButton).toHaveTextContent('All Stories19');\n    expect(draftsButton).toHaveTextContent('Drafts9');\n    expect(publishedButton).toHaveTextContent('Published10');\n    expect(screen.queryByText('Private')).not.toBeInTheDocument();\n  });\n\n  it('should call the set keyword function when new text is searched', async () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          sort={{ value: STORY_SORT_OPTIONS.NAME, set: jest.fn() }}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n    fireEvent.change(screen.getByPlaceholderText('Search Stories'), {\n      target: { value: 'Hermione Granger' },\n    });\n    await waitFor(() => {\n      expect(updateFilter).toHaveBeenCalledWith('search', {\n        filterId: 'Hermione Granger',\n      });\n    });\n  });\n\n  it('should call the set sort function when a new sort is selected', async () => {\n    renderWithProviders(\n      <LayoutProvider>\n        <Header\n          stories={fakeStories}\n          totalStoriesByStatus={{\n            all: 19,\n            draft: 9,\n            [STORY_STATUS.PUBLISH]: 10,\n          }}\n          view={{\n            style: VIEW_STYLE.GRID,\n            pageSize: { width: 200, height: 300 },\n          }}\n          initialPageReady\n        />\n      </LayoutProvider>\n    );\n    fireEvent.click(screen.getByLabelText('Choose sort option for display'));\n    fireEvent.click(screen.getByText('Last Modified'));\n\n    await waitFor(() => {\n      expect(updateSort).toHaveBeenCalledWith({ orderby: 'modified' });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useMemo, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { ScrollToTop, Layout } from '../../../components';\nimport { useStoryView } from '../../../utils';\nimport { useConfig } from '../../config';\nimport useApi from '../../api/useApi';\nimport useStoryFilters from './filters/useStoryFilters';\nimport Content from './content';\nimport Header from './header';\nimport StoryFiltersProvider from './filters/StoryFiltersProvider';\n\nfunction MyStoriesView() {\n  const {\n    duplicateStory,\n    fetchStories,\n    trashStory,\n    updateStory,\n    allPagesFetched,\n    isLoading,\n    stories,\n    storiesOrderById,\n    totalPages,\n    totalStoriesByStatus,\n  } = useApi(\n    ({\n      actions: {\n        storyApi: { duplicateStory, fetchStories, trashStory, updateStory },\n      },\n      state: {\n        stories: {\n          allPagesFetched,\n          isLoading,\n          stories,\n          storiesOrderById,\n          totalPages,\n          totalStoriesByStatus,\n        },\n      },\n    }) => ({\n      duplicateStory,\n      fetchStories,\n      trashStory,\n      updateStory,\n      allPagesFetched,\n      isLoading,\n      stories,\n      storiesOrderById,\n      totalPages,\n      totalStoriesByStatus,\n    })\n  );\n  const { filtersObject, sortObject } = useStoryFilters(\n    ({ state: { filtersObject, sortObject } }) => ({\n      filtersObject,\n      sortObject,\n    })\n  );\n\n  const { apiCallbacks, canViewDefaultTemplates } = useConfig();\n  const isMountedRef = useRef(false);\n\n  useEffect(() => {\n    isMountedRef.current = true;\n\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  const { page, view, showStoriesWhileLoading, initialPageReady } =\n    useStoryView({\n      filtersObject,\n      sortObject,\n      isLoading,\n      totalPages,\n    });\n\n  useEffect(() => {\n    fetchStories({\n      page: page.value,\n      filters: filtersObject,\n      sort: sortObject,\n    });\n  }, [fetchStories, filtersObject, sortObject, page.value, apiCallbacks]);\n\n  const orderedStories = useMemo(() => {\n    return storiesOrderById.map((storyId) => {\n      return stories[storyId];\n    });\n  }, [stories, storiesOrderById]);\n\n  return (\n    <Layout.Provider>\n      <Header\n        initialPageReady={initialPageReady}\n        stories={orderedStories}\n        totalStoriesByStatus={totalStoriesByStatus}\n        view={view}\n      />\n\n      <Content\n        allPagesFetched={allPagesFetched}\n        canViewDefaultTemplates={canViewDefaultTemplates}\n        filtersObject={filtersObject}\n        loading={{\n          isLoading: isLoading,\n          showStoriesWhileLoading,\n        }}\n        page={page}\n        stories={orderedStories}\n        storyActions={{\n          duplicateStory,\n          trashStory,\n          updateStory,\n        }}\n        view={view}\n      />\n\n      <Layout.Fixed>\n        <ScrollToTop />\n      </Layout.Fixed>\n    </Layout.Provider>\n  );\n}\n\nexport default function MyStories() {\n  return (\n    <StoryFiltersProvider>\n      <MyStoriesView />\n    </StoryFiltersProvider>\n  );\n}\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/karma/myStories.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Fixture from '../../../../karma/fixture';\nimport {\n  STORY_STATUS,\n  STORY_STATUSES,\n  STORY_VIEWING_LABELS,\n  STORY_SORT_MENU_ITEMS,\n} from '../../../../constants';\nimport useApi from '../../../api/useApi';\n\ndescribe('CUJ: Creator can view their stories in grid view', () => {\n  let fixture;\n  let dashboardGridItems = [];\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    dashboardGridItems = fixture.screen.getAllByTestId(/^story-grid-item/);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getStoriesState() {\n    const {\n      state: { stories },\n    } = await fixture.renderHook(() => useApi());\n\n    return stories;\n  }\n\n  async function focusOnGridByKeyboard() {\n    let limit = 0;\n    const gridContainer = fixture.screen.getByTestId('dashboard-grid-list');\n\n    while (!gridContainer.contains(document.activeElement) && limit < 20) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('tab');\n      limit++;\n    }\n\n    if (!gridContainer.contains(document.activeElement)) {\n      throw new Error('could not focus on grid');\n    }\n  }\n\n  async function getContextMenuItem(contextMenuText, storyIndex = 0) {\n    const storyButtons = fixture.screen.getAllByTestId(/story-context-button-/);\n    const selectedStory = storyButtons[storyIndex];\n    await focusOnGridByKeyboard();\n\n    for (let i = 0; i <= storyIndex; i++) {\n      const expectedStory = storyButtons[i];\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('right');\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('tab');\n      expect(expectedStory).toEqual(document.activeElement);\n    }\n\n    // we should have focused the indicated story in the grid\n    expect(selectedStory).toEqual(document.activeElement);\n\n    await fixture.events.keyboard.press('Enter');\n\n    // now the focused item should be the first context menu item\n    const contextMenuLists = fixture.screen.getAllByTestId(/context-menu-list/);\n    const contextMenuList = contextMenuLists[storyIndex];\n\n    // it is focused on the link within the list\n    const contextMenuItem = within(contextMenuList).getByRole('menuitem', {\n      name: contextMenuText,\n    });\n\n    let limit = 0;\n    while (\n      document.activeElement.textContent !== contextMenuText &&\n      limit < 8\n    ) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('down');\n      limit++;\n    }\n\n    expect(contextMenuItem).toEqual(document.activeElement);\n    return contextMenuItem;\n  }\n\n  describe('Creator should see dashboard and be able to navigate', () => {\n    it('should render without aXe violations', async () => {\n      const { storiesOrderById } = await getStoriesState();\n\n      expect(dashboardGridItems.length).toEqual(storiesOrderById.length);\n    });\n\n    it('should navigate to Explore Templates', async () => {\n      const navigation = fixture.screen.queryByRole('navigation');\n      const utils = within(navigation);\n\n      const exploreTemplatesMenuItem = utils.getByText(/^Explore Templates/);\n\n      expect(exploreTemplatesMenuItem).toBeTruthy();\n\n      await fixture.events.click(exploreTemplatesMenuItem);\n      const templatesGridEl = await fixture.screen.findByText(\n        'Viewing all templates'\n      );\n      expect(templatesGridEl).toBeTruthy();\n    });\n  });\n\n  describe('Creator should be prevented from performing basic updates on locked stories from dashboard', () => {\n    let utils;\n    let moreOptionsButton;\n\n    beforeEach(async () => {\n      const lockedStory = dashboardGridItems[1];\n      await fixture.events.hover(lockedStory);\n\n      utils = within(lockedStory);\n      moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n    });\n\n    it('should not Rename a locked story', () => {\n      const rename = utils.getByText(/^Rename/);\n      expect(rename.hasAttribute('disabled')).toBe(true);\n    });\n\n    it('should not delete a locked story', () => {\n      const deleteStory = utils.getByText(/^Delete/);\n      expect(deleteStory.hasAttribute('disabled')).toBe(true);\n    });\n  });\n\n  describe('Creator should be able to perform basic updates to stories from dashboard', () => {\n    let utils;\n    let moreOptionsButton;\n\n    beforeEach(async () => {\n      const firstStory = dashboardGridItems[0];\n      await fixture.events.hover(firstStory);\n\n      utils = within(firstStory);\n      moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n    });\n\n    it('should Rename a story', async () => {\n      const rename = utils.getByText(/^Rename/);\n      await fixture.events.click(rename);\n\n      const input = fixture.screen.getByRole('textbox');\n      const inputLength = input.value.length;\n\n      for (let iter = 0; iter < inputLength; iter++) {\n        // disable eslint to prevent overlapping .act calls\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('Backspace');\n      }\n\n      await fixture.events.keyboard.type('A New Title');\n\n      await fixture.events.keyboard.press('Enter');\n\n      expect(\n        utils.getByRole('heading', { level: 3, name: 'A New Title' })\n      ).toBeTruthy();\n    });\n\n    it('should Duplicate a story', async () => {\n      const duplicate = utils.getByText(/^Duplicate/);\n      await fixture.events.click(duplicate);\n\n      const updatedStories = fixture.screen.getAllByTestId(/^story-grid-item/);\n      const copiedStory = within(updatedStories[0]).getByRole('heading', {\n        level: 3,\n      });\n      expect(copiedStory.innerText).toContain('(Copy)');\n    });\n\n    it('should Delete a story', async () => {\n      const deleteStory = utils.getByText(/^Delete/);\n      await fixture.events.click(deleteStory);\n\n      const confirmDeleteButton = fixture.screen.getByRole('button', {\n        name: /^Confirm deleting story/,\n      });\n\n      await fixture.events.click(confirmDeleteButton);\n\n      expect(fixture.screen.getAllByTestId(/^story-grid-item/).length).toEqual(\n        dashboardGridItems.length - 1\n      );\n    });\n\n    it('should not Delete a story if Cancel is clicked in the confirmation modal', async () => {\n      const deleteStory = utils.getByText(/^Delete/);\n      await fixture.events.click(deleteStory);\n\n      const cancel = fixture.screen.getByRole('button', {\n        name: /^Cancel deleting story/,\n      });\n\n      await fixture.events.click(cancel);\n\n      expect(fixture.screen.getAllByTestId(/^story-grid-item/).length).toEqual(\n        dashboardGridItems.length\n      );\n    });\n  });\n\n  describe('Creator can filter their stories by status', () => {\n    it('should switch to the Drafts Tab', async () => {\n      const { stories } = await getStoriesState();\n      const numDrafts = Object.values(stories).filter(\n        ({ status }) => status === STORY_STATUS.DRAFT\n      ).length;\n\n      expect(numDrafts).toBeGreaterThan(0);\n\n      const draftsTabButton = fixture.screen.getByRole('button', {\n        name: new RegExp('^Filter stories by ' + STORY_STATUSES[1].label),\n      });\n\n      await fixture.events.click(draftsTabButton);\n\n      const viewDraftsText = fixture.screen.getByText(\n        (_, node) =>\n          node.innerHTML === STORY_VIEWING_LABELS[STORY_STATUS.DRAFT](numDrafts)\n      );\n\n      expect(viewDraftsText).toBeTruthy();\n\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n      expect(storyElements.length).toEqual(numDrafts);\n    });\n\n    it('should switch to the Published Tab', async () => {\n      const { stories } = await getStoriesState();\n      const numPublished = Object.values(stories).filter(\n        ({ status }) => status === STORY_STATUS.PUBLISH\n      ).length;\n\n      expect(numPublished).toBeGreaterThan(0);\n\n      const publishedTabButton = fixture.screen.getByRole('button', {\n        name: new RegExp('^Filter stories by ' + STORY_STATUSES[3].label),\n      });\n\n      expect(publishedTabButton).toBeTruthy();\n\n      await fixture.events.click(publishedTabButton);\n\n      const viewPublishedText = fixture.screen.getByText(\n        (_, node) =>\n          node.innerHTML ===\n          STORY_VIEWING_LABELS[STORY_STATUS.PUBLISH](numPublished)\n      );\n      expect(viewPublishedText).toBeTruthy();\n\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n      expect(storyElements.length).toEqual(numPublished);\n    });\n  });\n\n  describe('Creator can search dashboard stories by story names', () => {\n    it('should filter stories using the search input', async () => {\n      const { stories } = await getStoriesState();\n\n      const firstStoryTitle = Object.values(stories)[0].title;\n\n      const searchInput = fixture.screen.getByPlaceholderText('Search Stories');\n\n      expect(searchInput).toBeTruthy();\n\n      await fixture.events.focus(searchInput);\n\n      await fixture.events.keyboard.type(firstStoryTitle);\n\n      // Wait for the debounce\n      await fixture.events.sleep(500);\n\n      const storyElements =\n        await fixture.screen.findAllByTestId(/^story-context-menu-/);\n\n      expect(storyElements.length).toEqual(\n        Object.values(stories).filter(({ title }) =>\n          title.includes(firstStoryTitle)\n        ).length\n      );\n    });\n\n    it('should look at options in search menu and select one with keyboard', async () => {\n      const { stories } = await getStoriesState();\n\n      const firstStoryTitle = Object.values(stories)[0].title;\n\n      const searchInput = fixture.screen.getByPlaceholderText('Search Stories');\n\n      expect(searchInput).toBeTruthy();\n\n      await fixture.events.focus(searchInput);\n\n      await fixture.events.keyboard.type(firstStoryTitle.substring(0, 1)); // get first to characters of title so that other options come up too\n\n      // Wait for the debounce\n      await fixture.events.sleep(300);\n\n      const searchOptions = fixture.screen.getByRole('listbox');\n      expect(searchOptions).toBeTruthy();\n\n      const activeListItems = within(searchOptions).queryAllByRole('option');\n\n      await fixture.events.keyboard.press('down');\n\n      expect(activeListItems[0]).toEqual(document.activeElement);\n\n      // focus should move to the search input when keydown on 'up' from first list item\n      await fixture.events.keyboard.press('up');\n\n      expect(searchInput).toEqual(document.activeElement);\n      await fixture.events.sleep(300);\n      // key down to the bottom of the available search options\n      // plus once more beyond available search options to make sure focus stays intact\n      for (let iter = 0; iter < activeListItems.length + 1; iter++) {\n        // disable eslint to prevent overlapping .act calls\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('down');\n      }\n      await fixture.events.sleep(300);\n      expect(activeListItems[activeListItems.length - 1]).toBe(\n        document.activeElement\n      );\n\n      await fixture.events.keyboard.press('Enter');\n\n      const selectedStoryTitle =\n        Object.values(stories)[activeListItems.length - 1].title;\n\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n\n      expect(storyElements.length).toEqual(\n        Object.values(stories).filter(({ title }) =>\n          title.includes(selectedStoryTitle)\n        ).length\n      );\n    });\n  });\n\n  describe('Creator can sort their stories', () => {\n    let sortDropdown;\n    beforeEach(() => {\n      sortDropdown = fixture.screen.getByLabelText(\n        'Choose sort option for display'\n      );\n    });\n\n    const getRenderedStoriesById = () => {\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n      const renderedStoriesById = storyElements.map(({ dataset }) =>\n        Number(dataset['testid'].split('-').slice(-1)[0])\n      );\n      return renderedStoriesById;\n    };\n\n    const getStoriesOrderById = () => getStoriesState();\n\n    it('should sort by Date Created', async () => {\n      expect(sortDropdown).toBeTruthy();\n\n      await fixture.events.click(sortDropdown);\n\n      const dateCreated = fixture.screen.getByText(\n        new RegExp(`^${STORY_SORT_MENU_ITEMS[1].label}$`)\n      );\n\n      expect(dateCreated).toBeTruthy();\n\n      await fixture.events.click(dateCreated);\n\n      const renderedStoriesById = getRenderedStoriesById();\n      const { storiesOrderById } = await getStoriesOrderById();\n\n      expect(renderedStoriesById).toEqual(storiesOrderById);\n    });\n\n    it('should sort by Last Modified by default', async () => {\n      const { storiesOrderById } = await getStoriesOrderById();\n      const renderedStoriesById = getRenderedStoriesById();\n\n      expect(renderedStoriesById).toEqual(storiesOrderById);\n    });\n\n    it('should sort by Name', async () => {\n      expect(sortDropdown).toBeTruthy();\n\n      await fixture.events.click(sortDropdown);\n\n      const name = fixture.screen.getByText(\n        new RegExp(`^${STORY_SORT_MENU_ITEMS[0].label}$`)\n      );\n\n      expect(name).toBeTruthy();\n\n      await fixture.events.click(name);\n\n      const renderedStoriesById = getRenderedStoriesById();\n      const { storiesOrderById } = await getStoriesOrderById();\n      expect(renderedStoriesById).toEqual(storiesOrderById);\n    });\n\n    it('should sort by Created By', async () => {\n      expect(sortDropdown).toBeTruthy();\n\n      await fixture.events.click(sortDropdown);\n\n      const createdBy = fixture.screen.getByText(\n        new RegExp(`^${STORY_SORT_MENU_ITEMS[3].label}$`)\n      );\n\n      expect(createdBy).toBeTruthy();\n\n      await fixture.events.click(createdBy);\n\n      const renderedStoriesById = getRenderedStoriesById();\n      const { storiesOrderById } = await getStoriesOrderById();\n      expect(renderedStoriesById).toEqual(storiesOrderById);\n    });\n\n    it('should filter by author', async () => {\n      const originalStoryAuthorsNames = fixture.screen\n        .getAllByTestId(/^story-grid-item/)\n        .map((storyThumb) => storyThumb.innerText);\n\n      // click the author toggle\n      const authorDropdown = fixture.screen.getByLabelText(\n        'Filter stories by author'\n      );\n      expect(authorDropdown).toBeTruthy();\n      await fixture.events.click(authorDropdown);\n\n      // find all author filters\n      const authorSelect = await fixture.screen.findByLabelText(\n        /^Option List Selector$/\n      );\n      expect(authorSelect).toBeTruthy();\n\n      // click the first author\n      const firstAuthor = within(authorSelect).getAllByRole('option')?.[0];\n      expect(firstAuthor).toBeTruthy();\n      const firstAuthorName = firstAuthor.innerText;\n      await fixture.events.click(firstAuthor);\n\n      // Check that not all the stories were from the first author originally\n      expect(\n        originalStoryAuthorsNames.some((name) => name !== firstAuthorName)\n      ).toBeTruthy();\n\n      // see that all rendered stories are by the clicked author\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n      for (const storyThumb of storyElements) {\n        const authorEl = within(storyThumb).getByText(firstAuthorName);\n        expect(authorEl).toBeDefined();\n      }\n    });\n\n    it('should filter by category', async () => {\n      const { stories } = await getStoriesState();\n      let renderedStoriesById = getRenderedStoriesById();\n      // click the category dropdown\n      const categoryDropdown =\n        fixture.screen.getByLabelText('Filter by category');\n      expect(categoryDropdown).toBeTruthy();\n      await fixture.events.click(categoryDropdown);\n\n      // find all category filters\n      const categorySelect = await fixture.screen.findByLabelText(\n        /^Option List Selector$/\n      );\n      expect(categorySelect).toBeTruthy();\n\n      // click the first category\n      const firstCategory = within(categorySelect).getAllByRole('option')?.[0];\n      expect(firstCategory).toBeTruthy();\n      const firstCategoryName = firstCategory.innerText;\n      await fixture.events.click(firstCategory);\n\n      // Check that not all the stories have the first category originally\n      const found = renderedStoriesById.map(\n        (id) => !stories[id].categories.includes(firstCategoryName)\n      );\n      expect(found.length).toBeGreaterThan(0);\n\n      // see that all rendered stories have the selected category\n      renderedStoriesById = getRenderedStoriesById();\n      renderedStoriesById.every((id) =>\n        stories[id].categories.includes(firstCategoryName)\n      );\n    });\n  });\n\n  describe('Creator can navigate and use the Dashboard via keyboard', () => {\n    let storyCards = [];\n\n    beforeEach(async () => {\n      storyCards = fixture.screen.getAllByTestId(/story-context-button-/);\n      await focusOnGridByKeyboard();\n    });\n\n    it('should navigate the grid via keyboard', async () => {\n      for (let i = 0; i < storyCards.length; i++) {\n        const expectedStory = storyCards[i];\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('right');\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('tab');\n        expect(expectedStory).toEqual(document.activeElement);\n      }\n    });\n\n    it('should focus on context menu items via keyboard', async () => {\n      const [selectedStory] = storyCards;\n      await fixture.events.keyboard.press('right');\n      await fixture.events.keyboard.press('tab');\n      // we should have focused the first story menu in the grid\n      expect(selectedStory).toEqual(document.activeElement);\n\n      const [activeStoryContextMenu] =\n        fixture.screen.getAllByTestId(/^story-context-menu-/);\n\n      await fixture.events.keyboard.press('Enter');\n\n      // now the focused item should be the first context menu item\n      const [contextMenuList] = within(activeStoryContextMenu).getAllByTestId(\n        /context-menu-list/\n      );\n      await expectAsync(contextMenuList).toHaveNoViolations();\n      // it is focused on the link within the list\n      const [firstContextMenuItem, secondContextMenuItem] =\n        within(contextMenuList).getAllByRole('menuitem');\n\n      expect(firstContextMenuItem.innerText).toEqual(\n        document.activeElement.innerText\n      );\n\n      await fixture.events.keyboard.press('down');\n\n      expect(secondContextMenuItem.innerText).toEqual(\n        document.activeElement.innerText\n      );\n    });\n\n    it('should rename a story via keyboard', async () => {\n      await getContextMenuItem('Rename');\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('Backspace');\n      await fixture.events.keyboard.type('A New Title');\n      await fixture.events.keyboard.press('Enter');\n      const firstStory = dashboardGridItems[0];\n      const { getByRole } = within(firstStory);\n      expect(\n        getByRole('heading', { level: 3, name: 'A New Title' })\n      ).toBeTruthy();\n    });\n\n    it('should delete a story via keyboard', async () => {\n      let stories = fixture.screen.getAllByTestId(/^story-context-menu-/);\n      // count the original number of stories\n      const initialNumStories = stories.length;\n\n      // focus the delete context menu item of the first story with the keyboard\n      await getContextMenuItem('Delete Story');\n\n      // delete the story and confirm deletion\n      await fixture.events.keyboard.press('Enter');\n      const confirmDeleteButton = fixture.screen.getByRole('button', {\n        name: /^Confirm deleting story/,\n      });\n      let limit = 0;\n      while (\n        !confirmDeleteButton.contains(document.activeElement) &&\n        limit < 3\n      ) {\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('tab');\n        limit++;\n      }\n\n      // confirm deletion\n      await fixture.events.keyboard.press('Enter');\n\n      // count the new number of stories\n      stories = fixture.screen.getAllByTestId(/^story-context-menu-/);\n      expect(stories.length).toEqual(initialNumStories - 1);\n    });\n\n    it('should duplicate a story via keyboard', async () => {\n      // count the initial number of stories\n      const initialNumStories = dashboardGridItems.length;\n\n      //focus the duplicate item of the context menu of the first story\n      await getContextMenuItem('Duplicate');\n\n      expect(document.activeElement.innerText).toEqual('Duplicate');\n      // confirm duplication\n      await fixture.events.keyboard.press('Enter');\n\n      // count the new number of stories\n      const updatedStories = fixture.screen.getAllByTestId(/^story-grid-item/);\n      expect(updatedStories.length).toEqual(initialNumStories + 1);\n\n      // the copied story is now the first story and contains (Copy)\n      const firstStory = updatedStories[0];\n      const utils = within(firstStory);\n\n      const copiedStory = utils.getByRole('heading', { level: 3 });\n      expect(copiedStory.innerText).toContain('(Copy)');\n    });\n\n    it('should retain focus on menu close', async () => {\n      const allItemGridLinks = fixture.screen.getAllByTestId(\n        /story-editor-grid-link/\n      );\n\n      const storyIndex = 0;\n      const selectedStory = allItemGridLinks[storyIndex];\n      // focus the delete context menu item of the first story with the keyboard\n      // test cancelling deletion of the second story (not the default first story)\n      // to make sure focus is retained\n      await getContextMenuItem('Delete Story', storyIndex);\n\n      // delete the story and confirm deletion\n      await fixture.events.keyboard.press('Enter');\n      const cancelDeleteButton = fixture.screen.getByRole('button', {\n        name: /^Cancel/,\n      });\n      let limit = 0;\n      while (\n        !cancelDeleteButton.contains(document.activeElement) &&\n        limit < 3\n      ) {\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('tab');\n        limit++;\n      }\n\n      // confirm deletion\n      await fixture.events.keyboard.press('Enter');\n\n      // focus should return to the second story\n      expect(selectedStory).toEqual(document.activeElement);\n    });\n\n    it('should exit the grid and re-focus the first item', async () => {\n      const allItemGridLinks = fixture.screen.getAllByTestId(\n        /story-editor-grid-link/\n      );\n\n      const firstStory = allItemGridLinks[0];\n      const lastStory = allItemGridLinks[allItemGridLinks.length - 1];\n\n      for (let i = 0; i < allItemGridLinks.length; i++) {\n        const expectedStory = allItemGridLinks[i];\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('right');\n        expect(expectedStory).toEqual(document.activeElement);\n      }\n      expect(lastStory).toEqual(document.activeElement);\n\n      const searchInput = fixture.screen.getByPlaceholderText('Search Stories');\n      expect(searchInput).toBeTruthy();\n      await fixture.events.focus(searchInput);\n\n      await focusOnGridByKeyboard();\n      await fixture.events.keyboard.press('right');\n      expect(firstStory).toEqual(document.activeElement);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/myStories/karma/myStoriesList.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\nimport { getRelativeDisplayDate } from '@googleforcreators/date';\n\n/**\n * Internal dependencies\n */\nimport Fixture from '../../../../karma/fixture';\nimport { VIEW_STYLE_LABELS, VIEW_STYLE } from '../../../../constants';\nimport useApi from '../../../api/useApi';\n\ndescribe('CUJ: Creator can view their stories in list view: ', () => {\n  let fixture;\n  let listViewButton;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    listViewButton = fixture.screen.getByLabelText(\n      new RegExp(`^${VIEW_STYLE_LABELS[VIEW_STYLE.GRID]}$`)\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getStoriesState() {\n    const {\n      state: { stories },\n    } = await fixture.renderHook(() => useApi());\n\n    return stories;\n  }\n\n  function isElementVisible(element) {\n    return Boolean(\n      element.offsetWidth ||\n      element.offsetHeight ||\n      element.getClientRects().length\n    );\n  }\n\n  const clickListView = async () => {\n    expect(listViewButton).toBeTruthy();\n\n    await fixture.events.click(listViewButton);\n  };\n\n  const enterListView = async () => {\n    expect(listViewButton).toBeTruthy();\n    await fixture.events.focus(listViewButton);\n    await fixture.events.keyboard.press('Enter');\n  };\n\n  describe('Creator can see stories in list view', () => {\n    it('should switch to List View', async () => {\n      await clickListView();\n\n      const listViewTable = fixture.screen.getByTestId('story-list-view');\n\n      // await expectAsync(listViewTable).toHaveNoViolations();\n\n      expect(listViewTable).toBeTruthy();\n\n      await fixture.snapshot('List View');\n    });\n\n    it('should switch to List View and back to Grid View', async () => {\n      await clickListView();\n\n      const initialGridViewItems =\n        fixture.screen.queryAllByTestId(/^story-grid-item/);\n      expect(initialGridViewItems.length).toBe(0);\n\n      const listViewTable = fixture.screen.getByTestId('story-list-view');\n\n      expect(listViewTable).toBeTruthy();\n      const gridViewButton = fixture.screen.getByLabelText(\n        new RegExp(`^${VIEW_STYLE_LABELS[VIEW_STYLE.LIST]}$`)\n      );\n\n      await fixture.events.click(gridViewButton);\n\n      const storyElements = fixture.screen.getAllByTestId(/^story-grid-item/);\n\n      const { storiesOrderById } = await getStoriesState();\n\n      expect(storyElements.length).toEqual(storiesOrderById.length);\n\n      await fixture.snapshot('Grid View');\n    });\n\n    it('should Rename a story', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      await clickListView();\n\n      // drop the header row using slice\n      const rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const utils = within(rows[0]);\n\n      const titleCell = utils.getByRole('heading', {\n        name: storiesSortedByModified[0].title,\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const rename = utils.getByText(/^Rename/);\n\n      await fixture.events.click(rename);\n\n      const input = utils.getByRole('textbox');\n\n      const inputLength = input.value.length;\n\n      for (let iter = 0; iter < inputLength; iter++) {\n        // disable eslint to prevent overlapping .act calls\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('Backspace');\n      }\n\n      await fixture.events.keyboard.type('A New Title');\n\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.snapshot('Rename story');\n\n      expect(utils.getByText(/^A New Title$/)).toBeTruthy();\n    });\n\n    it('should Duplicate a story', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      const gridContainer = fixture.screen.getByTestId('dashboard-grid-list');\n\n      await fixture.events.focus(gridContainer);\n\n      await clickListView();\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      let utils = within(rows[0]);\n\n      const titleCell = utils.getByRole('cell', {\n        name: storiesSortedByModified[0].title,\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const duplicate = utils.getByText(/^Duplicate/);\n\n      await fixture.events.click(duplicate);\n\n      await fixture.snapshot('Duplicate story');\n\n      // requery rows\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesSortedByModified.length + 1);\n\n      utils = within(rows[0]);\n\n      const copiedStory = utils.queryAllByText(/Copy/)[0];\n\n      expect(copiedStory).toBeTruthy();\n    });\n\n    it('should Delete a story', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      await clickListView();\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const utils = within(rows[0]);\n\n      const titleCell = utils.getByRole('cell', {\n        name: storiesSortedByModified[0].title,\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const deleteButton = utils.getByText(/^Delete/);\n\n      await fixture.events.click(deleteButton);\n\n      const confirmDeleteButton = fixture.screen.getByRole('button', {\n        name: /^Confirm deleting/,\n      });\n\n      await fixture.snapshot('Delete story');\n\n      await fixture.events.click(confirmDeleteButton);\n\n      // requery rows\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesSortedByModified.length - 1);\n    });\n\n    it('should not Delete a story if Cancel is clicked in the confirmation modal', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      await clickListView();\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const utils = within(rows[0]);\n\n      const titleCell = utils.getByRole('cell', {\n        name: storiesSortedByModified[0].title,\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const deleteButton = utils.getByText(/^Delete/);\n\n      await fixture.events.click(deleteButton);\n\n      const cancel = fixture.screen.getByRole('button', {\n        name: /^Cancel deleting story/,\n      });\n\n      await fixture.events.click(cancel);\n\n      // requery rows\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesSortedByModified.length);\n    });\n  });\n\n  describe('Creator should be prevented from performing basic updates on locked stories from dashboard list view', () => {\n    it('should not Rename a locked story', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      await clickListView();\n\n      // drop the header row using slice\n      const rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const utils = within(rows[1]);\n\n      const titleCell = utils.getByRole('heading', {\n        name: new RegExp(`^${storiesSortedByModified[1].title}`),\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const rename = utils.getByText(/^Rename/);\n      expect(rename.hasAttribute('disabled')).toBe(true);\n    });\n\n    it('should not Delete a locked story', async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n      const storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n\n      await clickListView();\n\n      // drop the header row using slice\n      const rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const utils = within(rows[1]);\n      const titleCell = utils.getByRole('heading', {\n        name: new RegExp(`^${storiesSortedByModified[1].title}`),\n      });\n\n      await fixture.events.hover(titleCell);\n\n      const moreOptionsButton = utils.getByRole('button', {\n        name: /^Context menu for/,\n      });\n\n      await fixture.events.click(moreOptionsButton);\n\n      const deleteButton = utils.getByText(/^Delete/);\n      expect(deleteButton.hasAttribute('disabled')).toBe(true);\n    });\n  });\n\n  describe('Creator can sort their stories (last modified / date created / author / title)', () => {\n    beforeEach(async () => {\n      await enterListView();\n    });\n\n    it('should sort by Title in List View', async () => {\n      // There is a second hidden span with the same text\n      const titleHeader = fixture.screen.getAllByText(/^Title/)[0];\n\n      await fixture.events.click(titleHeader);\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storieTitlesSortedByTitle = storiesOrderById.map(\n        (id) => stories[id].title\n      );\n\n      // title is the second column\n      let rowTitles = rows.map((row) => row.children[1].innerText);\n\n      expect(rowTitles).toEqual(storieTitlesSortedByTitle);\n\n      // sort by descending\n      await fixture.events.click(titleHeader);\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // title is the second column\n      rowTitles = rows.map((row) => row.children[1].innerText);\n\n      expect(rowTitles).toEqual(storieTitlesSortedByTitle.reverse());\n    });\n\n    it('should sort by Author in List View', async () => {\n      const authorHeader = fixture.screen.getByText(/^Author/);\n\n      await fixture.events.click(authorHeader);\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storiesAuthorsSortedByAuthor = storiesOrderById.map(\n        (id) => stories[id].author.name\n      );\n\n      // author is the third column\n      let rowAuthors = rows.map((row) => row.children[2].innerText);\n\n      expect(rowAuthors).toEqual(storiesAuthorsSortedByAuthor);\n\n      // sort by descending\n      await fixture.events.click(authorHeader);\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // author is the third column\n      rowAuthors = rows.map((row) => row.children[2].innerText);\n\n      expect(rowAuthors).toEqual(storiesAuthorsSortedByAuthor.reverse());\n    });\n\n    it('should sort by Date Created in List View', async () => {\n      const dateCreatedHeader = fixture.screen.getByText(/^Date Created/);\n\n      await fixture.events.click(dateCreatedHeader);\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storiesDateCreatedSortedByDateCreated = storiesOrderById.map((id) =>\n        getRelativeDisplayDate(stories[id].createdGmt)\n      );\n\n      let rowDateCreatedValues = rows.map((row) => row.children[3].innerText);\n\n      expect(rowDateCreatedValues).toEqual(\n        storiesDateCreatedSortedByDateCreated\n      );\n\n      // sort by ascending\n      await fixture.events.click(dateCreatedHeader);\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // author is the fourth column\n      rowDateCreatedValues = rows.map((row) => row.children[3].innerText);\n\n      expect(rowDateCreatedValues).toEqual(\n        storiesDateCreatedSortedByDateCreated.reverse()\n      );\n    });\n\n    it('should sort by Last Modified in List View', async () => {\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storieModifiedSortedByModified = storiesOrderById.map((id) =>\n        getRelativeDisplayDate(stories[id].modifiedGmt)\n      );\n\n      // Last Modified is the fifth column\n      let rowModifiedValues = rows.map((row) => row.children[4].innerText);\n\n      expect(rowModifiedValues).toEqual(storieModifiedSortedByModified);\n\n      // sort ascending\n      const [table] = fixture.screen.getAllByTestId('story-list-view');\n      const utils = within(table);\n      const lastModifiedHeader = utils.getByText(/^Last Modified/);\n\n      await fixture.events.click(lastModifiedHeader);\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      rowModifiedValues = rows.map((row) => row.children[4].innerText);\n\n      expect(rowModifiedValues).toEqual(\n        storieModifiedSortedByModified.reverse()\n      );\n    });\n\n    it('should sort by Title in List View with keyboard', async () => {\n      // There is a second hidden span with the same text\n      const titleHeader = fixture.screen.getAllByText(/^Title/)[0];\n\n      await fixture.events.focus(titleHeader);\n      await fixture.events.keyboard.press('Enter');\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storieTitlesSortedByTitle = storiesOrderById.map(\n        (id) => stories[id].title\n      );\n\n      // title is the second column\n      let rowTitles = rows.map((row) => row.children[1].innerText);\n\n      expect(rowTitles).toEqual(storieTitlesSortedByTitle);\n\n      // sort by descending\n      await fixture.events.keyboard.press('Enter');\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // title is the second column\n      rowTitles = rows.map((row) => row.children[1].innerText);\n\n      expect(rowTitles).toEqual(storieTitlesSortedByTitle.reverse());\n    });\n\n    it('should sort by Author in List View with keyboard', async () => {\n      const authorHeader = fixture.screen.getByText(/^Author/);\n\n      await fixture.events.focus(authorHeader);\n      await fixture.events.keyboard.press('Enter');\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storiesAuthorsSortedByAuthor = storiesOrderById.map(\n        (id) => stories[id].author.name\n      );\n\n      // author is the third column\n      let rowAuthors = rows.map((row) => row.children[2].innerText);\n\n      expect(rowAuthors).toEqual(storiesAuthorsSortedByAuthor);\n\n      // sort by descending\n      await fixture.events.keyboard.press('Enter');\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // author is the third column\n      rowAuthors = rows.map((row) => row.children[2].innerText);\n\n      expect(rowAuthors).toEqual(storiesAuthorsSortedByAuthor.reverse());\n    });\n\n    it('should sort by Date Created in List View with keyboard', async () => {\n      const dateCreatedHeader = fixture.screen.getByText(/^Date Created/);\n\n      await fixture.events.focus(dateCreatedHeader);\n      await fixture.events.keyboard.press('Enter');\n\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storiesDateCreatedSortedByDateCreated = storiesOrderById.map((id) =>\n        getRelativeDisplayDate(stories[id].createdGmt)\n      );\n\n      let rowDateCreatedValues = rows.map((row) => row.children[3].innerText);\n\n      expect(rowDateCreatedValues).toEqual(\n        storiesDateCreatedSortedByDateCreated\n      );\n\n      // sort by ascending\n      await fixture.events.keyboard.press('Enter');\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      // author is the fourth column\n      rowDateCreatedValues = rows.map((row) => row.children[3].innerText);\n\n      expect(rowDateCreatedValues).toEqual(\n        storiesDateCreatedSortedByDateCreated.reverse()\n      );\n    });\n\n    it('should show default sort by Last Modified in List View with keyboard', async () => {\n      // drop the header row using slice\n      let rows = fixture.screen.getAllByRole('row').slice(1);\n\n      const { stories, storiesOrderById } = await getStoriesState();\n\n      expect(rows.length).toEqual(storiesOrderById.length);\n\n      const storieModifiedSortedByModified = storiesOrderById.map((id) =>\n        getRelativeDisplayDate(stories[id].modifiedGmt)\n      );\n\n      // Last Modified is the fifth column\n      let rowModifiedValues = rows.map((row) => row.children[4].innerText);\n\n      expect(rowModifiedValues).toEqual(storieModifiedSortedByModified);\n\n      // sort ascending\n      const [table] = fixture.screen.getAllByTestId('story-list-view');\n      const utils = within(table);\n      const lastModifiedHeader = utils.getByText(/^Last Modified/);\n\n      await fixture.events.focus(lastModifiedHeader);\n      await fixture.events.keyboard.press('Enter');\n\n      rows = fixture.screen.getAllByRole('row').slice(1);\n\n      rowModifiedValues = rows.map((row) => row.children[4].innerText);\n\n      expect(rowModifiedValues).toEqual(\n        storieModifiedSortedByModified.reverse()\n      );\n    });\n  });\n\n  describe('Creator can navigate list view using keyboard: Tab through each story in the list', () => {\n    let storiesSortedByModified = [];\n\n    beforeEach(async () => {\n      const { stories, storiesOrderById } = await getStoriesState();\n      storiesSortedByModified = storiesOrderById.map((id) => stories[id]);\n      // switch to list view\n      await clickListView();\n\n      // place focus on last modified header\n      const [table] = fixture.screen.getAllByTestId('story-list-view');\n      const utils = within(table);\n      const lastModifiedHeader = utils.getByText(/^Last Modified/);\n      await fixture.events.focus(lastModifiedHeader);\n    });\n\n    it('should be able to tab to story title', async () => {\n      // tabbing from Last Modified should get us to title\n      await fixture.events.keyboard.press('Tab');\n\n      const title = await document.activeElement.innerText;\n      expect(title).toContain(storiesSortedByModified[0].title);\n    });\n\n    it('should be able to tab to story menu control', async () => {\n      // drop the header row using slice\n      const rows = fixture.screen.getAllByRole('row').slice(1);\n      const { getByText } = within(rows[0]);\n\n      // Rename shouldn't be found until menu is open\n      expect(isElementVisible(getByText(/^Rename/))).toBeFalse();\n\n      // tabbing from Last Modified should get us to title\n      await fixture.events.keyboard.press('Tab');\n\n      // tabbing from title should move to menu control\n      await fixture.events.keyboard.press('Tab');\n\n      // hitting enter should open menu\n      await fixture.events.keyboard.press('Enter');\n\n      // Rename should be findable\n      expect(isElementVisible(getByText(/^Rename/))).toBeTrue();\n    });\n\n    it('should be able to tab to another story title', async () => {\n      // tabbing from Last Modified should get us to title\n      await fixture.events.keyboard.press('Tab');\n\n      // tabbing from title should move to menu control\n      await fixture.events.keyboard.press('Tab');\n\n      // tabbing from menu control should move to next story title\n      await fixture.events.keyboard.press('Tab');\n\n      const title = await document.activeElement.innerText;\n      expect(title).toContain(storiesSortedByModified[1].title);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/bodyViewOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { TranslateWithMarkup, __ } from '@googleforcreators/i18n';\nimport {\n  Text,\n  TextSize,\n  DatalistDropdown,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { StandardViewContentGutter, ViewStyleBar } from '../../../components';\nimport useStoryFilters from '../myStories/filters/useStoryFilters';\nimport SortDropDown from './sortDropDown';\n\nconst FILTER_MAX_WIDTH = 350;\n\nconst DisplayFormatContainer = styled.div`\n  display: grid;\n  gap: 1rem;\n  min-height: 76px;\n  grid-template-columns: 1fr auto auto;\n  justify-content: start;\n  align-items: center;\n  margin-top: -10px;\n`;\n\nconst StorySortDropdownContainer = styled.div`\n  margin: auto 8px;\n  align-self: flex-end;\n`;\n\nconst ControlsContainer = styled.div`\n  display: flex;\n  flex-wrap: wrap;\n  margin: 1rem 0;\n  row-gap: 1rem;\n  justify-self: end;\n`;\n\nconst BodyViewOptionsHeader = styled.div``;\nconst StyledDatalist = styled(DatalistDropdown)`\n  max-width: ${FILTER_MAX_WIDTH}px;\n`;\n\nexport default function BodyViewOptions({\n  handleLayoutSelect,\n  resultsLabel,\n  layoutStyle,\n  pageSortOptions = [],\n  pageSortDefaultOption,\n  showGridToggle,\n  showSortDropdown,\n  filters = [],\n  currentSort,\n  handleSortChange,\n}) {\n  const { updateFilter } = useStoryFilters(({ actions: { updateFilter } }) => ({\n    updateFilter,\n  }));\n\n  return (\n    <StandardViewContentGutter>\n      <BodyViewOptionsHeader id=\"body-view-options-header\" />\n      <DisplayFormatContainer>\n        <Text.Span size={TextSize.Small}>\n          <TranslateWithMarkup>{resultsLabel}</TranslateWithMarkup>\n        </Text.Span>\n        <ControlsContainer>\n          {filters?.length\n            ? filters.map((filter) => (\n                <StorySortDropdownContainer\n                  key={filter.key}\n                  title={filter.placeholder}\n                >\n                  <StyledDatalist\n                    hasSearch\n                    hasDropDownBorder\n                    searchResultsLabel={__('Search results', 'web-stories')}\n                    aria-label={filter.ariaLabel}\n                    onChange={({ id }) => {\n                      updateFilter(filter.key, {\n                        filterId: id,\n                      });\n                    }}\n                    getOptionsByQuery={filter.query}\n                    getPrimaryOptions={filter.getPrimaryOptions}\n                    selectedId={filter.filterId}\n                    placeholder={filter.placeholder}\n                    noMatchesFoundLabel={filter.noMatchesFoundLabel}\n                    searchPlaceholder={filter.searchPlaceholder}\n                    offsetOverride\n                    maxWidth={FILTER_MAX_WIDTH}\n                    containerStyleOverrides={css`\n                      flex-direction: column;\n                    `}\n                  />\n                </StorySortDropdownContainer>\n              ))\n            : null}\n          {showSortDropdown && (\n            <StorySortDropdownContainer>\n              <SortDropDown\n                pageSortOptions={pageSortOptions}\n                pageSortDefaultOption={pageSortDefaultOption}\n                currentSort={currentSort}\n                handleSortChange={handleSortChange}\n              />\n            </StorySortDropdownContainer>\n          )}\n        </ControlsContainer>\n        {showGridToggle && (\n          <ViewStyleBar\n            layoutStyle={layoutStyle}\n            onPress={handleLayoutSelect}\n          />\n        )}\n      </DisplayFormatContainer>\n    </StandardViewContentGutter>\n  );\n}\n\nBodyViewOptions.propTypes = {\n  handleLayoutSelect: PropTypes.func,\n  layoutStyle: PropTypes.string.isRequired,\n  resultsLabel: PropTypes.string.isRequired,\n  showGridToggle: PropTypes.bool,\n  showSortDropdown: PropTypes.bool,\n  filters: PropTypes.array,\n  pageSortOptions: PropTypes.arrayOf(\n    PropTypes.shape({\n      value: PropTypes.string,\n      label: PropTypes.string,\n    })\n  ),\n  pageSortDefaultOption: PropTypes.string,\n  currentSort: PropTypes.shape({\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n  }),\n  handleSortChange: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/emptyContentMessage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { DesertColor } from '@googleforcreators/design-system';\n\nconst Message = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  max-width: 400px;\n  margin: 20vh auto;\n\n  & > * {\n    text-align: center;\n    margin: 0 auto;\n  }\n\n  /* Sometimes children will contain button or anchor as cta. */\n  button,\n  a {\n    margin-top: 48px;\n  }\n`;\n\nconst EmptyImage = styled(DesertColor)`\n  margin-bottom: 48px;\n`;\nfunction EmptyContentMessage({ children }) {\n  return (\n    <Message>\n      <EmptyImage aria-hidden width={274} height={118} />\n      {children}\n    </Message>\n  );\n}\n\nEmptyContentMessage.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default EmptyContentMessage;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/grid/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n// Foundational styled components that are\n// shared by grid instances to create\n// the final presentation of grid items\n\n// Gradient overlays the grid item poster\nexport const Gradient = styled.div`\n  position: absolute;\n  bottom: 0;\n  height: 67%;\n  width: 100%;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.gradient.posterOverlay};\n`;\n\n// Holds grid item content\nexport const Scrim = styled.div`\n  position: absolute;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  box-sizing: border-box;\n  display: flex;\n  flex-direction: column;\n  justify-content: flex-end;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.opacity.black3};\n`;\n\n// Keeps grid item position contained\nexport const Container = styled.div`\n  position: relative;\n`;\n\n// Displays grid item image if available\n// as background of grid item area\nexport const Poster = styled.div`\n  height: 100%;\n  width: 100%;\n  object-fit: cover;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.gradient.placeholder};\n`;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as BodyViewOptions } from './bodyViewOptions';\nexport { default as EmptyContentMessage } from './emptyContentMessage';\nexport { default as PageHeading } from './pageHeading';\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/pageHeading.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Display,\n  Search,\n  TextSize,\n  noop,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { NavMenuButton, StandardViewContentGutter } from '../../../components';\n\nconst HeadingContainer = styled(StandardViewContentGutter)`\n  display: flex;\n  align-items: center;\n  flex-wrap: wrap;\n  justify-content: space-between;\n  margin-bottom: 16px;\n  padding-top: 48px;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.secondary};\n`;\n\nconst StyledHeadline = styled(Display)`\n  display: flex;\n  align-items: center;\n  margin-right: 28px;\n  padding-bottom: 24px;\n  white-space: nowrap;\n`;\n\nconst HeadlineFilters = styled.div`\n  display: flex;\n  align-items: center;\n  margin: auto 0 auto 0;\n  padding-bottom: 24px;\n`;\n\nconst HeaderSearch = styled.div`\n  width: 208px;\n  max-width: 208px;\n  min-width: 208px;\n  margin: auto 0;\n  padding-bottom: 24px;\n`;\n\nconst PageHeading = ({\n  children,\n  heading,\n  searchPlaceholder,\n  searchOptions = [],\n  showSearch,\n  handleSearchChange,\n  searchValue,\n  onClear = noop,\n}) => {\n  return (\n    <HeadingContainer>\n      <StyledHeadline as=\"h2\" size={TextSize.Small}>\n        <NavMenuButton showOnlyOnSmallViewport />\n        {heading}\n      </StyledHeadline>\n      {children && <HeadlineFilters>{children}</HeadlineFilters>}\n      {showSearch && (\n        <HeaderSearch>\n          <Search\n            placeholder={searchPlaceholder}\n            searchValue={searchValue}\n            options={searchOptions}\n            handleSearchValueChange={handleSearchChange}\n            onClear={onClear}\n            emptyText={__('No options available', 'web-stories')}\n          />\n        </HeaderSearch>\n      )}\n    </HeadingContainer>\n  );\n};\n\nPageHeading.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n  handleSearchChange: PropTypes.func,\n  heading: PropTypes.string.isRequired,\n  onClear: PropTypes.func,\n  searchOptions: PropTypes.arrayOf(PropTypes.object),\n  searchPlaceholder: PropTypes.string,\n  searchValue: PropTypes.string,\n  showSearch: PropTypes.bool,\n};\n\nexport default PageHeading;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/sortDropDown.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { DropDown } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { DROPDOWN_TYPES } from '../../../constants';\n\nconst StyledDropDown = styled(DropDown)`\n  width: 210px;\n`;\n\nfunction SortDropDown({\n  pageSortOptions,\n  pageSortDefaultOption,\n  currentSort,\n  handleSortChange,\n}) {\n  const _handleSortChange = useCallback(\n    (_, orderby) => {\n      handleSortChange({ orderby });\n    },\n    [handleSortChange]\n  );\n\n  return (\n    <StyledDropDown\n      ariaLabel={__('Choose sort option for display', 'web-stories')}\n      options={pageSortOptions}\n      type={DROPDOWN_TYPES.DropDown}\n      selectedValue={currentSort?.orderby || pageSortDefaultOption}\n      onMenuItemClick={_handleSortChange}\n    />\n  );\n}\n\nSortDropDown.propTypes = {\n  pageSortOptions: PropTypes.arrayOf(\n    PropTypes.shape({\n      value: PropTypes.string,\n      label: PropTypes.string,\n    })\n  ),\n  pageSortDefaultOption: PropTypes.string,\n  currentSort: PropTypes.shape({\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n  }),\n  handleSortChange: PropTypes.func.isRequired,\n};\n\nexport default SortDropDown;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/stories/emptyContentMessage.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { EmptyContentMessage } from '..';\n\nexport default {\n  title: 'Dashboard/Views/Shared/EmptyContentMessage',\n  args: {\n    message: 'default content to display',\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <EmptyContentMessage>{args.message}</EmptyContentMessage>;\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/shared/stories/pageHeading.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { PageHeading } from '..';\nimport { NavProvider, LeftRail } from '../../../../components';\n\nexport default {\n  title: 'Dashboard/Views/Shared/PageHeading',\n  component: PageHeading,\n  args: {\n    showSearch: false,\n    searchValue: 'value',\n    heading: 'Dashboard',\n    searchPlaceholder: 'Find Stories',\n  },\n  argTypes: {\n    handleSearchChange: {\n      action: 'Search with value',\n    },\n  },\n  parameters: {\n    controls: {\n      exclude: ['searchOptions', 'children', 'onClear'],\n    },\n  },\n};\n\nconst InnerContent = styled.div`\n  background-color: red;\n  width: 100%;\n  height: 50%;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <NavProvider>\n        <LeftRail />\n        <PageHeading\n          searchOptions={[]}\n          handleSearchChange={(value) => args.handleSearchChange(value)}\n          {...args}\n        >\n          <InnerContent />\n        </PageHeading>\n      </NavProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/composeTemplateFilter.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { TEMPLATE_META_DATA_TYPES } from '../constants';\n\n/**\n * Takes an array of template meta data filter entries\n * and composes them into a function that takes a template\n * and returns true if the template satisfies any of the\n * meta data filters.\n *\n * @param {Array} filters filter entries to compose\n * @return {Function} function that takes a template and returns true or false\n */\nfunction composeTemplateFilter(filters) {\n  return (template) => {\n    return (\n      !filters ||\n      filters.some((filter) => {\n        switch (filter?.type) {\n          case TEMPLATE_META_DATA_TYPES.TAG:\n            return template.tags\n              .map((tag) => tag.toLowerCase())\n              .includes(filter.value.toLowerCase());\n\n          case TEMPLATE_META_DATA_TYPES.COLOR:\n            return template.colors\n              .map((color) => color.label.toLowerCase())\n              .includes(filter.value.toLowerCase());\n\n          case TEMPLATE_META_DATA_TYPES.VERTICAL:\n            return template.vertical\n              .toLowerCase()\n              .includes(filter.value.toLowerCase());\n\n          case TEMPLATE_META_DATA_TYPES.TITLE:\n            return template.title\n              .toLowerCase()\n              .includes(filter.value.toLowerCase());\n\n          default:\n            return true;\n        }\n      })\n    );\n  };\n}\n\nexport default composeTemplateFilter;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/getSearchOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction getSearchOptions(options) {\n  return options.reduce((acc, option) => {\n    if (!option.title || option?.title.trim().length <= 0) {\n      return acc;\n    }\n    return [\n      ...acc,\n      {\n        label: option.title,\n        value: option.title,\n      },\n    ];\n  }, []);\n}\n\nexport default getSearchOptions;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/getTemplateFilters.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { uniqueEntriesByKey } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { TEMPLATE_META_DATA_TYPES } from '../constants';\n\n/**\n * Takes an dictionary of templates and extracts their metadata\n * to return an array of meta data entries compatible with the\n * dashboard header search options\n *\n * @param {Object} templates templates dictionary keyed by id\n * @return {Array<Object>} array of entries\n */\nfunction getTemplateFilters(templates) {\n  const templatesArr = Object.values(templates);\n\n  const colors = templatesArr\n    .flatMap((t) => t.colors)\n    .map((c) => ({\n      label: c.family,\n      value: c.family,\n      type: TEMPLATE_META_DATA_TYPES.COLOR,\n    }));\n\n  const tags = templatesArr\n    .flatMap((t) => t.tags)\n    .map((tag) => ({\n      label: tag,\n      value: tag,\n      type: TEMPLATE_META_DATA_TYPES.TAG,\n    }));\n\n  const verticals = templatesArr\n    .map((t) => t.vertical)\n    .map((vertical) => ({\n      label: vertical,\n      value: vertical,\n      type: TEMPLATE_META_DATA_TYPES.VERTICAL,\n    }));\n\n  const title = templatesArr.map((t) => ({\n    label: t.title,\n    value: t.title,\n    type: TEMPLATE_META_DATA_TYPES.TITLE,\n  }));\n\n  return [\n    ...uniqueEntriesByKey(tags, 'label'),\n    ...uniqueEntriesByKey(colors, 'label'),\n    ...uniqueEntriesByKey(verticals, 'label'),\n    ...uniqueEntriesByKey(title, 'label'),\n  ];\n}\n\nexport default getTemplateFilters;\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as getSearchOptions } from './getSearchOptions';\nexport { default as getTemplateFilters } from './getTemplateFilters';\nexport { default as composeTemplateFilter } from './composeTemplateFilter';\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/test/composeTemplateFilter.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport composeTemplateFilter from '../composeTemplateFilter';\nimport { TEMPLATE_META_DATA_TYPES } from '../../constants';\n\ndescribe('composeTemplateFilter', () => {\n  it('filters a template properly given a set of meta data entries', () => {\n    const filter = composeTemplateFilter([\n      { label: 'red', value: 'red', type: TEMPLATE_META_DATA_TYPES.COLOR },\n      { label: 'red', value: 'red', type: TEMPLATE_META_DATA_TYPES.TAG },\n      {\n        label: 'Travel',\n        value: 'Travel',\n        type: TEMPLATE_META_DATA_TYPES.VERTICAL,\n      },\n      {\n        label: 'Travel The World',\n        value: 'Travel The World',\n        type: TEMPLATE_META_DATA_TYPES.TITLE,\n      },\n    ]);\n\n    // tags filter correctly\n    expect(\n      filter({\n        tags: ['red'],\n        colors: [{ label: 'green' }],\n        vertical: 'Books',\n        title: 'Book Title',\n      })\n    ).toBeTruthy();\n\n    // colors filter correctly\n    expect(\n      filter({\n        tags: ['blue'],\n        colors: [{ label: 'red' }],\n        vertical: 'Books',\n        title: 'Book Title',\n      })\n    ).toBeTruthy();\n\n    // verticals filter correctly\n    expect(\n      filter({\n        tags: ['blue'],\n        colors: [{ label: 'blue' }],\n        vertical: 'Travel',\n        title: 'Travel Title',\n      })\n    ).toBeTruthy();\n\n    // title filter correctly\n    expect(\n      filter({\n        tags: ['blue'],\n        colors: [{ label: 'blue' }],\n        vertical: 'Books',\n        title: 'Travel The World',\n      })\n    ).toBeTruthy();\n\n    // exclusion filters correctly\n    expect(\n      filter({\n        tags: ['blue'],\n        colors: [{ label: 'blue' }],\n        vertical: 'Books',\n        title: 'Book Title',\n      })\n    ).not.toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/test/getSearchOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getSearchOptions from '../getSearchOptions';\n\nconst initialData = [\n  { id: 94, title: 'Maltese Falcon' },\n  { id: 65, title: 'Rear Window' },\n  { id: 78, title: 'Psycho' },\n  { id: 12, title: 'The Birds' },\n  { id: 2, title: 'Casa Blanca' },\n  { id: 7, title: 'Valley of the Dolls' },\n  { id: 8, title: 'Wrath of Khan' },\n  { id: 999, noGoodKey: 'Princess Bride' },\n  { id: 89, title: '' },\n  { id: 876, title: undefined },\n  { id: 76, title: null },\n  { id: 796, title: false },\n];\n\ndescribe('getSearchOptions', () => {\n  it('should shape an array of objects, returning label and value based on title', () => {\n    const searchOptions = getSearchOptions(initialData);\n\n    expect(searchOptions).toMatchObject([\n      { label: 'Maltese Falcon', value: 'Maltese Falcon' },\n      { label: 'Rear Window', value: 'Rear Window' },\n      { label: 'Psycho', value: 'Psycho' },\n      { label: 'The Birds', value: 'The Birds' },\n      { label: 'Casa Blanca', value: 'Casa Blanca' },\n      { label: 'Valley of the Dolls', value: 'Valley of the Dolls' },\n      { label: 'Wrath of Khan', value: 'Wrath of Khan' },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/app/views/utils/test/getTemplateFilters.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport getTemplateFilters from '../getTemplateFilters';\nimport { TEMPLATE_META_DATA_TYPES } from '../../constants';\n\ndescribe('getTemplateFilters', () => {\n  it('returns unique meta data entries', () => {\n    const templates = [\n      {\n        colors: [\n          { family: 'blue', label: 'blue' },\n          { family: 'green', label: 'green' },\n          { family: 'red', label: 'red' },\n        ],\n        tags: ['Greece', 'Italy', 'Spain'],\n        vertical: 'Travel',\n        title: 'Travel The World',\n      },\n      {\n        colors: [{ family: 'red', label: 'red' }],\n        tags: ['Reading', 'I might like tv better', 'red'],\n        vertical: 'Books',\n        title: 'All the books',\n      },\n    ];\n    expect(getTemplateFilters(templates)).toStrictEqual([\n      { label: 'Greece', value: 'Greece', type: TEMPLATE_META_DATA_TYPES.TAG },\n      { label: 'Italy', value: 'Italy', type: TEMPLATE_META_DATA_TYPES.TAG },\n      { label: 'Spain', value: 'Spain', type: TEMPLATE_META_DATA_TYPES.TAG },\n      {\n        label: 'Reading',\n        value: 'Reading',\n        type: TEMPLATE_META_DATA_TYPES.TAG,\n      },\n      {\n        label: 'I might like tv better',\n        value: 'I might like tv better',\n        type: TEMPLATE_META_DATA_TYPES.TAG,\n      },\n      { label: 'red', value: 'red', type: TEMPLATE_META_DATA_TYPES.TAG },\n      { label: 'blue', value: 'blue', type: TEMPLATE_META_DATA_TYPES.COLOR },\n      { label: 'green', value: 'green', type: TEMPLATE_META_DATA_TYPES.COLOR },\n      { label: 'red', value: 'red', type: TEMPLATE_META_DATA_TYPES.COLOR },\n      {\n        label: 'Travel',\n        value: 'Travel',\n        type: TEMPLATE_META_DATA_TYPES.VERTICAL,\n      },\n      {\n        label: 'Books',\n        value: 'Books',\n        type: TEMPLATE_META_DATA_TYPES.VERTICAL,\n      },\n      {\n        label: 'Travel The World',\n        value: 'Travel The World',\n        type: TEMPLATE_META_DATA_TYPES.TITLE,\n      },\n      {\n        label: 'All the books',\n        value: 'All the books',\n        type: TEMPLATE_META_DATA_TYPES.TITLE,\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGallery/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { Button, ButtonType } from '@googleforcreators/design-system';\n\nconst pictureCss = css`\n  picture {\n    display: block;\n    & > img {\n      display: block;\n      height: 100%;\n      width: 100%;\n      object-fit: fill;\n      border-radius: ${({ theme }) => theme.borders.radius.medium};\n      border: ${({ theme }) =>\n        `1px solid ${theme.colors.border.defaultNormal}`};\n    }\n  }\n`;\nexport const GalleryContainer = styled.div`\n  flex: 1;\n  display: flex;\n  justify-content: space-between;\n  align-items: start;\n`;\n\nexport const DisplayPage = styled.div`\n  overflow: hidden;\n  width: 38.6%;\n  margin-left: 2.1%;\n\n  ${pictureCss}\n\n  @media screen and (min-width: 1600px) {\n    width: 45.2%;\n    margin-left: 2.4%;\n  }\n`;\n\nDisplayPage.propTypes = {\n  $isThreeRows: PropTypes.bool,\n};\n\nexport const Thumbnails = styled.div`\n  position: relative;\n  display: grid;\n  width: 52.3%;\n  grid-template-columns: repeat(3, 1fr);\n  column-gap: 8px;\n  row-gap: 16px;\n  margin-right: 16px;\n\n  @media screen and (min-width: 1600px) {\n    width: 59.3%;\n    grid-template-columns: repeat(4, 1fr);\n  }\n`;\n\nexport const ThumbnailButton = styled(Button).attrs({\n  type: ButtonType.Plain,\n})`\n  display: block;\n  height: 100%;\n  padding: 0;\n  border: none;\n  background-color: transparent;\n  position: relative;\n  &:active {\n    background-color: transparent;\n  }\n  ${({ $isSelected, theme }) =>\n    $isSelected &&\n    css`\n      &:after {\n        content: '';\n        position: absolute;\n        box-sizing: border-box;\n        width: 100%;\n        height: 100%;\n        display: block;\n        top: 0;\n        right: 0;\n        border-radius: ${theme.borders.radius.medium};\n        border: 4px solid ${theme.colors.interactiveBg.active};\n      }\n    `}\n  ${pictureCss};\n`;\nThumbnailButton.propTypes = {\n  $isSelected: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGallery/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { useGridViewKeys } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  DEFAULT_GRID_IMG_HEIGHT,\n  DEFAULT_GRID_IMG_WIDTH,\n} from '../../constants';\nimport {\n  GalleryContainer,\n  ThumbnailButton,\n  Thumbnails,\n  DisplayPage,\n} from './components';\n\nfunction getPosterAltCopy(pageNumber) {\n  return sprintf(\n    /* translators: %s: page number. */\n    __('Poster of template page %s', 'web-stories'),\n    pageNumber\n  );\n}\n\nfunction CardGallery({ galleryPosters, isRTL, galleryLabel }) {\n  const [selectedGridItemIndex, setSelectedGridItemIndex] = useState(0);\n  const [focusedGridItemIndex, setFocusedGridItemIndex] = useState();\n  const containerRef = useRef();\n  const gridRef = useRef();\n  const postersRef = useRef({});\n\n  const handleMiniCardClick = useCallback((index) => {\n    setSelectedGridItemIndex(index);\n    setFocusedGridItemIndex(index);\n  }, []);\n\n  const handleGalleryItemFocus = useCallback((index) => {\n    setFocusedGridItemIndex(index);\n  }, []);\n\n  useEffect(() => {\n    // Reset state when posters update\n    if (galleryPosters) {\n      setSelectedGridItemIndex(0);\n      setFocusedGridItemIndex();\n    }\n  }, [galleryPosters]);\n\n  useGridViewKeys({\n    containerRef,\n    gridRef,\n    itemRefs: postersRef,\n    isRTL,\n    currentItemId: focusedGridItemIndex,\n    items: galleryPosters,\n  });\n\n  const GalleryItems = useMemo(() => {\n    return galleryPosters.map((poster, index) => {\n      const key = `gallery_item_${index}`;\n      const pageNumber = index + 1;\n      // If there's not a focused index we want to fall back to the selected grid item\n      const isFocusIndex = focusedGridItemIndex\n        ? focusedGridItemIndex === index\n        : selectedGridItemIndex === index;\n\n      return (\n        <div\n          key={key}\n          ref={(el) => {\n            postersRef.current[index] = el;\n          }}\n          onFocus={() => handleGalleryItemFocus(index)}\n        >\n          <ThumbnailButton\n            $isSelected={selectedGridItemIndex === index}\n            tabIndex={isFocusIndex ? 0 : -1}\n            onClick={() => handleMiniCardClick(index)}\n            aria-label={\n              selectedGridItemIndex === index\n                ? sprintf(\n                    /* translators: %s: page number. */\n                    __('Page %s (current page)', 'web-stories'),\n                    pageNumber\n                  )\n                : sprintf(\n                    /* translators: %s: page number. */\n                    __('Page %s', 'web-stories'),\n                    pageNumber\n                  )\n            }\n          >\n            <picture>\n              <source srcSet={poster.webp} type=\"image/webp\" />\n              <source srcSet={poster.png} type=\"image/png\" />\n              <img\n                src={poster.png}\n                decoding=\"async\"\n                alt={getPosterAltCopy(pageNumber)}\n                width={DEFAULT_GRID_IMG_WIDTH}\n                height={DEFAULT_GRID_IMG_HEIGHT}\n              />\n            </picture>\n          </ThumbnailButton>\n        </div>\n      );\n    });\n  }, [\n    galleryPosters,\n    selectedGridItemIndex,\n    focusedGridItemIndex,\n    handleGalleryItemFocus,\n    handleMiniCardClick,\n  ]);\n\n  return (\n    <GalleryContainer ref={containerRef}>\n      <Thumbnails\n        ref={gridRef}\n        role=\"group\"\n        aria-label={galleryLabel}\n        data-testid=\"mini-cards-container\"\n      >\n        {GalleryItems}\n      </Thumbnails>\n      <DisplayPage>\n        {galleryPosters[selectedGridItemIndex] && (\n          <picture>\n            <source\n              srcSet={galleryPosters[selectedGridItemIndex].webp}\n              type=\"image/webp\"\n            />\n            <source\n              srcSet={galleryPosters[selectedGridItemIndex].png}\n              type=\"image/png\"\n            />\n            <img\n              src={galleryPosters[selectedGridItemIndex].png}\n              decoding=\"async\"\n              alt={sprintf(\n                /* translators: %s: active preview page number */\n                __('Active Page Preview - Page %s', 'web-stories'),\n                selectedGridItemIndex + 1\n              )}\n              width={DEFAULT_GRID_IMG_WIDTH}\n              height={DEFAULT_GRID_IMG_HEIGHT}\n            />\n          </picture>\n        )}\n      </DisplayPage>\n    </GalleryContainer>\n  );\n}\n\nCardGallery.propTypes = {\n  galleryPosters: PropTypes.arrayOf(\n    PropTypes.shape({\n      png: PropTypes.string,\n      webp: PropTypes.string,\n      id: PropTypes.number,\n    })\n  ).isRequired,\n  isRTL: PropTypes.bool,\n  galleryLabel: PropTypes.string.isRequired,\n};\n\nexport default CardGallery;\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGallery/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport CardGallery from '..';\n\nconst demoPosterGroup = [\n  {\n    id: 0,\n    webp: 'https://placekitten.com/g/200/300',\n    png: 'https://placekitten.com/g/200/300',\n  },\n  {\n    id: 1,\n    webp: 'https://placekitten.com/g/200/300',\n    png: 'https://placekitten.com/g/200/300',\n  },\n  {\n    id: 2,\n    webp: 'https://placekitten.com/g/200/300',\n    png: 'https://placekitten.com/g/200/300',\n  },\n  {\n    id: 3,\n    webp: 'https://placekitten.com/g/200/300',\n    png: 'https://placekitten.com/g/200/300',\n  },\n];\nexport default {\n  title: 'Dashboard/Components/CardGallery',\n  component: CardGallery,\n  args: {\n    isRTL: false,\n    galleryLabel: 'my aria label text',\n  },\n  parameters: {\n    controls: {\n      exclude: ['galleryPosters'],\n    },\n  },\n};\n\nconst CardGalleryContainer = styled.div`\n  padding: 20px;\n`;\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <CardGalleryContainer>\n        <CardGallery galleryPosters={demoPosterGroup} {...args} />\n      </CardGalleryContainer>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGrid/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { forwardRef } from '@googleforcreators/react';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { PageSizePropType } from '../../propTypes';\nimport { GRID_SPACING } from '../../constants';\n\nconst DashboardGrid = styled.div`\n  display: grid;\n  width: 100%;\n  grid-column-gap: ${GRID_SPACING.COLUMN_GAP}px;\n  grid-row-gap: ${GRID_SPACING.ROW_GAP}px;\n  grid-template-columns: ${({ columnWidth }) => `\n    repeat(auto-fill, ${columnWidth}px)`};\n  grid-template-rows: ${({ columnHeight }) =>\n    `minmax(${columnHeight}px, auto)`};\n  scroll-margin-top: 30vh;\n\n  ${({ theme }) => css`\n    &:focus-visible {\n      ${themeHelpers.focusCSS(theme.colors.border.focus)};\n    }\n  `};\n`;\nDashboardGrid.propTypes = {\n  columnHeight: PropTypes.number,\n  columnWidth: PropTypes.number,\n};\n\nconst CardGrid = forwardRef(function CardGrid(\n  { ariaLabel, children, pageSize },\n  ref\n) {\n  return (\n    <DashboardGrid\n      ref={ref}\n      role=\"list\"\n      data-testid={'dashboard-grid-list'}\n      /* eslint-disable-next-line styled-components-a11y/no-noninteractive-tabindex --\n       * We need to focus this div to engage with `useGridViewKeys`\n       * which is critical to avoiding focus traps for keyboard users.\n       **/\n      tabIndex={0}\n      aria-label={ariaLabel}\n      columnWidth={pageSize.width}\n      columnHeight={pageSize.height}\n    >\n      {children}\n    </DashboardGrid>\n  );\n});\n\nCardGrid.propTypes = {\n  ariaLabel: PropTypes.string,\n  children: PropTypes.node.isRequired,\n  pageSize: PageSizePropType.isRequired,\n};\n\nexport default CardGrid;\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGrid/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { STORYBOOK_PAGE_SIZE } from '../../../storybookUtils';\nimport { CardGridItem } from '../..';\nimport CardGrid from '..';\n\nexport default {\n  title: 'Dashboard/Components/CardGrid',\n  component: CardGrid,\n  args: {\n    message: 'Sample Story Content',\n  },\n};\n\nconst Card = styled.div`\n  display: flex;\n  height: 200px;\n  justify-content: center;\n  padding: 20px;\n  background-color: orange;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const StorybookGridItem = (\n      <CardGridItem>\n        <Card>{args.message}</Card>\n      </CardGridItem>\n    );\n\n    const itemArray = Array.from({ length: 12 }).fill(StorybookGridItem);\n\n    return (\n      <CardGrid pageSize={STORYBOOK_PAGE_SIZE}>\n        {itemArray.map((gridItem, index) => (\n          //eslint-disable-next-line react/no-array-index-key\n          <div key={index}>{gridItem}</div>\n        ))}\n      </CardGrid>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGrid/test/card-grid.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport CardGrid from '..';\n\ndescribe('CardGrid', () => {\n  it('should render CardGrid', () => {\n    renderWithProviders(\n      <CardGrid pageSize={{ width: 210, height: 316 }}>\n        <div data-testid={'test-child'}>{'Item 1'}</div>\n        <div data-testid={'test-child'}>{'Item 2'}</div>\n        <div data-testid={'test-child'}>{'Item 3'}</div>\n        <div data-testid={'test-child'}>{'Item 4'}</div>\n        <div data-testid={'test-child'}>{'Item 5'}</div>\n      </CardGrid>\n    );\n\n    expect(screen.getAllByTestId('test-child')).toHaveLength(5);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGridItem/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { MoreVerticalButton } from '../storyMenu';\n\nconst CardGridItem = styled.div.attrs({ role: 'listitem' })`\n  margin: 0;\n  width: 100%;\n  display: grid;\n  grid-template-columns: 100%;\n  grid-template-rows: ${({ $posterHeight }) => `${$posterHeight}px auto`};\n\n  ${MoreVerticalButton} {\n    margin: 12px 0;\n  }\n  &:hover\n    ${MoreVerticalButton},\n    &:active\n    ${MoreVerticalButton},\n    &:focus-within\n    ${MoreVerticalButton} {\n    opacity: 1;\n  }\n  &:hover .card_buttons,\n  &:active .card_buttons,\n  &:focus-within .card_buttons {\n    opacity: 1;\n  }\n`;\nCardGridItem.propTypes = {\n  $posterHeight: PropTypes.number,\n};\n\nexport default CardGridItem;\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGridItem/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { STORYBOOK_PAGE_SIZE } from '../../../storybookUtils';\nimport { CardGrid, CardGridItem } from '../..';\n\nexport default {\n  title: 'Dashboard/Components/CardGridItem',\n  component: CardGridItem,\n  args: {\n    message: 'Sample grid item - anything can go here',\n  },\n};\n\nconst Card = styled.div`\n  display: flex;\n  height: 100%;\n  justify-content: center;\n  padding: 20px;\n  background-color: orange;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <CardGrid pageSize={STORYBOOK_PAGE_SIZE}>\n        <CardGridItem>\n          <Card>{args.message}</Card>\n        </CardGridItem>\n      </CardGrid>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/cardGridItem/test/cardGridItem.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport CardGridItem from '..';\n\ndescribe('CardGridItem', () => {\n  it('should render CardGridItem', () => {\n    renderWithProviders(\n      <CardGridItem>\n        <div>\n          <p>{'Grid Item Paragraph'}</p>\n          <button>{'Grid Item Button'}</button>\n        </div>\n      </CardGridItem>\n    );\n\n    expect(screen.getByText('Grid Item Paragraph')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/colorList/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { ColorType } from '../types';\n\nconst borderLookup = (color) => ({\n  '#fff': `border: solid 1px ${color}`,\n  '#ffffff': `border: solid 1px ${color}`,\n  white: `border: solid 1px ${color}`,\n  '#fef9f1': `border: solid 1px ${color}`,\n  '#fff8f2': `border: solid 1px ${color}`,\n  '#f9f9f9': `border: solid 1px ${color}`,\n  '#fcfcfc': `border: solid 1px ${color}`,\n});\n\nconst ColorContainer = styled.ul`\n  display: flex;\n  margin: 0;\n`;\n\nconst Color = styled.li`\n  ${({ theme, $backgroundColor, color, size, spacing }) => `\n    width: ${size}px;\n    height: ${size}px;\n    border-radius: 50%;\n    margin-bottom: 0;\n    background-color: rgb(${$backgroundColor});\n    ${borderLookup(theme.colors.border.defaultNormal)[color] || ''};\n\n    & + & {\n      margin-left: ${spacing || 10}px;\n    }\n  `}\n`;\n\nfunction ColorList({ colors, size, spacing, ...rest }) {\n  return (\n    <ColorContainer {...rest}>\n      {colors.map(({ label, color }) => {\n        const { r, g, b } = createSolidFromString(color).color;\n        const backgroundColor = `${r}, ${g}, ${b}`;\n        return (\n          <Color\n            key={color}\n            size={size}\n            spacing={spacing}\n            color={color}\n            $backgroundColor={backgroundColor}\n            title={label}\n            ariaLabel={label}\n            data-testid=\"detail-template-color\"\n          />\n        );\n      })}\n    </ColorContainer>\n  );\n}\n\nColorList.propTypes = {\n  colors: PropTypes.arrayOf(ColorType).isRequired,\n  size: PropTypes.number.isRequired,\n  spacing: PropTypes.number,\n};\n\nexport default ColorList;\n"
  },
  {
    "path": "packages/dashboard/src/components/colorList/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport ColorList from '..';\n\nexport default {\n  title: 'Dashboard/Components/ColorList',\n  component: ColorList,\n  args: {\n    size: 50,\n    spacing: 10,\n  },\n  parameters: {\n    controls: {\n      exclude: ['colors'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const colors = [\n      { label: 'Red', color: 'red' },\n      { label: 'Blue', color: 'blue' },\n      { label: 'Green', color: 'green' },\n      { label: 'White', color: 'white' },\n    ];\n\n    return <ColorList colors={colors} {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/contentGutter/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { PAGE_WRAPPER } from '../../constants';\n\nexport const StandardViewContentGutter = styled.div`\n  margin: 0 ${PAGE_WRAPPER.GUTTER}px;\n`;\n"
  },
  {
    "path": "packages/dashboard/src/components/dialog/dialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { ThemeProvider } from 'styled-components';\nimport {\n  Dialog as StyledDialog,\n  Button,\n  ButtonSize,\n  ButtonType,\n  theme,\n} from '@googleforcreators/design-system';\n\n/**\n * Dialog is wrapped in a ThemeProvider so that colors can be inverted.\n *\n * @param {boolean} isOpen When true, dialog will be visible - passed to dialog directly\n * @param {Function} onClose Action taken on 'x'/clicking outside of dialog. Default secondary action.\n * @param {Function} onSecondary Action taken on secondary button click when specified.\n * @param {Function} onPrimary Action taken on primary button click.\n * @param {string} primaryText When present, primary button will render.\n * @param {string} secondaryText When present, secondary button will render.\n * @param {Object} primaryRest Unique props needed on primary button, spread on button.\n * @param {Object} secondaryRest Unique props needed on secondary button, spread on button.\n * @param {Object} actions Custom actions object for when the API restrictions of primary and secondary structure are too much.\n * @param {Node} children Contents of dialog\n */\n\nconst Dialog = ({\n  onClose,\n  onSecondary,\n  onPrimary,\n  primaryText,\n  secondaryText,\n  primaryRest,\n  secondaryRest,\n  actions,\n  children,\n  ...rest\n}) => {\n  const _PrimaryButton = useMemo(\n    () =>\n      primaryText && (\n        <Button\n          type={ButtonType.Primary}\n          size={ButtonSize.Small}\n          onClick={() => onPrimary?.()}\n          {...primaryRest}\n        >\n          {primaryText}\n        </Button>\n      ),\n    [primaryText, primaryRest, onPrimary]\n  );\n\n  const _SecondaryButton = useMemo(\n    () =>\n      secondaryText && (\n        <Button\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          onClick={() => onSecondary?.() || onClose()}\n          {...secondaryRest}\n        >\n          {secondaryText}\n        </Button>\n      ),\n    [secondaryText, secondaryRest, onSecondary, onClose]\n  );\n\n  return (\n    <ThemeProvider theme={theme}>\n      <StyledDialog\n        onClose={onClose}\n        {...rest}\n        actions={\n          actions || (\n            <>\n              {_SecondaryButton}\n              {_PrimaryButton}\n            </>\n          )\n        }\n      >\n        {children}\n      </StyledDialog>\n    </ThemeProvider>\n  );\n};\n\nDialog.propTypes = {\n  open: PropTypes.bool,\n  onClose: PropTypes.func.isRequired,\n  onPrimary: PropTypes.func,\n  onSecondary: PropTypes.func,\n  primaryText: PropTypes.string,\n  primaryRest: PropTypes.object,\n  secondaryText: PropTypes.string,\n  secondaryRest: PropTypes.object,\n  actions: PropTypes.object,\n  children: PropTypes.node,\n};\n\nexport default Dialog;\n"
  },
  {
    "path": "packages/dashboard/src/components/dialog/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './dialog';\n"
  },
  {
    "path": "packages/dashboard/src/components/dialog/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Button,\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\n\nexport default {\n  title: 'Dashboard/Components/Dialog/Base',\n  component: Dialog,\n  args: {\n    isOpen: true,\n    title: 'my dialog title',\n    secondaryText: 'cancel action',\n    primaryText: 'confirm action',\n  },\n  argTypes: {\n    onClose: {\n      action: 'closed',\n    },\n    onPrimary: {\n      action: 'confirmed',\n    },\n  },\n  parameters: {\n    controls: {\n      include: ['isOpen', 'title', 'secondaryText', 'primaryText'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Dialog {...args}>\n        <Text.Paragraph size={TextSize.Small}>\n          {\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'\n          }\n        </Text.Paragraph>\n      </Dialog>\n    );\n  },\n};\n\nexport const WithCustomAction = {\n  render: ({ onClickButton, onConfirmed, ...args }) => {\n    return (\n      <Dialog\n        actions={\n          <>\n            <Button\n              type={ButtonType.Tertiary}\n              size={ButtonSize.Small}\n              onClick={onClickButton}\n            >\n              {'Dismiss'}\n            </Button>\n            <ButtonAsLink\n              type={ButtonType.Primary}\n              size={ButtonSize.Small}\n              href={args.href}\n              onClick={onConfirmed}\n            >\n              {'Add to new post'}\n            </ButtonAsLink>\n          </>\n        }\n        {...args}\n      >\n        <Text.Paragraph size={TextSize.Small}>\n          {\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'\n          }\n        </Text.Paragraph>\n      </Dialog>\n    );\n  },\n\n  args: {\n    isOpen: true,\n    title: 'my dialog title',\n    href: 'https://example.com',\n  },\n\n  argTypes: {\n    onClose: {\n      action: 'closed',\n    },\n    onClickButton: {\n      action: 'closed',\n      name: 'dismiss click',\n    },\n    onConfirmed: {\n      action: 'confirmed',\n      name: 'confirm click',\n    },\n  },\n\n  parameters: {\n    controls: {\n      include: [\n        'isOpen',\n        'title',\n        'href',\n        'onClose',\n        'dismiss click',\n        'confirm click',\n      ],\n    },\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/fileUpload/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  ButtonSize,\n  ButtonType,\n  Button,\n  Text,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_FILE_UPLOAD_TYPES } from '../../constants';\n\nconst StyledButton = styled(Button)`\n  :focus-within {\n    ${({ theme }) => themeHelpers.focusCSS(theme.colors.border.focus)}\n  }\n`;\n\nconst Input = styled.input(themeHelpers.visuallyHidden);\n\nconst UploadFormArea = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  position: relative;\n  justify-content: flex-end;\n  width: 100%;\n  min-height: 153px;\n  padding: 40px 0;\n  border-radius: 4px;\n  border: 1px dashed\n    ${({ isDragging, theme }) =>\n      isDragging\n        ? theme.colors.border.focus\n        : theme.colors.border.defaultNormal};\n\n  transition: border-color 300ms ease-in;\n`;\n\nconst UploadHelperText = styled(Text.Paragraph)`\n  margin: 0 auto 16px;\n  padding: 0 20%;\n  text-align: center;\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst LoadingIndicator = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  position: absolute;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  background-color: ${({ theme }) => theme.colors.standard.white};\n  opacity: ${({ isLoading }) => (isLoading ? 0.6 : 0)};\n  z-index: ${({ isLoading }) => (isLoading ? '100' : '0')};\n  pointer-events: none;\n\n  transition: opacity ease-in-out 300ms;\n\n  p {\n    font-style: italic;\n  }\n`;\n\nfunction disableDefaults(e) {\n  e.preventDefault();\n  e.stopPropagation();\n}\n\nconst FileUpload = ({\n  id,\n  label,\n  onSubmit,\n  isLoading,\n  isMultiple,\n  ariaLabel,\n  instructionalText = __('You can also drag your file here', 'web-stories'),\n  acceptableFormats = DEFAULT_FILE_UPLOAD_TYPES,\n}) => {\n  const uploadFileContainer = useRef(null);\n  const fileInputRef = useRef(null);\n  const [isDragging, setDragging] = useState(false);\n\n  const handleUploadFile = useCallback(\n    (files) => {\n      onSubmit(Object.values(files));\n    },\n    [onSubmit]\n  );\n\n  const handleChange = useCallback(\n    (e) => {\n      disableDefaults(e);\n      handleUploadFile(e.target.files);\n      fileInputRef.current.value = null;\n    },\n    [handleUploadFile]\n  );\n\n  const handleDragDrop = useCallback(\n    (e) => {\n      disableDefaults(e);\n      const files = e.dataTransfer.files;\n      if (files) {\n        handleUploadFile(files);\n      }\n      setDragging(false);\n    },\n    [handleUploadFile]\n  );\n\n  const handleDrag = useCallback(\n    (e) => {\n      disableDefaults(e);\n      setDragging((prevIsDragging) => !prevIsDragging);\n\n      if (isDragging) {\n        e.dataTransfer.clearData();\n      }\n    },\n    [isDragging]\n  );\n\n  useEffect(() => {\n    if (!fileInputRef?.current) {\n      return () => {};\n    }\n\n    const input = fileInputRef.current;\n\n    input.addEventListener('change', handleChange);\n    return () => {\n      input.removeEventListener('change', handleChange);\n    };\n  }, [handleChange]);\n\n  return (\n    <UploadFormArea\n      ref={uploadFileContainer}\n      isDragging={isDragging}\n      onDrop={handleDragDrop}\n      onDragEnter={handleDrag}\n      onDragLeave={handleDrag}\n      onDragOver={disableDefaults}\n      data-testid=\"file-upload-drop-area\"\n    >\n      <LoadingIndicator isLoading={isLoading}>\n        <p>{__('Loading…', 'web-stories')}</p>\n      </LoadingIndicator>\n      <UploadHelperText>{instructionalText}</UploadHelperText>\n\n      <StyledButton\n        forwardedAs=\"label\"\n        htmlFor={id}\n        aria-label={ariaLabel}\n        type={ButtonType.Primary}\n        size={ButtonSize.Small}\n      >\n        {label}\n        <Input\n          ref={fileInputRef}\n          type=\"file\"\n          id={id}\n          data-testid=\"upload-file-input\"\n          accept={acceptableFormats.join(',')}\n          multiple={isMultiple}\n          disabled={isLoading}\n          aria-live=\"polite\"\n          aria-busy={isLoading}\n        />\n      </StyledButton>\n    </UploadFormArea>\n  );\n};\n\nFileUpload.propTypes = {\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n  label: PropTypes.string.isRequired,\n  onSubmit: PropTypes.func.isRequired,\n  isLoading: PropTypes.bool,\n  isMultiple: PropTypes.bool,\n  ariaLabel: PropTypes.string,\n  acceptableFormats: PropTypes.arrayOf(PropTypes.string),\n  instructionalText: PropTypes.string,\n};\n\nexport default FileUpload;\n"
  },
  {
    "path": "packages/dashboard/src/components/fileUpload/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport FileUpload from '..';\n\nconst Container = styled.div`\n  width: 600px;\n`;\nexport default {\n  title: 'Dashboard/Components/FileUpload',\n  component: FileUpload,\n  args: {\n    label: 'Upload',\n    isLoading: false,\n    isMultiple: true,\n    instructionalText:\n      'Drag a jpg, png, or static gif in this box. Or click “Upload logo” below.',\n  },\n  argTypes: {\n    onSubmit: { action: 'files uploaded' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['id', 'ariaLabel', 'acceptableFormats'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Container>\n        <FileUpload\n          acceptableFormats={['.jpg', '.jpeg', '.png', '.gif']}\n          id={'898989'}\n          ariaLabel={'Click to upload a file'}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/fileUpload/test/fileUpload.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, createEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport FileUpload from '..';\n\ndescribe('FileUpload', () => {\n  it('should render upload component by default', () => {\n    renderWithProviders(\n      <FileUpload\n        onSubmit={jest.fn}\n        id={'898989'}\n        label=\"Upload\"\n        ariaLabel=\"Click to upload a file\"\n      />\n    );\n    expect(\n      screen.queryByTestId('file-upload-content-container')\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render upload component with loading overlay when isLoading is true', () => {\n    renderWithProviders(\n      <FileUpload\n        onSubmit={jest.fn}\n        id={'898989'}\n        label=\"Upload\"\n        ariaLabel=\"Click to upload a file\"\n        isLoading\n      />\n    );\n    expect(screen.getByText(/^Loading/)).toBeInTheDocument();\n  });\n\n  it('should trigger onSubmit when file is added through input', () => {\n    const onSubmitMock = jest.fn();\n\n    renderWithProviders(\n      <FileUpload\n        onSubmit={onSubmitMock}\n        id={'898989'}\n        label=\"Upload\"\n        ariaLabel=\"Click to upload a file\"\n      />\n    );\n\n    const UploadInput = screen.getByTestId('upload-file-input');\n    expect(UploadInput).toBeInTheDocument();\n    fireEvent.click(UploadInput);\n    fireEvent.change(UploadInput, { target: { files: {} } });\n    expect(onSubmitMock).toHaveBeenCalledOnce();\n  });\n\n  it('should trigger onSubmit when file is dropped in container', () => {\n    const onSubmitMock = jest.fn();\n\n    const mockFile = new File([''], 'mockfile.png', {\n      type: 'image/png',\n    });\n    renderWithProviders(\n      <FileUpload\n        onSubmit={onSubmitMock}\n        id={'898989'}\n        label=\"Upload\"\n        ariaLabel=\"Click to upload a file\"\n      />\n    );\n\n    const DropArea = screen.getByTestId('file-upload-drop-area');\n    expect(DropArea).toBeInTheDocument();\n\n    const dropEvent = createEvent.drop(DropArea);\n    const fileList = [mockFile];\n\n    Object.defineProperty(dropEvent, 'dataTransfer', {\n      value: {\n        files: {\n          item: (itemIndex) => fileList[itemIndex],\n          length: fileList.length,\n        },\n      },\n    });\n\n    fireEvent(DropArea, dropEvent);\n\n    expect(onSubmitMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as CardGallery } from './cardGallery';\nexport { default as CardGrid } from './cardGrid';\nexport { default as CardGridItem } from './cardGridItem';\nexport { default as ColorList } from './colorList';\nexport { StandardViewContentGutter } from './contentGutter';\nexport { default as Dialog } from './dialog';\nexport { default as FileUpload } from './fileUpload';\nexport { default as InlineInputForm } from './inlineInputForm';\nexport { default as Layout, useLayoutContext } from './layout';\nexport {\n  AppFrame,\n  LeftRail,\n  LoadingContainer,\n  PageContent,\n  NavMenuButton,\n} from './pageStructure';\nexport { default as NavProvider, useNavContext } from './navProvider';\nexport { default as ScrollToTop } from './scrollToTop';\nexport {\n  default as StoryMenu,\n  MoreVerticalButton,\n  CONTEXT_MENU_BUTTON_CLASS,\n} from './storyMenu';\nexport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHeader,\n  StickyTableHeader,\n  TableHeaderCell,\n  TablePreviewCell,\n  TablePreviewHeaderCell,\n  TableTitleCell,\n  TableContentCell,\n  TableContentHeaderCell,\n  TableRow,\n  TableTitleHeaderCell,\n  TableAuthorHeaderCell,\n  TableDateHeaderCell,\n  TableStatusHeaderCell,\n  TableStatusCell,\n} from './table';\nexport { Tooltip } from './tooltip';\nexport { default as ViewStyleBar } from './viewStyleBar';\n"
  },
  {
    "path": "packages/dashboard/src/components/inlineInputForm/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { Input } from '@googleforcreators/design-system';\n\nconst StyledInput = styled(Input)`\n  div {\n    height: auto;\n  }\n  ${({ $isInverted, theme }) =>\n    $isInverted &&\n    css`\n      input {\n        color: ${theme.colors.inverted.fg.primary};\n      }\n    `}\n`;\n\nconst InlineInputForm = ({\n  noAutoFocus,\n  error,\n  id,\n  isInverted,\n  label,\n  onEditCancel,\n  onEditComplete,\n  placeholder,\n  value,\n}) => {\n  const inputContainerRef = useRef(null);\n  const [newValue, setNewValue] = useState(value);\n\n  useEffect(() => {\n    // update internal value when `value` prop updates\n    setNewValue(value);\n  }, [value]);\n\n  useFocusOut(inputContainerRef, () => {\n    // cancel changes when user focuses away from input\n    onEditCancel();\n  }, [onEditCancel]);\n\n  useEffect(() => {\n    if (!noAutoFocus && inputContainerRef.current) {\n      inputContainerRef.current.querySelector('input')?.focus();\n    }\n  }, [noAutoFocus]);\n\n  const handleChange = useCallback(\n    ({ target }) => {\n      setNewValue(target.value);\n    },\n    [setNewValue]\n  );\n\n  const handleKeyPress = useCallback(\n    ({ nativeEvent }) => {\n      if (nativeEvent.keyCode === 13) {\n        onEditComplete(newValue);\n      } else if (nativeEvent.keyCode === 27) {\n        onEditCancel();\n      }\n    },\n    [newValue, onEditComplete, onEditCancel]\n  );\n  return (\n    <div ref={inputContainerRef}>\n      <StyledInput\n        aria-label={label}\n        id={`${id}`}\n        data-testid=\"inline-input-form\"\n        value={newValue}\n        onKeyDown={handleKeyPress}\n        onChange={handleChange}\n        placeholder={placeholder}\n        hasError={Boolean(error)}\n        hint={error}\n        $isInverted={isInverted}\n      />\n    </div>\n  );\n};\n\nInlineInputForm.propTypes = {\n  error: PropTypes.string,\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n  isInverted: PropTypes.bool,\n  label: PropTypes.string.isRequired,\n  noAutoFocus: PropTypes.bool,\n  onEditCancel: PropTypes.func.isRequired,\n  onEditComplete: PropTypes.func.isRequired,\n  placeholder: PropTypes.string,\n  value: PropTypes.string,\n};\n\nexport default InlineInputForm;\n"
  },
  {
    "path": "packages/dashboard/src/components/inlineInputForm/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport InlineInputForm from '..';\n\nexport default {\n  title: 'Dashboard/Components/InlineInputForm',\n  component: InlineInputForm,\n  args: {\n    error: 'error',\n  },\n  argTypes: {\n    onEditCancel: {\n      action: 'onEditCancel',\n    },\n    onEditComplete: {\n      action: 'onEditComplete',\n    },\n  },\n  parameters: {\n    controls: {\n      include: ['error', 'onEditCancel', 'onEditComplete'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <InlineInputForm\n        onEditComplete={(newValue) => args.onEditComplete(newValue)}\n        value={'some input value'}\n        id={'898989'}\n        label=\"my hidden input label\"\n        {...args}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/inlineInputForm/test/inlineInputForm.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport InlineInputForm from '..';\n\ndescribe('InlineInputForm', () => {\n  it('should render a text input field', () => {\n    renderWithProviders(\n      <InlineInputForm\n        onEditComplete={jest.fn}\n        onEditCancel={jest.fn}\n        value={'some input value'}\n        id={'898989'}\n        label=\"my hidden input label\"\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should call onEditCancel when focus is removed from input', () => {\n    const mockCancel = jest.fn();\n\n    renderWithProviders(\n      <InlineInputForm\n        onEditComplete={jest.fn}\n        onEditCancel={mockCancel}\n        value={'some input value'}\n        id={'898989'}\n        label=\"my hidden input label\"\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.keyDown(input, { key: 'escape', keyCode: 27 });\n\n    expect(mockCancel).toHaveBeenCalledOnce();\n  });\n\n  it('should call onEditComplete when enter is hit from the input', () => {\n    const mockComplete = jest.fn();\n\n    renderWithProviders(\n      <InlineInputForm\n        onEditComplete={mockComplete}\n        onEditCancel={jest.fn}\n        value={'some input value'}\n        id={'898989'}\n        label=\"my hidden input label\"\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.keyDown(input, { key: 'enter', keyCode: 13 });\n\n    expect(mockComplete).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/interfaceSkeleton/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  usePrevious,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { trackScreenView } from '@googleforcreators/tracking';\nimport {\n  SnackbarContainer,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { ExploreTemplatesView, MyStoriesView } from '../../app/views';\nimport { APP_ROUTES, ROUTE_TITLES } from '../../constants';\nimport { Route, useRouteHistory } from '../../app/router';\nimport { AppFrame, LeftRail, PageContent } from '../pageStructure';\nimport useApiAlerts from '../../app/api/useApiAlerts';\nimport useApi from '../../app/api/useApi';\nimport { useConfig } from '../../app/config';\n\nconst InterfaceSkeleton = ({ additionalRoutes }) => {\n  const { currentPath, templateId, availableRoutes } = useRouteHistory(\n    ({ state }) => ({\n      ...state,\n      templateId: state.queryParams.id,\n    })\n  );\n  const { push, setAvailableRoutes } = useRouteHistory(\n    ({ actions }) => actions\n  );\n\n  const {\n    canViewDefaultTemplates,\n    leftRailSecondaryNavigation = [],\n    documentTitleSuffix = __('Web Stories', 'web-stories'),\n  } = useConfig();\n\n  const { addInitialFetchListener } = useApi(\n    ({\n      actions: {\n        storyApi: { addInitialFetchListener },\n      },\n      state: {\n        templates: { templates },\n      },\n    }) => ({\n      currentTemplate:\n        templateId !== undefined ? templates[templateId]?.title : undefined,\n      addInitialFetchListener,\n    })\n  );\n  const isFirstLoadOnMyStoriesRef = useRef(\n    currentPath === APP_ROUTES.DASHBOARD\n  );\n  const [isRedirectComplete, setIsRedirectComplete] = useState(\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    !isFirstLoadOnMyStoriesRef.current\n  );\n\n  // Direct user to templates on first load if they\n  // have no stories created.\n  useEffect(() => {\n    return addInitialFetchListener?.((storyStatuses) => {\n      if (\n        storyStatuses?.all <= 0 &&\n        isFirstLoadOnMyStoriesRef.current &&\n        canViewDefaultTemplates\n      ) {\n        push(APP_ROUTES.TEMPLATES_GALLERY);\n        isFirstLoadOnMyStoriesRef.current = false;\n      }\n      setIsRedirectComplete(true);\n    });\n  }, [addInitialFetchListener, push, currentPath, canViewDefaultTemplates]);\n\n  // Only set the available routes & default route on initial mount\n  useEffect(() => {\n    if (availableRoutes.length > 0) {\n      return;\n    }\n    const additionalPaths = additionalRoutes\n      ? additionalRoutes.map(({ path }) => path)\n      : [];\n    setAvailableRoutes([...Object.values(APP_ROUTES), ...additionalPaths]);\n  }, [additionalRoutes, availableRoutes.length, setAvailableRoutes]);\n\n  useEffect(() => {\n    if (!isRedirectComplete) {\n      return;\n    }\n\n    const additionalRouteTitle = leftRailSecondaryNavigation.find(\n      (config) => config.value === currentPath\n    );\n    const dynamicPageTitle =\n      ROUTE_TITLES[currentPath] ||\n      additionalRouteTitle?.label ||\n      ROUTE_TITLES.DEFAULT;\n\n    document.title = sprintf(\n      /* translators: Admin screen title. 1: Admin screen name, 2: Network or site name. */\n      __('%1$s \\u2039 %2$s', 'web-stories'),\n      dynamicPageTitle,\n      documentTitleSuffix\n    );\n\n    trackScreenView(dynamicPageTitle);\n  }, [\n    currentPath,\n    isRedirectComplete,\n    leftRailSecondaryNavigation,\n    documentTitleSuffix,\n  ]);\n\n  useApiAlerts();\n  const { clearSnackbar, removeSnack, placement, currentSnacks } =\n    useSnackbar();\n\n  // if the current path changes clear the snackbar\n  const prevPath = usePrevious(currentPath);\n\n  useEffect(() => {\n    if (currentPath !== prevPath) {\n      clearSnackbar();\n    }\n  }, [clearSnackbar, currentPath, prevPath]);\n\n  return (\n    <>\n      <AppFrame>\n        <LeftRail />\n        <PageContent>\n          {availableRoutes.length > 0 && (\n            <>\n              <Route\n                exact\n                isDefault\n                path={APP_ROUTES.DASHBOARD}\n                component={<MyStoriesView />}\n              />\n              {canViewDefaultTemplates && (\n                <Route\n                  path={APP_ROUTES.TEMPLATES_GALLERY}\n                  component={<ExploreTemplatesView />}\n                />\n              )}\n              {additionalRoutes &&\n                additionalRoutes.map((routeProps) => (\n                  <Route key={routeProps.path} {...routeProps} />\n                ))}\n            </>\n          )}\n        </PageContent>\n      </AppFrame>\n      <SnackbarContainer\n        notifications={currentSnacks}\n        onRemove={removeSnack}\n        placement={placement}\n        max={1}\n      />\n    </>\n  );\n};\n\nInterfaceSkeleton.propTypes = {\n  additionalRoutes: PropTypes.array,\n};\n\nexport default InterfaceSkeleton;\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/fixed.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Z_INDEX } from '../../constants';\n\nconst FixedContent = styled.div`\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: ${Z_INDEX.LAYOUT_FIXED};\n  overflow: hidden;\n\n  /**\n   * This is an absolute positioned full size\n   * overlay over the scrollable content. being\n   * such, we don't want it to block pointer\n   * events to the scrollable and squishable\n   * content.\n   */\n  pointer-events: none;\n\n  /**\n   * Not sure how much I like this because\n   * it will be a higher specificity than a\n   * styled declaration, but I don't want\n   * devs to have to declare this on every\n   * component in this view.\n   */\n  & > * {\n    pointer-events: auto;\n  }\n`;\n\nconst Fixed = ({ children }) => <FixedContent>{children}</FixedContent>;\n\nFixed.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default Fixed;\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport Provider from './provider';\nimport Scrollable from './scrollable';\nimport Fixed from './fixed';\n\nconst Layout = {\n  Provider,\n  Scrollable,\n  Fixed,\n};\n\nexport default Layout;\nexport { default as useLayoutContext } from './useLayoutContext';\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useMemo,\n  useRef,\n  useCallback,\n  createContext,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\nexport const LayoutContext = createContext(null);\n\nconst Provider = ({ children }) => {\n  const firstFocusableContentRef = useRef();\n  const scrollFrameRef = useRef(null);\n\n  // Get the first focusable content in the dashboard\n  // so we can send focus there without having to\n  // tab through the whole WordPress dashboard to get back.\n  useEffect(() => {\n    firstFocusableContentRef.current = document\n      ?.getElementById('web-stories-dashboard')\n      ?.querySelector(['button', 'a']);\n  }, []);\n\n  const scrollToTop = useCallback(() => {\n    document.documentElement?.scrollTo?.({\n      top: 0,\n      behavior: 'smooth',\n    });\n    firstFocusableContentRef.current?.focus();\n  }, []);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        scrollFrameRef,\n      },\n      actions: {\n        scrollToTop,\n      },\n    }),\n    [scrollToTop]\n  );\n\n  return (\n    <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>\n  );\n};\n\nProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default Provider;\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/scrollable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport useLayoutContext from './useLayoutContext';\n\nconst ScrollContent = styled.div``;\n\nconst Scrollable = ({ children }) => {\n  const {\n    state: { scrollFrameRef },\n  } = useLayoutContext();\n  return <ScrollContent ref={scrollFrameRef}>{children}</ScrollContent>;\n};\n\nScrollable.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default Scrollable;\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/test/useLayoutContext.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport LayoutProvider from '../provider';\nimport useLayoutContext from '../useLayoutContext';\n\ndescribe('useLayoutContext()', () => {\n  it('should throw an error if used outside Layout.Provider', () => {\n    expect(() => {\n      const {\n        // eslint-disable-next-line no-unused-vars\n        result: { current },\n      } = renderHook(() => useLayoutContext());\n    }).toThrow(\n      Error('useLayoutContext() must be used within a <Layout.Provider />')\n    );\n  });\n\n  it('should not throw an error if used inside LayoutProvider', () => {\n    const { result } = renderHook(() => useLayoutContext(), {\n      wrapper: LayoutProvider,\n    });\n    expect(result.current.error).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/layout/useLayoutContext.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContext } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { LayoutContext } from './provider';\n\nconst useLayoutContext = () => {\n  const context = useContext(LayoutContext);\n  if (!context) {\n    throw new Error(\n      'useLayoutContext() must be used within a <Layout.Provider />'\n    );\n  }\n  return context;\n};\n\nexport default useLayoutContext;\n"
  },
  {
    "path": "packages/dashboard/src/components/navProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useMemo,\n  useState,\n  createContext,\n  useContextSelector,\n  identity,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\nexport const NavContext = createContext({ actions: {}, state: {} });\n\nexport function useNavContext(selector = identity) {\n  return useContextSelector(NavContext, selector);\n}\n\nexport default function NavProvider({ children }) {\n  const [sideBarVisible, setSideBarVisible] = useState(false);\n\n  const toggleSideBar = useCallback(() => {\n    setSideBarVisible(!sideBarVisible);\n  }, [sideBarVisible]);\n\n  const value = useMemo(\n    () => ({\n      actions: { toggleSideBar },\n      state: { sideBarVisible },\n    }),\n    [sideBarVisible, toggleSideBar]\n  );\n\n  return <NavContext.Provider value={value}>{children}</NavContext.Provider>;\n}\n\nNavProvider.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]).isRequired,\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './pageStructureComponents';\nexport { default as LeftRail } from './leftRail';\nexport { default as NavMenuButton } from './menuButton';\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/leftRail.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useFocusOut,\n  useLayoutEffect,\n  useRef,\n} from '@googleforcreators/react';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  LogoWithTypeCircleColor,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { resolveRoute, useRouteHistory } from '../../app/router';\nimport { useNavContext } from '../navProvider';\nimport { useConfig } from '../../app';\nimport { APP_ROUTES, PRIMARY_PATHS } from '../../constants';\nimport {\n  AppInfo,\n  Content,\n  Header,\n  NavLink,\n  NavList,\n  NavListItem,\n  PathName,\n} from './navigationComponents';\nimport { LeftRailContainer } from './pageStructureComponents';\n\nconst IconWrap = styled.div`\n  position: relative;\n`;\n\nfunction LeftRail() {\n  const activeRoute = useRouteHistory(({ state }) => state.activeRoute);\n\n  const {\n    newStoryURL,\n    version,\n    leftRailSecondaryNavigation,\n    canViewDefaultTemplates,\n    styleConstants: { topOffset },\n  } = useConfig();\n  const leftRailRef = useRef(null);\n  const upperContentRef = useRef(null);\n\n  const {\n    state: { sideBarVisible },\n    actions: { toggleSideBar },\n  } = useNavContext();\n\n  const onContainerClickCapture = useCallback(\n    ({ target }) => {\n      if (\n        target === leftRailRef.current ||\n        target === upperContentRef.current\n      ) {\n        return;\n      }\n      toggleSideBar();\n    },\n    [toggleSideBar, leftRailRef, upperContentRef]\n  );\n\n  const handleSideBarClose = useCallback(() => {\n    if (sideBarVisible) {\n      toggleSideBar();\n    }\n  }, [toggleSideBar, sideBarVisible]);\n\n  useFocusOut(leftRailRef, handleSideBarClose, [sideBarVisible]);\n\n  useLayoutEffect(() => {\n    if (sideBarVisible && leftRailRef.current) {\n      leftRailRef.current.focus();\n    }\n  }, [sideBarVisible]);\n\n  const onCreateNewStoryClick = useCallback(() => {\n    trackEvent('create_new_story');\n  }, []);\n\n  const onExternalLinkClick = useCallback((evt, path) => {\n    trackClick(evt, path.trackingEvent);\n  }, []);\n\n  return (\n    <LeftRailContainer\n      onClickCapture={onContainerClickCapture}\n      ref={leftRailRef}\n      isOpen={sideBarVisible}\n      topOffset={topOffset}\n      role=\"navigation\"\n      aria-label={__('Main dashboard navigation', 'web-stories')}\n    >\n      <div ref={upperContentRef}>\n        <Header forwardedAs=\"h2\">\n          <LogoWithTypeCircleColor\n            title={__('Web Stories Dashboard', 'web-stories')}\n          />\n        </Header>\n        <Content>\n          <ButtonAsLink\n            type={ButtonType.Quaternary}\n            size={ButtonSize.Small}\n            href={newStoryURL}\n            onClick={onCreateNewStoryClick}\n          >\n            {__('Create New Story', 'web-stories')}\n          </ButtonAsLink>\n        </Content>\n        <Content>\n          <NavList>\n            {PRIMARY_PATHS.map(({ Icon, ...path }) => {\n              const isTemplatesDisabled =\n                path.value === APP_ROUTES.TEMPLATES_GALLERY &&\n                !canViewDefaultTemplates;\n\n              if (isTemplatesDisabled) {\n                return null;\n              }\n\n              return (\n                <NavListItem key={path.value}>\n                  <NavLink\n                    active={activeRoute === path.value}\n                    href={resolveRoute(path.value)}\n                    size={TextSize.Small}\n                    isBold\n                    isIconLink={Boolean(Icon)}\n                    aria-label={\n                      activeRoute === path.value\n                        ? sprintf(\n                            /* translators: %s: the current page, for example \"Dashboard\". */\n                            __('%s (active view)', 'web-stories'),\n                            path.label\n                          )\n                        : path.label\n                    }\n                    {...(path.isExternal && {\n                      rel: 'noreferrer',\n                      target: '_blank',\n                      onClick: (evt) => onExternalLinkClick(evt, path),\n                    })}\n                  >\n                    <IconWrap>{Icon && <Icon width=\"22px\" />}</IconWrap>\n\n                    <PathName size={TextSize.Small} isBold>\n                      {path.label}\n                    </PathName>\n                  </NavLink>\n                </NavListItem>\n              );\n            })}\n          </NavList>\n        </Content>\n      </div>\n      <Content>\n        {leftRailSecondaryNavigation && (\n          <NavList>\n            {leftRailSecondaryNavigation.map((path) => (\n              <NavListItem key={path.value}>\n                <NavLink\n                  active={activeRoute === path.value}\n                  href={resolveRoute(path.value)}\n                  size={TextSize.Small}\n                  aria-label={\n                    activeRoute === path.value\n                      ? sprintf(\n                          /* translators: %s: the current page, for example \"Dashboard\". */\n                          __('%s (active view)', 'web-stories'),\n                          path.label\n                        )\n                      : path.label\n                  }\n                  {...(path.isExternal && {\n                    rel: 'noreferrer',\n                    target: '_blank',\n                    onClick: (evt) => onExternalLinkClick(evt, path),\n                  })}\n                >\n                  <Text.Span size={TextSize.Small} isBold>\n                    {path.label}\n                  </Text.Span>\n                </NavLink>\n              </NavListItem>\n            ))}\n          </NavList>\n        )}\n        <AppInfo size={TextSize.XSmall}>\n          {sprintf(\n            /* translators: 1: Current Year, 2: App Version */\n            __('\\u00A9 %1$s Google Version %2$s', 'web-stories'),\n            new Date().getFullYear(),\n            version\n          )}\n        </AppInfo>\n      </Content>\n    </LeftRailContainer>\n  );\n}\n\nexport default LeftRail;\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/menuButton.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { MIN_DASHBOARD_WIDTH } from '../../constants';\nimport { Menu as MenuSvg } from '../../icons';\nimport { useNavContext } from '../navProvider';\n\nconst MenuIcon = styled(MenuSvg).attrs({ width: 24, height: 24 })`\n  display: block;\n  color: ${({ theme }) => theme.colors.interactiveFg.brandNormal};\n`;\n\nconst TransparentButton = styled.button`\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 24px;\n  height: 24px;\n  padding: 0;\n  margin-right: 16px;\n  background: transparent;\n  border: 0;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${themeHelpers.focusableOutlineCSS}\n\n  ${({ showOnlyOnSmallViewport }) =>\n    showOnlyOnSmallViewport &&\n    css`\n      display: none;\n      @media screen and (max-width: ${MIN_DASHBOARD_WIDTH}px) {\n        display: inline-block;\n      }\n    `}\n`;\n\nfunction NavMenuButton({ showOnlyOnSmallViewport }) {\n  const { actions } = useNavContext();\n  return (\n    <TransparentButton\n      onClick={actions.toggleSideBar}\n      showOnlyOnSmallViewport={showOnlyOnSmallViewport}\n      aria-label={__('Toggle main navigation', 'web-stories')}\n    >\n      <MenuIcon aria-hidden />\n    </TransparentButton>\n  );\n}\n\nNavMenuButton.propTypes = {\n  showOnlyOnSmallViewport: PropTypes.bool,\n};\n\nexport default NavMenuButton;\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/navigationComponents.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { Headline, Link, Text } from '@googleforcreators/design-system';\n\nexport const Content = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin: 20px 0;\n  > * {\n    margin: 20px 28px;\n  }\n`;\n\nexport const Header = styled(Headline)`\n  margin: 42px 0px 72px;\n\n  & > svg {\n    margin: 0 28px;\n    height: 64px;\n  }\n`;\n\nexport const NavList = styled.ul`\n  margin: 0;\n  padding: 0;\n`;\n\nexport const NavListItem = styled.li`\n  margin: 10px 28px;\n  padding: 0;\n  list-style-type: none;\n`;\n\nconst activeLinkCss = css`\n  span {\n    color: ${({ theme }) => theme.colors.interactiveFg.brandPress};\n  }\n\n  svg path {\n    stroke: ${({ theme }) => theme.colors.interactiveFg.brandPress};\n  }\n`;\n\nexport const NavLink = styled(Link)(\n  ({ active, theme, isIconLink }) => css`\n    ${isIconLink &&\n    css`\n      display: grid;\n      grid-template-columns: 1fr 4fr;\n      grid-template-areas: 'icon link link link link';\n    `}\n    color: ${theme.colors.fg.secondary};\n\n    * {\n      transition:\n        color 0.25s linear,\n        stroke 0.25s linear;\n    }\n\n    ${active && activeLinkCss};\n\n    :hover {\n      ${activeLinkCss};\n    }\n  `\n);\n\nexport const PathName = styled(Text.Span)`\n  grid-area: link;\n`;\n\nexport const AppInfo = styled(Text.Paragraph)(\n  ({ theme }) => css`\n    color: ${theme.colors.fg.secondary};\n  `\n);\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/pageStructureComponents.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { BEZIER } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  Z_INDEX,\n  DASHBOARD_LEFT_NAV_WIDTH,\n  MIN_DASHBOARD_WIDTH,\n} from '../../constants';\n\nexport const AppFrame = styled.div`\n  width: 100%;\n  @media screen and (max-width: ${MIN_DASHBOARD_WIDTH}px) {\n    width: ${MIN_DASHBOARD_WIDTH}px;\n  }\n`;\n\nexport const PageContent = styled.div`\n  position: relative;\n  padding-top: 10px;\n  width: ${({ fullWidth }) =>\n    fullWidth ? '100%' : `calc(100% - ${DASHBOARD_LEFT_NAV_WIDTH}px)`};\n  left: ${({ fullWidth }) =>\n    fullWidth ? '0' : `${DASHBOARD_LEFT_NAV_WIDTH}px`};\n\n  @media screen and (max-width: ${MIN_DASHBOARD_WIDTH}px) {\n    left: 0;\n    width: 100%;\n  }\n`;\n\nexport const LeftRailContainer = styled.nav.attrs({\n  ['data-testid']: 'dashboard-left-rail',\n})`\n  position: fixed;\n  display: flex;\n  justify-content: space-between;\n  flex-direction: column;\n  top: ${({ topOffset }) => `${topOffset}px`};\n  bottom: 0;\n  width: ${DASHBOARD_LEFT_NAV_WIDTH}px;\n  background: ${({ theme }) => theme.colors.bg.primary};\n  z-index: ${Z_INDEX.LAYOUT_FIXED};\n  transition:\n    transform 0.25s ${BEZIER.outCubic},\n    opacity 0.25s linear;\n\n  @media screen and (max-width: ${MIN_DASHBOARD_WIDTH}px) {\n    padding-left: 0;\n    opacity: ${({ isOpen }) => (isOpen ? 1 : 0)};\n    visibility: ${({ isOpen }) => (isOpen ? 'visible' : 'hidden')};\n    transform: translateX(${({ isOpen }) => (isOpen ? 'none' : `-100%`)});\n  }\n`;\n\nexport const LoadingContainer = styled.div`\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  min-height: 550px;\n`;\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AppFrame, PageContent, LeftRail } from '..';\nimport NavProvider from '../../navProvider';\n\nexport default {\n  title: 'Dashboard/Components/LeftRail',\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <AppFrame>\n        <NavProvider>\n          <LeftRail />\n          <PageContent />\n        </NavProvider>\n      </AppFrame>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/stories/menuButton.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport NavProvider, { useNavContext } from '../../navProvider';\nimport NavMenuButton from '../menuButton';\n\nexport default {\n  title: 'Dashboard/Components/NavMenuButton',\n  args: {\n    showOnlyOnSmallViewport: true,\n  },\n  argTypes: {\n    showOnlyOnSmallViewport: { name: 'Show only on Small (Mobile) Viewort' },\n  },\n};\n\nconst Status = () => {\n  const { state } = useNavContext();\n  return <span>{`Sidebar Visible: ${String(state.sideBarVisible)}`}</span>;\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <NavProvider>\n        <NavMenuButton {...args} />\n        <br />\n        <Status />\n      </NavProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/pageStructure/test/pageStructure.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport { LeftRail } from '..';\nimport { NavContext } from '../../navProvider';\nimport { PRIMARY_PATHS } from '../../../constants';\n\ndescribe('<LeftRail />', () => {\n  const toggleSideBarFn = jest.fn();\n\n  const MockedNavProvider = ({ children }) => {\n    return (\n      <NavContext.Provider\n        value={{\n          actions: {\n            toggleSideBar: toggleSideBarFn,\n          },\n          state: { sideBarVisible: false },\n        }}\n      >\n        {children}\n      </NavContext.Provider>\n    );\n  };\n\n  it('should be visible by default in a regular viewport.', () => {\n    renderWithProviders(\n      <MockedNavProvider>\n        <LeftRail />\n      </MockedNavProvider>\n    );\n\n    const leftRail = screen.getByTestId('dashboard-left-rail');\n    const visibility = window.getComputedStyle(leftRail).visibility;\n\n    expect(visibility).toBe('visible');\n  });\n\n  it('should call the toggle sidebar function when a link is clicked to close the menu.', () => {\n    renderWithProviders(\n      <MockedNavProvider>\n        <LeftRail />\n      </MockedNavProvider>\n    );\n\n    expect(toggleSideBarFn).not.toHaveBeenCalled();\n\n    const firstLink = screen.getByText(PRIMARY_PATHS[0].label);\n    fireEvent.click(firstLink);\n\n    expect(toggleSideBarFn).toHaveBeenCalledWith();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/popoverMenu/story-menu-generator.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { STORY_CONTEXT_MENU_ACTIONS } from '../../constants';\nimport { noop } from '../../utils';\n\n/**\n * Generate story menu.\n *\n * @param {Object} arguments The arguments\n * @param {Array} arguments.menuItems The menu items to build out\n * @param {Object} arguments.story The story used to generate the menu items\n * @param {boolean} arguments.isLocked Communicates if the story is locked by another user so we can disable any actions necessary\n * @return {Array} Array of menu items\n */\nexport const generateStoryMenu = ({ menuItems, story, isLocked }) => {\n  const defaultFn = menuItems.default ? () => menuItems.default(story) : noop;\n  const getMenuItem = (value) =>\n    menuItems.find((item) => item?.value === value);\n\n  const menuItemsFiltered = menuItems.filter(\n    (item) => typeof item.isEnabled === 'undefined' || item.isEnabled(story)\n  );\n\n  return menuItemsFiltered.map(({ capability, value, ...menuItem }) => {\n    const menu = getMenuItem(value);\n    const extraProperties = {\n      onClick: menu ? () => menu['action'](story) : defaultFn,\n    };\n\n    switch (value) {\n      case STORY_CONTEXT_MENU_ACTIONS.OPEN_IN_EDITOR:\n        extraProperties.href = story.bottomTargetAction;\n        extraProperties.openNewTab = false;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.OPEN_STORY_LINK:\n        extraProperties.href = story.previewLink;\n        extraProperties.openNewTab = true;\n        break;\n      case STORY_CONTEXT_MENU_ACTIONS.RENAME:\n      case STORY_CONTEXT_MENU_ACTIONS.DELETE:\n        extraProperties.disabled = isLocked;\n        break;\n      default:\n        break;\n    }\n\n    // Since action was already used in onClick, and it would become an invalid attribute value for <a> or <button> tag.\n    delete menuItem?.action;\n\n    return {\n      ...menuItem,\n      ...extraProperties,\n    };\n  });\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/popoverMenu/test/story-menu-generator.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { STORY_CONTEXT_MENU_ITEMS } from '../../../constants';\nimport { generateStoryMenu } from '../story-menu-generator';\n\nconst TEST_STORY = {\n  previewLink: 'preview-link',\n  bottomTargetAction: 'bottom-target-action',\n  capabilities: {\n    hasEditAction: true,\n    hasDeleteAction: true,\n  },\n};\n\ndescribe('generateStoryMenu', () => {\n  it('should generate menu items of the correct shape', () => {\n    const menuItems = generateStoryMenu({\n      menuItems: STORY_CONTEXT_MENU_ITEMS,\n      story: TEST_STORY,\n    });\n\n    expect(menuItems).toStrictEqual([\n      expect.objectContaining({\n        href: 'bottom-target-action',\n        label: 'Open in editor',\n        openNewTab: false,\n        onClick: expect.any(Function),\n      }),\n      expect.objectContaining({\n        href: 'preview-link',\n        label: 'Open in new tab',\n        openNewTab: true,\n        onClick: expect.any(Function),\n      }),\n      expect.objectContaining({\n        label: 'Copy Story URL',\n        onClick: expect.any(Function),\n      }),\n      expect.objectContaining({\n        label: 'Rename',\n        onClick: expect.any(Function),\n      }),\n      expect.objectContaining({\n        label: 'Duplicate',\n        onClick: expect.any(Function),\n      }),\n      expect.objectContaining({\n        label: 'Delete Story',\n        onClick: expect.any(Function),\n      }),\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/scrollToTop/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Button, ButtonVariant, Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useLayoutContext } from '../layout';\n\nconst StyledButton = styled(Button)(\n  ({ $isVisible, theme }) => css`\n    position: fixed;\n    right: 40px;\n    bottom: 40px;\n    height: 50px;\n    width: 50px;\n    display: flex;\n    align-self: center;\n    justify-content: space-around;\n    align-items: center;\n    contain: content;\n    padding: 8px;\n    background-color: ${theme.colors.opacity.white64};\n    pointer-events: ${$isVisible ? 'auto' : 'none'};\n    box-shadow: 0px 4px 14px rgba(0, 0, 0, 0.25);\n    opacity: ${Number($isVisible)};\n    transition: opacity 300ms ease-in-out;\n  `\n);\n\nconst DropUpArrowIcon = styled(Icons.ChevronUp)`\n  position: relative;\n  transform: scale(2.4);\n`;\n\nconst ScrollToTop = () => {\n  const [isVisible, setIsVisible] = useState(false);\n  const {\n    actions: { scrollToTop },\n  } = useLayoutContext();\n\n  const handleScroll = useDebouncedCallback(\n    () => setIsVisible(window.scrollY > 0),\n    100\n  );\n\n  useEffect(() => {\n    window.addEventListener('scroll', handleScroll, { passive: true });\n    return () => {\n      window.removeEventListener('scroll', handleScroll, { passive: true });\n    };\n  }, [handleScroll]);\n\n  return (\n    <StyledButton\n      disabled={!isVisible}\n      aria-label={__('Scroll back to top', 'web-stories')}\n      data-testid=\"scroll-to-top-button\"\n      $isVisible={isVisible}\n      onClick={scrollToTop}\n      variant={ButtonVariant.Circle}\n    >\n      <DropUpArrowIcon aria-hidden />\n    </StyledButton>\n  );\n};\n\nexport default ScrollToTop;\n"
  },
  {
    "path": "packages/dashboard/src/components/scrollToTop/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport ScrollToTop from '..';\nimport Layout from '../../layout';\n\nexport default {\n  title: 'Dashboard/Components/ScrollToTop',\n  component: ScrollToTop,\n};\n\nconst Container = styled.div`\n  width: 100%;\n  height: 3000px;\n  overflow: scroll;\n  background-color: blue;\n  opacity: 0.25;\n`;\nexport const _default = {\n  render: function Render() {\n    return (\n      <Layout.Provider>\n        <Container />\n        <ScrollToTop />\n      </Layout.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/scrollToTop/test/scrollToTop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport ScrollToTop from '..';\nimport Layout from '../../layout';\n\ndescribe('ScrollToTop', () => {\n  it('should render a <ScrollToTop /> by default', () => {\n    renderWithProviders(\n      <Layout.Provider>\n        <ScrollToTop />\n      </Layout.Provider>\n    );\n\n    const Button = screen.getByTestId('scroll-to-top-button');\n\n    expect(Button).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/storyMenu/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { Fragment, useCallback } from '@googleforcreators/react';\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { MoreVertical as MoreVerticalSvg } from '../../icons';\n\nexport const CONTEXT_MENU_BUTTON_CLASS = 'context-menu-button';\n\nexport const MoreVerticalButton = styled.button`\n  display: flex;\n  background: transparent;\n  padding: 0 8px;\n  opacity: ${({ menuOpen, isVisible }) => (menuOpen || isVisible ? 1 : 0)};\n  transition: opacity ease-in-out 300ms;\n  cursor: pointer;\n  color: ${({ theme, $isInverted }) =>\n    $isInverted\n      ? theme.colors.inverted.fg.primary\n      : theme.colors.interactiveFg.brandNormal};\n  & > svg {\n    width: 4px;\n    max-height: 100%;\n  }\n\n  border: 0;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  ${({ theme, $isInverted }) =>\n    themeHelpers.focusableOutlineCSS(\n      false,\n      $isInverted ? theme.colors.standard.black : false\n    )};\n`;\n\nMoreVerticalButton.propTypes = {\n  menuOpen: PropTypes.bool,\n};\n\nconst MenuContainer = styled.div`\n  position: relative;\n  align-self: ${({ verticalAlign = 'flex-start' }) => verticalAlign};\n  text-align: right;\n  ${({ $menuStyleOverrides }) => $menuStyleOverrides}\n\n  & > div {\n    margin: 0; /* 0 out margin that is needed by default on other instances of popover menus */\n  }\n`;\n\nMenuContainer.propTypes = {\n  verticalAlign: PropTypes.oneOf(['center', 'flex-start', 'flex-end']),\n};\n\nexport default function StoryMenu({\n  contextMenuId,\n  onMoreButtonSelected,\n  storyId,\n  verticalAlign,\n  menuItems,\n  itemActive,\n  tabIndex,\n  menuStyleOverrides,\n  menuLabel,\n  isInverted,\n}) {\n  const isPopoverMenuOpen = contextMenuId === storyId;\n\n  const handleDismiss = useCallback(\n    (evt) => onMoreButtonSelected(evt, -1),\n    [onMoreButtonSelected]\n  );\n\n  return (\n    <MenuContainer\n      verticalAlign={verticalAlign}\n      data-testid={`story-context-menu-${storyId}`}\n      $menuStyleOverrides={menuStyleOverrides}\n    >\n      <MoreVerticalButton\n        data-testid={`story-context-button-${storyId}`}\n        tabIndex={tabIndex}\n        menuOpen={isPopoverMenuOpen}\n        isVisible={itemActive}\n        aria-label={menuLabel || __('More Options', 'web-stories')}\n        onClick={(evt) =>\n          onMoreButtonSelected(evt, isPopoverMenuOpen ? -1 : storyId)\n        }\n        className={CONTEXT_MENU_BUTTON_CLASS}\n        $isInverted={isInverted}\n      >\n        <MoreVerticalSvg />\n      </MoreVerticalButton>\n      <ContextMenu animate isOpen={isPopoverMenuOpen} onDismiss={handleDismiss}>\n        {menuItems.map(({ label, separator, ...props }) => {\n          // eslint-disable-next-line react/prop-types -- map is not picking up definition from StoryMenu proptypes.\n          const MenuItem = props.href\n            ? ContextMenuComponents.MenuLink\n            : ContextMenuComponents.MenuButton;\n\n          return (\n            <Fragment key={label}>\n              {separator === 'top' && <ContextMenuComponents.MenuSeparator />}\n              <MenuItem {...props}>{label}</MenuItem>\n              {separator === 'bottom' && (\n                <ContextMenuComponents.MenuSeparator />\n              )}\n            </Fragment>\n          );\n        })}\n      </ContextMenu>\n    </MenuContainer>\n  );\n}\n\nStoryMenu.propTypes = {\n  isInverted: PropTypes.bool,\n  itemActive: PropTypes.bool,\n  tabIndex: PropTypes.number,\n  storyId: PropTypes.number.isRequired,\n  onMoreButtonSelected: PropTypes.func.isRequired,\n  contextMenuId: PropTypes.number.isRequired,\n  menuItems: PropTypes.arrayOf(\n    PropTypes.shape({\n      disabled: PropTypes.bool,\n      href: PropTypes.string,\n      label: PropTypes.string.isRequired,\n      openNewTab: PropTypes.bool,\n      onClick: PropTypes.func,\n      onFocus: PropTypes.func,\n    })\n  ).isRequired,\n  menuLabel: PropTypes.string,\n  menuStyleOverrides: PropTypes.array,\n  verticalAlign: PropTypes.oneOf(['center', 'flex-start', 'flex-end']),\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/storyMenu/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport StoryMenu, { MoreVerticalButton } from '..';\nimport { STORY_CONTEXT_MENU_ITEMS } from '../../../constants';\n\nconst Container = styled.div`\n  margin: 200px 0 0 50px;\n  width: 300px;\n  display: flex;\n  justify-content: space-between;\n  border: 1px solid gray;\n\n  &:hover ${MoreVerticalButton}, &:active ${MoreVerticalButton} {\n    opacity: 1;\n  }\n`;\n\nexport default {\n  title: 'Dashboard/Components/StoryMenu',\n  component: StoryMenu,\n};\n\nexport const _default = {\n  render: function Render() {\n    const [contextMenuId, setContextMenuId] = useState(-1);\n    return (\n      <Container>\n        <p>{'Hover over me to see menu button'}</p>\n        <StoryMenu\n          onMoreButtonSelected={setContextMenuId}\n          contextMenuId={contextMenuId}\n          onMenuItemSelected={() => {\n            setContextMenuId(-1);\n          }}\n          menuItems={STORY_CONTEXT_MENU_ITEMS}\n          story={{ id: 1, status: 'publish', title: 'Sample Story' }}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/storyMenu/test/storyMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport StoryMenu from '..';\nimport { STORY_CONTEXT_MENU_ITEMS } from '../../../constants';\n\nconst mockMenuItemSelected = jest.fn();\n\nconst menuItems = STORY_CONTEXT_MENU_ITEMS.map((menuItem) => ({\n  ...menuItem,\n  onClick: () => mockMenuItemSelected(`called: ${menuItem.value}`),\n}));\n\ndescribe('StoryMenu', () => {\n  beforeEach(jest.clearAllMocks);\n\n  it('should render a button by default', () => {\n    renderWithProviders(\n      <StoryMenu\n        onMoreButtonSelected={jest.fn}\n        contextMenuId={1}\n        menuItems={menuItems}\n        storyId={1}\n      />\n    );\n\n    const menuButton = screen.getAllByRole('button')[0];\n    expect(menuButton).toBeInTheDocument();\n  });\n\n  it('should get access to menu on button click', () => {\n    const mockOnMoreButtonSelected = jest.fn();\n\n    renderWithProviders(\n      <StoryMenu\n        onMoreButtonSelected={mockOnMoreButtonSelected}\n        contextMenuId={1}\n        menuItems={menuItems}\n        storyId={1}\n      />\n    );\n\n    const menuButton = screen.getAllByRole('button')[0];\n    fireEvent.click(menuButton);\n    expect(mockOnMoreButtonSelected).toHaveBeenCalledOnce();\n  });\n\n  it('should call onMenuItemSelected when menu item is clicked', () => {\n    renderWithProviders(\n      <StoryMenu\n        onMoreButtonSelected={jest.fn}\n        contextMenuId={1}\n        menuItems={menuItems}\n        storyId={1}\n      />\n    );\n\n    const menuItem = screen.getAllByRole('menuitem')[0];\n\n    fireEvent.click(menuItem);\n\n    expect(mockMenuItemSelected).toHaveBeenCalledOnce();\n    expect(mockMenuItemSelected).toHaveBeenCalledWith(\n      `called: ${STORY_CONTEXT_MENU_ITEMS[0].value}`\n    );\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/table/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { STORY_PREVIEW_WIDTH, VIEWPORT_BREAKPOINT } from '../../constants';\n\nconst CELL_PADDING = 16;\n\nexport const Table = styled.table`\n  ${themeHelpers.expandTextPreset(\n    ({ paragraph }, { Small }) => paragraph[Small]\n  )}\n  border-collapse: collapse;\n  width: inherit;\n`;\n\nexport const TableBody = styled.tbody``;\n\nexport const TableHeader = styled.thead`\n  background: ${({ theme }) => theme.colors.bg.secondary};\n`;\n\nexport const StickyTableHeader = styled(TableHeader)`\n  width: 100%;\n  border-top: 0;\n  border-bottom: 0;\n\n  th {\n    height: 100%;\n    background: ${({ theme }) => theme.colors.bg.secondary};\n    position: sticky;\n    z-index: 2;\n    top: ${({ topOffset }) => `${topOffset}px`};\n\n    :first-child {\n      border-top-left-radius: ${({ theme }) => theme.borders.radius.small};\n      border-bottom-left-radius: ${({ theme }) => theme.borders.radius.small};\n    }\n\n    :last-child {\n      border-top-right-radius: ${({ theme }) => theme.borders.radius.small};\n      border-bottom-right-radius: ${({ theme }) => theme.borders.radius.small};\n    }\n  }\n`;\n\nexport const TableHeaderCell = styled.th`\n  padding: 16px;\n  text-align: left;\n  white-space: nowrap;\n`;\n\nexport const TablePreviewHeaderCell = styled(TableHeaderCell)`\n  padding-right: 0;\n`;\n\nexport const TableDateHeaderCell = styled(TableHeaderCell)`\n  min-width: 160px;\n`;\n\nexport const TableStatusHeaderCell = styled(TableHeaderCell)`\n  display: table-cell;\n  min-width: 100px;\n\n  @media ${({ theme }) => theme.breakpoint.tabletMax} {\n    display: none;\n  }\n`;\n\nexport const TableAuthorHeaderCell = styled(TableHeaderCell)`\n  min-width: 110px;\n`;\n\nexport const TableTitleHeaderCell = styled(TableHeaderCell)`\n  padding-left: 0;\n  width: 30%;\n  min-width: 135px;\n\n  span {\n    display: none;\n    margin-right: 5px;\n  }\n`;\n\nexport const TableContentHeaderCell = styled(TableHeaderCell)`\n  width: 17.5%;\n  min-width: 150px;\n`;\n\nexport const TableRow = styled.tr`\n  min-width: 1250px;\n\n  @media ${({ theme }) => theme.breakpoint.tabletMax} {\n    min-width: 0;\n  }\n`;\n\nexport const TableCell = styled.td`\n  padding: ${CELL_PADDING}px;\n  font-weight: normal;\n  overflow-wrap: anywhere;\n  word-break: normal;\n  height: ${CELL_PADDING * 2 + 50}px;\n  vertical-align: middle;\n\n  span {\n    color: ${({ theme }) => theme.colors.standard.black};\n    line-height: 20px;\n  }\n`;\n\nexport const TableStatusCell = styled(TableCell)`\n  display: table-cell;\n\n  span {\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n\n  @media ${({ theme }) => theme.breakpoint.tabletMax} {\n    display: none;\n  }\n`;\n\nexport const TableTitleCell = styled(TableCell)`\n  width: 30%;\n  word-wrap: break-word;\n`;\n\nexport const TableContentCell = styled(TableCell)`\n  width: 17.5%;\n  min-width: 150px;\n  word-wrap: break-word;\n`;\n\nexport const TablePreviewCell = styled(TableCell)`\n  width: ${STORY_PREVIEW_WIDTH[VIEWPORT_BREAKPOINT.THUMBNAIL]}px;\n`;\n"
  },
  {
    "path": "packages/dashboard/src/components/table/stories/table.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHeaderCell,\n  TableRow,\n  TableHeader,\n} from '..';\n\nexport default {\n  title: 'Dashboard/Components/Table',\n  component: Table,\n  args: {\n    tableHeaderPrimary: 'Title',\n    tableHeaderSecondary: 'Author',\n    tableHeaderTertiary: 'Date',\n  },\n};\n\nconst tableData = [\n  {\n    id: 1,\n    title: 'Fashion',\n    author: { name: 'Carlos', id: 1 },\n    date: 'July 13',\n  },\n  { id: 2, title: 'Sports', author: { name: 'Max', id: 1 }, date: 'April 12' },\n  {\n    id: 3,\n    title: 'Music & Vinyl',\n    author: { name: 'Brittany', id: 1 },\n    date: 'March 27',\n  },\n  {\n    id: 4,\n    title: 'Arts & Culture',\n    author: { name: 'Mariano', id: 1 },\n    date: 'September 5',\n  },\n];\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Table>\n        <TableHeader>\n          <TableRow>\n            <TableHeaderCell>{args.tableHeaderPrimary}</TableHeaderCell>\n            <TableHeaderCell>{args.tableHeaderSecondary}</TableHeaderCell>\n            <TableHeaderCell>{args.tableHeaderTertiary}</TableHeaderCell>\n          </TableRow>\n        </TableHeader>\n\n        <TableBody>\n          {tableData.map((data) => (\n            <TableRow key={data.id}>\n              <TableCell>{data.title}</TableCell>\n              <TableCell>{data.author.name}</TableCell>\n              <TableCell>{data.date}</TableCell>\n            </TableRow>\n          ))}\n        </TableBody>\n      </Table>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/tooltip/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Tooltip } from './tooltip';\n"
  },
  {
    "path": "packages/dashboard/src/components/tooltip/tooltip.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  RTL_PLACEMENT,\n  Tooltip as BaseTooltip,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app/config';\n\nexport default function Tooltip({ placement = Placement.Bottom, ...props }) {\n  const { isRTL } = useConfig();\n  const derivedPlacement = isRTL ? RTL_PLACEMENT[placement] : placement;\n\n  return <BaseTooltip placement={derivedPlacement} {...props} />;\n}\nTooltip.propTypes = {\n  children: PropTypes.node.isRequired,\n  hasTail: PropTypes.bool,\n  placement: PropTypes.oneOf(Object.values(Placement)),\n  onBlur: PropTypes.func,\n  onFocus: PropTypes.func,\n  shortcut: PropTypes.string,\n  title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),\n  forceAnchorRef: PropTypes.object,\n  styleOverride: PropTypes.object,\n  className: PropTypes.string,\n  isDelayed: PropTypes.bool,\n  popupZIndexOverride: PropTypes.number,\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/types.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\nexport const ColorType = PropTypes.shape({\n  label: PropTypes.string.isRequired,\n  color: PropTypes.string.isRequired,\n});\n"
  },
  {
    "path": "packages/dashboard/src/components/viewStyleBar/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Icons,\n  themeHelpers,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { VIEW_STYLE, VIEW_STYLE_LABELS } from '../../constants';\nimport { Tooltip } from '../tooltip';\n\nconst Container = styled.div`\n  display: flex;\n  justify-content: flex-end;\n  align-items: center;\n`;\n\nconst ToggleButton = styled.button`\n  border: none;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${themeHelpers.focusableOutlineCSS}\n  padding: 0;\n  background: transparent;\n  cursor: pointer;\n\n  &:hover svg {\n    color: ${({ theme }) => theme.colors.interactiveFg.hover};\n  }\n  &:active svg {\n    color: ${({ theme }) => theme.colors.interactiveFg.active};\n  }\n`;\n\nexport default function ViewStyleBar({ onPress, layoutStyle }) {\n  return (\n    <Container>\n      <Tooltip\n        title={VIEW_STYLE_LABELS[layoutStyle]}\n        placement={Placement.BottomEnd}\n        hasTail\n      >\n        <ToggleButton\n          aria-label={VIEW_STYLE_LABELS[layoutStyle]}\n          onClick={onPress}\n        >\n          {layoutStyle === VIEW_STYLE.GRID && (\n            <Icons.Table height=\"32px\" width=\"32px\" data-testid=\"list-icon\" />\n          )}\n          {layoutStyle === VIEW_STYLE.LIST && (\n            <Icons.Box4 height=\"32px\" width=\"32px\" data-testid=\"grid-icon\" />\n          )}\n        </ToggleButton>\n      </Tooltip>\n    </Container>\n  );\n}\n\nViewStyleBar.propTypes = {\n  onPress: PropTypes.func,\n  layoutStyle: PropTypes.oneOf([VIEW_STYLE.GRID, VIEW_STYLE.LIST]).isRequired,\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/viewStyleBar/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { VIEW_STYLE } from '../../../constants';\nimport ViewStyleBar from '..';\n\nexport default {\n  title: 'Dashboard/Components/ViewStyleBar',\n  component: ViewStyleBar,\n  argTypes: {\n    layoutStyle: {\n      options: Object.values(VIEW_STYLE),\n    },\n    onPress: {\n      action: 'on press clicked',\n    },\n  },\n  args: {\n    layoutStyle: VIEW_STYLE.LIST,\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <ViewStyleBar {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/components/viewStyleBar/test/viewStyleBar.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { VIEW_STYLE } from '../../../constants';\nimport { renderWithProviders } from '../../../testUtils';\nimport ViewStyleBar from '..';\n\ndescribe('<ViewStyleBar />', () => {\n  const mockPress = jest.fn();\n\n  it(`should render the list icon when layoutStyle is ${VIEW_STYLE.GRID}`, () => {\n    renderWithProviders(\n      <ViewStyleBar layoutStyle={VIEW_STYLE.GRID} onPress={mockPress} />\n    );\n\n    const listIcon = screen.getByTestId('list-icon');\n    expect(listIcon).toBeInTheDocument();\n\n    const gridIcon = screen.queryByTestId('grid-icon');\n    expect(gridIcon).not.toBeInTheDocument();\n  });\n\n  it(`should render the grid icon when layoutStyle is ${VIEW_STYLE.LIST}`, () => {\n    renderWithProviders(\n      <ViewStyleBar layoutStyle={VIEW_STYLE.LIST} onPress={mockPress} />\n    );\n\n    const gridIcon = screen.getByTestId('grid-icon');\n    expect(gridIcon).toBeInTheDocument();\n\n    const listIcon = screen.queryByTestId('list-icon');\n    expect(listIcon).not.toBeInTheDocument();\n  });\n\n  it('should have triggered mockPress once on onPress click', () => {\n    renderWithProviders(\n      <ViewStyleBar layoutStyle={VIEW_STYLE.LIST} onPress={mockPress} />\n    );\n\n    const gridIcon = screen.getByTestId('grid-icon');\n\n    fireEvent.click(gridIcon);\n    expect(mockPress).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/constants/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ButtonType = {\n  CTA: 'cta',\n  DEFAULT: 'default',\n  PRIMARY: 'primary',\n  SECONDARY: 'secondary',\n};\n\nexport const DROPDOWN_TYPES = {\n  MENU: 'menu',\n  PANEL: 'panel',\n  COLOR_PANEL: 'color_panel',\n};\n\nexport const DEFAULT_FILE_UPLOAD_TYPES = ['.jpg', '.jpeg', '.png', '.gif'];\n"
  },
  {
    "path": "packages/dashboard/src/constants/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n/**\n * Internal dependencies\n */\nimport { Compass, HomeWithHeart } from '../icons';\nimport { STORY_VIEWING_LABELS } from './stories';\nimport { TEMPLATES_GALLERY_VIEWING_LABELS } from './templates';\n\nexport const KEYBOARD_USER_CLASS = `useskeyboard`;\n\nexport const Z_INDEX = {\n  LAYOUT_SQUISHABLE: 3,\n  LAYOUT_FIXED: 5,\n  STICKY_TABLE: 2,\n  POPOVER_MENU: 10,\n  POPOVER_PANEL: 10,\n};\n\nexport const APP_ROUTES = {\n  DASHBOARD: '/',\n  TEMPLATES_GALLERY: '/templates-gallery',\n  TEMPLATE_DETAIL: 'template-detail',\n};\n\nexport const ROUTE_TITLES = {\n  [APP_ROUTES.DASHBOARD]: __('Dashboard', 'web-stories'),\n  [APP_ROUTES.TEMPLATES_GALLERY]: __('Explore Templates', 'web-stories'),\n  [`${APP_ROUTES.TEMPLATES_GALLERY}/${APP_ROUTES.TEMPLATE_DETAIL}`]: __(\n    'Template Details',\n    'web-stories'\n  ),\n  DEFAULT: __('Dashboard', 'web-stories'),\n};\n\nexport const PRIMARY_PATHS = [\n  {\n    value: APP_ROUTES.DASHBOARD,\n    label: ROUTE_TITLES[APP_ROUTES.DASHBOARD],\n    Icon: HomeWithHeart,\n  },\n  {\n    value: APP_ROUTES.TEMPLATES_GALLERY,\n    label: ROUTE_TITLES[APP_ROUTES.TEMPLATES_GALLERY],\n    Icon: Compass,\n  },\n];\n\nexport const VIEW_STYLE = {\n  GRID: 'grid',\n  LIST: 'list',\n};\n\nexport const VIEW_STYLE_LABELS = {\n  [VIEW_STYLE.GRID]: __('Switch to List View', 'web-stories'),\n  [VIEW_STYLE.LIST]: __('Switch to Grid View', 'web-stories'),\n};\n\nexport const DASHBOARD_VIEWS = {\n  DASHBOARD: 'DASHBOARD',\n  TEMPLATES_GALLERY: 'TEMPLATES_GALLERY',\n};\nexport const RESULT_LABELS = {\n  [DASHBOARD_VIEWS.DASHBOARD]: { ...STORY_VIEWING_LABELS },\n  [DASHBOARD_VIEWS.TEMPLATES_GALLERY]: { ...TEMPLATES_GALLERY_VIEWING_LABELS },\n};\n\n// API Query Constants\nexport const STORIES_PER_REQUEST = 24;\n\nexport const TEXT_INPUT_DEBOUNCE = 300;\n\nexport const MIN_IMG_HEIGHT = 96;\nexport const MIN_IMG_WIDTH = 96;\n\nexport const DEFAULT_GRID_IMG_HEIGHT = 853;\nexport const DEFAULT_GRID_IMG_WIDTH = 640;\n\nexport * from './components';\nexport * from './pageStructure';\nexport * from './stories';\nexport * from './templates';\n"
  },
  {
    "path": "packages/dashboard/src/constants/pageStructure.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { PAGE_RATIO, PAGE_WIDTH, PAGE_HEIGHT } from '@googleforcreators/units';\n\nexport const DASHBOARD_LEFT_NAV_WIDTH = 288;\n\nexport const MIN_DASHBOARD_WIDTH = 1098;\n\nexport const VIEWPORT_BREAKPOINT = {\n  TABLET: 'tablet',\n  DESKTOP: 'desktop',\n  THUMBNAIL: 'thumbnail',\n};\n\nexport const STORY_PREVIEW_WIDTH = {\n  [VIEWPORT_BREAKPOINT.TABLET]: 200,\n  [VIEWPORT_BREAKPOINT.DESKTOP]: 232,\n  [VIEWPORT_BREAKPOINT.THUMBNAIL]: 33,\n};\n\nexport const GRID_SPACING = {\n  COLUMN_GAP: 24,\n  ROW_GAP: 32,\n};\n\nexport const PAGE_WRAPPER = {\n  GUTTER: 52,\n};\n"
  },
  {
    "path": "packages/dashboard/src/constants/stories.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf, _n } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { DashboardStory } from '../types/configProvider';\n\nexport const STORY_CONTEXT_MENU_ACTIONS = {\n  OPEN_IN_EDITOR: 'open-in-editor-action',\n  RENAME: 'rename-action',\n  DUPLICATE: 'duplicate-action',\n  DELETE: 'delete-story-action',\n  COPY_STORY_LINK: 'copy-story-link',\n  OPEN_STORY_LINK: 'open-story-link',\n  CLOSE: 'close-menu',\n};\n\nexport const STORY_CONTEXT_MENU_ITEMS = [\n  {\n    label: __('Open in editor', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.OPEN_IN_EDITOR,\n    isEnabled: (story: DashboardStory) =>\n      Boolean(story?.capabilities?.hasEditAction),\n  },\n  {\n    label: __('Open in new tab', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.OPEN_STORY_LINK,\n    isEnabled: (story: DashboardStory) => Boolean(story?.previewLink),\n  },\n  {\n    label: __('Copy Story URL', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.COPY_STORY_LINK,\n    isEnabled: (story: DashboardStory) => Boolean(story?.previewLink),\n  },\n  {\n    label: __('Rename', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.RENAME,\n    separator: 'top',\n    isEnabled: (story: DashboardStory) =>\n      Boolean(story?.capabilities?.hasEditAction),\n  },\n  {\n    label: __('Duplicate', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.DUPLICATE,\n    isEnabled: (story: DashboardStory) =>\n      Boolean(story?.capabilities?.hasEditAction),\n  },\n  {\n    label: __('Delete Story', 'web-stories'),\n    value: STORY_CONTEXT_MENU_ACTIONS.DELETE,\n    separator: 'top',\n    isEnabled: (story: DashboardStory) =>\n      Boolean(story?.capabilities?.hasDeleteAction),\n  },\n];\n\nexport const SORT_DIRECTION = {\n  ASC: 'asc',\n  DESC: 'desc',\n};\n\nexport const STORY_SORT_OPTIONS = {\n  NAME: 'title',\n  DATE_CREATED: 'date',\n  LAST_MODIFIED: 'modified',\n  CREATED_BY: 'story_author',\n};\n\nexport const STORY_SORT_KEYS = {\n  orderby: STORY_SORT_OPTIONS,\n  order: SORT_DIRECTION,\n};\n\nexport const ORDER_BY_SORT = {\n  [STORY_SORT_OPTIONS.NAME]: SORT_DIRECTION.ASC,\n  [STORY_SORT_OPTIONS.DATE_CREATED]: SORT_DIRECTION.DESC,\n  [STORY_SORT_OPTIONS.LAST_MODIFIED]: SORT_DIRECTION.DESC,\n  [STORY_SORT_OPTIONS.CREATED_BY]: SORT_DIRECTION.ASC,\n};\n\nexport const STORY_SORT_MENU_ITEMS = [\n  {\n    label: __('Name', 'web-stories'),\n    value: STORY_SORT_OPTIONS.NAME,\n  },\n  {\n    label: __('Date Created', 'web-stories'),\n    value: STORY_SORT_OPTIONS.DATE_CREATED,\n  },\n  {\n    label: __('Last Modified', 'web-stories'), // default\n    value: STORY_SORT_OPTIONS.LAST_MODIFIED,\n  },\n  {\n    label: __('Created By', 'web-stories'),\n    value: STORY_SORT_OPTIONS.CREATED_BY,\n  },\n];\n\n/**\n * All possible story statuses.\n */\nconst BASE_STATUSES = {\n  DRAFT: 'draft',\n  FUTURE: 'future',\n  PENDING: 'pending',\n  PUBLISH: 'publish',\n  PRIVATE: 'private',\n};\n\nexport const STORY_STATUS = {\n  ALL: Object.values(BASE_STATUSES).join(','),\n  PUBLISHED_AND_FUTURE: [BASE_STATUSES.PUBLISH, BASE_STATUSES.FUTURE].join(','),\n  ...BASE_STATUSES,\n};\n\nexport const DISPLAY_STATUS = {\n  [STORY_STATUS.PUBLISH]: __('Published', 'web-stories'),\n  [STORY_STATUS.PENDING]: __('Pending', 'web-stories'),\n  [STORY_STATUS.FUTURE]: __('Scheduled', 'web-stories'),\n  [STORY_STATUS.DRAFT]: __('Draft', 'web-stories'),\n  [STORY_STATUS.PRIVATE]: __('Private', 'web-stories'),\n};\n\nexport const STORY_STATUSES = [\n  {\n    label: __('All Stories', 'web-stories'),\n    value: STORY_STATUS.ALL,\n    status: 'all',\n  },\n  {\n    label: __('Drafts', 'web-stories'),\n    value: STORY_STATUS.DRAFT,\n    status: STORY_STATUS.DRAFT,\n  },\n  {\n    label: __('Pending', 'web-stories'),\n    value: STORY_STATUS.PENDING,\n    status: STORY_STATUS.PENDING,\n  },\n  {\n    label: __('Published', 'web-stories'),\n    value: STORY_STATUS.PUBLISH,\n    status: STORY_STATUS.PUBLISH,\n  },\n  {\n    label: __('Scheduled', 'web-stories'),\n    value: STORY_STATUS.FUTURE,\n    status: STORY_STATUS.FUTURE,\n  },\n  {\n    label: __('Private', 'web-stories'),\n    value: STORY_STATUS.PRIVATE,\n    status: STORY_STATUS.PRIVATE,\n  },\n];\n\nexport const STORY_VIEWING_LABELS = {\n  [STORY_STATUS.ALL]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of stories in view */\n      _n(\n        'Viewing <strong>%d</strong> story',\n        'Viewing all <strong>%d</strong> stories',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n  [STORY_STATUS.DRAFT]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of draft stories in view */\n      _n(\n        'Viewing <strong>%d</strong> draft',\n        'Viewing <strong>%d</strong> drafts',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n  [STORY_STATUS.PUBLISH]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of stories */\n      _n(\n        'Viewing <strong>%d</strong> published story',\n        'Viewing <strong>%d</strong> published stories',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n  [STORY_STATUS.FUTURE]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of stories */\n      _n(\n        'Viewing <strong>%d</strong> scheduled story',\n        'Viewing <strong>%d</strong> scheduled stories',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n  [STORY_STATUS.PENDING]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of stories */\n      _n(\n        'Viewing <strong>%d</strong> pending story',\n        'Viewing <strong>%d</strong> pending stories',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n  [STORY_STATUS.PRIVATE]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of stories */\n      _n(\n        'Viewing <strong>%d</strong> private story',\n        'Viewing <strong>%d</strong> private stories',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n};\n\nexport const STORY_ANIMATION_STATE = {\n  RESET: 'reset',\n  PAUSED: 'paused',\n  SCRUBBING: 'scrubbing',\n  PLAYING: 'playing',\n};\n\nexport const DEFAULT_FILTERS = {\n  filters: {\n    status: STORY_STATUS.ALL,\n  },\n  sort: {\n    orderby: STORY_SORT_OPTIONS.LAST_MODIFIED,\n    order: ORDER_BY_SORT[STORY_SORT_OPTIONS.LAST_MODIFIED],\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/constants/templates.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x, sprintf, _n } from '@googleforcreators/i18n';\n\nexport const TEMPLATE_CATEGORIES = {\n  DIY_CRAFTS: 'diy_crafts',\n  MOVIES_TV: 'movies_tv',\n  BEAUTY_STYLE: 'beauty_style',\n  FITNESS_WELLBEING: 'fitness_wellbeing',\n  FOOD: 'food',\n  TRAVEL: 'travel',\n  MUSIC: 'music',\n  SPORTS: 'sports',\n};\n\nexport const TEMPLATE_CATEGORY_ITEMS = [\n  {\n    label: _x('DIY & Crafts', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.DIY_CRAFTS,\n  },\n  {\n    label: _x('Movies & TV', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.MOVIES_TV,\n  },\n  {\n    label: _x('Beauty & Style', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.BEAUTY_STYLE,\n  },\n  {\n    label: _x('Fitness & Wellbeing', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.FITNESS_WELLBEING,\n  },\n  {\n    label: _x('Food', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.FOOD,\n  },\n  {\n    label: _x('Travel', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.TRAVEL,\n  },\n  {\n    label: _x('Music', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.MUSIC,\n  },\n  {\n    label: _x('Sports', 'template vertical', 'web-stories'),\n    value: TEMPLATE_CATEGORIES.SPORTS,\n  },\n];\n\nexport const TEMPLATE_COLORS = {\n  WHITE: 'white',\n  BLACK: 'black',\n  GRAY: 'gray',\n  BROWN: 'brown',\n  RED: 'red',\n  ORANGE: 'orange',\n  YELLOW: 'yellow',\n  GREEN: 'green',\n  BLUE: 'blue',\n  PINK: 'pink',\n  PURPLE: 'purple',\n};\n\nexport const TEMPLATE_COLOR_ITEMS = [\n  {\n    label: _x('White', 'color', 'web-stories'),\n    hex: '#FFFFFF',\n    value: TEMPLATE_COLORS.WHITE,\n  },\n  {\n    label: _x('Black', 'color', 'web-stories'),\n    hex: '#1A1D1F',\n    value: TEMPLATE_COLORS.BLACK,\n  },\n  {\n    label: _x('Gray', 'color', 'web-stories'),\n    hex: '#9AA1A9',\n    value: TEMPLATE_COLORS.GRAY,\n  },\n  {\n    label: _x('Brown', 'color', 'web-stories'),\n    hex: '#974A04',\n    value: TEMPLATE_COLORS.BROWN,\n  },\n  {\n    label: _x('Red', 'color', 'web-stories'),\n    hex: '#EB5757',\n    value: TEMPLATE_COLORS.RED,\n  },\n  {\n    label: _x('Orange', 'color', 'web-stories'),\n    hex: '#FA902E',\n    value: TEMPLATE_COLORS.ORANGE,\n  },\n  {\n    label: _x('Yellow', 'color', 'web-stories'),\n    hex: '#FAE84C',\n    value: TEMPLATE_COLORS.YELLOW,\n  },\n  {\n    label: _x('Green', 'color', 'web-stories'),\n    hex: '#6AE86F',\n    value: TEMPLATE_COLORS.GREEN,\n  },\n  {\n    label: _x('Blue', 'color', 'web-stories'),\n    hex: '#1374FA',\n    value: TEMPLATE_COLORS.BLUE,\n  },\n  {\n    label: _x('Pink', 'color', 'web-stories'),\n    hex: '#F078F2',\n    value: TEMPLATE_COLORS.PINK,\n  },\n  {\n    label: _x('Purple', 'color', 'web-stories'),\n    hex: '#AA6FE1',\n    value: TEMPLATE_COLORS.PURPLE,\n  },\n];\n\nexport const TEMPLATES_GALLERY_STATUS = {\n  ALL: 'template',\n};\n\nexport const TEMPLATES_GALLERY_VIEWING_LABELS = {\n  [TEMPLATES_GALLERY_STATUS.ALL]: (n: number) =>\n    sprintf(\n      /* translators: %d: number of templates in view */\n      _n(\n        'Viewing <strong>%d</strong> template',\n        'Viewing all <strong>%d</strong> templates',\n        n,\n        'web-stories'\n      ),\n      n\n    ),\n};\n\nexport const TEMPLATE_SORT_DIRECTION = {\n  ASC: 'asc',\n  DESC: 'desc',\n};\n\nexport const TEMPLATES_GALLERY_SORT_OPTIONS = {\n  POPULAR: 'popular',\n  RECENT: 'recent',\n};\n\nexport const TEMPLATE_SORT_KEYS = {\n  orderby: TEMPLATES_GALLERY_SORT_OPTIONS,\n  order: TEMPLATE_SORT_DIRECTION,\n};\n\nexport const DEFAULT_TEMPLATE_FILTERS = {\n  filters: {\n    status: TEMPLATES_GALLERY_STATUS.ALL,\n  },\n  sort: {\n    orderby: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n  },\n};\n\nexport const TEMPLATES_GALLERY_SORT_MENU_ITEMS = [\n  {\n    label: __('Popular', 'web-stories'),\n    value: TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR,\n  },\n  {\n    label: __('Recent', 'web-stories'),\n    value: TEMPLATES_GALLERY_SORT_OPTIONS.RECENT,\n  },\n];\n\nexport const TEMPLATES_GALLERY_ITEM_CENTER_ACTION_LABELS = {\n  template: __('See details', 'web-stories'),\n};\n"
  },
  {
    "path": "packages/dashboard/src/dashboard.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  lightMode,\n  ModalGlobalStyle,\n  SnackbarProvider,\n  PopupProvider,\n  theme as externalDesignSystemTheme,\n  ThemeGlobals,\n  deepMerge,\n} from '@googleforcreators/design-system';\nimport { StyleSheetManager, ThemeProvider } from 'styled-components';\nimport stylisRTLPlugin from 'stylis-plugin-rtl';\nObject.defineProperty(stylisRTLPlugin, 'name', { value: 'stylisRTLPlugin' });\nimport PropTypes from 'prop-types';\nimport { FlagsProvider } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport { ConfigProvider } from './app/config';\nimport ApiProvider from './app/api/apiProvider';\nimport { NavProvider } from './components';\nimport { RouterProvider } from './app/router';\nimport { GlobalStyle } from './theme';\nimport { KeyboardOnlyOutline } from './utils';\nimport getDefaultConfig from './getDefaultConfig';\n\nfunction Dashboard({ config, children }) {\n  const _config = deepMerge(getDefaultConfig(), config);\n  const activeTheme = {\n    ...externalDesignSystemTheme,\n    colors: lightMode,\n  };\n  const {\n    isRTL,\n    flags,\n    styleConstants: { leftOffset, topOffset } = {},\n  } = _config;\n  return (\n    <FlagsProvider features={flags}>\n      <StyleSheetManager stylisPlugins={isRTL ? [stylisRTLPlugin] : []}>\n        <ThemeProvider theme={activeTheme}>\n          <ThemeGlobals.Styles />\n          <ModalGlobalStyle />\n          <ConfigProvider config={_config}>\n            <ApiProvider>\n              <NavProvider>\n                <RouterProvider>\n                  <SnackbarProvider>\n                    <PopupProvider\n                      value={{\n                        isRTL,\n                        leftOffset,\n                        topOffset,\n                      }}\n                    >\n                      <GlobalStyle />\n                      <KeyboardOnlyOutline />\n                      {children}\n                    </PopupProvider>\n                  </SnackbarProvider>\n                </RouterProvider>\n              </NavProvider>\n            </ApiProvider>\n          </ConfigProvider>\n        </ThemeProvider>\n      </StyleSheetManager>\n    </FlagsProvider>\n  );\n}\n\nDashboard.propTypes = {\n  config: PropTypes.object.isRequired,\n  children: PropTypes.node,\n};\n\nexport default Dashboard;\n"
  },
  {
    "path": "packages/dashboard/src/dataUtils/formattedStoriesArray.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { toUTCDate } from '@googleforcreators/date';\n\n// @todo Remove WordPress specific and unused fields.\nconst formattedStoriesArray = [\n  {\n    id: 167,\n    status: 'publish',\n    title: 'ORANGE SHAPES',\n    modified: toUTCDate('2020-05-21T23:25:51.000Z'),\n    modifiedGmt: '2020-05-21T23:25:51.000Z',\n    created: toUTCDate('2020-05-21T23:25:51.000Z'),\n    createdGmt: '2020-05-21T23:25:51.000Z',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-1.png',\n    tags: [],\n    categories: [],\n    author: {\n      name: 'Jango Fett',\n      id: 1,\n    },\n    bottomTargetAction:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=167',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n    editStoryLink:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=167',\n    previewLink: 'http://localhost:8899/wp-admin/post.php?action=edit&post=167',\n  },\n  {\n    locked: true,\n    lockUser: {\n      name: 'batgirl',\n      id: 888877665,\n      avatar:\n        'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp&f=y&s=96',\n    },\n    id: 168,\n    status: 'publish',\n    title: 'PURPLE SHAPES',\n    modified: toUTCDate('2020-05-21T23:25:35.000Z'),\n    modifiedGmt: '2020-05-21T23:25:35.000Z',\n    created: toUTCDate('2020-05-21T23:25:35.000Z'),\n    createdGmt: '2020-05-21T23:25:35.000Z',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-1.png',\n    tags: [],\n    categories: [{ name: 'Dagobah', id: 1 }],\n    author: {\n      name: 'Jango Fett',\n      id: 1,\n    },\n    bottomTargetAction:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=168',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n    editStoryLink:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=168',\n    previewLink: 'http://localhost:8899/wp-admin/post.php?action=edit&post=168',\n  },\n  {\n    id: 165,\n    status: 'draft',\n    title: 'GREEN SHAPES',\n    modified: toUTCDate('2020-05-21T23:25:22.000Z'),\n    modifiedGmt: '2020-05-21T23:25:22.000Z',\n    created: toUTCDate('2020-05-21T23:25:22.000Z'),\n    createdGmt: '2020-05-21T23:25:22.000Z',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-2.png',\n    tags: [],\n    categories: [],\n    author: {\n      name: 'Chewbacca',\n      id: 2,\n    },\n    bottomTargetAction:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=165',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n    editStoryLink:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=165',\n    previewLink: 'http://localhost:8899/wp-admin/post.php?action=edit&post=165',\n  },\n  {\n    id: 163,\n    status: 'draft',\n    title: 'RED SHAPES',\n    modified: toUTCDate('2020-05-21T23:24:47.000Z'),\n    modifiedGmt: '2020-05-21T23:24:47.000Z',\n    created: toUTCDate('2020-05-21T23:24:47.000Z'),\n    createdGmt: '2020-05-21T23:24:47.000Z',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-3.png',\n    tags: [],\n    categories: [],\n    author: {\n      name: 'Luke Skywalker',\n      id: 3,\n    },\n    bottomTargetAction:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=163',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n    editStoryLink:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=163',\n    previewLink: 'http://localhost:8899/wp-admin/post.php?action=edit&post=163',\n  },\n  {\n    id: 161,\n    status: 'private',\n    title: 'BLUE SHAPES',\n    modified: toUTCDate('2020-05-21T23:24:06.000Z'),\n    modifiedGmt: '2020-05-21T23:24:06.000Z',\n    created: toUTCDate('2020-05-21T23:24:06.000Z'),\n    createdGmt: '2020-05-21T23:24:06.000Z',\n    featuredMediaUrl: 'http://localhost:9876/__static__/featured-media-1.png',\n    tags: [],\n    categories: [],\n    author: {\n      name: 'Lando-Calrissian',\n      id: 4,\n    },\n    bottomTargetAction:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=161',\n    capabilities: {\n      hasEditAction: true,\n      hasDeleteAction: true,\n    },\n    editStoryLink:\n      'http://localhost:8899/wp-admin/post.php?action=edit&post=161',\n    previewLink: 'http://localhost:8899/wp-admin/post.php?action=edit&post=161',\n  },\n];\n\nexport default formattedStoriesArray;\n"
  },
  {
    "path": "packages/dashboard/src/dataUtils/formattedTaxonomiesArray.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst formattedTaxonomiesArray = [\n  {\n    description: '',\n    hierarchical: true,\n    name: 'Categories',\n    labels: {\n      searchItems: 'Search Categories',\n      filterByItem: 'Filter by category',\n      allItems: 'All Categories',\n    },\n    restBase: 'web_story_category',\n    restNamespace: 'web-stories/v1',\n    restPath: 'http://localhost:8899/wp-json/web-stories/v1/web_story_category',\n    slug: 'web_story_category',\n    types: ['web-story'],\n  },\n  {\n    description: 'Story Colors',\n    hierarchical: false,\n    name: 'Colors',\n    restBase: 'story-colors',\n    restNamespace: 'wp/v2',\n    restPath: 'http://localhost:8899/wp-json/wp/v2/story-colors',\n    slug: 'story-color',\n    types: ['web-story'],\n  },\n  {\n    description: 'Story Verticals',\n    hierarchical: true,\n    name: 'Verticals',\n    labels: {\n      searchItems: 'Search Verticals',\n      singularName: 'Vertical',\n      allItems: 'All Verticals',\n    },\n    restBase: 'story-verticals',\n    restNamespace: 'wp/v2',\n    restPath: 'http://localhost:8899/wp-json/wp/v2/story-verticals',\n    slug: 'story-vertical',\n    types: ['web-story'],\n  },\n  {\n    description: '',\n    hierarchical: false,\n    name: 'Tags',\n    restBase: 'web_story_tag',\n    restNamespace: 'web-stories/v1',\n    restPath: 'http://localhost:8899/wp-json/web-stories/v1/web_story_tag',\n    slug: 'web_story_tag',\n    types: ['web-story'],\n  },\n];\n\nexport default formattedTaxonomiesArray;\n"
  },
  {
    "path": "packages/dashboard/src/dataUtils/formattedTaxonomyTermsObject.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst formattedTaxonomyTermsObject = {\n  web_story_category: [\n    {\n      count: 1,\n      description: '',\n      id: 44,\n      meta: [],\n      name: 'SuperAwesomeCategory',\n      parent: 0,\n      slug: 'superawesomecategory',\n      taxonomy: 'web_story_category',\n    },\n  ],\n  'story-verticals': [\n    {\n      count: 1,\n      description: '',\n      id: 46,\n      meta: [],\n      name: 'That Vertical',\n      parent: 0,\n      slug: 'that-vertical',\n      taxonomy: 'story-vertical',\n    },\n  ],\n  web_story_tag: [],\n  'story-colors': [],\n};\n\nexport default formattedTaxonomyTermsObject;\n"
  },
  {
    "path": "packages/dashboard/src/dataUtils/formattedTemplatesArray.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { toUTCDate } from '@googleforcreators/date';\n\nconst formattedTemplatesArray = [\n  {\n    version: 2,\n    slug: 'template-slug-1',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 10,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID1',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        animations: [],\n        type: 'page',\n        id: 'ID1',\n        pageTemplateType: 'cover',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '4e5d3a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID3',\n        pageTemplateType: 'quote',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID4',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID4',\n        pageTemplateType: 'editorial',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID5',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID5',\n        pageTemplateType: 'list',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID6',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID6',\n        pageTemplateType: 'table',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID7',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID7',\n        pageTemplateType: 'steps',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook', 'Test Tag'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Fitness',\n    title: 'Filterable By Tag',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-2',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 9,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'cover',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n      { label: 'Test Color', color: '#fff000', family: 'Test Color' },\n    ],\n    vertical: 'Fitness',\n    title: 'Filterable By Color',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-3',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 3,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Entertainment',\n    title: 'Entertainment',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-4',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 4,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'editorial',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Test Vertical',\n    title: 'Filterable By Vertical',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-5',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 5,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'steps',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Fitness',\n    title: 'Fitness',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-6',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 6,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'cover',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Travel',\n    title: 'Travel',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-3.png',\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-7',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 7,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Wellbeing',\n    title: 'Wellbeing',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-1.png',\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n      },\n    ],\n  },\n  {\n    version: 2,\n    slug: 'template-slug-8',\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 8,\n    isLocal: false,\n    modified: toUTCDate('04/04/2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'editorial',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1', family: 'Pink' },\n      { label: 'Green', color: '#d8ddcc', family: 'Green' },\n      { label: 'Black', color: '#28292b', family: 'Black' },\n      { label: 'White', color: '#fff', family: 'White' },\n      { label: 'Brown', color: '#eadfd6', family: 'Brown' },\n    ],\n    vertical: 'Beauty',\n    title: 'Beauty',\n    postersByPage: [\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n      {\n        webp: 'http://localhost:9876/__static__/featured-media-2.png',\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n      },\n    ],\n  },\n];\n\nexport default formattedTemplatesArray;\n"
  },
  {
    "path": "packages/dashboard/src/dataUtils/formattedUsersObject.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst formattedUsersObject = {\n  1: {\n    id: 1,\n    name: 'admin',\n    url: '',\n    description: '',\n    link: 'http://localhost:8899/author/admin',\n    slug: 'admin',\n    avatarUrls: {\n      24: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=24&d=mm&r=g',\n      48: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=48&d=mm&r=g',\n      96: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=96&d=mm&r=g',\n    },\n    meta: [],\n  },\n  2: {\n    id: 2,\n    name: 'Fred Baby Diamond',\n    url: '',\n    description: '',\n    link: 'http://localhost:8899/author/fred-baby-diamond',\n    slug: 'fred-baby-diamond',\n    avatarUrls: {\n      24: 'http://0.gravatar.com/avatar/f775dcce8ac4dba60103f11582915c77?s=24&d=mm&r=g',\n      48: 'http://0.gravatar.com/avatar/f775dcce8ac4dba60103f11582915c77?s=48&d=mm&r=g',\n      96: 'http://0.gravatar.com/avatar/f775dcce8ac4dba60103f11582915c77?s=96&d=mm&r=g',\n    },\n    meta: [],\n  },\n};\nexport default formattedUsersObject;\n"
  },
  {
    "path": "packages/dashboard/src/getDefaultConfig.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst getDefaultConfig = () => ({\n  isRTL: false,\n  userId: 1,\n  locale: {\n    locale: 'en-US',\n    dateFormat: 'F j, Y',\n    timeFormat: 'g:i a',\n    gmtOffset: '0',\n    timezone: '',\n    months: [\n      'January',\n      'February',\n      'March',\n      'April',\n      'May',\n      'June',\n      'July',\n      'August',\n      'September',\n      'October',\n      'November',\n      'December',\n    ],\n    monthsShort: [\n      'Jan',\n      'Feb',\n      'Mar',\n      'Apr',\n      'May',\n      'Jun',\n      'Jul',\n      'Aug',\n      'Sep',\n      'Oct',\n      'Nov',\n      'Dec',\n    ],\n    weekdays: [\n      'Sunday',\n      'Monday',\n      'Tuesday',\n      'Wednesday',\n      'Thursday',\n      'Friday',\n      'Saturday',\n    ],\n    weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n    weekdaysInitials: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n    weekStartsOn: 1,\n  },\n  newStoryURL: '',\n  cdnURL: 'https://wp.stories.google/static/main/',\n  version: '',\n  capabilities: {\n    canManageSettings: false,\n    canUploadFiles: false,\n  },\n  canViewDefaultTemplates: false,\n  flags: {},\n  apiCallbacks: {},\n  leftRailSecondaryNavigation: [],\n  styleConstants: {\n    topOffset: 0,\n    leftOffset: 0,\n  },\n});\n\nexport default getDefaultConfig;\n"
  },
  {
    "path": "packages/dashboard/src/icons/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Compass } from './compass.svg';\nexport { default as HomeWithHeart } from './homeWithHeart.svg';\nexport { default as Menu } from './menu.svg';\nexport { default as MoreVertical } from './moreVertical.svg';\n"
  },
  {
    "path": "packages/dashboard/src/icons/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport * as Icons from '..';\n\nexport default {\n  title: 'Dashboard/Icons',\n  component: Icons,\n};\n\nconst IconsList = styled.ul`\n  color: ${({ theme }) => theme.colors.gray600};\n  list-style-type: none;\n  li {\n    padding: 10px 0;\n  }\n  svg {\n    height: 1em;\n    width: 1em;\n    margin-right: 10px;\n  }\n`;\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <IconsList>\n        {Object.keys(Icons).map((iconName) => {\n          // eslint-disable-next-line import/namespace\n          const Icon = Icons[iconName];\n          return (\n            <li key={iconName}>\n              <Icon />\n              {iconName}\n            </li>\n          );\n        })}\n      </IconsList>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/dashboard/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Dashboard } from './dashboard';\nexport * from './app';\nexport * from './app/router';\nexport * from './constants';\nexport * from './components';\nexport * from './app/views/shared';\nexport { GlobalStyle as DashboardGlobalStyle } from './theme';\nexport { default as DashboardKeyboardOnlyOutline } from './utils/keyboardOnlyOutline';\nexport { default as InterfaceSkeleton } from './components/interfaceSkeleton';\n"
  },
  {
    "path": "packages/dashboard/src/karma/apiProviderFixture.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { differenceInSeconds } from '@googleforcreators/date';\nimport { uniqueEntriesByKey } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport ApiContext from '../app/api/context';\nimport { defaultStoriesState } from '../app/reducer/story';\nimport formattedStoriesArray from '../dataUtils/formattedStoriesArray';\nimport formattedTaxonomiesArray from '../dataUtils/formattedTaxonomiesArray';\nimport formattedTaxonomyTermsObject from '../dataUtils/formattedTaxonomyTermsObject';\nimport formattedTemplatesArray from '../dataUtils/formattedTemplatesArray';\nimport { STORY_SORT_OPTIONS, DEFAULT_FILTERS } from '../constants/stories';\nimport { groupTemplatesByTag } from '../testUtils';\n\n/* eslint-disable jasmine/no-unsafe-spy */\nexport default function ApiProviderFixture({ children }) {\n  const [stories, setStoriesState] = useState(getStoriesState());\n  const [templates, setTemplatesState] = useState(getTemplatesState());\n\n  const storyApi = useMemo(\n    () => ({\n      duplicateStory: (story) =>\n        setStoriesState((currentState) => duplicateStory(story, currentState)),\n      fetchStories: (...args) =>\n        setStoriesState((currentState) => fetchStories(...args, currentState)),\n      createStoryFromTemplate: jasmine.createSpy('createStoryFromTemplate'),\n      trashStory: (story) =>\n        setStoriesState((currentState) => trashStory(story, currentState)),\n      updateStory: (story) =>\n        setStoriesState((currentState) => updateStory(story, currentState)),\n    }),\n    []\n  );\n\n  const templateApi = useMemo(\n    () => ({\n      fetchExternalTemplates: () =>\n        setTemplatesState((currentState) =>\n          fetchExternalTemplates(currentState)\n        ),\n      fetchExternalTemplateById: (id) =>\n        fetchExternalTemplateById(id, templates),\n    }),\n    [templates]\n  );\n\n  const usersApi = useMemo(\n    () => ({\n      getAuthors: () => {\n        const authors = formattedStoriesArray.map((story) => story.author);\n        return Promise.resolve(uniqueEntriesByKey(authors, 'id'));\n      },\n    }),\n    []\n  );\n\n  const taxonomyApi = useMemo(\n    () => ({\n      getTaxonomies: (args) => {\n        if (args.hierarchical) {\n          return Promise.resolve(\n            formattedTaxonomiesArray.filter((f) => f.hierarchical)\n          );\n        }\n        return Promise.resolve(formattedTaxonomiesArray);\n      },\n      getTaxonomyTerms: (path, args) => {\n        const restBase = path.split('/').pop();\n        const { search } = args;\n        let response = formattedTaxonomyTermsObject[restBase];\n        if (search) {\n          response = response.filter((r) => {\n            const term = r.name.toLowerCase();\n            return term.length && term.includes(search.toLowerCase());\n          });\n        }\n        return Promise.resolve(response);\n      },\n    }),\n    []\n  );\n\n  const value = useMemo(\n    () => ({\n      state: {\n        stories,\n        templates,\n      },\n      actions: {\n        storyApi,\n        templateApi,\n        usersApi,\n        taxonomyApi,\n      },\n    }),\n    [stories, templates, storyApi, templateApi, usersApi, taxonomyApi]\n  );\n\n  return <ApiContext.Provider value={value}>{children}</ApiContext.Provider>;\n}\n/* eslint-enable jasmine/no-unsafe-spy */\n\nApiProviderFixture.propTypes = {\n  children: PropTypes.node,\n};\n\nfunction getStoriesState() {\n  const copiedStories = [...formattedStoriesArray];\n  copiedStories.sort((a, b) => differenceInSeconds(b.modified, a.modified)); // initial sort is desc by modified\n  return {\n    ...defaultStoriesState,\n    stories: copiedStories.reduce((acc, curr) => {\n      acc[curr.id] = curr;\n\n      return acc;\n    }, {}),\n    storiesOrderById: copiedStories.map(({ id }) => id),\n    totalStoriesByStatus: getTotalStoriesByStatus(copiedStories),\n    totalPages: 1,\n    allPagesFetched: true,\n  };\n}\n\nfunction fetchStories({ sort = {}, filters = {} }, currentState) {\n  const storiesState = currentState ? { ...currentState } : getStoriesState();\n  const {\n    author,\n    web_story_category,\n    search = '',\n    status = DEFAULT_FILTERS.filters.status,\n  } = filters;\n  const {\n    orderby = DEFAULT_FILTERS.sort.orderby,\n    order = DEFAULT_FILTERS.sort.order,\n  } = sort;\n  const statuses = status.split(',');\n\n  storiesState.storiesOrderById = Object.values(storiesState.stories)\n    .filter(\n      ({ status: storyStatus, title }) =>\n        statuses.includes(storyStatus) &&\n        title.toLowerCase().includes(search.toLowerCase())\n    )\n    .filter((story) => typeof author !== 'number' || story.author.id === author)\n    .filter(\n      (story) =>\n        typeof category !== 'number' ||\n        Boolean(story.categories.find((c) => c.id === web_story_category))\n    )\n    .sort((a, b) => {\n      let value;\n      switch (orderby) {\n        case STORY_SORT_OPTIONS.DATE_CREATED: {\n          value = new Date(a.created).getTime() - new Date(b.created).getTime();\n          break;\n        }\n        case STORY_SORT_OPTIONS.LAST_MODIFIED: {\n          value = differenceInSeconds(a[orderby], b[orderby]);\n          break;\n        }\n        case STORY_SORT_OPTIONS.NAME: {\n          value = a[orderby].localeCompare(b[orderby]);\n          break;\n        }\n        case STORY_SORT_OPTIONS.CREATED_BY: {\n          value = a.author.name.localeCompare(b.author.name);\n          break;\n        }\n        default: {\n          value = 0;\n          break;\n        }\n      }\n\n      const shouldSortDescending =\n        (order && order === 'desc') ||\n        (!order && orderby === STORY_SORT_OPTIONS.LAST_MODIFIED);\n\n      return shouldSortDescending ? value * -1 : value;\n    })\n    .map(({ id }) => id);\n  return storiesState;\n}\n\nfunction updateStory(story, currentState) {\n  const copy = { ...story };\n\n  copy.title = copy.title.raw;\n  copy.content = copy.content?.raw;\n  copy.modified = new Date();\n  return {\n    ...currentState,\n    stories: {\n      ...currentState.stories,\n      [copy.id]: copy,\n    },\n  };\n}\n\nfunction duplicateStory(story, currentState) {\n  const copiedState = { ...currentState };\n  const copiedStory = { ...story };\n\n  // Update fields on copy\n  copiedStory.id = Math.round(Math.random() * 1000);\n  copiedStory.title = copiedStory.title + ' (Copy)';\n  copiedStory.created = new Date().toISOString();\n  copiedStory.modified = copiedStory.created;\n  copiedStory.bottomTargetAction = copiedStory.bottomTargetAction.replace(\n    story.id,\n    copiedStory.id\n  );\n  copiedStory.editStoryLink = copiedStory.editStoryLink.replace(\n    story.id,\n    copiedStory.id\n  );\n\n  // insert into copiedState\n  copiedState.stories[copiedStory.id] = copiedStory;\n  copiedState.storiesOrderById = [\n    copiedStory.id,\n    ...copiedState.storiesOrderById,\n  ];\n\n  // update stories by status\n  copiedState.totalStoriesByStatus = getTotalStoriesByStatus(\n    Object.values(copiedState.stories)\n  );\n\n  return copiedState;\n}\n\nfunction trashStory(story, currentState) {\n  const copiedState = { ...currentState };\n  // delete story from state and filter from ordered list\n  delete copiedState.stories[story.id];\n  copiedState.storiesOrderById = copiedState.storiesOrderById.filter(\n    (id) => id !== story.id\n  );\n\n  // update story status counts\n  copiedState.totalStoriesByStatus = getTotalStoriesByStatus(\n    Object.values(copiedState.stories)\n  );\n\n  return copiedState;\n}\n\nfunction getTotalStoriesByStatus(stories = []) {\n  return stories.reduce(\n    (acc, curr) => {\n      if (acc[curr.status] > 0) {\n        acc[curr.status] = acc[curr.status] + 1;\n      } else {\n        acc[curr.status] = 1;\n      }\n\n      return acc;\n    },\n    {\n      all: stories.length,\n      draft: 0,\n      publish: 0,\n      private: 0,\n      future: 0,\n    }\n  );\n}\n\nfunction getTemplatesState() {\n  const copiedTemplates = [...formattedTemplatesArray];\n  return {\n    allPagesFetched: true,\n    error: {},\n    isLoading: false,\n    templates: copiedTemplates.reduce((acc, curr) => {\n      acc[curr.id] = curr;\n\n      return acc;\n    }, {}),\n    templatesByTag: groupTemplatesByTag(copiedTemplates),\n    templatesOrderById: copiedTemplates.map(({ id }) => id),\n    totalTemplates: copiedTemplates.length,\n    totalPages: 1,\n  };\n}\n\nfunction fetchExternalTemplates(currentState) {\n  return currentState;\n}\n\nfunction fetchExternalTemplateById(id, currentState) {\n  return Promise.resolve(currentState.templates?.[id] ?? {});\n}\n"
  },
  {
    "path": "packages/dashboard/src/karma/fixture.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport {\n  act,\n  configure,\n  render,\n  screen,\n  waitFor,\n} from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport {\n  FixtureEvents,\n  ComponentStub,\n  actPromise,\n} from '@googleforcreators/karma-fixture';\n\n/**\n * Internal dependencies\n */\nimport Dashboard from '../dashboard';\nimport ApiProvider from '../app/api/apiProvider';\nimport { AppFrame } from '../components';\nimport InterfaceSkeleton from '../components/interfaceSkeleton';\nimport { noop } from '../utils';\nimport ApiProviderFixture from './apiProviderFixture';\n\nconst React = require('react');\n\nif ('true' === WEB_STORIES_CI) {\n  configure({\n    getElementError: (message) => {\n      const error = new Error(message);\n      error.name = 'TestingLibraryElementError';\n      error.stack = null;\n      return error;\n    },\n    asyncUtilTimeout: 5000,\n  });\n}\nexport const FIXTURE_DEFAULT_CONFIG = {\n  capabilities: {\n    canManageSettings: true,\n    canUploadFiles: true,\n  },\n  canViewDefaultTemplates: true,\n  isRTL: false,\n  userId: 123,\n  locale: {\n    dateFormat: 'F j, Y',\n    timeFormat: 'g:i a',\n    gmtOffset: -4,\n    timezone: 'America/New_York',\n    weekStartsOn: 0,\n  },\n  newStoryURL:\n    'http://localhost:8899/wp-admin/post-new.php?post_type=web-story',\n  cdnURL: 'https://cdn.example.com/',\n  version: '1.0.0-alpha.9',\n  flags: {},\n  apiCallbacks: {\n    trashStory: noop,\n    duplicateStory: noop,\n    updateStory: noop,\n    getAuthors: noop,\n    fetchStories: noop,\n    createStoryFromTemplate: noop,\n  },\n};\n\nexport default class Fixture {\n  constructor({ config = {}, flags = {} } = {}) {\n    this._config = { ...FIXTURE_DEFAULT_CONFIG, ...config };\n    this._flags = flags;\n    this._container = null;\n    this._appFrameStub = null;\n    this._screen = null;\n    this._componentStubs = new Map();\n    this._events = new FixtureEvents(act);\n\n    const createElement = React.createElement;\n    //eslint-disable-next-line jasmine/no-unsafe-spy\n    spyOn(React, 'createElement').and.callFake((type, props, ...children) => {\n      if (!props?._wrapped) {\n        const stubs = this._componentStubs.get(type);\n        if (stubs) {\n          const match = stubs.find((stub) => {\n            if (!stub._matcher) {\n              return true;\n            }\n            return stub._matcher(props);\n          });\n          if (match) {\n            type = match._wrapper;\n          }\n        }\n      }\n      return createElement(type, props, ...children);\n    });\n\n    this.stubComponent(ApiProvider).callFake(ApiProviderFixture);\n\n    this._appFrameStub = this.stubComponent(AppFrame);\n  }\n\n  get container() {\n    return this._container;\n  }\n\n  /**\n   * A fixture utility to fire native browser events. See `FixtureEvents` for\n   * more info.\n   *\n   * @return {FixtureEvents} fixture events that are executed on the native\n   * browser.\n   */\n  get events() {\n    return this._events;\n  }\n\n  get screen() {\n    return this._screen;\n  }\n\n  /**\n   * Set the feature flags. See `flags.js` for the list of flags.\n   *\n   * For instance, to enable a flag in your test call `setFlags` before\n   * calling the `render()` method:\n   * ```\n   * beforeEach(async () => {\n   *   fixture = new Fixture();\n   *   fixture.setFlags({FEATURE_NAME: true});\n   *   await fixture.render();\n   * });\n   * ```\n   *\n   * @param {Object} flags Flags object.\n   */\n  setFlags(flags) {\n    this._flags = { ...this._config.flags, ...flags };\n    this._config.flags = this._flags;\n  }\n\n  setConfig(config) {\n    this._config = { ...this._config, ...config };\n  }\n\n  /**\n   * Stubs a component. Can be used to render hooks on this component's level\n   * or even to completely replace the implementation of the component.\n   *\n   * All components must be stubbed before the `fixture.render()` is called.\n   *\n   * Use sparingly. See `ComponentStub` for more info.\n   *\n   * @param {Function} component Component.\n   * @param {Function|undefined} matcher Matcher.\n   * @return {ComponentStub} The component's stub.\n   */\n  stubComponent(component, matcher) {\n    const stub = new ComponentStub(this, component, matcher);\n    let stubs = this._componentStubs.get(component);\n    if (!stubs) {\n      stubs = [];\n      this._componentStubs.set(component, stubs);\n    }\n    stubs.push(stub);\n    return stub;\n  }\n\n  /**\n   * Renders the editor similarly to the `@testing-library/react`'s `render()`\n   * method.\n   *\n   * @return {Promise} Yields when the editor rendering is complete.\n   */\n  async render() {\n    const root = document.querySelector('test-root');\n\n    // see http://reactcommunity.org/react-modal/accessibility/\n    setAppElement(root);\n\n    const { container } = render(\n      <Dashboard key={Math.random()} config={this._config}>\n        <InterfaceSkeleton />\n      </Dashboard>,\n      {\n        container: root,\n      }\n    );\n    // The editor should always be given 100%:100% size. The testing-library\n    // renders an extra container so it should be given the same size.\n    container.style.width = '100%';\n    container.style.height = '100%';\n    container.style.overflow = 'scroll';\n    this._container = container;\n    this._screen = screen;\n\n    // Check to see if Google Sans font is loaded.\n    await waitFor(async () => {\n      const weights = ['400', '700'];\n      const font = '12px \"Google Sans\"';\n      const fonts = weights.map((weight) => `${weight} ${font}`);\n      await Promise.all(\n        fonts.map((thisFont) => document.fonts.load(thisFont, ''))\n      );\n      fonts.forEach((thisFont) => {\n        if (!document.fonts.check(thisFont, '')) {\n          throw new Error('Not ready: Google Sans font could not be loaded');\n        }\n      });\n    });\n  }\n\n  restore() {\n    window.location.hash = '#';\n    localStorage.clear();\n  }\n\n  /**\n   * Calls a hook in the context of the whole dashboard.\n   *\n   * Similar to the `@testing-library/react`'s `renderHook()` method.\n   *\n   * @param {Function} func The hook function. E.g. `useStory`.\n   * @return {Promise<Object>} Resolves when the hook is rendered with the\n   * value of the hook.\n   */\n  renderHook(func) {\n    return this._appFrameStub.renderHook(func);\n  }\n\n  /**\n   * Calls the specified callback and performs rendering actions on the\n   * whole editor.\n   *\n   * Similar to the `@testing-library/react`'s `act()` method.\n   *\n   * @param {Function} callback Callback.\n   * @return {Promise<Object>} Yields when the `act()` and all related\n   * editor rendering activity is complete. Resolves to the result of the\n   * callback.\n   */\n  act(callback) {\n    return actPromise(callback);\n  }\n\n  /**\n   * To be deprecated.\n   *\n   * @param {string} selector Selector.\n   * @return {Element|null} The found element or null.\n   */\n  querySelector(selector) {\n    return this._container.querySelector(selector);\n  }\n\n  /**\n   * To be deprecated?\n   *\n   * @param {string} selector Selector.\n   * @return {Array.<Element>} The potentially empty list of found elements.\n   */\n  querySelectorAll(selector) {\n    return this._container.querySelectorAll(selector);\n  }\n\n  /**\n   * @param {Element} element Element.\n   * @return {Promise} Yields when the element is displayed on the screen.\n   */\n  waitOnScreen(element) {\n    return new Promise((resolve) => {\n      const io = new IntersectionObserver((records) => {\n        records.forEach((record) => {\n          if (record.isIntersecting) {\n            resolve();\n            io.disconnect();\n          }\n        });\n      });\n      io.observe(element);\n    });\n  }\n\n  /**\n   * Makes a DOM snapshot of the current editor state. Karma must be run\n   * with the `--snapshots` option for the snapshotting to be enabled. When\n   * enabled, all snapshots are stored in the `/.test_artifacts/karma_snapshots`\n   * directory.\n   *\n   * @param {string} name Snapshot name.\n   * @return {Promise} Yields when the snapshot is completed.\n   */\n  snapshot(name) {\n    return karmaSnapshot(name);\n  }\n}\n"
  },
  {
    "path": "packages/dashboard/src/karma/integrationLayerTesting/config.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport Fixture from '../fixture';\nimport getDefaultConfig from '../../getDefaultConfig';\n\ndescribe('Integration Layer tests : EditorConfig Params :', () => {\n  let fixture;\n\n  const MINIMUM_CONFIG = {};\n\n  beforeAll(() => {\n    // fixture.setConfig() doesn't overwrite the whole object but merges therefore optional params need to be set undefined explicitly.\n    for (const key of Object.keys(getDefaultConfig())) {\n      MINIMUM_CONFIG[key] = undefined;\n    }\n    MINIMUM_CONFIG.apiCallbacks = {\n      fetchStories: () => Promise.resolve({}),\n    };\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const shouldRenderWithConfig = async (config) => {\n    let error;\n    try {\n      fixture.setConfig(config);\n      await fixture.render();\n    } catch (e) {\n      error = e;\n    }\n    expect(error).toBeUndefined();\n  };\n\n  it('should work with optional params being undefined', async () => {\n    fixture = new Fixture();\n    await shouldRenderWithConfig(MINIMUM_CONFIG);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/propTypes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { STORY_STATUS, TEMPLATES_GALLERY_STATUS } from './constants';\n\nexport const DashboardStatusesPropType = PropTypes.oneOf([\n  ...Object.values(STORY_STATUS),\n  ...Object.values(TEMPLATES_GALLERY_STATUS),\n]);\n\nexport const StoryPropType = PropTypes.shape({\n  id: PropTypes.number.isRequired,\n  status: DashboardStatusesPropType,\n  title: PropTypes.string.isRequired,\n  modified: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),\n  author: PropTypes.object,\n  capabilities: PropTypes.shape({\n    hasDeleteAction: PropTypes.bool,\n    hasEditAction: PropTypes.bool,\n  }),\n});\n\nexport const TemplatePropType = PropTypes.shape({\n  id: PropTypes.number.isRequired,\n  status: DashboardStatusesPropType,\n  title: PropTypes.string.isRequired,\n  pages: PropTypes.array,\n  modified: PropTypes.object,\n  colors: PropTypes.arrayOf(\n    PropTypes.shape({\n      label: PropTypes.string.isRequired,\n      color: PropTypes.string.isRequired,\n    })\n  ),\n  description: PropTypes.string,\n  tags: PropTypes.arrayOf(PropTypes.string),\n  createdBy: PropTypes.string,\n  postersByPage: PropTypes.arrayOf(\n    PropTypes.shape({\n      webp: PropTypes.string,\n      png: PropTypes.string,\n      type: PropTypes.string,\n    })\n  ),\n});\n\nexport const StoriesPropType = PropTypes.arrayOf(StoryPropType);\nexport const TemplatesPropType = PropTypes.arrayOf(TemplatePropType).isRequired;\n\nexport const StoryActionsPropType = PropTypes.shape({\n  duplicateStory: PropTypes.func,\n  trashStory: PropTypes.func,\n  updateStory: PropTypes.func,\n});\n\nexport const TemplateActionsPropType = PropTypes.shape({\n  createStoryFromTemplate: PropTypes.func,\n  handleDetailsToggle: PropTypes.func,\n  switchToTemplateByOffset: PropTypes.func,\n});\n\nexport const TotalStoriesByStatusPropType = PropTypes.shape({\n  all: PropTypes.number,\n  draft: PropTypes.number,\n  publish: PropTypes.number,\n});\n\nexport const PageSizePropType = PropTypes.shape({\n  width: PropTypes.number,\n  height: PropTypes.number,\n});\n\nexport const StoryMenuPropType = PropTypes.shape({\n  handleMenuToggle: PropTypes.func.isRequired,\n  contextMenuId: PropTypes.number.isRequired,\n  menuItems: PropTypes.arrayOf(\n    PropTypes.shape({\n      label: PropTypes.string,\n      value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n      url: PropTypes.string,\n      isEnabled: PropTypes.func,\n      action: PropTypes.func,\n    })\n  ),\n});\n\nexport const RenameStoryPropType = PropTypes.shape({\n  handleOnRenameStory: PropTypes.func,\n  id: PropTypes.number,\n  handleCancelRename: PropTypes.func,\n});\n"
  },
  {
    "path": "packages/dashboard/src/storybookUtils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as formattedStoriesArray } from '../dataUtils/formattedStoriesArray';\nexport { default as formattedTemplatesArray } from '../dataUtils/formattedTemplatesArray';\nexport { default as formattedUsersObject } from '../dataUtils/formattedUsersObject';\n\nexport const STORYBOOK_PAGE_SIZE = {\n  width: 212,\n  height: 318,\n};\n"
  },
  {
    "path": "packages/dashboard/src/testUtils/groupTemplatesByTag.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Creates an object of templates grouped by tag\n *\n * @param {Array.<Object>} templates An array of templates.\n * @return {Object} An object of templates grouped by tag name\n */\nexport const groupTemplatesByTag = (templates) =>\n  templates.reduce((result, template) => {\n    template.tags.forEach((tag) => {\n      if (result[tag]) {\n        result[tag].push(template.id);\n      } else {\n        result[tag] = [template.id];\n      }\n    });\n\n    return result;\n  }, {});\n"
  },
  {
    "path": "packages/dashboard/src/testUtils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as renderWithProviders } from './renderWithProviders';\nexport { groupTemplatesByTag } from './groupTemplatesByTag';\n"
  },
  {
    "path": "packages/dashboard/src/testUtils/mockApiProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport ApiContext from '../app/api/context';\n\nexport default function MockApiProvider({ children, value }) {\n  const mergedValue = {\n    state: {},\n    actions: {},\n    ...value,\n  };\n\n  return (\n    <ApiContext.Provider value={mergedValue}>{children}</ApiContext.Provider>\n  );\n}\n\nMockApiProvider.propTypes = {\n  children: PropTypes.node,\n  value: PropTypes.object,\n};\n"
  },
  {
    "path": "packages/dashboard/src/testUtils/renderWithProviders.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { FlagsProvider } from 'flagged';\nimport {\n  theme as externalDesignSystemTheme,\n  lightMode,\n  SnackbarProvider,\n  noop,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ConfigProvider } from '../app/config';\nimport MockApiProvider from './mockApiProvider';\n\nconst defaultProviderValues = {\n  features: {},\n  theme: {\n    ...externalDesignSystemTheme,\n    colors: lightMode,\n  },\n  config: {\n    userId: 8675301,\n    apiCallbacks: {\n      createStoryFromTemplate: noop, // Not required in general, but without this \"use template\" button will not render and a test will fail.\n    },\n    styleConstants: {\n      topOffset: 0,\n    },\n  },\n  api: {},\n};\n\nconst DefaultWrapper = ({ children }) => children;\n\nexport const renderWithProviders = (\n  ui,\n  providerValues = {},\n  renderOptions = {},\n  wrapper = DefaultWrapper\n) => {\n  const mergedProviderValues = { ...defaultProviderValues, ...providerValues };\n\n  const ProvidedWrapper = wrapper;\n\n  const Wrapper = ({ children }) => (\n    <ProvidedWrapper>\n      <FlagsProvider features={mergedProviderValues.features}>\n        <ThemeProvider theme={mergedProviderValues.theme}>\n          <ConfigProvider config={mergedProviderValues.config}>\n            <MockApiProvider value={mergedProviderValues.api}>\n              <SnackbarProvider value={mergedProviderValues.snackbar}>\n                {children}\n              </SnackbarProvider>\n            </MockApiProvider>\n          </ConfigProvider>\n        </ThemeProvider>\n      </FlagsProvider>\n    </ProvidedWrapper>\n  );\n\n  const mergedRenderOptions = { wrapper: Wrapper, ...renderOptions };\n\n  return render(ui, mergedRenderOptions);\n};\n\nexport default renderWithProviders;\n"
  },
  {
    "path": "packages/dashboard/src/theme.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\n\nexport const GlobalStyle = createGlobalStyle`\n  h1, h2, h3, h4, h5, h6, p, a {\n    margin: 0;\n  }\n`;\n"
  },
  {
    "path": "packages/dashboard/src/types/configProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Template } from '@googleforcreators/templates';\nimport type { ProductData } from '@googleforcreators/elements';\n\nexport interface Locale {\n  locale?: string;\n  dateFormat?: string;\n  timeFormat?: string;\n  gmtOffset?: number;\n  timeZone?: string;\n  months?: string[];\n  monthsShort?: string[];\n  weekdays?: string[];\n  weekdaysShort?: string[];\n  weekdaysInitials?: string[];\n  weekStartsOn?: number;\n  timezoneAbbr?: string;\n}\n\nexport interface Capabilities {\n  canManageSettings?: boolean;\n  canUploadFiles?: boolean;\n}\n\nexport interface Navigation {\n  value: string;\n  label: string;\n  isExternal?: boolean;\n  trackingEvent?: string;\n}\n\nexport interface StyleConstants {\n  topOffset: number;\n  leftOffset: number;\n}\n\nexport interface QueryParams {\n  page: number;\n  perPage: number;\n  filters: Record<string, string>;\n  sort: Record<string, string>;\n}\n\nexport interface Author {\n  id: number;\n  name: string;\n}\n\nexport type Taxonomy = {\n  name: string;\n  slug: string;\n  capabilities: Record<string, string>;\n  description?: string;\n  labels: Record<string, string>;\n  types: string[];\n  showCloud?: boolean;\n  hierarchical: boolean;\n  restBase: string;\n  restNamespace: string;\n  visibility: Record<string, boolean>;\n  restPath: string;\n};\n\ninterface TaxonomiesArgs {\n  hierarchical?: boolean;\n  show_ui?: boolean;\n}\n\ninterface TermArgs {\n  search?: string;\n  per_page?: number;\n}\n\ninterface Term {\n  id: number;\n  name: string;\n  slug: string;\n  taxonomy: string;\n}\n\nexport interface ApiCallbacks {\n  createStoryFromTemplate?: (template: Template) => Promise<DashboardStory>;\n  duplicateStory?: (story: DashboardStory) => Promise<DashboardStory>;\n  fetchStories?: () => Promise<DashboardStory[]>;\n  getAuthors?: (search: string) => Promise<Author[]>;\n  getProducts?: (search: string) => Promise<ProductData[]>;\n  getTaxonomies?: (args: TaxonomiesArgs) => Promise<Taxonomy[]>;\n  getTaxonomyTerms?: (endpoint: string, args: TermArgs) => Promise<Term>;\n  trashStory?: (id: number) => Promise<DashboardStory>;\n  updateStory?: (\n    story: Pick<DashboardStory, 'id' | 'author' | 'title'>\n  ) => Promise<DashboardStory>;\n}\n\ninterface LockUser {\n  name?: string;\n  id?: number;\n  avatar?: string | null;\n}\n\nexport interface DashboardStory {\n  id: number;\n  status: string;\n  title: string;\n  created: string;\n  createdGmt: string;\n  modified: string;\n  modifiedGmt: string;\n  author: Author;\n  locked: boolean;\n  lockUser: LockUser;\n  bottomTargetAction: string;\n  editStoryLink: string;\n  previewLink: string;\n  link: string;\n  capabilities: Record<string, boolean>;\n}\n\nexport interface DashboardConfig {\n  isRTL: boolean;\n  userId: number;\n  locale: Locale;\n  newStoryURL: string;\n  cdnURL: string;\n  version: string;\n  capabilities: Capabilities;\n  canViewDefaultTemplates: boolean;\n  flags: Record<string, boolean>;\n  apiCallbacks: ApiCallbacks;\n  leftRailSecondaryNavigation: Navigation[];\n  styleConstants: StyleConstants;\n  globalAutoAdvance?: boolean;\n  globalPageDuration?: number;\n  documentTitleSuffix?: string;\n  containerId: string;\n}\n"
  },
  {
    "path": "packages/dashboard/src/types/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './configProvider';\nexport * from './routerProvider';\n"
  },
  {
    "path": "packages/dashboard/src/types/routerProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Dispatch, SetStateAction } from 'react';\nimport type { History } from 'history';\n\ninterface State {\n  activeRoute: string;\n  currentPath: string;\n  queryParams: Record<string, string>;\n  availableRoutes: string[];\n  defaultRoute: string;\n}\ninterface Actions {\n  push: History['push'];\n  replace: History['replace'];\n  setAvailableRoutes: Dispatch<SetStateAction<string[]>>;\n}\nexport interface RouterProviderState {\n  state: State;\n  actions: Actions;\n}\n"
  },
  {
    "path": "packages/dashboard/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/dashboard/src/utils/groupBy.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst groupBy = (arr, key) => {\n  return arr.reduce((prev, curr) => {\n    if (!curr[key]) {\n      return prev;\n    }\n    if (prev[curr[key]]) {\n      prev[curr[key]] = curr;\n    } else {\n      prev[curr[key]] = curr;\n    }\n    return prev;\n  }, {});\n};\n\nexport default groupBy;\n"
  },
  {
    "path": "packages/dashboard/src/utils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as titleFormatted } from './titleFormatted';\nexport { default as KeyboardOnlyOutline } from './keyboardOnlyOutline';\nexport { default as useDashboardResultsLabel } from './useDashboardResultsLabel';\nexport {\n  default as usePagePreviewSize,\n  getPosterHeight,\n} from './usePagePreviewSize';\nexport { default as useStoryView } from './useStoryView';\nexport { default as useTemplateView } from './useTemplateView';\nexport { noop } from './noop';\n"
  },
  {
    "path": "packages/dashboard/src/utils/keyboardOnlyOutline.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Inspired by https://github.com/moxystudio/js-keyboard-only-outlines/blob/master/src/index.js\n\n/**\n * External dependencies\n */\nimport { useEffect, useState } from '@googleforcreators/react';\nimport { createGlobalStyle } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { KEYBOARD_USER_CLASS } from '../constants';\n\nexport const OutlineStyles = createGlobalStyle`\n    *:focus {\n        outline: none !important;\n    }\n`;\n\nconst ACCEPTED_KEYS = [\n  'ArrowUp',\n  'ArrowDown',\n  'ArrowLeft',\n  'ArrowRight',\n  'Tab',\n];\n\nconst KeyboardOnlyOutline = () => {\n  const [usingKeyboard, setUsingKeyboard] = useState(false);\n  const handleKeydown = (e) => {\n    if (!usingKeyboard && ACCEPTED_KEYS.includes(e.key)) {\n      setUsingKeyboard(true);\n    }\n  };\n\n  const handleMousedown = () => {\n    if (usingKeyboard) {\n      setUsingKeyboard(false);\n    }\n  };\n\n  useEffect(() => {\n    document.addEventListener('keydown', handleKeydown);\n    document.addEventListener('mousedown', handleMousedown);\n\n    return function cleanup() {\n      document.removeEventListener('keydown', handleKeydown);\n      document.removeEventListener('mousedown', handleMousedown);\n    };\n  });\n\n  useEffect(() => {\n    document.body.classList.toggle(KEYBOARD_USER_CLASS, usingKeyboard);\n  }, [usingKeyboard]);\n\n  return !usingKeyboard ? <OutlineStyles /> : null;\n};\n\nKeyboardOnlyOutline.propTypes = {};\n\nexport default KeyboardOnlyOutline;\n"
  },
  {
    "path": "packages/dashboard/src/utils/noop.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const noop = () => {};\n"
  },
  {
    "path": "packages/dashboard/src/utils/test/groupBy.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport groupBy from '../groupBy';\n\ndescribe('groupBy', () => {\n  it('should shape an array of objects by a given key', () => {\n    const initialArray = [\n      { id: 94, status: 'draft', title: 'my test story 1' },\n      { id: 65, status: 'published', title: 'my test story 2' },\n      { id: 78, status: 'draft', title: 'my test story 3' },\n      { id: 12, status: 'draft', title: 'my test story 4' },\n    ];\n\n    const groupedById = groupBy(initialArray, 'id');\n\n    expect(groupedById).toMatchObject({\n      94: { id: 94, status: 'draft', title: 'my test story 1' },\n      65: { id: 65, status: 'published', title: 'my test story 2' },\n      78: { id: 78, status: 'draft', title: 'my test story 3' },\n      12: { id: 12, status: 'draft', title: 'my test story 4' },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/test/useDashboardResultsLabel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport {\n  DASHBOARD_VIEWS,\n  RESULT_LABELS,\n  STORY_STATUS,\n  TEMPLATES_GALLERY_STATUS,\n} from '../../constants';\n\nimport useDashboardResultsLabel from '../useDashboardResultsLabel';\n\ndescribe('useGenericResultsLabel()', () => {\n  it(`should return an empty string to display if there is no currentFilter supplied`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          currentFilter: null,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe('');\n  });\n\n  // Dashboard\n  it(`should have default options initially selected for ${DASHBOARD_VIEWS.DASHBOARD}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          currentFilter: STORY_STATUS.ALL,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe(\n      RESULT_LABELS[DASHBOARD_VIEWS.DASHBOARD][STORY_STATUS.ALL](0)\n    );\n  });\n\n  it(`should have options selected for ${DASHBOARD_VIEWS.DASHBOARD} when filtered to drafts`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          currentFilter: STORY_STATUS.DRAFT,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe(\n      RESULT_LABELS[DASHBOARD_VIEWS.DASHBOARD][STORY_STATUS.DRAFT](0)\n    );\n  });\n\n  it(`should have options selected for ${DASHBOARD_VIEWS.DASHBOARD} when filtered to published stories`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          currentFilter: STORY_STATUS.PUBLISH,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe(\n      RESULT_LABELS[DASHBOARD_VIEWS.DASHBOARD][STORY_STATUS.PUBLISH](0)\n    );\n  });\n\n  it(`should show counted results if isActiveSearch is true for ${DASHBOARD_VIEWS.DASHBOARD}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          isActiveSearch: true,\n          totalResults: 4,\n          currentFilter: STORY_STATUS.PUBLISH,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe('<strong>4</strong> results');\n  });\n\n  it(`should show \"1 result\" if isActiveSearch is true and totalResults is 0 for ${DASHBOARD_VIEWS.DASHBOARD}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          isActiveSearch: true,\n          totalResults: 1,\n          currentFilter: STORY_STATUS.PUBLISH,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe('<strong>1</strong> result');\n  });\n\n  it(`should show \"0 results\" if isActiveSearch is true and totalResults is 0 for ${DASHBOARD_VIEWS.DASHBOARD}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          isActiveSearch: true,\n          totalResults: 0,\n          currentFilter: STORY_STATUS.PUBLISH,\n          view: DASHBOARD_VIEWS.DASHBOARD,\n        }),\n      {}\n    );\n    expect(result.current).toBe('<strong>0</strong> results');\n  });\n\n  // template gallery\n\n  it(`should have default options initially selected for ${DASHBOARD_VIEWS.TEMPLATES_GALLERY}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          currentFilter: TEMPLATES_GALLERY_STATUS.ALL,\n          view: DASHBOARD_VIEWS.TEMPLATES_GALLERY,\n        }),\n      {}\n    );\n    expect(result.current).toBe(\n      RESULT_LABELS[DASHBOARD_VIEWS.TEMPLATES_GALLERY][\n        TEMPLATES_GALLERY_STATUS.ALL\n      ](0)\n    );\n  });\n\n  it(`should show counted results if isActiveSearch is true for ${DASHBOARD_VIEWS.TEMPLATES_GALLERY}`, () => {\n    const { result } = renderHook(\n      () =>\n        useDashboardResultsLabel({\n          isActiveSearch: true,\n          totalResults: 41,\n          currentFilter: TEMPLATES_GALLERY_STATUS.ALL,\n          view: DASHBOARD_VIEWS.TEMPLATES_GALLERY,\n        }),\n      {}\n    );\n    expect(result.current).toBe('<strong>41</strong> results');\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/test/usePagePreviewSize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPosterHeight } from '../usePagePreviewSize';\n\ndescribe('usePagePreviewSize/getPosterHeight', () => {\n  it.each([\n    [202, 303],\n    [254, 381],\n  ])(\n    'should return height in 2:3 ratio relative to given width',\n    (width, expectedHeight) => {\n      const height = getPosterHeight(width);\n\n      expect(height).toBe(expectedHeight);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/test/useStoryView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useStoryView from '../useStoryView';\nimport {\n  SORT_DIRECTION,\n  STORY_SORT_OPTIONS,\n  STORY_STATUSES,\n  VIEW_STYLE,\n} from '../../constants';\n\ndescribe('useStoryView()', () => {\n  it('should have the default options initially selected', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 1 }), {});\n\n    expect(result.current.filters.value.status).toBe(STORY_STATUSES[0].value);\n    expect(result.current.sort.value).toBe(STORY_SORT_OPTIONS.LAST_MODIFIED);\n    expect(result.current.sort.direction).toBe(SORT_DIRECTION.DESC);\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new filter when passed and reset the page.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      const newFilters = {\n        ...result.current.filters,\n        status: STORY_STATUSES[1].value,\n      };\n      result.current.filters.set(newFilters);\n    });\n    expect(result.current.filters.value).toMatchObject({\n      status: STORY_STATUSES[1].value,\n    });\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new sort when passed and reset the page.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.sort.set({ orderby: STORY_SORT_OPTIONS.NAME });\n    });\n    expect(result.current.sort.value).toBe(STORY_SORT_OPTIONS.NAME);\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new filters when passed and reset the page.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.filters.set({ web_story_category: 45 });\n    });\n    expect(result.current.filters.value).toMatchObject({\n      web_story_category: 45,\n    });\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new search keyword when typed and reset the page.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.filters.set({ search: 'Harry Potter Story' });\n    });\n    expect(result.current.filters.value).toMatchObject({\n      search: 'Harry Potter Story',\n    });\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new view style when toggled.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    expect(result.current.view.style).toBe(VIEW_STYLE.GRID);\n\n    act(() => {\n      result.current.view.toggleStyle();\n    });\n    expect(result.current.view.style).toBe(VIEW_STYLE.LIST);\n  });\n\n  it('should request the next page when called.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n  });\n\n  it('should request the next page when called and not exceed maximum pages.', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n  });\n\n  it('should not show stories while loading by default', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    expect(result.current.showStoriesWhileLoading.current).toBeFalse();\n  });\n\n  it('should set showStoriesWhileLoading to true when next page is called', () => {\n    const { result } = renderHook(() => useStoryView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.showStoriesWhileLoading.current).toBeTrue();\n  });\n\n  it('should reset showStoriesWhileLoading when `isLoading` is set to false', () => {\n    let isLoading = true;\n    const { result, rerender } = renderHook(\n      () =>\n        useStoryView({\n          isLoading,\n          totalPages: 2,\n        }),\n      {}\n    );\n\n    // set showStoriesWhileLoading to `true`\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.showStoriesWhileLoading.current).toBeTrue();\n\n    isLoading = false;\n\n    rerender();\n\n    expect(result.current.showStoriesWhileLoading.current).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/test/useTemplateView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useTemplateView from '../useTemplateView';\nimport {\n  TEMPLATES_GALLERY_STATUS,\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n} from '../../constants';\n\ndescribe('useTemplateView()', () => {\n  it('should have the default options initially selected', () => {\n    const { result } = renderHook(() => useTemplateView({ totalPages: 1 }), {});\n\n    expect(result.current.filters.value.status).toBe(\n      TEMPLATES_GALLERY_STATUS.ALL\n    );\n    expect(result.current.sort.value).toBe(\n      TEMPLATES_GALLERY_SORT_OPTIONS.POPULAR\n    );\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new sort when passed and reset the page.', () => {\n    const { result } = renderHook(() => useTemplateView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.sort.set({\n        orderby: TEMPLATES_GALLERY_SORT_OPTIONS.RECENT,\n      });\n    });\n    expect(result.current.sort.value).toBe(\n      TEMPLATES_GALLERY_SORT_OPTIONS.RECENT\n    );\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should set the new search keyword when typed and reset the page.', () => {\n    const { result } = renderHook(() => useTemplateView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.filters.set({\n        search: 'Magical Creatures Template',\n      });\n    });\n    expect(result.current.filters.value.search).toBe(\n      'Magical Creatures Template'\n    );\n    expect(result.current.page.value).toBe(1);\n  });\n\n  it('should request the next page when called.', () => {\n    const { result } = renderHook(() => useTemplateView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n  });\n\n  it('should request the next page when called and not exceed maximum pages.', () => {\n    const { result } = renderHook(() => useTemplateView({ totalPages: 2 }), {});\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n\n    act(() => {\n      result.current.page.requestNextPage();\n    });\n\n    expect(result.current.page.value).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/titleFormatted.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nconst titleFormatted = (rawTitle) => {\n  return rawTitle === '' ? __('Untitled', 'web-stories') : rawTitle;\n};\n\nexport default titleFormatted;\n"
  },
  {
    "path": "packages/dashboard/src/utils/useDashboardResultsLabel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, _n } from '@googleforcreators/i18n';\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RESULT_LABELS } from '../constants';\n\nexport default function useDashboardResultsLabel({\n  isActiveSearch,\n  currentFilter,\n  totalResults,\n  view,\n}) {\n  const resultsLabel = useMemo(() => {\n    const numResults = totalResults ?? 0;\n    const defaultLabel = RESULT_LABELS[view]?.[currentFilter] || '';\n    const interpretedDefaultLabel =\n      typeof defaultLabel === 'function'\n        ? defaultLabel(numResults)\n        : defaultLabel;\n    return isActiveSearch\n      ? sprintf(\n          /* translators: %s: number of results. */\n          _n('%s result', '%s results', numResults, 'web-stories'),\n          sprintf('<strong>%s</strong>', numResults)\n        )\n      : interpretedDefaultLabel;\n  }, [isActiveSearch, totalResults, view, currentFilter]);\n\n  return resultsLabel;\n}\n"
  },
  {
    "path": "packages/dashboard/src/utils/usePagePreviewSize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useMemo,\n  useState,\n  useRef,\n  useDebouncedCallback,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport { PAGE_RATIO } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport {\n  DASHBOARD_LEFT_NAV_WIDTH,\n  MIN_DASHBOARD_WIDTH,\n  VIEWPORT_BREAKPOINT,\n  STORY_PREVIEW_WIDTH,\n  GRID_SPACING,\n  PAGE_WRAPPER,\n} from '../constants';\nimport useConfig from '../app/config/useConfig';\n\n/**\n * Here we need to calculate height for every pagePreview in use.\n * The height in 2:3 ratio which is consistent with poster sizes that serve as cover images\n *\n * @param {number} width  width of page to base ratios on\n * @return {Object}       heights to use in pagePreviews { fullBleedHeight: Number, storyHeight: Number}\n */\nexport const getPosterHeight = (width) => Math.round(width / PAGE_RATIO);\n\nconst getCurrentBp = (availableContainerSpace) =>\n  availableContainerSpace <= MIN_DASHBOARD_WIDTH\n    ? VIEWPORT_BREAKPOINT.TABLET\n    : VIEWPORT_BREAKPOINT.DESKTOP;\n\n// To determine the size of a story page we take the page size according to min viewport width\n// and then find the remaining width in the given space that the dashboard is showing stories in\n// if the container isn't important to size then respectSetWidth catches it (thumbnails or isn't a grid)\n// otherwise, we're taking the available space we have and finding out how many items in the default size we can fit in a row\n// then we calculate the grid column gutter and the page gutter\n// subtract those values from the availableContainer space to get remaining space\n// divide the remaining space by the itemsInRow\n// attach that extra space to the width\n// get heights for page and container in getPosterHeight\nconst sizeFromWidth = (\n  width,\n  { bp, respectSetWidth, availableContainerSpace }\n) => {\n  if (respectSetWidth) {\n    const height = getPosterHeight(width);\n    return {\n      width,\n      height,\n    };\n  }\n\n  if (bp === VIEWPORT_BREAKPOINT.DESKTOP) {\n    availableContainerSpace -= DASHBOARD_LEFT_NAV_WIDTH;\n  }\n\n  const itemsInRow = Math.floor(availableContainerSpace / width);\n  const columnGapWidth = GRID_SPACING.COLUMN_GAP * (itemsInRow - 1);\n  const pageGutter = PAGE_WRAPPER.GUTTER * 2;\n  const takenSpace = width * itemsInRow + columnGapWidth + pageGutter;\n  const remainingSpace = availableContainerSpace - takenSpace;\n  const addToWidthValue = remainingSpace / itemsInRow;\n\n  const trueWidth = width + addToWidthValue;\n  const height = getPosterHeight(trueWidth);\n\n  return {\n    width: trueWidth,\n    height,\n  };\n};\n\nconst getContainerWidth = (windowWidth) => {\n  // Because the dashboard has a min width (MIN_DASHBOARD_WIDTH) check to see if that min should be used or the actual space of the dashboard\n  const isWindowSmallerThanMinDashboardWidth =\n    window.innerWidth < MIN_DASHBOARD_WIDTH;\n  return isWindowSmallerThanMinDashboardWidth\n    ? MIN_DASHBOARD_WIDTH\n    : windowWidth;\n};\n\nexport default function usePagePreviewSize(options = {}) {\n  const { thumbnailMode = false, isGrid } = options;\n  const { containerId } = useConfig();\n  const dashboardContainerRef = useRef(document.getElementById(containerId));\n\n  // BP is contingent on the actual window size\n  const [viewportWidth, setViewportWidth] = useState(window.innerWidth);\n\n  const [bp, setBp] = useState(getCurrentBp(viewportWidth));\n\n  const [availableContainerSpace, setAvailableContainerSpace] = useState(\n    getContainerWidth(\n      // eslint-disable-next-line react-hooks/refs -- FIXME\n      dashboardContainerRef.current?.offsetWidth || window.innerWidth\n    )\n  );\n\n  const debounceSetViewportWidth = useDebouncedCallback((width) => {\n    setViewportWidth(width);\n  }, 500);\n\n  useEffect(() => {\n    setBp(getCurrentBp(viewportWidth));\n  }, [viewportWidth]);\n\n  useResizeEffect(\n    dashboardContainerRef,\n    ({ width }) => {\n      setAvailableContainerSpace(getContainerWidth(width));\n\n      if (window.innerWidth !== viewportWidth) {\n        debounceSetViewportWidth(window.innerWidth);\n      }\n    },\n    [setAvailableContainerSpace, viewportWidth, debounceSetViewportWidth]\n  );\n\n  return useMemo(\n    () => ({\n      pageSize: sizeFromWidth(\n        STORY_PREVIEW_WIDTH[thumbnailMode ? VIEWPORT_BREAKPOINT.THUMBNAIL : bp],\n        {\n          respectSetWidth: !isGrid || thumbnailMode,\n          availableContainerSpace,\n          bp,\n        }\n      ),\n    }),\n    [bp, isGrid, thumbnailMode, availableContainerSpace]\n  );\n}\n"
  },
  {
    "path": "packages/dashboard/src/utils/useStoryView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { clamp } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport {\n  DEFAULT_FILTERS,\n  SORT_DIRECTION,\n  STORY_SORT_OPTIONS,\n  VIEW_STYLE,\n} from '../constants';\nimport { PageSizePropType } from '../propTypes';\nimport usePagePreviewSize from './usePagePreviewSize';\n\nexport default function useStoryView({\n  filtersObject = DEFAULT_FILTERS.filters,\n  sortObject = DEFAULT_FILTERS.sort,\n  isLoading = false,\n  totalPages,\n}) {\n  const [viewStyle, setViewStyle] = useState(VIEW_STYLE.GRID);\n  const [sort, _setSort] = useState(sortObject);\n  const [filters, _setFilters] = useState(filtersObject);\n  const [page, setPage] = useState(1);\n  const showStoriesWhileLoadingRef = useRef(false);\n  const [initialPageReady, setInitialPageReady] = useState(false);\n\n  const { pageSize } = usePagePreviewSize({\n    thumbnailMode: viewStyle === VIEW_STYLE.LIST,\n    isGrid: viewStyle === VIEW_STYLE.GRID,\n  });\n\n  const setPageClamped = useCallback(\n    (newPage) => {\n      const pageRange = { MIN: 1, MAX: totalPages };\n      setPage(clamp(newPage, pageRange));\n    },\n    [totalPages]\n  );\n\n  const setSort = useCallback(\n    (newSort) => {\n      _setSort(newSort);\n      setPageClamped(1);\n    },\n    [setPageClamped]\n  );\n\n  const setFilters = useCallback(\n    (newFilters) => {\n      _setFilters(newFilters);\n      setPageClamped(1);\n    },\n    [setPageClamped]\n  );\n\n  const toggleViewStyle = useCallback(() => {\n    const newViewStyle =\n      viewStyle === VIEW_STYLE.LIST ? VIEW_STYLE.GRID : VIEW_STYLE.LIST;\n\n    setViewStyle(newViewStyle);\n  }, [viewStyle, setViewStyle]);\n\n  const requestNextPage = useCallback(() => {\n    showStoriesWhileLoadingRef.current = true;\n    setPageClamped(page + 1);\n  }, [page, setPageClamped]);\n\n  useEffect(() => {\n    if (filters?.search?.length) {\n      trackEvent('search', {\n        search_type: 'dashboard_stories',\n        search_term: filters.search,\n        search_filter: filters.status,\n        search_author_filter: filters.author,\n        search_order: sort.order,\n        search_orderby: sort.orderby,\n        search_view: viewStyle,\n      });\n    }\n  }, [filters, sort, viewStyle]);\n\n  useEffect(() => {\n    // reset ref state after request is finished\n    if (!isLoading) {\n      showStoriesWhileLoadingRef.current = false;\n    }\n  }, [isLoading]);\n\n  useEffect(() => {\n    // give views a way to prevent early excess renders by waiting until data's ready\n    if (totalPages && !initialPageReady) {\n      setInitialPageReady(true);\n    }\n  }, [totalPages, initialPageReady]);\n\n  useEffect(() => {\n    if (initialPageReady) {\n      setFilters(filtersObject);\n    }\n  }, [setFilters, initialPageReady, filtersObject]);\n\n  useEffect(() => {\n    if (initialPageReady) {\n      setSort(sortObject);\n    }\n  }, [setSort, initialPageReady, sortObject]);\n\n  return useMemo(\n    () => ({\n      view: {\n        style: viewStyle,\n        toggleStyle: toggleViewStyle,\n        pageSize,\n      },\n      sort: {\n        value: sort.orderby,\n        direction: sort.order,\n        set: setSort,\n      },\n      filters: {\n        value: filters,\n        set: setFilters,\n      },\n      page: {\n        value: page,\n        set: setPage,\n        requestNextPage,\n      },\n      initialPageReady,\n      showStoriesWhileLoading: showStoriesWhileLoadingRef,\n    }),\n    [\n      viewStyle,\n      toggleViewStyle,\n      pageSize,\n      sort,\n      setSort,\n      filters,\n      setFilters,\n      initialPageReady,\n      page,\n      requestNextPage,\n    ]\n  );\n}\n\nexport const ViewPropTypes = PropTypes.shape({\n  style: PropTypes.oneOf(Object.values(VIEW_STYLE)),\n  toggleStyle: PropTypes.func,\n  pageSize: PageSizePropType,\n});\n\nexport const AuthorPropTypes = PropTypes.shape({\n  filterId: PropTypes.number,\n  toggleFilterId: PropTypes.func,\n  queriedAuthors: PropTypes.arrayOf(\n    PropTypes.shape({\n      id: PropTypes.number,\n      name: PropTypes.string,\n    })\n  ).isRequired,\n  setQueriedAuthors: PropTypes.func,\n});\n\nexport const FilterPropTypes = PropTypes.shape({\n  value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  set: PropTypes.func,\n});\n\nexport const SortPropTypes = PropTypes.shape({\n  value: PropTypes.oneOf(Object.values(STORY_SORT_OPTIONS)),\n  set: PropTypes.func,\n  direction: PropTypes.oneOf(Object.values(SORT_DIRECTION)),\n  setDirection: PropTypes.func,\n});\n\nexport const PagePropTypes = PropTypes.shape({\n  value: PropTypes.number,\n  set: PropTypes.func,\n  requestNextPage: PropTypes.func,\n});\n\nexport const SearchPropTypes = PropTypes.shape({\n  keyword: PropTypes.string,\n  setKeyword: PropTypes.func,\n});\n\nexport const ShowStoriesWhileLoadingPropType = PropTypes.shape({\n  current: PropTypes.bool,\n});\n"
  },
  {
    "path": "packages/dashboard/src/utils/useTemplateView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport { clamp } from '@googleforcreators/units';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport {\n  TEMPLATES_GALLERY_SORT_OPTIONS,\n  VIEW_STYLE,\n  DEFAULT_TEMPLATE_FILTERS,\n} from '../constants';\nimport { PageSizePropType } from '../propTypes';\nimport usePagePreviewSize from './usePagePreviewSize';\n\nexport default function useTemplateView({\n  totalPages,\n  sortObject = DEFAULT_TEMPLATE_FILTERS.sort,\n  filtersObject = DEFAULT_TEMPLATE_FILTERS.filters,\n}) {\n  const [sort, _setSort] = useState(sortObject);\n  const [filters, _setFilters] = useState(filtersObject);\n  const [page, setPage] = useState(1);\n\n  const { pageSize } = usePagePreviewSize({\n    isGrid: true,\n  });\n\n  const setPageClamped = useCallback(\n    (newPage) => {\n      const pageRange = { MIN: 1, MAX: totalPages };\n      setPage(clamp(newPage, pageRange));\n    },\n    [totalPages]\n  );\n  const requestNextPage = useCallback(\n    () => setPageClamped(page + 1),\n    [page, setPageClamped]\n  );\n\n  const setSort = useCallback(\n    (newSort) => {\n      _setSort(newSort);\n      setPageClamped(1);\n    },\n    [setPageClamped]\n  );\n\n  const setFilters = useCallback(\n    (newSort) => {\n      _setFilters(newSort);\n      setPageClamped(1);\n    },\n    [setPageClamped]\n  );\n\n  return useMemo(\n    () => ({\n      view: {\n        style: VIEW_STYLE.GRID,\n        pageSize,\n      },\n      sort: {\n        value: sort.orderby,\n        direction: sort.order,\n        set: setSort,\n      },\n      filters: {\n        value: filters,\n        set: setFilters,\n      },\n      page: {\n        value: page,\n        set: setPage,\n        requestNextPage,\n      },\n    }),\n    [pageSize, sort, setSort, page, requestNextPage, filters, setFilters]\n  );\n}\n\nexport const ViewPropTypes = PropTypes.shape({\n  style: PropTypes.oneOf(Object.values(VIEW_STYLE)),\n  pageSize: PageSizePropType,\n});\n\nexport const FilterPropTypes = PropTypes.shape({\n  value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  set: PropTypes.func,\n});\n\nexport const PagePropTypes = PropTypes.shape({\n  value: PropTypes.number,\n  set: PropTypes.func,\n  requestNextPage: PropTypes.func,\n});\n\nexport const SearchPropTypes = PropTypes.shape({\n  keyword: PropTypes.string,\n  setKeyword: PropTypes.func,\n});\n\nexport const SortPropTypes = PropTypes.shape({\n  value: PropTypes.oneOf(Object.values(TEMPLATES_GALLERY_SORT_OPTIONS)),\n  set: PropTypes.func,\n});\n"
  },
  {
    "path": "packages/dashboard/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../date\" },\n    { \"path\": \"../design-system\" },\n    { \"path\": \"../element-library\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../templates\" },\n    { \"path\": \"../tracking\" },\n    { \"path\": \"../units\" },\n    { \"path\": \"../i18n\" }\n  ],\n  \"include\": [\n    \"src/app/config\",\n    \"src/app/router\",\n    \"src/constants\",\n    \"src/icons\",\n    \"src/types\",\n    \"src/typings\"\n  ]\n}\n"
  },
  {
    "path": "packages/date/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/date/README.md",
    "content": "# Date\n\nA custom wrapper around the [date-fns](https://date-fns.org/) library to handle all thing date and timezones.\n"
  },
  {
    "path": "packages/date/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/date\",\n  \"description\": \"Date-handling package, a tiny wrapper around date-fns.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"datetime\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/date/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/date\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"date-fns\": \"^2.30.0\",\n    \"date-fns-tz\": \"^2.0.0\"\n  },\n  \"devDependencies\": {\n    \"mockdate\": \"^3.0.5\"\n  }\n}\n"
  },
  {
    "path": "packages/date/src/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const FORMAT_TOKEN_SEPARATOR = '\\u2006';\n\nexport const FORMAT_TOKEN_SEPARATOR_REGEX = new RegExp(\n  FORMAT_TOKEN_SEPARATOR,\n  'gi'\n);\n"
  },
  {
    "path": "packages/date/src/convertFormatString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getDaysInMonth, isLeapYear, format } from 'date-fns';\nimport { format as formatWithTZ, zonedTimeToUtc, toDate } from 'date-fns-tz';\n\n/**\n * Internal dependencies\n */\nimport getOptions from './getOptions';\nimport { FORMAT_TOKEN_SEPARATOR } from './constants';\n\nconst MINUTE_IN_SECONDS = 60;\nconst HOUR_IN_MINUTES = 60;\nconst HOUR_IN_SECONDS = HOUR_IN_MINUTES * MINUTE_IN_SECONDS;\n\n/**\n * Map of PHP formats to date-fns formats.\n *\n * @see https://www.php.net/manual/en/datetime.format.php\n * @see https://date-fns.org/v2.16.1/docs/format\n */\nconst formatMap = {\n  // Day of the month, 2 digits with leading zeros. 01 to 31.\n  d: 'dd',\n\n  // A textual representation of a day, three letters. Mon through Sun.\n  D: 'EEE',\n\n  // Day of the month without leading zeros.\t1 to 31.\n  j: 'd',\n\n  // A full textual representation of the day of the week.\tSunday through Saturday\n  l: 'EEEE',\n\n  // ISO-8601 numeric representation of the day of the week. 1 (for Monday) through 7 (for Sunday)\n  N: 'i',\n\n  // English ordinal suffix for the day of the month, 2 characters. st, nd, rd or th.\n  S(date: Date) {\n    // Removes the \"1\" from \"1st\" to get only \"st\".\n    return format(date, 'do').replace(format(date, 'd'), '');\n  },\n\n  // Numeric representation of the day of the week. 0 (for Sunday) through 6 (for Saturday)\n  w(date: Date) {\n    return Number(format(date, 'i')) - 1;\n  },\n\n  // The day of the year (starting from 0). 0 through 365.\n  z(date: Date) {\n    return Number(format(date, 'DDD')) - 1;\n  },\n\n  // ISO-8601 week number of year, weeks starting on Monday. Example: 42 (the 42nd week in the year).\n  W: 'I',\n\n  // A full textual representation of a month, such as January or March.\n  F: 'MMMM',\n\n  // Numeric representation of a month, with leading zeros. 01 through 12.\n  m: 'MM',\n\n  // A short textual representation of a month, three letters. Jan through Dec.\n  M: 'MMM',\n\n  // Numeric representation of a month, without leading zeros. 1 through 12.\n  n: 'M',\n\n  // Number of days in the given month. 28 through 31\n  t(date: Date) {\n    return getDaysInMonth(date);\n  },\n\n  // Whether it's a leap year. 1 if it is a leap year, 0 otherwise.\n  L(date: Date) {\n    return Number(isLeapYear(date));\n  },\n\n  // ISO-8601 week-numbering year.\n  // This has the same value as Y, except that if the ISO week number (W) belongs to the previous or next year, that year is used instead.\n  // Examples: 1999 or 2003\n  o: 'RRRR',\n\n  // A full numeric representation of a year, 4 digits. Examples: 1999 or 2003\n  Y: 'yyyy',\n\n  //  A two digit representation of a year. Examples: 99 or 03\n  y: 'yy',\n\n  // Lowercase Ante meridiem and Post meridiem. am or pm.\n  a: 'aaa',\n\n  // Uppercase Ante meridiem and Post meridiem. AM or PM\n  A: 'aa',\n\n  //  Swatch Internet time. 000 through 999.\n  B(date: Date) {\n    // Biel Mean Time (BMT) is UTC+1.\n    const timezoned = zonedTimeToUtc(date, '+0100');\n    const seconds = Number.parseInt(format(timezoned, 's'));\n    const minutes = Number.parseInt(format(timezoned, 'm'));\n    const hours = Number.parseInt(format(timezoned, 'H'));\n\n    // Round results like PHP also does.\n    return Math.round(\n      (seconds + minutes * MINUTE_IN_SECONDS + hours * HOUR_IN_SECONDS) / 86.4\n    );\n  },\n\n  // 12-hour format of an hour without leading zeros. 1 through 12.\n  g: 'h',\n\n  // 24-hour format of an hour without leading zeros. 0 through 23\n  G: 'H',\n\n  // 12-hour format of an hour with leading zeros. 01 through 12.\n  h: 'hh',\n\n  // 24-hour format of an hour with leading zeros. 00 through 23.\n  H: 'HH',\n\n  // Minutes with leading zeros. 00 to 59.\n  i: 'mm',\n\n  // Seconds with leading zeros. 00 through 59.\n  s: 'ss',\n\n  // Microseconds. Example: 654321.\n  u: 'SSSSSS',\n\n  // Milliseconds. Example: 654.\n  v: 'SSS',\n\n  // Timezone identifier. Examples: UTC, GMT, Atlantic/Azores.\n  e: 'zzzz',\n\n  // Whether or not the date is in daylight saving time.\t1 if Daylight Saving Time, 0 otherwise.\n  I() {\n    // TODO: Not implemented yet.\n    return 0;\n  },\n\n  // Difference to Greenwich time (GMT) without colon between hours and minutes. Example: +0200\n  O: 'xx',\n\n  // Difference to Greenwich time (GMT) with colon between hours and minutes. Example: +02:00\n  P: 'xxx',\n\n  // Timezone abbreviation. Examples: EST, MDT.\n  T: 'zzz',\n\n  // Timezone offset in seconds. -43200 through 50400.\n  Z(date: Date) {\n    const offset = formatWithTZ(\n      toDate(date, getOptions()),\n      'XXX',\n      getOptions()\n    );\n\n    if ('Z' === offset) {\n      return 0;\n    }\n\n    const sign = offset[0] === '-' ? -1 : 1;\n    const parts = offset.substring(1).split(':').map(Number);\n    return sign * (parts[0] * HOUR_IN_MINUTES + parts[1]) * MINUTE_IN_SECONDS;\n  },\n\n  // ISO 8601 date. Example: 2004-02-12T15:19:21+00:00\n  c(date: Date) {\n    return formatWithTZ(\n      toDate(date, getOptions()),\n      \"yyyy-MM-dd'T'HH:mm:ssxxx\",\n      getOptions()\n    );\n  },\n\n  // RFC 2822 formatted date.\n  r(date: Date) {\n    return formatWithTZ(\n      toDate(date, getOptions()),\n      'EEE, dd MMM yyyy HH:mm:ss xx',\n      getOptions()\n    );\n  },\n\n  // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).\n  U: 't',\n};\n\ntype FormatMap = typeof formatMap;\ntype DateKey = keyof FormatMap;\ntype ObtainKeys<Obj, Type> = {\n  [Prop in keyof Obj]: Obj[Prop] extends Type ? Prop : never;\n}[keyof Obj];\ntype DateStringKey = ObtainKeys<FormatMap, string>;\ntype DateFormatter =\n  | ((date: Date) => string | number)\n  | (() => string | number);\ntype DateFunctionKey = ObtainKeys<FormatMap, DateFormatter>;\n\n/**\n * Formats a date. Does not alter the date's timezone.\n *\n * @see https://www.php.net/manual/en/datetime.format.php\n * @param dateFormat PHP-style formatting string.\n * @param date Date object.\n * @return Formatted date.\n */\nfunction convertFormatString(dateFormat: string, date: Date) {\n  let i;\n  let char;\n  const newFormat = [];\n\n  for (i = 0; i < dateFormat.length; i++) {\n    char = dateFormat[i];\n\n    // Is this an escape?\n    if ('\\\\' === char) {\n      // Add next character, then move on.\n      i++;\n      newFormat.push(`'${dateFormat[i]}'`);\n      continue;\n    }\n\n    if (char in formatMap) {\n      if (typeof formatMap[char as DateKey] === 'function') {\n        // If the format is a function, call it.\n        newFormat.push(`'${formatMap[char as DateFunctionKey](date)}'`);\n      } else {\n        // Otherwise, add as a formatting string.\n        newFormat.push(formatMap[char as DateStringKey]);\n      }\n    } else {\n      newFormat.push(char);\n    }\n  }\n\n  // Join with an arbitrary unicode character in order to create space between format tokens,\n  // as PHP doesn't use repeating tokens to indicate a different format, and instead the results\n  // of each call of the token should be concatenated with the previous.\n  return newFormat.join(FORMAT_TOKEN_SEPARATOR);\n}\n\nexport default convertFormatString;\n"
  },
  {
    "path": "packages/date/src/format.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { format as _format, toDate } from 'date-fns-tz';\n\n/**\n * Internal dependencies\n */\nimport { FORMAT_TOKEN_SEPARATOR_REGEX } from './constants';\nimport convertFormatString from './convertFormatString';\nimport getOptions from './getOptions';\n\n/**\n * Formats a date by a given format.\n *\n * @param date Date to format.\n * @param formatString PHP-style date format.\n * @return Formatted date.\n */\nfunction format(date: Date | string, formatString: string) {\n  if (!date) {\n    return '';\n  }\n\n  const parsedDate = toDate(date);\n  const options = getOptions();\n  const convertedFormat = convertFormatString(formatString, parsedDate);\n\n  return _format(parsedDate, convertedFormat, options).replace(\n    FORMAT_TOKEN_SEPARATOR_REGEX,\n    ''\n  );\n}\n\nexport default format;\n"
  },
  {
    "path": "packages/date/src/formatDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport format from './format';\nimport { getSettings } from './settings';\n\n/**\n * Formats a date by dateSettings.dateFormat (no time).\n *\n * @param date Date to format.\n * @return Displayable relative date string\n */\nfunction formatDate(date: Date | string) {\n  const settings = getSettings();\n  const { dateFormat } = settings;\n\n  return format(date, dateFormat);\n}\n\nexport default formatDate;\n"
  },
  {
    "path": "packages/date/src/formatDistance.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\n\ntype Token = 'lessThanXMinutes' | 'xMinutes' | 'aboutXHours' | 'xHours';\ntype Formatter = Record<Token, (count: number) => string>;\ntype Options = {\n  addSuffix?: boolean;\n  comparison?: number;\n};\n\nconst formatDistanceLocale: Formatter = {\n  lessThanXMinutes(count: number) {\n    return sprintf(\n      /* translators: Time difference between two dates, in minutes (min=minute). %s: Number of minutes. */\n      _n('less than %s min', 'less than %s mins', count, 'web-stories'),\n      String(count)\n    );\n  },\n\n  xMinutes(count: number) {\n    return sprintf(\n      /* translators: Time difference between two dates, in minutes. %s: Number of minutes. */\n      _n('%s minute', '%s minutes', count, 'web-stories'),\n      String(count)\n    );\n  },\n\n  aboutXHours(count: number) {\n    if (1 === count) {\n      return __('an hour', 'web-stories');\n    }\n\n    return sprintf(\n      /* translators: Time difference between two dates, in hours. %s: Number of hours. */\n      _n('%s hour', '%s hours', count, 'web-stories'),\n      String(count)\n    );\n  },\n\n  xHours(count: number) {\n    return sprintf(\n      /* translators: Time difference between two dates, in hours. %s: Number of hours. */\n      _n('%s hour', '%s hours', count, 'web-stories'),\n      String(count)\n    );\n  },\n};\n\nexport default function formatDistance(\n  token: Token,\n  count: number,\n  options: Options\n) {\n  options = options || {};\n\n  const result = formatDistanceLocale[token](count);\n\n  if (options.addSuffix) {\n    if ((options.comparison || 0) > 0) {\n      return sprintf(\n        /* translators: %s: Human-readable time difference. */\n        __('in %s', 'web-stories'),\n        result\n      );\n    } else {\n      return sprintf(\n        /* translators: %s: Human-readable time difference. */\n        __('%s ago', 'web-stories'),\n        result\n      );\n    }\n  }\n\n  return result;\n}\n"
  },
  {
    "path": "packages/date/src/formatTime.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport format from './format';\nimport { getSettings } from './settings';\n\n/**\n * Formats a date by dateSettings.timeFormat.\n *\n * @param date Date to format.\n * @return Displayable relative date string\n */\nfunction formatTime(date: Date | string) {\n  const settings = getSettings();\n  const { timeFormat } = settings;\n  return format(date, timeFormat);\n}\n\nexport default formatTime;\n"
  },
  {
    "path": "packages/date/src/getOptions.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport originalLocale from 'date-fns/locale/en-US/index';\n/**\n * Internal dependencies\n */\nimport buildLocalizeFn from './third_party/buildLocalizeFn';\n\n/** @typedef {import('date-fns-tz').OptionsWithTZ} OptionsWithTZ */\n/** @typedef {import('date-fns-tz').Locale} Locale */\n\n/**\n * Internal dependencies\n */\nimport { getSettings } from './settings';\nimport formatDistance from './formatDistance';\nimport getTimeZoneString from './getTimeZoneString';\n\n/**\n * Returns date-fns option.\n *\n * Takes locale settings from the host platform (e.g. WordPress)\n * and builds a special locale object for use with date-fns.\n *\n * If no locale settings are specified, some English strings\n * taken from date-fns's default en-US locale will be used.\n *\n * @return Date options.\n */\nfunction getOptions() {\n  const settings = getSettings();\n  const {\n    locale: localeCode,\n    weekStartsOn,\n    months,\n    monthsShort,\n    weekdays,\n    weekdaysShort,\n    weekdaysInitials,\n  } = settings;\n\n  const monthValues = {\n    narrow: monthsShort || [\n      'J',\n      'F',\n      'M',\n      'A',\n      'M',\n      'J',\n      'J',\n      'A',\n      'S',\n      'O',\n      'N',\n      'D',\n    ],\n    abbreviated: monthsShort || [\n      'Jan',\n      'Feb',\n      'Mar',\n      'Apr',\n      'May',\n      'Jun',\n      'Jul',\n      'Aug',\n      'Sep',\n      'Oct',\n      'Nov',\n      'Dec',\n    ],\n    wide: months || [\n      'January',\n      'February',\n      'March',\n      'April',\n      'May',\n      'June',\n      'July',\n      'August',\n      'September',\n      'October',\n      'November',\n      'December',\n    ],\n  };\n\n  const dayValues = {\n    narrow: weekdaysInitials || ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n    short: weekdaysShort || ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n    abbreviated: weekdaysShort || [\n      'Sun',\n      'Mon',\n      'Tue',\n      'Wed',\n      'Thu',\n      'Fri',\n      'Sat',\n    ],\n    wide: weekdays || [\n      'Sunday',\n      'Monday',\n      'Tuesday',\n      'Wednesday',\n      'Thursday',\n      'Friday',\n      'Saturday',\n    ],\n  };\n\n  const localize = {\n    ...originalLocale.localize,\n\n    month: buildLocalizeFn({\n      values: monthValues,\n      defaultWidth: 'wide',\n    }),\n\n    day: buildLocalizeFn({\n      values: dayValues,\n      defaultWidth: 'wide',\n    }),\n  };\n\n  const locale = {\n    ...originalLocale,\n    code: localeCode || originalLocale.code,\n    formatDistance: formatDistance,\n    localize: localize,\n    options: {\n      weekStartsOn: weekStartsOn,\n    },\n  } as Locale;\n\n  return {\n    weekStartsOn,\n    timeZone: getTimeZoneString(),\n    locale,\n  };\n}\n\nexport default getOptions;\n"
  },
  {
    "path": "packages/date/src/getRelativeDisplayDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { formatDistanceToNow, isToday, isYesterday } from 'date-fns';\nimport { toDate } from 'date-fns-tz';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport getOptions from './getOptions';\nimport formatDate from './formatDate';\n\n/**\n * Formats a date to display relative to time passed since date.\n *\n * If date to display is < 1 day ago it will display rounded time since date using timezone.\n * If date to display matches yesterday's date it will display \"yesterday\".\n * Otherwise date will come back formatted by dateSettings.dateFormat (no time).\n *\n * @param date Date to format according to how much time or how many days have passed since date.\n * @return Displayable relative date string\n */\nfunction getRelativeDisplayDate(date: Date | string) {\n  if (!date) {\n    return '';\n  }\n\n  const displayDate = toDate(date);\n  if (isToday(displayDate)) {\n    const { locale } = getOptions();\n    return formatDistanceToNow(displayDate, {\n      includeSeconds: false,\n      addSuffix: true,\n      locale,\n    });\n  }\n\n  if (isYesterday(displayDate)) {\n    return __('yesterday', 'web-stories');\n  }\n\n  return formatDate(date);\n}\n\nexport default getRelativeDisplayDate;\n"
  },
  {
    "path": "packages/date/src/getTimeZoneString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getSettings } from './settings';\n\n/**\n * Transforms a given number into a valid UTC Offset in hours and possibly minutes.\n *\n * @param offset A UTC offset as a number in either hours or minutes\n * @return UTC offset as a string.\n */\nfunction numberToUTCOffset(offset: number) {\n  const sign = offset < 0 ? '-' : '+';\n  const absoluteOffset = Math.abs(offset);\n  const isHours = absoluteOffset <= 12;\n  const offsetInMinutes = isHours\n    ? Math.round((absoluteOffset % 1) * 60)\n    : Math.round(absoluteOffset % 60);\n  const offsetInHours = isHours\n    ? Math.floor(absoluteOffset)\n    : Math.floor(absoluteOffset / 60);\n\n  const hoursAsString = String(offsetInHours).padStart(2, '0');\n\n  if (offsetInMinutes > 0) {\n    const minutesAsString = String(offsetInMinutes).padStart(2, '0');\n    return `${sign}${hoursAsString}:${minutesAsString}`;\n  }\n\n  return `${sign}${hoursAsString}`;\n}\n\n/**\n * Returns a properly formatted timezone from a timezone string or offset.\n *\n * @return Timezone string.\n */\nfunction getTimeZoneString() {\n  const settings = getSettings();\n  const { timezone, gmtOffset } = settings;\n\n  if (timezone) {\n    return timezone;\n  }\n\n  if (!Number.isNaN(Number(gmtOffset))) {\n    return numberToUTCOffset(gmtOffset);\n  }\n\n  return '+00';\n}\n\nexport default getTimeZoneString;\n"
  },
  {
    "path": "packages/date/src/hasLeadingZeros.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getSettings } from './settings';\n\nfunction hasLeadingZeros() {\n  const settings = getSettings();\n  const { timeFormat } = settings;\n\n  if (!timeFormat) {\n    return true;\n  }\n\n  return /h(?!\\\\)/.test(\n    timeFormat\n      .toLowerCase() // Test only for the lower case \"h\".\n      .replace(/\\\\\\\\/g, '') // Replace \"//\" with empty strings.\n      .split('')\n      .reverse()\n      .join('') // Reverse the string and test for \"h\" not followed by a slash.\n  );\n}\n\nexport default hasLeadingZeros;\n"
  },
  {
    "path": "packages/date/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {Object} DateSettings\n * @property {string} timezone - Indicates what the timezone to set the date\n * @property {number} gmtOffset - Indicates the offset to use to set the date\n * @property {string} dateFormat - Indicates the format the date should be displayed as\n * @property {string} timeFormat - Indicates the format the time should be displayed as} date\n * @param {*} dateSettings\n */\n\nexport {\n  subMinutes,\n  isValid,\n  differenceInSeconds,\n  differenceInDays,\n  isAfter,\n  compareDesc,\n  compareAsc,\n} from 'date-fns';\nexport { toDate } from 'date-fns-tz';\n\nexport { getSettings, updateSettings } from './settings';\nexport { default as format } from './format';\nexport { default as getRelativeDisplayDate } from './getRelativeDisplayDate';\nexport { default as formatDate } from './formatDate';\nexport { default as formatTime } from './formatTime';\nexport { default as toUTCDate } from './toUTCDate';\nexport { default as is12Hour } from './is12Hour';\nexport { default as hasLeadingZeros } from './hasLeadingZeros';\nexport { default as getOptions } from './getOptions';\n"
  },
  {
    "path": "packages/date/src/is12Hour.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getSettings } from './settings';\n\nfunction is12Hour() {\n  const settings = getSettings();\n  const { timeFormat } = settings;\n\n  if (!timeFormat) {\n    return true;\n  }\n\n  return /a(?!\\\\)/.test(\n    timeFormat\n      .toLowerCase() // Test only for the lower case \"a\".\n      .replace(/\\\\\\\\/g, '') // Replace \"//\" with empty strings.\n      .split('')\n      .reverse()\n      .join('') // Reverse the string and test for \"a\" not followed by a slash.\n  );\n}\n\nexport default is12Hour;\n"
  },
  {
    "path": "packages/date/src/settings.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype WeekdayIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\nexport const DEFAULT_DATE_SETTINGS = {\n  dateFormat: 'F j, Y',\n  timeFormat: 'g:i a',\n  gmtOffset: 0,\n  timezone: '',\n  timezoneAbbr: '',\n  weekStartsOn: 0 as WeekdayIndex,\n};\n\ntype Settings = {\n  dateFormat: string;\n  timeFormat: string;\n  gmtOffset: number;\n  timezone: string;\n  timezoneAbbr: string;\n  weekStartsOn: WeekdayIndex;\n  locale?: string;\n  months?: readonly [\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n  ];\n  monthsShort?: readonly [\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n  ];\n  weekdays?: readonly [string, string, string, string, string, string, string];\n  weekdaysShort?: readonly [\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n  ];\n  weekdaysInitials?: readonly [\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n    string,\n  ];\n};\n\nlet settings: Settings = {\n  ...DEFAULT_DATE_SETTINGS,\n};\n\n/**\n * Reset date settings to their defaults.\n */\nexport function resetSettings() {\n  settings = DEFAULT_DATE_SETTINGS;\n}\n\n/**\n * Update date settings.\n *\n * @param newSettings Date settings.\n */\nexport function updateSettings(newSettings: Partial<Settings>) {\n  settings = {\n    ...settings,\n    ...newSettings,\n  };\n}\n\n/**\n * Returns the current date settings.\n *\n * @return Date settings.\n */\nexport function getSettings() {\n  return settings;\n}\n"
  },
  {
    "path": "packages/date/src/test/convertFormatString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { FORMAT_TOKEN_SEPARATOR_REGEX } from '../constants';\nimport convertFormatString from '../convertFormatString';\nimport format from '../format';\n\ndescribe('date/convertFormatString', () => {\n  it.each([\n    ['d-m-Y H:i', 'dd-MM-yyyy HH:mm'],\n    ['F j, Y', 'MMMM d, yyyy'],\n    ['F M l D', 'MMMM MMM EEEE EEE'],\n    ['G \\\\h h \\\\m\\\\i\\\\n', \"H 'h' hh 'm''i''n'\"],\n  ])(\n    'converts PHP date format string to its date-fns equivalent',\n    (formatString, expectedOutput) => {\n      const convertedWithoutSeparator = convertFormatString(\n        formatString,\n        new Date()\n      ).replace(FORMAT_TOKEN_SEPARATOR_REGEX, '');\n      expect(convertedWithoutSeparator).toStrictEqual(expectedOutput);\n      expect(() => format(new Date(), formatString)).not.toThrow();\n    }\n  );\n});\n"
  },
  {
    "path": "packages/date/src/test/format.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport MockDate from 'mockdate';\n\n/**\n * Internal dependencies\n */\nimport format from '../format';\nimport { resetSettings, updateSettings } from '../settings';\n\ndescribe('date/format', () => {\n  beforeEach(() => {\n    MockDate.set('2020-07-15T22:47:26+00:00');\n  });\n\n  afterEach(() => {\n    MockDate.reset();\n    resetSettings();\n  });\n\n  it('should support \"S\" to obtain ordinal suffix of day of the month', () => {\n    const formattedDate = format('2019-06-18T11:00:00.000', 'S');\n\n    // th for 18th\n    expect(formattedDate).toBe('th');\n  });\n\n  it('should support \"z\" to obtain zero-indexed day of the year', () => {\n    const formattedDate = format('2019-01-01', 'z');\n\n    expect(formattedDate).toBe('0');\n  });\n\n  it('should support \"t\" to obtain the days in a given month', () => {\n    const formattedDate = format('2019-02', 't');\n\n    expect(formattedDate).toBe('28');\n  });\n\n  it('should support \"L\" to obtain whether or not the year is a leap year', () => {\n    const formattedDate = format('2020', 'L');\n\n    expect(formattedDate).toBe('1');\n  });\n\n  // TODO: Fix implementation/tests.\n  //eslint-disable-next-line jest/no-disabled-tests -- Not implemented yet.\n  it.skip('should support \"B\" to obtain the time in Swatch Internet Time (.beats)', () => {\n    const formattedDate = format('2020-10-09T11:00:00.000', 'B');\n\n    expect(formattedDate).toBe('500');\n  });\n\n  it('should support \"T\" to obtain the timezone abbreviation for the given date', () => {\n    updateSettings({\n      gmtOffset: -4,\n      timezone: 'America/New_York',\n    });\n\n    const formattedDate = format('2020-01-01T11:00:00.000', 'T');\n\n    expect(formattedDate).toBe('EST');\n  });\n\n  it('should support \"e\" to obtain timezone identifier', () => {\n    updateSettings({\n      gmtOffset: -4,\n      timezone: 'America/New_York',\n    });\n\n    const formattedDate = format('2020-10-09T11:00:00.000', 'e');\n\n    expect(formattedDate).toBe('Eastern Daylight Time');\n  });\n\n  it('should support \"w\" to obtain day of the week starting from 0', () => {\n    const formattedDate = format('2020-01-01T12:00:00.000', 'w'); // Wednesday Jan 1st, 2020\n\n    expect(formattedDate).toBe('2');\n  });\n\n  // TODO: Fix implementation/tests.\n  //eslint-disable-next-line jest/no-disabled-tests\n  it.skip('should support \"U\" to get epoc for given date', () => {\n    const formattedDate = format('2020-10-09T02:00:00.000', 'U');\n\n    expect(formattedDate).toBe('1602201600');\n  });\n\n  it('should support \"c\" to obtain the full date', () => {\n    const formattedDate = format('2020-10-09T11:00:00.000', 'c');\n\n    expect(formattedDate).toBe('2020-10-09T11:00:00+00:00');\n  });\n\n  it('should support \"r\" to obtain RFC2822 formatted date', () => {\n    const formattedDate = format('2020-10-09T11:00:00.000', 'r');\n\n    expect(formattedDate).toBe('Fri, 09 Oct 2020 11:00:00 +0000');\n  });\n\n  it('should support \"M\" to obtain short textual representation of a month, three letters', () => {\n    const formattedDate = format('2020-10-09T11:00:00.000', 'MM');\n\n    expect(formattedDate).toBe('OctOct');\n  });\n\n  //eslint-disable-next-line jest/no-disabled-tests -- Not implemented yet.\n  it.skip('should support \"I\" to obtain whether or not the timezone is observing DST', () => {\n    const formattedFall = format('2020-10-09T11:00:00.000', 'I');\n\n    expect(formattedFall).toBe('1');\n\n    const formattedWinter = format('2020-01-09T11:00:00.000', 'I');\n\n    expect(formattedWinter).toBe('0');\n  });\n\n  it('should support \"Z\" to obtain timezone offset in seconds', () => {\n    const formattedDate = format('2020-10-09T11:00:00.000', 'Z');\n\n    expect(formattedDate).toBe('0');\n  });\n\n  it('should support \"G \\\\h i \\\\m\\\\i\\\\n\" date format', () => {\n    const formattedDate = format(\n      '2019-06-18T11:22:00.000',\n      'G \\\\h i \\\\m\\\\i\\\\n'\n    );\n\n    // th for 18th\n    expect(formattedDate).toBe('11 h 22 min');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/formatDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport MockDate from 'mockdate';\n\n/**\n * Internal dependencies\n */\nimport formatDate from '../formatDate';\nimport { updateSettings, resetSettings } from '../settings';\n\ndescribe('date/formatDate', () => {\n  beforeEach(() => {\n    MockDate.set('2020-07-15T22:47:26+00:00');\n  });\n\n  afterEach(() => {\n    MockDate.reset();\n    resetSettings();\n  });\n\n  // Uses DEFAULT_DATE_SETTINGS.dateFormat\n  it('should return May 2, 2020 with no formatting options', () => {\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('May 2, 2020');\n  });\n\n  it('should return \"May 2, 2020\" with \"F j, Y\" formatting options', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('May 2, 2020');\n  });\n\n  it('should return \"2020-05-02\" with \"Y-m-d\" formatting options', () => {\n    updateSettings({\n      dateFormat: 'Y-m-d',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('2020-05-02');\n  });\n\n  it('should return 05/02/2020 with m/d/Y formatting options', () => {\n    updateSettings({\n      dateFormat: 'm/d/Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('05/02/2020');\n  });\n\n  it('should return 02/05/2020 with d/m/Y formatting options', () => {\n    updateSettings({\n      dateFormat: 'd/m/Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('02/05/2020');\n  });\n\n  it('should return Sat 05 02 2020 with D m d yy formatting options', () => {\n    updateSettings({\n      dateFormat: 'D m d yy',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const dateString = '2020-05-02T10:47:26';\n    const formattedDate = formatDate(dateString);\n\n    expect(formattedDate).toBe('Sat 05 02 2020');\n  });\n\n  it('should return an empty string when being passed an empty string', () => {\n    const formattedDate = formatDate('');\n\n    expect(formattedDate).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/formatTime.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport MockDate from 'mockdate';\n\n/**\n * Internal dependencies\n */\nimport formatTime from '../formatTime';\nimport { updateSettings, resetSettings } from '../settings';\n\ndescribe('date/formatTime', () => {\n  beforeEach(() => {\n    MockDate.set('2020-07-15T22:47:26+00:00');\n  });\n\n  afterEach(() => {\n    MockDate.reset();\n    resetSettings();\n  });\n\n  it('should return 10:47 am with no formatting options', () => {\n    const dateString = '2020-05-02T10:47:26';\n    const formattedTime = formatTime(dateString);\n\n    expect(formattedTime).toBe('10:47 am');\n  });\n\n  it('should return 5:47 PM with g:i A formatting options', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n    const dateString = '2020-05-02T17:47:26';\n    const formattedTime = formatTime(dateString);\n\n    expect(formattedTime).toBe('5:47 PM');\n  });\n\n  it('should return 20:23 with H:i formatting options', () => {\n    updateSettings({\n      dateFormat: 'm/d/Y',\n      gmtOffset: -7,\n      timeFormat: 'H:i',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const dateString = '2020-05-02T20:23:39';\n    const formattedTime = formatTime(dateString);\n\n    expect(formattedTime).toBe('20:23');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/getRelativeDisplayDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport MockDate from 'mockdate';\nimport { subMinutes, subHours, subDays } from 'date-fns';\nimport { toDate } from 'date-fns-tz';\n\n/**\n * Internal dependencies\n */\nimport getRelativeDisplayDate from '../getRelativeDisplayDate';\nimport { updateSettings, resetSettings } from '../settings';\nimport getOptions from '../getOptions';\n\n/**\n * Returns the current date in the site's timezone.\n *\n * @return Date object.\n */\nfunction getCurrentDate() {\n  return toDate(new Date(), getOptions());\n}\n\ndescribe('date/getRelativeDisplayDate', () => {\n  beforeEach(() => {\n    MockDate.set('2020-07-15T12:00:00.000');\n  });\n\n  afterEach(() => {\n    MockDate.reset();\n    resetSettings();\n  });\n\n  it('should return 2 minutes ago in America/New_York', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -4,\n      timeFormat: 'g:i A',\n      timezone: 'America/New_York',\n    });\n    const date = subMinutes(getCurrentDate(), 2);\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('2 minutes ago');\n  });\n\n  it('should return 2 minutes ago in America/Los_Angeles', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = subMinutes(getCurrentDate(), 2);\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('2 minutes ago');\n  });\n\n  it('should return an hour ago', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = subHours(getCurrentDate(), 1);\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('an hour ago');\n  });\n\n  it('should return 2 hours ago', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n    const date = subHours(getCurrentDate(), 2);\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('2 hours ago');\n  });\n\n  it('should return yesterday', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n    const date = subDays(getCurrentDate(), 1);\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('yesterday');\n  });\n\n  // Uses DEFAULT_DATE_SETTINGS.dateFormat\n  it('should return May 2, 2020 with no formatting options', () => {\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('May 2, 2020');\n  });\n\n  it('should return May 2, 2020 with F j, Y formatting options', () => {\n    updateSettings({\n      dateFormat: 'F j, Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('May 2, 2020');\n  });\n\n  it('should return 2020-05-02 with Y-m-d formatting options', () => {\n    updateSettings({\n      dateFormat: 'Y-m-d',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('2020-05-02');\n  });\n\n  it('should return 05/02/2020 with m/d/Y formatting options', () => {\n    updateSettings({\n      dateFormat: 'm/d/Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('05/02/2020');\n  });\n\n  it('should return 02/05/2020 with d/m/Y formatting options', () => {\n    updateSettings({\n      dateFormat: 'd/m/Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('02/05/2020');\n  });\n\n  it('should return Sat 05 02 2020 with D m d yy formatting options', () => {\n    updateSettings({\n      dateFormat: 'D m d yy',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('Sat 05 02 2020');\n  });\n\n  it('should correctly format a string date', () => {\n    updateSettings({\n      dateFormat: 'm/d/Y',\n      gmtOffset: -7,\n      timeFormat: 'g:i A',\n      timezone: 'America/Los_Angeles',\n    });\n\n    const date = '2020-05-02T10:47:26';\n    const formattedDate = getRelativeDisplayDate(date);\n\n    expect(formattedDate).toBe('05/02/2020');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/getTimeZoneString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getTimeZoneString from '../getTimeZoneString';\nimport { resetSettings, updateSettings } from '../settings';\n\ndescribe('date/getTimeZoneString', () => {\n  afterEach(() => {\n    resetSettings();\n  });\n\n  it('returns +00 by default', () => {\n    expect(getTimeZoneString()).toBe('+00');\n  });\n\n  it('returns timezone if present', () => {\n    updateSettings({ timezone: '+02:30' });\n    expect(getTimeZoneString()).toBe('+02:30');\n  });\n\n  it('returns value as hours from gmtOffset if low number', () => {\n    updateSettings({ gmtOffset: 10 });\n    expect(getTimeZoneString()).toBe('+10');\n\n    updateSettings({ gmtOffset: -6 });\n    expect(getTimeZoneString()).toBe('-06');\n  });\n\n  it('returns value converted from minutes to hours from gmtOffset if high number', () => {\n    updateSettings({ gmtOffset: 120 });\n    expect(getTimeZoneString()).toBe('+02');\n\n    updateSettings({ gmtOffset: -150 });\n    expect(getTimeZoneString()).toBe('-02:30');\n\n    updateSettings({ gmtOffset: 375 });\n    expect(getTimeZoneString()).toBe('+06:15');\n  });\n\n  it('rounds minutes appropriately', () => {\n    // With low numbers where minutes are the decimals\n    updateSettings({ gmtOffset: 6.25 });\n    expect(getTimeZoneString()).toBe('+06:15');\n\n    updateSettings({ gmtOffset: 6.27 });\n    expect(getTimeZoneString()).toBe('+06:16');\n\n    // With high numbers where minutes are the %60\n    updateSettings({ gmtOffset: -121 });\n    expect(getTimeZoneString()).toBe('-02:01');\n\n    updateSettings({ gmtOffset: -121.1 });\n    expect(getTimeZoneString()).toBe('-02:01');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/hasLeadingZeros.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport hasLeadingZeros from '../hasLeadingZeros';\nimport { updateSettings } from '../settings';\n\ndescribe('date/hasLeadingZeros', () => {\n  it('should detect time format correctly', () => {\n    updateSettings({\n      timeFormat: 'h:i A',\n    });\n\n    const hasLeadingZeros1 = hasLeadingZeros();\n    expect(hasLeadingZeros1).toBeTrue();\n\n    updateSettings({\n      timeFormat: 'H:i A',\n    });\n\n    const hasLeadingZeros2 = hasLeadingZeros();\n    expect(hasLeadingZeros2).toBeTrue();\n\n    updateSettings({\n      timeFormat: 'g:i',\n    });\n\n    const hasLeadingZeros3 = hasLeadingZeros();\n    expect(hasLeadingZeros3).toBeFalse();\n\n    updateSettings({\n      timeFormat: 'G:i',\n    });\n\n    const hasLeadingZeros4 = hasLeadingZeros();\n    expect(hasLeadingZeros4).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/is12Hour.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport is12Hour from '../is12Hour';\nimport { updateSettings } from '../settings';\n\ndescribe('date/is12Hour', () => {\n  it('should default to true', () => {\n    expect(is12Hour()).toBeTrue();\n  });\n\n  it('should detect time format correctly', () => {\n    updateSettings({\n      timeFormat: 'g:i A',\n    });\n\n    const is12Hour1 = is12Hour();\n    expect(is12Hour1).toBeTrue();\n\n    updateSettings({\n      timeFormat: 'H:i',\n    });\n\n    const is12Hour2 = is12Hour();\n    expect(is12Hour2).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/date/src/test/toUTCDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport MockDate from 'mockdate';\n\n/**\n * Internal dependencies\n */\nimport toUTCDate from '../toUTCDate';\n\ndescribe('date/toUTCDate', () => {\n  beforeEach(() => {\n    MockDate.set('2020-07-15T22:47:26+00:00');\n  });\n\n  afterEach(() => {\n    MockDate.reset();\n  });\n\n  it('should add UTC timezone information to date', () => {\n    const dateString = '2020-05-02T10:47:26';\n    const utcDate = toUTCDate(dateString);\n\n    expect(utcDate.toISOString()).toBe('2020-05-02T10:47:26.000Z');\n  });\n});\n"
  },
  {
    "path": "packages/date/src/third_party/buildLocalizeFn.ts",
    "content": "/**\n * @copyright 2021 Sasha Koss and Lesha Koss https://kossnocorp.mit-license.org\n * @license   MIT\n */\n\n/**\n * Original code from date-fns package modified for this project.\n *\n * @see https://github.com/date-fns/date-fns/issues/1116\n * @see https://github.com/date-fns/date-fns/blob/fadbd4eb7920bf932c25f734f3949027b2fe4887/src/locale/_lib/buildLocalizeFn/index.ts\n * @copyright 2023 Google LLC\n * @license   Apache-2.0\n */\n\ntype Era = 0 | 1;\n\ntype Quarter = 1 | 2 | 3 | 4;\n\ntype Day = 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\ntype Month = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;\n\ntype Unit =\n  | 'second'\n  | 'minute'\n  | 'hour'\n  | 'day'\n  | 'dayOfYear'\n  | 'date'\n  | 'week'\n  | 'month'\n  | 'quarter'\n  | 'year';\n\ntype LocalePatternWidth = 'narrow' | 'short' | 'abbreviated' | 'wide' | 'any';\n\ntype LocaleDayPeriod =\n  | 'am'\n  | 'pm'\n  | 'midnight'\n  | 'noon'\n  | 'morning'\n  | 'afternoon'\n  | 'evening'\n  | 'night';\n\ntype LocaleUnit = Era | Quarter | Month | Day | LocaleDayPeriod;\n\ntype LocalizeUnitIndex<U extends LocaleUnit> = U extends LocaleUnit\n  ? LocalizeUnitValuesIndex<LocalizeUnitValues<U>>\n  : number;\n\ntype LocalizeFn<\n  Result extends LocaleUnit,\n  ArgCallback extends BuildLocalizeFnArgCallback<Result> | undefined =\n    undefined,\n> = (\n  value: ArgCallback extends undefined\n    ? Result\n    : Result extends Quarter\n      ? Quarter\n      : LocalizeUnitIndex<Result>,\n  options?: {\n    width?: LocalePatternWidth;\n    context?: 'formatting' | 'standalone';\n    unit?: Unit;\n  }\n) => string;\n\ntype LocalizeEraValues = readonly [string, string];\n\ntype LocalizeQuarterValues = readonly [string, string, string, string];\n\ntype LocalizeDayValues = readonly [\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n];\n\ntype LocalizeMonthValues = readonly [\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n  string,\n];\n\ntype LocalizeUnitValuesIndex<Values extends LocalizeUnitValues<any>> =\n  Values extends Record<LocaleDayPeriod, string>\n    ? string\n    : Values extends LocalizeEraValues\n      ? Era\n      : Values extends LocalizeQuarterValues\n        ? Quarter\n        : Values extends LocalizeDayValues\n          ? Day\n          : Values extends LocalizeMonthValues\n            ? Month\n            : never;\n\ntype LocalizeUnitValues<U extends LocaleUnit> = U extends LocaleDayPeriod\n  ? Record<LocaleDayPeriod, string>\n  : U extends Era\n    ? LocalizeEraValues\n    : U extends Quarter\n      ? LocalizeQuarterValues\n      : U extends Day\n        ? LocalizeDayValues\n        : U extends Month\n          ? LocalizeMonthValues\n          : never;\n\ntype LocalizePeriodValuesMap<U extends LocaleUnit> = {\n  [pattern in LocalePatternWidth]?: LocalizeUnitValues<U>;\n};\n\ntype BuildLocalizeFnArgCallback<Result extends LocaleUnit> = (\n  value: Result\n) => LocalizeUnitIndex<Result>;\n\ntype BuildLocalizeFnArgs<\n  Result extends LocaleUnit,\n  ArgCallback extends BuildLocalizeFnArgCallback<Result> | undefined,\n> = {\n  values: LocalizePeriodValuesMap<Result>;\n  defaultWidth: LocalePatternWidth;\n  formattingValues?: LocalizePeriodValuesMap<Result>;\n  defaultFormattingWidth?: LocalePatternWidth;\n} & (ArgCallback extends undefined\n  ? { argumentCallback?: undefined }\n  : { argumentCallback: BuildLocalizeFnArgCallback<Result> });\n\nexport default function buildLocalizeFn<\n  Result extends LocaleUnit,\n  ArgCallback extends BuildLocalizeFnArgCallback<Result> | undefined,\n>(\n  args: BuildLocalizeFnArgs<Result, ArgCallback>\n): LocalizeFn<Result, ArgCallback> {\n  return (dirtyIndex, options) => {\n    const context = options?.context ? String(options.context) : 'standalone';\n\n    let valuesArray: LocalizeUnitValues<Result>;\n    if (context === 'formatting' && args.formattingValues) {\n      const defaultWidth = args.defaultFormattingWidth || args.defaultWidth;\n      const width = (\n        options?.width ? String(options.width) : defaultWidth\n      ) as LocalePatternWidth;\n      valuesArray = (args.formattingValues[width] ||\n        args.formattingValues[defaultWidth]) as LocalizeUnitValues<Result>;\n    } else {\n      const defaultWidth = args.defaultWidth;\n      const width = (\n        options?.width ? String(options.width) : args.defaultWidth\n      ) as LocalePatternWidth;\n      valuesArray = (args.values[width] ||\n        args.values[defaultWidth]) as LocalizeUnitValues<Result>;\n    }\n    const index = (\n      args.argumentCallback\n        ? args.argumentCallback(dirtyIndex as Result)\n        : (dirtyIndex as LocalizeUnitIndex<Result> as unknown)\n    ) as LocalizeUnitValuesIndex<typeof valuesArray>;\n    // @ts-ignore: For some reason TypeScript just don't want to match it, no matter how hard we try. I challenge you to try to remove it!\n    return valuesArray[index];\n  };\n}\n"
  },
  {
    "path": "packages/date/src/toUTCDate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { toDate } from 'date-fns-tz';\n\n/**\n * Parses a date as UTC date.\n *\n * Takes a string without timezone information and\n * explicitly marks it as UTC.\n *\n * @param date Date object or string.\n * @return UTC date.\n */\nfunction toUTCDate(date: Date | string) {\n  return toDate(date, { timeZone: '+0000' });\n}\n\nexport default toUTCDate;\n"
  },
  {
    "path": "packages/date/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../i18n\" }],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/design-system/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/design-system/README.md",
    "content": "# Design System\n\nThe story editor's design system.\n"
  },
  {
    "path": "packages/design-system/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/design-system\",\n  \"description\": \"Main UI components for the Web Stories editor and dashboard\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/design-system/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/design-system\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@types/react-modal\": \"^3.16.3\",\n    \"big.js\": \"^7.0.1\",\n    \"mousetrap\": \"^1.6.5\",\n    \"polished\": \"^4.3.1\",\n    \"prop-types\": \"^15.8.1\",\n    \"react-modal\": \"^3.16.3\",\n    \"react-transition-group\": \"^4.4.5\",\n    \"styled-components\": \"^5.3.11\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@types/big.js\": \"^6.2.2\",\n    \"@types/react-transition-group\": \"^4.4.6\",\n    \"@types/styled-components\": \"^5.1.26\",\n    \"use-debounce\": \"^10.0.6\"\n  }\n}\n"
  },
  {
    "path": "packages/design-system/src/components/banner/banner.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type { ForwardedRef, PropsWithChildren } from 'react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Cross } from '../../icons';\nimport { TextSize } from '../../theme';\nimport { Button, ButtonSize, ButtonType, ButtonVariant } from '../button';\nimport { Headline } from '../typography';\n\nconst Title = styled(Headline)`\n  grid-area: title;\n  padding-left: 8px;\n`;\n\nconst Content = styled.div`\n  grid-area: content;\n  margin-bottom: 4px;\n  max-width: 600px;\n  min-width: 50%;\n`;\n\nconst CloseButton = styled(Button)`\n  grid-area: closeButton;\n  justify-self: end;\n  align-self: flex-start;\n`;\n\nconst CloseButtonPlaceholder = styled.div`\n  grid-area: closeButton;\n  justify-self: end;\n  align-self: flex-start;\n  width: 32px;\n  height: 32px;\n`;\n\nconst Container = styled.div`\n  display: grid;\n  width: 100%;\n  min-height: 60px;\n  align-items: baseline;\n  padding: 6px 8px;\n  background-color: ${({ theme }) => theme.colors.gray[5]};\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n\n  max-height: 184px;\n  grid-template-columns: 1fr 32px;\n  grid-template-rows: 3;\n  grid-column-gap: 0;\n  grid-template-areas: '. closeButton' 'title title' 'content content';\n  text-align: center;\n\n  & + & {\n    margin-top: 18px;\n  }\n\n  ${Title} {\n    padding-left: 0;\n    margin-top: -10px;\n  }\n  ${Content} {\n    margin: 8px auto 18px;\n    max-width: 600px;\n  }\n`;\n\ninterface BannerProps {\n  closeButtonLabel: string;\n  title: string;\n  onClose?: () => void;\n}\n\nconst Banner = forwardRef(\n  (\n    {\n      children,\n      closeButtonLabel,\n      title,\n      onClose,\n      ...rest\n    }: PropsWithChildren<BannerProps>,\n    ref: ForwardedRef<HTMLDivElement>\n  ) => {\n    return (\n      <Container ref={ref} {...rest}>\n        <Title as=\"h2\" size={TextSize.XSmall}>\n          {title}\n        </Title>\n        {onClose ? (\n          <CloseButton\n            type={ButtonType.Tertiary}\n            variant={ButtonVariant.Square}\n            size={ButtonSize.Small}\n            aria-label={closeButtonLabel}\n            onClick={onClose}\n          >\n            <Cross aria-hidden />\n          </CloseButton>\n        ) : (\n          <CloseButtonPlaceholder />\n        )}\n        <Content>{children}</Content>\n      </Container>\n    );\n  }\n);\n\nexport default Banner;\n"
  },
  {
    "path": "packages/design-system/src/components/banner/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Banner } from './banner';\n"
  },
  {
    "path": "packages/design-system/src/components/banner/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { Text, Link } from '../../typography';\nimport { Banner } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/Banner',\n  component: Banner,\n  args: {\n    title: 'my banner',\n    isDashboard: false,\n    message: 'I am a banner child',\n  },\n  argTypes: {\n    onClose: { action: 'close banner clicked' },\n  },\n};\n\nexport const _default = {\n  render: ({ message, ...args }) => {\n    return (\n      <Banner closeButtonLabel={'Dismiss storybook banner'} {...args}>\n        <Text.Paragraph size={TextSize.XSmall}>{message}</Text.Paragraph>\n      </Banner>\n    );\n  },\n};\n\nexport const EditorBanner = {\n  render: ({ message, ...args }) => {\n    return (\n      <Banner\n        closeButtonLabel={'Dismiss storybook banner'}\n        onClose={(e) => args.onClose(e)}\n        {...args}\n      >\n        <Text.Paragraph size={TextSize.XSmall}>{message}</Text.Paragraph>\n      </Banner>\n    );\n  },\n\n  args: {\n    title: 'Animations are here!',\n    isDashboard: false,\n    message:\n      'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n  },\n};\n\nexport const DashboardBanner = {\n  render: ({ message, ...args }) => {\n    return (\n      <Banner\n        closeButtonLabel={'Dismiss storybook banner'}\n        onClose={(e) => args.onClose(e)}\n        {...args}\n      >\n        <Text.Paragraph size={TextSize.XSmall}>\n          {message}\n          <Link\n            size={TextSize.XSmall}\n            href=\"https://policies.google.com/privacy\"\n          >\n            {'Google Privacy Policy'}\n          </Link>\n        </Text.Paragraph>\n      </Banner>\n    );\n  },\n\n  args: {\n    title: 'Help improve the editor!',\n    isDashboard: true,\n    message:\n      'Check the box to help us improve the Web Stories plugin by allowing tracking of product usage stats. All data are treated in accordance with ',\n  },\n};\n\nexport const BannerNoBackgroundImage = {\n  render: ({ message, ...args }) => {\n    return (\n      <Banner\n        closeButtonLabel={'Dismiss storybook banner'}\n        onClose={(e) => args.onClose(e)}\n        {...args}\n      >\n        <Text.Paragraph size={TextSize.XSmall}>{message}</Text.Paragraph>\n      </Banner>\n    );\n  },\n\n  args: {\n    title: 'New Feature!',\n    isDashboard: true,\n    message:\n      'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/button/button.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n  PropsWithChildren,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { THEME_CONSTANTS, themeHelpers, TextSize } from '../../theme';\nimport type { Theme } from '../../theme';\nimport {\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  BUTTON_TRANSITION_TIMING,\n} from './constants';\n\ninterface WithTheme {\n  theme: Theme;\n}\n\ninterface ElementProps {\n  size: ButtonSize;\n  $type: ButtonType;\n  isToggled?: boolean;\n}\n\nconst base = css<ElementProps>`\n  display: flex;\n  align-items: center;\n  justify-content: space-around;\n  padding: 0;\n  margin: 0;\n  background: transparent;\n  border: none;\n  cursor: pointer;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  ${({ theme }) => themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n  ${({ theme, size }) =>\n    themeHelpers.expandPresetStyles({\n      preset: {\n        ...theme.typography.presets.label[\n          size === ButtonSize.Small ? TextSize.Small : TextSize.Medium\n        ],\n      },\n      theme,\n    })};\n\n  &:active {\n    background-color: ${({ theme }) => theme.colors.interactiveBg.active};\n    color: ${({ theme }) => theme.colors.interactiveFg.active};\n  }\n\n  &:disabled,\n  &[aria-disabled='true'] {\n    pointer-events: none;\n    background-color: ${({ theme }) => theme.colors.interactiveBg.disable};\n    color: ${({ theme }) => theme.colors.fg.disable};\n  }\n\n  transition:\n    background-color ${BUTTON_TRANSITION_TIMING},\n    color ${BUTTON_TRANSITION_TIMING};\n`;\n\nconst anchorBase = css`\n  /* additional specifications for anchors are necessary for wordpress to override common css */\n  &:hover,\n  &:focus {\n    color: ${({ theme }) => theme.colors.interactiveFg.active};\n  }\n`;\n\nconst primaryColors = ({ theme }: WithTheme) => css`\n  background-color: ${theme.colors.interactiveBg.brandNormal};\n  color: ${theme.colors.interactiveFg.brandNormal};\n  &:active {\n    background-color: ${theme.colors.interactiveBg.active};\n    color: ${theme.colors.interactiveFg.active};\n  }\n\n  &:hover,\n  &:focus {\n    background-color: ${theme.colors.interactiveBg.brandHover};\n    /* important is necessary for wordpress to override common css for anchors*/\n    color: ${theme.colors.interactiveFg.brandHover} !important;\n  }\n`;\n\nconst secondaryColors = ({ theme }: WithTheme) => css`\n  background-color: ${theme.colors.interactiveBg.secondaryNormal};\n\n  &:hover,\n  &:focus {\n    background-color: ${theme.colors.interactiveBg.secondaryHover};\n  }\n\n  &:disabled {\n    &:hover,\n    &:focus {\n      background-color: ${theme.colors.interactiveBg.disable};\n    }\n  }\n`;\n\nconst tertiaryColors = ({ theme }: WithTheme) => css`\n  background-color: ${theme.colors.interactiveBg.tertiaryNormal};\n\n  &:hover,\n  &:focus {\n    background-color: ${theme.colors.interactiveBg.tertiaryHover};\n  }\n\n  &:disabled,\n  &[aria-disabled='true'] {\n    background-color: ${theme.colors.interactiveBg.tertiaryNormal};\n    &:hover,\n    &:focus {\n      background-color: ${theme.colors.interactiveBg.tertiaryNormal};\n    }\n  }\n`;\n\nconst quaternaryColors = ({ theme }: WithTheme) => css<ElementProps>`\n  background-color: ${theme.colors.interactiveBg.quaternaryNormal};\n  border: 1px solid ${theme.colors.border.defaultNormal};\n\n  &:hover {\n    border-color: ${theme.colors.border.quaternaryHover};\n  }\n\n  &:focus {\n    box-shadow: none;\n    border-color: ${theme.colors.border.quaternaryHover};\n  }\n\n  &:active {\n    border-color: ${theme.colors.border.quaternaryActive};\n    background-color: ${theme.colors.interactiveBg.quaternaryNormal};\n  }\n\n  ${themeHelpers.focusableOutlineCSS};\n\n  ${({ isToggled }) =>\n    isToggled &&\n    css`\n      border-color: ${theme.colors.border.defaultPress};\n    `}\n\n  &:disabled,\n  &[aria-disabled='true'] {\n    border-color: ${theme.colors.border.disable};\n    background-color: ${theme.colors.interactiveBg.quaternaryNormal};\n  }\n`;\n\nconst buttonColors = {\n  [ButtonType.Primary]: primaryColors,\n  [ButtonType.Secondary]: secondaryColors,\n  [ButtonType.Tertiary]: tertiaryColors,\n  [ButtonType.Quaternary]: quaternaryColors,\n  [ButtonType.Plain]: css``,\n} as const;\n\nconst rectangle = css<ElementProps>`\n  ${({ $type }) => $type && buttonColors[$type]};\n  min-height: 1em;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  padding: ${({ size }) =>\n    size === ButtonSize.Small ? '8px 16px' : '18px 32px'};\n`;\n\nconst square = css<ElementProps>`\n  ${({ $type }) => $type && buttonColors[$type]};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  ${({ size }) => css`\n    width: ${size === ButtonSize.Small\n      ? THEME_CONSTANTS.ICON_SIZE\n      : THEME_CONSTANTS.LARGE_BUTTON_SIZE}px;\n    height: ${size === ButtonSize.Small\n      ? THEME_CONSTANTS.ICON_SIZE\n      : THEME_CONSTANTS.LARGE_BUTTON_SIZE}px;\n  `}\n\n  svg {\n    width: ${THEME_CONSTANTS.ICON_SIZE}px;\n    height: ${THEME_CONSTANTS.ICON_SIZE}px;\n  }\n`;\n\nconst circle = css`\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n`;\n\nconst icon = css<ElementProps>`\n  ${({ $type }) => $type && buttonColors[$type]};\n  width: ${THEME_CONSTANTS.ICON_SIZE}px;\n  height: ${THEME_CONSTANTS.ICON_SIZE}px;\n  svg {\n    width: 100%;\n    height: 100%;\n  }\n`;\n\nfunction getTextSize(size: ButtonSize): TextSize.Medium | TextSize.Small {\n  switch (size) {\n    case ButtonSize.Small:\n      return TextSize.Small;\n    case ButtonSize.Medium:\n    default:\n      return TextSize.Medium;\n  }\n}\n\nconst link = css<ElementProps>`\n  ${({ theme, size }) => css`\n    ${themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.link[getTextSize(size)],\n      theme,\n    })};\n\n    color: ${theme.colors.fg.linkNormal};\n    border-radius: 0;\n\n    :hover {\n      color: ${theme.colors.fg.linkHover};\n    }\n    &:active,\n    &:disabled,\n    &[aria-disabled='true'] {\n      background-color: ${theme.colors.opacity.footprint};\n    }\n  `}\n`;\n\nconst ButtonRectangle = styled.button<ElementProps>`\n  ${base} ${rectangle}\n`;\nconst AnchorRectangle = styled.a<ElementProps>`\n  ${base} ${anchorBase} ${rectangle}\n`;\n\nconst ButtonSquare = styled.button<ElementProps>`\n  ${base} ${square}\n`;\nconst AnchorSquare = styled.a<ElementProps>`\n  ${base} ${anchorBase} ${square}\n`;\n\n// Note that circle extends square\nconst ButtonCircle = styled.button<ElementProps>`\n  ${base} ${square} ${circle}\n`;\nconst AnchorCircle = styled.a<ElementProps>`\n  ${base} ${anchorBase} ${square} ${circle}\n`;\n\nconst ButtonIcon = styled.button<ElementProps>`\n  ${base} ${icon}\n`;\nconst AnchorIcon = styled.a<ElementProps>`\n  ${base} ${anchorBase} ${icon}\n`;\n\nconst ButtonLink = styled.button<ElementProps>`\n  ${base} ${link}\n`;\nconst AnchorLink = styled.a<ElementProps>`\n  ${base} ${anchorBase} ${link}\n`;\n\ntype Props = PropsWithChildren<{\n  size?: ButtonSize;\n  type?: ButtonType;\n  variant?: ButtonVariant;\n  isToggled?: boolean;\n}>;\n\nconst Button = forwardRef(function Button(\n  {\n    size = ButtonSize.Medium,\n    type = ButtonType.Plain,\n    variant = ButtonVariant.Rectangle,\n    children,\n    ...rest\n  }: Props & Omit<ComponentPropsWithoutRef<'button'>, 'type'>,\n  ref: ForwardedRef<HTMLButtonElement>\n) {\n  const elementProps = { ref, size, $type: type, ...rest } as const;\n\n  switch (variant) {\n    case ButtonVariant.Rectangle:\n      return <ButtonRectangle {...elementProps}>{children}</ButtonRectangle>;\n    case ButtonVariant.Circle:\n      return <ButtonCircle {...elementProps}>{children}</ButtonCircle>;\n    case ButtonVariant.Square:\n      return <ButtonSquare {...elementProps}>{children}</ButtonSquare>;\n    case ButtonVariant.Icon:\n      return <ButtonIcon {...elementProps}>{children}</ButtonIcon>;\n    case ButtonVariant.Link:\n      return <ButtonLink {...elementProps}>{children}</ButtonLink>;\n    default:\n      return null;\n  }\n});\n\nconst ButtonAsLink = forwardRef(function ButtonAsLink(\n  {\n    size = ButtonSize.Medium,\n    type = ButtonType.Plain,\n    variant = ButtonVariant.Rectangle,\n    children,\n    ...rest\n  }: Props & ComponentPropsWithoutRef<'a'>,\n  ref: ForwardedRef<HTMLAnchorElement>\n) {\n  const elementProps = { ref, size, $type: type, ...rest } as const;\n\n  switch (variant) {\n    case ButtonVariant.Rectangle:\n      return <AnchorRectangle {...elementProps}>{children}</AnchorRectangle>;\n    case ButtonVariant.Circle:\n      return <AnchorCircle {...elementProps}>{children}</AnchorCircle>;\n    case ButtonVariant.Square:\n      return <AnchorSquare {...elementProps}>{children}</AnchorSquare>;\n    case ButtonVariant.Icon:\n      return <AnchorIcon {...elementProps}>{children}</AnchorIcon>;\n    case ButtonVariant.Link:\n      return <AnchorLink {...elementProps}>{children}</AnchorLink>;\n    default:\n      return null;\n  }\n});\n\nexport { Button, ButtonAsLink };\n"
  },
  {
    "path": "packages/design-system/src/components/button/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ButtonType {\n  Primary = 'primary',\n  Secondary = 'secondary',\n  Tertiary = 'tertiary',\n  Quaternary = 'quaternary',\n  Plain = 'plain',\n}\n\nexport enum ButtonSize {\n  Small = 'small',\n  Medium = 'medium',\n}\n\nexport enum ButtonVariant {\n  Circle = 'circle',\n  Rectangle = 'rectangle',\n  Square = 'square',\n  Icon = 'icon',\n  Link = 'link',\n}\n\nexport const BUTTON_TRANSITION_TIMING = '0.3s ease 0s';\n"
  },
  {
    "path": "packages/design-system/src/components/button/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './button';\nexport * from './constants';\nexport * from './toggleButton';\n"
  },
  {
    "path": "packages/design-system/src/components/button/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { Headline, Text } from '../../typography';\nimport { Cross } from '../../../icons';\nimport { Button, ButtonAsLink } from '../button';\nimport { ButtonSize, ButtonType, ButtonVariant } from '../constants';\nimport { ToggleButton, LockToggle } from '../toggleButton';\nimport { DarkThemeProvider } from '../../../storybookUtils/darkThemeProvider';\n\nexport default {\n  title: 'DesignSystem/Components/Button',\n  argTypes: {\n    type: {\n      options: Object.values(ButtonType),\n      control: 'select',\n    },\n    variant: {\n      options: Object.values(ButtonVariant),\n      control: 'select',\n    },\n    size: {\n      options: Object.values(ButtonSize),\n      control: 'radio',\n    },\n  },\n  args: {\n    type: ButtonType.Primary,\n    variant: ButtonVariant.Rectangle,\n    size: ButtonSize.Medium,\n  },\n};\n\nconst Container = styled.div`\n  background-color: ${(props) => props.theme.colors.bg.primary};\n  border: 1px solid ${(props) => props.theme.colors.fg.black};\n\n  display: flex;\n  flex-direction: column;\n  padding: 20px;\n`;\n\nconst Row = styled.div`\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  & > div {\n    width: 200px;\n    margin: 10px;\n    p {\n      padding-top: 10px;\n    }\n  }\n`;\n\nfunction ButtonContent({ variant }) {\n  return [ButtonVariant.Rectangle, ButtonVariant.Link].includes(variant) ? (\n    'Standard Button'\n  ) : (\n    <Cross />\n  );\n}\n\nButtonContent.propTypes = {\n  variant: PropTypes.oneOf(Object.values(ButtonVariant)),\n};\n\nconst ButtonCombosToDisplay = (args) => (\n  <Container>\n    <Headline as=\"h2\">{'Buttons by Variant, Size, and Type'}</Headline>\n    {Object.values(ButtonVariant).map((buttonVariant) => {\n      return Object.values(ButtonSize).map((buttonSize) => (\n        <Row key={`${buttonVariant}_${buttonSize}_row_storybook`}>\n          {Object.values(ButtonType).map((buttonType) => (\n            <div key={`${buttonVariant}_${buttonSize}_${buttonType}_storybook`}>\n              <Button\n                key={`${buttonVariant}_${buttonType}_storybook`}\n                variant={buttonVariant}\n                type={buttonType}\n                size={buttonSize}\n              >\n                <ButtonContent variant={buttonVariant} />\n              </Button>\n              <Text.Paragraph>\n                {`variant: ${buttonVariant}`} <br />\n                {`size: ${buttonSize}`} <br />\n                {`type: ${buttonType}`}\n              </Text.Paragraph>\n            </div>\n          ))}\n        </Row>\n      ));\n    })}\n    <Headline as=\"h3\" size={TextSize.Small}>\n      {'Button Demos'}\n    </Headline>\n    <Row>\n      <div>\n        <ButtonAsLink href=\"\" {...args}>\n          {'Link as Button'}\n        </ButtonAsLink>\n        <Text.Paragraph>{'Link as Button'}</Text.Paragraph>\n      </div>\n      <div>\n        <Button type={ButtonType.Primary}>\n          {'Just a really really long button to ensure edge cases!!!!!'}\n        </Button>\n        <Text.Paragraph>{'Edge case: really long'}</Text.Paragraph>\n      </div>\n      <div>\n        <Button type={ButtonType.Primary}>{'Text'}</Button>\n        <Text.Paragraph>{'Edge case: short'}</Text.Paragraph>\n      </div>\n      <div>\n        <Button disabled {...args}>\n          {'Text'}\n        </Button>\n        <Text.Paragraph>{'Disabled button'}</Text.Paragraph>\n      </div>\n    </Row>\n  </Container>\n);\n\nexport const DarkTheme = {\n  render: function Render(args) {\n    return (\n      <DarkThemeProvider>\n        <ButtonCombosToDisplay {...args} />\n      </DarkThemeProvider>\n    );\n  },\n};\n\nexport const LightTheme = {\n  render: function Render(args) {\n    return <ButtonCombosToDisplay {...args} />;\n  },\n};\n\nconst TOGGLE_VARIANTS = [ButtonVariant.Circle, ButtonVariant.Square];\nconst ToggleButtonContainer = ({ isToggled, swapToggled, type }) => (\n  <Container>\n    {Object.values(ButtonSize).map((buttonSize) => (\n      <Row key={`${buttonSize}_row_storybook`}>\n        {TOGGLE_VARIANTS.map((buttonVariant) => (\n          <div key={`${buttonVariant}_${buttonSize}_storybook`}>\n            <ToggleButton\n              key={`${buttonVariant}_storybook`}\n              variant={buttonVariant}\n              size={buttonSize}\n              isToggled={isToggled}\n              onClick={swapToggled}\n              type={type}\n            >\n              <ButtonContent variant={buttonVariant} />\n            </ToggleButton>\n            <Text.Paragraph>\n              {`variant: ${buttonVariant}`} <br />\n              {`size: ${buttonSize}`} <br />\n              {`is toggled: ${isToggled}`}\n              {type && (\n                <>\n                  <br />\n                  {`type: ${type}`}\n                </>\n              )}\n            </Text.Paragraph>\n          </div>\n        ))}\n      </Row>\n    ))}\n  </Container>\n);\n\nToggleButtonContainer.propTypes = {\n  isToggled: PropTypes.bool.isRequired,\n  swapToggled: PropTypes.func.isRequired,\n  type: PropTypes.oneOf(Object.values(ButtonType)),\n};\n\nexport const ToggleButtons = {\n  render: function Render() {\n    const [isToggled, setToggled] = useState(false);\n    const swapToggled = useCallback(() => setToggled((b) => !b), []);\n    return (\n      <>\n        <ToggleButtonContainer\n          isToggled={isToggled}\n          swapToggled={swapToggled}\n        />\n        <DarkThemeProvider>\n          <ToggleButtonContainer\n            isToggled={isToggled}\n            swapToggled={swapToggled}\n          />\n        </DarkThemeProvider>\n        <ToggleButtonContainer\n          isToggled={isToggled}\n          swapToggled={swapToggled}\n          type={ButtonType.Quaternary}\n        />\n        <DarkThemeProvider>\n          <ToggleButtonContainer\n            isToggled={isToggled}\n            swapToggled={swapToggled}\n            type={ButtonType.Quaternary}\n          />\n        </DarkThemeProvider>\n      </>\n    );\n  },\n\n  parameters: { controls: { include: [] } },\n};\n\nexport const PrebakedButtons = {\n  render: function Render(args) {\n    const [isLocked, setLocked] = useState(false);\n    const swapLocked = useCallback(() => setLocked((b) => !b), []);\n    return (\n      <>\n        <Container>\n          <Row>\n            <LockToggle isLocked={isLocked} onClick={swapLocked} {...args} />\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Row>\n              <LockToggle isLocked={isLocked} onClick={swapLocked} {...args} />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n\n  parameters: { controls: { include: [] } },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/button/test/button.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Button } from '..';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('Button', () => {\n  const buttonText = 'Some button text';\n  const onClickMock = jest.fn();\n\n  it('should render the default non cta button', () => {\n    renderWithProviders(<Button onClick={onClickMock}>{buttonText}</Button>);\n\n    expect(screen.getByText(buttonText)).toBeInTheDocument();\n  });\n\n  it('should not allow onClick action when <Button /> is disabled', () => {\n    renderWithProviders(\n      <Button disabled onClick={onClickMock}>\n        {buttonText}\n      </Button>\n    );\n\n    const button = screen.getByText(buttonText);\n    fireEvent.click(button);\n\n    expect(onClickMock).toHaveBeenCalledTimes(0);\n  });\n\n  it('should simulate a click on <Button />', () => {\n    renderWithProviders(<Button onClick={onClickMock}>{buttonText}</Button>);\n\n    const button = screen.getByText(buttonText);\n\n    fireEvent.click(button);\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/button/toggleButton.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { LockOpen, LockClosed } from '../../icons';\nimport { ButtonType, ButtonVariant, ButtonSize } from './constants';\nimport { Button } from './button';\n\ninterface ToggleProps extends Omit<\n  ComponentPropsWithoutRef<typeof Button>,\n  'type'\n> {\n  type?: ButtonType;\n  isToggled?: boolean;\n}\n\nfunction ToggleButton({ isToggled = false, type, ...rest }: ToggleProps) {\n  // if type is set to quaternary, use that, otherwise use secondary or tertiary based on state\n  const actualType =\n    type === ButtonType.Quaternary\n      ? type\n      : isToggled\n        ? ButtonType.Secondary\n        : ButtonType.Tertiary;\n  return (\n    <Button\n      {...rest}\n      type={actualType}\n      aria-pressed={isToggled}\n      isToggled={isToggled}\n    />\n  );\n}\n\ninterface LockProps extends ComponentPropsWithoutRef<'button'> {\n  isLocked?: boolean;\n}\n\nfunction LockToggle({ isLocked = false, ...rest }: LockProps) {\n  return (\n    <Button\n      {...rest}\n      aria-pressed={isLocked}\n      type={ButtonType.Tertiary}\n      size={ButtonSize.Small}\n      variant={ButtonVariant.Square}\n    >\n      {isLocked ? <LockClosed /> : <LockOpen />}\n    </Button>\n  );\n}\n\nexport { ToggleButton, LockToggle };\n"
  },
  {
    "path": "packages/design-system/src/components/checkbox/checkbox.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { forwardRef } from '@googleforcreators/react';\nimport type { ComponentPropsWithoutRef, ForwardedRef } from 'react';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Checkmark } from '../../icons';\nimport { focusCSS } from '../../theme/helpers';\n\nconst CONTAINER_WIDTH = 24;\nconst BORDER_WIDTH = 1;\n\nconst Border = styled.div(\n  ({ theme }) => css`\n    position: absolute;\n    height: ${CONTAINER_WIDTH}px;\n    width: ${CONTAINER_WIDTH}px;\n    border-radius: ${theme.borders.radius.small};\n    border: ${BORDER_WIDTH}px solid ${theme.colors.border.defaultNormal};\n    pointer-events: none;\n  `\n);\n\nconst StyledCheckmark = styled(Checkmark).attrs({ role: 'img' })`\n  height: auto;\n  width: 32px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst CheckboxContainer = styled.div(\n  ({ theme }) => css`\n    position: relative;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    height: ${CONTAINER_WIDTH}px;\n    width: ${CONTAINER_WIDTH}px;\n    min-height: ${CONTAINER_WIDTH}px;\n    min-width: ${CONTAINER_WIDTH}px;\n\n    /* Hide Checkbox */\n    input[type='checkbox'] {\n      position: absolute;\n      width: ${CONTAINER_WIDTH + BORDER_WIDTH}px;\n      height: ${CONTAINER_WIDTH + BORDER_WIDTH}px;\n      margin: 0;\n      padding: 0;\n      opacity: 0;\n      cursor: pointer;\n\n      :disabled {\n        ~ ${Border} {\n          border-color: ${theme.colors.border.disable};\n        }\n\n        ~ ${StyledCheckmark} {\n          color: ${theme.colors.fg.disable};\n        }\n      }\n\n      &:focus-visible:not(:active) ~ ${Border} {\n        ${focusCSS(theme.colors.border.focus)};\n      }\n\n      :active ~ ${Border} {\n        border-color: ${theme.colors.border.defaultNormal};\n        box-shadow: 0 0 0 8px ${theme.colors.shadow.active};\n      }\n    }\n  `\n);\n\ntype CheckboxProps = ComponentPropsWithoutRef<'input'>;\n\nconst Checkbox = forwardRef(\n  (\n    { checked, disabled, className = '', ...props }: CheckboxProps,\n    ref: ForwardedRef<HTMLInputElement>\n  ) => (\n    <CheckboxContainer className={className}>\n      <input\n        type=\"checkbox\"\n        ref={ref}\n        checked={Boolean(checked)}\n        disabled={disabled}\n        aria-checked={checked}\n        {...props}\n      />\n      {checked && <StyledCheckmark aria-label={__('Checked', 'web-stories')} />}\n      <Border />\n    </CheckboxContainer>\n  )\n);\n\nexport default Checkbox;\n"
  },
  {
    "path": "packages/design-system/src/components/checkbox/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Checkbox } from './checkbox';\n"
  },
  {
    "path": "packages/design-system/src/components/checkbox/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Checkbox } from '..';\nimport { Text } from '../../typography';\nimport { DarkThemeProvider } from '../../../storybookUtils';\n\nexport default {\n  title: 'DesignSystem/Components/Checkbox',\n  component: Checkbox,\n  args: {\n    checkboxLabel1: 'Normal',\n    checkboxLabel2: 'Disabled',\n    checkboxLabel3: 'Checked',\n    checkboxLabel4: 'Checked and Disabled',\n  },\n  argTypes: {\n    checkboxLabel1: { name: 'Label 1' },\n    checkboxLabel2: { name: 'Label 2' },\n    checkboxLabel3: { name: 'Label 3' },\n    checkboxLabel4: { name: 'Label 4' },\n    handleChange: { action: 'checkbox changed' },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  max-width: 500px;\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  grid-column: 1 / -1;\n  grid-row-gap: 16px;\n\n  > div {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    grid-column: 1 / -1;\n    vertical-align: middle;\n  }\n\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const [formState, setFormState] = useState({\n      one: false,\n      two: true,\n      three: false,\n      four: true,\n      disabledOne: false,\n      disabledTwo: true,\n      disabledThree: false,\n      disabledFour: true,\n    });\n\n    const handleChange = (event) => {\n      const name = event.target.name;\n      const value = event.target.checked;\n\n      args.handleChange(event.target.name, event);\n      setFormState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Container>\n          <Row>\n            <div>\n              <label htmlFor=\"one\">\n                <Text.Span>{args.checkboxLabel1}</Text.Span>\n              </label>\n              <Checkbox\n                id=\"one\"\n                name=\"one\"\n                checked={formState.one}\n                onChange={handleChange}\n              />\n            </div>\n            <div>\n              <label htmlFor=\"disabledOne\">\n                <Text.Span>{args.checkboxLabel2}</Text.Span>\n              </label>\n              <Checkbox\n                id=\"disabledOne\"\n                name=\"disabledOne\"\n                checked={formState.disabledOne}\n                onChange={handleChange}\n                disabled\n              />\n            </div>\n          </Row>\n          <Row>\n            <div>\n              <label htmlFor=\"two\">\n                <Text.Span>{args.checkboxLabel3}</Text.Span>\n              </label>\n              <Checkbox\n                id=\"two\"\n                name=\"two\"\n                checked={formState.two}\n                onChange={handleChange}\n              />\n            </div>\n            <div>\n              <label htmlFor=\"disabledTwo\">\n                <Text.Span>{args.checkboxLabel4}</Text.Span>\n              </label>\n              <Checkbox\n                id=\"disabledTwo\"\n                name=\"disabledTwo\"\n                checked={formState.disabledTwo}\n                onChange={handleChange}\n                disabled\n              />\n            </div>\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container darkMode>\n            <Row>\n              <div>\n                <label htmlFor=\"three\">\n                  <Text.Span>{args.checkboxLabel1}</Text.Span>\n                </label>\n                <Checkbox\n                  id=\"three\"\n                  name=\"three\"\n                  checked={formState.three}\n                  onChange={handleChange}\n                />\n              </div>\n              <div>\n                <label htmlFor=\"disabledThree\">\n                  <Text.Span>{args.checkboxLabel2}</Text.Span>\n                </label>\n                <Checkbox\n                  id=\"disabledThree\"\n                  name=\"disabledThree\"\n                  checked={formState.disabledThree}\n                  onChange={handleChange}\n                  disabled\n                />\n              </div>\n            </Row>\n            <Row>\n              <div>\n                <label htmlFor=\"four\">\n                  <Text.Span>{args.checkboxLabel3}</Text.Span>\n                </label>\n                <Checkbox\n                  id=\"four\"\n                  name=\"four\"\n                  checked={formState.four}\n                  onChange={handleChange}\n                />\n              </div>\n              <div>\n                <label htmlFor=\"disabledFour\">\n                  <Text.Span>{args.checkboxLabel4}</Text.Span>\n                </label>\n                <Checkbox\n                  id=\"disabledFour\"\n                  name=\"disabledFour\"\n                  checked={formState.disabledFour}\n                  onChange={handleChange}\n                  disabled\n                />\n              </div>\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/checkbox/test/checkbox.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Checkbox from '../checkbox';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { noop } from '../../../utils';\n\ndescribe('Checkbox', () => {\n  it('should render the checkbox', () => {\n    renderWithProviders(<Checkbox onChange={noop} />);\n\n    expect(screen.getByRole('checkbox')).toBeInTheDocument();\n  });\n\n  it('should render the checkmark if the checkbox is checked', () => {\n    renderWithProviders(<Checkbox onChange={noop} checked />);\n\n    expect(screen.getByRole('img', { name: 'Checked' })).toBeInTheDocument();\n  });\n\n  it('should not render the checkmark if the checkbox is not checked', () => {\n    renderWithProviders(<Checkbox onChange={noop} />);\n\n    expect(\n      screen.queryByRole('img', { name: 'Checked' })\n    ).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/chip/chip.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n  PropsWithChildren,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../theme';\nimport type { Theme } from '../../theme';\nimport { focusableOutlineCSS } from '../../theme/helpers';\n\nconst getChipBackgroundColor = ({\n  theme,\n  active,\n  disabled,\n}: {\n  theme: Theme;\n  active?: boolean;\n  disabled?: boolean;\n}) =>\n  active && !disabled\n    ? theme.colors.interactiveBg.secondaryNormal\n    : 'transparent';\n\nconst Infix = styled.div<{ before?: boolean }>`\n  display: inline-block;\n  margin-right: ${({ before = false }) => (before ? '-8px' : '4px')};\n  margin-left: ${({ before = false }) => (before ? '4px' : '-8px')};\n  height: 28px;\n`;\n\nconst StyledChip = styled.span`\n  padding: 0 12px;\n  background: transparent;\n  border: none;\n  &:focus {\n    outline: none;\n  }\n`;\n\nconst ChipContainer = styled.button<{ active?: boolean; disabled?: boolean }>(\n  ({ theme, disabled }) => css`\n    display: inline-flex;\n    justify-content: center;\n    align-items: center;\n    height: 36px;\n    padding: 0;\n    background-color: ${getChipBackgroundColor};\n    border: 1px solid\n      ${disabled\n        ? theme.colors.border.disable\n        : theme.colors.interactiveBg.secondaryNormal};\n    border-radius: ${theme.borders.radius.x_large};\n    transition: all 0.3s ease-in-out;\n    transition-property:\n      background-color, border-color, height, width, transform;\n    cursor: ${disabled ? 'default' : 'pointer'};\n    ${focusableOutlineCSS}\n    :active {\n      background-color: ${getChipBackgroundColor({\n        theme,\n        active: true,\n        disabled,\n      })};\n    }\n    :hover:not(:active) {\n      border-color: ${disabled\n        ? theme.colors.border.disable\n        : theme.colors.border.defaultHover};\n    }\n\n    ${Infix}, ${StyledChip} {\n      white-space: nowrap;\n      cursor: ${disabled ? 'default' : 'pointer'};\n      color: ${disabled ? theme.colors.fg.disable : theme.colors.fg.primary};\n      ${themeHelpers.expandPresetStyles({\n        preset: theme.typography.presets.paragraph[TextSize.Small],\n        theme,\n      })};\n    }\n  `\n);\n\ninterface ChipProps extends ComponentPropsWithoutRef<'button'> {\n  prefix?: string;\n  suffix?: string;\n  active?: boolean;\n}\n\nconst Chip = forwardRef(\n  (\n    { children, prefix, suffix, ...props }: PropsWithChildren<ChipProps>,\n    ref: ForwardedRef<HTMLButtonElement>\n  ) => {\n    return (\n      <ChipContainer ref={ref} {...props}>\n        {prefix && <Infix before>{prefix}</Infix>}\n        <StyledChip>{children}</StyledChip>\n        {suffix && <Infix>{suffix}</Infix>}\n      </ChipContainer>\n    );\n  }\n);\n\nChip.displayName = 'Chip';\n\nexport default Chip;\n"
  },
  {
    "path": "packages/design-system/src/components/chip/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Chip } from './chip';\n"
  },
  {
    "path": "packages/design-system/src/components/chip/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { ThemeProvider } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Chip } from '..';\nimport { Checkmark, LetterIOutline } from '../../../icons';\nimport { theme } from '../../../theme';\n\nexport default {\n  title: 'DesignSystem/Components/Chip',\n  component: Chip,\n  argTypes: {\n    onClick: { action: 'clicked' },\n  },\n};\n\nconst Container = styled.div`\n  background-color: ${(props) => props.theme.colors.bg.primary};\n  padding: 30px;\n  display: flex;\n  gap: 20px;\n`;\n\nconst CHIP_STATES = [\n  { name: 'Normal' },\n  { name: 'Active', active: true },\n  { name: 'Disabled', disabled: true },\n  { name: 'with Suffix', suffix: <Checkmark height={28} width={28} /> },\n  {\n    name: 'with Prefix',\n    prefix: <LetterIOutline height={28} width={28} />,\n    active: true,\n  },\n  {\n    name: 'Suffix & Prefix',\n    prefix: <LetterIOutline height={28} width={28} />,\n    suffix: <Checkmark height={28} width={28} />,\n    disabled: true,\n  },\n];\n\nexport const _default = {\n  render: function Render(args) {\n    const chips = CHIP_STATES.map(({ name, ...state }) => (\n      <Chip key={name} onClick={() => args.onClick(name)} {...state}>\n        {name}\n      </Chip>\n    ));\n    return (\n      <>\n        <Container>{chips}</Container>\n        <ThemeProvider theme={theme}>\n          <Container>{chips}</Container>\n        </ThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/chip/test/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Chip from '../chip';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('Chip', () => {\n  const chipText = 'Some chip text';\n  const onClick = jest.fn();\n\n  beforeEach(() => jest.clearAllMocks());\n\n  it('should render a default button as a chip', () => {\n    renderWithProviders(<Chip>{chipText}</Chip>);\n    expect(screen.getByRole('button')).toHaveTextContent(chipText);\n  });\n\n  it('should render the prefix components', () => {\n    renderWithProviders(\n      <Chip prefix={<div data-testid=\"test-prefix\" />}>{chipText}</Chip>\n    );\n    expect(screen.getByTestId('test-prefix')).toBeInTheDocument();\n  });\n\n  it('should render the suffix components', () => {\n    renderWithProviders(\n      <Chip prefix={<div data-testid=\"test-suffix\" />}>{chipText}</Chip>\n    );\n    expect(screen.getByTestId('test-suffix')).toBeInTheDocument();\n  });\n\n  it('should simulate a click on <Chip />', () => {\n    renderWithProviders(<Chip onClick={onClick}>{chipText}</Chip>);\n    const chip = screen.getByText(chipText);\n    fireEvent.click(chip);\n    expect(onClick).toHaveBeenCalledOnce();\n  });\n\n  it('should not trigger a click on <Chip /> when disabled', () => {\n    renderWithProviders(\n      <Chip disabled onClick={onClick}>\n        {chipText}\n      </Chip>\n    );\n    const chip = screen.getByText(chipText);\n    fireEvent.click(chip);\n    expect(onClick).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/circularProgress/circular.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { keyframes } from 'styled-components';\nimport { CSSTransition } from 'react-transition-group';\nimport { useRef } from '@googleforcreators/react';\n\nconst wrapperRotation = keyframes`\n  100% { transform: rotate(360deg) }\n`;\n\nconst circleRotation = keyframes`\n  0% {\n    stroke-dasharray: 1, 200;\n    stroke-dashoffset: 0;\n  }\n  50% {\n    stroke-dasharray: 100, 200;\n    stroke-dashoffset: -15;\n  }\n  100% {\n    stroke-dasharray: 100, 200;\n    stroke-dashoffset: -125;\n  }\n`;\n\nconst Wrapper = styled.div.attrs({\n  role: 'progressbar',\n})<{ size: number }>`\n  width: ${({ size }) => `${size}px`};\n  height: ${({ size }) => `${size}px`};\n  animation: ${wrapperRotation} 1.4s linear infinite;\n`;\n\nconst StyledSpinner = styled.svg`\n  display: block;\n`;\n\nconst StyledCircle = styled.circle`\n  animation: ${circleRotation} 1.4s ease-in-out infinite;\n  stroke: ${({ theme }) => `${theme.colors.accent.secondary}`};\n`;\n\nfunction CircularProgress({\n  size = 24,\n  thickness = 2,\n}: {\n  size?: number;\n  thickness?: number;\n}) {\n  const nodeRef = useRef<HTMLDivElement>(null);\n\n  return (\n    <CSSTransition nodeRef={nodeRef} in appear timeout={0}>\n      <Wrapper ref={nodeRef} size={size}>\n        <StyledSpinner viewBox={`${size / 2} ${size / 2} ${size} ${size}`}>\n          <StyledCircle\n            cx={size}\n            cy={size}\n            r={(size - thickness) / 2}\n            fill=\"none\"\n            strokeWidth={thickness}\n            stroke=\"currentColor\"\n          />\n        </StyledSpinner>\n      </Wrapper>\n    </CSSTransition>\n  );\n}\n\nexport default CircularProgress;\n"
  },
  {
    "path": "packages/design-system/src/components/circularProgress/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as CircularProgress } from './circular';\n"
  },
  {
    "path": "packages/design-system/src/components/circularProgress/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport CircularProgress from '../circular';\n\nexport default {\n  title: 'Stories Editor/Components/Circular Progress',\n  component: CircularProgress,\n  args: {\n    size: 24,\n    thickness: 2,\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const size = args.size;\n    const thickness = args.thickness;\n\n    return <CircularProgress size={size} thickness={thickness} />;\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/animationContainer.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport type { ComponentPropsWithoutRef, PropsWithChildren } from 'react';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { BEZIER } from '../../theme/constants';\nimport {\n  CORNER_DIRECTIONS,\n  Direction,\n  type CornerDirection,\n} from '../../utils/directions';\nimport { Popover, Shadow } from './styled';\n\nconst PERCENTAGE_OFFSET = {\n  [Direction.Top]: 100,\n  [Direction.Right]: 0,\n  [Direction.Bottom]: -100,\n  [Direction.Left]: -50,\n};\n\nconst animationTimeSeconds = 0.175;\nconst transition = `transform ${animationTimeSeconds}s ${BEZIER.default}`;\nconst initialScale = 0.5;\nconst fullSize = css`\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n`;\n\nconst MenuWrapper = styled.div`\n  position: absolute;\n`;\n\nconst MenuRevealer = styled.div<{\n  animationFinished?: boolean;\n}>`\n  overflow: ${({ animationFinished }) =>\n    animationFinished ? 'normal' : 'hidden'};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${fullSize}\n`;\n\nconst MenuCounterRevealer = styled.div`\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n`;\n\nconst ButtonInner = styled(Popover)<{\n  align: keyof typeof CORNER_DIRECTIONS | null;\n  isReady?: boolean;\n}>`\n  ${fullSize}\n  ${({ isInline }) => isInline && `position: relative`};\n  transform: ${({ align }) => {\n    switch (align) {\n      case CORNER_DIRECTIONS.top_left:\n        return `translate(${PERCENTAGE_OFFSET[Direction.Left]}%, ${\n          PERCENTAGE_OFFSET[Direction.Top]\n        }%)`;\n      case CORNER_DIRECTIONS.top_right:\n        return `translate(${PERCENTAGE_OFFSET[Direction.Right]}%, ${\n          PERCENTAGE_OFFSET[Direction.Top]\n        }%)`;\n      case CORNER_DIRECTIONS.bottom_right:\n        return `translate(${PERCENTAGE_OFFSET[Direction.Right]}%, ${\n          PERCENTAGE_OFFSET[Direction.Bottom]\n        }%)`;\n      case CORNER_DIRECTIONS.bottom_left:\n      default:\n        return `translate(${PERCENTAGE_OFFSET[Direction.Left]}%, ${\n          PERCENTAGE_OFFSET[Direction.Bottom]\n        }%)`;\n    }\n  }};\n\n  ${MenuWrapper} {\n    ${(props) => {\n      switch (props.align) {\n        case CORNER_DIRECTIONS.top_right:\n          return css`\n            top: 0;\n            right: 0;\n          `;\n        case CORNER_DIRECTIONS.top_left:\n          return css`\n            top: 0;\n            left: 0;\n          `;\n        case CORNER_DIRECTIONS.bottom_right:\n          return css`\n            right: 0;\n            bottom: 0;\n          `;\n        case CORNER_DIRECTIONS.bottom_left:\n        default:\n          return css`\n            left: 0;\n            bottom: 0;\n          `;\n      }\n    }}\n  }\n\n  ${MenuRevealer} {\n    transition: ${(props) => (props.isReady ? transition : 'none')};\n    ${(props) => {\n      const translateFromScale = 100 * (1 - initialScale);\n      switch (props.align) {\n        case CORNER_DIRECTIONS.top_right:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(${translateFromScale}%, -${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.top_left:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(-${translateFromScale}%, -${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.bottom_right:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(${translateFromScale}%, ${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.bottom_left:\n        default:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(-${translateFromScale}%, ${translateFromScale}%)`};\n          `;\n      }\n    }}\n  }\n\n  ${MenuCounterRevealer} {\n    transition: ${(props) => (props.isReady ? transition : 'none')};\n    ${(props) => {\n      const translateFromScale = 100 * (1 - initialScale);\n      switch (props.align) {\n        case CORNER_DIRECTIONS.top_right:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(-${translateFromScale}%, ${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.top_left:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(${translateFromScale}%, ${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.bottom_right:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(-${translateFromScale}%, -${translateFromScale}%)`};\n          `;\n        case CORNER_DIRECTIONS.bottom_left:\n        default:\n          return css`\n            transform: ${props.isReady\n              ? 'none'\n              : `translate(${translateFromScale}%, -${translateFromScale}%)`};\n          `;\n      }\n    }}\n  }\n\n  ${Shadow} {\n    transition: ${(props) => (props.isReady ? transition : 'none')};\n    transform: ${(props) =>\n      props.isReady ? 'none' : `scale(${initialScale})`};\n    transform-origin: ${(props) => {\n      switch (props.align) {\n        case CORNER_DIRECTIONS.top_right:\n          return 'right top';\n        case CORNER_DIRECTIONS.top_left:\n          return 'left top';\n        case CORNER_DIRECTIONS.bottom_right:\n          return 'right bottom';\n        case CORNER_DIRECTIONS.bottom_left:\n        default:\n          return 'left bottom';\n      }\n    }};\n  }\n`;\n\nexport interface AnimationContainerProps extends ComponentPropsWithoutRef<\n  typeof ButtonInner\n> {\n  isOpen?: boolean;\n}\n\nfunction AnimationContainer({\n  children,\n  isOpen,\n  ...props\n}: PropsWithChildren<AnimationContainerProps>) {\n  const [align, setAlign] = useState<keyof typeof CORNER_DIRECTIONS | null>(\n    null\n  );\n  const [isReady, setIsReady] = useState(false);\n  const [animationFinished, setAnimationFinished] = useState(true);\n  const menuPositionRef = useRef<HTMLDivElement | null>(null);\n  const menuTogglePositionRef = useRef<HTMLDivElement | null>(null);\n\n  useLayoutEffect(() => {\n    if (!isOpen) {\n      setAlign(null);\n      return;\n    }\n    if (!(menuTogglePositionRef.current && menuPositionRef.current)) {\n      return;\n    }\n\n    const toggleBoundingBox =\n      menuTogglePositionRef.current.getBoundingClientRect();\n    const menuWrapperBoundingBox =\n      menuPositionRef.current.getBoundingClientRect();\n\n    const menuLeft =\n      toggleBoundingBox.left +\n      toggleBoundingBox.width * (PERCENTAGE_OFFSET[Direction.Left] / 100);\n    const menuBottom =\n      toggleBoundingBox.bottom +\n      toggleBoundingBox.height * (PERCENTAGE_OFFSET[Direction.Bottom] / 100);\n\n    const alignHorizontal =\n      menuLeft + menuWrapperBoundingBox.width > window.innerWidth\n        ? Direction.Right\n        : Direction.Left;\n    const alignVertical =\n      0 > menuBottom - menuWrapperBoundingBox.height\n        ? Direction.Top\n        : Direction.Bottom;\n\n    setAlign(\n      CORNER_DIRECTIONS[\n        `${alignVertical}_${alignHorizontal}`\n      ] as CornerDirection\n    );\n  }, [isOpen]);\n\n  useEffect(() => {\n    // some styles depend on the animation being finished. Set a timeout to set this variable\n    // once the animation has finished.\n    if (!isOpen) {\n      return undefined;\n    }\n    setAnimationFinished(false);\n    const timeoutId = setTimeout(\n      () => setAnimationFinished(true),\n      animationTimeSeconds * 1000\n    );\n    return () => clearTimeout(timeoutId);\n  }, [isOpen]);\n\n  /**\n   * Seems funky, but we need 1 full render where the proper\n   * alignment is set before we animate in. This prevents react\n   * from batching those renders and animating from wrong alignment.\n   */\n  useEffect(() => {\n    const frameId = requestAnimationFrame(() => setIsReady(Boolean(align)));\n\n    return () => cancelAnimationFrame(frameId);\n  }, [align]);\n\n  return (\n    <ButtonInner\n      align={align}\n      isOpen={isOpen}\n      isReady={isReady}\n      ref={menuTogglePositionRef}\n      {...props}\n    >\n      <MenuWrapper>\n        <MenuRevealer animationFinished={isOpen && animationFinished}>\n          <MenuCounterRevealer ref={menuPositionRef}>\n            {children}\n          </MenuCounterRevealer>\n        </MenuRevealer>\n        <Shadow />\n      </MenuWrapper>\n    </ButtonInner>\n  );\n}\n\nexport default AnimationContainer;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/button.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useMemo, forwardRef } from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  FocusEvent,\n  ForwardedRef,\n  MouseEvent,\n  SyntheticEvent,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport { Button as BaseButton } from '../../button';\nimport { useContextMenu } from '../contextMenuProvider';\nimport { menuItemStyles } from './styles';\n\nconst StyledButton = styled(BaseButton)<{\n  isHorizontal?: boolean;\n  isIconMenu?: boolean;\n  forcePadding?: boolean;\n}>`\n  ${menuItemStyles};\n\n  width: auto;\n\n  ${({ isHorizontal, isIconMenu, forcePadding, theme }) => {\n    const hasHeight = isHorizontal; // In a horizontal menu, all buttons are 32px high\n    const hasNoPadding = !forcePadding && (isHorizontal || isIconMenu);\n    const hasBorderRadius = isHorizontal || isIconMenu;\n    return {\n      height: hasHeight ? '32px' : undefined,\n      padding: hasNoPadding ? 0 : undefined,\n      borderRadius: hasBorderRadius ? theme.borders.radius.small : 0,\n    };\n  }}\n\n  :disabled {\n    background-color: transparent;\n\n    span {\n      color: ${({ theme }) => theme.colors.fg.disable};\n    }\n  }\n\n  :hover:not(:disabled) {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryHover};\n  }\n\n  :active:not(:disabled) {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryPress};\n  }\n`;\n\nexport interface MenuButtonProps extends ComponentPropsWithoutRef<\n  typeof StyledButton\n> {\n  id?: string;\n  onClick: (evt: SyntheticEvent<HTMLButtonElement>) => void;\n  onBlur?: (evt: SyntheticEvent<HTMLButtonElement>) => void;\n  onFocus?: (evt: SyntheticEvent<HTMLButtonElement>) => void;\n  forcePadding?: boolean;\n  dismissOnClick?: boolean;\n}\n\n/**\n * A styled button for use in the context menu.\n */\nconst Button = forwardRef(function Button(\n  {\n    id,\n    onBlur,\n    onClick,\n    onFocus,\n    forcePadding = false,\n    dismissOnClick = true,\n    ...props\n  }: MenuButtonProps,\n  ref: ForwardedRef<HTMLButtonElement>\n) {\n  const {\n    focusedId,\n    isIconMenu,\n    isHorizontal,\n    onDismiss,\n    onMenuItemBlur,\n    onMenuItemFocus,\n  } = useContextMenu(({ state, actions }) => ({\n    focusedId: state.focusedId,\n    isIconMenu: state.isIconMenu,\n    isHorizontal: state.isHorizontal,\n    onDismiss: actions.onDismiss,\n    onMenuItemBlur: actions.onMenuItemBlur,\n    onMenuItemFocus: actions.onMenuItemFocus,\n  }));\n  const autoGeneratedId = useMemo(() => uuidv4(), []);\n  const elementId = id || autoGeneratedId;\n\n  const handleBlur = (evt: FocusEvent<HTMLButtonElement>) => {\n    onMenuItemBlur();\n    onBlur?.(evt);\n  };\n\n  const handleClick = (evt: MouseEvent<HTMLButtonElement>) => {\n    onClick(evt);\n    if (dismissOnClick) {\n      onDismiss(evt.nativeEvent);\n    }\n  };\n\n  const handleFocus = (evt: FocusEvent<HTMLButtonElement>) => {\n    onMenuItemFocus(elementId);\n    onFocus?.(evt);\n  };\n\n  return (\n    <StyledButton\n      ref={ref}\n      id={elementId}\n      tabIndex={focusedId === elementId ? 0 : -1}\n      role=\"menuitem\"\n      isIconMenu={isIconMenu}\n      isHorizontal={isHorizontal}\n      forcePadding={forcePadding}\n      onBlur={handleBlur}\n      onClick={handleClick}\n      onFocus={handleFocus}\n      {...props}\n    />\n  );\n});\n\nexport default Button;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/group.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\n\nexport interface MenuGroupProps extends ComponentPropsWithoutRef<'div'> {\n  label: string;\n}\n\n/**\n * A wrapping div with `role=\"group\"` for use in the context menu.\n */\nfunction Group({ label, ...props }: MenuGroupProps) {\n  return <div role=\"group\" aria-label={label} {...props} />;\n}\n\nexport default Group;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/icon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef, PropsWithChildren } from 'react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { VisuallyHidden } from '../../visuallyHidden';\n\nconst IconWrapper = styled.div`\n  width: 32px;\n  height: 32px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  > * {\n    flex: 1;\n  }\n`;\n\nexport interface MenuIconProps extends ComponentPropsWithoutRef<'div'> {\n  title: string;\n}\n/**\n * A styled icon for use in the context menu. To be used within\n * the styled Button for the context menu.\n */\nfunction Icon({\n  children,\n  title,\n  className = '',\n  ...props\n}: PropsWithChildren<MenuIconProps>) {\n  return (\n    <>\n      <VisuallyHidden>{title}</VisuallyHidden>\n      <IconWrapper className={className} {...props}>\n        {children}\n      </IconWrapper>\n    </>\n  );\n}\n\nexport default Icon;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as MenuButton } from './button';\nexport { default as MenuGroup } from './group';\nexport { default as MenuIcon } from './icon';\nexport { default as MenuItem } from './item';\nexport { default as MenuItemSuffix } from './suffix';\nexport { default as MenuLabel } from './label';\nexport { default as MenuLink } from './link';\nexport { default as MenuSeparator } from './separator';\nexport { default as MenuShortcut } from './shortcut';\nexport { default as SubMenuTrigger } from './subMenuTrigger';\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/item.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { forwardRef } from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n  ReactNode,\n  VoidFunctionComponent,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport Button from './button';\nimport Shortcut from './shortcut';\nimport Suffix from './suffix';\n\nconst StyledButton = styled(Button)<{ supportsIcon?: boolean }>`\n  ${({ supportsIcon }) =>\n    supportsIcon &&\n    `\n    svg {\n      width: 32px;\n      position: absolute;\n      margin-left: -12px;\n    }\n    span {\n      padding-left: 18px;\n      font-size: 12px;\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n    }\n  `}\n`;\n\nexport interface MenuItemProps extends ComponentPropsWithoutRef<\n  typeof StyledButton\n> {\n  label: ReactNode;\n  shortcut?: { display: string };\n  icon?: ReactNode;\n  SuffixIcon?: VoidFunctionComponent;\n  className?: string;\n}\n\nconst MenuItem = forwardRef(function MenuItem(\n  {\n    label,\n    shortcut,\n    icon,\n    SuffixIcon,\n    className,\n    ...buttonProps\n  }: MenuItemProps,\n  ref: ForwardedRef<HTMLButtonElement>\n) {\n  return (\n    <StyledButton className={className} ref={ref} {...buttonProps}>\n      {icon}\n      {label}\n      {shortcut && <Shortcut>{shortcut.display}</Shortcut>}\n      {SuffixIcon && (\n        <Suffix>\n          <SuffixIcon />\n        </Suffix>\n      )}\n    </StyledButton>\n  );\n});\n\nexport default MenuItem;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/label.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { menuItemStyles } from './styles';\n\nconst Label = styled.div`\n  ${menuItemStyles};\n`;\n\nexport default Label;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/link.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useMemo } from '@googleforcreators/react';\nimport type { ComponentPropsWithoutRef, SyntheticEvent } from 'react';\n/**\n * Internal dependencies\n */\nimport { Link as BaseLink } from '../../typography/link';\nimport { useContextMenu } from '../contextMenuProvider';\nimport { menuItemStyles } from './styles';\n\nconst StyledLink = styled(BaseLink)`\n  ${menuItemStyles};\n\n  background-color: transparent;\n  text-decoration: none;\n\n  :active,\n  :hover,\n  :focus,\n  :active *,\n  :hover *,\n  :focus * {\n    /* Override the override to WordPress's common css */\n    color: ${({ theme }) => theme.colors.fg.primary} !important;\n  }\n\n  :hover {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryHover};\n  }\n\n  :active {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryPress};\n  }\n`;\n\nexport interface MenuLinkProps extends ComponentPropsWithoutRef<\n  typeof StyledLink\n> {\n  id?: string;\n  href: string;\n  onClick?: (evt: SyntheticEvent<HTMLElement>) => void;\n  onBlur?: (evt: SyntheticEvent<HTMLElement>) => void;\n  onFocus?: (evt: SyntheticEvent<HTMLElement>) => void;\n  openNewTab?: boolean;\n}\n\n/**\n * A styled link for use in the context menu.\n */\nfunction Link({\n  id,\n  onBlur,\n  onClick,\n  onFocus,\n  openNewTab,\n  ...props\n}: MenuLinkProps) {\n  const { focusedId, onDismiss, onMenuItemBlur, onMenuItemFocus } =\n    useContextMenu(({ state, actions }) => ({\n      focusedId: state.focusedId,\n      onDismiss: actions.onDismiss,\n      onMenuItemBlur: actions.onMenuItemBlur,\n      onMenuItemFocus: actions.onMenuItemFocus,\n    }));\n  const autoGeneratedId = useMemo(() => uuidv4(), []);\n  const elementId = id || autoGeneratedId;\n\n  const handleBlur = (evt: SyntheticEvent<HTMLAnchorElement>) => {\n    onMenuItemBlur();\n    onBlur?.(evt);\n  };\n\n  const handleClick = (evt: SyntheticEvent<HTMLAnchorElement>) => {\n    onClick?.(evt);\n    onDismiss(evt.nativeEvent);\n  };\n\n  const handleFocus = (evt: SyntheticEvent<HTMLAnchorElement>) => {\n    onMenuItemFocus(elementId);\n    onFocus?.(evt);\n  };\n\n  const newTabProps = openNewTab\n    ? {\n        target: '_blank',\n        rel: 'noreferrer',\n      }\n    : {};\n\n  return (\n    <StyledLink\n      id={elementId}\n      tabIndex={focusedId === elementId ? 0 : -1}\n      role=\"menuitem\"\n      onBlur={handleBlur}\n      onClick={handleClick}\n      onFocus={handleFocus}\n      {...newTabProps}\n      {...props}\n    />\n  );\n}\n\nexport default Link;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/separator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { useContextMenu } from '../contextMenuProvider';\n\nconst Line = styled.div<{ isHorizontal?: boolean; isIconMenu?: boolean }>`\n  display: block;\n  flex-shrink: 0;\n  ${({ isHorizontal, isIconMenu, theme }) =>\n    isHorizontal\n      ? `\n        width: 1px;\n        height: 89%; /* 32px out of 36px */\n        margin: auto 2px; /* there's an extra 6px horizontal flexbox gap */\n        background-color: ${theme.colors.divider.secondary};\n      `\n      : `\n        height: 1px;\n        margin: 2px auto; /* there's an extra 6px vertical flexbox gap */\n        width: ${isIconMenu ? 40 : 100}%;\n        background-color: ${theme.colors.divider.primary};\n      `}\n`;\n\n/**\n * A horizontal line that can be rendered between context menu\n * items.\n */\nfunction Separator() {\n  const props = useContextMenu(({ state: { isIconMenu, isHorizontal } }) => ({\n    isIconMenu,\n    isHorizontal,\n  }));\n\n  return <Line {...props} />;\n}\n\nexport default Separator;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/shortcut.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { Text } from '../../typography/text';\n\nconst Shortcut = styled(Text.Kbd).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nexport default Shortcut;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/styles.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { BUTTON_TRANSITION_TIMING } from '../../button/constants';\n\nexport const menuItemStyles = css`\n  ${({ theme }) =>\n    themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.paragraph[TextSize.XSmall],\n      theme,\n    })};\n\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 2px 16px;\n  border: 0;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  font-weight: 500;\n  text-align: left;\n  transition: background-color ${BUTTON_TRANSITION_TIMING};\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useDebouncedCallback,\n  useCallback,\n  useEffect,\n  useRef,\n} from '@googleforcreators/react';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { useKeyDownEffect } from '../../keyboard';\nimport { FOCUSABLE_SELECTORS, KEYS } from '../../../utils';\nimport { useContextMenu } from '../contextMenuProvider';\nimport MenuItem from './item';\nimport type { MenuItemProps } from './item';\n\n/**\n * Extracts all focusable children from an html tree.\n */\nfunction getFocusableChildren(parent: Element) {\n  return Array.from(\n    parent.querySelectorAll(FOCUSABLE_SELECTORS.join(', '))\n  ).filter((e): e is HTMLElement => e instanceof HTMLElement);\n}\n\nexport interface SubMenuTriggerProps extends MenuItemProps {\n  openSubMenu: () => void;\n  closeSubMenu: () => void;\n  isSubMenuOpen: boolean;\n  isRTL?: boolean;\n  subMenuRef: RefObject<HTMLElement>;\n  parentMenuRef: RefObject<HTMLElement>;\n}\n\nfunction SubMenuTrigger({\n  openSubMenu,\n  closeSubMenu,\n  isSubMenuOpen,\n  isRTL = false,\n  subMenuRef,\n  parentMenuRef,\n  ...buttonProps\n}: SubMenuTriggerProps) {\n  const ref = useRef<HTMLButtonElement | null>(null);\n  const pointerTrackerRef = useRef<{ x?: number; y?: number }>({});\n\n  const { setFocusedId } = useContextMenu(({ actions }) => ({\n    setFocusedId: actions.setFocusedId,\n  }));\n\n  const pointerIsOutside = (node: Element) => {\n    const { x, y, width, height } = node.getBoundingClientRect();\n    const { x: pointerX, y: pointerY } = pointerTrackerRef.current;\n    if (pointerX === undefined || pointerY === undefined) {\n      return true;\n    }\n    const buffer = 2;\n    return (\n      pointerX < x - buffer ||\n      pointerX > x + width + buffer ||\n      pointerY < y - buffer ||\n      pointerY > y + height + buffer\n    );\n  };\n\n  const maybeCloseSubMenu = useDebouncedCallback(() => {\n    if (\n      !ref.current ||\n      !subMenuRef.current?.firstChild ||\n      !(subMenuRef.current.firstChild instanceof Element)\n    ) {\n      return;\n    }\n    // If after 200ms the cursor is not in the submenu and not in itself, leave.\n    if (\n      pointerIsOutside(ref.current) &&\n      pointerIsOutside(subMenuRef.current.firstChild)\n    ) {\n      closeSubMenu();\n    }\n  }, 200);\n\n  useEffect(() => {\n    if (isSubMenuOpen && subMenuRef.current) {\n      const subMenuItems = getFocusableChildren(subMenuRef.current);\n      if (subMenuItems.length) {\n        subMenuItems[0].focus();\n        setFocusedId(subMenuItems[0].id);\n      }\n    }\n  }, [isSubMenuOpen, subMenuRef, setFocusedId]);\n\n  useEffect(() => {\n    const node = parentMenuRef.current?.querySelector('[role=\"dialog\"]');\n    if (!isSubMenuOpen || !node) {\n      return undefined;\n    }\n    const onPointerMove = (e: Event) => {\n      if (e instanceof PointerEvent) {\n        // Track the pointer when moving inside the menu while the submenu is open.\n        pointerTrackerRef.current.x = e.clientX;\n        pointerTrackerRef.current.y = e.clientY;\n        maybeCloseSubMenu();\n      }\n    };\n    node.addEventListener('pointermove', onPointerMove);\n    return () => node.removeEventListener('pointermove', onPointerMove);\n  }, [isSubMenuOpen, parentMenuRef, maybeCloseSubMenu]);\n\n  const handleKeyboardEvents = useCallback(\n    (evt: KeyboardEvent) => {\n      const { code } = evt;\n      if ([KEYS.SPACE, KEYS.ENTER].includes(code)) {\n        if (!isSubMenuOpen) {\n          openSubMenu();\n        } else {\n          closeSubMenu();\n        }\n        return;\n      }\n      if ((!isRTL && KEYS.RIGHT === code) || (isRTL && KEYS.LEFT) === code) {\n        if (!isSubMenuOpen) {\n          openSubMenu();\n        }\n      }\n    },\n    [openSubMenu, closeSubMenu, isSubMenuOpen, isRTL]\n  );\n\n  useKeyDownEffect(\n    ref,\n    { key: ['enter', 'space', 'left', 'right'] },\n    handleKeyboardEvents,\n    [handleKeyboardEvents]\n  );\n\n  // Menu trigger does not react to clicking.\n  return (\n    <MenuItem\n      {...buttonProps}\n      ref={ref}\n      onPointerEnter={openSubMenu}\n      onPointerLeave={() => {\n        // Reset tracker in case we moved out of the menu fully.\n        pointerTrackerRef.current = {};\n        maybeCloseSubMenu();\n      }}\n      onClick={(e: MouseEvent) => e.preventDefault()}\n      aria-haspopup\n      aria-expanded={isSubMenuOpen}\n      dismissOnClick={false}\n    />\n  );\n}\n\nexport default SubMenuTrigger;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/components/suffix.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\nconst Suffix = styled.div`\n  position: relative;\n  svg {\n    width: 32px;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n    position: absolute;\n    right: -14px;\n    top: -16px;\n  }\n`;\n\nexport default Suffix;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Some menus have text or numeric inputs nested within them.\n * This pattern should be avoided, however sometimes it happens.\n * When it does, CONTEXT_MENU_SKIP_ELEMENT should be attached to\n * the nested natively focusable element (ie: an input)\n * so that in /menu.js `getFocusableChildren` can remove these nested elements\n * from its returned value. This allows a wrapper element (probably a button)\n * to handle when to focus the input\n * so that a keyboard user doesn't get trapped in the freeform input within a menu.\n * Currently, this is used from within story-editor floatingMenu (see FocusTrapButton).\n */\nexport const CONTEXT_MENU_SKIP_ELEMENT = 'context-menu-skip-element';\n\nexport const CONTEXT_MENU_MIN_WIDTH = 200;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/contextMenu.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, forwardRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport type { ForwardedRef, PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils';\nimport { SmartPopover, Shadow } from './styled';\nimport Menu from './menu';\nimport AnimationContainer from './animationContainer';\nimport { ContextMenuProvider } from './contextMenuProvider';\nimport type { ContextMenuProps } from './types';\n\nconst ContextMenu = forwardRef(\n  (\n    {\n      animate,\n      'aria-label': ariaLabel = __('Menu', 'web-stories'),\n      children,\n      id,\n      isAlwaysVisible,\n      isIconMenu = false,\n      isHorizontal = false,\n      isInline = false,\n      onDismiss = noop,\n      popoverZIndex,\n      ...props\n    }: PropsWithChildren<ContextMenuProps>,\n    ref: ForwardedRef<HTMLDivElement>\n  ) => {\n    const { isRTL } = props;\n    const Wrapper = useMemo(\n      () => (animate ? AnimationContainer : SmartPopover),\n      [animate]\n    );\n\n    return (\n      <ContextMenuProvider\n        isIconMenu={isIconMenu}\n        isHorizontal={isHorizontal}\n        onDismiss={onDismiss}\n      >\n        {/* eslint-disable-next-line react-hooks/static-components -- FIXME */}\n        <Wrapper\n          aria-label={ariaLabel}\n          isInline={isInline}\n          role={isAlwaysVisible ? null : 'dialog'}\n          isOpen={isAlwaysVisible || props.isOpen}\n          isRTL={isRTL}\n          popoverZIndex={popoverZIndex}\n        >\n          <Menu\n            aria-label={ariaLabel}\n            ref={ref}\n            aria-expanded={props.isOpen}\n            {...props}\n          >\n            {children}\n          </Menu>\n          {/* <AnimationContainer /> has a <Shadow />. Don't double the shadow. */}\n          {!animate && <Shadow $isHorizontal={isHorizontal} />}\n        </Wrapper>\n      </ContextMenuProvider>\n    );\n  }\n);\n\nexport default ContextMenu;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/contextMenuProvider/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { ContextMenuProvider } from '../types';\n\nconst ContextMenuContext = createContext<ContextMenuProvider>({\n  state: {\n    focusedId: null,\n    isIconMenu: false,\n    isHorizontal: false,\n  },\n  actions: {\n    onDismiss: () => undefined,\n    onMenuItemBlur: () => undefined,\n    onMenuItemFocus: () => undefined,\n    setFocusedId: () => undefined,\n  },\n});\n\nexport default ContextMenuContext;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/contextMenuProvider/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as ContextMenuProvider } from './provider';\nexport { default as useContextMenu } from './useContextMenu';\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/contextMenuProvider/provider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\n\nimport { useCallback, useState } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n/**\n * Internal dependencies\n */\nimport ContextMenuContext from './context';\n\ninterface ContextMenuProviderProps {\n  isIconMenu?: boolean;\n  isHorizontal?: boolean;\n  onDismiss: (evt?: Event) => void;\n}\n\nexport default function ContextMenuProvider({\n  children,\n  isIconMenu = false,\n  isHorizontal = false,\n  onDismiss,\n}: PropsWithChildren<ContextMenuProviderProps>) {\n  const [focusedId, setFocusedId] = useState<string | null>(null);\n\n  const handleFocus = useCallback((id: string) => setFocusedId(id), []);\n  const handleBlur = useCallback(() => setFocusedId(null), []);\n\n  const value = {\n    state: {\n      focusedId,\n      isIconMenu,\n      isHorizontal,\n    },\n    actions: {\n      onDismiss,\n      onMenuItemBlur: handleBlur,\n      onMenuItemFocus: handleFocus,\n      setFocusedId,\n    },\n  };\n\n  return (\n    <ContextMenuContext.Provider value={value}>\n      {children}\n    </ContextMenuContext.Provider>\n  );\n}\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/contextMenuProvider/useContextMenu.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { ContextMenuProvider } from '../types';\nimport Context from './context';\n\nfunction useContextMenu(): ContextMenuProvider;\nfunction useContextMenu<T>(selector: (state: ContextMenuProvider) => T): T;\nfunction useContextMenu<T>(\n  selector: (state: ContextMenuProvider) => T | ContextMenuProvider = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useContextMenu;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as ContextMenu } from './contextMenu';\nexport * as ContextMenuComponents from './components';\nexport * from './types';\nexport { CONTEXT_MENU_SKIP_ELEMENT, CONTEXT_MENU_MIN_WIDTH } from './constants';\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/menu.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useCombinedRefs,\n  forwardRef,\n} from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport type { FocusEvent, ForwardedRef, PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  FOCUSABLE_SELECTORS,\n  KEYS,\n  noop,\n  useMouseDownOutsideRef,\n} from '../../utils';\nimport useForwardedRef from '../../utils/useForwardedRef';\nimport { useKeyDownEffect } from '../keyboard';\nimport { useContextMenu } from './contextMenuProvider';\nimport { CONTEXT_MENU_MIN_WIDTH, CONTEXT_MENU_SKIP_ELEMENT } from './constants';\nimport type { InnerContextMenuProps } from './types';\n\nconst CONTEXT_MENU_MAX_WIDTH = 300;\n\nconst MenuWrapper = styled.div<{\n  isIconMenu?: boolean;\n  isHorizontal?: boolean;\n  isSecondary?: boolean;\n}>(\n  ({ theme }) => css<{\n    isIconMenu?: boolean;\n    isHorizontal?: boolean;\n    isSecondary?: boolean;\n  }>`\n    background-color: ${({ isSecondary }) =>\n      isSecondary ? theme.colors.bg.secondary : theme.colors.bg.primary};\n    border-radius: ${({ isHorizontal }) =>\n      isHorizontal ? theme.borders.radius.medium : theme.borders.radius.small};\n    border: 1px solid ${theme.colors.border.disable};\n    gap: 6px;\n    display: flex;\n\n    ${({ isHorizontal, isIconMenu }) =>\n      isHorizontal\n        ? css`\n            // horizontal menu\n            height: 52px;\n            padding: 7px 10px;\n            align-items: center;\n          `\n        : css`\n            // vertical menu\n            flex-direction: column;\n            width: ${isIconMenu ? '40px' : 'auto'};\n            padding: ${isIconMenu ? '4px 3px' : '8px 0'};\n            max-width: ${CONTEXT_MENU_MAX_WIDTH}px;\n\n            ${!isIconMenu &&\n            css`\n              min-width: ${CONTEXT_MENU_MIN_WIDTH}px;\n            `};\n          `}\n\n    *:last-child {\n      margin-bottom: 0;\n    }\n  `\n);\n\n/**\n * Extracts all focusable children from an html tree, optionally ignoring items from submenu.\n */\nfunction getFocusableChildren(parent: HTMLElement, isSubMenu?: boolean) {\n  const allButtons = Array.from(\n    parent.querySelectorAll(FOCUSABLE_SELECTORS.join(', '))\n  ).filter((e): e is HTMLElement => e instanceof HTMLElement);\n  if (isSubMenu) {\n    return allButtons;\n  }\n  // Skip considering the submenu, and the submenu items as well as inputs that are focus traps (floating menu/toolbar)\n  return allButtons.filter((elem) => {\n    return !elem.matches(\n      `[role=\"menu\"], [role=\"menu\"] [role=\"menu\"] *, .${CONTEXT_MENU_SKIP_ELEMENT}`\n    );\n  });\n}\n\nconst Menu = forwardRef<\n  HTMLDivElement,\n  PropsWithChildren<InnerContextMenuProps>\n>(\n  (\n    {\n      children,\n      disableControlledTabNavigation,\n      isOpen,\n      onFocus = noop,\n      isSubMenu = false,\n      isSecondary = false,\n      parentMenuRef,\n      onCloseSubMenu = noop,\n      dismissOnEscape = true,\n      ...props\n    }: PropsWithChildren<InnerContextMenuProps>,\n    forwardedRef: ForwardedRef<HTMLDivElement>\n  ) => {\n    const { isRTL } = props;\n    const { focusedId, isIconMenu, isHorizontal, onDismiss, setFocusedId } =\n      useContextMenu(({ state, actions }) => ({\n        focusedId: state.focusedId,\n        isIconMenu: state.isIconMenu,\n        isHorizontal: state.isHorizontal,\n        onDismiss: actions.onDismiss,\n        setFocusedId: actions.setFocusedId,\n      }));\n    const mouseDownOutsideRef = useMouseDownOutsideRef<HTMLDivElement>(\n      () => isOpen && !isSubMenu && onDismiss()\n    );\n    const ref = useForwardedRef(forwardedRef);\n    const composedListRef = useCombinedRefs(mouseDownOutsideRef, ref);\n    /**\n     * Focus the first element when the user focuses the wrapper\n     * with their keyboard.\n     *\n     * Clicking in the wrapper should not automatically focus the first\n     * focusable element.\n     */\n    const handleFocus = useCallback(\n      (evt: FocusEvent<HTMLDivElement>) => {\n        onFocus(evt);\n        if (!ref.current) {\n          return;\n        }\n        const menuChildren = [...ref.current.children];\n        const isFocusOutsideMenu =\n          menuChildren.length &&\n          ![...menuChildren].some((child) => child.contains(evt.target));\n\n        if (ref.current === evt.target && isFocusOutsideMenu) {\n          const focusableChildren = getFocusableChildren(ref.current);\n          // used to shift focus outline correctly\n          document.dispatchEvent(new KeyboardEvent('keydown', { key: 'tab' }));\n          if (\n            focusableChildren.length > 0 &&\n            focusableChildren[0] instanceof HTMLElement\n          ) {\n            focusableChildren[0].focus();\n          }\n        }\n      },\n      [onFocus, ref]\n    );\n\n    const getPrevIndex = useCallback(\n      (focusableChildren: Element[]) => {\n        let prevIndex = focusableChildren.findIndex(\n          (element) => element.id === focusedId\n        );\n        // There are cases where the active element is in the present menu but the focusedId has been reset because of a popup interaction, in those cases we should double check the true focused id by looking at the active element id and comparing.\n        if (prevIndex === -1) {\n          prevIndex = focusableChildren.findIndex(\n            (element) => element.id === document.activeElement?.id\n          );\n        }\n        return prevIndex;\n      },\n      [focusedId]\n    );\n    /**\n     * Allow navigation of the list using the UP and DOWN arrow keys.\n     * Allow navigation between the parent menu and submenu with LEFT and RIGHT arrow keys.\n     * Close menu if ESCAPE is pressed.\n     *\n     * @param {Event} event The synthetic event\n     * @return {void} void\n     */\n    const handleKeyboardNav = useCallback(\n      (evt: KeyboardEvent) => {\n        const { key } = evt;\n        if (key === 'Escape') {\n          onDismiss(evt);\n          return;\n        }\n\n        if (!ref.current) {\n          return;\n        }\n        const focusableChildren = getFocusableChildren(ref.current, isSubMenu);\n\n        let prevIndex = getPrevIndex(focusableChildren);\n\n        if (prevIndex === -1 && focusableChildren.length) {\n          setFocusedId(focusableChildren[0].id);\n          prevIndex = 0;\n        }\n\n        const keyBackward = isHorizontal ? KEYS.LEFT : KEYS.UP;\n        const keyForward = isHorizontal ? KEYS.RIGHT : KEYS.DOWN;\n\n        // If we're moving through this menu (up/down in vertical, left/right in horizontal).\n        if ([keyBackward, keyForward].includes(key)) {\n          const isAscending = keyBackward === key;\n          let newIndex = prevIndex + (isAscending ? -1 : 1);\n          if (newIndex === -1) {\n            newIndex = focusableChildren.length - 1;\n          }\n\n          // Otherwise move to the next element or loop around the list.\n          const newSelectedElement =\n            focusableChildren[newIndex % focusableChildren.length];\n          newSelectedElement?.focus();\n\n          setFocusedId(newSelectedElement.id || null);\n          return;\n        }\n\n        // The direction to move out of a submenu depends on horizontal/vertical and RTL/LTR\n        const keyOut = isHorizontal ? KEYS.UP : isRTL ? KEYS.RIGHT : KEYS.LEFT;\n\n        // Maybe move from submenu to parent menu.\n        if (isSubMenu && keyOut === key && parentMenuRef?.current) {\n          // Get the button with expanded popup.\n          const parentButton = parentMenuRef.current.querySelector<HTMLElement>(\n            'button[aria-expanded=\"true\"]'\n          );\n          parentButton?.focus();\n          onCloseSubMenu();\n        }\n      },\n      [\n        ref,\n        isSubMenu,\n        getPrevIndex,\n        isHorizontal,\n        isRTL,\n        parentMenuRef,\n        onDismiss,\n        setFocusedId,\n        onCloseSubMenu,\n      ]\n    );\n\n    // focus first focusable element on open\n    useEffect(() => {\n      if (isOpen && ref.current) {\n        const focusableChildren = getFocusableChildren(ref.current);\n        if (\n          focusableChildren.length &&\n          focusableChildren[0] instanceof HTMLElement\n        ) {\n          focusableChildren[0].focus();\n          setFocusedId(focusableChildren[0].id);\n        }\n      }\n    }, [isOpen, ref, setFocusedId]);\n\n    const keySpec = useMemo(\n      () =>\n        disableControlledTabNavigation\n          ? { key: [] }\n          : { key: ['tab'], shift: true },\n      [disableControlledTabNavigation]\n    );\n\n    useKeyDownEffect(\n      ref,\n      {\n        key: dismissOnEscape\n          ? ['esc', 'down', 'up', 'left', 'right']\n          : ['down', 'up', 'left', 'right'],\n      },\n      handleKeyboardNav,\n      [handleKeyboardNav, dismissOnEscape]\n    );\n\n    useKeyDownEffect(ref, keySpec, onDismiss, [keySpec, onDismiss]);\n\n    return (\n      <MenuWrapper\n        ref={composedListRef}\n        data-testid=\"context-menu-list\"\n        role=\"menu\"\n        isIconMenu={isIconMenu}\n        isHorizontal={isHorizontal}\n        isSecondary={isSecondary}\n        // Tabbing out from the list while using 'shift' would\n        // focus the list element. Should just travel back to the previous\n        // focusable element in the DOM\n        // eslint-disable-next-line react-hooks/refs -- FIXME\n        tabIndex={ref.current?.contains(document.activeElement) ? -1 : 0}\n        onFocus={handleFocus}\n        {...props}\n      >\n        {children}\n      </MenuWrapper>\n    );\n  }\n);\n\nexport default Menu;\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useState,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport ContextMenu from '../contextMenu';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport {\n  Bucket,\n  Captions,\n  CheckmarkSmall,\n  ChevronRightSmall,\n  CircleSpeed,\n  Cross,\n  Eraser,\n  LetterTLargeLetterTSmall,\n  LetterTPlus,\n  Link as IconLink,\n  Media,\n  PictureSwap,\n} from '../../../icons';\nimport { Text } from '../../typography';\nimport { Placement } from '../../popup';\nimport * as MenuItems from '../components';\n\nexport default {\n  title: 'DesignSystem/Components/ContextMenu',\n  component: ContextMenu,\n  args: {\n    isOpen: true,\n  },\n  argTypes: {\n    onClick: { action: 'clicked' },\n  },\n  parameters: {\n    controls: {\n      include: ['isOpen', 'onClick'],\n    },\n  },\n};\n\nconst ViewportContainer = styled.div`\n  position: relative;\n  height: 100vh;\n  width: 100%;\n`;\n\nconst Container = styled.div`\n  position: relative;\n  height: 700px;\n  width: 500px;\n  padding: 20px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Grid = styled.div`\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n\n  ${Container} {\n    height: 500px;\n    width: 300px;\n    margin: 0 auto;\n\n    div {\n      transform: translate(0, 0);\n    }\n  }\n`;\n\nexport const _default = {\n  render: function Render({ onClick, ...args }) {\n    return (\n      <Container>\n        <ContextMenu {...args}>\n          <MenuItems.MenuButton onClick={() => onClick('one')}>\n            {'one'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuButton onClick={() => onClick('two')}>\n            {'two'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuButton onClick={() => onClick('disable')} disabled>\n            {'this is disabled'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuSeparator />\n          <MenuItems.MenuLabel>\n            {'i am neither a button nor a link'}\n          </MenuItems.MenuLabel>\n          <MenuItems.MenuSeparator />\n          <MenuItems.MenuButton onClick={() => onClick('i am a button')}>\n            {'i am a button!'}\n            <MenuItems.MenuShortcut>{'⌥ ⌘ A'}</MenuItems.MenuShortcut>\n          </MenuItems.MenuButton>\n          <MenuItems.MenuButton\n            onClick={() =>\n              onClick(\n                'Clicked on i am a very very very very very very very long label'\n              )\n            }\n          >\n            {'i am a very very very very very very very long label'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuLink href=\"https://www.google.com/\">\n            {'i am a link!'}\n          </MenuItems.MenuLink>\n          <MenuItems.MenuLink href=\"https://www.google.com/\" openNewTab>\n            {'i am a link that opens a new tab!'}\n          </MenuItems.MenuLink>\n          <MenuItems.MenuSeparator />\n          <MenuItems.MenuGroup label=\"The oh my section\">\n            <MenuItems.MenuButton onClick={() => onClick('lions')}>\n              {'lions'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton onClick={() => onClick('tigers')}>\n              {'tigers'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton onClick={() => onClick('bears')}>\n              {'bears'}\n            </MenuItems.MenuButton>\n          </MenuItems.MenuGroup>\n        </ContextMenu>\n      </Container>\n    );\n  },\n};\n\nexport const DarkMode = {\n  render: function Render({ onClick, ...args }) {\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <ContextMenu {...args}>\n            <MenuItems.MenuButton onClick={() => onClick('one')}>\n              {'one'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton onClick={() => onClick('two')}>\n              {'two'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton onClick={() => onClick('disable')} disabled>\n              {'this is disabled'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuLabel>\n              {'i am neither a button nor a link'}\n            </MenuItems.MenuLabel>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton onClick={() => onClick('i am a button')}>\n              {'i am a button!'}\n              <MenuItems.MenuShortcut>{'⌥ ⌘ A'}</MenuItems.MenuShortcut>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() =>\n                onClick(\n                  'Clicked on i am a very very very very very very very long label'\n                )\n              }\n            >\n              {'i am a very very very very very very very long label'}\n            </MenuItems.MenuButton>\n            <MenuItems.MenuLink href=\"https://www.google.com/\">\n              {'i am a link!'}\n            </MenuItems.MenuLink>\n            <MenuItems.MenuLink href=\"https://www.google.com/\" openNewTab>\n              {'i am a link that opens a new tab!'}\n            </MenuItems.MenuLink>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuGroup label=\"The oh my section\">\n              <MenuItems.MenuButton onClick={() => onClick('lions')}>\n                {'lions'}\n              </MenuItems.MenuButton>\n              <MenuItems.MenuButton onClick={() => onClick('tigers')}>\n                {'tigers'}\n              </MenuItems.MenuButton>\n              <MenuItems.MenuButton onClick={() => onClick('bears')}>\n                {'bears'}\n              </MenuItems.MenuButton>\n            </MenuItems.MenuGroup>\n          </ContextMenu>\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n\nexport const QuickActionMenu = {\n  render: function Render({ onClick, ...args }) {\n    return (\n      <Grid>\n        <Container>\n          <Text.Paragraph>{'Blank page; no item selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Change background color\">\n                <Bucket />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Insert media\">\n                <Media />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Insert text\">\n                <LetterTPlus />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Background Image selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Replace background\">\n                <PictureSwap />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Add animation\">\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Clear filters and animation\">\n                <Eraser />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Foreground Image selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Replace media\">\n                <PictureSwap />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Add animation\">\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Add link\">\n                <IconLink />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fourth action')}\n            >\n              <MenuItems.MenuIcon title=\"Clear filters and animation\">\n                <Eraser />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Video selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Replace media\">\n                <PictureSwap />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Add animation\">\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Add link\">\n                <IconLink />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fourth action')}\n            >\n              <MenuItems.MenuIcon title=\"Add captions\">\n                <Captions />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fifth action')}\n            >\n              <MenuItems.MenuIcon title=\"Clear filters and animation\">\n                <Eraser />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Shape selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Change color\">\n                <Bucket />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Add animation\">\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Add link\">\n                <IconLink />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fourth action')}\n            >\n              <MenuItems.MenuIcon title=\"Clear filters and animation\">\n                <Eraser />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Text selected'}</Text.Paragraph>\n          <ContextMenu isIconMenu {...args}>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the first action')}\n            >\n              <MenuItems.MenuIcon title=\"Change color\">\n                <Bucket />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the second action')}\n            >\n              <MenuItems.MenuIcon title=\"Edit text\">\n                <LetterTLargeLetterTSmall />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the third action')}\n            >\n              <MenuItems.MenuIcon title=\"Add animation\">\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fourth action')}\n            >\n              <MenuItems.MenuIcon title=\"Add link\">\n                <IconLink />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('on the fifth action')}\n            >\n              <MenuItems.MenuIcon title=\"Clear filters and animation\">\n                <Eraser />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n      </Grid>\n    );\n  },\n};\n\nexport const HorizontalMenu = {\n  render: function Render({ onClick, ...args }) {\n    return (\n      <Grid>\n        <Container>\n          <Text.Paragraph>{'Dummy horizontal menu'}</Text.Paragraph>\n          <ContextMenu isHorizontal isInline isSecondary {...args}>\n            <MenuItems.MenuButton onClick={() => onClick('Clicked on bucket')}>\n              <MenuItems.MenuIcon title=\"Bucket\" placement={Placement.Bottom}>\n                <Bucket />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton onClick={() => onClick('Clicked on link')}>\n              <MenuItems.MenuIcon title=\"Link\" placement={Placement.Bottom}>\n                <IconLink />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuButton\n              onClick={() => onClick('Clicked on captions')}\n            >\n              <MenuItems.MenuIcon title=\"Captions\" placement={Placement.Bottom}>\n                <Captions />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton\n              onClick={() => onClick('Clicked on animation')}\n            >\n              <MenuItems.MenuIcon\n                title=\"Animation\"\n                placement={Placement.BOTTOM}\n              >\n                <CircleSpeed />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n            <MenuItems.MenuSeparator />\n            <MenuItems.MenuButton onClick={() => onClick('Clicked on cross')}>\n              <MenuItems.MenuIcon title=\"Cross\" placement={Placement.Bottom}>\n                <Cross />\n              </MenuItems.MenuIcon>\n            </MenuItems.MenuButton>\n          </ContextMenu>\n        </Container>\n      </Grid>\n    );\n  },\n};\n\nconst rightClickMenuMainOptions = (\n  <>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Copy'}\n      <MenuItems.MenuShortcut>{'⌘C'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Paste'}\n      <MenuItems.MenuShortcut>{'⌘V'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Delete'}\n      <MenuItems.MenuShortcut>{'DEL'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst rightClickMenuLayeringOptions = (\n  <>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Send to back'}\n      <MenuItems.MenuShortcut>{'⌥⌘['}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Send backwards'}\n      <MenuItems.MenuShortcut>{'⌘['}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Bring forward'}\n      <MenuItems.MenuShortcut>{'⌘]'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Bring to front'}\n      <MenuItems.MenuShortcut>{'⌥⌘]'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst rightClickMenuPageAddOptions = (\n  <>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Add new page before'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Add new page after'}\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst rightClickMenuPageDeleteOptions = (\n  <>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Duplicate page'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Delete page'}\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst rightClickMenuStyleOptions = (\n  <>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Copy style'}\n      <MenuItems.MenuShortcut>{'⌥⌘C'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Paste style'}\n      <MenuItems.MenuShortcut>{'⌥⌘V'}</MenuItems.MenuShortcut>\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Clear style'}\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst pageMenu = (\n  <>\n    {rightClickMenuMainOptions}\n    <MenuItems.MenuSeparator />\n    {rightClickMenuPageAddOptions}\n    {rightClickMenuPageDeleteOptions}\n  </>\n);\n\nconst shapeMenu = (\n  <>\n    {rightClickMenuMainOptions}\n    <MenuItems.MenuSeparator />\n    {rightClickMenuLayeringOptions}\n    <MenuItems.MenuSeparator />\n    {rightClickMenuStyleOptions}\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Add color to \"Saved colors\"'}\n    </MenuItems.MenuButton>\n  </>\n);\n\nconst foregroundMediaMenu = (\n  <>\n    {rightClickMenuMainOptions}\n    <MenuItems.MenuSeparator />\n    {rightClickMenuLayeringOptions}\n    <MenuItems.MenuSeparator />\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Set as page background'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Scale & crop image'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuSeparator />\n    {rightClickMenuStyleOptions}\n  </>\n);\n\nconst backgroundMediaMenu = (\n  <>\n    {rightClickMenuMainOptions}\n    <MenuItems.MenuSeparator />\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Detach image from background'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Replace background image'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Scale & crop background image'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuButton onClick={() => {}}>\n      {'Clear style'}\n    </MenuItems.MenuButton>\n    <MenuItems.MenuSeparator />\n    {rightClickMenuPageAddOptions}\n    {rightClickMenuPageDeleteOptions}\n  </>\n);\n\nconst TextMenu = ({ children, ...args }) => {\n  const ref = useRef();\n  const subMenuRef = useRef();\n  const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n  return (\n    <Container ref={ref}>\n      {children}\n      <ContextMenu {...args}>\n        <MenuItems.SubMenuTrigger\n          subMenuRef={subMenuRef}\n          isSubMenuOpen={isSubMenuOpen}\n          parentMenuRef={ref}\n          closeSubMenu={() => setIsSubMenuOpen(false)}\n          openSubMenu={() => setIsSubMenuOpen(true)}\n          label=\"Heading Level\"\n          SuffixIcon={ChevronRightSmall}\n        />\n        <RightClickContextMenuContainer\n          position={{\n            y: 0,\n            x: 212,\n          }}\n          ref={subMenuRef}\n        >\n          <ContextMenu\n            isOpen={isSubMenuOpen}\n            onCloseSubMenu={() => setIsSubMenuOpen(false)}\n            isSubMenu\n            parentMenuRef={ref}\n          >\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => () => setIsSubMenuOpen(false)}\n              label={<span>{'Automatic'}</span>}\n            />\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              icon={<CheckmarkSmall />}\n              onClick={() => setIsSubMenuOpen(false)}\n              label={<span>{'Heading 1'}</span>}\n            />\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => setIsSubMenuOpen(false)}\n              label={<span>{'Heading 2'}</span>}\n            />\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => setIsSubMenuOpen(false)}\n              label={<span>{'Heading 3'}</span>}\n            />\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => setIsSubMenuOpen(false)}\n              label={<span>{'Paragraph'}</span>}\n            />\n          </ContextMenu>\n        </RightClickContextMenuContainer>\n        <MenuItems.MenuSeparator />\n        {rightClickMenuLayeringOptions}\n        <MenuItems.MenuSeparator />\n        {rightClickMenuStyleOptions}\n        <MenuItems.MenuButton onClick={() => {}}>\n          {'Add style to \"Saved styles\"'}\n        </MenuItems.MenuButton>\n        <MenuItems.MenuButton onClick={() => {}}>\n          {'Add color to \"Saved colors\"'}\n        </MenuItems.MenuButton>\n      </ContextMenu>\n    </Container>\n  );\n};\n\nTextMenu.propTypes = {\n  children: PropTypes.node,\n};\n\nconst SampleLayout = styled.div`\n  display: block;\n  width: 400px;\n  height: 800px;\n  border: 1px solid black;\n`;\nconst RightClickContextMenuContainer = styled.div`\n  position: absolute;\n  top: ${({ position }) => position?.y ?? 0}px;\n  left: ${({ position }) => position?.x ?? 0}px;\n`;\n\nconst RightClickMenuOnShapeAndBackground = ({ children, ...args }) => {\n  const ref = useRef();\n  const subMenuRef = useRef();\n  const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n  return (\n    <Container ref={ref}>\n      {children}\n      <ContextMenu {...args}>\n        <MenuItems.SubMenuTrigger\n          subMenuRef={subMenuRef}\n          isSubMenuOpen={isSubMenuOpen}\n          parentMenuRef={ref}\n          closeSubMenu={() => setIsSubMenuOpen(false)}\n          openSubMenu={() => setIsSubMenuOpen(true)}\n          label=\"Select Layer\"\n          SuffixIcon={ChevronRightSmall}\n        />\n        <RightClickContextMenuContainer\n          position={{\n            y: 0,\n            x: 212,\n          }}\n          ref={subMenuRef}\n        >\n          <ContextMenu\n            isOpen={isSubMenuOpen}\n            onCloseSubMenu={() => setIsSubMenuOpen(false)}\n            isSubMenu\n            parentMenuRef={ref}\n          >\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => () => setIsSubMenuOpen(false)}\n              icon={<CheckmarkSmall />}\n              label={<span>{'Select rectangle'}</span>}\n            />\n            <MenuItems.MenuItem\n              supportsIcon\n              dismissOnClick={false}\n              onClick={() => setIsSubMenuOpen(false)}\n              label={<span>{'Select background'}</span>}\n            />\n          </ContextMenu>\n        </RightClickContextMenuContainer>\n        <MenuItems.MenuSeparator />\n        {shapeMenu}\n      </ContextMenu>\n    </Container>\n  );\n};\n\nRightClickMenuOnShapeAndBackground.propTypes = {\n  children: PropTypes.node,\n};\n\nexport const WithSubMenu = {\n  render: function Render({ onClick, ...args }) {\n    const ref = useRef();\n    const subMenuRef = useRef();\n    const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n    const handleSubMenuClick = (clicked) => {\n      setIsSubMenuOpen(false);\n      onClick(clicked);\n    };\n    return (\n      <Container ref={ref}>\n        <ContextMenu {...args}>\n          <MenuItems.MenuButton onClick={() => onClick('one')}>\n            {'one'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuButton onClick={() => onClick('two')}>\n            {'two'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuButton onClick={() => onClick('disabled')} disabled>\n            {'this is disabled'}\n          </MenuItems.MenuButton>\n          <MenuItems.MenuSeparator />\n          <MenuItems.SubMenuTrigger\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            parentMenuRef={ref}\n            closeSubMenu={() => setIsSubMenuOpen(false)}\n            openSubMenu={() => setIsSubMenuOpen(true)}\n            label=\"More items\"\n            SuffixIcon={ChevronRightSmall}\n          />\n          <RightClickContextMenuContainer\n            position={{\n              y: 102,\n              x: 212,\n            }}\n            ref={subMenuRef}\n          >\n            <ContextMenu\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={() => setIsSubMenuOpen(false)}\n              isSubMenu\n              parentMenuRef={ref}\n            >\n              <MenuItems.MenuButton\n                dismissOnClick={false}\n                onClick={() => handleSubMenuClick('layer 1')}\n              >\n                {'Select layer 1'}\n              </MenuItems.MenuButton>\n              <MenuItems.MenuSeparator />\n              <MenuItems.MenuButton\n                dismissOnClick={false}\n                onClick={() => handleSubMenuClick('select background 1')}\n              >\n                {'Select background'}\n              </MenuItems.MenuButton>\n            </ContextMenu>\n          </RightClickContextMenuContainer>\n          <MenuItems.MenuLabel>\n            {'i am neither a button nor a link'}\n          </MenuItems.MenuLabel>\n          <MenuItems.MenuSeparator />\n          <MenuItems.MenuButton onClick={() => onClick('i am a button')}>\n            {'i am a button!'}\n            <MenuItems.MenuShortcut>{'⌥ ⌘ A'}</MenuItems.MenuShortcut>\n          </MenuItems.MenuButton>\n        </ContextMenu>\n      </Container>\n    );\n  },\n};\n\nexport const RightClickMenu = {\n  render: function Render(args) {\n    const [isOpen, setIsOpen] = useState(false);\n    const [menuPosition, setMenuPosition] = useState({});\n    const layoutRef = useRef();\n\n    const handleMenu = useCallback((e) => {\n      e.preventDefault();\n      const layoutRect = layoutRef?.current?.getBoundingClientRect();\n\n      setIsOpen(true);\n      setMenuPosition({\n        x: e.clientX - layoutRect?.left,\n        y: e.clientY - layoutRect?.top,\n      });\n    }, []);\n\n    // Override the browser's context menu\n    useEffect(() => {\n      const node = layoutRef.current;\n      if (!node) {\n        return undefined;\n      }\n\n      node.addEventListener('contextmenu', handleMenu);\n\n      return () => {\n        node.removeEventListener('contextmenu', handleMenu);\n      };\n    }, [handleMenu]);\n\n    return (\n      <ViewportContainer>\n        {/*eslint-disable-next-line styled-components-a11y/no-noninteractive-element-interactions*/}\n        <SampleLayout ref={layoutRef} role=\"region\" onKeyDown={() => {}} />\n        <RightClickContextMenuContainer position={menuPosition}>\n          <ContextMenu\n            isOpen={isOpen}\n            onDismiss={() => setIsOpen(false)}\n            {...args}\n          >\n            {pageMenu}\n          </ContextMenu>\n        </RightClickContextMenuContainer>\n      </ViewportContainer>\n    );\n  },\n};\n\nexport const RightClickMenuStaticValues = {\n  render: function Render(args) {\n    return (\n      <Grid>\n        <RightClickMenuOnShapeAndBackground {...args}>\n          <Text.Paragraph>\n            {'Right click menu on top of shape and background'}\n          </Text.Paragraph>\n        </RightClickMenuOnShapeAndBackground>\n        <Container>\n          <Text.Paragraph>{'Right click on page element'}</Text.Paragraph>\n          <ContextMenu {...args}>{pageMenu}</ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Right click on shape element'}</Text.Paragraph>\n          <ContextMenu {...args}>{shapeMenu}</ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>\n            {'Right click on foreground media element'}\n          </Text.Paragraph>\n          <ContextMenu {...args}>{foregroundMediaMenu}</ContextMenu>\n        </Container>\n        <Container>\n          <Text.Paragraph>{'Right click on background element'}</Text.Paragraph>\n          <ContextMenu {...args}>{backgroundMediaMenu}</ContextMenu>\n        </Container>\n        <TextMenu {...args}>\n          <Text.Paragraph>{'Right click on text element'}</Text.Paragraph>\n        </TextMenu>\n      </Grid>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/styled.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport type { ComponentPropsWithoutRef } from 'react';\n\n// z-index needs to be higher than the wordpress toolbar z-index: 9989.\n// Leaves room for mask to be higher than the wordpress toolbar z-index.\nexport const POPOVER_Z_INDEX = 9991;\n\nexport const Popover = styled.div<{\n  isOpen?: boolean;\n  isInline?: boolean;\n  popoverZIndex?: number;\n}>`\n  --translate-x: calc(var(--delta-x, 0) * 1px);\n  --translate-y: calc(var(--delta-y, 0) * 1px);\n  display: ${({ isOpen }) => (isOpen ? 'block' : 'none')};\n  position: ${({ isInline }) => (isInline ? 'relative' : 'absolute')};\n  z-index: ${({ popoverZIndex = POPOVER_Z_INDEX }) => popoverZIndex};\n  transform: translate(var(--translate-x), var(--translate-y));\n`;\n\nexport const Shadow = styled.div<{\n  $isHorizontal?: boolean;\n}>`\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  border-radius: ${({ theme, $isHorizontal }) =>\n    $isHorizontal ? theme.borders.radius.medium : theme.borders.radius.small};\n  box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);\n  pointer-events: none;\n`;\n\nexport interface SmartPopoverProps extends ComponentPropsWithoutRef<\n  typeof Popover\n> {\n  isRTL?: boolean;\n}\n\nexport function SmartPopover({ isRTL, ...props }: SmartPopoverProps) {\n  const setRef = useCallback(\n    (node: HTMLElement | null) => {\n      if (!node) {\n        return;\n      }\n\n      const boundingBox = node.getBoundingClientRect();\n      const max = {\n        x: window.innerWidth - boundingBox.width,\n        y: window.innerHeight - boundingBox.height,\n      };\n\n      // This is modeling the behavior of chrome:\n      // - menu becomes right justified if not enough space horizontally\n      // - menu sticks to bottom if not enough space vertically\n      const horizontalEdgeCondition = isRTL\n        ? boundingBox.x < 0\n        : max.x < boundingBox.x;\n      const horizontalEdgeTransform = isRTL\n        ? boundingBox.width\n        : -boundingBox.width;\n      const delta = {\n        x: horizontalEdgeCondition ? horizontalEdgeTransform : 0,\n        y: Math.min(0, max.y - boundingBox.y),\n      };\n      node.style.setProperty('--delta-x', String(delta.x));\n      node.style.setProperty('--delta-y', String(delta.y));\n    },\n    [isRTL]\n  );\n\n  return props.isOpen ? <Popover ref={setRef} {...props} /> : null;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/test/contextMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport ContextMenu from '../contextMenu';\nimport * as ContextMenuComponents from '../components';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { noop } from '../../../utils';\n\nconst items = [\n  { label: 'this is a button', onClick: noop },\n  { label: 'this is a link', href: 'my-link' },\n  { label: 'this is neither a button nor a link' },\n];\n\ndescribe('ContextMenu', () => {\n  it('contextMenu should be invisible', () => {\n    renderWithProviders(\n      <ContextMenu>\n        <ContextMenuComponents.MenuButton onClick={noop}>\n          {'this is a button'}\n        </ContextMenuComponents.MenuButton>\n        <ContextMenuComponents.MenuLink href=\"/\">\n          {'this is a link'}\n        </ContextMenuComponents.MenuLink>\n        <ContextMenuComponents.MenuLabel>\n          {'this is neither a button nor a link'}\n        </ContextMenuComponents.MenuLabel>\n      </ContextMenu>\n    );\n\n    expect(screen.queryByRole('menu')).not.toBeInTheDocument();\n    expect(screen.queryByRole('menuitem')).not.toBeInTheDocument();\n  });\n\n  it('contextMenu should be visible', () => {\n    renderWithProviders(\n      <ContextMenu isOpen>\n        <ContextMenuComponents.MenuButton onClick={noop}>\n          {'this is a button'}\n        </ContextMenuComponents.MenuButton>\n        <ContextMenuComponents.MenuLink href=\"/\">\n          {'this is a link'}\n        </ContextMenuComponents.MenuLink>\n        <ContextMenuComponents.MenuLabel>\n          {'this is neither a button nor a link'}\n        </ContextMenuComponents.MenuLabel>\n      </ContextMenu>\n    );\n\n    expect(screen.getByRole('menu')).toBeInTheDocument();\n    expect(screen.getByText('this is a button')).toBeInTheDocument();\n    expect(screen.getByText('this is a link')).toBeInTheDocument();\n  });\n\n  it('clicking outside the context menu should call onDismiss', () => {\n    const onDismiss = jest.fn();\n    renderWithProviders(\n      <div>\n        <div data-testid=\"some-element\" />\n        <ContextMenu isOpen onDismiss={onDismiss}>\n          <ContextMenuComponents.MenuButton onClick={noop}>\n            {'this is a button'}\n          </ContextMenuComponents.MenuButton>\n          <ContextMenuComponents.MenuLink href=\"/\">\n            {'this is a link'}\n          </ContextMenuComponents.MenuLink>\n          <ContextMenuComponents.MenuLabel>\n            {'this is neither a button nor a link'}\n          </ContextMenuComponents.MenuLabel>\n        </ContextMenu>\n      </div>\n    );\n\n    const elementOutsideContextMenu = screen.getByTestId('some-element');\n\n    fireEvent.mouseDown(elementOutsideContextMenu);\n\n    expect(onDismiss).toHaveBeenCalledOnce();\n  });\n\n  it('right clicking outside the context menu should call onDismiss', () => {\n    const onDismiss = jest.fn();\n    renderWithProviders(\n      <div>\n        <div data-testid=\"some-element\" />\n        <ContextMenu isOpen onDismiss={onDismiss}>\n          <ContextMenuComponents.MenuButton onClick={noop}>\n            {'this is a button'}\n          </ContextMenuComponents.MenuButton>\n          <ContextMenuComponents.MenuLink href=\"/\">\n            {'this is a link'}\n          </ContextMenuComponents.MenuLink>\n          <ContextMenuComponents.MenuLabel>\n            {'this is neither a button nor a link'}\n          </ContextMenuComponents.MenuLabel>\n        </ContextMenu>\n      </div>\n    );\n\n    const elementOutsideContextMenu = screen.getByTestId('some-element');\n\n    fireEvent.mouseDown(elementOutsideContextMenu, { button: 'right' });\n\n    expect(onDismiss).toHaveBeenCalledOnce();\n  });\n\n  it('should focus the first focusable element when the menu is opened', () => {\n    // need menu to start closed since focus gets changed\n    // when the menu goes from closed -> open\n    const { rerender } = renderWithProviders(\n      <ContextMenu isOpen={false}>\n        <ContextMenuComponents.MenuButton onClick={noop}>\n          {'this is a button'}\n        </ContextMenuComponents.MenuButton>\n        <ContextMenuComponents.MenuLink href=\"/\">\n          {'this is a link'}\n        </ContextMenuComponents.MenuLink>\n        <ContextMenuComponents.MenuLabel>\n          {'this is neither a button nor a link'}\n        </ContextMenuComponents.MenuLabel>\n      </ContextMenu>\n    );\n\n    rerender(\n      <ContextMenu isOpen>\n        <ContextMenuComponents.MenuButton onClick={noop}>\n          {'this is a button'}\n        </ContextMenuComponents.MenuButton>\n        <ContextMenuComponents.MenuLink href=\"/\">\n          {'this is a link'}\n        </ContextMenuComponents.MenuLink>\n        <ContextMenuComponents.MenuLabel>\n          {'this is neither a button nor a link'}\n        </ContextMenuComponents.MenuLabel>\n      </ContextMenu>\n    );\n\n    // opening the menu should focus the first focusable item\n    const [button] = screen.queryAllByRole('menuitem', {\n      name: items[0].label,\n    });\n\n    expect(button).toHaveFocus();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/contextMenu/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { RefObject, SyntheticEvent } from 'react';\n\nexport interface InnerContextMenuProps {\n  onFocus?: (e: SyntheticEvent) => void;\n  disableControlledTabNavigation?: boolean;\n  isOpen?: boolean;\n  onCloseSubMenu?: () => void;\n  isIconMenu?: boolean;\n  isSubMenu?: boolean;\n  isSecondary?: boolean;\n  isRTL?: boolean;\n  parentMenuRef: RefObject<HTMLElement>;\n  dismissOnEscape?: boolean;\n}\n\nexport interface ContextMenuProps extends InnerContextMenuProps {\n  animate?: boolean;\n  'aria-label'?: string;\n  id?: string;\n  isOpen?: boolean;\n  onDismiss?: (evt?: Event) => void;\n  isAlwaysVisible?: boolean;\n  isRTL?: boolean;\n  isInline?: boolean;\n  isHorizontal?: boolean;\n  popoverZIndex?: number;\n}\n\nexport interface ContextMenuState {\n  focusedId: string | null;\n  isIconMenu: boolean;\n  isHorizontal: boolean;\n}\n\nexport interface ContextMenuActions {\n  onDismiss: (evt?: Event) => void;\n  onMenuItemBlur: () => void;\n  onMenuItemFocus: (id: string) => void;\n  setFocusedId: (id: string | null) => void;\n}\n\nexport interface ContextMenuProvider {\n  state: ContextMenuState;\n  actions: ContextMenuActions;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/container.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useRef,\n  useState,\n  useFocusOut,\n  useMemo,\n  forwardRef,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport type { ForwardedRef } from 'react';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type { StyleOverride } from '../../types/theme';\nimport SearchInput from './searchInput';\nimport type { AbstractOption, OptionsContainerProps } from './types';\nimport { isKeywordFilterable } from './utils';\n\nconst Container = styled.div<{\n  isInline?: boolean;\n  hasDropDownBorder?: boolean;\n  $containerStyleOverrides?: StyleOverride;\n}>`\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  width: 100%;\n  min-width: 120px;\n  z-index: 2;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  padding: 5px;\n  margin-top: 16px;\n\n  ${({ isInline }) =>\n    isInline &&\n    css`\n      position: absolute;\n      margin-top: 0;\n      padding: 0;\n      min-width: initial;\n      width: initial;\n    `}\n\n  ${({ theme, hasDropDownBorder }) =>\n    hasDropDownBorder &&\n    css`\n      border: 1px solid ${theme.colors.border.defaultNormal};\n    `}\n\n   ${({ $containerStyleOverrides }) => $containerStyleOverrides};\n`;\n\nfunction OptionsContainerWithRef<O extends AbstractOption>(\n  {\n    onClose,\n    isOpen,\n    getOptionsByQuery,\n    hasSearch,\n    renderContents,\n    isInline,\n    hasDropDownBorder = false,\n    containerStyleOverrides,\n    title,\n    placeholder,\n  }: OptionsContainerProps<O>,\n  inputRef: ForwardedRef<HTMLInputElement>\n) {\n  const ref = useRef<HTMLDivElement>(null);\n  const [searchKeyword, setSearchKeyword] = useState('');\n  const [queriedOptions, setQueriedOptions] = useState<O[] | null>(null);\n  const [isExpanded, setIsExpanded] = useState(true);\n  const [trigger, setTrigger] = useState(0);\n\n  useFocusOut(ref, onClose, [onClose]);\n\n  const debounceHandleLoadOptions = useDebouncedCallback(\n    () => void getOptionsByQuery?.(searchKeyword)?.then(setQueriedOptions),\n    500\n  );\n\n  useEffect(() => {\n    if (getOptionsByQuery && isKeywordFilterable(searchKeyword)) {\n      debounceHandleLoadOptions();\n    } else {\n      setQueriedOptions(null);\n    }\n  }, [getOptionsByQuery, searchKeyword, debounceHandleLoadOptions]);\n\n  useEffect(() => {\n    if (isOpen && inputRef && 'current' in inputRef && inputRef.current) {\n      inputRef.current.focus();\n    }\n  }, [isOpen, inputRef]);\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  return (\n    <Container\n      role=\"dialog\"\n      title={title}\n      ref={ref}\n      isInline={isInline}\n      hasDropDownBorder={hasDropDownBorder}\n      $containerStyleOverrides={containerStyleOverrides}\n    >\n      {hasSearch && (\n        <SearchInput\n          ref={inputRef}\n          value={searchKeyword}\n          onChange={setSearchKeyword}\n          onClose={onClose}\n          isExpanded={isExpanded}\n          focusFontListFirstOption={() => setTrigger((v) => v + 1)}\n          aria-owns={listId}\n          placeholder={placeholder}\n        />\n      )}\n      {renderContents({\n        searchKeyword,\n        setIsExpanded,\n        trigger,\n        queriedOptions,\n        listId,\n      })}\n    </Container>\n  );\n}\n\n// This cast is really annoying, but required to make a forwardRef'ed component\n// accept a generic type argument.\n// @see https://fettblog.eu/typescript-react-generic-forward-refs/\nconst OptionsContainer = forwardRef(OptionsContainerWithRef) as <\n  O extends AbstractOption,\n>(\n  props: OptionsContainerProps<O> & {\n    ref?: ForwardedRef<HTMLDivElement>;\n  }\n) => ReturnType<typeof OptionsContainerWithRef>;\n\nexport default OptionsContainer;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/datalist.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useRef,\n  forwardRef,\n  useDebouncedCallback,\n  useEffect,\n} from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport type { ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\nimport useForwardedRef from '../../utils/useForwardedRef';\nimport { DropDownSelect } from '../dropDown';\nimport { Popup } from '../popup';\nimport OptionsContainer from './container';\nimport OptionList from './list';\nimport type { AbstractOption, DataListProps } from './types';\n\nconst focusStyle = css`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst DEFAULT_WIDTH = 240;\n\nconst Container = styled.div`\n  display: flex;\n  flex-direction: column;\n  flex-grow: 1;\n`;\n\nconst Datalist = forwardRef(function Datalist<O extends AbstractOption>(\n  {\n    onChange,\n    disabled = false,\n    selectedId,\n    options,\n    hasSearch = false,\n    getOptionsByQuery,\n    onObserve,\n    primaryOptions,\n    primaryLabel,\n    priorityOptionGroups,\n    searchResultsLabel,\n    renderer,\n    activeItemRenderer,\n    isInline = false,\n    dropDownLabel = '',\n    highlightStylesOverride,\n    hasDropDownBorder = false,\n    zIndex,\n    listStyleOverrides,\n    containerStyleOverrides,\n    title,\n    dropdownButtonLabel,\n    className,\n    offsetOverride = false,\n    noMatchesFoundLabel,\n    searchPlaceholder,\n    maxWidth,\n    getPrimaryOptions,\n    ...rest\n  }: DataListProps<O>,\n  forwardedRef: ForwardedRef<HTMLButtonElement>\n) {\n  const ref = useForwardedRef(forwardedRef);\n  const searchRef = useRef<HTMLInputElement>(null);\n  const listRef = useRef<HTMLDivElement>(null);\n  if (!options && !getOptionsByQuery) {\n    throw new Error(\n      'Dropdown initiated with invalid params: options or getOptionsByQuery has to be set'\n    );\n  }\n  // If search is not enabled, always display all options.\n  if (!hasSearch) {\n    primaryOptions = options;\n  }\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [_primaryOptions, _setPrimaryOptions] = useState<O[]>([]);\n\n  const closeDropDown = useCallback(() => {\n    setIsOpen(false);\n    // Restore focus\n    ref.current?.focus();\n  }, [ref]);\n\n  const toggleDropDown = useCallback(() => setIsOpen((val) => !val), []);\n  // Must be debounced to account for clicking the select box again\n  // (closing in useFocusOut and then opening again in onClick)\n  const debouncedCloseDropDown = useDebouncedCallback(closeDropDown, 100);\n\n  const handleSelect = useCallback(\n    (option: O) => {\n      onChange(option);\n      setIsOpen(false);\n      ref.current?.focus();\n    },\n    [onChange, ref]\n  );\n\n  const focusSearch = useCallback(() => {\n    searchRef.current?.focus();\n  }, []);\n\n  const list = (\n    <OptionsContainer\n      ref={searchRef}\n      isOpen={isOpen}\n      onClose={debouncedCloseDropDown}\n      getOptionsByQuery={getOptionsByQuery}\n      hasSearch={hasSearch}\n      isInline={isInline}\n      title={title}\n      hasDropDownBorder={hasDropDownBorder}\n      containerStyleOverrides={containerStyleOverrides}\n      placeholder={searchPlaceholder}\n      renderContents={({\n        searchKeyword,\n        setIsExpanded,\n        trigger,\n        queriedOptions,\n        listId,\n      }) => (\n        <OptionList\n          ref={listRef}\n          listId={listId}\n          value={selectedId}\n          keyword={searchKeyword}\n          onSelect={handleSelect}\n          onClose={debouncedCloseDropDown}\n          onExpandedChange={setIsExpanded}\n          focusTrigger={trigger}\n          onObserve={onObserve}\n          options={options || queriedOptions}\n          primaryOptions={_primaryOptions}\n          primaryLabel={primaryLabel}\n          priorityOptionGroups={priorityOptionGroups}\n          searchResultsLabel={searchResultsLabel}\n          focusSearch={focusSearch}\n          renderer={renderer}\n          listStyleOverrides={listStyleOverrides}\n          noMatchesFoundLabel={noMatchesFoundLabel}\n        />\n      )}\n    />\n  );\n\n  // Logic for fetching primaryOptions\n  useEffect(() => {\n    if (getPrimaryOptions) {\n      void getPrimaryOptions().then((res) => {\n        _setPrimaryOptions(res);\n      });\n    } else if (primaryOptions) {\n      _setPrimaryOptions(primaryOptions);\n    }\n  }, [\n    _setPrimaryOptions,\n    getOptionsByQuery,\n    getPrimaryOptions,\n    primaryOptions,\n  ]);\n\n  const selectedOption = _primaryOptions.find(({ id }) => id === selectedId);\n  // In case of isInline, the list is displayed with 'absolute' positioning instead of using a separate popup.\n  return (\n    <Container className={className}>\n      <DropDownSelect\n        aria-pressed={isOpen}\n        aria-haspopup\n        aria-expanded={isOpen}\n        ref={ref}\n        activeItemLabel={selectedOption?.name}\n        activeItemRenderer={activeItemRenderer}\n        dropDownLabel={dropDownLabel}\n        onSelectClick={toggleDropDown}\n        selectButtonStylesOverride={highlightStylesOverride || focusStyle}\n        aria-label={dropdownButtonLabel}\n        isOpen={isOpen}\n        disabled={disabled}\n        {...rest}\n      />\n      {isOpen && !disabled && isInline && list}\n      {!disabled && !isInline && (\n        <Popup\n          anchor={ref}\n          isOpen={isOpen}\n          zIndex={zIndex}\n          offsetOverride={offsetOverride}\n          maxWidth={maxWidth || DEFAULT_WIDTH}\n          fillWidth\n        >\n          {list}\n        </Popup>\n      )}\n    </Container>\n  );\n});\n\nexport default Datalist;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as DatalistDropdown } from './datalist';\nexport {\n  ListElement as DatalistOption,\n  Selected as DatalistSelected,\n} from './list/styled';\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/list/defaultRenderer.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\nimport { forwardRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { AbstractOption, OptionRendererProps } from '../types';\nimport { ListElement, Selected, OverflowEllipses } from './styled';\n\nfunction DefaultRendererWithRef<O extends AbstractOption>(\n  { option, value, ...rest }: OptionRendererProps<O>,\n  ref: ForwardedRef<HTMLLIElement>\n) {\n  return (\n    <ListElement key={option.id} {...rest} ref={ref}>\n      {value === option.id && (\n        <Selected aria-label={__('Selected', 'web-stories')} />\n      )}\n      <OverflowEllipses>{option.name}</OverflowEllipses>\n    </ListElement>\n  );\n}\n\n// This cast is really annoying, but required to make a forwardRef'ed component\n// accept a generic type argument.\n// @see https://fettblog.eu/typescript-react-generic-forward-refs/\nconst DefaultRenderer = forwardRef(DefaultRendererWithRef) as <\n  O extends AbstractOption,\n>(\n  props: OptionRendererProps<O> & {\n    ref?: ForwardedRef<HTMLLIElement>;\n  }\n) => ReturnType<typeof DefaultRendererWithRef>;\n\nexport default DefaultRenderer;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/list/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './list';\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/list/list.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  useCallback,\n  useLayoutEffect,\n  useFocusOut,\n  forwardRef,\n  memo,\n} from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport type { ForwardedRef, KeyboardEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../utils/noop';\nimport useForwardedRef from '../../../utils/useForwardedRef';\nimport { TextSize } from '../../../theme';\nimport { Text } from '../../typography';\nimport {\n  createOptionFilter,\n  isKeywordFilterable,\n  getOptions,\n  addUniqueEntries,\n  getInset,\n} from '../utils';\nimport type { AbstractOption, OptionListProps } from '../types';\nimport { List, GroupList, GroupLabel, NoResult } from './styled';\nimport DefaultRenderer from './defaultRenderer';\n\nconst StyledLabel = styled(Text.Span).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nfunction OptionListWithRef<O extends AbstractOption>(\n  {\n    keyword = '',\n    value = '',\n    onSelect = noop,\n    onClose = noop,\n    onExpandedChange = noop,\n    focusTrigger = 0,\n    options = [],\n    primaryOptions,\n    primaryLabel,\n    priorityOptionGroups = [],\n    searchResultsLabel,\n    renderer: OptionRenderer = DefaultRenderer,\n    onObserve,\n    focusSearch = noop,\n    listId,\n    listStyleOverrides,\n    noMatchesFoundLabel = __('No matches found', 'web-stories'),\n  }: OptionListProps<O>,\n  forwardedListRef: ForwardedRef<HTMLDivElement>\n) {\n  const listRef = useForwardedRef(forwardedListRef);\n  const optionsRef = useRef<(HTMLLIElement | null)[]>([]);\n  const [focusIndex, setFocusIndex] = useState(-1);\n  const userSeenOptionsRef = useRef<string[]>([]);\n\n  /*\n   * KEYWORD FILTERING\n   */\n  const filteredListGroups = useMemo(() => {\n    // If we're searching, return a single group of search results\n    // gotten from all available options\n    if (isKeywordFilterable(keyword) && options) {\n      return [\n        {\n          label: searchResultsLabel,\n          options: createOptionFilter(options)(keyword),\n        },\n      ];\n    }\n    // Otherwise return primary options in one group possibly preceded\n    // by an optional groups of priority options if such exist.\n    return [\n      ...(priorityOptionGroups?.length ? priorityOptionGroups : []),\n      {\n        label: primaryLabel,\n        options: primaryOptions,\n      },\n    ];\n  }, [\n    keyword,\n    options,\n    priorityOptionGroups,\n    primaryOptions,\n    primaryLabel,\n    searchResultsLabel,\n  ]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  const currentListRef = listRef.current;\n\n  /*\n   * LAZY OPTIONS LOADING\n   */\n  // Add option when observed entry is seen\n  const observer = useMemo(() => {\n    if (!currentListRef) {\n      return null;\n    }\n    return new window.IntersectionObserver(\n      (entries) => {\n        if (onObserve) {\n          const newlySeenOptions: string[] = entries\n            .filter((entry) => entry.isIntersecting)\n            .map((entry) => entry.target)\n            .filter((t): t is HTMLElement => t instanceof HTMLElement)\n            .map((target) => target.dataset.option)\n            .filter((o): o is string => Boolean(o));\n          userSeenOptionsRef.current = addUniqueEntries(\n            userSeenOptionsRef.current,\n            ...newlySeenOptions\n          );\n          onObserve(userSeenOptionsRef.current);\n        }\n      },\n      {\n        root: currentListRef,\n        // Gets ~2 extra items below scroll container BoundingBox\n        rootMargin: '60px',\n      }\n    );\n  }, [onObserve, currentListRef]);\n\n  // Observe rendered font options\n  useLayoutEffect(() => {\n    const renderedOptions = optionsRef.current;\n    if (onObserve) {\n      renderedOptions.forEach((option) => option && observer?.observe(option));\n    }\n    return () => {\n      if (onObserve) {\n        renderedOptions.forEach(\n          (option) => option && observer?.unobserve(option)\n        );\n      }\n      // clear existing option references before next update to filteredGroup\n      optionsRef.current = [];\n    };\n  }, [observer, onObserve, filteredListGroups, OptionRenderer]);\n\n  /*\n   * KEYBOARD ACCESSIBILITY\n   */\n  const filteredOptions = useMemo(\n    () => getOptions(filteredListGroups),\n    [filteredListGroups]\n  );\n\n  const handleKeyPress = useCallback(\n    (evt: KeyboardEvent) => {\n      const { key } = evt;\n\n      evt.stopPropagation();\n      evt.preventDefault();\n\n      if (key === 'Tab' && evt.shiftKey) {\n        focusSearch();\n      }\n\n      if (key === 'Escape') {\n        onClose();\n      } else if (key === 'Enter') {\n        if (filteredOptions[focusIndex]) {\n          onSelect(filteredOptions[focusIndex]);\n        }\n      } else if (key === 'ArrowUp') {\n        setFocusIndex((index) => Math.max(0, index - 1));\n      } else if (key === 'ArrowDown') {\n        setFocusIndex((index) =>\n          Math.min(filteredOptions.length - 1, index + 1)\n        );\n      }\n    },\n    [focusIndex, filteredOptions, onClose, onSelect, focusSearch]\n  );\n\n  useFocusOut(listRef, () => setFocusIndex(-1), []);\n\n  // scroll into view and focus focusIndex\n  useEffect(() => {\n    const listEl = listRef.current;\n    if (!listEl) {\n      return;\n    }\n    if (focusIndex === -1) {\n      listEl.scrollTo(0, 0);\n      return;\n    }\n\n    const highlightedOptionEl = optionsRef.current[focusIndex];\n    if (!highlightedOptionEl) {\n      return;\n    }\n\n    highlightedOptionEl.focus();\n    listEl.scrollTo(0, highlightedOptionEl.offsetTop - listEl.clientHeight / 2);\n  }, [focusIndex, filteredOptions, keyword, onClose, listRef]);\n\n  /*\n   * ACCESSIBILITY COMMUNICATION WITH SEARCH INPUT\n   */\n  const isExpanded = filteredOptions.length > 0;\n  useEffect(() => onExpandedChange(isExpanded), [onExpandedChange, isExpanded]);\n  useEffect(() => {\n    if (focusTrigger > 0) {\n      setFocusIndex(0);\n    }\n  }, [focusTrigger]);\n\n  return filteredOptions.length <= 0 ? (\n    <NoResult>{noMatchesFoundLabel}</NoResult>\n  ) : (\n    <List\n      ref={listRef}\n      tabIndex={0}\n      id={listId}\n      role=\"listbox\"\n      onKeyDown={handleKeyPress}\n      aria-label={__('Option List Selector', 'web-stories')}\n      aria-required={false}\n      $listStyleOverrides={listStyleOverrides}\n    >\n      {filteredListGroups.map((group, i) => {\n        const groupLabelId = `group-${uuidv4()}`;\n        return (\n          group.options.length > 0 && (\n            <GroupList\n              key={groupLabelId}\n              role=\"group\"\n              aria-labelledby={groupLabelId}\n            >\n              {group.label && (\n                <GroupLabel id={groupLabelId} role=\"presentation\">\n                  <StyledLabel>{group.label}</StyledLabel>\n                </GroupLabel>\n              )}\n              {group.options.map((option, j) => {\n                const optionInset = getInset(filteredListGroups, i, j);\n\n                return (\n                  <OptionRenderer\n                    key={option.id || ''}\n                    role={'option'}\n                    tabIndex={-1}\n                    aria-selected={value === option.id}\n                    aria-posinset={optionInset + 1}\n                    aria-setsize={filteredOptions.length}\n                    data-option={option.id}\n                    onClick={() => onSelect(option)}\n                    ref={(el: HTMLLIElement | null) =>\n                      (optionsRef.current[optionInset] = el)\n                    }\n                    option={option}\n                    value={value}\n                  />\n                );\n              })}\n            </GroupList>\n          )\n        );\n      })}\n    </List>\n  );\n}\n\n// This cast is really annoying, but required to make a forwardRef'ed component\n// accept a generic type argument.\n// @see https://fettblog.eu/typescript-react-generic-forward-refs/\nconst OptionList = memo(forwardRef(OptionListWithRef)) as <\n  O extends AbstractOption,\n>(\n  props: OptionListProps<O> & {\n    ref?: ForwardedRef<HTMLDivElement>;\n  }\n) => ReturnType<typeof OptionListWithRef>;\n\nexport default OptionList;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/list/styled.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { Checkmark } from '../../../icons';\nimport { Text } from '../../typography';\nimport type { StyleOverride } from '../../../types/theme';\n\nexport const List = styled.div<{ $listStyleOverrides?: StyleOverride }>`\n  width: 100%;\n  overflow-x: visible;\n  overflow-y: auto;\n  overscroll-behavior: none auto;\n  max-height: 305px;\n  padding: 4px;\n  margin: 10px 0 0 0;\n  font-size: 14px;\n  text-align: left;\n  list-style: none;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  ${themeHelpers.focusableOutlineCSS}\n\n  ${({ $listStyleOverrides }) => $listStyleOverrides}\n`;\n\nexport const GroupList = styled.ul`\n  margin: 0;\n  padding: 0;\n`;\n\nexport const GroupLabel = styled.li`\n  background: transparent;\n  padding: 8px;\n  margin: 0;\n`;\n\nexport const ListElement = styled.li.attrs<{ fontFamily?: string }>(\n  ({ fontFamily }) => ({\n    style: {\n      fontFamily,\n    },\n  })\n)`\n  display: flex;\n  align-items: center;\n  position: relative;\n  padding: 6px 16px;\n  margin: 6px 0 0 0;\n  cursor: pointer;\n  background-clip: padding-box;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  ${themeHelpers.expandTextPreset(({ label }, { Small }) => label[Small])}\n  ${themeHelpers.focusableOutlineCSS}\n\n  /* override preset line-height to avoid letters being cut off */\n  line-height: 16px;\n\n  :first-of-type {\n    margin-top: 0;\n  }\n\n  :hover {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.tertiaryHover};\n  }\n\n  :focus {\n    outline: none;\n  }\n`;\n\nexport const Selected = styled(Checkmark)`\n  width: 16px;\n  min-width: 16px;\n  height: auto;\n  margin-right: 4px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nexport const NoResult = styled(Text.Paragraph).attrs(() => ({\n  size: TextSize.XSmall,\n}))`\n  width: 100%;\n  padding: 13px 11px;\n  margin: 0;\n  text-align: center;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nexport const OverflowEllipses = styled.span`\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/searchInput.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef, useCallback } from '@googleforcreators/react';\nimport type { ForwardedRef, KeyboardEvent } from 'react';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\nimport { Magnifier, Cross } from '../../icons';\nimport { Button, ButtonVariant } from '../button';\nimport { noop } from '../../utils';\nimport type { SearchInputProps } from './types';\n\nconst SearchContainer = styled.div`\n  position: relative;\n  width: 100%;\n`;\n\nconst inputIconStyles = css`\n  position: absolute;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  top: 50%;\n  width: 30px;\n  padding: 0;\n  margin: 0;\n  transform: translateY(-50%);\n  background-color: transparent;\n  border: none;\n\n  > svg {\n    height: 100%;\n    width: auto;\n    color: ${({ theme }) => theme.colors.fg.primary};\n    fill: ${({ theme }) => theme.colors.fg.primary};\n  }\n`;\n\nconst SearchIconContainer = styled.div`\n  ${inputIconStyles}\n  left: 0;\n  height: 28px;\n`;\n\nconst ClearButton = styled(Button).attrs({ variant: ButtonVariant.Icon })`\n  ${inputIconStyles};\n  right: 0;\n  height: 20.5px;\n  opacity: 0.4;\n`;\n\nconst Input = styled.input.attrs({\n  type: 'search',\n  role: 'combobox',\n  ['aria-autocomplete']: 'list',\n})`\n  width: 100%;\n  padding: 6px 20px 6px 30px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  background: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultActive};\n  color: ${({ theme }) => theme.colors.fg.primary};\n  ${themeHelpers.expandTextPreset(\n    ({ paragraph }, { Small }) => paragraph[Small]\n  )}\n\n  &::-ms-clear {\n    display: none;\n  }\n\n  &:placeholder-shown {\n    text-overflow: ellipsis;\n  }\n  &::-webkit-input-placeholder {\n    /* Chrome/Opera/Safari */\n    text-overflow: ellipsis;\n  }\n  &::-moz-placeholder {\n    /* Firefox 19+ */\n    text-overflow: ellipsis;\n  }\n  &::-webkit-search-decoration,\n  &::-webkit-search-cancel-button,\n  &::-webkit-search-results-button,\n  &::-webkit-search-results-decoration {\n    appearance: none;\n  }\n\n  &:focus {\n    border-color: ${({ theme }) => theme.colors.border.focus};\n  }\n`;\n\nconst MAX_INPUT_SIZE = 35;\n\nconst SearchInput = forwardRef(function SearchInput(\n  {\n    isExpanded,\n    onClose,\n    value,\n    onChange,\n    focusFontListFirstOption = noop,\n    placeholder = __('Search', 'web-stories'),\n    ...rest\n  }: SearchInputProps,\n  ref: ForwardedRef<HTMLInputElement>\n) {\n  const handleKeyPress = useCallback(\n    (evt: KeyboardEvent<HTMLInputElement>) => {\n      evt.stopPropagation();\n\n      const { key } = evt;\n\n      if (key === 'Escape') {\n        onClose();\n      } else if (key === 'ArrowDown') {\n        focusFontListFirstOption();\n      }\n    },\n    [onClose, focusFontListFirstOption]\n  );\n\n  return (\n    <SearchContainer>\n      <Input\n        ref={ref}\n        aria-expanded={isExpanded}\n        value={value}\n        onKeyDown={handleKeyPress}\n        placeholder={placeholder}\n        size={Math.min(placeholder.length, MAX_INPUT_SIZE)}\n        onChange={(evt) => onChange(evt.target.value)}\n        aria-label={__('Search', 'web-stories')}\n        {...rest}\n      />\n      <SearchIconContainer>\n        <Magnifier />\n      </SearchIconContainer>\n      {value.trim().length > 0 && (\n        <ClearButton onClick={() => onChange('')}>\n          <Cross />\n        </ClearButton>\n      )}\n    </SearchContainer>\n  );\n});\n\nexport default SearchInput;\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  ComponentPropsWithoutRef,\n  FunctionComponent,\n  HTMLAttributes,\n  RefAttributes,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { StyleOverride } from '../../types/theme';\n\nexport interface AbstractOption {\n  id: string;\n  name: string;\n}\n\nexport interface Group<O extends AbstractOption> {\n  label: string;\n  options: O[];\n}\n\n// !! Here be dragons !!\nexport type OptionRendererProps<O extends AbstractOption> =\n  HTMLAttributes<HTMLLIElement> &\n    RefAttributes<HTMLLIElement> & {\n      option: O;\n      value: O['id'];\n    };\n\nexport type OptionRenderer<O extends AbstractOption> = FunctionComponent<\n  OptionRendererProps<O>\n>;\n\nexport interface OptionListProps<O extends AbstractOption> {\n  keyword?: string;\n  value?: O['id'];\n  options?: O[];\n  renderer?: OptionRenderer<O>;\n  onSelect?: (option: O) => void;\n  onClose?: () => void;\n  onExpandedChange?: (isExpanded: boolean) => void;\n  focusTrigger?: number;\n  primaryOptions: O[];\n  primaryLabel: string;\n  priorityOptionGroups?: Group<O>[];\n  searchResultsLabel: string;\n  onObserve?: (options: string[]) => void;\n  focusSearch?: () => void;\n  listId?: string;\n  listStyleOverrides?: StyleOverride;\n  noMatchesFoundLabel?: string;\n}\n\nexport type ContentRenderer<O> = (options: {\n  searchKeyword: string;\n  setIsExpanded: (isExpanded: boolean) => void;\n  trigger: number;\n  queriedOptions: O[] | null;\n  listId: string;\n}) => JSX.Element | null;\n\nexport interface OptionsContainerProps<O> {\n  isOpen: boolean;\n  onClose: () => void;\n  getOptionsByQuery?: (query: string) => Promise<O[]>;\n  hasSearch?: boolean;\n  renderContents: ContentRenderer<O>;\n  isInline?: boolean;\n  hasDropDownBorder?: boolean;\n  title?: string;\n  placeholder?: string;\n  containerStyleOverrides?: StyleOverride;\n}\n\nexport interface SearchInputProps extends Omit<\n  ComponentPropsWithoutRef<'input'>,\n  'type' | 'role' | 'aria-autocomplete' | 'onChange'\n> {\n  isExpanded: boolean;\n  onClose: () => void;\n  focusFontListFirstOption?: () => void;\n  value: string;\n  onChange: (value: string) => void;\n}\n\n// Either you specify options, or you specify a callback returning a promise. Not both, not neither.\nexport type DataListPropsOptions<O> =\n  | { options: O[]; getOptionsByQuery: never }\n  | { options: never; getOptionsByQuery: (query: string) => Promise<O[]> };\n\nexport type DataListProps<O extends AbstractOption> =\n  DataListPropsOptions<O> & {\n    onChange: (value: O) => void;\n    disabled?: boolean;\n    selectedId?: O['id'];\n    hasSearch?: boolean;\n    onObserve?: (options: string[]) => void;\n    primaryOptions: O[];\n    primaryLabel: string;\n    priorityOptionGroups?: Group<O>[];\n    searchResultsLabel: string;\n    renderer?: OptionRenderer<O>;\n    activeItemRender?: () => JSX.Element;\n    isInline?: boolean;\n    dropDownLabel: string;\n    zIndex?: number;\n    title?: string;\n    dropdownButtonLabel: string;\n    offsetOverride?: boolean;\n    maxWidth?: number;\n    activeItemRenderer?: FunctionComponent;\n    highlightStylesOverride?: StyleOverride;\n    hasDropDownBorder?: boolean;\n    listStyleOverrides?: StyleOverride;\n    containerStyleOverrides?: StyleOverride;\n    className?: string;\n    noMatchesFoundLabel?: string;\n    searchPlaceholder?: string;\n    getPrimaryOptions?: () => Promise<O[]>;\n  };\n"
  },
  {
    "path": "packages/design-system/src/components/datalist/utils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Group, AbstractOption } from './types';\n\nexport const createOptionFilter =\n  <O extends AbstractOption>(options: O[]) =>\n  (keyword: string) =>\n    options.filter(({ name }) =>\n      name.toLowerCase().includes(keyword.toLowerCase())\n    );\n\nexport const isKeywordFilterable = (keyword: string) =>\n  keyword.trim().length >= 2;\n\nexport const getOptions = <O extends AbstractOption>(groups: Group<O>[]) =>\n  groups.flatMap(({ options }) => options);\n\nexport const addUniqueEntries = <T>(array: T[], ...keys: T[]) => [\n  ...new Set(array.concat(keys)),\n];\n\nexport const getInset = <O extends AbstractOption>(\n  groups: Group<O>[],\n  i: number,\n  j: number\n) =>\n  groups\n    .slice(0, i)\n    .map((group) => group.options.length)\n    .reduce((a, b) => a + b, 0) + j;\n"
  },
  {
    "path": "packages/design-system/src/components/dialog/dialog.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentProps, PropsWithChildren, ReactElement } from 'react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../theme';\nimport { Modal } from '../modal';\nimport { Headline } from '../typography';\n\nconst DialogBox = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  max-width: 512px;\n  max-height: 100%;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  overflow-y: auto;\n  padding: 12px 16px;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  border: ${({ theme }) => `1px solid ${theme.colors.divider.primary}`};\n`;\n\nconst DialogContent = styled.div`\n  padding: 8px 0 12px;\n  margin: 0;\n  overflow-y: auto;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst DialogActions = styled.div`\n  display: flex;\n  justify-content: flex-end;\n  width: 100%;\n\n  & > button,\n  & > a {\n    margin-right: 10px;\n    margin-left: 6px;\n    &:last-child {\n      margin-right: 0;\n    }\n  }\n`;\n\n/**\n * @typedef {Object} DialogProps\n * @property {import('react').ReactNode} children Children.\n * @property {string} title Title.\n * @property {import('react').ReactNode[]} actions Actions.\n * @property {boolean} isOpen Whether the dialog is open.\n * @property {Function} onClose Close callback.\n * @property {string} contentLabel Content label.\n */\n\ntype ModalProps = ComponentProps<typeof Modal>;\ninterface DialogProps extends ModalProps {\n  title: string;\n  actions: ReactElement[];\n}\n\n/**\n * Dialog component.\n *\n * Dialogs should be wrapped in a ThemeProvider\n * and given the inverted theme to the app.\n */\nfunction Dialog({\n  children,\n  title,\n  actions = [],\n  isOpen = false,\n  onClose,\n  contentLabel,\n  ...rest\n}: PropsWithChildren<DialogProps>) {\n  return (\n    <Modal\n      isOpen={isOpen}\n      onClose={onClose}\n      contentLabel={contentLabel || title}\n      {...rest}\n    >\n      <DialogBox>\n        {Boolean(title) && (\n          <Headline as=\"h2\" size={TextSize.XSmall}>\n            {title}\n          </Headline>\n        )}\n        <DialogContent>{children}</DialogContent>\n        {Boolean(actions) && <DialogActions>{actions}</DialogActions>}\n      </DialogBox>\n    </Modal>\n  );\n}\n\nexport default Dialog;\n"
  },
  {
    "path": "packages/design-system/src/components/dialog/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Dialog } from './dialog';\n"
  },
  {
    "path": "packages/design-system/src/components/dialog/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { Button, ButtonSize, ButtonType } from '../../button';\nimport { Text } from '../../typography';\nimport { Dialog } from '..';\nimport { DarkThemeProvider } from '../../../storybookUtils/darkThemeProvider';\n\nexport default {\n  title: 'DesignSystem/Components/Dialog',\n  component: Dialog,\n  args: {\n    title: 'Headline',\n    message:\n      'Duka din veranda till fest, för en långväga gäst, i landet lagom är bäst.',\n  },\n  argTypes: {\n    onClick: { action: 'clicked' },\n  },\n  parameters: {\n    controls: {\n      include: ['title', 'message', 'onClick'],\n    },\n  },\n};\n\nconst InvertedWrapper = styled.div`\n  width: 100vw;\n  height: 100vh;\n  background-color: ${({ theme }) => theme.colors.inverted.bg.primary};\n`;\nexport const _default = {\n  render: function Render({ message, onClick, ...args }) {\n    const [toggleDialog, setToggleDialog] = useState(false);\n\n    const ActionsNode = (\n      <Button\n        size={ButtonSize.Small}\n        type={ButtonType.Primary}\n        onClick={() => {\n          onClick('button');\n          setToggleDialog(!toggleDialog);\n        }}\n      >\n        {'Primary'}\n      </Button>\n    );\n    return (\n      <InvertedWrapper>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => setToggleDialog(!toggleDialog)}\n        >\n          {'Toggle Dialog'}\n        </Button>\n        <Dialog\n          onClose={() => {\n            onClick('close dialog');\n            setToggleDialog(!toggleDialog);\n          }}\n          isOpen={toggleDialog}\n          contentLabel={'Dialog content Label for modal'}\n          actions={ActionsNode}\n          {...args}\n        >\n          <Text.Paragraph size={TextSize.Small}>{message}</Text.Paragraph>\n        </Dialog>\n      </InvertedWrapper>\n    );\n  },\n};\n\nexport const With2Actions = {\n  render: function Render({ message, onClick, ...args }) {\n    const [toggleDialog, setToggleDialog] = useState(false);\n\n    const ActionsNode = (\n      <>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Tertiary}\n          onClick={() => {\n            onClick('cancel button');\n            setToggleDialog(!toggleDialog);\n          }}\n        >\n          {'Secondary'}\n        </Button>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => {\n            onClick('primary button');\n          }}\n        >\n          {'Primary'}\n        </Button>\n      </>\n    );\n    return (\n      <InvertedWrapper>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => setToggleDialog(!toggleDialog)}\n        >\n          {'Toggle Dialog'}\n        </Button>\n        <Dialog\n          onClose={() => {\n            onClick('close dialog clicked');\n            setToggleDialog(!toggleDialog);\n          }}\n          isOpen={toggleDialog}\n          contentLabel={'Dialog content Label for modal'}\n          actions={ActionsNode}\n          {...args}\n        >\n          <Text.Paragraph size={TextSize.Small}>{message}</Text.Paragraph>\n        </Dialog>\n      </InvertedWrapper>\n    );\n  },\n};\n\nexport const With2ActionsDarkTheme = {\n  render: function Render({ message, onClick, ...args }) {\n    const [toggleDialog, setToggleDialog] = useState(false);\n\n    const ActionsNode = (\n      <>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Tertiary}\n          onClick={() => {\n            onClick('cancel button ');\n            setToggleDialog(!toggleDialog);\n          }}\n        >\n          {'Secondary'}\n        </Button>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => {\n            onClick('primary button ');\n          }}\n        >\n          {'Primary'}\n        </Button>\n      </>\n    );\n    return (\n      <DarkThemeProvider>\n        <InvertedWrapper>\n          <Button\n            size={ButtonSize.Small}\n            type={ButtonType.Primary}\n            onClick={() => setToggleDialog(!toggleDialog)}\n          >\n            {'Toggle Dialog'}\n          </Button>\n          <Dialog\n            onClose={() => {\n              onClick('close dialog');\n              setToggleDialog(!toggleDialog);\n            }}\n            isOpen={toggleDialog}\n            contentLabel={'Dialog content Label for modal'}\n            actions={ActionsNode}\n            {...args}\n          >\n            <Text.Paragraph size={TextSize.Small}>{message}</Text.Paragraph>\n          </Dialog>\n        </InvertedWrapper>\n      </DarkThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/dialog/test/dialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport Modal from 'react-modal';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport Dialog from '../dialog';\n\ndescribe('DesignSystem/Components/Dialog', () => {\n  it('should not render a dialog by default', () => {\n    const { container } = renderWithProviders(\n      <Dialog onClose={jest.fn}>\n        <p>{'dialog child'}</p>\n      </Dialog>\n    );\n\n    Modal.setAppElement(container);\n\n    expect(\n      screen.queryByRole('dialog', { hidden: true })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render a dialog when isOpen is true', () => {\n    const mockButtonClick = jest.fn();\n    const ActionsNode = (\n      <button onClick={mockButtonClick}>{'dialog button'}</button>\n    );\n\n    const { container } = renderWithProviders(\n      <Dialog\n        onClose={jest.fn}\n        isOpen\n        title=\"dialog title\"\n        actions={ActionsNode}\n      >\n        <p>{'dialog child'}</p>\n      </Dialog>\n    );\n\n    Modal.setAppElement(container);\n\n    expect(screen.getByRole('dialog')).toBeInTheDocument();\n    const dialogButton = screen.getByText('dialog button');\n\n    fireEvent.click(dialogButton);\n    expect(mockButtonClick).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/disclosure/disclosure.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { THEME_CONSTANTS } from '../../theme';\nimport { ChevronDownSmall } from '../../icons';\n\ntype Direction = 'up' | 'down' | 'left' | 'right';\nconst rotate: Record<Direction, [number, number]> = {\n  up: [180, 0],\n  down: [0, 180],\n  left: [-90, 0],\n  right: [90, 0],\n};\n/**\n * Simple component that shows a chevron icon which rotates when\n * controlled contents are shown (open). Values for `direction` prop of\n * 'up' or 'down' rotate icon 180deg, and 'right' or 'left' rotate down.\n */\nconst Disclosure = styled(ChevronDownSmall)<{\n  direction?: Direction;\n  disabled?: boolean;\n  duration?: number;\n  $isOpen?: boolean;\n}>`\n  height: ${THEME_CONSTANTS.ICON_SIZE}px;\n  width: auto;\n  margin: 0 -10px;\n  color: ${({ disabled, theme }) =>\n    disabled ? theme.colors.fg.disable : theme.colors.fg.secondary};\n  transition: transform ${({ duration = 0 }) => duration};\n  transform: ${({ direction = 'down', $isOpen = false }) => {\n    const [whenClosed, whenOpen] = rotate[direction];\n    return `rotate(${$isOpen ? whenOpen : whenClosed}deg);`;\n  }};\n`;\n\nexport default Disclosure;\n"
  },
  {
    "path": "packages/design-system/src/components/disclosure/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Disclosure } from './disclosure';\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../theme';\nimport { Text } from '../typography';\n\nexport const DropDownContainer = styled.div`\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n`;\n\nexport const Hint = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})<{ hasError?: boolean }>`\n  margin-top: 12px;\n  padding-left: 2px;\n  color: ${({ theme, hasError }) =>\n    hasError ? theme.colors.fg.negative : theme.colors.fg.tertiary};\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/dropdown.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  forwardRef,\n  useCallback,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\nimport type { ForwardedRef, RefObject, UIEvent } from 'react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Menu } from '../menu';\nimport type { DropdownValue } from '../menu';\nimport { Popup, Placement } from '../popup';\nimport useForwardedRef from '../../utils/useForwardedRef';\nimport { DropDownContainer, Hint } from './components';\nimport DropDownSelect from './select';\nimport useDropDown from './useDropDown';\nimport type { DropDownProps } from './types';\n\nconst DropDown = forwardRef(function DropDown(\n  {\n    ariaLabel,\n    disabled,\n    dropDownLabel,\n    hasError,\n    hint,\n    isKeepMenuOpenOnSelection,\n    onMenuItemClick,\n    options = [],\n    placement = Placement.Bottom,\n    popupFillWidth = true,\n    popupZIndex,\n    isInline = false,\n    selectedValue = '',\n    direction = 'down',\n    className,\n    ...rest\n  }: DropDownProps,\n  forwardedRef: ForwardedRef<HTMLButtonElement>\n) {\n  const ref = useForwardedRef(forwardedRef);\n  const [dynamicPlacement, setDynamicPlacement] = useState(placement);\n\n  const { activeOption, setIsOpen, isOpen, groups } = useDropDown({\n    options,\n    selectedValue,\n  });\n\n  const positionPlacement = useCallback(\n    (popupRef: RefObject<Element>) => {\n      if (!popupRef.current) {\n        return;\n      }\n\n      // check to see if there's an overlap with the window edge\n      const { bottom, top } = popupRef.current.getBoundingClientRect();\n\n      // if the popup was assigned as bottom we want to always check it\n      if (\n        dynamicPlacement.startsWith('bottom') &&\n        bottom >= window.innerHeight\n      ) {\n        setDynamicPlacement(Placement.Top);\n      }\n      // if the popup was assigned as top we want to always check it\n      if (dynamicPlacement.startsWith('top') && top <= 0) {\n        setDynamicPlacement(Placement.Bottom);\n      }\n    },\n    [dynamicPlacement]\n  );\n\n  const handleSelectClick = useCallback(\n    (event: UIEvent<HTMLButtonElement>) => {\n      event.preventDefault();\n      setIsOpen((prevIsOpen) => !prevIsOpen);\n    },\n    [setIsOpen]\n  );\n\n  const handleDismissMenu = useCallback(() => {\n    setIsOpen(false);\n    ref.current?.focus();\n    setDynamicPlacement(placement);\n  }, [setIsOpen, ref, placement]);\n\n  const handleMenuItemClick = useCallback(\n    (event: Event, menuItem: DropdownValue) => {\n      onMenuItemClick?.(event, menuItem);\n\n      if (!isKeepMenuOpenOnSelection) {\n        handleDismissMenu();\n      }\n    },\n    [handleDismissMenu, isKeepMenuOpenOnSelection, onMenuItemClick]\n  );\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const selectButtonId = useMemo(() => `select-button-${uuidv4()}`, []);\n\n  const menu = (\n    <Menu\n      activeValue={activeOption?.value}\n      parentId={selectButtonId}\n      listId={listId}\n      menuAriaLabel={sprintf(\n        /* translators: %s: dropdown aria label or general dropdown label if there is no specific aria label. */\n        __('%s Option List Selector', 'web-stories'),\n        ariaLabel || dropDownLabel\n      )}\n      onDismissMenu={handleDismissMenu}\n      handleMenuItemSelect={handleMenuItemClick}\n      groups={groups}\n      isAbsolute={isInline}\n      {...rest}\n    />\n  );\n\n  return (\n    <DropDownContainer className={className}>\n      <DropDownSelect\n        activeItemLabel={activeOption?.label}\n        aria-pressed={isOpen}\n        aria-disabled={disabled}\n        aria-expanded={isOpen}\n        aria-label={ariaLabel || dropDownLabel}\n        aria-owns={listId}\n        disabled={disabled}\n        dropDownLabel={dropDownLabel}\n        hasError={hasError}\n        id={selectButtonId}\n        isOpen={isOpen}\n        onSelectClick={handleSelectClick}\n        direction={direction}\n        ref={ref}\n        {...rest}\n      />\n      {!disabled && isInline ? (\n        isOpen && menu\n      ) : (\n        <Popup\n          anchor={ref}\n          isOpen={isOpen}\n          placement={dynamicPlacement}\n          refCallback={positionPlacement}\n          fillWidth={popupFillWidth}\n          zIndex={popupZIndex}\n          ignoreMaxOffsetY\n        >\n          {menu}\n        </Popup>\n      )}\n      {hint && <Hint hasError={hasError}>{hint}</Hint>}\n    </DropDownContainer>\n  );\n});\n\nexport default DropDown;\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as DropDown } from './dropdown';\nexport { default as DropDownSelect } from './select';\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/select/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { StyleOverride } from '../../../types/theme';\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { Text } from '../../typography';\n\nexport const SelectButton = styled.button<{\n  hasError?: boolean;\n  $isOpen?: boolean;\n  selectButtonStylesOverride?: StyleOverride;\n  autoHeight?: boolean;\n}>(\n  ({ theme, hasError, $isOpen, selectButtonStylesOverride, autoHeight }) => css`\n    // FIXME: Does the width *need* to be 100%?\n    //  This can lead to unexpected styling issues.\n    width: 100%;\n    height: ${autoHeight ? 'auto' : '36px'};\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n\n    border-radius: ${theme.borders.radius.small};\n    background-color: ${theme.colors.opacity.footprint};\n    border: 1px solid\n      ${theme.colors.border[$isOpen ? 'defaultActive' : 'defaultNormal']};\n\n    padding: 8px 12px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    cursor: pointer;\n\n    ${themeHelpers.focusableOutlineCSS}\n\n    &:hover {\n      border-color: ${theme.colors.border[\n        $isOpen ? 'defaultActive' : 'defaultHover'\n      ]};\n    }\n\n    ${hasError &&\n    css`\n      ${themeHelpers.focusableOutlineCSS(\n        theme.colors.interactiveBg.negativeNormal\n      )}\n      border-color: ${theme.colors.interactiveBg.negativeNormal};\n\n      &:active,\n      &:hover,\n      &:focus {\n        border-color: ${theme.colors.interactiveBg.negativeHover};\n      }\n    `}\n\n    &:disabled {\n      pointer-events: none;\n      border-color: ${theme.colors.border.disable};\n\n      &:hover {\n        border-color: ${theme.colors.border.disable};\n      }\n\n      label,\n      span,\n      svg {\n        color: ${theme.colors.fg.disable};\n      }\n    }\n    ${selectButtonStylesOverride};\n  `\n);\n\nexport const Value = styled(Text.Span).attrs({ size: TextSize.Small })<{\n  selectValueStylesOverride?: StyleOverride;\n}>`\n  max-width: 100%;\n  padding-right: 12px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  ${({ selectValueStylesOverride }) => selectValueStylesOverride};\n`;\n\nexport const LabelText = styled(Text.Span).attrs({ size: TextSize.Small })`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  padding-right: 8px;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: clip;\n`;\n\nexport const Label = styled.span`\n  display: flex;\n  align-items: center;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  cursor: pointer;\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/select/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './select';\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/select/select.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type { ComponentPropsWithoutRef, FC, ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { Disclosure } from '../../disclosure';\nimport type { StyleOverride } from '../../../types/theme';\nimport { SelectButton, Value, LabelText, Label } from './components';\n\ninterface DropDownSelectProps extends ComponentPropsWithoutRef<'button'> {\n  activeItemLabel?: string;\n  activeItemRenderer?: FC;\n  dropDownLabel?: string;\n  hasError?: boolean;\n  isOpen?: boolean;\n  onSelectClick?: ComponentPropsWithoutRef<'button'>['onClick'];\n  direction?: 'up' | 'down';\n  selectValueStylesOverride?: StyleOverride;\n  selectButtonStylesOverride?: StyleOverride;\n}\n\nconst DropDownSelect = forwardRef(\n  (\n    {\n      activeItemLabel,\n      activeItemRenderer,\n      disabled,\n      dropDownLabel,\n      hasError,\n      isOpen,\n      onSelectClick,\n      placeholder = '',\n      direction = 'down',\n      ...rest\n    }: DropDownSelectProps,\n    ref: ForwardedRef<HTMLButtonElement>\n  ) => {\n    const ValueRenderer = activeItemRenderer;\n    return (\n      <SelectButton\n        aria-haspopup\n        $isOpen={isOpen}\n        disabled={disabled}\n        hasError={hasError}\n        onClick={onSelectClick}\n        ref={ref}\n        autoHeight={Boolean(activeItemRenderer)}\n        {...rest}\n      >\n        {ValueRenderer ? (\n          <ValueRenderer />\n        ) : (\n          <Value selectValueStylesOverride={rest.selectValueStylesOverride}>\n            {activeItemLabel || placeholder}\n          </Value>\n        )}\n\n        <Label>\n          {dropDownLabel && <LabelText>{dropDownLabel}</LabelText>}\n\n          <Disclosure direction={direction} $isOpen={isOpen} />\n        </Label>\n      </SelectButton>\n    );\n  }\n);\n\nexport default DropDownSelect;\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { useState, forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Placement } from '../../popup';\nimport { Text } from '../../typography';\nimport { DropDown } from '..';\nimport {\n  basicDropDownOptions,\n  effectChooserOptions,\n  nestedDropDownOptions,\n  reallyLongOptions,\n} from '../../../storybookUtils/sampleData';\n\nexport default {\n  title: 'DesignSystem/Components/DropDown',\n  args: {\n    hasError: false,\n    hint: 'default hint text',\n    placeholder: 'select a value',\n    ariaLabel: 'ariaLabel',\n    dropDownLabel: 'label',\n    isKeepMenuOpenOnSelection: true,\n    isRTL: false,\n    disabled: false,\n    placement: Placement.Top,\n    popupZIndex: 1,\n  },\n  argTypes: {\n    placement: {\n      options: Object.values(Placement),\n      control: 'select',\n    },\n    onMenuItemClick: { action: 'onMenuItemClick' },\n  },\n};\n\nconst Container = styled.div`\n  width: ${({ narrow }) => (narrow ? 150 : 400)}px;\n  height: 100vh;\n  padding: 12px 24px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst StyledEffectListItem = styled.li`\n  border: none;\n  background: ${({ active }) => (active ? '#5732A3' : '#333')};\n  border-radius: 4px;\n  height: 48px;\n  position: relative;\n  overflow: hidden;\n  font-family: 'Teko', sans-serif;\n  font-size: 20px;\n  line-height: 1;\n  color: white;\n  text-transform: uppercase;\n  transition: background 0.1s linear;\n  grid-column-start: ${({ width }) => (width === 'full' ? 'span 4' : 'span 2')};\n  &:focus {\n    background: ${({ active }) => (active ? '#5732A3' : '#B488FC')};\n  }\n`;\n\nconst styleOverrideForAnimationEffectMenu = css`\n  width: 276px;\n  display: inline-block;\n  background: black;\n  ul {\n    display: grid;\n    justify-content: center;\n    gap: 15px 3px;\n    grid-template-columns: repeat(4, 58px);\n    padding: 15px;\n    position: relative;\n  }\n`;\n\nexport const _default = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(\n      basicDropDownOptions[2].value\n    );\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <Text.Paragraph>\n            {\n              'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque luctus luctus ex eu maximus. Nam cursus nulla massa, vel porta nisi mattis et. Vivamus vitae massa nulla. Sed enim velit, iaculis ut pharetra vitae, sagittis et dui. In sollicitudin lectus vel rhoncus auctor. Morbi pulvinar nisl sed mi fringilla, vitae bibendum felis egestas.'\n            }\n          </Text.Paragraph>\n          <DropDown\n            emptyText={'No options available'}\n            options={basicDropDownOptions}\n            selectedValue={selectedValue}\n            onMenuItemClick={(_, newValue) => {\n              onMenuItemClick(newValue);\n              setSelectedValue(newValue);\n            }}\n            {...args}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n\nexport const LightTheme = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(\n      basicDropDownOptions[2].value\n    );\n\n    return (\n      <Container>\n        <DropDown\n          emptyText={'No options available'}\n          options={basicDropDownOptions}\n          selectedValue={selectedValue}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nconst shortenedOptions = basicDropDownOptions.slice(0, 3);\n\nexport const ShortMenu = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container>\n        <DropDown\n          emptyText={'No options available'}\n          options={shortenedOptions}\n          selectedValue={selectedValue}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nexport const NoOptionsMenu = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container>\n        <DropDown\n          emptyText={'No options available'}\n          options={[]}\n          selectedValue={selectedValue}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nexport const ReallyLongLabelsMenu = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container narrow>\n        <DropDown\n          emptyText={'No options available'}\n          options={reallyLongOptions}\n          selectedValue={selectedValue}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nexport const SubMenus = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState('dog-2');\n\n    return (\n      <Container>\n        <DropDown\n          emptyText={'No options available'}\n          options={nestedDropDownOptions}\n          selectedValue={selectedValue}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nconst RenderItemOverride = forwardRef(\n  ({ option, isSelected, ...rest }, ref) => (\n    <StyledEffectListItem\n      ref={ref}\n      width={option.width}\n      active={isSelected}\n      {...rest}\n    >\n      {option.label}\n    </StyledEffectListItem>\n  )\n);\nRenderItemOverride.propTypes = {\n  option: PropTypes.object,\n  isSelected: PropTypes.bool,\n};\n\nexport const OverriddenAnimationProofOfConcept = {\n  // eslint-disable-next-line react/prop-types\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <DropDown\n            emptyText={'No options available'}\n            options={effectChooserOptions}\n            selectedValue={selectedValue}\n            onMenuItemClick={(event, newValue) => {\n              onMenuItemClick(newValue);\n              setSelectedValue(newValue);\n            }}\n            menuStylesOverride={styleOverrideForAnimationEffectMenu}\n            renderItem={RenderItemOverride}\n            {...args}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/test/dropDown.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { basicDropDownOptions } from '../../../testUtils/sampleData';\nimport DropDown from '../dropdown';\n\nconst scrollTo = jest.fn();\n\ndescribe('DropDown <DropDown />', () => {\n  beforeAll(() => {\n    // Mock scrollTo\n    Object.defineProperty(window.Element.prototype, 'scrollTo', {\n      writable: true,\n      value: scrollTo,\n    });\n\n    jest.useFakeTimers();\n  });\n\n  it('should render a closed <DropDown /> menu with a select button on default', () => {\n    renderWithProviders(\n      <DropDown options={basicDropDownOptions} dropDownLabel={'label'} />\n    );\n\n    const select = screen.getByRole('button');\n    expect(select).toBeInTheDocument();\n\n    const menu = screen.queryAllByRole('listbox');\n    expect(menu).toStrictEqual([]);\n  });\n\n  it('should show placeholder value when no selected value is found', () => {\n    renderWithProviders(\n      <DropDown options={basicDropDownOptions} placeholder={'select a value'} />\n    );\n\n    const placeholder = screen.getByText('select a value');\n    expect(placeholder).toBeInTheDocument();\n  });\n\n  it(\"should show selectedValue's associated label when selectedValue is present\", () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        placeholder={'select a value'}\n        dropDownLabel={'label'}\n        selectedValue={basicDropDownOptions[2].value}\n      />\n    );\n\n    const select = screen.getByText(basicDropDownOptions[2].label);\n    expect(select).toBeInTheDocument();\n  });\n\n  it(\"should show placeholder when selectedValue's associated label cannot be found\", () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        placeholder={'select a value'}\n        dropDownLabel={'label'}\n        selectedValue={'value that is not found in items'}\n      />\n    );\n\n    const select = screen.getByText('select a value');\n    expect(select).toBeInTheDocument();\n  });\n\n  it('should show label value when provided', () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        placeholder={'select a value'}\n        dropDownLabel={'my label'}\n      />\n    );\n\n    const label = screen.getByText('my label');\n    expect(label).toBeInTheDocument();\n  });\n\n  it('should use dropDownLabel as aria-label when no ariaLabel is specified', () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        placeholder={'select a value'}\n        dropDownLabel={'my label'}\n      />\n    );\n\n    const label = screen.getByLabelText('my label');\n    fireEvent.click(label);\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n  });\n\n  it('should use ariaLabel as aria-label when present', () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        placeholder={'select a value'}\n        dropDownLabel={'my label'}\n        ariaLabel={'my aria label override'}\n      />\n    );\n\n    const label = screen.getByLabelText('my aria label override');\n    fireEvent.click(label);\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n  });\n\n  it('should show <DropDown /> menu when a select button is clicked', () => {\n    renderWithProviders(\n      <DropDown\n        emptyText={'No options available'}\n        options={basicDropDownOptions}\n        dropDownLabel={'label'}\n      />\n    );\n\n    const select = screen.getByRole('button');\n    expect(select).toBeInTheDocument();\n\n    fireEvent.click(select);\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n  });\n\n  it('should show an active icon on list item that is active', () => {\n    renderWithProviders(\n      <DropDown\n        emptyText={'No options available'}\n        dropDownLabel={'label'}\n        isKeepMenuOpenOnSelection={false}\n        options={basicDropDownOptions}\n        selectedValue={basicDropDownOptions[2].value}\n      />\n    );\n\n    const select = screen.getByRole('button');\n    expect(select).toBeInTheDocument();\n    fireEvent.click(select);\n\n    const activeMenuItem = screen.getByRole('option', {\n      name: `Selected ${basicDropDownOptions[2].label}`,\n    });\n    expect(activeMenuItem).toBeInTheDocument();\n\n    // We can't really validate this number anyway in JSDom (no actual\n    // layout is happening), so just expect it to be called\n    expect(scrollTo).toHaveBeenCalledWith(0, expect.any(Number));\n  });\n\n  // Mouse events\n  it('should not expand menu when disabled is true', () => {\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        dropDownLabel={'my label'}\n        disabled\n      />\n    );\n\n    const select = screen.getByRole('button');\n    expect(select).toBeInTheDocument();\n\n    fireEvent.click(select);\n\n    const menu = screen.queryAllByRole('listbox');\n    expect(menu).toStrictEqual([]);\n  });\n\n  it('should trigger onMenuItemClick when item is clicked', () => {\n    const onClickMock = jest.fn();\n\n    renderWithProviders(\n      <DropDown\n        options={basicDropDownOptions}\n        selectedValue={null}\n        dropDownLabel={'my dropDown label'}\n        onMenuItemClick={onClickMock}\n      />\n    );\n\n    // Fire click event\n    const select = screen.getByRole('button');\n    fireEvent.click(select);\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n\n    const menuItems = screen.getAllByRole('option');\n    expect(menuItems).toHaveLength(12);\n\n    fireEvent.click(menuItems[2]);\n\n    // first prop we get back is the event\n    expect(onClickMock).toHaveBeenCalledWith(\n      expect.anything(),\n      basicDropDownOptions[2].value\n    );\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n\n  it('should close active menu when select is clicked', () => {\n    renderWithProviders(\n      <DropDown\n        dropDownLabel={'label'}\n        options={basicDropDownOptions}\n        selectedValue={basicDropDownOptions[1].value}\n      />\n    );\n    const select = screen.getByRole('button');\n    fireEvent.click(select);\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n\n    // wait for debounced callback to allow a select click handler to process\n    jest.runOnlyPendingTimers();\n\n    fireEvent.click(select);\n\n    expect(screen.queryByRole('listbox')).not.toBeInTheDocument();\n  });\n\n  describe('keyboard interactions', () => {\n    it('should trigger onMenuItemClick when using the down arrow plus enter key and keep menu open when isKeepMenuOpenOnSelection is true', async () => {\n      const onClickMock = jest.fn();\n      await renderWithProviders(\n        <DropDown\n          emptyText={'No options available'}\n          dropDownLabel={'label'}\n          isKeepMenuOpenOnSelection\n          options={basicDropDownOptions}\n          onMenuItemClick={onClickMock}\n          selectedValue={null}\n        />\n      );\n      const selectButton = screen.getByRole('button');\n      fireEvent.click(selectButton);\n\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n\n      const menu = screen.getByRole('listbox');\n      expect(menu).toBeInTheDocument();\n\n      const menuItems = screen.getAllByRole('option');\n      expect(menuItems).toHaveLength(12);\n\n      // first element in menu should have focus\n      expect(menuItems[0]).toHaveFocus();\n\n      // focus second element in menu\n      fireEvent.keyDown(menuItems[1], { key: 'ArrowDown', which: 40 });\n      expect(menuItems[1]).toHaveFocus();\n\n      fireEvent.keyDown(menu, { key: 'Enter', which: 13 });\n\n      // The second item in the menu.\n      // first prop we get back is the event\n      expect(onClickMock).toHaveBeenCalledWith(\n        expect.anything(),\n        basicDropDownOptions[1].value\n      );\n\n      expect(onClickMock).toHaveBeenCalledOnce();\n\n      expect(menu).toBeInTheDocument();\n    });\n\n    it('should trigger onMenuItemClick when using the down arrow plus enter key and close menu', async () => {\n      const onClickMock = jest.fn();\n\n      await renderWithProviders(\n        <DropDown\n          emptyText={'No options available'}\n          dropDownLabel={'label'}\n          options={basicDropDownOptions}\n          onMenuItemClick={onClickMock}\n          selectedValue={basicDropDownOptions[0].value}\n        />\n      );\n\n      // menu should not exist yet\n      expect(screen.queryByRole('listbox')).not.toBeInTheDocument();\n\n      // open menu\n      const selectButton = screen.getByRole('button');\n      fireEvent.click(selectButton);\n\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n\n      const menu = screen.getByRole('listbox');\n      expect(menu).toBeInTheDocument();\n\n      // focus first element in menu\n      fireEvent.keyDown(menu, { key: 'ArrowDown', which: 40 });\n\n      // focus second element in menu\n      fireEvent.keyDown(menu, { key: 'ArrowDown', which: 40 });\n\n      // select second entry\n      fireEvent.keyDown(menu, { key: 'Enter', which: 13 });\n\n      // Verify onClick was called with 'Enter'\n      expect(onClickMock).toHaveBeenCalledWith(\n        expect.anything(),\n        basicDropDownOptions[2].value\n      );\n      expect(onClickMock).toHaveBeenCalledOnce();\n\n      // menu should be closed\n      await waitFor(() =>\n        expect(screen.queryByRole('listbox')).not.toBeInTheDocument()\n      );\n    });\n\n    it('should trigger onDismissMenu when esc key is pressed', async () => {\n      await renderWithProviders(\n        <DropDown\n          dropDownLabel={'label'}\n          options={basicDropDownOptions}\n          selectedValue={basicDropDownOptions[1].value}\n        />\n      );\n      const select = screen.getByRole('button');\n      fireEvent.click(select);\n\n      const menu = screen.queryByRole('listbox');\n      expect(menu).toBeInTheDocument();\n\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n\n      fireEvent.keyDown(menu, { key: 'Escape', which: 27 });\n\n      await waitFor(() => expect(menu).not.toBeInTheDocument());\n    });\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/test/select.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport DropDownSelect from '../select';\n\ndescribe('DropDown <DropDownSelect />', () => {\n  const onClickMock = jest.fn();\n\n  it('should render a <DropDownSelect /> button by default', () => {\n    renderWithProviders(\n      <DropDownSelect\n        activeItemLabel={'chosen option'}\n        dropDownLabel={'my label'}\n        onSelectClick={onClickMock}\n        placeholder={'my placeholder'}\n      />\n    );\n\n    const select = screen.getByRole('button');\n    expect(select).toBeInTheDocument();\n  });\n\n  it('should not trigger onSelectClick on click if select is disabled', () => {\n    renderWithProviders(\n      <DropDownSelect\n        activeItemLabel={'chosen option'}\n        disabled\n        dropDownLabel={'my label'}\n        onSelectClick={onClickMock}\n        placeholder={'my placeholder'}\n      />\n    );\n\n    const select = screen.getByText('my label');\n    fireEvent.click(select);\n\n    expect(onClickMock).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/test/useDropDown.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\n\nimport {\n  basicDropDownOptions,\n  nestedDropDownOptions,\n} from '../../../testUtils/sampleData';\nimport useDropDown from '../useDropDown';\n\ndescribe('useDropDown()', () => {\n  it('should return falsy for activeOption when no selectedValue is present', () => {\n    const { result } = renderHook(() => useDropDown({ options: [] }));\n\n    expect(result.current.activeOption).toBeFalsy();\n  });\n\n  it('should return object from options containing selectedValue as active option', () => {\n    const { result } = renderHook(() =>\n      useDropDown({\n        selectedValue: basicDropDownOptions[2].value,\n        options: basicDropDownOptions,\n      })\n    );\n\n    expect(result.current.activeOption).toMatchObject(basicDropDownOptions[2]);\n  });\n\n  it('should return falsy for activeOption when selectedValue is not present in options', () => {\n    const { result } = renderHook(() =>\n      useDropDown({\n        selectedValue: 'bogus value',\n        options: basicDropDownOptions,\n      })\n    );\n\n    expect(result.current.activeOption).toBeFalsy();\n  });\n\n  it('should return an empty array when no options are present', () => {\n    const { result } = renderHook(() =>\n      useDropDown({ selectedValue: null, options: [] })\n    );\n\n    expect(result.current.groups).toStrictEqual([]);\n  });\n\n  it('should return an empty array when only bad options are present', () => {\n    const { result } = renderHook(() =>\n      useDropDown({\n        selectedValue: null,\n        options: [\n          'things that are not good for a dropDown',\n          1,\n          { 500: '', foo: () => {} },\n        ],\n      })\n    );\n\n    expect(result.current.groups).toStrictEqual([]);\n  });\n\n  it('should return only sanitized options that meet requirements', () => {\n    const { result } = renderHook(() =>\n      useDropDown({ selectedValue: null, options: nestedDropDownOptions })\n    );\n\n    expect(result.current.groups).toStrictEqual([\n      {\n        options: [\n          { label: 'ET', value: 'alien-1' },\n          { label: 'Stitch', value: 'alien-2' },\n          { label: 'Groot', value: 'alien-3' },\n          { label: 'The Worm Guys', value: 'alien-4' },\n          { label: \"Na'vi\", value: 'alien-5' },\n          { label: 'Arachnids', value: 'alien-6' },\n          { label: 'The Predator', value: 'alien-7' },\n          { label: 'Xenomorph', value: 'alien-8' },\n        ],\n        label: 'aliens',\n      },\n      {\n        options: [\n          { label: 'Smaug', value: 'dragon-1' },\n          { label: 'Mushu', value: 'dragon-2' },\n          { label: 'Toothless', value: 'dragon-3' },\n          { label: 'Falkor', value: 'dragon-4' },\n          { label: 'Drogon', value: 'dragon-5' },\n          { label: 'Kalessin', value: 'dragon-6' },\n        ],\n        label: 'dragons',\n      },\n      {\n        options: [\n          { label: 'Snoopy', value: 'dog-1' },\n          { label: 'Scooby', value: 'dog-2' },\n        ],\n        label: 'dogs',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  DropdownItem,\n  DropdownValue,\n  MenuProps,\n  NestedDropdownItem,\n} from '../menu';\nimport type { Placement } from '../popup';\n\nexport interface UseDropDownProps {\n  options: DropdownItem[] | NestedDropdownItem[];\n  selectedValue: DropdownValue;\n}\n\nexport type DropDownProps = Omit<\n  MenuProps,\n  'handleMenuItemSelect' | 'onDismissMenu' | 'groups'\n> &\n  UseDropDownProps & {\n    onMenuItemClick?: MenuProps['handleMenuItemSelect'];\n    ariaLabel?: string;\n    disabled?: boolean;\n    dropDownLabel: string;\n    hasError?: boolean;\n    hint?: string;\n    isKeepMenuOpenOnSelection?: boolean;\n    placement?: Placement;\n    popupFillWidth?: boolean;\n    popupZIndex?: number;\n    isInline?: boolean;\n    direction?: 'up' | 'down';\n    className?: string;\n  };\n"
  },
  {
    "path": "packages/design-system/src/components/dropDown/useDropDown.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useMemo,\n  useState,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport { sprintf, _n, __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { getGroups } from '../menu/utils';\nimport { useLiveRegion } from '../../utils';\nimport type { UseDropDownProps } from './types';\n\nexport default function useDropDown({\n  options = [],\n  selectedValue,\n}: UseDropDownProps) {\n  const [isOpen, _setIsOpen] = useState(false);\n  const speak = useLiveRegion('assertive');\n\n  const setIsOpen = useDebouncedCallback(_setIsOpen, 300, {\n    leading: true,\n    trailing: false,\n  });\n\n  const groups = useMemo(() => getGroups(options), [options]);\n\n  const activeOption = useMemo(() => {\n    if (!selectedValue || groups.length === 0) {\n      return null;\n    }\n\n    return groups\n      .flatMap((optionSet) => optionSet.options)\n      .find(\n        (option) =>\n          String(option.value).toLowerCase() ===\n          String(selectedValue).toLowerCase()\n      );\n  }, [selectedValue, groups]);\n\n  /* Announce length on open and changes to the length of the list */\n  useEffect(() => {\n    if (isOpen) {\n      const message = options.length\n        ? sprintf(\n            /* translators: %d number of options in dropdown */\n            _n(\n              '%d result found, use left and right or up and down arrow keys to navigate.',\n              '%d results found, use left and right or up and down arrow keys to navigate.',\n              options.length,\n              'web-stories'\n            ),\n            options.length\n          )\n        : __('No results found.', 'web-stories');\n\n      speak(message);\n    }\n  }, [isOpen, options.length, speak]);\n\n  return { activeOption, groups, isOpen, setIsOpen };\n}\n"
  },
  {
    "path": "packages/design-system/src/components/hex/hex.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  forwardRef,\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { parseToRgb } from 'polished';\nimport { getHexFromValue, getPreviewText } from '@googleforcreators/patterns';\nimport type { Solid } from '@googleforcreators/patterns';\nimport type {\n  ChangeEvent,\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport { useKeyDownEffect } from '../keyboard';\nimport { Input } from '../input';\n\ninterface HexProps extends Omit<\n  ComponentPropsWithoutRef<'input'>,\n  'value' | 'onChange'\n> {\n  value: Solid;\n  onChange: (color: Solid) => void;\n}\n\nconst HexInput = forwardRef(function Hex(\n  { value, placeholder, onChange, ...rest }: HexProps,\n  ref: ForwardedRef<HTMLInputElement>\n) {\n  const [inputValue, setInputValue] = useState<string | null>(null);\n\n  const inputRef = useRef(null);\n  const skipValidationRef = useRef(false);\n\n  const previewText = getPreviewText(value);\n  useEffect(() => setInputValue(previewText), [previewText]);\n\n  const handleInputChange = useCallback(\n    (evt: ChangeEvent<HTMLInputElement>) => {\n      // Trim and strip initial '#' (might very well be pasted in)\n      const val = evt.target.value.trim().replace(/^#/, '');\n      setInputValue(val);\n    },\n    []\n  );\n\n  const validateAndSubmitInput = useCallback(() => {\n    const hex = getHexFromValue(String(inputValue)) ?? previewText;\n    setInputValue(hex);\n\n    // Only trigger onChange when hex has been changed\n    if (hex !== previewText) {\n      // Update actual color, which will in turn update hex input from value\n      const { red: r, green: g, blue: b } = parseToRgb(`#${String(hex)}`);\n\n      // Keep same opacity as before though. In case of mixed values, set to default (1).\n      const a = value.color.a;\n      onChange({ color: { r, g, b, a } });\n    }\n  }, [inputValue, previewText, onChange, value]);\n\n  const handleEnter = useCallback(() => {\n    validateAndSubmitInput();\n  }, [validateAndSubmitInput]);\n\n  const handleInputBlur = useCallback(() => {\n    if (!skipValidationRef.current) {\n      validateAndSubmitInput();\n    }\n\n    // Reset flag after use\n    skipValidationRef.current = false;\n  }, [validateAndSubmitInput]);\n\n  const handleEsc = useCallback(() => {\n    // Revert input value and exit input focus without\n    // triggering blur validation\n    setInputValue(previewText);\n    skipValidationRef.current = true;\n    const availableRef = ref && 'current' in ref ? ref : inputRef;\n    availableRef.current?.blur();\n  }, [previewText, ref]);\n\n  useKeyDownEffect(\n    inputRef,\n    {\n      key: ['escape'],\n      editable: true,\n    },\n    handleEsc,\n    [handleEsc]\n  );\n\n  useKeyDownEffect(\n    inputRef,\n    {\n      key: ['enter'],\n      editable: true,\n    },\n    handleEnter,\n    [handleEnter]\n  );\n\n  return (\n    <Input\n      ref={ref || inputRef}\n      value={inputValue || ''}\n      onChange={handleInputChange}\n      onBlur={handleInputBlur}\n      placeholder={placeholder}\n      {...rest}\n    />\n  );\n});\n\nexport default HexInput;\n"
  },
  {
    "path": "packages/design-system/src/components/hex/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as HexInput } from './hex';\n"
  },
  {
    "path": "packages/design-system/src/components/hex/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { HexInput } from '..';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Headline } from '../../..';\n\nexport default {\n  title: 'DesignSystem/Components/HexInput',\n  component: HexInput,\n  args: {\n    label: 'Normal',\n    hint: 'Hint',\n  },\n  argTypes: {\n    handleOnChange: { action: 'on change' },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n  grid-column: 1 / -1;\n  grid-column-gap: 60px;\n\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nexport const _default = {\n  render: function Render({ handleOnChange, ...args }) {\n    const [inputState, setInputState] = useState({\n      oneLight: {\n        color: {\n          r: 255,\n          g: 255,\n          b: 255,\n        },\n      },\n      oneDark: {\n        color: {\n          r: 0,\n          g: 0,\n          b: 0,\n        },\n      },\n    });\n\n    const handleChange = (event) => {\n      handleOnChange(event);\n      if (!event?.target) {\n        return;\n      }\n      const name = event.target.name;\n      const value = event.target.value;\n\n      setInputState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Hex Input'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            <HexInput\n              aria-label=\"input-one\"\n              id=\"one-light\"\n              name=\"oneLight\"\n              value={inputState.oneLight}\n              onChange={handleChange}\n              placeholder=\"placeholder\"\n              {...args}\n            />\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container darkMode>\n            <Row>\n              <HexInput\n                aria-label=\"input-four\"\n                id=\"one-dark\"\n                name=\"oneDark\"\n                value={inputState.oneDark}\n                onChange={handleChange}\n                placeholder=\"placeholder\"\n                {...args}\n              />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './banner';\nexport * from './button';\nexport * from './checkbox';\nexport * from './chip';\nexport * from './circularProgress';\nexport * from './contextMenu';\nexport * from './datalist';\nexport * from './dialog';\nexport * from './disclosure';\nexport * from './dropDown';\nexport * from './hex';\nexport * from './infiniteScroller';\nexport * from './input';\nexport * from './input/numericInput';\nexport * from './keyboard';\nexport * from './keyboard/gridview';\nexport * from './loadingBar';\nexport * from './loadingSpinner';\nexport * from './mediaInput';\nexport * from './menu';\nexport * from './modal';\nexport * from './notificationBubble';\nexport * from './pill';\nexport * from './popup';\nexport * from './radio';\nexport * from './search';\nexport * from './slider';\nexport * from './swatch';\nexport * from './switch';\nexport * from './snackbar';\nexport * from './textArea';\nexport * from './toggle';\nexport * from './tooltip';\nexport * from './typography';\nexport * from './visuallyHidden';\n"
  },
  {
    "path": "packages/design-system/src/components/infiniteScroller/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as InfiniteScroller } from './infiniteScroller';\n"
  },
  {
    "path": "packages/design-system/src/components/infiniteScroller/infiniteScroller.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useRef,\n  useReducer,\n  useMemo,\n} from '@googleforcreators/react';\nimport type { ComponentProps } from 'react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { TextSize, themeHelpers } from '../../theme';\nimport { LoadingSpinner } from '../loadingSpinner';\nimport { Text } from '../typography';\n\nconst ScrollMessage = styled.div`\n  width: 100%;\n  padding: 140px 0 40px;\n  margin: -100px auto 0;\n  text-align: center;\n\n  p {\n    color: ${({ theme }) => theme.colors.fg.tertiary};\n  }\n`;\n\nconst LoadingContainer = styled.div`\n  display: flex;\n  justify-content: center;\n`;\n\nconst AriaOnlyAlert = styled.span`\n  ${themeHelpers.visuallyHidden}\n`;\n\nenum State {\n  Loadable = 'loadable',\n  LoadingInternal = 'loading_internal',\n  LoadingExternal = 'loading_external',\n  Complete = 'complete',\n}\n\nenum Action {\n  OnInternalLoad = 'internal on load',\n  OnExternalLoad = 'external on load',\n  OnAllLoaded = 'all loaded',\n  OnLoadSuccess = 'load success',\n  OnCanLoadMore = 'can load more',\n}\n\nconst machine: Record<State, Partial<Record<Action, State>>> = {\n  [State.Loadable]: {\n    [Action.OnInternalLoad]: State.LoadingInternal,\n    [Action.OnExternalLoad]: State.LoadingExternal,\n  },\n  [State.LoadingInternal]: {\n    [Action.OnAllLoaded]: State.Complete,\n    [Action.OnLoadSuccess]: State.Loadable,\n  },\n  [State.LoadingExternal]: {\n    [Action.OnAllLoaded]: State.Complete,\n    [Action.OnLoadSuccess]: State.Loadable,\n  },\n  [State.Complete]: {\n    [Action.OnCanLoadMore]: State.Loadable,\n  },\n};\n\nconst loadReducer = (state: State, action: Action) => {\n  return machine[state][action] || state;\n};\n\ninterface InfiniteScrollProps {\n  allDataLoadedMessage?: string;\n  allDataLoadedAriaMessage?: string;\n  onLoadMore?: () => void;\n  canLoadMore?: boolean;\n  isLoading?: boolean;\n  loadingAriaMessage?: string;\n  loadingSpinnerProps?: Partial<ComponentProps<typeof LoadingSpinner>>;\n}\n\nfunction InfiniteScroller({\n  allDataLoadedMessage,\n  allDataLoadedAriaMessage,\n  onLoadMore,\n  canLoadMore,\n  isLoading,\n  loadingAriaMessage,\n  loadingSpinnerProps = { animationSize: 50, circleSize: 6 },\n}: InfiniteScrollProps) {\n  const loadingRef = useRef(null);\n  const onLoadMoreRef = useRef(onLoadMore);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  onLoadMoreRef.current = onLoadMore;\n\n  const [loadState, dispatch] = useReducer(loadReducer, State.Loadable);\n\n  const loadingAlert = useMemo(() => {\n    if (loadState === State.LoadingInternal) {\n      return loadingAriaMessage;\n    } else if (loadState !== State.LoadingExternal && !canLoadMore) {\n      return allDataLoadedAriaMessage;\n    }\n    return null;\n  }, [allDataLoadedAriaMessage, loadingAriaMessage, loadState, canLoadMore]);\n\n  useEffect(() => {\n    if (loadState === State.LoadingInternal) {\n      onLoadMoreRef.current?.();\n    }\n  }, [loadState]);\n\n  useEffect(() => {\n    if (isLoading) {\n      dispatch(Action.OnExternalLoad);\n    }\n  }, [isLoading]);\n\n  useEffect(() => {\n    if (!isLoading) {\n      dispatch(canLoadMore ? Action.OnLoadSuccess : Action.OnAllLoaded);\n    }\n  }, [isLoading, canLoadMore]);\n\n  useEffect(() => {\n    if (canLoadMore) {\n      dispatch(Action.OnCanLoadMore);\n    }\n  }, [canLoadMore]);\n\n  useEffect(() => {\n    if (!loadingRef.current) {\n      return undefined;\n    }\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        entries.forEach((entry) => {\n          if (entry.isIntersecting) {\n            dispatch(Action.OnInternalLoad);\n          }\n        });\n      },\n      {\n        rootMargin: '0px',\n        threshold: 0,\n      }\n    );\n\n    const triggerEl = loadingRef.current;\n    observer.observe(triggerEl);\n    return () => {\n      observer.unobserve(triggerEl);\n    };\n  }, []);\n\n  const loadingContent = useMemo(() => {\n    if (loadState === State.LoadingExternal) {\n      return null;\n    }\n\n    if (!canLoadMore) {\n      if (!allDataLoadedMessage) {\n        return null;\n      }\n      return (\n        <Text.Paragraph size={TextSize.Small}>\n          {allDataLoadedMessage}\n        </Text.Paragraph>\n      );\n    }\n\n    return (\n      <LoadingContainer>\n        <LoadingSpinner {...loadingSpinnerProps} />\n      </LoadingContainer>\n    );\n  }, [allDataLoadedMessage, canLoadMore, loadState, loadingSpinnerProps]);\n\n  return (\n    <ScrollMessage data-testid=\"load-more-on-scroll\" ref={loadingRef}>\n      {loadingAlert && (\n        <AriaOnlyAlert role=\"status\">{loadingAlert}</AriaOnlyAlert>\n      )}\n      {loadingContent}\n    </ScrollMessage>\n  );\n}\n\nexport default InfiniteScroller;\n"
  },
  {
    "path": "packages/design-system/src/components/infiniteScroller/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useEffect } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport InfiniteScroller from '../infiniteScroller';\n\nexport default {\n  title: 'DesignSystem/Components/InfiniteScroller',\n  component: InfiniteScroller,\n  args: {\n    loadingAriaMessage:\n      'Data is loading - please note, intersection observers and storybook do not play nicely in firefox.',\n    allDataLoadedMessage: 'all data is loaded',\n    allDataLoadedAriaMessage: 'all data is loaded',\n  },\n  parameters: {\n    controls: {\n      include: ['loadingMessage', 'allDataLoadedMessage'],\n    },\n  },\n};\n\nconst Item = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-direction: column;\n  width: 100%;\n  height: 300px;\n  padding: 20px;\n  margin-top: 20px;\n  background-color: teal;\n  color: salmon;\n  font-size: 30px;\n  font-weight: 600;\n  &:nth-child(odd) {\n    background-color: salmon;\n    color: teal;\n  }\n`;\n\nconst generateArray = (n) =>\n  Array.from({ length: n }).fill(<span>{'Demo Item'}</span>);\n\nexport const _default = {\n  render: function Render(args) {\n    const [currentCount, setCurrentCount] = useState(5);\n    const [isAllDataLoaded, setIsAllDataLoaded] = useState(false);\n    const [isLoading, setIsLoading] = useState(false);\n    const [dummyData, setDummyData] = useState(generateArray(currentCount));\n\n    useEffect(() => {\n      setDummyData(generateArray(currentCount));\n      if (currentCount === 30) {\n        setIsAllDataLoaded(true);\n      }\n      setIsLoading(false);\n    }, [currentCount]);\n\n    if (dummyData.length > 0) {\n      return (\n        <>\n          {dummyData.map((data, index) => (\n            //eslint-disable-next-line react/no-array-index-key\n            <Item key={index}>\n              {data} {index}\n            </Item>\n          ))}\n          <InfiniteScroller\n            onLoadMore={() => {\n              setIsLoading(true);\n              setCurrentCount(currentCount + 5);\n            }}\n            isLoading={isLoading}\n            canLoadMore={!isAllDataLoaded}\n            {...args}\n          />\n        </>\n      );\n    }\n    return null;\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/infiniteScroller/test/infiniteScroller.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils';\nimport InfiniteScroller from '../infiniteScroller';\n\ndescribe('InfiniteScroller', () => {\n  const onGetDataMock = jest.fn();\n\n  it('should render a loading component by default', () => {\n    renderWithProviders(\n      <InfiniteScroller canLoadMore onLoadMore={onGetDataMock} />\n    );\n\n    const loadingComponent = screen.getByTestId('load-more-on-scroll');\n\n    expect(loadingComponent).toBeInTheDocument();\n  });\n\n  it('should show all data loaded message when `allDataLoadedMessage` is true', () => {\n    renderWithProviders(\n      <InfiniteScroller\n        onLoadMore={onGetDataMock}\n        allDataLoadedMessage=\"All data has been fetched\"\n        canLoadMore={false}\n      />\n    );\n\n    const allDataLoaded = screen.getByText('All data has been fetched');\n\n    expect(allDataLoaded).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/input/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Input } from './input';\nexport { BaseInput } from './styled';\nexport { default as NumericInput } from './numericInput';\nexport { default as useNumericInput } from './useNumericInput';\nexport * from './validation';\n"
  },
  {
    "path": "packages/design-system/src/components/input/input.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\nimport { forwardRef, useMemo, useState } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../theme';\nimport { focusCSS } from '../../theme/helpers';\nimport type { InputProps } from './types';\nimport { Container, Label, Suffix, BaseInput, Hint } from './styled';\n\nconst InputContainer = styled.div<{\n  focused: boolean;\n  hasError?: boolean;\n  styleOverride: string;\n}>(\n  ({ focused, hasError, theme, styleOverride }) => css`\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    height: 36px;\n    padding: 4px 12px;\n    border: 1px solid\n      ${theme.colors.border[hasError ? 'negativeNormal' : 'defaultNormal']};\n    border-radius: ${theme.borders.radius.small};\n    overflow: hidden;\n\n    ${focused &&\n    !hasError &&\n    css`\n      border-color: ${theme.colors.border.defaultActive};\n    `};\n\n    ${focused &&\n    css`\n      ${Suffix} {\n        color: ${theme.colors.fg.primary};\n      }\n    `};\n\n    :focus-within {\n      ${focusCSS(theme.colors.border.focus)};\n    }\n\n    ${styleOverride};\n  `\n);\n\nconst Input = forwardRef(\n  (\n    {\n      inputClassName,\n      className,\n      disabled,\n      hasError,\n      hint,\n      id,\n      label,\n      onBlur,\n      onFocus,\n      hasFocus = false,\n      suffix,\n      unit = '',\n      value = '',\n      isIndeterminate = false,\n      containerStyleOverride = '',\n      ...props\n    }: InputProps,\n    ref: ForwardedRef<HTMLInputElement>\n  ) => {\n    const inputId = useMemo(() => id || uuidv4(), [id]);\n\n    const [isFocused, setIsFocused] = useState(hasFocus);\n    const [hasBeenSelected, setHasBeenSelected] = useState(false);\n\n    let displayedValue = value;\n    if (unit && typeof value === 'string' && value.length) {\n      displayedValue = `${value}${!isFocused ? `${unit}` : ''}`;\n    }\n    if (isIndeterminate) {\n      // Display placeholder if value couldn't be determined.\n      displayedValue = '';\n    }\n    const hasSuffix = Boolean(suffix);\n\n    return (\n      <Container className={className}>\n        {label && (\n          <Label htmlFor={inputId} disabled={disabled}>\n            {label}\n          </Label>\n        )}\n        <InputContainer\n          focused={isFocused}\n          hasError={hasError}\n          styleOverride={containerStyleOverride}\n        >\n          <BaseInput\n            id={inputId}\n            disabled={disabled}\n            ref={(input) => {\n              // `ref` can either be a callback ref or a normal ref.\n              if (typeof ref === 'function') {\n                ref(input);\n              } else if (ref) {\n                ref.current = input;\n              }\n              if (input && isFocused && !hasBeenSelected) {\n                input.select();\n                setHasBeenSelected(true);\n              }\n            }}\n            onFocus={(e) => {\n              onFocus?.(e);\n              setIsFocused(true);\n              setHasBeenSelected(false);\n            }}\n            onBlur={(e) => {\n              onBlur?.(e);\n              setIsFocused(false);\n            }}\n            value={displayedValue}\n            hasSuffix={hasSuffix}\n            className={inputClassName}\n            {...props}\n          />\n          {hasSuffix && (\n            <Suffix size={TextSize.Small} onClick={() => setIsFocused(true)}>\n              {suffix}\n            </Suffix>\n          )}\n        </InputContainer>\n        {hint && <Hint hasError={hasError}>{hint}</Hint>}\n      </Container>\n    );\n  }\n);\n\nInput.displayName = 'Input';\n\nexport default Input;\n"
  },
  {
    "path": "packages/design-system/src/components/input/numericInput.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type { ForwardedRef } from 'react';\n/**\n * Internal dependencies\n */\nimport { useKeyDownEffect } from '../keyboard';\nimport useNumericInput from './useNumericInput';\nimport Input from './input';\nimport type { NumericInputProps } from './types';\n\nconst NumericInput = forwardRef(function NumericInput(\n  {\n    allowEmpty,\n    isFloat,\n    onBlur,\n    onChange,\n    updateOnChange,\n    max,\n    min,\n    value = '',\n    isIndeterminate: originalIsIndeterminate,\n    padZero,\n    ...props\n  }: NumericInputProps,\n  ref: ForwardedRef<HTMLInputElement>\n) {\n  const {\n    currentValue,\n    handleBlur,\n    handleChange,\n    handleEsc,\n    handleKeyUpAndDown,\n    inputRef,\n    isIndeterminate,\n  } = useNumericInput({\n    allowEmpty,\n    isFloat,\n    padZero,\n    onChange,\n    updateOnChange,\n    max,\n    min,\n    value,\n    ref,\n  });\n\n  useKeyDownEffect(\n    inputRef,\n    {\n      key: ['up', 'alt+up', 'down', 'alt+down'],\n      editable: true,\n    },\n    handleKeyUpAndDown,\n    [handleKeyUpAndDown]\n  );\n\n  useKeyDownEffect(\n    inputRef,\n    {\n      key: ['escape'],\n      editable: true,\n    },\n    handleEsc,\n    [handleEsc]\n  );\n\n  useKeyDownEffect(\n    inputRef,\n    {\n      key: ['enter'],\n      editable: true,\n    },\n    handleBlur,\n    [handleBlur]\n  );\n\n  // Convert Numeric value to String for padding processing.\n  value = String(value);\n\n  // Holds filteredValue that may have leading padZero when required.\n  let paddedValue = String(currentValue);\n\n  if (value !== '' && (currentValue === '' || currentValue === '-')) {\n    // When textbox is cleared or `-` sign is entered, pass it.\n    paddedValue = String(currentValue);\n  } else if (!allowEmpty && value === '' && currentValue === '') {\n    // When allowEmpty is not allowed and currentValue & value are empty, set new value to '0'.\n    // TODO (@AnuragVasanwala): Improve this logic by considering min and max boundary.\n    paddedValue = '0';\n  } else if (allowEmpty && value === '') {\n    // When allowEmpty is applied and value is empty string, pass it.\n    paddedValue = '';\n  } else if (currentValue !== '' && max !== undefined) {\n    // Add appropriate padding when necessary.\n    const maxPad = String(max).length;\n    if (maxPad >= String(currentValue).length) {\n      // Add padding Zero when length is less than maxPad.\n      paddedValue = padZero\n        ? String(currentValue).padStart(maxPad, '0')\n        : String(currentValue);\n    } else {\n      // Remove any leading Zero when maxPad is exceeded.\n      paddedValue = String(currentValue).replace(/^0+/, '');\n    }\n  }\n\n  return (\n    <Input\n      ref={inputRef}\n      onBlur={(ev) => {\n        onBlur?.(ev); // Executes callback when supplied via props.\n        handleBlur(ev); // Calls handleBlur which is responsible for maintaining value while moving focus to another element.\n      }}\n      onChange={(ev) => {\n        if (updateOnChange) {\n          onChange?.(ev); // Executes callback when supplied via props.\n        }\n        handleChange(ev); // Calls handleChange which is responsible for changing value.\n      }}\n      value={paddedValue}\n      isIndeterminate={isIndeterminate && originalIsIndeterminate}\n      {...props}\n    />\n  );\n});\n\nexport default NumericInput;\n"
  },
  {
    "path": "packages/design-system/src/components/input/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Input from '../input';\nimport NumericInput from '../numericInput';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Headline, Text } from '../../..';\nimport { AlignCenter } from '../../../icons';\n\nexport default {\n  title: 'DesignSystem/Components/Input',\n  component: Input,\n  args: {\n    label: 'Label',\n    hint: 'Hint',\n    placeholder: 'placeholder',\n    suffix: '',\n    unit: '',\n  },\n  argTypes: {\n    handleOnChange: { action: 'handle on change' },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n  grid-column: 1 / -1;\n  grid-column-gap: 60px;\n\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nconst IconContainer = styled.div`\n  height: 32px;\n  width: 32px;\n  margin-right: -8px;\n`;\n\nexport const _default = {\n  render: function Render({ handleOnChange, ...args }) {\n    const [inputState, setInputState] = useState({\n      oneLight: '600',\n      twoLight: 'w/ suffix',\n      threeLight: 'we have an error',\n      fourLight: 'disabled',\n      oneDark: 'Dark mode text',\n      twoDark: '',\n      threeDark: '',\n      fourDark: '',\n    });\n\n    const handleChange = (event) => {\n      const name = event.target.name;\n      const value = event.target.value;\n\n      handleOnChange(name, value);\n      setInputState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Input'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            <Text.Paragraph isBold>\n              {'Normal'}\n              <Input\n                aria-label=\"input-one\"\n                id=\"one-light\"\n                name=\"oneLight\"\n                value={inputState.oneLight}\n                onChange={handleChange}\n                unit=\"ms\"\n                {...args}\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Suffix Icon'}\n              <Input\n                aria-label=\"input-two\"\n                id=\"two-light\"\n                name=\"twoLight\"\n                value={inputState.twoLight}\n                onChange={handleChange}\n                {...args}\n                suffix={\n                  <IconContainer>\n                    <AlignCenter />\n                  </IconContainer>\n                }\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Error'}\n              <Input\n                aria-label=\"input-three\"\n                id=\"three-light\"\n                name=\"threeLight\"\n                value={inputState.threeLight}\n                onChange={handleChange}\n                {...args}\n                hasError\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Disabled'}\n              <Input\n                aria-label=\"disabled-input-one\"\n                id=\"four-light\"\n                name=\"fourLight\"\n                value={inputState.fourLight}\n                onChange={handleChange}\n                {...args}\n                disabled\n              />\n            </Text.Paragraph>\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Row>\n              <Input\n                aria-label=\"input-four\"\n                id=\"one-dark\"\n                name=\"oneDark\"\n                value={inputState.oneDark}\n                onChange={handleChange}\n                {...args}\n              />\n              <Input\n                aria-label=\"input-five\"\n                id=\"two-dark\"\n                name=\"twoDark\"\n                value={inputState.twoDark}\n                onChange={handleChange}\n                {...args}\n                suffix={\n                  <IconContainer>\n                    <AlignCenter />\n                  </IconContainer>\n                }\n              />\n              <Input\n                aria-label=\"input-six\"\n                id=\"three-dark\"\n                name=\"threeDark\"\n                value={inputState.threeDark}\n                onChange={handleChange}\n                {...args}\n                hasError\n              />\n              <Input\n                aria-label=\"disabled-input-two\"\n                id=\"four-dark\"\n                name=\"fourDark\"\n                value={inputState.fourDark}\n                onChange={handleChange}\n                {...args}\n                disabled\n              />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n\nexport const Numeric = {\n  render: function Render({ handleOnChange }) {\n    const [inputState, setInputState] = useState({\n      oneLight: 600,\n      twoLight: 0,\n      threeLight: 96.2,\n      disabledOneLight: 1234,\n      oneDark: 0,\n      twoDark: 100,\n      threeDark: -1.5,\n      disabledOneDark: 0,\n    });\n\n    const handleChange = (ev, value) => {\n      const name = ev.target.name;\n      handleOnChange(name, value);\n\n      setInputState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Numeric Input'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            <Text.Paragraph isBold>\n              {'Normal'}\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-one\"\n                hint=\"0 to 600\"\n                id=\"one-light\"\n                isFloat={false}\n                label=\"Label\"\n                max={600}\n                min={0}\n                name=\"oneLight\"\n                onChange={handleChange}\n                value={inputState.oneLight}\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Unit and Suffix'}\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-two\"\n                hint=\"0ms to 100ms\"\n                id=\"two-light\"\n                isFloat={false}\n                max={100}\n                min={0}\n                name=\"twoLight\"\n                onChange={handleChange}\n                suffix=\"Duration\"\n                unit=\"ms\"\n                value={inputState.twoLight}\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Floating Point'}\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-three\"\n                hint=\"92.0°F to 100°F\"\n                id=\"three-light\"\n                isFloat\n                max={100.0}\n                min={92.0}\n                name=\"threeLight\"\n                onChange={handleChange}\n                suffix=\"Body Temp\"\n                unit=\"°F\"\n                value={inputState.threeLight}\n              />\n            </Text.Paragraph>\n            <Text.Paragraph isBold>\n              {'Disabled'}\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"disabled-input-one\"\n                disabled\n                hint=\"0 to 1234\"\n                id=\"three-light\"\n                isFloat={false}\n                max={1234}\n                min={0}\n                name=\"threeLight\"\n                onChange={handleChange}\n                value={inputState.disabledOneLight}\n              />\n            </Text.Paragraph>\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Row>\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-three\"\n                hint=\"-10 to 10\"\n                id=\"one-dark\"\n                isFloat={false}\n                max={10}\n                min={-10}\n                name=\"oneDark\"\n                onChange={handleChange}\n                value={inputState.oneDark}\n              />\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-four\"\n                hint=\"-10° to 250°\"\n                id=\"two-dark\"\n                isFloat={false}\n                max={250}\n                min={-10}\n                name=\"twoDark\"\n                onChange={handleChange}\n                suffix=\"Temp\"\n                unit=\"°\"\n                value={inputState.twoDark}\n              />\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"input-three\"\n                hint=\"-1.5 to 1.5\"\n                id=\"three-light\"\n                isFloat\n                max={1.5}\n                min={-1.5}\n                name=\"threeDark\"\n                onChange={handleChange}\n                value={inputState.threeDark}\n              />\n              <NumericInput\n                allowEmpty={false}\n                aria-label=\"disabled-input-two\"\n                disabled\n                hint=\"-10 to 10\"\n                id=\"three-dark\"\n                isFloat={false}\n                max={10}\n                min={-10}\n                name=\"threeDark\"\n                onChange={handleChange}\n                value={inputState.disabledOneDark}\n              />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/input/styled.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Text } from '../typography';\nimport { themeHelpers, TextSize } from '../../theme';\n\nexport const Container = styled.div`\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  min-width: 40px;\n`;\n\nexport const Label = styled(Text.Label)`\n  margin-bottom: 12px;\n  display: inline-block;\n`;\n\nexport const Hint = styled(Text.Paragraph)<{ hasError?: boolean }>`\n  display: inline-block;\n  margin-top: 12px;\n  color: ${({ hasError, theme }) =>\n    theme.colors.fg[hasError ? 'negative' : 'tertiary']};\n`;\n\nexport const Suffix = styled(Text.Span)`\n  background: transparent;\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  white-space: nowrap;\n\n  svg {\n    width: 32px;\n    height: 32px;\n    margin: 2px -10px;\n    display: block;\n  }\n`;\n\nexport const BaseInput = styled.input<{ hasSuffix: boolean }>(\n  ({ hasSuffix, theme }) => css`\n    height: 100%;\n    width: 100%;\n    padding: 0;\n    ${hasSuffix &&\n    css`\n      padding-right: 8px;\n    `}\n    background-color: inherit;\n    border: none;\n    outline: none;\n    box-shadow: none;\n    color: ${theme.colors.fg.primary};\n\n    ${themeHelpers.expandPresetStyles({\n      preset: {\n        ...theme.typography.presets.paragraph[TextSize.Small],\n      },\n      theme,\n    })};\n\n    ::placeholder {\n      color: ${theme.colors.fg.tertiary};\n    }\n\n    :disabled {\n      color: ${theme.colors.fg.disable};\n      border-color: ${theme.colors.border.disable};\n\n      & ~ ${Suffix} {\n        color: ${theme.colors.fg.disable};\n      }\n    }\n    :focus {\n      box-shadow: none;\n    }\n    :active:enabled {\n      color: ${theme.colors.fg.primary};\n    }\n  `\n);\n"
  },
  {
    "path": "packages/design-system/src/components/input/test/input.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Input from '../input';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { noop } from '../../../utils';\n\ndescribe('Input', () => {\n  it('should render the input', () => {\n    renderWithProviders(\n      <Input\n        aria-label=\"test\"\n        placeholder=\"my placeholder\"\n        value=\"\"\n        onChange={noop}\n      />\n    );\n\n    expect(screen.getByPlaceholderText('my placeholder')).toBeInTheDocument();\n  });\n\n  it('should render a label', () => {\n    renderWithProviders(\n      <Input label=\"This is my input label\" value=\"\" onChange={noop} />\n    );\n\n    expect(screen.getByText('This is my input label')).toBeInTheDocument();\n  });\n\n  it('should render a hint', () => {\n    renderWithProviders(\n      <Input\n        aria-label=\"test\"\n        hint=\"This is my input hint\"\n        value=\"\"\n        onChange={noop}\n      />\n    );\n\n    expect(screen.getByText('This is my input hint')).toBeInTheDocument();\n  });\n\n  it('should render a suffix', () => {\n    renderWithProviders(\n      <Input aria-label=\"test\" suffix=\"suffix\" value=\"\" onChange={noop} />\n    );\n\n    const suffixElement = screen.getByText('suffix');\n\n    expect(suffixElement).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/input/test/useNumericInput.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport useNumericInput from '../useNumericInput';\n\nconst mockOnChange = jest.fn();\n\ndescribe('useNumericInput', () => {\n  beforeEach(jest.clearAllMocks);\n\n  it('should set initial state', () => {\n    const { result } = renderHook(() =>\n      useNumericInput({\n        allowEmpty: false,\n        isFloat: false,\n        onChange: mockOnChange,\n        value: 1,\n      })\n    );\n\n    expect(result.current.currentValue).toBe(1);\n    expect(mockOnChange).not.toHaveBeenCalled();\n    expect(result.current.inputRef.current).toBeNull();\n  });\n\n  describe('handleChange', () => {\n    it('should set internal state', () => {\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value: 1,\n        })\n      );\n\n      act(() => {\n        result.current.handleChange({ target: { value: '12' } });\n      });\n      expect(result.current.currentValue).toBe('12');\n      expect(mockOnChange).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('handleBlur', () => {\n    it('should call `onChange`', () => {\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value: 1,\n        })\n      );\n\n      // fire with internal value unchanged\n      act(() => {\n        result.current.handleBlur('dummy data');\n      });\n      expect(mockOnChange).toHaveBeenCalledTimes(0);\n\n      // change internal value\n      act(() => {\n        result.current.handleChange({ target: { value: '1234' } });\n      });\n\n      // fire with internal value changed\n      act(() => {\n        result.current.handleBlur('dummy data');\n      });\n      expect(mockOnChange).toHaveBeenCalledOnce();\n      expect(mockOnChange).toHaveBeenCalledWith('dummy data', 1234);\n    });\n\n    it('should call onChange with a valid value when the current value is over max', () => {\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          max: 10,\n          value: 15,\n        })\n      );\n\n      // fire with internal value unchanged\n      act(() => {\n        result.current.handleBlur('dummy data');\n      });\n      expect(mockOnChange).toHaveBeenCalledOnce();\n      expect(mockOnChange).toHaveBeenCalledWith('dummy data', 10);\n    });\n\n    it('should call onChange with a valid value when the current value is under min', () => {\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          min: 20,\n          value: 15,\n        })\n      );\n\n      // fire with internal value unchanged\n      act(() => {\n        result.current.handleBlur('dummy data');\n      });\n      expect(mockOnChange).toHaveBeenCalledOnce();\n      expect(mockOnChange).toHaveBeenCalledWith('dummy data', 20);\n    });\n\n    it('should not call onChange when the new value is invalid', () => {\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value: 1,\n        })\n      );\n\n      // change internal value\n      act(() => {\n        result.current.handleChange({ target: { value: 'abvde' } });\n      });\n\n      // blur field now that value is changed\n      act(() => {\n        result.current.handleBlur('dummy data');\n      });\n      expect(mockOnChange).toHaveBeenCalledTimes(0);\n    });\n  });\n\n  describe('handleKeyUpDown', () => {\n    it.each`\n      initialValue | key            | altKey   | isFloat  | max          | min          | finalValue\n      ${1}         | ${'ArrowUp'}   | ${false} | ${false} | ${undefined} | ${undefined} | ${2}\n      ${1}         | ${'ArrowDown'} | ${false} | ${false} | ${undefined} | ${undefined} | ${0}\n      ${1.01}      | ${'ArrowUp'}   | ${false} | ${true}  | ${undefined} | ${undefined} | ${2.01}\n      ${1.01}      | ${'ArrowDown'} | ${false} | ${true}  | ${undefined} | ${undefined} | ${0.01}\n      ${1}         | ${'ArrowUp'}   | ${true}  | ${false} | ${undefined} | ${undefined} | ${2}\n      ${1}         | ${'ArrowDown'} | ${true}  | ${false} | ${undefined} | ${undefined} | ${0}\n      ${1.01}      | ${'ArrowUp'}   | ${true}  | ${true}  | ${undefined} | ${undefined} | ${1.11}\n      ${1.01}      | ${'ArrowDown'} | ${true}  | ${true}  | ${undefined} | ${undefined} | ${0.91}\n      ${10}        | ${'ArrowUp'}   | ${false} | ${false} | ${10}        | ${undefined} | ${10}\n      ${-2}        | ${'ArrowDown'} | ${false} | ${false} | ${undefined} | ${-2}        | ${-2}\n      ${10}        | ${'ArrowUp'}   | ${false} | ${true}  | ${10}        | ${undefined} | ${10}\n      ${-2}        | ${'ArrowDown'} | ${false} | ${true}  | ${undefined} | ${-2}        | ${-2}\n      ${10}        | ${'ArrowUp'}   | ${true}  | ${false} | ${10}        | ${undefined} | ${10}\n      ${-2}        | ${'ArrowDown'} | ${true}  | ${false} | ${undefined} | ${-2}        | ${-2}\n      ${10}        | ${'ArrowUp'}   | ${true}  | ${true}  | ${10}        | ${undefined} | ${10}\n      ${-2}        | ${'ArrowDown'} | ${true}  | ${true}  | ${undefined} | ${-2}        | ${-2}\n    `(\n      '`$key`: should call onChange with `$finalValue` when the current value is $initialValue and options are `{ initialValue: $initialValue, altKey: $altKey, key: $key, isFloat: $isFloat, max: $max, min: $min }`',\n      ({ initialValue, key, altKey, isFloat, max, min, finalValue }) => {\n        const { result } = renderHook(() =>\n          useNumericInput({\n            allowEmpty: false,\n            isFloat,\n            onChange: mockOnChange,\n            max,\n            min,\n            value: initialValue,\n          })\n        );\n\n        act(() => {\n          result.current.handleKeyUpAndDown({ altKey, key });\n        });\n        expect(mockOnChange).toHaveBeenCalledWith({ altKey, key }, finalValue);\n      }\n    );\n\n    it.each`\n      key            | altKey   | isFloat  | max          | min          | finalValue\n      ${'ArrowUp'}   | ${false} | ${false} | ${undefined} | ${undefined} | ${1}\n      ${'ArrowDown'} | ${false} | ${false} | ${undefined} | ${undefined} | ${-1}\n      ${'ArrowUp'}   | ${false} | ${true}  | ${undefined} | ${undefined} | ${1}\n      ${'ArrowDown'} | ${false} | ${true}  | ${undefined} | ${undefined} | ${-1}\n      ${'ArrowUp'}   | ${true}  | ${false} | ${undefined} | ${undefined} | ${1}\n      ${'ArrowDown'} | ${true}  | ${false} | ${undefined} | ${undefined} | ${-1}\n      ${'ArrowUp'}   | ${true}  | ${true}  | ${undefined} | ${undefined} | ${0.1}\n      ${'ArrowDown'} | ${true}  | ${true}  | ${undefined} | ${undefined} | ${-0.1}\n      ${'ArrowUp'}   | ${false} | ${false} | ${10}        | ${undefined} | ${1}\n      ${'ArrowDown'} | ${false} | ${false} | ${undefined} | ${-2}        | ${-1}\n      ${'ArrowUp'}   | ${false} | ${true}  | ${10}        | ${undefined} | ${1}\n      ${'ArrowDown'} | ${false} | ${true}  | ${undefined} | ${-2}        | ${-1}\n      ${'ArrowUp'}   | ${true}  | ${false} | ${10}        | ${undefined} | ${1}\n      ${'ArrowDown'} | ${true}  | ${false} | ${undefined} | ${-2}        | ${-1}\n      ${'ArrowUp'}   | ${true}  | ${true}  | ${10}        | ${undefined} | ${0.1}\n      ${'ArrowDown'} | ${true}  | ${true}  | ${undefined} | ${-2}        | ${-0.1}\n      ${'ArrowUp'}   | ${false} | ${false} | ${0}         | ${undefined} | ${0}\n      ${'ArrowDown'} | ${false} | ${false} | ${undefined} | ${1}         | ${1}\n      ${'ArrowUp'}   | ${false} | ${true}  | ${0}         | ${undefined} | ${0}\n      ${'ArrowDown'} | ${false} | ${true}  | ${undefined} | ${1}         | ${1}\n      ${'ArrowUp'}   | ${true}  | ${false} | ${0}         | ${undefined} | ${0}\n      ${'ArrowDown'} | ${true}  | ${false} | ${undefined} | ${1}         | ${1}\n      ${'ArrowUp'}   | ${true}  | ${true}  | ${0}         | ${undefined} | ${0}\n      ${'ArrowDown'} | ${true}  | ${true}  | ${undefined} | ${1}         | ${1}\n    `(\n      '`$key`: should call onChange with `$finalValue` when the current value is invalid and options are `{ altKey: $altKey, key: $key, isFloat: $isFloat, max: $max, min: $min }`',\n      ({ key, altKey, isFloat, max, min, finalValue }) => {\n        const { result } = renderHook(() =>\n          useNumericInput({\n            allowEmpty: false,\n            isFloat,\n            onChange: mockOnChange,\n            max,\n            min,\n            value: 0,\n          })\n        );\n\n        // set internal value to something 'invalid'\n        act(() => {\n          result.current.handleChange({ target: { value: 'not-a-number' } });\n        });\n\n        act(() => {\n          result.current.handleKeyUpAndDown({ altKey, key });\n        });\n        expect(mockOnChange).toHaveBeenCalledWith({ altKey, key }, finalValue);\n      }\n    );\n  });\n\n  describe('handleEsc', () => {\n    it('should do nothing if `inputRef` is `null`', () => {\n      const mockOnBlur = jest.fn();\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value: 1,\n        })\n      );\n\n      act(() => {\n        result.current.handleEsc();\n      });\n      expect(mockOnBlur).not.toHaveBeenCalled();\n    });\n\n    it('should call refs `onBlur` when `handleEsc` is called', () => {\n      const mockOnBlur = jest.fn();\n      const { result } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value: 1,\n        })\n      );\n\n      // set inputRef\n      result.current.inputRef.current = { blur: mockOnBlur };\n\n      act(() => {\n        result.current.handleEsc();\n      });\n      expect(mockOnBlur).toHaveBeenCalledOnce();\n    });\n  });\n\n  describe('prop changes', () => {\n    it('should update the currentValue when the `value` is updated externally', () => {\n      let value = 1;\n      const { result, rerender } = renderHook(() =>\n        useNumericInput({\n          allowEmpty: false,\n          isFloat: false,\n          onChange: mockOnChange,\n          value,\n        })\n      );\n\n      value = 6082;\n\n      rerender();\n\n      expect(result.current.currentValue).toBe(6082);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/input/test/validation.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { isInputValid, parseInput } from '../validation';\n\ndescribe('isInputValid - should validate input', () => {\n  it.each`\n    test                               | value        | allowEmpty | isFloat  | max          | min          | result\n    ${'no options'}                    | ${0}         | ${false}   | ${false} | ${undefined} | ${undefined} | ${true}\n    ${'no options as string'}          | ${'0'}       | ${false}   | ${false} | ${undefined} | ${undefined} | ${true}\n    ${'no options as float'}           | ${1.002}     | ${false}   | ${false} | ${undefined} | ${undefined} | ${true}\n    ${'no options as string float'}    | ${'0'}       | ${false}   | ${false} | ${undefined} | ${undefined} | ${true}\n    ${'under minimum'}                 | ${-100}      | ${false}   | ${false} | ${undefined} | ${0}         | ${false}\n    ${'over maximum'}                  | ${99999}     | ${false}   | ${false} | ${10}        | ${undefined} | ${false}\n    ${'under minimum as float'}        | ${-101.102}  | ${false}   | ${false} | ${undefined} | ${0}         | ${false}\n    ${'over maximum as float'}         | ${999.83}    | ${false}   | ${false} | ${10}        | ${undefined} | ${false}\n    ${'under minimum as string'}       | ${'-100'}    | ${false}   | ${false} | ${undefined} | ${0}         | ${false}\n    ${'over maximum as string'}        | ${'99999'}   | ${false}   | ${false} | ${10}        | ${undefined} | ${false}\n    ${'over maximum as string float'}  | ${'999.83'}  | ${false}   | ${false} | ${10}        | ${undefined} | ${false}\n    ${'under minimum as string float'} | ${'-100.12'} | ${false}   | ${false} | ${undefined} | ${0}         | ${false}\n    ${'empty and allow empty'}         | ${''}        | ${true}    | ${false} | ${undefined} | ${undefined} | ${true}\n    ${'empty and disallow empty'}      | ${''}        | ${false}   | ${false} | ${undefined} | ${undefined} | ${false}\n  `(\n    '$test: returns `$result` when value=`$value`, allowEmpty=`$allowEmpty`, isFloat=`$isFloat`, max=`$max`, min=`$min`',\n    ({ value, allowEmpty, isFloat, max, min, result }) => {\n      expect(\n        isInputValid(value, {\n          allowEmpty,\n          isFloat,\n          max,\n          min,\n        })\n      ).toStrictEqual(result);\n    }\n  );\n});\n\ndescribe('parseInput - should parse input', () => {\n  it.each`\n    test                                 | value        | allowEmpty | isFloat  | max          | min          | result\n    ${'no options'}                      | ${0}         | ${false}   | ${false} | ${undefined} | ${undefined} | ${0}\n    ${'no options as string'}            | ${'0'}       | ${false}   | ${false} | ${undefined} | ${undefined} | ${0}\n    ${'no options as float'}             | ${1.002}     | ${false}   | ${false} | ${undefined} | ${undefined} | ${1}\n    ${'no options as string float'}      | ${'0'}       | ${false}   | ${false} | ${undefined} | ${undefined} | ${0}\n    ${'under minimum'}                   | ${-100}      | ${false}   | ${false} | ${undefined} | ${0}         | ${0}\n    ${'over maximum'}                    | ${99999}     | ${false}   | ${false} | ${10}        | ${undefined} | ${10}\n    ${'under minimum as float'}          | ${-101.102}  | ${false}   | ${false} | ${undefined} | ${0}         | ${0}\n    ${'over maximum as float'}           | ${999.83}    | ${false}   | ${false} | ${10}        | ${undefined} | ${10}\n    ${'under minimum as string'}         | ${'-100'}    | ${false}   | ${false} | ${undefined} | ${0}         | ${0}\n    ${'over maximum as string'}          | ${'99999'}   | ${false}   | ${false} | ${10}        | ${undefined} | ${10}\n    ${'under minimum as string float'}   | ${'-100.12'} | ${false}   | ${false} | ${undefined} | ${0}         | ${0}\n    ${'over maximum as string float'}    | ${'999.83'}  | ${false}   | ${false} | ${10}        | ${undefined} | ${10}\n    ${'empty and allow empty'}           | ${''}        | ${true}    | ${false} | ${undefined} | ${undefined} | ${''}\n    ${'empty and disallow empty'}        | ${''}        | ${false}   | ${false} | ${undefined} | ${undefined} | ${null}\n    ${'minimum and maximum in range'}    | ${25}        | ${false}   | ${false} | ${100}       | ${0}         | ${25}\n    ${'minimum and maximum below range'} | ${-25}       | ${false}   | ${false} | ${100}       | ${0}         | ${0}\n    ${'minimum and maximum above range'} | ${125}       | ${false}   | ${false} | ${100}       | ${0}         | ${100}\n  `(\n    '$test: returns `$result` when value=`$value`, allowEmpty=`$allowEmpty`, isFloat=`$isFloat`, max=`$max`, min=`$min`',\n    ({ value, allowEmpty, isFloat, max, min, result }) => {\n      expect(\n        parseInput(value, {\n          allowEmpty,\n          isFloat,\n          max,\n          min,\n        })\n      ).toStrictEqual(result);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/design-system/src/components/input/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef, ForwardedRef } from 'react';\n\nexport type InputValue = string | number;\nexport interface ParseInputProps {\n  allowEmpty: boolean;\n  isFloat: boolean;\n  min?: number;\n  max?: number;\n}\n\nexport interface AbstractNumericInputProps extends ParseInputProps {\n  onChange: (evt: unknown, val: InputValue) => void;\n  value: InputValue;\n  padZero?: boolean;\n  updateOnChange?: boolean;\n}\n\nexport interface UseNumericInputProps extends AbstractNumericInputProps {\n  ref: ForwardedRef<HTMLInputElement>;\n}\n\nexport interface InputProps extends ComponentPropsWithoutRef<'input'> {\n  inputClassName?: string;\n  hasError?: boolean;\n  hint?: string;\n  label?: string;\n  hasFocus?: boolean;\n  suffix?: string;\n  unit?: string;\n  value?: InputValue;\n  isIndeterminate?: boolean;\n  containerStyleOverride?: string;\n}\n\nexport type NumericInputProps = InputProps & AbstractNumericInputProps;\n"
  },
  {
    "path": "packages/design-system/src/components/input/useNumericInput.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { Big } from 'big.js';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport type { ChangeEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { isInputValid, parseInput } from './validation';\nimport type { UseNumericInputProps } from './types';\n\nconst useNumericInput = ({\n  allowEmpty,\n  updateOnChange,\n  isFloat,\n  padZero,\n  max,\n  min,\n  onChange,\n  value,\n  ref,\n}: UseNumericInputProps) => {\n  const _inputRef = useRef<HTMLInputElement>(null);\n  const inputRef = ref && 'current' in ref ? ref : _inputRef;\n  const oldValueRef = useRef(value);\n  const revertToOriginalRef = useRef(false);\n  const [currentValue, setCurrentValue] = useState(value);\n  const options = useMemo(\n    () => ({ allowEmpty, isFloat, padZero, max, min }),\n    [allowEmpty, isFloat, padZero, max, min]\n  );\n\n  /**\n   * Call external `onChange`\n   */\n  const handleBlur = useCallback(\n    (ev: unknown) => {\n      let newValue = parseInput(oldValueRef.current, options);\n\n      if (!revertToOriginalRef.current && newValue !== null) {\n        const parsedValue = parseInput(currentValue, options);\n\n        if (parsedValue !== null) {\n          newValue = parsedValue;\n        }\n      } else if (currentValue !== null) {\n        newValue = parseInput(currentValue, options);\n      }\n\n      revertToOriginalRef.current = false;\n      if (newValue !== null) {\n        // Set newly updated value.\n        setCurrentValue(newValue);\n        if (newValue !== oldValueRef.current) {\n          onChange(ev, newValue);\n        }\n      } else if (min !== undefined) {\n        // When new value is null and min is defined, set it to min value.\n        setCurrentValue(min);\n        onChange(ev, min);\n      } else if (!allowEmpty) {\n        // When above condition do not meet and empty values are not allowed, set value to `0`.\n        // TODO (@AnuragVasanwala): Improve this logic by considering min and max boundary.\n        setCurrentValue('0');\n        onChange(ev, '0');\n      } else {\n        // When none of the above condition met, set empty value.\n        setCurrentValue('');\n        onChange(ev, '');\n      }\n    },\n    [allowEmpty, currentValue, min, onChange, options]\n  );\n\n  /**\n   * Set internal state\n   */\n  const handleChange = useCallback(\n    (ev: ChangeEvent<HTMLInputElement>) => {\n      const trimmedTargetValue = ev.target.value.trim();\n      if (trimmedTargetValue === '') {\n        setCurrentValue('');\n        if (updateOnChange && allowEmpty) {\n          onChange(ev, '');\n        }\n\n        // Do not process further.\n        return;\n      } else if (!isNaN(Number(trimmedTargetValue))) {\n        // Do not process non-numeric keys.\n        // Return minimum number when string is empty.\n        if (ev.target.value === '') {\n          if (allowEmpty) {\n            setCurrentValue('');\n            if (updateOnChange) {\n              onChange(ev, '');\n            }\n\n            // Do not process further.\n            return;\n          }\n        }\n\n        // Restricts inputted string to be <= max.\n        const parsedValue = options.isFloat\n          ? Number.parseFloat(ev.target.value)\n          : Number.parseInt(ev.target.value);\n        if (max !== undefined && parsedValue > max) {\n          if (parsedValue > max) {\n            setCurrentValue(\n              trimmedTargetValue.charAt(trimmedTargetValue.length - 1)\n            );\n            if (updateOnChange) {\n              onChange(\n                ev,\n                Number(\n                  ev.target.value.trim().charAt(trimmedTargetValue.length - 1)\n                )\n              );\n            }\n          }\n\n          // Do not process further.\n          return;\n        }\n\n        // Determine maximum padding according to the number of characters in max number.\n        const maxPad = max !== undefined ? String(max).length : 0;\n        const paddedValue =\n          !ev.target.value.endsWith('.') && options.padZero\n            ? String(parsedValue).padStart(maxPad, '0')\n            : trimmedTargetValue;\n        setCurrentValue(paddedValue);\n        if (updateOnChange) {\n          onChange(ev, Number(paddedValue));\n        }\n      } else if (trimmedTargetValue === '-') {\n        setCurrentValue(trimmedTargetValue);\n        if (updateOnChange) {\n          onChange(ev, trimmedTargetValue);\n        }\n      }\n    },\n    [allowEmpty, max, onChange, options, updateOnChange]\n  );\n\n  /**\n   * Increment or decrement value using keyboard input\n   */\n  const handleKeyUpAndDown = useCallback(\n    (ev: KeyboardEvent) => {\n      const { altKey, key } = ev;\n      const isCurrentValueValid = isInputValid(currentValue, options);\n\n      let newValue = isCurrentValueValid\n        ? parseInput(currentValue, options)\n        : 0;\n      newValue = newValue === null ? '' : newValue;\n      const diff = Big(options.isFloat && altKey ? 0.1 : 1);\n\n      if (key === 'ArrowUp') {\n        // Increment\n        newValue =\n          typeof max !== 'undefined'\n            ? Math.min(max, Big(newValue).plus(diff).toNumber())\n            : Big(newValue).plus(diff).toNumber();\n      } else if (key === 'ArrowDown') {\n        // Decrement\n        newValue =\n          typeof min !== 'undefined'\n            ? Math.max(min, Big(newValue).minus(diff).toNumber())\n            : Big(newValue).minus(diff).toNumber();\n      }\n\n      setCurrentValue(newValue);\n      onChange(ev, Number(newValue));\n    },\n    [currentValue, max, min, onChange, options]\n  );\n\n  /**\n   * Blur input and revert value to original value\n   */\n  const handleEsc = useCallback(() => {\n    setCurrentValue(oldValueRef.current);\n    revertToOriginalRef.current = true;\n    inputRef?.current?.blur();\n  }, [inputRef]);\n\n  useEffect(() => {\n    // update internal value when `value` prop changes\n    oldValueRef.current = value;\n    setCurrentValue(value);\n  }, [value]);\n\n  return {\n    // state\n    currentValue,\n    inputRef,\n    // event handlers\n    handleBlur,\n    handleChange,\n    handleEsc,\n    handleKeyUpAndDown,\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    isIndeterminate: oldValueRef.current === currentValue,\n  };\n};\n\nexport default useNumericInput;\n"
  },
  {
    "path": "packages/design-system/src/components/input/validation.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { InputValue, ParseInputProps } from './types';\n\nexport function parseInput(\n  value: InputValue,\n  { allowEmpty, isFloat, min, max }: ParseInputProps\n) {\n  if (`${String(value)}`.length > 0) {\n    let boundedValue = isFloat\n      ? Number.parseFloat(String(value))\n      : Number.parseInt(String(value));\n\n    if (min !== undefined) {\n      boundedValue = Math.max(min, boundedValue);\n    }\n    if (max !== undefined) {\n      boundedValue = Math.min(max, boundedValue);\n    }\n\n    return !isNaN(boundedValue) ? boundedValue : null;\n  } else if (allowEmpty) {\n    return '';\n  }\n\n  return null;\n}\n\nexport function isInputValid(\n  value: InputValue,\n  { allowEmpty, isFloat, min, max }: ParseInputProps\n) {\n  if (allowEmpty && `${String(value)}`.length === 0) {\n    return true;\n  }\n\n  const valueAsANumber = isFloat\n    ? Number.parseFloat(String(value))\n    : Number.parseInt(String(value));\n\n  if (min !== undefined && valueAsANumber < min) {\n    return false;\n  }\n  if (max !== undefined && valueAsANumber > max) {\n    return false;\n  }\n\n  return !isNaN(valueAsANumber);\n}\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport keys from './keys';\n\nexport default createContext({ keys });\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useGridViewKeys } from './useGridViewKeys';\nexport {\n  focusOnPage,\n  getArrowDir,\n  getGridColumnAndRowCount,\n  getRow,\n  getColumn,\n  getIndex,\n} from './utils';\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/test/getArrowDir.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getArrowDir } from '../utils';\n\ndescribe('getArrowDir', () => {\n  it('will return arrow direction of movement as 1 when key is positive', () => {\n    const arrowDirection = getArrowDir(\n      'ArrowRight',\n      'ArrowRight',\n      'ArrowLeft',\n      undefined\n    );\n    expect(arrowDirection).toBe(1);\n  });\n\n  it('will return arrow direction of movement as -1 when key is positive and isRTL is true', () => {\n    const arrowDirection = getArrowDir(\n      'ArrowRight',\n      'ArrowRight',\n      'ArrowLeft',\n      true\n    );\n    expect(arrowDirection).toBe(-1);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/test/getColumn.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getColumn } from '../utils';\n\ndescribe('getColumn', () => {\n  it('will return current column of 2 when index is 1 and numColumns is 3', () => {\n    const currentColumnIndex = getColumn(1, 3);\n\n    expect(currentColumnIndex).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/test/getIndex.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getIndex } from '../utils';\n\ndescribe('getIndex', () => {\n  it('will return item index of 4 when in second row and second column of a grid with 3 columns and 7 items.', () => {\n    const newIndex = getIndex({\n      row: 2,\n      column: 2,\n      numRows: 3,\n      numColumns: 3,\n      numItems: 7,\n    });\n\n    expect(newIndex).toBe(4);\n  });\n\n  it('will return item index of -1 when in first row and first column of a grid with 3 columns and 7 items.', () => {\n    const newIndex = getIndex({\n      row: 0,\n      column: 1,\n      numRows: 3,\n      numColumns: 3,\n      numItems: 7,\n    });\n\n    expect(newIndex).toBe(-1);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/test/getRow.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getRow } from '../utils';\n\ndescribe('getRow', () => {\n  it('will return current row of 1 when index is 1 and numColumns is 3', () => {\n    const currentRowIndex = getRow(1, 3);\n\n    expect(currentRowIndex).toBe(1);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/useGridViewKeys.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useMemo, useState } from '@googleforcreators/react';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { useKeyDownEffect } from '..';\nimport {\n  focusOnPage,\n  getArrowDir,\n  getGridColumnAndRowCount,\n  getRow,\n  getColumn,\n  getIndex,\n} from './utils';\n\ninterface UseGridViewKeysProps {\n  currentItemId: string;\n  items: { id: string }[];\n  containerRef: RefObject<HTMLElement>;\n  gridRef: RefObject<HTMLElement>;\n  itemRefs: RefObject<Record<string, HTMLElement>>;\n  isRTL: boolean;\n  arrangeItem?: (id: string, newPosition: number) => void;\n}\n\n/**\n * Allows keyboard arrow navigation through grids\n */\nfunction useGridViewKeys({\n  currentItemId,\n  items,\n  containerRef,\n  gridRef,\n  itemRefs,\n  isRTL,\n  arrangeItem,\n}: UseGridViewKeysProps) {\n  const [focusedItemId, setFocusedItemId] = useState<string | null>(null);\n  const itemIds = useMemo(() => items.map(({ id }) => id), [items]);\n  // Navigate focus left, right, up, down\n  useEffect(() => {\n    setFocusedItemId(currentItemId);\n  }, [currentItemId]);\n\n  useKeyDownEffect(\n    containerRef,\n    { key: ['up', 'down', 'left', 'right'] },\n    ({ key }: KeyboardEvent) => {\n      switch (key) {\n        case 'ArrowLeft':\n        case 'ArrowRight': {\n          const dir = getArrowDir(key, 'ArrowRight', 'ArrowLeft', isRTL);\n\n          if (dir === 0) {\n            return;\n          }\n\n          const index =\n            focusedItemId !== null ? itemIds.indexOf(focusedItemId) : -1;\n          const nextIndex = index + dir;\n          if (nextIndex < 0 || nextIndex === itemIds.length) {\n            return;\n          }\n\n          const itemId = itemIds[nextIndex];\n\n          setFocusedItemId(itemId);\n          const item = itemRefs?.current?.[itemId];\n          focusOnPage(item);\n          break;\n        }\n        case 'ArrowUp':\n        case 'ArrowDown': {\n          if (!gridRef.current) {\n            return;\n          }\n          const { rows: numRows, columns: numColumns } =\n            getGridColumnAndRowCount(gridRef.current, itemIds.length);\n          const currentIndex =\n            focusedItemId !== null ? itemIds.indexOf(focusedItemId) : -1;\n          const dir = key === 'ArrowDown' ? 1 : -1;\n\n          const currentRow = getRow(currentIndex, numColumns);\n          const currentColumn = getColumn(currentIndex, numColumns);\n\n          const nextIndex = getIndex({\n            row: currentRow + dir,\n            column: currentColumn,\n            numRows,\n            numColumns,\n            numItems: itemIds.length,\n          });\n          if (nextIndex < 0) {\n            return;\n          }\n          const itemId = itemIds[nextIndex];\n          setFocusedItemId(itemId);\n          const item = itemRefs?.current?.[itemId];\n          focusOnPage(item);\n          break;\n        }\n        default:\n          break;\n      }\n    },\n    [focusedItemId, isRTL, itemIds, itemRefs, gridRef, currentItemId]\n  );\n\n  // jump to beginning or end of row and set active state. do this after normal keydown is good to go\n  // Rearrange pages\n  useKeyDownEffect(\n    containerRef,\n    { key: ['mod+up', 'mod+down', 'mod+left', 'mod+right'], shift: true },\n    (e) => {\n      const { key, shiftKey } = e;\n      let canArrange = false,\n        nextIndex;\n      // Cancel the default behavior of the event: it's very jarring to run\n      // into mod+left/right triggering the browser's back/forward navigation.\n      e.preventDefault();\n\n      switch (key) {\n        case 'ArrowLeft':\n        case 'ArrowRight': {\n          const dir = getArrowDir(key, 'ArrowRight', 'ArrowLeft', isRTL);\n\n          if (dir === 0) {\n            return;\n          }\n\n          const currentIndex =\n            focusedItemId !== null ? itemIds.indexOf(focusedItemId) : -1;\n          nextIndex = currentIndex;\n\n          // If the user is pressing shift, jump to the beginning/end\n          if (shiftKey) {\n            nextIndex = dir < 0 ? 0 : itemIds.length - 1;\n          } else {\n            nextIndex += dir;\n          }\n\n          canArrange =\n            nextIndex !== currentIndex &&\n            nextIndex >= 0 &&\n            nextIndex <= itemIds.length - 1;\n\n          break;\n        }\n        case 'ArrowUp':\n        case 'ArrowDown': {\n          if (!gridRef.current) {\n            return;\n          }\n          const { rows: numRows, columns: numColumns } =\n            getGridColumnAndRowCount(gridRef.current, itemIds.length);\n          const currentIndex =\n            focusedItemId !== null ? itemIds.indexOf(focusedItemId) : -1;\n          const dir = key === 'ArrowDown' ? 1 : -1;\n\n          const currentRow = getRow(currentIndex, numColumns);\n          const currentColumn = getColumn(currentIndex, numColumns);\n\n          nextIndex = getIndex({\n            row: currentRow + dir,\n            column: currentColumn,\n            numRows,\n            numColumns,\n            numItems: itemIds.length,\n          });\n\n          if (nextIndex < 0) {\n            return;\n          }\n\n          break;\n        }\n\n        default:\n          break;\n      }\n\n      if (canArrange && typeof nextIndex !== 'undefined') {\n        if (arrangeItem && focusedItemId) {\n          arrangeItem(focusedItemId, nextIndex);\n        }\n      }\n    },\n    [\n      currentItemId,\n      itemIds,\n      isRTL,\n      gridRef,\n      itemRefs,\n      focusedItemId,\n      arrangeItem,\n    ]\n  );\n}\n\nexport default useGridViewKeys;\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/gridview/utils.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// @todo: provide a cleaner `focusFirst()` API and takes into account\n// `tabIndex`, `disabled`, links, buttons, inputs, etc.\nexport function focusOnPage(page: Element | undefined) {\n  // grab the first focusable element available.\n  // currently can be a button or an anchor.\n  const button = page?.querySelector('button, a') as\n    | HTMLButtonElement\n    | HTMLAnchorElement;\n  if (button) {\n    button.focus();\n  }\n}\n\nexport function getArrowDir(\n  key: string,\n  pos: string,\n  neg: string,\n  isRTL: boolean\n) {\n  const rtlDir = isRTL ? -1 : 1;\n  if (key === pos) {\n    return rtlDir;\n  }\n  if (key === neg) {\n    return -1 * rtlDir;\n  }\n  return 0;\n}\n\nexport function getGridColumnAndRowCount(grid: HTMLElement, pageCount: number) {\n  let columns = 0;\n  let prevX;\n  for (const el of grid.children) {\n    const { x } = el.getBoundingClientRect();\n    if (typeof prevX !== 'undefined' && x < prevX) {\n      break;\n    }\n    prevX = x;\n    columns++;\n  }\n\n  const rows = Math.ceil(pageCount / columns);\n\n  return { rows, columns };\n}\n\n// will return a 1 based index\nexport function getRow(index: number, numColumns: number) {\n  return Math.ceil((index + 1) / numColumns);\n}\n\n// will return a 1 based index\nexport function getColumn(index: number, numColumns: number) {\n  return (index % numColumns) + 1;\n}\n\n// will return a 0 based index\nexport function getIndex({\n  row,\n  column,\n  numRows,\n  numColumns,\n  numItems,\n}: {\n  row: number;\n  column: number;\n  numRows: number;\n  numColumns: number;\n  numItems: number;\n}) {\n  const isOutOfBounds =\n    row > numRows || row <= 0 || column > numColumns || column <= 0;\n\n  if (isOutOfBounds) {\n    return -1;\n  }\n\n  const index = numColumns * (row - 1) + (column - 1);\n\n  // If the index is greater than or equal to numItems default to the last index.\n  // This handles the case when we press ArrowDown and there is another row, but\n  // the column below is empty. It will default to the last item in the list.\n  return index >= numItems ? numItems - 1 : index;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './keyboard';\nexport * from './utils';\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/keyboard.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useContext,\n  useBatchingCallback,\n  useCallback,\n} from '@googleforcreators/react';\nimport type { DependencyList } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type {\n  KeyEffectCallback,\n  KeyNameOrSpec,\n  RefOrNode,\n} from '../../types/keyboard';\nimport Context from './context';\nimport {\n  getNodeFromRefOrNode,\n  getOrCreateMousetrap,\n  resolveKeySpec,\n  createKeyHandler,\n  createShortcutAriaLabel,\n  prettifyShortcut,\n} from './utils';\nimport type { HTMLElementWithMouseTrap } from './utils';\n\nconst globalRef: { current: null | HTMLElement } = { current: null };\n\nfunction setGlobalRef() {\n  if (!globalRef.current) {\n    globalRef.current = document.documentElement;\n  }\n}\n\n/**\n * See https://craig.is/killing/mice#keys for the supported key codes.\n */\nfunction useKeyEffectInternal(\n  refOrNode: RefOrNode,\n  keyNameOrSpec: KeyNameOrSpec,\n  type: string | undefined,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  const { keys } = useContext(Context);\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  const batchingCallback = useBatchingCallback(callback, deps || []);\n  useEffect(\n    () => {\n      const nodeEl = getNodeFromRefOrNode(refOrNode);\n      if (!nodeEl) {\n        return undefined;\n      }\n      if (\n        nodeEl.nodeType !== Node.ELEMENT_NODE &&\n        nodeEl.nodeType !== Node.DOCUMENT_NODE\n      ) {\n        throw new Error('only an element or a document node can be used');\n      }\n\n      const keySpec = resolveKeySpec(keys, keyNameOrSpec);\n      if (keySpec.key.length === 1 && keySpec.key[0] === '') {\n        return undefined;\n      }\n\n      const mousetrap = getOrCreateMousetrap(\n        nodeEl as HTMLElementWithMouseTrap\n      );\n      const handler = createKeyHandler(\n        nodeEl as HTMLElement,\n        keySpec,\n        batchingCallback\n      );\n      mousetrap.bind(keySpec.key, handler, type);\n      return () => {\n        mousetrap.unbind(keySpec.key, type);\n      };\n    },\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Deliberately don't want the other possible deps here.\n    [batchingCallback, keys]\n  );\n}\n\n/**\n * Depending on the key spec, this will bind to either the 'keypress' or\n * 'keydown' event type, by passing 'undefined' to the event type parameter of\n * Mousetrap.bind.\n *\n * See https://craig.is/killing/mice#api.bind.\n */\nexport function useKeyEffect(\n  refOrNode: RefOrNode,\n  keyNameOrSpec: KeyNameOrSpec,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyEffectInternal(refOrNode, keyNameOrSpec, undefined, callback, deps);\n}\n\nexport function useKeyDownEffect(\n  refOrNode: RefOrNode,\n  keyNameOrSpec: KeyNameOrSpec,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyEffectInternal(refOrNode, keyNameOrSpec, 'keydown', callback, deps);\n}\n\nexport function useKeyUpEffect(\n  refOrNode: RefOrNode,\n  keyNameOrSpec: KeyNameOrSpec,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyEffectInternal(refOrNode, keyNameOrSpec, 'keyup', callback, deps);\n}\n\nexport function useIsKeyPressed(\n  refOrNode: RefOrNode,\n  keyNameOrSpec: KeyNameOrSpec,\n  deps: DependencyList\n) {\n  const [isKeyPressed, setIsKeyPressed] = useState(false);\n\n  const handleBlur = useCallback(() => {\n    setIsKeyPressed(false);\n  }, []);\n  useEffect(() => {\n    window.addEventListener('blur', handleBlur);\n    return () => {\n      window.removeEventListener('blur', handleBlur);\n    };\n  }, [handleBlur]);\n\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyDownEffect(refOrNode, keyNameOrSpec, () => setIsKeyPressed(true), deps);\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyUpEffect(refOrNode, keyNameOrSpec, () => setIsKeyPressed(false), deps);\n  return isKeyPressed;\n}\n\nexport function useGlobalKeyDownEffect(\n  keyNameOrSpec: KeyNameOrSpec,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  setGlobalRef();\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyDownEffect(globalRef, keyNameOrSpec, callback, deps);\n}\nexport function useGlobalKeyUpEffect(\n  keyNameOrSpec: KeyNameOrSpec,\n  callback: KeyEffectCallback,\n  deps: DependencyList\n) {\n  setGlobalRef();\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  useKeyUpEffect(globalRef, keyNameOrSpec, callback, deps);\n}\n\nexport function useGlobalIsKeyPressed(\n  keyNameOrSpec: KeyNameOrSpec,\n  deps: DependencyList\n) {\n  setGlobalRef();\n  return useIsKeyPressed(globalRef, keyNameOrSpec, deps);\n}\n\nexport function useEscapeToBlurEffect(\n  refOrNode: RefOrNode,\n  deps: DependencyList\n) {\n  useKeyDownEffect(\n    refOrNode,\n    { key: 'esc', editable: true },\n    () => {\n      const nodeEl = getNodeFromRefOrNode(refOrNode);\n      const { activeElement } = document;\n      if (nodeEl && activeElement && nodeEl.contains(activeElement)) {\n        (activeElement as HTMLInputElement).blur();\n      }\n    },\n    //eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n    deps\n  );\n}\n\ninterface ShortcutProps {\n  component: React.FC;\n  shortcut?: string;\n}\n/**\n * Returns a prettified shortcut wrapped with a <kbd> element.\n */\nexport function Shortcut({\n  component: Component,\n  shortcut = '',\n}: ShortcutProps) {\n  const chars = shortcut.split(' ');\n\n  return (\n    <Component aria-label={createShortcutAriaLabel(shortcut)}>\n      {chars.map((char, index) => (\n        // eslint-disable-next-line react/no-array-index-key -- Should be OK due to also using the character.\n        <Component key={`${index}-${char}`}>{prettifyShortcut(char)}</Component>\n      ))}\n    </Component>\n  );\n}\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/keys.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * See https://craig.is/killing/mice#keys for the supported key codes.\n */\nconst keys = {\n  undo: 'mod+z',\n  redo: 'shift+mod+z',\n  delete: ['del', 'backspace'],\n  clone: 'mod+d',\n};\n\nexport default keys;\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/test/createShortcutAriaLabel.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { createShortcutAriaLabel } from '..';\n\ndescribe('createShortcutArialabel', () => {\n  it.each`\n    operatingSystem | shortcut            | result\n    ${'MacIntel'}   | ${'mod alt delete'} | ${'Command Option Delete'}\n    ${'Windows'}    | ${'mod alt delete'} | ${'Control+Alt+Delete'}\n    ${'MacIntel'}   | ${'Shift 1 ,'}      | ${'Shift 1 Comma'}\n    ${'Windows'}    | ${'Shift 1 ,'}      | ${'Shift+1+Comma'}\n    ${'MacIntel'}   | ${'j . `'}          | ${'J Period Backtick'}\n    ${'Windows'}    | ${'j . `'}          | ${'J+Period+Backtick'}\n    ${'MacIntel'}   | ${'1 2 3'}          | ${'1 2 3'}\n    ${'Windows'}    | ${'1 2 3'}          | ${'1+2+3'}\n    ${'MacIntel'}   | ${'ctrl . ,'}       | ${'Control Period Comma'}\n    ${'Windows'}    | ${'ctrl . ,'}       | ${'Control+Period+Comma'}\n  `(\n    'should return $result for $shortcut on $operatingSystem',\n    ({ operatingSystem, shortcut, result }) => {\n      Object.defineProperty(window.navigator, 'platform', {\n        value: operatingSystem,\n        configurable: true,\n      });\n\n      expect(createShortcutAriaLabel(shortcut)).toBe(result);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/test/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint jest/expect-expect: [\"error\", { \"assertFunctionNames\": [\"testIsKeyPressed\"] }] */\n\n/**\n * External dependencies\n */\nimport { fireEvent } from '@testing-library/react';\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { useGlobalIsKeyPressed, useIsKeyPressed } from '..';\n\nconst keys = {\n  a: { key: 'a', which: 65 },\n  b: { key: 'b', which: 66 },\n};\n\n/** @typedef {import('@testing-library/react-hooks').HookResult} HookResult */\n\n/**\n * Runs tests simulating a key being held down for useIsKeyPressed\n * and useGlobalIsKeyPressed.\n *\n * @param {HookResult<boolean>} result Hook result.\n * @param {Node} node Node.\n * @param {Object<{key: string, which: number}>} key Key object.\n * @param {boolean} [shouldRegister] Whether the key press is registered by\n * the hook.\n */\nfunction testIsKeyPressed(result, node, { key, which }, shouldRegister = true) {\n  expect(result.current).toBeFalse();\n\n  // eslint-disable-next-line testing-library/no-unnecessary-act\n  act(() => {\n    fireEvent.keyDown(node, { key, which });\n  });\n\n  expect(result.current).toBe(shouldRegister);\n\n  // eslint-disable-next-line testing-library/no-unnecessary-act\n  act(() => {\n    fireEvent.keyUp(node, { key, which });\n  });\n\n  expect(result.current).toBeFalse();\n}\n\ndescribe('keyboard/index.js', () => {\n  describe('useIsKeyPressed', () => {\n    it('should initialize and then register key up and down events', () => {\n      const container = document.createElement('div');\n\n      const { result } = renderHook(() => useIsKeyPressed(container, 'a'));\n      testIsKeyPressed(result, container, keys.a);\n    });\n\n    it('should not register when other keys are pressed', () => {\n      const container = document.createElement('div');\n      const { result } = renderHook(() => useIsKeyPressed(container, 'a'));\n      testIsKeyPressed(result, container, keys.b, false);\n    });\n\n    it('should not register key presses on other elements', () => {\n      const elemWithHook = document.createElement('div');\n      const elemWhereKeyPressIsFired = document.createElement('div');\n\n      const { result } = renderHook(() => useIsKeyPressed(elemWithHook, 'a'));\n\n      testIsKeyPressed(result, elemWhereKeyPressIsFired, keys.a, false);\n    });\n  });\n\n  describe('useGlobalIsKeyPressed', () => {\n    it('should initialize and then register key up and down events', () => {\n      const { result } = renderHook(() => useGlobalIsKeyPressed('a'));\n      testIsKeyPressed(result, document.documentElement, keys.a);\n    });\n\n    it('should not register when other keys are pressed', () => {\n      const { result } = renderHook(() => useGlobalIsKeyPressed('a'));\n      testIsKeyPressed(result, document.documentElement, keys.b, false);\n    });\n\n    it('should register key presses on any part of the document', () => {\n      const elements = [\n        document.createElement('div'),\n        document.createElement('div'),\n        document.createElement('div'),\n      ];\n\n      document.body.append(...elements);\n\n      const { result } = renderHook(() => useGlobalIsKeyPressed('a'));\n\n      elements.forEach((e) => testIsKeyPressed(result, e, keys.a));\n    });\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/test/prettifyShortcut.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { prettifyShortcut } from '..';\n\ndescribe('prettifyShortcut', () => {\n  describe('default platform', () => {\n    it('should prettify keyboard shortcuts', () => {\n      expect(prettifyShortcut('shift+mod+z')).toBe('Shift+Ctrl+Z');\n      expect(prettifyShortcut('alt+b')).toBe('Alt+B');\n    });\n  });\n\n  describe('macOS / Apple platform', () => {\n    beforeEach(() => {\n      Object.defineProperty(window.navigator, 'platform', {\n        value: 'MacIntel',\n      });\n    });\n\n    it('should prettify keyboard shortcuts', () => {\n      expect(prettifyShortcut('shift+mod+z')).toBe('⇧⌘Z');\n      expect(prettifyShortcut('alt+b')).toBe('⌥B');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/keyboard/utils.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport Mousetrap from 'mousetrap';\nimport type { MousetrapInstance } from 'mousetrap';\nimport type {\n  RefOrNode,\n  KeyEffectCallback,\n  KeyNameOrSpec,\n  Keys,\n} from '../../types/keyboard';\n\nconst PROP = '__WEB_STORIES_MT__';\nconst NON_EDITABLE_INPUT_TYPES = [\n  'submit',\n  'button',\n  'checkbox',\n  'radio',\n  'image',\n  'file',\n  'range',\n  'reset',\n  'hidden',\n];\nconst CLICKABLE_INPUT_TYPES = [\n  'submit',\n  'button',\n  'checkbox',\n  'radio',\n  'image',\n  'file',\n  'reset',\n];\n\nexport interface HTMLElementWithMouseTrap extends HTMLElement {\n  [PROP]: undefined | MousetrapInstance;\n}\n/**\n * @param node The DOM node.\n * @return The Mousetrap object that will be used to intercept\n * the keyboard events on the specified node.\n */\nexport function getOrCreateMousetrap(node: HTMLElementWithMouseTrap) {\n  return node[PROP] || (node[PROP] = new Mousetrap(node));\n}\n\nexport function getNodeFromRefOrNode(refOrNode: RefOrNode) {\n  return refOrNode && 'current' in refOrNode ? refOrNode.current : refOrNode;\n}\n\nexport function resolveKeySpec(keyDict: Keys, keyNameOrSpec: KeyNameOrSpec) {\n  const keySpec =\n    typeof keyNameOrSpec === 'string' || Array.isArray(keyNameOrSpec)\n      ? { key: keyNameOrSpec }\n      : keyNameOrSpec;\n  const {\n    key: keyOrArray,\n    shift = false,\n    repeat = true,\n    clickable = true,\n    editable = false,\n    dialog = false,\n    allowDefault = false,\n  } = keySpec;\n  const mappedKeys = new Array<string>()\n    .concat(keyOrArray)\n    .flatMap((key) => keyDict[key as keyof Keys] || key);\n  const allKeys = addMods(mappedKeys, shift);\n  return {\n    key: allKeys,\n    shift,\n    clickable,\n    repeat,\n    editable,\n    dialog,\n    allowDefault,\n  };\n}\n\nexport function addMods(keys: string[], shift: boolean) {\n  if (!shift) {\n    return keys;\n  }\n  return keys.concat(keys.map((key) => `shift+${key}`));\n}\n\ninterface KeyHandlerProps {\n  repeat?: boolean;\n  editable?: boolean;\n  clickable?: boolean;\n  dialog?: boolean;\n  allowDefault?: boolean;\n}\n\nexport function createKeyHandler(\n  keyTarget: Element,\n  {\n    repeat: repeatAllowed,\n    editable: editableAllowed,\n    clickable: clickableAllowed,\n    dialog: dialogAllowed,\n    allowDefault = false,\n  }: KeyHandlerProps,\n  callback: KeyEffectCallback\n) {\n  return (evt: KeyboardEvent) => {\n    const { repeat, target } = evt;\n    if (!repeatAllowed && repeat) {\n      return undefined;\n    }\n    if (!editableAllowed && isEditableTarget(target as HTMLInputElement)) {\n      return undefined;\n    }\n    if (!clickableAllowed && isClickableTarget(target as HTMLInputElement)) {\n      return undefined;\n    }\n    if (\n      !dialogAllowed &&\n      crossesDialogBoundary(target as HTMLElement, keyTarget)\n    ) {\n      return undefined;\n    }\n    callback(evt);\n    // The default `false` value instructs Mousetrap to cancel event propagation\n    // and default behavior.\n    return allowDefault;\n  };\n}\n\ntype ClickableHTMLElement =\n  | HTMLInputElement\n  | HTMLAnchorElement\n  | HTMLButtonElement\n  | HTMLTextAreaElement;\nexport function isClickableTarget({ tagName, type }: ClickableHTMLElement) {\n  if (['BUTTON', 'A'].includes(tagName)) {\n    return true;\n  }\n  if (tagName === 'INPUT') {\n    return CLICKABLE_INPUT_TYPES.includes(type);\n  }\n  return false;\n}\n\nexport function isEditableTarget({\n  tagName,\n  isContentEditable,\n  type,\n  ...rest\n}: ClickableHTMLElement) {\n  if ('readOnly' in rest && rest.readOnly === true) {\n    return false;\n  }\n  if (isContentEditable || tagName === 'TEXTAREA') {\n    return true;\n  }\n  if (tagName === 'INPUT') {\n    return !NON_EDITABLE_INPUT_TYPES.includes(type);\n  }\n  return false;\n}\n\nexport function crossesDialogBoundary(target: Element, keyTarget: Element) {\n  if (target.nodeType !== 1) {\n    // Not an element. Most likely a document node. The dialog search\n    // does not apply.\n    return false;\n  }\n  // Check if somewhere between `keyTarget` and `target` there's a\n  // dialog boundary.\n  const dialog = target.closest('dialog,[role=\"dialog\"]');\n  return dialog && keyTarget !== dialog && keyTarget.contains(dialog);\n}\n\n/**\n * Determines if the current platform is a Mac or not.\n */\nexport function isPlatformMacOS() {\n  const { platform } = window.navigator;\n  return platform.includes('Mac') || ['iPad', 'iPhone'].includes(platform);\n}\n\n/**\n * Get the key specific to operating system.\n */\nexport function getKeyForOS(key: string) {\n  const isMacOS = isPlatformMacOS();\n\n  const replacementKeyMap: Record<string, string> = {\n    alt: isMacOS ? '⌥' : 'Alt',\n    ctrl: isMacOS ? '^' : 'Ctrl',\n    mod: isMacOS ? '⌘' : 'Ctrl',\n    cmd: '⌘',\n    shift: isMacOS ? '⇧' : 'Shift',\n  };\n\n  return replacementKeyMap[key] || key;\n}\n\n/**\n * Creates an aria label for a shortcut.\n *\n * Inspired from the worpress Gutenberg plugin:\n * https://github.com/WordPress/gutenberg/blob/3da717b8d0ac7d7821fc6d0475695ccf3ae2829f/packages/keycodes/src/index.js#L240-L277\n *\n * @example\n * createShortcutAriaLabel('mod alt del'); -> \"Command Alt Del\"\n */\nexport function createShortcutAriaLabel(shortcut: string) {\n  const isMacOS = isPlatformMacOS();\n\n  /* translators: Command key on the keyboard */\n  const command = __('Command', 'web-stories');\n  /* translators: Control key on the keyboard */\n  const control = __('Control', 'web-stories');\n  /* translators: Option key on the keyboard */\n  const option = __('Option', 'web-stories');\n  /* translators: Alt key on the keyboard */\n  const alt = __('Alt', 'web-stories');\n\n  const replacementKeyMap = {\n    alt: isMacOS ? option : alt,\n    mod: isMacOS ? command : control,\n    /* translators: Control key on the keyboard */\n    ctrl: __('Control', 'web-stories'),\n    /* translators: shift key on the keyboard */\n    shift: __('Shift', 'web-stories'),\n    /* translators: delete key on the keyboard */\n    delete: __('Delete', 'web-stories'),\n    cmd: command,\n    /* translators: comma character ',' */\n    ',': __('Comma', 'web-stories'),\n    /* translators: period character '.' */\n    '.': __('Period', 'web-stories'),\n    /* translators: backtick character '`' */\n    '`': __('Backtick', 'web-stories'),\n  };\n\n  const delimiter = isMacOS ? ' ' : '+';\n\n  return shortcut\n    .toLowerCase()\n    .replace('alt', replacementKeyMap.alt)\n    .replace('ctrl', replacementKeyMap.ctrl)\n    .replace('mod', replacementKeyMap.mod)\n    .replace('cmd', replacementKeyMap.cmd)\n    .replace('shift', replacementKeyMap.shift)\n    .replace('delete', replacementKeyMap.delete)\n    .replace(',', replacementKeyMap[','])\n    .replace('.', replacementKeyMap['.'])\n    .replace('`', replacementKeyMap['`'])\n    .split(/[\\s+]/)\n    .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n    .join(delimiter);\n}\n\n/**\n * Prettifies keyboard shortcuts in a platform-agnostic way.\n */\nexport function prettifyShortcut(shortcut: string) {\n  const isMacOS = isPlatformMacOS();\n\n  const delimiter = isMacOS ? '' : '+';\n\n  return shortcut\n    .toLowerCase()\n    .replace('alt', getKeyForOS('alt'))\n    .replace('ctrl', getKeyForOS('ctrl'))\n    .replace('mod', getKeyForOS('mod'))\n    .replace('cmd', getKeyForOS('cmd'))\n    .replace('shift', getKeyForOS('shift'))\n    .replace('left', '←')\n    .replace('up', '↑')\n    .replace('right', '→')\n    .replace('down', '↓')\n    .replace('delete', '⌫')\n    .replace('enter', '⏎')\n    .split('+')\n    .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n    .join(delimiter);\n}\n"
  },
  {
    "path": "packages/design-system/src/components/loadingBar/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './loadingBar';\n"
  },
  {
    "path": "packages/design-system/src/components/loadingBar/loadingBar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\nimport { CSSTransition } from 'react-transition-group';\nimport styled, { keyframes } from 'styled-components';\nimport { useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\n\nexport const LOADING_INDICATOR_CLASS = 'loading-indicator';\n\nconst AriaOnlyAlert = styled.span`\n  ${themeHelpers.visuallyHidden}\n`;\n\nconst gradientAnimation = keyframes`\n    0% { background-position:0% 50% }\n    50% { background-position:100% 50% }\n    100% { background-position:0% 50% }\n`;\n\nconst UploadingIndicator = styled.div`\n  height: 4px;\n  background: ${({ theme }) => theme.colors.gradient.loading};\n  background-size: 400% 400%;\n  position: absolute;\n  bottom: 0px;\n  border-radius: ${({ theme }) =>\n    `0px 0px ${theme.borders.radius.small} ${theme.borders.radius.small}`};\n\n  animation: ${gradientAnimation} 4s ease infinite;\n\n  &.${LOADING_INDICATOR_CLASS} {\n    &.appear {\n      width: 0;\n    }\n\n    &.appear-done {\n      width: 100%;\n      transition: 1s ease-out;\n      transition-property: width;\n    }\n  }\n`;\n\ninterface LoadingBarProps extends ComponentPropsWithoutRef<'div'> {\n  loadingMessage: string;\n}\n\nexport function LoadingBar({ loadingMessage, ...rest }: LoadingBarProps) {\n  const nodeRef = useRef<HTMLDivElement>(null);\n  return (\n    <>\n      {loadingMessage && (\n        <AriaOnlyAlert role=\"status\">{loadingMessage}</AriaOnlyAlert>\n      )}\n      <CSSTransition\n        nodeRef={nodeRef}\n        in\n        appear\n        timeout={0}\n        className={LOADING_INDICATOR_CLASS}\n      >\n        <UploadingIndicator ref={nodeRef} {...rest} />\n      </CSSTransition>\n    </>\n  );\n}\n"
  },
  {
    "path": "packages/design-system/src/components/loadingBar/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { LoadingBar } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/LoadingBar',\n  component: LoadingBar,\n  args: {\n    loadingMessage: 'sample aria loading text',\n    showLoadingBar: true,\n  },\n};\n\nconst Container = styled.div`\n  position: relative;\n  display: flex;\n  width: 100px;\n  height: 200px;\n  margin: 20px;\n  border-radius: 4px;\n  background-color: gray;\n`;\nexport const _default = {\n  render: function Render(args) {\n    const showLoadingBar = args.showLoadingBar;\n    return (\n      <Container>\n        {showLoadingBar && <LoadingBar loadingMessage={args.message} />}\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/loadingSpinner/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as LoadingSpinner } from './loadingSpinner';\n"
  },
  {
    "path": "packages/design-system/src/components/loadingSpinner/loadingSpinner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\nimport { useMemo } from '@googleforcreators/react';\nimport styled, { keyframes } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, BEZIER } from '../../theme';\n\nconst ANIMATION_DURATION = 0.85;\nconst TAU = Math.PI * 2;\n\nconst getAngleOfCircle = (index: number, numCircles: number) => {\n  return (TAU * index) / numCircles;\n};\n\nconst getCirclePosition = (angle: number, animationSize: number) => {\n  const radius = animationSize / 2;\n  const x = Math.sin(angle) * radius;\n  const y = -Math.cos(angle) * radius;\n\n  return { x: x.toFixed(1), y: y.toFixed(1) };\n};\n\nconst AriaOnlyAlert = styled.span`\n  ${themeHelpers.visuallyHidden}\n`;\n\nconst Container = styled.div<{ animationSize: number }>`\n  position: relative;\n  height: ${({ animationSize }) => animationSize}px;\n  width: ${({ animationSize }) => animationSize}px;\n  color: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n`;\n\nconst Circle = styled.div<{\n  $position: { x: string; y: string };\n  circleSize: number;\n  circleIndex: number;\n  numCircles: number;\n}>`\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  transform: translate(-50%, -50%)\n    ${({ $position: { x, y } }) => `translate(${x}px, ${y}px)`};\n\n  height: ${({ circleSize }) => circleSize}px;\n  width: ${({ circleSize }) => circleSize}px;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n\n  animation-name: ${({ circleIndex, numCircles }) => keyframes`\n    0% {\n      opacity: 1\n    }\n    ${`${(circleIndex * 100) / numCircles}%`} {\n      opacity: 1\n    }\n    ${`${((circleIndex + 1) * 100) / numCircles}%`} {\n      opacity: 0.3\n    }\n    ${`${((circleIndex + 1) * 100) / numCircles + 1}%`} {\n      opacity: 1\n    }\n  `};\n  animation-fill-mode: both;\n  animation-duration: ${ANIMATION_DURATION}s;\n  animation-iteration-count: infinite;\n  animation-timing-function: ${BEZIER.inOutQuad};\n`;\n\ninterface LoadingSpinnerProps extends ComponentPropsWithoutRef<'div'> {\n  animationSize?: number;\n  circleSize?: number;\n  loadingMessage?: string;\n  numCircles?: number;\n}\n\nfunction LoadingSpinner({\n  animationSize = 95,\n  circleSize = 12,\n  loadingMessage = __('Loading', 'web-stories'),\n  numCircles = 11,\n  ...props\n}: LoadingSpinnerProps) {\n  const ids = useMemo(\n    () =>\n      Array.from({ length: numCircles })\n        .fill(1)\n        .map(() => uuidv4()),\n    [numCircles]\n  );\n\n  return (\n    <Container animationSize={animationSize} {...props}>\n      {loadingMessage && (\n        <AriaOnlyAlert role=\"status\">{loadingMessage}</AriaOnlyAlert>\n      )}\n      {ids.map((id, index) => {\n        const angle = getAngleOfCircle(index, numCircles);\n        const position = getCirclePosition(angle, animationSize);\n\n        return (\n          <Circle\n            key={id}\n            circleIndex={index}\n            circleSize={circleSize}\n            numCircles={numCircles}\n            $position={position}\n          />\n        );\n      })}\n    </Container>\n  );\n}\n\nexport default LoadingSpinner;\n"
  },
  {
    "path": "packages/design-system/src/components/loadingSpinner/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { LoadingSpinner } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/LoadingSpinner',\n  component: LoadingSpinner,\n  args: {\n    animationSize: 95,\n    circleSize: 12,\n    numCircles: 11,\n  },\n  parameters: {\n    controls: {\n      exclude: ['loadingMessage'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <LoadingSpinner {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/loadingSpinner/test/loadingSpinner.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport LoadingSpinner from '../loadingSpinner';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('loadingSpinner', () => {\n  it('should render a loading message that is aria accessible', () => {\n    renderWithProviders(<LoadingSpinner />);\n\n    expect(screen.getByRole('status')).toBeInTheDocument();\n    expect(screen.getByRole('status')).toHaveTextContent('Loading');\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/mediaInput/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as MediaInput } from './mediaInput';\nexport * from './types';\n"
  },
  {
    "path": "packages/design-system/src/components/mediaInput/mediaInput.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css, keyframes } from 'styled-components';\nimport { useState, forwardRef, useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport type { ComponentPropsWithoutRef, ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  Button as DefaultButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '../button';\nimport { Pencil } from '../../icons';\nimport { Menu } from '../menu';\nimport type { DropdownItem, DropdownValue } from '../menu';\nimport { Tooltip } from '../tooltip';\nimport { Placement, Popup } from '../popup';\nimport type { Theme } from '../../theme';\nimport useForwardedRef from '../../utils/useForwardedRef';\nimport Landscape from './icons/landscape.svg';\nimport { MediaVariant } from './types';\n\nconst MediaRectangle = styled.section`\n  width: 100%;\n  height: 100%;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border-radius: 4px;\n  position: relative;\n`;\n\nconst MediaCircle = styled(MediaRectangle)`\n  border-radius: 100px;\n  height: 100%;\n  width: 100%;\n`;\n\nconst EmptyMediaWrapper = styled.div``;\n\nconst ImageWrapper = styled.div<{ variant?: MediaVariant }>`\n  border-radius: ${({ variant }) =>\n    variant === MediaVariant.Circle ? 100 : 4}px;\n  overflow: hidden;\n  height: 100%;\n  display: flex;\n`;\n\nconst DefaultImageWrapper = styled.div`\n  padding: 8px;\n`;\n\nconst DefaultImage = styled(Landscape)`\n  width: 100%;\n  height: 100%;\n  display: block;\n  color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nconst Img = styled.img`\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n`;\n\nconst menuStyleOverride = css`\n  white-space: nowrap;\n  margin-top: 0;\n  li {\n    display: block;\n  }\n`;\n\nconst Button = styled(DefaultButton)<{ showImage?: boolean }>(\n  ({ showImage }) => css`\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryNormal};\n    position: relative;\n\n    ${showImage &&\n    css`\n      position: absolute;\n      bottom: -8px;\n      right: -8px;\n    `}\n\n    &:hover {\n      background-color: ${({ theme }) =>\n        theme.colors.interactiveBg.secondaryHover};\n    }\n  `\n);\n\nconst MediaOptions = {\n  [MediaVariant.Rectangle]: MediaRectangle,\n  [MediaVariant.Circle]: MediaCircle,\n  [MediaVariant.None]: EmptyMediaWrapper,\n};\n\nconst dots = ({ theme }: { theme: Theme }) => keyframes`\n  0%,\n  20% {\n    color: transparent;\n    text-shadow: 6px 0 0 transparent, 12px 0 0 transparent;\n  }\n  40% {\n    color: white;\n    text-shadow: 6px 0 0 transparent, 12px 0 0 transparent;\n  }\n  60% {\n    text-shadow: 6px 0 0\n        ${theme.colors.standard.white},\n      12px 0 0 transparent;\n  }\n  80%,\n  100% {\n    text-shadow: 6px 0 0\n        ${theme.colors.standard.white},\n      12px 0 0 ${theme.colors.standard.white};\n  }\n`;\n\nconst LoadingDots = styled.div`\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  width: 100%;\n  height: 100%;\n  pointer-events: none;\n  border-radius: 50%;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  display: flex;\n\n  &:after {\n    pointer-events: none;\n    color: ${({ theme }) => theme.colors.standard.white};\n    content: '.';\n    font-weight: bold;\n    animation: ${dots} 1s steps(5, end) infinite;\n    margin-left: -12px;\n  }\n`;\n\ninterface MediaInputProps extends Omit<\n  ComponentPropsWithoutRef<'button'>,\n  'value' | 'type'\n> {\n  alt?: string;\n  ariaLabel?: string;\n  variant?: MediaVariant;\n  isLoading?: boolean;\n  menuOptions?: DropdownItem[];\n  onMenuOption: (evt: Event, option: DropdownValue) => void;\n  openMediaPicker: () => void;\n  canUpload: boolean;\n  menuProps?: Omit<ComponentPropsWithoutRef<'button'>, 'type'>;\n  imgProps?: ComponentPropsWithoutRef<'img'>;\n  value: string;\n}\n\nconst MediaInput = forwardRef(function MediaInput(\n  {\n    className,\n    onBlur,\n    alt = __('Preview image', 'web-stories'),\n    value,\n    ariaLabel = __('Choose an image', 'web-stories'),\n    variant = MediaVariant.Rectangle,\n    isLoading,\n    menuOptions = [],\n    onMenuOption,\n    openMediaPicker,\n    canUpload = true,\n    menuProps = {},\n    imgProps = {},\n    ...rest\n  }: MediaInputProps,\n  forwardedRef: ForwardedRef<HTMLButtonElement>\n) {\n  const hasMenu = menuOptions?.length > 0;\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const buttonId = useMemo(() => `button-${uuidv4()}`, []);\n\n  const ref = useForwardedRef(forwardedRef);\n\n  const StyledMedia = MediaOptions[variant];\n  // Media input only allows simplified dropdown with one group.\n  const groups = [{ options: menuOptions }];\n\n  return (\n    <StyledMedia className={className}>\n      {variant !== MediaVariant.None && (\n        <ImageWrapper variant={variant}>\n          {value ? (\n            <Img\n              src={value}\n              alt={alt}\n              crossOrigin=\"anonymous\"\n              decoding=\"async\"\n              width={imgProps?.width}\n              height={imgProps?.height}\n            />\n          ) : (\n            <DefaultImageWrapper>\n              <DefaultImage />\n            </DefaultImageWrapper>\n          )}\n          {isLoading && <LoadingDots />}\n        </ImageWrapper>\n      )}\n      {canUpload && (\n        <Tooltip title={hasMenu ? '' : __('Open media picker', 'web-stories')}>\n          <Button\n            ref={ref}\n            id={buttonId}\n            showImage={variant !== MediaVariant.None}\n            variant={ButtonVariant.Square}\n            type={ButtonType.Quaternary}\n            size={ButtonSize.Small}\n            aria-label={ariaLabel}\n            onClick={hasMenu ? () => setIsMenuOpen(true) : openMediaPicker}\n            aria-owns={hasMenu ? listId : undefined}\n            aria-pressed={isMenuOpen}\n            aria-expanded={isMenuOpen}\n            {...rest}\n          >\n            <Pencil />\n          </Button>\n        </Tooltip>\n      )}\n      <Popup\n        placement={Placement.BottomEnd}\n        anchor={ref}\n        isOpen={isMenuOpen}\n        // Ensure that popup is visible in publish dialog.\n        zIndex={11}\n      >\n        <Menu\n          parentId={buttonId}\n          listId={listId}\n          hasMenuRole\n          groups={groups}\n          handleMenuItemSelect={(evt, val) => {\n            onMenuOption(evt, val);\n            setIsMenuOpen(false);\n          }}\n          onDismissMenu={() => setIsMenuOpen(false)}\n          menuStylesOverride={menuStyleOverride}\n          {...menuProps}\n        />\n      </Popup>\n    </StyledMedia>\n  );\n});\n\nexport default MediaInput;\n"
  },
  {
    "path": "packages/design-system/src/components/mediaInput/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { ThemeProvider } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { theme, TextSize } from '../../../theme';\nimport { MediaInput as DefaultMediaInput } from '..';\nimport { shortDropDownOptions } from '../../../storybookUtils/sampleData';\nimport { MediaVariant } from '../types';\nimport { Headline } from '../../typography/headline';\nimport { Text } from '../../typography/text';\nimport image from './image.jpg';\n\nexport default {\n  title: 'DesignSystem/Components/MediaInput',\n};\n\nconst Container = styled.div`\n  background-color: ${(props) => props.theme.colors.bg.secondary};\n  width: 600px;\n  padding: 30px;\n`;\n\nconst Row = styled.div`\n  width: 100%;\n  margin: 20px 0;\n  display: flex;\n  justify-content: space-evenly;\n`;\n\nconst MediaInput = styled(DefaultMediaInput)`\n  width: 64px;\n  height: 114px;\n`;\n\nconst CircleMedia = styled(DefaultMediaInput)`\n  width: 64px;\n  height: 64px;\n`;\n\nconst mediaProps = {\n  onChange: () => {},\n  openMediaPicker: () => {},\n  onMenuOption: () => {},\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <ThemeProvider theme={theme}>\n        <Container>\n          <Headline as=\"h3\" size={TextSize.Small}>\n            {'Media Input demos'}\n          </Headline>\n          <Row>\n            <div>\n              <Text.Paragraph>\n                {'variant: rectangle'} <br />\n                {'with image'}\n              </Text.Paragraph>\n              <MediaInput\n                value={image}\n                variant={MediaVariant.Rectangle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n            <div>\n              <Text.Paragraph>\n                {'variant: circle'} <br />\n                {'with image'}\n              </Text.Paragraph>\n              <CircleMedia\n                value={image}\n                variant={MediaVariant.Circle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n          </Row>\n          <Row>\n            <div>\n              <Text.Paragraph>\n                {'variant: rectangle'} <br />\n                {'no edit icon'}\n              </Text.Paragraph>\n              <MediaInput\n                value={image}\n                canUpload={false}\n                variant={MediaVariant.Rectangle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n            <div>\n              <Text.Paragraph>\n                {'variant: circle'} <br />\n                {'no edit icon'}\n              </Text.Paragraph>\n              <CircleMedia\n                value={image}\n                canUpload={false}\n                variant={MediaVariant.Circle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n          </Row>\n          <Row>\n            <div>\n              <Text.Paragraph>\n                {'variant: rectangle'} <br />\n                {'without image'}\n              </Text.Paragraph>\n              <MediaInput\n                value={null}\n                variant={MediaVariant.Rectangle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n            <div>\n              <Text.Paragraph>\n                {'variant: circle'} <br />\n                {'without image'}\n              </Text.Paragraph>\n              <CircleMedia\n                value={null}\n                variant={MediaVariant.Circle}\n                menuOptions={shortDropDownOptions}\n                {...mediaProps}\n              />\n            </div>\n          </Row>\n          <Row>\n            <div>\n              <Text.Paragraph>\n                {'variant: rectangle'} <br />\n                {'no menu'}\n              </Text.Paragraph>\n              <MediaInput\n                value={image}\n                variant={MediaVariant.Rectangle}\n                {...mediaProps}\n              />\n            </div>\n            <div>\n              <Text.Paragraph>\n                {'variant: rectangle'} <br />\n                {'no menu'}\n              </Text.Paragraph>\n              <CircleMedia\n                value={image}\n                variant={MediaVariant.Circle}\n                {...mediaProps}\n              />\n            </div>\n          </Row>\n        </Container>\n      </ThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/mediaInput/test/mediaInput.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport MediaInput from '../mediaInput';\nimport { renderWithProviders } from '../../../testUtils';\n\nconst openMediaPicker = jest.fn();\n\ndescribe('mediaInput', () => {\n  it('should have image', () => {\n    renderWithProviders(\n      <MediaInput\n        openMediaPicker={openMediaPicker}\n        value={'http://www.example.com/test.jpg'}\n      />\n    );\n    expect(screen.getByRole('img')).toBeInTheDocument();\n  });\n  it('should have upload button', () => {\n    renderWithProviders(<MediaInput openMediaPicker={openMediaPicker} />);\n    const button = screen.queryByLabelText('Choose an image');\n    expect(button).toBeInTheDocument();\n  });\n  it('should not have upload button', () => {\n    renderWithProviders(\n      <MediaInput openMediaPicker={openMediaPicker} canUpload={false} />\n    );\n    const button = screen.queryByLabelText('Choose an image');\n    expect(button).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/mediaInput/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum MediaVariant {\n  Circle = 'circle',\n  Rectangle = 'rectangle',\n  None = 'none',\n}\n"
  },
  {
    "path": "packages/design-system/src/components/menu/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\nimport type { StyleOverride } from '../../types/theme';\nimport { DEFAULT_DROPDOWN_HEIGHT } from './constants';\n\nexport const MenuContainer = styled.div<{\n  dropDownHeight?: number;\n  styleOverride?: StyleOverride;\n  isAbsolute?: boolean;\n}>(\n  ({\n    dropDownHeight = DEFAULT_DROPDOWN_HEIGHT,\n    styleOverride = '',\n    theme,\n    isAbsolute,\n  }) => css`\n    position: relative;\n    display: flex;\n    flex-direction: row;\n    flex-wrap: wrap;\n    width: calc(100% - 2px);\n    max-height: ${dropDownHeight}px;\n    overflow-x: visible;\n    overflow-y: auto;\n    overscroll-behavior: none auto;\n    z-index: 2;\n    margin-top: 16px;\n    margin-bottom: 8px;\n    padding: 4px 0;\n    background-color: ${theme.colors.bg.primary};\n    border-radius: ${theme.borders.radius.small};\n    border: 1px solid ${theme.colors.divider.primary};\n\n    ${isAbsolute &&\n    css`\n      position: absolute;\n      top: 0;\n      left: 0;\n      right: 0;\n    `};\n\n    ${styleOverride};\n\n    ${themeHelpers.scrollbarCSS};\n  `\n);\n"
  },
  {
    "path": "packages/design-system/src/components/menu/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const DEFAULT_DROPDOWN_HEIGHT = 208;\n\nexport const KEYS_SHIFT_FOCUS = ['up', 'down', 'left', 'right'];\nexport const KEYS_CLOSE_MENU = ['esc', 'tab'];\nexport const KEYS_SELECT_ITEM = ['space', 'enter'];\n"
  },
  {
    "path": "packages/design-system/src/components/menu/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Menu } from './menu';\nexport { DefaultListItemInner, DefaultListItemLabelDisplayText } from './list';\nexport * from './types';\nexport { default as useDropDownMenu } from './useDropDownMenu';\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../../theme';\nimport { Text } from '../../typography';\n\nexport const ListGroup = styled.ul`\n  list-style-type: none;\n  margin: 6px 0;\n  display: block;\n  padding-inline-start: 0;\n  margin-block-start: 0;\n  margin-block-end: 0;\n  width: 100%;\n`;\n\nexport const ListItemLabel = styled.li`\n  display: flex;\n  padding: 6px 2px 6px 8px;\n  margin: 4px 8px;\n  align-items: center;\n`;\n\nexport const ListItem = styled.li<{ disabled?: boolean }>`\n  position: relative;\n  display: grid;\n  grid-template-columns: 32px 1fr;\n  padding: 6px 8px;\n  margin: 4px 8px;\n  align-items: center;\n\n  ${({ disabled, theme }) => css`\n    border-radius: ${theme.borders.radius.small};\n    cursor: ${disabled ? 'default' : 'pointer'};\n    ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n\n    &:hover {\n      background-color: ${theme.colors.bg.tertiary};\n    }\n\n    ${disabled &&\n    css`\n      pointer-events: none;\n\n      span {\n        color: ${theme.colors.fg.secondary};\n      }\n    `}\n\n    svg {\n      color: ${theme.colors.fg.primary};\n    }\n\n    & > span {\n      grid-column-start: 2;\n    }\n  `}\n`;\n\nexport const ListItemDisplayText = styled(Text.Span)(\n  ({ theme }) => css`\n    color: ${theme.colors.fg.primary};\n  `\n);\n\nexport const ListItemLabelDisplayText = styled(Text.Span)(\n  ({ theme }) => css`\n    color: ${theme.colors.form.dropDownSubtitle};\n  `\n);\n\nexport const NoOptionsContainer = styled.div`\n  display: flex;\n  align-items: center;\n  justify-items: center;\n  width: 100%;\n`;\nexport const NoOptionsMessage = styled(Text.Paragraph)`\n  padding: 6px 16px;\n  margin: 4px auto;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/defaultListItem.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type { ForwardedRef } from 'react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { CheckmarkSmall } from '../../../icons';\nimport { TextSize } from '../../../theme';\nimport type { DefaultListItemProps } from '../types';\nimport { ListItem, ListItemDisplayText } from './components';\n\nconst ActiveIcon = styled(CheckmarkSmall)`\n  position: absolute;\n  left: 4px;\n  top: 50%;\n  transform: translateY(-50%);\n`;\n\nconst DefaultListItem = forwardRef(function DefaultListItem(\n  { option, isSelected, ...rest }: DefaultListItemProps,\n  ref: ForwardedRef<HTMLLIElement>\n) {\n  return (\n    <ListItem\n      {...rest}\n      ref={ref}\n      disabled={option.disabled}\n      aria-disabled={option.disabled}\n    >\n      {isSelected && (\n        <ActiveIcon\n          data-testid={'dropdownMenuItem_active_icon'}\n          aria-label={__('Selected', 'web-stories')}\n          width={32}\n          height={32}\n        />\n      )}\n      <ListItemDisplayText size={TextSize.Small}>\n        {option.label}\n      </ListItemDisplayText>\n    </ListItem>\n  );\n});\n\nexport default DefaultListItem;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/emptyList.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { NoOptionsContainer, NoOptionsMessage } from './components';\n\nconst EmptyList = ({ emptyText }: { emptyText?: string }) => {\n  if (!emptyText) {\n    return null;\n  }\n  return (\n    <NoOptionsContainer>\n      <NoOptionsMessage size={TextSize.XSmall}>{emptyText}</NoOptionsMessage>\n    </NoOptionsContainer>\n  );\n};\n\nexport default EmptyList;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/groupLabel.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../../theme';\nimport { ListItemLabel, ListItemLabelDisplayText } from './components';\n\nfunction GroupLabel({ label }: { label?: string }) {\n  if (!label) {\n    return null;\n  }\n  return (\n    <ListItemLabel id={`dropDownMenuLabel-${label}`} role=\"presentation\">\n      <ListItemLabelDisplayText size={TextSize.XSmall}>\n        {label}\n      </ListItemLabelDisplayText>\n    </ListItemLabel>\n  );\n}\n\nexport default GroupLabel;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as DefaultListItem } from './defaultListItem';\nexport { default as EmptyList } from './emptyList';\nexport { default as List } from './list';\nexport { default as ListGroup } from './listGroup';\nexport {\n  ListItem as DefaultListItemInner,\n  ListItemLabelDisplayText as DefaultListItemLabelDisplayText,\n} from './components';\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/list.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport GroupLabel from './groupLabel';\nimport { ListGroup } from './components';\n\ninterface ListProps {\n  isManyGroups?: boolean;\n  label?: string;\n  listId?: string;\n  role?: 'menu' | 'listbox' | 'group';\n}\n\nconst List = ({\n  isManyGroups,\n  label,\n  listId,\n  children,\n  role = 'group',\n}: PropsWithChildren<ListProps>) => {\n  const groupAria = isManyGroups\n    ? { 'aria-label': label }\n    : { 'aria-labelledby': listId };\n\n  return (\n    <ListGroup role={role} {...groupAria}>\n      {label && <GroupLabel label={label} />}\n      {children}\n    </ListGroup>\n  );\n};\n\nexport default List;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/list/listGroup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { MouseEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { getInset } from '../utils';\nimport type { ListGroupProps } from '../types';\nimport DefaultListItem from './defaultListItem';\nimport List from './list';\n\nfunction ListGroup({\n  groups,\n  activeValue,\n  listLength,\n  listId,\n  hasMenuRole,\n  handleMenuItemSelect,\n  renderItem,\n  optionsRef,\n}: ListGroupProps) {\n  const ListItem = renderItem || DefaultListItem;\n  const isManyGroups = groups.length > 1;\n\n  return (\n    <>\n      {groups.map(({ label, options }, groupIndex) => (\n        <List\n          key={label || `menuGroup_${groupIndex}`}\n          isManyGroups={isManyGroups}\n          label={label}\n          listId={listId}\n          role={hasMenuRole ? 'menu' : 'listbox'}\n        >\n          {options.map((groupOption, optionIndex) => {\n            const isSelected = groupOption.value === activeValue;\n            const optionInset = getInset(groups, groupIndex, optionIndex);\n\n            return (\n              <ListItem\n                key={String(groupOption.value)}\n                aria-posinset={optionInset + 1}\n                aria-selected={isSelected}\n                aria-setsize={listLength}\n                id={`dropDownMenuItem-${String(groupOption.value)}`}\n                isSelected={isSelected}\n                onClick={(evt: MouseEvent<HTMLLIElement>) =>\n                  !groupOption.disabled &&\n                  handleMenuItemSelect(evt.nativeEvent, groupOption.value)\n                }\n                option={groupOption}\n                role={hasMenuRole ? 'menuitem' : 'option'}\n                ref={(el: HTMLLIElement | null) => {\n                  if (el && optionsRef?.current) {\n                    optionsRef.current[optionInset] = el;\n                  }\n                }}\n                tabIndex={0}\n              />\n            );\n          })}\n        </List>\n      ))}\n    </>\n  );\n}\nexport default ListGroup;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/menu.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { MenuContainer } from './components';\nimport useDropDownMenu from './useDropDownMenu';\nimport { EmptyList, ListGroup } from './list';\nimport type { MenuProps } from './types';\n\nfunction Menu({\n  dropDownHeight,\n  emptyText,\n  menuStylesOverride,\n  hasMenuRole,\n  handleReturnToParent,\n  isMenuFocused = true,\n  isRTL,\n  groups = [],\n  listId,\n  handleMenuItemSelect,\n  onDismissMenu,\n  renderItem,\n  activeValue,\n  menuAriaLabel,\n  parentId,\n  isAbsolute = false,\n}: MenuProps) {\n  const listRef = useRef<HTMLDivElement | null>(null);\n  const optionsRef = useRef<HTMLLIElement[]>([]);\n\n  const { focusedIndex, listLength } = useDropDownMenu({\n    activeValue,\n    handleMenuItemSelect,\n    isRTL,\n    groups,\n    listRef,\n    onDismissMenu,\n    handleReturnToParent,\n  });\n\n  useEffect(() => {\n    const listEl = listRef?.current;\n\n    if (!listEl || focusedIndex === null || !isMenuFocused) {\n      return;\n    }\n\n    if (focusedIndex === -1) {\n      listEl.scrollTo(0, 0);\n      return;\n    }\n\n    const highlightedOptionEl = optionsRef.current[focusedIndex];\n    if (!highlightedOptionEl) {\n      return;\n    }\n\n    highlightedOptionEl.focus();\n    listEl.scrollTo?.(\n      0,\n      highlightedOptionEl.offsetTop - listEl.clientHeight / 2\n    );\n  }, [focusedIndex, isMenuFocused]);\n\n  return (\n    <MenuContainer\n      id={listId}\n      dropDownHeight={dropDownHeight}\n      styleOverride={menuStylesOverride}\n      ref={listRef}\n      aria-label={menuAriaLabel}\n      aria-labelledby={parentId}\n      aria-expanded=\"true\"\n      isAbsolute={isAbsolute}\n    >\n      {groups.length === 0 ? (\n        <EmptyList emptyText={emptyText} />\n      ) : (\n        <ListGroup\n          groups={groups}\n          activeValue={activeValue}\n          listId={listId}\n          listLength={listLength}\n          hasMenuRole={hasMenuRole}\n          handleMenuItemSelect={handleMenuItemSelect}\n          renderItem={renderItem}\n          optionsRef={optionsRef}\n        />\n      )}\n    </MenuContainer>\n  );\n}\n\nexport default Menu;\n"
  },
  {
    "path": "packages/design-system/src/components/menu/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { useState, forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Menu } from '..';\nimport {\n  basicDropDownOptions,\n  effectChooserOptions,\n  nestedDropDownOptions,\n  reallyLongOptions,\n} from '../../../storybookUtils/sampleData';\nimport { getGroups } from '../utils';\n\nexport default {\n  title: 'DesignSystem/Components/Menu',\n  args: {\n    dropDownHeight: 100,\n    hasMenuRole: true,\n    isRTL: false,\n    menuAriaLabel: 'default aria label',\n    parentId: 'id-menu-associates-with',\n  },\n  argTypes: {\n    onMenuItemClick: { action: 'onMenuItemClick' },\n    onDismissMenu: { action: 'onDismissMenu occurred' },\n  },\n};\n\nconst STANDARD_WIDTH = 400;\nconst NARROW_WIDTH = 150;\n\nconst Container = styled.div`\n  width: ${({ narrow }) => (narrow ? NARROW_WIDTH : STANDARD_WIDTH)}px;\n  height: 100vh;\n  padding: 12px 24px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst StyledEffectListItem = styled.li`\n  border: none;\n  background: ${({ active }) => (active ? '#5732A3' : '#333')};\n  border-radius: 4px;\n  height: 48px;\n  position: relative;\n  overflow: hidden;\n  font-family: 'Teko', sans-serif;\n  font-size: 20px;\n  line-height: 1;\n  color: white;\n  text-transform: uppercase;\n  transition: background 0.1s linear;\n  grid-column-start: ${({ width }) => (width === 'full' ? 'span 4' : 'span 2')};\n  &:focus {\n    background: ${({ active }) => (active ? '#5732A3' : '#B488FC')};\n  }\n`;\n\nconst styleOverrideForAnimationEffectMenu = css`\n  width: 276px;\n  display: inline-block;\n  background: black;\n  ul {\n    display: grid;\n    justify-content: center;\n    gap: 15px 3px;\n    grid-template-columns: repeat(4, 58px);\n    padding: 15px;\n    position: relative;\n  }\n`;\n\nconst _basicDropDownOptions = getGroups(basicDropDownOptions);\nconst _effectChooserOptions = getGroups(effectChooserOptions);\nconst _nestedDropDownOptions = getGroups(nestedDropDownOptions);\nconst _reallyLongOptions = getGroups(reallyLongOptions);\n\nexport const _default = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(\n      basicDropDownOptions[2].value\n    );\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <Menu\n            options={_basicDropDownOptions}\n            listId={'list-id'}\n            onMenuItemClick={(_, newValue) => {\n              onMenuItemClick(newValue);\n              setSelectedValue(newValue);\n            }}\n            activeValue={selectedValue}\n            {...args}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n\nexport const LightTheme = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container>\n        <Menu\n          emptyText={'No options available'}\n          options={_basicDropDownOptions}\n          listId={'list-id'}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          activeValue={selectedValue}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\nexport const NoOptionsMenu = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container>\n        <Menu\n          emptyText={'No options available'}\n          options={[]}\n          listId={'list-id'}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          activeValue={selectedValue}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\nexport const ReallyLongLabelsMenu = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n\n    return (\n      <Container narrow>\n        <Menu\n          emptyText={'No options available'}\n          options={_reallyLongOptions}\n          listId={'list-id'}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          activeValue={selectedValue}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\nexport const SubMenus = {\n  render: function Render({ onMenuItemClick, ...args }) {\n    const [selectedValue, setSelectedValue] = useState('dog-2');\n\n    return (\n      <Container>\n        <Menu\n          emptyText={'No options available'}\n          options={_nestedDropDownOptions}\n          listId={'list-id'}\n          onMenuItemClick={(_, newValue) => {\n            onMenuItemClick(newValue);\n            setSelectedValue(newValue);\n          }}\n          activeValue={selectedValue}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n\nconst RenderItemOverride = forwardRef(\n  ({ option, isSelected, ...rest }, ref) => (\n    <StyledEffectListItem\n      ref={ref}\n      width={option.width}\n      active={isSelected}\n      {...rest}\n    >\n      {option.label}\n    </StyledEffectListItem>\n  )\n);\nRenderItemOverride.propTypes = {\n  option: PropTypes.object,\n  isSelected: PropTypes.bool,\n};\n\nexport const OverriddenAnimationProofOfConcept = {\n  render: function Render({\n    // eslint-disable-next-line react/prop-types\n    onMenuItemClick,\n    ...args\n  }) {\n    const [selectedValue, setSelectedValue] = useState(null);\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <Menu\n            emptyText={'No options available'}\n            options={_effectChooserOptions}\n            listId={'list-id'}\n            onMenuItemClick={(_, newValue) => {\n              onMenuItemClick(newValue);\n              setSelectedValue(newValue);\n            }}\n            activeValue={selectedValue}\n            menuStylesOverride={styleOverrideForAnimationEffectMenu}\n            renderItem={RenderItemOverride}\n            {...args}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/menu/test/menu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport Menu from '../menu';\nimport { basicDropDownOptions } from '../../../storybookUtils/sampleData';\nimport { getGroups } from '../utils';\n\nconst groupedOptions = getGroups(basicDropDownOptions);\n\nconst onClickMock = jest.fn();\nconst scrollTo = jest.fn();\n\ndescribe('<Menu />', () => {\n  beforeAll(() => {\n    // Mock scrollTo\n    Object.defineProperty(window.Element.prototype, 'scrollTo', {\n      writable: true,\n      value: scrollTo,\n    });\n  });\n\n  it('should render a <Menu /> list with 12 items', () => {\n    renderWithProviders(\n      <Menu\n        listId=\"foo\"\n        parentId=\"bar\"\n        hasMenuRole={false}\n        emptyText={'No options available'}\n        groups={groupedOptions}\n        handleMenuItemSelect={onClickMock}\n        onDismissMenu={() => {}}\n        activeValue={null}\n      />\n    );\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n\n    const options = screen.queryAllByRole('option');\n    expect(options).toHaveLength(12);\n  });\n\n  it('should return an emptyText message when there are no items to display', () => {\n    renderWithProviders(\n      <Menu\n        listId=\"foo\"\n        parentId=\"bar\"\n        hasMenuRole={false}\n        emptyText={'No options available'}\n        groups={[]}\n        handleMenuItemSelect={onClickMock}\n        onDismissMenu={() => {}}\n        activeValue={null}\n      />\n    );\n\n    const emptyMessage = screen.getByText('No options available');\n    expect(emptyMessage).toBeInTheDocument();\n  });\n\n  it('should trigger handleMenuItemSelect when list item is clicked', () => {\n    renderWithProviders(\n      <Menu\n        listId=\"foo\"\n        parentId=\"bar\"\n        hasMenuRole={false}\n        emptyText={'No options available'}\n        groups={groupedOptions}\n        handleMenuItemSelect={onClickMock}\n        onDismissMenu={() => {}}\n        activeValue={null}\n      />\n    );\n\n    const option3 = screen.queryAllByRole('option')[2];\n    expect(option3).toHaveTextContent(basicDropDownOptions[2].label);\n\n    fireEvent.click(option3);\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n\n  it('should override list items when renderMenu is present', () => {\n    const OverrideRenderItem = forwardRef(({ isSelected, ...rest }, ref) => {\n      return (\n        <li {...rest} ref={ref}>\n          {/* eslint-disable-next-line jest/no-conditional-in-test */}\n          {isSelected ? 'I AM SELECTED' : 'I AM EXTRA CONTENT'}\n        </li>\n      );\n    });\n    OverrideRenderItem.propTypes = {\n      isSelected: PropTypes.bool,\n    };\n\n    renderWithProviders(\n      <Menu\n        listId=\"foo\"\n        parentId=\"bar\"\n        hasMenuRole={false}\n        emptyText={'No options available'}\n        groups={groupedOptions}\n        handleMenuItemSelect={onClickMock}\n        onDismissMenu={() => {}}\n        activeValue={basicDropDownOptions[2].value}\n        renderItem={OverrideRenderItem}\n      />\n    );\n\n    const itemsNotSelected = screen.queryAllByText('I AM EXTRA CONTENT');\n    const selectedItem = screen.getByText('I AM SELECTED');\n\n    expect(itemsNotSelected).toHaveLength(11);\n    expect(selectedItem).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/menu/test/useDropDownMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\n\nimport {\n  basicDropDownOptions,\n  nestedDropDownOptions,\n} from '../../../testUtils/sampleData';\nimport useDropDownMenu from '../useDropDownMenu';\nimport { getGroups } from '../utils';\n\ndescribe('useDropDownMenu()', () => {\n  it('should have the default options initially selected', () => {\n    const { result } = renderHook(() =>\n      useDropDownMenu({\n        handleMenuItemSelect: () => {},\n        groups: getGroups(basicDropDownOptions),\n        listRef: { current: null },\n        onDismissMenu: () => {},\n      })\n    );\n\n    expect(result.current.focusedIndex).toBe(0);\n    expect(result.current.focusedValue).toBeUndefined();\n  });\n\n  it('should return focused index matching activeValue passed in initially if present', () => {\n    const { result } = renderHook(() =>\n      useDropDownMenu({\n        activeValue: basicDropDownOptions[2].value,\n        handleMenuItemSelect: () => {},\n        groups: getGroups(basicDropDownOptions),\n        listRef: { current: null },\n        onDismissMenu: () => {},\n      })\n    );\n\n    expect(result.current.focusedIndex).toBe(2);\n    expect(result.current.focusedValue).toBe(basicDropDownOptions[2].value);\n  });\n\n  it('should return focused index matching activeValue passed in initially if present in a nested list', () => {\n    const { result } = renderHook(() =>\n      useDropDownMenu({\n        activeValue: 'dog-2',\n        handleMenuItemSelect: () => {},\n        groups: getGroups(nestedDropDownOptions),\n        listRef: { current: null },\n        onDismissMenu: () => {},\n      })\n    );\n\n    expect(result.current.focusedIndex).toBe(15);\n    expect(result.current.focusedValue).toBe('dog-2');\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/menu/test/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { badOptions } from '../../../testUtils/sampleData';\nimport { getGroups, getInset } from '../utils';\n\nconst basicDropDownOptions = [\n  {\n    label: 'label item one',\n    value: 'label-item-one',\n  },\n  {\n    label: 'label item two',\n    value: 'label-item-two',\n  },\n  {\n    label: 'label item three',\n    value: 'label-item-three',\n  },\n];\n\ndescribe('DropDown/utils getGroups', () => {\n  it('should shape and sanititize basic dropDown options', () => {\n    const groupedOptions = getGroups(basicDropDownOptions);\n\n    expect(groupedOptions).toStrictEqual([\n      {\n        options: [\n          {\n            label: 'label item one',\n            value: 'label-item-one',\n          },\n          {\n            label: 'label item two',\n            value: 'label-item-two',\n          },\n          {\n            label: 'label item three',\n            value: 'label-item-three',\n          },\n        ],\n      },\n    ]);\n  });\n\n  it('should shape and sanitize basic dropDown options even when some shaped data is bad', () => {\n    const groupedOptions = getGroups([\n      ...basicDropDownOptions,\n      'just a string',\n      { label: 'bad data sneaking through', somethingNew: [1, 2, 3] },\n    ]);\n\n    expect(groupedOptions).toStrictEqual([\n      {\n        options: [\n          {\n            label: 'label item one',\n            value: 'label-item-one',\n          },\n          {\n            label: 'label item two',\n            value: 'label-item-two',\n          },\n          {\n            label: 'label item three',\n            value: 'label-item-three',\n          },\n        ],\n      },\n    ]);\n  });\n\n  it('should shape and sanitize dropDown options even when some value data is bad', () => {\n    const groupedOptions = getGroups(badOptions);\n\n    expect(groupedOptions).toStrictEqual([\n      {\n        options: [\n          {\n            label: '0 as a number',\n            value: 0,\n          },\n          {\n            label: '0 as a string',\n            value: '0',\n          },\n          {\n            label: 'false as a boolean',\n            value: false,\n          },\n          {\n            label: 'false as a string',\n            value: 'false',\n          },\n          {\n            label: 'true as a boolean',\n            value: true,\n          },\n        ],\n      },\n    ]);\n    expect(badOptions).toHaveLength(6);\n  });\n\n  it('should shape and sanitize nested dropDown options', () => {\n    const nestedDropDownOptions = [\n      'something terrible',\n      ['lions', 'tigers', 'bears'],\n      {\n        label: 'aliens',\n        options: [\n          { value: 'alien-1', label: 'ET' },\n          { value: 'alien-2', label: 'Stitch' },\n          { value: 'alien-3', label: 'Groot' },\n        ],\n      },\n      {\n        label: 'dogs',\n        options: [\n          { value: 'dog-1', label: 'Snoopy' },\n          { value: 'dog-2', label: 'Scooby' },\n        ],\n      },\n      {\n        label: 'tricky content',\n        options: [\n          { value: 0, label: '0 as a number' },\n          { value: false, label: 'false as a boolean' },\n          { value: true, label: 'true as a boolean' },\n          { value: undefined, label: \"undefined and shouldn't come through\" },\n        ],\n      },\n    ];\n\n    const groupedOptions = getGroups(nestedDropDownOptions);\n\n    expect(groupedOptions).toStrictEqual([\n      {\n        options: [\n          { label: 'ET', value: 'alien-1' },\n          { label: 'Stitch', value: 'alien-2' },\n          { label: 'Groot', value: 'alien-3' },\n        ],\n        label: 'aliens',\n      },\n      {\n        options: [\n          {\n            label: 'Snoopy',\n            value: 'dog-1',\n          },\n          {\n            label: 'Scooby',\n            value: 'dog-2',\n          },\n        ],\n        label: 'dogs',\n      },\n      {\n        options: [\n          {\n            label: '0 as a number',\n            value: 0,\n          },\n          {\n            label: 'false as a boolean',\n            value: false,\n          },\n          {\n            label: 'true as a boolean',\n            value: true,\n          },\n        ],\n        label: 'tricky content',\n      },\n    ]);\n  });\n});\n\ndescribe('DropDown/utils getInset', () => {\n  it('should take sanitized dropDown options and structure placement by group', () => {\n    const sanitizedOptions = getGroups(basicDropDownOptions);\n    const option = getInset(sanitizedOptions, 0, 2);\n\n    expect(option).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/menu/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  ComponentPropsWithoutRef,\n  FC,\n  RefAttributes,\n  RefObject,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { StyleOverride } from '../../types/theme';\n\nexport type DropdownValue = string | number | boolean;\nexport interface DropdownItem {\n  label: string;\n  value: DropdownValue;\n  disabled?: boolean;\n}\nexport interface NestedDropdownItem {\n  label?: string;\n  options: DropdownItem[];\n}\n\nexport interface DefaultListItemProps extends ComponentPropsWithoutRef<'li'> {\n  option: DropdownItem;\n  isSelected?: boolean;\n}\n\nexport type ListItemProps = DefaultListItemProps & RefAttributes<HTMLLIElement>;\n\nexport interface SharedMenuProps {\n  groups: NestedDropdownItem[];\n  activeValue?: DropdownValue;\n  handleMenuItemSelect: (evt: Event, value: DropdownValue) => void;\n\n  handleReturnToParent?: () => void;\n  isRTL?: boolean;\n  onDismissMenu: (evt: Event) => void;\n\n  listId?: string;\n  hasMenuRole?: boolean;\n  renderItem?: FC<ListItemProps>;\n}\n\nexport interface UseDropDownMenuProps extends Omit<\n  SharedMenuProps,\n  'listId' | 'hasMenuRole' | 'renderItem'\n> {\n  listRef: RefObject<HTMLElement>;\n}\n\nexport interface ListGroupProps extends Omit<\n  SharedMenuProps,\n  'handleReturnToParent' | 'isRTL' | 'onDismissMenu'\n> {\n  optionsRef: RefObject<HTMLLIElement[]>;\n  listLength?: number;\n}\n\nexport interface MenuProps extends SharedMenuProps {\n  dropDownHeight?: number;\n  emptyText?: string;\n  menuStylesOverride?: StyleOverride;\n  isMenuFocused?: boolean;\n  menuAriaLabel?: string;\n  parentId?: string;\n  isAbsolute?: boolean;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/menu/useDropDownMenu.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n  useFocusOut,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { isNullOrUndefinedOrEmptyString } from '../../utils';\nimport { useKeyDownEffect } from '../keyboard';\nimport {\n  KEYS_CLOSE_MENU,\n  KEYS_SELECT_ITEM,\n  KEYS_SHIFT_FOCUS,\n} from './constants';\nimport type { DropdownValue, UseDropDownMenuProps } from './types';\n\nexport default function useDropDownMenu({\n  activeValue,\n  handleMenuItemSelect,\n  handleReturnToParent,\n  isRTL,\n  groups = [],\n  listRef,\n  onDismissMenu,\n}: UseDropDownMenuProps) {\n  const allOptions = useMemo(\n    () => groups.flatMap(({ options }) => options),\n    [groups]\n  );\n\n  const listLength = allOptions.length;\n  const [focusedValue, setFocusedValue] = useState<\n    DropdownValue | null | undefined\n  >(activeValue);\n\n  const getFocusedIndex = useCallback(\n    () =>\n      allOptions.findIndex(\n        (option) => String(option?.value) === String(focusedValue)\n      ),\n    [allOptions, focusedValue]\n  );\n\n  // there's an edge case in this menu when the activeValue given to a menu isn't present\n  // in the options passed to it that we want to check against when this first renders.\n\n  useEffect(() => {\n    if (isNullOrUndefinedOrEmptyString(focusedValue)) {\n      return;\n    }\n    const validFocusedIndex = getFocusedIndex();\n\n    if (validFocusedIndex === -1) {\n      setFocusedValue(null);\n    }\n  }, [focusedValue, getFocusedIndex]);\n\n  const focusedIndex = useMemo(() => {\n    if (isNullOrUndefinedOrEmptyString(focusedValue)) {\n      return 0;\n    }\n    const foundIndex = getFocusedIndex();\n\n    return foundIndex;\n  }, [focusedValue, getFocusedIndex]);\n\n  const handleMoveFocus = useCallback(\n    (offset: number) =>\n      setFocusedValue(allOptions[focusedIndex + offset].value),\n    [allOptions, focusedIndex]\n  );\n\n  const handleFocusChange = useCallback(\n    ({ key }: KeyboardEvent) => {\n      const forward = isRTL ? 'ArrowRight' : 'ArrowLeft';\n      const isForward = ['ArrowUp', forward].includes(key);\n      const backward = isRTL ? 'ArrowLeft' : 'ArrowRight';\n      const isBackward = ['ArrowDown', backward].includes(key);\n\n      if (isForward) {\n        if (focusedIndex === 0) {\n          handleReturnToParent?.();\n        } else {\n          handleMoveFocus(-1);\n        }\n      } else if (isBackward && focusedIndex < listLength - 1) {\n        handleMoveFocus(1);\n      }\n    },\n    [focusedIndex, handleMoveFocus, handleReturnToParent, isRTL, listLength]\n  );\n\n  const handleMenuItemEnter = useCallback(\n    (event: Event) => {\n      const isDisabledItem = allOptions[focusedIndex]?.disabled;\n      if (isDisabledItem) {\n        return () => undefined;\n      }\n      const selectedValue = focusedValue || allOptions[focusedIndex].value;\n      return handleMenuItemSelect(event, selectedValue);\n    },\n    [allOptions, focusedIndex, focusedValue, handleMenuItemSelect]\n  );\n\n  useKeyDownEffect(\n    listRef,\n    { key: KEYS_SELECT_ITEM, shift: true },\n    handleMenuItemEnter,\n    [handleMenuItemEnter]\n  );\n\n  useKeyDownEffect(\n    listRef,\n    { key: KEYS_CLOSE_MENU },\n    (event) => onDismissMenu?.(event),\n    [onDismissMenu]\n  );\n\n  useKeyDownEffect(listRef, { key: KEYS_SHIFT_FOCUS }, handleFocusChange, [\n    handleFocusChange,\n  ]);\n\n  useFocusOut(listRef, (event) => onDismissMenu?.(event), []);\n\n  return useMemo(\n    () => ({\n      focusedValue,\n      focusedIndex,\n      listLength,\n    }),\n    [focusedIndex, focusedValue, listLength]\n  );\n}\n"
  },
  {
    "path": "packages/design-system/src/components/menu/utils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { DropdownItem, NestedDropdownItem } from './types';\n\nfunction isValid(opt: DropdownItem) {\n  return typeof opt === 'object' && typeof opt.value !== 'undefined';\n}\n\nexport function getGroups(\n  source: NestedDropdownItem[] | DropdownItem[]\n): NestedDropdownItem[] {\n  if (source.length === 0) {\n    return [];\n  }\n  const isNested = source.some(\n    (opt) => typeof opt === 'object' && 'options' in opt\n  );\n  if (isNested) {\n    const nestedOptions = source as NestedDropdownItem[];\n    return nestedOptions\n      .map((group) => ({\n        ...group,\n        options: (group.options || []).filter(isValid),\n      }))\n      .filter(({ options }) => options.length > 0);\n  }\n\n  // Double check that all data in groups should be treated as options to sanitize data\n  const options = (source as DropdownItem[]).filter(isValid);\n  return options.length ? [{ options }] : [];\n}\n\nexport function getInset(\n  groups: NestedDropdownItem[],\n  i: number,\n  j: number\n): number {\n  return (\n    groups\n      .slice(0, i)\n      .map(({ options }) => options.length)\n      .reduce((a: number, b: number) => a + b, 0) + j\n  );\n}\n"
  },
  {
    "path": "packages/design-system/src/components/modal/constants.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const BODY_CLASS = 'WebStories_ReactModal__Body--open';\nexport const CONTENT_CLASS = 'WebStories_ReactModal__Content';\nexport const OVERLAY_CLASS = 'WebStories_ReactModal__Overlay';\n"
  },
  {
    "path": "packages/design-system/src/components/modal/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Modal } from './modal';\nexport { ModalGlobalStyle } from './styles';\nexport { BODY_CLASS, CONTENT_CLASS, OVERLAY_CLASS } from './constants';\n"
  },
  {
    "path": "packages/design-system/src/components/modal/modal.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextReact as useContext } from '@googleforcreators/react';\nimport type { ComponentProps, CSSProperties } from 'react';\nimport ReactModal from 'react-modal';\nimport { ThemeContext } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Theme } from '../../theme';\nimport { BODY_CLASS, CONTENT_CLASS, OVERLAY_CLASS } from './constants';\n\nconst customStyles = {\n  overlay: (theme: Theme) =>\n    ({\n      position: 'fixed',\n      top: 0,\n      left: 0,\n      right: 0,\n      bottom: 0,\n      zIndex: 10,\n      backgroundColor: theme.colors.interactiveBg.modalScrim,\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n    }) as const,\n  content: {\n    overflow: 'auto',\n    outline: 'none',\n    display: 'flex',\n    maxHeight: '100%',\n    justifyContent: 'center',\n  },\n};\n\ntype ReactModalProps = ComponentProps<typeof ReactModal>;\n\ninterface ModalProps extends ReactModalProps {\n  onClose?: ReactModalProps['onRequestClose'];\n  modalStyles?: CSSProperties;\n  overlayStyles?: CSSProperties;\n  contentStyles?: CSSProperties;\n}\n\nfunction Modal({\n  closeTimeoutMS = 100,\n  children,\n  contentStyles,\n  modalStyles = {},\n  onClose,\n  overlayStyles,\n  ...rest\n}: ModalProps) {\n  const theme = useContext(ThemeContext);\n\n  return (\n    <ReactModal\n      className={CONTENT_CLASS}\n      closeTimeoutMS={closeTimeoutMS}\n      onRequestClose={onClose}\n      overlayClassName={OVERLAY_CLASS}\n      bodyOpenClassName={BODY_CLASS}\n      style={{\n        maxHeight: '100vh',\n        ...modalStyles,\n        overlay: { ...customStyles.overlay(theme), ...overlayStyles },\n        content: { ...customStyles.content, ...contentStyles },\n      }}\n      {...rest}\n    >\n      {children}\n    </ReactModal>\n  );\n}\n\nexport default Modal;\n"
  },
  {
    "path": "packages/design-system/src/components/modal/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { Button, ButtonSize, ButtonType } from '../../button';\nimport { Text, Headline } from '../../typography';\nimport { Modal } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/Modal',\n  component: Modal,\n  argTypes: {\n    onClose: { action: 'close modal clicked' },\n  },\n  parameters: {\n    controls: { include: ['onClose'] },\n  },\n};\n\nexport const _default = {\n  render: function Render({ onClose }) {\n    const [toggleModal, setToggleModal] = useState(false);\n    return (\n      <>\n        <Headline as=\"h1\">{'Lorem ipsum dolor'}</Headline>\n        <Text.Paragraph>\n          {\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '\n          }\n        </Text.Paragraph>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => setToggleModal(!toggleModal)}\n        >\n          {'Toggle Modal'}\n        </Button>\n\n        <Modal\n          ariaHideApp={false} // this is ONLY for storybook to eliminate a warning, we set the app id in the root index of dashboard\n          contentLabel={'my storybook modal label'}\n          aria={{\n            labelledby: 'additional Headline for aria - optional',\n            describedby: 'additional described by for aria - optional',\n          }}\n          isOpen={toggleModal}\n          onClose={() => {\n            onClose();\n            setToggleModal(!toggleModal);\n          }}\n        >\n          <div>\n            <Headline as=\"h2\">{'Ut enim ad minim veniam'}</Headline>\n            <Text.Paragraph>\n              {\n                'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'\n              }\n            </Text.Paragraph>\n          </div>\n        </Modal>\n      </>\n    );\n  },\n};\n\nexport const OverriddenStyles = {\n  render: function Render({ onClose }) {\n    const [toggleModal, setToggleModal] = useState(false);\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Lorem ipsum dolor'}</Headline>\n        <Text.Paragraph>\n          {\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '\n          }\n        </Text.Paragraph>\n        <Button\n          size={ButtonSize.Small}\n          type={ButtonType.Primary}\n          onClick={() => setToggleModal(!toggleModal)}\n        >\n          {'Toggle Modal'}\n        </Button>\n\n        <Modal\n          ariaHideApp={false} // this is ONLY for storybook to eliminate a warning, we set the app id in the root index of dashboard\n          isOpen={toggleModal}\n          onClose={() => {\n            onClose();\n            setToggleModal(!toggleModal);\n          }}\n          contentStyles={{\n            backgroundColor: 'salmon',\n            borderRadius: '5px',\n            padding: '10px 20px',\n          }}\n          overlayStyles={{\n            backgroundColor: 'rgba(255, 255, 255, 0.75)',\n          }}\n        >\n          <div>\n            <Headline as=\"h2\">{'Ut enim ad minim veniam'}</Headline>\n            <Text.Paragraph>\n              {\n                'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'\n              }\n            </Text.Paragraph>\n          </div>\n        </Modal>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/modal/styles.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { OVERLAY_CLASS } from './constants';\n\nexport const ModalGlobalStyle = createGlobalStyle`\n  .${OVERLAY_CLASS} {\n    opacity: 0;\n    transition: opacity 0.1s ease-out;\n  }\n\n  .${OVERLAY_CLASS}.ReactModal__Overlay--after-open {\n    opacity: 1;\n  }\n\n  .${OVERLAY_CLASS}.ReactModal__Overlay--before-close {\n    opacity: 0;\n  }\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/modal/test/modal.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport ReactModal from 'react-modal';\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport Modal from '../modal';\n\ndescribe('DesignSystem/Components/Modal', () => {\n  it('should not render a modal by default', () => {\n    const { container } = renderWithProviders(\n      <Modal onClose={jest.fn}>\n        <p>{'modal child'}</p>\n      </Modal>\n    );\n    ReactModal.setAppElement(container);\n\n    expect(\n      screen.queryByRole('dialog', { hidden: true })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render a modal when isOpen is true', () => {\n    const { container } = renderWithProviders(\n      <Modal onClose={jest.fn} isOpen>\n        <p>{'modal child'}</p>\n      </Modal>\n    );\n    ReactModal.setAppElement(container);\n\n    expect(screen.getByRole('dialog')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/notificationBubble/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as NotificationBubble } from './notificationBubble';\nexport * from './types';\n"
  },
  {
    "path": "packages/design-system/src/components/notificationBubble/notificationBubble.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\nimport { BubbleVariant, type NotificationBubbleProps } from './types';\n\nconst BUBBLE_DIAMETER = 24;\nconst SMALL_BUBBLE_DIAMETER = 20;\n\nfunction getBubbleWidth(numDigits: number) {\n  return 9 * (numDigits - 1);\n}\n\nconst Bubble = styled.div<{\n  variant: BubbleVariant;\n  digitLen: number;\n  $isSmall?: boolean;\n}>`\n  ${({ theme, variant }) => css`\n    color: ${theme.colors.fg.primary};\n    background-color: ${theme.colors.bg[variant]};\n    border-radius: ${theme.borders.radius.round};\n  `}\n  position: relative;\n  height: ${BUBBLE_DIAMETER}px;\n  width: ${({ digitLen }) => BUBBLE_DIAMETER + getBubbleWidth(digitLen)}px;\n\n  ${({ digitLen, $isSmall }) =>\n    $isSmall &&\n    css`\n      height: ${SMALL_BUBBLE_DIAMETER}px;\n      width: ${SMALL_BUBBLE_DIAMETER + getBubbleWidth(digitLen)}px;\n    `};\n`;\n\nconst Inner = styled.span<{\n  $invertColor?: boolean;\n  $isSmall?: boolean;\n}>`\n  ${themeHelpers.fullSizeAbsolute}\n  ${themeHelpers.centerContent}\n  ${({ $isSmall, theme }) =>\n    themeHelpers.expandTextPreset(\n      ({ paragraph }, sizes) => paragraph[$isSmall ? sizes.XSmall : sizes.Small]\n    )({ theme })};\n  font-weight: ${({ theme }) => theme.typography.weight.bold};\n  color: ${({ $invertColor, theme }) =>\n    $invertColor ? theme.colors.inverted.fg.primary : theme.colors.fg.primary};\n  user-select: none;\n`;\n\nfunction NotificationBubble({\n  notificationCount,\n  isSmall,\n  variant = BubbleVariant.Accent,\n  invertTextColor,\n  ...props\n}: NotificationBubbleProps) {\n  return (\n    <Bubble\n      variant={variant}\n      $isSmall={isSmall}\n      digitLen={notificationCount?.toString().length || 1}\n      {...props}\n    >\n      <Inner $invertColor={invertTextColor} $isSmall={isSmall}>\n        {notificationCount}\n      </Inner>\n    </Bubble>\n  );\n}\n\nexport default NotificationBubble;\n"
  },
  {
    "path": "packages/design-system/src/components/notificationBubble/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Headline } from '../../typography';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { NotificationBubble, BubbleVariant } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/NotificationBubble',\n  component: NotificationBubble,\n  args: {\n    isSmall: false,\n    invertTextColor: false,\n    notificationCount: 6,\n  },\n  parameters: {\n    controls: {\n      exclude: ['variant'],\n    },\n  },\n};\n\nconst VARIANT_OPTIONS = Object.values(BubbleVariant);\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;\n  grid-column: 1 / -1;\n\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <>\n        <Headline>{'Notification Bubble'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            {VARIANT_OPTIONS.map((variant) => (\n              <NotificationBubble key={variant} variant={variant} {...args} />\n            ))}\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Row>\n              {VARIANT_OPTIONS.map((variant) => (\n                <NotificationBubble key={variant} variant={variant} {...args} />\n              ))}\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/notificationBubble/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\n\nexport enum BubbleVariant {\n  Primary = 'primary',\n  Secondary = 'secondary',\n  Tertiary = 'tertiary',\n  Quaternary = 'quaternary',\n  Positive = 'positive',\n  Negative = 'negative',\n  Accent = 'accent',\n}\n\nexport interface NotificationBubbleProps extends ComponentPropsWithoutRef<'div'> {\n  notificationCount: number;\n  isSmall?: boolean;\n  variant?: BubbleVariant;\n  invertTextColor?: boolean;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/pill/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Pill } from './pill';\nexport { default as PillGroup } from './pillGroup';\n"
  },
  {
    "path": "packages/design-system/src/components/pill/pill.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n  PropsWithChildren,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../theme';\n\nconst StyledPill = styled.button<{\n  isActive?: boolean;\n  styleOverride?: string;\n}>(\n  ({ isActive, theme, styleOverride }) => css`\n    display: flex;\n    align-items: center;\n    justify-content: space-around;\n    padding: 6px 16px;\n    height: 32px;\n\n    background-color: ${isActive\n      ? theme.colors.interactiveBg.primaryNormal\n      : theme.colors.opacity.footprint};\n    border: none;\n    border-radius: ${theme.borders.radius.x_large};\n    ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n\n    color: ${isActive ? theme.colors.bg.primary : theme.colors.fg.secondary};\n    cursor: pointer;\n    ${themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.label[TextSize.Small],\n      theme,\n    })};\n\n    &:disabled {\n      pointer-events: none;\n      color: ${isActive ? theme.colors.bg.primary : theme.colors.fg.disable};\n    }\n\n    transition: color 0.3s ease 0s;\n    transition: background-color 0.3s ease 0s;\n\n    ${styleOverride};\n  `\n);\n\ninterface PillProps extends ComponentPropsWithoutRef<'button'> {\n  isActive?: boolean;\n  pillStyleOverride?: string;\n}\n\nconst Pill = forwardRef(function Pill(\n  {\n    children,\n    isActive,\n    onClick,\n    pillStyleOverride,\n    ...rest\n  }: PropsWithChildren<PillProps>,\n  ref: ForwardedRef<HTMLButtonElement>\n) {\n  return (\n    <StyledPill\n      ref={ref}\n      isActive={isActive}\n      onClick={onClick}\n      styleOverride={pillStyleOverride}\n      {...rest}\n    >\n      {children}\n    </StyledPill>\n  );\n});\n\nexport default Pill;\n"
  },
  {
    "path": "packages/design-system/src/components/pill/pillGroup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Pill from './pill';\n\nconst Container = styled.div.attrs({\n  role: 'listbox',\n})`\n  display: flex;\n  flex: 1;\n  column-gap: 4px;\n`;\n\ninterface PillOption {\n  id: string;\n  label: string;\n}\n\ninterface PillGroupProps extends Omit<\n  ComponentPropsWithoutRef<'button'>,\n  'onSelect' | 'onClick'\n> {\n  options: PillOption[];\n  value: string;\n  onSelect: (id: string) => void;\n}\n\nfunction PillGroup({ options, value, onSelect, ...rest }: PillGroupProps) {\n  return (\n    <Container>\n      {options.map(({ id, label }) => (\n        <Pill\n          key={id}\n          isActive={id === value}\n          onClick={() => onSelect(id)}\n          role=\"option\"\n          {...rest}\n        >\n          {label}\n        </Pill>\n      ))}\n    </Container>\n  );\n}\n\nexport default PillGroup;\n"
  },
  {
    "path": "packages/design-system/src/components/pill/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { ThemeProvider } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { theme } from '../../../theme';\nimport { Pill, PillGroup } from '..';\n\nexport default {\n  title: 'DesignSystem/Components/Pill',\n  args: {\n    pill1: 'pill 1 text',\n    pill2: 'pill 2 text',\n    pill3: 'pill 3 text',\n    pill1isActive: true,\n    pill2isActive: true,\n    pill3isActive: true,\n  },\n  argTypes: {\n    pill1: { name: 'first pill' },\n    pill2: { name: 'second pill' },\n    pill3: { name: 'third pill' },\n    pill1isActive: { name: 'first pill isActive' },\n    pill2isActive: { name: 'second pill isActive' },\n    pill3isActive: { name: 'third pill isActive' },\n    onClick: { action: 'clicked' },\n  },\n};\n\nconst Container = styled.div`\n  background-color: ${(props) => props.theme.colors.bg.primary};\n  padding: 30px;\n  display: flex;\n  gap: 12px;\n`;\n\n// eslint-disable-next-line react/prop-types\nfunction PillContainer({ prefix, onClick, ...args }) {\n  let message;\n  let active;\n\n  return (\n    <Container>\n      {[1, 2, 3].map((i) => {\n        switch (i) {\n          case 1:\n            message = args.pill1;\n            active = args.pill1isActive;\n            break;\n          case 2:\n            message = args.pill2;\n            active = args.pill2isActive;\n\n            break;\n          case 3:\n            message = args.pill3;\n            active = args.pill3isActive;\n\n            break;\n\n          default:\n            break;\n        }\n        return (\n          <Pill\n            key={i}\n            isActive={active}\n            onClick={(e) => onClick(`Theme: ${prefix}; pill: ${i}`, e)}\n          >\n            {message}\n          </Pill>\n        );\n      })}\n    </Container>\n  );\n}\n\nPillContainer.propTypes = {\n  prefix: PropTypes.string.isRequired,\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <>\n        <PillContainer prefix=\"Light\" {...args} />\n        <ThemeProvider theme={theme}>\n          <PillContainer prefix=\"Dark\" {...args} />\n        </ThemeProvider>\n      </>\n    );\n  },\n};\n\nconst PILL_OPTIONS = [\n  { id: 1, label: 'George' },\n  { id: 2, label: 'Ringo' },\n  { id: 3, label: 'Paul' },\n  { id: 4, label: 'John' },\n];\n\nfunction PillGroupContainer(args) {\n  const [active, setActive] = useState(1);\n  return (\n    <Container>\n      <PillGroup\n        options={PILL_OPTIONS}\n        value={active}\n        onSelect={setActive}\n        {...args}\n      />\n    </Container>\n  );\n}\n\nexport const PillGroups = {\n  render: function Render(args) {\n    return (\n      <>\n        <PillGroupContainer {...args} />\n        <ThemeProvider theme={theme}>\n          <PillGroupContainer {...args} />\n        </ThemeProvider>\n      </>\n    );\n  },\n\n  parameters: {\n    controls: { include: [], hideNoControlsWarning: true },\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/pill/test/pill.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Pill from '../pill';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('Pill', () => {\n  const pillText = 'Some pill text';\n  const onClickMock = jest.fn();\n\n  it('should render the default button as a pill', () => {\n    renderWithProviders(\n      <Pill onClick={onClickMock} isActive={false}>\n        {pillText}\n      </Pill>\n    );\n\n    expect(screen.getByRole('button')).toHaveTextContent(pillText);\n  });\n\n  it('should not trigger a click on <Pill /> when disabled', () => {\n    renderWithProviders(\n      <Pill disabled onClick={onClickMock} isActive={false}>\n        {pillText}\n      </Pill>\n    );\n\n    const pil = screen.getByText(pillText);\n\n    fireEvent.click(pil);\n\n    expect(onClickMock).toHaveBeenCalledTimes(0);\n  });\n\n  it('should simulate a click on <Pill />', () => {\n    renderWithProviders(\n      <Pill onClick={onClickMock} isActive={false}>\n        {pillText}\n      </Pill>\n    );\n\n    const pil = screen.getByText(pillText);\n\n    fireEvent.click(pil);\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/popup/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { type CSSProperties } from 'styled-components';\n\nexport enum Placement {\n  Top = 'top',\n  TopStart = 'top-start',\n  TopEnd = 'top-end',\n  Bottom = 'bottom',\n  BottomStart = 'bottom-start',\n  BottomEnd = 'bottom-end',\n  Right = 'right',\n  RightStart = 'right-start',\n  RightEnd = 'right-end',\n  Left = 'left',\n  LeftStart = 'left-start',\n  LeftEnd = 'left-end',\n}\n\nexport const RTL_PLACEMENT = {\n  [Placement.Top]: Placement.Top,\n  [Placement.TopStart]: Placement.TopStart,\n  [Placement.TopEnd]: Placement.TopEnd,\n  [Placement.Bottom]: Placement.Bottom,\n  [Placement.BottomEnd]: Placement.BottomEnd,\n  [Placement.BottomStart]: Placement.BottomStart,\n  [Placement.Right]: Placement.Left,\n  [Placement.RightStart]: Placement.LeftStart,\n  [Placement.RightEnd]: Placement.LeftEnd,\n  [Placement.Left]: Placement.Right,\n  [Placement.LeftStart]: Placement.RightStart,\n  [Placement.LeftEnd]: Placement.RightEnd,\n};\n\nexport const PopupContainer = styled.div<{\n  $offset: { x: number; y: number; width: number };\n  fillWidth?: boolean;\n  transforms?: string;\n  zIndex?: number;\n  maxWidth?: number;\n  noOverFlow?: boolean;\n  topOffset?: number;\n}>`\n  /*! @noflip */\n  ${({\n    $offset: { x, y, width },\n    fillWidth,\n    transforms = '',\n    zIndex,\n    maxWidth,\n  }) => {\n    // set the width properties\n    const widthProp: CSSProperties = {};\n\n    // fillWidth should expand the PopupContainer width to the offset.width\n    if (fillWidth) {\n      // if maxWidth is given with fillWidth, set the PopupContainers min-width\n      // to offset.width to ensure the PopupContainer does not get any smaller\n      // than offset.width\n      if (maxWidth) {\n        widthProp.minWidth = `${width}px`;\n      } else {\n        widthProp.width = `${width}px`;\n      }\n    }\n    // if maxWidth is given and the width property hasn't been set\n    // set the PopupContainers max-width\n    if (maxWidth && !widthProp.width) {\n      widthProp.maxWidth = `${maxWidth}px`;\n    }\n\n    return {\n      transform: `translate(${x}px, ${y}px) ${transforms}`,\n      ...widthProp,\n      zIndex,\n    };\n  }}\n  /*! @noflip */\n  left: 0px;\n  top: 0px;\n  position: fixed;\n  ${({ noOverFlow }) => (noOverFlow ? '' : 'overflow-y: auto;')};\n  max-height: ${({ topOffset = 0 }) => `calc(100vh - ${topOffset}px)`};\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/popup/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Popup } from './popup';\nexport { Placement, RTL_PLACEMENT } from './constants';\n"
  },
  {
    "path": "packages/design-system/src/components/popup/popup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useLayoutEffect,\n  useEffect,\n  useCallback,\n  useState,\n  useRef,\n  useResizeEffect,\n  createPortal,\n} from '@googleforcreators/react';\nimport type { PropsWithChildren, RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils';\nimport { usePopup } from '../../contexts';\nimport { getTransforms, getOffset } from './utils';\nimport { Placement, PopupContainer } from './constants';\nimport type { Offset, Spacing } from './types';\nimport { EMPTY_OFFSET } from './utils/getOffset';\n\nconst DEFAULT_TOP_OFFSET = 0;\nconst DEFAULT_POPUP_Z_INDEX = 2;\nconst DEFAULT_LEFT_OFFSET = 0;\n\ninterface PopupProps {\n  anchor: RefObject<Element>;\n  dock?: RefObject<Element>;\n  renderContents?: (props: { propagateDimensionChange: () => void }) => void;\n  placement?: Placement;\n  spacing?: Spacing;\n  isOpen?: boolean;\n  fillWidth?: number | boolean;\n  refCallback?: (ref: RefObject<Element>) => void;\n  zIndex?: number;\n  ignoreMaxOffsetY?: boolean;\n  offsetOverride?: boolean;\n  maxWidth?: number;\n}\n\nfunction Popup({\n  anchor,\n  dock,\n  children,\n  renderContents,\n  placement = Placement.Bottom,\n  spacing,\n  isOpen,\n  fillWidth = false,\n  refCallback = noop,\n  zIndex = DEFAULT_POPUP_Z_INDEX,\n  ignoreMaxOffsetY,\n  offsetOverride = false,\n  maxWidth,\n}: PropsWithChildren<PopupProps>) {\n  const {\n    topOffset = DEFAULT_TOP_OFFSET,\n    leftOffset = DEFAULT_LEFT_OFFSET,\n    isRTL = false,\n  } = usePopup();\n\n  const [popupState, setPopupState] = useState<{\n    offset: Offset;\n    height: number | null;\n  } | null>(null);\n  const isMountedRef = useRef(false);\n  const popup = useRef<HTMLDivElement | null>(null);\n\n  const positionPopup = useCallback(\n    (evt?: unknown) => {\n      if (!isMountedRef.current || !anchor?.current) {\n        return;\n      }\n      // If scrolling within the popup, ignore.\n      if (\n        evt instanceof Event &&\n        evt.target instanceof Element &&\n        popup.current?.contains(evt.target)\n      ) {\n        return;\n      }\n      const offset = anchor.current\n        ? getOffset({\n            placement,\n            spacing,\n            anchor,\n            dock,\n            popup,\n            isRTL,\n            topOffset,\n            ignoreMaxOffsetY,\n            offsetOverride,\n          })\n        : EMPTY_OFFSET;\n      const popupRect = popup.current?.getBoundingClientRect();\n\n      const updatedXOffset = (): Offset | null => {\n        if (!popupRect) {\n          return null;\n        }\n        // When in RTL the popup could render off the left side of the screen. If so, let's update the\n        // offset to keep it inbounds.)\n        if (popupRect.x <= leftOffset) {\n          switch (placement) {\n            case Placement.BottomEnd:\n            case Placement.TopEnd:\n              return {\n                ...offset,\n                x: isRTL ? offset.x : popupRect.width + leftOffset,\n              };\n            case Placement.LeftEnd:\n            case Placement.Left:\n            case Placement.LeftStart:\n              // Left placement shouldn't be used if it renders off the left of the screen in LTR\n              return {\n                ...offset,\n                x: isRTL\n                  ? offset.x\n                  : popupRect.width + -popupRect.x - leftOffset,\n              };\n            case Placement.BottomStart:\n            case Placement.TopStart:\n            case Placement.RightEnd:\n            case Placement.RightStart:\n            case Placement.Right:\n              // These should only matter in the case of isRTL so we'll need the entire width of the popup as the offset\n              return { ...offset, x: popupRect.width };\n            default:\n              return {\n                ...offset,\n                x: popupRect.width / 2 + (isRTL ? 0 : leftOffset),\n              };\n          }\n        }\n\n        if (isRTL && popupRect.right >= offset.bodyRight - leftOffset) {\n          // maxOffset should keep us inbounds, except in the case of RTL due to the admin-sidebar nav we could use another\n          // switch case here to make offset more precise, however the math below will always return the popup fully in screen.\n          return {\n            ...offset,\n            x: offset.bodyRight - popupRect.width - leftOffset,\n          };\n        }\n\n        return null;\n      };\n      setPopupState({\n        offset: updatedXOffset() || offset,\n        height: popupRect?.height || null,\n      });\n    },\n    [\n      anchor,\n      placement,\n      spacing,\n      dock,\n      isRTL,\n      topOffset,\n      leftOffset,\n      ignoreMaxOffsetY,\n      offsetOverride,\n    ]\n  );\n\n  useEffect(() => {\n    isMountedRef.current = true;\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  useEffect(() => {\n    // If the popup height changes meanwhile, let's update the popup, too.\n    if (\n      popupState?.height &&\n      popupState.height !== popup.current?.getBoundingClientRect()?.height\n    ) {\n      positionPopup();\n    }\n  }, [popupState?.height, positionPopup]);\n\n  useLayoutEffect(() => {\n    if (!isOpen) {\n      return undefined;\n    }\n    isMountedRef.current = true;\n    positionPopup();\n    // Adjust the position when scrolling.\n    document.addEventListener('scroll', positionPopup, true);\n    return () => {\n      document.removeEventListener('scroll', positionPopup, true);\n      isMountedRef.current = false;\n    };\n  }, [isOpen, positionPopup]);\n\n  useLayoutEffect(() => {\n    if (!isMountedRef.current) {\n      return;\n    }\n\n    refCallback(popup);\n  }, [popupState, refCallback]);\n\n  useResizeEffect({ current: document.body }, positionPopup, [positionPopup]);\n  if (!popupState || !isOpen) {\n    return null;\n  }\n\n  const portal = createPortal(\n    <PopupContainer\n      ref={popup}\n      fillWidth={Boolean(fillWidth)}\n      maxWidth={maxWidth}\n      $offset={popupState.offset}\n      topOffset={topOffset}\n      zIndex={zIndex}\n      transforms={getTransforms(placement, isRTL)}\n    >\n      {renderContents\n        ? renderContents({ propagateDimensionChange: positionPopup })\n        : children}\n    </PopupContainer>,\n    document.body\n  );\n  return portal;\n}\n\nexport default Popup;\n"
  },
  {
    "path": "packages/design-system/src/components/popup/test/popup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Popup from '../popup';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\n// TODO tests with karma to easily get positions and interact\n\ndescribe('Popup', () => {\n  it('should render popup', () => {\n    const anchor = {\n      current: document.createElement('div'),\n    };\n    document.body.append(anchor.current);\n    renderWithProviders(\n      <Popup anchor={anchor} isOpen>\n        {'Hello World!'}\n      </Popup>\n    );\n\n    const popup = screen.getByText('Hello World!');\n    expect(popup).toBeInTheDocument();\n  });\n\n  it('should not render popup when isOpen set to false', () => {\n    const anchor = {\n      current: document.createElement('div'),\n    };\n    document.body.append(anchor.current);\n    renderWithProviders(\n      <Popup anchor={anchor} isOpen={false}>\n        {'Hello World!'}\n      </Popup>\n    );\n\n    const popup = screen.queryByText('Hello World!');\n    expect(popup).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/popup/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface Spacing {\n  x: number;\n  y: number;\n}\n\nexport interface Rectangle {\n  left: number;\n  right: number;\n  top: number;\n  bottom: number;\n}\n\nexport interface Offset extends Spacing {\n  width: number;\n  height: number;\n  bodyRight: number;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/popup/utils/getOffset.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { Placement } from '../constants';\nimport type { Offset, Spacing } from '../types';\nimport { getXTransforms, getYTransforms } from './getTransforms';\n\nexport function getXOffset(\n  placement: Placement,\n  spacing = 0,\n  anchorRect: DOMRect,\n  dockRect: DOMRect | undefined,\n  isRTL: boolean\n) {\n  // doctRect.left can have a valid value of zero, if dockRect exists, it takes precedence.\n  const leftAligned = (dockRect ? dockRect.left : anchorRect.left) - spacing;\n  const rightAligned = (dockRect ? dockRect.right : anchorRect.right) + spacing;\n  const centerAligned = dockRect\n    ? dockRect.left + dockRect.width / 2\n    : anchorRect.left + anchorRect.width / 2;\n\n  switch (placement) {\n    case Placement.BottomStart:\n    case Placement.TopStart:\n    case Placement.Left:\n    case Placement.LeftEnd:\n    case Placement.LeftStart:\n      return isRTL ? rightAligned : leftAligned;\n    case Placement.BottomEnd:\n    case Placement.TopEnd:\n    case Placement.Right:\n    case Placement.RightEnd:\n    case Placement.RightStart:\n      return isRTL ? leftAligned : rightAligned;\n    case Placement.Bottom:\n    case Placement.Top:\n      return centerAligned;\n    default:\n      return 0;\n  }\n}\n\nexport function getYOffset(\n  placement: Placement,\n  spacing = 0,\n  anchorRect: DOMRect\n) {\n  switch (placement) {\n    case Placement.Bottom:\n    case Placement.BottomStart:\n    case Placement.BottomEnd:\n    case Placement.LeftEnd:\n    case Placement.RightEnd:\n      return anchorRect.top + anchorRect.height + spacing;\n    case Placement.Top:\n    case Placement.TopStart:\n    case Placement.TopEnd:\n    case Placement.LeftStart:\n    case Placement.RightStart:\n      return anchorRect.top - spacing;\n    case Placement.Right:\n    case Placement.Left:\n      return anchorRect.top + anchorRect.height / 2;\n    default:\n      return 0;\n  }\n}\n\nexport const EMPTY_OFFSET = {\n  x: 0,\n  y: 0,\n  width: 0,\n  height: 0,\n  bodyRight: 0,\n};\n\ninterface GetOffsetProps {\n  placement: Placement;\n  spacing?: Spacing;\n  anchor: RefObject<Element>;\n  dock?: RefObject<Element>;\n  popup: RefObject<Element>;\n  isRTL: boolean;\n  ignoreMaxOffsetY?: boolean;\n  offsetOverride?: boolean;\n  topOffset?: number;\n}\n\nexport function getOffset({\n  placement,\n  spacing,\n  anchor,\n  dock,\n  popup,\n  isRTL,\n  ignoreMaxOffsetY,\n  offsetOverride,\n  topOffset = 0,\n}: GetOffsetProps): Offset {\n  if (!anchor.current) {\n    return EMPTY_OFFSET;\n  }\n  const anchorRect = anchor.current.getBoundingClientRect();\n  const bodyRect = document.body.getBoundingClientRect();\n  const popupRect = popup.current?.getBoundingClientRect();\n  const dockRect = dock?.current?.getBoundingClientRect();\n\n  // Adjust dimensions based on the popup content's inner dimensions\n  if (popupRect) {\n    popupRect.height = Math.max(\n      popupRect.height,\n      popup.current?.scrollHeight || 0\n    );\n    popupRect.width = Math.max(\n      popupRect.width,\n      popup.current?.scrollWidth || 0\n    );\n  }\n\n  const { height = 0, width = 0 } = popupRect || {};\n  const { x: spacingH = 0, y: spacingV = 0 } = spacing || {};\n\n  // Horizontal\n  const offsetX = getXOffset(placement, spacingH, anchorRect, dockRect, isRTL);\n\n  const maxOffsetX = !isRTL\n    ? bodyRect.width - width - getXTransforms(placement, isRTL) * width\n    : bodyRect.width - getXTransforms(placement, isRTL) * width;\n\n  // Vertical\n  const offsetY = getYOffset(placement, spacingV, anchorRect);\n  const maxOffsetY =\n    bodyRect.height + bodyRect.y - height - getYTransforms(placement) * height;\n\n  const offset = {\n    width: anchorRect.width,\n    height: anchorRect.height,\n    bodyRight: bodyRect?.right,\n  };\n\n  // Clamp values\n  return offsetOverride\n    ? {\n        x: offsetX,\n        y: offsetY,\n        ...offset,\n      }\n    : {\n        x: Math.max(0, Math.min(offsetX, maxOffsetX)),\n        y: ignoreMaxOffsetY\n          ? offsetY\n          : Math.max(topOffset, Math.min(offsetY, maxOffsetY)),\n        ...offset,\n      };\n}\n"
  },
  {
    "path": "packages/design-system/src/components/popup/utils/getTransforms.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Placement } from '../constants';\n\nexport function getXTransforms(placement: Placement, isRTL: boolean) {\n  // left & right\n  if (placement.startsWith('left')) {\n    return isRTL ? 0 : -1;\n  } else if (placement.startsWith('right')) {\n    return isRTL ? -1 : 0;\n  }\n  // top & bottom\n  if (placement.endsWith('-start')) {\n    return isRTL ? -1 : 0;\n  } else if (placement.endsWith('-end')) {\n    return isRTL ? 0 : -1;\n  }\n  return -0.5;\n}\n\nexport function getYTransforms(placement: Placement) {\n  if (\n    placement.startsWith('top') ||\n    placement === Placement.RightEnd ||\n    placement === Placement.LeftEnd\n  ) {\n    return -1;\n  }\n  if (placement === Placement.Right || placement === Placement.Left) {\n    return -0.5;\n  }\n  return 0;\n}\n\n// note that we cannot use percentage values for transforms, which\n// do not work correctly for rotated elements\nexport function getTransforms(placement: Placement, isRTL: boolean) {\n  const xTransforms = getXTransforms(placement, isRTL);\n  const yTransforms = getYTransforms(placement);\n  if (!xTransforms && !yTransforms) {\n    return '';\n  }\n  const translateX = (xTransforms || 0) * 100;\n  const translateY = (yTransforms || 0) * 100;\n  return `translate(${translateX}%, ${translateY}%)`;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/popup/utils/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { getXTransforms, getYTransforms, getTransforms } from './getTransforms';\nexport { getXOffset, getYOffset, getOffset } from './getOffset';\n"
  },
  {
    "path": "packages/design-system/src/components/radio/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Radio } from './radio';\n"
  },
  {
    "path": "packages/design-system/src/components/radio/radio.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ForwardedRef, ComponentPropsWithoutRef } from 'react';\nimport { forwardRef, useMemo } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../theme';\nimport { Text } from '../typography';\n\nconst BORDER_WIDTH = 1;\nconst TEXT_GAP_HEIGHT = 8;\nconst RING_DIAMETER = 24;\nconst CONTAINER_HEIGHT = 44;\nconst RADIO_DIAMETER = 16;\n\nconst Container = styled.div`\n  display: flex;\n  align-items: center;\n  min-height: ${CONTAINER_HEIGHT}px;\n  padding: 8px 0;\n`;\n\nconst RadioInputContainer = styled.div`\n  position: relative;\n  height: ${RING_DIAMETER}px;\n  width: ${RING_DIAMETER}px;\n`;\n\nconst LabelContainer = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin: 0 12px;\n  gap: ${TEXT_GAP_HEIGHT}px;\n`;\n\nconst RadioBorder = styled.span(\n  ({ theme }) => css`\n    display: inline-block;\n    height: ${RING_DIAMETER}px;\n    width: ${RING_DIAMETER}px;\n    border: ${BORDER_WIDTH}px solid ${theme.colors.border.defaultNormal};\n    border-radius: ${theme.borders.radius.round};\n    pointer-events: none;\n    transition: all 0.15s;\n  `\n);\n\nconst InnerButton = styled.span(\n  ({ theme }) => css`\n    pointer-events: none;\n    display: none;\n\n    :after {\n      content: '';\n      position: absolute;\n      height: ${RADIO_DIAMETER}px;\n      width: ${RADIO_DIAMETER}px;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      background-color: ${theme.colors.fg.primary};\n      border-radius: ${theme.borders.radius.round};\n    }\n  `\n);\n\nconst HiddenInput = styled.input.attrs({ type: 'radio' })`\n  position: absolute;\n  height: ${RING_DIAMETER}px;\n  width: ${RING_DIAMETER}px;\n  margin: 0;\n  opacity: 0;\n  cursor: pointer;\n\n  :hover ~ ${RadioBorder} {\n    border-color: ${({ theme }) => theme.colors.border.defaultHover};\n  }\n\n  :focus {\n    outline: none;\n  }\n\n  :focus ~ ${RadioBorder}, &:focus-visible ~ ${RadioBorder} {\n    ${({ theme }) => themeHelpers.focusCSS(theme.colors.border.focus)};\n    border-color: ${({ theme }) => theme.colors.border.defaultHover};\n  }\n\n  :active ~ ${RadioBorder} {\n    box-shadow: 0 0 0 8px ${({ theme }) => theme.colors.shadow.active};\n  }\n\n  :checked ~ ${InnerButton} {\n    display: block;\n  }\n\n  :disabled {\n    cursor: auto;\n\n    ~ ${RadioBorder} {\n      border-color: ${({ theme }) => theme.colors.border.disable};\n    }\n\n    ~ ${InnerButton}::after {\n      background-color: ${({ theme }) => theme.colors.fg.disable};\n    }\n  }\n`;\n\nconst Hint = styled(Text.Span)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\ninterface RadioProps extends Omit<ComponentPropsWithoutRef<'input'>, 'type'> {\n  hint?: string;\n  label?: string;\n}\n\n/**\n * A controlled radio button. Can be used with other radio buttons.\n *\n * To configure a group of radio buttons, the following must be done:\n * 1. Give all the radio buttons of a group the same `name`\n * 2. Pass a unique `value` to each radio button. This tracks the value of the specific radio button.\n * 3. Pass `checked={true}` to the radio button that should be selected\n *\n * Keyboard navigation:\n * - [Tab] can be used to navigate between radio groups\n * - [ArrowUp] and [ArrowDown] can be used to navigate between radio buttons\n *\n * @param {Object} props The props\n * @param {string} props.className className that is applied to the outer container\n * @param {string} props.checked whether the radio button is selected\n * @param {string} props.hint hint to display\n * @param {string} props.id unique id used to associate the label to the input\n * @param {string} props.label label to display\n * @param {string} props.name name of the radio group\n * @param {Function} props.onChange change event handler\n * @param {string} props.value the value of the radio button\n * @return {Object} The radio button\n */\nconst Radio = forwardRef(function Radio(\n  { className, hint, id, label, ...props }: RadioProps,\n  ref: ForwardedRef<HTMLInputElement>\n) {\n  const inputId = useMemo(() => id || uuidv4(), [id]);\n\n  return (\n    <Container className={className}>\n      <RadioInputContainer>\n        <HiddenInput id={inputId} ref={ref} {...props} />\n        <RadioBorder />\n        <InnerButton />\n      </RadioInputContainer>\n\n      <LabelContainer>\n        <Text.Label htmlFor={inputId} size={TextSize.Small}>\n          {label}\n        </Text.Label>\n        {hint && <Hint>{hint}</Hint>}\n      </LabelContainer>\n    </Container>\n  );\n});\n\nexport default Radio;\n"
  },
  {
    "path": "packages/design-system/src/components/radio/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useState } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Radio from '../radio';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Headline } from '../../typography';\n\nexport default {\n  title: 'DesignSystem/Components/Radio',\n  component: Radio,\n  args: {\n    label1: 'One',\n    label2: 'Two',\n    label3: 'Disabled',\n    hint1: 'Hint 1',\n    hint2: 'Hint 2',\n    hint3: 'Hint 3',\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(25%, 1fr));\n\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const [inputState, setInputState] = useState({\n      radioOne: '1',\n      radioTwo: '1',\n      radioThree: '2',\n      radioFour: '2',\n      radioFive: '3',\n      radioSix: '3',\n    });\n\n    const handleChange = (ev) => {\n      const name = ev?.target?.name;\n      const value = ev?.target?.value;\n      setInputState((state) => ({ ...state, [name]: value }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Radio'}</Headline>\n        <Container>\n          <Radio\n            name=\"radioOne\"\n            value=\"1\"\n            onChange={handleChange}\n            checked={inputState.radioOne === '1'}\n            label={args.label1}\n          />\n          <Radio\n            name=\"radioOne\"\n            value=\"2\"\n            onChange={handleChange}\n            checked={inputState.radioOne === '2'}\n            label={args.label2}\n          />\n          <Radio\n            name=\"radioOne\"\n            value=\"3\"\n            onChange={handleChange}\n            checked={inputState.radioOne === '3'}\n            label={args.label3}\n            disabled\n          />\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Radio\n              name=\"radioTwo\"\n              onChange={handleChange}\n              value=\"1\"\n              checked={inputState.radioTwo === '1'}\n              label={args.label1}\n            />\n            <Radio\n              name=\"radioTwo\"\n              onChange={handleChange}\n              value=\"2\"\n              checked={inputState.radioTwo === '2'}\n              label={args.label2}\n            />\n            <Radio\n              name=\"radioTwo\"\n              value=\"3\"\n              onChange={handleChange}\n              checked={inputState.radioTwo === '3'}\n              label={args.label3}\n              disabled\n            />\n          </Container>\n        </DarkThemeProvider>\n        <br />\n        <br />\n        <Headline as=\"h1\">{'Radio with Hint'}</Headline>\n        <Container>\n          <Radio\n            name=\"radioThree\"\n            value=\"1\"\n            onChange={handleChange}\n            checked={inputState.radioThree === '1'}\n            label={args.label1}\n            hint={args.hint1}\n          />\n          <Radio\n            name=\"radioThree\"\n            value=\"2\"\n            onChange={handleChange}\n            checked={inputState.radioThree === '2'}\n            label={args.label2}\n            hint={args.hint2}\n          />\n          <Radio\n            name=\"radioThree\"\n            value=\"3\"\n            onChange={handleChange}\n            checked={inputState.radioThree === '3'}\n            label={args.label3}\n            hint={args.hint3}\n            disabled\n          />\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Radio\n              name=\"radioFour\"\n              onChange={handleChange}\n              value=\"1\"\n              checked={inputState.radioFour === '1'}\n              label={args.label1}\n              hint={args.hint1}\n            />\n            <Radio\n              name=\"radioFour\"\n              onChange={handleChange}\n              value=\"2\"\n              checked={inputState.radioFour === '2'}\n              label={args.label2}\n              hint={args.hint2}\n            />\n            <Radio\n              name=\"radioFour\"\n              value=\"3\"\n              onChange={handleChange}\n              checked={inputState.radioFour === '3'}\n              label={args.label3}\n              hint={args.hint3}\n              disabled\n            />\n          </Container>\n        </DarkThemeProvider>\n        <br />\n        <br />\n        <Headline as=\"h1\">\n          {'Disabled Radio Button Initially Selected'}\n        </Headline>\n        <Container>\n          <Radio\n            name=\"radioFive\"\n            value=\"1\"\n            onChange={handleChange}\n            checked={inputState.radioFive === '1'}\n            label={args.label1}\n            hint={args.hint1}\n          />\n          <Radio\n            name=\"radioFive\"\n            value=\"2\"\n            onChange={handleChange}\n            checked={inputState.radioFive === '2'}\n            label={args.label2}\n            hint={args.hint2}\n          />\n          <Radio\n            name=\"radioFive\"\n            value=\"3\"\n            onChange={handleChange}\n            checked={inputState.radioFive === '3'}\n            label={args.label3}\n            hint={args.hint3}\n            disabled\n          />\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Radio\n              name=\"radioSix\"\n              onChange={handleChange}\n              value=\"1\"\n              checked={inputState.radioSix === '1'}\n              label={args.label1}\n              hint={args.hint1}\n            />\n            <Radio\n              name=\"radioSix\"\n              onChange={handleChange}\n              value=\"2\"\n              checked={inputState.radioSix === '2'}\n              label={args.label2}\n              hint={args.hint2}\n            />\n            <Radio\n              name=\"radioSix\"\n              value=\"3\"\n              onChange={handleChange}\n              checked={inputState.radioSix === '3'}\n              label={args.label3}\n              hint={args.hint3}\n              disabled\n            />\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/radio/test/radio.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../utils';\nimport Radio from '../radio';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('Radio', () => {\n  it('should render a radio button', () => {\n    renderWithProviders(\n      <Radio name=\"foo\" label=\"this is my label\" onChange={noop} value=\"1\" />\n    );\n\n    expect(screen.getByRole('radio')).toBeInTheDocument();\n    expect(screen.getByText('this is my label')).toBeInTheDocument();\n  });\n\n  it('should render a hint', () => {\n    renderWithProviders(\n      <Radio\n        name=\"foo\"\n        label=\"this is my label\"\n        hint=\"this is my hint\"\n        onChange={noop}\n        value=\"1\"\n      />\n    );\n\n    expect(screen.getByText('this is my hint')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/search/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Text } from '../typography/text';\n\nexport const DropDownContainer = styled.div`\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n`;\n\nexport const Label = styled(Text.Label)`\n  margin-bottom: 8px;\n  color: ${({ theme, disabled }) =>\n    theme.colors.fg[disabled ? 'disable' : 'primary']};\n`;\n\nexport const Hint = styled(Text.Paragraph)<{ hasError?: boolean }>`\n  margin-top: 12px;\n  padding-left: 2px;\n  color: ${({ theme, hasError }) =>\n    theme.colors.fg[hasError ? 'negative' : 'tertiary']};\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/search/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const DEFAULT_POPUP_FILL_WIDTH = 276;\nexport const DEFAULT_PLACEHOLDER = __('Search', 'web-stories');\nexport const DEFAULT_ARIA_CLEAR_LABEL = __('Clear Search', 'web-stories');\nexport const DEFAULT_ARIA_INPUT_LABEL = __('Search', 'web-stories');\n\nexport const Z_INDEX = {\n  CLEAR_BUTTON: 5,\n};\n"
  },
  {
    "path": "packages/design-system/src/components/search/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Search } from './search';\nexport { default as SearchInput } from './input';\n"
  },
  {
    "path": "packages/design-system/src/components/search/input/components.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport {\n  ChevronDownSmall,\n  CrossSmall as Clear,\n  Magnifier as Search,\n} from '../../../icons';\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { Z_INDEX } from '../constants';\n\nexport const InputContainer = styled.div(\n  ({ theme }) => css`\n    display: flex;\n    position: relative;\n    height: 36px;\n    width: 100%;\n    max-width: 400px;\n    background-color: transparent;\n    color: ${theme.colors.fg.primary};\n  `\n);\n\nexport const Input = styled.input<{ hasError?: boolean }>(\n  ({ theme, hasError }) => css`\n    position: absolute;\n    height: 100%;\n    width: 100%;\n    background-color: transparent;\n    outline: none;\n    cursor: pointer;\n    ${themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.paragraph[TextSize.Small],\n      theme,\n    })};\n    color: ${theme.colors.fg.primary};\n    border: 1px solid ${theme.colors.border.defaultNormal};\n    padding: 8px 20px 8px 40px;\n    &::placeholder {\n      color: ${theme.colors.fg.tertiary};\n    }\n    &[aria-expanded='true'] {\n      border-color: ${theme.colors.border.defaultActive};\n    }\n\n    border-radius: ${theme.borders.radius.small};\n\n    &::-ms-clear {\n      display: none;\n    }\n\n    &::-webkit-search-decoration,\n    &::-webkit-search-cancel-button,\n    &::-webkit-search-results-button,\n    &::-webkit-search-results-decoration {\n      appearance: none;\n    }\n\n    &:hover {\n      border-color: ${theme.colors.border.defaultHover};\n    }\n\n    ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n\n    ${hasError &&\n    css`\n      border-color: ${theme.colors.interactiveBg.negativeHover};\n\n      &:active,\n      &:hover {\n        border-color: ${theme.colors.interactiveBg.negativeHover};\n      }\n    `}\n\n    &:disabled {\n      pointer-events: none;\n      border-color: ${theme.colors.border.disable};\n      color: ${theme.colors.fg.disable};\n\n      &:hover {\n        border-color: ${theme.colors.border.disable};\n      }\n    }\n  `\n);\n\nconst BaseDecorationContainer = css`\n  display: flex;\n  align-items: center;\n  width: 32px;\n  background-color: transparent;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  border: 0;\n  margin: auto 1px auto auto;\n  padding: 0;\n  align-self: flex-end;\n  cursor: pointer;\n`;\n\nexport const ClearButton = styled.button<{ isVisible?: boolean }>`\n  ${BaseDecorationContainer};\n  display: ${({ isVisible }) => (isVisible ? 'flex' : 'none')};\n  outline: none;\n  ${({ theme }) => themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n  height: 30px;\n  z-index: ${Z_INDEX.CLEAR_BUTTON};\n`;\n\nexport const ClearIcon = styled(Clear)`\n  width: 32px;\n  height: auto;\n  margin: auto;\n`;\n\nexport const ChevronDecoration = styled.div<{\n  isVisible?: boolean;\n  disabled?: boolean;\n}>`\n  ${BaseDecorationContainer};\n  display: ${({ isVisible }) => (isVisible ? 'flex' : 'none')};\n  visibility: ${({ isVisible }) => (isVisible ? 'visible' : 'collapsed')};\n  height: 100%;\n  ${({ disabled, theme }) =>\n    disabled &&\n    css`\n      pointer-events: none;\n      color: ${theme.colors.fg.disable};\n    `}\n`;\n\nexport const ChevronIcon = styled(ChevronDownSmall)<{ $isMenuOpen?: boolean }>`\n  width: 32px;\n  height: auto;\n  margin: auto;\n\n  ${({ $isMenuOpen }) =>\n    $isMenuOpen &&\n    css`\n      transform: rotate(180deg);\n    `}\n`;\n\nexport const SearchDecoration = styled.div<{\n  disabled?: boolean;\n  activeSearch?: boolean;\n}>(\n  ({ theme, activeSearch, disabled }) => css`\n    ${BaseDecorationContainer};\n    position: absolute;\n    height: 100%;\n    margin: 0;\n    left: 8px;\n    color: ${activeSearch ? theme.colors.fg.tertiary : theme.colors.fg.primary};\n    pointer-events: none;\n\n    ${disabled &&\n    css`\n      color: ${theme.colors.fg.disable};\n    `}\n  `\n);\n\nexport const SearchIcon = styled(Search)`\n  position: relative;\n  width: 32px;\n  height: auto;\n  margin: auto;\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/search/input/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './input';\n"
  },
  {
    "path": "packages/design-system/src/components/search/input/input.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useMemo,\n  useState,\n  forwardRef,\n} from '@googleforcreators/react';\nimport type { ForwardedRef, ComponentPropsWithoutRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  Input,\n  InputContainer,\n  ClearIcon,\n  ChevronIcon,\n  ChevronDecoration,\n  SearchDecoration,\n  SearchIcon,\n  ClearButton,\n} from './components';\n\ninterface SearchInputProps extends ComponentPropsWithoutRef<typeof Input> {\n  ariaClearLabel?: string;\n  clearId?: string;\n  handleClearInput?: () => void;\n  handleTabClear?: () => void;\n  inputValue: string;\n  isOpen: boolean;\n  listId?: string;\n  className?: string;\n  disabled?: boolean;\n}\n\nconst SearchInput = forwardRef(\n  (\n    {\n      ariaClearLabel,\n      clearId,\n      disabled,\n      handleClearInput = () => undefined,\n      handleTabClear,\n      inputValue,\n      isOpen,\n      listId,\n      className = '',\n      ...rest\n    }: SearchInputProps,\n    ref: ForwardedRef<HTMLInputElement>\n  ) => {\n    const [inputChanged, setInputChanged] = useState(false);\n    const [isEmptyValue, setIsEmptyValue] = useState(false);\n    // Avoid conditional rendering in this input because rerendering will remove the focus styling\n\n    const activeInput = useMemo(\n      () => inputValue.length > 0 && isOpen,\n      [isOpen, inputValue]\n    );\n    const alignInputCenter = useMemo(\n      () => inputValue.length === 0 && !isOpen,\n      [isOpen, inputValue]\n    );\n\n    const onClearButtonKeyDown = useCallback(\n      ({ key }) => {\n        if (key === 'Tab') {\n          handleTabClear?.();\n        }\n      },\n      [handleTabClear]\n    );\n\n    const handleOnInput = useCallback(\n      (value: string) => {\n        setIsEmptyValue(value === '');\n        setInputChanged(isOpen);\n      },\n      [isOpen]\n    );\n\n    return (\n      <InputContainer className={className}>\n        <Input\n          aria-disabled={disabled}\n          autoComplete=\"off\"\n          disabled={disabled}\n          onInput={(event) => handleOnInput(event.currentTarget.value)}\n          ref={ref}\n          type=\"search\"\n          value={inputValue}\n          {...(listId && {\n            role: 'combobox',\n            ['aria-expanded']: isOpen,\n            ['aria-controls']: listId,\n            ['aria-owns']: listId,\n            ['aria-autocomplete']: 'list',\n          })}\n          {...rest}\n        />\n        <SearchDecoration\n          activeSearch={alignInputCenter}\n          aria-hidden\n          disabled={disabled}\n        >\n          <SearchIcon id={clearId} />\n        </SearchDecoration>\n\n        <ClearButton\n          type=\"button\"\n          isVisible={activeInput && inputChanged}\n          tabIndex={0}\n          aria-label={activeInput && inputChanged ? ariaClearLabel : ''}\n          onClick={handleClearInput}\n          onKeyDown={onClearButtonKeyDown}\n        >\n          <ClearIcon id={clearId} data-testid=\"clear-search-icon\" />\n        </ClearButton>\n\n        <ChevronDecoration\n          disabled={disabled}\n          aria-hidden={(activeInput && inputChanged) || isEmptyValue}\n          isVisible={\n            (!activeInput || !inputChanged) &&\n            !isEmptyValue &&\n            inputValue.length > 0\n          }\n        >\n          <ChevronIcon $isMenuOpen={isOpen} data-testid=\"chevron-search-icon\" />\n        </ChevronDecoration>\n      </InputContainer>\n    );\n  }\n);\n\nexport default SearchInput;\n"
  },
  {
    "path": "packages/design-system/src/components/search/search.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useMemo,\n  useRef,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport type { ChangeEvent, KeyboardEvent, UIEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from '../../theme';\nimport { Menu } from '../menu';\nimport type { DropdownItem, DropdownValue } from '../menu';\nimport { Popup, Placement } from '../popup';\nimport { DropDownContainer, Hint, Label } from './components';\nimport {\n  DEFAULT_POPUP_FILL_WIDTH,\n  DEFAULT_PLACEHOLDER,\n  DEFAULT_ARIA_CLEAR_LABEL,\n  DEFAULT_ARIA_INPUT_LABEL,\n} from './constants';\nimport SearchInput from './input';\nimport useSearch from './useSearch';\nimport type { SearchProps } from './types';\n\nconst SearchInputWrapper = styled.div``;\n\nfunction Search({\n  ariaInputLabel = DEFAULT_ARIA_INPUT_LABEL,\n  ariaClearLabel = DEFAULT_ARIA_CLEAR_LABEL,\n  disabled,\n  handleSearchValueChange,\n  hasError,\n  hint,\n  label,\n  onMenuItemClick,\n  onClear,\n  options = [],\n  placeholder = DEFAULT_PLACEHOLDER,\n  placement = Placement.Bottom,\n  popupFillWidth = DEFAULT_POPUP_FILL_WIDTH,\n  popupZIndex,\n  selectedValue,\n  searchValue,\n  ...rest\n}: SearchProps) {\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const inputId = useMemo(() => `select-button-${uuidv4()}`, []);\n  const clearId = useMemo(() => `clear-button-${uuidv4()}`, []);\n\n  const inputRef = useRef<HTMLInputElement | null>(null);\n  const inputWrapperRef = useRef<HTMLDivElement | null>(null);\n\n  const {\n    activeOption,\n    getActiveOption,\n    inputState,\n    setInputState,\n    isMenuFocused,\n    setIsMenuFocused,\n    isOpen,\n    setIsOpen,\n    groups,\n  } = useSearch({\n    options,\n    selectedValue,\n    searchValue,\n    handleSearchValueChange,\n  });\n\n  const isMenuHidden = useMemo(\n    () => Boolean(disabled || !inputState?.length),\n    [disabled, inputState]\n  );\n\n  /**\n   * Callbacks that begin search interaction\n   */\n  const handleInputFocus = useCallback(() => {\n    setIsOpen(true);\n    setIsMenuFocused(false);\n  }, [setIsOpen, setIsMenuFocused]);\n\n  const handleInputClick = useCallback(\n    (event: UIEvent) => {\n      event.preventDefault();\n      setIsOpen(true);\n    },\n    [setIsOpen]\n  );\n\n  /**\n   * Callbacks passed to menu\n   */\n\n  const handleDismissMenu = useCallback(\n    (event?: Event) => {\n      // don't dismiss menu if clicking on clear button while menu is open\n      if (\n        clearId &&\n        event?.currentTarget instanceof HTMLElement &&\n        event.currentTarget.id === clearId\n      ) {\n        return;\n      }\n      setIsOpen(false);\n    },\n    [clearId, setIsOpen]\n  );\n\n  const handleMenuItemClick = useCallback(\n    (event: Event, menuItem: DropdownValue) => {\n      setIsOpen(false);\n      const newOption: DropdownItem = getActiveOption(menuItem) || {\n        label: String(menuItem),\n        value: menuItem,\n      };\n      setInputState(String(newOption.label));\n      onMenuItemClick?.(event, newOption);\n    },\n    [getActiveOption, setInputState, setIsOpen, onMenuItemClick]\n  );\n\n  const handleReturnToInput = useCallback(() => inputRef?.current?.focus(), []);\n\n  /**\n   * Callbacks passed to input\n   */\n  const handleInputChange = useCallback(\n    ({ target }: ChangeEvent<HTMLInputElement>) => {\n      setInputState(target.value);\n      setIsOpen(target.value.length > 0);\n    },\n    [setInputState, setIsOpen]\n  );\n\n  const handleClearInput = useCallback(() => {\n    setInputState('');\n    onClear?.();\n    handleReturnToInput?.();\n  }, [handleReturnToInput, setInputState, onClear]);\n\n  const handleTabClear = useCallback(() => {\n    setIsOpen(false);\n    setIsMenuFocused(false);\n  }, [setIsOpen, setIsMenuFocused]);\n\n  const focusSentToList = useCallback(\n    () => setIsMenuFocused(true),\n    [setIsMenuFocused]\n  );\n\n  const handleEndSearch = useCallback(() => {\n    if (isMenuHidden || inputState?.trim().length === 0) {\n      setIsMenuFocused(false);\n      setIsOpen(false);\n    }\n  }, [inputState, setIsMenuFocused, isMenuHidden, setIsOpen]);\n\n  const handleInputKeyPress = useCallback(\n    (event: KeyboardEvent<HTMLInputElement>) => {\n      const { key } = event;\n      if (key === 'Escape') {\n        if (!isMenuHidden) {\n          setIsMenuFocused(false);\n        }\n      } else if (key === 'Tab') {\n        handleEndSearch();\n      } else if (key === 'ArrowDown') {\n        focusSentToList();\n      } else if (key === 'Enter') {\n        if (inputState && inputState.trim().length > 0) {\n          handleMenuItemClick(event.nativeEvent, String(inputState));\n        }\n      }\n    },\n    [\n      isMenuHidden,\n      setIsMenuFocused,\n      handleEndSearch,\n      focusSentToList,\n      inputState,\n      handleMenuItemClick,\n    ]\n  );\n\n  // By using inputWrapperRef instead of inputRef we ensure that this isn't triggered\n  // when clicking on the search input's \"Clear\" button.\n  // It will still trigger when actually clicking on an option within the Popup.\n  useFocusOut(inputWrapperRef, handleEndSearch, [handleEndSearch]);\n\n  return (\n    <DropDownContainer>\n      {label && (\n        <Label size={TextSize.Small} disabled={disabled} isBold>\n          {label}\n        </Label>\n      )}\n      <SearchInputWrapper ref={inputWrapperRef}>\n        <SearchInput\n          // Passed through to input\n          aria-label={ariaInputLabel}\n          hasError={hasError}\n          id={inputId}\n          onChange={handleInputChange}\n          onClick={handleInputClick}\n          onFocus={handleInputFocus}\n          onKeyDown={handleInputKeyPress}\n          placeholder={placeholder}\n          // Used within SearchInput\n          ariaClearLabel={ariaClearLabel}\n          clearId={clearId}\n          disabled={disabled}\n          handleClearInput={handleClearInput}\n          handleTabClear={handleTabClear}\n          inputValue={inputState || ''}\n          isOpen={isOpen}\n          listId={listId}\n          ref={inputRef}\n          {...rest}\n        />\n      </SearchInputWrapper>\n\n      {!isMenuHidden && (\n        <Popup\n          anchor={inputRef}\n          isOpen={isOpen}\n          placement={placement}\n          fillWidth={popupFillWidth}\n          zIndex={popupZIndex}\n          ignoreMaxOffsetY\n        >\n          <Menu\n            activeValue={activeOption?.value}\n            handleReturnToParent={handleReturnToInput}\n            isMenuFocused={isMenuFocused}\n            listId={listId}\n            menuAriaLabel={sprintf(\n              /* translators: %s: dropdown aria label or general dropdown label if there is no specific aria label. */\n              __('%s Option List Selector', 'web-stories'),\n              ariaInputLabel\n            )}\n            onDismissMenu={handleDismissMenu}\n            handleMenuItemSelect={handleMenuItemClick}\n            groups={groups}\n            parentId={inputId}\n            {...rest}\n          />\n        </Popup>\n      )}\n\n      {hint && (\n        <Hint hasError={hasError} size={TextSize.Small}>\n          {hint}\n        </Hint>\n      )}\n    </DropDownContainer>\n  );\n}\n\nexport default Search;\n"
  },
  {
    "path": "packages/design-system/src/components/search/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Placement } from '../../popup';\nimport Search from '../search';\nimport { basicDropDownOptions } from '../../../storybookUtils/sampleData';\n\nexport default {\n  title: 'DesignSystem/Components/Search',\n  args: {\n    ariaClearLabel: 'clear search',\n    ariaInputLabel: 'search for an image',\n    disabled: false,\n    emptyText: 'No options available',\n    hasError: false,\n    hint: 'default hint text',\n    label: 'Find an image',\n    isRTL: false,\n    placeholder: 'search',\n    placement: Placement.Bottom,\n    popupZIndex: 1,\n  },\n  argTypes: {\n    placement: {\n      options: Object.values(Placement),\n      control: 'select',\n    },\n    onChange: { action: 'handleSearchValueChange' },\n  },\n};\n\nconst Container = styled.div`\n  width: 400px;\n  height: 100vh;\n  padding: 12px 24px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nexport const _default = {\n  render: function Render({ onChange, ...args }) {\n    const [selectedValue, setSelectedValue] = useState(basicDropDownOptions[2]);\n\n    const [inputValue, setInputValue] = useState('');\n\n    const options = useMemo(() => {\n      if (!inputValue || inputValue.length === 0) {\n        return basicDropDownOptions;\n      }\n\n      return basicDropDownOptions.filter(\n        ({ label, value }) =>\n          label\n            .toString()\n            .toLowerCase()\n            .startsWith(inputValue.toLowerCase().trim()) ||\n          value\n            .toString()\n            .toLowerCase()\n            .startsWith(inputValue.toLowerCase().trim())\n      );\n    }, [inputValue]);\n\n    const handleSearchValueChange = useCallback(\n      (value) => {\n        onChange(value);\n        setInputValue(value);\n      },\n      [onChange]\n    );\n\n    const handleOnClear = useCallback(() => {\n      setInputValue('');\n      setSelectedValue(null);\n    }, []);\n\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <Search\n            handleSearchValueChange={handleSearchValueChange}\n            onClear={handleOnClear}\n            options={options}\n            selectedValue={selectedValue}\n            {...args}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n};\n\nexport const LightTheme = {\n  render: function Render({ onChange, ...args }) {\n    const [selectedValue, setSelectedValue] = useState();\n\n    const [inputValue, setInputValue] = useState('');\n\n    const options = useMemo(() => {\n      if (!inputValue || inputValue.length === 0) {\n        return [];\n      }\n\n      return basicDropDownOptions.filter(\n        ({ label, value }) =>\n          label\n            .toString()\n            .toLowerCase()\n            .startsWith(inputValue.toLowerCase().trim()) ||\n          value\n            .toString()\n            .toLowerCase()\n            .startsWith(inputValue.toLowerCase().trim())\n      );\n    }, [inputValue]);\n\n    const handleSearchValueChange = useCallback(\n      (value) => {\n        onChange(value);\n        setInputValue(value);\n      },\n      [onChange]\n    );\n\n    const handleOnClear = useCallback(() => {\n      setInputValue('');\n      setSelectedValue(null);\n    }, []);\n\n    return (\n      <Container>\n        <Search\n          handleSearchValueChange={handleSearchValueChange}\n          onClear={handleOnClear}\n          options={options}\n          selectedValue={selectedValue}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/search/stories/input.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Text } from '../../typography';\nimport SearchInput from '../input';\n\nexport default {\n  title: 'DesignSystem/Components/Search/Input',\n  args: {\n    ariaClearLabel: 'label for clear button',\n    clearId: 'my-search-id',\n    disabled: false,\n    hasError: false,\n    id: 'my-input-id',\n    inputValue: '',\n    isOpen: true,\n    placeholder: 'search',\n  },\n  argTypes: {\n    onChange: { action: 'change event triggered' },\n    onClick: { action: 'click event triggered' },\n    onFocus: { action: 'on focus event triggered' },\n    handleClearInput: { action: 'handleClearInput triggered' },\n    handleTabClear: { action: 'handleTabClear triggered' },\n    onKeyDown: { action: 'on keyDown event triggered' },\n  },\n};\n\nconst Container = styled.div`\n  width: 300px;\n  padding: 12px 24px;\n  margin: 24px 0;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const StorybookInput = (\n      <SearchInput\n        aria-label={'my aria label'}\n        listId={'my-list-id'}\n        name={'my-input-id'}\n        {...args}\n      />\n    );\n\n    return (\n      <>\n        <Container>\n          <Text.Paragraph>{'Light Mode'}</Text.Paragraph>\n          {StorybookInput}\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Text.Paragraph>{'Dark Mode'}</Text.Paragraph>\n            {StorybookInput}\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/search/test/input.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport SearchInput from '../input';\nimport { noop } from '../../../utils';\n\ndescribe('Search <Input />', () => {\n  const onClickMock = jest.fn();\n  const handleClearInputMock = jest.fn();\n\n  beforeEach(jest.clearAllMocks);\n\n  it('should render a <SearchInput /> searchbox by default', () => {\n    renderWithProviders(\n      <SearchInput\n        ariaInputLabel=\"search label\"\n        ariaClearLabel=\"aria label for clearing value\"\n        onClick={onClickMock}\n        handleClearInput={handleClearInputMock}\n        inputValue=\"\"\n        onChange={noop}\n      />\n    );\n\n    const input = screen.getByRole('searchbox');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should render a <SearchInput /> combobox if it has a list id', () => {\n    renderWithProviders(\n      <SearchInput\n        ariaInputLabel=\"search label\"\n        ariaClearLabel=\"aria label for clearing value\"\n        onClick={onClickMock}\n        handleClearInput={handleClearInputMock}\n        inputValue=\"\"\n        listId={1}\n        onChange={noop}\n      />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should not trigger onClickMock on click if input is disabled', () => {\n    renderWithProviders(\n      <SearchInput\n        ariaInputLabel=\"search label\"\n        ariaClearLabel=\"aria label for clearing value\"\n        onClick={onClickMock}\n        handleClearInput={handleClearInputMock}\n        placeholder=\"search placeholder\"\n        inputValue=\"\"\n        disabled\n        onChange={noop}\n      />\n    );\n\n    const input = screen.getByPlaceholderText('search placeholder');\n    fireEvent.click(input);\n\n    expect(onClickMock).toHaveBeenCalledTimes(0);\n  });\n\n  it('should trigger handleClearInputMock on click of clear button if input has content', () => {\n    renderWithProviders(\n      <SearchInput\n        ariaInputLabel=\"search label\"\n        ariaClearLabel=\"aria label for clearing value\"\n        onClick={onClickMock}\n        handleClearInput={handleClearInputMock}\n        inputValue=\"my input value\"\n        placeholder=\"search placeholder\"\n        onChange={noop}\n      />\n    );\n\n    const clearButton = screen.getByTestId('clear-search-icon');\n    expect(clearButton).toBeInTheDocument();\n\n    fireEvent.click(clearButton);\n\n    expect(handleClearInputMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/search/test/search.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, act, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { basicDropDownOptions } from '../../../testUtils/sampleData';\nimport Search from '../search';\n\nconst scrollTo = jest.fn();\n\ndescribe('Search <Search />', () => {\n  beforeAll(() => {\n    // Mock scrollTo\n    Object.defineProperty(window.Element.prototype, 'scrollTo', {\n      writable: true,\n      value: scrollTo,\n    });\n\n    jest.useFakeTimers();\n  });\n\n  it('should render a closed <Search /> menu with an input field on default', () => {\n    renderWithProviders(\n      <Search options={basicDropDownOptions} ariaInputLabel=\"label\" />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    const menu = screen.queryAllByRole('listbox');\n    expect(menu).toStrictEqual([]);\n  });\n\n  it('should show placeholder value when no selected value is found', () => {\n    renderWithProviders(\n      <Search options={basicDropDownOptions} placeholder=\"select a value\" />\n    );\n\n    const placeholder = screen.getByPlaceholderText('select a value');\n    expect(placeholder).toBeInTheDocument();\n  });\n\n  it(\"should show selectedValue's associated label in input when selectedValue is present\", () => {\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        placeholder=\"select a value\"\n        ariaInputLabel=\"my aria label\"\n        selectedValue={basicDropDownOptions[2]}\n      />\n    );\n\n    const input = screen.getByDisplayValue(basicDropDownOptions[2].label);\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should allow inputState to update outside of options in menu', async () => {\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        placeholder=\"select a value\"\n        ariaInputLabel=\"my label\"\n      />\n    );\n\n    const input = screen.getByPlaceholderText('select a value');\n\n    fireEvent.change(input, { target: { value: 'bruce wayne' } });\n\n    await waitFor(() => {\n      expect(screen.getByDisplayValue('bruce wayne')).toBeInTheDocument();\n    });\n\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should show <Search /> menu when input has 1 or more characters', () => {\n    renderWithProviders(\n      <Search\n        emptyText=\"No options available\"\n        options={basicDropDownOptions}\n        ariaInputLabel=\"label\"\n      />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.click(input);\n    fireEvent.change(input, { target: { value: 'bruce' } });\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n  });\n\n  it('should show an active icon on list item that is active', () => {\n    renderWithProviders(\n      <Search\n        emptyText=\"No options available\"\n        ariaInputLabel=\"label\"\n        isKeepMenuOpenOnSelection={false}\n        options={basicDropDownOptions}\n        selectedValue={basicDropDownOptions[2]}\n      />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.click(input);\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    const activeMenuItem = screen.getByRole('option', {\n      name: `Selected ${basicDropDownOptions[2].label}`,\n    });\n    expect(activeMenuItem).toBeInTheDocument();\n  });\n\n  // Mouse events\n  it('should not expand menu when disabled is true', () => {\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        ariaInputLabel=\"my label\"\n        disabled\n      />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.click(input);\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    const menu = screen.queryAllByRole('listbox');\n    expect(menu).toStrictEqual([]);\n  });\n\n  it('should not expand menu with selected value when disabled is true', () => {\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        selectedValue={basicDropDownOptions[2]}\n        ariaInputLabel=\"my label\"\n        disabled\n      />\n    );\n\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    fireEvent.click(input);\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    const menu = screen.queryAllByRole('listbox');\n    expect(menu).toStrictEqual([]);\n  });\n\n  it('should not trigger onMenuItemClick when \"enter\" is hit but input has no value', () => {\n    const onClickMock = jest.fn();\n\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        ariaInputLabel=\"my dropDown label\"\n        onMenuItemClick={onClickMock}\n        selectedValue={basicDropDownOptions[2]}\n      />\n    );\n\n    // Fire click event\n    const input = screen.getByRole('combobox');\n\n    fireEvent.focus(input);\n    fireEvent.change(input, { target: { value: '' } });\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });\n\n    expect(onClickMock).toHaveBeenCalledTimes(0);\n  });\n\n  it('should trigger onMenuItemClick when \"enter\" is hit and input has value', () => {\n    const onClickMock = jest.fn();\n\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        ariaInputLabel=\"my dropDown label\"\n        onMenuItemClick={onClickMock}\n      />\n    );\n\n    // Fire click event\n    const input = screen.getByRole('combobox');\n\n    fireEvent.focus(input);\n    fireEvent.change(input, { target: { value: 'tapir' } });\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });\n\n    // first prop we get back is the event\n    expect(onClickMock).toHaveBeenCalledWith(expect.anything(), {\n      label: 'tapir',\n      value: 'tapir',\n    });\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n\n  it('should trigger onMenuItemClick from menu when input has value and menu can be seen', () => {\n    const onClickMock = jest.fn();\n\n    renderWithProviders(\n      <Search\n        options={basicDropDownOptions}\n        ariaInputLabel=\"my dropDown label\"\n        onMenuItemClick={onClickMock}\n      />\n    );\n\n    // Fire click event\n    const input = screen.getByRole('combobox');\n\n    fireEvent.focus(input);\n    fireEvent.change(input, { target: { value: 'capybara' } });\n\n    act(() => {\n      // wait for debounced callback to allow a select click handler to process\n      jest.runOnlyPendingTimers();\n    });\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n\n    const menuItems = screen.getAllByRole('option');\n    expect(menuItems).toHaveLength(12);\n\n    fireEvent.click(menuItems[2]);\n\n    // first prop we get back is the event\n    expect(onClickMock).toHaveBeenCalledWith(\n      expect.anything(),\n      basicDropDownOptions[2]\n    );\n\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n});\n\n// TODO: Keyboard events need mock useKeyDownEffect\n// https://github.com/googleforcreators/web-stories-wp/issues/5764\n"
  },
  {
    "path": "packages/design-system/src/components/search/test/useSearch.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\n\nimport {\n  basicDropDownOptions,\n  nestedDropDownOptions,\n} from '../../../testUtils/sampleData';\nimport useSearch from '../useSearch';\n\ndescribe('useSearch()', () => {\n  it('should return falsy for activeOption when no selectedValue is present', () => {\n    const { result } = renderHook(() => useSearch({ options: [] }));\n\n    expect(result.current.activeOption).toBeFalsy();\n  });\n\n  it('should return object from options containing selectedValue as active option', () => {\n    const { result } = renderHook(() =>\n      useSearch({\n        selectedValue: basicDropDownOptions[2],\n        options: basicDropDownOptions,\n      })\n    );\n\n    expect(result.current.activeOption).toMatchObject(basicDropDownOptions[2]);\n  });\n\n  it('should return undefined for activeOption when selectedValue is empty', () => {\n    const { result } = renderHook(() =>\n      useSearch({\n        selectedValue: {},\n        options: basicDropDownOptions,\n      })\n    );\n\n    act(() => {\n      result.current.setInputState('freeform answer not in options');\n    });\n\n    expect(result.current.activeOption).toBeUndefined();\n    expect(result.current.inputState).toBe('freeform answer not in options');\n  });\n\n  it('should return an empty array when no options are present', () => {\n    const { result } = renderHook(() =>\n      useSearch({ selectedValue: {}, options: [] })\n    );\n\n    expect(result.current.groups).toStrictEqual([]);\n  });\n\n  it('should return an empty array when only bad options are present', () => {\n    const { result } = renderHook(() =>\n      useSearch({\n        selectedValue: {},\n        options: [\n          'things that are not good for a dropDown',\n          1,\n          { 500: '', foo: () => {} },\n        ],\n      })\n    );\n\n    expect(result.current.groups).toStrictEqual([]);\n  });\n\n  it('should return only sanitized options that meet requirements', () => {\n    const { result } = renderHook(() =>\n      useSearch({ selectedValue: {}, options: nestedDropDownOptions })\n    );\n\n    expect(result.current.groups).toStrictEqual([\n      {\n        options: [\n          { label: 'ET', value: 'alien-1' },\n          { label: 'Stitch', value: 'alien-2' },\n          { label: 'Groot', value: 'alien-3' },\n          { label: 'The Worm Guys', value: 'alien-4' },\n          { label: \"Na'vi\", value: 'alien-5' },\n          { label: 'Arachnids', value: 'alien-6' },\n          { label: 'The Predator', value: 'alien-7' },\n          { label: 'Xenomorph', value: 'alien-8' },\n        ],\n        label: 'aliens',\n      },\n      {\n        options: [\n          { label: 'Smaug', value: 'dragon-1' },\n          { label: 'Mushu', value: 'dragon-2' },\n          { label: 'Toothless', value: 'dragon-3' },\n          { label: 'Falkor', value: 'dragon-4' },\n          { label: 'Drogon', value: 'dragon-5' },\n          { label: 'Kalessin', value: 'dragon-6' },\n        ],\n        label: 'dragons',\n      },\n      {\n        options: [\n          { label: 'Snoopy', value: 'dog-1' },\n          { label: 'Scooby', value: 'dog-2' },\n        ],\n        label: 'dogs',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/search/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { DropdownItem, NestedDropdownItem } from '../menu';\nimport type { Placement } from '../popup';\n\nexport interface UseSearchProps {\n  options: NestedDropdownItem[] | DropdownItem[];\n  handleSearchValueChange?: (value: string) => void;\n  selectedValue?: DropdownItem;\n  searchValue?: string;\n}\n\nexport interface SearchProps extends Omit<UseSearchProps, 'options'> {\n  options?: NestedDropdownItem[] | DropdownItem[];\n  ariaInputLabel?: string;\n  ariaClearLabel?: string;\n  disabled?: boolean;\n  hasError?: boolean;\n  hint?: string;\n  label?: string;\n  onMenuItemClick?: (evt: Event, option: DropdownItem) => void;\n  onClear?: () => void;\n  placeholder?: string;\n  placement?: Placement;\n  popupFillWidth?: number;\n  popupZIndex?: number;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/search/useSearch.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport { sprintf, _n, __ } from '@googleforcreators/i18n';\n/**\n * Internal dependencies\n */\nimport { getGroups } from '../menu/utils';\nimport type { DropdownValue } from '../menu';\nimport { useLiveRegion } from '../../utils';\nimport type { UseSearchProps } from './types';\n\nexport default function useSearch({\n  handleSearchValueChange,\n  selectedValue,\n  searchValue,\n  options,\n}: UseSearchProps) {\n  const speak = useLiveRegion('assertive');\n\n  /**\n   *Control when associated menu of search should be visible.\n   */\n  const [isOpen, _setIsOpen] = useState(false);\n  const setIsOpen = useDebouncedCallback(_setIsOpen, 100);\n\n  /**\n   * Control whether focus is shifted to menu or input.\n   */\n  const [isMenuFocused, _setIsMenuFocused] = useState(false);\n  const setIsMenuFocused = useDebouncedCallback(_setIsMenuFocused, 300, {\n    leading: true,\n  });\n\n  useEffect(() => {\n    if (!isOpen) {\n      setIsMenuFocused(false);\n    }\n  }, [isOpen, setIsMenuFocused]);\n\n  /**\n   * list of options to display in menu.\n   */\n\n  const groups = useMemo(() => getGroups(options), [options]);\n\n  /**\n   * the active option, if there is a selectedValue present that matches an option.\n   */\n\n  const getActiveOption = useCallback(\n    (selectedVal: DropdownValue) =>\n      groups\n        .flatMap((group) => group.options)\n        .find(\n          (option) =>\n            String(option.value).toLowerCase() ===\n            String(selectedVal).toLowerCase()\n        ),\n    [groups]\n  );\n\n  const activeOption = useMemo(() => {\n    const selected = selectedValue ? String(selectedValue.value) : searchValue;\n    if (!selected || groups.length === 0) {\n      return null;\n    }\n    return getActiveOption(selected);\n  }, [selectedValue, searchValue, groups, getActiveOption]);\n\n  /**\n   * Monitor input value separate from selected value to respect user input while maintaining accurate results.\n   */\n  const [inputState, _setInputState] = useState<string | undefined>(\n    searchValue\n  );\n\n  /**\n   * send the inputState when it changes back to the parent so that any results that need to change can be changed.\n   */\n  const setInputState = useCallback(\n    (value: string | undefined) => {\n      _setInputState(value);\n      if (value !== undefined) {\n        handleSearchValueChange?.(value);\n      }\n    },\n    [handleSearchValueChange]\n  );\n\n  useEffect(() => {\n    if (inputState === undefined && selectedValue?.value !== undefined) {\n      setInputState(selectedValue?.label || '');\n    }\n  }, [inputState, setInputState, selectedValue]);\n\n  /* Announce changes to the length of the list */\n  useEffect(() => {\n    if (isOpen && inputState?.length) {\n      const message = options.length\n        ? sprintf(\n            /* translators: %d: number of results. */\n            _n(\n              '%d result found.',\n              '%d results found.',\n              options.length,\n              'web-stories'\n            ),\n            options.length\n          )\n        : __('No results found.', 'web-stories');\n\n      speak(message);\n    }\n  }, [inputState, isOpen, options.length, speak]);\n\n  return {\n    activeOption,\n    getActiveOption,\n    groups,\n    inputState,\n    setInputState,\n    isMenuFocused,\n    setIsMenuFocused,\n    isOpen,\n    setIsOpen,\n  };\n}\n"
  },
  {
    "path": "packages/design-system/src/components/slider/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Slider } from './slider';\n"
  },
  {
    "path": "packages/design-system/src/components/slider/slider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  useRef,\n  useCallback,\n  useLayoutEffect,\n  useState,\n} from '@googleforcreators/react';\nimport type { ChangeEvent, ComponentProps } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { useKeyDownEffect } from '../keyboard';\nimport { Tooltip } from '../tooltip';\nimport { Placement } from '../popup';\nimport { noop } from '../../utils';\n\ninterface SliderElementProps {\n  thumbSize: number;\n  percentage: number;\n  width: number;\n}\n\nconst DEFAULT_SIZE = 24;\nconst rangeThumb = css<SliderElementProps>`\n  appearance: none;\n  width: ${({ thumbSize }) => thumbSize}px;\n  height: ${({ thumbSize }) => thumbSize}px;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.primaryNormal};\n  cursor: pointer;\n  border-radius: 50px;\n`;\nconst rangeThumbHover = css<SliderElementProps>`\n  background-color: ${({ theme }) => theme.colors.interactiveBg.primaryHover};\n`;\n\nconst rangeThumbFocus = css<SliderElementProps>`\n  z-index: 2;\n  border: 2px solid ${({ theme }) => theme.colors.accent.secondary};\n  padding: 2px;\n  background-clip: content-box;\n  width: ${({ thumbSize }) => thumbSize + 8}px;\n  height: ${({ thumbSize }) => thumbSize + 8}px;\n  margin-left: ${({ thumbSize, width, percentage }) =>\n    getFocusedThumbMargin(percentage, thumbSize, width)}px;\n`;\n\nconst Input = styled.input.attrs({\n  type: 'range',\n})<SliderElementProps>`\n  z-index: 1;\n  position: relative;\n  min-width: 100px;\n  cursor: pointer;\n  outline: none;\n  background: ${({ theme }) => theme.colors.bg.quaternary};\n  border-radius: 100px;\n  height: 4px;\n  appearance: none;\n  flex: 1;\n  margin: 0;\n\n  ::-webkit-slider-thumb {\n    ${rangeThumb}\n  }\n\n  ::-moz-range-thumb {\n    ${rangeThumb}\n  }\n\n  ::-ms-thumb {\n    ${rangeThumb}\n  }\n\n  ::before {\n    z-index: -1;\n    position: absolute;\n    content: ' ';\n    height: 6px;\n    top: calc(50% - 3px);\n    left: -calc(\n      ${({ percentage, thumbSize, width }) =>\n          getAdjustedWidthValue(percentage, thumbSize, width)}% -\n        4px\n    );\n    width: ${({ percentage = 0 }) => percentage}%;\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.primaryNormal};\n    border-radius: 50px;\n  }\n\n  :hover {\n    ::before {\n      background-color: ${({ theme }) =>\n        theme.colors.interactiveBg.primaryHover};\n    }\n    ::-webkit-slider-thumb {\n      ${rangeThumbHover}\n    }\n\n    ::-moz-range-thumb {\n      ${rangeThumbHover}\n    }\n\n    ::-ms-thumb {\n      ${rangeThumbHover}\n    }\n  }\n\n  &:focus {\n    &::-webkit-slider-thumb {\n      ${rangeThumbFocus}\n    }\n\n    &::-moz-range-thumb {\n      ${rangeThumbFocus}\n    }\n\n    &::-ms-thumb {\n      ${rangeThumbFocus}\n    }\n  }\n`;\n\n/**\n * Gets a value adjusted by the \"real\" absolute available width on the slider.\n * The available width for the slider is the total width - the thumb size\n * since otherwise values like left: 100% etc. would already go out of the slider.\n */\nfunction getAdjustedWidthValue(value = 0, thumbSize: number, width: number) {\n  if (!width) {\n    // Avoid dividing by 0 issues.\n    width = 1;\n  }\n  return ((width - thumbSize) / width) * value;\n}\n\nfunction getFocusedThumbMargin(\n  percentage: number,\n  thumbSize: number,\n  width: number\n) {\n  // 4 comes from 2px borer + 2px gap between the border and thumb\n  const leftMargin = Math.ceil(getAdjustedWidthValue(4, thumbSize, width));\n  // After 50% the left margin becomes positive so we take 50% as the 100%, thus multiplying by 2.\n  return -leftMargin + percentage * 2 * 0.01 * leftMargin;\n}\n\nconst Wrapper = styled.div`\n  position: relative;\n  left: 0;\n  top: 0;\n`;\n\n// This is static div positioned 12px below the top center of the thumb.\n// This is used to align the tooltip by, as this is the base position at the 0 mark.\nconst FakeThumb = styled.div<{ thumbSize: number }>`\n  width: 0;\n  height: 0;\n  position: absolute;\n  left: ${({ thumbSize }) => thumbSize / 2}px;\n  top: ${({ thumbSize }) => -thumbSize / 2 + 12}px;\n`;\n\ninterface SliderProps extends ComponentProps<typeof Input> {\n  minorStep: number;\n  majorStep: number;\n  handleChange?: (value: number) => void;\n  value: number;\n  min?: number;\n  max?: number;\n  thumbSize?: number;\n  suffix?: string;\n  popupZIndexOverride?: number;\n}\n\n/**\n * A styled range input component.\n *\n * This component must be initialized with two step values - one value (`majorStep`)\n * is the coarse value, that simply pressing arrow-left and arrow-right will move\n * between (e.g. 1) and the other (`minorStep`) is the more fine-grained value (e.g. 0.1)\n * which can be used by pressing shift+arrow.\n *\n * When using the mouse, only `minorStep` is considered and this is the resolution the\n * range has.\n */\nfunction Slider({\n  minorStep,\n  majorStep,\n  handleChange = noop,\n  value,\n  min = 0,\n  max = 500,\n  thumbSize = DEFAULT_SIZE,\n  suffix = '',\n  popupZIndexOverride,\n  ...rest\n}: SliderProps) {\n  const ref = useRef<HTMLInputElement>(null);\n  const fakeThumbRef = useRef<HTMLDivElement>(null);\n  const [widthTracker, setWidthTracker] = useState<number>(0);\n  const update = useCallback(\n    (direction, isMajor) => {\n      const diff = direction * (isMajor ? majorStep : minorStep);\n      let val = value + diff;\n      val = typeof min === 'number' ? Math.max(min, val) : val;\n      val = typeof max === 'number' ? Math.min(max, val) : val;\n      handleChange(val);\n    },\n    [minorStep, majorStep, handleChange, min, max, value]\n  );\n\n  const percentageVal = ((value - min) / (max - min)) * 100;\n\n  useLayoutEffect(() => {\n    if (ref.current && !widthTracker) {\n      const { width } = ref.current.getBoundingClientRect();\n      setWidthTracker(width);\n    }\n  }, [ref, widthTracker]);\n\n  useKeyDownEffect(ref, ['left', 'down'], () => update(-1, true), [update]);\n  useKeyDownEffect(ref, ['right', 'up'], () => update(1, true), [update]);\n  useKeyDownEffect(ref, ['shift+left', 'shift+down'], () => update(-1, false), [\n    update,\n  ]);\n  useKeyDownEffect(ref, ['shift+right', 'shift+up'], () => update(1, false), [\n    update,\n  ]);\n\n  const printValue = `${value}${suffix}`;\n  return (\n    <Tooltip\n      title={printValue}\n      placement={Placement.Top}\n      popupZIndexOverride={popupZIndexOverride}\n      forceAnchorRef={fakeThumbRef}\n      styleOverride={{\n        transform: `translate(${\n          ((widthTracker - thumbSize) * percentageVal) / 100\n        }px, 0)`,\n      }}\n    >\n      <Wrapper>\n        <Input\n          percentage={percentageVal}\n          ref={ref}\n          onChange={(evt: ChangeEvent<HTMLInputElement>) =>\n            handleChange(evt.target.valueAsNumber)\n          }\n          step={minorStep}\n          value={value}\n          min={min}\n          max={max}\n          thumbSize={thumbSize}\n          width={widthTracker}\n          aria-valuenow={value}\n          aria-valuetext={printValue}\n          {...rest}\n        />\n        <FakeThumb ref={fakeThumbRef} thumbSize={thumbSize} />\n      </Wrapper>\n    </Tooltip>\n  );\n}\n\nexport default Slider;\n"
  },
  {
    "path": "packages/design-system/src/components/slider/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Text } from '../../..';\nimport { Slider } from '..';\n\nconst Container = styled.div`\n  padding: 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nexport default {\n  title: 'DesignSystem/Components/Slider',\n  component: Slider,\n  args: {\n    thumbSize: 24,\n    min: 0,\n    max: 100,\n    majorStep: 10,\n    minorStep: 1,\n  },\n  parameters: {\n    controls: {\n      exclude: ['handleChange', 'value', 'suffix'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const [lightValue, setLightValue] = useState(0);\n    const [darkValue, setDarkValue] = useState(0);\n\n    return (\n      <>\n        <Container>\n          <Text.Paragraph>{'Percentage:'}</Text.Paragraph>\n          <Slider\n            {...args}\n            handleChange={setLightValue}\n            value={lightValue}\n            suffix=\"%\"\n          />\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <Text.Paragraph>{'Milliseconds:'}</Text.Paragraph>\n            <Slider\n              {...args}\n              handleChange={setDarkValue}\n              value={darkValue}\n              suffix=\"ms\"\n            />\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as SnackbarContainer } from './snackbarContainer';\nexport { default as SnackbarMessage } from './snackbarMessage';\nexport * from './types';\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/snackbarContainer.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { FC, ComponentProps } from 'react';\nimport {\n  createRef,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { useLiveRegion } from '../../utils';\nimport SnackbarMessage from './snackbarMessage';\nimport { SnackbarPlacement } from './types';\nimport type { SnackbarNotification } from './types';\n\nconst StyledContainer = styled.div<{\n  placement: SnackbarPlacement;\n  alignItems?: string;\n}>`\n  position: fixed;\n  top: ${({ placement = 'center' }) =>\n    placement.indexOf('top') === 0 ? 0 : 'inherit'};\n  bottom: ${({ placement = 'center' }) =>\n    placement.indexOf('bottom') === 0 ? 0 : 'inherit'};\n  ${getSnackbarXPos};\n  margin-bottom: 33px;\n  display: flex;\n  flex-direction: column;\n  align-items: ${({ alignItems = 'center' }) => alignItems};\n  width: 100%;\n  z-index: 2147483647;\n  pointer-events: none;\n`;\n\nfunction getSnackbarXPos({ placement }: { placement: SnackbarPlacement }) {\n  switch (placement) {\n    case SnackbarPlacement.Top:\n    case SnackbarPlacement.Bottom:\n      return `\n      left: calc(50% + 4rem);\n      transform: translateX(-50%);\n      width: auto;\n    `;\n    case SnackbarPlacement.TopLeft:\n    case SnackbarPlacement.BottomLeft:\n      return 'left: 60px;';\n    case SnackbarPlacement.TopRight:\n    case SnackbarPlacement.BottomRight:\n      return 'right: 60px;';\n    default:\n      return 'left: 60px;';\n  }\n}\n\nconst ChildContainer = styled.div`\n  &.react-snackbar-alert__snackbar-container-enter {\n    opacity: 0;\n  }\n\n  &.react-snackbar-alert__snackbar-container-enter-active {\n    opacity: 1;\n    transition: all 300ms ease-out;\n  }\n\n  &.react-snackbar-alert__snackbar-container-exit {\n    opacity: 1;\n  }\n\n  &.react-snackbar-alert__snackbar-container-exit-active {\n    opacity: 0;\n    transition: all 100ms ease-out;\n  }\n`;\n\ninterface SnackbarContainerProps {\n  component?: FC<ComponentProps<typeof SnackbarMessage>>;\n  notifications?: SnackbarNotification[];\n  onRemove?: (\n    notification: SnackbarNotification | SnackbarNotification[]\n  ) => void;\n  placement?: SnackbarPlacement;\n  max?: number;\n}\n\nfunction SnackbarContainer({\n  component: Component = SnackbarMessage,\n  notifications = [],\n  onRemove,\n  placement = SnackbarPlacement.Bottom,\n  max = 1,\n}: SnackbarContainerProps) {\n  const speak = useLiveRegion('assertive');\n  const announcedNotifications = useRef(new Set());\n  const ids = useMemo(() => notifications.map(() => uuidv4()), [notifications]);\n\n  const orderedNotifications =\n    placement.indexOf('top') === 0\n      ? [...notifications].reverse()\n      : notifications;\n\n  const handleDismiss = useCallback(\n    (notification: SnackbarNotification) => () => {\n      onRemove?.(notification);\n      notification.onDismiss?.();\n    },\n    [onRemove]\n  );\n\n  useEffect(() => {\n    if (typeof max === 'number' && notifications.length > max) {\n      onRemove?.(notifications.slice(0, notifications.length - max));\n    }\n    return undefined;\n  }, [max, notifications, onRemove]);\n\n  // Announce messages to screen reader when a new message shows up\n  useEffect(() => {\n    notifications.forEach((notification) => {\n      if (!announcedNotifications.current.has(notification)) {\n        // speak the message\n        const message = `${String(notification.message)} ${\n          notification.actionHelpText || ''\n        }`.trim();\n\n        speak(message);\n\n        announcedNotifications.current.add(notification);\n      }\n    });\n  }, [notifications, speak]);\n  return (\n    <StyledContainer placement={placement}>\n      <TransitionGroup>\n        {orderedNotifications.map((notification) => {\n          const {\n            actionLabel,\n            dismissible,\n            message,\n            onAction,\n            preventActionDismiss,\n            preventAutoDismiss,\n            timeout,\n            ...notificationProps\n          } = notification;\n          const id = notification.id || ids[0];\n          const ref = createRef<HTMLDivElement>();\n          return (\n            <CSSTransition\n              in\n              key={id}\n              timeout={300}\n              unmountOnExit\n              nodeRef={ref}\n              classNames=\"react-snackbar-alert__snackbar-container\"\n            >\n              <ChildContainer ref={ref}>\n                <Component\n                  {...notificationProps}\n                  aria-hidden\n                  placement={placement}\n                  onDismiss={handleDismiss(notification)}\n                  onAction={onAction}\n                  actionLabel={actionLabel}\n                  message={message}\n                  showCloseButton={dismissible}\n                  removeMessageTimeInterval={timeout}\n                  isPreventAutoDismiss={preventAutoDismiss}\n                  isPreventActionDismiss={preventActionDismiss}\n                />\n              </ChildContainer>\n            </CSSTransition>\n          );\n        })}\n      </TransitionGroup>\n    </StyledContainer>\n  );\n}\n\nexport default SnackbarContainer;\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/snackbarMessage.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef, MouseEvent } from 'react';\nimport { useRef, useEffect, useCallback } from '@googleforcreators/react';\nimport { rgba } from 'polished';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Button } from '../button';\nimport { Cross, CheckmarkSmall, ExclamationOutline } from '../../icons';\nimport { Text } from '../typography';\nimport { focusableOutlineCSS } from '../../theme/helpers';\nimport { TextSize } from '../../theme';\nimport { noop } from '../../utils';\nimport {\n  AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX,\n  AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MIN,\n  DEFAULT_MESSAGE_Z_INDEX,\n  SnackbarPlacement,\n  ThumbnailStatus,\n} from './types';\nimport type { SnackbarNotificationThumbnail } from './types';\n\nconst MessageContainer = styled.div<{\n  customZIndex?: number;\n  hasAction?: boolean;\n  placement?: SnackbarPlacement;\n}>`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  min-height: 48px;\n  padding: 10px 16px;\n  margin-top: 20px;\n  background-color: ${({ theme }) => theme.colors.inverted.bg.primary};\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  border: ${({ theme }) =>\n    `1px solid ${rgba(theme.colors.standard.white, 0.24)}`};\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  z-index: ${({ customZIndex }) => customZIndex || DEFAULT_MESSAGE_Z_INDEX};\n  pointer-events: auto;\n  position: absolute;\n  bottom: 0;\n`;\n\nconst Message = styled(Text.Paragraph)<{\n  hasAction?: boolean;\n  hasThumbnail?: boolean;\n}>`\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  max-width: 430px;\n  padding-right: ${({ hasAction, hasThumbnail }) => {\n    if (hasThumbnail) {\n      return '16px';\n    } else if (hasAction) {\n      return '52px';\n    } else {\n      return '0px';\n    }\n  }};\n`;\n\nconst ActionContainer = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n`;\n\nconst ThumbnailWrapper = styled.div<{ hasAction?: boolean }>`\n  position: relative;\n  margin-left: 16px;\n  margin-right: ${({ hasAction }) => (hasAction ? 16 : 0)}px;\n`;\n\nconst Thumbnail = styled.img<{ status?: ThumbnailStatus }>`\n  max-height: 45px;\n  max-width: 45px;\n  min-height: ${(45 * 2) / 3}px;\n  min-width: ${(45 * 2) / 3}px;\n  background-color: ${({ theme }) => theme.colors.fg.tertiary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${({ theme, status }) => {\n    if (status === ThumbnailStatus.Success) {\n      return css`\n        border: 1px solid ${theme.colors.green[20]};\n      `;\n    } else if (status === ThumbnailStatus.Error) {\n      return css`\n        border: 1px solid ${theme.colors.red[20]};\n      `;\n    }\n    return undefined;\n  }};\n`;\n\nconst ThumbnailIcon = styled.div<{ status?: ThumbnailStatus }>`\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  ${({ theme, status }) => {\n    if (status === ThumbnailStatus.Success) {\n      return css`\n        width: 30px;\n        color: ${theme.colors.fg.positive};\n      `;\n    } else if (status === ThumbnailStatus.Error) {\n      return css`\n        width: 20px;\n        color: ${theme.colors.fg.negative};\n      `;\n    }\n    return undefined;\n  }};\n\n  svg {\n    width: 100%;\n    height: auto;\n  }\n`;\n\nconst ActionButton = styled(Button)`\n  align-self: flex-end;\n  min-width: 1px;\n  height: 2em;\n  padding: 0;\n  color: ${({ theme }) => theme.colors.inverted.fg.linkNormal};\n  font-weight: ${({ theme }) => theme.typography.weight.bold};\n\n  ${({ theme }) =>\n    focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.inverted.bg.primary\n    )}\n\n  &:hover,\n  &:active {\n    color: ${({ theme }) => theme.colors.inverted.fg.linkHover};\n  }\n`;\n\nconst CloseButton = styled(Button)`\n  height: 2em;\n  padding: 0;\n  margin-left: 16px;\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n\n  ${({ theme }) =>\n    focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.inverted.bg.primary\n    )}\n\n  svg {\n    height: 32px;\n  }\n`;\n\ninterface SnackbarMessageProps extends ComponentPropsWithoutRef<'div'> {\n  actionLabel?: JSX.Element;\n  onAction?: (evt: MouseEvent<HTMLButtonElement>) => void;\n  onDismiss?: () => void;\n  isPreventAutoDismiss?: boolean;\n  isPreventActionDismiss?: boolean;\n  thumbnail?: SnackbarNotificationThumbnail;\n  message?: string;\n  removeMessageTimeInterval?: number;\n  showCloseButton?: boolean;\n  placement?: SnackbarPlacement;\n  actionHelpText?: string;\n}\n\nfunction SnackbarMessage({\n  'aria-label': ariaLabel,\n  actionLabel,\n  onAction = noop,\n  onDismiss = noop,\n  isPreventAutoDismiss,\n  isPreventActionDismiss,\n  thumbnail,\n  message,\n  removeMessageTimeInterval,\n  showCloseButton = true,\n  placement = SnackbarPlacement.Bottom,\n  actionHelpText,\n  ...props\n}: SnackbarMessageProps) {\n  const autoDismissRef = useRef<(() => void) | null>(null);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  autoDismissRef.current = isPreventAutoDismiss ? noop : onDismiss;\n\n  const messageRemovalTimeInterval = useRef(\n    typeof removeMessageTimeInterval === 'number' &&\n      removeMessageTimeInterval <= AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX &&\n      removeMessageTimeInterval >= AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MIN\n      ? removeMessageTimeInterval\n      : AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX\n  );\n\n  useEffect(() => {\n    if (!autoDismissRef.current) {\n      return noop;\n    }\n    const dismissTimeout = setTimeout(\n      () => autoDismissRef.current?.(),\n      messageRemovalTimeInterval.current\n    );\n    return () => clearTimeout(dismissTimeout);\n  }, []);\n\n  const handleAction = useCallback(\n    (evt: MouseEvent<HTMLButtonElement>) => {\n      onAction(evt);\n      if (!isPreventActionDismiss) {\n        onDismiss();\n      }\n    },\n    [onAction, onDismiss, isPreventActionDismiss]\n  );\n\n  const hasAction = Boolean(actionLabel);\n  const hasThumbnail = Boolean(actionLabel);\n\n  return (\n    <MessageContainer\n      role=\"alert\"\n      hasAction={hasAction}\n      placement={placement}\n      {...props}\n    >\n      <Message\n        aria-label={ariaLabel}\n        size={TextSize.Small}\n        hasAction={hasAction}\n        hasThumbnail={hasThumbnail}\n      >\n        {message}\n      </Message>\n      {thumbnail && (\n        <ThumbnailWrapper hasAction={hasAction}>\n          <Thumbnail\n            decoding=\"async\"\n            crossOrigin=\"anonymous\"\n            src={thumbnail.src}\n            alt={thumbnail.alt}\n            status={thumbnail.status}\n          />\n          <ThumbnailIcon status={thumbnail.status}>\n            {thumbnail.status === ThumbnailStatus.Success && <CheckmarkSmall />}\n            {thumbnail.status === ThumbnailStatus.Error && (\n              <ExclamationOutline />\n            )}\n          </ThumbnailIcon>\n        </ThumbnailWrapper>\n      )}\n      {(actionLabel || showCloseButton) && (\n        <ActionContainer>\n          {actionLabel && (\n            <ActionButton onClick={handleAction}>{actionLabel}</ActionButton>\n          )}\n          {showCloseButton && (\n            <CloseButton\n              onClick={onDismiss}\n              aria-label={__('Close', 'web-stories')}\n              tabIndex={-1}\n            >\n              <Cross aria-hidden />\n            </CloseButton>\n          )}\n        </ActionContainer>\n      )}\n    </MessageContainer>\n  );\n}\n\nexport default SnackbarMessage;\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled, { ThemeProvider } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { theme } from '../../..';\nimport { DarkThemeProvider } from '../../../storybookUtils/darkThemeProvider';\nimport SnackbarContainer from '../snackbarContainer';\nimport { ThumbnailStatus } from '../types';\nimport { Button, ButtonType } from '../..';\n\nconst buttonText = [\n  'Sorry, your image failed to load',\n  'Success! One cow successfully bought',\n  \"We're sorry, the number you are trying to reach is unavailable\",\n  'Pizza',\n  'Pizza bread',\n  'Bread sticks',\n  'goulash',\n  'Porcupines are cool',\n  'Whales are kind of cool too',\n];\n\nconst Container = styled.div`\n  background-color: ${(props) => props.theme.colors.bg.primary};\n  width: 100vw;\n  height: 100vh;\n  overflow: hidden;\n`;\n\nexport default {\n  title: 'DesignSystem/Components/Snackbar',\n  args: {\n    actionLabel: '',\n    customZIndex: 1,\n    dismissible: true,\n    preventAutoDismiss: true,\n    message: 'Sorry! File failed to upload.',\n  },\n  argTypes: {\n    onAction: { action: 'on action clicked' },\n    onDismiss: { action: 'on dismiss fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <ThemeProvider theme={theme}>\n        <Container>\n          <SnackbarContainer\n            notifications={[\n              {\n                'aria-label':\n                  'this is my aria label giving my message context for screen reader users',\n                ...args,\n              },\n            ]}\n          />\n        </Container>\n      </ThemeProvider>\n    );\n  },\n};\n\nexport const LightThemeDefault = {\n  render: function Render(args) {\n    return <SnackbarContainer notifications={[{ ...args }]} />;\n  },\n};\n\nexport const Action = {\n  render: function Render(args) {\n    return (\n      <SnackbarContainer\n        notifications={[\n          {\n            ...args,\n            timeout: 80000,\n          },\n        ]}\n      />\n    );\n  },\n\n  args: {\n    actionLabel: 'Retry',\n  },\n};\n\nexport const EarlyDismissWithAction = {\n  render: function Render(args) {\n    return (\n      <SnackbarContainer\n        notifications={[\n          {\n            timeout: 80000,\n            ...args,\n          },\n        ]}\n      />\n    );\n  },\n\n  args: {\n    actionLabel: 'Retry',\n  },\n};\n\nexport const NoActionWithRemoveMessageTimingOverride = {\n  render: function Render(args) {\n    return (\n      <SnackbarContainer\n        notifications={[\n          {\n            timeout: 80000,\n            ...args,\n          },\n        ]}\n      />\n    );\n  },\n};\n\nexport const LongMessage = {\n  render: function Render(args) {\n    return <SnackbarContainer notifications={[{ ...args }]} />;\n  },\n\n  args: {\n    actionLabel: 'Retry',\n    message:\n      'Sorry! File failed to upload because it is way too big. Try optimizing it and upload again.',\n  },\n};\n\nexport const ThumbnailMessage = {\n  render: ({ successBool, landscapeBool, ...args }) => {\n    const success = successBool;\n    const landscape = landscapeBool;\n\n    return (\n      <DarkThemeProvider>\n        <Container>\n          <SnackbarContainer\n            notifications={[\n              {\n                thumbnail: {\n                  src: `https://picsum.photos/${landscape ? '90/60' : '60/90'}`,\n                  alt: 'test',\n                  status: success\n                    ? ThumbnailStatus.Success\n                    : ThumbnailStatus.Error,\n                },\n                ...args,\n              },\n            ]}\n          />\n        </Container>\n      </DarkThemeProvider>\n    );\n  },\n\n  args: {\n    actionLabel: 'Retry',\n    message: 'Optimization failed. Try uploading a different file.',\n    successBool: true,\n    landscapeBool: true,\n  },\n};\n\nexport const ShowSnackbarByClickingButton = {\n  render: function Render({\n    // eslint-disable-next-line react/prop-types\n    onAction,\n    // eslint-disable-next-line react/prop-types\n    onDismiss,\n    ...args\n  }) {\n    const [messageQueue, setMessageQueue] = useState([]);\n\n    const handleRemoveMessage = ({ id }) => {\n      setMessageQueue((currentMessages) => {\n        const index = currentMessages.findIndex(\n          (message) => message.key === id\n        );\n\n        return [\n          ...currentMessages.slice(0, index),\n          ...currentMessages.slice(index + 1),\n        ];\n      });\n    };\n\n    const handleOnDismiss = (evt, notification) => {\n      onDismiss(evt);\n      handleRemoveMessage(notification);\n    };\n\n    const handleAddSnackbarToQueue = () => {\n      const newId = uuidv4();\n      const randomMessage =\n        buttonText[Math.floor(Math.random() * buttonText.length)];\n\n      setMessageQueue((currentMessages) => {\n        const hasAction = Boolean(Math.round(Math.random()));\n\n        let notification = {\n          id: newId,\n          'aria-label':\n            'this is my aria label giving my message context for screen reader users',\n\n          customZIndex: args.customZIndex,\n          dismissible: args.dismissible,\n          preventAutoDismiss: args.preventAutoDismiss,\n          message: randomMessage,\n          onDismiss: (evt) => handleOnDismiss(evt, { id: newId }),\n          timeout: 5000,\n        };\n\n        if (hasAction) {\n          notification = {\n            ...notification,\n            actionLabel: args.actionLabel,\n            onAction,\n            actionHelpText: args.actionHelpText,\n          };\n        }\n\n        return [...currentMessages, notification];\n      });\n    };\n\n    return (\n      <ThemeProvider theme={theme}>\n        <Container>\n          <Button type={ButtonType.Primary} onClick={handleAddSnackbarToQueue}>\n            {'Show Snackbar'}\n          </Button>\n          <SnackbarContainer notifications={messageQueue} />\n        </Container>\n      </ThemeProvider>\n    );\n  },\n\n  args: {\n    actionLabel: 'Undo',\n    actionHelpText: 'Click this button to get instant cheese',\n    preventAutoDismiss: false,\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/test/snackbarContainer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport SnackbarContainer from '../snackbarContainer';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { noop, useLiveRegion } from '../../../utils';\n\njest.mock('../../../utils', () => ({\n  ...jest.requireActual('../../../utils'),\n  useLiveRegion: jest.fn(),\n}));\n\nconst NOTIFICATIONS = [\n  {\n    'aria-label': 'test label',\n    message: 'this is my message',\n    onDismiss: noop,\n  },\n  {\n    'aria-label': 'test label again',\n    message: 'second message',\n    onDismiss: noop,\n  },\n  {\n    'aria-label': 'test label again',\n    message: 'third one omg',\n    onDismiss: noop,\n  },\n];\n\nconst NOTIFICATION_WITH_ACTION_AND_HELP_TEXT = {\n  'aria-label': 'test label again',\n  message: 'third one omg',\n  onDismiss: noop,\n  actionLabel: 'Derp',\n  actionHelpText: \"Get out 'ma swamp\",\n};\n\ndescribe('SnackbarContainer', () => {\n  const mockUseLiveRegion = useLiveRegion;\n  const mockSpeak = jest.fn();\n\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseLiveRegion.mockReturnValue(mockSpeak);\n  });\n\n  it('should announce messages', () => {\n    const { rerender } = renderWithProviders(\n      <SnackbarContainer notifications={[]} />\n    );\n\n    expect(mockSpeak).toHaveBeenCalledTimes(0);\n\n    rerender(<SnackbarContainer notifications={[NOTIFICATIONS[0]]} />);\n\n    expect(mockSpeak).toHaveBeenCalledOnce();\n    expect(mockSpeak).toHaveBeenCalledWith(NOTIFICATIONS[0].message);\n\n    rerender(<SnackbarContainer notifications={NOTIFICATIONS} />);\n\n    expect(mockSpeak).toHaveBeenCalledTimes(3);\n    expect(mockSpeak).toHaveBeenCalledWith(NOTIFICATIONS[1].message);\n    expect(mockSpeak).toHaveBeenCalledWith(NOTIFICATIONS[2].message);\n  });\n\n  it('should announce help text for an action', () => {\n    const { rerender } = renderWithProviders(\n      <SnackbarContainer notifications={[]} />\n    );\n\n    expect(mockSpeak).toHaveBeenCalledTimes(0);\n\n    rerender(\n      <SnackbarContainer\n        notifications={[\n          {\n            ...NOTIFICATIONS[0],\n            actionHelpText: 'click this button for christmas every day',\n          },\n        ]}\n      />\n    );\n\n    expect(mockSpeak).toHaveBeenCalledOnce();\n    expect(mockSpeak).toHaveBeenCalledWith(\n      `${NOTIFICATIONS[0].message} click this button for christmas every day`\n    );\n\n    rerender(\n      <SnackbarContainer\n        notifications={[NOTIFICATION_WITH_ACTION_AND_HELP_TEXT]}\n      />\n    );\n\n    expect(mockSpeak).toHaveBeenCalledTimes(2);\n    expect(mockSpeak).toHaveBeenCalledWith(\n      `${NOTIFICATION_WITH_ACTION_AND_HELP_TEXT.message} ${NOTIFICATION_WITH_ACTION_AND_HELP_TEXT.actionHelpText}`\n    );\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/test/snackbarMessage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport SnackbarMessage from '../snackbarMessage';\nimport { AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX } from '../types';\nimport { noop } from '../../../utils/noop';\n\ndescribe('design-system/components/snackbar/SnackbarMessage', () => {\n  beforeEach(jest.clearAllMocks);\n\n  const mockHandleDismiss = jest.fn();\n\n  it('should render 1 alert', () => {\n    renderWithProviders(\n      <SnackbarMessage\n        message=\"this is an error\"\n        aria-label=\"aria label for my alert\"\n        onDismiss={mockHandleDismiss}\n      />\n    );\n\n    const alert = screen.getByRole('alert', { hidden: true });\n\n    expect(alert).toBeInTheDocument();\n  });\n\n  it(\n    `should trigger mockHandleDismiss after ${AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX}ms`,\n    async () => {\n      jest.useFakeTimers();\n\n      renderWithProviders(\n        <SnackbarMessage\n          message=\"this is an error\"\n          aria-label=\"aria label for my alert\"\n          onDismiss={mockHandleDismiss}\n        />\n      );\n      jest.runAllTimers();\n      await waitFor(() => expect(mockHandleDismiss).toHaveBeenCalledOnce());\n    },\n    AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX + 500\n  );\n\n  it('should call mockHandleDismiss when the close button is clicked', () => {\n    renderWithProviders(\n      <SnackbarMessage\n        aria-label=\"aria label for my alert\"\n        message=\"this is an error\"\n        onDismiss={mockHandleDismiss}\n        showCloseButton\n      />\n    );\n\n    expect(mockHandleDismiss).not.toHaveBeenCalled();\n\n    const closeButton = screen.getByRole('button');\n\n    fireEvent.click(closeButton);\n\n    expect(mockHandleDismiss).toHaveBeenCalledOnce();\n  });\n\n  it('should not render a button if showCloseButton is false', () => {\n    renderWithProviders(\n      <SnackbarMessage\n        aria-label=\"aria label for my alert\"\n        message=\"this is an error\"\n        onDismiss={noop}\n        showCloseButton={false}\n      />\n    );\n    const buttons = screen.queryByRole('button');\n\n    expect(buttons).not.toBeInTheDocument();\n  });\n\n  it('should recognize click on Action button', () => {\n    const mockActionClick = jest.fn();\n    renderWithProviders(\n      <SnackbarMessage\n        aria-label=\"aria label for my alert\"\n        message=\"this is an error\"\n        onAction={mockActionClick}\n        onDismiss={noop}\n        actionLabel=\"retry\"\n      />\n    );\n\n    const button = screen.getByText('retry');\n\n    fireEvent.click(button);\n\n    expect(mockActionClick).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/snackbar/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MAX = 10000;\nexport const AUTO_REMOVE_MESSAGE_TIME_INTERVAL_MIN = 1200;\nexport const DEFAULT_MESSAGE_Z_INDEX = 15;\n\nexport enum SnackbarPlacement {\n  TopLeft = 'top-left',\n  BottomLeft = 'bottom-left',\n  TopRight = 'top-right',\n  BottomRight = 'bottom-right',\n  Top = 'top',\n  Bottom = 'bottom',\n}\n\nexport enum ThumbnailStatus {\n  Success = 'success',\n  Error = 'error',\n}\n\nexport interface SnackbarNotificationThumbnail {\n  src: string;\n  alt?: string;\n  status?: ThumbnailStatus;\n}\n\nexport interface SnackbarNotification {\n  message: string;\n  actionLabel?: JSX.Element;\n  actionHelpText?: string;\n  dismissible?: boolean;\n  onAction?: () => void;\n  onDismiss?: () => void;\n  preventActionDismiss?: boolean;\n  preventAutoDismiss?: boolean;\n  timeout?: number;\n  thumbnail?: SnackbarNotificationThumbnail;\n  id?: string;\n}\n"
  },
  {
    "path": "packages/design-system/src/components/swatch/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Swatch } from './swatch';\n"
  },
  {
    "path": "packages/design-system/src/components/swatch/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Tooltip } from '../../tooltip';\nimport { Text } from '../../typography';\nimport { Cross, Pipette } from '../../../icons';\nimport Swatch from '../swatch';\n\nconst Container = styled.div`\n  padding: 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: 30% repeat(4, 15%);\n  margin-bottom: 16px;\n  text-align: right;\n`;\n\nconst Cell = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n`;\n\nexport default {\n  title: 'DesignSystem/Components/Swatch',\n  component: Swatch,\n  args: {\n    isDisabled: false,\n  },\n  parameters: {\n    controls: {\n      include: ['isDisabled'],\n    },\n  },\n};\n\nconst DEMO_COLORS = [\n  {\n    label: 'Indeterminate',\n    pattern: { color: { r: 0, g: 0, b: 255, a: 0 } },\n    isIndeterminate: true,\n  },\n  {\n    label: 'Fully transparent',\n    pattern: { color: { r: 0, g: 0, b: 255, a: 0 } },\n  },\n  {\n    label: 'Semi-transparent',\n    pattern: { color: { r: 255, g: 0, b: 0, a: 0.5 } },\n  },\n  { label: 'Solid', pattern: { color: { r: 0, g: 255, b: 0, a: 1 } } },\n  {\n    label: 'Linear gradient',\n    pattern: {\n      type: 'linear',\n      stops: [\n        { color: { r: 0, g: 255, b: 255, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    },\n  },\n  {\n    label: 'Linear gradient with transparency',\n    pattern: {\n      type: 'linear',\n      stops: [\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0 },\n        { color: { r: 255, g: 0, b: 255, a: 0.5 }, position: 1 },\n      ],\n      alpha: 0.7,\n    },\n  },\n  {\n    label: 'Linear gradient with rotation',\n    pattern: {\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 255, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.375,\n    },\n  },\n  {\n    label: 'Radial gradient',\n    pattern: {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 255, a: 1 }, position: 1 },\n      ],\n    },\n  },\n  {\n    label: 'Radial gradient with transparency',\n    pattern: {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 255, a: 0.2 }, position: 0 },\n        { color: { r: 255, g: 0, b: 255, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 255, b: 255, a: 0.5 }, position: 1 },\n      ],\n      alpha: 0.9,\n    },\n  },\n  {\n    label: 'Radial gradient off-center',\n    pattern: {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 255, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 0.7 },\n      ],\n      center: { x: 0.3, y: 0.7 },\n    },\n  },\n];\n\nconst VARIANTS = [\n  {\n    variant: 'Regular',\n  },\n  {\n    variant: 'Disabled',\n    isDisabled: true,\n  },\n  {\n    variant: 'Icon',\n    Icon: Cross,\n  },\n  {\n    variant: 'Icon + disabled',\n    Icon: Pipette,\n    isDisabled: true,\n  },\n];\n\nfunction _default(args) {\n  return (\n    <DarkThemeProvider>\n      <Container>\n        <Row>\n          {/*We need an empty cell in the corner */}\n          <Cell />\n          {VARIANTS.map(({ variant }) => (\n            <Cell key={variant}>\n              <Text.Paragraph>{variant}</Text.Paragraph>\n            </Cell>\n          ))}\n        </Row>\n        {DEMO_COLORS.map(({ label, pattern, ...patternProps }) => (\n          <Row key={label}>\n            <Text.Paragraph>{label}</Text.Paragraph>\n            {VARIANTS.map(({ variant, Icon, ...props }) => (\n              <Cell key={variant}>\n                <Swatch pattern={pattern} {...patternProps} {...props}>\n                  {Icon && <Icon />}\n                </Swatch>\n              </Cell>\n            ))}\n          </Row>\n        ))}\n        <hr />\n        {DEMO_COLORS.map(({ label, pattern, ...patternProps }) => (\n          <Row key={`${label}_tooltip`}>\n            <Text.Paragraph>{`${label} + tooltips`}</Text.Paragraph>\n            {VARIANTS.map(({ variant, Icon, ...props }) => (\n              <Tooltip title={variant} key={variant}>\n                <Cell>\n                  <Swatch\n                    pattern={pattern}\n                    {...args}\n                    {...patternProps}\n                    {...props}\n                  >\n                    {Icon && <Icon />}\n                  </Swatch>\n                </Cell>\n              </Tooltip>\n            ))}\n          </Row>\n        ))}\n      </Container>\n    </DarkThemeProvider>\n  );\n}\n\nexport { _default };\n"
  },
  {
    "path": "packages/design-system/src/components/swatch/swatch.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  generatePatternStyles,\n  getOpaquePattern,\n  hasGradient,\n  hasOpacity,\n} from '@googleforcreators/patterns';\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { ComponentPropsWithoutRef, PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers } from '../../theme';\n\nconst SIZE = 24;\n\nconst Transparent = styled.div`\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  border-radius: 100%;\n  ${themeHelpers.transparentBg}\n`;\n\nconst SwatchButton = styled.button`\n  cursor: pointer;\n  background-color: transparent;\n  border-color: transparent;\n  padding: 0;\n  border-width: 0;\n  display: block;\n  width: ${SIZE}px;\n  height: ${SIZE}px;\n  border-radius: 100%;\n  overflow: hidden;\n  position: relative;\n  ${({ disabled }) =>\n    disabled &&\n    css`\n      opacity: 0.4;\n      cursor: default;\n      /* pointer-events none here fixes an edge case in Safari when swatch is within a tooltip #9188 */\n      pointer-events: none;\n    `}\n  ${({ theme }) => themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};\n\n  ::after {\n    content: '';\n    position: absolute;\n    /* pointer-events none here fixes an edge case in Safari when swatch is within a tooltip #9188 */\n    pointer-events: none;\n    left: 0;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    border-radius: 50%;\n    border: 1px solid ${({ theme }) => theme.colors.divider.primary};\n  }\n`;\n\nconst SwatchPreview = styled(SwatchButton).attrs({\n  as: 'div',\n  type: undefined,\n})``;\n\nconst SwatchItem = styled.div<{ displaySplit?: boolean }>`\n  transform: rotate(${({ displaySplit }) => (displaySplit ? -45 : 0)}deg);\n  display: block;\n  width: 100%;\n  height: 100%;\n  font-size: 13px;\n  position: relative;\n\n  svg {\n    width: ${SIZE}px;\n    height: ${SIZE}px;\n    position: absolute;\n    top: calc(50% - ${SIZE / 2}px);\n    left: calc(50% - ${SIZE / 2}px);\n    filter: drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.4));\n    color: ${({ theme }) => theme.colors.fg.primary};\n    transform: rotate(${({ displaySplit }) => (displaySplit ? 45 : 0)}deg);\n  }\n`;\n\nconst OpaqueColorWrapper = styled.div`\n  height: ${SIZE}px;\n  width: 50%;\n  overflow: hidden;\n  position: absolute;\n  left: 0;\n  top: 0;\n`;\n\nconst OpaqueColor = styled.div`\n  height: ${SIZE}px;\n  width: ${SIZE}px;\n  position: absolute;\n  top: 0;\n  left: 0;\n`;\n\ninterface SwatchProps extends Omit<ComponentPropsWithoutRef<'button'>, 'type'> {\n  pattern?: Pattern;\n  isPreview?: boolean;\n  isDisabled?: boolean;\n  isIndeterminate?: boolean;\n}\n\nfunction Swatch({\n  pattern,\n  children,\n  isPreview = false,\n  isDisabled = false,\n  isIndeterminate = false,\n  className = '',\n  ...props\n}: PropsWithChildren<SwatchProps>) {\n  if (!pattern) {\n    return null;\n  }\n  const swatchHasTransparency = hasOpacity(pattern);\n  const swatchIsGradient = hasGradient(pattern);\n  const opaquePattern = swatchHasTransparency\n    ? getOpaquePattern(pattern)\n    : pattern;\n  // gradient swatches and indeterminates are never split\n  const displaySplit =\n    !swatchIsGradient && swatchHasTransparency && !isIndeterminate;\n  const SwatchDisplay = isPreview ? SwatchPreview : SwatchButton;\n  return (\n    <SwatchDisplay disabled={isDisabled} className={className} {...props}>\n      {swatchHasTransparency && <Transparent />}\n      <SwatchItem\n        style={generatePatternStyles(pattern)}\n        displaySplit={displaySplit}\n      >\n        {displaySplit && (\n          <OpaqueColorWrapper>\n            <OpaqueColor style={generatePatternStyles(opaquePattern)} />\n          </OpaqueColorWrapper>\n        )}\n        {children}\n      </SwatchItem>\n    </SwatchDisplay>\n  );\n}\n\nexport default Swatch;\n"
  },
  {
    "path": "packages/design-system/src/components/switch/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Switch } from './switch';\n"
  },
  {
    "path": "packages/design-system/src/components/switch/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { Switch } from '..';\nimport { Headline, Text } from '../../typography';\nimport { DarkThemeProvider } from '../../../storybookUtils';\n\nexport default {\n  title: 'DesignSystem/Components/Switch',\n  component: Switch,\n  args: {\n    offLabel: 'OFF',\n    onLabel: 'ON',\n  },\n  argTypes: {\n    onHandleChange: { action: 'handleChange' },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));\n  column-gap: 80px;\n\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n\n  > div {\n    display: grid;\n    row-gap: 20px;\n  }\n`;\n\nexport const _default = {\n  render: function Render({ onHandleChange, ...args }) {\n    const [switchState, setSwitchState] = useState({\n      radioOne: true,\n      radioTwo: false,\n      radioOneDisabled: true,\n      radioTwoDisabled: false,\n    });\n\n    const handleChange = (evt, value) => {\n      const name = evt?.target?.name;\n\n      onHandleChange(name);\n      setSwitchState((currentState) => ({\n        ...currentState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Switch'}</Headline>\n        <Container>\n          <div>\n            <Text.Paragraph>{'Normal'}</Text.Paragraph>\n            <Switch\n              name=\"radioOne\"\n              groupLabel=\"radio one\"\n              onChange={handleChange}\n              value={switchState.radioOne}\n              {...args}\n            />\n          </div>\n          <div>\n            <Text.Paragraph>{'Disabled Switch'}</Text.Paragraph>\n            <Switch\n              name=\"radioOneDisabled\"\n              groupLabel=\"radio one disabled\"\n              onChange={handleChange}\n              value={switchState.radioOneDisabled}\n              disabled\n              {...args}\n            />\n          </div>\n        </Container>\n        <DarkThemeProvider>\n          <Container>\n            <div>\n              <Text.Paragraph>{'Normal'}</Text.Paragraph>\n              <Switch\n                name=\"radioTwo\"\n                groupLabel=\"radio two\"\n                onChange={handleChange}\n                value={switchState.radioTwo}\n                {...args}\n              />\n            </div>\n            <div>\n              <Text.Paragraph>{'Disabled Switch'}</Text.Paragraph>\n              <Switch\n                name=\"radioTwoDisabled\"\n                groupLabel=\"radio two disabled\"\n                onChange={handleChange}\n                value={switchState.radioTwoDisabled}\n                disabled\n                {...args}\n              />\n            </div>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/switch/switch.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type {\n  ChangeEvent,\n  ForwardedRef,\n  ComponentPropsWithoutRef,\n} from 'react';\nimport styled, { css } from 'styled-components';\nimport { forwardRef, useCallback, useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../theme';\nimport { Text } from '../typography';\n\nconst SWITCH_HEIGHT = 32;\nenum Value {\n  On = 'ON',\n  Off = 'Off',\n}\n\nconst VisuallyHiddenRadioGroupLabel = styled.p`\n  ${themeHelpers.visuallyHidden};\n`;\n\nconst SlidingButton = styled.span<{ hasOffset?: boolean }>`\n  position: absolute;\n  display: block;\n  top: 0;\n  left: 0;\n  width: 50%;\n  height: ${SWITCH_HEIGHT}px;\n  border-radius: 100px;\n  transition: all 0.15s ease-out;\n  z-index: 0;\n\n  ${({ hasOffset }) => hasOffset && `left: 50%`}\n`;\n\nconst SwitchContainer = styled.div<{ disabled?: boolean; darkTheme?: boolean }>`\n  position: relative;\n  height: ${SWITCH_HEIGHT}px;\n  display: flex;\n  flex-direction: row;\n  justify-content: center;\n  align-items: center;\n  appearance: none;\n  background: ${({ theme, darkTheme }) =>\n    darkTheme ? theme.colors.divider.secondary : theme.colors.bg.tertiary};\n  border-radius: 100px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  cursor: pointer;\n\n  ${({ disabled, theme, darkTheme }) =>\n    disabled\n      ? css`\n          cursor: default;\n          background: ${theme.colors.divider.tertiary};\n\n          ${SlidingButton} {\n            background-color: ${theme.colors.interactiveBg.disable};\n          }\n        `\n      : css`\n          :hover ${SlidingButton} {\n            background-color: ${darkTheme\n              ? theme.colors.interactiveBg.primaryHover\n              : theme.colors.interactiveBg.brandNormal};\n          }\n        `};\n`;\n\nconst HiddenRadioButton = styled.input.attrs({ type: 'radio' })`\n  position: absolute;\n  height: 0;\n  width: 0;\n  padding: 0;\n  min-width: unset;\n  appearance: none;\n  border: 0;\n  box-shadow: none;\n  margin: -1px;\n  outline: none;\n  overflow: hidden;\n  opacity: 0;\n`;\n\nconst RadioButtonLabel = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})<{ $disabled?: boolean; isActive?: boolean; darkTheme?: boolean }>`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex: 1;\n  height: ${SWITCH_HEIGHT}px;\n  width: 50%;\n  padding: 0px 6px;\n  z-index: 1;\n  color: ${({ isActive, theme, darkTheme }) =>\n    isActive\n      ? darkTheme\n        ? theme.colors.inverted.fg.primary\n        : theme.colors.fg.primary\n      : theme.colors.fg.secondary};\n  background-color: ${({ isActive, theme, darkTheme }) =>\n    isActive &&\n    (darkTheme\n      ? theme.colors.interactiveBg.primaryNormal\n      : theme.colors.interactiveBg.brandNormal)};\n  border-radius: 100px;\n  cursor: pointer;\n  overflow: hidden;\n  text-align: center;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  transition: all 0.15s ease-out;\n\n  ${({ $disabled, theme }) =>\n    $disabled &&\n    css`\n      cursor: default;\n      color: ${theme.colors.fg.disable};\n    `}\n\n  /* add focus styling on the slider when the hidden input is focused */\n  :focus-within ~ span {\n    ${themeHelpers.focusCSS()};\n  }\n`;\n\ninterface SwitchProps extends Omit<\n  ComponentPropsWithoutRef<'input'>,\n  'value' | 'onChange' | 'type'\n> {\n  groupLabel?: string;\n  offLabel: string;\n  onLabel: string;\n  value?: boolean;\n  darkTheme?: boolean;\n  onChange: (evt: ChangeEvent, value: boolean) => void;\n}\n\n/**\n * A controlled radio group that looks like a switch.\n *\n * Keyboard navigation:\n * - [Tab] can be used to navigate between radio groups\n * - [Enter], [Space], [ArrowLeft], [ArrowRight] [ArrowUp], and [ArrowDown] can be used to select radio buttons\n */\nconst Switch = forwardRef(function Switch(\n  {\n    className,\n    disabled,\n    groupLabel,\n    id,\n    offLabel,\n    onChange,\n    onLabel,\n    value = false,\n    darkTheme = true,\n    ...props\n  }: SwitchProps,\n  ref: ForwardedRef<HTMLDivElement>\n) {\n  const ids = useMemo(\n    () => ({\n      group: id || uuidv4(),\n      offInput: uuidv4(),\n      onInput: uuidv4(),\n    }),\n    [id]\n  );\n\n  const handleChange = useCallback(\n    (evt: ChangeEvent<HTMLInputElement>) => {\n      onChange(evt, (evt.target.value as Value) === Value.On);\n    },\n    [onChange]\n  );\n\n  return (\n    <SwitchContainer\n      ref={ref}\n      className={className}\n      role=\"radiogroup\"\n      aria-labelledby={ids.group}\n      aria-disabled={disabled}\n      disabled={disabled}\n      darkTheme={darkTheme}\n    >\n      <VisuallyHiddenRadioGroupLabel id={ids.group}>\n        {groupLabel}\n      </VisuallyHiddenRadioGroupLabel>\n\n      <RadioButtonLabel\n        htmlFor={ids.onInput}\n        isActive={value}\n        disabled={disabled}\n        darkTheme={darkTheme}\n      >\n        {onLabel}\n        <HiddenRadioButton\n          checked={value}\n          disabled={disabled}\n          id={ids.onInput}\n          onChange={handleChange}\n          value={Value.On}\n          {...props}\n        />\n      </RadioButtonLabel>\n      <RadioButtonLabel\n        htmlFor={ids.offInput}\n        isActive={!value}\n        disabled={disabled}\n        darkTheme={darkTheme}\n      >\n        {offLabel}\n        <HiddenRadioButton\n          checked={!value}\n          disabled={disabled}\n          id={ids.offInput}\n          onChange={handleChange}\n          value={Value.Off}\n          {...props}\n        />\n      </RadioButtonLabel>\n      <SlidingButton hasOffset={!value} />\n    </SwitchContainer>\n  );\n});\n\nSwitch.displayName = 'Switch';\n\nexport default Switch;\n"
  },
  {
    "path": "packages/design-system/src/components/switch/test/switch.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Switch from '../switch';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport { noop } from '../../../utils';\n\ndescribe('Switch', () => {\n  it('should render the switch', () => {\n    renderWithProviders(\n      <Switch\n        name=\"radioOne\"\n        groupLabel=\"radio one\"\n        offLabel=\"OFF\"\n        onLabel=\"ON\"\n        onChange={noop}\n        value={false}\n      />\n    );\n\n    expect(screen.getAllByRole('radio')).toHaveLength(2);\n    expect(screen.getByText('ON')).toBeInTheDocument();\n    expect(screen.getByText('OFF')).toBeInTheDocument();\n  });\n\n  it.each`\n    value\n    ${true}\n    ${false}\n  `(\n    'should call onChange with the value of the unchecked radio button when the value is `$value`',\n    ({ value }) => {\n      const onChange = jest.fn();\n      renderWithProviders(\n        <Switch\n          name=\"radioOne\"\n          groupLabel=\"radio one\"\n          offLabel=\"OFF\"\n          onLabel=\"ON\"\n          onChange={onChange}\n          value={value}\n        />\n      );\n\n      const radioButton = screen.getByRole('radio', { checked: false });\n      fireEvent.click(radioButton);\n\n      expect(onChange).toHaveBeenCalledWith(expect.any(Object), !value);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/design-system/src/components/textArea/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as TextArea } from './textArea';\n"
  },
  {
    "path": "packages/design-system/src/components/textArea/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { TextArea } from '..';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Headline, Text } from '../../..';\n\nexport default {\n  title: 'DesignSystem/Components/TextArea',\n  component: TextArea,\n  args: {\n    label: 'label',\n    hint: 'Hint',\n    placeholder: 'placeholder',\n  },\n  argTypes: {\n    onHandleChange: { action: 'onChange' },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n  grid-column: 1 / -1;\n  grid-column-gap: 60px;\n\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nexport const _default = {\n  render: function Render({ onHandleChange, ...args }) {\n    const [inputState, setInputState] = useState({\n      oneLight: 'Light mode text',\n      twoLight: 'disabled',\n      threeLight: 'disabled',\n      fourLight: 'limited',\n      oneDark: 'Dark mode text',\n      twoDark: '',\n      threeDark: '',\n      fourDark: '',\n    });\n\n    const handleChange = (event) => {\n      const name = event.target.name;\n      const value = event.target.value;\n\n      onHandleChange(`${name} changed to: ${value}`);\n      setInputState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Textarea'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            <div>\n              <Text.Paragraph isBold>{'Normal'}</Text.Paragraph>\n              <TextArea\n                aria-label=\"input-one\"\n                id=\"one-light\"\n                name=\"oneLight\"\n                value={inputState.oneLight}\n                onChange={handleChange}\n                {...args}\n              />\n            </div>\n            <div>\n              <Text.Paragraph isBold>{'Error'}</Text.Paragraph>\n              <TextArea\n                aria-label=\"input-two\"\n                id=\"two-light\"\n                name=\"twoLight\"\n                value={inputState.twoLight}\n                onChange={handleChange}\n                {...args}\n                hasError\n              />\n            </div>\n            <div>\n              <Text.Paragraph isBold>{'Disabled'}</Text.Paragraph>\n              <TextArea\n                aria-label=\"disabled-input-one\"\n                id=\"three-light\"\n                name=\"threeLight\"\n                value={inputState.threeLight}\n                onChange={handleChange}\n                {...args}\n                disabled\n              />\n            </div>\n            <div>\n              <Text.Paragraph isBold>{'With Counter'}</Text.Paragraph>\n              <TextArea\n                aria-label=\"input-four\"\n                id=\"four-light\"\n                name=\"fourLight\"\n                value={inputState.fourLight}\n                onChange={handleChange}\n                {...args}\n                showCount\n                maxLength={20}\n              />\n            </div>\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container darkMode>\n            <Row>\n              <TextArea\n                aria-label=\"input-four\"\n                id=\"one-dark\"\n                name=\"oneDark\"\n                value={inputState.oneDark}\n                onChange={handleChange}\n                {...args}\n              />\n              <TextArea\n                aria-label=\"input-five\"\n                id=\"two-dark\"\n                name=\"twoDark\"\n                value={inputState.twoDark}\n                onChange={handleChange}\n                {...args}\n                hasError\n              />\n              <TextArea\n                aria-label=\"disabled-input-two\"\n                id=\"three-dark\"\n                name=\"threeDark\"\n                value={inputState.threeDark}\n                onChange={handleChange}\n                {...args}\n                disabled\n              />\n              <TextArea\n                aria-label=\"input-four\"\n                id=\"four-dark\"\n                name=\"fourDark\"\n                value={inputState.fourDark}\n                onChange={handleChange}\n                {...args}\n                showCount\n                maxLength={200}\n              />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/textArea/test/textArea.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport TextArea from '../textArea';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('TextArea', () => {\n  const defaultProps = {\n    value: '',\n    onChange: () => {},\n  };\n\n  it('should render the textarea', () => {\n    renderWithProviders(\n      <TextArea\n        {...defaultProps}\n        aria-label=\"test\"\n        placeholder=\"my placeholder\"\n      />\n    );\n\n    expect(screen.getByPlaceholderText('my placeholder')).toBeInTheDocument();\n  });\n\n  it('should render a label', () => {\n    renderWithProviders(\n      <TextArea {...defaultProps} label=\"This is my input label\" />\n    );\n\n    expect(screen.getByText('This is my input label')).toBeInTheDocument();\n  });\n\n  it('should render a hint', () => {\n    renderWithProviders(\n      <TextArea\n        {...defaultProps}\n        aria-label=\"test\"\n        hint=\"This is my input hint\"\n      />\n    );\n\n    expect(screen.getByText('This is my input hint')).toBeInTheDocument();\n  });\n\n  it('should render the counter', () => {\n    renderWithProviders(\n      <TextArea\n        {...defaultProps}\n        aria-label=\"test\"\n        showCount\n        maxLength={10}\n        value=\"foo\"\n      />\n    );\n\n    expect(screen.getByText('3/10')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/textArea/textArea.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ForwardedRef, ComponentPropsWithoutRef } from 'react';\nimport { forwardRef, useMemo, useState } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../theme';\nimport { focusCSS } from '../../theme/helpers';\nimport { Text } from '../typography';\n\nconst Container = styled.div`\n  position: relative;\n  width: 100%;\n  min-width: 100px;\n`;\n\nconst CounterText = styled(Text.Span).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst Label = styled(Text.Label)`\n  margin-bottom: 12px;\n`;\n\nconst Hint = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})<{ hasError?: boolean }>`\n  margin-top: 12px;\n  color: ${({ hasError, theme }) =>\n    theme.colors.fg[hasError ? 'negative' : 'tertiary']};\n`;\n\nconst InputContainer = styled.div<{\n  focused?: boolean;\n  hasError?: boolean;\n  styleOverride?: string;\n}>(\n  ({ focused, hasError, theme, styleOverride }) => css`\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: 8px 12px;\n    border: 1px solid\n      ${theme.colors.border[hasError ? 'negativeNormal' : 'defaultNormal']};\n    border-radius: ${theme.borders.radius.small};\n    overflow: hidden;\n\n    ${focused &&\n    !hasError &&\n    css`\n      border-color: ${theme.colors.border.defaultActive};\n    `};\n\n    :focus-within {\n      ${focusCSS(theme.colors.border.focus)};\n    }\n\n    ${styleOverride};\n  `\n);\n\nconst StyledTextArea = styled.textarea(\n  ({ theme }) => css`\n    height: 100%;\n    width: 100%;\n    padding: 0;\n    background-color: inherit;\n    border: none;\n    outline: none;\n    color: ${theme.colors.fg.primary};\n    resize: none;\n    box-shadow: none;\n    ${themeHelpers.scrollbarCSS};\n\n    ${themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.paragraph[TextSize.Small],\n      theme,\n    })};\n\n    :focus {\n      box-shadow: none;\n    }\n\n    :disabled {\n      color: ${theme.colors.fg.disable};\n      border-color: ${theme.colors.border.disable};\n    }\n\n    :active {\n      color: ${theme.colors.fg.primary};\n    }\n\n    ::placeholder {\n      color: ${theme.colors.fg.tertiary};\n    }\n  `\n);\n\nconst Counter = styled.div`\n  text-align: right;\n  align-self: flex-end;\n  span {\n    color: ${({ theme }) => theme.colors.fg.tertiary};\n  }\n`;\n\ninterface TextAreaProps extends Omit<\n  ComponentPropsWithoutRef<'textarea'>,\n  'value'\n> {\n  hasError?: boolean;\n  hint?: string;\n  label?: string;\n  showCount?: boolean;\n  maxLength?: number;\n  isIndeterminate?: boolean;\n  containerStyleOverride?: string;\n  value?: string;\n}\n\nconst TextArea = forwardRef(\n  (\n    {\n      className,\n      disabled,\n      hasError,\n      hint,\n      id,\n      label,\n      onBlur,\n      onFocus,\n      value,\n      showCount = false,\n      maxLength,\n      isIndeterminate = false,\n      containerStyleOverride = '',\n      ...props\n    }: TextAreaProps,\n    ref: ForwardedRef<HTMLTextAreaElement>\n  ) => {\n    const textAreaId = useMemo(() => id || uuidv4(), [id]);\n\n    const hasCounter =\n      showCount && typeof maxLength === 'number' && maxLength > 0;\n\n    const [isFocused, setIsFocused] = useState(false);\n    const [hasBeenSelected, setHasBeenSelected] = useState(false);\n\n    let displayedValue = value;\n    if (isIndeterminate) {\n      // Display placeholder if value couldn't be determined.\n      displayedValue = '';\n    }\n\n    return (\n      <Container className={className}>\n        {label && (\n          <Label htmlFor={textAreaId} disabled={disabled}>\n            {label}\n          </Label>\n        )}\n        <InputContainer\n          focused={isFocused}\n          hasError={hasError}\n          styleOverride={containerStyleOverride}\n        >\n          <StyledTextArea\n            id={textAreaId}\n            disabled={disabled}\n            ref={(input) => {\n              // `ref` can either be a callback ref or a normal ref.\n              if (typeof ref === 'function') {\n                ref(input);\n              } else if (ref) {\n                ref.current = input;\n              }\n              if (input && isFocused && !hasBeenSelected) {\n                input.select();\n                setHasBeenSelected(true);\n              }\n            }}\n            onFocus={(e) => {\n              onFocus?.(e);\n              setIsFocused(true);\n              setHasBeenSelected(false);\n            }}\n            onBlur={(e) => {\n              onBlur?.(e);\n              setIsFocused(false);\n            }}\n            value={displayedValue}\n            maxLength={maxLength}\n            {...props}\n          />\n          {hasCounter && (\n            <Counter>\n              <CounterText>{`${\n                String(value).length\n              }/${maxLength}`}</CounterText>\n            </Counter>\n          )}\n        </InputContainer>\n        {hint && <Hint hasError={hasError}>{hint}</Hint>}\n      </Container>\n    );\n  }\n);\n\nTextArea.displayName = 'TextArea';\n\nexport default TextArea;\n"
  },
  {
    "path": "packages/design-system/src/components/toggle/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Toggle } from './toggle';\n"
  },
  {
    "path": "packages/design-system/src/components/toggle/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Toggle from '../toggle';\nimport { Text } from '../..';\nimport { DarkThemeProvider } from '../../../storybookUtils';\nimport { Headline } from '../../..';\n\nexport default {\n  title: 'DesignSystem/Components/Toggle',\n  component: Toggle,\n  args: {\n    label: 'label',\n  },\n  argTypes: {\n    onChange: { action: 'onChange' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['className', 'checked', 'disabled'],\n    },\n  },\n};\n\nconst Container = styled.div`\n  display: grid;\n  row-gap: 20px;\n  padding: 20px 40px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n  max-width: 400px;\n`;\n\nconst Row = styled.div`\n  display: grid;\n  grid-template-columns: repeat(4, 1fr);\n  grid-column: 1 / -1;\n  label {\n    display: flex;\n    align-items: center;\n  }\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const [inputState, setInputState] = useState({\n      oneLight: false,\n      twoLight: true,\n      threeLight: false,\n      fourLight: true,\n      oneDark: false,\n      twoDark: true,\n      threeDark: false,\n      fourDark: true,\n    });\n\n    const handleChange = (event) => {\n      const name = event.target.name;\n      const value = event.target.checked;\n\n      args.onChange(`${name} is: ${value}`);\n      setInputState((prevState) => ({\n        ...prevState,\n        [name]: value,\n      }));\n    };\n\n    return (\n      <>\n        <Headline as=\"h1\">{'Toggle'}</Headline>\n        <br />\n        <Container>\n          <Row>\n            <Text.Paragraph>{'Normal'}</Text.Paragraph>\n            <Text.Paragraph>{'Normal'}</Text.Paragraph>\n            <Text.Paragraph>{'Disabled'}</Text.Paragraph>\n            <Text.Paragraph>{'Disabled'}</Text.Paragraph>\n          </Row>\n          <Row>\n            <Toggle\n              id=\"one-light\"\n              aria-label=\"toggle-one-light\"\n              name=\"oneLight\"\n              checked={inputState.oneLight}\n              onChange={handleChange}\n            />\n            <Toggle\n              id=\"two-light\"\n              aria-label=\"toggle-two-light\"\n              name=\"twoLight\"\n              checked={inputState.twoLight}\n              onChange={handleChange}\n            />\n            <Toggle\n              id=\"three-light\"\n              aria-label=\"toggle-three-light\"\n              name=\"threeLight\"\n              checked={inputState.threeLight}\n              onChange={handleChange}\n              disabled\n            />\n            <Toggle\n              id=\"four-light\"\n              aria-label=\"toggle-four-light\"\n              name=\"fourLight\"\n              checked={inputState.fourLight}\n              onChange={handleChange}\n              disabled\n            />\n          </Row>\n        </Container>\n        <DarkThemeProvider>\n          <Container darkMode>\n            <Row>\n              <Text.Paragraph>{'Normal'}</Text.Paragraph>\n              <Text.Paragraph>{'Normal'}</Text.Paragraph>\n              <Text.Paragraph>{'Disabled'}</Text.Paragraph>\n              <Text.Paragraph>{'Disabled'}</Text.Paragraph>\n            </Row>\n            <Row>\n              <Toggle\n                id=\"one-dark\"\n                aria-label=\"toggle-one-dark\"\n                name=\"oneDark\"\n                checked={inputState.oneDark}\n                onChange={handleChange}\n              />\n              <Toggle\n                id=\"two-dark\"\n                aria-label=\"toggle-two-dark\"\n                name=\"twoDark\"\n                checked={inputState.twoDark}\n                onChange={handleChange}\n              />\n              <Toggle\n                id=\"three-dark\"\n                aria-label=\"toggle-three-dark\"\n                name=\"threeDark\"\n                checked={inputState.threeDark}\n                onChange={handleChange}\n                disabled\n              />\n              <Toggle\n                id=\"four-dark\"\n                aria-label=\"toggle-four-dark\"\n                name=\"fourDark\"\n                checked={inputState.fourDark}\n                onChange={handleChange}\n                disabled\n              />\n            </Row>\n          </Container>\n        </DarkThemeProvider>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/toggle/test/toggle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Toggle from '../toggle';\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\n\ndescribe('Toggle', () => {\n  it('should render the toggle', () => {\n    renderWithProviders(<Toggle data-testid=\"toggle\" />);\n\n    expect(screen.getByTestId('toggle')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/toggle/toggle.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ComponentPropsWithoutRef } from 'react';\nimport styled, { css } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { CheckmarkSmall } from '../../icons';\n\nconst BORDER_WIDTH = 1;\nconst TOGGLE_TRACK_HEIGHT = 20;\nconst TOGGLE_WIDTH = 44;\nconst CIRCLE_DIAMETER = 28;\nconst WRAPPER_PADDING = (CIRCLE_DIAMETER - TOGGLE_TRACK_HEIGHT) / 2;\nconst CIRCLE_INITIAL_POSITION =\n  (TOGGLE_TRACK_HEIGHT - CIRCLE_DIAMETER) / 2 - BORDER_WIDTH;\nconst CIRCLE_FINAL_POSITION =\n  TOGGLE_WIDTH - CIRCLE_INITIAL_POSITION - CIRCLE_DIAMETER;\n\nconst ICON_CONTAINER_WIDTH = 32;\nconst ICON_TOP_POSITION = -6;\nconst ICON_LEFT_POSITION = 19;\n\nconst Wrapper = styled.div`\n  /* Account for circle leaking out of ToggleContainer */\n  padding: ${WRAPPER_PADDING}px;\n`;\n\nconst Background = styled.div(\n  ({ theme }) => css`\n    position: absolute;\n    top: -${BORDER_WIDTH}px;\n    left: -${BORDER_WIDTH}px;\n    height: ${TOGGLE_TRACK_HEIGHT}px;\n    width: ${TOGGLE_WIDTH}px;\n    background-color: transparent;\n    border-radius: ${theme.borders.radius.x_large};\n    border: ${BORDER_WIDTH}px solid ${theme.colors.border.defaultNormal};\n    pointer-events: none;\n    transition: all 0.3s;\n  `\n);\n\nconst Circle = styled.span(\n  ({ theme }) => css`\n    pointer-events: none;\n\n    :after {\n      content: '';\n      position: absolute;\n      top: ${CIRCLE_INITIAL_POSITION}px;\n      left: ${CIRCLE_INITIAL_POSITION}px;\n      height: ${CIRCLE_DIAMETER}px;\n      width: ${CIRCLE_DIAMETER}px;\n      background-color: ${theme.colors.fg.secondary};\n      border-radius: ${theme.borders.radius.round};\n      cursor: pointer;\n      transition:\n        background-color 0.3s,\n        border-color 0.3s,\n        left 0.15s;\n    }\n  `\n);\n\nconst IconContainer = styled.div(\n  ({ theme }) => css`\n    position: absolute;\n    width: ${ICON_CONTAINER_WIDTH}px;\n    top: ${ICON_TOP_POSITION}px;\n    left: ${ICON_LEFT_POSITION}px;\n    z-index: 1;\n    opacity: 0;\n    transition: opacity 0.15s;\n    pointer-events: none;\n\n    svg {\n      color: ${theme.colors.standard.white};\n    }\n  `\n);\n\nconst ToggleContainer = styled.div(\n  ({ theme }) => css`\n    position: relative;\n    height: ${TOGGLE_TRACK_HEIGHT}px;\n    width: ${TOGGLE_WIDTH}px;\n    background-color: transparent;\n    border-radius: ${theme.borders.radius.x_large};\n\n    input[type='checkbox'] {\n      position: absolute;\n      top: -${BORDER_WIDTH / 2}px;\n      left: -${BORDER_WIDTH / 2}px;\n      height: ${TOGGLE_TRACK_HEIGHT}px;\n      width: ${TOGGLE_WIDTH}px;\n      margin: 0;\n      opacity: 0;\n      cursor: pointer;\n\n      :disabled {\n        cursor: default;\n\n        ~ ${Background} {\n          border-color: ${theme.colors.fg.disable};\n        }\n\n        :checked ~ ${Background} {\n          background-color: ${theme.colors.fg.disable};\n          border-color: ${theme.colors.fg.disable};\n        }\n\n        ~ ${Circle}:after {\n          background-color: ${theme.colors.fg.disable};\n        }\n\n        :checked ~ ${Circle}:after {\n          background-color: ${theme.colors.bg.secondary};\n        }\n\n        ~ ${IconContainer} svg {\n          color: ${theme.colors.fg.disable};\n        }\n      }\n\n      &:focus-visible {\n        ~ ${Background} {\n          outline: none;\n          box-shadow:\n            0 0 0 5px ${theme.colors.bg.primary},\n            0 0 0 7px ${theme.colors.border.focus};\n        }\n      }\n\n      :checked {\n        ~ ${Background} {\n          background-color: ${theme.colors.interactiveBg.positivePress};\n          border-color: ${theme.colors.interactiveBg.positivePress};\n        }\n\n        ~ ${Circle}:after {\n          left: ${CIRCLE_FINAL_POSITION}px;\n          background-color: ${theme.colors.interactiveBg.positiveNormal};\n        }\n\n        ~ ${IconContainer} {\n          opacity: 1;\n        }\n      }\n\n      :hover {\n        :not(:disabled) ~ ${Background} {\n          border-color: ${theme.colors.fg.secondary};\n        }\n\n        :checked:not(:disabled) ~ ${Background} {\n          background-color: ${theme.colors.interactiveBg.positiveHover};\n          border-color: ${theme.colors.interactiveBg.positiveHover};\n        }\n      }\n\n      :active {\n        ~ ${Background} {\n          box-shadow: 0 0 0 8px ${theme.colors.shadow.active};\n        }\n      }\n    }\n  `\n);\n\ntype ToggleProps = ComponentPropsWithoutRef<'input'>;\n\nfunction Toggle({ className, ...inputProps }: ToggleProps) {\n  return (\n    <Wrapper className={className}>\n      <ToggleContainer>\n        <input type=\"checkbox\" {...inputProps} />\n        <Background />\n        <IconContainer>\n          <CheckmarkSmall />\n        </IconContainer>\n        <Circle />\n      </ToggleContainer>\n    </Wrapper>\n  );\n}\n\nexport default Toggle;\n"
  },
  {
    "path": "packages/design-system/src/components/tooltip/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Tooltip } from './tooltip';\n"
  },
  {
    "path": "packages/design-system/src/components/tooltip/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { ThemeProvider } from 'styled-components';\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { theme } from '../../../theme';\nimport { Table } from '../../../icons';\nimport { Button, ButtonSize, ButtonType, ButtonVariant } from '../../button';\nimport { Placement } from '../../popup';\nimport { Tooltip } from '..';\nimport { Text } from '../../typography';\n\nexport default {\n  title: 'DesignSystem/Components/Tooltip',\n  args: {\n    hasTail: true,\n    placement: Placement.Bottom,\n    colorShortcut: 'mod+z',\n    colorTitle: 'Page background colors cannot have opacity',\n    iconShortcut: 'Shortcut for icon',\n    iconTitle: 'To save draft click enter',\n    buttonShortcut: 'Shortcut for button',\n    buttonTitle: 'Tooltip message over a button',\n  },\n  argTypes: {\n    placement: {\n      options: Object.values(Placement),\n      control: 'select',\n    },\n    colorShortcut: {\n      name: 'Shortcut for color',\n    },\n    colorTitle: {\n      name: 'Title for color',\n    },\n    iconShortcut: {\n      name: 'Shortcut for icon',\n    },\n    iconTitle: {\n      name: 'Title for icon',\n    },\n    buttonShortcut: {\n      name: 'Shortcut for button',\n    },\n    buttonTitle: {\n      name: 'Title for button',\n    },\n  },\n};\n\nconst Container = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 600px;\n  height: 400px;\n  background-color: ${(props) => props.theme.colors.bg.primary};\n  padding: 30px;\n\n  p {\n    margin: 10px;\n  }\n`;\n\nconst Color = styled.div`\n  width: 20px;\n  height: 20px;\n  border-radius: 50%;\n  background-color: red;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <ThemeProvider theme={theme}>\n        <Container>\n          <Tooltip\n            hasTail={args.hasTail}\n            placement={args.placement}\n            shortcut={args.colorShortcut}\n            title={args.colorTitle}\n          >\n            <Color />\n          </Tooltip>\n\n          <Tooltip\n            hasTail={args.hasTail}\n            placement={args.placement}\n            shortcut={args.iconShortcut}\n            title={args.iconTitle}\n          >\n            <Button type={ButtonType.Primary} variant={ButtonVariant.Icon}>\n              <Table aria-hidden />\n            </Button>\n          </Tooltip>\n\n          <Tooltip\n            hasTail={args.hasTail}\n            placement={args.placement}\n            shortcut={args.buttonShortcut}\n            title={args.buttonTitle}\n          >\n            <Button type={ButtonType.Primary} size={ButtonSize.Small}>\n              {'I am just a normal button'}\n            </Button>\n          </Tooltip>\n        </Container>\n      </ThemeProvider>\n    );\n  },\n};\n\nexport const LightMode = {\n  render: function Render(args) {\n    return (\n      <Container>\n        <Tooltip\n          hasTail={args.hasTail}\n          placement={args.placement}\n          shortcut={args.colorShortcut}\n          title={args.colorTitle}\n        >\n          <Color />\n        </Tooltip>\n\n        <Tooltip\n          hasTail={args.hasTail}\n          placement={args.placement}\n          shortcut={args.iconShortcut}\n          title={args.iconTitle}\n        >\n          <Button type={ButtonType.Primary} variant={ButtonVariant.Icon}>\n            <Table aria-hidden />\n          </Button>\n        </Tooltip>\n\n        <Tooltip\n          hasTail={args.hasTail}\n          placement={args.placement}\n          shortcut={args.buttonShortcut}\n          title={args.buttonTitle}\n        >\n          <Button type={ButtonType.Primary} size={ButtonSize.Small}>\n            {'I am just a normal button'}\n          </Button>\n        </Tooltip>\n      </Container>\n    );\n  },\n};\n\nconst tooltipTitles = [\n  'initial tooltip title',\n  'secondary tooltip title but quite a bit longer',\n];\n\nexport const TooltipWithChangingTextOnClick = {\n  render: function Render(args) {\n    const [currentTooltipIndex, setCurrentTooltipIndex] = useState(0);\n\n    const handleTooltipTextChange = useCallback(() => {\n      setCurrentTooltipIndex((existingIndex) => (existingIndex === 1 ? 0 : 1));\n    }, []);\n\n    return (\n      <Container>\n        <Text>{'Click button to change tooltip title.'}</Text>\n        <Tooltip\n          hasTail={args.hasTail}\n          placement={args.placement}\n          shortcut={args.iconShortcut}\n          title={tooltipTitles[currentTooltipIndex]}\n        >\n          <Button\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            onClick={handleTooltipTextChange}\n          >\n            {'Switch view'}\n          </Button>\n        </Tooltip>\n      </Container>\n    );\n  },\n\n  parameters: {\n    controls: {\n      include: ['hasTail', 'placement', 'Shortcut for icon'],\n    },\n  },\n};\n\nexport const TooltipWithChangingTextOnInterval = {\n  render: function Render(args) {\n    const [currentTooltipIndex, setCurrentTooltipIndex] = useState(0);\n    const [isTooltipIntervalActive, setIsTooltipIntervalActive] =\n      useState(false);\n\n    useEffect(() => {\n      let interval;\n      if (isTooltipIntervalActive) {\n        interval = setInterval(\n          () =>\n            setCurrentTooltipIndex((existingIndex) =>\n              existingIndex === 1 ? 0 : 1\n            ),\n          1000\n        );\n      }\n\n      return () => interval && clearInterval(interval);\n    }, [isTooltipIntervalActive]);\n\n    const handleToggleButtonFocus = useCallback(\n      () =>\n        setIsTooltipIntervalActive((currentActiveState) => !currentActiveState),\n      []\n    );\n\n    return (\n      <Container>\n        <Text>\n          {\n            'Place focus on button to begin updating tooltip text with interval behind the scenes, remove focus to stop.'\n          }\n        </Text>\n        <Tooltip\n          hasTail={args.hasTail}\n          placement={args.placement}\n          shortcut={args.iconShortcut}\n          title={tooltipTitles[currentTooltipIndex]}\n        >\n          <Button\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            onFocus={handleToggleButtonFocus}\n            onBlur={handleToggleButtonFocus}\n          >\n            {'Switch view'}\n          </Button>\n        </Tooltip>\n      </Container>\n    );\n  },\n\n  parameters: {\n    controls: {\n      include: ['hasTail', 'placement', 'Shortcut for icon'],\n    },\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/tooltip/tail.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Placement } from '../popup';\n\nexport const SVG_TOOLTIP_TAIL_ID = 'tooltip-tail';\nconst TAIL_WIDTH = 34;\nexport const TAIL_HEIGHT = 8;\n\ninterface TailPositionProps {\n  placement: Placement;\n  translateX: number;\n  isRTL: boolean;\n}\n\nconst getTailPosition = ({\n  placement,\n  translateX,\n  isRTL,\n}: TailPositionProps) => {\n  switch (placement) {\n    case Placement.Top:\n    case Placement.TopStart:\n    case Placement.TopEnd:\n      return css`\n        bottom: -${TAIL_HEIGHT - 1}px;\n        /*! @noflip */\n        transform: translateX(${translateX}px) rotate(180deg);\n      `;\n    case Placement.Bottom:\n    case Placement.BottomStart:\n    case Placement.BottomEnd:\n      return css`\n        top: -${TAIL_HEIGHT - 1}px;\n        /*! @noflip */\n        transform: translateX(${translateX}px);\n      `;\n    case Placement.Left:\n    case Placement.LeftStart:\n    case Placement.LeftEnd:\n      return css`\n        right: -${TAIL_WIDTH / 2 + TAIL_HEIGHT / 2 - 1}px;\n        transform: rotate(${isRTL ? '-90deg' : '90deg'});\n      `;\n    case Placement.Right:\n    case Placement.RightStart:\n    case Placement.RightEnd:\n      return css`\n        left: -${TAIL_WIDTH / 2 + TAIL_HEIGHT / 2 - 1}px;\n        transform: rotate(${isRTL ? '90deg' : '-90deg'});\n      `;\n    default:\n      return ``;\n  }\n};\n\nexport const SvgForTail = styled.svg`\n  position: absolute;\n  width: 0;\n  height: 0;\n`;\n\nexport const Tail = styled.span<TailPositionProps>`\n  @supports (clip-path: url('#${SVG_TOOLTIP_TAIL_ID}')) {\n    position: absolute;\n    display: block;\n    height: ${TAIL_HEIGHT}px;\n    width: ${TAIL_WIDTH}px;\n    ${({ placement, translateX, isRTL }) =>\n      getTailPosition({ placement, translateX, isRTL })};\n    background-color: inherit;\n    border: none;\n    border-bottom: none;\n    clip-path: url('#${SVG_TOOLTIP_TAIL_ID}');\n  }\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/tooltip/test/tooltip.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderWithProviders } from '../../../testUtils/renderWithProviders';\nimport Tooltip from '../tooltip';\n\ndescribe('<Tooltip />', () => {\n  it('should be not visible when the mouse is not hovering over the container', () => {\n    renderWithProviders(\n      <Tooltip title={'Some tooltip text'}>\n        <button>{'hover to see tooltip'}</button>\n      </Tooltip>\n    );\n\n    expect(screen.queryByText('Some tooltip text')).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/components/tooltip/tooltip.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useState,\n  useRef,\n  useMemo,\n  useCallback,\n  useDebouncedCallback,\n  useEffect,\n  useLayoutEffect,\n  useResizeEffect,\n  createPortal,\n} from '@googleforcreators/react';\nimport type {\n  ComponentPropsWithoutRef,\n  PropsWithChildren,\n  RefObject,\n} from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { StyleOverride } from '../../types/theme';\nimport { TextSize } from '../../theme';\nimport { noop } from '../../utils';\nimport { usePopup } from '../../contexts';\nimport { Placement } from '../popup';\nimport type { Offset } from '../popup/types';\nimport { prettifyShortcut } from '../keyboard';\nimport { Text } from '../typography';\nimport { PopupContainer } from '../popup/constants';\nimport { getOffset, getTransforms } from '../popup/utils';\nimport { SvgForTail, Tail, SVG_TOOLTIP_TAIL_ID, TAIL_HEIGHT } from './tail';\n\nconst SPACE_BETWEEN_TOOLTIP_AND_ELEMENT = TAIL_HEIGHT;\n// For how many milliseconds is a delayed tooltip waiting to appear?\nconst DELAY_MS = 1000;\n// For how many milliseconds will triggering another delayed tooltip show instantly?\nconst REPEAT_DELAYED_MS = 500;\n// To account for the wp-admin sidenav\nconst DEFAULT_LEFT_OFFSET = 0;\n\nconst DEFAULT_POPUP_Z_INDEX = 2;\n\nconst Wrapper = styled.div`\n  position: relative;\n`;\n\nconst TooltipContainer = styled.div<{\n  shown?: boolean;\n  zIndex: number;\n  styleOverride?: StyleOverride;\n}>`\n  margin: 0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  text-align: center;\n  flex-direction: row;\n  max-width: 14em;\n  transition: 0.4s opacity;\n  opacity: ${({ shown }) => (shown ? 1 : 0)};\n  pointer-events: ${({ shown }) => (shown ? 'all' : 'none')};\n  z-index: ${({ zIndex }) => zIndex};\n  border-radius: 4px;\n  background-color: ${({ theme }) => theme.colors.inverted.bg.primary};\n\n  filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));\n\n  ${({ styleOverride }) => styleOverride}\n`;\n\nconst TooltipText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.inverted.fg.primary};\n  padding: 10px;\n`;\n\nconst getBoundingBoxCenter = ({ x, width }: DOMRect) => x + width / 2;\n\nlet lastVisibleDelayedTooltip = 0;\n\ninterface TooltipProps extends ComponentPropsWithoutRef<'div'> {\n  title: string;\n  shortcut?: string;\n  hasTail?: boolean;\n  placement?: Placement;\n  isDelayed?: boolean;\n  forceAnchorRef?: RefObject<HTMLElement>;\n  popupZIndexOverride?: number;\n  styleOverride?: StyleOverride;\n}\n\nfunction Tooltip({\n  title,\n  shortcut = '',\n  hasTail = false,\n  placement = Placement.Bottom,\n  children,\n  onFocus = noop,\n  onBlur = noop,\n  isDelayed = false,\n  forceAnchorRef, // needed for WithLink so that the url tooltip hovers over the element, and isn't anchored\n  // to the whole canvas\n  className,\n  popupZIndexOverride,\n  styleOverride,\n  ...props\n}: PropsWithChildren<TooltipProps>) {\n  const { leftOffset = DEFAULT_LEFT_OFFSET, isRTL } = usePopup();\n  const [shown, setShown] = useState(false);\n  const [arrowDelta, setArrowDelta] = useState(0);\n  const anchorRef = useRef<HTMLDivElement>(null);\n  const tooltipRef = useRef<HTMLDivElement>(null);\n  const placementRef = useRef(placement);\n  const [dynamicPlacement, setDynamicPlacement] = useState(placement);\n  const isMountedRef = useRef(false);\n\n  const [popupState, setPopupState] = useState<{ offset?: Offset }>({});\n  const isPopupMountedRef = useRef(false);\n  const popupRef = useRef<HTMLDivElement>(null);\n  const isOpen = Boolean(shown && (shortcut || title));\n\n  const [dynamicOffset, setDynamicOffset] = useState<{ x?: number }>({});\n\n  const spacing = useMemo(\n    () => ({\n      x:\n        placement.startsWith('left') || placement.startsWith('right')\n          ? SPACE_BETWEEN_TOOLTIP_AND_ELEMENT\n          : 0,\n      y:\n        placement.startsWith('top') || placement.startsWith('bottom')\n          ? SPACE_BETWEEN_TOOLTIP_AND_ELEMENT\n          : 0,\n    }),\n    [placement]\n  );\n\n  const getAnchor = useCallback(\n    () => forceAnchorRef || anchorRef,\n    [forceAnchorRef]\n  );\n\n  const positionPopup = useCallback(() => {\n    if (!isPopupMountedRef.current || !anchorRef?.current) {\n      return;\n    }\n    setPopupState({\n      offset: anchorRef.current\n        ? getOffset({\n            placement: dynamicPlacement,\n            spacing,\n            anchor: getAnchor(),\n            popup: popupRef,\n            isRTL,\n            ignoreMaxOffsetY: true,\n          })\n        : undefined,\n    });\n  }, [dynamicPlacement, spacing, getAnchor, isRTL]);\n\n  // When near the edge of the viewport we want to force the tooltip to a new placement as to not\n  // cutoff the contents of the tooltip.\n  const positionPlacement = useCallback(\n    ({ offset }: { offset?: Offset }, { left, right, height }: DOMRect) => {\n      if (!offset) {\n        return;\n      }\n      //  In order to check if there's an overlap with the window's bottom edge we need the overall height of the tooltip\n      //  from the anchor's y position along with the amount of space between the anchor and the tooltip content.\n      const neededVerticalSpace =\n        offset.y + height + SPACE_BETWEEN_TOOLTIP_AND_ELEMENT;\n      const shouldMoveToTop =\n        dynamicPlacement.startsWith('bottom') &&\n        neededVerticalSpace >= window.innerHeight;\n      // We can sometimes render a tooltip too far to the left, i.e. in RTL mode, or with the wp-admin sidenav.\n      // When that is the case, let's update the offset.\n      const isOverFlowingLeft = Math.trunc(left) < (isRTL ? 0 : leftOffset);\n      // The getOffset util has a maxOffset that prevents the tooltip from being render too far to the right. However, when\n      // in RTL we can sometimes run into the wp-admin sidenav.\n      const isOverFlowingRight =\n        isRTL && Math.trunc(right) > offset.bodyRight - leftOffset;\n\n      if (shouldMoveToTop) {\n        if (dynamicPlacement.endsWith('-start')) {\n          setDynamicPlacement(Placement.TopStart);\n        } else if (dynamicPlacement.endsWith('-end')) {\n          setDynamicPlacement(Placement.TopEnd);\n        } else {\n          setDynamicPlacement(Placement.Top);\n        }\n      } else if (isOverFlowingLeft) {\n        setDynamicOffset({\n          x: (isRTL ? 0 : leftOffset) - left,\n        });\n      } else if (isOverFlowingRight) {\n        setDynamicOffset({\n          x: offset.bodyRight - right - leftOffset,\n        });\n      }\n    },\n    [dynamicPlacement, isRTL, leftOffset]\n  );\n\n  const positionArrow = useCallback(() => {\n    const anchor = getAnchor();\n    const anchorElBoundingBox = anchor.current?.getBoundingClientRect();\n    const tooltipElBoundingBox = tooltipRef.current?.getBoundingClientRect();\n    if (!tooltipElBoundingBox || !anchorElBoundingBox) {\n      return;\n    }\n    positionPlacement(popupState, tooltipElBoundingBox);\n\n    const delta =\n      getBoundingBoxCenter(anchorElBoundingBox) -\n      getBoundingBoxCenter(tooltipElBoundingBox);\n\n    setArrowDelta(delta);\n  }, [positionPlacement, popupState, getAnchor]);\n\n  const resetPlacement = useDebouncedCallback(() => {\n    setDynamicPlacement(placementRef.current);\n  }, 100);\n  const delayRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const onHover = useCallback(() => {\n    const handle = () => {\n      if (!isMountedRef.current) {\n        return;\n      }\n\n      setShown(true);\n    };\n\n    if (isDelayed) {\n      const now = performance.now();\n      if (now - lastVisibleDelayedTooltip < REPEAT_DELAYED_MS) {\n        // Show instantly\n        handle();\n      }\n      if (delayRef.current) {\n        clearTimeout(delayRef.current);\n      }\n      // Invoke in DELAY_MS\n      delayRef.current = setTimeout(handle, DELAY_MS);\n    } else {\n      handle();\n    }\n  }, [isDelayed]);\n  const onHoverOut = useCallback(() => {\n    setShown(false);\n    resetPlacement();\n    if (isDelayed && delayRef.current) {\n      clearTimeout(delayRef.current);\n      if (shown) {\n        lastVisibleDelayedTooltip = performance.now();\n      }\n    }\n  }, [resetPlacement, isDelayed, shown]);\n\n  useEffect(() => {\n    isMountedRef.current = true;\n\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  useEffect(() => {\n    isPopupMountedRef.current = true;\n\n    return () => {\n      isPopupMountedRef.current = false;\n    };\n  }, []);\n\n  useLayoutEffect(() => {\n    if (!isOpen) {\n      return undefined;\n    }\n    isPopupMountedRef.current = true;\n\n    positionPopup();\n    // Adjust the position when scrolling.\n    document.addEventListener('scroll', positionPopup, true);\n    return () => {\n      document.removeEventListener('scroll', positionPopup, true);\n      isPopupMountedRef.current = false;\n    };\n  }, [isOpen, positionPopup]);\n\n  useLayoutEffect(() => {\n    if (!isPopupMountedRef.current) {\n      return;\n    }\n\n    positionArrow();\n  }, [positionArrow]);\n\n  useResizeEffect({ current: document.body }, positionPopup, [positionPopup]);\n\n  return (\n    <>\n      <Wrapper\n        onPointerEnter={onHover}\n        onPointerLeave={onHoverOut}\n        onFocus={(e) => {\n          setShown(true);\n          onFocus(e);\n        }}\n        onBlur={(e) => {\n          setShown(false);\n          onBlur(e);\n          resetPlacement();\n        }}\n        ref={anchorRef}\n        {...props}\n      >\n        {children}\n      </Wrapper>\n\n      {popupState?.offset && isOpen\n        ? createPortal(\n            <PopupContainer\n              ref={popupRef}\n              $offset={\n                dynamicOffset\n                  ? {\n                      ...popupState.offset,\n                      x: (popupState.offset?.x || 0) + (dynamicOffset?.x || 0),\n                    }\n                  : popupState.offset\n              }\n              noOverFlow\n              zIndex={popupZIndexOverride || DEFAULT_POPUP_Z_INDEX}\n              transforms={getTransforms(dynamicPlacement, isRTL)}\n            >\n              <TooltipContainer\n                className={className}\n                ref={tooltipRef}\n                shown={shown}\n                zIndex={popupZIndexOverride || DEFAULT_POPUP_Z_INDEX}\n                styleOverride={styleOverride}\n              >\n                <TooltipText size={TextSize.XSmall}>\n                  {shortcut\n                    ? `${title} (${prettifyShortcut(shortcut)})`\n                    : title}\n                </TooltipText>\n                {hasTail && (\n                  <>\n                    <SvgForTail>\n                      <clipPath\n                        id={SVG_TOOLTIP_TAIL_ID}\n                        clipPathUnits=\"objectBoundingBox\"\n                      >\n                        <path d=\"M1,1 L0.868,1 C0.792,1,0.72,0.853,0.676,0.606 L0.585,0.098 C0.562,-0.033,0.513,-0.033,0.489,0.098 L0.399,0.606 C0.355,0.853,0.283,1,0.207,1 L0,1 L1,1\" />\n                      </clipPath>\n                    </SvgForTail>\n                    <Tail\n                      placement={dynamicPlacement}\n                      translateX={-(dynamicOffset?.x || 0) || arrowDelta}\n                      isRTL={isRTL}\n                    />\n                  </>\n                )}\n              </TooltipContainer>\n            </PopupContainer>,\n            document.body\n          )\n        : null}\n    </>\n  );\n}\n\nexport default Tooltip;\n"
  },
  {
    "path": "packages/design-system/src/components/typography/display/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { defaultTypographyStyle } from '../styles';\n\nexport const Display = styled.h1<{\n  size: TextSize.Large | TextSize.Medium | TextSize.Small;\n}>`\n  ${defaultTypographyStyle}\n  ${({ size = TextSize.Medium, theme }) =>\n    themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.display[size],\n      theme,\n    })}\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/typography/display/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { THEME_CONSTANTS } from '../../../..';\nimport { Text } from '../..';\nimport { Display } from '..';\n\nconst displayRenderAsOptions = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\nconst displayTextSizes = THEME_CONSTANTS.TYPOGRAPHY.DISPLAY_SIZES;\n\nexport default {\n  title: 'DesignSystem/Components/Typography/Display',\n  component: Display,\n  arg: {\n    as: 'h1',\n  },\n  argTypes: {\n    as: {\n      options: displayRenderAsOptions,\n      control: 'select',\n      name: 'as HTML:',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <>\n        {displayTextSizes.map((presetSize) => (\n          <div key={`${presetSize}_display`}>\n            <Text.Paragraph size={'small'}>{presetSize}</Text.Paragraph>\n\n            <Display size={presetSize} {...args}>\n              {'The Quick Brown Fox Jumps Over the Lazy Dog'} <br />\n            </Display>\n          </div>\n        ))}\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/typography/headline/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { defaultTypographyStyle } from '../styles';\n\nexport const Headline = styled.h1<{ size: TextSize; as?: React.ElementType }>`\n  ${defaultTypographyStyle};\n\n  ${({ theme, size = TextSize.Medium }) =>\n    themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.headline[size],\n      theme,\n    })}\n  ${({ as, theme }) =>\n    as === 'a' &&\n    css`\n      :hover {\n        color: ${theme.colors.fg.linkHover};\n      }\n\n      ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)}\n    `}\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/typography/headline/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { THEME_CONSTANTS } from '../../../..';\nimport { Text } from '../..';\nimport { Headline } from '..';\n\nconst headlineTextSizes = THEME_CONSTANTS.TYPOGRAPHY.HEADLINE_SIZES;\nconst headlineRenderAsOptions = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\nexport default {\n  title: 'DesignSystem/Components/Typography/Headline',\n  component: Headline,\n  arg: {\n    as: 'h1',\n  },\n  argTypes: {\n    as: {\n      options: headlineRenderAsOptions,\n      control: 'select',\n      name: 'as HTML:',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <>\n        {headlineTextSizes.map((presetSize) => (\n          <div key={`${presetSize}_headline`}>\n            <Text.Paragraph size={'small'}>{presetSize}</Text.Paragraph>\n            <Headline size={presetSize} {...args}>\n              {'The Quick Brown Fox Jumps Over the Lazy Dog'}\n            </Headline>\n          </div>\n        ))}\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/typography/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { Display } from './display';\nexport { Headline } from './headline';\nexport { Link } from './link';\nexport { List } from './list';\nexport { Text } from './text';\n"
  },
  {
    "path": "packages/design-system/src/components/typography/link/index.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  ComponentPropsWithoutRef,\n  ForwardedRef,\n  PropsWithChildren,\n} from 'react';\nimport styled, { css } from 'styled-components';\nimport { forwardRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { defaultTypographyStyle } from '../styles';\nimport { Launch } from '../../../icons';\n\nconst StyledLaunch = styled(Launch)`\n  width: 12px;\n  margin-left: 0.5ch;\n  margin-bottom: 2px;\n  stroke-width: 0;\n  vertical-align: text-bottom;\n`;\n\ntype LinkTextSize =\n  | TextSize.XLarge\n  | TextSize.Large\n  | TextSize.Medium\n  | TextSize.Small\n  | TextSize.XSmall;\n\nexport const StyledAnchor = styled.a<{ size: LinkTextSize }>`\n  ${({ size, theme }) => css`\n    ${defaultTypographyStyle};\n    ${themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.link[size],\n      theme,\n    })};\n\n    color: ${theme.colors.fg.linkNormal};\n    text-decoration: none;\n    cursor: pointer;\n    vertical-align: baseline;\n\n    :hover {\n      color: ${theme.colors.fg.linkHover};\n    }\n    :focus {\n      /* Override WordPress's common css */\n      color: ${theme.colors.fg.linkNormal} !important;\n    }\n\n    ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)}\n  `};\n`;\n\nfunction ConditionalSpanWrapper({\n  isWrapped,\n  children,\n}: PropsWithChildren<{ isWrapped?: boolean }>) {\n  // eslint-disable-next-line react/jsx-no-useless-fragment -- required for valid return type\n  return isWrapped ? <span>{children}</span> : <>{children}</>;\n}\n\nexport interface LinkProps extends ComponentPropsWithoutRef<'a'> {\n  size?: LinkTextSize;\n}\n\nconst Link = forwardRef(function Link(\n  { children, size = TextSize.Medium, ...props }: PropsWithChildren<LinkProps>,\n  ref: ForwardedRef<HTMLAnchorElement>\n) {\n  const isExternalLink = props.target === '_blank';\n  return (\n    <StyledAnchor ref={ref} size={size} {...props}>\n      <ConditionalSpanWrapper isWrapped={isExternalLink}>\n        {children}\n        {isExternalLink && <StyledLaunch />}\n      </ConditionalSpanWrapper>\n    </StyledAnchor>\n  );\n});\n\nexport { Link };\n"
  },
  {
    "path": "packages/design-system/src/components/typography/link/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Link } from '..';\nimport { THEME_CONSTANTS } from '../../../..';\n\nexport default {\n  title: 'DesignSystem/Components/Typography/Link',\n  component: Link,\n};\n\nconst textTextSizes = THEME_CONSTANTS.TYPOGRAPHY.TEXT_SIZES;\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <>\n        {textTextSizes.map((presetSize) => (\n          <Link\n            key={`${presetSize}_text_link`}\n            size={presetSize}\n            href=\"https://example.com\"\n          >\n            {`${presetSize} - Click here for more information`}\n            <br />\n          </Link>\n        ))}\n      </>\n    );\n  },\n};\n\nexport const ExternalLink = () => (\n  <Link href=\"https://example.com\" target=\"_blank\" rel=\"noreferrer\">\n    {`Support`}\n  </Link>\n);\n"
  },
  {
    "path": "packages/design-system/src/components/typography/list/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, TextSize } from '../../../theme';\nimport { defaultTypographyStyle } from '../styles';\n\ntype ListTextSize =\n  | TextSize.XLarge\n  | TextSize.Large\n  | TextSize.Medium\n  | TextSize.Small\n  | TextSize.XSmall;\n\nexport const List = styled.ul<{ size: ListTextSize }>(\n  ({ size = TextSize.Small, theme }) => css`\n    list-style-type: disc;\n    list-style-position: outside;\n    margin: 0;\n    padding: 0;\n    li {\n      ${defaultTypographyStyle};\n      ${themeHelpers.expandPresetStyles({\n        preset: theme.typography.presets.paragraph[size],\n        theme,\n      })};\n      padding: 0;\n      margin: 0;\n    }\n  `\n);\n"
  },
  {
    "path": "packages/design-system/src/components/typography/list/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { List } from '..';\nimport { THEME_CONSTANTS } from '../../../..';\n\nexport default {\n  title: 'DesignSystem/Components/Typography/List',\n  component: List,\n};\n\nconst textTextSizes = THEME_CONSTANTS.TYPOGRAPHY.TEXT_SIZES;\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <>\n        {textTextSizes.map((presetSize) => (\n          <List key={`${presetSize}_text_list`} size={presetSize}>\n            <li>{`${presetSize} - 1`}</li>\n            <li>{`${presetSize} - 2`}</li>\n            <li>{`${presetSize} - 3`}</li>\n            <li>{`${presetSize} - 4`}</li>\n          </List>\n        ))}\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/typography/styles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Theme } from '../../theme';\n\nexport const defaultTypographyStyle = ({ theme }: { theme: Theme }) => css`\n  font-family: ${theme.typography.family.primary};\n  color: ${theme.colors.fg.primary};\n  margin: 0;\n  padding: 0;\n\n  &:focus {\n    box-shadow: none;\n  }\n`;\n"
  },
  {
    "path": "packages/design-system/src/components/typography/text/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { themeHelpers, type Theme, TextSize } from '../../../theme';\nimport { defaultTypographyStyle } from '../styles';\n\nexport interface TextProps {\n  size?: TextSize.Large | TextSize.Medium | TextSize.Small | TextSize.XSmall;\n  isBold?: boolean;\n  disabled?: boolean;\n}\n\ninterface TextPropsWithTheme extends TextProps {\n  theme: Theme;\n}\n\nconst textCss = ({\n  isBold = false,\n  size = TextSize.Medium,\n  theme,\n}: TextPropsWithTheme) => css`\n  ${defaultTypographyStyle};\n  ${themeHelpers.expandPresetStyles({\n    preset: theme.typography.presets.paragraph[size],\n    theme,\n  })};\n  font-weight: ${isBold\n    ? theme.typography.weight.bold\n    : theme.typography.presets.paragraph[size].weight};\n`;\n\nconst labelTextCss = ({\n  isBold = false,\n  size = TextSize.Medium,\n  theme,\n}: TextPropsWithTheme) => css`\n  ${defaultTypographyStyle};\n  ${themeHelpers.expandPresetStyles({\n    preset: theme.typography.presets.label[size],\n    theme,\n  })};\n  font-weight: ${isBold\n    ? theme.typography.weight.bold\n    : theme.typography.presets.label[size].weight};\n`;\n\nconst Paragraph = styled.p<TextProps>`\n  ${textCss};\n`;\n\nconst Span = styled.span<TextProps>`\n  ${textCss};\n`;\n\nconst Kbd = styled.kbd<TextProps>`\n  ${textCss};\n  background-color: transparent;\n  white-space: nowrap;\n`;\n\nconst Label = styled.label<TextProps>`\n  ${labelTextCss};\n\n  color: ${({ disabled, theme }) =>\n    disabled ? theme.colors.fg.disable : 'auto'};\n`;\n\nexport const Text = {\n  Label,\n  Span,\n  Kbd,\n  Paragraph,\n} as const;\n"
  },
  {
    "path": "packages/design-system/src/components/typography/text/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Text } from '..';\nimport { Headline } from '../..';\nimport { THEME_CONSTANTS, theme } from '../../../..';\n\nconst textTextSizes = THEME_CONSTANTS.TYPOGRAPHY.TEXT_SIZES;\nconst textRenderAsOptions = ['p', 'a', 'span'];\n\nexport default {\n  title: 'DesignSystem/Components/Typography/Text',\n  component: Text,\n  arg: {\n    as: 'p',\n  },\n  argTypes: {\n    as: {\n      options: textRenderAsOptions,\n      control: 'radio',\n      name: 'as HTML:',\n    },\n  },\n  parameters: {\n    controls: {\n      include: ['as HTML:'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <>\n        {textTextSizes.map((presetSize) => (\n          <Text.Paragraph\n            key={`${presetSize}_text`}\n            size={presetSize}\n            {...args}\n          >\n            {presetSize} <br />\n            {\n              'Duka din veranda till fest, för en långväga gäst, i landet lagom är bäst.'\n            }\n          </Text.Paragraph>\n        ))}\n      </>\n    );\n  },\n};\n\nexport const Bold = {\n  render: function Render(args) {\n    return (\n      <>\n        {textTextSizes.map((presetSize) => (\n          <Text.Paragraph\n            key={`${presetSize}_text_bold`}\n            size={presetSize}\n            isBold\n            {...args}\n          >\n            {presetSize} <br />\n            {\n              'Regnet slår mot rutorna nu, men natten är ljus, i ett land utan ljud'\n            }\n          </Text.Paragraph>\n        ))}\n      </>\n    );\n  },\n};\n\nexport const Label = {\n  render: function Render(args) {\n    return (\n      <>\n        <Headline as=\"h1\">{'Label'}</Headline>\n        {textTextSizes.map((presetSize) => {\n          return (\n            theme.typography.presets.label[presetSize] && (\n              <Text.Label\n                key={`${presetSize}_text_link`}\n                size={presetSize}\n                {...args}\n              >\n                {`${presetSize} - Och glasen glittrar tyst på vårt bord`}\n                <br />\n              </Text.Label>\n            )\n          );\n        })}\n        <br />\n        <Headline as=\"h1\">{'Label - Disabled'}</Headline>\n        {textTextSizes.map((presetSize) => {\n          return (\n            theme.typography.presets.label[presetSize] && (\n              <Text\n                key={`${presetSize}_text_link_disabled`}\n                size={presetSize}\n                as=\"label\"\n                disabled\n                {...args}\n              >\n                {`${presetSize} - Och glasen glittrar tyst på vårt bord`}\n                <br />\n              </Text>\n            )\n          );\n        })}\n      </>\n    );\n  },\n\n  args: {\n    isBold: false,\n  },\n\n  parameters: {\n    controls: {\n      include: ['isBold'],\n    },\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/components/visuallyHidden.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { visuallyHidden } from '../theme/helpers';\n\n/**\n * Useful for rendering content for screen\n * readers only\n */\nexport const VisuallyHidden = styled.span`\n  ${visuallyHidden};\n`;\n"
  },
  {
    "path": "packages/design-system/src/contexts/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './snackbar';\nexport * from './popup';\n"
  },
  {
    "path": "packages/design-system/src/contexts/popup/context.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { PopupState } from './types';\n\nexport default createContext<PopupState>({\n  isRTL: false,\n  leftOffset: 0,\n  topOffset: 0,\n});\n"
  },
  {
    "path": "packages/design-system/src/contexts/popup/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as PopupContext } from './context';\nexport { default as PopupProvider } from './popupProvider';\nexport { default as usePopup } from './usePopup';\n"
  },
  {
    "path": "packages/design-system/src/contexts/popup/popupProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nexport default Context.Provider;\n"
  },
  {
    "path": "packages/design-system/src/contexts/popup/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface PopupState {\n  isRTL: boolean;\n  leftOffset: number;\n  topOffset: number;\n}\n"
  },
  {
    "path": "packages/design-system/src/contexts/popup/usePopup.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { PopupState } from './types';\n\nfunction usePopup(): PopupState;\nfunction usePopup<T>(selector: (state: PopupState) => T): T;\nfunction usePopup<T>(\n  selector: (state: PopupState) => T | PopupState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default usePopup;\n"
  },
  {
    "path": "packages/design-system/src/contexts/snackbar/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { SnackbarState } from '../../types/snackbar';\n\nexport default createContext<SnackbarState>({\n  showSnackbar: () => false,\n  clearSnackbar: () => false,\n  removeSnack: () => false,\n  currentSnacks: [],\n  placement: '',\n});\n"
  },
  {
    "path": "packages/design-system/src/contexts/snackbar/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as SnackbarContext } from './context';\nexport { default as SnackbarProvider } from './snackbarProvider';\nexport { useSnackbar } from './useSnackbar';\n"
  },
  {
    "path": "packages/design-system/src/contexts/snackbar/snackbarProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { SnackbarNotification } from '../../components';\nimport Context from './context';\n\ninterface SnackbarProviderProps {\n  children: ReactNode;\n  placement?: 'bottom' | 'top';\n}\nfunction SnackbarProvider({\n  children,\n  placement = 'bottom',\n}: SnackbarProviderProps) {\n  const [notifications, setNotifications] = useState<SnackbarNotification[]>(\n    []\n  );\n\n  const remove = useCallback(\n    (\n      toRemove:\n        | Pick<SnackbarNotification, 'id'>\n        | Pick<SnackbarNotification, 'id'>[]\n    ) => {\n      setNotifications((currentNotifications) =>\n        currentNotifications.filter((item) => {\n          if (Array.isArray(toRemove)) {\n            return !toRemove.find(({ id }) => id === item.id);\n          }\n          return item.id !== toRemove.id;\n        })\n      );\n    },\n    []\n  );\n\n  const create = useCallback(\n    (notification: Omit<SnackbarNotification, 'id'>) => {\n      const newNotification = {\n        id: uuidv4(),\n        ...notification,\n      };\n      // React may batch state updates, so use the setter that receives the\n      // previous state.\n      setNotifications((currentNotifications) => [\n        ...currentNotifications,\n        newNotification,\n      ]);\n    },\n    []\n  );\n\n  const clear = useCallback(() => {\n    setNotifications([]);\n  }, []);\n\n  const state = useMemo(\n    () => ({\n      showSnackbar: create,\n      clearSnackbar: clear,\n      removeSnack: remove,\n      currentSnacks: notifications,\n      placement,\n    }),\n    [create, clear, remove, notifications, placement]\n  );\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nexport default SnackbarProvider;\n"
  },
  {
    "path": "packages/design-system/src/contexts/snackbar/useSnackbar.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { SnackbarState } from '../../types/snackbar';\nimport Context from './context';\n\nexport function useSnackbar(): SnackbarState;\nexport function useSnackbar<T>(selector: (state: SnackbarState) => T): T;\nexport function useSnackbar<T>(\n  selector: (state: SnackbarState) => T | SnackbarState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n"
  },
  {
    "path": "packages/design-system/src/icons/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nexport { default as AlignBottom } from './align_bottom.svg';\nexport { default as AlignCenter } from './align_center.svg';\nexport { default as AlignLeft } from './align_left.svg';\nexport { default as AlignMiddle } from './align_middle.svg';\nexport { default as AlignRight } from './align_right.svg';\nexport { default as AlignTextCenter } from './align_text_center.svg';\nexport { default as AlignTextJustified } from './align_text_justified.svg';\nexport { default as AlignTextLeft } from './align_text_left.svg';\nexport { default as AlignTextRight } from './align_text_right.svg';\nexport { default as AlignTop } from './align_top.svg';\nexport { default as Angle } from './angle.svg';\nexport { default as ArrowCloud } from './arrow_cloud.svg';\nexport { default as ArrowDown } from './arrow_down.svg';\nexport { default as ArrowDownLeftCurved } from './arrow_down_left_curved.svg';\nexport { default as ArrowDownRightCurved } from './arrow_down_right_curved.svg';\nexport { default as ArrowLeft } from './arrow_left.svg';\nexport { default as ArrowLeftCurved } from './arrow_left_curved.svg';\nexport { default as ArrowLeftLarge } from './arrow_left_large.svg';\nexport { default as ArrowOutline } from './arrow_outline.svg';\nexport { default as ArrowRight } from './arrow_right.svg';\nexport { default as ArrowRightCurved } from './arrow_right_curved.svg';\nexport { default as ArrowRightLarge } from './arrow_right_large.svg';\nexport { default as ArrowsLeftRight } from './arrows_leftright.svg';\nexport { default as ArrowUp } from './arrow_up.svg';\nexport { default as AudioSticker } from './audio_stickers.svg';\nexport { default as BackgroundBlur } from './background_blur.svg';\nexport { default as BackgroundBlurOff } from './background_blur_off.svg';\nexport { default as Border } from './border.svg';\nexport { default as BorderBox } from './border_box.svg';\nexport { default as Box1 } from './box1.svg';\nexport { default as Box4 } from './box4.svg';\nexport { default as Box4Alternate } from './box4_alternate.svg';\nexport { default as BoxWithDots } from './box_with_dots.svg';\nexport { default as Bucket } from './bucket.svg';\nexport { default as Camera } from './camera.svg';\nexport { default as CameraOff } from './camera_off.svg';\nexport { default as Captions } from './captions.svg';\nexport { default as Checkbox } from './checkbox.svg';\nexport { default as Checklist } from './checklist.svg';\nexport { default as Checkmark } from './checkmark.svg';\nexport { default as CheckmarkCircle } from './checkmark_circle.svg';\nexport { default as CheckmarkSmall } from './checkmark_small.svg';\nexport { default as ChevronDown } from './chevron_down.svg';\nexport { default as ChevronDownSmall } from './chevron_down_small.svg';\nexport { default as ChevronRightSmall } from './chevron_right_small.svg';\nexport { default as ChevronUp } from './chevron_up.svg';\nexport { default as ChevronUpSmall } from './chevron_up_small.svg';\nexport { default as CircleSpeed } from './circle_speed.svg';\nexport { default as ColorBucket } from './color_bucket.svg';\nexport { default as ColorDrop } from './color_drop.svg';\nexport { default as Corner } from './corner.svg';\nexport { default as Cross } from './cross.svg';\nexport { default as CrossLarge } from './cross_large.svg';\nexport { default as CrossSmall } from './cross_small.svg';\nexport { default as DistributeHorizontal } from './distribute_horizontal.svg';\nexport { default as DistributeVertical } from './distribute_vertical.svg';\nexport { default as Dots } from './dots.svg';\nexport { default as DotsFillSmall } from './dots_fill_small.svg';\nexport { default as Eraser } from './eraser.svg';\nexport { default as ExclamationOutline } from './exclamation_outline.svg';\nexport { default as ExclamationTriangle } from './exclamation_triangle.svg';\nexport { default as ExternalLink } from './external_link.svg';\nexport { default as Eye } from './eye.svg';\nexport { default as FloppyDisk } from './floppy_disk.svg';\nexport { default as GearWithGauge } from './gear_with_gauge.svg';\nexport { default as Gif } from './gif.svg';\nexport { default as Group } from './group.svg';\nexport { default as History } from './history.svg';\nexport { default as Keyboard } from './keyboard.svg';\nexport { default as Launch } from './launch.svg';\nexport { default as LetterAHeight } from './letter_a_height.svg';\nexport { default as LetterAWidth } from './letter_a_width.svg';\nexport { default as LetterBBold } from './letter_b_bold.svg';\nexport { default as LetterIItalic } from './letter_i_italic.svg';\nexport { default as LetterIOutline } from './letter_i_outline.svg';\nexport { default as LetterMOutline } from './letter_m_outline.svg';\nexport { default as LetterSStrikethrough } from './letter_s_strikethrough.svg';\nexport { default as LetterT } from './letter_t.svg';\nexport { default as LetterTArrow } from './letter_t_arrow.svg';\nexport { default as LetterTLargeLetterTSmall } from './letter_t_large_letter_t_small.svg';\nexport { default as LetterTPlus } from './letter_t_plus.svg';\nexport { default as LetterTUppercase } from './letter_t_uppercase.svg';\nexport { default as LetterUUnderline } from './letter_u_underline.svg';\nexport { default as Link } from './link.svg';\nexport { default as LockClosed } from './lock_closed.svg';\nexport { default as LockFilledClosed } from './lock_filled_closed.svg';\nexport { default as LockOpen } from './lock_open.svg';\nexport { default as Magnifier } from './magnifier.svg';\nexport { default as Media } from './media.svg';\nexport { default as Mic } from './mic.svg';\nexport { default as MicOff } from './mic_off.svg';\nexport { default as MirrorLeftRight } from './mirror_leftright.svg';\nexport { default as MirrorUpDown } from './mirror_updown.svg';\nexport { default as Muted } from './muted.svg';\nexport { default as PageMargin } from './page_margin.svg';\nexport { default as PagePlus } from './page_plus.svg';\nexport { default as PageSwap } from './page_swap.svg';\nexport { default as PatternLinear } from './pattern_linear.svg';\nexport { default as PatternRadial } from './pattern_radial.svg';\nexport { default as PatternSolid } from './pattern_solid.svg';\nexport { default as Pencil } from './pencil.svg';\nexport { default as Percent } from './percent.svg';\nexport { default as PhotoCamera } from './photo_camera.svg';\nexport { default as Picture } from './picture.svg';\nexport { default as PictureSwap } from './picture_swap.svg';\nexport { default as Pipette } from './pipette.svg';\nexport { default as Play } from './play.svg';\nexport { default as PlayFilled } from './play_filled.svg';\nexport { default as PlayOutline } from './play_outline.svg';\nexport { default as Plus } from './plus.svg';\nexport { default as PlusFilled } from './plus_filled.svg';\nexport { default as PlusFilledSmall } from './plus_filled_small.svg';\nexport { default as PlusOutline } from './plus_outline.svg';\nexport { default as QuestionMarkOutline } from './question_mark_outline.svg';\nexport { default as RemoveMask } from './remove_mask.svg';\nexport { default as Rotate } from './rotate.svg';\nexport { default as Scissors } from './scissors.svg';\nexport { default as Settings } from './settings.svg';\nexport { default as Shapes } from './shapes.svg';\nexport { default as Shopping } from './shopping.svg';\nexport { default as Sort } from './sort.svg';\nexport { default as Sparkles } from './sparkles.svg';\nexport { default as StopFilled } from './stop_filled.svg';\nexport { default as StopOutline } from './stop_outline.svg';\nexport { default as Table } from './table.svg';\nexport { default as TailedRectangle } from './tailed_rectangle.svg';\nexport { default as Timeline } from './timeline.svg';\nexport { default as Trash } from './trash.svg';\nexport { default as TrashFilledSmall } from './trash_filled_small.svg';\nexport { default as TurningLine } from './turning_line.svg';\nexport { default as Union } from './union.svg';\nexport { default as Video } from './video.svg';\nexport { default as Visibility } from './visibility.svg';\nexport { default as VisibilityOff } from './visibility_off.svg';\n"
  },
  {
    "path": "packages/design-system/src/icons/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useMemo } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { Text } from '../..';\nimport * as Icons from '..';\n\nexport default {\n  title: 'DesignSystem/Icons',\n};\n\nconst Page = styled.main`\n  padding: 24px;\n  display: flex;\n  flex-direction: column;\n  align-items: stretch;\n`;\n\nconst IconsList = styled.ul`\n  color: ${({ theme }) => theme.colors.fg.primary};\n  list-style-type: none;\n  display: grid;\n  grid-template-columns: repeat(4, 1fr);\n  gap: 20px 10px;\n\n  li {\n    display: flex;\n    flex-direction: column;\n    justify-items: flex-start;\n    align-items: center;\n  }\n  svg {\n    height: 32px;\n    width: 32px;\n    margin-bottom: 10px;\n  }\n`;\n\n// eslint-disable-next-line import/namespace\nconst allIcons = Object.keys(Icons).map((key) => ({ key, Icon: Icons[key] }));\n\nfunction IconDisplay({ getStyle = () => {} }) {\n  const [query, setQuery] = useState('');\n  const matchingIcons = useMemo(() => {\n    if (!query) {\n      return allIcons;\n    }\n    return allIcons.filter(({ key }) => key.match(new RegExp(query, 'i')));\n  }, [query]);\n\n  return (\n    <Page>\n      <Text.Label>\n        <span>{'Filter: '}</span>\n        <input\n          type=\"search\"\n          value={query}\n          onChange={(evt) => setQuery(evt.target.value)}\n        />\n      </Text.Label>\n      <Text.Paragraph>{`Matching: ${matchingIcons.length}`}</Text.Paragraph>\n\n      <IconsList>\n        {matchingIcons.map(({ key, Icon }, index) => {\n          return (\n            <li key={key}>\n              <Icon style={getStyle(index, key)} />\n              <Text.Span isBold>{key}</Text.Span>\n            </li>\n          );\n        })}\n      </IconsList>\n    </Page>\n  );\n}\n\nIconDisplay.propTypes = {\n  getStyle: PropTypes.func,\n};\n\nexport const AllIcons = IconDisplay;\n\nexport const ColorfulIcons = () => {\n  const colors = ['blue', 'hotpink', 'rebeccapurple', 'lightgreen', 'red'];\n  return (\n    <IconDisplay\n      getStyle={(index) => ({ color: colors[index % colors.length] })}\n    />\n  );\n};\n"
  },
  {
    "path": "packages/design-system/src/images/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Logo } from './logo_bw.svg';\nexport { default as LogoColor } from './logo_color.svg';\nexport { default as LogoWithTypeCircle } from './logo_with_type_circle_bw.svg';\nexport { default as LogoWithTypeCircleColor } from './logo_with_type_circle_color.svg';\nexport { default as LogoWithType } from './logo_with_type_bw.svg';\nexport { default as DesertColor } from './desert_color.svg';\nexport { default as DesertBw } from './desert_bw.svg';\n"
  },
  {
    "path": "packages/design-system/src/images/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Text } from '../../components';\nimport * as Images from '..';\n\nexport default {\n  title: 'DesignSystem/Images',\n};\n\nconst ImageList = styled.ul`\n  list-style-type: none;\n  display: flex;\n  flex-direction: column;\n  padding: 24px;\n  width: 300px;\n\n  li {\n    margin: 20px 0;\n  }\n`;\n\nexport const Default = () => {\n  return (\n    <ImageList>\n      {Object.keys(Images).map((imageName) => {\n        // eslint-disable-next-line import/namespace\n        const Image = Images[imageName];\n        return (\n          <li key={imageName}>\n            <Image />\n            <Text.Span isBold>{imageName}</Text.Span>\n          </li>\n        );\n      })}\n    </ImageList>\n  );\n};\n"
  },
  {
    "path": "packages/design-system/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport Modal from 'react-modal';\n\n/**\n * Internal dependencies\n */\nimport { localStore, LOCAL_STORAGE_PREFIX } from './utils/localStore';\nimport { sessionStore, SESSION_STORAGE_PREFIX } from './utils/sessionStore';\nimport * as Icons from './icons';\n\nconst { setAppElement } = Modal;\n\nexport { Icons };\nexport { localStore, LOCAL_STORAGE_PREFIX };\nexport { sessionStore, SESSION_STORAGE_PREFIX };\nexport * from './components';\nexport * from './contexts';\nexport * from './images';\nexport * from './theme';\nexport * from './utils';\nexport { setAppElement };\n"
  },
  {
    "path": "packages/design-system/src/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { dark, light } from '../theme/colors';\nimport { Headline, Text, TextSize } from '..';\nimport { Button, ButtonType } from '../components';\n\nexport default {\n  title: 'DesignSystem/Colors',\n};\n\nconst Row = styled.div`\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  border-top: ${({ beginLightDark }) =>\n    beginLightDark ? '1px solid black' : 'none'};\n  padding-top: ${({ beginLightDark }) => (beginLightDark ? '6px' : 'inherit')};\n  & > h2,\n  & > h3 {\n    width: 100%;\n  }\n  & > h3 {\n    margin-top: 5px;\n  }\n`;\nconst FixedButton = styled(Button)`\n  position: fixed;\n  right: 0;\n  top: 0;\n  margin-top: 20px;\n  margin-right: 20px;\n`;\n\nconst Container = styled.div`\n  width: 100px;\n  height: 150px;\n  display: flex;\n  margin-right: 20px;\n  margin-top: 10px;\n  flex-direction: column;\n  align-items: center;\n  overflow-wrap: anywhere;\n  p {\n    text-align: center;\n  }\n`;\n\nconst ColorBlock = styled.span`\n  width: 75px;\n  height: 75px;\n  border-radius: 50%;\n  border: 1px solid gray;\n  background-color: ${({ color }) => color};\n`;\n\nexport const _default = {\n  render: function Render() {\n    const [isDarkTheme, setIsDarkTheme] = useState(true);\n    const activeTheme = useMemo(\n      () => (isDarkTheme ? dark : light),\n      [isDarkTheme]\n    );\n    const { Small } = TextSize;\n    return (\n      <div>\n        <FixedButton\n          type={ButtonType.Primary}\n          onClick={() => setIsDarkTheme(!isDarkTheme)}\n        >{`Toggle to ${isDarkTheme ? 'light' : 'dark'} theme`}</FixedButton>\n        {Object.keys(activeTheme).map((themeSection) => (\n          <Row key={themeSection} beginLightDark={themeSection === 'fg'}>\n            <Headline as=\"h2\">{themeSection}</Headline>\n            {Object.keys(activeTheme[themeSection]).map((sectionValue) => {\n              if (typeof activeTheme[themeSection][sectionValue] === 'object') {\n                return (\n                  <Row key={`${themeSection} - ${sectionValue}`}>\n                    <Headline as=\"h3\" size={Small}>\n                      {`${themeSection} - ${sectionValue}`}\n                    </Headline>\n                    {Object.keys(activeTheme[themeSection][sectionValue]).map(\n                      (nestedSection) => {\n                        return (\n                          <Container\n                            key={`${themeSection}_${sectionValue}_${nestedSection}`}\n                          >\n                            <ColorBlock\n                              color={\n                                activeTheme[themeSection][sectionValue][\n                                  nestedSection\n                                ]\n                              }\n                            />\n                            <Text.Paragraph\n                              size={Small}\n                            >{`${themeSection}.${sectionValue}.${nestedSection} (${activeTheme[themeSection][sectionValue][nestedSection]})`}</Text.Paragraph>\n                          </Container>\n                        );\n                      }\n                    )}\n                  </Row>\n                );\n              }\n\n              return (\n                <Container key={`${themeSection}_${sectionValue}`}>\n                  <ColorBlock color={activeTheme[themeSection][sectionValue]} />\n                  <Text.Paragraph\n                    size={Small}\n                  >{`${themeSection}.${sectionValue} (${activeTheme[themeSection][sectionValue]})`}</Text.Paragraph>\n                </Container>\n              );\n            })}\n          </Row>\n        ))}\n      </div>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/storybookUtils/darkThemeProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport { ThemeProvider } from 'styled-components';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { theme } from '../theme';\n\nexport const DarkThemeProvider = ({ children }) => (\n  <ThemeProvider theme={theme}>{children}</ThemeProvider>\n);\n\nDarkThemeProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n"
  },
  {
    "path": "packages/design-system/src/storybookUtils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { DarkThemeProvider } from './darkThemeProvider';\n"
  },
  {
    "path": "packages/design-system/src/storybookUtils/sampleData.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const shortDropDownOptions = [\n  {\n    label: 'drafts',\n    value: 'drafts',\n  },\n  {\n    label: 'cats',\n    value: 'cats',\n  },\n  {\n    label: 'dogs',\n    value: 'dogs',\n  },\n];\n\nexport const basicDropDownOptions = [\n  {\n    label: 'label item one',\n    value: 'label-item-one',\n  },\n  {\n    label: 'label item two',\n    value: 'label-item-two',\n  },\n  {\n    label: 'label item three',\n    value: 'label-item-three',\n  },\n  {\n    label: 'label item four (disabled)',\n    value: 'label-item-four',\n    disabled: true,\n  },\n  {\n    label: 'label item five (value is a number)',\n    value: 5,\n  },\n  {\n    label: 'label item six (value is a boolean)',\n    value: true,\n  },\n  {\n    label: 'drafts',\n    value: 'drafts',\n  },\n  {\n    label: 'cats',\n    value: 'cats',\n  },\n  {\n    label: 'dogs',\n    value: 'dogs',\n  },\n  {\n    label: 'parakeets',\n    value: 'parakeets',\n  },\n  {\n    label: 'lemurs',\n    value: 'lemurs',\n  },\n  {\n    label: 'ocelots',\n    value: 'ocelots',\n  },\n];\n\nexport const reallyLongOptions = [\n  {\n    label: 'mad mad mad mad world',\n    value: 'tears for fears',\n  },\n  {\n    label: 'bring on the dancing horses',\n    value: 'echo',\n  },\n  {\n    label: 'one 2 three four, uno dos tres rumba',\n    value: 'pitbull',\n  },\n];\n\nexport const effectChooserOptions = [\n  {\n    value: 'none',\n    label: 'none',\n    width: 'full',\n  },\n  {\n    value: 'drop in',\n    label: 'drop',\n    width: 'full',\n  },\n  {\n    value: 'fly in left-to-right',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in top-to-bottom',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in right-to-left',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in bottom-to-top',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'pulse',\n    label: 'pulse',\n    width: 'full',\n  },\n  {\n    value: 'rotate in left-to-right',\n    label: 'rotate in',\n    width: 'half',\n  },\n  {\n    value: 'rotate in right-to-left',\n    label: 'rotate in',\n    width: 'half',\n  },\n  {\n    value: 'twirl',\n    label: 'twirl',\n    width: 'full',\n  },\n];\n\nexport const nestedDropDownOptions = [\n  {\n    label: 'aliens',\n    options: [\n      { value: 'alien-1', label: 'ET' },\n      { value: 'alien-2', label: 'Stitch' },\n      { value: 'alien-3', label: 'Groot' },\n      { value: 'alien-4', label: 'The Worm Guys' },\n      { value: 'alien-5', label: \"Na'vi\" },\n      { value: 'alien-6', label: 'Arachnids' },\n      { value: 'alien-7', label: 'The Predator' },\n      { value: 'alien-8', label: 'Xenomorph' },\n    ],\n  },\n  {\n    label: 'dragons',\n    options: [\n      { value: 'dragon-1', label: 'Smaug' },\n      { value: 'dragon-2', label: 'Mushu' },\n      { value: 'dragon-3', label: 'Toothless' },\n      { value: 'dragon-4', label: 'Falkor' },\n      { value: 'dragon-5', label: 'Drogon' },\n      { value: 'dragon-6', label: 'Kalessin' },\n    ],\n  },\n  {\n    label: 'dogs',\n    options: [\n      { value: 'dog-1', label: 'Snoopy' },\n      { value: 'dog-2', label: 'Scooby' },\n    ],\n  },\n];\n"
  },
  {
    "path": "packages/design-system/src/testUtils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './queryById';\nexport * from './renderWithProviders';\nexport * from './sampleData';\n"
  },
  {
    "path": "packages/design-system/src/testUtils/queryById.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { queryAllByAttribute, buildQueries } from '@testing-library/react';\n\nconst queryAllById = (...args) => queryAllByAttribute('id', ...args);\n\nconst getMultipleError = (c, value) =>\n  `Found multiple elements with the id attribute of: ${value}`;\nconst getMissingError = (c, value) =>\n  `Unable to find an element with the id attribute of: ${value}`;\n\nconst [queryById, getAllById, getById, findAllById, findById] = buildQueries(\n  queryAllById,\n  getMultipleError,\n  getMissingError\n);\n\nexport { queryById, queryAllById, getById, getAllById, findAllById, findById };\n"
  },
  {
    "path": "packages/design-system/src/testUtils/renderWithProviders.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\nimport PropTypes from 'prop-types';\nimport { ThemeProvider } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { lightMode, theme } from '../theme';\n\nconst ProviderWrapper = ({ children }) => {\n  return (\n    <ThemeProvider theme={{ ...theme, colors: { ...lightMode } }}>\n      {children}\n    </ThemeProvider>\n  );\n};\nProviderWrapper.propTypes = {\n  children: PropTypes.node,\n};\n\nexport const renderWithProviders = (ui) => {\n  return render(ui, {\n    wrapper: ProviderWrapper,\n  });\n};\n"
  },
  {
    "path": "packages/design-system/src/testUtils/sampleData.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const basicDropDownOptions = [\n  {\n    label: 'label item one',\n    value: 'label-item-one',\n  },\n  {\n    label: 'label item two',\n    value: 'label-item-two',\n  },\n  {\n    label: 'label item three',\n    value: 'label-item-three',\n  },\n  {\n    label: 'label item four (disabled)',\n    value: 'label-item-four',\n    disabled: true,\n  },\n  {\n    label: 'label item five (value is a number)',\n    value: 5,\n  },\n  {\n    label: 'label item six (value is a boolean)',\n    value: true,\n  },\n  {\n    label: 'drafts',\n    value: 'drafts',\n  },\n  {\n    label: 'cats',\n    value: 'cats',\n  },\n  {\n    label: 'dogs',\n    value: 'dogs',\n  },\n  {\n    label: 'parakeets',\n    value: 'parakeets',\n  },\n  {\n    label: 'lemurs',\n    value: 'lemurs',\n  },\n  {\n    label: 'ocelots',\n    value: 'ocelots',\n  },\n];\n\nexport const effectChooserOptions = [\n  {\n    value: 'none',\n    label: 'none',\n    width: 'full',\n  },\n  {\n    value: 'drop in',\n    label: 'drop',\n    width: 'full',\n  },\n  {\n    value: 'fly in left-to-right',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in top-to-bottom',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in right-to-left',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'fly in bottom-to-top',\n    label: 'fly in',\n    width: 'half',\n  },\n  {\n    value: 'pulse',\n    label: 'pulse',\n    width: 'full',\n  },\n  {\n    value: 'rotate in left-to-right',\n    label: 'rotate in',\n    width: 'half',\n  },\n  {\n    value: 'rotate in right-to-left',\n    label: 'rotate in',\n    width: 'half',\n  },\n  {\n    value: 'twirl',\n    label: 'twirl',\n    width: 'full',\n  },\n];\n\nexport const nestedDropDownOptions = [\n  {\n    label: 'aliens',\n    options: [\n      { value: 'alien-1', label: 'ET' },\n      { value: 'alien-2', label: 'Stitch' },\n      { value: 'alien-3', label: 'Groot' },\n      { value: 'alien-4', label: 'The Worm Guys' },\n      { value: 'alien-5', label: \"Na'vi\" },\n      { value: 'alien-6', label: 'Arachnids' },\n      { value: 'alien-7', label: 'The Predator' },\n      { value: 'alien-8', label: 'Xenomorph' },\n    ],\n  },\n  {\n    label: 'dragons',\n    options: [\n      { value: 'dragon-1', label: 'Smaug' },\n      { value: 'dragon-2', label: 'Mushu' },\n      { value: 'dragon-3', label: 'Toothless' },\n      { value: 'dragon-4', label: 'Falkor' },\n      { value: 'dragon-5', label: 'Drogon' },\n      { value: 'dragon-6', label: 'Kalessin' },\n    ],\n  },\n  {\n    label: 'dogs',\n    options: [\n      { value: 'dog-1', label: 'Snoopy' },\n      { value: 'dog-2', label: 'Scooby' },\n    ],\n  },\n];\n\nexport const badOptions = [\n  { value: 0, label: '0 as a number' },\n  { value: '0', label: '0 as a string' },\n  { value: false, label: 'false as a boolean' },\n  { value: 'false', label: 'false as a string' },\n  { value: true, label: 'true as a boolean' },\n  { value: undefined, label: \"undefined and shouldn't come through\" },\n];\n"
  },
  {
    "path": "packages/design-system/src/theme/borders.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const borders = {\n  radius: {\n    small: '4px',\n    medium: '8px',\n    x_large: '50px',\n    round: '9999px',\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/breakpoint.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const raw = {\n  wide: 1441,\n  desktop: 1121,\n  tablet: 801,\n  mobile: 800,\n  mobileSmall: 684,\n  min: 684,\n};\n\nexport const breakpoint = {\n  wide: `screen and (min-width: ${raw.wide}px)`,\n  desktop: `screen and (min-width: ${raw.desktop}px)`,\n  tablet: `screen and (min-width: ${raw.tablet}px)`,\n  tabletMax: `screen and (max-width: ${raw.desktop}px)`,\n  mobile: `screen and (max-width: ${raw.mobile}px)`,\n  mobileSmall: `screen and (max-width: ${raw.mobileSmall}px)`,\n  min: `screen and (max-width: ${raw.min}px)`,\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/colors.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { rgba } from 'polished';\n\n// colors that are not subject to light or dark mode are stored in colors.\n// colors related to light or dark mode are nested in colors.light or colors.dark\n// it's important that the object structure be the same so that eventually we can flip from dark to light theme, vic versa\n\nconst brand = {\n  gray: {\n    90: '#131516',\n    85: '#1B1F20',\n    80: '#26292A',\n    75: '#2E3133',\n    70: '#393D3F',\n    60: '#4B5253',\n    50: '#5E6668',\n    40: '#767E80',\n    30: '#919899',\n    20: '#ADB1B3',\n    10: '#C8CBCC',\n    5: '#E4E5E6',\n  },\n  violet: {\n    90: '#351E7A',\n    80: '#482A90',\n    70: '#5732A3',\n    60: '#6B3DBA',\n    50: '#7B46CB',\n    40: '#9464E1',\n    30: '#B488FC',\n    20: '#CBACFF',\n    10: '#DFCDFE',\n    5: '#F3EBFF',\n  },\n  blue: {\n    90: '#2C2864',\n    80: '#364286',\n    70: '#4157A3',\n    60: '#476ABD',\n    50: '#4F7ED9',\n    40: '#5D96EB',\n    30: '#79B3FF',\n    20: '#9CC9FF',\n    10: '#C2DDFF',\n    5: '#E5F2FF',\n  },\n  red: {\n    90: '#690000',\n    80: '#7E0000',\n    70: '#930500',\n    60: '#AC1501',\n    50: '#C42300',\n    40: '#D43626',\n    30: '#E45F53',\n    20: '#F28B82',\n    10: '#FFC4C5',\n    5: '#FFE7E9',\n  },\n  green: {\n    90: '#133B20',\n    80: '#205630',\n    70: '#296B3C',\n    60: '#34824B',\n    50: '#3F9A5A',\n    40: '#5EAE75',\n    30: '#81C995',\n    20: '#A5D7B3',\n    10: '#C8E7D0',\n    5: '#E8F5EC',\n  },\n};\nconst accent = {\n  primary: brand.violet[30],\n  secondary: brand.blue[30],\n};\nconst status = {\n  negative: '#D93025',\n  positive: '#188038',\n  warning: '#f4b844',\n};\nconst standard = {\n  black: '#000',\n  white: '#FFF',\n};\n\nconst gradient = {\n  loading: 'linear-gradient(270deg, #4285f4 0%, #0f0bc8 57%, #4285f4 110%)',\n  placeholder: 'linear-gradient(180deg, #fff0, #000c)',\n  posterOverlay:\n    'linear-gradient(to top, rgba(33, 33, 33, 0.9), rgba(33, 33, 33, 0))',\n};\n\nconst opacity = {\n  footprint: 'transparent',\n  white64: rgba(standard.white, 0.64),\n  white24: rgba(standard.white, 0.24),\n  white16: rgba(standard.white, 0.16),\n  white8: rgba(standard.white, 0.08),\n  black64: rgba(standard.black, 0.64),\n  black40: rgba(standard.black, 0.4),\n  black32: rgba(standard.black, 0.32),\n  black24: rgba(standard.black, 0.24),\n  black10: rgba(standard.black, 0.1),\n  black3: rgba(standard.black, 0.03),\n  blue24: rgba(brand.blue[30], 0.24),\n  violet24: rgba(brand.violet[30], 0.24),\n  overlay: rgba('#1E1F1F', 0.5),\n  overlayDark: rgba(standard.black, 0.47),\n  overlayExtraDark: rgba(standard.black, 0.7),\n};\n\nconst darkTheme = {\n  gradient,\n  fg: {\n    primary: brand.gray[5],\n    secondary: brand.gray[20],\n    tertiary: brand.gray[30],\n    disable: brand.gray[50],\n    linkNormal: brand.blue[30],\n    linkHover: brand.blue[40],\n    positive: brand.green[30],\n    negative: brand.red[30],\n  },\n  bg: {\n    primary: brand.gray[90],\n    secondary: brand.gray[80],\n    tertiary: brand.gray[70],\n    quaternary: brand.gray[60],\n    positive: brand.green[90],\n    negative: brand.red[90],\n    storyPreview: '#202125',\n    accent: accent.primary,\n  },\n  interactiveFg: {\n    active: brand.gray[5],\n    brandNormal: brand.gray[90],\n    brandHover: brand.gray[90],\n    brandPress: brand.violet[40],\n  },\n  interactiveBg: {\n    active: brand.violet[70],\n    disable: brand.gray[85],\n    brandNormal: brand.violet[20],\n    brandHover: brand.violet[30],\n    brandPress: brand.violet[40],\n    primaryNormal: brand.gray[10],\n    primaryHover: brand.gray[20],\n    primaryPress: brand.gray[30],\n    secondaryNormal: brand.gray[70],\n    secondaryHover: brand.gray[60],\n    secondaryPress: brand.gray[50],\n    tertiaryNormal: opacity.footprint,\n    tertiaryHover: brand.gray[70],\n    tertiaryPress: brand.gray[60],\n    quaternaryNormal: opacity.footprint,\n    negativeNormal: brand.red[40],\n    negativeHover: brand.red[30],\n    negativePress: brand.red[20],\n    positiveNormal: brand.green[40],\n    positiveHover: brand.green[30],\n    positivePress: brand.green[20],\n    previewOverlay: opacity.black10,\n    modalScrim: opacity.white8,\n  },\n  border: {\n    focus: brand.blue[30],\n    disable: brand.gray[75],\n    defaultNormal: brand.gray[70],\n    defaultHover: brand.gray[40],\n    defaultPress: brand.gray[30],\n    defaultActive: brand.gray[10],\n    positiveNormal: brand.green[40],\n    positiveHover: brand.green[30],\n    positivePress: brand.green[20],\n    positiveActive: brand.green[10],\n    quaternaryNormal: brand.gray[70],\n    quaternaryHover: brand.gray[40],\n    quaternaryPress: standard.black,\n    quaternaryActive: brand.gray[30],\n    negativeNormal: brand.red[40],\n    negativeHover: brand.red[30],\n    negativePress: brand.red[20],\n    negativeActive: brand.red[10],\n    selection: brand.blue[30],\n  },\n  divider: {\n    primary: opacity.white24,\n    secondary: opacity.white8,\n    tertiary: opacity.black24,\n  },\n  form: {\n    dropDownSubtitle: brand.gray[20], // equivalent to fg.secondary\n  },\n  shadow: {\n    active: opacity.white16,\n  },\n};\n\nconst lightTheme = {\n  gradient,\n  fg: {\n    primary: brand.gray[90],\n    secondary: brand.gray[70],\n    tertiary: brand.gray[50],\n    disable: brand.gray[30],\n    linkNormal: brand.blue[50],\n    linkHover: brand.blue[60],\n    positive: brand.green[80],\n    negative: brand.red[80],\n  },\n  bg: {\n    primary: standard.white,\n    secondary: brand.gray[5],\n    tertiary: brand.gray[10],\n    quaternary: brand.gray[20],\n    positive: brand.green[10],\n    negative: brand.red[10],\n    storyPreview: '#202125',\n    accent: accent.primary,\n  },\n  interactiveFg: {\n    active: brand.gray[90],\n    brandNormal: brand.gray[90],\n    brandHover: brand.gray[90],\n    brandPress: brand.violet[40],\n  },\n  interactiveBg: {\n    active: brand.violet[10],\n    disable: brand.gray[10],\n    brandNormal: brand.violet[20],\n    brandHover: brand.violet[30],\n    brandPress: brand.violet[40],\n    primaryNormal: brand.gray[90],\n    primaryHover: brand.gray[80],\n    primaryPress: brand.gray[70],\n    secondaryNormal: brand.gray[20],\n    secondaryHover: brand.gray[30],\n    secondaryPress: brand.gray[40],\n    tertiaryNormal: opacity.footprint,\n    tertiaryHover: brand.gray[10],\n    tertiaryPress: brand.gray[20],\n    quaternaryNormal: opacity.footprint,\n    negativeNormal: brand.red[20],\n    negativeHover: brand.red[30],\n    negativePress: brand.red[40],\n    positiveNormal: brand.green[20],\n    positiveHover: brand.green[30],\n    positivePress: brand.green[40],\n    previewOverlay: opacity.white16,\n    modalScrim: opacity.black40,\n  },\n  border: {\n    focus: brand.blue[40],\n    disable: brand.gray[10],\n    defaultNormal: brand.gray[20],\n    defaultHover: brand.gray[30],\n    defaultPress: brand.gray[40],\n    defaultActive: brand.gray[90],\n    positiveNormal: brand.green[20],\n    positiveHover: brand.green[30],\n    positivePress: brand.green[40],\n    positiveActive: brand.green[90],\n    negativeNormal: brand.red[20],\n    negativeHover: brand.red[30],\n    negativePress: brand.red[40],\n    negativeActive: brand.red[90],\n    quaternaryNormal: brand.gray[20],\n    quaternaryHover: brand.gray[30],\n    quaternaryPress: standard.white,\n    quaternaryActive: brand.gray[40],\n    selection: brand.blue[40],\n  },\n  divider: {\n    primary: opacity.black24,\n    secondary: opacity.black10,\n    tertiary: opacity.white24,\n  },\n  form: {\n    dropDownSubtitle: brand.gray[50], // equivalent to fg.tertiary\n  },\n  shadow: {\n    active: opacity.black10,\n  },\n};\n\nexport const dark = {\n  standard,\n  accent,\n  status,\n  opacity,\n  ...brand,\n  ...darkTheme,\n  inverted: { ...lightTheme },\n};\n\nexport const light = {\n  standard,\n  accent,\n  status,\n  opacity,\n  ...brand,\n  ...lightTheme,\n  inverted: { ...darkTheme },\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/constants/breakpoints.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const BREAKPOINTS = {\n  TABLET: {\n    maxWidth: 1120,\n    minWidth: 768,\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/constants/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { BREAKPOINTS } from './breakpoints';\n\nconst ICON_SIZE = 32;\nconst LARGE_BUTTON_SIZE = 56;\n\nconst SCROLLBAR_WIDTH = 11;\n\nexport const THEME_CONSTANTS = {\n  BREAKPOINTS,\n  ICON_SIZE,\n  LARGE_BUTTON_SIZE,\n  SCROLLBAR_WIDTH,\n};\n\nexport const BEZIER = {\n  linear: 'linear',\n  inQuad: 'cubic-bezier(0.55, 0.085, 0.68, 0.53)',\n  outQuad: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n  inOutQuad: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)',\n  inCubic: 'cubic-bezier(0.55, 0.055, 0.675, 0.19)',\n  outCubic: 'cubic-bezier(0.215, 0.61, 0.355, 1)',\n  inOutCubic: 'cubic-bezier(0.645, 0.045, 0.355, 1)',\n  inQuart: 'cubic-bezier(0.895, 0.03, 0.685, 0.22)',\n  outQuart: 'cubic-bezier(0.165, 0.84, 0.44, 1)',\n  inOutQuart: 'cubic-bezier(0.77, 0, 0.175, 1)',\n  inQuint: 'cubic-bezier(0.755, 0.05, 0.855, 0.06)',\n  outQuint: 'cubic-bezier(0.23, 1, 0.32, 1)',\n  inOutQuint: 'cubic-bezier(0.86, 0, 0.07, 1)',\n  inSine: 'cubic-bezier(0.47, 0, 0.745, 0.715)',\n  outSine: 'cubic-bezier(0.39, 0.575, 0.565, 1)',\n  inOutSine: 'cubic-bezier(0.445, 0.05, 0.55, 0.95)',\n  inExpo: 'cubic-bezier(0.95, 0.05, 0.795, 0.035)',\n  outExpo: 'cubic-bezier(0.19, 1, 0.22, 1)',\n  inOutExpo: 'cubic-bezier(1, 0, 0, 1)',\n  inCirc: 'cubic-bezier(0.6, 0.04, 0.98, 0.335)',\n  outCirc: 'cubic-bezier(0.075, 0.82, 0.165, 1)',\n  inOutCirc: 'cubic-bezier(0.785, 0.135, 0.15, 0.86)',\n  default: 'cubic-bezier(0.4, 0.4, 0.0, 1)',\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/global/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { Styles } from './styles';\n"
  },
  {
    "path": "packages/design-system/src/theme/global/styles.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { scrollbarCSS } from '../helpers/scrollbar';\n\n/**\n * All components in the design system are created using the following global styling.\n * Not having these css rules may result in styling defects.\n */\nexport const Styles = createGlobalStyle`\n  *,\n  *::after,\n  *::before {\n    box-sizing: border-box;\n  }\n\n  ${scrollbarCSS};\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/centerContent.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\nexport const centerContent = css`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/expandPresetStyles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Preset } from '../../types/typography';\nimport type { Theme } from '../theme';\nimport { TextSize } from '../types';\n\ninterface ExpandPresetStylesProps {\n  preset?: Preset;\n  theme: Theme;\n}\n\nexport const expandPresetStyles = ({\n  preset,\n  theme,\n}: ExpandPresetStylesProps) =>\n  preset\n    ? css`\n        font-family: ${theme.typography.family.primary};\n        font-size: ${preset.size}px;\n        font-weight: ${preset.weight};\n        letter-spacing: ${preset.letterSpacing}px;\n        line-height: ${preset.lineHeight}px;\n        text-decoration: none;\n      `\n    : css``;\n\ntype PresetChoices = Theme['typography']['presets'];\ntype PresetSelector = (\n  choices: PresetChoices,\n  sizes: typeof TextSize\n) => Preset;\n\nexport const expandTextPreset =\n  (presetSelector: PresetSelector) =>\n  ({ theme }: { theme: Theme }) =>\n    expandPresetStyles({\n      preset: presetSelector(theme.typography.presets, TextSize),\n      theme,\n    });\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/fullSize.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\nexport const fullSizeAbsolute = css`\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n`;\n\nexport const fullSizeRelative = css`\n  position: relative;\n  top: 0;\n  left: 0;\n  height: 100%;\n  width: 100%;\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './outline';\nexport * from './scrollbar';\nexport { expandPresetStyles, expandTextPreset } from './expandPresetStyles';\nexport { fullSizeAbsolute, fullSizeRelative } from './fullSize';\nexport { centerContent } from './centerContent';\nexport { visuallyHidden } from './visuallyHidden';\nexport { transparentBg } from './transparentBg';\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/outline.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Theme } from '..';\n\n/**\n * A css snippet that can be used for the focus styling.\n */\nexport const focusCSS = (accent?: string, background?: string) => css`\n  outline: none;\n  box-shadow: ${({ theme }) =>\n    `0px 0px 0 2px ${background || theme.colors.bg.primary}, 0px 0px 0 4px ${\n      typeof accent === 'string' ? accent : theme.colors.border.focus\n    }`};\n`;\n\nexport const focusableOutlineCSS = (\n  colorOrProps: string | { theme: Theme },\n  background?: string\n) => {\n  const accent =\n    typeof colorOrProps === 'string'\n      ? colorOrProps\n      : colorOrProps?.theme?.colors?.border?.focus;\n  return css`\n    &:focus-visible {\n      ${focusCSS(accent, background)};\n    }\n  `;\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/scrollbar.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { THEME_CONSTANTS } from '../constants';\n\n/*\n * CSS for custom gray scrollbars for Chromium, Safari, Edge, & Opera.\n *\n * NOTE: Firefox does not yet support webkit scrollbar styling\n */\nexport const scrollbarCSS = () => css`\n  /* Firefox compatible css */\n  scrollbar-width: thin;\n  scrollbar-color: ${({ theme }) => theme.colors.interactiveBg.secondaryNormal}\n    ${({ theme }) => theme.colors.inverted.divider.secondary};\n  /* end Firefox compatible css */\n\n  ::-webkit-scrollbar {\n    width: ${THEME_CONSTANTS.SCROLLBAR_WIDTH}px;\n    height: ${THEME_CONSTANTS.SCROLLBAR_WIDTH}px;\n  }\n\n  ::-webkit-scrollbar-track {\n    background: ${({ theme }) => theme.colors.inverted.divider.secondary};\n  }\n\n  ::-webkit-scrollbar-thumb {\n    background-clip: content-box;\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryNormal};\n    border: 2px solid transparent;\n    border-radius: 10px;\n  }\n\n  ::-webkit-scrollbar-corner {\n    background-color: transparent;\n  }\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/transparentBg.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\nexport const transparentBg = css`\n  background-image: conic-gradient(\n    ${({ theme }) => theme.colors.fg.tertiary} 0.25turn,\n    transparent 0turn 0.5turn,\n    ${({ theme }) => theme.colors.fg.tertiary} 0turn 0.75turn,\n    transparent 0turn 1turn\n  );\n  background-size: 8px 8px;\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/helpers/visuallyHidden.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\n\n/**\n * Useful for rendering content for screen\n * readers only\n */\nexport const visuallyHidden = css`\n  position: absolute;\n  height: 1px;\n  width: 1px;\n  overflow: hidden;\n  clip: rect(1px, 1px, 1px, 1px);\n  white-space: nowrap;\n`;\n"
  },
  {
    "path": "packages/design-system/src/theme/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { light as lightMode } from './colors';\nexport { THEME_CONSTANTS, BEZIER } from './constants';\nexport * as ThemeGlobals from './global';\nexport * as themeHelpers from './helpers';\nexport * from './theme';\nexport * from './types';\n"
  },
  {
    "path": "packages/design-system/src/theme/stories/colors.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { dark, light } from '../colors';\nimport { Button, ButtonType, Headline, Text } from '../../components';\nimport { TextSize } from '../types';\n\nexport default {\n  title: 'DesignSystem/Theme/Colors',\n};\n\nconst Row = styled.div`\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  border-top: ${({ beginLightDark }) =>\n    beginLightDark ? '1px solid black' : 'none'};\n  padding-top: ${({ beginLightDark }) => (beginLightDark ? '6px' : 'inherit')};\n  & > h2,\n  & > h3 {\n    width: 100%;\n  }\n  & > h3 {\n    margin-top: 5px;\n  }\n`;\nconst FixedButton = styled(Button)`\n  position: fixed;\n  right: 0;\n  top: 0;\n  margin-top: 20px;\n  margin-right: 20px;\n`;\n\nconst Container = styled.div`\n  width: 100px;\n  height: 150px;\n  display: flex;\n  margin-right: 20px;\n  margin-top: 10px;\n  flex-direction: column;\n  align-items: center;\n  overflow-wrap: anywhere;\n  p {\n    text-align: center;\n  }\n`;\n\nconst ColorBlock = styled.span`\n  width: 75px;\n  height: 75px;\n  border-radius: 50%;\n  border: 1px solid gray;\n  background-color: ${({ color }) => color};\n`;\n\nexport const _default = {\n  render: function Render() {\n    const [isDarkTheme, setIsDarkTheme] = useState(true);\n    const activeTheme = useMemo(\n      () => (isDarkTheme ? dark : light),\n      [isDarkTheme]\n    );\n    return (\n      <div>\n        <FixedButton\n          type={ButtonType.Primary}\n          onClick={() => setIsDarkTheme(!isDarkTheme)}\n        >{`Toggle to ${isDarkTheme ? 'light' : 'dark'} theme`}</FixedButton>\n        {Object.keys(activeTheme).map((themeSection) => (\n          <Row key={themeSection} beginLightDark={themeSection === 'fg'}>\n            <Headline as=\"h2\">{themeSection}</Headline>\n            {Object.keys(activeTheme[themeSection]).map((sectionValue) => {\n              if (typeof activeTheme[themeSection][sectionValue] === 'object') {\n                return (\n                  <Row key={`${themeSection} - ${sectionValue}`}>\n                    <Headline as=\"h3\" size={TextSize.Small}>\n                      {`${themeSection} - ${sectionValue}`}\n                    </Headline>\n                    {Object.keys(activeTheme[themeSection][sectionValue]).map(\n                      (nestedSection) => {\n                        return (\n                          <Container\n                            key={`${themeSection}_${sectionValue}_${nestedSection}`}\n                          >\n                            <ColorBlock\n                              color={\n                                activeTheme[themeSection][sectionValue][\n                                  nestedSection\n                                ]\n                              }\n                            />\n                            <Text.Paragraph\n                              size={TextSize.Small}\n                            >{`${themeSection}.${sectionValue}.${nestedSection} (${activeTheme[themeSection][sectionValue][nestedSection]})`}</Text.Paragraph>\n                          </Container>\n                        );\n                      }\n                    )}\n                  </Row>\n                );\n              }\n\n              return (\n                <Container key={`${themeSection}_${sectionValue}`}>\n                  <ColorBlock color={activeTheme[themeSection][sectionValue]} />\n                  <Text.Paragraph\n                    size={TextSize.Small}\n                  >{`${themeSection}.${sectionValue} (${activeTheme[themeSection][sectionValue]})`}</Text.Paragraph>\n                </Container>\n              );\n            })}\n          </Row>\n        ))}\n      </div>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { Headline } from '../../components/typography';\nimport { DarkThemeProvider } from '../../storybookUtils';\nimport { scrollbarCSS } from '../helpers/scrollbar';\n\nexport default {\n  title: 'DesignSystem/Theme/Scrollbar',\n};\n\nconst randomInt = (max) => Math.floor(Math.random() * Math.floor(max));\n\nconst Container = styled.div`\n  display: flex;\n`;\n\nconst ScrollContainer = styled.div`\n  height: 400px;\n  width: 50%;\n  padding: 20px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  overflow-y: scroll;\n\n  ${scrollbarCSS};\n`;\n\nconst Content = styled.div`\n  height: 100px;\n  width: 100%;\n  margin-bottom: 25px;\n  background-color: ${({ theme }) =>\n    [\n      theme.colors.fg.primary,\n      theme.colors.interactiveBg.positiveNormal,\n      theme.colors.interactiveBg.negativeNormal,\n    ][randomInt(3)]};\n  border: 1px solid ${({ theme }) => theme.colors.bg.tertiary};\n  border-radius: 4px;\n`;\n\nexport const _default = {\n  render: function Render() {\n    const ids = useMemo(\n      () => Array.from({ length: 20 }).map(() => uuidv4()),\n      []\n    );\n\n    return (\n      <>\n        <Headline as=\"h2\">{'Scrollbar'}</Headline>\n        <Container>\n          <ScrollContainer>\n            {ids.map((id) => (\n              <Content key={id} />\n            ))}\n          </ScrollContainer>\n          <DarkThemeProvider>\n            <ScrollContainer>\n              {ids.map((id) => (\n                <Content key={id} />\n              ))}\n            </ScrollContainer>\n          </DarkThemeProvider>\n        </Container>\n      </>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/design-system/src/theme/theme.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { dark as darkMode } from './colors';\nimport { typography } from './typography';\nimport { borders } from './borders';\nimport { breakpoint, raw } from './breakpoint';\n\nexport const theme = {\n  borders,\n  typography,\n  colors: { ...darkMode },\n  breakpoint: {\n    ...breakpoint,\n    raw,\n  },\n};\nexport type Theme = typeof theme;\n"
  },
  {
    "path": "packages/design-system/src/theme/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum TextSize {\n  XXLarge = 'xxlarge',\n  XLarge = 'xlarge',\n  Large = 'large',\n  Medium = 'medium',\n  Small = 'small',\n  XSmall = 'xsmall',\n  XXSmall = 'xxsmall',\n  XXXSmall = 'xxxsmall',\n}\n\nexport type ParagraphSize =\n  | TextSize.XLarge\n  | TextSize.Large\n  | TextSize.Medium\n  | TextSize.Small\n  | TextSize.XSmall;\n\nexport type DisplaySize = TextSize.Large | TextSize.Medium | TextSize.Small;\n\nexport type HeadlineSize =\n  | TextSize.XXLarge\n  | TextSize.XLarge\n  | TextSize.Large\n  | TextSize.Medium\n  | TextSize.Small\n  | TextSize.XSmall\n  | TextSize.XXSmall\n  | TextSize.XXXSmall;\n"
  },
  {
    "path": "packages/design-system/src/theme/typography.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { TextSize } from './types';\n\n// sizes are in px but unit is left off in case calculations are necessary\nconst themeFonts = {\n  primary: \"'Google Sans', sans-serif\",\n};\n\nexport const typography = {\n  family: { ...themeFonts },\n  weight: {\n    bold: 700,\n    regular: 400,\n  },\n  presets: {\n    display: {\n      [TextSize.Large]: {\n        weight: 700,\n        size: 122,\n        lineHeight: 124,\n        letterSpacing: -2.4,\n      },\n      [TextSize.Medium]: {\n        weight: 700,\n        size: 58,\n        lineHeight: 64,\n        letterSpacing: -1.4,\n      },\n      [TextSize.Small]: {\n        weight: 700,\n        size: 36,\n        lineHeight: 40,\n        letterSpacing: -1,\n      },\n    },\n    headline: {\n      [TextSize.XXLarge]: {\n        weight: 400,\n        size: 42,\n        lineHeight: 56,\n        letterSpacing: 0,\n      },\n      [TextSize.XLarge]: {\n        weight: 400,\n        size: 36,\n        lineHeight: 44,\n        letterSpacing: 0,\n      },\n      [TextSize.Large]: {\n        weight: 400,\n        size: 32,\n        lineHeight: 40,\n        letterSpacing: 0,\n      },\n      [TextSize.Medium]: {\n        weight: 400,\n        size: 28,\n        lineHeight: 36,\n        letterSpacing: 0,\n      },\n      [TextSize.Small]: {\n        weight: 400,\n        size: 24,\n        lineHeight: 32,\n        letterSpacing: 0,\n      },\n      [TextSize.XSmall]: {\n        weight: 500,\n        size: 20,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.XXSmall]: {\n        weight: 700,\n        size: 16,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.XXXSmall]: {\n        weight: 700,\n        size: 14,\n        lineHeight: 20,\n        letterSpacing: 0,\n      },\n    },\n    paragraph: {\n      [TextSize.XLarge]: {\n        weight: 400,\n        size: 24,\n        lineHeight: 32,\n        letterSpacing: -0.02,\n      },\n      [TextSize.Large]: {\n        weight: 400,\n        size: 18,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.Medium]: {\n        weight: 400,\n        size: 16,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.Small]: {\n        weight: 400,\n        size: 14,\n        lineHeight: 20,\n        letterSpacing: 0,\n      },\n      [TextSize.XSmall]: {\n        weight: 400,\n        size: 12,\n        lineHeight: 20,\n        letterSpacing: 0.16,\n      },\n    },\n    link: {\n      [TextSize.XLarge]: {\n        weight: 400,\n        size: 24,\n        lineHeight: 32,\n        letterSpacing: -0.02,\n      },\n      [TextSize.Large]: {\n        weight: 700,\n        size: 18,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.Medium]: {\n        weight: 700,\n        size: 16,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.Small]: {\n        weight: 700,\n        size: 14,\n        lineHeight: 20,\n        letterSpacing: 0,\n      },\n      [TextSize.XSmall]: {\n        weight: 700,\n        size: 12,\n        lineHeight: 20,\n        letterSpacing: 0.16,\n      },\n    },\n    label: {\n      [TextSize.Large]: {\n        weight: 400,\n        size: 18,\n        lineHeight: 24,\n        letterSpacing: 0,\n      },\n      [TextSize.Medium]: {\n        weight: 400,\n        size: 16,\n        lineHeight: 20,\n        letterSpacing: 0,\n      },\n      [TextSize.Small]: {\n        weight: 400,\n        size: 14,\n        lineHeight: 12,\n        letterSpacing: 0,\n      },\n      [TextSize.XSmall]: {\n        weight: 400,\n        size: 12,\n        lineHeight: 20,\n        letterSpacing: 0,\n      },\n    },\n  },\n} as const;\n"
  },
  {
    "path": "packages/design-system/src/types/keyboard.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type keys from '../components/keyboard/keys';\n\nexport interface KeySpec {\n  key: string | string[];\n  shift?: boolean;\n  clickable?: boolean;\n  dialog?: boolean;\n  repeat?: boolean;\n  editable?: boolean;\n  allowDefault?: boolean;\n}\nexport type Keys = typeof keys;\nexport type KeyEffectCallback = (event: KeyboardEvent) => void;\nexport type KeyNameOrSpec = KeySpec | string | string[];\n\nexport type RefOrNode = Element | RefObject<Element> | null;\n"
  },
  {
    "path": "packages/design-system/src/types/snackbar.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { SnackbarNotification } from '../components';\n\nexport interface SnackbarState {\n  showSnackbar: (snackbar: Omit<SnackbarNotification, 'id'>) => void;\n  clearSnackbar: () => void;\n  removeSnack: (\n    toRemove: SnackbarNotification | SnackbarNotification[]\n  ) => void;\n  currentSnacks: SnackbarNotification[];\n  placement: string;\n}\n"
  },
  {
    "path": "packages/design-system/src/types/theme.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Interpolation, ThemedStyledProps } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Theme } from '../theme';\n\nexport type StyleOverride = Interpolation<ThemedStyledProps<object, Theme>>;\n"
  },
  {
    "path": "packages/design-system/src/types/typography.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface Preset {\n  size: number;\n  weight: number;\n  lineHeight: number;\n  letterSpacing: number;\n}\n"
  },
  {
    "path": "packages/design-system/src/typings/styled.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport type { Theme } from '../theme';\n\ndeclare module 'styled-components' {\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- On purpose.\n  export interface DefaultTheme extends Theme {}\n}\n"
  },
  {
    "path": "packages/design-system/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/design-system/src/utils/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const KEYS = {\n  DOWN: 'ArrowDown',\n  LEFT: 'ArrowLeft',\n  RIGHT: 'ArrowRight',\n  UP: 'ArrowUp',\n  ENTER: 'Enter',\n  SPACE: 'Space',\n  TAB: 'Tab',\n};\n\nexport const FOCUSABLE_SELECTORS = [\n  'button:not(:disabled)',\n  '[href]',\n  'input:not(:disabled)',\n  'select:not(:disabled)',\n  'textarea:not(:disabled)',\n  '[tabindex]:not([tabindex=\"-1\"])',\n];\n"
  },
  {
    "path": "packages/design-system/src/utils/deepMerge.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype Mergeable = Record<string, unknown>;\n\n/**\n * Deep merge objects.\n */\nexport default function deepMerge(object: Mergeable, source: Mergeable = {}) {\n  Object.entries(source).forEach(([key, value]) => {\n    if (value !== undefined) {\n      if (value && 'object' === typeof value && !Array.isArray(value)) {\n        if (!('key' in object) && !object[key]) {\n          Object.assign(object, { [key]: {} });\n        }\n        deepMerge(object[key] as Mergeable, value as Mergeable);\n      } else {\n        Object.assign(object, { [key]: value });\n      }\n    }\n  });\n\n  return object;\n}\n"
  },
  {
    "path": "packages/design-system/src/utils/directions.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport enum Direction {\n  Top = 'top',\n  Right = 'right',\n  Bottom = 'bottom',\n  Left = 'left',\n}\n\nexport type CornerDirection = keyof typeof CORNER_DIRECTIONS;\n\nexport const CORNER_DIRECTIONS = {\n  [`${Direction.Top}_${Direction.Left}`]: `${Direction.Top}_${Direction.Left}`,\n  [`${Direction.Top}_${Direction.Right}`]: `${Direction.Top}_${Direction.Right}`,\n  [`${Direction.Bottom}_${Direction.Right}`]: `${Direction.Bottom}_${Direction.Right}`,\n  [`${Direction.Bottom}_${Direction.Left}`]: `${Direction.Bottom}_${Direction.Left}`,\n};\n"
  },
  {
    "path": "packages/design-system/src/utils/getKeyboardMovement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst MOVE_COARSE_STEP = 10;\n\nfunction getKeyboardMovement(\n  key: string,\n  shiftKey: boolean,\n  coarseDistance = MOVE_COARSE_STEP\n) {\n  const dirX = getArrowDir(key, 'ArrowRight', 'ArrowLeft');\n  const dirY = getArrowDir(key, 'ArrowDown', 'ArrowUp');\n  const delta = shiftKey ? 1 : coarseDistance;\n  return {\n    dx: dirX * delta,\n    dy: dirY * delta,\n  };\n}\n\nfunction getArrowDir(key: string, pos: string, neg: string) {\n  if (key === pos) {\n    return 1;\n  }\n  if (key === neg) {\n    return -1;\n  }\n  return 0;\n}\n\nexport default getKeyboardMovement;\n"
  },
  {
    "path": "packages/design-system/src/utils/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as isNullOrUndefinedOrEmptyString } from './isNullOrUndefinedOrEmptyString';\nexport { noop } from './noop';\nexport { default as labelAccessibilityValidator } from './labelAccessibilityValidator';\nexport { default as useLiveRegion } from './useLiveRegion';\nexport { default as deepMerge } from './deepMerge';\nexport { default as useMouseDownOutsideRef } from './useMouseDownOutsideRef';\nexport { default as getKeyboardMovement } from './getKeyboardMovement';\nexport { default as uniqueEntriesByKey } from './uniqueEntriesByKey';\nexport { default as PanelTypes } from './panelTypes';\nexport { PanelSections } from './panelSections';\nexport { STYLE_PANE_IDS } from './panelSections';\nexport * from './constants';\nexport * from './directions';\n"
  },
  {
    "path": "packages/design-system/src/utils/isNullOrUndefinedOrEmptyString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default function isNullOrUndefinedOrEmptyString(val: unknown) {\n  return val === null || val === undefined || val === '';\n}\n"
  },
  {
    "path": "packages/design-system/src/utils/labelAccessibilityValidator.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Custom propTypes validator used to check if either `label`\n * or `aria-label` have been passed to the component.\n * This also checks that they are of the correct type.\n */\nfunction labelAccessibilityValidator(\n  props: Record<string, unknown>,\n  _: string,\n  componentName: string\n) {\n  if (!props.label && !props['aria-label']) {\n    return new Error(\n      `\\`label\\` or \\`aria-label\\` must be supplied to \\`${componentName}\\`. Validation failed.`\n    );\n  }\n\n  if (props.label && typeof props.label !== 'string') {\n    return new Error(\n      `Invalid prop \\`label\\` of type \\`${typeof props.label}\\` supplied to \\`${componentName}\\`, expected \\`string\\`.`\n    );\n  }\n\n  if (props['aria-label'] && typeof props['aria-label'] !== 'string') {\n    return new Error(\n      `Invalid prop \\`aria-label\\` of type \\`${typeof props[\n        'aria-label'\n      ]}\\` supplied to \\`${componentName}\\`, expected \\`string\\`.`\n    );\n  }\n\n  return null;\n}\n\nexport default labelAccessibilityValidator;\n"
  },
  {
    "path": "packages/design-system/src/utils/localStore.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { trackError } from '@googleforcreators/tracking';\n\nexport const LOCAL_STORAGE_PREFIX = {\n  PANEL: 'web_stories_ui_panel_settings',\n  TEXT_SET_SETTINGS: 'web_stores_text_set_settings',\n  TERMS_MEDIA3P: 'web_stories_media3p_terms_agreement',\n  VIDEO_OPTIMIZATION_DIALOG_DISMISSED:\n    'web_stories_video_optimization_dialog_dismissed',\n  HELP_CENTER: 'web_stories_help_center',\n  DELETE_COLOR_PRESET_DIALOG_DISMISSED:\n    'web_stories_delete_color_preset_dialog_dismissed',\n  DELETE_STYLE_PRESET_DIALOG_DISMISSED:\n    'web_stories_delete_style_preset_dialog_dismissed',\n  DEFAULT_VIEW_PAGE_TEMPLATE_LAYOUT: 'web_stories_default_template_view',\n  BACKGROUND_IS_SET_DIALOG_DISMISSED:\n    'web_stories_background_is_set_dialog_dismissed',\n  CORS_CHECK_DIALOG_DISMISSED: 'web_stories_cors_check_dialog_dismissed',\n  MEDIA_RECORDING_AUDIO_INPUT: 'web_stories_media_recording_audio_input',\n  MEDIA_RECORDING_VIDEO_INPUT: 'web_stories_media_recording_video_input',\n  ELEMENT_TOOLBAR_SETTINGS: 'web_stories_toolbar_settings',\n  MEDIA_RECORDING_VIDEO_EFFECT: 'web_stories_media_recording_video_effect',\n};\n\nfunction getItemByKey(key: string): unknown {\n  let parsed: unknown = null;\n  try {\n    const stored = localStorage.getItem(key);\n    parsed = stored !== null ? JSON.parse(stored) : stored;\n  } catch (err) {\n    if (err instanceof Error) {\n      void trackError('local_storage_read', err.message);\n    }\n  }\n  return parsed;\n}\n\nfunction setItemByKey(key: string, data: unknown) {\n  try {\n    localStorage.setItem(key, JSON.stringify(data));\n  } catch (err) {\n    if (err instanceof Error) {\n      void trackError('local_storage_write', err.message);\n    }\n  }\n}\n\nexport const localStore = {\n  getItemByKey,\n  setItemByKey,\n};\n"
  },
  {
    "path": "packages/design-system/src/utils/noop.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const noop = () => undefined;\n"
  },
  {
    "path": "packages/design-system/src/utils/panelSections.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PanelTypes from './panelTypes';\n\nexport enum STYLE_PANE_IDS {\n  Selection = 'selection',\n  Link = 'link',\n  Animation = 'animation',\n}\n\nconst { Link, Animation, ...panelsExcludingLinkAndAnimation } = PanelTypes;\n\nexport const PanelSections = {\n  [STYLE_PANE_IDS.Selection]: Object.values(panelsExcludingLinkAndAnimation),\n  [STYLE_PANE_IDS.Link]: [Link],\n  [STYLE_PANE_IDS.Animation]: [Animation],\n};\n"
  },
  {
    "path": "packages/design-system/src/utils/panelTypes.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nenum PanelTypes {\n  ElementAlignment = 'elementAlignment',\n  PageBackground = 'pageBackground',\n  PageAdvancement = 'pageAdvancement',\n  PageAttachment = 'pageAttachment',\n  PageBackgroundAudio = 'pageBackgroundAudio',\n  SizePosition = 'sizePosition',\n  TextStyle = 'textStyle',\n  TextAccessibility = 'textAccessibility',\n  Filter = 'filter',\n  ShapeStyle = 'shapeStyle',\n  Border = 'borderStyle',\n  Animation = 'animation',\n  VideoOptions = 'videoOptions',\n  VideoSegment = 'videoSegment',\n  Captions = 'captions',\n  Link = 'link',\n  ImageAccessibility = 'imageAccessibility',\n  VideoAcessibility = 'videoAccessibility',\n  Product = 'product',\n  AudioSticker = 'audioSticker',\n}\n\nexport default PanelTypes;\n"
  },
  {
    "path": "packages/design-system/src/utils/sessionStore.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { trackError } from '@googleforcreators/tracking';\n\nexport const SESSION_STORAGE_PREFIX = {\n  LOCAL_AUTOSAVE_PREFIX: 'wp_stories_autosave_story',\n};\n\nexport function getItemByKey(key: string) {\n  let parsed;\n  try {\n    const stored = window.sessionStorage.getItem(key);\n    if (stored) {\n      parsed = JSON.parse(stored) as unknown;\n    }\n  } catch (err) {\n    if (err instanceof Error) {\n      void trackError('session_storage_read', err.message);\n    }\n  }\n\n  return parsed;\n}\n\nexport function setItemByKey(key: string, data: Record<string, unknown>) {\n  try {\n    window.sessionStorage.setItem(key, JSON.stringify(data));\n  } catch (err) {\n    if (err instanceof Error) {\n      void trackError('session_storage_write', err.message);\n    }\n  }\n}\n\nexport function deleteItemByKey(key: string) {\n  try {\n    window.sessionStorage.removeItem(key);\n  } catch (err) {\n    if (err instanceof Error) {\n      void trackError('session_storage_delete', err.message);\n    }\n  }\n}\n\nexport const sessionStore = {\n  getItemByKey,\n  setItemByKey,\n  deleteItemByKey,\n};\n"
  },
  {
    "path": "packages/design-system/src/utils/test/deepMerge.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport deepMerge from '../deepMerge';\n\nconst object1 = {\n  b: {\n    c: {\n      d: {\n        e: 'e',\n        f: 'f',\n      },\n    },\n  },\n  g: 'g',\n  h: 'h',\n  i: 'i',\n  x: 'y',\n  z: {\n    dates: ['Jan', 'Feb'],\n  },\n};\n\nconst object2 = {\n  a: 'a',\n  b: {\n    c: {\n      d: {\n        e: 'not e',\n        g: 'g',\n      },\n    },\n  },\n  g: undefined,\n  h: null,\n  i: 'undefined',\n  x: 'y',\n  z: {\n    dates: ['Jan', 'Feb', 'March'],\n  },\n};\nconst expectedResult = {\n  a: 'a',\n  b: {\n    c: {\n      d: {\n        e: 'not e',\n        f: 'f',\n        g: 'g',\n      },\n    },\n  },\n  x: 'y',\n  g: 'g',\n  h: null,\n  i: 'undefined',\n  z: {\n    dates: ['Jan', 'Feb', 'March'],\n  },\n};\n\ndescribe('deepMerge', () => {\n  it.each`\n    object       | source       | result\n    ${undefined} | ${undefined} | ${undefined}\n    ${{}}        | ${undefined} | ${{}}\n    ${object1}   | ${undefined} | ${object1}\n    ${object1}   | ${{}}        | ${object1}\n    ${object1}   | ${object2}   | ${expectedResult}\n  `(\n    'should return merged object for $object and $source',\n    ({ object, source, result }) => {\n      expect(deepMerge(object, source)).toStrictEqual(result);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/design-system/src/utils/test/labelAccessibilityValidator.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport labelAccessibilityValidator from '../labelAccessibilityValidator';\n\ndescribe('labelAccessibilityValidator', () => {\n  it('should return null if `label` or `aria-label` are passed in as a prop', () => {\n    expect(\n      labelAccessibilityValidator({ label: 'test' }, '', 'Test')\n    ).toBeNull();\n    expect(\n      labelAccessibilityValidator({ 'aria-label': 'test' }, '', 'Test')\n    ).toBeNull();\n    expect(\n      labelAccessibilityValidator(\n        { label: 'test', 'aria-label': 'test' },\n        '',\n        'Test'\n      )\n    ).toBeNull();\n  });\n\n  it.each`\n    propName\n    ${'label'}\n    ${'aria-label'}\n  `('should throw an error if `label` is not a string type', ({ propName }) => {\n    expect(\n      labelAccessibilityValidator({ [propName]: 2 }, '', 'Test')\n    ).toStrictEqual(expect.any(Error));\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/utils/test/uniqueEntriesByKey.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport uniqueEntriesByKey from '../uniqueEntriesByKey';\n\ndescribe('uniqueEntriesByKey', () => {\n  it('should return unique entries by specified key', () => {\n    const entries = [\n      { id: 1, name: 'a' },\n      { id: 2, name: 'a' },\n      { id: 1, name: 'b' },\n      { id: 2, name: 'b' },\n      { id: 1, name: 'c' },\n    ];\n    expect(uniqueEntriesByKey(entries, 'id')).toStrictEqual([\n      { id: 1, name: 'c' },\n      { id: 2, name: 'b' },\n    ]);\n    expect(uniqueEntriesByKey(entries, 'name')).toStrictEqual([\n      { id: 2, name: 'a' },\n      { id: 2, name: 'b' },\n      { id: 1, name: 'c' },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/utils/test/useLiveRegion.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useLiveRegion from '../useLiveRegion';\nimport { queryById } from '../../testUtils';\n\ndescribe('useLiveRegion', () => {\n  it('should add message to live region', () => {\n    const { result } = renderHook(() => useLiveRegion());\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toBeEmptyDOMElement();\n\n    act(() => {\n      result.current('Hello World');\n    });\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toHaveTextContent('Hello World');\n  });\n\n  it('should change the politeness of the message', () => {\n    const { result } = renderHook(() => useLiveRegion('assertive'));\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).not.toBeInTheDocument();\n    expect(\n      queryById(\n        document.documentElement,\n        'web-stories-aria-live-region-assertive'\n      )\n    ).toBeEmptyDOMElement();\n\n    act(() => result.current('Hello World'));\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).not.toBeInTheDocument();\n    expect(\n      queryById(\n        document.documentElement,\n        'web-stories-aria-live-region-assertive'\n      )\n    ).toHaveTextContent('Hello World');\n  });\n\n  it('should remove container when unmounting', () => {\n    const { unmount } = renderHook(() => useLiveRegion());\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toBeEmptyDOMElement();\n\n    unmount();\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).not.toBeInTheDocument();\n  });\n\n  it('should clear existing messages', () => {\n    const { result } = renderHook(() => useLiveRegion());\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toBeEmptyDOMElement();\n\n    act(() => {\n      result.current('Foo');\n      result.current('Bar');\n    });\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).not.toHaveTextContent('Foo');\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toHaveTextContent('Bar');\n  });\n\n  it('should not add multiple containers', () => {\n    renderHook(() => {\n      useLiveRegion();\n      useLiveRegion();\n    });\n\n    expect(\n      queryById(document.documentElement, 'web-stories-aria-live-region-polite')\n    ).toBeEmptyDOMElement();\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/utils/test/useMouseDownOutside.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport useMouseDownOutsideRef from '../useMouseDownOutsideRef';\n\ndescribe('useMouseDownOutsideRef', () => {\n  const TestComponent = ({\n    handleMouseDownOutside,\n\n    childTestId = 'child',\n\n    containerTestId = 'container',\n  }) => {\n    const ref = useMouseDownOutsideRef(handleMouseDownOutside);\n    return (\n      <div ref={ref} data-testid={containerTestId}>\n        <button data-testid={childTestId}>{'click me!'}</button>\n      </div>\n    );\n  };\n\n  it('fires when a user mouses down outside of the referenced node', () => {\n    const handleMouseDownOutside = jest.fn();\n    render(\n      <div>\n        <div data-testid=\"some-element\" />\n        <TestComponent handleMouseDownOutside={handleMouseDownOutside} />\n      </div>\n    );\n\n    const elementOutsideContextMenu = screen.getByTestId('some-element');\n\n    fireEvent.mouseDown(elementOutsideContextMenu);\n\n    expect(handleMouseDownOutside).toHaveBeenCalledOnce();\n  });\n\n  it('does not fire when a user mouses down on the referenced node', () => {\n    const handleMouseDownOutside = jest.fn();\n    const containerTestId = 'containerTestId';\n    render(\n      <div>\n        <div data-testid=\"some-element\" />\n        <TestComponent\n          handleMouseDownOutside={handleMouseDownOutside}\n          containerTestId={containerTestId}\n        />\n      </div>\n    );\n\n    const containerNode = screen.getByTestId(containerTestId);\n\n    fireEvent.mouseDown(containerNode);\n\n    expect(handleMouseDownOutside).toHaveBeenCalledTimes(0);\n  });\n\n  it('does not fire when a user mouses down on a child of the referenced node', () => {\n    const handleMouseDownOutside = jest.fn();\n    const childTestId = 'childTestId';\n    render(\n      <div>\n        <div data-testid=\"some-element\" />\n        <TestComponent\n          handleMouseDownOutside={handleMouseDownOutside}\n          childTestId={childTestId}\n        />\n      </div>\n    );\n\n    const childNode = screen.getByTestId(childTestId);\n\n    fireEvent.mouseDown(childNode);\n\n    expect(handleMouseDownOutside).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/design-system/src/utils/uniqueEntriesByKey.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Takes an array of entries and returns an array of unique\n * entries based on the supplied key value for each entry\n */\nfunction uniqueEntriesByKey<\n  O extends Record<string, unknown>,\n  K extends keyof O,\n>(entries: O[], key: K) {\n  const map = new Map<unknown, O>();\n  entries.forEach((entry) => {\n    map.set(entry[key], entry);\n  });\n  return [...map.values()];\n}\n\nexport default uniqueEntriesByKey;\n"
  },
  {
    "path": "packages/design-system/src/utils/useForwardedRef.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport type { RefObject } from 'react';\n\nfunction useForwardedRef<T>(ref: React.ForwardedRef<T>) {\n  const wrappedRef = useRef<{ current: T | null }>({ current: null });\n  const referenceRef = useRef<T | null>(null);\n\n  Object.defineProperty(wrappedRef.current, 'current', {\n    get: () => referenceRef.current,\n    set: (value: T | null) => {\n      if (!Object.is(referenceRef.current, value)) {\n        referenceRef.current = value;\n        if (!ref) {\n          return;\n        }\n        if (typeof ref === 'function') {\n          ref(referenceRef.current);\n        } else {\n          // eslint-disable-next-line react-hooks/immutability -- FIXME\n          ref.current = referenceRef.current;\n        }\n      }\n    },\n  });\n\n  return wrappedRef.current as RefObject<T>;\n}\n\nexport default useForwardedRef;\n"
  },
  {
    "path": "packages/design-system/src/utils/useLiveRegion.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useRef } from '@googleforcreators/react';\n\n/**\n * Add messages to an ARIA live region.\n *\n * It’s possible that all the region content will be announced after an update\n * if the ARIA live region is too large.\n *\n * Please only provide users with just a simple, concise message.\n */\nfunction useLiveRegion(politeness: 'polite' | 'assertive' = 'polite') {\n  const elementRef = useRef<HTMLElement | null>(null);\n\n  const ensureContainerExists = useCallback(() => {\n    if (elementRef.current) {\n      return () => {\n        if (elementRef.current) {\n          document.body.removeChild(elementRef.current);\n          elementRef.current = null;\n        }\n      };\n    }\n\n    const containerId = 'web-stories-aria-live-region-' + politeness;\n\n    const existingContainer = document.getElementById(containerId);\n\n    if (existingContainer) {\n      elementRef.current = existingContainer;\n      return () => {\n        elementRef.current = null;\n      };\n    }\n\n    const container = document.createElement('div');\n    container.id = containerId;\n    container.className = 'web-stories-aria-live-region';\n\n    container.setAttribute(\n      'style',\n      'position: absolute;' +\n        'margin: -1px;' +\n        'padding: 0;' +\n        'height: 1px;' +\n        'width: 1px;' +\n        'overflow: hidden;' +\n        'clip: rect(1px, 1px, 1px, 1px);' +\n        '-webkit-clip-path: inset(50%);' +\n        'clip-path: inset(50%);' +\n        'border: 0;' +\n        'word-wrap: normal !important;'\n    );\n    container.setAttribute('aria-live', politeness);\n    container.setAttribute('aria-relevant', 'additions text');\n    container.setAttribute('aria-atomic', 'true');\n\n    document.body.appendChild(container);\n    elementRef.current = container;\n\n    return () => {\n      document.body.removeChild(container);\n      elementRef.current = null;\n    };\n  }, [politeness]);\n\n  useEffect(ensureContainerExists, [ensureContainerExists]);\n\n  /**\n   * Add message to aria live region so it can be announced by\n   * a screen reader.\n   */\n  const speak = useCallback(\n    (message: string) => {\n      if (!elementRef.current) {\n        return;\n      }\n      ensureContainerExists();\n\n      // Clear any existing messages.\n      const regions = document.querySelectorAll(\n        '.web-stories-aria-live-region'\n      );\n      for (const region of regions) {\n        region.textContent = '';\n      }\n\n      elementRef.current.textContent = message;\n    },\n    [ensureContainerExists]\n  );\n\n  return speak;\n}\n\nexport default useLiveRegion;\n"
  },
  {
    "path": "packages/design-system/src/utils/useMouseDownOutsideRef.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useRef, useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { noop } from './noop';\n\n/**\n * Takes a handler for mouseDownOutside event and returns a ref\n * to attach to the desired element you want to detect outside\n * mouse down events\n */\nfunction useMouseDownOutsideRef<E extends HTMLElement>(\n  onMouseDownOutside: (evt: MouseEvent) => void = noop\n) {\n  const targetRef = useRef<Node | null>(null);\n  // store handler outside of useCallback so we have the\n  // proper references when removing listeners\n  const handleDocumentClickCaptureRef = useRef<(evt: MouseEvent) => void>(noop);\n  const onMouseDownOutsideRef = useRef(onMouseDownOutside);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  onMouseDownOutsideRef.current = onMouseDownOutside;\n\n  return useCallback((node: E) => {\n    // clean up listeners associated with the previous node\n    if (targetRef.current) {\n      document.removeEventListener(\n        'mousedown',\n        handleDocumentClickCaptureRef.current,\n        true\n      );\n    }\n\n    // create and attach listeners with new node\n    if (node) {\n      handleDocumentClickCaptureRef.current = (evt: MouseEvent) => {\n        if (\n          node === evt.target ||\n          (evt.target instanceof Node && node.contains(evt.target))\n        ) {\n          return;\n        }\n        onMouseDownOutsideRef.current?.(evt);\n      };\n\n      document.addEventListener(\n        'mousedown',\n        handleDocumentClickCaptureRef.current,\n        true\n      );\n    }\n\n    targetRef.current = node;\n  }, []);\n}\n\nexport default useMouseDownOutsideRef;\n"
  },
  {
    "path": "packages/design-system/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../tracking\" }\n  ],\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/dom/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/dom/README.md",
    "content": "# DOM\n\nDOM utility package for Web Stories editor.\n"
  },
  {
    "path": "packages/dom/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/dom\",\n  \"description\": \"DOM utility package for Web Stories editor\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/dom/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/dom\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/dom/src/ensureFontLoaded.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Check whether a font has been loaded already.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/check\n *\n * @param fontFaceSet A font specification using the CSS value syntax, for example \"italic bold 16px Roboto\"\n * @param content Limit the font faces to those whose Unicode range contains at least one of the characters in text.\n * @return True if the font is loaded.\n */\nexport default function ensureFontLoaded(fontFaceSet: string, content: string) {\n  if (!document?.fonts) {\n    return Promise.resolve(true);\n  }\n\n  return document.fonts\n    .load(fontFaceSet, content || '')\n    .then(() => document.fonts.check(fontFaceSet, content || ''));\n}\n"
  },
  {
    "path": "packages/dom/src/escapeHTML.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst buffer = document.createElement('div');\n\nexport default function escapeHTML(string: string) {\n  // @todo: implement a cheaper way to escape HTML characters.\n  buffer.textContent = string;\n  return buffer.innerHTML;\n}\n"
  },
  {
    "path": "packages/dom/src/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as stripHTML } from './stripHTML';\nexport { default as escapeHTML } from './escapeHTML';\nexport { default as ensureFontLoaded } from './ensureFontLoaded';\nexport * from './loadStylesheet';\n"
  },
  {
    "path": "packages/dom/src/loadStylesheet.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function loadStylesheet(url: string, id: string) {\n  return new Promise((resolve, reject) => {\n    const link = document.createElement('link');\n    link.id = id;\n    link.rel = 'stylesheet';\n    link.href = url;\n    link.crossOrigin = 'anonymous';\n    link.addEventListener('load', resolve);\n    link.addEventListener('error', reject);\n    document.head.appendChild(link);\n  });\n}\n\n/**\n * Enqueue an inline stylesheet for a given font family and URL.\n *\n * @param id Element ID.\n * @param css  Css to load inline\n */\nexport function loadInlineStylesheet(id: string, css: string) {\n  if (!css) {\n    return;\n  }\n\n  const style = document.createElement('style');\n  style.textContent = css;\n  style.id = id;\n  document.head.appendChild(style);\n}\n"
  },
  {
    "path": "packages/dom/src/stripHTML.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst parser = new DOMParser();\n\nexport default function stripHTML(string: string) {\n  // @todo: implement a cheaper way to strip markup.\n  const doc = parser.parseFromString(string, 'text/html');\n  return doc.body.textContent || '';\n}\n"
  },
  {
    "path": "packages/dom/src/test/escapeHTML.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport escapeHTML from '../escapeHTML';\n\ndescribe('escapeHTML', () => {\n  it('should escape HTML', () => {\n    expect(escapeHTML('<div>Hello & World</div>')).toBe(\n      '&lt;div&gt;Hello &amp; World&lt;/div&gt;'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/dom/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/README.md",
    "content": "# E2E test utils\n\nA set of e2e utils for web stories tests.\n"
  },
  {
    "path": "packages/e2e-test-utils/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/e2e-test-utils\",\n  \"description\": \"Utils for running e2e tests for the WordPress Web Stories editor\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/e2e-test-utils/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/e2e-test-utils\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@wordpress/url\": \"^4.43.0\",\n    \"expect-puppeteer\": \"^11.0.0\"\n  },\n  \"devDependencies\": {\n    \"@percy/puppeteer\": \"^2.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/activatePlugin.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getCurrentUser, setCurrentUser } from './user';\nimport visitAdminPage from './visitAdminPage';\n\nasync function activatePlugin(slug) {\n  const currentUser = getCurrentUser();\n  await setCurrentUser('admin', 'password');\n\n  await visitAdminPage('plugins.php');\n  const disableLink = await page.$(`tr[data-slug=\"${slug}\"] .deactivate a`);\n\n  if (!disableLink) {\n    await page.click(`tr[data-slug=\"${slug}\"] .activate a`);\n    await page.waitForSelector(`tr[data-slug=\"${slug}\"] .deactivate a`);\n  }\n\n  await setCurrentUser(currentUser.username, currentUser.password);\n}\nexport default activatePlugin;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/activateRTL.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Creates a new story.\n */\nasync function activateRTL() {\n  await visitAdminPage('plugins.php', 'd=rtl');\n}\n\nexport default activateRTL;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/addRequestInterception.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Add a request handler for intercepting requests.\n *\n * Used intercept HTTP requests during tests with a custom handler function.\n * Returns a function that, when called, stops further request\n * handling/interception.\n *\n * @param  {Function} callback Function to handle requests.\n * @return {Function} Function that can be called to remove the added handler function from the page.\n */\nfunction addRequestInterception(callback) {\n  const requestHandler = (request) => {\n    // Prevent errors for requests that happen after interception is disabled.\n    if (request.isInterceptResolutionHandled()) {\n      return;\n    }\n\n    callback(request);\n  };\n\n  page.on('request', requestHandler);\n\n  return () => {\n    page.off('request', requestHandler);\n  };\n}\n\nexport default addRequestInterception;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/addTextElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default async function addTextElement(preset = 'Paragraph') {\n  await page.waitForSelector('#library-tab-text');\n  await page.click('#library-tab-text');\n  await expect(page).toClick('#library-pane-text button', { text: preset });\n  await expect(page).toMatchElement('[data-testid=\"textFrame\"]', {\n    text: 'Paragraph' === preset ? 'Fill in some text' : preset,\n  });\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/checkVersion.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction checkVersion(a, b) {\n  const x = a.split('.').map((e) => Number.parseInt(e));\n  const y = b.split('.').map((e) => Number.parseInt(e));\n\n  // eslint-disable-next-line guard-for-in\n  for (const i in x) {\n    y[i] = y[i] || 0;\n    if (x[i] === y[i]) {\n      continue;\n    } else {\n      return x[i] > y[i];\n    }\n  }\n  return !(y.length > x.length);\n}\nexport default checkVersion;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/config.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst WP_ADMIN_USER = {\n  username: 'admin',\n  password: 'password',\n};\n\nconst {\n  WP_USERNAME = WP_ADMIN_USER.username,\n  WP_PASSWORD = WP_ADMIN_USER.password,\n  WP_BASE_URL = 'http://localhost:8889',\n} = process.env;\n\nexport { WP_ADMIN_USER, WP_USERNAME, WP_PASSWORD, WP_BASE_URL };\n"
  },
  {
    "path": "packages/e2e-test-utils/src/createNewPost.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport { addQueryArgs } from '@wordpress/url';\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport loadPostEditor from './loadPostEditor.js';\n/**\n * Creates new post.\n *\n * @param {Object}  object                    Object to create new post, along with tips enabling option.\n * @param {string}  [object.postType]         Post type of the new post.\n * @param {string}  [object.title]            Title of the new post.\n * @param {string}  [object.content]          Content of the new post.\n * @param {string}  [object.excerpt]          Excerpt of the new post.\n * @param {boolean} [object.showWelcomeGuide] Whether to show the welcome guide.\n */\nasync function createNewPost({\n  postType,\n  title,\n  content,\n  excerpt,\n  showWelcomeGuide = false,\n} = {}) {\n  const query = addQueryArgs('', {\n    post_type: postType,\n    post_title: title,\n    content,\n    excerpt,\n  }).slice(1);\n  await visitAdminPage('post-new.php', query);\n  await loadPostEditor(showWelcomeGuide);\n}\nexport default createNewPost;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/createNewStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Creates a new story.\n */\nasync function createNewStory() {\n  await visitAdminPage('post-new.php', 'post_type=web-story');\n}\n\nexport default createNewStory;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/createNewTerm.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Creates a new term in a given taxonomy.\n *\n * @param {string} taxonomy Taxonomy name\n * @param {string} term Term name.\n * @param {string} [parent] Parent term name.\n */\nasync function createNewTerm(taxonomy, term, parent) {\n  await visitAdminPage('edit-tags.php', `taxonomy=${taxonomy}`);\n\n  await expect(page).toMatchElement('input#tag-name');\n  await page.type('input#tag-name', term);\n\n  if (parent) {\n    await expect(page).toSelect('#parent', parent);\n  }\n\n  await page.click('#submit');\n\n  await expect(page).toMatchElement('td.slug', {\n    text: term.replaceAll(' ', '-'),\n  });\n}\n\nexport default createNewTerm;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/createURL.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { join } from 'path';\n\n/**\n * Internal dependencies\n */\nimport { WP_BASE_URL } from './config';\n\n/**\n * Creates new URL by parsing base URL, path and query string.\n *\n * @param {string}  path String to be serialized as pathname.\n * @param {?string} query  String to be serialized as query portion of URL.\n * @return {string} String which represents full URL.\n */\nfunction createURL(path, query = '') {\n  const url = new URL(WP_BASE_URL);\n\n  url.pathname = join(url.pathname, path);\n  url.search = query;\n\n  return url.href;\n}\n\nexport default createURL;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/customFonts.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction parseText(optionsText) {\n  return optionsText.map((option) => {\n    const [name, url] = option.split('\\n');\n    return { name, url };\n  });\n}\n\nexport const removeAllFonts = async () => {\n  const fonts = await getFontList();\n\n  if (fonts.length === 0) {\n    return;\n  }\n\n  for (let i = 0; i < fonts.length; i++) {\n    // eslint-disable-next-line no-await-in-loop -- Can't be done in parallel because of the confirmation dialog.\n    await removeCustomFont(fonts[i].name);\n  }\n\n  const fontsAfter = await getFontList();\n  await expect(fontsAfter).toHaveLength(0);\n};\n\n/**\n * @typedef {Object} FontData font data parsed from custom font listbox\n * @property {string} name font family name.\n * @property {string} url url for font.\n */\n\n/**\n * Get array of fonts that have been added\n *\n * @return {Promise<[FontData]>} Fonts list.\n */\nexport const getFontList = async () => {\n  try {\n    const optionsText = await page.evaluate(() =>\n      Array.from(\n        document.querySelectorAll(\n          'div[role=listbox] [role=option] div:first-child'\n        ),\n        (element) => element.innerText\n      )\n    );\n    return parseText(optionsText);\n  } catch {\n    return [];\n  }\n};\n\n/**\n * Add a custom font on the settings page.\n *\n * @param {string} fontUrl Font URL.\n * @return {Promise<void>}\n */\nexport const addCustomFont = async (fontUrl) => {\n  await expect(page).toMatchTextContent('Custom Fonts');\n\n  await expect(page).toClick('label', {\n    text: 'Insert Font URL',\n  });\n\n  await page.waitForFunction(\n    () => document.activeElement.tagName.toLowerCase() === 'input'\n  );\n\n  await page.keyboard.type(fontUrl);\n  await Promise.all([\n    expect(page).toClick('button', { text: 'Add Font' }),\n    page.waitForResponse((response) => response.url() === fontUrl),\n    page.waitForResponse((response) =>\n      response.url().includes('web-stories/v1/font')\n    ),\n  ]);\n  await expect(page).toMatchElement('[role=\"option\"]', { text: fontUrl });\n};\n\n/**\n * Remove a custom font from the settings page.\n *\n * @param {string} fontName fontName to delete\n * @return {Promise<void>}\n */\nexport const removeCustomFont = async (fontName) => {\n  await expect(page).toMatchTextContent('Custom Fonts');\n\n  const numberOfFonts = await page.evaluate(() => {\n    return document.querySelector('div[role=listbox]')?.children?.length || 0;\n  });\n\n  if (0 === numberOfFonts) {\n    return;\n  }\n\n  const selector = `[aria-label=\"Delete ${fontName}\"]`;\n  await page.waitForSelector(selector);\n  await page.focus(selector);\n  await page.click(selector);\n  await page.waitForSelector('[role=\"dialog\"]');\n  await expect(page).toClick('button', { text: 'Delete Font' });\n  await page.waitForFunction(\n    (expectedNumberOfFonts) => {\n      const count =\n        document.querySelector('div[role=listbox]')?.children?.length || 0;\n      return count === expectedNumberOfFonts;\n    },\n    {},\n    numberOfFonts - 1\n  );\n};\n"
  },
  {
    "path": "packages/e2e-test-utils/src/deactivatePlugin.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setCurrentUser, getCurrentUser } from './user';\nimport visitAdminPage from './visitAdminPage';\n\nasync function deactivatePlugin(slug) {\n  const currentUser = getCurrentUser();\n  await setCurrentUser('admin', 'password');\n\n  await visitAdminPage('plugins.php');\n  const deleteLink = await page.$(`tr[data-slug=\"${slug}\"] .delete a`);\n\n  if (!deleteLink) {\n    await page.click(`tr[data-slug=\"${slug}\"] .deactivate a`);\n    await page.waitForSelector(`tr[data-slug=\"${slug}\"] .delete a`);\n  }\n\n  await setCurrentUser(currentUser.username, currentUser.password);\n}\n\nexport default deactivatePlugin;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/deactivateRTL.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Creates a new story.\n */\nasync function deactivateRTL() {\n  await visitAdminPage('plugins.php', 'd=ltr');\n}\n\nexport default deactivateRTL;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/deleteAllMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Deletes all manually uploaded attachments from the WordPress media library.\n */\nasync function deleteAllMedia() {\n  await visitAdminPage('upload.php', 'mode=list');\n\n  const itemsToDelete = await page.evaluate(() => {\n    const items = [];\n    document.querySelectorAll('p.filename').forEach((el) => {\n      const currentFileName = el.textContent.replace('File name:', '').trim();\n      if (currentFileName.includes('e2e-')) {\n        items.push(el.closest('tr').id);\n      }\n    });\n    return items;\n  });\n\n  /*eslint-disable no-await-in-loop*/\n  for (const elementId of itemsToDelete) {\n    // Make row actions appear.\n    await page.hover(`#${elementId}`);\n\n    await Promise.all([\n      expect(page).toClick(`#${elementId} a.submitdelete`),\n      page.waitForNavigation(),\n    ]);\n    await page.waitForSelector(`#message`);\n    await expect(page).toMatchTextContent('Media file permanently deleted.');\n  }\n  /*eslint-enable no-await-in-loop*/\n}\n\nexport default deleteAllMedia;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/deleteMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Deletes an attachment with a given file name from the WordPress media library.\n *\n * @param {string} fileName File name with or without extension.\n */\nasync function deleteMedia(fileName) {\n  await visitAdminPage('upload.php', 'mode=list');\n\n  await expect(page).toMatchTextContent(fileName);\n\n  // Make row actions appear.\n  const elementId = await page.evaluate((name) => {\n    let _id;\n    document.querySelectorAll('p.filename').forEach((el) => {\n      const currentFileName = el.textContent.replace('File name:', '').trim();\n      if (currentFileName.startsWith(name)) {\n        _id = el.closest('tr').id;\n      }\n    });\n    return _id;\n  }, fileName);\n\n  await page.hover(`#${elementId}`);\n\n  await Promise.all([\n    expect(page).toClick(`#${elementId} a.submitdelete`),\n    page.waitForNavigation(),\n  ]);\n  await page.waitForSelector(`#message`);\n  await expect(page).toMatchTextContent('Media file permanently deleted.');\n}\n\nexport default deleteMedia;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/deleteWidgets.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport activatePlugin from './activatePlugin';\nimport deactivatePlugin from './deactivatePlugin';\n\nasync function deleteWidgets() {\n  await activatePlugin('classic-widgets');\n\n  // Remove all widgets\n  await visitAdminPage('widgets.php');\n\n  const widgets = await page.$$('#widgets-right .widget');\n\n  /* eslint-disable no-await-in-loop */\n  for (const item of widgets) {\n    await item.$eval('.widget-action', (toggleButton) => toggleButton.click());\n\n    // Transition animation.\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 300));\n\n    await item.$eval('.widget-control-remove', (deleteLink) =>\n      deleteLink.click()\n    );\n\n    // Transition animation.\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 300));\n  }\n  /* eslint-enable no-await-in-loop */\n\n  await deactivatePlugin('classic-widgets');\n}\n\nexport default deleteWidgets;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/disableCheckbox.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport default async function disableCheckbox(selector) {\n  await page.waitForSelector(selector);\n  await page.evaluate((checkbox) => {\n    const node = document.querySelector(checkbox);\n    if (node.checked) {\n      node.click();\n    }\n  }, selector);\n\n  await expect(page).not.toMatchElement(`${selector}:checked`);\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/editStoryWithTitle.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Open an existing story with a specific title in the editor.\n *\n * @param {string} storyTitle Story title.\n * @return {Promise<void>}\n */\nasync function editStoryWithTitle(storyTitle) {\n  await visitAdminPage('edit.php', 'post_type=web-story');\n  await expect(page).toMatchTextContent(storyTitle);\n\n  await Promise.all([\n    page.waitForNavigation(),\n    expect(page).toClick('a', { text: storyTitle }),\n  ]);\n}\n\nexport default editStoryWithTitle;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/enableCheckbox.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport default async function enableCheckbox(selector) {\n  await page.waitForSelector(selector);\n  await page.evaluate((checkbox) => {\n    const node = document.querySelector(checkbox);\n    if (!node.checked) {\n      node.click();\n    }\n  }, selector);\n\n  await expect(page).toMatchElement(`${selector}:checked`);\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/experimentalFeatures.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport { getCurrentUser, setCurrentUser } from './user';\n\n/**\n * Toggle experiments state.\n *\n * @param {Array<string>}features Array of experiments to enable.\n * @param {boolean} enable Whether the features should be enabled or not.\n * @return {Promise<void>}\n */\nexport async function toggleExperiments(features, enable) {\n  const currentUser = getCurrentUser();\n  await setCurrentUser('admin', 'password');\n\n  await visitAdminPage(\n    'edit.php',\n    'post_type=web-story&page=web-stories-experiments'\n  );\n\n  /* eslint-disable no-await-in-loop */\n  for (let i = 0; i < features.length; i++) {\n    const selector = `#${features[i]}`;\n    await page.waitForSelector(selector);\n    const checkedSelector = `${selector}:checked`;\n    const isChecked = Boolean(await page.$(checkedSelector));\n\n    if ((!isChecked && enable) || (isChecked && !enable)) {\n      await page.click(selector);\n    }\n  }\n  /* eslint-enable no-await-in-loop */\n\n  // Ensures the button is visible and can be clicked on in Firefox.\n  await page.evaluate(() => {\n    document.getElementById('submit').scrollIntoView();\n  });\n\n  await Promise.all([page.waitForNavigation(), page.click('#submit')]);\n  await expect(page).toMatchTextContent('Settings saved.');\n  await setCurrentUser(currentUser.username, currentUser.password);\n}\n\n/**\n * Establishes test lifecycle to enable experimental feature for the duration of\n * the grouped test block.\n *\n * @param {Array<string>} features Array of experiments to enable.\n */\nexport default function withExperimentalFeatures(features) {\n  /* eslint-disable require-await */\n  beforeAll(async () => toggleExperiments(features, true));\n  afterAll(async () => toggleExperiments(features, false));\n  /* eslint-enable require-await */\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/getFileName.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst getFileName = (name) => name.split('.').slice(0, -1).join('.');\n\nexport default getFileName;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as createNewStory } from './createNewStory';\nexport { default as previewStory } from './previewStory';\nexport { default as visitDashboard } from './visitDashboard';\nexport { default as visitSettings } from './visitSettings';\nexport { default as addRequestInterception } from './addRequestInterception';\nexport { default as withExperimentalFeatures } from './experimentalFeatures';\nexport { default as withDisabledToolbarOnFrontend } from './toolbarProfileOption';\nexport { default as withUser } from './withUser';\nexport { default as withPlugin } from './withPlugin';\nexport { default as withRTL } from './withRTL';\nexport { default as deactivateRTL } from './deactivateRTL';\nexport { default as activateRTL } from './activateRTL';\nexport { default as publishPost } from './publishPost';\nexport { default as publishStory } from './publishStory';\nexport { default as addTextElement } from './addTextElement';\nexport { default as insertStoryTitle } from './insertStoryTitle';\nexport { default as setAnalyticsCode } from './setAnalyticsCode';\nexport { default as uploadFile } from './uploadFile';\nexport { default as uploadMedia } from './uploadMedia';\nexport { default as uploadPublisherLogo } from './uploadPublisherLogo';\nexport { default as toggleVideoOptimization } from './toggleVideoOptimization';\nexport { default as deleteMedia } from './deleteMedia';\nexport { default as deleteAllMedia } from './deleteAllMedia';\nexport { default as deleteWidgets } from './deleteWidgets';\nexport { default as getFileName } from './getFileName';\nexport { default as trashAllPosts } from './trashAllPosts';\nexport { default as trashAllTerms } from './trashAllTerms';\nexport { default as visitAdminPage } from './visitAdminPage';\nexport {\n  addCustomFont,\n  removeCustomFont,\n  getFontList,\n  removeAllFonts,\n} from './customFonts';\n\nexport { insertProduct, setShoppingProvider } from './shopping';\nexport { setCurrentUser, getCurrentUser } from './user';\nexport { default as activatePlugin } from './activatePlugin';\nexport { default as deactivatePlugin } from './deactivatePlugin';\nexport { default as createNewPost } from './createNewPost';\nexport { default as createNewTerm } from './createNewTerm';\nexport { default as minWPVersionRequired } from './minWPVersionRequired';\nexport { default as visitBlockWidgetScreen } from './visitBlockWidgetScreen';\nexport { default as insertWidget } from './insertWidget';\nexport { default as triggerHighPriorityChecklistSection } from './triggerHighPriorityChecklistSection';\nexport { default as disableCheckbox } from './disableCheckbox';\nexport { default as enableCheckbox } from './enableCheckbox';\nexport { default as takeSnapshot } from './takeSnapshot';\nexport { default as loadPostEditor } from './loadPostEditor';\nexport { default as editStoryWithTitle } from './editStoryWithTitle';\nexport { default as createURL } from './createURL';\n\nexport function setPostContent(content) {\n  return page.evaluate((_content) => {\n    wp.data\n      .dispatch('core/block-editor')\n      .resetBlocks(wp.blocks.parse(_content));\n  }, content);\n}\n\nexport async function clearLocalStorage() {\n  await page.evaluate(() => window.localStorage.clear());\n}\n\nexport async function insertBlock() {\n  await page.evaluate(() =>\n    wp.data\n      .dispatch('core/block-editor')\n      .insertBlock(wp.blocks.createBlock('web-stories/embed', {}))\n  );\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/insertStoryTitle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nasync function insertStoryTitle(title) {\n  await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n  await page.type('input[placeholder=\"Add title\"]', title);\n}\n\nexport default insertStoryTitle;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/insertWidget.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function insertWidget(name) {\n  await expect(page).toMatchElement('#widgets-left .widget-title', {\n    text: name,\n  });\n  await expect(page).toClick('#widgets-left button', {\n    text: `Add widget: ${name}`,\n  });\n  await expect(page).toClick('.widgets-chooser-add', { text: 'Add Widget' });\n\n  await page.waitForResponse(\n    (response) =>\n      response.url().includes('/wp-admin/admin-ajax.php') &&\n      response.status() === 200\n  );\n\n  // Transition animation.\n  // TODO: Remove and replace with waitForSelector or locator API.\n  await new Promise((r) => setTimeout(r, 300));\n\n  await expect(page).toMatchElement('#widgets-right .widget .widget-title', {\n    text: name,\n  });\n\n  await expect(page).toMatchTextContent('Widget Title');\n}\nexport default insertWidget;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/isCurrentURL.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createURL from './createURL.js';\n\n/**\n * Checks if current URL is a WordPress path.\n *\n * @param {string}  path  String to be serialized as pathname.\n * @param {?string} query String to be serialized as query portion of URL.\n * @return {boolean} Boolean represents whether current URL is or not a WordPress path.\n */\nfunction isCurrentURL(path, query = '') {\n  const currentURL = new URL(page.url());\n\n  currentURL.search = query;\n\n  return createURL(path, query) === currentURL.href;\n}\n\nexport default isCurrentURL;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/loadPostEditor.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nasync function loadPostEditor(showWelcomeGuide = false) {\n  await page.waitForSelector('.edit-post-layout');\n  const isWelcomeGuideActive = await page.evaluate(() =>\n    wp.data.select('core/edit-post').isFeatureActive('welcomeGuide')\n  );\n  const isFullscreenMode = await page.evaluate(() =>\n    wp.data.select('core/edit-post').isFeatureActive('fullscreenMode')\n  );\n\n  if (showWelcomeGuide !== isWelcomeGuideActive) {\n    await page.evaluate(() =>\n      wp.data.dispatch('core/edit-post').toggleFeature('welcomeGuide')\n    );\n    await page.reload();\n    await page.waitForSelector('.edit-post-layout');\n  }\n\n  if (isFullscreenMode) {\n    await page.evaluate(() =>\n      wp.data.dispatch('core/edit-post').toggleFeature('fullscreenMode')\n    );\n    await page.waitForSelector('body:not(.is-fullscreen-mode)');\n  }\n}\nexport default loadPostEditor;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/loginUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createURL from './createURL';\nimport isCurrentURL from './isCurrentURL';\n\n/**\n * Performs log in with specified username and password.\n *\n * @param {?string} username String to be used as user credential.\n * @param {?string} password String to be used as user credential.\n */\nasync function loginUser(username, password) {\n  if (!isCurrentURL('wp-login.php')) {\n    await page.goto(createURL('wp-login.php'));\n  }\n\n  // Puppeteer appears to sometimes have issues with typing,\n  // where the first 1-2 characters are simply not typed.\n  // Hence not using page.type() as one would typically use.\n  // Should be OK since there are no event listeners on the login form.\n  // See https://github.com/puppeteer/puppeteer/issues/1648\n\n  await page.evaluate(\n    (value) => (document.getElementById('user_login').value = value),\n    username\n  );\n  await page.evaluate(\n    (value) => (document.getElementById('user_pass').value = value),\n    password\n  );\n\n  await Promise.all([page.waitForNavigation(), page.click('#wp-submit')]);\n\n  await expect(page).not.toMatchElement('#login_error', {\n    text: /Unknown username/i,\n  });\n}\n\nexport default loginUser;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/logoutUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createURL from './createURL';\n\nasync function logoutUser() {\n  await page.goto(createURL('wp-login.php', 'action=logout'));\n  await Promise.all([\n    page.waitForNavigation(),\n    expect(page).toClick('a', { text: 'log out' }),\n  ]);\n\n  await expect(page).toMatchTextContent(/You are now logged out/i);\n}\n\nexport default logoutUser;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/minWPVersionRequired.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport checkVersion from './checkVersion';\n\n/**\n * Check minimum version of WordPress.\n *\n * @param {string} minVersion Minimum require WordPress version.\n */\nfunction minWPVersionRequired(minVersion) {\n  const WPVersion = process.env?.WP_VERSION || 'latest';\n  if ('latest' !== WPVersion && !checkVersion(WPVersion, minVersion)) {\n    //eslint-disable-next-line jest/no-focused-tests\n    test.only('minimum WordPress requirement not met', () => {});\n  }\n}\n\nexport default minWPVersionRequired;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/previewStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** @typedef {import('puppeteer').Page} Page */\n\n/**\n * Attempts to open the story preview in a new tab.\n *\n * @param {boolean} waitForStoryDebugView Whether to wait for the expected dev view.\n * @return {Promise<Page>} Preview page object.\n */\nasync function previewStory(waitForStoryDebugView = true) {\n  await page.waitForSelector('button:not([disabled])[aria-label=\"Preview\"]');\n  await page.click('button:not([disabled])[aria-label=\"Preview\"]');\n\n  const currentTarget = page.target();\n  const previewPageTarget = await browser.waitForTarget(\n    (target) => target.opener() === currentTarget\n  );\n\n  const previewPage = await previewPageTarget.page();\n  await previewPage.waitForSelector('body');\n\n  await previewPage.waitForFunction(\n    () =>\n      document.title.length > 0 &&\n      !document.title.includes('Generating the preview')\n  );\n\n  if (waitForStoryDebugView) {\n    await previewPage.waitForSelector('.i-amphtml-story-dev-tools-header');\n\n    await expect(previewPage).toMatchTextContent(/Preview/i);\n    await expect(previewPage).toMatchTextContent(/Debug/i);\n    await expect(previewPage).toMatchTextContent(/Add device/i);\n  }\n\n  return previewPage;\n}\n\nexport default previewStory;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/publishPost.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nasync function openPublishPanel() {\n  const publishPanelToggle = await page.waitForSelector(\n    '.editor-post-publish-panel__toggle:not([aria-disabled=\"true\"])'\n  );\n  const isEntityPublishToggle = await publishPanelToggle.evaluate((element) =>\n    element.classList.contains('has-changes-dot')\n  );\n  await page.click('.editor-post-publish-panel__toggle');\n\n  // Wait for either the entity save button or the post publish button.\n  if (isEntityPublishToggle) {\n    await page.waitForSelector('.editor-entities-saved-states__save-button');\n  } else {\n    await page.waitForSelector('.editor-post-publish-button');\n  }\n}\n\n/**\n * Custom helper function to publish posts in Gutenberg.\n *\n * Avoids using `disablePrePublishChecks`.\n *\n * The main reason for this is that it calls toggleScreenOption,\n * which itself is rather flaky and sometimes\n * doesn't find the requested element, causing JS errors.\n *\n * Also avoids using the original `publishPost` helper as it often\n * fails waiting for a snackbar message to appear.\n * Instead, we wait to receive the post's updated permalink.\n *\n * @see https://github.com/WordPress/gutenberg/blob/f96bd6b6fdfca02d47edce8c2f0d68dccf3a37be/packages/e2e-test-utils/src/toggle-screen-option.js#L20-L23\n * @return {Promise<string>} The post's permalink.\n */\nasync function publishPost() {\n  const prePublishChecksEnabled = await page.evaluate(() =>\n    wp.data.select('core/editor').isPublishSidebarEnabled()\n  );\n\n  if (prePublishChecksEnabled) {\n    await openPublishPanel();\n\n    // Wait for the panel to fully slide in.\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 500));\n  }\n\n  // Publish the post\n  await page.click('.editor-post-publish-button');\n\n  // Wait until the selector returns a truthy value.\n  await page.waitForFunction(\n    () =>\n      wp.data.select('core/editor').getEditedPostAttribute('status') ===\n        'publish' &&\n      (document.querySelector(\n        '.editor-post-publish-button[aria-disabled=\"true\"]'\n      ).textContent === 'Update' ||\n        document.querySelector(\n          '.editor-post-publish-button[aria-disabled=\"true\"]'\n        ).textContent === 'Save')\n  );\n\n  // The first time around the selector might return undefined.\n  await page.waitForFunction(() =>\n    wp.data\n      .select('core')\n      .getPostType(wp.data.select('core/editor').getCurrentPostType())\n  );\n\n  // \"View Post\" or \"View Page\", depending on post type,\n  // but always \"View Post\" on older WordPress versions.\n  const linkText = await page.evaluate(\n    () =>\n      wp.data\n        .select('core')\n        .getPostType(wp.data.select('core/editor').getCurrentPostType()).labels\n        .view_item\n  );\n  const linkTextRegex = new RegExp(`^(${linkText}|View Post)`);\n\n  await expect(page).toMatchElement('a', { text: linkTextRegex });\n\n  return page.evaluate(() => wp.data.select('core/editor').getPermalink());\n}\n\nexport default publishPost;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/publishStory.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Publishes the story in the editor.\n *\n * @param {boolean} [dismiss] Whether to dismiss the success dialog.\n * @return {Promise<void>}\n */\nasync function publishStory(dismiss = true) {\n  await expect(page).toClick('button', { text: /^Publish$/ });\n  await expect(page).toMatchElement('div[aria-label=\"Story details\"]');\n  await expect(page).toMatchTextContent('Story Details');\n  await expect(page).toClick('div[aria-label=\"Story details\"] button', {\n    text: /^Publish$/,\n  });\n\n  await expect(page).toMatchTextContent('Story published.');\n\n  await expect(page).toMatchElement('button', { text: /^Dismiss$/ });\n\n  if (dismiss) {\n    await expect(page).toClick('button', { text: /^Dismiss$/ });\n    await expect(page).not.toMatchElement(\n      '[role=\"dialog\"][aria-label=\"Story published.\"]'\n    );\n  }\n}\n\nexport default publishStory;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/setAnalyticsCode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitSettings from './visitSettings';\n\nasync function setAnalyticsCode(code) {\n  await visitSettings();\n\n  const inputSelector =\n    'input[placeholder^=\"Enter your Google Analytics Measurement ID\"]';\n\n  await expect(page).toMatchElement(inputSelector);\n  await page.evaluate(() => {\n    const input = document.getElementById('gaTrackingId');\n    input.value = '';\n  });\n\n  // If empty string, type space and remove it.\n  if (code === '') {\n    await page.type(inputSelector, ' ');\n    await page.keyboard.press('Backspace');\n  } else {\n    await page.type(inputSelector, code);\n  }\n\n  await expect(page).toClick('button', { text: 'Save' });\n  // Wait for setting to save.\n  // TODO: Remove and replace with waitForSelector or locator API.\n  await new Promise((r) => setTimeout(r, 1000));\n}\n\nexport default setAnalyticsCode;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/shopping.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport visitSettings from './visitSettings';\n\nasync function clearSearch() {\n  const hasText = await page.$eval(\n    '[aria-label=\"Product search\"]',\n    (el) => el.value.length\n  );\n  if (hasText >= 1) {\n    await expect(page).toClick('[aria-label=\"Clear product search\"]');\n  }\n}\n\nexport const insertProduct = async (product, clickOnTab = true) => {\n  if (clickOnTab) {\n    // Switch to the Products tab and wait for initial list of products to be fetched.\n    await Promise.all([\n      page.waitForResponse(\n        (response) =>\n          response.url().includes('web-stories/v1/products') &&\n          response.status() === 200\n      ),\n      expect(page).toClick('[aria-controls=\"library-pane-shopping\"]'),\n    ]);\n  }\n\n  await clearSearch();\n  await page.waitForSelector('[aria-label=\"Product search\"]');\n  await page.focus('[aria-label=\"Product search\"]');\n  await page.type('[aria-label=\"Product search\"]', product);\n\n  await Promise.all([\n    page.waitForResponse(\n      (response) =>\n        response.url().includes('web-stories/v1/products') &&\n        response.status() === 200\n    ),\n    page.waitForSelector(`[aria-label=\"Add ${product}\"]`),\n  ]);\n\n  expect(page).toClick(`[aria-label=\"Add ${product}\"]`);\n\n  // TODO: Remove and replace with waitForSelector or locator API.\n  await new Promise((r) => setTimeout(r, 400));\n\n  await page.waitForSelector(\n    '[aria-label=\"Design menu\"] [aria-label=\"Product\"]',\n    { text: product }\n  );\n};\n\nexport const setShoppingProvider = async (provider) => {\n  await visitSettings();\n  // Small trick to ensure we scroll to this input.\n  const shoppingProviderDropdown = await page.$(\n    'button[aria-label=\"Shopping provider\"]'\n  );\n  await shoppingProviderDropdown.focus();\n\n  await expect(page).toClick('button[aria-label=\"Shopping provider\"]');\n\n  await expect(page).toClick('[role=\"listbox\"] li', {\n    text: provider,\n  });\n\n  await expect(page).toMatchTextContent('Setting saved.');\n};\n"
  },
  {
    "path": "packages/e2e-test-utils/src/takeSnapshot.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport percySnapshot from '@percy/puppeteer';\n\nasync function takeSnapshot(page, name, options) {\n  if (!process.env?.PERCY_TOKEN) {\n    return;\n  }\n  await percySnapshot(page, name, options);\n}\n\nexport default takeSnapshot;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/toggleVideoOptimization.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitSettings from './visitSettings';\n\nasync function toggleVideoOptimization() {\n  await visitSettings();\n  const selector = '[data-testid=\"media-optimization-settings-checkbox\"]';\n  await page.waitForSelector(selector);\n  // Clicking will only act on the first element.\n  await expect(page).toClick(selector);\n  // Await REST API request.\n  await page.waitForResponse((response) =>\n    response.url().includes('web-stories/v1/users/me')\n  );\n}\nexport default toggleVideoOptimization;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/toolbarProfileOption.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Toggle experiments state.\n *\n * @param {boolean} enable Whether the option should be enabled or not.\n * @return {Promise<void>}\n */\nasync function toggleToolbarProfileOption(enable) {\n  await visitAdminPage('profile.php');\n\n  const selector = `#admin_bar_front`;\n  await page.waitForSelector(selector);\n  const checkedSelector = `${selector}[checked=checked]`;\n  const isChecked = Boolean(await page.$(checkedSelector));\n  if ((!isChecked && enable) || (isChecked && !enable)) {\n    await page.click(selector);\n  }\n\n  await Promise.all([\n    page.waitForNavigation({ waitUntil: 'networkidle0' }),\n    page.click('#submit'),\n  ]);\n}\n\n/**\n * Establishes test lifecycle to disable the toolbar on the frontend\n * for the duration of the grouped test block.\n */\nexport default function withDisabledToolbarOnFrontend() {\n  beforeAll(() => toggleToolbarProfileOption(false));\n  afterAll(() => toggleToolbarProfileOption(true));\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/trashAllPosts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport { getCurrentUser, setCurrentUser } from './user';\n\n/**\n * Navigates to the post listing screen and bulk-trashes any posts which exist.\n *\n * Note: any lingering locked posts cannot be trashed.\n *\n * @param {string} postType Post type slug.\n * @return {Promise<void>} Promise resolving once posts have been trashed.\n */\nasync function trashAllPosts(postType = 'post') {\n  const currentUser = getCurrentUser();\n  await setCurrentUser('admin', 'password');\n\n  // Visit `/wp-admin/edit.php` so we can see a list of posts and delete them.\n  await visitAdminPage('edit.php', `post_type=${postType}`);\n\n  // If this selector doesn't exist there are no posts for us to delete.\n  const bulkSelector = await page.$('#bulk-action-selector-top');\n  if (bulkSelector) {\n    // Select all posts.\n    await page.waitForSelector('[id^=cb-select-all-]');\n    await page.click('[id^=cb-select-all-]');\n\n    // Select the \"bulk actions\" > \"trash\" option.\n    await page.select('#bulk-action-selector-top', 'trash');\n\n    // Bail early if there were no items selected,\n    // e.g. if there were no posts or if they were all locked.\n    // See https://core.trac.wordpress.org/ticket/45006.\n    const hasSelectedCheckboxes = await page.evaluate(\n      () => document.querySelectorAll('input[name=\"post[]\"]:checked').length > 0\n    );\n\n    if (hasSelectedCheckboxes) {\n      // Submit the form to send all draft/scheduled/published posts to the trash.\n      await Promise.all([page.waitForNavigation(), page.click('#doaction')]);\n    }\n  }\n\n  await setCurrentUser(currentUser.username, currentUser.password);\n}\n\nexport default trashAllPosts;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/trashAllTerms.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport { getCurrentUser, setCurrentUser } from './user';\n\n/**\n * Navigates to the taxonomy's list table and bulk-trashes any terms which exist.\n *\n * @param {string} taxonomy Taxonomy slug.\n * @return {Promise<void>} Promise resolving once terms have been trashed.\n */\nasync function trashAllTerms(taxonomy) {\n  const currentUser = getCurrentUser();\n  await setCurrentUser('admin', 'password');\n\n  await visitAdminPage('edit-tags.php', `taxonomy=${taxonomy}`);\n\n  // If this selector doesn't exist there are no terms for us to delete.\n  const bulkSelector = await page.$('#bulk-action-selector-top');\n  if (bulkSelector) {\n    await page.waitForSelector('[id^=cb-select-all-]');\n    await page.click('[id^=cb-select-all-]');\n    await page.select('#bulk-action-selector-top', 'delete');\n    await Promise.all([page.waitForNavigation(), page.click('#doaction')]);\n  }\n\n  await setCurrentUser(currentUser.username, currentUser.password);\n}\n\nexport default trashAllTerms;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/triggerHighPriorityChecklistSection.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The high priority section of the checklist will show once\n * the story reaches 5 pages\n */\nexport default async function triggerHighPriorityChecklistSection() {\n  await expect(page).toClick('button[aria-label=\"Add New Page\"]');\n  await expect(page).toClick('button[aria-label=\"Add New Page\"]');\n  await expect(page).toClick('button[aria-label=\"Add New Page\"]');\n  await expect(page).toClick('button[aria-label=\"Add New Page\"]');\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/uploadFile.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { join, resolve } from 'path';\nimport { tmpdir } from 'os';\nimport { copyFileSync } from 'fs';\n\n/**\n * Uploads a file to the Media Library, and awaits its upload.\n *\n * The file should reside in packages/e2e-tests/src/assets/.\n *\n * @param {string|null} file The file name to upload, for example 'foo.mp4'.\n * @param {boolean} checkUpload Whether to check if upload was successful.\n * @return {string|null} The name of the file as it was uploaded.\n */\nasync function uploadFile(file, checkUpload = true) {\n  await page.setDefaultTimeout(10000);\n\n  const testMediaPath = resolve(\n    process.cwd(),\n    `packages/e2e-tests/src/assets/${file}`\n  );\n\n  // Prefixing makes it easier to identify files from tests later on.\n  const tmpFileName = join(tmpdir(), `e2e-${file}`);\n  copyFileSync(testMediaPath, tmpFileName);\n\n  // Wait for media modal to appear and upload file.\n  await expect(page).toUploadFile('.media-modal input[type=file]', tmpFileName);\n\n  await page.waitForSelector('.media-uploader-status:not(.uploading)');\n  await page.waitForSelector('.button.media-button-select:not([disabled])');\n  await expect(page).not.toMatchElement('.media-modal .upload-error');\n\n  const fileNameEl = await page.waitForSelector(\n    '.media-modal-content .attachment-details .filename'\n  );\n  const newFileName = await fileNameEl.evaluate((el) => el.textContent);\n\n  if (checkUpload) {\n    const attachmentTitleEl = await page.waitForSelector(\n      '#attachment-details-title'\n    );\n    const attachmentTitle = await attachmentTitleEl.evaluate((el) => el.value);\n    const escapedTitle = attachmentTitle.replace(/\"/g, '\\\\\"');\n    await page.waitForSelector(\n      `.attachments-browser .attachments .attachment[aria-label=\"${escapedTitle}\"]`\n    );\n  }\n  await page.setDefaultTimeout(3000);\n\n  return newFileName;\n}\n\nexport default uploadFile;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/uploadMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport uploadFile from './uploadFile';\n\n/**\n * Helper that upload a file in the media dialog in the stories editor.\n *\n * @param {string} file Name of the file to upload.\n * @param {boolean} exit Whether to exit the media modal.\n * @return {Promise<string>} Uploaded file name.\n */\nasync function uploadMedia(file, exit = true) {\n  await expect(page).toClick('button[aria-label=\"Upload\"]');\n\n  await page.waitForSelector('.media-modal', {\n    visible: true,\n  });\n\n  await expect(page).toClick('.media-modal #menu-item-upload', {\n    text: 'Upload files',\n    visible: true,\n  });\n\n  const fileName = await uploadFile(file);\n\n  if (exit) {\n    await page.keyboard.press('Escape');\n\n    await page.waitForSelector('.media-modal', {\n      visible: false,\n    });\n  }\n\n  return fileName;\n}\n\nexport default uploadMedia;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/uploadPublisherLogo.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { join, resolve } from 'path';\nimport { tmpdir } from 'os';\nimport { copyFileSync } from 'fs';\n\n/**\n * Internal dependencies\n */\nimport getFileName from './getFileName';\n\n/**\n * Helper that upload a publisher logo in the dashboard settings.\n *\n * @param {string} file Filename\n * @param {boolean} checkUpload Check if upload was successful.\n * @return {Promise<string>} Return the filename.\n */\nasync function uploadPublisherLogo(file, checkUpload = true) {\n  await page.setDefaultTimeout(10000);\n\n  const testMediaPath = resolve(\n    process.cwd(),\n    `packages/e2e-tests/src/assets/${file}`\n  );\n\n  // Prefixing makes it easier to identify files from tests later on.\n  const newFileName = `e2e-${file}`;\n  const newBaseName = getFileName(newFileName);\n  const tmpFileName = join(tmpdir(), newFileName);\n  copyFileSync(testMediaPath, tmpFileName);\n\n  await expect(page).toUploadFile('#settings_publisher_logos', tmpFileName);\n\n  if (checkUpload) {\n    await page.waitForSelector(\n      `button[aria-label^=\"Publisher Logo ${newBaseName}\"`\n    );\n  }\n\n  await page.setDefaultTimeout(3000);\n\n  return newBaseName;\n}\n\nexport default uploadPublisherLogo;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/user.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\nimport loginUser from './loginUser';\nimport logoutUser from './logoutUser';\n\nconst current = {\n  username: null,\n  password: null,\n};\n\nexport async function setCurrentUser(username, password) {\n  if (username === null) {\n    return;\n  }\n\n  if (current.username === username) {\n    return;\n  }\n\n  await logoutUser();\n\n  await loginUser(username, password);\n\n  await visitAdminPage('index.php');\n\n  const currentUser = await page.evaluate(\n    () => document.querySelector('.display-name')?.textContent || ''\n  );\n\n  expect(currentUser).toMatch(username);\n\n  await expect(page).toMatchElement('.display-name', {\n    text: username,\n  });\n\n  current.username = username;\n  current.password = password;\n}\n\nexport function getCurrentUser() {\n  return current;\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/visitAdminPage.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { join } from 'path';\n\n/**\n * Internal dependencies\n */\nimport createURL from './createURL';\nimport isCurrentURL from './isCurrentURL';\n\nconst REGEXP_PHP_ERROR =\n  /(<b>)?(Fatal error|Recoverable fatal error|Warning|Parse error|Notice|Strict Standards|Deprecated|Unknown error)(<\\/b>)?: (.*?) in (.*?) on line (<b>)?\\d+(<\\/b>)?/;\n\nasync function getPageError() {\n  const content = await page.content();\n  const match = content.match(REGEXP_PHP_ERROR);\n  return match ? match[0] : null;\n}\n\n/**\n * Visits admin page/\n *\n * @param {string} adminPath String to be serialized as pathname.\n * @param {string} [query] String to be serialized as query portion of URL.\n * @param {string} [hash] Location hash string, e.g. \"/editor-settings\".\n */\nasync function visitAdminPage(adminPath, query = '', hash = '') {\n  const targetUrl =\n    createURL(join('wp-admin', adminPath), query) + (hash ? `#${hash}` : '');\n\n  if (isCurrentURL(targetUrl)) {\n    return;\n  }\n\n  await page.goto(targetUrl);\n\n  // Handle upgrade required screen\n  if (isCurrentURL('wp-admin/upgrade.php')) {\n    // Click update\n    await page.click('.button.button-large.button-primary');\n    // Click continue\n    await page.click('.button.button-large');\n  }\n\n  const error = await getPageError();\n  if (error) {\n    throw new Error('Unexpected error in page content: ' + error);\n  }\n}\n\nexport default visitAdminPage;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/visitBlockWidgetScreen.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Visit block based widget screen, found in WordPress 5.8+ and dismiss welcome message.\n *\n * @return {Promise<void>}\n */\nasync function visitBlockWidgetScreen() {\n  await visitAdminPage('widgets.php');\n\n  // Disable welcome guide if it is enabled.\n  const isWelcomeGuideActive = await page.evaluate(() => {\n    return Boolean(\n      wp.data\n        .select('core/preferences')\n        .get('core/edit-widgets', 'welcomeGuide')\n    );\n  });\n\n  if (isWelcomeGuideActive) {\n    await page.evaluate(() => {\n      wp.data\n        .dispatch('core/preferences')\n        .toggle('core/edit-widgets', 'welcomeGuide');\n    });\n  }\n}\nexport default visitBlockWidgetScreen;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/visitDashboard.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage';\n\n/**\n * Creates a new story.\n */\nasync function visitDashboard() {\n  await visitAdminPage(\n    'edit.php',\n    'post_type=web-story&page=stories-dashboard'\n  );\n}\n\nexport default visitDashboard;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/visitSettings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport visitAdminPage from './visitAdminPage.js';\n\n/**\n * Creates a new story.\n */\nasync function visitSettings() {\n  await visitAdminPage(\n    'edit.php',\n    'post_type=web-story&page=stories-dashboard',\n    '/editor-settings'\n  );\n\n  await expect(page).toMatchElement('h2', { text: 'Settings' });\n}\n\nexport default visitSettings;\n"
  },
  {
    "path": "packages/e2e-test-utils/src/withPlugin.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport activatePlugin from './activatePlugin';\nimport deactivatePlugin from './deactivatePlugin';\n\n/**\n * Establishes test lifecycle to activate a given plugin\n * for the duration of the test.\n *\n * @param {string} slug Plugin slug.\n */\nexport default function withPlugin(slug) {\n  beforeAll(async () => {\n    await activatePlugin(slug);\n  });\n\n  afterAll(async () => {\n    await deactivatePlugin(slug);\n  });\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/withRTL.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport activateRTL from './activateRTL';\nimport deactivateRTL from './deactivateRTL';\n\n/**\n * Establishes test lifecycle to enable RTL mode\n * for the duration of the test.\n */\nexport default function withRTL() {\n  beforeAll(async () => {\n    await activateRTL();\n  });\n\n  afterAll(async () => {\n    await deactivateRTL();\n  });\n}\n"
  },
  {
    "path": "packages/e2e-test-utils/src/withUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getCurrentUser, setCurrentUser } from './user';\n\n/**\n * Establishes test lifecycle to enforce a specific user to be logged in.\n *\n * @param {string} username Username.\n * @param {string} password Password.\n */\nexport default function withUser(username, password) {\n  const currentUser = getCurrentUser();\n\n  /* eslint-disable require-await */\n  beforeAll(async () => setCurrentUser(username, password));\n\n  afterAll(async () =>\n    setCurrentUser(currentUser.username, currentUser.password)\n  );\n  /* eslint-enable require-await */\n}\n"
  },
  {
    "path": "packages/e2e-tests/README.md",
    "content": "# E2E tests\n\nA set of e2e test for web stories editor, dashboard and integrations with plugins.\n"
  },
  {
    "path": "packages/e2e-tests/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/e2e-tests\",\n  \"description\": \"E2E Tests for the WordPress Web Stories editor\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web-stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/e2e-tests/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/e2e-tests\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@web-stories-wp/e2e-test-utils\": \"*\",\n    \"@web-stories-wp/jest-puppeteer-amp\": \"*\",\n    \"@web-stories-wp/jest-resolver\": \"*\",\n    \"@wordpress/jest-console\": \"^8.43.0\",\n    \"babel-jest\": \"^30.3.0\",\n    \"expect-puppeteer\": \"^11.0.0\",\n    \"jest-extended\": \"^6.0.0\",\n    \"jest-json-schema\": \"^6.1.0\",\n    \"jest-puppeteer\": \"^11.0.0\"\n  },\n  \"peerDependencies\": {\n    \"puppeteer\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/e2e-tests/src/assets/README.md",
    "content": "This folder contains example assets that are used for E2E tests.\n\nSee [`install-wordpress.sh`](../../../../bin/local-env/install-wordpress.sh) to see how they are imported into the WordPress media library.\n"
  },
  {
    "path": "packages/e2e-tests/src/assets/test.vtt",
    "content": "WEBVTT\n\n00:11.000 --> 00:13.000\n<v Roger Bingham>We are in New York City\n\n00:13.000 --> 00:16.000\n<v Roger Bingham>We’re actually at the Lucern Hotel, just down the street\n\n00:16.000 --> 00:18.000\n<v Roger Bingham>from the American Museum of Natural History\n\n00:18.000 --> 00:20.000\n<v Roger Bingham>And with me is Neil deGrasse Tyson\n\n00:20.000 --> 00:22.000\n<v Roger Bingham>Astrophysicist, Director of the Hayden Planetarium\n\n00:22.000 --> 00:24.000\n<v Roger Bingham>at the AMNH.\n\n00:24.000 --> 00:26.000\n<v Roger Bingham>Thank you for walking down here.\n\n00:27.000 --> 00:30.000\n<v Roger Bingham>And I want to do a follow-up on the last conversation we did.\n\n00:30.000 --> 00:31.500 align:right size:50%\n<v Roger Bingham>When we e-mailed—\n\n00:30.500 --> 00:32.500 align:left size:50%\n<v Neil deGrasse Tyson>Didn’t we talk about enough in that conversation?\n\n00:32.000 --> 00:35.500 align:right size:50%\n<v Roger Bingham>No! No no no no; 'cos 'cos obviously 'cos\n\n00:32.500 --> 00:33.500 align:left size:50%\n<v Neil deGrasse Tyson><i>Laughs</i>\n\n00:35.500 --> 00:38.000\n<v Roger Bingham>You know I’m so excited my glasses are falling off here.\nWEBVTT\n\n00:11.000 --> 00:13.000\n<v Roger Bingham>We are in New York City\n\n00:13.000 --> 00:16.000\n<v Roger Bingham>We’re actually at the Lucern Hotel, just down the street\n\n00:16.000 --> 00:18.000\n<v Roger Bingham>from the American Museum of Natural History\n\n00:18.000 --> 00:20.000\n<v Roger Bingham>And with me is Neil deGrasse Tyson\n\n00:20.000 --> 00:22.000\n<v Roger Bingham>Astrophysicist, Director of the Hayden Planetarium\n\n00:22.000 --> 00:24.000\n<v Roger Bingham>at the AMNH.\n\n00:24.000 --> 00:26.000\n<v Roger Bingham>Thank you for walking down here.\n\n00:27.000 --> 00:30.000\n<v Roger Bingham>And I want to do a follow-up on the last conversation we did.\n\n00:30.000 --> 00:31.500 align:right size:50%\n<v Roger Bingham>When we e-mailed—\n\n00:30.500 --> 00:32.500 align:left size:50%\n<v Neil deGrasse Tyson>Didn’t we talk about enough in that conversation?\n\n00:32.000 --> 00:35.500 align:right size:50%\n<v Roger Bingham>No! No no no no; 'cos 'cos obviously 'cos\n\n00:32.500 --> 00:33.500 align:left size:50%\n<v Neil deGrasse Tyson><i>Laughs</i>\n\n00:35.500 --> 00:38.000\n<v Roger Bingham>You know I’m so excited my glasses are falling off here.\nWEBVTT\n\n00:11.000 --> 00:13.000\n<v Roger Bingham>We are in New York City\n\n00:13.000 --> 00:16.000\n<v Roger Bingham>We’re actually at the Lucern Hotel, just down the street\n\n00:16.000 --> 00:18.000\n<v Roger Bingham>from the American Museum of Natural History\n\n00:18.000 --> 00:20.000\n<v Roger Bingham>And with me is Neil deGrasse Tyson\n\n00:20.000 --> 00:22.000\n<v Roger Bingham>Astrophysicist, Director of the Hayden Planetarium\n\n00:22.000 --> 00:24.000\n<v Roger Bingham>at the AMNH.\n\n00:24.000 --> 00:26.000\n<v Roger Bingham>Thank you for walking down here.\n\n00:27.000 --> 00:30.000\n<v Roger Bingham>And I want to do a follow-up on the last conversation we did.\n\n00:30.000 --> 00:31.500 align:right size:50%\n<v Roger Bingham>When we e-mailed—\n\n00:30.500 --> 00:32.500 align:left size:50%\n<v Neil deGrasse Tyson>Didn’t we talk about enough in that conversation?\n\n00:32.000 --> 00:35.500 align:right size:50%\n<v Roger Bingham>No! No no no no; 'cos 'cos obviously 'cos\n\n00:32.500 --> 00:33.500 align:left size:50%\n<v Neil deGrasse Tyson><i>Laughs</i>\n\n00:35.500 --> 00:38.000\n<v Roger Bingham>You know I’m so excited my glasses are falling off here.\nWEBVTT\n\n00:11.000 --> 00:13.000\n<v Roger Bingham>We are in New York City\n\n00:13.000 --> 00:16.000\n<v Roger Bingham>We’re actually at the Lucern Hotel, just down the street\n\n00:16.000 --> 00:18.000\n<v Roger Bingham>from the American Museum of Natural History\n\n00:18.000 --> 00:20.000\n<v Roger Bingham>And with me is Neil deGrasse Tyson\n\n00:20.000 --> 00:22.000\n<v Roger Bingham>Astrophysicist, Director of the Hayden Planetarium\n\n00:22.000 --> 00:24.000\n<v Roger Bingham>at the AMNH.\n\n00:24.000 --> 00:26.000\n<v Roger Bingham>Thank you for walking down here.\n\n00:27.000 --> 00:30.000\n<v Roger Bingham>And I want to do a follow-up on the last conversation we did.\n\n00:30.000 --> 00:31.500 align:right size:50%\n<v Roger Bingham>When we e-mailed—\n\n00:30.500 --> 00:32.500 align:left size:50%\n<v Neil deGrasse Tyson>Didn’t we talk about enough in that conversation?\n\n00:32.000 --> 00:35.500 align:right size:50%\n<v Roger Bingham>No! No no no no; 'cos 'cos obviously 'cos\n\n00:32.500 --> 00:33.500 align:left size:50%\n<v Neil deGrasse Tyson><i>Laughs</i>\n\n00:35.500 --> 00:38.000\n<v Roger Bingham>You know I’m so excited my glasses are falling off here."
  },
  {
    "path": "packages/e2e-tests/src/config/bootstrap.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { setDefaultOptions } from 'expect-puppeteer';\nimport { matchers } from 'jest-json-schema';\nimport { toBeValidAMP } from '@web-stories-wp/jest-puppeteer-amp';\nimport {\n  setCurrentUser,\n  trashAllPosts,\n  deleteAllMedia,\n  trashAllTerms,\n  clearLocalStorage,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Environment variables\n */\nconst { PUPPETEER_TIMEOUT, EXPECT_PUPPETEER_TIMEOUT } = process.env;\n\n// The Jest timeout is increased because these tests are a bit slow\njest.setTimeout(PUPPETEER_TIMEOUT || 100000);\n\nexpect.extend({\n  toBeValidAMP,\n});\n\nexpect.extend(matchers);\n\n/**\n * Set of console logging types observed to protect against unexpected yet\n * handled (i.e. not catastrophic) errors or warnings. Each key corresponds\n * to the Puppeteer ConsoleMessage type, its value the corresponding function\n * on the console global object.\n *\n * @type {Object<string,string>}\n */\nconst OBSERVED_CONSOLE_MESSAGE_TYPES = {\n  warning: 'warn',\n  error: 'error',\n};\n\n/**\n * A list of \"allowed\" error message - or actually error message substrings.\n *\n * The list comes prepopulated with known messages,\n * but can be appended to by tests where relevant.\n *\n * @type {Array<string>}\n */\nconst ALLOWED_ERROR_MESSAGES = [\n  // As of WordPress 5.3.2 in Chrome 79, navigating to the block editor\n  // (Posts > Add New) will display a console warning about\n  // non - unique IDs.\n  // See: https://core.trac.wordpress.org/ticket/23165\n  'elements with non-unique id #_wpnonce',\n\n  // Ignore warning about isSecondary prop on button component as used by AMP plugin.\n  // The prop is only supported in newer versions of Gutenberg, and as such will trigger\n  // warnings on older WordPress versions (but not on newer ones).\n  'isSecondary',\n\n  // styled-components warns about dynamically created components.\n  // @todo Fix issues.\n  ' has been created dynamically.',\n\n  // WordPress still bundles jQuery Migrate, which logs to the console.\n  'JQMIGRATE',\n\n  // Firefox warns about this issue in WordPress admin.\n  'This page uses the non standard property “zoom”',\n\n  // Firefox warns about this issue when there's no proper favicon.\n  'Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIContentSniffer.getMIMETypeFromContent]',\n\n  // Firefox warns about this issue on the login screen.\n  'wp-includes/js/zxcvbn.min.js',\n\n  // Another Firefox warning.\n  'Layout was forced before the page was fully loaded',\n\n  // Upstream issue in gutenberg and twentytwenty theme.\n  'Stylesheet twentytwenty-block-editor-styles-css was not properly added.',\n\n  // TODO(#9240): Fix usage in the web stories block.\n  \"select( 'core' ).getAuthors() is deprecated since version 5.9.\",\n\n  // See https://www.chromestatus.com/feature/508239670987980\n  \"Blocked attempt to show a 'beforeunload' confirmation panel for a frame that never had a user gesture since its load\",\n\n  // Sometimes the AMP viewer can fail to load translations when viewing a story.\n  'Bundle not found for language en:',\n\n  // Media3p API requests can sometimes fail in the Docker environment (due to network issues?).\n  'Failed to fetch',\n\n  // Sometimes WASM modules (e.g. ffmpeg.wasm, @mediapipe/selfie_segmentation) are not loading.\n  'wasm streaming compile failed',\n  'falling back to ArrayBuffer instantiation',\n  'still waiting on run dependencies',\n  'dependency: wasm-instantiate',\n  '(end of list)',\n\n  // Customizer preview iframe.\n  'An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute',\n\n  // Needed because the tinymce package is not yet using React 18.\n  // TODO: Migrate & remove once WordPress 6.2 is minimum.\n  'Warning: ReactDOM.render is no longer supported in React 18',\n\n  // Coming from <amp-story-player>\n  // See https://github.com/ampproject/amphtml/blob/413457c3598f8c6694ca4ee7b83a5d84f9b9f00c/src/amp-story-player/amp-story-player-impl.js#L562\n  \"Unrecognized feature: 'web-share'\",\n\n  // This is a known issue in core.\n  'You are importing createRoot from \"react-dom\" which is not supported.',\n];\n\nexport function addAllowedErrorMessage(message) {\n  ALLOWED_ERROR_MESSAGES.push(message);\n  return () => {\n    const index = ALLOWED_ERROR_MESSAGES.findIndex((msg) => msg === message);\n    ALLOWED_ERROR_MESSAGES.splice(index, 1);\n  };\n}\n\n/**\n * Array of page event tuples of [ eventName, handler ].\n *\n * @type {Array}\n */\nconst pageEvents = [];\n\n// Set default timeout for individual expect-puppeteer assertions. (Default: 500)\nsetDefaultOptions({ timeout: EXPECT_PUPPETEER_TIMEOUT || 2000 });\n\n/**\n * Set up browser.\n */\nasync function setupBrowser() {\n  // Same as jest-puppeteer.config.cjs and percy.config.yml\n  const width = 1600;\n  const height = 1000;\n\n  await page.setViewport({\n    width,\n    height,\n  });\n\n  await page\n    .mainFrame()\n    .waitForFunction(\n      `window.innerWidth === ${width} && window.innerHeight === ${height}`\n    );\n}\n\n/**\n * Adds an event listener to the page to handle additions of page event\n * handlers, to assure that they are removed at test teardown.\n */\nfunction capturePageEventsForTearDown() {\n  page.on('newListener', (eventName, listener) => {\n    pageEvents.push([eventName, listener]);\n  });\n}\n\n/**\n * Removes all bound page event handlers.\n */\nfunction removePageEvents() {\n  pageEvents.forEach(([eventName, handler]) => {\n    page.removeListener(eventName, handler);\n  });\n}\n\nfunction enablePageDialogAccept() {\n  page.on('dialog', async (dialog) => {\n    await dialog.accept();\n  });\n}\n\n/**\n * Adds a page event handler to emit uncaught exception to process if one of\n * the observed console logging types is encountered.\n */\nfunction observeConsoleLogging() {\n  page.on('console', (message) => {\n    const type = message.type();\n    if (!Object.hasOwnProperty.call(OBSERVED_CONSOLE_MESSAGE_TYPES, type)) {\n      return;\n    }\n\n    let text = message.text();\n\n    // Short-circuit abort if any known \"allowed\" message fails\n    if (ALLOWED_ERROR_MESSAGES.some((msg) => text.includes(msg))) {\n      return;\n    }\n\n    // Special case: ignore 403 errors on logout page.\n    // See https://github.com/googleforcreators/web-stories-wp/pull/7889\n    if (\n      text.includes(\n        'Failed to load resource: the server responded with a status of 403 (Forbidden)'\n      ) &&\n      message.stackTrace()?.[0]?.url?.endsWith('wp-login.php?action=logout')\n    ) {\n      return;\n    }\n\n    //eslint-disable-next-line security/detect-object-injection -- Negligible.\n    const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[type];\n\n    // As of Puppeteer 1.6.1, `message.text()` wrongly returns an object of\n    // type JSHandle for error logging, instead of the expected string.\n    //\n    // See: https://github.com/GoogleChrome/puppeteer/issues/3397\n    //\n    // The recommendation there to asynchronously resolve the error value\n    // upon a console event may be prone to a race condition with the test\n    // completion, leaving a possibility of an error not being surfaced\n    // correctly. Instead, the logic here synchronously inspects the\n    // internal object shape of the JSHandle to find the error text. If it\n    // cannot be found, the default text value is used instead.\n    text = message.args()?.[0]?._remoteObject?.description || text;\n\n    /* eslint-disable-next-line no-console, security/detect-object-injection --\n     * We intentionally bubble up the console message\n     * which, unless the test explicitly anticipates the logging via\n     * @wordpress/jest-console matchers, will cause the intended test\n     * failure.\n     **/\n    console[logFunction](text);\n  });\n}\n\nasync function clearSessionStorage() {\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  await page.evaluate(() => window.sessionStorage.clear());\n}\n\n/**\n * Before every test suite run, delete all content created by the test. This ensures\n * other posts/comments/etc. aren't dirtying tests and tests don't depend on\n * each other's side-effects.\n */\n// eslint-disable-next-line jest/require-top-level-describe\nbeforeAll(async () => {\n  capturePageEventsForTearDown();\n  enablePageDialogAccept();\n  observeConsoleLogging();\n  await setupBrowser();\n  await page.setDefaultNavigationTimeout(10000);\n  await page.setDefaultTimeout(3000);\n\n  await setCurrentUser('admin', 'password');\n  await trashAllPosts();\n  await trashAllPosts('web-story');\n  await trashAllTerms('web_story_category');\n  await trashAllTerms('web_story_tag');\n  await deleteAllMedia();\n\n  await clearLocalStorage();\n  await clearSessionStorage();\n});\n\n// eslint-disable-next-line jest/require-top-level-describe\nafterEach(async () => {\n  await clearLocalStorage();\n  await clearSessionStorage();\n});\n\n// eslint-disable-next-line jest/require-top-level-describe\nafterAll(() => {\n  removePageEvents();\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/jest.config.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Environment variables\n */\nconst {\n  WP_USERNAME = 'admin',\n  WP_PASSWORD = 'password',\n  WP_BASE_URL = 'http://localhost:8899',\n} = process.env;\n\n// Explicitly set these environment variables if not already there.\nprocess.env.WP_USERNAME = WP_USERNAME;\nprocess.env.WP_PASSWORD = WP_PASSWORD;\nprocess.env.WP_BASE_URL = WP_BASE_URL;\n\nexport default {\n  rootDir: '../../../',\n  resolver: '@web-stories-wp/jest-resolver',\n  preset: '<rootDir>/node_modules/jest-puppeteer',\n  testEnvironment: '<rootDir>/packages/e2e-tests/src/puppeteerEnvironment.js',\n  testMatch: ['**/specs/**/*.[jt]s'],\n  testPathIgnorePatterns: [\n    '<rootDir>/.git',\n    '<rootDir>/build',\n    '<rootDir>/node_modules',\n    '<rootDir>/vendor',\n  ],\n  // Do not transform any node_modules except use-reduction\n  // See https://jestjs.io/docs/configuration#transformignorepatterns-arraystring\n  transformIgnorePatterns: ['/node_modules/(?!(use-reduction)/)'],\n  setupFilesAfterEnv: [\n    'jest-extended/all',\n    '<rootDir>/packages/e2e-tests/src/config/bootstrap.js',\n    '<rootDir>/node_modules/@wordpress/jest-console',\n    '<rootDir>/node_modules/expect-puppeteer',\n  ],\n  modulePathIgnorePatterns: ['<rootDir>/build', '<rootDir>/vendor'],\n};\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/disable-block-directory.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Disable Block Directory\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Disable access to block directory and remote patterns.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License:     Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2023 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\BlockDirectory;\n\nadd_action(\n\t'admin_init',\n\tfunction() {\n\t\tremove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );\n\t\tremove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );\n\t}\n);\n\nadd_filter( 'should_load_remote_block_patterns', '__return_false' );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/disable-gravatar.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Disable Gravatar\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Disable loading Gravatar to avoid CORS issues.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License:     Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2023 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\BlockDirectory;\n\n// Hat tip https://github.com/norcross/airplane-mode\n\nadd_filter(\n\t'get_avatar',\n\tstatic function ( $avatar, $id_or_email, $size, $default, $alt ) {\n\t\t$image  = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';\n\t\treturn \"<img alt='{$alt}' src='{$image}' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' style='background:#eee;' />\";\n\t},\n\t1,\n\t5\n);\n\nadd_filter(\n\t'get_avatar_url',\n\tstatic function ( $url ) {\n\t\treturn set_url_scheme( $url, 'https' );\n\t},\n\t1\n);\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/locked-post-mock.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Post Lock mock\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Mock post lock.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\PostLock;\n\nconst USERNAME = 'test_locker';\n\nfunction filter_meta( $value, $object_id, $meta_key ) {\n\tif ( '_edit_lock' !== $meta_key ) {\n\t\treturn $value;\n\t}\n\n\t$user = get_user_by( 'login', USERNAME );\n\tif ( ! $user ) {\n\t\treturn $value;\n\t}\n\t$user_id = $user->ID;\n\t$now     = time();\n\n\treturn \"$now:$user_id\";\n}\nadd_filter( 'get_post_metadata', __NAMESPACE__ . '\\filter_meta', 10, 3 );\n\nfunction activate() {\n\t$user = get_user_by( 'login', USERNAME );\n\tif ( ! $user ) {\n\t\twp_insert_user(\n\t\t\t[\n\t\t\t\t'user_login' => USERNAME,\n\t\t\t\t'role'       => 'author',\n\t\t\t\t'user_email' => 'lock@example.com',\n\t\t\t\t'user_pass'  => 'fsfdsfds',\n\t\t\t]\n\t\t);\n\t}\n}\n\nfunction deactivate() {\n\t$user = get_user_by( 'login', USERNAME );\n\tif ( $user ) {\n\t\twp_delete_user( $user->ID );\n\t}\n}\n\nregister_activation_hook( __FILE__, __NAMESPACE__ . '\\activate' );\nregister_deactivation_hook( __FILE__, __NAMESPACE__ . '\\deactivate' );\n\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/site-kit-adsense.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Site kit adsense mock\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Utility plugin to mock sitekit adsense\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\Sitekit\\Adsense;\n\ndefine( 'GOOGLESITEKIT_VERSION', '1.0.0' );\n\n/**\n * Force adsense to be enabled.\n *\n * @param $current\n *\n * @return string[]\n */\nfunction mock_enable_active_modules( $current ) {\n\treturn [ 'adsense' ];\n}\nadd_filter( 'pre_option_googlesitekit_active_modules', __NAMESPACE__ . '\\mock_enable_active_modules' );\n\n\n/**\n * Force adsense snippet to be enabled.\n *\n * @param $current\n *\n * @return string[]\n */\nfunction mock_enable_adsense_settings( $current ) {\n\treturn [\n\t\t'useSnippet'       => true,\n\t\t'webStoriesAdUnit' => '123456',\n\t\t'clientID'         => '98765',\n\t];\n}\nadd_filter( 'pre_option_googlesitekit_adsense_settings', __NAMESPACE__ . '\\mock_enable_adsense_settings' );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/site-kit-analytics.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Site kit Analytics mock\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Utility plugin to mock sitekit analytics\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\Sitekit\\Analytics;\n\ndefine( 'GOOGLESITEKIT_VERSION', '1.0.0' );\n\n/**\n * Mock output for plugin.\n *\n * @return void\n */\nfunction print_amp_gtag() {\n\t$property_id  = 'XXX-YYY';\n\t$gtag_amp_opt = [\n\t\t'vars'            => [\n\t\t\t'gtag_id' => $property_id,\n\t\t\t'config'  => [\n\t\t\t\t$property_id => [\n\t\t\t\t\t'groups' => 'default',\n\t\t\t\t\t'linker' => [\n\t\t\t\t\t\t'domains' => [ home_url() ],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t\t'optoutElementId' => '__gaOptOutExtension',\n\t];\n\n\t/**\n\t * Filters the gtag configuration options for the amp-analytics tag.\n\t *\n\t * You can use the {@see 'googlesitekit_gtag_opt'} filter to do the same for gtag in non-AMP.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @param array $gtag_amp_opt gtag config options for AMP.\n\t *\n\t * @see   https://developers.google.com/gtagjs/devguide/amp\n\t *\n\t */\n\t$gtag_amp_opt_filtered = apply_filters( 'googlesitekit_amp_gtag_opt', $gtag_amp_opt );\n\n\t// Ensure gtag_id is set to the correct value.\n\tif ( ! is_array( $gtag_amp_opt_filtered ) ) {\n\t\t$gtag_amp_opt_filtered = $gtag_amp_opt;\n\t}\n\n\tif ( ! isset( $gtag_amp_opt_filtered['vars'] ) || ! is_array( $gtag_amp_opt_filtered['vars'] ) ) {\n\t\t$gtag_amp_opt_filtered['vars'] = $gtag_amp_opt['vars'];\n\t}\n\n\t$gtag_amp_opt_filtered['vars']['gtag_id'] = $property_id;\n\n\tprintf(\n\t\t'<amp-analytics type=\"gtag\" data-credentials=\"include\"%s><script type=\"application/json\">%s</script></amp-analytics>',\n\t\tget_tag_amp_block_on_consent_attribute(), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\twp_json_encode( $gtag_amp_opt_filtered )\n\t);\n}\n\nadd_action( 'web_stories_print_analytics', __NAMESPACE__ . '\\print_amp_gtag' );\n\n/**\n * Force analytics to be enabled.\n *\n * @param $current\n *\n * @return string[]\n */\nfunction mock_enable_active_modules( $current ) {\n\treturn [ 'analytics' ];\n}\nadd_filter( 'pre_option_googlesitekit_active_modules', __NAMESPACE__ . '\\mock_enable_active_modules' );\n\n\n/**\n * Force analytics snippet to be enabled.\n *\n * @param $current\n *\n * @return string[]\n */\nfunction mock_enable_analytics_settings( $current ) {\n\treturn [ 'useSnippet' => true ];\n}\nadd_filter( 'pre_option_googlesitekit_analytics_settings', __NAMESPACE__ . '\\mock_enable_analytics_settings' );\n\n/**\n * Gets the HTML attributes for an AMP tag that may potentially require user consent before loading.\n *\n *\n * @return string HTML attributes to add if the tag requires consent to load, or an empty string.\n */\nfunction get_tag_amp_block_on_consent_attribute() {\n\t/**\n\t * Filters whether the tag requires user consent before loading.\n\t *\n\t * @since 1.18.0\n\t *\n\t * @param bool|string $blocked Whether or not the tag requires user consent to load. Alternatively, this can also be one of\n\t *                             the special string values '_till_responded', '_till_accepted', or '_auto_reject'. Default: false.\n\t */\n\t$block_on_consent = apply_filters( 'googlesitekit_analytics_tag_amp_block_on_consent', false );\n\n\tif ( in_array( $block_on_consent, get_allowed_amp_block_on_consent_values(), true ) ) {\n\t\treturn sprintf( ' data-block-on-consent=\"%s\"', $block_on_consent );\n\t}\n\n\tif ( filter_var( $block_on_consent, FILTER_VALIDATE_BOOLEAN ) ) {\n\t\treturn ' data-block-on-consent';\n\t}\n\n\treturn '';\n}\n\n\nfunction get_allowed_amp_block_on_consent_values() {\n\treturn [\n\t\t'_till_responded',\n\t\t'_till_accepted',\n\t\t'_auto_reject',\n\t];\n}\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/status-check-200-invalid.php",
    "content": "<?php\n/**\n * Plugin Name: Web Stories Test Plugin: Status Check 200 Invalid\n * Plugin URI:  https://github.com/google/web-stories-wp\n * Description: Test plugin for status check with status 200.\n * Author:      Google\n * Author URI:  https://opensource.google.com/\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E_Tests;\n\nuse WP_HTTP_Response;\nuse WP_REST_Request;\nuse WP_REST_Server;\n\n/**\n * Filters the REST API response.\n *\n * @param WP_HTTP_Response $result  Result to send to the client. Usually a `WP_REST_Response`.\n * @param WP_REST_Server   $server  Server instance.\n * @param WP_REST_Request  $request Request used to generate the response.\n * @return WP_HTTP_Response Modified result.\n */\nfunction filter_rest_response( $result, $server, $request ) {\n\tif ( '/web-stories/v1/status-check' === $request->get_route() ) {\n\t\t$result->set_status( 200 );\n\t\t$result->set_data( 'This is some unexpected content before the actual response.{\"success\":true}' );\n\t}\n\n\treturn $result;\n}\n\nadd_action( 'rest_post_dispatch', __NAMESPACE__ . '\\filter_rest_response', 10, 3 );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/status-check-403.php",
    "content": "<?php\n/**\n * Plugin Name: Web Stories Test Plugin: Status Check 403\n * Plugin URI:  https://github.com/google/web-stories-wp\n * Description: Test plugin for status check with status 403.\n * Author:      Google\n * Author URI:  https://opensource.google.com/\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E_Tests;\n\nuse WP_HTTP_Response;\nuse WP_REST_Request;\nuse WP_REST_Server;\n\n/**\n * Filters the REST API response.\n *\n * @param WP_HTTP_Response $result  Result to send to the client. Usually a `WP_REST_Response`.\n * @param WP_REST_Server   $server  Server instance.\n * @param WP_REST_Request  $request Request used to generate the response.\n * @return WP_HTTP_Response Modified result.\n */\nfunction filter_rest_response( $result, $server, $request ) {\n\tif ( '/web-stories/v1/status-check' === $request->get_route() ) {\n\t\t$result->set_status( 403 );\n\t\t$result->set_data( 'Forbidden' );\n\t}\n\n\treturn $result;\n}\n\nadd_action( 'rest_post_dispatch', __NAMESPACE__ . '\\filter_rest_response', 10, 3 );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/status-check-500.php",
    "content": "<?php\n/**\n * Plugin Name: Web Stories Test Plugin: Status Check 500\n * Plugin URI:  https://github.com/google/web-stories-wp\n * Description: Test plugin for status check with status 500.\n * Author:      Google\n * Author URI:  https://opensource.google.com/\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E_Tests;\n\nuse WP_HTTP_Response;\nuse WP_REST_Request;\nuse WP_REST_Server;\n\n/**\n * Filters the REST API response.\n *\n * @param WP_HTTP_Response $result  Result to send to the client. Usually a `WP_REST_Response`.\n * @param WP_REST_Server   $server  Server instance.\n * @param WP_REST_Request  $request Request used to generate the response.\n * @return WP_HTTP_Response Modified result.\n */\nfunction filter_rest_response( $result, $server, $request ) {\n\tif ( '/web-stories/v1/status-check' === $request->get_route() ) {\n\t\t$result->set_status( 500 );\n\t\t$result->set_data( 'Forbidden' );\n\t}\n\n\treturn $result;\n}\n\nadd_action( 'rest_post_dispatch', __NAMESPACE__ . '\\filter_rest_response', 10, 3 );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-cors-error.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests CORS error\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: CORS errors on purpose for testing.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\CORS;\n\n/**\n * Override the REST request to show an invalid response with cors errors.\n *\n * @since 1.19.0\n *\n * @param \\WP_REST_Response $response Response object.\n *\n * @return \\WP_REST_Response\n */\nfunction change_response( $response, $post, $request ) {\n\t// Only filter requests for cors check.\n\tif ( $request['per_page'] !== 10 && $request['_fields'] !== 'source_url' ) {\n\t\treturn $response;\n\t}\n\t/**\n\t * Response data.\n\t *\n\t * @var array $data\n\t */\n\t$data = $response->get_data();\n\n\t$data['source_url']             = 'https://ps.w.org/web-stories/assets/banner-772x250.png';\n\t$data['media_details']['sizes'] = [];\n\n\t$response->set_data( $data );\n\n\treturn $response;\n}\n\nadd_filter( 'web_stories_rest_prepare_attachment', __NAMESPACE__ . '\\change_response', 20, 3 );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-disable-default-templates.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Disable default templates\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Disable default templates.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\DefaultTemplates;\n\nfunction change_get_settings( array $settings ): array {\n\t$settings['canViewDefaultTemplates'] = false;\n\n\treturn $settings;\n}\nadd_filter( 'web_stories_editor_settings', __NAMESPACE__ . '\\change_get_settings' );\nadd_filter( 'web_stories_dashboard_settings', __NAMESPACE__ . '\\change_get_settings' );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-disable-media3p.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Disable 3P media.\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Disable 3P media.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\Media3P;\n\n\nfunction change_get_editor_settings( array $settings ): array {\n\t$settings['showMedia3p'] = false;\n\n\treturn $settings;\n}\nadd_filter( 'web_stories_editor_settings', __NAMESPACE__ . '\\change_get_editor_settings' );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-embed.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Embed\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Hook into embed REST API controller to avoid making real requests.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\Embed;\n\n/**\n * Hotwire the value of transient, so that a real request is not made.\n *\n * @return string\n */\nfunction filter_transient(): string {\n\t$data = [\n\t\t'title'  => 'Stories in AMP - Hello World',\n\t\t'poster' => 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg',\n\t];\n\n\treturn wp_json_encode( $data );\n}\n\nadd_filter( 'pre_transient_web_stories_embed_data_' . md5( content_url( 'https://wp.stories.google/stories/intro-to-web-stories-storytime/' ) ), __NAMESPACE__ . '\\filter_transient', 20 );\n\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-hotlink.php",
    "content": "<?php\n/**\n * Plugin Name: E2E Tests Hotlink\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Hook into Hotlinking REST API controller to avoid making real requests.\n * Author:      Google\n * Author URI:  https://opensource.google.com\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E\\Hotlink;\n\n/**\n * Hotwire the value of transient, so that a real request is not made.\n *\n * @return string\n */\nfunction filter_transient_vtt_file(): string {\n\t$data = [\n\t\t'ext'       => 'vtt',\n\t\t'file_name' => 'test.vtt',\n\t\t'file_size' => '2000',\n\t\t'mime_type' => 'text/vtt',\n\t\t'type'      => 'caption',\n\t];\n\n\treturn wp_json_encode( $data );\n}\n\nadd_filter( 'pre_transient_web_stories_url_data_' . md5( content_url( '/e2e-assets/test.vtt' ) ), __NAMESPACE__ . '\\filter_transient_vtt_file', 20 );\n\n/**\n * Hotwire the value of transient, so that a real request is not made.\n *\n * @return string\n */\nfunction filter_transient_jpg_file(): string {\n\t$data = [\n\t\t'ext'       => 'png',\n\t\t'file_name' => 'example-3.png',\n\t\t'file_size' => '381503',\n\t\t'mime_type' => 'image/png',\n\t\t'type'      => 'image',\n\t];\n\n\treturn wp_json_encode( $data );\n}\n\nadd_filter( 'pre_transient_web_stories_url_data_' . md5( content_url( '/e2e-assets/example-3.png' ) ), __NAMESPACE__ . '\\filter_transient_jpg_file', 20 );\n\n/**\n * Hotwire the value of transient, so that a real request is not made.\n *\n * @return string\n */\nfunction filter_transient_external_jpg_file(): string {\n\t$data = [\n\t\t'ext'       => 'jpg',\n\t\t'file_name' => 'example.jpg',\n\t\t'file_size' => '21171',\n\t\t'mime_type' => 'image/jpeg',\n\t\t'type'      => 'image',\n\t];\n\n\treturn wp_json_encode( $data );\n}\n\nadd_filter( 'pre_transient_web_stories_url_data_' . md5( 'https://wp.stories.google/e2e-tests/example.jpg' ), __NAMESPACE__ . '\\filter_transient_external_jpg_file', 20 );\n\n/**\n * Hotwire the value of transient, so that a real request is not made.\n *\n * @return string\n */\nfunction filter_transient_audio_file(): string {\n\t$data = [\n\t\t'ext'       => 'mp3',\n\t\t'file_name' => 'audio.mp3',\n\t\t'file_size' => '2000',\n\t\t'mime_type' => 'audio/mpeg',\n\t\t'type'      => 'audio',\n\t];\n\n\treturn wp_json_encode( $data );\n}\n\nadd_filter( 'pre_transient_web_stories_url_data_' . md5( content_url( '/e2e-assets/audio.mp3' ) ), __NAMESPACE__ . '\\filter_transient_audio_file', 20 );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-meta-box.php",
    "content": "<?php\n/**\n * Plugin Name: Web Stories Test Plugin: Meta Box\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Test plugin for custom meta boxes.\n * Author:      Google\n * Author URI:  https://opensource.google.com/\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E_Tests;\n\nfunction add_meta_box() {\n\t\\add_meta_box(\n\t\t'web-stories-test-meta-box',\n\t\t'Web Stories Test Meta Box',\n\t\tstatic function( $post ) {\n\t\t\t// Add an nonce field so we can check for it later.\n\t\t\twp_nonce_field( 'web_stories_test_meta_box', 'web_stories_test_meta_box_nonce' );\n\n\t\t\t$value = get_post_meta( $post->ID, '_web_stories_test_meta_box_content', true );\n\t\t\t?>\n\t\t\t<label for=\"web_stories_test_meta_box_field\">Meta Box Test Content:</label>\n\t\t\t<input type=\"text\" id=\"web_stories_test_meta_box_field\" name=\"web_stories_test_meta_box_content\" value=\"<?php echo esc_attr( $value ); ?>\" />\n\t\t\t<?php\n\t\t}\n\t);\n}\n\nadd_action( 'add_meta_boxes', __NAMESPACE__ . '\\add_meta_box' );\n\nfunction save_post( $post_id ) {\n\tif ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {\n\t\treturn;\n\t}\n\n\tif ( ! isset( $_POST['web_stories_test_meta_box_nonce'] ) ) {\n\t\treturn;\n\t}\n\n\t$nonce = $_POST['web_stories_test_meta_box_nonce'];\n\n\tif ( ! wp_verify_nonce( $nonce, 'web_stories_test_meta_box' ) ) {\n\t\treturn;\n\t}\n\n\t$post_type     = get_post_type( $post_id );\n\t$post_type_obj = get_post_type_object( $post_type );\n\n\tif ( ! current_user_can( $post_type_obj->cap->edit_post, $post_id ) ) {\n\t\treturn;\n\t}\n\n\t$value = sanitize_text_field( $_POST['web_stories_test_meta_box_content'] );\n\n\tupdate_post_meta( $post_id, '_web_stories_test_meta_box_content', $value );\n}\n\nadd_action( 'save_post', __NAMESPACE__ . '\\save_post' );\n\nfunction render_head() {\n\t$value = get_post_meta( get_the_ID(), '_web_stories_test_meta_box_content', true );\n\t?>\n\t<meta property=\"web-stories:meta-box-test\" content=\"<?php echo esc_attr( $value ); ?>\" />\n\t<?php\n}\n\nadd_action( 'web_stories_story_head', __NAMESPACE__ . '\\render_head' );\nadd_action( 'wp_head', __NAMESPACE__ . '\\render_head' );\n"
  },
  {
    "path": "packages/e2e-tests/src/plugins/web-stories-taxonomies.php",
    "content": "<?php\n/**\n * Plugin Name: Web Stories Test Plugin: Taxonomies\n * Plugin URI:  https://github.com/googleforcreators/web-stories-wp\n * Description: Test plugin that adds some custom taxonomies.\n * Author:      Google\n * Author URI:  https://opensource.google.com/\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2022 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\E2E_Tests;\n\nfunction add_taxonomies() {\n\tregister_taxonomy(\n\t\t'story-color',\n\t\t'web-story',\n\t\t[\n\t\t\t'description'  => 'Story Colors',\n\t\t\t'show_in_rest' => true,\n\t\t\t'show_ui'      => true,\n\t\t\t'rest_base'    => 'story-colors',\n\t\t\t'labels'       => [\n\t\t\t\t'name'                       => 'Colors',\n\t\t\t\t'singular_name'              => 'Color',\n\t\t\t\t'search_items'               => 'Search Colors',\n\t\t\t\t'popular_items'              => 'Popular Colors',\n\t\t\t\t'all_items'                  => 'All Colors',\n\t\t\t\t'edit_item'                  => 'Edit Color',\n\t\t\t\t'view_item'                  => 'View Color',\n\t\t\t\t'update_item'                => 'Update Color',\n\t\t\t\t'add_new_item'               => 'Add New Color',\n\t\t\t\t'new_item_name'              => 'New Color Name',\n\t\t\t\t'separate_items_with_commas' => 'Separate colors with commas',\n\t\t\t\t'add_or_remove_items'        => 'Add or remove colors',\n\t\t\t\t'choose_from_most_used'      => 'Choose from the most used colors',\n\t\t\t\t'not_found'                  => 'No colors found.',\n\t\t\t\t'no_terms'                   => 'No colors',\n\t\t\t\t'items_list_navigation'      => 'Colors list navigation',\n\t\t\t\t'items_list'                 => 'Colors list',\n\t\t\t\t'most_used'                  => 'Most Used',\n\t\t\t\t'back_to_items'              => '&larr; Go to Colors',\n\t\t\t\t'item_link'                  => 'Color Color',\n\t\t\t\t'item_link_description'      => 'A link to a color.',\n\t\t\t],\n\t\t]\n\t);\n\n\tregister_taxonomy(\n\t\t'story-vertical',\n\t\t'web-story',\n\t\t[\n\t\t\t'description'  => 'Story Verticals',\n\t\t\t'hierarchical' => true,\n\t\t\t'show_in_rest' => true,\n\t\t\t'show_ui'      => true,\n\t\t\t'rest_base'    => 'story-verticals',\n\t\t\t'labels'       => [\n\t\t\t\t'name'                  => 'Verticals',\n\t\t\t\t'singular_name'         => 'Vertical',\n\t\t\t\t'search_items'          => 'Search Verticals',\n\t\t\t\t'all_items'             => 'All Verticals',\n\t\t\t\t'parent_item'           => 'Parent Vertical',\n\t\t\t\t'parent_item_colon'     => 'Parent Vertical:',\n\t\t\t\t'edit_item'             => 'Edit Vertical',\n\t\t\t\t'view_item'             => 'View Vertical',\n\t\t\t\t'update_item'           => 'Update Vertical',\n\t\t\t\t'add_new_item'          => 'Add New Vertical',\n\t\t\t\t'new_item_name'         => 'New Vertical Name',\n\t\t\t\t'not_found'             => 'No verticals found.',\n\t\t\t\t'no_terms'              => 'No verticals',\n\t\t\t\t'filter_by_item'        => 'Filter by vertical',\n\t\t\t\t'items_list_navigation' => 'Verticals list navigation',\n\t\t\t\t'items_list'            => 'Verticals list',\n\t\t\t\t'most_used'             => 'Most Used',\n\t\t\t\t'back_to_items'         => '&larr; Go to Verticals',\n\t\t\t\t'item_link'             => 'Color Vertical',\n\t\t\t\t'item_link_description' => 'A link to a vertical.',\n\t\t\t],\n\t\t]\n\t);\n}\nadd_action( 'init', __NAMESPACE__ . '\\add_taxonomies' );\n"
  },
  {
    "path": "packages/e2e-tests/src/puppeteerEnvironment.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { mkdirSync, writeFileSync } from 'fs';\nimport util from 'node:util';\n// eslint-disable-next-line import/no-extraneous-dependencies -- Transitive dependency.\nimport JestPuppeteerEnvironment from 'jest-environment-puppeteer';\n\nconst ARTIFACTS_PATH =\n  process.env.E2E_ARTIFACTS_PATH ||\n  (process.env.GITHUB_WORKSPACE || process.cwd()) + '/build/e2e-artifacts';\n\nclass PuppeteerEnvironment extends JestPuppeteerEnvironment {\n  async setup() {\n    await super.setup();\n\n    try {\n      mkdirSync(ARTIFACTS_PATH, { recursive: true });\n    } catch (err) {\n      if (err.code !== 'EEXIST') {\n        throw err;\n      }\n    }\n  }\n\n  async handleTestEvent(event, state) {\n    if (event.name === 'test_fn_failure' || event.name === 'hook_failure') {\n      const testName =\n        event.name === 'test_fn_failure'\n          ? `${state.currentlyRunningTest.parent.name}  ${state.currentlyRunningTest.name}`\n          : 'before or after hook';\n\n      let errorMessages = '';\n\n      if (event.test) {\n        const errors = state.currentlyRunningTest?.errors || [];\n        const eventError = util.inspect(event);\n        errorMessages += `========= ${testName} ==========\\n\\n`;\n        errorMessages +=\n          'started:' +\n          new Date(event.test.startedAt).toLocaleString() +\n          ' ended:' +\n          new Date().toLocaleString();\n        errorMessages += '============end==========\\n\\n';\n        errors.forEach((error) => {\n          errorMessages += `${testName}:${error}\\n\\n`;\n        });\n        errorMessages += '=========================\\n\\n';\n        errorMessages += eventError;\n      }\n\n      await this.storeArtifacts(testName, errorMessages);\n    }\n  }\n\n  async storeArtifacts(testName, errorMessages) {\n    const datetime = new Date().toISOString().split('.')[0];\n    const fileName = `${testName} ${datetime}`.replaceAll(/[ :\"/\\\\|?*]+/g, '-');\n\n    writeFileSync(`${ARTIFACTS_PATH}/${fileName}-errors.txt`, errorMessages);\n\n    if (this.global.page.isClosed()) {\n      return;\n    }\n\n    writeFileSync(\n      `${ARTIFACTS_PATH}/${fileName}-snapshot.html`,\n      await this.global.page.content()\n    );\n\n    await this.global.page.screenshot({\n      path: `${ARTIFACTS_PATH}/${fileName}.jpg`,\n    });\n  }\n}\n\nexport default PuppeteerEnvironment;\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/adminMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { visitDashboard } from '@web-stories-wp/e2e-test-utils';\n\nexpect.extend({\n  async toHaveSyncedNav(page) {\n    const activeMenuItem = await page.evaluate(\n      () =>\n        document.querySelector('#menu-posts-web-story .current a')?.innerText\n    );\n    const activePage = await page.evaluate(\n      () => document.querySelector('h2')?.innerText\n    );\n\n    const pass = activeMenuItem === activePage;\n\n    return {\n      pass,\n      message: `Expected active admin menu link \"${activeMenuItem}\" to match current page \"${activePage}\"`,\n    };\n  },\n});\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Admin Menu', () => {\n  it('should sync the WP nav with the dashboard nav', async () => {\n    await visitDashboard();\n\n    // Initial visit to `/` makes `Dashboard` link current in WP\n    await page.hover('#menu-posts-web-story');\n\n    await expect(page).toHaveSyncedNav();\n\n    // Navigating through the application to a new page syncs the WP current page in Nav\n    await Promise.all([\n      page.waitForNavigation(),\n      expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n        text: 'Explore Templates',\n      }),\n    ]);\n    await expect(page).toHaveSyncedNav();\n\n    // Navigating through WP to a new page syncs the WP current page in Nav\n    await page.hover('#menu-posts-web-story');\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 100));\n    await Promise.all([\n      page.waitForNavigation(),\n      expect(page).toClick('#menu-posts-web-story a', {\n        text: 'Settings',\n      }),\n    ]);\n    await expect(page).toHaveSyncedNav();\n\n    // Navigating through application back to Dashboard from another route\n    await Promise.all([\n      page.waitForNavigation(),\n      expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n        text: 'Dashboard',\n      }),\n    ]);\n    await expect(page).toHaveSyncedNav();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/dashboard.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  withRTL,\n  visitDashboard,\n  createNewStory,\n  insertStoryTitle,\n  publishStory,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst percyCSS = `.dashboard-grid-item-date { display: none; }`;\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Stories Dashboard', () => {\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  it('should be able to open the dashboard', async () => {\n    await visitDashboard();\n\n    // If there are no existing stories, the app goes to the templates page instead.\n    // Account for both here, but then force-visit the dashboard.\n    await expect(page).toMatchElement('h2', {\n      text: /(Dashboard|Explore Templates)/,\n    });\n\n    await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n      text: 'Dashboard',\n    });\n\n    await takeSnapshot(page, 'Stories Dashboard', { percyCSS });\n  });\n\n  it('should be able to skip to main content of Dashboard for keyboard navigation', async () => {\n    await visitDashboard();\n\n    // If there are no existing stories, the app goes to the Templates page instead.\n    // Either is fine since we're testing keyboard navigation.\n    await expect(page).toMatchElement('h2', {\n      text: /(Dashboard|Explore Templates)/,\n    });\n\n    // When navigating to Dashboard, immediately use keyboard to\n    // tab to WordPress shortcut of \"Main Content\"\n    await page.keyboard.press('Tab');\n\n    // Verify that Main Content skip link is present\n    await expect(page).toMatchElement('a', { text: 'Skip to main content' });\n\n    // Use the keyboard to select skip link while it is present (since it's now focused)\n    await page.keyboard.press('Enter');\n\n    // Make sure we see the dashboard\n    await expect(page).toMatchElement('h2', {\n      text: /(Dashboard|Explore Templates)/,\n    });\n\n    // Now let's make sure that the next focusable element is the link to create a new story\n    await page.keyboard.press('Tab');\n\n    const activeElement = await page.evaluate(() => {\n      return {\n        text: document.activeElement.textContent,\n        element: document.activeElement.tagName.toLowerCase(),\n      };\n    });\n\n    await expect(activeElement).toMatchObject({\n      text: 'Create New Story',\n      element: 'a',\n    });\n\n    await takeSnapshot(page, 'Stories Dashboard on Keyboard Navigation', {\n      percyCSS,\n    });\n  });\n\n  it('should choose sort option for display', async () => {\n    // dropdown needs a story for filtering\n    await createNewStory();\n    await insertStoryTitle('Stories Dashboard test - story');\n    await publishStory();\n    await visitDashboard();\n    await expect(page).toClick('[aria-label=\"Dashboard (active view)\"]', {\n      text: 'Dashboard',\n    });\n    const sortButtonSelector =\n      'button[aria-label=\"Choose sort option for display\"]';\n    await expect(page).toClick(sortButtonSelector, { text: 'Last Modified' });\n    await takeSnapshot(page, 'Dashboard sort option dropdown', { percyCSS });\n    await expect(page).toClick('li', { text: 'Created By' });\n    await expect(page).toMatchElement(sortButtonSelector, {\n      text: 'Created By',\n    });\n  });\n\n  describe('RTL', () => {\n    withRTL();\n\n    it('should be able to open the dashboard', async () => {\n      await visitDashboard();\n\n      await expect(page).toMatchElement('h2', {\n        text: /(Dashboard|Explore Templates)/,\n      });\n\n      await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n        text: 'Dashboard',\n      });\n\n      await takeSnapshot(page, 'Stories Dashboard on RTL', { percyCSS });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/documentTitle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { visitDashboard } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Document Title', () => {\n  it('should update the document title during navigation', async () => {\n    await visitDashboard();\n\n    // First visit to Dashboard my redirect to Explore Templates.\n    // See https://github.com/googleforcreators/web-stories-wp/pull/7213, needs updating.\n    // Work around this by explicitly clicking on dashboard again.\n\n    await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n      text: 'Dashboard',\n    });\n\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n    await expect(page.title()).resolves.toStartWith('Dashboard');\n\n    await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n      text: 'Explore Templates',\n    });\n\n    await expect(page).toMatchElement('h2', { text: 'Explore Templates' });\n    await expect(page.title()).resolves.toStartWith('Explore Templates');\n\n    await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n      text: 'Settings',\n    });\n\n    await expect(page).toMatchElement('h2', { text: 'Settings' });\n    await expect(page.title()).resolves.toStartWith('Settings');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/myStories.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  publishStory,\n  visitDashboard,\n  insertStoryTitle,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst storyName = 'Test Story';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Stories Dashboard', () => {\n  beforeEach(async () => {\n    await createNewStory();\n    await insertStoryTitle(storyName);\n    await publishStory();\n    await visitDashboard();\n  });\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  it('should delete story', async () => {\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n    await page.hover(\n      `[role=\"listitem\"][aria-label=\"Details about ${storyName}\"]`\n    );\n    await expect(page).toClick(\n      `button[aria-label=\"Context menu for ${storyName}\"]`\n    );\n\n    await expect(page).toClick('button', { text: 'Delete Story' });\n    await expect(page).toMatchTextContent(/Are you sure you want to delete/);\n\n    await expect(page).toMatchElement(\n      '[role=\"dialog\"][aria-label=\"Dialog to confirm deleting a story\"] button',\n      {\n        text: 'Delete',\n      }\n    );\n\n    await expect(page).toClick(\n      '[role=\"dialog\"][aria-label=\"Dialog to confirm deleting a story\"] button',\n      {\n        text: 'Delete',\n      }\n    );\n\n    await page.waitForResponse((response) =>\n      response.url().includes('web-stories/v1/web-story/')\n    );\n\n    await expect(page).not.toMatchElement('h3', {\n      text: storyName,\n    });\n  });\n\n  it('should duplicate story', async () => {\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n    await page.hover(\n      `[role=\"listitem\"][aria-label=\"Details about ${storyName}\"]`\n    );\n    await expect(page).toClick(\n      `button[aria-label=\"Context menu for ${storyName}\"]`\n    );\n\n    await Promise.all([\n      expect(page).toClick('button', { text: 'Duplicate' }),\n      page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('web-stories/v1/web-story/') &&\n          response.status() === 201\n      ),\n    ]);\n\n    await expect(page).toMatchElement('h3', {\n      text: `${storyName} (Copy)`,\n    });\n  });\n\n  it('should rename story', async () => {\n    const newStoryName = 'Renamed story';\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n    await page.hover(\n      `[role=\"listitem\"][aria-label=\"Details about ${storyName}\"]`\n    );\n    await expect(page).toClick(\n      `button[aria-label=\"Context menu for ${storyName}\"]`\n    );\n    await expect(page).toClick('button', { text: 'Rename' });\n    await expect(page).toMatchElement(`input[value=\"${storyName}\"]`);\n    await page.type(`input[value=\"${storyName}\"]`, newStoryName);\n\n    await Promise.all([\n      page.keyboard.press('Enter'),\n      page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('web-stories/v1/web-story/') &&\n          response.status() === 200\n      ),\n    ]);\n\n    await expect(page).toMatchElement('h3', {\n      text: newStoryName,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/noJS.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { takeSnapshot, visitDashboard } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Stories Dashboard with disabled JavaScript', () => {\n  it('should display error message', async () => {\n    // Disable javascript for test.\n    await page.setJavaScriptEnabled(false);\n\n    await visitDashboard();\n\n    await expect(page).toMatchElement('.web-stories-wp-no-js');\n\n    // Re-enable javascript for snapshots.\n    await page.setJavaScriptEnabled(true);\n\n    await takeSnapshot(page, 'Dashboard no js');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/analytics.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { visitSettings } from '@web-stories-wp/e2e-test-utils';\n\nconst INPUT_SELECTOR =\n  '[aria-label=\"Enter your Google Analytics Measurement ID\"]';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Analytics', () => {\n  beforeEach(async () => {\n    await visitSettings();\n  });\n\n  it('should render', async () => {\n    const settingsView = await page.$('[data-testid=\"editor-settings\"]');\n    expect(settingsView).toBeTruthy();\n\n    await expect(page).toMatchElement('h2', { text: 'Settings' });\n  });\n\n  it('should update the tracking id when pressing enter and display snackbar confirmation', async () => {\n    await page.click(INPUT_SELECTOR);\n\n    const inputLength = await page.$eval(INPUT_SELECTOR, (el) => {\n      return el.value.length;\n    });\n\n    for (let iter = 0; iter < inputLength; iter++) {\n      // disable eslint to prevent overlapping .act calls\n      // eslint-disable-next-line no-await-in-loop\n      await page.keyboard.press('Backspace');\n    }\n\n    await page.keyboard.type('UA-009345-10');\n    await page.keyboard.press('Enter');\n\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 400));\n    await expect(page).toMatchTextContent('Setting saved.');\n  });\n\n  it('should update the tracking id by clicking the save button and display snackbar confirmation', async () => {\n    await page.hover(INPUT_SELECTOR);\n    await page.click(INPUT_SELECTOR);\n\n    const inputLength = await page.$eval(INPUT_SELECTOR, (el) => {\n      return el.value.length;\n    });\n\n    for (let iter = 0; iter < inputLength; iter++) {\n      // disable eslint to prevent overlapping .act calls\n      // eslint-disable-next-line no-await-in-loop\n      await page.keyboard.press('Backspace');\n    }\n\n    await page.keyboard.type('UA-009345-11');\n    await expect(page).toClick('button', { text: 'Save' });\n\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 400));\n    await expect(page).toMatchTextContent('Setting saved.');\n  });\n\n  it('should allow the analytics id to be saved as an empty string and display snackbar confirmation', async () => {\n    await page.click(INPUT_SELECTOR);\n    const inputLength = await page.$eval(INPUT_SELECTOR, (el) => {\n      return el.value.length;\n    });\n\n    for (let iter = 0; iter < inputLength; iter++) {\n      // disable eslint to prevent overlapping .act calls\n      // eslint-disable-next-line no-await-in-loop\n      await page.keyboard.press('Backspace');\n    }\n\n    await expect(page).toClick('button', { text: 'Save' });\n\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 400));\n    await expect(page).toMatchTextContent('Setting saved.');\n  });\n\n  it('should not allow an invalid analytics id to be saved', async () => {\n    await page.click(INPUT_SELECTOR);\n    await page.keyboard.type('INVALID');\n    await expect(page).toClick('button', { text: 'Save' });\n\n    await expect(page).toMatchTextContent('Invalid ID format');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/customFonts.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  visitSettings,\n  addCustomFont,\n  removeAllFonts,\n  getFontList,\n  takeSnapshot,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../../../config/bootstrap';\n\nconst FONT_BASE_URL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets`;\nconst OPEN_SANS_CONDENSED_LIGHT = 'Open Sans Condensed Light';\nconst OPEN_SANS_CONDENSED_LIGHT_URL = `${FONT_BASE_URL}/OpenSansCondensed-Light.ttf`;\nconst OPEN_SANS_CONDENSED_BOLD = 'Open Sans Condensed Bold';\nconst OPEN_SANS_CONDENSED_BOLD_URL = `${FONT_BASE_URL}/OpenSansCondensed-Bold.ttf`;\nconst OPEN_SANS_CONDENSED_LIGHT_ITALIC_URL = `${FONT_BASE_URL}/OpenSansCondensed-LightItalic.ttf`;\n\nconst findByUrl = (arr, val) => arr.find((o) => o.url === val);\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Custom Fonts', () => {\n  let removeResourceErrorMessage;\n\n  beforeAll(() => {\n    // Ignore resource failing to load. This is only present because of the REST API error.\n    removeResourceErrorMessage = addAllowedErrorMessage(\n      'Failed to load resource'\n    );\n  });\n\n  beforeEach(async () => {\n    await visitSettings();\n    await removeAllFonts();\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n    await removeAllFonts();\n  });\n\n  afterAll(() => {\n    removeResourceErrorMessage();\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- Needs further investigation.\n  it.skip('should add a font and handle keyboard navigation', async () => {\n    await addCustomFont(OPEN_SANS_CONDENSED_LIGHT_URL);\n    await addCustomFont(OPEN_SANS_CONDENSED_BOLD_URL);\n    await addCustomFont(OPEN_SANS_CONDENSED_LIGHT_ITALIC_URL);\n\n    const fonts = await getFontList();\n    const font1 = findByUrl(fonts, OPEN_SANS_CONDENSED_LIGHT_URL);\n    expect(font1?.name).toStrictEqual(OPEN_SANS_CONDENSED_LIGHT);\n    const font2 = findByUrl(fonts, OPEN_SANS_CONDENSED_BOLD_URL);\n    expect(font2?.name).toStrictEqual(OPEN_SANS_CONDENSED_BOLD);\n\n    await page.keyboard.press('Tab');\n    await page.keyboard.press('ArrowDown');\n    await page.keyboard.press('ArrowDown');\n    await page.keyboard.press('ArrowUp');\n\n    const listbox = await page.$('[role=\"listbox\"]');\n\n    const ariaActiveDescendant = await page.evaluate((el) => {\n      const id = el.getAttribute('aria-activedescendant');\n      return document.getElementById(id).getAttribute('aria-selected');\n    }, listbox);\n\n    expect(ariaActiveDescendant).toBe('true');\n    await page.keyboard.press('Tab');\n\n    await expect(page).toMatchElement(\n      `button[aria-label=\"Delete ${OPEN_SANS_CONDENSED_LIGHT}\"]`\n    );\n\n    await takeSnapshot(page, 'Custom Fonts Settings');\n  });\n\n  it('should show error on trying add font twice', async () => {\n    await addCustomFont(OPEN_SANS_CONDENSED_LIGHT_URL);\n    await addCustomFont(OPEN_SANS_CONDENSED_LIGHT_URL);\n\n    await expect(page).toMatchTextContent(\n      'A font with the name Open Sans Condensed Light already exists.'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/dataRemovalSettings.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  enableCheckbox,\n  visitSettings,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\n\nconst checkbox = 'input[data-testid=\"data-removal-settings-checkbox\"]';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Admin User', () => {\n  beforeEach(async () => {\n    await visitSettings();\n    await enableCheckbox(checkbox);\n  });\n\n  it('should let me see and update data removal settings', async () => {\n    // verify that the data removal checkbox can be changed\n    await expect(page).toMatchElement(`${checkbox}:checked`);\n\n    await disableCheckbox(checkbox);\n\n    // verify that the data removal checkbox can be changed\n    await expect(page).toMatchElement(`${checkbox}:not(:checked)`);\n    await disableCheckbox(checkbox);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/monetization.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { visitSettings } from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { monetizationDropdownSelector } from '../../../../utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Admin User', () => {\n  it('should let me see and update monetization settings', async () => {\n    await visitSettings();\n\n    // Small trick to ensure we scroll to this input.\n    const monetizationDropdown = await page.$(monetizationDropdownSelector);\n    await monetizationDropdown.focus();\n\n    await expect(page).toMatchElement(monetizationDropdownSelector);\n\n    // verify that the monetization settings can be changed\n    await expect(page).toClick(monetizationDropdownSelector, { text: 'None' });\n\n    await expect(page).toClick('li', { text: 'Google AdSense' });\n    await expect(page).toMatchElement(monetizationDropdownSelector, {\n      text: 'Google AdSense',\n    });\n\n    // reset monetization setting\n    await expect(page).toClick(monetizationDropdownSelector, {\n      text: 'Google AdSense',\n    });\n    await expect(page).toClick('li', { text: 'None' });\n    await expect(page).toMatchElement(monetizationDropdownSelector, {\n      text: 'None',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/publisherLogo.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  visitSettings,\n  uploadPublisherLogo,\n  withExperimentalFeatures,\n  deleteAllMedia,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst ERROR_TEXT =\n  'Sorry, this file type is not supported. Only jpg, png, and static gifs are supported for publisher logos.';\n\nasync function deleteAllPublisherLogos() {\n  const publisherLogos = await page.$$(\n    '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n  );\n  // We can only delete all but one publisher logo.\n  publisherLogos.shift();\n\n  /* eslint-disable no-await-in-loop */\n  for (const item of publisherLogos) {\n    await item.$eval('button', (button) => button.click());\n\n    await expect(item).toClick('button[aria-label^=\"Publisher logo menu for\"]');\n\n    await page.waitForSelector(\n      '[role=\"menu\"][aria-label=\"Menu\"][aria-expanded=\"true\"]'\n    );\n\n    await expect(item).toClick(\n      '[role=\"menu\"][aria-label=\"Menu\"] button[role=\"menuitem\"]',\n      {\n        text: 'Delete',\n        visible: true,\n      }\n    );\n\n    await expect(page).toMatchTextContent('Setting saved.');\n  }\n  /* eslint-enable no-await-in-loop */\n}\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey test.\ndescribe.skip('Publisher Logos', () => {\n  describe('Without SVG support', () => {\n    beforeEach(async () => {\n      await deleteAllMedia(); // Will also delete *all* publisher logos.\n      await visitSettings();\n      await uploadPublisherLogo('web-stories.png');\n      await uploadPublisherLogo('wordpress-logo.png');\n      await uploadPublisherLogo('google.png');\n    });\n\n    afterEach(async () => {\n      await deleteAllMedia();\n    });\n\n    it('should update the default logo', async () => {\n      const publisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      const initialDefault = publisherLogos[0];\n      const logoToMakeDefault = publisherLogos[1];\n\n      await expect(initialDefault).toMatchElement('p', { text: 'Default' });\n      await expect(logoToMakeDefault).not.toMatchElement('p', {\n        text: 'Default',\n      });\n\n      await logoToMakeDefault.hover();\n\n      await expect(logoToMakeDefault).toClick(\n        'button[aria-label^=\"Publisher logo menu for\"]'\n      );\n\n      // Flyout animation.\n      // TODO: Remove and replace with waitForSelector or locator API.\n      await new Promise((r) => setTimeout(r, 100));\n\n      await page.waitForSelector(\n        '[role=\"menu\"][aria-label=\"Menu\"][aria-expanded=\"true\"]'\n      );\n\n      await Promise.all([\n        expect(logoToMakeDefault).toClick(\n          '[aria-label=\"Menu\"] button[role=\"menuitem\"]',\n          {\n            text: 'Set as Default',\n            visible: true,\n          }\n        ),\n        page.waitForResponse(\n          (response) =>\n            // eslint-disable-next-line jest/no-conditional-in-test\n            response.url().includes('/web-stories/v1/publisher-logos') &&\n            response.status() === 200\n        ),\n      ]);\n\n      await expect(page).toMatchTextContent('Setting saved.');\n\n      const updatedPublisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      const oldDefault = updatedPublisherLogos[0];\n      const newDefault = updatedPublisherLogos[1];\n\n      await expect(oldDefault).not.toMatchElement('p', { text: 'Default' });\n      await expect(newDefault).toMatchElement('p', { text: 'Default' });\n    });\n\n    it('should update the default logo via keyboard', async () => {\n      const publisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      // eslint-disable-next-line jest/no-conditional-in-test\n      if (1 === (publisherLogos?.length || 0)) {\n        throw new Error('Not enough publisher logos');\n      }\n\n      const initialDefault = await publisherLogos[0];\n      expect(initialDefault).toBeTruthy();\n      await expect(initialDefault).toMatchElement('p', { text: 'Default' });\n\n      await page.focus('[aria-label=\"Viewing existing publisher logos\"]');\n\n      await page.keyboard.press('ArrowRight');\n      await page.keyboard.press('ArrowRight');\n\n      await page.keyboard.press('Tab');\n      await page.keyboard.press('Enter');\n      await page.keyboard.press('Enter');\n\n      await expect(page).toMatchTextContent('Setting saved.');\n\n      const updatedPublisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      const oldDefault = updatedPublisherLogos[0];\n      const newDefault = updatedPublisherLogos[1];\n\n      expect(oldDefault).toBeTruthy();\n      await expect(oldDefault).not.toMatchElement('p', { text: 'Default' });\n\n      expect(newDefault).toBeTruthy();\n      await expect(newDefault).toMatchElement('p', { text: 'Default' });\n    });\n\n    it('should remove a logo via keyboard', async () => {\n      const publisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      // eslint-disable-next-line jest/no-conditional-in-test\n      const initialPublisherLogosLength = publisherLogos.length || 0;\n\n      // eslint-disable-next-line jest/no-conditional-in-test\n      if (1 === initialPublisherLogosLength) {\n        throw new Error('Not enough publisher logos');\n      }\n\n      await page.focus('[aria-label=\"Viewing existing publisher logos\"]');\n\n      await page.keyboard.press('ArrowRight');\n      await page.keyboard.press('ArrowRight');\n      await page.keyboard.press('Tab');\n      await page.keyboard.press('Enter');\n      await page.keyboard.press('ArrowDown');\n      await page.keyboard.press('Enter');\n\n      await expect(page).toMatchTextContent('Setting saved.');\n\n      const updatedPublisherLogos = await page.$$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]'\n      );\n\n      // eslint-disable-next-line jest/no-conditional-in-test\n      const updatedPublisherLogosLength = updatedPublisherLogos.length || 0;\n\n      expect(updatedPublisherLogosLength).toBe(initialPublisherLogosLength - 1);\n    });\n\n    it('should not be able to delete the last logo', async () => {\n      await deleteAllPublisherLogos();\n\n      const firstLogo = await page.$(\n        '[role=\"list\"][aria-label=\"Viewing existing publisher logos\"] [role=\"listitem\"]:nth-of-type(1)'\n      );\n\n      await firstLogo.hover();\n\n      await expect(firstLogo).not.toMatchElement(\n        'button[aria-label^=\"Publisher logo menu for\"]'\n      );\n    });\n  });\n\n  describe('With SVG support', () => {\n    withExperimentalFeatures(['enableSVG']);\n\n    it('should not allow using an SVG as a publisher logo', async () => {\n      await visitSettings();\n\n      // Upload publisher logo\n      await uploadPublisherLogo('video-play.svg', false);\n\n      // verify error message\n      await expect(page).toMatchElement('[role=\"alert\"]', {\n        text: ERROR_TEXT,\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/shoppingProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { visitSettings } from '@web-stories-wp/e2e-test-utils';\n\nconst shoppingProviderDropdownSelector =\n  'button[aria-label=\"Shopping provider\"]';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Shopify settings', () => {\n  it('should let me see and update shopping provider settings', async () => {\n    await visitSettings();\n    // Small trick to ensure we scroll to this input.\n    const shoppingProviderDropdown = await page.$(\n      shoppingProviderDropdownSelector\n    );\n    await shoppingProviderDropdown.focus();\n\n    await expect(page).toMatchElement(shoppingProviderDropdownSelector);\n\n    // verify that the shopping provider settings can be changed\n    await expect(page).toClick(shoppingProviderDropdownSelector, {\n      text: /None|WooCommerce|Shopify/i,\n    });\n\n    await expect(page).toClick('[role=\"listbox\"] li', { text: 'Shopify' });\n    await expect(page).toMatchElement(shoppingProviderDropdownSelector, {\n      text: 'Shopify',\n    });\n\n    // reset shopping provider setting\n    await expect(page).toClick(shoppingProviderDropdownSelector, {\n      text: 'Shopify',\n    });\n    await expect(page).toClick('[role=\"listbox\"] li', { text: 'None' });\n    await expect(page).toMatchElement(shoppingProviderDropdownSelector, {\n      text: 'None',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/telemetryBanner.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { disableCheckbox, visitSettings } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Telemetry Banner', () => {\n  beforeEach(async () => {\n    await visitSettings();\n  });\n\n  afterEach(async () => {\n    await page.evaluate(() => {\n      window.location.hash = '#';\n      localStorage.clear();\n    });\n  });\n\n  afterAll(async () => {\n    await visitSettings();\n    await disableCheckbox('[data-testid=\"telemetry-settings-checkbox\"]');\n    await page.evaluate(() => {\n      localStorage.removeItem('web_stories_tracking_optin_banner_closed');\n    });\n  });\n\n  it('should render the telemetry settings checkbox', async () => {\n    const settingsView = await page.$('[data-testid=\"editor-settings\"]');\n    expect(settingsView).toBeTruthy();\n\n    const TelemetrySettingsCheckbox = await page.$(\n      '[data-testid=\"telemetry-settings-checkbox\"]'\n    );\n    expect(TelemetrySettingsCheckbox).toBeTruthy();\n  });\n\n  it('should toggle the value and call the API provider when the tracking opt in box is clicked and display snackbar confirmation', async () => {\n    await disableCheckbox('[data-testid=\"telemetry-settings-checkbox\"]');\n\n    const settingsView = await page.$('[data-testid=\"editor-settings\"]');\n    expect(settingsView).toBeTruthy();\n\n    const telemetrySettingsCheckbox = await page.$(\n      '[data-testid=\"telemetry-settings-checkbox\"]'\n    );\n    const checkboxStatus = await telemetrySettingsCheckbox.evaluate((el) => {\n      return el.checked;\n    });\n\n    expect(checkboxStatus).toBeFalse();\n\n    await expect(page).toClick('[data-testid=\"telemetry-settings-checkbox\"]');\n\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 300));\n\n    const updatedCheckboxStatus = await telemetrySettingsCheckbox.evaluate(\n      (el) => {\n        return el.checked;\n      }\n    );\n    expect(updatedCheckboxStatus).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/adminUser/videoSettings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  enableCheckbox,\n  visitSettings,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  videoCacheCheckboxSelector,\n  videoOptimizationCheckboxSelector,\n} from '../../../../utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Admin User', () => {\n  beforeEach(async () => {\n    await visitSettings();\n\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n    await enableCheckbox(videoCacheCheckboxSelector);\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n    await disableCheckbox(videoCacheCheckboxSelector);\n  });\n\n  it('should let me see and update video settings', async () => {\n    // verify that the video optimization checkbox can be changed\n    await expect(page).toMatchElement(\n      `${videoOptimizationCheckboxSelector}:checked`\n    );\n\n    await disableCheckbox(videoOptimizationCheckboxSelector);\n\n    // verify that the video cache checkbox can be changed\n    await expect(page).toMatchElement(`${videoCacheCheckboxSelector}:checked`);\n    await disableCheckbox(videoCacheCheckboxSelector);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/authorUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  enableCheckbox,\n  visitSettings,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  monetizationDropdownSelector,\n  telemetryCheckboxSelector,\n  videoCacheCheckboxSelector,\n  videoOptimizationCheckboxSelector,\n} from '../../../utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Author User', () => {\n  withUser('author', 'password');\n\n  beforeEach(async () => {\n    await visitSettings();\n\n    await enableCheckbox(telemetryCheckboxSelector);\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n\n    await disableCheckbox(telemetryCheckboxSelector);\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n  });\n\n  it('should only let me see and update the telemetry and video optimization settings', async () => {\n    // verify that the telemetry checkbox can be changed\n    await expect(page).toMatchElement(`${telemetryCheckboxSelector}:checked`);\n    await disableCheckbox(telemetryCheckboxSelector);\n\n    // verify that the video optimization checkbox can be changed\n    await expect(page).toMatchElement(\n      `${videoOptimizationCheckboxSelector}:checked`\n    );\n    await disableCheckbox(videoOptimizationCheckboxSelector);\n\n    // verify no other settings are showing\n    await expect(page).not.toMatchElement(\n      '[data-testid=\"publisher-logos-container\"]'\n    );\n    await expect(page).not.toMatchElement(monetizationDropdownSelector);\n    await expect(page).not.toMatchElement(videoCacheCheckboxSelector);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/contributorUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  enableCheckbox,\n  visitSettings,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  monetizationDropdownSelector,\n  telemetryCheckboxSelector,\n  videoCacheCheckboxSelector,\n  videoOptimizationCheckboxSelector,\n} from '../../../utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Contributor User', () => {\n  withUser('contributor', 'password');\n\n  beforeEach(async () => {\n    await visitSettings();\n\n    await enableCheckbox(telemetryCheckboxSelector);\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n\n    await disableCheckbox(telemetryCheckboxSelector);\n  });\n\n  it('should only let me see and update the telemetry setting', async () => {\n    // verify that the telemetry checkbox can be changed\n    await expect(page).toMatchElement(`${telemetryCheckboxSelector}:checked`);\n    await disableCheckbox(telemetryCheckboxSelector);\n\n    // verify no other settings are showing\n    await expect(page).not.toMatchElement(\n      '[data-testid=\"publisher-logos-container\"]'\n    );\n    await expect(page).not.toMatchElement(monetizationDropdownSelector);\n    await expect(page).not.toMatchElement(videoOptimizationCheckboxSelector);\n    await expect(page).not.toMatchElement(videoCacheCheckboxSelector);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/settings/editorUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  enableCheckbox,\n  visitSettings,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n/**\n * Internal dependencies\n */\nimport {\n  monetizationDropdownSelector,\n  telemetryCheckboxSelector,\n  videoCacheCheckboxSelector,\n  videoOptimizationCheckboxSelector,\n} from '../../../utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Editor User', () => {\n  withUser('editor', 'password');\n\n  beforeEach(async () => {\n    await visitSettings();\n\n    await enableCheckbox(telemetryCheckboxSelector);\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n\n    await disableCheckbox(telemetryCheckboxSelector);\n    await enableCheckbox(videoOptimizationCheckboxSelector);\n  });\n\n  it('should only let me see and update the telemetry and video optimization settings', async () => {\n    // verify that the telemetry checkbox can be changed\n    await expect(page).toMatchElement(`${telemetryCheckboxSelector}:checked`);\n    await disableCheckbox(telemetryCheckboxSelector);\n\n    // verify that the video optimization checkbox can be changed\n    await expect(page).toMatchElement(\n      `${videoOptimizationCheckboxSelector}:checked`\n    );\n    await disableCheckbox(videoOptimizationCheckboxSelector);\n\n    // verify no other settings are showing\n    await expect(page).not.toMatchElement(\n      '[data-testid=\"publisher-logos-container\"]'\n    );\n    await expect(page).not.toMatchElement(monetizationDropdownSelector);\n    await expect(page).not.toMatchElement(videoCacheCheckboxSelector);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/telemetryBanner.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  disableCheckbox,\n  visitDashboard,\n  visitSettings,\n  clearLocalStorage,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Telemetry Banner', () => {\n  beforeAll(async () => {\n    await visitSettings();\n    await disableCheckbox('[data-testid=\"telemetry-settings-checkbox\"]');\n    await clearLocalStorage();\n  });\n\n  beforeEach(async () => {\n    await visitDashboard();\n  });\n\n  afterEach(async () => {\n    await clearLocalStorage();\n  });\n\n  afterAll(async () => {\n    await visitSettings();\n    await disableCheckbox('[data-testid=\"telemetry-settings-checkbox\"]');\n    await page.evaluate(() => {\n      localStorage.removeItem('web_stories_tracking_optin_banner_closed');\n    });\n  });\n\n  it('should render the telemetry opt in banner', async () => {\n    await expect(page).toMatchTextContent('Help improve the editor!');\n  });\n\n  it('should close the banner when the exit button is closed', async () => {\n    await expect(page).toMatchTextContent('Help improve the editor!');\n    await expect(page).toClick('[aria-label=\"Dismiss telemetry banner\"]');\n    await expect(page).not.toMatchTextContent('Help improve the editor!');\n  });\n\n  it('should not display the banner after it has been closed', async () => {\n    await expect(page).toMatchTextContent('Help improve the editor!');\n    await expect(page).toClick('[aria-label=\"Dismiss telemetry banner\"]');\n    await page.reload();\n    await expect(page).not.toMatchTextContent('Help improve the editor!');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/dashboard/templates/useTemplate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  visitDashboard,\n  withPlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Explore Templates', () => {\n  it('should be able to use existing template for new story', async () => {\n    await visitDashboard();\n\n    await expect(page).toMatchElement(\n      '[aria-label=\"Main dashboard navigation\"]'\n    );\n\n    await expect(page).toClick('[aria-label=\"Main dashboard navigation\"] a', {\n      text: 'Explore Templates',\n    });\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 100));\n\n    await expect(page).toMatchTextContent(/Viewing all (\\d+) templates/);\n\n    await expect(page).toClick('[data-testid=\"template-grid-item-1\"] button', {\n      text: 'See details',\n    });\n    // Get count of template colors to compare to 'saved colors' in the editor.\n    const templateDetailsColors = await page.evaluate(() => {\n      const elements = document.querySelectorAll(\n        'li[data-testid=\"detail-template-color\"]'\n      );\n      const count = elements.length;\n      const colors = [];\n      for (let i = 0; i < count; i++) {\n        colors.push(window.getComputedStyle(elements[i]).backgroundColor);\n      }\n      return colors;\n    });\n\n    await Promise.all([\n      expect(page).toClick(\n        'button[aria-label=\"Use Fresh & Bright template to create new story\"]'\n      ),\n      page.waitForNavigation(),\n    ]);\n\n    // Wait for title input to load before continuing.\n    await page.waitForSelector('input[placeholder=\"Add title\"]');\n\n    // Wait for skeleton thumbnails in the carousel to render which gives footer time to also render\n    await page.waitForFunction(\n      () =>\n        !document.querySelector(\n          'li[data-testid^=\"carousel-page-preview-skeleton\"]'\n        ),\n      { timeout: 5000 } // requestIdleCallback in the carousel kicks in after 5s the latest.\n    );\n\n    // Click on text element so the 'Saved Colors' panel is present.\n    // Pressing Option/Alt key because it's part of a layer group.\n    await page.keyboard.down('Alt');\n    await expect(page).toClick(\n      '[data-testid=\"frameElement\"][aria-label^=\"Element: Fresh\"]'\n    );\n    await page.keyboard.up('Alt');\n\n    await takeSnapshot(page, 'Story From Template');\n\n    // Open the color picker from the floating menu\n    await expect(page).toClick('button[aria-label=\"Text color\"]');\n\n    // Get all saved story colors and subtract 1 button for adding other colors\n    const editorSavedColors = await page.evaluate(() => {\n      const elements = document.querySelectorAll(\n        'div[data-testid=\"saved-story-colors\"] button > div'\n      );\n      const count = elements.length;\n      const colors = [];\n      for (let i = 0; i < count; i++) {\n        colors.push(window.getComputedStyle(elements[i]).backgroundColor);\n      }\n      return colors;\n    });\n\n    expect(editorSavedColors).toStrictEqual(templateDetailsColors);\n  });\n\n  describe('Disabled', () => {\n    withPlugin('e2e-tests-disable-default-templates');\n\n    it('should not display Explore Templates screen', async () => {\n      await visitDashboard();\n\n      await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n\n      await expect(page).not.toMatchElement('a', {\n        text: 'Explore Templates',\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/authorUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  previewStory,\n  insertStoryTitle,\n  withUser,\n  publishStory,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Author User', () => {\n  withUser('author', 'password');\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  it('should directly preview a story without markup being stripped', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Previewing without Publishing');\n\n    await expect(page).toClick('[data-testid=\"mediaElement-image\"]');\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    const previewPage = await previewStory();\n    await expect(previewPage).toMatchElement('amp-img');\n\n    await page.bringToFront();\n    await previewPage.close();\n  });\n\n  it('should publish a story without markup being stripped', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Publishing and Previewing');\n\n    // Make some changes _before_ publishing the story.\n    await expect(page).toClick('[data-testid=\"mediaElement-image\"]');\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    await publishStory();\n\n    const previewPage = await previewStory();\n    await expect(previewPage).toMatchElement('amp-img');\n\n    await previewPage.close();\n    await page.bringToFront();\n  });\n\n  it('should publish and preview a story without markup being stripped', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Autosaving and Previewing');\n\n    await publishStory();\n\n    // Make some changes _after_ publishing so previewing will cause an autosave.\n    await expect(page).toClick('[data-testid=\"mediaElement-image\"]');\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    const previewPage = await previewStory();\n    await expect(previewPage).toMatchElement('amp-img');\n\n    await page.bringToFront();\n    await previewPage.close();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/backgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  uploadFile,\n  deleteMedia,\n  takeSnapshot,\n  withPlugin,\n  insertStoryTitle,\n  publishStory,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst VTT_URL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets/test.vtt`;\nconst MP3_URL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets/audio.mp3`;\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Background Audio', () => {\n  let uploadedFiles;\n\n  beforeEach(() => (uploadedFiles = []));\n\n  afterEach(async () => {\n    for (const file of uploadedFiles) {\n      // eslint-disable-next-line no-await-in-loop\n      await deleteMedia(file);\n    }\n  });\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  describe('Story Background Audio', () => {\n    it('should allow adding background audio', async () => {\n      await createNewStory();\n\n      await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n\n      await expect(page).toMatchTextContent('Background Audio');\n\n      // Toggle the panel which is collapsed by default.\n      await expect(page).toClick('[aria-label=\"Background Audio\"]');\n\n      await expect(page).toClick('button', { text: 'Upload an audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: true,\n      });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileName = await uploadFile('audio.mp3', false);\n      uploadedFiles.push(fileName);\n\n      await expect(page).toClick('button', { text: 'Select audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: false,\n      });\n\n      await expect(page).toMatchTextContent(fileName);\n\n      await expect(page).toMatchElement('button[aria-label=\"Play\"]');\n\n      await takeSnapshot(page, 'Story Background Audio');\n    });\n  });\n\n  describe('Page Background Audio', () => {\n    it('should allow adding background audio', async () => {\n      await createNewStory();\n\n      await page.focus('[aria-label=\"Element: Background\"]');\n\n      await expect(page).toClick('li', { text: /^Style$/i });\n\n      await expect(page).toMatchTextContent('Page Background Audio');\n\n      await expect(page).toClick('button', { text: 'Upload an audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: true,\n      });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileName = await uploadFile('audio.mp3', false);\n      uploadedFiles.push(fileName);\n\n      await expect(page).toClick('button', { text: 'Select audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: false,\n      });\n\n      await expect(page).toMatchTextContent(fileName);\n\n      await expect(page).toMatchElement('button[aria-label=\"Play\"]');\n\n      await expect(page).toMatchElement('label', {\n        text: 'Loop',\n      });\n    });\n\n    it('should allow adding background audio with captions', async () => {\n      await createNewStory();\n\n      await page.focus('[aria-label=\"Element: Background\"]');\n\n      await expect(page).toClick('li', { text: /^Style$/i });\n\n      await expect(page).toMatchTextContent('Page Background Audio');\n\n      await expect(page).toClick('button', { text: 'Upload an audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: true,\n      });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileName = await uploadFile('audio.mp3', false);\n      uploadedFiles.push(fileName);\n\n      await expect(page).toClick('button', { text: 'Select audio file' });\n\n      await page.waitForSelector('.media-modal', {\n        visible: false,\n      });\n\n      await expect(page).toMatchTextContent(fileName);\n\n      await expect(page).toMatchElement('button[aria-label=\"Play\"]');\n\n      await expect(page).toClick('button', { text: 'Upload audio captions' });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileNameCaptions = await uploadFile('test.vtt');\n      uploadedFiles.push(fileNameCaptions);\n\n      await expect(page).toClick('button', { text: 'Select caption' });\n\n      await expect(page).toMatchTextContent('test.vtt');\n    });\n\n    describe('Hotlink', () => {\n      withPlugin('e2e-tests-hotlink');\n\n      describe('Audio file', () => {\n        it('should allow adding background audio', async () => {\n          await createNewStory();\n\n          await page.focus('[aria-label=\"Element: Background\"]');\n\n          await expect(page).toClick('li', { text: /^Style$/i });\n\n          await expect(page).toMatchTextContent('Page Background Audio');\n\n          await expect(page).toClick('button', { text: 'Link to audio file' });\n\n          await page.waitForSelector('[role=\"dialog\"]');\n          await expect(page).toMatchTextContent(\n            'Insert external background audio'\n          );\n\n          await expect(page).toMatchElement('[role=\"dialog\"]');\n\n          await page.type('[role=\"dialog\"] input[type=\"url\"]', MP3_URL);\n\n          await expect(page).toClick('[role=\"dialog\"] button', {\n            text: 'Use audio file',\n          });\n\n          // Dialog should disappear by now.\n          await expect(page).not.toMatchTextContent(\n            'Insert external background audio'\n          );\n\n          await page.waitForSelector('audio source[src*=\"audio.mp3\"]');\n\n          await expect(page).not.toMatchElement('button', {\n            text: 'Link to audio file',\n          });\n        });\n      });\n\n      describe('Captions', () => {\n        it('should allow adding background audio with captions', async () => {\n          await createNewStory();\n\n          await page.focus('[aria-label=\"Element: Background\"]');\n\n          await expect(page).toClick('li', { text: /^Style$/i });\n\n          await expect(page).toMatchTextContent('Page Background Audio');\n\n          await expect(page).toClick('button', {\n            text: 'Upload an audio file',\n          });\n\n          await page.waitForSelector('.media-modal', {\n            visible: true,\n          });\n\n          await expect(page).toClick('.media-modal #menu-item-upload', {\n            text: 'Upload files',\n            visible: true,\n          });\n\n          const fileName = await uploadFile('audio.mp3', false);\n          uploadedFiles.push(fileName);\n\n          await expect(page).toClick('button', { text: 'Select audio file' });\n\n          await page.waitForSelector('.media-modal', {\n            visible: false,\n          });\n\n          await expect(page).toMatchTextContent(fileName);\n\n          await expect(page).toMatchElement('button[aria-label=\"Play\"]');\n\n          await expect(page).toClick('button', {\n            text: 'Link to caption file',\n          });\n\n          await page.waitForSelector('[role=\"dialog\"]');\n          await expect(page).toMatchTextContent('Insert external captions');\n\n          await expect(page).toMatchElement('[role=\"dialog\"]');\n\n          await page.type('[role=\"dialog\"] input[type=\"url\"]', VTT_URL);\n\n          await Promise.all([\n            expect(page).toClick('[role=\"dialog\"] button', {\n              text: 'Use caption',\n            }),\n            expect(page).toMatchElement('[role=\"dialog\"] button[disabled]', {\n              text: 'Selecting caption',\n            }),\n          ]);\n\n          await expect(page).toMatchTextContent('test.vtt');\n        });\n      });\n    });\n\n    describe('Add and remove background audio', () => {\n      // see: https://github.com/GoogleForCreators/web-stories-wp/issues/11229\n      it('should allow saving after deleting audio', async () => {\n        await createNewStory();\n        await insertStoryTitle('Add and delete background audio');\n        await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n\n        // Toggle the panel which is collapsed by default.\n        await expect(page).toClick('[aria-label=\"Background Audio\"]');\n        await expect(page).toClick('button', { text: 'Upload an audio file' });\n\n        await page.waitForSelector('.media-modal', {\n          visible: true,\n        });\n\n        await expect(page).toClick('.media-modal #menu-item-upload', {\n          text: 'Upload files',\n          visible: true,\n        });\n\n        const fileName = await uploadFile('audio.mp3', false);\n        uploadedFiles.push(fileName);\n\n        await expect(page).toClick('button', { text: 'Select audio file' });\n        await page.waitForSelector('.media-modal', { visible: false });\n        await expect(page).toMatchTextContent(fileName);\n        await expect(page).toClick('[aria-label=\"Remove file\"]');\n        await publishStory();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/contributorUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  insertStoryTitle,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Contributor User', () => {\n  withUser('contributor', 'password');\n\n  it('should only be able to submit a story for review', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Submitting for review');\n\n    await expect(page).toMatchElement('button', { text: 'Submit for review' });\n\n    await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n\n    await expect(page).toMatchElement('button[disabled]', {\n      text: /^Public/,\n    });\n    await expect(page).not.toMatchElement('li[role=\"option\"]', {\n      text: /^Private/,\n    });\n    await expect(page).not.toMatchElement('li[role=\"option\"]', {\n      text: /^Password Protected/,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/editor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  createNewStory,\n  toggleVideoOptimization,\n  withRTL,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Story Editor', () => {\n  it('should be able to create a blank story', async () => {\n    await createNewStory();\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    await takeSnapshot(page, 'Empty Editor');\n  });\n\n  describe('RTL', () => {\n    withRTL();\n\n    it('should be able to create a blank story on RTL', async () => {\n      await createNewStory();\n\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n      await takeSnapshot(page, 'Empty Editor on RTL');\n    });\n  });\n\n  it('should have cross-origin isolation enabled', async () => {\n    await createNewStory();\n\n    const crossOriginIsolated = await page.evaluate(\n      () => window.crossOriginIsolated\n    );\n    expect(crossOriginIsolated).toBeTrue();\n  });\n\n  it('should have cross-origin isolation disabled', async () => {\n    await toggleVideoOptimization();\n    await createNewStory();\n\n    const crossOriginIsolated = await page.evaluate(\n      () => window.crossOriginIsolated\n    );\n    expect(crossOriginIsolated).toBeFalse();\n    await toggleVideoOptimization();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/floatingMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addTextElement, createNewStory } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Floating Menu', () => {\n  const floatingMenu = 'section[aria-label=\"Design menu\"]';\n\n  beforeEach(async () => {\n    await createNewStory();\n  });\n\n  it('should display text floating menu', async () => {\n    await addTextElement('Paragraph');\n\n    await page.waitForSelector(floatingMenu);\n    await expect(page).toMatchElement(floatingMenu);\n  });\n\n  it('should display media floating menu', async () => {\n    await expect(page).toClick('[data-testid=\"mediaElement-image\"]');\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    // Floating menu should show up\n    await page.waitForSelector(floatingMenu);\n    await expect(page).toMatchElement(floatingMenu);\n  });\n\n  it('should display media3p floating menu', async () => {\n    // Open a media3p tab\n    const media3pSelector = '#library-tab-media3p';\n\n    await expect(page).toMatchElement(media3pSelector);\n    await expect(page).toClick(media3pSelector);\n\n    await expect(page).toMatchElement('button', { text: 'Image' });\n    await expect(page).toClick('button', { text: 'Image' });\n\n    await page.waitForSelector(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n    // Clicking will only act on the first element.\n    await expect(page).toClick(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n    const insertButton = await page.waitForSelector(\n      `xpath/.//li//span[contains(text(), 'Insert image')]`\n    );\n    await insertButton.click();\n\n    // Floating menu should show up\n    await page.waitForSelector(floatingMenu);\n    await expect(page).toMatchElement(floatingMenu);\n  });\n\n  it('should display shapes floating menu', async () => {\n    // Open a shapes tab\n    await expect(page).toClick('#library-tab-shapes');\n\n    // Add a shape\n    await expect(page).toClick(\n      'div[data-testid=\"shapes-library-pane\"] div:first-child'\n    );\n\n    // Floating menu should show up\n    await page.waitForSelector(floatingMenu);\n    await expect(page).toMatchElement(floatingMenu);\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/fontCheck.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  editStoryWithTitle,\n  insertStoryTitle,\n  publishStory,\n  takeSnapshot,\n  addCustomFont,\n  removeCustomFont,\n  visitSettings,\n  removeAllFonts,\n  addRequestInterception,\n  addTextElement,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst OPEN_SANS_CONDENSED_LIGHT = 'Open Sans Condensed Light';\nconst OPEN_SANS_CONDENSED_LIGHT_URL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets/OpenSansCondensed-Light.ttf`;\n\nasync function changeFont(fontName) {\n  await expect(page).toClick('button[aria-label=\"Font family\"]');\n  await page.keyboard.type(fontName);\n  await page.waitForResponse(\n    (response) =>\n      response.url().includes('web-stories/v1/fonts/?search=') &&\n      response.status() === 200\n  );\n  await expect(page).toMatchElement('li[role=\"option\"]', {\n    text: fontName,\n  });\n  await expect(page).toClick('li[role=\"option\"]', {\n    text: fontName,\n  });\n  await expect(page).toMatchElement('button[aria-label=\"Font family\"]', {\n    text: fontName,\n  });\n}\n\nasync function createStoryWithFont(title, font = OPEN_SANS_CONDENSED_LIGHT) {\n  await createNewStory();\n  await insertStoryTitle(title);\n  await addTextElement('Title 1');\n\n  await changeFont(font);\n\n  await publishStory();\n}\n\nasync function replaceFontWithFontPicker(fontFamily = '') {\n  await changeFont(fontFamily);\n\n  await expect(page).toClick('button', { text: 'Replace font' });\n  await expect(page).toClick('[data-testid=\"textFrame\"]');\n}\n\nasync function replaceFontUsingDefault() {\n  await expect(page).toClick('button', { text: 'Open anyway' });\n  await expect(page).toClick('[data-testid=\"textFrame\"]');\n}\n\nasync function prepareStoryWithFontCheckDialog(title) {\n  await createStoryWithFont(title);\n\n  await visitSettings();\n  await removeCustomFont(OPEN_SANS_CONDENSED_LIGHT);\n\n  await editStoryWithTitle(title);\n\n  await page.waitForSelector('[data-testid=\"textFrame\"]');\n  await page.waitForSelector('[role=\"dialog\"][aria-label=\"Missing Fonts\"]');\n  await expect(page).toMatchElement('button', { text: 'Open anyway' });\n  await expect(page).toMatchElement('button', { text: 'Replace font' });\n}\n\nfunction isPlatformMacOS() {\n  return page.evaluate(() => {\n    const { platform } = window.navigator;\n    return platform.includes('Mac') || ['iPad', 'iPhone'].includes(platform);\n  });\n}\n\nasync function toggleDevTools() {\n  const areDevToolsOpen = Boolean(await page.$('#web-stories-editor textarea'));\n\n  // Cancel whatever current action to ensure the below shortcut works.\n  await page.keyboard.press('Escape');\n  await page.click('#wpadminbar');\n  await page.click('[aria-label=\"Web Stories Editor\"]');\n\n  const isMacOS = await isPlatformMacOS();\n  const Meta = isMacOS ? 'Meta' : 'Control';\n  await page.keyboard.down(Meta);\n  await page.keyboard.down('Shift');\n  await page.keyboard.down('Alt');\n  await page.keyboard.down('J');\n  await page.keyboard.up('J');\n  await page.keyboard.up('Alt');\n  await page.keyboard.up('Shift');\n  await page.keyboard.down(Meta);\n\n  // Dev Tools were not open before, but now they should be open.\n  if (!areDevToolsOpen) {\n    await page.waitForSelector('#web-stories-editor textarea');\n  }\n}\n\nasync function getCurrentStoryData() {\n  await toggleDevTools();\n\n  const textareaContent = await page.evaluate(\n    () => document.querySelector('#web-stories-editor textarea').value\n  );\n\n  await toggleDevTools();\n\n  return JSON.parse(textareaContent);\n}\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey tests.\ndescribe.skip('Font Check', () => {\n  beforeEach(async () => {\n    await visitSettings();\n    await removeAllFonts();\n    await addCustomFont(OPEN_SANS_CONDENSED_LIGHT_URL);\n  });\n\n  afterEach(async () => {\n    await visitSettings();\n    await removeAllFonts();\n  });\n\n  it('should show dialog & replace font with default font', async () => {\n    const title = 'Test replace missing font with (default) Roboto';\n    const replacementFont = 'Roboto';\n    await prepareStoryWithFontCheckDialog(title);\n\n    await takeSnapshot(page, 'Missing fonts dialog');\n\n    await replaceFontUsingDefault(replacementFont);\n\n    await expect(page).toMatchElement('button[aria-label=\"Font family\"]', {\n      text: replacementFont,\n    });\n  });\n\n  it('should show dialog & replace it with selected font', async () => {\n    const title = 'Test replace missing font with Bungee';\n    const replacementFont = 'Bungee';\n    await prepareStoryWithFontCheckDialog(title);\n    await replaceFontWithFontPicker(replacementFont);\n\n    await expect(page).toClick('[data-testid=\"textFrame\"]');\n\n    await expect(page).toMatchElement('button[aria-label=\"Font family\"]', {\n      text: replacementFont,\n    });\n  });\n\n  it('should show dialog & visit settings page', async () => {\n    const title = 'Test visit to settings from dialog';\n    await prepareStoryWithFontCheckDialog(title);\n    await Promise.all([\n      expect(page).toClick('[role=\"dialog\"][aria-label=\"Missing Fonts\"] a', {\n        text: 'Settings',\n      }),\n      page.waitForNavigation(),\n    ]);\n    await expect(page).toMatchElement('h2', { text: 'Settings' });\n  });\n\n  it('should show dialog & visit dashboard page', async () => {\n    const title = 'Test back to dashboard from dialog';\n    await prepareStoryWithFontCheckDialog(title);\n    await Promise.all([\n      expect(page).toClick('a', { text: 'Back to dashboard' }),\n      page.waitForNavigation(),\n    ]);\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n  });\n\n  it('should redirect to dashboard when clicking outside dialog', async () => {\n    const title = 'Test back to dashboard from dialog';\n    await prepareStoryWithFontCheckDialog(title);\n    // click outside the dialog\n    await Promise.all([page.mouse.click(100, 100), page.waitForNavigation()]);\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n  });\n\n  it('should redirect to dashboard when pressing ESC', async () => {\n    const title = 'Test back to dashboard from dialog';\n    await prepareStoryWithFontCheckDialog(title);\n    await Promise.all([\n      page.keyboard.press('Escape'),\n      page.waitForNavigation(),\n    ]);\n    await expect(page).toMatchElement('h2', { text: 'Dashboard' });\n  });\n\n  it('should receive updated font metrics and not alter history', async () => {\n    const storyTitle = 'Font Check Metrics';\n    await createStoryWithFont(storyTitle, 'Rock Salt');\n\n    const storyData = await getCurrentStoryData();\n\n    const fontBefore = storyData.pages[0].elements[1].font;\n    expect(fontBefore.family).toBe('Rock Salt');\n    expect(fontBefore.fallbacks).toIncludeAllMembers(['cursive']);\n    expect(fontBefore.metrics.upm).toBe(1024);\n\n    const mockResponse = {\n      status: 200,\n      contentType: 'application/json',\n      body: JSON.stringify([\n        {\n          family: 'Rock Salt',\n          fallbacks: ['sans-serif'], // Original is \"cursive\"\n          weights: [900],\n          styles: ['italic'],\n          variants: [[0, 400]],\n          service: 'fonts.google.com',\n          metrics: {\n            upm: 200, // Original is 1024\n            asc: 1623,\n            des: -788,\n            tAsc: 824,\n            tDes: -240,\n            tLGap: 63,\n            wAsc: 1623,\n            wDes: 788,\n            xH: 833,\n            capH: 1154,\n            yMin: -787,\n            yMax: 1623,\n            hAsc: 1623,\n            hDes: -788,\n            lGap: 32,\n          },\n        },\n      ]),\n    };\n\n    await page.setRequestInterception(true);\n    const stopRequestInterception = addRequestInterception((request) => {\n      // eslint-disable-next-line jest/no-conditional-in-test\n      if (request.url().includes('web-stories/v1/fonts') && mockResponse) {\n        request.respond(mockResponse);\n        return;\n      }\n\n      request.continue();\n    });\n\n    await Promise.all([\n      page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test -- False positive.\n          response.url().includes('web-stories/v1/fonts') &&\n          response.status() === 200\n      ),\n      page.reload(),\n    ]);\n\n    stopRequestInterception();\n    await page.setRequestInterception(false);\n\n    const newStoryData = await getCurrentStoryData();\n    const fontAfter = newStoryData.pages[0].elements[1].font;\n    expect(fontAfter.family).toBe('Rock Salt');\n    expect(fontAfter.fallbacks).toIncludeAllMembers(['sans-serif']);\n    expect(fontAfter.metrics.upm).toBe(200);\n\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Undo Changes\"]:disabled'\n    );\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Redo Changes\"]:disabled'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/hotlinking.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  takeSnapshot,\n  withPlugin,\n} from '@web-stories-wp/e2e-test-utils';\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../../config/bootstrap';\n\nconst IMAGE_URL_LOCAL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets/example-3.png`;\nconst IMAGE_URL_CORS_PROXY = 'https://wp.stories.google/e2e-tests/example.jpg';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Media Hotlinking', () => {\n  withPlugin('e2e-tests-hotlink');\n\n  let removeMessage1;\n  let removeMessage2;\n\n  beforeAll(() => {\n    // Ignore CORS error, this is present in the test by design.\n    removeMessage1 = addAllowedErrorMessage('has been blocked by CORS policy');\n    // Ignore resource failing to load. This is only present because of the CORS error.\n    removeMessage2 = addAllowedErrorMessage('Failed to load resource');\n  });\n\n  afterAll(() => {\n    removeMessage1();\n    removeMessage2();\n  });\n\n  // Uses the existence of the element's frame element as an indicator for successful insertion.\n  it('should insert a local image', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('button[aria-label=\"Insert by link\"]');\n\n    await page.waitForSelector('[role=\"dialog\"]');\n    await expect(page).toMatchTextContent('Insert external image or video');\n\n    await page.type('input[type=\"url\"]', IMAGE_URL_LOCAL);\n\n    await expect(page).toMatchElement(\n      '[role=\"dialog\"] button:not([disabled])',\n      {\n        text: 'Insert',\n      }\n    );\n\n    await Promise.all([\n      expect(page).toClick('[role=\"dialog\"] button', {\n        text: 'Insert',\n      }),\n      page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test -- False positive.\n          response.url().includes('web-stories/v1/hotlink/validate') &&\n          response.status() === 200\n      ),\n    ]);\n\n    // Dialog should disappear by now.\n    await expect(page).not.toMatchTextContent('Insert external image or video');\n\n    await expect(page).toMatchElement(`img[src=\"${IMAGE_URL_LOCAL}\"]`);\n  });\n\n  it('should insert an external image via proxy', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('button[aria-label=\"Insert by link\"]');\n\n    await page.waitForSelector('[role=\"dialog\"]');\n    await expect(page).toMatchTextContent('Insert external image or video');\n\n    await page.type('input[type=\"url\"]', IMAGE_URL_CORS_PROXY);\n\n    await expect(page).toMatchElement(\n      '[role=\"dialog\"] button:not([disabled])',\n      {\n        text: 'Insert',\n      }\n    );\n\n    await Promise.all([\n      expect(page).toClick('[role=\"dialog\"] button', {\n        text: 'Insert',\n      }),\n      page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test -- False positive.\n          response.url().includes('web-stories/v1/hotlink/validate') &&\n          response.status() === 200\n      ),\n    ]);\n\n    // Dialog should disappear by now.\n    await expect(page).not.toMatchTextContent('Insert external image or video');\n\n    await page.waitForSelector(\n      '[aria-label=\"Design options for selected element\"]'\n    );\n\n    await expect(page).toMatchElement(\n      'img[src*=\"/web-stories/v1/hotlink/proxy/\"]'\n    );\n    await expect(page).not.toMatchElement(`img[src=\"${IMAGE_URL_CORS_PROXY}\"]`);\n\n    await takeSnapshot(page, 'Media Hotlinking - with CORS');\n  });\n\n  describe('Story Poster', () => {\n    it('should insert an external poster via proxy', async () => {\n      await createNewStory();\n\n      await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n      await expect(page).toMatchElement('button[aria-label=\"Poster image\"]');\n\n      await expect(page).toClick('button[aria-label=\"Poster image\"]');\n      await expect(page).toClick('[role=\"menuitem\"]', {\n        text: 'Link to a file',\n      });\n      await page.waitForSelector('[role=\"dialog\"]');\n      await expect(page).toMatchTextContent(\n        'Use external image as poster image'\n      );\n\n      await page.type('input[type=\"url\"]', IMAGE_URL_LOCAL);\n\n      await expect(page).toMatchElement(\n        '[role=\"dialog\"] button:not([disabled])',\n        {\n          text: 'Use image as poster image',\n        }\n      );\n\n      await expect(page).toClick('[role=\"dialog\"] button', {\n        text: 'Use image as poster image',\n      });\n\n      await expect(page).toMatchElement(`img[src=\"${IMAGE_URL_LOCAL}\"]`);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/insert3PMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  withPlugin,\n  clearLocalStorage,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../../config/bootstrap';\n\nconst media3pSelector = '#library-tab-media3p';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\nasync function goToMedia3PTab() {\n  await expect(page).toClick('#library-tab-media3p');\n\n  await expect(page).toMatchTextContent(\n    'Your use of stock content is subject to third party terms'\n  );\n\n  await expect(page).toClick('button', { text: 'Dismiss' });\n\n  await expect(page).not.toMatchTextContent(\n    'Your use of stock content is subject to third party terms'\n  );\n}\n\ndescribe('Inserting 3P Media', () => {\n  let removeErrorMessage;\n\n  beforeAll(() => {\n    // Coverr videos served from stream.mux.com don't have any CORS headers.\n    removeErrorMessage = addAllowedErrorMessage(\n      'NotSameOriginAfterDefaultedToSameOriginByCoep'\n    );\n  });\n\n  afterAll(() => {\n    removeErrorMessage();\n  });\n\n  it('should insert an Unsplash image', async () => {\n    await createNewStory();\n    await clearLocalStorage();\n    await goToMedia3PTab();\n\n    await expect(page).toMatchElement('button', { text: 'Image' });\n    await expect(page).toClick('button', { text: 'Image' });\n\n    await page.waitForSelector(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n    // Clicking will only act on the first element.\n    await expect(page).toClick(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n    const insertButton = await page.waitForSelector(\n      `xpath/.//li//span[contains(text(), 'Insert image')]`\n    );\n    await insertButton.click();\n\n    await page.waitForSelector('[data-testid=\"imageElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n  });\n\n  it('should insert a Coverr video', async () => {\n    await createNewStory();\n    await clearLocalStorage();\n    await goToMedia3PTab();\n\n    await expect(page).toClick('[role=\"tablist\"] [role=\"tab\"] ', {\n      text: 'Video',\n    });\n\n    await page.waitForSelector(\n      '#library-pane-media3p [data-testid=\"mediaElement-video\"]'\n    );\n\n    // This will click in the center of the element, opening the \"+\" insertion menu.\n    await expect(page).toClick(\n      '#library-pane-media3p [data-testid=\"mediaElement-video\"]'\n    );\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert video',\n    });\n\n    await page.waitForSelector('[data-testid=\"videoElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n  });\n\n  it('should insert a Tenor GIF', async () => {\n    await createNewStory();\n    await clearLocalStorage();\n    await goToMedia3PTab();\n\n    await expect(page).toClick('[role=\"tablist\"] [role=\"tab\"] ', {\n      text: 'GIFs',\n    });\n\n    await page.waitForSelector(\n      '#library-pane-media3p [data-testid=\"mediaElement-gif\"]'\n    );\n\n    // This will click in the center of the element, opening the \"+\" insertion menu.\n    await expect(page).toClick(\n      '#library-pane-media3p [data-testid=\"mediaElement-gif\"]'\n    );\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    await page.waitForSelector('[data-testid=\"videoElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n  });\n\n  it('should insert a Tenor sticker', async () => {\n    await createNewStory();\n    await clearLocalStorage();\n    await goToMedia3PTab();\n\n    await expect(page).toClick('[role=\"tablist\"] [role=\"tab\"] ', {\n      text: 'Stickers',\n    });\n\n    await page.waitForSelector(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n\n    // This will click in the center of the element, opening the \"+\" insertion menu.\n    await expect(page).toClick(\n      '#library-pane-media3p [data-testid=\"mediaElement-image\"]'\n    );\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    await page.waitForSelector('[data-testid=\"imageElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n  });\n\n  describe('Disabled', () => {\n    withPlugin('e2e-tests-disable-3p-media');\n\n    it('should not render 3p media tab', async () => {\n      await createNewStory();\n\n      await expect(page).not.toMatchElement(media3pSelector);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/insertMediaFromDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  uploadMedia,\n  deleteMedia,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Inserting Media from Dialog', () => {\n  it('should insert an image by clicking on it', async () => {\n    await createNewStory();\n\n    const filename = await uploadMedia('example-1.jpg', false);\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n\n    await deleteMedia(filename);\n  });\n\n  describe('Contributor User', () => {\n    withUser('contributor', 'password');\n\n    it('should display permission error dialog', async () => {\n      await createNewStory();\n      await expect(page).toMatchTextContent('Howdy, contributor');\n\n      await expect(page).not.toMatchElement('button[aria-label=\"Upload\"]');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/insertMediaFromLibrary.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  deleteMedia,\n  uploadMedia,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Inserting Media from Media Library', () => {\n  let uploadedFiles;\n\n  beforeEach(() => (uploadedFiles = []));\n\n  afterEach(async () => {\n    for (const file of uploadedFiles) {\n      // eslint-disable-next-line no-await-in-loop\n      await deleteMedia(file);\n    }\n  });\n\n  it('should insert an image by clicking on it', async () => {\n    await createNewStory();\n\n    const filename = await uploadMedia('example-1.jpg', true);\n    uploadedFiles.push(filename);\n\n    await page.waitForSelector('[data-testid=\"mediaElement-image\"]');\n\n    // This will click in the center of the element, opening the \"+\" insertion menu.\n    await expect(page).toClick('[data-testid=\"mediaElement-image\"]');\n    await expect(page).toClick('[role=\"menu\"] [role=\"menuitem\"]', {\n      text: 'Insert image',\n    });\n\n    await page.waitForSelector('[data-testid=\"imageElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/insertMovVideo.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  uploadFile,\n  deleteMedia,\n  toggleVideoOptimization,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Inserting MOV video', () => {\n  let uploadedFiles;\n\n  beforeEach(() => (uploadedFiles = []));\n\n  afterEach(async () => {\n    for (const file of uploadedFiles) {\n      // eslint-disable-next-line no-await-in-loop\n      await deleteMedia(file);\n    }\n  });\n\n  it('should insert video via media modal', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('button[aria-label=\"Upload\"]');\n\n    await page.waitForSelector('.media-modal', {\n      visible: true,\n    });\n\n    await expect(page).toClick('.media-modal #menu-item-upload', {\n      text: 'Upload files',\n      visible: true,\n    });\n\n    const fileName = await uploadFile('small-video.mov', false);\n    uploadedFiles.push(fileName);\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await page.waitForSelector('[data-testid=\"videoElement\"]', {\n      visible: false,\n    });\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]', {\n      visible: false,\n    });\n  });\n\n  describe('Inserting .mov from dialog', () => {\n    beforeEach(async () => {\n      await toggleVideoOptimization();\n    });\n\n    afterEach(async () => {\n      await toggleVideoOptimization();\n    });\n\n    // Uses the existence of the element's frame element as an indicator for successful insertion.\n    it('should not list the .mov', async () => {\n      await createNewStory();\n      await expect(page).toClick('button[aria-label=\"Upload\"]');\n\n      await page.waitForSelector('.media-modal', {\n        visible: true,\n      });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileName = await uploadFile('small-video.mov', false);\n      uploadedFiles.push(fileName);\n\n      await expect(page).toClick(\n        '.attachments-browser .attachments .attachment:first-of-type'\n      );\n\n      await expect(page).not.toMatchElement('.type-video.subtype-quicktime');\n\n      await page.keyboard.press('Escape');\n\n      await page.waitForSelector('.media-modal', {\n        visible: false,\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/insertWebMVideo.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  previewStory,\n  insertStoryTitle,\n  uploadMedia,\n  deleteMedia,\n  uploadFile,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Inserting WebM Video', () => {\n  let uploadedFiles;\n\n  beforeEach(() => (uploadedFiles = []));\n\n  afterEach(async () => {\n    for (const file of uploadedFiles) {\n      // eslint-disable-next-line no-await-in-loop\n      await deleteMedia(file);\n    }\n  });\n\n  async function openPanel(name) {\n    await expect(page).toClick('li', { text: /^Style$/ });\n\n    // Open the panel.\n    const panel = await page.$(`button[aria-label=\"${name}\"]`);\n    const isCollapsed = await page.evaluate(\n      (button) => button?.getAttribute('aria-expanded') === 'false',\n      panel\n    );\n\n    if (isCollapsed) {\n      await panel.click();\n    }\n  }\n\n  async function openA11yPanel() {\n    // Open the Accessibility panel.\n    await openPanel('Accessibility');\n  }\n\n  it('should insert a video via media modal', async () => {\n    await createNewStory();\n\n    const fileName = await uploadMedia('small-video.webm', false);\n    uploadedFiles.push(fileName);\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n\n    // Wait for poster image (inside Accessibility panel) to appear.\n    await openA11yPanel();\n\n    await page.waitForSelector('[alt=\"Preview poster image\"]');\n    await expect(page).toMatchElement('[alt=\"Preview poster image\"]');\n  });\n\n  it('should insert a video via media modal and add captions', async () => {\n    await createNewStory();\n\n    const fileName = await uploadMedia('small-video.webm', false);\n    uploadedFiles.push(fileName);\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n\n    await openPanel('Caption and Subtitles');\n\n    await expect(page).toClick('button', { text: 'Upload a file' });\n\n    await expect(page).toClick('.media-modal #menu-item-upload', {\n      text: 'Upload files',\n      visible: true,\n    });\n\n    const fileNameCaptions = await uploadFile('test.vtt');\n    uploadedFiles.push(fileNameCaptions);\n\n    await expect(page).toClick('button', { text: 'Select caption' });\n\n    await expect(page).toMatchTextContent('test.vtt');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n  it.skip('should insert a video via media library', async () => {\n    await createNewStory();\n\n    const fileName = await uploadMedia('small-video.webm');\n    uploadedFiles.push(fileName);\n\n    await page.waitForSelector(\n      `[data-testid=\"mediaElement-video\"] [src*=\"${fileName}\"]`\n    );\n    // Clicking will only act on the first element.\n    await expect(page).toClick('[data-testid=\"mediaElement-video\"]');\n    const insertButton = await page.waitForSelector(\n      `xpath/.//li//span[contains(text(), 'Insert video')]`\n    );\n    await insertButton.click();\n\n    await page.waitForSelector('[data-testid=\"videoElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n\n    // Wait for poster image (inside Accessibility panel) to appear.\n    await openA11yPanel();\n    await page.waitForSelector('[alt=\"Preview poster image\"]');\n    await expect(page).toMatchElement('[alt=\"Preview poster image\"]');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n  it.skip('should insert a video via media library and preview on FE', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Publishing with video');\n\n    const fileName = await uploadMedia('small-video.webm');\n    uploadedFiles.push(fileName);\n\n    await page.waitForSelector(\n      `[data-testid=\"mediaElement-video\"] [src*=\"${fileName}\"]`\n    );\n    // Clicking will only act on the first element.\n    await expect(page).toClick('[data-testid=\"mediaElement-video\"]');\n    const insertButton = await page.waitForSelector(\n      `xpath/.//li//span[contains(text(), 'Insert video')]`\n    );\n    await insertButton.click();\n\n    await page.waitForSelector('[data-testid=\"videoElement\"]');\n    await expect(page).toMatchElement('[data-testid=\"videoElement\"]');\n\n    // Wait for poster image (inside Accessibility panel) to appear.\n    await openA11yPanel();\n    await page.waitForSelector('[alt=\"Preview poster image\"]');\n    await expect(page).toMatchElement('[alt=\"Preview poster image\"]');\n\n    const editorPage = page;\n    const previewPage = await previewStory();\n    await expect(previewPage).toMatchElement('amp-video');\n\n    const poster = await previewPage.evaluate((selector) => {\n      return document.querySelector(selector).getAttribute('poster');\n    }, 'amp-video');\n\n    expect(poster).not.toBeNull();\n    expect(poster).toStrictEqual(expect.any(String));\n    expect(poster).not.toBe('');\n\n    await editorPage.bringToFront();\n    await previewPage.close();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/media/svg.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  withExperimentalFeatures,\n  createNewStory,\n  uploadMedia,\n  deleteMedia,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst MODAL = '.media-modal';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('SVG', () => {\n  withExperimentalFeatures(['enableSVG']);\n\n  it('should insert an existing SVG from media dialog', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('button[aria-label=\"Upload\"]');\n    await expect(page).toMatchTextContent('Upload to Story');\n    await expect(page).toClick('button', { text: 'Media Library' });\n\n    await expect(page).toClick(\n      '.attachments-browser .attachments .attachment[aria-label=\"video-play\"]'\n    );\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n\n    await takeSnapshot(page, 'Inserting SVG from Dialog');\n  });\n\n  it('should upload an SVG file via media dialog', async () => {\n    await createNewStory();\n\n    const filename = await uploadMedia('close.svg', false);\n\n    await expect(page).toClick('button', { text: 'Insert into page' });\n\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n\n    await takeSnapshot(page, 'Uploading SVG to editor');\n\n    await deleteMedia(filename);\n  });\n\n  it('should not allow selecting an SVG file as publisher logo', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n    await expect(page).toClick('[aria-label=\"Publisher Logo\"]');\n    await expect(page).toClick('[aria-label=\"Add new\"]');\n\n    await page.waitForSelector(MODAL, {\n      visible: true,\n    });\n\n    await expect(page).toMatchTextContent('Select as publisher logo');\n    await expect(page).toClick('button', { text: 'Media Library' });\n\n    await expect(page).not.toMatchElement(\n      '.attachments-browser .attachments .attachment[aria-label=\"video-play\"]'\n    );\n\n    await page.keyboard.press('Escape');\n\n    await page.waitForSelector(MODAL, {\n      visible: false,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/metaBoxes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  createNewStory,\n  publishStory,\n  withPlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Custom Meta Boxes', () => {\n  describe('Unavailable', () => {\n    it('should not display button to toggle meta boxes', async () => {\n      await createNewStory();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).not.toMatchElement(\n        '[aria-label=\"Third-Party Meta Boxes\"]'\n      );\n    });\n  });\n\n  describe('Available', () => {\n    withPlugin('web-stories-test-plugin-meta-box');\n\n    it('should display meta boxes and save their content', async () => {\n      await createNewStory();\n\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await page.type('input[placeholder=\"Add title\"]', 'Meta Box Test');\n\n      await expect(page).not.toMatchElement(\n        '#web-stories-editor #web_stories_test_meta_box_field',\n        {\n          visible: false,\n        }\n      );\n\n      await expect(page).toClick('[aria-label=\"Third-Party Meta Boxes\"]');\n\n      await expect(page).toMatchElement(\n        '#web-stories-editor #web_stories_test_meta_box_field',\n        {\n          visible: false,\n        }\n      );\n      await page.type(\n        '#web_stories_test_meta_box_field',\n        'Meta Box Test Value'\n      );\n\n      await takeSnapshot(page, 'Custom Meta Boxes');\n\n      // Verify that collapsing works via postbox.js from WordPress.\n\n      await expect(page).toClick('button.handlediv[aria-expanded=\"true\"]');\n      await expect(page).toMatchElement(\n        'button.handlediv[aria-expanded=\"false\"]'\n      );\n\n      await expect(page).toClick('button.handlediv[aria-expanded=\"false\"]');\n      await expect(page).toMatchElement(\n        'button.handlediv[aria-expanded=\"true\"]'\n      );\n\n      await publishStory();\n\n      // Refresh page to verify that the text has been persisted.\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n      await expect(page).not.toMatchElement(\n        '#web-stories-editor #web_stories_test_meta_box_field',\n        {\n          visible: false,\n        }\n      );\n\n      await expect(page).toClick('[aria-label=\"Third-Party Meta Boxes\"]');\n\n      await expect(page).toMatchElement(\n        '#web-stories-editor #web_stories_test_meta_box_field',\n        {\n          visible: false,\n        }\n      );\n\n      const metaBoxValue = await page.evaluate(\n        () => document.getElementById('web_stories_test_meta_box_field').value\n      );\n      await expect(metaBoxValue).toBe('Meta Box Test Value');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/noJS.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { takeSnapshot, createNewStory } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Story Editor with disabled JavaScript', () => {\n  it('should display error message', async () => {\n    // Disable javascript for test.\n    await page.setJavaScriptEnabled(false);\n\n    await createNewStory();\n\n    await expect(page).toMatchElement('.web-stories-wp-no-js');\n\n    // Re-enable javascript for snapshots.\n    await page.setJavaScriptEnabled(true);\n\n    await takeSnapshot(page, 'Editor no js');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/pageTemplates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  addTextElement,\n  clearLocalStorage,\n  createNewStory,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Page Templates', () => {\n  beforeAll(async () => {\n    // force to load default templates in the page template pane.\n    await clearLocalStorage();\n  });\n\n  it('should be able to load an create custom page templates', async () => {\n    await createNewStory();\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    // Use keyboard to open Page Templates panel.\n    await page.focus('ul[aria-label=\"Element Library Selection\"] li');\n    await page.keyboard.press('ArrowLeft');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"true\"]', {\n      text: 'Save current page as template',\n    });\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Select templates type\"]'\n    );\n    await expect(page).toMatchTextContent('Default templates');\n\n    await addTextElement();\n\n    // Go back to the templates panel.\n    await page.click('#library-tab-pageTemplates');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"false\"]', {\n      text: 'Save current page as template',\n    });\n\n    await expect(page).toClick('button', {\n      text: 'Save current page as template',\n    });\n\n    await page.waitForSelector('[role=\"dialog\"]');\n\n    // Add a name for the template\n    await page.type('input[placeholder=\"Untitled\"]', 'Test template');\n\n    // Close dialog\n    await page.keyboard.press('Enter');\n\n    // Adding a custom page template automatically switches to the \"Saved Templates\" view.\n    await expect(page).toMatchTextContent('Page Template saved.');\n    await expect(page).toMatchTextContent('Saved templates');\n    await expect(page).toMatchElement(\n      '[aria-label=\"Page Template Options\"] [role=\"listitem\"]'\n    );\n\n    await takeSnapshot(page, 'Page Templates');\n  });\n\n  it('should be able search default page templates', async () => {\n    await createNewStory();\n    await page.click('#library-tab-pageTemplates');\n    await page.click('[aria-label=\"Search\"]');\n    await page.keyboard.type('baking');\n    await page.keyboard.press('Enter');\n\n    // Fresh & Bright Cover template should not be on the page\n    await expect(page).not.toMatchElement(\n      'button[aria-label=\"Fresh & Bright Cover\"]'\n    );\n\n    await takeSnapshot(page, 'Search Default Page Templates');\n\n    await page.click('[aria-label=\"Clear Search\"]');\n\n    // Fresh & Bright Cover template should be on the page\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Fresh & Bright Cover\"]'\n    );\n  });\n\n  it('should be able search saved page templates', async () => {\n    await createNewStory();\n    await page.click('#library-tab-pageTemplates');\n    await createNewStory();\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    // Use keyboard to open Page Templates panel.\n    await page.focus('ul[aria-label=\"Element Library Selection\"] li');\n    await page.keyboard.press('ArrowLeft');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"true\"]', {\n      text: 'Save current page as template',\n    });\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Select templates type\"]'\n    );\n    await expect(page).toMatchTextContent('Default templates');\n\n    await addTextElement();\n\n    // Go back to the templates panel.\n    await page.click('#library-tab-pageTemplates');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"false\"]', {\n      text: 'Save current page as template',\n    });\n\n    await expect(page).toClick('button', {\n      text: 'Save current page as template',\n    });\n\n    await page.waitForSelector('[role=\"dialog\"]');\n\n    // Add a name for the template\n    await page.type('input[placeholder=\"Untitled\"]', 'Test template');\n\n    // Close dialog\n    await page.keyboard.press('Enter');\n\n    await page.click('[aria-label=\"Search\"]');\n    await page.keyboard.type('Test Template');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement('[aria-label=\"Test template\"]');\n  });\n\n  it('should be able rename saved page templates', async () => {\n    await createNewStory();\n    await page.click('#library-tab-pageTemplates');\n    await createNewStory();\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    // Use keyboard to open Page Templates panel.\n    await page.focus('ul[aria-label=\"Element Library Selection\"] li');\n    await page.keyboard.press('ArrowLeft');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"true\"]', {\n      text: 'Save current page as template',\n    });\n    await expect(page).toMatchElement(\n      'button[aria-label=\"Select templates type\"]'\n    );\n    await expect(page).toMatchTextContent('Default templates');\n\n    await addTextElement();\n\n    // Go back to the templates panel.\n    await page.click('#library-tab-pageTemplates');\n\n    await expect(page).toMatchElement('button[aria-disabled=\"false\"]', {\n      text: 'Save current page as template',\n    });\n\n    await expect(page).toClick('button', {\n      text: 'Save current page as template',\n    });\n\n    await page.waitForSelector('[role=\"dialog\"]');\n\n    // Add a name for the template\n    await page.type('input[placeholder=\"Untitled\"]', 'template name');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement(\n      '[aria-label=\"template name\"][role=\"listitem\"]'\n    );\n\n    await page.hover('[aria-label=\"template name\"][role=\"listitem\"]');\n\n    await page.click('[aria-label=\"More\"]');\n    await page.click('li[role=\"menuitem\"]');\n\n    await page.click('input[placeholder=\"template name\"]');\n    await page.keyboard.press('Backspace');\n    await page.keyboard.type('new template name');\n    await page.keyboard.press('Enter');\n\n    await expect(page).toMatchElement(\n      '[aria-label=\"new template name\"][role=\"listitem\"]'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/passwordProtected.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  addTextElement,\n  createNewStory,\n  insertStoryTitle,\n  previewStory,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Password protected stories', () => {\n  let removeErrorMessage;\n\n  beforeAll(() => {\n    // TODO: Address 404 caused by AMP validation being called for protected post.\n    removeErrorMessage = addAllowedErrorMessage(\n      'the server responded with a status of 404'\n    );\n  });\n\n  afterAll(() => {\n    removeErrorMessage();\n  });\n\n  it('should display password form on frontend', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Password protected story');\n\n    await addTextElement();\n\n    await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n    await expect(page).toClick('button', { text: 'Public' });\n    await expect(page).toClick('li[role=\"option\"]', {\n      text: /^Password Protected/,\n    });\n\n    await expect(page).toMatchElement('input[placeholder=\"Enter a password\"]');\n    await page.type('input[placeholder=\"Enter a password\"]', 'password');\n\n    const editorPage = page;\n    const previewPage = await previewStory(false);\n\n    await expect(previewPage).toMatchTextContent(\n      'Protected: Password protected story'\n    );\n\n    await expect(previewPage).not.toMatchTextContent('Page not found');\n\n    await previewPage.waitForSelector('input[name=\"post_password\"]');\n    await previewPage.focus('input[name=\"post_password\"]');\n\n    await expect(previewPage).toMatchTextContent(\n      /This content is password[- ]protected/\n    );\n\n    await expect(previewPage).toFill('input[name=\"post_password\"]', 'password');\n\n    // Submitting the form will cause the page to be reloaded.\n    await Promise.all([\n      previewPage.waitForNavigation(),\n      previewPage.keyboard.press('Enter'),\n    ]);\n\n    await editorPage.bringToFront();\n    await previewPage.close();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/pendingStories.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  getCurrentUser,\n  insertStoryTitle,\n  setCurrentUser,\n  editStoryWithTitle,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Pending Stories', () => {\n  let currentUser;\n\n  beforeAll(() => {\n    currentUser = getCurrentUser();\n  });\n\n  //eslint-disable-next-line require-await\n  afterAll(async () =>\n    setCurrentUser(currentUser.username, currentUser.password)\n  );\n\n  it('should be able to publish a pending story', async () => {\n    await setCurrentUser('contributor', 'password');\n\n    await createNewStory();\n\n    await insertStoryTitle('Submitting for review');\n\n    // Contributor can only save or submit for review.\n    await expect(page).toMatchElement('button[aria-label=\"Save draft\"]');\n    await expect(page).toMatchElement('button', {\n      text: 'Submit for review',\n    });\n\n    await expect(page).toClick('button', { text: 'Submit for review' });\n    // Contributor is now in story details modal\n    await expect(page).toMatchElement('div[aria-label=\"Story details\"]');\n    await expect(page).toClick('div[aria-label=\"Story details\"] button', {\n      text: 'Submit for review',\n    });\n    // Modal closes\n    await expect(page).toMatchElement('button:not([disabled]', {\n      text: 'Submit for review',\n    });\n    await expect(page).toMatchElement('button[aria-label=\"Switch to Draft\"]');\n\n    await setCurrentUser('admin', 'password');\n\n    await editStoryWithTitle('Submitting for review');\n\n    // An admin can take save a pending story (so it stays pending), switch to draft,\n    // or publish.\n    await expect(page).toMatchElement('button[aria-label=\"Switch to Draft\"]');\n    await expect(page).toMatchElement('button[aria-label=\"Save as pending\"]');\n    await expect(page).toMatchElement('button', { text: /^Publish$/ });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/prePublishChecklist/adminUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  publishStory,\n  triggerHighPriorityChecklistSection,\n  takeSnapshot,\n  addTextElement,\n  insertStoryTitle,\n  uploadFile,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\nasync function uploadPosterImage(file) {\n  await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n\n  await expect(page).toClick('button[aria-label=\"Poster image\"]');\n  await expect(page).toClick('[role=\"menuitem\"]', { text: 'Upload a file' });\n\n  await page.waitForSelector('.media-modal', {\n    visible: true,\n  });\n\n  await expect(page).toClick('.media-modal #menu-item-upload', {\n    text: 'Upload files',\n    visible: true,\n  });\n\n  const fileName = await uploadFile(file, false);\n\n  await expect(page).toClick('button', {\n    text: 'Select as poster image',\n    visible: true,\n  });\n\n  await expect(page).toClick('button', {\n    text: 'Crop image',\n    visible: true,\n  });\n\n  await page.keyboard.press('Escape');\n\n  await page.waitForSelector('.media-modal', {\n    visible: false,\n  });\n\n  await page.waitForSelector('[alt=\"Preview image\"]');\n  await expect(page).toMatchElement('[alt=\"Preview image\"]');\n\n  return fileName;\n}\n\ndescribe('Pre-Publish Checklist : Admin User', () => {\n  const addNewPage = async () => {\n    await expect(page).toClick('button[aria-label=\"Add New Page\"]');\n    await addTextElement();\n  };\n  const addPages = async (number) => {\n    for (let i = 0; i < number; i++) {\n      // eslint-disable-next-line no-await-in-loop\n      await addNewPage();\n    }\n  };\n\n  beforeEach(async () => {\n    await createNewStory();\n  });\n\n  it('should show the checklist', async () => {\n    await expect(page).toClick('button[aria-label=\"Checklist\"]');\n    await triggerHighPriorityChecklistSection();\n    await expect(page).toMatchElement(\n      '#pre-publish-checklist[data-isexpanded=\"true\"]'\n    );\n  });\n\n  it('should show that there is no poster attached to the story', async () => {\n    await expect(page).toClick('[data-testid^=\"mediaElement\"]');\n    const insertButton = await page.waitForSelector(\n      `xpath/.//li//span[contains(text(), 'Insert image')]`\n    );\n    await insertButton.click();\n    await expect(page).toMatchElement('[data-testid=\"imageElement\"]');\n\n    await insertStoryTitle(\n      'Prepublish Checklist - admin - missing poster warning'\n    );\n\n    await publishStory();\n\n    await page.reload();\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    await expect(page).toClick('button[aria-label^=\"Checklist: \"]');\n    await expect(page).toMatchElement(\n      '#pre-publish-checklist[data-isexpanded=\"true\"]'\n    );\n    await expect(page).toMatchTextContent('Add poster image');\n    await takeSnapshot(page, 'Pre-publish Checklist');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey test.\n  it.skip('should show cards related to poster image issues', async () => {\n    await addTextElement();\n    await addPages(3);\n\n    await expect(page).toClick('button', { text: 'Publish' });\n    await expect(page).toClick(\n      'div[aria-label=\"Story details\"] button[aria-label^=\"Checklist\"]'\n    );\n    await expect(page).toMatchTextContent('Add poster image');\n\n    await expect(page).toClick('p', { text: 'Document' });\n\n    //find publish panel button\n    const publishPanelButton = await expect(page).toMatchElement(\n      '#sidebar-tab-document button',\n      { text: 'Publishing' }\n    );\n\n    const isPublishPanelExpanded = await publishPanelButton.evaluate(\n      (node) => node.getAttribute('aria-expanded') === 'true'\n    );\n\n    //open publish panel if not open\n\n    //eslint-disable-next-line jest/no-conditional-in-test\n    if (!isPublishPanelExpanded) {\n      await publishPanelButton.click();\n    }\n\n    await uploadPosterImage('example-1.jpg');\n\n    await expect(page).not.toMatchTextContent('Add poster image');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey test.\n  it.skip('should focus on media button when poster image issue card is clicked', async () => {\n    await addTextElement();\n    await addPages(3);\n\n    await expect(page).toClick('button', { text: 'Publish' });\n    await expect(page).toClick(\n      'div[aria-label=\"Story details\"] button[aria-label^=\"Checklist\"]'\n    );\n    const title = await expect(page).toMatchElement('h2', {\n      text: 'Add poster image',\n    });\n    const button = await title.evaluateHandle((node) => node.parentNode);\n\n    expect(button).toBeDefined();\n\n    await button.click();\n\n    const isMediaPickerInFocus = await page.evaluate(\n      () => document.activeElement.getAttribute('aria-label') === 'Poster image'\n    );\n\n    expect(isMediaPickerInFocus).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/prePublishChecklist/contributorUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createNewStory, withUser } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Pre-Publish Checklist : Contributor User', () => {\n  withUser('contributor', 'password');\n\n  it('should not show messages user does not have permission for anyway', async () => {\n    await createNewStory();\n\n    await expect(page).toClick('button[aria-label=\"Checklist\"]');\n    await expect(page).toMatchElement(\n      '#pre-publish-checklist[data-isexpanded=\"true\"]'\n    );\n\n    // verify no issues are present\n    await expect(page).toMatchElement('p', {\n      text: 'You are all set for now. Return to this checklist as you build your Web Story for tips on how to improve it.',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/publishPanel/adminUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createNewStory } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Publish panel in document tab', () => {\n  const openPublishPanel = async () => {\n    await expect(page).toClick('p', { text: 'Document' });\n\n    //find publish panel button\n    const publishPanelButton = await expect(page).toMatchElement(\n      '#sidebar-tab-document button',\n      { text: 'Publishing' }\n    );\n\n    const isPublishPanelExpanded = await publishPanelButton.evaluate(\n      (node) => node.getAttribute('aria-expanded') === 'true'\n    );\n\n    //open publish panel if not open\n    if (!isPublishPanelExpanded) {\n      await publishPanelButton.click();\n    }\n  };\n  beforeEach(async () => {\n    await createNewStory();\n    await openPublishPanel();\n  });\n\n  it('should allow changing author', async () => {\n    await expect(page).toClick('button[aria-label=\"Author\"]', {\n      text: 'admin',\n    });\n\n    await expect(page).toMatchElement('[aria-label=\"Option List Selector\"]', {\n      text: 'author',\n    });\n\n    await expect(page).toClick(' [aria-label=\"Option List Selector\"] li', {\n      text: 'author',\n    });\n\n    await expect(page).toMatchElement('button[aria-label=\"Author\"]', {\n      text: 'author',\n    });\n  });\n\n  it('should allow searching author', async () => {\n    const authorDropDownButton = await expect(page).toMatchElement(\n      'button[aria-label=\"Author\"]'\n    );\n    await expect(authorDropDownButton).toMatchTextContent('admin');\n\n    await authorDropDownButton.click();\n\n    const authorDropDownOptions = await expect(page).toMatchElement(\n      '[aria-label=\"Option List Selector\"]'\n    );\n\n    const optionListBeforeSearch = await authorDropDownOptions.$$eval(\n      'li[role=\"option\"]',\n      (nodeList) => nodeList.map((node) => node.innerText)\n    );\n    expect(optionListBeforeSearch).toBeDefined();\n    expect(optionListBeforeSearch.length).toBeGreaterThan(1);\n\n    await page.keyboard.type('auth');\n\n    // wait for search results\n    await page.waitForResponse(\n      (response) =>\n        //eslint-disable-next-line jest/no-conditional-in-test\n        response.url().includes('web-stories/v1/users') &&\n        response.url().includes('search=auth') &&\n        response.status() === 200\n    );\n\n    // add small delay after we have results\n    // TODO: Remove and replace with waitForSelector or locator API.\n    await new Promise((r) => setTimeout(r, 400));\n\n    const optionListAfterSearch = await authorDropDownOptions.$$eval(\n      'li[role=\"option\"]',\n      (nodeList) => nodeList.map((node) => node.innerText)\n    );\n\n    expect(optionListAfterSearch).toHaveLength(1);\n\n    await expect(authorDropDownOptions).toClick('li', { text: 'author' });\n    await expect(authorDropDownButton).toMatchTextContent('author');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/publishingFlow.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  insertStoryTitle,\n  withPlugin,\n  publishStory,\n  loadPostEditor,\n  publishPost,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\nasync function addPosterImage() {\n  await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n\n  await expect(page).toClick('button[aria-label=\"Poster image\"]');\n  await expect(page).toClick('[role=\"menuitem\"]', { text: 'Upload a file' });\n\n  await page.waitForSelector('.media-modal', {\n    visible: true,\n  });\n\n  await expect(page).toMatchElement('.media-toolbar-primary button', {\n    text: 'Select as poster image',\n  });\n\n  await expect(page).toClick('button', { text: 'Media Library' });\n\n  await expect(page).toClick(\n    '.attachments-browser .attachments .attachment[aria-label=\"example-3\"]'\n  );\n\n  await expect(page).toClick('.media-toolbar-primary button', {\n    text: 'Select as poster image',\n  });\n\n  await page.waitForSelector('[alt=\"Preview image\"]');\n  await expect(page).toMatchElement('[alt=\"Preview image\"]');\n}\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\nfunction getEditedPostContent() {\n  return page.evaluate(() =>\n    wp.data.select('core/editor').getEditedPostContent()\n  );\n}\n\ndescribe('Publishing Flow', () => {\n  let removeCORSErrorMessage;\n  let removeResourceErrorMessage;\n  let removeAMPPreloadErrorMessage;\n\n  beforeAll(() => {\n    // Ignore CORS errors related to the AMP validator JS.\n    removeCORSErrorMessage = addAllowedErrorMessage(\n      'has been blocked by CORS policy'\n    );\n    removeResourceErrorMessage = addAllowedErrorMessage(\n      'Failed to load resource'\n    );\n    // From the story embedded in amp-story-player\n    removeAMPPreloadErrorMessage = addAllowedErrorMessage(\n      'The resource https://cdn.ampproject.org/v0/amp-story-1.0.js was preloaded using link preload'\n    );\n  });\n\n  afterAll(async () => {\n    removeCORSErrorMessage();\n    removeResourceErrorMessage();\n    removeAMPPreloadErrorMessage();\n\n    await trashAllPosts();\n    await trashAllPosts('web-story');\n  });\n\n  it('should guide me towards creating a new post to embed my story with poster', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Publishing Flow Test');\n    await addPosterImage();\n    await publishStory(false);\n\n    // Create new post and embed story.\n    await Promise.all([\n      expect(page).toClick('a', { text: 'Add to new post' }),\n      page.waitForNavigation(),\n    ]);\n\n    await loadPostEditor();\n\n    await expect(getEditedPostContent()).resolves.toMatch(\n      '<!-- wp:web-stories/embed'\n    );\n    await expect(page).not.toMatchTextContent(\n      'This block contains unexpected or invalid content.'\n    );\n\n    await page.waitForFunction(\n      () => !document.querySelector('.wp-block-web-stories-embed.is-loading')\n    );\n\n    await page.waitForSelector('amp-story-player');\n\n    await expect(page).toMatchElement('amp-story-player');\n    await expect(page).toMatchTextContent('Publishing Flow Test');\n\n    const postPermalink = await publishPost();\n\n    expect(postPermalink).not.toBeNull();\n    expect(postPermalink).toStrictEqual(expect.any(String));\n\n    await page.goto(postPermalink, {\n      waitUntil: 'networkidle2',\n    });\n\n    await expect(page).toMatchElement('amp-story-player');\n    await expect(page).toMatchTextContent('Publishing Flow Test');\n  });\n\n  it('should guide me towards creating a new post to embed my story without poster', async () => {\n    await createNewStory();\n\n    await insertStoryTitle('Publishing Flow Test');\n    await publishStory(false);\n\n    // Create new post and embed story.\n    await Promise.all([\n      expect(page).toClick('a', { text: 'Add to new post' }),\n      page.waitForNavigation(),\n    ]);\n\n    await loadPostEditor();\n\n    await expect(getEditedPostContent()).resolves.toMatch(\n      '<!-- wp:web-stories/embed'\n    );\n    await expect(page).not.toMatchTextContent(\n      'This block contains unexpected or invalid content.'\n    );\n  });\n\n  describe('Classic Editor', () => {\n    withPlugin('classic-editor');\n\n    it('should guide me towards creating a new post to embed my story', async () => {\n      await createNewStory();\n\n      await insertStoryTitle('Publishing Flow Test (Shortcode)');\n      await addPosterImage();\n      await publishStory(false);\n\n      // Create new post and embed story.\n      await Promise.all([\n        expect(page).toClick('a', { text: 'Add to new post' }),\n        page.waitForNavigation(),\n      ]);\n\n      await expect(page).toMatchTextContent('Publishing Flow Test');\n\n      // Switch to HTML mode\n      await expect(page).toClick('#content-html');\n\n      const textEditorContent = await page.$eval(\n        '.wp-editor-area',\n        (element) => element.value\n      );\n\n      expect(textEditorContent).toMatch('[web_stories_embed');\n\n      await expect(page).toClick('#publish');\n\n      const btnTab = '#message a';\n      await page.waitForSelector(btnTab);\n      const postPermalink = await page.evaluate((selector) => {\n        return document.querySelector(selector).getAttribute('href');\n      }, btnTab);\n\n      expect(postPermalink).not.toBeNull();\n      expect(postPermalink).toStrictEqual(expect.any(String));\n\n      await page.goto(postPermalink, {\n        waitUntil: 'networkidle2',\n      });\n\n      await page.waitForSelector('amp-story-player');\n      await expect(page).toMatchElement('amp-story-player');\n      await expect(page).toMatchTextContent('Publishing Flow Test');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/saveStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  addRequestInterception,\n  createNewStory,\n  insertStoryTitle,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Saving Story', () => {\n  let removeErrorMessage;\n  let stopRequestInterception;\n  let mockResponse;\n\n  beforeAll(async () => {\n    removeErrorMessage = addAllowedErrorMessage(\n      'the server responded with a status of'\n    );\n\n    await page.setRequestInterception(true);\n    stopRequestInterception = addRequestInterception((request) => {\n      if (\n        request.url().includes('/web-stories/v1/web-story/') &&\n        mockResponse\n      ) {\n        request.respond(mockResponse);\n        return;\n      }\n\n      request.continue();\n    });\n  });\n\n  afterEach(() => {\n    mockResponse = undefined;\n  });\n\n  afterAll(async () => {\n    removeErrorMessage();\n\n    await page.setRequestInterception(false);\n    stopRequestInterception();\n  });\n\n  it('should display detailed error snackbar message', async () => {\n    mockResponse = {\n      status: 500,\n      body: JSON.stringify({\n        code: 'internal_server_error',\n        message: '<p>There has been a critical error on this website</p>',\n        data: {\n          status: 500,\n        },\n      }),\n    };\n    await createNewStory();\n    await insertStoryTitle('Test story 500');\n    await expect(page).toClick('button', { text: /^Publish$/ });\n    await expect(page).toMatchElement('div[aria-label=\"Story details\"]');\n    await expect(page).toMatchTextContent('Story Details');\n    await expect(page).toClick('div[aria-label=\"Story details\"] button', {\n      text: /^Publish$/,\n    });\n\n    await page.waitForSelector('[role=\"alert\"]');\n    await expect(page).toMatchElement('[role=\"alert\"]', {\n      text: 'Failed to save the story: There has been a critical error on this website (Internal Server Error)',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/shopping/productMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  withPlugin,\n  insertProduct,\n  setShoppingProvider,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Shopping product', () => {\n  describe('Product menu', () => {\n    withPlugin('woocommerce');\n\n    beforeAll(async () => {\n      await setShoppingProvider('WooCommerce');\n    });\n\n    function isStoryEmpty() {\n      return page.evaluate(() =>\n        Boolean(document.getElementById('emptystate-message'))\n      );\n    }\n\n    it('should show a floating menu with product dropdown', async () => {\n      const productText = 'Hoodie with Zipper';\n\n      await createNewStory();\n      await expect(isStoryEmpty()).resolves.toBe(true);\n\n      await insertProduct(productText);\n      await expect(isStoryEmpty()).resolves.toBe(false);\n\n      await page.waitForSelector(\n        '[aria-label=\"Design menu\"] [aria-label=\"Product\"]'\n      );\n\n      await expect(page).toMatchElement(\n        '[aria-label=\"Design menu\"] [aria-label=\"Product\"]',\n        { text: productText }\n      );\n\n      await expect(page).toClick('button', { text: 'Remove product' });\n      await expect(isStoryEmpty()).resolves.toBe(true);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/shopping/schema.json",
    "content": "{\n  \"title\": \"Product\",\n  \"description\": \"A product from an amp-story-shopping configuration.\",\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"properties\": {\n    \"productId\": {\n      \"description\": \"Keys for amp-story-shopping-tag nodes, sent out in analytics events.\",\n      \"type\": \"string\"\n    },\n    \"productUrl\": {\n      \"description\": \"Links to the product's website, when the buy now button is clicked.\",\n      \"type\": \"string\",\n      \"$ref\": \"#/$defs/https\"\n    },\n    \"productTitle\": {\n      \"description\": \"The name of the product, displayed on the tag.\",\n      \"type\": \"string\"\n    },\n    \"productPrice\": {\n      \"description\": \"The price of the product, displayed on the tag.\",\n      \"type\": \"number\"\n    },\n    \"productPriceCurrency\": {\n      \"description\": \"The ISO 4217 currency code of the product price.\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"AED\",\n        \"AFN\",\n        \"ALL\",\n        \"AMD\",\n        \"ANG\",\n        \"AOA\",\n        \"ARS\",\n        \"AUD\",\n        \"AWG\",\n        \"AZN\",\n        \"BAM\",\n        \"BBD\",\n        \"BDT\",\n        \"BGN\",\n        \"BHD\",\n        \"BIF\",\n        \"BMD\",\n        \"BND\",\n        \"BOB\",\n        \"BOV\",\n        \"BRL\",\n        \"BSD\",\n        \"BTN\",\n        \"BWP\",\n        \"BYN\",\n        \"BZD\",\n        \"CAD\",\n        \"CDF\",\n        \"CHE\",\n        \"CHF\",\n        \"CHW\",\n        \"CLF\",\n        \"CLP\",\n        \"CNY\",\n        \"COP\",\n        \"COU\",\n        \"CRC\",\n        \"CUC\",\n        \"CUP\",\n        \"CVE\",\n        \"CZK\",\n        \"DJF\",\n        \"DKK\",\n        \"DOP\",\n        \"DZD\",\n        \"EGP\",\n        \"ERN\",\n        \"ETB\",\n        \"EUR\",\n        \"FJD\",\n        \"FKP\",\n        \"GBP\",\n        \"GEL\",\n        \"GHS\",\n        \"GIP\",\n        \"GMD\",\n        \"GNF\",\n        \"GTQ\",\n        \"GYD\",\n        \"HKD\",\n        \"HNL\",\n        \"HRK\",\n        \"HTG\",\n        \"HUF\",\n        \"IDR\",\n        \"ILS\",\n        \"INR\",\n        \"IQD\",\n        \"IRR\",\n        \"ISK\",\n        \"JMD\",\n        \"JOD\",\n        \"JPY\",\n        \"KES\",\n        \"KGS\",\n        \"KHR\",\n        \"KMF\",\n        \"KPW\",\n        \"KRW\",\n        \"KWD\",\n        \"KYD\",\n        \"KZT\",\n        \"LAK\",\n        \"LBP\",\n        \"LKR\",\n        \"LRD\",\n        \"LSL\",\n        \"LYD\",\n        \"MAD\",\n        \"MDL\",\n        \"MGA\",\n        \"MKD\",\n        \"MMK\",\n        \"MNT\",\n        \"MOP\",\n        \"MRU\",\n        \"MUR\",\n        \"MVR\",\n        \"MWK\",\n        \"MXN\",\n        \"MXV\",\n        \"MYR\",\n        \"MZN\",\n        \"NAD\",\n        \"NGN\",\n        \"NIO\",\n        \"NOK\",\n        \"NPR\",\n        \"NZD\",\n        \"OMR\",\n        \"PAB\",\n        \"PEN\",\n        \"PGK\",\n        \"PHP\",\n        \"PKR\",\n        \"PLN\",\n        \"PYG\",\n        \"QAR\",\n        \"RON\",\n        \"RSD\",\n        \"RUB\",\n        \"RWF\",\n        \"SAR\",\n        \"SBD\",\n        \"SCR\",\n        \"SDG\",\n        \"SEK\",\n        \"SGD\",\n        \"SHP\",\n        \"SLL\",\n        \"SOS\",\n        \"SRD\",\n        \"SSP\",\n        \"STN\",\n        \"SVC\",\n        \"SYP\",\n        \"SZL\",\n        \"THB\",\n        \"TJS\",\n        \"TMT\",\n        \"TND\",\n        \"TOP\",\n        \"TRY\",\n        \"TTD\",\n        \"TWD\",\n        \"TZS\",\n        \"UAH\",\n        \"UGX\",\n        \"USD\",\n        \"USN\",\n        \"UYI\",\n        \"UYU\",\n        \"UYW\",\n        \"UZS\",\n        \"VED\",\n        \"VES\",\n        \"VND\",\n        \"VUV\",\n        \"WST\",\n        \"XAF\",\n        \"XAG\",\n        \"XAU\",\n        \"XBA\",\n        \"XBB\",\n        \"XBC\",\n        \"XBD\",\n        \"XCD\",\n        \"XDR\",\n        \"XOF\",\n        \"XPD\",\n        \"XPF\",\n        \"XPT\",\n        \"XSU\",\n        \"XTS\",\n        \"XUA\",\n        \"XXX\",\n        \"YER\",\n        \"ZAR\",\n        \"ZMW\",\n        \"ZWL\"\n      ]\n    },\n    \"productImages\": {\n      \"description\": \"A list of images for the product used in the carousel of the product page.\",\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"items\": {\n        \"required\": [\"url\", \"alt\"],\n        \"additionalProperties\": false,\n        \"type\": \"object\",\n        \"properties\": {\n          \"url\": {\n            \"type\": \"string\",\n            \"$ref\": \"#/$defs/https\"\n          },\n          \"alt\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    },\n    \"productDetails\": {\n      \"description\": \"Details about the product used in the product details page.\",\n      \"type\": \"string\"\n    },\n    \"productBrand\": {\n      \"description\": \"Brand name of the product used in the tag.\",\n      \"type\": \"string\"\n    },\n    \"productIcon\": {\n      \"description\": \"Links the icon image for the product in the tag. Defaults to a shopping bag icon.\",\n      \"type\": \"string\"\n    },\n    \"productTagText\": {\n      \"description\": \"Text for the Product tag. Supersedes productPrice.\",\n      \"type\": \"string\"\n    },\n    \"aggregateRating\": {\n      \"description\": \"Ratings and review data for the product displayed on the product page.\",\n      \"type\": \"object\",\n      \"required\": [\"ratingValue\", \"reviewCount\", \"reviewUrl\"],\n      \"additionalProperties\": false,\n      \"properties\": {\n        \"ratingValue\": {\n          \"description\": \"The aggregate rating value of the product.\",\n          \"type\": \"number\"\n        },\n        \"reviewCount\": {\n          \"description\": \"The number of reviews for the product.\",\n          \"type\": \"number\"\n        },\n        \"reviewUrl\": {\n          \"description\": \"The Url for the product reviews.\",\n          \"type\": \"string\",\n          \"$ref\": \"#/$defs/https\"\n        }\n      }\n    }\n  },\n  \"required\": [\n    \"productId\",\n    \"productUrl\",\n    \"productTitle\",\n    \"productPrice\",\n    \"productPriceCurrency\",\n    \"productImages\",\n    \"productDetails\"\n  ],\n  \"$defs\": {\n    \"https\": {\n      \"type\": \"string\",\n      \"format\": \"uri-reference\",\n      \"pattern\": \"^(/|https://|https?://(127.0.0.1|([^/]+\\\\.)?localhost)(:[0-9]+)?/)\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/shopping/woocommerce.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  previewStory,\n  withPlugin,\n  insertProduct,\n  setShoppingProvider,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport * as schema from './schema.json';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Shopping', () => {\n  describe('WooCommerce', () => {\n    withPlugin('woocommerce');\n\n    beforeAll(async () => {\n      await setShoppingProvider('WooCommerce');\n    });\n\n    describe('Schema Validation', () => {\n      it('should match a valid schema', async () => {\n        await createNewStory();\n        await insertProduct('Hoodie with Zipper', true);\n        await insertProduct('Album', false);\n        await insertProduct('Sunglasses', false);\n        const previewPage = await previewStory();\n\n        await previewPage.waitForSelector(\n          'amp-story-shopping-attachment script'\n        );\n\n        // pull product data from the DOM\n        const data = await previewPage.evaluate(() =>\n          JSON.parse(\n            document.querySelector('amp-story-shopping-attachment script')\n              .textContent\n          )\n        );\n\n        await page.bringToFront();\n        await previewPage.close();\n        const { items } = data;\n\n        items.forEach((item) => {\n          expect(item).toMatchSchema(schema);\n        });\n\n        // Since product IDs and attachment URLs can change between test runs / setups,\n        // this changes them to something deterministic for the sake of this snapshot.\n        // Note: Could also be done with a custom snapshot serializer.\n        const normalizedItems = items.map((item) => ({\n          ...item,\n          productId: 'product-id',\n          productImages: item.productImages.map((image) => ({\n            ...image,\n            url: 'product-image-url',\n          })),\n        }));\n\n        // eslint-disable-next-line jest/no-large-snapshots\n        expect(normalizedItems).toMatchInlineSnapshot(`\n          [\n            {\n              \"aggregateRating\": {\n                \"ratingValue\": 0,\n                \"reviewCount\": 0,\n                \"reviewUrl\": \"http://localhost:8899/product/hoodie-with-zipper\",\n              },\n              \"productBrand\": \"\",\n              \"productDetails\": \"This is a simple product.\",\n              \"productId\": \"product-id\",\n              \"productImages\": [\n                {\n                  \"alt\": \"\",\n                  \"url\": \"product-image-url\",\n                },\n              ],\n              \"productPrice\": 45,\n              \"productPriceCurrency\": \"USD\",\n              \"productTitle\": \"Hoodie with Zipper\",\n              \"productUrl\": \"http://localhost:8899/product/hoodie-with-zipper\",\n            },\n            {\n              \"aggregateRating\": {\n                \"ratingValue\": 0,\n                \"reviewCount\": 0,\n                \"reviewUrl\": \"http://localhost:8899/product/album\",\n              },\n              \"productBrand\": \"\",\n              \"productDetails\": \"This is a simple, virtual product.\",\n              \"productId\": \"product-id\",\n              \"productImages\": [\n                {\n                  \"alt\": \"\",\n                  \"url\": \"product-image-url\",\n                },\n              ],\n              \"productPrice\": 15,\n              \"productPriceCurrency\": \"USD\",\n              \"productTitle\": \"Album\",\n              \"productUrl\": \"http://localhost:8899/product/album\",\n            },\n            {\n              \"aggregateRating\": {\n                \"ratingValue\": 0,\n                \"reviewCount\": 0,\n                \"reviewUrl\": \"http://localhost:8899/product/sunglasses\",\n              },\n              \"productBrand\": \"\",\n              \"productDetails\": \"This is a simple product.\",\n              \"productId\": \"product-id\",\n              \"productImages\": [\n                {\n                  \"alt\": \"\",\n                  \"url\": \"product-image-url\",\n                },\n              ],\n              \"productPrice\": 90,\n              \"productPriceCurrency\": \"USD\",\n              \"productTitle\": \"Sunglasses\",\n              \"productUrl\": \"http://localhost:8899/product/sunglasses\",\n            },\n          ]\n        `);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/sidebar.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createNewStory, withUser } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Sidebar', () => {\n  describe('Document', () => {\n    it('should display publisher logo upload', async () => {\n      await createNewStory();\n\n      await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n      await expect(page).toMatchElement('[aria-label=\"Publisher Logo\"]');\n    });\n\n    // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n    describe.skip('Contributor User', () => {\n      withUser('contributor', 'password');\n\n      it('should not display publisher logo upload', async () => {\n        await createNewStory();\n        await expect(page).toMatchTextContent('Howdy, contributor');\n\n        await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n        await expect(page).toClick('[aria-label=\"Publisher Logo\"]');\n\n        await expect(page).not.toMatchElement('[aria-label=\"Add new\"]');\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/statusCheck.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createNewStory, withPlugin } from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// TODO: Use request interception instead of WP plugins once supported in Firefox.\n// See https://bugzilla.mozilla.org/show_bug.cgi?id=1587857\ndescribe('Status Check', () => {\n  let removeErrorMessage;\n\n  beforeAll(() => {\n    removeErrorMessage = addAllowedErrorMessage(\n      'the server responded with a status of'\n    );\n  });\n\n  afterAll(() => {\n    removeErrorMessage();\n  });\n\n  describe('200 OK', () => {\n    it('should not display error dialog', async () => {\n      await createNewStory();\n\n      await expect(page).not.toMatchTextContent('Unable to save your story');\n    });\n  });\n\n  describe('Invalid JSON response', () => {\n    withPlugin('web-stories-test-plugin-status-check-200-invalid');\n\n    it('should display error dialog', async () => {\n      await createNewStory();\n\n      await expect(page).toMatchTextContent('Unable to save your story');\n    });\n  });\n\n  describe('403 Forbidden (WAF)', () => {\n    withPlugin('web-stories-test-plugin-status-check-403');\n\n    it('should display error dialog', async () => {\n      await createNewStory();\n\n      await expect(page).toMatchTextContent('Unable to save your story');\n    });\n  });\n\n  describe('500 Internal Server Error', () => {\n    withPlugin('web-stories-test-plugin-status-check-500');\n\n    it('should display error dialog', async () => {\n      await createNewStory();\n\n      await expect(page).toMatchTextContent('Unable to save your story');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/storyDetailsModal/adminUser.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  deleteMedia,\n  takeSnapshot,\n  uploadFile,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../../config/bootstrap';\n\nconst openStoryDetailsModal = async () => {\n  await expect(page).toClick('button', { text: 'Publish' });\n  await expect(page).toMatchElement('div[aria-label=\"Story details\"]');\n};\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Story Details Modal - Admin User', () => {\n  let removeErrorMessage;\n  let uploadedFiles;\n\n  beforeAll(() => {\n    // TODO: Address 404 caused by AMP validation being called for protected post.\n    removeErrorMessage = addAllowedErrorMessage(\n      'the server responded with a status of 404'\n    );\n  });\n\n  beforeEach(async () => {\n    uploadedFiles = [];\n\n    await createNewStory();\n    await openStoryDetailsModal();\n  });\n\n  afterEach(async () => {\n    for (const file of uploadedFiles) {\n      // eslint-disable-next-line no-await-in-loop\n      await deleteMedia(file);\n    }\n  });\n\n  afterAll(() => {\n    removeErrorMessage();\n  });\n\n  describe('Main Details', () => {\n    it('should allow title update', async () => {\n      await expect(page).toMatchElement('textarea[placeholder=\"Add title\"]');\n\n      await page.type(\n        'textarea[placeholder=\"Add title\"]',\n        'Story Details Modal - admin'\n      );\n      await page.keyboard.press('Tab');\n\n      // Make sure title is displayed over preview\n      await expect(page).toMatchElement('div[aria-label=\"Story details\"] h3', {\n        text: 'Story Details Modal - admin',\n      });\n\n      await takeSnapshot(page, 'Story Details Modal - Admin');\n    });\n\n    it('should have 3 visibility options', async () => {\n      await expect(page).toClick('button', { text: 'Public' });\n\n      await expect(page).toClick('[aria-label=\" Option List Selector\"] li', {\n        text: 'Password Protected',\n      });\n\n      await expect(page).toMatchElement('p', {\n        text: 'Visible only to those with the password.',\n      });\n    });\n  });\n\n  describe('Publishing Panel', () => {\n    async function openPublishingPanel() {\n      //find publish panel button\n      const publishPanelButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button',\n        { text: 'Publishing' }\n      );\n\n      const isPublishPanelExpanded = await publishPanelButton.evaluate(\n        (node) => node.getAttribute('aria-expanded') === 'true'\n      );\n      //open publish panel if not open\n      if (!isPublishPanelExpanded) {\n        await publishPanelButton.click();\n      }\n    }\n\n    it('should allow changing author', async () => {\n      await openPublishingPanel();\n\n      const authorDropDownButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Author\"]'\n      );\n      await expect(authorDropDownButton).toMatchTextContent('admin');\n\n      await authorDropDownButton.click();\n\n      const authorDropDownOptions = await expect(page).toMatchElement(\n        '[aria-label=\"Option List Selector\"]'\n      );\n\n      await expect(authorDropDownOptions).toClick('li', { text: 'author' });\n\n      await expect(authorDropDownButton).toMatchTextContent('author');\n    });\n\n    it('should allow searching author', async () => {\n      await openPublishingPanel();\n\n      const authorDropDownButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Author\"]'\n      );\n      await expect(authorDropDownButton).toMatchTextContent('admin');\n\n      await authorDropDownButton.click();\n\n      await expect(page).toMatchElement('[aria-label=\"Option List Selector\"]');\n\n      const optionListBeforeSearch = await page.$$eval(\n        '[aria-label=\"Option List Selector\"] li[role=\"option\"]',\n        (nodeList) => nodeList.map((node) => node.innerText)\n      );\n      expect(optionListBeforeSearch).toBeDefined();\n      expect(optionListBeforeSearch.length).toBeGreaterThan(1);\n\n      await page.keyboard.type('auth');\n\n      // wait for search results\n      await page.waitForResponse(\n        (response) =>\n          //eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('web-stories/v1/users') &&\n          response.url().includes('search=auth') &&\n          response.status() === 200\n      );\n\n      // add small delay after we have results\n      // TODO: Remove and replace with waitForSelector or locator API.\n      await new Promise((r) => setTimeout(r, 400));\n\n      const optionListAfterSearch = await page.$$eval(\n        '[aria-label=\"Option List Selector\"] li[role=\"option\"]',\n        (nodeList) => nodeList.map((node) => node.innerText)\n      );\n\n      expect(optionListAfterSearch).toHaveLength(1);\n\n      await expect(page).toClick('[aria-label=\"Option List Selector\"] li', {\n        text: 'author',\n      });\n      await expect(authorDropDownButton).toMatchTextContent('author');\n    });\n\n    it('should allow publish date to change', async () => {\n      await openPublishingPanel();\n\n      await expect(page).toClick(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Story publish time\"]',\n        { text: 'Immediately' }\n      );\n\n      // date picker is in a new popup so use keyboard to avoid more targets.\n      // We want to tab from hour, am/pm, month back, to currently selected \"immediate\" date\n      await page.keyboard.press('Tab');\n      await page.keyboard.press('Tab');\n      await page.keyboard.press('Tab');\n      await page.keyboard.press('Tab');\n      // From the currently selected date, arrow right to get a future date\n      await page.keyboard.press('ArrowRight');\n      await page.keyboard.press('ArrowRight');\n      // Select future date with keyboard\n      await page.keyboard.press('Enter');\n\n      // check that publish button says 'schedule'\n      await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button',\n        { name: 'Schedule' }\n      );\n    });\n\n    it('should update featured media (poster)', async () => {\n      await openPublishingPanel();\n\n      await expect(page).toClick(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Poster image\"]'\n      );\n\n      await expect(page).toClick('[role=\"menuitem\"]', {\n        text: 'Upload a file',\n      });\n\n      await page.waitForSelector('.media-modal', {\n        visible: true,\n      });\n\n      await expect(page).toClick('.media-modal #menu-item-upload', {\n        text: 'Upload files',\n        visible: true,\n      });\n\n      const fileName = await uploadFile('example-1.jpg', false);\n      uploadedFiles.push(fileName);\n\n      await expect(page).toClick('button', {\n        text: 'Select as poster image',\n        visible: true,\n      });\n\n      await expect(page).toClick('button', {\n        text: 'Crop image',\n        visible: true,\n      });\n\n      await page.keyboard.press('Escape');\n\n      await page.waitForSelector('.media-modal', {\n        visible: false,\n      });\n\n      await expect(page).toMatchElement(\n        '[data-testid=\"story_preview_featured_media\"]'\n      );\n    });\n  });\n\n  describe('Permalink Panel', () => {\n    async function openPermalinkPanel() {\n      //find permalink panel button\n      const permalinkPanelButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button',\n        { text: 'Permalink' }\n      );\n\n      const isPermalinkPanelExpanded = await permalinkPanelButton.evaluate(\n        (node) => node.getAttribute('aria-expanded') === 'true'\n      );\n      //open publish panel if not open\n      if (!isPermalinkPanelExpanded) {\n        await permalinkPanelButton.click();\n      }\n    }\n\n    it('should create a permalink based on story title', async () => {\n      openPermalinkPanel();\n      await expect(page).toMatchElement('textarea[placeholder=\"Add title\"]');\n\n      await page.type(\n        'textarea[placeholder=\"Add title\"]',\n        'Story Details Modal - admin'\n      );\n\n      await page.keyboard.press('Tab');\n\n      await expect(page).toMatchElement(\n        'input[aria-label=\"URL slug\"][value=\"story-details-modal-admin\"]'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/storyDetailsModal/contributorUser.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  takeSnapshot,\n  trashAllPosts,\n  withPlugin,\n  withUser,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst IMAGE_URL_LOCAL = `${process.env.WP_BASE_URL}/wp-content/e2e-assets/example-3.png`;\n\nconst openStoryDetailsModal = async () => {\n  await expect(page).toClick('button', { text: 'Submit for review' });\n  await expect(page).toMatchElement('div[aria-label=\"Story details\"]');\n};\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Story Details Modal - Contributor User', () => {\n  withPlugin('e2e-tests-hotlink');\n\n  beforeEach(async () => {\n    await createNewStory();\n    await openStoryDetailsModal();\n  });\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  withUser('contributor', 'password');\n\n  it('should allow title update', async () => {\n    await expect(page).toMatchElement('textarea[placeholder=\"Add title\"]');\n\n    await page.type(\n      'textarea[placeholder=\"Add title\"]',\n      'Story Details Modal - contributor'\n    );\n    await page.keyboard.press('Tab');\n\n    // Make sure title is displayed over preview\n    await expect(page).toMatchElement('div[aria-label=\"Story details\"] h3', {\n      text: 'Story Details Modal - contributor',\n    });\n\n    await takeSnapshot(page, 'Story Details Modal - contributor');\n  });\n\n  it('should close modal when story submitted for review', async () => {\n    await expect(page).toClick('div[aria-label=\"Story details\"] button', {\n      text: 'Submit for review',\n    });\n    await expect(page).toMatchElement('button', { text: 'Dismiss' });\n    await expect(page).not.toMatchElement('div[aria-label=\"Story details\"]');\n    await expect(page).not.toMatchTextContent('Story published.');\n  });\n\n  it('should not be able to update Story visibility', async () => {\n    await expect(page).toClick('button', {\n      text: 'Public',\n    });\n\n    await expect(page).not.toMatchElement(\n      '[aria-label=\"Option List Selector\"]'\n    );\n  });\n\n  describe('Publishing Panel', () => {\n    async function openPublishingPanel() {\n      //find publish panel button\n      const publishPanelButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button',\n        { text: 'Publishing' }\n      );\n\n      const isPublishPanelExpanded = await publishPanelButton.evaluate(\n        (node) => node.getAttribute('aria-expanded') === 'true'\n      );\n      //open publish panel if not open\n      if (!isPublishPanelExpanded) {\n        await publishPanelButton.click();\n      }\n    }\n\n    it('should not allow author to change', async () => {\n      await openPublishingPanel();\n\n      await expect(page).not.toMatchElement(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Author\"]'\n      );\n    });\n\n    it('should not allow publish date to change', async () => {\n      await openPublishingPanel();\n\n      await expect(page).not.toMatchElement(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Story publish time\"]'\n      );\n    });\n\n    it('should update featured media (poster)', async () => {\n      await openPublishingPanel();\n\n      await expect(page).toClick(\n        'div[aria-label=\"Story details\"] button[aria-label=\"Poster image\"]'\n      );\n\n      await expect(page).not.toMatchElement('[role=\"menuitem\"]', {\n        text: 'Upload a file',\n      });\n\n      await expect(page).toClick('[role=\"menuitem\"]', {\n        text: 'Link to a file',\n      });\n\n      await page.waitForSelector('[role=\"dialog\"]');\n      await expect(page).toMatchTextContent(\n        'Use external image as poster image'\n      );\n\n      await page.type('input[type=\"url\"]', IMAGE_URL_LOCAL);\n\n      await expect(page).toMatchElement(\n        '[role=\"dialog\"] button:not([disabled])',\n        {\n          text: 'Use image as poster image',\n        }\n      );\n\n      await Promise.all([\n        expect(page).toClick('[role=\"dialog\"] button', {\n          text: 'Use image as poster image',\n        }),\n        page.waitForResponse(\n          (response) =>\n            //eslint-disable-next-line jest/no-conditional-in-test -- False positive.\n            response.url().includes('web-stories/v1/hotlink/validate') &&\n            response.status() === 200\n        ),\n      ]);\n\n      // Dialog should disappear by now.\n      await expect(page).not.toMatchTextContent(\n        'Use external image as poster image'\n      );\n\n      await expect(page).toMatchElement(\n        '[data-testid=\"story_preview_featured_media\"]'\n      );\n    });\n  });\n\n  describe('Permalink Panel', () => {\n    async function openPermalinkPanel() {\n      //find permalink panel button\n      const permalinkPanelButton = await expect(page).toMatchElement(\n        'div[aria-label=\"Story details\"] button',\n        { text: 'Permalink' }\n      );\n\n      const isPermalinkPanelExpanded = await permalinkPanelButton.evaluate(\n        (node) => node.getAttribute('aria-expanded') === 'true'\n      );\n      //open publish panel if not open\n      if (!isPermalinkPanelExpanded) {\n        await permalinkPanelButton.click();\n      }\n    }\n\n    it('should create a permalink based on story title', async () => {\n      openPermalinkPanel();\n      await expect(page).toMatchElement('textarea[placeholder=\"Add title\"]');\n\n      await page.type(\n        'textarea[placeholder=\"Add title\"]',\n        'Story Details Modal - contributor'\n      );\n\n      await page.keyboard.press('Tab');\n\n      await expect(page).toMatchElement(\n        'input[aria-label=\"URL slug\"][value=\"story-details-modal-contributor\"]'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/taxonomy.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  withUser,\n  publishStory,\n  insertStoryTitle,\n  withPlugin,\n  createNewTerm,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\nasync function goToAndExpandTaxonomyPanel() {\n  await expect(page).toClick('li[role=\"tab\"]', { text: 'Document' });\n  await expect(page).toMatchTextContent('Taxonomies');\n\n  const taxonomyPanel = await page.$('button[aria-label=\"Taxonomies\"]');\n\n  const isCollapsed = await page.evaluate(\n    (button) => button.getAttribute('aria-expanded') === 'false',\n    taxonomyPanel\n  );\n\n  if (isCollapsed) {\n    await taxonomyPanel.click();\n  }\n\n  // Small trick to ensure we scroll to this panel.\n  await taxonomyPanel.focus();\n}\n\n/**\n * Add a new category.\n *\n * @param {string} name Category name.\n * @param {string} [parent] Parent category name.\n * @return {Promise<void>}\n */\nasync function addCategory(name, parent) {\n  await expect(page).toClick('button', { text: 'Add New Category' });\n\n  if (parent) {\n    await expect(page).toClick('button[aria-label=\"Parent Category\"]');\n    await page.waitForSelector('li[role=\"option\"]');\n\n    await expect(page).toMatchElement('li[role=\"option\"]', { text: parent });\n\n    await expect(page).toClick('li[role=\"option\"]', { text: parent });\n\n    await expect(page).toMatchElement('button[aria-label=\"Parent Category\"]', {\n      text: parent,\n    });\n  }\n\n  await expect(page).toFill('input[name=\"New Category Name\"]', name);\n\n  await expect(page).toClick('input[name=\"New Category Name\"]');\n\n  await page.focus('input[name=\"New Category Name\"]');\n  await page.keyboard.press('Enter');\n\n  await expect(page).toMatchElement('label', {\n    text: name,\n  });\n}\n\nasync function addTag(name) {\n  // get number of input children before we add the token\n  // so we have a metric to see when the new token renders\n  const numChildren = await page.$eval(\n    '#web_story_tag-input',\n    (el) => el.parentNode.children.length\n  );\n\n  // Add the new token\n  await page.focus('input#web_story_tag-input');\n  await page.type('input#web_story_tag-input', name);\n  await page.keyboard.press('Enter');\n\n  // wait for token to render\n  await page.waitForFunction(\n    (originalNumChildren) =>\n      document.getElementById('web_story_tag-input').parentNode.children\n        .length > originalNumChildren,\n    {},\n    numChildren\n  );\n\n  const tokenNames = await page.$$eval(\n    '[data-testid=\"flat-term-token\"]',\n    (nodes) => Array.from(nodes, (node) => node.innerText)\n  );\n\n  await expect(tokenNames).toContain(name);\n}\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Taxonomies', () => {\n  // Create some categories and tags before running all tests so that they are available there.\n  beforeAll(async () => {\n    await createNewTerm('web_story_category', 'music genres');\n    await createNewTerm('web_story_category', 'rock', 'music genres');\n\n    await createNewTerm('web_story_tag', 'adventure');\n    await createNewTerm('web_story_tag', 'sci-fi');\n    await createNewTerm('web_story_tag', 'comedy');\n  });\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  describe('Administrator', () => {\n    it('should be able to add new categories', async () => {\n      await createNewStory();\n      await insertStoryTitle('Taxonomies - Categories - Admin');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // Add some new categories.\n      await addCategory('jazz', 'music genres');\n      await addCategory('industrial', 'music genres');\n      await addCategory('electro-pop', 'music genres');\n      await addCategory('funk', 'music genres');\n\n      await publishStory();\n\n      // Refresh page to verify that the assignments persisted.\n      await page.reload({ waitUntil: 'networkidle2' });\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // See that category made in another story is available here.\n      await expect(page).toMatchElement('input[name=\"hierarchical_term_rock\"]');\n\n      // categories added are checked automatically.\n      await expect(page).toMatchElement(\n        'input[name=\"hierarchical_term_funk\"][checked]'\n      );\n      await expect(page).toMatchElement(\n        'input[name=\"hierarchical_term_jazz\"][checked]'\n      );\n    });\n\n    it('should be able to add new tags and existing tags', async () => {\n      await createNewStory();\n      await insertStoryTitle('Taxonomies - Tags - Admin');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // Add some new tags.\n      await addTag('noir');\n      await addTag('action');\n\n      // Find an existing tag and select it.\n      await page.focus('input#web_story_tag-input');\n      await page.type('input#web_story_tag-input', 'adven');\n      await page.waitForSelector('ul[data-testid=\"suggested_terms_list\"]');\n      await expect(page).toMatchElement(\n        'ul[data-testid=\"suggested_terms_list\"]'\n      );\n      await expect(page).toMatchElement('li[role=\"option\"]', {\n        text: 'adventure',\n      });\n      await expect(page).toClick('li[role=\"option\"]', { text: 'adventure' });\n      await page.focus('input#web_story_tag-input');\n\n      const tokens = await page.evaluate(() =>\n        Array.from(\n          document.querySelectorAll('[data-testid=\"flat-term-token\"]'),\n          (element) => element.innerText\n        )\n      );\n\n      await expect(tokens).toStrictEqual(\n        expect.arrayContaining(['noir', 'action', 'adventure'])\n      );\n\n      await publishStory();\n\n      // Refresh page to verify that the assignments persisted.\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // See that added tags persist.\n      const tokens2 = await page.evaluate(() =>\n        Array.from(\n          document.querySelectorAll('[data-testid=\"flat-term-token\"]'),\n          (element) => element.innerText\n        )\n      );\n\n      await expect(tokens2).toStrictEqual(\n        expect.arrayContaining(['noir', 'action', 'adventure'])\n      );\n    });\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n  describe.skip('Contributor', () => {\n    withUser('contributor', 'password');\n\n    it('should be able to manage categories but not add new ones', async () => {\n      await createNewStory();\n      await insertStoryTitle('Taxonomies - Categories - Contributor');\n\n      await goToAndExpandTaxonomyPanel();\n\n      await expect(page).not.toMatchElement('button', {\n        text: 'Add New Category',\n      });\n\n      await expect(page).toMatchElement('input[name=\"hierarchical_term_rock\"]');\n\n      await expect(page).toClick('label', { text: 'rock' });\n\n      await expect(page).toClick('button[aria-label=\"Save draft\"]');\n      await page.waitForSelector(\n        'button[aria-label=\"Preview\"]:not([disabled])'\n      );\n\n      // Refresh page to verify that the assignments persisted.\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).toMatchElement('a.ab-item', { text: 'View Story' });\n\n      await goToAndExpandTaxonomyPanel();\n\n      await expect(page).toMatchElement(\n        'input[name=\"hierarchical_term_rock\"][checked]'\n      );\n    });\n\n    it('should be able to add new tags and existing tags', async () => {\n      await createNewStory();\n      await insertStoryTitle('Taxonomies - Tags - Contributor');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // Add some new tags that won't stick on refresh\n      await addTag('rom-com');\n      await addTag('creature feature');\n\n      // Find an existing tag and select it.\n      await page.focus('input#web_story_tag-input');\n      await page.type('input#web_story_tag-input', 'adven');\n      await page.waitForSelector('ul[data-testid=\"suggested_terms_list\"]');\n      await expect(page).toMatchElement(\n        'ul[data-testid=\"suggested_terms_list\"]'\n      );\n      await expect(page).toMatchElement('li[role=\"option\"]', {\n        text: 'adventure',\n      });\n      await expect(page).toClick('li[role=\"option\"]', { text: 'adventure' });\n      await page.focus('input#web_story_tag-input');\n\n      const tokens = await page.evaluate(() =>\n        Array.from(\n          document.querySelectorAll('[data-testid=\"flat-term-token\"]'),\n          (element) => element.innerText\n        )\n      );\n\n      await expect(tokens).toStrictEqual(\n        expect.arrayContaining(['rom-com', 'creature feature', 'adventure'])\n      );\n\n      await expect(page).toClick('button[aria-label=\"Save draft\"]');\n      await page.waitForSelector(\n        'button[aria-label=\"Preview\"]:not([disabled])'\n      );\n\n      // Refresh page to verify that the assignments persisted.\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n      await goToAndExpandTaxonomyPanel();\n\n      // See that added tags persist.\n      const tokens2 = await page.evaluate(() =>\n        Array.from(\n          document.querySelectorAll('[data-testid=\"flat-term-token\"]'),\n          (element) => element.innerText\n        )\n      );\n\n      await expect(tokens2).toStrictEqual(\n        expect.arrayContaining(['rom-com', 'creature feature', 'adventure'])\n      );\n    });\n  });\n\n  describe('Custom Taxonomy', () => {\n    withPlugin('web-stories-test-plugin-taxonomies');\n\n    describe('Administrator', () => {\n      it('should see custom taxonomies', async () => {\n        await createNewStory();\n        await goToAndExpandTaxonomyPanel();\n\n        await expect(page).toMatchTextContent('Add New Color');\n        await expect(page).toMatchTextContent('Search Verticals');\n\n        await expect(page).toMatchElement('button', {\n          text: 'Add New Vertical',\n        });\n      });\n    });\n\n    // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n    describe.skip('Contributor', () => {\n      withUser('contributor', 'password');\n\n      it('should see custom taxonomies', async () => {\n        await createNewStory();\n        await goToAndExpandTaxonomyPanel();\n\n        await expect(page).toMatchTextContent('Add New Color');\n        await expect(page).toMatchTextContent('Search Verticals');\n\n        await expect(page).not.toMatchElement('button', {\n          text: 'Add New Vertical',\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/editor/templates.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  trashAllPosts,\n  withPlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Templates', () => {\n  describe('Disabled', () => {\n    withPlugin('e2e-tests-disable-default-templates');\n\n    afterAll(async () => {\n      await trashAllPosts('web-story');\n    });\n\n    it('should not render default templates', async () => {\n      await createNewStory();\n\n      // Use keyboard to open Page Templates panel.\n      await page.focus('ul[aria-label=\"Element Library Selection\"] li');\n      await page.keyboard.press('ArrowLeft');\n      await page.keyboard.press('Enter');\n\n      await expect(page).toMatchElement('button[aria-disabled=\"true\"]', {\n        text: 'Save current page as template',\n      });\n      await expect(page).not.toMatchElement(\n        'button[aria-label=\"Select templates type\"]'\n      );\n      await expect(page).not.toMatchTextContent('Default templates');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/integrations/amp.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  addTextElement,\n  createNewStory,\n  previewStory,\n  insertStoryTitle,\n  setAnalyticsCode,\n  withPlugin,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('AMP plugin integration', () => {\n  withPlugin('amp');\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  it('should be able to directly preview a story without amp-analytics being stripped', async () => {\n    await setAnalyticsCode('UA-10876-1');\n\n    await createNewStory();\n\n    await insertStoryTitle('Previewing without Publishing');\n\n    await addTextElement();\n\n    const editorPage = page;\n    const previewPage = await previewStory();\n\n    await expect(previewPage).toMatchElement('amp-analytics');\n\n    await editorPage.bringToFront();\n    await previewPage.close();\n    await setAnalyticsCode('');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/integrations/sitekit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  addTextElement,\n  createNewStory,\n  previewStory,\n  insertStoryTitle,\n  withPlugin,\n  visitSettings,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Site Kit plugin integration', () => {\n  describe('Google Analytics', () => {\n    withPlugin('e2e-tests-site-kit-analytics-mock');\n\n    describe('Editor', () => {\n      afterAll(async () => {\n        await trashAllPosts('web-story');\n      });\n\n      it('should print an analytics tag', async () => {\n        await createNewStory();\n\n        await insertStoryTitle('Previewing Analytics');\n\n        await addTextElement();\n\n        const editorPage = page;\n        const previewPage = await previewStory();\n        await expect(previewPage).toMatchTextContent('XXX-YYY');\n\n        await editorPage.bringToFront();\n        await previewPage.close();\n      });\n    });\n  });\n\n  describe('Google AdSense', () => {\n    withPlugin('e2e-tests-site-kit-adsense-mock');\n\n    describe('Dashboard', () => {\n      it('should see Google AdSense specific message', async () => {\n        await visitSettings();\n\n        await expect(page).toMatchTextContent(\n          'Site Kit by Google has already enabled Google AdSense for your Web Stories'\n        );\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/adminMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { visitAdminPage } from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Admin Menu', () => {\n  it('should contain links to Dashboard sub-pages', async () => {\n    await visitAdminPage('index.php');\n\n    await page.hover('#menu-posts-web-story');\n    await expect(page).toMatchElement('#menu-posts-web-story.opensub');\n\n    await expect(page).toMatchElement('#menu-posts-web-story a', {\n      text: 'Dashboard',\n      visible: true,\n    });\n    await expect(page).toMatchElement('#menu-posts-web-story a', {\n      text: 'Explore Templates',\n      visible: true,\n    });\n    await expect(page).toMatchElement('#menu-posts-web-story a', {\n      text: 'Settings',\n      visible: true,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/archive.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewPost,\n  insertBlock,\n  insertWidget,\n  publishPost,\n  visitAdminPage,\n  visitBlockWidgetScreen,\n  visitSettings,\n  withPlugin,\n  createURL,\n  trashAllPosts,\n  setPostContent,\n  deleteWidgets,\n  activatePlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\nconst pageTitle = 'Web Stories Archive';\nconst pageContent = 'Web Stories archive content';\n\n/**\n * Change archives page type.\n *\n * @param {string} option Archive type to select.\n * @return {Promise<void>}\n */\nconst changeStoriesArchivesType = async (option) => {\n  await expect(page).toClick('button[aria-label=\"Stories Archives\"]');\n  await expect(page).toClick('li[role=\"option\"]', { text: option });\n  await page.waitForResponse(\n    (response) =>\n      response.url().includes('web-stories/v1/settings') &&\n      response.status() === 200\n  );\n  await expect(page).toMatchElement('[role=\"alert\"]', {\n    text: 'Setting saved.',\n  });\n};\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Stories Archive', () => {\n  describe('Custom Page', () => {\n    beforeAll(async () => {\n      await createNewPost({\n        showWelcomeGuide: false,\n        postType: 'page',\n        title: pageTitle,\n      });\n      await setPostContent(pageContent);\n      await publishPost();\n    });\n\n    afterAll(async () => {\n      await visitSettings();\n      await changeStoriesArchivesType('Default');\n      await trashAllPosts();\n      await trashAllPosts('page');\n    });\n\n    it('should select a custom page', async () => {\n      await visitSettings();\n      await changeStoriesArchivesType('Create your own');\n      await expect(page).toMatchElement('input[placeholder=\"Select page\"]');\n      await page.type('input[placeholder=\"Select page\"]', pageTitle);\n      await expect(page).toMatchElement('li[role=\"option\"]', {\n        text: pageTitle,\n      });\n      await Promise.all([\n        expect(page).toClick('li[role=\"option\"]', {\n          text: pageTitle,\n        }),\n        page.waitForResponse(\n          (response) =>\n            //eslint-disable-next-line jest/no-conditional-in-test\n            response.url().includes('web-stories/v1/settings') &&\n            response.status() === 200\n        ),\n      ]);\n      await expect(page).toMatchElement('[role=\"alert\"]', {\n        text: 'Setting saved.',\n      });\n      const archiveLink = createURL('web-stories');\n      await page.goto(archiveLink, {\n        waitUntil: 'networkidle2',\n      });\n      await expect(page).toMatchTextContent(pageContent);\n    });\n  });\n\n  describe('Disabled', () => {\n    beforeAll(async () => {\n      await visitSettings();\n      await changeStoriesArchivesType('Disabled');\n    });\n    afterAll(async () => {\n      await visitSettings();\n      await changeStoriesArchivesType('Default');\n    });\n\n    describe('Block', () => {\n      it('should insert a new web stories block', async () => {\n        await createNewPost({\n          showWelcomeGuide: false,\n        });\n        await insertBlock();\n        await page.waitForSelector('.web-stories-block-configuration-panel');\n\n        await expect(page).toClick('button', { text: 'Latest Stories' });\n        await expect(page).toClick('button', { text: 'Box Carousel' });\n        await expect(page).not.toMatchElement('label', {\n          text: 'Display Archive Link',\n        });\n      });\n    });\n\n    describe('Widget Block', () => {\n      let removeErrorMessage;\n\n      beforeAll(() => {\n        // Caused by the NotEmpty component in wp-includes/js/dist/widgets.js.\n        removeErrorMessage = addAllowedErrorMessage(\n          \"Can't perform a React state update on an unmounted component\"\n        );\n      });\n\n      beforeEach(async () => {\n        await deleteWidgets();\n      });\n\n      afterEach(async () => {\n        await deleteWidgets();\n      });\n\n      afterAll(() => {\n        removeErrorMessage();\n      });\n\n      it('should not show archive link option', async () => {\n        await visitBlockWidgetScreen();\n\n        await expect(page).toClick('button[aria-label=\"Add block\"]');\n\n        await page.type('input[type=\"search\"]', 'Web Stories');\n        await expect(page).toClick('button span', { text: 'Web Stories' });\n\n        await page.waitForSelector('.web-stories-block-configuration-panel');\n        await expect(page).toClick('.web-stories-block-configuration-panel');\n\n        await expect(page).toClick('button', { text: 'Latest Stories' });\n        await expect(page).toClick('button', { text: 'Box Carousel' });\n        await expect(page).not.toMatchElement('label', {\n          text: 'Display Archive Link',\n        });\n      });\n    });\n\n    describe('Widget', () => {\n      withPlugin('classic-widgets');\n\n      beforeEach(async () => {\n        await deleteWidgets();\n        await activatePlugin('classic-widgets');\n      });\n\n      afterEach(async () => {\n        await deleteWidgets();\n      });\n\n      it('should not show archive link option', async () => {\n        await visitAdminPage('widgets.php');\n\n        await insertWidget('Web Stories');\n        await expect(page).toMatchElement(\n          '.widget-liquid-right .web-stories-field-wrapper'\n        );\n        await expect(page).not.toMatchElement('label', {\n          text: 'Display Archive Link',\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/blockWidget.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  deleteWidgets,\n  visitAdminPage,\n  activatePlugin,\n  deactivatePlugin,\n  visitBlockWidgetScreen,\n  insertWidget,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Web Stories Widget Block', () => {\n  let removeErrorMessage;\n\n  beforeAll(() => {\n    // Known issue in WP 6.0 RC1, see https://github.com/GoogleForCreators/web-stories-wp/pull/11435\n    removeErrorMessage = addAllowedErrorMessage(\n      \"Warning: Can't perform a React state update on an unmounted component.\"\n    );\n  });\n\n  beforeEach(async () => {\n    await deleteWidgets();\n  });\n\n  afterEach(async () => {\n    await deleteWidgets();\n  });\n\n  afterAll(() => {\n    removeErrorMessage();\n  });\n\n  it('should insert a new Web Stories block', async () => {\n    await visitBlockWidgetScreen();\n    await expect(page).toClick('button[aria-label=\"Add block\"]');\n    await page.type('input[placeholder=\"Search\"]', 'Web Stories');\n    await expect(page).toClick('button span', { text: 'Web Stories' });\n\n    await page.waitForSelector('.web-stories-block-configuration-panel');\n    await expect(page).toClick('.web-stories-block-configuration-panel');\n\n    await expect(page).toClick('button[aria-label=\"Embed a single story.\"]');\n\n    await expect(page).toMatchTextContent(\n      'Select an existing story from your site, or add one with a URL.'\n    );\n    await expect(page).toClick('button', { text: 'Insert from URL' });\n\n    await page.type(\n      'input[aria-label=\"Story URL\"]',\n      'https://wp.stories.google/stories/intro-to-web-stories-storytime'\n    );\n    await expect(page).toClick('button[aria-label=\"Embed\"]');\n\n    await page.waitForFunction(\n      () => !document.querySelector('.wp-block-web-stories-embed.is-loading')\n    );\n\n    await expect(page).not.toMatchTextContent(\n      'Sorry, this content could not be embedded.'\n    );\n\n    // Wait a little longer for embed REST API request to come back.\n    await page.waitForSelector('amp-story-player');\n    await expect(page).toMatchElement('amp-story-player');\n    await expect(page).toMatchTextContent('Embed Settings');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey test.\n  it.skip('should insert and transform a legacy Web Stories widget', async () => {\n    await activatePlugin('classic-widgets');\n\n    await visitAdminPage('widgets.php');\n\n    await insertWidget('Web Stories');\n    await expect(page).toMatchElement(\n      '.widget-liquid-right .web-stories-field-wrapper'\n    );\n\n    await page.evaluate(() => {\n      const input = document.querySelector(\n        '.widget-liquid-right .web-stories-field-wrapper input'\n      );\n      input.value = '';\n    });\n\n    await page.type(\n      '.widget-liquid-right .web-stories-field-wrapper input',\n      'Test widget'\n    );\n\n    await Promise.all([\n      expect(page).toClick(\n        '.widget-liquid-right .widget-control-save:not(:disabled)'\n      ),\n      page.waitForResponse(\n        (response) =>\n          // eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('/wp-admin/admin-ajax.php') &&\n          response.status() === 200\n      ),\n    ]);\n\n    await expect(page).toMatchElement(\n      '.widget-liquid-right .widget-control-save:disabled'\n    );\n\n    await deactivatePlugin('classic-widgets');\n\n    await visitBlockWidgetScreen();\n\n    // Wait for widget to render.\n    await page.waitForSelector('.wp-block-legacy-widget__edit-preview');\n\n    await expect(page).toClick('.wp-block-legacy-widget');\n    await expect(page).toMatchElement('.web-stories-field-wrapper', {\n      visible: true,\n    });\n\n    await page.evaluate(() => {\n      const input = document.querySelector('.web-stories-field-wrapper input');\n      input.value = '';\n    });\n\n    await Promise.all([\n      page.type('.web-stories-field-wrapper input', 'Test Block Widget'),\n\n      page.waitForResponse(\n        (response) =>\n          // eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('wp/v2/widget-types/web_stories_widget') &&\n          response.status() === 200\n      ),\n    ]);\n\n    await expect(page).toClick('.components-button.is-primary', {\n      text: 'Update',\n    });\n\n    await expect(page).toClick('.wp-block-legacy-widget');\n\n    // More reliable here than toClick(), page.click(), or transformBlockTo()\n    await page.evaluate(() =>\n      document.querySelector('button[aria-label=\"Legacy Widget\"]').click()\n    );\n\n    await expect(page).toClick('button[role=\"menuitem\"]', {\n      text: 'Web Stories',\n    });\n\n    // The core/legacy-widget block should have been replaced by core/heading + web-stories/embed.\n    const widgetBlocks = await page.evaluate(() =>\n      wp.data\n        .select('core/block-editor')\n        .getBlocks(wp.data.select('core/block-editor').getBlockOrder()[0])\n        .map(({ name }) => name)\n        .join(',')\n    );\n    await expect(widgetBlocks).toBe('core/heading,web-stories/embed');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/corsCheck.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  takeSnapshot,\n  trashAllPosts,\n  withPlugin,\n} from '@web-stories-wp/e2e-test-utils';\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('CORS check', () => {\n  withPlugin('e2e-tests-cors-error');\n\n  let removeCORSErrorMessage;\n  let removeResourceErrorMessage;\n\n  beforeAll(() => {\n    // Ignore CORS error, this is present in the test by design.\n    removeCORSErrorMessage = addAllowedErrorMessage(\n      'has been blocked by CORS policy'\n    );\n    // Ignore resource failing to load. This is only present because of the CORS error.\n    removeResourceErrorMessage = addAllowedErrorMessage(\n      'Failed to load resource'\n    );\n  });\n\n  afterAll(async () => {\n    removeCORSErrorMessage();\n    removeResourceErrorMessage();\n\n    await trashAllPosts('web-story');\n  });\n\n  it('should see media dialog', async () => {\n    await createNewStory();\n\n    await page.waitForSelector('.ReactModal__Content');\n\n    await expect(page).toMatchTextContent('Unable to load media');\n\n    await takeSnapshot(page, 'Stories editor with CORS dialog');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/getStartedStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  withUser,\n  visitAdminPage,\n  publishStory,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Get Started Story', () => {\n  describe('Admin User', () => {\n    it('should pre-fill post title and post content', async () => {\n      await visitAdminPage(\n        'post-new.php',\n        'post_type=web-story&web-stories-demo=1'\n      );\n\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).toMatchTextContent(\n        /Tips to make the most of the Web Stories Editor/i\n      );\n\n      await page.waitForSelector('[data-testid=\"mediaElement-image\"]');\n      await page.waitForSelector('[data-testid=\"frameElement\"]');\n\n      // Wait for skeleton thumbnails in the carousel to render before taking a screenshot.\n      await page.waitForFunction(\n        () =>\n          !document.querySelector(\n            'li[data-testid^=\"carousel-page-preview-skeleton\"]'\n          ),\n        { timeout: 5000 } // requestIdleCallback in the carousel kicks in after 5s the latest.\n      );\n      await takeSnapshot(page, 'Get Started Story');\n      await publishStory();\n\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).toMatchTextContent(\n        /Tips to make the most of the Web Stories Editor/i\n      );\n    });\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\n  describe.skip('Author User', () => {\n    withUser('author', 'password');\n\n    it('should pre-fill post title and post content', async () => {\n      await visitAdminPage(\n        'post-new.php',\n        'post_type=web-story&web-stories-demo=1'\n      );\n\n      // Wait for skeleton thumbnails in the carousel to render before taking a screenshot.\n      await page.waitForFunction(\n        () =>\n          !document.querySelector(\n            'li[data-testid^=\"carousel-page-preview-skeleton\"]'\n          ),\n        { timeout: 5000 } // requestIdleCallback in the carousel kicks in after 5s the latest.\n      );\n      await takeSnapshot(page, 'Get Started Story (Author)');\n\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).toMatchTextContent(\n        /Tips to make the most of the Web Stories Editor/i\n      );\n\n      await page.waitForSelector('[data-testid=\"mediaElement-image\"]');\n      await page.waitForSelector('[data-testid=\"frameElement\"]');\n      await publishStory();\n\n      await page.reload();\n      await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n      await expect(page).toMatchTextContent(\n        /Tips to make the most of the Web Stories Editor/i\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/pluginActivation.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  visitAdminPage,\n  withRTL,\n  activatePlugin,\n  deactivatePlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst percyCSS = `.plugin-version-author-uri, .amp-plugin-notice, .update-message, .subsubsub { display: none; }`;\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Fix flakey test.\ndescribe.skip('Plugin Activation', () => {\n  beforeEach(async () => {\n    await deactivatePlugin('web-stories');\n    await activatePlugin('web-stories');\n  });\n\n  it('should display a custom message after plugin activation', async () => {\n    await expect(page).toMatchTextContent(\"You're all set!\");\n    await expect(page).toMatchTextContent('Tell some stories.');\n\n    await takeSnapshot(page, 'Plugin Activation', { percyCSS });\n  });\n\n  describe('RTL', () => {\n    withRTL();\n\n    it('should display a custom message after plugin activation', async () => {\n      await deactivatePlugin('web-stories');\n      await activatePlugin('web-stories');\n      await expect(page).toMatchTextContent(\"You're all set!\");\n      await expect(page).toMatchTextContent('Tell some stories.');\n\n      await takeSnapshot(page, 'Plugin Activation on RTL', { percyCSS });\n    });\n  });\n\n  it('should dismiss plugin activation message', async () => {\n    await expect(page).toClick('button', { text: /Dismiss this notice/ });\n    await expect(page).not.toMatchTextContent(\"You're all set!\");\n    await expect(page).not.toMatchTextContent('Tell some stories.');\n  });\n\n  it('should not display message when visiting plugins screen a second time', async () => {\n    await visitAdminPage('plugins.php');\n    await expect(page).not.toMatchTextContent(\"You're all set!\");\n    await expect(page).not.toMatchTextContent('Tell some stories.');\n  });\n\n  it('should lead to the dashboard in success message', async () => {\n    await Promise.all([\n      expect(page).toClick('a', { text: 'Go to Stories Dashboard' }),\n      page.waitForNavigation(),\n    ]);\n\n    // Can be Explore Templates or My Stories depending on if user has 0\n    // stories, so just check that we get navigated to the dashboard\n    await expect(page).toMatchElement('#web-stories-dashboard');\n  });\n\n  it('should lead to the dashboard in step 2', async () => {\n    const dashboardStep = await expect(page).toMatchElement('p', {\n      text: /Head to the\\s?Dashboard/i,\n    });\n    await Promise.all([\n      expect(dashboardStep).toClick('a', { text: 'Dashboard' }),\n      page.waitForNavigation(),\n    ]);\n\n    // Can be Explore Templates or My Stories depending on if user has 0\n    // stories, so just check that we get navigated to the dashboard\n    await expect(page).toMatchElement('#web-stories-dashboard');\n  });\n\n  /* eslint-disable-next-line jest/no-disabled-tests --\n   * Step 3 is not visible on the screen size used in E2E tests.\n   * This might change in the future though.\n   **/\n  it.skip('should lead to the editor in step 3', async () => {\n    const editorStep = await expect(page).toMatchElement('p', {\n      text: /Jump into the\\s?Editor/i,\n    });\n\n    await Promise.all([\n      expect(editorStep).toClick('a', { text: 'Editor' }),\n      page.waitForNavigation(),\n    ]);\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/postLocking.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  visitDashboard,\n  createNewStory,\n  insertStoryTitle,\n  publishStory,\n  editStoryWithTitle,\n  activatePlugin,\n  deactivatePlugin,\n  takeSnapshot,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\nconst percyCSS = `.dashboard-grid-item-date { display: none; }`;\n\nconst storyTitle = 'Test post lock';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Post Locking', () => {\n  beforeAll(async () => {\n    await createNewStory();\n\n    await insertStoryTitle(storyTitle);\n\n    await publishStory();\n\n    // Not using the withPlugin() here because this plugin\n    // needs to be activated *after* creating this story.\n    await activatePlugin('e2e-tests-post-lock-mock');\n  });\n\n  afterAll(async () => {\n    await deactivatePlugin('e2e-tests-post-lock-mock');\n    await trashAllPosts('web-story');\n  });\n\n  it('should be able to open the dashboard with locked story', async () => {\n    await visitDashboard();\n\n    await expect(page).toMatchTextContent('Test post lock');\n    await page.hover('[data-test-id=\"lock-user-avatar\"]');\n    await expect(page).toMatchTextContent(\n      'test_locker is currently editing this story'\n    );\n    await takeSnapshot(page, 'Stories Dashboard with lock', { percyCSS });\n  });\n\n  it('should be able to open the editor with locked story', async () => {\n    await editStoryWithTitle(storyTitle);\n\n    await page.waitForSelector('.ReactModal__Content');\n\n    await expect(page).toMatchTextContent('This story is already being edited');\n\n    await takeSnapshot(page, 'Stories editor with lock dialog');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/quickEdit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createNewStory,\n  publishStory,\n  withUser,\n  visitAdminPage,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n// eslint-disable-next-line jest/no-disabled-tests -- TODO: Needs investigation.\ndescribe.skip('Quick Edit', () => {\n  withUser('author', 'password');\n\n  afterAll(async () => {\n    await trashAllPosts('web-story');\n  });\n\n  it('should save story without breaking markup', async () => {\n    await createNewStory();\n\n    await expect(page).toMatchElement('input[placeholder=\"Add title\"]');\n\n    const storyTitle = 'Test quick edit';\n\n    await page.type('input[placeholder=\"Add title\"]', storyTitle);\n\n    await publishStory();\n\n    await visitAdminPage('edit.php', 'post_type=web-story');\n\n    await expect(page).toMatchTextContent(storyTitle);\n\n    // Make row actions appear.\n    const elmId = await page.evaluate((storytitle) => {\n      return document\n        .querySelector(`a[aria-label=\"“${storytitle}” (Edit)\"]`)\n        .closest('tr').id;\n    }, storyTitle);\n\n    await page.hover(`#${elmId}`);\n\n    await expect(page).toClick('button', { text: 'Quick Edit' });\n\n    await page.type('input[name=\"post_title\"]', ' - updated.');\n    await expect(page).toClick('button', { text: 'Update' });\n\n    // Wait for update to finish and for the Quick Edit form to close.\n    await page.waitForResponse(\n      (response) =>\n        // eslint-disable-next-line jest/no-conditional-in-test -- False positive\n        response.url().includes('admin-ajax.php') && response.status() === 200\n    );\n    await page.waitForSelector('.spinner', {\n      visible: false,\n    });\n\n    // After updating, the row for this story in the table will be slowly fading in.\n    // The \"Quick Edit\" link will be focused after successful editing.\n    // See https://github.com/WordPress/wordpress-develop/blob/6d23d07e8014f551d836c3876515c3cc2c5c594b/src/js/_enqueues/admin/inline-edit-post.js#L457-L463\n    await page.waitForFunction(\n      () => document.activeElement.innerHTML === 'Quick&nbsp;Edit'\n    );\n\n    await expect(page).toMatchElement('button', { text: 'Quick Edit' });\n\n    await expect(page).toMatchTextContent('Test quick edit – updated.');\n\n    const [response] = await Promise.all([\n      page.waitForNavigation(),\n      page.click(`#${elmId} a[rel=\"bookmark\"]`),\n    ]);\n\n    // When the <amp-story> element exists in the response body we know that the output was not mangled.\n    await expect(response.text()).resolves.toContain('<amp-story');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/tinymce.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  takeSnapshot,\n  withPlugin,\n  visitAdminPage,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('TinyMCE button', () => {\n  withPlugin('classic-editor');\n\n  it('should allow inserting shortcode via modal', async () => {\n    await visitAdminPage('post-new.php');\n\n    // Ensure we're in the visual editor.\n    await expect(page).toClick('#content-tmce');\n    await expect(page).toMatchElement('.mce-tinymce.mce-container', {\n      visible: true,\n    });\n\n    await expect(page).toClick('.mce-web-stories button');\n\n    await page.waitForSelector('.components-modal__frame', {\n      visible: true,\n    });\n\n    await takeSnapshot(page, 'TinyMCE dialog');\n\n    await expect(page).toMatchTextContent('Archive Link Label');\n\n    await expect(page).toClick('button', { text: 'Insert' });\n\n    // Switch to HTML mode\n    await expect(page).toClick('#content-html');\n\n    // Get content of textarea.\n    const textEditorContent = await page.$eval(\n      '.wp-editor-area',\n      (element) => element.value\n    );\n\n    expect(textEditorContent).toMatch('[web_stories');\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/webStoriesBlock.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  publishPost,\n  withDisabledToolbarOnFrontend,\n  insertBlock,\n  withPlugin,\n  createNewPost,\n  setPostContent,\n  takeSnapshot,\n  trashAllPosts,\n} from '@web-stories-wp/e2e-test-utils';\n\n/**\n * Internal dependencies\n */\nimport { addAllowedErrorMessage } from '../../config/bootstrap';\n\nconst EMBED_BLOCK_CONTENT = `\n<!-- wp:web-stories/embed {\"url\":\"https://wp.stories.google/stories/intro-to-web-stories-storytime\",\"title\":\"Stories in AMP - Hello World\",\"poster\":\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"} -->\n<div class=\"wp-block-web-stories-embed alignnone\"><amp-story-player style=\"width:360px;height:600px\" data-testid=\"amp-story-player\"><a href=\"https://wp.stories.google/stories/intro-to-web-stories-storytime\" style=\"--story-player-poster:url('https://amp.dev/static/samples/img/story_dog2_portrait.jpg')\">Stories in AMP - Hello World</a></amp-story-player></div>\n<!-- /wp:web-stories/embed -->\n`;\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Web Stories Block', () => {\n  withPlugin('e2e-tests-embed');\n\n  let removeErrorMessage;\n\n  beforeAll(() => {\n    removeErrorMessage = addAllowedErrorMessage(\n      'Failed to load resource: the server responded with a status of 404'\n    );\n  });\n\n  afterAll(async () => {\n    removeErrorMessage();\n\n    await trashAllPosts();\n  });\n\n  it('should insert a new web stories block', async () => {\n    await createNewPost({\n      showWelcomeGuide: false,\n    });\n    await insertBlock();\n\n    await page.waitForSelector('.web-stories-block-configuration-panel');\n\n    await expect(page).toClick('button', { text: 'Single Story' });\n\n    await expect(page).toMatchTextContent(\n      'Select an existing story from your site, or add one with a URL.'\n    );\n    await expect(page).toClick('button', { text: 'Insert from URL' });\n\n    await page.type(\n      'input[aria-label=\"Story URL\"]',\n      'https://wp.stories.google/stories/intro-to-web-stories-storytime/'\n    );\n    await expect(page).toClick('button[aria-label=\"Embed\"]');\n\n    await expect(page).not.toMatchTextContent(\n      'Sorry, this content could not be embedded.'\n    );\n\n    // Wait a little longer for embed REST API request to come back.\n    await page.waitForSelector('amp-story-player');\n    await expect(page).toMatchElement('amp-story-player');\n    await expect(page).toMatchTextContent('Embed Settings');\n  });\n\n  it('should insert a new web stories block and select story', async () => {\n    await createNewPost({\n      showWelcomeGuide: false,\n    });\n    await insertBlock();\n\n    await page.waitForSelector('.web-stories-block-configuration-panel');\n\n    await expect(page).toClick('button', { text: 'Selected Stories' });\n\n    await expect(page).toClick('button', { text: 'Box Carousel' });\n\n    await expect(page).toClick('button', { text: 'Select Stories' });\n\n    await page.waitForSelector('.components-modal__screen-overlay');\n    await expect(page).toMatchElement('.components-modal__screen-overlay');\n\n    await page.waitForFunction(\n      () => !document.querySelector('.components-spinner')\n    );\n\n    await takeSnapshot(page, 'Story select modal');\n  });\n\n  describe('AMP validation', () => {\n    withDisabledToolbarOnFrontend();\n    withPlugin('amp');\n\n    let removeMessage1;\n    let removeMessage2;\n\n    beforeAll(() => {\n      // Some CORS errors when trying to load scripts from AMP CDN.\n      removeMessage1 = addAllowedErrorMessage(\n        'has been blocked by CORS policy'\n      );\n      removeMessage2 = addAllowedErrorMessage('Failed to load resource');\n    });\n\n    afterAll(() => {\n      removeMessage1();\n      removeMessage2();\n    });\n\n    // The AMP validator currently emits warning about the \"data-ampdevmode\"\n    // attribute, which is added by the AMP plugin.\n    // Perhaps because the toolbar is not properly disabled on the frontend?\n    // eslint-disable-next-line jest/no-disabled-tests -- TODO: Revisit later.\n    it.skip('should produce valid AMP when using the AMP plugin', async () => {\n      await createNewPost({\n        showWelcomeGuide: false,\n      });\n\n      await setPostContent(EMBED_BLOCK_CONTENT);\n\n      const postPermalink = await publishPost();\n\n      expect(postPermalink).not.toBeNull();\n      expect(postPermalink).toStrictEqual(expect.any(String));\n\n      //eslint-disable-next-line jest/no-conditional-in-test\n      const ampPostPermaLink = postPermalink.includes('?')\n        ? `${postPermalink}&amp`\n        : `${postPermalink}?amp`;\n\n      await expect(ampPostPermaLink).toBeValidAMP();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/specs/wordpress/widget.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  deleteWidgets,\n  visitAdminPage,\n  withPlugin,\n  insertWidget,\n  activatePlugin,\n} from '@web-stories-wp/e2e-test-utils';\n\njest.retryTimes(3, { logErrorsBeforeRetry: true });\n\ndescribe('Web Stories Widget', () => {\n  withPlugin('classic-widgets');\n\n  beforeEach(async () => {\n    await deleteWidgets();\n    await activatePlugin('classic-widgets');\n  });\n\n  describe('Widgets Screen', () => {\n    it('should be able to add widget', async () => {\n      await visitAdminPage('widgets.php');\n\n      await insertWidget('Web Stories');\n\n      await expect(page).toMatchElement(\n        '.widget-liquid-right .web-stories-field-wrapper'\n      );\n\n      await page.$eval(\n        '.widget-liquid-right .web-stories-field-wrapper input',\n        (input) => (input.value = '')\n      );\n\n      await page.type(\n        '.widget-liquid-right .web-stories-field-wrapper input',\n        'Test widget'\n      );\n\n      await expect(page).toClick(\n        '.widget-liquid-right .widget-control-save:not(:disabled)'\n      );\n\n      await page.waitForSelector('.spinner', {\n        visible: false,\n      });\n\n      await expect(page).toMatchElement(\n        '.widget-control-close-wrapper .widget-control-close',\n        {\n          text: 'Done',\n        }\n      );\n    });\n  });\n\n  describe('Customizer', () => {\n    // eslint-disable-next-line jest/no-disabled-tests -- Started failing on WP 6.7, needs investigation.\n    it.skip('should be able to add widget', async () => {\n      await visitAdminPage('customize.php');\n\n      await expect(page).toClick('li', { text: 'Widgets' });\n\n      await expect(page).toMatchElement('.control-panel-widgets.current-panel');\n      await expect(page).toMatchElement(\n        '#accordion-section-sidebar-widgets-sidebar-1 .accordion-section-title'\n      );\n\n      // The customizer has lots of transition animations.\n      // TODO: Remove and replace with waitForSelector or locator API.\n      await new Promise((r) => setTimeout(r, 500));\n\n      // expect(page).toClick(...) doesn't seem to work.\n      await page.evaluate(() => {\n        document\n          .querySelector(\n            '#accordion-section-sidebar-widgets-sidebar-1 .accordion-section-title'\n          )\n          .click();\n      });\n\n      // The customizer has lots of transition animations.\n      // TODO: Remove and replace with waitForSelector or locator API.\n      await new Promise((r) => setTimeout(r, 500));\n\n      await expect(page).toClick('button', { text: 'Add a Widget' });\n\n      await expect(page).toMatchTextContent('Web Stories');\n\n      await page.type('#widgets-search', 'web stories');\n\n      await expect(page).toClick(\"div[class*='web_stories_widget-']\");\n\n      // The customizer has lots of transition animations.\n      // TODO: Remove and replace with waitForSelector or locator API.\n      await new Promise((r) => setTimeout(r, 500));\n\n      await page.$eval(\n        '.web-stories-field-wrapper input',\n        (input) => (input.value = '')\n      );\n\n      await page.type('.web-stories-field-wrapper input', 'Test widget');\n\n      await page.keyboard.press('Enter');\n\n      await page.waitForResponse(\n        (response) =>\n          // eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('/wp-admin/admin-ajax.php') &&\n          response.status() === 200\n      );\n\n      await page.waitForSelector('.spinner', {\n        visible: false,\n      });\n\n      await expect(page).toClick('.widget-control-close', { text: 'Done' });\n\n      await expect(page).toClick('#save');\n      await expect(page).toMatchElement('#save[value=\"Published\"]');\n\n      await page.waitForResponse(\n        (response) =>\n          // eslint-disable-next-line jest/no-conditional-in-test\n          response.url().includes('/wp-admin/admin-ajax.php') &&\n          response.status() === 200\n      );\n\n      await page.waitForSelector('.spinner', {\n        visible: false,\n      });\n\n      await page.waitForSelector(\"iframe[title='Site Preview']\");\n      const frameHandle = await page.$(\"iframe[title='Site Preview']\");\n      const frame = await frameHandle.contentFrame();\n      expect(frame).not.toBeNull();\n      await expect(frame).toMatchElement('.web-stories-widget');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/e2e-tests/src/utils/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const monetizationDropdownSelector =\n  'button[aria-label=\"Monetization type\"]';\n\nexport const telemetryCheckboxSelector =\n  'input[data-testid=\"telemetry-settings-checkbox\"]';\n\nexport const videoOptimizationCheckboxSelector =\n  'input[data-testid=\"media-optimization-settings-checkbox\"]';\n\nexport const videoCacheCheckboxSelector =\n  'input[data-testid=\"video-cache-settings-checkbox\"]';\n"
  },
  {
    "path": "packages/e2e-tests/src/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/element-library/README.md",
    "content": "# Element Library\n\n---\n\nA library of all elements used in story-editor.\n"
  },
  {
    "path": "packages/element-library/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/element-library\",\n  \"description\": \"A library of all elements used in story-editor\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/element-library/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/element-library\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 16\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/dom\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/masks\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/moveable\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/rich-text\": \"*\",\n    \"@googleforcreators/stickers\": \"*\",\n    \"@googleforcreators/transform\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"classnames\": \"^2.5.1\",\n    \"polished\": \"^4.3.1\",\n    \"prop-types\": \"^15.7.2\",\n    \"react-transition-group\": \"^4.4.5\",\n    \"styled-components\": \"^5.3.11\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/constants.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nexport const hasEditMode = false;\nexport const hasEditModeIfLocked = false;\nexport const hasEditModeMoveable = false;\nexport const editModeGrayout = false;\n\nexport const hasDesignMenu = true;\n\nexport const hasDuplicateMenu = false;\n\nexport const isMedia = false;\n\nexport const canFlip = true;\n\nexport const isMaskable = false;\n\nexport const isAspectAlwaysLocked = true;\n\nexport const resizeRules = {\n  vertical: false,\n  horizontal: false,\n  diagonal: false,\n  minWidth: 120,\n  minHeight: 120,\n};\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  size: 'small',\n  sticker: 'headphone-cat',\n  style: 'none',\n  lockDimensions: true,\n};\n\nexport const panels = [PanelTypes.ElementAlignment, PanelTypes.AudioSticker];\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/display.tsx",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport type {\n  Element,\n  AudioStickerElement,\n  DisplayProps,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { elementFillContent } from '../shared';\nimport { AUDIO_STICKER_STYLES, AUDIO_STICKER_LABELS } from '../constants';\n\ninterface ElementProps {\n  stickerStyle: keyof typeof AUDIO_STICKER_STYLES;\n}\n\nconst Element = styled.img<ElementProps>`\n  ${elementFillContent}\n  ${({ stickerStyle }) => AUDIO_STICKER_STYLES[stickerStyle]}\n`;\n\nfunction AudioStickerDisplay({\n  element,\n  cdnUrl,\n}: DisplayProps<AudioStickerElement>) {\n  const {\n    width: elementWidth,\n    height: elementHeight,\n    sticker,\n    style,\n  } = element;\n\n  return (\n    <Element\n      src={`${cdnUrl}images/audio-sticker/${sticker}-pretap.png`}\n      crossOrigin=\"anonymous\"\n      stickerStyle={style}\n      height={elementHeight}\n      width={elementWidth}\n      alt={AUDIO_STICKER_LABELS[sticker].label}\n    />\n  );\n}\n\nexport default AudioStickerDisplay;\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\nconst IconContainer = styled.div`\n  height: 21px;\n  width: 21px;\n  overflow: hidden;\n`;\n\nfunction AudioStickerIcon() {\n  return (\n    <IconContainer>\n      <Icons.AudioSticker height={21} width={21} />\n    </IconContainer>\n  );\n}\n\nexport default AudioStickerIcon;\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/index.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Display } from './display';\nexport { default as Output } from './output';\nexport { default as LayerIcon } from './icon';\nexport { default as getLayerText } from './layer';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/layer.tsx",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nfunction getAudioStickerLayerText() {\n  return __('Audio Sticker', 'web-stories');\n}\n\nexport default getAudioStickerLayerText;\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/output.tsx",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  AudioStickerElement,\n  OutputProps,\n} from '@googleforcreators/elements';\n\nfunction AudioStickerOutput({ element }: OutputProps<AudioStickerElement>) {\n  return (\n    <div className=\"audio-sticker\">\n      <amp-story-audio-sticker\n        size={element.size}\n        sticker={element.sticker}\n        sticker-style={\n          element.style && element.style !== 'none' ? element.style : undefined\n        }\n        style={{\n          height: '100%',\n        }}\n      />\n    </div>\n  );\n}\n\nexport default AudioStickerOutput;\n"
  },
  {
    "path": "packages/element-library/src/audioSticker/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport AudioStickerOutput from '../output';\n\ndescribe('AudioSticker output', () => {\n  it('should produce valid AMP output', async () => {\n    const props = {\n      element: {\n        type: 'audioSticker',\n        id: '123',\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        size: 'small',\n        sticker: 'headphone-cat',\n        style: 'none',\n      },\n      box: { width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 },\n    };\n\n    await expect(<AudioStickerOutput {...props} />).toBeValidAMPStoryElement();\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const AUDIO_STICKER_STYLES = {\n  none: '',\n  outline: 'border: 4px solid white; border-radius: 20px',\n  dropshadow: 'filter: drop-shadow(2px 2px 10px white)',\n};\n\nexport const AUDIO_STICKER_LABELS = {\n  'headphone-cat': {\n    label: __('Headphone Cat', 'web-stories'),\n  },\n  'tape-player': {\n    label: __('Tape Player', 'web-stories'),\n  },\n  'loud-speaker': {\n    label: __('Loud Speaker', 'web-stories'),\n  },\n  'audio-cloud': {\n    label: __('Audio Cloud', 'web-stories'),\n  },\n};\n\nexport const DEFAULT_ATTRIBUTES_FOR_MEDIA = {\n  scale: 100,\n  focalX: 50,\n  focalY: 50,\n};\n"
  },
  {
    "path": "packages/element-library/src/elementTypes.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  type ElementDefinition,\n  type AudioStickerElement,\n  type TextElement,\n  type ImageElement,\n  type ShapeElement,\n  type VideoElement,\n  type GifElement,\n  type StickerElement,\n  type ProductElement,\n  ElementType,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport * as textElement from './text';\nimport * as imageElement from './image';\nimport * as shapeElement from './shape';\nimport * as videoElement from './video';\nimport * as gifElement from './gif';\nimport * as stickerElement from './sticker';\nimport * as productElement from './product';\nimport * as audioStickerElement from './audioSticker';\n\nconst elementTypes = [\n  {\n    type: ElementType.Text,\n    name: __('Text', 'web-stories'),\n    ...textElement,\n  } as ElementDefinition<TextElement>,\n  {\n    type: ElementType.Image,\n    name: __('Image', 'web-stories'),\n    ...imageElement,\n  } as ElementDefinition<ImageElement>,\n  {\n    type: ElementType.Shape,\n    name: __('Shape', 'web-stories'),\n    ...shapeElement,\n  } as ElementDefinition<ShapeElement>,\n  {\n    type: ElementType.Video,\n    name: __('Video', 'web-stories'),\n    ...videoElement,\n  } as ElementDefinition<VideoElement>,\n  {\n    type: ElementType.Gif,\n    name: __('GIF', 'web-stories'),\n    ...gifElement,\n  } as ElementDefinition<GifElement>,\n  {\n    type: ElementType.Sticker,\n    name: __('Sticker', 'web-stories') as string,\n    ...stickerElement,\n  } as ElementDefinition<StickerElement>,\n  {\n    type: ElementType.Product,\n    name: __('Product', 'web-stories'),\n    ...productElement,\n  } as ElementDefinition<ProductElement>,\n  {\n    type: ElementType.AudioSticker,\n    name: __('Audio Sticker', 'web-stories'),\n    ...audioStickerElement,\n  } as ElementDefinition<AudioStickerElement>,\n];\n\nexport default elementTypes;\n"
  },
  {
    "path": "packages/element-library/src/gif/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\nimport { MEDIA_DEFAULT_ATTRIBUTES, MEDIA_PANELS } from '../media';\n\nexport {\n  canFlip,\n  isMaskable,\n  isAspectAlwaysLocked,\n  isMedia,\n  hasEditMode,\n  hasEditModeIfLocked,\n  hasEditModeMoveable,\n  hasDuplicateMenu,\n  hasDesignMenu,\n  editModeGrayout,\n} from '../media/constants';\n\nexport { resizeRules } from '../media/constants';\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  ...MEDIA_DEFAULT_ATTRIBUTES,\n  resource: {\n    type: ResourceType.Gif,\n    id: 0,\n    width: 0,\n    height: 0,\n    alt: '',\n    src: '',\n    mimeType: 'image/gif',\n    output: {\n      mimeType: 'video/mp4',\n      src: '',\n    },\n  },\n};\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  ...MEDIA_PANELS,\n  PanelTypes.Link,\n  PanelTypes.ImageAccessibility,\n];\n"
  },
  {
    "path": "packages/element-library/src/gif/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport { getMediaSizePositionProps } from '@googleforcreators/media';\nimport type { GifElement, DisplayProps } from '@googleforcreators/elements';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport MediaDisplay from '../media/display';\nimport { getBackgroundStyle, Video, VideoImage } from '../media/util';\n\nfunction GifDisplay({\n  previewMode,\n  box: { width, height },\n  element,\n  renderResourcePlaceholder,\n}: DisplayProps<GifElement>) {\n  const { id, poster, resource, isBackground, scale, focalX, focalY } = element;\n  const ref = useRef<HTMLImageElement | HTMLVideoElement>(null);\n  let style = {};\n  if (isBackground) {\n    const styleProps = getBackgroundStyle();\n    style = {\n      ...style,\n      ...styleProps,\n    };\n  }\n\n  const videoProps = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    focalX,\n    focalY\n  );\n\n  return (\n    <MediaDisplay<GifElement>\n      element={element}\n      mediaRef={ref}\n      showPlaceholder\n      previewMode={previewMode}\n      renderResourcePlaceholder={renderResourcePlaceholder}\n    >\n      {previewMode ? (\n        (poster || resource.poster) && (\n          <VideoImage\n            src={poster || resource.poster}\n            alt={element.alt || resource.alt}\n            style={style}\n            {...videoProps}\n            ref={ref as RefObject<HTMLImageElement>}\n          />\n        )\n      ) : (\n        <Video\n          id={`video-${id}`}\n          poster={poster || resource.poster}\n          style={style}\n          {...videoProps}\n          loop\n          autoPlay\n          muted\n          preload=\"all\"\n          ref={ref as RefObject<HTMLVideoElement>}\n          data-testid=\"videoElement\"\n          data-leaf-element=\"true\"\n        >\n          {resource.output.src && (\n            <source src={resource.output.src} type={resource.output.mimeType} />\n          )}\n        </Video>\n      )}\n    </MediaDisplay>\n  );\n}\n\nexport default GifDisplay;\n"
  },
  {
    "path": "packages/element-library/src/gif/edit.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { GifElement, EditProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport MediaEdit from '../media/edit';\n\nfunction GifEdit({ element, box, ...rest }: EditProps<GifElement>) {\n  return <MediaEdit<GifElement> element={element} box={box} {...rest} />;\n}\n\nexport default GifEdit;\n"
  },
  {
    "path": "packages/element-library/src/gif/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport MediaFrame from '../media/frame';\n\nfunction GifFrame() {\n  return <MediaFrame />;\n}\nexport default GifFrame;\n"
  },
  {
    "path": "packages/element-library/src/gif/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { GifElement, LayerIconProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport VisibleImage from '../shared/visibleImage';\n\nfunction GifLayerIcon({\n  element: {\n    resource: { poster, alt },\n  },\n}: LayerIconProps<GifElement>) {\n  return <VisibleImage src={poster} alt={alt} height={21} width={21} />;\n}\nexport default GifLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/gif/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Edit } from './edit';\nexport { default as Frame } from './frame';\nexport { default as getLayerText } from './layer';\nexport { default as Output } from './output';\nexport { default as LayerIcon } from './icon';\nexport { default as TextContent } from '../media/textContent';\nexport { default as Display } from './display';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/gif/layer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { GifElement } from '@googleforcreators/elements';\n\nfunction getGifLayerText(element: GifElement) {\n  const { alt } = element?.resource || {};\n\n  return alt || __('GIF', 'web-stories');\n}\n\nexport default getGifLayerText;\n"
  },
  {
    "path": "packages/element-library/src/gif/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { isBlobURL } from '@googleforcreators/media';\nimport type { GifElement, OutputProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport MediaOutput from '../media/output';\n\nfunction GifOutput({ element, box, flags }: OutputProps<GifElement>) {\n  const { resource } = element;\n\n  const src =\n    flags?.allowBlobs || !isBlobURL(resource.output.src)\n      ? resource.output.src\n      : '';\n  const poster =\n    flags?.allowBlobs || !isBlobURL(resource.poster) ? resource.poster : '';\n\n  return (\n    <MediaOutput element={element} box={box} data-leaf-element=\"true\">\n      <amp-video\n        id={`el-${element.id}-media`}\n        // @ts-expect-error Needs to be lowercase.\n        autoplay=\"autoplay\"\n        loop=\"loop\"\n        noaudio=\"noaudio\"\n        poster={poster || ''}\n        layout=\"fill\"\n        alt={element.alt ?? resource.alt}\n      >\n        <source type={resource.output.mimeType} src={src} />\n      </amp-video>\n    </MediaOutput>\n  );\n}\n\nexport default GifOutput;\n"
  },
  {
    "path": "packages/element-library/src/gif/test/__snapshots__/output.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Gif Output should include poster image if available 1`] = `\"<div style=\"position:absolute;width:100%;height:100%;left:0%;top:0%\" data-leaf-element=\"true\"><amp-video id=\"el-048426c8-69ae-4e04-80f1-8f3fd4434261-media\" autoplay=\"autoplay\" loop=\"loop\" noaudio=\"noaudio\" poster=\"https://c.tenor.com/4F2m7BWP6KYAAAAC/flying-kiss-muah-poster.png\" layout=\"fill\" alt=\"\"><source type=\"video/mp4\" src=\"https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4\"/></amp-video></div>\"`;\n\nexports[`Gif Output should produce an AMP video with autoplay, no controls, no audio, and loop 1`] = `\"<div style=\"position:absolute;width:100%;height:100%;left:0%;top:0%\" data-leaf-element=\"true\"><amp-video id=\"el-048426c8-69ae-4e04-80f1-8f3fd4434261-media\" autoplay=\"autoplay\" loop=\"loop\" noaudio=\"noaudio\" poster=\"\" layout=\"fill\" alt=\"\"><source type=\"video/mp4\" src=\"https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4\"/></amp-video></div>\"`;\n"
  },
  {
    "path": "packages/element-library/src/gif/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport GifOutput from '../output';\n\ndescribe('Gif Output', () => {\n  const baseProps = {\n    element: {\n      id: '048426c8-69ae-4e04-80f1-8f3fd4434261',\n      type: 'gif',\n      opacity: 100,\n      x: 65,\n      y: 196,\n      width: 281,\n      height: 223,\n      scale: 100,\n      rotationAngle: 0,\n      resource: {\n        type: 'gif',\n        mimeType: 'image/gif',\n        creationDate: '2016-02-04T18:16:22Z',\n        src: 'https://c.tenor.com/4F2m7BWP6KYAAAAC/flying-kiss-muah.gif',\n        width: 281,\n        height: 223,\n        alt: '',\n        attribution: {\n          author: [],\n          registerUsageUrl:\n            'https://media3p.googleapis.com/v1/media:registerUsage?token=AX7RMSdePGQBB3c/QAOBJ20QC%2BZNp2A549gSosisUYOjIC71nkvySPH5yj%2BqDBOVBmmFZ89azzUAN9x2GjkNbq3OXauUMho%3D',\n        },\n        output: {\n          mimeType: 'video/mp4',\n          src: 'https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4',\n        },\n      },\n    },\n    box: {\n      x: 15.7767,\n      y: 31.71521,\n      width: 68.20388,\n      height: 36.08414,\n      rotationAngle: 0,\n    },\n  };\n\n  it('should produce an AMP video with autoplay, no controls, no audio, and loop', async () => {\n    const output = <GifOutput {...baseProps} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(\n        'src=\"https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4\"'\n      )\n    );\n    await expect(outputStr).toMatchSnapshot();\n  });\n\n  it('should include poster image if available', async () => {\n    const newProps = { ...baseProps };\n    newProps.element.resource.poster =\n      'https://c.tenor.com/4F2m7BWP6KYAAAAC/flying-kiss-muah-poster.png';\n    const output = <GifOutput {...newProps} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(\n        'src=\"https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4\"'\n      )\n    );\n    await expect(outputStr).toMatchSnapshot();\n  });\n\n  it('should remove blob URLs', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        resource: {\n          ...baseProps.element.resource,\n          output: {\n            ...baseProps.element.resource.output,\n            src: 'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n          },\n        },\n      },\n    };\n    const output = <GifOutput {...props} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).not.toStrictEqual(expect.stringMatching('blob:'));\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output', async () => {\n      await expect(<GifOutput {...baseProps} />).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output with poster', async () => {\n      const newProps = { ...baseProps };\n      newProps.element.resource.poster =\n        'https://c.tenor.com/4F2m7BWP6KYAAAAC/flying-kiss-muah-poster.png';\n      await expect(<GifOutput {...newProps} />).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/image/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\nimport { MEDIA_DEFAULT_ATTRIBUTES, MEDIA_PANELS } from '../media';\n\nexport {\n  canFlip,\n  isMaskable,\n  isAspectAlwaysLocked,\n  isMedia,\n  hasEditMode,\n  hasEditModeIfLocked,\n  hasEditModeMoveable,\n  hasDuplicateMenu,\n  hasDesignMenu,\n  editModeGrayout,\n  resizeRules,\n} from '../media/constants';\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  ...MEDIA_DEFAULT_ATTRIBUTES,\n  lockAspectRatio: false,\n  resource: {\n    type: ResourceType.Image,\n    id: 0,\n    width: 0,\n    height: 0,\n    alt: '',\n    src: '',\n    mimeType: '',\n  },\n};\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  ...MEDIA_PANELS,\n  PanelTypes.ImageAccessibility,\n];\n"
  },
  {
    "path": "packages/element-library/src/image/edit.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ImageElement, EditProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport MediaEdit from '../media/edit';\n\nfunction ImageEdit({ element, box, ...rest }: EditProps<ImageElement>) {\n  return <MediaEdit<ImageElement> element={element} box={box} {...rest} />;\n}\n\nexport default ImageEdit;\n"
  },
  {
    "path": "packages/element-library/src/image/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport MediaFrame from '../media/frame';\n\nfunction ImageFrame() {\n  return <MediaFrame />;\n}\n\nexport default ImageFrame;\n"
  },
  {
    "path": "packages/element-library/src/image/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getSmallestUrlForWidth } from '@googleforcreators/media';\nimport type { ImageElement, LayerIconProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport VisibleImage from '../shared/visibleImage';\n\nfunction ImageLayerIcon({\n  element: { resource },\n  getProxiedUrl,\n}: LayerIconProps<ImageElement>) {\n  const url = getSmallestUrlForWidth(0, resource);\n  const src = getProxiedUrl(resource, url) || undefined;\n  return <VisibleImage src={src} height={21} width={21} />;\n}\n\nexport default ImageLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/image/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Edit } from './edit';\nexport { default as Frame } from './frame';\nexport { default as Output } from './output';\nexport { default as LayerIcon } from './icon';\nexport { default as getLayerText } from './layer';\nexport { default as Display } from '../media/imageDisplay';\nexport { default as TextContent } from '../media/textContent';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/image/layer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { ImageElement } from '@googleforcreators/elements';\n\nfunction getImageLayerText(element: ImageElement) {\n  const { alt } = element?.resource || {};\n\n  return alt || __('Image', 'web-stories');\n}\n\nexport default getImageLayerText;\n"
  },
  {
    "path": "packages/element-library/src/image/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { calculateSrcSet, isBlobURL } from '@googleforcreators/media';\nimport {\n  PAGE_WIDTH,\n  FULLBLEED_HEIGHT,\n  FULLBLEED_RATIO,\n} from '@googleforcreators/units';\nimport type { ImageElement, OutputProps } from '@googleforcreators/elements';\nimport type { HTMLProps } from 'react';\n\n/**\n * Internal dependencies\n */\nimport MediaOutput from '../media/output';\n\n/**\n * Returns AMP HTML for saving into post content for displaying in the FE.\n *\n * @param props Props.\n * @return Rendered component.\n */\nfunction ImageOutput({ element, box, flags }: OutputProps<ImageElement>) {\n  const { alt, isBackground, resource, width, height, scale } = element;\n\n  const props: Pick<\n    HTMLProps<HTMLImageElement>,\n    'src' | 'alt' | 'srcSet' | 'sizes'\n  > = {\n    src: flags?.allowBlobs || !isBlobURL(resource.src) ? resource.src : '',\n    alt: alt !== undefined ? alt : resource.alt,\n  };\n\n  const srcSet = calculateSrcSet(resource);\n  if (srcSet) {\n    props.srcSet = srcSet;\n\n    // `width` of background elements reflects their original size.\n    // We need to account for both aspect-scale-to-fit background and element scale level.\n    let displayWidth = width;\n    if (isBackground) {\n      const aspectRatio = width / height;\n      const widthAsBackground =\n        aspectRatio <= FULLBLEED_RATIO\n          ? PAGE_WIDTH\n          : aspectRatio * FULLBLEED_HEIGHT;\n      displayWidth = widthAsBackground * ((scale || 100) / 100);\n    }\n\n    // If `srcset` exists but `sizes` doesn't, amp-img will generate a sizes attribute\n    // with best-guess values that can result in poor image selection.\n    const imageWidthPercent = displayWidth / PAGE_WIDTH;\n    const mobileWidth = Math.round(imageWidthPercent * 100) + 'vw';\n    // Width of a story page in desktop mode is 45vh.\n    const desktopWidth = Math.round(imageWidthPercent * 45) + 'vh';\n    // 1024px is the minimum width for STAMP desktop mode.\n    props.sizes = `(min-width: 1024px) ${desktopWidth}, ${mobileWidth}`;\n  }\n\n  // Prevent inline `width` style from being inserted by AMP (due to presence of `sizes` attribute),\n  // which avoids an undesirable interaction between AMP and the Optimizer's SSR transforms.\n  // See https://github.com/googleforcreators/web-stories-wp/pull/8099#issuecomment-870987667.\n  return (\n    <MediaOutput box={box} element={element} data-leaf-element=\"true\">\n      <amp-img layout=\"fill\" {...props} disable-inline-width />\n    </MediaOutput>\n  );\n}\n\nexport default ImageOutput;\n"
  },
  {
    "path": "packages/element-library/src/image/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport ImageOutput from '../output';\n\ndescribe('Image output', () => {\n  jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n  const baseProps = {\n    element: {\n      id: '123',\n      type: 'image',\n      mimeType: 'image/png',\n      scale: 200,\n      origRatio: 16 / 9,\n      x: 50,\n      y: 100,\n      height: 231.75,\n      width: 206,\n      rotationAngle: 0,\n      resource: {\n        id: 123,\n        type: 'image',\n        mimeType: 'image/png',\n        src: 'https://example.com/image.png',\n        alt: 'alt text',\n        height: 1080,\n        width: 1920,\n        sizes: {\n          mid: {\n            sourceUrl: 'https://example.com/image-mid.png',\n            width: 960,\n            height: 540,\n            mimeType: 'image/png',\n          },\n          full: {\n            sourceUrl: 'https://example.com/image.png',\n            width: 1920,\n            height: 1080,\n            mimeType: 'image/png',\n          },\n        },\n      },\n    },\n    box: { width: 1920, height: 1080, x: 50, y: 100, rotationAngle: 0 },\n  };\n\n  it('should produce valid AMP output', async () => {\n    await expect(<ImageOutput {...baseProps} />).toBeValidAMPStoryElement();\n  });\n\n  it('should produce an AMP img with a srcset/sizes', async () => {\n    const output = <ImageOutput {...baseProps} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(output).toBeValidAMPStoryElement();\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(\n        'srcSet=\"https://example.com/image.png 1920w,' +\n          'https://example.com/image-mid.png 960w\"'\n      )\n    );\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('src=\"https://example.com/image.png\"')\n    );\n    // `sizes` should match: (min-width: <desktop_screen_width>) <desktop_image_width>, <mobile_image_width>\n    // The image size is 206px wide, which is half page width.\n    // 45vh is the page width of stories in desktop mode (divided by 2, rounded up is 23).\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(/sizes=\"\\(min-width: 1024px\\) 23vh, 50vw\"/)\n    );\n    // The \"disable-inline-width\" attribute should accompany the \"sizes\" attribute.\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('disable-inline-width=\"true\"')\n    );\n  });\n\n  it('should generate correct `sizes` for a narrower background image', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        width: 206, // 50%\n        height: 732, // 100%\n        isBackground: true,\n        scale: 300,\n      },\n    };\n    const output = <ImageOutput {...props} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(output).toBeValidAMPStoryElement();\n    // `sizes` should match: (min-width: <desktop_screen_width>) <desktop_image_width>, <mobile_image_width>\n    // The background image should scale up its width to fit the page.\n    // 45vh is the page width of stories in desktop mode.\n    // The image zoom is 300 (3x) so triple both measurements.\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(/sizes=\"\\(min-width: 1024px\\) 135vh, 300vw\"/)\n    );\n    // The \"disable-inline-width\" attribute should accompany the \"sizes\" attribute.\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('disable-inline-width=\"true\"')\n    );\n  });\n\n  it('should generate correct `sizes` for a wider background image', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        width: 412, // 100%\n        height: 183, // 25%\n        isBackground: true,\n        scale: 100,\n      },\n    };\n    const output = <ImageOutput {...props} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(output).toBeValidAMPStoryElement();\n    // `sizes` should match: (min-width: <desktop_screen_width>) <desktop_image_width>, <mobile_image_width>\n    // The background image should scale up its width 4x since its height is 25%.\n    // 45vh is the page width of stories in desktop mode.\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching(/sizes=\"\\(min-width: 1024px\\) 180vh, 400vw\"/)\n    );\n    // The \"disable-inline-width\" attribute should accompany the \"sizes\" attribute.\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('disable-inline-width=\"true\"')\n    );\n  });\n\n  it('should produce an AMP img with no srcset/sizes if the resource has no `sizes`', async () => {\n    const basePropsNoSrcset = { ...baseProps };\n    basePropsNoSrcset.element.resource.sizes = {};\n    const output = <ImageOutput {...basePropsNoSrcset} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(output).toBeValidAMPStoryElement();\n    await expect(outputStr).toStrictEqual(expect.not.stringMatching('srcSet='));\n    await expect(outputStr).toStrictEqual(expect.not.stringMatching('sizes='));\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('src=\"https://example.com/image.png\"')\n    );\n  });\n\n  it('an undefined alt tag in the element should fall back to the resource', async () => {\n    const props = {\n      ...baseProps,\n      element: { ...baseProps.element, alt: undefined },\n    };\n    const output = <ImageOutput {...props} />;\n    await expect(output).toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(expect.stringMatching('alt text'));\n  });\n\n  it('an empty string alt tag in the element should not fall back to the resource', async () => {\n    const props = { ...baseProps, element: { ...baseProps.element, alt: '' } };\n    const output = <ImageOutput {...props} />;\n    await expect(output).toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).not.toStrictEqual(\n      expect.stringMatching('alt text')\n    );\n  });\n\n  it('should remove blob URLs', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        resource: {\n          ...baseProps.element.resource,\n          src: 'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n        },\n      },\n    };\n    const output = <ImageOutput {...props} />;\n    await expect(output).not.toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).not.toStrictEqual(expect.stringMatching('blob:'));\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './shared';\nexport * from './media';\nexport * from './utils/textMeasurements';\nexport * from './text/util';\nexport * from './constants';\nexport { default as TextOutput } from './text/output';\nexport { default as elementTypes } from './elementTypes';\n"
  },
  {
    "path": "packages/element-library/src/media/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_ATTRIBUTES_FOR_MEDIA } from '../constants';\n\nexport const MEDIA_DEFAULT_ATTRIBUTES = {\n  ...DEFAULT_ATTRIBUTES_FOR_MEDIA,\n  resource: {\n    alt: '',\n  },\n};\n\nexport const MEDIA_MASK_OPACITY = 0.4;\n\nexport const hasEditMode = true;\nexport const hasEditModeIfLocked = true;\nexport const hasEditModeMoveable = false;\nexport const editModeGrayout = true;\n\nexport const hasDuplicateMenu = true;\n\nexport const hasDesignMenu = true;\n\nexport const isMedia = true;\n\nexport const canFlip = true;\n\nexport const isMaskable = true;\n\nexport const isAspectAlwaysLocked = false;\n\nexport const resizeRules = {\n  vertical: true,\n  horizontal: true,\n  diagonal: true,\n  minWidth: 20,\n  minHeight: 20,\n};\n\nexport const MEDIA_PANELS = [\n  PanelTypes.Filter,\n  PanelTypes.SizePosition,\n  PanelTypes.Border,\n  PanelTypes.Animation,\n  PanelTypes.Link,\n];\n"
  },
  {
    "path": "packages/element-library/src/media/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useRef } from '@googleforcreators/react';\nimport { useUnits } from '@googleforcreators/units';\nimport { getMediaSizePositionProps } from '@googleforcreators/media';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport {\n  getResponsiveBorder,\n  shouldDisplayBorder,\n} from '@googleforcreators/masks';\nimport type {\n  SequenceMediaElement,\n  OverlayableElement,\n  Element as ElementType,\n  MediaElement,\n  DisplayProps,\n} from '@googleforcreators/elements';\nimport type { ReactNode, RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  elementFillContent,\n  elementWithBorder,\n  elementWithBackgroundColor,\n  useColorTransformHandler,\n} from '../shared';\nimport { getMediaWithScaleCss } from './util';\n\nconst Element = styled.div.attrs({ className: 'story-media-display-element' })<\n  {\n    showPlaceholder: boolean;\n  } & Pick<ElementType, 'border' | 'borderRadius' | 'width' | 'height' | 'mask'>\n>`\n  ${elementFillContent}\n  ${({ showPlaceholder }) => showPlaceholder && `background-color: #C4C4C4;`}\n  color: transparent;\n  overflow: hidden;\n  ${elementWithBorder}\n`;\n\nconst Overlay = styled.div`\n  ${elementFillContent}\n  ${elementWithBackgroundColor}\n`;\n\ninterface MediaDisplayProps<T extends MediaElement> {\n  element: T & OverlayableElement;\n  showPlaceholder?: boolean;\n  previewMode?: boolean;\n  mediaRef: RefObject<\n    T extends SequenceMediaElement\n      ? HTMLVideoElement | HTMLImageElement\n      : HTMLImageElement\n  >;\n  renderResourcePlaceholder?: DisplayProps<T>['renderResourcePlaceholder'];\n  children: ReactNode;\n}\nfunction MediaDisplay<T extends MediaElement>({\n  element,\n  mediaRef,\n  children,\n  previewMode,\n  showPlaceholder = false,\n  renderResourcePlaceholder,\n}: MediaDisplayProps<T>) {\n  const {\n    id,\n    resource,\n    scale,\n    focalX,\n    focalY,\n    border,\n    borderRadius,\n    width,\n    height,\n    overlay,\n    mask,\n  } = element;\n\n  const { dataToEditorX } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n  }));\n\n  const ref = useRef<HTMLDivElement>(null);\n  useColorTransformHandler({\n    id,\n    targetRef: ref,\n    expectedStyle: 'border-color',\n  });\n  useTransformHandler(id, (transform) => {\n    const target = mediaRef.current;\n    if (target) {\n      if (transform === null) {\n        target.style.cssText = '';\n      } else {\n        const { resize } = transform;\n        if (resize && resize[0] !== 0 && resize[1] !== 0) {\n          // @todo this needs to resize the outside border element separately now.\n          const newImgProps = getMediaSizePositionProps(\n            resource,\n            resize[0],\n            resize[1],\n            scale,\n            focalX,\n            focalY\n          );\n          target.style.cssText = getMediaWithScaleCss(newImgProps);\n          if (shouldDisplayBorder(element) && ref.current) {\n            ref.current.style.width =\n              resize[0] + (border?.left || 0) + (border?.right || 0) + 'px';\n            ref.current.style.height =\n              resize[1] + (border?.top || 0) + (border?.bottom || 0) + 'px';\n          }\n        }\n      }\n    }\n  });\n\n  return (\n    <Element\n      ref={ref}\n      border={getResponsiveBorder(border, previewMode, dataToEditorX)}\n      borderRadius={borderRadius}\n      width={width}\n      height={height}\n      mask={mask}\n      showPlaceholder={showPlaceholder}\n    >\n      {showPlaceholder &&\n        renderResourcePlaceholder &&\n        renderResourcePlaceholder(resource)}\n      {children}\n      {overlay && <Overlay backgroundColor={overlay} />}\n    </Element>\n  );\n}\n\nexport default MediaDisplay;\n"
  },
  {
    "path": "packages/element-library/src/media/edit.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n  useUnmount,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  calculateSrcSet,\n  getMediaSizePositionProps,\n} from '@googleforcreators/media';\nimport {\n  DisplayWithMask as WithMask,\n  shouldDisplayBorder,\n} from '@googleforcreators/masks';\nimport {\n  type MediaElement,\n  type SequenceMediaElement,\n  type EditProps,\n  getTransformFlip,\n  elementIs,\n} from '@googleforcreators/elements';\nimport type { Dispatch, SetStateAction } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { elementFillContent, elementWithFlip } from '../shared';\nimport EditCropMoveable from './editCropMoveable';\nimport { mediaWithScale } from './util';\nimport EditPanMoveable from './editPanMoveable';\nimport ScalePanel from './scalePanel';\nimport { MEDIA_MASK_OPACITY } from './constants';\nimport { CropBox } from '.';\n\nconst Element = styled.div`\n  ${elementFillContent}\n`;\n\n// Opacity of the mask is reduced depending on the opacity assigned to the media.\nconst fadedMediaCSS = css<{\n  opacity?: number;\n  width: number;\n  height: number;\n  offsetX: number;\n  offsetY: number;\n  $transformFlip: string | null;\n}>`\n  position: absolute;\n  opacity: ${({ opacity }) =>\n    typeof opacity !== 'undefined'\n      ? opacity * MEDIA_MASK_OPACITY\n      : MEDIA_MASK_OPACITY};\n  pointer-events: none;\n  ${mediaWithScale}\n  ${elementWithFlip}\n`;\n\nconst FadedImage = styled.img`\n  ${fadedMediaCSS}\n`;\n\nconst FadedVideo = styled.video`\n  max-width: initial;\n  max-height: initial;\n  ${fadedMediaCSS}\n`;\n\n// Opacity is adjusted so that the double image opacity would equal\n// the opacity assigned to the image.\nconst cropMediaCSS = css<{\n  opacity?: number;\n  width: number;\n  height: number;\n  offsetX: number;\n  offsetY: number;\n  $transformFlip?: string | null;\n}>`\n  ${mediaWithScale}\n  ${elementWithFlip}\n  position: absolute;\n  cursor: grab;\n  opacity: ${({ opacity }) =>\n    typeof opacity !== 'undefined'\n      ? 1 - (1 - opacity) / (1 - opacity * MEDIA_MASK_OPACITY)\n      : null};\n`;\n\nconst CropImage = styled.img`\n  ${cropMediaCSS}\n`;\n\n// Opacity of the mask is reduced depending on the opacity assigned to the video.\nconst CropVideo = styled.video`\n  max-width: initial;\n  max-height: initial;\n  ${cropMediaCSS}\n`;\n\n// eslint-disable-next-line complexity -- TODO: Refactor to reduce complexity.\nfunction MediaEdit<T extends MediaElement = MediaElement>({\n  element,\n  box,\n  setLocalProperties,\n  getProxiedUrl,\n  updateElementById,\n  zIndexCanvas,\n  scaleMin,\n  scaleMax,\n}: Omit<EditProps<T>, 'isTrimMode'>) {\n  const {\n    id,\n    resource,\n    opacity,\n    scale,\n    flip,\n    focalX,\n    focalY,\n    isBackground,\n    isLocked,\n    borderRadius,\n  } = element;\n  const { x, y, width, height, rotationAngle } = box;\n  const [fullMedia, setFullMedia] = useState<\n    | (T extends SequenceMediaElement ? HTMLVideoElement : HTMLImageElement)\n    | null\n  >(null);\n  const [croppedMedia, setCroppedMedia] = useState<\n    | (T extends SequenceMediaElement ? HTMLVideoElement : HTMLImageElement)\n    | null\n  >(null);\n  const [cropBox, setCropBox] = useState<HTMLDivElement | null>(null);\n  const elementRef = useRef<HTMLDivElement>(null);\n\n  const isUpdatedLocallyRef = useRef(false);\n  const lastLocalPropertiesRef = useRef<Partial<T>>({ scale } as Partial<T>);\n\n  const updateLocalProperties = useCallback(\n    (properties: Partial<T> | ((p: Partial<T>) => Partial<T>)) => {\n      lastLocalPropertiesRef.current = {\n        ...lastLocalPropertiesRef.current,\n        ...(typeof properties === 'function'\n          ? properties(lastLocalPropertiesRef.current)\n          : properties),\n      };\n      isUpdatedLocallyRef.current = true;\n      setLocalProperties(lastLocalPropertiesRef.current);\n    },\n    [setLocalProperties]\n  );\n\n  const updateProperties = useCallback(() => {\n    if (!isUpdatedLocallyRef.current) {\n      return;\n    }\n    isUpdatedLocallyRef.current = false;\n    const properties: Partial<T> = lastLocalPropertiesRef.current;\n    updateElementById({ elementId: id, properties });\n  }, [id, updateElementById]);\n\n  useUnmount(updateProperties);\n\n  const isImage = elementIs.media(element) && !elementIs.video(element);\n  const isVideo = elementIs.video(element);\n\n  const mediaProps = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    flip?.horizontal ? 100 - (focalX || 0) : focalX,\n    flip?.vertical ? 100 - (focalY || 0) : focalY\n  );\n\n  const fadedMediaProps = {\n    draggable: false,\n    alt: '',\n    opacity: (opacity || 100) / 100,\n    $transformFlip: getTransformFlip(flip),\n    ...mediaProps,\n  };\n\n  const cropMediaProps = {\n    draggable: false,\n    src: resource.src,\n    alt: __('Drag to move media element', 'web-stories'),\n    opacity: (opacity || 100) / 100,\n    tabIndex: 0,\n    $transformFlip: getTransformFlip(flip),\n    ...mediaProps,\n  };\n\n  const url = getProxiedUrl(resource, resource?.src);\n  useEffect(() => {\n    if (\n      croppedMedia &&\n      elementRef.current &&\n      !elementRef.current.contains(document.activeElement)\n    ) {\n      croppedMedia.focus();\n    }\n  }, [croppedMedia]);\n\n  const srcSet = calculateSrcSet(element.resource);\n\n  const handleWheel = useCallback(\n    (evt: WheelEvent) => {\n      updateLocalProperties(\n        ({ scale: oldScale }: Partial<T>) =>\n          ({\n            scale: Math.min(\n              scaleMax,\n              Math.max(scaleMin, (oldScale || 0) + evt.deltaY)\n            ),\n          }) as Partial<T>\n      );\n      evt.preventDefault();\n      evt.stopPropagation();\n    },\n    [updateLocalProperties, scaleMin, scaleMax]\n  );\n\n  // Cancelable wheel events require a non-passive listener, which React\n  // can't do on its own, so we need to attach manually.\n  useEffect(() => {\n    const node = elementRef.current;\n    const opts = { passive: false };\n    node?.addEventListener('wheel', handleWheel, opts);\n    // @ts-expect-error TODO: Fix type.\n    return () => node?.removeEventListener('wheel', handleWheel, opts);\n  }, [handleWheel]);\n\n  const borderProps =\n    shouldDisplayBorder(element) && borderRadius\n      ? {\n          borderRadius: element.borderRadius,\n          width: element.width,\n          height: element.height,\n          mask: element.mask,\n        }\n      : null;\n\n  return (\n    <Element ref={elementRef}>\n      {isImage && (\n        /* eslint-disable-next-line styled-components-a11y/alt-text -- False positive. */\n        <FadedImage\n          {...fadedMediaProps}\n          crossOrigin=\"anonymous\"\n          ref={\n            setFullMedia as Dispatch<SetStateAction<HTMLImageElement | null>>\n          }\n          src={url || undefined}\n          srcSet={calculateSrcSet(resource) || undefined}\n        />\n      )}\n      {isVideo && (\n        //eslint-disable-next-line styled-components-a11y/media-has-caption,jsx-a11y/media-has-caption -- Faded video doesn't need captions.\n        <FadedVideo\n          {...fadedMediaProps}\n          crossOrigin=\"anonymous\"\n          ref={\n            setFullMedia as Dispatch<SetStateAction<HTMLVideoElement | null>>\n          }\n        >\n          {url && <source src={url} type={resource.mimeType} />}\n        </FadedVideo>\n      )}\n\n      {/* @ts-expect-error TODO: Fix type. */}\n      <CropBox ref={setCropBox} {...borderProps}>\n        <WithMask element={element} fill applyFlip={false}>\n          {}\n          {isImage && (\n            /*eslint-disable-next-line styled-components-a11y/alt-text -- False positive. */\n            <CropImage\n              {...cropMediaProps}\n              crossOrigin=\"anonymous\"\n              ref={\n                setCroppedMedia as Dispatch<\n                  SetStateAction<HTMLImageElement | null>\n                >\n              }\n              srcSet={srcSet || undefined}\n            />\n          )}\n          {isVideo && (\n            /*eslint-disable-next-line styled-components-a11y/media-has-caption,jsx-a11y/media-has-caption -- Tracks might not exist. Also, unwanted in edit mode. */\n            <CropVideo\n              {...cropMediaProps}\n              crossOrigin=\"anonymous\"\n              ref={\n                setCroppedMedia as Dispatch<\n                  SetStateAction<HTMLVideoElement | null>\n                >\n              }\n            >\n              <source src={url || undefined} type={resource.mimeType} />\n            </CropVideo>\n          )}\n        </WithMask>\n      </CropBox>\n\n      {fullMedia && croppedMedia && (\n        <EditPanMoveable\n          setProperties={updateLocalProperties}\n          fullMedia={fullMedia}\n          croppedMedia={croppedMedia}\n          flip={flip}\n          x={x}\n          y={y}\n          width={width}\n          height={height}\n          rotationAngle={rotationAngle}\n          offsetX={mediaProps.offsetX}\n          offsetY={mediaProps.offsetY}\n          mediaWidth={mediaProps.width}\n          mediaHeight={mediaProps.height}\n        />\n      )}\n\n      {!isBackground && !isLocked && cropBox && croppedMedia && (\n        <EditCropMoveable\n          setProperties={updateLocalProperties}\n          cropBox={cropBox}\n          croppedMedia={croppedMedia}\n          flip={flip}\n          x={x}\n          y={y}\n          width={width}\n          height={height}\n          rotationAngle={rotationAngle}\n          offsetX={mediaProps.offsetX}\n          offsetY={mediaProps.offsetY}\n          mediaWidth={mediaProps.width}\n          mediaHeight={mediaProps.height}\n        />\n      )}\n\n      <ScalePanel<T>\n        aria-label={__('Scale media', 'web-stories')}\n        data-testid=\"edit-panel-slider\"\n        setProperties={updateLocalProperties}\n        x={x}\n        y={y}\n        width={width}\n        height={height}\n        scale={scale || 100}\n        zIndexCanvas={zIndexCanvas}\n        min={scaleMin}\n        max={scaleMax}\n      />\n    </Element>\n  );\n}\n\nexport default MediaEdit;\n"
  },
  {
    "path": "packages/element-library/src/media/editCropMoveable.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport { useUnits, calcRotatedResizeOffset } from '@googleforcreators/units';\nimport { getFocalFromOffset } from '@googleforcreators/media';\nimport { Moveable } from '@googleforcreators/moveable';\nimport {\n  getTransformFlip,\n  type Flip,\n  type MediaElement,\n} from '@googleforcreators/elements';\nimport type MoveableType from 'react-moveable';\n\ninterface EditCropMoveableProps<T> {\n  setProperties: (properties: Partial<T>) => void;\n  cropBox: HTMLElement;\n  croppedMedia: HTMLElement;\n  flip?: Flip;\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n  rotationAngle: number;\n  offsetX: number;\n  offsetY: number;\n  mediaWidth: number;\n  mediaHeight: number;\n}\n\nfunction EditCropMoveable<T extends MediaElement = MediaElement>({\n  setProperties,\n  cropBox,\n  croppedMedia,\n  flip,\n  x,\n  y,\n  width,\n  height,\n  rotationAngle,\n  offsetX,\n  offsetY,\n  mediaWidth,\n  mediaHeight,\n}: EditCropMoveableProps<T>) {\n  const { editorToDataX, editorToDataY } = useUnits((state) => ({\n    editorToDataX: state.actions.editorToDataX,\n    editorToDataY: state.actions.editorToDataY,\n  }));\n\n  const moveableRef = useRef<MoveableType>(null);\n  const cropRef = useRef([0, 0, 0, 0, 0, 0]);\n  const transformFlip = getTransformFlip(flip);\n\n  // Refresh moveables to ensure that the selection rect is always correct.\n  useEffect(() => {\n    moveableRef.current?.updateRect();\n  });\n\n  return (\n    <Moveable\n      ref={moveableRef}\n      className=\"crop-moveable\"\n      target={cropBox}\n      origin={false}\n      resizable\n      onResize={({\n        width: resizeWidth,\n        height: resizeHeight,\n        direction,\n        delta,\n        drag,\n      }) => {\n        // Focal point offset.\n        const [fx, fy] = [drag.beforeTranslate[0], drag.beforeTranslate[1]];\n        // Direction of resize: left/right/top/bottom and resize deltas for\n        // each side.\n        const [dirX, dirY] = direction;\n        const dw = resizeWidth - width;\n        const dh = resizeHeight - height;\n        const left = dirX < 0 ? dw : 0;\n        const right = dirX > 0 ? dw : 0;\n        const top = dirY < 0 ? dh : 0;\n        const bottom = dirY > 0 ? dh : 0;\n        cropRef.current = [fx, fy, left, right, top, bottom];\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        cropBox.style.transform = `translate(${fx}px, ${fy}px)`;\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        croppedMedia.style.transform = `translate(${-fx}px, ${-fy}px) ${\n          transformFlip ?? ''\n        }`;\n\n        if (delta[0]) {\n          cropBox.style.width = `${resizeWidth}px`;\n        }\n        if (delta[1]) {\n          cropBox.style.height = `${resizeHeight}px`;\n        }\n      }}\n      onResizeEnd={() => {\n        const [fx, fy, left, right, top, bottom] = cropRef.current;\n        cropRef.current = [0, 0, 0, 0, 0, 0];\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        cropBox.style.transform = '';\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        croppedMedia.style.transform = '';\n        cropBox.style.width = '';\n        cropBox.style.height = '';\n        if (left === 0 && right === 0 && top === 0 && bottom === 0) {\n          return;\n        }\n        const resizeWidth = width + left + right;\n        const resizeHeight = height + top + bottom;\n        const [dx, dy] = calcRotatedResizeOffset(\n          rotationAngle,\n          left,\n          right,\n          top,\n          bottom\n        );\n        const resizeScale =\n          Math.min(mediaWidth / resizeWidth, mediaHeight / resizeHeight) * 100;\n        const resizeFocalX = getFocalFromOffset(\n          resizeWidth,\n          mediaWidth,\n          offsetX + fx\n        );\n        const resizeFocalY = getFocalFromOffset(\n          resizeHeight,\n          mediaHeight,\n          offsetY + fy\n        );\n        setProperties({\n          x: editorToDataX(x + dx),\n          y: editorToDataY(y + dy),\n          width: editorToDataX(resizeWidth),\n          height: editorToDataY(resizeHeight),\n          scale: resizeScale,\n          focalX: flip?.horizontal ? 100 - resizeFocalX : resizeFocalX,\n          focalY: flip?.vertical ? 100 - resizeFocalY : resizeFocalY,\n        } as Partial<T>);\n      }}\n      snappable\n      // todo@: it looks like resizing bounds are not supported.\n      verticalGuidelines={[x - offsetX, x - offsetX + mediaWidth]}\n      horizontalGuidelines={[y - offsetY, y - offsetY + mediaHeight]}\n    />\n  );\n}\n\nexport default EditCropMoveable;\n"
  },
  {
    "path": "packages/element-library/src/media/editPanMoveable.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef, useCallback } from '@googleforcreators/react';\nimport { getFocalFromOffset } from '@googleforcreators/media';\nimport {\n  useKeyDownEffect,\n  getKeyboardMovement,\n} from '@googleforcreators/design-system';\nimport { Moveable } from '@googleforcreators/moveable';\nimport {\n  type Flip,\n  getTransformFlip,\n  type MediaElement,\n} from '@googleforcreators/elements';\nimport type MoveableType from 'react-moveable';\n\ninterface EditPanMoveableProps<T> {\n  setProperties: (properties: Partial<T>) => void;\n  fullMedia: HTMLElement;\n  croppedMedia: HTMLElement;\n  flip?: Flip;\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n  rotationAngle: number;\n  offsetX: number;\n  offsetY: number;\n  mediaWidth: number;\n  mediaHeight: number;\n}\n\nfunction EditPanMoveable<T extends MediaElement = MediaElement>({\n  setProperties,\n  fullMedia,\n  croppedMedia,\n  flip,\n  x,\n  y,\n  width,\n  height,\n  rotationAngle,\n  offsetX,\n  offsetY,\n  mediaWidth,\n  mediaHeight,\n}: EditPanMoveableProps<T>) {\n  const moveableRef = useRef<MoveableType>(null);\n  const translateRef = useRef([0, 0]);\n  const transformFlip = getTransformFlip(flip);\n\n  const update = useCallback(() => {\n    const [tx, ty] = translateRef.current;\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    fullMedia.style.transform = `translate(${tx}px, ${ty}px) ${\n      transformFlip ?? ''\n    }`;\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    croppedMedia.style.transform = `translate(${tx}px, ${ty}px) ${\n      transformFlip ?? ''\n    }`;\n  }, [croppedMedia, fullMedia, transformFlip]);\n\n  // Refresh moveables to ensure that the selection rect is always correct.\n  useEffect(() => {\n    moveableRef.current?.updateRect();\n  });\n\n  useEffect(update, [update]);\n\n  useKeyDownEffect(\n    croppedMedia,\n    { key: ['up', 'down', 'left', 'right'], shift: true },\n    ({ key, shiftKey }) => {\n      const { dx, dy } = getKeyboardMovement(key, shiftKey);\n      const panFocalX = getFocalFromOffset(width, mediaWidth, offsetX - dx);\n      const panFocalY = getFocalFromOffset(height, mediaHeight, offsetY - dy);\n      setProperties({\n        focalX: flip?.horizontal ? 100 - panFocalX : panFocalX,\n        focalY: flip?.vertical ? 100 - panFocalY : panFocalY,\n      } as Partial<T>);\n      update();\n    },\n    [\n      update,\n      flip?.horizontal,\n      flip?.vertical,\n      offsetX,\n      offsetY,\n      setProperties,\n      width,\n      height,\n      mediaHeight,\n      mediaWidth,\n    ]\n  );\n\n  return (\n    <Moveable\n      ref={moveableRef}\n      target={croppedMedia}\n      origin\n      draggable\n      throttleDrag={0}\n      onDrag={({ dist }) => {\n        translateRef.current = dist;\n        update();\n      }}\n      onDragEnd={() => {\n        croppedMedia.focus();\n        const [tx, ty] = translateRef.current;\n        translateRef.current = [0, 0];\n        const panFocalX = getFocalFromOffset(width, mediaWidth, offsetX - tx);\n        const panFocalY = getFocalFromOffset(height, mediaHeight, offsetY - ty);\n        setProperties({\n          focalX: flip?.horizontal ? 100 - panFocalX : panFocalX,\n          focalY: flip?.vertical ? 100 - panFocalY : panFocalY,\n        } as Partial<T>);\n        update();\n      }}\n      snappable\n      // todo@: Moveable defines bounds and guidelines as the vertical and\n      // horizontal lines and doesn't work well with `rotationAngle > 0` for\n      // cropping/panning. It's possible to define a larger bounds using\n      // the expansion radius, but the UX is very poor for a rotated shape.\n      bounds={\n        rotationAngle === 0\n          ? {\n              left: x + width - mediaWidth,\n              top: y + height - mediaHeight,\n              right: x + mediaWidth,\n              bottom: y + mediaHeight,\n            }\n          : {}\n      }\n      verticalGuidelines={\n        rotationAngle === 0 ? [x, x + width / 2, x + width] : [x + width / 2]\n      }\n      horizontalGuidelines={\n        rotationAngle === 0 ? [y, y + height / 2, y + height] : [y + height / 2]\n      }\n    />\n  );\n}\n\nexport default EditPanMoveable;\n"
  },
  {
    "path": "packages/element-library/src/media/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { elementFillContent } from '../shared';\n\nconst Element = styled.div`\n  ${elementFillContent}\n`;\n\nfunction MediaFrame() {\n  return <Element />;\n}\n\nexport default MediaFrame;\n"
  },
  {
    "path": "packages/element-library/src/media/imageDisplay.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useEffect, useRef, useState } from '@googleforcreators/react';\nimport {\n  calculateSrcSet,\n  getMediaSizePositionProps,\n  getSmallestUrlForWidth,\n  preloadImage,\n  type ResourceCacheEntry,\n  ResourceCacheEntryType,\n  resourceList,\n} from '@googleforcreators/media';\nimport type { ImageElement, DisplayProps } from '@googleforcreators/elements';\nimport type { HTMLProps } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { mediaWithScale } from './util';\nimport MediaDisplay from './display';\n\nconst Image = styled.img`\n  position: absolute;\n  ${mediaWithScale}\n`;\n\nconst noop = () => false;\n\nfunction ImageDisplay({\n  element,\n  box,\n  previewMode,\n  getProxiedUrl,\n  isCurrentResourceProcessing = noop,\n  isCurrentResourceUploading = noop,\n  renderResourcePlaceholder,\n}: DisplayProps<ImageElement>) {\n  const { resource, scale, focalX, focalY } = element;\n  const { id: resourceId, alt } = resource;\n  const { width, height } = box;\n  const ref = useRef<HTMLImageElement>(null);\n\n  let initialSrcType = 'smallest';\n  let initialSrc: string | null = getSmallestUrlForWidth(0, resource);\n\n  if (resourceList.get(resourceId)?.type === ResourceCacheEntryType.Cached) {\n    initialSrcType = 'cached';\n    initialSrc = (resourceList.get(resourceId) as ResourceCacheEntry).url;\n  }\n\n  if (\n    resourceList.get(resourceId)?.type === ResourceCacheEntryType.Fullsize ||\n    isCurrentResourceProcessing(resourceId) ||\n    isCurrentResourceUploading(resourceId)\n  ) {\n    initialSrcType = 'fullsize';\n    initialSrc = resource.src;\n  }\n\n  initialSrc = getProxiedUrl(resource, initialSrc);\n\n  const [srcType, setSrcType] = useState(initialSrcType);\n  const [src, setSrc] = useState<string | null>(initialSrc);\n  const srcSet = srcType === 'fullsize' ? calculateSrcSet(resource) : '';\n\n  const imgProps: HTMLProps<HTMLImageElement> = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    focalX,\n    focalY\n  );\n\n  imgProps.crossOrigin = 'anonymous';\n\n  useEffect(() => {\n    let timeout: number;\n    let mounted = true;\n    if (\n      resourceList.get(resourceId)?.type !== ResourceCacheEntryType.Fullsize &&\n      resource.src\n    ) {\n      timeout = window.setTimeout(() => {\n        void (async () => {\n          const url: string = getProxiedUrl(resource, resource.src) as string;\n          try {\n            const preloadedImg = await preloadImage({\n              src: url,\n              srcset: srcSet || undefined,\n            });\n            if (mounted) {\n              resourceList.set(resource.id, {\n                type: ResourceCacheEntryType.Fullsize,\n                url,\n              });\n              setSrc(preloadedImg.currentSrc);\n              setSrcType(ResourceCacheEntryType.Fullsize);\n            }\n          } catch {\n            // Ignore\n          }\n        })();\n      });\n    } else {\n      setSrc(getProxiedUrl(resource, resource.src));\n    }\n    return () => {\n      mounted = false;\n      clearTimeout(timeout);\n    };\n  }, [getProxiedUrl, resource, srcSet, srcType, resourceId]);\n\n  const showPlaceholder = srcType !== 'fullsize' || resource.isPlaceholder;\n\n  return (\n    <MediaDisplay<ImageElement>\n      element={element}\n      mediaRef={ref}\n      showPlaceholder={showPlaceholder}\n      previewMode={previewMode}\n      renderResourcePlaceholder={renderResourcePlaceholder}\n    >\n      <Image\n        // @ts-expect-error TODO: Investigate.\n        ref={ref}\n        draggable={false}\n        decoding=\"sync\"\n        src={src || undefined}\n        srcSet={srcSet || undefined}\n        alt={alt}\n        data-testid=\"imageElement\"\n        data-leaf-element=\"true\"\n        {...imgProps}\n      />\n    </MediaDisplay>\n  );\n}\n\nexport default ImageDisplay;\n"
  },
  {
    "path": "packages/element-library/src/media/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { elementWithBorderRadius } from '../shared';\n\nexport const CropBox = styled.div`\n  width: 100%;\n  height: 100%;\n  position: relative;\n  overflow: hidden;\n  ${elementWithBorderRadius}\n\n  &::after {\n    content: '';\n    display: block;\n    position: absolute;\n    left: 0;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    pointer-events: none;\n  }\n`;\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/media/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  PAGE_WIDTH,\n  PAGE_HEIGHT,\n  editorPixels,\n  type ElementBox,\n} from '@googleforcreators/units';\nimport { getMediaSizePositionProps } from '@googleforcreators/media';\nimport type {\n  ImageElement,\n  SequenceMediaElement,\n} from '@googleforcreators/elements';\nimport type { CSSProperties, ReactNode } from 'react';\n\ninterface MediaOutputProps {\n  element: SequenceMediaElement | ImageElement;\n  box: ElementBox;\n  children: ReactNode;\n  'data-leaf-element': 'true';\n}\n\n/**\n * Returns AMP HTML for saving into post content for displaying in the FE.\n *\n * @return Rendered component.\n */\nfunction MediaOutput({\n  element: { resource, scale, focalX, focalY },\n  box: { width: vw, height: vh },\n  children,\n  ...props\n}: MediaOutputProps) {\n  // Width and height are taken from the basis of 100% taking into account the\n  // aspect ratio.\n  const width = vw;\n  const height = (vh * PAGE_HEIGHT) / PAGE_WIDTH;\n  const mediaProps = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    focalX,\n    focalY\n  );\n\n  const wrapperStyle: CSSProperties = {\n    position: 'absolute',\n    width: `${editorPixels((mediaProps.width / width) * 100)}%`,\n    height: `${editorPixels((mediaProps.height / height) * 100)}%`,\n    left: `${-editorPixels((mediaProps.offsetX / width) * 100)}%`,\n    top: `${-editorPixels((mediaProps.offsetY / height) * 100)}%`,\n  };\n\n  return (\n    <div style={wrapperStyle} {...props}>\n      {children}\n    </div>\n  );\n}\n\nexport default MediaOutput;\n"
  },
  {
    "path": "packages/element-library/src/media/scalePanel.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { _x } from '@googleforcreators/i18n';\nimport { Slider } from '@googleforcreators/design-system';\nimport { InOverlay } from '@googleforcreators/moveable';\nimport type { MediaElement } from '@googleforcreators/elements';\n\nconst MIN_WIDTH = 165;\nconst HEIGHT = 36;\nconst OFFSET_Y = 8;\nconst HORIZONTAL_PADDING = 8;\n\nconst Container = styled.div<{\n  $x: number;\n  $y: number;\n  $width: number;\n  $height: number;\n}>`\n  position: absolute;\n  left: ${({ $x, $width }) =>\n    `${$x + ($width - Math.max($width, MIN_WIDTH)) / 2}px`};\n  top: ${({ $y, $height }) => `${$y + $height + OFFSET_Y}px`};\n  width: ${({ $width }) => `${Math.max($width, MIN_WIDTH)}px`};\n  height: ${HEIGHT}px;\n  background: ${({ theme }) => theme.colors.bg.primary};\n  border-radius: 8px;\n  padding: 3px ${HORIZONTAL_PADDING}px;\n  margin-top: 8px;\n`;\n\nconst ScaleSlider = styled(Slider)<{ width: number }>`\n  width: ${({ width }) =>\n    Math.max(width, MIN_WIDTH) - 2 * HORIZONTAL_PADDING}px;\n`;\n\ninterface ScalePanelProps<T> {\n  setProperties: (properties: Partial<T>) => void;\n  width: number;\n  height: number;\n  x: number;\n  y: number;\n  scale: number;\n  zIndexCanvas: Record<string, number>;\n  min?: number;\n  max?: number;\n}\n\nfunction ScalePanel<T extends MediaElement = MediaElement>({\n  setProperties,\n  width,\n  height,\n  x,\n  y,\n  scale,\n  zIndexCanvas,\n  ...rest\n}: ScalePanelProps<T>) {\n  return (\n    <InOverlay zIndex={zIndexCanvas.FLOAT_PANEL} pointerEvents=\"initial\">\n      <Container $x={x} $y={y} $width={width} $height={height}>\n        {/*\n          @todo: Should maxScale depend on the maximum resolution? Or should that\n          be left up to the helper errors? Both? In either case there'd be maximum\n          bounding scale.\n        */}\n        <ScaleSlider\n          width={width}\n          majorStep={10}\n          minorStep={1}\n          value={scale}\n          handleChange={(value: number) =>\n            setProperties({ scale: value } as Partial<T>)\n          }\n          thumbSize={24}\n          suffix={_x('%', 'Percentage', 'web-stories')}\n          {...rest}\n        />\n      </Container>\n    </InOverlay>\n  );\n}\n\nexport default ScalePanel;\n"
  },
  {
    "path": "packages/element-library/src/media/textContent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { type MediaElement } from '@googleforcreators/elements';\n\nfunction TextContent({ resource }: MediaElement) {\n  return `image: ${resource.src}`;\n}\n\nexport default TextContent;\n"
  },
  {
    "path": "packages/element-library/src/media/util.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\nexport const mediaWithScale = css<{\n  width: number;\n  height: number;\n  offsetX: number;\n  offsetY: number;\n}>`\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n  left: ${({ offsetX }) => `${-offsetX}px`};\n  top: ${({ offsetY }) => `${-offsetY}px`};\n`;\n\nconst videoWithScale = css<{\n  width: number;\n  offsetX: number;\n  offsetY: number;\n  isBackground?: boolean;\n}>`\n  width: ${({ width }) => `${width}px`};\n  left: ${({ offsetX }) => `${-offsetX}px`};\n  top: ${({ offsetY }) => `${-offsetY}px`};\n  max-width: ${({ isBackground }) => (isBackground ? 'initial' : null)};\n`;\n\nexport function getMediaWithScaleCss({\n  width,\n  height,\n  offsetX,\n  offsetY,\n}: {\n  width: number;\n  height: number;\n  offsetX: number;\n  offsetY: number;\n}) {\n  // @todo: This is a complete duplication of `mediaWithScale` above. But\n  // no other apparent way to execute interpolate `mediaWithScale` dynamically.\n  return `width:${width}px; height:${height}px; left:${-offsetX}px; top:${-offsetY}px;`;\n}\n\nexport const getBackgroundStyle = () => {\n  return {\n    minWidth: '100%',\n    minHeight: '100%',\n    maxWidth: 'initial',\n  };\n};\n\n// TODO: Display poster as actual <img> with crossorigin attr to avoid CORS issues.\nexport const Video = styled.video.attrs({ crossOrigin: 'anonymous' })`\n  position: absolute;\n  max-width: initial;\n  max-height: initial;\n  height: ${({ height }) => `${height}px`};\n  background-image: ${({ poster }) => poster && `url(\"${poster}\")`};\n  background-repeat: no-repeat;\n  background-size: cover;\n  ${videoWithScale}\n`;\n\nexport const VideoImage = styled.img.attrs({ crossOrigin: 'anonymous' })`\n  position: absolute;\n  max-height: initial;\n  object-fit: contain;\n  ${videoWithScale}\n`;\n"
  },
  {
    "path": "packages/element-library/src/media/videoImage.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\nconst Video = styled.video`\n  display: block;\n  height: 21px;\n  width: 21px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  object-fit: cover;\n`;\n\nfunction VideoImage({ alt, ...attrs }: { src: string; alt: string }) {\n  return (\n    <Video\n      controls={false}\n      crossOrigin=\"anonymous\"\n      disablePictureInPicture\n      muted\n      // @ts-expect-error TODO: Is this actually legit?\n      noControls\n      title={alt}\n      {...attrs}\n    />\n  );\n}\n\nexport default VideoImage;\n"
  },
  {
    "path": "packages/element-library/src/product/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { PanelTypes } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nconst defaultBackgroundColor = createSolidFromString('#c4c4c4');\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  backgroundColor: defaultBackgroundColor,\n  lockDimensions: true,\n  supportsRotation: false,\n};\n\nexport const hasEditMode = false;\nexport const hasEditModeIfLocked = false;\nexport const hasEditModeMoveable = false;\nexport const editModeGrayout = false;\n\nexport const hasDesignMenu = true;\n\nexport const hasDuplicateMenu = false;\n\nexport const isMedia = false;\n\nexport const canFlip = true;\n\nexport const isMaskable = false;\n\nexport const isAspectAlwaysLocked = false;\n\nexport const resizeRules = {\n  vertical: true,\n  horizontal: true,\n  diagonal: true,\n  minWidth: 20,\n  minHeight: 20,\n};\n\nexport const panels = [PanelTypes.Product];\n"
  },
  {
    "path": "packages/element-library/src/product/display.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { keyframes } from 'styled-components';\nimport { useRef } from '@googleforcreators/react';\nimport {\n  createSolid,\n  generatePatternStyles,\n} from '@googleforcreators/patterns';\nimport type {\n  Element,\n  ProductElement,\n  DisplayProps,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { elementFillContent } from '../shared';\nimport useColorTransformHandler from '../shared/useColorTransformHandler';\n\nconst Element = styled.div`\n  ${elementFillContent}\n`;\n\nconst animateInSequenceBefore = keyframes`\n  0% {\n    animation-timing-function: cubic-bezier(.85, 0, .15, 1);\n    transform: scale(0);\n  }\n  60% {\n    transform: scale(1);\n  }\n  100% {\n    transform: scale(1);\n  }\n`;\n\nconst pulseDotBefore = keyframes`\n  0% {\n    animation-timing-function: cubic-bezier(.83, 0, .71, .99);\n    transform: scale(1);\n  }\n  40% {\n    transform: scale(.8);\n  }\n  90% {\n    transform: scale(1);\n  }\n  100% {\n    transform: scale(1);\n  }\n`;\n\nconst animateInSequenceAfter = keyframes`\n  0% {\n    animation-timing-function: cubic-bezier(.85, 0, .15, 1);\n    transform: scale(0);\n  }\n  40% {\n    transform: scale(1);\n  }\n  100% {\n    transform: scale(1);\n  }\n`;\n\nconst pulseDotAfter = keyframes`\n  0% {\n    animation-timing-function: cubic-bezier(0.76, 0, 0.24, 1);\n    transform: scale(1);\n  }\n  40% {\n    transform: scale(.8);\n  }\n  90% {\n    transform: scale(1);\n  }\n  100% {\n    transform: scale(1);\n  }\n`;\n\n// See https://github.com/ampproject/amphtml/blob/b2dbb6b805529b7cf699dad3a91f6d7556131543/extensions/amp-story-shopping/0.1/amp-story-shopping-tag.css\nconst ShoppingTagDot = styled.div`\n  border-radius: 100%;\n  position: relative;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-shrink: 0;\n  width: 100%;\n  height: 100%;\n\n  &:before {\n    content: '';\n    position: absolute;\n    border-radius: inherit;\n    width: 100%;\n    height: 100%;\n    ${generatePatternStyles(createSolid(125, 125, 125, 0.75))};\n  }\n\n  @media (prefers-reduced-motion: no-preference) {\n    &:before {\n      animation:\n        ${animateInSequenceBefore} 2s forwards,\n        ${pulseDotBefore} 2.5s 1.5s infinite;\n    }\n  }\n\n  &:after {\n    content: '';\n    position: absolute;\n    border-radius: inherit;\n    width: 50%;\n    height: 50%;\n    ${generatePatternStyles(\n      createSolid(125, 125, 125, 0.75),\n      '--box-shadow-color'\n    )};\n    box-shadow: 0 2px 8px var(--box-shadow-color);\n    background-color: white;\n  }\n\n  @media (prefers-reduced-motion: no-preference) {\n    &:after {\n      animation:\n        ${animateInSequenceAfter} 2s forwards,\n        ${pulseDotAfter} 2.5s calc(1.5s * 1.2) infinite;\n    }\n  }\n`;\n\nfunction ProductDisplay({\n  element,\n  siblingCount,\n}: DisplayProps<ProductElement>) {\n  const { id } = element;\n\n  const ref = useRef<HTMLDivElement | null>(null);\n  useColorTransformHandler({ id, targetRef: ref });\n\n  return (\n    <Element ref={ref}>\n      <ShoppingTagDot\n        key={`dots-${siblingCount}`} /* see: https://github.com/GoogleForCreators/web-stories-wp/issues/11705 */\n      />\n    </Element>\n  );\n}\n\nexport default ProductDisplay;\n"
  },
  {
    "path": "packages/element-library/src/product/icon.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport type {\n  ProductElement,\n  LayerIconProps,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport VisibleImage from '../shared/visibleImage';\n\nfunction ProductLayerIcon({\n  element: { product },\n}: LayerIconProps<ProductElement>) {\n  const productImage = product?.productImages?.[0] || {};\n  const { url, alt } = productImage;\n  if (!url) {\n    return <Icons.Shopping width={21} height={21} aria-hidden />;\n  }\n  return <VisibleImage src={url} alt={alt} height={21} width={21} />;\n}\n\nexport default ProductLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/product/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Display } from './display';\nexport { default as Output } from './output';\nexport { default as getLayerText } from './layer';\nexport { default as LayerIcon } from './icon';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/product/layer.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { ProductElement } from '@googleforcreators/elements';\n\nfunction getProductLayerText(element: ProductElement) {\n  return element?.product?.productTitle || __('Product', 'web-stories');\n}\n\nexport default getProductLayerText;\n"
  },
  {
    "path": "packages/element-library/src/product/output.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ProductElement, OutputProps } from '@googleforcreators/elements';\n\n/**\n * Returns AMP HTML for saving into post content for displaying in the FE.\n *\n * @param props Props.\n * @return Rendered component.\n */\nfunction ProductOutput({ element }: OutputProps<ProductElement>) {\n  const { product } = element;\n\n  if (!product?.productId) {\n    return null;\n  }\n\n  return <amp-story-shopping-tag data-product-id={product.productId} />;\n}\n\nexport default ProductOutput;\n"
  },
  {
    "path": "packages/element-library/src/shape/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { PanelTypes } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nconst defaultBackgroundColor = createSolidFromString('#c4c4c4');\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  backgroundColor: defaultBackgroundColor,\n};\n\nexport const hasEditMode = false;\nexport const hasEditModeIfLocked = false;\nexport const hasEditModeMoveable = false;\nexport const editModeGrayout = false;\n\nexport const hasDesignMenu = true;\n\nexport const isMedia = false;\n\nexport const canFlip = true;\n\nexport const hasDuplicateMenu = true;\n\nexport const isMaskable = true;\n\nexport const isAspectAlwaysLocked = false;\n\nexport const resizeRules = {\n  vertical: true,\n  horizontal: true,\n  diagonal: true,\n  minWidth: 20,\n  minHeight: 20,\n};\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  PanelTypes.SizePosition,\n  PanelTypes.Border,\n  PanelTypes.Link,\n  PanelTypes.ShapeStyle,\n  PanelTypes.Animation,\n];\n"
  },
  {
    "path": "packages/element-library/src/shape/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useRef } from '@googleforcreators/react';\nimport { useUnits } from '@googleforcreators/units';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport {\n  getResponsiveBorder,\n  shouldDisplayBorder,\n} from '@googleforcreators/masks';\nimport type { ShapeElement, DisplayProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport {\n  elementFillContent,\n  elementWithBackgroundColor,\n  elementWithBorder,\n  useColorTransformHandler,\n} from '../shared';\n\nconst Element = styled.div<\n  Partial<\n    Pick<\n      ShapeElement,\n      | 'border'\n      | 'borderRadius'\n      | 'width'\n      | 'height'\n      | 'mask'\n      | 'backgroundColor'\n    >\n  >\n>`\n  ${elementFillContent}\n  ${elementWithBackgroundColor}\n  ${elementWithBorder}\n`;\n\nfunction ShapeDisplay({ element, previewMode }: DisplayProps<ShapeElement>) {\n  const {\n    id,\n    isDefaultBackground,\n    backgroundColor,\n    border,\n    borderRadius,\n    mask,\n    width: elementWidth,\n    height: elementHeight,\n  } = element;\n\n  const { dataToEditorX } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n  }));\n\n  const ref = useRef<HTMLDivElement>(null);\n  useColorTransformHandler({ id, targetRef: ref });\n\n  useTransformHandler(id, (transform) => {\n    // Since outside border is applied directly to the element, we need to\n    // adjust the size of the element according to the border width.\n    if (ref.current && !isDefaultBackground) {\n      if (transform) {\n        const { resize } = transform;\n        if (resize && resize[0] !== 0 && resize[1] !== 0) {\n          const [width, height] = resize;\n          if (shouldDisplayBorder(element)) {\n            ref.current.style.width =\n              width + (border?.left || 0) + (border?.right || 0) + 'px';\n            ref.current.style.height =\n              height + (border?.top || 0) + (border?.bottom || 0) + 'px';\n          }\n        }\n      } else {\n        ref.current.style.width = '';\n        ref.current.style.height = '';\n      }\n    }\n  });\n\n  if (isDefaultBackground) {\n    return <Element ref={ref} />;\n  }\n\n  return (\n    <Element\n      ref={ref}\n      backgroundColor={backgroundColor}\n      borderRadius={borderRadius}\n      width={elementWidth}\n      height={elementHeight}\n      border={getResponsiveBorder(border, previewMode, dataToEditorX)}\n      mask={mask}\n    />\n  );\n}\n\nexport default ShapeDisplay;\n"
  },
  {
    "path": "packages/element-library/src/shape/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { getMaskByType } from '@googleforcreators/masks';\nimport type { ShapeElement, LayerIconProps } from '@googleforcreators/elements';\nimport {\n  generatePatternStyles,\n  type Pattern,\n} from '@googleforcreators/patterns';\n\nconst Container = styled.div`\n  display: flex;\n  flex-direction: row;\n  justify-content: center;\n  align-items: center;\n  height: 21px;\n  width: 21px;\n  padding: 1px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  background-color: ${({ theme }) => theme.colors.opacity.black10};\n`;\n\nconst ShapePreview = styled.div.attrs(\n  ({ $backgroundColor }: { $backgroundColor: Pattern | undefined }) => ({\n    // Prevents `ShapePreview` class from being generated with each new layer.\n    // https://styled-components.com/docs/faqs#when-to-use-attrs\n    style: generatePatternStyles($backgroundColor),\n  })\n)<{ $maskId: string; $backgroundColor: Pattern | undefined }>`\n  width: 100%;\n  height: 100%;\n  margin: 1px;\n  clip-path: ${({ $maskId }) => `url(#${$maskId})`};\n`;\n\n/*\nclip-path isn't stable in Safari yet, so these\nShape Layer Icons are going to show up as various quadrilateral\nuntil that stabilizes for inline SVGs as clip paths.\nMore info here:\nhttps://stackoverflow.com/questions/41860477/why-doesnt-css-clip-path-with-svg-work-in-safari\nhttps://caniuse.com/css-clip-path\n*/\n\nfunction ShapeLayerIcon({\n  element: { id, mask, backgroundColor, isDefaultBackground },\n  currentPageBackgroundColor,\n}: LayerIconProps<ShapeElement>) {\n  const maskDef = getMaskByType(mask?.type);\n\n  const maskId = `mask-${maskDef.type}-${id}-layer-preview`;\n  if (isDefaultBackground) {\n    backgroundColor = currentPageBackgroundColor;\n  }\n\n  return (\n    <Container>\n      <ShapePreview $maskId={maskId} $backgroundColor={backgroundColor}>\n        <svg width={0} height={0}>\n          <defs>\n            <clipPath\n              id={maskId}\n              // Bring the path scale down a bit from 1\n              // so that we can make sure the entire SVG path is visible when the mask ratio is > 1\n              // this is important for Firefox's interpretation of clip paths\n              transform=\"scale(1 0.9)\"\n              clipPathUnits=\"objectBoundingBox\"\n            >\n              <path d={maskDef.path} />\n            </clipPath>\n          </defs>\n        </svg>\n      </ShapePreview>\n    </Container>\n  );\n}\n\nexport default ShapeLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/shape/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Display } from './display';\nexport { default as Output } from './output';\nexport { default as getLayerText } from './layer';\nexport { default as LayerIcon } from './icon';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/shape/layer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { getMaskByType } from '@googleforcreators/masks';\nimport type { ShapeElement } from '@googleforcreators/elements';\n\nfunction getShapeLayerText(element: ShapeElement) {\n  const maskDef = getMaskByType(element.mask?.type).name;\n  return maskDef || __('Shape', 'web-stories');\n}\n\nexport default getShapeLayerText;\n"
  },
  {
    "path": "packages/element-library/src/shape/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport type { ShapeElement, OutputProps } from '@googleforcreators/elements';\n\n/**\n * Returns AMP HTML for saving into post content for displaying in the FE.\n *\n * @param props Props.\n * @return Rendered component.\n */\nfunction ShapeOutput({\n  element: { backgroundColor, isDefaultBackground },\n}: OutputProps<ShapeElement>) {\n  const style = isDefaultBackground\n    ? null\n    : generatePatternStyles(backgroundColor);\n  // willChange added by #7380 https://github.com/googleforcreators/web-stories-wp/pull/7380\n  // to prevent issues with the border radius on shapes not being respected when animated\n  return <div className=\"fill\" style={{ ...style, willChange: 'transform' }} />;\n}\n\nexport default ShapeOutput;\n"
  },
  {
    "path": "packages/element-library/src/shape/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport ShapeOutput from '../output';\n\ndescribe('Shape output', () => {\n  it('should produce valid AMP output', async () => {\n    const props = {\n      element: {\n        type: 'shape',\n        id: '123',\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n      },\n      box: { width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 },\n    };\n\n    await expect(<ShapeOutput {...props} />).toBeValidAMPStoryElement();\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/shared/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const SHARED_DEFAULT_ATTRIBUTES = {\n  opacity: 100,\n  flip: {\n    vertical: false,\n    horizontal: false,\n  },\n  rotationAngle: 0,\n  lockAspectRatio: true,\n};\n"
  },
  {
    "path": "packages/element-library/src/shared/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\nexport * from './shared';\nexport { default as useColorTransformHandler } from './useColorTransformHandler';\n"
  },
  {
    "path": "packages/element-library/src/shared/shared.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\nimport {\n  generatePatternStyles,\n  type Pattern,\n} from '@googleforcreators/patterns';\nimport { getBorderStyle, getBorderRadius } from '@googleforcreators/masks';\nimport type {\n  BorderRadius,\n  Element,\n  TextElementFont,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { generateFontFamily } from '../text/util';\n\nexport const elementFillContent = css`\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n`;\n\nexport const elementWithPosition = css<Element>`\n  position: absolute;\n  z-index: 1;\n  left: ${({ x }) => `${x}px`};\n  top: ${({ y }) => `${y}px`};\n`;\n\n// TODO: removed round/ceil, calculateFitTextFontSize needs to be improved?\nexport const elementWithSize = css<{ width: number; height: number }>`\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n`;\n\nexport const elementWithRotation = css<{ rotationAngle: number }>`\n  transform: ${({ rotationAngle }) => `rotate(${rotationAngle}deg)`};\n`;\n\nexport const elementWithBorderRadius = css<Element>`\n  ${(element) => getBorderRadius(element)}\n`;\n\ntype DataToStyle = (prop: number) => string | number;\n\nexport const elementWithHighlightBorderRadius = ({\n  borderRadius,\n  dataToEditorY,\n}: {\n  borderRadius?: BorderRadius;\n  dataToEditorY?: DataToStyle;\n}) =>\n  dataToEditorY &&\n  css`\n    border-radius: ${dataToEditorY(borderRadius?.topLeft || 0)}px\n      ${dataToEditorY(borderRadius?.topRight || 0)}px\n      ${dataToEditorY(borderRadius?.bottomRight || 0)}px\n      ${dataToEditorY(borderRadius?.bottomLeft || 0)}px;\n  `;\n\nexport const elementWithBorder = css<\n  Partial<\n    Pick<Element, 'border' | 'borderRadius' | 'width' | 'height' | 'mask'>\n  >\n>`\n  ${({ border, borderRadius, width, height, mask }) =>\n    getBorderStyle({\n      border,\n      borderRadius,\n      width,\n      height,\n      mask,\n    } as Element)}\n  background-clip: padding-box;\n`;\n\nexport const elementWithBackgroundColor = css<{\n  backgroundColor?: Pattern;\n}>`\n  ${({ backgroundColor }) =>\n    backgroundColor && generatePatternStyles(backgroundColor)};\n`;\n\nexport const elementWithFont = css<{\n  font: TextElementFont;\n  fontStyle?: string;\n  fontSize: string | number;\n  fontWeight?: string | number;\n}>`\n  white-space: pre-line;\n  font-family: ${({ font }) => generateFontFamily(font)};\n  overflow-wrap: break-word;\n  word-break: break-word;\n  letter-spacing: normal;\n  font-style: ${({ fontStyle }) => fontStyle};\n  font-size: ${({ fontSize }) => fontSize}px;\n  font-weight: ${({ fontWeight }) => fontWeight};\n  color: #000000;\n`;\n\n// See generateParagraphTextStyle for the full set of properties.\nexport const elementWithTextParagraphStyle = css<{\n  margin?: number | string;\n  padding?: number | string;\n  lineHeight?: number | string;\n  textAlign?: string;\n}>`\n  margin: ${({ margin }) => margin};\n  padding: ${({ padding }) => padding || 0};\n  line-height: ${({ lineHeight }) => lineHeight};\n  text-align: ${({ textAlign }) => textAlign};\n  overflow-wrap: break-word;\n`;\n\nexport const elementWithFlip = css<{\n  $transformFlip?: string | null;\n}>`\n  ${({ $transformFlip }) => $transformFlip && `transform: ${$transformFlip}`};\n`;\n"
  },
  {
    "path": "packages/element-library/src/shared/useCSSVarColorTransformHandler.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ElementId } from '@googleforcreators/elements';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport type { RefObject } from 'react';\nimport type { Solid } from '@googleforcreators/patterns';\n\nfunction useCSSVarColorTransformHandler({\n  id,\n  targetRef,\n  cssVar,\n  expectedStyle,\n}: {\n  id: ElementId;\n  targetRef: RefObject<HTMLElement>;\n  cssVar: string;\n  expectedStyle: string;\n}) {\n  useTransformHandler(id, (transform) => {\n    const target = targetRef.current;\n    if (target) {\n      if (transform === null) {\n        target.style.removeProperty(cssVar);\n      } else {\n        const { color, style } = transform;\n        if (color && style === expectedStyle) {\n          const {\n            color: { r, g, b, a },\n          } = color as Solid;\n          target.style.setProperty(\n            cssVar,\n            `rgba(${r}, ${g}, ${b}, ${a !== undefined ? a : 1})`\n          );\n        }\n      }\n    }\n  });\n}\n\nexport default useCSSVarColorTransformHandler;\n"
  },
  {
    "path": "packages/element-library/src/shared/useColorTransformHandler.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  generatePatternStyles,\n  convertToCSS,\n  type Solid,\n} from '@googleforcreators/patterns';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport type { ElementId } from '@googleforcreators/elements';\nimport type { RefObject } from 'react';\n\nfunction useColorTransformHandler({\n  id,\n  targetRef,\n  expectedStyle,\n  resetOnNullTransform = true,\n}: {\n  id: ElementId;\n  targetRef: RefObject<HTMLElement | null> | null;\n  expectedStyle?: string;\n  resetOnNullTransform?: boolean;\n}) {\n  useTransformHandler(id, (transform) => {\n    // @ts-expect-error -- Can only be an HTMLElement or null.\n    const target: HTMLElement | null =\n      undefined !== targetRef?.current ? targetRef.current : targetRef;\n    if (target) {\n      if (transform === null) {\n        if (resetOnNullTransform) {\n          // eslint-disable-next-line react-hooks/immutability -- FIXME\n          target.style.cssText = '';\n        }\n      } else {\n        const { color, style } = transform;\n        // If the transforming style and the expected style don't match, return.\n        if (expectedStyle && expectedStyle !== style) {\n          return;\n        }\n        if (color && style) {\n          // In case we're changing text color, we need the children instead of the element itself.\n          if ('color' === style && target.children?.length > 0) {\n            const toApply = convertToCSS(\n              generatePatternStyles(color as Solid, style)\n            );\n            for (const node of target.children) {\n              (node as HTMLElement).style.cssText = toApply;\n            }\n          } else {\n            target.style.cssText = convertToCSS(\n              generatePatternStyles(color as Solid, style)\n            );\n          }\n        }\n      }\n    }\n  });\n}\n\nexport default useColorTransformHandler;\n"
  },
  {
    "path": "packages/element-library/src/shared/visibleImage.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport type { ImgHTMLAttributes } from 'react';\n\nconst Image = styled.img`\n  display: block;\n  height: 21px;\n  width: 21px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  object-fit: cover;\n`;\n\nfunction VisibleImage({ ...attrs }: ImgHTMLAttributes<HTMLImageElement>) {\n  // The image is purely decorative by default, because the alt text is already used\n  // for the layer description. Hence, using alt=\"\" to avoid repetition.\n  return <Image alt=\"\" {...attrs} decoding=\"async\" crossOrigin=\"anonymous\" />;\n}\n\nexport default VisibleImage;\n"
  },
  {
    "path": "packages/element-library/src/sticker/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nexport const hasEditMode = false;\nexport const hasEditModeIfLocked = false;\nexport const hasEditModeMoveable = false;\nexport const editModeGrayout = false;\n\nexport const hasDesignMenu = true;\nexport const hasDuplicateMenu = true;\n\nexport const isMedia = false;\n\nexport const canFlip = true;\n\nexport const isMaskable = false;\n\nexport const isAspectAlwaysLocked = true;\n\nexport const resizeRules = {\n  diagonal: true,\n  minWidth: 20,\n  minHeight: 20,\n};\n\nexport const defaultAttributes = SHARED_DEFAULT_ATTRIBUTES;\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  PanelTypes.SizePosition,\n  PanelTypes.Animation,\n  PanelTypes.Link,\n];\n"
  },
  {
    "path": "packages/element-library/src/sticker/display.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport stickers from '@googleforcreators/stickers';\nimport type { StickerElement, DisplayProps } from '@googleforcreators/elements';\nimport type { CSSProperties } from 'react';\n\nconst style: CSSProperties = {\n  display: 'block',\n  position: 'absolute',\n  top: 0,\n  height: '100%',\n  width: 'auto',\n};\n\nconst Noop = () => null;\n\nfunction StickerDisplay({ element }: DisplayProps<StickerElement>) {\n  const { sticker } = element;\n  const Sticker = stickers[sticker?.type]?.svg || Noop;\n  return <Sticker style={style} />;\n}\n\nexport default StickerDisplay;\n"
  },
  {
    "path": "packages/element-library/src/sticker/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport stickers from '@googleforcreators/stickers';\nimport type {\n  StickerElement,\n  LayerIconProps,\n} from '@googleforcreators/elements';\n\nconst style = {\n  display: 'block',\n  height: 21,\n  width: 21,\n};\n\nconst Noop = () => null;\n\nfunction StickerLayerIcon({ element }: LayerIconProps<StickerElement>) {\n  const { sticker } = element;\n  const Sticker = stickers[sticker.type]?.svg || Noop;\n\n  return <Sticker style={style} />;\n}\n\nexport default StickerLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/sticker/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as getLayerText } from './layer';\nexport { default as Output } from './output';\nexport { default as LayerIcon } from './icon';\nexport { default as Display } from './display';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/sticker/layer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport stickers from '@googleforcreators/stickers';\nimport type { StickerElement } from '@googleforcreators/elements';\n\nfunction getStickerLayerText(element: StickerElement) {\n  const { sticker } = element;\n  return stickers[sticker?.type]?.title || __('Sticker', 'web-stories');\n}\n\nexport default getStickerLayerText;\n"
  },
  {
    "path": "packages/element-library/src/sticker/output.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport stickers from '@googleforcreators/stickers';\nimport type { StickerElement, OutputProps } from '@googleforcreators/elements';\nimport type { CSSProperties } from 'react';\n\nconst style: CSSProperties = {\n  display: 'block',\n  position: 'absolute',\n  top: 0,\n  height: '100%',\n  width: 'auto',\n};\n\nconst Noop = () => null;\n\nfunction StickerOutput({ element }: OutputProps<StickerElement>) {\n  const { sticker } = element;\n  const Sticker = stickers[sticker.type]?.svg || Noop;\n  return <Sticker className=\"fill\" style={style} />;\n}\n\nexport default StickerOutput;\n"
  },
  {
    "path": "packages/element-library/src/test/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createNewElement,\n  createPage,\n  duplicatePage,\n  duplicateElement,\n  registerElementType,\n  TEXT_ELEMENT_DEFAULT_FONT,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport elementTypes from '../elementTypes';\n\ndescribe('Element', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  describe('createNewElement', () => {\n    it('should create an element with just default attributes', () => {\n      const imageElement = createNewElement('image');\n      expect(imageElement).toStrictEqual(\n        expect.objectContaining({\n          opacity: 100, // a default shared attribute\n          scale: 100, // a default media attribute\n        })\n      );\n    });\n\n    it('should create an element with correct attributes', () => {\n      const atts = {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 100,\n      };\n      const textElement = createNewElement('text', atts);\n      expect(textElement.rotationAngle).toBe(0);\n      expect(textElement.width).toBe(100);\n      expect(textElement.font).toMatchObject(TEXT_ELEMENT_DEFAULT_FONT);\n    });\n\n    it('should throw if trying to create unknown element type', () => {\n      const unknownElementCreator = () => createNewElement('puppy');\n      expect(unknownElementCreator).toThrow(\n        /No element definition found for 'puppy'/i\n      );\n    });\n  });\n\n  describe('createPage', () => {\n    it('should create a Page element with default background element', () => {\n      const page = createPage();\n      expect(page.elements).toStrictEqual([\n        expect.objectContaining({\n          isBackground: true,\n          isDefaultBackground: true,\n        }),\n      ]);\n    });\n  });\n\n  describe('duplicateElement', () => {\n    it('should create element with new id', () => {\n      const oldElement = {\n        id: 'abc',\n        type: 'image',\n        x: 10,\n        y: 20,\n      };\n      const { element } = duplicateElement({\n        element: oldElement,\n        shouldOffset: false,\n      });\n      expect(element).toStrictEqual(\n        expect.objectContaining({\n          ...oldElement,\n          id: expect.not.stringMatching(new RegExp(`/^${oldElement.id}$/`)),\n        })\n      );\n    });\n\n    it('should offset element if based on an existing element', () => {\n      const oldElement = {\n        id: 'abc',\n        type: 'image',\n        x: 10,\n        y: 20,\n      };\n      const { element } = duplicateElement({\n        element: oldElement,\n        currentElements: [oldElement],\n      });\n      expect(element).toStrictEqual(\n        expect.objectContaining({\n          ...oldElement,\n          id: expect.not.stringMatching(new RegExp(`/^${oldElement.id}$/`)),\n          x: expect.any(Number),\n          y: expect.any(Number),\n        })\n      );\n      expect(element.x).not.toBe(oldElement.x);\n      expect(element.y).not.toBe(oldElement.y);\n    });\n\n    it('should duplicate element animations', () => {\n      const oldElement = {\n        id: 'abc',\n        type: 'image',\n        x: 10,\n        y: 20,\n      };\n      const animations = [\n        { id: 'aaaa', type: 'animation_1', targets: [oldElement.id] },\n        { id: 'bbbb', type: 'animation_1', targets: ['ccc'] },\n        { id: 'cccc', type: 'animation_2', targets: [oldElement.id] },\n      ];\n      const { element, elementAnimations } = duplicateElement({\n        element: oldElement,\n        animations: animations,\n      });\n\n      expect(elementAnimations).toStrictEqual([\n        expect.objectContaining({\n          ...animations[0],\n          id: expect.not.stringMatching(new RegExp(`/^${animations[0].id}$/`)),\n          targets: [element.id],\n        }),\n        expect.objectContaining({\n          ...animations[2],\n          id: expect.not.stringMatching(new RegExp(`/^${animations[2].id}$/`)),\n          targets: [element.id],\n        }),\n      ]);\n    });\n  });\n\n  describe('duplicatePage', () => {\n    it('should generate new ids (including bg)', () => {\n      const oldElements = [\n        { id: 'abc001', isBackground: true, x: 10, y: 20, type: 'shape' },\n        { id: 'abc002', x: 110, y: 120, type: 'text' },\n        { id: 'abc003', x: 210, y: 220, type: 'image' },\n      ];\n      const oldPage = {\n        id: 'abc000',\n        elements: oldElements,\n        backgroundColor: { color: { r: 255, g: 0, b: 0 } },\n      };\n      const newPage = duplicatePage(oldPage);\n\n      // Expect same structure but new id's!\n      expect(newPage).toStrictEqual({\n        id: expect.not.stringMatching(new RegExp(`/^${oldPage.id}$/`)),\n        animations: [],\n        backgroundColor: { color: { r: 255, g: 0, b: 0 } },\n        elements: [\n          expect.objectContaining({\n            id: expect.not.stringMatching(\n              new RegExp(`/^${oldElements[0].id}$/`)\n            ),\n            isBackground: true,\n            x: 10,\n            y: 20,\n            type: 'shape',\n          }),\n          expect.objectContaining({\n            id: expect.not.stringMatching(\n              new RegExp(`/^${oldElements[1].id}$/`)\n            ),\n            x: 110,\n            y: 120,\n            type: 'text',\n          }),\n          expect.objectContaining({\n            id: expect.not.stringMatching(\n              new RegExp(`/^${oldElements[2].id}$/`)\n            ),\n            x: 210,\n            y: 220,\n            type: 'image',\n          }),\n        ],\n      });\n    });\n\n    it('should update animation ids to new element ids', () => {\n      const oldElements = [\n        { id: 'a', isBackground: true, x: 10, y: 20, type: 'shape' },\n        { id: 'b', x: 110, y: 120, type: 'text' },\n        { id: 'c', x: 210, y: 220, type: 'image' },\n      ];\n      const oldAnimations = [\n        { id: 'anim_id', targets: ['a'], duration: 1000, type: 'ANIM_TYPE' },\n      ];\n      const oldPage = {\n        id: '1',\n        type: 'page',\n        elements: oldElements,\n        animations: oldAnimations,\n        otherProperty: '45',\n      };\n      const newPage = duplicatePage(oldPage);\n\n      // Expect same structure but new id's!\n      expect(newPage.animations).toStrictEqual([\n        {\n          ...oldAnimations[0],\n          id: expect.any(String),\n          targets: [newPage.elements[0].id],\n        },\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/text/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { PanelTypes } from '@googleforcreators/design-system';\nimport {\n  TEXT_ELEMENT_DEFAULT_FONT,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n  font: TEXT_ELEMENT_DEFAULT_FONT,\n  fontSize: 36,\n  backgroundColor: createSolid(196, 196, 196),\n  lineHeight: 1.3,\n  textAlign: 'initial',\n  padding: {\n    vertical: 0,\n    horizontal: 0,\n    locked: true,\n  },\n};\n\nexport const hasEditMode = true;\nexport const hasEditModeIfLocked = false;\nexport const hasEditModeMoveable = true;\nexport const editModeGrayout = false;\n\nexport const hasDesignMenu = true;\n\nexport const hasDuplicateMenu = true;\n\nexport const isMedia = false;\n\nexport const canFlip = false;\n\nexport const isMaskable = false;\n\nexport const isAspectAlwaysLocked = false;\n\nexport const resizeRules = {\n  vertical: false,\n  horizontal: true,\n  diagonal: true,\n  minWidth: 20,\n  minHeight: 0, // Enforced by min font size\n};\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  PanelTypes.SizePosition,\n  PanelTypes.TextStyle,\n  PanelTypes.TextAccessibility,\n  PanelTypes.Border,\n  PanelTypes.Link,\n  PanelTypes.Animation,\n];\n"
  },
  {
    "path": "packages/element-library/src/text/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { type DefaultTheme } from 'styled-components';\nimport { useEffect, useRef, useMemo } from '@googleforcreators/react';\nimport { createSolid, type Solid } from '@googleforcreators/patterns';\nimport { useUnits } from '@googleforcreators/units';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport {\n  getHTMLFormatters,\n  getHTMLInfo,\n  sanitizeEditorHtml,\n} from '@googleforcreators/rich-text';\nimport { stripHTML } from '@googleforcreators/dom';\nimport {\n  getResponsiveBorder,\n  shouldDisplayBorder,\n} from '@googleforcreators/masks';\nimport {\n  type TextElement,\n  type TextElementFont,\n  type Element,\n  BACKGROUND_TEXT_MODE,\n  type FontStyle,\n  type FontWeight,\n  type DisplayProps,\n} from '@googleforcreators/elements';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  elementFillContent,\n  elementWithFont,\n  elementWithBackgroundColor,\n  elementWithTextParagraphStyle,\n  elementWithBorder,\n  elementWithHighlightBorderRadius,\n  useColorTransformHandler,\n} from '../shared';\nimport {\n  getHighlightLineHeight,\n  generateParagraphTextStyle,\n  calcFontMetrics,\n  generateFontFamily,\n} from './util';\n\ninterface WrapperProps {\n  element: TextElement;\n  marginOffset: number;\n  backgroundColor?: Solid;\n  horizontalPadding: number;\n  verticalPadding: number;\n  whiteSpace: string;\n  overflowWrap: string;\n  wordBreak: string;\n  margin: string;\n  padding: string | number;\n  color?: string;\n  fontFamily: string;\n  fontSize: number;\n  font: TextElementFont;\n  fontStyle?: string;\n  fontWeight?: number;\n  lineHeight: number;\n  textAlign: 'left' | 'right' | 'center' | 'justify' | 'initial' | 'inherit';\n}\n\nconst OutsideBorder = styled.div`\n  ${elementWithBorder}\n`;\nconst HighlightWrapperElement = styled.div<WrapperProps>`\n  ${elementFillContent}\n  ${elementWithFont}\n  ${elementWithTextParagraphStyle}\n  line-height: ${({ lineHeight, verticalPadding }) =>\n    getHighlightLineHeight(lineHeight, verticalPadding)};\n  padding: 0;\n`;\nconst HighlightElement = styled.p<{ verticalPadding: number }>`\n  font-size: inherit;\n  line-height: inherit;\n  margin: 0;\n  position: absolute;\n  width: ${({ verticalPadding }) => `calc(100% - ${verticalPadding}px)`};\n`;\n\nconst MarginedElement = styled.span`\n  position: relative;\n  display: block;\n  top: 0;\n  left: 0;\n`;\n\nconst Span = styled.span<{\n  margin: number | string;\n  padding?: number | string;\n  lineHeight: number;\n  textAlign: 'left' | 'right' | 'center' | 'justify' | 'initial' | 'inherit';\n}>`\n  ${elementWithBackgroundColor}\n  ${elementWithTextParagraphStyle}\n\n  box-decoration-break: clone;\n  position: relative;\n`;\n\nconst BackgroundSpan = styled(Span)`\n  color: transparent;\n  ${elementWithHighlightBorderRadius}\n`;\n\nconst ForegroundSpan = styled(Span)`\n  background: none;\n`;\n\n// Using attributes to avoid creation of hundreds of classes by styled components for previewMode.\nconst FillElement = styled.p.attrs(\n  ({\n    theme,\n    previewMode,\n    fontStyle,\n    fontSize,\n    fontWeight,\n    font,\n    marginOffset,\n    padding,\n    lineHeight,\n    textAlign,\n    dataToEditorY,\n  }: WrapperProps & {\n    previewMode: boolean;\n    theme: DefaultTheme;\n    dataToEditorY: (prop: number) => string | number;\n  }) => {\n    return previewMode\n      ? {\n          style: {\n            zIndex: 1,\n            whiteSpace: 'pre-line',\n            wordBreak: 'break-word',\n            letterSpacing: 'normal',\n            color: theme.colors.standard.black,\n            fontStyle,\n            fontSize: `${fontSize}px`,\n            fontWeight,\n            fontFamily: generateFontFamily(font),\n            margin: `${dataToEditorY(-marginOffset / 2)} 0`,\n            padding: padding || 0,\n            lineHeight,\n            textAlign,\n          },\n        }\n      : {};\n  }\n)<WrapperProps & { previewMode: boolean }>`\n  margin: 0;\n  ${elementFillContent}\n  ${({ previewMode }) => !previewMode && elementWithFont}\n  ${({ previewMode }) => !previewMode && elementWithTextParagraphStyle}\n`;\n\nconst Background = styled.div<\n  Pick<Element, 'border' | 'borderRadius' | 'width' | 'height' | 'mask'> & {\n    backgroundColor?: Solid;\n  }\n>`\n  ${elementWithBackgroundColor}\n  ${elementFillContent}\n  ${elementWithBorder}\n  margin: 0;\n`;\n\nfunction TextDisplay({\n  element,\n  element: {\n    id,\n    content,\n    backgroundColor,\n    backgroundTextMode,\n    border,\n    borderRadius,\n    ...rest\n  },\n  previewMode,\n  maybeEnqueueFontStyle,\n}: DisplayProps<TextElement>) {\n  const ref = useRef<HTMLDivElement>(null);\n  const outerBorderRef = useRef<HTMLDivElement>(null);\n  const bgRef = useRef<HTMLSpanElement>(null);\n  const fgRef = useRef<HTMLElement>(null);\n\n  const { dataToEditorX, dataToEditorY } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n    dataToEditorY: state.actions.dataToEditorY,\n  }));\n\n  const { font, width: elementWidth, height: elementHeight } = rest;\n  const fontFaceSetConfigs = useMemo(() => {\n    const htmlInfo = getHTMLInfo(content);\n    return {\n      fontStyle: htmlInfo.isItalic ? 'italic' : ('normal' as FontStyle),\n      fontWeight: htmlInfo.fontWeight as FontWeight,\n      content: stripHTML(content),\n    };\n  }, [content]);\n\n  const { marginOffset } = calcFontMetrics(element);\n  const props = {\n    element,\n    marginOffset: dataToEditorY(marginOffset),\n    backgroundColor:\n      backgroundTextMode === BACKGROUND_TEXT_MODE.NONE\n        ? undefined\n        : backgroundColor,\n    ...generateParagraphTextStyle(\n      rest,\n      (x) => `${dataToEditorX(x)}px`,\n      (y) => `${dataToEditorY(y)}px`,\n      dataToEditorY,\n      element\n    ),\n    horizontalPadding: dataToEditorX(rest.padding?.horizontal || 0),\n    verticalPadding: dataToEditorX(rest.padding?.vertical || 0),\n  };\n  useEffect(() => {\n    void maybeEnqueueFontStyle([{ ...fontFaceSetConfigs, font }]);\n  }, [font, fontFaceSetConfigs, maybeEnqueueFontStyle]);\n\n  const isHighLight = backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT;\n  const refWithBorder = isHighLight ? outerBorderRef : bgRef;\n\n  useTransformHandler(id, (transform) => {\n    // Ref is set in case of high-light mode only, use the fgRef if that's missing.\n    const target = ref?.current || fgRef.current;\n    if (!target) {\n      return;\n    }\n    const updatedFontSize = transform?.updates?.fontSize as number;\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    target.style.fontSize = updatedFontSize\n      ? `${dataToEditorY(updatedFontSize)}px`\n      : '';\n    const updatedMargin = transform?.updates?.marginOffset as number;\n    target.style.margin = updatedMargin\n      ? `${dataToEditorY(-updatedMargin) / 2}px 0`\n      : '';\n\n    if (outerBorderRef.current || bgRef.current) {\n      // Depending on the background mode, choose the element that has border assigned to it.\n      if (transform) {\n        const { resize } = transform;\n        if (resize && resize[0] !== 0 && resize[1] !== 0) {\n          const [width, height] = resize;\n          if (shouldDisplayBorder(element) && refWithBorder.current) {\n            refWithBorder.current.style.width =\n              width + (border?.left || 0) + (border?.right || 0) + 'px';\n            refWithBorder.current.style.height =\n              height + (border?.top || 0) + (border?.bottom || 0) + 'px';\n          }\n        }\n      }\n    }\n  });\n\n  useColorTransformHandler({\n    id,\n    targetRef: bgRef,\n    expectedStyle: 'background',\n  });\n  useColorTransformHandler({\n    id,\n    targetRef: refWithBorder,\n    expectedStyle: 'border-color',\n  });\n\n  // Setting the text color of the entire block to black essentially removes all inline\n  // color styling allowing us to apply transparent to all of them.\n  const contentWithoutColor = useMemo(\n    () => getHTMLFormatters().setColor(content, createSolid(0, 0, 0)),\n    [content]\n  );\n\n  if (isHighLight) {\n    // We need a separate outside border wrapper for outside border\n    // since the highlight wrapper uses negative margin to position the content.\n    // This, however, would shift the border incorrectly.\n    return (\n      <OutsideBorder\n        ref={outerBorderRef}\n        border={getResponsiveBorder(border, previewMode, dataToEditorX)}\n        borderRadius={borderRadius}\n        width={elementWidth}\n        height={elementHeight}\n      >\n        <HighlightWrapperElement ref={ref} {...props}>\n          <HighlightElement {...props}>\n            <MarginedElement {...props}>\n              <BackgroundSpan\n                ref={bgRef}\n                {...props}\n                borderRadius={borderRadius}\n                dataToEditorY={dataToEditorY}\n                dangerouslySetInnerHTML={{\n                  __html: sanitizeEditorHtml(contentWithoutColor),\n                }}\n              />\n            </MarginedElement>\n          </HighlightElement>\n          <HighlightElement {...props}>\n            <MarginedElement {...props}>\n              <ForegroundSpan\n                ref={fgRef}\n                {...props}\n                dangerouslySetInnerHTML={{\n                  __html: sanitizeEditorHtml(content),\n                }}\n              />\n            </MarginedElement>\n          </HighlightElement>\n        </HighlightWrapperElement>\n      </OutsideBorder>\n    );\n  }\n\n  return (\n    <Background\n      ref={bgRef as RefObject<HTMLDivElement>}\n      backgroundColor={\n        backgroundTextMode === BACKGROUND_TEXT_MODE.FILL\n          ? backgroundColor\n          : undefined\n      }\n      borderRadius={borderRadius}\n      border={getResponsiveBorder(border, previewMode, dataToEditorX)}\n      width={elementWidth}\n      height={elementHeight}\n    >\n      <FillElement\n        ref={fgRef as RefObject<HTMLParagraphElement>}\n        dangerouslySetInnerHTML={{\n          __html: sanitizeEditorHtml(content),\n        }}\n        previewMode={previewMode}\n        {...props}\n      />\n    </Background>\n  );\n}\nexport default TextDisplay;\n"
  },
  {
    "path": "packages/element-library/src/text/edit.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useCallback,\n  useMemo,\n  useUnmount,\n} from '@googleforcreators/react';\nimport { generatePatternStyles, type Solid } from '@googleforcreators/patterns';\nimport {\n  useUnits,\n  calcRotatedResizeOffset,\n  type ElementBox,\n} from '@googleforcreators/units';\nimport {\n  useTransformHandler,\n  useTransform,\n} from '@googleforcreators/transform';\nimport {\n  RichTextEditor,\n  getHTMLInfo,\n  useRichText,\n} from '@googleforcreators/rich-text';\nimport { stripHTML } from '@googleforcreators/dom';\nimport { shouldDisplayBorder } from '@googleforcreators/masks';\nimport {\n  BACKGROUND_TEXT_MODE,\n  type Border,\n  type FontFamily,\n  type FontStyle,\n  type FontWeight,\n  type TextElement,\n  type TextElementFont,\n  type EditProps,\n} from '@googleforcreators/elements';\nimport type { MouseEventHandler } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  elementFillContent,\n  elementWithFont,\n  elementWithTextParagraphStyle,\n  elementWithBackgroundColor,\n  elementWithBorder,\n  elementWithHighlightBorderRadius,\n} from '../shared';\nimport useCSSVarColorTransformHandler from '../shared/useCSSVarColorTransformHandler';\nimport useColorTransformHandler from '../shared/useColorTransformHandler';\nimport {\n  calcFontMetrics,\n  generateParagraphTextStyle,\n  getHighlightLineHeight,\n} from './util';\n\ninterface WrapperProps {\n  element: TextElement;\n  backgroundColor: Solid | null;\n  verticalPadding: number;\n  whiteSpace?: string;\n  overflowWrap?: string;\n  wordBreak?: string;\n  margin?: string;\n  fontFamily?: FontFamily;\n  fontSize: number;\n  font: TextElementFont;\n  lineHeight?: number | string;\n  textAlign?: string;\n  padding?: number | string;\n  opacity?: number;\n  highlightColor?: Solid;\n}\n\n// Wrapper bounds the text editor within the element bounds. The resize\n// logic updates the height of this element to show the new height based\n// on the content and properties.\nconst Wrapper = styled.div`\n  ${elementFillContent}\n  ${elementWithBackgroundColor}\n  --faux-selection-color: inherit;\n  span {\n    box-decoration-break: clone;\n  }\n`;\n\n// TextBox defines all text display properties and is used for measuring\n// of text height. This element has an unbounded height (bottom) so that\n// it can be used for height measurement.\nconst TextBox = styled.div<WrapperProps>`\n  ${elementWithFont}\n  ${elementWithTextParagraphStyle}\n  opacity: ${({ opacity }) =>\n    typeof opacity !== 'undefined' ? opacity / 100 : null};\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n`;\n\nconst TextBoxPadded = styled(TextBox)<{ verticalPadding: number }>(\n  ({ verticalPadding }) => ({\n    width: `calc(100% - ${verticalPadding}px)`,\n  })\n);\n\nconst EditTextBox = styled(TextBox)<{\n  $hasHighlightBackgroundTextMode: boolean;\n}>(\n  ({ $hasHighlightBackgroundTextMode }) =>\n    $hasHighlightBackgroundTextMode && {\n      paddingTop: 0,\n      paddingBottom: 0,\n    }\n);\n\nconst Highlight = styled.span<\n  WrapperProps & { dataToEditorY: (prop: number) => string | number }\n>`\n  ${elementWithHighlightBorderRadius}\n  ${({ highlightColor }) => generatePatternStyles(highlightColor)};\n  color: transparent !important;\n  * {\n    color: transparent !important;\n  }\n  padding: ${({ padding }) => padding};\n  width: ${({ verticalPadding }) => `calc(100% - ${verticalPadding}px)`};\n`;\n\nconst OutsideBorder = styled.div`\n  overflow: hidden;\n  ${elementWithBorder}\n`;\n\nfunction TextEdit({\n  element,\n  box: { x, y, width, height, rotationAngle },\n  editWrapper,\n  onResize,\n  updateElementById,\n  deleteSelectedElements,\n  maybeEnqueueFontStyle,\n}: EditProps<TextElement>) {\n  const {\n    id,\n    content,\n    backgroundColor,\n    backgroundTextMode,\n    border = {},\n    borderRadius,\n    opacity,\n    height: elementHeight,\n    ...rest\n  } = element;\n  const { font } = rest;\n  const { top = 0, bottom = 0, left = 0, right = 0 } = (border || {}) as Border;\n  const fontFaceSetConfigs = useMemo(() => {\n    const htmlInfo = getHTMLInfo(content);\n    return {\n      fontStyle: htmlInfo.isItalic ? 'italic' : ('normal' as FontStyle),\n      fontWeight: htmlInfo.fontWeight as FontWeight,\n      content: stripHTML(content),\n    };\n  }, [content]);\n\n  const { dataToEditorX, dataToEditorY, editorToDataX, editorToDataY } =\n    useUnits(\n      ({\n        actions: { dataToEditorX, dataToEditorY, editorToDataX, editorToDataY },\n      }) => ({\n        dataToEditorX,\n        dataToEditorY,\n        editorToDataX,\n        editorToDataY,\n      })\n    );\n\n  const textProps = {\n    ...generateParagraphTextStyle(\n      rest,\n      (styleX) => `${dataToEditorX(styleX)}px`,\n      (styleY) => `${dataToEditorY(styleY)}px`,\n      dataToEditorY,\n      element\n    ),\n    font,\n    element,\n    backgroundColor,\n    opacity,\n    verticalPadding: dataToEditorX(rest.padding?.vertical || 0),\n    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT && {\n      lineHeight: getHighlightLineHeight(\n        rest.lineHeight,\n        dataToEditorX(rest.padding?.vertical || 0)\n      ),\n      backgroundColor: null,\n      highlightColor: backgroundColor,\n    }),\n    ...(backgroundTextMode === BACKGROUND_TEXT_MODE.NONE && {\n      backgroundColor: null,\n    }),\n  };\n\n  const { padding: _, ...highlightTextProps } = textProps;\n\n  const { isAnythingTransforming } = useTransform((state) => ({\n    isAnythingTransforming: state.state.isAnythingTransforming,\n  }));\n\n  const setProperties = useCallback(\n    (properties: Partial<TextElement>) =>\n      updateElementById({ elementId: id, properties }),\n    [id, updateElementById]\n  );\n\n  const wrapperRef = useRef<HTMLDivElement>(null);\n  const highlightRef = useRef<HTMLDivElement>(null);\n  const highlightBgRef = useRef<HTMLDivElement>(null);\n  const textBoxRef = useRef<HTMLDivElement>(null);\n  const editorRef = useRef<HTMLDivElement>(null);\n  const boxRef =\n    useRef<Pick<ElementBox, 'x' | 'y' | 'height' | 'rotationAngle'>>();\n  const contentRef = useRef<string | null>();\n  const editorHeightRef = useRef<number>(0);\n  const outsideBorderRef = useRef<HTMLDivElement>(null);\n\n  // x, y, height, rotationAngle changes should not update the content while in edit mode.\n  // updateContent should be only called on unmount.\n  useEffect(() => {\n    boxRef.current = { x, y, height, rotationAngle };\n  }, [x, y, height, rotationAngle]);\n\n  // Make sure to allow the user to click in the text box while working on the text.\n  const onClick: MouseEventHandler<HTMLDivElement> = (evt) => {\n    const editor = editorRef.current;\n    editor?.focus();\n    evt.stopPropagation();\n  };\n\n  // Set focus when initially rendered.\n  useLayoutEffect(() => {\n    if (editorRef.current) {\n      editorRef.current.focus();\n    }\n  }, []);\n\n  const updateContent = useCallback(() => {\n    const newHeight = editorHeightRef.current;\n    if (wrapperRef.current) {\n      wrapperRef.current.style.height = '';\n    }\n    if (contentRef.current) {\n      // Remove manual line breaks and remember to trim any trailing non-breaking space.\n      const properties: Partial<TextElement> = { content: contentRef.current };\n      // Recalculate the new height and offset.\n      // boxRef includes adjustment for the border, let's take the border values out for element updating.\n      if (newHeight) {\n        properties.height = editorToDataY(newHeight);\n        if (boxRef.current) {\n          const [dx, dy] = calcRotatedResizeOffset(\n            boxRef.current.rotationAngle,\n            -left,\n            -right,\n            -top,\n            Math.round(newHeight - (boxRef.current.height - top))\n          );\n          properties.x = editorToDataX(boxRef.current.x + dx);\n          properties.y = editorToDataY(boxRef.current.y + dy);\n        }\n      }\n      setProperties(properties);\n    }\n  }, [editorToDataX, editorToDataY, setProperties, top, left, right]);\n\n  // Update content or delete the whole element (if empty) on unmount.\n  const handleUnmount = useCallback(() => {\n    if (contentRef.current) {\n      updateContent();\n    } else {\n      deleteSelectedElements();\n    }\n  }, [updateContent, deleteSelectedElements]);\n  useUnmount(handleUnmount);\n\n  useEffect(() => {\n    // If there are any moveable actions happening, let's update the content\n    // Otherwise the font size and measures will not be correct.\n    if (isAnythingTransforming) {\n      updateContent();\n    }\n  }, [isAnythingTransforming, updateContent]);\n\n  // A function to remeasure height\n  const handleResize = useCallback(() => {\n    const wrapper = wrapperRef.current;\n    const textBox = textBoxRef.current;\n    const { marginOffset } = calcFontMetrics(element);\n    if (wrapper) {\n      wrapper.style.height = `${editorHeightRef.current}px`;\n    }\n    if (textBox) {\n      editorHeightRef.current =\n        textBox.offsetHeight - dataToEditorY(marginOffset);\n      textBox.style.margin = '';\n    }\n    if (editWrapper) {\n      if (boxRef.current) {\n        // We need to consider the potential border, too, and remove/add it to the content height.\n        const [dx, dy] = calcRotatedResizeOffset(\n          boxRef.current.rotationAngle,\n          0,\n          0,\n          0,\n          editorHeightRef.current - (boxRef.current.height - top - bottom)\n        );\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        editWrapper.style.height = `${editorHeightRef.current + top + bottom}px`;\n        editWrapper.style.left = `${boxRef.current.x + dx}px`;\n        editWrapper.style.top = `${boxRef.current.y + dy}px`;\n      }\n      if (onResize) {\n        onResize();\n      }\n    }\n  }, [dataToEditorY, editWrapper, element, onResize, top, bottom]);\n  // Invoke on each content update.\n  const handleUpdate = useCallback(\n    (newContent: string | null) => {\n      contentRef.current = newContent;\n      handleResize();\n    },\n    [handleResize]\n  );\n  // Also invoke if the raw element height ever changes\n  useEffect(handleResize, [elementHeight, handleResize]);\n\n  useEffect(() => {\n    void maybeEnqueueFontStyle([\n      {\n        ...fontFaceSetConfigs,\n        font,\n      },\n    ]);\n  }, [font, fontFaceSetConfigs, maybeEnqueueFontStyle]);\n\n  useTransformHandler(id, (transform) => {\n    const target = textBoxRef.current;\n    const wrapper = wrapperRef.current;\n    const highlight = highlightRef.current;\n    const updatedFontSize = transform?.updates?.fontSize as number;\n    if (target) {\n      target.style.fontSize = updatedFontSize\n        ? `${dataToEditorY(updatedFontSize)}px`\n        : '';\n    }\n    if (highlight) {\n      const updatedMargin = transform?.updates?.marginOffset as number;\n      highlight.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;\n      if (target) {\n        highlight.style.fontSize = target.style.fontSize;\n        target.style.margin = `${dataToEditorY(-updatedMargin) / 2}px 0`;\n      }\n    }\n\n    if (wrapper) {\n      if (transform === null) {\n        wrapper.style.width = '';\n        wrapper.style.height = '';\n      } else {\n        const { resize } = transform;\n        if (resize && resize[0] !== 0 && resize[1] !== 0) {\n          wrapper.style.width = `${resize[0]}px`;\n          wrapper.style.height = `${resize[1]}px`;\n        }\n      }\n    }\n  });\n\n  const hasHighlightBackgroundTextMode =\n    backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT;\n\n  // For instant color change on selection.\n  useCSSVarColorTransformHandler({\n    id,\n    targetRef: wrapperRef,\n    cssVar: '--faux-selection-color',\n    expectedStyle: 'color',\n  });\n\n  const backgroundRef = hasHighlightBackgroundTextMode\n    ? highlightBgRef\n    : wrapperRef;\n  useColorTransformHandler({\n    id,\n    targetRef: backgroundRef,\n    expectedStyle: 'background',\n  });\n\n  // Inner and center color are handled separately, add transform for outside border if relevant.\n  useColorTransformHandler({\n    id,\n    targetRef: shouldDisplayBorder(element) ? outsideBorderRef : null,\n    expectedStyle: 'border-color',\n  });\n\n  const {\n    state: { editorState },\n    actions: { getContentFromState },\n  } = useRichText();\n\n  const editorContent = editorState && getContentFromState(editorState);\n  const wrapperBackgroundColor =\n    backgroundTextMode === BACKGROUND_TEXT_MODE.FILL && backgroundColor;\n\n  const wrapperProps = {\n    $backgroundColor: wrapperBackgroundColor,\n  };\n\n  return (\n    <OutsideBorder\n      ref={outsideBorderRef}\n      border={border as Border}\n      borderRadius={borderRadius}\n      width={width}\n      height={height}\n    >\n      {/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions -- Needed here to ensure the editor keeps focus, e.g. after setting inline colour. */}\n      <Wrapper\n        ref={wrapperRef}\n        onClick={onClick}\n        data-testid=\"textEditor\"\n        {...wrapperProps}\n      >\n        {editorContent && hasHighlightBackgroundTextMode && (\n          <TextBoxPadded ref={highlightRef} {...highlightTextProps}>\n            <Highlight\n              ref={highlightBgRef}\n              dangerouslySetInnerHTML={{ __html: editorContent }}\n              {...textProps}\n            />\n          </TextBoxPadded>\n        )}\n        <EditTextBox\n          $hasHighlightBackgroundTextMode={hasHighlightBackgroundTextMode}\n          className=\"syncMargin\"\n          ref={textBoxRef}\n          {...textProps}\n        >\n          <RichTextEditor\n            ref={editorRef}\n            content={content}\n            onChange={handleUpdate}\n          />\n        </EditTextBox>\n      </Wrapper>\n    </OutsideBorder>\n  );\n}\n\nexport default TextEdit;\n"
  },
  {
    "path": "packages/element-library/src/text/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useRef, useEffect } from '@googleforcreators/react';\nimport { useUnits } from '@googleforcreators/units';\nimport { areEventsDragging } from '@googleforcreators/moveable';\nimport type {\n  TextElement,\n  TextElementFont,\n  FrameProps,\n} from '@googleforcreators/elements';\nimport {\n  getCaretCharacterOffsetWithin,\n  sanitizeEditorHtml,\n} from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport {\n  elementFillContent,\n  elementWithFont,\n  elementWithTextParagraphStyle,\n} from '../shared';\nimport { generateParagraphTextStyle } from './util';\n\nconst Element = styled.p<{\n  font: TextElementFont;\n  fontSize: string | number;\n  fontWeight?: string | number;\n  margin: number | string;\n  padding?: number | string;\n  lineHeight: number;\n  textAlign: string;\n}>`\n  ${elementFillContent}\n  ${elementWithFont}\n  ${elementWithTextParagraphStyle}\n\n  opacity: 0;\n  user-select: none;\n`;\n\nfunction TextFrame({\n  element,\n  element: { id, content, isLocked, ...rest },\n  wrapperRef,\n  setEditingElementWithState,\n  isOnlySelectedElement,\n}: FrameProps<TextElement>) {\n  const { dataToEditorX, dataToEditorY } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n    dataToEditorY: state.actions.dataToEditorY,\n  }));\n  const props = generateParagraphTextStyle(\n    rest,\n    (x) => `${dataToEditorX(x)}px`,\n    (y) => `${dataToEditorY(y)}px`,\n    dataToEditorY,\n    element\n  );\n\n  const elementRef = useRef<HTMLParagraphElement>(null);\n\n  useEffect(() => {\n    if (!isOnlySelectedElement) {\n      return undefined;\n    }\n\n    const wrapper = wrapperRef.current;\n    const elementNode = elementRef.current;\n\n    let clickTime = 0;\n    let clickCoordinates: { clientX: number; clientY: number } | null = null;\n\n    const handleKeyDown = (evt: KeyboardEvent) => {\n      if (evt.metaKey || evt.altKey || evt.ctrlKey || isLocked) {\n        // Some modifier (except shift) was pressed. Ignore and bubble\n        return;\n      }\n\n      if (evt.key === 'Enter' || /^\\w$/.test(evt.key)) {\n        // TODO: in above check all printable characters across alphabets, no just a-z0-9 as \\w regex is\n        // Enter on editing mode. When inserting content, first letter will be correctly inserted from keyup\n        setEditingElementWithState(id, { selectAll: true });\n        evt.stopPropagation();\n        // Make sure no actual Enter is pressed\n        if (evt.key === 'Enter') {\n          evt.preventDefault();\n        }\n      }\n    };\n\n    const handleMouseDown = (evt: MouseEvent) => {\n      clickTime = evt.timeStamp;\n      clickCoordinates = {\n        clientX: evt.clientX,\n        clientY: evt.clientY,\n      };\n    };\n\n    const handleMouseUp = (evt: MouseEvent) => {\n      if (\n        isLocked ||\n        !clickCoordinates ||\n        areEventsDragging(\n          {\n            timeStamp: clickTime,\n            ...clickCoordinates,\n          } as MouseEvent,\n          evt\n        )\n      ) {\n        // Abort early as this is part of a user dragging\n        return;\n      }\n\n      // Enter editing mode and place cursor at current selection offset\n      evt.stopPropagation();\n      setEditingElementWithState(id, {\n        offset: elementRef.current\n          ? getCaretCharacterOffsetWithin(\n              elementRef.current,\n              evt.clientX,\n              evt.clientY\n            )\n          : 0,\n      });\n    };\n\n    wrapper?.addEventListener('keydown', handleKeyDown);\n    elementNode?.addEventListener('mousedown', handleMouseDown);\n    elementNode?.addEventListener('mouseup', handleMouseUp);\n    return () => {\n      wrapper?.removeEventListener('keydown', handleKeyDown);\n      elementNode?.removeEventListener('mousedown', handleMouseDown);\n      elementNode?.removeEventListener('mouseup', handleMouseUp);\n    };\n  }, [\n    id,\n    wrapperRef,\n    isOnlySelectedElement,\n    setEditingElementWithState,\n    isLocked,\n  ]);\n\n  return (\n    <Element\n      ref={elementRef}\n      data-testid=\"textFrame\"\n      // data-fix-caret is for allowing caretRangeFromPoint to work in Safari.\n      // See https://github.com/googleforcreators/web-stories-wp/issues/7745.\n      data-fix-caret\n      className=\"syncMargin\"\n      dangerouslySetInnerHTML={{ __html: sanitizeEditorHtml(content) }}\n      {...props}\n    />\n  );\n}\n\nexport default TextFrame;\n"
  },
  {
    "path": "packages/element-library/src/text/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\nconst IconContainer = styled.div`\n  height: 21px;\n  width: 21px;\n  overflow: hidden;\n`;\n\nfunction TextIcon() {\n  return (\n    <IconContainer>\n      <Icons.LetterT height={21} width={21} />\n    </IconContainer>\n  );\n}\n\nexport default TextIcon;\n"
  },
  {
    "path": "packages/element-library/src/text/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Display } from './display';\nexport { default as Edit } from './edit';\nexport { default as Frame } from './frame';\nexport { default as Output } from './output';\nexport { default as TextContent } from './textContent';\nexport { default as getLayerText } from './layer';\nexport { default as LayerIcon } from './icon';\nexport { default as updateForResizeEvent } from './updateForResizeEvent';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/text/layer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { stripHTML } from '@googleforcreators/dom';\nimport type { TextElement } from '@googleforcreators/elements';\n\nfunction getTextLayerText({ content }: TextElement) {\n  return stripHTML(content);\n}\n\nexport default getTextLayerText;\n"
  },
  {
    "path": "packages/element-library/src/text/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  dataToEditorX,\n  dataToEditorY,\n  dataToFontSizeY as dataToFontSize,\n} from '@googleforcreators/units';\nimport type { TextElement, OutputProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\n\nimport TextOutputWithUnits from './outputWithUnits';\n\n/**\n * Returns AMP HTML for saving into post content for displaying in the FE.\n *\n * @param props Props.\n * @return Rendered component.\n */\nfunction TextOutput({ element }: OutputProps<TextElement>) {\n  const { width } = element;\n  return (\n    <TextOutputWithUnits\n      element={element}\n      className=\"fill\"\n      dataToStyleX={(x) => `${dataToEditorX(x, 100)}%`}\n      dataToStyleY={(y) => `${dataToEditorY(y, 100)}%`}\n      dataToFontSizeY={(y) => `${dataToFontSize(y, 100)}em`}\n      // Both vertical and horizontal paddings are calculated in % relative to\n      // the box's width per CSS rules.\n      dataToPaddingX={(x) => `${(x / width) * 100}%`}\n      dataToPaddingY={(y) => `${(y / width) * 100}%`}\n    />\n  );\n}\n\nexport default TextOutput;\n"
  },
  {
    "path": "packages/element-library/src/text/outputWithUnits.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\nimport {\n  createSolid,\n  generatePatternStyles,\n} from '@googleforcreators/patterns';\nimport { useMemo } from '@googleforcreators/react';\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\nimport classnames from 'classnames';\nimport type { TextElement } from '@googleforcreators/elements';\nimport type { CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport {\n  generateParagraphTextStyle,\n  getHighlightLineHeight,\n  calcFontMetrics,\n} from './util';\n\ntype DataToStyle = (prop: number) => string;\ninterface TextOutputWithUnitsProps {\n  element: TextElement;\n  dataToStyleX: DataToStyle;\n  dataToStyleY: DataToStyle;\n  dataToFontSizeY?: DataToStyle;\n  dataToPaddingX?: DataToStyle;\n  dataToPaddingY?: DataToStyle;\n  className?: string;\n}\n\n/**\n * Renders DOM for the text output based on the provided unit converters.\n */\nfunction TextOutputWithUnits({\n  element,\n  dataToStyleX,\n  dataToStyleY,\n  dataToFontSizeY,\n  dataToPaddingX,\n  dataToPaddingY,\n  className,\n}: TextOutputWithUnitsProps) {\n  const {\n    content: rawContent,\n    backgroundColor,\n    backgroundTextMode,\n    padding,\n    borderRadius,\n    ...rest\n  } = element;\n\n  // It can never be 'auto' here thanks to getTextElementTagNames(),\n  // but this makes TypeScript happy.\n  const TagName =\n    element.tagName && element.tagName !== 'auto' ? element.tagName : 'p';\n\n  if (!dataToFontSizeY) {\n    dataToFontSizeY = dataToStyleY;\n  }\n  if (!dataToPaddingX) {\n    dataToPaddingX = dataToStyleX;\n  }\n  if (!dataToPaddingY) {\n    dataToPaddingY = dataToStyleY;\n  }\n  const paddingStyles = {\n    vertical: padding?.vertical ? dataToPaddingY(padding.vertical) : 0,\n    horizontal: padding?.horizontal ? dataToPaddingX(padding.horizontal) : 0,\n  };\n\n  const hasPadding = paddingStyles.vertical || paddingStyles.horizontal;\n  const paddingStyle = hasPadding\n    ? `${paddingStyles.vertical} ${paddingStyles.horizontal}`\n    : 0;\n\n  const bgColor =\n    backgroundTextMode !== BACKGROUND_TEXT_MODE.NONE\n      ? generatePatternStyles(backgroundColor)\n      : undefined;\n\n  const {\n    dataToEditorY: _dataToEditorY,\n    font: _font,\n    ...styles\n  } = generateParagraphTextStyle(\n    rest,\n    dataToStyleX,\n    dataToStyleY,\n    dataToFontSizeY,\n    element,\n    dataToPaddingY\n  );\n  const fillStyle = {\n    ...styles,\n    color: '#000000',\n    // Overrides styles.padding.\n    padding: paddingStyle,\n  };\n\n  const unitlessPaddingVertical = padding?.vertical\n    ? Number.parseFloat(dataToStyleY(padding.vertical))\n    : 0;\n  const unitlessFontSize = Number.parseFloat(dataToStyleY(rest.fontSize));\n\n  const lineHeight = getHighlightLineHeight(\n    rest.lineHeight,\n    unitlessPaddingVertical / unitlessFontSize,\n    'em'\n  );\n\n  const highlightStyle = {\n    ...fillStyle,\n    ...bgColor,\n    margin: 0,\n    padding: 0,\n    background: 'none',\n    lineHeight,\n    overflowWrap: 'break-word',\n  } as CSSProperties;\n\n  const highlightCloneStyle = {\n    ...highlightStyle,\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    right: 0,\n  } as CSSProperties;\n\n  const marginStyle = (el: TextElement): CSSProperties => {\n    const { marginOffset } = calcFontMetrics(el);\n    return {\n      display: 'block',\n      position: 'relative',\n      left: 0,\n      top: '0',\n      margin: `${dataToPaddingY ? dataToPaddingY(-marginOffset / 2) : 0} 0`,\n      /* stylelint-disable-next-line */\n      WebkitBoxDecorationBreak: 'clone',\n      boxDecorationBreak: 'clone',\n    };\n  };\n\n  const textStyle = {\n    ...bgColor,\n    /* stylelint-disable-next-line */\n    WebkitBoxDecorationBreak: 'clone',\n    boxDecorationBreak: 'clone',\n    position: 'relative',\n    padding: paddingStyle,\n    textAlign: styles.textAlign,\n    borderRadius: `${borderRadius?.topLeft || 0}px ${\n      borderRadius?.topRight || 0\n    }px ${borderRadius?.bottomRight || 0}px ${borderRadius?.bottomLeft || 0}px`,\n  } as CSSProperties;\n\n  const backgroundTextStyle = {\n    ...textStyle,\n    color: 'transparent',\n  };\n\n  const foregroundTextStyle = {\n    ...textStyle,\n    background: 'none',\n  };\n\n  const content = rawContent.replace(/\\n$/, '\\n\\n');\n\n  // Setting the text color of the entire block to black essentially removes all inline\n  // color styling allowing us to apply transparent to all of them.\n  const contentWithoutColor = useMemo(\n    () => getHTMLFormatters().setColor(content, createSolid(0, 0, 0)),\n    [content]\n  );\n\n  className = classnames(className, 'text-wrapper');\n  if (backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT) {\n    return (\n      <>\n        <TagName className={className} style={highlightStyle}>\n          <span style={marginStyle(element)}>\n            <span\n              style={backgroundTextStyle}\n              dangerouslySetInnerHTML={{\n                __html: contentWithoutColor,\n              }}\n            />\n          </span>\n        </TagName>\n        <TagName\n          className={className}\n          style={highlightCloneStyle}\n          aria-hidden=\"true\"\n        >\n          <span style={marginStyle(element)}>\n            <span\n              style={foregroundTextStyle}\n              dangerouslySetInnerHTML={{\n                __html: content,\n              }}\n            />\n          </span>\n        </TagName>\n      </>\n    );\n  }\n  return (\n    <TagName className={className} style={fillStyle as CSSProperties}>\n      <span dangerouslySetInnerHTML={{ __html: content }} />\n    </TagName>\n  );\n}\n\nexport default TextOutputWithUnits;\n"
  },
  {
    "path": "packages/element-library/src/text/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport TextOutput from '../output';\n\nfunction renderViaString(...args) {\n  // Render an element via string to test that Output templates do not use\n  // forbidden dependencies.\n  const html = renderToStaticMarkup(...args);\n  const div = document.createElement('div');\n  div.innerHTML = html;\n  return div.firstElementChild;\n}\n\ndescribe('TextOutput', () => {\n  it('should return HTML Output based on the params', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      backgroundColor: {\n        color: {\n          r: 255,\n          g: 0,\n          b: 0,\n          a: 0.3,\n        },\n      },\n      font: {\n        family: 'Roboto',\n        metrics: {\n          upm: 2048,\n          asc: 1900,\n          des: -500,\n          tAsc: 1536,\n          tDes: -512,\n          tLGap: 102,\n          wAsc: 1946,\n          wDes: 512,\n          xH: 1082,\n          capH: 1456,\n          yMin: -555,\n          yMax: 2163,\n          hAsc: 1900,\n          hDes: -500,\n          lGap: 0,\n        },\n      },\n      fontSize: 16,\n      textAlign: 'left',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 50,\n      rotationAngle: 0,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n      box: { width: 1080 },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 }}\n      />\n    );\n    expect(output.tagName).toBe('P');\n    expect(output.innerHTML).toBe('<span>Content</span>');\n    expect(output).toHaveClass('fill text-wrapper', { exact: true });\n    expect(output).toHaveStyle({\n      whiteSpace: 'pre-line',\n      padding: '0px',\n      fontSize: '0.258900em',\n      textAlign: 'left',\n    });\n  });\n\n  it('should convert padding to percent of width', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 16,\n      textAlign: 'left',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 100,\n      rotationAngle: 0,\n      padding: {\n        vertical: 10,\n        horizontal: 10,\n      },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 }}\n      />\n    );\n    expect(output.tagName).toBe('P');\n    expect(output.innerHTML).toBe('<span>Content</span>');\n    expect(output).toHaveClass('fill text-wrapper', { exact: true });\n    expect(output).toHaveStyle('padding: 20% 20%');\n  });\n\n  it('should convert one-sided padding', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 16,\n      textAlign: 'left',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 100,\n      rotationAngle: 0,\n      padding: {\n        vertical: 10,\n        horizontal: 0,\n      },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 }}\n      />\n    );\n    expect(output.tagName).toBe('P');\n    expect(output.innerHTML).toBe('<span>Content</span>');\n    expect(output).toHaveClass('fill text-wrapper', { exact: true });\n    expect(output).toHaveStyle('padding: 20% 0px');\n  });\n\n  it('should default to zero padding if not a number', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 16,\n      textAlign: 'left',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 100,\n      rotationAngle: 0,\n      padding: {\n        vertical: Number.NaN,\n        horizontal: null,\n      },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 }}\n      />\n    );\n    expect(output.tagName).toBe('P');\n    expect(output.innerHTML).toBe('<span>Content</span>');\n    expect(output).toHaveClass('fill text-wrapper', { exact: true });\n    expect(output).toHaveStyle('padding: 0');\n  });\n\n  it('should wrap font-family into quotes', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 50,\n      font: {\n        family: 'Baloo Bhaina 2',\n      },\n      fontSize: 16,\n      rotationAngle: 0,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 50, height: 50, x: 10, y: 10, rotationAngle: 0 }}\n      />\n    );\n    expect(output).toHaveStyle({\n      fontFamily: '\"Baloo Bhaina 2\"',\n    });\n  });\n\n  it('should display correct font fallback', () => {\n    const element = {\n      id: '123',\n      content: 'Content',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 50,\n      font: {\n        family: 'Baloo Bhaina 2',\n        fallbacks: ['Roboto', 'cursive'],\n      },\n      fontSize: 16,\n      rotationAngle: 0,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n    };\n\n    const output = renderViaString(\n      <TextOutput\n        element={element}\n        box={{ width: 50, height: 50, x: 10, y: 10, rotationAngle: 0 }}\n      />\n    );\n    expect(output).toHaveStyle({\n      fontFamily: '\"Baloo Bhaina 2\",\"Roboto\",cursive',\n    });\n  });\n  it('should not have overflow: hidden style applied', () => {\n    const props = {\n      element: {\n        type: 'text',\n        id: '123',\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        content: 'Look Mom! No hands!',\n        color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n        padding: {\n          horizontal: 0,\n          vertical: 0,\n        },\n        font: {\n          family: 'Roboto',\n        },\n      },\n      box: { width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 },\n    };\n\n    const output = renderViaString(<TextOutput {...props} />);\n    expect(output).not.toHaveStyle({\n      overflow: 'hidden',\n    });\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output', async () => {\n      const props = {\n        element: {\n          type: 'text',\n          id: '123',\n          x: 50,\n          y: 100,\n          height: 1920,\n          width: 1080,\n          rotationAngle: 0,\n          content: 'Hello World',\n          color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n          padding: {\n            horizontal: 0,\n            vertical: 0,\n          },\n          font: {\n            family: 'Roboto',\n          },\n        },\n        box: { width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 },\n      };\n\n      await expect(<TextOutput {...props} />).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/text/test/util.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  dataToEditorX,\n  dataToEditorY,\n  dataToFontSizeY as dataToFontSize,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport {\n  generateFontFamily,\n  getHighlightLineHeight,\n  generateParagraphTextStyle,\n} from '../util';\n\nconst TEXT_ELEMENT = {\n  opacity: 100,\n  flip: {\n    vertical: false,\n    horizontal: false,\n  },\n  rotationAngle: 0,\n  lockAspectRatio: true,\n  backgroundTextMode: 'NONE',\n  font: {\n    family: 'Roboto',\n    weights: [100, 300, 400, 500, 700, 900],\n    styles: ['italic', 'regular'],\n    variants: [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900],\n    ],\n    fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n    service: 'fonts.google.com',\n    metrics: {\n      upm: 2048,\n      asc: 1900,\n      des: -500,\n      tAsc: 1536,\n      tDes: -512,\n      tLGap: 102,\n      wAsc: 1946,\n      wDes: 512,\n      xH: 1082,\n      capH: 1456,\n      yMin: -555,\n      yMax: 2163,\n      hAsc: 1900,\n      hDes: -500,\n      lGap: 0,\n    },\n  },\n  fontSize: 18,\n  backgroundColor: {\n    color: {\n      r: 196,\n      g: 196,\n      b: 196,\n    },\n  },\n  lineHeight: 1.5,\n  textAlign: 'initial',\n  padding: {\n    vertical: 0,\n    horizontal: 0,\n    locked: true,\n  },\n  type: 'text',\n  content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',\n  x: 40,\n  y: 300,\n  width: 206,\n  height: 75,\n  scale: 100,\n  focalX: 50,\n  focalY: 50,\n  id: '8d110168-e765-4c76-b63a-74ec23d54f27',\n};\n\ndescribe('Text/util', () => {\n  describe('generateFontFamily', () => {\n    it('should return correct string value for font family', () => {\n      const fallbackArray = [];\n      const expected = '\"Baloo Bhaina 2\"';\n      expect(\n        generateFontFamily({\n          family: 'Baloo Bhaina 2',\n          fallbacks: fallbackArray,\n        })\n      ).toStrictEqual(expected);\n      expect(generateFontFamily({ family: 'Baloo Bhaina 2' })).toStrictEqual(\n        expected\n      );\n    });\n\n    it('should return correct string value for font family with fallbacks', () => {\n      const fallbackArray = ['foo', 'bar', 'sans-serif'];\n      const expected = '\"Baloo Bhaina 2\",\"foo\",\"bar\",sans-serif';\n      expect(\n        generateFontFamily({\n          family: 'Baloo Bhaina 2',\n          fallbacks: fallbackArray,\n        })\n      ).toStrictEqual(expected);\n    });\n  });\n\n  describe('getHighlightLineHeight', () => {\n    it('should return correct value when just line-height', () => {\n      const actual = getHighlightLineHeight(3);\n      const expected = '3em';\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should return correct value with positive padding', () => {\n      const actual = getHighlightLineHeight(3, 10);\n      const expected = 'calc(3em + 20px)';\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should return correct value with negative padding', () => {\n      const actual = getHighlightLineHeight(3, -6);\n      const expected = 'calc(3em - 12px)';\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should return correct value with given units', () => {\n      const actual = getHighlightLineHeight(3, 2, '%');\n      const expected = 'calc(3em + 4%)';\n      expect(actual).toStrictEqual(expected);\n    });\n  });\n\n  describe('generateParagraphTextStyle', () => {\n    it('should return valid styles', () => {\n      const element = TEXT_ELEMENT;\n      const { width } = element;\n      const { font, lineHeight, textAlign } = element;\n\n      // Usage as in <TextOutput>\n      const dataToStyleX = (x) => `${dataToEditorX(x, 100)}%`;\n      const dataToStyleY = (y) => `${dataToEditorY(y, 100)}%`;\n      const dataToFontSizeY = (y) => `${dataToFontSize(y, 100)}em`;\n      const dataToPaddingY = (y) => `${(y / width) * 100}%`;\n      const actual = generateParagraphTextStyle(\n        element,\n        dataToStyleX,\n        dataToStyleY,\n        dataToFontSizeY,\n        element,\n        dataToPaddingY\n      );\n      const expected = {\n        dataToEditorY: dataToStyleY,\n        whiteSpace: 'pre-line',\n        overflowWrap: 'break-word',\n        wordBreak: 'break-word',\n        margin: '-1.4335558252427185% 0',\n        fontFamily: '\"Roboto\",\"Helvetica Neue\",\"Helvetica\",sans-serif',\n        fontSize: '0.291262em',\n        font,\n        lineHeight,\n        textAlign,\n        padding: 0,\n      };\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should return valid styles for element with padding', () => {\n      const element = {\n        ...TEXT_ELEMENT,\n        padding: {\n          vertical: 10,\n          horizontal: 10,\n          locked: true,\n        },\n      };\n      const { width } = element;\n      const { font, lineHeight, textAlign } = element;\n\n      // Usage as in <TextOutput>\n      const dataToStyleX = (x) => `${dataToEditorX(x, 100)}%`;\n      const dataToStyleY = (y) => `${dataToEditorY(y, 100)}%`;\n      const dataToFontSizeY = (y) => `${dataToFontSize(y, 100)}em`;\n      const dataToPaddingY = (y) => `${(y / width) * 100}%`;\n      const actual = generateParagraphTextStyle(\n        element,\n        dataToStyleX,\n        dataToStyleY,\n        dataToFontSizeY,\n        element,\n        dataToPaddingY\n      );\n      const expected = {\n        dataToEditorY: dataToStyleY,\n        whiteSpace: 'pre-line',\n        overflowWrap: 'break-word',\n        wordBreak: 'break-word',\n        margin: '-1.4335558252427185% 0',\n        fontFamily: '\"Roboto\",\"Helvetica Neue\",\"Helvetica\",sans-serif',\n        fontSize: '0.291262em',\n        font,\n        lineHeight,\n        textAlign,\n        padding: '1.61812% 2.42718%',\n      };\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should return valid styles for element with one-sided padding', () => {\n      const element = {\n        ...TEXT_ELEMENT,\n        padding: {\n          vertical: 10,\n          horizontal: 0,\n          locked: true,\n        },\n      };\n      const { width } = element;\n      const { font, lineHeight, textAlign } = element;\n\n      // Usage as in <TextOutput>\n      const dataToStyleX = (x) => `${dataToEditorX(x, 100)}%`;\n      const dataToStyleY = (y) => `${dataToEditorY(y, 100)}%`;\n      const dataToFontSizeY = (y) => `${dataToFontSize(y, 100)}em`;\n      const dataToPaddingY = (y) => `${(y / width) * 100}%`;\n      const actual = generateParagraphTextStyle(\n        element,\n        dataToStyleX,\n        dataToStyleY,\n        dataToFontSizeY,\n        element,\n        dataToPaddingY\n      );\n      const expected = {\n        dataToEditorY: dataToStyleY,\n        whiteSpace: 'pre-line',\n        overflowWrap: 'break-word',\n        wordBreak: 'break-word',\n        margin: '-1.4335558252427185% 0',\n        fontFamily: '\"Roboto\",\"Helvetica Neue\",\"Helvetica\",sans-serif',\n        fontSize: '0.291262em',\n        font,\n        lineHeight,\n        textAlign,\n        padding: '1.61812% 0%',\n      };\n      expect(actual).toStrictEqual(expected);\n    });\n\n    it('should allow using pixels as padding units', () => {\n      const element = {\n        ...TEXT_ELEMENT,\n        padding: {\n          vertical: 10,\n          horizontal: 0,\n          locked: true,\n        },\n      };\n\n      // Usage with pixels\n      const dataToStyleX = (x) => `${dataToEditorX(x, 100)}px`;\n      const dataToStyleY = (y) => `${dataToEditorY(y, 100)}px`;\n      const { padding } = generateParagraphTextStyle(\n        element,\n        dataToStyleX,\n        dataToStyleY,\n        undefined,\n        element\n      );\n      expect(padding).toBe('1.61812px 0px');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/text/textContent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { stripHTML } from '@googleforcreators/dom';\nimport type { TextElement } from '@googleforcreators/elements';\n\nfunction TextContent({ content }: TextElement) {\n  return stripHTML(content);\n}\n\nexport default TextContent;\n"
  },
  {
    "path": "packages/element-library/src/text/updateForResizeEvent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { dataPixels } from '@googleforcreators/units';\nimport { type TextElement } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport {\n  calculateFitTextFontSize,\n  calculateTextHeight,\n} from '../utils/textMeasurements';\n\nfunction updateForResizeEvent(\n  element: TextElement,\n  direction: [number, number],\n  newWidth: number,\n  newHeight: number\n) {\n  const isResizingWidth = direction[0] !== 0;\n  const isResizingHeight = direction[1] !== 0;\n\n  // Vertical or diagonal resizing w/keep ratio.\n  if (isResizingHeight) {\n    const { fontSize, marginOffset } = calculateFitTextFontSize(\n      element,\n      newWidth || element.width,\n      newHeight\n    );\n\n    return {\n      fontSize: dataPixels(fontSize),\n      marginOffset,\n    };\n  }\n\n  // Width-only resize: recalc height.\n  if (isResizingWidth) {\n    return { height: dataPixels(calculateTextHeight(element, newWidth)) };\n  }\n\n  return null;\n}\n\nexport default updateForResizeEvent;\n"
  },
  {
    "path": "packages/element-library/src/text/util.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  BaseFontData,\n  Padding,\n  TextAlign,\n  TextElement,\n  TextElementFont,\n} from '@googleforcreators/elements';\n\ntype DataToStyle = (prop: number) => string | number;\ninterface Props {\n  font: TextElementFont;\n  fontSize: number;\n  lineHeight: number;\n  padding?: Padding;\n  textAlign: TextAlign;\n}\n/**\n * Generates paragraph text style for a text element.\n */\nexport function generateParagraphTextStyle(\n  props: Props,\n  dataToStyleX: DataToStyle,\n  dataToStyleY: DataToStyle,\n  dataToFontSizeY = dataToStyleY,\n  element: TextElement,\n  dataToPaddingY = dataToStyleY\n) {\n  const { font, fontSize, lineHeight, padding, textAlign } = props;\n  const { marginOffset } = calcFontMetrics(element);\n\n  const verticalPadding = padding?.vertical || 0;\n  const horizontalPadding = padding?.horizontal || 0;\n  const hasPadding = verticalPadding || horizontalPadding;\n  const paddingStyle = hasPadding\n    ? `${dataToStyleY(verticalPadding)} ${dataToStyleX(horizontalPadding)}`\n    : 0;\n\n  return {\n    dataToEditorY: dataToStyleY,\n    whiteSpace: 'pre-line',\n    overflowWrap: 'break-word',\n    wordBreak: 'break-word',\n    margin: `${dataToPaddingY(-marginOffset / 2)} 0`,\n    fontFamily: generateFontFamily(font),\n    fontSize: dataToFontSizeY(fontSize) as number,\n    font,\n    lineHeight,\n    textAlign,\n    padding: paddingStyle,\n  };\n}\n\nexport const generateFontFamily = ({\n  family,\n  fallbacks,\n}: Partial<BaseFontData>) => {\n  const genericFamilyKeywords = [\n    'cursive',\n    'fantasy',\n    'monospace',\n    'serif',\n    'sans-serif',\n  ];\n  // Wrap into \" since some fonts won't work without it.\n  let fontFamilyDisplay = family ? `\"${family}\"` : '';\n  if (fallbacks && fallbacks.length) {\n    fontFamilyDisplay += family ? `,` : ``;\n    fontFamilyDisplay += fallbacks\n      .map((fallback) =>\n        genericFamilyKeywords.includes(fallback) ? fallback : `\"${fallback}\"`\n      )\n      .join(`,`);\n  }\n  return fontFamilyDisplay;\n};\n\nexport const getHighlightLineHeight = (\n  lineHeight: number,\n  verticalPadding = 0,\n  unit = 'px'\n) => {\n  if (verticalPadding === 0) {\n    return `${lineHeight}em`;\n  }\n  return `calc(${lineHeight}em ${verticalPadding > 0 ? '+' : '-'} ${\n    2 * Math.abs(verticalPadding)\n  }${unit})`;\n};\n\nexport function calcFontMetrics(element: TextElement) {\n  if (!element.font?.metrics) {\n    return {\n      contentAreaPx: 0,\n      lineBoxPx: 0,\n      marginOffset: 0,\n    };\n  }\n\n  const {\n    fontSize,\n    lineHeight,\n    font: {\n      metrics: { upm, asc, des },\n    },\n  } = element;\n\n  // We cant to cut some of the \"virtual-area\"\n  // More info: https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align\n  const contentAreaPx = ((asc - des) / upm) * fontSize;\n  const lineBoxPx = lineHeight * fontSize;\n  const marginOffset = lineBoxPx - contentAreaPx;\n\n  return {\n    marginOffset,\n    contentAreaPx,\n    lineBoxPx,\n  };\n}\n"
  },
  {
    "path": "packages/element-library/src/typings/global.d.ts",
    "content": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type {\n  CSSProperties,\n  DetailedHTMLProps,\n  ImgHTMLAttributes,\n  VideoHTMLAttributes,\n} from 'react';\n\ntype AmpLayout =\n  | 'fill'\n  | 'fixed'\n  | 'fixed-height'\n  | 'flex-item'\n  | 'intrinsic'\n  | 'nodisplay'\n  | 'responsive'\n  | 'container';\n\ninterface AmpVideo extends DetailedHTMLProps<\n  Omit<VideoHTMLAttributes<HTMLVideoElement>, 'loop' | 'autoPlay'>,\n  HTMLVideoElement\n> {\n  layout: AmpLayout;\n  'captions-id'?: string;\n  autoPlay?: string;\n  loop?: string;\n  noaudio?: string;\n  alt?: string;\n}\n\ninterface AmpImg extends DetailedHTMLProps<\n  ImgHTMLAttributes<HTMLImageElement>,\n  HTMLImageElement\n> {\n  layout: AmpLayout;\n  'disable-inline-width'?: boolean;\n}\n\ninterface AmpStoryShoppingTag {\n  'data-product-id'?: string | number;\n}\n\ninterface AmpStoryAudioSticker {\n  sticker: 'headphone-cat' | 'tape-player' | 'loud-speaker' | 'audio-cloud';\n  'sticker-style'?: 'none' | 'outline' | 'dropshadow';\n  size: 'large' | 'small';\n  style?: CSSProperties;\n}\n\ndeclare global {\n  namespace JSX {\n    interface IntrinsicElements {\n      'amp-story-shopping-tag': AmpStoryShoppingTag;\n      'amp-story-audio-sticker': AmpStoryAudioSticker;\n      'amp-video': AmpVideo;\n      'amp-img': AmpImg;\n    }\n  }\n}\n\nexport {};\n"
  },
  {
    "path": "packages/element-library/src/typings/images.d.ts",
    "content": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.png' {\n  const value: string;\n  export = value;\n}\n"
  },
  {
    "path": "packages/element-library/src/typings/styled.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport 'styled-components';\nimport type { Theme } from '@googleforcreators/design-system';\n\ndeclare module 'styled-components' {\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- On purpose.\n  export interface DefaultTheme extends Theme {}\n}\n"
  },
  {
    "path": "packages/element-library/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/element-library/src/utils/noop.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const noop = () => {};\n"
  },
  {
    "path": "packages/element-library/src/utils/textMeasurements.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport { dataPixels, PAGE_HEIGHT } from '@googleforcreators/units';\nimport type { Element, TextElement } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport TextOutputWithUnits from '../text/outputWithUnits';\nimport { calcFontMetrics } from '../text/util';\n\ntype CSSProperty = string | number | null | undefined;\ntype CSSProperties = Record<string, CSSProperty>;\nconst MEASURER_STYLES: CSSProperties = {\n  boxSizing: 'border-box',\n  visibility: 'hidden',\n  position: 'fixed',\n  contain: 'layout paint',\n  top: '-9999px',\n  left: '-9999px',\n  zIndex: -1,\n  overflowWrap: 'break-word',\n  // oxlint-disable-next-line no-constant-condition\n  ...(false\n    ? {\n        // For debugging purposes - this will show the output render on screen\n        background: 'red',\n        visibility: 'visible',\n        top: '99px',\n        left: '99px',\n        zIndex: 10000,\n      }\n    : null),\n};\n\nconst MEASURER_PROPS = {\n  dataToStyleX: (x: number) => `${x}px`,\n  dataToStyleY: (y: number) => `${y}px`,\n};\n\nconst MEASURER_NODE = '__WEB_STORIES_MEASURER__';\nconst LAST_ELEMENT = '__WEB_STORIES_LASTEL__';\n\nexport function calculateTextHeight(element: TextElement, width: number) {\n  const measurer = getOrCreateMeasurer(element);\n  setStyles(measurer, { width: `${width}px`, height: undefined });\n  return (measurer.parentNode as HTMLElement).offsetHeight;\n}\n\nexport function calculateFitTextFontSize(\n  element: TextElement,\n  width: number,\n  height: number\n) {\n  const measurer = getOrCreateMeasurer(element);\n  setStyles(measurer, {\n    width: `${width}px`,\n    height: undefined,\n    fontSize: undefined,\n  });\n\n  // Binomial search for the best font size.\n  let minFontSize = 1;\n  let maxFontSize = PAGE_HEIGHT;\n  let margin = 0;\n  while (maxFontSize - minFontSize > 1) {\n    const mid = dataPixels((minFontSize + maxFontSize) / 2);\n    const { marginOffset } = calcFontMetrics({ ...element, fontSize: mid });\n    margin = marginOffset;\n    setStyles(measurer, {\n      fontSize: `${mid}px`,\n      margin: `${-marginOffset / 2}px 0`,\n    });\n    const currentHeight = measurer.offsetHeight;\n    if (currentHeight - marginOffset > height) {\n      maxFontSize = mid;\n    } else {\n      minFontSize = mid;\n    }\n  }\n  // This is for keeping the debug window in sync\n  setStyles(measurer, {\n    fontSize: `${minFontSize}px`,\n    margin: `${-margin / 2}px 0`,\n  });\n  return { fontSize: minFontSize, marginOffset: margin };\n}\n\ninterface ExtendedBody extends HTMLElement {\n  __WEB_STORIES_MEASURER__?: HTMLElement;\n}\nfunction getOrCreateMeasurer(element: TextElement): HTMLElement {\n  let measurerNode = (document.body as ExtendedBody)[MEASURER_NODE];\n  if (!measurerNode) {\n    measurerNode = document.createElement('div');\n    measurerNode.id = '__web-stories-text-measurer';\n    measurerNode.className = 'web-stories-content';\n    setStyles(measurerNode, MEASURER_STYLES);\n    document.body.appendChild(measurerNode);\n    (document.body as ExtendedBody)[MEASURER_NODE] = measurerNode;\n  }\n  // Very unfortunately `ReactDOM.render()` is not synchoronous. Thus, we\n  // have to use `renderToStaticMarkup()` markup instead and do manual\n  // diffing.\n  if (changed(measurerNode, element)) {\n    measurerNode.innerHTML = renderToStaticMarkup(\n      <TextOutputWithUnits element={element} {...MEASURER_PROPS} />\n    );\n  }\n  return measurerNode.firstElementChild as HTMLElement;\n}\n\nfunction setStyles(node: HTMLElement, styles: CSSProperties) {\n  for (const k in styles) {\n    if (Object.prototype.hasOwnProperty.call(styles, k)) {\n      const v = styles[k];\n      if (v === null) {\n        node.style.setProperty(k, '');\n      } else {\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- k can be a string, too.\n        // @ts-ignore\n        node.style[k] = v;\n      }\n    }\n  }\n}\n\ninterface CustomHTMLElement extends HTMLElement {\n  __WEB_STORIES_LASTEL__?: Element;\n}\nfunction changed(node: CustomHTMLElement, element: Element) {\n  const lastElement = node[LAST_ELEMENT];\n  node[LAST_ELEMENT] = element;\n  if (!node.firstElementChild || !lastElement) {\n    return true;\n  }\n  return lastElement !== element;\n}\n"
  },
  {
    "path": "packages/element-library/src/video/captions.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { Track } from '@googleforcreators/elements';\n\nfunction Captions({ tracks, kind }: { tracks?: Track[]; kind?: string }) {\n  if (!tracks) {\n    return null;\n  }\n\n  return (\n    <>\n      {tracks.map(({ srclang, label, kind: trackKind, track, id: key }, i) => (\n        <track\n          srcLang={srclang}\n          label={label}\n          kind={kind || trackKind}\n          src={track || undefined}\n          key={key}\n          default={i === 0}\n        />\n      ))}\n    </>\n  );\n}\n\nexport default Captions;\n"
  },
  {
    "path": "packages/element-library/src/video/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport {\n  MEDIA_DEFAULT_ATTRIBUTES,\n  MEDIA_PANELS,\n  resizeRules as mediaResizeRules,\n} from '../media/constants';\nimport { SHARED_DEFAULT_ATTRIBUTES } from '../shared';\n\nexport {\n  canFlip,\n  isMaskable,\n  isAspectAlwaysLocked,\n  isMedia,\n  hasEditMode,\n  hasDuplicateMenu,\n  hasEditModeIfLocked,\n  hasEditModeMoveable,\n  hasDesignMenu,\n  editModeGrayout,\n} from '../media/constants';\n\nexport const resizeRules = {\n  ...mediaResizeRules,\n};\n\nexport const defaultAttributes = {\n  ...SHARED_DEFAULT_ATTRIBUTES,\n  ...MEDIA_DEFAULT_ATTRIBUTES,\n  controls: false,\n  loop: false,\n  autoPlay: true,\n  volume: 1,\n  tracks: [],\n  resource: {\n    type: ResourceType.Video,\n    id: 0,\n    width: 0,\n    height: 0,\n    length: 0,\n    lengthFormatted: '',\n    alt: '',\n    src: '',\n    mimeType: '',\n  },\n};\n\nexport const panels = [\n  PanelTypes.ElementAlignment,\n  ...MEDIA_PANELS,\n  PanelTypes.VideoOptions,\n  PanelTypes.VideoSegment,\n  PanelTypes.VideoAcessibility,\n  PanelTypes.Captions,\n];\n"
  },
  {
    "path": "packages/element-library/src/video/controls.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { VideoElement } from '@googleforcreators/elements';\nimport type { ElementBox } from '@googleforcreators/units';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport PlayPauseButton from './playPauseButton';\n\ninterface VideoControlsProps {\n  box: ElementBox;\n  isActive: boolean;\n  isTransforming: boolean;\n  elementRef: RefObject<HTMLElement>;\n  element: VideoElement;\n  isRTL: boolean;\n}\n\nfunction VideoControls({\n  box,\n  isActive,\n  isTransforming,\n  elementRef,\n  element,\n  isRTL,\n}: VideoControlsProps) {\n  return (\n    <PlayPauseButton\n      box={box}\n      isActive={isActive}\n      isTransforming={isTransforming}\n      elementRef={elementRef}\n      element={element}\n      isRTL={isRTL}\n    />\n  );\n}\n\nexport default VideoControls;\n"
  },
  {
    "path": "packages/element-library/src/video/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport { getMediaSizePositionProps } from '@googleforcreators/media';\nimport type { VideoElement, DisplayProps } from '@googleforcreators/elements';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport MediaDisplay from '../media/display';\nimport { getBackgroundStyle, Video, VideoImage } from '../media/util';\nimport Captions from './captions';\n\nfunction VideoDisplay({\n  previewMode,\n  box: { width, height },\n  element,\n  getProxiedUrl,\n  renderResourcePlaceholder,\n}: DisplayProps<VideoElement>) {\n  const {\n    id,\n    poster,\n    resource,\n    tracks = [],\n    isBackground,\n    scale,\n    focalX,\n    focalY,\n    loop,\n    volume,\n  } = element;\n  const ref = useRef<HTMLVideoElement | HTMLImageElement>(null);\n\n  let style = {};\n  if (isBackground) {\n    const styleProps = getBackgroundStyle();\n    style = {\n      ...style,\n      ...styleProps,\n    };\n  }\n\n  const videoProps = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    focalX,\n    focalY\n  );\n\n  const muted = Boolean(resource?.isMuted);\n\n  const url = getProxiedUrl(resource, resource?.src);\n  const tracksFormatted = tracks.map((track) => {\n    const src = getProxiedUrl(track, track?.track || undefined);\n    return {\n      ...track,\n      track: src,\n    };\n  });\n\n  return (\n    <MediaDisplay<VideoElement>\n      element={element}\n      mediaRef={ref}\n      showPlaceholder\n      previewMode={previewMode}\n      renderResourcePlaceholder={renderResourcePlaceholder}\n    >\n      {previewMode ? (\n        (poster || resource.poster) && (\n          <VideoImage\n            src={poster || resource.poster}\n            alt={element.alt || resource.alt}\n            style={style}\n            {...videoProps}\n            ref={ref as RefObject<HTMLImageElement>}\n          />\n        )\n      ) : (\n        // eslint-disable-next-line jsx-a11y/media-has-caption -- False positive.\n        <Video\n          id={`video-${id}`}\n          // Force React to update the video in the DOM, causing it to properly reload if the URL changes.\n          // See https://github.com/GoogleForCreators/web-stories-wp/issues/10678\n          key={url}\n          poster={poster || resource.poster}\n          style={style}\n          {...videoProps}\n          preload=\"metadata\"\n          loop={loop}\n          muted={muted}\n          // @ts-expect-error TODO: Is this actually legit?\n          volume={!muted && volume ? volume : undefined}\n          ref={ref as RefObject<HTMLVideoElement>}\n          data-testid=\"videoElement\"\n          data-leaf-element=\"true\"\n        >\n          {url && <source src={url} type={resource.mimeType} />}\n          {/*Hides the track from the user. Displaying happens in MediaCaptionsLayer instead.*/}\n          <Captions tracks={tracksFormatted} kind=\"metadata\" />\n        </Video>\n      )}\n    </MediaDisplay>\n  );\n}\n\nexport default VideoDisplay;\n"
  },
  {
    "path": "packages/element-library/src/video/edit.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { VideoElement, EditProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport MediaEdit from '../media/edit';\nimport Trim from './trim';\n\nfunction VideoEdit({\n  element,\n  box,\n  isTrimMode,\n  ...rest\n}: EditProps<VideoElement>) {\n  if (isTrimMode) {\n    return <Trim element={element} box={box} {...rest} />;\n  }\n\n  return <MediaEdit<VideoElement> element={element} box={box} {...rest} />;\n}\n\nexport default VideoEdit;\n"
  },
  {
    "path": "packages/element-library/src/video/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport MediaFrame from '../media/frame';\n\nfunction VideoFrame() {\n  return <MediaFrame />;\n}\n\nexport default VideoFrame;\n"
  },
  {
    "path": "packages/element-library/src/video/icon.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport type { VideoElement, LayerIconProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport VideoImage from '../media/videoImage';\nimport VisibleImage from '../shared/visibleImage';\n\nfunction VideoLayerIcon({\n  element: {\n    resource: { poster: defaultPoster, src },\n    poster,\n  },\n  showVideoPreviewAsBackup,\n}: LayerIconProps<VideoElement>) {\n  const iconImage = poster?.length ? poster : defaultPoster;\n\n  // The image/video is purely decorative by default, because the alt text is already used\n  // for the layer description. Hence using alt=\"\" / title=\"\" to avoid repetition.\n  if (!iconImage && showVideoPreviewAsBackup) {\n    return <VideoImage src={src} alt=\"\" />;\n  } else if (!iconImage) {\n    return <Icons.Video width={21} height={21} title=\"\" />;\n  }\n\n  return <VisibleImage src={iconImage} width={21} height={21} />;\n}\n\nexport default VideoLayerIcon;\n"
  },
  {
    "path": "packages/element-library/src/video/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Display } from './display';\nexport { default as Edit } from './edit';\nexport { default as Frame } from './frame';\nexport { default as Controls } from './controls';\nexport { default as Output } from './output';\nexport { default as getLayerText } from './layer';\nexport { default as LayerIcon } from './icon';\nexport { default as onDropHandler } from './onDropHandler';\n\nexport * from './constants';\n"
  },
  {
    "path": "packages/element-library/src/video/layer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { VideoElement } from '@googleforcreators/elements';\n\nfunction getVideoLayerText(element: VideoElement) {\n  const { alt } = element?.resource || {};\n\n  return alt || __('Video Content', 'web-stories');\n}\n\nexport default getVideoLayerText;\n"
  },
  {
    "path": "packages/element-library/src/video/onDropHandler.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction onDropHandler(dropTargetId: string) {\n  // Auto-play video on drop\n  setTimeout(() => {\n    const videoEl = document.getElementById(\n      `video-${dropTargetId}`\n    ) as HTMLVideoElement | null;\n    if (videoEl) {\n      videoEl.load();\n      videoEl.play().catch(() => {});\n    }\n  });\n}\n\nexport default onDropHandler;\n"
  },
  {
    "path": "packages/element-library/src/video/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { isBlobURL } from '@googleforcreators/media';\nimport type { VideoElement, OutputProps } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport MediaOutput from '../media/output';\nimport Captions from './captions';\n\nfunction defaultForUndefined<V, D>(value: V | undefined, def: D): V | D {\n  return value === undefined ? def : value;\n}\n\nfunction VideoOutput({ element, box, flags }: OutputProps<VideoElement>) {\n  const { resource, loop, tracks, volume } = element;\n  const { isMuted, mimeType, src } = resource;\n\n  const poster = defaultForUndefined(element.poster, resource.poster);\n  const alt = defaultForUndefined(element.alt, resource.alt);\n\n  const sourceProps = {\n    type: mimeType,\n    src: flags?.allowBlobs || !isBlobURL(src) ? src : '',\n  };\n\n  const videoProps = {\n    autoplay: 'autoplay',\n    poster: flags?.allowBlobs || !isBlobURL(poster) ? poster : '',\n    artwork: flags?.allowBlobs || !isBlobURL(poster) ? poster : '',\n    title: alt,\n    alt,\n    loop: loop ? 'loop' : undefined,\n    noaudio: isMuted ? 'noaudio' : undefined,\n    volume: !isMuted && volume ? volume : undefined,\n  };\n\n  return (\n    <MediaOutput element={element} box={box} data-leaf-element=\"true\">\n      <amp-video\n        layout=\"fill\"\n        {...videoProps}\n        id={`el-${element.id}-media`}\n        // Actual <amp-story-captions> output happens in OutputPage.\n        captions-id={\n          tracks?.length > 0 ? `el-${element.id}-captions` : undefined\n        }\n      >\n        <source {...sourceProps} />\n        <Captions tracks={tracks} />\n      </amp-video>\n    </MediaOutput>\n  );\n}\n\nexport default VideoOutput;\n"
  },
  {
    "path": "packages/element-library/src/video/playPauseButton.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  useDebouncedCallback,\n  useEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { CSSTransition } from 'react-transition-group';\nimport { __ } from '@googleforcreators/i18n';\nimport { rgba } from 'polished';\nimport {\n  Icons,\n  Placement,\n  Popup,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport { type VideoElement } from '@googleforcreators/elements';\nimport type { ElementBox } from '@googleforcreators/units';\nimport type { ReactNode, RefObject, MouseEventHandler } from 'react';\n\nconst PLAY_BUTTON_SIZE = 82;\nconst ICON_SVG_SIZE = 72;\nconst PLAY_ABOVE_BREAKPOINT_WIDTH = 108;\nconst PLAY_ABOVE_BREAKPOINT_HEIGHT = 120;\n\nconst Controls = styled.div<{\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n}>`\n  position: absolute;\n  z-index: 2;\n  left: ${({ x }) => `${x}px`};\n  top: ${({ y }) => `${y}px`};\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n  pointer-events: none;\n`;\n\nconst ButtonWrapper = styled.div.attrs({ role: 'button', tabIndex: -1 })<{\n  isAbove: boolean;\n}>`\n  ${({ isAbove }) =>\n    !isAbove &&\n    css`\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n    `}\n  cursor: pointer;\n  pointer-events: initial;\n  width: ${PLAY_BUTTON_SIZE}px;\n  height: ${PLAY_BUTTON_SIZE}px;\n  overflow: hidden;\n  opacity: ${({ isAbove }) => (isAbove ? 1 : 0)};\n  &.button-enter {\n    opacity: 0;\n  }\n  &.button-enter-active,\n  &.button-enter-done {\n    opacity: 1;\n    transition: opacity 100ms;\n  }\n  &.button-exit {\n    opacity: 1;\n  }\n  &.button-exit-active,\n  &.button-exit-done {\n    opacity: 0;\n    transition: opacity 100ms;\n  }\n`;\n\nconst iconCss = css<{\n  $isRTL: boolean;\n}>`\n  width: ${ICON_SVG_SIZE}px;\n  height: ${ICON_SVG_SIZE}px;\n  pointer-events: none;\n  transform: translate(\n    ${({ $isRTL }) =>\n      ((PLAY_BUTTON_SIZE - ICON_SVG_SIZE) / 2) * ($isRTL ? -1 : 1)}px,\n    ${(PLAY_BUTTON_SIZE - ICON_SVG_SIZE) / 2}px\n  );\n  color: ${({ theme }) => theme.colors.standard.white};\n  filter: drop-shadow(\n    0px 0px 10px ${({ theme }) => rgba(theme.colors.bg.primary, 0.4)}\n  );\n`;\n\nconst Play = styled(Icons.PlayFilled)`\n  ${iconCss};\n`;\nconst Pause = styled(Icons.StopFilled)`\n  ${iconCss};\n`;\n\nconst playAboveSpacing = {\n  x: 0,\n  y: 22,\n};\n\ninterface PlayPauseButtonProps {\n  box: ElementBox;\n  isActive?: boolean;\n  isTransforming?: boolean;\n  shouldResetOnEnd?: boolean;\n  elementRef: RefObject<HTMLElement>;\n  element: VideoElement;\n  videoRef?: RefObject<HTMLVideoElement> | null;\n  isRTL: boolean;\n}\n\nfunction PlayPauseButton({\n  box,\n  isActive = true,\n  isTransforming = false,\n  shouldResetOnEnd = true,\n  elementRef,\n  element,\n  videoRef = null,\n  isRTL,\n}: PlayPauseButtonProps) {\n  const isPlayAbove =\n    element.width < PLAY_ABOVE_BREAKPOINT_WIDTH ||\n    element.height < PLAY_ABOVE_BREAKPOINT_HEIGHT;\n  const [hovering, setHovering] = useState(false);\n  const [showControls, setShowControls] = useState(true);\n  const [isPlaying, setIsPlaying] = useState(false);\n  const [videoNode, setVideoNode] = useState<HTMLVideoElement | null>(null);\n  const { id } = element;\n  useEffect(\n    () =>\n      setVideoNode(\n        videoRef\n          ? videoRef.current\n          : (document.getElementById(`video-${id}`) as HTMLVideoElement)\n      ),\n    [videoRef, id]\n  );\n\n  useEffect(() => {\n    if (!isActive) {\n      if (videoNode) {\n        videoNode.pause();\n        // eslint-disable-next-line react-hooks/immutability -- FIXME\n        videoNode.currentTime = 0;\n      }\n      setShowControls(false);\n    }\n  }, [videoNode, isActive]);\n\n  useEffect(() => {\n    if (videoNode && !videoNode.paused && !isTransforming) {\n      videoNode.pause();\n    }\n  }, [videoNode, isTransforming]);\n\n  useEffect(() => {\n    if (!videoNode || !shouldResetOnEnd) {\n      return undefined;\n    }\n\n    const onVideoEnd = () => {\n      videoNode.currentTime = 0;\n      setIsPlaying(false);\n    };\n\n    videoNode.addEventListener('ended', onVideoEnd);\n    return () => videoNode.removeEventListener('ended', onVideoEnd);\n  }, [shouldResetOnEnd, videoNode, id]);\n\n  useEffect(() => {\n    if (!videoNode) {\n      return undefined;\n    }\n\n    const onVideoPlay = () => setIsPlaying(true);\n    const onVideoPause = () => setIsPlaying(false);\n\n    videoNode.addEventListener('play', onVideoPlay);\n    videoNode.addEventListener('pause', onVideoPause);\n    return () => {\n      videoNode.removeEventListener('play', onVideoPlay);\n      videoNode.removeEventListener('pause', onVideoPause);\n    };\n  }, [videoNode, id]);\n\n  const checkShowControls = useDebouncedCallback(() => {\n    if (!isPlayAbove) {\n      setShowControls(!isPlaying);\n    }\n  }, 2000);\n  const checkMouseInBBox = useDebouncedCallback((evt: MouseEvent) => {\n    const node = elementRef.current;\n    if (!node) {\n      return;\n    }\n    const elementBBox = node.getBoundingClientRect();\n    const isHovering =\n      evt.clientX >= elementBBox.left &&\n      evt.clientX <= elementBBox.right &&\n      evt.clientY >= elementBBox.top &&\n      evt.clientY <= elementBBox.bottom;\n    setHovering(isHovering);\n    setShowControls(true);\n    checkShowControls();\n  }, 10);\n\n  useEffect(() => {\n    document.addEventListener('pointermove', checkMouseInBBox);\n    return () => {\n      document.removeEventListener('pointermove', checkMouseInBBox);\n    };\n  }, [checkMouseInBBox]);\n\n  const handlePlayPause = <T extends Event = MouseEvent>(evt: T): void => {\n    evt.stopPropagation();\n    if (!videoNode) {\n      return;\n    }\n\n    if (isPlaying) {\n      videoNode.pause();\n      setShowControls(true);\n    } else {\n      videoNode.play().catch(() => {});\n    }\n  };\n  useKeyDownEffect(\n    elementRef,\n    {\n      key: ['space'],\n    },\n    handlePlayPause,\n    [handlePlayPause]\n  );\n  const nodeRef = useRef<HTMLDivElement>(null);\n  if (!isActive) {\n    return null;\n  }\n\n  const buttonLabel = isPlaying\n    ? __('Click to pause', 'web-stories')\n    : __('Click to play', 'web-stories');\n  const TransitionWrapper = isPlayAbove\n    ? ({ children }: { children: ReactNode }) => (\n        <Popup\n          anchor={elementRef}\n          isOpen\n          placement={Placement.Top}\n          spacing={playAboveSpacing}\n        >\n          {children}\n        </Popup>\n      )\n    : CSSTransition;\n\n  const Icon = isPlaying ? Pause : Play;\n  return (\n    <Controls data-controls-id={id} {...box}>\n      {showControls && element.resource.src && (\n        <TransitionWrapper\n          in={hovering}\n          appear\n          nodeRef={nodeRef}\n          classNames=\"button\"\n          timeout={100}\n        >\n          <ButtonWrapper\n            ref={nodeRef}\n            aria-label={buttonLabel}\n            aria-pressed={isPlaying}\n            key=\"wrapper\"\n            onMouseDown={handlePlayPause as MouseEventHandler<HTMLDivElement>}\n            isAbove={isPlayAbove}\n          >\n            <Icon $isRTL={isRTL} />\n          </ButtonWrapper>\n        </TransitionWrapper>\n      )}\n    </Controls>\n  );\n}\n\nexport default PlayPauseButton;\n"
  },
  {
    "path": "packages/element-library/src/video/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport VideoOutput from '../output';\n\ndescribe('Video output', () => {\n  jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n  const baseProps = {\n    element: {\n      id: '123',\n      type: 'video',\n      mimeType: 'video/mp4',\n      scale: 1,\n      origRatio: 9 / 16,\n      x: 50,\n      y: 100,\n      height: 1920,\n      width: 1080,\n      rotationAngle: 0,\n      loop: true,\n      tracks: [],\n      resource: {\n        type: 'video',\n        mimeType: 'video/mp4',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        alt: 'alt text',\n        height: 1920,\n        width: 1080,\n      },\n    },\n    box: { width: 1080, height: 1920, x: 50, y: 100, rotationAngle: 0 },\n  };\n\n  it('an undefined alt tag in the element should fall back to the resource', async () => {\n    const props = {\n      ...baseProps,\n      element: { ...baseProps.element, alt: undefined },\n    };\n    const output = <VideoOutput {...props} />;\n    await expect(output).toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(expect.stringMatching('alt text'));\n  });\n\n  it('should not render noaudio attribute if isMuted is not set', async () => {\n    const output = <VideoOutput {...baseProps} />;\n    await expect(output).toBeValidAMPStoryElement();\n    await expect(output).not.toStrictEqual(expect.stringMatching('noaudio'));\n  });\n\n  it('should render noaudio attribute if isMuted is true', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        resource: { ...baseProps.element.resource, isMuted: true },\n      },\n    };\n\n    const output = <VideoOutput {...props} />;\n    await expect(output).toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(expect.stringMatching('noaudio'));\n  });\n\n  it('an empty string alt tag in the element should not fall back to the resource', async () => {\n    const props = { ...baseProps, element: { ...baseProps.element, alt: '' } };\n    const output = <VideoOutput {...props} />;\n    await expect(output).toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).not.toStrictEqual(\n      expect.stringMatching('alt text')\n    );\n  });\n\n  it('should remove blob URLs', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        resource: {\n          ...baseProps.element.resource,\n          src: 'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n          poster:\n            'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n        },\n      },\n    };\n    const output = <VideoOutput {...props} />;\n    await expect(output).not.toBeValidAMPStoryElement();\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).not.toStrictEqual(expect.stringMatching('blob:'));\n  });\n\n  it('should add captions-id attribute if there are tracks', async () => {\n    const props = {\n      ...baseProps,\n      element: {\n        ...baseProps.element,\n        tracks: [\n          {\n            track: 'https://example.com/track.vtt',\n            trackId: 123,\n            trackName: 'track.vtt',\n            id: 'rersd-fdfd-fdfd-fdfd',\n            srcLang: '',\n            label: '',\n            kind: 'captions',\n          },\n        ],\n      },\n    };\n\n    const output = <VideoOutput {...props} />;\n    const outputStr = renderToStaticMarkup(output);\n    await expect(outputStr).toStrictEqual(\n      expect.stringMatching('captions-id=\"el-123-captions\"')\n    );\n  });\n\n  describe('AMP validation', () => {\n    it('should produce valid AMP output', async () => {\n      await expect(<VideoOutput {...baseProps} />).toBeValidAMPStoryElement();\n    });\n\n    // eslint-disable-next-line jest/no-disabled-tests -- amp-story-captions is not stable yet.\n    it.skip('should produce valid AMP output with track', async () => {\n      const props = {\n        ...baseProps,\n        element: {\n          ...baseProps.element,\n          tracks: [\n            {\n              track: 'https://example.com/track.vtt',\n              trackId: 123,\n              trackName: 'track.vtt',\n              id: 'rersd-fdfd-fdfd-fdfd',\n              srcLang: '',\n              label: '',\n              kind: 'captions',\n            },\n          ],\n        },\n      };\n      await expect(<VideoOutput {...props} />).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/element-library/src/video/trim.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useRef, useMemo, useCallback } from '@googleforcreators/react';\nimport {\n  getMediaSizePositionProps,\n  type Resource,\n  type VideoResource,\n} from '@googleforcreators/media';\nimport { CircularProgress } from '@googleforcreators/design-system';\nimport {\n  getTransformFlip,\n  type VideoElement,\n  type DisplayProps,\n} from '@googleforcreators/elements';\nimport type { ElementBox } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport MediaDisplay from '../media/display';\nimport { elementWithFlip } from '../shared';\nimport { getBackgroundStyle, Video } from '../media/util';\nimport PlayPauseButton from './playPauseButton';\nimport Captions from './captions';\n\nconst StyledVideo = styled(Video)`\n  ${elementWithFlip}\n`;\n\nconst Wrapper = styled.div`\n  width: 100%;\n  height: 100%;\n  position: absolute;\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\ninterface VideoTrimProps {\n  element: VideoElement;\n  box: ElementBox;\n  isRTL: boolean;\n  topOffset: number;\n  resource?: VideoResource;\n  setVideoNode: (node: HTMLVideoElement) => void;\n  getProxiedUrl: (\n    resource: Pick<Resource, 'needsProxy'>,\n    src?: string\n  ) => string | null;\n  renderResourcePlaceholder?: DisplayProps<VideoElement>['renderResourcePlaceholder'];\n}\n\nfunction VideoTrim({\n  box,\n  element,\n  isRTL,\n  resource,\n  setVideoNode,\n  getProxiedUrl,\n  renderResourcePlaceholder,\n}: VideoTrimProps) {\n  const { width, height } = box;\n  const {\n    poster,\n    tracks = [],\n    isBackground,\n    scale,\n    flip,\n    focalX,\n    focalY,\n    volume,\n  } = element;\n  const wrapperRef = useRef<HTMLDivElement | null>(null);\n  const videoRef = useRef<HTMLVideoElement | null>(null);\n  let style = {};\n  if (isBackground) {\n    const styleProps = getBackgroundStyle();\n    style = {\n      ...style,\n      ...styleProps,\n    };\n  }\n\n  const boxAtOrigin = useMemo(\n    () => ({\n      ...box,\n      x: 0,\n      y: 0,\n    }),\n    [box]\n  );\n  const setRef = useCallback(\n    (node: HTMLVideoElement) => {\n      videoRef.current = node;\n      setVideoNode(node);\n    },\n    [setVideoNode]\n  );\n\n  if (!resource) {\n    return (\n      <Wrapper>\n        <Spinner>\n          <CircularProgress />\n        </Spinner>\n      </Wrapper>\n    );\n  }\n\n  const videoProps = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    flip?.horizontal ? 100 - (focalX || 0) : focalX,\n    flip?.vertical ? 100 - (focalY || 0) : focalY\n  );\n  const muted = Boolean(resource?.isMuted);\n  const tracksFormatted = tracks.map((track) => {\n    const src = getProxiedUrl(track, track?.track || undefined);\n    return {\n      ...track,\n      track: src,\n    };\n  });\n\n  return (\n    <>\n      <Wrapper ref={wrapperRef}>\n        <MediaDisplay<VideoElement>\n          element={element}\n          mediaRef={videoRef}\n          showPlaceholder\n          previewMode={false}\n          renderResourcePlaceholder={renderResourcePlaceholder}\n        >\n          {}\n          {/* eslint-disable-next-line jsx-a11y/media-has-caption -- False positive. */}\n          <StyledVideo\n            poster={poster || resource.poster}\n            style={style}\n            {...videoProps}\n            $transformFlip={getTransformFlip(flip)}\n            // @ts-expect-error TODO: Is this actually legit?\n            volume={!muted && volume ? volume : undefined}\n            preload=\"metadata\"\n            autoPlay\n            tabIndex={0}\n            ref={setRef}\n          >\n            {resource.src && (\n              <source src={resource.src} type={resource.mimeType} />\n            )}\n            <Captions tracks={tracksFormatted} />\n          </StyledVideo>\n        </MediaDisplay>\n      </Wrapper>\n      <PlayPauseButton\n        box={boxAtOrigin}\n        element={element}\n        elementRef={wrapperRef}\n        videoRef={videoRef}\n        shouldResetOnEnd={false}\n        isRTL={isRTL}\n      />\n    </>\n  );\n}\n\nexport default VideoTrim;\n"
  },
  {
    "path": "packages/element-library/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../dom\" },\n    { \"path\": \"../elements\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../masks\" },\n    { \"path\": \"../media\" },\n    { \"path\": \"../moveable\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../rich-text\" },\n    { \"path\": \"../stickers\" },\n    { \"path\": \"../transform\" },\n    { \"path\": \"../units\" }\n  ],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/elements/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/elements/README.md",
    "content": "# Elements\n\nProvides various APIs to register & retrieve element types.\n"
  },
  {
    "path": "packages/elements/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/elements\",\n  \"description\": \"Provides various APIs to register & retrieve element types.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/elements/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/elements\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 16\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/animation\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"prop-types\": \"^15.7.2\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"immer\": \"^10.1.1\"\n  }\n}\n"
  },
  {
    "path": "packages/elements/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { FontService, type GoogleFontData } from './types';\n\nexport const ELEMENT_TYPES = {\n  IMAGE: 'image',\n  SHAPE: 'shape',\n  TEXT: 'text',\n  VIDEO: 'video',\n  GIF: 'gif',\n  STICKER: 'sticker',\n  PRODUCT: 'product',\n  AUDIO_STICKER: 'audioSticker',\n} as const;\n\nexport const MEDIA_ELEMENT_TYPES = [\n  ELEMENT_TYPES.IMAGE,\n  ELEMENT_TYPES.VIDEO,\n  ELEMENT_TYPES.GIF,\n  ELEMENT_TYPES.PRODUCT,\n] as const;\n\nexport const MULTIPLE_VALUE = '((MULTIPLE))';\n\n// @todo: only provide font family, and use font provider to fill the rest.\nexport const TEXT_ELEMENT_DEFAULT_FONT: GoogleFontData = {\n  family: 'Roboto',\n  weights: [100, 300, 400, 500, 700, 900],\n  styles: ['italic', 'regular'],\n  variants: [\n    [0, 100],\n    [1, 100],\n    [0, 300],\n    [1, 300],\n    [0, 400],\n    [1, 400],\n    [0, 500],\n    [1, 500],\n    [0, 700],\n    [1, 700],\n    [0, 900],\n    [1, 900],\n  ],\n  fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n  service: FontService.GoogleFonts,\n  metrics: {\n    upm: 2048,\n    asc: 1900,\n    des: -500,\n    tAsc: 1536,\n    tDes: -512,\n    tLGap: 102,\n    wAsc: 1946,\n    wDes: 512,\n    xH: 1082,\n    capH: 1456,\n    yMin: -555,\n    yMax: 2163,\n    hAsc: 1900,\n    hDes: -500,\n    lGap: 0,\n  },\n};\n\nexport const BACKGROUND_TEXT_MODE = {\n  NONE: 'NONE',\n  FILL: 'FILL',\n  HIGHLIGHT: 'HIGHLIGHT',\n};\n\nexport const OverlayType = {\n  NONE: 'none',\n  SOLID: 'solid',\n  LINEAR: 'linear',\n  RADIAL: 'radial',\n};\n\nexport const DEFAULT_PAGE_BACKGROUND_COLOR = createSolid(255, 255, 255);\n"
  },
  {
    "path": "packages/elements/src/elementType.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ElementDefinition, ElementTypes } from './types';\n\n// @todo Create a custom hook to manage state.\nconst elementTypes: ElementTypes = {} as ElementTypes;\n\nfunction registerElementType(elementType: ElementDefinition) {\n  elementTypes[elementType.type] = elementType;\n}\n\nexport { registerElementType, elementTypes };\n"
  },
  {
    "path": "packages/elements/src/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './constants';\nexport * from './utils';\nexport * from './elementType';\nexport * from './types';\nexport * from './propTypes';\n"
  },
  {
    "path": "packages/elements/src/propTypes.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n/* eslint-disable no-restricted-imports -- Still used by other packages. */\nimport PropTypes, { type ValidationMap } from 'prop-types';\n/* eslint-enable no-restricted-imports -- Still used by other packages. */\nimport { PatternPropType } from '@googleforcreators/patterns';\nimport {\n  BackgroundAudioPropType,\n  ResourcePropTypes,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE, BACKGROUND_TEXT_MODE, OverlayType } from './constants';\n\nconst mask = PropTypes.shape({\n  type: PropTypes.string.isRequired,\n});\n\nconst link = PropTypes.shape({\n  url: PropTypes.string.isRequired,\n  desc: PropTypes.string,\n  needsProxy: PropTypes.bool,\n  icon: PropTypes.string,\n  rel: PropTypes.arrayOf(PropTypes.string),\n});\n\nconst box = PropTypes.exact({\n  x: PropTypes.number.isRequired,\n  y: PropTypes.number.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n  rotationAngle: PropTypes.number.isRequired,\n});\n\nconst flip = PropTypes.shape({\n  vertical: PropTypes.bool,\n  horizontal: PropTypes.bool,\n});\n\nconst StoryElementPropTypes: ValidationMap<unknown> = {\n  id: PropTypes.string.isRequired,\n  groupId: PropTypes.string,\n  type: PropTypes.string.isRequired,\n  x: PropTypes.number.isRequired,\n  y: PropTypes.number.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n  flip,\n  rotationAngle: PropTypes.number.isRequired,\n  mask,\n  link,\n  opacity: PropTypes.number,\n  lockAspectRatio: PropTypes.bool,\n  isBackground: PropTypes.bool,\n};\n\nconst element = PropTypes.shape(StoryElementPropTypes);\n\nconst page = PropTypes.shape({\n  id: PropTypes.string.isRequired,\n  // Temporary solution for animations. Better would be to move this\n  // prop type to the types package, but really?\n  animations: PropTypes.arrayOf(PropTypes.object),\n  elements: PropTypes.arrayOf(element),\n  overlay: PropTypes.oneOf(Object.values(OverlayType)),\n  backgroundAudio: PropTypes.shape({\n    resource: BackgroundAudioPropType,\n    loop: PropTypes.bool,\n    tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  }),\n});\n\nconst StoryLayerPropTypes = {\n  id: PropTypes.string.isRequired,\n  type: PropTypes.string.isRequired,\n};\n\nconst StoryMediaPropTypes = {\n  scale: PropTypes.number.isRequired,\n  focalX: PropTypes.number,\n  focalY: PropTypes.number,\n};\n\nconst layer = PropTypes.shape(StoryLayerPropTypes);\n\nconst image = PropTypes.shape({\n  ...StoryElementPropTypes,\n  ...StoryMediaPropTypes,\n  resource: ResourcePropTypes.imageResource,\n});\n\nconst video = PropTypes.shape({\n  ...StoryElementPropTypes,\n  ...StoryMediaPropTypes,\n  resource: ResourcePropTypes.videoResource,\n  poster: PropTypes.string,\n  tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  loop: PropTypes.bool,\n  volume: PropTypes.number,\n});\n\nconst gif = PropTypes.shape({\n  ...StoryElementPropTypes,\n  ...StoryMediaPropTypes,\n  resource: ResourcePropTypes.gifResource,\n});\n\nconst media = PropTypes.oneOfType([image, video, gif]);\n\nexport const FontPropType = PropTypes.shape({\n  family: PropTypes.string,\n  service: PropTypes.string,\n  weights: PropTypes.arrayOf(PropTypes.number),\n  styles: PropTypes.arrayOf(PropTypes.string),\n  // There's no built-in prop type validation for tuples.\n  variants: PropTypes.arrayOf(PropTypes.array),\n  fallbacks: PropTypes.array,\n});\n\nexport const PaddingPropType = PropTypes.shape({\n  horizontal: PropTypes.oneOfType([\n    PropTypes.number,\n    PropTypes.oneOf([MULTIPLE_VALUE]),\n  ]),\n  vertical: PropTypes.oneOfType([\n    PropTypes.number,\n    PropTypes.oneOf([MULTIPLE_VALUE]),\n  ]),\n  locked: PropTypes.oneOfType([\n    PropTypes.bool,\n    PropTypes.oneOf([MULTIPLE_VALUE]),\n  ]),\n});\n\nconst StoryTextElementPropTypes = {\n  content: PropTypes.string,\n  backgroundTextMode: PropTypes.oneOf(Object.values(BACKGROUND_TEXT_MODE)),\n  backgroundColor: PatternPropType,\n  font: FontPropType.isRequired,\n  fontSize: PropTypes.number,\n  lineHeight: PropTypes.number,\n  padding: PaddingPropType,\n  textAlign: PropTypes.string,\n  tagName: PropTypes.oneOf(['h1', 'h2', 'h3', 'p', 'auto']),\n};\n\nconst textContent = PropTypes.shape({\n  ...StoryTextElementPropTypes,\n});\n\nconst text = PropTypes.shape({\n  ...StoryElementPropTypes,\n  ...StoryTextElementPropTypes,\n});\n\nconst shape = PropTypes.shape({\n  ...StoryElementPropTypes,\n  backgroundColor: PatternPropType,\n});\n\nconst sticker = PropTypes.shape({\n  ...StoryElementPropTypes,\n  sticker: PropTypes.shape({\n    type: PropTypes.string.isRequired,\n  }),\n});\n\nconst background = PropTypes.shape({\n  ...StoryLayerPropTypes,\n  inner: element,\n});\n\nconst product = PropTypes.shape({\n  ...StoryElementPropTypes,\n});\n\nconst audioSticker = PropTypes.shape({\n  ...StoryElementPropTypes,\n});\n\nconst StoryPropTypes = {\n  mask,\n  link,\n  box,\n  page,\n  flip,\n  element,\n  layer,\n  textContent,\n  elements: {\n    image,\n    video,\n    gif,\n    media,\n    text,\n    shape,\n    sticker,\n    background,\n    product,\n    audioSticker,\n  },\n};\n\nexport { StoryPropTypes };\n"
  },
  {
    "path": "packages/elements/src/types/data.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { AudioResource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type { Page } from './page';\n\nexport type FontFamily = string;\n\nexport type FontStyle = 'normal' | 'italic' | 'regular';\n\nexport enum FontVariantStyle {\n  Normal = 0,\n  Italic = 1,\n}\n\nexport type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;\n\nexport type FontVariant = [FontVariantStyle, FontWeight];\n\nexport enum FontService {\n  Custom = 'custom',\n  GoogleFonts = 'fonts.google.com',\n  System = 'system',\n}\n\nexport interface FontMetrics {\n  upm: number;\n  asc: number;\n  des: number;\n  tAsc: number;\n  tDes: number;\n  tLGap: number;\n  wAsc: number;\n  wDes: number;\n  xH: number;\n  capH: number;\n  yMin: number;\n  yMax: number;\n  hAsc: number;\n  hDes: number;\n  lGap: number;\n}\n\nexport interface BaseFontData {\n  service: FontService;\n  family: FontFamily;\n  weights?: FontWeight[];\n  styles?: FontStyle[];\n  variants?: FontVariant[];\n  fallbacks?: string[];\n  metrics?: FontMetrics;\n}\n\nexport interface GoogleFontData extends BaseFontData {\n  service: FontService.GoogleFonts;\n}\n\nexport interface SystemFontData extends BaseFontData {\n  service: FontService.System;\n}\n\nexport interface CustomFontData extends BaseFontData {\n  service: FontService.Custom;\n  url: string;\n}\n\nexport type FontData = GoogleFontData | SystemFontData | CustomFontData;\n\nexport interface ProductImage {\n  alt: string;\n  url: string;\n}\n\nexport interface ProductData {\n  productId: string;\n  productBrand: string;\n  productDetails: string;\n  productImages: ProductImage[];\n  productPrice: number;\n  productPriceCurrency: string;\n  productTitle: string;\n  productUrl: string;\n  productIcon?: string;\n  aggregateRating?: {\n    ratingValue: number;\n    reviewCount: number;\n    reviewUrl: string;\n  };\n}\n\n// Data retrieved as part of the raw data from the backend, used for example in the templates, in migration.\nexport interface StoryData {\n  version: number;\n  pages: Page[];\n  autoAdvance: boolean;\n  defaultPageDuration: number;\n  currentStoryStyles: {\n    colors: Pattern[];\n  };\n  backgroundAudio?: {\n    resource: AudioResource;\n  };\n  fonts?: Record<string, FontData>;\n}\n"
  },
  {
    "path": "packages/elements/src/types/element.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Solid, Pattern } from '@googleforcreators/patterns';\nimport type {\n  Resource,\n  SequenceResource,\n  GifResource,\n  VideoResource,\n} from '@googleforcreators/media';\nimport type { ElementBox } from '@googleforcreators/units';\nimport type stickers from '@googleforcreators/stickers';\n\n/**\n * Internal dependencies\n */\nimport type { ElementType } from './elementType';\nimport type { Track } from './media';\nimport type {\n  ProductData,\n  GoogleFontData,\n  SystemFontData,\n  CustomFontData,\n} from './data';\n\nexport enum LinkType {\n  Regular = 'regular',\n  Branching = 'branching',\n}\n\nexport interface Link {\n  type?: LinkType;\n  pageId?: ElementId;\n  url: string;\n  desc?: string;\n  needsProxy?: boolean;\n  icon?: string | null;\n  rel?: string[];\n}\n\nexport interface Flip {\n  vertical: boolean;\n  horizontal: boolean;\n}\n\nexport interface Mask {\n  type: string;\n  // TODO(#12259): Remove these from the type & from templates.\n  showInLibrary?: boolean;\n  name?: string;\n  path?: string;\n  ratio?: number;\n  iconPath?: string;\n  iconRatio?: number;\n  supportsBorder?: boolean;\n}\n\nexport interface Border {\n  top: number;\n  right: number;\n  bottom: number;\n  left: number;\n  locked?: boolean;\n  lockedWidth?: boolean;\n  color?: Solid;\n}\n\nexport interface BorderRadius {\n  topLeft: number;\n  topRight: number;\n  bottomLeft: number;\n  bottomRight: number;\n  locked: boolean;\n}\n\nexport type ElementId = string;\n\nexport interface Element extends ElementBox {\n  id: ElementId;\n  type: ElementType;\n  mask?: Mask;\n  link?: Link;\n  opacity?: number;\n  lockAspectRatio?: boolean;\n  flip?: Flip;\n  groupId?: string;\n  border?: Border;\n  borderRadius?: BorderRadius;\n  layerName?: string;\n  isLocked?: boolean;\n  isHidden?: boolean;\n}\n\nexport interface LinkableElement extends Element {\n  link: Link;\n}\n\nexport interface DefaultBackgroundElement extends Element {\n  isDefaultBackground: boolean;\n  backgroundColor: Solid;\n}\n\nexport interface BackgroundableElement extends Element {\n  isBackground?: boolean;\n}\n\nexport interface MediaElement extends BackgroundableElement {\n  resource: Resource;\n  scale?: number;\n  focalX?: number;\n  focalY?: number;\n  alt?: string;\n}\n\nexport interface SequenceMediaElement extends MediaElement {\n  resource: SequenceResource;\n}\n\nexport interface VideoElement extends SequenceMediaElement {\n  type: ElementType.Video;\n  tracks: Track[];\n  resource: VideoResource;\n  poster?: string;\n  loop?: boolean;\n  volume: number;\n}\n\nexport interface GifElement extends SequenceMediaElement {\n  type: ElementType.Gif;\n  poster?: string;\n  resource: GifResource;\n}\n\nexport interface ImageElement extends MediaElement {\n  type: ElementType.Image;\n  alt?: string;\n}\n\nexport interface OverlayableElement extends Element {\n  overlay?: Pattern | null;\n}\n\nexport interface ProductElement extends Element {\n  type: ElementType.Product;\n  product: ProductData;\n}\n\nexport interface StickerElement extends Element {\n  type: ElementType.Sticker;\n  sticker: {\n    type: keyof typeof stickers;\n  };\n}\n\nexport type TextElementFont = GoogleFontData | SystemFontData | CustomFontData;\n\nexport interface Padding {\n  horizontal: number;\n  vertical: number;\n  locked: boolean;\n  hasHiddenPadding?: boolean;\n}\n\nexport type TextAlign = 'center' | 'justify' | 'left' | 'right';\nexport interface TextElement extends Element {\n  backgroundColor: Solid;\n  content: string;\n  font: TextElementFont;\n  fontSize: number;\n\n  backgroundTextMode?: string;\n  tagName?: 'h1' | 'h2' | 'h3' | 'p' | 'auto';\n  padding?: Padding;\n  marginOffset: number;\n  lineHeight: number;\n  textAlign: TextAlign;\n\n  type: ElementType.Text;\n  fontStyle?: 'italic' | 'normal';\n  fontWeight?: number;\n}\n\nexport interface AudioStickerElement extends Element {\n  type: ElementType.AudioSticker;\n  sticker: 'headphone-cat' | 'tape-player' | 'loud-speaker' | 'audio-cloud';\n  style: 'none' | 'outline' | 'dropshadow';\n  size: 'large' | 'small';\n}\n\nexport interface ShapeElement extends Element {\n  type: ElementType.Shape;\n  backgroundColor?: Pattern;\n  isBackground?: boolean;\n  isDefaultBackground?: boolean;\n}\n"
  },
  {
    "path": "packages/elements/src/types/elementDefinition.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ElementBox } from '@googleforcreators/units';\nimport type {\n  GifResource,\n  ImageResource,\n  Resource,\n  VideoResource,\n  ResourceId,\n} from '@googleforcreators/media';\nimport type { RefObject, VoidFunctionComponent } from 'react';\nimport type { Pattern } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport type { Element, ElementId, GifElement, VideoElement } from './element';\nimport type { ElementType } from './elementType';\nimport type { FontData, FontStyle, FontWeight } from './data';\n\ninterface FontConfig {\n  fontStyle: FontStyle;\n  fontWeight: FontWeight;\n  content: string;\n  font: FontData;\n}\n\nexport interface EditProps<E extends Element> {\n  element: E;\n  box: ElementBox;\n  editWrapper?: HTMLElement;\n  onResize: () => void;\n  setLocalProperties: (properties: Partial<E>) => void;\n  getProxiedUrl: (\n    resource: Pick<Resource, 'needsProxy'>,\n    src?: string\n  ) => string | null;\n  isRTL: boolean;\n  isTrimMode: boolean;\n  topOffset: number;\n  resource?: E extends VideoElement\n    ? VideoResource\n    : E extends GifElement\n      ? GifResource\n      : ImageResource;\n  setVideoNode: (node: HTMLVideoElement) => void;\n  updateElementById: (update: {\n    elementId: ElementId;\n    properties: Partial<E>;\n  }) => void;\n  deleteSelectedElements: () => void;\n  maybeEnqueueFontStyle: (fonts: FontConfig[]) => Promise<boolean>;\n  zIndexCanvas: Record<string, number>;\n  scaleMin: number;\n  scaleMax: number;\n}\n\ninterface EditingState {\n  hasEditMenu?: boolean;\n  showOverflow?: boolean;\n  selectAll?: boolean;\n  offset?: number;\n}\n\nexport interface FrameProps<E extends Element> {\n  wrapperRef: RefObject<HTMLElement>;\n  element: E;\n  box: ElementBox;\n  isOnlySelectedElement: boolean;\n  setEditingElementWithState: (id: string, state: EditingState) => void;\n}\n\nexport interface OutputProps<E extends Element> {\n  element: E;\n  box: ElementBox;\n  flags: Record<string, boolean>;\n}\n\nexport interface LayerIconProps<E extends Element> {\n  element: E;\n  getProxiedUrl: (\n    resource: Pick<Resource, 'needsProxy'>,\n    src?: string\n  ) => string | null;\n  currentPageBackgroundColor: Pattern;\n  // Only provided for videos.\n  showVideoPreviewAsBackup?: boolean;\n}\n\nexport type LayerTextFunction<E> = (element: E) => string;\nexport type TextContentFunction<E> = (element: E) => string;\n\nexport interface DisplayProps<E extends Element> {\n  element: E;\n  previewMode: boolean;\n  box: ElementBox;\n  getProxiedUrl: (\n    resource: Pick<Resource, 'needsProxy'>,\n    src?: string\n  ) => string | null;\n  isCurrentResourceProcessing?: (resourceId: ResourceId) => boolean;\n  isCurrentResourceUploading?: (resourceId: ResourceId) => boolean;\n  maybeEnqueueFontStyle: (fonts: FontConfig[]) => Promise<boolean>;\n  siblingCount: number;\n  renderResourcePlaceholder: (args: {\n    blurHash?: string;\n    baseColor?: string;\n  }) => void;\n  cdnUrl: string;\n}\n\nexport type Direction = [0 | 1, 0 | 1];\n\nexport interface ElementDefinition<E extends Element = Element> {\n  type: ElementType;\n  name: string;\n  isMedia?: boolean;\n  getLayerText: LayerTextFunction<E>;\n  defaultAttributes: Partial<E>;\n  // Only text & media elements have an edit mode.\n  Edit?: VoidFunctionComponent<EditProps<E>>;\n  Frame?: VoidFunctionComponent<FrameProps<E>>;\n  Output: VoidFunctionComponent<OutputProps<E>>;\n  LayerIcon: VoidFunctionComponent<LayerIconProps<E>>;\n  // TODO: Make mandatory? Used for copy/pasting.\n  TextContent?: TextContentFunction<E>;\n  Display: VoidFunctionComponent<DisplayProps<E>>;\n  canFlip: boolean;\n  isMaskable: boolean;\n  isAspectAlwaysLocked: boolean;\n  hasDesignMenu: boolean;\n  hasDuplicateMenu: boolean;\n  hasEditMode: boolean;\n  hasEditModeIfLocked: boolean;\n  hasEditModeMoveable: boolean;\n  editModeGrayout: boolean;\n  resizeRules: {\n    vertical: boolean;\n    horizontal: boolean;\n    diagonal: boolean;\n    minWidth: number;\n    minHeight: number;\n  };\n  panels: string[];\n  updateForResizeEvent?: (\n    element: E,\n    direction: Direction,\n    newWidth: number,\n    newHeight: number\n  ) => { height: number };\n}\n\nexport type ElementTypes<E extends Element = Element> = Record<\n  E['type'],\n  ElementDefinition<E>\n>;\n"
  },
  {
    "path": "packages/elements/src/types/elementType.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ElementType {\n  Text = 'text',\n  Image = 'image',\n  Video = 'video',\n  Gif = 'gif',\n  Sticker = 'sticker',\n  Shape = 'shape',\n  Product = 'product',\n  AudioSticker = 'audioSticker',\n}\n"
  },
  {
    "path": "packages/elements/src/types/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './data';\nexport * from './element';\nexport * from './elementType';\nexport * from './elementDefinition';\nexport * from './page';\nexport * from './story';\nexport * from './taxonomies';\nexport * from './media';\n"
  },
  {
    "path": "packages/elements/src/types/media.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type Track = {\n  id: string;\n  track: string | null;\n  trackId?: number;\n  kind?: string;\n  srclang?: string;\n  label?: string;\n  needsProxy?: boolean;\n};\n"
  },
  {
    "path": "packages/elements/src/types/page.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { StoryAnimation } from '@googleforcreators/animation';\nimport type { AudioResource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type { DefaultBackgroundElement, Element, ElementId } from './element';\nimport type { Track } from './media';\n\nexport interface Group {\n  name: string;\n  isLocked: boolean;\n  isCollapsed?: boolean;\n}\n\nexport type BackgroundAudio = {\n  resource: AudioResource;\n  tracks?: Track[];\n  loop?: boolean;\n};\n\nexport type Groups = Record<string, Group>;\n\nexport type PageAttachment = {\n  url: string;\n  ctaText?: string;\n  theme?: 'light' | 'dark';\n  icon?: string;\n  rel?: string[];\n  needsProxy?: boolean;\n};\n\nexport type ShoppingAttachment = {\n  ctaText: string;\n  theme?: 'light' | 'dark';\n};\n\nexport interface Page {\n  id: ElementId;\n  elements: Element[];\n  defaultBackgroundElement?: DefaultBackgroundElement;\n  animations?: StoryAnimation[];\n  backgroundColor: Pattern;\n  groups?: Groups;\n  backgroundAudio?: BackgroundAudio;\n  pageAttachment?: PageAttachment;\n  shoppingAttachment?: ShoppingAttachment;\n  advancement?: {\n    autoAdvance?: boolean;\n    pageDuration?: number;\n  };\n}\n"
  },
  {
    "path": "packages/elements/src/types/story.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { AudioResource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type { FontData } from './data';\nimport type { Term } from './taxonomies';\n\ninterface FeaturedMedia {\n  id: number;\n  height: number;\n  width: number;\n  url: string;\n  needsProxy?: boolean;\n  isExternal?: boolean;\n}\ninterface PublisherLogo {\n  id: number;\n  height: number;\n  width: number;\n  url: string;\n}\n\ninterface Author {\n  id: number;\n  name: string;\n}\ninterface CurrentStyles {\n  colors: Pattern[];\n}\ninterface GlobalStyles {\n  colors: Pattern[];\n  textStyles: Partial<Text>;\n}\n\n// General story post data as it is in the story state and history entry.\nexport interface Story {\n  storyId: number;\n  title: string;\n  author: Author;\n  date: null | string;\n  origDate: null | string;\n  modified: string;\n  excerpt: string;\n  slug: string;\n  link: string;\n  extras: Record<string, unknown>;\n  featuredMedia: FeaturedMedia;\n  permalinkConfig: null | {\n    prefix: string;\n    suffix: string;\n  };\n  publisherLogo: PublisherLogo;\n  previewLink: string;\n  editLink: string;\n  password: string;\n  embedPostLink: string;\n  revisions: {\n    count: number;\n  };\n  currentStoryStyles: CurrentStyles;\n  globalStoryStyles: GlobalStyles;\n  terms: Term[] | null;\n  status: string;\n  backgroundAudio?: {\n    resource: AudioResource;\n  };\n  fonts: Record<string, FontData>;\n  autoAdvance?: boolean;\n  defaultPageDuration?: number;\n}\n"
  },
  {
    "path": "packages/elements/src/types/taxonomies.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type TermId = number;\n\nexport type TaxonomySlug = string;\n\nexport type TermSlug = string;\n\nexport type Taxonomy = {\n  name: string;\n  slug: TaxonomySlug;\n  capabilities: Record<string, string>;\n  description?: string;\n  labels: Record<string, string>;\n  types: string[];\n  showCloud?: boolean;\n  hierarchical: boolean;\n  restBase: string;\n  restNamespace: string;\n  visibility: Record<string, boolean>;\n  restPath?: string;\n};\n\nexport type Term = {\n  id: TermId;\n  link: string;\n  name: string;\n  slug: TermSlug;\n  taxonomy: TaxonomySlug;\n  parent?: number;\n  _links: Record<string, string>;\n};\n"
  },
  {
    "path": "packages/elements/src/utils/createNewElement.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ElementBox } from '@googleforcreators/units';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport type { DefaultBackgroundElement, Element, ElementType } from '../types';\n\n/**\n * Internal dependencies\n */\nimport getDefinitionForType from './getDefinitionForType';\n\nfunction isDefaultBackgroundElement(\n  e: Partial<Element>\n): e is DefaultBackgroundElement {\n  return 'isDefaultBackground' in e;\n}\ntype Attributes = Partial<Element> & ElementBox;\n\n// If we're copying an existing default background element into a new one,\n// we should ignore the default background color from the element (which will\n// be a shape)\nfunction getDefaultAttributes(\n  defaultAttributes: Partial<Element>,\n  attributes: Attributes\n): Partial<Element> {\n  if (\n    isDefaultBackgroundElement(attributes) &&\n    isDefaultBackgroundElement(defaultAttributes) &&\n    attributes.isDefaultBackground\n  ) {\n    const { backgroundColor, ...defaultAttributesWithoutColor } =\n      defaultAttributes;\n    return defaultAttributesWithoutColor;\n  }\n  return defaultAttributes;\n}\n\nfunction createNewElement(\n  type: ElementType,\n  attributes: Attributes = {\n    x: 0,\n    y: 0,\n    width: 1,\n    height: 1,\n    rotationAngle: 0,\n  }\n): Element {\n  const element = getDefinitionForType(type);\n  if (!element) {\n    throw new Error(`Unknown element type: ${type}`);\n  }\n  const defaultAttributes = getDefaultAttributes(\n    element.defaultAttributes,\n    attributes\n  );\n  const newElement: Element = {\n    ...defaultAttributes,\n    ...attributes,\n    type,\n    id: uuidv4(),\n  };\n\n  return newElement;\n}\n\nexport default createNewElement;\n"
  },
  {
    "path": "packages/elements/src/utils/createPage.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_PAGE_BACKGROUND_COLOR } from '../constants';\nimport { ElementType, type Page } from '../types';\nimport createNewElement from './createNewElement';\n\nconst createPage = (pageProps: Partial<Page> | null = null): Page => {\n  const backgroundElementProps = {\n    // The values of x, y, width, height are irrelevant here, however, need to be set.\n    x: 1,\n    y: 1,\n    width: 1,\n    height: 1,\n    rotationAngle: 0,\n    mask: {\n      type: 'rectangle',\n    },\n    isBackground: true,\n    isDefaultBackground: true,\n  };\n  const backgroundElement = createNewElement(\n    ElementType.Shape,\n    backgroundElementProps\n  );\n\n  const page: Page = {\n    elements: [backgroundElement],\n    backgroundColor: DEFAULT_PAGE_BACKGROUND_COLOR,\n    ...pageProps,\n    // id must be overridden even if present in partial\n    id: uuidv4(),\n  };\n\n  return page;\n};\n\nexport default createPage;\n"
  },
  {
    "path": "packages/elements/src/utils/duplicateElement.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport type { StoryAnimation } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport type { Element } from '../types';\nimport createNewElement from './createNewElement';\nimport getOffsetCoordinates from './getOffsetCoordinates';\n\n/**\n * returns a copy of element and element's animations as well\n * as offsetting the elements position if the new element is based\n * on any existing element on the page.\n *\n * @param args - named arguments\n * @param args.element - story element to be copied\n * @param args.animations - set of existing animations\n * @param args.currentElements - set of existing story elements\n * @param args.offsetBase - a point from which offset will be applied\n * @return cloned story element and associated cloned animations\n */\ninterface DuplicateElementArgs {\n  element: Element;\n  animations?: StoryAnimation[];\n  currentElements?: Element[];\n  offsetBase?: { x: number; y: number };\n}\ninterface DuplicateElementReturn {\n  element: Element;\n  elementAnimations: StoryAnimation[];\n}\nfunction duplicateElement({\n  element,\n  animations = [],\n  currentElements = [],\n  offsetBase,\n}: DuplicateElementArgs): DuplicateElementReturn {\n  const { type, ...attrs } = element;\n  const duplicatedElement = createNewElement(type, attrs);\n\n  // update position with an offset if copied element is on canvas\n  if (currentElements.map(({ id }) => id).includes(element.id)) {\n    // use provided base offset if passed or offset from element's position\n    const pastedXY = getOffsetCoordinates(\n      offsetBase?.x ?? element.x,\n      offsetBase?.y ?? element.y\n    );\n    duplicatedElement.x = pastedXY.x;\n    duplicatedElement.y = pastedXY.y;\n  }\n\n  const duplicatedAnimations = animations\n    .filter((animation) => animation.targets.includes(element.id))\n    .map((animation) => ({\n      ...animation,\n      targets: [duplicatedElement.id],\n      id: uuidv4(),\n    }))\n    .filter((animation) => animation.targets.length > 0);\n\n  return {\n    element: duplicatedElement,\n    elementAnimations: duplicatedAnimations,\n  };\n}\n\nexport default duplicateElement;\n"
  },
  {
    "path": "packages/elements/src/utils/duplicatePage.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Page } from '../types';\nimport createPage from './createPage';\nimport duplicateElement from './duplicateElement';\n\n// Required<> is a reverse Partial<> - removing the optional\n// part from the animations property\ntype ElementsAndAnimationsOnly = Required<\n  Pick<Page, 'elements' | 'animations'>\n>;\n\nconst duplicatePage = (oldPage: Page) => {\n  const {\n    elements: oldElements,\n    animations: oldAnimations = [],\n    ...rest\n  } = oldPage;\n\n  const elementAndAnimations: ElementsAndAnimationsOnly =\n    oldElements.reduce<ElementsAndAnimationsOnly>(\n      ({ elements, animations }, oldElement) => {\n        const { element, elementAnimations } = duplicateElement({\n          element: oldElement,\n          animations: oldAnimations,\n        });\n        return {\n          elements: [...elements, element],\n          animations: [...animations, ...elementAnimations],\n        };\n      },\n      {\n        elements: [],\n        animations: [],\n      }\n    );\n\n  const newAttributes: Partial<Page> = {\n    ...elementAndAnimations,\n    ...rest,\n  };\n\n  return createPage(newAttributes);\n};\n\nexport default duplicatePage;\n"
  },
  {
    "path": "packages/elements/src/utils/elementIs.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Draft } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  BackgroundableElement,\n  DefaultBackgroundElement,\n  Element,\n  MediaElement,\n  ProductElement,\n  SequenceMediaElement,\n  StickerElement,\n  TextElement,\n  VideoElement,\n  GifElement,\n  LinkableElement,\n  OverlayableElement,\n} from '../types';\nimport { ElementType } from '../types';\n\nfunction isMediaElement(e: Element): e is MediaElement;\nfunction isMediaElement(e: Draft<Element>): e is Draft<MediaElement>;\nfunction isMediaElement(e: Element): e is MediaElement {\n  return 'resource' in e && Boolean(e.resource);\n}\n\nfunction isTextElement(e: Element): e is TextElement;\nfunction isTextElement(e: Draft<Element>): e is Draft<TextElement>;\nfunction isTextElement(e: Element): e is TextElement {\n  return 'font' in e && Boolean(e.font);\n}\n\nfunction isDefaultBackgroundElement(e: Element): e is DefaultBackgroundElement;\nfunction isDefaultBackgroundElement(\n  e: Draft<Element>\n): e is Draft<DefaultBackgroundElement>;\nfunction isDefaultBackgroundElement(e: Element): e is DefaultBackgroundElement {\n  return 'isDefaultBackground' in e && Boolean(e.isDefaultBackground);\n}\n\nfunction isBackgroundable(e: Element): e is BackgroundableElement;\nfunction isBackgroundable(e: Draft<Element>): e is Draft<BackgroundableElement>;\nfunction isBackgroundable(e: Element): e is BackgroundableElement {\n  // All media is backgroundable.\n  return (\n    // Property can be undefined if e is of type Draft<Element>.\n    ('isBackground' in e && typeof e.isBackground !== 'undefined') ||\n    isMediaElement(e)\n  );\n}\n\nfunction isProduct(e: Element): e is ProductElement;\nfunction isProduct(e: Draft<Element>): e is Draft<ProductElement>;\nfunction isProduct(e: Element): e is ProductElement {\n  return 'product' in e && Boolean(e.product);\n}\n\nfunction isSequenceMediaElement(e: MediaElement): e is SequenceMediaElement;\nfunction isSequenceMediaElement(\n  e: Draft<MediaElement>\n): e is Draft<SequenceMediaElement>;\nfunction isSequenceMediaElement(e: MediaElement): e is SequenceMediaElement {\n  return (\n    ('poster' in e.resource && Boolean(e.resource.poster)) ||\n    ('length' in e.resource && Boolean(e.resource.length))\n  );\n}\n\nfunction isSticker(e: Element): e is StickerElement {\n  return 'sticker' in e && Boolean(e.sticker);\n}\n\nfunction isVideo(e: Draft<Element>): e is Draft<VideoElement>;\nfunction isVideo(e: Element): e is VideoElement {\n  return (\n    isMediaElement(e) &&\n    isSequenceMediaElement(e) &&\n    e.type === ElementType.Video\n  );\n}\n\nfunction isGif(e: Draft<Element>): e is Draft<GifElement>;\nfunction isGif(e: Element): e is GifElement {\n  return (\n    isMediaElement(e) && isSequenceMediaElement(e) && e.type === ElementType.Gif\n  );\n}\n\nfunction isLinkable(e: Element): e is LinkableElement;\nfunction isLinkable(e: Draft<Element>): e is Draft<LinkableElement>;\nfunction isLinkable(e: Element): e is LinkableElement {\n  return (\n    'link' in e && typeof e.link !== 'undefined' && e.link?.url?.length > 0\n  );\n}\n\nfunction isOverlayable(e: Element): e is OverlayableElement;\nfunction isOverlayable(e: Draft<Element>): e is Draft<OverlayableElement>;\nfunction isOverlayable(e: Element): e is OverlayableElement {\n  return 'overlay' in e && typeof e.overlay !== 'undefined';\n}\n\nconst elementIs = {\n  media: isMediaElement,\n  text: isTextElement,\n  defaultBackground: isDefaultBackgroundElement,\n  backgroundable: isBackgroundable,\n  product: isProduct,\n  sequenceMedia: isSequenceMediaElement,\n  sticker: isSticker,\n  video: isVideo,\n  gif: isGif,\n  linkable: isLinkable,\n  overlayable: isOverlayable,\n};\n\nexport default elementIs;\n"
  },
  {
    "path": "packages/elements/src/utils/getDefinitionForType.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { elementTypes } from '../elementType';\nimport type { ElementTypes } from '../types';\n\nfunction getDefinitionForType<T extends keyof ElementTypes>(\n  type: T\n): ElementTypes[T] {\n  const definition = elementTypes[type];\n  if (!definition) {\n    throw new Error(`No element definition found for '${type}'`);\n  }\n  return definition;\n}\n\nexport default getDefinitionForType;\n"
  },
  {
    "path": "packages/elements/src/utils/getLayerName.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { Element } from '../types';\nimport getDefinitionForType from './getDefinitionForType';\nimport elementIs from './elementIs';\n\n/**\n * Returns the layer name based on the element properties.\n *\n * @param element Element.\n * @return Layer name.\n */\nfunction getLayerName(element: Element) {\n  if (element.layerName) {\n    return element.layerName;\n  }\n\n  if (elementIs.backgroundable(element) && element.isBackground) {\n    return __('Background', 'web-stories');\n  }\n\n  return getDefinitionForType(element.type)?.getLayerText(element);\n}\n\nexport default getLayerName;\n"
  },
  {
    "path": "packages/elements/src/utils/getOffsetCoordinates.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { PAGE_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\n\n/**\n * Gets x, y values for cloned element, ensuring it's not added out of the page.\n *\n * @param originX Original X.\n * @param originY Original Y.\n * @return Coordinates.\n */\nexport default function getOffsetCoordinates(originX: number, originY: number) {\n  const placementDiff = 30;\n  const allowedBorderDistance = 20;\n  const x = originX + placementDiff;\n  const y = originY + placementDiff;\n  return {\n    x: PAGE_WIDTH - x > allowedBorderDistance ? x : placementDiff,\n    y: PAGE_HEIGHT - y > allowedBorderDistance ? y : placementDiff,\n  };\n}\n"
  },
  {
    "path": "packages/elements/src/utils/getTransformFlip.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Flip } from '../types';\n\n/**\n * Returns transform scale value based on the flip setting.\n *\n * @param flip Flip value.\n * @return CSS transform scale value.\n */\nfunction getTransformFlip(flip?: Flip) {\n  // If no flip\n  if (!flip || (!flip.horizontal && !flip.vertical)) {\n    return null;\n  }\n\n  const xSign = flip.horizontal ? '-' : '';\n  const ySign = flip.vertical ? '-' : '';\n  return `scale3d(${xSign}1, ${ySign}1, 1)`;\n}\n\nexport default getTransformFlip;\n"
  },
  {
    "path": "packages/elements/src/utils/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as getDefinitionForType } from './getDefinitionForType';\nexport { default as createNewElement } from './createNewElement';\nexport { default as createPage } from './createPage';\nexport { default as duplicatePage } from './duplicatePage';\nexport { default as isElementBelowLimit } from './isElementBelowLimit';\nexport { default as getTransformFlip } from './getTransformFlip';\nexport { default as getLayerName } from './getLayerName';\nexport { default as duplicateElement } from './duplicateElement';\nexport { default as getOffsetCoordinates } from './getOffsetCoordinates';\nexport { default as elementIs } from './elementIs';\n"
  },
  {
    "path": "packages/elements/src/utils/isElementBelowLimit.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  DANGER_ZONE_HEIGHT,\n  FULLBLEED_HEIGHT,\n  getCorners,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport type { Element } from '../types';\nimport elementIs from './elementIs';\n\nfunction isElementBelowLimit(element: Element, verifyLink = true) {\n  if (verifyLink && !elementIs.linkable(element)) {\n    return false;\n  }\n\n  const limit = FULLBLEED_HEIGHT * 0.8 - DANGER_ZONE_HEIGHT;\n  const { x, y, width, height, rotationAngle } = element;\n  const points = getCorners(rotationAngle, x, y, width, height);\n  return Object.values(points).some((coord) => coord.y > limit);\n}\nexport default isElementBelowLimit;\n"
  },
  {
    "path": "packages/elements/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../animation\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../media\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../stickers\" },\n    { \"path\": \"../units\" }\n  ],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/eslint-import-resolver/README.md",
    "content": "# eslint-import-resolver\n\nCustom resolver for [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import) to resolve packages locally in a monorepo.\n\nExample usage:\n\n```json\n{\n  \"settings\": {\n    \"import/resolver\": {\n      \"@web-stories-wp/eslint-import-resolver\": {\n        \"mapping\": {\n          \"^@foo\\\\/(.*)\": \"./packages/$1/src/\"\n        }\n      }\n    }\n  }\n}\n```\n\nWith this config, a package named `@foo/bar` will be looked up in `packages/bar/src`.\n"
  },
  {
    "path": "packages/eslint-import-resolver/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/eslint-import-resolver\",\n  \"description\": \"Custom resolver for eslint-plugin-import for monorepos\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"jest\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/eslint-import-resolver/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/eslint-plugin-resolver\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.cjs\",\n  \"dependencies\": {\n    \"eslint-import-resolver-node\": \"^0.3.9\"\n  }\n}\n"
  },
  {
    "path": "packages/eslint-import-resolver/src/index.cjs",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst path = require('path');\nconst nodeResolver = require('eslint-import-resolver-node');\n\nexports.interfaceVersion = 2;\n\nexports.resolve = (source, file, config) => {\n  function nodeResolve(src) {\n    return nodeResolver.resolve(src, file, {\n      ...config,\n      extensions: ['.tsx', '.ts', '.mjs', '.js', '.json', '.node'],\n    });\n  }\n\n  if (!config.mapping) {\n    return nodeResolve(source);\n  }\n\n  for (const [regex, dir] of Object.entries(config.mapping)) {\n    // eslint-disable-next-line security/detect-non-literal-regexp\n    const sourceLocation = source.replace(new RegExp(regex), dir);\n    const result = nodeResolve(path.resolve(sourceLocation));\n\n    if (result.found) {\n      return result;\n    }\n  }\n\n  return nodeResolve(source);\n};\n"
  },
  {
    "path": "packages/fonts/.npmignore",
    "content": "scripts\nsrc\n"
  },
  {
    "path": "packages/fonts/README.md",
    "content": "# Fonts\n\nProvides a list of system fonts and fonts available from Google Fonts, prepared for use in the Web Stories editor.\n\nThe list, `font.json`, contains additional information like metrics for each font, and is updated regularly using an automated CI task.\n\nTo update the list, run `GOOGLE_FONTS_API_KEY=yourapikey node index.js`.\n"
  },
  {
    "path": "packages/fonts/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/fonts\",\n  \"description\": \"A list of curated font names as well as all current Google Fonts including their font metrics.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"fonts\",\n    \"google fonts\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/fonts/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/fonts\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \"./fonts.json\": {\n      \"default\": \"./src/fonts.json\"\n    },\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"exports\": {\n    \"./fonts.json\": {\n      \"import\": \"./dist-module/fonts.json\",\n      \"require\": \"./dist/fonts.json\"\n    },\n    \".\": {\n      \"import\": \"./dist-module/index.js\",\n      \"require\": \"./dist/index.js\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/src/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"devDependencies\": {\n    \"@types/opentype.js\": \"^1.3.8\",\n    \"opentype.js\": \"^1.3.4\"\n  },\n  \"scripts\": {\n    \"update-fonts\": \"bun scripts/cli.ts ./src/fonts.json\"\n  }\n}\n"
  },
  {
    "path": "packages/fonts/scripts/cli.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint-disable no-console */\n\n/**\n * Internal dependencies\n */\nimport buildFonts from './utils/buildFonts';\n\nif (!process.env.GOOGLE_FONTS_API_KEY) {\n  throw new Error('Google Fonts API key missing!');\n}\n\nconst args = process.argv.slice(2);\nconst file = args[0] ? args[0] : undefined;\n\nif (!file) {\n  throw new Error('File path was not provided');\n}\n\nawait buildFonts(file);\n\nconsole.log('Web fonts updated!');\n\n/* eslint-enable no-console */\n"
  },
  {
    "path": "packages/fonts/scripts/utils/buildFonts.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { writeFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport { SYSTEM_FONTS } from './constants';\nimport normalizeFont from './normalizeFont';\nimport getFontMetrics from './getFontMetrics';\nimport type { RawFont } from './types';\n\nconst GOOGLE_WEB_FONTS_API = 'https://www.googleapis.com/webfonts/v1/webfonts';\n\n/**\n * Main function to build the fonts list.\n *\n * @param targetFile Path to the target file to be written.\n */\nasync function buildFonts(targetFile: string) {\n  const url = new URL(GOOGLE_WEB_FONTS_API);\n  url.searchParams.append('fields', 'items');\n  url.searchParams.append('prettyPrint', 'false');\n  url.searchParams.append('key', process.env.GOOGLE_FONTS_API_KEY ?? '');\n\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  const response = await fetch(url.toString());\n\n  if (!response.ok) {\n    return;\n  }\n\n  const rawFonts = (await response.json()) as { items: RawFont[] };\n\n  if (!Object.prototype.hasOwnProperty.call(rawFonts, 'items')) {\n    return;\n  }\n\n  const googleFonts = await Promise.all(\n    rawFonts.items.map(async (font: RawFont) => {\n      const normalizedFont = normalizeFont(font);\n\n      const fontFileURL =\n        font.files['regular'] ||\n        font.files[400] ||\n        font.files[Object.keys(font.files)[0]];\n\n      let fontMetrics = {};\n      try {\n        fontMetrics = await getFontMetrics(fontFileURL);\n      } catch (err) {\n        // eslint-disable-next-line no-console -- Surface error for debugging.\n        console.error(\n          `Error loading font metrics for \"${font.family}\" (${fontFileURL})`,\n          err\n        );\n      }\n\n      process.stdout.write('.');\n\n      return {\n        ...normalizedFont,\n        metrics: fontMetrics,\n      };\n    })\n  );\n\n  // Force newlines after the dots.\n  process.stdout.write('\\n');\n\n  const fonts = [...SYSTEM_FONTS, ...googleFonts];\n  fonts.sort((a, b) => a.family.localeCompare(b.family));\n\n  writeFileSync(targetFile, JSON.stringify(fonts));\n}\n\nexport default buildFonts;\n"
  },
  {
    "path": "packages/fonts/scripts/utils/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Font, FontMetrics, FontStyle, FontWeight } from './types';\n\nconst DEFAULT_ATTRIBUTES = {\n  weights: [400, 700] as FontWeight[],\n  styles: ['italic', 'regular'] as FontStyle[],\n  service: 'system',\n};\n\nexport const SYSTEM_FONTS: Font[] = [\n  {\n    family: 'Arial',\n    fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1854,\n      des: -434,\n      tAsc: 1491,\n      tDes: -431,\n      tLGap: 307,\n      wAsc: 1854,\n      wDes: 1854,\n      xH: 1062,\n      capH: 1467,\n      yMin: -665,\n      yMax: 2060,\n      hAsc: 1854,\n      hDes: -434,\n      lGap: 67,\n    } as FontMetrics,\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Arial Black',\n    fallbacks: ['Arial Black', 'Arial Bold', 'Gadget', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 2254,\n      des: -634,\n      tAsc: 1466,\n      tDes: 434,\n      tLGap: 291,\n      wAsc: 2254,\n      wDes: 2254,\n      xH: 1062, // from Arial\n      capH: 1467, // from Arial\n      yMin: -628,\n      yMax: 2219,\n      hAsc: 2254,\n      hDes: -634,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Arial Narrow',\n    fallbacks: ['Arial', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1916,\n      des: -434,\n      tAsc: 1491,\n      tDes: -431,\n      tLGap: 269,\n      wAsc: 1888,\n      wDes: 1888,\n      xH: 1062, // from Arial\n      capH: 1467, // from Arial\n      yMin: -628,\n      yMax: 2224,\n      hAsc: 1916,\n      hDes: -434,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Baskerville',\n    fallbacks: [\n      'Baskerville Old Face',\n      'Hoefler Text',\n      'Garamond',\n      'Times New Roman',\n      'serif',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1839,\n      des: -504,\n      tAsc: 1376,\n      tDes: -504,\n      tLGap: 311,\n      wAsc: 1839,\n      wDes: 1839,\n      xH: 819,\n      capH: 1356,\n      yMin: -504,\n      yMax: 1869,\n      hAsc: 1839,\n      hDes: -504,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Brush Script MT',\n    fallbacks: ['cursive'],\n    metrics: {\n      upm: 2048,\n      asc: 1820,\n      des: -692,\n      tAsc: 1229,\n      tDes: -506,\n      tLGap: 456,\n      wAsc: 1820,\n      wDes: 1820,\n      xH: undefined,\n      capH: undefined,\n      yMin: -692,\n      yMax: 1983,\n      hAsc: 1820,\n      hDes: -692,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Copperplate',\n    fallbacks: ['Copperplate Gothic Light', 'fantasy'],\n    metrics: {\n      upm: 1000,\n      asc: 763,\n      des: -248,\n      tAsc: 763,\n      tDes: -250,\n      tLGap: 20,\n      wAsc: 763,\n      wDes: 763,\n      xH: 440,\n      capH: 526,\n      yMin: -248,\n      yMax: 924,\n      hAsc: 763,\n      hDes: -248,\n      lGap: 19,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Courier New',\n    fallbacks: [\n      'Courier',\n      'Lucida Sans Typewriter',\n      'Lucida Typewriter',\n      'monospace',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1705,\n      des: -615,\n      tAsc: 1255,\n      tDes: -386,\n      tLGap: 0,\n      wAsc: 1705,\n      wDes: 1705,\n      xH: 866,\n      capH: 1170,\n      yMin: -1392,\n      yMax: 2091,\n      hAsc: 1705,\n      hDes: -615,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Century Gothic',\n    fallbacks: ['CenturyGothic', 'AppleGothic', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 2060,\n      des: -451,\n      tAsc: 1536,\n      tDes: -426,\n      tLGap: 229,\n      wAsc: 1989,\n      wDes: 1989,\n      xH: undefined,\n      capH: undefined,\n      yMin: -628,\n      yMax: 2170,\n      hAsc: 2060,\n      hDes: -451,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Garamond',\n    fallbacks: [\n      'Baskerville',\n      'Baskerville Old Face',\n      'Hoefler Text',\n      'Times New Roman',\n      'serif',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1765,\n      des: -539,\n      tAsc: 1339,\n      tDes: -539,\n      tLGap: 313,\n      wAsc: 1765,\n      wDes: 1765,\n      xH: undefined,\n      capH: undefined,\n      yMin: -762,\n      yMax: 2040,\n      hAsc: 1765,\n      hDes: -539,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Georgia',\n    fallbacks: ['Times', 'Times New Roman', 'serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1878,\n      des: -449,\n      tAsc: 1549,\n      tDes: -444,\n      tLGap: 198,\n      wAsc: 1878,\n      wDes: 1878,\n      xH: 986,\n      capH: 1419,\n      yMin: -621,\n      yMax: 2201,\n      hAsc: 1878,\n      hDes: -449,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Gill Sans',\n    fallbacks: ['Gill Sans MT', 'Calibri', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1880,\n      des: -472,\n      tAsc: 1415,\n      tDes: -471,\n      tLGap: 305,\n      wAsc: 1880,\n      wDes: 1880,\n      xH: 920,\n      capH: 1397,\n      yMin: -473,\n      yMax: 1896,\n      hAsc: 1880,\n      hDes: -472,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Lucida Bright',\n    fallbacks: ['Georgia', 'serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1980,\n      des: -432,\n      tAsc: 1579,\n      tDes: -420,\n      tLGap: 49,\n      wAsc: 1900,\n      wDes: 1900,\n      xH: undefined,\n      capH: undefined,\n      yMin: -432,\n      yMax: 1900,\n      hAsc: 1980,\n      hDes: -432,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Lucida Sans Typewriter',\n    fallbacks: [\n      'Lucida Console',\n      'monaco',\n      'Bitstream Vera Sans Mono',\n      'monospace',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1974,\n      des: -432,\n      tAsc: 1579,\n      tDes: 420,\n      tLGap: 49,\n      wAsc: 1900,\n      wDes: 1900,\n      xH: undefined,\n      capH: undefined,\n      yMin: -420,\n      yMax: 1900,\n      hAsc: 1974,\n      hDes: -432,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Palatino',\n    fallbacks: [\n      'Palatino Linotype',\n      'Palatino LT STD',\n      'Book Antiqua',\n      'Georgia',\n      'serif',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1491,\n      des: -600,\n      tAsc: 1491,\n      tDes: -580,\n      tLGap: 0,\n      wAsc: 2322,\n      wDes: 2322,\n      xH: undefined,\n      capH: undefined,\n      yMin: -580,\n      yMax: 2322,\n      hAsc: 1491,\n      hDes: -600,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Papyrus',\n    fallbacks: ['fantasy'],\n    metrics: {\n      upm: 2048,\n      asc: 1925,\n      des: -1235,\n      tAsc: 1913,\n      tDes: -780,\n      tLGap: -502,\n      wAsc: 1925,\n      wDes: 1925,\n      xH: 910,\n      capH: 1351,\n      yMin: -1235,\n      yMax: 1935,\n      hAsc: 1925,\n      hDes: -1235,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Tahoma',\n    fallbacks: ['Verdana', 'Segoe', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 2049,\n      des: -423,\n      tAsc: 1566,\n      tDes: -423,\n      tLGap: 59,\n      wAsc: 2049,\n      wDes: 2049,\n      xH: 1117,\n      capH: 1489,\n      yMin: -442,\n      yMax: 2118,\n      hAsc: 2049,\n      hDes: -423,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Times New Roman',\n    fallbacks: ['Times New Roman', 'Times', 'Baskerville', 'Georgia', 'serif'],\n    metrics: {\n      upm: 2048,\n      asc: 1825,\n      des: -443,\n      tAsc: 1420,\n      tDes: -442,\n      tLGap: 307,\n      wAsc: 1825,\n      wDes: 1825,\n      xH: 916,\n      capH: 1356,\n      yMin: -628,\n      yMax: 2062,\n      hAsc: 1825,\n      hDes: -443,\n      lGap: 87,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Trebuchet MS',\n    fallbacks: [\n      'Lucida Grande',\n      'Lucida Sans Unicode',\n      'Lucida Sans',\n      'Tahoma',\n      'sans-serif',\n    ],\n    metrics: {\n      upm: 2048,\n      asc: 1923,\n      des: -455,\n      tAsc: 1510,\n      tDes: -420,\n      tLGap: 0,\n      wAsc: 1923,\n      wDes: 1923,\n      xH: undefined,\n      capH: undefined,\n      yMin: -537,\n      yMax: 1931,\n      hAsc: 1923,\n      hDes: -455,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n  {\n    family: 'Verdana',\n    fallbacks: ['Geneva', 'sans-serif'],\n    metrics: {\n      upm: 2048,\n      asc: 2059,\n      des: -430,\n      tAsc: 1566,\n      tDes: -423,\n      tLGap: 202,\n      wAsc: 2059,\n      wDes: 2059,\n      xH: 1117,\n      capH: 1489,\n      yMin: -621,\n      yMax: 2049,\n      hAsc: 2059,\n      hDes: -430,\n      lGap: 0,\n    },\n    ...DEFAULT_ATTRIBUTES,\n  },\n];\n"
  },
  {
    "path": "packages/fonts/scripts/utils/getFontFallback.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns a valid CSS font fallback declaration for a given category.\n *\n * @param category Font category as used on Google Fonts.\n * @return Font fallback.\n */\nfunction getFontFallback(category: string) {\n  switch (category) {\n    case 'handwriting':\n    case 'display':\n      return 'cursive';\n    case 'sans-serif':\n    case 'monospace':\n      return category;\n    default:\n      return 'serif';\n  }\n}\n\nexport default getFontFallback;\n"
  },
  {
    "path": "packages/fonts/scripts/utils/getFontMetrics.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { unlinkSync, writeFileSync } from 'node:fs';\nimport Crypto from 'node:crypto';\nimport { tmpdir } from 'node:os';\nimport Path from 'node:path';\nimport { loadSync } from 'opentype.js';\n\n/**\n * Internal dependencies\n */\nimport type { FontMetrics } from './types';\n\n/**\n * Returns a pseudo-random temporary file name.\n *\n * @return File name.\n */\nfunction getTmpFileName() {\n  return Path.join(\n    tmpdir(),\n    `font.${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.ttf`\n  );\n}\n\n/**\n * Returns font metrics for a given external font file.\n *\n * @param fontFileURL Font file URL.\n * @return Font metrics.\n */\nasync function getFontMetrics(fontFileURL: string) {\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  const response = await fetch(fontFileURL);\n\n  const tempFile = getTmpFileName();\n  writeFileSync(tempFile, Buffer.from(await response.arrayBuffer()));\n  const fontInfo = loadSync(tempFile);\n  unlinkSync(tempFile);\n\n  return {\n    upm: fontInfo.unitsPerEm,\n    asc: fontInfo.ascender,\n    des: fontInfo.descender,\n    tAsc: fontInfo.tables.os2.sTypoAscender as number,\n    tDes: fontInfo.tables.os2.sTypoDescender as number,\n    tLGap: fontInfo.tables.os2.sTypoLineGap as number,\n    wAsc: fontInfo.tables.os2.usWinAscent as number,\n    wDes: fontInfo.tables.os2.usWinDescent as number,\n    xH: fontInfo.tables.os2.sxHeight as number,\n    capH: fontInfo.tables.os2.sCapHeight as number,\n    yMin: fontInfo.tables.head.yMin as number,\n    yMax: fontInfo.tables.head.yMax as number,\n    hAsc: fontInfo.tables.hhea.ascender as number,\n    hDes: fontInfo.tables.hhea.descender as number,\n    lGap: fontInfo.tables.hhea.lineGap as number,\n  } as FontMetrics;\n}\n\nexport default getFontMetrics;\n"
  },
  {
    "path": "packages/fonts/scripts/utils/normalizeFont.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFontFallback from './getFontFallback';\nimport type { Font, RawFont } from './types';\n\n// eslint-disable-next-line security/detect-unsafe-regex\nconst FONT_VARIANT_PATTERN = /(?<weight>\\d+)?(?<style>\\D+)?/;\n\n/**\n * Normalizes font objects for later use.\n *\n * Drops unnecessary fields, and splits provided variants list\n * into weights, styles, and variants tuples.\n *\n * @param font Font object.\n * @return Normalized font object.\n */\nfunction normalizeFont(font: RawFont) {\n  const variants = [];\n  const weights = [];\n  const styles = [];\n\n  const { family, category, variants: initialVariants } = font;\n\n  for (const variant of initialVariants) {\n    const found = variant.match(FONT_VARIANT_PATTERN);\n\n    const weight = found?.groups?.weight;\n\n    if (weight) {\n      weights.push(Number(weight));\n    }\n\n    const style = found?.groups?.style;\n\n    if (style) {\n      if ('regular' === style || !weight) {\n        weights.push(400);\n      }\n\n      styles.push(style);\n    }\n\n    // Example: [ 1, 700] for italic+bold.\n    const variantTuple = [\n      Number('italic' === style),\n      weight ? Number(weight) : 400,\n    ];\n\n    variants.push(variantTuple);\n  }\n\n  return {\n    family,\n    fallbacks: [getFontFallback(category)],\n    weights: [...new Set(weights)],\n    styles: [...new Set(styles)],\n    variants,\n    service: 'fonts.google.com',\n  } as Font;\n}\n\nexport default normalizeFont;\n"
  },
  {
    "path": "packages/fonts/scripts/utils/test/buildFonts.js",
    "content": "/**\n * @jest-environment node\n */\n\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n// eslint-disable-next-line header/header -- Needed because of the @jest-environment comment.\nimport { __setMockFiles, readFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport { SYSTEM_FONTS } from '../constants';\nimport buildFonts from '../buildFonts';\nimport getFontMetrics from '../getFontMetrics';\n\njest.spyOn(global, 'fetch').mockImplementation();\n\njest.mock('node:fs');\njest.mock('../getFontMetrics');\n\nconst ABEZEE_FONT_METRICS = {\n  upm: 1,\n  asc: 1,\n  des: 1,\n  tAsc: 1,\n  tDes: 1,\n  tLGap: 1,\n  wAsc: 1,\n  wDes: 1,\n  xH: 1,\n  capH: 1,\n  yMin: 1,\n  yMax: 1,\n  hAsc: 1,\n  hDes: 1,\n  lGap: 1,\n};\n\nconst ABEZEE_FONT_AFTER = {\n  family: 'ABeeZee',\n  fallbacks: ['sans-serif'],\n  weights: [400],\n  styles: ['regular', 'italic'],\n  variants: [\n    [0, 400],\n    [1, 400],\n  ],\n  service: 'fonts.google.com',\n  metrics: ABEZEE_FONT_METRICS,\n};\n\ndescribe('buildFonts', () => {\n  const MOCK_FILE_INFO = {\n    '/assets/src/fonts/fonts.json': '{}',\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should combine system fonts with pre-existing list of Google Fonts', async () => {\n    global.fetch.mockImplementationOnce(() => {\n      return {\n        ok: true,\n        json: () =>\n          Promise.resolve({\n            items: [\n              {\n                family: 'ABeeZee',\n                variants: ['regular', 'italic'],\n                category: 'sans-serif',\n                files: {\n                  regular:\n                    'http://fonts.gstatic.com/s/abeezee/v13/esDR31xSG-6AGleN6tKukbcHCpE.ttf',\n                  italic:\n                    'http://fonts.gstatic.com/s/abeezee/v13/esDT31xSG-6AGleN2tCklZUCGpG-GQ.ttf',\n                },\n              },\n            ],\n          }),\n      };\n    });\n\n    getFontMetrics.mockImplementationOnce(() => ABEZEE_FONT_METRICS);\n\n    await buildFonts('/assets/src/fonts/fonts.json');\n\n    const contentAfter = JSON.parse(\n      readFileSync('/assets/src/fonts/fonts.json')\n    );\n    expect(getFontMetrics).toHaveBeenCalledWith(\n      'http://fonts.gstatic.com/s/abeezee/v13/esDR31xSG-6AGleN6tKukbcHCpE.ttf'\n    );\n    expect(contentAfter).toHaveLength(1 + SYSTEM_FONTS.length);\n    expect(contentAfter).toContainEqual(ABEZEE_FONT_AFTER);\n  });\n\n  it('should bail on empty response', async () => {\n    global.fetch.mockImplementationOnce(() => ({ body: '' }));\n\n    await buildFonts('/assets/src/fonts/fonts.json');\n\n    const contentAfter = readFileSync('/assets/src/fonts/fonts.json');\n    expect(contentAfter).toBe('{}');\n  });\n});\n"
  },
  {
    "path": "packages/fonts/scripts/utils/test/getFontFallback.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFontFallback from '../getFontFallback';\n\ndescribe('getFontFallback', () => {\n  const categories = [\n    ['handwriting', 'cursive'],\n    ['display', 'cursive'],\n    ['sans-serif', 'sans-serif'],\n    ['monospace', 'monospace'],\n    ['serif', 'serif'],\n    ['invalid', 'serif'],\n  ];\n  it.each(categories)(\n    'should return expected fallback for category \"%s\"',\n    (category, expected) => {\n      expect(getFontFallback(category)).toStrictEqual(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/fonts/scripts/utils/test/getFontMetrics.js",
    "content": "/**\n * @jest-environment node\n */\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n// eslint-disable-next-line header/header -- Needed because of the @jest-environment comment.\nimport { join } from 'node:path';\nimport { readFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport getFontMetrics from '../getFontMetrics';\n\njest.spyOn(global, 'fetch').mockImplementation();\n\ndescribe('getFontMetrics', () => {\n  it('should return font metrics', async () => {\n    global.fetch.mockImplementationOnce(() => {\n      return {\n        ok: true,\n        arrayBuffer: () =>\n          Promise.resolve(\n            readFileSync(join(__dirname, '/fixtures/abezee.ttf'))\n          ),\n      };\n    });\n\n    const result = await getFontMetrics(\n      'http://fonts.gstatic.com/s/abeezee/v13/esDR31xSG-6AGleN6tKukbcHCpE.ttf'\n    );\n\n    expect(result).toStrictEqual({\n      asc: 920,\n      capH: 700,\n      des: -262,\n      hAsc: 920,\n      hDes: -262,\n      lGap: 0,\n      tAsc: 920,\n      tDes: -262,\n      tLGap: 0,\n      upm: 1000,\n      wAsc: 920,\n      wDes: 262,\n      xH: 520,\n      yMax: 920,\n      yMin: -262,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/fonts/scripts/utils/test/normalizeFont.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport normalizeFont from '../normalizeFont';\n\n// As downloaded from Google Fonts API.\nconst ABEZEE_FONT_BEFORE = {\n  family: 'ABeeZee',\n  variants: ['regular', 'italic'],\n  category: 'sans-serif',\n};\n\nconst ABEZEE_FONT_AFTER = {\n  family: 'ABeeZee',\n  fallbacks: ['sans-serif'],\n  weights: [400],\n  styles: ['regular', 'italic'],\n  variants: [\n    [0, 400],\n    [1, 400],\n  ],\n  service: 'fonts.google.com',\n};\n\nconst ABHAYA_LIBRE_BEFORE = {\n  family: 'Abhaya Libre',\n  variants: ['regular', '500', '600', '700', '800'],\n  category: 'serif',\n};\n\nconst ABHAYA_LIBRE_AFTER = {\n  family: 'Abhaya Libre',\n  fallbacks: ['serif'],\n  weights: [400, 500, 600, 700, 800],\n  styles: ['regular'],\n  variants: [\n    [0, 400],\n    [0, 500],\n    [0, 600],\n    [0, 700],\n    [0, 800],\n  ],\n  service: 'fonts.google.com',\n};\n\nconst ROBOTO_BEFORE = {\n  family: 'Roboto',\n  category: 'sans-serif',\n  variants: [\n    '100',\n    '100italic',\n    '300',\n    '300italic',\n    'regular',\n    'italic',\n    '500',\n    '500italic',\n    '700',\n    '700italic',\n    '900',\n    '900italic',\n  ],\n};\n\nconst ROBOTO_AFTER = {\n  family: 'Roboto',\n  fallbacks: ['sans-serif'],\n  weights: [100, 300, 400, 500, 700, 900],\n  styles: ['italic', 'regular'],\n  variants: [\n    [0, 100],\n    [1, 100],\n    [0, 300],\n    [1, 300],\n    [0, 400],\n    [1, 400],\n    [0, 500],\n    [1, 500],\n    [0, 700],\n    [1, 700],\n    [0, 900],\n    [1, 900],\n  ],\n  service: 'fonts.google.com',\n};\n\ndescribe('normalizeFont', () => {\n  it('should normalize Google Fonts font objects', () => {\n    expect(normalizeFont(ABEZEE_FONT_BEFORE)).toStrictEqual(ABEZEE_FONT_AFTER);\n    expect(normalizeFont(ABHAYA_LIBRE_BEFORE)).toStrictEqual(\n      ABHAYA_LIBRE_AFTER\n    );\n    expect(normalizeFont(ROBOTO_BEFORE)).toStrictEqual(ROBOTO_AFTER);\n  });\n});\n"
  },
  {
    "path": "packages/fonts/scripts/utils/types.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface RawFont {\n  family: string;\n  category: string;\n  variants: string[];\n  fonts: unknown;\n  files: Record<number | string, string>;\n}\n\nexport type FontStyle = 'normal' | 'italic' | 'regular';\nexport enum FontVariantStyle {\n  Normal = 0,\n  Italic = 1,\n}\n\nexport type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;\n\nexport type FontVariant = [FontVariantStyle, FontWeight];\n\nexport interface FontMetrics {\n  upm: number;\n  asc: number;\n  des: number;\n  tAsc: number;\n  tDes: number;\n  tLGap: number;\n  wAsc: number;\n  wDes: number;\n  xH?: number;\n  capH?: number;\n  yMin: number;\n  yMax: number;\n  hAsc: number;\n  hDes: number;\n  lGap: number;\n}\n\nexport interface Font {\n  family: string;\n  weights?: FontWeight[];\n  styles?: FontStyle[];\n  variants?: FontVariant[];\n  fallbacks?: string[];\n  metrics?: FontMetrics;\n  service: string;\n}\n"
  },
  {
    "path": "packages/fonts/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Curated Fonts list source:\n// https://github.com/googleforcreators/web-stories-wp/issues/1989#issuecomment-662253222\nexport const CURATED_FONT_NAMES: string[] = [\n  'Karla',\n  'Lato',\n  'Lora',\n  'Merriweather',\n  'Montserrat',\n  'Nunito',\n  'Oswald',\n  'Playfair Display',\n  'Poppins',\n  'Raleway',\n  'Roboto',\n  'Roboto Condensed',\n  'Source Serif 4',\n  'Titillium Web',\n  'Work Sans',\n  'Alegreya',\n  'Arimo',\n  'EB Garamond',\n  'IBM Plex Mono',\n  'IBM Plex Serif',\n  'Inconsolata',\n  'Mulish',\n  'Noto Sans',\n  'Noto Serif',\n  'Open Sans',\n  'PT Mono',\n  'PT Sans',\n  'PT Serif',\n  'Roboto Mono',\n  'Source Sans 3',\n  'Ubuntu',\n  'Anton',\n  'BioRhyme',\n  'Bungee',\n  'Bungee Shade',\n  'Cookie',\n  'Dancing Script',\n  'Monoton',\n  'Nothing You Could Do',\n  'Parisienne',\n  'Rock Salt',\n  'UnifrakturMaguntia',\n];\n"
  },
  {
    "path": "packages/fonts/src/fonts.json",
    "content": "[\n  {\n    \"family\": \"ABeeZee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -262,\n      \"tAsc\": 920,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 263,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -262,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abel\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2006,\n      \"des\": -604,\n      \"tAsc\": 2006,\n      \"tDes\": -604,\n      \"tLGap\": 0,\n      \"wAsc\": 2006,\n      \"wDes\": 604,\n      \"xH\": 1044,\n      \"capH\": 1434,\n      \"yMin\": -604,\n      \"yMax\": 2005,\n      \"hAsc\": 2006,\n      \"hDes\": -604,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abhaya Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 860,\n      \"des\": -348,\n      \"tAsc\": 860,\n      \"tDes\": -348,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 348,\n      \"yMin\": -340,\n      \"yMax\": 856,\n      \"hAsc\": 860,\n      \"hDes\": -348,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aboreto\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -230,\n      \"tAsc\": 930,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 924,\n      \"wDes\": 256,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -256,\n      \"yMax\": 924,\n      \"hAsc\": 930,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abril Fatface\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1058,\n      \"des\": -291,\n      \"tAsc\": 1058,\n      \"tDes\": -291,\n      \"tLGap\": 0,\n      \"wAsc\": 1058,\n      \"wDes\": 291,\n      \"xH\": 476,\n      \"capH\": 700,\n      \"yMin\": -291,\n      \"yMax\": 1058,\n      \"hAsc\": 1058,\n      \"hDes\": -291,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Abyssinica SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2034,\n      \"des\": -682,\n      \"tAsc\": 2034,\n      \"tDes\": -682,\n      \"tLGap\": 0,\n      \"wAsc\": 2034,\n      \"wDes\": 682,\n      \"xH\": 983,\n      \"capH\": 1108,\n      \"yMin\": -682,\n      \"yMax\": 2034,\n      \"hAsc\": 2034,\n      \"hDes\": -682,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aclonica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1687,\n      \"des\": -533,\n      \"tAsc\": 1687,\n      \"tDes\": -533,\n      \"tLGap\": 101,\n      \"wAsc\": 1687,\n      \"wDes\": 533,\n      \"xH\": 1155,\n      \"capH\": 1440,\n      \"yMin\": -607,\n      \"yMax\": 2141,\n      \"hAsc\": 1687,\n      \"hDes\": -533,\n      \"lGap\": 101\n    }\n  },\n  {\n    \"family\": \"Acme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -307,\n      \"tAsc\": 959,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 307,\n      \"xH\": 107,\n      \"capH\": 695,\n      \"yMin\": -307,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Actor\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 941,\n      \"des\": -262,\n      \"tAsc\": 941,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 941,\n      \"wDes\": 262,\n      \"xH\": 503,\n      \"capH\": 682,\n      \"yMin\": -262,\n      \"yMax\": 941,\n      \"hAsc\": 941,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Adamina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1072,\n      \"des\": -290,\n      \"tAsc\": 1072,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 290,\n      \"xH\": 534,\n      \"capH\": 796,\n      \"yMin\": -290,\n      \"yMax\": 1072,\n      \"hAsc\": 1072,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ADLaM Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2140,\n      \"des\": -532,\n      \"tAsc\": 2140,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 2140,\n      \"wDes\": 532,\n      \"xH\": 1118,\n      \"capH\": 1434,\n      \"yMin\": -526,\n      \"yMax\": 2034,\n      \"hAsc\": 2140,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Advent Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -232,\n      \"tAsc\": 962,\n      \"tDes\": -232,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 232,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 962,\n      \"hAsc\": 964,\n      \"hDes\": -232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Afacad\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1440,\n      \"asc\": 1440,\n      \"des\": -480,\n      \"tAsc\": 1440,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 480,\n      \"xH\": 600,\n      \"capH\": 900,\n      \"yMin\": -433,\n      \"yMax\": 1368,\n      \"hAsc\": 1440,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Afacad Flux\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1440,\n      \"asc\": 1440,\n      \"des\": -480,\n      \"tAsc\": 1440,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 480,\n      \"xH\": 600,\n      \"capH\": 900,\n      \"yMin\": -433,\n      \"yMax\": 1368,\n      \"hAsc\": 1440,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agbalumo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -280,\n      \"tAsc\": 1200,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 600,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -335,\n      \"yMax\": 1173,\n      \"hAsc\": 1200,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agdasima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -410,\n      \"tAsc\": 1565,\n      \"tDes\": -369,\n      \"tLGap\": 164,\n      \"wAsc\": 1889,\n      \"wDes\": 410,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -371,\n      \"yMax\": 1766,\n      \"hAsc\": 2015,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Agu Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1190,\n      \"des\": -310,\n      \"tAsc\": 1190,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 1186,\n      \"hAsc\": 1190,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aguafina Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -581,\n      \"tAsc\": 966,\n      \"tDes\": -581,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 581,\n      \"xH\": 356,\n      \"capH\": 780,\n      \"yMin\": -581,\n      \"yMax\": 966,\n      \"hAsc\": 966,\n      \"hDes\": -581,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akatab\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2093,\n      \"des\": -713,\n      \"tAsc\": 2093,\n      \"tDes\": -713,\n      \"tLGap\": 0,\n      \"wAsc\": 2093,\n      \"wDes\": 713,\n      \"xH\": 1024,\n      \"capH\": 1393,\n      \"yMin\": -713,\n      \"yMax\": 2033,\n      \"hAsc\": 2093,\n      \"hDes\": -713,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akaya Kanadaka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -276,\n      \"tAsc\": 920,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 834,\n      \"xH\": 396,\n      \"capH\": 634,\n      \"yMin\": -834,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akaya Telivigala\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -276,\n      \"tAsc\": 920,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 834,\n      \"xH\": 450,\n      \"capH\": 613,\n      \"yMin\": -805,\n      \"yMax\": 1011,\n      \"hAsc\": 920,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Akronim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 785,\n      \"des\": -314,\n      \"tAsc\": 785,\n      \"tDes\": -314,\n      \"tLGap\": 43,\n      \"wAsc\": 989,\n      \"wDes\": 404,\n      \"xH\": 486,\n      \"capH\": 730,\n      \"yMin\": -404,\n      \"yMax\": 989,\n      \"hAsc\": 785,\n      \"hDes\": -314,\n      \"lGap\": 43\n    }\n  },\n  {\n    \"family\": \"Akshar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -390,\n      \"tAsc\": 990,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 390,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -317,\n      \"yMax\": 991,\n      \"hAsc\": 990,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aladin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -321,\n      \"tAsc\": 905,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 905,\n      \"wDes\": 321,\n      \"xH\": 337,\n      \"capH\": 387,\n      \"yMin\": -321,\n      \"yMax\": 905,\n      \"hAsc\": 905,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alan Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 212,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -212,\n      \"yMax\": 912,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -280,\n      \"tAsc\": 1100,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 350,\n      \"xH\": 459,\n      \"capH\": 735,\n      \"yMin\": -302,\n      \"yMax\": 1254,\n      \"hAsc\": 1100,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alatsi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 3000,\n      \"wDes\": 700,\n      \"xH\": 996,\n      \"capH\": 1394,\n      \"yMin\": -650,\n      \"yMax\": 2344,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Albert Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -264,\n      \"yMax\": 958,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aldrich\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1475,\n      \"des\": -430,\n      \"tAsc\": 1475,\n      \"tDes\": -430,\n      \"tLGap\": 98,\n      \"wAsc\": 1872,\n      \"wDes\": 586,\n      \"xH\": 1065,\n      \"capH\": 1434,\n      \"yMin\": -809,\n      \"yMax\": 2120,\n      \"hAsc\": 1475,\n      \"hDes\": -430,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Alef\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2067,\n      \"des\": -722,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 2067,\n      \"wDes\": 722,\n      \"xH\": 1040,\n      \"capH\": 1438,\n      \"yMin\": -682,\n      \"yMax\": 2067,\n      \"hAsc\": 2067,\n      \"hDes\": -722,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -345,\n      \"tAsc\": 1016,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 345,\n      \"xH\": 452,\n      \"capH\": 637,\n      \"yMin\": -293,\n      \"yMax\": 962,\n      \"hAsc\": 1016,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1126,\n      \"wDes\": 312,\n      \"xH\": 458,\n      \"capH\": 641,\n      \"yMin\": -262,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1131,\n      \"wDes\": 312,\n      \"xH\": 458,\n      \"capH\": 641,\n      \"yMin\": -262,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alegreya SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -345,\n      \"tAsc\": 1016,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 345,\n      \"xH\": 452,\n      \"capH\": 636,\n      \"yMin\": -293,\n      \"yMax\": 1025,\n      \"hAsc\": 1016,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aleo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -295,\n      \"tAsc\": 905,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 372,\n      \"xH\": 507,\n      \"capH\": 737,\n      \"yMin\": -335,\n      \"yMax\": 1140,\n      \"hAsc\": 905,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alex Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 825,\n      \"des\": -425,\n      \"tAsc\": 825,\n      \"tDes\": -425,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 430,\n      \"xH\": 320,\n      \"capH\": 700,\n      \"yMin\": -425,\n      \"yMax\": 962,\n      \"hAsc\": 825,\n      \"hDes\": -425,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alexandria\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1166,\n      \"wDes\": 566,\n      \"xH\": 531,\n      \"capH\": 700,\n      \"yMin\": -566,\n      \"yMax\": 1146,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alfa Slab One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -333,\n      \"tAsc\": 1036,\n      \"tDes\": -333,\n      \"tLGap\": 0,\n      \"wAsc\": 1238,\n      \"wDes\": 327,\n      \"xH\": 556,\n      \"capH\": 778,\n      \"yMin\": -327,\n      \"yMax\": 1238,\n      \"hAsc\": 1036,\n      \"hDes\": -333,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alice\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 909,\n      \"des\": -234,\n      \"tAsc\": 909,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 868,\n      \"wDes\": 323,\n      \"xH\": 453,\n      \"capH\": 631,\n      \"yMin\": -323,\n      \"yMax\": 849,\n      \"hAsc\": 909,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alike\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -270,\n      \"tAsc\": 984,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 335,\n      \"xH\": 505,\n      \"capH\": 705,\n      \"yMin\": -335,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alike Angular\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -270,\n      \"tAsc\": 984,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 335,\n      \"xH\": 505,\n      \"capH\": 705,\n      \"yMin\": -335,\n      \"yMax\": 977,\n      \"hAsc\": 984,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alkalami\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -857,\n      \"tAsc\": 1035,\n      \"tDes\": -857,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 1200,\n      \"xH\": 430,\n      \"capH\": 660,\n      \"yMin\": -1056,\n      \"yMax\": 1372,\n      \"hAsc\": 1035,\n      \"hDes\": -857,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alkatra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -589,\n      \"tAsc\": 1095,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 1121,\n      \"wDes\": 606,\n      \"xH\": 475,\n      \"capH\": 680,\n      \"yMin\": -606,\n      \"yMax\": 1121,\n      \"hAsc\": 1095,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allan\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1928,\n      \"des\": -412,\n      \"tAsc\": 1928,\n      \"tDes\": -412,\n      \"tLGap\": 0,\n      \"wAsc\": 1928,\n      \"wDes\": 412,\n      \"xH\": 1040,\n      \"capH\": 1483,\n      \"yMin\": -418,\n      \"yMax\": 1929,\n      \"hAsc\": 1928,\n      \"hDes\": -412,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allerta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1057,\n      \"des\": -252,\n      \"tAsc\": 1057,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 252,\n      \"xH\": 564,\n      \"capH\": 737,\n      \"yMin\": -252,\n      \"yMax\": 1057,\n      \"hAsc\": 1057,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allerta Stencil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1057,\n      \"des\": -252,\n      \"tAsc\": 1057,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 252,\n      \"xH\": 564,\n      \"capH\": 737,\n      \"yMin\": -252,\n      \"yMax\": 1055,\n      \"hAsc\": 1057,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allison\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -380,\n      \"tAsc\": 890,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 396,\n      \"xH\": 220,\n      \"capH\": 630,\n      \"yMin\": -396,\n      \"yMax\": 916,\n      \"hAsc\": 890,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allkin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1200,\n      \"des\": 0,\n      \"tAsc\": 1200,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 0,\n      \"xH\": 500,\n      \"capH\": 1180,\n      \"yMin\": 0,\n      \"yMax\": 1180,\n      \"hAsc\": 1200,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Allura\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 615,\n      \"xH\": 295,\n      \"capH\": 590,\n      \"yMin\": -612,\n      \"yMax\": 1101,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almarai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 905,\n      \"des\": -211,\n      \"tAsc\": 905,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 1108,\n      \"wDes\": 453,\n      \"xH\": 514,\n      \"capH\": 716,\n      \"yMin\": -396,\n      \"yMax\": 1090,\n      \"hAsc\": 905,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -345,\n      \"tAsc\": 951,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 345,\n      \"xH\": 514,\n      \"capH\": 666,\n      \"yMin\": -227,\n      \"yMax\": 939,\n      \"hAsc\": 951,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -345,\n      \"tAsc\": 951,\n      \"tDes\": -345,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 345,\n      \"xH\": 505,\n      \"capH\": 666,\n      \"yMin\": -233,\n      \"yMax\": 879,\n      \"hAsc\": 951,\n      \"hDes\": -345,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Almendra SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 939,\n      \"des\": -251,\n      \"tAsc\": 939,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 939,\n      \"wDes\": 251,\n      \"xH\": 193,\n      \"capH\": 271,\n      \"yMin\": -219,\n      \"yMax\": 885,\n      \"hAsc\": 939,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -292,\n      \"yMax\": 829,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Collegiate One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -284,\n      \"yMax\": 908,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Inline One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -302,\n      \"yMax\": 891,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans Pinstripe\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -286,\n      \"yMax\": 810,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alumni Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 305,\n      \"xH\": 495,\n      \"capH\": 591,\n      \"yMin\": -292,\n      \"yMax\": 829,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Alyamama\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -530,\n      \"tAsc\": 900,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 1132,\n      \"wDes\": 530,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -468,\n      \"yMax\": 998,\n      \"hAsc\": 900,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amarante\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1010,\n      \"capH\": 1530,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amaranth\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -236,\n      \"tAsc\": 976,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 236,\n      \"xH\": 498,\n      \"capH\": 677,\n      \"yMin\": -223,\n      \"yMax\": 928,\n      \"hAsc\": 976,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amarna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -350,\n      \"tAsc\": 1025,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 350,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -331,\n      \"yMax\": 1000,\n      \"hAsc\": 1025,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amatic SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -245,\n      \"tAsc\": 1016,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 265,\n      \"xH\": 659,\n      \"capH\": 754,\n      \"yMin\": -234,\n      \"yMax\": 1093,\n      \"hAsc\": 1016,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amethysta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2022,\n      \"des\": -563,\n      \"tAsc\": 2022,\n      \"tDes\": -563,\n      \"tLGap\": 0,\n      \"wAsc\": 2022,\n      \"wDes\": 563,\n      \"xH\": 1024,\n      \"capH\": 1475,\n      \"yMin\": -563,\n      \"yMax\": 1952,\n      \"hAsc\": 2022,\n      \"hDes\": -563,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -406,\n      \"tAsc\": 928,\n      \"tDes\": -406,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 406,\n      \"xH\": 522,\n      \"capH\": 696,\n      \"yMin\": -406,\n      \"yMax\": 929,\n      \"hAsc\": 928,\n      \"hDes\": -406,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiri\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1124,\n      \"des\": -634,\n      \"tAsc\": 1124,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1850,\n      \"wDes\": 910,\n      \"xH\": 433,\n      \"capH\": 646,\n      \"yMin\": -900,\n      \"yMax\": 1815,\n      \"hAsc\": 1124,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amiri Quran\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1815,\n      \"des\": -634,\n      \"tAsc\": 1815,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1864,\n      \"wDes\": 910,\n      \"xH\": 433,\n      \"capH\": 646,\n      \"yMin\": -835,\n      \"yMax\": 1864,\n      \"hAsc\": 1815,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Amita\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1292,\n      \"des\": -650,\n      \"tAsc\": 1292,\n      \"tDes\": -650,\n      \"tLGap\": 0,\n      \"wAsc\": 1292,\n      \"wDes\": 650,\n      \"xH\": 495,\n      \"capH\": 720,\n      \"yMin\": -619,\n      \"yMax\": 1292,\n      \"hAsc\": 1292,\n      \"hDes\": -650,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anaheim\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1968,\n      \"des\": -672,\n      \"tAsc\": 1968,\n      \"tDes\": -672,\n      \"tLGap\": 0,\n      \"wAsc\": 2452,\n      \"wDes\": 723,\n      \"xH\": 985,\n      \"capH\": 1284,\n      \"yMin\": -467,\n      \"yMax\": 2166,\n      \"hAsc\": 1968,\n      \"hDes\": -672,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ancizar Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 851,\n      \"wDes\": 271,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -272,\n      \"yMax\": 858,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ancizar Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 904,\n      \"wDes\": 277,\n      \"xH\": 450,\n      \"capH\": 612,\n      \"yMin\": -277,\n      \"yMax\": 902,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Andada Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -235,\n      \"tAsc\": 942,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 390,\n      \"xH\": 494,\n      \"capH\": 705,\n      \"yMin\": -382,\n      \"yMax\": 1068,\n      \"hAsc\": 942,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Andika\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -800,\n      \"tAsc\": 2500,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 800,\n      \"xH\": 1040,\n      \"capH\": 1485,\n      \"yMin\": -1148,\n      \"yMax\": 2620,\n      \"hAsc\": 2500,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Bangla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2500,\n      \"des\": -1232,\n      \"tAsc\": 2500,\n      \"tDes\": -1232,\n      \"tLGap\": 0,\n      \"wAsc\": 2659,\n      \"wDes\": 1232,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1118,\n      \"yMax\": 2214,\n      \"hAsc\": 2500,\n      \"hDes\": -1232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2026,\n      \"des\": -1385,\n      \"tAsc\": 2026,\n      \"tDes\": -1385,\n      \"tLGap\": 0,\n      \"wAsc\": 2026,\n      \"wDes\": 1385,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1036,\n      \"yMax\": 1936,\n      \"hAsc\": 2026,\n      \"hDes\": -1385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Gujarati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1975,\n      \"des\": -1064,\n      \"tAsc\": 1975,\n      \"tDes\": -1064,\n      \"tLGap\": 0,\n      \"wAsc\": 2217,\n      \"wDes\": 1344,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1054,\n      \"yMax\": 1956,\n      \"hAsc\": 1975,\n      \"hDes\": -1064,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Gurmukhi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1500,\n      \"des\": -900,\n      \"tAsc\": 1500,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 2120,\n      \"wDes\": 1376,\n      \"xH\": 494,\n      \"capH\": 660,\n      \"yMin\": -1093,\n      \"yMax\": 2024,\n      \"hAsc\": 1500,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Kannada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2030,\n      \"des\": -1310,\n      \"tAsc\": 2030,\n      \"tDes\": -1310,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 1320,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1098,\n      \"yMax\": 1858,\n      \"hAsc\": 2030,\n      \"hDes\": -1310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Latin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -400,\n      \"tAsc\": 1800,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2136,\n      \"wDes\": 550,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -465,\n      \"yMax\": 1994,\n      \"hAsc\": 1800,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Malayalam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2035,\n      \"des\": -830,\n      \"tAsc\": 2035,\n      \"tDes\": -830,\n      \"tLGap\": 0,\n      \"wAsc\": 2005,\n      \"wDes\": 1060,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -676,\n      \"yMax\": 1770,\n      \"hAsc\": 2035,\n      \"hDes\": -830,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Odia\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1960,\n      \"des\": -1400,\n      \"tAsc\": 1960,\n      \"tDes\": -1400,\n      \"tLGap\": 0,\n      \"wAsc\": 2161,\n      \"wDes\": 1982,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1923,\n      \"yMax\": 2131,\n      \"hAsc\": 1960,\n      \"hDes\": -1400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Tamil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1963,\n      \"des\": -853,\n      \"tAsc\": 1963,\n      \"tDes\": -853,\n      \"tLGap\": 0,\n      \"wAsc\": 1963,\n      \"wDes\": 853,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -835,\n      \"yMax\": 1913,\n      \"hAsc\": 1963,\n      \"hDes\": -853,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anek Telugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -1200,\n      \"tAsc\": 1800,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2286,\n      \"wDes\": 1942,\n      \"xH\": 978,\n      \"capH\": 1278,\n      \"yMin\": -1761,\n      \"yMax\": 2120,\n      \"hAsc\": 1800,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Angkor\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1130,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1130,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Annapurna SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1939,\n      \"des\": -984,\n      \"tAsc\": 1939,\n      \"tDes\": -984,\n      \"tLGap\": 0,\n      \"wAsc\": 2879,\n      \"wDes\": 1033,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -1007,\n      \"yMax\": 2866,\n      \"hAsc\": 1939,\n      \"hDes\": -984,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Annie Use Your Telescope\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1049,\n      \"des\": -419,\n      \"tAsc\": 1049,\n      \"tDes\": -419,\n      \"tLGap\": 0,\n      \"wAsc\": 1049,\n      \"wDes\": 419,\n      \"xH\": 427,\n      \"capH\": 730,\n      \"yMin\": -419,\n      \"yMax\": 1049,\n      \"hAsc\": 1049,\n      \"hDes\": -419,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anonymous Pro\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1675,\n      \"des\": -373,\n      \"tAsc\": 1675,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 1675,\n      \"wDes\": 373,\n      \"xH\": 932,\n      \"capH\": 1305,\n      \"yMin\": -395,\n      \"yMax\": 1854,\n      \"hAsc\": 1675,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -534,\n      \"tAsc\": 1966,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 534,\n      \"xH\": 1049,\n      \"capH\": 1422,\n      \"yMin\": -534,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -251,\n      \"tAsc\": 940,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 251,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic Didone\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antic Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anton\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2409,\n      \"des\": -674,\n      \"tAsc\": 2409,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 2876,\n      \"wDes\": 674,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -667,\n      \"yMax\": 2874,\n      \"hAsc\": 2409,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anton SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2409,\n      \"des\": -674,\n      \"tAsc\": 2409,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 2876,\n      \"wDes\": 674,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -667,\n      \"yMax\": 2874,\n      \"hAsc\": 2409,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Antonio\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2365,\n      \"des\": -285,\n      \"tAsc\": 2365,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 2365,\n      \"wDes\": 689,\n      \"xH\": 1500,\n      \"capH\": 1760,\n      \"yMin\": -637,\n      \"yMax\": 2326,\n      \"hAsc\": 2365,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anuphan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1119,\n      \"wDes\": 324,\n      \"xH\": 570,\n      \"capH\": 698,\n      \"yMin\": -324,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Anybody\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1590,\n      \"des\": -480,\n      \"tAsc\": 1590,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2190,\n      \"wDes\": 685,\n      \"xH\": 1186,\n      \"capH\": 1350,\n      \"yMin\": -505,\n      \"yMax\": 1896,\n      \"hAsc\": 1590,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aoboshi One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 460,\n      \"capH\": 750,\n      \"yMin\": -348,\n      \"yMax\": 993,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"AR One Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -300,\n      \"tAsc\": 1060,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 300,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -236,\n      \"yMax\": 1050,\n      \"hAsc\": 1060,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arapey\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 868,\n      \"des\": -228,\n      \"tAsc\": 868,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 868,\n      \"wDes\": 228,\n      \"xH\": 438,\n      \"capH\": 639,\n      \"yMin\": -228,\n      \"yMax\": 868,\n      \"hAsc\": 868,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arbutus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 234,\n      \"capH\": 103,\n      \"yMin\": -550,\n      \"yMax\": 2010,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arbutus Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 1014,\n      \"capH\": 1500,\n      \"yMin\": -550,\n      \"yMax\": 2010,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Architects Daughter\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -413,\n      \"tAsc\": 1010,\n      \"tDes\": -413,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 413,\n      \"xH\": 439,\n      \"capH\": 675,\n      \"yMin\": -431,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -413,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -210,\n      \"tAsc\": 878,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 410,\n      \"xH\": 526,\n      \"capH\": 686,\n      \"yMin\": -394,\n      \"yMax\": 1083,\n      \"hAsc\": 878,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo Black\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -210,\n      \"tAsc\": 878,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1035,\n      \"wDes\": 312,\n      \"xH\": 528,\n      \"capH\": 688,\n      \"yMin\": -267,\n      \"yMax\": 957,\n      \"hAsc\": 878,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Archivo Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -312,\n      \"tAsc\": 1035,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 303,\n      \"xH\": 526,\n      \"capH\": 686,\n      \"yMin\": -303,\n      \"yMax\": 1050,\n      \"hAsc\": 1035,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Are You Serious\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -320,\n      \"tAsc\": 880,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 601,\n      \"xH\": 300,\n      \"capH\": 660,\n      \"yMin\": -601,\n      \"yMax\": 931,\n      \"hAsc\": 880,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aref Ruqaa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1221,\n      \"des\": -244,\n      \"tAsc\": 1221,\n      \"tDes\": -244,\n      \"tLGap\": 98,\n      \"wAsc\": 1221,\n      \"wDes\": 439,\n      \"xH\": 462,\n      \"capH\": 683,\n      \"yMin\": -379,\n      \"yMax\": 1028,\n      \"hAsc\": 1221,\n      \"hDes\": -244,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Aref Ruqaa Ink\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1221,\n      \"des\": -244,\n      \"tAsc\": 1221,\n      \"tDes\": -244,\n      \"tLGap\": 98,\n      \"wAsc\": 1221,\n      \"wDes\": 439,\n      \"xH\": 462,\n      \"capH\": 683,\n      \"yMin\": -376,\n      \"yMax\": 1028,\n      \"hAsc\": 1221,\n      \"hDes\": -244,\n      \"lGap\": 98\n    }\n  },\n  {\n    \"family\": \"Arial\",\n    \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -434,\n      \"tAsc\": 1491,\n      \"tDes\": -431,\n      \"tLGap\": 307,\n      \"wAsc\": 1854,\n      \"wDes\": 1854,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -665,\n      \"yMax\": 2060,\n      \"hAsc\": 1854,\n      \"hDes\": -434,\n      \"lGap\": 67\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arial Black\",\n    \"fallbacks\": [\"Arial Black\", \"Arial Bold\", \"Gadget\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2254,\n      \"des\": -634,\n      \"tAsc\": 1466,\n      \"tDes\": 434,\n      \"tLGap\": 291,\n      \"wAsc\": 2254,\n      \"wDes\": 2254,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -628,\n      \"yMax\": 2219,\n      \"hAsc\": 2254,\n      \"hDes\": -634,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arial Narrow\",\n    \"fallbacks\": [\"Arial\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1916,\n      \"des\": -434,\n      \"tAsc\": 1491,\n      \"tDes\": -431,\n      \"tLGap\": 269,\n      \"wAsc\": 1888,\n      \"wDes\": 1888,\n      \"xH\": 1062,\n      \"capH\": 1467,\n      \"yMin\": -628,\n      \"yMax\": 2224,\n      \"hAsc\": 1916,\n      \"hDes\": -434,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Arima\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1073,\n      \"des\": -560,\n      \"tAsc\": 1073,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 1073,\n      \"wDes\": 560,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -535,\n      \"yMax\": 1024,\n      \"hAsc\": 1073,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arimo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -434,\n      \"tAsc\": 1854,\n      \"tDes\": -434,\n      \"tLGap\": 67,\n      \"wAsc\": 2136,\n      \"wDes\": 797,\n      \"xH\": 1082,\n      \"capH\": 1409,\n      \"yMin\": -797,\n      \"yMax\": 2136,\n      \"hAsc\": 1854,\n      \"hDes\": -434,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Arizonia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 355,\n      \"xH\": 280,\n      \"capH\": 660,\n      \"yMin\": -354,\n      \"yMax\": 1012,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Armata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1190,\n      \"capH\": 1530,\n      \"yMin\": -560,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arsenal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -254,\n      \"tAsc\": 1000,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 339,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -288,\n      \"yMax\": 1012,\n      \"hAsc\": 1000,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arsenal SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -254,\n      \"tAsc\": 1000,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 339,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -288,\n      \"yMax\": 1012,\n      \"hAsc\": 1000,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Artifika\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -508,\n      \"tAsc\": 1984,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 1984,\n      \"wDes\": 508,\n      \"xH\": 1045,\n      \"capH\": 1433,\n      \"yMin\": -508,\n      \"yMax\": 1984,\n      \"hAsc\": 1984,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Arvo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1968,\n      \"des\": -506,\n      \"tAsc\": 1556,\n      \"tDes\": -471,\n      \"tLGap\": 110,\n      \"wAsc\": 1968,\n      \"wDes\": 506,\n      \"xH\": 1036,\n      \"capH\": 1516,\n      \"yMin\": -506,\n      \"yMax\": 1969,\n      \"hAsc\": 1968,\n      \"hDes\": -506,\n      \"lGap\": 55\n    }\n  },\n  {\n    \"family\": \"Arya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1265,\n      \"des\": -544,\n      \"tAsc\": 1265,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1265,\n      \"wDes\": 544,\n      \"xH\": 392,\n      \"capH\": 579,\n      \"yMin\": -544,\n      \"yMax\": 1265,\n      \"hAsc\": 1265,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asap\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -212,\n      \"tAsc\": 934,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 264,\n      \"xH\": 523,\n      \"capH\": 700,\n      \"yMin\": -225,\n      \"yMax\": 1044,\n      \"hAsc\": 934,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asap Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -212,\n      \"tAsc\": 934,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 264,\n      \"xH\": 523,\n      \"capH\": 700,\n      \"yMin\": -225,\n      \"yMax\": 1044,\n      \"hAsc\": 934,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1196,\n      \"des\": -557,\n      \"tAsc\": 1196,\n      \"tDes\": -557,\n      \"tLGap\": 0,\n      \"wAsc\": 1196,\n      \"wDes\": 557,\n      \"xH\": 484,\n      \"capH\": 680,\n      \"yMin\": -555,\n      \"yMax\": 1194,\n      \"hAsc\": 1196,\n      \"hDes\": -557,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asimovian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 342,\n      \"xH\": 535,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 1131,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asset\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1971,\n      \"des\": -589,\n      \"tAsc\": 1971,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 2449,\n      \"wDes\": 888,\n      \"xH\": 1047,\n      \"capH\": 1291,\n      \"yMin\": -888,\n      \"yMax\": 2449,\n      \"hAsc\": 1971,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Assistant\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1021,\n      \"des\": -287,\n      \"tAsc\": 1021,\n      \"tDes\": -287,\n      \"tLGap\": 200,\n      \"wAsc\": 1021,\n      \"wDes\": 287,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -259,\n      \"yMax\": 1021,\n      \"hAsc\": 1021,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Asta Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -241,\n      \"tAsc\": 952,\n      \"tDes\": -241,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 241,\n      \"xH\": 505,\n      \"capH\": 707,\n      \"yMin\": -241,\n      \"yMax\": 959,\n      \"hAsc\": 952,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Astloch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1948,\n      \"des\": -526,\n      \"tAsc\": 1696,\n      \"tDes\": -352,\n      \"tLGap\": 106,\n      \"wAsc\": 1948,\n      \"wDes\": 526,\n      \"xH\": 1200,\n      \"capH\": 1567,\n      \"yMin\": -376,\n      \"yMax\": 1934,\n      \"hAsc\": 1948,\n      \"hDes\": -526,\n      \"lGap\": 53\n    }\n  },\n  {\n    \"family\": \"Asul\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 949,\n      \"des\": -264,\n      \"tAsc\": 949,\n      \"tDes\": -264,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 264,\n      \"xH\": 488,\n      \"capH\": 703,\n      \"yMin\": -264,\n      \"yMax\": 949,\n      \"hAsc\": 949,\n      \"hDes\": -264,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Athiti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -450,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 450,\n      \"xH\": 468,\n      \"capH\": 614,\n      \"yMin\": -437,\n      \"yMax\": 1080,\n      \"hAsc\": 1150,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -290,\n      \"tAsc\": 950,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 290,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -250,\n      \"yMax\": 888,\n      \"hAsc\": 950,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -316,\n      \"tAsc\": 984,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 411,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -237,\n      \"yMax\": 892,\n      \"hAsc\": 984,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atkinson Hyperlegible Next\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -316,\n      \"tAsc\": 984,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 411,\n      \"xH\": 496,\n      \"capH\": 668,\n      \"yMin\": -250,\n      \"yMax\": 903,\n      \"hAsc\": 984,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atma\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1101,\n      \"des\": -518,\n      \"tAsc\": 1101,\n      \"tDes\": -518,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 518,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -441,\n      \"yMax\": 990,\n      \"hAsc\": 1101,\n      \"hDes\": -518,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Atomic Age\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2091,\n      \"des\": -656,\n      \"tAsc\": 2091,\n      \"tDes\": -656,\n      \"tLGap\": 0,\n      \"wAsc\": 2091,\n      \"wDes\": 656,\n      \"xH\": 1047,\n      \"capH\": 1516,\n      \"yMin\": -656,\n      \"yMax\": 2091,\n      \"hAsc\": 2091,\n      \"hDes\": -656,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Aubrey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -212,\n      \"tAsc\": 830,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 830,\n      \"wDes\": 211,\n      \"xH\": 450,\n      \"capH\": 616,\n      \"yMin\": -211,\n      \"yMax\": 830,\n      \"hAsc\": 830,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Audiowide\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2027,\n      \"des\": -584,\n      \"tAsc\": 2027,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2027,\n      \"wDes\": 584,\n      \"xH\": 1083,\n      \"capH\": 1434,\n      \"yMin\": -584,\n      \"yMax\": 2027,\n      \"hAsc\": 2027,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Autour One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2010,\n      \"des\": -550,\n      \"tAsc\": 2010,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2010,\n      \"wDes\": 550,\n      \"xH\": 1190,\n      \"capH\": 1561,\n      \"yMin\": -550,\n      \"yMax\": 2012,\n      \"hAsc\": 2010,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Average\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -263,\n      \"tAsc\": 953,\n      \"tDes\": -263,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 265,\n      \"xH\": 456,\n      \"capH\": 691,\n      \"yMin\": -265,\n      \"yMax\": 1077,\n      \"hAsc\": 953,\n      \"hDes\": -263,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Average Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1027,\n      \"des\": -269,\n      \"tAsc\": 1027,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 1027,\n      \"wDes\": 269,\n      \"xH\": 456,\n      \"capH\": 691,\n      \"yMin\": -269,\n      \"yMax\": 1027,\n      \"hAsc\": 1027,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Gruesa Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1952,\n      \"des\": -492,\n      \"tAsc\": 1952,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1952,\n      \"wDes\": 492,\n      \"yMin\": -460,\n      \"yMax\": 1884,\n      \"hAsc\": 1952,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1952,\n      \"des\": -492,\n      \"tAsc\": 1952,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1952,\n      \"wDes\": 492,\n      \"yMin\": -458,\n      \"yMax\": 1891,\n      \"hAsc\": 1952,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Sans Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2035,\n      \"des\": -499,\n      \"tAsc\": 2035,\n      \"tDes\": -499,\n      \"tLGap\": 0,\n      \"wAsc\": 2035,\n      \"wDes\": 499,\n      \"yMin\": -467,\n      \"yMax\": 1954,\n      \"hAsc\": 2035,\n      \"hDes\": -499,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Averia Serif Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1828,\n      \"des\": -465,\n      \"tAsc\": 1622,\n      \"tDes\": -426,\n      \"tLGap\": 184,\n      \"wAsc\": 1828,\n      \"wDes\": 465,\n      \"yMin\": -465,\n      \"yMax\": 1828,\n      \"hAsc\": 1828,\n      \"hDes\": -465,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Azeret Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -230,\n      \"tAsc\": 937,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 230,\n      \"xH\": 544,\n      \"capH\": 698,\n      \"yMin\": -221,\n      \"yMax\": 1106,\n      \"hAsc\": 937,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"B612\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1934,\n      \"wDes\": 712,\n      \"xH\": 1100,\n      \"capH\": 1500,\n      \"yMin\": -710,\n      \"yMax\": 1920,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"B612 Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 712,\n      \"xH\": 1100,\n      \"capH\": 1500,\n      \"yMin\": -710,\n      \"yMax\": 1924,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Babylonica\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -450,\n      \"tAsc\": 875,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 672,\n      \"xH\": 220,\n      \"capH\": 630,\n      \"yMin\": -671,\n      \"yMax\": 948,\n      \"hAsc\": 875,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bacasime Antique\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1536,\n      \"des\": -512,\n      \"tAsc\": 1408,\n      \"tDes\": -366,\n      \"tLGap\": 417,\n      \"wAsc\": 1805,\n      \"wDes\": 531,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -413,\n      \"yMax\": 1557,\n      \"hAsc\": 1536,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bad Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -648,\n      \"tAsc\": 1324,\n      \"tDes\": -648,\n      \"tLGap\": 0,\n      \"wAsc\": 1455,\n      \"wDes\": 648,\n      \"xH\": 505,\n      \"capH\": 960,\n      \"yMin\": -648,\n      \"yMax\": 1455,\n      \"hAsc\": 1324,\n      \"hDes\": -648,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Badeen Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -250,\n      \"tAsc\": 1150,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 300,\n      \"xH\": 600,\n      \"capH\": 700,\n      \"yMin\": -300,\n      \"yMax\": 959,\n      \"hAsc\": 1150,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bagel Fat One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 523,\n      \"capH\": 726,\n      \"yMin\": -220,\n      \"yMax\": 1005,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bahiana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 250,\n      \"xH\": 492,\n      \"capH\": 710,\n      \"yMin\": -250,\n      \"yMax\": 900,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bahianita\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -238,\n      \"tAsc\": 962,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 1007,\n      \"wDes\": 330,\n      \"xH\": 582,\n      \"capH\": 710,\n      \"yMin\": -330,\n      \"yMax\": 1007,\n      \"hAsc\": 962,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bai Jamjuree\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1225,\n      \"wDes\": 561,\n      \"xH\": 499,\n      \"capH\": 700,\n      \"yMin\": -488,\n      \"yMax\": 1206,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bakbak One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 602,\n      \"xH\": 500,\n      \"capH\": 607,\n      \"yMin\": -602,\n      \"yMax\": 970,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ballet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -770,\n      \"tAsc\": 1130,\n      \"tDes\": -770,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 920,\n      \"xH\": 339,\n      \"capH\": 1209,\n      \"yMin\": -913,\n      \"yMax\": 1152,\n      \"hAsc\": 1130,\n      \"hDes\": -770,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -524,\n      \"tAsc\": 1078,\n      \"tDes\": -524,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 524,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -470,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -524,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhai 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -544,\n      \"tAsc\": 1078,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 544,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -459,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhaijaan 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1080,\n      \"des\": -632,\n      \"tAsc\": 1080,\n      \"tDes\": -632,\n      \"tLGap\": 0,\n      \"wAsc\": 1080,\n      \"wDes\": 632,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -533,\n      \"yMax\": 1017,\n      \"hAsc\": 1080,\n      \"hDes\": -632,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Bhaina 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1185,\n      \"des\": -827,\n      \"tAsc\": 1185,\n      \"tDes\": -827,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 827,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -721,\n      \"yMax\": 1023,\n      \"hAsc\": 1185,\n      \"hDes\": -827,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Chettan 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -392,\n      \"tAsc\": 1078,\n      \"tDes\": -392,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 390,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -349,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -392,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Da 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -589,\n      \"tAsc\": 1095,\n      \"tDes\": -589,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 589,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -579,\n      \"yMax\": 1029,\n      \"hAsc\": 1095,\n      \"hDes\": -589,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Paaji 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1157,\n      \"des\": -614,\n      \"tAsc\": 1157,\n      \"tDes\": -614,\n      \"tLGap\": 0,\n      \"wAsc\": 1157,\n      \"wDes\": 614,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -523,\n      \"yMax\": 1018,\n      \"hAsc\": 1157,\n      \"hDes\": -614,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Tamma 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -673,\n      \"tAsc\": 1078,\n      \"tDes\": -673,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 757,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -739,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -673,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Tammudu 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1177,\n      \"des\": -1119,\n      \"tAsc\": 1177,\n      \"tDes\": -1119,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 1065,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -1065,\n      \"yMax\": 1071,\n      \"hAsc\": 1177,\n      \"hDes\": -1119,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baloo Thambi 2\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1078,\n      \"des\": -486,\n      \"tAsc\": 1078,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 486,\n      \"xH\": 460,\n      \"capH\": 602,\n      \"yMin\": -432,\n      \"yMax\": 1018,\n      \"hAsc\": 1078,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Balsamiq Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1220,\n      \"wDes\": 420,\n      \"xH\": 520,\n      \"capH\": 715,\n      \"yMin\": -347,\n      \"yMax\": 1136,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Balthazar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 796,\n      \"des\": -222,\n      \"tAsc\": 796,\n      \"tDes\": -222,\n      \"tLGap\": 0,\n      \"wAsc\": 796,\n      \"wDes\": 222,\n      \"xH\": 399,\n      \"capH\": 605,\n      \"yMin\": -222,\n      \"yMax\": 796,\n      \"hAsc\": 796,\n      \"hDes\": -222,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bangers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 883,\n      \"des\": -181,\n      \"tAsc\": 883,\n      \"tDes\": -181,\n      \"tLGap\": 0,\n      \"wAsc\": 1401,\n      \"wDes\": 356,\n      \"xH\": 721,\n      \"capH\": 721,\n      \"yMin\": -356,\n      \"yMax\": 1392,\n      \"hAsc\": 883,\n      \"hDes\": -181,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 249,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -209,\n      \"yMax\": 1084,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 274,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -209,\n      \"yMax\": 1074,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barlow Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1089,\n      \"wDes\": 261,\n      \"xH\": 506,\n      \"capH\": 700,\n      \"yMin\": -212,\n      \"yMax\": 1079,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barriecito\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -238,\n      \"tAsc\": 962,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 1041,\n      \"wDes\": 346,\n      \"xH\": 582,\n      \"capH\": 710,\n      \"yMin\": -346,\n      \"yMax\": 1041,\n      \"hAsc\": 962,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Barrio\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -247,\n      \"tAsc\": 880,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 880,\n      \"wDes\": 247,\n      \"xH\": 492,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 880,\n      \"hAsc\": 880,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Basic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -511,\n      \"tAsc\": 2066,\n      \"tDes\": -511,\n      \"tLGap\": 0,\n      \"wAsc\": 2066,\n      \"wDes\": 511,\n      \"xH\": 1022,\n      \"capH\": 1358,\n      \"yMin\": -507,\n      \"yMax\": 1960,\n      \"hAsc\": 2066,\n      \"hDes\": -511,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baskerville\",\n    \"fallbacks\": [\n      \"Baskerville Old Face\",\n      \"Hoefler Text\",\n      \"Garamond\",\n      \"Times New Roman\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1839,\n      \"des\": -504,\n      \"tAsc\": 1376,\n      \"tDes\": -504,\n      \"tLGap\": 311,\n      \"wAsc\": 1839,\n      \"wDes\": 1839,\n      \"xH\": 819,\n      \"capH\": 1356,\n      \"yMin\": -504,\n      \"yMax\": 1869,\n      \"hAsc\": 1839,\n      \"hDes\": -504,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Baskervville\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -295,\n      \"tAsc\": 998,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 300,\n      \"xH\": 436,\n      \"capH\": 710,\n      \"yMin\": -300,\n      \"yMax\": 1150,\n      \"hAsc\": 998,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baskervville SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -295,\n      \"tAsc\": 998,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 300,\n      \"xH\": 436,\n      \"capH\": 710,\n      \"yMin\": -300,\n      \"yMax\": 1150,\n      \"hAsc\": 998,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Battambang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2197,\n      \"wDes\": 1051,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1050,\n      \"yMax\": 2181,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Baumans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -240,\n      \"tAsc\": 942,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 240,\n      \"xH\": 480,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bayon\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Bartle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -201,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Bogle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BBH Hegarty\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 216,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 800,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Be Vietnam Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -265,\n      \"tAsc\": 1000,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1261,\n      \"wDes\": 265,\n      \"xH\": 530,\n      \"capH\": 740,\n      \"yMin\": -263,\n      \"yMax\": 1199,\n      \"hAsc\": 1000,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beau Rivage\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -400,\n      \"tAsc\": 940,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 445,\n      \"xH\": 350,\n      \"capH\": 700,\n      \"yMin\": -441,\n      \"yMax\": 1116,\n      \"hAsc\": 940,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bebas Neue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 350,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 912,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beiruti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 936,\n      \"wDes\": 450,\n      \"xH\": 390,\n      \"capH\": 605,\n      \"yMin\": -449,\n      \"yMax\": 921,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belanosima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1835,\n      \"des\": -416,\n      \"tAsc\": 1835,\n      \"tDes\": -416,\n      \"tLGap\": 190,\n      \"wAsc\": 1827,\n      \"wDes\": 416,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -504,\n      \"yMax\": 1938,\n      \"hAsc\": 1835,\n      \"hDes\": -416,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belgrano\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -278,\n      \"tAsc\": 990,\n      \"tDes\": -278,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 278,\n      \"xH\": 499,\n      \"capH\": 706,\n      \"yMin\": -279,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -278,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellefair\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -277,\n      \"tAsc\": 869,\n      \"tDes\": -277,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 277,\n      \"xH\": 364,\n      \"capH\": 688,\n      \"yMin\": -277,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -277,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Belleza\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -224,\n      \"tAsc\": 928,\n      \"tDes\": -224,\n      \"tLGap\": 0,\n      \"wAsc\": 1171,\n      \"wDes\": 312,\n      \"xH\": 452,\n      \"capH\": 662,\n      \"yMin\": -312,\n      \"yMax\": 1171,\n      \"hAsc\": 928,\n      \"hDes\": -224,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellota\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -290,\n      \"tAsc\": 968,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 325,\n      \"xH\": 500,\n      \"capH\": 684,\n      \"yMin\": -317,\n      \"yMax\": 1147,\n      \"hAsc\": 968,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bellota Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -290,\n      \"tAsc\": 968,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 325,\n      \"xH\": 500,\n      \"capH\": 684,\n      \"yMin\": -317,\n      \"yMax\": 1147,\n      \"hAsc\": 968,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BenchNine\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -720,\n      \"tAsc\": 2020,\n      \"tDes\": -720,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 720,\n      \"xH\": 1006,\n      \"capH\": 1438,\n      \"yMin\": -683,\n      \"yMax\": 2018,\n      \"hAsc\": 2020,\n      \"hDes\": -720,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Benne\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 630,\n      \"des\": -370,\n      \"tAsc\": 630,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 742,\n      \"xH\": 404,\n      \"capH\": 655,\n      \"yMin\": -742,\n      \"yMax\": 1105,\n      \"hAsc\": 630,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bentham\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 879,\n      \"des\": -260,\n      \"tAsc\": 768,\n      \"tDes\": -256,\n      \"tLGap\": 92,\n      \"wAsc\": 879,\n      \"wDes\": 260,\n      \"yMin\": -260,\n      \"yMax\": 878,\n      \"hAsc\": 879,\n      \"hDes\": -260,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Berkshire Swash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2007,\n      \"des\": -537,\n      \"tAsc\": 2007,\n      \"tDes\": -537,\n      \"tLGap\": 0,\n      \"wAsc\": 2007,\n      \"wDes\": 537,\n      \"xH\": 1038,\n      \"capH\": 1858,\n      \"yMin\": -537,\n      \"yMax\": 2007,\n      \"hAsc\": 2007,\n      \"hDes\": -537,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Besley\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2500,\n      \"des\": -850,\n      \"tAsc\": 2500,\n      \"tDes\": -850,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 850,\n      \"xH\": 1040,\n      \"capH\": 1500,\n      \"yMin\": -623,\n      \"yMax\": 2159,\n      \"hAsc\": 2500,\n      \"hDes\": -850,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1048,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos GDL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos In\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Betania Patmos In GDL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -262,\n      \"tAsc\": 1038,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1072,\n      \"wDes\": 380,\n      \"xH\": 419,\n      \"capH\": 775,\n      \"yMin\": -373,\n      \"yMax\": 1043,\n      \"hAsc\": 1038,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Beth Ellen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 3250,\n      \"des\": -1190,\n      \"tAsc\": 3250,\n      \"tDes\": -1190,\n      \"tLGap\": 0,\n      \"wAsc\": 3224,\n      \"wDes\": 946,\n      \"xH\": 1208,\n      \"capH\": 2248,\n      \"yMin\": -946,\n      \"yMax\": 3224,\n      \"hAsc\": 3250,\n      \"hDes\": -1190,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bevan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2366,\n      \"des\": -925,\n      \"tAsc\": 2366,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 2689,\n      \"wDes\": 870,\n      \"xH\": 1072,\n      \"capH\": 1592,\n      \"yMin\": -705,\n      \"yMax\": 2470,\n      \"hAsc\": 2366,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BhuTuka Expanded One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 826,\n      \"des\": -182,\n      \"tAsc\": 826,\n      \"tDes\": -182,\n      \"tLGap\": 0,\n      \"wAsc\": 844,\n      \"wDes\": 464,\n      \"xH\": 357,\n      \"capH\": 520,\n      \"yMin\": -464,\n      \"yMax\": 844,\n      \"hAsc\": 826,\n      \"hDes\": -182,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1971,\n      \"des\": -429,\n      \"tAsc\": 1971,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 2614,\n      \"wDes\": 730,\n      \"xH\": 1200,\n      \"capH\": 1600,\n      \"yMin\": -417,\n      \"yMax\": 2310,\n      \"hAsc\": 1971,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4000,\n      \"asc\": 3942,\n      \"des\": -858,\n      \"tAsc\": 3942,\n      \"tDes\": -858,\n      \"tLGap\": 0,\n      \"wAsc\": 5228,\n      \"wDes\": 1460,\n      \"xH\": 2400,\n      \"capH\": 3200,\n      \"yMin\": -860,\n      \"yMax\": 4688,\n      \"hAsc\": 3942,\n      \"hDes\": -858,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Big Shoulders Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1971,\n      \"des\": -429,\n      \"tAsc\": 1971,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 2614,\n      \"wDes\": 730,\n      \"xH\": 1200,\n      \"capH\": 1600,\n      \"yMin\": -415,\n      \"yMax\": 2310,\n      \"hAsc\": 1971,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bigelow Rules\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1857,\n      \"des\": -516,\n      \"tAsc\": 1857,\n      \"tDes\": -516,\n      \"tLGap\": 0,\n      \"wAsc\": 1857,\n      \"wDes\": 516,\n      \"xH\": 1227,\n      \"capH\": 1528,\n      \"yMin\": -516,\n      \"yMax\": 1857,\n      \"hAsc\": 1857,\n      \"hDes\": -516,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bigshot One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -179,\n      \"tAsc\": 869,\n      \"tDes\": -179,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 179,\n      \"xH\": 449,\n      \"capH\": 615,\n      \"yMin\": -179,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -179,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bilbo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 630,\n      \"xH\": 375,\n      \"capH\": 650,\n      \"yMin\": -627,\n      \"yMax\": 1024,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bilbo Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 400,\n      \"xH\": 327,\n      \"capH\": 542,\n      \"yMin\": -400,\n      \"yMax\": 850,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BioRhyme\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1127,\n      \"des\": -422,\n      \"tAsc\": 1127,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1127,\n      \"wDes\": 422,\n      \"xH\": 471,\n      \"capH\": 686,\n      \"yMin\": -370,\n      \"yMax\": 1117,\n      \"hAsc\": 1127,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BioRhyme Expanded\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1127,\n      \"des\": -422,\n      \"tAsc\": 1127,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1127,\n      \"wDes\": 422,\n      \"xH\": 471,\n      \"capH\": 686,\n      \"yMin\": -398,\n      \"yMax\": 1120,\n      \"hAsc\": 1127,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Birthstone\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 685,\n      \"xH\": 320,\n      \"capH\": 880,\n      \"yMin\": -648,\n      \"yMax\": 1052,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Birthstone Bounce\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 685,\n      \"xH\": 390,\n      \"capH\": 700,\n      \"yMin\": -643,\n      \"yMax\": 1046,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Biryani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1109,\n      \"des\": -656,\n      \"tAsc\": 1109,\n      \"tDes\": -656,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 656,\n      \"xH\": 563,\n      \"capH\": 758,\n      \"yMin\": -592,\n      \"yMax\": 1109,\n      \"hAsc\": 1109,\n      \"hDes\": -656,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Double\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Double Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Grid Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 900,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Double\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Double Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Prop Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Single\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -300,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitcount Single Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 840,\n      \"des\": -360,\n      \"tAsc\": 840,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 360,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -350,\n      \"yMax\": 1000,\n      \"hAsc\": 840,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bitter\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1255,\n      \"wDes\": 376,\n      \"xH\": 528,\n      \"capH\": 698,\n      \"yMin\": -275,\n      \"yMax\": 1073,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDGothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -246,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDMincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -262,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDPGothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -246,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BIZ UDPMincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1802,\n      \"des\": -246,\n      \"tAsc\": 1802,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 246,\n      \"xH\": 1108,\n      \"capH\": 1567,\n      \"yMin\": -262,\n      \"yMax\": 1802,\n      \"hAsc\": 1802,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"BJCree\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2080,\n      \"des\": -400,\n      \"tAsc\": 2080,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2080,\n      \"wDes\": 450,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -450,\n      \"yMax\": 2000,\n      \"hAsc\": 2080,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Black And White Picture\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 297,\n      \"xH\": 442,\n      \"capH\": 648,\n      \"yMin\": -297,\n      \"yMax\": 802,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Black Han Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 250,\n      \"wAsc\": 810,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -198,\n      \"yMax\": 810,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Black Ops One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1871,\n      \"des\": -689,\n      \"tAsc\": 1871,\n      \"tDes\": -689,\n      \"tLGap\": 0,\n      \"wAsc\": 2232,\n      \"wDes\": 689,\n      \"xH\": 1062,\n      \"capH\": 1327,\n      \"yMin\": -638,\n      \"yMax\": 2232,\n      \"hAsc\": 1871,\n      \"hDes\": -689,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka Hollow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blaka Ink\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -235,\n      \"tAsc\": 932,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 666,\n      \"yMin\": -400,\n      \"yMax\": 933,\n      \"hAsc\": 932,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Blinker\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 240,\n      \"xH\": 494,\n      \"capH\": 627,\n      \"yMin\": -223,\n      \"yMax\": 838,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bodoni Moda\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2250,\n      \"des\": -800,\n      \"tAsc\": 2250,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 800,\n      \"xH\": 920,\n      \"capH\": 1500,\n      \"yMin\": -627,\n      \"yMax\": 2095,\n      \"hAsc\": 2250,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bodoni Moda SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2250,\n      \"des\": -800,\n      \"tAsc\": 2250,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 800,\n      \"xH\": 920,\n      \"capH\": 1500,\n      \"yMin\": -627,\n      \"yMax\": 2095,\n      \"hAsc\": 2250,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bokor\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2594,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2594,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Boldonse\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1520,\n      \"des\": -400,\n      \"tAsc\": 1520,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1600,\n      \"wDes\": 458,\n      \"xH\": 870,\n      \"capH\": 1190,\n      \"yMin\": -458,\n      \"yMax\": 1600,\n      \"hAsc\": 1520,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bona Nova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -268,\n      \"tAsc\": 932,\n      \"tDes\": -268,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 500,\n      \"xH\": 440,\n      \"capH\": 665,\n      \"yMin\": -456,\n      \"yMax\": 1090,\n      \"hAsc\": 932,\n      \"hDes\": -268,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bona Nova SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -268,\n      \"tAsc\": 932,\n      \"tDes\": -268,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 500,\n      \"xH\": 440,\n      \"capH\": 665,\n      \"yMin\": -456,\n      \"yMax\": 1090,\n      \"hAsc\": 932,\n      \"hDes\": -268,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bonbon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 845,\n      \"des\": -330,\n      \"tAsc\": 845,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 845,\n      \"wDes\": 330,\n      \"xH\": 504,\n      \"capH\": 644,\n      \"yMin\": -330,\n      \"yMax\": 845,\n      \"hAsc\": 845,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bonheur Royale\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 780,\n      \"des\": -380,\n      \"tAsc\": 780,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 440,\n      \"xH\": 280,\n      \"capH\": 620,\n      \"yMin\": -440,\n      \"yMax\": 923,\n      \"hAsc\": 780,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Boogaloo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 943,\n      \"des\": -246,\n      \"tAsc\": 943,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 943,\n      \"wDes\": 246,\n      \"xH\": 338,\n      \"capH\": 469,\n      \"yMin\": -246,\n      \"yMax\": 943,\n      \"hAsc\": 943,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Borel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -1014,\n      \"tAsc\": 986,\n      \"tDes\": -1014,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1014,\n      \"xH\": 472,\n      \"capH\": 722,\n      \"yMin\": -514,\n      \"yMax\": 1203,\n      \"hAsc\": 986,\n      \"hDes\": -1014,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bowlby One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2276,\n      \"des\": -932,\n      \"tAsc\": 2276,\n      \"tDes\": -932,\n      \"tLGap\": 0,\n      \"wAsc\": 2276,\n      \"wDes\": 932,\n      \"xH\": 1196,\n      \"capH\": 1520,\n      \"yMin\": -932,\n      \"yMax\": 2276,\n      \"hAsc\": 2276,\n      \"hDes\": -932,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bowlby One SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2248,\n      \"des\": -876,\n      \"tAsc\": 2248,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 2248,\n      \"wDes\": 876,\n      \"xH\": 1392,\n      \"capH\": 1520,\n      \"yMin\": -876,\n      \"yMax\": 2248,\n      \"hAsc\": 2248,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Huninn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 273,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -242,\n      \"yMax\": 1008,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Iansui\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 273,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -202,\n      \"yMax\": 1048,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bpmf Zihi Kai Std\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 278,\n      \"xH\": 512,\n      \"capH\": 800,\n      \"yMin\": -278,\n      \"yMax\": 2042,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Braah One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -382,\n      \"tAsc\": 1018,\n      \"tDes\": -382,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 650,\n      \"xH\": 512,\n      \"capH\": 636,\n      \"yMin\": -619,\n      \"yMax\": 1120,\n      \"hAsc\": 1018,\n      \"hDes\": -382,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Brawler\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 971,\n      \"des\": -248,\n      \"tAsc\": 971,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 275,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 971,\n      \"hAsc\": 971,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bree Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -281,\n      \"tAsc\": 1077,\n      \"tDes\": -281,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 281,\n      \"xH\": 503,\n      \"capH\": 665,\n      \"yMin\": -281,\n      \"yMax\": 1077,\n      \"hAsc\": 1077,\n      \"hDes\": -281,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bricolage Grotesque\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -270,\n      \"tAsc\": 930,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 400,\n      \"xH\": 517,\n      \"capH\": 660,\n      \"yMin\": -343,\n      \"yMax\": 1137,\n      \"hAsc\": 930,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bruno Ace\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -253,\n      \"tAsc\": 953,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 253,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bruno Ace SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -253,\n      \"tAsc\": 953,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 253,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 908,\n      \"hAsc\": 953,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Brush Script MT\",\n    \"fallbacks\": [\"cursive\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -692,\n      \"tAsc\": 1229,\n      \"tDes\": -506,\n      \"tLGap\": 456,\n      \"wAsc\": 1820,\n      \"wDes\": 1820,\n      \"yMin\": -692,\n      \"yMax\": 1983,\n      \"hAsc\": 1820,\n      \"hDes\": -692,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Brygada 1918\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -250,\n      \"tAsc\": 920,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 440,\n      \"xH\": 460,\n      \"capH\": 670,\n      \"yMin\": -436,\n      \"yMax\": 1049,\n      \"hAsc\": 920,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bubblegum Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 852,\n      \"des\": -311,\n      \"tAsc\": 852,\n      \"tDes\": -311,\n      \"tLGap\": 0,\n      \"wAsc\": 852,\n      \"wDes\": 311,\n      \"xH\": 410,\n      \"capH\": 470,\n      \"yMin\": -311,\n      \"yMax\": 852,\n      \"hAsc\": 852,\n      \"hDes\": -311,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bubbler One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -263,\n      \"tAsc\": 900,\n      \"tDes\": -263,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 263,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 900,\n      \"hAsc\": 900,\n      \"hDes\": -263,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Buda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300],\n    \"styles\": [],\n    \"variants\": [[0, 300]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1836,\n      \"des\": -724,\n      \"tAsc\": 1519,\n      \"tDes\": -529,\n      \"tLGap\": 512,\n      \"wAsc\": 1836,\n      \"wDes\": 724,\n      \"yMin\": -446,\n      \"yMax\": 1862,\n      \"hAsc\": 1836,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Buenard\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1031,\n      \"des\": -270,\n      \"tAsc\": 1031,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 1009,\n      \"hAsc\": 1031,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Hairline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 894,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -894,\n      \"yMax\": 1614,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -924,\n      \"yMax\": 1644,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Shade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Spice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bungee Tint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1647,\n      \"wDes\": 927,\n      \"xH\": 500,\n      \"capH\": 720,\n      \"yMin\": -916,\n      \"yMax\": 1636,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Butcherman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2600,\n      \"des\": -1363,\n      \"tAsc\": 2600,\n      \"tDes\": -1363,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 1363,\n      \"xH\": 1521,\n      \"capH\": 1509,\n      \"yMin\": -1363,\n      \"yMax\": 2600,\n      \"hAsc\": 2600,\n      \"hDes\": -1363,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Butterfly Kids\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 917,\n      \"des\": -304,\n      \"tAsc\": 917,\n      \"tDes\": -304,\n      \"tLGap\": 0,\n      \"wAsc\": 917,\n      \"wDes\": 304,\n      \"xH\": 338,\n      \"capH\": 802,\n      \"yMin\": -304,\n      \"yMax\": 917,\n      \"hAsc\": 917,\n      \"hDes\": -304,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Bytesized\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 16,\n      \"asc\": 12,\n      \"des\": -8,\n      \"tAsc\": 12,\n      \"tDes\": -8,\n      \"tLGap\": 0,\n      \"wAsc\": 10,\n      \"wDes\": 6,\n      \"xH\": 8,\n      \"capH\": 11,\n      \"yMin\": -6,\n      \"yMax\": 10,\n      \"hAsc\": 12,\n      \"hDes\": -8,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -500,\n      \"tAsc\": 1930,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 630,\n      \"xH\": 980,\n      \"capH\": 1400,\n      \"yMin\": -608,\n      \"yMax\": 2276,\n      \"hAsc\": 1930,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -250,\n      \"tAsc\": 965,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 314,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -284,\n      \"yMax\": 1124,\n      \"hAsc\": 965,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cabin Sketch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -298,\n      \"tAsc\": 873,\n      \"tDes\": -298,\n      \"tLGap\": 0,\n      \"wAsc\": 873,\n      \"wDes\": 298,\n      \"xH\": 505,\n      \"capH\": 652,\n      \"yMin\": -249,\n      \"yMax\": 865,\n      \"hAsc\": 873,\n      \"hDes\": -298,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cactus Classical Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -229,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 229,\n      \"xH\": 501,\n      \"capH\": 761,\n      \"yMin\": -545,\n      \"yMax\": 2017,\n      \"hAsc\": 995,\n      \"hDes\": -229,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caesar Dressing\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1017,\n      \"des\": -226,\n      \"tAsc\": 1017,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 231,\n      \"xH\": 772,\n      \"capH\": 773,\n      \"yMin\": -226,\n      \"yMax\": 1017,\n      \"hAsc\": 1017,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cagliostro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -355,\n      \"tAsc\": 998,\n      \"tDes\": -355,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 355,\n      \"xH\": 444,\n      \"capH\": 700,\n      \"yMin\": -355,\n      \"yMax\": 998,\n      \"hAsc\": 998,\n      \"hDes\": -355,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cairo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -571,\n      \"tAsc\": 1303,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1312,\n      \"wDes\": 571,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -430,\n      \"yMax\": 1084,\n      \"hAsc\": 1303,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cairo Play\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -571,\n      \"tAsc\": 1303,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1312,\n      \"wDes\": 571,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -430,\n      \"yMax\": 1084,\n      \"hAsc\": 1303,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cal Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 222,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -221,\n      \"yMax\": 1139,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caladea\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 250,\n      \"xH\": 467,\n      \"capH\": 667,\n      \"yMin\": -222,\n      \"yMax\": 936,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Calistoga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 400,\n      \"xH\": 530,\n      \"capH\": 698,\n      \"yMin\": -396,\n      \"yMax\": 1199,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Calligraffitti\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 986,\n      \"des\": -607,\n      \"tAsc\": 866,\n      \"tDes\": -457,\n      \"tLGap\": 28,\n      \"wAsc\": 986,\n      \"wDes\": 607,\n      \"xH\": 819,\n      \"capH\": 841,\n      \"yMin\": -607,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -607,\n      \"lGap\": 14\n    }\n  },\n  {\n    \"family\": \"Cambay\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 800,\n      \"asc\": 800,\n      \"des\": -503,\n      \"tAsc\": 800,\n      \"tDes\": -503,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 503,\n      \"xH\": 384,\n      \"capH\": 550,\n      \"yMin\": -499,\n      \"yMax\": 760,\n      \"hAsc\": 800,\n      \"hDes\": -503,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cambo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 879,\n      \"des\": -243,\n      \"tAsc\": 879,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 879,\n      \"wDes\": 243,\n      \"xH\": 506,\n      \"capH\": 676,\n      \"yMin\": -243,\n      \"yMax\": 879,\n      \"hAsc\": 879,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Candal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2226,\n      \"des\": -432,\n      \"tAsc\": 2226,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 432,\n      \"xH\": 1079,\n      \"capH\": 1414,\n      \"yMin\": -997,\n      \"yMax\": 2226,\n      \"hAsc\": 2226,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantarell\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2240,\n      \"des\": -660,\n      \"tAsc\": 2240,\n      \"tDes\": -660,\n      \"tLGap\": 0,\n      \"wAsc\": 2157,\n      \"wDes\": 585,\n      \"yMin\": -555,\n      \"yMax\": 2137,\n      \"hAsc\": 2240,\n      \"hDes\": -660,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantata One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -560,\n      \"tAsc\": 2040,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 560,\n      \"xH\": 1023,\n      \"capH\": 1530,\n      \"yMin\": -560,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cantora One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caprasimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1880,\n      \"des\": -469,\n      \"tAsc\": 1376,\n      \"tDes\": -395,\n      \"tLGap\": 0,\n      \"wAsc\": 1880,\n      \"wDes\": 469,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -520,\n      \"yMax\": 1916,\n      \"hAsc\": 1880,\n      \"hDes\": -469,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Capriola\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1992,\n      \"des\": -568,\n      \"tAsc\": 1992,\n      \"tDes\": -568,\n      \"tLGap\": 0,\n      \"wAsc\": 1992,\n      \"wDes\": 568,\n      \"xH\": 1128,\n      \"capH\": 1533,\n      \"yMin\": -568,\n      \"yMax\": 1994,\n      \"hAsc\": 1992,\n      \"hDes\": -568,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caramel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 335,\n      \"xH\": 270,\n      \"capH\": 650,\n      \"yMin\": -335,\n      \"yMax\": 923,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carattere\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -350,\n      \"tAsc\": 800,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 568,\n      \"xH\": 350,\n      \"capH\": 690,\n      \"yMin\": -568,\n      \"yMax\": 1011,\n      \"hAsc\": 800,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cardo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2028,\n      \"des\": -745,\n      \"tAsc\": 2028,\n      \"tDes\": -745,\n      \"tLGap\": 0,\n      \"wAsc\": 2028,\n      \"wDes\": 745,\n      \"xH\": 900,\n      \"capH\": 1410,\n      \"yMin\": -745,\n      \"yMax\": 2336,\n      \"hAsc\": 2028,\n      \"hDes\": -745,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carlito\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1950,\n      \"des\": -550,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 452,\n      \"wAsc\": 1950,\n      \"wDes\": 550,\n      \"xH\": 978,\n      \"capH\": 1314,\n      \"yMin\": -529,\n      \"yMax\": 2078,\n      \"hAsc\": 1950,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1946,\n      \"des\": -513,\n      \"tAsc\": 1946,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1946,\n      \"wDes\": 513,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -513,\n      \"yMax\": 1946,\n      \"hAsc\": 1946,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carrois Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -270,\n      \"tAsc\": 922,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carrois Gothic SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -270,\n      \"tAsc\": 922,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Carter One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2264,\n      \"des\": -890,\n      \"tAsc\": 2264,\n      \"tDes\": -890,\n      \"tLGap\": 0,\n      \"wAsc\": 2264,\n      \"wDes\": 890,\n      \"xH\": 473,\n      \"capH\": 1481,\n      \"yMin\": -891,\n      \"yMax\": 2264,\n      \"hAsc\": 2264,\n      \"hDes\": -890,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cascadia Code\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -480,\n      \"tAsc\": 1900,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 480,\n      \"xH\": 1060,\n      \"capH\": 1420,\n      \"yMin\": -989,\n      \"yMax\": 2304,\n      \"hAsc\": 1900,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cascadia Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -480,\n      \"tAsc\": 1900,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 2226,\n      \"wDes\": 480,\n      \"xH\": 1060,\n      \"capH\": 1420,\n      \"yMin\": -989,\n      \"yMax\": 2304,\n      \"hAsc\": 1900,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Castoro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Castoro Titling\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 455,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Catamaran\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -540,\n      \"tAsc\": 1100,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 540,\n      \"xH\": 485,\n      \"capH\": 680,\n      \"yMin\": -377,\n      \"yMax\": 1100,\n      \"hAsc\": 1100,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caudex\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2034,\n      \"des\": -606,\n      \"tAsc\": 2034,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2034,\n      \"wDes\": 606,\n      \"yMin\": -606,\n      \"yMax\": 2034,\n      \"hAsc\": 2034,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cause\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 930,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caveat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 315,\n      \"xH\": 400,\n      \"capH\": 610,\n      \"yMin\": -299,\n      \"yMax\": 960,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Caveat Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 300,\n      \"xH\": 420,\n      \"capH\": 660,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cedarville Cursive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1279,\n      \"des\": -663,\n      \"tAsc\": 1279,\n      \"tDes\": -663,\n      \"tLGap\": 0,\n      \"wAsc\": 1279,\n      \"wDes\": 663,\n      \"xH\": 400,\n      \"capH\": 775,\n      \"yMin\": -663,\n      \"yMax\": 1279,\n      \"hAsc\": 1279,\n      \"hDes\": -663,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Century Gothic\",\n    \"fallbacks\": [\"CenturyGothic\", \"AppleGothic\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -451,\n      \"tAsc\": 1536,\n      \"tDes\": -426,\n      \"tLGap\": 229,\n      \"wAsc\": 1989,\n      \"wDes\": 1989,\n      \"yMin\": -628,\n      \"yMax\": 2170,\n      \"hAsc\": 2060,\n      \"hDes\": -451,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Ceviche One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 806,\n      \"des\": -237,\n      \"tAsc\": 806,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 806,\n      \"wDes\": 237,\n      \"xH\": 451,\n      \"capH\": 425,\n      \"yMin\": -237,\n      \"yMax\": 806,\n      \"hAsc\": 806,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chakra Petch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -308,\n      \"tAsc\": 992,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 1248,\n      \"wDes\": 566,\n      \"xH\": 498,\n      \"capH\": 700,\n      \"yMin\": -533,\n      \"yMax\": 1236,\n      \"hAsc\": 992,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Changa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1227,\n      \"des\": -613,\n      \"tAsc\": 1227,\n      \"tDes\": -613,\n      \"tLGap\": 0,\n      \"wAsc\": 1368,\n      \"wDes\": 680,\n      \"xH\": 500,\n      \"capH\": 625,\n      \"yMin\": -553,\n      \"yMax\": 1223,\n      \"hAsc\": 1227,\n      \"hDes\": -613,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Changa One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 882,\n      \"des\": -180,\n      \"tAsc\": 882,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 882,\n      \"wDes\": 180,\n      \"xH\": 500,\n      \"capH\": 625,\n      \"yMin\": -180,\n      \"yMax\": 882,\n      \"hAsc\": 882,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chango\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -216,\n      \"tAsc\": 995,\n      \"tDes\": -216,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 216,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 995,\n      \"hAsc\": 995,\n      \"hDes\": -216,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charis SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2450,\n      \"des\": -900,\n      \"tAsc\": 2450,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 2450,\n      \"wDes\": 900,\n      \"xH\": 987,\n      \"capH\": 1374,\n      \"yMin\": -1092,\n      \"yMax\": 2600,\n      \"hAsc\": 2450,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charm\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -434,\n      \"tAsc\": 1115,\n      \"tDes\": -434,\n      \"tLGap\": 0,\n      \"wAsc\": 1639,\n      \"wDes\": 714,\n      \"xH\": 466,\n      \"capH\": 684,\n      \"yMin\": -692,\n      \"yMax\": 1597,\n      \"hAsc\": 1115,\n      \"hDes\": -434,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Charmonman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -700,\n      \"tAsc\": 1200,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 1630,\n      \"wDes\": 937,\n      \"xH\": 420,\n      \"capH\": 700,\n      \"yMin\": -919,\n      \"yMax\": 1562,\n      \"hAsc\": 1200,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chathura\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -602,\n      \"tAsc\": 1020,\n      \"tDes\": -602,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 602,\n      \"xH\": 294,\n      \"capH\": 404,\n      \"yMin\": -602,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -602,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chau Philomene One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1033,\n      \"des\": -334,\n      \"tAsc\": 1033,\n      \"tDes\": -334,\n      \"tLGap\": 0,\n      \"wAsc\": 1033,\n      \"wDes\": 334,\n      \"xH\": 512,\n      \"capH\": 752,\n      \"yMin\": -334,\n      \"yMax\": 1033,\n      \"hAsc\": 1033,\n      \"hDes\": -334,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chela One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -235,\n      \"tAsc\": 942,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 235,\n      \"xH\": 534,\n      \"capH\": 721,\n      \"yMin\": -235,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chelsea Market\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1029,\n      \"des\": -274,\n      \"tAsc\": 1029,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 274,\n      \"xH\": 608,\n      \"capH\": 796,\n      \"yMin\": -274,\n      \"yMax\": 1029,\n      \"hAsc\": 1029,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chenla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Cherish\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -320,\n      \"tAsc\": 850,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 465,\n      \"xH\": 330,\n      \"capH\": 600,\n      \"yMin\": -465,\n      \"yMax\": 981,\n      \"hAsc\": 850,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cherry Bomb One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -272,\n      \"yMax\": 1054,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cherry Cream Soda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1006,\n      \"des\": -247,\n      \"tAsc\": 738,\n      \"tDes\": -247,\n      \"tLGap\": 57,\n      \"wAsc\": 1006,\n      \"wDes\": 247,\n      \"xH\": 502,\n      \"capH\": 741,\n      \"yMin\": -247,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -247,\n      \"lGap\": 29\n    }\n  },\n  {\n    \"family\": \"Cherry Swash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -301,\n      \"tAsc\": 1025,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 301,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -301,\n      \"yMax\": 1000,\n      \"hAsc\": 1025,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chewy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1003,\n      \"des\": -310,\n      \"tAsc\": 801,\n      \"tDes\": -308,\n      \"tLGap\": 49,\n      \"wAsc\": 1003,\n      \"wDes\": 310,\n      \"xH\": 577,\n      \"capH\": 768,\n      \"yMin\": -310,\n      \"yMax\": 1003,\n      \"hAsc\": 1003,\n      \"hDes\": -310,\n      \"lGap\": 25\n    }\n  },\n  {\n    \"family\": \"Chicle\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -294,\n      \"tAsc\": 915,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 294,\n      \"xH\": 277,\n      \"capH\": 513,\n      \"yMin\": -294,\n      \"yMax\": 915,\n      \"hAsc\": 915,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chilanka\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -750,\n      \"tAsc\": 1500,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 1914,\n      \"wDes\": 1282,\n      \"xH\": 999,\n      \"capH\": 1448,\n      \"yMin\": -1282,\n      \"yMax\": 1914,\n      \"hAsc\": 1500,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron GoRound TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron Hei HK\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chiron Sung HK\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -210,\n      \"tAsc\": 970,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1810,\n      \"wDes\": 1050,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 970,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chivo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 413,\n      \"xH\": 511,\n      \"capH\": 686,\n      \"yMin\": -314,\n      \"yMax\": 1104,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chivo Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -250,\n      \"tAsc\": 940,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 413,\n      \"xH\": 511,\n      \"capH\": 686,\n      \"yMin\": -314,\n      \"yMax\": 1104,\n      \"hAsc\": 940,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chocolate Classical Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -549,\n      \"yMax\": 1323,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chokokutai\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 486,\n      \"capH\": 774,\n      \"yMin\": -239,\n      \"yMax\": 1141,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Chonburi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -401,\n      \"yMax\": 1072,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cinzel\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -372,\n      \"tAsc\": 976,\n      \"tDes\": -372,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 372,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -372,\n      \"yMax\": 976,\n      \"hAsc\": 976,\n      \"hDes\": -372,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cinzel Decorative\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -372,\n      \"tAsc\": 976,\n      \"tDes\": -372,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 372,\n      \"xH\": 714,\n      \"capH\": 700,\n      \"yMin\": -284,\n      \"yMax\": 945,\n      \"hAsc\": 976,\n      \"hDes\": -372,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Clicker Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -807,\n      \"tAsc\": 1898,\n      \"tDes\": -807,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 807,\n      \"xH\": 621,\n      \"capH\": 1358,\n      \"yMin\": -807,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -807,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Climate Crisis\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -260,\n      \"tAsc\": 1070,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 320,\n      \"xH\": 620,\n      \"capH\": 750,\n      \"yMin\": -308,\n      \"yMax\": 1292,\n      \"hAsc\": 1070,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -784,\n      \"tAsc\": 2124,\n      \"tDes\": -784,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 784,\n      \"yMin\": -691,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -784,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Codystar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 953,\n      \"des\": -255,\n      \"tAsc\": 953,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 255,\n      \"xH\": 753,\n      \"capH\": 761,\n      \"yMin\": -255,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coiny\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": 250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 600,\n      \"wAsc\": 750,\n      \"wDes\": 250,\n      \"yMin\": -466,\n      \"yMax\": 1311,\n      \"hAsc\": 750,\n      \"hDes\": 250,\n      \"lGap\": 600\n    }\n  },\n  {\n    \"family\": \"Combo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 907,\n      \"des\": -269,\n      \"tAsc\": 907,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 907,\n      \"wDes\": 269,\n      \"xH\": 516,\n      \"capH\": 670,\n      \"yMin\": -269,\n      \"yMax\": 907,\n      \"hAsc\": 907,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comfortaa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 881,\n      \"des\": -234,\n      \"tAsc\": 881,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 1285,\n      \"wDes\": 332,\n      \"xH\": 547,\n      \"capH\": 781,\n      \"yMin\": -289,\n      \"yMax\": 1264,\n      \"hAsc\": 881,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comforter\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -480,\n      \"tAsc\": 930,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 739,\n      \"xH\": 400,\n      \"capH\": 750,\n      \"yMin\": -654,\n      \"yMax\": 1119,\n      \"hAsc\": 930,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comforter Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -480,\n      \"tAsc\": 930,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 739,\n      \"xH\": 400,\n      \"capH\": 750,\n      \"yMin\": -661,\n      \"yMax\": 1114,\n      \"hAsc\": 930,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comic Neue\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 350,\n      \"xH\": 487,\n      \"capH\": 670,\n      \"yMin\": -215,\n      \"yMax\": 928,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Comic Relief\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2160,\n      \"des\": -697,\n      \"tAsc\": 2160,\n      \"tDes\": -697,\n      \"tLGap\": 0,\n      \"wAsc\": 2257,\n      \"wDes\": 641,\n      \"xH\": 1105,\n      \"capH\": 1554,\n      \"yMin\": -641,\n      \"yMax\": 2257,\n      \"hAsc\": 2160,\n      \"hDes\": -697,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coming Soon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1053,\n      \"des\": -498,\n      \"tAsc\": 792,\n      \"tDes\": -444,\n      \"tLGap\": 42,\n      \"wAsc\": 1053,\n      \"wDes\": 498,\n      \"xH\": 569,\n      \"capH\": 763,\n      \"yMin\": -498,\n      \"yMax\": 1053,\n      \"hAsc\": 1053,\n      \"hDes\": -498,\n      \"lGap\": 21\n    }\n  },\n  {\n    \"family\": \"Comme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1957,\n      \"des\": -501,\n      \"tAsc\": 1957,\n      \"tDes\": -501,\n      \"tLGap\": 0,\n      \"wAsc\": 2519,\n      \"wDes\": 632,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -523,\n      \"yMax\": 2399,\n      \"hAsc\": 1957,\n      \"hDes\": -501,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Commissioner\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2034,\n      \"des\": -412,\n      \"tAsc\": 2034,\n      \"tDes\": -412,\n      \"tLGap\": 0,\n      \"wAsc\": 2424,\n      \"wDes\": 586,\n      \"xH\": 992,\n      \"capH\": 1426,\n      \"yMin\": -570,\n      \"yMax\": 2321,\n      \"hAsc\": 2034,\n      \"hDes\": -412,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Concert One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2005,\n      \"des\": -410,\n      \"tAsc\": 2005,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 2005,\n      \"wDes\": 410,\n      \"xH\": 1004,\n      \"capH\": 1400,\n      \"yMin\": -400,\n      \"yMax\": 1958,\n      \"hAsc\": 2005,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Condiment\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 882,\n      \"des\": -641,\n      \"tAsc\": 882,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 882,\n      \"wDes\": 641,\n      \"xH\": 317,\n      \"capH\": 327,\n      \"yMin\": -641,\n      \"yMax\": 882,\n      \"hAsc\": 882,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Content\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Contrail One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1939,\n      \"des\": -625,\n      \"tAsc\": 1939,\n      \"tDes\": -625,\n      \"tLGap\": 0,\n      \"wAsc\": 1939,\n      \"wDes\": 625,\n      \"xH\": 255,\n      \"capH\": 421,\n      \"yMin\": -625,\n      \"yMax\": 1939,\n      \"hAsc\": 1939,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Convergence\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 943,\n      \"des\": -230,\n      \"tAsc\": 943,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 943,\n      \"wDes\": 230,\n      \"xH\": 541,\n      \"capH\": 727,\n      \"yMin\": -230,\n      \"yMax\": 943,\n      \"hAsc\": 943,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cookie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 789,\n      \"des\": -320,\n      \"tAsc\": 789,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 789,\n      \"wDes\": 320,\n      \"xH\": 115,\n      \"capH\": 312,\n      \"yMin\": -320,\n      \"yMax\": 789,\n      \"hAsc\": 789,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Copperplate\",\n    \"fallbacks\": [\"Copperplate Gothic Light\", \"fantasy\"],\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 763,\n      \"des\": -248,\n      \"tAsc\": 763,\n      \"tDes\": -250,\n      \"tLGap\": 20,\n      \"wAsc\": 763,\n      \"wDes\": 763,\n      \"xH\": 440,\n      \"capH\": 526,\n      \"yMin\": -248,\n      \"yMax\": 924,\n      \"hAsc\": 763,\n      \"hDes\": -248,\n      \"lGap\": 19\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Copse\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1991,\n      \"des\": -483,\n      \"tAsc\": 1583,\n      \"tDes\": -439,\n      \"tLGap\": 113,\n      \"wAsc\": 1991,\n      \"wDes\": 483,\n      \"xH\": 1001,\n      \"capH\": 1505,\n      \"yMin\": -483,\n      \"yMax\": 1991,\n      \"hAsc\": 1991,\n      \"hDes\": -483,\n      \"lGap\": 57\n    }\n  },\n  {\n    \"family\": \"Coral Pixels\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -346,\n      \"tAsc\": 1039,\n      \"tDes\": -346,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 385,\n      \"xH\": 539,\n      \"capH\": 693,\n      \"yMin\": -231,\n      \"yMax\": 924,\n      \"hAsc\": 1039,\n      \"hDes\": -346,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Corben\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2826,\n      \"des\": -969,\n      \"tAsc\": 2826,\n      \"tDes\": -969,\n      \"tLGap\": 0,\n      \"wAsc\": 2826,\n      \"wDes\": 969,\n      \"xH\": 958,\n      \"capH\": 1404,\n      \"yMin\": -495,\n      \"yMax\": 2202,\n      \"hAsc\": 2826,\n      \"hDes\": -969,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Corinthia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 760,\n      \"des\": -440,\n      \"tAsc\": 760,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 863,\n      \"wDes\": 447,\n      \"xH\": 240,\n      \"capH\": 535,\n      \"yMin\": -420,\n      \"yMax\": 843,\n      \"hAsc\": 760,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Garamond\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Infant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Unicase\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -283,\n      \"yMax\": 927,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cormorant Upright\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -287,\n      \"tAsc\": 924,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 937,\n      \"wDes\": 283,\n      \"xH\": 386,\n      \"capH\": 625,\n      \"yMin\": -281,\n      \"yMax\": 904,\n      \"hAsc\": 924,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cossette Texte\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -210,\n      \"tAsc\": 1000,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -210,\n      \"yMax\": 975,\n      \"hAsc\": 1000,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cossette Titre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -210,\n      \"tAsc\": 1000,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -210,\n      \"yMax\": 905,\n      \"hAsc\": 1000,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Courgette\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 112,\n      \"capH\": 301,\n      \"yMin\": -560,\n      \"yMax\": 2005,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Courier New\",\n    \"fallbacks\": [\n      \"Courier\",\n      \"Lucida Sans Typewriter\",\n      \"Lucida Typewriter\",\n      \"monospace\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1705,\n      \"des\": -615,\n      \"tAsc\": 1255,\n      \"tDes\": -386,\n      \"tLGap\": 0,\n      \"wAsc\": 1705,\n      \"wDes\": 1705,\n      \"xH\": 866,\n      \"capH\": 1170,\n      \"yMin\": -1392,\n      \"yMax\": 2091,\n      \"hAsc\": 1705,\n      \"hDes\": -615,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Courier Prime\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1600,\n      \"des\": -700,\n      \"tAsc\": 1600,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 800,\n      \"xH\": 924,\n      \"capH\": 1187,\n      \"yMin\": -526,\n      \"yMax\": 1827,\n      \"hAsc\": 1600,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cousine\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1705,\n      \"des\": -615,\n      \"tAsc\": 1255,\n      \"tDes\": -386,\n      \"tLGap\": 0,\n      \"wAsc\": 1705,\n      \"wDes\": 615,\n      \"xH\": 1082,\n      \"capH\": 1349,\n      \"yMin\": -615,\n      \"yMax\": 2009,\n      \"hAsc\": 1705,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Coustard\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -781,\n      \"tAsc\": 2095,\n      \"tDes\": -781,\n      \"tLGap\": 0,\n      \"wAsc\": 2097,\n      \"wDes\": 780,\n      \"xH\": 1067,\n      \"capH\": 1489,\n      \"yMin\": -629,\n      \"yMax\": 2097,\n      \"hAsc\": 2095,\n      \"hDes\": -781,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Covered By Your Grace\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 995,\n      \"des\": -384,\n      \"tAsc\": 995,\n      \"tDes\": -384,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 384,\n      \"xH\": 500,\n      \"capH\": 795,\n      \"yMin\": -384,\n      \"yMax\": 1021,\n      \"hAsc\": 995,\n      \"hDes\": -384,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crafty Girls\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1001,\n      \"des\": -461,\n      \"tAsc\": 761,\n      \"tDes\": -327,\n      \"tLGap\": 40,\n      \"wAsc\": 1001,\n      \"wDes\": 461,\n      \"xH\": 548,\n      \"capH\": 772,\n      \"yMin\": -461,\n      \"yMax\": 999,\n      \"hAsc\": 1001,\n      \"hDes\": -461,\n      \"lGap\": 21\n    }\n  },\n  {\n    \"family\": \"Creepster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 974,\n      \"des\": -223,\n      \"tAsc\": 974,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 223,\n      \"xH\": 751,\n      \"capH\": 751,\n      \"yMin\": -223,\n      \"yMax\": 971,\n      \"hAsc\": 974,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crete Round\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -286,\n      \"tAsc\": 990,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 286,\n      \"xH\": 495,\n      \"capH\": 679,\n      \"yMin\": -277,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crimson Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 918,\n      \"des\": -220,\n      \"tAsc\": 918,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 295,\n      \"xH\": 430,\n      \"capH\": 587,\n      \"yMin\": -286,\n      \"yMax\": 984,\n      \"hAsc\": 918,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crimson Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 972,\n      \"des\": -359,\n      \"tAsc\": 972,\n      \"tDes\": -359,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 297,\n      \"xH\": 430,\n      \"capH\": 656,\n      \"yMin\": -297,\n      \"yMax\": 1038,\n      \"hAsc\": 972,\n      \"hDes\": -359,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Croissant One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1071,\n      \"des\": -344,\n      \"tAsc\": 1071,\n      \"tDes\": -344,\n      \"tLGap\": 0,\n      \"wAsc\": 1071,\n      \"wDes\": 344,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -344,\n      \"yMax\": 1071,\n      \"hAsc\": 1071,\n      \"hDes\": -344,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Crushed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -483,\n      \"tAsc\": 1374,\n      \"tDes\": -115,\n      \"tLGap\": 100,\n      \"wAsc\": 1820,\n      \"wDes\": 483,\n      \"xH\": 958,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1820,\n      \"hAsc\": 1820,\n      \"hDes\": -483,\n      \"lGap\": 51\n    }\n  },\n  {\n    \"family\": \"Cuprum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 895,\n      \"des\": -260,\n      \"tAsc\": 895,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 1057,\n      \"hAsc\": 895,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cute Font\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 710,\n      \"des\": -290,\n      \"tAsc\": 710,\n      \"tDes\": -290,\n      \"tLGap\": 250,\n      \"wAsc\": 708,\n      \"wDes\": 290,\n      \"xH\": 312,\n      \"capH\": 429,\n      \"yMin\": -291,\n      \"yMax\": 708,\n      \"hAsc\": 710,\n      \"hDes\": -290,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Cutive\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1580,\n      \"des\": -666,\n      \"tAsc\": 1580,\n      \"tDes\": -666,\n      \"tLGap\": 0,\n      \"wAsc\": 2470,\n      \"wDes\": 804,\n      \"xH\": 1160,\n      \"capH\": 1714,\n      \"yMin\": -778,\n      \"yMax\": 2470,\n      \"hAsc\": 1580,\n      \"hDes\": -666,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Cutive Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1697,\n      \"des\": -558,\n      \"tAsc\": 1697,\n      \"tDes\": -558,\n      \"tLGap\": 0,\n      \"wAsc\": 1697,\n      \"wDes\": 558,\n      \"xH\": 774,\n      \"capH\": 1171,\n      \"yMin\": -558,\n      \"yMax\": 1697,\n      \"hAsc\": 1697,\n      \"hDes\": -558,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dai Banna SIL\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1685,\n      \"des\": -638,\n      \"tAsc\": 1685,\n      \"tDes\": -638,\n      \"tLGap\": 0,\n      \"wAsc\": 1685,\n      \"wDes\": 638,\n      \"xH\": 906,\n      \"capH\": 1355,\n      \"yMin\": -627,\n      \"yMax\": 1635,\n      \"hAsc\": 1685,\n      \"hDes\": -638,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Damion\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -746,\n      \"tAsc\": 2068,\n      \"tDes\": -746,\n      \"tLGap\": 0,\n      \"wAsc\": 2122,\n      \"wDes\": 747,\n      \"xH\": 720,\n      \"capH\": 1440,\n      \"yMin\": -747,\n      \"yMax\": 2068,\n      \"hAsc\": 2068,\n      \"hDes\": -746,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dancing Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1096,\n      \"wDes\": 306,\n      \"xH\": 332,\n      \"capH\": 720,\n      \"yMin\": -284,\n      \"yMax\": 1095,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Danfo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 716,\n      \"yMin\": -288,\n      \"yMax\": 1065,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dangrek\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2353,\n      \"wDes\": 1130,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1130,\n      \"yMax\": 2353,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Darker Grotesque\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -296,\n      \"tAsc\": 1060,\n      \"tDes\": -296,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 295,\n      \"xH\": 406,\n      \"capH\": 563,\n      \"yMin\": -204,\n      \"yMax\": 871,\n      \"hAsc\": 1060,\n      \"hDes\": -296,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Darumadrop One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 435,\n      \"capH\": 590,\n      \"yMin\": -279,\n      \"yMax\": 860,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Datatype\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 251,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 976,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"David Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1599,\n      \"des\": -449,\n      \"tAsc\": 1599,\n      \"tDes\": -449,\n      \"tLGap\": 0,\n      \"wAsc\": 2207,\n      \"wDes\": 733,\n      \"xH\": 989,\n      \"capH\": 1360,\n      \"yMin\": -725,\n      \"yMax\": 2169,\n      \"hAsc\": 1599,\n      \"hDes\": -449,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dawning of a New Day\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1151,\n      \"des\": -500,\n      \"tAsc\": 1151,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 500,\n      \"xH\": 218,\n      \"capH\": 818,\n      \"yMin\": -462,\n      \"yMax\": 1151,\n      \"hAsc\": 1151,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Days One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -567,\n      \"tAsc\": 2040,\n      \"tDes\": -568,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 567,\n      \"xH\": 1096,\n      \"capH\": 1434,\n      \"yMin\": -567,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -567,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dekko\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 910,\n      \"des\": -519,\n      \"tAsc\": 910,\n      \"tDes\": -519,\n      \"tLGap\": 0,\n      \"wAsc\": 910,\n      \"wDes\": 519,\n      \"xH\": 432,\n      \"capH\": 556,\n      \"yMin\": -519,\n      \"yMax\": 909,\n      \"hAsc\": 910,\n      \"hDes\": -519,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dela Gothic One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 726,\n      \"yMin\": -288,\n      \"yMax\": 1150,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delicious Handrawn\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 357,\n      \"xH\": 500,\n      \"capH\": 850,\n      \"yMin\": -357,\n      \"yMax\": 1062,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -270,\n      \"tAsc\": 986,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 270,\n      \"xH\": 85,\n      \"capH\": 195,\n      \"yMin\": -270,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -270,\n      \"tAsc\": 986,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 270,\n      \"xH\": 113,\n      \"capH\": 282,\n      \"yMin\": -270,\n      \"yMax\": 986,\n      \"hAsc\": 986,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Delius Unicase\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -236,\n      \"tAsc\": 1016,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 1016,\n      \"wDes\": 236,\n      \"xH\": 320,\n      \"capH\": 195,\n      \"yMin\": -236,\n      \"yMax\": 1016,\n      \"hAsc\": 1016,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Della Respira\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2196,\n      \"des\": -607,\n      \"tAsc\": 2196,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 2196,\n      \"wDes\": 607,\n      \"yMin\": -632,\n      \"yMax\": 2207,\n      \"hAsc\": 2196,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Denk One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2118,\n      \"des\": -442,\n      \"tAsc\": 2118,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 2631,\n      \"wDes\": 609,\n      \"xH\": 1202,\n      \"capH\": 1690,\n      \"yMin\": -609,\n      \"yMax\": 2631,\n      \"hAsc\": 2118,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Devonshire\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 981,\n      \"des\": -433,\n      \"tAsc\": 981,\n      \"tDes\": -433,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 433,\n      \"xH\": 405,\n      \"capH\": 664,\n      \"yMin\": -433,\n      \"yMax\": 981,\n      \"hAsc\": 981,\n      \"hDes\": -433,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dhurjati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 870,\n      \"asc\": 1101,\n      \"des\": -509,\n      \"tAsc\": 1101,\n      \"tDes\": -509,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 509,\n      \"xH\": 314,\n      \"capH\": 419,\n      \"yMin\": -509,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -509,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Didact Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -265,\n      \"tAsc\": 1046,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 267,\n      \"xH\": 468,\n      \"capH\": 682,\n      \"yMin\": -267,\n      \"yMax\": 1127,\n      \"hAsc\": 1046,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diphylleia\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 476,\n      \"capH\": 674,\n      \"yMin\": -238,\n      \"yMax\": 925,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diplomata\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -287,\n      \"tAsc\": 930,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 396,\n      \"xH\": 558,\n      \"capH\": 650,\n      \"yMin\": -396,\n      \"yMax\": 1003,\n      \"hAsc\": 930,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Diplomata SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -287,\n      \"tAsc\": 930,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 396,\n      \"xH\": 558,\n      \"capH\": 650,\n      \"yMin\": -396,\n      \"yMax\": 1003,\n      \"hAsc\": 930,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 992,\n      \"wDes\": 310,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -270,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 310,\n      \"xH\": 504,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Serif Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 335,\n      \"xH\": 481,\n      \"capH\": 660,\n      \"yMin\": -265,\n      \"yMax\": 916,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DM Serif Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 335,\n      \"xH\": 480,\n      \"capH\": 661,\n      \"yMin\": -263,\n      \"yMax\": 918,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Do Hyeon\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 636,\n      \"capH\": 851,\n      \"yMin\": -174,\n      \"yMax\": 761,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Dokdo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 696,\n      \"des\": -304,\n      \"tAsc\": 696,\n      \"tDes\": -304,\n      \"tLGap\": 250,\n      \"wAsc\": 696,\n      \"wDes\": 394,\n      \"xH\": 272,\n      \"capH\": 475,\n      \"yMin\": -394,\n      \"yMax\": 695,\n      \"hAsc\": 696,\n      \"hDes\": -304,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Domine\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -240,\n      \"tAsc\": 900,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 240,\n      \"xH\": 540,\n      \"capH\": 720,\n      \"yMin\": -240,\n      \"yMax\": 908,\n      \"hAsc\": 900,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Donegal One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1020,\n      \"capH\": 1530,\n      \"yMin\": -537,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dongle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -598,\n      \"tAsc\": 570,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 598,\n      \"xH\": 280,\n      \"capH\": 395,\n      \"yMin\": -460,\n      \"yMax\": 712,\n      \"hAsc\": 850,\n      \"hDes\": -598,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Doppio One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -500,\n      \"tAsc\": 2060,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2060,\n      \"wDes\": 500,\n      \"xH\": 1055,\n      \"capH\": 1427,\n      \"yMin\": -500,\n      \"yMax\": 2060,\n      \"hAsc\": 2060,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dorsa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 857,\n      \"des\": -200,\n      \"tAsc\": 857,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 857,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 857,\n      \"hAsc\": 857,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dosis\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1027,\n      \"des\": -237,\n      \"tAsc\": 1027,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1123,\n      \"wDes\": 237,\n      \"xH\": 472,\n      \"capH\": 731,\n      \"yMin\": -237,\n      \"yMax\": 1074,\n      \"hAsc\": 1027,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DotGothic16\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 787,\n      \"yMin\": -120,\n      \"yMax\": 880,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Doto\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -300,\n      \"yMax\": 900,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dr Sugiyama\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1009,\n      \"des\": -450,\n      \"tAsc\": 1009,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 450,\n      \"xH\": 235,\n      \"capH\": 710,\n      \"yMin\": -450,\n      \"yMax\": 1009,\n      \"hAsc\": 1009,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Duru Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1157,\n      \"capH\": 1554,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Dynalight\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1840,\n      \"des\": -645,\n      \"tAsc\": 1840,\n      \"tDes\": -645,\n      \"tLGap\": 0,\n      \"wAsc\": 1840,\n      \"wDes\": 645,\n      \"xH\": 723,\n      \"capH\": 1441,\n      \"yMin\": -645,\n      \"yMax\": 1840,\n      \"hAsc\": 1840,\n      \"hDes\": -645,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"DynaPuff\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -235,\n      \"tAsc\": 965,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 985,\n      \"wDes\": 279,\n      \"xH\": 620,\n      \"capH\": 730,\n      \"yMin\": -279,\n      \"yMax\": 985,\n      \"hAsc\": 965,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Eagle Lake\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2420,\n      \"des\": -925,\n      \"tAsc\": 2420,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 2420,\n      \"wDes\": 925,\n      \"xH\": 1094,\n      \"capH\": 1518,\n      \"yMin\": -926,\n      \"yMax\": 2420,\n      \"hAsc\": 2420,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"East Sea Dokdo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 706,\n      \"des\": -294,\n      \"tAsc\": 706,\n      \"tDes\": -294,\n      \"tLGap\": 250,\n      \"wAsc\": 707,\n      \"wDes\": 297,\n      \"xH\": 239,\n      \"capH\": 418,\n      \"yMin\": -297,\n      \"yMax\": 707,\n      \"hAsc\": 706,\n      \"hDes\": -294,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Eater\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2898,\n      \"des\": -919,\n      \"tAsc\": 2898,\n      \"tDes\": -919,\n      \"tLGap\": 0,\n      \"wAsc\": 2898,\n      \"wDes\": 919,\n      \"xH\": 1706,\n      \"capH\": 1729,\n      \"yMin\": -919,\n      \"yMax\": 2898,\n      \"hAsc\": 2898,\n      \"hDes\": -919,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"EB Garamond\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1007,\n      \"des\": -298,\n      \"tAsc\": 1007,\n      \"tDes\": -298,\n      \"tLGap\": 0,\n      \"wAsc\": 1047,\n      \"wDes\": 390,\n      \"xH\": 400,\n      \"capH\": 650,\n      \"yMin\": -324,\n      \"yMax\": 985,\n      \"hAsc\": 1007,\n      \"hDes\": -298,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Economica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 949,\n      \"des\": -200,\n      \"tAsc\": 949,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 200,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -200,\n      \"yMax\": 927,\n      \"hAsc\": 949,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Eczar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1143,\n      \"des\": -634,\n      \"tAsc\": 1143,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1143,\n      \"wDes\": 634,\n      \"xH\": 468,\n      \"capH\": 650,\n      \"yMin\": -473,\n      \"yMax\": 1021,\n      \"hAsc\": 1143,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Arrows\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -857,\n      \"yMax\": 2002,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2002,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -865,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu AU VIC WA NT Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Cursive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2642,\n      \"des\": -926,\n      \"tAsc\": 2642,\n      \"tDes\": -926,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 945,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -940,\n      \"yMax\": 2777,\n      \"hAsc\": 2642,\n      \"hDes\": -926,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Foundation\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu NSW ACT Hand Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2642,\n      \"des\": -926,\n      \"tAsc\": 2642,\n      \"tDes\": -926,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 945,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -940,\n      \"yMax\": 2777,\n      \"hAsc\": 2642,\n      \"hDes\": -926,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu QLD Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -364,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu QLD Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2727,\n      \"des\": -1143,\n      \"tAsc\": 2727,\n      \"tDes\": -1143,\n      \"tLGap\": 0,\n      \"wAsc\": 3409,\n      \"wDes\": 1143,\n      \"xH\": 1055,\n      \"capH\": 1958,\n      \"yMin\": -1143,\n      \"yMax\": 3158,\n      \"hAsc\": 2727,\n      \"hDes\": -1143,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu SA Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu SA Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 2925,\n      \"wDes\": 946,\n      \"xH\": 1082,\n      \"capH\": 2008,\n      \"yMin\": -946,\n      \"yMax\": 2777,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu TAS Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -356,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Beginner\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1016,\n      \"des\": -244,\n      \"tAsc\": 1016,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 368,\n      \"xH\": 416,\n      \"capH\": 772,\n      \"yMin\": -363,\n      \"yMax\": 890,\n      \"hAsc\": 1016,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -861,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Edu VIC WA NT Hand Pre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2576,\n      \"des\": -903,\n      \"tAsc\": 2576,\n      \"tDes\": -903,\n      \"tLGap\": 0,\n      \"wAsc\": 3205,\n      \"wDes\": 903,\n      \"xH\": 995,\n      \"capH\": 1847,\n      \"yMin\": -860,\n      \"yMax\": 2751,\n      \"hAsc\": 2576,\n      \"hDes\": -903,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"El Messiri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1019,\n      \"des\": -544,\n      \"tAsc\": 1019,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 544,\n      \"xH\": 480,\n      \"capH\": 660,\n      \"yMin\": -437,\n      \"yMax\": 993,\n      \"hAsc\": 1019,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Electrolize\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 911,\n      \"des\": -275,\n      \"tAsc\": 911,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 911,\n      \"wDes\": 275,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 911,\n      \"hAsc\": 911,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elms Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1230,\n      \"wDes\": 330,\n      \"xH\": 480,\n      \"capH\": 700,\n      \"yMin\": -330,\n      \"yMax\": 1156,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elsie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -274,\n      \"tAsc\": 878,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 878,\n      \"wDes\": 274,\n      \"xH\": 511,\n      \"capH\": 650,\n      \"yMin\": -238,\n      \"yMax\": 872,\n      \"hAsc\": 878,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Elsie Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 878,\n      \"des\": -274,\n      \"tAsc\": 878,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 878,\n      \"wDes\": 274,\n      \"xH\": 511,\n      \"capH\": 650,\n      \"yMin\": -235,\n      \"yMax\": 872,\n      \"hAsc\": 878,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Emblema One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -546,\n      \"tAsc\": 1898,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 546,\n      \"xH\": 1002,\n      \"capH\": 1361,\n      \"yMin\": -546,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Emilys Candy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 996,\n      \"des\": -286,\n      \"tAsc\": 996,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 996,\n      \"wDes\": 293,\n      \"xH\": 529,\n      \"capH\": 762,\n      \"yMin\": -286,\n      \"yMax\": 996,\n      \"hAsc\": 996,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1080,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2142,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2149,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2146,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1080,\n      \"capH\": 1480,\n      \"yMin\": -466,\n      \"yMax\": 2142,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -465,\n      \"yMax\": 2141,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Encode Sans Semi Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2060,\n      \"des\": -440,\n      \"tAsc\": 2060,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2758,\n      \"wDes\": 520,\n      \"xH\": 1085,\n      \"capH\": 1480,\n      \"yMin\": -467,\n      \"yMax\": 2143,\n      \"hAsc\": 2060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Engagement\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1843,\n      \"des\": -684,\n      \"tAsc\": 1843,\n      \"tDes\": -684,\n      \"tLGap\": 0,\n      \"wAsc\": 1843,\n      \"wDes\": 684,\n      \"xH\": 653,\n      \"capH\": 1500,\n      \"yMin\": -684,\n      \"yMax\": 1843,\n      \"hAsc\": 1843,\n      \"hDes\": -684,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Englebert\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2064,\n      \"des\": -598,\n      \"tAsc\": 2064,\n      \"tDes\": -598,\n      \"tLGap\": 0,\n      \"wAsc\": 1954,\n      \"wDes\": 637,\n      \"xH\": 1077,\n      \"capH\": 1466,\n      \"yMin\": -637,\n      \"yMax\": 1954,\n      \"hAsc\": 2064,\n      \"hDes\": -598,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Enriqueta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -261,\n      \"tAsc\": 1077,\n      \"tDes\": -261,\n      \"tLGap\": 0,\n      \"wAsc\": 1053,\n      \"wDes\": 295,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -257,\n      \"yMax\": 1031,\n      \"hAsc\": 1077,\n      \"hDes\": -261,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ephesis\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -400,\n      \"tAsc\": 900,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 646,\n      \"xH\": 300,\n      \"capH\": 670,\n      \"yMin\": -618,\n      \"yMax\": 953,\n      \"hAsc\": 900,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epilogue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1580,\n      \"des\": -470,\n      \"tAsc\": 1580,\n      \"tDes\": -470,\n      \"tLGap\": 0,\n      \"wAsc\": 2310,\n      \"wDes\": 520,\n      \"xH\": 1062,\n      \"capH\": 1475,\n      \"yMin\": -467,\n      \"yMax\": 2133,\n      \"hAsc\": 1580,\n      \"hDes\": -470,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epunda Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -316,\n      \"tAsc\": 985,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -293,\n      \"yMax\": 1012,\n      \"hAsc\": 985,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Epunda Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -316,\n      \"tAsc\": 985,\n      \"tDes\": -316,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -293,\n      \"yMax\": 900,\n      \"hAsc\": 985,\n      \"hDes\": -316,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Erica One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1153,\n      \"des\": -339,\n      \"tAsc\": 1153,\n      \"tDes\": -339,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 339,\n      \"xH\": 591,\n      \"capH\": 691,\n      \"yMin\": -339,\n      \"yMax\": 1153,\n      \"hAsc\": 1153,\n      \"hDes\": -339,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Esteban\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -290,\n      \"tAsc\": 984,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 290,\n      \"xH\": 127,\n      \"capH\": 137,\n      \"yMin\": -290,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Estonia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -340,\n      \"tAsc\": 900,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 789,\n      \"xH\": 261,\n      \"capH\": 447,\n      \"yMin\": -789,\n      \"yMax\": 1003,\n      \"hAsc\": 900,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Euphoria Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1250,\n      \"asc\": 1014,\n      \"des\": -442,\n      \"tAsc\": 1013,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 442,\n      \"xH\": 344,\n      \"capH\": 274,\n      \"yMin\": -442,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ewert\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -299,\n      \"tAsc\": 944,\n      \"tDes\": -299,\n      \"tLGap\": 0,\n      \"wAsc\": 944,\n      \"wDes\": 299,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -299,\n      \"yMax\": 944,\n      \"hAsc\": 944,\n      \"hDes\": -299,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exile\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -350,\n      \"tAsc\": 1000,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 482,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -360,\n      \"yMax\": 1099,\n      \"hAsc\": 1000,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1002,\n      \"des\": -327,\n      \"tAsc\": 1002,\n      \"tDes\": -327,\n      \"tLGap\": 0,\n      \"wAsc\": 1134,\n      \"wDes\": 270,\n      \"xH\": 531,\n      \"capH\": 732,\n      \"yMin\": -270,\n      \"yMax\": 1102,\n      \"hAsc\": 1002,\n      \"hDes\": -327,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Exo 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 999,\n      \"des\": -201,\n      \"tAsc\": 999,\n      \"tDes\": -201,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 311,\n      \"xH\": 487,\n      \"capH\": 690,\n      \"yMin\": -275,\n      \"yMax\": 1051,\n      \"hAsc\": 999,\n      \"hDes\": -201,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Expletus Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2066,\n      \"des\": -612,\n      \"tAsc\": 2066,\n      \"tDes\": -612,\n      \"tLGap\": 0,\n      \"wAsc\": 1798,\n      \"wDes\": 586,\n      \"xH\": 1034,\n      \"capH\": 1454,\n      \"yMin\": -586,\n      \"yMax\": 1798,\n      \"hAsc\": 2066,\n      \"hDes\": -612,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Explora\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 580,\n      \"xH\": 325,\n      \"capH\": 542,\n      \"yMin\": -580,\n      \"yMax\": 938,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faculty Glyphic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1037,\n      \"des\": -262,\n      \"tAsc\": 1037,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 280,\n      \"xH\": 550,\n      \"capH\": 775,\n      \"yMin\": -276,\n      \"yMax\": 1010,\n      \"hAsc\": 1037,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fahkwang\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -292,\n      \"tAsc\": 1008,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1258,\n      \"wDes\": 456,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -452,\n      \"yMax\": 1203,\n      \"hAsc\": 1008,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Familjen Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1230,\n      \"des\": -270,\n      \"tAsc\": 1230,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1230,\n      \"wDes\": 270,\n      \"xH\": 600,\n      \"capH\": 780,\n      \"yMin\": -265,\n      \"yMax\": 1200,\n      \"hAsc\": 1230,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fanwood Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3761,\n      \"des\": -1609,\n      \"tAsc\": 3761,\n      \"tDes\": -1609,\n      \"tLGap\": 0,\n      \"wAsc\": 3761,\n      \"wDes\": 1609,\n      \"xH\": 1606,\n      \"capH\": 1282,\n      \"yMin\": -1601,\n      \"yMax\": 3687,\n      \"hAsc\": 3761,\n      \"hDes\": -1609,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Farro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 306,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -285,\n      \"yMax\": 1014,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Farsan\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 711,\n      \"des\": -289,\n      \"tAsc\": 711,\n      \"tDes\": -289,\n      \"tLGap\": 200,\n      \"wAsc\": 993,\n      \"wDes\": 391,\n      \"xH\": 441,\n      \"capH\": 664,\n      \"yMin\": -391,\n      \"yMax\": 993,\n      \"hAsc\": 711,\n      \"hDes\": -289,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Fascinate\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2125,\n      \"des\": -591,\n      \"tAsc\": 2125,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 2125,\n      \"wDes\": 591,\n      \"xH\": 1024,\n      \"capH\": 1436,\n      \"yMin\": -591,\n      \"yMax\": 2125,\n      \"hAsc\": 2125,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fascinate Inline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2125,\n      \"des\": -591,\n      \"tAsc\": 2125,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 2125,\n      \"wDes\": 591,\n      \"xH\": 1024,\n      \"capH\": 1436,\n      \"yMin\": -591,\n      \"yMax\": 2125,\n      \"hAsc\": 2125,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faster One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 898,\n      \"des\": -165,\n      \"tAsc\": 898,\n      \"tDes\": -165,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 372,\n      \"xH\": 529,\n      \"capH\": 625,\n      \"yMin\": -372,\n      \"yMax\": 999,\n      \"hAsc\": 898,\n      \"hDes\": -165,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fasthand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2502,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2502,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fauna One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 987,\n      \"des\": -243,\n      \"tAsc\": 987,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 281,\n      \"xH\": 572,\n      \"capH\": 730,\n      \"yMin\": -281,\n      \"yMax\": 1043,\n      \"hAsc\": 987,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Faustina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1043,\n      \"des\": -217,\n      \"tAsc\": 1043,\n      \"tDes\": -217,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 215,\n      \"xH\": 494,\n      \"capH\": 648,\n      \"yMin\": -212,\n      \"yMax\": 1014,\n      \"hAsc\": 1043,\n      \"hDes\": -217,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Federant\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 942,\n      \"des\": -284,\n      \"tAsc\": 942,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 284,\n      \"xH\": 516,\n      \"capH\": 714,\n      \"yMin\": -377,\n      \"yMax\": 949,\n      \"hAsc\": 942,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Federo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1883,\n      \"des\": -530,\n      \"tAsc\": 1883,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 1883,\n      \"wDes\": 530,\n      \"xH\": 942,\n      \"capH\": 1487,\n      \"yMin\": -530,\n      \"yMax\": 1883,\n      \"hAsc\": 1883,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Felipa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -319,\n      \"tAsc\": 966,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 319,\n      \"xH\": 501,\n      \"capH\": 752,\n      \"yMin\": -319,\n      \"yMax\": 966,\n      \"hAsc\": 966,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fenix\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 879,\n      \"des\": -238,\n      \"tAsc\": 879,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 879,\n      \"wDes\": 238,\n      \"xH\": 450,\n      \"capH\": 650,\n      \"yMin\": -238,\n      \"yMax\": 879,\n      \"hAsc\": 879,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Festive\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -590,\n      \"tAsc\": 1100,\n      \"tDes\": -590,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 590,\n      \"xH\": 360,\n      \"capH\": 800,\n      \"yMin\": -587,\n      \"yMax\": 1055,\n      \"hAsc\": 1100,\n      \"hDes\": -590,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Figtree\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 222,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -220,\n      \"yMax\": 917,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Finger Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1097,\n      \"des\": -377,\n      \"tAsc\": 1097,\n      \"tDes\": -377,\n      \"tLGap\": 0,\n      \"wAsc\": 1097,\n      \"wDes\": 377,\n      \"xH\": 540,\n      \"capH\": 720,\n      \"yMin\": -377,\n      \"yMax\": 1097,\n      \"hAsc\": 1097,\n      \"hDes\": -377,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Finlandica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 331,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -322,\n      \"yMax\": 1000,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1980,\n      \"des\": -644,\n      \"tAsc\": 1980,\n      \"tDes\": -644,\n      \"tLGap\": 0,\n      \"wAsc\": 2164,\n      \"wDes\": 1000,\n      \"xH\": 1053,\n      \"capH\": 1377,\n      \"yMin\": -1000,\n      \"yMax\": 2400,\n      \"hAsc\": 1980,\n      \"hDes\": -644,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -500,\n      \"yMax\": 1050,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -353,\n      \"yMax\": 1104,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 526,\n      \"capH\": 688,\n      \"yMin\": -350,\n      \"yMax\": 1101,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fira Sans Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -265,\n      \"tAsc\": 935,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 265,\n      \"xH\": 527,\n      \"capH\": 689,\n      \"yMin\": -352,\n      \"yMax\": 1101,\n      \"hAsc\": 935,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fjalla One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -508,\n      \"tAsc\": 2066,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 2702,\n      \"wDes\": 608,\n      \"xH\": 1377,\n      \"capH\": 1708,\n      \"yMin\": -531,\n      \"yMax\": 2702,\n      \"hAsc\": 2066,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fjord One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1940,\n      \"des\": -620,\n      \"tAsc\": 1940,\n      \"tDes\": -620,\n      \"tLGap\": 0,\n      \"wAsc\": 1940,\n      \"wDes\": 620,\n      \"xH\": 950,\n      \"capH\": 1448,\n      \"yMin\": -620,\n      \"yMax\": 1940,\n      \"hAsc\": 1940,\n      \"hDes\": -620,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flamenco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -231,\n      \"tAsc\": 800,\n      \"tDes\": -231,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 231,\n      \"xH\": 385,\n      \"capH\": 608,\n      \"yMin\": -229,\n      \"yMax\": 800,\n      \"hAsc\": 800,\n      \"hDes\": -231,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flavors\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1015,\n      \"des\": -293,\n      \"tAsc\": 1015,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 300,\n      \"xH\": 845,\n      \"capH\": 801,\n      \"yMin\": -293,\n      \"yMax\": 1014,\n      \"hAsc\": 1015,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fleur De Leah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -450,\n      \"tAsc\": 920,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 549,\n      \"xH\": 324,\n      \"capH\": 620,\n      \"yMin\": -549,\n      \"yMax\": 913,\n      \"hAsc\": 920,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Block\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 320,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Circular\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 320,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Flow Rounded\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 470,\n      \"capH\": 640,\n      \"yMin\": 0,\n      \"yMax\": 470,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Foldit\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -342,\n      \"yMax\": 965,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fondamento\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2060,\n      \"des\": -774,\n      \"tAsc\": 2060,\n      \"tDes\": -774,\n      \"tLGap\": 0,\n      \"wAsc\": 2060,\n      \"wDes\": 774,\n      \"xH\": 953,\n      \"capH\": 1439,\n      \"yMin\": -774,\n      \"yMax\": 2060,\n      \"hAsc\": 2060,\n      \"hDes\": -774,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fontdiner Swanky\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1047,\n      \"des\": -510,\n      \"tAsc\": 879,\n      \"tDes\": -251,\n      \"tLGap\": 40,\n      \"wAsc\": 1047,\n      \"wDes\": 510,\n      \"xH\": 579,\n      \"capH\": 805,\n      \"yMin\": -510,\n      \"yMax\": 1047,\n      \"hAsc\": 1047,\n      \"hDes\": -510,\n      \"lGap\": 20\n    }\n  },\n  {\n    \"family\": \"Forum\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -248,\n      \"tAsc\": 856,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 248,\n      \"xH\": 420,\n      \"capH\": 660,\n      \"yMin\": -248,\n      \"yMax\": 856,\n      \"hAsc\": 856,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fragment Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 265,\n      \"xH\": 524,\n      \"capH\": 699,\n      \"yMin\": -265,\n      \"yMax\": 945,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Francois One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1089,\n      \"des\": -329,\n      \"tAsc\": 1089,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1351,\n      \"wDes\": 332,\n      \"xH\": 563,\n      \"capH\": 750,\n      \"yMin\": -332,\n      \"yMax\": 1351,\n      \"hAsc\": 1089,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Frank Ruhl Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 957,\n      \"des\": -334,\n      \"tAsc\": 957,\n      \"tDes\": -334,\n      \"tLGap\": 0,\n      \"wAsc\": 957,\n      \"wDes\": 334,\n      \"xH\": 468,\n      \"capH\": 660,\n      \"yMin\": -289,\n      \"yMax\": 947,\n      \"hAsc\": 957,\n      \"hDes\": -334,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fraunces\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1956,\n      \"des\": -510,\n      \"tAsc\": 1956,\n      \"tDes\": -510,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 609,\n      \"xH\": 964,\n      \"capH\": 1400,\n      \"yMin\": -523,\n      \"yMax\": 2176,\n      \"hAsc\": 1956,\n      \"hDes\": -510,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freckle Face\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1946,\n      \"des\": -571,\n      \"tAsc\": 1946,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1946,\n      \"wDes\": 571,\n      \"xH\": 1147,\n      \"capH\": 1563,\n      \"yMin\": -571,\n      \"yMax\": 1946,\n      \"hAsc\": 1946,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fredericka the Great\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1001,\n      \"des\": -254,\n      \"tAsc\": 1001,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 1001,\n      \"wDes\": 254,\n      \"xH\": 519,\n      \"capH\": 772,\n      \"yMin\": -254,\n      \"yMax\": 1001,\n      \"hAsc\": 1001,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fredoka\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -236,\n      \"tAsc\": 974,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 252,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 962,\n      \"hAsc\": 974,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freehand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Freeman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -280,\n      \"tAsc\": 1050,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1195,\n      \"wDes\": 350,\n      \"xH\": 564,\n      \"capH\": 750,\n      \"yMin\": -349,\n      \"yMax\": 1188,\n      \"hAsc\": 1050,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fresca\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -285,\n      \"tAsc\": 869,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 285,\n      \"xH\": 484,\n      \"capH\": 648,\n      \"yMin\": -285,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Frijole\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1075,\n      \"des\": -337,\n      \"tAsc\": 1075,\n      \"tDes\": -7,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 337,\n      \"xH\": 712,\n      \"capH\": 788,\n      \"yMin\": -337,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -337,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fruktur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2726,\n      \"wDes\": 558,\n      \"xH\": 1182,\n      \"capH\": 1529,\n      \"yMin\": -558,\n      \"yMax\": 2557,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fugaz One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -422,\n      \"tAsc\": 1046,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 1046,\n      \"wDes\": 422,\n      \"xH\": 488,\n      \"capH\": 720,\n      \"yMin\": -422,\n      \"yMax\": 1046,\n      \"hAsc\": 1046,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fuggles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -351,\n      \"tAsc\": 850,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 555,\n      \"xH\": 400,\n      \"capH\": 667,\n      \"yMin\": -552,\n      \"yMax\": 781,\n      \"hAsc\": 850,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Funnel Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1200,\n      \"des\": -300,\n      \"tAsc\": 1200,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 330,\n      \"xH\": 600,\n      \"capH\": 810,\n      \"yMin\": -336,\n      \"yMax\": 1132,\n      \"hAsc\": 1200,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Funnel Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1200,\n      \"des\": -300,\n      \"tAsc\": 1200,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 330,\n      \"xH\": 600,\n      \"capH\": 810,\n      \"yMin\": -336,\n      \"yMax\": 1132,\n      \"hAsc\": 1200,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fustat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -420,\n      \"tAsc\": 1000,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -518,\n      \"yMax\": 1007,\n      \"hAsc\": 1000,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Fuzzy Bubbles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1196,\n      \"wDes\": 362,\n      \"xH\": 520,\n      \"capH\": 670,\n      \"yMin\": -362,\n      \"yMax\": 1147,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ga Maamli\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1154,\n      \"wDes\": 347,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -306,\n      \"yMax\": 1154,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gabarito\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 295,\n      \"xH\": 488,\n      \"capH\": 681,\n      \"yMin\": -292,\n      \"yMax\": 960,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gabriela\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 986,\n      \"des\": -295,\n      \"tAsc\": 986,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 580,\n      \"xH\": 497,\n      \"capH\": 718,\n      \"yMin\": -580,\n      \"yMax\": 1045,\n      \"hAsc\": 986,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gaegu\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 760,\n      \"des\": -240,\n      \"tAsc\": 760,\n      \"tDes\": -240,\n      \"tLGap\": 250,\n      \"wAsc\": 762,\n      \"wDes\": 242,\n      \"xH\": 340,\n      \"capH\": 525,\n      \"yMin\": -240,\n      \"yMax\": 760,\n      \"hAsc\": 760,\n      \"hDes\": -240,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Gafata\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 921,\n      \"des\": -202,\n      \"tAsc\": 921,\n      \"tDes\": -202,\n      \"tLGap\": 0,\n      \"wAsc\": 921,\n      \"wDes\": 202,\n      \"xH\": 492,\n      \"capH\": 648,\n      \"yMin\": -202,\n      \"yMax\": 921,\n      \"hAsc\": 921,\n      \"hDes\": -202,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gajraj One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -400,\n      \"tAsc\": 1065,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 515,\n      \"xH\": 500,\n      \"capH\": 665,\n      \"yMin\": -505,\n      \"yMax\": 1051,\n      \"hAsc\": 1065,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1035,\n      \"des\": -592,\n      \"tAsc\": 1035,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 1035,\n      \"wDes\": 592,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -592,\n      \"yMax\": 1035,\n      \"hAsc\": 1035,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galdeano\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 820,\n      \"des\": -230,\n      \"tAsc\": 820,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 820,\n      \"wDes\": 230,\n      \"xH\": 166,\n      \"capH\": 605,\n      \"yMin\": -230,\n      \"yMax\": 820,\n      \"hAsc\": 820,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Galindo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2014,\n      \"des\": -883,\n      \"tAsc\": 2014,\n      \"tDes\": -883,\n      \"tLGap\": 0,\n      \"wAsc\": 2014,\n      \"wDes\": 883,\n      \"xH\": 1096,\n      \"capH\": 1505,\n      \"yMin\": -883,\n      \"yMax\": 2014,\n      \"hAsc\": 2014,\n      \"hDes\": -883,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gamja Flower\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 800,\n      \"des\": -224,\n      \"tAsc\": 800,\n      \"tDes\": -224,\n      \"tLGap\": 256,\n      \"wAsc\": 800,\n      \"wDes\": 258,\n      \"xH\": 311,\n      \"capH\": 526,\n      \"yMin\": -258,\n      \"yMax\": 799,\n      \"hAsc\": 800,\n      \"hDes\": -224,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Gantari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 261,\n      \"xH\": 470,\n      \"capH\": 668,\n      \"yMin\": -260,\n      \"yMax\": 976,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Garamond\",\n    \"fallbacks\": [\n      \"Baskerville\",\n      \"Baskerville Old Face\",\n      \"Hoefler Text\",\n      \"Times New Roman\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1765,\n      \"des\": -539,\n      \"tAsc\": 1339,\n      \"tDes\": -539,\n      \"tLGap\": 313,\n      \"wAsc\": 1765,\n      \"wDes\": 1765,\n      \"yMin\": -762,\n      \"yMax\": 2040,\n      \"hAsc\": 1765,\n      \"hDes\": -539,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Gasoek One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 620,\n      \"capH\": 770,\n      \"yMin\": -226,\n      \"yMax\": 1015,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gayathri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -1000,\n      \"tAsc\": 1500,\n      \"tDes\": -1000,\n      \"tLGap\": 0,\n      \"wAsc\": 2038,\n      \"wDes\": 1234,\n      \"xH\": 1000,\n      \"capH\": 1385,\n      \"yMin\": -1173,\n      \"yMax\": 2036,\n      \"hAsc\": 1500,\n      \"hDes\": -1000,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geist\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 262,\n      \"xH\": 530,\n      \"capH\": 710,\n      \"yMin\": -240,\n      \"yMax\": 940,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geist Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 262,\n      \"xH\": 530,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 1012,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gelasio\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -700,\n      \"tAsc\": 1900,\n      \"tDes\": -700,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 800,\n      \"xH\": 986,\n      \"capH\": 1419,\n      \"yMin\": -620,\n      \"yMax\": 2593,\n      \"hAsc\": 1900,\n      \"hDes\": -700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gemunu Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 884,\n      \"des\": -200,\n      \"tAsc\": 884,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 311,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -311,\n      \"yMax\": 863,\n      \"hAsc\": 884,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Genos\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 300,\n      \"xH\": 400,\n      \"capH\": 460,\n      \"yMin\": -201,\n      \"yMax\": 757,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gentium Book Plus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2250,\n      \"des\": -750,\n      \"tAsc\": 2250,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 750,\n      \"xH\": 930,\n      \"capH\": 1260,\n      \"yMin\": -950,\n      \"yMax\": 2600,\n      \"hAsc\": 2250,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gentium Plus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2250,\n      \"des\": -750,\n      \"tAsc\": 2250,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2250,\n      \"wDes\": 750,\n      \"xH\": 930,\n      \"capH\": 1260,\n      \"yMin\": -950,\n      \"yMax\": 2600,\n      \"hAsc\": 2250,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 821,\n      \"des\": -225,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 92,\n      \"wAsc\": 821,\n      \"wDes\": 225,\n      \"xH\": 451,\n      \"capH\": 573,\n      \"yMin\": -225,\n      \"yMax\": 821,\n      \"hAsc\": 821,\n      \"hDes\": -225,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Geologica\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1950,\n      \"des\": -550,\n      \"tAsc\": 1950,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 2518,\n      \"wDes\": 895,\n      \"xH\": 990,\n      \"capH\": 1400,\n      \"yMin\": -722,\n      \"yMax\": 2441,\n      \"hAsc\": 1950,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geom\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -235,\n      \"tAsc\": 1015,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 315,\n      \"xH\": 536,\n      \"capH\": 712,\n      \"yMin\": -263,\n      \"yMax\": 988,\n      \"hAsc\": 1015,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Georama\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -226,\n      \"tAsc\": 968,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 1184,\n      \"wDes\": 420,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -328,\n      \"yMax\": 1132,\n      \"hAsc\": 968,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Georgia\",\n    \"fallbacks\": [\"Times\", \"Times New Roman\", \"serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1878,\n      \"des\": -449,\n      \"tAsc\": 1549,\n      \"tDes\": -444,\n      \"tLGap\": 198,\n      \"wAsc\": 1878,\n      \"wDes\": 1878,\n      \"xH\": 986,\n      \"capH\": 1419,\n      \"yMin\": -621,\n      \"yMax\": 2201,\n      \"hAsc\": 1878,\n      \"hDes\": -449,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Geostar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -226,\n      \"tAsc\": 922,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 226,\n      \"xH\": 469,\n      \"capH\": 695,\n      \"yMin\": -226,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Geostar Fill\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -226,\n      \"tAsc\": 922,\n      \"tDes\": -226,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 226,\n      \"xH\": 469,\n      \"capH\": 695,\n      \"yMin\": -226,\n      \"yMax\": 922,\n      \"hAsc\": 922,\n      \"hDes\": -226,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Germania One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 911,\n      \"des\": -250,\n      \"tAsc\": 911,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 911,\n      \"wDes\": 250,\n      \"xH\": 539,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 911,\n      \"hAsc\": 911,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"GFS Didot\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 947,\n      \"des\": -277,\n      \"tAsc\": 703,\n      \"tDes\": -271,\n      \"tLGap\": 50,\n      \"wAsc\": 947,\n      \"wDes\": 277,\n      \"xH\": 456,\n      \"capH\": 689,\n      \"yMin\": -336,\n      \"yMax\": 1145,\n      \"hAsc\": 947,\n      \"hDes\": -277,\n      \"lGap\": 25\n    }\n  },\n  {\n    \"family\": \"GFS Neohellenic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -245,\n      \"tAsc\": 600,\n      \"tDes\": -222,\n      \"tLGap\": 47,\n      \"wAsc\": 873,\n      \"wDes\": 245,\n      \"xH\": 387,\n      \"capH\": 623,\n      \"yMin\": -286,\n      \"yMax\": 1051,\n      \"hAsc\": 873,\n      \"hDes\": -245,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Gideon Roman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 398,\n      \"xH\": 475,\n      \"capH\": 660,\n      \"yMin\": -398,\n      \"yMax\": 1018,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gidole\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1960,\n      \"des\": -560,\n      \"tAsc\": 1960,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2274,\n      \"wDes\": 717,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -717,\n      \"yMax\": 2274,\n      \"hAsc\": 1960,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gidugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1124,\n      \"asc\": 1294,\n      \"des\": -790,\n      \"tAsc\": 1294,\n      \"tDes\": -790,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 790,\n      \"xH\": 410,\n      \"capH\": 596,\n      \"yMin\": -790,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -790,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gilda Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 892,\n      \"des\": -285,\n      \"tAsc\": 892,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 290,\n      \"xH\": 473,\n      \"capH\": 700,\n      \"yMin\": -290,\n      \"yMax\": 989,\n      \"hAsc\": 892,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gill Sans\",\n    \"fallbacks\": [\"Gill Sans MT\", \"Calibri\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1880,\n      \"des\": -472,\n      \"tAsc\": 1415,\n      \"tDes\": -471,\n      \"tLGap\": 305,\n      \"wAsc\": 1880,\n      \"wDes\": 1880,\n      \"xH\": 920,\n      \"capH\": 1397,\n      \"yMin\": -473,\n      \"yMax\": 1896,\n      \"hAsc\": 1880,\n      \"hDes\": -472,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Girassol\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -250,\n      \"tAsc\": 944,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 326,\n      \"xH\": 540,\n      \"capH\": 750,\n      \"yMin\": -326,\n      \"yMax\": 1070,\n      \"hAsc\": 944,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Give You Glory\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1020,\n      \"des\": -625,\n      \"tAsc\": 1020,\n      \"tDes\": -627,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 621,\n      \"xH\": 551,\n      \"capH\": 747,\n      \"yMin\": -619,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glass Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 835,\n      \"des\": -200,\n      \"tAsc\": 835,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 200,\n      \"xH\": 480,\n      \"capH\": 638,\n      \"yMin\": -200,\n      \"yMax\": 834,\n      \"hAsc\": 835,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glegoo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1267,\n      \"des\": -526,\n      \"tAsc\": 1267,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 1267,\n      \"wDes\": 526,\n      \"yMin\": -518,\n      \"yMax\": 1267,\n      \"hAsc\": 1267,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gloock\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -225,\n      \"tAsc\": 975,\n      \"tDes\": -225,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 363,\n      \"xH\": 508,\n      \"capH\": 750,\n      \"yMin\": -363,\n      \"yMax\": 1004,\n      \"hAsc\": 975,\n      \"hDes\": -225,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gloria Hallelujah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1439,\n      \"des\": -591,\n      \"tAsc\": 1439,\n      \"tDes\": -591,\n      \"tLGap\": 0,\n      \"wAsc\": 1439,\n      \"wDes\": 591,\n      \"xH\": 580,\n      \"capH\": 904,\n      \"yMin\": -591,\n      \"yMax\": 1439,\n      \"hAsc\": 1439,\n      \"hDes\": -591,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Glory\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -220,\n      \"tAsc\": 900,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 280,\n      \"xH\": 472,\n      \"capH\": 672,\n      \"yMin\": -242,\n      \"yMax\": 974,\n      \"hAsc\": 900,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gluten\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1290,\n      \"des\": -475,\n      \"tAsc\": 1290,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 2395,\n      \"wDes\": 550,\n      \"xH\": 833,\n      \"capH\": 1167,\n      \"yMin\": -470,\n      \"yMax\": 2064,\n      \"hAsc\": 1290,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goblin One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -640,\n      \"tAsc\": 1920,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 640,\n      \"xH\": 1107,\n      \"capH\": 1434,\n      \"yMin\": -640,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gochi Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1579,\n      \"des\": -835,\n      \"tAsc\": 1579,\n      \"tDes\": -835,\n      \"tLGap\": 0,\n      \"wAsc\": 1579,\n      \"wDes\": 835,\n      \"xH\": 765,\n      \"capH\": 975,\n      \"yMin\": -835,\n      \"yMax\": 1579,\n      \"hAsc\": 1579,\n      \"hDes\": -835,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goldman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 700,\n      \"xH\": 448,\n      \"capH\": 588,\n      \"yMin\": -680,\n      \"yMax\": 1054,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Golos Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -220,\n      \"tAsc\": 980,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 980,\n      \"wDes\": 230,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -230,\n      \"yMax\": 955,\n      \"hAsc\": 980,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -286,\n      \"tAsc\": 966,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1323,\n      \"wDes\": 1079,\n      \"xH\": 510,\n      \"capH\": 716,\n      \"yMin\": -989,\n      \"yMax\": 1263,\n      \"hAsc\": 966,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1932,\n      \"des\": -572,\n      \"tAsc\": 1932,\n      \"tDes\": -572,\n      \"tLGap\": 0,\n      \"wAsc\": 2377,\n      \"wDes\": 930,\n      \"xH\": 1047,\n      \"capH\": 1432,\n      \"yMin\": -811,\n      \"yMax\": 2303,\n      \"hAsc\": 1932,\n      \"hDes\": -572,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Google Sans Flex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1932,\n      \"des\": -572,\n      \"tAsc\": 1932,\n      \"tDes\": -572,\n      \"tLGap\": 0,\n      \"wAsc\": 2452,\n      \"wDes\": 999,\n      \"xH\": 1020,\n      \"capH\": 1432,\n      \"yMin\": -605,\n      \"yMax\": 2210,\n      \"hAsc\": 1932,\n      \"hDes\": -572,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gorditas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 954,\n      \"des\": -259,\n      \"tAsc\": 954,\n      \"tDes\": -259,\n      \"tLGap\": 0,\n      \"wAsc\": 954,\n      \"wDes\": 259,\n      \"xH\": 274,\n      \"capH\": 380,\n      \"yMin\": -250,\n      \"yMax\": 948,\n      \"hAsc\": 954,\n      \"hDes\": -259,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gothic A1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 817,\n      \"des\": -207,\n      \"tAsc\": 817,\n      \"tDes\": -207,\n      \"tLGap\": 256,\n      \"wAsc\": 1238,\n      \"wDes\": 378,\n      \"xH\": 538,\n      \"capH\": 749,\n      \"yMin\": -329,\n      \"yMax\": 1137,\n      \"hAsc\": 817,\n      \"hDes\": -207,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Gotu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -545,\n      \"tAsc\": 1115,\n      \"tDes\": -545,\n      \"tLGap\": 0,\n      \"wAsc\": 1124,\n      \"wDes\": 545,\n      \"xH\": 514,\n      \"capH\": 713,\n      \"yMin\": -543,\n      \"yMax\": 1124,\n      \"hAsc\": 1115,\n      \"hDes\": -545,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Goudy Bookletter 1911\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 983,\n      \"des\": -318,\n      \"tAsc\": 755,\n      \"tDes\": -269,\n      \"tLGap\": 92,\n      \"wAsc\": 983,\n      \"wDes\": 318,\n      \"xH\": 458,\n      \"capH\": 691,\n      \"yMin\": -319,\n      \"yMax\": 983,\n      \"hAsc\": 983,\n      \"hDes\": -318,\n      \"lGap\": 92\n    }\n  },\n  {\n    \"family\": \"Gowun Batang\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 775,\n      \"yMin\": -170,\n      \"yMax\": 1155,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gowun Dodum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 540,\n      \"capH\": 775,\n      \"yMin\": -170,\n      \"yMax\": 1158,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Graduate\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 953,\n      \"des\": -186,\n      \"tAsc\": 953,\n      \"tDes\": -186,\n      \"tLGap\": 0,\n      \"wAsc\": 953,\n      \"wDes\": 186,\n      \"xH\": 650,\n      \"capH\": 750,\n      \"yMin\": -186,\n      \"yMax\": 953,\n      \"hAsc\": 953,\n      \"hDes\": -186,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grand Hotel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1938,\n      \"des\": -844,\n      \"tAsc\": 1938,\n      \"tDes\": -844,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 844,\n      \"xH\": 803,\n      \"capH\": 1434,\n      \"yMin\": -844,\n      \"yMax\": 1938,\n      \"hAsc\": 1938,\n      \"hDes\": -844,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grandiflora One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 407,\n      \"capH\": 687,\n      \"yMin\": -357,\n      \"yMax\": 1013,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grandstander\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1465,\n      \"des\": -530,\n      \"tAsc\": 1465,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2395,\n      \"wDes\": 915,\n      \"xH\": 1063,\n      \"capH\": 1291,\n      \"yMin\": -579,\n      \"yMax\": 2247,\n      \"hAsc\": 1465,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grape Nuts\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -325,\n      \"tAsc\": 900,\n      \"tDes\": -325,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 402,\n      \"xH\": 365,\n      \"capH\": 590,\n      \"yMin\": -319,\n      \"yMax\": 928,\n      \"hAsc\": 900,\n      \"hDes\": -325,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gravitas One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1937,\n      \"des\": -668,\n      \"tAsc\": 1937,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 1937,\n      \"wDes\": 668,\n      \"xH\": 1113,\n      \"capH\": 1417,\n      \"yMin\": -668,\n      \"yMax\": 1937,\n      \"hAsc\": 1937,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Great Vibes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 851,\n      \"des\": -401,\n      \"tAsc\": 851,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 590,\n      \"xH\": 328,\n      \"capH\": 750,\n      \"yMin\": -556,\n      \"yMax\": 1153,\n      \"hAsc\": 851,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grechen Fuemen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -320,\n      \"tAsc\": 900,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 304,\n      \"xH\": 317,\n      \"capH\": 580,\n      \"yMin\": -304,\n      \"yMax\": 1032,\n      \"hAsc\": 900,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grenze\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -380,\n      \"tAsc\": 1100,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 380,\n      \"xH\": 448,\n      \"capH\": 603,\n      \"yMin\": -252,\n      \"yMax\": 1017,\n      \"hAsc\": 1100,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grenze Gotisch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -380,\n      \"tAsc\": 1100,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 380,\n      \"xH\": 448,\n      \"capH\": 603,\n      \"yMin\": -271,\n      \"yMax\": 984,\n      \"hAsc\": 1100,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Grey Qo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -360,\n      \"tAsc\": 900,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 493,\n      \"xH\": 265,\n      \"capH\": 540,\n      \"yMin\": -473,\n      \"yMax\": 793,\n      \"hAsc\": 900,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Griffy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 984,\n      \"des\": -399,\n      \"tAsc\": 984,\n      \"tDes\": -399,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 399,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -399,\n      \"yMax\": 984,\n      \"hAsc\": 984,\n      \"hDes\": -399,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gruppo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1639,\n      \"des\": -340,\n      \"tAsc\": 1639,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1639,\n      \"wDes\": 372,\n      \"xH\": 766,\n      \"capH\": 1114,\n      \"yMin\": -354,\n      \"yMax\": 1588,\n      \"hAsc\": 1639,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gudea\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -264,\n      \"tAsc\": 972,\n      \"tDes\": -264,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 264,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -240,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -264,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gugi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -142,\n      \"tAsc\": 858,\n      \"tDes\": -142,\n      \"tLGap\": 250,\n      \"wAsc\": 869,\n      \"wDes\": 169,\n      \"xH\": 602,\n      \"capH\": 794,\n      \"yMin\": -169,\n      \"yMax\": 866,\n      \"hAsc\": 858,\n      \"hDes\": -142,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Gulzar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1500,\n      \"des\": -1200,\n      \"tAsc\": 1500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 1494,\n      \"wDes\": 900,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -900,\n      \"yMax\": 1494,\n      \"hAsc\": 1500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gupter\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -250,\n      \"tAsc\": 900,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 400,\n      \"xH\": 450,\n      \"capH\": 622,\n      \"yMin\": -235,\n      \"yMax\": 837,\n      \"hAsc\": 900,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gurajada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1070,\n      \"asc\": 1294,\n      \"des\": -810,\n      \"tAsc\": 1294,\n      \"tDes\": -810,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 810,\n      \"xH\": 358,\n      \"capH\": 482,\n      \"yMin\": -810,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -810,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gveret Levin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1221,\n      \"wDes\": 418,\n      \"xH\": 510,\n      \"capH\": 680,\n      \"yMin\": -418,\n      \"yMax\": 1221,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Gwendolyn\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -320,\n      \"tAsc\": 880,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 903,\n      \"wDes\": 641,\n      \"xH\": 290,\n      \"capH\": 618,\n      \"yMin\": -641,\n      \"yMax\": 892,\n      \"hAsc\": 880,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Habibi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 989,\n      \"capH\": 1508,\n      \"yMin\": -562,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hachi Maru Pop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -271,\n      \"yMax\": 812,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hahmlet\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 492,\n      \"capH\": 742,\n      \"yMin\": -265,\n      \"yMax\": 1116,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Halant\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1089,\n      \"des\": -486,\n      \"tAsc\": 1089,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1089,\n      \"wDes\": 486,\n      \"xH\": 504,\n      \"capH\": 660,\n      \"yMin\": -422,\n      \"yMax\": 1009,\n      \"hAsc\": 1089,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hammersmith One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1844,\n      \"des\": -716,\n      \"tAsc\": 1844,\n      \"tDes\": -716,\n      \"tLGap\": 0,\n      \"wAsc\": 1844,\n      \"wDes\": 716,\n      \"xH\": 1045,\n      \"capH\": 1330,\n      \"yMin\": -716,\n      \"yMax\": 1843,\n      \"hAsc\": 1844,\n      \"hDes\": -716,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanalei\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -541,\n      \"tAsc\": 2124,\n      \"tDes\": -541,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 541,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -541,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -541,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanalei Fill\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2124,\n      \"des\": -541,\n      \"tAsc\": 2124,\n      \"tDes\": -541,\n      \"tLGap\": 0,\n      \"wAsc\": 2124,\n      \"wDes\": 541,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -541,\n      \"yMax\": 2124,\n      \"hAsc\": 2124,\n      \"hDes\": -541,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Handjet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 8160,\n      \"asc\": 7200,\n      \"des\": -1920,\n      \"tAsc\": 7200,\n      \"tDes\": -1920,\n      \"tLGap\": 0,\n      \"wAsc\": 9840,\n      \"wDes\": 3840,\n      \"xH\": 3840,\n      \"capH\": 5280,\n      \"yMin\": -3840,\n      \"yMax\": 9840,\n      \"hAsc\": 7200,\n      \"hDes\": -1920,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Handlee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 934,\n      \"des\": -401,\n      \"tAsc\": 933,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 401,\n      \"xH\": 331,\n      \"capH\": 438,\n      \"yMin\": -400,\n      \"yMax\": 934,\n      \"hAsc\": 934,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanken Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -303,\n      \"tAsc\": 1000,\n      \"tDes\": -303,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 303,\n      \"xH\": 493,\n      \"capH\": 697,\n      \"yMin\": -257,\n      \"yMax\": 993,\n      \"hAsc\": 1000,\n      \"hDes\": -303,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hanuman\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -1000,\n      \"tAsc\": 2000,\n      \"tDes\": -1000,\n      \"tLGap\": 0,\n      \"wAsc\": 2150,\n      \"wDes\": 900,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -900,\n      \"yMax\": 2150,\n      \"hAsc\": 2000,\n      \"hDes\": -1000,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Happy Monkey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -255,\n      \"tAsc\": 950,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 255,\n      \"xH\": 500,\n      \"capH\": 699,\n      \"yMin\": -255,\n      \"yMax\": 950,\n      \"hAsc\": 950,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Harmattan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2166,\n      \"des\": -1323,\n      \"tAsc\": 2166,\n      \"tDes\": -1323,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 1750,\n      \"xH\": 778,\n      \"capH\": 1111,\n      \"yMin\": -1308,\n      \"yMax\": 2133,\n      \"hAsc\": 2166,\n      \"hDes\": -1323,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Headland One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2043,\n      \"des\": -522,\n      \"tAsc\": 2043,\n      \"tDes\": -522,\n      \"tLGap\": 0,\n      \"wAsc\": 2043,\n      \"wDes\": 522,\n      \"xH\": 1189,\n      \"capH\": 1530,\n      \"yMin\": -522,\n      \"yMax\": 2043,\n      \"hAsc\": 2043,\n      \"hDes\": -522,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hedvig Letters Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 320,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -257,\n      \"yMax\": 947,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hedvig Letters Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 320,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -257,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Heebo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -862,\n      \"tAsc\": 2146,\n      \"tDes\": -862,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 862,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -687,\n      \"yMax\": 1994,\n      \"hAsc\": 2146,\n      \"hDes\": -862,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Henny Penny\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2324,\n      \"des\": -1305,\n      \"tAsc\": 2324,\n      \"tDes\": -1305,\n      \"tLGap\": 0,\n      \"wAsc\": 2324,\n      \"wDes\": 1305,\n      \"xH\": 1264,\n      \"capH\": 1794,\n      \"yMin\": -1305,\n      \"yMax\": 2324,\n      \"hAsc\": 2324,\n      \"hDes\": -1305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hepta Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1976,\n      \"des\": -526,\n      \"tAsc\": 1976,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2800,\n      \"wDes\": 660,\n      \"xH\": 1052,\n      \"capH\": 1504,\n      \"yMin\": -545,\n      \"yMax\": 2556,\n      \"hAsc\": 1976,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Herr Von Muellerhoff\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -497,\n      \"tAsc\": 925,\n      \"tDes\": -497,\n      \"tLGap\": 0,\n      \"wAsc\": 925,\n      \"wDes\": 497,\n      \"xH\": 269,\n      \"capH\": 644,\n      \"yMin\": -497,\n      \"yMax\": 925,\n      \"hAsc\": 925,\n      \"hDes\": -497,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hi Melody\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 679,\n      \"des\": -345,\n      \"tAsc\": 679,\n      \"tDes\": -345,\n      \"tLGap\": 256,\n      \"wAsc\": 679,\n      \"wDes\": 345,\n      \"xH\": 321,\n      \"capH\": 512,\n      \"yMin\": -345,\n      \"yMax\": 679,\n      \"hAsc\": 679,\n      \"hDes\": -345,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Hina Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 380,\n      \"capH\": 700,\n      \"yMin\": -321,\n      \"yMax\": 1035,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1055,\n      \"des\": -546,\n      \"tAsc\": 1055,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 546,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -440,\n      \"yMax\": 1003,\n      \"hAsc\": 1055,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Guntur\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1115,\n      \"des\": -773,\n      \"tAsc\": 1115,\n      \"tDes\": -773,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 773,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -682,\n      \"yMax\": 1045,\n      \"hAsc\": 1115,\n      \"hDes\": -773,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Madurai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -398,\n      \"tAsc\": 982,\n      \"tDes\": -398,\n      \"tLGap\": 0,\n      \"wAsc\": 982,\n      \"wDes\": 398,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -388,\n      \"yMax\": 930,\n      \"hAsc\": 982,\n      \"hDes\": -398,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Mysuru\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 989,\n      \"des\": -725,\n      \"tAsc\": 989,\n      \"tDes\": -725,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 725,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -673,\n      \"yMax\": 930,\n      \"hAsc\": 989,\n      \"hDes\": -725,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Siliguri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -501,\n      \"tAsc\": 1116,\n      \"tDes\": -501,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 501,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -499,\n      \"yMax\": 1033,\n      \"hAsc\": 1116,\n      \"hDes\": -501,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hind Vadodara\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -373,\n      \"tAsc\": 1125,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 373,\n      \"xH\": 505,\n      \"capH\": 679,\n      \"yMin\": -371,\n      \"yMax\": 1037,\n      \"hAsc\": 1125,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Holtwood One SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2457,\n      \"des\": -876,\n      \"tAsc\": 2457,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 2470,\n      \"wDes\": 976,\n      \"xH\": 1408,\n      \"capH\": 1536,\n      \"yMin\": -976,\n      \"yMax\": 2470,\n      \"hAsc\": 2457,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Homemade Apple\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1327,\n      \"des\": -866,\n      \"tAsc\": 989,\n      \"tDes\": -662,\n      \"tLGap\": 35,\n      \"wAsc\": 1327,\n      \"wDes\": 866,\n      \"xH\": 600,\n      \"capH\": 1022,\n      \"yMin\": -866,\n      \"yMax\": 1327,\n      \"hAsc\": 1327,\n      \"hDes\": -866,\n      \"lGap\": 18\n    }\n  },\n  {\n    \"family\": \"Homenaje\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 892,\n      \"des\": -204,\n      \"tAsc\": 892,\n      \"tDes\": -204,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 163,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -204,\n      \"yMax\": 892,\n      \"hAsc\": 892,\n      \"hDes\": -204,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Honk\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -640,\n      \"tAsc\": 1800,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1800,\n      \"wDes\": 640,\n      \"xH\": 970,\n      \"capH\": 1200,\n      \"yMin\": -418,\n      \"yMax\": 1597,\n      \"hAsc\": 1800,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Host Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 977,\n      \"wDes\": 372,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 968,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hubballi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 765,\n      \"des\": -191,\n      \"tAsc\": 765,\n      \"tDes\": -191,\n      \"tLGap\": 0,\n      \"wAsc\": 816,\n      \"wDes\": 580,\n      \"xH\": 392,\n      \"capH\": 535,\n      \"yMin\": -580,\n      \"yMax\": 816,\n      \"hAsc\": 765,\n      \"hDes\": -191,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hubot Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -320,\n      \"tAsc\": 1090,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 320,\n      \"xH\": 525,\n      \"capH\": 729,\n      \"yMin\": -267,\n      \"yMax\": 1057,\n      \"hAsc\": 1090,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Huninn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 273,\n      \"xH\": 717,\n      \"capH\": 684,\n      \"yMin\": -251,\n      \"yMax\": 1031,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Hurricane\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -430,\n      \"tAsc\": 950,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 982,\n      \"wDes\": 609,\n      \"xH\": 326,\n      \"capH\": 610,\n      \"yMin\": -609,\n      \"yMax\": 982,\n      \"hAsc\": 950,\n      \"hDes\": -430,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iansui\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -180,\n      \"tAsc\": 940,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 273,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -273,\n      \"yMax\": 1066,\n      \"hAsc\": 940,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ibarra Real Nova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 400,\n      \"xH\": 426,\n      \"capH\": 673,\n      \"yMin\": -260,\n      \"yMax\": 881,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -350,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -245,\n      \"yMax\": 1119,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1085,\n      \"des\": -415,\n      \"tAsc\": 1085,\n      \"tDes\": -415,\n      \"tLGap\": 0,\n      \"wAsc\": 1128,\n      \"wDes\": 601,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -568,\n      \"yMax\": 1075,\n      \"hAsc\": 1085,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 780,\n      \"tDes\": -220,\n      \"tLGap\": 300,\n      \"wAsc\": 1025,\n      \"wDes\": 275,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -246,\n      \"yMax\": 1126,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -460,\n      \"tAsc\": 1070,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1099,\n      \"wDes\": 488,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -421,\n      \"yMax\": 1021,\n      \"hAsc\": 1070,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Hebrew\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 365,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -314,\n      \"yMax\": 976,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -440,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 440,\n      \"xH\": 541,\n      \"capH\": 733,\n      \"yMin\": -223,\n      \"yMax\": 1091,\n      \"hAsc\": 1060,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans KR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1085,\n      \"des\": -415,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1085,\n      \"wDes\": 415,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -757,\n      \"yMax\": 1367,\n      \"hAsc\": 1085,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Thai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -534,\n      \"tAsc\": 1116,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1116,\n      \"wDes\": 534,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -533,\n      \"yMax\": 1076,\n      \"hAsc\": 1116,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Sans Thai Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1116,\n      \"des\": -534,\n      \"tAsc\": 1116,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 534,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -533,\n      \"yMax\": 1159,\n      \"hAsc\": 1116,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IBM Plex Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 286,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -246,\n      \"yMax\": 1122,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iceberg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 936,\n      \"des\": -284,\n      \"tAsc\": 936,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 936,\n      \"wDes\": 284,\n      \"xH\": 519,\n      \"capH\": 691,\n      \"yMin\": -284,\n      \"yMax\": 936,\n      \"hAsc\": 936,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iceland\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -220,\n      \"tAsc\": 750,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 750,\n      \"wDes\": 220,\n      \"xH\": 350,\n      \"capH\": 490,\n      \"yMin\": -220,\n      \"yMax\": 750,\n      \"hAsc\": 750,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Idiqlat\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2233,\n      \"des\": -1109,\n      \"tAsc\": 2233,\n      \"tDes\": -1109,\n      \"tLGap\": 0,\n      \"wAsc\": 2310,\n      \"wDes\": 1326,\n      \"xH\": 991,\n      \"capH\": 1399,\n      \"yMin\": -1109,\n      \"yMax\": 2308,\n      \"hAsc\": 2233,\n      \"hDes\": -1109,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Double Pica\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1924,\n      \"des\": -643,\n      \"tAsc\": 1485,\n      \"tDes\": -593,\n      \"tLGap\": 489,\n      \"wAsc\": 1924,\n      \"wDes\": 643,\n      \"xH\": 926,\n      \"capH\": 1509,\n      \"yMin\": -617,\n      \"yMax\": 1937,\n      \"hAsc\": 1924,\n      \"hDes\": -643,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Double Pica SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1924,\n      \"des\": -643,\n      \"tAsc\": 1485,\n      \"tDes\": -593,\n      \"tLGap\": 489,\n      \"wAsc\": 1924,\n      \"wDes\": 643,\n      \"xH\": 946,\n      \"capH\": 1509,\n      \"yMin\": -595,\n      \"yMax\": 1926,\n      \"hAsc\": 1924,\n      \"hDes\": -643,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell DW Pica\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -692,\n      \"tAsc\": 1548,\n      \"tDes\": -640,\n      \"tLGap\": 372,\n      \"wAsc\": 1868,\n      \"wDes\": 692,\n      \"xH\": 903,\n      \"capH\": 1438,\n      \"yMin\": -645,\n      \"yMax\": 1915,\n      \"hAsc\": 1868,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell DW Pica SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -692,\n      \"tAsc\": 1548,\n      \"tDes\": -640,\n      \"tLGap\": 372,\n      \"wAsc\": 1868,\n      \"wDes\": 692,\n      \"xH\": 903,\n      \"capH\": 1438,\n      \"yMin\": -578,\n      \"yMax\": 1868,\n      \"hAsc\": 1868,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell English\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -744,\n      \"tAsc\": 1519,\n      \"tDes\": -637,\n      \"tLGap\": 442,\n      \"wAsc\": 1854,\n      \"wDes\": 744,\n      \"xH\": 962,\n      \"capH\": 1417,\n      \"yMin\": -588,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -744,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell English SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -744,\n      \"tAsc\": 1519,\n      \"tDes\": -637,\n      \"tLGap\": 442,\n      \"wAsc\": 1854,\n      \"wDes\": 744,\n      \"xH\": 901,\n      \"capH\": 1417,\n      \"yMin\": -588,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -744,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell French Canon\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -530,\n      \"tAsc\": 1501,\n      \"tDes\": -508,\n      \"tLGap\": 389,\n      \"wAsc\": 1868,\n      \"wDes\": 530,\n      \"xH\": 981,\n      \"capH\": 1465,\n      \"yMin\": -530,\n      \"yMax\": 1873,\n      \"hAsc\": 1868,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell French Canon SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1868,\n      \"des\": -530,\n      \"tAsc\": 1501,\n      \"tDes\": -508,\n      \"tLGap\": 389,\n      \"wAsc\": 1868,\n      \"wDes\": 530,\n      \"xH\": 984,\n      \"capH\": 1465,\n      \"yMin\": -523,\n      \"yMax\": 1873,\n      \"hAsc\": 1868,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Great Primer\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1942,\n      \"des\": -562,\n      \"tAsc\": 1500,\n      \"tDes\": -505,\n      \"tLGap\": 499,\n      \"wAsc\": 1942,\n      \"wDes\": 562,\n      \"xH\": 962,\n      \"capH\": 1488,\n      \"yMin\": -562,\n      \"yMax\": 1943,\n      \"hAsc\": 1942,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"IM Fell Great Primer SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1942,\n      \"des\": -562,\n      \"tAsc\": 1500,\n      \"tDes\": -505,\n      \"tLGap\": 499,\n      \"wAsc\": 1942,\n      \"wDes\": 562,\n      \"xH\": 957,\n      \"capH\": 1488,\n      \"yMin\": -562,\n      \"yMax\": 1943,\n      \"hAsc\": 1942,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imbue\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1046,\n      \"capH\": 1400,\n      \"yMin\": -502,\n      \"yMax\": 2025,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imperial Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -330,\n      \"tAsc\": 880,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 854,\n      \"wDes\": 524,\n      \"xH\": 325,\n      \"capH\": 620,\n      \"yMin\": -524,\n      \"yMax\": 854,\n      \"hAsc\": 880,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Imprima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 919,\n      \"des\": -239,\n      \"tAsc\": 919,\n      \"tDes\": -239,\n      \"tLGap\": 0,\n      \"wAsc\": 999,\n      \"wDes\": 265,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -265,\n      \"yMax\": 999,\n      \"hAsc\": 919,\n      \"hDes\": -239,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inclusive Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -338,\n      \"yMax\": 1149,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inconsolata\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -190,\n      \"tAsc\": 859,\n      \"tDes\": -190,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 454,\n      \"xH\": 457,\n      \"capH\": 623,\n      \"yMin\": -400,\n      \"yMax\": 1000,\n      \"hAsc\": 859,\n      \"hDes\": -190,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inder\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -520,\n      \"tAsc\": 2040,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 520,\n      \"xH\": 1032,\n      \"capH\": 1392,\n      \"yMin\": -520,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Indie Flower\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 994,\n      \"des\": -500,\n      \"tAsc\": 994,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 994,\n      \"wDes\": 500,\n      \"xH\": 374,\n      \"capH\": 587,\n      \"yMin\": -500,\n      \"yMax\": 994,\n      \"hAsc\": 994,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ingrid Darling\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -380,\n      \"tAsc\": 860,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 630,\n      \"xH\": 300,\n      \"capH\": 640,\n      \"yMin\": -626,\n      \"yMax\": 928,\n      \"hAsc\": 860,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inika\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -297,\n      \"tAsc\": 1006,\n      \"tDes\": -297,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 297,\n      \"xH\": 509,\n      \"capH\": 700,\n      \"yMin\": -289,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -297,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inknut Antiqua\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1703,\n      \"des\": -876,\n      \"tAsc\": 1703,\n      \"tDes\": -876,\n      \"tLGap\": 0,\n      \"wAsc\": 1703,\n      \"wDes\": 876,\n      \"xH\": 531,\n      \"capH\": 786,\n      \"yMin\": -846,\n      \"yMax\": 1566,\n      \"hAsc\": 1703,\n      \"hDes\": -876,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inria Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -223,\n      \"tAsc\": 976,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 256,\n      \"xH\": 495,\n      \"capH\": 680,\n      \"yMin\": -248,\n      \"yMax\": 990,\n      \"hAsc\": 976,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inria Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -223,\n      \"tAsc\": 976,\n      \"tDes\": -223,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 248,\n      \"xH\": 495,\n      \"capH\": 680,\n      \"yMin\": -242,\n      \"yMax\": 974,\n      \"hAsc\": 976,\n      \"hDes\": -223,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inspiration\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -400,\n      \"tAsc\": 870,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1055,\n      \"wDes\": 420,\n      \"xH\": 340,\n      \"capH\": 680,\n      \"yMin\": -420,\n      \"yMax\": 1055,\n      \"hAsc\": 870,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Instrument Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -250,\n      \"tAsc\": 970,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 986,\n      \"wDes\": 350,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -296,\n      \"yMax\": 986,\n      \"hAsc\": 970,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Instrument Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -310,\n      \"tAsc\": 990,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 310,\n      \"xH\": 510,\n      \"capH\": 720,\n      \"yMin\": -309,\n      \"yMax\": 986,\n      \"hAsc\": 990,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Intel One Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -290,\n      \"tAsc\": 1090,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1122,\n      \"wDes\": 420,\n      \"xH\": 465,\n      \"capH\": 655,\n      \"yMin\": -420,\n      \"yMax\": 1098,\n      \"hAsc\": 1090,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -494,\n      \"tAsc\": 1984,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 2269,\n      \"wDes\": 660,\n      \"xH\": 1118,\n      \"capH\": 1490,\n      \"yMin\": -660,\n      \"yMax\": 2269,\n      \"hAsc\": 1984,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Inter Tight\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1984,\n      \"des\": -494,\n      \"tAsc\": 1984,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 654,\n      \"xH\": 1118,\n      \"capH\": 1490,\n      \"yMin\": -654,\n      \"yMax\": 2234,\n      \"hAsc\": 1984,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iosevka Charon\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -265,\n      \"tAsc\": 1015,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1198,\n      \"wDes\": 604,\n      \"xH\": 520,\n      \"capH\": 735,\n      \"yMin\": -597,\n      \"yMax\": 1190,\n      \"hAsc\": 1015,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Iosevka Charon Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -265,\n      \"tAsc\": 1015,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1198,\n      \"wDes\": 604,\n      \"xH\": 520,\n      \"capH\": 735,\n      \"yMin\": -597,\n      \"yMax\": 1190,\n      \"hAsc\": 1015,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Irish Grover\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 965,\n      \"des\": -246,\n      \"tAsc\": 780,\n      \"tDes\": -180,\n      \"tLGap\": 54,\n      \"wAsc\": 965,\n      \"wDes\": 246,\n      \"xH\": 573,\n      \"capH\": 731,\n      \"yMin\": -246,\n      \"yMax\": 965,\n      \"hAsc\": 965,\n      \"hDes\": -246,\n      \"lGap\": 27\n    }\n  },\n  {\n    \"family\": \"Island Moments\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -400,\n      \"tAsc\": 750,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 857,\n      \"wDes\": 535,\n      \"xH\": 270,\n      \"capH\": 480,\n      \"yMin\": -535,\n      \"yMax\": 857,\n      \"hAsc\": 750,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Istok Web\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2061,\n      \"des\": -887,\n      \"tAsc\": 2061,\n      \"tDes\": -887,\n      \"tLGap\": 0,\n      \"wAsc\": 2061,\n      \"wDes\": 887,\n      \"xH\": 1050,\n      \"capH\": 1434,\n      \"yMin\": -887,\n      \"yMax\": 2052,\n      \"hAsc\": 2061,\n      \"hDes\": -887,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Italiana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -250,\n      \"tAsc\": 928,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 928,\n      \"hAsc\": 928,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Italianno\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 900,\n      \"wDes\": 560,\n      \"xH\": 273,\n      \"capH\": 577,\n      \"yMin\": -556,\n      \"yMax\": 876,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Itim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 474,\n      \"capH\": 635,\n      \"yMin\": -452,\n      \"yMax\": 978,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 12\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1260,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 720,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -720,\n      \"yMax\": 1020,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 12 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1260,\n      \"asc\": 960,\n      \"des\": -300,\n      \"tAsc\": 960,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 720,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -720,\n      \"yMax\": 1020,\n      \"hAsc\": 960,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 24\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1290,\n      \"asc\": 1020,\n      \"des\": -270,\n      \"tAsc\": 1020,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 750,\n      \"xH\": 510,\n      \"capH\": 750,\n      \"yMin\": -750,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquard 24 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1290,\n      \"asc\": 1020,\n      \"des\": -270,\n      \"tAsc\": 1020,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 750,\n      \"xH\": 510,\n      \"capH\": 750,\n      \"yMin\": -750,\n      \"yMax\": 1022,\n      \"hAsc\": 1020,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquarda Bastarda 9\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 1045,\n      \"des\": -320,\n      \"tAsc\": 1045,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 320,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -320,\n      \"yMax\": 1040,\n      \"hAsc\": 1045,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacquarda Bastarda 9 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 1045,\n      \"des\": -320,\n      \"tAsc\": 1045,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 320,\n      \"xH\": 480,\n      \"capH\": 720,\n      \"yMin\": -320,\n      \"yMax\": 1045,\n      \"hAsc\": 1045,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacques Francois\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -606,\n      \"tAsc\": 2095,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2095,\n      \"wDes\": 606,\n      \"xH\": 879,\n      \"capH\": 1464,\n      \"yMin\": -565,\n      \"yMax\": 2054,\n      \"hAsc\": 2095,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jacques Francois Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -606,\n      \"tAsc\": 2095,\n      \"tDes\": -606,\n      \"tLGap\": 0,\n      \"wAsc\": 2095,\n      \"wDes\": 606,\n      \"xH\": 930,\n      \"capH\": 1513,\n      \"yMin\": -606,\n      \"yMax\": 2095,\n      \"hAsc\": 2095,\n      \"hDes\": -606,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaini\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -266,\n      \"tAsc\": 1048,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 266,\n      \"xH\": 494,\n      \"capH\": 639,\n      \"yMin\": -266,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaini Purva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -266,\n      \"tAsc\": 1048,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 266,\n      \"xH\": 494,\n      \"capH\": 639,\n      \"yMin\": -266,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaldi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2350,\n      \"des\": -1111,\n      \"tAsc\": 2350,\n      \"tDes\": -1111,\n      \"tLGap\": 0,\n      \"wAsc\": 2350,\n      \"wDes\": 1111,\n      \"xH\": 930,\n      \"capH\": 1243,\n      \"yMin\": -972,\n      \"yMax\": 2350,\n      \"hAsc\": 2350,\n      \"hDes\": -1111,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jaro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2000,\n      \"des\": -500,\n      \"tAsc\": 2000,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 673,\n      \"xH\": 1100,\n      \"capH\": 1333,\n      \"yMin\": -500,\n      \"yMax\": 1960,\n      \"hAsc\": 2000,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 10\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1400,\n      \"asc\": 1125,\n      \"des\": -375,\n      \"tAsc\": 1125,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 375,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -375,\n      \"yMax\": 1125,\n      \"hAsc\": 1125,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 10 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1400,\n      \"asc\": 1125,\n      \"des\": -375,\n      \"tAsc\": 1125,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 375,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -375,\n      \"yMax\": 1130,\n      \"hAsc\": 1125,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 15\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1350,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1054,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -300,\n      \"yMax\": 1050,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 15 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1350,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1054,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -300,\n      \"yMax\": 1054,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 20\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1292,\n      \"asc\": 1026,\n      \"des\": -266,\n      \"tAsc\": 1026,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 266,\n      \"xH\": 570,\n      \"capH\": 760,\n      \"yMin\": -266,\n      \"yMax\": 1026,\n      \"hAsc\": 1026,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 20 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1292,\n      \"asc\": 1026,\n      \"des\": -266,\n      \"tAsc\": 1026,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 1029,\n      \"wDes\": 266,\n      \"xH\": 570,\n      \"capH\": 760,\n      \"yMin\": -266,\n      \"yMax\": 1029,\n      \"hAsc\": 1026,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 25\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1230,\n      \"asc\": 988,\n      \"des\": -242,\n      \"tAsc\": 988,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 276,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -276,\n      \"yMax\": 990,\n      \"hAsc\": 988,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jersey 25 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1230,\n      \"asc\": 988,\n      \"des\": -242,\n      \"tAsc\": 988,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 276,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -242,\n      \"yMax\": 990,\n      \"hAsc\": 988,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"JetBrains Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -300,\n      \"tAsc\": 1020,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 300,\n      \"xH\": 550,\n      \"capH\": 730,\n      \"yMin\": -300,\n      \"yMax\": 1020,\n      \"hAsc\": 1020,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jim Nightshade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1852,\n      \"des\": -1050,\n      \"tAsc\": 1852,\n      \"tDes\": -1050,\n      \"tLGap\": 0,\n      \"wAsc\": 1852,\n      \"wDes\": 1050,\n      \"xH\": 930,\n      \"capH\": 1234,\n      \"yMin\": -1050,\n      \"yMax\": 1852,\n      \"hAsc\": 1852,\n      \"hDes\": -1050,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Joan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -292,\n      \"tAsc\": 1000,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1117,\n      \"wDes\": 615,\n      \"xH\": 456,\n      \"capH\": 707,\n      \"yMin\": -615,\n      \"yMax\": 1117,\n      \"hAsc\": 1000,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jockey One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1079,\n      \"des\": -319,\n      \"tAsc\": 1079,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 319,\n      \"xH\": 511,\n      \"capH\": 700,\n      \"yMin\": -319,\n      \"yMax\": 1079,\n      \"hAsc\": 1079,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jolly Lodger\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 988,\n      \"des\": -257,\n      \"tAsc\": 988,\n      \"tDes\": -257,\n      \"tLGap\": 0,\n      \"wAsc\": 988,\n      \"wDes\": 263,\n      \"xH\": 642,\n      \"capH\": 757,\n      \"yMin\": -257,\n      \"yMax\": 988,\n      \"hAsc\": 988,\n      \"hDes\": -257,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jomhuria\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 3000,\n      \"asc\": 1840,\n      \"des\": -1160,\n      \"tAsc\": 1840,\n      \"tDes\": -1160,\n      \"tLGap\": 0,\n      \"wAsc\": 3083,\n      \"wDes\": 1575,\n      \"xH\": 850,\n      \"capH\": 1172,\n      \"yMin\": -1575,\n      \"yMax\": 3083,\n      \"hAsc\": 1840,\n      \"hDes\": -1160,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jomolhari\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1248,\n      \"des\": -392,\n      \"tAsc\": 1248,\n      \"tDes\": -392,\n      \"tLGap\": 0,\n      \"wAsc\": 1302,\n      \"wDes\": 610,\n      \"xH\": 360,\n      \"capH\": 756,\n      \"yMin\": -610,\n      \"yMax\": 1302,\n      \"hAsc\": 1248,\n      \"hDes\": -392,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Josefin Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1242,\n      \"wDes\": 324,\n      \"xH\": 378,\n      \"capH\": 702,\n      \"yMin\": -237,\n      \"yMax\": 1183,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Josefin Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 932,\n      \"wDes\": 250,\n      \"xH\": 375,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 931,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jost\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -375,\n      \"tAsc\": 1070,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1070,\n      \"wDes\": 375,\n      \"xH\": 460,\n      \"capH\": 700,\n      \"yMin\": -350,\n      \"yMax\": 1030,\n      \"hAsc\": 1070,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Joti One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1003,\n      \"des\": -331,\n      \"tAsc\": 1003,\n      \"tDes\": -331,\n      \"tLGap\": 0,\n      \"wAsc\": 1003,\n      \"wDes\": 331,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -331,\n      \"yMax\": 1003,\n      \"hAsc\": 1003,\n      \"hDes\": -331,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jua\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 874,\n      \"wDes\": 239,\n      \"xH\": 432,\n      \"capH\": 711,\n      \"yMin\": -242,\n      \"yMax\": 867,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Judson\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 902,\n      \"des\": -248,\n      \"tAsc\": 902,\n      \"tDes\": -248,\n      \"tLGap\": 0,\n      \"wAsc\": 902,\n      \"wDes\": 248,\n      \"xH\": 440,\n      \"capH\": 585,\n      \"yMin\": -248,\n      \"yMax\": 902,\n      \"hAsc\": 902,\n      \"hDes\": -248,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Julee\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -284,\n      \"tAsc\": 894,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 973,\n      \"wDes\": 345,\n      \"xH\": 153,\n      \"capH\": 206,\n      \"yMin\": -345,\n      \"yMax\": 973,\n      \"hAsc\": 894,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Julius Sans One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 863,\n      \"des\": -228,\n      \"tAsc\": 863,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 863,\n      \"wDes\": 228,\n      \"xH\": 649,\n      \"capH\": 715,\n      \"yMin\": -228,\n      \"yMax\": 863,\n      \"hAsc\": 863,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Junge\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1901,\n      \"des\": -588,\n      \"tAsc\": 1901,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1901,\n      \"wDes\": 588,\n      \"xH\": 1010,\n      \"capH\": 1444,\n      \"yMin\": -588,\n      \"yMax\": 1901,\n      \"hAsc\": 1901,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Jura\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1930,\n      \"des\": -436,\n      \"tAsc\": 1930,\n      \"tDes\": -436,\n      \"tLGap\": 0,\n      \"wAsc\": 2203,\n      \"wDes\": 456,\n      \"xH\": 922,\n      \"capH\": 1266,\n      \"yMin\": -427,\n      \"yMax\": 2154,\n      \"hAsc\": 1930,\n      \"hDes\": -436,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Just Another Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1842,\n      \"wDes\": 755,\n      \"xH\": 880,\n      \"capH\": 1436,\n      \"yMin\": -755,\n      \"yMax\": 1842,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Just Me Again Down Here\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -429,\n      \"tAsc\": 1069,\n      \"tDes\": -429,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 429,\n      \"xH\": 289,\n      \"capH\": 600,\n      \"yMin\": -429,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -429,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"K2D\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -252,\n      \"tAsc\": 1048,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1339,\n      \"wDes\": 577,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -513,\n      \"yMax\": 1262,\n      \"hAsc\": 1048,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kablammo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2078,\n      \"des\": -506,\n      \"tAsc\": 2078,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 2368,\n      \"wDes\": 730,\n      \"xH\": 1100,\n      \"capH\": 1400,\n      \"yMin\": -730,\n      \"yMax\": 2294,\n      \"hAsc\": 2078,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kadwa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2691,\n      \"des\": -1421,\n      \"tAsc\": 2691,\n      \"tDes\": -1421,\n      \"tLGap\": 0,\n      \"wAsc\": 2691,\n      \"wDes\": 1421,\n      \"xH\": 1085,\n      \"capH\": 1434,\n      \"yMin\": -1233,\n      \"yMax\": 2464,\n      \"hAsc\": 2691,\n      \"hDes\": -1421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Decol\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei HarunoUmi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Opti\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kaisei Tokumin\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 501,\n      \"capH\": 738,\n      \"yMin\": -209,\n      \"yMax\": 933,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalam\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1063,\n      \"des\": -531,\n      \"tAsc\": 1063,\n      \"tDes\": -531,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 531,\n      \"xH\": 526,\n      \"capH\": 739,\n      \"yMin\": -471,\n      \"yMax\": 1031,\n      \"hAsc\": 1063,\n      \"hDes\": -531,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalnia\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -300,\n      \"tAsc\": 1045,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 708,\n      \"yMin\": -225,\n      \"yMax\": 939,\n      \"hAsc\": 1045,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kalnia Glaze\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -300,\n      \"tAsc\": 1045,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 708,\n      \"yMin\": -225,\n      \"yMax\": 939,\n      \"hAsc\": 1045,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kameron\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1823,\n      \"des\": -608,\n      \"tAsc\": 1823,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1823,\n      \"wDes\": 608,\n      \"xH\": 895,\n      \"capH\": 1290,\n      \"yMin\": -608,\n      \"yMax\": 1823,\n      \"hAsc\": 1823,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kanchenjunga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -800,\n      \"tAsc\": 2500,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 800,\n      \"xH\": 1040,\n      \"capH\": 1485,\n      \"yMin\": -800,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kanit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -395,\n      \"tAsc\": 1100,\n      \"tDes\": -395,\n      \"tLGap\": 0,\n      \"wAsc\": 1180,\n      \"wDes\": 400,\n      \"xH\": 474,\n      \"capH\": 644,\n      \"yMin\": -351,\n      \"yMax\": 1061,\n      \"hAsc\": 1100,\n      \"hDes\": -395,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kantumruy Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -260,\n      \"tAsc\": 920,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 468,\n      \"xH\": 550,\n      \"capH\": 750,\n      \"yMin\": -468,\n      \"yMax\": 960,\n      \"hAsc\": 920,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kapakana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 680,\n      \"des\": -320,\n      \"tAsc\": 680,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 680,\n      \"wDes\": 320,\n      \"xH\": 250,\n      \"capH\": 535,\n      \"yMin\": -310,\n      \"yMax\": 690,\n      \"hAsc\": 680,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karantina\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -153,\n      \"tAsc\": 859,\n      \"tDes\": -153,\n      \"tLGap\": 0,\n      \"wAsc\": 859,\n      \"wDes\": 228,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -206,\n      \"yMax\": 845,\n      \"hAsc\": 859,\n      \"hDes\": -153,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1834,\n      \"des\": -504,\n      \"tAsc\": 1834,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 2062,\n      \"wDes\": 545,\n      \"xH\": 956,\n      \"capH\": 1256,\n      \"yMin\": -492,\n      \"yMax\": 1952,\n      \"hAsc\": 1834,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Karla Tamil Inclined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 796,\n      \"des\": -345,\n      \"tAsc\": 796,\n      \"tDes\": -345,\n      \"tLGap\": 34,\n      \"wAsc\": 796,\n      \"wDes\": 345,\n      \"xH\": 499,\n      \"capH\": 717,\n      \"yMin\": -351,\n      \"yMax\": 819,\n      \"hAsc\": 796,\n      \"hDes\": -345,\n      \"lGap\": 17\n    }\n  },\n  {\n    \"family\": \"Karla Tamil Upright\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 749,\n      \"wDes\": 215,\n      \"xH\": 503,\n      \"capH\": 727,\n      \"yMin\": -349,\n      \"yMax\": 813,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 9\n    }\n  },\n  {\n    \"family\": \"Karma\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -508,\n      \"tAsc\": 945,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 508,\n      \"xH\": 489,\n      \"capH\": 677,\n      \"yMin\": -508,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Katibeh\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 490,\n      \"des\": -510,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -637,\n      \"yMax\": 1094,\n      \"hAsc\": 490,\n      \"hDes\": -510,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Kaushan Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1084,\n      \"des\": -367,\n      \"tAsc\": 1084,\n      \"tDes\": -367,\n      \"tLGap\": 0,\n      \"wAsc\": 1084,\n      \"wDes\": 367,\n      \"xH\": 452,\n      \"capH\": 714,\n      \"yMin\": -367,\n      \"yMax\": 1084,\n      \"hAsc\": 1084,\n      \"hDes\": -367,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kavivanar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -417,\n      \"tAsc\": 1065,\n      \"tDes\": -417,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 417,\n      \"yMin\": -417,\n      \"yMax\": 1065,\n      \"hAsc\": 1065,\n      \"hDes\": -417,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kavoon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 1185,\n      \"capH\": 1530,\n      \"yMin\": -524,\n      \"yMax\": 2365,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kay Pho Du\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1944,\n      \"des\": -525,\n      \"tAsc\": 1944,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1969,\n      \"wDes\": 525,\n      \"xH\": 1050,\n      \"capH\": 1563,\n      \"yMin\": -525,\n      \"yMax\": 1944,\n      \"hAsc\": 1944,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kdam Thmor Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1146,\n      \"des\": -400,\n      \"tAsc\": 1146,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1146,\n      \"wDes\": 550,\n      \"xH\": 612,\n      \"capH\": 793,\n      \"yMin\": -550,\n      \"yMax\": 1146,\n      \"hAsc\": 1146,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Keania One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 989,\n      \"des\": -228,\n      \"tAsc\": 989,\n      \"tDes\": -228,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 228,\n      \"xH\": 500,\n      \"capH\": 723,\n      \"yMin\": -228,\n      \"yMax\": 989,\n      \"hAsc\": 989,\n      \"hDes\": -228,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kedebideri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 668,\n      \"capH\": 668,\n      \"yMin\": -247,\n      \"yMax\": 976,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kelly Slab\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -250,\n      \"tAsc\": 962,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -250,\n      \"yMax\": 962,\n      \"hAsc\": 962,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kenia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 330,\n      \"xH\": 512,\n      \"capH\": 727,\n      \"yMin\": -330,\n      \"yMax\": 958,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khand\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -479,\n      \"tAsc\": 1050,\n      \"tDes\": -479,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 479,\n      \"xH\": 569,\n      \"capH\": 672,\n      \"yMin\": -394,\n      \"yMax\": 933,\n      \"hAsc\": 1050,\n      \"hDes\": -479,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khmer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2300,\n      \"des\": -1200,\n      \"tAsc\": 2300,\n      \"tDes\": -1200,\n      \"tLGap\": 132,\n      \"wAsc\": 2300,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2283,\n      \"hAsc\": 2300,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Khula\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1978,\n      \"asc\": 1978,\n      \"des\": -1198,\n      \"tAsc\": 1978,\n      \"tDes\": -1198,\n      \"tLGap\": 0,\n      \"wAsc\": 1978,\n      \"wDes\": 1198,\n      \"xH\": 986,\n      \"capH\": 1316,\n      \"yMin\": -1021,\n      \"yMax\": 1883,\n      \"hAsc\": 1978,\n      \"hDes\": -1198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kings\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -450,\n      \"tAsc\": 950,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1344,\n      \"wDes\": 508,\n      \"xH\": 460,\n      \"capH\": 630,\n      \"yMin\": -508,\n      \"yMax\": 1344,\n      \"hAsc\": 950,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kirang Haerang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 250,\n      \"wAsc\": 800,\n      \"wDes\": 300,\n      \"xH\": 337,\n      \"capH\": 558,\n      \"yMin\": -300,\n      \"yMax\": 800,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Kite One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1094,\n      \"des\": -351,\n      \"tAsc\": 1094,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 351,\n      \"xH\": 493,\n      \"capH\": 860,\n      \"yMin\": -351,\n      \"yMax\": 1190,\n      \"hAsc\": 1094,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kiwi Maru\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 506,\n      \"capH\": 727,\n      \"yMin\": -259,\n      \"yMax\": 980,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Klee One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 600],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -211,\n      \"yMax\": 942,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Knewave\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1169,\n      \"des\": -385,\n      \"tAsc\": 1169,\n      \"tDes\": -385,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 385,\n      \"xH\": 497,\n      \"capH\": 780,\n      \"yMin\": -365,\n      \"yMax\": 1146,\n      \"hAsc\": 1169,\n      \"hDes\": -385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kodchasan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1024,\n      \"des\": -276,\n      \"tAsc\": 1024,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1249,\n      \"wDes\": 539,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -510,\n      \"yMax\": 1192,\n      \"hAsc\": 1024,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kode Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -300,\n      \"tAsc\": 980,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1034,\n      \"wDes\": 500,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -500,\n      \"yMax\": 1000,\n      \"hAsc\": 980,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Koh Santepheap\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2050,\n      \"des\": -550,\n      \"tAsc\": 2050,\n      \"tDes\": -550,\n      \"tLGap\": 132,\n      \"wAsc\": 2320,\n      \"wDes\": 909,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -900,\n      \"yMax\": 2290,\n      \"hAsc\": 2050,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"KoHo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -255,\n      \"tAsc\": 1045,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1187,\n      \"wDes\": 479,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -461,\n      \"yMax\": 1135,\n      \"hAsc\": 1045,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kolker Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -350,\n      \"tAsc\": 750,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 822,\n      \"wDes\": 350,\n      \"xH\": 205,\n      \"capH\": 480,\n      \"yMin\": -295,\n      \"yMax\": 822,\n      \"hAsc\": 750,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Konkhmer Sleokchher\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1503,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1503,\n      \"yMax\": 2487,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kosugi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 901,\n      \"des\": -123,\n      \"tAsc\": 901,\n      \"tDes\": -123,\n      \"tLGap\": 0,\n      \"wAsc\": 901,\n      \"wDes\": 123,\n      \"xH\": 539,\n      \"capH\": 774,\n      \"yMin\": -123,\n      \"yMax\": 901,\n      \"hAsc\": 901,\n      \"hDes\": -123,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kosugi Maru\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 901,\n      \"des\": -123,\n      \"tAsc\": 901,\n      \"tDes\": -123,\n      \"tLGap\": 0,\n      \"wAsc\": 901,\n      \"wDes\": 123,\n      \"xH\": 546,\n      \"capH\": 781,\n      \"yMin\": -123,\n      \"yMax\": 901,\n      \"hAsc\": 901,\n      \"hDes\": -123,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kotta One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -288,\n      \"tAsc\": 915,\n      \"tDes\": -288,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 288,\n      \"xH\": 76,\n      \"capH\": 212,\n      \"yMin\": -288,\n      \"yMax\": 915,\n      \"hAsc\": 915,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Koulen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2501,\n      \"wDes\": 1126,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1126,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kranky\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 977,\n      \"des\": -294,\n      \"tAsc\": 744,\n      \"tDes\": -221,\n      \"tLGap\": 55,\n      \"wAsc\": 977,\n      \"wDes\": 294,\n      \"xH\": 432,\n      \"capH\": 777,\n      \"yMin\": -294,\n      \"yMax\": 977,\n      \"hAsc\": 977,\n      \"hDes\": -294,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Kreon\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -286,\n      \"tAsc\": 974,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 326,\n      \"xH\": 481,\n      \"capH\": 691,\n      \"yMin\": -297,\n      \"yMax\": 1102,\n      \"hAsc\": 974,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kristi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1836,\n      \"des\": -724,\n      \"tAsc\": 1272,\n      \"tDes\": -776,\n      \"tLGap\": 512,\n      \"wAsc\": 1836,\n      \"wDes\": 724,\n      \"yMin\": -1035,\n      \"yMax\": 1613,\n      \"hAsc\": 1836,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Krona One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 1180,\n      \"capH\": 1563,\n      \"yMin\": -530,\n      \"yMax\": 2030,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Krub\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1007,\n      \"des\": -293,\n      \"tAsc\": 1007,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1232,\n      \"wDes\": 507,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -498,\n      \"yMax\": 1201,\n      \"hAsc\": 1007,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kufam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -400,\n      \"tAsc\": 900,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1252,\n      \"wDes\": 1050,\n      \"xH\": 544,\n      \"capH\": 720,\n      \"yMin\": -1008,\n      \"yMax\": 1228,\n      \"hAsc\": 900,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kulim Park\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 931,\n      \"des\": -204,\n      \"tAsc\": 931,\n      \"tDes\": -204,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 238,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -220,\n      \"yMax\": 918,\n      \"hAsc\": 931,\n      \"hDes\": -204,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumar One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1137,\n      \"des\": -642,\n      \"tAsc\": 1137,\n      \"tDes\": -642,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 642,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -642,\n      \"yMax\": 1137,\n      \"hAsc\": 1137,\n      \"hDes\": -642,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumar One Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1137,\n      \"des\": -642,\n      \"tAsc\": 1137,\n      \"tDes\": -642,\n      \"tLGap\": 0,\n      \"wAsc\": 1137,\n      \"wDes\": 642,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -642,\n      \"yMax\": 1137,\n      \"hAsc\": 1137,\n      \"hDes\": -642,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kumbh Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -520,\n      \"tAsc\": 2020,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 520,\n      \"xH\": 1000,\n      \"capH\": 1500,\n      \"yMin\": -520,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Kurale\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1095,\n      \"des\": -383,\n      \"tAsc\": 1095,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 1108,\n      \"wDes\": 383,\n      \"xH\": 450,\n      \"capH\": 650,\n      \"yMin\": -383,\n      \"yMax\": 1108,\n      \"hAsc\": 1095,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"La Belle Aurore\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1103,\n      \"des\": -794,\n      \"tAsc\": 1103,\n      \"tDes\": -796,\n      \"tLGap\": 0,\n      \"wAsc\": 1103,\n      \"wDes\": 794,\n      \"xH\": 377,\n      \"capH\": 688,\n      \"yMin\": -794,\n      \"yMax\": 1235,\n      \"hAsc\": 1103,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Labrada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -300,\n      \"tAsc\": 1145,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 300,\n      \"xH\": 450,\n      \"capH\": 640,\n      \"yMin\": -269,\n      \"yMax\": 1063,\n      \"hAsc\": 1145,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lacquer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 557,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -557,\n      \"yMax\": 1150,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Laila\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1098,\n      \"des\": -452,\n      \"tAsc\": 1098,\n      \"tDes\": -452,\n      \"tLGap\": 0,\n      \"wAsc\": 1098,\n      \"wDes\": 452,\n      \"xH\": 517,\n      \"capH\": 717,\n      \"yMin\": -390,\n      \"yMax\": 1027,\n      \"hAsc\": 1098,\n      \"hDes\": -452,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lakki Reddy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -765,\n      \"tAsc\": 938,\n      \"tDes\": -765,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 765,\n      \"xH\": 529,\n      \"capH\": 718,\n      \"yMin\": -765,\n      \"yMax\": 965,\n      \"hAsc\": 938,\n      \"hDes\": -765,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lalezar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 979,\n      \"des\": -588,\n      \"tAsc\": 979,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 588,\n      \"xH\": 186,\n      \"capH\": 570,\n      \"yMin\": -588,\n      \"yMax\": 979,\n      \"hAsc\": 979,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lancelot\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1595,\n      \"des\": -668,\n      \"tAsc\": 1595,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 1595,\n      \"wDes\": 668,\n      \"xH\": 804,\n      \"capH\": 1190,\n      \"yMin\": -668,\n      \"yMax\": 1595,\n      \"hAsc\": 1595,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Langar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 739,\n      \"des\": -200,\n      \"tAsc\": 739,\n      \"tDes\": -200,\n      \"tLGap\": 455,\n      \"wAsc\": 1085,\n      \"wDes\": 390,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -390,\n      \"yMax\": 1085,\n      \"hAsc\": 739,\n      \"hDes\": -200,\n      \"lGap\": 455\n    }\n  },\n  {\n    \"family\": \"Lateef\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1937,\n      \"des\": -1024,\n      \"tAsc\": 1937,\n      \"tDes\": -1024,\n      \"tLGap\": 0,\n      \"wAsc\": 2742,\n      \"wDes\": 1488,\n      \"xH\": 690,\n      \"capH\": 1022,\n      \"yMin\": -998,\n      \"yMax\": 2151,\n      \"hAsc\": 1937,\n      \"hDes\": -1024,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lato\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1974,\n      \"des\": -426,\n      \"tAsc\": 1610,\n      \"tDes\": -390,\n      \"tLGap\": 400,\n      \"wAsc\": 1974,\n      \"wDes\": 426,\n      \"xH\": 1013,\n      \"capH\": 1433,\n      \"yMin\": -365,\n      \"yMax\": 1837,\n      \"hAsc\": 1974,\n      \"hDes\": -426,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lavishly Yours\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -500,\n      \"tAsc\": 1100,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1142,\n      \"wDes\": 530,\n      \"xH\": 244,\n      \"capH\": 780,\n      \"yMin\": -524,\n      \"yMax\": 1142,\n      \"hAsc\": 1100,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1935,\n      \"des\": -465,\n      \"tAsc\": 1935,\n      \"tDes\": -465,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 500,\n      \"xH\": 1094,\n      \"capH\": 1470,\n      \"yMin\": -500,\n      \"yMax\": 2103,\n      \"hAsc\": 1935,\n      \"hDes\": -465,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1536,\n      \"asc\": 1100,\n      \"des\": -600,\n      \"tAsc\": 1100,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 600,\n      \"xH\": 542,\n      \"capH\": 936,\n      \"yMin\": -598,\n      \"yMax\": 1315,\n      \"hAsc\": 1100,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"League Spartan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1400,\n      \"des\": -440,\n      \"tAsc\": 1400,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 2305,\n      \"wDes\": 675,\n      \"xH\": 821,\n      \"capH\": 1320,\n      \"yMin\": -488,\n      \"yMax\": 2176,\n      \"hAsc\": 1400,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Leckerli One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1032,\n      \"des\": -313,\n      \"tAsc\": 1032,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 313,\n      \"xH\": 300,\n      \"capH\": 521,\n      \"yMin\": -313,\n      \"yMax\": 1032,\n      \"hAsc\": 1032,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ledger\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1062,\n      \"des\": -329,\n      \"tAsc\": 1062,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 329,\n      \"xH\": 487,\n      \"capH\": 750,\n      \"yMin\": -329,\n      \"yMax\": 1062,\n      \"hAsc\": 1062,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lekton\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 585,\n      \"xH\": 475,\n      \"capH\": 655,\n      \"yMin\": -585,\n      \"yMax\": 1112,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lemon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1019,\n      \"des\": -287,\n      \"tAsc\": 1019,\n      \"tDes\": -287,\n      \"tLGap\": 0,\n      \"wAsc\": 1129,\n      \"wDes\": 424,\n      \"xH\": 575,\n      \"capH\": 710,\n      \"yMin\": -424,\n      \"yMax\": 1129,\n      \"hAsc\": 1019,\n      \"hDes\": -287,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lemonada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1345,\n      \"des\": -653,\n      \"tAsc\": 1345,\n      \"tDes\": -653,\n      \"tLGap\": 0,\n      \"wAsc\": 1346,\n      \"wDes\": 651,\n      \"xH\": 575,\n      \"capH\": 710,\n      \"yMin\": -566,\n      \"yMax\": 1345,\n      \"hAsc\": 1345,\n      \"hDes\": -653,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1080,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Deca\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1080,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Exa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1112,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Giga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1125,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Mega\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1131,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Peta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1138,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Tera\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1144,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lexend Zetta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 1160,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Keyboard\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 894,\n      \"wDes\": 246,\n      \"xH\": 754,\n      \"capH\": 754,\n      \"yMin\": -243,\n      \"yMax\": 754,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Math\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 3813,\n      \"wDes\": 1641,\n      \"xH\": 429,\n      \"capH\": 658,\n      \"yMin\": -1641,\n      \"yMax\": 3813,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 895,\n      \"wDes\": 288,\n      \"xH\": 495,\n      \"capH\": 613,\n      \"yMin\": -288,\n      \"yMax\": 895,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 268,\n      \"xH\": 460,\n      \"capH\": 658,\n      \"yMin\": -268,\n      \"yMax\": 893,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1802,\n      \"wDes\": 328,\n      \"xH\": 429,\n      \"capH\": 658,\n      \"yMin\": -256,\n      \"yMax\": 1125,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libertinus Serif Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -246,\n      \"tAsc\": 894,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1052,\n      \"wDes\": 249,\n      \"xH\": 409,\n      \"capH\": 658,\n      \"yMin\": -249,\n      \"yMax\": 1052,\n      \"hAsc\": 894,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 128\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 128 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Extended\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Extended Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode 39 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 600,\n      \"des\": -400,\n      \"tAsc\": 600,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 400,\n      \"xH\": 400,\n      \"capH\": 590,\n      \"yMin\": -400,\n      \"yMax\": 600,\n      \"hAsc\": 600,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Barcode EAN13 Text\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 840,\n      \"des\": -120,\n      \"tAsc\": 840,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 840,\n      \"wDes\": 120,\n      \"xH\": 420,\n      \"capH\": 840,\n      \"yMin\": -120,\n      \"yMax\": 840,\n      \"hAsc\": 840,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Baskerville\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -270,\n      \"tAsc\": 970,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 270,\n      \"xH\": 530,\n      \"capH\": 770,\n      \"yMin\": -270,\n      \"yMax\": 1182,\n      \"hAsc\": 970,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Bodoni\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 924,\n      \"des\": -326,\n      \"tAsc\": 924,\n      \"tDes\": -326,\n      \"tLGap\": 0,\n      \"wAsc\": 1204,\n      \"wDes\": 326,\n      \"xH\": 450,\n      \"capH\": 754,\n      \"yMin\": -326,\n      \"yMax\": 1146,\n      \"hAsc\": 924,\n      \"hDes\": -326,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Caslon Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -266,\n      \"tAsc\": 970,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 963,\n      \"wDes\": 254,\n      \"xH\": 424,\n      \"capH\": 690,\n      \"yMin\": -254,\n      \"yMax\": 963,\n      \"hAsc\": 970,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Caslon Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -260,\n      \"tAsc\": 970,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 260,\n      \"xH\": 530,\n      \"capH\": 770,\n      \"yMin\": -260,\n      \"yMax\": 970,\n      \"hAsc\": 970,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Libre Franklin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -246,\n      \"tAsc\": 966,\n      \"tDes\": -246,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 246,\n      \"xH\": 530,\n      \"capH\": 742,\n      \"yMin\": -239,\n      \"yMax\": 1151,\n      \"hAsc\": 966,\n      \"hDes\": -246,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Licorice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -400,\n      \"tAsc\": 850,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1043,\n      \"wDes\": 452,\n      \"xH\": 400,\n      \"capH\": 720,\n      \"yMin\": -452,\n      \"yMax\": 1043,\n      \"hAsc\": 850,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Life Savers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -250,\n      \"tAsc\": 972,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 251,\n      \"xH\": 436,\n      \"capH\": 821,\n      \"yMin\": -250,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lilex\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 999,\n      \"des\": -301,\n      \"tAsc\": 999,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 427,\n      \"xH\": 516,\n      \"capH\": 698,\n      \"yMin\": -350,\n      \"yMax\": 1119,\n      \"hAsc\": 999,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lilita One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 923,\n      \"des\": -220,\n      \"tAsc\": 922,\n      \"tDes\": -219,\n      \"tLGap\": 0,\n      \"wAsc\": 923,\n      \"wDes\": 220,\n      \"xH\": 506,\n      \"capH\": 704,\n      \"yMin\": -220,\n      \"yMax\": 923,\n      \"hAsc\": 923,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lily Script One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1017,\n      \"des\": -359,\n      \"tAsc\": 1017,\n      \"tDes\": -359,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 359,\n      \"xH\": 762,\n      \"capH\": 762,\n      \"yMin\": -359,\n      \"yMax\": 1017,\n      \"hAsc\": 1017,\n      \"hDes\": -359,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Limelight\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1864,\n      \"des\": -629,\n      \"tAsc\": 1864,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1864,\n      \"wDes\": 629,\n      \"xH\": 1068,\n      \"capH\": 1415,\n      \"yMin\": -636,\n      \"yMax\": 1864,\n      \"hAsc\": 1864,\n      \"hDes\": -629,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Linden Hill\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3633,\n      \"des\": -1888,\n      \"tAsc\": 3633,\n      \"tDes\": -1888,\n      \"tLGap\": 0,\n      \"wAsc\": 3633,\n      \"wDes\": 1081,\n      \"xH\": 1606,\n      \"capH\": 2732,\n      \"yMin\": -1081,\n      \"yMax\": 3633,\n      \"hAsc\": 3633,\n      \"hDes\": -1888,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LINE Seed JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -168,\n      \"tAsc\": 932,\n      \"tDes\": -168,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 317,\n      \"xH\": 509,\n      \"capH\": 751,\n      \"yMin\": -466,\n      \"yMax\": 1112,\n      \"hAsc\": 932,\n      \"hDes\": -168,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Linefont\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -200,\n      \"tAsc\": 1200,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1274,\n      \"yMax\": 1320,\n      \"hAsc\": 1200,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lisu Bosa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 230,\n      \"xH\": 425,\n      \"capH\": 530,\n      \"yMin\": -230,\n      \"yMax\": 834,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Liter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -396,\n      \"tAsc\": 1030,\n      \"tDes\": -396,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 396,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -396,\n      \"yMax\": 979,\n      \"hAsc\": 1030,\n      \"hDes\": -396,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Literata\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1177,\n      \"des\": -308,\n      \"tAsc\": 1177,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 308,\n      \"xH\": 507,\n      \"capH\": 701,\n      \"yMin\": -268,\n      \"yMax\": 1136,\n      \"hAsc\": 1177,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Liu Jian Mao Cao\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 615,\n      \"xH\": 420,\n      \"capH\": 600,\n      \"yMin\": -615,\n      \"yMax\": 888,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Livvic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -250,\n      \"tAsc\": 1005,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1171,\n      \"wDes\": 285,\n      \"xH\": 497,\n      \"capH\": 710,\n      \"yMin\": -270,\n      \"yMax\": 1101,\n      \"hAsc\": 1005,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lobster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 490,\n      \"xH\": 500,\n      \"capH\": 748,\n      \"yMin\": -490,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lobster Two\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 754,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Outline\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 215,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -215,\n      \"yMax\": 940,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 238,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -238,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Sketch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 935,\n      \"wDes\": 217,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -217,\n      \"yMax\": 935,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Londrina Solid\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 300, 400, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -238,\n      \"tAsc\": 945,\n      \"tDes\": -238,\n      \"tLGap\": 0,\n      \"wAsc\": 941,\n      \"wDes\": 215,\n      \"xH\": 508,\n      \"capH\": 722,\n      \"yMin\": -208,\n      \"yMax\": 937,\n      \"hAsc\": 945,\n      \"hDes\": -238,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Long Cang\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 318,\n      \"xH\": 512,\n      \"capH\": 684,\n      \"yMin\": -318,\n      \"yMax\": 868,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lora\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -274,\n      \"tAsc\": 1006,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1206,\n      \"wDes\": 294,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -271,\n      \"yMax\": 1114,\n      \"hAsc\": 1006,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Love Light\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -500,\n      \"tAsc\": 900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 531,\n      \"xH\": 320,\n      \"capH\": 700,\n      \"yMin\": -531,\n      \"yMax\": 1020,\n      \"hAsc\": 900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Love Ya Like A Sister\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 942,\n      \"des\": -333,\n      \"tAsc\": 942,\n      \"tDes\": -333,\n      \"tLGap\": 0,\n      \"wAsc\": 942,\n      \"wDes\": 333,\n      \"xH\": 510,\n      \"capH\": 674,\n      \"yMin\": -333,\n      \"yMax\": 942,\n      \"hAsc\": 942,\n      \"hDes\": -333,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Loved by the King\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2398,\n      \"des\": -1137,\n      \"tAsc\": 2398,\n      \"tDes\": -1137,\n      \"tLGap\": 0,\n      \"wAsc\": 2398,\n      \"wDes\": 1137,\n      \"xH\": 1111,\n      \"capH\": 1774,\n      \"yMin\": -1024,\n      \"yMax\": 2157,\n      \"hAsc\": 2398,\n      \"hDes\": -1137,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lovers Quarrel\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 726,\n      \"des\": -401,\n      \"tAsc\": 726,\n      \"tDes\": -401,\n      \"tLGap\": 0,\n      \"wAsc\": 810,\n      \"wDes\": 420,\n      \"xH\": 274,\n      \"capH\": 609,\n      \"yMin\": -402,\n      \"yMax\": 777,\n      \"hAsc\": 726,\n      \"hDes\": -401,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lucida Bright\",\n    \"fallbacks\": [\"Georgia\", \"serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1980,\n      \"des\": -432,\n      \"tAsc\": 1579,\n      \"tDes\": -420,\n      \"tLGap\": 49,\n      \"wAsc\": 1900,\n      \"wDes\": 1900,\n      \"yMin\": -432,\n      \"yMax\": 1900,\n      \"hAsc\": 1980,\n      \"hDes\": -432,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Lucida Sans Typewriter\",\n    \"fallbacks\": [\n      \"Lucida Console\",\n      \"monaco\",\n      \"Bitstream Vera Sans Mono\",\n      \"monospace\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1974,\n      \"des\": -432,\n      \"tAsc\": 1579,\n      \"tDes\": 420,\n      \"tLGap\": 49,\n      \"wAsc\": 1900,\n      \"wDes\": 1900,\n      \"yMin\": -420,\n      \"yMax\": 1900,\n      \"hAsc\": 1974,\n      \"hDes\": -432,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Luckiest Guy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 2006,\n      \"wDes\": 504,\n      \"xH\": 1400,\n      \"capH\": 1424,\n      \"yMin\": -716,\n      \"yMax\": 2045,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lugrasimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2122,\n      \"des\": -666,\n      \"tAsc\": 1752,\n      \"tDes\": -666,\n      \"tLGap\": -370,\n      \"wAsc\": 1900,\n      \"wDes\": 666,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -670,\n      \"yMax\": 2122,\n      \"hAsc\": 2122,\n      \"hDes\": -666,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lumanosimo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2098,\n      \"des\": -727,\n      \"tAsc\": 1752,\n      \"tDes\": -666,\n      \"tLGap\": -370,\n      \"wAsc\": 1964,\n      \"wDes\": 666,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -461,\n      \"yMax\": 2060,\n      \"hAsc\": 2098,\n      \"hDes\": -727,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lunasima\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1980,\n      \"des\": -432,\n      \"tAsc\": 1604,\n      \"tDes\": -419,\n      \"tLGap\": 168,\n      \"wAsc\": 1980,\n      \"wDes\": 432,\n      \"xH\": 1086,\n      \"capH\": 1480,\n      \"yMin\": -832,\n      \"yMax\": 2134,\n      \"hAsc\": 1980,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lusitana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -341,\n      \"tAsc\": 956,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 341,\n      \"xH\": 139,\n      \"capH\": 714,\n      \"yMin\": -337,\n      \"yMax\": 933,\n      \"hAsc\": 956,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Lustria\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -327,\n      \"tAsc\": 955,\n      \"tDes\": -227,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 327,\n      \"xH\": 504,\n      \"capH\": 704,\n      \"yMin\": -327,\n      \"yMax\": 955,\n      \"hAsc\": 955,\n      \"hDes\": -327,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Luxurious Roman\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1017,\n      \"wDes\": 402,\n      \"xH\": 480,\n      \"capH\": 665,\n      \"yMin\": -402,\n      \"yMax\": 1017,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Luxurious Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 515,\n      \"xH\": 330,\n      \"capH\": 565,\n      \"yMin\": -515,\n      \"yMax\": 934,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW Marker Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -198,\n      \"tAsc\": 982,\n      \"tDes\": -198,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 510,\n      \"capH\": 760,\n      \"yMin\": -267,\n      \"yMax\": 1240,\n      \"hAsc\": 982,\n      \"hDes\": -198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW WenKai Mono TC\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -241,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 241,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -306,\n      \"yMax\": 1103,\n      \"hAsc\": 928,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"LXGW WenKai TC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1032,\n      \"des\": -285,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1032,\n      \"wDes\": 285,\n      \"xH\": 468,\n      \"capH\": 695,\n      \"yMin\": -285,\n      \"yMax\": 1102,\n      \"hAsc\": 1032,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1189,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1 Code\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -235,\n      \"tAsc\": 1000,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1235,\n      \"wDes\": 270,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1213,\n      \"hAsc\": 1000,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS 1p\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -320,\n      \"tAsc\": 860,\n      \"tDes\": -140,\n      \"tLGap\": 90,\n      \"wAsc\": 1075,\n      \"wDes\": 320,\n      \"yMin\": -343,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -320,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"M PLUS 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1189,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS Code Latin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -235,\n      \"tAsc\": 1000,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1235,\n      \"wDes\": 270,\n      \"xH\": 520,\n      \"capH\": 730,\n      \"yMin\": -270,\n      \"yMax\": 1213,\n      \"hAsc\": 1000,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"M PLUS Rounded 1c\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -320,\n      \"tAsc\": 860,\n      \"tDes\": -140,\n      \"tLGap\": 90,\n      \"wAsc\": 1075,\n      \"wDes\": 320,\n      \"yMin\": -343,\n      \"yMax\": 1075,\n      \"hAsc\": 1075,\n      \"hDes\": -320,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Ma Shan Zheng\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 373,\n      \"xH\": 506,\n      \"capH\": 760,\n      \"yMin\": -373,\n      \"yMax\": 915,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Macondo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 888,\n      \"des\": -292,\n      \"tAsc\": 888,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 888,\n      \"wDes\": 292,\n      \"xH\": 24,\n      \"capH\": 53,\n      \"yMin\": -292,\n      \"yMax\": 888,\n      \"hAsc\": 888,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Macondo Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 888,\n      \"des\": -292,\n      \"tAsc\": 888,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 888,\n      \"wDes\": 292,\n      \"xH\": 24,\n      \"capH\": 696,\n      \"yMin\": -292,\n      \"yMax\": 888,\n      \"hAsc\": 888,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -350,\n      \"tAsc\": 950,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1185,\n      \"wDes\": 420,\n      \"xH\": 486,\n      \"capH\": 656,\n      \"yMin\": -403,\n      \"yMax\": 1088,\n      \"hAsc\": 950,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Madimi One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1010,\n      \"des\": -310,\n      \"tAsc\": 1010,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Magra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -247,\n      \"tAsc\": 968,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 968,\n      \"wDes\": 247,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -247,\n      \"yMax\": 941,\n      \"hAsc\": 968,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maiden Orange\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1832,\n      \"wDes\": 506,\n      \"xH\": 1056,\n      \"capH\": 1406,\n      \"yMin\": -635,\n      \"yMax\": 1848,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maitree\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -500,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 500,\n      \"xH\": 489,\n      \"capH\": 695,\n      \"yMin\": -463,\n      \"yMax\": 1111,\n      \"hAsc\": 1150,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Major Mono Display\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -100,\n      \"tAsc\": 900,\n      \"tDes\": -100,\n      \"tLGap\": 0,\n      \"wAsc\": 1152,\n      \"wDes\": 223,\n      \"xH\": 696,\n      \"capH\": 696,\n      \"yMin\": -223,\n      \"yMax\": 1152,\n      \"hAsc\": 900,\n      \"hDes\": -100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mako\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2141,\n      \"des\": -538,\n      \"tAsc\": 2141,\n      \"tDes\": -538,\n      \"tLGap\": 0,\n      \"wAsc\": 2141,\n      \"wDes\": 538,\n      \"xH\": 1031,\n      \"capH\": 1437,\n      \"yMin\": -538,\n      \"yMax\": 2093,\n      \"hAsc\": 2141,\n      \"hDes\": -538,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mali\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1523,\n      \"wDes\": 599,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -516,\n      \"yMax\": 1410,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mallanna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 870,\n      \"asc\": 1105,\n      \"des\": -504,\n      \"tAsc\": 1105,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 504,\n      \"xH\": 379,\n      \"capH\": 546,\n      \"yMin\": -504,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maname\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": 0,\n      \"tAsc\": 1200,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 342,\n      \"xH\": 424,\n      \"capH\": 578,\n      \"yMin\": -307,\n      \"yMax\": 1110,\n      \"hAsc\": 1200,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mandali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 790,\n      \"asc\": 1087,\n      \"des\": -475,\n      \"tAsc\": 1087,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 1087,\n      \"wDes\": 475,\n      \"xH\": 382,\n      \"capH\": 550,\n      \"yMin\": -475,\n      \"yMax\": 1087,\n      \"hAsc\": 1087,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manjari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1500,\n      \"des\": -750,\n      \"tAsc\": 1500,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 2076,\n      \"wDes\": 1285,\n      \"xH\": 1024,\n      \"capH\": 1385,\n      \"yMin\": -1231,\n      \"yMax\": 1978,\n      \"hAsc\": 1500,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manrope\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2132,\n      \"des\": -600,\n      \"tAsc\": 2132,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2132,\n      \"wDes\": 600,\n      \"xH\": 1080,\n      \"capH\": 1440,\n      \"yMin\": -550,\n      \"yMax\": 2241,\n      \"hAsc\": 2132,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mansalva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1112,\n      \"des\": -466,\n      \"tAsc\": 1112,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 435,\n      \"xH\": 384,\n      \"capH\": 702,\n      \"yMin\": -435,\n      \"yMax\": 1112,\n      \"hAsc\": 1112,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Manuale\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -236,\n      \"tAsc\": 980,\n      \"tDes\": -236,\n      \"tLGap\": 221,\n      \"wAsc\": 980,\n      \"wDes\": 236,\n      \"xH\": 491,\n      \"capH\": 611,\n      \"yMin\": -236,\n      \"yMax\": 980,\n      \"hAsc\": 980,\n      \"hDes\": -236,\n      \"lGap\": 221\n    }\n  },\n  {\n    \"family\": \"Manufacturing Consent\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 1100,\n      \"des\": -340,\n      \"tAsc\": 1100,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 415,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -415,\n      \"yMax\": 1079,\n      \"hAsc\": 1100,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marcellus\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1995,\n      \"des\": -573,\n      \"tAsc\": 1995,\n      \"tDes\": -573,\n      \"tLGap\": 0,\n      \"wAsc\": 1995,\n      \"wDes\": 573,\n      \"xH\": 1024,\n      \"capH\": 1434,\n      \"yMin\": -573,\n      \"yMax\": 1995,\n      \"hAsc\": 1995,\n      \"hDes\": -573,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marcellus SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1995,\n      \"des\": -573,\n      \"tAsc\": 1995,\n      \"tDes\": -573,\n      \"tLGap\": 0,\n      \"wAsc\": 1995,\n      \"wDes\": 573,\n      \"xH\": 1075,\n      \"capH\": 1434,\n      \"yMin\": -573,\n      \"yMax\": 1995,\n      \"hAsc\": 1995,\n      \"hDes\": -573,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marck Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -385,\n      \"tAsc\": 864,\n      \"tDes\": -385,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 385,\n      \"xH\": 263,\n      \"capH\": 638,\n      \"yMin\": -385,\n      \"yMax\": 864,\n      \"hAsc\": 864,\n      \"hDes\": -385,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Margarine\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2075,\n      \"des\": -678,\n      \"tAsc\": 2075,\n      \"tDes\": -678,\n      \"tLGap\": 0,\n      \"wAsc\": 2075,\n      \"wDes\": 678,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -678,\n      \"yMax\": 2075,\n      \"hAsc\": 2075,\n      \"hDes\": -678,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marhey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -640,\n      \"tAsc\": 1100,\n      \"tDes\": -640,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 700,\n      \"xH\": 450,\n      \"capH\": 750,\n      \"yMin\": -700,\n      \"yMax\": 1097,\n      \"hAsc\": 1100,\n      \"hDes\": -640,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Markazi Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1718,\n      \"des\": -740,\n      \"tAsc\": 1718,\n      \"tDes\": -740,\n      \"tLGap\": 0,\n      \"wAsc\": 1695,\n      \"wDes\": 963,\n      \"xH\": 746,\n      \"capH\": 990,\n      \"yMin\": -893,\n      \"yMax\": 1664,\n      \"hAsc\": 1718,\n      \"hDes\": -740,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marko One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2019,\n      \"des\": -727,\n      \"tAsc\": 2019,\n      \"tDes\": -727,\n      \"tLGap\": 0,\n      \"wAsc\": 2019,\n      \"wDes\": 727,\n      \"xH\": 713,\n      \"capH\": 1475,\n      \"yMin\": -727,\n      \"yMax\": 2019,\n      \"hAsc\": 2019,\n      \"hDes\": -727,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marmelad\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -221,\n      \"tAsc\": 972,\n      \"tDes\": -221,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 252,\n      \"xH\": 502,\n      \"capH\": 709,\n      \"yMin\": -252,\n      \"yMax\": 1106,\n      \"hAsc\": 972,\n      \"hDes\": -221,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martel\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -562,\n      \"tAsc\": 1125,\n      \"tDes\": -562,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 562,\n      \"xH\": 546,\n      \"capH\": 758,\n      \"yMin\": -542,\n      \"yMax\": 1050,\n      \"hAsc\": 1125,\n      \"hDes\": -562,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martel Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -674,\n      \"tAsc\": 1150,\n      \"tDes\": -674,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 674,\n      \"xH\": 534,\n      \"capH\": 680,\n      \"yMin\": -519,\n      \"yMax\": 1071,\n      \"hAsc\": 1150,\n      \"hDes\": -674,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Martian Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 250,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -251,\n      \"yMax\": 1088,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Marvel\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 951,\n      \"des\": -259,\n      \"tAsc\": 951,\n      \"tDes\": -259,\n      \"tLGap\": 0,\n      \"wAsc\": 951,\n      \"wDes\": 259,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -259,\n      \"yMax\": 951,\n      \"hAsc\": 951,\n      \"hDes\": -259,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Matangi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -360,\n      \"tAsc\": 1200,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 702,\n      \"xH\": 840,\n      \"capH\": 948,\n      \"yMin\": -740,\n      \"yMax\": 1332,\n      \"hAsc\": 1200,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mate\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -262,\n      \"tAsc\": 958,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1041,\n      \"wDes\": 307,\n      \"xH\": 456,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 1039,\n      \"hAsc\": 958,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mate SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -262,\n      \"tAsc\": 958,\n      \"tDes\": -262,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 262,\n      \"xH\": 473,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 1039,\n      \"hAsc\": 958,\n      \"hDes\": -262,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Matemasie\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -230,\n      \"tAsc\": 1250,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1273,\n      \"wDes\": 241,\n      \"xH\": 600,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 1272,\n      \"hAsc\": 1250,\n      \"hDes\": -230,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -3,\n      \"yMax\": 515,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Outlined\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Round\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Sharp\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Icons Two Tone\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 512,\n      \"asc\": 512,\n      \"des\": 0,\n      \"tAsc\": 512,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 512,\n      \"wDes\": 0,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": 0,\n      \"yMax\": 512,\n      \"hAsc\": 512,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 961,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Outlined\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 961,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Rounded\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 962,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Material Symbols Sharp\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 1056,\n      \"des\": -96,\n      \"tAsc\": 1056,\n      \"tDes\": -96,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 91,\n      \"xH\": 960,\n      \"capH\": 960,\n      \"yMin\": -91,\n      \"yMax\": 985,\n      \"hAsc\": 1056,\n      \"hDes\": -96,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Maven Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 965,\n      \"des\": -210,\n      \"tAsc\": 965,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 233,\n      \"xH\": 499,\n      \"capH\": 667,\n      \"yMin\": -217,\n      \"yMax\": 1030,\n      \"hAsc\": 965,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"McLaren\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2216,\n      \"des\": -722,\n      \"tAsc\": 2216,\n      \"tDes\": -722,\n      \"tLGap\": 0,\n      \"wAsc\": 2216,\n      \"wDes\": 722,\n      \"xH\": 1042,\n      \"capH\": 1445,\n      \"yMin\": -729,\n      \"yMax\": 2216,\n      \"hAsc\": 2216,\n      \"hDes\": -722,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mea Culpa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -400,\n      \"tAsc\": 1000,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1098,\n      \"wDes\": 593,\n      \"xH\": 300,\n      \"capH\": 800,\n      \"yMin\": -593,\n      \"yMax\": 1098,\n      \"hAsc\": 1000,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meddon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2860,\n      \"des\": -1457,\n      \"tAsc\": 2860,\n      \"tDes\": -1457,\n      \"tLGap\": 0,\n      \"wAsc\": 2860,\n      \"wDes\": 1457,\n      \"xH\": 756,\n      \"capH\": 2177,\n      \"yMin\": -1457,\n      \"yMax\": 3565,\n      \"hAsc\": 2860,\n      \"hDes\": -1457,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MedievalSharp\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1771,\n      \"des\": -543,\n      \"tAsc\": 1771,\n      \"tDes\": -543,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 543,\n      \"xH\": 224,\n      \"capH\": 201,\n      \"yMin\": -467,\n      \"yMax\": 1951,\n      \"hAsc\": 1771,\n      \"hDes\": -543,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Medula One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 846,\n      \"des\": -162,\n      \"tAsc\": 846,\n      \"tDes\": -162,\n      \"tLGap\": 0,\n      \"wAsc\": 846,\n      \"wDes\": 162,\n      \"xH\": 490,\n      \"capH\": 650,\n      \"yMin\": -162,\n      \"yMax\": 846,\n      \"hAsc\": 846,\n      \"hDes\": -162,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meera Inimai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1986,\n      \"des\": -1200,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1986,\n      \"wDes\": 1200,\n      \"xH\": 1056,\n      \"capH\": 1460,\n      \"yMin\": -1200,\n      \"yMax\": 1986,\n      \"hAsc\": 1986,\n      \"hDes\": -1200,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Megrim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 90,\n      \"wAsc\": 880,\n      \"wDes\": 200,\n      \"xH\": 580,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 880,\n      \"hAsc\": 880,\n      \"hDes\": -200,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Meie Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1814,\n      \"des\": -780,\n      \"tAsc\": 1814,\n      \"tDes\": -780,\n      \"tLGap\": 0,\n      \"wAsc\": 1814,\n      \"wDes\": 780,\n      \"xH\": 354,\n      \"capH\": 862,\n      \"yMin\": -780,\n      \"yMax\": 1814,\n      \"hAsc\": 1814,\n      \"hDes\": -780,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Menbere\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1229,\n      \"des\": -338,\n      \"tAsc\": 1229,\n      \"tDes\": -338,\n      \"tLGap\": 0,\n      \"wAsc\": 1340,\n      \"wDes\": 380,\n      \"xH\": 570,\n      \"capH\": 758,\n      \"yMin\": -341,\n      \"yMax\": 1288,\n      \"hAsc\": 1229,\n      \"hDes\": -338,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Meow Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -370,\n      \"tAsc\": 830,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 947,\n      \"wDes\": 662,\n      \"xH\": 320,\n      \"capH\": 560,\n      \"yMin\": -622,\n      \"yMax\": 947,\n      \"hAsc\": 830,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merienda\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1102,\n      \"des\": -342,\n      \"tAsc\": 1102,\n      \"tDes\": -342,\n      \"tLGap\": 0,\n      \"wAsc\": 1436,\n      \"wDes\": 418,\n      \"xH\": 599,\n      \"capH\": 847,\n      \"yMin\": -347,\n      \"yMax\": 1403,\n      \"hAsc\": 1102,\n      \"hDes\": -342,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merriweather\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1968,\n      \"des\": -546,\n      \"tAsc\": 1968,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 2476,\n      \"wDes\": 988,\n      \"xH\": 1111,\n      \"capH\": 1486,\n      \"yMin\": -969,\n      \"yMax\": 2429,\n      \"hAsc\": 1968,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Merriweather Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1968,\n      \"des\": -546,\n      \"tAsc\": 1968,\n      \"tDes\": -546,\n      \"tLGap\": 0,\n      \"wAsc\": 2580,\n      \"wDes\": 660,\n      \"xH\": 1114,\n      \"capH\": 1486,\n      \"yMin\": -567,\n      \"yMax\": 2472,\n      \"hAsc\": 1968,\n      \"hDes\": -546,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metal\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2600,\n      \"des\": -1600,\n      \"tAsc\": 2600,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 3166,\n      \"wDes\": 1600,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1600,\n      \"yMax\": 3166,\n      \"hAsc\": 2600,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metal Mania\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 965,\n      \"des\": -303,\n      \"tAsc\": 965,\n      \"tDes\": -303,\n      \"tLGap\": 0,\n      \"wAsc\": 965,\n      \"wDes\": 303,\n      \"xH\": 620,\n      \"capH\": 820,\n      \"yMin\": -303,\n      \"yMax\": 965,\n      \"hAsc\": 965,\n      \"hDes\": -303,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metamorphous\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1972,\n      \"des\": -588,\n      \"tAsc\": 1972,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1972,\n      \"wDes\": 588,\n      \"xH\": 1208,\n      \"capH\": 1530,\n      \"yMin\": -588,\n      \"yMax\": 1972,\n      \"hAsc\": 1972,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Metrophobic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2065,\n      \"des\": -460,\n      \"tAsc\": 2065,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 2284,\n      \"wDes\": 597,\n      \"xH\": 1011,\n      \"capH\": 1441,\n      \"yMin\": -597,\n      \"yMax\": 2284,\n      \"hAsc\": 2065,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Michroma\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2368,\n      \"des\": -544,\n      \"tAsc\": 2368,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 3040,\n      \"wDes\": 576,\n      \"xH\": 1152,\n      \"capH\": 1536,\n      \"yMin\": -576,\n      \"yMax\": 3040,\n      \"hAsc\": 2368,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Micro 5\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1650,\n      \"asc\": 1190,\n      \"des\": -460,\n      \"tAsc\": 1190,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1350,\n      \"wDes\": 460,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -450,\n      \"yMax\": 1350,\n      \"hAsc\": 1190,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Micro 5 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1650,\n      \"asc\": 1190,\n      \"des\": -460,\n      \"tAsc\": 1190,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1350,\n      \"wDes\": 460,\n      \"xH\": 600,\n      \"capH\": 750,\n      \"yMin\": -460,\n      \"yMax\": 1350,\n      \"hAsc\": 1190,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Milonga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -260,\n      \"tAsc\": 990,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 260,\n      \"xH\": 458,\n      \"capH\": 809,\n      \"yMin\": -260,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miltonian\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -274,\n      \"tAsc\": 918,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 274,\n      \"xH\": 454,\n      \"capH\": 689,\n      \"yMin\": -274,\n      \"yMax\": 918,\n      \"hAsc\": 918,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miltonian Tattoo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -274,\n      \"tAsc\": 918,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 274,\n      \"xH\": 454,\n      \"capH\": 689,\n      \"yMin\": -274,\n      \"yMax\": 918,\n      \"hAsc\": 918,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mina\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1075,\n      \"des\": -515,\n      \"tAsc\": 1075,\n      \"tDes\": -515,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 539,\n      \"yMin\": -487,\n      \"yMax\": 1002,\n      \"hAsc\": 1075,\n      \"hDes\": -515,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mingzat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1427,\n      \"des\": -670,\n      \"tAsc\": 1427,\n      \"tDes\": -670,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 670,\n      \"xH\": 705,\n      \"capH\": 1100,\n      \"yMin\": -670,\n      \"yMax\": 1530,\n      \"hAsc\": 1427,\n      \"hDes\": -670,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miniver\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -474,\n      \"tAsc\": 1019,\n      \"tDes\": -474,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 474,\n      \"xH\": 501,\n      \"capH\": 782,\n      \"yMin\": -474,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -474,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miranda Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -240,\n      \"tAsc\": 990,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 990,\n      \"wDes\": 240,\n      \"xH\": 520,\n      \"capH\": 720,\n      \"yMin\": -230,\n      \"yMax\": 990,\n      \"hAsc\": 990,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Miriam Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 969,\n      \"des\": -344,\n      \"tAsc\": 969,\n      \"tDes\": -344,\n      \"tLGap\": 0,\n      \"wAsc\": 969,\n      \"wDes\": 344,\n      \"xH\": 566,\n      \"capH\": 695,\n      \"yMin\": -335,\n      \"yMax\": 952,\n      \"hAsc\": 969,\n      \"hDes\": -344,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mirza\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 547,\n      \"des\": -453,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 200,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -571,\n      \"yMax\": 1088,\n      \"hAsc\": 547,\n      \"hDes\": -453,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Miss Fajardose\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -389,\n      \"tAsc\": 859,\n      \"tDes\": -389,\n      \"tLGap\": 0,\n      \"wAsc\": 859,\n      \"wDes\": 389,\n      \"xH\": 158,\n      \"capH\": 658,\n      \"yMin\": -389,\n      \"yMax\": 859,\n      \"hAsc\": 859,\n      \"hDes\": -389,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mitr\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -420,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1150,\n      \"wDes\": 420,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1079,\n      \"hAsc\": 1150,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mochiy Pop One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -295,\n      \"yMax\": 1142,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mochiy Pop P One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -295,\n      \"yMax\": 1142,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Modak\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2035,\n      \"des\": -1049,\n      \"tAsc\": 2035,\n      \"tDes\": -1049,\n      \"tLGap\": 0,\n      \"wAsc\": 2035,\n      \"wDes\": 1049,\n      \"xH\": 1099,\n      \"capH\": 1290,\n      \"yMin\": -1049,\n      \"yMax\": 2035,\n      \"hAsc\": 2035,\n      \"hDes\": -1049,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Modern Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1815,\n      \"des\": -508,\n      \"tAsc\": 1815,\n      \"tDes\": -508,\n      \"tLGap\": 0,\n      \"wAsc\": 1815,\n      \"wDes\": 508,\n      \"xH\": 1089,\n      \"capH\": 1511,\n      \"yMin\": -435,\n      \"yMax\": 1950,\n      \"hAsc\": 1815,\n      \"hDes\": -508,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moderustic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1067,\n      \"wDes\": 401,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -401,\n      \"yMax\": 1067,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mogra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 850,\n      \"wDes\": 350,\n      \"xH\": 565,\n      \"capH\": 705,\n      \"yMin\": -574,\n      \"yMax\": 1063,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Mohave\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1980,\n      \"des\": -806,\n      \"tAsc\": 1980,\n      \"tDes\": -806,\n      \"tLGap\": 0,\n      \"wAsc\": 1980,\n      \"wDes\": 806,\n      \"xH\": 1080,\n      \"capH\": 1500,\n      \"yMin\": -806,\n      \"yMax\": 1975,\n      \"hAsc\": 1980,\n      \"hDes\": -806,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moirai One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 488,\n      \"capH\": 778,\n      \"yMin\": -343,\n      \"yMax\": 984,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Molengo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1928,\n      \"des\": -522,\n      \"tAsc\": 1928,\n      \"tDes\": -522,\n      \"tLGap\": 0,\n      \"wAsc\": 1928,\n      \"wDes\": 522,\n      \"xH\": 938,\n      \"capH\": 1391,\n      \"yMin\": -522,\n      \"yMax\": 1928,\n      \"hAsc\": 1928,\n      \"hDes\": -522,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Molle\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"italic\"],\n    \"variants\": [[1, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1852,\n      \"des\": -701,\n      \"tAsc\": 1852,\n      \"tDes\": -701,\n      \"tLGap\": 0,\n      \"wAsc\": 1852,\n      \"wDes\": 701,\n      \"xH\": 910,\n      \"capH\": 1588,\n      \"yMin\": -701,\n      \"yMax\": 1852,\n      \"hAsc\": 1852,\n      \"hDes\": -701,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Signature\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -285,\n      \"tAsc\": 1145,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1345,\n      \"wDes\": 380,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -379,\n      \"yMax\": 1344,\n      \"hAsc\": 1145,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Trust Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 555,\n      \"xH\": 570,\n      \"capH\": 750,\n      \"yMin\": -554,\n      \"yMax\": 1165,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Momo Trust Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -275,\n      \"tAsc\": 1025,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 1228,\n      \"wDes\": 554,\n      \"xH\": 530,\n      \"capH\": 750,\n      \"yMin\": -536,\n      \"yMax\": 1227,\n      \"hAsc\": 1025,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mona Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -320,\n      \"tAsc\": 1090,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1090,\n      \"wDes\": 320,\n      \"xH\": 525,\n      \"capH\": 729,\n      \"yMin\": -242,\n      \"yMax\": 1047,\n      \"hAsc\": 1090,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monda\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2461,\n      \"des\": -875,\n      \"tAsc\": 2461,\n      \"tDes\": -875,\n      \"tLGap\": 0,\n      \"wAsc\": 2480,\n      \"wDes\": 875,\n      \"xH\": 1060,\n      \"capH\": 1446,\n      \"yMin\": -770,\n      \"yMax\": 2383,\n      \"hAsc\": 2461,\n      \"hDes\": -875,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monofett\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2001,\n      \"des\": -315,\n      \"tAsc\": 2001,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 2001,\n      \"wDes\": 315,\n      \"xH\": 1370,\n      \"capH\": 1370,\n      \"yMin\": -315,\n      \"yMax\": 1983,\n      \"hAsc\": 2001,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monomakh\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -341,\n      \"tAsc\": 932,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 984,\n      \"wDes\": 334,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -334,\n      \"yMax\": 984,\n      \"hAsc\": 932,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monomaniac One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 518,\n      \"capH\": 676,\n      \"yMin\": -274,\n      \"yMax\": 876,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monoton\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2366,\n      \"des\": -822,\n      \"tAsc\": 2366,\n      \"tDes\": -822,\n      \"tLGap\": 0,\n      \"wAsc\": 2366,\n      \"wDes\": 822,\n      \"xH\": 1440,\n      \"capH\": 1656,\n      \"yMin\": -822,\n      \"yMax\": 2366,\n      \"hAsc\": 2366,\n      \"hDes\": -822,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Monsieur La Doulaise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1048,\n      \"des\": -513,\n      \"tAsc\": 1048,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 513,\n      \"xH\": 164,\n      \"capH\": 729,\n      \"yMin\": -513,\n      \"yMax\": 1048,\n      \"hAsc\": 1048,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montaga\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 978,\n      \"des\": -254,\n      \"tAsc\": 978,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 978,\n      \"wDes\": 254,\n      \"xH\": 466,\n      \"capH\": 700,\n      \"yMin\": -254,\n      \"yMax\": 978,\n      \"hAsc\": 978,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montagu Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 982,\n      \"des\": -300,\n      \"tAsc\": 982,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1136,\n      \"wDes\": 318,\n      \"xH\": 518,\n      \"capH\": 682,\n      \"yMin\": -262,\n      \"yMax\": 1113,\n      \"hAsc\": 982,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MonteCarlo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -500,\n      \"tAsc\": 1200,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1795,\n      \"wDes\": 1290,\n      \"xH\": 315,\n      \"capH\": 750,\n      \"yMin\": -1293,\n      \"yMax\": 1794,\n      \"hAsc\": 1200,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montez\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1831,\n      \"des\": -848,\n      \"tAsc\": 1831,\n      \"tDes\": -848,\n      \"tLGap\": 0,\n      \"wAsc\": 1831,\n      \"wDes\": 848,\n      \"xH\": 766,\n      \"capH\": 1456,\n      \"yMin\": -848,\n      \"yMax\": 1831,\n      \"hAsc\": 1831,\n      \"hDes\": -848,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 453,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -459,\n      \"yMax\": 1018,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat Alternates\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 270,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -262,\n      \"yMax\": 1043,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Montserrat Underline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 968,\n      \"des\": -251,\n      \"tAsc\": 968,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1109,\n      \"wDes\": 453,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -370,\n      \"yMax\": 1043,\n      \"hAsc\": 968,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moo Lah Lah\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -300,\n      \"tAsc\": 920,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1253,\n      \"wDes\": 367,\n      \"xH\": 565,\n      \"capH\": 650,\n      \"yMin\": -367,\n      \"yMax\": 1253,\n      \"hAsc\": 920,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mooli\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1928,\n      \"des\": -472,\n      \"tAsc\": 1928,\n      \"tDes\": -472,\n      \"tLGap\": 0,\n      \"wAsc\": 1960,\n      \"wDes\": 625,\n      \"xH\": 1026,\n      \"capH\": 1456,\n      \"yMin\": -625,\n      \"yMax\": 1960,\n      \"hAsc\": 1928,\n      \"hDes\": -472,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moon Dance\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -370,\n      \"tAsc\": 970,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 1128,\n      \"wDes\": 595,\n      \"xH\": 350,\n      \"capH\": 605,\n      \"yMin\": -595,\n      \"yMax\": 1128,\n      \"hAsc\": 970,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moul\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1201,\n      \"yMax\": 2501,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Moulpali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2900,\n      \"des\": -1600,\n      \"tAsc\": 2900,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 2950,\n      \"wDes\": 1600,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1600,\n      \"yMax\": 2950,\n      \"hAsc\": 2900,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mountains of Christmas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1066,\n      \"des\": -354,\n      \"tAsc\": 1066,\n      \"tDes\": -354,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 354,\n      \"xH\": 515,\n      \"capH\": 743,\n      \"yMin\": -347,\n      \"yMax\": 1066,\n      \"hAsc\": 1066,\n      \"hDes\": -354,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mouse Memoirs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1917,\n      \"des\": -428,\n      \"tAsc\": 1917,\n      \"tDes\": -428,\n      \"tLGap\": 0,\n      \"wAsc\": 1917,\n      \"wDes\": 428,\n      \"xH\": 1044,\n      \"capH\": 1448,\n      \"yMin\": -428,\n      \"yMax\": 1917,\n      \"hAsc\": 1917,\n      \"hDes\": -428,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mozilla Headline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1323,\n      \"wDes\": 213,\n      \"xH\": 534,\n      \"capH\": 690,\n      \"yMin\": -213,\n      \"yMax\": 1110,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mozilla Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1339,\n      \"wDes\": 229,\n      \"xH\": 534,\n      \"capH\": 690,\n      \"yMin\": -229,\n      \"yMax\": 1110,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr Bedfort\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -661,\n      \"tAsc\": 1015,\n      \"tDes\": -661,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 661,\n      \"xH\": 245,\n      \"capH\": 770,\n      \"yMin\": -661,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -661,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr Dafoe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 981,\n      \"des\": -416,\n      \"tAsc\": 981,\n      \"tDes\": -416,\n      \"tLGap\": 0,\n      \"wAsc\": 981,\n      \"wDes\": 416,\n      \"xH\": 313,\n      \"capH\": 622,\n      \"yMin\": -416,\n      \"yMax\": 981,\n      \"hAsc\": 981,\n      \"hDes\": -416,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mr De Haviland\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -442,\n      \"tAsc\": 875,\n      \"tDes\": -442,\n      \"tLGap\": 0,\n      \"wAsc\": 875,\n      \"wDes\": 442,\n      \"xH\": 217,\n      \"capH\": 557,\n      \"yMin\": -442,\n      \"yMax\": 891,\n      \"hAsc\": 875,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mrs Saint Delafield\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 906,\n      \"des\": -619,\n      \"tAsc\": 906,\n      \"tDes\": -619,\n      \"tLGap\": 0,\n      \"wAsc\": 906,\n      \"wDes\": 619,\n      \"xH\": 224,\n      \"capH\": 708,\n      \"yMin\": -619,\n      \"yMax\": 906,\n      \"hAsc\": 906,\n      \"hDes\": -619,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mrs Sheppards\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -378,\n      \"tAsc\": 959,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 378,\n      \"xH\": 285,\n      \"capH\": 662,\n      \"yMin\": -378,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ms Madi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -420,\n      \"tAsc\": 900,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 975,\n      \"wDes\": 535,\n      \"xH\": 335,\n      \"capH\": 640,\n      \"yMin\": -535,\n      \"yMax\": 973,\n      \"hAsc\": 900,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -508,\n      \"yMax\": 1130,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Mahee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -541,\n      \"yMax\": 956,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Malar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -351,\n      \"yMax\": 935,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mukta Vaani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -532,\n      \"tAsc\": 1130,\n      \"tDes\": -532,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 532,\n      \"xH\": 468,\n      \"capH\": 630,\n      \"yMin\": -494,\n      \"yMax\": 935,\n      \"hAsc\": 1130,\n      \"hDes\": -532,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mulish\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -250,\n      \"tAsc\": 1005,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 297,\n      \"xH\": 500,\n      \"capH\": 705,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1005,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Murecho\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 728,\n      \"yMin\": -291,\n      \"yMax\": 939,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"MuseoModerno\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -445,\n      \"tAsc\": 1145,\n      \"tDes\": -445,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 445,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -381,\n      \"yMax\": 1109,\n      \"hAsc\": 1145,\n      \"hDes\": -445,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"My Soul\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -350,\n      \"tAsc\": 975,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1170,\n      \"wDes\": 515,\n      \"xH\": 360,\n      \"capH\": 760,\n      \"yMin\": -513,\n      \"yMax\": 1167,\n      \"hAsc\": 975,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mynerve\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -380,\n      \"tAsc\": 930,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 469,\n      \"xH\": 420,\n      \"capH\": 670,\n      \"yMin\": -469,\n      \"yMax\": 985,\n      \"hAsc\": 930,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Mystery Quest\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 989,\n      \"des\": -409,\n      \"tAsc\": 989,\n      \"tDes\": -409,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 419,\n      \"xH\": 626,\n      \"capH\": 769,\n      \"yMin\": -409,\n      \"yMax\": 989,\n      \"hAsc\": 989,\n      \"hDes\": -409,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nabla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1263,\n      \"des\": -380,\n      \"tAsc\": 1263,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1263,\n      \"wDes\": 380,\n      \"xH\": 500,\n      \"capH\": 600,\n      \"yMin\": -380,\n      \"yMax\": 1263,\n      \"hAsc\": 1263,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Namdhinggo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1600,\n      \"des\": -550,\n      \"tAsc\": 1600,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1778,\n      \"wDes\": 550,\n      \"xH\": 500,\n      \"capH\": 1150,\n      \"yMin\": -534,\n      \"yMax\": 1728,\n      \"hAsc\": 1600,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Brush Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 630,\n      \"des\": -370,\n      \"tAsc\": 630,\n      \"tDes\": -370,\n      \"tLGap\": 250,\n      \"wAsc\": 635,\n      \"wDes\": 372,\n      \"xH\": 300,\n      \"capH\": 460,\n      \"yMin\": -370,\n      \"yMax\": 632,\n      \"hAsc\": 630,\n      \"hDes\": -370,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Nanum Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 844,\n      \"des\": -156,\n      \"tAsc\": 856,\n      \"tDes\": -144,\n      \"tLGap\": 250,\n      \"wAsc\": 885,\n      \"wDes\": 198,\n      \"xH\": 542,\n      \"capH\": 743,\n      \"yMin\": -198,\n      \"yMax\": 844,\n      \"hAsc\": 844,\n      \"hDes\": -156,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Gothic Coding\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 498,\n      \"capH\": 699,\n      \"yMin\": -200,\n      \"yMax\": 801,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nanum Myeongjo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 819,\n      \"des\": -205,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 256,\n      \"wAsc\": 932,\n      \"wDes\": 247,\n      \"xH\": 480,\n      \"capH\": 755,\n      \"yMin\": -237,\n      \"yMax\": 929,\n      \"hAsc\": 819,\n      \"hDes\": -205,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Nanum Pen Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 809,\n      \"wDes\": 202,\n      \"xH\": 476,\n      \"capH\": 674,\n      \"yMin\": -200,\n      \"yMax\": 801,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Narnoor\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1314,\n      \"des\": -237,\n      \"tAsc\": 1314,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1314,\n      \"wDes\": 237,\n      \"xH\": 553,\n      \"capH\": 735,\n      \"yMin\": -237,\n      \"yMax\": 939,\n      \"hAsc\": 1314,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nata Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -250,\n      \"tAsc\": 1050,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 419,\n      \"xH\": 500,\n      \"capH\": 660,\n      \"yMin\": -288,\n      \"yMax\": 1014,\n      \"hAsc\": 1050,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"National Park\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -300,\n      \"tAsc\": 1030,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1194,\n      \"wDes\": 300,\n      \"xH\": 515,\n      \"capH\": 700,\n      \"yMin\": -217,\n      \"yMax\": 1194,\n      \"hAsc\": 1030,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Neonderthaw\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -300,\n      \"tAsc\": 1050,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1152,\n      \"wDes\": 534,\n      \"xH\": 350,\n      \"capH\": 750,\n      \"yMin\": -534,\n      \"yMax\": 1152,\n      \"hAsc\": 1050,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nerko One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 894,\n      \"des\": -317,\n      \"tAsc\": 894,\n      \"tDes\": -317,\n      \"tLGap\": 0,\n      \"wAsc\": 937,\n      \"wDes\": 319,\n      \"xH\": 426,\n      \"capH\": 586,\n      \"yMin\": -319,\n      \"yMax\": 937,\n      \"hAsc\": 894,\n      \"hDes\": -317,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Neucha\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 787,\n      \"des\": -292,\n      \"tAsc\": 787,\n      \"tDes\": -292,\n      \"tLGap\": 49,\n      \"wAsc\": 954,\n      \"wDes\": 296,\n      \"xH\": 523,\n      \"capH\": 720,\n      \"yMin\": -296,\n      \"yMax\": 981,\n      \"hAsc\": 787,\n      \"hDes\": -292,\n      \"lGap\": 49\n    }\n  },\n  {\n    \"family\": \"Neuton\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2106,\n      \"des\": -485,\n      \"tAsc\": 2106,\n      \"tDes\": -485,\n      \"tLGap\": 0,\n      \"wAsc\": 2106,\n      \"wDes\": 485,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -418,\n      \"yMax\": 1710,\n      \"hAsc\": 2106,\n      \"hDes\": -485,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Amsterdam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 820,\n      \"wDes\": 212,\n      \"xH\": 649,\n      \"capH\": 650,\n      \"yMin\": -212,\n      \"yMax\": 820,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Rocker\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 946,\n      \"des\": -283,\n      \"tAsc\": 946,\n      \"tDes\": -283,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 283,\n      \"xH\": 465,\n      \"capH\": 733,\n      \"yMin\": -283,\n      \"yMax\": 946,\n      \"hAsc\": 946,\n      \"hDes\": -283,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"New Tegomin\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 438,\n      \"capH\": 635,\n      \"yMin\": -281,\n      \"yMax\": 914,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"News Cycle\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2574,\n      \"des\": -794,\n      \"tAsc\": 2574,\n      \"tDes\": -794,\n      \"tLGap\": 0,\n      \"wAsc\": 2574,\n      \"wDes\": 794,\n      \"yMin\": -794,\n      \"yMax\": 2510,\n      \"hAsc\": 2574,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Newsreader\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1470,\n      \"des\": -530,\n      \"tAsc\": 1470,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2326,\n      \"wDes\": 531,\n      \"xH\": 852,\n      \"capH\": 1340,\n      \"yMin\": -519,\n      \"yMax\": 2131,\n      \"hAsc\": 1470,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Niconne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1898,\n      \"des\": -585,\n      \"tAsc\": 1898,\n      \"tDes\": -585,\n      \"tLGap\": 0,\n      \"wAsc\": 1898,\n      \"wDes\": 585,\n      \"xH\": 218,\n      \"capH\": 1442,\n      \"yMin\": -585,\n      \"yMax\": 1898,\n      \"hAsc\": 1898,\n      \"hDes\": -585,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Niramit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1105,\n      \"des\": -195,\n      \"tAsc\": 1105,\n      \"tDes\": -195,\n      \"tLGap\": 0,\n      \"wAsc\": 1246,\n      \"wDes\": 513,\n      \"xH\": 485,\n      \"capH\": 700,\n      \"yMin\": -476,\n      \"yMax\": 1205,\n      \"hAsc\": 1105,\n      \"hDes\": -195,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nixie One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -210,\n      \"tAsc\": 926,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 926,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 920,\n      \"hAsc\": 926,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nobile\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1731,\n      \"des\": -578,\n      \"tAsc\": 1614,\n      \"tDes\": -502,\n      \"tLGap\": 0,\n      \"wAsc\": 1731,\n      \"wDes\": 578,\n      \"xH\": 1169,\n      \"capH\": 1579,\n      \"yMin\": -617,\n      \"yMax\": 2353,\n      \"hAsc\": 1731,\n      \"hDes\": -578,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nokora\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1907,\n      \"des\": -800,\n      \"tAsc\": 1907,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 810,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -810,\n      \"yMax\": 1900,\n      \"hAsc\": 1907,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Norican\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2095,\n      \"des\": -791,\n      \"tAsc\": 2095,\n      \"tDes\": -791,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 791,\n      \"xH\": 810,\n      \"capH\": 1518,\n      \"yMin\": -791,\n      \"yMax\": 2097,\n      \"hAsc\": 2095,\n      \"hDes\": -791,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nosifer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2236,\n      \"des\": -1328,\n      \"tAsc\": 2236,\n      \"tDes\": -1328,\n      \"tLGap\": 0,\n      \"wAsc\": 2236,\n      \"wDes\": 1328,\n      \"xH\": 925,\n      \"capH\": 854,\n      \"yMin\": -1328,\n      \"yMax\": 2236,\n      \"hAsc\": 2236,\n      \"hDes\": -1328,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Notable\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1143,\n      \"des\": -157,\n      \"tAsc\": 1143,\n      \"tDes\": -157,\n      \"tLGap\": 0,\n      \"wAsc\": 1275,\n      \"wDes\": 300,\n      \"xH\": 356,\n      \"capH\": 700,\n      \"yMin\": -213,\n      \"yMax\": 907,\n      \"hAsc\": 1143,\n      \"hDes\": -157,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nothing You Could Do\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 959,\n      \"des\": -407,\n      \"tAsc\": 962,\n      \"tDes\": -407,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 407,\n      \"xH\": 462,\n      \"capH\": 758,\n      \"yMin\": -407,\n      \"yMax\": 959,\n      \"hAsc\": 959,\n      \"hDes\": -407,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noticia Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2202,\n      \"des\": -593,\n      \"tAsc\": 2202,\n      \"tDes\": -593,\n      \"tLGap\": 0,\n      \"wAsc\": 2202,\n      \"wDes\": 593,\n      \"xH\": 1085,\n      \"capH\": 1353,\n      \"yMin\": -593,\n      \"yMax\": 2167,\n      \"hAsc\": 2202,\n      \"hDes\": -593,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Color Emoji\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 250,\n      \"xH\": 512,\n      \"capH\": 717,\n      \"yMin\": -250,\n      \"yMax\": 950,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Emoji\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1900,\n      \"wDes\": 500,\n      \"xH\": 0,\n      \"capH\": 1900,\n      \"yMin\": -415,\n      \"yMax\": 1815,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Kufi Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1282,\n      \"des\": -615,\n      \"tAsc\": 1282,\n      \"tDes\": -615,\n      \"tLGap\": 0,\n      \"wAsc\": 1507,\n      \"wDes\": 650,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -650,\n      \"yMax\": 1507,\n      \"hAsc\": 1282,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Music\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1389,\n      \"des\": -398,\n      \"tAsc\": 1389,\n      \"tDes\": -398,\n      \"tLGap\": 0,\n      \"wAsc\": 1645,\n      \"wDes\": 709,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -709,\n      \"yMax\": 1645,\n      \"hAsc\": 1389,\n      \"hDes\": -398,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Naskh Arabic\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -634,\n      \"tAsc\": 1069,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1405,\n      \"wDes\": 634,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -590,\n      \"yMax\": 1405,\n      \"hAsc\": 1069,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Nastaliq Urdu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1904,\n      \"des\": -596,\n      \"tAsc\": 1904,\n      \"tDes\": -596,\n      \"tLGap\": 0,\n      \"wAsc\": 1904,\n      \"wDes\": 596,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1382,\n      \"yMax\": 1808,\n      \"hAsc\": 1904,\n      \"hDes\": -596,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Rashi Hebrew\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -290,\n      \"tAsc\": 896,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 290,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 896,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1124,\n      \"wDes\": 395,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -508,\n      \"yMax\": 1067,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Adlam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 575,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1004,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Adlam Unjoined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 575,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1004,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Anatolian Hieroglyphs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1153,\n      \"des\": -253,\n      \"tAsc\": 1153,\n      \"tDes\": -253,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 253,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 1148,\n      \"hAsc\": 1153,\n      \"hDes\": -253,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Arabic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1374,\n      \"des\": -738,\n      \"tAsc\": 1374,\n      \"tDes\": -738,\n      \"tLGap\": 0,\n      \"wAsc\": 1431,\n      \"wDes\": 738,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -548,\n      \"yMax\": 1431,\n      \"hAsc\": 1374,\n      \"hDes\": -738,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Armenian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -245,\n      \"yMax\": 995,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Avestan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 652,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Balinese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1363,\n      \"des\": -838,\n      \"tAsc\": 1363,\n      \"tDes\": -838,\n      \"tLGap\": 0,\n      \"wAsc\": 1363,\n      \"wDes\": 838,\n      \"xH\": 536,\n      \"capH\": 700,\n      \"yMin\": -830,\n      \"yMax\": 1289,\n      \"hAsc\": 1363,\n      \"hDes\": -838,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bamum\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1035,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bassa Vah\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 674,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Batak\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 319,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -319,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bengali\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -408,\n      \"tAsc\": 917,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -408,\n      \"yMax\": 995,\n      \"hAsc\": 917,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Bhaiksuki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -460,\n      \"tAsc\": 960,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 630,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -630,\n      \"yMax\": 995,\n      \"hAsc\": 960,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Brahmi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -306,\n      \"tAsc\": 1069,\n      \"tDes\": -306,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 306,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -303,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -306,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Buginese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Buhid\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Canadian Aboriginal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 500,\n      \"capH\": 714,\n      \"yMin\": -267,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Carian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Caucasian Albanian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -274,\n      \"tAsc\": 976,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1071,\n      \"wDes\": 274,\n      \"xH\": 410,\n      \"capH\": 714,\n      \"yMin\": -271,\n      \"yMax\": 1071,\n      \"hAsc\": 976,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Chakma\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1140,\n      \"des\": -320,\n      \"tAsc\": 1140,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 467,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -467,\n      \"yMax\": 1107,\n      \"hAsc\": 1140,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1117,\n      \"des\": -351,\n      \"tAsc\": 1117,\n      \"tDes\": -351,\n      \"tLGap\": 0,\n      \"wAsc\": 1368,\n      \"wDes\": 645,\n      \"xH\": 536,\n      \"capH\": 594,\n      \"yMin\": -494,\n      \"yMax\": 1242,\n      \"hAsc\": 1117,\n      \"hDes\": -351,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cherokee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 535,\n      \"capH\": 714,\n      \"yMin\": -269,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Chorasmian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 550,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Coptic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1044,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cuneiform\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1596,\n      \"des\": -690,\n      \"tAsc\": 1596,\n      \"tDes\": -690,\n      \"tLGap\": 0,\n      \"wAsc\": 1596,\n      \"wDes\": 690,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -690,\n      \"yMax\": 1596,\n      \"hAsc\": 1596,\n      \"hDes\": -690,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cypriot\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 736,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Cypro Minoan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Deseret\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Devanagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 558,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -530,\n      \"yMax\": 1347,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1072,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Duployan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1729,\n      \"wDes\": 833,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -833,\n      \"yMax\": 1672,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Egyptian Hieroglyphs\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -326,\n      \"tAsc\": 1324,\n      \"tDes\": -326,\n      \"tLGap\": 0,\n      \"wAsc\": 1324,\n      \"wDes\": 326,\n      \"xH\": 536,\n      \"capH\": 900,\n      \"yMin\": -326,\n      \"yMax\": 1324,\n      \"hAsc\": 1324,\n      \"hDes\": -326,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Elbasan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 847,\n      \"des\": -270,\n      \"tAsc\": 847,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 270,\n      \"xH\": 560,\n      \"capH\": 714,\n      \"yMin\": -267,\n      \"yMax\": 995,\n      \"hAsc\": 847,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Elymaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 290,\n      \"xH\": 570,\n      \"capH\": 570,\n      \"yMin\": -290,\n      \"yMax\": 995,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ethiopic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Georgian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1086,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 995,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Glagolitic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 646,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Grantha\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1290,\n      \"des\": -534,\n      \"tAsc\": 1290,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1755,\n      \"xH\": 566,\n      \"capH\": 714,\n      \"yMin\": -1755,\n      \"yMax\": 1135,\n      \"hAsc\": 1290,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gujarati\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 1076,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 592,\n      \"yMin\": -394,\n      \"yMax\": 995,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gunjala Gondi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1014,\n      \"des\": -252,\n      \"tAsc\": 1014,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1062,\n      \"wDes\": 286,\n      \"xH\": 561,\n      \"capH\": 622,\n      \"yMin\": -255,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Gurmukhi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -408,\n      \"tAsc\": 896,\n      \"tDes\": -408,\n      \"tLGap\": 0,\n      \"wAsc\": 896,\n      \"wDes\": 408,\n      \"xH\": 622,\n      \"capH\": 622,\n      \"yMin\": -398,\n      \"yMax\": 995,\n      \"hAsc\": 896,\n      \"hDes\": -408,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hanifi Rohingya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 293,\n      \"xH\": 525,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1089,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hanunoo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hatran\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 560,\n      \"capH\": 763,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Hebrew\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -292,\n      \"yMax\": 1068,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans HK\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Imperial Aramaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -276,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Indic Siyaq Numbers\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1215,\n      \"des\": -347,\n      \"tAsc\": 1215,\n      \"tDes\": -347,\n      \"tLGap\": 0,\n      \"wAsc\": 1215,\n      \"wDes\": 347,\n      \"xH\": 553,\n      \"capH\": 964,\n      \"yMin\": -303,\n      \"yMax\": 1210,\n      \"hAsc\": 1215,\n      \"hDes\": -347,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Inscriptional Pahlavi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -352,\n      \"tAsc\": 1069,\n      \"tDes\": -352,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 352,\n      \"xH\": 536,\n      \"capH\": 760,\n      \"yMin\": -352,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -352,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Inscriptional Parthian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -301,\n      \"tAsc\": 1069,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 301,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -301,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Javanese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1120,\n      \"des\": -916,\n      \"tAsc\": 1120,\n      \"tDes\": -916,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 916,\n      \"xH\": 536,\n      \"capH\": 750,\n      \"yMin\": -916,\n      \"yMax\": 1044,\n      \"hAsc\": 1120,\n      \"hDes\": -916,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans JP\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kaithi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1077,\n      \"des\": -425,\n      \"tAsc\": 1077,\n      \"tDes\": -425,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 425,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -425,\n      \"yMax\": 1024,\n      \"hAsc\": 1077,\n      \"hDes\": -425,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kannada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 809,\n      \"des\": -540,\n      \"tAsc\": 809,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 540,\n      \"xH\": 551,\n      \"capH\": 690,\n      \"yMin\": -532,\n      \"yMax\": 995,\n      \"hAsc\": 809,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kawi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -900,\n      \"tAsc\": 1100,\n      \"tDes\": -900,\n      \"tLGap\": 0,\n      \"wAsc\": 1411,\n      \"wDes\": 1034,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1034,\n      \"yMax\": 1266,\n      \"hAsc\": 1100,\n      \"hDes\": -900,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kayah Li\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Kharoshthi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -301,\n      \"tAsc\": 1069,\n      \"tDes\": -301,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 301,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -301,\n      \"yMax\": 1046,\n      \"hAsc\": 1069,\n      \"hDes\": -301,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khmer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1155,\n      \"wDes\": 707,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -691,\n      \"yMax\": 1155,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khojki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1409,\n      \"des\": -447,\n      \"tAsc\": 1409,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1409,\n      \"wDes\": 447,\n      \"xH\": 545,\n      \"capH\": 714,\n      \"yMin\": -445,\n      \"yMax\": 1404,\n      \"hAsc\": 1409,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Khudawadi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -373,\n      \"tAsc\": 944,\n      \"tDes\": -373,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 373,\n      \"xH\": 536,\n      \"capH\": 620,\n      \"yMin\": -370,\n      \"yMax\": 995,\n      \"hAsc\": 944,\n      \"hDes\": -373,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans KR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lao\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1183,\n      \"des\": -462,\n      \"tAsc\": 1183,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1183,\n      \"wDes\": 462,\n      \"xH\": 548,\n      \"capH\": 714,\n      \"yMin\": -438,\n      \"yMax\": 1107,\n      \"hAsc\": 1183,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lao Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -350,\n      \"tAsc\": 1250,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1380,\n      \"wDes\": 620,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -433,\n      \"yMax\": 1182,\n      \"hAsc\": 1250,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lepcha\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -450,\n      \"tAsc\": 1069,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 450,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -425,\n      \"yMax\": 1028,\n      \"hAsc\": 1069,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Limbu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Linear A\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Linear B\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 1020,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lisu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lycian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -16,\n      \"yMax\": 729,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Lydian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mahajani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 757,\n      \"des\": -243,\n      \"tAsc\": 757,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 243,\n      \"xH\": 536,\n      \"capH\": 600,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 757,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Malayalam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -383,\n      \"tAsc\": 864,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 383,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -367,\n      \"yMax\": 995,\n      \"hAsc\": 864,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mandaic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 724,\n      \"des\": -423,\n      \"tAsc\": 724,\n      \"tDes\": -423,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 423,\n      \"xH\": 536,\n      \"capH\": 694,\n      \"yMin\": -403,\n      \"yMax\": 995,\n      \"hAsc\": 724,\n      \"hDes\": -423,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Manichaean\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -340,\n      \"tAsc\": 790,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 340,\n      \"xH\": 439,\n      \"capH\": 625,\n      \"yMin\": -337,\n      \"yMax\": 995,\n      \"hAsc\": 790,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Marchen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1107,\n      \"des\": -534,\n      \"tAsc\": 1107,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1107,\n      \"wDes\": 1025,\n      \"xH\": 678,\n      \"capH\": 678,\n      \"yMin\": -1025,\n      \"yMax\": 995,\n      \"hAsc\": 1107,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Masaram Gondi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 357,\n      \"capH\": 630,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Math\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -423,\n      \"tAsc\": 1069,\n      \"tDes\": -423,\n      \"tLGap\": 0,\n      \"wAsc\": 3105,\n      \"wDes\": 2550,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -2548,\n      \"yMax\": 3104,\n      \"hAsc\": 1069,\n      \"hDes\": -423,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mayan Numerals\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Medefaidrin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 408,\n      \"xH\": 536,\n      \"capH\": 713,\n      \"yMin\": -408,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Meetei Mayek\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -321,\n      \"tAsc\": 1069,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 321,\n      \"xH\": 536,\n      \"capH\": 659,\n      \"yMin\": -318,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mende Kikakui\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -237,\n      \"tAsc\": 1030,\n      \"tDes\": -237,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1017,\n      \"hAsc\": 1030,\n      \"hDes\": -237,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Meroitic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -415,\n      \"tAsc\": 928,\n      \"tDes\": -415,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 415,\n      \"xH\": 536,\n      \"capH\": 680,\n      \"yMin\": -412,\n      \"yMax\": 995,\n      \"hAsc\": 928,\n      \"hDes\": -415,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Miao\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1142,\n      \"des\": -350,\n      \"tAsc\": 1142,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1268,\n      \"wDes\": 553,\n      \"xH\": 341,\n      \"capH\": 714,\n      \"yMin\": -553,\n      \"yMax\": 1268,\n      \"hAsc\": 1142,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Modi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 891,\n      \"des\": -463,\n      \"tAsc\": 891,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 463,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -460,\n      \"yMax\": 995,\n      \"hAsc\": 891,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mongolian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1457,\n      \"des\": -293,\n      \"tAsc\": 1457,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1642,\n      \"wDes\": 388,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -388,\n      \"yMax\": 1642,\n      \"hAsc\": 1457,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1229,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1229,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Mro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Multani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 510,\n      \"capH\": 630,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Myanmar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1324,\n      \"des\": -860,\n      \"tAsc\": 1324,\n      \"tDes\": -860,\n      \"tLGap\": 0,\n      \"wAsc\": 1324,\n      \"wDes\": 860,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -690,\n      \"yMax\": 1252,\n      \"hAsc\": 1324,\n      \"hDes\": -860,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nabataean\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 550,\n      \"capH\": 640,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nag Mundari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1073,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nandinagari\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -560,\n      \"tAsc\": 900,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 560,\n      \"xH\": 558,\n      \"capH\": 622,\n      \"yMin\": -524,\n      \"yMax\": 995,\n      \"hAsc\": 900,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans New Tai Lue\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 474,\n      \"xH\": 510,\n      \"capH\": 714,\n      \"yMin\": -457,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Newa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -396,\n      \"tAsc\": 1036,\n      \"tDes\": -396,\n      \"tLGap\": 0,\n      \"wAsc\": 1036,\n      \"wDes\": 396,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -394,\n      \"yMax\": 1036,\n      \"hAsc\": 1036,\n      \"hDes\": -396,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans NKo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 513,\n      \"capH\": 714,\n      \"yMin\": -272,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans NKo Unjoined\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 293,\n      \"xH\": 513,\n      \"capH\": 714,\n      \"yMin\": -272,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Nushu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -321,\n      \"tAsc\": 1069,\n      \"tDes\": -321,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 321,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -321,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ogham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 695,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ol Chiki\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Hungarian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -177,\n      \"tAsc\": 859,\n      \"tDes\": -177,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 600,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 859,\n      \"hDes\": -177,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Italic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old North Arabian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 665,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Permic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 638,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Persian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 724,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Sogdian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old South Arabian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 859,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Old Turkic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Oriya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 658,\n      \"capH\": 714,\n      \"yMin\": -292,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Osage\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Osmanya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Pahawh Hmong\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 1055,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Palmyrene\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 640,\n      \"capH\": 778,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Pau Cin Hau\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans PhagsPa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 670,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Phoenician\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 719,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Psalter Pahlavi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 737,\n      \"des\": -554,\n      \"tAsc\": 737,\n      \"tDes\": -554,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 554,\n      \"xH\": 469,\n      \"capH\": 625,\n      \"yMin\": -551,\n      \"yMax\": 995,\n      \"hAsc\": 737,\n      \"hDes\": -554,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Rejang\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Runic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Samaritan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 659,\n      \"yMin\": -241,\n      \"yMax\": 1064,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Saurashtra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1021,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sharada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -455,\n      \"tAsc\": 925,\n      \"tDes\": -455,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 455,\n      \"xH\": 536,\n      \"capH\": 625,\n      \"yMin\": -402,\n      \"yMax\": 995,\n      \"hAsc\": 925,\n      \"hDes\": -455,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Shavian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 771,\n      \"yMin\": -245,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Siddham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -1030,\n      \"tAsc\": 1000,\n      \"tDes\": -1030,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 1030,\n      \"xH\": 683,\n      \"capH\": 714,\n      \"yMin\": -1025,\n      \"yMax\": 995,\n      \"hAsc\": 1000,\n      \"hDes\": -1030,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans SignWriting\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 802,\n      \"des\": -200,\n      \"tAsc\": 802,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 241,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 802,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sinhala\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -293,\n      \"tAsc\": 1011,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 612,\n      \"yMin\": -271,\n      \"yMax\": 995,\n      \"hAsc\": 1011,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sogdian\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -313,\n      \"tAsc\": 1069,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 313,\n      \"xH\": 382,\n      \"capH\": 674,\n      \"yMin\": -310,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sora Sompeng\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 433,\n      \"capH\": 800,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Soyombo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1239,\n      \"des\": -357,\n      \"tAsc\": 1239,\n      \"tDes\": -357,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 357,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -354,\n      \"yMax\": 1234,\n      \"hAsc\": 1239,\n      \"hDes\": -357,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sundanese\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -368,\n      \"tAsc\": 1069,\n      \"tDes\": -368,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 385,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -368,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -368,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Sunuwar\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syloti Nagri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 679,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Symbols\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1480,\n      \"des\": -570,\n      \"tAsc\": 1480,\n      \"tDes\": -570,\n      \"tLGap\": 0,\n      \"wAsc\": 1480,\n      \"wDes\": 570,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -565,\n      \"yMax\": 1471,\n      \"hAsc\": 1480,\n      \"hDes\": -570,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Symbols 2\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -630,\n      \"tAsc\": 1069,\n      \"tDes\": -630,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 630,\n      \"xH\": 536,\n      \"capH\": 945,\n      \"yMin\": -422,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -630,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -442,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac Eastern\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -392,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Syriac Western\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -486,\n      \"tAsc\": 926,\n      \"tDes\": -486,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 486,\n      \"xH\": 553,\n      \"capH\": 714,\n      \"yMin\": -405,\n      \"yMax\": 995,\n      \"hAsc\": 926,\n      \"hDes\": -486,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tagalog\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tagbanwa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Le\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Tham\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -520,\n      \"tAsc\": 1069,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 520,\n      \"xH\": 534,\n      \"capH\": 700,\n      \"yMin\": -520,\n      \"yMax\": 1059,\n      \"hAsc\": 1069,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tai Viet\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1055,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Takri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -307,\n      \"tAsc\": 955,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 307,\n      \"xH\": 575,\n      \"capH\": 625,\n      \"yMin\": -304,\n      \"yMax\": 995,\n      \"hAsc\": 955,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tamil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -370,\n      \"tAsc\": 870,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 870,\n      \"wDes\": 370,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -321,\n      \"yMax\": 995,\n      \"hAsc\": 870,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tamil Supplement\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -370,\n      \"tAsc\": 870,\n      \"tDes\": -370,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 451,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -451,\n      \"yMax\": 995,\n      \"hAsc\": 870,\n      \"hDes\": -370,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tangsa\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -1048,\n      \"yMax\": 1808,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Telugu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -483,\n      \"tAsc\": 869,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 620,\n      \"yMin\": -476,\n      \"yMax\": 995,\n      \"hAsc\": 869,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thaana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -424,\n      \"tAsc\": 1069,\n      \"tDes\": -424,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 424,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -300,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -424,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1061,\n      \"des\": -450,\n      \"tAsc\": 1061,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1061,\n      \"wDes\": 450,\n      \"xH\": 556,\n      \"capH\": 714,\n      \"yMin\": -433,\n      \"yMax\": 1009,\n      \"hAsc\": 1061,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Thai Looped\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1250,\n      \"des\": -350,\n      \"tAsc\": 1250,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 490,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -474,\n      \"yMax\": 1108,\n      \"hAsc\": 1250,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tifinagh\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1190,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -250,\n      \"yMax\": 1190,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Tirhuta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1026,\n      \"des\": -519,\n      \"tAsc\": 1026,\n      \"tDes\": -519,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 519,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -516,\n      \"yMax\": 1021,\n      \"hAsc\": 1026,\n      \"hDes\": -519,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Ugaritic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 743,\n      \"des\": -381,\n      \"tAsc\": 743,\n      \"tDes\": -381,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 381,\n      \"xH\": 536,\n      \"capH\": 723,\n      \"yMin\": -381,\n      \"yMax\": 995,\n      \"hAsc\": 743,\n      \"hDes\": -381,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Vai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Vithkuqi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Wancho\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1096,\n      \"des\": -161,\n      \"tAsc\": 1096,\n      \"tDes\": -161,\n      \"tLGap\": 0,\n      \"wAsc\": 1096,\n      \"wDes\": 241,\n      \"xH\": 536,\n      \"capH\": 710,\n      \"yMin\": -241,\n      \"yMax\": 1078,\n      \"hAsc\": 1096,\n      \"hDes\": -161,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Warang Citi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -100,\n      \"tAsc\": 1042,\n      \"tDes\": -100,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 241,\n      \"xH\": 561,\n      \"capH\": 710,\n      \"yMin\": -241,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Yi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -241,\n      \"yMax\": 995,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Sans Zanabazar Square\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1621,\n      \"des\": -821,\n      \"tAsc\": 1621,\n      \"tDes\": -821,\n      \"tLGap\": 0,\n      \"wAsc\": 1621,\n      \"wDes\": 821,\n      \"xH\": 536,\n      \"capH\": 678,\n      \"yMin\": -821,\n      \"yMax\": 1621,\n      \"hAsc\": 1621,\n      \"hDes\": -821,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1048,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ahom\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -675,\n      \"tAsc\": 980,\n      \"tDes\": -675,\n      \"tLGap\": 0,\n      \"wAsc\": 980,\n      \"wDes\": 675,\n      \"xH\": 550,\n      \"capH\": 680,\n      \"yMin\": -672,\n      \"yMax\": 979,\n      \"hAsc\": 980,\n      \"hDes\": -675,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Armenian\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -268,\n      \"yMax\": 979,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Balinese\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -726,\n      \"tAsc\": 1069,\n      \"tDes\": -726,\n      \"tLGap\": 0,\n      \"wAsc\": 1249,\n      \"wDes\": 1005,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1005,\n      \"yMax\": 1249,\n      \"hAsc\": 1069,\n      \"hDes\": -726,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Bengali\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1092,\n      \"des\": -502,\n      \"tAsc\": 1092,\n      \"tDes\": -502,\n      \"tLGap\": 0,\n      \"wAsc\": 1213,\n      \"wDes\": 502,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -408,\n      \"yMax\": 1213,\n      \"hAsc\": 1092,\n      \"hDes\": -502,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Devanagari\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -625,\n      \"tAsc\": 930,\n      \"tDes\": -625,\n      \"tLGap\": 0,\n      \"wAsc\": 1407,\n      \"wDes\": 792,\n      \"xH\": 623,\n      \"capH\": 715,\n      \"yMin\": -524,\n      \"yMax\": 1397,\n      \"hAsc\": 930,\n      \"hDes\": -625,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -389,\n      \"yMax\": 1048,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Dives Akuru\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -710,\n      \"tAsc\": 1069,\n      \"tDes\": -710,\n      \"tLGap\": 0,\n      \"wAsc\": 1551,\n      \"wDes\": 764,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -764,\n      \"yMax\": 1551,\n      \"hAsc\": 1069,\n      \"hDes\": -710,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Dogra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -364,\n      \"tAsc\": 1130,\n      \"tDes\": -364,\n      \"tLGap\": 0,\n      \"wAsc\": 1214,\n      \"wDes\": 445,\n      \"xH\": 554,\n      \"capH\": 625,\n      \"yMin\": -445,\n      \"yMax\": 1214,\n      \"hAsc\": 1130,\n      \"hDes\": -364,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ethiopic\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -240,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Georgian\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1086,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -252,\n      \"yMax\": 1046,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Grantha\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1290,\n      \"des\": -534,\n      \"tAsc\": 1290,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1290,\n      \"wDes\": 1757,\n      \"xH\": 566,\n      \"capH\": 714,\n      \"yMin\": -1757,\n      \"yMax\": 1151,\n      \"hAsc\": 1290,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Gujarati\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -450,\n      \"tAsc\": 997,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1078,\n      \"wDes\": 682,\n      \"xH\": 536,\n      \"capH\": 592,\n      \"yMin\": -588,\n      \"yMax\": 1036,\n      \"hAsc\": 997,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Gurmukhi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -428,\n      \"tAsc\": 1006,\n      \"tDes\": -428,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 428,\n      \"xH\": 536,\n      \"capH\": 622,\n      \"yMin\": -579,\n      \"yMax\": 979,\n      \"hAsc\": 1006,\n      \"hDes\": -428,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Hebrew\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 896,\n      \"des\": -290,\n      \"tAsc\": 896,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 290,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 896,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Hentaigana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 1151,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 880,\n      \"capH\": 880,\n      \"yMin\": -286,\n      \"yMax\": 1151,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif HK\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif JP\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Kannada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 910,\n      \"des\": -710,\n      \"tAsc\": 910,\n      \"tDes\": -710,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 710,\n      \"xH\": 547,\n      \"capH\": 690,\n      \"yMin\": -710,\n      \"yMax\": 979,\n      \"hAsc\": 910,\n      \"hDes\": -710,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khitan Small Script\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 2300,\n      \"des\": -1700,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 2300,\n      \"wDes\": 1700,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -1681,\n      \"yMax\": 2277,\n      \"hAsc\": 2300,\n      \"hDes\": -1700,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khmer\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 839,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -839,\n      \"yMax\": 1255,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Khojki\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1409,\n      \"des\": -447,\n      \"tAsc\": 1409,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1613,\n      \"wDes\": 447,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -384,\n      \"yMax\": 1117,\n      \"hAsc\": 1409,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif KR\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Lao\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1174,\n      \"des\": -482,\n      \"tAsc\": 1174,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1174,\n      \"wDes\": 482,\n      \"xH\": 550,\n      \"capH\": 714,\n      \"yMin\": -447,\n      \"yMax\": 1162,\n      \"hAsc\": 1174,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Makasar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Malayalam\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 864,\n      \"des\": -383,\n      \"tAsc\": 864,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 864,\n      \"wDes\": 383,\n      \"xH\": 554,\n      \"capH\": 714,\n      \"yMin\": -383,\n      \"yMax\": 979,\n      \"hAsc\": 864,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Myanmar\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1239,\n      \"des\": -1260,\n      \"tAsc\": 1239,\n      \"tDes\": -1260,\n      \"tLGap\": 0,\n      \"wAsc\": 1239,\n      \"wDes\": 1260,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -1210,\n      \"yMax\": 1212,\n      \"hAsc\": 1239,\n      \"hDes\": -1260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif NP Hmong\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 292,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -240,\n      \"yMax\": 1039,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Old Uyghur\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -313,\n      \"tAsc\": 1069,\n      \"tDes\": -313,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 504,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -504,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -313,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Oriya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -492,\n      \"tAsc\": 917,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 917,\n      \"wDes\": 492,\n      \"xH\": 657,\n      \"capH\": 657,\n      \"yMin\": -492,\n      \"yMax\": 979,\n      \"hAsc\": 917,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Ottoman Siyaq\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -634,\n      \"tAsc\": 1069,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 634,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -634,\n      \"yMax\": 1069,\n      \"hAsc\": 1069,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Sinhala\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -307,\n      \"tAsc\": 997,\n      \"tDes\": -307,\n      \"tLGap\": 0,\n      \"wAsc\": 997,\n      \"wDes\": 307,\n      \"xH\": 536,\n      \"capH\": 612,\n      \"yMin\": -290,\n      \"yMax\": 979,\n      \"hAsc\": 997,\n      \"hDes\": -307,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tamil\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -492,\n      \"tAsc\": 1069,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 492,\n      \"xH\": 554,\n      \"capH\": 829,\n      \"yMin\": -547,\n      \"yMax\": 1107,\n      \"hAsc\": 1069,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tangut\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -150,\n      \"tAsc\": 856,\n      \"tDes\": -150,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 150,\n      \"xH\": 502,\n      \"capH\": 712,\n      \"yMin\": -240,\n      \"yMax\": 979,\n      \"hAsc\": 856,\n      \"hDes\": -150,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif TC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1151,\n      \"des\": -286,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1151,\n      \"wDes\": 286,\n      \"xH\": 514,\n      \"capH\": 729,\n      \"yMin\": -1049,\n      \"yMax\": 1809,\n      \"hAsc\": 1151,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Telugu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 869,\n      \"des\": -483,\n      \"tAsc\": 869,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 620,\n      \"yMin\": -477,\n      \"yMax\": 979,\n      \"hAsc\": 869,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Thai\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1064,\n      \"des\": -534,\n      \"tAsc\": 1064,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1064,\n      \"wDes\": 534,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -472,\n      \"yMax\": 1056,\n      \"hAsc\": 1064,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Tibetan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1466,\n      \"des\": -1349,\n      \"tAsc\": 1466,\n      \"tDes\": -1349,\n      \"tLGap\": 0,\n      \"wAsc\": 1466,\n      \"wDes\": 1349,\n      \"xH\": 678,\n      \"capH\": 714,\n      \"yMin\": -995,\n      \"yMax\": 1401,\n      \"hAsc\": 1466,\n      \"hDes\": -1349,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Todhri\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 389,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -270,\n      \"yMax\": 979,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Toto\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -378,\n      \"tAsc\": 925,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 378,\n      \"xH\": 622,\n      \"capH\": 720,\n      \"yMin\": -375,\n      \"yMax\": 979,\n      \"hAsc\": 925,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Vithkuqi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1069,\n      \"des\": -293,\n      \"tAsc\": 1069,\n      \"tDes\": -293,\n      \"tLGap\": 0,\n      \"wAsc\": 1069,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -256,\n      \"yMax\": 1018,\n      \"hAsc\": 1069,\n      \"hDes\": -293,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Serif Yezidi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -292,\n      \"tAsc\": 1068,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 293,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -293,\n      \"yMax\": 979,\n      \"hAsc\": 1068,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Traditional Nushu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1055,\n      \"des\": -117,\n      \"tAsc\": 860,\n      \"tDes\": -117,\n      \"tLGap\": 90,\n      \"wAsc\": 1055,\n      \"wDes\": 118,\n      \"xH\": 543,\n      \"capH\": 733,\n      \"yMin\": -241,\n      \"yMax\": 1000,\n      \"hAsc\": 1055,\n      \"hDes\": -117,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Noto Znamenny Musical Notation\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -292,\n      \"tAsc\": 995,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 292,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -292,\n      \"yMax\": 995,\n      \"hAsc\": 995,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Cut\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1140,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Flat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2215,\n      \"des\": -639,\n      \"tAsc\": 2215,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 2215,\n      \"wDes\": 639,\n      \"xH\": 1120,\n      \"capH\": 1509,\n      \"yMin\": -567,\n      \"yMax\": 2215,\n      \"hAsc\": 2215,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Oval\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Round\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1550,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Slim\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1120,\n      \"capH\": 1530,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nova Square\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1966,\n      \"des\": -506,\n      \"tAsc\": 1966,\n      \"tDes\": -506,\n      \"tLGap\": 0,\n      \"wAsc\": 1966,\n      \"wDes\": 506,\n      \"xH\": 1100,\n      \"capH\": 1510,\n      \"yMin\": -450,\n      \"yMax\": 1966,\n      \"hAsc\": 1966,\n      \"hDes\": -506,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"NTR\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1294,\n      \"des\": -877,\n      \"tAsc\": 1294,\n      \"tDes\": -877,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 877,\n      \"xH\": 422,\n      \"capH\": 572,\n      \"yMin\": -877,\n      \"yMax\": 1294,\n      \"hAsc\": 1294,\n      \"hDes\": -877,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Numans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -553,\n      \"tAsc\": 1853,\n      \"tDes\": -553,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 553,\n      \"xH\": 1096,\n      \"capH\": 1434,\n      \"yMin\": -553,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -553,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nunito\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -353,\n      \"tAsc\": 1011,\n      \"tDes\": -353,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 300,\n      \"xH\": 484,\n      \"capH\": 705,\n      \"yMin\": -277,\n      \"yMax\": 1047,\n      \"hAsc\": 1011,\n      \"hDes\": -353,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nunito Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -353,\n      \"tAsc\": 1011,\n      \"tDes\": -353,\n      \"tLGap\": 0,\n      \"wAsc\": 1102,\n      \"wDes\": 327,\n      \"xH\": 486,\n      \"capH\": 705,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1011,\n      \"hDes\": -353,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Nuosu SIL\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2200,\n      \"des\": -500,\n      \"tAsc\": 2200,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2200,\n      \"wDes\": 500,\n      \"xH\": 1000,\n      \"capH\": 1800,\n      \"yMin\": -462,\n      \"yMax\": 2150,\n      \"hAsc\": 2200,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Odibee Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -250,\n      \"tAsc\": 858,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 858,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 858,\n      \"hAsc\": 858,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Odor Mean Chey\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1210,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1210,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Offside\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 996,\n      \"des\": -265,\n      \"tAsc\": 996,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1044,\n      \"wDes\": 265,\n      \"xH\": 605,\n      \"capH\": 740,\n      \"yMin\": -265,\n      \"yMax\": 1044,\n      \"hAsc\": 996,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -510,\n      \"tAsc\": 1070,\n      \"tDes\": -510,\n      \"tLGap\": 0,\n      \"wAsc\": 1141,\n      \"wDes\": 510,\n      \"xH\": 696,\n      \"capH\": 760,\n      \"yMin\": -507,\n      \"yMax\": 1141,\n      \"hAsc\": 1070,\n      \"hDes\": -510,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ojuju\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1130,\n      \"des\": -276,\n      \"tAsc\": 1130,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1130,\n      \"wDes\": 276,\n      \"xH\": 483,\n      \"capH\": 700,\n      \"yMin\": -270,\n      \"yMax\": 1035,\n      \"hAsc\": 1130,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Old Standard TT\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 762,\n      \"des\": -238,\n      \"tAsc\": 762,\n      \"tDes\": -238,\n      \"tLGap\": 236,\n      \"wAsc\": 948,\n      \"wDes\": 282,\n      \"xH\": 456,\n      \"capH\": 712,\n      \"yMin\": -294,\n      \"yMax\": 1100,\n      \"hAsc\": 762,\n      \"hDes\": -238,\n      \"lGap\": 236\n    }\n  },\n  {\n    \"family\": \"Oldenburg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 482,\n      \"capH\": 1555,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 9\n    }\n  },\n  {\n    \"family\": \"Ole\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -380,\n      \"tAsc\": 880,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 880,\n      \"wDes\": 446,\n      \"xH\": 270,\n      \"capH\": 510,\n      \"yMin\": -446,\n      \"yMax\": 829,\n      \"hAsc\": 880,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oleo Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -379,\n      \"tAsc\": 1004,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 379,\n      \"xH\": 443,\n      \"capH\": 710,\n      \"yMin\": -279,\n      \"yMax\": 938,\n      \"hAsc\": 1004,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oleo Script Swash Caps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -379,\n      \"tAsc\": 1004,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 379,\n      \"xH\": 443,\n      \"capH\": 747,\n      \"yMin\": -369,\n      \"yMax\": 938,\n      \"hAsc\": 1004,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Onest\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -305,\n      \"tAsc\": 970,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1212,\n      \"wDes\": 334,\n      \"xH\": 527,\n      \"capH\": 707,\n      \"yMin\": -304,\n      \"yMax\": 960,\n      \"hAsc\": 970,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oooh Baby\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -325,\n      \"tAsc\": 900,\n      \"tDes\": -325,\n      \"tLGap\": 0,\n      \"wAsc\": 1007,\n      \"wDes\": 351,\n      \"xH\": 365,\n      \"capH\": 695,\n      \"yMin\": -351,\n      \"yMax\": 1007,\n      \"hAsc\": 900,\n      \"hDes\": -325,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Open Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2189,\n      \"des\": -600,\n      \"tAsc\": 2189,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2302,\n      \"wDes\": 651,\n      \"xH\": 1096,\n      \"capH\": 1462,\n      \"yMin\": -557,\n      \"yMax\": 2146,\n      \"hAsc\": 2189,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oranienbaum\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 895,\n      \"des\": -260,\n      \"tAsc\": 895,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 895,\n      \"wDes\": 260,\n      \"xH\": 475,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 895,\n      \"hAsc\": 895,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orbit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 710,\n      \"yMin\": -278,\n      \"yMax\": 1003,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orbitron\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1011,\n      \"des\": -243,\n      \"tAsc\": 1011,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 243,\n      \"xH\": 580,\n      \"capH\": 720,\n      \"yMin\": -250,\n      \"yMax\": 974,\n      \"hAsc\": 1011,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oregano\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1975,\n      \"des\": -669,\n      \"tAsc\": 1975,\n      \"tDes\": -669,\n      \"tLGap\": 0,\n      \"wAsc\": 1975,\n      \"wDes\": 669,\n      \"xH\": 864,\n      \"capH\": 1460,\n      \"yMin\": -669,\n      \"yMax\": 1975,\n      \"hAsc\": 1975,\n      \"hDes\": -669,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Orelega One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 4096,\n      \"asc\": 3296,\n      \"des\": -801,\n      \"tAsc\": 3296,\n      \"tDes\": -801,\n      \"tLGap\": 369,\n      \"wAsc\": 3480,\n      \"wDes\": 801,\n      \"xH\": 1840,\n      \"capH\": 2480,\n      \"yMin\": -801,\n      \"yMax\": 3480,\n      \"hAsc\": 3296,\n      \"hDes\": -801,\n      \"lGap\": 369\n    }\n  },\n  {\n    \"family\": \"Orienta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -235,\n      \"tAsc\": 960,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 301,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -301,\n      \"yMax\": 1030,\n      \"hAsc\": 960,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Original Surfer\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2036,\n      \"des\": -526,\n      \"tAsc\": 2036,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2036,\n      \"wDes\": 526,\n      \"xH\": 987,\n      \"capH\": 1497,\n      \"yMin\": -526,\n      \"yMax\": 2036,\n      \"hAsc\": 2036,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oswald\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1193,\n      \"des\": -289,\n      \"tAsc\": 1193,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1325,\n      \"wDes\": 377,\n      \"xH\": 578,\n      \"capH\": 810,\n      \"yMin\": -287,\n      \"yMax\": 1297,\n      \"hAsc\": 1193,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Outfit\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -260,\n      \"tAsc\": 1000,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 260,\n      \"xH\": 475,\n      \"capH\": 694,\n      \"yMin\": -338,\n      \"yMax\": 988,\n      \"hAsc\": 1000,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Over the Rainbow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1412,\n      \"des\": -677,\n      \"tAsc\": 1412,\n      \"tDes\": -677,\n      \"tLGap\": 0,\n      \"wAsc\": 1412,\n      \"wDes\": 677,\n      \"xH\": 636,\n      \"capH\": 812,\n      \"yMin\": -677,\n      \"yMax\": 1410,\n      \"hAsc\": 1412,\n      \"hDes\": -677,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overlock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -254,\n      \"tAsc\": 966,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 254,\n      \"xH\": 125,\n      \"capH\": 154,\n      \"yMin\": -253,\n      \"yMax\": 899,\n      \"hAsc\": 966,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overlock SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 966,\n      \"des\": -254,\n      \"tAsc\": 966,\n      \"tDes\": -254,\n      \"tLGap\": 0,\n      \"wAsc\": 966,\n      \"wDes\": 254,\n      \"xH\": 159,\n      \"capH\": 154,\n      \"yMin\": -253,\n      \"yMax\": 899,\n      \"hAsc\": 966,\n      \"hDes\": -254,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overpass\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1766,\n      \"des\": -766,\n      \"tAsc\": 1766,\n      \"tDes\": -766,\n      \"tLGap\": 0,\n      \"wAsc\": 2316,\n      \"wDes\": 756,\n      \"xH\": 1022,\n      \"capH\": 1400,\n      \"yMin\": -756,\n      \"yMax\": 2298,\n      \"hAsc\": 1766,\n      \"hDes\": -766,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Overpass Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1766,\n      \"des\": -766,\n      \"tAsc\": 1766,\n      \"tDes\": -766,\n      \"tLGap\": 0,\n      \"wAsc\": 2316,\n      \"wDes\": 756,\n      \"xH\": 1022,\n      \"capH\": 1400,\n      \"yMin\": -756,\n      \"yMax\": 2316,\n      \"hAsc\": 1766,\n      \"hDes\": -766,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ovo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1770,\n      \"des\": -534,\n      \"tAsc\": 1770,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1770,\n      \"wDes\": 534,\n      \"xH\": 356,\n      \"capH\": 210,\n      \"yMin\": -534,\n      \"yMax\": 1770,\n      \"hAsc\": 1770,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oxanium\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 250,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 515,\n      \"capH\": 690,\n      \"yMin\": -208,\n      \"yMax\": 969,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Oxygen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2103,\n      \"des\": -483,\n      \"tAsc\": 2103,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 2103,\n      \"wDes\": 483,\n      \"yMin\": -672,\n      \"yMax\": 2131,\n      \"hAsc\": 2103,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Oxygen Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -672,\n      \"tAsc\": 2015,\n      \"tDes\": -672,\n      \"tLGap\": 0,\n      \"wAsc\": 2015,\n      \"wDes\": 672,\n      \"xH\": 1097,\n      \"capH\": 1491,\n      \"yMin\": -678,\n      \"yMax\": 2104,\n      \"hAsc\": 2015,\n      \"hDes\": -672,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pacifico\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1303,\n      \"des\": -453,\n      \"tAsc\": 1303,\n      \"tDes\": -453,\n      \"tLGap\": 0,\n      \"wAsc\": 1478,\n      \"wDes\": 457,\n      \"xH\": 460,\n      \"capH\": 840,\n      \"yMin\": -457,\n      \"yMax\": 1478,\n      \"hAsc\": 1303,\n      \"hDes\": -453,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Padauk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -500,\n      \"tAsc\": 1010,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 500,\n      \"xH\": 459,\n      \"capH\": 903,\n      \"yMin\": -600,\n      \"yMax\": 955,\n      \"hAsc\": 1010,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Padyakke Expanded One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 813,\n      \"des\": -628,\n      \"tAsc\": 813,\n      \"tDes\": -628,\n      \"tLGap\": 0,\n      \"wAsc\": 843,\n      \"wDes\": 628,\n      \"xH\": 357,\n      \"capH\": 520,\n      \"yMin\": -628,\n      \"yMax\": 843,\n      \"hAsc\": 813,\n      \"hDes\": -628,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palanquin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1320,\n      \"des\": -491,\n      \"tAsc\": 770,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1320,\n      \"wDes\": 491,\n      \"xH\": 485,\n      \"capH\": 680,\n      \"yMin\": -432,\n      \"yMax\": 1320,\n      \"hAsc\": 1320,\n      \"hDes\": -491,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palanquin Dark\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1320,\n      \"des\": -491,\n      \"tAsc\": 770,\n      \"tDes\": -230,\n      \"tLGap\": 0,\n      \"wAsc\": 1320,\n      \"wDes\": 491,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -491,\n      \"yMax\": 1320,\n      \"hAsc\": 1320,\n      \"hDes\": -491,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Palatino\",\n    \"fallbacks\": [\n      \"Palatino Linotype\",\n      \"Palatino LT STD\",\n      \"Book Antiqua\",\n      \"Georgia\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1491,\n      \"des\": -600,\n      \"tAsc\": 1491,\n      \"tDes\": -580,\n      \"tLGap\": 0,\n      \"wAsc\": 2322,\n      \"wDes\": 2322,\n      \"yMin\": -580,\n      \"yMax\": 2322,\n      \"hAsc\": 1491,\n      \"hDes\": -600,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Palette Mosaic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 465,\n      \"capH\": 790,\n      \"yMin\": -251,\n      \"yMax\": 876,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pangolin\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1259,\n      \"wDes\": 255,\n      \"xH\": 555,\n      \"capH\": 720,\n      \"yMin\": -256,\n      \"yMax\": 1259,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Paprika\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1145,\n      \"des\": -274,\n      \"tAsc\": 1145,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1225,\n      \"wDes\": 326,\n      \"xH\": 689,\n      \"capH\": 889,\n      \"yMin\": -326,\n      \"yMax\": 1225,\n      \"hAsc\": 1145,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Papyrus\",\n    \"fallbacks\": [\"fantasy\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1925,\n      \"des\": -1235,\n      \"tAsc\": 1913,\n      \"tDes\": -780,\n      \"tLGap\": -502,\n      \"wAsc\": 1925,\n      \"wDes\": 1925,\n      \"xH\": 910,\n      \"capH\": 1351,\n      \"yMin\": -1235,\n      \"yMax\": 1935,\n      \"hAsc\": 1925,\n      \"hDes\": -1235,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Parastoo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2727,\n      \"asc\": 2635,\n      \"des\": -1200,\n      \"tAsc\": 2635,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2782,\n      \"wDes\": 1200,\n      \"xH\": 1082,\n      \"capH\": 1638,\n      \"yMin\": -1012,\n      \"yMax\": 2782,\n      \"hAsc\": 2635,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Parisienne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1875,\n      \"des\": -915,\n      \"tAsc\": 1875,\n      \"tDes\": -915,\n      \"tLGap\": 0,\n      \"wAsc\": 1875,\n      \"wDes\": 915,\n      \"xH\": 723,\n      \"capH\": 1558,\n      \"yMin\": -915,\n      \"yMax\": 1875,\n      \"hAsc\": 1875,\n      \"hDes\": -915,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Parkinsans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 350,\n      \"xH\": 549,\n      \"capH\": 693,\n      \"yMin\": -275,\n      \"yMax\": 975,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passero One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1820,\n      \"des\": -618,\n      \"tAsc\": 1820,\n      \"tDes\": -618,\n      \"tLGap\": 0,\n      \"wAsc\": 1820,\n      \"wDes\": 618,\n      \"xH\": 983,\n      \"capH\": 1323,\n      \"yMin\": -618,\n      \"yMax\": 1820,\n      \"hAsc\": 1820,\n      \"hDes\": -618,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passion One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 835,\n      \"des\": -266,\n      \"tAsc\": 835,\n      \"tDes\": -266,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 266,\n      \"xH\": 479,\n      \"capH\": 621,\n      \"yMin\": -198,\n      \"yMax\": 835,\n      \"hAsc\": 835,\n      \"hDes\": -266,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Passions Conflict\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -350,\n      \"tAsc\": 750,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 771,\n      \"wDes\": 350,\n      \"xH\": 170,\n      \"capH\": 475,\n      \"yMin\": -346,\n      \"yMax\": 769,\n      \"hAsc\": 750,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pathway Extreme\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -286,\n      \"tAsc\": 1070,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 286,\n      \"xH\": 540,\n      \"capH\": 700,\n      \"yMin\": -233,\n      \"yMax\": 1159,\n      \"hAsc\": 1070,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pathway Gothic One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 954,\n      \"des\": -198,\n      \"tAsc\": 954,\n      \"tDes\": -198,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 222,\n      \"xH\": 540,\n      \"capH\": 700,\n      \"yMin\": -222,\n      \"yMax\": 1004,\n      \"hAsc\": 954,\n      \"hDes\": -198,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patrick Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -312,\n      \"tAsc\": 1024,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 312,\n      \"xH\": 467,\n      \"capH\": 661,\n      \"yMin\": -312,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patrick Hand SC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1042,\n      \"des\": -312,\n      \"tAsc\": 1024,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 312,\n      \"xH\": 464,\n      \"capH\": 661,\n      \"yMin\": -307,\n      \"yMax\": 1042,\n      \"hAsc\": 1042,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pattaya\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2065,\n      \"des\": -777,\n      \"tAsc\": 2065,\n      \"tDes\": -777,\n      \"tLGap\": 0,\n      \"wAsc\": 2065,\n      \"wDes\": 777,\n      \"xH\": 1024,\n      \"capH\": 1532,\n      \"yMin\": -777,\n      \"yMax\": 2065,\n      \"hAsc\": 2065,\n      \"hDes\": -777,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Patua One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 972,\n      \"des\": -247,\n      \"tAsc\": 972,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 972,\n      \"wDes\": 247,\n      \"xH\": 500,\n      \"capH\": 690,\n      \"yMin\": -247,\n      \"yMax\": 972,\n      \"hAsc\": 972,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pavanam\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -339,\n      \"tAsc\": 693,\n      \"tDes\": -162,\n      \"tLGap\": 59,\n      \"wAsc\": 952,\n      \"wDes\": 339,\n      \"yMin\": -322,\n      \"yMax\": 952,\n      \"hAsc\": 952,\n      \"hDes\": -339,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Paytone One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1113,\n      \"des\": -283,\n      \"tAsc\": 1113,\n      \"tDes\": -283,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 380,\n      \"xH\": 501,\n      \"capH\": 688,\n      \"yMin\": -371,\n      \"yMax\": 1213,\n      \"hAsc\": 1113,\n      \"hDes\": -283,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Peddana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 703,\n      \"des\": -518,\n      \"tAsc\": 703,\n      \"tDes\": -518,\n      \"tLGap\": 0,\n      \"wAsc\": 703,\n      \"wDes\": 518,\n      \"xH\": 241,\n      \"capH\": 329,\n      \"yMin\": -518,\n      \"yMax\": 703,\n      \"hAsc\": 703,\n      \"hDes\": -518,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Peralta\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2004,\n      \"des\": -647,\n      \"tAsc\": 2004,\n      \"tDes\": -647,\n      \"tLGap\": 0,\n      \"wAsc\": 2004,\n      \"wDes\": 647,\n      \"xH\": 1036,\n      \"capH\": 1479,\n      \"yMin\": -647,\n      \"yMax\": 2004,\n      \"hAsc\": 2004,\n      \"hDes\": -647,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Permanent Marker\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1136,\n      \"des\": -325,\n      \"tAsc\": 622,\n      \"tDes\": -61,\n      \"tLGap\": 61,\n      \"wAsc\": 1136,\n      \"wDes\": 325,\n      \"xH\": 625,\n      \"capH\": 758,\n      \"yMin\": -325,\n      \"yMax\": 1136,\n      \"hAsc\": 1136,\n      \"hDes\": -325,\n      \"lGap\": 31\n    }\n  },\n  {\n    \"family\": \"Petemoss\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 774,\n      \"wDes\": 335,\n      \"xH\": 305,\n      \"capH\": 480,\n      \"yMin\": -335,\n      \"yMax\": 774,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Petit Formal Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2033,\n      \"des\": -527,\n      \"tAsc\": 2033,\n      \"tDes\": -527,\n      \"tLGap\": 0,\n      \"wAsc\": 2033,\n      \"wDes\": 527,\n      \"xH\": 1185,\n      \"capH\": 1609,\n      \"yMin\": -527,\n      \"yMax\": 2033,\n      \"hAsc\": 2033,\n      \"hDes\": -527,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Petrona\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 858,\n      \"des\": -270,\n      \"tAsc\": 858,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 342,\n      \"xH\": 443,\n      \"capH\": 641,\n      \"yMin\": -270,\n      \"yMax\": 1076,\n      \"hAsc\": 858,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Phetsarath\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2123,\n      \"des\": -857,\n      \"tAsc\": 2123,\n      \"tDes\": -857,\n      \"tLGap\": 0,\n      \"wAsc\": 2123,\n      \"wDes\": 857,\n      \"yMin\": -857,\n      \"yMax\": 2123,\n      \"hAsc\": 2123,\n      \"hDes\": -857,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Philosopher\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -220,\n      \"tAsc\": 900,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 330,\n      \"xH\": 470,\n      \"capH\": 660,\n      \"yMin\": -325,\n      \"yMax\": 975,\n      \"hAsc\": 900,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Phudu\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1025,\n      \"des\": -200,\n      \"tAsc\": 1025,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 1025,\n      \"hAsc\": 1025,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Piazzolla\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1110,\n      \"des\": -310,\n      \"tAsc\": 1110,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 310,\n      \"xH\": 478,\n      \"capH\": 644,\n      \"yMin\": -232,\n      \"yMax\": 980,\n      \"hAsc\": 1110,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Piedra\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 973,\n      \"des\": -328,\n      \"tAsc\": 973,\n      \"tDes\": -328,\n      \"tLGap\": 0,\n      \"wAsc\": 973,\n      \"wDes\": 328,\n      \"xH\": 437,\n      \"capH\": 655,\n      \"yMin\": -328,\n      \"yMax\": 973,\n      \"hAsc\": 973,\n      \"hDes\": -328,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pinyon Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1768,\n      \"des\": -787,\n      \"tAsc\": 1768,\n      \"tDes\": -787,\n      \"tLGap\": 0,\n      \"wAsc\": 2207,\n      \"wDes\": 963,\n      \"xH\": 760,\n      \"capH\": 1388,\n      \"yMin\": -963,\n      \"yMax\": 2147,\n      \"hAsc\": 1768,\n      \"hDes\": -787,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pirata One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1006,\n      \"des\": -279,\n      \"tAsc\": 1006,\n      \"tDes\": -279,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 279,\n      \"xH\": 594,\n      \"capH\": 793,\n      \"yMin\": -279,\n      \"yMax\": 1006,\n      \"hAsc\": 1006,\n      \"hDes\": -279,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pixelify Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -280,\n      \"tAsc\": 920,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 922,\n      \"wDes\": 289,\n      \"xH\": 450,\n      \"capH\": 700,\n      \"yMin\": -248,\n      \"yMax\": 919,\n      \"hAsc\": 920,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Plaster\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -560,\n      \"tAsc\": 2000,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 2000,\n      \"wDes\": 560,\n      \"xH\": 1020,\n      \"capH\": 1361,\n      \"yMin\": -560,\n      \"yMax\": 2000,\n      \"hAsc\": 2000,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Platypi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1125,\n      \"des\": -251,\n      \"tAsc\": 1125,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1125,\n      \"wDes\": 342,\n      \"xH\": 484,\n      \"capH\": 690,\n      \"yMin\": -301,\n      \"yMax\": 1042,\n      \"hAsc\": 1125,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Play\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -220,\n      \"tAsc\": 937,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1052,\n      \"wDes\": 224,\n      \"xH\": 484,\n      \"capH\": 649,\n      \"yMin\": -220,\n      \"yMax\": 1035,\n      \"hAsc\": 937,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playball\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 400,\n      \"xH\": 403,\n      \"capH\": 706,\n      \"yMin\": -359,\n      \"yMax\": 1031,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1240,\n      \"asc\": 1098,\n      \"des\": -390,\n      \"tAsc\": 1098,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 271,\n      \"xH\": 513,\n      \"capH\": 708,\n      \"yMin\": -262,\n      \"yMax\": 1110,\n      \"hAsc\": 1098,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair Display\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1082,\n      \"des\": -251,\n      \"tAsc\": 1082,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1159,\n      \"wDes\": 251,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -241,\n      \"yMax\": 1159,\n      \"hAsc\": 1082,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playfair Display SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1082,\n      \"des\": -251,\n      \"tAsc\": 1082,\n      \"tDes\": -251,\n      \"tLGap\": 0,\n      \"wAsc\": 1201,\n      \"wDes\": 251,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -241,\n      \"yMax\": 1156,\n      \"hAsc\": 1082,\n      \"hDes\": -251,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1170,\n      \"des\": -340,\n      \"tAsc\": 1170,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 502,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -486,\n      \"yMax\": 1238,\n      \"hAsc\": 1170,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Arabic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -550,\n      \"tAsc\": 1100,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1224,\n      \"wDes\": 604,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -539,\n      \"yMax\": 1224,\n      \"hAsc\": 1100,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Deva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -750,\n      \"tAsc\": 1280,\n      \"tDes\": -750,\n      \"tLGap\": 0,\n      \"wAsc\": 1382,\n      \"wDes\": 1040,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -708,\n      \"yMax\": 1270,\n      \"hAsc\": 1280,\n      \"hDes\": -750,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Hebrew\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -460,\n      \"tAsc\": 1070,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1294,\n      \"wDes\": 432,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -392,\n      \"yMax\": 1224,\n      \"hAsc\": 1070,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playpen Sans Thai\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1363,\n      \"des\": -380,\n      \"tAsc\": 1363,\n      \"tDes\": -380,\n      \"tLGap\": 0,\n      \"wAsc\": 1363,\n      \"wDes\": 432,\n      \"xH\": 537,\n      \"capH\": 764,\n      \"yMin\": -392,\n      \"yMax\": 1278,\n      \"hAsc\": 1363,\n      \"hDes\": -380,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1508,\n      \"des\": -571,\n      \"tAsc\": 1508,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 588,\n      \"xH\": 500,\n      \"capH\": 1065,\n      \"yMin\": -584,\n      \"yMax\": 1541,\n      \"hAsc\": 1508,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1508,\n      \"des\": -571,\n      \"tAsc\": 1508,\n      \"tDes\": -571,\n      \"tLGap\": 0,\n      \"wAsc\": 1558,\n      \"wDes\": 588,\n      \"xH\": 500,\n      \"capH\": 1065,\n      \"yMin\": -584,\n      \"yMax\": 1521,\n      \"hAsc\": 1508,\n      \"hDes\": -571,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AT\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU NSW\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU NSW Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU QLD\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU QLD Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU SA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1413,\n      \"des\": -492,\n      \"tAsc\": 1413,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1473,\n      \"wDes\": 512,\n      \"xH\": 500,\n      \"capH\": 988,\n      \"yMin\": -507,\n      \"yMax\": 1461,\n      \"hAsc\": 1413,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU SA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1413,\n      \"des\": -492,\n      \"tAsc\": 1413,\n      \"tDes\": -492,\n      \"tLGap\": 0,\n      \"wAsc\": 1473,\n      \"wDes\": 512,\n      \"xH\": 500,\n      \"capH\": 988,\n      \"yMin\": -507,\n      \"yMax\": 1430,\n      \"hAsc\": 1413,\n      \"hDes\": -492,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU TAS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU TAS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU VIC\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite AU VIC Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE VLG\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE VLG Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE WAL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1924,\n      \"des\": -922,\n      \"tAsc\": 1924,\n      \"tDes\": -922,\n      \"tLGap\": 0,\n      \"wAsc\": 1935,\n      \"wDes\": 926,\n      \"xH\": 500,\n      \"capH\": 1405,\n      \"yMin\": -925,\n      \"yMax\": 1889,\n      \"hAsc\": 1924,\n      \"hDes\": -922,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BE WAL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1924,\n      \"des\": -922,\n      \"tAsc\": 1924,\n      \"tDes\": -922,\n      \"tLGap\": 0,\n      \"wAsc\": 1935,\n      \"wDes\": 926,\n      \"xH\": 500,\n      \"capH\": 1405,\n      \"yMin\": -925,\n      \"yMax\": 1873,\n      \"hAsc\": 1924,\n      \"hDes\": -922,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1588,\n      \"des\": -639,\n      \"tAsc\": 1588,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 1631,\n      \"wDes\": 654,\n      \"xH\": 500,\n      \"capH\": 1131,\n      \"yMin\": -650,\n      \"yMax\": 1608,\n      \"hAsc\": 1588,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite BR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1588,\n      \"des\": -639,\n      \"tAsc\": 1588,\n      \"tDes\": -639,\n      \"tLGap\": 0,\n      \"wAsc\": 1631,\n      \"wDes\": 654,\n      \"xH\": 500,\n      \"capH\": 1131,\n      \"yMin\": -650,\n      \"yMax\": 1589,\n      \"hAsc\": 1588,\n      \"hDes\": -639,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1423,\n      \"des\": -500,\n      \"tAsc\": 1423,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1482,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 996,\n      \"yMin\": -515,\n      \"yMax\": 1469,\n      \"hAsc\": 1423,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1423,\n      \"des\": -500,\n      \"tAsc\": 1423,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 1482,\n      \"wDes\": 520,\n      \"xH\": 500,\n      \"capH\": 996,\n      \"yMin\": -515,\n      \"yMax\": 1437,\n      \"hAsc\": 1423,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1591,\n      \"des\": -641,\n      \"tAsc\": 1591,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 1634,\n      \"wDes\": 656,\n      \"xH\": 500,\n      \"capH\": 1133,\n      \"yMin\": -652,\n      \"yMax\": 1610,\n      \"hAsc\": 1591,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1591,\n      \"des\": -641,\n      \"tAsc\": 1591,\n      \"tDes\": -641,\n      \"tLGap\": 0,\n      \"wAsc\": 1634,\n      \"wDes\": 656,\n      \"xH\": 500,\n      \"capH\": 1133,\n      \"yMin\": -652,\n      \"yMax\": 1591,\n      \"hAsc\": 1591,\n      \"hDes\": -641,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1452,\n      \"des\": -525,\n      \"tAsc\": 1452,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1509,\n      \"wDes\": 544,\n      \"xH\": 500,\n      \"capH\": 1020,\n      \"yMin\": -540,\n      \"yMax\": 1493,\n      \"hAsc\": 1452,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1452,\n      \"des\": -525,\n      \"tAsc\": 1452,\n      \"tDes\": -525,\n      \"tLGap\": 0,\n      \"wAsc\": 1509,\n      \"wDes\": 544,\n      \"xH\": 500,\n      \"capH\": 1020,\n      \"yMin\": -539,\n      \"yMax\": 1461,\n      \"hAsc\": 1452,\n      \"hDes\": -525,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CU\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1569,\n      \"des\": -623,\n      \"tAsc\": 1569,\n      \"tDes\": -623,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 638,\n      \"xH\": 500,\n      \"capH\": 1115,\n      \"yMin\": -635,\n      \"yMax\": 1588,\n      \"hAsc\": 1569,\n      \"hDes\": -623,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CU Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1569,\n      \"des\": -623,\n      \"tAsc\": 1569,\n      \"tDes\": -623,\n      \"tLGap\": 0,\n      \"wAsc\": 1614,\n      \"wDes\": 638,\n      \"xH\": 500,\n      \"capH\": 1115,\n      \"yMin\": -634,\n      \"yMax\": 1562,\n      \"hAsc\": 1569,\n      \"hDes\": -623,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -505,\n      \"yMax\": 1458,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite CZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -504,\n      \"yMax\": 1425,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE Grund\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1393,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE Grund Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1371,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE LA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1393,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE LA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1330,\n      \"des\": -421,\n      \"tAsc\": 1330,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 1398,\n      \"wDes\": 445,\n      \"xH\": 500,\n      \"capH\": 920,\n      \"yMin\": -439,\n      \"yMax\": 1357,\n      \"hAsc\": 1330,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE SAS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1291,\n      \"des\": -388,\n      \"tAsc\": 1291,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 413,\n      \"xH\": 500,\n      \"capH\": 888,\n      \"yMin\": -407,\n      \"yMax\": 1361,\n      \"hAsc\": 1291,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE SAS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1291,\n      \"des\": -388,\n      \"tAsc\": 1291,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 413,\n      \"xH\": 500,\n      \"capH\": 888,\n      \"yMin\": -407,\n      \"yMax\": 1326,\n      \"hAsc\": 1291,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE VA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1402,\n      \"des\": -482,\n      \"tAsc\": 1402,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1463,\n      \"wDes\": 503,\n      \"xH\": 500,\n      \"capH\": 979,\n      \"yMin\": -498,\n      \"yMax\": 1452,\n      \"hAsc\": 1402,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DE VA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1402,\n      \"des\": -482,\n      \"tAsc\": 1402,\n      \"tDes\": -482,\n      \"tLGap\": 0,\n      \"wAsc\": 1463,\n      \"wDes\": 503,\n      \"xH\": 500,\n      \"capH\": 979,\n      \"yMin\": -498,\n      \"yMax\": 1425,\n      \"hAsc\": 1402,\n      \"hDes\": -482,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Loopet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Loopet Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Uloopet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite DK Uloopet Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Deco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Deco Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ES Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Moderne\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1550,\n      \"des\": -607,\n      \"tAsc\": 1550,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1597,\n      \"wDes\": 623,\n      \"xH\": 500,\n      \"capH\": 1100,\n      \"yMin\": -619,\n      \"yMax\": 1577,\n      \"hAsc\": 1550,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Moderne Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1550,\n      \"des\": -607,\n      \"tAsc\": 1550,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1597,\n      \"wDes\": 623,\n      \"xH\": 500,\n      \"capH\": 1100,\n      \"yMin\": -619,\n      \"yMax\": 1557,\n      \"hAsc\": 1550,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1927,\n      \"des\": -925,\n      \"tAsc\": 1927,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 929,\n      \"xH\": 500,\n      \"capH\": 1408,\n      \"yMin\": -928,\n      \"yMax\": 1892,\n      \"hAsc\": 1927,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite FR Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1927,\n      \"des\": -925,\n      \"tAsc\": 1927,\n      \"tDes\": -925,\n      \"tLGap\": 0,\n      \"wAsc\": 1938,\n      \"wDes\": 929,\n      \"xH\": 500,\n      \"capH\": 1408,\n      \"yMin\": -928,\n      \"yMax\": 1876,\n      \"hAsc\": 1927,\n      \"hDes\": -925,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB J\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB J Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB S\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite GB S Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -399,\n      \"yMax\": 1352,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1315,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Lijeva\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1351,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HR Lijeva Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1280,\n      \"des\": -379,\n      \"tAsc\": 1280,\n      \"tDes\": -379,\n      \"tLGap\": 0,\n      \"wAsc\": 1352,\n      \"wDes\": 404,\n      \"xH\": 500,\n      \"capH\": 879,\n      \"yMin\": -398,\n      \"yMax\": 1328,\n      \"hAsc\": 1280,\n      \"hDes\": -379,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HU\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1362,\n      \"des\": -448,\n      \"tAsc\": 1362,\n      \"tDes\": -448,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 470,\n      \"xH\": 500,\n      \"capH\": 946,\n      \"yMin\": -465,\n      \"yMax\": 1419,\n      \"hAsc\": 1362,\n      \"hDes\": -448,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite HU Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1362,\n      \"des\": -448,\n      \"tAsc\": 1362,\n      \"tDes\": -448,\n      \"tLGap\": 0,\n      \"wAsc\": 1427,\n      \"wDes\": 470,\n      \"xH\": 500,\n      \"capH\": 946,\n      \"yMin\": -465,\n      \"yMax\": 1398,\n      \"hAsc\": 1362,\n      \"hDes\": -448,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ID\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1964,\n      \"des\": -956,\n      \"tAsc\": 1964,\n      \"tDes\": -956,\n      \"tLGap\": 0,\n      \"wAsc\": 1971,\n      \"wDes\": 959,\n      \"xH\": 500,\n      \"capH\": 1438,\n      \"yMin\": -958,\n      \"yMax\": 1924,\n      \"hAsc\": 1964,\n      \"hDes\": -956,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ID Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1964,\n      \"des\": -956,\n      \"tAsc\": 1964,\n      \"tDes\": -956,\n      \"tLGap\": 0,\n      \"wAsc\": 1971,\n      \"wDes\": 959,\n      \"xH\": 500,\n      \"capH\": 1438,\n      \"yMin\": -958,\n      \"yMax\": 1907,\n      \"hAsc\": 1964,\n      \"hDes\": -956,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IE\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1405,\n      \"des\": -484,\n      \"tAsc\": 1405,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1465,\n      \"wDes\": 505,\n      \"xH\": 500,\n      \"capH\": 981,\n      \"yMin\": -501,\n      \"yMax\": 1454,\n      \"hAsc\": 1405,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IE Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1405,\n      \"des\": -484,\n      \"tAsc\": 1405,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1465,\n      \"wDes\": 505,\n      \"xH\": 500,\n      \"capH\": 981,\n      \"yMin\": -500,\n      \"yMax\": 1421,\n      \"hAsc\": 1405,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IN\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1456,\n      \"des\": -528,\n      \"tAsc\": 1456,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 1512,\n      \"wDes\": 547,\n      \"xH\": 500,\n      \"capH\": 1023,\n      \"yMin\": -542,\n      \"yMax\": 1496,\n      \"hAsc\": 1456,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IN Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1456,\n      \"des\": -528,\n      \"tAsc\": 1456,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 1512,\n      \"wDes\": 547,\n      \"xH\": 500,\n      \"capH\": 1023,\n      \"yMin\": -542,\n      \"yMax\": 1465,\n      \"hAsc\": 1456,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IS\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IS Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1313,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Moderna\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1347,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Moderna Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -394,\n      \"yMax\": 1324,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1378,\n      \"des\": -462,\n      \"tAsc\": 1378,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1441,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 959,\n      \"yMin\": -478,\n      \"yMax\": 1433,\n      \"hAsc\": 1378,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite IT Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1378,\n      \"des\": -462,\n      \"tAsc\": 1378,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1441,\n      \"wDes\": 483,\n      \"xH\": 500,\n      \"capH\": 959,\n      \"yMin\": -478,\n      \"yMax\": 1411,\n      \"hAsc\": 1378,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite MX\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite MX Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NG Modern\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NG Modern Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1762,\n      \"des\": -786,\n      \"tAsc\": 1762,\n      \"tDes\": -786,\n      \"tLGap\": 0,\n      \"wAsc\": 1789,\n      \"wDes\": 795,\n      \"xH\": 500,\n      \"capH\": 1273,\n      \"yMin\": -793,\n      \"yMax\": 1751,\n      \"hAsc\": 1762,\n      \"hDes\": -786,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1762,\n      \"des\": -786,\n      \"tAsc\": 1762,\n      \"tDes\": -786,\n      \"tLGap\": 0,\n      \"wAsc\": 1789,\n      \"wDes\": 795,\n      \"xH\": 500,\n      \"capH\": 1273,\n      \"yMin\": -793,\n      \"yMax\": 1728,\n      \"hAsc\": 1762,\n      \"hDes\": -786,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1391,\n      \"des\": -473,\n      \"tAsc\": 1391,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 1453,\n      \"wDes\": 494,\n      \"xH\": 500,\n      \"capH\": 970,\n      \"yMin\": -490,\n      \"yMax\": 1443,\n      \"hAsc\": 1391,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1391,\n      \"des\": -473,\n      \"tAsc\": 1391,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 1453,\n      \"wDes\": 494,\n      \"xH\": 500,\n      \"capH\": 970,\n      \"yMin\": -489,\n      \"yMax\": 1409,\n      \"hAsc\": 1391,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Basic\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1348,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Basic Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1317,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite NZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1275,\n      \"des\": -375,\n      \"tAsc\": 1275,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1348,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 875,\n      \"yMin\": -395,\n      \"yMax\": 1310,\n      \"hAsc\": 1275,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PE\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1475,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PE Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1454,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PL\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1411,\n      \"des\": -490,\n      \"tAsc\": 1411,\n      \"tDes\": -490,\n      \"tLGap\": 0,\n      \"wAsc\": 1471,\n      \"wDes\": 510,\n      \"xH\": 500,\n      \"capH\": 986,\n      \"yMin\": -505,\n      \"yMax\": 1460,\n      \"hAsc\": 1411,\n      \"hDes\": -490,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PL Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1411,\n      \"des\": -490,\n      \"tAsc\": 1411,\n      \"tDes\": -490,\n      \"tLGap\": 0,\n      \"wAsc\": 1471,\n      \"wDes\": 510,\n      \"xH\": 500,\n      \"capH\": 986,\n      \"yMin\": -505,\n      \"yMax\": 1439,\n      \"hAsc\": 1411,\n      \"hDes\": -490,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PT\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1527,\n      \"des\": -588,\n      \"tAsc\": 1527,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1576,\n      \"wDes\": 604,\n      \"xH\": 500,\n      \"capH\": 1081,\n      \"yMin\": -600,\n      \"yMax\": 1557,\n      \"hAsc\": 1527,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite PT Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1527,\n      \"des\": -588,\n      \"tAsc\": 1527,\n      \"tDes\": -588,\n      \"tLGap\": 0,\n      \"wAsc\": 1576,\n      \"wDes\": 604,\n      \"xH\": 500,\n      \"capH\": 1081,\n      \"yMin\": -600,\n      \"yMax\": 1537,\n      \"hAsc\": 1527,\n      \"hDes\": -588,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite RO\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite RO Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite SK\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -505,\n      \"yMax\": 1458,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite SK Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1410,\n      \"des\": -489,\n      \"tAsc\": 1410,\n      \"tDes\": -489,\n      \"tLGap\": 0,\n      \"wAsc\": 1470,\n      \"wDes\": 509,\n      \"xH\": 500,\n      \"capH\": 985,\n      \"yMin\": -504,\n      \"yMax\": 1425,\n      \"hAsc\": 1410,\n      \"hDes\": -489,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite TZ\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -520,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite TZ Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1442,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Modern\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1352,\n      \"des\": -440,\n      \"tAsc\": 1352,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 1418,\n      \"wDes\": 463,\n      \"xH\": 500,\n      \"capH\": 938,\n      \"yMin\": -457,\n      \"yMax\": 1411,\n      \"hAsc\": 1352,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Modern Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1352,\n      \"des\": -440,\n      \"tAsc\": 1352,\n      \"tDes\": -440,\n      \"tLGap\": 0,\n      \"wAsc\": 1418,\n      \"wDes\": 463,\n      \"xH\": 500,\n      \"capH\": 938,\n      \"yMin\": -457,\n      \"yMax\": 1390,\n      \"hAsc\": 1352,\n      \"hDes\": -440,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Trad\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1473,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite US Trad Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1441,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite VN\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1743,\n      \"des\": -769,\n      \"tAsc\": 1743,\n      \"tDes\": -769,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 779,\n      \"xH\": 500,\n      \"capH\": 1257,\n      \"yMin\": -777,\n      \"yMax\": 1737,\n      \"hAsc\": 1743,\n      \"hDes\": -769,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite VN Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1743,\n      \"des\": -769,\n      \"tAsc\": 1743,\n      \"tDes\": -769,\n      \"tLGap\": 0,\n      \"wAsc\": 1771,\n      \"wDes\": 779,\n      \"xH\": 500,\n      \"capH\": 1257,\n      \"yMin\": -777,\n      \"yMax\": 1720,\n      \"hAsc\": 1743,\n      \"hDes\": -769,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ZA\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1474,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Playwrite ZA Guides\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1428,\n      \"des\": -504,\n      \"tAsc\": 1428,\n      \"tDes\": -504,\n      \"tLGap\": 0,\n      \"wAsc\": 1486,\n      \"wDes\": 524,\n      \"xH\": 500,\n      \"capH\": 1000,\n      \"yMin\": -519,\n      \"yMax\": 1446,\n      \"hAsc\": 1428,\n      \"hDes\": -504,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Plus Jakarta Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1038,\n      \"des\": -222,\n      \"tAsc\": 1038,\n      \"tDes\": -222,\n      \"tLGap\": 0,\n      \"wAsc\": 1296,\n      \"wDes\": 356,\n      \"xH\": 536,\n      \"capH\": 745,\n      \"yMin\": -240,\n      \"yMax\": 1189,\n      \"hAsc\": 1038,\n      \"hDes\": -222,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pochaevsk\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1051,\n      \"des\": -400,\n      \"tAsc\": 1051,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1051,\n      \"wDes\": 433,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -433,\n      \"yMax\": 1051,\n      \"hAsc\": 1051,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Podkova\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 859,\n      \"des\": -249,\n      \"tAsc\": 859,\n      \"tDes\": -249,\n      \"tLGap\": 0,\n      \"wAsc\": 1091,\n      \"wDes\": 343,\n      \"xH\": 429,\n      \"capH\": 589,\n      \"yMin\": -301,\n      \"yMax\": 969,\n      \"hAsc\": 859,\n      \"hDes\": -249,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poetsen One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 200,\n      \"xH\": 550,\n      \"capH\": 710,\n      \"yMin\": -200,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poiret One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 962,\n      \"des\": -208,\n      \"tAsc\": 962,\n      \"tDes\": -208,\n      \"tLGap\": 0,\n      \"wAsc\": 962,\n      \"wDes\": 208,\n      \"xH\": 450,\n      \"capH\": 750,\n      \"yMin\": -208,\n      \"yMax\": 962,\n      \"hAsc\": 962,\n      \"hDes\": -208,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poller One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -514,\n      \"tAsc\": 1920,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 514,\n      \"xH\": 991,\n      \"capH\": 1486,\n      \"yMin\": -514,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -514,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poltawski Nowy\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 400,\n      \"xH\": 440,\n      \"capH\": 700,\n      \"yMin\": -362,\n      \"yMax\": 1098,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poly\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -224,\n      \"tAsc\": 964,\n      \"tDes\": -224,\n      \"tLGap\": 0,\n      \"wAsc\": 964,\n      \"wDes\": 224,\n      \"xH\": 473,\n      \"capH\": 693,\n      \"yMin\": -223,\n      \"yMax\": 919,\n      \"hAsc\": 964,\n      \"hDes\": -224,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pompiere\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1918,\n      \"des\": -543,\n      \"tAsc\": 1919,\n      \"tDes\": -543,\n      \"tLGap\": 0,\n      \"wAsc\": 1918,\n      \"wDes\": 543,\n      \"xH\": 616,\n      \"capH\": 1315,\n      \"yMin\": -543,\n      \"yMax\": 1918,\n      \"hAsc\": 1918,\n      \"hDes\": -543,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ponnala\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -861,\n      \"tAsc\": 938,\n      \"tDes\": -861,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 861,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -861,\n      \"yMax\": 938,\n      \"hAsc\": 938,\n      \"hDes\": -861,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ponomar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1150,\n      \"des\": -460,\n      \"tAsc\": 1150,\n      \"tDes\": -460,\n      \"tLGap\": 0,\n      \"wAsc\": 1430,\n      \"wDes\": 460,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -460,\n      \"yMax\": 1080,\n      \"hAsc\": 1150,\n      \"hDes\": -460,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pontano Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2025,\n      \"des\": -599,\n      \"tAsc\": 2025,\n      \"tDes\": -599,\n      \"tLGap\": 0,\n      \"wAsc\": 2190,\n      \"wDes\": 599,\n      \"xH\": 1023,\n      \"capH\": 1464,\n      \"yMin\": -599,\n      \"yMax\": 2120,\n      \"hAsc\": 2025,\n      \"hDes\": -599,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Poor Story\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 819,\n      \"des\": -205,\n      \"tAsc\": 819,\n      \"tDes\": -205,\n      \"tLGap\": 256,\n      \"wAsc\": 819,\n      \"wDes\": 205,\n      \"xH\": 389,\n      \"capH\": 641,\n      \"yMin\": -205,\n      \"yMax\": 819,\n      \"hAsc\": 819,\n      \"hDes\": -205,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Poppins\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 100,\n      \"wAsc\": 1135,\n      \"wDes\": 627,\n      \"xH\": 548,\n      \"capH\": 698,\n      \"yMin\": -572,\n      \"yMax\": 1065,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 100\n    }\n  },\n  {\n    \"family\": \"Port Lligat Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -211,\n      \"tAsc\": 860,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 211,\n      \"xH\": 178,\n      \"capH\": 125,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Port Lligat Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -211,\n      \"tAsc\": 860,\n      \"tDes\": -211,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 211,\n      \"xH\": 155,\n      \"capH\": 99,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -211,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Potta One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 565,\n      \"capH\": 780,\n      \"yMin\": -290,\n      \"yMax\": 1160,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pragati Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1158,\n      \"des\": -534,\n      \"tAsc\": 1158,\n      \"tDes\": -534,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 534,\n      \"xH\": 484,\n      \"capH\": 630,\n      \"yMin\": -534,\n      \"yMax\": 1158,\n      \"hAsc\": 1158,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Praise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -350,\n      \"tAsc\": 850,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1023,\n      \"wDes\": 544,\n      \"xH\": 425,\n      \"capH\": 600,\n      \"yMin\": -544,\n      \"yMax\": 1023,\n      \"hAsc\": 850,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prata\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 993,\n      \"des\": -362,\n      \"tAsc\": 993,\n      \"tDes\": -362,\n      \"tLGap\": 0,\n      \"wAsc\": 1201,\n      \"wDes\": 362,\n      \"xH\": 518,\n      \"capH\": 800,\n      \"yMin\": -362,\n      \"yMax\": 1201,\n      \"hAsc\": 993,\n      \"hDes\": -362,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Preahvihear\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Press Start 2P\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": 0,\n      \"tAsc\": 1000,\n      \"tDes\": 0,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 374,\n      \"xH\": 750,\n      \"capH\": 1000,\n      \"yMin\": -374,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": 0,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Pridi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -450,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1100,\n      \"wDes\": 450,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -411,\n      \"yMax\": 1049,\n      \"hAsc\": 1100,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Princess Sofia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1010,\n      \"des\": -574,\n      \"tAsc\": 1010,\n      \"tDes\": -574,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 588,\n      \"xH\": 670,\n      \"capH\": 858,\n      \"yMin\": -574,\n      \"yMax\": 1010,\n      \"hAsc\": 1010,\n      \"hDes\": -574,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prociono\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -212,\n      \"tAsc\": 1008,\n      \"tDes\": -212,\n      \"tLGap\": 0,\n      \"wAsc\": 1008,\n      \"wDes\": 212,\n      \"xH\": 203,\n      \"capH\": 738,\n      \"yMin\": -212,\n      \"yMax\": 1008,\n      \"hAsc\": 1008,\n      \"hDes\": -212,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prompt\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -422,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1090,\n      \"wDes\": 422,\n      \"xH\": 536,\n      \"capH\": 714,\n      \"yMin\": -368,\n      \"yMax\": 1061,\n      \"hAsc\": 1090,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Prosto One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -295,\n      \"tAsc\": 940,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 295,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -295,\n      \"yMax\": 940,\n      \"hAsc\": 940,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Guerrilla\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 204,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -204,\n      \"yMax\": 1140,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Revolution\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1254,\n      \"wDes\": 303,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -303,\n      \"yMax\": 1254,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Riot\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1206,\n      \"wDes\": 251,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -251,\n      \"yMax\": 1206,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Protest Strike\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -240,\n      \"tAsc\": 960,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1140,\n      \"wDes\": 204,\n      \"xH\": 575,\n      \"capH\": 720,\n      \"yMin\": -204,\n      \"yMax\": 1140,\n      \"hAsc\": 960,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Proza Libre\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1996,\n      \"des\": -800,\n      \"tAsc\": 1996,\n      \"tDes\": -800,\n      \"tLGap\": 0,\n      \"wAsc\": 1996,\n      \"wDes\": 800,\n      \"xH\": 1060,\n      \"capH\": 1465,\n      \"yMin\": -558,\n      \"yMax\": 1962,\n      \"hAsc\": 1996,\n      \"hDes\": -800,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -235,\n      \"tAsc\": 885,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 235,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 915,\n      \"hAsc\": 885,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 993,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans Caption\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -251,\n      \"yMax\": 999,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Sans Narrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -276,\n      \"tAsc\": 1018,\n      \"tDes\": -276,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 276,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -245,\n      \"yMax\": 993,\n      \"hAsc\": 1018,\n      \"hDes\": -276,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -286,\n      \"tAsc\": 1039,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 286,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -272,\n      \"yMax\": 1003,\n      \"hAsc\": 1039,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"PT Serif Caption\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1039,\n      \"des\": -286,\n      \"tAsc\": 1039,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1039,\n      \"wDes\": 286,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -280,\n      \"yMax\": 1002,\n      \"hAsc\": 1039,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Public Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -450,\n      \"tAsc\": 1900,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 2315,\n      \"wDes\": 495,\n      \"xH\": 1034,\n      \"capH\": 1446,\n      \"yMin\": -480,\n      \"yMax\": 2125,\n      \"hAsc\": 1900,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Puppies Play\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 810,\n      \"wDes\": 280,\n      \"xH\": 260,\n      \"capH\": 530,\n      \"yMin\": -278,\n      \"yMax\": 809,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Puritan\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 881,\n      \"des\": -256,\n      \"tAsc\": 881,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 881,\n      \"wDes\": 238,\n      \"xH\": 507,\n      \"capH\": 655,\n      \"yMin\": -238,\n      \"yMax\": 881,\n      \"hAsc\": 881,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Purple Purse\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1870,\n      \"des\": -690,\n      \"tAsc\": 1870,\n      \"tDes\": -690,\n      \"tLGap\": 0,\n      \"wAsc\": 1870,\n      \"wDes\": 690,\n      \"xH\": 856,\n      \"capH\": 1419,\n      \"yMin\": -690,\n      \"yMax\": 1869,\n      \"hAsc\": 1870,\n      \"hDes\": -690,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qahiri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 600,\n      \"des\": -250,\n      \"tAsc\": 600,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 600,\n      \"wDes\": 250,\n      \"xH\": 230,\n      \"capH\": 560,\n      \"yMin\": -250,\n      \"yMax\": 560,\n      \"hAsc\": 600,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quando\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 1200,\n      \"capH\": 1533,\n      \"yMin\": -514,\n      \"yMax\": 2029,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quantico\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1063,\n      \"des\": -367,\n      \"tAsc\": 1063,\n      \"tDes\": -367,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 367,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -335,\n      \"yMax\": 1033,\n      \"hAsc\": 1063,\n      \"hDes\": -367,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quattrocento\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -260,\n      \"tAsc\": 848,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 848,\n      \"wDes\": 260,\n      \"xH\": 459,\n      \"capH\": 660,\n      \"yMin\": -260,\n      \"yMax\": 849,\n      \"hAsc\": 848,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quattrocento Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -260,\n      \"tAsc\": 848,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 848,\n      \"wDes\": 260,\n      \"xH\": 460,\n      \"capH\": 660,\n      \"yMin\": -260,\n      \"yMax\": 848,\n      \"hAsc\": 848,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Questrial\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 820,\n      \"des\": -210,\n      \"tAsc\": 820,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 440,\n      \"xH\": 500,\n      \"capH\": 662,\n      \"yMin\": -439,\n      \"yMax\": 1028,\n      \"hAsc\": 820,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quicksand\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1183,\n      \"wDes\": 303,\n      \"xH\": 503,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 1133,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Quintessential\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2341,\n      \"des\": -799,\n      \"tAsc\": 2341,\n      \"tDes\": -799,\n      \"tLGap\": 0,\n      \"wAsc\": 2341,\n      \"wDes\": 799,\n      \"xH\": 1057,\n      \"capH\": 1489,\n      \"yMin\": -799,\n      \"yMax\": 2340,\n      \"hAsc\": 2341,\n      \"hDes\": -799,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qwigley\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -500,\n      \"tAsc\": 750,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 805,\n      \"wDes\": 500,\n      \"xH\": 300,\n      \"capH\": 460,\n      \"yMin\": -470,\n      \"yMax\": 780,\n      \"hAsc\": 750,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Qwitcher Grypen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 802,\n      \"wDes\": 350,\n      \"xH\": 220,\n      \"capH\": 500,\n      \"yMin\": -332,\n      \"yMax\": 786,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Racing Sans One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 976,\n      \"des\": -284,\n      \"tAsc\": 976,\n      \"tDes\": -284,\n      \"tLGap\": 0,\n      \"wAsc\": 976,\n      \"wDes\": 284,\n      \"xH\": 430,\n      \"capH\": 635,\n      \"yMin\": -284,\n      \"yMax\": 976,\n      \"hAsc\": 976,\n      \"hDes\": -284,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radio Canada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -255,\n      \"tAsc\": 945,\n      \"tDes\": -255,\n      \"tLGap\": 0,\n      \"wAsc\": 1193,\n      \"wDes\": 448,\n      \"xH\": 515,\n      \"capH\": 690,\n      \"yMin\": -288,\n      \"yMax\": 1152,\n      \"hAsc\": 945,\n      \"hDes\": -255,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radio Canada Big\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -305,\n      \"tAsc\": 995,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 275,\n      \"xH\": 530,\n      \"capH\": 690,\n      \"yMin\": -275,\n      \"yMax\": 1035,\n      \"hAsc\": 995,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Radley\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1973,\n      \"des\": -615,\n      \"tAsc\": 1973,\n      \"tDes\": -615,\n      \"tLGap\": 0,\n      \"wAsc\": 1980,\n      \"wDes\": 615,\n      \"xH\": 899,\n      \"capH\": 1302,\n      \"yMin\": -615,\n      \"yMax\": 1980,\n      \"hAsc\": 1973,\n      \"hDes\": -615,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rajdhani\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -346,\n      \"tAsc\": 930,\n      \"tDes\": -346,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 346,\n      \"xH\": 510,\n      \"capH\": 643,\n      \"yMin\": -314,\n      \"yMax\": 888,\n      \"hAsc\": 930,\n      \"hDes\": -346,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rakkas\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -445,\n      \"tAsc\": 1046,\n      \"tDes\": -445,\n      \"tLGap\": 0,\n      \"wAsc\": 1046,\n      \"wDes\": 445,\n      \"xH\": 450,\n      \"capH\": 670,\n      \"yMin\": -445,\n      \"yMax\": 1046,\n      \"hAsc\": 1046,\n      \"hDes\": -445,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Raleway\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -234,\n      \"tAsc\": 940,\n      \"tDes\": -234,\n      \"tLGap\": 0,\n      \"wAsc\": 1154,\n      \"wDes\": 234,\n      \"xH\": 519,\n      \"capH\": 710,\n      \"yMin\": -224,\n      \"yMax\": 1141,\n      \"hAsc\": 940,\n      \"hDes\": -234,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Raleway Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -213,\n      \"tAsc\": 918,\n      \"tDes\": -213,\n      \"tLGap\": 0,\n      \"wAsc\": 918,\n      \"wDes\": 213,\n      \"xH\": 520,\n      \"capH\": 710,\n      \"yMin\": -218,\n      \"yMax\": 940,\n      \"hAsc\": 918,\n      \"hDes\": -213,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramabhadra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 830,\n      \"asc\": 1101,\n      \"des\": -474,\n      \"tAsc\": 1101,\n      \"tDes\": -474,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 474,\n      \"xH\": 439,\n      \"capH\": 571,\n      \"yMin\": -474,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -474,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramaraja\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 741,\n      \"des\": -544,\n      \"tAsc\": 741,\n      \"tDes\": -544,\n      \"tLGap\": 0,\n      \"wAsc\": 741,\n      \"wDes\": 544,\n      \"xH\": 293,\n      \"capH\": 439,\n      \"yMin\": -544,\n      \"yMax\": 741,\n      \"hAsc\": 741,\n      \"hDes\": -544,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rambla\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 929,\n      \"des\": -295,\n      \"tAsc\": 929,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 929,\n      \"wDes\": 295,\n      \"xH\": 506,\n      \"capH\": 668,\n      \"yMin\": -255,\n      \"yMax\": 929,\n      \"hAsc\": 929,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rammetto One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2437,\n      \"des\": -1022,\n      \"tAsc\": 2437,\n      \"tDes\": -1022,\n      \"tLGap\": 0,\n      \"wAsc\": 2453,\n      \"wDes\": 1022,\n      \"xH\": 1243,\n      \"capH\": 1622,\n      \"yMin\": -1022,\n      \"yMax\": 2453,\n      \"hAsc\": 2437,\n      \"hDes\": -1022,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rampart One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 555,\n      \"capH\": 764,\n      \"yMin\": -276,\n      \"yMax\": 1076,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ramsina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1560,\n      \"des\": -689,\n      \"tAsc\": 1560,\n      \"tDes\": -689,\n      \"tLGap\": 0,\n      \"wAsc\": 1560,\n      \"wDes\": 689,\n      \"xH\": 612,\n      \"capH\": 864,\n      \"yMin\": -688,\n      \"yMax\": 1425,\n      \"hAsc\": 1560,\n      \"hDes\": -689,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ranchers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -205,\n      \"tAsc\": 1045,\n      \"tDes\": -205,\n      \"tLGap\": 0,\n      \"wAsc\": 1045,\n      \"wDes\": 205,\n      \"xH\": 598,\n      \"capH\": 818,\n      \"yMin\": -205,\n      \"yMax\": 1045,\n      \"hAsc\": 1045,\n      \"hDes\": -205,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rancho\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 919,\n      \"des\": -329,\n      \"tAsc\": 681,\n      \"tDes\": -259,\n      \"tLGap\": 48,\n      \"wAsc\": 919,\n      \"wDes\": 329,\n      \"xH\": 407,\n      \"capH\": 705,\n      \"yMin\": -329,\n      \"yMax\": 919,\n      \"hAsc\": 919,\n      \"hDes\": -329,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Ranga\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2218,\n      \"asc\": 2218,\n      \"des\": -1027,\n      \"tAsc\": 2218,\n      \"tDes\": -1027,\n      \"tLGap\": 0,\n      \"wAsc\": 2218,\n      \"wDes\": 1027,\n      \"xH\": 1040,\n      \"capH\": 1483,\n      \"yMin\": -901,\n      \"yMax\": 2168,\n      \"hAsc\": 2218,\n      \"hDes\": -1027,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rasa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 728,\n      \"des\": -272,\n      \"tAsc\": 728,\n      \"tDes\": -272,\n      \"tLGap\": 218,\n      \"wAsc\": 971,\n      \"wDes\": 422,\n      \"xH\": 413,\n      \"capH\": 568,\n      \"yMin\": -395,\n      \"yMax\": 925,\n      \"hAsc\": 728,\n      \"hDes\": -272,\n      \"lGap\": 218\n    }\n  },\n  {\n    \"family\": \"Rationale\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 903,\n      \"des\": -250,\n      \"tAsc\": 903,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 903,\n      \"wDes\": 250,\n      \"xH\": 508,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 903,\n      \"hAsc\": 903,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ravi Prakash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 938,\n      \"des\": -684,\n      \"tAsc\": 938,\n      \"tDes\": -684,\n      \"tLGap\": 0,\n      \"wAsc\": 938,\n      \"wDes\": 684,\n      \"xH\": 410,\n      \"capH\": 552,\n      \"yMin\": -684,\n      \"yMax\": 938,\n      \"hAsc\": 938,\n      \"hDes\": -684,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Readex Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -250,\n      \"tAsc\": 1000,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 555,\n      \"xH\": 525,\n      \"capH\": 700,\n      \"yMin\": -514,\n      \"yMax\": 1134,\n      \"hAsc\": 1000,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Recursive\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1207,\n      \"wDes\": 271,\n      \"xH\": 532,\n      \"capH\": 700,\n      \"yMin\": -362,\n      \"yMax\": 1121,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 501,\n      \"capH\": 700,\n      \"yMin\": -264,\n      \"yMax\": 1004,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 488,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 1006,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Hat Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1018,\n      \"des\": -305,\n      \"tAsc\": 1018,\n      \"tDes\": -305,\n      \"tLGap\": 0,\n      \"wAsc\": 1018,\n      \"wDes\": 305,\n      \"xH\": 488,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 1006,\n      \"hAsc\": 1018,\n      \"hDes\": -305,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Red Rose\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 690,\n      \"xH\": 468,\n      \"capH\": 600,\n      \"yMin\": -680,\n      \"yMax\": 1086,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redacted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -200,\n      \"yMax\": 800,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redacted Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 200,\n      \"xH\": 439,\n      \"capH\": 702,\n      \"yMin\": -30,\n      \"yMax\": 285,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1060,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1060,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reddit Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2068,\n      \"des\": -592,\n      \"tAsc\": 2068,\n      \"tDes\": -592,\n      \"tLGap\": 0,\n      \"wAsc\": 2600,\n      \"wDes\": 644,\n      \"xH\": 1080,\n      \"capH\": 1474,\n      \"yMin\": -550,\n      \"yMax\": 2356,\n      \"hAsc\": 2068,\n      \"hDes\": -592,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Redressed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1907,\n      \"des\": -494,\n      \"tAsc\": 1907,\n      \"tDes\": -494,\n      \"tLGap\": 0,\n      \"wAsc\": 1907,\n      \"wDes\": 494,\n      \"xH\": 834,\n      \"capH\": 1495,\n      \"yMin\": -494,\n      \"yMax\": 2353,\n      \"hAsc\": 1907,\n      \"hDes\": -494,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi Fun\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reem Kufi Ink\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -400,\n      \"tAsc\": 1100,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1400,\n      \"wDes\": 400,\n      \"xH\": 418,\n      \"capH\": 725,\n      \"yMin\": -400,\n      \"yMax\": 1191,\n      \"hAsc\": 1100,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reenie Beanie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 835,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -314,\n      \"yMax\": 835,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Reggae One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 557,\n      \"capH\": 780,\n      \"yMin\": -229,\n      \"yMax\": 1066,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"REM\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -270,\n      \"tAsc\": 980,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 225,\n      \"xH\": 503,\n      \"capH\": 700,\n      \"yMin\": -217,\n      \"yMax\": 1072,\n      \"hAsc\": 980,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rethink Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 992,\n      \"des\": -310,\n      \"tAsc\": 992,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 992,\n      \"wDes\": 310,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -259,\n      \"yMax\": 967,\n      \"hAsc\": 992,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Revalia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": 382,\n      \"tAsc\": 2146,\n      \"tDes\": 382,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 382,\n      \"xH\": 1140,\n      \"capH\": 879,\n      \"yMin\": -382,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": 382,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rhodium Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -610,\n      \"tAsc\": 1100,\n      \"tDes\": -610,\n      \"tLGap\": 705,\n      \"wAsc\": 1100,\n      \"wDes\": 610,\n      \"xH\": 502,\n      \"capH\": 680,\n      \"yMin\": -532,\n      \"yMax\": 1152,\n      \"hAsc\": 1100,\n      \"hDes\": -610,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ribeye\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2130,\n      \"des\": -668,\n      \"tAsc\": 2130,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 2130,\n      \"wDes\": 668,\n      \"xH\": 1061,\n      \"capH\": 1491,\n      \"yMin\": -668,\n      \"yMax\": 2130,\n      \"hAsc\": 2130,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ribeye Marrow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2130,\n      \"des\": -668,\n      \"tAsc\": 2130,\n      \"tDes\": -668,\n      \"tLGap\": 0,\n      \"wAsc\": 2130,\n      \"wDes\": 668,\n      \"xH\": 1061,\n      \"capH\": 1460,\n      \"yMin\": -668,\n      \"yMax\": 2130,\n      \"hAsc\": 2130,\n      \"hDes\": -668,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Righteous\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2017,\n      \"des\": -526,\n      \"tAsc\": 2017,\n      \"tDes\": -526,\n      \"tLGap\": 0,\n      \"wAsc\": 2017,\n      \"wDes\": 526,\n      \"xH\": 1077,\n      \"capH\": 1434,\n      \"yMin\": -526,\n      \"yMax\": 2017,\n      \"hAsc\": 2017,\n      \"hDes\": -526,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Risque\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -514,\n      \"tAsc\": 1853,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 514,\n      \"xH\": 1016,\n      \"capH\": 1413,\n      \"yMin\": -514,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -514,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Road Rage\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -250,\n      \"tAsc\": 850,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 965,\n      \"wDes\": 253,\n      \"xH\": 450,\n      \"capH\": 600,\n      \"yMin\": -253,\n      \"yMax\": 965,\n      \"hAsc\": 850,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 102,\n      \"wAsc\": 1946,\n      \"wDes\": 512,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2163,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1536,\n      \"tDes\": -512,\n      \"tLGap\": 102,\n      \"wAsc\": 1946,\n      \"wDes\": 512,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2163,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Flex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2461,\n      \"wDes\": 600,\n      \"xH\": 1052,\n      \"capH\": 1456,\n      \"yMin\": -600,\n      \"yMax\": 2461,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -555,\n      \"tAsc\": 2146,\n      \"tDes\": -555,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 555,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": -555,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 927,\n      \"des\": -244,\n      \"tAsc\": 927,\n      \"tDes\": -244,\n      \"tLGap\": 0,\n      \"wAsc\": 1048,\n      \"wDes\": 251,\n      \"xH\": 518,\n      \"capH\": 710,\n      \"yMin\": -325,\n      \"yMax\": 1193,\n      \"hAsc\": 927,\n      \"hDes\": -244,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Roboto Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2146,\n      \"des\": -555,\n      \"tAsc\": 2146,\n      \"tDes\": -555,\n      \"tLGap\": 0,\n      \"wAsc\": 2146,\n      \"wDes\": 618,\n      \"xH\": 1082,\n      \"capH\": 1456,\n      \"yMin\": -555,\n      \"yMax\": 2146,\n      \"hAsc\": 2146,\n      \"hDes\": -555,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rochester\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2109,\n      \"des\": -528,\n      \"tAsc\": 2109,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 2109,\n      \"wDes\": 528,\n      \"xH\": 192,\n      \"capH\": 326,\n      \"yMin\": -528,\n      \"yMax\": 2109,\n      \"hAsc\": 2109,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rock 3D\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 530,\n      \"capH\": 780,\n      \"yMin\": -246,\n      \"yMax\": 956,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rock Salt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1623,\n      \"des\": -788,\n      \"tAsc\": 824,\n      \"tDes\": -240,\n      \"tLGap\": 63,\n      \"wAsc\": 1623,\n      \"wDes\": 788,\n      \"xH\": 833,\n      \"capH\": 1154,\n      \"yMin\": -787,\n      \"yMax\": 1623,\n      \"hAsc\": 1623,\n      \"hDes\": -788,\n      \"lGap\": 32\n    }\n  },\n  {\n    \"family\": \"RocknRoll One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 572,\n      \"capH\": 800,\n      \"yMin\": -212,\n      \"yMax\": 1034,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rokkitt\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 817,\n      \"des\": -320,\n      \"tAsc\": 817,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1111,\n      \"wDes\": 324,\n      \"xH\": 399,\n      \"capH\": 583,\n      \"yMin\": -229,\n      \"yMax\": 937,\n      \"hAsc\": 817,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Romanesco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1866,\n      \"des\": -483,\n      \"tAsc\": 1866,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1866,\n      \"wDes\": 483,\n      \"xH\": 780,\n      \"capH\": 1393,\n      \"yMin\": -483,\n      \"yMax\": 1866,\n      \"hAsc\": 1866,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ropa Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 841,\n      \"des\": -231,\n      \"tAsc\": 841,\n      \"tDes\": -231,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 231,\n      \"xH\": 488,\n      \"capH\": 655,\n      \"yMin\": -231,\n      \"yMax\": 865,\n      \"hAsc\": 841,\n      \"hDes\": -231,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rosario\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 977,\n      \"des\": -235,\n      \"tAsc\": 977,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1167,\n      \"wDes\": 292,\n      \"xH\": 497,\n      \"capH\": 728,\n      \"yMin\": -286,\n      \"yMax\": 1139,\n      \"hAsc\": 977,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rosarivo\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 979,\n      \"des\": -424,\n      \"tAsc\": 979,\n      \"tDes\": -424,\n      \"tLGap\": 0,\n      \"wAsc\": 979,\n      \"wDes\": 424,\n      \"xH\": 170,\n      \"capH\": 757,\n      \"yMin\": -424,\n      \"yMax\": 979,\n      \"hAsc\": 979,\n      \"hDes\": -424,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rouge Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1250,\n      \"asc\": 1050,\n      \"des\": -419,\n      \"tAsc\": 1050,\n      \"tDes\": -419,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 419,\n      \"xH\": 534,\n      \"capH\": 385,\n      \"yMin\": -419,\n      \"yMax\": 1050,\n      \"hAsc\": 1050,\n      \"hDes\": -419,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rowdies\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 997,\n      \"des\": -245,\n      \"tAsc\": 997,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1250,\n      \"wDes\": 700,\n      \"xH\": 473,\n      \"capH\": 708,\n      \"yMin\": -680,\n      \"yMax\": 1228,\n      \"hAsc\": 997,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rozha One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 998,\n      \"des\": -422,\n      \"tAsc\": 998,\n      \"tDes\": -422,\n      \"tLGap\": 0,\n      \"wAsc\": 998,\n      \"wDes\": 422,\n      \"xH\": 460,\n      \"capH\": 560,\n      \"yMin\": -422,\n      \"yMax\": 998,\n      \"hAsc\": 998,\n      \"hDes\": -422,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1066,\n      \"wDes\": 466,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -478,\n      \"yMax\": 1076,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik 80s Fade\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -294,\n      \"yMax\": 942,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Beastly\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -374,\n      \"yMax\": 1040,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Broken Fax\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 308,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 938,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Bubbles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -327,\n      \"yMax\": 971,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Burned\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -341,\n      \"yMax\": 978,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Dirt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -312,\n      \"yMax\": 950,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Distressed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 962,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Doodle Shadow\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 967,\n      \"wDes\": 340,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -340,\n      \"yMax\": 967,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Doodle Triangles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 963,\n      \"wDes\": 324,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -324,\n      \"yMax\": 963,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Gemstones\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -319,\n      \"yMax\": 959,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Glitch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Glitch Pop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 360,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -305,\n      \"yMax\": 946,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Iso\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -315,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Lines\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 307,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -304,\n      \"yMax\": 952,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Maps\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 307,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 946,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Marker Hatch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -308,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Maze\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -313,\n      \"yMax\": 931,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Microbe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -312,\n      \"yMax\": 954,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Mono One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -306,\n      \"tAsc\": 932,\n      \"tDes\": -306,\n      \"tLGap\": 0,\n      \"wAsc\": 932,\n      \"wDes\": 306,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -211,\n      \"yMax\": 860,\n      \"hAsc\": 932,\n      \"hDes\": -306,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Moonrocks\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -307,\n      \"yMax\": 945,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Pixels\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -287,\n      \"yMax\": 955,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Puddles\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -399,\n      \"yMax\": 1067,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Scribble\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 321,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -321,\n      \"yMax\": 959,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Spray Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -331,\n      \"yMax\": 990,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Storm\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -336,\n      \"yMax\": 957,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Vinyl\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -361,\n      \"yMax\": 983,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rubik Wet Paint\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 935,\n      \"des\": -250,\n      \"tAsc\": 935,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 374,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -490,\n      \"yMax\": 947,\n      \"hAsc\": 935,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruda\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 922,\n      \"des\": -295,\n      \"tAsc\": 922,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1030,\n      \"wDes\": 295,\n      \"xH\": 582,\n      \"capH\": 695,\n      \"yMin\": -233,\n      \"yMax\": 1030,\n      \"hAsc\": 922,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rufina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -290,\n      \"tAsc\": 945,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 290,\n      \"xH\": 488,\n      \"capH\": 668,\n      \"yMin\": -290,\n      \"yMax\": 939,\n      \"hAsc\": 945,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruge Boogie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 875,\n      \"des\": -375,\n      \"tAsc\": 875,\n      \"tDes\": -375,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 504,\n      \"xH\": 390,\n      \"capH\": 640,\n      \"yMin\": -504,\n      \"yMax\": 1026,\n      \"hAsc\": 875,\n      \"hDes\": -375,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruluko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 914,\n      \"des\": -241,\n      \"tAsc\": 914,\n      \"tDes\": -241,\n      \"tLGap\": 0,\n      \"wAsc\": 914,\n      \"wDes\": 241,\n      \"xH\": 470,\n      \"capH\": 690,\n      \"yMin\": -241,\n      \"yMax\": 914,\n      \"hAsc\": 914,\n      \"hDes\": -241,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rum Raisin\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2013,\n      \"des\": -629,\n      \"tAsc\": 2013,\n      \"tDes\": -629,\n      \"tLGap\": 0,\n      \"wAsc\": 2013,\n      \"wDes\": 629,\n      \"xH\": 1118,\n      \"capH\": 1466,\n      \"yMin\": -629,\n      \"yMax\": 2013,\n      \"hAsc\": 2013,\n      \"hDes\": -629,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruslan Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 688,\n      \"des\": -397,\n      \"tAsc\": 688,\n      \"tDes\": -397,\n      \"tLGap\": 0,\n      \"wAsc\": 704,\n      \"wDes\": 397,\n      \"xH\": 500,\n      \"capH\": 500,\n      \"yMin\": -397,\n      \"yMax\": 704,\n      \"hAsc\": 688,\n      \"hDes\": -397,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Russo One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 926,\n      \"des\": -279,\n      \"tAsc\": 926,\n      \"tDes\": -279,\n      \"tLGap\": 0,\n      \"wAsc\": 926,\n      \"wDes\": 279,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -279,\n      \"yMax\": 926,\n      \"hAsc\": 926,\n      \"hDes\": -279,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruthie\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -450,\n      \"tAsc\": 800,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 524,\n      \"xH\": 315,\n      \"capH\": 701,\n      \"yMin\": -524,\n      \"yMax\": 938,\n      \"hAsc\": 800,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ruwudu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 867,\n      \"des\": -741,\n      \"tAsc\": 867,\n      \"tDes\": -741,\n      \"tLGap\": 0,\n      \"wAsc\": 1500,\n      \"wDes\": 1200,\n      \"xH\": 430,\n      \"capH\": 660,\n      \"yMin\": -840,\n      \"yMax\": 1223,\n      \"hAsc\": 867,\n      \"hDes\": -741,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Rye\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 387,\n      \"capH\": 363,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sacramento\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1905,\n      \"des\": -1084,\n      \"tAsc\": 1905,\n      \"tDes\": -1084,\n      \"tLGap\": 0,\n      \"wAsc\": 1905,\n      \"wDes\": 1084,\n      \"xH\": 627,\n      \"capH\": 1550,\n      \"yMin\": -1084,\n      \"yMax\": 1905,\n      \"hAsc\": 1905,\n      \"hDes\": -1084,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sahitya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1106,\n      \"des\": -447,\n      \"tAsc\": 1106,\n      \"tDes\": -447,\n      \"tLGap\": 0,\n      \"wAsc\": 1106,\n      \"wDes\": 447,\n      \"xH\": 452,\n      \"capH\": 637,\n      \"yMin\": -412,\n      \"yMax\": 1053,\n      \"hAsc\": 1106,\n      \"hDes\": -447,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sail\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 860,\n      \"des\": -294,\n      \"tAsc\": 860,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 294,\n      \"xH\": 435,\n      \"capH\": 666,\n      \"yMin\": -294,\n      \"yMax\": 860,\n      \"hAsc\": 860,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -398,\n      \"yMax\": 1167,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -351,\n      \"yMax\": 1090,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -348,\n      \"yMax\": 1088,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1135,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -359,\n      \"yMax\": 1095,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 439,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -398,\n      \"yMax\": 1160,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Saira Stencil One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1135,\n      \"des\": -439,\n      \"tAsc\": 1135,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1163,\n      \"wDes\": 360,\n      \"xH\": 510,\n      \"capH\": 688,\n      \"yMin\": -354,\n      \"yMax\": 1163,\n      \"hAsc\": 1135,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Salsa\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 974,\n      \"des\": -252,\n      \"tAsc\": 974,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 974,\n      \"wDes\": 252,\n      \"xH\": 113,\n      \"capH\": 82,\n      \"yMin\": -252,\n      \"yMax\": 974,\n      \"hAsc\": 974,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sanchez\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1004,\n      \"des\": -274,\n      \"tAsc\": 1004,\n      \"tDes\": -274,\n      \"tLGap\": 0,\n      \"wAsc\": 1004,\n      \"wDes\": 274,\n      \"xH\": 492,\n      \"capH\": 718,\n      \"yMin\": -274,\n      \"yMax\": 1004,\n      \"hAsc\": 1004,\n      \"hDes\": -274,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sancreek\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2104,\n      \"des\": -738,\n      \"tAsc\": 2104,\n      \"tDes\": -738,\n      \"tLGap\": 0,\n      \"wAsc\": 2104,\n      \"wDes\": 738,\n      \"xH\": 402,\n      \"capH\": 281,\n      \"yMin\": -738,\n      \"yMax\": 2104,\n      \"hAsc\": 2104,\n      \"hDes\": -738,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sankofa Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1081,\n      \"wDes\": 315,\n      \"xH\": 450,\n      \"capH\": 700,\n      \"yMin\": -267,\n      \"yMax\": 1018,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansation\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1854,\n      \"des\": -438,\n      \"tAsc\": 1854,\n      \"tDes\": -438,\n      \"tLGap\": 0,\n      \"wAsc\": 1854,\n      \"wDes\": 438,\n      \"yMin\": -434,\n      \"yMax\": 1854,\n      \"hAsc\": 1854,\n      \"hDes\": -438,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansita\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -180,\n      \"tAsc\": 1020,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 959,\n      \"wDes\": 284,\n      \"xH\": 510,\n      \"capH\": 660,\n      \"yMin\": -256,\n      \"yMax\": 920,\n      \"hAsc\": 1020,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sansita Swashed\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -180,\n      \"tAsc\": 1020,\n      \"tDes\": -180,\n      \"tLGap\": 0,\n      \"wAsc\": 1134,\n      \"wDes\": 337,\n      \"xH\": 510,\n      \"capH\": 660,\n      \"yMin\": -299,\n      \"yMax\": 1111,\n      \"hAsc\": 1020,\n      \"hDes\": -180,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarabun\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1068,\n      \"des\": -232,\n      \"tAsc\": 1068,\n      \"tDes\": -232,\n      \"tLGap\": 0,\n      \"wAsc\": 1286,\n      \"wDes\": 567,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -535,\n      \"yMax\": 1265,\n      \"hAsc\": 1068,\n      \"hDes\": -232,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarala\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2398,\n      \"des\": -941,\n      \"tAsc\": 2398,\n      \"tDes\": -941,\n      \"tLGap\": 0,\n      \"wAsc\": 2398,\n      \"wDes\": 941,\n      \"xH\": 1053,\n      \"capH\": 1450,\n      \"yMin\": -829,\n      \"yMax\": 2300,\n      \"hAsc\": 2398,\n      \"hDes\": -941,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarina\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1916,\n      \"des\": -644,\n      \"tAsc\": 1916,\n      \"tDes\": -644,\n      \"tLGap\": 0,\n      \"wAsc\": 1916,\n      \"wDes\": 644,\n      \"xH\": 1022,\n      \"capH\": 1530,\n      \"yMin\": -664,\n      \"yMax\": 1916,\n      \"hAsc\": 1916,\n      \"hDes\": -644,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sarpanch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -350,\n      \"tAsc\": 1050,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 350,\n      \"xH\": 485,\n      \"capH\": 622,\n      \"yMin\": -483,\n      \"yMax\": 996,\n      \"hAsc\": 1050,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sassy Frass\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -300,\n      \"tAsc\": 800,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 800,\n      \"wDes\": 300,\n      \"xH\": 220,\n      \"capH\": 550,\n      \"yMin\": -285,\n      \"yMax\": 759,\n      \"hAsc\": 800,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Satisfy\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 957,\n      \"des\": -501,\n      \"tAsc\": 724,\n      \"tDes\": -465,\n      \"tLGap\": 34,\n      \"wAsc\": 957,\n      \"wDes\": 501,\n      \"xH\": 417,\n      \"capH\": 767,\n      \"yMin\": -501,\n      \"yMax\": 957,\n      \"hAsc\": 957,\n      \"hDes\": -501,\n      \"lGap\": 17\n    }\n  },\n  {\n    \"family\": \"Savate\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -285,\n      \"tAsc\": 1015,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 390,\n      \"xH\": 551,\n      \"capH\": 730,\n      \"yMin\": -348,\n      \"yMax\": 1137,\n      \"hAsc\": 1015,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sawarabi Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1110,\n      \"des\": -272,\n      \"tAsc\": 834,\n      \"tDes\": -166,\n      \"tLGap\": 90,\n      \"wAsc\": 1110,\n      \"wDes\": 292,\n      \"xH\": 524,\n      \"capH\": 725,\n      \"yMin\": -282,\n      \"yMax\": 1100,\n      \"hAsc\": 1110,\n      \"hDes\": -272,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Sawarabi Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1070,\n      \"des\": -319,\n      \"tAsc\": 834,\n      \"tDes\": -165,\n      \"tLGap\": 90,\n      \"wAsc\": 1071,\n      \"wDes\": 320,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -320,\n      \"yMax\": 1070,\n      \"hAsc\": 1070,\n      \"hDes\": -319,\n      \"lGap\": 90\n    }\n  },\n  {\n    \"family\": \"Scada\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 955,\n      \"des\": -289,\n      \"tAsc\": 955,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 289,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 930,\n      \"hAsc\": 955,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Scheherazade New\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2750,\n      \"des\": -1427,\n      \"tAsc\": 2750,\n      \"tDes\": -1427,\n      \"tLGap\": 0,\n      \"wAsc\": 2884,\n      \"wDes\": 2100,\n      \"xH\": 684,\n      \"capH\": 1034,\n      \"yMin\": -1509,\n      \"yMax\": 2694,\n      \"hAsc\": 2750,\n      \"hDes\": -1427,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Schibsted Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2000,\n      \"des\": -528,\n      \"tAsc\": 2000,\n      \"tDes\": -528,\n      \"tLGap\": 0,\n      \"wAsc\": 2502,\n      \"wDes\": 568,\n      \"xH\": 1080,\n      \"capH\": 1440,\n      \"yMin\": -485,\n      \"yMax\": 2427,\n      \"hAsc\": 2000,\n      \"hDes\": -528,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Schoolbell\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -383,\n      \"tAsc\": 794,\n      \"tDes\": -326,\n      \"tLGap\": 48,\n      \"wAsc\": 1019,\n      \"wDes\": 383,\n      \"xH\": 485,\n      \"capH\": 770,\n      \"yMin\": -383,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -383,\n      \"lGap\": 24\n    }\n  },\n  {\n    \"family\": \"Science Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 2176,\n      \"des\": -776,\n      \"tAsc\": 2176,\n      \"tDes\": -776,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 708,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -619,\n      \"yMax\": 2173,\n      \"hAsc\": 2176,\n      \"hDes\": -776,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Scope One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 928,\n      \"des\": -455,\n      \"tAsc\": 928,\n      \"tDes\": -455,\n      \"tLGap\": 0,\n      \"wAsc\": 928,\n      \"wDes\": 455,\n      \"xH\": 500,\n      \"capH\": 645,\n      \"yMin\": -455,\n      \"yMax\": 928,\n      \"hAsc\": 928,\n      \"hDes\": -455,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Seaweed Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 969,\n      \"des\": -421,\n      \"tAsc\": 969,\n      \"tDes\": -421,\n      \"tLGap\": 0,\n      \"wAsc\": 969,\n      \"wDes\": 431,\n      \"xH\": 380,\n      \"capH\": 765,\n      \"yMin\": -420,\n      \"yMax\": 969,\n      \"hAsc\": 969,\n      \"hDes\": -421,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Secular One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1022,\n      \"des\": -433,\n      \"tAsc\": 1022,\n      \"tDes\": -433,\n      \"tLGap\": 0,\n      \"wAsc\": 1022,\n      \"wDes\": 433,\n      \"xH\": 515,\n      \"capH\": 666,\n      \"yMin\": -433,\n      \"yMax\": 1022,\n      \"hAsc\": 1022,\n      \"hDes\": -433,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedan\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 407,\n      \"xH\": 438,\n      \"capH\": 675,\n      \"yMin\": -407,\n      \"yMax\": 989,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedan SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 989,\n      \"wDes\": 407,\n      \"xH\": 438,\n      \"capH\": 675,\n      \"yMin\": -407,\n      \"yMax\": 989,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedgwick Ave\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 2555,\n      \"wDes\": 551,\n      \"xH\": 660,\n      \"capH\": 950,\n      \"yMin\": -521,\n      \"yMax\": 1361,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sedgwick Ave Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 937,\n      \"des\": -312,\n      \"tAsc\": 937,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 2555,\n      \"wDes\": 551,\n      \"xH\": 650,\n      \"capH\": 950,\n      \"yMin\": -551,\n      \"yMax\": 2555,\n      \"hAsc\": 937,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sekuya\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 971,\n      \"wDes\": 277,\n      \"xH\": 700,\n      \"capH\": 700,\n      \"yMin\": -274,\n      \"yMax\": 971,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sen\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 962,\n      \"des\": -270,\n      \"tAsc\": 962,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 1169,\n      \"wDes\": 342,\n      \"xH\": 500,\n      \"capH\": 670,\n      \"yMin\": -255,\n      \"yMax\": 940,\n      \"hAsc\": 962,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Send Flowers\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 975,\n      \"des\": -350,\n      \"tAsc\": 975,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1068,\n      \"wDes\": 480,\n      \"xH\": 395,\n      \"capH\": 710,\n      \"yMin\": -473,\n      \"yMax\": 1068,\n      \"hAsc\": 975,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sevillana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2062,\n      \"des\": -717,\n      \"tAsc\": 2062,\n      \"tDes\": -717,\n      \"tLGap\": 0,\n      \"wAsc\": 2062,\n      \"wDes\": 717,\n      \"xH\": 860,\n      \"capH\": 1679,\n      \"yMin\": -717,\n      \"yMax\": 2062,\n      \"hAsc\": 2062,\n      \"hDes\": -717,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Seymour One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2015,\n      \"des\": -559,\n      \"tAsc\": 2015,\n      \"tDes\": -559,\n      \"tLGap\": 0,\n      \"wAsc\": 2202,\n      \"wDes\": 890,\n      \"xH\": 1026,\n      \"capH\": 1465,\n      \"yMin\": -887,\n      \"yMax\": 2182,\n      \"hAsc\": 2015,\n      \"hDes\": -559,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shadows Into Light\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1203,\n      \"des\": -442,\n      \"tAsc\": 1203,\n      \"tDes\": -443,\n      \"tLGap\": 0,\n      \"wAsc\": 1203,\n      \"wDes\": 440,\n      \"xH\": 616,\n      \"capH\": 648,\n      \"yMin\": -434,\n      \"yMax\": 1203,\n      \"hAsc\": 1203,\n      \"hDes\": -442,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shadows Into Light Two\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1145,\n      \"des\": -341,\n      \"tAsc\": 1145,\n      \"tDes\": -341,\n      \"tLGap\": 0,\n      \"wAsc\": 1145,\n      \"wDes\": 341,\n      \"xH\": 610,\n      \"capH\": 848,\n      \"yMin\": -341,\n      \"yMax\": 1145,\n      \"hAsc\": 1145,\n      \"hDes\": -341,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shafarik\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1080,\n      \"des\": -462,\n      \"tAsc\": 1080,\n      \"tDes\": -462,\n      \"tLGap\": 0,\n      \"wAsc\": 1080,\n      \"wDes\": 462,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -462,\n      \"yMax\": 1080,\n      \"hAsc\": 1080,\n      \"hDes\": -462,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shalimar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -420,\n      \"tAsc\": 800,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 994,\n      \"wDes\": 645,\n      \"xH\": 315,\n      \"capH\": 560,\n      \"yMin\": -642,\n      \"yMax\": 994,\n      \"hAsc\": 800,\n      \"hDes\": -420,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shantell Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1020,\n      \"des\": -320,\n      \"tAsc\": 1020,\n      \"tDes\": -320,\n      \"tLGap\": 0,\n      \"wAsc\": 1215,\n      \"wDes\": 515,\n      \"xH\": 491,\n      \"capH\": 700,\n      \"yMin\": -509,\n      \"yMax\": 1134,\n      \"hAsc\": 1020,\n      \"hDes\": -320,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shanti\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2012,\n      \"des\": -599,\n      \"tAsc\": 2012,\n      \"tDes\": -599,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 639,\n      \"xH\": 984,\n      \"capH\": 1412,\n      \"yMin\": -569,\n      \"yMax\": 2026,\n      \"hAsc\": 2012,\n      \"hDes\": -599,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 707,\n      \"yMin\": -240,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share Tech\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Share Tech Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 885,\n      \"des\": -242,\n      \"tAsc\": 885,\n      \"tDes\": -242,\n      \"tLGap\": 0,\n      \"wAsc\": 885,\n      \"wDes\": 242,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -235,\n      \"yMax\": 855,\n      \"hAsc\": 885,\n      \"hDes\": -242,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Antique\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 524,\n      \"capH\": 733,\n      \"yMin\": -336,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Antique B1\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 524,\n      \"capH\": 733,\n      \"yMin\": -336,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 480,\n      \"capH\": 726,\n      \"yMin\": -266,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shippori Mincho B1\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 480,\n      \"capH\": 726,\n      \"yMin\": -266,\n      \"yMax\": 981,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shizuru\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 400,\n      \"capH\": 700,\n      \"yMin\": -288,\n      \"yMax\": 898,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shojumaru\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -692,\n      \"tAsc\": 2020,\n      \"tDes\": -692,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 692,\n      \"xH\": 1206,\n      \"capH\": 1534,\n      \"yMin\": -692,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -692,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Short Stack\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1913,\n      \"des\": -609,\n      \"tAsc\": 1913,\n      \"tDes\": -609,\n      \"tLGap\": 0,\n      \"wAsc\": 1913,\n      \"wDes\": 609,\n      \"xH\": 758,\n      \"capH\": 1367,\n      \"yMin\": -609,\n      \"yMax\": 1913,\n      \"hAsc\": 1913,\n      \"hDes\": -609,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Shrikhand\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1026,\n      \"des\": -432,\n      \"tAsc\": 1026,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 1026,\n      \"wDes\": 432,\n      \"xH\": 520,\n      \"capH\": 669,\n      \"yMin\": -432,\n      \"yMax\": 1026,\n      \"hAsc\": 1026,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Siemreap\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 307,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -1200,\n      \"yMax\": 2502,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 67\n    }\n  },\n  {\n    \"family\": \"Sigmar\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -466,\n      \"tAsc\": 1172,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1275,\n      \"wDes\": 477,\n      \"xH\": 578,\n      \"capH\": 655,\n      \"yMin\": -477,\n      \"yMax\": 1275,\n      \"hAsc\": 1172,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sigmar One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -466,\n      \"tAsc\": 1172,\n      \"tDes\": -466,\n      \"tLGap\": 0,\n      \"wAsc\": 1182,\n      \"wDes\": 466,\n      \"xH\": 578,\n      \"capH\": 676,\n      \"yMin\": -375,\n      \"yMax\": 1182,\n      \"hAsc\": 1172,\n      \"hDes\": -466,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Signika\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1880,\n      \"des\": -584,\n      \"tAsc\": 1880,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2307,\n      \"wDes\": 592,\n      \"xH\": 996,\n      \"capH\": 1366,\n      \"yMin\": -532,\n      \"yMax\": 2175,\n      \"hAsc\": 1880,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Signika Negative\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1880,\n      \"des\": -584,\n      \"tAsc\": 1880,\n      \"tDes\": -584,\n      \"tLGap\": 0,\n      \"wAsc\": 2307,\n      \"wDes\": 592,\n      \"xH\": 980,\n      \"capH\": 1370,\n      \"yMin\": -526,\n      \"yMax\": 2162,\n      \"hAsc\": 1880,\n      \"hDes\": -584,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Silkscreen\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1030,\n      \"des\": -250,\n      \"tAsc\": 1030,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1030,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Simonetta\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1970,\n      \"des\": -594,\n      \"tAsc\": 1970,\n      \"tDes\": -594,\n      \"tLGap\": 0,\n      \"wAsc\": 1970,\n      \"wDes\": 594,\n      \"xH\": 897,\n      \"capH\": 1391,\n      \"yMin\": -545,\n      \"yMax\": 1927,\n      \"hAsc\": 1970,\n      \"hDes\": -594,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Single Day\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 779,\n      \"des\": -245,\n      \"tAsc\": 779,\n      \"tDes\": -245,\n      \"tLGap\": 256,\n      \"wAsc\": 779,\n      \"wDes\": 245,\n      \"xH\": 390,\n      \"capH\": 582,\n      \"yMin\": -241,\n      \"yMax\": 773,\n      \"hAsc\": 779,\n      \"hDes\": -245,\n      \"lGap\": 256\n    }\n  },\n  {\n    \"family\": \"Sintony\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -308,\n      \"tAsc\": 995,\n      \"tDes\": -308,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 308,\n      \"xH\": 572,\n      \"capH\": 730,\n      \"yMin\": -301,\n      \"yMax\": 988,\n      \"hAsc\": 995,\n      \"hDes\": -308,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sirin Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2380,\n      \"des\": -604,\n      \"tAsc\": 2380,\n      \"tDes\": -604,\n      \"tLGap\": 0,\n      \"wAsc\": 2380,\n      \"wDes\": 604,\n      \"xH\": 1055,\n      \"capH\": 1423,\n      \"yMin\": -604,\n      \"yMax\": 2380,\n      \"hAsc\": 2380,\n      \"hDes\": -604,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sirivennela\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1200,\n      \"asc\": 927,\n      \"des\": -513,\n      \"tAsc\": 927,\n      \"tDes\": -513,\n      \"tLGap\": 0,\n      \"wAsc\": 1091,\n      \"wDes\": 982,\n      \"xH\": 419,\n      \"capH\": 661,\n      \"yMin\": -868,\n      \"yMax\": 878,\n      \"hAsc\": 927,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Six Caps\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2263,\n      \"des\": -432,\n      \"tAsc\": 2263,\n      \"tDes\": -432,\n      \"tLGap\": 0,\n      \"wAsc\": 2263,\n      \"wDes\": 432,\n      \"yMin\": -506,\n      \"yMax\": 2281,\n      \"hAsc\": 2263,\n      \"hDes\": -432,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sixtyfour\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sixtyfour Convergence\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Skranji\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1008,\n      \"des\": -383,\n      \"tAsc\": 1008,\n      \"tDes\": -383,\n      \"tLGap\": 0,\n      \"wAsc\": 1008,\n      \"wDes\": 383,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -327,\n      \"yMax\": 1008,\n      \"hAsc\": 1008,\n      \"hDes\": -383,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slabo 13px\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 780,\n      \"asc\": 720,\n      \"des\": -240,\n      \"tAsc\": 720,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 720,\n      \"wDes\": 240,\n      \"xH\": 420,\n      \"capH\": 540,\n      \"yMin\": -180,\n      \"yMax\": 750,\n      \"hAsc\": 720,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slabo 27px\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 810,\n      \"asc\": 750,\n      \"des\": -240,\n      \"tAsc\": 750,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 750,\n      \"wDes\": 240,\n      \"xH\": 390,\n      \"capH\": 540,\n      \"yMin\": -190,\n      \"yMax\": 740,\n      \"hAsc\": 750,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Slackey\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1078,\n      \"des\": -351,\n      \"tAsc\": 769,\n      \"tDes\": -74,\n      \"tLGap\": 55,\n      \"wAsc\": 1078,\n      \"wDes\": 351,\n      \"xH\": 691,\n      \"capH\": 772,\n      \"yMin\": -351,\n      \"yMax\": 1078,\n      \"hAsc\": 1078,\n      \"hDes\": -351,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Slackside One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 255,\n      \"capH\": 513,\n      \"yMin\": -286,\n      \"yMax\": 770,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smokum\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1986,\n      \"des\": -512,\n      \"tAsc\": 1986,\n      \"tDes\": -512,\n      \"tLGap\": 0,\n      \"wAsc\": 1986,\n      \"wDes\": 512,\n      \"xH\": 1024,\n      \"capH\": 1536,\n      \"yMin\": -512,\n      \"yMax\": 1986,\n      \"hAsc\": 1986,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smooch\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -450,\n      \"tAsc\": 950,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1159,\n      \"wDes\": 563,\n      \"xH\": 375,\n      \"capH\": 640,\n      \"yMin\": -563,\n      \"yMax\": 1159,\n      \"hAsc\": 950,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smooch Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1011,\n      \"wDes\": 300,\n      \"xH\": 470,\n      \"capH\": 620,\n      \"yMin\": -257,\n      \"yMax\": 930,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Smythe\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1883,\n      \"des\": -480,\n      \"tAsc\": 1883,\n      \"tDes\": -480,\n      \"tLGap\": 0,\n      \"wAsc\": 1883,\n      \"wDes\": 480,\n      \"xH\": 963,\n      \"capH\": 1317,\n      \"yMin\": -527,\n      \"yMax\": 1883,\n      \"hAsc\": 1883,\n      \"hDes\": -480,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SN Pro\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 985,\n      \"des\": -315,\n      \"tAsc\": 985,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1077,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 670,\n      \"yMin\": -277,\n      \"yMax\": 1049,\n      \"hAsc\": 985,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sniglet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -289,\n      \"tAsc\": 956,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 289,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -260,\n      \"yMax\": 952,\n      \"hAsc\": 956,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Snippet\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -261,\n      \"tAsc\": 890,\n      \"tDes\": -261,\n      \"tLGap\": 0,\n      \"wAsc\": 890,\n      \"wDes\": 261,\n      \"xH\": 498,\n      \"capH\": 684,\n      \"yMin\": -261,\n      \"yMax\": 890,\n      \"hAsc\": 890,\n      \"hDes\": -261,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Snowburst One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2134,\n      \"des\": -454,\n      \"tAsc\": 2134,\n      \"tDes\": -454,\n      \"tLGap\": 0,\n      \"wAsc\": 2134,\n      \"wDes\": 454,\n      \"xH\": 1347,\n      \"capH\": 1635,\n      \"yMin\": -454,\n      \"yMax\": 2134,\n      \"hAsc\": 2134,\n      \"hDes\": -454,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofadi One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 856,\n      \"des\": -310,\n      \"tAsc\": 856,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 856,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 856,\n      \"hAsc\": 856,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1138,\n      \"des\": -438,\n      \"tAsc\": 1138,\n      \"tDes\": -438,\n      \"tLGap\": 0,\n      \"wAsc\": 1138,\n      \"wDes\": 438,\n      \"xH\": 441,\n      \"capH\": 700,\n      \"yMin\": -438,\n      \"yMax\": 1138,\n      \"hAsc\": 1138,\n      \"hDes\": -438,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 488,\n      \"capH\": 655,\n      \"yMin\": -243,\n      \"yMax\": 904,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 655,\n      \"yMin\": -227,\n      \"yMax\": 871,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Extra Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 486,\n      \"capH\": 655,\n      \"yMin\": -225,\n      \"yMax\": 867,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sofia Sans Semi Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -300,\n      \"tAsc\": 900,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1010,\n      \"wDes\": 300,\n      \"xH\": 487,\n      \"capH\": 655,\n      \"yMin\": -231,\n      \"yMax\": 895,\n      \"hAsc\": 900,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Solitreo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -550,\n      \"tAsc\": 880,\n      \"tDes\": -550,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 600,\n      \"xH\": 490,\n      \"capH\": 700,\n      \"yMin\": -528,\n      \"yMax\": 989,\n      \"hAsc\": 880,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Solway\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 400,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 954,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sometype Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 929,\n      \"wDes\": 295,\n      \"xH\": 470,\n      \"capH\": 650,\n      \"yMin\": -293,\n      \"yMax\": 923,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Song Myung\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 848,\n      \"des\": -152,\n      \"tAsc\": 848,\n      \"tDes\": -152,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 235,\n      \"xH\": 457,\n      \"capH\": 635,\n      \"yMin\": -230,\n      \"yMax\": 848,\n      \"hAsc\": 848,\n      \"hDes\": -152,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1824,\n      \"des\": -576,\n      \"tAsc\": 1824,\n      \"tDes\": -576,\n      \"tLGap\": 0,\n      \"wAsc\": 2122,\n      \"wDes\": 522,\n      \"xH\": 952,\n      \"capH\": 1238,\n      \"yMin\": -496,\n      \"yMax\": 1997,\n      \"hAsc\": 1824,\n      \"hDes\": -576,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sonsie One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2050,\n      \"des\": -600,\n      \"tAsc\": 2050,\n      \"tDes\": -600,\n      \"tLGap\": 0,\n      \"wAsc\": 2050,\n      \"wDes\": 600,\n      \"xH\": 272,\n      \"capH\": 506,\n      \"yMin\": -600,\n      \"yMax\": 2050,\n      \"hAsc\": 2050,\n      \"hDes\": -600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sora\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -290,\n      \"tAsc\": 970,\n      \"tDes\": -290,\n      \"tLGap\": 0,\n      \"wAsc\": 1220,\n      \"wDes\": 320,\n      \"xH\": 534,\n      \"capH\": 730,\n      \"yMin\": -284,\n      \"yMax\": 1180,\n      \"hAsc\": 970,\n      \"hDes\": -290,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sorts Mill Goudy\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 960,\n      \"des\": -478,\n      \"tAsc\": 960,\n      \"tDes\": -478,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 478,\n      \"xH\": 442,\n      \"capH\": 713,\n      \"yMin\": -438,\n      \"yMax\": 960,\n      \"hAsc\": 960,\n      \"hDes\": -478,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sour Gummy\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 996,\n      \"des\": -296,\n      \"tAsc\": 996,\n      \"tDes\": -296,\n      \"tLGap\": 0,\n      \"wAsc\": 950,\n      \"wDes\": 508,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -275,\n      \"yMax\": 866,\n      \"hAsc\": 996,\n      \"hDes\": -296,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Code Pro\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -273,\n      \"tAsc\": 984,\n      \"tDes\": -273,\n      \"tLGap\": 0,\n      \"wAsc\": 1060,\n      \"wDes\": 454,\n      \"xH\": 486,\n      \"capH\": 660,\n      \"yMin\": -454,\n      \"yMax\": 1060,\n      \"hAsc\": 984,\n      \"hDes\": -273,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Sans 3\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1024,\n      \"des\": -400,\n      \"tAsc\": 1024,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 288,\n      \"xH\": 486,\n      \"capH\": 660,\n      \"yMin\": -295,\n      \"yMax\": 958,\n      \"hAsc\": 1024,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Source Serif 4\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1036,\n      \"des\": -335,\n      \"tAsc\": 1036,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1009,\n      \"wDes\": 324,\n      \"xH\": 475,\n      \"capH\": 670,\n      \"yMin\": -328,\n      \"yMax\": 998,\n      \"hAsc\": 1036,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Space Grotesk\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 984,\n      \"des\": -292,\n      \"tAsc\": 984,\n      \"tDes\": -292,\n      \"tLGap\": 0,\n      \"wAsc\": 1150,\n      \"wDes\": 292,\n      \"xH\": 486,\n      \"capH\": 700,\n      \"yMin\": -277,\n      \"yMax\": 1096,\n      \"hAsc\": 984,\n      \"hDes\": -292,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Space Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1120,\n      \"des\": -361,\n      \"tAsc\": 1120,\n      \"tDes\": -361,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 361,\n      \"xH\": 496,\n      \"capH\": 700,\n      \"yMin\": -309,\n      \"yMax\": 1085,\n      \"hAsc\": 1120,\n      \"hDes\": -361,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Elite\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1440,\n      \"des\": -608,\n      \"tAsc\": 1440,\n      \"tDes\": -608,\n      \"tLGap\": 0,\n      \"wAsc\": 1440,\n      \"wDes\": 608,\n      \"xH\": 528,\n      \"capH\": 713,\n      \"yMin\": -659,\n      \"yMax\": 1962,\n      \"hAsc\": 1440,\n      \"hDes\": -608,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 504,\n      \"capH\": 710,\n      \"yMin\": -242,\n      \"yMax\": 913,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic Condensed One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 509,\n      \"capH\": 710,\n      \"yMin\": -254,\n      \"yMax\": 927,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Special Gothic Expanded One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 298,\n      \"xH\": 514,\n      \"capH\": 710,\n      \"yMin\": -298,\n      \"yMax\": 956,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spectral\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1059,\n      \"des\": -463,\n      \"tAsc\": 1059,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 1059,\n      \"wDes\": 463,\n      \"xH\": 450,\n      \"capH\": 660,\n      \"yMin\": -250,\n      \"yMax\": 1057,\n      \"hAsc\": 1059,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spectral SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1059,\n      \"des\": -463,\n      \"tAsc\": 1059,\n      \"tDes\": -463,\n      \"tLGap\": 0,\n      \"wAsc\": 1059,\n      \"wDes\": 463,\n      \"xH\": 450,\n      \"capH\": 660,\n      \"yMin\": -250,\n      \"yMax\": 1057,\n      \"hAsc\": 1059,\n      \"hDes\": -463,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spicy Rice\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2091,\n      \"des\": -733,\n      \"tAsc\": 2091,\n      \"tDes\": -733,\n      \"tLGap\": 0,\n      \"wAsc\": 2091,\n      \"wDes\": 733,\n      \"xH\": 1208,\n      \"capH\": 1481,\n      \"yMin\": -733,\n      \"yMax\": 2091,\n      \"hAsc\": 2091,\n      \"hDes\": -733,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spinnaker\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1920,\n      \"des\": -487,\n      \"tAsc\": 1920,\n      \"tDes\": -487,\n      \"tLGap\": 0,\n      \"wAsc\": 1920,\n      \"wDes\": 487,\n      \"xH\": 1000,\n      \"capH\": 1416,\n      \"yMin\": -487,\n      \"yMax\": 1920,\n      \"hAsc\": 1920,\n      \"hDes\": -487,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spirax\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 947,\n      \"des\": -288,\n      \"tAsc\": 947,\n      \"tDes\": -288,\n      \"tLGap\": 0,\n      \"wAsc\": 947,\n      \"wDes\": 288,\n      \"xH\": 463,\n      \"capH\": 696,\n      \"yMin\": -288,\n      \"yMax\": 947,\n      \"hAsc\": 947,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Splash\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -580,\n      \"tAsc\": 1050,\n      \"tDes\": -580,\n      \"tLGap\": 0,\n      \"wAsc\": 1300,\n      \"wDes\": 976,\n      \"xH\": 440,\n      \"capH\": 700,\n      \"yMin\": -976,\n      \"yMax\": 1299,\n      \"hAsc\": 1050,\n      \"hDes\": -580,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spline Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1927,\n      \"des\": -473,\n      \"tAsc\": 1927,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 2024,\n      \"wDes\": 605,\n      \"xH\": 1091,\n      \"capH\": 1454,\n      \"yMin\": -503,\n      \"yMax\": 1978,\n      \"hAsc\": 1927,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Spline Sans Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1927,\n      \"des\": -473,\n      \"tAsc\": 1927,\n      \"tDes\": -473,\n      \"tLGap\": 0,\n      \"wAsc\": 2160,\n      \"wDes\": 622,\n      \"xH\": 1091,\n      \"capH\": 1454,\n      \"yMin\": -548,\n      \"yMax\": 1993,\n      \"hAsc\": 1927,\n      \"hDes\": -473,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Squada One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 861,\n      \"des\": -196,\n      \"tAsc\": 861,\n      \"tDes\": -196,\n      \"tLGap\": 0,\n      \"wAsc\": 861,\n      \"wDes\": 196,\n      \"xH\": 498,\n      \"capH\": 647,\n      \"yMin\": -196,\n      \"yMax\": 861,\n      \"hAsc\": 861,\n      \"hDes\": -196,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Square Peg\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -400,\n      \"tAsc\": 920,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 1012,\n      \"wDes\": 410,\n      \"xH\": 260,\n      \"capH\": 600,\n      \"yMin\": -409,\n      \"yMax\": 1012,\n      \"hAsc\": 920,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sree Krushnadevaraya\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 720,\n      \"asc\": 1105,\n      \"des\": -378,\n      \"tAsc\": 1105,\n      \"tDes\": -378,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 378,\n      \"xH\": 273,\n      \"capH\": 408,\n      \"yMin\": -378,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -378,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sriracha\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1220,\n      \"des\": -550,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1220,\n      \"wDes\": 550,\n      \"xH\": 474,\n      \"capH\": 656,\n      \"yMin\": -562,\n      \"yMax\": 1220,\n      \"hAsc\": 1220,\n      \"hDes\": -550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Srisakdi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1484,\n      \"wDes\": 664,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -664,\n      \"yMax\": 1484,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Staatliches\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1006,\n      \"wDes\": 306,\n      \"xH\": 500,\n      \"capH\": 696,\n      \"yMin\": -306,\n      \"yMax\": 1006,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Headline\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Notch\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stack Sans Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 273,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -242,\n      \"yMax\": 955,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stalemate\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1837,\n      \"des\": -1165,\n      \"tAsc\": 1837,\n      \"tDes\": -1165,\n      \"tLGap\": 0,\n      \"wAsc\": 1837,\n      \"wDes\": 1165,\n      \"xH\": 539,\n      \"capH\": 1501,\n      \"yMin\": -1165,\n      \"yMax\": 1837,\n      \"hAsc\": 1837,\n      \"hDes\": -1165,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stalinist One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1037,\n      \"des\": -439,\n      \"tAsc\": 1037,\n      \"tDes\": -439,\n      \"tLGap\": 0,\n      \"wAsc\": 1037,\n      \"wDes\": 439,\n      \"xH\": 530,\n      \"capH\": 700,\n      \"yMin\": -439,\n      \"yMax\": 1037,\n      \"hAsc\": 1037,\n      \"hDes\": -439,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stardos Stencil\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1994,\n      \"des\": -831,\n      \"tAsc\": 1994,\n      \"tDes\": -831,\n      \"tLGap\": 0,\n      \"wAsc\": 1994,\n      \"wDes\": 831,\n      \"xH\": 981,\n      \"capH\": 1421,\n      \"yMin\": -808,\n      \"yMax\": 1970,\n      \"hAsc\": 1994,\n      \"hDes\": -831,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stick\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 520,\n      \"capH\": 715,\n      \"yMin\": -274,\n      \"yMax\": 1160,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stick No Bills\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -312,\n      \"tAsc\": 940,\n      \"tDes\": -312,\n      \"tLGap\": 0,\n      \"wAsc\": 1237,\n      \"wDes\": 622,\n      \"xH\": 515,\n      \"capH\": 700,\n      \"yMin\": -311,\n      \"yMax\": 946,\n      \"hAsc\": 940,\n      \"hDes\": -312,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stint Ultra Condensed\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1829,\n      \"des\": -483,\n      \"tAsc\": 1829,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1829,\n      \"wDes\": 483,\n      \"xH\": 952,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1829,\n      \"hAsc\": 1829,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stint Ultra Expanded\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1853,\n      \"des\": -483,\n      \"tAsc\": 1853,\n      \"tDes\": -483,\n      \"tLGap\": 0,\n      \"wAsc\": 1853,\n      \"wDes\": 483,\n      \"xH\": 952,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1853,\n      \"hAsc\": 1853,\n      \"hDes\": -483,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"STIX Two Text\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 762,\n      \"des\": -238,\n      \"tAsc\": 762,\n      \"tDes\": -238,\n      \"tLGap\": 250,\n      \"wAsc\": 1047,\n      \"wDes\": 441,\n      \"xH\": 473,\n      \"capH\": 657,\n      \"yMin\": -373,\n      \"yMax\": 1047,\n      \"hAsc\": 762,\n      \"hDes\": -238,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Stoke\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -530,\n      \"tAsc\": 2030,\n      \"tDes\": -530,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 530,\n      \"xH\": 479,\n      \"capH\": 683,\n      \"yMin\": -526,\n      \"yMax\": 2027,\n      \"hAsc\": 2030,\n      \"hDes\": -530,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Story Script\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 959,\n      \"des\": -340,\n      \"tAsc\": 959,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 365,\n      \"xH\": 438,\n      \"capH\": 617,\n      \"yMin\": -363,\n      \"yMax\": 1022,\n      \"hAsc\": 959,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Strait\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 901,\n      \"des\": -194,\n      \"tAsc\": 901,\n      \"tDes\": -194,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 265,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -265,\n      \"yMax\": 958,\n      \"hAsc\": 901,\n      \"hDes\": -194,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Style Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -520,\n      \"tAsc\": 1000,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 1120,\n      \"wDes\": 800,\n      \"xH\": 434,\n      \"capH\": 700,\n      \"yMin\": -799,\n      \"yMax\": 1113,\n      \"hAsc\": 1000,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Stylish\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 821,\n      \"des\": -179,\n      \"tAsc\": 821,\n      \"tDes\": -179,\n      \"tLGap\": 250,\n      \"wAsc\": 848,\n      \"wDes\": 235,\n      \"xH\": 410,\n      \"capH\": 600,\n      \"yMin\": -196,\n      \"yMax\": 820,\n      \"hAsc\": 821,\n      \"hDes\": -179,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sue Ellen Francisco\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1362,\n      \"des\": -634,\n      \"tAsc\": 1362,\n      \"tDes\": -634,\n      \"tLGap\": 0,\n      \"wAsc\": 1362,\n      \"wDes\": 634,\n      \"xH\": 439,\n      \"capH\": 1085,\n      \"yMin\": -571,\n      \"yMax\": 1362,\n      \"hAsc\": 1362,\n      \"hDes\": -634,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suez One\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 987,\n      \"des\": -319,\n      \"tAsc\": 987,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 987,\n      \"wDes\": 319,\n      \"xH\": 523,\n      \"capH\": 674,\n      \"yMin\": -319,\n      \"yMax\": 987,\n      \"hAsc\": 987,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sulphur Point\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 790,\n      \"des\": -210,\n      \"tAsc\": 790,\n      \"tDes\": -210,\n      \"tLGap\": 369,\n      \"wAsc\": 893,\n      \"wDes\": 224,\n      \"xH\": 500,\n      \"capH\": 665,\n      \"yMin\": -224,\n      \"yMax\": 892,\n      \"hAsc\": 790,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sumana\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1922,\n      \"des\": -1005,\n      \"tAsc\": 1922,\n      \"tDes\": -1005,\n      \"tLGap\": 0,\n      \"wAsc\": 1922,\n      \"wDes\": 1005,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -493,\n      \"yMax\": 961,\n      \"hAsc\": 1922,\n      \"hDes\": -1005,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sunflower\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 500, 700],\n    \"styles\": [],\n    \"variants\": [\n      [0, 300],\n      [0, 500],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 782,\n      \"des\": -218,\n      \"tAsc\": 782,\n      \"tDes\": -218,\n      \"tLGap\": 250,\n      \"wAsc\": 810,\n      \"wDes\": 235,\n      \"xH\": 500,\n      \"capH\": 692,\n      \"yMin\": -235,\n      \"yMax\": 798,\n      \"hAsc\": 782,\n      \"hDes\": -218,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Sunshiney\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -306,\n      \"tAsc\": 626,\n      \"tDes\": -190,\n      \"tLGap\": 53,\n      \"wAsc\": 1019,\n      \"wDes\": 306,\n      \"xH\": 391,\n      \"capH\": 759,\n      \"yMin\": -306,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -306,\n      \"lGap\": 27\n    }\n  },\n  {\n    \"family\": \"Supermercado One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1925,\n      \"des\": -527,\n      \"tAsc\": 1925,\n      \"tDes\": -527,\n      \"tLGap\": 0,\n      \"wAsc\": 1925,\n      \"wDes\": 527,\n      \"xH\": 1066,\n      \"capH\": 1359,\n      \"yMin\": -526,\n      \"yMax\": 1925,\n      \"hAsc\": 1925,\n      \"hDes\": -527,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Sura\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2359,\n      \"des\": -872,\n      \"tAsc\": 2359,\n      \"tDes\": -872,\n      \"tLGap\": 0,\n      \"wAsc\": 2359,\n      \"wDes\": 872,\n      \"xH\": 1022,\n      \"capH\": 1464,\n      \"yMin\": -780,\n      \"yMax\": 2257,\n      \"hAsc\": 2359,\n      \"hDes\": -872,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suranna\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 780,\n      \"asc\": 1101,\n      \"des\": -607,\n      \"tAsc\": 1101,\n      \"tDes\": -607,\n      \"tLGap\": 0,\n      \"wAsc\": 1101,\n      \"wDes\": 607,\n      \"xH\": 319,\n      \"capH\": 492,\n      \"yMin\": -607,\n      \"yMax\": 1101,\n      \"hAsc\": 1101,\n      \"hDes\": -607,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suravaram\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 980,\n      \"asc\": 1295,\n      \"des\": -794,\n      \"tAsc\": 1295,\n      \"tDes\": -794,\n      \"tLGap\": 0,\n      \"wAsc\": 1295,\n      \"wDes\": 794,\n      \"xH\": 344,\n      \"capH\": 482,\n      \"yMin\": -794,\n      \"yMax\": 1295,\n      \"hAsc\": 1295,\n      \"hDes\": -794,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SUSE\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -280,\n      \"tAsc\": 980,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 410,\n      \"xH\": 481,\n      \"capH\": 700,\n      \"yMin\": -379,\n      \"yMax\": 1084,\n      \"hAsc\": 980,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"SUSE Mono\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 980,\n      \"des\": -280,\n      \"tAsc\": 980,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 1153,\n      \"wDes\": 410,\n      \"xH\": 481,\n      \"capH\": 700,\n      \"yMin\": -379,\n      \"yMax\": 1084,\n      \"hAsc\": 980,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Suwannaphum\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 300, 400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2230,\n      \"wDes\": 910,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -910,\n      \"yMax\": 2202,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Swanky and Moo Moo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 995,\n      \"des\": -507,\n      \"tAsc\": 995,\n      \"tDes\": -507,\n      \"tLGap\": 0,\n      \"wAsc\": 995,\n      \"wDes\": 507,\n      \"xH\": 341,\n      \"capH\": 424,\n      \"yMin\": -507,\n      \"yMax\": 955,\n      \"hAsc\": 995,\n      \"hDes\": -507,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syncopate\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1556,\n      \"des\": -426,\n      \"tAsc\": 1556,\n      \"tDes\": -426,\n      \"tLGap\": 150,\n      \"wAsc\": 1853,\n      \"wDes\": 483,\n      \"xH\": 958,\n      \"capH\": 1374,\n      \"yMin\": -483,\n      \"yMax\": 1853,\n      \"hAsc\": 1556,\n      \"hDes\": -426,\n      \"lGap\": 150\n    }\n  },\n  {\n    \"family\": \"Syne\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -254,\n      \"yMax\": 952,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syne Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -253,\n      \"yMax\": 917,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Syne Tactile\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 925,\n      \"des\": -275,\n      \"tAsc\": 925,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 955,\n      \"wDes\": 495,\n      \"xH\": 500,\n      \"capH\": 650,\n      \"yMin\": -493,\n      \"yMax\": 920,\n      \"hAsc\": 925,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tac One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -200,\n      \"tAsc\": 830,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 860,\n      \"wDes\": 280,\n      \"xH\": 400,\n      \"capH\": 554,\n      \"yMin\": -280,\n      \"yMax\": 859,\n      \"hAsc\": 830,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tagesschrift\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1065,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -289,\n      \"yMax\": 1065,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tahoma\",\n    \"fallbacks\": [\"Verdana\", \"Segoe\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2049,\n      \"des\": -423,\n      \"tAsc\": 1566,\n      \"tDes\": -423,\n      \"tLGap\": 59,\n      \"wAsc\": 2049,\n      \"wDes\": 2049,\n      \"xH\": 1117,\n      \"capH\": 1489,\n      \"yMin\": -442,\n      \"yMax\": 2118,\n      \"hAsc\": 2049,\n      \"hDes\": -423,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Tai Heritage Pro\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2700,\n      \"des\": -1600,\n      \"tAsc\": 2700,\n      \"tDes\": -1600,\n      \"tLGap\": 0,\n      \"wAsc\": 2700,\n      \"wDes\": 1600,\n      \"xH\": 1150,\n      \"capH\": 1700,\n      \"yMin\": -1546,\n      \"yMax\": 2775,\n      \"hAsc\": 2700,\n      \"hDes\": -1600,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tajawal\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 643,\n      \"des\": -357,\n      \"tAsc\": 643,\n      \"tDes\": -357,\n      \"tLGap\": 200,\n      \"wAsc\": 1016,\n      \"wDes\": 375,\n      \"xH\": 454,\n      \"capH\": 633,\n      \"yMin\": -375,\n      \"yMax\": 995,\n      \"hAsc\": 643,\n      \"hDes\": -357,\n      \"lGap\": 200\n    }\n  },\n  {\n    \"family\": \"Tangerine\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 750,\n      \"des\": -250,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 765,\n      \"wDes\": 286,\n      \"xH\": 255,\n      \"capH\": 644,\n      \"yMin\": -286,\n      \"yMax\": 765,\n      \"hAsc\": 750,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tapestry\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -300,\n      \"tAsc\": 950,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 300,\n      \"xH\": 454,\n      \"capH\": 640,\n      \"yMin\": -286,\n      \"yMax\": 1016,\n      \"hAsc\": 950,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Taprom\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2500,\n      \"des\": -1200,\n      \"tAsc\": 2500,\n      \"tDes\": -1200,\n      \"tLGap\": 0,\n      \"wAsc\": 2500,\n      \"wDes\": 1200,\n      \"xH\": 1098,\n      \"capH\": 1462,\n      \"yMin\": -1200,\n      \"yMax\": 2500,\n      \"hAsc\": 2500,\n      \"hDes\": -1200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TASA Explorer\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -250,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TASA Orbiter\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 260,\n      \"xH\": 500,\n      \"capH\": 680,\n      \"yMin\": -250,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tauri\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2040,\n      \"des\": -520,\n      \"tAsc\": 2040,\n      \"tDes\": -520,\n      \"tLGap\": 0,\n      \"wAsc\": 2040,\n      \"wDes\": 520,\n      \"xH\": 1135,\n      \"capH\": 1571,\n      \"yMin\": -520,\n      \"yMax\": 2040,\n      \"hAsc\": 2040,\n      \"hDes\": -520,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Taviraj\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1172,\n      \"des\": -534,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1172,\n      \"wDes\": 534,\n      \"xH\": 470,\n      \"capH\": 700,\n      \"yMin\": -489,\n      \"yMax\": 1131,\n      \"hAsc\": 1172,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Teachers\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 940,\n      \"wDes\": 273,\n      \"xH\": 440,\n      \"capH\": 680,\n      \"yMin\": -273,\n      \"yMax\": 930,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Teko\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 958,\n      \"des\": -475,\n      \"tAsc\": 958,\n      \"tDes\": -475,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 475,\n      \"xH\": 485,\n      \"capH\": 626,\n      \"yMin\": -394,\n      \"yMax\": 857,\n      \"hAsc\": 958,\n      \"hDes\": -475,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tektur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 300,\n      \"xH\": 560,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 1000,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Telex\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -260,\n      \"tAsc\": 945,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 945,\n      \"wDes\": 260,\n      \"xH\": 514,\n      \"capH\": 708,\n      \"yMin\": -260,\n      \"yMax\": 945,\n      \"hAsc\": 945,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tenali Ramakrishna\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 661,\n      \"des\": -512,\n      \"tAsc\": 661,\n      \"tDes\": -512,\n      \"tLGap\": 0,\n      \"wAsc\": 661,\n      \"wDes\": 512,\n      \"xH\": 268,\n      \"capH\": 367,\n      \"yMin\": -512,\n      \"yMax\": 661,\n      \"hAsc\": 661,\n      \"hDes\": -512,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tenor Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 920,\n      \"des\": -250,\n      \"tAsc\": 920,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 920,\n      \"wDes\": 250,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -250,\n      \"yMax\": 920,\n      \"hAsc\": 920,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Text Me One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -269,\n      \"tAsc\": 952,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 952,\n      \"wDes\": 269,\n      \"xH\": 502,\n      \"capH\": 700,\n      \"yMin\": -269,\n      \"yMax\": 952,\n      \"hAsc\": 952,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Texturina\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1260,\n      \"des\": -300,\n      \"tAsc\": 1260,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1260,\n      \"wDes\": 300,\n      \"xH\": 500,\n      \"capH\": 704,\n      \"yMin\": -280,\n      \"yMax\": 1192,\n      \"hAsc\": 1260,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Thasadith\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1005,\n      \"des\": -295,\n      \"tAsc\": 1005,\n      \"tDes\": -295,\n      \"tLGap\": 0,\n      \"wAsc\": 1177,\n      \"wDes\": 494,\n      \"xH\": 510,\n      \"capH\": 700,\n      \"yMin\": -464,\n      \"yMax\": 1140,\n      \"hAsc\": 1005,\n      \"hDes\": -295,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"The Girl Next Door\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1139,\n      \"des\": -748,\n      \"tAsc\": 1139,\n      \"tDes\": -748,\n      \"tLGap\": 0,\n      \"wAsc\": 1139,\n      \"wDes\": 748,\n      \"xH\": 519,\n      \"capH\": 627,\n      \"yMin\": -673,\n      \"yMax\": 1025,\n      \"hAsc\": 1139,\n      \"hDes\": -748,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"The Nautigal\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 870,\n      \"des\": -330,\n      \"tAsc\": 870,\n      \"tDes\": -330,\n      \"tLGap\": 0,\n      \"wAsc\": 946,\n      \"wDes\": 417,\n      \"xH\": 265,\n      \"capH\": 600,\n      \"yMin\": -417,\n      \"yMax\": 939,\n      \"hAsc\": 870,\n      \"hDes\": -330,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tienne\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2030,\n      \"des\": -724,\n      \"tAsc\": 2030,\n      \"tDes\": -724,\n      \"tLGap\": 0,\n      \"wAsc\": 2030,\n      \"wDes\": 724,\n      \"xH\": 363,\n      \"capH\": 1437,\n      \"yMin\": -724,\n      \"yMax\": 2030,\n      \"hAsc\": 2030,\n      \"hDes\": -724,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"TikTok Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -300,\n      \"tAsc\": 1000,\n      \"tDes\": -300,\n      \"tLGap\": 0,\n      \"wAsc\": 1118,\n      \"wDes\": 242,\n      \"xH\": 526,\n      \"capH\": 705,\n      \"yMin\": -236,\n      \"yMax\": 1086,\n      \"hAsc\": 1000,\n      \"hDes\": -300,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tillana\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1158,\n      \"des\": -484,\n      \"tAsc\": 1158,\n      \"tDes\": -484,\n      \"tLGap\": 0,\n      \"wAsc\": 1158,\n      \"wDes\": 484,\n      \"xH\": 546,\n      \"capH\": 732,\n      \"yMin\": -312,\n      \"yMax\": 1041,\n      \"hAsc\": 1158,\n      \"hDes\": -484,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Neon\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -395,\n      \"yMax\": 1174,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Prism\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -274,\n      \"yMax\": 1186,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tilt Warp\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 990,\n      \"des\": -272,\n      \"tAsc\": 990,\n      \"tDes\": -272,\n      \"tLGap\": 0,\n      \"wAsc\": 1186,\n      \"wDes\": 422,\n      \"xH\": 517,\n      \"capH\": 680,\n      \"yMin\": -422,\n      \"yMax\": 1177,\n      \"hAsc\": 990,\n      \"hDes\": -272,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Times New Roman\",\n    \"fallbacks\": [\n      \"Times New Roman\",\n      \"Times\",\n      \"Baskerville\",\n      \"Georgia\",\n      \"serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1825,\n      \"des\": -443,\n      \"tAsc\": 1420,\n      \"tDes\": -442,\n      \"tLGap\": 307,\n      \"wAsc\": 1825,\n      \"wDes\": 1825,\n      \"xH\": 916,\n      \"capH\": 1356,\n      \"yMin\": -628,\n      \"yMax\": 2062,\n      \"hAsc\": 1825,\n      \"hDes\": -443,\n      \"lGap\": 87\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Timmana\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 750,\n      \"asc\": 668,\n      \"des\": -554,\n      \"tAsc\": 668,\n      \"tDes\": -554,\n      \"tLGap\": 0,\n      \"wAsc\": 668,\n      \"wDes\": 554,\n      \"xH\": 354,\n      \"capH\": 454,\n      \"yMin\": -554,\n      \"yMax\": 668,\n      \"hAsc\": 668,\n      \"hDes\": -554,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tinos\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1825,\n      \"des\": -443,\n      \"tAsc\": 1420,\n      \"tDes\": -442,\n      \"tLGap\": 307,\n      \"wAsc\": 1825,\n      \"wDes\": 443,\n      \"xH\": 940,\n      \"capH\": 1341,\n      \"yMin\": -621,\n      \"yMax\": 2010,\n      \"hAsc\": 1825,\n      \"hDes\": -443,\n      \"lGap\": 87\n    }\n  },\n  {\n    \"family\": \"Tiny5\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -256,\n      \"tAsc\": 896,\n      \"tDes\": -256,\n      \"tLGap\": 0,\n      \"wAsc\": 1408,\n      \"wDes\": 384,\n      \"xH\": 512,\n      \"capH\": 640,\n      \"yMin\": -384,\n      \"yMax\": 1408,\n      \"hAsc\": 896,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tiro Bangla\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Hindi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 501,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -501,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Marathi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 501,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -501,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Devanagari Sanskrit\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 330,\n      \"wAsc\": 1091,\n      \"wDes\": 545,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -545,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 330\n    }\n  },\n  {\n    \"family\": \"Tiro Gurmukhi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 250,\n      \"wAsc\": 1447,\n      \"wDes\": 430,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1447,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Tiro Kannada\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 794,\n      \"wAsc\": 1091,\n      \"wDes\": 694,\n      \"xH\": 475,\n      \"capH\": 699,\n      \"yMin\": -694,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 794\n    }\n  },\n  {\n    \"family\": \"Tiro Tamil\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 436,\n      \"wAsc\": 1091,\n      \"wDes\": 430,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -430,\n      \"yMax\": 1091,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 436\n    }\n  },\n  {\n    \"family\": \"Tiro Telugu\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 755,\n      \"des\": -245,\n      \"tAsc\": 755,\n      \"tDes\": -245,\n      \"tLGap\": 794,\n      \"wAsc\": 1189,\n      \"wDes\": 563,\n      \"xH\": 478,\n      \"capH\": 699,\n      \"yMin\": -563,\n      \"yMax\": 1189,\n      \"hAsc\": 755,\n      \"hDes\": -245,\n      \"lGap\": 794\n    }\n  },\n  {\n    \"family\": \"Tirra\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2093,\n      \"des\": -713,\n      \"tAsc\": 2093,\n      \"tDes\": -713,\n      \"tLGap\": 0,\n      \"wAsc\": 2093,\n      \"wDes\": 713,\n      \"xH\": 1024,\n      \"capH\": 1393,\n      \"yMin\": -713,\n      \"yMax\": 1860,\n      \"hAsc\": 2093,\n      \"hDes\": -713,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Titan One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -175,\n      \"tAsc\": 970,\n      \"tDes\": -175,\n      \"tLGap\": 0,\n      \"wAsc\": 970,\n      \"wDes\": 175,\n      \"xH\": 580,\n      \"capH\": 710,\n      \"yMin\": -175,\n      \"yMax\": 970,\n      \"hAsc\": 970,\n      \"hDes\": -175,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Titillium Web\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 600, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1133,\n      \"des\": -388,\n      \"tAsc\": 1133,\n      \"tDes\": -388,\n      \"tLGap\": 0,\n      \"wAsc\": 1133,\n      \"wDes\": 388,\n      \"xH\": 500,\n      \"capH\": 692,\n      \"yMin\": -285,\n      \"yMax\": 1082,\n      \"hAsc\": 1133,\n      \"hDes\": -388,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tomorrow\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -200,\n      \"tAsc\": 1000,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1233,\n      \"wDes\": 279,\n      \"xH\": 523,\n      \"capH\": 737,\n      \"yMin\": -232,\n      \"yMax\": 1166,\n      \"hAsc\": 1000,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tourney\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1800,\n      \"des\": -400,\n      \"tAsc\": 1800,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 2160,\n      \"wDes\": 540,\n      \"xH\": 1080,\n      \"capH\": 1400,\n      \"yMin\": -533,\n      \"yMax\": 2116,\n      \"hAsc\": 1800,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trade Winds\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1019,\n      \"des\": -469,\n      \"tAsc\": 1019,\n      \"tDes\": -469,\n      \"tLGap\": 0,\n      \"wAsc\": 1019,\n      \"wDes\": 469,\n      \"xH\": 576,\n      \"capH\": 814,\n      \"yMin\": -469,\n      \"yMax\": 1019,\n      \"hAsc\": 1019,\n      \"hDes\": -469,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Train One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 557,\n      \"capH\": 780,\n      \"yMin\": -221,\n      \"yMax\": 1061,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trebuchet MS\",\n    \"fallbacks\": [\n      \"Lucida Grande\",\n      \"Lucida Sans Unicode\",\n      \"Lucida Sans\",\n      \"Tahoma\",\n      \"sans-serif\"\n    ],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1923,\n      \"des\": -455,\n      \"tAsc\": 1510,\n      \"tDes\": -420,\n      \"tLGap\": 0,\n      \"wAsc\": 1923,\n      \"wDes\": 1923,\n      \"yMin\": -537,\n      \"yMax\": 1931,\n      \"hAsc\": 1923,\n      \"hDes\": -455,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Triodion\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1126,\n      \"des\": -511,\n      \"tAsc\": 1126,\n      \"tDes\": -511,\n      \"tLGap\": 0,\n      \"wAsc\": 1126,\n      \"wDes\": 511,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -511,\n      \"yMax\": 1126,\n      \"hAsc\": 1126,\n      \"hDes\": -511,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trirong\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 200],\n      [1, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800],\n      [0, 900],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -534,\n      \"tAsc\": 750,\n      \"tDes\": -250,\n      \"tLGap\": 200,\n      \"wAsc\": 1200,\n      \"wDes\": 534,\n      \"xH\": 498,\n      \"capH\": 700,\n      \"yMin\": -487,\n      \"yMax\": 1133,\n      \"hAsc\": 1200,\n      \"hDes\": -534,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trispace\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1830,\n      \"des\": -430,\n      \"tAsc\": 1830,\n      \"tDes\": -430,\n      \"tLGap\": 0,\n      \"wAsc\": 2355,\n      \"wDes\": 630,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -547,\n      \"yMax\": 2258,\n      \"hAsc\": 1830,\n      \"hDes\": -430,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trocchi\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2085,\n      \"des\": -576,\n      \"tAsc\": 2085,\n      \"tDes\": -576,\n      \"tLGap\": 0,\n      \"wAsc\": 2085,\n      \"wDes\": 580,\n      \"xH\": 1073,\n      \"capH\": 1505,\n      \"yMin\": -580,\n      \"yMax\": 2085,\n      \"hAsc\": 2085,\n      \"hDes\": -576,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trochut\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 967,\n      \"des\": -210,\n      \"tAsc\": 967,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 967,\n      \"wDes\": 210,\n      \"xH\": 470,\n      \"capH\": 690,\n      \"yMin\": -210,\n      \"yMax\": 922,\n      \"hAsc\": 967,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Truculenta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1050,\n      \"des\": -340,\n      \"tAsc\": 1050,\n      \"tDes\": -340,\n      \"tLGap\": 0,\n      \"wAsc\": 1050,\n      \"wDes\": 340,\n      \"xH\": 515,\n      \"capH\": 693,\n      \"yMin\": -288,\n      \"yMax\": 982,\n      \"hAsc\": 1050,\n      \"hDes\": -340,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Trykker\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2022,\n      \"des\": -538,\n      \"tAsc\": 2022,\n      \"tDes\": -538,\n      \"tLGap\": 0,\n      \"wAsc\": 2022,\n      \"wDes\": 538,\n      \"xH\": 1013,\n      \"capH\": 1492,\n      \"yMin\": -539,\n      \"yMax\": 2027,\n      \"hAsc\": 2022,\n      \"hDes\": -538,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tsukimi Rounded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 500,\n      \"capH\": 800,\n      \"yMin\": -288,\n      \"yMax\": 1055,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tuffy\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2340,\n      \"des\": -697,\n      \"tAsc\": 2340,\n      \"tDes\": -697,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 697,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -648,\n      \"yMax\": 2023,\n      \"hAsc\": 2340,\n      \"hDes\": -697,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Tulpen One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1767,\n      \"des\": -465,\n      \"tAsc\": 1767,\n      \"tDes\": -465,\n      \"tLGap\": 0,\n      \"wAsc\": 1767,\n      \"wDes\": 465,\n      \"xH\": 1018,\n      \"capH\": 1393,\n      \"yMin\": -465,\n      \"yMax\": 1767,\n      \"hAsc\": 1767,\n      \"hDes\": -465,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Turret Road\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [200, 300, 400, 500, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -243,\n      \"tAsc\": 850,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 931,\n      \"wDes\": 246,\n      \"xH\": 478,\n      \"capH\": 700,\n      \"yMin\": -234,\n      \"yMax\": 924,\n      \"hAsc\": 850,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Twinkle Star\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -350,\n      \"tAsc\": 930,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 1112,\n      \"wDes\": 426,\n      \"xH\": 470,\n      \"capH\": 705,\n      \"yMin\": -426,\n      \"yMax\": 1112,\n      \"hAsc\": 930,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -189,\n      \"tAsc\": 776,\n      \"tDes\": -185,\n      \"tLGap\": 56,\n      \"wAsc\": 932,\n      \"wDes\": 189,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -189,\n      \"yMax\": 962,\n      \"hAsc\": 932,\n      \"hDes\": -189,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Ubuntu Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 932,\n      \"des\": -189,\n      \"tAsc\": 776,\n      \"tDes\": -185,\n      \"tLGap\": 56,\n      \"wAsc\": 932,\n      \"wDes\": 189,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -195,\n      \"yMax\": 973,\n      \"hAsc\": 932,\n      \"hDes\": -189,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Ubuntu Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 830,\n      \"des\": -170,\n      \"tAsc\": 693,\n      \"tDes\": -165,\n      \"tLGap\": 49,\n      \"wAsc\": 830,\n      \"wDes\": 170,\n      \"xH\": 520,\n      \"capH\": 693,\n      \"yMin\": -170,\n      \"yMax\": 830,\n      \"hAsc\": 830,\n      \"hDes\": -170,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 223,\n      \"xH\": 518,\n      \"capH\": 693,\n      \"yMin\": -195,\n      \"yMax\": 958,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ubuntu Sans Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 940,\n      \"des\": -260,\n      \"tAsc\": 940,\n      \"tDes\": -260,\n      \"tLGap\": 0,\n      \"wAsc\": 1020,\n      \"wDes\": 223,\n      \"xH\": 518,\n      \"capH\": 693,\n      \"yMin\": -205,\n      \"yMax\": 932,\n      \"hAsc\": 940,\n      \"hDes\": -260,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Uchen\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1248,\n      \"des\": -660,\n      \"tAsc\": 1248,\n      \"tDes\": -660,\n      \"tLGap\": 0,\n      \"wAsc\": 1361,\n      \"wDes\": 909,\n      \"xH\": 485,\n      \"capH\": 744,\n      \"yMin\": -909,\n      \"yMax\": 1361,\n      \"hAsc\": 1248,\n      \"hDes\": -660,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ultra\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2066,\n      \"des\": -561,\n      \"tAsc\": 2066,\n      \"tDes\": -561,\n      \"tLGap\": 0,\n      \"wAsc\": 2066,\n      \"wDes\": 561,\n      \"xH\": 1102,\n      \"capH\": 1473,\n      \"yMin\": -561,\n      \"yMax\": 2066,\n      \"hAsc\": 2066,\n      \"hDes\": -561,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unbounded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 995,\n      \"des\": -245,\n      \"tAsc\": 995,\n      \"tDes\": -245,\n      \"tLGap\": 0,\n      \"wAsc\": 1262,\n      \"wDes\": 286,\n      \"xH\": 566,\n      \"capH\": 750,\n      \"yMin\": -286,\n      \"yMax\": 1173,\n      \"hAsc\": 995,\n      \"hDes\": -245,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Uncial Antiqua\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2019,\n      \"des\": -676,\n      \"tAsc\": 2019,\n      \"tDes\": -676,\n      \"tLGap\": 0,\n      \"wAsc\": 2019,\n      \"wDes\": 676,\n      \"xH\": 1079,\n      \"capH\": 1841,\n      \"yMin\": -676,\n      \"yMax\": 2019,\n      \"hAsc\": 2019,\n      \"hDes\": -676,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Underdog\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 909,\n      \"des\": -247,\n      \"tAsc\": 909,\n      \"tDes\": -247,\n      \"tLGap\": 0,\n      \"wAsc\": 909,\n      \"wDes\": 247,\n      \"xH\": 520,\n      \"capH\": 710,\n      \"yMin\": -247,\n      \"yMax\": 915,\n      \"hAsc\": 909,\n      \"hDes\": -247,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unica One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 917,\n      \"des\": -265,\n      \"tAsc\": 917,\n      \"tDes\": -265,\n      \"tLGap\": 0,\n      \"wAsc\": 1042,\n      \"wDes\": 265,\n      \"xH\": 650,\n      \"capH\": 650,\n      \"yMin\": -265,\n      \"yMax\": 1041,\n      \"hAsc\": 917,\n      \"hDes\": -265,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UnifrakturCook\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [700],\n    \"styles\": [],\n    \"variants\": [[0, 700]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2110,\n      \"des\": -570,\n      \"tAsc\": 2110,\n      \"tDes\": -570,\n      \"tLGap\": 0,\n      \"wAsc\": 2110,\n      \"wDes\": 570,\n      \"xH\": 319,\n      \"capH\": 485,\n      \"yMin\": -570,\n      \"yMax\": 2110,\n      \"hAsc\": 2110,\n      \"hDes\": -570,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UnifrakturMaguntia\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1607,\n      \"des\": -513,\n      \"tAsc\": 1607,\n      \"tDes\": -514,\n      \"tLGap\": 0,\n      \"wAsc\": 1607,\n      \"wDes\": 512,\n      \"xH\": 1095,\n      \"capH\": 1409,\n      \"yMin\": -496,\n      \"yMax\": 1906,\n      \"hAsc\": 1607,\n      \"hDes\": -513,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unkempt\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 977,\n      \"des\": -246,\n      \"tAsc\": 695,\n      \"tDes\": -226,\n      \"tLGap\": 55,\n      \"wAsc\": 977,\n      \"wDes\": 246,\n      \"xH\": 482,\n      \"capH\": 753,\n      \"yMin\": -246,\n      \"yMax\": 977,\n      \"hAsc\": 977,\n      \"hDes\": -246,\n      \"lGap\": 28\n    }\n  },\n  {\n    \"family\": \"Unlock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 873,\n      \"des\": -195,\n      \"tAsc\": 873,\n      \"tDes\": -195,\n      \"tLGap\": 0,\n      \"wAsc\": 958,\n      \"wDes\": 295,\n      \"xH\": 550,\n      \"capH\": 635,\n      \"yMin\": -295,\n      \"yMax\": 958,\n      \"hAsc\": 873,\n      \"hDes\": -195,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Unna\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 883,\n      \"des\": -269,\n      \"tAsc\": 883,\n      \"tDes\": -269,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 269,\n      \"xH\": 420,\n      \"capH\": 597,\n      \"yMin\": -269,\n      \"yMax\": 878,\n      \"hAsc\": 883,\n      \"hDes\": -269,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"UoqMunThenKhung\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 941,\n      \"des\": -187,\n      \"tAsc\": 941,\n      \"tDes\": -187,\n      \"tLGap\": 0,\n      \"wAsc\": 949,\n      \"wDes\": 213,\n      \"xH\": 541,\n      \"capH\": 732,\n      \"yMin\": -213,\n      \"yMax\": 949,\n      \"hAsc\": 941,\n      \"hDes\": -187,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Updock\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 900,\n      \"des\": -350,\n      \"tAsc\": 900,\n      \"tDes\": -350,\n      \"tLGap\": 0,\n      \"wAsc\": 910,\n      \"wDes\": 500,\n      \"xH\": 350,\n      \"capH\": 630,\n      \"yMin\": -497,\n      \"yMax\": 906,\n      \"hAsc\": 900,\n      \"hDes\": -350,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Urbanist\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2000,\n      \"asc\": 1900,\n      \"des\": -500,\n      \"tAsc\": 1900,\n      \"tDes\": -500,\n      \"tLGap\": 0,\n      \"wAsc\": 2120,\n      \"wDes\": 500,\n      \"xH\": 1000,\n      \"capH\": 1400,\n      \"yMin\": -500,\n      \"yMax\": 2011,\n      \"hAsc\": 1900,\n      \"hDes\": -500,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vampiro One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 956,\n      \"des\": -294,\n      \"tAsc\": 956,\n      \"tDes\": -294,\n      \"tLGap\": 0,\n      \"wAsc\": 956,\n      \"wDes\": 294,\n      \"xH\": 534,\n      \"capH\": 705,\n      \"yMin\": -294,\n      \"yMax\": 956,\n      \"hAsc\": 956,\n      \"hDes\": -294,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varela\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -285,\n      \"tAsc\": 1015,\n      \"tDes\": -285,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 285,\n      \"xH\": 510,\n      \"capH\": 698,\n      \"yMin\": -285,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -285,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varela Round\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 918,\n      \"des\": -286,\n      \"tAsc\": 918,\n      \"tDes\": -286,\n      \"tLGap\": 0,\n      \"wAsc\": 1025,\n      \"wDes\": 286,\n      \"xH\": 510,\n      \"capH\": 698,\n      \"yMin\": -286,\n      \"yMax\": 1025,\n      \"hAsc\": 918,\n      \"hDes\": -286,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Varta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1902,\n      \"des\": -1068,\n      \"tAsc\": 1902,\n      \"tDes\": -1068,\n      \"tLGap\": 0,\n      \"wAsc\": 2340,\n      \"wDes\": 1450,\n      \"xH\": 990,\n      \"capH\": 1346,\n      \"yMin\": -514,\n      \"yMax\": 1966,\n      \"hAsc\": 1902,\n      \"hDes\": -1068,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vast Shadow\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1875,\n      \"des\": -685,\n      \"tAsc\": 1875,\n      \"tDes\": -685,\n      \"tLGap\": 0,\n      \"wAsc\": 1875,\n      \"wDes\": 683,\n      \"xH\": 965,\n      \"capH\": 1245,\n      \"yMin\": -685,\n      \"yMax\": 1875,\n      \"hAsc\": 1875,\n      \"hDes\": -685,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vazirmatn\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2100,\n      \"des\": -1100,\n      \"tAsc\": 2100,\n      \"tDes\": -1100,\n      \"tLGap\": 0,\n      \"wAsc\": 2200,\n      \"wDes\": 1300,\n      \"xH\": 1082,\n      \"capH\": 1638,\n      \"yMin\": -1142,\n      \"yMax\": 2163,\n      \"hAsc\": 2100,\n      \"hDes\": -1100,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vend Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1090,\n      \"des\": -390,\n      \"tAsc\": 1090,\n      \"tDes\": -390,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 380,\n      \"xH\": 550,\n      \"capH\": 700,\n      \"yMin\": -273,\n      \"yMax\": 1030,\n      \"hAsc\": 1090,\n      \"hDes\": -390,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Verdana\",\n    \"fallbacks\": [\"Geneva\", \"sans-serif\"],\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2059,\n      \"des\": -430,\n      \"tAsc\": 1566,\n      \"tDes\": -423,\n      \"tLGap\": 202,\n      \"wAsc\": 2059,\n      \"wDes\": 2059,\n      \"xH\": 1117,\n      \"capH\": 1489,\n      \"yMin\": -621,\n      \"yMax\": 2049,\n      \"hAsc\": 2059,\n      \"hDes\": -430,\n      \"lGap\": 0\n    },\n    \"weights\": [400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"service\": \"system\"\n  },\n  {\n    \"family\": \"Vesper Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2330,\n      \"des\": -1550,\n      \"tAsc\": 2330,\n      \"tDes\": -1550,\n      \"tLGap\": 0,\n      \"wAsc\": 2330,\n      \"wDes\": 1550,\n      \"xH\": 950,\n      \"capH\": 1384,\n      \"yMin\": -1345,\n      \"yMax\": 2097,\n      \"hAsc\": 2330,\n      \"hDes\": -1550,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Viaoda Libre\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1051,\n      \"des\": -360,\n      \"tAsc\": 1051,\n      \"tDes\": -360,\n      \"tLGap\": 0,\n      \"wAsc\": 1051,\n      \"wDes\": 360,\n      \"xH\": 467,\n      \"capH\": 740,\n      \"yMin\": -360,\n      \"yMax\": 1051,\n      \"hAsc\": 1051,\n      \"hDes\": -360,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vibes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1105,\n      \"des\": -680,\n      \"tAsc\": 1105,\n      \"tDes\": -680,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 680,\n      \"xH\": 500,\n      \"capH\": 38,\n      \"yMin\": -680,\n      \"yMax\": 1105,\n      \"hAsc\": 1105,\n      \"hDes\": -680,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vibur\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1960,\n      \"des\": -792,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1960,\n      \"wDes\": 792,\n      \"yMin\": -792,\n      \"yMax\": 1960,\n      \"hAsc\": 1960,\n      \"hDes\": -792,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Victor Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1100,\n      \"des\": -250,\n      \"tAsc\": 1100,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1306,\n      \"wDes\": 529,\n      \"xH\": 618,\n      \"capH\": 800,\n      \"yMin\": -529,\n      \"yMax\": 1306,\n      \"hAsc\": 1100,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vidaloka\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1927,\n      \"des\": -560,\n      \"tAsc\": 1927,\n      \"tDes\": -560,\n      \"tLGap\": 0,\n      \"wAsc\": 1927,\n      \"wDes\": 560,\n      \"xH\": 1004,\n      \"capH\": 1427,\n      \"yMin\": -560,\n      \"yMax\": 1927,\n      \"hAsc\": 1927,\n      \"hDes\": -560,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Viga\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -329,\n      \"tAsc\": 1015,\n      \"tDes\": -329,\n      \"tLGap\": 0,\n      \"wAsc\": 1015,\n      \"wDes\": 329,\n      \"xH\": 571,\n      \"capH\": 712,\n      \"yMin\": -329,\n      \"yMax\": 1015,\n      \"hAsc\": 1015,\n      \"hDes\": -329,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vina Sans\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1045,\n      \"des\": -170,\n      \"tAsc\": 1045,\n      \"tDes\": -170,\n      \"tLGap\": 0,\n      \"wAsc\": 1063,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -200,\n      \"yMax\": 1063,\n      \"hAsc\": 1045,\n      \"hDes\": -170,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Voces\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1014,\n      \"des\": -335,\n      \"tAsc\": 1014,\n      \"tDes\": -335,\n      \"tLGap\": 0,\n      \"wAsc\": 1014,\n      \"wDes\": 335,\n      \"xH\": 520,\n      \"capH\": 700,\n      \"yMin\": -335,\n      \"yMax\": 1014,\n      \"hAsc\": 1014,\n      \"hDes\": -335,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Volkhov\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 971,\n      \"des\": -319,\n      \"tAsc\": 971,\n      \"tDes\": -319,\n      \"tLGap\": 0,\n      \"wAsc\": 971,\n      \"wDes\": 319,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -306,\n      \"yMax\": 970,\n      \"hAsc\": 971,\n      \"hDes\": -319,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vollkorn\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -441,\n      \"tAsc\": 952,\n      \"tDes\": -441,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 489,\n      \"xH\": 458,\n      \"capH\": 676,\n      \"yMin\": -280,\n      \"yMax\": 1078,\n      \"hAsc\": 952,\n      \"hDes\": -441,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vollkorn SC\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 600, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 952,\n      \"des\": -441,\n      \"tAsc\": 952,\n      \"tDes\": -441,\n      \"tLGap\": 0,\n      \"wAsc\": 1115,\n      \"wDes\": 489,\n      \"xH\": 458,\n      \"capH\": 676,\n      \"yMin\": -280,\n      \"yMax\": 1078,\n      \"hAsc\": 952,\n      \"hDes\": -441,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Voltaire\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -531,\n      \"tAsc\": 2020,\n      \"tDes\": -531,\n      \"tLGap\": 0,\n      \"wAsc\": 2571,\n      \"wDes\": 580,\n      \"xH\": 1062,\n      \"capH\": 1593,\n      \"yMin\": -572,\n      \"yMax\": 2412,\n      \"hAsc\": 2020,\n      \"hDes\": -531,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"VT323\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1040,\n      \"wDes\": 240,\n      \"xH\": 400,\n      \"capH\": 560,\n      \"yMin\": -240,\n      \"yMax\": 1040,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Vujahday Script\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -410,\n      \"tAsc\": 950,\n      \"tDes\": -410,\n      \"tLGap\": 0,\n      \"wAsc\": 1144,\n      \"wDes\": 678,\n      \"xH\": 360,\n      \"capH\": 640,\n      \"yMin\": -678,\n      \"yMax\": 1144,\n      \"hAsc\": 950,\n      \"hDes\": -410,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Waiting for the Sunrise\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1146,\n      \"des\": -547,\n      \"tAsc\": 1146,\n      \"tDes\": -547,\n      \"tLGap\": 0,\n      \"wAsc\": 1146,\n      \"wDes\": 547,\n      \"xH\": 570,\n      \"capH\": 755,\n      \"yMin\": -547,\n      \"yMax\": 1146,\n      \"hAsc\": 1146,\n      \"hDes\": -547,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wallpoet\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 806,\n      \"des\": -196,\n      \"tAsc\": 806,\n      \"tDes\": -196,\n      \"tLGap\": 0,\n      \"wAsc\": 806,\n      \"wDes\": 196,\n      \"xH\": 440,\n      \"capH\": 575,\n      \"yMin\": -196,\n      \"yMax\": 806,\n      \"hAsc\": 806,\n      \"hDes\": -196,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Walter Turncoat\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 1078,\n      \"des\": -323,\n      \"tAsc\": 544,\n      \"tDes\": -64,\n      \"tLGap\": 57,\n      \"wAsc\": 1078,\n      \"wDes\": 323,\n      \"xH\": 559,\n      \"capH\": 752,\n      \"yMin\": -322,\n      \"yMax\": 1078,\n      \"hAsc\": 1078,\n      \"hDes\": -323,\n      \"lGap\": 29\n    }\n  },\n  {\n    \"family\": \"Warnes\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 994,\n      \"des\": -310,\n      \"tAsc\": 994,\n      \"tDes\": -310,\n      \"tLGap\": 0,\n      \"wAsc\": 1095,\n      \"wDes\": 359,\n      \"xH\": 540,\n      \"capH\": 710,\n      \"yMin\": -359,\n      \"yMax\": 1095,\n      \"hAsc\": 994,\n      \"hDes\": -310,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Water Brush\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1000,\n      \"des\": -450,\n      \"tAsc\": 1000,\n      \"tDes\": -450,\n      \"tLGap\": 0,\n      \"wAsc\": 1165,\n      \"wDes\": 475,\n      \"xH\": 375,\n      \"capH\": 750,\n      \"yMin\": -472,\n      \"yMax\": 1152,\n      \"hAsc\": 1000,\n      \"hDes\": -450,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Waterfall\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -280,\n      \"tAsc\": 880,\n      \"tDes\": -280,\n      \"tLGap\": 0,\n      \"wAsc\": 858,\n      \"wDes\": 563,\n      \"xH\": 215,\n      \"capH\": 580,\n      \"yMin\": -563,\n      \"yMax\": 858,\n      \"hAsc\": 880,\n      \"hDes\": -280,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wavefont\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1200,\n      \"des\": -200,\n      \"tAsc\": 1200,\n      \"tDes\": -200,\n      \"tLGap\": 0,\n      \"wAsc\": 1200,\n      \"wDes\": 200,\n      \"xH\": 0,\n      \"capH\": 0,\n      \"yMin\": -90,\n      \"yMax\": 1270,\n      \"hAsc\": 1200,\n      \"hDes\": -200,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont JP N\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WDXL Lubrifont TC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 945,\n      \"des\": -235,\n      \"tAsc\": 945,\n      \"tDes\": -235,\n      \"tLGap\": 0,\n      \"wAsc\": 1168,\n      \"wDes\": 235,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -220,\n      \"yMax\": 1168,\n      \"hAsc\": 945,\n      \"hDes\": -235,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wellfleet\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2020,\n      \"des\": -540,\n      \"tAsc\": 2020,\n      \"tDes\": -540,\n      \"tLGap\": 0,\n      \"wAsc\": 2020,\n      \"wDes\": 540,\n      \"xH\": 747,\n      \"capH\": 1535,\n      \"yMin\": -540,\n      \"yMax\": 2020,\n      \"hAsc\": 2020,\n      \"hDes\": -540,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wendy One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 819,\n      \"des\": -236,\n      \"tAsc\": 819,\n      \"tDes\": -236,\n      \"tLGap\": 0,\n      \"wAsc\": 819,\n      \"wDes\": 236,\n      \"xH\": 474,\n      \"capH\": 606,\n      \"yMin\": -236,\n      \"yMax\": 819,\n      \"hAsc\": 819,\n      \"hDes\": -236,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Whisper\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -400,\n      \"tAsc\": 880,\n      \"tDes\": -400,\n      \"tLGap\": 0,\n      \"wAsc\": 930,\n      \"wDes\": 407,\n      \"xH\": 300,\n      \"capH\": 620,\n      \"yMin\": -407,\n      \"yMax\": 923,\n      \"hAsc\": 880,\n      \"hDes\": -400,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"WindSong\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400, 500],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -515,\n      \"tAsc\": 890,\n      \"tDes\": -515,\n      \"tLGap\": 0,\n      \"wAsc\": 1930,\n      \"wDes\": 745,\n      \"xH\": 268,\n      \"capH\": 705,\n      \"yMin\": -745,\n      \"yMax\": 1297,\n      \"hAsc\": 890,\n      \"hDes\": -515,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Winky Rough\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -247,\n      \"yMax\": 935,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Winky Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1015,\n      \"des\": -315,\n      \"tAsc\": 1015,\n      \"tDes\": -315,\n      \"tLGap\": 0,\n      \"wAsc\": 1057,\n      \"wDes\": 430,\n      \"xH\": 500,\n      \"capH\": 667,\n      \"yMin\": -249,\n      \"yMax\": 941,\n      \"hAsc\": 1015,\n      \"hDes\": -315,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wire One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 890,\n      \"des\": -210,\n      \"tAsc\": 890,\n      \"tDes\": -210,\n      \"tLGap\": 0,\n      \"wAsc\": 890,\n      \"wDes\": 210,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -210,\n      \"yMax\": 889,\n      \"hAsc\": 890,\n      \"hDes\": -210,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wittgenstein\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1065,\n      \"des\": -435,\n      \"tAsc\": 1065,\n      \"tDes\": -435,\n      \"tLGap\": 0,\n      \"wAsc\": 1180,\n      \"wDes\": 435,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1019,\n      \"hAsc\": 1065,\n      \"hDes\": -435,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wix Madefor Display\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -252,\n      \"tAsc\": 1008,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1176,\n      \"wDes\": 307,\n      \"xH\": 492,\n      \"capH\": 715,\n      \"yMin\": -270,\n      \"yMax\": 1109,\n      \"hAsc\": 1008,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Wix Madefor Text\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700],\n      [0, 800],\n      [1, 800]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1008,\n      \"des\": -252,\n      \"tAsc\": 1008,\n      \"tDes\": -252,\n      \"tLGap\": 0,\n      \"wAsc\": 1176,\n      \"wDes\": 307,\n      \"xH\": 492,\n      \"capH\": 715,\n      \"yMin\": -270,\n      \"yMax\": 1109,\n      \"hAsc\": 1008,\n      \"hDes\": -252,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Work Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -243,\n      \"tAsc\": 930,\n      \"tDes\": -243,\n      \"tLGap\": 0,\n      \"wAsc\": 1105,\n      \"wDes\": 343,\n      \"xH\": 500,\n      \"capH\": 660,\n      \"yMin\": -337,\n      \"yMax\": 1100,\n      \"hAsc\": 930,\n      \"hDes\": -243,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Workbench\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 896,\n      \"des\": -128,\n      \"tAsc\": 896,\n      \"tDes\": -128,\n      \"tLGap\": 0,\n      \"wAsc\": 1024,\n      \"wDes\": 256,\n      \"xH\": 640,\n      \"capH\": 896,\n      \"yMin\": -256,\n      \"yMax\": 1024,\n      \"hAsc\": 896,\n      \"hDes\": -128,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Xanh Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 970,\n      \"des\": -220,\n      \"tAsc\": 970,\n      \"tDes\": -220,\n      \"tLGap\": 0,\n      \"wAsc\": 1100,\n      \"wDes\": 220,\n      \"xH\": 540,\n      \"capH\": 740,\n      \"yMin\": -213,\n      \"yMax\": 1100,\n      \"hAsc\": 970,\n      \"hDes\": -220,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yaldevi\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1060,\n      \"des\": -256,\n      \"tAsc\": 1060,\n      \"tDes\": -256,\n      \"tLGap\": 0,\n      \"wAsc\": 1110,\n      \"wDes\": 450,\n      \"xH\": 570,\n      \"capH\": 769,\n      \"yMin\": -323,\n      \"yMax\": 1086,\n      \"hAsc\": 1060,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yanone Kaffeesatz\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 735,\n      \"des\": -200,\n      \"tAsc\": 735,\n      \"tDes\": -200,\n      \"tLGap\": 57,\n      \"wAsc\": 1063,\n      \"wDes\": 279,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -263,\n      \"yMax\": 1072,\n      \"hAsc\": 735,\n      \"hDes\": -200,\n      \"lGap\": 57\n    }\n  },\n  {\n    \"family\": \"Yantramanav\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1923,\n      \"des\": -733,\n      \"tAsc\": 1923,\n      \"tDes\": -733,\n      \"tLGap\": 0,\n      \"wAsc\": 1923,\n      \"wDes\": 733,\n      \"xH\": 986,\n      \"capH\": 1279,\n      \"yMin\": -676,\n      \"yMax\": 1911,\n      \"hAsc\": 1923,\n      \"hDes\": -733,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 12\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 910,\n      \"des\": -130,\n      \"tAsc\": 910,\n      \"tDes\": -130,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": 0,\n      \"yMax\": 780,\n      \"hAsc\": 910,\n      \"hDes\": -130,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 12 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1040,\n      \"asc\": 910,\n      \"des\": -130,\n      \"tAsc\": 910,\n      \"tDes\": -130,\n      \"tLGap\": 0,\n      \"wAsc\": 915,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -130,\n      \"yMax\": 915,\n      \"hAsc\": 910,\n      \"hDes\": -130,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 20\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 880,\n      \"des\": -80,\n      \"tAsc\": 880,\n      \"tDes\": -80,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": 0,\n      \"yMax\": 800,\n      \"hAsc\": 880,\n      \"hDes\": -80,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yarndings 20 Charted\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 960,\n      \"asc\": 880,\n      \"des\": -80,\n      \"tAsc\": 880,\n      \"tDes\": -80,\n      \"tLGap\": 0,\n      \"wAsc\": 883,\n      \"wDes\": 200,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -80,\n      \"yMax\": 883,\n      \"hAsc\": 880,\n      \"hDes\": -80,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yatra One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 991,\n      \"des\": -487,\n      \"tAsc\": 991,\n      \"tDes\": -487,\n      \"tLGap\": 0,\n      \"wAsc\": 991,\n      \"wDes\": 487,\n      \"xH\": 460,\n      \"capH\": 679,\n      \"yMin\": -487,\n      \"yMax\": 991,\n      \"hAsc\": 991,\n      \"hDes\": -487,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yellowtail\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 1990,\n      \"des\": -617,\n      \"tAsc\": 1638,\n      \"tDes\": -410,\n      \"tLGap\": 184,\n      \"wAsc\": 1990,\n      \"wDes\": 617,\n      \"yMin\": -617,\n      \"yMax\": 1990,\n      \"hAsc\": 1990,\n      \"hDes\": -617,\n      \"lGap\": 184\n    }\n  },\n  {\n    \"family\": \"Yeon Sung\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 800,\n      \"des\": -200,\n      \"tAsc\": 800,\n      \"tDes\": -200,\n      \"tLGap\": 250,\n      \"wAsc\": 830,\n      \"wDes\": 323,\n      \"xH\": 446,\n      \"capH\": 659,\n      \"yMin\": -323,\n      \"yMax\": 830,\n      \"hAsc\": 800,\n      \"hDes\": -200,\n      \"lGap\": 250\n    }\n  },\n  {\n    \"family\": \"Yeseva One\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 915,\n      \"des\": -240,\n      \"tAsc\": 915,\n      \"tDes\": -240,\n      \"tLGap\": 0,\n      \"wAsc\": 1079,\n      \"wDes\": 310,\n      \"xH\": 500,\n      \"capH\": 700,\n      \"yMin\": -310,\n      \"yMax\": 1079,\n      \"hAsc\": 915,\n      \"hDes\": -240,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yesteryear\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 2048,\n      \"asc\": 2001,\n      \"des\": -1004,\n      \"tAsc\": 2001,\n      \"tDes\": -1004,\n      \"tLGap\": 0,\n      \"wAsc\": 2001,\n      \"wDes\": 1004,\n      \"xH\": 625,\n      \"capH\": 1581,\n      \"yMin\": -1004,\n      \"yMax\": 2001,\n      \"hAsc\": 2001,\n      \"hDes\": -1004,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yomogi\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 475,\n      \"capH\": 720,\n      \"yMin\": -270,\n      \"yMax\": 1043,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Young Serif\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1046,\n      \"des\": -366,\n      \"tAsc\": 1046,\n      \"tDes\": -366,\n      \"tLGap\": 0,\n      \"wAsc\": 1302,\n      \"wDes\": 366,\n      \"xH\": 500,\n      \"capH\": 750,\n      \"yMin\": -304,\n      \"yMax\": 1302,\n      \"hAsc\": 1046,\n      \"hDes\": -366,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yrsa\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 728,\n      \"des\": -272,\n      \"tAsc\": 728,\n      \"tDes\": -272,\n      \"tLGap\": 218,\n      \"wAsc\": 971,\n      \"wDes\": 422,\n      \"xH\": 413,\n      \"capH\": 568,\n      \"yMin\": -211,\n      \"yMax\": 925,\n      \"hAsc\": 728,\n      \"hDes\": -272,\n      \"lGap\": 218\n    }\n  },\n  {\n    \"family\": \"Ysabeau\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau Infant\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau Office\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 100],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -291,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Ysabeau SC\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 100],\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1054,\n      \"des\": -289,\n      \"tAsc\": 1054,\n      \"tDes\": -289,\n      \"tLGap\": 0,\n      \"wAsc\": 1056,\n      \"wDes\": 311,\n      \"xH\": 414,\n      \"capH\": 658,\n      \"yMin\": -290,\n      \"yMax\": 1024,\n      \"hAsc\": 1054,\n      \"hDes\": -289,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Boku\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -334,\n      \"yMax\": 936,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Hentaigana Akari\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -232,\n      \"yMax\": 970,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Hentaigana Akebono\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -232,\n      \"yMax\": 970,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Mai\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -255,\n      \"yMax\": 936,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yuji Syuku\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 545,\n      \"capH\": 761,\n      \"yMin\": -190,\n      \"yMax\": 881,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Yusei Magic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 510,\n      \"capH\": 760,\n      \"yMin\": -233,\n      \"yMax\": 1047,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zain\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 700, 800, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [0, 800],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 800,\n      \"asc\": 869,\n      \"des\": -459,\n      \"tAsc\": 869,\n      \"tDes\": -459,\n      \"tLGap\": 0,\n      \"wAsc\": 869,\n      \"wDes\": 459,\n      \"xH\": 480,\n      \"capH\": 699,\n      \"yMin\": -459,\n      \"yMax\": 869,\n      \"hAsc\": 869,\n      \"hDes\": -459,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans Expanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zalando Sans SemiExpanded\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 200],\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800],\n      [0, 900],\n      [1, 200],\n      [1, 300],\n      [1, 400],\n      [1, 500],\n      [1, 600],\n      [1, 700],\n      [1, 800],\n      [1, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 964,\n      \"des\": -250,\n      \"tAsc\": 964,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1175,\n      \"wDes\": 255,\n      \"xH\": 514,\n      \"capH\": 714,\n      \"yMin\": -255,\n      \"yMax\": 1119,\n      \"hAsc\": 964,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL KuaiLe\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 913,\n      \"wDes\": 152,\n      \"xH\": 512,\n      \"capH\": 700,\n      \"yMin\": -152,\n      \"yMax\": 913,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL QingKe HuangYou\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 884,\n      \"wDes\": 187,\n      \"xH\": 485,\n      \"capH\": 710,\n      \"yMin\": -187,\n      \"yMax\": 884,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"ZCOOL XiaoWei\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 210,\n      \"xH\": 470,\n      \"capH\": 660,\n      \"yMin\": -210,\n      \"yMax\": 859,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Antique\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 473,\n      \"capH\": 726,\n      \"yMin\": -283,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Antique Soft\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 473,\n      \"capH\": 726,\n      \"yMin\": -283,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Dots\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 930,\n      \"des\": -270,\n      \"tAsc\": 930,\n      \"tDes\": -270,\n      \"tLGap\": 0,\n      \"wAsc\": 960,\n      \"wDes\": 300,\n      \"xH\": 515,\n      \"capH\": 715,\n      \"yMin\": -225,\n      \"yMax\": 960,\n      \"hAsc\": 930,\n      \"hDes\": -270,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kaku Gothic Antique\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kaku Gothic New\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Kurenaido\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 406,\n      \"capH\": 700,\n      \"yMin\": -253,\n      \"yMax\": 959,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Loop\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 850,\n      \"des\": -275,\n      \"tAsc\": 850,\n      \"tDes\": -275,\n      \"tLGap\": 0,\n      \"wAsc\": 850,\n      \"wDes\": 275,\n      \"xH\": 477,\n      \"capH\": 690,\n      \"yMin\": -271,\n      \"yMax\": 835,\n      \"hAsc\": 850,\n      \"hDes\": -275,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Maru Gothic\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"weights\": [300, 400, 500, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 479,\n      \"capH\": 700,\n      \"yMin\": -216,\n      \"yMax\": 960,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Old Mincho\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 500, 600, 700, 900],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 900]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 1160,\n      \"des\": -288,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1160,\n      \"wDes\": 288,\n      \"xH\": 430,\n      \"capH\": 726,\n      \"yMin\": -303,\n      \"yMax\": 965,\n      \"hAsc\": 1160,\n      \"hDes\": -288,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zen Tokyo Zoo\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 950,\n      \"des\": -250,\n      \"tAsc\": 950,\n      \"tDes\": -250,\n      \"tLGap\": 0,\n      \"wAsc\": 1075,\n      \"wDes\": 250,\n      \"xH\": 402,\n      \"capH\": 804,\n      \"yMin\": -230,\n      \"yMax\": 1074,\n      \"hAsc\": 950,\n      \"hDes\": -250,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zeyada\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1024,\n      \"asc\": 934,\n      \"des\": -680,\n      \"tAsc\": 934,\n      \"tDes\": -680,\n      \"tLGap\": 0,\n      \"wAsc\": 934,\n      \"wDes\": 680,\n      \"xH\": 312,\n      \"capH\": 602,\n      \"yMin\": -680,\n      \"yMax\": 934,\n      \"hAsc\": 934,\n      \"hDes\": -680,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zhi Mang Xing\",\n    \"fallbacks\": [\"cursive\"],\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 880,\n      \"des\": -120,\n      \"tAsc\": 880,\n      \"tDes\": -120,\n      \"tLGap\": 0,\n      \"wAsc\": 1000,\n      \"wDes\": 383,\n      \"xH\": 496,\n      \"capH\": 750,\n      \"yMin\": -383,\n      \"yMax\": 912,\n      \"hAsc\": 880,\n      \"hDes\": -120,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zilla Slab\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -256,\n      \"tAsc\": 787,\n      \"tDes\": -213,\n      \"tLGap\": 200,\n      \"wAsc\": 944,\n      \"wDes\": 256,\n      \"xH\": 445,\n      \"capH\": 650,\n      \"yMin\": -231,\n      \"yMax\": 883,\n      \"hAsc\": 944,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  },\n  {\n    \"family\": \"Zilla Slab Highlight\",\n    \"fallbacks\": [\"serif\"],\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ],\n    \"service\": \"fonts.google.com\",\n    \"metrics\": {\n      \"upm\": 1000,\n      \"asc\": 944,\n      \"des\": -256,\n      \"tAsc\": 787,\n      \"tDes\": -213,\n      \"tLGap\": 200,\n      \"wAsc\": 944,\n      \"wDes\": 256,\n      \"xH\": 445,\n      \"capH\": 650,\n      \"yMin\": -252,\n      \"yMax\": 918,\n      \"hAsc\": 944,\n      \"hDes\": -256,\n      \"lGap\": 0\n    }\n  }\n]\n"
  },
  {
    "path": "packages/fonts/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\nexport * from './utils';\n"
  },
  {
    "path": "packages/fonts/src/test/curatedFonts.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readFileSync } from 'fs';\nimport { resolve } from 'path';\n\n/**\n * Internal dependencies\n */\nimport { CURATED_FONT_NAMES } from '../constants';\nimport type { Font } from '../types';\n\ndescribe('Curated fonts', () => {\n  const fonts: Font[] = JSON.parse(\n    readFileSync(\n      resolve(process.cwd(), 'packages/fonts/src/fonts.json'),\n      'utf8'\n    )\n  ) as Font[];\n  const fontNames = fonts.map(({ family }) => family);\n\n  // @see https://github.com/googleforcreators/web-stories-wp/issues/3880\n  it.each(CURATED_FONT_NAMES)(\n    '%s font should exist in global fonts list',\n    (fontName) => {\n      expect(fontNames).toContain(fontName);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/fonts/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface Font {\n  family: string;\n  variants?: Array<[number, number]>;\n}\n"
  },
  {
    "path": "packages/fonts/src/utils/getFontCSS.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Get the CSS font format for a given font URL.\n *\n * @param src Font URL.\n * @return Font format string or null if the font is unsupported.\n */\nfunction getFontFormat(src: string): string | null {\n  const fileExtension = src.split(/[#?]/)?.[0]?.split('.')?.pop()?.trim();\n\n  switch (fileExtension) {\n    case 'woff':\n    case 'woff2':\n      return fileExtension;\n    case 'ttf':\n      return 'truetype';\n    case 'otf':\n      return 'opentype';\n    default:\n      return null;\n  }\n}\n\n/**\n * Get the inline stylesheet for a specific font family.\n *\n * @param name Font family.\n * @param src Font URL.\n * @return Stylesheet or null if the font has an unsupported format.\n */\nfunction getFontCSS(name: string, src: string): string | null {\n  const format = getFontFormat(src);\n\n  if (!format) {\n    return null;\n  }\n\n  return `@font-face {\n    font-family: \"${name}\";\n    src: url('${src}') format('${format}');\n    font-weight: normal;\n    font-display:swap;\n  }`;\n}\n\nexport default getFontCSS;\n"
  },
  {
    "path": "packages/fonts/src/utils/getGoogleFontURL.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Font } from '../types';\n\n/**\n * Given a list of Google fonts, returns a URL to embed them.\n *\n * Uses the given list of font variants (axis tuples) to assemble the\n * axis tag list and axis tuple list that Google Fonts expects.\n *\n * @see https://developers.google.com/fonts/docs/css2\n * @param fonts List of font objects.\n * @param [display] Valid font-display value, e.g. 'swap' or 'auto'. Default 'swap'.\n * @return Google Fonts embed URL.\n */\nfunction getGoogleFontURL(fonts: Font[], display: 'swap' | 'auto' = 'swap') {\n  const url = new URL('https://fonts.googleapis.com/css2');\n  url.searchParams.append('display', display);\n\n  for (const { family: familyName, variants = [] } of fonts) {\n    // [ [ 1, 400 ], [ 0, 700 ] ] -> [ ital, wght ]\n    const axes: string[] = variants\n      .reduce(\n        (acc, [fontStyle, fontWeight]) => {\n          // Uses axis names as listed on https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts.\n          if (fontStyle === 1 && !acc.includes('ital')) {\n            acc.push('ital');\n          }\n          if (fontWeight && fontWeight !== 400 && !acc.includes('wght')) {\n            acc.push('wght');\n          }\n          return acc;\n        },\n        [] as Array<'ital' | 'wght'>\n      )\n      .sort(); // Need to be sorted alphabetically.\n\n    let family = familyName;\n\n    const axisTagList = axes.join(',');\n\n    // [ ital, wght ] -> Roboto:ital,wght\n    if (axisTagList) {\n      family += ':' + axisTagList;\n    }\n\n    const axisTuples = [...variants]\n      .sort((a, b) => {\n        if (a[0] < b[0]) {\n          return -1;\n        }\n\n        if (a[0] > b[0]) {\n          return 1;\n        }\n\n        return a[1] - b[1];\n      })\n      .map(([fontStyle, fontWeight]) => {\n        const tuple = [];\n        if (axes.includes('ital')) {\n          tuple.push(fontStyle);\n        }\n        if (axes.includes('wght')) {\n          tuple.push(fontWeight);\n        }\n        return tuple;\n      });\n\n    // [ [ 1, 400 ], [ 0, 700 ] ] -> 1,400;0,700\n    const axisTupleList = axisTuples.join(';');\n\n    const onlyRegularVariant = axisTupleList === '400';\n\n    if (axisTupleList && !onlyRegularVariant) {\n      family += '@' + axisTupleList;\n    }\n\n    url.searchParams.append('family', family);\n  }\n\n  return decodeURI(url.toString());\n}\n\nexport default getGoogleFontURL;\n"
  },
  {
    "path": "packages/fonts/src/utils/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as getFontCSS } from './getFontCSS';\nexport { default as getGoogleFontURL } from './getGoogleFontURL';\n"
  },
  {
    "path": "packages/fonts/src/utils/test/getFontCSS.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFontCSS from '../getFontCSS';\n\ndescribe('getFontCSS', () => {\n  it('should not return CSS for unsupported font', () => {\n    const actual = getFontCSS('Foo Regular', 'https://example.com/font.eot');\n    expect(actual).toBeNull();\n  });\n\n  it('should return CSS for woff font', () => {\n    const actual = getFontCSS('Foo Regular', 'https://example.com/font.woff');\n    expect(actual).toContain('font-family: \"Foo Regular\";');\n    expect(actual).toContain(\n      \"src: url('https://example.com/font.woff') format('woff');\"\n    );\n  });\n\n  it('should return CSS for woff2 font', () => {\n    const actual = getFontCSS('Foo Regular', 'https://example.com/font.woff2');\n    expect(actual).toContain('font-family: \"Foo Regular\";');\n    expect(actual).toContain(\n      \"src: url('https://example.com/font.woff2') format('woff2');\"\n    );\n  });\n\n  it('should return CSS for ttf font', () => {\n    const actual = getFontCSS('Foo Regular', 'https://example.com/font.ttf');\n    expect(actual).toContain('font-family: \"Foo Regular\";');\n    expect(actual).toContain(\n      \"src: url('https://example.com/font.ttf') format('truetype');\"\n    );\n  });\n\n  it('should return CSS for otf font', () => {\n    const actual = getFontCSS('Foo Regular', 'https://example.com/font.otf');\n    expect(actual).toContain('font-family: \"Foo Regular\";');\n    expect(actual).toContain(\n      \"src: url('https://example.com/font.otf') format('opentype');\"\n    );\n  });\n});\n"
  },
  {
    "path": "packages/fonts/src/utils/test/getGoogleFontURL.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getGoogleFontURL from '../getGoogleFontURL';\n\ndescribe('getGoogleFontURL', () => {\n  it('should produce valid URLs', () => {\n    const roboto_400 = { family: 'Roboto', variants: [[0, 400]] };\n    const roboto_400_400i = {\n      family: 'Roboto',\n      variants: [\n        [0, 400],\n        [1, 400],\n      ],\n    };\n    const roboto_100_400 = {\n      family: 'Roboto',\n      variants: [\n        [0, 100],\n        [0, 400],\n      ],\n    };\n\n    const roboto_400_700 = {\n      family: 'Roboto',\n      variants: [\n        [0, 400],\n        [0, 700],\n      ],\n    };\n\n    const lato_300i_900i = {\n      family: 'Lato',\n      variants: [\n        [1, 300],\n        [1, 900],\n      ],\n    };\n    const lato_900i_300i = {\n      family: 'Lato',\n      variants: [\n        [1, 900],\n        [1, 300],\n      ],\n    };\n    const architects_daughter = {\n      family: 'Architects Daughter',\n    };\n    const roboto_condensed_all = {\n      family: 'Roboto Condensed',\n      variants: [\n        [0, 300],\n        [1, 300],\n        [0, 400],\n        [1, 400],\n        [0, 700],\n        [1, 700],\n      ],\n    };\n\n    expect(getGoogleFontURL([roboto_400])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto'\n    );\n    expect(getGoogleFontURL([roboto_400_400i])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Aital%400%3B1'\n    );\n    expect(getGoogleFontURL([roboto_400_700])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Awght%40400%3B700'\n    );\n    expect(getGoogleFontURL([roboto_100_400])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Awght%40100%3B400'\n    );\n    expect(getGoogleFontURL([lato_300i_900i])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Lato%3Aital%2Cwght%401%2C300%3B1%2C900'\n    );\n    expect(getGoogleFontURL([lato_900i_300i])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Lato%3Aital%2Cwght%401%2C300%3B1%2C900'\n    );\n    expect(getGoogleFontURL([roboto_100_400, lato_300i_900i])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Awght%40100%3B400&family=Lato%3Aital%2Cwght%401%2C300%3B1%2C900'\n    );\n    expect(getGoogleFontURL([architects_daughter])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Architects+Daughter'\n    );\n    expect(getGoogleFontURL([roboto_condensed_all])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto+Condensed%3Aital%2Cwght%400%2C300%3B0%2C400%3B0%2C700%3B1%2C300%3B1%2C400%3B1%2C700'\n    );\n  });\n\n  it('should use provided font-display parameter', () => {\n    const roboto_400 = { family: 'Roboto', variants: [[0, 400]] };\n    expect(getGoogleFontURL([roboto_400])).toBe(\n      'https://fonts.googleapis.com/css2?display=swap&family=Roboto'\n    );\n    expect(getGoogleFontURL([roboto_400], 'auto')).toBe(\n      'https://fonts.googleapis.com/css2?display=auto&family=Roboto'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/fonts/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDirs\": [\"src\", \"scripts\"],\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\", \"scripts/**/*\"]\n}\n"
  },
  {
    "path": "packages/glider/README.md",
    "content": "# Glider\n\nPatched version of [Glider.js](https://github.com/NickPiscitelli/Glider.js).\n"
  },
  {
    "path": "packages/glider/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/glider\",\n  \"description\": \"Patched version of Glider.js\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"glider\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/glider/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/glider\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.ts\",\n  \"dependencies\": {\n    \"glider-js\": \"^1.7.9\"\n  },\n  \"devDependencies\": {\n    \"@types/glider-js\" : \"^1.7.12\"\n  }\n}\n"
  },
  {
    "path": "packages/glider/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport Glider from 'glider-js';\nimport 'glider-js/glider.css';\n\n/**\n * Override to add basic support for the nav arrows for RTL\n *\n * Glider-JS doesn't support RTL at the moment, this is to add basic\n * functioning support for the nav arrows as otherwise the nav arrows\n * become useless on RTL sites.\n *\n * @todo Maybe replace glider-js with other lightweight lib which has RTL support. or Replace it with 'amp-carousel' once we have the support.\n * @param slideIndex Slide arrow string based on action.\n * @param isActuallyDotIndex   Is dot navigation action.\n * @param e     Event object.\n * @return Navigation done.\n */\nGlider.prototype.scrollItem = function (\n  slideIndex: number,\n  isActuallyDotIndex: boolean,\n  e: Event\n) {\n  // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Workaround\n  // @ts-ignore\n  if (e === undefined && isActuallyDotIndex?.target) {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Workaround\n    // @ts-ignore\n    e = isActuallyDotIndex;\n    isActuallyDotIndex = false;\n  }\n\n  if (e === undefined) {\n    // Somehow we ended up triggering this function twice. Abort to prevent scrolling back and forth.\n    return false;\n  }\n\n  if (e) {\n    e.preventDefault();\n  }\n\n  // Somehow slidesToScroll and slidesToShow can end up being 0.\n  this.opt.slidesToScroll = Math.max(1, this.opt.slidesToScroll as number);\n  this.opt.slidesToShow = Math.max(1, this.opt.slidesToShow as number);\n  // This will also cause this.itemWidth to be Infinity because division by zero returns Infinity in JS.\n  // Update this.itemWidth with actual value in this case.\n  if (this.itemWidth === Number.POSITIVE_INFINITY) {\n    // It's a sibling.\n    const carouselWrapper = (\n      e.target as HTMLElement\n    ).parentElement?.querySelector(\n      '.web-stories-list__carousel'\n    ) as HTMLElement;\n    const itemStyle = window.getComputedStyle(\n      carouselWrapper.querySelector(\n        '.web-stories-list__story'\n      ) as unknown as HTMLElement\n    );\n\n    this.itemWidth =\n      Number.parseFloat(itemStyle.width) +\n      (Number.parseFloat(itemStyle.marginLeft) +\n        Number.parseFloat(itemStyle.marginRight));\n  }\n\n  const originalSlide = slideIndex;\n  ++this.animate_id;\n\n  if (isActuallyDotIndex === true) {\n    slideIndex = slideIndex * this.containerWidth;\n    slideIndex = Math.round(slideIndex / this.itemWidth) * this.itemWidth;\n  } else {\n    if (typeof slideIndex === 'string') {\n      const backwards = slideIndex === 'prev';\n\n      // use precise location if fractional slides are on\n      if (this.opt.slidesToScroll % 1 || this.opt.slidesToShow % 1) {\n        slideIndex = this.getCurrentSlide();\n      } else {\n        slideIndex = !isNaN(this.slide) ? this.slide : 0;\n      }\n\n      if (backwards) {\n        slideIndex -= this.opt.slidesToScroll;\n      } else {\n        slideIndex += this.opt.slidesToScroll;\n      }\n\n      if (this.opt.rewind) {\n        const scrollLeft = (this.ele as HTMLElement)\n          .scrollLeft as unknown as number;\n        slideIndex =\n          backwards && !scrollLeft\n            ? this.slides.length\n            : !backwards &&\n                scrollLeft + this.containerWidth >= Math.floor(this.trackWidth)\n              ? 0\n              : slideIndex;\n      }\n    }\n\n    slideIndex = Math.min(slideIndex, this.slides.length);\n\n    this.slide = slideIndex;\n    slideIndex = this.itemWidth * slideIndex;\n  }\n\n  this.scrollTo(\n    slideIndex,\n    this.opt.duration *\n      Math.abs((this.ele as HTMLElement).scrollLeft - slideIndex),\n    function (this: Glider<HTMLElement>) {\n      this.updateControls();\n      this.emit('animated', {\n        value: originalSlide,\n        type:\n          typeof originalSlide === 'string'\n            ? 'arrow'\n            : isActuallyDotIndex\n              ? 'dot'\n              : 'slide',\n      });\n    }\n  );\n\n  return false;\n};\n\nexport default Glider;\n"
  },
  {
    "path": "packages/glider/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [],\n   \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/i18n/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/i18n/README.md",
    "content": "# Internationalization (i18n)\n\nInternationalization utilities for client-side localization.\n\nThis package uses [@wordpress/i18n](https://github.com/WordPress/gutenberg/tree/master/packages/i18n) and exports the following functions.\n\n- `__`\n- `_x`\n- `_n`\n- `_nx`\n- `sprintf`\n- `TranslateWithMarkup`\n- `translateToExclusiveList`\n- `translateToInclusiveList`\n"
  },
  {
    "path": "packages/i18n/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/i18n\",\n  \"description\": \"Tiny i18n gettext helper package.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"i18n\",\n    \"gettext\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/i18n/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/i18n\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@googleforcreators/react\": \"*\",\n    \"@tannin/sprintf\": \"^1.3.3\",\n    \"prop-types\": \"^15.8.1\",\n    \"tannin\": \"^1.2.0\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/i18n.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport Tannin from 'tannin';\nimport type { TanninLocaleDomain } from 'tannin';\n\n/**\n * Internal dependencies\n */\nimport type { TranslatableText } from './types';\n\ninterface LocaleData {\n  locale_data: {\n    [key: string]: TanninLocaleDomain;\n  };\n}\n\nconst TEXT_DOMAIN = 'web-stories';\n\nconst tannin = new Tannin({\n  [TEXT_DOMAIN]: {\n    '': {\n      plural_forms(n: number) {\n        return n === 1 ? 0 : 1;\n      },\n    },\n  },\n});\n\n/**\n * Merge locale data into the Tannin instance.\n *\n * @param data Locale data.\n */\nexport function setLocaleData(data: LocaleData) {\n  const translations =\n    data.locale_data['web-stories'] || data.locale_data.messages;\n\n  tannin.data[TEXT_DOMAIN] = {\n    ...tannin.data[TEXT_DOMAIN],\n    ...translations,\n    '': {\n      ...tannin.data[TEXT_DOMAIN][''],\n    },\n  };\n}\n\n/**\n * Retrieve the translation of the given text.\n *\n * @param text Text to translate.\n * @param [domain] Text domain. Unique identifier for retrieving translated strings.\n * @return Translated text.\n */\nexport function __<T extends string>(\n  text: T,\n  domain = TEXT_DOMAIN\n): TranslatableText<T> {\n  return tannin.dcnpgettext(domain, undefined, text) as TranslatableText<T>;\n}\n\n/**\n * Retrieve the translation of the given text with gettext context..\n *\n * @param text Text to translate.\n * @param context Context information for the translators.\n * @param [domain] Text domain. Unique identifier for retrieving translated strings.\n * @return Translated text.\n */\nexport function _x<T extends string>(\n  text: T,\n  context: string,\n  domain = TEXT_DOMAIN\n): TranslatableText<T> {\n  return tannin.dcnpgettext(domain, context, text) as TranslatableText<T>;\n}\n\n/**\n * Retrieve the translation of the given text with gettext context..\n *\n * @param singular The text to be used if the number is singular.\n * @param plural The text to be used if the number is plural.\n * @param number The number to compare against to use either the singular or plural form.\n * @param [domain] Text domain. Unique identifier for retrieving translated strings.\n * @return Translated text.\n */\nexport function _n<T extends string, P extends string>(\n  singular: T,\n  plural: P,\n  number: number,\n  domain = TEXT_DOMAIN\n): TranslatableText<T | P> {\n  return tannin.dcnpgettext(\n    domain,\n    undefined,\n    singular,\n    plural,\n    number\n  ) as TranslatableText<T | P>;\n}\n\n/**\n * Retrieve the translation of the given text with gettext context..\n *\n * @param singular The text to be used if the number is singular.\n * @param plural The text to be used if the number is plural.\n * @param number The number to compare against to use either the singular or plural form.\n * @param context Context information for the translators.\n * @param [domain] Text domain. Unique identifier for retrieving translated strings.\n * @return Translated text.\n */\nexport function _nx<T extends string, P extends string>(\n  singular: T,\n  plural: P,\n  number: number,\n  context: string,\n  domain = TEXT_DOMAIN\n): TranslatableText<T | P> {\n  return tannin.dcnpgettext(\n    domain,\n    context,\n    singular,\n    plural,\n    number\n  ) as TranslatableText<T | P>;\n}\n"
  },
  {
    "path": "packages/i18n/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nexport { default as translateToExclusiveList } from './translateToExclusiveList';\nexport { default as translateToInclusiveList } from './translateToInclusiveList';\nexport { default as TranslateWithMarkup } from './translateWithMarkup';\nexport { default as sprintf } from './sprintf';\nexport * from './i18n';\n"
  },
  {
    "path": "packages/i18n/src/sprintf.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport _sprintf from '@tannin/sprintf';\nimport type { SprintfArgs } from '@tannin/sprintf/types';\n\n/**\n * Internal dependencies\n */\nimport type { TranslatableText } from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- on purpose.\ntype DistributeSprintfArgs<T extends string> = T extends any\n  ? SprintfArgs<T>\n  : never;\n\nexport function sprintf<T extends string>(\n  format: T | TranslatableText<T>,\n  ...args: DistributeSprintfArgs<T>\n): string;\nexport function sprintf<T extends string>(\n  format: T | TranslatableText<T>,\n  args: DistributeSprintfArgs<T>\n): string;\n\n/**\n * Returns a formatted string.\n *\n * @param format The format of the string to generate.\n * @param args   Arguments to apply to the format.\n *\n * @see https://www.npmjs.com/package/@tannin/sprintf\n *\n * @return The formatted string.\n */\nexport default function sprintf<T extends string>(\n  format: T | TranslatableText<T>,\n  ...args: DistributeSprintfArgs<T>\n): string {\n  return _sprintf(format as T, ...args);\n}\n"
  },
  {
    "path": "packages/i18n/src/test/transformNode.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { transformNode } from '../transformNode';\n\ndescribe('transformNode', () => {\n  it('returns text content for text node', () => {\n    const actual = transformNode(document.createTextNode('Hello World'));\n    expect(actual).toBe('Hello World');\n  });\n\n  it('does not preserve node attributes', () => {\n    const node = document.createElement('div');\n    node.setAttribute('id', 'foo');\n    node.setAttribute('class', 'bar');\n    node.textContent = 'Hello World';\n    const actual = renderToStaticMarkup(transformNode(node));\n    expect(actual).toBe('<div>Hello World</div>');\n  });\n\n  it('does transform children recursively', () => {\n    const node = document.createElement('div');\n    const p = document.createElement('p');\n    const span = document.createElement('span');\n    span.textContent = 'Hello World';\n    p.appendChild(span);\n    node.appendChild(p);\n\n    const actual = renderToStaticMarkup(transformNode(node));\n    expect(actual).toBe('<div><p><span>Hello World</span></p></div>');\n  });\n\n  it('replaces node with mapped component', () => {\n    const node = document.createElement('div');\n    node.setAttribute('id', 'foo');\n    node.setAttribute('class', 'bar');\n    node.textContent = 'Hello World';\n\n    const AwesomeComponent = ({ children }: { children?: ReactNode }) => {\n      return (\n        <div id=\"bar\" className=\"baz\">\n          {children}\n        </div>\n      );\n    };\n\n    const mapping = {\n      div: <AwesomeComponent />,\n    };\n\n    const actual = renderToStaticMarkup(transformNode(node, mapping));\n    expect(actual).toBe('<div id=\"bar\" class=\"baz\">Hello World</div>');\n  });\n\n  it('replaces nested node with mapped component', () => {\n    const node = document.createElement('div');\n    const p = document.createElement('p');\n    const span = document.createElement('span');\n    span.textContent = 'Hello World';\n    p.appendChild(span);\n    node.appendChild(p);\n\n    const AwesomeComponent = ({\n      children,\n    }: {\n      children?: ReactNode | undefined;\n    }) => {\n      return (\n        <span id=\"bar\" className=\"baz\">\n          <em>{children}</em>\n        </span>\n      );\n    };\n\n    const mapping = {\n      span: <AwesomeComponent />,\n    };\n\n    const actual = renderToStaticMarkup(transformNode(node, mapping));\n    expect(actual).toBe(\n      '<div><p><span id=\"bar\" class=\"baz\"><em>Hello World</em></span></p></div>'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/i18n/src/test/translateToExclusiveList.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport translateToExclusiveList from '../translateToExclusiveList';\n\ndescribe('translateToExclusiveList', () => {\n  it.each([\n    [[], ''],\n    [['one'], 'one'],\n    [['doctor', 'barnacle'], 'doctor or barnacle'],\n    [\n      ['apple', 'banana', 'mango', 'dragonfruit'],\n      'apple, banana, mango, or dragonfruit',\n    ],\n  ])('should translate as expected', (options, result) => {\n    expect(translateToExclusiveList(options)).toBe(result);\n  });\n});\n"
  },
  {
    "path": "packages/i18n/src/test/translateToInclusiveList.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport translateToInclusiveList from '../translateToInclusiveList';\n\ndescribe('translateToInclusiveList', () => {\n  it.each([\n    [[], ''],\n    [['one'], 'one'],\n    [['doctor', 'barnacle'], 'doctor and barnacle'],\n    [\n      ['apple', 'banana', 'mango', 'dragonfruit'],\n      'apple, banana, mango, and dragonfruit',\n    ],\n  ])('should translate as expected', (options, result) => {\n    expect(translateToInclusiveList(options)).toBe(result);\n  });\n});\n"
  },
  {
    "path": "packages/i18n/src/test/translateWithMarkup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport TranslateWithMarkup from '../translateWithMarkup';\n\ndescribe('TranslateWithMarkup component', () => {\n  it('returns same string when not passing mapping', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup>\n        {\n          'This is a <b>bold</b> move!<br/>Look at all these <em>line breaks</em>!'\n        }\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe(\n      'This is a <b>bold</b> move!<br/>Look at all these <em>line breaks</em>!'\n    );\n  });\n\n  it('returns same string when it contains no tokens', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup mapping={{ foo: <strong /> }}>\n        {'This is a string'}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a string');\n  });\n\n  it('returns same string when it contains a non-matching token', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup mapping={{ foo: <strong /> }}>\n        {'This is a <span></span> string'}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a <span></span> string');\n  });\n\n  it('returns expected React element for component', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup mapping={{ a: <a href=\"https://example.com\" /> }}>\n        {'This is a <a>link</a>!'}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a <a href=\"https://example.com\">link</a>!');\n  });\n\n  it('returns expected React element for custom component', () => {\n    const string = 'This is a <a>link</a>!';\n\n    const Link = (props: {\n      href: string;\n      children?: ReactNode | undefined;\n    }) => {\n      return <a {...props}>{props.children}</a>;\n    };\n\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup mapping={{ a: <Link href=\"https://example.com\" /> }}>\n        {string}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a <a href=\"https://example.com\">link</a>!');\n  });\n\n  it('returns expected React element for multiple components', () => {\n    const Link = (props: {\n      href: string;\n      target: string;\n      rel: string;\n      children?: ReactNode | undefined;\n    }) => {\n      return <a {...props}>{props.children}</a>;\n    };\n\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup\n        mapping={{\n          a: (\n            <Link href=\"https://example.com\" target=\"_blank\" rel=\"noreferrer\" />\n          ),\n          a2: (\n            <Link href=\"https://example.org\" target=\"_blank\" rel=\"noreferrer\" />\n          ),\n        }}\n      >\n        {'Read the<br/><a>Get Started story</a>, or <a2>this blog post</a2>!'}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe(\n      'Read the<br/><a href=\"https://example.com\" target=\"_blank\" rel=\"noreferrer\">Get Started story</a>, or <a href=\"https://example.org\" target=\"_blank\" rel=\"noreferrer\">this blog post</a>!'\n    );\n  });\n\n  it('does not preserve HTML attributes', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup mapping={{ a: <a href=\"https://example.com\" /> }}>\n        {\n          'This is a <a href=\"https://example.org\" target=\"_blank\" rel=\"noreferrer\">link</a>!'\n        }\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a <a href=\"https://example.com\">link</a>!');\n  });\n\n  it('converts mapping keys to lowercase', () => {\n    const result = renderToStaticMarkup(\n      <TranslateWithMarkup\n        mapping={{ CustomLink: <a href=\"https://example.com\" /> }}\n      >\n        {'This is a <CustomLink>link</CustomLink>!'}\n      </TranslateWithMarkup>\n    );\n\n    expect(result).toBe('This is a <a href=\"https://example.com\">link</a>!');\n  });\n\n  it('throws error when accidentally using void elements', () => {\n    const component = (\n      <TranslateWithMarkup mapping={{ link: <a href=\"https://example.com\" /> }}>\n        {'This is a <link>link</link>!'}\n      </TranslateWithMarkup>\n    );\n\n    expect(() => renderToStaticMarkup(component)).toThrow(\n      'Found disallowed void elements in TranslateWithMarkup map: link'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/i18n/src/transformNode.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactElement, ReactNode } from 'react';\nimport { cloneElement, createElement } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { Mapping } from './types';\n\n/**\n * Recursively traverses through a DOM node and its children and transforms them\n * to React elements.\n *\n * @param node DOM node.\n * @param mapping Map of tag names to React components.\n * @return List of transformed nodes.\n */\nexport function transform(node: Element, mapping: Mapping = {}): ReactNode[] {\n  const result = [];\n\n  do {\n    result.push(transformNode(node, mapping));\n    node = node.nextSibling as Element;\n  } while (node !== null);\n\n  return result;\n}\n\n/**\n * Transforms a single DOM node.\n *\n * @param node DOM node.\n * @param mapping Map of tag names to React components.\n * @return Transformed node.\n */\nexport function transformNode(\n  node: Element | Text,\n  mapping: Mapping = {}\n): ReactElement | string | null {\n  const { childNodes, nodeType, textContent } = node;\n  if (Node.TEXT_NODE === nodeType) {\n    return textContent;\n  }\n\n  const children = node.hasChildNodes()\n    ? Array.from(childNodes).map((child) =>\n        transform(child as Element, mapping)\n      )\n    : null;\n\n  const { localName } = node as Element;\n\n  if (localName in mapping) {\n    return cloneElement(mapping[localName], {}, children);\n  }\n\n  return createElement(localName, null, children);\n}\n"
  },
  {
    "path": "packages/i18n/src/translateToExclusiveList.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport sprintf from './sprintf';\nimport { __ } from './i18n';\n\n/**\n * Join all options in a list and translate. These will be joined with\n * the conjunction `or`.\n *\n * @param options The options that will be joined with the `or` conjunction.\n * @return Localized list items.\n */\nfunction translateToExclusiveList(options: string[]) {\n  switch (options.length) {\n    case 0:\n      return '';\n    case 1:\n      return options[0];\n    case 2:\n      return sprintf(\n        /* translators: %1$s: first item of list. %2$s: second item of list. */\n        __('%1$s or %2$s', 'web-stories'),\n        options[0],\n        options[1]\n      );\n    default:\n      return sprintf(\n        /* translators: %1$s: is a comma separated list. %2$s: last entry in list  */\n        __('%1$s, or %2$s', 'web-stories'),\n        options.slice(0, options.length - 1).join(\n          /* translators: delimiter used in a list */\n          __(', ', 'web-stories') // eslint-disable-line @wordpress/i18n-no-flanking-whitespace -- Expected behaviour.\n        ),\n        options[options.length - 1]\n      );\n  }\n}\n\nexport default translateToExclusiveList;\n"
  },
  {
    "path": "packages/i18n/src/translateToInclusiveList.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport sprintf from './sprintf';\nimport { __ } from './i18n';\n\n/**\n * Join all options in a list and translate. These will be joined with\n * the conjunction `and`.\n *\n * @param options The options that will be joined with the `and` conjunction.\n * @return Localized list items.\n */\nfunction translateToInclusiveList(options: string[]) {\n  switch (options.length) {\n    case 0:\n      return '';\n    case 1:\n      return options[0];\n    case 2:\n      return sprintf(\n        /* translators: %1$s: first item of list. %2$s: second item of list. */\n        __('%1$s and %2$s', 'web-stories'),\n        options[0],\n        options[1]\n      );\n    default:\n      return sprintf(\n        /* translators: %1$s: is a comma separated list. %2$s: last entry in list  */\n        __('%1$s, and %2$s', 'web-stories'),\n        options.slice(0, options.length - 1).join(\n          /* translators: delimiter used in a list */\n          __(', ', 'web-stories') // eslint-disable-line @wordpress/i18n-no-flanking-whitespace -- Expected behaviour.\n        ),\n        options[options.length - 1]\n      );\n  }\n}\n\nexport default translateToInclusiveList;\n"
  },
  {
    "path": "packages/i18n/src/translateWithMarkup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Fragment } from '@googleforcreators/react';\nimport type { ReactElement } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { Mapping } from './types';\nimport { transform } from './transformNode';\n\n// See https://html.spec.whatwg.org/multipage/syntax.html#void-elements\nconst VOID_ELEMENTS = [\n  'area',\n  'base',\n  'br',\n  'col',\n  'embed',\n  'hr',\n  'img',\n  'input',\n  'link',\n  'meta',\n  'param',\n  'source',\n  'track',\n  'wbr',\n];\n\ninterface TranslateWithMarkupProps {\n  mapping?: Mapping;\n  children: string;\n}\n\n/**\n * Component to facilitate translation of strings containing markup.\n *\n * Parses a string using DOMParser and replaces found element nodes\n * with the provided React components.\n *\n * This way, using dangerouslySetInnerHTML can be avoided.\n *\n * @see https://github.com/googleforcreators/web-stories-wp/issues/1578\n * @param props Component props.\n * @param props.mapping Map of tag names to React components.\n * @param props.children Children / string to parse.\n * @return Transformed children.\n */\nfunction TranslateWithMarkup({\n  mapping = {},\n  children,\n}: TranslateWithMarkupProps): ReactElement | null {\n  //Ensure all Object keys are lowercase as the DOMParser converts tag names to lowercase.\n  mapping = Object.fromEntries(\n    Object.entries(mapping).map(([k, v]) => [k.toLowerCase(), v])\n  );\n\n  // Disallow void elements in mapping because it will lead to unexpected behavior\n  // because a void element cannot have contents under any circumstances.\n  // See https://www.w3.org/TR/2011/WD-html-markup-20110113/syntax.html#void-element\n  const foundVoidElements = Object.keys(mapping)\n    .filter((tag) => VOID_ELEMENTS.includes(tag))\n    .join(' ');\n  if (foundVoidElements.length > 0) {\n    throw new Error(\n      `Found disallowed void elements in TranslateWithMarkup map: ${foundVoidElements}`\n    );\n  }\n\n  const node = new DOMParser().parseFromString(children, 'text/html').body\n    .firstChild as Element;\n\n  if (!node) {\n    return null;\n  }\n\n  return (\n    <Fragment>\n      {transform(node, mapping).map((element, index) => (\n        <Fragment\n          // eslint-disable-next-line react/no-array-index-key -- Order should never change.\n          key={index}\n        >\n          {element}\n        </Fragment>\n      ))}\n    </Fragment>\n  );\n}\n\nexport default TranslateWithMarkup;\n"
  },
  {
    "path": "packages/i18n/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactElement } from 'react';\n\nexport type Mapping = Record<string, ReactElement>;\n\nexport type TranslatableText<T extends string> = string & {\n  readonly __translatableText: T;\n};\n"
  },
  {
    "path": "packages/i18n/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../react\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/jest-amp/README.md",
    "content": "# jest-amp\n"
  },
  {
    "path": "packages/jest-amp/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/jest-amp\",\n  \"description\": \"Custom Jest matchers for AMP validation\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"jest\",\n    \"amp\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/jest-amp/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/jest-amp\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@ampproject/toolbox-optimizer\": \"^2.10.1\",\n    \"@googleforcreators/react\": \"*\",\n    \"amphtml-validator\": \"1.0.38\",\n    \"prop-types\": \"^15.8.1\"\n  }\n}\n"
  },
  {
    "path": "packages/jest-amp/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as toBeValidAMP } from './toBeValidAMP';\nexport { default as toBeValidAMPStoryElement } from './toBeValidAMPStoryElement';\nexport { default as toBeValidAMPStoryPage } from './toBeValidAMPStoryPage';\nexport { getAMPValidationErrors } from './utils';\n"
  },
  {
    "path": "packages/jest-amp/src/toBeValidAMP.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { getAMPValidationErrors } from './utils';\n\n/** @typedef {import('react').ReactElement} ReactElement */\n/** @typedef {import('jest').CustomMatcherResult} CustomMatcherResult */\n\n/**\n * @param {string|ReactElement} stringOrComponent String or React component to test.\n * @param {Array} args Optional arguments to pass down.\n * @return {CustomMatcherResult} Matcher result.\n */\nasync function toBeValidAMP(stringOrComponent, ...args) {\n  const string = renderToStaticMarkup(stringOrComponent);\n  const errors = await getAMPValidationErrors(string, ...args);\n  const pass = errors.length === 0;\n\n  return {\n    pass,\n    message: () =>\n      pass\n        ? `Expected ${string} not to be valid AMP.`\n        : `Expected ${string} to be valid AMP. Errors:\\n${errors.join('\\n')}`,\n  };\n}\n\nexport default toBeValidAMP;\n"
  },
  {
    "path": "packages/jest-amp/src/toBeValidAMPStoryElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  AmpStory,\n  AmpStoryPage,\n  AmpStoryGridLayer,\n  getAMPValidationErrors,\n} from './utils';\n\n/** @typedef {import('react').ReactElement} ReactElement */\n/** @typedef {import('jest').CustomMatcherResult} CustomMatcherResult */\n\n/**\n * @param {string|ReactElement} stringOrComponent String containing HTML markup or a component.\n * @param {boolean} [optimize] Whether to use AMP Optimizer on the input string.\n * @return {CustomMatcherResult} Matcher result.\n */\nasync function toBeValidAMPStoryElement(stringOrComponent, optimize = true) {\n  const string = renderToStaticMarkup(stringOrComponent);\n  const errors = await getAMPValidationErrors(\n    renderToStaticMarkup(\n      <AmpStory>\n        <AmpStoryPage>\n          <AmpStoryGridLayer>{stringOrComponent}</AmpStoryGridLayer>\n        </AmpStoryPage>\n      </AmpStory>\n    ),\n    optimize\n  );\n\n  const pass = errors.length === 0;\n\n  return {\n    pass,\n    message: () =>\n      pass\n        ? `Expected ${string} not to be valid AMP.`\n        : `Expected ${string} to be valid AMP. Errors:\\n${errors.join('\\n')}`,\n  };\n}\n\nexport default toBeValidAMPStoryElement;\n"
  },
  {
    "path": "packages/jest-amp/src/toBeValidAMPStoryPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { AmpStory, getAMPValidationErrors } from './utils';\n\n/** @typedef {import('react').ReactElement} ReactElement */\n/** @typedef {import('jest').CustomMatcherResult} CustomMatcherResult */\n\n/**\n * @param {string|ReactElement} stringOrComponent String containing HTML markup or a component.\n * @param {boolean} [optimize] Whether to use AMP Optimizer on the input string.\n * @return {CustomMatcherResult} Matcher result.\n */\nasync function toBeValidAMPStoryPage(stringOrComponent, optimize = true) {\n  const string = renderToStaticMarkup(stringOrComponent);\n  const errors = await getAMPValidationErrors(\n    renderToStaticMarkup(<AmpStory>{stringOrComponent}</AmpStory>),\n    optimize\n  );\n\n  const pass = errors.length === 0;\n\n  return {\n    pass,\n    message: () =>\n      pass\n        ? `Expected ${string} not to be valid AMP.`\n        : `Expected ${string} to be valid AMP. Errors:\\n${errors.join('\\n')}`,\n  };\n}\n\nexport default toBeValidAMPStoryPage;\n"
  },
  {
    "path": "packages/jest-amp/src/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { existsSync } from 'fs';\nimport { tmpdir } from 'os';\nimport PropTypes from 'prop-types';\nimport AmpOptimizer, {\n  TRANSFORMATIONS_AMP_FIRST,\n} from '@ampproject/toolbox-optimizer';\nimport amphtmlValidator from 'amphtml-validator';\n\nconst fallback = tmpdir() + '/validator_wasm.js';\nconst validatorJs =\n  process.env.AMP_VALIDATOR_FILE ||\n  (existsSync(fallback) ? fallback : undefined);\n\n/** @typedef {import('react').ReactElement} ReactElement */\n\n/**\n * @param {Object} props Component props.\n * @param {Node} props.children Children.\n * @return {ReactElement} AMP Story grid layer component\n */\nfunction AmpStoryGridLayer({ children }) {\n  return (\n    <amp-story-grid-layer template=\"vertical\">{children}</amp-story-grid-layer>\n  );\n}\n\nAmpStoryGridLayer.propTypes = {\n  children: PropTypes.node,\n};\n\n/**\n * @param {Object} props Component props.\n * @param {Node} props.children Children.\n * @return {ReactElement} AMP Story page component\n */\nfunction AmpStoryPage({ children }) {\n  return <amp-story-page id=\"foo\">{children}</amp-story-page>;\n}\n\nAmpStoryPage.propTypes = {\n  children: PropTypes.node,\n};\n\n/**\n * @param {Object} props Component props.\n * @param {Node} props.children Children.\n * @return {ReactElement} AMP story component.\n */\nfunction AmpStory({ children }) {\n  return (\n    <amp-story\n      standalone=\"standalone\"\n      publisher=\"Example Publisher\"\n      publisher-logo-src=\"https://example.com/publisher.png\"\n      title=\"Example Story\"\n      poster-portrait-src=\"https://example.com/poster.png\"\n    >\n      {children}\n    </amp-story>\n  );\n}\n\nAmpStory.propTypes = {\n  children: PropTypes.node,\n};\n\n// Ignore some false positives when validating URLs in Puppeteer.\n// Perhaps the validator is outdated or something.\nconst ERRORS_TO_IGNORE = [\n  /The attribute 'nomodule' may not appear in tag 'amphtml module engine script'/,\n  /The attribute 'type' in tag '.* nomodule extension script' is set to the invalid value 'module'/,\n  /The tag 'amphtml nomodule engine script' is missing or incorrect, but required by 'amphtml module engine script'/,\n];\n\n/**\n * Tests a given string for its AMP compatibility.\n *\n * Uses AMP Optimizer to add any missing tags and extension imports.\n *\n * @see https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer#incomplete-markup\n * @param {string} string Input string.\n * @param {boolean} [optimize] Whether to use AMP Optimizer on the input string.\n * @return {Promise<[]>} List of AMP validation errors.\n */\nasync function getAMPValidationErrors(string, optimize = true) {\n  let completeString = string;\n\n  if (!completeString.startsWith('<!DOCTYPE html>')) {\n    completeString = `<!DOCTYPE html>${string}`;\n  }\n\n  if (optimize) {\n    // We only want the bare minimum here - adding missing tags & extensions.\n    // See https://www.npmjs.com/package/@ampproject/toolbox-optimizer#options\n    const ampOptimizer = AmpOptimizer.create({\n      autoAddMandatoryTags: true,\n      autoExtensionImport: true,\n      optimizeHeroImages: false,\n      blurredPlaceholders: false,\n      // Reduces debug noise due to missing dependencies.\n      transformations: TRANSFORMATIONS_AMP_FIRST.filter(\n        (transformation) => transformation !== 'AddBlurryImagePlaceholders'\n      ),\n    });\n    const params = {\n      canonical: 'https://example.com',\n    };\n    completeString = await ampOptimizer.transformHtml(completeString, params);\n  }\n\n  const validator = await amphtmlValidator.getInstance(validatorJs);\n  const { errors } = validator.validateString(completeString);\n\n  const errorMessages = [];\n\n  for (const err of errors) {\n    const { message, specUrl } = err;\n\n    if (ERRORS_TO_IGNORE.some((ignoredMsg) => message.match(ignoredMsg))) {\n      continue;\n    }\n\n    const msg = specUrl ? `${message} (see ${specUrl})` : message;\n\n    errorMessages.push(msg);\n  }\n\n  return errorMessages;\n}\n\nexport { AmpStory, AmpStoryPage, AmpStoryGridLayer, getAMPValidationErrors };\n"
  },
  {
    "path": "packages/jest-puppeteer-amp/README.md",
    "content": "# jest-puppeteer-amp\n"
  },
  {
    "path": "packages/jest-puppeteer-amp/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/jest-puppeteer-amp\",\n  \"description\": \"Custom Jest matcher for AMP validation on Puppeteer pages\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"jest\",\n    \"amp\",\n    \"puppeteer\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/jest-puppeeer-amp/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/jest-puppeteer-amp\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@web-stories-wp/jest-amp\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/jest-puppeteer-amp/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as toBeValidAMP } from './toBeValidAMP';\n"
  },
  {
    "path": "packages/jest-puppeteer-amp/src/toBeValidAMP.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getAMPValidationErrors } from '@web-stories-wp/jest-amp';\n\n/** @typedef {import('puppeteer').Page} Page */\n/** @typedef {import('jest').CustomMatcherResult} CustomMatcherResult */\n\n/**\n * Whether a given URL is valid AMP or not.\n *\n * Opens the URL in a new incognito page, retrieves the\n * page's content and then runs it through the AMP validator.\n *\n * @param {string} url The URL to validate.\n * @return {CustomMatcherResult} Matcher result.\n */\nasync function toBeValidAMP(url) {\n  const context = await browser.createIncognitoBrowserContext();\n  const incognitoPage = await context.newPage();\n  const response = await incognitoPage.goto(url);\n  const content = await response.text();\n  await incognitoPage.close();\n  await context.close();\n\n  const errors = await getAMPValidationErrors(content, true);\n  const pass = errors.length === 0;\n\n  return {\n    pass,\n    message: () =>\n      pass\n        ? `Expected page not to be valid AMP.`\n        : `Expected page to be valid AMP. Errors:\\n${errors.join('\\n')}`,\n  };\n}\n\nexport default toBeValidAMP;\n"
  },
  {
    "path": "packages/jest-resolver/README.md",
    "content": "# jest-resolver\n\nCustom [Jest resolver](https://jestjs.io/docs/configuration#resolver-string) to resolve packages locally in a monorepo.\n\nMakes sure that Jest looks for files in the `src` directory, not in the `dist` or `dist-module` directories.\n"
  },
  {
    "path": "packages/jest-resolver/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/jest-resolver\",\n  \"description\": \"Custom Jest resolver for monorepos\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"jest\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/jest-resolver/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/jest-resolver\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.cjs\",\n  \"dependencies\": {\n  }\n}\n"
  },
  {
    "path": "packages/jest-resolver/src/index.cjs",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst isLocalRepo = (name) =>\n  name.startsWith('@googleforcreators/') || name.startsWith('@web-stories-wp/');\n\n// See https://jestjs.io/docs/configuration#resolver-string\nmodule.exports = (request, options) => {\n  // Workaround for https://github.com/uuidjs/uuid/pull/616.\n  //\n  // jest-environment-jsdom 28+ tries to use browser exports instead of default exports,\n  // but uuid only offers an ESM browser export and not a CommonJS one. Jest does not yet\n  // support ESM modules natively, so this causes a Jest error related to trying to parse\n  // \"export\" syntax.\n  //\n  // This workaround prevents Jest from considering uuid's module-based exports at all;\n  // it falls back to uuid's CommonJS+node \"main\" property.\n  //\n  // Once we're able to migrate our Jest config to ESM and a browser crypto\n  // implementation is available for the browser+ESM version of uuid to use (eg, via\n  // https://github.com/jsdom/jsdom/pull/3352 or a similar polyfill), this can go away.\n  //\n  // Same goes for other packages like react-colorful, which is used by @wordpress/components.\n  const affectedPackages = [\n    'uuid',\n    'react-colorful',\n    'use-debounce',\n    'blurhash',\n  ];\n\n  for (const affectedPackage of affectedPackages) {\n    if (affectedPackage === request) {\n      return options.defaultResolver(request, {\n        ...options,\n        packageFilter: (pkg) => {\n          if (affectedPackage === pkg.name) {\n            delete pkg.exports;\n            delete pkg.module;\n          }\n\n          return pkg;\n        },\n      });\n    }\n  }\n\n  if (!isLocalRepo(request)) {\n    return options.defaultResolver(request, options);\n  }\n\n  // Call the defaultResolver, so we leverage its cache, error handling, etc.\n  return options.defaultResolver(request, {\n    ...options,\n    packageFilter: (pkg) => {\n      if (isLocalRepo(pkg.name)) {\n        delete pkg.exports;\n\n        // Alter the value of `main` before resolving the package\n        pkg.main = pkg.source || pkg.module || pkg.main;\n      }\n\n      return pkg;\n    },\n  });\n};\n"
  },
  {
    "path": "packages/karma-failed-tests-reporter/.eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true\n  }\n}\n"
  },
  {
    "path": "packages/karma-failed-tests-reporter/README.md",
    "content": "# karma-failed-tests-reporter\n\nCustom Karma reporter that writes the names of all failed specs to a file.\n\nThis can be used to easily re-run only failed tests by providing the `--grep` option in Karma.\n\n## Configuration\n\n```js\n// karma.conf.js\nmodule.exports = function (config) {\n  config.set({\n    // reporters configuration\n    reporters: ['@web-stories-wp/karma-failed-tests-reporter'],\n  });\n};\n```\n\n## Options\n\n**outputFile**\n**Type:** String\n\n**Default Values:**\n\nNone.\n\nDefine the full path to the file to be written.\n\n**Example:**\n\n```js\n// karma.conf.js\nmodule.exports = function (config) {\n  config.set({\n    // reporters configuration\n    reporters: ['@web-stories-wp/karma-failed-tests-reporter'],\n\n    failedTestsReporter: {\n      outputFile: 'path/to/file.txt',\n    },\n  });\n};\n```\n"
  },
  {
    "path": "packages/karma-failed-tests-reporter/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/karma-failed-tests-reporter\",\n  \"description\": \"Karma reporter to list failed tests in a txt file\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"karma\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/karma-faield-tests-reporter/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/karma-failed-tests-reporter\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.cjs\",\n  \"peerDependencies\": {\n    \"karma\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/karma-failed-tests-reporter/src/index.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst path = require('path');\nconst fs = require('fs');\n\nconst FailedTestsReporter = function (baseReporterDecorator, config) {\n  baseReporterDecorator(this);\n\n  const { failedTestsReporter: failedTestsReporterConfig = {} } = config;\n  const { outputFile } = failedTestsReporterConfig;\n\n  const failedTests = [];\n\n  this.onSpecComplete = (browser, result) => {\n    const { success, fullName } = result;\n    if (!success) {\n      failedTests.push(fullName);\n    }\n  };\n\n  this.onRunComplete = () => {\n    if (outputFile) {\n      fs.mkdirSync(path.dirname(outputFile), { recursive: true });\n      fs.writeFileSync(outputFile, failedTests.join('\\n'));\n    }\n  };\n};\n\nFailedTestsReporter.$inject = ['baseReporterDecorator', 'config', 'helper'];\n\nmodule.exports = {\n  'reporter:@web-stories-wp/karma-failed-tests-reporter': ['type', FailedTestsReporter],\n};\n"
  },
  {
    "path": "packages/karma-fixture/README.md",
    "content": "# Karma Fixture\n\nKarma Fixture data used in tests.\n"
  },
  {
    "path": "packages/karma-fixture/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/karma-fixture\",\n  \"description\": \"Karma fixtures\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"karma\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/karma-fixture/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/karrma-fixture\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@googleforcreators/react\": \"*\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\"\n  }\n}\n"
  },
  {
    "path": "packages/karma-fixture/src/actPromise.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act } from '@testing-library/react';\n\nexport default function actPromise(callback) {\n  return new Promise((resolve) => {\n    let callbackResult;\n    const actResult = act(() => {\n      callbackResult = callback();\n      return Promise.resolve(callbackResult);\n    });\n    resolve(\n      new Promise((aResolve, aReject) => {\n        actResult.then(aResolve, aReject);\n      }).then(() => callbackResult)\n    );\n  });\n}\n"
  },
  {
    "path": "packages/karma-fixture/src/client_with_context.html",
    "content": "\n<!DOCTYPE html>\n<!--\nThis is the combined client and execution context.\nIs used for single-shot tests.\n-->\n<html>\n<head>\n\n  <title>Karma</title>\n  <link href=\"favicon.ico\" rel=\"icon\" type=\"image/x-icon\">\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\" />\n  <link\n    href=\"https://fonts.googleapis.com/css?family=Google+Sans|Google+Sans:b|Google+Sans:500&display=swap\"\n    rel=\"stylesheet\"\n  />\n  <style type=\"text/css\">\n    iframe {\n      height: 100%;\n      width: 100%;\n      border: 0;\n    }\n\n    html, body {\n      height: 100%;\n      padding: 0;\n      margin: 0;\n\n      font-family: sans-serif;\n    }\n\n    .offline {\n      background: #DDD;\n    }\n\n    .online {\n      background: #6C4;\n    }\n\n    .idle {\n    }\n\n    .executing {\n      background: #F99;\n    }\n\n    #banner {\n      padding: 5px 10px;\n    }\n\n    h1 {\n      font-size: 1.8em;\n      margin: 0;\n      padding: 0;\n    }\n\n    ul {\n      margin: 0;\n      padding: 0;\n\n      list-style: none;\n    }\n\n    li {\n      padding: 5px 12px;\n    }\n\n    .btn-debug {\n      float: right;\n    }\n\n    .offline .btn-debug {\n      display: none;\n    }\n\n    .btn-debug {\n      -moz-box-shadow:inset 0px 1px 0px 0px #ffffff;\n      -webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;\n      box-shadow:inset 0px 1px 0px 0px #ffffff;\n      background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #f6f6f6) );\n      background:-moz-linear-gradient( center top, #ffffff 5%, #f6f6f6 100% );\n      filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6');\n      background-color:#ffffff;\n      -moz-border-radius:6px;\n      -webkit-border-radius:6px;\n      border-radius:6px;\n      border:1px solid #dcdcdc;\n      display:inline-block;\n      color:#666666;\n      font-family:arial;\n      font-size:15px;\n      font-weight:bold;\n      padding:6px 24px;\n      text-decoration:none;\n      text-shadow:1px 1px 0px #ffffff;\n    }\n\n    .btn-debug:hover {\n      background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #f6f6f6), color-stop(1, #ffffff) );\n      background:-moz-linear-gradient( center top, #f6f6f6 5%, #ffffff 100% );\n      filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#ffffff');\n      background-color:#f6f6f6;\n    }\n  </style>\n</head>\n<body>\n  <script src=\"socket.io/socket.io.js\"></script>\n  <script src=\"karma.js\"></script>\n  <script src=\"context.js\"></script>\n  <!-- The scripts need to be at the end of body, so that some test running frameworks\n       (Angular Scenario, for example) need the body to be loaded so that it can insert its magic\n       into it. If it is before body, then it fails to find the body and crashes and burns in an epic\n       manner. -->\n  <script type=\"text/javascript\">\n    // sets window.__karma__ and overrides console and error handling\n    %CLIENT_CONFIG%\n    window.__karma__.setupContext(window);\n\n    // All served files with the latest timestamps\n    %MAPPINGS%\n    %SCRIPT_URL_ARRAY%\n  </script>\n  <!-- Dynamically replaced with <script> tags -->\n</body>\n</html>\n"
  },
  {
    "path": "packages/karma-fixture/src/componentStub.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState, useMemo, forwardRef } from '@googleforcreators/react';\nimport { act } from '@testing-library/react';\n\nexport default class ComponentStub {\n  constructor(fixture, Component, matcher) {\n    this._fixture = fixture;\n    this._matcher = matcher;\n    this._implementation = null;\n\n    this._props = null;\n\n    let setRefresher;\n    this._refresh = () => {\n      act(() => {\n        if (setRefresher) {\n          setRefresher((v) => v + 1);\n        }\n      });\n    };\n\n    const pendingHooks = [];\n    this._pushPendingHook = (func) => {\n      let resolver;\n      const promise = new Promise((resolve) => {\n        resolver = resolve;\n      });\n      pendingHooks.push(() => {\n        const result = func();\n        resolver(result);\n      });\n      this._refresh();\n      return promise;\n    };\n\n    const Wrapper = forwardRef((props, ref) => {\n      this._props = props;\n\n      const [refresher, setRefresherInternal] = useState(0);\n      setRefresher = setRefresherInternal;\n      const hooks = useMemo(\n        () => {\n          const hooksToExecute = pendingHooks.slice(0);\n          pendingHooks.length = 0;\n          return hooksToExecute;\n        },\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [refresher]\n      );\n\n      const Impl = useMemo(\n        () => {\n          if (this._implementation) {\n            const MockImpl = forwardRef((fProps, fRef) =>\n              this._implementation(fProps, fRef)\n            );\n            MockImpl.displayName = `Stub(${\n              Component.displayName || Component.name || ''\n            })`;\n            return MockImpl;\n          }\n          return Component;\n        },\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [refresher]\n      );\n\n      return (\n        <>\n          <HookExecutor key={refresher} hooks={hooks} />\n          <Impl _wrapped ref={ref} {...props} />\n        </>\n      );\n    });\n    Wrapper.displayName = `Mock(${\n      Component.displayName || Component.name || ''\n    })`;\n    this._wrapper = Wrapper;\n  }\n\n  get and() {\n    return this;\n  }\n\n  get props() {\n    return this._props;\n  }\n\n  mockImplementation(implementation) {\n    this._implementation = implementation;\n    this._refresh();\n    return this;\n  }\n\n  callFake(implementation) {\n    return this.mockImplementation(implementation);\n  }\n\n  renderHook(func) {\n    return this._fixture.act(() => this._pushPendingHook(func));\n  }\n}\n\n/* eslint-disable react/prop-types, react/jsx-no-useless-fragment */\nfunction HookExecutor({ hooks }) {\n  hooks.forEach((func) => func());\n  return <></>;\n}\n/* eslint-enable react/prop-types, react/jsx-no-useless-fragment */\n"
  },
  {
    "path": "packages/karma-fixture/src/events.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst KEY_MAP = {\n  ALT: 'Alt',\n  COMMAND: 'Meta',\n  CMD: 'Meta',\n  CONTROL: 'Control',\n  CNTRL: 'Control',\n  DOWN: 'ArrowDown',\n  ENTER: 'Enter',\n  ESC: 'Escape',\n  LEFT: 'ArrowLeft',\n  META: 'Meta',\n  RIGHT: 'ArrowRight',\n  SHIFT: 'Shift',\n  SPACE: 'Space',\n  TAB: 'Tab',\n  UP: 'ArrowUp',\n};\n\n/**\n * Events utility. Uses native and synthetic events as needed.\n */\nclass FixtureEvents {\n  /**\n   * @param {function():Promise} act Actor.\n   */\n  constructor(act) {\n    this._act = act;\n    this._keyboard = new Keyboard(act);\n    this._mouse = new Mouse(act);\n    this._clipboard = new Clipboard(act);\n  }\n\n  get keyboard() {\n    return this._keyboard;\n  }\n\n  get mouse() {\n    return this._mouse;\n  }\n\n  get clipboard() {\n    return this._clipboard;\n  }\n\n  /**\n   * Return a promise sleeping for a given number of milliseconds.\n   *\n   * @param {number} ms Number of milliseconds to wait\n   * @return {!Promise} A promise resolving after the given time\n   */\n  sleep(ms) {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n\n  /**\n   * See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pageclickselector-options.\n   *\n   * @param {Element} target The event target.\n   * @param {Object} options The event options.\n   * @return {!Promise} The promise when the event handling is complete.\n   */\n  click(target, options = {}) {\n    return this._act(() => karmaPuppeteer.click(target, options));\n  }\n\n  /**\n   * See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagefocusselector.\n   *\n   * @param {Element} target The event target.\n   * @param {Object} options The event options.\n   * @return {!Promise} The promise when the event handling is complete.\n   */\n  focus(target, options = {}) {\n    return this._act(() => karmaPuppeteer.focus(target, options));\n  }\n\n  /**\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#framehoverselector.\n   *\n   * @param {Element} target The event target.\n   * @param {Object} options The event options.\n   * @return {!Promise} The promise when the event handling is complete.\n   */\n  hover(target, options = {}) {\n    return this._act(() => karmaPuppeteer.hover(target, options));\n  }\n\n  /**\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#frameselectselector-values\n   *\n   * Triggers a change and input event once all the provided options have been\n   * selected.\n   *\n   * @param {Element} target The event target.\n   * @param {Array<string>} values Values of options to select.\n   * @return {!Promise} The promise when the event handling is complete.\n   */\n  select(target, ...values) {\n    return this._act(() => karmaPuppeteer.select(target, values));\n  }\n}\n\n/**\n * Events utility for keyboard.\n *\n * The list of all keycodes is available in https://github.com/puppeteer/puppeteer/blob/main/src/common/USKeyboardLayout.ts.\n *\n * In addition to this, the following special codes are allowed:\n * - \"mod\": \"Meta\" on OSX and \"Control\" elsewhere.\n *\n * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#class-keyboard.\n */\nclass Keyboard {\n  /**\n   * @param {function():Promise} act Actor.\n   */\n  constructor(act) {\n    this._act = act;\n\n    this._events = {\n      down: (key, options = {}) => {\n        const type = 'down';\n        return { type, key, options };\n      },\n      up: (key, options = {}) => {\n        const type = 'up';\n        return { type, key, options };\n      },\n      press: (key, options = {}) => {\n        const type = 'press';\n        return { type, key, options };\n      },\n    };\n  }\n\n  /**\n   * A sequence of:\n   * - `type: 'down`: [keyboard.down](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboarddownkey-options).\n   * - `type: 'up'`: [keyboard.up](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardupkey).\n   * - `type: 'press'`: [keyboard.press](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardpresskey-options).\n   *\n   * @param {Array<{type: string, key: string, options: Object}>|Function} arrayOrGenerator Sequence of key events.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  seq(arrayOrGenerator) {\n    const array =\n      typeof arrayOrGenerator === 'function'\n        ? arrayOrGenerator(this._events)\n        : arrayOrGenerator;\n    const keys = cleanupKeys(array);\n    return this._act(() => karmaPuppeteer.keyboard.seq(keys));\n  }\n\n  /**\n   * Decodes and executes a sequence of keys corresponding to a shortcut,\n   * such as \"mod+b\". In this example, \"mod+b\" will be translated into the\n   * following sequence:\n   * - down Meta (or Control for non-Mac)\n   * - press KeyB\n   * - up Meta\n   *\n   * @param {string} shortcut Keyboard shortcut.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  shortcut(shortcut) {\n    return this.seq(parseShortcutToSeq(shortcut));\n  }\n\n  /**\n   * The `keyboard.down` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboarddownkey-options\n   *\n   * @param {string} key Name of key to press, such as ArrowLeft\n   * @param {Object} options Options\n   * @return {!Promise} Yields when the event is processed.\n   */\n  down(key, options = {}) {\n    return this.seq([this._events.down(key, options)]);\n  }\n\n  /**\n   * The `keyboard.up` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardupkey\n   *\n   * @param {string} key Name of key to release, such as ArrowLeft.\n   * @param {Object<{text: string}>} options Event options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  up(key, options = {}) {\n    return this.seq([this._events.up(key, options)]);\n  }\n\n  /**\n   * The `keyboard.press` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardpresskey-options\n   *\n   * @param {string} key Name of key to press, such as ArrowLeft\n   * @param {Object<{text: string, delay: number}>} options Event options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  press(key, options = {}) {\n    return this.seq([this._events.press(key, options)]);\n  }\n\n  /**\n   * The `keyboard.type` API.\n   *\n   * Sends a keydown, keypress/input, and keyup event for each character in the\n   * text.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardtypetext-options\n   *\n   * @param {string} text Text to type.\n   * @param {Object<{delay: number}>} options Event options. Accepts `delay` option to wait between key presses\n   * in milliseconds.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  type(text, options = {}) {\n    return this._act(() => karmaPuppeteer.keyboard.type(text, options));\n  }\n\n  /**\n   * The `keyboard.sendCharacter` API.\n   *\n   * Dispatches a keypress and input event. This does not send a keydown or\n   * keyup event.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#keyboardsendcharacterchar\n   *\n   * @param {string} char Character to send into the page.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  sendCharacter(char) {\n    return this._act(() => karmaPuppeteer.keyboard.sendCharacter(char));\n  }\n}\n\n/**\n * Events utility for mouse.\n *\n * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#class-mouse.\n */\nclass Mouse {\n  /**\n   * @param {function():Promise} act Actor.\n   */\n  constructor(act) {\n    this._act = act;\n\n    this._xy = [0, 0];\n\n    const relToDelta = (rel, size) => {\n      if (!rel) {\n        return 0;\n      }\n      if (typeof rel === 'number') {\n        return rel;\n      }\n      if (rel.endsWith('%')) {\n        const percent = Number.parseFloat(rel) / 100;\n        return size * percent;\n      }\n      throw new Error('Unknown rel size: ' + rel);\n    };\n\n    const elementXY = (element, relX, relY) => {\n      const { x, y, width, height } = element.getBoundingClientRect();\n      const dx = relToDelta(relX, width);\n      const dy = relToDelta(relY, height);\n      return [x + dx, y + dy];\n    };\n\n    this._events = {\n      click: (x, y, options = {}) => {\n        this._xy = [x, y];\n        const type = 'click';\n        return { type, x, y, options };\n      },\n      down: (options = {}) => {\n        const type = 'down';\n        return { type, options };\n      },\n      up: (options = {}) => {\n        const type = 'up';\n        return { type, options };\n      },\n      wheel: (options = {}) => {\n        const type = 'wheel';\n        return { type, options };\n      },\n      move: (x, y, options = {}) => {\n        this._xy = [x, y];\n        const type = 'move';\n        return { type, x, y, options };\n      },\n\n      clickOn: (element, relX = 0, relY = 0, options = {}) => {\n        const [x, y] = elementXY(element, relX, relY);\n        this._xy = [x, y];\n        return this._events.click(x, y, options);\n      },\n\n      moveRel: (element, relX = 0, relY = 0, options = {}) => {\n        const [x, y] = elementXY(element, relX, relY);\n        this._xy = [x, y];\n        return this._events.move(x, y, options);\n      },\n\n      moveBy: (dx, dy, options = {}) => {\n        let [x, y] = this._xy;\n        x += dx;\n        y += dy;\n        this._xy = [x, y];\n        return this._events.move(x, y, options);\n      },\n    };\n  }\n\n  /**\n   * A sequence of:\n   * - `type: 'down`: [mouse.down](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousedownoptions).\n   * - `type: 'up'`: [mouse.up](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mouseupoptions).\n   * - `type: 'move'`: [mouse.move](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousemovex-y-options).\n   * - `type: 'click'`: [mouse.click](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mouseclickx-y-options).\n   *\n   * @param {Array<{type: string, x: number, y: number, options: Object}>|Function} arrayOrGenerator Array/Generator for event sequence.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  seq(arrayOrGenerator) {\n    const array =\n      typeof arrayOrGenerator === 'function'\n        ? arrayOrGenerator(this._events)\n        : arrayOrGenerator;\n    return this._act(() => karmaPuppeteer.mouse.seq(cleanupMouseEvents(array)));\n  }\n\n  /**\n   * The `mouse.click` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mouseclickx-y-options\n   *\n   * @param {number} x X coordinates.\n   * @param {number} y Y coordinates.\n   * @param {Object} options Options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  click(x, y, options = {}) {\n    return this.seq([this._events.click(x, y, options)]);\n  }\n\n  /**\n   * The `mouse.down` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousedownoptions\n   *\n   * @param {Object} options Accepts `button` and `clickCount` options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  down(options = {}) {\n    return this.seq([this._events.down(options)]);\n  }\n\n  /**\n   * The `mouse.up` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mouseupoptions\n   *\n   * @param {Object} options Accepts `button` and `clickCount` options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  up(options = {}) {\n    return this.seq([this._events.up(options)]);\n  }\n\n  /**\n   * The `mouse.wheel` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousewheeloptions\n   *\n   * @param {Object} options Accepts `deltaX` and `deltaY` options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  wheel(options = {}) {\n    return this.seq([this._events.wheel(options)]);\n  }\n\n  /**\n   * The `mouse.move` API.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousemovex-y-options\n   *\n   * @param {number} x X coordinates.\n   * @param {number} y Y coordinates.\n   * @param {Object} options Accepts `steps` option for the number of\n   * intermediate mousemove events.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  move(x, y, options = {}) {\n    return this.seq([this._events.move(x, y, options)]);\n  }\n\n  /**\n   * Moves the mouse pointer to a position relative to the specified element\n   * and calls `mouse.click` at that position.\n   *\n   * The position is calculated relative to the specified element. The\n   * `relX` and `relY` can be either:\n   * 1. A number specifying the pixel distance relative to the element's\n   * top-left corner.\n   * 2. A string with \"%\" suffix specifying the percent distance relative\n   * to the element's top-left corner.\n   *\n   * For instance, to click on the center of an element, call\n   * `clickOn(element, '50%', '50%')`.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mouseclickx-y-options\n   *\n   * @param {Element} element Element.\n   * @param {number|string} relX A relative pixel or percent value. Default is 0.\n   * @param {number|string} relY A relative pixel or percent value. Default is 0.\n   * @param {Object<{button: string, clickCount: number, delay: number}>} options Mouse click options.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  clickOn(element, relX = 0, relY = 0, options = {}) {\n    return this.seq([this._events.clickOn(element, relX, relY, options)]);\n  }\n\n  /**\n   * Moves the mouse pointer to a position relative to the specified element.\n   *\n   * The position is calculated relative to the specified element. The\n   * `relX` and `relY` can be either:\n   * 1. A number specifying the pixel distance relative to the element's\n   * top-left corner.\n   * 2. A string with \"%\" suffix specifying the percent distance relative\n   * to the element's top-left corner.\n   *\n   * For instance, to move pointer to the center of an element, call\n   * `moveRel(element, '50%', '50%')`.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousemovex-y-options\n   *\n   * @param {Element} element Element.\n   * @param {number|string} relX A relative pixel or percent value. Default is 0.\n   * @param {number|string} relY A relative pixel or percent value. Default is 0.\n   * @param {Object<{steps: number}>} options Accepts `steps` option for the number of\n   * intermediate mousemove events.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  moveRel(element, relX = 0, relY = 0, options = {}) {\n    return this.seq([this._events.moveRel(element, relX, relY, options)]);\n  }\n\n  /**\n   * Moves the mouse pointer to a position relative to the last position.\n   *\n   * See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#mousemovex-y-options\n   *\n   * @param {number} dx A relative pixel value.\n   * @param {number} dy A relative pixel value.\n   * @param {Object} options Accepts `steps` option for the number of\n   * intermediate mousemove events.\n   * @return {!Promise} Yields when the event is processed.\n   */\n  moveBy(dx, dy, options = {}) {\n    return this.seq([this._events.moveBy(dx, dy, options)]);\n  }\n}\n\n/**\n * Events utility for clipboard.\n */\nclass Clipboard {\n  /**\n   * @param {function():Promise} act Actor.\n   */\n  constructor(act) {\n    this._act = act;\n  }\n\n  /**\n   * Copy whatever is currently selected to the clipboard\n   *\n   * @return {!Promise} Resolves when operation completes with a boolean success flag\n   */\n  copy() {\n    return this._act(() => karmaPuppeteer.clipboard.copy());\n  }\n\n  /**\n   * Paste whatever is in the clipboard to the currently active target\n   *\n   * @return {!Promise} Yields when the event is processed.\n   */\n  paste() {\n    return this._act(() => karmaPuppeteer.clipboard.paste());\n  }\n\n  /**\n   * Paste plain text by sending fake event to current target\n   *\n   * @param {string} plainText Plain-text string to paste\n   */\n  pastePlain(plainText) {\n    const pasteEvent = Object.assign(\n      new Event('paste', { bubbles: true, cancelable: true }),\n      {\n        clipboardData: {\n          types: ['text/plain'],\n          items: {\n            length: 1,\n            0: {\n              kind: 'string',\n              type: 'text/plain',\n              getAsString: () => plainText,\n            },\n          },\n          getData: () => plainText,\n        },\n      }\n    );\n    document.activeElement.dispatchEvent(pasteEvent);\n  }\n}\n\n/**\n * @param {Array<{type: string, key: string, options: Object}>} array List of keys.\n * @return {Array<{type: string, key: string, options: Object}>} The cleaned\n * up array that can be accepted by the Puppeteer.\n */\nfunction cleanupKeys(array) {\n  return array.map(({ type, key, options }) => ({\n    type,\n    key: cleanupKey(key),\n    options: options || {},\n  }));\n}\n\n/**\n * Converts a key to the allowed key set. See\n * https://github.com/puppeteer/puppeteer/blob/main/src/USKeyboardLayout.ts.\n *\n * @param {string} key Key name.\n * @return {string} The cleaned up key that can be accepted by the Puppeteer.\n */\nfunction cleanupKey(key) {\n  const upperKey = key.toUpperCase();\n  if (upperKey in KEY_MAP) {\n    return KEY_MAP[upperKey];\n  }\n  const isApple = /iPhone|iPad|iPod|Mac/i.test(navigator.userAgent);\n  if (upperKey === 'MOD') {\n    return isApple ? 'Meta' : 'Control';\n  }\n  if (upperKey === 'DEL') {\n    return isApple ? 'Backspace' : 'Delete';\n  }\n  if (upperKey.length === 1 && /[A-Z]/.test(upperKey)) {\n    return `Key${upperKey}`;\n  }\n  if (upperKey.length === 1 && /[0-9]/.test(upperKey)) {\n    return `Digit${upperKey}`;\n  }\n  return key;\n}\n\n/**\n * Parses a given keyboard shortcut string into a key sequence.\n *\n * @param {string} shortcut Keyboard shortcut.\n * @return {Array<{type: string, key: string, options: Object}>} The sequence\n * corresponding to the shortcut.\n */\nfunction parseShortcutToSeq(shortcut) {\n  const parts = shortcut.split('+');\n  // All shortcuts parts except for the last one generate down/up events\n  // and the final part generates press event.\n  const down = [];\n  const up = [];\n  for (let i = 0; i < parts.length - 1; i++) {\n    down.push(parts[i]);\n    up.unshift(parts[i]);\n  }\n  const last = parts[parts.length - 1];\n  return [\n    ...down.map((key) => ({ type: 'down', key })),\n    { type: 'press', key: last },\n    ...up.map((key) => ({ type: 'up', key })),\n  ];\n}\n\n/**\n * @param {Array<{type: string, x: number, y: number, options: Object}>} array List of events.\n * @return {Array<{type: string, x: number, y: number, options: Object}>} The cleaned\n * up array that can be accepted by the Puppeteer.\n */\nfunction cleanupMouseEvents(array) {\n  const { x: offsetX, y: offsetY } = window.frameElement\n    ? window.frameElement.getBoundingClientRect()\n    : { x: 0, y: 0 };\n  return array.map(({ type, x, y, options }) => {\n    const xy =\n      x !== undefined && y !== undefined\n        ? { x: x + offsetX, y: y + offsetY }\n        : {};\n    return {\n      type,\n      ...xy,\n      options: options || {},\n    };\n  });\n}\n\nexport default FixtureEvents;\n"
  },
  {
    "path": "packages/karma-fixture/src/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as actPromise } from './actPromise';\nexport { default as ComponentStub } from './componentStub';\nexport { default as FixtureEvents } from './events';\n"
  },
  {
    "path": "packages/karma-fixture/src/init.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Debug timeout is 1hr.\nconst DEBUG_TIMEOUT = 3600000;\n\n// Make Jasmine just a tiny bit more like Jest and Mocha.\nself.describe.only = self.fdescribe;\nself.it.only = self.fit;\nself.describe.skip = self.xdescribe;\nself.it.skip = self.xit;\n\nlet currentSpec;\nlet rootEl;\nlet cleanupsAll;\n\nfunction withCleanupAll(callback) {\n  if (!cleanupsAll) {\n    cleanupsAll = [];\n  }\n  cleanupsAll.push(callback());\n}\n\nfunction setupDebugMode() {\n  // The debug.html page always runs on the top window context, vs normal\n  // tests run in a context frame.\n  const isDebug = window === top;\n\n  if (isDebug) {\n    // In the debug mode, the timeout is extended to an hour.\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = DEBUG_TIMEOUT;\n  }\n\n  let resumeCallback = null;\n\n  self.karmaPause = () => {\n    if (!isDebug) {\n      //eslint-disable-next-line no-console\n      console.error(\n        'No pausing in a non-debug mode. ' +\n          'Go to http://localhost:9876/debug.html for debugging.'\n      );\n      return undefined;\n    }\n\n    if (resumeCallback) {\n      // Already paused.\n      //eslint-disable-next-line no-console\n      console.error('Karma is already paused. Call karmaResume() to resume.');\n      return undefined;\n    }\n\n    //eslint-disable-next-line no-console\n    console.info('Karma paused. Call karmaResume() to resume.');\n    return new Promise((resolve) => {\n      resumeCallback = resolve;\n      setTimeout(() => {\n        resumeCallback = null;\n        resolve();\n      }, DEBUG_TIMEOUT);\n    });\n  };\n\n  self.karmaResume = () => {\n    if (!isDebug) {\n      return;\n    }\n    if (!resumeCallback) {\n      return;\n    }\n    resumeCallback();\n    resumeCallback = null;\n    //eslint-disable-next-line no-console\n    console.info('Karma resumed.');\n  };\n}\n\nbeforeAll(() => {\n  jasmine.getEnv().addReporter({\n    specStarted(result) {\n      currentSpec = result;\n    },\n    specDone() {\n      currentSpec = null;\n    },\n  });\n\n  setupDebugMode();\n\n  self.karmaSnapshot = (name) => {\n    return karmaPuppeteer.saveSnapshot(currentSpec?.fullName, name);\n  };\n\n  /*eslint-disable no-console*/\n\n  // Suppress react-dom/server error messages during tests.\n  withCleanupAll(() => {\n    const originalConsoleError = console.error;\n\n    console.error = (...args) => {\n      if (\n        args[0].includes('Warning: useLayoutEffect does nothing on the server')\n      ) {\n        return;\n      }\n\n      originalConsoleError(...args);\n    };\n\n    return () => {\n      console.error = originalConsoleError;\n    };\n  });\n\n  /*eslint-enable no-console*/\n\n  // Disable transitions. These add unnecessarily flakiness into integration\n  // tests and snapshots/screenshots.\n  withCleanupAll(() => {\n    const testRootStyles = document.createElement('style');\n    testRootStyles.setAttribute('data-desc', 'Karma test-root styles');\n    testRootStyles.textContent = `\n      * {\n        transition-property: none !important;\n        transition-delay: 0s !important;\n        transition-duration: 0s !important;\n      }\n    `;\n    document.head.appendChild(testRootStyles);\n    return () => {\n      testRootStyles.remove();\n    };\n  });\n\n  // By default Jasmine doesn't report unhandled promise rejections.\n  // But with `act()` it's very easy to do. So this is patched for Jasmine\n  // here until the relevant issues are addressed.\n  // See https://github.com/karma-runner/karma-jasmine/issues/184\n  // See https://eng.wealthfront.com/2016/11/03/handling-unhandledrejections-in-node-and-the-browser/\n  withCleanupAll(() => {\n    const handler = (evt) => {\n      throw evt.reason?.stack || evt.reason || evt;\n    };\n    self.addEventListener('unhandledrejection', handler);\n    return () => {\n      self.removeEventListener('unhandledrejection', handler);\n    };\n  });\n\n  // Make sure that testing iframe takes over the whole screen. This way, the\n  // native events can be targeted precisely.\n  // The documented approach is to supply our own\n  // [client_with_context.html](https://github.com/karma-runner/karma/blob/master/static/client_with_context.html)\n  // file via [customClientContextFile](http://karma-runner.github.io/5.0/config/configuration-file.html)\n  // configuration option. But, IMHO, that'd make it a much more fragile\n  // dependency.\n  withCleanupAll(() => {\n    const frameElement = self.frameElement;\n    if (!frameElement) {\n      return undefined;\n    }\n    frameElement.style.position = 'absolute';\n    frameElement.style.top = '0';\n    frameElement.style.left = '0';\n    return () => {\n      frameElement.style.position = '';\n      frameElement.style.top = '';\n      frameElement.style.left = '';\n    };\n  });\n\n  // Add custom matchers inspired by jest's and jest-dom's ditto\n  jasmine.addMatchers({\n    toBeEmpty: () => ({\n      compare: (actual) => {\n        const innerHTML = actual?.innerHTML ?? '';\n        const pass = innerHTML === '';\n        return {\n          pass,\n          message: pass\n            ? `Expected element to not be empty`\n            : `Expected element to be empty`,\n        };\n      },\n    }),\n    toHaveFocus: () => ({\n      compare: (actual) => {\n        const doc = actual?.ownerDocument || actual?.document;\n        const pass = doc.activeElement === actual;\n        return {\n          pass,\n          message: pass\n            ? `Expected element ${actual} to not have focus`\n            : `Expected element ${actual} to have focus, but focus is on ${doc.activeElement}`,\n        };\n      },\n    }),\n    toHaveStyle: (util, customEqualityTesters) => ({\n      compare: (element, property, expected) => {\n        const actual = element\n          ? window.getComputedStyle(element)[property]\n          : null;\n        const pass = util.equals(actual, expected, customEqualityTesters);\n        return {\n          pass,\n          message: pass\n            ? `Expected element to not have style \"${property}: ${expected}\"`\n            : `Expected element to have style \"${property}: ${expected}\" but found \"${actual}\"`,\n        };\n      },\n    }),\n    toHaveProperty: (util, customEqualityTesters) => ({\n      compare: (element, property, expected) => {\n        const actual = element?.[property] ?? '';\n        const pass =\n          typeof expected === 'string'\n            ? util.equals(actual, expected, customEqualityTesters)\n            : expected.test(actual);\n        return {\n          pass,\n          message: pass\n            ? `Expected element to not have ${property} = \"${expected}\"`\n            : `Expected element to have ${property} = \"${expected}\" but found \"${actual}\"`,\n        };\n      },\n    }),\n    toHaveTextContent: (util, customEqualityTesters) => ({\n      compare: (element, expected) => {\n        const actual = element.textContent.trim();\n        const pass = util.equals(actual, expected, customEqualityTesters);\n        return {\n          pass,\n          message: pass\n            ? `Expected element to not have text content \"${expected}\"`\n            : `Expected element to have text content \"${expected}\" but found \"${actual}\"`,\n        };\n      },\n    }),\n    toBeOneOf: (util, customEqualityTesters) => ({\n      compare: (actual, expecteds) => {\n        const passer = (expected) =>\n          util.equals(actual, expected, customEqualityTesters);\n        const pass = expecteds.some(passer);\n        return {\n          pass,\n          message: pass\n            ? `Expected value to not be in list: ${expecteds.join(\n                ', '\n              )}, received: ${actual}\"`\n            : `Expected value to be in list: ${expecteds.join(\n                ', '\n              )}, received: ${actual}\"`,\n        };\n      },\n    }),\n  });\n\n  jasmine.addAsyncMatchers({\n    toHaveNoViolations: () => ({\n      compare: async (element, options) => {\n        const result = await window.axe.run(element, options);\n        const pass = result.violations.length === 0;\n\n        const formattedViolations = result.violations.map((violation) => {\n          const { id, impact, description, help, helpUrl } = violation;\n\n          const message = [];\n\n          message.push(`[ ${id}] ${description}`);\n          message.push(helpUrl ? `${help} (${helpUrl}` : help);\n          message.push(`Impact: ${impact}`);\n          message.push('\\n');\n\n          for (const { html, failureSummary } of violation.nodes) {\n            message.push(`HTML: ${html}`);\n            message.push(failureSummary);\n            message.push('\\n');\n          }\n\n          return message.join('\\n');\n        });\n\n        const message = !pass\n          ? `Expected element to pass aXe accessibility tests. Violations found:\n            ${formattedViolations.join('\\n')}`\n          : 'Expected element to contain aXe accessibility test violations. No violations found.';\n\n        return {\n          pass,\n          message: () => message,\n        };\n      },\n    }),\n  });\n\n  // Virtual cursor.\n  withCleanupAll(() => {\n    const el = document.createElement('div');\n    el.id = '__karma__cursor';\n    el.className = 'i__karma__snapshot__hide';\n    el.style.cssText = `\n      width: 0px;\n      height: 0px;\n      border-left: 10px solid red;\n      border-bottom: 10px solid transparent;\n      position: fixed;\n      top: 0px;\n      left: 0px;\n      z-index: 2147483647;\n      pointer-events: none;\n    `;\n    document.body.appendChild(el);\n\n    let clientX = -9999;\n    let clientY = -9999;\n    let scheduled = false;\n\n    const move = (evt) => {\n      clientX = evt.clientX;\n      clientY = evt.clientY;\n      if (!scheduled) {\n        scheduled = true;\n        requestAnimationFrame(() => {\n          scheduled = false;\n          el.style.transform = `translate(${clientX}px, ${clientY}px)`;\n        });\n      }\n    };\n\n    document.addEventListener('mousemove', move, true);\n    document.addEventListener('drag', move, true);\n    return () => {\n      document.removeEventListener('mousemove', move, true);\n      document.removeEventListener('drag', move, true);\n    };\n  });\n});\n\nafterAll(() => {\n  if (cleanupsAll) {\n    const toCleanup = cleanupsAll.slice(0);\n    cleanupsAll = undefined;\n    toCleanup.forEach((cleanup) => {\n      if (cleanup) {\n        cleanup();\n      }\n    });\n  }\n});\n\nbeforeEach(async () => {\n  // @todo: ideally we can find a way to use a new <body> for each test, but\n  // there are too many browser APIs to patch to make it consistent.\n\n  // @todo: ideally we can find a way to use a new <head> for each test, but\n  // styled-components uses some side-effect-y global constants to manage\n  // the stylesheet state, e.g. `masterSheet`.\n  // See https://github.com/styled-components/styled-components/blob/4add697ac770634300f7775fc880882b5497bdf4/packages/styled-components/src/models/StyleSheetManager.js#L25\n\n  rootEl = document.createElement('test-root');\n  rootEl.style.cssText = `\n    display: block;\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    margin: 0;\n  `;\n  document.body.appendChild(rootEl);\n  // The below is added to make the body element cover the entire window, as\n  // the app above is fixed-positioned. This ensures proper placement of\n  // popups in karma test runs.\n  document.body.cssText = `\n    height: 100vh;\n    width: 100vw;\n    margin: 0;\n  `;\n\n  // Each test should start with the pointer in the same location ([-1,-1]) to\n  // avoid pointerover/mouseover/hover flakes.\n  await karmaPuppeteer.mouse.seq([{ type: 'move', x: -1, y: -1 }]);\n});\n\nafterEach(() => {\n  rootEl.remove();\n});\n"
  },
  {
    "path": "packages/karma-puppeteer-client/.eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true\n  },\n  \"overrides\": [\n    {\n      \"files\": [\n        \"client.js\"\n      ],\n      \"env\": {\n        \"browser\": true,\n        \"es6\": false\n      },\n      \"rules\": {\n        \"no-unused-vars\": \"off\",\n        \"prefer-rest-params\": \"off\",\n        \"prefer-spread\": \"off\"\n      },\n      \"globals\": {\n        \"karmaPuppeteer\": \"writable\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/karma-puppeteer-client/README.md",
    "content": "# karma-puppeteer-client\n\nThe karma-puppeteer-launcher exposes a few Puppeteer APIs, mainly related to native\nevents and native browser support. The APIs are exposed via `karmaPuppeteer` global.\n\nNotice, that all exposed Puppeteer APIs that accept an element selector, also\naccept the element reference in its place. Thus, both of these forms are valid:\n\n```js\nkarmaPuppeteer.click('.element1'); // Valid. Finds the element by the selector.\nkarmaPuppeteer.click(element1); // Also valid. Passes the element by reference.\n```\n\n## Supported APIs\n\n### karmaPuppeteer.click\n\nSee [puppeteer.click](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pageclickselector-options).\n\n### karmaPuppeteer.focus\n\nSee [puppeteer.focus](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagefocusselector).\n\n### karmaPuppeteer.select\n\nSee [puppeteer.select](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#frameselectselector-values).\n\n### karmaPuppeteer.keyboard\n\nSee [puppeteer.keyboard](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard).\n\nMethods:\n\n- [`down(key, options)`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboarddownkey-options).\n- [`up(key, options)`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardupkey-options).\n- [`press(key, options)`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardpresskey-options).\n- [`type(text, options)`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardtypetext-options).\n- [`sendCharacter(text, options)`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardsendcharacterchar).\n- `seq([{type: 'up'|'down'|'press', key, options}])` - a sequence of down/up/press.\n\n### karmaPuppeteer.mouse\n\nSee [puppeteer.mouse](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse).\n\nMethods:\n\n- `seq([{type: 'up'|'down'|'press', x, y, options}])` - a sequence of move/down/up/click.\n"
  },
  {
    "path": "packages/karma-puppeteer-client/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/karma-puppeteer-client\",\n  \"description\": \"Karma Puppeteer client\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"karma\",\n    \"puppeteer\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/karma-puppeteer-client/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/activation-notice\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.cjs\",\n  \"peerDependencies\": {\n    \"karma\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/karma-puppeteer-client/src/client.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function () {\n  'use strict';\n\n  function noCleanup() {}\n\n  /**\n   * Runs a function exposed by Puppeteer browser.\n   * See `@web-stories-wp/karma-puppeteer-launcher`.\n   *\n   * @param {string} methodName The name of the karmaPuppeteer method.\n   * @return {*} Function result.\n   */\n  function puppeteerFunction(methodName) {\n    return function () {\n      var args = Array.prototype.slice.call(arguments, 0);\n      var name = '__karma_puppeteer_' + methodName;\n      if (!window[name]) {\n        throw new Error('unknown method: ' + name);\n      }\n      return window[name].apply(null, args);\n    };\n  }\n\n  /**\n   * Runs a function exposed by Puppeteer browser, but replaces the element\n   * provided as an argument with a unique selector. Thus, all Puppeteer APIs\n   * that accept the selector, can also be passed the actual element reference.\n   *\n   * For instance, both are allowed: `click('.element1')` and `click(element1)`.\n   *\n   * @param {string} methodName The name of the karmaPuppeteer method.\n   * @return {*} Function result.\n   */\n  function withSelector(methodName) {\n    var func = puppeteerFunction(methodName);\n    return function () {\n      var args = Array.prototype.slice.call(arguments, 0);\n      var node = args[0] && args[0].nodeType ? args[0] : null;\n      var cleanup = noCleanup;\n      if (node) {\n        var uniqueId = Math.random();\n        node.setAttribute('karma_puppeteer_id', uniqueId);\n        args[0] = '[karma_puppeteer_id=\"' + uniqueId + '\"]';\n        cleanup = function () {\n          node.removeAttribute('karma_puppeteer_id');\n        };\n      }\n      return func.apply(null, args).then(\n        (value) => {\n          cleanup();\n          return value;\n        },\n        (reason) => {\n          cleanup();\n          throw reason;\n        }\n      );\n    };\n  }\n\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard.\n  function keyboard() {\n    function keyboardFunction(name) {\n      return puppeteerFunction('keyboard_' + name);\n    }\n    return {\n      seq: keyboardFunction('seq'),\n      // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardsendcharacterchar\n      sendCharacter: keyboardFunction('sendCharacter'),\n      // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardtypetext-options\n      type: keyboardFunction('type'),\n    };\n  }\n\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse.\n  function mouse() {\n    function mouseFunction(name) {\n      return puppeteerFunction('mouse_' + name);\n    }\n    return {\n      seq: mouseFunction('seq'),\n    };\n  }\n\n  function clipboard() {\n    function clipboardFunction(name) {\n      return puppeteerFunction('clipboard_' + name);\n    }\n    return {\n      copy: clipboardFunction('copy'),\n      paste: clipboardFunction('paste'),\n    };\n  }\n\n  window.karmaPuppeteer = {\n    saveSnapshot: puppeteerFunction('saveSnapshot'),\n    // See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pageclickselector-options\n    click: withSelector('click'),\n    clipboard: clipboard(),\n    // See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagefocusselector\n    focus: withSelector('focus'),\n    // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#framehoverselector\n    hover: withSelector('hover'),\n    // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard.\n    keyboard: keyboard(),\n    // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse.\n    mouse: mouse(),\n    // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#frameselectselector-values\n    select: withSelector('select'),\n  };\n})(typeof window !== 'undefined' ? window : global);\n"
  },
  {
    "path": "packages/karma-puppeteer-client/src/index.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst path = require('path');\n\nfunction createPattern(pattern) {\n  return { pattern, included: true, served: true, watched: false };\n}\n\nfunction initEvents(files) {\n  files.unshift(createPattern(path.join(__dirname, '/client.js')));\n}\n\ninitEvents.$inject = ['config.files'];\n\nmodule.exports = {\n  'framework:@web-stories-wp/karma-puppeteer-client': ['factory', initEvents],\n};\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/.eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true\n  }\n}\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/README.md",
    "content": "# karma-puppeteer-launcher\n\nA Karma browser launcher implemented via [Puppeteer](https://github.com/puppeteer/puppeteer).\n\n## Launch options\n\nSee [puppeteer.launch](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions) for more info.\n\nThe available options are currently exposed via Karma command line args:\n\n- `slowMo`: Slows down Puppeteer operations by the specified amount of milliseconds. Default is `0`.\n- `headless`: Runs in headless mode. Default is `false`.\n\nFor instance, you can run Karma with the following options:\n\n```sh\nnpm run test:karma --headless --slowMo=100\n```\n\n## Exposed functions\n\nThe karma-puppeteer-launcher exposes a few Puppeteer APIs. They are documented\nin the [karma-puppeteer-client](packages/karma-puppeteer-client/README.md) docs.\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/karma-puppeteer-launcher\",\n  \"description\": \"Karma Puppeteer launcher\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"karma\",\n    \"puppeteer\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/karma-puppeteer-launcher/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/karma-puppeteer-launcher\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.cjs\",\n  \"dependencies\": {\n    \"@percy/puppeteer\": \"^2.0.2\"\n  },\n  \"peerDependencies\": {\n    \"karma\": \"*\",\n    \"puppeteer\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/src/index.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst puppeteer = require('puppeteer');\n\n/**\n * Internal dependencies\n */\nconst MouseWithDnd = require('./mouseWithDnd.cjs');\nconst takePercySnapshot = require('./snapshot.cjs');\n\nfunction puppeteerBrowser(baseBrowserDecorator, config) {\n  baseBrowserDecorator(this);\n  this.name = 'karma-puppeteer-launcher';\n\n  let browser = null;\n\n  this._start = async (url) => {\n    const defaultPuppeteerOptions = {\n      product: 'chrome',\n      slowMo: 0,\n      // Only enable for debugging\n      // dumpio: true,\n      headless: false,\n      devtools: false,\n      defaultViewport: null,\n      snapshots: false,\n      // See https://peter.sh/experiments/chromium-command-line-switches/\n      args: [\n        // Disables GPU hardware acceleration.\n        '--disable-gpu',\n        // Disables the sandbox for all process types that are normally sandboxed.\n        '--no-sandbox',\n        // The /dev/shm partition is too small in certain VM environments, causing Chrome to fail or crash.\n        // See http://crbug.com/715363\n        // We use this flag to work-around this issue.\n        '--disable-dev-shm-usage',\n      ],\n    };\n    const puppeteerOptions = {\n      ...defaultPuppeteerOptions,\n      ...(config && config.puppeteer),\n    };\n\n    // See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions.\n    browser = await puppeteer.launch(puppeteerOptions);\n\n    const page = await (async () => {\n      const pages = await browser.pages();\n      const lastPage = pages.length > 0 ? pages[pages.length - 1] : null;\n      if (lastPage && lastPage.url() === 'about:blank') {\n        return lastPage;\n      }\n      return browser.newPage();\n    })();\n\n    // Test APIs.\n    await exposeFunctions(page, puppeteerOptions);\n    browser.on('targetcreated', async (target) => {\n      if (target.type() !== 'page') {\n        // Not a page. E.g. a worker.\n        return;\n      }\n      const newPage = await target.page();\n      if (newPage === page) {\n        // An already handled page.\n        return;\n      }\n      await exposeFunctions(newPage, puppeteerOptions);\n    });\n\n    await page.goto(url);\n  };\n\n  this.on('kill', async (done) => {\n    if (browser !== null) {\n      await browser.close();\n    }\n    done();\n  });\n}\n\nasync function exposeFunctions(page, config) {\n  // Save snapshot.\n  await exposeFunction(\n    page,\n    'saveSnapshot',\n    async (frame, testName, snapshotName, options) => {\n      if (!process.env?.PERCY_TOKEN) {\n        // Do nothing unless snapshots are enabled.\n        return;\n      }\n\n      await takePercySnapshot(frame, testName, snapshotName, options);\n    }\n  );\n\n  // click.\n  // See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#frameclickselector-options\n  await exposeFunction(page, 'click', (frame, selector, options) => {\n    return frame.click(selector, options);\n  });\n\n  // focus.\n  // See https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagefocusselector\n  await exposeFunction(page, 'focus', (frame, selector, options) => {\n    return frame.focus(selector, options);\n  });\n\n  // hover.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#framehoverselector\n  await exposeFunction(page, 'hover', (frame, selector, options) => {\n    return frame.hover(selector, options);\n  });\n\n  // select.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#frameselectselector-values\n  await exposeFunction(page, 'select', (frame, selector, values) => {\n    return frame.select(selector, ...values);\n  });\n\n  // keyboard.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard\n  await exposeKeyboardFunctions(page);\n\n  // mouse.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse\n  await exposeMouseFunctions(page);\n\n  // clipboard.\n  await exposeClipboard(page);\n}\n\nfunction exposeFunction(page, name, func) {\n  return page.exposeFunction(`__karma_puppeteer_${name}`, (...args) => {\n    return func(getContextFrame(page), ...args);\n  });\n}\n\nasync function exposeKeyboardFunctions(page) {\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard\n  const { keyboard } = page;\n\n  function exposeKeyboardFunction(name, func) {\n    return exposeFunction(page, `keyboard_${name}`, func);\n  }\n\n  // Keyboard sequence.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-keyboard\n  await exposeKeyboardFunction('seq', (frame, seq) => {\n    return seq.reduce((promise, item) => {\n      const { type, key, options } = item;\n      return promise.then(() => keyboard[type](key, options));\n    }, Promise.resolve());\n  });\n\n  // Keyboard sendCharacter.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardsendcharacterchar\n  await exposeKeyboardFunction('sendCharacter', (frame, char) => {\n    return keyboard.sendCharacter(char);\n  });\n\n  // Keyboard type.\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#keyboardtypetext-options\n  await exposeKeyboardFunction('type', (frame, text, options) => {\n    return keyboard.type(text, options);\n  });\n}\n\nasync function exposeMouseFunctions(page) {\n  // See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse\n  const mouseForFrame = new Map();\n\n  function getMouse(frame) {\n    if (!mouseForFrame.has(frame)) {\n      mouseForFrame.set(frame, new MouseWithDnd(page, frame));\n    }\n    return mouseForFrame.get(frame);\n  }\n\n  function exposeMouseFunction(name, func) {\n    return exposeFunction(page, `mouse_${name}`, func);\n  }\n\n  // Mouse sequence of \"down\", \"up\", \"move\", and \"click\".\n  await exposeMouseFunction('seq', (frame, seq) => {\n    const mouse = getMouse(frame);\n    return seq.reduce((promise, item) => {\n      const { type, x, y, options } = item;\n      const acceptsXY = type === 'move' || type === 'click';\n      if (acceptsXY) {\n        return promise.then(() => mouse[type](x, y, options));\n      }\n      return promise.then(() => mouse[type](options));\n    }, Promise.resolve());\n  });\n}\n\nasync function exposeClipboard(page) {\n  await page\n    .browserContext()\n    .overridePermissions('http://localhost:9876', [\n      'clipboard-read',\n      'clipboard-write',\n    ]);\n\n  function exposeClipboardFunction(name, func) {\n    return exposeFunction(page, `clipboard_${name}`, func);\n  }\n\n  // @todo: Drop the local clipboardData once `navigator.clipboard.read()`\n  // supports text/html. It will be a lot better since it will also support\n  // native clipboard. OTOH, there's something good in not running tests on\n  // a real clipboard. E.g. a test cannot accidentally copy/print a secret\n  // value.\n  // See the https://crbug.com/931839 for \"text/html\" support.\n  let clipboardData;\n\n  // @todo: Implement `cut` and `set()`.\n\n  // Copy.\n  await exposeClipboardFunction('copy', async (frame) => {\n    clipboardData = await frame.evaluateHandle(() => {\n      // @todo: do `document.execCommand('copy')` inside an input or\n      // a contenteditable.\n      const target = document.activeElement;\n      const data = new DataTransfer();\n      const event = new ClipboardEvent('copy', {\n        bubbles: true,\n        cancelable: true,\n        clipboardData: data,\n      });\n      target.dispatchEvent(event);\n      return data;\n    });\n  });\n\n  // Paste.\n  await exposeClipboardFunction('paste', async (frame) => {\n    if (!clipboardData) {\n      throw new Error('clipboard is empty');\n    }\n    await frame.evaluate((data) => {\n      // @todo: do `document.execCommand('paste')` inside an input or\n      // a contenteditable.\n      const target = document.activeElement;\n      const event = new ClipboardEvent('paste', {\n        bubbles: true,\n        cancelable: true,\n        clipboardData: data,\n      });\n      target.dispatchEvent(event);\n    }, clipboardData);\n  });\n}\n\nfunction getContextFrame(page) {\n  return (\n    page.frames().find((frame) => frame.name() === 'context') ||\n    page.mainFrame()\n  );\n}\n\npuppeteerBrowser.$inject = ['baseBrowserDecorator', 'config.puppeteerLauncher'];\n\nmodule.exports = {\n  'launcher:karma-puppeteer-launcher': ['type', puppeteerBrowser], // Could not use @web-stories-wp/ because it does not accept symbols in name.\n};\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/src/mouseWithDnd.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst DndMode = {\n  OFF: 0,\n  MAYBE: 1,\n  ON: 2,\n};\n\n/**\n * Supports the Puppeteer Mouse interface with DND simulation.\n * See https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#class-mouse\n */\nclass MouseWithDnd {\n  /**\n   * @param {Object} page Page.\n   * @param {Object} frame Frame.\n   */\n  constructor(page, frame) {\n    this._page = page;\n    this._mouse = page.mouse;\n    this._xy = [-1, -1];\n    this._dndMode = DndMode.OFF;\n    this._client = new DndClientBinding(frame);\n  }\n\n  async click(x, y, options = {}) {\n    this._cancelDnd();\n    await this._mouse.click(x, y, options);\n  }\n\n  async down(options = {}) {\n    this._cancelDnd();\n    const [x, y] = this._xy;\n    const canStartDnd = await this._client.canStart(x, y);\n    if (canStartDnd) {\n      this._dndMode = DndMode.MAYBE;\n    }\n    return this._mouse.down(options);\n  }\n\n  async move(x, y, options = {}) {\n    const [startX, startY] = this._xy;\n    this._xy = [x, y];\n    if (this._dndMode === DndMode.MAYBE) {\n      const startResult = await this._client.start(startX, startY);\n      this._dndMode = startResult ? DndMode.ON : DndMode.OFF;\n    }\n    if (this._dndMode === DndMode.ON) {\n      const steps = options.steps || 1;\n      const dx = (x - startX) / steps;\n      const dy = (y - startY) / steps;\n      for (let i = 1; i <= steps; i++) {\n        const ix = i === steps ? x : startX + i * dx;\n        const iy = i === steps ? y : startY + i * dy;\n        // eslint-disable-next-line no-await-in-loop\n        await this._client.drag(ix, iy);\n      }\n    } else {\n      await this._mouse.move(x, y, options);\n    }\n  }\n\n  async up(options = {}) {\n    if (this._dndMode === DndMode.ON) {\n      this._dndMode = DndMode.OFF;\n      const [endX, endY] = this._xy;\n      await this._client.end(endX, endY);\n    } else {\n      this._dndMode = DndMode.OFF;\n      await this._mouse.up(options);\n    }\n  }\n\n  async _cancelDnd() {\n    if (this._dndMode !== DndMode.OFF) {\n      if (this._dndMode === DndMode.ON) {\n        const [endX, endY] = this._xy;\n        await this._client.end(endX, endY, /* canceled */ true);\n      }\n      this._dndMode = DndMode.OFF;\n    }\n  }\n\n  async wheel(options = {}) {\n    await this._mouse.wheel(options);\n  }\n}\n\n/**\n * The binding to the client running in the page.\n */\nclass DndClientBinding {\n  /**\n   * @param {Object} context Context.\n   */\n  constructor(context) {\n    this._context = context;\n\n    // Start client initialization right away.\n    this._whenClientReady();\n  }\n\n  /**\n   * @return {Promise} Resolves when client is ready.\n   */\n  _whenClientReady() {\n    return this._context.evaluate(() => {\n      if (window.__karma_dnd) {\n        // Already handled.\n        return;\n      }\n\n      class DndClient {\n        constructor() {\n          this._draggable = null;\n          this._dataTransfer = null;\n          this._target = null;\n          this._dropping = false;\n\n          document.addEventListener(\n            'dragstart',\n            (e) => {\n              if (e.isTrusted) {\n                e.preventDefault();\n                e.stopPropagation();\n                if (e.stopImmediatePropagation) {\n                  e.stopImmediatePropagation();\n                }\n              }\n            },\n            true\n          );\n        }\n\n        /**\n         * @param {number} clientX X coordinates.\n         * @param {number} clientY Y coordinates.\n         * @return {boolean} Returns `true` if DND can be started at these\n         * coordinates.\n         */\n        canStart(clientX, clientY) {\n          this._draggable = this._getDraggable(clientX, clientY);\n          return Boolean(this._draggable);\n        }\n\n        /**\n         * @param {number} clientX X coordinates.\n         * @param {number} clientY Y coordinates.\n         * @return {boolean} Returns `true` if DND has successfully started.\n         */\n        start(clientX, clientY) {\n          const dataTransfer = (this._dataTransfer = new DataTransfer());\n          return this._dispatchEvent(this._draggable, 'dragstart', {\n            cancelable: true,\n            clientX,\n            clientY,\n            dataTransfer,\n          });\n        }\n\n        /**\n         * @param {number} clientX X coordinates.\n         * @param {number} clientY Y coordinates.\n         * @param {boolean} canceled Whether the event is canceled.\n         */\n        end(clientX, clientY, canceled) {\n          const dataTransfer = this._dataTransfer;\n          const dropping = this._dropping;\n          const target = this._target;\n          const draggable = this._draggable;\n\n          this._draggable = null;\n          this._dataTransfer = null;\n          this._target = null;\n          this._dropping = false;\n\n          if (dropping && !canceled) {\n            this._dispatchEvent(target, 'drop', {\n              cancelable: false,\n              clientX,\n              clientY,\n              dataTransfer,\n            });\n          } else {\n            this._dispatchEvent(target, 'dragleave', {\n              cancelable: false,\n              clientX,\n              clientY,\n              dataTransfer,\n            });\n          }\n          this._dispatchEvent(draggable, 'dragend', {\n            cancelable: false,\n            clientX,\n            clientY,\n            dataTransfer,\n          });\n        }\n\n        /**\n         * @param {number} clientX X coordinates.\n         * @param {number} clientY Y coordinates.\n         */\n        drag(clientX, clientY) {\n          const dataTransfer = this._dataTransfer;\n          const oldTarget = this._target;\n          const target = document.elementFromPoint(clientX, clientY);\n          if (target !== oldTarget) {\n            // Change the drop targets.\n            this._target = target;\n            // It's very important that the \"dragenter\" is sent before\n            // \"dragleave\".\n            if (target) {\n              this._dropping = !this._dispatchEvent(target, 'dragenter', {\n                cancelable: true,\n                clientX,\n                clientY,\n                dataTransfer,\n              });\n            }\n            if (oldTarget) {\n              this._dispatchEvent(oldTarget, 'dragleave', {\n                cancelable: false,\n                clientX,\n                clientY,\n                dataTransfer,\n              });\n            }\n          }\n          this._dropping = !this._dispatchEvent(this._target, 'dragover', {\n            cancelable: true,\n            clientX,\n            clientY,\n            dataTransfer,\n          });\n          this._dispatchEvent(this._draggable, 'drag', {\n            cancelable: true,\n            clientX,\n            clientY,\n            dataTransfer,\n          });\n        }\n\n        _getDraggable(clientX, clientY) {\n          const topElement = document.elementFromPoint(clientX, clientY);\n          if (topElement) {\n            for (let n = topElement; n; n = n.parentElement) {\n              const element = n;\n              const draggableAttr = element.getAttribute('draggable');\n              if (draggableAttr === 'false') {\n                continue;\n              }\n              if (element.tagName === 'IMG' || draggableAttr === 'true') {\n                return element;\n              }\n            }\n          }\n          return null;\n        }\n\n        _dispatchEvent(target, type, options) {\n          const event = new DragEvent(type, {\n            bubbles: true,\n            ...options,\n          });\n          return target.dispatchEvent(event);\n        }\n      }\n      window.__karma_dnd = new DndClient();\n    });\n  }\n\n  /**\n   * @param {number} clientX X coordinates.\n   * @param {number} clientY Y coordinates.\n   * @return {Promise<boolean>} Returns `true` if DND can be started at these\n   * coordinates.\n   */\n  async canStart(clientX, clientY) {\n    await this._whenClientReady();\n    return this._context.evaluate(\n      (ax, ay) => window.__karma_dnd.canStart(ax, ay),\n      clientX,\n      clientY\n    );\n  }\n\n  /**\n   * @param {number} clientX X coordinates.\n   * @param {number} clientY Y coordinates.\n   * @return {Promise<boolean>} Returns `true` if DND has successfully started.\n   */\n  async start(clientX, clientY) {\n    await this._whenClientReady();\n    return this._context.evaluate(\n      (ax, ay) => window.__karma_dnd.start(ax, ay),\n      clientX,\n      clientY\n    );\n  }\n\n  /**\n   * @param {number} clientX X coordinates.\n   * @param {number} clientY Y coordinates.\n   * @return {Promise} Resolves when the event has been processed.\n   */\n  async drag(clientX, clientY) {\n    await this._whenClientReady();\n    return this._context.evaluate(\n      (ax, ay) => window.__karma_dnd.drag(ax, ay),\n      clientX,\n      clientY\n    );\n  }\n\n  /**\n   * Completes the DND sequence.\n   *\n   * @param {number} clientX X coordinates.\n   * @param {number} clientY Y coordinates.\n   * @param {boolean} canceled Whether the event is canceled.\n   * @return {Promise} Resolves when the event has been processed.\n   */\n  async end(clientX, clientY, canceled = false) {\n    await this._whenClientReady();\n    return this._context.evaluate(\n      (x, y, canceld) => window.__karma_dnd.end(x, y, canceld),\n      clientX,\n      clientY,\n      canceled\n    );\n  }\n}\n\nmodule.exports = MouseWithDnd;\n"
  },
  {
    "path": "packages/karma-puppeteer-launcher/src/snapshot.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst percySnapshot = require('@percy/puppeteer');\n\n/**\n * @param {Object} frame Frame.\n * @param {string} testName Test name.\n * @param {string} snapshotName Snapshot name.\n * @param {Object} options Additional options to pass through\n */\nasync function takePercySnapshot(\n  frame,\n  testName,\n  snapshotName,\n  options = {}\n) {\n  if (!testName) {\n    testName = '_';\n  }\n  testName = testName.trim();\n  if (!snapshotName) {\n    snapshotName = 'default';\n  }\n  snapshotName = snapshotName.trim();\n\n  await percySnapshot(frame, `${testName}: ${snapshotName}`, options);\n}\n\nmodule.exports = takePercySnapshot;\n"
  },
  {
    "path": "packages/masks/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/masks/README.md",
    "content": "# Masks\n\n---\n\nMasks package for story-editor elements\n"
  },
  {
    "path": "packages/masks/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/masks\",\n  \"description\": \"Masks package for story-editor elements\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/masks/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/masks\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 16\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"prop-types\": \"^15.8.0\",\n    \"styled-components\": \"^5.3.11\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/masks/src/borderedMaskedElement.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getTransformFlip } from '@googleforcreators/elements';\nimport type {\n  Element,\n  Mask,\n  BackgroundableElement,\n} from '@googleforcreators/elements';\nimport type { ReactNode, CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { MaskTypes } from './constants';\nimport {\n  getElementMask,\n  canSupportMultiBorder,\n  getBorderedMaskProperties,\n} from './masks';\nimport { getBorderColor } from './utils/elementBorder';\n\nconst FILL_STYLE: CSSProperties = {\n  position: 'absolute',\n  top: 0,\n  left: 0,\n  right: 0,\n  bottom: 0,\n};\n\nconst SVG_STYLE: CSSProperties = {\n  position: 'absolute',\n  top: 0,\n  left: 0,\n  right: 0,\n  bottom: 0,\n  height: '100%',\n  width: '100%',\n};\n\ninterface MaskedElementProps {\n  style: CSSProperties;\n  id: string;\n  mask: Mask;\n  children: ReactNode;\n}\n\nfunction MaskedElement({\n  style,\n  id,\n  mask: { ratio, path },\n  children,\n  ...rest\n}: MaskedElementProps) {\n  return (\n    <div\n      style={{\n        ...style,\n        clipPath: `url(#${id})`,\n        // stylelint-disable-next-line\n        WebkitClipPath: `url(#${id})`,\n      }}\n      {...rest}\n    >\n      <svg width={0} height={0}>\n        <defs>\n          <clipPath\n            id={id}\n            transform={`scale(1 ${ratio || 1})`}\n            clipPathUnits=\"objectBoundingBox\"\n          >\n            <path d={path} />\n          </clipPath>\n        </defs>\n      </svg>\n      {children}\n    </div>\n  );\n}\n\ninterface BorderedMaskedElementProps {\n  element: Element;\n  style?: CSSProperties;\n  children?: ReactNode;\n  applyFlip?: boolean;\n  hasFill: boolean;\n  getBorderWidth: () => number;\n  postfix?: string;\n  elementWidth: number;\n  elementHeight: number;\n  forceRectangularMask: boolean;\n}\n\nfunction elementAsBackground(\n  element: Element\n): element is BackgroundableElement {\n  return 'isBackground' in element;\n}\n\nfunction BorderedMaskedElement({\n  hasFill = false,\n  style,\n  children,\n  applyFlip = true,\n  postfix = '',\n  getBorderWidth,\n  element,\n  elementWidth,\n  elementHeight,\n  forceRectangularMask = false,\n  ...rest\n}: BorderedMaskedElementProps) {\n  // This component is used twice - random id appended to make sure\n  // id is unique for the Mask.\n  const randomId = useMemo(() => uuidv4(), []);\n  const mask = getElementMask(element);\n  const { id, flip, border } = element;\n\n  const flipTransform = (applyFlip && flip && getTransformFlip(flip)) || '';\n\n  const actualTransform = `${style?.transform || ''} ${flipTransform}`.trim();\n\n  const fullStyle: CSSProperties = {\n    ...(hasFill ? FILL_STYLE : {}),\n    ...style,\n    transform: actualTransform || undefined,\n  };\n\n  const borderWidth = getBorderWidth();\n  const borderColor = border?.color\n    ? getBorderColor({ color: border.color })\n    : 'none';\n\n  // If this is rectangular bordered element, just display a CSS border with the element inside\n  if (\n    !mask?.type ||\n    (elementAsBackground(element) &&\n      element.isBackground &&\n      mask.type !== MaskTypes.RECTANGLE) ||\n    forceRectangularMask\n  ) {\n    return (\n      <div style={fullStyle} {...rest}>\n        {children}\n      </div>\n    );\n  }\n\n  const showSingleBorder =\n    !canSupportMultiBorder(element) &&\n    borderWidth > 0 &&\n    borderColor !== 'none';\n\n  // @todo: Chrome cannot do inline clip-path using data: URLs.\n  // See https://bugs.chromium.org/p/chromium/issues/detail?id=1041024.\n  const maskId = `mask-${mask.type}-${id}-display${postfix}-${randomId}`;\n\n  if (showSingleBorder) {\n    const { viewBox, groupTransform, borderWrapperStyle } =\n      getBorderedMaskProperties(mask, borderWidth, elementWidth, elementHeight);\n\n    const borderStyle: CSSProperties = {\n      ...style,\n      ...borderWrapperStyle,\n      transform: actualTransform,\n      pointerEvents: 'none',\n    };\n\n    return (\n      <div style={style}>\n        <div style={borderStyle}>\n          <svg\n            viewBox={viewBox}\n            width=\"100%\"\n            height=\"100%\"\n            preserveAspectRatio=\"none\"\n            style={SVG_STYLE}\n          >\n            <g transform={groupTransform}>\n              <path\n                d={mask.path}\n                stroke={borderColor}\n                strokeWidth={borderWidth}\n                vectorEffect=\"non-scaling-stroke\"\n                fill=\"transparent\"\n              />\n            </g>\n          </svg>\n        </div>\n        <MaskedElement\n          style={{ ...fullStyle, opacity: 1 }}\n          mask={mask}\n          id={maskId}\n          {...rest}\n        >\n          {children}\n        </MaskedElement>\n      </div>\n    );\n  }\n\n  return (\n    <MaskedElement style={fullStyle} mask={mask} id={maskId} {...rest}>\n      {children}\n    </MaskedElement>\n  );\n}\n\nexport default BorderedMaskedElement;\n"
  },
  {
    "path": "packages/masks/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\nimport type { Mask } from '@googleforcreators/elements';\n\nexport const MaskTypes = {\n  HEART: 'heart',\n  STAR: 'star',\n  CIRCLE: 'circle',\n  CIRCLE_2: 'circle-2',\n  RECTANGLE: 'rectangle',\n  TRIANGLE: 'triangle',\n  ROUNDED: 'rounded-rectangle',\n  ROUNDED_2: 'rounded-rectangle-2',\n  PENTAGON: 'pentagon',\n  HEXAGON: 'hexagon',\n  CROSS: 'cross',\n  ARROW: 'arrow',\n  BURST: 'burst',\n  BULLSEYE: 'bullseye',\n  BLOB_1: 'blob-1',\n  BLOB_2: 'blob-2',\n  BLOB_3: 'blob-3',\n  BLOB_4: 'blob-4',\n  BLOB_5: 'blob-5',\n  BLOB_6: 'blob-6',\n  GRID_1: 'grid-1',\n  GRID_2: 'grid-2',\n  GRID_3: 'grid-3',\n  GRID_4: 'grid-4',\n  GRID_5: 'grid-5',\n  GRID_6: 'grid-6',\n  GRID_7: 'grid-7',\n  GRID_8: 'grid-8',\n  BURST_OUTLINE: 'burst-outline',\n  ARROW_1: 'arrow-1',\n  ARROW_2: 'arrow-2',\n  ARROW_3: 'arrow-3',\n  GEOGRAPHY_1: 'geography-1',\n  TWITTER: 'twitter',\n  INSTAGRAM: 'instagram',\n  FACEBOOK: 'facebook',\n  YOUTUBE: 'youtube',\n  BRUSH_STROKE_1: 'brush-stroke-1',\n  BRUSH_STROKE_2: 'brush-stroke-2',\n  CHAT_BUBBLE: 'chat-bubble',\n  CHECK_MARK: 'check-mark',\n  NEW_MUSIC: 'new-music',\n  MUSIC_NOTE: 'music-note',\n  FASHION_ARROW: 'fashion-arrow',\n  FASHION_ARROW_2: 'fashion-arrow-2',\n  WELLBEING_ARROW: 'wellbeing-arrow',\n};\n\nconst ICON_CLIP_PATHS = {\n  [MaskTypes.BLOB_6]: `M0.41,0.99c-0.01,0-0.01,0-0.02,0c-0.04,0-0.09-0.01-0.15-0.03c-0.05-0.01-0.08-0.08-0.1-0.13\n  C0.12,0.79,0.11,0.73,0.11,0.68c0-0.06,0.01-0.13,0.05-0.17c0.06-0.05,0.09-0.08,0.11-0.12C0.3,0.34,0.31,0.3,0.31,0.26\n  c0-0.01,0.01-0.03,0.01-0.04c0.01-0.05,0.03-0.1,0.09-0.16c0.04-0.04,0.1-0.05,0.15-0.05c0.04,0,0.09,0.01,0.14,0.03\n  C0.76,0.06,0.8,0.09,0.83,0.13l0,0c0.03,0.04,0.06,0.09,0.06,0.16c0,0.05-0.03,0.11-0.06,0.17C0.79,0.54,0.77,0.6,0.76,0.64\n  l0,0.02c0,0.02-0.01,0.03-0.01,0.05c-0.01,0.05-0.02,0.1-0.06,0.17C0.66,0.94,0.59,0.96,0.54,0.97C0.5,0.98,0.46,0.99,0.41,0.99z\n   M0.57,0.05C0.57,0.05,0.57,0.05,0.57,0.05c-0.05,0-0.1,0.01-0.12,0.04c-0.06,0.05-0.07,0.1-0.08,0.14c0,0.01-0.01,0.03-0.01,0.04\n  C0.35,0.31,0.34,0.36,0.31,0.41C0.29,0.45,0.25,0.49,0.19,0.54C0.16,0.56,0.15,0.62,0.15,0.67c0,0.05,0.01,0.1,0.03,0.15\n  c0.02,0.06,0.05,0.09,0.07,0.1c0.05,0.02,0.1,0.02,0.14,0.03c0.05,0,0.09-0.01,0.14-0.02c0.06-0.02,0.1-0.03,0.12-0.07\n  C0.68,0.79,0.69,0.75,0.7,0.7c0-0.02,0.01-0.03,0.01-0.05l0-0.02c0.01-0.05,0.03-0.11,0.07-0.2c0.03-0.05,0.05-0.1,0.05-0.14\n  c0-0.04-0.02-0.09-0.05-0.13C0.77,0.13,0.73,0.1,0.69,0.08C0.65,0.06,0.6,0.05,0.57,0.05z`,\n  [MaskTypes.GRID_2]: `M0.8,1H0.2V0H0.8V1z M0.24,0.96h0.53V0.74H0.24V0.96z M0.36,0.71h0.4V0.62h-0.4V0.71z M0.24,0.71h0.09V0.62\n\tH0.24V0.71z M0.24,0.59h0.53V0.04H0.24V0.59z`,\n  [MaskTypes.GRID_3]: `M0.2,1V0.01L0.8,0l0,0.99L0.2,1z M0.24,0.13v0.83l0.52,0l0-0.83H0.24z M0.24,0.1h0.52l0-0.06l-0.52,0V0.1z`,\n  [MaskTypes.GRID_4]: `M0.8,1H0.2V0H0.8V1z M0.24,0.96h0.52V0.04H0.24V0.96z`,\n  [MaskTypes.GRID_5]: `M0.79,1H0.21V0h0.59V1z M0.24,0.96h0.52V0.17H0.24V0.96z M0.24,0.14h0.52v-0.1H0.24V0.14z`,\n  [MaskTypes.GRID_6]: `M 0.791667 , 0.991667 h -0.583333 V 0.008333 h 0.583333 V 0.991667 z  M 0.236111 , 0.963889 h 0.527778 v -0.069444 h -0.527778 V 0.963889 z  M 0.336111 , 0.869444 h 0.427778 v -0.066667 H 0.336111 V 0.869444 z  M 0.236111 , 0.869444 h 0.072222 v -0.066667 H 0.236111 V 0.869444 z  M 0.336111 , 0.775000 h 0.427778 v -0.066667 H 0.336111 V 0.775000 z  M 0.236111 , 0.775000 h 0.072222 v -0.066667 H 0.236111 V 0.775000 z  M 0.336111 , 0.680556 h 0.427778 v -0.066667 H 0.336111 V 0.680556 z  M 0.236111 , 0.680556 h 0.072222 v -0.066667 H 0.236111 V 0.680556 z  M 0.336111 , 0.586111 h 0.427778 v -0.066667 H 0.336111 V 0.586111 z  M 0.236111 , 0.586111 h 0.072222 v -0.066667 H 0.236111 V 0.586111 z  M 0.336111 , 0.494444 h 0.427778 v -0.066667 H 0.336111 V 0.494444 z  M 0.236111 , 0.494444 h 0.072222 v -0.066667 H 0.236111 V 0.494444 z  M 0.336111 , 0.400000 h 0.427778 V 0.333333 H 0.336111 V 0.400000 z  M 0.236111 , 0.400000 h 0.072222 V 0.333333 H 0.236111 V 0.400000 z  M 0.336111 , 0.305556 h 0.427778 V 0.238889 H 0.336111 V 0.305556 z  M 0.236111 , 0.305556 h 0.072222 V 0.238889 H 0.236111 V 0.305556 z  M 0.236111 , 0.211111 h 0.527778 V 0.036111 h -0.527778 V 0.211111 z`,\n  [MaskTypes.GRID_7]: `M0.79,1H0.21V0h0.59V1z M0.43,0.96h0.33V0.87H0.43V0.96z M0.24,0.96H0.4V0.87H0.24V0.96z M0.43,0.84h0.33V0.75\n\tH0.43V0.84z M0.24,0.84H0.4V0.75H0.24V0.84z M0.24,0.71h0.52V0.04H0.24V0.71z`,\n  [MaskTypes.GRID_8]: `M0.8,1H0.2V0H0.8V1z M0.24,0.96h0.53V0.83H0.24V0.96z M0.24,0.8h0.53V0.67H0.24V0.8z M0.24,0.64h0.53V0.51H0.24\n  V0.64z M0.24,0.47h0.53V0.34H0.24V0.47z M0.24,0.31h0.53V0.18H0.24V0.31z M0.24,0.15h0.53V0.04H0.24V0.15z`,\n  [MaskTypes.ARROW_2]: `M0.92,0.59L0.91,0.58L0.98,0.5H0V0.49h0.97L0.91,0.42l0.01-0.01L1,0.5L0.92,0.59z`,\n  [MaskTypes.BURST_OUTLINE]: `M 0.500000 , 0.993333 l -0.054167 -0.065278 l -0.068889 , 0.049722 l -0.036389 -0.076667 l -0.078889 , 0.031111 l -0.016111 -0.083333 l -0.084167 , 0.010556 l 0.005000 -0.084722 l -0.084167 -0.010833 l 0.026111 -0.080833 l -0.078889 -0.031389 l 0.045278 -0.071944 l -0.068333 -0.050000 l 0.061667 -0.058333 l -0.053889 -0.065556 l 0.074167 -0.041111 l -0.035833 -0.076944 l 0.082222 -0.021389 L 0.118889 , 0.182500 l 0.085000 -0.000278 l 0.005556 -0.084722 l 0.082222 , 0.020833 l 0.026389 -0.080556 l 0.074444 , 0.040833 l 0.045833 -0.071667 L 0.500000 , 0.065000 l 0.061944 -0.058056 l 0.045556 , 0.071667 l 0.074444 -0.040833 l 0.026389 , 0.080556 l 0.082222 -0.020833 l 0.005556 , 0.084722 l 0.084722 , 0.000278 l -0.015556 , 0.083611 l 0.082222 , 0.021389 l -0.035833 , 0.076944 l 0.074167 , 0.041111 l -0.053889 , 0.065556 l 0.061667 , 0.058333 l -0.068611 , 0.050000 l 0.045278 , 0.071944 l -0.078889 , 0.031389 l 0.026111 , 0.080833 l -0.084167 , 0.010833 l 0.005000 , 0.084722 l -0.084167 -0.010556 l -0.016111 , 0.083333 l -0.078889 -0.031111 l -0.036389 , 0.076667 l -0.068889 -0.049722 L 0.500000 , 0.993333 z  M 0.448889 , 0.902500 L 0.500000 , 0.964167 l 0.051111 -0.061389 l 0.064722 , 0.046944 l 0.034167 -0.072222 l 0.074444 , 0.029167 l 0.015278 -0.078611 l 0.079167 , 0.009722 l -0.004722 -0.079722 l 0.079167 -0.010278 l -0.024444 -0.076111 l 0.074167 -0.029722 l -0.042500 -0.067500 l 0.064444 -0.047222 l -0.058056 -0.055000 l 0.050833 -0.061667 l -0.070000 -0.038611 l 0.033889 -0.072500 l -0.077222 -0.020000 l 0.014722 -0.078611 l -0.080000 -0.000278 l -0.005278 -0.079722 l -0.077222 , 0.019722 l -0.025000 -0.075833 l -0.070000 , 0.038333 L 0.558333 , 0.035833 L 0.500000 , 0.090278 l -0.058333 -0.054444 l -0.043056 , 0.067500 l -0.070000 -0.038333 l -0.025000 , 0.075833 L 0.226389 , 0.121111 L 0.221111 , 0.200833 L 0.141389 , 0.201111 l 0.014722 , 0.078611 l -0.077222 , 0.020000 l 0.033889 , 0.072500 l -0.070000 , 0.038611 l 0.050833 , 0.061667 l -0.058056 , 0.055000 l 0.064444 , 0.047222 l -0.042778 , 0.067500 l 0.074167 , 0.029444 l -0.024444 , 0.076111 l 0.079167 , 0.010278 l -0.004722 , 0.079722 l 0.079167 -0.009722 l 0.015000 , 0.078611 l 0.074167 -0.029167 l 0.034167 , 0.072222 L 0.448889 , 0.902500 z`,\n};\n\nconst CLIP_PATHS = {\n  [MaskTypes.RECTANGLE]: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n  [MaskTypes.CIRCLE]:\n    'M 0.972222 , 0.500000 c 0.000000 , 0.261111 -0.211111 , 0.472222 -0.472222 , 0.472222 S 0.027778 , 0.761111 , 0.027778 , 0.500000 S 0.238889 , 0.027778 , 0.500000 , 0.027778 S 0.972222 , 0.238889 , 0.972222 , 0.500000 z',\n  [MaskTypes.CIRCLE_2]: 'M 0,0.5 a 0.5,0.5 0 1,0 1,0 a 0.5,0.5 0 1,0 -1,0 Z',\n  [MaskTypes.TRIANGLE]: 'M 0.5 0 L 1 1 L 0 1 Z',\n  [MaskTypes.HEART]:\n    'M.99834689.27724859C.98374997.1165844.87003101.00001922.7277144.00001922c-.0948137 0-.18162681.05102248-.23047608.13279699C.44883142.04998394.36557613 0 .27228183 0 .12998435 0 .01624632.1165652.00166847.27722932c-.00115382.007097-.00588463.0444451.00850059.10535296.0207321.0878518.06861968.1677608.13845102.23103404l.34838744.31615494.35436847-.31613565c.0698315-.0632926.1177191-.14318227.13845114-.23105333.0143856-.0608885.009655-.0982371.00852-.10533369 Z',\n  [MaskTypes.STAR]:\n    'M 0.50000026,0.78688566 0.19262278,0.95082018 0.2500004,0.6065577 0,0.36065594 0.34426194,0.31147556 0.50000026,0 0.65573858,0.31147556 1,0.36065594 0.75000014,0.6065577 0.80737774,0.95082018 Z',\n  [MaskTypes.PENTAGON]:\n    'M 0.50000026,0 1,0.36065593 0.80737774,0.95082017 H 0.19262279 L 0,0.36065593 Z',\n  [MaskTypes.HEXAGON]:\n    'm 0.74863333,0 h -0.494535 L 0,0.42896111 0.25409833,0.86611944 h 0.494535 L 1,0.42896111 Z',\n  [MaskTypes.CROSS]:\n    'M 0.000 0.861 L 0.861 0.000 l 0.089 0.083 L 0.083 0.950 z M 0.089 0.000 l 0.461 0.461 L 0.461 0.556 0.000 0.089 z m 0.561 0.561 l 0.322 0.322 -0.083 0.089 -0.322 -0.322 z',\n  [MaskTypes.ARROW]:\n    'M 0.889 0.433 V 0.494 C 0.913 0.494 0.935 0.480 0.945 0.458 C 0.955 0.435 0.950 0.409 0.933 0.391 L 0.889 0.433 Z  M 0.571 0.932 L 0.876 0.626 L 0.790 0.540 L 0.485 0.846 L 0.571 0.932 Z  M 0.000 0.494 H 0.889 V 0.372 H 0.000 V 0.494 Z  M 0.933 0.391 L 0.578 0.014 L 0.489 0.097 L 0.844 0.475 L 0.933 0.391 Z',\n  [MaskTypes.BURST]:\n    'M 0.496 0.058 L 0.558 0 L 0.604 0.072 L 0.679 0.031 L 0.706 0.112 L 0.788 0.091 L 0.794 0.176 L 0.879 0.177 L 0.863 0.261 L 0.946 0.282 L 0.91 0.359 L 0.984 0.401 L 0.93 0.467 L 0.992 0.525 L 0.923 0.576 L 0.969 0.648 L 0.89 0.68 L 0.916 0.761 L 0.831 0.772 L 0.836 0.857 L 0.752 0.847 L 0.736 0.931 L 0.656 0.899 L 0.62 0.977 L 0.551 0.926 L 0.496 0.992 L 0.442 0.926 L 0.372 0.977 L 0.336 0.899 L 0.257 0.931 L 0.24 0.847 L 0.156 0.857 L 0.161 0.772 L 0.076 0.761 L 0.103 0.68 L 0.023 0.648 L 0.069 0.576 L 0 0.525 L 0.062 0.467 L 0.008 0.401 L 0.082 0.359 L 0.046 0.282 L 0.129 0.261 L 0.113 0.177 L 0.198 0.176 L 0.204 0.091 L 0.287 0.112 L 0.313 0.031 L 0.388 0.072 L 0.434 0 L 0.496 0.058 Z',\n  [MaskTypes.BULLSEYE]: `M 0.500000 , 0.268710 c 0.127742 , 0.000000 , 0.231290 , 0.103548 , 0.231290 , 0.231290 s -0.103548 , 0.231290 -0.231290 , 0.231290 s -0.231290 -0.103548 -0.231290 -0.231290 S 0.372258 , 0.268710 , 0.500000 , 0.268710 z  M 0.500000 , 0.983871 c -0.266774 , 0.000000 -0.483871 -0.217097 -0.483871 -0.483871 s 0.217097 -0.483871 , 0.483871 -0.483871 s 0.483871 , 0.217097 , 0.483871 , 0.483871 S 0.766774 , 0.983871 , 0.500000 , 0.983871 z  M 0.500000 , 0.047419 c -0.249677 , 0.000000 -0.452581 , 0.203226 -0.452581 , 0.452581 s 0.203226 , 0.452581 , 0.452581 , 0.452581 s 0.452581 -0.203226 , 0.452581 -0.452581 S 0.749677 , 0.047419 , 0.500000 , 0.047419 z`,\n  [MaskTypes.BLOB_1]:\n    'M0.830816788,0.220786927 C0.875069274,0.303846138 0.868747722,0.386905348 0.900357103,0.469964559 C0.931968103,0.553023769 1.00150842,0.641273848 0.995186867,0.750290059 C0.995186867,0.854114072 0.925644932,0.973510691 0.818172064,0.994276822 C0.710699195,1.0150403 0.571615327,0.942364151 0.426211524,0.89045148 C0.280806103,0.838540138 0.135400682,0.817775335 0.0658587481,0.739906993 C-0.0100047388,0.667230848 -0.00368318612,0.542642033 0.0216062612,0.423244085 C0.0405709191,0.298655269 0.091146577,0.179257322 0.18597634,0.10138898 C0.287127656,0.0183297695 0.43885463,-0.0180076384 0.565293774,0.0131389011 C0.685411367,0.0390959011 0.78024113,0.132536848 0.830816788,0.220786927 Z',\n  [MaskTypes.BLOB_2]:\n    'M 0.157040 , 0.886024 C 0.081227 , 0.837803 , 0.030944 , 0.761733 , 0.009541 , 0.687983 c -0.023724 -0.081485 -0.006704 -0.152140 , 0.084580 -0.190562 c 0.095152 -0.039969 , 0.144404 -0.089479 , 0.182568 -0.125322 c 0.069108 -0.064724 , 0.073749 -0.121196 , 0.101857 -0.181795 c 0.021919 -0.047189 , 0.063950 -0.091542 , 0.161939 -0.142084 c 0.095926 -0.049510 , 0.175090 -0.063693 , 0.240330 -0.028623 c 0.056730 , 0.030428 , 0.102114 , 0.097473 , 0.142341 , 0.194172 c 0.025529 , 0.060598 , 0.044611 , 0.135121 , 0.065498 , 0.222537 c 0.016503 , 0.070139 , 0.014183 , 0.134605 -0.004126 , 0.194430 c -0.019082 , 0.062919 -0.045900 , 0.125580 -0.096699 , 0.172254 c -0.047705 , 0.043837 -0.119907 , 0.065498 -0.190046 , 0.091542 c -0.069881 , 0.025786 -0.122744 , 0.055441 -0.173801 , 0.068076 c -0.072976 , 0.017793 -0.134348 , 0.028107 -0.193914 , 0.014956 C 0.276173 , 0.965188 , 0.224342 , 0.928314 , 0.157040 , 0.886024 z',\n  [MaskTypes.BLOB_3]:\n    'M 0.205572 , 1.093842 c -0.054252 -0.008798 -0.099413 -0.059824 -0.138710 -0.124340 c -0.033431 -0.054545 -0.055718 -0.117009 -0.063050 -0.179472 c -0.008211 -0.072727 -0.007038 -0.144575 , 0.040762 -0.183578 C 0.119648 , 0.545455 , 0.165396 , 0.498827 , 0.191789 , 0.454545 c 0.047507 -0.080059 , 0.043109 -0.137830 , 0.056012 -0.204106 c 0.009971 -0.051906 , 0.027566 -0.112023 , 0.102933 -0.184457 c 0.041056 -0.039589 , 0.110264 -0.059238 , 0.183578 -0.064809 c 0.062170 -0.004692 , 0.129326 , 0.005572 , 0.193255 , 0.024340 c 0.064809 , 0.018768 , 0.124047 , 0.048974 , 0.170968 , 0.090323 c 0.049267 , 0.043988 , 0.094135 , 0.097654 , 0.100587 , 0.165982 c 0.005279 , 0.055132 -0.024927 , 0.114663 -0.060997 , 0.184751 c -0.058065 , 0.112610 -0.068328 , 0.188563 -0.080352 , 0.247801 c -0.016716 , 0.080938 -0.010264 , 0.143109 -0.067449 , 0.252199 c -0.030792 , 0.058944 -0.102053 , 0.082405 -0.175367 , 0.105279 c -0.061877 , 0.019648 -0.130205 , 0.038710 -0.202346 , 0.039589 C 0.340762 , 1.112903 , 0.268622 , 1.104106 , 0.205572 , 1.093842 z',\n  [MaskTypes.BLOB_4]:\n    'M 0.989829 , 0.233137 C 0.935760 -0.017398 , 0.663544 , 0.008298 , 0.544165 , 0.000000 C 0.259101 , 0.020878 , 0.182281 , 0.213330 , 0.029443 , 0.604122 c -0.153105 , 0.391060 , 0.334315 , 0.384101 , 0.461456 , 0.317719 c 0.071734 -0.037473 , 0.283726 -0.132227 , 0.327623 -0.167827 C 0.862687 , 0.718415 , 1.044165 , 0.483940 , 0.989829 , 0.233137 z',\n  [MaskTypes.BLOB_5]:\n    'M 0.156198 , 0.447658 c 0.151515 -0.094766 , 0.054821 -0.194766 , 0.090634 -0.290634 c 0.113774 -0.373829 , 0.543251 , 0.000000 , 0.702204 , 0.290634 C 1.107989 , 0.738292 , 0.859504 , 0.922865 , 0.700551 , 1.024793 c -0.158953 , 0.102204 -0.196970 , 0.026446 -0.304132 -0.126446 S 0.097245 , 0.836364 , 0.030854 , 0.722590 C -0.035537 , 0.608815 , 0.004683 , 0.542424 , 0.156198 , 0.447658 z',\n  [MaskTypes.BLOB_6]: `M 0.374874 , 1.281615 c -0.006738 , 0.000000 -0.013629 -0.000153 -0.020367 -0.000613 c -0.057119 -0.003216 -0.118986 -0.014548 -0.194634 -0.035680 c -0.044562 -0.012251 -0.082233 -0.061407 -0.118986 -0.154666 c -0.026645 -0.068145 -0.040274 -0.139812 -0.040887 -0.212857 c -0.000153 -0.079630 , 0.006738 -0.166917 , 0.058344 -0.210713 c 0.078558 -0.066460 , 0.126489 -0.117454 , 0.155585 -0.165692 c 0.040274 -0.066920 , 0.050994 -0.120364 , 0.062479 -0.176871 c 0.003675 -0.018070 , 0.007350 -0.036752 , 0.012251 -0.055741 c 0.014701 -0.058344 , 0.037212 -0.127255 , 0.117454 -0.207038 c 0.050381 -0.049616 , 0.126642 -0.060948 , 0.181771 -0.061713 c 0.055435 -0.000766 , 0.116382 , 0.013323 , 0.181158 , 0.042265 c 0.061407 , 0.027105 , 0.114238 , 0.067686 , 0.152828 , 0.117454 l 0.000000 , 0.000000 c 0.034149 , 0.043950 , 0.079324 , 0.112554 , 0.078099 , 0.200300 c -0.000919 , 0.065848 -0.038284 , 0.136137 -0.077639 , 0.210407 c -0.059723 , 0.112554 -0.080243 , 0.193562 -0.096781 , 0.258644 c -0.001991 , 0.007963 -0.003982 , 0.015467 -0.005819 , 0.022970 c -0.006432 , 0.024348 -0.011179 , 0.047625 -0.015926 , 0.070136 c -0.013629 , 0.065389 -0.026339 , 0.127255 -0.075036 , 0.217757 c -0.036752 , 0.068451 -0.111788 , 0.090503 -0.177942 , 0.109951 C 0.495391 , 1.266454 , 0.435974 , 1.281615 , 0.374874 , 1.281615 z  M 0.592478 , 0.001562 c -0.001531 , 0.000000 -0.003063 , 0.000000 -0.004441 , 0.000000 c -0.054975 , 0.000919 -0.130777 , 0.012098 -0.180546 , 0.061713 c -0.079936 , 0.079477 -0.102294 , 0.148081 -0.116995 , 0.206119 c -0.004747 , 0.018836 -0.008576 , 0.037518 -0.012251 , 0.055588 c -0.011026 , 0.054210 -0.022358 , 0.110257 -0.062632 , 0.177483 c -0.029249 , 0.048391 -0.077333 , 0.099538 -0.156044 , 0.165998 c -0.051147 , 0.043337 -0.057885 , 0.130164 -0.057732 , 0.209488 c 0.000459 , 0.072892 , 0.014242 , 0.144406 , 0.040734 , 0.212245 c 0.036446 , 0.092646 , 0.073811 , 0.141496 , 0.117761 , 0.153594 c 0.075495 , 0.020979 , 0.137209 , 0.032311 , 0.194175 , 0.035527 c 0.068145 , 0.003982 , 0.134452 -0.012710 , 0.195859 -0.031393 c 0.065848 -0.019295 , 0.140578 -0.041346 , 0.177024 -0.109185 c 0.048544 -0.090196 , 0.061407 -0.151910 , 0.074883 -0.217298 c 0.004594 -0.022511 , 0.009494 -0.045787 , 0.015926 -0.070136 c 0.001991 -0.007350 , 0.003828 -0.015007 , 0.005819 -0.022970 c 0.016539 -0.065235 , 0.037059 -0.146397 , 0.096781 -0.258951 c 0.039356 -0.074117 , 0.076414 -0.144253 , 0.077486 -0.209641 c 0.001225 -0.087134 -0.043797 -0.155432 -0.077639 -0.199228 l 0.000000 , 0.000000 c -0.038437 -0.049462 -0.091115 -0.089890 -0.152216 -0.116842 C 0.705645 , 0.015803 , 0.646381 , 0.001562 , 0.592478 , 0.001562 z`,\n  [MaskTypes.GRID_1]:\n    'M 0.999 0.999 H 0.001 V 0.001 h 0.998 V 0.999 z  M 0.900 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.801 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.702 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.603 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.504 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.405 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.306 0.992 h 0.091 v -0.091 h -0.091 V 0.992 z  M 0.207 0.992 h 0.091 v -0.091 H 0.207 V 0.992 z  M 0.108 0.992 h 0.091 v -0.091 H 0.108 V 0.992 z  M 0.008 0.992 h 0.091 v -0.091 H 0.008 V 0.992 z  M 0.900 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.801 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.702 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.603 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.504 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.405 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.306 0.892 h 0.091 v -0.091 h -0.091 V 0.892 z  M 0.207 0.892 h 0.091 v -0.091 H 0.207 V 0.892 z  M 0.108 0.892 h 0.091 v -0.091 H 0.108 V 0.892 z  M 0.008 0.892 h 0.091 v -0.091 H 0.008 V 0.892 z  M 0.900 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.801 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.702 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.603 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.504 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.405 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.306 0.793 h 0.091 v -0.091 h -0.091 V 0.793 z  M 0.207 0.793 h 0.091 v -0.091 H 0.207 V 0.793 z  M 0.108 0.793 h 0.091 v -0.091 H 0.108 V 0.793 z  M 0.008 0.793 h 0.091 v -0.091 H 0.008 V 0.793 z  M 0.900 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.801 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.702 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.603 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.504 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.405 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.306 0.694 h 0.091 v -0.091 h -0.091 V 0.694 z  M 0.207 0.694 h 0.091 v -0.091 H 0.207 V 0.694 z  M 0.108 0.694 h 0.091 v -0.091 H 0.108 V 0.694 z  M 0.008 0.694 h 0.091 v -0.091 H 0.008 V 0.694 z  M 0.900 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.801 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.702 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.603 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.504 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.405 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.306 0.595 h 0.091 v -0.091 h -0.091 V 0.595 z  M 0.207 0.595 h 0.091 v -0.091 H 0.207 V 0.595 z  M 0.108 0.595 h 0.091 v -0.091 H 0.108 V 0.595 z  M 0.008 0.595 h 0.091 v -0.091 H 0.008 V 0.595 z  M 0.900 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.801 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.702 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.603 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.504 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.405 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.306 0.496 h 0.091 v -0.091 h -0.091 V 0.496 z  M 0.207 0.496 h 0.091 v -0.091 H 0.207 V 0.496 z  M 0.108 0.496 h 0.091 v -0.091 H 0.108 V 0.496 z  M 0.008 0.496 h 0.091 v -0.091 H 0.008 V 0.496 z  M 0.900 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.801 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.702 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.603 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.504 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.405 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.306 0.397 h 0.091 v -0.091 h -0.091 V 0.397 z  M 0.207 0.397 h 0.091 v -0.091 H 0.207 V 0.397 z  M 0.108 0.397 h 0.091 v -0.091 H 0.108 V 0.397 z  M 0.008 0.397 h 0.091 v -0.091 H 0.008 V 0.397 z  M 0.900 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.801 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.702 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.603 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.504 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.405 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.306 0.298 h 0.091 V 0.207 h -0.091 V 0.298 z  M 0.207 0.298 h 0.091 V 0.207 H 0.207 V 0.298 z  M 0.108 0.298 h 0.091 V 0.207 H 0.108 V 0.298 z  M 0.008 0.298 h 0.091 V 0.207 H 0.008 V 0.298 z  M 0.900 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.801 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.702 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.603 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.504 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.405 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.306 0.199 h 0.091 V 0.108 h -0.091 V 0.199 z  M 0.207 0.199 h 0.091 V 0.108 H 0.207 V 0.199 z  M 0.108 0.199 h 0.091 V 0.108 H 0.108 V 0.199 z  M 0.008 0.199 h 0.091 V 0.108 H 0.008 V 0.199 z  M 0.900 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.801 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.702 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.603 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.504 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.405 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.306 0.100 h 0.091 V 0.008 h -0.091 V 0.100 z  M 0.207 0.100 h 0.091 V 0.008 H 0.207 V 0.100 z  M 0.108 0.100 h 0.091 V 0.008 H 0.108 V 0.100 z  M 0.008 0.100 h 0.091 V 0.008 H 0.008 V 0.100 z',\n  [MaskTypes.GRID_2]: `M 0.000000 , 0.000000 v 1.709945 h 1.000000 V 0.000000 L 0.000000 , 0.000000 L 0.000000 , 0.000000 z  M 0.994475 , 0.005525 v 1.038674 H 0.005525 V 0.005525 L 0.994475 , 0.005525 L 0.994475 , 0.005525 z  M 0.005525 , 1.254696 V 1.049724 h 0.219337 v 0.204972 L 0.005525 , 1.254696 L 0.005525 , 1.254696 z  M 0.230387 , 1.049724 h 0.764365 v 0.204972 H 0.230387 V 1.049724 z  M 0.005525 , 1.704420 V 1.260221 h 0.988950 v 0.444475 H 0.005525 V 1.704420 z`,\n  [MaskTypes.GRID_3]: `M 0.002772 , 0.002772 H 0.000000 v 1.712860 l 0.994457 -0.002772 h 0.002772 l 0.002772 -1.710089 V 0.000000 L 0.002772 , 0.002772 z  M 0.994457 , 0.005543 l -0.000277 , 0.161585 H 0.005543 V 0.008315 L 0.994457 , 0.005543 z  M 0.005543 , 1.710089 V 0.172672 h 0.988636 L 0.991685 , 1.707317 L 0.005543 , 1.710089 z`,\n  [MaskTypes.GRID_4]: `M 1.000000 , 1.712784 H 0.000000 V 0.000000 h 1.000000 L 1.000000 , 1.712784 L 1.000000 , 1.712784 z  M 0.005534 , 1.707250 h 0.988932 V 0.005534 H 0.005534 V 1.707250 z`,\n  [MaskTypes.GRID_5]: `M 1.000000 , 1.718490 H 0.000000 V 0.000000 h 0.999722 v 1.718490 H 1.000000 z  M 0.005552 , 1.712937 h 0.988617 V 0.250416 H 0.005552 V 1.712937 z  M 0.005552 , 0.244864 h 0.988617 V 0.005552 H 0.005552 V 0.244864 z`,\n  [MaskTypes.GRID_6]: `M 1.000000 , 1.719444 H 0.000000 V 0.000000 h 1.000000 V 1.719444 z  M 0.005556 , 1.713889 h 0.988889 v -0.166667 H 0.005556 V 1.713889 z  M 0.183889 , 1.541667 H 0.994444 v -0.162500 H 0.183889 V 1.541667 z  M 0.005556 , 1.541667 h 0.172778 v -0.162500 H 0.005556 V 1.541667 z  M 0.183889 , 1.373611 H 0.994444 V 1.211111 H 0.183889 V 1.373611 z  M 0.005556 , 1.373611 h 0.172778 V 1.211111 H 0.005556 V 1.373611 z  M 0.183889 , 1.205556 H 0.994444 v -0.162500 H 0.183889 V 1.205556 z  M 0.005556 , 1.205556 h 0.172778 v -0.162500 H 0.005556 V 1.205556 z  M 0.183889 , 1.037500 H 0.994444 V 0.875000 H 0.183889 V 1.037500 z  M 0.005556 , 1.037500 h 0.172778 V 0.875000 H 0.005556 V 1.037500 z  M 0.183889 , 0.869444 H 0.994444 v -0.162778 H 0.183889 V 0.869444 z  M 0.005556 , 0.869444 h 0.172778 v -0.162778 H 0.005556 V 0.869444 z  M 0.183889 , 0.701111 H 0.994444 v -0.162500 H 0.183889 V 0.701111 z  M 0.005556 , 0.701111 h 0.172778 v -0.162500 H 0.005556 V 0.701111 z  M 0.183889 , 0.533056 H 0.994444 v -0.162500 H 0.183889 V 0.533056 z  M 0.005556 , 0.533056 h 0.172778 v -0.162500 H 0.005556 V 0.533056 z  M 0.005556 , 0.365000 h 0.988889 V 0.005556 H 0.005556 V 0.365000 z`,\n  [MaskTypes.GRID_7]: `M 1.000000 , 1.711911 H 0.000000 V 0.000000 h 1.000000 V 1.711911 z  M 0.350416 , 1.706371 H 0.994460 v -0.218006 H 0.350416 V 1.706371 z  M 0.005540 , 1.706371 h 0.339335 v -0.218006 H 0.005540 V 1.706371 z  M 0.350416 , 1.482825 H 0.994460 v -0.213573 H 0.350416 V 1.482825 z  M 0.005540 , 1.482825 h 0.339335 v -0.213573 H 0.005540 V 1.482825 z  M 0.005540 , 1.263435 h 0.988920 V 0.005540 H 0.005540 V 1.263435 z`,\n  [MaskTypes.GRID_8]: `M 1.000000 , 1.705234 H 0.000000 V 0.000000 h 1.000000 V 1.705234 z  M 0.005510 , 1.699725 h 0.988981 V 1.417080 H 0.005510 V 1.699725 z  M 0.005510 , 1.411570 h 0.988981 V 1.127548 H 0.005510 V 1.411570 z  M 0.005510 , 1.122039 h 0.988981 v -0.283747 H 0.005510 V 1.122039 z  M 0.005510 , 0.832782 h 0.988981 V 0.548760 H 0.005510 V 0.832782 z  M 0.005510 , 0.543251 h 0.988981 V 0.259229 H 0.005510 V 0.543251 z  M 0.005510 , 0.253719 h 0.988981 V 0.005510 H 0.005510 V 0.253719 z`,\n  [MaskTypes.ARROW_1]: `M 0.987859 , 0.201435 l -0.193157 -0.193157 c -0.011038 -0.011038 -0.033113 -0.011038 -0.044150 , 0.000000 s -0.011038 , 0.033113 , 0.000000 , 0.044150 l 0.143488 , 0.143488 H 0.000000 v 0.060706 h 0.894040 l -0.143488 , 0.143488 c -0.011038 , 0.011038 -0.011038 , 0.033113 , 0.000000 , 0.044150 s 0.033113 , 0.011038 , 0.044150 , 0.000000 l 0.193157 -0.193157 C 1.004415 , 0.234547 , 1.004415 , 0.212472 , 0.987859 , 0.201435 z`,\n  [MaskTypes.ARROW_2]: `M 0.975200 , 0.060200 l -0.003800 -0.003100 l 0.021050 -0.025550 H 0.000000 V 0.026650 h 0.990800 l -0.019400 -0.023550 L 0.975200 , 0.000000 L 1.000000 , 0.030100 L 0.975200 , 0.060200 z`,\n  [MaskTypes.ARROW_3]: `M 0.000000 , 0.386861 V 0.350365 h 0.832117 C 0.664234 , 0.270073 , 0.598540 , 0.124088 , 0.598540 , 0.000000 c 0.007299 , 0.000000 , 0.029197 , 0.000000 , 0.036496 , 0.000000 c 0.000000 , 0.226277 , 0.189781 , 0.350365 , 0.364964 , 0.350365 v 0.036496 c -0.291971 , 0.000000 -0.364964 , 0.255474 -0.364964 , 0.357664 H 0.598540 c 0.000000 -0.204380 , 0.155766 -0.333285 , 0.233577 -0.357664 H 0.000000 z`,\n  [MaskTypes.GEOGRAPHY_1]: `M 0.001020 , 0.241045 c 0.015379 , 0.019302 , 0.031033 , 0.003845 , 0.046451 , 0.000000 c 0.001805 -0.000510 , 0.004119 -0.004119 , 0.003845 -0.005924 c -0.002315 -0.012868 , 0.004119 -0.028051 -0.011299 -0.038134 c 0.006670 -0.007964 , 0.013339 -0.015183 , 0.018989 -0.022912 c 0.002040 -0.002825 , 0.003335 -0.007454 , 0.002825 -0.010828 c -0.001020 -0.006709 -0.003845 -0.013378 -0.005375 -0.020087 c -0.000510 -0.002825 , 0.000275 -0.006199 , 0.001020 -0.009024 c 0.002040 -0.005649 , 0.004629 -0.011338 , 0.007964 -0.019577 c 0.010514 -0.004119 , 0.024873 -0.009769 , 0.015379 -0.031151 c 0.001295 , 0.000000 , 0.002550 , 0.000000 , 0.004119 -0.000275 c 0.007180 , 0.004629 , 0.014359 , 0.009534 , 0.021813 , 0.013888 c 0.002825 , 0.001530 , 0.006434 , 0.002589 , 0.009769 , 0.002589 c 0.010279 , 0.000275 , 0.020793 , 0.000000 , 0.032092 , 0.000000 c 0.003609 -0.008513 , 0.013104 -0.007729 , 0.022049 -0.010554 c 0.009769 -0.003099 , 0.017184 -0.002315 , 0.028483 , 0.004629 c 0.002315 -0.012358 , 0.004865 -0.022676 , 0.005649 -0.032955 c 0.001295 -0.014948 , 0.007690 -0.020087 , 0.022833 -0.017262 c 0.007964 , 0.001530 , 0.015928 , 0.003609 , 0.023853 , 0.003099 c 0.010279 -0.000510 , 0.014359 -0.012123 , 0.009494 -0.025227 c -0.000785 -0.003335 -0.003335 -0.006709 -0.004865 -0.009259 c 0.011299 , 0.001295 , 0.023108 , 0.003335 , 0.035152 , 0.004119 c 0.003335 , 0.000275 , 0.008474 -0.002825 , 0.010279 -0.005924 c 0.007180 -0.013143 , 0.015379 -0.013888 , 0.023853 -0.001295 c 0.001530 , 0.002079 , 0.003060 , 0.004119 , 0.004355 , 0.006434 c 0.007690 , 0.015183 , 0.007180 , 0.014948 , 0.017969 , 0.001530 c 0.002825 -0.003335 , 0.007690 -0.006709 , 0.011809 -0.006709 c 0.002315 , 0.000000 , 0.004865 , 0.006199 , 0.007454 , 0.009534 c 0.005885 , 0.007964 , 0.007454 , 0.020872 , 0.023853 , 0.019302 c -0.008710 , 0.013888 -0.002040 , 0.031661 -0.016948 , 0.043274 c -0.003060 , 0.002315 -0.002550 , 0.011574 -0.001530 , 0.017262 c 0.001295 , 0.006944 , 0.004355 , 0.013653 , 0.007964 , 0.019577 c 0.001530 , 0.002315 , 0.008474 , 0.004629 , 0.009769 , 0.003335 c 0.008984 -0.007964 , 0.014634 , 0.000000 , 0.024638 , 0.005414 c 0.002315 -0.003335 , 0.005139 -0.007729 , 0.007964 -0.011848 c 0.006905 -0.010044 , 0.015889 -0.009024 , 0.025894 -0.005414 c 0.004865 , 0.001805 , 0.010279 , 0.001295 , 0.015654 , 0.002079 c 0.003335 , 0.000510 , 0.009220 , 0.001295 , 0.009220 , 0.002079 c 0.000000 , 0.004119 , 0.000275 , 0.010554 -0.002315 , 0.012358 c -0.006944 , 0.004904 -0.008984 , 0.008749 -0.003845 , 0.016242 c 0.002315 , 0.003335 , 0.001805 , 0.008239 , 0.003060 , 0.012358 c 0.002825 , 0.009534 , 0.005885 , 0.018792 , 0.009769 , 0.030405 c -0.007180 , 0.010554 -0.016948 , 0.023932 -0.008710 , 0.041469 c 0.000785 , 0.001805 -0.001295 , 0.005414 -0.003060 , 0.007454 c -0.004119 , 0.004629 -0.008984 , 0.008749 -0.012829 , 0.013378 c -0.010279 , 0.012633 -0.009494 , 0.016242 , 0.004629 , 0.024207 c 0.000000 , 0.009024 -0.001020 , 0.018008 , 0.000275 , 0.026796 c 0.001805 , 0.012633 -0.005885 , 0.019577 -0.012594 , 0.027816 c -0.003845 , 0.004629 -0.005885 , 0.011064 -0.007180 , 0.016988 c -0.001805 , 0.008513 -0.001805 , 0.017498 -0.002825 , 0.026796 c 0.007180 , 0.004394 , 0.015144 , 0.009259 , 0.022833 , 0.013888 c 0.011534 -0.014438 , 0.018714 -0.032720 , 0.039782 -0.036329 c 0.003609 -0.000785 , 0.006434 -0.007219 , 0.009494 -0.011338 c 0.001295 -0.001805 , 0.002040 -0.004629 , 0.003609 -0.005139 c 0.010789 -0.003609 , 0.017694 -0.010318 , 0.021029 -0.021107 c 0.000510 -0.001295 , 0.008710 -0.000275 , 0.016438 -0.000275 c 0.003099 -0.003335 , 0.009769 -0.008239 , 0.013614 -0.014948 c 0.005924 -0.010554 , 0.013104 -0.007454 , 0.017969 -0.001530 c 0.011809 , 0.014673 , 0.026953 , 0.022402 , 0.044647 , 0.025737 c 0.010004 , 0.002079 , 0.009769 , 0.007729 , 0.005375 , 0.014673 c 0.003845 , 0.002825 , 0.006944 , 0.004904 , 0.008200 , 0.005649 c 0.005885 -0.005139 , 0.011299 -0.009259 , 0.016438 -0.013888 c 0.007180 -0.006434 , 0.014359 -0.011574 , 0.025148 -0.007729 c 0.002040 , 0.000785 , 0.008710 -0.005139 , 0.009494 -0.008749 c 0.002550 -0.014948 , 0.010004 -0.025227 , 0.023618 -0.031425 c -0.003845 -0.013888 , 0.002040 -0.022166 , 0.015889 -0.018792 c 0.017184 , 0.004119 , 0.033622 , 0.011574 , 0.050296 , 0.017498 c 0.002315 , 0.000785 , 0.005375 , 0.003335 , 0.006670 , 0.002589 c 0.013849 -0.008513 , 0.016399 , 0.002315 , 0.022598 , 0.011064 c 0.011299 , 0.015968 , 0.020283 , 0.033230 , 0.033112 , 0.048688 c 0.012594 , 0.014948 , 0.026168 , 0.025501 , 0.041822 , 0.035780 c 0.012044 , 0.007729 , 0.016399 , 0.038644 , 0.011299 , 0.053553 c -0.003335 , 0.009259 -0.004355 , 0.019302 -0.005139 , 0.029346 c -0.000785 , 0.010828 -0.002825 , 0.022912 , 0.000510 , 0.032720 c 0.004629 , 0.013143 , 0.013614 , 0.024717 , 0.021029 , 0.037075 c 0.004355 , 0.007219 , 0.007964 , 0.014948 , 0.013849 , 0.020597 c 0.005885 , 0.005924 , 0.013104 , 0.011064 , 0.020793 , 0.014163 c 0.007180 , 0.003099 , 0.015654 , 0.003099 , 0.025148 , 0.004904 c -0.010279 , 0.010828 -0.006944 , 0.019812 , 0.000510 , 0.027816 c 0.002040 , 0.002315 , 0.005649 , 0.003845 , 0.008710 , 0.003845 c 0.012554 , 0.000510 , 0.020519 , 0.011574 , 0.016438 , 0.023422 c -0.003845 , 0.010828 -0.002825 , 0.024481 -0.022049 , 0.025501 c 0.001295 , 0.001530 , 0.002825 , 0.002825 , 0.004119 , 0.004394 c 0.004119 , 0.001530 , 0.007964 , 0.003099 , 0.013104 , 0.004904 c -0.005375 , 0.007219 -0.010789 , 0.014398 -0.015654 , 0.021107 c 0.001530 , 0.002079 , 0.001805 , 0.003099 , 0.002550 , 0.003609 c 0.011299 , 0.005649 , 0.018479 , 0.013653 , 0.009769 , 0.025737 c -0.007180 , 0.010044 -0.004629 , 0.021107 -0.003335 , 0.030915 c 0.002315 , 0.015732 -0.007180 , 0.023186 -0.016674 , 0.030405 c -0.005139 , 0.004119 -0.012829 , 0.004904 -0.018989 , 0.007729 c -0.003335 , 0.001530 -0.005885 , 0.004629 -0.008474 , 0.007454 c -0.002825 , 0.002825 -0.005375 , 0.005924 -0.008200 , 0.008749 c -0.003099 -0.003609 -0.008984 -0.007219 -0.008984 -0.010828 c 0.000000 -0.010044 -0.005649 -0.011574 -0.013339 -0.013378 c -0.013849 -0.003099 -0.027188 -0.004119 -0.040292 , 0.003609 c -0.003845 , 0.002315 -0.009769 , 0.001530 -0.014634 , 0.001020 c -0.016164 -0.001530 -0.032092 -0.002825 -0.048256 , 0.003099 c -0.014124 , 0.005139 -0.036682 -0.002589 -0.042607 -0.011848 c -0.020009 , 0.004394 -0.040292 , 0.008239 -0.059790 , 0.013378 c -0.017969 , 0.004904 -0.033858 , 0.013143 -0.037193 , 0.034760 c -0.000510 , 0.003335 -0.003609 , 0.006434 -0.005649 , 0.009534 c -0.003609 , 0.005414 -0.006670 , 0.011574 -0.011024 , 0.016242 c -0.005375 , 0.005924 -0.011809 , 0.011574 -0.018204 , 0.016478 c -0.005139 , 0.003845 -0.011299 , 0.006709 , 0.000510 , 0.015693 c -0.013339 , 0.001295 -0.022598 , 0.002040 -0.033348 , 0.003335 c 0.002825 , 0.016478 , 0.005649 , 0.032720 , 0.008474 , 0.048688 c 0.000510 , 0.002825 , 0.001530 , 0.005924 , 0.003335 , 0.008239 c 0.010514 , 0.013888 , 0.011299 , 0.029621 , 0.009220 , 0.046098 c -0.000275 , 0.003099 , 0.002550 , 0.007454 , 0.005139 , 0.010044 c 0.009494 , 0.009259 , 0.019224 , 0.017772 , 0.029778 , 0.027306 c -0.016948 , 0.015458 -0.011024 , 0.031425 -0.005885 , 0.048688 c -0.007180 -0.007729 -0.014359 -0.015458 -0.021539 -0.023186 c -0.001020 , 0.000510 -0.002040 , 0.001020 -0.003060 , 0.001530 c 0.000785 , 0.006434 , 0.001805 , 0.012633 , 0.002040 , 0.016242 c -0.007964 -0.003845 -0.016948 -0.008239 -0.025933 -0.012633 c -0.002825 -0.001295 -0.007180 -0.002825 -0.007454 -0.004904 c -0.000275 -0.002315 , 0.002550 -0.005414 , 0.004355 -0.008003 c 0.001805 -0.002589 , 0.003845 -0.005139 , 0.004355 -0.009259 c -0.001805 , 0.001020 -0.003609 , 0.002079 -0.005649 , 0.003099 c -0.001805 -0.003099 -0.003609 -0.006199 -0.005375 -0.009259 c -0.000785 , 0.000275 -0.001530 , 0.000510 -0.002315 , 0.000785 c 0.000000 , 0.003609 , 0.000000 , 0.007219 , 0.000000 , 0.008003 c -0.011299 -0.006944 -0.024128 -0.014438 -0.036447 -0.022676 c -0.003335 -0.002315 -0.006160 -0.005649 -0.008474 -0.009259 c -0.009220 -0.013888 -0.011299 -0.012358 -0.026443 -0.008239 c -0.012044 , 0.003335 -0.023853 , 0.008513 -0.039272 , 0.003609 c -0.013849 -0.004629 -0.033112 -0.012084 -0.046961 , 0.004904 c -0.002550 -0.002315 -0.004865 -0.005414 -0.007690 -0.006434 c -0.009769 -0.003335 -0.005649 -0.007729 -0.002040 -0.013378 c 0.002315 -0.003609 , 0.003845 -0.008003 , 0.004629 -0.012358 c 0.004119 -0.020322 -0.004865 -0.042489 , 0.008710 -0.061791 c 0.002040 -0.002825 , 0.001020 -0.008239 , 0.001295 -0.012358 c -0.024363 -0.006199 -0.047707 -0.009259 -0.071835 -0.004629 c -0.004355 , 0.000785 -0.009769 -0.004119 -0.014124 -0.006199 c -0.001020 , 0.002315 -0.002040 , 0.006709 -0.004629 , 0.008513 c -0.012319 , 0.007454 -0.025383 , 0.014163 -0.039272 , 0.021617 c 0.005885 , 0.006160 , 0.010004 , 0.010279 , 0.013614 , 0.014438 c 0.006434 , 0.007454 , 0.010789 , 0.015458 , 0.004629 , 0.025737 c -0.012044 , 0.020872 -0.013849 , 0.042999 -0.010279 , 0.066970 c 0.003060 , 0.020322 , 0.006944 , 0.042764 -0.014634 , 0.057947 c -0.001530 , 0.001020 -0.003609 , 0.003609 -0.003609 , 0.005139 c 0.001020 , 0.027306 -0.021813 , 0.043784 -0.029268 , 0.067205 c -0.002315 , 0.006709 -0.002825 , 0.014163 -0.004355 , 0.022912 c -0.007180 , 0.002589 -0.010279 , 0.019067 -0.004629 , 0.036055 c -0.011024 , 0.016752 -0.021813 , 0.032720 -0.032092 , 0.048923 c -0.001020 , 0.001530 , 0.001020 , 0.005414 , 0.002040 , 0.008239 c 0.001020 , 0.003335 , 0.002315 , 0.006709 , 0.002825 , 0.008513 c -0.006160 , 0.001020 -0.010514 , 0.001530 -0.015144 , 0.002315 c 0.001805 , 0.005414 , 0.003609 , 0.011064 , 0.004355 , 0.013378 c -0.004629 , 0.037585 -0.011809 , 0.072620 , 0.011534 , 0.102515 c -0.002550 , 0.007454 -0.005649 , 0.012868 -0.005649 , 0.018047 c 0.000000 , 0.001805 , 0.007964 , 0.003609 , 0.013339 , 0.005649 c -0.000275 , 0.001020 -0.000785 , 0.003335 -0.001805 , 0.007454 c 0.007690 -0.003884 , 0.013614 -0.006709 , 0.019773 -0.009769 c 0.011534 -0.005924 , 0.023343 -0.012868 , 0.036447 -0.006709 c 0.004119 , 0.001805 , 0.007454 , 0.008239 , 0.008200 , 0.012868 c 0.003060 , 0.017498 , 0.005649 , 0.035270 , 0.006944 , 0.053042 c 0.001295 , 0.016242 , 0.009494 , 0.028601 , 0.018989 , 0.040684 c 0.003845 , 0.004904 , 0.007690 , 0.009534 , 0.013339 , 0.013888 c -0.002315 -0.007219 -0.004629 -0.014163 -0.006944 -0.022402 c 0.011299 , 0.010044 , 0.014124 , 0.018282 , 0.013614 , 0.031935 c -0.000275 , 0.003099 , 0.004629 , 0.006434 , 0.005649 , 0.010044 c 0.007964 , 0.031935 , 0.015379 , 0.064106 , 0.023108 , 0.096041 c 0.000000 , 0.000510 , 0.000000 , 0.001020 , 0.000275 , 0.001295 c 0.014359 , 0.016988 , 0.022049 , 0.039154 , 0.042842 , 0.051002 c 0.011024 , 0.006434 , 0.021029 , 0.012633 , 0.034132 , 0.010318 c 0.007964 -0.001295 , 0.016164 -0.002315 , 0.024128 -0.003845 c 0.013064 -0.002589 , 0.023853 , 0.000275 , 0.031308 , 0.012358 c 0.008474 , 0.013378 , 0.017459 , 0.026521 , 0.025894 , 0.039664 l 0.023853 , 0.020087 c 0.010004 , 0.005139 , 0.011299 , 0.018557 , 0.002550 , 0.028326 c -0.005375 , 0.006199 -0.012319 , 0.010554 -0.010789 , 0.021617 c 0.000510 , 0.003609 -0.011024 , 0.009024 -0.016948 , 0.013653 c 0.000785 , 0.000785 , 0.001805 , 0.001295 , 0.002550 , 0.002040 c -0.004865 -0.001295 -0.009769 -0.002315 -0.016948 -0.004119 c -0.000510 -0.001295 -0.001295 -0.006434 -0.004119 -0.008749 c -0.003609 -0.002825 -0.008710 -0.004394 -0.013339 -0.004629 c -0.003845 -0.000275 -0.008710 , 0.001295 -0.011809 , 0.003845 c -0.007690 , 0.005924 -0.022833 , 0.003609 -0.022598 , 0.020087 c 0.000000 , 0.003335 -0.007690 , 0.006709 -0.011809 , 0.010044 c -0.000785 , 0.000000 -0.001805 , 0.000000 -0.002550 , 0.000000 c -0.002315 -0.004629 -0.003609 -0.011064 -0.007454 -0.013888 c -0.010004 -0.007729 -0.010004 -0.015693 , 0.000510 -0.022166 c 0.002825 -0.001805 , 0.005139 -0.006709 , 0.005139 -0.010318 c 0.000510 -0.006944 -0.003335 -0.014948 -0.000785 -0.020597 c 0.003609 -0.008749 , 0.000275 -0.009769 -0.006434 -0.010044 c -0.007964 -0.000275 -0.016164 , 0.000000 -0.024128 , 0.000000 c -0.001020 -0.004394 -0.002040 -0.009259 -0.003060 -0.014163 c -0.001805 -0.009769 -0.006944 -0.010318 -0.016674 -0.011064 c -0.014359 -0.001295 -0.027973 -0.009024 -0.041822 -0.013888 c -0.001020 -0.000275 -0.002040 -0.002079 -0.002040 -0.003099 c 0.001020 -0.013888 -0.009220 -0.012084 -0.017184 -0.013653 c -0.001805 , 0.011338 -0.003335 , 0.021892 -0.005139 , 0.032210 c -0.001530 -0.000275 -0.002825 -0.000510 -0.004355 -0.000785 c 0.000000 -0.004119 , 0.000000 -0.007964 , 0.000000 -0.012868 c -0.003335 , 0.001805 -0.005649 , 0.003099 -0.007180 , 0.004119 c -0.006160 -0.007454 -0.011024 -0.015183 -0.017694 -0.021382 c -0.007454 -0.006944 -0.016674 -0.012358 -0.024638 -0.019067 c -0.001295 -0.001020 , 0.000275 -0.005414 -0.000275 -0.007964 c -0.002315 -0.009259 -0.002550 -0.023422 -0.008474 -0.026796 c -0.010004 -0.005414 -0.011809 -0.010318 -0.007964 -0.020362 c -0.001020 -0.000785 -0.002040 -0.001530 -0.003060 -0.002315 c -0.005649 , 0.003609 -0.011024 , 0.007454 -0.015654 , 0.010554 c -0.006670 -0.022402 -0.010789 -0.047903 -0.036447 -0.066185 c 0.000785 , 0.007964 , 0.002040 , 0.013653 , 0.002040 , 0.019302 c -0.000275 , 0.005924 -0.001805 , 0.011574 -0.002825 , 0.017498 c -0.001530 , 0.000000 -0.002825 , 0.000275 -0.004355 , 0.000275 c -0.000785 -0.008003 -0.002825 -0.016242 -0.001805 -0.023971 c 0.001020 -0.010044 -0.003060 -0.019302 -0.010004 -0.018047 c 0.005649 -0.019302 , 0.004355 -0.021892 -0.014869 -0.024717 c -0.003060 -0.000510 -0.006160 -0.001530 -0.007180 -0.001805 c -0.003060 -0.011848 -0.005885 -0.022676 -0.008710 -0.033975 c -0.003335 , 0.002315 -0.005885 , 0.004119 -0.010789 , 0.007454 c 0.003060 -0.008513 , 0.005375 -0.014438 , 0.007690 -0.021107 c -0.008984 , 0.004629 -0.018204 , 0.006944 -0.023108 , 0.012633 c -0.005139 , 0.005924 -0.005885 , 0.015458 -0.008710 , 0.024481 c -0.004119 -0.003609 -0.006670 -0.005649 -0.009220 -0.007729 c -0.000785 , 0.001020 -0.001530 , 0.001805 -0.002550 , 0.002825 c 0.004629 , 0.004394 , 0.009494 , 0.008749 , 0.014359 , 0.013378 c -0.001530 , 0.003335 -0.003609 , 0.006944 -0.005375 , 0.011064 c 0.002550 , 0.003099 , 0.004865 , 0.005924 , 0.006670 , 0.007729 c -0.005139 , 0.006160 -0.009769 , 0.011574 -0.014634 , 0.017262 c -0.001020 -0.000510 -0.002315 -0.000785 -0.003335 -0.001295 c -0.000510 -0.011574 -0.000785 -0.022912 -0.001530 -0.034525 c -0.000785 -0.011338 , 0.000510 -0.023186 -0.003060 -0.033465 c -0.008984 -0.025227 -0.001530 -0.048688 , 0.004355 -0.072384 c 0.001020 -0.004394 -0.001805 -0.009534 -0.001805 -0.014438 c 0.000275 -0.008749 , 0.001295 -0.017262 , 0.001805 -0.026011 c 0.012319 , 0.001530 , 0.011299 -0.009259 , 0.013849 -0.015968 c 0.002315 -0.005924 , 0.003335 -0.012358 , 0.005375 -0.019577 c 0.002550 , 0.003099 , 0.004119 , 0.005139 , 0.005649 , 0.007219 c 0.001020 -0.000510 , 0.001805 -0.000785 , 0.002825 -0.001295 c -0.001805 -0.005414 -0.003335 -0.011064 -0.005139 -0.016478 c 0.003060 -0.006709 , 0.004355 -0.014438 , 0.005375 -0.021892 c 0.000275 -0.002315 , 0.000275 -0.004904 , 0.001020 -0.007219 c 0.006944 -0.014948 , 0.014634 -0.029621 , 0.021303 -0.044568 c 0.003845 -0.008513 , 0.006434 -0.017498 , 0.008710 -0.026286 c 0.001530 -0.005924 , 0.003609 -0.013143 , 0.001295 -0.018047 c -0.004355 -0.009769 -0.000510 -0.015183 , 0.005885 -0.020872 c 0.007454 -0.006709 , 0.021813 -0.007219 , 0.020519 -0.022402 c 0.000000 -0.000510 , 0.001020 -0.001295 , 0.001805 -0.001530 c 0.014634 -0.007454 , 0.024873 -0.018047 , 0.030013 -0.034015 c 0.002040 -0.006199 , 0.007180 -0.011338 , 0.010514 -0.017262 c 0.005139 -0.009769 , 0.009769 -0.019812 , 0.015144 -0.030405 c 0.009220 -0.000785 , 0.022598 -0.017498 , 0.018714 -0.025737 c -0.004119 -0.008749 -0.008984 -0.017498 -0.012829 -0.026521 c -0.001020 -0.002589 , 0.001295 -0.006434 , 0.001805 -0.009769 c 0.000275 -0.001020 -0.000275 -0.002315 -0.000510 -0.003845 c -0.002550 , 0.000275 -0.005139 , 0.000275 -0.005885 , 0.000275 c -0.002040 -0.007219 -0.004629 -0.013653 -0.005885 -0.020322 c -0.001530 -0.009024 -0.002825 -0.018282 -0.002315 -0.027306 c 0.000510 -0.006199 , 0.000785 -0.009769 -0.006160 -0.012633 c -0.015379 -0.006434 -0.021539 -0.019812 -0.024363 -0.035780 c -0.000785 -0.004629 -0.003609 -0.009024 -0.004629 -0.013928 c -0.001530 -0.006434 -0.002315 -0.013143 -0.003335 -0.019577 c 0.004865 -0.001020 , 0.008474 -0.001805 , 0.012554 -0.002825 c -0.000785 -0.005139 -0.002550 -0.009259 -0.002040 -0.013378 c 0.003609 -0.036055 -0.009494 -0.066970 -0.028483 -0.096041 c -0.000510 -0.001020 -0.001295 -0.002079 -0.002315 -0.002589 c -0.022598 -0.012084 -0.043627 -0.025737 -0.053631 -0.051238 c -0.000510 -0.001020 -0.001805 -0.001530 -0.002550 -0.002589 c -0.010514 -0.016988 -0.029503 -0.029111 -0.030288 -0.052022 c -0.000275 -0.004119 -0.000510 -0.008513 -0.001805 -0.012358 c -0.005375 -0.020322 , 0.002550 -0.030131 , 0.021813 -0.028836 c 0.001295 -0.003609 , 0.002040 -0.008749 , 0.003845 -0.009024 c 0.005375 -0.001020 , 0.011299 -0.000510 , 0.018714 -0.000510 c 0.000000 -0.027306 , 0.000000 -0.056416 , 0.000000 -0.084742 c 0.004865 -0.003884 , 0.009494 -0.007729 , 0.012829 -0.010554 c 0.006434 -0.000510 , 0.015379 , 0.001295 , 0.016948 -0.001530 c 0.005139 -0.008749 , 0.007964 -0.019067 , 0.010514 -0.028836 c 0.000510 -0.002079 -0.002550 -0.006709 -0.004865 -0.007729 c -0.002040 -0.000785 -0.006160 , 0.001020 -0.008474 , 0.002825 c -0.004629 , 0.003609 -0.008984 , 0.008239 -0.011534 , 0.010828 c -0.009494 -0.017772 -0.018989 -0.034760 -0.027698 -0.052297 c -0.001020 -0.001805 , 0.000275 -0.005924 , 0.001805 -0.007729 c 0.006670 -0.006944 , 0.005375 -0.014673 , 0.000510 -0.020597 c -0.011024 -0.013653 -0.026678 -0.022912 -0.035662 -0.038369 c -0.003845 -0.006434 -0.007690 -0.012868 -0.012554 -0.018282 c -0.011809 -0.012868 -0.025383 -0.024207 -0.036447 -0.037585 c -0.006160 -0.007729 -0.013614 -0.019812 -0.011534 -0.027306 c 0.002550 -0.009024 , 0.003845 -0.014673 -0.001295 -0.022676 c -0.003609 -0.005649 -0.005885 -0.012123 -0.007690 -0.018557 c -0.004355 -0.014948 -0.004119 -0.014948 -0.016164 -0.007729 c -0.005885 -0.011064 -0.011809 -0.021892 -0.017459 -0.032955 C 0.001020 , 0.244655 , 0.001020 , 0.242850 , 0.001020 , 0.241045 z`,\n  [MaskTypes.BURST_OUTLINE]:\n    'M 0.499917 , 0.998842 l -0.054940 -0.066192 l -0.069667 , 0.050306 l -0.036737 -0.077776 l -0.079927 , 0.031441 l -0.016383 -0.084395 l -0.085388 , 0.010591 l 0.005130 -0.085884 h 0.000000 L 0.076949 , 0.766176 l 0.026311 -0.081913 h 0.000000 l -0.079762 -0.031772 l 0.045838 -0.072646 L 0.000000 , 0.528876 l 0.062552 -0.059077 h 0.000000 l -0.054609 -0.066358 l 0.075128 -0.041536 l -0.036406 -0.077941 l 0.083237 -0.021678 l -0.015886 -0.084561 l 0.086050 -0.000165 l 0.005626 -0.085884 l 0.083237 , 0.021182 l 0.000000 , 0.000000 l 0.026808 -0.081747 l 0.075459 , 0.041205 L 0.437200 , 0.000000 l 0.062717 , 0.058746 L 0.562800 , 0.000000 l 0.046169 , 0.072481 l 0.000000 , 0.000000 l 0.075294 -0.041205 l 0.026808 , 0.081747 l 0.083237 -0.021182 l 0.005626 , 0.085884 l 0.085884 , 0.000165 l -0.015886 , 0.084561 l 0.083071 , 0.021678 l -0.036406 , 0.077941 l 0.075128 , 0.041536 l -0.054609 , 0.066358 l 0.062386 , 0.059077 l -0.069336 , 0.050637 L 0.976336 , 0.652325 l -0.079762 , 0.031938 l 0.026311 , 0.081913 l -0.085223 , 0.010922 l 0.005130 , 0.085884 l -0.085223 -0.010591 l -0.016383 , 0.084395 l -0.079927 -0.031441 l -0.036737 , 0.077776 l -0.069667 -0.050306 L 0.499917 , 0.998842 z  M 0.446963 , 0.917591 l 0.052954 , 0.063876 l 0.052954 -0.063876 l 0.067185 , 0.048651 l 0.035413 -0.075128 l 0.077279 , 0.030448 l 0.015721 -0.081582 l 0.082244 , 0.010260 l -0.004964 -0.082906 l 0.082244 -0.010591 l -0.025484 -0.079100 l 0.076949 -0.030779 l -0.044183 -0.070164 l 0.067020 -0.048982 l -0.060235 -0.057091 l 0.052623 -0.064041 l -0.072646 -0.040212 l 0.035082 -0.075128 l -0.080258 -0.020851 l 0.015390 -0.081582 l -0.082906 -0.000165 L 0.784213 , 0.105908 l -0.080424 , 0.020354 l -0.025815 -0.078934 l -0.072812 , 0.039881 l -0.044514 -0.069998 l -0.060566 , 0.056594 l -0.060566 -0.056594 l -0.044680 , 0.069998 l -0.072812 -0.039881 L 0.296210 , 0.126262 L 0.215787 , 0.105908 l -0.005461 , 0.082906 L 0.127420 , 0.188979 l 0.015390 , 0.081582 l -0.080258 , 0.020851 l 0.035082 , 0.075128 l -0.072646 , 0.040212 l 0.052788 , 0.064041 L 0.017375 , 0.527884 l 0.067020 , 0.048982 L 0.040046 , 0.647030 l 0.077114 , 0.030779 l -0.025484 , 0.079100 l 0.082244 , 0.010591 l -0.004964 , 0.082906 l 0.082409 -0.010260 l 0.015721 , 0.081582 l 0.077114 -0.030448 l 0.035413 , 0.075128 L 0.446963 , 0.917591 z',\n  [MaskTypes.TWITTER]: `M1,0.2C0.96,0.21,0.92,0.22,0.88,0.23C0.92,0.2,0.96,0.17,0.97,0.12C0.93,0.14,0.89,0.16,0.84,0.17\n\tC0.8,0.13,0.75,0.1,0.69,0.1c-0.11,0-0.21,0.09-0.21,0.2c0,0.02,0,0.03,0.01,0.05C0.32,0.34,0.17,0.26,0.07,0.14\n\tC0.05,0.17,0.04,0.2,0.04,0.24c0,0.07,0.04,0.13,0.09,0.17c-0.03,0-0.07-0.01-0.09-0.02c0,0,0,0,0,0c0,0.1,0.07,0.18,0.16,0.2\n\tc-0.02,0-0.04,0.01-0.05,0.01c-0.01,0-0.03,0-0.04,0c0.03,0.08,0.1,0.14,0.19,0.14C0.23,0.78,0.15,0.81,0.05,0.81\n\tc-0.02,0-0.03,0-0.05,0C0.09,0.86,0.2,0.9,0.31,0.9c0.38,0,0.58-0.3,0.58-0.57c0-0.01,0-0.02,0-0.03C0.94,0.27,0.97,0.24,1,0.2z`,\n  [MaskTypes.INSTAGRAM]: `M0.7,0H0.3C0.14,0,0.01,0.13,0.01,0.28v0.43C0.01,0.87,0.14,1,0.3,1H0.7c0.16,0,0.28-0.13,0.28-0.28V0.28\n\tC0.99,0.13,0.86,0,0.7,0z M0.91,0.72c0,0.06-0.02,0.11-0.06,0.15C0.81,0.9,0.76,0.93,0.7,0.93v0H0.3c-0.06,0-0.11-0.02-0.15-0.06\n\tC0.11,0.82,0.09,0.77,0.09,0.72V0.28c0-0.06,0.02-0.11,0.06-0.15C0.19,0.1,0.24,0.07,0.3,0.07H0.7c0.06,0,0.11,0.02,0.15,0.06\n\tc0.04,0.04,0.06,0.09,0.06,0.15V0.72z M0.5,0.23c-0.15,0-0.27,0.12-0.27,0.27S0.35,0.76,0.5,0.76c0.15,0,0.27-0.12,0.27-0.27\n\tS0.65,0.23,0.5,0.23z M0.5,0.67c-0.1,0-0.18-0.08-0.18-0.18S0.4,0.32,0.5,0.32c0.1,0,0.18,0.08,0.18,0.18S0.6,0.67,0.5,0.67z\n\t M0.84,0.22c0,0.04-0.03,0.06-0.06,0.06c-0.04,0-0.06-0.03-0.06-0.06s0.03-0.06,0.06-0.06C0.81,0.16,0.84,0.19,0.84,0.22z`,\n  [MaskTypes.FACEBOOK]: `M0.57,1V0.54h0.15l0.02-0.18H0.57V0.25c0-0.05,0.01-0.09,0.08-0.09h0.09V0.01C0.73,0,0.68,0,0.62,0\n\tC0.49,0,0.4,0.08,0.4,0.23v0.13H0.25v0.18H0.4V1H0.57z`,\n  [MaskTypes.YOUTUBE]: `M0.74,0.16H0.26C0,0.16,0,0.23,0,0.41v0.18c0,0.17,0.04,0.25,0.26,0.25h0.48C0.94,0.84,1,0.79,1,0.59V0.41\n\tC1,0.22,0.99,0.16,0.74,0.16z M0.4,0.63V0.36L0.67,0.5L0.4,0.63z`,\n  [MaskTypes.BRUSH_STROKE_1]:\n    'M 0.463 0.010 C 0.464 0.007 0.464 0.007 0.464 0.010 C 0.464 0.011 0.464 0.013 0.464 0.013 C 0.463 0.013 0.463 0.012 0.463 0.010 Z  M 0.385 0.011 C 0.385 0.010 0.386 0.009 0.386 0.009 C 0.386 0.009 0.386 0.009 0.386 0.010 C 0.386 0.010 0.386 0.011 0.386 0.012 C 0.386 0.012 0.385 0.012 0.385 0.011 Z  M 0.550 0.073 C 0.550 0.072 0.551 0.072 0.551 0.073 C 0.551 0.073 0.551 0.074 0.551 0.074 C 0.550 0.074 0.550 0.073 0.550 0.073 Z  M 0.606 0.083 C 0.606 0.083 0.607 0.083 0.607 0.083 C 0.607 0.084 0.607 0.084 0.607 0.084 C 0.606 0.084 0.606 0.084 0.606 0.083 Z  M 0.604 0.085 C 0.604 0.084 0.604 0.083 0.604 0.083 C 0.605 0.083 0.605 0.083 0.605 0.084 C 0.605 0.084 0.605 0.085 0.604 0.085 C 0.604 0.086 0.604 0.086 0.604 0.085 Z  M 0.753 0.087 C 0.753 0.086 0.754 0.086 0.754 0.087 C 0.754 0.087 0.754 0.088 0.754 0.088 C 0.753 0.088 0.753 0.088 0.753 0.087 Z  M 0.738 0.086 C 0.738 0.085 0.738 0.085 0.738 0.085 C 0.739 0.085 0.739 0.085 0.739 0.085 C 0.739 0.086 0.739 0.087 0.738 0.087 C 0.738 0.088 0.738 0.087 0.738 0.086 Z  M 0.742 0.089 C 0.742 0.088 0.742 0.088 0.743 0.089 C 0.743 0.089 0.743 0.090 0.742 0.090 C 0.742 0.090 0.742 0.089 0.742 0.089 Z  M 0.870 0.090 C 0.870 0.085 0.871 0.083 0.872 0.086 C 0.873 0.089 0.873 0.089 0.872 0.091 C 0.871 0.095 0.870 0.094 0.870 0.090 Z  M 0.780 0.093 C 0.780 0.092 0.780 0.092 0.781 0.091 C 0.781 0.090 0.781 0.091 0.781 0.092 C 0.781 0.093 0.780 0.094 0.780 0.093 Z  M 0.759 0.092 C 0.759 0.091 0.759 0.091 0.760 0.091 C 0.760 0.092 0.761 0.092 0.761 0.093 C 0.761 0.093 0.760 0.094 0.760 0.094 C 0.759 0.094 0.759 0.093 0.759 0.092 Z  M 0.770 0.094 C 0.771 0.091 0.772 0.091 0.772 0.094 C 0.772 0.095 0.771 0.095 0.770 0.095 C 0.769 0.095 0.769 0.095 0.770 0.094 Z  M 0.886 0.095 C 0.885 0.093 0.886 0.091 0.886 0.092 C 0.887 0.093 0.887 0.093 0.887 0.095 C 0.886 0.097 0.886 0.097 0.886 0.095 Z  M 0.854 0.095 C 0.854 0.094 0.854 0.094 0.854 0.094 C 0.855 0.094 0.855 0.095 0.855 0.096 C 0.854 0.097 0.854 0.096 0.854 0.095 Z  M 0.870 0.101 C 0.870 0.101 0.870 0.101 0.871 0.101 C 0.871 0.102 0.871 0.102 0.870 0.102 C 0.870 0.102 0.870 0.102 0.870 0.101 Z  M 0.946 0.134 C 0.946 0.133 0.947 0.133 0.947 0.134 C 0.948 0.134 0.947 0.135 0.947 0.135 C 0.946 0.135 0.946 0.134 0.946 0.134 Z  M 0.051 0.173 C 0.051 0.173 0.051 0.173 0.052 0.173 C 0.052 0.174 0.052 0.174 0.051 0.174 C 0.051 0.174 0.051 0.174 0.051 0.173 Z  M 0.046 0.201 C 0.046 0.200 0.046 0.200 0.046 0.200 C 0.046 0.200 0.047 0.200 0.047 0.201 C 0.048 0.204 0.048 0.204 0.046 0.201 Z  M 0.056 0.234 C 0.056 0.233 0.056 0.232 0.057 0.232 C 0.057 0.232 0.057 0.233 0.057 0.234 C 0.057 0.235 0.056 0.236 0.056 0.236 C 0.056 0.236 0.056 0.235 0.056 0.234 Z  M 0.045 0.256 C 0.045 0.256 0.046 0.255 0.046 0.256 C 0.047 0.257 0.046 0.257 0.046 0.257 C 0.045 0.257 0.045 0.257 0.045 0.256 Z  M 0.049 0.257 C 0.049 0.256 0.049 0.255 0.050 0.255 C 0.050 0.255 0.050 0.256 0.050 0.256 C 0.050 0.257 0.050 0.257 0.050 0.258 C 0.049 0.259 0.049 0.258 0.049 0.257 Z  M 0.050 0.279 C 0.050 0.279 0.049 0.277 0.049 0.276 C 0.049 0.273 0.049 0.273 0.051 0.274 C 0.054 0.275 0.055 0.276 0.054 0.279 C 0.053 0.281 0.051 0.281 0.050 0.279 Z  M 0.056 0.281 C 0.056 0.280 0.056 0.279 0.057 0.280 C 0.059 0.282 0.059 0.282 0.057 0.282 C 0.056 0.282 0.056 0.282 0.056 0.281 Z  M 0.058 0.315 C 0.057 0.313 0.057 0.313 0.059 0.314 C 0.061 0.316 0.061 0.317 0.060 0.317 C 0.059 0.317 0.058 0.316 0.058 0.315 Z  M 0.054 0.317 C 0.053 0.315 0.053 0.315 0.054 0.315 C 0.055 0.315 0.055 0.315 0.056 0.314 C 0.056 0.314 0.056 0.315 0.056 0.316 C 0.056 0.319 0.056 0.319 0.054 0.317 Z  M 0.073 0.333 C 0.073 0.333 0.073 0.333 0.074 0.333 C 0.074 0.334 0.074 0.334 0.073 0.334 C 0.073 0.334 0.073 0.334 0.073 0.333 Z  M 0.980 0.339 C 0.980 0.338 0.981 0.338 0.981 0.339 C 0.981 0.339 0.981 0.340 0.980 0.340 C 0.980 0.340 0.980 0.339 0.980 0.339 Z  M 0.107 0.364 C 0.107 0.363 0.107 0.363 0.107 0.364 C 0.108 0.364 0.108 0.365 0.107 0.365 C 0.107 0.365 0.106 0.365 0.107 0.364 Z  M 0.085 0.383 C 0.085 0.382 0.085 0.381 0.085 0.381 C 0.086 0.379 0.087 0.381 0.087 0.383 C 0.087 0.385 0.085 0.385 0.085 0.383 Z  M 0.075 0.396 C 0.075 0.396 0.075 0.396 0.075 0.396 C 0.076 0.397 0.076 0.397 0.075 0.397 C 0.075 0.397 0.074 0.397 0.075 0.396 Z  M 0.100 0.427 C 0.101 0.426 0.101 0.426 0.102 0.427 C 0.102 0.427 0.102 0.428 0.101 0.428 C 0.100 0.428 0.100 0.427 0.100 0.427 Z  M 0.068 0.439 C 0.068 0.437 0.074 0.437 0.074 0.439 C 0.074 0.440 0.073 0.441 0.071 0.441 C 0.070 0.441 0.068 0.440 0.068 0.439 Z  M 0.017 0.452 C 0.018 0.452 0.018 0.452 0.018 0.452 C 0.019 0.453 0.019 0.453 0.018 0.453 C 0.018 0.453 0.017 0.453 0.017 0.452 Z  M 0.014 0.452 C 0.014 0.451 0.014 0.450 0.015 0.451 C 0.016 0.452 0.016 0.453 0.015 0.453 C 0.014 0.453 0.014 0.453 0.014 0.452 Z  M 0.008 0.451 C 0.007 0.450 0.007 0.450 0.009 0.450 C 0.011 0.450 0.012 0.450 0.011 0.451 C 0.010 0.453 0.010 0.453 0.008 0.451 Z  M 0.027 0.468 C 0.026 0.465 0.030 0.464 0.032 0.466 C 0.033 0.467 0.034 0.468 0.034 0.469 C 0.034 0.470 0.027 0.469 0.027 0.468 Z  M 0.049 0.475 C 0.049 0.474 0.050 0.473 0.050 0.473 C 0.051 0.473 0.051 0.474 0.050 0.475 C 0.049 0.476 0.049 0.476 0.048 0.476 C 0.048 0.476 0.048 0.476 0.049 0.475 Z  M 0.058 0.496 C 0.056 0.494 0.057 0.491 0.059 0.492 C 0.060 0.493 0.062 0.493 0.063 0.493 C 0.064 0.493 0.066 0.496 0.065 0.497 C 0.063 0.498 0.059 0.497 0.058 0.496 Z  M 0.028 0.497 C 0.027 0.495 0.027 0.495 0.027 0.496 C 0.027 0.497 0.027 0.498 0.026 0.498 C 0.024 0.497 0.023 0.495 0.025 0.495 C 0.026 0.495 0.026 0.494 0.026 0.493 C 0.026 0.491 0.028 0.489 0.030 0.489 C 0.031 0.489 0.031 0.488 0.031 0.487 C 0.031 0.487 0.033 0.486 0.036 0.486 C 0.038 0.486 0.040 0.487 0.039 0.488 C 0.039 0.489 0.040 0.489 0.040 0.488 C 0.041 0.487 0.041 0.487 0.045 0.488 C 0.047 0.489 0.049 0.489 0.050 0.489 C 0.052 0.489 0.052 0.490 0.052 0.491 C 0.052 0.492 0.053 0.492 0.053 0.492 C 0.054 0.490 0.056 0.492 0.056 0.494 C 0.056 0.495 0.053 0.496 0.049 0.496 C 0.043 0.496 0.041 0.496 0.040 0.498 C 0.040 0.500 0.038 0.500 0.034 0.500 C 0.029 0.500 0.028 0.499 0.028 0.497 Z  M 0.066 0.514 C 0.065 0.513 0.065 0.513 0.066 0.513 C 0.066 0.513 0.066 0.513 0.066 0.514 C 0.066 0.515 0.066 0.516 0.066 0.516 C 0.066 0.516 0.066 0.515 0.066 0.514 Z  M 0.063 0.514 C 0.062 0.513 0.062 0.513 0.063 0.513 C 0.064 0.513 0.064 0.513 0.065 0.514 C 0.065 0.517 0.064 0.517 0.063 0.514 Z  M 0.061 0.516 C 0.061 0.515 0.061 0.514 0.061 0.514 C 0.061 0.514 0.062 0.515 0.062 0.515 C 0.062 0.516 0.061 0.516 0.061 0.517 C 0.061 0.518 0.061 0.517 0.061 0.516 Z  M 0.048 0.516 C 0.048 0.515 0.047 0.515 0.046 0.516 C 0.045 0.516 0.045 0.516 0.045 0.515 C 0.045 0.512 0.056 0.512 0.056 0.514 C 0.056 0.515 0.055 0.516 0.054 0.516 C 0.050 0.517 0.048 0.517 0.048 0.516 Z  M 0.074 0.518 C 0.074 0.517 0.074 0.516 0.073 0.517 C 0.072 0.518 0.071 0.518 0.071 0.516 C 0.071 0.515 0.072 0.514 0.073 0.514 C 0.074 0.514 0.075 0.514 0.076 0.513 C 0.076 0.512 0.076 0.512 0.076 0.515 C 0.075 0.516 0.075 0.518 0.075 0.519 C 0.075 0.519 0.075 0.520 0.075 0.520 C 0.075 0.520 0.074 0.519 0.074 0.518 Z  M 0.044 0.521 C 0.044 0.521 0.045 0.520 0.045 0.519 C 0.046 0.519 0.046 0.519 0.046 0.520 C 0.046 0.522 0.044 0.522 0.044 0.521 Z  M 0.034 0.530 C 0.034 0.530 0.035 0.529 0.035 0.528 C 0.036 0.528 0.036 0.528 0.036 0.529 C 0.036 0.531 0.034 0.531 0.034 0.530 Z  M 0.026 0.541 C 0.026 0.540 0.026 0.540 0.027 0.541 C 0.027 0.541 0.027 0.541 0.027 0.540 C 0.027 0.539 0.028 0.539 0.028 0.538 C 0.029 0.538 0.030 0.539 0.030 0.540 C 0.030 0.541 0.030 0.541 0.030 0.540 C 0.031 0.538 0.031 0.538 0.032 0.539 C 0.033 0.541 0.033 0.541 0.032 0.542 C 0.027 0.543 0.026 0.543 0.026 0.541 Z  M 0.014 0.542 C 0.013 0.541 0.013 0.540 0.012 0.541 C 0.012 0.542 0.012 0.541 0.012 0.540 C 0.013 0.538 0.015 0.539 0.015 0.542 C 0.015 0.544 0.014 0.544 0.014 0.542 Z  M 0.015 0.543 C 0.015 0.542 0.015 0.541 0.016 0.541 C 0.016 0.541 0.016 0.541 0.016 0.540 C 0.015 0.538 0.015 0.538 0.016 0.538 C 0.017 0.537 0.018 0.537 0.019 0.538 C 0.020 0.539 0.021 0.539 0.021 0.538 C 0.022 0.537 0.023 0.536 0.023 0.536 C 0.024 0.536 0.023 0.537 0.022 0.539 L 0.021 0.541 L 0.022 0.541 C 0.023 0.540 0.024 0.541 0.023 0.542 C 0.023 0.544 0.018 0.544 0.018 0.542 C 0.018 0.540 0.018 0.540 0.018 0.540 C 0.017 0.540 0.017 0.540 0.017 0.541 C 0.018 0.542 0.017 0.543 0.017 0.544 C 0.016 0.546 0.015 0.545 0.015 0.543 Z  M 0.079 0.546 C 0.080 0.545 0.080 0.545 0.081 0.546 C 0.081 0.546 0.081 0.546 0.080 0.546 C 0.079 0.546 0.079 0.546 0.079 0.546 Z  M 0.075 0.586 C 0.075 0.586 0.074 0.585 0.073 0.586 C 0.072 0.586 0.071 0.586 0.073 0.585 C 0.074 0.582 0.077 0.584 0.077 0.587 C 0.078 0.589 0.076 0.589 0.075 0.586 Z  M 0.066 0.586 C 0.065 0.585 0.065 0.585 0.067 0.584 C 0.068 0.583 0.069 0.584 0.069 0.585 C 0.070 0.586 0.070 0.586 0.069 0.585 C 0.069 0.585 0.068 0.585 0.067 0.586 C 0.067 0.587 0.066 0.587 0.066 0.586 Z  M 0.042 0.610 C 0.042 0.610 0.043 0.610 0.043 0.610 C 0.043 0.611 0.043 0.611 0.043 0.611 C 0.042 0.611 0.042 0.611 0.042 0.610 Z  M 0.045 0.615 C 0.044 0.614 0.044 0.614 0.045 0.614 C 0.046 0.613 0.046 0.614 0.046 0.615 C 0.046 0.616 0.047 0.617 0.046 0.617 C 0.046 0.617 0.046 0.616 0.045 0.615 Z  M 0.015 0.637 C 0.015 0.637 0.016 0.637 0.016 0.637 C 0.016 0.638 0.016 0.638 0.016 0.638 C 0.015 0.638 0.015 0.638 0.015 0.637 Z  M 0.016 0.650 C 0.017 0.649 0.017 0.649 0.017 0.650 C 0.018 0.650 0.017 0.651 0.017 0.651 C 0.016 0.651 0.016 0.650 0.016 0.650 Z  M 0.009 0.674 C 0.009 0.673 0.009 0.673 0.010 0.673 C 0.012 0.673 0.013 0.674 0.013 0.674 C 0.014 0.677 0.011 0.677 0.009 0.674 Z  M 0.008 0.704 C 0.008 0.703 0.008 0.702 0.009 0.702 C 0.009 0.702 0.009 0.703 0.009 0.704 C 0.009 0.704 0.009 0.705 0.009 0.705 C 0.008 0.705 0.008 0.704 0.008 0.704 Z  M 0.033 0.710 C 0.033 0.709 0.033 0.709 0.034 0.709 C 0.035 0.709 0.035 0.710 0.035 0.711 C 0.035 0.713 0.035 0.712 0.033 0.710 Z  M 0.013 0.709 C 0.012 0.705 0.012 0.705 0.013 0.705 C 0.014 0.705 0.014 0.706 0.014 0.707 C 0.014 0.708 0.014 0.708 0.014 0.708 C 0.015 0.707 0.015 0.707 0.015 0.708 C 0.015 0.709 0.016 0.711 0.016 0.711 C 0.017 0.712 0.017 0.712 0.016 0.712 C 0.014 0.712 0.014 0.711 0.013 0.709 Z  M 0.006 0.712 C 0.007 0.711 0.007 0.711 0.006 0.710 C 0.006 0.710 0.006 0.710 0.006 0.708 C 0.007 0.706 0.007 0.706 0.007 0.708 C 0.007 0.710 0.008 0.710 0.009 0.710 C 0.010 0.710 0.010 0.710 0.010 0.710 C 0.009 0.710 0.009 0.711 0.009 0.712 C 0.009 0.713 0.008 0.713 0.007 0.714 C 0.006 0.714 0.006 0.713 0.006 0.712 Z  M 0.034 0.716 C 0.034 0.714 0.030 0.711 0.031 0.712 C 0.031 0.714 0.030 0.715 0.028 0.715 C 0.028 0.715 0.026 0.714 0.025 0.714 C 0.024 0.714 0.024 0.714 0.025 0.712 C 0.026 0.711 0.027 0.710 0.028 0.710 C 0.029 0.710 0.030 0.709 0.030 0.708 C 0.031 0.706 0.032 0.707 0.032 0.709 C 0.033 0.712 0.036 0.716 0.037 0.716 C 0.038 0.716 0.038 0.716 0.037 0.714 C 0.037 0.713 0.037 0.712 0.038 0.712 C 0.039 0.712 0.040 0.713 0.040 0.715 C 0.040 0.716 0.039 0.718 0.039 0.718 C 0.039 0.718 0.038 0.717 0.039 0.715 C 0.039 0.714 0.039 0.714 0.038 0.715 C 0.038 0.718 0.035 0.718 0.034 0.716 Z  M 0.032 0.717 C 0.032 0.716 0.033 0.716 0.033 0.716 C 0.033 0.717 0.033 0.717 0.033 0.718 C 0.032 0.718 0.032 0.717 0.032 0.717 Z  M 0.050 0.722 C 0.050 0.721 0.050 0.721 0.051 0.722 C 0.051 0.722 0.051 0.723 0.050 0.723 C 0.050 0.723 0.050 0.723 0.050 0.722 Z  M 0.020 0.723 C 0.019 0.722 0.019 0.721 0.020 0.721 C 0.020 0.721 0.021 0.722 0.021 0.723 C 0.021 0.725 0.020 0.725 0.020 0.723 Z  M 0.017 0.724 C 0.018 0.723 0.018 0.723 0.018 0.724 C 0.019 0.724 0.019 0.725 0.018 0.725 C 0.018 0.725 0.017 0.724 0.017 0.724 Z  M 0.034 0.725 C 0.034 0.725 0.035 0.725 0.035 0.725 C 0.036 0.726 0.035 0.726 0.035 0.726 C 0.034 0.726 0.034 0.726 0.034 0.725 Z  M 0.027 0.726 C 0.028 0.725 0.028 0.725 0.028 0.725 C 0.029 0.726 0.029 0.726 0.028 0.727 C 0.028 0.727 0.027 0.726 0.027 0.726 Z  M 0.004 0.727 C 0.004 0.726 0.004 0.725 0.005 0.726 C 0.005 0.727 0.006 0.728 0.005 0.728 C 0.005 0.728 0.004 0.728 0.004 0.727 Z  M 0.027 0.734 C 0.027 0.732 0.034 0.733 0.034 0.735 C 0.034 0.735 0.033 0.736 0.031 0.735 C 0.029 0.735 0.027 0.734 0.027 0.734 Z  M 0.021 0.734 C 0.021 0.734 0.022 0.734 0.022 0.734 C 0.022 0.735 0.022 0.735 0.021 0.735 C 0.021 0.735 0.020 0.735 0.021 0.734 Z  M 0.002 0.812 C 0.002 0.812 0.002 0.811 0.003 0.811 C 0.003 0.810 0.003 0.810 0.003 0.811 C 0.003 0.813 0.002 0.814 0.002 0.812 Z  M 0.004 0.842 C 0.003 0.841 0.003 0.840 0.003 0.840 C 0.004 0.840 0.005 0.841 0.005 0.842 C 0.006 0.844 0.005 0.844 0.004 0.842 Z  M 0.010 0.878 C 0.010 0.877 0.010 0.876 0.011 0.876 C 0.012 0.876 0.012 0.876 0.011 0.878 C 0.010 0.880 0.010 0.880 0.010 0.878 Z  M 0.023 0.898 C 0.023 0.898 0.024 0.898 0.024 0.898 C 0.025 0.899 0.024 0.899 0.024 0.899 C 0.023 0.899 0.023 0.899 0.023 0.898 Z  M 0.885 0.948 C 0.885 0.947 0.885 0.946 0.885 0.946 C 0.886 0.946 0.886 0.947 0.886 0.948 C 0.886 0.949 0.886 0.950 0.885 0.950 C 0.885 0.950 0.885 0.949 0.885 0.948 Z  M 0.925 0.960 C 0.925 0.959 0.925 0.959 0.926 0.959 C 0.926 0.959 0.926 0.959 0.926 0.960 C 0.926 0.961 0.925 0.962 0.925 0.962 C 0.925 0.962 0.925 0.961 0.925 0.960 Z  M 0.512 0.969 C 0.511 0.968 0.511 0.968 0.512 0.968 C 0.512 0.968 0.513 0.969 0.513 0.969 C 0.514 0.970 0.514 0.971 0.513 0.971 C 0.513 0.971 0.512 0.970 0.512 0.969 Z  M 0.362 0.028 C 0.361 0.027 0.361 0.027 0.361 0.028 C 0.361 0.028 0.361 0.029 0.361 0.029 C 0.362 0.029 0.362 0.028 0.362 0.028 Z  M 0.363 0.038 C 0.363 0.034 0.362 0.033 0.362 0.037 C 0.362 0.039 0.362 0.041 0.363 0.041 C 0.364 0.041 0.364 0.041 0.363 0.038 L 0.363 0.038 Z  M 0.365 0.047 C 0.364 0.046 0.364 0.045 0.364 0.045 C 0.364 0.045 0.363 0.046 0.363 0.047 C 0.363 0.048 0.364 0.049 0.364 0.049 C 0.365 0.049 0.365 0.048 0.365 0.047 Z  M 0.363 0.046 C 0.363 0.043 0.362 0.043 0.362 0.045 C 0.361 0.046 0.361 0.048 0.361 0.048 C 0.361 0.048 0.361 0.049 0.362 0.049 C 0.362 0.049 0.363 0.047 0.363 0.046 Z  M 0.475 0.052 C 0.475 0.051 0.475 0.050 0.475 0.050 C 0.475 0.050 0.475 0.051 0.474 0.052 C 0.474 0.053 0.474 0.054 0.475 0.054 C 0.475 0.054 0.475 0.053 0.475 0.052 Z  M 0.424 0.052 C 0.424 0.051 0.424 0.050 0.423 0.050 C 0.423 0.050 0.423 0.051 0.423 0.052 C 0.423 0.053 0.423 0.054 0.423 0.054 C 0.424 0.054 0.424 0.053 0.424 0.052 Z  M 0.411 0.052 C 0.411 0.051 0.410 0.050 0.410 0.050 C 0.410 0.050 0.410 0.051 0.410 0.052 C 0.410 0.053 0.410 0.054 0.410 0.054 C 0.410 0.054 0.411 0.053 0.411 0.052 Z  M 0.377 0.052 C 0.377 0.051 0.376 0.050 0.376 0.050 C 0.376 0.050 0.376 0.051 0.376 0.052 C 0.376 0.053 0.377 0.054 0.377 0.054 C 0.377 0.054 0.377 0.053 0.377 0.052 Z  M 0.364 0.053 C 0.364 0.052 0.364 0.050 0.363 0.050 C 0.363 0.050 0.363 0.052 0.364 0.053 C 0.365 0.057 0.365 0.056 0.364 0.053 Z  M 0.418 0.056 C 0.418 0.055 0.418 0.054 0.417 0.054 C 0.417 0.054 0.417 0.055 0.417 0.056 C 0.417 0.057 0.417 0.058 0.417 0.058 C 0.418 0.058 0.418 0.057 0.418 0.056 Z  M 0.393 0.056 C 0.394 0.054 0.394 0.054 0.393 0.055 C 0.392 0.055 0.391 0.055 0.391 0.054 C 0.390 0.051 0.390 0.052 0.390 0.054 C 0.391 0.058 0.392 0.058 0.393 0.056 Z  M 0.399 0.058 C 0.398 0.058 0.398 0.058 0.398 0.058 C 0.398 0.059 0.398 0.059 0.398 0.059 C 0.399 0.059 0.399 0.059 0.399 0.058 Z  M 0.422 0.061 C 0.422 0.060 0.422 0.059 0.422 0.059 C 0.421 0.059 0.421 0.060 0.421 0.061 C 0.421 0.062 0.421 0.063 0.422 0.063 C 0.422 0.063 0.422 0.062 0.422 0.061 Z  M 0.409 0.060 C 0.409 0.060 0.409 0.059 0.408 0.059 C 0.408 0.059 0.408 0.060 0.408 0.061 C 0.408 0.062 0.408 0.063 0.408 0.062 C 0.409 0.061 0.409 0.061 0.409 0.060 Z  M 0.390 0.061 C 0.390 0.060 0.390 0.059 0.390 0.059 C 0.390 0.059 0.389 0.059 0.389 0.058 C 0.388 0.057 0.388 0.058 0.388 0.060 C 0.389 0.063 0.389 0.064 0.390 0.061 Z  M 0.370 0.060 C 0.370 0.059 0.370 0.060 0.370 0.062 C 0.370 0.064 0.370 0.065 0.370 0.063 C 0.370 0.062 0.370 0.060 0.370 0.060 Z  M 0.358 0.067 C 0.358 0.066 0.357 0.065 0.357 0.065 C 0.357 0.065 0.357 0.066 0.357 0.067 C 0.357 0.068 0.357 0.068 0.358 0.068 C 0.358 0.068 0.358 0.068 0.358 0.067 Z  M 0.355 0.067 C 0.355 0.066 0.355 0.065 0.354 0.065 C 0.354 0.065 0.354 0.066 0.354 0.067 C 0.354 0.068 0.354 0.068 0.355 0.068 C 0.355 0.068 0.355 0.068 0.355 0.067 Z  M 0.461 0.067 C 0.460 0.066 0.460 0.065 0.460 0.065 C 0.460 0.065 0.460 0.066 0.460 0.067 C 0.460 0.069 0.461 0.070 0.461 0.070 C 0.461 0.070 0.461 0.069 0.461 0.067 Z  M 0.458 0.068 C 0.458 0.067 0.458 0.067 0.457 0.067 C 0.457 0.068 0.457 0.067 0.457 0.066 C 0.457 0.065 0.456 0.065 0.456 0.066 C 0.455 0.067 0.455 0.067 0.456 0.068 C 0.457 0.070 0.458 0.070 0.458 0.068 Z  M 0.438 0.066 C 0.438 0.064 0.438 0.063 0.438 0.062 C 0.437 0.060 0.437 0.058 0.438 0.058 C 0.438 0.058 0.438 0.057 0.438 0.056 C 0.438 0.053 0.438 0.053 0.437 0.055 C 0.436 0.059 0.436 0.071 0.437 0.069 C 0.437 0.069 0.438 0.067 0.438 0.066 Z  M 0.427 0.065 C 0.427 0.062 0.427 0.059 0.428 0.058 C 0.428 0.057 0.428 0.055 0.428 0.054 C 0.428 0.053 0.428 0.052 0.429 0.052 C 0.429 0.051 0.429 0.051 0.428 0.051 C 0.426 0.051 0.426 0.052 0.426 0.055 C 0.426 0.058 0.426 0.059 0.425 0.059 C 0.425 0.059 0.425 0.061 0.426 0.063 C 0.427 0.065 0.427 0.067 0.427 0.068 C 0.427 0.069 0.427 0.070 0.427 0.070 C 0.427 0.070 0.428 0.068 0.427 0.065 Z  M 0.422 0.068 C 0.422 0.067 0.422 0.067 0.422 0.067 C 0.421 0.067 0.421 0.067 0.421 0.068 C 0.421 0.069 0.421 0.070 0.421 0.070 C 0.421 0.070 0.422 0.069 0.422 0.068 Z  M 0.484 0.067 C 0.484 0.065 0.484 0.063 0.484 0.063 C 0.483 0.063 0.483 0.066 0.484 0.067 C 0.484 0.068 0.484 0.069 0.484 0.071 C 0.484 0.072 0.484 0.072 0.484 0.071 C 0.484 0.071 0.484 0.069 0.484 0.067 Z  M 0.422 0.074 C 0.422 0.074 0.421 0.074 0.421 0.074 C 0.421 0.075 0.421 0.075 0.422 0.075 C 0.422 0.075 0.422 0.075 0.422 0.074 Z  M 0.414 0.066 C 0.414 0.064 0.413 0.063 0.414 0.062 C 0.414 0.062 0.414 0.061 0.413 0.061 C 0.413 0.061 0.413 0.062 0.413 0.064 C 0.413 0.065 0.412 0.066 0.411 0.067 C 0.410 0.067 0.410 0.067 0.410 0.065 C 0.410 0.064 0.409 0.063 0.409 0.064 C 0.409 0.064 0.409 0.067 0.409 0.069 C 0.410 0.073 0.410 0.073 0.411 0.073 C 0.412 0.072 0.412 0.072 0.412 0.074 C 0.412 0.075 0.412 0.074 0.413 0.072 C 0.414 0.069 0.414 0.067 0.414 0.066 Z  M 0.434 0.076 C 0.434 0.075 0.434 0.074 0.434 0.074 C 0.434 0.074 0.433 0.072 0.433 0.071 C 0.433 0.068 0.433 0.069 0.433 0.072 C 0.433 0.077 0.434 0.080 0.434 0.076 Z  M 0.432 0.075 C 0.432 0.074 0.431 0.074 0.431 0.074 C 0.431 0.074 0.431 0.073 0.431 0.072 C 0.432 0.071 0.432 0.061 0.431 0.061 C 0.431 0.061 0.430 0.060 0.430 0.058 C 0.430 0.056 0.429 0.056 0.429 0.056 C 0.428 0.057 0.428 0.058 0.428 0.060 C 0.429 0.062 0.429 0.063 0.429 0.063 C 0.429 0.063 0.429 0.065 0.429 0.067 C 0.429 0.071 0.429 0.072 0.428 0.073 C 0.426 0.075 0.427 0.077 0.429 0.077 C 0.431 0.077 0.432 0.076 0.432 0.075 Z  M 0.404 0.076 C 0.404 0.076 0.404 0.074 0.404 0.072 C 0.404 0.071 0.404 0.068 0.404 0.066 C 0.404 0.064 0.404 0.063 0.405 0.063 C 0.405 0.063 0.405 0.062 0.405 0.060 C 0.404 0.058 0.404 0.058 0.405 0.058 C 0.405 0.058 0.406 0.059 0.406 0.060 C 0.406 0.062 0.406 0.062 0.407 0.060 C 0.407 0.058 0.408 0.058 0.409 0.058 C 0.410 0.059 0.410 0.059 0.409 0.054 C 0.409 0.051 0.408 0.051 0.408 0.052 C 0.408 0.053 0.408 0.054 0.408 0.054 C 0.407 0.054 0.407 0.053 0.407 0.052 C 0.408 0.049 0.404 0.051 0.403 0.054 C 0.402 0.059 0.401 0.057 0.401 0.052 C 0.401 0.048 0.401 0.048 0.399 0.051 L 0.397 0.054 L 0.398 0.056 C 0.399 0.057 0.400 0.058 0.400 0.058 C 0.400 0.058 0.400 0.058 0.400 0.059 C 0.400 0.061 0.401 0.066 0.402 0.066 C 0.403 0.066 0.404 0.073 0.403 0.076 C 0.402 0.077 0.403 0.077 0.403 0.077 C 0.404 0.077 0.405 0.077 0.404 0.076 Z  M 0.356 0.076 C 0.356 0.075 0.355 0.074 0.355 0.074 C 0.355 0.074 0.355 0.075 0.355 0.076 C 0.355 0.077 0.355 0.077 0.355 0.077 C 0.356 0.077 0.356 0.077 0.356 0.076 Z  M 0.417 0.077 C 0.417 0.077 0.417 0.077 0.417 0.075 C 0.416 0.072 0.417 0.070 0.418 0.070 C 0.419 0.070 0.419 0.070 0.418 0.068 C 0.418 0.067 0.418 0.064 0.418 0.063 C 0.418 0.061 0.417 0.059 0.417 0.059 C 0.416 0.058 0.416 0.058 0.416 0.062 C 0.416 0.065 0.416 0.067 0.416 0.067 C 0.416 0.067 0.416 0.068 0.416 0.070 C 0.416 0.073 0.416 0.074 0.415 0.075 C 0.414 0.076 0.415 0.079 0.415 0.078 C 0.416 0.078 0.417 0.078 0.417 0.077 Z  M 0.414 0.076 C 0.414 0.076 0.414 0.076 0.414 0.076 C 0.414 0.076 0.413 0.076 0.413 0.077 C 0.413 0.078 0.414 0.079 0.414 0.078 C 0.414 0.078 0.414 0.077 0.414 0.076 Z  M 0.394 0.077 C 0.395 0.076 0.396 0.077 0.396 0.078 C 0.396 0.079 0.396 0.078 0.396 0.076 C 0.396 0.072 0.396 0.070 0.397 0.068 C 0.399 0.064 0.399 0.061 0.397 0.062 C 0.396 0.063 0.395 0.063 0.394 0.064 C 0.392 0.064 0.390 0.067 0.391 0.071 C 0.392 0.072 0.392 0.075 0.392 0.076 C 0.391 0.080 0.391 0.080 0.394 0.077 Z  M 0.378 0.076 C 0.378 0.075 0.378 0.074 0.378 0.075 C 0.379 0.076 0.381 0.074 0.381 0.072 C 0.381 0.071 0.381 0.070 0.381 0.070 C 0.382 0.070 0.382 0.070 0.381 0.069 C 0.380 0.067 0.381 0.063 0.382 0.063 C 0.383 0.063 0.384 0.067 0.383 0.067 C 0.383 0.067 0.383 0.067 0.383 0.069 C 0.383 0.071 0.384 0.072 0.384 0.072 C 0.385 0.072 0.385 0.071 0.385 0.069 C 0.386 0.067 0.386 0.067 0.385 0.067 C 0.385 0.067 0.385 0.065 0.385 0.064 C 0.385 0.062 0.385 0.061 0.385 0.061 C 0.385 0.061 0.388 0.074 0.387 0.076 C 0.387 0.077 0.387 0.078 0.389 0.078 C 0.391 0.079 0.391 0.078 0.391 0.074 C 0.391 0.071 0.390 0.070 0.390 0.071 C 0.389 0.072 0.389 0.071 0.389 0.068 C 0.389 0.066 0.389 0.065 0.389 0.065 C 0.388 0.065 0.388 0.063 0.388 0.062 C 0.387 0.060 0.386 0.059 0.386 0.059 C 0.386 0.058 0.385 0.057 0.385 0.055 C 0.385 0.052 0.385 0.052 0.385 0.054 C 0.385 0.056 0.384 0.057 0.383 0.056 C 0.383 0.056 0.382 0.056 0.381 0.057 C 0.380 0.059 0.380 0.059 0.379 0.059 C 0.379 0.059 0.379 0.060 0.379 0.061 C 0.379 0.062 0.379 0.063 0.379 0.062 C 0.379 0.062 0.379 0.062 0.379 0.064 C 0.379 0.065 0.379 0.067 0.379 0.067 C 0.378 0.068 0.378 0.067 0.378 0.066 C 0.379 0.064 0.378 0.063 0.378 0.063 C 0.376 0.063 0.376 0.066 0.376 0.069 C 0.377 0.071 0.377 0.072 0.377 0.076 C 0.377 0.080 0.378 0.080 0.378 0.076 Z  M 0.469 0.077 C 0.468 0.074 0.468 0.075 0.468 0.079 C 0.468 0.082 0.468 0.082 0.469 0.081 C 0.469 0.080 0.469 0.079 0.469 0.077 Z  M 0.405 0.081 C 0.405 0.080 0.404 0.079 0.404 0.079 C 0.404 0.079 0.404 0.080 0.404 0.081 C 0.404 0.082 0.404 0.083 0.404 0.083 C 0.404 0.083 0.405 0.082 0.405 0.081 Z  M 0.359 0.081 C 0.359 0.080 0.359 0.079 0.359 0.078 C 0.358 0.078 0.358 0.079 0.358 0.080 C 0.358 0.082 0.358 0.083 0.359 0.083 C 0.359 0.083 0.359 0.082 0.359 0.081 Z  M 0.437 0.083 C 0.437 0.082 0.437 0.081 0.437 0.081 C 0.436 0.081 0.436 0.082 0.436 0.083 C 0.436 0.084 0.436 0.085 0.437 0.085 C 0.437 0.085 0.437 0.084 0.437 0.083 Z  M 0.410 0.081 C 0.411 0.077 0.410 0.076 0.409 0.076 C 0.409 0.076 0.409 0.076 0.409 0.077 C 0.410 0.078 0.410 0.079 0.409 0.080 C 0.409 0.082 0.409 0.085 0.409 0.085 C 0.410 0.085 0.410 0.083 0.410 0.081 Z  M 0.460 0.082 C 0.461 0.078 0.461 0.077 0.461 0.077 C 0.460 0.077 0.458 0.084 0.458 0.085 C 0.459 0.087 0.459 0.087 0.460 0.082 Z  M 0.425 0.080 C 0.426 0.073 0.425 0.062 0.424 0.065 C 0.424 0.066 0.424 0.067 0.424 0.067 C 0.424 0.067 0.424 0.067 0.424 0.068 C 0.423 0.070 0.423 0.077 0.423 0.077 C 0.424 0.077 0.424 0.079 0.424 0.082 C 0.423 0.087 0.424 0.086 0.425 0.080 Z  M 0.569 0.087 C 0.569 0.086 0.569 0.086 0.568 0.087 C 0.568 0.088 0.569 0.088 0.569 0.088 C 0.570 0.088 0.570 0.087 0.569 0.087 Z  M 0.413 0.087 C 0.413 0.086 0.412 0.086 0.412 0.087 C 0.412 0.087 0.412 0.088 0.413 0.088 C 0.413 0.088 0.414 0.087 0.413 0.087 Z  M 0.422 0.088 C 0.421 0.087 0.421 0.087 0.422 0.086 C 0.422 0.085 0.422 0.084 0.422 0.084 C 0.422 0.083 0.421 0.083 0.421 0.084 C 0.420 0.085 0.420 0.086 0.421 0.087 C 0.421 0.089 0.421 0.090 0.422 0.090 C 0.422 0.090 0.422 0.089 0.422 0.088 Z  M 0.391 0.088 C 0.391 0.087 0.390 0.085 0.390 0.084 C 0.390 0.083 0.390 0.083 0.390 0.084 C 0.390 0.084 0.390 0.086 0.390 0.086 C 0.390 0.087 0.390 0.088 0.390 0.088 C 0.389 0.088 0.389 0.087 0.389 0.086 C 0.389 0.085 0.389 0.085 0.388 0.085 C 0.387 0.085 0.387 0.085 0.387 0.087 C 0.387 0.089 0.391 0.090 0.391 0.088 Z  M 0.406 0.089 C 0.406 0.088 0.405 0.088 0.405 0.088 C 0.405 0.088 0.405 0.089 0.405 0.090 C 0.405 0.091 0.405 0.091 0.405 0.091 C 0.405 0.090 0.406 0.089 0.406 0.089 Z  M 0.402 0.087 C 0.402 0.086 0.402 0.085 0.402 0.085 C 0.402 0.085 0.401 0.083 0.401 0.081 C 0.401 0.079 0.401 0.077 0.401 0.077 C 0.400 0.075 0.400 0.078 0.401 0.080 C 0.401 0.081 0.401 0.082 0.401 0.083 C 0.400 0.085 0.400 0.092 0.401 0.091 C 0.402 0.090 0.402 0.089 0.402 0.087 Z  M 0.756 0.092 C 0.756 0.092 0.755 0.092 0.755 0.092 C 0.755 0.093 0.755 0.093 0.756 0.093 C 0.756 0.093 0.756 0.093 0.756 0.092 Z  M 0.451 0.091 C 0.452 0.086 0.452 0.084 0.451 0.087 C 0.451 0.089 0.450 0.091 0.450 0.092 C 0.450 0.095 0.451 0.094 0.451 0.091 Z  M 0.371 0.083 C 0.370 0.078 0.371 0.077 0.372 0.078 C 0.372 0.079 0.373 0.079 0.372 0.076 C 0.372 0.073 0.372 0.073 0.373 0.075 C 0.374 0.078 0.373 0.083 0.372 0.083 C 0.372 0.083 0.372 0.084 0.372 0.088 C 0.372 0.091 0.372 0.093 0.373 0.093 C 0.374 0.094 0.374 0.093 0.373 0.092 C 0.373 0.090 0.372 0.085 0.373 0.085 C 0.373 0.085 0.374 0.085 0.374 0.086 C 0.374 0.088 0.374 0.088 0.375 0.087 C 0.375 0.087 0.375 0.087 0.375 0.088 C 0.374 0.090 0.375 0.093 0.376 0.092 C 0.377 0.091 0.377 0.090 0.377 0.090 C 0.376 0.090 0.376 0.087 0.377 0.083 C 0.377 0.082 0.377 0.081 0.377 0.081 C 0.376 0.081 0.376 0.082 0.376 0.083 C 0.376 0.086 0.375 0.085 0.374 0.080 C 0.374 0.076 0.374 0.076 0.374 0.073 C 0.375 0.071 0.375 0.070 0.374 0.070 C 0.374 0.070 0.374 0.069 0.374 0.068 C 0.374 0.067 0.374 0.067 0.373 0.068 C 0.372 0.071 0.372 0.071 0.372 0.067 C 0.372 0.066 0.371 0.065 0.371 0.065 C 0.371 0.065 0.371 0.066 0.371 0.067 C 0.371 0.069 0.370 0.069 0.368 0.069 C 0.366 0.069 0.366 0.069 0.366 0.067 C 0.366 0.065 0.366 0.065 0.367 0.066 C 0.367 0.066 0.368 0.066 0.368 0.065 C 0.368 0.064 0.367 0.063 0.367 0.063 C 0.366 0.063 0.365 0.060 0.366 0.059 C 0.367 0.058 0.366 0.058 0.366 0.058 C 0.365 0.058 0.364 0.058 0.365 0.059 C 0.365 0.062 0.364 0.067 0.362 0.069 C 0.361 0.071 0.362 0.075 0.363 0.074 C 0.364 0.074 0.364 0.074 0.364 0.075 C 0.364 0.075 0.364 0.077 0.363 0.079 C 0.361 0.083 0.361 0.086 0.362 0.086 C 0.363 0.086 0.363 0.085 0.363 0.083 C 0.363 0.079 0.363 0.079 0.364 0.081 C 0.364 0.082 0.364 0.084 0.364 0.086 C 0.364 0.087 0.364 0.087 0.365 0.087 C 0.365 0.086 0.366 0.085 0.366 0.083 C 0.365 0.082 0.366 0.080 0.366 0.080 C 0.366 0.079 0.367 0.078 0.366 0.076 C 0.366 0.073 0.367 0.072 0.369 0.074 C 0.370 0.075 0.370 0.076 0.369 0.075 C 0.367 0.074 0.367 0.076 0.369 0.079 C 0.369 0.080 0.370 0.082 0.370 0.082 C 0.370 0.083 0.369 0.083 0.369 0.081 C 0.368 0.079 0.367 0.080 0.367 0.083 C 0.367 0.084 0.367 0.084 0.368 0.084 C 0.368 0.083 0.369 0.084 0.369 0.085 C 0.369 0.088 0.369 0.088 0.369 0.088 C 0.368 0.088 0.369 0.089 0.369 0.091 C 0.370 0.093 0.370 0.093 0.370 0.091 C 0.371 0.089 0.371 0.086 0.371 0.083 Z  M 0.440 0.093 C 0.440 0.091 0.440 0.090 0.439 0.090 C 0.439 0.090 0.439 0.091 0.439 0.092 C 0.439 0.093 0.439 0.094 0.439 0.094 C 0.438 0.095 0.438 0.095 0.439 0.095 C 0.439 0.095 0.440 0.094 0.440 0.093 Z  M 0.401 0.094 C 0.400 0.092 0.400 0.092 0.399 0.095 C 0.399 0.095 0.400 0.096 0.401 0.096 C 0.402 0.097 0.402 0.096 0.401 0.094 Z  M 0.370 0.096 C 0.370 0.095 0.370 0.095 0.369 0.096 C 0.369 0.096 0.369 0.097 0.370 0.097 C 0.371 0.097 0.371 0.096 0.370 0.096 Z  M 0.368 0.095 C 0.368 0.095 0.368 0.093 0.368 0.093 C 0.367 0.092 0.367 0.093 0.367 0.095 C 0.367 0.096 0.367 0.097 0.368 0.097 C 0.368 0.097 0.368 0.096 0.368 0.095 Z  M 0.303 0.097 C 0.303 0.096 0.303 0.096 0.302 0.096 C 0.302 0.096 0.301 0.097 0.301 0.098 C 0.301 0.099 0.303 0.099 0.303 0.097 Z  M 0.798 0.099 C 0.798 0.098 0.798 0.097 0.797 0.097 C 0.796 0.097 0.796 0.097 0.797 0.099 C 0.798 0.101 0.798 0.101 0.798 0.099 Z  M 0.783 0.098 C 0.783 0.094 0.783 0.094 0.783 0.094 C 0.782 0.094 0.782 0.094 0.783 0.095 C 0.783 0.095 0.783 0.097 0.782 0.098 C 0.782 0.100 0.782 0.101 0.782 0.101 C 0.783 0.101 0.783 0.099 0.783 0.098 Z  M 0.745 0.099 C 0.745 0.098 0.745 0.097 0.744 0.097 C 0.744 0.097 0.744 0.098 0.744 0.099 C 0.744 0.100 0.745 0.101 0.745 0.101 C 0.745 0.101 0.745 0.100 0.745 0.099 Z  M 0.420 0.098 C 0.420 0.097 0.419 0.095 0.419 0.095 C 0.419 0.094 0.418 0.095 0.418 0.097 C 0.418 0.099 0.419 0.101 0.419 0.101 C 0.419 0.101 0.420 0.100 0.420 0.098 Z  M 0.434 0.101 C 0.434 0.100 0.434 0.099 0.434 0.099 C 0.434 0.099 0.433 0.100 0.433 0.101 C 0.433 0.102 0.434 0.103 0.434 0.103 C 0.434 0.103 0.434 0.102 0.434 0.101 Z  M 0.422 0.099 C 0.422 0.098 0.422 0.097 0.421 0.097 C 0.421 0.097 0.421 0.098 0.421 0.100 C 0.422 0.103 0.423 0.102 0.422 0.099 Z  M 0.418 0.097 C 0.418 0.095 0.417 0.094 0.417 0.094 C 0.417 0.095 0.416 0.095 0.416 0.094 C 0.416 0.093 0.417 0.091 0.417 0.091 C 0.418 0.089 0.418 0.089 0.418 0.088 C 0.417 0.087 0.417 0.085 0.417 0.084 C 0.417 0.081 0.416 0.080 0.415 0.083 C 0.414 0.084 0.414 0.084 0.415 0.085 C 0.416 0.087 0.416 0.093 0.415 0.094 C 0.415 0.095 0.415 0.095 0.415 0.095 C 0.416 0.095 0.416 0.096 0.416 0.097 C 0.416 0.098 0.416 0.099 0.417 0.099 C 0.417 0.099 0.417 0.100 0.417 0.101 C 0.417 0.102 0.418 0.103 0.418 0.102 C 0.418 0.101 0.418 0.099 0.418 0.097 Z  M 0.820 0.103 C 0.821 0.102 0.820 0.099 0.819 0.099 C 0.818 0.099 0.818 0.100 0.818 0.100 C 0.819 0.101 0.819 0.102 0.819 0.103 C 0.818 0.105 0.819 0.105 0.820 0.103 Z  M 0.393 0.101 C 0.394 0.099 0.393 0.094 0.391 0.094 C 0.390 0.094 0.390 0.097 0.391 0.098 C 0.391 0.099 0.391 0.100 0.391 0.101 C 0.391 0.102 0.391 0.102 0.390 0.102 C 0.390 0.101 0.389 0.102 0.389 0.103 C 0.389 0.104 0.390 0.105 0.391 0.104 C 0.392 0.103 0.393 0.102 0.393 0.101 Z  M 0.386 0.094 C 0.386 0.093 0.386 0.092 0.386 0.092 C 0.387 0.092 0.387 0.093 0.387 0.094 C 0.387 0.095 0.387 0.095 0.387 0.095 C 0.386 0.095 0.386 0.095 0.386 0.094 Z  M 0.387 0.103 C 0.386 0.102 0.386 0.101 0.387 0.098 C 0.388 0.094 0.388 0.093 0.387 0.091 C 0.386 0.088 0.384 0.089 0.385 0.092 C 0.385 0.093 0.385 0.094 0.384 0.093 C 0.384 0.092 0.383 0.093 0.383 0.095 C 0.382 0.101 0.382 0.098 0.382 0.092 C 0.383 0.087 0.383 0.087 0.382 0.087 C 0.382 0.088 0.382 0.089 0.382 0.090 C 0.382 0.091 0.382 0.092 0.381 0.093 C 0.381 0.093 0.380 0.095 0.380 0.096 C 0.380 0.098 0.380 0.099 0.381 0.098 C 0.381 0.098 0.382 0.099 0.383 0.101 C 0.384 0.102 0.385 0.104 0.386 0.104 C 0.387 0.104 0.387 0.103 0.387 0.103 Z  M 0.382 0.103 C 0.382 0.100 0.381 0.100 0.380 0.103 C 0.380 0.104 0.380 0.104 0.380 0.104 C 0.381 0.104 0.381 0.104 0.382 0.103 Z  M 0.379 0.098 C 0.379 0.095 0.378 0.095 0.378 0.097 C 0.377 0.099 0.377 0.100 0.378 0.102 C 0.378 0.104 0.379 0.102 0.379 0.098 Z  M 0.426 0.103 C 0.427 0.104 0.427 0.103 0.427 0.101 C 0.427 0.099 0.427 0.097 0.426 0.097 C 0.426 0.097 0.426 0.096 0.427 0.095 C 0.427 0.094 0.427 0.094 0.427 0.094 C 0.426 0.093 0.426 0.093 0.427 0.092 C 0.427 0.090 0.427 0.090 0.427 0.087 C 0.426 0.086 0.426 0.085 0.425 0.085 C 0.425 0.085 0.425 0.085 0.425 0.087 C 0.426 0.089 0.426 0.092 0.425 0.091 C 0.425 0.090 0.425 0.091 0.425 0.093 C 0.425 0.096 0.425 0.097 0.425 0.097 C 0.424 0.097 0.424 0.098 0.425 0.099 C 0.425 0.101 0.425 0.101 0.424 0.100 C 0.423 0.099 0.423 0.099 0.423 0.103 C 0.423 0.105 0.424 0.106 0.424 0.104 C 0.425 0.103 0.426 0.103 0.426 0.103 Z  M 0.401 0.104 C 0.401 0.103 0.401 0.103 0.400 0.103 C 0.400 0.103 0.400 0.103 0.400 0.104 C 0.400 0.105 0.400 0.106 0.401 0.106 C 0.401 0.106 0.401 0.105 0.401 0.104 Z  M 0.422 0.106 C 0.422 0.105 0.422 0.104 0.422 0.104 C 0.421 0.104 0.421 0.105 0.421 0.106 C 0.421 0.107 0.421 0.108 0.422 0.108 C 0.422 0.108 0.422 0.107 0.422 0.106 Z  M 0.419 0.107 C 0.418 0.105 0.418 0.105 0.417 0.105 C 0.417 0.106 0.417 0.107 0.418 0.108 C 0.420 0.110 0.420 0.110 0.419 0.107 Z  M 0.305 0.107 C 0.305 0.106 0.305 0.104 0.306 0.103 C 0.307 0.101 0.308 0.094 0.307 0.094 C 0.306 0.094 0.306 0.094 0.307 0.096 C 0.307 0.097 0.307 0.097 0.306 0.096 C 0.306 0.096 0.305 0.096 0.305 0.096 C 0.304 0.098 0.303 0.101 0.304 0.107 C 0.304 0.110 0.305 0.111 0.305 0.107 Z  M 0.713 0.110 C 0.712 0.110 0.712 0.110 0.712 0.110 C 0.711 0.111 0.712 0.111 0.712 0.111 C 0.713 0.111 0.713 0.111 0.713 0.110 Z  M 0.432 0.108 C 0.432 0.106 0.432 0.104 0.431 0.104 C 0.431 0.104 0.431 0.104 0.431 0.102 C 0.432 0.101 0.432 0.101 0.431 0.101 C 0.430 0.102 0.430 0.102 0.430 0.099 C 0.431 0.096 0.431 0.096 0.430 0.097 C 0.429 0.097 0.429 0.099 0.429 0.101 C 0.429 0.103 0.429 0.104 0.429 0.105 C 0.428 0.105 0.429 0.105 0.429 0.105 C 0.430 0.105 0.431 0.106 0.431 0.108 C 0.433 0.113 0.433 0.113 0.432 0.108 L 0.432 0.108 Z  M 0.420 0.112 C 0.420 0.112 0.419 0.112 0.419 0.112 C 0.418 0.113 0.419 0.113 0.419 0.113 C 0.420 0.113 0.420 0.113 0.420 0.112 Z  M 0.412 0.107 C 0.412 0.106 0.412 0.105 0.412 0.104 C 0.413 0.102 0.413 0.104 0.413 0.106 C 0.413 0.108 0.413 0.108 0.412 0.107 Z  M 0.412 0.111 C 0.411 0.108 0.412 0.107 0.413 0.109 C 0.413 0.110 0.413 0.111 0.413 0.112 C 0.413 0.113 0.413 0.113 0.414 0.112 C 0.414 0.112 0.414 0.110 0.414 0.110 C 0.414 0.109 0.414 0.109 0.415 0.109 C 0.416 0.111 0.415 0.103 0.414 0.101 C 0.412 0.099 0.412 0.097 0.414 0.098 C 0.415 0.099 0.415 0.099 0.414 0.097 C 0.413 0.096 0.412 0.096 0.411 0.097 C 0.411 0.098 0.410 0.098 0.410 0.097 C 0.409 0.094 0.409 0.095 0.409 0.100 C 0.409 0.102 0.409 0.103 0.410 0.104 C 0.411 0.105 0.411 0.106 0.410 0.107 C 0.409 0.108 0.409 0.112 0.410 0.111 C 0.411 0.111 0.411 0.111 0.410 0.110 C 0.410 0.108 0.410 0.108 0.410 0.108 C 0.411 0.108 0.411 0.109 0.411 0.111 C 0.411 0.112 0.411 0.113 0.412 0.113 C 0.412 0.113 0.412 0.112 0.412 0.111 Z  M 0.405 0.111 C 0.405 0.108 0.405 0.108 0.406 0.109 C 0.406 0.110 0.407 0.109 0.407 0.106 C 0.408 0.104 0.408 0.103 0.407 0.103 C 0.407 0.104 0.407 0.103 0.407 0.101 C 0.406 0.099 0.406 0.097 0.406 0.097 C 0.405 0.097 0.405 0.100 0.405 0.102 C 0.405 0.103 0.404 0.104 0.404 0.106 C 0.403 0.107 0.403 0.108 0.403 0.108 C 0.404 0.108 0.404 0.109 0.404 0.110 C 0.404 0.111 0.404 0.112 0.405 0.113 C 0.405 0.113 0.405 0.112 0.405 0.111 Z  M 0.305 0.112 C 0.305 0.112 0.305 0.112 0.305 0.112 C 0.304 0.113 0.305 0.113 0.305 0.113 C 0.306 0.113 0.306 0.113 0.305 0.112 Z  M 0.428 0.113 C 0.429 0.112 0.429 0.111 0.429 0.110 C 0.428 0.109 0.428 0.110 0.427 0.112 C 0.427 0.115 0.427 0.116 0.428 0.113 Z  M 0.417 0.111 C 0.417 0.111 0.416 0.110 0.416 0.111 C 0.415 0.112 0.415 0.113 0.415 0.113 C 0.415 0.114 0.415 0.114 0.416 0.114 C 0.416 0.113 0.417 0.112 0.417 0.111 Z  M 0.307 0.113 C 0.307 0.111 0.306 0.113 0.307 0.116 C 0.307 0.118 0.307 0.118 0.307 0.117 C 0.308 0.116 0.308 0.115 0.307 0.113 Z  M 0.299 0.117 C 0.299 0.116 0.299 0.116 0.299 0.116 C 0.298 0.117 0.298 0.118 0.298 0.118 C 0.298 0.118 0.298 0.119 0.299 0.119 C 0.299 0.119 0.299 0.118 0.299 0.117 Z  M 0.297 0.117 C 0.296 0.115 0.296 0.115 0.297 0.115 C 0.298 0.115 0.298 0.114 0.298 0.113 C 0.298 0.111 0.297 0.110 0.297 0.111 C 0.296 0.112 0.296 0.111 0.296 0.109 C 0.296 0.105 0.296 0.105 0.295 0.110 C 0.294 0.112 0.294 0.113 0.294 0.113 C 0.295 0.113 0.295 0.115 0.296 0.116 C 0.296 0.117 0.297 0.119 0.297 0.119 C 0.297 0.119 0.297 0.118 0.297 0.117 Z  M 0.428 0.120 C 0.428 0.119 0.427 0.119 0.426 0.118 C 0.425 0.118 0.425 0.118 0.425 0.119 C 0.425 0.120 0.428 0.121 0.428 0.120 Z  M 0.303 0.119 C 0.303 0.118 0.302 0.117 0.302 0.118 C 0.302 0.118 0.302 0.119 0.302 0.120 C 0.302 0.120 0.302 0.121 0.302 0.121 C 0.302 0.121 0.303 0.120 0.303 0.119 Z  M 0.280 0.117 C 0.280 0.115 0.280 0.113 0.280 0.113 C 0.280 0.113 0.280 0.115 0.280 0.117 C 0.280 0.119 0.280 0.121 0.280 0.121 C 0.280 0.121 0.281 0.119 0.280 0.117 Z  M 0.293 0.129 C 0.293 0.128 0.293 0.126 0.293 0.124 C 0.292 0.122 0.292 0.121 0.292 0.123 C 0.291 0.124 0.291 0.125 0.290 0.125 C 0.288 0.125 0.288 0.126 0.289 0.128 C 0.289 0.130 0.293 0.130 0.293 0.129 Z  M 0.943 0.134 C 0.943 0.133 0.942 0.133 0.942 0.134 C 0.942 0.134 0.942 0.135 0.943 0.135 C 0.943 0.135 0.943 0.134 0.943 0.134 Z  M 0.936 0.164 C 0.936 0.164 0.935 0.164 0.935 0.164 C 0.935 0.165 0.935 0.165 0.936 0.165 C 0.936 0.165 0.937 0.165 0.936 0.164 Z  M 0.965 0.207 C 0.965 0.207 0.964 0.207 0.964 0.208 C 0.964 0.208 0.964 0.209 0.965 0.208 C 0.965 0.208 0.965 0.208 0.965 0.207 Z  M 0.972 0.279 C 0.972 0.279 0.972 0.279 0.971 0.280 C 0.971 0.280 0.972 0.281 0.972 0.280 C 0.973 0.280 0.973 0.280 0.972 0.279 Z  M 0.970 0.279 C 0.970 0.279 0.970 0.279 0.970 0.280 C 0.969 0.280 0.970 0.281 0.970 0.280 C 0.971 0.280 0.971 0.280 0.970 0.279 Z  M 0.963 0.279 C 0.962 0.279 0.962 0.279 0.962 0.280 C 0.962 0.280 0.962 0.281 0.962 0.280 C 0.963 0.280 0.963 0.280 0.963 0.279 Z  M 0.972 0.283 C 0.972 0.282 0.972 0.283 0.971 0.283 C 0.971 0.284 0.972 0.284 0.972 0.284 C 0.973 0.284 0.973 0.284 0.972 0.283 Z  M 0.079 0.347 C 0.079 0.346 0.079 0.345 0.079 0.345 C 0.078 0.345 0.078 0.346 0.078 0.347 C 0.078 0.348 0.078 0.349 0.079 0.349 C 0.079 0.349 0.079 0.348 0.079 0.347 Z  M 0.059 0.456 C 0.058 0.455 0.057 0.455 0.057 0.456 C 0.057 0.457 0.057 0.458 0.058 0.458 C 0.059 0.458 0.059 0.458 0.059 0.456 Z  M 0.050 0.456 C 0.050 0.454 0.049 0.453 0.049 0.453 C 0.049 0.453 0.049 0.454 0.050 0.456 C 0.050 0.457 0.051 0.459 0.051 0.459 C 0.051 0.459 0.051 0.457 0.050 0.456 Z  M 0.043 0.457 C 0.042 0.457 0.040 0.457 0.040 0.457 C 0.039 0.458 0.039 0.458 0.041 0.458 C 0.043 0.458 0.043 0.458 0.043 0.457 Z  M 0.047 0.458 C 0.047 0.457 0.046 0.457 0.046 0.457 C 0.045 0.457 0.045 0.458 0.045 0.459 C 0.045 0.460 0.047 0.459 0.047 0.458 Z  M 0.083 0.470 C 0.083 0.470 0.082 0.470 0.082 0.470 C 0.082 0.471 0.082 0.471 0.083 0.471 C 0.084 0.471 0.084 0.470 0.083 0.470 Z  M 0.088 0.498 C 0.089 0.498 0.089 0.498 0.089 0.496 C 0.088 0.494 0.083 0.496 0.084 0.498 C 0.084 0.499 0.085 0.499 0.086 0.499 C 0.086 0.499 0.088 0.499 0.088 0.498 Z  M 0.954 0.508 C 0.954 0.507 0.953 0.506 0.952 0.507 C 0.952 0.508 0.952 0.509 0.953 0.509 C 0.953 0.509 0.954 0.509 0.954 0.508 Z  M 0.084 0.518 C 0.084 0.517 0.083 0.516 0.083 0.517 C 0.083 0.518 0.083 0.519 0.083 0.519 C 0.083 0.519 0.083 0.520 0.083 0.520 C 0.083 0.520 0.084 0.519 0.084 0.518 Z  M 0.080 0.515 C 0.080 0.514 0.080 0.515 0.080 0.517 C 0.080 0.519 0.080 0.520 0.080 0.518 C 0.080 0.517 0.080 0.515 0.080 0.515 Z  M 0.065 0.525 C 0.065 0.524 0.064 0.523 0.064 0.523 C 0.063 0.523 0.063 0.524 0.064 0.525 C 0.065 0.527 0.065 0.527 0.065 0.525 Z  M 0.056 0.526 C 0.056 0.525 0.055 0.525 0.055 0.526 C 0.055 0.526 0.055 0.527 0.056 0.527 C 0.056 0.527 0.057 0.526 0.056 0.526 Z  M 0.084 0.529 C 0.083 0.529 0.083 0.529 0.083 0.530 C 0.083 0.530 0.083 0.531 0.083 0.530 C 0.084 0.530 0.084 0.530 0.084 0.529 Z  M 0.077 0.529 C 0.077 0.529 0.076 0.529 0.076 0.529 C 0.076 0.530 0.076 0.530 0.077 0.530 C 0.077 0.530 0.078 0.530 0.077 0.529 Z  M 0.072 0.529 C 0.072 0.528 0.072 0.527 0.071 0.527 C 0.071 0.527 0.071 0.526 0.071 0.525 C 0.071 0.523 0.071 0.522 0.070 0.523 C 0.070 0.524 0.070 0.524 0.070 0.526 C 0.070 0.527 0.071 0.529 0.071 0.529 C 0.072 0.530 0.072 0.530 0.073 0.530 C 0.073 0.531 0.073 0.530 0.072 0.529 Z  M 0.991 0.531 C 0.991 0.531 0.990 0.531 0.990 0.531 C 0.990 0.532 0.990 0.532 0.990 0.532 C 0.991 0.532 0.991 0.532 0.991 0.531 Z  M 0.047 0.532 C 0.045 0.530 0.044 0.530 0.044 0.532 C 0.044 0.533 0.045 0.534 0.046 0.534 C 0.047 0.534 0.048 0.534 0.047 0.532 Z  M 0.061 0.533 C 0.061 0.531 0.058 0.532 0.058 0.534 C 0.058 0.535 0.058 0.535 0.060 0.535 C 0.061 0.535 0.061 0.535 0.061 0.533 Z  M 0.085 0.534 C 0.085 0.533 0.085 0.532 0.084 0.533 C 0.084 0.533 0.084 0.535 0.084 0.536 C 0.084 0.537 0.084 0.538 0.084 0.537 C 0.084 0.537 0.085 0.536 0.085 0.534 Z  M 0.083 0.536 C 0.083 0.535 0.083 0.534 0.083 0.533 C 0.082 0.532 0.082 0.533 0.082 0.534 C 0.082 0.535 0.081 0.536 0.081 0.536 C 0.080 0.536 0.080 0.536 0.080 0.533 C 0.081 0.531 0.081 0.531 0.079 0.531 C 0.079 0.531 0.078 0.531 0.078 0.532 C 0.079 0.533 0.079 0.536 0.078 0.537 C 0.077 0.537 0.078 0.537 0.080 0.537 C 0.081 0.537 0.083 0.537 0.083 0.536 Z  M 0.056 0.535 C 0.055 0.532 0.054 0.532 0.052 0.534 C 0.052 0.535 0.052 0.536 0.053 0.535 C 0.054 0.534 0.055 0.535 0.055 0.536 C 0.055 0.537 0.055 0.538 0.056 0.538 C 0.056 0.538 0.056 0.537 0.056 0.535 Z  M 0.076 0.537 C 0.075 0.536 0.075 0.534 0.075 0.534 C 0.075 0.533 0.075 0.532 0.075 0.532 C 0.074 0.532 0.074 0.536 0.075 0.538 C 0.075 0.539 0.075 0.540 0.076 0.540 C 0.076 0.539 0.076 0.539 0.076 0.537 Z  M 0.072 0.533 C 0.071 0.532 0.069 0.531 0.068 0.532 C 0.066 0.533 0.064 0.534 0.063 0.534 C 0.063 0.534 0.063 0.535 0.063 0.536 C 0.063 0.536 0.063 0.537 0.064 0.537 C 0.065 0.537 0.066 0.536 0.066 0.535 C 0.066 0.534 0.066 0.534 0.067 0.535 C 0.068 0.535 0.069 0.535 0.069 0.534 C 0.069 0.533 0.070 0.533 0.070 0.533 C 0.070 0.534 0.070 0.535 0.070 0.536 C 0.070 0.537 0.070 0.538 0.070 0.538 C 0.071 0.538 0.071 0.537 0.071 0.536 C 0.071 0.533 0.072 0.534 0.072 0.537 C 0.072 0.540 0.072 0.540 0.073 0.538 C 0.073 0.535 0.073 0.535 0.072 0.533 Z  M 0.068 0.538 C 0.067 0.536 0.067 0.536 0.067 0.538 C 0.067 0.539 0.068 0.540 0.068 0.540 C 0.069 0.540 0.069 0.539 0.068 0.538 Z  M 0.054 0.538 C 0.054 0.538 0.053 0.538 0.053 0.539 C 0.053 0.539 0.053 0.540 0.054 0.539 C 0.054 0.539 0.054 0.539 0.054 0.538 Z  M 0.038 0.538 C 0.038 0.538 0.037 0.538 0.037 0.539 C 0.037 0.539 0.037 0.540 0.038 0.539 C 0.038 0.539 0.038 0.539 0.038 0.538 Z  M 0.044 0.540 C 0.044 0.540 0.044 0.540 0.043 0.540 C 0.043 0.541 0.044 0.541 0.044 0.541 C 0.045 0.541 0.045 0.541 0.044 0.540 Z  M 0.045 0.567 C 0.045 0.567 0.045 0.567 0.045 0.567 C 0.044 0.567 0.044 0.567 0.044 0.568 C 0.044 0.570 0.044 0.570 0.045 0.569 C 0.045 0.569 0.045 0.568 0.045 0.567 Z  M 0.978 0.581 C 0.978 0.580 0.978 0.579 0.978 0.579 C 0.977 0.579 0.977 0.580 0.977 0.581 C 0.977 0.582 0.977 0.583 0.978 0.583 C 0.978 0.583 0.978 0.582 0.978 0.581 Z  M 0.075 0.623 C 0.074 0.622 0.074 0.622 0.074 0.623 C 0.073 0.624 0.074 0.624 0.074 0.624 C 0.075 0.624 0.075 0.623 0.075 0.623 Z  M 0.965 0.626 C 0.965 0.625 0.965 0.624 0.965 0.624 C 0.964 0.624 0.964 0.624 0.964 0.626 C 0.965 0.628 0.965 0.628 0.965 0.626 Z  M 0.964 0.629 C 0.964 0.627 0.962 0.627 0.961 0.629 C 0.961 0.630 0.961 0.631 0.962 0.631 C 0.963 0.631 0.964 0.630 0.964 0.629 Z  M 0.045 0.632 C 0.045 0.631 0.045 0.631 0.044 0.632 C 0.044 0.633 0.044 0.633 0.045 0.633 C 0.046 0.633 0.046 0.632 0.045 0.632 Z  M 0.961 0.634 C 0.961 0.634 0.960 0.633 0.960 0.632 C 0.960 0.632 0.959 0.632 0.959 0.633 C 0.959 0.634 0.960 0.635 0.960 0.635 C 0.960 0.635 0.961 0.635 0.961 0.634 Z  M 0.035 0.633 C 0.035 0.632 0.035 0.631 0.035 0.631 C 0.034 0.631 0.034 0.632 0.034 0.633 C 0.035 0.635 0.035 0.635 0.035 0.633 Z  M 0.962 0.636 C 0.963 0.637 0.963 0.636 0.963 0.634 C 0.962 0.630 0.962 0.631 0.961 0.635 C 0.961 0.639 0.961 0.639 0.961 0.637 C 0.962 0.636 0.962 0.636 0.962 0.636 Z  M 0.032 0.664 C 0.031 0.663 0.029 0.663 0.029 0.665 C 0.029 0.665 0.030 0.665 0.031 0.665 C 0.032 0.665 0.033 0.665 0.032 0.664 Z  M 0.026 0.669 C 0.026 0.668 0.026 0.667 0.026 0.667 C 0.026 0.667 0.025 0.668 0.025 0.669 C 0.025 0.670 0.025 0.671 0.025 0.671 C 0.025 0.671 0.026 0.670 0.026 0.669 Z  M 0.056 0.703 C 0.056 0.702 0.056 0.701 0.056 0.701 C 0.055 0.701 0.055 0.702 0.055 0.703 C 0.055 0.704 0.055 0.705 0.056 0.705 C 0.056 0.705 0.056 0.704 0.056 0.703 Z  M 0.045 0.754 C 0.045 0.754 0.044 0.754 0.044 0.754 C 0.044 0.754 0.043 0.754 0.044 0.755 C 0.044 0.757 0.045 0.756 0.045 0.754 Z  M 0.062 0.767 C 0.062 0.767 0.062 0.766 0.061 0.766 C 0.060 0.766 0.060 0.765 0.060 0.764 C 0.060 0.763 0.060 0.763 0.059 0.763 C 0.059 0.763 0.059 0.764 0.059 0.765 C 0.059 0.767 0.060 0.768 0.061 0.768 C 0.062 0.768 0.063 0.768 0.062 0.767 Z  M 0.056 0.770 C 0.056 0.769 0.055 0.768 0.055 0.768 C 0.055 0.768 0.054 0.769 0.054 0.770 C 0.054 0.771 0.054 0.772 0.055 0.772 C 0.056 0.772 0.056 0.771 0.056 0.770 Z  M 0.044 0.779 C 0.044 0.778 0.044 0.777 0.043 0.777 C 0.041 0.777 0.041 0.777 0.042 0.779 C 0.043 0.780 0.044 0.780 0.044 0.780 C 0.044 0.781 0.044 0.780 0.044 0.779 Z  M 0.038 0.788 C 0.038 0.787 0.038 0.786 0.038 0.786 C 0.037 0.786 0.037 0.787 0.037 0.788 C 0.037 0.789 0.038 0.790 0.038 0.790 C 0.038 0.790 0.038 0.789 0.038 0.788 Z  M 0.041 0.790 C 0.041 0.789 0.040 0.788 0.040 0.788 C 0.040 0.788 0.040 0.789 0.040 0.790 C 0.040 0.791 0.040 0.791 0.041 0.791 C 0.041 0.791 0.041 0.791 0.041 0.790 Z  M 0.016 0.831 C 0.016 0.829 0.015 0.829 0.015 0.831 C 0.015 0.832 0.015 0.832 0.015 0.832 C 0.016 0.832 0.016 0.831 0.016 0.831 Z  M 0.016 0.835 C 0.016 0.835 0.016 0.835 0.016 0.835 C 0.015 0.836 0.016 0.836 0.016 0.836 C 0.017 0.836 0.017 0.836 0.016 0.835 Z  M 0.013 0.840 C 0.013 0.839 0.013 0.838 0.013 0.839 C 0.012 0.840 0.012 0.841 0.012 0.841 C 0.012 0.841 0.012 0.842 0.013 0.842 C 0.013 0.842 0.013 0.841 0.013 0.840 Z  M 0.024 0.850 C 0.023 0.849 0.023 0.849 0.023 0.850 C 0.023 0.850 0.023 0.851 0.023 0.851 C 0.024 0.851 0.024 0.850 0.024 0.850 Z  M 0.022 0.849 C 0.022 0.848 0.021 0.847 0.021 0.847 C 0.020 0.847 0.020 0.848 0.020 0.849 C 0.020 0.850 0.021 0.851 0.021 0.851 C 0.022 0.851 0.022 0.850 0.022 0.849 Z  M 0.017 0.858 C 0.017 0.857 0.016 0.856 0.016 0.856 C 0.016 0.856 0.015 0.857 0.015 0.858 C 0.015 0.859 0.016 0.860 0.016 0.860 C 0.017 0.860 0.017 0.859 0.017 0.858 Z  M 0.020 0.867 C 0.020 0.866 0.019 0.865 0.019 0.865 C 0.019 0.865 0.018 0.866 0.018 0.867 C 0.018 0.868 0.018 0.869 0.019 0.869 C 0.020 0.869 0.020 0.868 0.020 0.867 Z  M 0.636 0.995 C 0.636 0.993 0.635 0.993 0.634 0.993 C 0.631 0.993 0.631 0.993 0.630 0.990 C 0.629 0.986 0.628 0.984 0.628 0.987 C 0.629 0.988 0.628 0.988 0.627 0.988 C 0.626 0.988 0.624 0.989 0.624 0.990 C 0.624 0.992 0.623 0.992 0.621 0.991 C 0.619 0.989 0.618 0.988 0.616 0.988 C 0.616 0.988 0.616 0.987 0.616 0.986 C 0.616 0.985 0.615 0.983 0.615 0.982 C 0.613 0.980 0.612 0.975 0.612 0.973 C 0.612 0.972 0.612 0.971 0.612 0.971 C 0.611 0.971 0.611 0.972 0.611 0.973 C 0.611 0.974 0.611 0.975 0.611 0.975 C 0.610 0.975 0.610 0.977 0.609 0.980 C 0.608 0.986 0.607 0.988 0.607 0.983 C 0.607 0.980 0.607 0.980 0.604 0.985 C 0.604 0.987 0.603 0.987 0.603 0.986 C 0.603 0.984 0.600 0.985 0.599 0.987 C 0.599 0.989 0.598 0.989 0.598 0.987 C 0.598 0.987 0.598 0.986 0.598 0.985 C 0.599 0.985 0.598 0.984 0.598 0.984 C 0.598 0.984 0.597 0.985 0.597 0.986 C 0.597 0.989 0.595 0.988 0.594 0.984 C 0.593 0.982 0.592 0.980 0.591 0.980 C 0.590 0.980 0.589 0.979 0.588 0.977 C 0.586 0.974 0.586 0.974 0.585 0.976 C 0.585 0.977 0.584 0.978 0.584 0.978 C 0.584 0.978 0.584 0.979 0.584 0.980 C 0.584 0.981 0.583 0.982 0.583 0.982 C 0.582 0.982 0.582 0.982 0.582 0.980 C 0.583 0.978 0.582 0.978 0.581 0.978 C 0.581 0.979 0.580 0.978 0.580 0.976 C 0.580 0.973 0.579 0.971 0.578 0.971 C 0.578 0.971 0.578 0.972 0.578 0.973 C 0.578 0.973 0.576 0.974 0.574 0.973 C 0.571 0.973 0.570 0.973 0.569 0.976 C 0.569 0.980 0.567 0.981 0.567 0.978 C 0.567 0.975 0.566 0.976 0.565 0.980 C 0.564 0.982 0.564 0.984 0.563 0.984 C 0.563 0.984 0.563 0.984 0.563 0.982 C 0.564 0.981 0.564 0.980 0.563 0.979 C 0.563 0.979 0.562 0.977 0.562 0.976 C 0.562 0.974 0.562 0.972 0.561 0.970 C 0.559 0.967 0.559 0.967 0.558 0.970 C 0.557 0.971 0.556 0.973 0.554 0.974 C 0.552 0.975 0.552 0.975 0.552 0.973 C 0.553 0.972 0.553 0.971 0.552 0.971 C 0.551 0.971 0.550 0.975 0.549 0.977 C 0.549 0.978 0.548 0.978 0.548 0.978 C 0.547 0.977 0.547 0.976 0.547 0.975 C 0.548 0.973 0.546 0.968 0.544 0.968 C 0.543 0.969 0.542 0.968 0.541 0.966 C 0.540 0.964 0.540 0.964 0.539 0.966 C 0.538 0.968 0.537 0.968 0.537 0.966 C 0.536 0.965 0.536 0.965 0.535 0.968 C 0.534 0.970 0.534 0.971 0.533 0.971 C 0.532 0.970 0.532 0.971 0.532 0.972 C 0.532 0.974 0.531 0.973 0.530 0.970 C 0.529 0.966 0.528 0.965 0.528 0.968 C 0.528 0.969 0.528 0.969 0.527 0.969 C 0.527 0.969 0.527 0.970 0.527 0.972 C 0.527 0.973 0.527 0.974 0.526 0.974 C 0.525 0.974 0.525 0.973 0.525 0.972 C 0.525 0.971 0.524 0.970 0.523 0.970 C 0.521 0.971 0.521 0.970 0.521 0.968 C 0.520 0.966 0.520 0.966 0.519 0.968 C 0.519 0.969 0.518 0.969 0.517 0.968 C 0.517 0.967 0.516 0.967 0.515 0.967 C 0.513 0.967 0.512 0.966 0.511 0.965 C 0.511 0.964 0.510 0.964 0.510 0.966 C 0.511 0.971 0.509 0.969 0.509 0.964 C 0.508 0.960 0.508 0.958 0.507 0.957 C 0.506 0.957 0.506 0.956 0.506 0.955 C 0.506 0.954 0.506 0.953 0.506 0.953 C 0.505 0.953 0.505 0.953 0.505 0.952 C 0.505 0.951 0.504 0.950 0.503 0.950 C 0.501 0.950 0.500 0.950 0.500 0.954 C 0.499 0.959 0.497 0.962 0.496 0.959 C 0.496 0.956 0.493 0.958 0.494 0.962 C 0.494 0.963 0.494 0.964 0.493 0.964 C 0.492 0.964 0.492 0.963 0.492 0.962 C 0.492 0.959 0.487 0.952 0.485 0.955 C 0.485 0.956 0.485 0.956 0.485 0.957 C 0.486 0.958 0.486 0.958 0.485 0.959 C 0.484 0.959 0.483 0.957 0.483 0.955 C 0.483 0.953 0.483 0.953 0.483 0.954 C 0.482 0.955 0.481 0.954 0.481 0.952 C 0.480 0.951 0.480 0.950 0.479 0.952 C 0.479 0.953 0.478 0.954 0.477 0.954 C 0.476 0.954 0.476 0.954 0.475 0.955 C 0.474 0.958 0.472 0.959 0.471 0.956 C 0.470 0.953 0.467 0.953 0.466 0.955 C 0.465 0.957 0.462 0.954 0.462 0.951 C 0.462 0.950 0.462 0.950 0.461 0.951 C 0.460 0.951 0.460 0.951 0.459 0.948 C 0.458 0.946 0.458 0.944 0.458 0.944 C 0.457 0.944 0.457 0.943 0.458 0.942 C 0.458 0.940 0.457 0.942 0.456 0.946 C 0.455 0.947 0.454 0.948 0.451 0.949 C 0.448 0.949 0.445 0.950 0.444 0.951 C 0.442 0.953 0.442 0.953 0.442 0.951 C 0.441 0.950 0.441 0.949 0.441 0.950 C 0.441 0.952 0.439 0.948 0.439 0.946 C 0.439 0.944 0.438 0.943 0.438 0.943 C 0.437 0.943 0.437 0.944 0.437 0.945 C 0.437 0.947 0.434 0.948 0.434 0.946 C 0.434 0.944 0.433 0.944 0.433 0.946 C 0.433 0.947 0.432 0.948 0.432 0.947 C 0.432 0.946 0.431 0.947 0.431 0.947 C 0.430 0.950 0.427 0.953 0.427 0.952 C 0.427 0.951 0.426 0.951 0.425 0.950 C 0.424 0.950 0.424 0.949 0.424 0.949 C 0.423 0.946 0.415 0.947 0.414 0.949 C 0.413 0.952 0.411 0.954 0.411 0.951 C 0.411 0.950 0.410 0.950 0.410 0.950 C 0.409 0.950 0.409 0.949 0.409 0.948 C 0.409 0.947 0.408 0.946 0.407 0.946 C 0.406 0.946 0.405 0.947 0.405 0.948 C 0.405 0.949 0.405 0.950 0.405 0.950 C 0.404 0.950 0.404 0.951 0.404 0.952 C 0.403 0.956 0.401 0.958 0.400 0.954 C 0.400 0.953 0.399 0.951 0.399 0.951 C 0.398 0.951 0.398 0.951 0.398 0.950 C 0.398 0.949 0.398 0.949 0.397 0.948 C 0.396 0.948 0.395 0.950 0.394 0.953 C 0.394 0.955 0.393 0.957 0.393 0.955 C 0.393 0.954 0.390 0.946 0.389 0.946 C 0.389 0.946 0.388 0.949 0.387 0.952 C 0.386 0.955 0.386 0.956 0.386 0.955 C 0.386 0.954 0.386 0.954 0.385 0.954 C 0.385 0.955 0.384 0.955 0.384 0.954 C 0.384 0.951 0.378 0.951 0.378 0.953 C 0.377 0.954 0.377 0.955 0.377 0.955 C 0.378 0.955 0.378 0.956 0.377 0.957 C 0.377 0.958 0.377 0.958 0.376 0.957 C 0.375 0.955 0.373 0.954 0.371 0.954 C 0.368 0.954 0.366 0.953 0.365 0.953 C 0.364 0.953 0.363 0.953 0.362 0.954 C 0.360 0.955 0.360 0.954 0.359 0.952 C 0.358 0.948 0.356 0.948 0.356 0.952 C 0.356 0.955 0.354 0.957 0.353 0.955 C 0.352 0.954 0.352 0.953 0.351 0.953 C 0.350 0.953 0.350 0.953 0.350 0.951 C 0.350 0.950 0.350 0.950 0.350 0.950 C 0.349 0.950 0.349 0.948 0.349 0.947 C 0.350 0.946 0.350 0.944 0.349 0.944 C 0.349 0.944 0.349 0.946 0.349 0.947 C 0.349 0.948 0.348 0.950 0.348 0.950 C 0.347 0.950 0.347 0.951 0.347 0.952 C 0.346 0.956 0.345 0.956 0.342 0.952 C 0.339 0.948 0.338 0.948 0.335 0.948 C 0.334 0.949 0.332 0.949 0.332 0.948 C 0.332 0.947 0.332 0.948 0.331 0.950 C 0.330 0.955 0.329 0.956 0.329 0.953 C 0.329 0.952 0.328 0.951 0.328 0.951 C 0.328 0.951 0.327 0.951 0.327 0.950 C 0.327 0.948 0.325 0.949 0.324 0.951 C 0.324 0.951 0.323 0.952 0.322 0.952 C 0.321 0.952 0.319 0.954 0.319 0.955 C 0.318 0.958 0.316 0.956 0.315 0.951 C 0.315 0.949 0.315 0.948 0.314 0.949 C 0.313 0.950 0.313 0.949 0.313 0.948 C 0.312 0.945 0.310 0.946 0.309 0.948 C 0.309 0.950 0.309 0.950 0.308 0.948 C 0.308 0.947 0.307 0.947 0.306 0.947 C 0.306 0.948 0.305 0.947 0.305 0.946 C 0.305 0.944 0.305 0.944 0.305 0.945 C 0.304 0.951 0.295 0.955 0.296 0.949 C 0.296 0.948 0.296 0.948 0.295 0.948 C 0.294 0.949 0.294 0.948 0.294 0.947 C 0.294 0.946 0.294 0.946 0.293 0.947 C 0.293 0.948 0.292 0.949 0.292 0.949 C 0.291 0.950 0.291 0.949 0.291 0.948 C 0.291 0.947 0.290 0.947 0.289 0.948 C 0.289 0.948 0.287 0.947 0.287 0.946 C 0.286 0.945 0.285 0.944 0.285 0.946 C 0.284 0.947 0.282 0.948 0.280 0.949 C 0.277 0.949 0.274 0.950 0.273 0.951 C 0.272 0.951 0.271 0.950 0.271 0.948 C 0.270 0.946 0.270 0.946 0.269 0.949 C 0.268 0.951 0.268 0.951 0.268 0.949 C 0.268 0.947 0.268 0.946 0.267 0.946 C 0.267 0.946 0.267 0.945 0.267 0.944 C 0.267 0.943 0.266 0.943 0.265 0.945 C 0.264 0.947 0.264 0.947 0.263 0.945 C 0.261 0.941 0.257 0.945 0.258 0.950 C 0.258 0.952 0.258 0.952 0.255 0.952 C 0.254 0.953 0.253 0.952 0.253 0.950 C 0.252 0.948 0.252 0.948 0.251 0.949 C 0.251 0.950 0.250 0.950 0.250 0.950 C 0.249 0.949 0.248 0.948 0.248 0.948 C 0.247 0.948 0.246 0.947 0.246 0.946 C 0.246 0.945 0.244 0.940 0.243 0.940 C 0.243 0.940 0.242 0.941 0.241 0.941 C 0.241 0.942 0.240 0.942 0.239 0.938 C 0.238 0.934 0.238 0.933 0.238 0.935 C 0.237 0.938 0.230 0.939 0.229 0.937 C 0.228 0.935 0.228 0.935 0.226 0.937 C 0.224 0.940 0.221 0.941 0.221 0.939 C 0.221 0.938 0.221 0.937 0.221 0.937 C 0.221 0.937 0.220 0.938 0.220 0.939 C 0.220 0.940 0.220 0.940 0.220 0.939 C 0.219 0.938 0.218 0.938 0.217 0.939 C 0.217 0.940 0.216 0.940 0.216 0.939 C 0.216 0.938 0.214 0.938 0.212 0.938 C 0.209 0.938 0.207 0.939 0.206 0.939 C 0.205 0.939 0.204 0.940 0.204 0.942 C 0.203 0.944 0.203 0.944 0.203 0.943 C 0.204 0.939 0.201 0.939 0.197 0.941 C 0.196 0.943 0.195 0.942 0.194 0.941 C 0.193 0.938 0.188 0.939 0.186 0.942 C 0.185 0.943 0.185 0.942 0.185 0.941 C 0.185 0.940 0.185 0.939 0.185 0.940 C 0.184 0.940 0.184 0.940 0.183 0.938 C 0.182 0.935 0.182 0.935 0.181 0.939 C 0.180 0.942 0.179 0.942 0.178 0.941 C 0.177 0.939 0.175 0.939 0.175 0.941 C 0.175 0.942 0.174 0.942 0.173 0.943 C 0.172 0.943 0.171 0.943 0.171 0.942 C 0.171 0.941 0.171 0.941 0.170 0.941 C 0.170 0.941 0.170 0.939 0.170 0.938 C 0.170 0.936 0.169 0.935 0.164 0.936 C 0.161 0.937 0.157 0.937 0.157 0.938 C 0.156 0.938 0.156 0.937 0.156 0.935 C 0.156 0.934 0.156 0.932 0.155 0.932 C 0.154 0.930 0.151 0.935 0.151 0.938 C 0.151 0.938 0.150 0.939 0.149 0.938 C 0.148 0.937 0.147 0.937 0.147 0.939 C 0.147 0.942 0.145 0.941 0.145 0.938 C 0.145 0.936 0.144 0.936 0.144 0.936 C 0.144 0.937 0.143 0.936 0.143 0.935 C 0.143 0.934 0.143 0.934 0.142 0.934 C 0.141 0.935 0.141 0.934 0.140 0.933 C 0.140 0.932 0.140 0.932 0.139 0.933 C 0.138 0.933 0.138 0.933 0.138 0.932 C 0.137 0.931 0.135 0.930 0.133 0.929 C 0.131 0.928 0.128 0.927 0.128 0.927 C 0.127 0.927 0.126 0.926 0.125 0.926 C 0.125 0.926 0.123 0.925 0.122 0.923 C 0.121 0.922 0.120 0.921 0.120 0.923 C 0.119 0.925 0.116 0.925 0.116 0.923 C 0.116 0.921 0.115 0.921 0.115 0.923 C 0.114 0.924 0.114 0.924 0.113 0.924 C 0.113 0.923 0.113 0.923 0.113 0.925 C 0.113 0.926 0.112 0.926 0.112 0.923 C 0.111 0.921 0.110 0.920 0.107 0.920 C 0.105 0.920 0.102 0.919 0.101 0.918 C 0.100 0.918 0.098 0.917 0.097 0.917 C 0.095 0.916 0.094 0.916 0.094 0.915 C 0.093 0.915 0.089 0.914 0.078 0.913 C 0.071 0.912 0.064 0.911 0.062 0.910 C 0.060 0.909 0.057 0.908 0.055 0.908 C 0.054 0.907 0.052 0.907 0.052 0.906 C 0.050 0.903 0.048 0.903 0.040 0.902 C 0.030 0.901 0.027 0.899 0.026 0.892 C 0.026 0.888 0.026 0.887 0.024 0.886 C 0.023 0.886 0.021 0.886 0.020 0.885 C 0.019 0.885 0.019 0.884 0.019 0.882 C 0.020 0.880 0.019 0.880 0.018 0.880 C 0.018 0.880 0.017 0.879 0.016 0.877 C 0.016 0.875 0.016 0.875 0.016 0.877 C 0.016 0.880 0.016 0.880 0.014 0.880 C 0.013 0.881 0.012 0.880 0.013 0.879 C 0.013 0.878 0.014 0.878 0.015 0.878 C 0.015 0.879 0.015 0.878 0.015 0.876 C 0.015 0.874 0.016 0.874 0.017 0.875 C 0.018 0.876 0.019 0.875 0.018 0.874 C 0.018 0.873 0.017 0.872 0.016 0.872 C 0.015 0.872 0.013 0.871 0.013 0.871 C 0.012 0.869 0.012 0.869 0.013 0.869 C 0.014 0.868 0.015 0.868 0.016 0.868 C 0.016 0.868 0.017 0.867 0.017 0.866 C 0.018 0.864 0.018 0.863 0.016 0.862 C 0.015 0.861 0.014 0.860 0.015 0.856 C 0.015 0.855 0.016 0.854 0.018 0.854 C 0.020 0.853 0.020 0.853 0.020 0.850 C 0.019 0.848 0.019 0.847 0.019 0.848 C 0.019 0.849 0.018 0.850 0.017 0.850 C 0.015 0.849 0.015 0.850 0.016 0.851 C 0.017 0.852 0.017 0.852 0.016 0.852 C 0.015 0.853 0.014 0.853 0.014 0.854 C 0.013 0.855 0.013 0.855 0.014 0.852 C 0.015 0.849 0.015 0.847 0.014 0.847 C 0.013 0.847 0.013 0.846 0.013 0.845 C 0.013 0.844 0.013 0.844 0.013 0.844 C 0.012 0.844 0.012 0.844 0.012 0.845 C 0.013 0.847 0.011 0.847 0.011 0.845 C 0.011 0.844 0.010 0.844 0.010 0.845 C 0.009 0.847 0.009 0.847 0.008 0.845 C 0.008 0.843 0.007 0.842 0.007 0.841 C 0.006 0.841 0.006 0.840 0.007 0.840 C 0.008 0.840 0.009 0.839 0.009 0.838 C 0.009 0.837 0.009 0.837 0.010 0.839 C 0.010 0.840 0.011 0.842 0.011 0.842 C 0.012 0.842 0.012 0.841 0.011 0.840 C 0.010 0.839 0.010 0.838 0.011 0.838 C 0.012 0.838 0.012 0.838 0.012 0.835 C 0.011 0.833 0.011 0.833 0.011 0.833 C 0.012 0.834 0.012 0.834 0.013 0.833 C 0.013 0.831 0.013 0.831 0.013 0.833 C 0.013 0.834 0.014 0.834 0.014 0.831 C 0.014 0.829 0.014 0.827 0.015 0.827 C 0.015 0.827 0.015 0.827 0.015 0.826 C 0.015 0.825 0.015 0.825 0.014 0.825 C 0.014 0.826 0.013 0.825 0.013 0.824 C 0.013 0.824 0.014 0.823 0.015 0.823 C 0.016 0.823 0.018 0.822 0.018 0.820 C 0.018 0.819 0.020 0.818 0.023 0.819 C 0.026 0.819 0.027 0.819 0.027 0.817 C 0.027 0.816 0.027 0.815 0.026 0.815 C 0.025 0.815 0.025 0.814 0.026 0.813 C 0.027 0.811 0.027 0.810 0.031 0.808 C 0.033 0.808 0.034 0.807 0.034 0.805 C 0.033 0.804 0.032 0.803 0.031 0.804 C 0.030 0.804 0.029 0.804 0.030 0.802 C 0.030 0.800 0.032 0.800 0.034 0.800 C 0.038 0.800 0.039 0.799 0.037 0.796 C 0.037 0.795 0.036 0.795 0.035 0.795 C 0.034 0.795 0.033 0.794 0.034 0.793 C 0.034 0.792 0.034 0.792 0.034 0.791 C 0.033 0.790 0.033 0.790 0.033 0.791 C 0.032 0.793 0.031 0.789 0.031 0.787 C 0.032 0.786 0.031 0.786 0.031 0.787 C 0.031 0.787 0.031 0.789 0.031 0.790 C 0.031 0.792 0.031 0.792 0.029 0.789 C 0.026 0.785 0.023 0.785 0.023 0.788 C 0.022 0.790 0.022 0.790 0.022 0.788 C 0.022 0.787 0.022 0.786 0.022 0.786 C 0.022 0.786 0.021 0.787 0.022 0.787 C 0.022 0.788 0.021 0.789 0.020 0.789 C 0.019 0.789 0.019 0.788 0.019 0.788 C 0.019 0.787 0.019 0.786 0.019 0.786 C 0.018 0.786 0.018 0.785 0.017 0.785 C 0.017 0.784 0.017 0.784 0.017 0.786 C 0.017 0.787 0.017 0.788 0.016 0.788 H 0.015 L 0.016 0.785 C 0.018 0.781 0.018 0.779 0.016 0.779 C 0.015 0.779 0.015 0.778 0.015 0.777 C 0.015 0.777 0.017 0.776 0.019 0.775 C 0.024 0.775 0.026 0.774 0.026 0.773 C 0.027 0.773 0.027 0.773 0.028 0.773 C 0.028 0.774 0.029 0.773 0.029 0.772 C 0.029 0.770 0.029 0.770 0.029 0.771 C 0.030 0.773 0.035 0.773 0.038 0.771 C 0.040 0.770 0.042 0.764 0.041 0.764 C 0.040 0.764 0.040 0.763 0.040 0.761 C 0.041 0.759 0.041 0.758 0.042 0.759 C 0.043 0.759 0.043 0.759 0.042 0.757 C 0.042 0.756 0.041 0.755 0.041 0.755 C 0.040 0.755 0.040 0.754 0.040 0.753 C 0.040 0.752 0.040 0.752 0.040 0.752 C 0.040 0.753 0.039 0.753 0.039 0.751 C 0.038 0.750 0.038 0.750 0.038 0.752 C 0.039 0.754 0.038 0.755 0.037 0.757 C 0.036 0.758 0.035 0.759 0.034 0.759 C 0.034 0.759 0.032 0.760 0.031 0.761 C 0.029 0.762 0.027 0.762 0.027 0.762 C 0.027 0.761 0.026 0.762 0.026 0.763 C 0.026 0.763 0.026 0.764 0.025 0.763 C 0.024 0.762 0.024 0.762 0.024 0.761 C 0.025 0.760 0.024 0.760 0.023 0.760 C 0.021 0.760 0.020 0.760 0.020 0.759 C 0.019 0.758 0.019 0.757 0.018 0.758 C 0.018 0.758 0.017 0.758 0.018 0.757 C 0.018 0.755 0.017 0.755 0.016 0.757 C 0.016 0.758 0.015 0.758 0.015 0.756 C 0.014 0.755 0.014 0.754 0.014 0.754 C 0.014 0.754 0.015 0.753 0.015 0.752 C 0.016 0.752 0.016 0.752 0.016 0.754 C 0.015 0.755 0.016 0.755 0.017 0.753 C 0.017 0.751 0.018 0.750 0.019 0.751 C 0.020 0.751 0.021 0.751 0.022 0.750 C 0.023 0.749 0.026 0.748 0.028 0.747 C 0.031 0.747 0.033 0.745 0.033 0.744 C 0.034 0.743 0.035 0.742 0.036 0.742 C 0.037 0.742 0.038 0.740 0.038 0.739 C 0.038 0.738 0.039 0.737 0.040 0.736 C 0.040 0.736 0.041 0.736 0.041 0.736 C 0.041 0.735 0.042 0.734 0.043 0.734 C 0.044 0.734 0.044 0.733 0.043 0.731 C 0.043 0.728 0.042 0.727 0.039 0.728 C 0.037 0.728 0.036 0.727 0.037 0.726 C 0.037 0.726 0.037 0.725 0.037 0.725 C 0.036 0.725 0.037 0.724 0.037 0.723 C 0.038 0.722 0.038 0.722 0.039 0.724 C 0.039 0.725 0.039 0.724 0.040 0.722 C 0.041 0.721 0.041 0.719 0.042 0.719 C 0.042 0.719 0.042 0.719 0.042 0.718 C 0.041 0.717 0.041 0.716 0.041 0.716 C 0.042 0.716 0.042 0.717 0.042 0.717 C 0.042 0.718 0.044 0.720 0.045 0.720 C 0.046 0.720 0.048 0.722 0.049 0.723 C 0.050 0.725 0.051 0.725 0.052 0.723 C 0.053 0.721 0.053 0.721 0.052 0.718 C 0.051 0.715 0.050 0.714 0.048 0.714 C 0.046 0.713 0.045 0.712 0.044 0.712 C 0.044 0.711 0.043 0.711 0.043 0.713 C 0.042 0.714 0.041 0.714 0.041 0.713 C 0.040 0.710 0.044 0.708 0.045 0.710 C 0.046 0.710 0.046 0.710 0.046 0.709 C 0.046 0.708 0.046 0.707 0.046 0.707 C 0.047 0.707 0.047 0.707 0.048 0.707 C 0.049 0.707 0.049 0.707 0.048 0.704 C 0.047 0.703 0.046 0.702 0.046 0.702 C 0.045 0.702 0.043 0.702 0.041 0.701 C 0.040 0.700 0.037 0.700 0.035 0.700 C 0.032 0.700 0.031 0.699 0.031 0.698 C 0.031 0.696 0.031 0.696 0.030 0.697 C 0.030 0.698 0.026 0.698 0.022 0.697 C 0.021 0.697 0.021 0.696 0.021 0.695 C 0.021 0.693 0.021 0.693 0.020 0.693 C 0.019 0.694 0.019 0.694 0.020 0.693 C 0.020 0.691 0.023 0.690 0.026 0.691 C 0.026 0.691 0.028 0.691 0.028 0.690 C 0.029 0.689 0.030 0.689 0.031 0.690 C 0.032 0.691 0.032 0.691 0.033 0.691 C 0.033 0.690 0.032 0.689 0.032 0.689 C 0.031 0.689 0.031 0.688 0.031 0.688 C 0.031 0.687 0.031 0.685 0.031 0.684 C 0.030 0.682 0.030 0.681 0.031 0.682 C 0.031 0.683 0.031 0.683 0.031 0.682 C 0.031 0.680 0.031 0.680 0.029 0.679 C 0.029 0.679 0.028 0.678 0.028 0.678 C 0.028 0.677 0.027 0.677 0.026 0.677 C 0.025 0.677 0.024 0.676 0.024 0.675 C 0.023 0.674 0.023 0.674 0.023 0.673 C 0.024 0.671 0.024 0.671 0.023 0.671 C 0.022 0.671 0.021 0.670 0.021 0.669 C 0.021 0.667 0.021 0.668 0.021 0.670 C 0.021 0.671 0.021 0.673 0.022 0.673 C 0.022 0.673 0.022 0.674 0.022 0.675 C 0.022 0.676 0.022 0.676 0.021 0.675 C 0.021 0.675 0.020 0.674 0.019 0.674 C 0.019 0.673 0.018 0.671 0.019 0.671 C 0.019 0.671 0.019 0.670 0.019 0.668 C 0.019 0.666 0.019 0.665 0.022 0.666 C 0.026 0.666 0.026 0.666 0.026 0.663 C 0.026 0.662 0.027 0.661 0.027 0.661 C 0.028 0.661 0.029 0.660 0.028 0.660 C 0.028 0.659 0.028 0.658 0.027 0.658 C 0.027 0.658 0.027 0.658 0.027 0.656 C 0.028 0.655 0.028 0.655 0.029 0.656 C 0.030 0.659 0.031 0.657 0.029 0.654 C 0.029 0.652 0.027 0.651 0.024 0.651 C 0.021 0.651 0.019 0.650 0.019 0.649 C 0.019 0.648 0.019 0.647 0.019 0.648 C 0.020 0.649 0.020 0.647 0.019 0.644 C 0.019 0.642 0.019 0.642 0.020 0.643 C 0.020 0.643 0.021 0.643 0.021 0.642 C 0.021 0.641 0.021 0.641 0.021 0.642 C 0.021 0.642 0.023 0.643 0.025 0.642 C 0.027 0.641 0.028 0.641 0.027 0.641 C 0.027 0.640 0.026 0.639 0.026 0.638 C 0.025 0.637 0.025 0.637 0.024 0.638 C 0.023 0.639 0.020 0.640 0.020 0.638 C 0.020 0.637 0.019 0.637 0.018 0.637 C 0.016 0.637 0.018 0.635 0.022 0.634 C 0.025 0.633 0.027 0.632 0.027 0.631 C 0.028 0.630 0.028 0.630 0.029 0.631 C 0.029 0.632 0.029 0.631 0.029 0.630 C 0.029 0.627 0.029 0.627 0.030 0.630 C 0.030 0.632 0.031 0.631 0.031 0.629 C 0.031 0.627 0.031 0.627 0.031 0.630 C 0.031 0.631 0.031 0.631 0.031 0.630 C 0.031 0.628 0.033 0.628 0.036 0.631 C 0.037 0.631 0.038 0.631 0.038 0.630 C 0.038 0.629 0.038 0.629 0.039 0.628 C 0.040 0.628 0.040 0.629 0.040 0.630 C 0.040 0.631 0.040 0.631 0.040 0.631 C 0.041 0.631 0.042 0.631 0.042 0.630 C 0.042 0.629 0.042 0.628 0.043 0.627 C 0.044 0.627 0.044 0.627 0.044 0.628 C 0.044 0.629 0.043 0.630 0.043 0.630 C 0.042 0.630 0.042 0.630 0.043 0.631 C 0.043 0.631 0.044 0.630 0.045 0.628 C 0.046 0.625 0.046 0.625 0.046 0.627 C 0.046 0.629 0.047 0.632 0.048 0.630 C 0.048 0.628 0.051 0.628 0.058 0.628 C 0.059 0.628 0.061 0.627 0.061 0.626 C 0.062 0.625 0.064 0.624 0.067 0.624 L 0.071 0.624 L 0.068 0.622 C 0.066 0.621 0.063 0.621 0.061 0.620 C 0.059 0.620 0.058 0.619 0.058 0.618 C 0.058 0.618 0.056 0.617 0.053 0.617 C 0.050 0.617 0.048 0.616 0.048 0.614 L 0.046 0.612 L 0.048 0.612 C 0.049 0.613 0.049 0.613 0.050 0.614 C 0.050 0.616 0.052 0.615 0.053 0.613 C 0.053 0.611 0.053 0.611 0.053 0.613 C 0.053 0.616 0.055 0.616 0.055 0.612 C 0.055 0.610 0.055 0.610 0.056 0.610 C 0.057 0.611 0.057 0.610 0.057 0.610 C 0.057 0.609 0.058 0.608 0.059 0.608 C 0.062 0.608 0.067 0.607 0.068 0.606 C 0.068 0.605 0.069 0.605 0.069 0.605 C 0.070 0.606 0.070 0.605 0.070 0.604 C 0.070 0.603 0.071 0.602 0.072 0.602 C 0.072 0.601 0.073 0.599 0.074 0.598 C 0.074 0.596 0.075 0.595 0.077 0.595 C 0.080 0.595 0.084 0.592 0.084 0.589 C 0.084 0.589 0.084 0.588 0.084 0.589 C 0.083 0.590 0.083 0.589 0.082 0.588 C 0.082 0.587 0.081 0.587 0.081 0.588 C 0.080 0.588 0.079 0.588 0.079 0.587 C 0.079 0.586 0.079 0.584 0.078 0.584 C 0.078 0.584 0.079 0.583 0.081 0.584 C 0.083 0.584 0.085 0.585 0.085 0.586 C 0.086 0.586 0.086 0.586 0.086 0.585 C 0.086 0.584 0.088 0.583 0.089 0.583 C 0.091 0.583 0.093 0.580 0.093 0.578 C 0.093 0.578 0.087 0.577 0.080 0.577 C 0.074 0.577 0.068 0.576 0.068 0.575 C 0.067 0.574 0.055 0.575 0.054 0.577 C 0.053 0.577 0.053 0.577 0.053 0.576 C 0.053 0.575 0.051 0.574 0.050 0.576 C 0.050 0.577 0.050 0.576 0.049 0.576 C 0.048 0.575 0.047 0.574 0.046 0.575 C 0.044 0.575 0.044 0.575 0.045 0.574 C 0.045 0.572 0.045 0.572 0.043 0.573 C 0.041 0.573 0.041 0.573 0.042 0.572 C 0.043 0.570 0.043 0.566 0.043 0.567 C 0.042 0.567 0.042 0.567 0.042 0.567 C 0.041 0.566 0.043 0.565 0.045 0.564 C 0.047 0.563 0.049 0.562 0.049 0.563 C 0.050 0.564 0.050 0.564 0.051 0.563 C 0.051 0.563 0.051 0.563 0.052 0.565 C 0.052 0.566 0.052 0.566 0.053 0.565 C 0.054 0.562 0.056 0.562 0.059 0.564 C 0.061 0.565 0.061 0.565 0.061 0.563 C 0.061 0.562 0.061 0.561 0.062 0.561 C 0.062 0.561 0.062 0.562 0.062 0.563 C 0.062 0.565 0.062 0.565 0.063 0.564 C 0.064 0.563 0.070 0.561 0.081 0.560 C 0.086 0.560 0.090 0.559 0.091 0.558 C 0.091 0.557 0.093 0.557 0.095 0.556 C 0.096 0.556 0.098 0.555 0.098 0.554 C 0.099 0.552 0.091 0.545 0.088 0.545 C 0.086 0.545 0.085 0.544 0.085 0.543 C 0.085 0.542 0.085 0.541 0.084 0.542 C 0.083 0.543 0.083 0.543 0.082 0.543 C 0.079 0.542 0.075 0.543 0.075 0.544 C 0.075 0.545 0.073 0.544 0.072 0.542 C 0.072 0.541 0.072 0.542 0.072 0.542 C 0.072 0.544 0.057 0.544 0.046 0.543 C 0.043 0.542 0.042 0.543 0.042 0.544 C 0.042 0.545 0.042 0.545 0.041 0.544 C 0.041 0.543 0.039 0.542 0.034 0.541 C 0.034 0.541 0.033 0.540 0.033 0.539 C 0.033 0.539 0.033 0.538 0.032 0.537 C 0.032 0.537 0.033 0.537 0.034 0.537 C 0.035 0.538 0.036 0.537 0.036 0.535 C 0.036 0.533 0.036 0.532 0.037 0.533 C 0.038 0.534 0.038 0.533 0.039 0.532 C 0.039 0.531 0.039 0.531 0.038 0.531 C 0.038 0.531 0.037 0.530 0.037 0.529 C 0.037 0.528 0.038 0.528 0.038 0.528 C 0.040 0.528 0.040 0.530 0.039 0.533 C 0.039 0.535 0.040 0.536 0.043 0.534 C 0.044 0.534 0.043 0.531 0.042 0.531 C 0.042 0.531 0.042 0.531 0.042 0.533 C 0.042 0.534 0.042 0.534 0.042 0.534 C 0.041 0.534 0.041 0.533 0.041 0.532 C 0.041 0.531 0.041 0.530 0.041 0.529 C 0.040 0.527 0.046 0.528 0.048 0.530 C 0.048 0.530 0.049 0.530 0.049 0.529 C 0.049 0.528 0.049 0.527 0.049 0.527 C 0.048 0.528 0.047 0.527 0.047 0.525 C 0.047 0.524 0.047 0.524 0.047 0.525 C 0.046 0.525 0.046 0.525 0.046 0.524 C 0.046 0.523 0.046 0.522 0.047 0.522 C 0.047 0.522 0.048 0.521 0.048 0.520 C 0.049 0.520 0.049 0.520 0.049 0.522 C 0.049 0.523 0.049 0.524 0.049 0.523 C 0.050 0.522 0.050 0.523 0.050 0.523 C 0.051 0.524 0.051 0.525 0.051 0.525 C 0.052 0.525 0.052 0.525 0.052 0.524 C 0.051 0.522 0.051 0.520 0.052 0.522 C 0.054 0.524 0.055 0.523 0.054 0.519 C 0.054 0.518 0.054 0.518 0.055 0.519 C 0.055 0.521 0.056 0.521 0.056 0.520 C 0.056 0.519 0.056 0.519 0.057 0.521 C 0.057 0.522 0.057 0.524 0.057 0.525 C 0.057 0.526 0.057 0.527 0.057 0.527 C 0.058 0.527 0.059 0.522 0.058 0.520 C 0.058 0.519 0.059 0.519 0.060 0.519 C 0.062 0.520 0.063 0.519 0.063 0.518 C 0.063 0.516 0.063 0.516 0.063 0.518 C 0.063 0.520 0.064 0.521 0.065 0.521 L 0.068 0.520 L 0.067 0.525 C 0.066 0.529 0.066 0.529 0.067 0.528 C 0.069 0.526 0.069 0.525 0.068 0.525 C 0.068 0.525 0.068 0.525 0.068 0.523 C 0.068 0.521 0.068 0.520 0.068 0.520 C 0.068 0.519 0.069 0.519 0.070 0.519 C 0.073 0.520 0.075 0.523 0.074 0.526 C 0.074 0.527 0.074 0.527 0.075 0.525 C 0.075 0.524 0.075 0.523 0.075 0.525 C 0.075 0.527 0.075 0.527 0.076 0.525 C 0.077 0.524 0.077 0.524 0.077 0.524 C 0.076 0.523 0.076 0.523 0.076 0.521 C 0.076 0.520 0.076 0.520 0.077 0.521 C 0.078 0.522 0.080 0.520 0.079 0.518 C 0.079 0.517 0.078 0.517 0.077 0.517 C 0.076 0.518 0.076 0.518 0.077 0.516 C 0.077 0.515 0.078 0.514 0.078 0.514 C 0.079 0.514 0.080 0.512 0.079 0.507 L 0.078 0.502 L 0.079 0.501 C 0.080 0.500 0.081 0.500 0.082 0.500 C 0.083 0.501 0.083 0.500 0.083 0.498 C 0.083 0.495 0.072 0.494 0.071 0.496 C 0.070 0.499 0.066 0.498 0.065 0.494 C 0.064 0.491 0.064 0.491 0.065 0.489 C 0.065 0.488 0.065 0.487 0.064 0.488 C 0.062 0.489 0.051 0.486 0.047 0.483 C 0.045 0.481 0.047 0.479 0.050 0.477 C 0.052 0.477 0.053 0.475 0.054 0.474 C 0.054 0.473 0.054 0.473 0.054 0.475 C 0.055 0.477 0.055 0.476 0.055 0.472 C 0.055 0.471 0.056 0.471 0.057 0.472 C 0.058 0.473 0.059 0.474 0.060 0.474 C 0.063 0.473 0.076 0.471 0.077 0.471 C 0.077 0.470 0.067 0.467 0.064 0.467 C 0.062 0.467 0.061 0.467 0.060 0.466 C 0.060 0.465 0.060 0.464 0.061 0.464 C 0.061 0.464 0.061 0.464 0.061 0.463 C 0.061 0.462 0.060 0.463 0.060 0.464 C 0.059 0.466 0.054 0.468 0.053 0.465 C 0.053 0.464 0.048 0.463 0.040 0.463 C 0.034 0.462 0.028 0.461 0.027 0.460 L 0.025 0.459 L 0.027 0.459 C 0.032 0.459 0.032 0.459 0.032 0.456 C 0.032 0.454 0.031 0.453 0.031 0.454 C 0.031 0.455 0.031 0.454 0.031 0.453 C 0.031 0.453 0.035 0.452 0.039 0.452 C 0.044 0.452 0.048 0.452 0.048 0.452 C 0.048 0.451 0.051 0.451 0.054 0.451 C 0.058 0.450 0.061 0.449 0.062 0.448 C 0.063 0.447 0.070 0.445 0.077 0.444 C 0.084 0.443 0.090 0.441 0.091 0.440 C 0.091 0.439 0.092 0.439 0.092 0.440 C 0.092 0.440 0.094 0.439 0.096 0.438 C 0.099 0.436 0.101 0.436 0.101 0.436 C 0.102 0.437 0.103 0.435 0.103 0.434 C 0.105 0.430 0.105 0.430 0.104 0.429 C 0.103 0.427 0.103 0.427 0.104 0.426 C 0.105 0.425 0.105 0.425 0.103 0.425 C 0.102 0.425 0.100 0.424 0.100 0.422 C 0.100 0.421 0.100 0.421 0.100 0.422 C 0.101 0.422 0.101 0.422 0.101 0.421 C 0.101 0.420 0.101 0.419 0.102 0.419 C 0.102 0.419 0.102 0.418 0.101 0.417 C 0.100 0.414 0.100 0.414 0.103 0.412 C 0.104 0.411 0.105 0.410 0.106 0.410 C 0.107 0.410 0.107 0.410 0.106 0.408 C 0.105 0.407 0.105 0.407 0.106 0.407 C 0.106 0.407 0.106 0.405 0.106 0.404 C 0.106 0.402 0.106 0.401 0.106 0.401 C 0.107 0.401 0.107 0.400 0.107 0.399 C 0.107 0.398 0.106 0.398 0.105 0.398 C 0.104 0.398 0.104 0.397 0.104 0.396 C 0.104 0.395 0.105 0.394 0.106 0.394 C 0.108 0.394 0.108 0.391 0.106 0.389 C 0.105 0.387 0.105 0.387 0.107 0.385 L 0.109 0.383 L 0.107 0.383 C 0.106 0.383 0.106 0.382 0.105 0.381 C 0.105 0.380 0.103 0.379 0.101 0.379 C 0.099 0.379 0.097 0.378 0.097 0.377 C 0.096 0.377 0.099 0.377 0.101 0.377 C 0.104 0.377 0.106 0.377 0.106 0.376 C 0.105 0.375 0.105 0.374 0.107 0.373 C 0.109 0.372 0.115 0.370 0.117 0.370 C 0.118 0.370 0.118 0.369 0.118 0.368 C 0.118 0.367 0.119 0.367 0.119 0.368 C 0.120 0.370 0.123 0.367 0.123 0.365 C 0.123 0.364 0.123 0.364 0.122 0.364 C 0.122 0.365 0.119 0.365 0.115 0.366 C 0.112 0.366 0.109 0.367 0.109 0.368 C 0.109 0.369 0.109 0.369 0.109 0.368 C 0.109 0.367 0.109 0.365 0.109 0.364 C 0.109 0.361 0.108 0.361 0.107 0.361 C 0.106 0.362 0.105 0.361 0.105 0.360 C 0.106 0.358 0.104 0.356 0.102 0.355 C 0.102 0.354 0.098 0.354 0.094 0.354 C 0.084 0.353 0.080 0.352 0.080 0.349 C 0.080 0.347 0.079 0.347 0.079 0.349 C 0.079 0.350 0.079 0.351 0.078 0.350 C 0.075 0.348 0.075 0.346 0.077 0.345 C 0.081 0.343 0.081 0.341 0.079 0.339 C 0.078 0.337 0.076 0.336 0.076 0.336 C 0.075 0.336 0.075 0.334 0.075 0.333 C 0.074 0.332 0.073 0.331 0.073 0.331 C 0.072 0.330 0.071 0.329 0.071 0.329 C 0.071 0.328 0.072 0.328 0.073 0.328 C 0.073 0.329 0.074 0.329 0.073 0.328 C 0.073 0.327 0.072 0.325 0.071 0.325 C 0.070 0.324 0.068 0.323 0.068 0.322 C 0.067 0.321 0.066 0.319 0.065 0.319 C 0.064 0.319 0.062 0.317 0.061 0.316 C 0.061 0.314 0.059 0.313 0.059 0.312 C 0.058 0.311 0.058 0.310 0.058 0.310 C 0.058 0.309 0.058 0.308 0.057 0.306 C 0.056 0.303 0.056 0.301 0.057 0.299 C 0.059 0.297 0.059 0.297 0.058 0.297 C 0.057 0.297 0.057 0.296 0.057 0.294 C 0.058 0.292 0.060 0.290 0.063 0.289 C 0.064 0.288 0.063 0.284 0.061 0.284 C 0.060 0.283 0.059 0.280 0.060 0.278 C 0.060 0.278 0.061 0.278 0.061 0.278 C 0.061 0.279 0.062 0.280 0.063 0.280 C 0.064 0.280 0.065 0.280 0.065 0.278 C 0.064 0.277 0.064 0.275 0.064 0.274 C 0.063 0.274 0.064 0.274 0.064 0.274 C 0.066 0.275 0.066 0.275 0.066 0.273 C 0.066 0.272 0.065 0.272 0.064 0.271 C 0.062 0.271 0.062 0.271 0.063 0.269 C 0.066 0.266 0.065 0.264 0.056 0.262 C 0.052 0.261 0.051 0.259 0.051 0.257 C 0.051 0.257 0.057 0.256 0.064 0.256 C 0.077 0.255 0.081 0.254 0.081 0.252 C 0.081 0.250 0.075 0.247 0.074 0.249 C 0.074 0.250 0.073 0.249 0.073 0.248 C 0.072 0.247 0.070 0.246 0.069 0.246 C 0.067 0.246 0.066 0.246 0.067 0.245 C 0.067 0.243 0.067 0.243 0.066 0.243 C 0.064 0.243 0.064 0.243 0.064 0.245 C 0.065 0.246 0.065 0.246 0.064 0.245 C 0.063 0.245 0.062 0.244 0.061 0.244 C 0.060 0.245 0.060 0.244 0.060 0.243 C 0.060 0.241 0.061 0.239 0.062 0.240 C 0.062 0.240 0.063 0.240 0.065 0.239 L 0.067 0.238 L 0.065 0.238 C 0.064 0.237 0.063 0.237 0.064 0.236 C 0.065 0.235 0.063 0.230 0.062 0.231 C 0.062 0.231 0.061 0.230 0.061 0.229 C 0.061 0.228 0.062 0.227 0.062 0.227 C 0.063 0.227 0.064 0.226 0.064 0.226 C 0.065 0.225 0.067 0.225 0.068 0.225 C 0.072 0.224 0.071 0.224 0.066 0.222 C 0.060 0.220 0.053 0.218 0.052 0.218 C 0.051 0.218 0.051 0.217 0.051 0.216 C 0.051 0.215 0.053 0.215 0.054 0.215 C 0.055 0.215 0.056 0.215 0.056 0.214 C 0.057 0.214 0.057 0.213 0.058 0.213 C 0.062 0.211 0.062 0.209 0.057 0.207 C 0.052 0.204 0.053 0.202 0.058 0.201 L 0.060 0.201 L 0.058 0.200 C 0.057 0.199 0.056 0.198 0.056 0.197 C 0.056 0.195 0.055 0.194 0.054 0.193 C 0.053 0.193 0.053 0.193 0.054 0.194 C 0.054 0.195 0.054 0.196 0.054 0.196 C 0.053 0.196 0.053 0.195 0.052 0.193 C 0.052 0.192 0.050 0.190 0.049 0.190 C 0.048 0.189 0.046 0.188 0.046 0.187 C 0.046 0.187 0.045 0.186 0.045 0.186 C 0.044 0.185 0.043 0.184 0.043 0.183 C 0.042 0.180 0.045 0.178 0.050 0.177 C 0.052 0.176 0.055 0.175 0.056 0.174 C 0.057 0.173 0.058 0.173 0.058 0.173 C 0.059 0.174 0.060 0.174 0.061 0.173 C 0.066 0.169 0.085 0.166 0.096 0.166 C 0.104 0.167 0.105 0.166 0.105 0.163 C 0.105 0.161 0.105 0.160 0.106 0.160 C 0.106 0.160 0.106 0.161 0.106 0.163 C 0.106 0.165 0.107 0.165 0.111 0.164 C 0.114 0.164 0.117 0.163 0.117 0.162 C 0.117 0.161 0.120 0.161 0.122 0.160 C 0.125 0.160 0.130 0.159 0.133 0.158 C 0.136 0.157 0.139 0.157 0.140 0.157 C 0.141 0.158 0.142 0.157 0.142 0.156 C 0.143 0.154 0.146 0.153 0.147 0.155 C 0.148 0.156 0.149 0.155 0.149 0.154 C 0.150 0.152 0.151 0.151 0.151 0.151 C 0.152 0.151 0.153 0.150 0.153 0.149 C 0.154 0.148 0.155 0.147 0.156 0.149 C 0.157 0.151 0.161 0.148 0.162 0.144 C 0.163 0.141 0.167 0.139 0.167 0.142 C 0.167 0.145 0.168 0.144 0.169 0.140 C 0.169 0.138 0.169 0.137 0.170 0.138 C 0.170 0.138 0.170 0.138 0.170 0.137 C 0.170 0.136 0.172 0.134 0.173 0.132 C 0.174 0.130 0.176 0.128 0.176 0.127 C 0.176 0.127 0.176 0.126 0.176 0.126 C 0.177 0.126 0.177 0.125 0.177 0.123 C 0.178 0.122 0.179 0.121 0.182 0.120 C 0.184 0.120 0.186 0.119 0.186 0.117 C 0.186 0.116 0.187 0.115 0.188 0.114 C 0.189 0.113 0.191 0.115 0.194 0.122 C 0.194 0.124 0.195 0.126 0.196 0.127 C 0.196 0.128 0.197 0.130 0.198 0.133 C 0.199 0.137 0.200 0.137 0.204 0.138 C 0.208 0.138 0.209 0.137 0.209 0.136 C 0.209 0.132 0.212 0.133 0.212 0.136 C 0.213 0.139 0.213 0.139 0.213 0.135 C 0.213 0.132 0.213 0.131 0.214 0.132 C 0.214 0.133 0.215 0.132 0.215 0.131 C 0.215 0.128 0.223 0.128 0.224 0.131 C 0.224 0.133 0.225 0.133 0.225 0.131 C 0.226 0.130 0.227 0.129 0.228 0.130 C 0.228 0.130 0.229 0.129 0.230 0.128 C 0.231 0.127 0.232 0.126 0.232 0.127 C 0.232 0.127 0.232 0.126 0.233 0.125 C 0.233 0.123 0.234 0.123 0.235 0.123 C 0.235 0.124 0.236 0.124 0.237 0.122 C 0.237 0.121 0.238 0.121 0.240 0.121 C 0.243 0.122 0.244 0.122 0.245 0.120 C 0.245 0.118 0.246 0.117 0.247 0.117 C 0.248 0.119 0.251 0.115 0.251 0.113 C 0.251 0.112 0.251 0.112 0.251 0.112 C 0.251 0.112 0.251 0.112 0.252 0.113 C 0.252 0.116 0.257 0.119 0.258 0.116 C 0.258 0.116 0.259 0.117 0.259 0.119 C 0.260 0.121 0.261 0.122 0.261 0.122 C 0.261 0.121 0.261 0.121 0.261 0.121 C 0.260 0.121 0.260 0.120 0.260 0.119 C 0.261 0.118 0.261 0.117 0.261 0.118 C 0.261 0.118 0.262 0.118 0.262 0.116 C 0.262 0.115 0.263 0.113 0.264 0.113 C 0.265 0.111 0.269 0.113 0.269 0.115 C 0.268 0.117 0.269 0.118 0.271 0.117 C 0.271 0.117 0.272 0.118 0.272 0.119 C 0.272 0.122 0.273 0.121 0.274 0.117 C 0.274 0.114 0.274 0.113 0.273 0.112 C 0.273 0.110 0.273 0.110 0.274 0.111 C 0.275 0.112 0.276 0.111 0.276 0.109 C 0.276 0.105 0.276 0.104 0.277 0.106 C 0.278 0.108 0.278 0.108 0.279 0.105 C 0.280 0.103 0.280 0.102 0.281 0.103 C 0.283 0.104 0.283 0.104 0.283 0.101 C 0.283 0.096 0.283 0.096 0.284 0.101 C 0.285 0.105 0.286 0.104 0.286 0.099 C 0.286 0.098 0.286 0.094 0.286 0.091 C 0.287 0.086 0.287 0.085 0.289 0.084 C 0.290 0.083 0.291 0.083 0.291 0.084 C 0.291 0.085 0.292 0.086 0.292 0.086 C 0.293 0.086 0.293 0.088 0.293 0.089 C 0.293 0.091 0.294 0.092 0.294 0.092 C 0.294 0.092 0.294 0.091 0.294 0.089 C 0.294 0.087 0.294 0.086 0.295 0.086 C 0.295 0.086 0.295 0.085 0.295 0.084 C 0.295 0.083 0.295 0.082 0.296 0.083 C 0.296 0.084 0.297 0.083 0.298 0.080 C 0.298 0.076 0.299 0.075 0.300 0.076 C 0.301 0.077 0.301 0.077 0.301 0.073 C 0.301 0.069 0.301 0.068 0.302 0.068 C 0.303 0.068 0.303 0.069 0.303 0.070 C 0.304 0.073 0.305 0.072 0.305 0.069 C 0.305 0.068 0.306 0.067 0.306 0.066 C 0.307 0.066 0.308 0.064 0.308 0.062 C 0.309 0.060 0.309 0.057 0.310 0.057 C 0.311 0.056 0.311 0.055 0.311 0.052 C 0.311 0.050 0.311 0.047 0.311 0.044 C 0.311 0.041 0.312 0.040 0.313 0.040 C 0.314 0.040 0.314 0.040 0.314 0.041 C 0.314 0.042 0.314 0.043 0.315 0.043 C 0.316 0.043 0.316 0.042 0.316 0.040 C 0.316 0.037 0.317 0.036 0.318 0.036 C 0.319 0.036 0.320 0.037 0.320 0.038 C 0.322 0.041 0.324 0.041 0.325 0.037 C 0.326 0.036 0.327 0.034 0.327 0.033 C 0.328 0.033 0.329 0.031 0.328 0.030 C 0.328 0.028 0.330 0.026 0.330 0.029 C 0.330 0.030 0.331 0.031 0.332 0.031 C 0.333 0.031 0.333 0.032 0.334 0.033 C 0.334 0.035 0.335 0.036 0.335 0.036 C 0.335 0.036 0.335 0.035 0.335 0.035 C 0.334 0.034 0.335 0.031 0.336 0.031 C 0.336 0.031 0.337 0.029 0.337 0.026 C 0.338 0.022 0.338 0.022 0.339 0.023 C 0.341 0.023 0.341 0.023 0.340 0.022 C 0.339 0.020 0.339 0.020 0.340 0.021 C 0.341 0.021 0.342 0.023 0.342 0.024 C 0.342 0.026 0.342 0.026 0.342 0.024 C 0.342 0.023 0.343 0.022 0.343 0.022 C 0.344 0.022 0.344 0.021 0.344 0.020 C 0.345 0.019 0.345 0.018 0.345 0.018 C 0.346 0.018 0.345 0.019 0.345 0.020 C 0.344 0.023 0.344 0.023 0.345 0.026 C 0.345 0.028 0.346 0.029 0.346 0.026 C 0.346 0.025 0.346 0.023 0.346 0.022 C 0.347 0.020 0.347 0.020 0.348 0.023 C 0.348 0.026 0.349 0.025 0.349 0.021 C 0.349 0.019 0.349 0.018 0.348 0.018 C 0.348 0.018 0.348 0.017 0.348 0.017 C 0.349 0.015 0.352 0.022 0.351 0.025 C 0.351 0.026 0.351 0.027 0.352 0.027 C 0.353 0.027 0.353 0.026 0.353 0.023 C 0.352 0.016 0.353 0.010 0.354 0.008 C 0.355 0.006 0.356 0.007 0.357 0.011 C 0.357 0.014 0.357 0.014 0.357 0.013 C 0.358 0.011 0.358 0.011 0.359 0.014 C 0.360 0.019 0.362 0.020 0.363 0.017 C 0.363 0.014 0.365 0.014 0.365 0.016 C 0.365 0.018 0.365 0.018 0.365 0.017 C 0.366 0.014 0.368 0.013 0.369 0.014 C 0.370 0.015 0.370 0.015 0.370 0.014 C 0.370 0.013 0.371 0.013 0.371 0.013 C 0.371 0.013 0.372 0.013 0.372 0.014 C 0.371 0.016 0.374 0.014 0.374 0.012 C 0.374 0.011 0.375 0.011 0.376 0.012 C 0.377 0.013 0.378 0.013 0.379 0.013 C 0.379 0.013 0.379 0.013 0.379 0.014 C 0.379 0.015 0.380 0.016 0.381 0.016 C 0.383 0.016 0.383 0.017 0.382 0.018 C 0.381 0.019 0.381 0.020 0.382 0.020 C 0.384 0.021 0.384 0.021 0.384 0.018 C 0.384 0.017 0.384 0.015 0.385 0.014 C 0.386 0.013 0.386 0.013 0.386 0.014 C 0.386 0.015 0.387 0.014 0.387 0.012 C 0.388 0.008 0.391 0.009 0.391 0.013 C 0.392 0.015 0.392 0.015 0.392 0.013 C 0.393 0.011 0.393 0.012 0.393 0.015 C 0.394 0.018 0.394 0.021 0.394 0.022 C 0.394 0.024 0.395 0.025 0.396 0.025 C 0.397 0.025 0.397 0.025 0.397 0.021 C 0.397 0.017 0.397 0.016 0.398 0.016 C 0.398 0.016 0.399 0.015 0.399 0.013 C 0.398 0.011 0.399 0.011 0.400 0.011 C 0.400 0.011 0.401 0.012 0.401 0.013 C 0.401 0.014 0.401 0.014 0.401 0.014 C 0.401 0.014 0.401 0.015 0.401 0.016 C 0.401 0.018 0.402 0.019 0.403 0.018 C 0.404 0.018 0.404 0.019 0.405 0.020 C 0.405 0.022 0.406 0.021 0.405 0.019 C 0.405 0.016 0.406 0.015 0.406 0.015 C 0.407 0.015 0.407 0.016 0.407 0.018 C 0.407 0.020 0.407 0.020 0.408 0.017 C 0.408 0.016 0.409 0.014 0.409 0.014 C 0.410 0.014 0.410 0.013 0.411 0.012 C 0.412 0.010 0.413 0.009 0.413 0.010 C 0.413 0.011 0.414 0.009 0.414 0.006 C 0.414 0.001 0.416 -0.000 0.415 0.005 C 0.415 0.009 0.417 0.011 0.418 0.008 C 0.419 0.005 0.419 0.005 0.419 0.007 C 0.419 0.009 0.419 0.010 0.420 0.010 C 0.421 0.011 0.422 0.016 0.422 0.019 C 0.421 0.021 0.422 0.022 0.423 0.021 C 0.423 0.021 0.425 0.022 0.426 0.024 C 0.427 0.026 0.428 0.027 0.428 0.027 C 0.429 0.027 0.429 0.029 0.429 0.032 C 0.429 0.039 0.430 0.036 0.430 0.028 C 0.430 0.021 0.430 0.019 0.432 0.017 C 0.433 0.016 0.434 0.017 0.434 0.021 C 0.436 0.025 0.436 0.025 0.436 0.023 C 0.436 0.021 0.437 0.020 0.437 0.020 C 0.437 0.020 0.438 0.019 0.438 0.018 C 0.438 0.017 0.438 0.016 0.439 0.015 C 0.440 0.015 0.440 0.015 0.441 0.018 C 0.441 0.021 0.442 0.022 0.442 0.021 C 0.442 0.018 0.444 0.018 0.444 0.020 C 0.444 0.021 0.445 0.022 0.445 0.022 C 0.446 0.022 0.447 0.023 0.447 0.026 C 0.448 0.028 0.449 0.029 0.448 0.027 C 0.448 0.026 0.448 0.025 0.449 0.025 C 0.449 0.025 0.449 0.024 0.449 0.024 C 0.448 0.021 0.450 0.017 0.450 0.019 C 0.451 0.019 0.451 0.019 0.452 0.018 C 0.452 0.017 0.452 0.016 0.452 0.016 C 0.452 0.016 0.456 0.000 0.456 0.000 C 0.457 0.000 0.457 0.002 0.458 0.005 C 0.459 0.010 0.459 0.011 0.460 0.008 C 0.460 0.005 0.460 0.005 0.461 0.008 C 0.461 0.010 0.462 0.013 0.462 0.013 C 0.463 0.014 0.462 0.014 0.462 0.014 C 0.461 0.013 0.461 0.016 0.462 0.018 C 0.463 0.019 0.463 0.021 0.463 0.024 C 0.463 0.027 0.463 0.027 0.463 0.026 C 0.464 0.026 0.465 0.024 0.466 0.023 C 0.467 0.021 0.469 0.014 0.468 0.014 C 0.468 0.014 0.468 0.014 0.468 0.013 C 0.468 0.010 0.469 0.010 0.469 0.013 C 0.469 0.015 0.469 0.017 0.470 0.018 C 0.470 0.019 0.471 0.022 0.471 0.025 C 0.471 0.029 0.471 0.030 0.472 0.031 C 0.473 0.032 0.474 0.033 0.473 0.034 C 0.473 0.036 0.473 0.036 0.474 0.035 C 0.474 0.035 0.474 0.033 0.474 0.033 C 0.474 0.032 0.474 0.030 0.475 0.029 C 0.476 0.026 0.476 0.023 0.475 0.023 C 0.474 0.023 0.474 0.023 0.475 0.021 C 0.475 0.019 0.476 0.018 0.476 0.018 C 0.476 0.018 0.476 0.017 0.476 0.016 C 0.476 0.013 0.479 0.011 0.480 0.013 C 0.480 0.014 0.480 0.016 0.480 0.016 C 0.480 0.017 0.480 0.018 0.481 0.019 C 0.481 0.020 0.481 0.021 0.481 0.022 C 0.481 0.023 0.481 0.023 0.482 0.023 C 0.482 0.023 0.482 0.025 0.483 0.027 C 0.483 0.029 0.483 0.031 0.484 0.031 C 0.484 0.031 0.484 0.030 0.484 0.029 C 0.483 0.027 0.483 0.027 0.484 0.025 C 0.484 0.024 0.485 0.022 0.484 0.021 C 0.484 0.020 0.484 0.020 0.485 0.021 C 0.485 0.021 0.485 0.021 0.486 0.020 C 0.486 0.018 0.487 0.018 0.488 0.019 C 0.489 0.020 0.489 0.019 0.489 0.017 C 0.488 0.015 0.489 0.015 0.489 0.016 C 0.489 0.016 0.490 0.017 0.491 0.017 C 0.492 0.017 0.492 0.018 0.492 0.020 C 0.492 0.022 0.492 0.022 0.493 0.020 C 0.493 0.018 0.493 0.018 0.494 0.020 C 0.494 0.022 0.494 0.022 0.494 0.020 C 0.494 0.019 0.495 0.018 0.495 0.018 C 0.496 0.018 0.496 0.018 0.495 0.020 C 0.495 0.020 0.495 0.022 0.495 0.023 C 0.495 0.025 0.497 0.023 0.499 0.019 C 0.500 0.017 0.501 0.019 0.501 0.023 C 0.501 0.024 0.501 0.025 0.502 0.025 C 0.502 0.025 0.504 0.034 0.503 0.036 C 0.503 0.037 0.503 0.037 0.504 0.037 C 0.505 0.036 0.505 0.036 0.505 0.037 C 0.505 0.038 0.505 0.040 0.505 0.040 C 0.505 0.041 0.506 0.040 0.506 0.037 C 0.507 0.034 0.507 0.033 0.509 0.033 C 0.511 0.032 0.511 0.033 0.512 0.037 C 0.513 0.040 0.513 0.043 0.513 0.044 C 0.513 0.046 0.513 0.047 0.514 0.047 C 0.515 0.047 0.515 0.048 0.515 0.049 C 0.515 0.052 0.516 0.050 0.516 0.047 C 0.517 0.044 0.517 0.043 0.518 0.043 C 0.518 0.043 0.519 0.042 0.519 0.042 C 0.520 0.038 0.522 0.037 0.522 0.040 C 0.522 0.041 0.522 0.043 0.522 0.045 C 0.523 0.046 0.523 0.046 0.523 0.044 C 0.524 0.039 0.525 0.042 0.525 0.049 C 0.525 0.052 0.525 0.055 0.526 0.055 C 0.526 0.056 0.526 0.055 0.526 0.054 C 0.526 0.053 0.527 0.053 0.527 0.054 C 0.528 0.055 0.530 0.053 0.531 0.049 C 0.531 0.046 0.532 0.046 0.532 0.049 C 0.532 0.052 0.534 0.056 0.534 0.054 C 0.535 0.054 0.535 0.053 0.535 0.051 C 0.534 0.049 0.535 0.049 0.536 0.049 C 0.536 0.049 0.537 0.049 0.536 0.050 C 0.536 0.051 0.536 0.054 0.537 0.054 C 0.537 0.054 0.537 0.055 0.537 0.057 C 0.538 0.058 0.538 0.059 0.538 0.059 C 0.539 0.059 0.539 0.061 0.539 0.063 C 0.539 0.065 0.539 0.065 0.540 0.063 C 0.540 0.061 0.541 0.059 0.541 0.059 C 0.541 0.059 0.541 0.058 0.541 0.057 C 0.541 0.054 0.541 0.054 0.542 0.055 C 0.543 0.056 0.543 0.057 0.543 0.059 C 0.543 0.060 0.543 0.061 0.543 0.061 C 0.544 0.061 0.545 0.066 0.545 0.068 C 0.544 0.068 0.544 0.069 0.545 0.071 C 0.545 0.072 0.546 0.071 0.546 0.069 C 0.547 0.066 0.548 0.067 0.547 0.071 C 0.547 0.072 0.547 0.072 0.548 0.071 C 0.548 0.071 0.549 0.070 0.549 0.069 C 0.550 0.068 0.550 0.069 0.550 0.071 C 0.550 0.074 0.550 0.075 0.552 0.075 C 0.554 0.076 0.554 0.075 0.554 0.074 C 0.554 0.073 0.554 0.072 0.554 0.072 C 0.554 0.072 0.555 0.071 0.554 0.070 C 0.554 0.069 0.555 0.069 0.556 0.069 C 0.558 0.071 0.558 0.072 0.557 0.074 C 0.557 0.076 0.557 0.076 0.558 0.074 C 0.559 0.073 0.560 0.073 0.560 0.074 C 0.560 0.075 0.560 0.075 0.561 0.075 C 0.561 0.074 0.562 0.075 0.562 0.076 C 0.562 0.077 0.563 0.078 0.565 0.078 C 0.566 0.078 0.567 0.079 0.568 0.081 C 0.568 0.083 0.569 0.084 0.569 0.083 C 0.570 0.083 0.570 0.083 0.570 0.084 C 0.570 0.087 0.571 0.086 0.574 0.082 C 0.574 0.080 0.576 0.079 0.577 0.078 C 0.579 0.078 0.580 0.076 0.580 0.075 C 0.580 0.074 0.580 0.074 0.581 0.074 C 0.581 0.075 0.581 0.075 0.581 0.074 C 0.582 0.071 0.583 0.076 0.583 0.079 C 0.583 0.080 0.583 0.081 0.584 0.081 C 0.584 0.081 0.584 0.082 0.584 0.085 C 0.584 0.087 0.584 0.088 0.585 0.088 C 0.586 0.088 0.586 0.087 0.586 0.086 C 0.586 0.085 0.587 0.085 0.588 0.085 C 0.589 0.085 0.589 0.085 0.588 0.086 C 0.588 0.086 0.587 0.087 0.587 0.088 C 0.587 0.089 0.588 0.089 0.590 0.088 C 0.591 0.088 0.591 0.087 0.591 0.086 C 0.591 0.085 0.591 0.085 0.591 0.086 C 0.590 0.086 0.590 0.086 0.590 0.084 C 0.591 0.083 0.591 0.082 0.591 0.082 C 0.592 0.083 0.592 0.082 0.592 0.081 C 0.593 0.079 0.599 0.079 0.598 0.081 C 0.598 0.082 0.598 0.083 0.599 0.083 C 0.599 0.083 0.599 0.084 0.599 0.085 C 0.599 0.087 0.600 0.087 0.600 0.084 C 0.601 0.083 0.601 0.083 0.601 0.083 C 0.601 0.084 0.601 0.085 0.601 0.086 C 0.600 0.088 0.600 0.088 0.601 0.088 C 0.601 0.088 0.602 0.089 0.602 0.090 C 0.602 0.091 0.602 0.091 0.603 0.090 C 0.604 0.089 0.605 0.088 0.605 0.089 C 0.606 0.090 0.606 0.089 0.606 0.088 C 0.606 0.086 0.608 0.085 0.609 0.087 C 0.609 0.088 0.610 0.088 0.611 0.088 C 0.612 0.087 0.614 0.093 0.613 0.095 C 0.613 0.096 0.613 0.096 0.614 0.097 C 0.615 0.097 0.615 0.097 0.614 0.096 C 0.614 0.095 0.614 0.094 0.615 0.093 C 0.617 0.092 0.618 0.092 0.618 0.093 C 0.618 0.093 0.618 0.092 0.618 0.090 C 0.619 0.085 0.620 0.085 0.622 0.090 C 0.623 0.093 0.626 0.096 0.626 0.094 C 0.626 0.093 0.627 0.091 0.627 0.090 C 0.629 0.087 0.629 0.087 0.629 0.090 C 0.630 0.094 0.632 0.095 0.632 0.091 C 0.633 0.090 0.633 0.090 0.633 0.092 C 0.633 0.093 0.633 0.094 0.634 0.092 C 0.634 0.090 0.634 0.090 0.634 0.092 C 0.634 0.096 0.636 0.101 0.636 0.099 C 0.637 0.097 0.638 0.099 0.638 0.101 C 0.638 0.103 0.638 0.103 0.640 0.103 C 0.641 0.103 0.642 0.103 0.642 0.105 C 0.642 0.106 0.642 0.106 0.642 0.105 C 0.643 0.103 0.643 0.102 0.644 0.103 C 0.644 0.104 0.644 0.103 0.645 0.101 C 0.645 0.099 0.645 0.097 0.645 0.097 C 0.646 0.097 0.646 0.096 0.646 0.095 C 0.646 0.094 0.646 0.095 0.647 0.098 C 0.647 0.102 0.648 0.103 0.650 0.102 C 0.652 0.101 0.653 0.100 0.654 0.097 C 0.655 0.092 0.656 0.091 0.657 0.094 C 0.658 0.096 0.658 0.097 0.659 0.097 C 0.660 0.097 0.660 0.098 0.660 0.099 C 0.660 0.100 0.660 0.101 0.660 0.102 C 0.661 0.103 0.663 0.100 0.666 0.094 C 0.666 0.093 0.667 0.093 0.668 0.093 C 0.668 0.094 0.669 0.094 0.669 0.094 C 0.670 0.093 0.672 0.100 0.671 0.104 C 0.671 0.105 0.671 0.106 0.672 0.106 C 0.672 0.106 0.673 0.107 0.673 0.108 C 0.673 0.110 0.675 0.106 0.676 0.103 C 0.677 0.101 0.678 0.100 0.679 0.101 C 0.679 0.101 0.679 0.102 0.679 0.104 C 0.679 0.106 0.679 0.106 0.680 0.105 C 0.681 0.104 0.681 0.106 0.682 0.110 C 0.683 0.113 0.684 0.115 0.683 0.115 C 0.683 0.115 0.683 0.116 0.684 0.117 C 0.685 0.118 0.685 0.118 0.685 0.117 C 0.685 0.116 0.686 0.116 0.686 0.116 C 0.687 0.118 0.687 0.114 0.687 0.108 C 0.687 0.103 0.688 0.102 0.689 0.104 C 0.692 0.110 0.693 0.110 0.693 0.109 C 0.693 0.108 0.694 0.109 0.694 0.110 C 0.694 0.112 0.694 0.111 0.694 0.109 C 0.695 0.108 0.695 0.106 0.695 0.106 C 0.696 0.106 0.697 0.104 0.697 0.102 C 0.698 0.099 0.699 0.097 0.700 0.097 C 0.701 0.098 0.701 0.098 0.700 0.100 C 0.700 0.102 0.700 0.102 0.701 0.100 C 0.703 0.099 0.703 0.099 0.704 0.102 C 0.704 0.106 0.707 0.108 0.706 0.104 C 0.706 0.102 0.706 0.102 0.707 0.104 C 0.707 0.105 0.708 0.106 0.708 0.106 C 0.709 0.105 0.709 0.105 0.709 0.106 C 0.709 0.108 0.712 0.107 0.714 0.105 C 0.715 0.104 0.715 0.104 0.715 0.106 C 0.714 0.107 0.714 0.108 0.715 0.108 C 0.715 0.108 0.715 0.107 0.715 0.106 C 0.715 0.103 0.718 0.104 0.719 0.107 C 0.719 0.109 0.719 0.109 0.720 0.108 C 0.721 0.107 0.721 0.107 0.721 0.108 C 0.721 0.111 0.722 0.110 0.723 0.106 C 0.724 0.102 0.725 0.101 0.725 0.105 C 0.725 0.107 0.727 0.105 0.728 0.102 C 0.729 0.099 0.729 0.099 0.728 0.099 C 0.728 0.099 0.729 0.097 0.730 0.095 C 0.732 0.092 0.733 0.092 0.732 0.096 C 0.732 0.099 0.732 0.099 0.733 0.098 C 0.734 0.097 0.734 0.097 0.734 0.098 C 0.734 0.100 0.735 0.101 0.735 0.101 C 0.736 0.101 0.736 0.100 0.736 0.099 C 0.735 0.098 0.735 0.097 0.736 0.097 C 0.736 0.097 0.736 0.096 0.736 0.094 C 0.737 0.091 0.737 0.090 0.738 0.090 C 0.739 0.091 0.740 0.091 0.740 0.092 C 0.740 0.093 0.740 0.094 0.740 0.094 C 0.741 0.094 0.741 0.094 0.740 0.096 C 0.740 0.097 0.741 0.097 0.741 0.095 C 0.742 0.092 0.743 0.092 0.744 0.095 C 0.745 0.097 0.746 0.098 0.746 0.097 C 0.746 0.096 0.747 0.095 0.747 0.095 C 0.748 0.095 0.748 0.094 0.747 0.093 C 0.745 0.092 0.745 0.092 0.747 0.093 C 0.750 0.094 0.751 0.094 0.751 0.092 C 0.752 0.089 0.756 0.090 0.757 0.092 C 0.759 0.095 0.764 0.096 0.764 0.093 C 0.764 0.092 0.765 0.092 0.766 0.094 C 0.766 0.095 0.768 0.096 0.770 0.096 C 0.773 0.097 0.774 0.096 0.775 0.093 C 0.775 0.091 0.776 0.090 0.777 0.091 C 0.780 0.093 0.780 0.094 0.779 0.095 C 0.778 0.096 0.778 0.097 0.779 0.098 C 0.780 0.098 0.780 0.098 0.780 0.097 C 0.780 0.095 0.783 0.091 0.784 0.093 C 0.785 0.094 0.785 0.094 0.784 0.095 C 0.783 0.097 0.784 0.098 0.785 0.099 C 0.786 0.100 0.786 0.100 0.786 0.100 C 0.786 0.099 0.786 0.098 0.786 0.096 C 0.787 0.093 0.791 0.091 0.790 0.093 C 0.790 0.094 0.791 0.095 0.791 0.096 C 0.792 0.098 0.793 0.097 0.792 0.095 C 0.791 0.094 0.791 0.094 0.792 0.094 C 0.792 0.094 0.793 0.094 0.793 0.095 C 0.794 0.097 0.794 0.097 0.794 0.095 C 0.794 0.094 0.795 0.094 0.796 0.094 C 0.797 0.095 0.798 0.095 0.798 0.094 C 0.797 0.093 0.797 0.092 0.798 0.091 C 0.799 0.091 0.799 0.090 0.799 0.091 C 0.799 0.091 0.799 0.092 0.799 0.092 C 0.799 0.092 0.799 0.093 0.799 0.094 C 0.800 0.098 0.803 0.096 0.803 0.091 C 0.803 0.089 0.803 0.087 0.804 0.087 C 0.804 0.086 0.804 0.087 0.804 0.088 C 0.804 0.090 0.804 0.090 0.805 0.089 C 0.806 0.089 0.806 0.089 0.806 0.090 C 0.806 0.091 0.807 0.092 0.807 0.092 C 0.808 0.092 0.808 0.094 0.807 0.097 C 0.807 0.098 0.807 0.099 0.807 0.099 C 0.808 0.099 0.808 0.098 0.808 0.097 C 0.808 0.094 0.816 0.091 0.817 0.094 C 0.817 0.095 0.817 0.095 0.818 0.094 C 0.818 0.094 0.819 0.094 0.820 0.096 L 0.822 0.100 L 0.820 0.092 L 0.821 0.093 C 0.822 0.094 0.823 0.093 0.822 0.092 C 0.822 0.091 0.823 0.090 0.823 0.090 C 0.824 0.090 0.824 0.091 0.824 0.092 C 0.824 0.095 0.826 0.094 0.827 0.091 C 0.828 0.087 0.828 0.087 0.828 0.091 C 0.828 0.094 0.829 0.096 0.830 0.094 C 0.830 0.094 0.830 0.094 0.830 0.096 C 0.830 0.097 0.831 0.099 0.831 0.101 C 0.832 0.105 0.832 0.105 0.832 0.101 C 0.832 0.099 0.832 0.099 0.833 0.101 C 0.833 0.103 0.833 0.103 0.834 0.101 C 0.834 0.099 0.834 0.099 0.834 0.101 C 0.834 0.105 0.833 0.105 0.838 0.101 C 0.840 0.101 0.840 0.101 0.839 0.103 C 0.839 0.104 0.839 0.104 0.840 0.103 C 0.841 0.103 0.842 0.102 0.842 0.102 C 0.843 0.102 0.843 0.102 0.843 0.100 C 0.843 0.098 0.843 0.097 0.843 0.097 C 0.844 0.097 0.844 0.098 0.844 0.100 C 0.844 0.102 0.844 0.103 0.845 0.103 C 0.845 0.103 0.845 0.103 0.845 0.104 C 0.844 0.104 0.844 0.105 0.844 0.106 C 0.844 0.108 0.847 0.106 0.847 0.104 C 0.848 0.103 0.848 0.103 0.849 0.103 C 0.849 0.104 0.849 0.104 0.849 0.102 C 0.849 0.100 0.849 0.099 0.849 0.099 C 0.849 0.099 0.850 0.098 0.851 0.098 C 0.851 0.098 0.852 0.098 0.852 0.099 C 0.852 0.100 0.852 0.101 0.851 0.101 C 0.851 0.101 0.851 0.101 0.851 0.103 C 0.851 0.104 0.852 0.104 0.854 0.103 C 0.857 0.102 0.857 0.102 0.856 0.101 L 0.854 0.100 L 0.856 0.098 C 0.856 0.097 0.857 0.097 0.857 0.098 C 0.857 0.098 0.858 0.098 0.858 0.097 C 0.859 0.095 0.860 0.097 0.860 0.099 C 0.860 0.100 0.860 0.101 0.860 0.101 C 0.861 0.101 0.861 0.096 0.860 0.095 C 0.860 0.094 0.860 0.094 0.861 0.094 C 0.862 0.095 0.862 0.096 0.863 0.097 C 0.863 0.098 0.863 0.099 0.864 0.099 C 0.864 0.099 0.865 0.100 0.865 0.100 C 0.864 0.101 0.865 0.103 0.867 0.103 C 0.868 0.104 0.869 0.105 0.869 0.106 C 0.868 0.107 0.869 0.108 0.869 0.109 C 0.869 0.109 0.869 0.109 0.869 0.108 C 0.869 0.106 0.870 0.105 0.871 0.105 C 0.873 0.104 0.873 0.104 0.872 0.102 C 0.871 0.101 0.871 0.101 0.873 0.101 C 0.873 0.101 0.874 0.102 0.874 0.103 C 0.875 0.106 0.877 0.107 0.877 0.105 C 0.877 0.104 0.879 0.103 0.882 0.104 C 0.885 0.104 0.887 0.104 0.887 0.103 C 0.887 0.102 0.887 0.102 0.888 0.102 C 0.889 0.103 0.891 0.103 0.891 0.101 C 0.892 0.100 0.892 0.099 0.892 0.099 C 0.892 0.098 0.892 0.097 0.892 0.095 C 0.892 0.093 0.893 0.093 0.896 0.093 C 0.899 0.092 0.901 0.094 0.901 0.099 C 0.901 0.101 0.901 0.103 0.902 0.104 C 0.903 0.106 0.903 0.107 0.902 0.108 C 0.902 0.109 0.902 0.110 0.904 0.110 C 0.905 0.111 0.906 0.110 0.907 0.106 C 0.908 0.101 0.910 0.098 0.910 0.101 C 0.910 0.101 0.910 0.103 0.911 0.103 C 0.911 0.104 0.912 0.105 0.912 0.107 C 0.912 0.108 0.912 0.110 0.913 0.111 C 0.913 0.111 0.914 0.113 0.914 0.114 C 0.913 0.116 0.917 0.119 0.918 0.118 C 0.918 0.117 0.919 0.118 0.919 0.120 C 0.920 0.122 0.920 0.122 0.921 0.122 C 0.922 0.121 0.923 0.121 0.923 0.122 C 0.923 0.124 0.925 0.123 0.928 0.121 C 0.930 0.120 0.931 0.120 0.931 0.120 C 0.932 0.121 0.934 0.123 0.936 0.124 C 0.938 0.125 0.940 0.127 0.941 0.129 C 0.942 0.131 0.943 0.131 0.944 0.131 C 0.945 0.130 0.945 0.130 0.945 0.131 C 0.945 0.132 0.945 0.133 0.945 0.133 C 0.946 0.133 0.945 0.134 0.945 0.135 C 0.944 0.136 0.944 0.136 0.946 0.137 C 0.947 0.137 0.948 0.138 0.949 0.139 C 0.950 0.141 0.950 0.139 0.949 0.136 C 0.948 0.133 0.948 0.133 0.949 0.133 C 0.952 0.132 0.953 0.133 0.954 0.136 C 0.955 0.138 0.956 0.138 0.957 0.138 C 0.958 0.137 0.958 0.137 0.957 0.139 C 0.956 0.140 0.956 0.141 0.957 0.142 C 0.957 0.143 0.957 0.143 0.956 0.143 C 0.955 0.143 0.955 0.142 0.955 0.142 C 0.955 0.140 0.954 0.140 0.952 0.143 C 0.951 0.145 0.949 0.146 0.949 0.146 C 0.948 0.146 0.948 0.147 0.948 0.148 C 0.948 0.149 0.947 0.149 0.947 0.148 C 0.946 0.145 0.946 0.145 0.946 0.148 C 0.946 0.150 0.946 0.151 0.945 0.152 C 0.945 0.152 0.945 0.154 0.945 0.155 C 0.945 0.160 0.942 0.164 0.939 0.163 C 0.938 0.163 0.937 0.163 0.938 0.163 C 0.938 0.164 0.938 0.165 0.938 0.166 C 0.938 0.167 0.938 0.167 0.938 0.167 C 0.938 0.166 0.939 0.167 0.940 0.169 C 0.941 0.171 0.943 0.173 0.946 0.174 C 0.952 0.177 0.956 0.182 0.954 0.184 C 0.953 0.185 0.953 0.184 0.953 0.183 C 0.953 0.182 0.953 0.182 0.953 0.183 C 0.952 0.185 0.951 0.186 0.947 0.186 C 0.944 0.186 0.943 0.187 0.943 0.188 C 0.944 0.189 0.945 0.191 0.946 0.191 C 0.947 0.192 0.948 0.193 0.949 0.193 C 0.950 0.194 0.951 0.195 0.951 0.196 C 0.951 0.197 0.951 0.198 0.951 0.199 C 0.952 0.199 0.953 0.201 0.953 0.201 C 0.954 0.202 0.955 0.203 0.956 0.204 C 0.958 0.204 0.959 0.205 0.959 0.206 C 0.959 0.209 0.961 0.207 0.961 0.205 C 0.961 0.203 0.961 0.203 0.961 0.205 C 0.962 0.207 0.967 0.207 0.967 0.205 C 0.968 0.204 0.968 0.204 0.968 0.206 C 0.968 0.208 0.968 0.209 0.967 0.210 C 0.966 0.210 0.965 0.211 0.964 0.211 C 0.963 0.212 0.963 0.212 0.964 0.210 C 0.964 0.208 0.960 0.210 0.957 0.212 C 0.957 0.213 0.956 0.214 0.955 0.213 C 0.955 0.213 0.954 0.213 0.954 0.215 C 0.954 0.217 0.953 0.218 0.952 0.218 C 0.950 0.218 0.950 0.218 0.950 0.222 C 0.950 0.225 0.950 0.227 0.949 0.228 C 0.949 0.230 0.949 0.234 0.950 0.234 C 0.951 0.234 0.951 0.234 0.950 0.236 C 0.949 0.237 0.949 0.237 0.950 0.237 C 0.952 0.238 0.952 0.238 0.951 0.239 C 0.950 0.240 0.950 0.241 0.952 0.243 C 0.953 0.246 0.953 0.246 0.952 0.246 C 0.952 0.246 0.951 0.248 0.951 0.249 C 0.951 0.251 0.951 0.252 0.950 0.252 C 0.949 0.252 0.949 0.253 0.950 0.257 C 0.950 0.259 0.952 0.261 0.954 0.262 C 0.958 0.263 0.959 0.265 0.958 0.268 C 0.958 0.270 0.960 0.273 0.962 0.274 C 0.964 0.274 0.964 0.274 0.962 0.275 L 0.960 0.276 L 0.962 0.277 C 0.963 0.277 0.964 0.276 0.965 0.275 C 0.966 0.275 0.968 0.275 0.971 0.276 C 0.973 0.277 0.974 0.278 0.974 0.279 C 0.973 0.279 0.973 0.280 0.973 0.282 C 0.974 0.284 0.975 0.284 0.975 0.281 C 0.975 0.280 0.975 0.279 0.976 0.279 C 0.978 0.279 0.978 0.279 0.977 0.281 C 0.977 0.282 0.977 0.282 0.979 0.281 C 0.980 0.281 0.981 0.281 0.982 0.283 C 0.982 0.284 0.982 0.284 0.981 0.283 C 0.980 0.282 0.979 0.285 0.980 0.288 C 0.981 0.289 0.981 0.290 0.980 0.289 C 0.979 0.289 0.975 0.290 0.971 0.291 C 0.966 0.291 0.963 0.291 0.964 0.290 C 0.964 0.289 0.963 0.289 0.962 0.289 C 0.961 0.290 0.957 0.290 0.955 0.290 C 0.947 0.291 0.948 0.291 0.948 0.294 C 0.948 0.296 0.949 0.297 0.949 0.297 C 0.950 0.297 0.951 0.297 0.951 0.298 C 0.951 0.299 0.953 0.301 0.954 0.303 C 0.956 0.305 0.957 0.307 0.958 0.308 C 0.958 0.309 0.965 0.313 0.968 0.313 C 0.969 0.313 0.969 0.314 0.968 0.315 C 0.967 0.317 0.967 0.317 0.966 0.315 C 0.966 0.311 0.965 0.313 0.965 0.317 C 0.965 0.322 0.967 0.324 0.971 0.324 C 0.973 0.324 0.974 0.325 0.974 0.326 C 0.974 0.327 0.974 0.327 0.974 0.327 C 0.973 0.327 0.973 0.328 0.973 0.329 C 0.973 0.331 0.976 0.333 0.976 0.330 C 0.977 0.329 0.977 0.329 0.977 0.330 C 0.977 0.331 0.978 0.333 0.980 0.334 L 0.982 0.336 L 0.980 0.336 C 0.978 0.336 0.977 0.337 0.977 0.338 C 0.977 0.340 0.977 0.340 0.977 0.338 C 0.976 0.337 0.976 0.337 0.976 0.338 C 0.975 0.339 0.975 0.340 0.975 0.339 C 0.975 0.338 0.975 0.339 0.974 0.340 C 0.974 0.341 0.973 0.342 0.973 0.341 C 0.972 0.340 0.972 0.341 0.972 0.342 C 0.972 0.344 0.972 0.344 0.971 0.342 C 0.971 0.341 0.971 0.340 0.970 0.342 C 0.969 0.343 0.968 0.343 0.968 0.342 C 0.968 0.342 0.968 0.343 0.967 0.344 C 0.966 0.346 0.963 0.344 0.964 0.342 C 0.965 0.340 0.963 0.341 0.961 0.344 C 0.960 0.345 0.958 0.345 0.955 0.345 C 0.953 0.345 0.951 0.346 0.951 0.347 C 0.952 0.348 0.951 0.349 0.951 0.349 C 0.950 0.349 0.950 0.350 0.950 0.352 C 0.949 0.353 0.949 0.354 0.947 0.354 C 0.946 0.355 0.946 0.355 0.947 0.356 C 0.947 0.358 0.954 0.360 0.957 0.360 C 0.957 0.360 0.958 0.362 0.958 0.363 C 0.958 0.366 0.959 0.367 0.960 0.366 L 0.961 0.365 L 0.960 0.367 C 0.958 0.369 0.958 0.372 0.959 0.370 C 0.960 0.370 0.961 0.370 0.961 0.371 C 0.961 0.372 0.961 0.372 0.960 0.372 C 0.959 0.372 0.958 0.374 0.958 0.376 C 0.957 0.378 0.956 0.380 0.954 0.381 C 0.950 0.382 0.950 0.382 0.951 0.384 C 0.952 0.386 0.952 0.387 0.951 0.387 C 0.950 0.387 0.953 0.390 0.956 0.392 C 0.958 0.393 0.960 0.396 0.961 0.398 L 0.963 0.403 L 0.961 0.403 C 0.957 0.403 0.956 0.407 0.960 0.409 C 0.964 0.411 0.964 0.415 0.961 0.416 C 0.959 0.417 0.958 0.418 0.958 0.420 C 0.957 0.422 0.956 0.423 0.953 0.424 C 0.949 0.426 0.948 0.427 0.948 0.432 C 0.948 0.433 0.950 0.435 0.953 0.439 C 0.954 0.439 0.956 0.440 0.957 0.440 C 0.961 0.439 0.971 0.442 0.972 0.445 C 0.974 0.447 0.974 0.449 0.973 0.450 C 0.973 0.451 0.973 0.451 0.974 0.451 C 0.975 0.450 0.976 0.451 0.977 0.451 C 0.977 0.453 0.977 0.453 0.976 0.453 C 0.976 0.453 0.975 0.454 0.976 0.455 C 0.976 0.457 0.974 0.458 0.973 0.457 C 0.972 0.457 0.972 0.458 0.971 0.459 C 0.971 0.460 0.970 0.460 0.970 0.460 C 0.969 0.457 0.966 0.457 0.966 0.459 C 0.966 0.460 0.965 0.460 0.964 0.460 C 0.963 0.460 0.963 0.460 0.963 0.459 C 0.964 0.457 0.964 0.457 0.963 0.458 C 0.959 0.460 0.958 0.460 0.958 0.458 C 0.958 0.457 0.958 0.457 0.958 0.457 C 0.955 0.460 0.955 0.461 0.955 0.459 C 0.956 0.458 0.955 0.457 0.954 0.458 C 0.953 0.458 0.952 0.459 0.952 0.459 C 0.952 0.459 0.952 0.460 0.953 0.461 C 0.954 0.464 0.954 0.464 0.953 0.464 C 0.951 0.463 0.951 0.464 0.951 0.466 C 0.951 0.469 0.948 0.473 0.947 0.472 C 0.946 0.472 0.945 0.472 0.945 0.473 C 0.946 0.474 0.944 0.475 0.942 0.475 C 0.938 0.476 0.937 0.477 0.937 0.479 C 0.936 0.482 0.935 0.482 0.931 0.482 C 0.929 0.482 0.927 0.483 0.928 0.484 C 0.928 0.485 0.929 0.486 0.930 0.486 C 0.931 0.486 0.932 0.486 0.932 0.487 C 0.932 0.490 0.934 0.490 0.935 0.487 C 0.935 0.485 0.935 0.485 0.935 0.487 C 0.935 0.490 0.935 0.490 0.937 0.486 C 0.938 0.485 0.938 0.485 0.938 0.486 C 0.938 0.487 0.939 0.488 0.940 0.488 C 0.942 0.488 0.942 0.488 0.941 0.489 C 0.940 0.491 0.940 0.491 0.941 0.491 C 0.942 0.491 0.942 0.492 0.942 0.494 C 0.942 0.497 0.942 0.498 0.942 0.499 C 0.943 0.500 0.943 0.501 0.943 0.502 C 0.943 0.503 0.943 0.503 0.944 0.502 C 0.945 0.502 0.946 0.502 0.946 0.504 C 0.946 0.506 0.945 0.507 0.944 0.508 L 0.942 0.508 L 0.944 0.508 C 0.946 0.510 0.947 0.511 0.946 0.513 C 0.945 0.514 0.945 0.514 0.946 0.514 C 0.947 0.514 0.948 0.513 0.948 0.511 C 0.948 0.510 0.948 0.509 0.949 0.510 C 0.949 0.510 0.949 0.510 0.950 0.509 C 0.950 0.507 0.950 0.507 0.949 0.508 C 0.949 0.509 0.949 0.509 0.949 0.508 C 0.949 0.507 0.951 0.505 0.953 0.504 C 0.957 0.501 0.958 0.501 0.957 0.504 C 0.956 0.505 0.956 0.506 0.956 0.507 C 0.956 0.508 0.957 0.508 0.957 0.506 C 0.958 0.503 0.959 0.503 0.959 0.506 C 0.958 0.509 0.960 0.510 0.971 0.512 C 0.978 0.513 0.987 0.519 0.987 0.522 C 0.987 0.524 0.992 0.526 0.995 0.525 C 0.996 0.524 0.998 0.525 0.998 0.527 C 0.997 0.528 0.998 0.529 0.998 0.529 C 0.998 0.529 0.998 0.529 0.998 0.531 C 0.997 0.531 0.997 0.532 0.997 0.531 C 0.997 0.531 0.996 0.531 0.996 0.532 C 0.996 0.533 0.994 0.534 0.993 0.534 C 0.991 0.534 0.989 0.535 0.989 0.536 C 0.989 0.537 0.988 0.538 0.987 0.537 C 0.986 0.536 0.983 0.539 0.983 0.541 C 0.983 0.542 0.982 0.542 0.982 0.542 C 0.981 0.541 0.980 0.542 0.981 0.543 C 0.981 0.545 0.980 0.545 0.962 0.545 C 0.948 0.546 0.944 0.547 0.949 0.549 C 0.950 0.550 0.952 0.551 0.954 0.552 C 0.955 0.553 0.956 0.554 0.957 0.554 C 0.958 0.554 0.959 0.555 0.959 0.556 C 0.959 0.557 0.959 0.557 0.960 0.557 C 0.961 0.557 0.962 0.558 0.963 0.559 C 0.964 0.560 0.967 0.561 0.969 0.562 C 0.974 0.563 0.981 0.566 0.982 0.569 C 0.982 0.570 0.982 0.571 0.981 0.574 C 0.981 0.576 0.980 0.577 0.980 0.577 C 0.980 0.577 0.980 0.579 0.980 0.580 C 0.981 0.582 0.982 0.583 0.983 0.583 C 0.984 0.583 0.984 0.584 0.984 0.585 C 0.984 0.587 0.983 0.587 0.981 0.587 C 0.978 0.586 0.969 0.592 0.968 0.595 C 0.967 0.595 0.964 0.596 0.961 0.596 C 0.958 0.596 0.955 0.596 0.955 0.597 C 0.955 0.598 0.957 0.598 0.959 0.599 C 0.963 0.599 0.965 0.600 0.971 0.602 C 0.972 0.602 0.974 0.603 0.975 0.604 C 0.976 0.606 0.976 0.606 0.972 0.609 C 0.971 0.610 0.971 0.610 0.972 0.612 C 0.972 0.613 0.972 0.613 0.972 0.613 C 0.971 0.613 0.971 0.614 0.972 0.615 C 0.972 0.617 0.972 0.617 0.972 0.617 C 0.971 0.617 0.972 0.618 0.973 0.619 L 0.974 0.622 L 0.973 0.623 C 0.972 0.624 0.971 0.624 0.970 0.623 L 0.969 0.622 L 0.970 0.626 C 0.971 0.630 0.971 0.631 0.969 0.627 C 0.968 0.624 0.968 0.624 0.966 0.627 C 0.965 0.631 0.965 0.631 0.965 0.632 C 0.966 0.632 0.967 0.633 0.967 0.634 C 0.968 0.635 0.968 0.635 0.967 0.632 C 0.967 0.629 0.967 0.629 0.968 0.630 C 0.968 0.631 0.969 0.632 0.969 0.633 C 0.969 0.634 0.970 0.635 0.971 0.635 C 0.971 0.635 0.971 0.635 0.970 0.637 L 0.969 0.638 L 0.970 0.638 C 0.971 0.639 0.971 0.639 0.970 0.642 C 0.969 0.643 0.969 0.646 0.969 0.647 C 0.969 0.648 0.968 0.649 0.965 0.649 C 0.962 0.649 0.960 0.652 0.961 0.656 C 0.961 0.656 0.961 0.656 0.960 0.655 C 0.959 0.653 0.959 0.653 0.958 0.655 C 0.958 0.657 0.956 0.659 0.955 0.659 C 0.951 0.661 0.950 0.662 0.950 0.664 C 0.950 0.665 0.951 0.666 0.953 0.666 C 0.956 0.666 0.958 0.668 0.958 0.671 C 0.958 0.672 0.958 0.673 0.957 0.674 C 0.957 0.674 0.956 0.676 0.956 0.676 C 0.957 0.677 0.955 0.678 0.954 0.679 C 0.952 0.680 0.950 0.682 0.950 0.684 L 0.948 0.687 L 0.950 0.688 C 0.950 0.689 0.952 0.690 0.952 0.691 C 0.953 0.692 0.954 0.692 0.955 0.692 C 0.956 0.692 0.956 0.693 0.956 0.694 C 0.956 0.696 0.955 0.697 0.952 0.699 C 0.951 0.699 0.949 0.701 0.949 0.702 C 0.949 0.703 0.949 0.706 0.948 0.708 C 0.947 0.714 0.947 0.715 0.949 0.720 C 0.949 0.721 0.950 0.725 0.951 0.728 C 0.951 0.732 0.951 0.733 0.950 0.736 C 0.950 0.738 0.949 0.739 0.949 0.738 C 0.949 0.738 0.949 0.738 0.949 0.739 C 0.948 0.740 0.948 0.742 0.948 0.743 C 0.948 0.744 0.948 0.745 0.948 0.745 C 0.947 0.745 0.947 0.746 0.947 0.747 C 0.946 0.748 0.945 0.750 0.945 0.751 C 0.944 0.752 0.943 0.753 0.944 0.753 C 0.945 0.754 0.945 0.761 0.944 0.760 C 0.942 0.760 0.940 0.761 0.941 0.762 C 0.941 0.763 0.941 0.764 0.941 0.764 C 0.941 0.765 0.942 0.767 0.942 0.769 C 0.943 0.771 0.944 0.773 0.944 0.774 C 0.944 0.774 0.944 0.775 0.945 0.777 C 0.946 0.779 0.946 0.786 0.945 0.788 C 0.943 0.791 0.944 0.793 0.947 0.793 C 0.951 0.793 0.952 0.795 0.953 0.800 C 0.954 0.806 0.954 0.812 0.952 0.817 C 0.951 0.819 0.950 0.822 0.950 0.822 C 0.950 0.823 0.954 0.827 0.956 0.828 C 0.958 0.829 0.958 0.831 0.957 0.832 C 0.956 0.833 0.956 0.834 0.955 0.836 C 0.955 0.837 0.954 0.838 0.953 0.839 C 0.953 0.840 0.949 0.842 0.946 0.843 C 0.939 0.848 0.938 0.853 0.944 0.855 C 0.947 0.857 0.952 0.861 0.950 0.861 C 0.950 0.861 0.950 0.862 0.950 0.863 C 0.950 0.864 0.950 0.865 0.949 0.865 C 0.949 0.865 0.947 0.866 0.947 0.867 C 0.946 0.869 0.946 0.869 0.946 0.870 C 0.947 0.872 0.943 0.875 0.938 0.877 C 0.936 0.878 0.934 0.879 0.934 0.879 C 0.933 0.879 0.931 0.880 0.930 0.880 C 0.928 0.881 0.926 0.884 0.925 0.886 C 0.923 0.889 0.922 0.891 0.921 0.892 C 0.920 0.892 0.919 0.893 0.919 0.894 C 0.919 0.895 0.918 0.896 0.918 0.898 C 0.917 0.899 0.916 0.901 0.916 0.902 C 0.916 0.903 0.915 0.904 0.913 0.904 C 0.912 0.905 0.910 0.905 0.910 0.906 C 0.910 0.907 0.907 0.908 0.904 0.907 C 0.898 0.907 0.897 0.908 0.897 0.910 C 0.896 0.912 0.895 0.913 0.895 0.912 C 0.895 0.912 0.894 0.912 0.894 0.914 C 0.894 0.915 0.894 0.916 0.893 0.916 C 0.892 0.916 0.892 0.916 0.892 0.917 C 0.892 0.920 0.889 0.921 0.888 0.918 C 0.888 0.916 0.887 0.915 0.886 0.916 C 0.884 0.916 0.884 0.916 0.884 0.916 C 0.884 0.913 0.881 0.912 0.880 0.913 C 0.879 0.914 0.878 0.915 0.878 0.917 C 0.878 0.918 0.878 0.919 0.878 0.918 C 0.877 0.917 0.877 0.918 0.877 0.920 C 0.877 0.923 0.876 0.925 0.875 0.924 C 0.875 0.923 0.874 0.923 0.874 0.924 C 0.873 0.927 0.862 0.927 0.861 0.925 C 0.860 0.923 0.857 0.922 0.857 0.924 C 0.857 0.928 0.856 0.927 0.855 0.923 C 0.854 0.919 0.853 0.919 0.853 0.923 C 0.853 0.927 0.851 0.933 0.850 0.932 C 0.850 0.932 0.849 0.932 0.849 0.933 C 0.849 0.936 0.847 0.936 0.846 0.934 C 0.846 0.933 0.846 0.932 0.845 0.932 C 0.845 0.932 0.844 0.931 0.844 0.930 C 0.844 0.927 0.840 0.926 0.839 0.928 C 0.838 0.929 0.838 0.929 0.837 0.928 C 0.837 0.926 0.837 0.927 0.836 0.930 C 0.835 0.936 0.833 0.942 0.832 0.942 C 0.832 0.942 0.831 0.940 0.829 0.938 C 0.828 0.935 0.827 0.934 0.826 0.934 C 0.826 0.935 0.825 0.934 0.825 0.933 C 0.824 0.931 0.823 0.932 0.821 0.936 C 0.819 0.941 0.818 0.941 0.817 0.936 C 0.816 0.933 0.816 0.933 0.816 0.935 C 0.815 0.936 0.815 0.937 0.814 0.937 C 0.813 0.937 0.812 0.938 0.812 0.940 C 0.812 0.942 0.812 0.942 0.811 0.942 C 0.808 0.939 0.808 0.939 0.808 0.941 C 0.808 0.942 0.806 0.942 0.805 0.942 C 0.803 0.942 0.802 0.943 0.802 0.944 C 0.802 0.945 0.802 0.946 0.801 0.946 C 0.800 0.946 0.800 0.947 0.800 0.948 C 0.800 0.949 0.800 0.950 0.800 0.950 C 0.800 0.950 0.799 0.949 0.799 0.947 C 0.799 0.946 0.799 0.944 0.798 0.943 C 0.797 0.942 0.797 0.941 0.797 0.941 C 0.798 0.941 0.798 0.937 0.797 0.937 C 0.797 0.937 0.797 0.938 0.796 0.940 C 0.796 0.942 0.794 0.944 0.791 0.945 C 0.790 0.945 0.789 0.946 0.789 0.946 C 0.789 0.951 0.784 0.951 0.782 0.947 C 0.782 0.944 0.779 0.943 0.778 0.946 C 0.778 0.946 0.777 0.947 0.777 0.947 C 0.776 0.948 0.775 0.951 0.774 0.955 L 0.773 0.963 L 0.770 0.960 C 0.769 0.958 0.767 0.957 0.767 0.957 C 0.766 0.957 0.765 0.956 0.765 0.954 C 0.765 0.950 0.764 0.951 0.764 0.955 C 0.763 0.958 0.761 0.958 0.761 0.955 C 0.761 0.952 0.759 0.961 0.758 0.965 C 0.758 0.968 0.757 0.969 0.757 0.969 C 0.757 0.969 0.756 0.970 0.757 0.971 C 0.757 0.975 0.755 0.971 0.754 0.967 C 0.753 0.964 0.752 0.963 0.751 0.964 C 0.751 0.964 0.750 0.965 0.750 0.966 C 0.750 0.969 0.747 0.976 0.745 0.976 C 0.743 0.976 0.742 0.978 0.739 0.983 C 0.737 0.987 0.736 0.987 0.736 0.983 C 0.736 0.980 0.734 0.977 0.732 0.979 C 0.732 0.980 0.731 0.980 0.730 0.978 C 0.729 0.975 0.729 0.976 0.726 0.981 C 0.725 0.982 0.725 0.982 0.724 0.979 C 0.723 0.978 0.722 0.977 0.722 0.977 C 0.721 0.978 0.720 0.977 0.720 0.976 C 0.719 0.972 0.718 0.972 0.716 0.977 C 0.714 0.981 0.714 0.981 0.712 0.978 C 0.710 0.975 0.708 0.975 0.709 0.978 C 0.709 0.979 0.708 0.980 0.708 0.980 C 0.704 0.981 0.701 0.982 0.701 0.983 C 0.701 0.983 0.700 0.983 0.699 0.982 C 0.698 0.981 0.698 0.981 0.697 0.982 C 0.697 0.984 0.697 0.984 0.695 0.982 C 0.694 0.981 0.694 0.981 0.693 0.982 C 0.693 0.983 0.693 0.983 0.693 0.982 C 0.692 0.979 0.688 0.978 0.687 0.981 C 0.686 0.987 0.682 0.990 0.679 0.986 C 0.677 0.983 0.676 0.983 0.677 0.986 C 0.677 0.987 0.677 0.988 0.676 0.987 C 0.675 0.986 0.675 0.987 0.674 0.989 C 0.674 0.990 0.674 0.991 0.673 0.990 C 0.673 0.990 0.673 0.990 0.672 0.991 C 0.672 0.992 0.672 0.993 0.671 0.993 C 0.670 0.993 0.669 0.994 0.669 0.995 C 0.668 0.996 0.668 0.996 0.667 0.994 C 0.667 0.992 0.666 0.991 0.665 0.991 C 0.664 0.991 0.662 0.990 0.661 0.989 C 0.659 0.986 0.659 0.986 0.659 0.989 C 0.659 0.991 0.658 0.991 0.656 0.990 C 0.654 0.989 0.653 0.990 0.653 0.991 C 0.653 0.992 0.652 0.992 0.649 0.992 C 0.647 0.991 0.646 0.991 0.646 0.992 C 0.646 0.996 0.643 0.997 0.641 0.995 C 0.640 0.993 0.639 0.993 0.638 0.994 C 0.637 0.997 0.635 0.997 0.636 0.995 L 0.636 0.995 Z',\n  [MaskTypes.BRUSH_STROKE_2]:\n    'M 0.286 0.002 C 0.286 0.001 0.286 0.000 0.285 0.000 C 0.285 0.000 0.285 0.001 0.285 0.002 C 0.285 0.003 0.285 0.004 0.286 0.004 C 0.286 0.004 0.286 0.003 0.286 0.002 Z  M 0.289 0.014 C 0.289 0.013 0.289 0.012 0.289 0.012 C 0.289 0.012 0.288 0.013 0.288 0.014 C 0.288 0.015 0.289 0.016 0.289 0.016 C 0.289 0.016 0.289 0.015 0.289 0.014 Z  M 0.233 0.019 C 0.233 0.018 0.233 0.018 0.233 0.018 C 0.233 0.018 0.233 0.018 0.233 0.019 C 0.232 0.020 0.232 0.021 0.233 0.021 C 0.233 0.021 0.233 0.020 0.233 0.019 Z  M 0.284 0.020 C 0.283 0.019 0.283 0.019 0.282 0.020 C 0.282 0.020 0.282 0.021 0.283 0.021 C 0.284 0.021 0.284 0.020 0.284 0.020 Z  M 0.198 0.021 C 0.198 0.020 0.198 0.019 0.198 0.019 C 0.197 0.019 0.197 0.020 0.197 0.021 C 0.197 0.022 0.198 0.023 0.198 0.023 C 0.198 0.023 0.198 0.022 0.198 0.021 Z  M 0.200 0.021 C 0.200 0.020 0.200 0.019 0.200 0.019 C 0.200 0.019 0.200 0.020 0.199 0.021 C 0.199 0.022 0.199 0.023 0.200 0.023 C 0.200 0.023 0.200 0.022 0.200 0.021 Z  M 0.251 0.027 C 0.251 0.026 0.250 0.025 0.250 0.024 C 0.250 0.023 0.249 0.024 0.249 0.025 C 0.250 0.028 0.251 0.029 0.251 0.027 Z  M 0.288 0.023 C 0.289 0.020 0.289 0.019 0.289 0.017 C 0.288 0.017 0.288 0.016 0.287 0.016 C 0.287 0.016 0.287 0.016 0.287 0.018 C 0.288 0.019 0.288 0.019 0.287 0.018 C 0.286 0.018 0.285 0.018 0.285 0.020 C 0.285 0.022 0.285 0.023 0.285 0.023 C 0.284 0.023 0.284 0.024 0.284 0.025 C 0.284 0.026 0.284 0.026 0.285 0.026 C 0.285 0.025 0.286 0.025 0.286 0.026 C 0.287 0.027 0.287 0.027 0.288 0.023 Z  M 0.188 0.028 C 0.188 0.027 0.188 0.027 0.188 0.028 C 0.187 0.029 0.187 0.030 0.187 0.030 C 0.188 0.030 0.188 0.029 0.188 0.028 Z  M 0.345 0.028 C 0.345 0.027 0.345 0.026 0.344 0.026 C 0.344 0.026 0.344 0.027 0.344 0.028 C 0.344 0.029 0.344 0.030 0.344 0.030 C 0.345 0.030 0.345 0.029 0.345 0.028 Z  M 0.171 0.030 C 0.171 0.029 0.171 0.028 0.171 0.028 C 0.171 0.028 0.170 0.029 0.170 0.030 C 0.170 0.031 0.171 0.032 0.171 0.032 C 0.171 0.032 0.171 0.031 0.171 0.030 Z  M 0.184 0.030 C 0.184 0.029 0.183 0.028 0.183 0.029 C 0.183 0.029 0.183 0.030 0.183 0.030 C 0.184 0.031 0.184 0.031 0.184 0.030 Z  M 0.290 0.031 C 0.290 0.030 0.290 0.030 0.290 0.029 C 0.289 0.028 0.289 0.029 0.289 0.030 C 0.289 0.031 0.289 0.032 0.290 0.032 C 0.290 0.032 0.290 0.031 0.290 0.031 Z  M 0.339 0.030 C 0.339 0.029 0.339 0.028 0.338 0.028 C 0.337 0.028 0.337 0.029 0.337 0.030 C 0.338 0.032 0.338 0.032 0.339 0.030 Z  M 0.249 0.032 C 0.249 0.030 0.249 0.028 0.248 0.028 C 0.248 0.028 0.248 0.029 0.248 0.030 C 0.248 0.031 0.248 0.032 0.248 0.032 C 0.248 0.033 0.248 0.033 0.248 0.033 C 0.248 0.033 0.248 0.033 0.249 0.032 Z  M 0.203 0.033 C 0.203 0.032 0.203 0.032 0.202 0.032 C 0.202 0.032 0.201 0.032 0.202 0.033 C 0.202 0.036 0.202 0.036 0.203 0.033 Z  M 0.181 0.036 C 0.181 0.035 0.181 0.034 0.181 0.033 C 0.181 0.032 0.180 0.033 0.180 0.034 C 0.180 0.036 0.180 0.037 0.181 0.037 C 0.181 0.037 0.182 0.036 0.181 0.036 Z  M 0.548 0.035 C 0.547 0.032 0.547 0.031 0.547 0.034 C 0.547 0.036 0.547 0.037 0.547 0.037 C 0.548 0.037 0.548 0.036 0.548 0.035 Z  M 0.624 0.035 C 0.624 0.034 0.624 0.033 0.624 0.033 C 0.623 0.033 0.623 0.034 0.623 0.034 C 0.623 0.035 0.623 0.035 0.624 0.036 C 0.624 0.037 0.624 0.036 0.624 0.035 Z  M 0.266 0.038 C 0.266 0.035 0.266 0.035 0.266 0.037 C 0.266 0.038 0.266 0.039 0.266 0.039 C 0.267 0.040 0.267 0.040 0.266 0.038 Z  M 0.252 0.040 C 0.252 0.040 0.251 0.039 0.251 0.039 C 0.251 0.039 0.251 0.040 0.251 0.040 C 0.251 0.041 0.251 0.042 0.251 0.042 C 0.252 0.042 0.252 0.041 0.252 0.040 Z  M 0.262 0.040 C 0.262 0.040 0.262 0.039 0.262 0.039 C 0.262 0.039 0.262 0.040 0.262 0.040 C 0.262 0.041 0.262 0.042 0.262 0.042 C 0.262 0.042 0.262 0.041 0.262 0.040 Z  M 0.287 0.040 C 0.287 0.039 0.287 0.038 0.286 0.038 C 0.286 0.037 0.286 0.035 0.286 0.034 C 0.286 0.033 0.285 0.032 0.285 0.032 C 0.285 0.032 0.285 0.036 0.285 0.038 C 0.285 0.038 0.286 0.040 0.285 0.041 C 0.285 0.042 0.285 0.042 0.286 0.042 C 0.286 0.042 0.287 0.041 0.287 0.040 H 0.287 Z  M 0.291 0.040 C 0.291 0.040 0.290 0.039 0.290 0.039 C 0.290 0.039 0.290 0.040 0.290 0.040 C 0.290 0.041 0.290 0.042 0.290 0.042 C 0.290 0.042 0.291 0.041 0.291 0.040 Z  M 0.292 0.040 C 0.292 0.040 0.292 0.039 0.291 0.039 C 0.291 0.039 0.291 0.040 0.291 0.040 C 0.291 0.041 0.291 0.042 0.291 0.042 C 0.292 0.042 0.292 0.041 0.292 0.040 Z  M 0.209 0.043 C 0.209 0.043 0.209 0.042 0.209 0.041 C 0.209 0.041 0.209 0.041 0.209 0.042 C 0.209 0.043 0.209 0.044 0.209 0.044 C 0.209 0.044 0.209 0.044 0.209 0.043 Z  M 0.274 0.045 C 0.274 0.045 0.274 0.044 0.274 0.043 C 0.274 0.043 0.274 0.043 0.274 0.044 C 0.274 0.045 0.274 0.046 0.274 0.046 C 0.274 0.046 0.274 0.045 0.274 0.045 Z  M 0.307 0.044 C 0.307 0.043 0.306 0.042 0.306 0.042 C 0.305 0.042 0.305 0.043 0.305 0.044 C 0.305 0.045 0.305 0.046 0.306 0.046 C 0.307 0.046 0.307 0.045 0.307 0.044 Z  M 0.283 0.046 C 0.283 0.044 0.283 0.042 0.282 0.043 C 0.282 0.044 0.282 0.045 0.282 0.046 C 0.282 0.048 0.282 0.048 0.283 0.046 Z  M 0.312 0.046 C 0.312 0.045 0.312 0.044 0.312 0.044 C 0.311 0.044 0.311 0.045 0.311 0.046 C 0.311 0.047 0.311 0.048 0.311 0.048 C 0.312 0.048 0.312 0.047 0.312 0.046 Z  M 0.167 0.046 C 0.166 0.044 0.166 0.042 0.166 0.042 C 0.166 0.042 0.166 0.044 0.166 0.046 C 0.166 0.048 0.166 0.049 0.166 0.049 C 0.167 0.049 0.167 0.048 0.167 0.046 Z  M 0.323 0.048 C 0.322 0.045 0.321 0.045 0.321 0.046 C 0.320 0.047 0.320 0.047 0.321 0.048 C 0.322 0.049 0.323 0.050 0.324 0.050 C 0.324 0.051 0.324 0.050 0.323 0.048 Z  M 0.270 0.051 C 0.271 0.050 0.271 0.049 0.270 0.049 C 0.270 0.049 0.269 0.050 0.269 0.051 C 0.269 0.053 0.270 0.053 0.270 0.051 Z  M 0.267 0.054 C 0.267 0.054 0.267 0.053 0.266 0.052 C 0.266 0.052 0.266 0.052 0.266 0.053 C 0.266 0.054 0.266 0.055 0.266 0.055 C 0.267 0.055 0.267 0.054 0.267 0.054 Z  M 0.316 0.053 C 0.316 0.052 0.315 0.051 0.315 0.050 C 0.315 0.049 0.314 0.048 0.315 0.047 C 0.315 0.046 0.315 0.046 0.314 0.046 C 0.314 0.046 0.313 0.047 0.314 0.049 C 0.314 0.050 0.314 0.052 0.314 0.053 C 0.314 0.054 0.315 0.054 0.316 0.053 Z  M 0.254 0.055 C 0.254 0.055 0.254 0.055 0.253 0.055 C 0.253 0.056 0.253 0.056 0.254 0.056 C 0.254 0.056 0.254 0.056 0.254 0.055 Z  M 0.294 0.055 C 0.294 0.052 0.293 0.051 0.293 0.053 C 0.293 0.053 0.293 0.055 0.294 0.055 C 0.294 0.056 0.294 0.056 0.294 0.055 Z  M 0.310 0.054 C 0.309 0.052 0.309 0.051 0.309 0.051 C 0.308 0.051 0.308 0.052 0.309 0.054 C 0.309 0.055 0.309 0.056 0.309 0.056 C 0.310 0.056 0.310 0.055 0.310 0.054 Z  M 0.237 0.059 C 0.237 0.059 0.237 0.058 0.237 0.057 C 0.237 0.057 0.236 0.057 0.236 0.058 C 0.236 0.059 0.237 0.060 0.237 0.060 C 0.237 0.060 0.237 0.060 0.237 0.059 Z  M 0.288 0.057 C 0.288 0.056 0.288 0.054 0.288 0.055 C 0.287 0.056 0.287 0.057 0.288 0.058 C 0.288 0.060 0.288 0.059 0.288 0.057 Z  M 0.247 0.058 C 0.247 0.056 0.247 0.055 0.247 0.055 C 0.246 0.055 0.246 0.056 0.247 0.058 C 0.247 0.060 0.247 0.062 0.247 0.062 C 0.247 0.062 0.247 0.060 0.247 0.058 Z  M 0.276 0.059 C 0.276 0.058 0.275 0.056 0.275 0.056 C 0.275 0.056 0.275 0.058 0.275 0.059 C 0.275 0.060 0.275 0.062 0.275 0.062 C 0.276 0.062 0.276 0.061 0.276 0.059 Z  M 0.168 0.057 C 0.169 0.054 0.169 0.051 0.169 0.050 C 0.169 0.049 0.165 0.061 0.166 0.063 C 0.166 0.063 0.167 0.061 0.168 0.057 Z  M 0.181 0.062 C 0.181 0.061 0.181 0.060 0.180 0.060 C 0.180 0.060 0.180 0.061 0.180 0.062 C 0.180 0.063 0.180 0.063 0.180 0.063 C 0.180 0.063 0.180 0.063 0.181 0.062 Z  M 0.259 0.061 C 0.259 0.059 0.259 0.058 0.259 0.058 C 0.259 0.058 0.259 0.059 0.259 0.061 C 0.259 0.062 0.259 0.063 0.259 0.063 C 0.259 0.063 0.260 0.062 0.259 0.061 Z  M 0.291 0.061 C 0.291 0.060 0.291 0.060 0.291 0.061 C 0.292 0.061 0.292 0.061 0.292 0.060 C 0.292 0.058 0.291 0.058 0.290 0.060 C 0.290 0.061 0.290 0.061 0.290 0.062 C 0.291 0.063 0.291 0.062 0.291 0.061 Z  M 0.295 0.062 C 0.295 0.061 0.294 0.060 0.294 0.060 C 0.294 0.060 0.294 0.061 0.294 0.062 C 0.293 0.063 0.294 0.063 0.294 0.063 C 0.294 0.063 0.295 0.063 0.295 0.062 Z  M 0.163 0.063 C 0.164 0.061 0.164 0.060 0.163 0.061 C 0.163 0.061 0.162 0.061 0.161 0.061 C 0.160 0.062 0.161 0.065 0.162 0.065 C 0.162 0.065 0.163 0.064 0.163 0.063 Z  M 0.169 0.064 C 0.169 0.062 0.169 0.060 0.168 0.060 C 0.168 0.060 0.168 0.061 0.168 0.063 C 0.168 0.065 0.168 0.066 0.169 0.064 Z  M 0.265 0.064 C 0.265 0.063 0.264 0.063 0.264 0.064 C 0.264 0.064 0.264 0.065 0.265 0.065 C 0.265 0.065 0.265 0.064 0.265 0.064 Z  M 0.261 0.065 C 0.261 0.064 0.261 0.063 0.261 0.063 C 0.260 0.063 0.260 0.064 0.260 0.064 C 0.260 0.065 0.260 0.065 0.261 0.066 C 0.261 0.067 0.261 0.066 0.261 0.065 Z  M 0.290 0.065 C 0.290 0.064 0.289 0.063 0.289 0.063 C 0.289 0.063 0.289 0.064 0.289 0.064 C 0.289 0.065 0.289 0.065 0.289 0.066 C 0.289 0.067 0.290 0.066 0.290 0.065 Z  M 0.167 0.068 C 0.167 0.067 0.167 0.067 0.167 0.067 C 0.167 0.068 0.167 0.069 0.167 0.069 C 0.168 0.070 0.168 0.070 0.167 0.068 Z  M 0.172 0.066 C 0.172 0.062 0.172 0.062 0.171 0.063 C 0.170 0.063 0.170 0.064 0.170 0.065 C 0.169 0.066 0.170 0.068 0.171 0.069 C 0.172 0.070 0.172 0.070 0.172 0.066 Z  M 0.174 0.069 C 0.174 0.069 0.174 0.067 0.174 0.066 C 0.174 0.065 0.174 0.065 0.174 0.067 C 0.173 0.068 0.173 0.069 0.173 0.070 C 0.173 0.070 0.174 0.070 0.174 0.069 Z  M 0.178 0.069 C 0.178 0.068 0.178 0.063 0.178 0.063 C 0.177 0.063 0.177 0.065 0.177 0.067 C 0.177 0.069 0.177 0.070 0.177 0.070 C 0.177 0.070 0.177 0.070 0.178 0.069 Z  M 0.294 0.071 C 0.294 0.070 0.295 0.069 0.295 0.070 C 0.295 0.071 0.296 0.070 0.295 0.069 C 0.295 0.066 0.294 0.066 0.294 0.070 C 0.293 0.072 0.293 0.074 0.294 0.074 C 0.294 0.074 0.294 0.073 0.294 0.071 Z  M 0.252 0.074 C 0.252 0.072 0.252 0.070 0.251 0.071 C 0.251 0.071 0.250 0.072 0.251 0.073 C 0.251 0.075 0.251 0.075 0.252 0.074 Z  M 0.175 0.078 C 0.174 0.077 0.174 0.077 0.175 0.075 C 0.176 0.073 0.175 0.072 0.174 0.072 C 0.172 0.072 0.172 0.073 0.173 0.074 C 0.173 0.075 0.174 0.076 0.174 0.077 C 0.174 0.078 0.174 0.079 0.175 0.079 C 0.175 0.079 0.175 0.079 0.175 0.078 Z  M 0.242 0.055 C 0.242 0.054 0.242 0.053 0.243 0.054 C 0.243 0.055 0.243 0.056 0.242 0.056 C 0.242 0.056 0.242 0.056 0.242 0.055 Z  M 0.242 0.076 C 0.242 0.074 0.242 0.073 0.243 0.074 C 0.243 0.074 0.244 0.073 0.244 0.072 C 0.244 0.066 0.244 0.064 0.243 0.063 C 0.243 0.062 0.243 0.062 0.244 0.062 C 0.245 0.062 0.245 0.061 0.244 0.059 C 0.244 0.056 0.244 0.056 0.245 0.054 C 0.245 0.053 0.245 0.052 0.245 0.051 C 0.245 0.050 0.245 0.050 0.245 0.050 C 0.245 0.051 0.244 0.052 0.243 0.051 C 0.242 0.051 0.241 0.052 0.241 0.053 C 0.241 0.054 0.241 0.055 0.241 0.055 C 0.240 0.055 0.240 0.055 0.240 0.056 C 0.240 0.057 0.240 0.058 0.240 0.058 C 0.241 0.058 0.241 0.059 0.241 0.060 C 0.241 0.061 0.241 0.062 0.240 0.062 C 0.240 0.062 0.240 0.063 0.240 0.064 C 0.240 0.068 0.239 0.070 0.237 0.069 C 0.236 0.068 0.236 0.071 0.239 0.075 C 0.241 0.078 0.242 0.079 0.242 0.076 Z  M 0.114 0.079 C 0.114 0.078 0.114 0.077 0.114 0.077 C 0.114 0.077 0.114 0.078 0.113 0.079 C 0.113 0.080 0.113 0.081 0.114 0.081 C 0.114 0.081 0.114 0.080 0.114 0.079 Z  M 0.169 0.077 C 0.170 0.072 0.170 0.070 0.169 0.075 C 0.168 0.078 0.167 0.078 0.167 0.076 C 0.167 0.075 0.167 0.074 0.167 0.074 C 0.166 0.074 0.166 0.074 0.167 0.078 C 0.167 0.082 0.167 0.082 0.169 0.077 Z  M 0.288 0.080 C 0.287 0.079 0.287 0.079 0.286 0.080 C 0.286 0.080 0.286 0.081 0.287 0.081 C 0.288 0.081 0.288 0.080 0.288 0.080 Z  M 0.292 0.078 C 0.292 0.076 0.292 0.073 0.292 0.073 C 0.292 0.071 0.290 0.074 0.290 0.076 C 0.290 0.077 0.290 0.077 0.289 0.077 L 0.288 0.076 L 0.289 0.078 C 0.290 0.080 0.290 0.079 0.291 0.077 C 0.291 0.074 0.291 0.074 0.292 0.078 L 0.292 0.082 L 0.292 0.078 Z  M 0.161 0.082 C 0.161 0.081 0.162 0.081 0.162 0.081 C 0.163 0.080 0.164 0.079 0.164 0.078 C 0.164 0.077 0.164 0.076 0.165 0.077 C 0.165 0.078 0.166 0.077 0.166 0.074 C 0.166 0.071 0.165 0.071 0.165 0.072 C 0.165 0.073 0.165 0.074 0.164 0.074 C 0.164 0.074 0.164 0.075 0.164 0.076 C 0.164 0.077 0.163 0.078 0.163 0.077 C 0.161 0.074 0.161 0.074 0.161 0.077 C 0.161 0.078 0.160 0.079 0.160 0.079 C 0.160 0.079 0.160 0.080 0.160 0.081 C 0.160 0.083 0.160 0.083 0.161 0.082 Z  M 0.295 0.081 C 0.296 0.080 0.296 0.079 0.295 0.079 C 0.295 0.079 0.295 0.080 0.294 0.081 C 0.294 0.083 0.294 0.083 0.295 0.081 Z  M 0.171 0.085 C 0.171 0.084 0.171 0.082 0.171 0.082 C 0.170 0.081 0.170 0.082 0.170 0.084 C 0.170 0.087 0.170 0.087 0.171 0.085 Z  M 0.248 0.085 C 0.248 0.084 0.248 0.083 0.247 0.082 C 0.245 0.080 0.244 0.082 0.246 0.086 C 0.247 0.087 0.248 0.087 0.248 0.085 Z  M 0.173 0.087 C 0.173 0.083 0.173 0.081 0.172 0.084 C 0.172 0.086 0.171 0.088 0.170 0.089 C 0.170 0.089 0.170 0.089 0.171 0.089 C 0.172 0.089 0.173 0.088 0.173 0.087 Z  M 0.256 0.086 C 0.256 0.084 0.256 0.079 0.256 0.076 C 0.256 0.072 0.256 0.071 0.256 0.072 C 0.256 0.075 0.254 0.074 0.253 0.070 C 0.253 0.068 0.253 0.067 0.253 0.068 C 0.254 0.068 0.254 0.067 0.254 0.065 C 0.255 0.062 0.255 0.062 0.254 0.063 C 0.253 0.064 0.252 0.070 0.253 0.073 C 0.253 0.075 0.253 0.076 0.253 0.076 C 0.253 0.076 0.253 0.076 0.253 0.076 C 0.252 0.077 0.251 0.079 0.251 0.081 C 0.251 0.083 0.253 0.087 0.254 0.089 C 0.255 0.090 0.255 0.089 0.256 0.086 H 0.256 Z  M 0.141 0.092 C 0.141 0.091 0.140 0.086 0.139 0.086 C 0.138 0.086 0.138 0.090 0.139 0.092 C 0.139 0.093 0.141 0.094 0.141 0.092 Z  M 0.163 0.092 C 0.163 0.091 0.163 0.090 0.162 0.090 C 0.162 0.090 0.162 0.090 0.162 0.091 C 0.162 0.091 0.162 0.092 0.162 0.092 C 0.163 0.093 0.163 0.093 0.163 0.092 Z  M 0.148 0.093 C 0.148 0.092 0.147 0.092 0.147 0.092 C 0.147 0.092 0.146 0.092 0.146 0.092 C 0.146 0.093 0.147 0.093 0.147 0.094 C 0.147 0.095 0.148 0.094 0.148 0.093 Z  M 0.123 0.095 C 0.123 0.094 0.122 0.093 0.122 0.093 C 0.122 0.093 0.122 0.094 0.121 0.095 C 0.121 0.096 0.121 0.097 0.122 0.097 C 0.122 0.097 0.123 0.096 0.123 0.095 Z  M 0.161 0.095 C 0.161 0.094 0.161 0.093 0.161 0.093 C 0.161 0.093 0.161 0.092 0.161 0.092 C 0.162 0.090 0.162 0.090 0.161 0.090 C 0.161 0.090 0.160 0.089 0.160 0.088 C 0.160 0.087 0.160 0.087 0.160 0.087 C 0.159 0.088 0.159 0.097 0.160 0.097 C 0.160 0.097 0.160 0.096 0.161 0.095 L 0.161 0.095 Z  M 0.213 0.094 C 0.214 0.092 0.214 0.090 0.214 0.089 C 0.214 0.089 0.214 0.088 0.214 0.088 C 0.215 0.088 0.215 0.086 0.215 0.085 C 0.215 0.083 0.216 0.081 0.216 0.081 C 0.216 0.081 0.216 0.080 0.216 0.078 C 0.216 0.075 0.213 0.070 0.212 0.070 C 0.211 0.070 0.209 0.077 0.209 0.079 C 0.209 0.080 0.209 0.080 0.209 0.081 C 0.209 0.081 0.209 0.081 0.209 0.080 C 0.209 0.074 0.208 0.072 0.206 0.075 C 0.205 0.076 0.205 0.082 0.205 0.084 C 0.206 0.084 0.206 0.085 0.206 0.086 C 0.206 0.087 0.206 0.088 0.207 0.089 C 0.208 0.090 0.208 0.093 0.207 0.094 C 0.206 0.094 0.209 0.096 0.211 0.097 C 0.212 0.097 0.213 0.096 0.213 0.094 L 0.213 0.094 Z  M 0.463 0.096 C 0.462 0.095 0.462 0.095 0.462 0.096 C 0.461 0.096 0.461 0.097 0.462 0.097 C 0.462 0.097 0.463 0.096 0.463 0.096 Z  M 0.147 0.099 C 0.147 0.098 0.147 0.097 0.147 0.097 C 0.146 0.097 0.146 0.098 0.146 0.099 C 0.146 0.100 0.146 0.100 0.146 0.100 C 0.147 0.100 0.147 0.100 0.147 0.099 Z  M 0.149 0.099 C 0.149 0.098 0.148 0.097 0.148 0.097 C 0.148 0.097 0.148 0.098 0.147 0.099 C 0.147 0.100 0.147 0.100 0.148 0.100 C 0.148 0.100 0.149 0.100 0.149 0.099 Z  M 0.151 0.090 C 0.151 0.089 0.151 0.088 0.152 0.088 C 0.152 0.088 0.152 0.088 0.152 0.090 C 0.151 0.092 0.151 0.092 0.151 0.090 Z  M 0.153 0.101 C 0.153 0.100 0.154 0.099 0.154 0.100 C 0.155 0.100 0.155 0.100 0.155 0.099 C 0.155 0.095 0.154 0.090 0.153 0.090 C 0.152 0.090 0.152 0.089 0.153 0.085 C 0.153 0.082 0.153 0.081 0.152 0.081 C 0.152 0.081 0.151 0.082 0.152 0.084 C 0.152 0.086 0.151 0.087 0.150 0.085 C 0.150 0.085 0.150 0.083 0.150 0.083 C 0.150 0.082 0.150 0.081 0.150 0.081 C 0.149 0.081 0.148 0.087 0.149 0.088 C 0.151 0.093 0.151 0.094 0.152 0.092 C 0.152 0.090 0.153 0.091 0.153 0.092 C 0.154 0.095 0.154 0.095 0.153 0.094 C 0.153 0.093 0.152 0.094 0.152 0.095 C 0.151 0.096 0.151 0.097 0.152 0.099 C 0.152 0.100 0.152 0.102 0.152 0.103 C 0.152 0.103 0.152 0.104 0.152 0.104 C 0.152 0.104 0.153 0.103 0.153 0.101 L 0.153 0.101 Z  M 0.215 0.103 C 0.215 0.102 0.214 0.102 0.214 0.103 C 0.214 0.103 0.214 0.104 0.214 0.104 C 0.215 0.104 0.215 0.103 0.215 0.103 Z  M 0.193 0.105 C 0.194 0.102 0.194 0.095 0.193 0.093 C 0.192 0.090 0.190 0.093 0.190 0.098 C 0.189 0.106 0.191 0.110 0.193 0.105 Z  M 0.204 0.106 C 0.204 0.106 0.205 0.104 0.205 0.102 C 0.205 0.100 0.205 0.098 0.205 0.098 C 0.205 0.097 0.205 0.091 0.204 0.089 C 0.203 0.087 0.200 0.088 0.199 0.091 C 0.199 0.093 0.199 0.094 0.198 0.092 C 0.198 0.089 0.196 0.089 0.196 0.092 C 0.195 0.095 0.195 0.096 0.196 0.100 C 0.196 0.102 0.196 0.104 0.197 0.104 C 0.197 0.104 0.197 0.105 0.196 0.106 C 0.195 0.107 0.196 0.107 0.197 0.107 C 0.197 0.107 0.198 0.107 0.198 0.105 C 0.197 0.104 0.197 0.104 0.198 0.104 C 0.198 0.105 0.199 0.105 0.199 0.104 C 0.199 0.102 0.200 0.103 0.201 0.105 C 0.202 0.107 0.203 0.108 0.204 0.106 L 0.204 0.106 Z  M 0.408 0.106 C 0.408 0.106 0.407 0.106 0.407 0.106 C 0.407 0.107 0.407 0.107 0.407 0.107 C 0.408 0.107 0.408 0.107 0.408 0.106 Z  M 0.164 0.105 C 0.164 0.102 0.164 0.100 0.164 0.097 C 0.164 0.096 0.163 0.095 0.163 0.096 C 0.163 0.098 0.163 0.099 0.163 0.099 C 0.162 0.099 0.162 0.099 0.163 0.101 C 0.164 0.104 0.164 0.104 0.163 0.104 C 0.162 0.104 0.162 0.105 0.162 0.106 C 0.162 0.107 0.162 0.107 0.162 0.107 C 0.162 0.107 0.162 0.108 0.163 0.108 C 0.163 0.109 0.163 0.108 0.164 0.105 H 0.164 Z  M 0.410 0.108 C 0.410 0.106 0.410 0.106 0.409 0.106 C 0.409 0.106 0.409 0.106 0.409 0.106 C 0.409 0.107 0.409 0.108 0.409 0.108 C 0.410 0.109 0.410 0.109 0.410 0.108 Z  M 0.200 0.109 C 0.200 0.108 0.200 0.107 0.200 0.107 C 0.199 0.107 0.198 0.108 0.199 0.110 C 0.200 0.110 0.200 0.110 0.200 0.109 Z  M 0.264 0.110 C 0.263 0.109 0.263 0.109 0.263 0.110 C 0.262 0.110 0.262 0.111 0.263 0.111 C 0.263 0.111 0.264 0.110 0.264 0.110 Z  M 0.278 0.109 C 0.278 0.108 0.278 0.107 0.278 0.107 C 0.278 0.107 0.278 0.108 0.278 0.108 C 0.278 0.109 0.278 0.109 0.278 0.110 C 0.278 0.111 0.278 0.110 0.278 0.109 Z  M 0.159 0.111 C 0.159 0.110 0.159 0.109 0.159 0.109 C 0.159 0.109 0.158 0.107 0.158 0.105 C 0.158 0.101 0.158 0.100 0.158 0.100 C 0.158 0.100 0.158 0.100 0.158 0.099 C 0.158 0.098 0.157 0.101 0.156 0.104 C 0.156 0.106 0.156 0.107 0.155 0.107 C 0.155 0.107 0.155 0.108 0.156 0.110 C 0.157 0.113 0.159 0.114 0.159 0.111 L 0.159 0.111 Z  M 0.275 0.112 C 0.275 0.111 0.274 0.111 0.274 0.111 C 0.274 0.112 0.274 0.112 0.274 0.113 C 0.275 0.113 0.275 0.112 0.275 0.112 Z  M 0.208 0.113 C 0.207 0.113 0.207 0.113 0.207 0.113 C 0.206 0.114 0.206 0.114 0.207 0.114 C 0.207 0.114 0.208 0.114 0.208 0.113 Z  M 0.149 0.113 C 0.149 0.108 0.148 0.106 0.147 0.109 C 0.147 0.111 0.147 0.112 0.147 0.114 C 0.149 0.117 0.149 0.117 0.149 0.113 H 0.149 Z  M 0.186 0.113 C 0.186 0.107 0.186 0.102 0.185 0.100 C 0.183 0.096 0.183 0.104 0.184 0.112 C 0.185 0.117 0.185 0.117 0.186 0.113 Z  M 0.237 0.116 C 0.237 0.115 0.237 0.114 0.237 0.114 C 0.236 0.113 0.236 0.113 0.236 0.114 C 0.236 0.116 0.237 0.117 0.237 0.116 Z  M 0.258 0.115 C 0.258 0.114 0.257 0.113 0.257 0.114 C 0.256 0.114 0.256 0.115 0.256 0.116 C 0.256 0.116 0.256 0.116 0.257 0.116 C 0.257 0.116 0.258 0.115 0.258 0.115 Z  M 0.248 0.116 C 0.246 0.114 0.245 0.114 0.245 0.116 C 0.245 0.117 0.246 0.118 0.247 0.118 C 0.249 0.118 0.249 0.117 0.248 0.116 Z  M 0.134 0.118 C 0.134 0.115 0.134 0.114 0.133 0.115 C 0.132 0.115 0.132 0.116 0.133 0.118 C 0.133 0.119 0.134 0.119 0.134 0.118 Z  M 0.165 0.118 C 0.165 0.117 0.165 0.116 0.164 0.116 C 0.164 0.116 0.164 0.117 0.164 0.119 C 0.164 0.119 0.165 0.119 0.165 0.118 Z  M 0.149 0.124 C 0.149 0.123 0.149 0.123 0.148 0.124 C 0.148 0.124 0.148 0.125 0.149 0.125 C 0.149 0.125 0.149 0.125 0.149 0.124 Z  M 0.072 0.147 C 0.072 0.145 0.071 0.143 0.070 0.143 C 0.069 0.143 0.069 0.143 0.070 0.146 C 0.070 0.150 0.072 0.151 0.072 0.147 Z  M 0.074 0.156 C 0.074 0.155 0.074 0.155 0.074 0.155 C 0.073 0.156 0.073 0.156 0.074 0.157 C 0.074 0.157 0.075 0.156 0.074 0.156 Z  M 0.952 0.194 C 0.952 0.194 0.951 0.194 0.951 0.194 C 0.951 0.195 0.951 0.195 0.951 0.195 C 0.952 0.195 0.952 0.195 0.952 0.194 Z  M 0.003 0.218 C 0.004 0.215 0.004 0.214 0.003 0.212 C 0.002 0.209 0.000 0.210 0.000 0.214 C -0.000 0.217 0.001 0.222 0.002 0.222 C 0.002 0.222 0.003 0.220 0.003 0.218 Z  M 0.956 0.222 C 0.957 0.221 0.957 0.220 0.957 0.220 C 0.956 0.220 0.956 0.221 0.955 0.222 C 0.954 0.224 0.955 0.224 0.956 0.222 Z  M 0.049 0.229 C 0.049 0.229 0.048 0.229 0.048 0.229 C 0.048 0.230 0.048 0.230 0.049 0.230 C 0.049 0.230 0.049 0.230 0.049 0.229 Z  M 0.042 0.231 C 0.043 0.231 0.043 0.229 0.043 0.228 C 0.044 0.226 0.043 0.225 0.042 0.225 C 0.041 0.225 0.040 0.226 0.040 0.227 C 0.040 0.229 0.040 0.229 0.039 0.228 C 0.036 0.226 0.034 0.225 0.034 0.227 C 0.035 0.228 0.035 0.229 0.034 0.229 C 0.034 0.229 0.034 0.228 0.034 0.227 C 0.033 0.226 0.033 0.226 0.032 0.226 C 0.031 0.226 0.030 0.225 0.029 0.225 C 0.028 0.224 0.028 0.224 0.028 0.225 C 0.028 0.227 0.028 0.227 0.027 0.226 C 0.026 0.225 0.026 0.226 0.027 0.227 C 0.027 0.228 0.027 0.229 0.026 0.229 C 0.025 0.231 0.039 0.232 0.042 0.231 L 0.042 0.231 Z  M 0.067 0.254 C 0.067 0.251 0.066 0.251 0.065 0.254 C 0.065 0.255 0.065 0.255 0.066 0.255 C 0.066 0.255 0.067 0.255 0.067 0.254 Z  M 0.947 0.254 C 0.947 0.253 0.946 0.252 0.946 0.252 C 0.946 0.252 0.946 0.253 0.946 0.254 C 0.946 0.255 0.946 0.255 0.947 0.255 C 0.947 0.255 0.947 0.255 0.947 0.254 Z  M 0.957 0.275 C 0.957 0.275 0.957 0.275 0.956 0.275 C 0.956 0.276 0.956 0.276 0.957 0.276 C 0.957 0.276 0.957 0.276 0.957 0.275 Z  M 0.953 0.277 C 0.953 0.276 0.953 0.275 0.953 0.275 C 0.953 0.275 0.952 0.275 0.952 0.275 C 0.952 0.276 0.953 0.277 0.953 0.277 C 0.953 0.278 0.953 0.278 0.953 0.277 Z  M 0.953 0.298 C 0.953 0.298 0.953 0.296 0.954 0.295 C 0.954 0.292 0.954 0.292 0.951 0.293 C 0.948 0.294 0.948 0.295 0.949 0.298 C 0.950 0.299 0.951 0.300 0.953 0.298 Z  M 0.947 0.299 C 0.947 0.298 0.947 0.298 0.946 0.299 C 0.944 0.300 0.944 0.301 0.945 0.301 C 0.946 0.301 0.947 0.300 0.947 0.299 Z  M 0.039 0.304 C 0.039 0.303 0.039 0.302 0.038 0.301 C 0.038 0.301 0.038 0.302 0.038 0.304 C 0.038 0.307 0.039 0.307 0.039 0.304 Z  M 0.051 0.332 C 0.051 0.331 0.051 0.331 0.050 0.332 C 0.050 0.332 0.050 0.333 0.051 0.333 C 0.051 0.333 0.051 0.332 0.051 0.332 Z  M 0.945 0.333 C 0.946 0.331 0.945 0.331 0.944 0.332 C 0.942 0.334 0.942 0.335 0.943 0.335 C 0.944 0.334 0.945 0.334 0.945 0.333 Z  M 0.948 0.335 C 0.950 0.333 0.950 0.333 0.949 0.333 C 0.948 0.333 0.947 0.333 0.947 0.332 C 0.947 0.332 0.947 0.333 0.947 0.334 C 0.947 0.337 0.947 0.337 0.948 0.335 Z  M 0.040 0.350 C 0.041 0.349 0.041 0.349 0.040 0.349 C 0.039 0.349 0.039 0.349 0.039 0.350 C 0.038 0.353 0.039 0.353 0.040 0.350 Z  M 0.930 0.351 C 0.930 0.350 0.930 0.350 0.930 0.351 C 0.929 0.351 0.929 0.352 0.930 0.352 C 0.930 0.352 0.931 0.352 0.930 0.351 Z  M 0.042 0.356 C 0.041 0.356 0.041 0.356 0.040 0.356 C 0.040 0.357 0.040 0.357 0.041 0.357 C 0.042 0.357 0.042 0.357 0.042 0.356 Z  M 0.897 0.381 C 0.897 0.380 0.897 0.380 0.896 0.381 C 0.896 0.381 0.896 0.382 0.897 0.382 C 0.897 0.382 0.897 0.382 0.897 0.381 Z  M 0.047 0.386 C 0.047 0.385 0.047 0.384 0.047 0.384 C 0.047 0.384 0.046 0.385 0.046 0.386 C 0.046 0.387 0.046 0.387 0.046 0.387 C 0.047 0.387 0.047 0.387 0.047 0.386 Z  M 0.057 0.388 C 0.056 0.387 0.056 0.387 0.056 0.388 C 0.055 0.388 0.055 0.389 0.056 0.389 C 0.056 0.389 0.057 0.389 0.057 0.388 Z  M 0.059 0.388 C 0.059 0.387 0.058 0.387 0.058 0.388 C 0.057 0.388 0.057 0.389 0.058 0.389 C 0.059 0.389 0.059 0.388 0.059 0.388 Z  M 0.046 0.391 C 0.046 0.390 0.046 0.389 0.045 0.389 C 0.045 0.389 0.045 0.390 0.045 0.391 C 0.045 0.392 0.045 0.393 0.045 0.393 C 0.046 0.393 0.046 0.392 0.046 0.391 Z  M 0.918 0.400 C 0.918 0.399 0.918 0.398 0.918 0.397 C 0.917 0.396 0.916 0.398 0.916 0.400 C 0.917 0.402 0.918 0.402 0.918 0.400 Z  M 0.929 0.413 C 0.928 0.412 0.928 0.412 0.928 0.413 C 0.927 0.413 0.928 0.414 0.928 0.414 C 0.929 0.414 0.929 0.413 0.929 0.413 Z  M 0.903 0.443 C 0.903 0.442 0.902 0.442 0.902 0.442 C 0.902 0.443 0.902 0.443 0.903 0.443 C 0.903 0.443 0.904 0.443 0.903 0.443 Z  M 0.935 0.455 C 0.935 0.453 0.929 0.452 0.929 0.454 C 0.929 0.455 0.930 0.456 0.932 0.456 C 0.933 0.456 0.935 0.455 0.935 0.455 Z  M 0.985 0.467 C 0.984 0.467 0.984 0.467 0.984 0.467 C 0.983 0.468 0.984 0.468 0.984 0.468 C 0.985 0.468 0.985 0.468 0.985 0.467 Z  M 0.988 0.467 C 0.988 0.466 0.987 0.466 0.987 0.466 C 0.986 0.467 0.986 0.468 0.987 0.468 C 0.988 0.468 0.988 0.468 0.988 0.467 Z  M 0.994 0.467 C 0.995 0.465 0.994 0.465 0.992 0.465 C 0.991 0.465 0.990 0.465 0.991 0.467 C 0.992 0.468 0.992 0.468 0.994 0.467 Z  M 0.068 0.481 C 0.068 0.481 0.068 0.481 0.067 0.481 C 0.067 0.482 0.067 0.482 0.068 0.482 C 0.068 0.482 0.068 0.482 0.068 0.481 Z  M 0.976 0.482 C 0.976 0.480 0.972 0.479 0.970 0.481 C 0.969 0.482 0.969 0.483 0.969 0.483 C 0.969 0.485 0.975 0.484 0.976 0.482 Z  M 0.954 0.489 C 0.954 0.489 0.953 0.488 0.952 0.488 C 0.952 0.488 0.952 0.489 0.953 0.489 C 0.953 0.490 0.954 0.491 0.954 0.491 C 0.955 0.491 0.955 0.490 0.954 0.489 Z  M 0.945 0.510 C 0.947 0.508 0.946 0.505 0.944 0.506 C 0.942 0.507 0.941 0.507 0.940 0.507 C 0.939 0.507 0.937 0.510 0.938 0.511 C 0.940 0.512 0.944 0.511 0.945 0.510 Z  M 0.975 0.511 C 0.975 0.509 0.975 0.509 0.975 0.510 C 0.975 0.511 0.975 0.512 0.976 0.512 C 0.978 0.512 0.979 0.509 0.977 0.509 C 0.976 0.509 0.976 0.508 0.976 0.507 C 0.976 0.506 0.974 0.504 0.972 0.503 C 0.971 0.503 0.971 0.502 0.971 0.502 C 0.971 0.501 0.969 0.501 0.967 0.501 C 0.965 0.501 0.963 0.501 0.963 0.502 C 0.963 0.503 0.963 0.503 0.962 0.503 C 0.961 0.501 0.961 0.501 0.957 0.503 C 0.956 0.503 0.954 0.504 0.952 0.504 C 0.951 0.504 0.950 0.504 0.950 0.505 C 0.950 0.506 0.950 0.507 0.950 0.506 C 0.949 0.505 0.947 0.507 0.947 0.509 C 0.947 0.509 0.950 0.510 0.954 0.510 C 0.959 0.510 0.962 0.510 0.962 0.512 C 0.963 0.514 0.964 0.514 0.968 0.514 C 0.973 0.514 0.974 0.513 0.975 0.511 Z  M 0.075 0.519 C 0.075 0.518 0.074 0.518 0.074 0.518 C 0.074 0.518 0.074 0.518 0.073 0.519 C 0.073 0.520 0.074 0.521 0.074 0.521 C 0.074 0.521 0.075 0.520 0.075 0.519 Z  M 0.937 0.528 C 0.938 0.527 0.938 0.526 0.937 0.526 C 0.937 0.526 0.937 0.527 0.937 0.528 C 0.937 0.529 0.937 0.530 0.937 0.530 C 0.937 0.530 0.937 0.529 0.937 0.528 Z  M 0.940 0.528 C 0.941 0.527 0.941 0.527 0.940 0.527 C 0.939 0.526 0.939 0.527 0.938 0.528 C 0.938 0.530 0.938 0.530 0.940 0.528 Z  M 0.942 0.530 C 0.942 0.529 0.942 0.528 0.942 0.528 C 0.941 0.528 0.941 0.529 0.941 0.529 C 0.941 0.529 0.941 0.530 0.942 0.531 C 0.942 0.531 0.942 0.531 0.942 0.530 Z  M 0.955 0.530 C 0.955 0.529 0.955 0.529 0.956 0.529 C 0.957 0.530 0.958 0.530 0.958 0.529 C 0.957 0.526 0.947 0.526 0.947 0.528 C 0.947 0.529 0.948 0.530 0.949 0.530 C 0.953 0.531 0.955 0.531 0.955 0.530 Z  M 0.929 0.532 C 0.929 0.530 0.929 0.530 0.930 0.531 C 0.931 0.532 0.932 0.531 0.932 0.530 C 0.932 0.529 0.931 0.528 0.930 0.528 C 0.929 0.528 0.928 0.528 0.928 0.527 C 0.927 0.526 0.927 0.526 0.928 0.529 C 0.928 0.530 0.928 0.532 0.928 0.532 C 0.928 0.533 0.928 0.533 0.928 0.533 C 0.929 0.533 0.929 0.533 0.929 0.532 Z  M 0.958 0.535 C 0.958 0.534 0.958 0.533 0.957 0.533 C 0.957 0.532 0.957 0.533 0.957 0.534 C 0.957 0.535 0.958 0.536 0.958 0.535 Z  M 0.968 0.543 C 0.968 0.543 0.968 0.542 0.967 0.542 C 0.967 0.541 0.967 0.542 0.967 0.542 C 0.967 0.544 0.968 0.545 0.968 0.543 Z  M 0.976 0.555 C 0.976 0.554 0.976 0.553 0.976 0.554 C 0.975 0.555 0.975 0.554 0.975 0.553 C 0.975 0.553 0.974 0.552 0.974 0.552 C 0.973 0.552 0.973 0.552 0.973 0.553 C 0.973 0.554 0.972 0.554 0.972 0.553 C 0.972 0.551 0.971 0.551 0.971 0.553 C 0.970 0.554 0.970 0.555 0.971 0.555 C 0.975 0.556 0.976 0.556 0.976 0.555 Z  M 0.988 0.555 C 0.989 0.554 0.989 0.554 0.990 0.554 C 0.990 0.555 0.990 0.555 0.990 0.553 C 0.989 0.551 0.987 0.552 0.987 0.555 C 0.987 0.557 0.988 0.557 0.988 0.555 Z  M 0.987 0.556 C 0.987 0.555 0.987 0.555 0.986 0.554 C 0.986 0.554 0.986 0.554 0.986 0.553 C 0.987 0.552 0.987 0.551 0.986 0.551 C 0.985 0.550 0.984 0.551 0.983 0.551 C 0.982 0.552 0.981 0.552 0.981 0.551 C 0.980 0.550 0.980 0.549 0.979 0.549 C 0.979 0.550 0.979 0.551 0.980 0.552 L 0.981 0.555 L 0.980 0.554 C 0.979 0.554 0.979 0.554 0.979 0.555 C 0.980 0.558 0.984 0.557 0.984 0.555 C 0.984 0.554 0.984 0.553 0.984 0.553 C 0.985 0.553 0.985 0.554 0.985 0.554 C 0.984 0.555 0.985 0.556 0.985 0.557 C 0.986 0.559 0.987 0.558 0.987 0.556 Z  M 0.924 0.559 C 0.924 0.558 0.923 0.558 0.923 0.559 C 0.922 0.559 0.922 0.560 0.923 0.560 C 0.924 0.560 0.924 0.559 0.924 0.559 Z  M 0.928 0.599 C 0.929 0.598 0.930 0.597 0.930 0.598 C 0.932 0.599 0.932 0.599 0.931 0.597 C 0.929 0.595 0.926 0.596 0.926 0.599 C 0.925 0.601 0.927 0.601 0.928 0.599 Z  M 0.937 0.599 C 0.938 0.598 0.938 0.597 0.936 0.596 C 0.935 0.596 0.934 0.596 0.934 0.597 C 0.933 0.598 0.933 0.599 0.934 0.598 C 0.935 0.597 0.935 0.597 0.936 0.598 C 0.936 0.599 0.937 0.599 0.937 0.599 Z  M 0.960 0.622 C 0.960 0.622 0.960 0.622 0.960 0.622 C 0.959 0.623 0.959 0.623 0.960 0.623 C 0.960 0.623 0.961 0.623 0.960 0.622 Z  M 0.957 0.627 C 0.958 0.625 0.958 0.625 0.958 0.625 C 0.957 0.625 0.956 0.626 0.956 0.627 C 0.956 0.628 0.956 0.628 0.956 0.628 C 0.956 0.628 0.957 0.628 0.957 0.627 Z  M 0.987 0.649 C 0.987 0.648 0.986 0.648 0.986 0.648 C 0.986 0.649 0.986 0.649 0.986 0.650 C 0.987 0.650 0.987 0.649 0.987 0.649 Z  M 0.986 0.661 C 0.985 0.660 0.985 0.660 0.985 0.661 C 0.984 0.661 0.985 0.662 0.985 0.662 C 0.986 0.662 0.986 0.661 0.986 0.661 Z  M 0.993 0.685 C 0.993 0.684 0.993 0.683 0.991 0.683 C 0.990 0.683 0.989 0.684 0.989 0.685 C 0.988 0.687 0.991 0.687 0.993 0.685 Z  M 0.994 0.713 C 0.994 0.713 0.994 0.712 0.993 0.712 C 0.993 0.712 0.992 0.713 0.992 0.713 C 0.992 0.714 0.993 0.715 0.993 0.715 C 0.993 0.715 0.994 0.714 0.994 0.713 Z  M 0.969 0.720 C 0.970 0.719 0.970 0.719 0.969 0.719 C 0.968 0.719 0.967 0.720 0.967 0.720 C 0.967 0.722 0.968 0.722 0.969 0.720 Z  M 0.989 0.718 C 0.990 0.715 0.990 0.715 0.989 0.715 C 0.988 0.715 0.988 0.716 0.988 0.717 C 0.988 0.718 0.988 0.718 0.988 0.717 C 0.987 0.717 0.987 0.717 0.987 0.718 C 0.987 0.719 0.986 0.720 0.986 0.721 C 0.985 0.721 0.985 0.721 0.986 0.722 C 0.988 0.722 0.988 0.721 0.989 0.718 Z  M 0.996 0.722 C 0.995 0.720 0.995 0.720 0.995 0.720 C 0.996 0.720 0.996 0.720 0.996 0.718 C 0.995 0.716 0.995 0.716 0.995 0.718 C 0.994 0.720 0.994 0.720 0.993 0.720 C 0.992 0.719 0.992 0.719 0.992 0.720 C 0.992 0.720 0.993 0.721 0.993 0.722 C 0.993 0.722 0.994 0.723 0.994 0.723 C 0.996 0.723 0.996 0.723 0.996 0.722 L 0.996 0.722 Z  M 0.968 0.726 C 0.968 0.724 0.972 0.720 0.972 0.722 C 0.971 0.724 0.972 0.725 0.974 0.724 C 0.975 0.724 0.976 0.724 0.977 0.724 C 0.978 0.723 0.978 0.723 0.977 0.722 C 0.977 0.721 0.975 0.720 0.974 0.720 C 0.973 0.719 0.972 0.719 0.972 0.718 C 0.971 0.716 0.970 0.716 0.970 0.719 C 0.970 0.721 0.967 0.725 0.965 0.725 C 0.965 0.725 0.964 0.725 0.965 0.724 C 0.966 0.722 0.965 0.722 0.964 0.722 C 0.963 0.722 0.963 0.723 0.963 0.725 C 0.963 0.726 0.963 0.727 0.964 0.727 C 0.964 0.727 0.964 0.726 0.964 0.725 C 0.964 0.723 0.964 0.723 0.964 0.725 C 0.965 0.727 0.967 0.728 0.968 0.726 Z  M 0.970 0.726 C 0.970 0.725 0.970 0.725 0.969 0.726 C 0.969 0.727 0.969 0.727 0.970 0.727 C 0.970 0.727 0.970 0.727 0.970 0.726 Z  M 0.953 0.731 C 0.953 0.731 0.952 0.731 0.952 0.731 C 0.952 0.732 0.952 0.732 0.952 0.732 C 0.953 0.732 0.953 0.732 0.953 0.731 Z  M 0.983 0.732 C 0.983 0.731 0.983 0.731 0.982 0.731 C 0.982 0.731 0.981 0.731 0.981 0.732 C 0.981 0.735 0.982 0.735 0.983 0.732 Z  M 0.985 0.733 C 0.984 0.733 0.984 0.732 0.984 0.733 C 0.983 0.734 0.984 0.734 0.984 0.734 C 0.985 0.734 0.985 0.734 0.985 0.733 Z  M 0.968 0.735 C 0.968 0.734 0.967 0.734 0.967 0.735 C 0.967 0.735 0.967 0.736 0.968 0.736 C 0.968 0.736 0.969 0.735 0.968 0.735 Z  M 0.975 0.735 C 0.975 0.734 0.974 0.734 0.974 0.735 C 0.974 0.735 0.974 0.736 0.974 0.736 C 0.975 0.736 0.975 0.735 0.975 0.735 Z  M 0.998 0.736 C 0.998 0.735 0.998 0.735 0.997 0.735 C 0.996 0.736 0.996 0.738 0.997 0.738 C 0.997 0.738 0.997 0.737 0.998 0.736 Z  M 0.975 0.743 C 0.975 0.741 0.969 0.743 0.968 0.744 C 0.968 0.745 0.970 0.745 0.972 0.745 C 0.974 0.744 0.975 0.744 0.975 0.743 Z  M 0.981 0.744 C 0.981 0.743 0.980 0.743 0.980 0.744 C 0.980 0.744 0.980 0.744 0.981 0.744 C 0.981 0.744 0.982 0.744 0.981 0.744 Z  M 1.000 0.820 C 1.000 0.819 1.000 0.819 0.999 0.818 C 0.999 0.818 0.998 0.818 0.998 0.819 C 0.999 0.820 1.000 0.821 1.000 0.820 Z  M 0.998 0.849 C 0.999 0.847 0.999 0.847 0.998 0.847 C 0.998 0.847 0.997 0.848 0.997 0.849 C 0.996 0.851 0.997 0.851 0.998 0.849 Z  M 0.992 0.884 C 0.992 0.883 0.991 0.882 0.991 0.882 C 0.990 0.882 0.990 0.882 0.991 0.884 C 0.991 0.886 0.992 0.886 0.992 0.884 Z  M 0.979 0.904 C 0.979 0.903 0.978 0.903 0.978 0.904 C 0.978 0.904 0.978 0.905 0.978 0.905 C 0.979 0.905 0.979 0.904 0.979 0.904 Z  M 0.135 0.953 C 0.135 0.952 0.134 0.951 0.134 0.951 C 0.134 0.951 0.134 0.952 0.134 0.953 C 0.134 0.953 0.134 0.954 0.134 0.954 C 0.134 0.954 0.135 0.953 0.135 0.953 Z  M 0.095 0.965 C 0.095 0.964 0.095 0.963 0.095 0.963 C 0.094 0.963 0.094 0.964 0.095 0.965 C 0.095 0.966 0.095 0.967 0.095 0.967 C 0.096 0.967 0.096 0.966 0.095 0.965 Z  M 0.500 0.974 C 0.501 0.973 0.501 0.972 0.500 0.972 C 0.500 0.972 0.499 0.973 0.499 0.974 C 0.498 0.975 0.498 0.975 0.499 0.975 C 0.499 0.975 0.500 0.974 0.500 0.974 Z  M 0.647 0.052 C 0.648 0.051 0.648 0.051 0.648 0.052 C 0.648 0.052 0.648 0.053 0.648 0.053 C 0.647 0.053 0.647 0.052 0.647 0.052 Z  M 0.646 0.062 C 0.646 0.058 0.647 0.057 0.647 0.061 C 0.647 0.063 0.647 0.065 0.646 0.065 C 0.645 0.065 0.645 0.064 0.646 0.062 L 0.646 0.062 Z  M 0.644 0.070 C 0.645 0.069 0.645 0.069 0.645 0.069 C 0.645 0.069 0.646 0.069 0.646 0.070 C 0.646 0.071 0.645 0.072 0.645 0.072 C 0.644 0.072 0.644 0.071 0.644 0.070 Z  M 0.646 0.069 C 0.646 0.067 0.647 0.067 0.647 0.069 C 0.648 0.070 0.648 0.071 0.648 0.072 C 0.648 0.072 0.648 0.072 0.647 0.072 C 0.647 0.072 0.646 0.071 0.646 0.069 Z  M 0.536 0.076 C 0.536 0.075 0.536 0.074 0.536 0.074 C 0.536 0.074 0.537 0.075 0.537 0.076 C 0.537 0.077 0.537 0.077 0.537 0.077 C 0.536 0.077 0.536 0.077 0.536 0.076 Z  M 0.586 0.076 C 0.586 0.075 0.586 0.074 0.587 0.074 C 0.587 0.074 0.588 0.075 0.587 0.076 C 0.587 0.077 0.587 0.077 0.587 0.077 C 0.587 0.077 0.586 0.077 0.586 0.076 Z  M 0.599 0.076 C 0.599 0.075 0.600 0.074 0.600 0.074 C 0.600 0.074 0.600 0.075 0.600 0.076 C 0.600 0.077 0.600 0.077 0.600 0.077 C 0.600 0.077 0.599 0.077 0.599 0.076 Z  M 0.632 0.076 C 0.632 0.075 0.633 0.074 0.633 0.074 C 0.633 0.074 0.633 0.075 0.633 0.076 C 0.633 0.077 0.633 0.077 0.632 0.077 C 0.632 0.077 0.632 0.077 0.632 0.076 Z  M 0.645 0.077 C 0.645 0.075 0.645 0.074 0.646 0.074 C 0.646 0.074 0.646 0.075 0.645 0.077 C 0.644 0.080 0.644 0.080 0.645 0.077 Z  M 0.592 0.079 C 0.592 0.078 0.592 0.077 0.593 0.077 C 0.593 0.077 0.593 0.078 0.593 0.079 C 0.593 0.080 0.593 0.081 0.593 0.081 C 0.592 0.081 0.592 0.080 0.592 0.079 Z  M 0.616 0.079 C 0.616 0.078 0.616 0.077 0.617 0.078 C 0.618 0.079 0.619 0.078 0.619 0.077 C 0.620 0.075 0.620 0.075 0.619 0.078 C 0.618 0.081 0.617 0.082 0.616 0.079 Z  M 0.611 0.082 C 0.611 0.081 0.612 0.081 0.612 0.082 C 0.612 0.082 0.612 0.083 0.611 0.083 C 0.611 0.083 0.611 0.082 0.611 0.082 Z  M 0.588 0.085 C 0.588 0.084 0.588 0.083 0.589 0.083 C 0.589 0.083 0.589 0.084 0.589 0.085 C 0.589 0.085 0.589 0.086 0.589 0.086 C 0.588 0.086 0.588 0.085 0.588 0.085 Z  M 0.601 0.084 C 0.601 0.083 0.601 0.083 0.602 0.083 C 0.602 0.083 0.602 0.084 0.602 0.085 C 0.602 0.086 0.602 0.086 0.602 0.085 C 0.601 0.085 0.601 0.084 0.601 0.084 Z  M 0.620 0.085 C 0.620 0.084 0.620 0.083 0.620 0.083 C 0.620 0.083 0.620 0.082 0.621 0.082 C 0.621 0.081 0.621 0.081 0.621 0.083 C 0.621 0.087 0.620 0.087 0.620 0.085 Z  M 0.639 0.083 C 0.639 0.083 0.639 0.084 0.639 0.086 C 0.639 0.088 0.639 0.088 0.639 0.087 C 0.639 0.085 0.639 0.084 0.639 0.083 Z  M 0.651 0.090 C 0.651 0.089 0.652 0.088 0.652 0.088 C 0.652 0.088 0.652 0.089 0.652 0.090 C 0.652 0.091 0.652 0.092 0.651 0.092 C 0.651 0.092 0.651 0.091 0.651 0.090 Z  M 0.654 0.090 C 0.654 0.089 0.654 0.088 0.655 0.088 C 0.655 0.088 0.655 0.089 0.655 0.090 C 0.655 0.091 0.654 0.092 0.654 0.092 C 0.654 0.092 0.654 0.091 0.654 0.090 Z  M 0.550 0.091 C 0.551 0.089 0.551 0.088 0.551 0.088 C 0.551 0.088 0.551 0.089 0.551 0.091 C 0.551 0.092 0.550 0.093 0.550 0.093 C 0.550 0.093 0.550 0.092 0.550 0.091 Z  M 0.553 0.091 C 0.553 0.090 0.553 0.090 0.553 0.090 C 0.554 0.091 0.554 0.091 0.554 0.090 C 0.554 0.089 0.555 0.088 0.555 0.089 C 0.556 0.090 0.556 0.091 0.555 0.092 C 0.553 0.093 0.553 0.093 0.553 0.091 Z  M 0.573 0.089 C 0.573 0.087 0.573 0.086 0.573 0.085 C 0.574 0.084 0.573 0.081 0.573 0.081 C 0.572 0.081 0.572 0.080 0.572 0.080 C 0.572 0.076 0.573 0.076 0.573 0.079 C 0.574 0.082 0.575 0.094 0.574 0.092 C 0.573 0.092 0.573 0.090 0.573 0.089 Z  M 0.583 0.088 C 0.583 0.086 0.583 0.083 0.583 0.081 C 0.582 0.080 0.582 0.078 0.583 0.078 C 0.583 0.077 0.582 0.076 0.582 0.075 C 0.581 0.075 0.582 0.074 0.583 0.075 C 0.584 0.075 0.584 0.075 0.584 0.079 C 0.584 0.081 0.584 0.083 0.585 0.083 C 0.585 0.083 0.585 0.084 0.584 0.086 C 0.584 0.088 0.583 0.090 0.583 0.091 C 0.583 0.092 0.583 0.093 0.583 0.093 C 0.583 0.093 0.583 0.091 0.583 0.088 Z  M 0.588 0.092 C 0.588 0.091 0.588 0.090 0.589 0.090 C 0.589 0.090 0.589 0.091 0.589 0.092 C 0.589 0.093 0.589 0.093 0.589 0.093 C 0.589 0.093 0.589 0.093 0.588 0.092 Z  M 0.527 0.090 C 0.527 0.088 0.527 0.086 0.528 0.086 C 0.528 0.086 0.528 0.089 0.528 0.091 C 0.527 0.091 0.527 0.093 0.527 0.094 C 0.528 0.095 0.528 0.095 0.527 0.094 C 0.527 0.094 0.527 0.092 0.527 0.090 Z  M 0.588 0.097 C 0.588 0.097 0.589 0.097 0.589 0.098 C 0.589 0.098 0.589 0.099 0.588 0.098 C 0.588 0.098 0.588 0.098 0.588 0.097 Z  M 0.596 0.089 C 0.596 0.088 0.597 0.086 0.596 0.086 C 0.596 0.085 0.596 0.085 0.597 0.085 C 0.597 0.085 0.597 0.086 0.597 0.087 C 0.597 0.088 0.598 0.090 0.599 0.090 C 0.600 0.091 0.600 0.090 0.600 0.088 C 0.600 0.087 0.600 0.087 0.601 0.087 C 0.601 0.088 0.601 0.090 0.601 0.092 C 0.600 0.096 0.600 0.096 0.599 0.096 C 0.598 0.095 0.598 0.095 0.598 0.097 C 0.598 0.098 0.598 0.097 0.597 0.095 C 0.596 0.092 0.596 0.090 0.596 0.089 Z  M 0.576 0.099 C 0.576 0.098 0.576 0.097 0.576 0.097 C 0.577 0.097 0.577 0.095 0.577 0.094 C 0.577 0.092 0.577 0.092 0.577 0.096 C 0.578 0.100 0.577 0.102 0.576 0.099 Z  M 0.579 0.098 C 0.579 0.098 0.579 0.097 0.579 0.097 C 0.580 0.097 0.580 0.096 0.579 0.095 C 0.579 0.094 0.579 0.085 0.579 0.085 C 0.580 0.085 0.580 0.083 0.580 0.082 C 0.581 0.080 0.581 0.079 0.582 0.080 C 0.582 0.081 0.582 0.082 0.582 0.084 C 0.582 0.085 0.581 0.086 0.582 0.086 C 0.582 0.086 0.582 0.088 0.581 0.091 C 0.581 0.094 0.581 0.095 0.582 0.096 C 0.584 0.098 0.583 0.100 0.581 0.100 C 0.580 0.100 0.579 0.099 0.579 0.098 Z  M 0.606 0.099 C 0.606 0.099 0.606 0.097 0.606 0.095 C 0.605 0.094 0.605 0.091 0.605 0.089 C 0.606 0.088 0.605 0.086 0.605 0.086 C 0.605 0.086 0.605 0.085 0.605 0.084 C 0.606 0.081 0.606 0.081 0.605 0.081 C 0.605 0.081 0.604 0.082 0.604 0.083 C 0.604 0.085 0.604 0.085 0.603 0.083 C 0.603 0.081 0.602 0.081 0.601 0.082 C 0.600 0.083 0.600 0.082 0.601 0.077 C 0.601 0.075 0.602 0.074 0.602 0.075 C 0.602 0.077 0.602 0.077 0.602 0.077 C 0.603 0.077 0.603 0.077 0.603 0.076 C 0.602 0.073 0.606 0.075 0.607 0.078 C 0.608 0.082 0.609 0.080 0.609 0.076 C 0.609 0.072 0.609 0.071 0.611 0.075 L 0.613 0.077 L 0.611 0.079 C 0.611 0.080 0.610 0.081 0.610 0.081 C 0.609 0.081 0.609 0.082 0.609 0.082 C 0.610 0.085 0.609 0.090 0.608 0.089 C 0.607 0.089 0.606 0.096 0.607 0.099 C 0.607 0.100 0.607 0.100 0.606 0.100 C 0.606 0.100 0.605 0.100 0.606 0.099 Z  M 0.653 0.099 C 0.653 0.098 0.653 0.097 0.654 0.097 C 0.654 0.097 0.654 0.098 0.654 0.099 C 0.654 0.100 0.653 0.100 0.653 0.100 C 0.653 0.100 0.653 0.100 0.653 0.099 Z  M 0.593 0.100 C 0.593 0.100 0.593 0.100 0.593 0.098 C 0.594 0.095 0.593 0.093 0.592 0.093 C 0.591 0.093 0.591 0.093 0.592 0.091 C 0.592 0.090 0.592 0.088 0.592 0.086 C 0.592 0.084 0.593 0.083 0.593 0.082 C 0.594 0.081 0.594 0.082 0.594 0.086 C 0.594 0.088 0.594 0.090 0.594 0.090 C 0.594 0.090 0.594 0.091 0.594 0.093 C 0.594 0.096 0.594 0.097 0.595 0.098 C 0.596 0.099 0.595 0.102 0.595 0.101 C 0.594 0.101 0.593 0.101 0.593 0.100 Z  M 0.596 0.099 C 0.596 0.099 0.596 0.099 0.596 0.099 C 0.596 0.099 0.597 0.099 0.597 0.100 C 0.597 0.101 0.596 0.102 0.596 0.101 C 0.596 0.101 0.596 0.100 0.596 0.099 Z  M 0.616 0.101 C 0.615 0.099 0.614 0.100 0.614 0.101 C 0.614 0.102 0.614 0.101 0.614 0.099 C 0.614 0.095 0.614 0.093 0.613 0.091 C 0.611 0.087 0.611 0.084 0.613 0.086 C 0.613 0.086 0.615 0.087 0.616 0.087 C 0.618 0.087 0.619 0.090 0.618 0.094 C 0.618 0.095 0.618 0.098 0.618 0.099 C 0.618 0.103 0.618 0.103 0.616 0.101 Z  M 0.632 0.100 C 0.632 0.098 0.631 0.097 0.631 0.098 C 0.630 0.099 0.628 0.097 0.628 0.095 C 0.628 0.094 0.628 0.093 0.628 0.093 C 0.628 0.093 0.628 0.093 0.628 0.092 C 0.629 0.090 0.629 0.087 0.627 0.087 C 0.626 0.087 0.625 0.090 0.626 0.090 C 0.627 0.090 0.627 0.091 0.626 0.092 C 0.626 0.094 0.625 0.095 0.625 0.095 C 0.625 0.095 0.624 0.094 0.624 0.092 C 0.624 0.090 0.624 0.090 0.624 0.090 C 0.625 0.090 0.625 0.089 0.625 0.087 C 0.625 0.086 0.625 0.085 0.625 0.085 C 0.624 0.085 0.622 0.097 0.622 0.099 C 0.622 0.101 0.622 0.101 0.620 0.101 C 0.619 0.102 0.619 0.101 0.619 0.098 C 0.619 0.094 0.619 0.094 0.620 0.094 C 0.620 0.095 0.620 0.094 0.620 0.092 C 0.620 0.090 0.621 0.088 0.621 0.088 C 0.621 0.088 0.622 0.087 0.622 0.085 C 0.622 0.084 0.623 0.082 0.623 0.082 C 0.624 0.082 0.624 0.080 0.624 0.078 C 0.624 0.075 0.624 0.075 0.624 0.078 C 0.625 0.080 0.625 0.080 0.626 0.080 C 0.627 0.079 0.627 0.079 0.628 0.080 C 0.629 0.082 0.629 0.082 0.630 0.083 C 0.630 0.083 0.631 0.084 0.631 0.085 C 0.631 0.086 0.631 0.086 0.630 0.086 C 0.630 0.085 0.630 0.086 0.630 0.087 C 0.630 0.089 0.630 0.090 0.631 0.091 C 0.631 0.091 0.631 0.090 0.631 0.089 C 0.631 0.087 0.631 0.086 0.631 0.086 C 0.633 0.086 0.634 0.089 0.633 0.092 C 0.633 0.094 0.633 0.095 0.633 0.099 C 0.633 0.103 0.632 0.103 0.632 0.100 Z  M 0.542 0.101 C 0.543 0.097 0.543 0.098 0.543 0.102 C 0.543 0.105 0.543 0.105 0.542 0.104 C 0.542 0.103 0.542 0.102 0.542 0.101 Z  M 0.605 0.104 C 0.605 0.103 0.605 0.102 0.606 0.102 C 0.606 0.102 0.606 0.103 0.606 0.104 C 0.606 0.105 0.606 0.106 0.606 0.106 C 0.605 0.106 0.605 0.105 0.605 0.104 Z  M 0.650 0.104 C 0.650 0.103 0.650 0.102 0.650 0.101 C 0.651 0.101 0.651 0.102 0.651 0.103 C 0.651 0.104 0.651 0.106 0.650 0.106 C 0.650 0.106 0.650 0.105 0.650 0.104 Z  M 0.573 0.106 C 0.573 0.105 0.574 0.104 0.574 0.104 C 0.574 0.104 0.574 0.105 0.574 0.106 C 0.574 0.107 0.574 0.107 0.574 0.107 C 0.574 0.107 0.573 0.107 0.573 0.106 Z  M 0.600 0.104 C 0.599 0.100 0.600 0.099 0.601 0.099 C 0.601 0.099 0.601 0.099 0.601 0.100 C 0.600 0.101 0.600 0.102 0.601 0.103 C 0.601 0.105 0.601 0.107 0.601 0.107 C 0.600 0.107 0.600 0.106 0.600 0.104 Z  M 0.551 0.105 C 0.550 0.101 0.550 0.100 0.550 0.100 C 0.551 0.100 0.553 0.107 0.552 0.108 C 0.552 0.110 0.552 0.109 0.551 0.105 Z  M 0.585 0.103 C 0.585 0.096 0.585 0.086 0.586 0.088 C 0.586 0.089 0.586 0.090 0.586 0.090 C 0.586 0.090 0.586 0.090 0.586 0.091 C 0.587 0.093 0.587 0.100 0.587 0.100 C 0.587 0.100 0.587 0.102 0.587 0.105 C 0.587 0.110 0.586 0.109 0.585 0.103 Z  M 0.444 0.110 C 0.444 0.109 0.444 0.109 0.445 0.110 C 0.445 0.110 0.445 0.111 0.444 0.111 C 0.444 0.111 0.443 0.110 0.444 0.110 Z  M 0.597 0.110 C 0.597 0.109 0.598 0.109 0.598 0.110 C 0.598 0.110 0.598 0.111 0.597 0.111 C 0.597 0.111 0.596 0.110 0.597 0.110 Z  M 0.589 0.111 C 0.589 0.110 0.589 0.109 0.589 0.109 C 0.588 0.108 0.588 0.107 0.588 0.107 C 0.588 0.106 0.589 0.106 0.589 0.107 C 0.590 0.108 0.590 0.108 0.589 0.110 C 0.589 0.112 0.589 0.113 0.588 0.113 C 0.588 0.113 0.588 0.112 0.589 0.111 Z  M 0.619 0.110 C 0.619 0.110 0.619 0.108 0.619 0.107 C 0.619 0.106 0.619 0.106 0.620 0.107 C 0.620 0.107 0.620 0.108 0.620 0.109 C 0.620 0.110 0.620 0.111 0.620 0.111 C 0.620 0.111 0.620 0.110 0.620 0.109 C 0.620 0.108 0.621 0.107 0.622 0.107 C 0.622 0.107 0.623 0.108 0.622 0.110 C 0.622 0.112 0.619 0.113 0.619 0.110 Z  M 0.604 0.112 C 0.604 0.111 0.604 0.111 0.605 0.111 C 0.605 0.111 0.605 0.112 0.605 0.113 C 0.605 0.114 0.605 0.114 0.605 0.114 C 0.604 0.113 0.604 0.112 0.604 0.112 Z  M 0.608 0.110 C 0.608 0.109 0.608 0.107 0.608 0.107 C 0.608 0.107 0.608 0.106 0.608 0.104 C 0.608 0.102 0.609 0.100 0.609 0.100 C 0.610 0.099 0.610 0.101 0.609 0.103 C 0.609 0.104 0.609 0.105 0.609 0.106 C 0.610 0.108 0.609 0.114 0.608 0.113 C 0.608 0.113 0.608 0.111 0.608 0.110 Z  M 0.261 0.115 C 0.261 0.114 0.262 0.115 0.262 0.115 C 0.262 0.116 0.262 0.116 0.261 0.116 C 0.261 0.116 0.261 0.116 0.261 0.115 Z  M 0.559 0.113 C 0.559 0.108 0.559 0.106 0.560 0.110 C 0.560 0.112 0.560 0.114 0.560 0.115 C 0.560 0.117 0.560 0.116 0.559 0.113 Z  M 0.639 0.106 C 0.639 0.101 0.639 0.100 0.638 0.101 C 0.637 0.102 0.637 0.102 0.637 0.099 C 0.637 0.096 0.637 0.096 0.636 0.098 C 0.636 0.101 0.636 0.106 0.637 0.106 C 0.637 0.106 0.637 0.107 0.637 0.110 C 0.637 0.114 0.637 0.115 0.636 0.116 C 0.635 0.116 0.635 0.116 0.636 0.114 C 0.637 0.112 0.637 0.107 0.636 0.107 C 0.636 0.107 0.636 0.108 0.636 0.109 C 0.636 0.110 0.635 0.111 0.635 0.110 C 0.634 0.109 0.634 0.110 0.634 0.110 C 0.635 0.113 0.634 0.116 0.633 0.114 C 0.632 0.114 0.632 0.113 0.632 0.113 C 0.633 0.113 0.633 0.110 0.632 0.106 C 0.632 0.105 0.632 0.104 0.633 0.104 C 0.633 0.104 0.633 0.105 0.633 0.106 C 0.633 0.109 0.634 0.107 0.635 0.103 C 0.636 0.099 0.636 0.099 0.635 0.096 C 0.635 0.094 0.634 0.093 0.635 0.093 C 0.635 0.093 0.635 0.093 0.635 0.092 C 0.635 0.090 0.635 0.090 0.636 0.092 C 0.637 0.094 0.637 0.094 0.637 0.091 C 0.637 0.089 0.638 0.088 0.638 0.088 C 0.638 0.088 0.638 0.089 0.638 0.090 C 0.638 0.092 0.639 0.093 0.641 0.093 C 0.643 0.093 0.643 0.092 0.643 0.090 C 0.643 0.089 0.643 0.088 0.642 0.089 C 0.642 0.090 0.641 0.089 0.641 0.088 C 0.641 0.087 0.642 0.086 0.642 0.086 C 0.644 0.086 0.644 0.083 0.643 0.082 C 0.642 0.082 0.643 0.081 0.643 0.081 C 0.644 0.081 0.645 0.082 0.644 0.083 C 0.644 0.085 0.645 0.090 0.647 0.092 C 0.648 0.094 0.647 0.098 0.646 0.098 C 0.645 0.097 0.645 0.098 0.645 0.098 C 0.645 0.098 0.645 0.100 0.646 0.102 C 0.648 0.106 0.648 0.109 0.647 0.109 C 0.646 0.109 0.646 0.108 0.646 0.105 C 0.646 0.102 0.646 0.102 0.645 0.104 C 0.645 0.105 0.645 0.107 0.645 0.108 C 0.645 0.110 0.645 0.110 0.644 0.110 C 0.644 0.109 0.643 0.108 0.643 0.106 C 0.644 0.105 0.643 0.103 0.643 0.103 C 0.643 0.102 0.642 0.101 0.643 0.099 C 0.643 0.096 0.642 0.095 0.640 0.097 C 0.639 0.099 0.639 0.099 0.640 0.098 C 0.642 0.097 0.642 0.099 0.640 0.102 C 0.640 0.103 0.639 0.105 0.639 0.105 C 0.640 0.106 0.640 0.105 0.640 0.104 C 0.641 0.102 0.642 0.103 0.642 0.106 C 0.642 0.107 0.642 0.107 0.642 0.107 C 0.641 0.106 0.640 0.107 0.640 0.108 C 0.640 0.110 0.640 0.111 0.640 0.111 C 0.641 0.111 0.641 0.112 0.640 0.114 C 0.639 0.116 0.639 0.116 0.639 0.114 C 0.638 0.112 0.638 0.109 0.639 0.106 Z  M 0.571 0.115 C 0.571 0.114 0.571 0.113 0.571 0.113 C 0.571 0.113 0.572 0.113 0.571 0.114 C 0.571 0.115 0.571 0.116 0.572 0.117 C 0.573 0.117 0.572 0.118 0.572 0.118 C 0.571 0.118 0.571 0.117 0.571 0.115 Z  M 0.609 0.117 C 0.609 0.114 0.610 0.114 0.610 0.117 C 0.611 0.118 0.610 0.119 0.609 0.119 C 0.608 0.119 0.608 0.119 0.609 0.117 Z  M 0.639 0.119 C 0.639 0.118 0.640 0.118 0.640 0.119 C 0.640 0.119 0.640 0.119 0.639 0.119 C 0.639 0.119 0.638 0.119 0.639 0.119 Z  M 0.641 0.118 C 0.641 0.117 0.641 0.116 0.641 0.116 C 0.642 0.115 0.642 0.116 0.642 0.117 C 0.642 0.119 0.642 0.120 0.641 0.120 C 0.641 0.120 0.641 0.119 0.641 0.118 Z  M 0.205 0.120 C 0.205 0.119 0.205 0.118 0.205 0.118 C 0.205 0.118 0.205 0.119 0.205 0.120 C 0.205 0.121 0.205 0.121 0.205 0.121 C 0.205 0.121 0.205 0.121 0.205 0.120 Z  M 0.705 0.120 C 0.705 0.119 0.705 0.118 0.706 0.118 C 0.706 0.119 0.706 0.119 0.706 0.120 C 0.706 0.122 0.705 0.122 0.705 0.120 Z  M 0.207 0.122 C 0.207 0.122 0.208 0.122 0.208 0.122 C 0.208 0.123 0.208 0.123 0.207 0.123 C 0.207 0.123 0.207 0.123 0.207 0.122 Z  M 0.220 0.121 C 0.220 0.121 0.220 0.120 0.221 0.120 C 0.221 0.120 0.221 0.120 0.221 0.121 C 0.220 0.124 0.220 0.124 0.220 0.121 Z  M 0.227 0.123 C 0.227 0.122 0.227 0.121 0.227 0.121 C 0.228 0.120 0.228 0.121 0.228 0.122 C 0.228 0.123 0.227 0.124 0.227 0.123 Z  M 0.234 0.120 C 0.234 0.117 0.234 0.116 0.235 0.116 C 0.235 0.116 0.235 0.117 0.235 0.117 C 0.235 0.118 0.235 0.120 0.235 0.121 C 0.235 0.122 0.235 0.123 0.235 0.123 C 0.235 0.123 0.235 0.122 0.234 0.120 Z  M 0.272 0.121 C 0.272 0.121 0.272 0.120 0.272 0.120 C 0.273 0.120 0.273 0.121 0.272 0.121 C 0.272 0.122 0.272 0.123 0.272 0.123 C 0.272 0.123 0.272 0.122 0.272 0.121 Z  M 0.590 0.121 C 0.590 0.119 0.591 0.118 0.591 0.117 C 0.592 0.117 0.592 0.117 0.592 0.120 C 0.592 0.122 0.591 0.123 0.591 0.123 C 0.591 0.123 0.590 0.122 0.590 0.121 Z  M 0.576 0.123 C 0.576 0.122 0.577 0.121 0.577 0.121 C 0.577 0.121 0.577 0.122 0.577 0.123 C 0.577 0.124 0.577 0.125 0.576 0.125 C 0.576 0.125 0.576 0.124 0.576 0.123 Z  M 0.588 0.122 C 0.588 0.121 0.589 0.120 0.589 0.120 C 0.590 0.120 0.590 0.120 0.589 0.122 C 0.588 0.125 0.587 0.125 0.588 0.122 Z  M 0.592 0.120 C 0.593 0.118 0.593 0.117 0.593 0.117 C 0.593 0.118 0.594 0.117 0.594 0.116 C 0.594 0.115 0.593 0.114 0.593 0.113 C 0.592 0.112 0.592 0.112 0.593 0.111 C 0.593 0.110 0.594 0.108 0.594 0.107 C 0.594 0.104 0.594 0.103 0.595 0.106 C 0.596 0.107 0.596 0.107 0.595 0.108 C 0.594 0.110 0.594 0.115 0.595 0.117 C 0.595 0.117 0.595 0.118 0.595 0.118 C 0.594 0.118 0.594 0.119 0.594 0.120 C 0.594 0.121 0.594 0.121 0.593 0.121 C 0.593 0.121 0.593 0.122 0.593 0.124 C 0.593 0.125 0.593 0.125 0.592 0.125 C 0.592 0.124 0.592 0.122 0.592 0.120 Z  M 0.199 0.126 C 0.198 0.124 0.198 0.121 0.199 0.122 C 0.200 0.122 0.200 0.122 0.200 0.123 C 0.199 0.123 0.199 0.124 0.199 0.125 C 0.200 0.127 0.200 0.127 0.199 0.126 Z  M 0.616 0.124 C 0.615 0.122 0.617 0.116 0.618 0.116 C 0.620 0.116 0.620 0.119 0.619 0.121 C 0.618 0.121 0.618 0.123 0.618 0.124 C 0.619 0.124 0.619 0.125 0.619 0.124 C 0.620 0.124 0.620 0.124 0.620 0.125 C 0.620 0.127 0.620 0.127 0.619 0.126 C 0.618 0.125 0.617 0.124 0.616 0.124 Z  M 0.623 0.116 C 0.623 0.115 0.623 0.114 0.623 0.114 C 0.623 0.114 0.623 0.115 0.623 0.116 C 0.623 0.117 0.623 0.118 0.623 0.118 C 0.623 0.118 0.623 0.117 0.623 0.116 Z  M 0.623 0.125 C 0.623 0.125 0.623 0.124 0.622 0.120 C 0.622 0.117 0.622 0.115 0.622 0.113 C 0.623 0.111 0.625 0.112 0.625 0.115 C 0.624 0.116 0.625 0.116 0.625 0.116 C 0.626 0.115 0.626 0.116 0.626 0.118 C 0.627 0.123 0.628 0.120 0.627 0.114 C 0.626 0.110 0.626 0.109 0.627 0.110 C 0.627 0.111 0.627 0.112 0.627 0.113 C 0.627 0.114 0.628 0.115 0.628 0.115 C 0.628 0.116 0.629 0.118 0.629 0.119 C 0.629 0.121 0.629 0.122 0.629 0.121 C 0.628 0.120 0.627 0.121 0.627 0.123 C 0.626 0.125 0.624 0.126 0.624 0.126 C 0.623 0.126 0.622 0.126 0.623 0.125 Z  M 0.628 0.125 C 0.627 0.123 0.628 0.123 0.629 0.125 C 0.630 0.126 0.630 0.127 0.629 0.127 C 0.628 0.127 0.628 0.126 0.628 0.125 Z  M 0.630 0.120 C 0.630 0.117 0.631 0.117 0.632 0.120 C 0.632 0.121 0.632 0.122 0.631 0.124 C 0.631 0.126 0.630 0.124 0.630 0.120 L 0.630 0.120 Z  M 0.584 0.126 C 0.584 0.126 0.583 0.125 0.583 0.123 C 0.583 0.121 0.584 0.120 0.584 0.120 C 0.584 0.120 0.584 0.119 0.584 0.118 C 0.583 0.116 0.583 0.116 0.584 0.116 C 0.584 0.116 0.584 0.116 0.584 0.115 C 0.583 0.113 0.583 0.112 0.584 0.110 C 0.584 0.109 0.585 0.107 0.585 0.107 C 0.585 0.107 0.586 0.108 0.585 0.110 C 0.584 0.112 0.584 0.115 0.585 0.113 C 0.585 0.113 0.585 0.113 0.585 0.116 C 0.585 0.119 0.585 0.120 0.586 0.120 C 0.586 0.120 0.586 0.120 0.585 0.122 C 0.585 0.123 0.585 0.123 0.586 0.123 C 0.587 0.122 0.587 0.122 0.587 0.126 C 0.587 0.128 0.587 0.128 0.586 0.127 C 0.585 0.126 0.585 0.125 0.584 0.126 Z  M 0.609 0.127 C 0.609 0.126 0.609 0.125 0.609 0.125 C 0.610 0.125 0.610 0.126 0.610 0.127 C 0.610 0.128 0.609 0.129 0.609 0.129 C 0.609 0.129 0.609 0.128 0.609 0.127 Z  M 0.588 0.129 C 0.588 0.128 0.588 0.127 0.588 0.127 C 0.589 0.127 0.589 0.128 0.589 0.129 C 0.589 0.129 0.589 0.130 0.588 0.130 C 0.588 0.130 0.588 0.129 0.588 0.129 Z  M 0.591 0.129 C 0.592 0.128 0.592 0.127 0.593 0.128 C 0.593 0.129 0.593 0.130 0.592 0.130 C 0.590 0.132 0.590 0.132 0.591 0.129 Z  M 0.703 0.130 C 0.703 0.128 0.702 0.126 0.702 0.125 C 0.701 0.123 0.700 0.116 0.701 0.116 C 0.701 0.116 0.701 0.117 0.701 0.118 C 0.701 0.119 0.701 0.120 0.701 0.119 C 0.702 0.118 0.702 0.118 0.703 0.119 C 0.704 0.120 0.705 0.124 0.704 0.129 C 0.704 0.133 0.703 0.133 0.703 0.130 Z  M 0.304 0.133 C 0.304 0.132 0.304 0.132 0.304 0.133 C 0.305 0.133 0.304 0.134 0.304 0.134 C 0.303 0.134 0.303 0.133 0.304 0.133 Z  M 0.578 0.130 C 0.578 0.128 0.579 0.127 0.579 0.127 C 0.580 0.127 0.580 0.127 0.579 0.125 C 0.579 0.123 0.579 0.123 0.580 0.124 C 0.580 0.125 0.580 0.124 0.580 0.121 C 0.580 0.119 0.580 0.118 0.581 0.119 C 0.581 0.120 0.581 0.121 0.581 0.123 C 0.581 0.125 0.581 0.127 0.582 0.127 C 0.582 0.128 0.582 0.128 0.581 0.127 C 0.580 0.127 0.579 0.128 0.579 0.130 C 0.578 0.135 0.577 0.135 0.578 0.130 L 0.578 0.130 Z  M 0.590 0.134 C 0.591 0.134 0.591 0.134 0.591 0.134 C 0.592 0.135 0.591 0.135 0.591 0.135 C 0.590 0.135 0.590 0.135 0.590 0.134 Z  M 0.598 0.129 C 0.598 0.129 0.598 0.127 0.598 0.126 C 0.597 0.125 0.597 0.126 0.597 0.129 C 0.597 0.131 0.597 0.131 0.598 0.129 Z  M 0.598 0.133 C 0.598 0.130 0.598 0.130 0.597 0.131 C 0.597 0.132 0.597 0.133 0.597 0.134 C 0.597 0.135 0.597 0.135 0.596 0.134 C 0.596 0.134 0.596 0.133 0.596 0.132 C 0.596 0.131 0.596 0.131 0.595 0.132 C 0.594 0.133 0.595 0.126 0.596 0.123 C 0.598 0.121 0.598 0.119 0.596 0.121 C 0.595 0.122 0.595 0.122 0.596 0.120 C 0.597 0.118 0.598 0.118 0.599 0.120 C 0.599 0.121 0.600 0.121 0.600 0.119 C 0.601 0.117 0.601 0.118 0.601 0.122 C 0.601 0.125 0.601 0.126 0.600 0.127 C 0.599 0.128 0.599 0.128 0.600 0.129 C 0.601 0.130 0.601 0.134 0.600 0.134 C 0.599 0.134 0.599 0.133 0.600 0.132 C 0.600 0.131 0.600 0.130 0.600 0.130 C 0.599 0.130 0.599 0.131 0.599 0.133 C 0.599 0.134 0.599 0.136 0.598 0.136 C 0.598 0.136 0.598 0.134 0.598 0.133 Z  M 0.605 0.133 C 0.605 0.131 0.605 0.130 0.604 0.131 C 0.603 0.132 0.603 0.131 0.603 0.128 C 0.602 0.126 0.602 0.125 0.602 0.126 C 0.603 0.127 0.603 0.126 0.603 0.123 C 0.603 0.121 0.604 0.120 0.604 0.120 C 0.604 0.120 0.605 0.122 0.605 0.124 C 0.605 0.125 0.605 0.127 0.606 0.128 C 0.607 0.130 0.607 0.130 0.606 0.130 C 0.606 0.130 0.606 0.131 0.606 0.132 C 0.606 0.133 0.606 0.134 0.605 0.135 C 0.605 0.136 0.605 0.134 0.605 0.133 Z  M 0.702 0.134 C 0.703 0.134 0.703 0.134 0.703 0.135 C 0.703 0.135 0.703 0.136 0.703 0.135 C 0.702 0.135 0.702 0.135 0.702 0.134 Z  M 0.582 0.136 C 0.581 0.135 0.581 0.133 0.582 0.132 C 0.582 0.131 0.582 0.132 0.583 0.134 C 0.584 0.138 0.583 0.139 0.582 0.136 Z  M 0.594 0.134 C 0.594 0.133 0.594 0.133 0.594 0.133 C 0.595 0.134 0.595 0.135 0.595 0.136 C 0.595 0.136 0.595 0.137 0.594 0.136 C 0.594 0.136 0.594 0.135 0.594 0.134 Z  M 0.700 0.136 C 0.701 0.133 0.702 0.135 0.701 0.138 C 0.701 0.140 0.701 0.140 0.701 0.139 C 0.700 0.138 0.700 0.137 0.700 0.136 Z  M 0.708 0.139 C 0.708 0.138 0.709 0.138 0.709 0.138 C 0.709 0.139 0.710 0.140 0.710 0.140 C 0.710 0.141 0.709 0.141 0.709 0.141 C 0.709 0.141 0.708 0.140 0.708 0.139 Z  M 0.711 0.139 C 0.711 0.138 0.711 0.137 0.711 0.137 C 0.710 0.137 0.710 0.137 0.710 0.135 C 0.710 0.133 0.710 0.133 0.711 0.133 C 0.712 0.134 0.712 0.134 0.712 0.131 C 0.711 0.128 0.712 0.128 0.713 0.132 C 0.713 0.134 0.713 0.136 0.713 0.136 C 0.713 0.136 0.712 0.137 0.712 0.138 C 0.712 0.140 0.711 0.141 0.711 0.141 C 0.710 0.141 0.711 0.140 0.711 0.139 Z  M 0.583 0.142 C 0.583 0.142 0.583 0.141 0.584 0.140 C 0.585 0.140 0.585 0.140 0.585 0.141 C 0.585 0.143 0.583 0.143 0.583 0.142 Z  M 0.705 0.141 C 0.705 0.140 0.705 0.139 0.706 0.140 C 0.706 0.141 0.706 0.141 0.706 0.142 C 0.706 0.142 0.706 0.143 0.706 0.143 C 0.705 0.143 0.705 0.142 0.705 0.141 Z  M 0.727 0.139 C 0.727 0.137 0.727 0.136 0.728 0.136 C 0.728 0.136 0.728 0.137 0.728 0.139 C 0.728 0.141 0.727 0.143 0.727 0.143 C 0.727 0.143 0.727 0.141 0.727 0.139 Z  M 0.714 0.151 C 0.714 0.150 0.714 0.148 0.715 0.146 C 0.715 0.144 0.716 0.143 0.716 0.145 C 0.716 0.146 0.717 0.147 0.718 0.147 C 0.719 0.147 0.719 0.148 0.719 0.150 C 0.718 0.152 0.714 0.152 0.714 0.151 Z  M 0.078 0.155 C 0.078 0.155 0.078 0.155 0.079 0.156 C 0.079 0.156 0.078 0.157 0.078 0.157 C 0.077 0.156 0.077 0.156 0.078 0.155 Z  M 0.084 0.185 C 0.085 0.185 0.085 0.185 0.085 0.185 C 0.086 0.186 0.086 0.186 0.085 0.186 C 0.084 0.186 0.084 0.186 0.084 0.185 Z  M 0.056 0.228 C 0.056 0.227 0.057 0.227 0.057 0.228 C 0.057 0.228 0.057 0.229 0.056 0.229 C 0.056 0.229 0.056 0.228 0.056 0.228 Z  M 0.049 0.298 C 0.049 0.298 0.050 0.298 0.050 0.298 C 0.050 0.299 0.050 0.299 0.049 0.299 C 0.049 0.299 0.049 0.299 0.049 0.298 Z  M 0.051 0.298 C 0.051 0.298 0.051 0.298 0.052 0.298 C 0.052 0.299 0.052 0.299 0.051 0.299 C 0.051 0.299 0.050 0.299 0.051 0.298 Z  M 0.058 0.298 C 0.059 0.298 0.059 0.298 0.059 0.298 C 0.059 0.299 0.059 0.299 0.059 0.299 C 0.058 0.299 0.058 0.299 0.058 0.298 Z  M 0.049 0.302 C 0.049 0.301 0.050 0.301 0.050 0.302 C 0.050 0.302 0.050 0.303 0.049 0.303 C 0.049 0.303 0.049 0.302 0.049 0.302 Z  M 0.924 0.364 C 0.924 0.363 0.924 0.363 0.925 0.363 C 0.925 0.363 0.925 0.363 0.925 0.364 C 0.925 0.365 0.925 0.366 0.925 0.366 C 0.924 0.366 0.924 0.365 0.924 0.364 Z  M 0.053 0.461 C 0.052 0.461 0.053 0.460 0.054 0.459 C 0.056 0.458 0.056 0.458 0.056 0.461 C 0.055 0.462 0.055 0.462 0.053 0.461 Z  M 0.050 0.464 C 0.049 0.462 0.049 0.461 0.050 0.461 C 0.050 0.461 0.051 0.462 0.051 0.464 C 0.051 0.465 0.051 0.467 0.051 0.467 C 0.050 0.467 0.050 0.465 0.050 0.464 Z  M 0.064 0.469 C 0.065 0.468 0.065 0.468 0.065 0.469 C 0.065 0.470 0.065 0.470 0.064 0.470 C 0.064 0.470 0.064 0.469 0.064 0.469 Z  M 0.944 0.471 C 0.945 0.470 0.946 0.470 0.946 0.471 C 0.946 0.472 0.946 0.473 0.945 0.473 C 0.943 0.473 0.943 0.473 0.944 0.471 Z  M 0.952 0.471 C 0.953 0.470 0.953 0.468 0.954 0.468 C 0.954 0.468 0.954 0.470 0.953 0.471 C 0.953 0.472 0.952 0.474 0.952 0.474 C 0.952 0.474 0.952 0.472 0.952 0.471 Z  M 0.960 0.472 C 0.961 0.472 0.962 0.472 0.963 0.472 C 0.964 0.473 0.963 0.473 0.961 0.473 C 0.960 0.473 0.959 0.473 0.960 0.472 Z  M 0.956 0.473 C 0.956 0.472 0.956 0.472 0.957 0.472 C 0.958 0.472 0.958 0.473 0.958 0.474 C 0.957 0.475 0.956 0.474 0.956 0.473 Z  M 0.920 0.485 C 0.920 0.484 0.921 0.484 0.921 0.485 C 0.922 0.485 0.921 0.486 0.920 0.486 C 0.920 0.486 0.919 0.485 0.920 0.485 Z  M 0.083 0.504 C 0.084 0.504 0.084 0.504 0.084 0.504 C 0.084 0.505 0.084 0.505 0.084 0.505 C 0.083 0.505 0.083 0.505 0.083 0.504 Z  M 0.915 0.512 C 0.914 0.512 0.914 0.512 0.915 0.511 C 0.916 0.509 0.920 0.510 0.920 0.512 C 0.919 0.513 0.919 0.513 0.918 0.513 C 0.917 0.513 0.916 0.513 0.915 0.512 Z  M 0.067 0.522 C 0.067 0.521 0.068 0.520 0.069 0.521 C 0.069 0.522 0.068 0.523 0.068 0.523 C 0.067 0.523 0.067 0.523 0.067 0.522 Z  M 0.069 0.525 C 0.069 0.524 0.070 0.523 0.070 0.523 C 0.070 0.523 0.071 0.524 0.071 0.525 C 0.071 0.526 0.070 0.526 0.070 0.526 C 0.070 0.526 0.069 0.526 0.069 0.525 Z  M 0.920 0.532 C 0.920 0.531 0.920 0.530 0.920 0.531 C 0.920 0.531 0.921 0.532 0.921 0.533 C 0.921 0.533 0.920 0.533 0.920 0.533 C 0.920 0.533 0.920 0.533 0.920 0.532 Z  M 0.923 0.529 C 0.923 0.528 0.923 0.529 0.923 0.531 C 0.923 0.533 0.923 0.533 0.923 0.532 C 0.923 0.531 0.923 0.529 0.923 0.529 Z  M 0.074 0.536 C 0.075 0.535 0.075 0.535 0.076 0.536 C 0.076 0.536 0.076 0.537 0.075 0.537 C 0.074 0.537 0.074 0.536 0.074 0.536 Z  M 0.938 0.539 C 0.938 0.538 0.939 0.537 0.939 0.537 C 0.940 0.537 0.940 0.537 0.939 0.539 C 0.938 0.541 0.938 0.541 0.938 0.539 Z  M 0.947 0.539 C 0.947 0.539 0.947 0.539 0.948 0.539 C 0.948 0.540 0.948 0.540 0.947 0.540 C 0.947 0.540 0.946 0.540 0.947 0.539 Z  M 0.920 0.543 C 0.920 0.542 0.920 0.542 0.921 0.543 C 0.921 0.544 0.920 0.544 0.920 0.544 C 0.919 0.544 0.919 0.543 0.920 0.543 Z  M 0.926 0.543 C 0.926 0.542 0.927 0.542 0.927 0.543 C 0.927 0.543 0.927 0.544 0.927 0.544 C 0.926 0.544 0.926 0.543 0.926 0.543 Z  M 0.931 0.542 C 0.931 0.541 0.931 0.541 0.932 0.541 C 0.932 0.541 0.932 0.540 0.932 0.538 C 0.932 0.536 0.932 0.536 0.933 0.537 C 0.933 0.537 0.934 0.538 0.933 0.540 C 0.933 0.541 0.932 0.542 0.932 0.543 C 0.931 0.543 0.931 0.544 0.931 0.544 C 0.931 0.544 0.931 0.543 0.931 0.542 Z  M 0.031 0.545 C 0.031 0.544 0.031 0.544 0.032 0.545 C 0.032 0.545 0.032 0.546 0.031 0.546 C 0.031 0.546 0.030 0.545 0.031 0.545 Z  M 0.956 0.546 C 0.958 0.544 0.958 0.544 0.958 0.546 C 0.958 0.547 0.958 0.547 0.957 0.547 C 0.955 0.547 0.955 0.547 0.956 0.546 Z  M 0.942 0.547 C 0.942 0.545 0.945 0.545 0.945 0.547 C 0.945 0.548 0.944 0.548 0.943 0.548 C 0.942 0.549 0.941 0.548 0.942 0.547 Z  M 0.919 0.548 C 0.918 0.546 0.919 0.546 0.919 0.546 C 0.919 0.547 0.920 0.548 0.920 0.549 C 0.920 0.551 0.920 0.551 0.919 0.551 C 0.919 0.550 0.919 0.549 0.919 0.548 Z  M 0.920 0.549 C 0.920 0.548 0.920 0.547 0.921 0.546 C 0.921 0.546 0.921 0.546 0.921 0.547 C 0.922 0.548 0.922 0.549 0.923 0.549 C 0.923 0.549 0.923 0.549 0.923 0.547 C 0.922 0.544 0.923 0.544 0.924 0.544 C 0.925 0.544 0.925 0.545 0.925 0.545 C 0.924 0.547 0.924 0.549 0.925 0.550 C 0.926 0.550 0.925 0.551 0.923 0.551 C 0.922 0.551 0.921 0.550 0.920 0.549 Z  M 0.947 0.548 C 0.948 0.546 0.949 0.545 0.950 0.548 C 0.951 0.549 0.951 0.549 0.950 0.548 C 0.949 0.548 0.948 0.548 0.948 0.549 C 0.948 0.550 0.947 0.551 0.947 0.551 C 0.947 0.551 0.947 0.550 0.947 0.548 Z  M 0.928 0.550 C 0.928 0.549 0.928 0.548 0.928 0.547 C 0.928 0.546 0.928 0.546 0.928 0.546 C 0.929 0.546 0.929 0.550 0.928 0.552 C 0.928 0.552 0.928 0.553 0.927 0.553 C 0.927 0.553 0.927 0.552 0.928 0.550 Z  M 0.931 0.546 C 0.932 0.545 0.934 0.545 0.935 0.545 C 0.937 0.546 0.939 0.547 0.940 0.547 C 0.940 0.547 0.940 0.548 0.940 0.549 C 0.940 0.550 0.940 0.550 0.939 0.550 C 0.938 0.550 0.937 0.549 0.937 0.549 C 0.937 0.548 0.937 0.547 0.936 0.548 C 0.935 0.549 0.934 0.548 0.934 0.547 C 0.934 0.546 0.933 0.546 0.933 0.547 C 0.933 0.547 0.933 0.549 0.933 0.549 C 0.933 0.550 0.933 0.551 0.933 0.551 C 0.933 0.551 0.932 0.550 0.932 0.549 C 0.932 0.546 0.931 0.547 0.931 0.550 C 0.932 0.553 0.931 0.553 0.931 0.551 C 0.930 0.549 0.930 0.548 0.931 0.546 Z  M 0.935 0.551 C 0.936 0.549 0.936 0.549 0.936 0.551 C 0.936 0.552 0.936 0.553 0.935 0.553 C 0.934 0.553 0.934 0.553 0.935 0.551 Z  M 0.949 0.552 C 0.949 0.551 0.950 0.551 0.950 0.552 C 0.950 0.552 0.950 0.553 0.949 0.553 C 0.949 0.553 0.948 0.552 0.949 0.552 Z  M 0.965 0.552 C 0.965 0.551 0.965 0.551 0.965 0.552 C 0.966 0.552 0.965 0.553 0.965 0.553 C 0.964 0.553 0.964 0.552 0.965 0.552 Z  M 0.958 0.553 C 0.959 0.553 0.959 0.553 0.959 0.554 C 0.959 0.554 0.959 0.555 0.959 0.554 C 0.958 0.554 0.958 0.554 0.958 0.553 Z  M 0.957 0.580 C 0.957 0.580 0.958 0.579 0.958 0.579 C 0.958 0.579 0.958 0.580 0.958 0.581 C 0.958 0.582 0.958 0.582 0.958 0.582 C 0.958 0.581 0.957 0.580 0.957 0.580 Z  M 0.043 0.593 C 0.043 0.592 0.043 0.592 0.044 0.592 C 0.044 0.592 0.044 0.592 0.044 0.593 C 0.044 0.594 0.044 0.595 0.044 0.595 C 0.043 0.595 0.043 0.594 0.043 0.593 Z  M 0.929 0.634 C 0.929 0.634 0.929 0.634 0.930 0.635 C 0.930 0.635 0.929 0.636 0.929 0.635 C 0.928 0.635 0.928 0.635 0.929 0.634 Z  M 0.056 0.637 C 0.056 0.636 0.056 0.636 0.057 0.636 C 0.057 0.636 0.057 0.636 0.057 0.637 C 0.056 0.639 0.056 0.639 0.056 0.637 Z  M 0.057 0.641 C 0.057 0.639 0.059 0.639 0.060 0.641 C 0.060 0.641 0.060 0.642 0.059 0.642 C 0.058 0.642 0.057 0.641 0.057 0.641 V 0.154 Z  M 0.957 0.643 C 0.958 0.643 0.958 0.643 0.958 0.643 C 0.958 0.644 0.958 0.644 0.958 0.644 C 0.957 0.644 0.957 0.644 0.957 0.643 Z  M 0.060 0.645 C 0.060 0.645 0.061 0.644 0.061 0.644 C 0.061 0.643 0.062 0.644 0.062 0.644 C 0.062 0.645 0.061 0.646 0.061 0.646 C 0.061 0.646 0.060 0.646 0.060 0.645 Z  M 0.967 0.644 C 0.967 0.643 0.967 0.643 0.968 0.643 C 0.969 0.643 0.969 0.643 0.968 0.644 C 0.967 0.647 0.967 0.647 0.967 0.644 Z  M 0.059 0.647 C 0.058 0.648 0.058 0.647 0.058 0.645 C 0.059 0.642 0.059 0.642 0.060 0.647 C 0.060 0.650 0.060 0.650 0.060 0.648 C 0.059 0.647 0.059 0.647 0.059 0.647 H 0.059 Z  M 0.970 0.674 C 0.971 0.673 0.973 0.674 0.973 0.675 C 0.973 0.676 0.972 0.676 0.971 0.676 C 0.970 0.676 0.970 0.675 0.970 0.674 Z  M 0.976 0.680 C 0.976 0.679 0.976 0.678 0.976 0.678 C 0.976 0.678 0.977 0.679 0.977 0.680 C 0.978 0.681 0.978 0.681 0.977 0.681 C 0.977 0.681 0.977 0.681 0.976 0.680 Z  M 0.947 0.713 C 0.947 0.712 0.947 0.711 0.947 0.711 C 0.947 0.711 0.948 0.712 0.948 0.713 C 0.948 0.714 0.947 0.715 0.947 0.715 C 0.947 0.715 0.947 0.714 0.947 0.713 Z  M 0.958 0.763 C 0.958 0.763 0.958 0.762 0.959 0.762 C 0.959 0.762 0.959 0.763 0.959 0.764 C 0.959 0.766 0.958 0.765 0.958 0.763 Z  M 0.940 0.776 C 0.941 0.775 0.941 0.775 0.942 0.774 C 0.943 0.774 0.943 0.773 0.943 0.773 C 0.943 0.772 0.943 0.771 0.943 0.771 C 0.944 0.771 0.944 0.772 0.944 0.774 C 0.944 0.776 0.943 0.776 0.942 0.776 C 0.941 0.776 0.940 0.776 0.940 0.776 Z  M 0.947 0.778 C 0.947 0.777 0.947 0.776 0.948 0.776 C 0.948 0.776 0.949 0.777 0.949 0.778 C 0.949 0.779 0.948 0.780 0.948 0.780 C 0.947 0.780 0.947 0.779 0.947 0.778 Z  M 0.959 0.787 C 0.958 0.786 0.959 0.785 0.960 0.785 C 0.961 0.786 0.961 0.786 0.960 0.787 C 0.960 0.788 0.959 0.788 0.959 0.789 C 0.959 0.789 0.959 0.788 0.959 0.787 Z  M 0.964 0.796 C 0.965 0.795 0.965 0.794 0.965 0.794 C 0.965 0.794 0.965 0.795 0.965 0.796 C 0.965 0.797 0.965 0.798 0.965 0.798 C 0.964 0.798 0.964 0.797 0.964 0.796 Z  M 0.962 0.798 C 0.962 0.797 0.962 0.796 0.962 0.796 C 0.962 0.796 0.962 0.797 0.962 0.798 C 0.962 0.799 0.962 0.799 0.962 0.799 C 0.962 0.799 0.962 0.799 0.962 0.798 Z  M 0.986 0.838 C 0.986 0.836 0.987 0.836 0.987 0.838 C 0.987 0.839 0.987 0.839 0.987 0.839 C 0.986 0.839 0.986 0.838 0.986 0.838 Z  M 0.986 0.842 C 0.986 0.842 0.986 0.842 0.986 0.842 C 0.987 0.843 0.986 0.843 0.986 0.843 C 0.985 0.843 0.985 0.843 0.986 0.842 Z  M 0.989 0.847 C 0.989 0.846 0.989 0.845 0.989 0.846 C 0.989 0.847 0.990 0.847 0.990 0.848 C 0.990 0.848 0.989 0.849 0.989 0.849 C 0.989 0.849 0.989 0.848 0.989 0.847 Z  M 0.978 0.856 C 0.979 0.856 0.979 0.856 0.979 0.856 C 0.979 0.857 0.979 0.857 0.979 0.857 C 0.978 0.857 0.978 0.857 0.978 0.856 Z  M 0.980 0.856 C 0.980 0.855 0.981 0.854 0.981 0.854 C 0.982 0.854 0.982 0.855 0.982 0.856 C 0.982 0.857 0.981 0.857 0.981 0.857 C 0.981 0.857 0.980 0.857 0.980 0.856 Z  M 0.985 0.864 C 0.985 0.864 0.986 0.863 0.986 0.863 C 0.986 0.863 0.987 0.864 0.987 0.864 C 0.987 0.865 0.986 0.866 0.986 0.866 C 0.985 0.866 0.985 0.865 0.985 0.864 Z  M 0.982 0.873 C 0.982 0.872 0.983 0.872 0.983 0.872 C 0.984 0.872 0.984 0.872 0.984 0.873 C 0.984 0.874 0.984 0.875 0.983 0.875 C 0.983 0.875 0.982 0.874 0.982 0.873 Z  M 0.379 0.998 C 0.378 0.997 0.379 0.997 0.381 0.997 C 0.383 0.997 0.384 0.996 0.384 0.993 C 0.385 0.990 0.386 0.988 0.386 0.991 C 0.386 0.992 0.387 0.992 0.388 0.992 C 0.389 0.992 0.390 0.992 0.390 0.994 C 0.390 0.995 0.391 0.996 0.393 0.994 C 0.395 0.993 0.396 0.992 0.398 0.991 C 0.398 0.991 0.399 0.990 0.398 0.989 C 0.398 0.989 0.399 0.987 0.399 0.986 C 0.401 0.984 0.402 0.979 0.402 0.977 C 0.402 0.976 0.402 0.975 0.402 0.975 C 0.403 0.975 0.403 0.976 0.403 0.977 C 0.403 0.978 0.403 0.979 0.403 0.979 C 0.404 0.979 0.404 0.981 0.405 0.984 C 0.406 0.990 0.407 0.991 0.407 0.987 C 0.407 0.984 0.407 0.984 0.410 0.989 C 0.410 0.990 0.411 0.991 0.411 0.990 C 0.411 0.988 0.414 0.989 0.414 0.991 C 0.415 0.993 0.416 0.993 0.416 0.991 C 0.416 0.990 0.416 0.989 0.416 0.989 C 0.415 0.988 0.415 0.988 0.416 0.988 C 0.416 0.988 0.417 0.988 0.417 0.989 C 0.417 0.993 0.419 0.992 0.420 0.988 C 0.421 0.986 0.422 0.984 0.422 0.984 C 0.423 0.984 0.425 0.983 0.426 0.981 C 0.427 0.978 0.428 0.978 0.428 0.980 C 0.429 0.981 0.429 0.982 0.430 0.982 C 0.430 0.982 0.430 0.983 0.430 0.984 C 0.430 0.985 0.430 0.986 0.431 0.986 C 0.432 0.986 0.432 0.986 0.431 0.984 C 0.431 0.982 0.431 0.982 0.432 0.982 C 0.433 0.983 0.433 0.982 0.433 0.980 C 0.433 0.977 0.434 0.975 0.435 0.975 C 0.436 0.975 0.436 0.976 0.436 0.977 C 0.436 0.977 0.437 0.978 0.439 0.977 C 0.442 0.977 0.443 0.977 0.444 0.980 C 0.445 0.984 0.447 0.985 0.447 0.982 C 0.447 0.980 0.447 0.981 0.448 0.984 C 0.449 0.986 0.449 0.988 0.450 0.988 C 0.450 0.988 0.450 0.987 0.450 0.986 C 0.449 0.985 0.449 0.984 0.450 0.983 C 0.450 0.983 0.451 0.981 0.451 0.980 C 0.451 0.979 0.451 0.976 0.452 0.974 C 0.454 0.971 0.454 0.971 0.455 0.974 C 0.456 0.975 0.457 0.977 0.459 0.978 C 0.460 0.979 0.461 0.979 0.460 0.977 C 0.460 0.976 0.460 0.975 0.461 0.975 C 0.462 0.975 0.463 0.979 0.464 0.981 C 0.464 0.982 0.464 0.982 0.465 0.982 C 0.465 0.981 0.466 0.980 0.466 0.979 C 0.465 0.977 0.467 0.972 0.469 0.973 C 0.469 0.973 0.471 0.972 0.471 0.970 C 0.472 0.968 0.473 0.968 0.474 0.970 C 0.474 0.972 0.475 0.972 0.476 0.971 C 0.477 0.969 0.477 0.970 0.478 0.972 C 0.478 0.974 0.479 0.975 0.480 0.975 C 0.480 0.974 0.481 0.975 0.481 0.976 C 0.481 0.978 0.481 0.977 0.482 0.974 C 0.483 0.970 0.484 0.969 0.484 0.972 C 0.484 0.973 0.484 0.974 0.485 0.974 C 0.485 0.974 0.485 0.975 0.485 0.976 C 0.485 0.977 0.485 0.978 0.486 0.978 C 0.487 0.978 0.487 0.978 0.487 0.976 C 0.488 0.975 0.488 0.974 0.489 0.975 C 0.491 0.975 0.491 0.974 0.492 0.973 C 0.492 0.971 0.492 0.971 0.493 0.972 C 0.494 0.973 0.494 0.973 0.495 0.972 C 0.495 0.972 0.496 0.971 0.497 0.971 C 0.499 0.971 0.500 0.970 0.501 0.970 C 0.501 0.969 0.502 0.969 0.502 0.970 C 0.501 0.975 0.503 0.974 0.503 0.968 C 0.503 0.964 0.504 0.963 0.505 0.962 C 0.506 0.961 0.506 0.960 0.506 0.959 C 0.506 0.958 0.506 0.958 0.506 0.958 C 0.507 0.958 0.507 0.957 0.507 0.956 C 0.507 0.956 0.508 0.955 0.509 0.955 C 0.511 0.954 0.511 0.955 0.512 0.959 C 0.512 0.963 0.514 0.966 0.515 0.963 C 0.516 0.961 0.518 0.963 0.518 0.966 C 0.518 0.968 0.518 0.968 0.519 0.968 C 0.520 0.968 0.520 0.968 0.520 0.967 C 0.519 0.963 0.525 0.957 0.526 0.959 C 0.527 0.960 0.527 0.960 0.526 0.962 C 0.525 0.963 0.525 0.963 0.526 0.963 C 0.528 0.963 0.529 0.961 0.528 0.959 C 0.528 0.958 0.528 0.958 0.529 0.958 C 0.529 0.959 0.530 0.958 0.530 0.957 C 0.531 0.955 0.532 0.955 0.532 0.956 C 0.532 0.957 0.533 0.958 0.534 0.958 C 0.535 0.958 0.536 0.959 0.536 0.960 C 0.537 0.963 0.539 0.963 0.540 0.961 C 0.541 0.958 0.544 0.957 0.545 0.960 C 0.547 0.961 0.549 0.959 0.549 0.956 C 0.549 0.955 0.549 0.955 0.550 0.955 C 0.551 0.956 0.551 0.955 0.552 0.953 C 0.552 0.951 0.553 0.949 0.553 0.949 C 0.554 0.949 0.554 0.948 0.553 0.947 C 0.553 0.945 0.554 0.946 0.555 0.950 C 0.556 0.952 0.557 0.953 0.560 0.953 C 0.562 0.954 0.565 0.955 0.566 0.956 C 0.568 0.958 0.569 0.957 0.569 0.956 C 0.569 0.955 0.569 0.954 0.570 0.955 C 0.570 0.956 0.572 0.953 0.572 0.950 C 0.572 0.949 0.572 0.948 0.573 0.948 C 0.573 0.948 0.574 0.949 0.574 0.949 C 0.574 0.952 0.576 0.953 0.577 0.950 C 0.577 0.949 0.577 0.949 0.577 0.951 C 0.578 0.952 0.578 0.952 0.578 0.952 C 0.579 0.951 0.579 0.951 0.579 0.952 C 0.580 0.955 0.583 0.958 0.583 0.957 C 0.584 0.956 0.584 0.955 0.585 0.955 C 0.586 0.955 0.587 0.954 0.587 0.953 C 0.587 0.951 0.595 0.951 0.596 0.954 C 0.597 0.957 0.599 0.958 0.599 0.956 C 0.599 0.955 0.600 0.954 0.600 0.954 C 0.601 0.954 0.601 0.953 0.601 0.953 C 0.601 0.952 0.602 0.951 0.603 0.951 C 0.604 0.951 0.605 0.952 0.605 0.953 C 0.605 0.953 0.605 0.954 0.605 0.954 C 0.606 0.954 0.606 0.955 0.606 0.957 C 0.607 0.961 0.609 0.962 0.610 0.959 C 0.610 0.957 0.611 0.956 0.611 0.956 C 0.611 0.956 0.611 0.955 0.611 0.955 C 0.611 0.954 0.612 0.953 0.613 0.953 C 0.614 0.953 0.614 0.954 0.615 0.957 C 0.616 0.960 0.616 0.961 0.616 0.960 C 0.616 0.958 0.620 0.951 0.621 0.951 C 0.621 0.951 0.622 0.953 0.622 0.956 C 0.623 0.959 0.624 0.961 0.624 0.960 C 0.624 0.958 0.624 0.958 0.624 0.959 C 0.625 0.959 0.625 0.959 0.626 0.958 C 0.626 0.956 0.631 0.956 0.632 0.958 C 0.632 0.959 0.632 0.960 0.632 0.960 C 0.632 0.960 0.632 0.960 0.632 0.961 C 0.632 0.962 0.633 0.962 0.633 0.961 C 0.634 0.960 0.636 0.959 0.639 0.958 C 0.641 0.958 0.643 0.958 0.644 0.957 C 0.645 0.957 0.646 0.958 0.647 0.958 C 0.649 0.959 0.649 0.959 0.650 0.956 C 0.651 0.952 0.653 0.953 0.653 0.957 C 0.653 0.960 0.655 0.961 0.656 0.959 C 0.656 0.959 0.657 0.958 0.658 0.958 C 0.659 0.958 0.659 0.957 0.659 0.956 C 0.659 0.955 0.659 0.954 0.659 0.954 C 0.659 0.954 0.659 0.953 0.659 0.952 C 0.659 0.950 0.659 0.949 0.659 0.949 C 0.660 0.949 0.660 0.950 0.660 0.952 C 0.660 0.953 0.661 0.954 0.661 0.954 C 0.661 0.954 0.662 0.955 0.662 0.957 C 0.663 0.961 0.663 0.961 0.667 0.956 C 0.670 0.953 0.671 0.952 0.673 0.953 C 0.675 0.953 0.676 0.953 0.676 0.952 C 0.676 0.951 0.677 0.953 0.677 0.955 C 0.679 0.960 0.680 0.961 0.680 0.958 C 0.680 0.957 0.680 0.956 0.680 0.956 C 0.681 0.956 0.681 0.955 0.681 0.954 C 0.681 0.953 0.683 0.953 0.684 0.955 C 0.684 0.956 0.686 0.957 0.687 0.957 C 0.688 0.957 0.689 0.958 0.689 0.959 C 0.690 0.962 0.692 0.960 0.693 0.956 C 0.693 0.953 0.693 0.953 0.694 0.954 C 0.695 0.954 0.695 0.954 0.695 0.953 C 0.696 0.950 0.698 0.950 0.699 0.953 C 0.699 0.955 0.699 0.955 0.700 0.953 C 0.700 0.952 0.701 0.951 0.701 0.952 C 0.702 0.953 0.702 0.952 0.702 0.951 C 0.702 0.949 0.703 0.949 0.703 0.950 C 0.704 0.955 0.712 0.959 0.712 0.954 C 0.711 0.953 0.712 0.952 0.712 0.953 C 0.713 0.953 0.714 0.953 0.713 0.952 C 0.713 0.951 0.714 0.951 0.714 0.952 C 0.715 0.952 0.716 0.953 0.716 0.954 C 0.716 0.954 0.717 0.954 0.717 0.953 C 0.717 0.952 0.717 0.952 0.718 0.952 C 0.719 0.953 0.720 0.952 0.721 0.951 C 0.722 0.949 0.722 0.949 0.723 0.950 C 0.723 0.951 0.725 0.953 0.728 0.953 C 0.730 0.954 0.733 0.955 0.734 0.955 C 0.735 0.955 0.736 0.955 0.736 0.953 C 0.737 0.951 0.737 0.951 0.738 0.953 C 0.739 0.956 0.739 0.956 0.739 0.953 C 0.739 0.952 0.739 0.951 0.740 0.951 C 0.740 0.951 0.741 0.950 0.741 0.949 C 0.741 0.948 0.741 0.948 0.742 0.950 C 0.743 0.952 0.743 0.952 0.744 0.950 C 0.746 0.946 0.750 0.950 0.749 0.954 C 0.749 0.956 0.749 0.956 0.752 0.957 C 0.753 0.957 0.754 0.956 0.754 0.954 C 0.755 0.952 0.755 0.952 0.755 0.954 C 0.756 0.955 0.756 0.955 0.757 0.954 C 0.757 0.953 0.758 0.953 0.759 0.953 C 0.760 0.953 0.760 0.952 0.760 0.951 C 0.760 0.949 0.763 0.945 0.764 0.945 C 0.764 0.945 0.765 0.945 0.765 0.946 C 0.766 0.947 0.766 0.946 0.767 0.943 C 0.768 0.939 0.768 0.938 0.769 0.940 C 0.770 0.943 0.776 0.944 0.777 0.941 C 0.778 0.940 0.779 0.940 0.780 0.942 C 0.782 0.945 0.785 0.946 0.785 0.944 C 0.785 0.943 0.785 0.942 0.785 0.942 C 0.786 0.942 0.786 0.943 0.786 0.944 C 0.786 0.945 0.786 0.945 0.786 0.944 C 0.787 0.942 0.788 0.942 0.789 0.944 C 0.789 0.945 0.790 0.945 0.790 0.944 C 0.790 0.943 0.792 0.943 0.794 0.943 C 0.797 0.943 0.799 0.944 0.800 0.944 C 0.801 0.944 0.802 0.945 0.802 0.947 C 0.803 0.948 0.803 0.949 0.803 0.948 C 0.802 0.944 0.804 0.943 0.808 0.946 C 0.810 0.947 0.811 0.947 0.812 0.945 C 0.813 0.943 0.817 0.944 0.820 0.947 C 0.821 0.947 0.821 0.947 0.821 0.946 C 0.820 0.945 0.820 0.944 0.821 0.945 C 0.821 0.945 0.822 0.944 0.822 0.943 C 0.823 0.940 0.823 0.940 0.825 0.944 C 0.826 0.947 0.826 0.947 0.827 0.946 C 0.828 0.944 0.831 0.944 0.831 0.946 C 0.831 0.946 0.831 0.947 0.832 0.948 C 0.833 0.948 0.834 0.948 0.834 0.947 C 0.834 0.946 0.834 0.945 0.835 0.945 C 0.835 0.945 0.836 0.944 0.836 0.943 C 0.836 0.941 0.836 0.940 0.841 0.941 C 0.844 0.942 0.847 0.942 0.848 0.942 C 0.848 0.943 0.849 0.942 0.849 0.940 C 0.849 0.939 0.849 0.937 0.850 0.937 C 0.851 0.935 0.854 0.940 0.854 0.942 C 0.854 0.943 0.855 0.944 0.856 0.943 C 0.857 0.942 0.857 0.942 0.857 0.944 C 0.857 0.947 0.860 0.946 0.860 0.943 C 0.860 0.941 0.860 0.940 0.861 0.941 C 0.861 0.942 0.861 0.941 0.861 0.940 C 0.861 0.939 0.862 0.939 0.862 0.939 C 0.863 0.940 0.864 0.939 0.864 0.938 C 0.864 0.937 0.865 0.937 0.865 0.938 C 0.866 0.938 0.867 0.938 0.867 0.937 C 0.867 0.936 0.869 0.935 0.871 0.934 C 0.873 0.933 0.876 0.933 0.877 0.932 C 0.877 0.932 0.878 0.931 0.879 0.931 C 0.879 0.931 0.881 0.930 0.882 0.929 C 0.883 0.927 0.884 0.927 0.885 0.928 C 0.885 0.930 0.888 0.930 0.888 0.928 C 0.888 0.927 0.889 0.927 0.889 0.928 C 0.890 0.929 0.890 0.929 0.891 0.929 C 0.891 0.928 0.891 0.929 0.891 0.930 C 0.891 0.931 0.891 0.931 0.892 0.929 C 0.893 0.926 0.894 0.925 0.897 0.925 C 0.899 0.925 0.902 0.924 0.903 0.924 C 0.904 0.923 0.905 0.922 0.907 0.922 C 0.908 0.921 0.909 0.921 0.909 0.921 C 0.910 0.920 0.914 0.919 0.926 0.918 C 0.932 0.918 0.939 0.916 0.941 0.915 C 0.943 0.914 0.946 0.913 0.947 0.913 C 0.949 0.913 0.950 0.912 0.951 0.912 C 0.952 0.909 0.955 0.908 0.963 0.908 C 0.973 0.907 0.975 0.905 0.976 0.898 C 0.976 0.894 0.977 0.893 0.978 0.892 C 0.979 0.892 0.981 0.892 0.982 0.891 C 0.983 0.891 0.983 0.890 0.983 0.888 C 0.982 0.886 0.983 0.886 0.984 0.886 C 0.984 0.886 0.985 0.885 0.986 0.883 C 0.986 0.882 0.986 0.882 0.986 0.883 C 0.986 0.886 0.986 0.886 0.988 0.886 C 0.989 0.887 0.990 0.886 0.989 0.885 C 0.989 0.884 0.988 0.884 0.987 0.884 C 0.987 0.885 0.987 0.884 0.987 0.883 C 0.987 0.880 0.986 0.880 0.985 0.881 C 0.984 0.882 0.983 0.881 0.984 0.880 C 0.984 0.879 0.985 0.879 0.986 0.878 C 0.987 0.878 0.989 0.878 0.989 0.877 C 0.990 0.875 0.990 0.875 0.989 0.875 C 0.988 0.875 0.987 0.874 0.986 0.874 C 0.986 0.874 0.985 0.873 0.985 0.872 C 0.984 0.870 0.984 0.870 0.986 0.869 C 0.987 0.867 0.988 0.866 0.987 0.863 C 0.987 0.861 0.986 0.860 0.984 0.860 C 0.982 0.860 0.982 0.860 0.982 0.857 C 0.983 0.855 0.983 0.854 0.983 0.855 C 0.983 0.856 0.984 0.857 0.985 0.856 C 0.987 0.856 0.987 0.856 0.986 0.857 C 0.985 0.859 0.985 0.859 0.986 0.859 C 0.987 0.859 0.988 0.860 0.988 0.860 C 0.989 0.861 0.989 0.861 0.988 0.859 C 0.987 0.856 0.987 0.854 0.988 0.854 C 0.988 0.854 0.989 0.853 0.989 0.852 C 0.989 0.851 0.989 0.850 0.989 0.850 C 0.990 0.850 0.990 0.851 0.989 0.852 C 0.989 0.854 0.991 0.854 0.991 0.851 C 0.991 0.850 0.992 0.851 0.992 0.852 C 0.993 0.854 0.993 0.854 0.993 0.852 C 0.994 0.850 0.994 0.849 0.995 0.848 C 0.996 0.848 0.995 0.847 0.995 0.847 C 0.994 0.847 0.993 0.846 0.993 0.845 C 0.993 0.844 0.993 0.844 0.992 0.846 C 0.992 0.847 0.991 0.849 0.991 0.849 C 0.990 0.848 0.990 0.848 0.991 0.847 C 0.992 0.845 0.992 0.845 0.991 0.845 C 0.990 0.845 0.990 0.845 0.990 0.842 C 0.991 0.840 0.991 0.840 0.990 0.841 C 0.990 0.841 0.990 0.841 0.989 0.840 C 0.989 0.838 0.989 0.838 0.989 0.840 C 0.989 0.841 0.988 0.841 0.988 0.838 C 0.988 0.836 0.988 0.835 0.987 0.835 C 0.987 0.835 0.987 0.834 0.987 0.833 C 0.987 0.832 0.987 0.832 0.988 0.832 C 0.988 0.833 0.989 0.832 0.989 0.832 C 0.989 0.831 0.988 0.830 0.987 0.830 C 0.986 0.830 0.985 0.829 0.984 0.828 C 0.984 0.826 0.982 0.826 0.979 0.826 C 0.976 0.827 0.975 0.826 0.975 0.825 C 0.975 0.823 0.975 0.822 0.976 0.822 C 0.977 0.822 0.977 0.822 0.977 0.820 C 0.976 0.818 0.975 0.818 0.971 0.816 C 0.969 0.815 0.968 0.814 0.969 0.813 C 0.969 0.812 0.970 0.811 0.971 0.811 C 0.973 0.812 0.973 0.812 0.972 0.810 C 0.972 0.808 0.971 0.807 0.968 0.808 C 0.965 0.808 0.964 0.807 0.965 0.804 C 0.965 0.803 0.966 0.802 0.967 0.802 C 0.968 0.802 0.969 0.802 0.969 0.801 C 0.968 0.800 0.968 0.799 0.969 0.799 C 0.969 0.798 0.969 0.798 0.970 0.799 C 0.970 0.801 0.971 0.797 0.971 0.795 C 0.971 0.794 0.971 0.794 0.971 0.795 C 0.972 0.795 0.972 0.797 0.972 0.798 C 0.971 0.800 0.971 0.800 0.974 0.797 C 0.976 0.793 0.979 0.793 0.980 0.796 C 0.980 0.798 0.980 0.798 0.980 0.796 C 0.980 0.795 0.980 0.794 0.980 0.794 C 0.981 0.794 0.981 0.795 0.981 0.795 C 0.980 0.796 0.981 0.797 0.982 0.797 C 0.983 0.797 0.983 0.796 0.983 0.796 C 0.983 0.795 0.983 0.794 0.983 0.794 C 0.984 0.794 0.984 0.794 0.985 0.793 C 0.985 0.792 0.985 0.792 0.985 0.794 C 0.985 0.795 0.985 0.796 0.986 0.796 H 0.987 L 0.986 0.793 C 0.984 0.789 0.984 0.787 0.986 0.787 C 0.986 0.787 0.987 0.786 0.987 0.786 C 0.987 0.785 0.985 0.784 0.983 0.784 C 0.978 0.783 0.976 0.782 0.976 0.782 C 0.976 0.782 0.975 0.781 0.975 0.782 C 0.974 0.782 0.974 0.781 0.974 0.780 C 0.974 0.779 0.973 0.778 0.973 0.779 C 0.972 0.781 0.967 0.781 0.964 0.779 C 0.963 0.778 0.961 0.773 0.962 0.773 C 0.962 0.773 0.962 0.771 0.962 0.770 C 0.962 0.767 0.962 0.767 0.961 0.767 C 0.960 0.768 0.960 0.768 0.960 0.766 C 0.960 0.765 0.961 0.764 0.962 0.764 C 0.962 0.764 0.962 0.763 0.962 0.762 C 0.962 0.761 0.962 0.761 0.963 0.761 C 0.963 0.762 0.963 0.761 0.964 0.760 C 0.964 0.758 0.964 0.758 0.964 0.761 C 0.964 0.763 0.964 0.764 0.966 0.766 C 0.967 0.766 0.968 0.767 0.968 0.767 C 0.969 0.768 0.970 0.768 0.972 0.769 C 0.973 0.770 0.975 0.771 0.975 0.770 C 0.975 0.770 0.976 0.770 0.976 0.771 C 0.976 0.772 0.977 0.772 0.977 0.772 C 0.979 0.771 0.979 0.770 0.978 0.769 C 0.977 0.769 0.978 0.768 0.979 0.768 C 0.981 0.769 0.982 0.768 0.982 0.767 C 0.983 0.766 0.983 0.766 0.984 0.766 C 0.984 0.767 0.985 0.767 0.985 0.766 C 0.984 0.764 0.985 0.764 0.986 0.766 C 0.986 0.767 0.987 0.767 0.987 0.765 C 0.988 0.764 0.988 0.762 0.988 0.762 C 0.988 0.762 0.987 0.762 0.987 0.761 C 0.986 0.760 0.986 0.761 0.986 0.763 C 0.987 0.764 0.986 0.764 0.985 0.762 C 0.985 0.760 0.984 0.759 0.983 0.759 C 0.983 0.760 0.981 0.759 0.980 0.759 C 0.979 0.758 0.976 0.757 0.974 0.756 C 0.972 0.755 0.969 0.754 0.969 0.753 C 0.968 0.752 0.967 0.751 0.966 0.751 C 0.966 0.751 0.965 0.749 0.965 0.748 C 0.964 0.747 0.964 0.746 0.963 0.745 C 0.962 0.745 0.962 0.745 0.962 0.745 C 0.961 0.744 0.961 0.743 0.960 0.743 C 0.959 0.743 0.959 0.742 0.959 0.740 C 0.960 0.737 0.960 0.737 0.963 0.737 C 0.965 0.737 0.966 0.737 0.966 0.736 C 0.966 0.735 0.965 0.734 0.966 0.734 C 0.966 0.734 0.966 0.733 0.965 0.733 C 0.965 0.732 0.964 0.732 0.964 0.733 C 0.963 0.734 0.963 0.734 0.962 0.732 C 0.962 0.730 0.961 0.729 0.961 0.729 C 0.960 0.729 0.960 0.729 0.961 0.727 C 0.961 0.726 0.961 0.725 0.961 0.725 C 0.961 0.725 0.961 0.726 0.960 0.727 C 0.960 0.728 0.959 0.729 0.958 0.729 C 0.957 0.730 0.955 0.731 0.954 0.732 C 0.953 0.734 0.952 0.734 0.951 0.733 C 0.950 0.731 0.950 0.731 0.951 0.727 C 0.951 0.725 0.952 0.724 0.955 0.723 C 0.956 0.723 0.958 0.722 0.958 0.721 C 0.958 0.721 0.959 0.721 0.960 0.722 C 0.961 0.724 0.961 0.724 0.962 0.722 C 0.962 0.720 0.959 0.718 0.957 0.719 C 0.957 0.720 0.957 0.720 0.957 0.719 C 0.957 0.718 0.957 0.717 0.956 0.717 C 0.956 0.717 0.955 0.717 0.955 0.717 C 0.954 0.717 0.954 0.717 0.955 0.714 C 0.956 0.713 0.956 0.712 0.957 0.712 C 0.958 0.712 0.959 0.712 0.961 0.711 C 0.963 0.710 0.966 0.709 0.968 0.709 C 0.970 0.710 0.971 0.709 0.971 0.708 C 0.971 0.706 0.971 0.706 0.972 0.707 C 0.973 0.708 0.976 0.708 0.980 0.707 C 0.981 0.707 0.981 0.706 0.981 0.705 C 0.981 0.703 0.981 0.703 0.982 0.703 C 0.983 0.704 0.983 0.704 0.982 0.703 C 0.982 0.701 0.980 0.700 0.976 0.701 C 0.976 0.701 0.975 0.701 0.974 0.700 C 0.973 0.699 0.972 0.699 0.971 0.700 C 0.970 0.701 0.970 0.702 0.970 0.701 C 0.970 0.700 0.970 0.699 0.970 0.699 C 0.971 0.699 0.971 0.698 0.971 0.698 C 0.971 0.697 0.971 0.695 0.971 0.694 C 0.972 0.692 0.972 0.692 0.971 0.693 C 0.971 0.693 0.971 0.693 0.971 0.692 C 0.971 0.690 0.971 0.690 0.973 0.689 C 0.973 0.689 0.974 0.689 0.974 0.688 C 0.975 0.687 0.975 0.687 0.976 0.687 C 0.977 0.687 0.978 0.687 0.978 0.686 C 0.980 0.684 0.980 0.684 0.979 0.683 C 0.978 0.682 0.978 0.682 0.979 0.681 C 0.980 0.681 0.981 0.680 0.981 0.679 C 0.981 0.678 0.981 0.678 0.981 0.680 C 0.981 0.682 0.981 0.683 0.981 0.683 C 0.980 0.683 0.980 0.684 0.980 0.685 C 0.980 0.686 0.980 0.686 0.981 0.686 C 0.981 0.685 0.982 0.684 0.983 0.684 C 0.984 0.684 0.984 0.681 0.984 0.681 C 0.983 0.681 0.983 0.680 0.983 0.679 C 0.984 0.676 0.983 0.676 0.980 0.676 C 0.976 0.677 0.976 0.676 0.976 0.674 C 0.976 0.673 0.976 0.672 0.975 0.672 C 0.974 0.672 0.974 0.671 0.974 0.670 C 0.974 0.670 0.974 0.669 0.975 0.669 C 0.975 0.669 0.975 0.669 0.975 0.667 C 0.975 0.666 0.974 0.666 0.974 0.667 C 0.972 0.670 0.972 0.668 0.973 0.665 C 0.973 0.663 0.975 0.662 0.978 0.662 C 0.981 0.662 0.983 0.661 0.983 0.660 C 0.984 0.659 0.983 0.658 0.983 0.659 C 0.982 0.660 0.982 0.658 0.983 0.655 C 0.983 0.653 0.983 0.653 0.982 0.654 C 0.982 0.654 0.982 0.654 0.981 0.653 C 0.981 0.652 0.981 0.652 0.981 0.653 C 0.981 0.654 0.979 0.654 0.977 0.653 C 0.976 0.652 0.975 0.652 0.975 0.652 C 0.976 0.652 0.976 0.651 0.977 0.649 C 0.977 0.648 0.977 0.648 0.978 0.649 C 0.979 0.651 0.983 0.651 0.983 0.649 C 0.983 0.649 0.983 0.648 0.984 0.648 C 0.986 0.648 0.984 0.646 0.980 0.645 C 0.977 0.645 0.975 0.643 0.975 0.643 C 0.975 0.642 0.974 0.642 0.974 0.642 C 0.973 0.643 0.973 0.643 0.973 0.641 C 0.974 0.638 0.973 0.639 0.972 0.641 C 0.972 0.643 0.972 0.643 0.972 0.641 C 0.972 0.639 0.972 0.639 0.971 0.641 C 0.971 0.643 0.971 0.643 0.971 0.641 C 0.971 0.639 0.970 0.639 0.966 0.642 C 0.965 0.643 0.965 0.642 0.965 0.642 C 0.965 0.641 0.964 0.640 0.963 0.640 C 0.962 0.640 0.962 0.640 0.962 0.641 C 0.963 0.642 0.963 0.643 0.962 0.643 C 0.961 0.643 0.961 0.642 0.961 0.641 C 0.961 0.640 0.960 0.639 0.960 0.639 C 0.959 0.638 0.958 0.639 0.959 0.639 C 0.959 0.640 0.959 0.641 0.960 0.641 C 0.961 0.641 0.961 0.641 0.960 0.642 C 0.959 0.643 0.959 0.641 0.958 0.639 C 0.957 0.636 0.957 0.636 0.957 0.638 C 0.957 0.641 0.955 0.643 0.955 0.641 C 0.955 0.640 0.952 0.639 0.945 0.639 C 0.944 0.640 0.942 0.639 0.942 0.638 C 0.941 0.636 0.939 0.635 0.936 0.635 L 0.932 0.635 L 0.935 0.634 C 0.937 0.633 0.940 0.632 0.942 0.632 C 0.943 0.631 0.945 0.631 0.945 0.630 C 0.945 0.629 0.947 0.629 0.949 0.629 C 0.952 0.629 0.954 0.628 0.955 0.626 L 0.956 0.624 L 0.955 0.624 C 0.954 0.624 0.953 0.625 0.953 0.626 C 0.953 0.628 0.950 0.627 0.950 0.625 C 0.950 0.623 0.950 0.623 0.950 0.625 C 0.950 0.628 0.948 0.627 0.948 0.624 C 0.948 0.622 0.948 0.621 0.947 0.622 C 0.946 0.622 0.946 0.622 0.946 0.621 C 0.945 0.620 0.945 0.620 0.944 0.620 C 0.941 0.620 0.936 0.619 0.935 0.618 C 0.935 0.617 0.934 0.617 0.934 0.617 C 0.933 0.617 0.933 0.617 0.933 0.616 C 0.933 0.615 0.932 0.614 0.931 0.614 C 0.931 0.613 0.930 0.611 0.929 0.610 C 0.929 0.608 0.928 0.607 0.926 0.607 C 0.924 0.607 0.919 0.604 0.919 0.602 C 0.919 0.601 0.919 0.601 0.920 0.601 C 0.920 0.602 0.921 0.602 0.921 0.601 C 0.921 0.600 0.922 0.599 0.923 0.600 C 0.924 0.600 0.924 0.600 0.924 0.599 C 0.924 0.598 0.925 0.597 0.925 0.596 C 0.925 0.596 0.924 0.596 0.922 0.596 C 0.921 0.596 0.919 0.597 0.918 0.598 C 0.918 0.599 0.917 0.598 0.917 0.598 C 0.917 0.597 0.916 0.596 0.915 0.596 C 0.913 0.595 0.910 0.592 0.911 0.591 C 0.911 0.590 0.916 0.590 0.923 0.589 C 0.929 0.589 0.935 0.588 0.935 0.588 C 0.936 0.586 0.947 0.587 0.949 0.589 C 0.949 0.590 0.950 0.590 0.950 0.589 C 0.949 0.587 0.952 0.587 0.952 0.588 C 0.952 0.589 0.953 0.589 0.954 0.588 C 0.955 0.587 0.956 0.587 0.957 0.587 C 0.958 0.588 0.958 0.588 0.958 0.586 C 0.957 0.585 0.958 0.584 0.959 0.585 C 0.961 0.586 0.961 0.586 0.961 0.584 C 0.960 0.582 0.959 0.579 0.960 0.579 C 0.960 0.580 0.961 0.579 0.961 0.579 C 0.961 0.579 0.960 0.578 0.958 0.577 C 0.955 0.576 0.953 0.575 0.953 0.576 C 0.953 0.577 0.953 0.577 0.952 0.576 C 0.952 0.576 0.951 0.576 0.951 0.577 C 0.951 0.579 0.951 0.579 0.950 0.578 C 0.949 0.575 0.947 0.575 0.944 0.577 C 0.942 0.578 0.942 0.577 0.942 0.576 C 0.942 0.575 0.942 0.574 0.941 0.574 C 0.941 0.574 0.941 0.575 0.941 0.576 C 0.941 0.577 0.941 0.578 0.940 0.577 C 0.939 0.575 0.933 0.574 0.922 0.573 C 0.918 0.573 0.913 0.572 0.913 0.571 C 0.913 0.570 0.911 0.569 0.909 0.569 C 0.907 0.569 0.906 0.568 0.905 0.567 C 0.905 0.565 0.912 0.558 0.916 0.558 C 0.917 0.558 0.918 0.557 0.918 0.556 C 0.918 0.555 0.918 0.555 0.919 0.555 C 0.920 0.556 0.921 0.556 0.921 0.556 C 0.924 0.556 0.928 0.556 0.928 0.557 C 0.928 0.558 0.930 0.557 0.931 0.555 C 0.931 0.555 0.931 0.555 0.931 0.556 C 0.931 0.557 0.945 0.557 0.956 0.556 C 0.959 0.556 0.961 0.556 0.961 0.557 C 0.961 0.558 0.961 0.558 0.961 0.557 C 0.962 0.556 0.963 0.555 0.968 0.554 C 0.969 0.554 0.969 0.553 0.969 0.553 C 0.969 0.552 0.969 0.551 0.970 0.550 C 0.970 0.550 0.970 0.550 0.969 0.550 C 0.967 0.551 0.967 0.551 0.967 0.548 C 0.966 0.546 0.966 0.546 0.965 0.546 C 0.965 0.547 0.964 0.547 0.964 0.546 C 0.963 0.544 0.963 0.544 0.964 0.544 C 0.965 0.544 0.965 0.543 0.965 0.542 C 0.965 0.542 0.965 0.541 0.964 0.541 C 0.963 0.541 0.963 0.543 0.963 0.547 C 0.964 0.549 0.962 0.549 0.960 0.548 C 0.959 0.547 0.959 0.544 0.960 0.544 C 0.961 0.544 0.961 0.545 0.961 0.546 C 0.961 0.547 0.961 0.548 0.961 0.547 C 0.961 0.547 0.961 0.546 0.961 0.545 C 0.961 0.545 0.962 0.543 0.962 0.542 C 0.962 0.541 0.957 0.541 0.955 0.543 C 0.954 0.544 0.954 0.543 0.954 0.542 C 0.953 0.541 0.953 0.541 0.954 0.541 C 0.955 0.541 0.956 0.540 0.955 0.539 C 0.955 0.538 0.955 0.537 0.956 0.538 C 0.956 0.539 0.957 0.538 0.957 0.537 C 0.957 0.536 0.956 0.535 0.956 0.535 C 0.956 0.535 0.955 0.535 0.954 0.534 C 0.954 0.533 0.953 0.533 0.954 0.535 C 0.954 0.537 0.954 0.537 0.953 0.536 C 0.953 0.536 0.952 0.536 0.952 0.537 C 0.952 0.538 0.952 0.539 0.951 0.539 C 0.951 0.539 0.951 0.538 0.951 0.538 C 0.952 0.536 0.952 0.534 0.950 0.535 C 0.949 0.537 0.948 0.536 0.948 0.533 C 0.949 0.531 0.948 0.531 0.948 0.533 C 0.947 0.535 0.947 0.535 0.947 0.534 C 0.947 0.532 0.946 0.533 0.946 0.534 C 0.946 0.536 0.945 0.538 0.946 0.539 C 0.946 0.540 0.946 0.541 0.945 0.541 C 0.945 0.541 0.944 0.535 0.945 0.534 C 0.945 0.533 0.944 0.533 0.943 0.533 C 0.941 0.533 0.940 0.533 0.940 0.531 C 0.940 0.530 0.940 0.530 0.940 0.532 C 0.940 0.534 0.939 0.534 0.938 0.534 L 0.936 0.534 L 0.936 0.538 C 0.937 0.542 0.937 0.542 0.936 0.541 C 0.934 0.540 0.934 0.539 0.935 0.539 C 0.935 0.539 0.935 0.538 0.935 0.536 C 0.935 0.535 0.935 0.534 0.935 0.533 C 0.935 0.533 0.934 0.533 0.933 0.533 C 0.930 0.533 0.929 0.536 0.929 0.539 C 0.929 0.540 0.929 0.540 0.929 0.539 C 0.928 0.537 0.928 0.537 0.928 0.538 C 0.928 0.541 0.928 0.541 0.927 0.539 C 0.926 0.537 0.926 0.537 0.927 0.537 C 0.927 0.537 0.927 0.536 0.927 0.535 C 0.927 0.534 0.927 0.534 0.927 0.534 C 0.925 0.536 0.924 0.534 0.924 0.531 C 0.924 0.531 0.925 0.530 0.926 0.531 C 0.927 0.532 0.927 0.531 0.927 0.530 C 0.926 0.529 0.925 0.528 0.925 0.528 C 0.924 0.528 0.924 0.525 0.925 0.521 L 0.926 0.516 L 0.924 0.515 C 0.923 0.514 0.922 0.514 0.922 0.514 C 0.921 0.515 0.920 0.514 0.920 0.512 C 0.920 0.509 0.931 0.508 0.932 0.511 C 0.933 0.513 0.937 0.512 0.938 0.508 C 0.939 0.506 0.939 0.505 0.938 0.503 C 0.938 0.502 0.938 0.502 0.939 0.502 C 0.941 0.504 0.952 0.500 0.956 0.497 C 0.957 0.496 0.956 0.493 0.953 0.492 C 0.951 0.491 0.949 0.490 0.949 0.489 C 0.949 0.487 0.949 0.488 0.948 0.489 C 0.948 0.492 0.948 0.491 0.948 0.487 C 0.948 0.486 0.947 0.486 0.946 0.487 C 0.945 0.488 0.944 0.488 0.943 0.488 C 0.940 0.488 0.927 0.486 0.927 0.485 C 0.926 0.484 0.936 0.482 0.939 0.482 C 0.941 0.482 0.942 0.481 0.942 0.481 C 0.943 0.480 0.942 0.479 0.942 0.479 C 0.942 0.479 0.942 0.478 0.942 0.478 C 0.942 0.477 0.942 0.477 0.943 0.478 C 0.944 0.481 0.948 0.483 0.950 0.480 C 0.950 0.479 0.955 0.478 0.962 0.478 C 0.969 0.477 0.974 0.476 0.975 0.475 L 0.977 0.474 L 0.975 0.474 C 0.971 0.474 0.970 0.474 0.970 0.471 C 0.970 0.469 0.971 0.469 0.971 0.469 C 0.972 0.470 0.972 0.469 0.972 0.469 C 0.971 0.468 0.968 0.467 0.963 0.467 C 0.959 0.467 0.955 0.467 0.955 0.467 C 0.955 0.467 0.952 0.466 0.948 0.466 C 0.945 0.466 0.942 0.464 0.941 0.463 C 0.940 0.462 0.933 0.461 0.926 0.460 C 0.919 0.458 0.913 0.457 0.913 0.456 C 0.912 0.455 0.912 0.454 0.912 0.455 C 0.912 0.456 0.909 0.455 0.907 0.453 C 0.905 0.452 0.903 0.451 0.902 0.451 C 0.902 0.452 0.901 0.451 0.900 0.449 C 0.899 0.446 0.899 0.446 0.900 0.444 C 0.901 0.443 0.901 0.443 0.900 0.442 C 0.899 0.441 0.899 0.440 0.901 0.440 C 0.902 0.440 0.903 0.439 0.903 0.438 C 0.904 0.437 0.904 0.437 0.903 0.437 C 0.903 0.438 0.903 0.438 0.903 0.437 C 0.903 0.436 0.902 0.435 0.902 0.435 C 0.901 0.435 0.901 0.434 0.902 0.432 C 0.903 0.430 0.903 0.430 0.901 0.428 C 0.900 0.427 0.898 0.426 0.898 0.426 C 0.897 0.426 0.897 0.426 0.898 0.424 C 0.898 0.423 0.898 0.423 0.898 0.423 C 0.898 0.423 0.897 0.421 0.898 0.420 C 0.898 0.418 0.898 0.417 0.897 0.417 C 0.897 0.417 0.897 0.416 0.897 0.416 C 0.897 0.415 0.898 0.414 0.899 0.414 C 0.900 0.414 0.900 0.413 0.900 0.412 C 0.900 0.411 0.899 0.410 0.898 0.410 C 0.896 0.410 0.896 0.407 0.897 0.405 C 0.898 0.404 0.898 0.403 0.897 0.402 L 0.895 0.400 L 0.897 0.400 C 0.898 0.400 0.898 0.399 0.898 0.398 C 0.898 0.397 0.900 0.396 0.903 0.396 C 0.905 0.395 0.907 0.394 0.907 0.394 C 0.907 0.393 0.905 0.393 0.902 0.394 C 0.900 0.394 0.898 0.394 0.898 0.393 C 0.899 0.392 0.898 0.391 0.897 0.390 C 0.895 0.389 0.889 0.387 0.887 0.387 C 0.886 0.387 0.886 0.386 0.886 0.385 C 0.886 0.384 0.886 0.384 0.885 0.385 C 0.885 0.386 0.881 0.384 0.881 0.382 C 0.881 0.381 0.881 0.381 0.882 0.381 C 0.882 0.382 0.885 0.382 0.889 0.383 C 0.892 0.383 0.895 0.383 0.895 0.384 C 0.895 0.385 0.895 0.386 0.895 0.385 C 0.895 0.384 0.895 0.382 0.895 0.381 C 0.895 0.378 0.896 0.378 0.897 0.378 C 0.898 0.379 0.899 0.378 0.899 0.377 C 0.898 0.375 0.899 0.374 0.901 0.372 C 0.902 0.372 0.906 0.371 0.909 0.371 C 0.919 0.370 0.923 0.369 0.923 0.366 C 0.924 0.364 0.924 0.364 0.924 0.366 C 0.924 0.368 0.924 0.368 0.925 0.367 C 0.928 0.365 0.929 0.363 0.926 0.362 C 0.922 0.360 0.922 0.359 0.924 0.356 C 0.926 0.355 0.927 0.354 0.927 0.353 C 0.928 0.353 0.928 0.352 0.929 0.351 C 0.929 0.350 0.930 0.348 0.931 0.348 C 0.932 0.348 0.932 0.347 0.932 0.346 C 0.932 0.346 0.931 0.346 0.931 0.346 C 0.930 0.347 0.930 0.347 0.930 0.345 C 0.930 0.345 0.932 0.343 0.932 0.343 C 0.933 0.342 0.935 0.340 0.935 0.339 C 0.936 0.338 0.937 0.337 0.938 0.337 C 0.939 0.336 0.941 0.335 0.942 0.334 C 0.942 0.332 0.943 0.331 0.944 0.330 C 0.945 0.329 0.945 0.329 0.945 0.328 C 0.945 0.327 0.945 0.326 0.946 0.324 C 0.947 0.322 0.947 0.319 0.945 0.317 C 0.944 0.316 0.944 0.315 0.945 0.315 C 0.946 0.315 0.946 0.315 0.946 0.313 C 0.945 0.310 0.943 0.309 0.940 0.308 C 0.939 0.307 0.940 0.303 0.942 0.302 C 0.943 0.302 0.944 0.299 0.943 0.297 C 0.942 0.296 0.942 0.297 0.942 0.297 C 0.942 0.298 0.941 0.299 0.940 0.299 C 0.939 0.299 0.938 0.299 0.938 0.297 C 0.939 0.295 0.939 0.294 0.939 0.293 C 0.940 0.293 0.939 0.293 0.938 0.293 C 0.937 0.294 0.937 0.293 0.937 0.292 C 0.937 0.291 0.938 0.290 0.939 0.290 C 0.941 0.290 0.941 0.290 0.940 0.288 C 0.937 0.285 0.938 0.284 0.947 0.281 C 0.950 0.280 0.952 0.278 0.952 0.277 C 0.952 0.276 0.946 0.275 0.939 0.275 C 0.926 0.275 0.922 0.274 0.922 0.271 C 0.922 0.269 0.928 0.266 0.929 0.268 C 0.929 0.269 0.930 0.269 0.931 0.268 C 0.931 0.267 0.933 0.266 0.934 0.266 C 0.936 0.266 0.937 0.265 0.936 0.264 C 0.936 0.263 0.936 0.262 0.937 0.262 C 0.939 0.262 0.939 0.263 0.939 0.264 C 0.938 0.266 0.938 0.266 0.939 0.265 C 0.940 0.264 0.941 0.264 0.942 0.264 C 0.942 0.264 0.943 0.263 0.943 0.263 C 0.943 0.261 0.941 0.258 0.941 0.259 C 0.941 0.260 0.940 0.260 0.938 0.259 L 0.936 0.257 L 0.938 0.257 C 0.939 0.257 0.939 0.256 0.939 0.256 C 0.938 0.255 0.940 0.250 0.941 0.251 C 0.941 0.251 0.941 0.250 0.942 0.249 C 0.942 0.248 0.941 0.247 0.941 0.247 C 0.940 0.247 0.939 0.246 0.939 0.246 C 0.938 0.245 0.936 0.245 0.935 0.245 C 0.931 0.244 0.932 0.244 0.937 0.242 C 0.943 0.240 0.949 0.238 0.951 0.238 C 0.951 0.238 0.952 0.237 0.951 0.236 C 0.951 0.235 0.950 0.235 0.949 0.235 C 0.948 0.235 0.947 0.235 0.946 0.235 C 0.946 0.234 0.945 0.233 0.945 0.233 C 0.941 0.231 0.941 0.229 0.946 0.227 C 0.950 0.225 0.950 0.223 0.945 0.222 L 0.943 0.221 L 0.945 0.220 C 0.946 0.219 0.947 0.218 0.947 0.217 C 0.947 0.216 0.948 0.215 0.949 0.214 C 0.950 0.213 0.950 0.213 0.949 0.215 C 0.948 0.216 0.948 0.216 0.949 0.216 C 0.949 0.217 0.950 0.215 0.950 0.214 C 0.951 0.213 0.952 0.211 0.954 0.210 C 0.955 0.210 0.956 0.209 0.957 0.208 C 0.957 0.207 0.957 0.207 0.958 0.206 C 0.958 0.206 0.959 0.205 0.959 0.204 C 0.960 0.201 0.958 0.199 0.953 0.198 C 0.950 0.197 0.948 0.196 0.947 0.195 C 0.946 0.194 0.945 0.194 0.945 0.194 C 0.944 0.195 0.943 0.195 0.942 0.194 C 0.937 0.190 0.918 0.187 0.907 0.187 C 0.899 0.188 0.899 0.188 0.899 0.184 C 0.899 0.182 0.899 0.181 0.898 0.181 C 0.898 0.181 0.898 0.183 0.898 0.184 C 0.898 0.186 0.897 0.187 0.893 0.186 C 0.890 0.185 0.887 0.184 0.887 0.183 C 0.887 0.183 0.884 0.182 0.882 0.182 C 0.879 0.181 0.874 0.180 0.871 0.179 C 0.868 0.178 0.865 0.178 0.864 0.179 C 0.863 0.179 0.862 0.179 0.862 0.177 C 0.862 0.175 0.859 0.175 0.857 0.177 C 0.857 0.177 0.856 0.176 0.855 0.175 C 0.855 0.174 0.854 0.173 0.853 0.173 C 0.853 0.173 0.852 0.172 0.851 0.171 C 0.851 0.169 0.850 0.169 0.849 0.170 C 0.848 0.173 0.844 0.170 0.843 0.166 C 0.842 0.163 0.838 0.161 0.838 0.164 C 0.838 0.167 0.837 0.166 0.837 0.162 C 0.836 0.159 0.836 0.159 0.835 0.159 C 0.835 0.160 0.835 0.160 0.835 0.159 C 0.835 0.158 0.834 0.156 0.832 0.154 C 0.831 0.152 0.830 0.150 0.830 0.149 C 0.830 0.149 0.829 0.148 0.829 0.148 C 0.829 0.148 0.828 0.147 0.828 0.145 C 0.827 0.144 0.826 0.143 0.823 0.142 C 0.821 0.142 0.820 0.141 0.820 0.139 C 0.819 0.138 0.819 0.137 0.818 0.136 C 0.816 0.135 0.815 0.137 0.812 0.144 C 0.811 0.146 0.810 0.148 0.810 0.149 C 0.810 0.150 0.809 0.152 0.808 0.155 C 0.806 0.159 0.806 0.159 0.801 0.159 C 0.798 0.160 0.797 0.159 0.797 0.158 C 0.797 0.154 0.794 0.154 0.794 0.158 C 0.793 0.161 0.793 0.161 0.793 0.157 C 0.793 0.154 0.793 0.153 0.792 0.154 C 0.792 0.155 0.791 0.154 0.791 0.153 C 0.791 0.150 0.783 0.150 0.782 0.153 C 0.782 0.155 0.782 0.155 0.781 0.153 C 0.780 0.152 0.779 0.151 0.779 0.152 C 0.778 0.152 0.777 0.151 0.776 0.150 C 0.775 0.149 0.775 0.148 0.775 0.149 C 0.775 0.149 0.774 0.148 0.774 0.147 C 0.773 0.145 0.773 0.145 0.772 0.145 C 0.771 0.146 0.770 0.146 0.770 0.144 C 0.769 0.143 0.768 0.143 0.766 0.143 C 0.764 0.144 0.763 0.144 0.762 0.142 C 0.761 0.140 0.760 0.139 0.760 0.140 C 0.759 0.141 0.756 0.137 0.756 0.135 C 0.756 0.134 0.756 0.134 0.756 0.134 C 0.756 0.134 0.755 0.135 0.755 0.135 C 0.755 0.138 0.749 0.141 0.749 0.139 C 0.749 0.138 0.748 0.139 0.748 0.141 C 0.747 0.143 0.746 0.144 0.746 0.144 C 0.746 0.143 0.746 0.143 0.746 0.143 C 0.747 0.143 0.747 0.142 0.747 0.141 C 0.746 0.140 0.746 0.139 0.746 0.140 C 0.746 0.141 0.745 0.140 0.745 0.139 C 0.745 0.137 0.744 0.136 0.743 0.135 C 0.742 0.134 0.738 0.136 0.739 0.138 C 0.739 0.139 0.738 0.140 0.736 0.139 C 0.736 0.139 0.736 0.140 0.736 0.141 C 0.736 0.144 0.734 0.143 0.733 0.139 C 0.733 0.137 0.733 0.135 0.734 0.134 C 0.734 0.133 0.734 0.132 0.733 0.133 C 0.732 0.134 0.732 0.134 0.732 0.132 C 0.732 0.127 0.731 0.126 0.730 0.129 C 0.729 0.131 0.729 0.130 0.728 0.128 C 0.728 0.126 0.727 0.125 0.726 0.126 C 0.725 0.126 0.724 0.126 0.724 0.123 C 0.724 0.119 0.724 0.119 0.723 0.123 C 0.722 0.127 0.721 0.126 0.721 0.122 C 0.722 0.120 0.721 0.117 0.721 0.113 C 0.721 0.109 0.720 0.107 0.719 0.106 C 0.718 0.106 0.717 0.106 0.717 0.107 C 0.716 0.108 0.716 0.109 0.715 0.109 C 0.715 0.109 0.715 0.110 0.714 0.112 C 0.714 0.113 0.714 0.114 0.714 0.114 C 0.713 0.114 0.713 0.113 0.713 0.112 C 0.714 0.110 0.713 0.109 0.713 0.109 C 0.713 0.109 0.712 0.108 0.713 0.107 C 0.713 0.106 0.713 0.105 0.712 0.106 C 0.711 0.107 0.711 0.106 0.710 0.103 C 0.709 0.099 0.709 0.098 0.708 0.099 C 0.707 0.100 0.707 0.100 0.707 0.096 C 0.707 0.092 0.707 0.092 0.706 0.092 C 0.705 0.092 0.705 0.092 0.704 0.093 C 0.704 0.096 0.703 0.095 0.703 0.093 C 0.703 0.091 0.702 0.090 0.701 0.089 C 0.700 0.089 0.700 0.088 0.700 0.085 C 0.699 0.083 0.699 0.081 0.698 0.080 C 0.697 0.080 0.697 0.079 0.697 0.076 C 0.697 0.074 0.697 0.070 0.697 0.068 C 0.697 0.064 0.696 0.063 0.695 0.063 C 0.694 0.063 0.694 0.064 0.694 0.065 C 0.694 0.066 0.694 0.067 0.693 0.067 C 0.692 0.067 0.692 0.066 0.692 0.063 C 0.692 0.061 0.691 0.060 0.690 0.060 C 0.690 0.060 0.689 0.061 0.688 0.062 C 0.687 0.065 0.684 0.064 0.683 0.061 C 0.682 0.060 0.681 0.058 0.681 0.057 C 0.680 0.057 0.680 0.055 0.680 0.054 C 0.680 0.052 0.679 0.050 0.678 0.053 C 0.678 0.054 0.677 0.055 0.676 0.055 C 0.676 0.055 0.675 0.056 0.675 0.057 C 0.674 0.059 0.674 0.060 0.674 0.060 C 0.673 0.060 0.673 0.059 0.674 0.059 C 0.674 0.057 0.674 0.055 0.673 0.055 C 0.672 0.055 0.672 0.053 0.671 0.050 C 0.671 0.047 0.670 0.046 0.669 0.047 C 0.668 0.047 0.668 0.047 0.669 0.046 C 0.669 0.044 0.669 0.044 0.668 0.045 C 0.667 0.046 0.667 0.047 0.666 0.048 C 0.666 0.050 0.666 0.050 0.666 0.048 C 0.666 0.047 0.666 0.046 0.665 0.046 C 0.665 0.046 0.664 0.045 0.664 0.044 C 0.664 0.043 0.664 0.042 0.663 0.042 C 0.663 0.042 0.663 0.043 0.664 0.045 C 0.664 0.047 0.664 0.047 0.664 0.050 C 0.663 0.052 0.663 0.053 0.663 0.051 C 0.663 0.049 0.663 0.047 0.662 0.046 C 0.662 0.044 0.662 0.044 0.661 0.047 C 0.660 0.050 0.660 0.049 0.660 0.045 C 0.660 0.043 0.660 0.042 0.660 0.042 C 0.661 0.042 0.661 0.042 0.661 0.041 C 0.660 0.039 0.657 0.046 0.657 0.049 C 0.657 0.050 0.657 0.051 0.657 0.051 C 0.656 0.051 0.656 0.050 0.656 0.047 C 0.656 0.040 0.656 0.035 0.655 0.033 C 0.653 0.030 0.652 0.031 0.652 0.036 C 0.652 0.038 0.651 0.039 0.651 0.037 C 0.651 0.035 0.651 0.036 0.650 0.038 C 0.649 0.043 0.647 0.044 0.646 0.041 C 0.646 0.038 0.644 0.038 0.644 0.041 C 0.644 0.042 0.644 0.042 0.644 0.041 C 0.643 0.038 0.641 0.037 0.640 0.039 C 0.639 0.040 0.639 0.040 0.639 0.039 C 0.639 0.038 0.638 0.037 0.638 0.037 C 0.638 0.037 0.638 0.038 0.638 0.038 C 0.638 0.041 0.636 0.039 0.635 0.036 C 0.635 0.035 0.634 0.035 0.633 0.036 C 0.632 0.037 0.631 0.038 0.631 0.037 C 0.630 0.037 0.630 0.038 0.630 0.039 C 0.630 0.040 0.629 0.041 0.628 0.041 C 0.627 0.041 0.627 0.041 0.627 0.042 C 0.628 0.044 0.628 0.044 0.627 0.044 C 0.626 0.045 0.626 0.045 0.626 0.042 C 0.626 0.041 0.625 0.039 0.624 0.039 C 0.624 0.038 0.623 0.038 0.623 0.038 C 0.623 0.039 0.623 0.038 0.623 0.036 C 0.622 0.033 0.619 0.033 0.618 0.037 C 0.618 0.039 0.618 0.039 0.617 0.037 C 0.617 0.036 0.617 0.036 0.616 0.039 C 0.616 0.042 0.615 0.045 0.615 0.047 C 0.615 0.048 0.615 0.049 0.614 0.049 C 0.613 0.049 0.612 0.049 0.613 0.045 C 0.613 0.041 0.613 0.040 0.612 0.040 C 0.611 0.040 0.611 0.040 0.611 0.038 C 0.611 0.036 0.611 0.035 0.610 0.035 C 0.609 0.035 0.609 0.036 0.609 0.037 C 0.609 0.038 0.609 0.039 0.609 0.039 C 0.608 0.039 0.608 0.040 0.609 0.040 C 0.609 0.042 0.608 0.043 0.606 0.042 C 0.606 0.042 0.606 0.043 0.605 0.044 C 0.604 0.046 0.604 0.046 0.604 0.043 C 0.604 0.041 0.604 0.040 0.604 0.040 C 0.603 0.040 0.603 0.041 0.603 0.042 C 0.603 0.044 0.603 0.044 0.602 0.042 C 0.602 0.040 0.601 0.039 0.601 0.039 C 0.600 0.039 0.599 0.038 0.599 0.036 C 0.598 0.035 0.597 0.034 0.597 0.034 C 0.597 0.035 0.596 0.033 0.596 0.031 C 0.596 0.026 0.594 0.024 0.595 0.029 C 0.595 0.033 0.593 0.035 0.592 0.032 C 0.591 0.030 0.591 0.030 0.591 0.032 C 0.591 0.033 0.591 0.034 0.590 0.035 C 0.589 0.036 0.588 0.040 0.588 0.044 C 0.589 0.045 0.588 0.046 0.587 0.046 C 0.587 0.045 0.585 0.047 0.584 0.048 C 0.583 0.050 0.582 0.051 0.582 0.051 C 0.582 0.051 0.581 0.053 0.581 0.056 C 0.581 0.063 0.580 0.060 0.580 0.052 C 0.580 0.045 0.580 0.043 0.578 0.041 C 0.577 0.041 0.577 0.042 0.576 0.045 C 0.575 0.049 0.575 0.049 0.574 0.047 C 0.574 0.045 0.574 0.044 0.574 0.044 C 0.573 0.044 0.573 0.043 0.573 0.042 C 0.573 0.042 0.572 0.040 0.572 0.040 C 0.571 0.039 0.570 0.040 0.570 0.043 C 0.569 0.045 0.569 0.046 0.569 0.045 C 0.568 0.043 0.566 0.042 0.566 0.044 C 0.566 0.045 0.566 0.046 0.565 0.046 C 0.565 0.046 0.564 0.048 0.563 0.050 C 0.563 0.052 0.562 0.053 0.562 0.051 C 0.563 0.050 0.562 0.049 0.562 0.049 C 0.562 0.049 0.562 0.049 0.562 0.048 C 0.562 0.046 0.561 0.042 0.560 0.043 C 0.560 0.044 0.560 0.043 0.559 0.042 C 0.559 0.041 0.559 0.041 0.559 0.041 C 0.559 0.040 0.555 0.025 0.555 0.025 C 0.554 0.025 0.554 0.027 0.553 0.030 C 0.552 0.035 0.551 0.035 0.551 0.032 C 0.551 0.029 0.551 0.029 0.550 0.033 C 0.550 0.035 0.549 0.037 0.549 0.038 C 0.548 0.038 0.548 0.038 0.549 0.038 C 0.550 0.037 0.550 0.040 0.549 0.042 C 0.548 0.044 0.548 0.045 0.548 0.048 C 0.548 0.051 0.548 0.051 0.548 0.051 C 0.547 0.050 0.546 0.049 0.545 0.047 C 0.544 0.046 0.542 0.039 0.543 0.039 C 0.543 0.039 0.543 0.038 0.543 0.037 C 0.543 0.034 0.542 0.035 0.542 0.038 C 0.542 0.039 0.542 0.041 0.541 0.042 C 0.541 0.043 0.541 0.046 0.541 0.049 C 0.540 0.053 0.540 0.054 0.539 0.055 C 0.538 0.056 0.538 0.057 0.538 0.058 C 0.538 0.060 0.538 0.060 0.538 0.059 C 0.537 0.058 0.537 0.057 0.537 0.057 C 0.537 0.056 0.537 0.054 0.537 0.053 C 0.536 0.050 0.535 0.048 0.536 0.048 C 0.537 0.048 0.537 0.047 0.536 0.045 C 0.536 0.043 0.536 0.042 0.535 0.042 C 0.535 0.042 0.535 0.041 0.535 0.040 C 0.535 0.037 0.532 0.035 0.531 0.037 C 0.531 0.038 0.531 0.040 0.531 0.041 C 0.531 0.042 0.531 0.043 0.531 0.043 C 0.530 0.044 0.530 0.045 0.530 0.046 C 0.530 0.047 0.530 0.048 0.530 0.048 C 0.529 0.048 0.529 0.049 0.529 0.051 C 0.529 0.053 0.528 0.055 0.528 0.055 C 0.527 0.055 0.527 0.054 0.528 0.053 C 0.528 0.051 0.528 0.051 0.528 0.049 C 0.527 0.048 0.527 0.046 0.527 0.045 C 0.527 0.044 0.527 0.044 0.527 0.045 C 0.527 0.045 0.526 0.045 0.526 0.044 C 0.525 0.043 0.524 0.042 0.524 0.043 C 0.523 0.044 0.523 0.044 0.523 0.041 C 0.523 0.039 0.523 0.039 0.523 0.040 C 0.522 0.041 0.521 0.041 0.521 0.041 C 0.520 0.041 0.519 0.042 0.520 0.044 C 0.520 0.046 0.520 0.046 0.519 0.044 C 0.518 0.042 0.518 0.042 0.518 0.044 C 0.517 0.046 0.517 0.046 0.517 0.044 C 0.517 0.043 0.517 0.042 0.517 0.042 C 0.516 0.042 0.516 0.043 0.516 0.044 C 0.517 0.045 0.517 0.046 0.517 0.047 C 0.516 0.049 0.515 0.048 0.513 0.044 C 0.511 0.042 0.511 0.043 0.511 0.047 C 0.511 0.048 0.510 0.049 0.510 0.049 C 0.509 0.049 0.508 0.058 0.509 0.060 C 0.509 0.061 0.508 0.061 0.508 0.061 C 0.507 0.060 0.507 0.060 0.507 0.061 C 0.507 0.062 0.507 0.064 0.507 0.064 C 0.506 0.065 0.506 0.063 0.506 0.061 C 0.505 0.058 0.505 0.057 0.503 0.057 C 0.501 0.056 0.500 0.057 0.500 0.061 C 0.499 0.063 0.499 0.067 0.499 0.068 C 0.499 0.070 0.499 0.070 0.498 0.070 C 0.497 0.070 0.497 0.071 0.497 0.072 C 0.497 0.075 0.496 0.074 0.496 0.070 C 0.496 0.068 0.495 0.067 0.494 0.067 C 0.494 0.067 0.493 0.066 0.493 0.065 C 0.492 0.062 0.490 0.061 0.490 0.064 C 0.490 0.065 0.490 0.067 0.490 0.068 C 0.490 0.070 0.489 0.070 0.489 0.067 C 0.488 0.063 0.487 0.066 0.487 0.072 C 0.487 0.076 0.487 0.078 0.487 0.079 C 0.486 0.079 0.486 0.079 0.486 0.078 C 0.486 0.076 0.486 0.076 0.485 0.077 C 0.484 0.079 0.482 0.077 0.482 0.073 C 0.481 0.070 0.480 0.070 0.480 0.073 C 0.480 0.076 0.479 0.079 0.478 0.078 C 0.478 0.078 0.478 0.076 0.478 0.075 C 0.478 0.073 0.478 0.072 0.477 0.072 C 0.476 0.072 0.476 0.073 0.476 0.073 C 0.477 0.075 0.477 0.077 0.476 0.077 C 0.476 0.077 0.475 0.079 0.475 0.080 C 0.475 0.082 0.474 0.083 0.474 0.083 C 0.474 0.083 0.473 0.084 0.473 0.086 C 0.473 0.089 0.473 0.089 0.473 0.086 C 0.472 0.084 0.472 0.083 0.472 0.083 C 0.471 0.083 0.471 0.082 0.471 0.080 C 0.471 0.077 0.471 0.077 0.470 0.078 C 0.470 0.079 0.470 0.081 0.470 0.082 C 0.470 0.083 0.470 0.085 0.469 0.085 C 0.468 0.085 0.467 0.089 0.468 0.091 C 0.468 0.092 0.468 0.093 0.468 0.094 C 0.467 0.095 0.467 0.095 0.467 0.092 C 0.466 0.089 0.465 0.090 0.465 0.094 C 0.465 0.095 0.465 0.095 0.465 0.094 C 0.464 0.094 0.464 0.093 0.463 0.092 C 0.463 0.092 0.463 0.092 0.463 0.095 C 0.463 0.097 0.463 0.098 0.461 0.098 C 0.459 0.099 0.459 0.098 0.459 0.097 C 0.459 0.096 0.459 0.095 0.459 0.095 C 0.458 0.095 0.458 0.094 0.458 0.093 C 0.459 0.092 0.458 0.092 0.457 0.093 C 0.455 0.094 0.455 0.095 0.456 0.097 C 0.456 0.099 0.456 0.099 0.454 0.097 C 0.454 0.096 0.453 0.096 0.453 0.097 C 0.453 0.098 0.452 0.098 0.452 0.098 C 0.452 0.098 0.451 0.098 0.451 0.099 C 0.451 0.100 0.450 0.101 0.448 0.101 C 0.447 0.101 0.446 0.102 0.445 0.104 C 0.445 0.106 0.444 0.107 0.444 0.106 C 0.443 0.106 0.443 0.106 0.443 0.107 C 0.443 0.110 0.442 0.109 0.440 0.104 C 0.439 0.103 0.437 0.102 0.436 0.101 C 0.435 0.101 0.434 0.099 0.434 0.098 C 0.433 0.097 0.433 0.097 0.433 0.098 C 0.432 0.098 0.432 0.098 0.432 0.097 C 0.432 0.094 0.430 0.099 0.430 0.102 C 0.430 0.103 0.430 0.104 0.430 0.104 C 0.429 0.104 0.429 0.105 0.429 0.107 C 0.430 0.110 0.429 0.111 0.428 0.111 C 0.428 0.111 0.427 0.110 0.427 0.109 C 0.427 0.108 0.427 0.108 0.426 0.108 C 0.424 0.108 0.424 0.108 0.425 0.109 C 0.426 0.109 0.426 0.110 0.426 0.111 C 0.426 0.112 0.426 0.112 0.423 0.111 C 0.423 0.111 0.422 0.110 0.422 0.109 C 0.422 0.108 0.423 0.108 0.423 0.108 C 0.423 0.109 0.423 0.109 0.423 0.107 C 0.423 0.106 0.423 0.105 0.422 0.105 C 0.422 0.106 0.422 0.105 0.421 0.104 C 0.421 0.102 0.415 0.102 0.415 0.104 C 0.416 0.105 0.415 0.106 0.415 0.106 C 0.415 0.106 0.414 0.106 0.415 0.107 C 0.415 0.110 0.414 0.110 0.413 0.107 C 0.413 0.106 0.413 0.106 0.413 0.106 C 0.412 0.107 0.413 0.108 0.413 0.109 C 0.414 0.111 0.413 0.111 0.413 0.111 C 0.412 0.111 0.412 0.112 0.412 0.113 C 0.412 0.114 0.411 0.113 0.410 0.112 C 0.410 0.112 0.409 0.111 0.408 0.112 C 0.408 0.112 0.408 0.112 0.408 0.111 C 0.408 0.109 0.406 0.107 0.405 0.109 C 0.405 0.110 0.404 0.111 0.403 0.111 C 0.402 0.110 0.400 0.116 0.401 0.118 C 0.401 0.118 0.401 0.119 0.400 0.119 C 0.399 0.120 0.399 0.119 0.400 0.118 C 0.400 0.117 0.400 0.116 0.399 0.116 C 0.398 0.115 0.397 0.115 0.396 0.115 C 0.396 0.116 0.396 0.115 0.396 0.113 C 0.395 0.108 0.394 0.108 0.393 0.112 C 0.392 0.116 0.388 0.119 0.388 0.117 C 0.388 0.116 0.388 0.114 0.387 0.112 C 0.386 0.110 0.386 0.110 0.385 0.113 C 0.384 0.117 0.383 0.117 0.382 0.114 C 0.382 0.112 0.382 0.112 0.382 0.114 C 0.382 0.116 0.381 0.116 0.381 0.114 C 0.380 0.113 0.380 0.113 0.380 0.115 C 0.380 0.118 0.379 0.124 0.378 0.122 C 0.378 0.119 0.377 0.121 0.377 0.124 C 0.377 0.125 0.376 0.126 0.375 0.125 C 0.373 0.125 0.373 0.126 0.373 0.127 C 0.373 0.129 0.372 0.129 0.372 0.127 C 0.372 0.126 0.371 0.125 0.371 0.126 C 0.371 0.126 0.370 0.126 0.370 0.123 C 0.370 0.121 0.370 0.120 0.369 0.120 C 0.369 0.120 0.369 0.119 0.369 0.118 C 0.369 0.116 0.368 0.118 0.368 0.120 C 0.367 0.125 0.367 0.125 0.364 0.124 C 0.363 0.124 0.362 0.122 0.361 0.120 C 0.360 0.115 0.358 0.114 0.358 0.117 C 0.357 0.119 0.356 0.120 0.356 0.120 C 0.355 0.120 0.355 0.120 0.355 0.121 C 0.355 0.122 0.355 0.124 0.355 0.124 C 0.354 0.125 0.352 0.123 0.349 0.117 C 0.349 0.116 0.348 0.115 0.347 0.116 C 0.347 0.117 0.346 0.117 0.346 0.117 C 0.345 0.116 0.343 0.123 0.344 0.126 C 0.344 0.128 0.344 0.129 0.343 0.129 C 0.343 0.129 0.343 0.129 0.343 0.130 C 0.343 0.132 0.340 0.129 0.339 0.126 C 0.339 0.124 0.338 0.123 0.336 0.123 C 0.336 0.123 0.336 0.124 0.336 0.126 C 0.336 0.128 0.336 0.129 0.335 0.128 C 0.335 0.127 0.334 0.128 0.333 0.132 C 0.332 0.135 0.332 0.137 0.332 0.137 C 0.332 0.138 0.332 0.138 0.331 0.139 C 0.331 0.140 0.330 0.140 0.330 0.139 C 0.330 0.138 0.330 0.138 0.329 0.138 C 0.329 0.140 0.328 0.136 0.328 0.131 C 0.328 0.126 0.327 0.124 0.326 0.127 C 0.323 0.132 0.323 0.132 0.322 0.131 C 0.322 0.131 0.322 0.131 0.322 0.132 C 0.322 0.134 0.322 0.134 0.321 0.132 C 0.321 0.130 0.321 0.129 0.320 0.129 C 0.320 0.129 0.319 0.127 0.319 0.124 C 0.318 0.121 0.317 0.120 0.316 0.120 C 0.315 0.120 0.315 0.121 0.315 0.123 C 0.316 0.125 0.316 0.125 0.314 0.123 C 0.313 0.121 0.313 0.121 0.312 0.125 C 0.312 0.129 0.309 0.130 0.310 0.126 C 0.310 0.125 0.310 0.125 0.309 0.127 C 0.309 0.128 0.308 0.129 0.308 0.128 C 0.307 0.128 0.307 0.128 0.307 0.129 C 0.307 0.130 0.304 0.129 0.302 0.127 C 0.302 0.127 0.301 0.127 0.302 0.128 C 0.302 0.129 0.302 0.130 0.301 0.130 C 0.301 0.130 0.301 0.129 0.301 0.129 C 0.301 0.126 0.298 0.126 0.297 0.129 C 0.297 0.131 0.297 0.131 0.296 0.130 C 0.295 0.129 0.295 0.129 0.295 0.130 C 0.295 0.133 0.294 0.132 0.293 0.129 C 0.292 0.125 0.291 0.124 0.291 0.127 C 0.291 0.130 0.289 0.127 0.288 0.124 C 0.288 0.122 0.288 0.121 0.288 0.121 C 0.288 0.121 0.288 0.120 0.287 0.118 C 0.285 0.114 0.284 0.115 0.284 0.119 C 0.284 0.121 0.284 0.121 0.283 0.120 C 0.283 0.120 0.282 0.120 0.282 0.121 C 0.282 0.122 0.282 0.123 0.281 0.123 C 0.281 0.123 0.281 0.122 0.281 0.121 C 0.281 0.121 0.281 0.120 0.281 0.120 C 0.281 0.120 0.280 0.118 0.280 0.116 C 0.280 0.113 0.279 0.113 0.278 0.113 C 0.277 0.113 0.276 0.114 0.277 0.115 C 0.277 0.116 0.277 0.116 0.276 0.116 C 0.276 0.116 0.276 0.117 0.276 0.118 C 0.276 0.120 0.276 0.119 0.275 0.118 C 0.274 0.115 0.274 0.115 0.272 0.118 C 0.271 0.120 0.270 0.121 0.270 0.120 C 0.270 0.119 0.270 0.118 0.269 0.118 C 0.269 0.118 0.269 0.117 0.270 0.116 C 0.272 0.115 0.272 0.115 0.270 0.115 C 0.267 0.117 0.266 0.117 0.266 0.115 C 0.265 0.112 0.261 0.112 0.260 0.115 C 0.258 0.118 0.253 0.119 0.253 0.116 C 0.253 0.115 0.252 0.115 0.252 0.116 C 0.251 0.118 0.249 0.119 0.247 0.119 C 0.244 0.119 0.243 0.119 0.243 0.116 C 0.242 0.114 0.241 0.113 0.240 0.114 C 0.238 0.115 0.237 0.116 0.238 0.118 C 0.239 0.119 0.239 0.119 0.238 0.120 C 0.238 0.121 0.237 0.121 0.237 0.120 C 0.238 0.118 0.235 0.114 0.234 0.115 C 0.233 0.116 0.233 0.117 0.233 0.118 C 0.234 0.120 0.234 0.121 0.232 0.122 C 0.231 0.123 0.231 0.123 0.231 0.122 C 0.232 0.121 0.232 0.121 0.231 0.119 C 0.231 0.116 0.227 0.113 0.227 0.116 C 0.227 0.117 0.227 0.118 0.227 0.119 C 0.226 0.120 0.225 0.120 0.226 0.118 C 0.227 0.117 0.227 0.116 0.226 0.116 C 0.225 0.116 0.225 0.117 0.224 0.118 C 0.224 0.119 0.223 0.119 0.223 0.118 C 0.223 0.117 0.223 0.117 0.221 0.117 C 0.220 0.118 0.220 0.117 0.220 0.116 C 0.221 0.115 0.221 0.115 0.220 0.114 C 0.219 0.113 0.219 0.113 0.218 0.114 C 0.218 0.114 0.219 0.114 0.219 0.114 C 0.219 0.114 0.219 0.115 0.219 0.117 C 0.218 0.121 0.215 0.118 0.215 0.113 C 0.215 0.112 0.215 0.110 0.214 0.109 C 0.214 0.109 0.214 0.109 0.214 0.111 C 0.214 0.113 0.214 0.113 0.213 0.112 C 0.212 0.111 0.212 0.112 0.212 0.113 C 0.212 0.114 0.211 0.114 0.211 0.114 C 0.210 0.114 0.210 0.116 0.211 0.119 C 0.211 0.121 0.211 0.121 0.210 0.121 C 0.210 0.121 0.209 0.121 0.209 0.120 C 0.209 0.117 0.202 0.114 0.202 0.117 C 0.201 0.117 0.201 0.118 0.200 0.117 C 0.200 0.116 0.199 0.117 0.198 0.119 L 0.197 0.122 L 0.198 0.118 L 0.198 0.114 L 0.197 0.116 C 0.196 0.116 0.196 0.116 0.196 0.115 C 0.196 0.113 0.196 0.113 0.195 0.113 C 0.195 0.113 0.194 0.114 0.194 0.115 C 0.195 0.118 0.192 0.117 0.191 0.114 C 0.191 0.110 0.190 0.110 0.190 0.113 C 0.191 0.116 0.189 0.119 0.188 0.117 C 0.188 0.116 0.188 0.117 0.188 0.118 C 0.188 0.119 0.188 0.122 0.187 0.124 C 0.186 0.128 0.186 0.128 0.186 0.124 C 0.187 0.121 0.187 0.121 0.186 0.123 C 0.185 0.125 0.185 0.125 0.185 0.123 C 0.184 0.121 0.184 0.121 0.185 0.124 C 0.185 0.127 0.185 0.127 0.180 0.124 C 0.179 0.123 0.179 0.123 0.179 0.125 C 0.180 0.127 0.180 0.127 0.179 0.126 C 0.178 0.125 0.177 0.125 0.176 0.125 C 0.176 0.125 0.176 0.124 0.176 0.122 C 0.176 0.121 0.176 0.120 0.175 0.120 C 0.175 0.120 0.175 0.121 0.175 0.122 C 0.175 0.124 0.175 0.125 0.174 0.125 C 0.174 0.125 0.174 0.126 0.174 0.126 C 0.174 0.127 0.175 0.128 0.175 0.129 C 0.175 0.131 0.172 0.129 0.171 0.126 C 0.171 0.125 0.171 0.125 0.170 0.126 C 0.170 0.126 0.170 0.126 0.170 0.124 C 0.170 0.123 0.170 0.121 0.170 0.121 C 0.170 0.121 0.169 0.121 0.168 0.121 C 0.167 0.120 0.167 0.121 0.167 0.122 C 0.167 0.123 0.167 0.123 0.168 0.123 C 0.168 0.123 0.168 0.124 0.168 0.125 C 0.168 0.127 0.167 0.127 0.165 0.126 C 0.162 0.124 0.162 0.124 0.163 0.123 L 0.165 0.122 L 0.163 0.121 C 0.163 0.120 0.162 0.120 0.162 0.120 C 0.162 0.121 0.161 0.121 0.161 0.120 C 0.160 0.118 0.159 0.119 0.159 0.122 C 0.159 0.123 0.159 0.123 0.159 0.123 C 0.158 0.123 0.158 0.118 0.159 0.117 C 0.159 0.117 0.159 0.117 0.158 0.117 C 0.157 0.117 0.157 0.119 0.156 0.120 C 0.156 0.121 0.156 0.121 0.155 0.121 C 0.155 0.121 0.154 0.122 0.155 0.123 C 0.155 0.124 0.154 0.125 0.153 0.126 C 0.151 0.126 0.150 0.128 0.151 0.128 C 0.151 0.129 0.151 0.131 0.150 0.131 C 0.150 0.132 0.150 0.131 0.150 0.130 C 0.150 0.128 0.149 0.127 0.148 0.127 C 0.147 0.127 0.146 0.126 0.147 0.125 C 0.148 0.124 0.148 0.123 0.147 0.123 C 0.146 0.123 0.145 0.124 0.145 0.126 C 0.144 0.129 0.142 0.130 0.142 0.127 C 0.142 0.126 0.140 0.126 0.137 0.126 C 0.134 0.127 0.132 0.126 0.133 0.125 C 0.133 0.124 0.132 0.124 0.131 0.125 C 0.130 0.126 0.129 0.125 0.128 0.124 C 0.128 0.123 0.127 0.121 0.127 0.121 C 0.128 0.121 0.128 0.119 0.127 0.118 C 0.127 0.116 0.126 0.115 0.124 0.115 C 0.120 0.115 0.119 0.117 0.119 0.122 C 0.119 0.124 0.119 0.126 0.118 0.127 C 0.117 0.128 0.117 0.129 0.118 0.130 C 0.118 0.131 0.117 0.132 0.116 0.132 C 0.115 0.133 0.114 0.132 0.113 0.128 C 0.112 0.124 0.110 0.120 0.110 0.123 C 0.110 0.124 0.110 0.125 0.109 0.126 C 0.109 0.126 0.108 0.128 0.108 0.129 C 0.108 0.131 0.108 0.132 0.107 0.133 C 0.107 0.134 0.106 0.135 0.107 0.136 C 0.107 0.138 0.103 0.141 0.102 0.140 C 0.102 0.139 0.101 0.140 0.101 0.142 C 0.100 0.144 0.100 0.145 0.099 0.144 C 0.098 0.143 0.097 0.143 0.097 0.144 C 0.097 0.146 0.096 0.145 0.092 0.143 C 0.091 0.142 0.089 0.142 0.089 0.142 C 0.089 0.143 0.087 0.145 0.085 0.146 C 0.083 0.147 0.081 0.149 0.080 0.151 C 0.079 0.153 0.078 0.153 0.077 0.153 C 0.076 0.152 0.076 0.152 0.076 0.153 C 0.076 0.154 0.076 0.155 0.075 0.155 C 0.075 0.155 0.075 0.156 0.076 0.157 C 0.077 0.158 0.077 0.158 0.075 0.158 C 0.074 0.158 0.072 0.159 0.072 0.160 C 0.071 0.163 0.071 0.161 0.072 0.157 C 0.073 0.155 0.072 0.155 0.071 0.155 C 0.069 0.154 0.068 0.155 0.067 0.158 C 0.066 0.160 0.065 0.160 0.064 0.160 C 0.063 0.159 0.063 0.159 0.064 0.160 C 0.065 0.162 0.065 0.163 0.064 0.164 C 0.064 0.164 0.064 0.165 0.065 0.165 C 0.066 0.165 0.066 0.164 0.066 0.163 C 0.066 0.161 0.067 0.162 0.069 0.165 C 0.070 0.166 0.071 0.168 0.072 0.168 C 0.073 0.168 0.073 0.168 0.073 0.169 C 0.073 0.171 0.073 0.171 0.074 0.169 C 0.075 0.166 0.075 0.167 0.075 0.170 C 0.075 0.171 0.075 0.173 0.075 0.173 C 0.076 0.174 0.076 0.175 0.076 0.177 C 0.075 0.181 0.079 0.185 0.081 0.184 C 0.082 0.184 0.083 0.184 0.083 0.184 C 0.082 0.185 0.082 0.186 0.082 0.187 C 0.083 0.188 0.083 0.188 0.082 0.188 C 0.082 0.187 0.081 0.188 0.081 0.190 C 0.080 0.192 0.077 0.194 0.074 0.195 C 0.069 0.198 0.065 0.203 0.067 0.205 C 0.068 0.205 0.068 0.205 0.068 0.204 C 0.067 0.202 0.068 0.203 0.068 0.204 C 0.069 0.206 0.070 0.207 0.073 0.207 C 0.077 0.207 0.078 0.207 0.077 0.209 C 0.077 0.210 0.076 0.211 0.075 0.212 C 0.074 0.213 0.072 0.213 0.071 0.214 C 0.070 0.215 0.070 0.216 0.070 0.217 C 0.070 0.218 0.070 0.219 0.069 0.219 C 0.069 0.220 0.068 0.221 0.068 0.222 C 0.067 0.223 0.066 0.224 0.065 0.224 C 0.063 0.225 0.062 0.226 0.062 0.227 C 0.062 0.229 0.060 0.227 0.060 0.225 C 0.060 0.224 0.060 0.224 0.060 0.225 C 0.059 0.227 0.054 0.227 0.054 0.225 C 0.053 0.224 0.053 0.224 0.053 0.226 C 0.053 0.228 0.053 0.229 0.054 0.230 C 0.055 0.230 0.056 0.231 0.057 0.232 C 0.058 0.232 0.058 0.232 0.058 0.231 C 0.057 0.229 0.061 0.230 0.064 0.233 C 0.064 0.234 0.065 0.234 0.066 0.233 C 0.066 0.233 0.067 0.233 0.067 0.235 C 0.067 0.237 0.068 0.238 0.069 0.238 C 0.071 0.238 0.071 0.238 0.071 0.242 C 0.071 0.245 0.071 0.247 0.071 0.248 C 0.072 0.250 0.072 0.253 0.070 0.254 C 0.069 0.254 0.070 0.254 0.071 0.255 C 0.072 0.257 0.072 0.257 0.070 0.257 C 0.069 0.257 0.069 0.258 0.070 0.259 C 0.071 0.260 0.070 0.260 0.069 0.263 C 0.068 0.265 0.068 0.266 0.069 0.266 C 0.069 0.266 0.070 0.267 0.070 0.268 C 0.070 0.270 0.070 0.271 0.071 0.271 C 0.072 0.271 0.072 0.273 0.071 0.277 C 0.070 0.279 0.069 0.280 0.067 0.281 C 0.063 0.282 0.062 0.284 0.063 0.287 C 0.063 0.289 0.061 0.292 0.059 0.293 C 0.057 0.293 0.057 0.293 0.059 0.294 L 0.061 0.295 L 0.059 0.295 C 0.058 0.296 0.057 0.295 0.056 0.294 C 0.055 0.293 0.053 0.294 0.051 0.295 C 0.049 0.296 0.047 0.297 0.048 0.297 C 0.048 0.297 0.048 0.299 0.048 0.300 C 0.048 0.303 0.047 0.303 0.047 0.300 C 0.047 0.299 0.046 0.298 0.045 0.298 C 0.044 0.298 0.044 0.298 0.044 0.299 C 0.045 0.301 0.044 0.301 0.042 0.300 C 0.041 0.300 0.040 0.300 0.040 0.301 C 0.040 0.303 0.040 0.303 0.040 0.302 C 0.042 0.301 0.042 0.304 0.041 0.306 C 0.040 0.308 0.041 0.308 0.042 0.308 C 0.043 0.308 0.047 0.308 0.051 0.309 C 0.055 0.310 0.058 0.310 0.057 0.309 C 0.057 0.308 0.058 0.307 0.059 0.308 C 0.060 0.308 0.064 0.309 0.066 0.309 C 0.074 0.310 0.073 0.310 0.073 0.313 C 0.073 0.314 0.072 0.315 0.071 0.315 C 0.071 0.315 0.070 0.316 0.070 0.317 C 0.070 0.317 0.068 0.320 0.067 0.321 C 0.065 0.323 0.064 0.325 0.063 0.326 C 0.063 0.327 0.056 0.331 0.053 0.331 C 0.052 0.331 0.053 0.332 0.053 0.333 C 0.054 0.335 0.055 0.335 0.055 0.333 C 0.055 0.329 0.056 0.331 0.056 0.335 C 0.056 0.340 0.054 0.342 0.050 0.342 C 0.049 0.342 0.047 0.343 0.047 0.343 C 0.047 0.344 0.047 0.345 0.048 0.345 C 0.048 0.345 0.048 0.346 0.048 0.347 C 0.048 0.349 0.046 0.350 0.045 0.348 C 0.045 0.347 0.044 0.347 0.044 0.348 C 0.044 0.349 0.043 0.351 0.042 0.352 L 0.040 0.353 L 0.042 0.353 C 0.043 0.353 0.044 0.354 0.044 0.355 C 0.044 0.357 0.045 0.357 0.045 0.356 C 0.045 0.354 0.045 0.354 0.046 0.356 C 0.046 0.357 0.046 0.357 0.046 0.357 C 0.046 0.356 0.047 0.356 0.047 0.357 C 0.047 0.359 0.048 0.359 0.049 0.358 C 0.049 0.358 0.049 0.358 0.049 0.360 C 0.049 0.361 0.050 0.361 0.050 0.360 C 0.050 0.358 0.051 0.358 0.052 0.359 C 0.052 0.360 0.053 0.360 0.053 0.360 C 0.053 0.359 0.053 0.360 0.054 0.361 C 0.055 0.363 0.058 0.362 0.057 0.359 C 0.056 0.357 0.058 0.358 0.060 0.361 C 0.061 0.362 0.063 0.363 0.065 0.363 C 0.068 0.363 0.070 0.363 0.069 0.364 C 0.069 0.365 0.070 0.366 0.070 0.366 C 0.071 0.366 0.071 0.367 0.071 0.369 C 0.071 0.371 0.072 0.372 0.073 0.372 C 0.075 0.372 0.075 0.372 0.074 0.373 C 0.073 0.375 0.067 0.377 0.064 0.377 C 0.064 0.377 0.063 0.379 0.063 0.380 C 0.063 0.383 0.062 0.384 0.061 0.383 L 0.060 0.382 L 0.061 0.384 C 0.063 0.386 0.063 0.388 0.062 0.387 C 0.061 0.386 0.061 0.387 0.060 0.388 C 0.060 0.389 0.060 0.389 0.061 0.389 C 0.062 0.389 0.063 0.390 0.063 0.393 C 0.064 0.395 0.065 0.396 0.067 0.397 C 0.070 0.398 0.071 0.399 0.070 0.401 C 0.069 0.403 0.069 0.403 0.070 0.403 C 0.071 0.404 0.068 0.406 0.065 0.409 C 0.063 0.409 0.061 0.412 0.060 0.415 L 0.058 0.419 L 0.060 0.419 C 0.064 0.419 0.065 0.423 0.061 0.425 C 0.057 0.427 0.057 0.430 0.060 0.432 C 0.062 0.433 0.063 0.434 0.063 0.436 C 0.064 0.438 0.065 0.439 0.068 0.440 C 0.072 0.441 0.073 0.443 0.073 0.447 C 0.073 0.448 0.071 0.451 0.068 0.454 C 0.067 0.455 0.065 0.455 0.064 0.455 C 0.060 0.454 0.050 0.458 0.049 0.460 C 0.048 0.462 0.047 0.464 0.048 0.466 C 0.049 0.466 0.048 0.466 0.047 0.466 C 0.046 0.465 0.045 0.466 0.045 0.467 C 0.044 0.468 0.044 0.468 0.045 0.468 C 0.045 0.468 0.046 0.469 0.046 0.470 C 0.045 0.472 0.047 0.473 0.049 0.472 C 0.049 0.472 0.049 0.473 0.050 0.474 C 0.050 0.475 0.051 0.475 0.051 0.474 C 0.053 0.472 0.055 0.472 0.055 0.474 C 0.055 0.475 0.056 0.475 0.057 0.475 C 0.058 0.475 0.059 0.475 0.058 0.473 C 0.057 0.472 0.057 0.472 0.058 0.473 C 0.062 0.475 0.063 0.475 0.063 0.473 C 0.062 0.472 0.063 0.472 0.063 0.472 C 0.066 0.475 0.066 0.476 0.066 0.474 C 0.065 0.473 0.066 0.472 0.067 0.473 C 0.068 0.473 0.069 0.474 0.069 0.474 C 0.069 0.474 0.069 0.475 0.068 0.476 C 0.067 0.478 0.066 0.479 0.067 0.479 C 0.069 0.478 0.070 0.479 0.070 0.481 C 0.070 0.484 0.073 0.488 0.074 0.487 C 0.075 0.487 0.075 0.487 0.075 0.488 C 0.075 0.488 0.077 0.489 0.079 0.490 C 0.082 0.490 0.083 0.491 0.084 0.494 C 0.085 0.496 0.086 0.497 0.089 0.497 C 0.092 0.497 0.093 0.497 0.092 0.498 C 0.092 0.499 0.091 0.500 0.090 0.500 C 0.089 0.500 0.088 0.501 0.088 0.502 C 0.088 0.504 0.087 0.504 0.086 0.501 C 0.085 0.500 0.085 0.500 0.086 0.501 C 0.086 0.504 0.086 0.504 0.084 0.501 C 0.083 0.499 0.082 0.499 0.082 0.500 C 0.083 0.501 0.082 0.502 0.081 0.502 C 0.079 0.502 0.079 0.502 0.080 0.504 C 0.081 0.505 0.081 0.505 0.080 0.505 C 0.079 0.505 0.079 0.506 0.079 0.509 C 0.079 0.511 0.079 0.512 0.078 0.513 C 0.078 0.514 0.077 0.515 0.078 0.516 C 0.078 0.517 0.077 0.517 0.076 0.517 C 0.075 0.516 0.075 0.516 0.075 0.518 C 0.075 0.520 0.075 0.521 0.077 0.521 L 0.078 0.522 L 0.077 0.522 C 0.074 0.523 0.074 0.525 0.075 0.526 C 0.076 0.528 0.075 0.528 0.074 0.528 C 0.073 0.528 0.073 0.527 0.073 0.525 C 0.073 0.524 0.073 0.523 0.072 0.524 C 0.072 0.524 0.071 0.524 0.071 0.523 C 0.071 0.521 0.071 0.521 0.071 0.522 C 0.072 0.523 0.072 0.523 0.072 0.522 C 0.071 0.521 0.070 0.519 0.068 0.518 C 0.064 0.515 0.063 0.515 0.064 0.518 C 0.065 0.519 0.065 0.520 0.065 0.521 C 0.065 0.522 0.064 0.522 0.064 0.520 C 0.063 0.517 0.062 0.517 0.062 0.520 C 0.063 0.523 0.061 0.523 0.051 0.526 C 0.044 0.527 0.035 0.532 0.035 0.535 C 0.035 0.538 0.030 0.540 0.027 0.539 C 0.026 0.538 0.024 0.539 0.024 0.541 C 0.024 0.541 0.024 0.542 0.024 0.542 C 0.023 0.542 0.023 0.543 0.024 0.544 C 0.024 0.545 0.025 0.545 0.025 0.545 C 0.025 0.544 0.025 0.545 0.026 0.546 C 0.026 0.547 0.027 0.548 0.029 0.548 C 0.031 0.548 0.033 0.548 0.033 0.549 C 0.033 0.551 0.034 0.551 0.034 0.550 C 0.036 0.549 0.039 0.552 0.039 0.555 C 0.039 0.555 0.039 0.555 0.040 0.555 C 0.041 0.554 0.041 0.555 0.041 0.556 C 0.041 0.558 0.041 0.558 0.059 0.559 C 0.073 0.559 0.076 0.560 0.072 0.562 C 0.070 0.563 0.068 0.564 0.067 0.565 C 0.066 0.566 0.065 0.567 0.064 0.567 C 0.063 0.567 0.062 0.568 0.062 0.569 C 0.062 0.570 0.062 0.570 0.061 0.570 C 0.060 0.570 0.059 0.571 0.058 0.572 C 0.057 0.573 0.054 0.574 0.052 0.575 C 0.047 0.575 0.040 0.579 0.040 0.581 C 0.039 0.583 0.039 0.584 0.040 0.587 C 0.041 0.588 0.041 0.590 0.042 0.590 C 0.042 0.590 0.042 0.591 0.041 0.593 C 0.041 0.594 0.040 0.596 0.039 0.595 C 0.038 0.595 0.037 0.596 0.038 0.597 C 0.038 0.599 0.039 0.599 0.041 0.599 C 0.044 0.598 0.052 0.604 0.054 0.607 C 0.054 0.607 0.057 0.608 0.060 0.608 C 0.063 0.608 0.066 0.608 0.066 0.609 C 0.066 0.610 0.064 0.610 0.062 0.611 C 0.058 0.611 0.056 0.612 0.050 0.614 C 0.049 0.614 0.047 0.615 0.047 0.616 C 0.046 0.618 0.046 0.618 0.049 0.621 C 0.050 0.621 0.050 0.622 0.049 0.623 C 0.049 0.625 0.049 0.625 0.049 0.625 C 0.050 0.625 0.050 0.625 0.049 0.627 C 0.049 0.628 0.049 0.629 0.049 0.629 C 0.050 0.629 0.049 0.630 0.049 0.631 L 0.047 0.633 L 0.049 0.634 C 0.049 0.635 0.051 0.635 0.051 0.634 L 0.052 0.633 L 0.051 0.637 C 0.050 0.641 0.051 0.642 0.052 0.638 C 0.053 0.636 0.053 0.636 0.055 0.639 C 0.056 0.642 0.057 0.642 0.056 0.643 C 0.055 0.644 0.054 0.645 0.054 0.645 C 0.053 0.646 0.053 0.646 0.054 0.643 C 0.055 0.641 0.055 0.641 0.054 0.642 C 0.053 0.642 0.052 0.644 0.052 0.645 C 0.052 0.645 0.051 0.646 0.051 0.646 C 0.050 0.646 0.050 0.647 0.051 0.648 L 0.052 0.649 L 0.051 0.650 C 0.050 0.650 0.050 0.650 0.051 0.653 C 0.052 0.654 0.053 0.657 0.053 0.658 C 0.053 0.659 0.054 0.660 0.056 0.660 C 0.059 0.660 0.061 0.663 0.060 0.666 C 0.060 0.667 0.060 0.667 0.061 0.666 C 0.062 0.664 0.062 0.664 0.063 0.666 C 0.063 0.668 0.065 0.669 0.066 0.670 C 0.070 0.671 0.071 0.672 0.071 0.674 C 0.071 0.675 0.069 0.676 0.068 0.676 C 0.065 0.676 0.063 0.678 0.063 0.681 C 0.063 0.683 0.063 0.684 0.064 0.684 C 0.064 0.685 0.065 0.686 0.064 0.687 C 0.064 0.687 0.066 0.689 0.067 0.689 C 0.069 0.690 0.070 0.692 0.071 0.694 L 0.072 0.697 L 0.071 0.698 C 0.070 0.699 0.069 0.700 0.069 0.701 C 0.068 0.702 0.067 0.703 0.066 0.703 C 0.065 0.703 0.065 0.703 0.065 0.704 C 0.065 0.706 0.066 0.707 0.069 0.709 C 0.070 0.709 0.071 0.711 0.071 0.712 C 0.071 0.713 0.072 0.716 0.073 0.718 C 0.074 0.723 0.074 0.725 0.072 0.729 C 0.071 0.731 0.070 0.735 0.070 0.737 C 0.070 0.741 0.070 0.742 0.071 0.745 C 0.071 0.747 0.071 0.748 0.071 0.747 C 0.071 0.747 0.072 0.747 0.072 0.748 C 0.072 0.749 0.073 0.751 0.073 0.752 C 0.072 0.753 0.073 0.754 0.073 0.754 C 0.073 0.754 0.074 0.755 0.074 0.756 C 0.074 0.757 0.075 0.759 0.076 0.760 C 0.077 0.761 0.077 0.761 0.077 0.762 C 0.076 0.763 0.076 0.769 0.077 0.769 C 0.078 0.769 0.081 0.770 0.080 0.771 C 0.079 0.771 0.079 0.772 0.079 0.773 C 0.079 0.774 0.079 0.776 0.078 0.778 C 0.077 0.779 0.077 0.781 0.077 0.782 C 0.077 0.782 0.076 0.784 0.076 0.785 C 0.074 0.788 0.074 0.794 0.076 0.796 C 0.078 0.799 0.077 0.801 0.074 0.801 C 0.070 0.801 0.069 0.803 0.068 0.808 C 0.067 0.813 0.067 0.820 0.069 0.824 C 0.070 0.827 0.071 0.829 0.071 0.829 C 0.071 0.830 0.067 0.834 0.065 0.835 C 0.063 0.836 0.063 0.838 0.064 0.839 C 0.065 0.840 0.065 0.842 0.066 0.843 C 0.066 0.844 0.067 0.845 0.068 0.846 C 0.068 0.846 0.071 0.848 0.074 0.850 C 0.082 0.855 0.082 0.859 0.076 0.862 C 0.074 0.863 0.069 0.868 0.070 0.868 C 0.071 0.868 0.071 0.869 0.071 0.870 C 0.071 0.871 0.071 0.872 0.072 0.872 C 0.072 0.872 0.073 0.872 0.074 0.873 C 0.075 0.875 0.075 0.876 0.074 0.877 C 0.073 0.878 0.077 0.881 0.083 0.883 C 0.085 0.884 0.086 0.885 0.087 0.885 C 0.087 0.885 0.089 0.886 0.090 0.886 C 0.092 0.887 0.094 0.890 0.096 0.892 C 0.097 0.894 0.099 0.897 0.099 0.897 C 0.100 0.898 0.101 0.899 0.101 0.900 C 0.101 0.901 0.102 0.902 0.103 0.903 C 0.103 0.905 0.104 0.906 0.104 0.907 C 0.104 0.909 0.105 0.910 0.107 0.910 C 0.108 0.910 0.110 0.911 0.110 0.912 C 0.110 0.912 0.113 0.913 0.116 0.913 C 0.121 0.913 0.122 0.913 0.123 0.916 C 0.124 0.917 0.124 0.918 0.125 0.918 C 0.125 0.917 0.125 0.918 0.125 0.919 C 0.125 0.920 0.126 0.921 0.127 0.921 C 0.127 0.921 0.128 0.922 0.128 0.922 C 0.128 0.926 0.130 0.926 0.131 0.923 C 0.132 0.921 0.132 0.921 0.134 0.921 C 0.135 0.922 0.136 0.922 0.136 0.921 C 0.135 0.919 0.138 0.917 0.140 0.918 C 0.140 0.919 0.141 0.921 0.141 0.922 C 0.141 0.923 0.141 0.924 0.142 0.923 C 0.142 0.923 0.142 0.923 0.142 0.925 C 0.142 0.928 0.144 0.930 0.145 0.929 C 0.145 0.928 0.145 0.928 0.146 0.929 C 0.146 0.932 0.157 0.932 0.158 0.930 C 0.159 0.928 0.162 0.927 0.162 0.929 C 0.162 0.933 0.163 0.932 0.164 0.928 C 0.165 0.924 0.166 0.925 0.166 0.929 C 0.166 0.932 0.168 0.938 0.169 0.937 C 0.169 0.937 0.170 0.937 0.170 0.938 C 0.170 0.941 0.172 0.941 0.172 0.938 C 0.173 0.937 0.173 0.937 0.174 0.937 C 0.174 0.937 0.175 0.936 0.175 0.935 C 0.175 0.932 0.179 0.931 0.180 0.933 C 0.180 0.934 0.181 0.934 0.181 0.933 C 0.182 0.931 0.182 0.932 0.182 0.935 C 0.184 0.941 0.185 0.947 0.186 0.947 C 0.186 0.947 0.188 0.945 0.189 0.943 C 0.190 0.940 0.192 0.939 0.192 0.939 C 0.192 0.940 0.193 0.939 0.194 0.938 C 0.194 0.936 0.195 0.937 0.197 0.941 C 0.199 0.945 0.200 0.945 0.201 0.940 C 0.202 0.938 0.202 0.938 0.202 0.940 C 0.203 0.941 0.203 0.942 0.204 0.942 C 0.205 0.942 0.206 0.943 0.206 0.945 C 0.206 0.947 0.206 0.947 0.207 0.946 C 0.210 0.944 0.210 0.944 0.210 0.945 C 0.210 0.946 0.212 0.947 0.213 0.947 C 0.215 0.947 0.216 0.948 0.216 0.949 C 0.216 0.950 0.216 0.951 0.217 0.951 C 0.218 0.951 0.218 0.952 0.218 0.953 C 0.218 0.953 0.218 0.954 0.218 0.954 C 0.218 0.954 0.218 0.953 0.218 0.952 C 0.218 0.950 0.219 0.948 0.220 0.948 C 0.220 0.947 0.221 0.946 0.220 0.946 C 0.220 0.945 0.220 0.942 0.220 0.942 C 0.221 0.942 0.221 0.943 0.221 0.944 C 0.221 0.947 0.224 0.949 0.227 0.949 C 0.228 0.950 0.228 0.950 0.228 0.951 C 0.228 0.955 0.234 0.956 0.235 0.952 C 0.236 0.949 0.239 0.948 0.239 0.950 C 0.239 0.951 0.240 0.952 0.241 0.952 C 0.241 0.952 0.242 0.956 0.243 0.960 L 0.245 0.967 L 0.247 0.964 C 0.248 0.963 0.250 0.961 0.251 0.961 C 0.252 0.961 0.252 0.961 0.252 0.959 C 0.252 0.955 0.253 0.955 0.253 0.959 C 0.254 0.963 0.256 0.963 0.256 0.959 C 0.256 0.956 0.258 0.965 0.259 0.969 C 0.259 0.972 0.260 0.974 0.260 0.974 C 0.260 0.974 0.260 0.975 0.260 0.976 C 0.260 0.979 0.262 0.975 0.263 0.971 C 0.264 0.968 0.265 0.967 0.266 0.968 C 0.266 0.968 0.267 0.969 0.267 0.970 C 0.267 0.973 0.270 0.980 0.272 0.980 C 0.274 0.980 0.275 0.982 0.277 0.987 C 0.279 0.991 0.280 0.991 0.280 0.987 C 0.280 0.984 0.283 0.981 0.284 0.983 C 0.285 0.984 0.286 0.984 0.286 0.982 C 0.287 0.979 0.288 0.980 0.290 0.985 C 0.291 0.986 0.292 0.986 0.293 0.983 C 0.293 0.982 0.294 0.981 0.295 0.981 C 0.295 0.982 0.296 0.981 0.296 0.980 C 0.297 0.976 0.298 0.977 0.300 0.981 C 0.302 0.985 0.302 0.985 0.304 0.982 C 0.306 0.979 0.308 0.979 0.307 0.982 C 0.307 0.983 0.308 0.984 0.308 0.984 C 0.312 0.985 0.314 0.986 0.315 0.987 C 0.315 0.987 0.316 0.987 0.316 0.986 C 0.317 0.985 0.318 0.985 0.318 0.986 C 0.319 0.988 0.319 0.988 0.320 0.986 C 0.321 0.985 0.322 0.985 0.322 0.986 C 0.322 0.987 0.323 0.987 0.323 0.986 C 0.324 0.983 0.328 0.982 0.328 0.984 C 0.329 0.991 0.334 0.994 0.337 0.990 C 0.339 0.987 0.339 0.987 0.339 0.990 C 0.338 0.991 0.339 0.991 0.339 0.991 C 0.340 0.990 0.341 0.991 0.341 0.992 C 0.341 0.994 0.342 0.995 0.342 0.994 C 0.342 0.994 0.343 0.994 0.343 0.995 C 0.343 0.996 0.344 0.997 0.344 0.997 C 0.345 0.997 0.346 0.997 0.346 0.998 C 0.347 1.000 0.347 0.999 0.348 0.997 C 0.348 0.996 0.349 0.995 0.350 0.995 C 0.351 0.995 0.353 0.994 0.354 0.992 C 0.356 0.990 0.356 0.990 0.356 0.992 C 0.356 0.994 0.357 0.995 0.359 0.994 C 0.360 0.993 0.361 0.993 0.362 0.994 C 0.362 0.996 0.363 0.996 0.366 0.995 C 0.368 0.995 0.369 0.995 0.369 0.996 C 0.368 0.999 0.371 1.001 0.373 0.998 C 0.375 0.997 0.375 0.997 0.376 0.998 C 0.377 1.001 0.379 1.001 0.379 0.998 L 0.379 0.998 Z',\n  [MaskTypes.ROUNDED]:\n    'M 0.000000 , 0.158046 c 0.000000 , -0.085879 0.072167 , -0.158046 0.158046 , -0.158046 l 0.683908 , 0.000000 c 0.085879 , 0.000000 0.158046 , 0.072167 0.158046 , 0.158046 l 0.000000 , 0.000000 c 0.000000 , 0.085879 -0.072167 , 0.158046 -0.158046 , 0.158046 l -0.683908 , 0.000000 c -0.085879 , 0.000000 -0.158046 , -0.072167 -0.158046 , -0.158046 Z',\n  [MaskTypes.ROUNDED_2]:\n    'M 0.883212 0.000000 C 0.961058 0.000000 1.000000 0.038942 1.000000 0.116788 C 1.000000 0.116788 1.000000 0.116788 1.000000 0.116788 C 1.000000 0.194635 0.961058 0.233577 0.883212 0.233577 C 0.423358 0.233577 0.167883 0.233577 0.116788 0.233577 C 0.038942 0.233577 0.000000 0.194635 0.000000 0.116788 C 0.000000 0.116788 0.000000 0.116788 0.000000 0.116788 C 0.000000 0.038942 0.038942 0.000000 0.116788 0.000000 C 0.576642 0.000000 0.832117 0.000000 0.883212 0.000000 Z',\n  [MaskTypes.CHAT_BUBBLE]:\n    'M 0.142857 0.001488 C 0.063959 0.001488 0.000000 0.065447 0.000000 0.144345 V 0.382440 C 0.000000 0.461339 0.063959 0.525298 0.142857 0.525298 H 0.819482 L 0.898810 0.607143 V 0.514914 C 0.951164 0.493720 0.988095 0.442393 0.988095 0.382440 V 0.144345 C 0.988095 0.065447 0.924137 0.001488 0.845238 0.001488 H 0.142857 Z',\n  [MaskTypes.CHECK_MARK]:\n    'M 0.356388 , 0.780019 L 0.000000 , 0.423631 L 0.135447 , 0.288184 l 0.219981 , 0.219981 L 0.864553 , 0.000000 l 0.135447 , 0.135447 L 0.356388 , 0.780019 z',\n  [MaskTypes.NEW_MUSIC]:\n    'M 0.377812 , 0.012500 l 0.047375 , 0.130375 l -0.012937 , 0.004812 L 0.300750 , 0.064438 l 0.039875 , 0.109688 l -0.012937 , 0.004812 L 0.280250 , 0.048500 L 0.293250 , 0.043750 l 0.111437 , 0.083000 L 0.364875 , 0.017313 L 0.377812 , 0.012500 z  M 0.492750 , 0.140500 c -0.030562 , 0.000750 -0.053312 -0.020188 -0.054125 -0.054500 c -0.000813 -0.034563 , 0.020563 -0.056313 , 0.051500 -0.057063 c 0.031563 -0.000750 , 0.051375 , 0.021375 , 0.052062 , 0.049000 c 0.000125 , 0.004375 , 0.000188 , 0.007125 -0.000125 , 0.010937 l -0.089250 , 0.002187 c 0.001812 , 0.025375 , 0.019625 , 0.038250 , 0.039750 , 0.037812 c 0.018313 -0.000438 , 0.030500 -0.010500 , 0.034125 -0.025062 l 0.014563 -0.000375 C 0.536750 , 0.123875 , 0.519813 , 0.139813 , 0.492750 , 0.140500 z  M 0.452500 , 0.079625 l 0.075687 -0.001812 c 0.000000 -0.025250 -0.018438 -0.037500 -0.038375 -0.037000 C 0.470313 , 0.041250 , 0.453437 , 0.054375 , 0.452500 , 0.079625 z  M 0.581687 , 0.031000 l 0.013187 , 0.004687 l -0.005812 , 0.098000 l 0.059562 -0.078875 l 0.013000 , 0.004625 l -0.003125 , 0.099125 l 0.056250 -0.080250 l 0.012812 , 0.004562 l -0.067562 , 0.091000 l -0.013000 -0.004625 l 0.001937 -0.095750 l -0.058125 , 0.075875 l -0.013187 -0.004687 L 0.581687 , 0.031000 z  M 0.842750 , 0.134563 l 0.009187 , 0.011437 l -0.058625 , 0.115875 l 0.124812 -0.033375 l 0.009312 , 0.011562 l -0.105813 , 0.086125 l -0.008687 -0.010812 l 0.084500 -0.068750 l -0.115000 , 0.030750 l -0.006313 -0.007875 l 0.053750 -0.106500 L 0.745625 , 0.231438 l -0.008687 -0.010812 L 0.842750 , 0.134563 z  M 0.855813 , 0.435438 l -0.004188 -0.013250 l 0.018063 -0.005750 c -0.014938 -0.002125 -0.026000 -0.013562 -0.030812 -0.028937 c -0.007375 -0.023500 , 0.001063 -0.046562 , 0.031187 -0.056188 l 0.059937 -0.019125 l 0.004125 , 0.013062 l -0.058437 , 0.018625 c -0.022750 , 0.007250 -0.030500 , 0.023500 -0.024563 , 0.042438 c 0.006063 , 0.019312 , 0.022312 , 0.028937 , 0.047313 , 0.020938 l 0.055813 -0.017813 l 0.004188 , 0.013250 L 0.855813 , 0.435438 z  M 0.856875 , 0.495375 c -0.000500 -0.024625 , 0.011312 -0.042188 , 0.031000 -0.044375 l 0.000313 , 0.014313 c -0.011813 , 0.001437 -0.020063 , 0.011938 -0.019688 , 0.029625 c 0.000313 , 0.015500 , 0.008750 , 0.024063 , 0.019062 , 0.023813 c 0.026625 -0.000562 , 0.009687 -0.065375 , 0.050062 -0.066250 c 0.016000 -0.000313 , 0.029500 , 0.014688 , 0.030000 , 0.037500 c 0.000500 , 0.023250 -0.011375 , 0.038812 -0.032063 , 0.040438 l -0.000313 -0.013875 c 0.012000 -0.001063 , 0.020875 -0.010187 , 0.020563 -0.026687 c -0.000313 -0.014500 -0.008188 -0.023500 -0.017625 -0.023250 c -0.029187 , 0.000625 -0.012250 , 0.064438 -0.050313 , 0.065875 C 0.870500 , 0.532875 , 0.857375 , 0.517813 , 0.856875 , 0.495375 z  M 0.960938 , 0.570625 l -0.002250 , 0.013750 l -0.106187 -0.017813 l 0.002250 -0.013750 L 0.960938 , 0.570625 z  M 0.991563 , 0.572625 c 0.005812 , 0.001000 , 0.009187 , 0.006188 , 0.008250 , 0.011687 c -0.000937 , 0.005500 -0.005750 , 0.009312 -0.011562 , 0.008313 c -0.005875 -0.001000 -0.009375 -0.006188 -0.008438 -0.011687 C 0.980750 , 0.575375 , 0.985750 , 0.571625 , 0.991563 , 0.572625 z  M 0.934375 , 0.674813 c -0.009938 , 0.025250 -0.029812 , 0.036375 -0.052312 , 0.032688 l 0.005437 -0.013813 c 0.015563 , 0.002375 , 0.029187 -0.006250 , 0.035875 -0.023250 c 0.007813 -0.019750 , 0.000750 -0.041188 -0.026375 -0.052000 c -0.027125 -0.010875 -0.047000 -0.000188 -0.054813 , 0.019563 c -0.006688 , 0.017000 -0.002812 , 0.032438 , 0.010437 , 0.041813 l -0.005500 , 0.013813 c -0.018125 -0.012625 -0.025812 -0.034687 -0.015813 -0.060000 c 0.011187 -0.028437 , 0.039063 -0.041000 , 0.070750 -0.028313 C 0.933875 , 0.618000 , 0.945562 , 0.646375 , 0.934375 , 0.674813 z  M 0.622188 , 0.987500 l -0.047375 -0.130375 l 0.012937 -0.004812 l 0.111500 , 0.083187 l -0.039875 -0.109688 l 0.012937 -0.004750 l 0.047375 , 0.130375 l -0.012937 , 0.004812 l -0.111437 -0.083000 l 0.039813 , 0.109500 L 0.622188 , 0.987500 z  M 0.507250 , 0.859500 c 0.030562 -0.000750 , 0.053312 , 0.020188 , 0.054125 , 0.054500 c 0.000813 , 0.034563 -0.020563 , 0.056313 -0.051500 , 0.057063 c -0.031563 , 0.000750 -0.051375 -0.021375 -0.052062 -0.049000 c -0.000125 -0.004375 -0.000188 -0.007125 , 0.000125 -0.010937 l 0.089250 -0.002187 c -0.001812 -0.025375 -0.019625 -0.038250 -0.039750 -0.037812 c -0.018313 , 0.000438 -0.030500 , 0.010500 -0.034125 , 0.025062 l -0.014563 , 0.000375 C 0.463250 , 0.876125 , 0.480250 , 0.860187 , 0.507250 , 0.859500 z  M 0.547500 , 0.920375 l -0.075687 , 0.001812 c 0.000000 , 0.025250 , 0.018438 , 0.037500 , 0.038375 , 0.037000 C 0.529687 , 0.958750 , 0.546563 , 0.945625 , 0.547500 , 0.920375 z  M 0.418313 , 0.969063 l -0.013187 -0.004687 l 0.005812 -0.098000 l -0.059562 , 0.078875 l -0.013000 -0.004625 l 0.003125 -0.099125 l -0.056250 , 0.080250 l -0.012812 -0.004562 l 0.067562 -0.091000 l 0.013000 , 0.004625 l -0.001937 , 0.095750 l 0.058062 -0.075875 l 0.013187 , 0.004687 L 0.418313 , 0.969063 z  M 0.157250 , 0.865500 l -0.009187 -0.011437 l 0.058625 -0.115875 l -0.124812 , 0.033375 l -0.009312 -0.011562 l 0.105813 -0.086125 l 0.008687 , 0.010812 l -0.084500 , 0.068750 l 0.115000 -0.030750 l 0.006313 , 0.007875 l -0.053750 , 0.106500 l 0.084187 -0.068500 l 0.008687 , 0.010812 L 0.157250 , 0.865500 z  M 0.144250 , 0.564625 l 0.004188 , 0.013250 l -0.018063 , 0.005750 c 0.014938 , 0.002125 , 0.026000 , 0.013562 , 0.030812 , 0.028937 c 0.007375 , 0.023500 -0.001063 , 0.046562 -0.031187 , 0.056188 l -0.059937 , 0.019125 l -0.004125 -0.013062 l 0.058437 -0.018625 c 0.022750 -0.007250 , 0.030500 -0.023500 , 0.024500 -0.042438 c -0.006063 -0.019312 -0.022312 -0.028937 -0.047313 -0.020938 l -0.055813 , 0.017813 l -0.004188 -0.013250 L 0.144250 , 0.564625 z  M 0.143125 , 0.504625 c 0.000500 , 0.024625 -0.011312 , 0.042188 -0.031000 , 0.044375 l -0.000313 -0.014313 c 0.011813 -0.001437 , 0.020063 -0.011938 , 0.019688 -0.029625 c -0.000313 -0.015500 -0.008812 -0.024063 -0.019062 -0.023813 c -0.026625 , 0.000562 -0.009625 , 0.065375 -0.050062 , 0.066250 c -0.016000 , 0.000313 -0.029500 -0.014688 -0.030000 -0.037500 c -0.000500 -0.023250 , 0.011375 -0.038812 , 0.032063 -0.040438 l 0.000313 , 0.013875 c -0.012000 , 0.001063 -0.020875 , 0.010187 -0.020563 , 0.026687 c 0.000313 , 0.014500 , 0.008188 , 0.023500 , 0.017625 , 0.023250 c 0.029187 -0.000625 , 0.012250 -0.064438 , 0.050250 -0.065875 C 0.129500 , 0.467125 , 0.142625 , 0.482188 , 0.143125 , 0.504625 z  M 0.008438 , 0.427438 c -0.005812 -0.001000 -0.009187 -0.006188 -0.008250 -0.011687 c 0.000875 -0.005500 , 0.005750 -0.009312 , 0.011562 -0.008313 c 0.005875 , 0.001000 , 0.009375 , 0.006188 , 0.008438 , 0.011687 S 0.014250 , 0.428375 , 0.008438 , 0.427438 z  M 0.039063 , 0.429375 l 0.002250 -0.013750 l 0.106187 , 0.017813 l -0.002250 , 0.013750 L 0.039063 , 0.429375 z  M 0.065625 , 0.325188 c 0.010000 -0.025312 , 0.029812 -0.036375 , 0.052312 -0.032688 L 0.112500 , 0.306312 c -0.015563 -0.002375 -0.029187 , 0.006250 -0.035875 , 0.023250 c -0.007813 , 0.019750 -0.000750 , 0.041188 , 0.026375 , 0.052000 c 0.027125 , 0.010875 , 0.047000 , 0.000250 , 0.054813 -0.019500 c 0.006688 -0.017000 , 0.002812 -0.032438 -0.010437 -0.041813 l 0.005437 -0.013813 c 0.018125 , 0.012625 , 0.025812 , 0.034687 , 0.015813 , 0.060000 c -0.011187 , 0.028437 -0.039063 , 0.041000 -0.070750 , 0.028313 C 0.066125 , 0.382000 , 0.054438 , 0.353625 , 0.065625 , 0.325188 z',\n  [MaskTypes.MUSIC_NOTE]:\n    'M 0.998090 , 0.510679 c -0.010245 -0.095503 -0.060080 -0.177288 -0.144296 -0.236152 C 0.673902 , 0.148290 , 0.618510 , 0.020490 , 0.617989 , 0.019274 c -0.005730 -0.013718 -0.020316 -0.021532 -0.034902 -0.018580 c -0.014586 , 0.002952 -0.025004 , 0.015801 -0.025004 , 0.030735 v 0.875847 c -0.001736 -0.001563 -0.003473 -0.003126 -0.005209 -0.004688 c -0.060427 -0.051051 -0.150894 -0.070325 -0.248133 -0.053134 C 0.133877 , 0.879840 , 0.000000 , 1.010071 , 0.000000 , 1.145859 c 0.000000 , 0.056086 , 0.023962 , 0.107310 , 0.067373 , 0.144122 c 0.045841 , 0.038896 , 0.109047 , 0.059212 , 0.179545 , 0.059212 c 0.022226 , 0.000000 , 0.045147 -0.002084 , 0.068588 -0.006251 c 0.170863 -0.030387 , 0.304740 -0.160445 , 0.304740 -0.296406 V 0.376802 c 0.031082 , 0.027435 , 0.076055 , 0.061469 , 0.140128 , 0.109568 c 0.116861 , 0.087689 , 0.086647 , 0.287724 , 0.086473 , 0.289634 c -0.002257 , 0.013718 , 0.004688 , 0.027088 , 0.017017 , 0.033165 c 0.012329 , 0.006077 , 0.027088 , 0.003299 , 0.036465 -0.006772 C 0.971696 , 0.725126 , 1.009029 , 0.613301 , 0.998090 , 0.510679 z  M 0.304740 , 1.281125 c -0.077965 , 0.013891 -0.151762 -0.000868 -0.197256 -0.039417 c -0.029519 -0.025004 -0.045147 -0.058170 -0.045147 -0.096024 c 0.000000 -0.104532 , 0.113735 -0.209759 , 0.253343 -0.234589 c 0.019274 -0.003473 , 0.038375 -0.005036 , 0.056781 -0.005036 c 0.056086 , 0.000000 , 0.106268 , 0.015454 , 0.140476 , 0.044452 c 0.029519 , 0.025004 , 0.045147 , 0.058170 , 0.045147 , 0.096024 C 0.558083 , 1.151242 , 0.444522 , 1.256294 , 0.304740 , 1.281125 z  M 0.911269 , 0.671992 c -0.006425 -0.076749 -0.031950 -0.174857 -0.113735 -0.235978 c -0.113388 -0.085084 -0.166522 -0.126932 -0.177288 -0.153499 V 0.139955 c 0.039937 , 0.052092 , 0.102796 , 0.119292 , 0.197951 , 0.185970 c 0.068936 , 0.048272 , 0.109741 , 0.114430 , 0.117902 , 0.191353 C 0.941657 , 0.568675 , 0.932454 , 0.623025 , 0.911269 , 0.671992 z',\n  [MaskTypes.FASHION_ARROW]: `M 0.000000 , 0.386861 V 0.350365 h 0.832117 C 0.664234 , 0.270073 , 0.598540 , 0.124088 , 0.598540 , 0.000000 c 0.007299 , 0.000000 , 0.029197 , 0.000000 , 0.036496 , 0.000000 c 0.000000 , 0.226277 , 0.189781 , 0.350365 , 0.364964 , 0.350365 v 0.036496 c -0.291971 , 0.000000 -0.364964 , 0.255474 -0.364964 , 0.357664 H 0.598540 c 0.000000 -0.204380 , 0.155766 -0.333285 , 0.233577 -0.357664 H 0.000000 z`,\n  [MaskTypes.FASHION_ARROW_2]: `M 0.989956 , 0.229755 l -0.219711 -0.219711 c -0.013183 -0.013183 -0.035154 -0.013183 -0.048964 , 0.000000 c -0.013183 , 0.013183 -0.013183 , 0.035154 , 0.000000 , 0.048964 l 0.160703 , 0.160703 H 0.000000 v 0.069052 h 0.882611 L 0.721908 , 0.448839 c -0.013183 , 0.013183 -0.013183 , 0.035154 , 0.000000 , 0.048964 c 0.013810 , 0.013183 , 0.035154 , 0.013183 , 0.048964 , 0.000000 l 0.219711 -0.219711 C 1.003139 , 0.264909 , 1.003139 , 0.242938 , 0.989956 , 0.229755 z`,\n  [MaskTypes.WELLBEING_ARROW]: `M 0.975046 , 0.060525 l -0.004159 -0.003425 l 0.020746 -0.025149 H 0.000000 v -0.005382 h 0.989970 l -0.019033 -0.023143 l 0.004159 -0.003425 l 0.024905 , 0.030238 L 0.975046 , 0.060525 z`,\n};\n\nexport const MASKS: Mask[] = [\n  {\n    type: MaskTypes.RECTANGLE,\n    showInLibrary: true,\n    name: _x('Rectangle', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.RECTANGLE],\n    ratio: 1,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.CIRCLE,\n    // This circle was retired in #12869 but kept to keep old stories\n    // and templates looking the same\n    // @see https://github.com/GoogleForCreators/web-stories-wp/pull/12869\n    showInLibrary: false,\n    name: _x('Circle', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.CIRCLE],\n    ratio: 1,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.CIRCLE_2,\n    showInLibrary: true,\n    name: _x('Circle', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.CIRCLE_2],\n    ratio: 1,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.TRIANGLE,\n    showInLibrary: true,\n    name: _x('Triangle', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.TRIANGLE],\n    ratio: 1,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.HEART,\n    showInLibrary: true,\n    name: _x('Heart', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.HEART],\n    ratio: 1.075533375284871,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.STAR,\n    showInLibrary: true,\n    name: _x('Star', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.STAR],\n    ratio: 1.051524710830705,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.PENTAGON,\n    showInLibrary: true,\n    name: _x('Pentagon', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.PENTAGON],\n    ratio: 1.051524710830705,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.HEXAGON,\n    showInLibrary: true,\n    name: _x('Hexagon', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.HEXAGON],\n    ratio: 1.15473441108545,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_1,\n    showInLibrary: true,\n    name: _x('Blob 1', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_1],\n    ratio: 1,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_2,\n    showInLibrary: true,\n    name: _x('Blob 2', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_2],\n    ratio: 1.01704694,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_3,\n    showInLibrary: true,\n    name: _x('Blob 3', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_3],\n    ratio: 0.89949881,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_4,\n    showInLibrary: true,\n    name: _x('Blob 4', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_4],\n    ratio: 1.04561993,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_5,\n    showInLibrary: true,\n    name: _x('Blob 5', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_5],\n    ratio: 0.93316195,\n    supportsBorder: true,\n  },\n  {\n    type: MaskTypes.BLOB_6,\n    name: _x('Blob 6', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BLOB_6],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.BLOB_6],\n    ratio: 0.78026574,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_1,\n    name: _x('Grid 1', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_1],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.GRID_2,\n    name: _x('Grid 2', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_2],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_2],\n    ratio: 0.58481422,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_3,\n    name: _x('Grid 3', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_3],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_3],\n    ratio: 0.58287561,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_4,\n    name: _x('Grid 4', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_4],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_4],\n    ratio: 0.58384491,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_5,\n    name: _x('Grid 5', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_5],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_5],\n    ratio: 0.5819063,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_6,\n    name: _x('Grid 6', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_6],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_6],\n    ratio: 0.5815832,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_7,\n    name: _x('Grid 7', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_7],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_7],\n    ratio: 0.58414239,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GRID_8,\n    name: _x('Grid 8', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GRID_8],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.GRID_8],\n    ratio: 0.58642973,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.ARROW_1,\n    name: _x('Arrow 1', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ARROW_1],\n    ratio: 2.2097561,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.ARROW_2,\n    name: _x('Arrow 2', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ARROW_2],\n    iconPath: ICON_CLIP_PATHS[MaskTypes.ARROW_2],\n    ratio: 16.6112957,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.ARROW_3,\n    name: _x('Arrow 3', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ARROW_3],\n    ratio: 1.34323725,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.BURST_OUTLINE,\n    name: _x('Burst Outline', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BURST_OUTLINE],\n    iconPath: CLIP_PATHS[MaskTypes.BURST_OUTLINE],\n    ratio: 1.00115971,\n    iconRatio: 1,\n  },\n  {\n    type: MaskTypes.GEOGRAPHY_1,\n    name: _x('Geography 1', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.GEOGRAPHY_1],\n    ratio: 0.54013562,\n  },\n  {\n    type: MaskTypes.TWITTER,\n    name: _x('Twitter', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.TWITTER],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.INSTAGRAM,\n    name: _x('Instagram', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.INSTAGRAM],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.FACEBOOK,\n    name: _x('Facebook', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.FACEBOOK],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.YOUTUBE,\n    name: _x('YouTube', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.YOUTUBE],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.CROSS,\n    name: _x('Cross', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.CROSS],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.ARROW,\n    name: _x('Arrow', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ARROW],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.BURST,\n    name: _x('Burst', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BURST],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.BULLSEYE,\n    name: _x('Bullseye', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BULLSEYE],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.BRUSH_STROKE_1,\n    name: _x('Brush Stroke 1', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BRUSH_STROKE_1],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.BRUSH_STROKE_2,\n    name: _x('Brush Stroke 2', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.BRUSH_STROKE_2],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.ROUNDED,\n    name: _x('Rounded Rectangle', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ROUNDED],\n    ratio: 174 / 55,\n    showInLibrary: false,\n  },\n  {\n    type: MaskTypes.ROUNDED_2,\n    name: _x('Rounded Rectangle 2', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.ROUNDED_2],\n    ratio: 274 / 64,\n    showInLibrary: false,\n  },\n  {\n    type: MaskTypes.CHAT_BUBBLE,\n    name: _x('Chat Bubble', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.CHAT_BUBBLE],\n    ratio: 336 / 208,\n  },\n  {\n    type: MaskTypes.CHECK_MARK,\n    name: _x('Check Mark', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.CHECK_MARK],\n    ratio: 10.41 / 8.12,\n  },\n  {\n    type: MaskTypes.NEW_MUSIC,\n    name: _x('New Music', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.NEW_MUSIC],\n    ratio: 1,\n  },\n  {\n    type: MaskTypes.MUSIC_NOTE,\n    name: _x('Music Note', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.MUSIC_NOTE],\n    ratio: 57.59 / 77.7,\n  },\n  {\n    type: MaskTypes.FASHION_ARROW,\n    name: _x('Fashion Arrow', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.FASHION_ARROW],\n    ratio: 68.5 / 51,\n  },\n  {\n    type: MaskTypes.FASHION_ARROW_2,\n    name: _x('Fashion Arrow', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.FASHION_ARROW_2],\n    ratio: 15.93 / 8.09,\n  },\n  {\n    type: MaskTypes.WELLBEING_ARROW,\n    name: _x('Fashion Arrow', 'shape/mask name', 'web-stories'),\n    path: CLIP_PATHS[MaskTypes.WELLBEING_ARROW],\n    ratio: 204.38 / 12.37,\n  },\n];\n\nexport const DEFAULT_MASK = MASKS.find(\n  (mask) => mask.type === MaskTypes.RECTANGLE\n) as Mask;\n"
  },
  {
    "path": "packages/masks/src/display.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useUnits } from '@googleforcreators/units';\nimport type { Border, MediaElement } from '@googleforcreators/elements';\nimport type { CSSProperties, ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { shouldDisplayBorder } from './utils/elementBorder';\nimport BorderedMaskedElement from './borderedMaskedElement';\n\ninterface WithMaskProps {\n  element: MediaElement;\n  fill: boolean;\n  previewMode?: boolean;\n  responsiveBorder?: Border;\n  style?: CSSProperties;\n  children: ReactNode;\n  applyFlip?: boolean;\n}\n\nexport default function WithMask({\n  element,\n  fill,\n  previewMode = false,\n  responsiveBorder,\n  ...rest\n}: WithMaskProps) {\n  const { dataToEditorX, dataToEditorY } = useUnits(({ actions }) => ({\n    dataToEditorX: actions.dataToEditorX,\n    dataToEditorY: actions.dataToEditorY,\n  }));\n\n  const getBorderWidth = () =>\n    (!previewMode ? element.border?.left : responsiveBorder?.left) || 0;\n  const postfix = previewMode ? '-preview' : '';\n  const elementWidth = dataToEditorX(element.width);\n  const elementHeight = dataToEditorY(element.height);\n  const forceRectangularMask = shouldDisplayBorder(element);\n\n  return (\n    <BorderedMaskedElement\n      element={element}\n      hasFill={fill}\n      getBorderWidth={getBorderWidth}\n      postfix={postfix}\n      elementWidth={elementWidth}\n      elementHeight={elementHeight}\n      forceRectangularMask={forceRectangularMask}\n      {...rest}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/masks/src/frame.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  useRef,\n  useEffect,\n  useState,\n  forwardRef,\n} from '@googleforcreators/react';\nimport { getTransformFlip } from '@googleforcreators/elements';\nimport type { Flip, MediaElement } from '@googleforcreators/elements';\nimport type { Resource } from '@googleforcreators/media';\nimport type { CSSProperties, SVGAttributes, ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { MaskTypes } from './constants';\nimport { getElementMask, generateMaskId } from './masks';\nimport type {\n  RegisterDropTargetCallback,\n  UnregisterDropTargetCallback,\n} from './types';\n\nconst FILL_STYLE: CSSProperties = {\n  position: 'absolute',\n  top: 0,\n  left: 0,\n  right: 0,\n  bottom: 0,\n};\n\nconst svgCss = css`\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  pointer-events: none;\n`;\n\ninterface DropTargetSVGProps {\n  active: boolean;\n}\n\nconst DropTargetSVG = styled.svg<DropTargetSVGProps>`\n  ${svgCss}\n  z-index: ${({ active }) => (active ? 1 : -1)};\n`;\n\nconst Filler = styled.svg`\n  ${svgCss}\n`;\n\ninterface FillerPathProps {\n  isClickable: boolean;\n}\n\nconst FillerPath = styled.path<FillerPathProps>`\n  pointer-events: ${({ isClickable }) => (isClickable ? 'all' : 'none')};\n`;\n\ninterface DropTargetPathProps {\n  active?: boolean;\n}\n\nconst DropTargetPath = styled.path<DropTargetPathProps>`\n  transition: opacity 0.5s;\n  pointer-events: visibleStroke;\n  opacity: ${({ active }) => (active ? 0.3 : 0)};\n  stroke: ${({ theme }) => theme.colors.border.selection};\n`;\n\ninterface WrapperProps {\n  hasBackgroundOutline: boolean;\n}\n\nconst Wrapper = styled.div<WrapperProps>`\n  width: 100%;\n  height: 100%;\n\n  ::before {\n    transition: opacity 0.5s;\n    opacity: ${({ hasBackgroundOutline }) => (hasBackgroundOutline ? 1 : 0)};\n    display: block;\n    content: '';\n    position: absolute;\n    width: calc(100% + 8px);\n    height: calc(100% + 8px);\n    border-radius: 8px;\n    left: -4px;\n    top: -4px;\n    border: 1px solid ${({ theme }) => theme.colors.border.selection};\n  }\n`;\n\ninterface WithDropTargetProps {\n  element: MediaElement;\n  children: JSX.Element;\n  hover: boolean;\n  draggingResource: Resource;\n  activeDropTargetId: string;\n  isDropSource: (type: string) => boolean;\n  registerDropTarget: RegisterDropTargetCallback;\n  unregisterDropTarget: UnregisterDropTargetCallback;\n}\n\nfunction WithDropTarget({\n  element,\n  children,\n  hover,\n  draggingResource,\n  activeDropTargetId,\n  isDropSource,\n  registerDropTarget,\n  unregisterDropTarget,\n}: WithDropTargetProps): JSX.Element {\n  const pathRef = useRef<SVGPathElement>(null);\n\n  const { id, resource, isBackground, isLocked, isHidden } = element;\n  const mask = getElementMask(element);\n\n  useEffect(() => {\n    if (isLocked) {\n      return undefined;\n    }\n    registerDropTarget(id, pathRef.current);\n    return () => {\n      unregisterDropTarget(id);\n    };\n  }, [id, isLocked, registerDropTarget, unregisterDropTarget]);\n\n  if (!mask) {\n    return children;\n  }\n\n  // Show an outline if hovering when not dragging\n  // or if dragging another droppable element\n  const canHasOutline =\n    (hover && !draggingResource) ||\n    (Boolean(draggingResource) &&\n      isDropSource(draggingResource.type) &&\n      draggingResource !== resource);\n\n  const hasOutline = !isLocked && !isHidden && canHasOutline;\n\n  const hasThinOutline = hasOutline && !isBackground;\n  const hasBackgroundOutline = Boolean(hasOutline && isBackground);\n\n  const pathProps: SVGAttributes<SVGPathElement> = {\n    vectorEffect: 'non-scaling-stroke',\n    fill: 'none',\n    strokeLinecap: 'round',\n    strokeLinejoin: 'round',\n    d: mask?.path,\n  };\n\n  return (\n    <Wrapper hasBackgroundOutline={hasBackgroundOutline}>\n      {children}\n      <DropTargetSVG\n        viewBox={`0 0 1 ${1 / (mask.ratio || 1)}`}\n        width=\"100%\"\n        height=\"100%\"\n        preserveAspectRatio=\"none\"\n        // Fixes issue where the outline prevents double-clicks from\n        // reaching the frame through zIndex\n        active={activeDropTargetId === element.id}\n      >\n        {/** Subtle indicator that the element is a drop target */}\n        <DropTargetPath\n          {...pathProps}\n          strokeWidth=\"3\"\n          style={{ opacity: hasThinOutline ? 1 : 0 }}\n        />\n        {/** Drop target snap border when an element is in the drop target area */}\n        <DropTargetPath ref={pathRef} strokeWidth=\"48\" {...pathProps} />\n      </DropTargetSVG>\n    </Wrapper>\n  );\n}\n\ninterface WithMaskProps {\n  element: MediaElement;\n  style: CSSProperties;\n  fill: boolean;\n  flip: Flip;\n  children: JSX.Element;\n  draggingResource: Resource;\n  activeDropTargetId: string;\n  isDropSource: (type: string) => boolean;\n  isSelected?: boolean;\n  registerDropTarget: RegisterDropTargetCallback;\n  unregisterDropTarget: UnregisterDropTargetCallback;\n}\n\nconst WithMask = forwardRef(\n  (\n    {\n      element,\n      fill,\n      style,\n      children,\n      flip,\n      draggingResource,\n      activeDropTargetId,\n      isDropSource,\n      isSelected = false,\n      registerDropTarget,\n      unregisterDropTarget,\n      ...rest\n    }: WithMaskProps,\n    ref: ForwardedRef<HTMLDivElement>\n  ) => {\n    const [hover, setHover] = useState(false);\n    const { isBackground, isLocked, isHidden } = element;\n\n    // Unlocked elements are always clickable,\n    // locked elements are only clickable if selected\n    const isClickable = (!isLocked || isSelected) && !isHidden;\n\n    const dropTargets = {\n      draggingResource,\n      activeDropTargetId,\n      isDropSource,\n      registerDropTarget,\n      unregisterDropTarget,\n    };\n\n    const mask = getElementMask(element);\n    const flipStyle: CSSProperties = flip\n      ? { transform: getTransformFlip(flip) || undefined }\n      : {};\n    if (!mask?.type || (isBackground && mask.type !== MaskTypes.RECTANGLE)) {\n      return (\n        <div\n          style={{\n            ...(fill ? FILL_STYLE : {}),\n            ...style,\n            ...flipStyle,\n          }}\n          {...rest}\n        >\n          {children}\n        </div>\n      );\n    }\n\n    // @todo: Chrome cannot do inline clip-path using data: URLs.\n    // See https://bugs.chromium.org/p/chromium/issues/detail?id=1041024.\n    const maskId = generateMaskId(element, 'frame');\n\n    return (\n      <div\n        ref={ref}\n        style={{\n          ...(fill ? FILL_STYLE : {}),\n          ...style,\n          ...flipStyle,\n          ...(!isBackground ? { clipPath: `url(#${maskId})` } : {}),\n        }}\n        {...rest}\n        onPointerOver={() => setHover(true)}\n        onPointerOut={() => setHover(false)}\n      >\n        <svg width={0} height={0}>\n          <defs>\n            <clipPath\n              id={maskId}\n              transform={`scale(1 ${mask.ratio || 1})`}\n              clipPathUnits=\"objectBoundingBox\"\n            >\n              <path d={mask.path} />\n            </clipPath>\n          </defs>\n        </svg>\n        <Filler\n          viewBox={`0 0 1 ${1 / (mask.ratio || 1)}`}\n          width=\"100%\"\n          height=\"100%\"\n          preserveAspectRatio=\"none\"\n        >\n          <FillerPath isClickable={isClickable} fill=\"none\" d={mask?.path} />\n        </Filler>\n        {isClickable ? (\n          <WithDropTarget\n            element={element}\n            hover={hover}\n            {...dropTargets}\n            {...rest}\n          >\n            {children}\n          </WithDropTarget>\n        ) : (\n          children\n        )}\n      </div>\n    );\n  }\n);\n\nexport default WithMask;\n"
  },
  {
    "path": "packages/masks/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './types';\nexport * from './masks';\nexport * from './constants';\nexport * from './utils/elementBorder';\nexport { default as DisplayWithMask } from './display';\nexport { default as FrameWithMask } from './frame';\nexport { default as OutputWithMask } from './output';\n"
  },
  {
    "path": "packages/masks/src/masks.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport type { ElementType, Element, Mask } from '@googleforcreators/elements';\nimport type { CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_MASK, MASKS } from './constants';\n\nexport function getElementMask({ type, mask }: Element) {\n  if (mask?.type) {\n    return MASKS.find((m) => m.type === mask.type);\n  }\n  return getDefaultElementMask(type);\n}\n\n// Only no-mask and masks with supportsBorder support border.\nexport function canMaskHaveBorder(element: Element) {\n  const mask = getElementMask(element);\n  return Boolean(!mask || mask.supportsBorder);\n}\n\nexport function canSupportMultiBorder(element: Element) {\n  const { mask } = element;\n  return !mask || DEFAULT_MASK.type === mask?.type;\n}\n\nexport function getMaskByType(type?: string) {\n  return MASKS.find((mask) => mask.type === type) || DEFAULT_MASK;\n}\n\nexport function generateMaskId(element: Element, postfix: string) {\n  const maskDef = getMaskByType(element?.mask?.type as string);\n  return `mask-${maskDef.type}-${element.id}-${postfix}`;\n}\n\nfunction getDefaultElementMask(type: string) {\n  if (!type) {\n    return null;\n  }\n  const definition = getDefinitionForType(type as ElementType);\n  return definition?.isMaskable ? DEFAULT_MASK : null;\n}\n\n/*\n * This constant and calculation concerns growing the element while shrinking\n * the inside SVG through viewbox so it overlaps the element correctly.\n * The math and logic is explained in this GH comment:\n * https://github.com/GoogleForCreators/web-stories-wp/pull/9851#issuecomment-1020461756\n */\nconst BORDER_MULTIPLIER = 3;\nexport function getBorderedMaskProperties(\n  mask: Mask,\n  borderWidth: number,\n  elementWidth: number,\n  elementHeight: number\n) {\n  const fullPadding = BORDER_MULTIPLIER * borderWidth;\n  const relativeWidth = (elementWidth + fullPadding) / elementWidth;\n  const relativeHeight = (elementHeight + fullPadding) / elementHeight;\n  const offsetX = (relativeWidth - 1) / 2;\n  const offsetY = (relativeHeight - 1) / 2;\n  const scaledHeight = relativeHeight / (mask.ratio ?? 1);\n  const viewBox = `0 0 ${relativeWidth} ${scaledHeight}`;\n  const groupTransform = `translate(${offsetX},${offsetY})`;\n  const borderWrapperStyle: CSSProperties = {\n    width: `${relativeWidth * 100}%`,\n    height: `${relativeHeight * 100}%`,\n    position: 'absolute',\n    left: `${-offsetX * 100}%`,\n    top: `${-offsetY * 100}%`,\n    pointerEvents: 'initial',\n    display: 'block',\n    zIndex: 1,\n    opacity: 1,\n  };\n  return { viewBox, groupTransform, borderWrapperStyle };\n}\n"
  },
  {
    "path": "packages/masks/src/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Important! This file cannot use `styled-components` or any stateful/context\n// React features to stay compatible with the \"output\" templates.\n\n/* eslint no-restricted-imports: [\"error\", { \"paths\": [\"styled-components\"] }] -- Cannot use styled-components here. */\n\n/**\n * External dependencies\n */\nimport type { Element } from '@googleforcreators/elements';\nimport type { CSSProperties, ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport BorderedMaskedElement from './borderedMaskedElement';\nimport { DEFAULT_MASK } from './constants';\n\ninterface WithMaskProps {\n  element: Element;\n  style: CSSProperties;\n  fill?: boolean;\n  children: ReactNode;\n  skipDefaultMask?: boolean;\n  className?: string;\n  id?: string;\n}\n\nexport default function WithMask({\n  element,\n  fill = false,\n  skipDefaultMask = false,\n  ...rest\n}: WithMaskProps) {\n  const getBorderWidth = () => element.border?.left || 0;\n  const elementWidth = element.width;\n  const elementHeight = element.height;\n  const forceRectangularMask =\n    skipDefaultMask && element.mask?.type === DEFAULT_MASK.type;\n\n  return (\n    <BorderedMaskedElement\n      element={element}\n      hasFill={fill}\n      getBorderWidth={getBorderWidth}\n      elementWidth={elementWidth}\n      elementHeight={elementHeight}\n      forceRectangularMask={forceRectangularMask}\n      {...rest}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/masks/src/test/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { MASKS } from '../constants';\n\ndescribe('Masks', () => {\n  it('every path should end with a closepath function', () => {\n    Object.values(MASKS).map((mask) =>\n      expect(mask.path.toUpperCase().endsWith('Z')).toBeTrue()\n    );\n  });\n});\n"
  },
  {
    "path": "packages/masks/src/test/output.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport { registerElementType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport WithMask from '../output';\nimport { MaskTypes } from '../constants';\n\nconst elementTypes = [{ type: 'text', name: 'Text' }];\n\ndescribe('WithMask', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should not add mask for background element', async () => {\n    const props = {\n      element: {\n        id: '123',\n        isBackground: true,\n        type: 'image',\n        mimeType: 'image/png',\n        scale: 1,\n        origRatio: 9 / 16,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: 'image',\n          mimeType: 'image/png',\n          src: 'https://example.com/image.png',\n          height: 1920,\n          width: 1080,\n        },\n        mask: {\n          type: MaskTypes.HEART,\n          fill: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n          style: {},\n        },\n      },\n    };\n\n    const content = renderToStaticMarkup(\n      <WithMask {...props}>\n        <p>{'Hello World'}</p>\n      </WithMask>\n    );\n\n    await expect(content).not.toContain(MaskTypes.HEART);\n  });\n\n  it('should add mask for shaped image element', async () => {\n    const props = {\n      element: {\n        id: '123',\n        isBackground: false,\n        type: 'image',\n        mimeType: 'image/png',\n        scale: 1,\n        origRatio: 9 / 16,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: 'image',\n          mimeType: 'image/png',\n          src: 'https://example.com/image.png',\n          height: 1920,\n          width: 1080,\n        },\n        mask: {\n          type: MaskTypes.HEART,\n          fill: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n          style: {},\n        },\n      },\n    };\n\n    const content = renderToStaticMarkup(\n      <WithMask {...props}>\n        <p>{'Hello World'}</p>\n      </WithMask>\n    );\n\n    await expect(content).toContain(MaskTypes.HEART);\n  });\n\n  it('should add default mask', async () => {\n    const props = {\n      element: {\n        id: '123',\n        isBackground: false,\n        type: 'image',\n        mimeType: 'image/png',\n        scale: 1,\n        origRatio: 9 / 16,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: 'image',\n          mimeType: 'image/png',\n          src: 'https://example.com/image.png',\n          height: 1920,\n          width: 1080,\n        },\n        mask: {\n          type: MaskTypes.RECTANGLE,\n        },\n      },\n    };\n\n    const content = renderToStaticMarkup(\n      <WithMask {...props}>\n        <p>{'Hello World'}</p>\n      </WithMask>\n    );\n\n    await expect(content).toContain(MaskTypes.RECTANGLE);\n  });\n\n  it('should ignore default mask when requested', async () => {\n    const props = {\n      element: {\n        id: '123',\n        isBackground: false,\n        type: 'image',\n        mimeType: 'image/png',\n        scale: 1,\n        origRatio: 9 / 16,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: 'image',\n          mimeType: 'image/png',\n          src: 'https://example.com/image.png',\n          height: 1920,\n          width: 1080,\n        },\n        mask: {\n          type: MaskTypes.RECTANGLE,\n        },\n      },\n    };\n\n    const content = renderToStaticMarkup(\n      <WithMask {...props} skipDefaultMask>\n        <p>{'Hello World'}</p>\n      </WithMask>\n    );\n\n    await expect(content).not.toContain(MaskTypes.RECTANGLE);\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output', async () => {\n      const props = {\n        element: {\n          id: '123',\n          type: 'image',\n          mimeType: 'image/png',\n          scale: 1,\n          origRatio: 9 / 16,\n          x: 50,\n          y: 100,\n          height: 1920,\n          width: 1080,\n          rotationAngle: 0,\n          resource: {\n            type: 'image',\n            mimeType: 'image/png',\n            src: 'https://example.com/image.png',\n            height: 1920,\n            width: 1080,\n          },\n          mask: {\n            type: 'heart',\n            fill: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n            style: {},\n          },\n        },\n      };\n\n      await expect(\n        <WithMask {...props}>\n          <amp-img src=\"https://example.com/image.png\" layout=\"fill\" />\n        </WithMask>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when no mask is set', async () => {\n      const props = {\n        element: {\n          id: '123',\n          type: 'text',\n          x: 50,\n          y: 100,\n          height: 1920,\n          width: 1080,\n          rotationAngle: 0,\n        },\n      };\n\n      await expect(\n        <WithMask {...props}>\n          <p>{'Hello World'}</p>\n        </WithMask>\n      ).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/masks/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type RegisterDropTargetCallback = (\n  id: string,\n  pathRef: SVGPathElement | null\n) => void;\n\nexport type UnregisterDropTargetCallback = (id: string) => void;\n"
  },
  {
    "path": "packages/masks/src/typings/styled-components.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport 'styled-components';\n\ndeclare module 'styled-components' {\n  export interface DefaultTheme {\n    colors: {\n      [key: string]: {\n        [key: string]: string;\n      };\n    };\n  }\n}\n"
  },
  {
    "path": "packages/masks/src/utils/elementBorder.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  Border,\n  BorderRadius,\n  Element,\n} from '@googleforcreators/elements';\nimport type { CSSObject } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { canMaskHaveBorder, canSupportMultiBorder } from '../masks';\n\ninterface ElementWithBorder extends Element {\n  border: Border;\n}\n\nfunction hasBorder(element: Element): element is ElementWithBorder {\n  const { border } = element;\n\n  if (!border) {\n    return false;\n  }\n  const { left, top, right, bottom, color } = border;\n  // If we have no color, let's short-circuit.\n  if (!color) {\n    return false;\n  }\n  // If we have no border set either, let's short-circuit.\n  return !(!left && !top && !right && !bottom);\n}\n\n/**\n * Check if rectangular border should be displayed for an element.\n *\n * @param element Element object.\n * @return If should be displayed.\n */\nexport function shouldDisplayBorder(\n  element: Element\n): element is ElementWithBorder {\n  return (\n    hasBorder(element) &&\n    canMaskHaveBorder(element) &&\n    canSupportMultiBorder(element)\n  );\n}\n\ninterface SizeAndPosition {\n  width: string;\n  height: string;\n  posTop: string;\n  posLeft: string;\n}\n\ntype BorderPositionProps = Border & Partial<SizeAndPosition>;\n\n/**\n * Gets the CSS values for an element with border.\n *\n * @param obj An object with params relevant to border.\n * @param obj.left Left border width.\n * @param obj.top Top border width.\n * @param obj.right Right border width.\n * @param obj.bottom Bottom border width.\n * @param obj.width Original element width.\n * @param obj.height Original element height.\n * @param obj.posTop Element top position, needed for output mainly.\n * @param obj.posLeft Element left position, needed for output mainly.\n * @return Positioning CSS.\n */\nexport function getBorderPositionCSS({\n  left,\n  top,\n  right,\n  bottom,\n  width = '100%',\n  height = '100%',\n  posTop = '0px',\n  posLeft = '0px',\n}: BorderPositionProps) {\n  return {\n    left: `calc(${posLeft} - ${left}px)`,\n    top: `calc(${posTop} - ${top}px)`,\n    width: `calc(${width} + ${left + right}px)`,\n    height: `calc(${height} + ${top + bottom}px)`,\n  };\n}\n\n/**\n * Gets style for the element with border.\n *\n * @param element Element.\n * @return Border style.\n */\nexport function getBorderStyle(element: Element): CSSObject {\n  // If there's no rectangular border, return the radius only.\n  if (!hasBorder(element) || !canSupportMultiBorder(element)) {\n    return getBorderRadius(element);\n  }\n  const { border } = element;\n  const { left, top, right, bottom } = border;\n\n  // We're making the border-width responsive just for the preview,\n  // since the calculation is not 100% precise here, we're opting to the safe side by rounding the widths up\n  // as opposed to having potential margin between the border and the element.\n  // When not in preview, the rounding doesn't have any effect.\n  const borderWidth = `${Math.ceil(top)}px ${Math.ceil(right)}px ${Math.ceil(\n    bottom\n  )}px ${Math.ceil(left)}px`;\n  const borderStyle = {\n    borderWidth,\n    borderColor:\n      border && border.color\n        ? getBorderColor({ color: border.color })\n        : undefined,\n    borderStyle: 'solid',\n    ...getBorderRadius(element),\n  };\n  return {\n    top: 0,\n    left: 0,\n    right: 0,\n    bottom: 0,\n    width: '100%',\n    height: '100%',\n    position: 'absolute',\n    ...borderStyle,\n  };\n}\n\nfunction getPercentage(value: number, fullValue: number) {\n  if (!value || !fullValue) {\n    return 0;\n  }\n  return (value / fullValue) * 100;\n}\n\ninterface CornerPercentages {\n  topLeft: number;\n  topRight: number;\n  bottomRight: number;\n  bottomLeft: number;\n}\n\nfunction getCornerPercentages(\n  borderRadius: BorderRadius,\n  measure: number\n): CornerPercentages | string {\n  if (!borderRadius) {\n    return '0%';\n  }\n  const { topLeft, topRight, bottomRight, bottomLeft } = borderRadius;\n  return {\n    topLeft: getPercentage(topLeft, measure),\n    topRight: getPercentage(topRight, measure),\n    bottomRight: getPercentage(bottomRight, measure),\n    bottomLeft: getPercentage(bottomLeft, measure),\n  };\n}\n\n/**\n * Gets border radius from pixel units.\n *\n * @param element Element.\n * @return Border radius value for CSS.\n */\nexport function getBorderRadius(element: Element) {\n  const { borderRadius, width, height } = element;\n  if (!borderRadius || !canSupportMultiBorder(element)) {\n    return {};\n  }\n  /* We're using the format\n    `border-radius: topLeft topRight bottomRight bottomLeft / topLeft topRight bottomRight bottomLeft`\n    here so that we could convert one px value for border into % value which requires two values per each corner. */\n  const wValues = getCornerPercentages(\n    borderRadius,\n    width\n  ) as CornerPercentages;\n  const hValues = getCornerPercentages(\n    borderRadius,\n    height\n  ) as CornerPercentages;\n  return {\n    borderRadius: `${wValues.topLeft}% ${wValues.topRight}% ${wValues.bottomRight}% ${wValues.bottomLeft}% / ${hValues.topLeft}% ${hValues.topRight}% ${hValues.bottomRight}% ${hValues.bottomLeft}%`,\n  };\n}\n\n/**\n * Gets the border color from rgba object.\n *\n * @param color Solid color object.\n * @param color.color Color object consisting rgba values.\n * @return rgba value for CSS.\n */\nexport function getBorderColor({ color }: Required<Pick<Border, 'color'>>) {\n  // Border color can be only solid.\n  const {\n    color: { r, g, b, a },\n  } = color;\n  return `rgba(${r},${g},${b},${a === undefined ? 1 : a})`;\n}\n\ntype Converter = (border: number) => number;\n\n/**\n * Returns border values based on if it's preview or not.\n *\n * @param border Original border.\n * @param previewMode If it's preview mode.\n * @param converter Function to convert the border values.\n * @return New border values.\n */\nexport function getResponsiveBorder(\n  border: Border | undefined,\n  previewMode: boolean | undefined,\n  converter: Converter\n) {\n  if (!previewMode || !border) {\n    return border;\n  }\n  const { left, top, right, bottom } = border;\n  return {\n    ...border,\n    left: converter(left),\n    top: converter(top),\n    right: converter(right),\n    bottom: converter(bottom),\n  };\n}\n"
  },
  {
    "path": "packages/masks/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../elements\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../units\" }\n  ],\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"src/test/**/*\"]\n}\n"
  },
  {
    "path": "packages/media/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/media/README.md",
    "content": "# Media\n\nMedia utils for creating and working with media resources.\n"
  },
  {
    "path": "packages/media/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/media\",\n  \"description\": \"Functionality for creating and working with media resources in the Web Stories editor.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/media/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/media\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"mime\": \"^3.0.0\",\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"devDependencies\": {\n    \"@types/mime\": \"^3.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/media/src/aspectRatiosApproximatelyMatch.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Dimensions } from './types';\n\nfunction aspectRatiosApproximatelyMatch(\n  obj1: Dimensions,\n  obj2: Dimensions\n): boolean {\n  return Math.abs(obj1.width / obj1.height - obj2.width / obj2.height) < 0.01;\n}\n\nexport default aspectRatiosApproximatelyMatch;\n"
  },
  {
    "path": "packages/media/src/blob.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype CacheObject = File | Blob | MediaSource;\n\nconst blobCache: Record<string, CacheObject> = {};\n\n/**\n * Create a blob URL from a file.\n *\n * @param file File object.\n * @return Blob URL.\n */\nexport function createBlob(file: CacheObject): string {\n  const url = window.URL.createObjectURL(file);\n\n  blobCache[url] = file;\n\n  return url;\n}\n\n/**\n * Get file by blob URL if it exists.\n *\n * @param url Blob URL.\n * @return File if exists.\n */\nexport function getBlob(url: string): CacheObject {\n  return blobCache[url];\n}\n\n/**\n * Remove blob from cache (and browser memory).\n *\n * @param url Blob URL.\n */\nexport function revokeBlob(url: string): void {\n  if (getBlob(url)) {\n    window.URL.revokeObjectURL(url);\n  }\n\n  delete blobCache[url];\n}\n\n/**\n * Check whether a URL is a blob URL.\n *\n * @param url The URL.\n * @return Is the url a blob url?\n */\nexport function isBlobURL(url?: string): boolean {\n  return url ? url.startsWith('blob:') : false;\n}\n"
  },
  {
    "path": "packages/media/src/blobToFile.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Create a new File from a Blob instance.\n *\n * @param blob Blob object.\n * @param filename File name.\n * @param type Mime type.\n * @return File object.\n */\nfunction blobToFile(blob: Blob, filename: string, type: string): File {\n  return new File([blob], filename, { type });\n}\n\nexport default blobToFile;\n"
  },
  {
    "path": "packages/media/src/calculateSrcSet.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Resource, ResourceSize } from './types';\nimport aspectRatiosApproximatelyMatch from './aspectRatiosApproximatelyMatch';\n\n/**\n * Encodes a text string as a valid Uniform Resource Identifier (URI)\n *\n * Only encodes strings that do not look like they're already encoded,\n * by first looking for the percentage sign character.\n *\n * @param str A value representing an encoded URI.\n * @return Encoded URI\n */\nfunction maybeEncodeURI(str: string): string {\n  if (str.includes('%')) {\n    return str;\n  }\n\n  return encodeURI(str);\n}\n\n/**\n * Returns a valid srcSet attribute value for the given media resource.\n *\n * @param resource The resource.\n * @return The srcSet value, or null if the resource has no `sizes`\n * attribute.\n */\nfunction calculateSrcSet(resource: Resource): string | null {\n  if (!resource.sizes) {\n    return null;\n  }\n\n  return (\n    Object.values(resource.sizes)\n      .sort((s1, s2) => s2.width - s1.width)\n      .filter((s) => aspectRatiosApproximatelyMatch(s, resource))\n      // Remove duplicates. Given it's already ordered in descending width order, we can be\n      // more efficient and just check the last item in each reduction.\n      .reduce(\n        (unique: Array<ResourceSize>, s) =>\n          unique.length && unique[unique.length - 1].width === s.width\n            ? unique\n            : [...unique, s],\n        []\n      )\n      .filter((s) => s && s.sourceUrl && s.width)\n      .map(\n        (s) =>\n          `${maybeEncodeURI(s.sourceUrl).replaceAll(',', '%2C')} ${s.width}w`\n      )\n      .join(',')\n  );\n}\n\nexport default calculateSrcSet;\n"
  },
  {
    "path": "packages/media/src/createFileReader.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction createFileReader(file: File): Promise<FileReader> {\n  const reader = new window.FileReader();\n  return new Promise((resolve, reject) => {\n    reader.onload = () => resolve(reader);\n    reader.onerror = reject;\n    reader.readAsArrayBuffer(file);\n  });\n}\n\nexport default createFileReader;\n"
  },
  {
    "path": "packages/media/src/createResource.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ResourceType } from './types';\nimport type {\n  ResourceInput,\n  GifResource,\n  Resource,\n  VideoResource,\n  AudioResource,\n  ImageResource,\n} from './types';\nimport getTypeFromMime from './getTypeFromMime';\n\n/**\n * Creates a resource object.\n *\n * @param data Resource data.\n * @return Resource object.\n */\nfunction createResource({\n  type,\n  mimeType,\n  poster,\n  posterId,\n  length,\n  lengthFormatted,\n  sizes = {},\n  output,\n  width = 0,\n  height = 0,\n  isPlaceholder = false,\n  isOptimized = false,\n  isMuted = false,\n  isExternal = false,\n  trimData,\n  needsProxy = false,\n  ...rest\n}: ResourceInput): ImageResource | VideoResource | GifResource | AudioResource {\n  type = type || getTypeFromMime(mimeType);\n  const resource: Resource = {\n    type,\n    mimeType,\n    width,\n    height,\n    sizes,\n    isPlaceholder,\n    isExternal,\n    needsProxy,\n    ...rest,\n  };\n  const sequenceProps = {\n    poster,\n    posterId,\n    isOptimized,\n  };\n  if (type === ResourceType.Video) {\n    return {\n      ...resource,\n      ...sequenceProps,\n      length,\n      lengthFormatted,\n      isMuted,\n      trimData,\n    } as VideoResource;\n  }\n  if (type === ResourceType.Gif) {\n    return {\n      ...resource,\n      ...sequenceProps,\n      output,\n    } as GifResource;\n  }\n  if (type === ResourceType.Audio) {\n    return {\n      ...resource,\n      length,\n      lengthFormatted,\n    } as AudioResource;\n  }\n  return resource as ImageResource;\n}\n\nexport default createResource;\n"
  },
  {
    "path": "packages/media/src/fetchRemoteBlob.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Helper to get remote file using fetch and return blob.\n *\n * @param url URL of file.\n * @return Blob object.\n */\nasync function fetchRemoteBlob(url: string): Promise<Blob> {\n  const response = await fetch(url);\n  if (!response.ok) {\n    throw new Error(`An error has occurred: ${response.status}`);\n  }\n  return response.blob();\n}\n\nexport default fetchRemoteBlob;\n"
  },
  {
    "path": "packages/media/src/fetchRemoteFile.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFileNameFromUrl from './getFileNameFromUrl';\nimport fetchRemoteBlob from './fetchRemoteBlob';\nimport blobToFile from './blobToFile';\nimport getFileBasename from './getFileBasename';\n\nfunction generateFileName(url: string): string {\n  const currentFileName = getFileNameFromUrl(url);\n  const currentFileExt = getFileBasename({ name: currentFileName });\n\n  return currentFileName.replace(\n    `.${currentFileExt}`,\n    `-optimized.${currentFileExt}`\n  );\n}\n\n/**\n * Helper to get remote file using fetch.\n *\n * @param url URL of file.\n * @param mimeType Mime type of file.\n * @return File object.\n */\nasync function fetchRemoteFile(url: string, mimeType: string): Promise<File> {\n  const data = await fetchRemoteBlob(url);\n  const name = generateFileName(url);\n  return blobToFile(data, name, mimeType);\n}\n\nexport default fetchRemoteFile;\n"
  },
  {
    "path": "packages/media/src/formatDuration.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction formatDuration(time: number): string {\n  return time.toLocaleString('en-US', {\n    minimumIntegerDigits: 2,\n    useGrouping: false,\n  });\n}\n\nexport default formatDuration;\n"
  },
  {
    "path": "packages/media/src/formatMsToHMS.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport formatDuration from './formatDuration';\n\n/**\n * Converts length in milliseconds to HH:MM:SS.SSS format.\n *\n * @param ms Original length in milliseconds.\n * @return Formatted length.\n */\nfunction formatMsToHMS(ms: number): string {\n  if (!ms) {\n    return '00:00:00';\n  }\n  let seconds = ms / 1000;\n  const hours = Math.floor(seconds / 3600);\n  seconds = seconds % 3600;\n  const minutes = Math.floor(seconds / 60);\n  seconds = seconds % 60;\n\n  return `${formatDuration(hours)}:${formatDuration(minutes)}:${formatDuration(\n    seconds\n  )}`;\n}\n\nexport default formatMsToHMS;\n"
  },
  {
    "path": "packages/media/src/getCanvasBlob.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction getCanvasBlob(\n  canvasEl: HTMLCanvasElement,\n  type: 'image/jpeg' | 'image/png' | 'image/webp' = 'image/jpeg',\n  quality = 0.82\n): Promise<Blob | null> {\n  return new Promise((resolve) => {\n    canvasEl.toBlob((blob) => resolve(blob), type, quality);\n  });\n}\n\nexport default getCanvasBlob;\n"
  },
  {
    "path": "packages/media/src/getFileBasename.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns file basename without extension.\n *\n * @param file File object.\n * @param file.name File name.\n * @return File name without extension.\n */\nfunction getFileBasename({ name = '' }): string {\n  return name.includes('.') ? name.split('.').slice(0, -1).join('.') : name;\n}\n\nexport default getFileBasename;\n"
  },
  {
    "path": "packages/media/src/getFileNameFromUrl.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns the file name including extension from a URL.\n *\n * @param url File URL.\n * @return File name.\n */\nfunction getFileNameFromUrl(url: string): string {\n  const tail = url.split('/').at(-1);\n  if (!tail) {\n    // Edge case that doesn't happen for a proper URL.\n    return url;\n  }\n\n  return tail.split(/[#?]/).at(0) ?? tail;\n}\n\nexport default getFileNameFromUrl;\n"
  },
  {
    "path": "packages/media/src/getFirstFrameOfVideo.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport preloadVideo from './preloadVideo';\nimport getImageFromVideo from './getImageFromVideo';\nimport seekVideo from './seekVideo';\n\n/**\n * Returns an image of the first frame of a given video.\n *\n * @see https://github.com/ampproject/amp-wp/blob/c5fba13dd17d4f713c9889d26898aec6091e421b/assets/src/stories-editor/helpers/uploadVideoFrame.js#L10-L39\n * @param src Video src URL.\n * @return The extracted image.\n */\nasync function getFirstFrameOfVideo(src: string): Promise<Blob | null> {\n  const video = await preloadVideo(src);\n  await seekVideo(video);\n  return getImageFromVideo(video);\n}\n\nexport default getFirstFrameOfVideo;\n"
  },
  {
    "path": "packages/media/src/getFocalFromOffset.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Gets point from offset.\n *\n * @param side Side.\n * @param mediaElementSide Media element side.\n * @param offset Offset.\n * @return Focal\n */\nfunction getFocalFromOffset(\n  side: number,\n  mediaElementSide: number,\n  offset: number\n): number {\n  return ((offset + side * 0.5) / mediaElementSide) * 100;\n}\n\nexport default getFocalFromOffset;\n"
  },
  {
    "path": "packages/media/src/getImageDimensions.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Dimensions } from './types';\nimport preloadImage from './preloadImage';\n\n/**\n * Get image dimensions from an image.\n *\n * @param src Image source.\n * @return Image dimensions object.\n */\nasync function getImageDimensions(src: string): Promise<Dimensions> {\n  const img = await preloadImage({ src });\n  return {\n    width: img.naturalWidth,\n    height: img.naturalHeight,\n  };\n}\n\nexport default getImageDimensions;\n"
  },
  {
    "path": "packages/media/src/getImageFromVideo.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getCanvasBlob from './getCanvasBlob';\n\n/**\n * Returns a still image from a given video element.\n *\n * @param video Video element.\n * @return JPEG image blob.\n */\nfunction getImageFromVideo(video: HTMLVideoElement): Promise<Blob | null> {\n  const canvas = document.createElement('canvas');\n  canvas.width = video.videoWidth;\n  canvas.height = video.videoHeight;\n\n  const ctx = canvas.getContext('2d');\n\n  // If the contextType doesn't match a possible drawing context,\n  // or differs from the first contextType requested, null is returned.\n  if (!ctx) {\n    return Promise.resolve(null);\n  }\n\n  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n  return getCanvasBlob(canvas);\n}\n\nexport default getImageFromVideo;\n"
  },
  {
    "path": "packages/media/src/getMediaSizePositionProps.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Resource } from './types';\n\ninterface MediaSizePositionProps {\n  width: number;\n  height: number;\n  offsetX: number;\n  offsetY: number;\n  scale: number;\n  focalX: number;\n  focalY: number;\n}\n\n/**\n * Get props for media specifically influenced by scale and focal point.\n *\n * @param resource   Media resource.\n * @param width      Original width.\n * @param height     Original height.\n * @param scale      Scale, 100 is the default.\n * @param focalX     X axis focal point.\n * @param focalY     Y axis focal point.\n * @return Media properties.\n */\nfunction getMediaSizePositionProps(\n  resource: Resource,\n  width: number,\n  height: number,\n  scale = 100,\n  focalX?: number,\n  focalY?: number\n): MediaSizePositionProps {\n  const ratio = width / height;\n  const oRatio =\n    resource.width && resource.height ? resource.width / resource.height : 1;\n  scale = Math.max(scale || 100, 100);\n  focalX = typeof focalX === 'number' ? focalX : 50;\n  focalY = typeof focalY === 'number' ? focalY : 50;\n  const mediaWidth = (oRatio <= ratio ? width : height * oRatio) * scale * 0.01;\n  const mediaHeight =\n    (oRatio <= ratio ? width / oRatio : height) * scale * 0.01;\n  const offsetX = Math.max(\n    0,\n    Math.min(mediaWidth * focalX * 0.01 - width * 0.5, mediaWidth - width)\n  );\n  const offsetY = Math.max(\n    0,\n    Math.min(mediaHeight * focalY * 0.01 - height * 0.5, mediaHeight - height)\n  );\n\n  return {\n    width: mediaWidth,\n    height: mediaHeight,\n    offsetX,\n    offsetY,\n    scale,\n    focalX,\n    focalY,\n  };\n}\n\nexport default getMediaSizePositionProps;\n"
  },
  {
    "path": "packages/media/src/getMsFromHMS.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Converts time in H:M:S format to milliseconds.\n *\n * @param time Time in HH:MM:SS or H:M:S format.\n * @return Milliseconds.\n */\nfunction getMsFromHMS(time: string | null): number {\n  if (!time) {\n    return 0;\n  }\n  const parts = time.split(':');\n  if (parts.length !== 3) {\n    return 0;\n  }\n  const seconds =\n    Number.parseFloat(parts[2]) +\n    Number.parseInt(parts[1]) * 60 +\n    Number.parseInt(parts[0]) * 3600;\n  return Math.round(1000 * seconds);\n}\n\nexport default getMsFromHMS;\n"
  },
  {
    "path": "packages/media/src/getResourceSize.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FULLBLEED_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\n\ninterface ResourceSizeParams {\n  width?: number;\n  height?: number;\n  posterGenerated?: boolean;\n  posterWidth?: number;\n  posterHeight?: number;\n}\n\ninterface ResourceSize {\n  width: number;\n  height: number;\n}\n\n/**\n * Returns the best known size of the resource. The generated poster can\n * override the resource's size because the poster generation has a more\n * accurate data.\n *\n * @param obj An object with height/width params.\n * @param obj.width Width.\n * @param obj.height Height.\n * @param [obj.posterGenerated] Whether a poster has been generated.\n * @param [obj.posterWidth] Poster width.\n * @param [obj.posterHeight] Poster height.\n * @return The resource's size (width and height).\n */\nfunction getResourceSize({\n  width = 0,\n  height = 0,\n  posterGenerated,\n  posterWidth = 0,\n  posterHeight = 0,\n}: ResourceSizeParams): ResourceSize {\n  // Use poster image size, if poster is generated.\n  if (posterGenerated && posterWidth && posterHeight) {\n    return { width: posterWidth, height: posterHeight };\n  }\n  // If height / width is set, then use them.\n  if (width || height) {\n    return { width, height };\n  }\n\n  // Return a default height and width.\n  return {\n    width: PAGE_WIDTH,\n    height: FULLBLEED_HEIGHT,\n  };\n}\n\nexport default getResourceSize;\n"
  },
  {
    "path": "packages/media/src/getSmallestUrlForWidth.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Resource } from './types';\nimport aspectRatiosApproximatelyMatch from './aspectRatiosApproximatelyMatch';\n\n/**\n * Choose the source URL of the smallest available size image / video wider than\n * minWidth, according to the device pixel ratio.\n *\n * @param minWidth The minimum width of the thumbnail to return.\n * @param resource The resource.\n * @return Source URL of the smallest available size media.\n */\nfunction getSmallestUrlForWidth(minWidth: number, resource: Resource): string {\n  if (resource.sizes) {\n    const smallestMedia = Object.values(resource.sizes)\n      .sort((s1, s2) => s1.width - s2.width)\n      .filter((s) => aspectRatiosApproximatelyMatch(s, resource))\n      .find((s) => s.width >= minWidth * window.devicePixelRatio);\n    if (smallestMedia) {\n      return smallestMedia.sourceUrl;\n    }\n  }\n  return resource.src;\n}\n\nexport default getSmallestUrlForWidth;\n"
  },
  {
    "path": "packages/media/src/getTypeFromMime.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from './types';\n\n/**\n * Infer element type from mime type of its resource\n *\n * @param mimeType Mime type.\n * @return Element type.\n */\nfunction getTypeFromMime(mimeType: string): ResourceType {\n  return mimeType.split('/')[0] as ResourceType;\n}\n\nexport default getTypeFromMime;\n"
  },
  {
    "path": "packages/media/src/getVideoLength.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getVideoLengthDisplay from './getVideoLengthDisplay';\n\ninterface VideoLength {\n  length: number;\n  lengthFormatted: string;\n}\n\n/**\n * Get video length from a video.\n *\n * @param video Video element.\n * @return Video length information.\n */\nfunction getVideoLength(video: HTMLMediaElement): VideoLength {\n  // If the element's media doesn't have a known duration—such as for live media streams—the value of duration is +Infinity.\n  // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration\n  const isNumber =\n    !isNaN(video.duration) && Number.POSITIVE_INFINITY !== video.duration;\n  const duration = isNumber ? video.duration : 0;\n  const length = Math.round(duration);\n  const lengthFormatted = getVideoLengthDisplay(length);\n  return {\n    length,\n    lengthFormatted,\n  };\n}\n\nexport default getVideoLength;\n"
  },
  {
    "path": "packages/media/src/getVideoLengthDisplay.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport formatDuration from './formatDuration';\n\n/**\n * Get video length to display from seconds.\n *\n * @param seconds Length in seconds.\n * @return Video length in H:MM:SS format.\n */\nfunction getVideoLengthDisplay(seconds: number): string {\n  const hours = Math.floor(seconds / 3600);\n  seconds = seconds % 3600;\n  const minutes = Math.floor(seconds / 60);\n  seconds = seconds % 60;\n  if (hours) {\n    return `${hours}:${formatDuration(minutes)}:${formatDuration(seconds)}`;\n  }\n  return `${minutes}:${formatDuration(seconds)}`;\n}\n\nexport default getVideoLengthDisplay;\n"
  },
  {
    "path": "packages/media/src/hasVideoGotAudio.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Determines whether a video element has audio tracks.\n *\n * @param video Video element.\n * @return Whether the video has audio or not.\n */\nfunction hasVideoGotAudio(video: HTMLVideoElement): boolean {\n  return (\n    video.mozHasAudio ||\n    Boolean(video.webkitAudioDecodedByteCount) ||\n    (video.audioTracks ? video.audioTracks.length > 0 : false)\n  );\n}\n\nexport default hasVideoGotAudio;\n"
  },
  {
    "path": "packages/media/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './blob';\nexport * from './types';\nexport * from './mimeTypes';\n\nexport { default as calculateSrcSet } from './calculateSrcSet';\nexport { default as createResource } from './createResource';\nexport { default as getFileBasename } from './getFileBasename';\nexport { default as createFileReader } from './createFileReader';\nexport { default as fetchRemoteFile } from './fetchRemoteFile';\nexport { default as fetchRemoteBlob } from './fetchRemoteBlob';\nexport { default as formatMsToHMS } from './formatMsToHMS';\nexport { default as getFileNameFromUrl } from './getFileNameFromUrl';\nexport { default as getFirstFrameOfVideo } from './getFirstFrameOfVideo';\nexport { default as getImageDimensions } from './getImageDimensions';\nexport { default as getMsFromHMS } from './getMsFromHMS';\nexport { default as getVideoLength } from './getVideoLength';\nexport { default as getVideoLengthDisplay } from './getVideoLengthDisplay';\nexport { default as getResourceSize } from './getResourceSize';\nexport { default as getFocalFromOffset } from './getFocalFromOffset';\nexport { default as getMediaSizePositionProps } from './getMediaSizePositionProps';\nexport { default as getSmallestUrlForWidth } from './getSmallestUrlForWidth';\nexport { default as getTypeFromMime } from './getTypeFromMime';\nexport { default as preloadImage } from './preloadImage';\nexport { default as preloadVideo } from './preloadVideo';\nexport { default as preloadVideoMetadata } from './preloadVideoMetadata';\nexport { default as seekVideo } from './seekVideo';\nexport { default as resourceList } from './resourceList';\nexport { default as isAnimatedGif } from './isAnimatedGif';\nexport { default as hasVideoGotAudio } from './hasVideoGotAudio';\nexport { default as getImageFromVideo } from './getImageFromVideo';\nexport { default as blobToFile } from './blobToFile';\nexport { default as getCanvasBlob } from './getCanvasBlob';\nexport { default as readFile } from './readFile';\nexport { default as resourceIs } from './resourceIs';\n"
  },
  {
    "path": "packages/media/src/isAnimatedGif.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// See http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp.\nconst BLOCK_TERMINATOR = 0x00;\nconst EXTENSION_INTRODUCER = 0x21;\nconst GRAPHIC_CONTROL_LABEL = 0xf9;\n\n/**\n *\n * Loosely based on https://www.npmjs.com/package/animated-gif-detector (MIT-compatible ISC license)\n *\n * See http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp for how GIFs are structured.\n *\n * @param buffer The GIF ArrayBuffer instance.\n * @return Whether this is an animated GIF or not.\n */\nfunction isAnimatedGif(buffer: ArrayBuffer): boolean {\n  const arr = new Uint8Array(buffer);\n  let frames = 0;\n\n  // Make sure it's a GIF and skip early if it isn't.\n  // 47=\"G\", 49=\"I\", 46=\"F\", 38=\"8\"\n  if (\n    arr[0] !== 0x47 ||\n    arr[1] !== 0x49 ||\n    arr[2] !== 0x46 ||\n    arr[3] !== 0x38\n  ) {\n    return false;\n  }\n\n  for (let i = 4; i < arr.length; i++) {\n    // We reached a new block, increase frame count.\n    if (\n      arr[i] === BLOCK_TERMINATOR &&\n      arr[i + 1] === EXTENSION_INTRODUCER &&\n      arr[i + 2] === GRAPHIC_CONTROL_LABEL\n    ) {\n      frames++;\n    }\n  }\n\n  return frames > 1;\n}\n\nexport default isAnimatedGif;\n"
  },
  {
    "path": "packages/media/src/mimeTypes.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport * as mime from 'mime/lite';\n\n/**\n * Get the file extension for a given mime type.\n *\n * @param mimeType Mime type.\n * @return File extension.\n */\nexport function getExtensionFromMimeType(mimeType: string): string | null {\n  return mime.getExtension(mimeType);\n}\n\n/**\n * Get all possible file extensions for a given mime type.\n *\n * Some mime types can map to multiple file extensions, but\n * the mime package does not offer a way to retrieve all of them.\n *\n * Since this is only needed for user-facing error messages\n * (e.g. \"You can upload jpeg, png, mp4, ...\"), this function\n * contains a simple, opinionated, hardcoded list of extensions for the\n * most relevant mime types as used in the story editor.\n *\n * @see https://github.com/broofa/mime/issues/254\n * @param mimeType Mime type.\n * @return File extension.\n */\nexport function getExtensionsFromMimeType(mimeType: string): string[] {\n  switch (mimeType) {\n    case 'audio/mpeg':\n      return ['mp3', 'm3a'];\n    case 'audio/aac':\n      return ['aac'];\n    case 'audio/ogg':\n      return ['oga', 'ogg'];\n    case 'image/jpeg':\n      return ['jpg', 'jpeg'];\n    default:\n      return [getExtensionFromMimeType(mimeType)].filter(Boolean) as string[];\n  }\n}\n"
  },
  {
    "path": "packages/media/src/preloadImage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ninterface ImageArguments {\n  src: string;\n  srcset?: string;\n  width?: string | number;\n  height?: string | number;\n}\n\n/**\n * Preload image using a promise.\n *\n * @param attr Image attributes\n * @param attr.src Image source.\n * @param attr.srcset Image source set.\n * @param attr.width Image width.\n * @param attr.height Image height.\n * @return Image object.\n */\nfunction preloadImage({\n  src,\n  srcset,\n  width,\n  height,\n}: ImageArguments): Promise<HTMLImageElement> {\n  return new Promise((resolve, reject) => {\n    // If no width or height are provided, set them to undefined\n    // so that is preloaded with its full dimensions.\n    // Avoids creating an image with 0x0 dimensions.\n    const image = new window.Image(\n      width ? Number(width) : undefined,\n      height ? Number(height) : undefined\n    );\n    image.onload = () => resolve(image);\n    image.onerror = reject;\n    image.decoding = 'async';\n    image.crossOrigin = 'anonymous';\n    if (srcset) {\n      image.srcset = srcset;\n    }\n    image.src = src;\n  });\n}\n\nexport default preloadImage;\n"
  },
  {
    "path": "packages/media/src/preloadVideo.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport preloadVideoMetadata from './preloadVideoMetadata';\n\n/**\n * Preload a video.\n *\n * @param src Video source.\n * @return Video element.\n */\nasync function preloadVideo(src: string): Promise<HTMLVideoElement> {\n  const video = await preloadVideoMetadata(src);\n\n  return new Promise((resolve, reject) => {\n    video.addEventListener('canplay', () => resolve(video), { once: true });\n    video.addEventListener('error', reject);\n\n    video.preload = 'auto';\n  });\n}\n\nexport default preloadVideo;\n"
  },
  {
    "path": "packages/media/src/preloadVideoMetadata.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Preload video metadata.\n *\n * @param src Video source.\n * @return Video element.\n */\nfunction preloadVideoMetadata(src: string): Promise<HTMLVideoElement> {\n  const video = document.createElement('video');\n  video.muted = true;\n  video.crossOrigin = 'anonymous';\n  video.preload = 'metadata';\n\n  return new Promise((resolve, reject) => {\n    video.addEventListener('loadedmetadata', () => resolve(video));\n    video.addEventListener('error', reject);\n\n    video.src = src;\n  });\n}\n\nexport default preloadVideoMetadata;\n"
  },
  {
    "path": "packages/media/src/readFile.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction readFile(file: File) {\n  const reader = new FileReader();\n  return new Promise<Uint8Array>((resolve, reject) => {\n    reader.addEventListener('load', () => {\n      resolve(new Uint8Array(reader.result as ArrayBuffer));\n    });\n    reader.addEventListener('error', () => {\n      reject(new Error(`Could not read file ${file.name}`));\n    });\n    reader.readAsArrayBuffer(file);\n  });\n}\n\nexport default readFile;\n"
  },
  {
    "path": "packages/media/src/resourceIs.ts",
    "content": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  AudioResource,\n  ImageResource,\n  Resource,\n  VideoResource,\n} from './types';\nimport { ResourceType } from './types';\n\nfunction isImage(\n  resource: Resource | AudioResource\n): resource is ImageResource {\n  return resource && resource.type === ResourceType.Image;\n}\n\nfunction isVideo(\n  resource: Resource | AudioResource\n): resource is VideoResource {\n  return resource && resource.type === ResourceType.Video;\n}\n\nconst resourceIs = {\n  image: isImage,\n  video: isVideo,\n};\n\nexport default resourceIs;\n"
  },
  {
    "path": "packages/media/src/resourceList.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  type ResourceId,\n  type ResourceCacheEntry,\n  ResourceCacheEntryType,\n} from './types';\n\ninterface ResourceCache {\n  list: Record<ResourceId, ResourceCacheEntry>;\n  get: (id: ResourceId) => ResourceCacheEntry | undefined;\n  set: (id: ResourceId, value: ResourceCacheEntry) => void;\n  resetList: () => void;\n}\n\n/**\n * Temporary list to hold currently used resources and their state.\n */\nconst resourceList: ResourceCache = {\n  list: {},\n  resetList: function () {\n    this.list = {};\n  },\n  get: function (id: ResourceId): ResourceCacheEntry {\n    return this.list[id];\n  },\n  set: function (id: ResourceId, value: ResourceCacheEntry): void {\n    if (value?.type === ResourceCacheEntryType.Cached && this.list[id]) {\n      // We already have better (or equal) resource than cached, prevent flickering\n      return;\n    }\n    this.list[id] = value;\n  },\n};\n\nexport default resourceList;\n"
  },
  {
    "path": "packages/media/src/seekVideo.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst THREE_SECONDS = 3000;\n\n/**\n * Seek video element to a given offset.\n *\n * @param video Video element.\n * @param [offset] Optional. Desired offset. Defaults to roughly the first frame.\n */\nfunction seekVideo(video: HTMLVideoElement, offset = 0.99): Promise<void> {\n  if (video.currentTime === offset) {\n    return Promise.resolve();\n  }\n\n  return new Promise((resolve, reject) => {\n    // If the seek takes longer 3 seconds, guess it timed out and error out.\n    video.addEventListener('seeking', (evt) => {\n      const wait = setTimeout(() => {\n        clearTimeout(wait);\n        reject(evt as unknown as Error);\n      }, THREE_SECONDS);\n    });\n    video.addEventListener('error', reject);\n    video.addEventListener('seeked', () => resolve(), { once: true });\n\n    video.currentTime = offset;\n  });\n}\n\nexport default seekVideo;\n"
  },
  {
    "path": "packages/media/src/test/calculateSrcSet.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport calculateSrcSet from '../calculateSrcSet';\nimport createResource from '../createResource';\nimport { type ImageResource, ResourceType } from '../types';\n\ndescribe('calculateSrcSet', () => {\n  it('should generate srcset properly', () => {\n    const resource = createResource({\n      id: 123,\n      width: 400,\n      height: 800,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      src: 'URL',\n      alt: '',\n      sizes: {\n        size1: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL1',\n          width: 200,\n          height: 400,\n        },\n        size2: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL2',\n          width: 400,\n          height: 800,\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe('URL2 400w,URL1 200w');\n  });\n\n  it(\"should skip images that don't match the largest image's orientation\", () => {\n    const resource = createResource({\n      id: 123,\n      width: 400,\n      height: 800,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      src: 'URL',\n      alt: '',\n      sizes: {\n        size1: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL1',\n          width: 200,\n          height: 400,\n        },\n        size2: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL2',\n          width: 400,\n          height: 800,\n        },\n        size3: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL3',\n          width: 400,\n          height: 410,\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe('URL2 400w,URL1 200w');\n  });\n\n  it('should remove duplicate width images', () => {\n    const resource = createResource({\n      id: 123,\n      width: 800,\n      height: 1600,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      src: 'URL',\n      alt: '',\n      sizes: {\n        size1: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL1',\n          width: 200,\n          height: 400,\n        },\n        size2: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL2',\n          width: 400,\n          height: 800,\n        },\n        size3: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL3',\n          width: 200,\n          height: 400,\n        },\n        size4: {\n          mimeType: 'image/jpeg',\n          sourceUrl: 'URL3',\n          width: 800,\n          height: 1600,\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe('URL3 800w,URL2 400w,URL1 200w');\n  });\n\n  it('should encode URLs with spaces', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 500,\n      height: 500,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 100,\n          height: 100,\n          sourceUrl: 'small url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 200,\n          sourceUrl: 'medium url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 300,\n          sourceUrl: 'large url',\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe('large%20url 300w,medium%20url 200w,small%20url 100w');\n  });\n\n  it('should not encode already encoded URLs', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 500,\n      height: 500,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 100,\n          height: 100,\n          sourceUrl:\n            'https://firebasestorage.googleapis.com/v0/b/c-dashboard-d4a82.appspot.com/o/media%2FNurUn5ekSeOkSCfk1yPIkg17buI3%2Fimages%2F1650068451121-omid-armin-nACf6L_pXq8-unsplash.jpeg?alt=media&token=edc4dfd7-6ac1-44a0-83b7-1aa99a3adad3',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 200,\n          sourceUrl: 'medium%2Furl',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 300,\n          sourceUrl: 'large%2Furl',\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe(\n      'large%2Furl 300w,medium%2Furl 200w,https://firebasestorage.googleapis.com/v0/b/c-dashboard-d4a82.appspot.com/o/media%2FNurUn5ekSeOkSCfk1yPIkg17buI3%2Fimages%2F1650068451121-omid-armin-nACf6L_pXq8-unsplash.jpeg?alt=media&token=edc4dfd7-6ac1-44a0-83b7-1aa99a3adad3 100w'\n    );\n  });\n\n  it('should encode URLs with multiple spaces', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 500,\n      height: 500,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 100,\n          height: 100,\n          sourceUrl: 'small      url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 200,\n          sourceUrl: 'medium     url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 300,\n          sourceUrl: 'large      url',\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe(\n      'large%20%20%20%20%20%20url 300w,medium%20%20%20%20%20url 200w,small%20%20%20%20%20%20url 100w'\n    );\n  });\n\n  it('should ignore sizes with empty URLs', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 500,\n      height: 500,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 100,\n          height: 100,\n          sourceUrl: '',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 200,\n          sourceUrl: '',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 300,\n          sourceUrl: '',\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe('');\n  });\n\n  it('should not break image URLs with commas in them', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'image.jpg',\n      width: 640,\n      height: 853,\n      sizes: {\n        thumbnail: {\n          mimeType: 'image/jpeg',\n          width: 150,\n          height: 200,\n          sourceUrl:\n            'https://example.com/images/w_150,h_200,c_scale/image.jpg?_i=AA',\n        },\n        medium: {\n          mimeType: 'image/jpeg',\n          width: 225,\n          height: 300,\n          sourceUrl:\n            'https://example.com/images/w_225,h_300,c_scale/image.jpg?_i=AA',\n        },\n        full: {\n          mimeType: 'image/jpeg',\n          width: 640,\n          height: 853,\n          sourceUrl:\n            'https://example.com/images/w_640,h_853,c_scale/image.jpg?_i=AA',\n        },\n      },\n    }) as ImageResource;\n\n    const srcSet = calculateSrcSet(resource);\n    expect(srcSet).toBe(\n      'https://example.com/images/w_640%2Ch_853%2Cc_scale/image.jpg?_i=AA 640w,' +\n        'https://example.com/images/w_225%2Ch_300%2Cc_scale/image.jpg?_i=AA 225w,' +\n        'https://example.com/images/w_150%2Ch_200%2Cc_scale/image.jpg?_i=AA 150w'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/formatMsToHMS.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport formatMsToHMS from '../formatMsToHMS';\n\ndescribe('formatMsToHMS', () => {\n  it('should correctly format 0', () => {\n    expect(formatMsToHMS(0)).toBe('00:00:00');\n  });\n\n  it('should return correct results', () => {\n    expect(formatMsToHMS(1000)).toBe('00:00:01');\n    expect(formatMsToHMS(60000)).toBe('00:01:00');\n    expect(formatMsToHMS(10500)).toBe('00:00:10.5');\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/getFileBasename.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFileBasename from '../getFileBasename';\n\ndescribe('getFileName', () => {\n  it('should remove the file extension', () => {\n    expect(getFileBasename({ name: 'my-video.mp4' })).toBe('my-video');\n  });\n\n  it('should remove the file extension with period in name', () => {\n    expect(getFileBasename({ name: 'my.video.mp4' })).toBe('my.video');\n  });\n\n  it('should support files without extension', () => {\n    expect(getFileBasename({ name: 'my-video' })).toBe('my-video');\n  });\n\n  it('should return an empty string if missing name', () => {\n    expect(getFileBasename({ name: '' })).toBe('');\n  });\n\n  it('should default to an empty name', () => {\n    expect(getFileBasename({})).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/getMsFromHMS.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getMsFromHMS from '../getMsFromHMS';\n\ndescribe('getMsFromHMS', () => {\n  it('should correctly format values resulting in 0', () => {\n    expect(getMsFromHMS('00:00:00')).toBe(0);\n    expect(getMsFromHMS(null)).toBe(0);\n    expect(getMsFromHMS('foo')).toBe(0);\n  });\n\n  it('should return correct results', () => {\n    expect(getMsFromHMS('00:00:01')).toBe(1000);\n    expect(getMsFromHMS('00:01:00')).toBe(60000);\n    expect(getMsFromHMS('00:00:10.5')).toBe(10500);\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/getResourceSize.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FULLBLEED_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport getResourceSize from '../getResourceSize';\n\ndescribe('getResourceSize', () => {\n  it('return default values', () => {\n    const result = getResourceSize({});\n    const expected = {\n      width: PAGE_WIDTH,\n      height: FULLBLEED_HEIGHT,\n    };\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('return no poster values', () => {\n    const result = getResourceSize({ width: 300, height: 300 });\n    const expected = {\n      width: 300,\n      height: 300,\n    };\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('return with poster values', () => {\n    const result = getResourceSize({\n      width: 300,\n      height: 300,\n      posterGenerated: true,\n      posterWidth: 400,\n      posterHeight: 400,\n    });\n    const expected = {\n      width: 400,\n      height: 400,\n    };\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('return with missing poster values', () => {\n    const result = getResourceSize({\n      width: 300,\n      height: 300,\n      posterWidth: 400,\n      posterHeight: 400,\n    });\n    const expected = {\n      width: 300,\n      height: 300,\n    };\n    expect(result).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/getSmallestUrlForWidth.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getSmallestUrlForWidth from '../getSmallestUrlForWidth';\nimport createResource from '../createResource';\nimport { type ImageResource, ResourceType } from '../types';\n\ndescribe('getSmallestUrlForWidth', () => {\n  beforeEach(() => {\n    window.devicePixelRatio = 1;\n  });\n\n  afterEach(() => {\n    window.devicePixelRatio = 1;\n  });\n\n  it('should return the smallest available image URL greater than minWidth', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 400,\n      height: 200,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 100,\n          sourceUrl: 'full-url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 150,\n          sourceUrl: 'med-url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 400,\n          height: 200,\n          sourceUrl: 'large-url',\n        },\n      },\n    }) as ImageResource;\n    expect(getSmallestUrlForWidth(210, resource)).toBe('med-url');\n  });\n\n  it('should return an image according to the device pixel ratio', () => {\n    window.devicePixelRatio = 2;\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 400,\n      height: 200,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 100,\n          sourceUrl: 'full-url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 150,\n          sourceUrl: 'med-url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 400,\n          height: 200,\n          sourceUrl: 'large-url',\n        },\n      },\n    }) as ImageResource;\n    expect(getSmallestUrlForWidth(160, resource)).toBe('large-url');\n  });\n\n  it('should return an image with the same aspect ratio', () => {\n    const resource: ImageResource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 400,\n      height: 200,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 500,\n          sourceUrl: 'portrait-url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 250,\n          height: 250,\n          sourceUrl: 'square-url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 150,\n          sourceUrl: 'med-url',\n        },\n        img4: {\n          mimeType: 'image/jpeg',\n          width: 400,\n          height: 200,\n          sourceUrl: 'large-url',\n        },\n      },\n    }) as ImageResource;\n    expect(getSmallestUrlForWidth(150, resource)).toBe('med-url');\n  });\n\n  it('should return the resource.src if there is no valid thumb', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 400,\n      height: 200,\n      sizes: {\n        img1: {\n          mimeType: 'image/jpeg',\n          width: 200,\n          height: 1,\n          sourceUrl: 'small-url',\n        },\n        img2: {\n          mimeType: 'image/jpeg',\n          width: 300,\n          height: 1,\n          sourceUrl: 'med-url',\n        },\n        img3: {\n          mimeType: 'image/jpeg',\n          width: 400,\n          height: 1,\n          sourceUrl: 'large-url',\n        },\n      },\n    }) as ImageResource;\n    expect(getSmallestUrlForWidth(440, resource)).toBe('default-url');\n  });\n\n  it('should return the default src URL if no alternatives', () => {\n    const resource = createResource({\n      id: 123,\n      type: ResourceType.Image,\n      mimeType: 'image/jpeg',\n      alt: '',\n      src: 'default-url',\n      width: 400,\n      height: 200,\n      sizes: {},\n    }) as ImageResource;\n    expect(getSmallestUrlForWidth(200, resource)).toBe('default-url');\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/getVideoLengthDisplay.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getVideoLengthDisplay from '../getVideoLengthDisplay';\n\ndescribe('getVideoLengthDisplay', () => {\n  it.each([\n    [0, '0:00'],\n    [60, '1:00'],\n    [610, '10:10'],\n    [6000, '1:40:00'],\n  ])('getVideoLengthDisplay(%d) should return %s', (length, expected) => {\n    expect(getVideoLengthDisplay(length)).toBe(expected);\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/isAnimatedGif.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\n\n/**\n * Internal dependencies\n */\nimport isAnimatedGif from '../isAnimatedGif';\n\ndescribe('isAnimatedGif', () => {\n  it('should detect animated GIF', () => {\n    const buffer = readFileSync(join(__dirname, '/testUtils/nyancat.gif'));\n    const arrayBuffer = buffer.slice(\n      buffer.byteOffset,\n      buffer.byteOffset + buffer.byteLength\n    );\n    const result = isAnimatedGif(arrayBuffer as unknown as ArrayBuffer);\n\n    expect(result).toBeTrue();\n  });\n\n  it('should not detect non-animated GIF', () => {\n    const buffer = readFileSync(join(__dirname, '/testUtils/still.gif'));\n    const arrayBuffer = buffer.slice(\n      buffer.byteOffset,\n      buffer.byteOffset + buffer.byteLength\n    );\n    const result = isAnimatedGif(arrayBuffer as unknown as ArrayBuffer);\n\n    expect(result).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/mimeTypes.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getExtensionsFromMimeType } from '../mimeTypes';\n\ndescribe('getExtensionsFromMimeType', () => {\n  it('returns an array of file extensions', () => {\n    expect(getExtensionsFromMimeType('audio/mpeg')).toStrictEqual([\n      'mp3',\n      'm3a',\n    ]);\n    expect(getExtensionsFromMimeType('audio/mp3')).toStrictEqual(['mp3']);\n    expect(getExtensionsFromMimeType('audio/aac')).toStrictEqual(['aac']);\n    expect(getExtensionsFromMimeType('audio/ogg')).toStrictEqual([\n      'oga',\n      'ogg',\n    ]);\n    expect(getExtensionsFromMimeType('video/mp4')).toStrictEqual(['mp4']);\n    expect(getExtensionsFromMimeType('invalid/type')).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/media/src/test/resourceList.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport resourceList from '../resourceList';\nimport { ResourceCacheEntryType } from '../types';\n\ndescribe('resourceList', () => {\n  beforeEach(() => {\n    resourceList.resetList();\n  });\n\n  it('should set and get cached resource by id', () => {\n    const id = 461;\n    const resourceState = {\n      type: ResourceCacheEntryType.Cached,\n      url: 'http://localhost/thumb.jpg',\n    };\n\n    resourceList.set(id, resourceState);\n    const result = resourceList.get(id);\n\n    expect(result).toStrictEqual(resourceState);\n  });\n\n  it('should start with empty list', () => {\n    expect(resourceList.list).toStrictEqual({});\n  });\n\n  it('should not update the resource to lower(cached) quality', () => {\n    const id = 461;\n    const resourceStateCached = {\n      type: ResourceCacheEntryType.Cached,\n      url: 'http://localhost/thumb.jpg',\n    };\n    const resourceStateFullsize = {\n      type: ResourceCacheEntryType.Fullsize,\n      url: 'http://localhost/full.jpg',\n    };\n\n    resourceList.set(id, resourceStateCached);\n    expect(resourceList.get(id)).toStrictEqual(resourceStateCached);\n\n    resourceList.set(id, resourceStateFullsize);\n    expect(resourceList.get(id)).toStrictEqual(resourceStateFullsize);\n\n    resourceList.set(id, resourceStateCached);\n    // Should not downgrade\n    expect(resourceList.get(id)).toStrictEqual(resourceStateFullsize);\n  });\n});\n"
  },
  {
    "path": "packages/media/src/types/audioResource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Resource } from './resource';\n\nexport interface AudioResource extends Pick<\n  Resource,\n  'type' | 'id' | 'src' | 'mimeType' | 'isExternal' | 'isPlaceholder'\n> {\n  /** Length in seconds. */\n  length: number;\n  /** The formatted length, e.g. \"01:17\". */\n  lengthFormatted: string;\n}\n"
  },
  {
    "path": "packages/media/src/types/gifResource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { SequenceResource } from './sequenceResource';\nimport type { ResourceType } from './resourceType';\n\nexport interface Output {\n  /** The MIME type of the resource. E.g. \"image/png\". */\n  mimeType: string;\n  /** The source URL of the resource. */\n  src: string;\n}\n\nexport interface GifResource extends SequenceResource {\n  type: ResourceType.Gif;\n  output: Output;\n}\n"
  },
  {
    "path": "packages/media/src/types/imageResource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from './resourceType';\nimport type { Resource } from './resource';\n\nexport interface ImageResource extends Resource {\n  type: ResourceType.Image;\n}\n"
  },
  {
    "path": "packages/media/src/types/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './gifResource';\nexport * from './imageResource';\nexport * from './resource';\nexport * from './resourceType';\nexport * from './videoResource';\nexport * from './audioResource';\nexport * from './sequenceResource';\nexport * from './resourceInput';\nexport * from './mediaElement';\nexport * from './propTypes';\nexport * from './resourceCache';\n"
  },
  {
    "path": "packages/media/src/types/mediaElement.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DimensionableElement } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport type { Resource } from './resource';\n\nexport interface MediaElement extends DimensionableElement {\n  resource: Resource;\n  scale?: number;\n  focalX?: number;\n  focalY?: number;\n}\n"
  },
  {
    "path": "packages/media/src/types/propTypes.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n/* eslint-disable no-restricted-imports -- Still used by other packages. */\nimport * as PropTypes from 'prop-types';\nimport type { Requireable } from 'prop-types';\n/* eslint-enable no-restricted-imports -- Still used by other packages. */\n\nexport const BackgroundAudioPropTypeShape = {\n  id: PropTypes.number,\n  src: PropTypes.string,\n  length: PropTypes.number,\n  lengthFormatted: PropTypes.string,\n  mimeType: PropTypes.string,\n  needsProxy: PropTypes.bool,\n};\nexport const BackgroundAudioPropType = PropTypes.shape(\n  BackgroundAudioPropTypeShape\n);\n\nexport const ResourcePropTypes: Record<string, Requireable<unknown>> = {};\n\nResourcePropTypes.resourceSize = PropTypes.shape({\n  file: PropTypes.string,\n  sourceUrl: PropTypes.string.isRequired,\n  mimeType: PropTypes.string.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n});\n\nResourcePropTypes.imageResourceSizes = PropTypes.oneOfType([\n  PropTypes.array,\n  PropTypes.objectOf(ResourcePropTypes.resourceSize),\n]);\n\nResourcePropTypes.videoResourceSizes = PropTypes.oneOfType([\n  PropTypes.array,\n  PropTypes.objectOf(ResourcePropTypes.resourceSize),\n]);\n\nResourcePropTypes.imageResource = PropTypes.shape({\n  type: PropTypes.string.isRequired,\n  id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  mimeType: PropTypes.string.isRequired,\n  src: PropTypes.string.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n  alt: PropTypes.string,\n  sizes: ResourcePropTypes.imageResourceSizes,\n});\n\nResourcePropTypes.trackResource = PropTypes.shape({\n  id: PropTypes.string.isRequired,\n  track: PropTypes.string.isRequired,\n  trackId: PropTypes.number,\n  kind: PropTypes.string,\n  srclang: PropTypes.string,\n  label: PropTypes.string,\n  needsProxy: PropTypes.bool,\n});\n\nResourcePropTypes.videoResource = PropTypes.shape({\n  type: PropTypes.string.isRequired,\n  id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  mimeType: PropTypes.string.isRequired,\n  src: PropTypes.string.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n  poster: PropTypes.string,\n  posterId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  alt: PropTypes.string,\n  title: PropTypes.string,\n  sizes: ResourcePropTypes.videoResourceSizes,\n});\n\nResourcePropTypes.gifResource = PropTypes.shape({\n  type: PropTypes.string.isRequired,\n  id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  mimeType: PropTypes.string.isRequired,\n  src: PropTypes.string.isRequired,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n  title: PropTypes.string,\n  alt: PropTypes.string,\n  sizes: ResourcePropTypes.imageResourceSizes,\n  output: PropTypes.shape({\n    mimeType: PropTypes.string.isRequired,\n    src: PropTypes.string.isRequired,\n    sizes: PropTypes.shape({\n      mp4: ResourcePropTypes.videoResourceSizes,\n      webm: ResourcePropTypes.videoResourceSizes,\n    }),\n  }),\n});\n\nResourcePropTypes.resource = PropTypes.oneOfType([\n  ResourcePropTypes.imageResource,\n  ResourcePropTypes.videoResource,\n  ResourcePropTypes.trackResource,\n  ResourcePropTypes.gifResource,\n]);\n\n/**\n * Author object\n *\n * @typedef {Author} Author\n * @property {string} displayName The display name of the author.\n * @property {?string} url An optional URL to link to the author's profile or\n * website.\n */\n\n/**\n * Attribution object\n *\n * @typedef {Attribution} Attribution\n * @property {?Author} author The optional author of the media object.\n * @property {?string} registerUsageUrl The optional url to register the media\n * usage.\n */\n\n/**\n * TrimData object\n *\n * @typedef {TrimData} TrimData data object linking a trimmed video to its original\n * @property {number} original The ID of the original video.\n * @property {string} start Time stamp of start time of new video. Example '00:01:02.345'.\n * @property {string} end Time stamp of end time of new video. Example '00:02:00'.\n */\n\n/**\n * Attachment object.\n *\n * @typedef {Attachment} Attachment\n * @property {string|null} baseColor Attachment base color.\n * @property {string|null} blurHash Attachment blur hash.\n * @property {string} [type] Attachment type, e.g. video or image.\n * @property {string} mimeType The MIME type.\n * @property {string|null} creationDate When the attachment was created.\n * @property {string} src The source URL.\n * @property {number} width The natural resource width.\n * @property {number} height The natural resource height.\n * @property {string|null} poster The poster URL for the \"video\" type.\n * @property {number|null} posterId The system poster ID.\n * @property {number|null} id The system ID.\n * @property {number|null} length The length for the \"video\" type.\n * @property {string|null} lengthFormatted The formatted length for the \"video\" type.\n * @property {string|null} alt The user-readable accessibility label for the resource.\n * @property {boolean} local Whether the resource has been already uploaded to the server.\n * @property {boolean} isOptimized Whether the resource has already been optimized.\n * @property {boolean|null} isMuted Whether the resource has already been muted.\n * @property {boolean|null} isExternal Whether the resource is externally hosted.\n * @property {boolean|null} isPlaceholder Whether the resource is a placeholder.\n * @property {Object} sizes Object of image sizes.\n * @property {?Object} output An optional object of video sizes for rendering gifs as videos.\n * @property {?TrimData} trimData An optional object of video trim data.\n * @property {boolean} needsProxy Whether the resource needs a CORS proxy.\n */\n\n/**\n * ResourceSize object\n *\n * @typedef {ResourceSize} ResourceSize\n * @property {number} width The width of the ResourceSize.\n * @property {number} height The height of the ResourceSize.\n * @property {string} sourceUrl The URL pointing to the resource for this size.\n * @property {string|null} mimeType The mimeType of this ResourceSize.\n */\n\n/**\n * Resource object.\n *\n * @typedef {Resource} Resource\n * @property {string|null} baseColor An optional attribution to detect the base color of a resource (an image or video). Value looks like #ff00ff.\n * @property {string|null} blurHash An optional attribution to detect the blurhash of a resource (an image or video).\n * @property {string|null} type Resource type. Currently only \"image\" and \"video\" values are allowed. If not specified, will be calculated from the mime-type.\n * @property {string} mimeType The MIME type.\n * @property {string|null} creationDate When resource was created.\n * @property {string} src The source URL.\n * @property {number} width The natural resource width.\n * @property {number} height The natural resource height.\n * @property {string|null} poster The poster URL for the \"video\" type.\n * @property {number|null} posterId The system poster ID.\n * @property {number|null} id The system ID.\n * @property {number|null} length The length for the \"video\" type.\n * @property {string|null} lengthFormatted The formatted length for the \"video\" type.\n * @property {string|null} alt The user-readable accessibility label for the resource.\n * @property {boolean} local Whether the resource has been already uploaded to the server.\n * @property {boolean} isOptimized Whether the resource has already been optimized.\n * @property {boolean} isMuted Whether the resource has already been muted.\n * @property {boolean} isExternal Whether the resource is externally hosted.\n * @property {boolean} isPlaceholder Whether the resource is a placeholder.\n * @property {Object.<string, ResourceSize>} sizes Object of image sizes.\n * @property {Attribution|null} attribution An optional attribution for the resource.\n * @property {?Object} output An optional object of video sizes for rendering gifs as videos\n * @property {?TrimData} trimData An optional object of video trim data.\n * @property {boolean} needsProxy Whether the resource needs a CORS proxy.\n */\n"
  },
  {
    "path": "packages/media/src/types/resource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from './resourceType';\n\nexport interface Dimensions {\n  width: number;\n  height: number;\n}\n\nexport interface AttributionAuthor {\n  /** Display name of the author. */\n  displayName: string;\n  /** The author's profile or website. */\n  url: string;\n}\n\nexport interface Attribution {\n  /** The optional author of the media object. */\n  author?: AttributionAuthor;\n  /** The optional url to register the media usage. */\n  registerUsageUrl?: string;\n}\n\nexport interface ResourceSize {\n  /** The MIME type of the resource. E.g. \"image/png\". */\n  mimeType: string;\n  /** The source URL of the resource. */\n  sourceUrl: string;\n  /** The natural width of the resource in physical pixels. */\n  width: number;\n  /** The natural height of the resource in physical pixels. */\n  height: number;\n}\n\nexport type ResourceId = string | number;\n\n/** A media resource. */\nexport interface Resource {\n  /**\n   * The resource ID.\n   * TODO: currently this value is local to the editor's media system.\n   */\n  id: ResourceId;\n  /** The type of the resource. */\n  type: ResourceType;\n  /** The MIME type of the resource. E.g. \"image/png\". */\n  mimeType: string;\n  /** The source URL of the resource. */\n  src: string;\n  /** The \"alt\" text of the resource. */\n  alt: string;\n  /** The natural width of the resource in physical pixels. */\n  width: number;\n  /** The natural height of the resource in physical pixels. */\n  height: number;\n  /** The resource's average color. */\n  baseColor?: string;\n  /** BlurHash. */\n  blurHash?: string;\n  /** Whether the resource externally hosted. */\n  isExternal?: boolean;\n  /** Whether the resource is a placeholder. */\n  isPlaceholder?: boolean;\n  /** Whether the resource needs a CORS proxy. */\n  needsProxy?: boolean;\n  /** Resource creation date. */\n  readonly creationDate?: string;\n  /** Resource sizes */\n  sizes?: { [key: string]: ResourceSize };\n  /** Resource author attribution */\n  attribution?: Attribution;\n\n  // TODO: Figure out why sometimes _images_ end up having these properties.\n  posterId?: ResourceId;\n  isOptimized?: boolean;\n\n  // TODO: This property should probably not end up in a story. Only relevant for the media library.\n  provider?: 'local' | 'unsplash' | 'coverr' | 'tenor' | 'tenor_stickers';\n}\n"
  },
  {
    "path": "packages/media/src/types/resourceCache.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ResourceCacheEntryType {\n  Cached = 'cached',\n  Fullsize = 'fullsize',\n}\n\nexport interface ResourceCacheEntry {\n  url: string;\n  type: ResourceCacheEntryType;\n}\n"
  },
  {
    "path": "packages/media/src/types/resourceInput.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from './resourceType';\nimport type { ResourceSize, Attribution, ResourceId } from './resource';\nimport type { TrimData } from './videoResource';\nimport type { Output } from './gifResource';\n\nexport interface ResourceInput {\n  /**\n   * The resource ID.\n   * TODO: currently this value is local to the editor's media system.\n   */\n  id: ResourceId;\n  /** The type of the resource. */\n  type: ResourceType;\n  /** The MIME type of the resource. E.g. \"image/png\". */\n  mimeType: string;\n  /** The source URL of the resource. */\n  src: string;\n  /** The \"alt\" text of the resource. */\n  alt: string;\n  /** The natural width of the resource in physical pixels. */\n  width: number;\n  /** The natural height of the resource in physical pixels. */\n  height: number;\n  /** The resource's average color. */\n  baseColor?: string;\n  /** BlurHash. */\n  blurHash?: string;\n  /** Whether the resource externally hosted. */\n  isExternal?: boolean;\n  /** Whether the resource is a placeholder. */\n  isPlaceholder?: boolean;\n  /** Whether the resource needs a CORS proxy. */\n  needsProxy?: boolean;\n  /** Resource creation date. */\n  creationDate?: string;\n  /** Resource sizes */\n  sizes?: { [key: string]: ResourceSize };\n  /** Resource author attribution */\n  attribution?: Attribution;\n  /** The resource's poster. */\n  poster?: string;\n  /** The resource's poster ID. */\n  posterId?: ResourceId;\n  /** Length in seconds. */\n  length?: number;\n  /** The formatted length, e.g. \"01:17\". */\n  lengthFormatted?: string;\n  /** Whether the resource has already been optimized. */\n  isOptimized?: boolean;\n  /** Whether the resource is muted. */\n  isMuted?: boolean;\n  /** Information about trimmed video and its original. */\n  trimData?: TrimData;\n  /** Output type data, for GIFs */\n  output?: Output;\n}\n"
  },
  {
    "path": "packages/media/src/types/resourceType.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ResourceType {\n  Image = 'image',\n  Video = 'video',\n  Gif = 'gif',\n  Audio = 'audio',\n}\n"
  },
  {
    "path": "packages/media/src/types/sequenceResource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Resource, ResourceId } from './resource';\n\n/** This is an abstract parent type of both video and gif resources */\nexport interface SequenceResource extends Resource {\n  /** The resource's poster. */\n  poster?: string;\n  /** The resource's poster ID. */\n  posterId?: ResourceId;\n  /** Whether the resource has already been optimized. */\n  isOptimized?: boolean;\n}\n"
  },
  {
    "path": "packages/media/src/types/videoResource.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from './resourceType';\nimport type { SequenceResource } from './sequenceResource';\nimport type { ResourceId } from './resource';\n\nexport interface TrimData {\n  /** ID of the original video. */\n  original: ResourceId;\n  /** Time stamp of start time of new video. Example '00:01:02.345'. */\n  start: string;\n  /** Time stamp of end time of new video. Example '00:01:02.345'. */\n  end: string;\n}\n\nexport interface VideoResource extends SequenceResource {\n  type: ResourceType.Video;\n  /** Length in seconds. */\n  length: number;\n  /** The formatted length, e.g. \"01:17\". */\n  lengthFormatted: string;\n  /** Whether the resource is muted. */\n  isMuted?: boolean;\n  /** Information about trimmed video and its original. */\n  trimData?: TrimData;\n}\n"
  },
  {
    "path": "packages/media/src/typings/dom.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// See https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#more-libdomdts-refinements\n\ninterface AudioTrack {\n  enabled: boolean;\n  id: string;\n  kind:\n    | 'alternative'\n    | 'descriptions'\n    | 'main'\n    | 'main-desc'\n    | 'translation'\n    | 'commentary'\n    | '';\n  label: string;\n  language: string;\n  sourceBuffer: SourceBuffer | null;\n}\n\ninterface AudioTrackList {\n  [Symbol.iterator](): IterableIterator<AudioTrack>;\n  length: number;\n}\n\ninterface HTMLVideoElement {\n  readonly audioTracks?: AudioTrackList;\n  readonly mozHasAudio?: boolean;\n  readonly webkitAudioDecodedByteCount?: number;\n}\n"
  },
  {
    "path": "packages/media/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../react\" },\n    { \"path\": \"../tracking\" },\n    { \"path\": \"../units\" }\n  ],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/migration/.npmignore",
    "content": "scripts\nsrc\n"
  },
  {
    "path": "packages/migration/README.md",
    "content": "# Migrations\n\nThis package contains the code to migrate stories and templates to the latest version.\n\n## Exports\n\n- `DATA_VERSION`: the latest version\n- `migrate`: the function to migrate a story, given a data object and the story's current version.\n\n## Used by\n\n- Dashboard\n- Editor\n- Continuous Integration (automated migrations of templates and FTUE story)\n\n## ES Module\n\nThis package uses depends on third-party packages like [`polished`](https://www.npmjs.com/package/polished).\n\nTo ensure the migrations can be run via Node.js on CI, [Rollup](https://rollupjs.org/guide/en/) is used to create a working ES module for it.\n\nUsage:\n\n```bash\n$ npx rollup --config rollup.config.js\nindex.js → module.js...\ncreated module.js in 123ms\n```\n"
  },
  {
    "path": "packages/migration/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/migration\",\n  \"description\": \"Utility package for migrating stories to the latest data format.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/migration/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/migration\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/elements\": \"*\",\n    \"polished\": \"^4.3.1\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@rollup/plugin-babel\": \"^6.0.4\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.3\",\n    \"rollup\": \"^2.80.0\"\n  },\n  \"scripts\": {\n    \"migration\": \"node ./scripts/cli.js\"\n  }\n}\n"
  },
  {
    "path": "packages/migration/rollup.config.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { dirname, resolve as resolvePath } from 'path';\nimport { fileURLToPath } from 'url';\nimport resolve from '@rollup/plugin-node-resolve';\nimport { babel } from '@rollup/plugin-babel';\n\nconst __dirname = fileURLToPath(dirname(import.meta.url));\n\nexport default {\n  input: resolvePath(__dirname, 'src/index.ts'),\n  output: {\n    file: resolvePath(__dirname, 'scripts/module.js'),\n    format: 'es',\n  },\n  plugins: [\n    resolve({\n      preferBuiltins: true,\n      extensions: ['.ts'],\n    }),\n    babel({\n      babelrc: false,\n      extensions: ['.ts'],\n      babelHelpers: 'inline',\n      exclude: 'node_modules/**',\n      presets: ['@babel/preset-env', '@babel/preset-typescript'],\n    }),\n  ],\n  external: ['crypto'],\n};\n"
  },
  {
    "path": "packages/migration/scripts/cli.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport updateTemplates from './utils/updateTemplates.js';\n\nconst args = process.argv.slice(2);\nconst dir = args[0] ? args[0] : undefined;\n\nif (!dir) {\n  throw new Error('Directory path was not provided');\n}\n\nupdateTemplates(dir);\n\n// eslint-disable-next-line no-console\nconsole.log(\"Files updated! Don't forget to run prettier!\");\n"
  },
  {
    "path": "packages/migration/scripts/utils/test/updateTemplates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __setMockFiles, readFileSync } from 'node:fs';\n\n/**\n * Internal dependencies\n */\nimport updateTemplates from '../updateTemplates';\n\njest.mock('node:fs');\njest.mock('../../module', () => ({\n  migrate: jest.fn(() => ({ migratedkey: 'migratedvalue' })),\n  DATA_VERSION: 9999,\n}));\n\nconst TEMPLATE_1_CONTENT = JSON.stringify({\n  version: 1,\n  foo: 'bar',\n  baz: 'foobar',\n});\n\nconst TEMPLATE_2_CONTENT = JSON.stringify({\n  version: 9999,\n  foo: 'bar',\n  baz: 'foobar',\n});\n\ndescribe('updateTemplates', () => {\n  const MOCK_FILE_INFO = {\n    '/foo/template1.json': TEMPLATE_1_CONTENT,\n    '/foo/template2.json': TEMPLATE_2_CONTENT,\n  };\n\n  beforeEach(() => {\n    __setMockFiles(MOCK_FILE_INFO);\n  });\n\n  it('should use provided version number', () => {\n    updateTemplates('/foo');\n    const template1 = readFileSync('/foo/template1.json');\n    const template2 = readFileSync('/foo/template2.json');\n\n    expect(template1).toStrictEqual(\n      JSON.stringify({\n        version: 9999,\n        migratedkey: 'migratedvalue',\n      })\n    );\n    expect(template2).toStrictEqual(TEMPLATE_2_CONTENT);\n  });\n});\n"
  },
  {
    "path": "packages/migration/scripts/utils/updateTemplates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readdirSync, readFileSync, writeFileSync, lstatSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\n/**\n * Internal dependencies\n */\n// eslint-disable-next-line import/no-unresolved\nimport { migrate, DATA_VERSION } from '../module.js';\n\nfunction updateTemplates(templatesDir) {\n  const fileNamePattern = /^.*\\.json$/;\n\n  const getFiles = (dir) =>\n    readdirSync(dir).map((fileOrDir) =>\n      lstatSync(join(dir, fileOrDir)).isDirectory()\n        ? getFiles(join(dir, fileOrDir))\n        : join(dir, fileOrDir)\n    );\n\n  // templatesDir is relative from the project root,\n  // heence going two levels up.\n  const templateFiles = getFiles(\n    resolve(process.cwd(), '..', '..', templatesDir)\n  )\n    .flat()\n    .filter((file) => fileNamePattern.test(file));\n\n  for (const file of templateFiles) {\n    const template = JSON.parse(readFileSync(file, 'utf8'));\n\n    if (Number(template.version) === Number(DATA_VERSION)) {\n      continue;\n    }\n\n    // This ensures that the version number is always at the top.\n    const updatedTemplate = {\n      version: DATA_VERSION,\n      ...migrate(template, template.version),\n    };\n    updatedTemplate.version = DATA_VERSION;\n\n    const templateFileContent = JSON.stringify(updatedTemplate);\n\n    writeFileSync(file, templateFileContent);\n  }\n}\n\nexport default updateTemplates;\n"
  },
  {
    "path": "packages/migration/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { DATA_VERSION, migrate } from './migrate';\n"
  },
  {
    "path": "packages/migration/src/migrate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { StoryData } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport storyDataArrayToObject from './migrations/v0001_storyDataArrayToObject';\nimport dataPixelTo1080 from './migrations/v0002_dataPixelTo1080';\nimport fullbleedToFill from './migrations/v0003_fullbleedToFill';\nimport squareToShape from './migrations/v0004_squareToShape';\nimport mediaElementToResource from './migrations/v0004_mediaElementToResource';\nimport setOpacity from './migrations/v0005_setOpacity';\nimport colorToPattern from './migrations/v0006_colorToPattern';\nimport setFlip from './migrations/v0007_setFlip';\nimport paddingToObject from './migrations/v0008_paddingToObject';\nimport defaultBackground from './migrations/v0009_defaultBackground';\nimport dataPixelTo440 from './migrations/v0010_dataPixelTo440';\nimport pageAdvancement from './migrations/v0011_pageAdvancement';\nimport setBackgroundTextMode from './migrations/v0012_setBackgroundTextMode';\nimport videoIdToId from './migrations/v0013_videoIdToId';\nimport oneTapLinkDeprecate from './migrations/v0014_oneTapLinkDeprecate';\nimport fontObjects from './migrations/v0015_fontObjects';\nimport isFullBleedDeprecate from './migrations/v0016_isFullbleedDeprecate';\nimport inlineTextProperties from './migrations/v0017_inlineTextProperties';\nimport defaultBackgroundElement from './migrations/v0018_defaultBackgroundElement';\nimport conicToLinear from './migrations/v0019_conicToLinear';\nimport isFillDeprecate from './migrations/v0020_isFillDeprecate';\nimport backgroundColorToPage from './migrations/v0021_backgroundColorToPage';\nimport dataPixelTo412 from './migrations/v0022_dataPixelTo412';\nimport convertOverlayPattern from './migrations/v0023_convertOverlayPattern';\nimport blobsToSingleBlob from './migrations/v0024_blobsToSingleBlob';\nimport singleAnimationTarget from './migrations/v0025_singleAnimationTarget';\nimport backgroundOverlayToOverlay from './migrations/v0026_backgroundOverlayToOverlay';\nimport videoDuration from './migrations/v0027_videoDuration';\nimport mark3pVideoAsOptimized from './migrations/v0028_mark3pVideoAsOptimized';\nimport unifyGifResources from './migrations/v0029_unifyGifResources';\nimport mark3pVideoAsMuted from './migrations/v0030_mark3pVideoAsMuted';\nimport normalizeResourceSizes from './migrations/v0031_normalizeResourceSizes';\nimport pageOutlinkTheme from './migrations/v0032_pageOutlinkTheme';\nimport removeTitleFromResources from './migrations/v0033_removeTitleFromResources';\nimport removeUnusedBackgroundProps from './migrations/v0034_removeUnusedBackgroundProps';\nimport markVideoAsExternal from './migrations/v0035_markVideoAsExternal';\nimport changeBaseColorToHex from './migrations/v0036_changeBaseColorToHex';\nimport removeTransientMediaProperties from './migrations/v0037_removeTransientMediaProperties';\nimport camelCaseResourceSizes from './migrations/v0038_camelCaseResourceSizes';\nimport backgroundAudioFormatting from './migrations/v0039_backgroundAudioFormatting';\nimport andadaFontToAndadaPro from './migrations/v0040_andadaFontToAndadaPro';\nimport removeFontProperties from './migrations/v0041_removeFontProperties';\nimport removeTrackName from './migrations/v0042_removeTrackName';\nimport removeTagNames from './migrations/v0043_removeTagNames';\nimport unusedProperties from './migrations/v0044_unusedProperties';\nimport globalPageAdvancement from './migrations/v0045_globalPageAdvancement';\nimport removeRedundantScalingProperties from './migrations/v0046_removeRedundantScalingProperties';\nimport fixBrokenTemplates from './migrations/v0047_fixBrokenTemplates';\n\ntype MigrationFn<T, S> = (storyData: T) => S;\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- See below.\n// @ts-ignore Reason: Temporary (hopefully). Don't have a good solution for this yet as it accepts all story types.\nconst MIGRATIONS: Record<number, MigrationFn<any, any>[]> = { // eslint-disable-line @typescript-eslint/no-explicit-any,prettier/prettier -- See above.\n  1: [storyDataArrayToObject],\n  2: [dataPixelTo1080],\n  3: [fullbleedToFill],\n  4: [squareToShape, mediaElementToResource],\n  5: [setOpacity],\n  6: [colorToPattern],\n  7: [setFlip],\n  8: [paddingToObject],\n  9: [defaultBackground],\n  10: [dataPixelTo440],\n  11: [pageAdvancement],\n  12: [setBackgroundTextMode],\n  13: [videoIdToId],\n  14: [oneTapLinkDeprecate],\n  15: [fontObjects],\n  16: [isFullBleedDeprecate],\n  17: [inlineTextProperties],\n  18: [defaultBackgroundElement],\n  19: [conicToLinear],\n  20: [isFillDeprecate],\n  21: [backgroundColorToPage],\n  22: [dataPixelTo412],\n  23: [convertOverlayPattern],\n  24: [blobsToSingleBlob],\n  25: [singleAnimationTarget],\n  26: [backgroundOverlayToOverlay],\n  27: [videoDuration],\n  28: [mark3pVideoAsOptimized],\n  29: [unifyGifResources],\n  30: [mark3pVideoAsMuted],\n  31: [normalizeResourceSizes],\n  32: [pageOutlinkTheme],\n  33: [removeTitleFromResources],\n  34: [removeUnusedBackgroundProps],\n  35: [markVideoAsExternal],\n  36: [changeBaseColorToHex],\n  37: [removeTransientMediaProperties],\n  38: [camelCaseResourceSizes],\n  39: [backgroundAudioFormatting],\n  40: [andadaFontToAndadaPro],\n  41: [removeFontProperties],\n  42: [removeTrackName],\n  43: [removeTagNames],\n  44: [unusedProperties],\n  45: [globalPageAdvancement],\n  46: [removeRedundantScalingProperties],\n  47: [fixBrokenTemplates],\n};\n\nexport const DATA_VERSION = Math.max.apply(\n  null,\n  Object.keys(MIGRATIONS).map(Number)\n);\n\nexport function migrate(\n  storyData: Partial<StoryData>,\n  version: number\n): Partial<StoryData> {\n  let result = storyData;\n  for (let v = version; v < DATA_VERSION; v++) {\n    const migrations = MIGRATIONS[v + 1];\n    if (!migrations) {\n      continue;\n    }\n    for (let i = 0; i < migrations.length; i++) {\n      if (Object.prototype.hasOwnProperty.call(migrations, i)) {\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- Remove when MigrationFn is typed correctly.\n        result = migrations[i](result);\n      }\n    }\n  }\n  return result;\n}\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0001_storyDataArrayToObject.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport storyDataArrayToObject from '../v0001_storyDataArrayToObject';\n\ndescribe('storyDataArrayToObject', () => {\n  it('should convert an array of pages into a story object', () => {\n    expect(\n      storyDataArrayToObject([{ _test: 'page1' }, { _test: 'page2' }])\n    ).toStrictEqual({\n      pages: [{ _test: 'page1' }, { _test: 'page2' }],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0002_dataPixelTo1080.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport dataPixelTo1080 from '../v0002_dataPixelTo1080';\n\ndescribe('dataPixelTo1080', () => {\n  it('should convert all pixel props', () => {\n    expect(\n      dataPixelTo1080({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                x: 11,\n                y: 21,\n                width: 101,\n                height: 201,\n                fontSize: 22,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              x: 26,\n              y: 52,\n              width: 262,\n              height: 525,\n            },\n            {\n              _test: 'element2',\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0003_fullbleedToFill.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport fullbleedToFill from '../v0003_fullbleedToFill';\n\ndescribe('fullbleedToFill', () => {\n  it('should fullbleed to fill', () => {\n    expect(\n      fullbleedToFill({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                isFullbleed: true,\n              },\n              {\n                _test: 'element2',\n                isFullbleed: false,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              isFill: true,\n            },\n            {\n              _test: 'element2',\n              isFill: false,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0004_mediaElementToResource.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport dataMediaElementToResource from '../v0004_mediaElementToResource';\n\ndescribe('dataMediaElementToResource', () => {\n  it('should convert all image and video elements to use resource', () => {\n    expect(\n      dataMediaElementToResource({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                videoId: 102113,\n                mimeType: 'video/mp4',\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                videoId: 102113,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0004_squareToShape.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport dataSquareToShape from '../v0004_squareToShape';\n\ndescribe('dataSquareToShape', () => {\n  it('should convert all square elements', () => {\n    expect(\n      dataSquareToShape({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 101,\n                height: 201,\n              },\n              {\n                _test: 'element2',\n                type: 'square',\n                x: 29,\n                y: 55,\n                width: 101,\n                height: 201,\n                fontSize: 22,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'square',\n                x: 29,\n                y: 55,\n                width: 101,\n                height: 201,\n                fontSize: 22,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'shape',\n              x: 10,\n              y: 20,\n              width: 101,\n              height: 201,\n            },\n            {\n              _test: 'element2',\n              type: 'shape',\n              x: 29,\n              y: 55,\n              width: 101,\n              height: 201,\n              fontSize: 22,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'shape',\n              x: 29,\n              y: 55,\n              width: 101,\n              height: 201,\n              fontSize: 22,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0005_setOpacity.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport setOpacity from '../v0005_setOpacity';\n\ndescribe('setOpacity', () => {\n  it('should set opacity if not set', () => {\n    expect(\n      setOpacity({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                opacity: 0,\n              },\n              {\n                _test: 'element2',\n              },\n              {\n                _test: 'element3',\n                opacity: 50,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              opacity: 0,\n            },\n            {\n              _test: 'element2',\n              opacity: 100,\n            },\n            {\n              _test: 'element3',\n              opacity: 50,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0006_colorToPattern.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport colorToPattern from '../v0006_colorToPattern';\n\ndescribe('colorToPattern', () => {\n  it('should fullbleed to fill', () => {\n    expect(\n      colorToPattern({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            backgroundColor: '#fff',\n            elements: [\n              {\n                _test: 'element1',\n              },\n              {\n                _test: 'element2',\n                color: 'black',\n              },\n              {\n                _test: 'element3',\n                color: 'transparent',\n              },\n              {\n                _test: 'element4',\n                color: null,\n              },\n              {\n                _test: 'element5',\n                color: '#f00',\n              },\n              {\n                _test: 'element6',\n                backgroundColor: '#c0ffee',\n              },\n              {\n                _test: 'element7',\n                backgroundColor: 'rgba(255, 0, 0, .5)',\n                color: 'salmon',\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              _test: 'element1',\n            },\n            {\n              _test: 'element2',\n              color: { color: { r: 0, g: 0, b: 0 } },\n            },\n            {\n              _test: 'element3',\n              color: null,\n            },\n            {\n              _test: 'element4',\n              color: null,\n            },\n            {\n              _test: 'element5',\n              color: { color: { r: 255, g: 0, b: 0 } },\n            },\n            {\n              _test: 'element6',\n              backgroundColor: { color: { r: 192, g: 255, b: 238 } },\n            },\n            {\n              _test: 'element7',\n              backgroundColor: { color: { r: 255, g: 0, b: 0, a: 0.5 } },\n              color: { color: { r: 250, g: 128, b: 114 } },\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          backgroundColor: null,\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0007_setFlip.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport setFlip from '../v0007_setFlip';\n\ndescribe('setFlip', () => {\n  it('should set flip if not set', () => {\n    expect(\n      setFlip({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                flip: {\n                  horizontal: false,\n                  vertical: true,\n                },\n              },\n              {\n                _test: 'element2',\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              flip: {\n                horizontal: false,\n                vertical: true,\n              },\n            },\n            {\n              _test: 'element2',\n              flip: {\n                horizontal: false,\n                vertical: false,\n              },\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0008_paddingToObject.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport paddingToObject from '../v0008_paddingToObject';\n\ndescribe('paddingToObject', () => {\n  it('should convert padding to object', () => {\n    expect(\n      paddingToObject({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'text',\n                padding: 10,\n                content: '',\n              },\n              {\n                _test: 'element2',\n                type: 'text',\n                content: '',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              padding: {\n                horizontal: 10,\n                vertical: 10,\n              },\n              content: '',\n            },\n            {\n              _test: 'element2',\n              type: 'text',\n              padding: {\n                horizontal: 0,\n                vertical: 0,\n              },\n              content: '',\n            },\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should not set padding for non-text elements', () => {\n    expect(\n      paddingToObject({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'image',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'image',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0009_defaultBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport defaultBackground from '../v0009_defaultBackground';\n\ndescribe('defaultBackground', () => {\n  it('should add a default background to pages that dont have it', () => {\n    const migrated = defaultBackground({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              padding: 10,\n            },\n            {\n              _test: 'element2',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n    const page = migrated.pages[0];\n    const bgEl = page.elements[0];\n    expect(page.backgroundElementId).not.toBeNull();\n    expect(page.backgroundElementId).toStrictEqual(bgEl.id);\n    expect(bgEl.type).toBe('shape');\n    expect(bgEl.isBackground).toBeTrue();\n  });\n\n  it('should maintain background color when migrating', () => {\n    const migrated = defaultBackground({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          backgroundColor: { color: { r: 255, g: 0, b: 0, a: 0.5 } },\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              padding: 10,\n            },\n            {\n              _test: 'element2',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n    const page = migrated.pages[0];\n    const bgEl = page.elements[0];\n    expect(page.backgroundElementId).not.toBeNull();\n    expect(page.backgroundElementId).toStrictEqual(bgEl.id);\n    expect(bgEl.type).toBe('shape');\n    expect(bgEl.isBackground).toBeTrue();\n    expect(bgEl.backgroundColor).toStrictEqual({\n      color: { r: 255, g: 0, b: 0, a: 0.5 },\n    });\n  });\n\n  it('should not add a background to elements that already have it', () => {\n    expect(\n      defaultBackground({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            backgroundElementId: 'unique-id',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'image',\n                isBackground: true,\n                id: 'unique-id',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          backgroundElementId: 'unique-id',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'image',\n              isBackground: true,\n              id: 'unique-id',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0010_dataPixelTo440.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport dataPixelTo440 from '../v0010_dataPixelTo440';\n\ndescribe('dataPixelTo440', () => {\n  it('should convert all pixel props', () => {\n    expect(\n      dataPixelTo440({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                x: 40,\n                y: 80,\n                width: 1080,\n                height: 1920,\n              },\n              {\n                _test: 'element2',\n                x: 41,\n                y: 81,\n                width: 401,\n                height: 801,\n                fontSize: 82,\n                padding: { horizontal: 10, vertical: 10 },\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              x: 14,\n              y: 28,\n              width: 371,\n              height: 660,\n            },\n            {\n              _test: 'element2',\n              x: 14,\n              y: 28,\n              width: 138,\n              height: 275,\n              fontSize: 28,\n              padding: { horizontal: 3, vertical: 3 },\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0011_pageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport pageAdvancement from '../v0011_pageAdvancement';\n\ndescribe('pageAdvancement', () => {\n  it('should add page advancement properties', () => {\n    expect(\n      pageAdvancement({\n        _test: 'story',\n        pages: [],\n      })\n    ).toStrictEqual({\n      autoAdvance: true,\n      defaultPageDuration: 7,\n      _test: 'story',\n      pages: [],\n    });\n  });\n\n  it('should not override existing page advancement properties', () => {\n    expect(\n      pageAdvancement({\n        _test: 'story',\n        pages: [],\n        autoAdvance: false,\n        defaultPageDuration: 10,\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [],\n      autoAdvance: false,\n      defaultPageDuration: 10,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0012_setBackgroundTextMode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport setBackgroundTextMode from '../v0012_setBackgroundTextMode';\n\ndescribe('setBackgroundTextMode', () => {\n  it('should set background text mode if not set', () => {\n    expect(\n      setBackgroundTextMode({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'text',\n                backgroundColor: '#000',\n                content: '',\n              },\n              {\n                _test: 'element2',\n                type: 'text',\n                content: '',\n              },\n              {\n                _test: 'element3',\n                type: 'text',\n                content: '',\n              },\n              {\n                _test: 'element4',\n                type: 'image',\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              backgroundColor: '#000',\n              backgroundTextMode: 'FILL',\n              type: 'text',\n              content: '',\n            },\n            {\n              _test: 'element2',\n              backgroundTextMode: 'NONE',\n              type: 'text',\n              content: '',\n            },\n            {\n              _test: 'element3',\n              backgroundTextMode: 'NONE',\n              type: 'text',\n              content: '',\n            },\n            {\n              _test: 'element4',\n              type: 'image',\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0013_videoIdToId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport videoIdToId from '../v0013_videoIdToId';\n\ndescribe('videoIdToId', () => {\n  it('should migrate videoId to id', () => {\n    expect(\n      videoIdToId({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  videoId: 102113,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0014_oneTapLinkDeprecate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport oneTapLinkDeprecate from '../v0014_oneTapLinkDeprecate';\n\ndescribe('oneTapLinkDeprecate', () => {\n  it('should remove link type', () => {\n    expect(\n      oneTapLinkDeprecate({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                link: {\n                  type: 1,\n                  url: 'https://example.com/',\n                },\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                link: {\n                  type: 2,\n                  url: 'https://example.com/',\n                },\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                link: {\n                  type: 1,\n                  url: 'https://example.com/',\n                  image: 'https://example.com/image.png',\n                },\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n              link: {\n                url: 'https://example.com/',\n              },\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n              link: {\n                url: 'https://example.com/',\n              },\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n              link: {\n                url: 'https://example.com/',\n                image: 'https://example.com/image.png',\n              },\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0015_fontObjects.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport fontObjects from '../v0015_fontObjects';\n\ndescribe('fontObjects', () => {\n  it('should convert fontFamily to font object', () => {\n    expect(\n      fontObjects({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'text',\n                fontFamily: 'Roboto',\n                fontFallback: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n              },\n              {\n                _test: 'element2',\n                type: 'text',\n                fontFamily: 'Arial',\n                fontFallback: ['Verdana', 'sans-serif'],\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              font: {\n                service: 'fonts.google.com',\n                family: 'Roboto',\n                fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n              },\n            },\n            {\n              _test: 'element2',\n              type: 'text',\n              font: {\n                service: 'system',\n                family: 'Arial',\n                fallbacks: ['Verdana', 'sans-serif'],\n              },\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0016_isFullbleedDeprecate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport isFullbleedDeprecate from '../v0016_isFullbleedDeprecate';\n\ndescribe('isFullbleedDeprecate', () => {\n  it('should remove isFullbleedBackground', () => {\n    expect(\n      isFullbleedDeprecate({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                isFullbleedBackground: true,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                isFullbleedBackground: false,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                isFullbleedBackground: true,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0017_inlineTextProperties.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport inlineTextProperties from '../v0017_inlineTextProperties';\n\nfunction convert(content, properties) {\n  const converted = inlineTextProperties({\n    pages: [{ elements: [{ type: 'text', content, ...properties }] }],\n  });\n  return converted.pages[0].elements[0].content;\n}\n\ndescribe('inlineTextProperties', () => {\n  describe('should parse all text elements', () => {\n    it('should ignore non-text elements', () => {\n      expect(\n        inlineTextProperties({\n          pages: [\n            {\n              elements: [\n                {\n                  type: 'square',\n                  bold: true,\n                },\n                {\n                  type: 'image',\n                  color: 'red',\n                },\n              ],\n            },\n          ],\n        })\n      ).toStrictEqual({\n        pages: [\n          {\n            elements: [\n              {\n                type: 'square',\n                bold: true,\n              },\n              {\n                type: 'image',\n                color: 'red',\n              },\n            ],\n          },\n        ],\n      });\n    });\n\n    it('should parse multiple text elements on multiple pages', () => {\n      expect(\n        inlineTextProperties({\n          pages: [\n            {\n              elements: [\n                {\n                  type: 'text',\n                  bold: true,\n                  content: 'Hello',\n                },\n                {\n                  type: 'text',\n                  textDecoration: 'underline',\n                  content: 'Hello',\n                },\n              ],\n            },\n            {\n              elements: [\n                {\n                  type: 'text',\n                  fontStyle: 'italic',\n                  content: 'Hello',\n                },\n                {\n                  type: 'text',\n                  fontWeight: 300,\n                  content: 'Hello',\n                },\n              ],\n            },\n          ],\n        })\n      ).toStrictEqual({\n        pages: [\n          {\n            elements: [\n              {\n                type: 'text',\n                content: '<span style=\"font-weight: 700\">Hello</span>',\n              },\n              {\n                type: 'text',\n                content:\n                  '<span style=\"text-decoration: underline\">Hello</span>',\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                type: 'text',\n                content: '<span style=\"font-style: italic\">Hello</span>',\n              },\n              {\n                type: 'text',\n                content: '<span style=\"font-weight: 300\">Hello</span>',\n              },\n            ],\n          },\n        ],\n      });\n    });\n\n    it('should remove all deprecated properties', () => {\n      const res = inlineTextProperties({\n        pages: [\n          {\n            elements: [\n              {\n                type: 'text',\n                bold: true,\n                fontWeight: 300,\n                fontStyle: 'italic',\n                textDecoration: 'underline',\n                letterSpacing: 5,\n                color: { color: { r: 255, g: 0, b: 0 } },\n                content: 'Hello',\n              },\n            ],\n          },\n        ],\n      });\n\n      const convertedElementKeys = res.pages[0].elements[0];\n      expect(convertedElementKeys).toContainKey('content');\n      expect(convertedElementKeys).not.toContainKeys([\n        'bold',\n        'fontWeight',\n        'fontStyle',\n        'textDecoration',\n        'letterSpacing',\n        'color',\n      ]);\n    });\n  });\n\n  it('should convert inline elements', () => {\n    const original = `\n      Lorem\n      <strong>ipsum</strong>\n      <em>dolor</em>\n      <strong>sit</strong>\n      amet,\n      <em>\n        consectetur\n        <u>adipiscing</u>\n        elit\n      </em>.\n    `;\n    const converted = convert(original);\n    const expected = `\n      Lorem\n      <span style=\"font-weight: 700\">ipsum</span>\n      <span style=\"font-style: italic\">dolor</span>\n      <span style=\"font-weight: 700\">sit</span>\n      amet,\n      <span style=\"font-style: italic\">\n        consectetur\n        <span style=\"text-decoration: underline\">adipiscing</span>\n        elit\n      </span>.\n    `;\n    expect(converted).toStrictEqual(expected);\n  });\n\n  it('should convert nested elements', () => {\n    const original = `\n      <strong>Lorem\n      <strong>ipsum</strong></strong>\n      <em><em>dolor</em>\n      <strong>sit</strong></em>\n      amet,\n      <u><em>\n        consectetur\n        <u>adipiscing</u>\n        elit\n      </em></u>.\n    `;\n    const converted = convert(original);\n    const expected = `\n      <span style=\"font-weight: 700\">Lorem\n      <span style=\"font-weight: 700\">ipsum</span></span>\n      <span style=\"font-style: italic\"><span style=\"font-style: italic\">dolor</span>\n      <span style=\"font-weight: 700\">sit</span></span>\n      amet,\n      <span style=\"text-decoration: underline\"><span style=\"font-style: italic\">\n        consectetur\n        <span style=\"text-decoration: underline\">adipiscing</span>\n        elit\n      </span></span>.\n    `;\n    expect(converted).toStrictEqual(expected);\n  });\n  describe('should correctly interpret bold properties', () => {\n    it('should correctly interpret bold property and ignore inline elements', () => {\n      const original = 'Lorem <strong>ipsum</strong>';\n      const properties = { bold: true };\n      const converted = convert(original, properties);\n      const expected = '<span style=\"font-weight: 700\">Lorem ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should correctly interpret font weight property and ignore inline elements', () => {\n      const original = 'Lorem <strong>ipsum</strong>';\n      const properties = { fontWeight: 300 };\n      const converted = convert(original, properties);\n      const expected = '<span style=\"font-weight: 300\">Lorem ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should ignore font weight set to 400', () => {\n      const original = 'Lorem <strong>ipsum</strong>';\n      const properties = { fontWeight: 400 };\n      const converted = convert(original, properties);\n      const expected = 'Lorem <span style=\"font-weight: 700\">ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should use font weight over bold when both set if not 400', () => {\n      const original = 'Lorem <strong>ipsum</strong>';\n      const properties = { fontWeight: 300, bold: true };\n      const converted = convert(original, properties);\n      const expected = '<span style=\"font-weight: 300\">Lorem ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should do nothing globally if font weight is 400 and bold is false', () => {\n      const original = 'Lorem <strong>ipsum</strong>';\n      const properties = { fontWeight: 400, bold: false };\n      const converted = convert(original, properties);\n      const expected = 'Lorem <span style=\"font-weight: 700\">ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n  });\n\n  describe('should correctly interpret italic property', () => {\n    it('should correctly interpret font style property and ignore inline elements', () => {\n      const original = 'Lorem <em>ipsum</em>';\n      const properties = { fontStyle: 'italic' };\n      const converted = convert(original, properties);\n      const expected = '<span style=\"font-style: italic\">Lorem ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should ignore font style set to anything but \"italic\"', () => {\n      const original = 'Lorem <em>ipsum</em>';\n      const properties = { fontStyle: 'oblique' };\n      const converted = convert(original, properties);\n      const expected = 'Lorem <span style=\"font-style: italic\">ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n  });\n\n  describe('should correctly interpret underline property', () => {\n    it('should correctly interpret text decoration property and ignore inline elements', () => {\n      const original = 'Lorem <u>ipsum</u>';\n      const properties = { textDecoration: 'underline' };\n      const converted = convert(original, properties);\n      const expected =\n        '<span style=\"text-decoration: underline\">Lorem ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n\n    it('should ignore text decoration set to anything but \"underline\"', () => {\n      const original = 'Lorem <u>ipsum</u>';\n      const properties = { textDecoration: 'line-through' };\n      const converted = convert(original, properties);\n      const expected =\n        'Lorem <span style=\"text-decoration: underline\">ipsum</span>';\n      expect(converted).toStrictEqual(expected);\n    });\n  });\n\n  it('should correctly inline color property', () => {\n    const original = 'Lorem ipsum';\n    const properties = { color: { color: { r: 255, g: 0, b: 0, a: 0.5 } } };\n    const converted = convert(original, properties);\n    const expected =\n      '<span style=\"color: rgba(255, 0, 0, 0.5)\">Lorem ipsum</span>';\n    expect(converted).toStrictEqual(expected);\n  });\n\n  it('should correctly inline letter spacing property', () => {\n    const original = 'Lorem ipsum';\n    const properties = { letterSpacing: 20 };\n    const converted = convert(original, properties);\n    const expected = '<span style=\"letter-spacing: 0.2em\">Lorem ipsum</span>';\n    expect(converted).toStrictEqual(expected);\n  });\n\n  it('should all work correctly together', () => {\n    const original = `\n      Lorem\n      <strong>ipsum</strong>\n      <em>dolor</em>\n      <strong>sit</strong>\n      amet,\n      <em>consectetur\n        <u>adipiscing</u>\n        elit</em>.\n    `;\n    // Here we have global italic, color and letter spacing, but no global font weight or underline.\n    const properties = {\n      letterSpacing: 20,\n      bold: false,\n      fontWeight: 400,\n      fontStyle: 'italic',\n      color: { color: { r: 255, g: 0, b: 0 } },\n      textDecoration: 'line-through',\n    };\n    const converted = convert(original, properties);\n    const expected = `\n      <span style=\"letter-spacing: 0.2em\">\n        <span style=\"color: rgba(255, 0, 0, 1)\">\n          <span style=\"font-style: italic\">\n            Lorem\n            <span style=\"font-weight: 700\">ipsum</span>\n            dolor\n            <span style=\"font-weight: 700\">sit</span>\n            amet,\n            consectetur\n            <span style=\"text-decoration: underline\">adipiscing</span>\n            elit.\n          </span>\n        </span>\n      </span>\n    `;\n    expect(uniformWhitespace(converted)).toStrictEqual(\n      uniformWhitespace(expected)\n    );\n\n    function uniformWhitespace(str) {\n      return str\n        .replace(/^|$/g, ' ') // insert single space front and back\n        .replace(/></g, '> <') // and insert space between tags\n        .replace(/\\s+/g, ' '); // and then collapse all multi-whitespace to single space\n    }\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0018_defaultBackgroundElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createDefaultBackgroundElement from '../v0018_defaultBackgroundElement';\n\ndescribe('createDefaultBackgroundElement', () => {\n  it('should remove background id', () => {\n    const migrated = createDefaultBackgroundElement({\n      pages: [\n        {\n          backgroundElementId: 'x',\n          elements: [{ id: 'x' }],\n        },\n      ],\n    });\n    const page = migrated.pages[0];\n    expect(page).not.toHaveProperty('backgroundElementId');\n  });\n\n  it('should mark existing background shapes as default background', () => {\n    const migrated = createDefaultBackgroundElement({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'shape',\n              isBackground: true,\n            },\n            {\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n    const page = migrated.pages[0];\n    const bgEl = page.elements[0];\n    expect(bgEl).toStrictEqual({\n      type: 'shape',\n      isBackground: true,\n      isDefaultBackground: true,\n    });\n  });\n\n  it('should add default background element when non-shape is bg', () => {\n    const migrated = createDefaultBackgroundElement({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'image',\n              isBackground: true,\n            },\n            {\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n    const page = migrated.pages[0];\n    expect(page.defaultBackgroundElement).toStrictEqual(\n      expect.objectContaining({\n        type: 'shape',\n        isBackground: true,\n        isDefaultBackground: true,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0019_conicToLinear.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport conicToLinear from '../v0019_conicToLinear';\n\ndescribe('conicToLinear', () => {\n  it('should convert conic to linear', () => {\n    expect(\n      conicToLinear({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                backgroundColor: {\n                  color: { r: 1, g: 1, b: 1 },\n                },\n              },\n              {\n                _test: 'element2',\n                backgroundColor: {\n                  type: 'conic',\n                  stops: [\n                    {\n                      color: { r: 1, g: 1, b: 1 },\n                    },\n                    {\n                      color: { r: 1, g: 1, b: 1 },\n                    },\n                  ],\n                },\n              },\n              {\n                _test: 'element3',\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              backgroundColor: {\n                color: { r: 1, g: 1, b: 1 },\n              },\n            },\n            {\n              _test: 'element2',\n              backgroundColor: {\n                type: 'linear',\n                stops: [\n                  {\n                    color: { r: 1, g: 1, b: 1 },\n                  },\n                  {\n                    color: { r: 1, g: 1, b: 1 },\n                  },\n                ],\n              },\n            },\n            {\n              _test: 'element3',\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0020_isFillDeprecate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport isFillDeprecate from '../v0020_isFillDeprecate';\n\nconst PAGE_WIDTH = 440;\nconst PAGE_HEIGHT = 660;\nconst FULLBLEED_RATIO = 9 / 16;\nconst FULLBLEED_HEIGHT = PAGE_WIDTH / FULLBLEED_RATIO;\nconst DANGER_ZONE_HEIGHT = (FULLBLEED_HEIGHT - PAGE_HEIGHT) / 2;\n\ndescribe('isFillDeprecate', () => {\n  it('should remove isFillBackground', () => {\n    expect(\n      isFillDeprecate({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 123,\n                  height: 234,\n                },\n                x: 12,\n                y: 34,\n                width: 123,\n                height: 345,\n                fontSize: 16,\n                isFill: false,\n              },\n              {\n                _test: 'element2',\n                type: 'shape',\n                x: 12,\n                y: 34,\n                width: 123,\n                height: 345,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 1,\n                  id: 1,\n                  mimeType: 'video/mp4',\n                  width: 123,\n                  height: 345,\n                },\n                x: 12,\n                y: 23,\n                width: 123,\n                height: 345,\n                fontSize: 16,\n                rotationAngle: 5,\n                isFill: true,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 123,\n                height: 234,\n              },\n              x: 12,\n              y: 34,\n              width: 123,\n              height: 345,\n              fontSize: 16,\n            },\n            {\n              _test: 'element2',\n              type: 'shape',\n              x: 12,\n              y: 34,\n              width: 123,\n              height: 345,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 1,\n                id: 1,\n                mimeType: 'video/mp4',\n                width: 123,\n                height: 345,\n              },\n              x: 0,\n              y: -DANGER_ZONE_HEIGHT,\n              width: PAGE_WIDTH,\n              height: PAGE_WIDTH / FULLBLEED_RATIO,\n              fontSize: 16,\n              rotationAngle: 0,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0021_backgroundColorToPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport backgroundColorToPage from '../v0021_backgroundColorToPage';\n\ndescribe('backgroundColorToPage', () => {\n  it('should migrate background element color to page', () => {\n    expect(\n      backgroundColorToPage({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                backgroundColor: {\n                  color: { r: 1, g: 1, b: 1 },\n                },\n                isDefaultBackground: true,\n              },\n              {\n                _test: 'element2',\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                backgroundColor: {\n                  color: { r: 1, g: 1, b: 1 },\n                },\n              },\n            ],\n            defaultBackgroundElement: {\n              _test: 'element4',\n              backgroundColor: {\n                color: { r: 0, g: 0, b: 0 },\n              },\n            },\n          },\n          {\n            _test: 'page3',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              backgroundColor: {\n                color: { r: 1, g: 1, b: 1 },\n              },\n              isDefaultBackground: true,\n            },\n            {\n              _test: 'element2',\n            },\n          ],\n          backgroundColor: {\n            color: { r: 1, g: 1, b: 1 },\n          },\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              backgroundColor: {\n                color: { r: 1, g: 1, b: 1 },\n              },\n            },\n          ],\n          defaultBackgroundElement: {\n            _test: 'element4',\n            backgroundColor: {\n              color: { r: 0, g: 0, b: 0 },\n            },\n          },\n          backgroundColor: {\n            color: { r: 0, g: 0, b: 0 },\n          },\n        },\n        {\n          _test: 'page3',\n          elements: [],\n          backgroundColor: {\n            type: 'solid',\n            color: { r: 255, g: 255, b: 255 },\n          },\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0022_dataPixelTo412.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport dataPixelTo412 from '../v0022_dataPixelTo412';\n\ndescribe('dataPixelTo412', () => {\n  it('should convert all pixel props', () => {\n    expect(\n      dataPixelTo412({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                x: 0,\n                y: 0,\n                width: 440,\n                height: 660,\n              },\n              {\n                _test: 'element2',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                fontSize: 22,\n                padding: { horizontal: 10, vertical: 10 },\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              x: 0,\n              y: 0,\n              width: 412,\n              height: 618,\n            },\n            {\n              _test: 'element2',\n              x: 9,\n              y: 19,\n              width: 94,\n              height: 187,\n              fontSize: 21,\n              padding: { horizontal: 9, vertical: 9 },\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0023_convertOverlayPattern.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport convertOverlayPattern from '../v0023_convertOverlayPattern';\n\ndescribe('convertOverlayPattern', () => {\n  it('should ignore missing overlays, non-media backgrounds and empty pages', () => {\n    expect(\n      convertOverlayPattern({\n        pages: [\n          {\n            elements: [\n              {\n                type: 'image',\n                isBackground: true,\n              },\n            ],\n          },\n          {\n            backgroundOverlay: 'none',\n            elements: [\n              {\n                type: 'image',\n                isBackground: true,\n              },\n            ],\n          },\n          {\n            backgroundOverlay: 'random',\n            elements: [\n              {\n                type: 'image',\n                isBackground: true,\n              },\n            ],\n          },\n          {\n            backgroundOverlay: 'linear',\n            elements: [\n              {\n                type: 'shape',\n                isBackground: true,\n              },\n            ],\n          },\n          {\n            backgroundOverlay: 'linear',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'image',\n              isBackground: true,\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              type: 'image',\n              isBackground: true,\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              type: 'image',\n              isBackground: true,\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              type: 'shape',\n              isBackground: true,\n            },\n          ],\n        },\n        {\n          elements: [],\n        },\n      ],\n    });\n  });\n\n  it('should convert solid overlays', () => {\n    expect(\n      convertOverlayPattern({\n        pages: [\n          {\n            backgroundOverlay: 'solid',\n            elements: [\n              {\n                type: 'video',\n                isBackground: true,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'video',\n              backgroundOverlay: { color: { r: 0, g: 0, b: 0, a: 0.3 } },\n              isBackground: true,\n            },\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should convert linear overlays', () => {\n    expect(\n      convertOverlayPattern({\n        pages: [\n          {\n            backgroundOverlay: 'linear',\n            elements: [\n              {\n                type: 'image',\n                isBackground: true,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'image',\n              backgroundOverlay: {\n                type: 'linear',\n                rotation: 0,\n                stops: [\n                  { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0.4 },\n                  { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n                ],\n                alpha: 0.9,\n              },\n              isBackground: true,\n            },\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should convert radial overlays', () => {\n    expect(\n      convertOverlayPattern({\n        pages: [\n          {\n            backgroundOverlay: 'radial',\n            elements: [\n              {\n                type: 'video',\n                isBackground: true,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              type: 'video',\n              backgroundOverlay: {\n                type: 'radial',\n                size: { w: 0.8, h: 0.5 },\n                stops: [\n                  { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0.25 },\n                  { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n                ],\n                alpha: 0.6,\n              },\n              isBackground: true,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0024_blobsToSingleBlob.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport blobsToSingleBlob from '../v0024_blobsToSingleBlob';\n\ndescribe('blobsToSingleBlob', () => {\n  it('should migrate elements with old blobs to a single blob type', () => {\n    expect(\n      blobsToSingleBlob({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                mask: {\n                  type: 'blob-2',\n                },\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                mask: {\n                  type: 'blob-1',\n                },\n              },\n              {\n                _test: 'element4',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n                mask: {\n                  type: 'blob-7',\n                },\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n              mask: {\n                type: 'blob',\n              },\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n              mask: {\n                type: 'blob',\n              },\n            },\n            {\n              _test: 'element4',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n              mask: {\n                type: 'blob',\n              },\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0025_singleAnimationTarget.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\njest.mock('uuid');\nimport { v4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport singleAnimationTarget from '../v0025_singleAnimationTarget';\n\nconst MOCK_ID = 'newUuid';\n\ndescribe('singleAnimationTarget', () => {\n  beforeAll(() => {\n    v4.mockImplementation(() => MOCK_ID);\n  });\n\n  it('should migrate old animations with multiple targets to separate animations with a single target', () => {\n    expect(\n      singleAnimationTarget({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            animations: [\n              {\n                type: 'bounce',\n                duration: 1000,\n                delay: 200,\n                id: '1',\n                targets: ['a', 'b'],\n              },\n              {\n                type: 'fly-in',\n                duration: 1000,\n                delay: 200,\n                id: '2',\n                targets: ['a', 'b', 'c'],\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            animations: [\n              {\n                type: 'move',\n                duration: 1000,\n                delay: 200,\n                id: '3',\n                targets: ['a'],\n              },\n              {\n                type: 'bounce',\n                duration: 1000,\n                delay: 200,\n                id: '4',\n                targets: ['a', 'b', 'c'],\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          animations: [\n            {\n              type: 'bounce',\n              duration: 1000,\n              delay: 200,\n              id: '1',\n              targets: ['a'],\n            },\n            {\n              type: 'bounce',\n              duration: 1000,\n              delay: 200,\n              id: MOCK_ID,\n              targets: ['b'],\n            },\n            {\n              type: 'fly-in',\n              duration: 1000,\n              delay: 200,\n              id: '2',\n              targets: ['a'],\n            },\n            {\n              type: 'fly-in',\n              duration: 1000,\n              delay: 200,\n              id: MOCK_ID,\n              targets: ['b'],\n            },\n            {\n              type: 'fly-in',\n              duration: 1000,\n              delay: 200,\n              id: MOCK_ID,\n              targets: ['c'],\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          animations: [\n            {\n              type: 'move',\n              duration: 1000,\n              delay: 200,\n              id: '3',\n              targets: ['a'],\n            },\n            {\n              type: 'bounce',\n              duration: 1000,\n              delay: 200,\n              id: '4',\n              targets: ['a'],\n            },\n            {\n              type: 'bounce',\n              duration: 1000,\n              delay: 200,\n              id: MOCK_ID,\n              targets: ['b'],\n            },\n            {\n              type: 'bounce',\n              duration: 1000,\n              delay: 200,\n              id: MOCK_ID,\n              targets: ['c'],\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0026_backgroundOverlayToOverlay.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport backgroundOverlayToOverlay from '../v0026_backgroundOverlayToOverlay';\n\ndescribe('backgroundOverlayToOverlay', () => {\n  it('should replace backgroundOverlay with overlay', () => {\n    expect(\n      backgroundOverlayToOverlay({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 123,\n                  height: 234,\n                },\n                x: 12,\n                y: 34,\n                width: 123,\n                height: 345,\n                fontSize: 16,\n                backgroundOverlay: { r: 1, g: 1, b: 1 },\n              },\n              {\n                _test: 'element2',\n                type: 'shape',\n                x: 12,\n                y: 34,\n                width: 123,\n                height: 345,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 1,\n                  id: 1,\n                  mimeType: 'video/mp4',\n                  width: 123,\n                  height: 345,\n                },\n                backgroundOverlay: { r: 2, g: 2, b: 2 },\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 123,\n                height: 234,\n              },\n              x: 12,\n              y: 34,\n              width: 123,\n              height: 345,\n              fontSize: 16,\n              overlay: { r: 1, g: 1, b: 1 },\n            },\n            {\n              _test: 'element2',\n              type: 'shape',\n              x: 12,\n              y: 34,\n              width: 123,\n              height: 345,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 1,\n                id: 1,\n                mimeType: 'video/mp4',\n                width: 123,\n                height: 345,\n              },\n              overlay: { r: 2, g: 2, b: 2 },\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0027_videoDuration.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport videoDuration from '../v0027_videoDuration';\n\ndescribe('videoDuration', () => {\n  it('should migrate lengthFormatted to length', () => {\n    expect(\n      videoDuration({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  lengthFormatted: '0:32',\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element4',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video1.mp4',\n                  poster: 'https://example.com/image1.png',\n                  posterId: 100003,\n                  id: 102114,\n                  lengthFormatted: '1:32',\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element5',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video2.mp4',\n                  poster: 'https://example.com/image2.png',\n                  posterId: 100006,\n                  id: 102117,\n                  lengthFormatted: '1:01:32',\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                lengthFormatted: '0:32',\n                length: 32,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element4',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video1.mp4',\n                poster: 'https://example.com/image1.png',\n                posterId: 100003,\n                id: 102114,\n                lengthFormatted: '1:32',\n                length: 92,\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element5',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video2.mp4',\n                poster: 'https://example.com/image2.png',\n                posterId: 100006,\n                id: 102117,\n                length: 3692,\n                lengthFormatted: '1:01:32',\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0028_mark3pVideoAsOptimized.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport mark3pVideoAsOptimized from '../v0028_mark3pVideoAsOptimized';\n\ndescribe('mark3pVideoAsOptimized', () => {\n  it('should migrate 3P video to optimized', () => {\n    expect(\n      mark3pVideoAsOptimized({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  lengthFormatted: '0:32',\n                  length: 32,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element4',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video1.mp4',\n                  poster: 'https://example.com/image1.png',\n                  posterId: 100003,\n                  id: 'media/coverr:aSb45qtWTus',\n                  lengthFormatted: '1:32',\n                  length: 92,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element5',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video2.mp4',\n                  poster: 'https://example.com/image2.png',\n                  posterId: 100006,\n                  id: 'media/tenor:5588823039677022824',\n                  lengthFormatted: '1:01:32',\n                  length: 3692,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                lengthFormatted: '0:32',\n                length: 32,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element4',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video1.mp4',\n                poster: 'https://example.com/image1.png',\n                posterId: 100003,\n                id: 'media/coverr:aSb45qtWTus',\n                isOptimized: true,\n                lengthFormatted: '1:32',\n                length: 92,\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element5',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video2.mp4',\n                poster: 'https://example.com/image2.png',\n                posterId: 100006,\n                id: 'media/tenor:5588823039677022824',\n                length: 3692,\n                lengthFormatted: '1:01:32',\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0029_unifyGifResources.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport unifyGifResources from '../v0029_unifyGifResources';\n\ndescribe('unifyGifResources', () => {\n  it('should update GIF resource format', () => {\n    expect(\n      unifyGifResources({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'gif',\n                  mimeType: 'image/gif',\n                  creationDate: '2019-11-13T18:15:52Z',\n                  src: 'https://c.tenor.com/MU7TSJjNtA0AAAAC/flapjack-smile.gif',\n                  width: 498,\n                  height: 361,\n                  alt: 'media/tenor:3553009464796623885',\n                  sizes: {\n                    full: {\n                      file: 'media/tenor:3553009464796623885',\n                      source_url:\n                        'https://c.tenor.com/MU7TSJjNtA0AAAAC/flapjack-smile.gif',\n                      mime_type: 'image/gif',\n                      width: 498,\n                      height: 361,\n                    },\n                    large: {\n                      file: 'media/tenor:3553009464796623885',\n                      source_url:\n                        'https://c.tenor.com/MU7TSJjNtA0AAAAM/flapjack-smile.gif',\n                      mime_type: 'image/gif',\n                      width: 220,\n                      height: 160,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/tenor:3553009464796623885',\n                      source_url:\n                        'https://c.tenor.com/MU7TSJjNtA0AAAAS/flapjack-smile.gif',\n                      mime_type: 'image/gif',\n                      width: 124,\n                      height: 90,\n                    },\n                  },\n                  attribution: {\n                    author: {},\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE9q%2BbGN9PeNDcmeFuRDySDlixmUMmb1Fq55a74d09EwCQk767JW2sZcmUk%2BaLWlD7Mj6xXYkCku9BtqpWuKh%2Buykw%3D%3D',\n                  },\n                  output: {\n                    mimeType: 'video/mp4',\n                    sizes: {\n                      webm: {\n                        full: {\n                          file: 'media/tenor:3553009464796623885',\n                          source_url:\n                            'https://c.tenor.com/MU7TSJjNtA0AAAPs/flapjack-smile.webm',\n                          mime_type: 'image/webm',\n                          width: 640,\n                          height: 464,\n                        },\n                        preview: {\n                          file: 'media/tenor:3553009464796623885',\n                          source_url:\n                            'https://c.tenor.com/MU7TSJjNtA0AAAP4/flapjack-smile.webm',\n                          mime_type: 'image/webm',\n                          width: 150,\n                          height: 108,\n                        },\n                      },\n                      mp4: {\n                        full: {\n                          file: 'media/tenor:3553009464796623885',\n                          source_url:\n                            'https://c.tenor.com/MU7TSJjNtA0AAAPo/flapjack-smile.mp4',\n                          mime_type: 'video/mp4',\n                          width: 640,\n                          height: 464,\n                        },\n                        preview: {\n                          file: 'media/tenor:3553009464796623885',\n                          source_url:\n                            'https://c.tenor.com/MU7TSJjNtA0AAAP2/flapjack-smile.mp4',\n                          mime_type: 'video/mp4',\n                          width: 150,\n                          height: 108,\n                        },\n                      },\n                    },\n                    src: 'https://c.tenor.com/MU7TSJjNtA0AAAPo/flapjack-smile.mp4',\n                    poster:\n                      'https://c.tenor.com/MU7TSJjNtA0AAAAe/flapjack-smile.png',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  baseColor: [175, 182, 142],\n                },\n                type: 'gif',\n                x: 48,\n                y: 0,\n                width: 249,\n                height: 181,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: 'be0e182e-bfed-43d8-9fe6-000eaee7c94f',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                id: 'media/tenor:3553009464796623885',\n                posterId: 'media/tenor:3553009464796623885',\n                type: 'gif',\n                mimeType: 'image/gif',\n                creationDate: '2019-11-13T18:15:52Z',\n                src: 'https://c.tenor.com/MU7TSJjNtA0AAAAC/flapjack-smile.gif',\n                poster:\n                  'https://c.tenor.com/MU7TSJjNtA0AAAAe/flapjack-smile.png',\n                width: 498,\n                height: 361,\n                alt: 'media/tenor:3553009464796623885',\n                sizes: {\n                  full: {\n                    file: 'media/tenor:3553009464796623885',\n                    source_url:\n                      'https://c.tenor.com/MU7TSJjNtA0AAAAC/flapjack-smile.gif',\n                    mime_type: 'image/gif',\n                    width: 498,\n                    height: 361,\n                  },\n                  large: {\n                    file: 'media/tenor:3553009464796623885',\n                    source_url:\n                      'https://c.tenor.com/MU7TSJjNtA0AAAAM/flapjack-smile.gif',\n                    mime_type: 'image/gif',\n                    width: 220,\n                    height: 160,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/tenor:3553009464796623885',\n                    source_url:\n                      'https://c.tenor.com/MU7TSJjNtA0AAAAS/flapjack-smile.gif',\n                    mime_type: 'image/gif',\n                    width: 124,\n                    height: 90,\n                  },\n                },\n                attribution: {\n                  author: {},\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE9q%2BbGN9PeNDcmeFuRDySDlixmUMmb1Fq55a74d09EwCQk767JW2sZcmUk%2BaLWlD7Mj6xXYkCku9BtqpWuKh%2Buykw%3D%3D',\n                },\n                output: {\n                  mimeType: 'video/mp4',\n                  src: 'https://c.tenor.com/MU7TSJjNtA0AAAPo/flapjack-smile.mp4',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                baseColor: [175, 182, 142],\n              },\n              type: 'gif',\n              x: 48,\n              y: 0,\n              width: 249,\n              height: 181,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: 'be0e182e-bfed-43d8-9fe6-000eaee7c94f',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0030_mark3pVideoAsMuted.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport mark3pVideoAsMuted from '../v0030_mark3pVideoAsMuted';\n\ndescribe('mark3pVideoAsMuted', () => {\n  it('should migrate 3P video to optimized', () => {\n    expect(\n      mark3pVideoAsMuted({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  lengthFormatted: '0:32',\n                  length: 32,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element4',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video1.mp4',\n                  poster: 'https://example.com/image1.png',\n                  posterId: 100003,\n                  id: 'media/coverr:aSb45qtWTus',\n                  lengthFormatted: '1:32',\n                  length: 92,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element5',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video2.mp4',\n                  poster: 'https://example.com/image2.png',\n                  posterId: 100006,\n                  id: 'media/tenor:5588823039677022824',\n                  lengthFormatted: '1:01:32',\n                  length: 3692,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                lengthFormatted: '0:32',\n                length: 32,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element4',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video1.mp4',\n                poster: 'https://example.com/image1.png',\n                posterId: 100003,\n                id: 'media/coverr:aSb45qtWTus',\n                isMuted: true,\n                lengthFormatted: '1:32',\n                length: 92,\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element5',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video2.mp4',\n                poster: 'https://example.com/image2.png',\n                posterId: 100006,\n                id: 'media/tenor:5588823039677022824',\n                length: 3692,\n                lengthFormatted: '1:01:32',\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0031_normalizeResourceSizes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport normalizeResourceSizes from '../v0031_normalizeResourceSizes';\n\ndescribe('normalizeResourceSizes', () => {\n  it('should normalize resource sizes', () => {\n    expect(\n      normalizeResourceSizes({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: '265',\n                  height: '527',\n                  sizes: {\n                    size1: {\n                      width: '300',\n                      height: '300',\n                      source_url: 'image-300x300.png',\n                    },\n                    size2: {\n                      width: '600',\n                      height: '600',\n                      source_url: 'image-600x600.png',\n                    },\n                  },\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  lengthFormatted: '0:32',\n                  length: 32,\n                  mimeType: 'video/mp4',\n                  width: '265',\n                  height: '527',\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element4',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video1.mp4',\n                  poster: 'https://example.com/image1.png',\n                  posterId: 100003,\n                  id: 123,\n                  lengthFormatted: '1:32',\n                  length: 92,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element5',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video2.mp4',\n                  poster: 'https://example.com/image2.png',\n                  posterId: 100006,\n                  id: 456,\n                  lengthFormatted: '1:01:32',\n                  length: 3692,\n                  mimeType: 'video/mp4',\n                  width: '365',\n                  height: '627',\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n                sizes: {\n                  size1: {\n                    width: 300,\n                    height: 300,\n                    source_url: 'image-300x300.png',\n                  },\n                  size2: {\n                    width: 600,\n                    height: 600,\n                    source_url: 'image-600x600.png',\n                  },\n                },\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                lengthFormatted: '0:32',\n                length: 32,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element4',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video1.mp4',\n                poster: 'https://example.com/image1.png',\n                posterId: 100003,\n                id: 123,\n                lengthFormatted: '1:32',\n                length: 92,\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element5',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video2.mp4',\n                poster: 'https://example.com/image2.png',\n                posterId: 100006,\n                id: 456,\n                length: 3692,\n                lengthFormatted: '1:01:32',\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0032_pageOutlinkTheme.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport pageOutlinkTheme from '../v0032_pageOutlinkTheme';\n\ndescribe('pageOutlinkTheme', () => {\n  it('should add theme to page outlink', () => {\n    expect(\n      pageOutlinkTheme({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [],\n            pageAttachment: {\n              url: 'https://example.test',\n              ctaText: 'Learn',\n            },\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [],\n          pageAttachment: {\n            url: 'https://example.test',\n            ctaText: 'Learn',\n            theme: 'light',\n          },\n        },\n      ],\n    });\n  });\n\n  it('should not do anything in case of outlink not being set', () => {\n    expect(\n      pageOutlinkTheme({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [],\n        },\n      ],\n    });\n  });\n\n  it('should not override existing page outlink theme', () => {\n    expect(\n      pageOutlinkTheme({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [],\n            pageAttachment: {\n              url: 'https://example.test',\n              ctaText: 'Learn',\n              theme: 'dark',\n            },\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [],\n          pageAttachment: {\n            url: 'https://example.test',\n            ctaText: 'Learn',\n            theme: 'dark',\n          },\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0033_removeTitleFromResource.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport removeTitleFromResources from '../v0033_removeTitleFromResources';\n\ndescribe('removeTitleFromResources', () => {\n  it('should remove title from resource', () => {\n    expect(\n      removeTitleFromResources({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                  title: 'Image 1',\n                  sizes: {\n                    size1: {\n                      width: 300,\n                      height: 300,\n                      source_url: 'image-300x300.png',\n                    },\n                    size2: {\n                      width: 600,\n                      height: 600,\n                      source_url: 'image-600x600.png',\n                    },\n                  },\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                _test: 'element3',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video.mp4',\n                  poster: 'https://example.com/image.png',\n                  posterId: 100002,\n                  id: 102113,\n                  lengthFormatted: '0:32',\n                  length: 32,\n                  mimeType: 'video/mp4',\n                  width: 265,\n                  height: 527,\n                  title: 'Video 1',\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element4',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video1.mp4',\n                  poster: 'https://example.com/image1.png',\n                  posterId: 100003,\n                  id: 123,\n                  lengthFormatted: '1:32',\n                  length: 92,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                  title: 'Video 2',\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n              {\n                _test: 'element5',\n                type: 'video',\n                resource: {\n                  type: 'video',\n                  src: 'https://example.com/video2.mp4',\n                  poster: 'https://example.com/image2.png',\n                  posterId: 100006,\n                  id: 456,\n                  lengthFormatted: '1:01:32',\n                  length: 3692,\n                  mimeType: 'video/mp4',\n                  width: 365,\n                  height: 627,\n                  title: 'Video 3',\n                },\n                x: 129,\n                y: 155,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n                sizes: {\n                  size1: {\n                    width: 300,\n                    height: 300,\n                    source_url: 'image-300x300.png',\n                  },\n                  size2: {\n                    width: 600,\n                    height: 600,\n                    source_url: 'image-600x600.png',\n                  },\n                },\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              _test: 'element3',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/image.png',\n                posterId: 100002,\n                id: 102113,\n                lengthFormatted: '0:32',\n                length: 32,\n                mimeType: 'video/mp4',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element4',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video1.mp4',\n                poster: 'https://example.com/image1.png',\n                posterId: 100003,\n                id: 123,\n                lengthFormatted: '1:32',\n                length: 92,\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n            {\n              _test: 'element5',\n              type: 'video',\n              resource: {\n                type: 'video',\n                src: 'https://example.com/video2.mp4',\n                poster: 'https://example.com/image2.png',\n                posterId: 100006,\n                id: 456,\n                length: 3692,\n                lengthFormatted: '1:01:32',\n                mimeType: 'video/mp4',\n                width: 365,\n                height: 627,\n              },\n              x: 129,\n              y: 155,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0034_removeUnusedBackgroundProps.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport removeUnusedBackgroundProps from '../v0034_removeUnusedBackgroundProps';\n\ndescribe('removeUnusedBackgroundProps', () => {\n  it('should remove overlay from pages', () => {\n    expect(\n      removeUnusedBackgroundProps({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [],\n            overlay: 'solid',\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [],\n        },\n      ],\n    });\n  });\n\n  it('should not do anything in case of overlay not being set', () => {\n    expect(\n      removeUnusedBackgroundProps({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [],\n        },\n      ],\n    });\n  });\n\n  it('should remove backgroundColor from default background but not other elements', () => {\n    expect(\n      removeUnusedBackgroundProps({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                type: 'shape',\n                isDefaultBackground: true,\n                backgroundColor: { r: 255, g: 255, b: 255 },\n              },\n              {\n                type: 'shape',\n                backgroundColor: { r: 0, g: 0, b: 0 },\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              type: 'shape',\n              isDefaultBackground: true,\n            },\n            {\n              type: 'shape',\n              backgroundColor: { r: 0, g: 0, b: 0 },\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0035_markVideoAsExternal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport markVideoAsExternal from '../v0035_markVideoAsExternal';\n\ndescribe('markVideoAsExternal', () => {\n  it('should migrate 3P video to external', () => {\n    expect(\n      markVideoAsExternal({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                backgroundColor: {\n                  color: {\n                    r: 196,\n                    g: 196,\n                    b: 196,\n                  },\n                },\n                x: 1,\n                y: 1,\n                width: 1,\n                height: 1,\n                mask: {\n                  type: 'rectangle',\n                },\n                isBackground: true,\n                isDefaultBackground: true,\n                type: 'shape',\n                id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: [118, 72, 36],\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2021-09-09T15:54:00',\n                  src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                  width: 560,\n                  height: 320,\n                  poster:\n                    'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                  posterId: 4702,\n                  id: 4701,\n                  length: 6,\n                  lengthFormatted: '0:06',\n                  alt: 'small-video',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 280,\n                height: 160,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: [204, 177, 140],\n                  type: 'image',\n                  mimeType: 'image/jpeg',\n                  creationDate: '2021-08-05T19:21:03Z',\n                  src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                  width: 8256,\n                  height: 5504,\n                  id: 'media/unsplash:m_wA8tFR128',\n                  alt: 'media/unsplash:m_wA8tFR128',\n                  sizes: {\n                    full: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 8256,\n                      height: 5504,\n                    },\n                    large: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 6604,\n                      height: 4403,\n                    },\n                    '4953_3302': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 4953,\n                      height: 3302,\n                    },\n                    '3302_2201': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 3302,\n                      height: 2201,\n                    },\n                    '1651_1101': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 1651,\n                      height: 1101,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 340,\n                      height: 227,\n                    },\n                  },\n                  attribution: {\n                    author: {\n                      displayName: 'Hillshire Farm',\n                      url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                    },\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isExternal: true,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 220,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: null,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2018-07-09T22:49:13Z',\n                  src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                  width: 1920,\n                  height: 1080,\n                  poster:\n                    'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                  posterId: 'media/coverr:hWGAKF358u',\n                  id: 'media/coverr:hWGAKF358u',\n                  length: 13,\n                  lengthFormatted: '0:13',\n                  alt: 'media/coverr:hWGAKF358u',\n                  sizes: {\n                    full: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 1920,\n                      height: 1080,\n                    },\n                    preview: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 640,\n                      height: 360,\n                    },\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 185,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: null,\n                  type: 'gif',\n                  mimeType: 'image/gif',\n                  creationDate: '2021-01-24T19:47:19Z',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                  width: 498,\n                  height: 424,\n                  poster:\n                    'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                  posterId: 'media/tenor:11865227026495928048',\n                  id: 'media/tenor:11865227026495928048',\n                  alt: 'media/tenor:11865227026495928048',\n                  sizes: {\n                    full: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 498,\n                      height: 424,\n                    },\n                    large: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 220,\n                      height: 188,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 105,\n                      height: 90,\n                    },\n                  },\n                  attribution: {\n                    author: {},\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                  },\n                  output: {\n                    mimeType: 'video/mp4',\n                    src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: false,\n                },\n                type: 'gif',\n                x: 48,\n                y: 0,\n                width: 249,\n                height: 212,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '953777f0-e959-457c-aef2-c06780cf3478',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/gif',\n                  src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                  width: 320,\n                  height: 180,\n                  alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 160,\n                height: 90,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n                isExternal: true,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              backgroundColor: {\n                color: {\n                  r: 196,\n                  g: 196,\n                  b: 196,\n                },\n              },\n              x: 1,\n              y: 1,\n              width: 1,\n              height: 1,\n              mask: {\n                type: 'rectangle',\n              },\n              isBackground: true,\n              isDefaultBackground: true,\n              type: 'shape',\n              id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: [118, 72, 36],\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2021-09-09T15:54:00',\n                src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                width: 560,\n                height: 320,\n                poster:\n                  'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                posterId: 4702,\n                id: 4701,\n                length: 6,\n                lengthFormatted: '0:06',\n                alt: 'small-video',\n                sizes: {},\n                local: false,\n                isPlaceholder: false,\n                isExternal: false,\n                isOptimized: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 280,\n              height: 160,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: [204, 177, 140],\n                type: 'image',\n                mimeType: 'image/jpeg',\n                creationDate: '2021-08-05T19:21:03Z',\n                src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                width: 8256,\n                height: 5504,\n                id: 'media/unsplash:m_wA8tFR128',\n                alt: 'media/unsplash:m_wA8tFR128',\n                sizes: {\n                  full: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 8256,\n                    height: 5504,\n                  },\n                  large: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 6604,\n                    height: 4403,\n                  },\n                  '4953_3302': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 4953,\n                    height: 3302,\n                  },\n                  '3302_2201': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 3302,\n                    height: 2201,\n                  },\n                  '1651_1101': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 1651,\n                    height: 1101,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 340,\n                    height: 227,\n                  },\n                },\n                attribution: {\n                  author: {\n                    displayName: 'Hillshire Farm',\n                    url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                  },\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: false,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 220,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: null,\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2018-07-09T22:49:13Z',\n                src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                width: 1920,\n                height: 1080,\n                poster:\n                  'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                posterId: 'media/coverr:hWGAKF358u',\n                id: 'media/coverr:hWGAKF358u',\n                length: 13,\n                lengthFormatted: '0:13',\n                alt: 'media/coverr:hWGAKF358u',\n                sizes: {\n                  full: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 1920,\n                    height: 1080,\n                  },\n                  preview: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 640,\n                    height: 360,\n                  },\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 185,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: null,\n                type: 'gif',\n                mimeType: 'image/gif',\n                creationDate: '2021-01-24T19:47:19Z',\n                src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                width: 498,\n                height: 424,\n                poster:\n                  'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                posterId: 'media/tenor:11865227026495928048',\n                id: 'media/tenor:11865227026495928048',\n                alt: 'media/tenor:11865227026495928048',\n                sizes: {\n                  full: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 498,\n                    height: 424,\n                  },\n                  large: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 220,\n                    height: 188,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 105,\n                    height: 90,\n                  },\n                },\n                attribution: {\n                  author: {},\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                },\n                output: {\n                  mimeType: 'video/mp4',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'gif',\n              x: 48,\n              y: 0,\n              width: 249,\n              height: 212,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '953777f0-e959-457c-aef2-c06780cf3478',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'image',\n                mimeType: 'image/gif',\n                src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                width: 320,\n                height: 180,\n                alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                sizes: {},\n                local: false,\n                isExternal: true,\n                isPlaceholder: false,\n                isOptimized: false,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 160,\n              height: 90,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0036_changeBaseColorToHex.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport changeBaseColorToHex from '../v0036_changeBaseColorToHex';\n\ndescribe('changeBaseColorToHex', () => {\n  it('should base color to hex', () => {\n    expect(\n      changeBaseColorToHex({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  isExternal: true,\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                backgroundColor: {\n                  color: {\n                    r: 196,\n                    g: 196,\n                    b: 196,\n                  },\n                },\n                x: 1,\n                y: 1,\n                width: 1,\n                height: 1,\n                mask: {\n                  type: 'rectangle',\n                },\n                isBackground: true,\n                isDefaultBackground: true,\n                type: 'shape',\n                id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: [118, 72, 36],\n                  isExternal: false,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2021-09-09T15:54:00',\n                  src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                  width: 560,\n                  height: 320,\n                  poster:\n                    'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                  posterId: 4702,\n                  id: 4701,\n                  length: 6,\n                  lengthFormatted: '0:06',\n                  alt: 'small-video',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 280,\n                height: 160,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: [118, 72, 36],\n                  type: 'image',\n                  mimeType: 'image/jpeg',\n                  creationDate: '2021-08-05T19:21:03Z',\n                  src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                  width: 8256,\n                  height: 5504,\n                  id: 'media/unsplash:m_wA8tFR128',\n                  alt: 'media/unsplash:m_wA8tFR128',\n                  sizes: {\n                    full: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 8256,\n                      height: 5504,\n                    },\n                    large: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 6604,\n                      height: 4403,\n                    },\n                    '4953_3302': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 4953,\n                      height: 3302,\n                    },\n                    '3302_2201': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 3302,\n                      height: 2201,\n                    },\n                    '1651_1101': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 1651,\n                      height: 1101,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 340,\n                      height: 227,\n                    },\n                  },\n                  attribution: {\n                    author: {\n                      displayName: 'Hillshire Farm',\n                      url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                    },\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isExternal: true,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 220,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: undefined,\n                  isExternal: true,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2018-07-09T22:49:13Z',\n                  src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                  width: 1920,\n                  height: 1080,\n                  poster:\n                    'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                  posterId: 'media/coverr:hWGAKF358u',\n                  id: 'media/coverr:hWGAKF358u',\n                  length: 13,\n                  lengthFormatted: '0:13',\n                  alt: 'media/coverr:hWGAKF358u',\n                  sizes: {\n                    full: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 1920,\n                      height: 1080,\n                    },\n                    preview: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 640,\n                      height: 360,\n                    },\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 185,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: undefined,\n                  type: 'gif',\n                  mimeType: 'image/gif',\n                  isExternal: true,\n                  creationDate: '2021-01-24T19:47:19Z',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                  width: 498,\n                  height: 424,\n                  poster:\n                    'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                  posterId: 'media/tenor:11865227026495928048',\n                  id: 'media/tenor:11865227026495928048',\n                  alt: 'media/tenor:11865227026495928048',\n                  sizes: {\n                    full: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 498,\n                      height: 424,\n                    },\n                    large: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 220,\n                      height: 188,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 105,\n                      height: 90,\n                    },\n                  },\n                  attribution: {\n                    author: {},\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                  },\n                  output: {\n                    mimeType: 'video/mp4',\n                    src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: false,\n                },\n                type: 'gif',\n                x: 48,\n                y: 0,\n                width: 249,\n                height: 212,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '953777f0-e959-457c-aef2-c06780cf3478',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/gif',\n                  isExternal: true,\n                  src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                  width: 320,\n                  height: 180,\n                  alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 160,\n                height: 90,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                isExternal: true,\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              backgroundColor: {\n                color: {\n                  r: 196,\n                  g: 196,\n                  b: 196,\n                },\n              },\n              x: 1,\n              y: 1,\n              width: 1,\n              height: 1,\n              mask: {\n                type: 'rectangle',\n              },\n              isBackground: true,\n              isDefaultBackground: true,\n              type: 'shape',\n              id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: '#764824',\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2021-09-09T15:54:00',\n                src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                width: 560,\n                height: 320,\n                poster:\n                  'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                posterId: 4702,\n                id: 4701,\n                length: 6,\n                lengthFormatted: '0:06',\n                alt: 'small-video',\n                sizes: {},\n                local: false,\n                isPlaceholder: false,\n                isExternal: false,\n                isOptimized: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 280,\n              height: 160,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: '#764824',\n                type: 'image',\n                mimeType: 'image/jpeg',\n                creationDate: '2021-08-05T19:21:03Z',\n                src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                width: 8256,\n                height: 5504,\n                id: 'media/unsplash:m_wA8tFR128',\n                alt: 'media/unsplash:m_wA8tFR128',\n                sizes: {\n                  full: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 8256,\n                    height: 5504,\n                  },\n                  large: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 6604,\n                    height: 4403,\n                  },\n                  '4953_3302': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 4953,\n                    height: 3302,\n                  },\n                  '3302_2201': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 3302,\n                    height: 2201,\n                  },\n                  '1651_1101': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 1651,\n                    height: 1101,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 340,\n                    height: 227,\n                  },\n                },\n                attribution: {\n                  author: {\n                    displayName: 'Hillshire Farm',\n                    url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                  },\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: false,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 220,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: undefined,\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2018-07-09T22:49:13Z',\n                src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                width: 1920,\n                height: 1080,\n                poster:\n                  'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                posterId: 'media/coverr:hWGAKF358u',\n                id: 'media/coverr:hWGAKF358u',\n                length: 13,\n                lengthFormatted: '0:13',\n                alt: 'media/coverr:hWGAKF358u',\n                sizes: {\n                  full: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 1920,\n                    height: 1080,\n                  },\n                  preview: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 640,\n                    height: 360,\n                  },\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 185,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: undefined,\n                type: 'gif',\n                mimeType: 'image/gif',\n                creationDate: '2021-01-24T19:47:19Z',\n                src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                width: 498,\n                height: 424,\n                poster:\n                  'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                posterId: 'media/tenor:11865227026495928048',\n                id: 'media/tenor:11865227026495928048',\n                alt: 'media/tenor:11865227026495928048',\n                sizes: {\n                  full: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 498,\n                    height: 424,\n                  },\n                  large: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 220,\n                    height: 188,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 105,\n                    height: 90,\n                  },\n                },\n                attribution: {\n                  author: {},\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                },\n                output: {\n                  mimeType: 'video/mp4',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'gif',\n              x: 48,\n              y: 0,\n              width: 249,\n              height: 212,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '953777f0-e959-457c-aef2-c06780cf3478',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'image',\n                mimeType: 'image/gif',\n                src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                width: 320,\n                height: 180,\n                alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                sizes: {},\n                local: false,\n                isExternal: true,\n                isPlaceholder: false,\n                isOptimized: false,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 160,\n              height: 90,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0038_camelCaseResourceSizes.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport camelCaseResourceSizes from '../v0038_camelCaseResourceSizes';\n\ndescribe('camelCaseResourceSizes', () => {\n  it('should migrate resource sizes to camel case', () => {\n    expect(\n      camelCaseResourceSizes({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  isExternal: true,\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                backgroundColor: {\n                  color: {\n                    r: 196,\n                    g: 196,\n                    b: 196,\n                  },\n                },\n                x: 1,\n                y: 1,\n                width: 1,\n                height: 1,\n                mask: {\n                  type: 'rectangle',\n                },\n                isBackground: true,\n                isDefaultBackground: true,\n                type: 'shape',\n                id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: '#764824',\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2021-09-09T15:54:00',\n                  src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                  width: 560,\n                  height: 320,\n                  poster:\n                    'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                  posterId: 4702,\n                  id: 4701,\n                  length: 6,\n                  lengthFormatted: '0:06',\n                  alt: 'small-video',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isExternal: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 280,\n                height: 160,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: '#764824',\n                  type: 'image',\n                  mimeType: 'image/jpeg',\n                  creationDate: '2021-08-05T19:21:03Z',\n                  src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                  width: 8256,\n                  height: 5504,\n                  id: 'media/unsplash:m_wA8tFR128',\n                  alt: 'media/unsplash:m_wA8tFR128',\n                  sizes: {\n                    full: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 8256,\n                      height: 5504,\n                    },\n                    large: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 6604,\n                      height: 4403,\n                    },\n                    '4953_3302': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 4953,\n                      height: 3302,\n                    },\n                    '3302_2201': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 3302,\n                      height: 2201,\n                    },\n                    '1651_1101': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 1651,\n                      height: 1101,\n                    },\n                    'web-stories-thumbnail': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 340,\n                      height: 227,\n                    },\n                  },\n                  attribution: {\n                    author: {\n                      displayName: 'Hillshire Farm',\n                      url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                    },\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isExternal: true,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 220,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: undefined,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2018-07-09T22:49:13Z',\n                  src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                  width: 1920,\n                  height: 1080,\n                  poster:\n                    'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                  posterId: 'media/coverr:hWGAKF358u',\n                  id: 'media/coverr:hWGAKF358u',\n                  length: 13,\n                  lengthFormatted: '0:13',\n                  alt: 'media/coverr:hWGAKF358u',\n                  sizes: {\n                    full: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 1920,\n                      height: 1080,\n                    },\n                    preview: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 640,\n                      height: 360,\n                    },\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isExternal: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 185,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  baseColor: undefined,\n                  type: 'gif',\n                  mimeType: 'image/gif',\n                  creationDate: '2021-01-24T19:47:19Z',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                  width: 498,\n                  height: 424,\n                  poster:\n                    'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                  posterId: 'media/tenor:11865227026495928048',\n                  id: 'media/tenor:11865227026495928048',\n                  alt: 'media/tenor:11865227026495928048',\n                  sizes: {\n                    full: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 498,\n                      height: 424,\n                    },\n                    large: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 220,\n                      height: 188,\n                    },\n                    'web-stories-thumbnail': {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 105,\n                      height: 90,\n                    },\n                  },\n                  attribution: {\n                    author: {},\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                  },\n                  output: {\n                    mimeType: 'video/mp4',\n                    src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isExternal: true,\n                  isMuted: false,\n                },\n                type: 'gif',\n                x: 48,\n                y: 0,\n                width: 249,\n                height: 212,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '953777f0-e959-457c-aef2-c06780cf3478',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/gif',\n                  src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                  width: 320,\n                  height: 180,\n                  alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                  sizes: {},\n                  local: false,\n                  isExternal: true,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 160,\n                height: 90,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                isExternal: true,\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              backgroundColor: {\n                color: {\n                  r: 196,\n                  g: 196,\n                  b: 196,\n                },\n              },\n              x: 1,\n              y: 1,\n              width: 1,\n              height: 1,\n              mask: {\n                type: 'rectangle',\n              },\n              isBackground: true,\n              isDefaultBackground: true,\n              type: 'shape',\n              id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: '#764824',\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2021-09-09T15:54:00',\n                src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                width: 560,\n                height: 320,\n                poster:\n                  'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                posterId: 4702,\n                id: 4701,\n                length: 6,\n                lengthFormatted: '0:06',\n                alt: 'small-video',\n                sizes: {},\n                local: false,\n                isPlaceholder: false,\n                isExternal: false,\n                isOptimized: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 280,\n              height: 160,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: '#764824',\n                type: 'image',\n                mimeType: 'image/jpeg',\n                creationDate: '2021-08-05T19:21:03Z',\n                src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                width: 8256,\n                height: 5504,\n                id: 'media/unsplash:m_wA8tFR128',\n                alt: 'media/unsplash:m_wA8tFR128',\n                sizes: {\n                  full: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 8256,\n                    height: 5504,\n                  },\n                  large: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 6604,\n                    height: 4403,\n                  },\n                  '4953_3302': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 4953,\n                    height: 3302,\n                  },\n                  '3302_2201': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 3302,\n                    height: 2201,\n                  },\n                  '1651_1101': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 1651,\n                    height: 1101,\n                  },\n                  'web-stories-thumbnail': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    sourceUrl:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                    mimeType: 'image/jpeg',\n                    width: 340,\n                    height: 227,\n                  },\n                },\n                attribution: {\n                  author: {\n                    displayName: 'Hillshire Farm',\n                    url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                  },\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: false,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 220,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: undefined,\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2018-07-09T22:49:13Z',\n                src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                width: 1920,\n                height: 1080,\n                poster:\n                  'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                posterId: 'media/coverr:hWGAKF358u',\n                id: 'media/coverr:hWGAKF358u',\n                length: 13,\n                lengthFormatted: '0:13',\n                alt: 'media/coverr:hWGAKF358u',\n                sizes: {\n                  full: {\n                    file: 'media/coverr:hWGAKF358u',\n                    sourceUrl:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mimeType: 'video/mp4',\n                    width: 1920,\n                    height: 1080,\n                  },\n                  preview: {\n                    file: 'media/coverr:hWGAKF358u',\n                    sourceUrl:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mimeType: 'video/mp4',\n                    width: 640,\n                    height: 360,\n                  },\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 185,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                baseColor: undefined,\n                type: 'gif',\n                mimeType: 'image/gif',\n                creationDate: '2021-01-24T19:47:19Z',\n                src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                width: 498,\n                height: 424,\n                poster:\n                  'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                posterId: 'media/tenor:11865227026495928048',\n                id: 'media/tenor:11865227026495928048',\n                alt: 'media/tenor:11865227026495928048',\n                sizes: {\n                  full: {\n                    file: 'media/tenor:11865227026495928048',\n                    sourceUrl:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                    mimeType: 'image/gif',\n                    width: 498,\n                    height: 424,\n                  },\n                  large: {\n                    file: 'media/tenor:11865227026495928048',\n                    sourceUrl:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                    mimeType: 'image/gif',\n                    width: 220,\n                    height: 188,\n                  },\n                  'web-stories-thumbnail': {\n                    file: 'media/tenor:11865227026495928048',\n                    sourceUrl:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                    mimeType: 'image/gif',\n                    width: 105,\n                    height: 90,\n                  },\n                },\n                attribution: {\n                  author: {},\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                },\n                output: {\n                  mimeType: 'video/mp4',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                },\n                local: false,\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'gif',\n              x: 48,\n              y: 0,\n              width: 249,\n              height: 212,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '953777f0-e959-457c-aef2-c06780cf3478',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'image',\n                mimeType: 'image/gif',\n                src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                width: 320,\n                height: 180,\n                alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                sizes: {},\n                local: false,\n                isExternal: true,\n                isPlaceholder: false,\n                isOptimized: false,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 160,\n              height: 90,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0038_removeTransientMediaProperties.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeTransientMediaProperties from '../v0037_removeTransientMediaProperties';\n\ndescribe('removeTransientMediaProperties', () => {\n  it('should remove properties', () => {\n    expect(\n      removeTransientMediaProperties({\n        _test: 'story',\n        pages: [\n          {\n            _test: 'page1',\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n              {\n                _test: 'element2',\n                type: 'image',\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/png',\n                  isExternal: true,\n                  local: false,\n                  isTrimming: false,\n                  isTranscoding: false,\n                  isMuting: false,\n                  src: 'https://example.com/image.png',\n                  width: 265,\n                  height: 527,\n                },\n                x: 29,\n                y: 55,\n                width: 265,\n                height: 527,\n                fontSize: 58,\n              },\n            ],\n          },\n          {\n            _test: 'page2',\n            elements: [\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                backgroundColor: {\n                  color: {\n                    r: 196,\n                    g: 196,\n                    b: 196,\n                  },\n                },\n                x: 1,\n                y: 1,\n                width: 1,\n                height: 1,\n                mask: {\n                  type: 'rectangle',\n                },\n                isBackground: true,\n                isDefaultBackground: true,\n                type: 'shape',\n                id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  isExternal: false,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2021-09-09T15:54:00',\n                  src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                  width: 560,\n                  height: 320,\n                  poster:\n                    'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                  posterId: 4702,\n                  id: 4701,\n                  length: 6,\n                  lengthFormatted: '0:06',\n                  alt: 'small-video',\n                  sizes: {},\n                  local: false,\n                  isTrimming: false,\n                  isMuting: false,\n                  isTranscoding: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 280,\n                height: 160,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/jpeg',\n                  creationDate: '2021-08-05T19:21:03Z',\n                  src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                  width: 8256,\n                  height: 5504,\n                  id: 'media/unsplash:m_wA8tFR128',\n                  alt: 'media/unsplash:m_wA8tFR128',\n                  sizes: {\n                    full: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 8256,\n                      height: 5504,\n                    },\n                    large: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 6604,\n                      height: 4403,\n                    },\n                    '4953_3302': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 4953,\n                      height: 3302,\n                    },\n                    '3302_2201': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 3302,\n                      height: 2201,\n                    },\n                    '1651_1101': {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 1651,\n                      height: 1101,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/unsplash:m_wA8tFR128',\n                      source_url:\n                        'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                      mime_type: 'image/jpeg',\n                      width: 340,\n                      height: 227,\n                    },\n                  },\n                  attribution: {\n                    author: {\n                      displayName: 'Hillshire Farm',\n                      url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                    },\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isExternal: true,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 220,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  isExternal: true,\n                  type: 'video',\n                  mimeType: 'video/mp4',\n                  creationDate: '2018-07-09T22:49:13Z',\n                  src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                  width: 1920,\n                  height: 1080,\n                  poster:\n                    'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                  posterId: 'media/coverr:hWGAKF358u',\n                  id: 'media/coverr:hWGAKF358u',\n                  length: 13,\n                  lengthFormatted: '0:13',\n                  alt: 'media/coverr:hWGAKF358u',\n                  sizes: {\n                    full: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 1920,\n                      height: 1080,\n                    },\n                    preview: {\n                      file: 'media/coverr:hWGAKF358u',\n                      source_url:\n                        'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                      mime_type: 'video/mp4',\n                      width: 640,\n                      height: 360,\n                    },\n                  },\n                  local: false,\n                  isTrimming: true,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuted: true,\n                },\n                controls: false,\n                loop: false,\n                autoPlay: true,\n                tracks: [],\n                type: 'video',\n                x: 48,\n                y: 0,\n                width: 330,\n                height: 185,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'gif',\n                  mimeType: 'image/gif',\n                  isExternal: true,\n                  creationDate: '2021-01-24T19:47:19Z',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                  width: 498,\n                  height: 424,\n                  poster:\n                    'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                  posterId: 'media/tenor:11865227026495928048',\n                  id: 'media/tenor:11865227026495928048',\n                  alt: 'media/tenor:11865227026495928048',\n                  sizes: {\n                    full: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 498,\n                      height: 424,\n                    },\n                    large: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 220,\n                      height: 188,\n                    },\n                    web_stories_thumbnail: {\n                      file: 'media/tenor:11865227026495928048',\n                      source_url:\n                        'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                      mime_type: 'image/gif',\n                      width: 105,\n                      height: 90,\n                    },\n                  },\n                  attribution: {\n                    author: {},\n                    registerUsageUrl:\n                      'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                  },\n                  output: {\n                    mimeType: 'video/mp4',\n                    src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                  },\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: true,\n                  isMuting: false,\n                  isMuted: false,\n                },\n                type: 'gif',\n                x: 48,\n                y: 0,\n                width: 249,\n                height: 212,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '953777f0-e959-457c-aef2-c06780cf3478',\n              },\n              {\n                opacity: 100,\n                flip: {\n                  vertical: false,\n                  horizontal: false,\n                },\n                rotationAngle: 0,\n                lockAspectRatio: true,\n                scale: 100,\n                focalX: 50,\n                focalY: 50,\n                resource: {\n                  type: 'image',\n                  mimeType: 'image/gif',\n                  isExternal: true,\n                  src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                  width: 320,\n                  height: 180,\n                  alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                  sizes: {},\n                  local: false,\n                  isPlaceholder: false,\n                  isOptimized: false,\n                  isTrimming: false,\n                  isMuted: false,\n                },\n                type: 'image',\n                x: 48,\n                y: 0,\n                width: 160,\n                height: 90,\n                mask: {\n                  type: 'rectangle',\n                  showInLibrary: true,\n                  name: 'Rectangle',\n                  path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                  ratio: 1,\n                  supportsBorder: true,\n                },\n                id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [\n        {\n          _test: 'page1',\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n            {\n              _test: 'element2',\n              type: 'image',\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                isExternal: true,\n                src: 'https://example.com/image.png',\n                width: 265,\n                height: 527,\n              },\n              x: 29,\n              y: 55,\n              width: 265,\n              height: 527,\n              fontSize: 58,\n            },\n          ],\n        },\n        {\n          _test: 'page2',\n          elements: [\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              backgroundColor: {\n                color: {\n                  r: 196,\n                  g: 196,\n                  b: 196,\n                },\n              },\n              x: 1,\n              y: 1,\n              width: 1,\n              height: 1,\n              mask: {\n                type: 'rectangle',\n              },\n              isBackground: true,\n              isDefaultBackground: true,\n              type: 'shape',\n              id: '2b0da9d0-8a79-4cba-8ab2-572f1ea6f011',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2021-09-09T15:54:00',\n                src: 'http://localhost:8899/wp-content/uploads/2021/09/small-video-muted-2.mp4',\n                width: 560,\n                height: 320,\n                poster:\n                  'http://localhost:8899/wp-content/uploads/2021/09/small-video-poster-4.jpeg',\n                posterId: 4702,\n                id: 4701,\n                length: 6,\n                lengthFormatted: '0:06',\n                alt: 'small-video',\n                sizes: {},\n                isPlaceholder: false,\n                isExternal: false,\n                isOptimized: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 280,\n              height: 160,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: 'c0fcdb12-1c21-4e0b-ae21-3b8d5bc20e26',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'image',\n                mimeType: 'image/jpeg',\n                creationDate: '2021-08-05T19:21:03Z',\n                src: 'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                width: 8256,\n                height: 5504,\n                id: 'media/unsplash:m_wA8tFR128',\n                alt: 'media/unsplash:m_wA8tFR128',\n                sizes: {\n                  full: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=8256&h=5504&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 8256,\n                    height: 5504,\n                  },\n                  large: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=6604&h=4403&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 6604,\n                    height: 4403,\n                  },\n                  '4953_3302': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=4953&h=3302&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 4953,\n                    height: 3302,\n                  },\n                  '3302_2201': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=3302&h=2201&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 3302,\n                    height: 2201,\n                  },\n                  '1651_1101': {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=1651&h=1101&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 1651,\n                    height: 1101,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/unsplash:m_wA8tFR128',\n                    source_url:\n                      'https://images.unsplash.com/photo-1628191139344-11bec156abdc?ixid=MnwxMzcxOTN8MXwxfGFsbHwxfHx8fHx8Mnx8MTYzMTU1MjQ1NA&ixlib=rb-1.2.1&fm=jpg&w=340&h=227&fit=max',\n                    mime_type: 'image/jpeg',\n                    width: 340,\n                    height: 227,\n                  },\n                },\n                attribution: {\n                  author: {\n                    displayName: 'Hillshire Farm',\n                    url: 'https://unsplash.com/@hillshirefarm?utm_source=web_stories_wordpress&utm_medium=referral',\n                  },\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE86lG6LiDVvZYIEXmajZcQampNUuhLYiVO7gOdLIWi0rS%2BBe2gThAEF7QaCtIfENe3HW8yRrf3LucXQw7NdUKx9Bxbj84xgVgJDaGmroSMxeWRIl9RP/P/PXuV4LVYeuQo4lchY6YL9kUoYcOQYjJEFBPDoLmABiHF6KzPR6mMHH%2BIxQCoC%2Bsgf8QTIZJjlEIOwGvoOIzg65ELpYa4J',\n                },\n                isPlaceholder: false,\n                isOptimized: false,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 220,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '25e5b3aa-9483-4ee5-aa61-56512f31e01d',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                creationDate: '2018-07-09T22:49:13Z',\n                src: 'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                width: 1920,\n                height: 1080,\n                poster:\n                  'https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk',\n                posterId: 'media/coverr:hWGAKF358u',\n                id: 'media/coverr:hWGAKF358u',\n                length: 13,\n                lengthFormatted: '0:13',\n                alt: 'media/coverr:hWGAKF358u',\n                sizes: {\n                  full: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 1920,\n                    height: 1080,\n                  },\n                  preview: {\n                    file: 'media/coverr:hWGAKF358u',\n                    source_url:\n                      'https://storage.coverr.co/videos/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyNjFDMkM5QUYxNEY5NkJDRTc2IiwiaWF0IjoxNjMxNTUyODc4fQ.o-jt3gxwUqyHRlrLYNQEP9bMdw2oUyBDsqIfPqHU6SE',\n                    mime_type: 'video/mp4',\n                    width: 640,\n                    height: 360,\n                  },\n                },\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: true,\n              },\n              controls: false,\n              loop: false,\n              autoPlay: true,\n              tracks: [],\n              type: 'video',\n              x: 48,\n              y: 0,\n              width: 330,\n              height: 185,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '6684f5ad-836c-4b2f-99af-e7029ae9a23a',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'gif',\n                mimeType: 'image/gif',\n                creationDate: '2021-01-24T19:47:19Z',\n                src: 'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                width: 498,\n                height: 424,\n                poster:\n                  'https://c.tenor.com/pKnBHa2ndvAAAAAe/blackpink-jisoo.png',\n                posterId: 'media/tenor:11865227026495928048',\n                id: 'media/tenor:11865227026495928048',\n                alt: 'media/tenor:11865227026495928048',\n                sizes: {\n                  full: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAC/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 498,\n                    height: 424,\n                  },\n                  large: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAM/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 220,\n                    height: 188,\n                  },\n                  web_stories_thumbnail: {\n                    file: 'media/tenor:11865227026495928048',\n                    source_url:\n                      'https://c.tenor.com/pKnBHa2ndvAAAAAS/blackpink-jisoo.gif',\n                    mime_type: 'image/gif',\n                    width: 105,\n                    height: 90,\n                  },\n                },\n                attribution: {\n                  author: {},\n                  registerUsageUrl:\n                    'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE8I8BnSU6u4O5s/C6Ga8oW0K5NV4xcgWjKL07xCVPgk9HWpdiEqj1yxvu5yHljtmnjnFro2XYFva9HVZT%2BJMYLscTw%3D',\n                },\n                output: {\n                  mimeType: 'video/mp4',\n                  src: 'https://c.tenor.com/pKnBHa2ndvAAAAPo/blackpink-jisoo.mp4',\n                },\n                isPlaceholder: false,\n                isOptimized: true,\n                isExternal: true,\n                isMuted: false,\n              },\n              type: 'gif',\n              x: 48,\n              y: 0,\n              width: 249,\n              height: 212,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '953777f0-e959-457c-aef2-c06780cf3478',\n            },\n            {\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              resource: {\n                type: 'image',\n                mimeType: 'image/gif',\n                src: 'https://media4.giphy.com/media/zOvBKUUEERdNm/giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy.gif&ct=g',\n                width: 320,\n                height: 180,\n                alt: 'giphy.gif?cid=ecf05e478ffb4156f631b7c278fad987f328fe33f2fdd3d1&rid=giphy',\n                sizes: {},\n                isExternal: true,\n                isPlaceholder: false,\n                isOptimized: false,\n                isMuted: false,\n              },\n              type: 'image',\n              x: 48,\n              y: 0,\n              width: 160,\n              height: 90,\n              mask: {\n                type: 'rectangle',\n                showInLibrary: true,\n                name: 'Rectangle',\n                path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n                ratio: 1,\n                supportsBorder: true,\n              },\n              id: '1581fcfc-2c39-4fc2-bb3b-2685edf5e3fa',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0039_backgroundAudioFormatting.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport backgroundAudioFormatting from '../v0039_backgroundAudioFormatting';\n\ndescribe('backgroundAudioFormatting', () => {\n  it('should move properties', () => {\n    expect(\n      backgroundAudioFormatting({\n        backgroundAudio: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        pages: [\n          {\n            backgroundAudio: {\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n            },\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n      },\n      pages: [\n        {\n          backgroundAudio: {\n            loop: true,\n            resource: {\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n            },\n            tracks: [],\n          },\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0040_andadaFontToAndadaPro.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport andadaFontToAndadaPro from '../v0040_andadaFontToAndadaPro';\n\ndescribe('andadaFontToAndadaPro', () => {\n  it('should migrate to Andada Pro font', () => {\n    expect(\n      andadaFontToAndadaPro({\n        pages: [\n          {\n            elements: [\n              {\n                _test: 'element1',\n                type: 'text',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                font: {\n                  family: 'Andada',\n                  fallbacks: ['serif'],\n                  weights: [400, 500, 600],\n                  styles: ['regular'],\n                  variants: [\n                    [0, 400],\n                    [0, 500],\n                    [0, 600],\n                    [0, 700],\n                    [0, 800],\n                  ],\n                  service: 'fonts.google.com',\n                },\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n              font: {\n                family: 'Andada Pro',\n                fallbacks: ['serif'],\n                weights: [400, 500, 600, 700, 800],\n                styles: ['regular', 'italic'],\n                variants: [\n                  [0, 400],\n                  [0, 500],\n                  [0, 600],\n                  [0, 700],\n                  [0, 800],\n                  [1, 400],\n                  [1, 500],\n                  [1, 600],\n                  [1, 700],\n                  [1, 800],\n                ],\n                service: 'fonts.google.com',\n                metrics: {\n                  upm: 1000,\n                  asc: 942,\n                  des: -235,\n                  tAsc: 942,\n                  tDes: -235,\n                  tLGap: 0,\n                  wAsc: 1100,\n                  wDes: 390,\n                  xH: 494,\n                  capH: 705,\n                  yMin: -382,\n                  yMax: 1068,\n                  hAsc: 942,\n                  hDes: -235,\n                  lGap: 0,\n                },\n              },\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0041_removeFontProperties.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeFontProperties from '../v0041_removeFontProperties';\n\ndescribe('removeFontProperties', () => {\n  it('should migrate to Andada Pro font', () => {\n    expect(\n      removeFontProperties({\n        pages: [\n          {\n            elements: [\n              {\n                _test: 'element1',\n                type: 'text',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n                font: {\n                  family: 'Andada',\n                  name: 'Andada',\n                  id: 'Andada',\n                  value: 'Andada',\n                  fallbacks: ['serif'],\n                  weights: [400, 500, 600],\n                  styles: ['regular'],\n                  variants: [\n                    [0, 400],\n                    [0, 500],\n                    [0, 600],\n                    [0, 700],\n                    [0, 800],\n                  ],\n                  service: 'fonts.google.com',\n                },\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                _test: 'element1',\n                type: 'square',\n                x: 10,\n                y: 20,\n                width: 100,\n                height: 200,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              _test: 'element1',\n              type: 'text',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n              font: {\n                family: 'Andada',\n                fallbacks: ['serif'],\n                weights: [400, 500, 600],\n                styles: ['regular'],\n                variants: [\n                  [0, 400],\n                  [0, 500],\n                  [0, 600],\n                  [0, 700],\n                  [0, 800],\n                ],\n                service: 'fonts.google.com',\n              },\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              _test: 'element1',\n              type: 'square',\n              x: 10,\n              y: 20,\n              width: 100,\n              height: 200,\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0042_removeTrackName.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeTrackName from '../v0042_removeTrackName';\n\ndescribe('removeTrackName', () => {\n  it('should move properties', () => {\n    expect(\n      removeTrackName({\n        backgroundAudio: {\n          resource: {\n            src: 'https://example.com/audio.mp3',\n            id: 123,\n            mimeType: 'audio/mpeg',\n          },\n        },\n        pages: [\n          {\n            backgroundAudio: {\n              loop: true,\n              resource: {\n                src: 'https://example.com/audio.mp3',\n                id: 123,\n                mimeType: 'audio/mpeg',\n              },\n              tracks: [\n                {\n                  track: 'https://example.com/track.vtt',\n                  trackId: 123,\n                  trackName: 'track.vtt',\n                  id: 'rersd-fdfd-fdfd-fdfd',\n                  srcLang: '',\n                  label: '',\n                  kind: 'captions',\n                },\n              ],\n            },\n            elements: [],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n      },\n      pages: [\n        {\n          backgroundAudio: {\n            loop: true,\n            resource: {\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n            },\n            tracks: [\n              {\n                track: 'https://example.com/track.vtt',\n                trackId: 123,\n                id: 'rersd-fdfd-fdfd-fdfd',\n                srcLang: '',\n                label: '',\n                kind: 'captions',\n              },\n            ],\n          },\n          elements: [],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0043_removeTagNames.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeTagNames from '../v0043_removeTagNames';\n\ndescribe('removeTagNames', () => {\n  it('should remove tag names', () => {\n    expect(\n      removeTagNames({\n        pages: [\n          {\n            elements: [\n              {\n                id: '1',\n                type: 'text',\n                tagName: 'auto',\n              },\n              {\n                id: '2',\n                type: 'text',\n              },\n              {\n                id: '3',\n                type: 'text',\n                tagName: 'h1',\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                id: '4',\n                type: 'text',\n                tagName: 'auto',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              id: '1',\n              type: 'text',\n            },\n            {\n              id: '2',\n              type: 'text',\n            },\n            {\n              id: '3',\n              type: 'text',\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              id: '4',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0044_unusedProperties.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport unusedProperties from '../v0044_unusedProperties';\n\ndescribe('unusedProperties', () => {\n  it('should remove backgroundOverlay and fontWeight', () => {\n    expect(\n      unusedProperties({\n        pages: [\n          {\n            elements: [\n              {\n                id: '1',\n                type: 'text',\n                fontWeight: 400,\n              },\n              {\n                id: '2',\n                type: 'image',\n              },\n              {\n                id: '3',\n                type: 'video',\n                backgroundOverlay: {\n                  type: 'radial',\n                  size: { w: 0.8, h: 0.5 },\n                  stops: [\n                    { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0.25 },\n                    { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n                  ],\n                  alpha: 0.6,\n                },\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                id: '4',\n                type: 'text',\n                fontWeight: 700,\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              id: '1',\n              type: 'text',\n            },\n            {\n              id: '2',\n              type: 'image',\n            },\n            {\n              id: '3',\n              type: 'video',\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              id: '4',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0045_globalPageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport globalPageAdvancement from '../v0045_globalPageAdvancement';\n\ndescribe('globalPageAdvancement', () => {\n  it('should not remove non-default page advancement properties', () => {\n    expect(\n      globalPageAdvancement({\n        _test: 'story',\n        pages: [],\n        autoAdvance: false,\n        defaultPageDuration: 7,\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [],\n      autoAdvance: false,\n      defaultPageDuration: 7,\n    });\n\n    expect(\n      globalPageAdvancement({\n        _test: 'story',\n        pages: [],\n        autoAdvance: true,\n        defaultPageDuration: 12,\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [],\n      autoAdvance: true,\n      defaultPageDuration: 12,\n    });\n  });\n\n  it('should remove existing default page advancement properties', () => {\n    expect(\n      globalPageAdvancement({\n        _test: 'story',\n        pages: [],\n        autoAdvance: true,\n        defaultPageDuration: 7,\n      })\n    ).toStrictEqual({\n      _test: 'story',\n      pages: [],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0046_removeRedundantScalingProperties.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeRedundantScalingProperties from '../v0046_removeRedundantScalingProperties';\n\ndescribe('unusedProperties', () => {\n  it('should remove scaling properties from non-media elements', () => {\n    expect(\n      removeRedundantScalingProperties({\n        pages: [\n          {\n            elements: [\n              {\n                id: '1',\n                type: 'text',\n                scale: 400,\n                focalX: 10,\n                focalY: 30,\n              },\n              {\n                id: '2',\n                type: 'image',\n                resource: {},\n                scale: 100,\n                focalX: 0,\n                focalY: 0,\n              },\n              {\n                id: '3',\n                type: 'shape',\n                scale: 10,\n                focalX: 10,\n                focalY: 10,\n              },\n            ],\n          },\n          {\n            elements: [\n              {\n                id: '4',\n                type: 'text',\n              },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            {\n              id: '1',\n              type: 'text',\n            },\n            {\n              id: '2',\n              type: 'image',\n              resource: {},\n              scale: 100,\n              focalX: 0,\n              focalY: 0,\n            },\n            {\n              id: '3',\n              type: 'shape',\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              id: '4',\n              type: 'text',\n            },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0047_fixBrokenTemplates.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport fixBrokenTemplates from '../v0047_fixBrokenTemplates';\n\ndescribe('fixBrokenTemplates', () => {\n  it('should move grouped elements together', () => {\n    expect(\n      fixBrokenTemplates({\n        pages: [\n          {\n            elements: [\n              { id: '1_1', groupId: 'a' },\n              { id: '1_2' },\n              { id: '1_3', groupId: 'a' },\n            ],\n          },\n          {\n            elements: [\n              { id: '2_1', groupId: 'b' },\n              { id: '2_2' },\n              { id: '2_3', groupId: 'c' },\n              { id: '2_4', groupId: 'c' },\n              { id: '2_5', groupId: 'b' },\n            ],\n          },\n          {\n            elements: [\n              { id: '3_1', groupId: 'd' },\n              { id: '3_2', groupId: 'e' },\n              { id: '3_3', groupId: 'f' },\n              { id: '3_4', groupId: 'g' },\n              { id: '3_5', groupId: 'd' },\n              { id: '3_6', groupId: 'e' },\n              { id: '3_7', groupId: 'f' },\n              { id: '3_8', groupId: 'g' },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            { id: '1_1', groupId: 'a' },\n            { id: '1_3', groupId: 'a' },\n            { id: '1_2' },\n          ],\n        },\n        {\n          elements: [\n            { id: '2_1', groupId: 'b' },\n            { id: '2_5', groupId: 'b' },\n            { id: '2_2' },\n            { id: '2_3', groupId: 'c' },\n            { id: '2_4', groupId: 'c' },\n          ],\n        },\n        {\n          elements: [\n            { id: '3_1', groupId: 'd' },\n            { id: '3_5', groupId: 'd' },\n            { id: '3_2', groupId: 'e' },\n            { id: '3_6', groupId: 'e' },\n            { id: '3_3', groupId: 'f' },\n            { id: '3_7', groupId: 'f' },\n            { id: '3_4', groupId: 'g' },\n            { id: '3_8', groupId: 'g' },\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should remove unused animations', () => {\n    expect(\n      fixBrokenTemplates({\n        pages: [\n          {\n            elements: [{ id: '1' }],\n            animations: [\n              { id: 'a', targets: ['1'] },\n              { id: 'b', targets: ['2'] },\n              { id: 'c', targets: ['1'] },\n            ],\n          },\n          {\n            elements: [{ id: '2' }],\n            animations: [{ id: 'a', targets: ['2'] }],\n          },\n          {\n            elements: [{ id: '3' }, { id: '4' }],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [{ id: '1' }],\n          animations: [\n            { id: 'a', targets: ['1'] },\n            { id: 'c', targets: ['1'] },\n          ],\n        },\n        {\n          elements: [{ id: '2' }],\n          animations: [{ id: 'a', targets: ['2'] }],\n        },\n        {\n          elements: [{ id: '3' }, { id: '4' }],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/test/v0048_removeBasedOnFromElements.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport removeBasedOnFromElements from '../v0048_removeBasedOnFromElements';\n\ndescribe('removeBasedOnFromElements', () => {\n  it('should move grouped elements together', () => {\n    expect(\n      removeBasedOnFromElements({\n        pages: [\n          {\n            elements: [\n              { id: '1_1', groupId: 'a', basedOn: '123' },\n              { id: '1_3', groupId: 'a' },\n              { id: '1_2' },\n            ],\n          },\n          {\n            elements: [\n              { id: '2_1', groupId: 'b' },\n              { id: '2_5', groupId: 'b', basedOn: '123' },\n              { id: '2_2' },\n              { id: '2_3', groupId: 'c' },\n              { id: '2_4', groupId: 'c' },\n            ],\n          },\n          {\n            elements: [\n              { id: '3_1', groupId: 'd' },\n              { id: '3_5', groupId: 'd', basedOn: '123' },\n              { id: '3_2', groupId: 'e' },\n              { id: '3_6', groupId: 'e' },\n              { id: '3_3', groupId: 'f' },\n              { id: '3_7', groupId: 'f' },\n              { id: '3_4', groupId: 'g' },\n              { id: '3_8', groupId: 'g' },\n            ],\n          },\n        ],\n      })\n    ).toStrictEqual({\n      pages: [\n        {\n          elements: [\n            { id: '1_1', groupId: 'a' },\n            { id: '1_3', groupId: 'a' },\n            { id: '1_2' },\n          ],\n        },\n        {\n          elements: [\n            { id: '2_1', groupId: 'b' },\n            { id: '2_5', groupId: 'b' },\n            { id: '2_2' },\n            { id: '2_3', groupId: 'c' },\n            { id: '2_4', groupId: 'c' },\n          ],\n        },\n        {\n          elements: [\n            { id: '3_1', groupId: 'd' },\n            { id: '3_5', groupId: 'd' },\n            { id: '3_2', groupId: 'e' },\n            { id: '3_6', groupId: 'e' },\n            { id: '3_3', groupId: 'f' },\n            { id: '3_7', groupId: 'f' },\n            { id: '3_4', groupId: 'g' },\n            { id: '3_8', groupId: 'g' },\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/migration/src/migrations/v0001_storyDataArrayToObject.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  PageV0,\n  StoryV0,\n  TextElementV0,\n  GifElementV0,\n  ImageElementV0,\n  VideoElementV0,\n  ShapeElementV0,\n  ProductElementV0,\n} from '../types';\n\nexport type PageV1 = PageV0;\nexport interface StoryV1 {\n  pages: PageV1[];\n  version?: number;\n  backgroundAudio?: {\n    src: string;\n    id: number;\n    mimeType: string;\n  };\n}\n\nexport type TextElementV1 = TextElementV0;\nexport type GifElementV1 = GifElementV0;\nexport type ImageElementV1 = ImageElementV0;\nexport type VideoElementV1 = VideoElementV0;\nexport type ShapeElementV1 = ShapeElementV0;\nexport type ProductElementV1 = ProductElementV0;\n\nexport type UnionElementV1 =\n  | ShapeElementV1\n  | ImageElementV1\n  | VideoElementV1\n  | TextElementV1;\n\nfunction storyDataArrayToObject(storyData: StoryV0): StoryV1 {\n  return { pages: storyData };\n}\n\nexport default storyDataArrayToObject;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0002_dataPixelTo1080.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  StoryV1,\n  PageV1,\n  TextElementV1,\n  GifElementV1,\n  ImageElementV1,\n  VideoElementV1,\n  ShapeElementV1,\n  ProductElementV1,\n  UnionElementV1,\n} from './v0001_storyDataArrayToObject';\n\nconst NEW_PAGE_WIDTH = 1080;\nconst NEW_PAGE_HEIGHT = 1920;\nconst OLD_PAGE_WIDTH = 412;\nconst OLD_PAGE_HEIGHT = 732;\n\nconst SCALE_X = NEW_PAGE_WIDTH / OLD_PAGE_WIDTH;\nconst SCALE_Y = NEW_PAGE_HEIGHT / OLD_PAGE_HEIGHT;\n\nexport type TextElementV2 = TextElementV1;\nexport type GifElementV2 = GifElementV1;\nexport type ImageElementV2 = ImageElementV1;\nexport type VideoElementV2 = VideoElementV1;\nexport type ShapeElementV2 = ShapeElementV1;\nexport type ProductElementV2 = ProductElementV1;\n\nexport type UnionElementV2 =\n  | ShapeElementV2\n  | ImageElementV2\n  | VideoElementV2\n  | TextElementV2;\n\nexport interface StoryV2 extends Omit<StoryV1, 'pages'> {\n  pages: PageV2[];\n}\nexport interface PageV2 extends Omit<PageV1, 'elements'> {\n  elements: UnionElementV2[];\n}\n\nfunction dataPixelTo1080({ pages, ...rest }: StoryV1): StoryV2 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV1): PageV2 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement({\n  x,\n  y,\n  width,\n  height,\n  ...rest\n}: UnionElementV1): UnionElementV2 {\n  const element = {\n    x: dataPixels(x * SCALE_X),\n    y: dataPixels(y * SCALE_Y),\n    width: dataPixels(width * SCALE_X),\n    height: dataPixels(height * SCALE_Y),\n    ...rest,\n  };\n  if ('fontSize' in element && typeof element.fontSize === 'number') {\n    element.fontSize = dataPixels(element.fontSize * SCALE_Y);\n  }\n  return element;\n}\n\n/**\n * See `units/dimensions.js`.\n *\n * @param v The value to be rounded.\n * @return The value rounded to the \"data\" space precision.\n */\nfunction dataPixels(v: number) {\n  return Number(v.toFixed(0));\n}\n\nexport default dataPixelTo1080;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0003_fullbleedToFill.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  PageV2,\n  StoryV2,\n  VideoElementV2,\n  GifElementV2,\n  ImageElementV2,\n  TextElementV2,\n  ShapeElementV2,\n  ProductElementV2,\n  UnionElementV2,\n} from './v0002_dataPixelTo1080';\n\nexport interface VideoElementV3 extends Omit<VideoElementV2, 'isFullbleed'> {\n  isFill?: boolean;\n}\n\nexport interface GifElementV3 extends Omit<GifElementV2, 'isFullbleed'> {\n  isFill?: boolean;\n}\n\nexport interface ImageElementV3 extends Omit<ImageElementV2, 'isFullbleed'> {\n  isFill?: boolean;\n}\n\nexport type TextElementV3 = TextElementV2;\nexport type ShapeElementV3 = ShapeElementV2;\nexport type ProductElementV3 = ProductElementV2;\n\nexport type UnionElementV3 =\n  | ShapeElementV3\n  | ImageElementV3\n  | VideoElementV3\n  | TextElementV3;\n\nexport interface StoryV3 extends Omit<StoryV2, 'pages'> {\n  pages: PageV3[];\n}\nexport interface PageV3 extends Omit<PageV2, 'elements'> {\n  elements: UnionElementV3[];\n}\n\nfunction fullbleedToFill({ pages, ...rest }: StoryV2): StoryV3 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV2): PageV3 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV2): UnionElementV3 {\n  if ('isFullbleed' in element) {\n    const { isFullbleed, ...rest } = element;\n    return {\n      isFill: isFullbleed,\n      ...rest,\n    };\n  }\n  return element;\n}\n\nexport default fullbleedToFill;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0004_mediaElementToResource.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV0,\n  ImageResourceV0,\n  VideoResourceV0,\n  ResourceType,\n} from '../types';\nimport type {\n  ImageElementV3,\n  GifElementV3,\n  VideoElementV3,\n  PageV3,\n  StoryV3,\n  TextElementV3,\n  ShapeElementV3,\n  ProductElementV3,\n  UnionElementV3,\n} from './v0003_fullbleedToFill';\n\nexport interface VideoElementV4 extends Omit<\n  VideoElementV3,\n  'src' | 'origRatio' | 'mimeType' | 'videoId' | 'poster' | 'posterId'\n> {\n  resource: VideoResourceV0;\n}\n\nexport interface GifElementV4 extends Omit<\n  GifElementV3,\n  'src' | 'origRatio' | 'mimeType'\n> {\n  resource: GifResourceV0;\n}\n\nexport interface ImageElementV4 extends Omit<\n  ImageElementV3,\n  'src' | 'origRatio' | 'mimeType'\n> {\n  resource: ImageResourceV0;\n}\n\nexport type TextElementV4 = TextElementV3;\nexport type ShapeElementV4 = ShapeElementV3;\nexport type ProductElementV4 = ProductElementV3;\n\nexport type UnionElementV4 =\n  | ShapeElementV4\n  | ImageElementV4\n  | VideoElementV4\n  | TextElementV4\n  | GifElementV4;\n\nexport interface StoryV4 extends Omit<StoryV3, 'pages'> {\n  pages: PageV4[];\n}\nexport interface PageV4 extends Omit<PageV3, 'elements'> {\n  elements: UnionElementV4[];\n}\n\nfunction dataMediaElementToResource({ pages, ...rest }: StoryV3): StoryV4 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV3): PageV4 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV3): UnionElementV4 {\n  if ('mimeType' in element) {\n    if ('videoId' in element) {\n      const {\n        src,\n        origRatio,\n        poster,\n        posterId,\n        videoId,\n        mimeType,\n        width,\n        height,\n        ...rest\n      } = element;\n      return {\n        resource: {\n          type: 'video' as ResourceType.Video,\n          src,\n          width,\n          height,\n          poster,\n          posterId,\n          videoId,\n          mimeType,\n        },\n        width,\n        height,\n        ...rest,\n      };\n    } else if (element.type === 'image') {\n      const { src, origRatio, width, height, mimeType, ...rest } = element;\n      return {\n        resource: {\n          type: 'image' as ResourceType.Image,\n          src,\n          width,\n          height,\n          mimeType,\n        },\n        width,\n        height,\n        ...rest,\n      };\n    }\n  }\n  return element as UnionElementV4;\n}\n\nexport default dataMediaElementToResource;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0004_squareToShape.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  StoryV4,\n  PageV4,\n  UnionElementV4,\n  ShapeElementV4,\n} from './v0004_mediaElementToResource';\n\nfunction dataSquareToShape({ pages, ...rest }: StoryV4): StoryV4 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV4): PageV4 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV4): UnionElementV4 {\n  const { type, ...rest } = element;\n  if ('square' === type) {\n    return {\n      type: 'shape',\n      ...rest,\n    } as ShapeElementV4;\n  }\n  return element;\n}\n\nexport default dataSquareToShape;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0005_setOpacity.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV4,\n  ImageElementV4,\n  PageV4,\n  ProductElementV4,\n  ShapeElementV4,\n  StoryV4,\n  TextElementV4,\n  UnionElementV4,\n  VideoElementV4,\n} from './v0004_mediaElementToResource';\n\nexport interface VideoElementV5 extends VideoElementV4 {\n  opacity: number;\n}\n\nexport interface GifElementV5 extends GifElementV4 {\n  opacity: number;\n}\n\nexport interface ImageElementV5 extends ImageElementV4 {\n  opacity: number;\n}\n\nexport interface TextElementV5 extends TextElementV4 {\n  opacity: number;\n}\n\nexport interface ShapeElementV5 extends ShapeElementV4 {\n  opacity: number;\n}\nexport type ProductElementV5 = ProductElementV4;\n\nexport type UnionElementV5 =\n  | ShapeElementV5\n  | ImageElementV5\n  | VideoElementV5\n  | GifElementV5\n  | TextElementV5;\n\nexport interface StoryV5 extends Omit<StoryV4, 'pages'> {\n  pages: PageV5[];\n}\nexport interface PageV5 extends Omit<PageV4, 'elements'> {\n  elements: UnionElementV5[];\n}\n\nfunction setOpacity({ pages, ...rest }: StoryV4): StoryV5 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV4): PageV5 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV4): UnionElementV5 {\n  if ('opacity' in element && element.opacity) {\n    return element;\n  }\n  return {\n    opacity: 100,\n    ...element,\n  };\n}\n\nexport default setOpacity;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0006_colorToPattern.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { parseToRgb } from 'polished';\n\n/**\n * Internal dependencies\n */\nimport type { PatternV0, Pattern } from '../types/pattern';\nimport type {\n  GifElementV5,\n  ImageElementV5,\n  PageV5,\n  ProductElementV5,\n  ShapeElementV5,\n  StoryV5,\n  TextElementV5,\n  UnionElementV5,\n  VideoElementV5,\n} from './v0005_setOpacity';\n\nexport interface TextElementV6 extends Omit<\n  TextElementV5,\n  'color' | 'backgroundColor'\n> {\n  color: Pattern | null;\n  backgroundColor: PatternV0 | null;\n}\n\nexport interface ShapeElementV6 extends Omit<\n  ShapeElementV5,\n  'backgroundColor'\n> {\n  backgroundColor: PatternV0;\n}\nexport type GifElementV6 = GifElementV5;\nexport type ProductElementV6 = ProductElementV5;\nexport type ImageElementV6 = ImageElementV5;\nexport type VideoElementV6 = VideoElementV5;\n\nexport type UnionElementV6 =\n  | ShapeElementV6\n  | ImageElementV6\n  | VideoElementV6\n  | GifElementV6\n  | TextElementV6\n  | ProductElementV6;\n\nexport interface StoryV6 extends Omit<StoryV5, 'pages'> {\n  pages: PageV6[];\n}\nexport interface PageV6 extends Omit<PageV5, 'elements' | 'backgroundColor'> {\n  elements: UnionElementV6[];\n  backgroundColor: PatternV0 | null;\n}\n\nfunction colorToPattern({ pages, ...rest }: StoryV5): StoryV6 {\n  return {\n    pages: pages.map(updatePage),\n    ...rest,\n  };\n}\n\nfunction updatePage({ elements, backgroundColor, ...rest }: PageV5): PageV6 {\n  return {\n    elements: elements.map(updateElement),\n    backgroundColor: parse(backgroundColor),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV5): UnionElementV6 {\n  const newProps: Record<string, null | PatternV0> = {};\n\n  if ('color' in element) {\n    newProps.color = parse(element.color);\n  }\n\n  if ('backgroundColor' in element) {\n    newProps.backgroundColor = parse(element.backgroundColor);\n  }\n\n  return {\n    ...element,\n    ...newProps,\n  } as UnionElementV6;\n}\n\nfunction parse(colorString: string | undefined): PatternV0 | null {\n  if (!colorString || colorString === 'transparent') {\n    return null;\n  }\n  const colorObject = parseToRgb(colorString);\n  const { red: r, green: g, blue: b } = colorObject;\n  if ('alpha' in colorObject && colorObject.alpha !== 1) {\n    const { alpha: a } = colorObject;\n    return { color: { r, g, b, a } };\n  }\n  return { color: { r, g, b } };\n}\n\nexport default colorToPattern;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0007_setFlip.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  ShapeElementV6,\n  TextElementV6,\n  GifElementV6,\n  ProductElementV6,\n  ImageElementV6,\n  VideoElementV6,\n  StoryV6,\n  PageV6,\n  UnionElementV6,\n} from './v0006_colorToPattern';\n\ninterface Flip {\n  vertical: boolean;\n  horizontal: boolean;\n}\n\nexport interface ShapeElementV7 extends ShapeElementV6 {\n  flip?: Flip;\n}\nexport interface GifElementV7 extends GifElementV6 {\n  flip?: Flip;\n}\n\nexport interface ImageElementV7 extends ImageElementV6 {\n  flip?: Flip;\n}\n\nexport interface VideoElementV7 extends VideoElementV6 {\n  flip?: Flip;\n}\n\nexport type TextElementV7 = TextElementV6;\nexport type ProductElementV7 = ProductElementV6;\n\nexport type UnionElementV7 =\n  | ShapeElementV7\n  | ImageElementV7\n  | VideoElementV7\n  | GifElementV7\n  | TextElementV7\n  | ProductElementV7;\n\nexport interface StoryV7 extends Omit<StoryV6, 'pages'> {\n  pages: PageV7[];\n}\nexport interface PageV7 extends Omit<PageV6, 'elements'> {\n  elements: UnionElementV7[];\n}\n\nfunction setFlip({ pages, ...rest }: StoryV6): StoryV7 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV6): PageV7 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV6): UnionElementV7 {\n  // If it's a text element or already has flip set, return as is.\n  if ('content' in element || 'flip' in element) {\n    // Casting since if flip was set, it was already UnionElementV7.\n    return element as UnionElementV7;\n  }\n  return {\n    ...element,\n    flip: {\n      horizontal: false,\n      vertical: false,\n    },\n  };\n}\n\nexport default setFlip;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0008_paddingToObject.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV7,\n  ImageElementV7,\n  PageV7,\n  ProductElementV7,\n  ShapeElementV7,\n  StoryV7,\n  TextElementV7,\n  VideoElementV7,\n  UnionElementV7,\n} from './v0007_setFlip';\n\ninterface Padding {\n  horizontal: number;\n  vertical: number;\n}\n\nexport interface TextElementV8 extends Omit<TextElementV7, 'padding'> {\n  padding: Padding;\n}\nexport type ProductElementV8 = ProductElementV7;\nexport type ShapeElementV8 = ShapeElementV7;\nexport type ImageElementV8 = ImageElementV7;\nexport type VideoElementV8 = VideoElementV7;\nexport type GifElementV8 = GifElementV7;\n\nexport type UnionElementV8 =\n  | ShapeElementV8\n  | ImageElementV8\n  | VideoElementV8\n  | GifElementV8\n  | TextElementV8\n  | ProductElementV8;\n\nexport interface StoryV8 extends Omit<StoryV7, 'pages'> {\n  pages: PageV8[];\n}\nexport interface PageV8 extends Omit<PageV7, 'elements'> {\n  elements: UnionElementV8[];\n}\n\nfunction paddingToObject({ pages, ...rest }: StoryV7): StoryV8 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV7): PageV8 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV7): UnionElementV8 {\n  if (!('content' in element)) {\n    return element;\n  }\n\n  const { padding } = element;\n  if (\n    padding &&\n    Object.prototype.hasOwnProperty.call(element.padding, 'vertical') &&\n    Object.prototype.hasOwnProperty.call(element.padding, 'horizontal')\n  ) {\n    // If padding is already set, just return as is.\n    return element as UnionElementV8;\n  }\n\n  const newPadding = padding || 0;\n  return {\n    ...element,\n    padding: {\n      horizontal: newPadding,\n      vertical: newPadding,\n    },\n  };\n}\n\nexport default paddingToObject;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0009_defaultBackground.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV8,\n  ImageElementV8,\n  PageV8,\n  ProductElementV8,\n  ShapeElementV8,\n  StoryV8,\n  TextElementV8,\n  VideoElementV8,\n} from './v0008_paddingToObject';\n\nexport type TextElementV9 = TextElementV8;\nexport type ProductElementV9 = ProductElementV8;\nexport type ShapeElementV9 = ShapeElementV8;\nexport type ImageElementV9 = ImageElementV8;\nexport type VideoElementV9 = VideoElementV8;\nexport type GifElementV9 = GifElementV8;\n\nexport type UnionElementV9 =\n  | ShapeElementV9\n  | ImageElementV9\n  | VideoElementV9\n  | GifElementV9\n  | TextElementV9\n  | ProductElementV9;\n\nexport interface StoryV9 extends Omit<StoryV8, 'pages'> {\n  pages: PageV9[];\n}\nexport interface PageV9 extends Omit<PageV8, 'elements' | 'backgroundColor'> {\n  elements: UnionElementV9[];\n  backgroundElementId?: string;\n}\n\nconst PAGE_WIDTH = 1080;\nconst DEFAULT_ELEMENT_WIDTH = PAGE_WIDTH / 3;\n\nfunction defaultBackground({ pages, ...rest }: StoryV8): StoryV9 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ backgroundColor, ...rest }: PageV8): PageV9 {\n  if (!('backgroundElementId' in rest)) {\n    const { elements } = rest;\n    const element = {\n      type: 'shape',\n      x: (PAGE_WIDTH / 4) * Math.random(),\n      y: (PAGE_WIDTH / 4) * Math.random(),\n      width: DEFAULT_ELEMENT_WIDTH,\n      height: DEFAULT_ELEMENT_WIDTH,\n      rotationAngle: 0,\n      mask: {\n        type: 'rectangle',\n      },\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      isBackground: true,\n      backgroundColor: backgroundColor || {\n        color: { r: 255, g: 255, b: 255, a: 1 },\n      },\n      id: (uuidv4 as () => string)(),\n      opacity: 100,\n    };\n    elements.unshift(element);\n    return {\n      ...rest,\n      elements,\n      backgroundElementId: element.id,\n    };\n  }\n  // Casting since if it was set already, it was PageV9 already.\n  return rest as PageV9;\n}\n\nexport default defaultBackground;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0010_dataPixelTo440.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV9,\n  ImageElementV9,\n  PageV9,\n  ProductElementV9,\n  ShapeElementV9,\n  StoryV9,\n  TextElementV9,\n  UnionElementV9,\n  VideoElementV9,\n} from './v0009_defaultBackground';\n\nexport type TextElementV10 = TextElementV9;\nexport type ProductElementV10 = ProductElementV9;\nexport type ShapeElementV10 = ShapeElementV9;\nexport type ImageElementV10 = ImageElementV9;\nexport type VideoElementV10 = VideoElementV9;\nexport type GifElementV10 = GifElementV9;\n\nexport type UnionElementV10 =\n  | ShapeElementV10\n  | ImageElementV10\n  | VideoElementV10\n  | GifElementV10\n  | TextElementV10\n  | ProductElementV10;\n\nexport interface StoryV10 extends Omit<StoryV9, 'pages'> {\n  pages: PageV10[];\n}\nexport interface PageV10 extends Omit<PageV9, 'elements'> {\n  elements: UnionElementV10[];\n}\n\nconst NEW_PAGE_WIDTH = 440;\nconst NEW_PAGE_HEIGHT = 660;\nconst OLD_PAGE_WIDTH = 1080;\nconst OLD_PAGE_HEIGHT = 1920;\n\n// Aspect ratio is changed, but we don't want to break ratios of existing\n// elements at this point. Thus the formula here is \"contain\".\nconst SCALE = Math.min(\n  NEW_PAGE_WIDTH / OLD_PAGE_WIDTH,\n  NEW_PAGE_HEIGHT / OLD_PAGE_HEIGHT\n);\n\nfunction dataPixelTo440({ pages, ...rest }: StoryV9): StoryV10 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV9): PageV10 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement({\n  x,\n  y,\n  width,\n  height,\n  ...rest\n}: UnionElementV9): UnionElementV10 {\n  const element = {\n    x: dataPixels(x * SCALE),\n    y: dataPixels(y * SCALE),\n    width: dataPixels(width * SCALE),\n    height: dataPixels(height * SCALE),\n    ...rest,\n  };\n  if ('fontSize' in element) {\n    const { fontSize } = element;\n    if (typeof fontSize === 'number') {\n      element.fontSize = dataPixels(fontSize * SCALE);\n    }\n  }\n\n  if ('padding' in element && element.padding) {\n    const { padding } = element;\n    const { horizontal, vertical } = padding;\n    element.padding = {\n      horizontal: dataPixels(horizontal * SCALE),\n      vertical: dataPixels(vertical * SCALE),\n    };\n  }\n\n  return element;\n}\n\n/**\n * See `units/dimensions.js`.\n *\n * @param v The value to be rounded.\n * @return The value rounded to the \"data\" space precision.\n */\nfunction dataPixels(v: number) {\n  return Number(v.toFixed(0));\n}\n\nexport default dataPixelTo440;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0011_pageAdvancement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV10,\n  ImageElementV10,\n  PageV10,\n  ProductElementV10,\n  ShapeElementV10,\n  StoryV10,\n  TextElementV10,\n  VideoElementV10,\n} from './v0010_dataPixelTo440';\n\nexport type TextElementV11 = TextElementV10;\nexport type ProductElementV11 = ProductElementV10;\nexport type ShapeElementV11 = ShapeElementV10;\nexport type ImageElementV11 = ImageElementV10;\nexport type VideoElementV11 = VideoElementV10;\nexport type GifElementV11 = GifElementV10;\n\nexport type UnionElementV11 =\n  | ShapeElementV11\n  | ImageElementV11\n  | VideoElementV11\n  | GifElementV11\n  | TextElementV11\n  | ProductElementV11;\n\nexport interface StoryV11 extends Omit<StoryV10, 'pages'> {\n  pages: PageV11[];\n  autoAdvance: boolean;\n  defaultPageDuration: number;\n}\nexport interface PageV11 extends Omit<PageV10, 'elements'> {\n  elements: UnionElementV11[];\n}\n\nfunction pageAdvancement(story: StoryV10): StoryV11 {\n  if ('autoAdvance' in story && 'defaultPageDuration' in story) {\n    return story as StoryV11;\n  }\n  return {\n    autoAdvance: true,\n    defaultPageDuration: 7,\n    ...story,\n  };\n}\n\nexport default pageAdvancement;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0012_setBackgroundTextMode.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV11,\n  ImageElementV11,\n  PageV11,\n  ProductElementV11,\n  ShapeElementV11,\n  StoryV11,\n  TextElementV11,\n  UnionElementV11,\n  VideoElementV11,\n} from './v0011_pageAdvancement';\n\nexport interface TextElementV12 extends TextElementV11 {\n  backgroundTextMode: string;\n}\n\nexport type ProductElementV12 = ProductElementV11;\nexport type ShapeElementV12 = ShapeElementV11;\nexport type ImageElementV12 = ImageElementV11;\nexport type VideoElementV12 = VideoElementV11;\nexport type GifElementV12 = GifElementV11;\n\nexport type UnionElementV12 =\n  | ShapeElementV12\n  | ImageElementV12\n  | VideoElementV12\n  | GifElementV12\n  | TextElementV12\n  | ProductElementV12;\n\nexport interface StoryV12 extends Omit<StoryV11, 'pages'> {\n  pages: PageV12[];\n}\nexport interface PageV12 extends Omit<PageV11, 'elements'> {\n  elements: UnionElementV12[];\n}\n\nfunction setBackgroundTextMode({ pages, ...rest }: StoryV11): StoryV12 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV11): PageV12 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV11): UnionElementV12 {\n  if ('content' in element) {\n    let hasBackgroundColor = false;\n    if ('backgroundColor' in element) {\n      hasBackgroundColor = Boolean(element.backgroundColor);\n    }\n\n    return {\n      backgroundTextMode: hasBackgroundColor ? 'FILL' : 'NONE',\n      ...element,\n    };\n  }\n\n  return element;\n}\n\nexport default setBackgroundTextMode;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0013_videoIdToId.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType } from '../types';\nimport type {\n  GifElementV12,\n  ImageElementV12,\n  PageV12,\n  ProductElementV12,\n  ShapeElementV12,\n  StoryV12,\n  TextElementV12,\n  UnionElementV12,\n  VideoElementV12,\n} from './v0012_setBackgroundTextMode';\n\nexport interface VideoElementV13 extends Omit<VideoElementV12, 'resource'> {\n  resource: {\n    poster?: string;\n    posterId?: number;\n    id?: number;\n    type: ResourceType.Video;\n    lengthFormatted?: string;\n  };\n}\n\nexport type TextElementV13 = TextElementV12;\nexport type ProductElementV13 = ProductElementV12;\nexport type ShapeElementV13 = ShapeElementV12;\nexport type ImageElementV13 = ImageElementV12;\nexport type GifElementV13 = GifElementV12;\n\nexport type UnionElementV13 =\n  | ShapeElementV13\n  | ImageElementV13\n  | VideoElementV13\n  | GifElementV13\n  | TextElementV13\n  | ProductElementV13;\n\nexport interface StoryV13 extends Omit<StoryV12, 'pages'> {\n  pages: PageV13[];\n}\nexport interface PageV13 extends Omit<PageV12, 'elements'> {\n  elements: UnionElementV13[];\n}\n\nfunction videoIdToId({ pages, ...rest }: StoryV12): StoryV13 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV12): PageV13 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV12): UnionElementV13 {\n  if ('resource' in element && 'videoId' in element.resource) {\n    const { resource } = element;\n    const { videoId, ...rest } = resource;\n    const updatedResource = {\n      ...rest,\n      id: videoId,\n    };\n    return {\n      ...element,\n      resource: updatedResource,\n    } as VideoElementV13;\n  }\n  return element;\n}\n\nexport default videoIdToId;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0014_oneTapLinkDeprecate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { LinkV0 } from '../types';\nimport type {\n  GifElementV13,\n  ImageElementV13,\n  PageV13,\n  ProductElementV13,\n  ShapeElementV13,\n  StoryV13,\n  TextElementV13,\n  UnionElementV13,\n  VideoElementV13,\n} from './v0013_videoIdToId';\n\nexport type LinkV14 = Omit<LinkV0, 'type'>;\nexport interface VideoElementV14 extends Omit<VideoElementV13, 'link'> {\n  link?: LinkV14;\n}\n\nexport interface TextElementV14 extends Omit<TextElementV13, 'link'> {\n  link?: LinkV14;\n}\nexport interface ProductElementV14 extends Omit<ProductElementV13, 'link'> {\n  link?: LinkV14;\n}\nexport interface ShapeElementV14 extends Omit<ShapeElementV13, 'link'> {\n  link?: LinkV14;\n}\nexport interface ImageElementV14 extends Omit<ImageElementV13, 'link'> {\n  link?: LinkV14;\n}\nexport interface GifElementV14 extends Omit<GifElementV13, 'link'> {\n  link?: LinkV14;\n}\n\nexport type UnionElementV14 =\n  | ShapeElementV14\n  | ImageElementV14\n  | VideoElementV14\n  | GifElementV14\n  | TextElementV14\n  | ProductElementV14;\n\nexport interface StoryV14 extends Omit<StoryV13, 'pages'> {\n  pages: PageV14[];\n}\nexport interface PageV14 extends Omit<PageV13, 'elements'> {\n  elements: UnionElementV14[];\n}\n\nfunction oneTapLinkDeprecate({ pages, ...rest }: StoryV13): StoryV14 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV13): PageV14 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV13): UnionElementV14 {\n  if (element.link?.type) {\n    delete element.link.type;\n  }\n  return element;\n}\n\nexport default oneTapLinkDeprecate;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0015_fontObjects.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV14,\n  ImageElementV14,\n  PageV14,\n  ProductElementV14,\n  ShapeElementV14,\n  StoryV14,\n  TextElementV14,\n  UnionElementV14,\n  VideoElementV14,\n} from './v0014_oneTapLinkDeprecate';\n\nexport interface TextElementV15 extends Omit<\n  TextElementV14,\n  'fontFamily' | 'fontFallback'\n> {\n  font: {\n    service: string;\n    family: string;\n    fallbacks: string[];\n    id?: string;\n    name?: string;\n    value?: string;\n  };\n}\n\nexport type ProductElementV15 = ProductElementV14;\nexport type ShapeElementV15 = ShapeElementV14;\nexport type ImageElementV15 = ImageElementV14;\nexport type VideoElementV15 = VideoElementV14;\nexport type GifElementV15 = GifElementV14;\n\nexport type UnionElementV15 =\n  | ShapeElementV15\n  | ImageElementV15\n  | VideoElementV15\n  | GifElementV15\n  | TextElementV15\n  | ProductElementV15;\n\nexport interface StoryV15 extends Omit<StoryV14, 'pages'> {\n  pages: PageV15[];\n}\nexport interface PageV15 extends Omit<PageV14, 'elements'> {\n  elements: UnionElementV15[];\n}\n\nfunction fontObjects({ pages, ...rest }: StoryV14): StoryV15 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV14): PageV15 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nconst SYSTEM_FONTS = [\n  'Arial',\n  'Arial Black',\n  'Arial Narrow',\n  'Baskerville',\n  'Brush Script MT',\n  'Copperplate',\n  'Courier New',\n  'Century Gothic',\n  'Garamond',\n  'Georgia',\n  'Gill Sans',\n  'Lucida Bright',\n  'Lucida Sans Typewriter',\n  'Palatino',\n  'Papyrus',\n  'Tahoma',\n  'Times New Roman',\n  'Trebuchet MS',\n  'Verdana',\n];\n\nfunction updateElement(element: UnionElementV14): UnionElementV15 {\n  if (!('fontFamily' in element)) {\n    return element;\n  }\n\n  const { fontFamily, fontFallback, ...rest } = element;\n  const isSystemFont = SYSTEM_FONTS.includes(fontFamily);\n\n  return {\n    font: {\n      service: isSystemFont ? 'system' : 'fonts.google.com',\n      family: fontFamily,\n      fallbacks: fontFallback,\n    },\n    ...rest,\n  };\n}\n\nexport default fontObjects;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0016_isFullbleedDeprecate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV15,\n  ImageElementV15,\n  PageV15,\n  ProductElementV15,\n  ShapeElementV15,\n  StoryV15,\n  TextElementV15,\n  UnionElementV15,\n  VideoElementV15,\n} from './v0015_fontObjects';\n\nexport type TextElementV16 = TextElementV15;\nexport type ProductElementV16 = ProductElementV15;\nexport type ShapeElementV16 = ShapeElementV15;\nexport type ImageElementV16 = Omit<ImageElementV15, 'isFullbleedBackground'>;\nexport type VideoElementV16 = Omit<VideoElementV15, 'isFullbleedBackground'>;\nexport type GifElementV16 = Omit<GifElementV15, 'isFullbleedBackground'>;\n\nexport type UnionElementV16 =\n  | ShapeElementV16\n  | ImageElementV16\n  | VideoElementV16\n  | GifElementV16\n  | TextElementV16\n  | ProductElementV16;\n\nexport interface StoryV16 extends Omit<StoryV15, 'pages'> {\n  pages: PageV16[];\n}\nexport interface PageV16 extends Omit<PageV15, 'elements'> {\n  elements: UnionElementV16[];\n}\n\nfunction isFullbleedDeprecate({ pages, ...rest }: StoryV15): StoryV16 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV15): PageV16 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV15): UnionElementV16 {\n  if ('isFullbleedBackground' in element) {\n    delete element.isFullbleedBackground;\n  }\n  return element;\n}\n\nexport default isFullbleedDeprecate;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0017_inlineTextProperties.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Pattern } from '../types/pattern';\nimport type {\n  GifElementV16,\n  ImageElementV16,\n  PageV16,\n  ProductElementV16,\n  ShapeElementV16,\n  StoryV16,\n  TextElementV16,\n  UnionElementV16,\n  VideoElementV16,\n} from './v0016_isFullbleedDeprecate';\n\nexport type TextElementV17 = Omit<\n  TextElementV16,\n  | 'bold'\n  | 'fontWeight'\n  | 'fontStyle'\n  | 'textDecoration'\n  | 'letterSpacing'\n  | 'color'\n>;\n\nexport type ProductElementV17 = ProductElementV16;\nexport type ShapeElementV17 = ShapeElementV16;\nexport type ImageElementV17 = ImageElementV16;\nexport type VideoElementV17 = VideoElementV16;\nexport type GifElementV17 = GifElementV16;\n\nexport type UnionElementV17 =\n  | ShapeElementV17\n  | ImageElementV17\n  | VideoElementV17\n  | GifElementV17\n  | TextElementV17\n  | ProductElementV17;\n\nexport interface StoryV17 extends Omit<StoryV16, 'pages'> {\n  pages: PageV17[];\n}\nexport interface PageV17 extends Omit<PageV16, 'elements'> {\n  elements: UnionElementV17[];\n}\n\nfunction inlineTextProperties({ pages, ...rest }: StoryV16): StoryV17 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV16): PageV17 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV16): UnionElementV17 {\n  if ('content' in element) {\n    return updateTextContent(element);\n  }\n\n  return element;\n}\n\nfunction updateTextContent({\n  bold,\n  fontWeight,\n  fontStyle,\n  textDecoration,\n  letterSpacing,\n  color,\n  content,\n  ...rest\n}: TextElementV16): TextElementV17 {\n  // We use an array to chain all the converters more nicely\n  const convertedContent = [content]\n    .map((c) => convertInlineBold(c, bold, fontWeight))\n    .map((c) => convertInlineItalic(c, fontStyle))\n    .map((c) => convertInlineUnderline(c, textDecoration))\n    .map((c) => addInlineColor(c, color))\n    .map((c) => addInlineLetterSpacing(c, letterSpacing))\n    .pop();\n\n  return { ...rest, content: convertedContent as string };\n}\n\nfunction convertInlineBold(\n  content: string,\n  isBold: boolean,\n  fontWeight: number\n): string {\n  // Do we have a specific global weight to apply for entire text field?\n  const globalWeight =\n    typeof fontWeight === 'number' && fontWeight !== 400\n      ? fontWeight\n      : isBold\n        ? 700\n        : null;\n\n  if (globalWeight) {\n    // In that case, strip any inline bold from the text and wrap everything in a span with correct style\n    const stripped = stripTag(content, 'strong');\n    const fancyBold = `font-weight: ${globalWeight}`;\n    return wrapWithSpan(stripped, fancyBold);\n  }\n\n  const justBold = 'font-weight: 700';\n  return replaceTagWithSpan(content, 'strong', justBold);\n}\n\nfunction convertInlineItalic(content: string, fontStyle: string): string {\n  // Do we have a specific font style to apply for entire text field?\n  const globalFontStyle = fontStyle === 'italic' ? fontStyle : null;\n  const italicStyle = 'font-style: italic';\n\n  if (globalFontStyle) {\n    // In that case, strip any inline em from the text and wrap everything in a span with correct style\n    const stripped = stripTag(content, 'em');\n    return wrapWithSpan(stripped, italicStyle);\n  }\n\n  return replaceTagWithSpan(content, 'em', italicStyle);\n}\n\nfunction convertInlineUnderline(\n  content: string,\n  textDecoration: string\n): string {\n  // Do we have a specific text decoration to apply for entire text field?\n  const globalDecoration =\n    textDecoration === 'underline' ? textDecoration : null;\n  const underlineStyle = 'text-decoration: underline';\n\n  if (globalDecoration) {\n    // In that case, strip any inline underline from the text and wrap everything in a span with correct style\n    const stripped = stripTag(content, 'u');\n    return wrapWithSpan(stripped, underlineStyle);\n  }\n\n  return replaceTagWithSpan(content, 'u', underlineStyle);\n}\n\nfunction addInlineColor(content: string, color: Pattern | null): string {\n  // If we don't have a color (should never happen, but if), just return\n  if (!color) {\n    return content;\n  }\n\n  if ('color' in color) {\n    const {\n      color: { r, g, b, a = 1 },\n    } = color;\n    return wrapWithSpan(content, `color: rgba(${r}, ${g}, ${b}, ${a})`);\n  }\n  return content;\n}\n\nfunction addInlineLetterSpacing(\n  content: string,\n  letterSpacing: number\n): string {\n  // If we don't have letterSpacing, just return\n  if (!letterSpacing) {\n    return content;\n  }\n\n  return wrapWithSpan(content, `letter-spacing: ${letterSpacing / 100}em`);\n}\n\nfunction stripTag(html: string, tag: string) {\n  // This is a very naive strip. Can only remove non-self-closing tags with attributes, which is sufficient here\n  return html.replace(new RegExp(`</?${tag}>`, 'gi'), '');\n}\n\nfunction replaceTagWithSpan(html: string, tag: string, style: string) {\n  // Again, very naive\n  return html\n    .replace(new RegExp(`<${tag}>`, 'gi'), `<span style=\"${style}\">`)\n    .replace(new RegExp(`</${tag}>`, 'gi'), '</span>');\n}\n\nfunction wrapWithSpan(html: string, style: string) {\n  return `<span style=\"${style}\">${html}</span>`;\n}\n\nexport default inlineTextProperties;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0018_defaultBackgroundElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV17,\n  ImageElementV17,\n  PageV17,\n  ProductElementV17,\n  ShapeElementV17,\n  StoryV17,\n  TextElementV17,\n  VideoElementV17,\n} from './v0017_inlineTextProperties';\n\nexport interface ShapeElementV18 extends ShapeElementV17 {\n  isDefaultBackground?: boolean;\n}\n\nexport type TextElementV18 = TextElementV17;\nexport type ProductElementV18 = ProductElementV17;\nexport type ImageElementV18 = ImageElementV17;\nexport type VideoElementV18 = VideoElementV17;\nexport type GifElementV18 = GifElementV17;\n\nexport type UnionElementV18 =\n  | ShapeElementV18\n  | ImageElementV18\n  | VideoElementV18\n  | GifElementV18\n  | TextElementV18\n  | ProductElementV18;\n\nexport interface StoryV18 extends Omit<StoryV17, 'pages'> {\n  pages: PageV18[];\n}\nexport interface PageV18 extends Omit<\n  PageV17,\n  'elements' | 'backgroundElementId'\n> {\n  elements: UnionElementV18[];\n  defaultBackgroundElement?: ShapeElementV18;\n}\n\nfunction createDefaultBackgroundElement({\n  pages,\n  ...rest\n}: StoryV17): StoryV18 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({\n  elements,\n  backgroundElementId,\n  ...rest\n}: PageV17): PageV18 {\n  const backgroundElement = elements[0];\n  let extra = {};\n  const updatedElements = { ...elements };\n  if (backgroundElement.type === 'shape') {\n    (updatedElements[0] as ShapeElementV18).isDefaultBackground = true;\n  } else {\n    extra = {\n      defaultBackgroundElement: {\n        type: 'shape',\n        x: 1,\n        y: 1,\n        width: 1,\n        height: 1,\n        rotationAngle: 0,\n        mask: {\n          type: 'rectangle',\n        },\n        backgroundColor: {\n          color: { r: 255, g: 255, b: 255, a: 1 },\n        },\n        isBackground: true,\n        isDefaultBackground: true,\n        id: uuidv4(),\n      },\n    };\n  }\n  // Note that we're not including `backgroundElementId` here\n  return {\n    elements: updatedElements,\n    ...rest,\n    ...extra,\n  };\n}\n\nexport default createDefaultBackgroundElement;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0019_conicToLinear.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { type Linear, type Pattern, PatternTypeV0 } from '../types/pattern';\nimport type {\n  GifElementV18,\n  ImageElementV18,\n  PageV18,\n  ProductElementV18,\n  ShapeElementV18,\n  StoryV18,\n  TextElementV18,\n  UnionElementV18,\n  VideoElementV18,\n} from './v0018_defaultBackgroundElement';\n\nexport interface ShapeElementV19 extends Omit<\n  ShapeElementV18,\n  'backgroundColor'\n> {\n  backgroundColor?: Pattern;\n}\nexport interface TextElementV19 extends Omit<\n  TextElementV18,\n  'color' | 'backgroundColor'\n> {\n  color: Pattern;\n  backgroundColor?: Pattern;\n}\nexport type ProductElementV19 = ProductElementV18;\nexport type ImageElementV19 = ImageElementV18;\nexport type VideoElementV19 = VideoElementV18;\nexport type GifElementV19 = GifElementV18;\n\nexport type UnionElementV19 =\n  | ShapeElementV19\n  | ImageElementV19\n  | VideoElementV19\n  | GifElementV19\n  | TextElementV19\n  | ProductElementV19;\n\nexport interface StoryV19 extends Omit<StoryV18, 'pages'> {\n  pages: PageV19[];\n}\nexport interface PageV19 extends Omit<\n  PageV18,\n  | 'elements'\n  | 'backgroundElementId'\n  | 'backgroundColor'\n  | 'defaultBackgroundElement'\n> {\n  elements: UnionElementV19[];\n  backgroundColor?: Pattern;\n  defaultBackgroundElement?: ShapeElementV19;\n}\n\nfunction conicToLinear({ pages, ...rest }: StoryV18): StoryV19 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({\n  elements,\n  defaultBackgroundElement,\n  ...rest\n}: PageV18): PageV19 {\n  const updatedDefaultBackground = defaultBackgroundElement\n    ? (updateElement(defaultBackgroundElement) as ShapeElementV19)\n    : null;\n  return {\n    elements: elements.map(updateElement),\n    ...(updatedDefaultBackground\n      ? {\n          defaultBackgroundElement: updatedDefaultBackground,\n        }\n      : null),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV18): UnionElementV19 {\n  if ('backgroundColor' in element) {\n    const { backgroundColor, ...rest } = element;\n    if (!backgroundColor) {\n      return {\n        ...rest,\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n      };\n    }\n    if (backgroundColor.type === PatternTypeV0.Conic) {\n      return {\n        ...element,\n        backgroundColor: {\n          ...backgroundColor,\n          type: 'linear',\n        } as Linear,\n      };\n    }\n    return element as UnionElementV19;\n  }\n  return element;\n}\n\nexport default conicToLinear;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0020_isFillDeprecate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV19,\n  ImageElementV19,\n  PageV19,\n  ProductElementV19,\n  ShapeElementV19,\n  StoryV19,\n  TextElementV19,\n  UnionElementV19,\n  VideoElementV19,\n} from './v0019_conicToLinear';\n\nexport type TextElementV20 = TextElementV19;\nexport type ProductElementV20 = ProductElementV19;\nexport type ShapeElementV20 = ShapeElementV19;\nexport type ImageElementV20 = Omit<ImageElementV19, 'isFill'>;\nexport type VideoElementV20 = Omit<VideoElementV19, 'isFill'>;\nexport type GifElementV20 = Omit<GifElementV19, 'isFill'>;\n\nexport type UnionElementV20 =\n  | ShapeElementV20\n  | ImageElementV20\n  | VideoElementV20\n  | GifElementV20\n  | TextElementV20\n  | ProductElementV20;\n\nexport interface StoryV20 extends Omit<StoryV19, 'pages'> {\n  pages: PageV20[];\n}\nexport interface PageV20 extends Omit<PageV19, 'elements'> {\n  elements: UnionElementV20[];\n}\n\nconst PAGE_WIDTH = 440;\nconst PAGE_HEIGHT = 660;\nconst FULLBLEED_RATIO = 9 / 16;\nconst FULLBLEED_HEIGHT = PAGE_WIDTH / FULLBLEED_RATIO;\nconst DANGER_ZONE_HEIGHT = (FULLBLEED_HEIGHT - PAGE_HEIGHT) / 2;\n\nfunction isFillDeprecate({ pages, ...rest }: StoryV19): StoryV20 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV19): PageV20 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV19): UnionElementV20 {\n  if ('isFill' in element) {\n    const { isFill, ...rest } = element;\n    return isFill\n      ? {\n          ...rest,\n          x: 0,\n          y: -DANGER_ZONE_HEIGHT,\n          width: PAGE_WIDTH,\n          height: PAGE_WIDTH / FULLBLEED_RATIO,\n          rotationAngle: 0,\n        }\n      : rest;\n  }\n  return element;\n}\n\nexport default isFillDeprecate;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0021_backgroundColorToPage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Pattern } from '../types/pattern';\nimport type {\n  GifElementV20,\n  ImageElementV20,\n  PageV20,\n  ProductElementV20,\n  ShapeElementV20,\n  StoryV20,\n  TextElementV20,\n  VideoElementV20,\n} from './v0020_isFillDeprecate';\n\nexport type TextElementV21 = TextElementV20;\nexport type ProductElementV21 = ProductElementV20;\nexport type ShapeElementV21 = ShapeElementV20;\nexport type ImageElementV21 = ImageElementV20;\nexport type VideoElementV21 = VideoElementV20;\nexport type GifElementV21 = GifElementV20;\n\nexport type UnionElementV21 =\n  | ShapeElementV21\n  | ImageElementV21\n  | VideoElementV21\n  | GifElementV21\n  | TextElementV21\n  | ProductElementV21;\n\nexport interface StoryV21 extends Omit<StoryV20, 'pages'> {\n  pages: PageV21[];\n}\nexport interface PageV21 extends Omit<PageV20, 'elements'> {\n  elements: UnionElementV21[];\n  backgroundColor: Pattern;\n}\n\nfunction backgroundColorToPage({ pages, ...rest }: StoryV20): StoryV21 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage(page: PageV20): PageV21 {\n  const { elements, defaultBackgroundElement } = page;\n  const defaultBackground = {\n    type: 'solid',\n    color: { r: 255, g: 255, b: 255 },\n  } as Pattern;\n  let pageBackgroundColor;\n  if (\n    elements[0] &&\n    'isDefaultBackground' in elements[0] &&\n    elements[0].isDefaultBackground &&\n    elements[0].backgroundColor\n  ) {\n    pageBackgroundColor = elements[0].backgroundColor;\n  } else {\n    pageBackgroundColor = defaultBackgroundElement?.backgroundColor;\n  }\n  return {\n    ...page,\n    backgroundColor: pageBackgroundColor\n      ? pageBackgroundColor\n      : defaultBackground,\n  };\n}\n\nexport default backgroundColorToPage;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0022_dataPixelTo412.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV21,\n  ImageElementV21,\n  PageV21,\n  ProductElementV21,\n  ShapeElementV21,\n  StoryV21,\n  TextElementV21,\n  UnionElementV21,\n  VideoElementV21,\n} from './v0021_backgroundColorToPage';\n\nexport type TextElementV22 = TextElementV21;\nexport type ProductElementV22 = ProductElementV21;\nexport type ShapeElementV22 = ShapeElementV21;\nexport type ImageElementV22 = ImageElementV21;\nexport type VideoElementV22 = VideoElementV21;\nexport type GifElementV22 = GifElementV21;\n\nexport type UnionElementV22 =\n  | ShapeElementV22\n  | ImageElementV22\n  | VideoElementV22\n  | GifElementV22\n  | TextElementV22\n  | ProductElementV22;\n\nexport interface StoryV22 extends Omit<StoryV21, 'pages'> {\n  pages: PageV22[];\n}\nexport interface PageV22 extends Omit<PageV21, 'elements'> {\n  elements: UnionElementV22[];\n  backgroundOverlay?: string | undefined | null;\n}\n\nconst NEW_PAGE_WIDTH = 412;\nconst NEW_PAGE_HEIGHT = 618;\nconst OLD_PAGE_WIDTH = 440;\nconst OLD_PAGE_HEIGHT = 660;\n\n// Aspect ratio is changed, but we don't want to break ratios of existing\n// elements at this point. Thus the formula here is \"contain\".\nconst SCALE = Math.min(\n  NEW_PAGE_WIDTH / OLD_PAGE_WIDTH,\n  NEW_PAGE_HEIGHT / OLD_PAGE_HEIGHT\n);\n\nfunction dataPixelTo440({ pages, ...rest }: StoryV21): StoryV22 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV21): PageV22 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(props: UnionElementV21): UnionElementV22 {\n  const { x, y, width, height, ...rest } = props;\n  const element = {\n    x: dataPixels(x * SCALE),\n    y: dataPixels(y * SCALE),\n    width: dataPixels(width * SCALE),\n    height: dataPixels(height * SCALE),\n    ...rest,\n  };\n  if ('fontSize' in element && typeof element.fontSize === 'number') {\n    element.fontSize = dataPixels(element.fontSize * SCALE);\n  }\n  if ('padding' in element && element.padding) {\n    const { horizontal, vertical } = element.padding;\n    element.padding = {\n      horizontal: dataPixels(horizontal * SCALE),\n      vertical: dataPixels(vertical * SCALE),\n    };\n  }\n  return element;\n}\n\n/**\n * See `units/dimensions.js`.\n *\n * @param v The value to be rounded.\n * @return The value rounded to the \"data\" space precision.\n */\nfunction dataPixels(v: number) {\n  return Number(v.toFixed(0));\n}\n\nexport default dataPixelTo440;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0023_convertOverlayPattern.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Pattern, PatternType } from '../types/pattern';\nimport type {\n  GifElementV22,\n  ImageElementV22,\n  PageV22,\n  ProductElementV22,\n  ShapeElementV22,\n  StoryV22,\n  TextElementV22,\n  VideoElementV22,\n} from './v0022_dataPixelTo412';\n\nexport type TextElementV23 = TextElementV22;\nexport type ProductElementV23 = ProductElementV22;\nexport interface ShapeElementV23 extends ShapeElementV22 {\n  backgroundOverlay?: Pattern | null;\n}\nexport interface ImageElementV23 extends ImageElementV22 {\n  backgroundOverlay?: Pattern | null;\n}\nexport interface VideoElementV23 extends VideoElementV22 {\n  backgroundOverlay?: Pattern | null;\n}\nexport interface GifElementV23 extends GifElementV22 {\n  backgroundOverlay?: Pattern | null;\n}\n\nexport type UnionElementV23 =\n  | ShapeElementV23\n  | ImageElementV23\n  | VideoElementV23\n  | GifElementV23\n  | TextElementV23\n  | ProductElementV23;\n\nexport interface StoryV23 extends Omit<StoryV22, 'pages'> {\n  pages: PageV23[];\n}\nexport interface PageV23 extends Omit<\n  PageV22,\n  'elements' | 'backgroundOverlay'\n> {\n  elements: UnionElementV23[];\n}\n\nfunction convertOverlayPattern({ pages, ...rest }: StoryV22): StoryV23 {\n  return {\n    pages: pages.map(convertPage),\n    ...rest,\n  };\n}\n\nfunction convertPage({\n  elements,\n  backgroundOverlay,\n  ...rest\n}: PageV22): PageV23 {\n  const hasNonTrivialOverlay =\n    backgroundOverlay &&\n    ['solid', 'linear', 'radial'].includes(backgroundOverlay);\n  const backgroundElement = elements[0];\n  const isValidBackgroundElement = ['image', 'video'].includes(\n    backgroundElement?.type\n  );\n  if (!hasNonTrivialOverlay || !isValidBackgroundElement) {\n    return {\n      elements,\n      ...rest,\n    };\n  }\n\n  return {\n    elements: [\n      {\n        ...backgroundElement,\n        backgroundOverlay: getBackgroundOverlay(backgroundOverlay),\n      },\n      ...elements.slice(1),\n    ],\n    ...rest,\n  };\n}\n\nfunction getBackgroundOverlay(overlayType: string): Pattern | null {\n  switch (overlayType) {\n    case 'solid':\n      return {\n        color: { r: 0, g: 0, b: 0, a: 0.3 },\n      };\n\n    case 'linear':\n      return {\n        type: 'linear' as PatternType.Linear,\n        rotation: 0,\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0.4 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.9,\n      };\n\n    case 'radial':\n      return {\n        type: 'radial' as PatternType.Radial,\n        size: { w: 0.8, h: 0.5 },\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0.25 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.6,\n      };\n\n    default:\n      return null;\n  }\n}\n\nexport default convertOverlayPattern;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0024_blobsToSingleBlob.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV23,\n  ImageElementV23,\n  PageV23,\n  ProductElementV23,\n  ShapeElementV23,\n  StoryV23,\n  TextElementV23,\n  UnionElementV23,\n  VideoElementV23,\n} from './v0023_convertOverlayPattern';\n\nexport type TextElementV24 = TextElementV23;\nexport type ProductElementV24 = ProductElementV23;\nexport type ShapeElementV24 = ShapeElementV23;\nexport type ImageElementV24 = ImageElementV23;\nexport type VideoElementV24 = VideoElementV23;\nexport type GifElementV24 = GifElementV23;\n\nexport type UnionElementV24 =\n  | ShapeElementV24\n  | ImageElementV24\n  | VideoElementV24\n  | GifElementV24\n  | TextElementV24\n  | ProductElementV24;\n\nexport interface StoryV24 extends Omit<StoryV23, 'pages'> {\n  pages: PageV24[];\n}\nexport interface PageV24 extends Omit<PageV23, 'elements'> {\n  elements: UnionElementV24[];\n}\n\nfunction blobsToSingleBlob({ pages, ...rest }: StoryV23): StoryV24 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV23): PageV24 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV23): UnionElementV24 {\n  if (element?.mask?.type && element?.mask?.type.startsWith('blob-')) {\n    element.mask.type = 'blob';\n  }\n  return element;\n}\n\nexport default blobsToSingleBlob;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0025_singleAnimationTarget.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationV0 } from '../types';\nimport type {\n  GifElementV24,\n  ImageElementV24,\n  PageV24,\n  ProductElementV24,\n  ShapeElementV24,\n  StoryV24,\n  TextElementV24,\n  VideoElementV24,\n} from './v0024_blobsToSingleBlob';\n\nexport type TextElementV25 = TextElementV24;\nexport type ProductElementV25 = ProductElementV24;\nexport type ShapeElementV25 = ShapeElementV24;\nexport type ImageElementV25 = ImageElementV24;\nexport type VideoElementV25 = VideoElementV24;\nexport type GifElementV25 = GifElementV24;\n\nexport type UnionElementV25 =\n  | ShapeElementV25\n  | ImageElementV25\n  | VideoElementV25\n  | GifElementV25\n  | TextElementV25\n  | ProductElementV25;\n\nexport interface StoryV25 extends Omit<StoryV24, 'pages'> {\n  pages: PageV25[];\n}\nexport interface PageV25 extends Omit<PageV24, 'elements'> {\n  elements: UnionElementV25[];\n}\n\nfunction singleAnimationTarget({ pages, ...rest }: StoryV24): StoryV25 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ animations, ...rest }: PageV24): PageV25 {\n  return {\n    animations: (animations || []).reduce(updateAnimation, []),\n    ...rest,\n  };\n}\n\nfunction updateAnimation(animations: AnimationV0[], animation: AnimationV0) {\n  const { targets, id, ...rest } = animation;\n  targets.forEach((target, i) => {\n    animations.push({\n      id: i === 0 ? id : uuidv4(),\n      targets: [target],\n      ...rest,\n    });\n  });\n  return animations;\n}\n\nexport default singleAnimationTarget;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0026_backgroundOverlayToOverlay.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Pattern } from '../types/pattern';\nimport type {\n  GifElementV25,\n  ImageElementV25,\n  PageV25,\n  ProductElementV25,\n  ShapeElementV25,\n  StoryV25,\n  TextElementV25,\n  UnionElementV25,\n  VideoElementV25,\n} from './v0025_singleAnimationTarget';\n\nexport type TextElementV26 = TextElementV25;\nexport type ProductElementV26 = ProductElementV25;\n\nexport interface ShapeElementV26 extends Omit<\n  ShapeElementV25,\n  'backgroundOverlay'\n> {\n  overlay?: Pattern | null;\n}\nexport interface ImageElementV26 extends Omit<\n  ImageElementV25,\n  'backgroundOverlay'\n> {\n  overlay?: Pattern | null;\n}\nexport interface VideoElementV26 extends Omit<\n  VideoElementV25,\n  'backgroundOverlay'\n> {\n  overlay?: Pattern | null;\n}\nexport interface GifElementV26 extends Omit<\n  GifElementV25,\n  'backgroundOverlay'\n> {\n  overlay?: Pattern | null;\n}\n\nexport type UnionElementV26 =\n  | ShapeElementV26\n  | ImageElementV26\n  | VideoElementV26\n  | GifElementV26\n  | TextElementV26\n  | ProductElementV26;\n\nexport interface StoryV26 extends Omit<StoryV25, 'pages'> {\n  pages: PageV26[];\n}\nexport interface PageV26 extends Omit<PageV25, 'elements'> {\n  elements: UnionElementV26[];\n}\n\nfunction backgroundOverlayToOverlay({ pages, ...rest }: StoryV25): StoryV26 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV25): PageV26 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV25): UnionElementV26 {\n  if ('backgroundOverlay' in element) {\n    const { backgroundOverlay, ...rest } = element;\n    return {\n      ...rest,\n      overlay: backgroundOverlay,\n    };\n  }\n  return element;\n}\n\nexport default backgroundOverlayToOverlay;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0027_videoDuration.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType, ResourceV0 } from '../types';\nimport type {\n  GifElementV26,\n  ImageElementV26,\n  PageV26,\n  ProductElementV26,\n  ShapeElementV26,\n  StoryV26,\n  TextElementV26,\n  UnionElementV26,\n  VideoElementV26,\n} from './v0026_backgroundOverlayToOverlay';\n\nexport type TextElementV27 = TextElementV26;\nexport type ProductElementV27 = ProductElementV26;\nexport type ShapeElementV27 = ShapeElementV26;\nexport type ImageElementV27 = ImageElementV26;\n\ninterface VideoResourceV26 extends ResourceV0 {\n  poster?: string;\n  posterId?: number;\n  id?: number;\n  type: ResourceType.Video;\n  lengthFormatted?: string;\n  length?: number;\n  isOptimized?: boolean;\n}\nexport interface VideoElementV27 extends Omit<VideoElementV26, 'resource'> {\n  resource: VideoResourceV26;\n}\nexport type GifElementV27 = GifElementV26;\n\nexport type UnionElementV27 =\n  | ShapeElementV27\n  | ImageElementV27\n  | VideoElementV27\n  | GifElementV27\n  | TextElementV27\n  | ProductElementV27;\n\nexport interface StoryV27 extends Omit<StoryV26, 'pages'> {\n  pages: PageV27[];\n}\nexport interface PageV27 extends Omit<PageV26, 'elements'> {\n  elements: UnionElementV27[];\n}\n\nfunction videoDuration({ pages, ...rest }: StoryV26): StoryV27 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV26): PageV27 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV26): UnionElementV27 {\n  if (\n    'resource' in element &&\n    element.resource.type === ('video' as ResourceType.Video) &&\n    element.resource &&\n    element.resource.lengthFormatted\n  ) {\n    let length = 0;\n    const times = element.resource.lengthFormatted.split(':');\n    const timesNumbers = times.map(Number);\n    if (timesNumbers.length === 2) {\n      const [minutes, seconds] = timesNumbers;\n      length = 60 * minutes + seconds;\n    } else if (timesNumbers.length === 3) {\n      const [hours, minutes, seconds] = timesNumbers;\n      length = 60 * 60 * hours + 60 * minutes + seconds;\n    }\n    const { resource } = element;\n    return {\n      ...element,\n      resource: {\n        ...resource,\n        length,\n      },\n    } as VideoElementV27;\n  }\n  return element as UnionElementV27;\n}\n\nexport default videoDuration;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0028_mark3pVideoAsOptimized.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType, ResourceV0 } from '../types';\nimport type {\n  GifElementV27,\n  ImageElementV27,\n  PageV27,\n  ProductElementV27,\n  ShapeElementV27,\n  StoryV27,\n  TextElementV27,\n  UnionElementV27,\n  VideoElementV27,\n} from './v0027_videoDuration';\n\nexport type TextElementV28 = TextElementV27;\nexport type ProductElementV28 = ProductElementV27;\nexport type ShapeElementV28 = ShapeElementV27;\nexport type ImageElementV28 = ImageElementV27;\nexport type GifElementV28 = GifElementV27;\n\ninterface VideoResource28 extends ResourceV0 {\n  poster?: string;\n  posterId?: number;\n  id?: number;\n  type: ResourceType.Video;\n  lengthFormatted?: string;\n  length?: number;\n  isOptimized?: boolean;\n}\nexport interface VideoElementV28 extends Omit<VideoElementV27, 'resource'> {\n  resource: VideoResource28;\n}\n\nexport type UnionElementV28 =\n  | ShapeElementV28\n  | ImageElementV28\n  | VideoElementV28\n  | GifElementV28\n  | TextElementV28\n  | ProductElementV28;\n\nexport interface StoryV28 extends Omit<StoryV27, 'pages'> {\n  pages: PageV28[];\n}\nexport interface PageV28 extends Omit<PageV27, 'elements'> {\n  elements: UnionElementV28[];\n}\n\nfunction mark3pVideoAsOptimized({ pages, ...rest }: StoryV27): StoryV28 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV27): PageV28 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV27): UnionElementV28 {\n  if (\n    'resource' in element &&\n    element.resource.type === ('video' as ResourceType.Video) &&\n    element.resource?.id\n  ) {\n    const resourceId = element.resource.id.toString();\n    const isCoverrMedia = resourceId.startsWith('media/coverr');\n    if (isCoverrMedia) {\n      return {\n        ...element,\n        resource: {\n          ...element.resource,\n          isOptimized: true,\n        },\n      } as VideoElementV28;\n    }\n  }\n  return element;\n}\n\nexport default mark3pVideoAsOptimized;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0029_unifyGifResources.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceType, ResourceV0 } from '../types';\nimport type {\n  GifElementV28,\n  ImageElementV28,\n  PageV28,\n  ProductElementV28,\n  ShapeElementV28,\n  StoryV28,\n  TextElementV28,\n  UnionElementV28,\n  VideoElementV28,\n} from './v0028_mark3pVideoAsOptimized';\n\nexport type TextElementV29 = TextElementV28;\nexport type ProductElementV29 = ProductElementV28;\nexport type ShapeElementV29 = ShapeElementV28;\nexport type ImageElementV29 = ImageElementV28;\nexport type VideoElementV29 = VideoElementV28;\n\nexport interface GifResourceV29 extends ResourceV0 {\n  type: ResourceType.Gif;\n  output: {\n    mimeType: string;\n    src: string;\n  };\n  isTrimming?: boolean;\n  isTranscoding?: boolean;\n  isMuting?: boolean;\n  title: string;\n  isOptimized?: boolean;\n  posterId: string;\n  poster?: string;\n  id: string;\n}\nexport interface GifElementV29 extends Omit<GifElementV28, 'resource'> {\n  resource: GifResourceV29;\n}\n\nexport type UnionElementV29 =\n  | ShapeElementV29\n  | ImageElementV29\n  | VideoElementV29\n  | GifElementV29\n  | TextElementV29\n  | ProductElementV29;\n\nexport interface StoryV29 extends Omit<StoryV28, 'pages'> {\n  pages: PageV29[];\n}\nexport interface PageV29 extends Omit<PageV28, 'elements'> {\n  elements: UnionElementV29[];\n}\n\nfunction unifyGifResources({ pages, ...rest }: StoryV28): StoryV29 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV28): PageV29 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV28): UnionElementV29 {\n  if (!('resource' in element)) {\n    return element;\n  }\n\n  if (element.resource.type !== ('gif' as ResourceType.Gif)) {\n    return element as UnionElementV29;\n  }\n\n  if ('id' in element.resource && 'posterId' in element.resource) {\n    return element as UnionElementV29;\n  }\n\n  const { sizes, poster, ...output } = element.resource.output;\n  return {\n    ...element,\n    resource: {\n      ...element.resource,\n      id: element.resource.alt,\n      posterId: element.resource.alt,\n      poster: element.resource.output?.poster\n        ? element.resource.output.poster\n        : undefined,\n      isOptimized: true,\n      output,\n    },\n  };\n}\n\nexport default unifyGifResources;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0030_mark3pVideoAsMuted.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceV0, ResourceType } from '../types';\nimport type {\n  GifElementV29,\n  ImageElementV29,\n  PageV29,\n  ProductElementV29,\n  ShapeElementV29,\n  StoryV29,\n  TextElementV29,\n  UnionElementV29,\n  VideoElementV29,\n} from './v0029_unifyGifResources';\n\nexport type TextElementV30 = TextElementV29;\nexport type ProductElementV30 = ProductElementV29;\nexport type ShapeElementV30 = ShapeElementV29;\nexport type ImageElementV30 = ImageElementV29;\n\nexport interface VideoResourceV30 extends ResourceV0 {\n  poster?: string;\n  posterId?: number;\n  id?: number;\n  type: ResourceType.Video;\n  lengthFormatted?: string;\n  length?: number;\n  isOptimized?: boolean;\n  isMuted?: boolean;\n}\nexport interface VideoElementV30 extends Omit<VideoElementV29, 'resource'> {\n  resource: VideoResourceV30;\n}\nexport type GifElementV30 = GifElementV29;\n\nexport type UnionElementV30 =\n  | ShapeElementV30\n  | ImageElementV30\n  | VideoElementV30\n  | GifElementV30\n  | TextElementV30\n  | ProductElementV30;\n\nexport interface StoryV30 extends Omit<StoryV29, 'pages'> {\n  pages: PageV30[];\n}\nexport interface PageV30 extends Omit<PageV29, 'elements'> {\n  elements: UnionElementV30[];\n}\n\nfunction mark3pVideoAsMuted({ pages, ...rest }: StoryV29): StoryV30 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV29): PageV30 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV29): UnionElementV30 {\n  if (\n    'resource' in element &&\n    'id' in element.resource &&\n    element.type === 'video' &&\n    element.resource?.id\n  ) {\n    const resourceId = element.resource.id.toString();\n    const isCoverrMedia = resourceId.startsWith('media/coverr');\n    if (isCoverrMedia) {\n      return {\n        ...element,\n        resource: {\n          ...element.resource,\n          isMuted: true,\n        },\n      } as VideoElementV30;\n    }\n  }\n  return element;\n}\n\nexport default mark3pVideoAsMuted;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0031_normalizeResourceSizes.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ResourceV0 } from '../types';\nimport type {\n  GifElementV30,\n  ImageElementV30,\n  PageV30,\n  ProductElementV30,\n  ShapeElementV30,\n  StoryV30,\n  TextElementV30,\n  UnionElementV30,\n  VideoElementV30,\n  VideoResourceV30,\n} from './v0030_mark3pVideoAsMuted';\nimport type { GifResourceV29 } from './v0029_unifyGifResources';\n\ninterface Size {\n  width: number;\n  height: number;\n  source_url: string;\n}\nexport interface ResourceV31 extends Omit<ResourceV0, 'sizes'> {\n  sizes: Record<string, Size>;\n}\n\nexport type TextElementV31 = TextElementV30;\nexport type ProductElementV31 = ProductElementV30;\nexport type ShapeElementV31 = ShapeElementV30;\nexport type ImageResourceV31 = ResourceV31;\nexport interface ImageElementV31 extends Omit<ImageElementV30, 'resource'> {\n  resource: ImageResourceV31;\n}\n\nexport interface VideoResourceV31 extends Omit<VideoResourceV30, 'sizes'> {\n  sizes: Record<string, Size>;\n}\nexport interface VideoElementV31 extends Omit<VideoElementV30, 'resource'> {\n  resource: VideoResourceV31;\n}\n\nexport interface GifResourceV31 extends Omit<GifResourceV29, 'resource'> {\n  sizes: Record<string, Size>;\n}\nexport interface GifElementV31 extends Omit<GifElementV30, 'resource'> {\n  resource: GifResourceV31;\n}\n\nexport type UnionElementV31 =\n  | ShapeElementV31\n  | ImageElementV31\n  | VideoElementV31\n  | GifElementV31\n  | TextElementV31\n  | ProductElementV31;\n\nexport interface StoryV31 extends Omit<StoryV30, 'pages'> {\n  pages: PageV31[];\n}\nexport interface PageV31 extends Omit<PageV30, 'elements'> {\n  elements: UnionElementV31[];\n}\n\nfunction normalizeResourceSizes({ pages, ...rest }: StoryV30): StoryV31 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV30): PageV31 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV30): UnionElementV31 {\n  if ('resource' in element) {\n    element.resource.width = Number(element.resource.width);\n    element.resource.height = Number(element.resource.height);\n\n    if ('sizes' in element.resource && element.resource.sizes) {\n      for (const size of Object.keys(element.resource.sizes)) {\n        // Disable reason: not acting on untrusted user input.\n        const data = element.resource.sizes[size];\n        element.resource.sizes[size] = {\n          ...data,\n          width: Number(data.width),\n          height: Number(data.height),\n        };\n      }\n    }\n  }\n\n  return element as UnionElementV31;\n}\n\nexport default normalizeResourceSizes;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0032_pageOutlinkTheme.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV31,\n  GifResourceV31,\n  ImageElementV31,\n  ImageResourceV31,\n  PageV31,\n  ProductElementV31,\n  ShapeElementV31,\n  StoryV31,\n  TextElementV31,\n  VideoElementV31,\n  VideoResourceV31,\n} from './v0031_normalizeResourceSizes';\n\nexport type TextElementV32 = TextElementV31;\nexport type ProductElementV32 = ProductElementV31;\nexport type ShapeElementV32 = ShapeElementV31;\nexport type ImageElementV32 = ImageElementV31;\nexport type ImageResourceV32 = ImageResourceV31;\nexport type VideoElementV32 = VideoElementV31;\nexport type VideoResourceV32 = VideoResourceV31;\nexport type GifElementV32 = GifElementV31;\nexport type GifResourceV32 = GifResourceV31;\n\nexport type UnionElementV32 =\n  | ShapeElementV32\n  | ImageElementV32\n  | VideoElementV32\n  | GifElementV32\n  | TextElementV32\n  | ProductElementV32;\n\nexport interface StoryV32 extends Omit<StoryV31, 'pages'> {\n  pages: PageV32[];\n}\nexport interface PageV32 extends Omit<PageV31, 'elements' | 'pageAttachment'> {\n  elements: UnionElementV32[];\n  pageAttachment?: {\n    url: string;\n    ctaText?: string;\n    theme?: string;\n  };\n}\n\nfunction pageOutlinkTheme({ pages, ...rest }: StoryV31): StoryV32 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage(page: PageV31): PageV32 {\n  const { pageAttachment } = page;\n  if (!pageAttachment) {\n    return page;\n  }\n\n  if ('theme' in pageAttachment) {\n    return page;\n  }\n  return {\n    ...page,\n    pageAttachment: {\n      ...pageAttachment,\n      theme: 'light',\n    },\n  };\n}\n\nexport default pageOutlinkTheme;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0033_removeTitleFromResources.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV32,\n  GifResourceV32,\n  ImageElementV32,\n  ImageResourceV32,\n  PageV32,\n  ProductElementV32,\n  ShapeElementV32,\n  StoryV32,\n  TextElementV32,\n  UnionElementV32,\n  VideoElementV32,\n  VideoResourceV32,\n} from './v0032_pageOutlinkTheme';\n\nexport type TextElementV33 = TextElementV32;\nexport type ProductElementV33 = ProductElementV32;\nexport type ShapeElementV33 = ShapeElementV32;\nexport type ImageResourceV33 = Omit<ImageResourceV32, 'title'>;\nexport interface ImageElementV33 extends Omit<ImageElementV32, 'resource'> {\n  resource: ImageResourceV33;\n}\n\nexport type VideoResourceV33 = Omit<VideoResourceV32, 'title'>;\nexport interface VideoElementV33 extends Omit<VideoElementV32, 'resource'> {\n  resource: VideoResourceV33;\n}\n\nexport type GifResourceV33 = Omit<GifResourceV32, 'title'>;\nexport interface GifElementV33 extends Omit<GifElementV32, 'resource'> {\n  resource: GifResourceV33;\n}\n\nexport type UnionElementV33 =\n  | ShapeElementV33\n  | ImageElementV33\n  | VideoElementV33\n  | GifElementV33\n  | TextElementV33\n  | ProductElementV33;\n\nexport interface StoryV33 extends Omit<StoryV32, 'pages'> {\n  pages: PageV33[];\n}\nexport interface PageV33 extends Omit<PageV32, 'elements'> {\n  elements: UnionElementV33[];\n}\n\nfunction removeTitleFromResources({ pages, ...rest }: StoryV32): StoryV33 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV32): PageV33 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV32): UnionElementV33 {\n  if ('resource' in element && element.resource?.title) {\n    delete element.resource?.title;\n  }\n\n  return element;\n}\n\nexport default removeTitleFromResources;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0034_removeUnusedBackgroundProps.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV33,\n  ImageResourceV33,\n  VideoResourceV33,\n  GifElementV33,\n  ImageElementV33,\n  PageV33,\n  ProductElementV33,\n  ShapeElementV33,\n  StoryV33,\n  TextElementV33,\n  UnionElementV33,\n  VideoElementV33,\n} from './v0033_removeTitleFromResources';\n\nexport type TextElementV34 = TextElementV33;\nexport type ProductElementV34 = ProductElementV33;\nexport type ShapeElementV34 = ShapeElementV33;\nexport type ImageElementV34 = ImageElementV33;\nexport type VideoElementV34 = VideoElementV33;\nexport type GifElementV34 = GifElementV33;\n\nexport type ImageResourceV34 = ImageResourceV33;\nexport type VideoResourceV34 = VideoResourceV33;\nexport type GifResourceV34 = GifResourceV33;\n\nexport type UnionElementV34 =\n  | ShapeElementV34\n  | ImageElementV34\n  | VideoElementV34\n  | GifElementV34\n  | TextElementV34\n  | ProductElementV34;\n\nexport interface StoryV34 extends Omit<StoryV33, 'pages'> {\n  pages: PageV34[];\n}\nexport interface PageV34 extends Omit<PageV33, 'elements' | 'overlay'> {\n  elements: UnionElementV34[];\n}\n\nfunction removeUnusedBackgroundProps({ pages, ...rest }: StoryV33): StoryV34 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, overlay, ...rest }: PageV33): PageV34 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV33): UnionElementV34 {\n  if ('isDefaultBackground' in element && element.isDefaultBackground) {\n    const { backgroundColor, ...rest } = element;\n    return rest;\n  }\n\n  return element;\n}\n\nexport default removeUnusedBackgroundProps;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0035_markVideoAsExternal.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV34,\n  ImageResourceV34,\n  VideoResourceV34,\n  GifElementV34,\n  ImageElementV34,\n  PageV34,\n  ProductElementV34,\n  ShapeElementV34,\n  StoryV34,\n  TextElementV34,\n  UnionElementV34,\n  VideoElementV34,\n} from './v0034_removeUnusedBackgroundProps';\n\nexport type TextElementV35 = TextElementV34;\nexport type ProductElementV35 = ProductElementV34;\nexport type ShapeElementV35 = Omit<ShapeElementV34, 'isDefaultBackground'>;\n\nexport interface ImageResourceV35 extends ImageResourceV34 {\n  isExternal?: boolean;\n}\nexport interface VideoResourceV35 extends VideoResourceV34 {\n  isExternal?: boolean;\n}\nexport interface GifResourceV35 extends GifResourceV34 {\n  isExternal?: boolean;\n}\n\nexport interface ImageElementV35 extends Omit<ImageElementV34, 'resource'> {\n  resource: ImageResourceV35;\n}\nexport interface VideoElementV35 extends Omit<VideoElementV34, 'resource'> {\n  resource: VideoResourceV35;\n}\nexport interface GifElementV35 extends Omit<GifElementV34, 'resource'> {\n  resource: GifResourceV35;\n}\n\nexport type UnionElementV35 =\n  | ShapeElementV35\n  | ImageElementV35\n  | VideoElementV35\n  | GifElementV35\n  | TextElementV35\n  | ProductElementV35;\n\nexport interface StoryV35 extends Omit<StoryV34, 'pages'> {\n  pages: PageV35[];\n}\nexport interface PageV35 extends Omit<PageV34, 'elements'> {\n  elements: UnionElementV35[];\n}\n\nfunction markVideoAsExternal({ pages, ...rest }: StoryV34): StoryV35 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV34): PageV35 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV34): UnionElementV35 {\n  if ('resource' in element) {\n    if ('id' in element.resource && element.resource.id) {\n      const resourceId = element.resource.id.toString();\n      const is3pMedia = resourceId.startsWith('media/');\n      return {\n        ...element,\n        resource: {\n          ...element.resource,\n          isExternal: is3pMedia,\n        },\n      };\n    } else {\n      return {\n        ...element,\n        resource: {\n          ...element.resource,\n          isExternal: true,\n        },\n      };\n    }\n  }\n  return element;\n}\n\nexport default markVideoAsExternal;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0036_changeBaseColorToHex.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV35,\n  ImageResourceV35,\n  VideoResourceV35,\n  GifElementV35,\n  ImageElementV35,\n  PageV35,\n  ProductElementV35,\n  ShapeElementV35,\n  StoryV35,\n  TextElementV35,\n  UnionElementV35,\n  VideoElementV35,\n} from './v0035_markVideoAsExternal';\n\nexport type TextElementV36 = TextElementV35;\nexport type ProductElementV36 = ProductElementV35;\nexport type ShapeElementV36 = Omit<ShapeElementV35, 'isDefaultBackground'>;\nexport interface ImageResourceV36 extends Omit<ImageResourceV35, 'baseColor'> {\n  baseColor?: string;\n}\nexport interface VideoResourceV36 extends Omit<VideoResourceV35, 'baseColor'> {\n  baseColor?: string;\n}\nexport interface GifResourceV36 extends Omit<GifResourceV35, 'baseColor'> {\n  baseColor?: string;\n}\n\nexport interface ImageElementV36 extends Omit<ImageElementV35, 'resource'> {\n  resource: ImageResourceV36;\n}\nexport interface VideoElementV36 extends Omit<VideoElementV35, 'resource'> {\n  resource: VideoResourceV36;\n}\nexport interface GifElementV36 extends Omit<GifElementV35, 'resource'> {\n  resource: GifResourceV36;\n}\n\nexport type UnionElementV36 =\n  | ShapeElementV36\n  | ImageElementV36\n  | VideoElementV36\n  | GifElementV36\n  | TextElementV36\n  | ProductElementV36;\n\nexport interface StoryV36 extends Omit<StoryV35, 'pages'> {\n  pages: PageV36[];\n}\nexport interface PageV36 extends Omit<PageV35, 'elements'> {\n  elements: UnionElementV36[];\n}\n\nfunction changeBaseColorToHex({ pages, ...rest }: StoryV35): StoryV36 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV35): PageV36 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction getHexFromSolidArray(baseColor: number[]): string {\n  const color = baseColor\n    .map((n) => n.toString(16))\n    .map((s) => s.padStart(2, '0'))\n    .join('');\n  return `#${color}`;\n}\n\nfunction updateElement(element: UnionElementV35): UnionElementV36 {\n  if (!('resource' in element)) {\n    return element;\n  }\n  if (\n    'baseColor' in element.resource &&\n    Array.isArray(element.resource.baseColor)\n  ) {\n    return {\n      ...element,\n      resource: {\n        ...element.resource,\n        baseColor: getHexFromSolidArray(element?.resource?.baseColor),\n      },\n    };\n  }\n  return element as UnionElementV36;\n}\n\nexport default changeBaseColorToHex;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0037_removeTransientMediaProperties.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV36,\n  ImageResourceV36,\n  VideoResourceV36,\n  GifElementV36,\n  ImageElementV36,\n  PageV36,\n  ProductElementV36,\n  ShapeElementV36,\n  StoryV36,\n  TextElementV36,\n  UnionElementV36,\n  VideoElementV36,\n} from './v0036_changeBaseColorToHex';\n\nexport type TextElementV37 = TextElementV36;\nexport type ProductElementV37 = ProductElementV36;\nexport type ShapeElementV37 = Omit<ShapeElementV36, 'isDefaultBackground'>;\n\nexport interface ImageResourceV37 extends ImageResourceV36 {\n  isExternal?: boolean;\n}\nexport interface VideoResourceV37 extends VideoResourceV36 {\n  isExternal?: boolean;\n}\nexport interface GifResourceV37 extends GifResourceV36 {\n  isExternal?: boolean;\n}\n\nexport interface ImageElementV37 extends Omit<ImageElementV36, 'resource'> {\n  resource: ImageResourceV37;\n}\nexport interface VideoElementV37 extends Omit<VideoElementV36, 'resource'> {\n  resource: VideoResourceV37;\n}\nexport interface GifElementV37 extends Omit<GifElementV36, 'resource'> {\n  resource: GifResourceV37;\n}\n\nexport type UnionElementV37 =\n  | ShapeElementV37\n  | ImageElementV37\n  | VideoElementV37\n  | GifElementV37\n  | TextElementV37\n  | ProductElementV37;\n\nexport interface StoryV37 extends Omit<StoryV36, 'pages'> {\n  pages: PageV37[];\n}\nexport interface PageV37 extends Omit<PageV36, 'elements'> {\n  elements: UnionElementV37[];\n}\n\nfunction removeTransientMediaProperties({\n  pages,\n  ...rest\n}: StoryV36): StoryV37 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV36): PageV37 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV36): UnionElementV37 {\n  if (!('resource' in element)) {\n    return element;\n  }\n\n  delete element.resource.local;\n  delete element.resource.isTrimming;\n  delete element.resource.isTranscoding;\n  delete element.resource.isMuting;\n\n  return element;\n}\n\nexport default removeTransientMediaProperties;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0038_camelCaseResourceSizes.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV37,\n  ImageResourceV37,\n  VideoResourceV37,\n  GifElementV37,\n  ImageElementV37,\n  PageV37,\n  ProductElementV37,\n  ShapeElementV37,\n  StoryV37,\n  TextElementV37,\n  UnionElementV37,\n  VideoElementV37,\n} from './v0037_removeTransientMediaProperties';\n\nexport type TextElementV38 = TextElementV37;\nexport type ProductElementV38 = ProductElementV37;\nexport type ShapeElementV38 = Omit<ShapeElementV37, 'isDefaultBackground'>;\n\nexport interface ImageResourceV38 extends Omit<ImageResourceV37, 'sizes'> {\n  sizes: Record<string, CamelCaseSize>;\n}\nexport interface VideoResourceV38 extends Omit<VideoResourceV37, 'sizes'> {\n  sizes: Record<string, CamelCaseSize>;\n}\nexport interface GifResourceV38 extends Omit<GifResourceV37, 'sizes'> {\n  sizes: Record<string, CamelCaseSize>;\n}\n\nexport interface ImageElementV38 extends Omit<ImageElementV37, 'resource'> {\n  resource: ImageResourceV38;\n}\nexport interface VideoElementV38 extends Omit<VideoElementV37, 'resource'> {\n  resource: VideoResourceV38;\n}\nexport interface GifElementV38 extends Omit<GifElementV37, 'resource'> {\n  resource: GifResourceV38;\n}\n\nexport type UnionElementV38 =\n  | ShapeElementV38\n  | ImageElementV38\n  | VideoElementV38\n  | GifElementV38\n  | TextElementV38\n  | ProductElementV38;\n\ninterface Size {\n  file: string;\n  source_url: string;\n  mime_type: string;\n  width: number;\n  height: number;\n}\n\ninterface CamelCaseSize {\n  [index: string]: string | number;\n  file: string;\n  sourceUrl: string;\n  mimeType: string;\n  width: number;\n  height: number;\n}\n\nexport interface StoryV38 extends Omit<StoryV37, 'pages'> {\n  pages: PageV38[];\n}\nexport interface PageV38 extends Omit<PageV37, 'elements'> {\n  elements: UnionElementV38[];\n}\n\nfunction camelCaseResourceSizes({ pages, ...rest }: StoryV37): StoryV38 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV37): PageV38 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction snakeToCamelCase(string = ''): string {\n  if (!string.includes('_') && !string.includes('-')) {\n    return string;\n  }\n\n  return string\n    .toLowerCase()\n    .replace(\n      /([a-z])([_|-][a-z])/g,\n      (_match, group1: string, group2: string) =>\n        group1 + group2.toUpperCase().replace('_', '').replace('-', '')\n    );\n}\n\ntype Key = keyof CamelCaseSize;\nfunction snakeToCamelCaseObjectKeys(obj: Size): CamelCaseSize {\n  return Object.entries(obj).reduce(\n    (_obj: CamelCaseSize, [key, value]: [string, string | number]) => {\n      _obj[snakeToCamelCase(key) as Key] = value;\n      return _obj;\n    },\n    {} as CamelCaseSize\n  );\n}\n\nfunction updateElement(element: UnionElementV37): UnionElementV38 {\n  if (\n    'resource' in element &&\n    'sizes' in element.resource &&\n    element.resource.sizes\n  ) {\n    const sizes: Record<string, CamelCaseSize> = {};\n    for (const [key, value] of Object.entries(element.resource.sizes)) {\n      sizes[key] = snakeToCamelCaseObjectKeys(value as Size);\n    }\n    return {\n      ...element,\n      resource: {\n        ...element.resource,\n        sizes,\n      },\n    };\n  }\n  return element as UnionElementV38;\n}\n\nexport default camelCaseResourceSizes;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0039_backgroundAudioFormatting.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV38,\n  ImageResourceV38,\n  VideoResourceV38,\n  GifElementV38,\n  ImageElementV38,\n  PageV38,\n  ProductElementV38,\n  ShapeElementV38,\n  StoryV38,\n  TextElementV38,\n  VideoElementV38,\n} from './v0038_camelCaseResourceSizes';\n\nexport type TextElementV39 = TextElementV38;\nexport type ProductElementV39 = ProductElementV38;\nexport type ShapeElementV39 = ShapeElementV38;\nexport type ImageElementV39 = ImageElementV38;\nexport type VideoElementV39 = VideoElementV38;\nexport type GifElementV39 = GifElementV38;\n\nexport type ImageResourceV39 = ImageResourceV38;\nexport type VideoResourceV39 = VideoResourceV38;\nexport type GifResourceV39 = GifResourceV38;\n\nexport type UnionElementV39 =\n  | ShapeElementV39\n  | ImageElementV39\n  | VideoElementV39\n  | GifElementV39\n  | TextElementV39\n  | ProductElementV39;\n\nexport interface AudioTrackV39 {\n  track: string;\n  trackId: number;\n  trackName: string;\n  id: string;\n  srcLang?: string;\n  label?: string;\n  kind: string;\n}\n\ninterface BackgroundAudioResource {\n  src: string;\n  id: number;\n  mimeType: string;\n}\nexport interface BackgroundAudioV39 {\n  resource: BackgroundAudioResource;\n  tracks?: AudioTrackV39[];\n  loop?: boolean;\n}\nexport interface StoryV39 extends Omit<StoryV38, 'pages' | 'backgroundAudio'> {\n  pages: PageV39[];\n  backgroundAudio?: {\n    resource: BackgroundAudioResource;\n  };\n}\nexport interface PageV39 extends Omit<PageV38, 'elements' | 'backgroundAudio'> {\n  elements: UnionElementV39[];\n  backgroundAudio?: BackgroundAudioV39;\n}\n\nfunction backgroundAudioFormatting(storyData: StoryV38): StoryV39 {\n  const { pages, backgroundAudio, ...rest } = storyData;\n  return {\n    pages: pages.map(updatePage),\n    ...(backgroundAudio\n      ? {\n          backgroundAudio: {\n            resource: backgroundAudio as BackgroundAudioResource,\n          },\n        }\n      : null),\n    ...rest,\n  };\n}\n\nfunction updatePage(page: PageV38): PageV39 {\n  const { backgroundAudio } = page;\n  if (backgroundAudio !== undefined) {\n    return {\n      ...page,\n      backgroundAudio: {\n        resource: page.backgroundAudio as BackgroundAudioResource,\n        loop: true,\n        tracks: [],\n      },\n    };\n  }\n  return page as PageV39;\n}\n\nexport default backgroundAudioFormatting;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0040_andadaFontToAndadaPro.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV39,\n  ImageResourceV39,\n  VideoResourceV39,\n  GifElementV39,\n  ImageElementV39,\n  PageV39,\n  ProductElementV39,\n  ShapeElementV39,\n  StoryV39,\n  TextElementV39,\n  UnionElementV39,\n  VideoElementV39,\n} from './v0039_backgroundAudioFormatting';\n\nexport type TextElementV40 = TextElementV39;\nexport type ProductElementV40 = ProductElementV39;\nexport type ShapeElementV40 = ShapeElementV39;\nexport type ImageElementV40 = ImageElementV39;\nexport type VideoElementV40 = VideoElementV39;\nexport type GifElementV40 = GifElementV39;\n\nexport type ImageResourceV40 = ImageResourceV39;\nexport type VideoResourceV40 = VideoResourceV39;\nexport type GifResourceV40 = GifResourceV39;\n\nexport type UnionElementV40 =\n  | ShapeElementV40\n  | ImageElementV40\n  | VideoElementV40\n  | GifElementV40\n  | TextElementV40\n  | ProductElementV40;\n\nexport interface StoryV40 extends Omit<StoryV39, 'pages'> {\n  pages: PageV40[];\n}\nexport interface PageV40 extends Omit<PageV39, 'elements'> {\n  elements: UnionElementV40[];\n}\n\nfunction andadaFontToAndadaPro({ pages, ...rest }: StoryV39): StoryV40 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV39): PageV40 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nconst andadaPro = {\n  family: 'Andada Pro',\n  fallbacks: ['serif'],\n  weights: [400, 500, 600, 700, 800],\n  styles: ['regular', 'italic'],\n  variants: [\n    [0, 400],\n    [0, 500],\n    [0, 600],\n    [0, 700],\n    [0, 800],\n    [1, 400],\n    [1, 500],\n    [1, 600],\n    [1, 700],\n    [1, 800],\n  ],\n  service: 'fonts.google.com',\n  metrics: {\n    upm: 1000,\n    asc: 942,\n    des: -235,\n    tAsc: 942,\n    tDes: -235,\n    tLGap: 0,\n    wAsc: 1100,\n    wDes: 390,\n    xH: 494,\n    capH: 705,\n    yMin: -382,\n    yMax: 1068,\n    hAsc: 942,\n    hDes: -235,\n    lGap: 0,\n  },\n};\n\nfunction updateElement(element: UnionElementV39): UnionElementV40 {\n  if ('font' in element && element.font?.family === 'Andada') {\n    element.font = {\n      ...element.font,\n      ...andadaPro,\n    };\n  }\n  return element;\n}\n\nexport default andadaFontToAndadaPro;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0041_removeFontProperties.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV40,\n  ImageResourceV40,\n  VideoResourceV40,\n  GifElementV40,\n  ImageElementV40,\n  PageV40,\n  ProductElementV40,\n  ShapeElementV40,\n  StoryV40,\n  TextElementV40,\n  UnionElementV40,\n  VideoElementV40,\n} from './v0040_andadaFontToAndadaPro';\n\nexport interface TextElementV41 extends Omit<TextElementV40, 'font'> {\n  font: {\n    service: string;\n    family: string;\n    fallbacks: string[];\n  };\n}\nexport type ProductElementV41 = ProductElementV40;\nexport type ShapeElementV41 = ShapeElementV40;\nexport type ImageElementV41 = ImageElementV40;\nexport type VideoElementV41 = VideoElementV40;\nexport type GifElementV41 = GifElementV40;\n\nexport type ImageResourceV41 = ImageResourceV40;\nexport type VideoResourceV41 = VideoResourceV40;\nexport type GifResourceV41 = GifResourceV40;\n\nexport type UnionElementV41 =\n  | ShapeElementV41\n  | ImageElementV41\n  | VideoElementV41\n  | GifElementV41\n  | TextElementV41\n  | ProductElementV41;\n\nexport interface StoryV41 extends Omit<StoryV40, 'pages'> {\n  pages: PageV41[];\n}\nexport interface PageV41 extends Omit<PageV40, 'elements'> {\n  elements: UnionElementV41[];\n}\n\nfunction removeFontProperties({ pages, ...rest }: StoryV40): StoryV41 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV40): PageV41 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV40): UnionElementV41 {\n  if ('font' in element) {\n    const { id, name, value, ...newFontFormatted } = element.font;\n    element.font = newFontFormatted;\n  }\n  return element;\n}\n\nexport default removeFontProperties;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0042_removeTrackName.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV41,\n  ImageResourceV41,\n  VideoResourceV41,\n  GifElementV41,\n  ImageElementV41,\n  PageV41,\n  ProductElementV41,\n  ShapeElementV41,\n  StoryV41,\n  TextElementV41,\n  VideoElementV41,\n} from './v0041_removeFontProperties';\n\n// @todo Should we now add Track version to each file instead?\nimport type { AudioTrackV39 } from './v0039_backgroundAudioFormatting';\n\nexport type TextElementV42 = TextElementV41;\nexport type ProductElementV42 = ProductElementV41;\nexport type ShapeElementV42 = ShapeElementV41;\nexport type ImageElementV42 = ImageElementV41;\nexport type VideoElementV42 = VideoElementV41;\nexport type GifElementV42 = GifElementV41;\n\nexport type ImageResourceV42 = ImageResourceV41;\nexport type VideoResourceV42 = VideoResourceV41;\nexport type GifResourceV42 = GifResourceV41;\n\nexport type UnionElementV42 =\n  | ShapeElementV42\n  | ImageElementV42\n  | VideoElementV42\n  | GifElementV42\n  | TextElementV42\n  | ProductElementV42;\n\nexport interface StoryV42 extends Omit<StoryV41, 'pages'> {\n  pages: PageV42[];\n}\n\ninterface Track {\n  track: string;\n  trackId: number;\n  id: string;\n  srcLang?: string;\n  label?: string;\n  kind: string;\n}\n\nexport interface PageV42 extends Omit<PageV41, 'elements' | 'backgroundAudio'> {\n  elements: UnionElementV42[];\n  backgroundAudio?: {\n    loop?: boolean;\n    resource: {\n      src: string;\n      id: number;\n      mimeType: string;\n    };\n    tracks?: Track[];\n  };\n}\n\nfunction removeTrackName(storyData: StoryV41): StoryV42 {\n  const { pages, ...rest } = storyData;\n  return {\n    pages: pages.map(updatePage),\n    ...rest,\n  };\n}\n\nfunction updatePage(page: PageV41): PageV42 {\n  if (\n    'backgroundAudio' in page &&\n    page.backgroundAudio &&\n    'tracks' in page.backgroundAudio &&\n    page.backgroundAudio.tracks\n  ) {\n    const tracks = page.backgroundAudio.tracks.map((track: AudioTrackV39) => {\n      const { trackName, ...rest } = track;\n      return rest;\n    });\n    return {\n      ...page,\n      backgroundAudio: {\n        ...page.backgroundAudio,\n        tracks,\n      },\n    };\n  }\n  return page;\n}\n\nexport default removeTrackName;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0043_removeTagNames.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV42,\n  ImageResourceV42,\n  VideoResourceV42,\n  GifElementV42,\n  ImageElementV42,\n  PageV42,\n  ProductElementV42,\n  ShapeElementV42,\n  StoryV42,\n  TextElementV42,\n  VideoElementV42,\n  UnionElementV42,\n} from './v0042_removeTrackName';\n\nexport type TextElementV43 = TextElementV42;\nexport type ProductElementV43 = ProductElementV42;\nexport type ShapeElementV43 = ShapeElementV42;\nexport type ImageElementV43 = ImageElementV42;\nexport type VideoElementV43 = VideoElementV42;\nexport type GifElementV43 = GifElementV42;\n\nexport type ImageResourceV43 = ImageResourceV42;\nexport type VideoResourceV43 = VideoResourceV42;\nexport type GifResourceV43 = GifResourceV42;\n\nexport type UnionElementV43 =\n  | ShapeElementV43\n  | ImageElementV43\n  | VideoElementV43\n  | GifElementV43\n  | TextElementV43\n  | ProductElementV43;\n\nexport interface StoryV43 extends Omit<StoryV42, 'pages'> {\n  pages: PageV43[];\n}\n\nexport interface PageV43 extends Omit<PageV42, 'elements'> {\n  elements: UnionElementV43[];\n}\n\nfunction removeTagNames({ pages, ...rest }: StoryV42): StoryV43 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV42): PageV43 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV42): UnionElementV43 {\n  if ('tagName' in element) {\n    const { tagName, ...rest } = element;\n    return rest;\n  }\n  return element;\n}\n\nexport default removeTagNames;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0044_unusedProperties.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV43,\n  ImageResourceV43,\n  VideoResourceV43,\n  GifElementV43,\n  ImageElementV43,\n  PageV43,\n  ProductElementV43,\n  ShapeElementV43,\n  StoryV43,\n  TextElementV43,\n  VideoElementV43,\n  UnionElementV43,\n} from './v0043_removeTagNames';\n\nexport type TextElementV44 = TextElementV43;\nexport type ProductElementV44 = ProductElementV43;\nexport type ShapeElementV44 = ShapeElementV43;\nexport type ImageElementV44 = ImageElementV43;\nexport type VideoElementV44 = VideoElementV43;\nexport type GifElementV44 = GifElementV43;\n\nexport type ImageResourceV44 = ImageResourceV43;\nexport type VideoResourceV44 = VideoResourceV43;\nexport type GifResourceV44 = GifResourceV43;\n\nexport type UnionElementV44 =\n  | ShapeElementV44\n  | ImageElementV44\n  | VideoElementV44\n  | GifElementV44\n  | TextElementV44\n  | ProductElementV44;\n\nexport interface StoryV44 extends Omit<StoryV43, 'pages'> {\n  pages: PageV44[];\n}\n\nexport interface PageV44 extends Omit<PageV43, 'elements'> {\n  elements: UnionElementV44[];\n}\n\nfunction unusedProperties({ pages, ...rest }: StoryV43): StoryV44 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV43): PageV44 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV43): UnionElementV44 {\n  if ('fontWeight' in element) {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Removes lingering properties that came from the templates but don't exist on the type.\n    // @ts-ignore -- Ignore fontWeight not existing on element.\n    delete element.fontWeight;\n  }\n  if ('backgroundOverlay' in element) {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Removes lingering properties that came from the templates but don't exist on the type.\n    // @ts-ignore -- Ignore backgroundOverlay not existing on element.\n    delete element.backgroundOverlay;\n  }\n  return element;\n}\n\nexport default unusedProperties;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0045_globalPageAdvancement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifElementV44,\n  ImageElementV44,\n  PageV44,\n  ProductElementV44,\n  ShapeElementV44,\n  StoryV44,\n  TextElementV44,\n  VideoElementV44,\n  GifResourceV44,\n  ImageResourceV44,\n  VideoResourceV44,\n} from './v0044_unusedProperties';\n\nexport type TextElementV45 = TextElementV44;\nexport type ProductElementV45 = ProductElementV44;\nexport type ShapeElementV45 = ShapeElementV44;\nexport type ImageElementV45 = ImageElementV44;\nexport type VideoElementV45 = VideoElementV44;\nexport type GifElementV45 = GifElementV44;\n\nexport type ImageResourceV45 = ImageResourceV44;\nexport type VideoResourceV45 = VideoResourceV44;\nexport type GifResourceV45 = GifResourceV44;\n\nexport type UnionElementV45 =\n  | ShapeElementV45\n  | ImageElementV45\n  | VideoElementV45\n  | GifElementV45\n  | TextElementV45\n  | ProductElementV45;\n\nexport interface StoryV45 extends Omit<\n  StoryV44,\n  'pages' | 'autoAdvance' | 'defaultPageDuration'\n> {\n  pages: PageV45[];\n  autoAdvance?: boolean;\n  defaultPageDuration?: number;\n}\nexport interface PageV45 extends Omit<PageV44, 'elements'> {\n  elements: UnionElementV45[];\n}\n\nfunction pageAdvancement(story: StoryV44): StoryV45 {\n  const { autoAdvance, defaultPageDuration, ...rest } = story;\n  if (autoAdvance && defaultPageDuration === 7) {\n    return rest;\n  }\n  return story;\n}\n\nexport default pageAdvancement;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0046_removeRedundantScalingProperties.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  GifResourceV45,\n  ImageResourceV45,\n  VideoResourceV45,\n  GifElementV45,\n  ImageElementV45,\n  PageV45,\n  ProductElementV45,\n  ShapeElementV45,\n  StoryV45,\n  TextElementV45,\n  VideoElementV45,\n  UnionElementV45,\n} from './v0045_globalPageAdvancement';\n\nexport type TextElementV46 = Omit<\n  TextElementV45,\n  'focalX' | 'focalY' | 'scale'\n>;\nexport type ProductElementV46 = Omit<\n  ProductElementV45,\n  'focalX' | 'focalY' | 'scale'\n>;\nexport type ShapeElementV46 = Omit<\n  ShapeElementV45,\n  'focalX' | 'focalY' | 'scale'\n>;\nexport type ImageElementV46 = ImageElementV45;\nexport type VideoElementV46 = VideoElementV45;\nexport type GifElementV46 = GifElementV45;\n\nexport type ImageResourceV46 = ImageResourceV45;\nexport type VideoResourceV46 = VideoResourceV45;\nexport type GifResourceV46 = GifResourceV45;\n\nexport type UnionElementV46 =\n  | ShapeElementV46\n  | ImageElementV46\n  | VideoElementV46\n  | GifElementV46\n  | TextElementV46\n  | ProductElementV46;\n\nexport interface StoryV46 extends Omit<StoryV45, 'pages'> {\n  pages: PageV46[];\n}\n\nexport interface PageV46 extends Omit<PageV45, 'elements'> {\n  elements: UnionElementV46[];\n}\n\nfunction removeRedundantScalingProperties({\n  pages,\n  ...rest\n}: StoryV45): StoryV46 {\n  return {\n    pages: pages.map(reducePage),\n    ...rest,\n  };\n}\n\nfunction reducePage({ elements, ...rest }: PageV45): PageV46 {\n  return {\n    elements: elements.map(updateElement),\n    ...rest,\n  };\n}\n\nfunction updateElement(element: UnionElementV45): UnionElementV46 {\n  if (!('resource' in element)) {\n    delete element.focalX;\n    delete element.focalY;\n    delete element.scale;\n  }\n  return element;\n}\n\nexport default removeRedundantScalingProperties;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0047_fixBrokenTemplates.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ElementId } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { AnimationV0 } from '../types';\nimport type {\n  PageV46,\n  StoryV46,\n  UnionElementV46,\n} from './v0046_removeRedundantScalingProperties';\n\nexport type StoryV47 = StoryV46;\nexport type PageV47 = PageV46;\nexport type UnionElementV47 = UnionElementV46;\n\nfunction fixBrokenTemplate({ pages, ...rest }: StoryV46): StoryV47 {\n  return {\n    pages: pages.map(fixBrokenPage),\n    ...rest,\n  };\n}\n\nfunction fixBrokenPage({ elements, animations, ...rest }: PageV46): PageV47 {\n  const elementIds = elements.map(({ id }) => id);\n\n  return {\n    elements: fixElementOrder(elements.concat()),\n    ...(animations\n      ? {\n          animations: animations.filter((animation) =>\n            removeBrokenAnimation(animation, elementIds)\n          ),\n        }\n      : {}),\n    ...rest,\n  };\n}\n\nfunction fixElementOrder(elements: UnionElementV46[]) {\n  const newElements: UnionElementV47[] = [];\n  while (elements.length) {\n    const nextElement = elements.shift() as UnionElementV46;\n    newElements.push(nextElement);\n    if (!nextElement.groupId) {\n      continue;\n    }\n    // Find all group members in order and move them one by one\n    const { groupId } = nextElement;\n    const isGroupMember = (e: UnionElementV46) => e.groupId === groupId;\n    while (elements.some(isGroupMember)) {\n      const index = elements.findIndex(isGroupMember);\n      newElements.push(...elements.splice(index, 1));\n    }\n  }\n  return newElements;\n}\n\nfunction removeBrokenAnimation(\n  animation: AnimationV0,\n  elementIds: ElementId[]\n): boolean {\n  return elementIds.includes(animation.targets[0]);\n}\n\nexport default fixBrokenTemplate;\n"
  },
  {
    "path": "packages/migration/src/migrations/v0048_removeBasedOnFromElements.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  PageV47,\n  StoryV47,\n  UnionElementV47,\n} from './v0047_fixBrokenTemplates';\n\nexport interface PageV48 extends Omit<PageV47, 'elements'> {\n  elements: Omit<UnionElementV47, 'basedOn'>[];\n}\n\nexport interface StoryV48 extends Omit<StoryV47, 'pages'> {\n  pages: PageV48[];\n}\n\nfunction removeBasedOnFromElements({ pages, ...rest }: StoryV47): StoryV48 {\n  return {\n    pages: pages.map(fixBrokenPage),\n    ...rest,\n  };\n}\n\nfunction fixBrokenPage({ elements, ...rest }: PageV47): PageV48 {\n  return {\n    elements: elements.map(\n      (element) =>\n        objectWithout(element, ['basedOn']) as Omit<UnionElementV47, 'basedOn'>\n    ),\n    ...rest,\n  };\n}\n\nfunction objectWithout<T extends object>(\n  obj: T,\n  propertiesToRemove: string[]\n): Partial<T> {\n  return Object.keys(obj)\n    .filter((key) => !propertiesToRemove.includes(key))\n    .reduce((newObj, key) => ({ ...newObj, [key]: obj[key as keyof T] }), {});\n}\n\nexport default removeBasedOnFromElements;\n"
  },
  {
    "path": "packages/migration/src/types/element.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { GifResourceV0 } from './resource';\n\ntype TextAlign = 'left' | 'center' | 'right' | 'justify';\ntype TagName = 'h1' | 'h2' | 'h3' | 'p' | 'auto';\n\nexport interface FontMetrics {\n  upm: number;\n  asc: number;\n  des: number;\n  tAsc: number;\n  tDes: number;\n  tLGap: number;\n  wAsc: number;\n  wDes: number;\n  xH: number;\n  capH: number;\n  yMin: number;\n  yMax: number;\n  hAsc: number;\n  hDes: number;\n  lGap: number;\n}\n\nexport interface LinkV0 {\n  url: string;\n  desc?: string;\n  needsProxy?: boolean;\n  icon?: string;\n  rel?: string[];\n  type?: string;\n}\n\ninterface ElementBoxV0 {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n  rotationAngle: number;\n}\n\ninterface BorderV0 {\n  top: number;\n  right: number;\n  bottom: number;\n  left: number;\n  locked: boolean;\n}\n\ninterface BorderRadiusV0 {\n  topLeft: number;\n  topRight: number;\n  bottomLeft: number;\n  bottomRight: number;\n  locked: boolean;\n}\n\nexport interface ElementV0 extends ElementBoxV0 {\n  id: string;\n  type: string;\n  isBackground: boolean;\n\n  mask?: {\n    type: string;\n  };\n  link?: LinkV0;\n  lockAspectRatio?: boolean;\n  groupId?: string;\n  border?: BorderV0;\n  borderRadius?: BorderRadiusV0;\n\n  scale?: number;\n  focalX?: number;\n  focalY?: number;\n}\n\nexport interface MediaElementV0 extends ElementV0 {\n  isFullbleed?: boolean;\n  isFullbleedBackground?: boolean;\n  src: string;\n  origRatio: number;\n  mimeType: string;\n  scale: number;\n  focalX?: number;\n  focalY?: number;\n}\n\nexport interface GifElementV0 extends MediaElementV0 {\n  opacity: number;\n  resource: GifResourceV0;\n}\n\ninterface VideoTrackV0 {\n  id: string;\n  track: string;\n  trackId?: number;\n  kind?: string;\n  srclang?: string;\n  label?: string;\n  needsProxy?: boolean;\n}\n\nexport interface VideoElementV0 extends MediaElementV0 {\n  poster: string;\n  posterId: number;\n  videoId: number;\n  tracks?: VideoTrackV0[];\n  loop?: boolean;\n  type: 'video';\n}\n\nexport type ImageElementV0 = MediaElementV0;\n\nexport interface TextElementV0 extends ElementV0 {\n  content: string;\n  bold: boolean;\n  fontWeight: number;\n  fontStyle: string;\n  textDecoration: string;\n  letterSpacing: number;\n  color: string;\n  fontFamily: string;\n  fontFallback: string[];\n\n  backgroundColor?: string;\n  fontSize?: number;\n  lineHeight?: number;\n  padding?: number;\n  textAlign?: TextAlign;\n  tagName?: TagName;\n  marginOffset?: number;\n  metrics?: FontMetrics;\n}\n\nexport interface ShapeElementV0 extends ElementV0 {\n  backgroundColor: string;\n}\n\nexport interface ProductElementV0 extends ElementV0 {\n  productId: string;\n}\n\nexport type UnionElementV0 =\n  | ShapeElementV0\n  | ImageElementV0\n  | VideoElementV0\n  | TextElementV0;\n"
  },
  {
    "path": "packages/migration/src/types/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './resource';\nexport * from './element';\nexport * from './story';\n"
  },
  {
    "path": "packages/migration/src/types/pattern.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum PatternTypeV0 {\n  Solid = 'solid',\n  Linear = 'linear',\n  Radial = 'radial',\n  Conic = 'conic',\n}\ntype AbstractGradientV0 = {\n  type: PatternTypeV0.Linear | PatternTypeV0.Radial | PatternTypeV0.Conic;\n  stops: ColorStop[];\n  alpha?: number;\n};\n\nexport type ConicV0 = AbstractGradientV0 & {\n  type: PatternTypeV0.Conic;\n  rotation?: number;\n};\n\nexport type GradientV0 = Linear | Radial | ConicV0;\nexport type PatternV0 = Solid | GradientV0;\n\nexport type Hex = {\n  r: number;\n  g: number;\n  b: number;\n  a?: number;\n};\n\nexport enum PatternType {\n  Solid = 'solid',\n  Linear = 'linear',\n  Radial = 'radial',\n}\n\nexport type Solid = {\n  type?: PatternType.Solid;\n  color: Hex;\n};\n\nexport type ColorStop = {\n  color: Hex;\n  position: number;\n};\n\ntype AbstractGradient = {\n  type: PatternType.Linear | PatternType.Radial;\n  stops: ColorStop[];\n  alpha?: number;\n};\n\nexport type Linear = AbstractGradient & {\n  type: PatternType.Linear;\n  rotation?: number;\n};\n\nexport type Radial = AbstractGradient & {\n  type: PatternType.Radial;\n  size?: {\n    w: number;\n    h: number;\n  };\n  center?: {\n    x: number;\n    y: number;\n  };\n  rotation?: number;\n};\n\nexport type Gradient = Linear | Radial;\nexport type Pattern = Solid | Gradient;\n"
  },
  {
    "path": "packages/migration/src/types/resource.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ResourceType {\n  Image = 'image',\n  Video = 'video',\n  Gif = 'gif',\n}\n\ninterface ResourceSizeV0 {\n  mimeType: string;\n  sourceUrl: string;\n  width: number | string;\n  height: number | string;\n}\n\ninterface SizeV0 {\n  width: string | number;\n  height: string | number;\n  source_url: string;\n}\nexport interface ResourceV0 {\n  type: ResourceType;\n  mimeType: string;\n  src: string;\n  width: number | string;\n  height: number | string;\n  sizes?: Record<string, SizeV0>;\n  title?: string;\n  baseColor?: number[];\n  local?: boolean;\n  isTrimming?: boolean;\n  isTranscoding?: boolean;\n  isMuting?: boolean;\n}\n\nexport interface ImageResourceV0 extends ResourceV0 {\n  type: ResourceType.Image;\n}\n\nexport interface VideoResourceV0 extends ResourceV0 {\n  poster?: string;\n  posterId?: number;\n  videoId?: number;\n  type: ResourceType.Video;\n}\n\ninterface OutputV0 {\n  mimeType: string;\n  src: string;\n  poster?: string;\n  sizes?: { [key: string]: ResourceSizeV0 };\n}\n\nexport interface GifResourceV0 extends ResourceV0 {\n  type: ResourceType.Gif;\n  output: OutputV0;\n  isTrimming?: boolean;\n  isTranscoding?: boolean;\n  isMuting?: boolean;\n  title: string;\n  alt: string;\n}\n"
  },
  {
    "path": "packages/migration/src/types/story.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* The types in StoryV0 do not reflect the exact state as the Story actually was at that point.\n The types are accurate for the properties that have been migrated\n but since the types were added only later then we don't how the story exactly was at that point.\n For example FontMetrics, Resource, and GifElement did not exist at StoryV0.\n */\n\n/**\n * Internal dependencies\n */\nimport type { UnionElementV0 } from './element';\n\nexport interface Group {\n  name: string;\n  isLocked: boolean;\n  isCollapsed?: boolean;\n}\n\ntype AnimationTypeV0 =\n  | 'blinkOn'\n  | 'bounce'\n  | 'effect-background-pan'\n  | 'effect-background-pan-and-zoom'\n  | 'effect-background-zoom'\n  | 'effect-drop'\n  | 'effect-fade-in'\n  | 'effect-fly-in'\n  | 'effect-pan'\n  | 'effect-pulse'\n  | 'effect-rotate-in'\n  | 'effect-twirl-in'\n  | 'effect-whoosh-in'\n  | 'effect-zoom'\n  | 'fade'\n  | 'flip'\n  | 'floatOn'\n  | 'move'\n  | 'pulse'\n  | 'spin'\n  | 'zoom';\n\ntype AnimationZoomDirectionV0 =\n  | 'dynamicPropertyValue'\n  | 'scaleIn'\n  | 'scaleInBottomRight'\n  | 'scaleInTopLeft'\n  | 'scaleOut'\n  | 'scaleOutTopRight'\n  | 'scaleOutBottomLeft';\n\ntype AnimationPanDirectionV0 =\n  | 'leftToRight'\n  | 'topToBottom'\n  | 'rightToLeft'\n  | 'bottomToTop';\n\nexport interface AnimationV0 {\n  id: string;\n  type: AnimationTypeV0;\n  targets: string[];\n  panDir?: AnimationPanDirectionV0;\n  duration: number;\n  delay: number;\n  zoomDirection?: AnimationZoomDirectionV0;\n}\n\nexport type Groups = Record<string, Group>;\n\nexport interface PageV0 {\n  backgroundColor: string;\n  elements: UnionElementV0[];\n  animations?: AnimationV0[];\n  type: 'page';\n  groups: Groups;\n  backgroundAudio?: {\n    src: string;\n    id: number;\n    mimeType: string;\n  };\n  pageAttachment?: {\n    url: string;\n    ctaText?: string;\n  };\n  overlay: string;\n  autoAdvance?: boolean;\n  defaultPageDuration?: number;\n}\n\nexport type StoryV0 = PageV0[];\n"
  },
  {
    "path": "packages/migration/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../elements\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/moveable/README.md",
    "content": "# Moveable\n\n---\n\nPackage that provides a wrapper around react-moveable.\n"
  },
  {
    "path": "packages/moveable/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/moveable\",\n  \"description\": \"Provides a wrapper around react-moveable.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/moveable/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/moveable\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@types/styled-components\": \"^5.1.26\",\n    \"prop-types\": \"^15.7.2\",\n    \"react-moveable\": \"^0.56.0\",\n    \"styled-components\": \"^5.3.11\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/moveable/src/areEventsDragging.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Determine if two mouse events are part of a dragging action or not.\n *\n * It can be any two mouse event such as down and up or dragstart and drag.\n *\n * @param firstEvent First mouse event object.\n * @param secondEvent Second mouse event object.\n * @return Whether the events are considered part of dragging\n */\nfunction areEventsDragging(\n  firstEvent: MouseEvent,\n  secondEvent: MouseEvent\n): boolean {\n  const { clientX, clientY, timeStamp } = firstEvent;\n  const timingDifference = secondEvent.timeStamp - timeStamp;\n\n  const distanceMoved =\n    Math.abs(secondEvent.clientX - clientX) +\n    Math.abs(secondEvent.clientY - clientY);\n  return timingDifference > 300 || distanceMoved > 4;\n}\n\nexport default areEventsDragging;\n"
  },
  {
    "path": "packages/moveable/src/cropStyle.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\n\nconst SIDE_WIDE = 24;\nconst SIDE_NARROW = 8;\nconst SIDE_BORDER = 1;\nconst SIDES_DIFF = SIDE_WIDE - SIDE_NARROW;\n\nexport const GlobalStyle = createGlobalStyle`\n  .crop-moveable .moveable-control {\n    background: ${({ theme }) => theme.colors.bg.primary} !important;\n    border: none !important;\n  }\n\n  .crop-moveable .moveable-control.moveable-n,\n  .crop-moveable .moveable-control.moveable-s,\n  .crop-moveable .moveable-control.moveable-e,\n  .crop-moveable .moveable-control.moveable-w {\n    border: 1px solid ${({ theme }) =>\n      theme.colors.border.selection} !important;\n    border-radius: 4px;\n  }\n\n  .crop-moveable .moveable-control.moveable-n,\n  .crop-moveable .moveable-control.moveable-s {\n    width: ${SIDE_WIDE}px !important;\n    height: ${SIDE_NARROW}px !important;\n    margin-left: -12px !important;\n  }\n\n  .crop-moveable .moveable-control.moveable-n {\n    margin-top: -8px !important;\n  }\n  .crop-moveable .moveable-control.moveable-s {\n    margin-top: 0px !important;\n  }\n  .crop-moveable .moveable-control.moveable-e {\n    margin-left: 0 !important;\n  }\n  .crop-moveable .moveable-control.moveable-w {\n    margin-top: 0 !important;\n    margin-left: -8px !important;\n  }\n\n  .crop-moveable .moveable-control.moveable-e,\n  .crop-moveable .moveable-control.moveable-w {\n    width: ${SIDE_NARROW}px !important;\n    height: ${SIDE_WIDE}px !important;\n    margin-top: -12px !important;\n  }\n\n  .crop-moveable .moveable-control.moveable-nw,\n  .crop-moveable .moveable-control.moveable-ne,\n  .crop-moveable .moveable-control.moveable-sw,\n  .crop-moveable .moveable-control.moveable-se,\n  .crop-moveable .moveable-control.moveable-nw::before,\n  .crop-moveable .moveable-control.moveable-ne::before,\n  .crop-moveable .moveable-control.moveable-sw::before,\n  .crop-moveable .moveable-control.moveable-se::before,\n  .crop-moveable .moveable-control.moveable-nw::after,\n  .crop-moveable .moveable-control.moveable-ne::after,\n  .crop-moveable .moveable-control.moveable-sw::after,\n  .crop-moveable .moveable-control.moveable-se::after {\n    left: initial !important;\n    right: initial !important;\n    top: initial !important;\n    bottom: initial !important;\n    background: ${({ theme }) => theme.colors.bg.primary} !important;\n    position: absolute !important;\n    border-style: solid !important;\n    border-color: ${({ theme }) => theme.colors.border.selection} !important;\n  }\n\n  .crop-moveable .moveable-control.moveable-nw::before,\n  .crop-moveable .moveable-control.moveable-ne::before,\n  .crop-moveable .moveable-control.moveable-sw::before,\n  .crop-moveable .moveable-control.moveable-se::before,\n  .crop-moveable .moveable-control.moveable-nw::after,\n  .crop-moveable .moveable-control.moveable-ne::after,\n  .crop-moveable .moveable-control.moveable-sw::after,\n  .crop-moveable .moveable-control.moveable-se::after {\n    content: '';\n  }\n\n  /* The corner piece */\n  .crop-moveable .moveable-control.moveable-nw,\n  .crop-moveable .moveable-control.moveable-ne,\n  .crop-moveable .moveable-control.moveable-sw,\n  .crop-moveable .moveable-control.moveable-se {\n    width: ${SIDE_NARROW - SIDE_BORDER}px !important;\n    height: ${SIDE_NARROW - SIDE_BORDER}px !important;\n  }\n\n  /* top left corner piece */\n  .crop-moveable .moveable-control.moveable-nw {\n    top: -${SIDE_BORDER}px !important;\n    left: -${SIDE_BORDER}px !important;\n    border-width: 1px 0 0 1px !important;\n    border-radius: 2px 0 0 0 !important;\n  }\n\n  /* top right corner piece */\n  .crop-moveable .moveable-control.moveable-ne {\n    top: -${SIDE_BORDER}px !important;\n    right: -${SIDE_NARROW - SIDE_BORDER}px !important;\n    border-width: 1px 1px 0 0 !important;\n    border-radius: 0 2px 0 0 !important;\n  }\n\n  /* bottom left corner piece */\n  .crop-moveable .moveable-control.moveable-sw {\n    left: -${SIDE_BORDER}px !important;\n    bottom: -${SIDE_NARROW - SIDE_BORDER}px !important;\n    border-width: 0 0 1px 1px !important;\n    border-radius: 0 0 0 2px !important;\n  }\n\n  /* bottom right corner piece */\n  .crop-moveable .moveable-control.moveable-se {\n    right: -${SIDE_NARROW - SIDE_BORDER}px !important;\n    bottom: -${SIDE_NARROW - SIDE_BORDER}px !important;\n    border-width:  0 1px 1px 0 !important;\n    border-radius: 0 0 2px 0 !important;\n  }\n\n  /* The horizontal edges */\n  .crop-moveable .moveable-control.moveable-nw::before,\n  .crop-moveable .moveable-control.moveable-ne::before,\n  .crop-moveable .moveable-control.moveable-sw::before,\n  .crop-moveable .moveable-control.moveable-se::before {\n    width: ${SIDES_DIFF + SIDE_BORDER}px !important;\n    height: ${SIDE_NARROW}px !important;\n    top: 0;\n  }\n\n  /* The horizontal edges to the left of corner */\n  .crop-moveable .moveable-control.moveable-nw::before,\n  .crop-moveable .moveable-control.moveable-sw::before {\n    left: ${SIDE_NARROW - 2 * SIDE_BORDER}px !important;\n    border-width: 1px 1px 1px 0;\n    border-radius: 0 2px 2px 0;\n  }\n\n  /* The horizontal edges to the right of corner */\n  .crop-moveable .moveable-control.moveable-ne::before,\n  .crop-moveable .moveable-control.moveable-se::before {\n    right: ${SIDE_NARROW - 2 * SIDE_BORDER}px !important;\n    border-width: 1px 0 1px 1px;\n    border-radius: 2px 0 0 2px;\n  }\n\n  /* The horizontal edges along the top */\n  .crop-moveable .moveable-control.moveable-nw::before,\n  .crop-moveable .moveable-control.moveable-ne::before {\n    top: -${SIDE_BORDER}px !important;\n  }\n\n  /* The horizontal edges along the bottom */\n  .crop-moveable .moveable-control.moveable-sw::before,\n  .crop-moveable .moveable-control.moveable-se::before {\n    bottom: -${SIDE_BORDER}px !important;\n  }\n\n  /* The vertical edges */\n  .crop-moveable .moveable-control.moveable-nw::after,\n  .crop-moveable .moveable-control.moveable-ne::after,\n  .crop-moveable .moveable-control.moveable-sw::after,\n  .crop-moveable .moveable-control.moveable-se::after {\n    width: ${SIDE_NARROW}px !important;\n    height: ${SIDES_DIFF + SIDE_BORDER}px !important;\n  }\n\n  /* The vertical edges below corner */\n  .crop-moveable .moveable-control.moveable-nw::after,\n  .crop-moveable .moveable-control.moveable-ne::after {\n    top: ${SIDE_NARROW - 2 * SIDE_BORDER}px !important;\n    border-width: 0 1px 1px 1px;\n    border-radius: 0 0 2px 2px;\n  }\n\n  /* The vertical edges above corner */\n  .crop-moveable .moveable-control.moveable-sw::after,\n  .crop-moveable .moveable-control.moveable-se::after {\n    bottom: ${SIDE_NARROW - 2 * SIDE_BORDER}px !important;\n    border-width: 1px 1px 0 1px;\n    border-radius: 2px 2px 0 0;\n  }\n\n  /* The vertical edges along the left edge */\n  .crop-moveable .moveable-control.moveable-nw::after,\n  .crop-moveable .moveable-control.moveable-sw::after {\n    left: -${SIDE_BORDER}px !important;\n  }\n\n  /* The vertical edges along the right edge */\n  .crop-moveable .moveable-control.moveable-ne::after,\n  .crop-moveable .moveable-control.moveable-se::after {\n    right: -${SIDE_BORDER}px !important;\n  }\n\n\n  .crop-moveable .moveable-line.moveable-direction[data-line-index=\"0\"] {\n    margin-top: -4px;\n  }\n  .crop-moveable .moveable-line.moveable-direction[data-line-index=\"3\"] {\n    margin-top: 4px;\n  }\n  .crop-moveable .moveable-line.moveable-direction[data-line-index=\"1\"] {\n    margin-left: 4px;\n  }\n  .crop-moveable .moveable-line.moveable-direction[data-line-index=\"2\"] {\n    margin-left: -4px;\n  }\n\n  .crop-moveable .moveable-direction.moveable-line {\n    background: ${({ theme }) => theme.colors.border.selection} !important;\n    width: 2px;\n    height: 2px;\n    pointer-events: none;\n  }\n`;\n"
  },
  {
    "path": "packages/moveable/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nexport { default as Moveable } from './moveable';\nexport { GlobalStyle as CropMoveableGlobalStyle } from './cropStyle';\nexport { GlobalStyle as DefaultMoveableGlobalStyle } from './moveStyle';\nexport { default as InOverlay } from './overlay';\nexport { default as withOverlay } from './overlay/withOverlay';\nexport { default as areEventsDragging } from './areEventsDragging';\n"
  },
  {
    "path": "packages/moveable/src/moveStyle.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport arrowCircle from './inline-icons/arrow_circle.svg';\n\nexport const GlobalStyle = createGlobalStyle`\n  .default-moveable .moveable-control,\n  .default-moveable .moveable-line.moveable-rotation-line .moveable-control {\n    background: ${({ theme }) => theme.colors.bg.primary} !important;\n    border: 1px solid ${({ theme }) =>\n      theme.colors.border.selection} !important;\n  }\n\n  .default-moveable.type-text .moveable-direction.moveable-n, .default-moveable.type-text .moveable-direction.moveable-s {\n    pointer-events: none;\n  }\n  .default-moveable .moveable-control.moveable-n {\n    display: none !important;\n  }\n\n  .default-moveable .moveable-line {\n    border: 0;\n    background: transparent !important;\n    width: 1px;\n    height: 1px;\n  }\n\n  .default-moveable .moveable-horizontal {\n    border-bottom: 1px dashed ${({ theme }) =>\n      theme.colors.border.focus} !important;\n  }\n\n  .default-moveable .moveable-vertical {\n    border-right: 1px dashed ${({ theme }) =>\n      theme.colors.border.focus} !important;\n  }\n\n  .default-moveable .moveable-gap {\n    border-color: ${({ theme }) =>\n      theme.colors.border.negativePress} !important;\n  }\n\n  .default-moveable .moveable-target {\n    border-style: solid !important;\n  }\n\n  .default-moveable .moveable-control.moveable-s,\n  .default-moveable .moveable-control.moveable-e,\n  .default-moveable .moveable-control.moveable-w {\n    border-radius: 4px;\n  }\n\n  .default-moveable .moveable-control.moveable-nw,\n  .default-moveable .moveable-control.moveable-ne,\n  .default-moveable .moveable-control.moveable-sw,\n  .default-moveable .moveable-control.moveable-se {\n    border-radius: 2px;\n    width: 8px;\n    height: 8px;\n    margin-left: -4px;\n    margin-top: -4px;\n  }\n\n  .default-moveable .moveable-control.moveable-s {\n    height: 6px !important;\n    width: 16px !important;\n    margin-top: -3px !important;\n  }\n\n  .default-moveable .moveable-control.moveable-e {\n    height: 16px !important;\n    width: 6px !important;\n    margin-left: -3px !important;\n  }\n\n  .default-moveable .moveable-control.moveable-w {\n    height: 16px !important;\n    width: 6px !important;\n    margin-left: -3px !important;\n  }\n\n  .default-moveable.moveable-control-box .moveable-line.moveable-direction {\n    background: ${({ theme }) => theme.colors.border.selection} !important;\n    width: 1px;\n    height: 1px;\n  }\n\n  .default-moveable.moveable-control-box .moveable-line.moveable-rotation-line {\n    background: ${({ theme }) => theme.colors.border.selection} !important;\n    width: 1px;\n    height: 12px;\n    top: 28px;\n  }\n\n  .default-moveable.moveable-control-box .moveable-control.moveable-rotation-control {\n    border-radius: 50px;\n    width: 29px;\n    height: 29px;\n    margin-left: -14.5px;\n    top: 10.5px;\n  }\n\n  .default-moveable.moveable-control-box .moveable-control.moveable-rotation-control::after {\n    content: '';\n    position: absolute;\n    width: 28px;\n    height: 28px;\n    left: -1px;\n    top: -1px;\n    background-image: url(\"${arrowCircle}\");\n    background-size: 100%;\n    /* The svg is made into an image and styles can't be shared across documents.\n    Black is the default so invert to white. */\n    filter: invert(100%);\n  }\n\n  .default-moveable.hide-handles .moveable-line.moveable-rotation-line,\n  .default-moveable.hide-handles .moveable-line.moveable-direction {\n    display: none;\n  }\n\n  .default-moveable.visually-hide-handles .moveable-control.moveable-e,\n  .default-moveable.visually-hide-handles .moveable-control.moveable-w,\n  .default-moveable.visually-hide-handles .moveable-control.moveable-s,\n  .default-moveable.visually-hide-handles .moveable-control.moveable-ne,\n  .default-moveable.visually-hide-handles .moveable-control.moveable-nw,\n  .default-moveable.visually-hide-handles .moveable-control.moveable-sw {\n    opacity: 0;\n  }\n\n  .default-moveable.immoveable .moveable-line.moveable-direction {\n    cursor: default;\n  }\n`;\n"
  },
  {
    "path": "packages/moveable/src/moveable.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport OriginalMoveable from 'react-moveable';\nimport type { MoveableProps, MoveableDefaultOptions } from 'react-moveable';\nimport type { ForwardedRef, MouseEventHandler } from 'react';\n\n/**\n * Internal dependencies\n */\nimport InOverlay from './overlay';\n\nconst DEFAULT_Z_INDEX = 10;\n\ninterface MoveableWithRefProps extends MoveableProps {\n  onContextMenu?: MouseEventHandler<HTMLElement>;\n}\n\nfunction MoveableWithRef(\n  { onContextMenu, ...moveableProps }: MoveableWithRefProps,\n  ref: ForwardedRef<OriginalMoveable>\n) {\n  return (\n    <InOverlay\n      onContextMenu={onContextMenu}\n      zIndex={DEFAULT_Z_INDEX}\n      pointerEvents=\"initial\"\n      render={({ container }: MoveableDefaultOptions) => {\n        return (\n          <OriginalMoveable\n            ref={ref}\n            container={container}\n            {...moveableProps}\n          />\n        );\n      }}\n    />\n  );\n}\n\nconst Moveable = forwardRef<OriginalMoveable, MoveableWithRefProps>(\n  MoveableWithRef\n);\n\nexport default Moveable;\n"
  },
  {
    "path": "packages/moveable/src/overlay/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\ninterface State {\n  container?: HTMLElement | null;\n  layer?: unknown;\n  overlay?: Element | null;\n}\n\nexport default createContext<State>({ container: null, layer: null });\n"
  },
  {
    "path": "packages/moveable/src/overlay/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { forwardRef, useContext, createPortal } from '@googleforcreators/react';\nimport type { ReactNode, HTMLAttributes, ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\ntype PointerEventsValue = 'none' | 'auto' | 'initial';\n\ninterface WrapperProps {\n  $zIndex: number;\n  ref: ForwardedRef<HTMLDivElement>;\n  pointerEvents?: PointerEventsValue;\n}\n\nconst Wrapper = styled.div<WrapperProps>`\n  pointer-events: ${({ pointerEvents }) => pointerEvents}\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 0;\n  height: 0;\n  z-index: ${({ $zIndex }) => `${$zIndex}`};\n`;\n\ninterface RenderProps {\n  container: HTMLElement;\n  overlay: Element;\n}\n\ninterface InOverlayProps extends HTMLAttributes<HTMLDivElement> {\n  pointerEvents: PointerEventsValue;\n  children?: ReactNode;\n  zIndex: number;\n  render?: (props: RenderProps) => JSX.Element;\n}\n\nfunction InOverlayWithRef(\n  { zIndex, pointerEvents, render, children = null, ...props }: InOverlayProps,\n  ref: ForwardedRef<HTMLDivElement>\n) {\n  const { container, overlay } = useContext(Context);\n  if (!container || !overlay) {\n    return null;\n  }\n  const slot = (\n    /* eslint-disable-next-line styled-components-a11y/no-static-element-interactions -- No role required here. */\n    <Wrapper\n      {...props}\n      ref={ref}\n      $zIndex={zIndex || 0}\n      pointerEvents={pointerEvents}\n      onMouseDown={(evt) => evt.stopPropagation()}\n    >\n      {render ? render({ container, overlay }) : children}\n    </Wrapper>\n  );\n  return createPortal(slot, overlay);\n}\n\nconst InOverlay = forwardRef<HTMLDivElement, InOverlayProps>(InOverlayWithRef);\n\nexport default InOverlay;\n"
  },
  {
    "path": "packages/moveable/src/overlay/withOverlay.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  forwardRef,\n  useCombinedRefs,\n  useState,\n} from '@googleforcreators/react';\nimport type { ElementType, ForwardedRef, ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\ninterface OverlayProps {\n  $zIndex: number;\n}\n\ninterface WithOverlayProps {\n  zIndex: number;\n  children: ReactNode;\n}\n\nconst Overlay = styled.div<OverlayProps>`\n  position: absolute;\n  top: 0;\n  /*! @noflip */\n  left: 0;\n  width: 0;\n  height: 0;\n  z-index: ${({ $zIndex }) => $zIndex};\n`;\n\nfunction withOverlay(Comp: ElementType) {\n  function WithOverlay(\n    { children, ...rest }: WithOverlayProps,\n    ref: ForwardedRef<HTMLElement>\n  ) {\n    const [overlay, setOverlay] = useState<HTMLElement | null>(null);\n    const [container, setContainer] = useState<HTMLElement | null>(null);\n    const { zIndex = 1 } = rest;\n    return (\n      <Context.Provider value={{ container, overlay }}>\n        <Comp ref={useCombinedRefs(ref, setContainer)} {...rest}>\n          {children}\n          <Overlay ref={setOverlay} $zIndex={zIndex} />\n        </Comp>\n      </Context.Provider>\n    );\n  }\n\n  return forwardRef(WithOverlay);\n}\n\nexport default withOverlay;\n"
  },
  {
    "path": "packages/moveable/src/test/areEventsDragging.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport areEventsDragging from '../areEventsDragging';\n\ndescribe('areEventsDragging', () => {\n  it('should *not* consider a quick sequence of events at about the same point dragging', () => {\n    const firstEvent = {\n      clientX: 0,\n      clientY: 0,\n      timeStamp: window.performance.now(),\n    };\n    const secondEvent = {\n      clientX: 1,\n      clientY: 1,\n      timeStamp: window.performance.now() + 10,\n    };\n    expect(\n      areEventsDragging(firstEvent as MouseEvent, secondEvent as MouseEvent)\n    ).toBeFalse();\n  });\n\n  it('should consider a long delay between events dragging even if only moving a small distance', () => {\n    const firstEvent = {\n      clientX: 0,\n      clientY: 0,\n      timeStamp: window.performance.now(),\n    };\n    const secondEvent = {\n      clientX: 1,\n      clientY: 1,\n      timeStamp: window.performance.now() + 1000,\n    };\n    expect(\n      areEventsDragging(firstEvent as MouseEvent, secondEvent as MouseEvent)\n    ).toBeTrue();\n  });\n\n  it('should consider a long distance between events dragging even if fired in quick succession', () => {\n    const firstEvent = {\n      clientX: 0,\n      clientY: 0,\n      timeStamp: window.performance.now(),\n    };\n    const secondEvent = {\n      clientX: 10,\n      clientY: 10,\n      timeStamp: window.performance.now() + 10,\n    };\n    expect(\n      areEventsDragging(firstEvent as MouseEvent, secondEvent as MouseEvent)\n    ).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/moveable/src/typings/styled-components.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport 'styled-components';\n\ndeclare module 'styled-components' {\n  export interface DefaultTheme {\n    borders: {\n      radius: {\n        [key: string]: string;\n      };\n    };\n    typography: {\n      family: {\n        [key: string]: string;\n      };\n      weight: {\n        [key: string]: number;\n      };\n      presets: {\n        [key: string]: {\n          [key: string]: {\n            [key: string]: number;\n          };\n        };\n      };\n    };\n    colors: {\n      [key: string]: {\n        [key: string]: string;\n      };\n    };\n    breakpoint: {\n      [key: string]: string;\n    };\n  }\n}\n"
  },
  {
    "path": "packages/moveable/src/typings/svg-imports.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  const content: string;\n  export default content;\n}\n"
  },
  {
    "path": "packages/moveable/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../react\" }],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/output/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/output/README.md",
    "content": "# Output\n\nPackage for Web Stories AMP output\n"
  },
  {
    "path": "packages/output/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/output\",\n  \"description\": \"Package for Web Stories AMP output\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/output/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/output\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/animation\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/fonts\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/masks\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/rich-text\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"@googleforcreators/url\": \"*\",\n    \"prop-types\": \"^15.8.0\"\n  },\n  \"devDependencies\": {\n    \"@googleforcreators/element-library\": \"*\",\n    \"@googleforcreators/test-utils\": \"*\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"flagged\": \"^2.0.10\",\n    \"react\": \"^17.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/output/src/components/withLink/index.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { withProtocol } from '@googleforcreators/url';\nimport { LinkType } from '@googleforcreators/elements';\nimport { type Element, elementIs } from '@googleforcreators/elements';\nimport type { HTMLAttributes, PropsWithChildren, ReactElement } from 'react';\n\ntype WithLinkProps = PropsWithChildren<{\n  element: Element;\n}> &\n  HTMLAttributes<HTMLAnchorElement>;\n\nfunction WithLink({ element, children, ...rest }: WithLinkProps) {\n  if (!elementIs.linkable(element)) {\n    return children as unknown as ReactElement;\n  }\n\n  const link = element.link || {};\n  const { url, icon, desc, rel = [], type, pageId } = link;\n\n  if (type === LinkType.Branching && pageId) {\n    return (\n      <a\n        href={`#page=${pageId}`}\n        data-tooltip-icon={icon || undefined}\n        data-tooltip-text={desc}\n        {...rest}\n      >\n        {children}\n      </a>\n    );\n  }\n\n  if (!url) {\n    return children as unknown as ReactElement;\n  }\n\n  const clonedRel = rel.concat(['noreferrer']);\n  const urlWithProtocol = withProtocol(url);\n\n  return (\n    // eslint-disable-next-line react/jsx-no-target-blank -- Working as intended.\n    <a\n      href={urlWithProtocol}\n      data-tooltip-icon={icon || undefined}\n      data-tooltip-text={desc}\n      target=\"_blank\"\n      rel={clonedRel.join(' ')}\n      {...rest}\n    >\n      {children}\n    </a>\n  );\n}\n\nexport default WithLink;\n"
  },
  {
    "path": "packages/output/src/components/withLink/test/output.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\nimport { ElementType, type Link } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport WithLink from '..';\n\ndescribe('WithLink', () => {\n  function withLink(linkProps: Partial<Link> = {}) {\n    const props = {\n      element: {\n        id: '123',\n        type: ElementType.Image,\n        mimeType: 'image/png',\n        scale: 1,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: 'image',\n          mimeType: 'image/png',\n          src: 'https://example.com/image.png',\n          height: 1920,\n          width: 1080,\n        },\n        link: {\n          url: 'https://example.com/',\n          icon: 'https://example.com/image.png',\n          desc: 'Lorem ipsum dolor',\n          ...linkProps,\n        },\n      },\n    };\n    return (\n      <WithLink {...props}>\n        <amp-img src=\"https://example.com/image.png\" layout=\"fill\" />\n      </WithLink>\n    );\n  }\n\n  describe('a[target]', () => {\n    it('should use target=_blank', () => {\n      render(withLink());\n      const a = screen.getByRole<HTMLAnchorElement>('link');\n      expect(a.target).toBe('_blank');\n      expect(a.rel).toBe('noreferrer');\n    });\n  });\n\n  describe('a[rel]', () => {\n    it('should use rel=noreferrer', () => {\n      render(withLink());\n      const a = screen.getByRole<HTMLAnchorElement>('link');\n      expect(a.rel).toBe('noreferrer');\n    });\n\n    it('should use rel=noreferrer nofollow', () => {\n      render(withLink({ rel: ['nofollow'] }));\n      const a = screen.getByRole<HTMLAnchorElement>('link');\n      expect(a.rel).toBe('nofollow noreferrer');\n    });\n  });\n\n  describe('a[data-tooltip-icon]', () => {\n    it('should not add data-tooltip-icon attribute if there is no icon', () => {\n      render(withLink({ icon: '' }));\n      const a = screen.getByRole<HTMLAnchorElement>('link');\n      expect(a).not.toHaveAttribute('data-tooltip-icon');\n    });\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output', async () => {\n      await expect(withLink()).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output for link with rel', async () => {\n      await expect(withLink({ rel: ['nofollow'] })).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output for link without icon', async () => {\n      await expect(withLink({ icon: '' })).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/output/src/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const DEFAULT_PAGE_DURATION = 7;\nexport const DEFAULT_AUTO_ADVANCE = true;\n"
  },
  {
    "path": "packages/output/src/element.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { getBox } from '@googleforcreators/units';\nimport { AMPWrapper } from '@googleforcreators/animation';\nimport {\n  BACKGROUND_TEXT_MODE,\n  getDefinitionForType,\n  type Element,\n  elementIs,\n} from '@googleforcreators/elements';\nimport {\n  OutputWithMask as WithMask,\n  getBorderPositionCSS,\n  getBorderRadius,\n  getBorderStyle,\n  shouldDisplayBorder,\n} from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport WithLink from './components/withLink';\n\ninterface OutputElementProps {\n  element: Element;\n  flags: Record<string, boolean>;\n}\n\nfunction OutputElement({ element, flags }: OutputElementProps) {\n  const { id, opacity, type, isHidden } = element;\n\n  if (isHidden) {\n    return null;\n  }\n\n  const { Output, isMaskable } = getDefinitionForType(type);\n\n  // Box is calculated based on the 100%:100% basis for width and height\n  const box = getBox(element, 100, 100);\n  const { x, y, width, height, rotationAngle } = box;\n\n  const backgroundColor = elementIs.text(element)\n    ? element.backgroundColor\n    : null;\n\n  const isFillBackground =\n    elementIs.text(element) &&\n    element.backgroundTextMode === BACKGROUND_TEXT_MODE.FILL;\n\n  const isOverlayable = elementIs.overlayable(element);\n\n  // We're adding background styles in case of Fill here so that\n  // the background and the border would match together.\n  const bgStyles = {\n    backgroundClip: 'content-box',\n    ...generatePatternStyles(backgroundColor),\n  };\n\n  return (\n    <div\n      style={{\n        position: 'absolute',\n        pointerEvents: 'none',\n        left: x ? `${x}%` : 0,\n        top: y ? `${y}%` : 0,\n        width: `${width}%`,\n        height: `${height}%`,\n        ...(shouldDisplayBorder(element)\n          ? getBorderPositionCSS({\n              ...element.border,\n              width: `${width}%`,\n              height: `${height}%`,\n              posTop: `${y}%`,\n              posLeft: `${x}%`,\n            })\n          : null),\n        transform: rotationAngle ? `rotate(${rotationAngle}deg)` : undefined,\n        opacity: typeof opacity !== 'undefined' ? opacity / 100 : undefined,\n      }}\n    >\n      <AMPWrapper target={id}>\n        <WithMask\n          className={!isMaskable ? undefined : 'mask'}\n          element={element}\n          id={`el-${id}`}\n          style={{\n            ...(shouldDisplayBorder(element) ? getBorderStyle(element) : null),\n            pointerEvents: 'initial',\n            width: '100%',\n            height: '100%',\n            display: 'block',\n            position: 'absolute',\n            top: 0,\n            left: 0,\n            zIndex: 0,\n            ...getBorderRadius(element),\n            ...(isFillBackground ? bgStyles : null),\n          }}\n          skipDefaultMask\n        >\n          <WithLink\n            element={element}\n            style={{\n              width: '100%',\n              height: '100%',\n              display: 'block',\n              position: 'absolute',\n              top: 0,\n              left: 0,\n            }}\n          >\n            <Output element={element} box={box} flags={flags} />\n          </WithLink>\n          {isOverlayable && element.overlay && (\n            <div\n              className=\"element-overlay-area\"\n              style={generatePatternStyles(element.overlay)}\n            />\n          )}\n        </WithMask>\n      </AMPWrapper>\n    </div>\n  );\n}\n\nexport default OutputElement;\n"
  },
  {
    "path": "packages/output/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as OutputStory } from './story';\nexport { default as getStoryMarkup } from './utils/getStoryMarkup';\nexport { populateElementFontData } from './utils/populateElementFontData';\nexport { default as getTextElementTagNames } from './utils/getTextElementTagNames';\nexport * from './constants';\n"
  },
  {
    "path": "packages/output/src/page.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { PAGE_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\nimport { AnimationProvider, AMPAnimations } from '@googleforcreators/animation';\nimport {\n  isElementBelowLimit,\n  type Page,\n  elementIs,\n  type Element,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_AUTO_ADVANCE, DEFAULT_PAGE_DURATION } from './constants';\nimport OutputElement from './element';\nimport BackgroundAudio from './utils/backgroundAudio';\nimport getTextElementTagNames from './utils/getTextElementTagNames';\nimport getAutoAdvanceAfter from './utils/getAutoAdvanceAfter';\nimport Outlink from './utils/outlink';\nimport ShoppingAttachment from './utils/shoppingAttachment';\n\nconst ASPECT_RATIO = `${PAGE_WIDTH}:${PAGE_HEIGHT}`;\n\ninterface OutputPageProps {\n  page: Page;\n  defaultAutoAdvance?: boolean;\n  defaultPageDuration?: number;\n  flags: Record<string, boolean>;\n}\n\nfunction OutputPage({\n  page,\n  defaultAutoAdvance = DEFAULT_AUTO_ADVANCE,\n  defaultPageDuration = DEFAULT_PAGE_DURATION,\n  flags,\n}: OutputPageProps) {\n  const {\n    id,\n    animations,\n    advancement,\n    elements,\n    backgroundColor,\n    backgroundAudio,\n    pageAttachment = null,\n    shoppingAttachment = {},\n  } = page;\n\n  // Note: backgroundElement is undefined if elements is empty.\n  const [backgroundElement, ...otherElements] = elements;\n\n  // If the background element has base color set, it's media, use that.\n  const baseColor =\n    backgroundElement && elementIs.media(backgroundElement)\n      ? backgroundElement?.resource?.baseColor\n      : undefined;\n  const backgroundStyles = baseColor\n    ? { backgroundColor: baseColor }\n    : { backgroundColor: 'white', ...generatePatternStyles(backgroundColor) };\n\n  const {\n    autoAdvance = defaultAutoAdvance,\n    pageDuration = defaultPageDuration,\n  } = advancement || {};\n\n  const autoAdvanceAfter = autoAdvance\n    ? getAutoAdvanceAfter({\n        animations,\n        elements,\n        defaultPageDuration: pageDuration,\n        backgroundAudio,\n        id,\n      })\n    : undefined;\n\n  const tagNamesMap = getTextElementTagNames(\n    otherElements.filter(elementIs.text)\n  );\n\n  const regularElements = otherElements.map((element) => {\n    // Check if we need to change anything in this element\n\n    // Text elements need a tag name\n    const needsTagName = elementIs.text(element);\n    // Invalid links must be removed\n    // TODO: this should come from the pre-publish checklist in the future.\n    const hasIllegalLink = pageAttachment?.url && isElementBelowLimit(element);\n    const requiresChange = needsTagName || hasIllegalLink;\n\n    // If neither change needed, return original\n    if (!requiresChange) {\n      return element;\n    }\n\n    // At least one change needed, create shallow clone and modify that\n    const newElement: Element = { ...element };\n    if (elementIs.text(newElement)) {\n      newElement.tagName = tagNamesMap.get(element.id);\n    }\n    if (hasIllegalLink) {\n      delete newElement.link;\n    }\n    return newElement;\n  });\n\n  const products = elements\n    .filter(elementIs.product)\n    .filter(({ isHidden }) => !isHidden)\n    .map(({ product }) => product)\n    .filter(Boolean);\n\n  const hasProducts = products.length > 0;\n  const hasPageAttachment = pageAttachment?.url && !hasProducts;\n\n  const videoCaptions = elements\n    .filter(elementIs.video)\n    .filter(({ tracks }) => tracks?.length > 0)\n    .map(({ id: videoId }) => `el-${videoId}-captions`);\n\n  const backgroundAudioSrc = backgroundAudio?.resource?.src;\n  const hasBackgroundAudioCaptions = Boolean(backgroundAudio?.tracks?.length);\n  const hasNonLoopingBackgroundAudio =\n    false === backgroundAudio?.loop && backgroundAudio?.resource?.length;\n  const needsEnhancedBackgroundAudio =\n    hasBackgroundAudioCaptions || hasNonLoopingBackgroundAudio;\n\n  if (backgroundAudioSrc && hasBackgroundAudioCaptions) {\n    videoCaptions.push(`el-${id}-captions`);\n  }\n\n  return (\n    <amp-story-page\n      id={id}\n      auto-advance-after={autoAdvanceAfter}\n      background-audio={\n        backgroundAudioSrc && !needsEnhancedBackgroundAudio\n          ? backgroundAudioSrc\n          : undefined\n      }\n    >\n      <AnimationProvider animations={animations} elements={elements}>\n        <AMPAnimations />\n\n        {backgroundElement && (\n          <amp-story-grid-layer\n            template=\"vertical\"\n            aspect-ratio={ASPECT_RATIO}\n            class=\"grid-layer\"\n          >\n            <div className=\"page-fullbleed-area\" style={backgroundStyles}>\n              <div className=\"page-safe-area\">\n                <OutputElement element={backgroundElement} flags={flags} />\n                {elementIs.overlayable(backgroundElement) && (\n                  <div\n                    className=\"page-background-overlay-area\"\n                    style={generatePatternStyles(backgroundElement.overlay)}\n                  />\n                )}\n              </div>\n            </div>\n          </amp-story-grid-layer>\n        )}\n\n        {backgroundAudioSrc && needsEnhancedBackgroundAudio && (\n          <BackgroundAudio backgroundAudio={backgroundAudio} id={id} />\n        )}\n\n        <amp-story-grid-layer\n          template=\"vertical\"\n          aspect-ratio={ASPECT_RATIO}\n          class=\"grid-layer\"\n        >\n          <div className=\"page-fullbleed-area\">\n            <div className=\"page-safe-area\">\n              {regularElements.map((element) => (\n                <OutputElement\n                  key={element.id}\n                  element={element}\n                  flags={flags}\n                />\n              ))}\n            </div>\n          </div>\n        </amp-story-grid-layer>\n      </AnimationProvider>\n\n      {videoCaptions.length > 0 && (\n        <amp-story-grid-layer\n          template=\"vertical\"\n          aspect-ratio={ASPECT_RATIO}\n          class=\"grid-layer align-bottom\"\n        >\n          <div className=\"captions-area\">\n            {videoCaptions.map((captionId) => (\n              <amp-story-captions\n                id={captionId}\n                key={captionId}\n                layout=\"container\" // \"container\" layout will only occupy required height.\n                style-preset=\"default\"\n              />\n            ))}\n          </div>\n        </amp-story-grid-layer>\n      )}\n      {/* <amp-story-page-outlink> needs to be the last child element */}\n      {hasPageAttachment && <Outlink {...pageAttachment} />}\n      {hasProducts && (\n        <ShoppingAttachment products={products} {...shoppingAttachment} />\n      )}\n    </amp-story-page>\n  );\n}\n\nexport default OutputPage;\n"
  },
  {
    "path": "packages/output/src/story.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport getUsedAmpExtensions from './utils/getUsedAmpExtensions';\nimport Boilerplate from './utils/ampBoilerplate';\nimport CustomCSS from './utils/styles';\nimport FontDeclarations from './utils/fontDeclarations';\nimport OutputPage from './page';\nimport getPreloadResources from './utils/getPreloadResources';\nimport { populateElementFontData } from './utils/populateElementFontData';\nimport type { StoryMetadata, Story } from './types';\n\ninterface OutputStoryProps {\n  story: Story;\n  pages: Page[];\n  flags: Record<string, boolean>;\n  metadata: StoryMetadata;\n}\n\nfunction OutputStory({\n  story: {\n    featuredMedia,\n    link,\n    title,\n    fonts,\n    autoAdvance,\n    defaultPageDuration,\n    backgroundAudio,\n    publisherLogo,\n  },\n  pages,\n  metadata: { publisher },\n  flags,\n}: OutputStoryProps) {\n  const ampExtensions = getUsedAmpExtensions(pages);\n  const preloadResources = getPreloadResources(pages);\n\n  const featuredMediaUrl = featuredMedia?.url || '';\n  const publisherLogoUrl = publisherLogo?.url || '';\n\n  if (fonts && Object.keys(fonts).length >= 1) {\n    // if fonts are stored at the story level, populate the font data to the elements\n    pages = populateElementFontData(pages, fonts);\n  }\n\n  return (\n    <html amp=\"\" lang=\"en\">\n      <head>\n        <meta charSet=\"utf-8\" />\n        <meta\n          name=\"viewport\"\n          content=\"width=device-width,minimum-scale=1,initial-scale=1\"\n        />\n        {ampExtensions.map(({ name, src }) => (\n          <script\n            key={src}\n            // @ts-expect-error -- To ensure valid AMP on the frontend.\n            async=\"async\"\n            src={src}\n            custom-element={name}\n          />\n        ))}\n        <FontDeclarations pages={pages} />\n        {preloadResources.map(({ url, type }) => (\n          <link key={url} href={url} rel=\"preload\" as={type} />\n        ))}\n        <Boilerplate />\n        <CustomCSS />\n        {/* Everything between these markers can be replaced server-side. */}\n        <meta name=\"web-stories-replace-head-start\" />\n        <title>{title}</title>\n        {link && <link rel=\"canonical\" href={link} />}\n        <meta name=\"web-stories-replace-head-end\" />\n      </head>\n      <body>\n        <amp-story\n          standalone=\"\"\n          publisher={publisher}\n          publisher-logo-src={publisherLogoUrl}\n          title={title}\n          poster-portrait-src={featuredMediaUrl}\n          background-audio={backgroundAudio?.resource?.src ?? undefined}\n        >\n          {pages.map((page, index) => (\n            <OutputPage\n              key={page.id}\n              page={index === 0 ? { ...page, animations: undefined } : page}\n              defaultAutoAdvance={autoAdvance}\n              defaultPageDuration={defaultPageDuration}\n              flags={flags}\n            />\n          ))}\n        </amp-story>\n      </body>\n    </html>\n  );\n}\n\nexport default OutputStory;\n"
  },
  {
    "path": "packages/output/src/test/__snapshots__/page.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Page output background audio should add background audio as amp-video 1`] = `\n<amp-story-captions\n  id=\"el-123-captions\"\n  layout=\"container\"\n  style-preset=\"default\"\n/>\n`;\n\nexports[`Page output background audio should add background audio as amp-video 2`] = `\n<amp-video\n  autoplay=\"autoplay\"\n  captions-id=\"el-123-captions\"\n  crossorigin=\"anonymous\"\n  height=\"1\"\n  id=\"page-123-background-audio\"\n  layout=\"fixed\"\n  loop=\"loop\"\n  poster=\"\"\n  width=\"1\"\n>\n  <source\n    src=\"https://example.com/audio.mp3\"\n    type=\"audio/mpeg\"\n  />\n  <track\n    default=\"\"\n    kind=\"captions\"\n    label=\"\"\n    src=\"https://example.com/track.vtt\"\n  />\n</amp-video>\n`;\n\nexports[`Page output background audio should use amp-video for non-looping background audio 1`] = `\n<amp-video\n  autoplay=\"autoplay\"\n  height=\"1\"\n  id=\"page-123-background-audio\"\n  layout=\"fixed\"\n  poster=\"\"\n  width=\"1\"\n>\n  <source\n    src=\"https://example.com/audio.mp3\"\n    type=\"audio/mpeg\"\n  />\n</amp-video>\n`;\n\nexports[`Page output background audio should use amp-video with crossorigin=\"anonymous\" for background audio with tracks 1`] = `\n<amp-video\n  autoplay=\"autoplay\"\n  captions-id=\"el-123-captions\"\n  crossorigin=\"anonymous\"\n  height=\"1\"\n  id=\"page-123-background-audio\"\n  layout=\"fixed\"\n  poster=\"\"\n  width=\"1\"\n>\n  <source\n    src=\"https://example.com/audio.mp3\"\n    type=\"audio/mpeg\"\n  />\n  <track\n    default=\"\"\n    kind=\"captions\"\n    label=\"\"\n    src=\"https://example.com/track.vtt\"\n  />\n</amp-video>\n`;\n"
  },
  {
    "path": "packages/output/src/test/__snapshots__/textElement.tsx.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Text Element output should render text with adjusted font-size and family 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-3.5838895631067964% 0;font-family:&quot;Bungee Shade&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.728155em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with alignment 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:left;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with alignment 2`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:right;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with alignment 3`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with alignment 4`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:justify;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with applied rotation 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;transform:rotate(45deg);opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with bold, italic, and underline 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span><span style=\"font-weight: 700; font-style: italic; text-decoration: underline\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></span></p></div></div>\"`;\n\nexports[`Text Element output should render text with color 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span><span style=\"color: #0a08ec\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></span></p></div></div>\"`;\n\nexports[`Text Element output should render text with fill 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0;background-clip:content-box;background-color:#c4c4c4\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with highlight 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5em;text-align:center;padding:0;color:#000000;background-color:#c4c4c4;background:none\"><span style=\"display:block;position:relative;left:0;top:0;margin:-1.4335558252427185% 0;-webkit-box-decoration-break:clone;box-decoration-break:clone\"><span style=\"background-color:#c4c4c4;-webkit-box-decoration-break:clone;box-decoration-break:clone;position:relative;padding:0;text-align:center;border-radius:0px 0px 0px 0px;color:transparent\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></span></p><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5em;text-align:center;padding:0;color:#000000;background-color:#c4c4c4;background:none;position:absolute;top:0;left:0;right:0\" aria-hidden=\"true\"><span style=\"display:block;position:relative;left:0;top:0;margin:-1.4335558252427185% 0;-webkit-box-decoration-break:clone;box-decoration-break:clone\"><span style=\"background-color:#c4c4c4;-webkit-box-decoration-break:clone;box-decoration-break:clone;position:relative;padding:0;text-align:center;border-radius:0px 0px 0px 0px;background:none\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></span></p></div></div>\"`;\n\nexports[`Text Element output should render text with letter-spacing 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:0;color:#000000\"><span><span style=\"letter-spacing: 0.5em\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></span></p></div></div>\"`;\n\nexports[`Text Element output should render text with line-height 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-12.355885922330097% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:4;text-align:center;padding:0;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n\nexports[`Text Element output should render text with padding 1`] = `\"<div style=\"position:absolute;pointer-events:none;left:9.70874%;top:48.54369%;width:50%;height:12.13592%;opacity:1\"><div style=\"pointer-events:initial;width:100%;height:100%;display:block;position:absolute;top:0;left:0;z-index:0\" id=\"el-8d110168-e765-4c76-b63a-74ec23d54f27\"><p class=\"fill text-wrapper\" style=\"white-space:pre-line;overflow-wrap:break-word;word-break:break-word;margin:-1.4335558252427185% 0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.291262em;line-height:1.5;text-align:center;padding:12.135922330097088% 5.825242718446602%;color:#000000\"><span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span></p></div></div>\"`;\n"
  },
  {
    "path": "packages/output/src/test/_utils/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ElementType, FontService } from '@googleforcreators/elements';\n\nexport const DEFAULT_TEXT = {\n  opacity: 100,\n  flip: {\n    vertical: false,\n    horizontal: false,\n  },\n  rotationAngle: 0,\n  lockAspectRatio: true,\n  backgroundTextMode: 'NONE',\n  font: {\n    family: 'Roboto',\n    weights: [100, 300, 400, 500, 700, 900],\n    styles: ['italic', 'regular'],\n    variants: [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900],\n    ],\n    fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n    service: FontService.GoogleFonts,\n    metrics: {\n      upm: 2048,\n      asc: 1900,\n      des: -500,\n      tAsc: 1536,\n      tDes: -512,\n      tLGap: 102,\n      wAsc: 1946,\n      wDes: 512,\n      xH: 1082,\n      capH: 1456,\n      yMin: -555,\n      yMax: 2163,\n      hAsc: 1900,\n      hDes: -500,\n      lGap: 0,\n    },\n  },\n  fontSize: 18,\n  backgroundColor: {\n    color: {\n      r: 196,\n      g: 196,\n      b: 196,\n    },\n  },\n  lineHeight: 1.5,\n  textAlign: 'center',\n  padding: {\n    vertical: 0,\n    horizontal: 0,\n    locked: true,\n  },\n  type: ElementType.Text,\n  content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',\n  x: 40,\n  y: 300,\n  width: 206,\n  height: 75,\n  scale: 100,\n  focalX: 50,\n  focalY: 50,\n  id: '8d110168-e765-4c76-b63a-74ec23d54f27',\n};\n"
  },
  {
    "path": "packages/output/src/test/page.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport { render } from '@testing-library/react';\nimport { PAGE_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\nimport { MaskTypes } from '@googleforcreators/masks';\nimport {\n  type BackgroundableElement,\n  type MediaElement,\n  type PageAttachment,\n  type ProductData,\n  type ShoppingAttachment,\n  ElementType,\n  registerElementType,\n} from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport {\n  getByAutoAdvanceAfter,\n  getById,\n  queryByAutoAdvanceAfter,\n  queryById,\n} from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  AnimationType,\n  type StoryAnimation,\n} from '@googleforcreators/animation';\nimport { type Resource, ResourceType } from '@googleforcreators/media';\nimport PageOutput from '../page';\n\njest.mock('flagged');\n\nconst PRODUCT_LAMP: ProductData = {\n  productUrl: 'https://www.google.com',\n  productId: 'lamp',\n  productTitle: 'Brass Lamp',\n  productBrand: 'Lamp Co',\n  productPrice: 799.0,\n  productPriceCurrency: 'USD',\n  productImages: [\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 1' },\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 2' },\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 3' },\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 4' },\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 5' },\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'lamp 6' },\n  ],\n  aggregateRating: {\n    ratingValue: 4.4,\n    reviewCount: 89,\n    reviewUrl: 'https://www.google.com',\n  },\n  productDetails:\n    'One newline after this. \\n Two newlines after this. \\n\\n  Five consecutive newlines after this, should become 2 newlines. \\n\\n\\n\\n\\n Many consecutive newlines with different spacing and tabs after this, should become 2 newlines. \\n          \\n\\n   \\n  \\n \\n  \\n \\n I hope it works!',\n};\n\nconst PRODUCT_ART: ProductData = {\n  productUrl: 'https://www.google.com',\n  productId: 'art',\n  productTitle: 'Abstract Art',\n  productBrand: 'V. Artsy',\n  productPrice: 1200.0,\n  productPriceCurrency: 'INR',\n  productImages: [\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'art' },\n  ],\n  aggregateRating: {\n    ratingValue: 4.4,\n    reviewCount: 89,\n    reviewUrl: 'https://www.google.com',\n  },\n  productDetails: 'Some short text',\n};\n\nconst PRODUCT_CHAIR: ProductData = {\n  productUrl: 'https://www.google.com',\n  productId: 'chair',\n  productTitle: 'Yellow chair',\n  productBrand: 'The Chair Company',\n  productPrice: 1000.0,\n  productPriceCurrency: 'BRL',\n  productImages: [\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'chair' },\n  ],\n  aggregateRating: {\n    ratingValue: 4.4,\n    reviewCount: 89,\n    reviewUrl: 'https://www.google.com',\n  },\n  productDetails:\n    'Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere error deserunt dignissimos in laborum ea molestias veritatis sint laudantium iusto expedita atque provident doloremque, ad voluptatem culpa adipisci.',\n};\n\nconst PRODUCT_FLOWERS: ProductData = {\n  productUrl: 'https://www.google.com',\n  productId: 'flowers',\n  productTitle: 'Flowers',\n  productBrand: 'Very Long Flower Company Name',\n  productPrice: 10.0,\n  productPriceCurrency: 'USD',\n  productIcon: '/examples/visual-tests/amp-story/img/shopping/icon.png',\n  productImages: [\n    { url: '/examples/visual-tests/amp-story/img/cat1.jpg', alt: 'flowers' },\n  ],\n  aggregateRating: {\n    ratingValue: 4.4,\n    reviewCount: 89,\n    reviewUrl: 'https://www.google.com',\n  },\n  productDetails:\n    'Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere error deserunt dignissimos in laborum ea molestias veritatis sint laudantium iusto expedita atque provident doloremque, ad voluptatem culpa adipisci.',\n};\n\ndescribe('Page output', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  describe('aspect-ratio markup', () => {\n    let backgroundElement: BackgroundableElement & MediaElement;\n\n    beforeEach(() => {\n      backgroundElement = {\n        isBackground: true,\n        id: 'baz',\n        type: ElementType.Image,\n        scale: 1,\n        x: 50,\n        y: 100,\n        height: 1920,\n        width: 1080,\n        rotationAngle: 0,\n        resource: {\n          type: ResourceType.Image,\n          mimeType: 'image/png',\n          id: 123,\n          src: 'https://example.com/image.png',\n          poster: 'https://example.com/poster.png',\n          height: 1920,\n          width: 1080,\n          alt: '',\n          isExternal: false,\n        } as Resource,\n      };\n    });\n\n    it('should render a single layer with no background', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const layers = container.querySelectorAll('amp-story-grid-layer');\n      expect(layers).toHaveLength(1);\n      const layer = layers[0];\n      expect(layer).toHaveAttribute(\n        'aspect-ratio',\n        `${PAGE_WIDTH}:${PAGE_HEIGHT}`\n      );\n      expect(layer.firstElementChild).toHaveClass('page-fullbleed-area', {\n        exact: true,\n      });\n      expect(layer.firstElementChild?.firstElementChild).toHaveClass(\n        'page-safe-area',\n        { exact: true }\n      );\n    });\n\n    it('should render the layer for background', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [backgroundElement],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const layers = container.querySelectorAll('amp-story-grid-layer');\n      expect(layers).toHaveLength(2);\n      const bgLayer = layers[0];\n      expect(bgLayer).toHaveAttribute(\n        'aspect-ratio',\n        `${PAGE_WIDTH}:${PAGE_HEIGHT}`\n      );\n      expect(bgLayer.children).toHaveLength(1);\n      expect(bgLayer.children[0]).toHaveClass('page-fullbleed-area', {\n        exact: true,\n      });\n      expect(bgLayer.children[0].children[0]).toHaveClass('page-safe-area', {\n        exact: true,\n      });\n    });\n\n    it('should render the layer for background with overlay', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              ...backgroundElement,\n              overlay: { color: { r: 0, g: 255, b: 0, a: 0.4 } },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const overlayLayer = container.querySelector(\n        '.page-background-overlay-area'\n      );\n      expect(overlayLayer).toBeInTheDocument();\n    });\n  });\n\n  describe('animation markup', () => {\n    it('should render animation tags for animations', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          animations: [\n            {\n              id: '123',\n              targets: ['123', '124'],\n              type: AnimationType.Bounce,\n              duration: 1000,\n            },\n            {\n              id: '124',\n              targets: ['123'],\n              type: AnimationType.Spin,\n              duration: 1000,\n            },\n          ] as StoryAnimation[],\n          elements: [\n            {\n              id: '123',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: true,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/image.png',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n            },\n            {\n              id: '124',\n              type: ElementType.Shape,\n              opacity: 100,\n              flip: {\n                vertical: false,\n                horizontal: false,\n              },\n              rotationAngle: 0,\n              lockAspectRatio: true,\n              backgroundColor: {\n                color: {\n                  r: 51,\n                  g: 51,\n                  b: 51,\n                },\n              },\n              x: 249,\n              y: 67,\n              width: 147,\n              height: 147,\n              scale: 100,\n              focalX: 50,\n              focalY: 50,\n              mask: {\n                type: 'circle',\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n\n      const storyAnimations = container.querySelectorAll('amp-story-animation');\n      expect(storyAnimations).toHaveLength(3);\n      expect(storyAnimations[0]).toHaveAttribute('trigger', `visibility`);\n    });\n  });\n\n  describe('page advancement', () => {\n    it('should use default value for auto-advance-after', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(queryByAutoAdvanceAfter(container, '7s')).not.toBeInTheDocument();\n    });\n\n    it('should use default duration for auto-advance-after', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(getByAutoAdvanceAfter(container, '7s')).toBeInTheDocument();\n    });\n\n    it('should use custom value for auto-advance-after', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          advancement: { autoAdvance: false },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(queryByAutoAdvanceAfter(container, '7s')).not.toBeInTheDocument();\n    });\n\n    it('should use custom duration for auto-advance-after', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          advancement: { autoAdvance: true, pageDuration: 9 },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(getByAutoAdvanceAfter(container, '9s')).toBeInTheDocument();\n    });\n\n    it('should use default duration for images', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Image,\n              mimeType: 'image/png',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: true,\n              resource: {\n                type: 'image',\n                mimeType: 'image/png',\n                id: 123,\n                src: 'https://example.com/image.png',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(getByAutoAdvanceAfter(container, '7s')).toBeInTheDocument();\n    });\n\n    it('should use video element ID for auto-advance-after', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: false,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const video = queryById(container, 'el-baz-media');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchInlineSnapshot(`\n        <amp-video\n          artwork=\"https://example.com/poster.png\"\n          autoplay=\"autoplay\"\n          id=\"el-baz-media\"\n          layout=\"fill\"\n          poster=\"https://example.com/poster.png\"\n        >\n          <source\n            src=\"https://example.com/video.mp4\"\n            type=\"video/mp4\"\n          />\n        </amp-video>\n      `);\n      expect(\n        getByAutoAdvanceAfter(container, 'el-baz-media')\n      ).toBeInTheDocument();\n    });\n\n    it('should use video with volume', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: false,\n              volume: 0.5,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n            },\n          ],\n        },\n        autoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const video = queryById(container, 'el-baz-media');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchInlineSnapshot(`\n        <amp-video\n          artwork=\"https://example.com/poster.png\"\n          autoplay=\"autoplay\"\n          id=\"el-baz-media\"\n          layout=\"fill\"\n          poster=\"https://example.com/poster.png\"\n          volume=\"0.5\"\n        >\n          <source\n            src=\"https://example.com/video.mp4\"\n            type=\"video/mp4\"\n          />\n        </amp-video>\n      `);\n      expect(\n        getByAutoAdvanceAfter(container, 'el-baz-media')\n      ).toBeInTheDocument();\n    });\n\n    it('should use video element ID for auto-advance-after if video is below defaultPageDuration', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: false,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 1,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const video = getById(container, 'el-baz-media');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchInlineSnapshot(`\n        <amp-video\n          artwork=\"https://example.com/poster.png\"\n          autoplay=\"autoplay\"\n          id=\"el-baz-media\"\n          layout=\"fill\"\n          poster=\"https://example.com/poster.png\"\n        >\n          <source\n            src=\"https://example.com/video.mp4\"\n            type=\"video/mp4\"\n          />\n        </amp-video>\n      `);\n      expect(\n        getByAutoAdvanceAfter(container, 'el-baz-media')\n      ).toBeInTheDocument();\n    });\n\n    it('should ignore looping video for auto-advance-after and set default instead', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: true,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      expect(getByAutoAdvanceAfter(container, '7s')).toBeInTheDocument();\n    });\n  });\n\n  describe('pageAttachment', () => {\n    const BACKGROUND_ELEMENT = {\n      isBackground: true,\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 1,\n      height: 1,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n      },\n    };\n\n    const TEXT_ELEMENT = {\n      id: 'baz',\n      type: ElementType.Text,\n      content: 'Hello, link!',\n      x: 50,\n      y: PAGE_HEIGHT,\n      height: 300,\n      width: 100,\n      rotationAngle: 10,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n      fontSize: 30,\n      font: {\n        family: 'Roboto',\n        service: 'fonts.google.com',\n      },\n      color: {\n        color: {\n          r: 255,\n          g: 255,\n          b: 255,\n          a: 0.5,\n        },\n      },\n    };\n\n    it('should output page attachment if the URL is set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n          pageAttachment: {\n            url: 'https://example.test',\n            ctaText: 'Click me!',\n            theme: 'dark',\n            icon: 'https://example.test/example.jpg',\n          } as PageAttachment,\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).toHaveTextContent('Click me!');\n      expect(pageOutlink).toHaveAttribute(\n        'cta-image',\n        'https://example.test/example.jpg'\n      );\n      expect(pageOutlink).toHaveAttribute('theme', 'dark');\n      expect(pageOutlink?.firstChild).toHaveAttribute(\n        'href',\n        'https://example.test'\n      );\n      expect(pageOutlink).toBeInTheDocument();\n    });\n\n    it('should not output page attachment if the URL is empty', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n          pageAttachment: {\n            url: '',\n            ctaText: 'Click me!',\n          },\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).not.toBeInTheDocument();\n    });\n\n    it('should not output cta-image if empty', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n          pageAttachment: {\n            url: 'https://example.test',\n            ctaText: 'Click me!',\n            theme: 'dark',\n            icon: '',\n          } as PageAttachment,\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).toHaveTextContent('Click me!');\n      expect(pageOutlink).not.toHaveAttribute('cta-image');\n      expect(pageOutlink).toBeInTheDocument();\n    });\n\n    it('should output rel', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n          pageAttachment: {\n            url: 'https://example.test',\n            ctaText: 'Click me!',\n            theme: 'dark',\n            icon: '',\n            rel: ['nofollow'],\n          } as PageAttachment,\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).not.toBeNull();\n      expect(pageOutlink).toBeInTheDocument();\n      expect(pageOutlink).toHaveTextContent('Click me!');\n      expect(pageOutlink).not.toHaveAttribute('cta-image');\n\n      const pageOutATag = pageOutlink?.querySelector('a');\n      expect(pageOutATag).toBeInTheDocument();\n      expect(pageOutATag).toHaveAttribute('rel', 'nofollow');\n    });\n\n    it('should not output a link in page attachment area', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...TEXT_ELEMENT,\n              link: {\n                url: 'https://shouldremove.com',\n              },\n            },\n          ],\n          pageAttachment: {\n            url: 'https://example.com',\n            ctaText: 'Click me!',\n          },\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('Hello, link');\n      expect(content).not.toContain('https://shouldremove.com');\n    });\n\n    it('should output a link outside of page attachment area', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...TEXT_ELEMENT,\n              link: {\n                url: 'https://shouldoutput.com',\n              },\n              y: 0,\n              height: 100,\n            },\n          ],\n          pageAttachment: {\n            url: 'https://example.com',\n            ctaText: 'Click me!',\n          },\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('Hello, link');\n      expect(content).toContain('https://shouldoutput.com');\n    });\n\n    it('should output a link in page attachment area if page attachment is not set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...TEXT_ELEMENT,\n              link: {\n                url: 'https://shouldoutput.com',\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('Hello, link');\n      expect(content).toContain('https://shouldoutput.com');\n    });\n\n    it('should print page attachment as the last child element', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          pageAttachment: {\n            url: 'https://example.com',\n            ctaText: 'Click me!',\n          },\n          animations: [],\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: false,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n              tracks: [\n                {\n                  track: 'https://example.com/track.vtt',\n                  trackId: 123,\n                  trackName: 'track.vtt',\n                  id: 'rersd-fdfd-fdfd-fdfd',\n                  srcLang: '',\n                  label: '',\n                  kind: 'captions',\n                },\n              ],\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const page = container.querySelector('amp-story-page');\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).toBeInTheDocument();\n      expect(page?.lastChild).toBe(pageOutlink);\n    });\n  });\n\n  describe('background color', () => {\n    const BACKGROUND_ELEMENT = {\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 1,\n      height: 1,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n        baseColor: '#00379b',\n      },\n    };\n\n    it('should output background media base color if available', () => {\n      const props = {\n        id: '123',\n        page: {\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          id: '123',\n          elements: [BACKGROUND_ELEMENT],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('background-color:#00379b');\n    });\n\n    it('should output the page background color in case of default background element', () => {\n      const props = {\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255, a: 0.5 } },\n          elements: [\n            {\n              id: '123',\n              type: ElementType.Shape,\n              isBackground: true,\n              isDefaultBackground: true,\n              x: 1,\n              y: 1,\n              width: 1,\n              height: 1,\n              rotationAngle: 0,\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('background-color:rgba(255,255,255,0.5)');\n    });\n  });\n\n  describe('link', () => {\n    const BACKGROUND_ELEMENT = {\n      isBackground: true,\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 1,\n      height: 1,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n      },\n    };\n\n    const TEXT_ELEMENT = {\n      id: 'baz',\n      type: ElementType.Text,\n      content: 'Hello, link!',\n      x: 50,\n      y: PAGE_HEIGHT,\n      height: 300,\n      width: 100,\n      rotationAngle: 10,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n      fontSize: 30,\n      font: {\n        family: 'Roboto',\n        service: 'fonts.google.com',\n      },\n      color: {\n        color: {\n          r: 255,\n          g: 255,\n          b: 255,\n          a: 0.5,\n        },\n      },\n    };\n\n    it('should output element with link if the url is set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...TEXT_ELEMENT,\n              link: {\n                url: 'https://hello.example',\n                desc: 'Hello, example!',\n                icon: 'https://hello.example/icon.png',\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('Hello, example!');\n      expect(content).toContain('https://hello.example');\n    });\n\n    it('should not output element link if the url is empty', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...TEXT_ELEMENT,\n              link: {\n                url: '',\n                desc: 'Hello, example!',\n                icon: 'https://hello.example/icon.png',\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).not.toContain('Hello, example!');\n      expect(content).not.toContain('https://hello.example');\n    });\n  });\n\n  describe('border', () => {\n    const BACKGROUND_ELEMENT = {\n      isBackground: true,\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 1,\n      height: 1,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n      },\n    };\n\n    const MEDIA_ELEMENT = {\n      ...BACKGROUND_ELEMENT,\n      isBackground: false,\n    };\n\n    it('should output element with border if border is set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...MEDIA_ELEMENT,\n              border: {\n                top: 10,\n                left: 10,\n                right: 10,\n                bottom: 10,\n                color: { color: { r: 255, g: 255, b: 255 } },\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('border-width:10px 10px 10px 10px;');\n      expect(content).toContain('border-color:rgba(255,255,255,1);');\n    });\n\n    it('should not output border if the element is not rectangular', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...MEDIA_ELEMENT,\n              border: {\n                top: 10,\n                left: 10,\n                right: 10,\n                bottom: 10,\n                color: { color: { r: 255, g: 255, b: 255 } },\n                position: 'center',\n              },\n              mask: {\n                type: MaskTypes.CIRCLE,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).not.toContain('border-width:10px 10px 10px 10px;');\n      expect(content).not.toContain('border-color:rgba(255,255,255,1);');\n    });\n  });\n\n  describe('overlay', () => {\n    const BACKGROUND_ELEMENT = {\n      isBackground: true,\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 1,\n      height: 1,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n      },\n    };\n\n    const MEDIA_ELEMENT = {\n      ...BACKGROUND_ELEMENT,\n      isBackground: false,\n    };\n\n    it('should output image with linear overlay if set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...MEDIA_ELEMENT,\n              overlay: {\n                type: 'linear',\n                rotation: 0,\n                stops: [\n                  { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n                  { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n                ],\n                alpha: 0.7,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain(\n        'background-image:linear-gradient(0.5turn, rgba(0,0,0,0) 0%, rgba(0,0,0,0.7) 100%)'\n      );\n    });\n\n    it('should output video with solid overlay if set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...MEDIA_ELEMENT,\n              type: ElementType.Video,\n              overlay: {\n                color: { r: 0, g: 0, b: 0, a: 0.5 },\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain('background-color:rgba(0,0,0,0.5)');\n    });\n  });\n\n  describe('borderRadius', () => {\n    const BACKGROUND_ELEMENT = {\n      isBackground: true,\n      id: 'baz',\n      type: ElementType.Image,\n      mimeType: 'image/png',\n      origRatio: 1,\n      x: 50,\n      y: 100,\n      scale: 1,\n      rotationAngle: 0,\n      width: 10,\n      height: 10,\n      resource: {\n        type: 'image',\n        mimeType: 'image/png',\n        id: 123,\n        src: 'https://example.com/image.png',\n        poster: 'https://example.com/poster.png',\n        height: 1,\n        width: 1,\n      },\n    };\n\n    const MEDIA_ELEMENT = {\n      ...BACKGROUND_ELEMENT,\n      isBackground: false,\n      id: 'baz',\n      type: ElementType.Image,\n      borderRadius: {\n        locked: false,\n        topLeft: 10,\n        topRight: 20,\n        bottomRight: 10,\n        bottomLeft: 10,\n      },\n    };\n\n    it('should output element with border radius if the radius is set', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [BACKGROUND_ELEMENT, MEDIA_ELEMENT],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain(\n        'border-radius:100% 200% 100% 100% / 100% 200% 100% 100%'\n      );\n    });\n\n    it('should not output border radius if the element is not rectangular', () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            BACKGROUND_ELEMENT,\n            {\n              ...MEDIA_ELEMENT,\n              mask: {\n                type: MaskTypes.CIRCLE,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).not.toContain(\n        'border-radius:100% 200% 100% 100% / 100% 200% 100% 100%'\n      );\n    });\n  });\n\n  describe('background audio', () => {\n    it('should add background audio', () => {\n      const props = {\n        id: '123',\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            loop: true,\n            tracks: [],\n          },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const content = renderToStaticMarkup(\n        <PageOutput {...props} flags={{}} />\n      );\n      expect(content).toContain(\n        'background-audio=\"https://example.com/audio.mp3\"'\n      );\n      expect(content).not.toContain('amp-video');\n    });\n\n    it('should add background audio as amp-video', () => {\n      const props = {\n        id: '123',\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [\n              {\n                track: 'https://example.com/track.vtt',\n                trackId: 123,\n                trackName: 'track.vtt',\n                id: 'rersd-fdfd-fdfd-fdfd',\n                srcLang: '',\n                label: '',\n                kind: 'captions',\n              },\n            ],\n            loop: true,\n          },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n\n      const captions = container.querySelector('amp-story-captions');\n      expect(captions).toBeInTheDocument();\n      expect(captions).toMatchSnapshot();\n      expect(captions).toHaveAttribute('id', 'el-123-captions');\n\n      const video = container.querySelector('amp-video');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchSnapshot();\n      expect(video).toHaveAttribute('captions-id', 'el-123-captions');\n\n      const page = container.querySelector('amp-story-page');\n      expect(page).toBeInTheDocument();\n      expect(page).not.toContain(\n        'background-audio=\"https://example.com/audio.mp3\"'\n      );\n    });\n\n    it('should not contain background audio if missing', () => {\n      const props = {\n        id: '123',\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const page = container.querySelector('amp-story-page');\n      expect(page).toBeInTheDocument();\n      expect(page).not.toContain('background-audio=');\n    });\n\n    it('should use amp-video for non-looping background audio', () => {\n      const props = {\n        id: '123',\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [],\n            loop: false,\n          },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const video = container.querySelector('amp-video');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchSnapshot();\n\n      const page = container.querySelector('amp-story-page');\n      expect(page).toBeInTheDocument();\n      expect(page).not.toContain(\n        'background-audio=\"https://example.com/audio.mp3\"'\n      );\n    });\n\n    it('should use amp-video with crossorigin=\"anonymous\" for background audio with tracks', () => {\n      const props = {\n        id: '123',\n        page: {\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [\n              {\n                track: 'https://example.com/track.vtt',\n                trackId: 123,\n                trackName: 'track.vtt',\n                id: 'rersd-fdfd-fdfd-fdfd',\n                srcLang: '',\n                label: '',\n                kind: 'captions',\n              },\n            ],\n            loop: false,\n          },\n          id: '123',\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const video = container.querySelector('amp-video');\n      expect(video).toBeInTheDocument();\n      expect(video).toMatchSnapshot();\n\n      const page = container.querySelector('amp-story-page');\n      expect(page).toBeInTheDocument();\n      expect(page).not.toContain(\n        'background-audio=\"https://example.com/audio.mp3\"'\n      );\n    });\n  });\n\n  describe('video captions', () => {\n    it('should render layer for amp-story-captions', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'baz',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: false,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/video.mp4',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n              tracks: [\n                {\n                  track: 'https://example.com/track.vtt',\n                  trackId: 123,\n                  trackName: 'track.vtt',\n                  id: 'rersd-fdfd-fdfd-fdfd',\n                  srcLang: '',\n                  label: '',\n                  kind: 'captions',\n                },\n              ],\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const captions = container.querySelector('amp-story-captions');\n      expect(captions).toBeInTheDocument();\n      expect(captions).toMatchInlineSnapshot(`\n      <amp-story-captions\n        id=\"el-baz-captions\"\n        layout=\"container\"\n        style-preset=\"default\"\n      />\n      `);\n    });\n  });\n\n  describe('Shopping', () => {\n    it('should render shopping attachment if there are products', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'el1',\n              type: ElementType.Product,\n              x: 50,\n              y: 50,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_LAMP,\n            },\n            {\n              id: 'el2',\n              type: ElementType.Product,\n              x: 100,\n              y: 100,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_ART,\n            },\n          ],\n        },\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const shoppingAttachment = container.querySelector(\n        'amp-story-shopping-attachment'\n      );\n      expect(shoppingAttachment).toBeInTheDocument();\n    });\n\n    it('should render shopping attachment with custom cta text if there are products', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          shoppingAttachment: {\n            theme: 'light',\n            ctaText: 'Buy now',\n          } as ShoppingAttachment,\n          elements: [\n            {\n              id: 'el1',\n              type: ElementType.Product,\n              x: 50,\n              y: 50,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_LAMP,\n            },\n            {\n              id: 'el2',\n              type: ElementType.Product,\n              x: 100,\n              y: 100,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_ART,\n            },\n          ],\n        },\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const shoppingAttachment = container.querySelector(\n        'amp-story-shopping-attachment'\n      );\n\n      expect(shoppingAttachment).toBeInTheDocument();\n      expect(shoppingAttachment).toHaveAttribute('cta-text', 'Buy now');\n      expect(shoppingAttachment).toHaveAttribute('theme', 'light');\n    });\n\n    it('should not render page attachment if there are products', () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'el1',\n              type: ElementType.Product,\n              x: 50,\n              y: 50,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_LAMP,\n            },\n            {\n              id: 'el2',\n              type: ElementType.Product,\n              x: 100,\n              y: 100,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_ART,\n            },\n          ],\n          pageAttachment: {\n            url: 'https://example.com',\n            ctaText: 'Click me!',\n          },\n        },\n      };\n\n      const { container } = render(<PageOutput {...props} flags={{}} />);\n      const shoppingAttachment = container.querySelector(\n        'amp-story-shopping-attachment'\n      );\n      expect(shoppingAttachment).toBeInTheDocument();\n      const pageOutlink = container.querySelector('amp-story-page-outlink');\n      expect(pageOutlink).not.toBeInTheDocument();\n    });\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid AMP output with manual page advancement', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: false,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid AMP output with custom page duration', async () => {\n      const props = {\n        id: 's1',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'p1',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          advancement: { autoAdvance: true, pageDuration: 10 },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 7,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid AMP output with custom manual page advancement', async () => {\n      const props = {\n        id: 's1',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'p1',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          advancement: { autoAdvance: false },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid AMP output with Page Attachment', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        pageAttachment: {\n          url: 'https://example.com',\n          ctaText: 'Click me!',\n        },\n      };\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid output with media elements', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: '123',\n              type: ElementType.Video,\n              mimeType: 'video/mp4',\n              scale: 1,\n              origRatio: 9 / 16,\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              loop: true,\n              resource: {\n                type: 'video',\n                mimeType: 'video/mp4',\n                id: 123,\n                src: 'https://example.com/image.png',\n                poster: 'https://example.com/poster.png',\n                height: 1920,\n                width: 1080,\n                length: 99,\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid output with animations', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          animations: [\n            {\n              id: '123',\n              targets: ['123'],\n              type: AnimationType.Bounce,\n              duration: 1000,\n            },\n          ] as StoryAnimation[],\n          elements: [\n            {\n              type: ElementType.Text,\n              id: '123',\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              content: 'Hello World',\n              color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n              padding: {\n                horizontal: 0,\n                vertical: 0,\n              },\n              font: {\n                family: 'Roboto',\n                service: 'fonts.google.com',\n              },\n            },\n          ],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid output with background audio', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [],\n            loop: true,\n          },\n          animations: [],\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid output with background audio with captions', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [\n              {\n                track: 'https://example.com/track.vtt',\n                trackId: 123,\n                trackName: 'track.vtt',\n                id: 'rersd-fdfd-fdfd-fdfd',\n                srcLang: '',\n                label: '',\n                kind: 'captions',\n              },\n            ],\n            loop: false,\n          },\n          animations: [],\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it('should produce valid output with non-looping background audio', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: '123',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n            tracks: [],\n            loop: false,\n          },\n          animations: [],\n          elements: [],\n        },\n        defaultAutoAdvance: true,\n        defaultPageDuration: 11,\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n\n    it.skip('should produce valid output with shopping products', async () => {\n      const props = {\n        id: 'foo',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        page: {\n          id: 'bar',\n          backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          elements: [\n            {\n              id: 'el1',\n              type: ElementType.Product,\n              x: 50,\n              y: 50,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_LAMP,\n            },\n            {\n              id: 'el2',\n              type: ElementType.Product,\n              x: 100,\n              y: 100,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_ART,\n            },\n            {\n              id: 'el3',\n              type: ElementType.Product,\n              x: 150,\n              y: 150,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_CHAIR,\n            },\n            {\n              id: 'el3',\n              type: ElementType.Product,\n              x: 200,\n              y: 200,\n              width: 32,\n              height: 32,\n              rotationAngle: 0,\n              product: PRODUCT_FLOWERS,\n            },\n          ],\n        },\n      };\n\n      await expect(\n        <PageOutput {...props} flags={{}} />\n      ).toBeValidAMPStoryPage();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/output/src/test/story.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport { ElementType, registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport {\n  AnimationType,\n  type StoryAnimation,\n} from '@googleforcreators/animation';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport StoryOutput from '../story';\n\ndescribe('Story output', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should include Google Fonts stylesheet', () => {\n    const props = {\n      id: '123',\n      backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n      story: {\n        title: 'Example',\n        slug: 'example',\n        status: 'publish',\n        author: { id: 1, name: 'John Doe' },\n        date: '123',\n        modified: '123',\n        excerpt: '123',\n        featuredMedia: {\n          id: 123,\n          url: 'https://example.com/poster.png',\n          width: 640,\n          height: 853,\n        },\n        fonts: {},\n        publisherLogo: {\n          id: 1,\n          url: 'https://example.com/logo.png',\n          height: 0,\n          width: 0,\n        },\n        password: '123',\n        link: 'https://example.com/story',\n        autoAdvance: false,\n      },\n      pages: [\n        {\n          id: '123',\n          animations: [\n            {\n              id: 'anim1',\n              targets: ['123'],\n              type: AnimationType.Bounce,\n              duration: 1000,\n            },\n            {\n              id: 'anim1',\n              targets: ['124'],\n              type: AnimationType.Spin,\n              duration: 500,\n            },\n          ] as StoryAnimation[],\n          backgroundColor: {\n            color: { r: 255, g: 255, b: 255 },\n          },\n          page: {\n            id: '123',\n          },\n          elements: [\n            {\n              type: ElementType.Text,\n              id: '123',\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              content: '<span style=\"font-style: italic\">Hello World</span>',\n              color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n              padding: {\n                horizontal: 0,\n                vertical: 0,\n              },\n              font: {\n                family: 'Roboto',\n                service: 'fonts.google.com',\n                variants: [\n                  [0, 400],\n                  [1, 400],\n                ],\n              },\n            },\n            {\n              type: ElementType.Text,\n              id: '124',\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              content: '<span style=\"font-weight: 400\">Hello World</span>',\n              color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n              padding: {\n                horizontal: 0,\n                vertical: 0,\n              },\n              font: {\n                family: 'Lato',\n                service: 'fonts.google.com',\n                variants: [\n                  [0, 400],\n                  [1, 400],\n                ],\n              },\n            },\n          ],\n        },\n      ],\n      metadata: {\n        publisher: 'Publisher Name',\n      },\n    };\n\n    const content = renderToStaticMarkup(<StoryOutput {...props} flags={{}} />);\n\n    expect(content).toContain(\n      '<link href=\"https://fonts.googleapis.com/css2?display=swap&amp;family=Roboto%3Aital%401&amp;family=Lato\" rel=\"stylesheet\"/>'\n    );\n  });\n\n  it('should add background audio', () => {\n    const props = {\n      id: '123',\n      backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n      story: {\n        title: 'Example',\n        slug: 'example',\n        status: 'publish',\n        author: { id: 1, name: 'John Doe' },\n        date: '123',\n        modified: '123',\n        excerpt: '123',\n        featuredMedia: {\n          id: 123,\n          url: 'https://example.com/poster.png',\n          width: 640,\n          height: 853,\n        },\n        publisherLogo: {\n          id: 1,\n          url: 'https://example.com/logo.png',\n          height: 0,\n          width: 0,\n        },\n        password: '123',\n        link: 'https://example.com/story',\n        autoAdvance: false,\n        backgroundAudio: {\n          resource: {\n            type: ResourceType.Audio,\n            src: 'https://example.com/audio.mp3',\n            id: 123,\n            mimeType: 'audio/mpeg',\n            length: 100,\n            lengthFormatted: '1:40',\n          },\n        },\n        fonts: {},\n      },\n      pages: [\n        {\n          id: '123',\n          animations: [\n            {\n              id: 'anim1',\n              targets: ['123'],\n              type: AnimationType.Bounce,\n              duration: 1000,\n            },\n            {\n              id: 'anim1',\n              targets: ['123'],\n              type: AnimationType.Spin,\n              duration: 500,\n            },\n          ] as StoryAnimation[],\n          backgroundColor: {\n            color: { r: 255, g: 255, b: 255 },\n          },\n          page: {\n            id: '123',\n          },\n          elements: [\n            {\n              type: ElementType.Text,\n              id: '123',\n              x: 50,\n              y: 100,\n              height: 1920,\n              width: 1080,\n              rotationAngle: 0,\n              content: 'Hello World',\n              color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n              padding: {\n                horizontal: 0,\n                vertical: 0,\n              },\n              font: {\n                family: 'Roboto',\n                service: 'fonts.google.com',\n              },\n            },\n          ],\n        },\n      ],\n      metadata: {\n        publisher: 'Publisher Name',\n      },\n    };\n\n    const content = renderToStaticMarkup(<StoryOutput {...props} flags={{}} />);\n\n    expect(content).toContain(\n      'background-audio=\"https://example.com/audio.mp3\"'\n    );\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('requires at least one page', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n        story: {\n          title: 'Example',\n          slug: 'example',\n          status: 'publish',\n          author: { id: 1, name: 'John Doe' },\n          date: '123',\n          modified: '123',\n          excerpt: '123',\n          featuredMedia: {\n            id: 123,\n            url: 'https://example.com/poster.png',\n            width: 640,\n            height: 853,\n          },\n          publisherLogo: {\n            id: 1,\n            url: 'https://example.com/logo.png',\n            height: 0,\n            width: 0,\n          },\n          password: '123',\n          link: 'https://example.com/story',\n          autoAdvance: false,\n          fonts: {},\n        },\n        pages: [],\n        metadata: {\n          publisher: 'Publisher Name',\n        },\n      };\n\n      await expect(<StoryOutput {...props} flags={{}} />).not.toBeValidAMP();\n    });\n\n    it('should produce valid AMP output', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        story: {\n          title: 'Example',\n          slug: 'example',\n          status: 'publish',\n          author: { id: 1, name: 'John Doe' },\n          date: '123',\n          modified: '123',\n          excerpt: '123',\n          featuredMedia: {\n            id: 123,\n            url: 'https://example.com/poster.png',\n            width: 640,\n            height: 853,\n          },\n          publisherLogo: {\n            id: 1,\n            url: 'https://example.com/logo.png',\n            height: 0,\n            width: 0,\n          },\n          password: '123',\n          link: 'https://example.com/story',\n          autoAdvance: false,\n          fonts: {},\n        },\n        pages: [\n          {\n            id: '123',\n            backgroundColor: {\n              color: { r: 255, g: 255, b: 255 },\n            },\n            page: {\n              id: '123',\n            },\n            elements: [],\n          },\n        ],\n        metadata: {\n          publisher: 'Publisher Name',\n        },\n      };\n\n      await expect(<StoryOutput {...props} flags={{}} />).toBeValidAMP();\n    });\n\n    it('should produce valid AMP output when using Google fonts', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n        story: {\n          title: 'Example',\n          slug: 'example',\n          status: 'publish',\n          author: { id: 1, name: 'John Doe' },\n          date: '123',\n          modified: '123',\n          excerpt: '123',\n          featuredMedia: {\n            id: 123,\n            url: 'https://example.com/poster.png',\n            width: 640,\n            height: 853,\n          },\n          publisherLogo: {\n            id: 1,\n            url: 'https://example.com/logo.png',\n            height: 0,\n            width: 0,\n          },\n          password: '123',\n          link: 'https://example.com/story',\n          autoAdvance: false,\n          fonts: {},\n        },\n        pages: [\n          {\n            id: '123',\n            backgroundColor: {\n              color: { r: 255, g: 255, b: 255 },\n            },\n            page: {\n              id: '123',\n            },\n            elements: [\n              {\n                type: ElementType.Text,\n                id: '123',\n                x: 50,\n                y: 100,\n                height: 1920,\n                width: 1080,\n                rotationAngle: 0,\n                content: 'Hello World',\n                color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n                padding: {\n                  horizontal: 0,\n                  vertical: 0,\n                },\n                font: {\n                  family: 'Roboto',\n                  service: 'fonts.google.com',\n                },\n              },\n            ],\n          },\n        ],\n        metadata: {\n          publisher: 'Publisher Name',\n        },\n      };\n\n      await expect(<StoryOutput {...props} flags={{}} />).toBeValidAMP();\n    });\n\n    it('should produce valid AMP output when using animations', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n        story: {\n          title: 'Example',\n          slug: 'example',\n          status: 'publish',\n          author: { id: 1, name: 'John Doe' },\n          date: '123',\n          modified: '123',\n          excerpt: '123',\n          featuredMedia: {\n            id: 123,\n            url: 'https://example.com/poster.png',\n            width: 640,\n            height: 853,\n          },\n          publisherLogo: {\n            id: 1,\n            url: 'https://example.com/logo.png',\n            height: 0,\n            width: 0,\n          },\n          password: '123',\n          link: 'https://example.com/story',\n          autoAdvance: false,\n          fonts: {},\n        },\n        pages: [\n          {\n            id: '123',\n            animations: [\n              {\n                id: 'anim1',\n                targets: ['123'],\n                type: AnimationType.Bounce,\n                duration: 1000,\n              },\n            ] as StoryAnimation[],\n            backgroundColor: {\n              color: { r: 255, g: 255, b: 255 },\n            },\n            page: {\n              id: '123',\n            },\n            elements: [\n              {\n                type: ElementType.Text,\n                id: '123',\n                x: 50,\n                y: 100,\n                height: 1920,\n                width: 1080,\n                rotationAngle: 0,\n                content: 'Hello World',\n                color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n                padding: {\n                  horizontal: 0,\n                  vertical: 0,\n                },\n                font: {\n                  family: 'Roboto',\n                  service: 'fonts.google.com',\n                },\n              },\n            ],\n          },\n        ],\n        metadata: {\n          publisher: 'Publisher Name',\n        },\n      };\n\n      await expect(<StoryOutput {...props} flags={{}} />).toBeValidAMP();\n    });\n\n    it('should produce valid AMP output when using background audio', async () => {\n      const props = {\n        id: '123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        story: {\n          title: 'Example',\n          slug: 'example',\n          status: 'publish',\n          author: { id: 1, name: 'John Doe' },\n          date: '123',\n          modified: '123',\n          excerpt: '123',\n          featuredMedia: {\n            id: 123,\n            url: 'https://example.com/poster.png',\n            width: 640,\n            height: 853,\n          },\n          publisherLogo: {\n            id: 1,\n            url: 'https://example.com/logo.png',\n            height: 0,\n            width: 0,\n          },\n          password: '123',\n          link: 'https://example.com/story',\n          autoAdvance: false,\n          backgroundAudio: {\n            resource: {\n              type: ResourceType.Audio,\n              src: 'https://example.com/audio.mp3',\n              id: 123,\n              mimeType: 'audio/mpeg',\n              length: 100,\n              lengthFormatted: '1:40',\n            },\n          },\n          fonts: {},\n        },\n        pages: [\n          {\n            id: '123',\n            animations: [\n              {\n                id: 'anim1',\n                targets: ['123'],\n                type: AnimationType.Bounce,\n                duration: 1000,\n              },\n            ] as StoryAnimation[],\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n            page: {\n              id: '123',\n            },\n            elements: [\n              {\n                type: ElementType.Text,\n                id: '123',\n                x: 50,\n                y: 100,\n                height: 1920,\n                width: 1080,\n                rotationAngle: 0,\n                content: 'Hello World',\n                color: { type: 'solid', color: { r: 255, g: 255, b: 255 } },\n                padding: {\n                  horizontal: 0,\n                  vertical: 0,\n                },\n                font: {\n                  family: 'Roboto',\n                  service: 'fonts.google.com',\n                },\n              },\n            ],\n          },\n        ],\n        metadata: {\n          publisher: 'Publisher Name',\n        },\n      };\n\n      await expect(<StoryOutput {...props} flags={{}} />).toBeValidAMP();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/output/src/test/textElement.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport { AnimationProvider } from '@googleforcreators/animation';\nimport {\n  registerElementType,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport OutputElement from '../element';\nimport { DEFAULT_TEXT } from './_utils/constants';\n\nfunction WrapAnimation({ children }: PropsWithChildren<unknown>) {\n  return <AnimationProvider animations={[]}>{children}</AnimationProvider>;\n}\n\nconst TEXT_WITH_COLOR = {\n  ...DEFAULT_TEXT,\n  content:\n    '<span style=\"color: #0a08ec\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>',\n};\n\nconst TEXT_WITH_BIU = {\n  ...DEFAULT_TEXT,\n  content:\n    '<span style=\"font-weight: 700; font-style: italic; text-decoration: underline\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>',\n};\n\nconst TEXT_WITH_FILL = {\n  ...DEFAULT_TEXT,\n  backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n};\n\nconst TEXT_WITH_HIGHLIGHT = {\n  ...DEFAULT_TEXT,\n  backgroundTextMode: BACKGROUND_TEXT_MODE.HIGHLIGHT,\n};\n\nconst TEXT_WITH_PADDING = {\n  ...DEFAULT_TEXT,\n  padding: {\n    locked: false,\n    horizontal: 12,\n    vertical: 25,\n  },\n};\n\nconst TEXT_WITH_FONTSIZE_FAMILY = {\n  ...DEFAULT_TEXT,\n  font: {\n    ...DEFAULT_TEXT.font,\n    family: 'Bungee Shade',\n  },\n  fontSize: 45,\n};\n\nconst TEXT_WITH_LINEHEIGHT = {\n  ...DEFAULT_TEXT,\n  lineHeight: 4,\n};\n\nconst TEXT_WITH_LETTERSPACING = {\n  ...DEFAULT_TEXT,\n  content:\n    '<span style=\"letter-spacing: 0.5em\">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>',\n};\n\nconst TEXT_WITH_ROTATION = {\n  ...DEFAULT_TEXT,\n  rotationAngle: 45,\n};\n\ndescribe('Text Element output', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should render text with color', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_COLOR} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with fill', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_FILL} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with highlight', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_HIGHLIGHT} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with padding', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_PADDING} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with alignment', () => {\n    const TEXT_ALIGN_LEFT = {\n      ...DEFAULT_TEXT,\n      textAlign: 'left',\n    };\n\n    const textLeft = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_ALIGN_LEFT} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(textLeft).toMatchSnapshot();\n\n    const TEXT_ALIGN_RIGHT = {\n      ...DEFAULT_TEXT,\n      textAlign: 'right',\n    };\n\n    const textRight = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_ALIGN_RIGHT} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(textRight).toMatchSnapshot();\n\n    const TEXT_ALIGN_CENTER = {\n      ...DEFAULT_TEXT,\n      textAlign: 'center',\n    };\n\n    const textCenter = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_ALIGN_CENTER} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(textCenter).toMatchSnapshot();\n\n    const TEXT_ALIGN_JUSTIFY = {\n      ...DEFAULT_TEXT,\n      textAlign: 'justify',\n    };\n\n    const textJustify = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_ALIGN_JUSTIFY} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(textJustify).toMatchSnapshot();\n  });\n\n  it('should render text with bold, italic, and underline', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_BIU} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with adjusted font-size and family', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_FONTSIZE_FAMILY} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with line-height', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_LINEHEIGHT} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with letter-spacing', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_LETTERSPACING} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text with applied rotation', () => {\n    const element = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={TEXT_WITH_ROTATION} flags={{}} />\n      </WrapAnimation>\n    );\n    expect(element).toMatchSnapshot();\n  });\n\n  it('should render text without the mask class', () => {\n    const html = renderToStaticMarkup(\n      <WrapAnimation>\n        <OutputElement element={DEFAULT_TEXT} flags={{}} />\n      </WrapAnimation>\n    );\n    const div = document.createElement('div');\n    div.innerHTML = html;\n    const element = div.firstElementChild;\n    expect(element).not.toHaveStyle({ overflow: 'hidden' });\n    expect(element).not.toHaveClass('mask');\n  });\n\n  describe('AMP validation', () => {\n    jest.retryTimes(3, { logErrorsBeforeRetry: true });\n\n    it('should produce valid AMP output when setting text color', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_COLOR} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text fill', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_FILL} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text highlight', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_HIGHLIGHT} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text padding', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_PADDING} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text alignment', async () => {\n      const TEXT_ALIGN_LEFT = {\n        ...DEFAULT_TEXT,\n        textAlign: 'left',\n      };\n\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_ALIGN_LEFT} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n\n      const TEXT_ALIGN_RIGHT = {\n        ...DEFAULT_TEXT,\n        textAlign: 'right',\n      };\n\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_ALIGN_RIGHT} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n\n      const TEXT_ALIGN_CENTER = {\n        ...DEFAULT_TEXT,\n        textAlign: 'center',\n      };\n\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_ALIGN_CENTER} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n\n      const TEXT_ALIGN_JUSTIFY = {\n        ...DEFAULT_TEXT,\n        textAlign: 'justify',\n      };\n\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_ALIGN_JUSTIFY} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text to bold, italic, and underline', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_BIU} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text font-size and family', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_FONTSIZE_FAMILY} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text line-height', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_LINEHEIGHT} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text letter-spacing', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_LETTERSPACING} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n\n    it('should produce valid AMP output when setting text rotation', async () => {\n      await expect(\n        <WrapAnimation>\n          <OutputElement element={TEXT_WITH_ROTATION} flags={{}} />\n        </WrapAnimation>\n      ).toBeValidAMPStoryElement();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/output/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page, Story as FullStory } from '@googleforcreators/elements';\n\nexport type Story = Pick<\n  FullStory,\n  | 'featuredMedia'\n  | 'link'\n  | 'title'\n  | 'fonts'\n  | 'autoAdvance'\n  | 'defaultPageDuration'\n  | 'backgroundAudio'\n  | 'publisherLogo'\n>;\n\nexport interface StoryMetadata {\n  publisher?: string;\n}\n\nexport declare function getStoryMarkup(\n  story: Story,\n  pages: Page[],\n  metadata: StoryMetadata,\n  flags: Record<string, boolean>\n): string;\n\nexport * from './utils/populateElementFontData';\n"
  },
  {
    "path": "packages/output/src/typings/global.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type * as React from 'react';\n\ntype AmpLayout =\n  | 'fill'\n  | 'fixed'\n  | 'fixed-height'\n  | 'flex-item'\n  | 'intrinsic'\n  | 'nodisplay'\n  | 'responsive'\n  | 'container';\n\ninterface AmpHTMLHtmlElement extends React.DetailedHTMLProps<\n  React.HtmlHTMLAttributes<HTMLHtmlElement>,\n  HTMLHtmlElement\n> {\n  amp: string;\n}\n\ninterface AmpVideo extends React.DetailedHTMLProps<\n  Omit<React.VideoHTMLAttributes<HTMLVideoElement>, 'loop'>,\n  HTMLVideoElement\n> {\n  layout: AmpLayout;\n  'captions-id'?: string;\n  autoplay?: 'autoplay';\n  loop?: 'loop';\n}\n\ninterface AmpImg extends React.DetailedHTMLProps<\n  React.ImgHTMLAttributes<HTMLImageElement>,\n  HTMLImageElement\n> {\n  layout: AmpLayout;\n  'disable-inline-width'?: boolean;\n}\n\ninterface AmpStory {\n  standalone: '';\n  title: string;\n  publisher?: string;\n  'publisher-logo-src': string;\n  'poster-portrait-src': string;\n  'background-audio'?: string;\n  children?: React.ReactNode;\n}\n\ninterface AmpStoryGridLayer {\n  template: 'fill' | 'vertical';\n  'aspect-ratio'?: string;\n  class?: string;\n  children?: React.ReactNode;\n}\n\ninterface AmpStoryPage {\n  id?: string;\n  'auto-advance-after'?: string;\n  'background-audio'?: string;\n  children?: React.ReactNode;\n}\n\ninterface AmpStoryShoppingAttachment {\n  theme?: 'light' | 'dark';\n  'cta-text'?: string;\n  children?: React.ReactNode;\n}\n\ninterface AmpStoryPageOutlink {\n  theme?: 'light' | 'dark';\n  layout: AmpLayout;\n  'cta-image'?: string;\n  children?: React.ReactNode;\n}\n\ninterface AmpStoryCaptions {\n  key: string;\n  id: string;\n  layout: AmpLayout;\n}\n\ndeclare module 'react' {\n  interface HtmlHTMLAttributes<T> extends React.HTMLAttributes<T> {\n    amp?: string;\n  }\n}\n\ndeclare global {\n  namespace JSX {\n    interface IntrinsicElements {\n      'amp-story': AmpStory;\n      'amp-story-grid-layer': AmpStoryGridLayer;\n      'amp-story-page': AmpStoryPage;\n      'amp-story-page-outlink': AmpStoryPageOutlink;\n      'amp-story-shopping-attachment': AmpStoryShoppingAttachment;\n      'amp-story-captions': AmpStoryCaptions;\n      'amp-video': AmpVideo;\n      'amp-img': AmpImg;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/output/src/typings/jest.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// eslint-disable-next-line import/no-extraneous-dependencies -- Installed in main package.json.\nimport 'jest-extended';\n// eslint-disable-next-line import/no-extraneous-dependencies -- Installed in main package.json.\nimport '@testing-library/jest-dom';\n\ndeclare global {\n  namespace jest {\n    interface Matchers<R> {\n      toBeValidAMP(): Promise<R>;\n      toBeValidAMPStory(): Promise<R>;\n      toBeValidAMPStoryPage(): Promise<R>;\n      toBeValidAMPStoryElement(): Promise<R>;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/output/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/output/src/utils/ampBoilerplate.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Renders AMP boilerplate\n *\n * @see https://amp.dev/documentation/guides-and-tutorials/learn/spec/amp-boilerplate/\n * @see https://amp.dev/documentation/components/amp-story/#boilerplate\n * @return AMP boilerplate.\n */\nfunction Boilerplate() {\n  return (\n    <>\n      <style\n        amp-boilerplate=\"\"\n        dangerouslySetInnerHTML={{\n          __html:\n            'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',\n        }}\n      />\n      <noscript>\n        <style\n          amp-boilerplate=\"\"\n          dangerouslySetInnerHTML={{\n            __html:\n              'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',\n          }}\n        />\n      </noscript>\n    </>\n  );\n}\n\nexport default Boilerplate;\n"
  },
  {
    "path": "packages/output/src/utils/backgroundAudio.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  BackgroundAudio as BackgroundAudioType,\n  ElementId,\n} from '@googleforcreators/elements';\n\ninterface BackgroundAudioProps {\n  backgroundAudio: BackgroundAudioType;\n  id: ElementId;\n}\n\nfunction BackgroundAudio({ backgroundAudio, id }: BackgroundAudioProps) {\n  const { resource, tracks, loop } = backgroundAudio;\n  const { mimeType, src } = resource;\n\n  const hasTracks = tracks?.length && tracks?.length > 0;\n\n  const sourceProps = {\n    type: mimeType,\n    src,\n  };\n\n  return (\n    <amp-story-grid-layer template=\"fill\">\n      <amp-video\n        autoplay=\"autoplay\"\n        // Not using \"nodisplay\" here, because it might cause the audio to\n        // not actually load at all.\n        // The good thing is that even with a layout, there's nothing visible\n        // on the screen because it's an audio file and not a video.\n        layout=\"fixed\"\n        width=\"1\"\n        height=\"1\"\n        poster=\"\"\n        id={`page-${id}-background-audio`}\n        loop={loop ? 'loop' : undefined}\n        // Actual <amp-story-captions> output happens in OutputPage.\n        captions-id={hasTracks ? `el-${id}-captions` : undefined}\n        // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track#attr-src\n        // and https://github.com/GoogleForCreators/web-stories-wp/issues/11479\n        crossOrigin={hasTracks ? 'anonymous' : undefined}\n      >\n        <source {...sourceProps} />\n        {tracks &&\n          tracks.map(({ srclang, label, kind, track, id: key }, i) => (\n            <track\n              srcLang={srclang}\n              label={label}\n              kind={kind}\n              src={track || undefined}\n              key={key}\n              default={i === 0}\n            />\n          ))}\n      </amp-video>\n    </amp-story-grid-layer>\n  );\n}\n\nexport default BackgroundAudio;\n"
  },
  {
    "path": "packages/output/src/utils/fontDeclarations.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getFontCSS, getGoogleFontURL } from '@googleforcreators/fonts';\nimport { getFontVariants } from '@googleforcreators/rich-text';\nimport type {\n  CustomFontData,\n  FontFamily,\n  FontVariant,\n  GoogleFontData,\n  Page,\n} from '@googleforcreators/elements';\nimport { elementIs, FontService } from '@googleforcreators/elements';\n\nconst hasTuple = (tuples: FontVariant[], tuple: FontVariant) =>\n  tuples.some((val) => val[0] === tuple[0] && val[1] === tuple[1]);\n\nconst tupleDiff = (a: FontVariant, b: FontVariant) => {\n  return Math.abs(a[0] + a[1] - b[0] - b[1]);\n};\n\nconst getNearestTuple = (tuples: FontVariant[], tuple: FontVariant) => {\n  return tuples.reduce((acc, curr) => {\n    const currDiff = tupleDiff(curr, tuple);\n    const accDiff = tupleDiff(acc, tuple);\n\n    return currDiff < accDiff ? curr : acc;\n  });\n};\n\nfunction FontDeclarations({ pages }: { pages: Page[] }) {\n  const map = new Map<\n    FontService,\n    Map<FontFamily, CustomFontData | GoogleFontData>\n  >();\n\n  for (const { elements } of pages) {\n    const textElements = elements.filter(elementIs.text);\n    // Prepare font objects for later use.\n    for (const { font, content } of textElements) {\n      const { service, family, variants = [] } = font;\n      if (!service || service === FontService.System) {\n        continue;\n      }\n\n      const serviceMap =\n        map.get(service) || new Map<string, GoogleFontData | CustomFontData>();\n      map.set(service, serviceMap);\n\n      const fontObj =\n        serviceMap.get(family) ||\n        ({\n          family,\n          variants: [],\n          url: 'url' in font ? font.url : null,\n          service: FontService.Custom,\n        } as CustomFontData);\n\n      const contentVariants = getFontVariants(content);\n\n      if (variants.length > 0) {\n        // A variant (\"axis tuple\" in Google Fonts terms) is a combination\n        // of font style and weight for a given font.\n        // The first item is a flag for italic.\n        // The second item is the numeric font weight.\n        // Example: [1, 700] for italic + bold\n        for (const variant of contentVariants) {\n          // Use the closest variant as fallback and let browser do the math if needed.\n          // Examples:\n          // - If only [ [ 0, 200 ], [ 0, 400 ] ] exist, and\n          //   [ 1, 200] was requested, fall back to [ 0, 200 ].\n          // - If only [ [ 0, 400 ], [ 0, 800 ] ] exist, and\n          //   [ 1, 800] was requested, fall back to [ 0, 800 ].\n          // - If only [ [ 1, 400 ] ] exist, and\n          //   [ 0, 400] was requested, fall back to [ 1, 400 ].\n\n          fontObj.variants ??= [];\n\n          const newVariant = getNearestTuple(variants, variant);\n          const fontObjHasVariant = hasTuple(fontObj.variants, newVariant);\n          const isValidVariant = hasTuple(variants, newVariant);\n\n          // Keeps list unique.\n          if (!fontObjHasVariant && isValidVariant) {\n            fontObj.variants.push(newVariant);\n          }\n        }\n      }\n\n      serviceMap.set(family, fontObj);\n    }\n  }\n\n  return (\n    <>\n      {Array.from(map.keys()).map((service) => {\n        const serviceMap = map.get(service);\n        if (!serviceMap) {\n          return null;\n        }\n        switch (service) {\n          case FontService.GoogleFonts:\n            return (\n              <link\n                key={service}\n                href={getGoogleFontURL(\n                  Array.from(\n                    (serviceMap as Map<FontFamily, GoogleFontData>).values()\n                  )\n                )}\n                rel=\"stylesheet\"\n              />\n            );\n          case FontService.Custom:\n            return Array.from(\n              (serviceMap as Map<FontFamily, CustomFontData>).values()\n            ).map(({ family, url }) => {\n              const inlineStyle = getFontCSS(family, url);\n\n              if (!inlineStyle) {\n                return null;\n              }\n\n              return (\n                <style\n                  key={family}\n                  dangerouslySetInnerHTML={{\n                    __html: inlineStyle,\n                  }}\n                />\n              );\n            });\n          default:\n            return null;\n        }\n      })}\n    </>\n  );\n}\n\nexport default FontDeclarations;\n"
  },
  {
    "path": "packages/output/src/utils/getAutoAdvanceAfter.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  getTotalDuration,\n  type StoryAnimation,\n} from '@googleforcreators/animation';\nimport type {\n  BackgroundAudio,\n  Element,\n  ElementId,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_PAGE_DURATION } from '../constants';\nimport getLongestMediaElement from './getLongestMediaElement';\n\ninterface AutoAdvanceProps {\n  animations?: StoryAnimation[];\n  defaultPageDuration?: number;\n  elements: Element[];\n  backgroundAudio?: BackgroundAudio;\n  id: ElementId;\n}\n\nfunction getAutoAdvanceAfter({\n  animations,\n  defaultPageDuration = DEFAULT_PAGE_DURATION,\n  elements,\n  backgroundAudio,\n  id,\n}: AutoAdvanceProps) {\n  const { resource, loop } = backgroundAudio || {};\n\n  const visibleAnimations = animations?.filter((animation) =>\n    animation.targets.some(\n      (target) => !elements.find((element) => element.id === target)?.isHidden\n    )\n  );\n  const animationDuration = getTotalDuration(visibleAnimations) / 1000;\n  const backgroundAudioDuration =\n    !loop && resource?.length ? resource.length : 0;\n\n  // If we have media, take the media time for advancement time and ignore the default,\n  // but still consider animation time as the minimum, too.\n  const longestMediaElement = getLongestMediaElement(\n    elements,\n    Math.max(animationDuration || 1, backgroundAudioDuration)\n  );\n  if (longestMediaElement?.id) {\n    return `el-${longestMediaElement?.id}-media`;\n  }\n\n  // If the page doesn't have media, take either the animations time or the configured default duration time.\n  const nonMediaPageDuration = Math.max(\n    animationDuration || 0,\n    backgroundAudioDuration,\n    defaultPageDuration\n  );\n  return nonMediaPageDuration > backgroundAudioDuration\n    ? `${nonMediaPageDuration}s`\n    : `page-${id}-background-audio`;\n}\n\nexport default getAutoAdvanceAfter;\n"
  },
  {
    "path": "packages/output/src/utils/getLongestMediaElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  elementIs,\n  type SequenceMediaElement,\n  type VideoElement,\n  type Element,\n} from '@googleforcreators/elements';\n\n/**\n * Among all elements, returns the media element with the longest duration.\n *\n * @param elements List of elements.\n * @param minDuration Duration that the minimum element must exceed in seconds.\n * @return Found element, or undefined if there are no media elements.\n */\nfunction getLongestMediaElement(\n  elements: Element[],\n  minDuration = 0\n): SequenceMediaElement | undefined {\n  return elements\n    .filter(elementIs.video)\n    .filter(({ loop, isHidden }) => {\n      // Ensure looping media is not considered.\n      return !loop && !isHidden;\n    })\n    .reduce((longest: VideoElement | undefined, element) => {\n      if (!element?.resource.length) {\n        return longest;\n      }\n\n      if (element?.resource?.length < minDuration) {\n        return longest;\n      }\n\n      if (!longest) {\n        return element;\n      }\n\n      return longest?.resource?.length > element?.resource?.length\n        ? longest\n        : element;\n    }, undefined);\n}\n\nexport default getLongestMediaElement;\n"
  },
  {
    "path": "packages/output/src/utils/getPreloadResources.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { elementIs, ElementType, type Page } from '@googleforcreators/elements';\n\ninterface PreloadResource {\n  url: string;\n  type: string;\n}\n\n/**\n * Goes through all pages in a story to find the resources that should be preloaded.\n *\n * Currently, this includes the first page's background image/video.\n *\n * @param pages List of pages.\n * @return List of preload resources.\n */\nfunction getPreloadResources(pages: Page[]) {\n  const preloadResources: PreloadResource[] = [];\n\n  if (pages.length === 0) {\n    return preloadResources;\n  }\n\n  const mediaElements = pages[0].elements\n    .filter(elementIs.media)\n    .filter(elementIs.backgroundable);\n\n  for (const element of mediaElements) {\n    const { type, isBackground } = element;\n    if (!isBackground) {\n      continue;\n    }\n\n    // resource?.output?.src is used only for GIF resources.\n    const src = elementIs.gif(element)\n      ? element.resource?.output?.src\n      : element.resource.src;\n\n    preloadResources.push({\n      url: src,\n      type: type === ElementType.Image ? 'image' : 'video',\n    });\n  }\n\n  return preloadResources;\n}\n\nexport default getPreloadResources;\n"
  },
  {
    "path": "packages/output/src/utils/getStoryMarkup.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\nimport { renderToStaticMarkup } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport OutputStory from '../story';\nimport type { Story, StoryMetadata } from '../types';\n\n/**\n * Creates AMP HTML markup for saving to DB for rendering in the FE.\n *\n * @param story Story object.\n * @param pages List of pages.\n * @param metadata Metadata.\n * @param flags Feature flags.\n * @return Story markup.\n */\nexport default function getStoryMarkup(\n  story: Story,\n  pages: Page[],\n  metadata: StoryMetadata,\n  flags = {}\n) {\n  // Note that react-dom/server will warn about useLayoutEffect usage here.\n  // Not because of any wrongdoing in our code, but mostly because\n  // of its own profiler.\n  // See https://github.com/facebook/react/issues/14927\n  return renderToStaticMarkup(\n    <OutputStory\n      story={story}\n      pages={pages}\n      metadata={metadata}\n      flags={flags}\n    />\n  );\n}\n"
  },
  {
    "path": "packages/output/src/utils/getTextElementTagNames.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { elementIs, type Element } from '@googleforcreators/elements';\n\nconst MINIMUM_CONTENT_LENGTH = 3;\n\n/**\n * Returns a map of tag names for text elements.\n *\n * Uses a very simple algorithm to set tag name (h1, h2, h3, p)\n * based on font size.\n *\n * @param elements List of text elements\n * @return Map of element IDs to tag name.\n */\nfunction getTextElementTagNames(elements: Element[]) {\n  return elements\n    .filter(elementIs.text)\n    .sort((a, b) => a.y - b.y)\n    .reduce(\n      /**\n       * Reducer.\n       *\n       * @param tagNamesMap Tag names map.\n       * @param element Text element.\n       * @param element.id Element ID\n       * @param element.fontSize Font size.\n       * @param element.content Text content.\n       * @param element.tagName Existing tagName\n       * @return Tag names map.\n       */\n      (tagNamesMap, { id, fontSize, content, tagName }) => {\n        // if a tag already exists,\n        // utilize the one already part of the element\n        if (tagName && tagName !== 'auto') {\n          tagNamesMap.set(id, tagName);\n          return tagNamesMap;\n        }\n\n        if (content.length <= MINIMUM_CONTENT_LENGTH) {\n          tagNamesMap.set(id, 'p');\n          return tagNamesMap;\n        }\n\n        const hasH1 = Array.from(tagNamesMap.values()).includes('h1');\n\n        if (fontSize >= 36 && !hasH1) {\n          tagNamesMap.set(id, 'h1');\n          return tagNamesMap;\n        }\n\n        if (fontSize >= 27) {\n          tagNamesMap.set(id, 'h2');\n        } else if (fontSize >= 21) {\n          tagNamesMap.set(id, 'h3');\n        } else {\n          tagNamesMap.set(id, 'p');\n        }\n\n        return tagNamesMap;\n      },\n      new Map<string, 'h1' | 'h2' | 'h3' | 'p'>()\n    );\n}\n\nexport default getTextElementTagNames;\n"
  },
  {
    "path": "packages/output/src/utils/getUsedAmpExtensions.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ElementType,\n  type Page,\n  type VideoElement,\n} from '@googleforcreators/elements';\n\ntype ExtensionName = `amp-${Lowercase<string>}`;\n\ninterface AmpExtension {\n  src: string;\n  name?: ExtensionName;\n}\n\n/**\n * Goes through all pages in a story to find the needed AMP extensions for them.\n *\n * Always includes the runtime as well as the amp-story extension.\n *\n * @param pages List of pages.\n * @return List of used AMP extensions.\n */\nconst getUsedAmpExtensions = (pages: Page[]) => {\n  const extensions: AmpExtension[] = [\n    // runtime.\n    { src: 'https://cdn.ampproject.org/v0.js' },\n    {\n      name: 'amp-story',\n      src: 'https://cdn.ampproject.org/v0/amp-story-1.0.js',\n    },\n  ];\n\n  const ampVideo: AmpExtension = {\n    name: 'amp-video',\n    src: 'https://cdn.ampproject.org/v0/amp-video-0.1.js',\n  };\n\n  const ampStoryCaptions: AmpExtension = {\n    name: 'amp-story-captions',\n    src: 'https://cdn.ampproject.org/v0/amp-story-captions-0.1.js',\n  };\n\n  const ampStoryShopping: AmpExtension = {\n    name: 'amp-story-shopping',\n    src: 'https://cdn.ampproject.org/v0/amp-story-shopping-0.1.js',\n  };\n\n  const ampStoryAudioSticker: AmpExtension = {\n    name: 'amp-story-audio-sticker',\n    src: 'https://cdn.ampproject.org/v0/amp-story-audio-sticker-0.1.js',\n  };\n\n  for (const { elements, backgroundAudio } of pages) {\n    if (backgroundAudio?.resource?.src && backgroundAudio?.tracks?.length) {\n      extensions.push(ampVideo);\n      extensions.push(ampStoryCaptions);\n    }\n    for (const element of elements) {\n      const { type } = element;\n      switch (type) {\n        case ElementType.Video:\n          extensions.push(ampVideo);\n          if ((element as VideoElement).tracks?.length > 0) {\n            extensions.push(ampStoryCaptions);\n          }\n          break;\n        case ElementType.Gif:\n          extensions.push(ampVideo);\n          break;\n        case ElementType.Product:\n          extensions.push(ampStoryShopping);\n          break;\n        case ElementType.AudioSticker:\n          extensions.push(ampStoryAudioSticker);\n          break;\n        default:\n          break;\n      }\n    }\n  }\n\n  return [...new Set(extensions)];\n};\n\nexport default getUsedAmpExtensions;\n"
  },
  {
    "path": "packages/output/src/utils/outlink.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport type { PageAttachment } from '@googleforcreators/elements';\n\nfunction Outlink({ ctaText, url, icon, theme, rel = [] }: PageAttachment) {\n  return (\n    <amp-story-page-outlink\n      layout=\"nodisplay\"\n      cta-image={icon || undefined}\n      theme={theme}\n    >\n      <a href={url} rel={rel.join(' ')}>\n        {ctaText || __('Learn more', 'web-stories')}\n      </a>\n    </amp-story-page-outlink>\n  );\n}\n\nexport default Outlink;\n"
  },
  {
    "path": "packages/output/src/utils/populateElementFontData.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { FontData, Page } from '@googleforcreators/elements';\nimport { elementIs, ElementType } from '@googleforcreators/elements';\n\ntype Fonts = Record<string, FontData>;\n\nfunction populateElementFontProperties(\n  { elements, ...rest }: Page,\n  fonts: Fonts\n) {\n  if (!fonts) {\n    return { elements, ...rest };\n  }\n\n  return {\n    elements: elements.map((element) => {\n      if (\n        elementIs.text(element) &&\n        element.type === ElementType.Text &&\n        Boolean(element.font?.family)\n      ) {\n        return { ...element, font: fonts[element.font?.family] };\n      }\n      return element;\n    }),\n    ...rest,\n  };\n}\n\nexport function populateElementFontData(data: Page[], fonts: Fonts): Page[] {\n  return data.map((page) => populateElementFontProperties(page, fonts));\n}\n"
  },
  {
    "path": "packages/output/src/utils/shoppingAttachment.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  ShoppingAttachment as ShoppingAttachmentType,\n  ProductData,\n} from '@googleforcreators/elements';\n\ntype ShoppingAttachmentProps = Partial<ShoppingAttachmentType> & {\n  products: ProductData[];\n};\n\nfunction ShoppingAttachment({\n  products,\n  theme,\n  ctaText,\n}: ShoppingAttachmentProps) {\n  return (\n    <amp-story-shopping-attachment\n      theme={theme}\n      cta-text={ctaText || undefined}\n    >\n      <script\n        type=\"application/json\"\n        dangerouslySetInnerHTML={{\n          __html: JSON.stringify({\n            items: products,\n          }),\n        }}\n      />\n    </amp-story-shopping-attachment>\n  );\n}\n\nexport default ShoppingAttachment;\n"
  },
  {
    "path": "packages/output/src/utils/styles.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FULLBLEED_RATIO, PAGE_RATIO } from '@googleforcreators/units';\nimport { theme } from '@googleforcreators/design-system';\nimport { isHexColorString } from '@googleforcreators/patterns';\n\nfunction CustomStyles() {\n  const safeToFullRatio = PAGE_RATIO / FULLBLEED_RATIO;\n  const fullToSafeRatio = 1 / safeToFullRatio;\n  const safeRatio = PAGE_RATIO;\n  const fullRatio = FULLBLEED_RATIO;\n\n  // Make the story content aligned with top of viewport between aspect ratios\n  // 320:678 and 9:16. This ensures that the story's system UI (progress bar,\n  // share button) is either completely overlapping or not overlapping the story\n  // content (i.e. never partially overlapping). The icon height is 48px. Based\n  // on research, the smallest screen size in active use is 320 pixels wide. In\n  // this case, the minimum screen width that this ratio will work for it 320px.\n  const gridLayerExpandLowerBound = '320 / 678';\n  const gridLayerExpandUpperBound = '9 / 16';\n\n  // Match page background color to the workspace background color.\n  // Validate since we're using dangerouslySetInnerHTML with imported variable.\n  const workspaceColor = theme.colors.bg.primary;\n  const pageBackgroundColor = isHexColorString(workspaceColor)\n    ? workspaceColor\n    : '#1B1D1C';\n\n  return (\n    <style\n      amp-custom=\"\"\n      dangerouslySetInnerHTML={{\n        __html:\n          `\n              h1, h2, h3 { font-weight: normal; }\n\n              amp-story-page {\n                background-color: ${pageBackgroundColor};\n              }\n\n              amp-story-grid-layer {\n                overflow: visible;\n              }\n\n              @media (max-aspect-ratio: ${gridLayerExpandUpperBound})  {\n                @media (min-aspect-ratio: ${gridLayerExpandLowerBound}) {\n                  amp-story-grid-layer.grid-layer {\n                    margin-top: calc((100% / ${fullRatio} - 100% / ${safeRatio}) / 2);\n                  }\n                }\n              }\n          ` +\n          /*\n            The following rule is for Safari only.\n            In Safari, the font size is rounded up, causing overflow, this hack undoes this.\n            See https://github.com/googleforcreators/web-stories-wp/issues/6323\n           */\n          `\n              @media not all and (min-resolution:.001dpcm) {\n                @media {\n                  p.text-wrapper > span {\n                    font-size: calc(100% - 0.5px);\n                  }\n                }\n              }\n\n              .page-fullbleed-area,\n              .page-background-overlay-area {\n                position: absolute;\n                overflow: hidden;\n                width: 100%;\n                left: 0;\n                height: calc(${safeToFullRatio} * 100%);\n                top: calc((1 - ${safeToFullRatio}) * 100% / 2);\n              }\n\n              .element-overlay-area {\n                position: absolute;\n                width: 100%;\n                height: 100%;\n                top: 0;\n                left: 0;\n              }\n\n              .page-safe-area {\n                overflow: visible;\n                position: absolute;\n                top: 0;\n                bottom: 0;\n                left: 0;\n                right: 0;\n                width: 100%;\n                height: calc(${fullToSafeRatio} * 100%);\n                margin: auto 0;\n              }\n\n              .mask {\n                position: absolute;\n                overflow: hidden;\n              }\n\n              .fill {\n                position: absolute;\n                top: 0;\n                left: 0;\n                right: 0;\n                bottom: 0;\n                margin: 0;\n              }\n\n              @media (prefers-reduced-motion: no-preference) {\n                .animation-wrapper {\n                  opacity: var(--initial-opacity);\n                  transform: var(--initial-transform);\n                }\n              }\n\n              amp-story-grid-layer.align-bottom {\n                align-content: end;\n                padding: 0;\n                /*\n                  AMP CTA Layer will exactly occupy 74px regardless of any device.\n                  To space out captions 74px from the BOTTOM (AMP CTA Layer),\n                  74px from the TOP should also be spaced out and thus: 2 * 74px\n                  will be the desired max-height.\n                */\n                max-height: calc(100vh - (2 * 74px));\n              }\n\n              .captions-area {\n                padding: 0 32px 0;\n              }\n\n              amp-story-captions {\n                margin-bottom: 16px;\n                text-align: center;\n              }\n\n              amp-story-audio-sticker {\n                height: 100%;\n              }\n\n              .audio-sticker {\n                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;\n              }\n              `,\n      }}\n    />\n  );\n}\n\nexport default CustomStyles;\n"
  },
  {
    "path": "packages/output/src/utils/test/fontDeclarations.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page, TextElement } from '@googleforcreators/elements';\nimport { ElementType, FontService } from '@googleforcreators/elements';\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport FontDeclarations from '../fontDeclarations';\n\ndescribe('FontDeclarations', () => {\n  it('should ignore system fonts', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'a',\n            type: ElementType.Text,\n            font: {\n              family: 'Arial',\n              service: FontService.System,\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as TextElement,\n          {\n            id: 'b',\n            type: ElementType.Text,\n            font: {\n              family: 'Helvetica',\n              service: FontService.System,\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as TextElement,\n        ],\n      },\n    ];\n\n    const { container } = render(<FontDeclarations pages={pages} />);\n    expect(container).toMatchInlineSnapshot(`<div />`);\n  });\n\n  it('should return one item for multiple Google fonts', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'def456',\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            type: ElementType.Text,\n            font: {\n              family: 'Roboto',\n              service: FontService.GoogleFonts,\n              variants: [\n                [0, 400],\n                [1, 400],\n              ],\n              fallbacks: ['Arial', 'sans-serif'],\n            },\n            content: '<span style=\"font-style: italic\">Hello</span>',\n            padding: {\n              locked: false,\n              vertical: 0,\n              horizontal: 0,\n            },\n            marginOffset: 0,\n            fontSize: 10,\n            lineHeight: 1,\n            textAlign: 'center',\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          } as TextElement,\n          {\n            id: 'abc123',\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            type: ElementType.Text,\n            font: {\n              family: 'Roboto',\n              service: FontService.GoogleFonts,\n              variants: [\n                [0, 400],\n                [1, 400],\n              ],\n              fallbacks: ['Arial', 'sans-serif'],\n            },\n            content: '<span style=\"font-style: italic\">Hello</span>',\n            padding: {\n              locked: false,\n              vertical: 0,\n              horizontal: 0,\n            },\n            marginOffset: 0,\n            fontSize: 10,\n            lineHeight: 1,\n            textAlign: 'center',\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          } as TextElement,\n          {\n            id: 'xyz789',\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            type: ElementType.Text,\n            font: {\n              family: 'Lato',\n              service: FontService.GoogleFonts,\n            },\n          } as TextElement,\n          {\n            id: 'd',\n            type: ElementType.Text,\n            font: {\n              family: 'Lato',\n              service: 'fonts.google.com',\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as TextElement,\n        ],\n      },\n    ];\n\n    const { container } = render(<FontDeclarations pages={pages} />);\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <link\n          href=\"https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Aital%401&family=Lato\"\n          rel=\"stylesheet\"\n        />\n      </div>\n    `);\n  });\n\n  it('should only include valid variants', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'def456',\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            type: ElementType.Text,\n            font: {\n              family: 'Architects Daughter',\n              service: FontService.GoogleFonts,\n              variants: [[0, 400]],\n              fallbacks: ['sans-serif'],\n            },\n            content: '<span style=\"font-style: italic\">Hello</span>',\n            padding: {\n              locked: false,\n              vertical: 0,\n              horizontal: 0,\n            },\n            marginOffset: 0,\n            fontSize: 10,\n            lineHeight: 1,\n            textAlign: 'center',\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          } as TextElement,\n        ],\n      },\n    ];\n\n    const { container } = render(<FontDeclarations pages={pages} />);\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <link\n          href=\"https://fonts.googleapis.com/css2?display=swap&family=Architects+Daughter\"\n          rel=\"stylesheet\"\n        />\n      </div>\n    `);\n  });\n\n  it('should fall back to closest variant', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'a',\n            type: ElementType.Text,\n            font: {\n              family: 'Mukta Mahee',\n              service: 'fonts.google.com',\n              variants: [\n                [0, 200],\n                [0, 300],\n                [0, 400],\n                [0, 500],\n                [0, 600],\n                [0, 700],\n                [0, 800],\n              ],\n            },\n            content:\n              '<span style=\"font-style: italic;font-weight: 200\">Hello World</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'b',\n            type: ElementType.Text,\n            font: {\n              family: 'Mukta Mahee',\n              service: 'fonts.google.com',\n              variants: [\n                [0, 200],\n                [0, 300],\n                [0, 400],\n                [0, 500],\n                [0, 600],\n                [0, 700],\n                [0, 800],\n              ],\n            },\n            content:\n              '<span style=\"font-style: italic;font-weight: 800\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'c',\n            type: ElementType.Text,\n            font: {\n              family: 'Molle',\n              service: 'fonts.google.com',\n              variants: [[1, 400]],\n            },\n            content: '<span style=\"font-weight: 400\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'd',\n            type: ElementType.Text,\n            font: {\n              family: 'Abel',\n              service: 'fonts.google.com',\n              variants: [[0, 400]],\n            },\n            content: '<span style=\"font-weight: 700\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'e',\n            type: ElementType.Text,\n            font: {\n              family: 'Alef',\n              service: 'fonts.google.com',\n              variants: [\n                [0, 400],\n                [0, 700],\n              ],\n            },\n            content:\n              '<span style=\"font-style: italic;font-weight: 600\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n        ],\n      },\n    ];\n\n    const { container } = render(<FontDeclarations pages={pages} />);\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <link\n          href=\"https://fonts.googleapis.com/css2?display=swap&family=Mukta+Mahee%3Awght%40200%3B800&family=Molle%3Aital%401&family=Abel&family=Alef%3Awght%40700\"\n          rel=\"stylesheet\"\n        />\n      </div>\n    `);\n  });\n\n  it('should add inline stylesheets for custom fonts', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc123',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'a',\n            type: ElementType.Text,\n            font: {\n              family: 'Roboto',\n              service: 'fonts.google.com',\n              variants: [\n                [0, 400],\n                [1, 400],\n              ],\n            },\n            content: '<span style=\"font-style: italic\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'b',\n            type: ElementType.Text,\n            font: {\n              family: 'Roboto',\n              service: 'fonts.google.com',\n              variants: [\n                [0, 400],\n                [1, 400],\n              ],\n            },\n            content: '<span style=\"font-style: italic\">Hello</span>',\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'c',\n            type: ElementType.Text,\n            font: {\n              family: 'Lato',\n              service: 'fonts.google.com',\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'd',\n            type: ElementType.Text,\n            font: {\n              family: 'Lato',\n              service: 'fonts.google.com',\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n          {\n            id: 'e',\n            type: ElementType.Text,\n            font: {\n              family: 'Vazir Regular',\n              service: 'custom',\n              url: 'https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf',\n            },\n            x: 100,\n            y: 100,\n            width: 200,\n            height: 50,\n            rotationAngle: 0,\n          } as unknown as TextElement,\n        ],\n      },\n    ];\n\n    const { container } = render(<FontDeclarations pages={pages} />);\n    expect(container).toMatchInlineSnapshot(`\n      <div>\n        <link\n          href=\"https://fonts.googleapis.com/css2?display=swap&family=Roboto%3Aital%401&family=Lato\"\n          rel=\"stylesheet\"\n        />\n        <style>\n          @font-face {\n          font-family: \"Vazir Regular\";\n          src: url('https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf') format('truetype');\n          font-weight: normal;\n          font-display:swap;\n        }\n        </style>\n      </div>\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getAutoAdvanceAfter.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { StoryAnimation } from '@googleforcreators/animation';\nimport { AnimationType } from '@googleforcreators/animation';\nimport type {\n  BackgroundAudio,\n  Element,\n  VideoElement,\n  ShapeElement,\n} from '@googleforcreators/elements';\nimport { ElementType, registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport getAutoAdvanceAfter from '../getAutoAdvanceAfter';\n\nconst id = '999';\n\ndescribe('getAutoAdvanceAfter', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should return the media element with the longest duration', () => {\n    const elements: Element[] = [\n      {\n        id: '123',\n        type: 'video',\n        resource: { length: 1, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        id: '456',\n        type: 'video',\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        id: '789',\n        type: 'video',\n        resource: { length: 15, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n    ];\n\n    expect(\n      getAutoAdvanceAfter({ id: '999', elements, defaultPageDuration: 7 })\n    ).toBe('el-789-media');\n  });\n\n  it('should return default value', () => {\n    expect(\n      getAutoAdvanceAfter({ id: '999', elements: [], defaultPageDuration: 7 })\n    ).toBe('7s');\n  });\n\n  it('should return background audio length', () => {\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements: [],\n        backgroundAudio: {\n          resource: { length: 15 },\n          loop: false,\n        } as unknown as BackgroundAudio,\n      })\n    ).toBe('page-999-background-audio');\n  });\n\n  it('should return not background audio length as not looping', () => {\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements: [],\n        backgroundAudio: {\n          resource: { length: 15 },\n          loop: true,\n        } as unknown as BackgroundAudio,\n      })\n    ).toBe('7s');\n  });\n\n  it('should not return background audio if there are elements', () => {\n    const elements: Element[] = [\n      {\n        id: 456,\n        type: ElementType.Video,\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n    ];\n    const animations: StoryAnimation[] = [\n      {\n        id: '1',\n        targets: ['456'],\n        type: AnimationType.Bounce,\n        duration: 1000,\n      },\n    ];\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements,\n        animations,\n        backgroundAudio: {\n          resource: { length: 15 },\n          loop: true,\n        } as unknown as BackgroundAudio,\n      })\n    ).toBe('el-456-media');\n  });\n\n  it('should return background audio length with video elements', () => {\n    const elements: Element[] = [\n      {\n        id: '456',\n        x: 0,\n        y: 0,\n        width: 100,\n        height: 100,\n        rotationAngle: 0,\n        type: ElementType.Video,\n        resource: {\n          type: 'video',\n          mimeType: 'video/mp4',\n          id: 123,\n          src: 'https://example.com/video.mp4',\n          poster: 'https://example.com/poster.png',\n          alt: '',\n          width: 100,\n          height: 100,\n          isExternal: false,\n          length: 10,\n          lengthFormatted: '0:10',\n        },\n        volume: 1,\n        tracks: [],\n      } as VideoElement,\n    ];\n    const animations: StoryAnimation[] = [\n      {\n        id: '1',\n        targets: ['456'],\n        type: AnimationType.Bounce,\n        duration: 1000,\n      },\n    ];\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements,\n        animations,\n        backgroundAudio: {\n          resource: { length: 15 },\n          loop: false,\n        } as unknown as BackgroundAudio,\n      })\n    ).toBe('page-999-background-audio');\n  });\n\n  it('should return animation time', () => {\n    const elements: Element[] = [\n      {\n        id: '123',\n        x: 0,\n        y: 0,\n        width: 100,\n        height: 100,\n        rotationAngle: 0,\n        type: ElementType.Video,\n        loop: true,\n        resource: {\n          type: 'video',\n          mimeType: 'video/mp4',\n          id: 123,\n          src: 'https://example.com/video.mp4',\n          poster: 'https://example.com/poster.png',\n          alt: '',\n          width: 100,\n          height: 100,\n          isExternal: false,\n          length: 10,\n          lengthFormatted: '0:10',\n        },\n        volume: 1,\n        tracks: [],\n      } as VideoElement,\n      { id: '456', x: 0, y: 0, type: 'shape' } as ShapeElement,\n    ];\n\n    const animations: StoryAnimation[] = [\n      {\n        id: '1',\n        targets: ['456'],\n        duration: 10000,\n        zoomFrom: 1,\n        zoomTo: 2,\n        type: AnimationType.Zoom,\n      },\n      {\n        id: '2',\n        targets: ['123'],\n        duration: 10000,\n        zoomFrom: 2,\n        zoomTo: 1,\n        type: AnimationType.Zoom,\n      },\n    ];\n\n    const backgroundAudio = {\n      resource: { length: 15 },\n      loop: true,\n    } as unknown as BackgroundAudio;\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements,\n        backgroundAudio,\n        animations,\n      })\n    ).toBe('10s');\n  });\n\n  it('should return animation time non-looping media', () => {\n    const elements: Element[] = [\n      {\n        id: '123',\n        type: 'video',\n        poster: 'https://example.com/poster.png',\n        loop: false,\n        resource: { length: 5 },\n      } as VideoElement,\n      { id: '456', x: 0, y: 0, type: ElementType.Shape } as ShapeElement,\n    ];\n\n    const animations: StoryAnimation[] = [\n      {\n        id: '1',\n        targets: ['456'],\n        duration: 10000,\n        zoomFrom: 1,\n        zoomTo: 2,\n        type: AnimationType.Zoom,\n      },\n      {\n        id: '2',\n        targets: ['123'],\n        duration: 10000,\n        zoomFrom: 2,\n        zoomTo: 1,\n        type: AnimationType.Zoom,\n      },\n    ];\n\n    const backgroundAudio = {\n      resource: { length: 8 },\n      loop: false,\n    } as unknown as BackgroundAudio;\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements,\n        backgroundAudio,\n        animations,\n      })\n    ).toBe('10s');\n  });\n\n  it('should return default page duration', () => {\n    const elements: Element[] = [\n      { id: '456', x: 0, y: 0, type: 'shape' } as ShapeElement,\n    ];\n    expect(\n      getAutoAdvanceAfter({\n        id,\n        elements,\n        animations: [],\n      })\n    ).toBe('7s');\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getLongestMediaElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  type Element,\n  type TextElement,\n  type VideoElement,\n  type ImageElement,\n  ElementType,\n  registerElementType,\n} from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport getLongestMediaElement from '../getLongestMediaElement';\n\ndescribe('getLongestMediaElement', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should return the media element with the longest duration', () => {\n    const elements: Element[] = [\n      {\n        type: ElementType.Video,\n        resource: { length: 1, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 15, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n    ];\n\n    expect(getLongestMediaElement(elements)).toStrictEqual({\n      type: ElementType.Video,\n      resource: { length: 15, poster: 'https://example.com/poster.png' },\n    });\n  });\n\n  it('should ignore looping media', () => {\n    const elements: Element[] = [\n      {\n        type: ElementType.Video,\n        resource: { length: 1, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 15, poster: 'https://example.com/poster.png' },\n        loop: true,\n      } as unknown as VideoElement,\n    ];\n\n    expect(getLongestMediaElement(elements)).toStrictEqual({\n      type: ElementType.Video,\n      resource: { length: 10, poster: 'https://example.com/poster.png' },\n    });\n  });\n\n  it('should ignore images', () => {\n    const elements: Element[] = [{ type: 'image' } as unknown as ImageElement];\n\n    expect(getLongestMediaElement(elements)).toBeUndefined();\n  });\n\n  it('should return undefined if there are no elements', () => {\n    const elements: Element[] = [];\n\n    expect(getLongestMediaElement(elements)).toBeUndefined();\n  });\n\n  it('should return undefined if there are no media elements', () => {\n    const elements: Element[] = [\n      { type: ElementType.Text } as unknown as TextElement,\n      { type: ElementType.Text } as unknown as TextElement,\n      { type: ElementType.Text } as unknown as TextElement,\n    ];\n\n    expect(getLongestMediaElement(elements)).toBeUndefined();\n  });\n\n  it('should return the media element with the longest duration if longer than minDuration', () => {\n    const elements: Element[] = [\n      {\n        type: ElementType.Video,\n        resource: { length: 1, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 15, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n    ];\n\n    expect(getLongestMediaElement(elements, 13)).toStrictEqual({\n      type: ElementType.Video,\n      resource: { length: 15, poster: 'https://example.com/poster.png' },\n    });\n  });\n\n  it('should return undefined if the longest duration is less than the minDuration', () => {\n    const elements: Element[] = [\n      {\n        type: ElementType.Video,\n        resource: { length: 1, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 10, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n      {\n        type: ElementType.Video,\n        resource: { length: 15, poster: 'https://example.com/poster.png' },\n      } as unknown as VideoElement,\n    ];\n\n    expect(getLongestMediaElement(elements, 16)).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getPreloadResources.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  type Page,\n  type BackgroundableElement,\n  type ImageElement,\n  ElementType,\n} from '@googleforcreators/elements';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport getPreloadResources from '../getPreloadResources';\n\nconst IMAGE_ELEMENT: ImageElement = {\n  id: 'baz',\n  type: ElementType.Image,\n  scale: 1,\n  x: 50,\n  y: 100,\n  height: 1920,\n  width: 1080,\n  rotationAngle: 0,\n  resource: {\n    type: ResourceType.Image,\n    mimeType: 'image/png',\n    id: 123,\n    src: 'https://example.com/image.png',\n    height: 1920,\n    width: 1080,\n    alt: '',\n    isExternal: true,\n  },\n};\n\nconst VIDEO_ELEMENT = {\n  id: '123',\n  type: ElementType.Video,\n  mimeType: 'video/mp4',\n  scale: 1,\n  origRatio: 9 / 16,\n  x: 50,\n  y: 100,\n  height: 1920,\n  width: 1080,\n  rotationAngle: 0,\n  loop: true,\n  resource: {\n    type: 'video',\n    mimeType: 'video/mp4',\n    id: 123,\n    src: 'https://example.com/video.mp4',\n    poster: 'https://example.com/poster.png',\n    height: 1920,\n    width: 1080,\n    length: 99,\n  },\n};\n\nconst GIF_ELEMENT = {\n  id: '048426c8-69ae-4e04-80f1-8f3fd4434261',\n  type: ElementType.Gif,\n  opacity: 100,\n  x: 65,\n  y: 196,\n  width: 281,\n  height: 223,\n  scale: 100,\n  rotationAngle: 0,\n  resource: {\n    type: 'gif',\n    mimeType: 'image/gif',\n    creationDate: '2016-02-04T18:16:22Z',\n    src: 'https://c.tenor.com/4F2m7BWP6KYAAAAC/flying-kiss-muah.gif',\n    poster: 'https://example.com/poster.png',\n    width: 281,\n    height: 223,\n    alt: '',\n    attribution: {\n      author: [],\n      registerUsageUrl:\n        'https://media3p.googleapis.com/v1/media:registerUsage?token=AX7RMSdePGQBB3c/QAOBJ20QC%2BZNp2A549gSosisUYOjIC71nkvySPH5yj%2BqDBOVBmmFZ89azzUAN9x2GjkNbq3OXauUMho%3D',\n    },\n    output: {\n      mimeType: 'video/mp4',\n      src: 'https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4',\n    },\n  },\n};\n\ndescribe('getPreloadResources', () => {\n  it('should bail early on empty pages', () => {\n    const result = getPreloadResources([]);\n    expect(result).toStrictEqual([]);\n  });\n\n  it('should ignore non-background elements', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [IMAGE_ELEMENT, GIF_ELEMENT, VIDEO_ELEMENT],\n      },\n    ];\n    const result = getPreloadResources(pages);\n    expect(result).toStrictEqual([]);\n  });\n\n  it(\"should add the first page's background video\", () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          { ...VIDEO_ELEMENT, isBackground: true } as BackgroundableElement,\n        ],\n      } as Page,\n    ];\n    const result = getPreloadResources(pages);\n    expect(result).toStrictEqual([\n      {\n        url: 'https://example.com/video.mp4',\n        type: 'video',\n      },\n    ]);\n  });\n\n  it(\"should add the first page's background image\", () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          { ...IMAGE_ELEMENT, isBackground: true } as BackgroundableElement,\n        ],\n      } as Page,\n    ];\n    const result = getPreloadResources(pages);\n    expect(result).toStrictEqual([\n      {\n        url: 'https://example.com/image.png',\n        type: 'image',\n      },\n    ]);\n  });\n\n  it(\"should add the first page's background GIF\", () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          { ...GIF_ELEMENT, isBackground: true } as BackgroundableElement,\n        ],\n      },\n    ];\n    const result = getPreloadResources(pages);\n    expect(result).toStrictEqual([\n      {\n        url: 'https://c.tenor.com/4F2m7BWP6KYAAAPo/flying-kiss-muah.mp4',\n        type: 'video',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getStoryMarkup.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ElementType,\n  registerElementType,\n  type Page,\n  type TextElement,\n  FontService,\n} from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { AnimationType } from '@googleforcreators/animation';\nimport getStoryMarkup from '../getStoryMarkup';\n\njest.mock('flagged');\n\ndescribe('getStoryMarkup', () => {\n  beforeAll(() => {\n    // @ts-expect-error TODO: Fix types.\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should generate expected story markup', () => {\n    const story = {\n      storyId: 1,\n      title: 'Story!',\n      author: { id: 1, name: 'John Doe' },\n      slug: 'story',\n      link: 'https://example.com',\n      publisherLogo: {\n        id: 1234,\n        height: 96,\n        width: 96,\n        url: 'https://example.com',\n      },\n      defaultPageDuration: 7,\n      status: 'publish',\n      date: '2020-04-10T07:06:26',\n      modified: '',\n      excerpt: '',\n      featuredMedia: {\n        id: 0,\n        url: 'https://example.com/poster.png',\n        width: 640,\n        height: 853,\n      },\n      fonts: {},\n      password: '',\n    };\n    const metadata = {\n      publisher: 'AMP',\n    };\n    const pages: Page[] = [\n      {\n        id: '2',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        animations: [\n          {\n            id: '1',\n            targets: ['2'],\n            type: AnimationType.Bounce,\n            duration: 1000,\n          },\n          { id: '2', targets: ['2'], type: AnimationType.Spin, duration: 1000 },\n        ],\n        elements: [\n          {\n            id: '2',\n            type: ElementType.Text,\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            content: 'Hello World',\n            font: {\n              family: 'Roboto',\n              service: FontService.GoogleFonts,\n              fallbacks: ['Arial', 'sans-serif'],\n            },\n            color: {\n              color: {\n                r: 255,\n                g: 255,\n                b: 255,\n                a: 0.5,\n              },\n            },\n            padding: {\n              locked: false,\n              vertical: 0,\n              horizontal: 0,\n            },\n            marginOffset: 0,\n            fontSize: 10,\n            lineHeight: 1,\n            textAlign: 'center',\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          } as TextElement,\n        ],\n      },\n      {\n        id: '2',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        animations: [\n          {\n            id: '1',\n            targets: ['2'],\n            type: AnimationType.Bounce,\n            duration: 1000,\n          },\n          { id: '2', targets: ['2'], type: AnimationType.Spin, duration: 1000 },\n        ],\n        elements: [\n          {\n            id: '2',\n            type: ElementType.Text,\n            x: 0,\n            y: 0,\n            width: 211,\n            height: 221,\n            rotationAngle: 1,\n            content: 'Hello World',\n            font: {\n              family: 'Roboto',\n              service: FontService.GoogleFonts,\n              fallbacks: ['Arial', 'sans-serif'],\n            },\n            color: {\n              color: {\n                r: 255,\n                g: 255,\n                b: 255,\n                a: 0.5,\n              },\n            },\n            padding: {\n              locked: false,\n              vertical: 0,\n              horizontal: 0,\n            },\n            marginOffset: 0,\n            fontSize: 10,\n            lineHeight: 1,\n            textAlign: 'center',\n            backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n          } as TextElement,\n        ],\n      },\n    ];\n    const markup = getStoryMarkup(story, pages, metadata);\n    expect(markup).toContain('Hello World');\n    expect(markup).toContain('transform:rotate(1deg)');\n    expect(markup).toContain(\n      '</amp-story-grid-layer></amp-story-page></amp-story></body></html>'\n    );\n    expect(markup).toContain(\n      'poster-portrait-src=\"https://example.com/poster.png\"'\n    );\n\n    expect(markup).toContain('<amp-story-animation');\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getTextElementTagNames.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ElementType, FontService } from '@googleforcreators/elements';\nimport type { TextElement } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport getTextElementTagNames from '../getTextElementTagNames';\n\nconst ELEMENT_H1: TextElement = {\n  id: '111',\n  content: 'Title 1',\n  fontSize: 36,\n  type: ElementType.Text,\n  x: 10,\n  y: 10,\n  font: {\n    family: 'Arial',\n    service: FontService.System,\n  },\n} as TextElement;\n\nconst ELEMENT_H2: TextElement = {\n  id: '222',\n  content: 'Title 2',\n  fontSize: 27,\n  type: 'text',\n  x: 10,\n  y: 10,\n  font: {\n    family: 'Arial',\n    service: FontService.System,\n  },\n} as TextElement;\n\nconst ELEMENT_H3: TextElement = {\n  id: '333',\n  content: 'Title 3',\n  fontSize: 21,\n  type: 'text',\n  x: 10,\n  y: 10,\n  font: {\n    family: 'Arial',\n    service: FontService.System,\n  },\n} as TextElement;\n\nconst PARAGRAPH: TextElement = {\n  id: '444',\n  content: 'Paragraph',\n  fontSize: 17,\n  type: 'text',\n  x: 10,\n  y: 10,\n  font: {\n    family: 'Arial',\n    service: FontService.System,\n  },\n} as TextElement;\n\nconst ELEMENT_WITH_TAG_NAME: TextElement = {\n  id: '555',\n  content: 'Title 1',\n  fontSize: 36,\n  type: 'text',\n  tagName: 'h1',\n  x: 10,\n  y: 10,\n  font: {\n    family: 'Arial',\n    service: FontService.System,\n  },\n} as TextElement;\n\ndescribe('getTextElementTagNames', () => {\n  it('should return tag name map for elements', () => {\n    const elements = [ELEMENT_H1, ELEMENT_H2, ELEMENT_H3, PARAGRAPH];\n\n    expect(getTextElementTagNames(elements)).toStrictEqual(\n      new Map([\n        ['111', 'h1'],\n        ['222', 'h2'],\n        ['333', 'h3'],\n        ['444', 'p'],\n      ])\n    );\n  });\n\n  it('should return a tag name map for elements with tags already', () => {\n    const elements = [ELEMENT_WITH_TAG_NAME];\n\n    expect(getTextElementTagNames(elements)).toStrictEqual(\n      new Map([['555', 'h1']])\n    );\n  });\n\n  it('should have only one h1 element', () => {\n    const elements = [\n      ELEMENT_H1,\n      {\n        ...ELEMENT_H1,\n        id: '555',\n      },\n      ELEMENT_H2,\n      ELEMENT_H3,\n      PARAGRAPH,\n    ];\n\n    expect(getTextElementTagNames(elements)).toStrictEqual(\n      new Map([\n        ['111', 'h1'],\n        ['555', 'h2'],\n        ['222', 'h2'],\n        ['333', 'h3'],\n        ['444', 'p'],\n      ])\n    );\n  });\n\n  it('should prefer possible h1 elements higher up on the page', () => {\n    const elements = [\n      ELEMENT_H1,\n      {\n        ...ELEMENT_H1,\n        id: '555',\n        x: 0,\n        y: 0,\n      },\n      ELEMENT_H2,\n      ELEMENT_H3,\n      PARAGRAPH,\n    ];\n\n    expect(getTextElementTagNames(elements)).toStrictEqual(\n      new Map([\n        ['111', 'h2'],\n        ['555', 'h1'],\n        ['222', 'h2'],\n        ['333', 'h3'],\n        ['444', 'p'],\n      ])\n    );\n  });\n\n  it('should ignore elements with short content', () => {\n    const elements = [\n      ELEMENT_H1,\n      {\n        ...ELEMENT_H1,\n        id: '555',\n        content: '#1',\n      },\n      ELEMENT_H2,\n      ELEMENT_H3,\n      PARAGRAPH,\n    ];\n\n    expect(getTextElementTagNames(elements)).toStrictEqual(\n      new Map([\n        ['111', 'h1'],\n        ['555', 'p'],\n        ['222', 'h2'],\n        ['333', 'h3'],\n        ['444', 'p'],\n      ])\n    );\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/getUsedAmpExtensions.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ElementType } from '@googleforcreators/elements';\nimport type {\n  BackgroundAudio,\n  Page,\n  ProductElement,\n  VideoElement,\n} from '@googleforcreators/elements';\nimport type { AudioResource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport getUsedAmpExtensions from '../getUsedAmpExtensions';\n\ndescribe('getUsedAmpExtensions', () => {\n  it('should always include the AMP runtime script', () => {\n    const actual = getUsedAmpExtensions([]);\n\n    expect(actual).toHaveLength(2);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([{ src: 'https://cdn.ampproject.org/v0.js' }])\n    );\n  });\n\n  it('should always include the AMP Stories script', () => {\n    const actual = getUsedAmpExtensions([]);\n\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-story',\n          src: 'https://cdn.ampproject.org/v0/amp-story-1.0.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-video script if there is a video', () => {\n    const pages: Page[] = [\n      {\n        elements: [{ type: ElementType.Video }],\n      } as Page,\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(3);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-video',\n          src: 'https://cdn.ampproject.org/v0/amp-video-0.1.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-video script if there is a gif element', () => {\n    const pages: Page[] = [\n      {\n        elements: [{ type: ElementType.Gif }],\n      } as Page,\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(3);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-video',\n          src: 'https://cdn.ampproject.org/v0/amp-video-0.1.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-video script only once if there are multiple videos', () => {\n    const pages: Page[] = [\n      {\n        elements: [{ type: ElementType.Video }],\n      } as Page,\n      {\n        elements: [{ type: ElementType.Text }],\n      } as Page,\n      {\n        elements: [{ type: ElementType.Video }],\n      } as Page,\n      {\n        elements: [{ type: ElementType.Video }],\n      } as Page,\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(3);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-video',\n          src: 'https://cdn.ampproject.org/v0/amp-video-0.1.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-story-captions script if there is a video with tracks', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'a',\n            x: 0,\n            y: 0,\n            width: 100,\n            height: 100,\n            rotationAngle: 0,\n            type: ElementType.Video,\n            resource: {\n              type: 'video',\n              mimeType: 'video/mp4',\n              id: 123,\n              src: 'https://example.com/video.mp4',\n              alt: '',\n              width: 100,\n              height: 100,\n              isExternal: false,\n            },\n            volume: 1,\n            tracks: [\n              {\n                track: 'https://example.com/track.vtt',\n                trackId: 123,\n                id: 'rersd-fdfd-fdfd-fdfd',\n                srclang: '',\n                label: '',\n                kind: 'captions',\n              },\n            ],\n          } as VideoElement,\n        ],\n      } as Page,\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(4);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-story-captions',\n          src: 'https://cdn.ampproject.org/v0/amp-story-captions-0.1.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-story-captions script if there is a background audio with tracks', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        backgroundAudio: {\n          resource: { src: 'https://example.com/audio.mp3' } as AudioResource,\n          tracks: [\n            {\n              track: 'https://example.com/track.vtt',\n              trackId: 123,\n              id: 'rersd-fdfd-fdfd-fdfd',\n              srclang: '',\n              label: '',\n              kind: 'captions',\n            },\n          ],\n        } as BackgroundAudio,\n        elements: [],\n      },\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(4);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-video',\n          src: 'https://cdn.ampproject.org/v0/amp-video-0.1.js',\n        },\n        {\n          name: 'amp-story-captions',\n          src: 'https://cdn.ampproject.org/v0/amp-story-captions-0.1.js',\n        },\n      ])\n    );\n  });\n\n  it('should include the amp-story-shopping script if there are products', () => {\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'el1',\n            type: ElementType.Product,\n            x: 50,\n            y: 50,\n            width: 32,\n            height: 32,\n            rotationAngle: 0,\n            product: {},\n          } as ProductElement,\n        ],\n      },\n    ];\n\n    const actual = getUsedAmpExtensions(pages);\n\n    expect(actual).toHaveLength(3);\n    expect(actual).toStrictEqual(\n      expect.arrayContaining([\n        {\n          name: 'amp-story-shopping',\n          src: 'https://cdn.ampproject.org/v0/amp-story-shopping-0.1.js',\n        },\n      ])\n    );\n  });\n});\n"
  },
  {
    "path": "packages/output/src/utils/test/populateElementFontData.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ElementType,\n  FontService,\n  type FontData,\n  type Page,\n  type TextElement,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { populateElementFontData } from '../populateElementFontData';\n\ndescribe('populateElementFontData', () => {\n  it('adds font properties to elements', () => {\n    const fonts: Record<string, FontData> = {\n      Oswald: {\n        family: 'Oswald',\n        service: FontService.GoogleFonts,\n        metrics: {\n          upm: 1000,\n          asc: 1193,\n          des: -289,\n          tAsc: 1193,\n          tDes: -289,\n          tLGap: 0,\n          wAsc: 1325,\n          wDes: 377,\n          xH: 578,\n          capH: 810,\n          yMin: -287,\n          yMax: 1297,\n          hAsc: 1193,\n          hDes: -289,\n          lGap: 0,\n        },\n      },\n      Roboto: {\n        family: 'Roboto',\n        service: FontService.GoogleFonts,\n        metrics: {\n          upm: 2048,\n          asc: 1900,\n          des: -500,\n          tAsc: 1536,\n          tDes: -512,\n          tLGap: 102,\n          wAsc: 1946,\n          wDes: 512,\n          xH: 1082,\n          capH: 1456,\n          yMin: -555,\n          yMax: 2163,\n          hAsc: 1900,\n          hDes: -500,\n          lGap: 0,\n        },\n      },\n    };\n\n    const pages: Page[] = [\n      {\n        id: 'abc',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'a',\n            x: 0,\n            y: 0,\n            width: 100,\n            height: 100,\n            rotationAngle: 0,\n            type: ElementType.Text,\n            font: { family: 'Oswald' },\n          } as TextElement,\n          {\n            id: 'b',\n            x: 0,\n            y: 0,\n            width: 100,\n            height: 100,\n            rotationAngle: 0,\n            type: ElementType.Shape,\n          },\n        ],\n      },\n      {\n        id: 'def',\n        backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n        elements: [\n          {\n            id: 'c',\n            x: 0,\n            y: 0,\n            width: 100,\n            height: 100,\n            rotationAngle: 0,\n            type: ElementType.Shape,\n          },\n          {\n            id: 'd',\n            x: 0,\n            y: 0,\n            width: 100,\n            height: 100,\n            rotationAngle: 0,\n            type: ElementType.Text,\n            font: { family: 'Roboto' },\n          } as TextElement,\n        ],\n      },\n    ];\n\n    const newPages = populateElementFontData(pages, fonts);\n    expect(newPages[0].elements[0]).toMatchObject({\n      type: 'text',\n      font: { ...fonts['Oswald'] },\n    });\n    expect(newPages[1].elements[1]).toMatchObject({\n      type: 'text',\n      font: { ...fonts['Roboto'] },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/output/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../design-system\" },\n    { \"path\": \"../elements\" },\n    { \"path\": \"../element-library\" },\n    { \"path\": \"../fonts\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../masks\" },\n    { \"path\": \"../media\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../rich-text\" },\n    { \"path\": \"../test-utils\" },\n    { \"path\": \"../units\" },\n    { \"path\": \"../url\" }\n  ],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/patterns/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/patterns/README.md",
    "content": "# Patterns\n\nLightweight package to work with colors and patterns (background colors, gradients, etc.).\n"
  },
  {
    "path": "packages/patterns/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/patterns\",\n  \"description\": \"Utility package to deal with color \\\"patterns\\\" like solid colors, and gradients.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/patterns/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/patterns\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"polished\": \"^4.3.1\",\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/patterns/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { PatternType, type Linear } from './types';\n\nexport const DEFAULT_GRADIENT: Linear = {\n  type: PatternType.Linear,\n  stops: [\n    {\n      color: {\n        r: 0,\n        g: 0,\n        b: 0,\n      },\n      position: 0,\n    },\n    {\n      color: {\n        r: 1,\n        g: 1,\n        b: 1,\n      },\n      position: 1,\n    },\n  ],\n};\n\nexport const GRADIENT = {\n  LINEAR: 'linear-gradient',\n  RADIAL: 'radial-gradient',\n};\n\nexport const GRADIENT_REGEX = {\n  [GRADIENT.LINEAR]:\n    /linear-gradient\\((?:-?\\d*\\.?\\d+turn,\\s*)?(?:rgba?\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3}),?\\s*(\\d*\\.?\\d+)?\\)|#([0-9a-fA-F]{6}))\\s*0%,\\s*(?:rgba?\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3}),?\\s*(\\d*\\.?\\d+)?\\)|#([0-9a-fA-F]{6}))\\s*100%\\)/,\n  [GRADIENT.RADIAL]:\n    /radial-gradient\\((?:rgba?\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3}),?\\s*(\\d*\\.?\\d+)?\\)|#([0-9a-fA-F]{6}))\\s*0%,\\s*(?:rgba?\\((\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3}),?\\s*(\\d*\\.?\\d+)?\\)|#([0-9a-fA-F]{6}))\\s*100%\\)/,\n};\n"
  },
  {
    "path": "packages/patterns/src/convertToCSS.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { CSSProperties } from 'react';\n\nfunction convertToCSS(style: CSSProperties) {\n  return Object.entries(style).reduce((str, [key, val]) => {\n    const casedKey = key.replace(\n      /[A-Z]/g,\n      (match) => `-${match.toLowerCase()}`\n    );\n    return `${str}${casedKey}:${String(val)};`;\n  }, '');\n}\n\nexport default convertToCSS;\n"
  },
  {
    "path": "packages/patterns/src/createSolid.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Solid } from './types';\n\nfunction createSolid(r: number, g: number, b: number, a = 1): Solid {\n  if (a !== 1) {\n    return { color: { r, g, b, a } };\n  }\n  return { color: { r, g, b } };\n}\n\nexport default createSolid;\n"
  },
  {
    "path": "packages/patterns/src/createSolidFromString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { parseToRgb } from 'polished';\n\n/**\n * Internal dependencies\n */\nimport createSolid from './createSolid';\n\nfunction createSolidFromString(str: string) {\n  const rgb = parseToRgb(str);\n  const { red, green, blue } = rgb;\n  const alpha = 'alpha' in rgb ? rgb.alpha : undefined;\n  return createSolid(red, green, blue, alpha);\n}\n\nexport default createSolidFromString;\n"
  },
  {
    "path": "packages/patterns/src/generatePatternStyles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { rgba } from 'polished';\n\n/**\n * Internal dependencies\n */\nimport { PatternType } from './types';\nimport type { ColorStop, Gradient, Hex, Pattern, Solid } from './types';\n\n/**\n * Truncate a number to a given number of decimals.\n *\n * @param val Number to truncate\n * @param pos Maximum number of allowed decimals\n * @return Number in given precision\n */\nfunction truncate(val: number, pos: number) {\n  return Number(val.toFixed(pos));\n}\n\n/**\n * Get a description for a gradient - that is the first parameter to the\n * gradient function. It might be null (but never for linears).\n *\n * For a linear gradient, always return the rotation as description.\n *\n * For a radial gradient, return either center, size, both or none\n * depending on whether the values are set.\n *\n * @param pattern Gradient pattern description\n * @param pattern.type Gradient type as a string\n * @param pattern.rotation Gradient rotation between 0 and 1\n * @param pattern.center Gradient center if not 50/50\n * @param pattern.size Gradient size if not full size\n * @return Minimal description for gradient.\n */\nfunction getGradientDescription(pattern: Gradient) {\n  switch (pattern.type) {\n    case PatternType.Radial: {\n      const { size, center } = pattern;\n      const sizeString = size\n        ? `ellipse ${truncate(100 * size.w, 2)}% ${truncate(100 * size.h, 2)}%`\n        : '';\n      const centerString = center\n        ? ` at ${truncate(100 * center.x, 2)}% ${truncate(100 * center.y, 2)}%`\n        : '';\n      if (!centerString && !sizeString) {\n        return null;\n      }\n      return `${sizeString}${centerString}`.trim();\n    }\n    case PatternType.Linear: {\n      // Always include rotation and offset by .5turn, as default is .5turn(?)\n      const { rotation } = pattern;\n      return `${((rotation || 0) + 0.5) % 1}turn`;\n    }\n    // Ignore reason: only here because of eslint, will not happen\n    // istanbul ignore next\n    default:\n      return null;\n  }\n}\n\n/**\n * Convert a list of stops to serialized minimal versions. And use percent\n * or turn as unit depending on whether stops are angular or not.\n *\n * @param stops List of stops as an object with color and position\n * @param alpha Alpha opacity to multiple to each stop\n * @return List of serialized stops\n */\nfunction getStopList(stops: Array<ColorStop>, alpha: number) {\n  const getColor = ({ r, g, b, a = 1 }: Hex) => rgba(r, g, b, a * alpha);\n  return stops.map(\n    ({ color, position }) =>\n      `${getColor(color)} ${truncate(position * 100, 2)}%`\n  );\n}\n\n/**\n * Generate CSS object from a Pattern.\n *\n * @param pattern Patterns as describe by the Pattern type\n * @param property Type of CSS to generate. Defaults to 'background',\n * but can also be 'color', 'fill', 'stroke', or even a CSS variable.\n * @return CSS declaration as object, e.g. {fill: 'transparent'} or\n * {backgroundImage: 'radial-gradient(red, blue)'}.\n */\nfunction generatePatternStyles(\n  pattern: Pattern | null = null,\n  property = 'background'\n): Record<string, string> {\n  if (pattern === null) {\n    return { [property]: 'transparent' };\n  }\n\n  const isBackground = property === 'background';\n  const { type = PatternType.Solid } = pattern;\n  if (!Object.values(PatternType).includes(type)) {\n    throw new Error(`Unknown pattern type: '${type}'`);\n  }\n\n  // Gradients are only possible for backgrounds\n  if (!isBackground && type !== PatternType.Solid) {\n    throw new Error(\n      `Can only generate solid colors for property '${property}'`\n    );\n  }\n\n  if (type === PatternType.Solid) {\n    const {\n      color: { r, g, b, a = 1 },\n    } = pattern as Solid;\n    const objectPropertyPostfix = isBackground ? 'Color' : '';\n    return { [`${property}${objectPropertyPostfix}`]: rgba(r, g, b, a) };\n  }\n\n  const { stops, alpha = 1 } = pattern as Gradient;\n  const func = `${type}-gradient`;\n  const description = getGradientDescription(pattern as Gradient);\n  const stopList = getStopList(stops, alpha);\n  const parms = description ? [description, ...stopList] : stopList;\n  const value = `${func}(${parms.join(', ')})`;\n  return { backgroundImage: value };\n}\n\nexport default generatePatternStyles;\n"
  },
  {
    "path": "packages/patterns/src/getColorFromGradientStyle.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { DEFAULT_GRADIENT, GRADIENT, GRADIENT_REGEX } from './constants';\nimport createSolidFromString from './createSolidFromString';\nimport { PatternType, type Gradient } from './types';\n\nexport default function getColorFromGradientStyle(style: string): Gradient {\n  if (style.includes(GRADIENT.LINEAR)) {\n    return parseGradient(style, GRADIENT.LINEAR);\n  } else if (style.includes(GRADIENT.RADIAL)) {\n    return parseGradient(style, GRADIENT.RADIAL);\n  }\n  throw new Error('Invalid style string passed.');\n}\n\nfunction parseGradient(style: string, gradient: string): Gradient {\n  const regex = GRADIENT_REGEX[gradient];\n  const matches = style.match(regex);\n  if (!matches) {\n    return DEFAULT_GRADIENT;\n  }\n\n  const { startColor, endColor } = getColorRange(matches);\n\n  if (gradient === GRADIENT.LINEAR) {\n    const rotationMatch = style.match(/0(\\.((25|5|75)))?turn/);\n    return {\n      type: PatternType.Linear,\n      stops: [\n        { color: startColor, position: 0 },\n        { color: endColor, position: 1 },\n      ],\n      rotation: rotationMatch ? Number.parseFloat(rotationMatch[0]) : 0,\n    };\n  }\n\n  return {\n    type: PatternType.Radial,\n    stops: [\n      { color: startColor, position: 0 },\n      { color: endColor, position: 1 },\n    ],\n  };\n}\n\nfunction getColorRange(matches: RegExpMatchArray) {\n  const [\n    ,\n    startColorR,\n    startColorG,\n    startColorB,\n    startAlpha,\n    startHex,\n    endColorR,\n    endColorG,\n    endColorB,\n    endAlpha,\n    endHex,\n  ] = matches;\n\n  const startColor = startHex\n    ? createSolidFromString(`#${startHex}`).color\n    : parseColor(startColorR, startColorG, startColorB, startAlpha);\n\n  const endColor = endHex\n    ? createSolidFromString(`#${endHex}`).color\n    : parseColor(endColorR, endColorG, endColorB, endAlpha);\n\n  return { startColor, endColor };\n}\n\nfunction parseColor(r: string, g: string, b: string, a: string) {\n  return {\n    r: Number.parseInt(r),\n    g: Number.parseInt(g),\n    b: Number.parseInt(b),\n    a: a ? Number.parseFloat(a) : undefined,\n  };\n}\n"
  },
  {
    "path": "packages/patterns/src/getGradientStyleFromColor.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport generatePatternStyles from './generatePatternStyles';\nimport type { Gradient } from './types';\n\nexport default function getGradientStyleFromColor(color: Gradient) {\n  const gradient = generatePatternStyles(color);\n\n  return gradient.backgroundImage;\n}\n"
  },
  {
    "path": "packages/patterns/src/getHexFromSolid.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Solid } from './types';\n\nfunction getHexFromSolid(solid: Solid) {\n  const {\n    color: { r, g, b, a = 1 },\n  } = solid;\n  const dims = [r, g, b, Math.round(a * 100)];\n  return dims\n    .map((n) => n.toString(16))\n    .map((s) => s.padStart(2, '0'))\n    .join('');\n}\n\nexport default getHexFromSolid;\n"
  },
  {
    "path": "packages/patterns/src/getHexFromSolidArray.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction getHexFromSolidArray(dims: Array<number>) {\n  const color = dims\n    .map((n) => n.toString(16))\n    .map((s) => s.padStart(2, '0'))\n    .join('');\n  return `#${color}`;\n}\n\nexport default getHexFromSolidArray;\n"
  },
  {
    "path": "packages/patterns/src/getHexFromValue.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction getHexFromValue(value: string) {\n  const val = (value || '').toUpperCase().trim().replace(/^#/, '');\n\n  const hasNonHex = /[^0-9a-f]/i.test(val);\n  if (hasNonHex) {\n    return null;\n  }\n\n  // Normal Hex\n  if (val.length === 6) {\n    return val;\n  }\n\n  // Shorthand rules.\n  // 2 => 222222\n  if (val.length === 1) {\n    return val.repeat(6);\n  }\n\n  // 21 => 212121\n  if (val.length === 2) {\n    return val.repeat(3);\n  }\n\n  // 221 => 22221\n  if (val.length === 3) {\n    return val.replace(/./g, '$&$&');\n  }\n\n  // 2211 => 222211\n  if (val.length === 4) {\n    return `${val.substring(0, 2).repeat(2)}${val.substring(2)}`;\n  }\n\n  return null;\n}\n\nexport default getHexFromValue;\n"
  },
  {
    "path": "packages/patterns/src/getOpaquePattern.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { PatternType } from './types';\nimport type { Gradient, Pattern } from './types';\n\nfunction getOpaquePattern(pattern: Pattern): Pattern {\n  if (!pattern.type || pattern.type === PatternType.Solid) {\n    const { color } = pattern;\n    return {\n      color: {\n        ...color,\n        a: 1,\n      },\n    };\n  }\n\n  const { alpha, ...opaquePattern } = pattern as Gradient;\n  return opaquePattern;\n}\n\nexport default getOpaquePattern;\n"
  },
  {
    "path": "packages/patterns/src/getPreviewText.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { PatternType } from './types';\nimport type { Pattern } from './types';\n\nfunction printRGB(r: number, g: number, b: number) {\n  const hex = (v: number) => v.toString(16).padStart(2, '0');\n  return `${hex(r)}${hex(g)}${hex(b)}`.toUpperCase();\n}\n\nfunction getPreviewText(pattern: Pattern | null) {\n  if (!pattern) {\n    return null;\n  }\n  switch (pattern.type) {\n    case PatternType.Radial:\n      return __('Radial', 'web-stories');\n    case PatternType.Linear:\n      return __('Linear', 'web-stories');\n    case PatternType.Solid:\n    default: {\n      const {\n        color: { r, g, b },\n      } = pattern;\n      return printRGB(r, g, b);\n    }\n  }\n}\n\nexport default getPreviewText;\n"
  },
  {
    "path": "packages/patterns/src/getSolidFromHex.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createSolid from './createSolid';\nimport createSolidFromString from './createSolidFromString';\nimport type { Pattern } from './types';\n\nfunction getSolidFromHex(hex: string): Pattern {\n  // We already have a nice parser for most of this, but we need to\n  // parse opacity as the last two hex digits as percent, not 1/256th\n\n  const {\n    color: { r, g, b },\n  } = createSolidFromString(`#${hex.slice(0, 6)}`);\n\n  const opacityDigits = hex.slice(6);\n  const opacity = opacityDigits ? Number.parseInt(opacityDigits, 16) : 100;\n\n  return createSolid(r, g, b, opacity / 100);\n}\n\nexport default getSolidFromHex;\n"
  },
  {
    "path": "packages/patterns/src/hasGradient.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { PatternType } from './types';\nimport type { Pattern } from './types';\n\nfunction hasGradient(pattern: Pattern) {\n  return Boolean(pattern?.type) && PatternType.Solid !== pattern.type;\n}\n\nexport default hasGradient;\n"
  },
  {
    "path": "packages/patterns/src/hasOpacity.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Hex, Pattern } from './types';\n\nfunction colorHasTransparency(color: Hex) {\n  return color.a !== undefined && color.a < 1;\n}\n\nfunction hasOpacity(pattern: Pattern) {\n  if ('color' in pattern) {\n    return Boolean(colorHasTransparency(pattern.color));\n  }\n  if (typeof pattern.alpha === 'number' && pattern.alpha < 1) {\n    return true;\n  }\n  for (const colorStop of pattern.stops || []) {\n    if (colorHasTransparency(colorStop.color)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport default hasOpacity;\n"
  },
  {
    "path": "packages/patterns/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './types';\nexport * from './constants';\n\nexport { default as convertToCSS } from './convertToCSS';\nexport { default as createSolid } from './createSolid';\nexport { default as createSolidFromString } from './createSolidFromString';\nexport { default as generatePatternStyles } from './generatePatternStyles';\nexport { default as getHexFromSolid } from './getHexFromSolid';\nexport { default as getHexFromSolidArray } from './getHexFromSolidArray';\nexport { default as getHexFromValue } from './getHexFromValue';\nexport { default as getOpaquePattern } from './getOpaquePattern';\nexport { default as getPreviewText } from './getPreviewText';\nexport { default as getSolidFromHex } from './getSolidFromHex';\nexport { default as hasGradient } from './hasGradient';\nexport { default as hasOpacity } from './hasOpacity';\nexport { default as isPatternEqual } from './isPatternEqual';\nexport { default as isHexColorString } from './isHexColorString';\nexport { default as getGradientStyleFromColor } from './getGradientStyleFromColor';\nexport { default as getColorFromGradientStyle } from './getColorFromGradientStyle';\n"
  },
  {
    "path": "packages/patterns/src/isHexColorString.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction isHexColorString(s: string) {\n  return /^#(?:[a-f0-9]{3}){1,2}$/i.test(s);\n}\n\nexport default isHexColorString;\n"
  },
  {
    "path": "packages/patterns/src/isPatternEqual.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport convertToCSS from './convertToCSS';\nimport generatePatternStyles from './generatePatternStyles';\nimport type { Pattern } from './types';\n\nexport default function isPatternEqual(\n  p1: Pattern,\n  p2: Pattern,\n  patternType?: string\n) {\n  const p1CSS = convertToCSS(generatePatternStyles(p1, patternType));\n  const p2CSS = convertToCSS(generatePatternStyles(p2, patternType));\n  return p1CSS === p2CSS;\n}\n"
  },
  {
    "path": "packages/patterns/src/test/convertToCSS.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport convertToCSS from '../convertToCSS';\n\ndescribe('convertToCSS', () => {\n  it('should convert object correctly', () => {\n    const input: CSSProperties = {\n      fill: 'none',\n      backgroundColor: 'red',\n      borderImage: 'radial-gradient(red, blue)',\n    };\n    expect(convertToCSS(input)).toMatchInlineSnapshot(\n      `\"fill:none;background-color:red;border-image:radial-gradient(red, blue);\"`\n    );\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/createSolid.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createSolid from '../createSolid';\n\ndescribe('createSolid', () => {\n  it('should convert with specifying opacity', () => {\n    expect(createSolid(255, 0, 0)).toStrictEqual({\n      color: { r: 255, g: 0, b: 0 },\n    });\n  });\n\n  it('should convert with full opacity', () => {\n    expect(createSolid(0, 255, 0, 1)).toStrictEqual({\n      color: { r: 0, g: 255, b: 0 },\n    });\n  });\n\n  it('should convert with less than full opacity', () => {\n    expect(createSolid(0, 0, 255, 0.1)).toStrictEqual({\n      color: { r: 0, g: 0, b: 255, a: 0.1 },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/createSolidFromString.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport createSolidFromString from '../createSolidFromString';\n\ndescribe('createSolidFromString', () => {\n  it('should convert via polished', () => {\n    expect(createSolidFromString('red')).toStrictEqual({\n      color: { r: 255, g: 0, b: 0 },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/generatePatternStyles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport generatePatternStyles from '../generatePatternStyles';\nimport type { Linear, Radial } from '../types';\n\ndescribe('generatePatternStyles', () => {\n  describe('given null', () => {\n    it('should return transparent', () => {\n      expect(generatePatternStyles(null)).toStrictEqual({\n        background: 'transparent',\n      });\n    });\n  });\n\n  describe('given an unknown type', () => {\n    it('should throw error', () => {\n      // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- Testing the pattern type runtime check.\n      // @ts-ignore\n      expect(() => generatePatternStyles({ type: 'comic' })).toThrow(\n        /unknown pattern type/i\n      );\n    });\n  });\n\n  describe('given a color', () => {\n    it('should return shortest form if possible', () => {\n      expect(\n        generatePatternStyles({ color: { r: 255, g: 0, b: 0 } })\n      ).toStrictEqual({ backgroundColor: '#f00' });\n    });\n\n    it('should return short form', () => {\n      expect(\n        generatePatternStyles({ color: { r: 254, g: 0, b: 0, a: 1 } })\n      ).toStrictEqual({ backgroundColor: '#fe0000' });\n    });\n\n    it('should return rgba if transparent', () => {\n      expect(\n        generatePatternStyles({ color: { r: 255, g: 0, b: 0, a: 0.7 } })\n      ).toStrictEqual({ backgroundColor: 'rgba(255,0,0,0.7)' });\n    });\n\n    it('should be able to render non-background properties', () => {\n      expect(\n        generatePatternStyles({ color: { r: 255, g: 0, b: 0 } }, 'fill')\n      ).toStrictEqual({ fill: '#f00' });\n    });\n  });\n\n  describe('given any gradient', () => {\n    it('should not be able to render non-background properties', () => {\n      expect(() =>\n        generatePatternStyles(\n          {\n            type: 'linear',\n            stops: [\n              { color: { r: 255, g: 0, b: 0 }, position: 0 },\n              { color: { r: 0, g: 0, b: 255 }, position: 1 },\n            ],\n          } as Linear,\n          'fill'\n        )\n      ).toThrow(/only generate solid/i);\n    });\n  });\n\n  describe('given a linear gradient', () => {\n    it('should be able to render a two-stop gradient at default rotation', () => {\n      expect(\n        generatePatternStyles({\n          type: 'linear',\n          stops: [\n            { color: { r: 255, g: 0, b: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n        } as Linear)\n      ).toStrictEqual({\n        backgroundImage: 'linear-gradient(0.5turn, #f00 0%, #00f 100%)',\n      });\n    });\n\n    it('should be able to render a multi-stop gradient with transparencies at an angle', () => {\n      expect(\n        generatePatternStyles({\n          type: 'linear',\n          stops: [\n            { color: { r: 255, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 255, g: 0, b: 0 }, position: 0.6 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n          rotation: 0.25,\n        } as Linear)\n      ).toStrictEqual({\n        backgroundImage:\n          'linear-gradient(0.75turn, rgba(255,0,0,0) 0%, #f00 60%, #00f 100%)',\n      });\n    });\n\n    it('should be able to multiply a global alpha to stops', () => {\n      expect(\n        generatePatternStyles({\n          type: 'linear',\n          stops: [\n            { color: { r: 255, g: 0, b: 0, a: 0.5 }, position: 0 },\n            { color: { r: 255, g: 0, b: 0 }, position: 0.6 },\n            { color: { r: 0, g: 0, b: 255, a: 0 }, position: 1 },\n          ],\n          alpha: 0.7,\n        } as Linear)\n      ).toStrictEqual({\n        backgroundImage:\n          'linear-gradient(0.5turn, rgba(255,0,0,0.35) 0%, rgba(255,0,0,0.7) 60%, rgba(0,0,255,0) 100%)',\n      });\n    });\n  });\n\n  describe('given a radial gradient', () => {\n    it('should be able to render a two-stop gradient', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage: 'radial-gradient(#f00 0%, #00f 100%)',\n      });\n    });\n\n    it('should be able to render a multi-stop gradient', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 255, g: 0, b: 0 }, position: 0.6 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage:\n          'radial-gradient(rgba(255,0,0,0) 0%, #f00 60%, #00f 100%)',\n      });\n    });\n\n    it('should be able to render different size', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n          size: { w: 0.2, h: 0.45678 },\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage:\n          'radial-gradient(ellipse 20% 45.68%, #f00 0%, #00f 100%)',\n      });\n    });\n\n    it('should be able to render off-center', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n          center: { x: 0.4, y: 0.6 },\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage: 'radial-gradient(at 40% 60%, #f00 0%, #00f 100%)',\n      });\n    });\n\n    it('should be able to different size *and* off-center', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n          size: { w: 0.2, h: 0.45678 },\n          center: { x: 0.4, y: 0.6 },\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage:\n          'radial-gradient(ellipse 20% 45.68% at 40% 60%, #f00 0%, #00f 100%)',\n      });\n    });\n\n    it('should be able to multiply a global alpha to stops', () => {\n      expect(\n        generatePatternStyles({\n          type: 'radial',\n          stops: [\n            { color: { r: 255, g: 0, b: 0, a: 0.5 }, position: 0 },\n            { color: { r: 255, g: 0, b: 0 }, position: 0.6 },\n            { color: { r: 0, g: 0, b: 255, a: 0 }, position: 1 },\n          ],\n          alpha: 0.7,\n        } as Radial)\n      ).toStrictEqual({\n        backgroundImage:\n          'radial-gradient(rgba(255,0,0,0.35) 0%, rgba(255,0,0,0.7) 60%, rgba(0,0,255,0) 100%)',\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/getColorFromGradientStyle.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getColorFromGradientStyle from '../getColorFromGradientStyle';\nimport { PatternType } from '../types';\n\ndescribe('getColorFromGradientStyle', () => {\n  describe('Linear Gradient', () => {\n    describe('with rotation', () => {\n      it('should return Linear gradient with two stops', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(0.25turn, #883030 0%, #1cb59b 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0.25,\n          stops: [\n            {\n              color: {\n                r: 136,\n                g: 48,\n                b: 48,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 28,\n                g: 181,\n                b: 155,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with first stop with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(0.25turn, rgba(60,171,152,0.57) 0%, #c41d1d 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0.25,\n          stops: [\n            {\n              color: {\n                r: 60,\n                g: 171,\n                b: 152,\n                a: 0.57,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 196,\n                g: 29,\n                b: 29,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with second stop with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(0.25turn, #a32929 0%, rgba(14,37,33,0.78) 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0.25,\n          stops: [\n            {\n              color: {\n                r: 163,\n                g: 41,\n                b: 41,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 14,\n                g: 37,\n                b: 33,\n                a: 0.78,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with both stops with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(0.5turn, rgba(60,171,152,0.57) 0%, rgba(196,29,29,0.66) 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0.5,\n          stops: [\n            {\n              color: {\n                r: 60,\n                g: 171,\n                b: 152,\n                a: 0.57,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 196,\n                g: 29,\n                b: 29,\n                a: 0.66,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n    });\n\n    describe('without rotation', () => {\n      it('should return Linear gradient with two stops', () => {\n        expect(\n          getColorFromGradientStyle('linear-gradient(#883030 0%, #1cb59b 100%)')\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0,\n          stops: [\n            {\n              color: {\n                r: 136,\n                g: 48,\n                b: 48,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 28,\n                g: 181,\n                b: 155,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with first stop with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(rgba(60,171,152,0.57) 0%, #c41d1d 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0,\n          stops: [\n            {\n              color: {\n                r: 60,\n                g: 171,\n                b: 152,\n                a: 0.57,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 196,\n                g: 29,\n                b: 29,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with second stop with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(#a32929 0%, rgba(14,37,33,0.78) 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0,\n          stops: [\n            {\n              color: {\n                r: 163,\n                g: 41,\n                b: 41,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 14,\n                g: 37,\n                b: 33,\n                a: 0.78,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n\n      it('should return Linear gradient with both stops with transparency', () => {\n        expect(\n          getColorFromGradientStyle(\n            'linear-gradient(rgba(60,171,152,0.57) 0%, rgba(196,29,29,0.66) 100%)'\n          )\n        ).toStrictEqual({\n          type: PatternType.Linear,\n          rotation: 0,\n          stops: [\n            {\n              color: {\n                r: 60,\n                g: 171,\n                b: 152,\n                a: 0.57,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 196,\n                g: 29,\n                b: 29,\n                a: 0.66,\n              },\n              position: 1,\n            },\n          ],\n        });\n      });\n    });\n  });\n\n  describe('Radial Gradient', () => {\n    it('should return Radial gradient with two stops', () => {\n      expect(\n        getColorFromGradientStyle('radial-gradient(#a971a3 0%, #c1d3aa 100%)')\n      ).toStrictEqual({\n        type: PatternType.Radial,\n        stops: [\n          {\n            color: {\n              r: 169,\n              g: 113,\n              b: 163,\n            },\n            position: 0,\n          },\n          {\n            color: {\n              r: 193,\n              g: 211,\n              b: 170,\n            },\n            position: 1,\n          },\n        ],\n      });\n    });\n\n    it('should return Radial gradient with first stop with transparency', () => {\n      expect(\n        getColorFromGradientStyle(\n          'radial-gradient(rgba(178,75,100,0.56) 0%, #c1d3aa 100%)'\n        )\n      ).toStrictEqual({\n        type: PatternType.Radial,\n        stops: [\n          {\n            color: {\n              r: 178,\n              g: 75,\n              b: 100,\n              a: 0.56,\n            },\n            position: 0,\n          },\n          {\n            color: {\n              r: 193,\n              g: 211,\n              b: 170,\n            },\n            position: 1,\n          },\n        ],\n      });\n    });\n\n    it('should return Radial gradient with second stop with transparency', () => {\n      expect(\n        getColorFromGradientStyle(\n          'radial-gradient(#c1d3aa 0%, rgba(178,75,100,0.56) 100%)'\n        )\n      ).toStrictEqual({\n        type: PatternType.Radial,\n        stops: [\n          {\n            color: {\n              r: 193,\n              g: 211,\n              b: 170,\n            },\n            position: 0,\n          },\n          {\n            color: {\n              r: 178,\n              g: 75,\n              b: 100,\n              a: 0.56,\n            },\n            position: 1,\n          },\n        ],\n      });\n    });\n\n    it('should return Radial gradient with both stops with transparency', () => {\n      expect(\n        getColorFromGradientStyle(\n          'radial-gradient(rgba(60,171,152,0.25) 0%, rgba(196,29,29,0.3) 100%)'\n        )\n      ).toStrictEqual({\n        type: PatternType.Radial,\n        stops: [\n          {\n            color: {\n              r: 60,\n              g: 171,\n              b: 152,\n              a: 0.25,\n            },\n            position: 0,\n          },\n          {\n            color: {\n              r: 196,\n              g: 29,\n              b: 29,\n              a: 0.3,\n            },\n            position: 1,\n          },\n        ],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/getHexFromValue.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getHexFromValue from '../getHexFromValue';\n\ndescribe('getHexFromValue', () => {\n  describe('when value is valid', () => {\n    it('should accept valid 1 character hex values', () => {\n      // Include # at start of string\n      expect(getHexFromValue('#A')).toBe('AAAAAA');\n\n      // Missing # at start of string\n      expect(getHexFromValue('B')).toBe('BBBBBB');\n\n      // Has extra space in string\n      expect(getHexFromValue('  F ')).toBe('FFFFFF');\n    });\n\n    it('should accept valid 2 character hex values', () => {\n      // Include # at start of string\n      expect(getHexFromValue('#EF')).toBe('EFEFEF');\n\n      // Missing # at start of string\n      expect(getHexFromValue('EF')).toBe('EFEFEF');\n\n      // Has extra space in string\n      expect(getHexFromValue('  EF ')).toBe('EFEFEF');\n    });\n\n    it('should accept valid 3 character shorthand hex values', () => {\n      // Include # at start of string\n      expect(getHexFromValue('#F60')).toBe('FF6600');\n\n      // Missing # at start of string\n      expect(getHexFromValue('4AF')).toBe('44AAFF');\n\n      // Has extra space in string\n      expect(getHexFromValue('  AF1  ')).toBe('AAFF11');\n    });\n\n    it('should accept valid 4 character hex values', () => {\n      // Include # at start of string\n      expect(getHexFromValue('#1122')).toBe('111122');\n\n      // Missing # at start of string\n      expect(getHexFromValue('1122')).toBe('111122');\n\n      // Has extra space in string\n      expect(getHexFromValue('  1122 ')).toBe('111122');\n    });\n\n    it('should accept valid 6 character hex values', () => {\n      // Include # at start of string\n      expect(getHexFromValue('#45FFAA')).toBe('45FFAA');\n\n      // Missing # at start of string\n      expect(getHexFromValue('BB88AA')).toBe('BB88AA');\n\n      // Has extra space in string\n      expect(getHexFromValue('  22FFAA ')).toBe('22FFAA');\n    });\n\n    it('should accept uppercase or lowercase strings', () => {\n      expect(getHexFromValue('#11a3cf')).toBe('11A3CF');\n      expect(getHexFromValue('a6f')).toBe('AA66FF');\n    });\n  });\n\n  describe('when value is invalid', () => {\n    it('should return null if invalid 6 character hex', () => {\n      // invalid character(s) in string\n      expect(getHexFromValue('#45ZFAA')).toBeNull();\n      expect(getHexFromValue('asdlfa')).toBeNull();\n      expect(getHexFromValue('11111x')).toBeNull();\n    });\n\n    it('should return null if invalid 3 character shorthand hex', () => {\n      // invalid character(s) in string\n      expect(getHexFromValue('#ZA1')).toBeNull();\n      expect(getHexFromValue('MM8')).toBeNull();\n      expect(getHexFromValue('..$')).toBeNull();\n    });\n\n    it('should return null if value length is too short or too long', () => {\n      expect(getHexFromValue('#')).toBeNull();\n      expect(getHexFromValue('f2a4A')).toBeNull();\n      expect(getHexFromValue('f2a4Af3214')).toBeNull();\n      expect(getHexFromValue('jsdhf78384')).toBeNull();\n      expect(getHexFromValue('')).toBeNull();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/getOpaquePattern.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getOpaquePattern from '../getOpaquePattern';\nimport { PatternType } from '../types';\nimport type { Linear } from '../types';\n\ndescribe('getOpaquePattern', () => {\n  it('should get the opaque color correctly from a solid', () => {\n    expect(getOpaquePattern({ color: { r: 1, g: 1, b: 1 } })).toMatchObject({\n      color: { r: 1, g: 1, b: 1, a: 1 },\n    });\n    expect(\n      getOpaquePattern({ color: { r: 1, g: 1, b: 1, a: 0.4 } })\n    ).toMatchObject({\n      color: { r: 1, g: 1, b: 1, a: 1 },\n    });\n    expect(\n      getOpaquePattern({ color: { r: 1, g: 1, b: 1, a: 0 } })\n    ).toMatchObject({\n      color: { r: 1, g: 1, b: 1, a: 1 },\n    });\n  });\n\n  it('should get the opaque color correctly from a gradient', () => {\n    const input: Linear = {\n      type: PatternType.Linear,\n      stops: [\n        { color: { r: 1, g: 1, b: 1 }, position: 0 },\n        { color: { r: 1, g: 1, b: 1, a: 0.5 }, position: 1 },\n      ],\n      alpha: 0.5,\n    };\n    const expected: Linear = {\n      type: PatternType.Linear,\n      stops: [\n        { color: { r: 1, g: 1, b: 1 }, position: 0 },\n        { color: { r: 1, g: 1, b: 1, a: 0.5 }, position: 1 },\n      ],\n    };\n    expect(getOpaquePattern(input)).toMatchObject(expected);\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/getPreviewText.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getPreviewText from '../getPreviewText';\nimport createSolid from '../createSolid';\nimport { PatternType } from '../types';\nimport type { Linear, Radial, Solid } from '../types';\n\ndescribe('getPreviewText', () => {\n  it('should return null for no pattern', () => {\n    const input = null;\n    const result = getPreviewText(input);\n    const expected = null;\n    expect(result).toBe(expected);\n  });\n\n  it('should return hex ignoring alpha for non-transparent solid', () => {\n    const input = createSolid(255, 0, 0, 0.1);\n    const result = getPreviewText(input);\n    const expected = 'FF0000';\n    expect(result).toBe(expected);\n  });\n\n  it('should return hex ignoring alpha for explicit non-transparent solid', () => {\n    const input: Solid = {\n      ...createSolid(255, 0, 255, 0.3),\n      type: PatternType.Solid,\n    };\n    const result = getPreviewText(input);\n    const expected = 'FF00FF';\n    expect(result).toBe(expected);\n  });\n\n  it('should return correct text for gradient', () => {\n    const linearResult = getPreviewText({ type: 'linear' } as Linear);\n    expect(linearResult).toBe('Linear');\n\n    const radialResult = getPreviewText({ type: 'radial' } as Radial);\n    expect(radialResult).toBe('Radial');\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/getSolidFromHex.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getSolidFromHex from '../getSolidFromHex';\n\ndescribe('getSolidFromHex', () => {\n  it.each([\n    ['aabbcc', { color: { r: 170, g: 187, b: 204 } }],\n    ['aabbcc00', { color: { r: 170, g: 187, b: 204, a: 0 } }],\n    ['aabbcc0f', { color: { r: 170, g: 187, b: 204, a: 0.15 } }],\n    ['aabbcc63', { color: { r: 170, g: 187, b: 204, a: 0.99 } }],\n    ['aabbcc64', { color: { r: 170, g: 187, b: 204 } }],\n  ])('should return valid pattern for %s hex string', (hex, expected) => {\n    expect(getSolidFromHex(hex)).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/test/hasOpacity.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport hasOpacity from '../hasOpacity';\nimport { PatternType } from '../types';\nimport type { Linear } from '../types';\n\ndescribe('hasOpacity', () => {\n  it('should return false for opaque solid', () => {\n    expect(hasOpacity({ color: { r: 1, g: 1, b: 1 } })).toBeFalse();\n  });\n\n  it('should return true for semi-transparent solid', () => {\n    expect(hasOpacity({ color: { r: 1, g: 1, b: 1, a: 0.5 } })).toBeTrue();\n  });\n\n  it('should return true for gradient with semitransparent stops', () => {\n    const pattern: Linear = {\n      type: PatternType.Linear,\n      stops: [\n        { color: { r: 1, g: 1, b: 1 }, position: 0 },\n        { color: { r: 1, g: 1, b: 1, a: 0.5 }, position: 1 },\n      ],\n    };\n    expect(hasOpacity(pattern)).toBeTrue();\n  });\n\n  it('should return true for gradient with opaque stops but overall opacity', () => {\n    const pattern: Linear = {\n      type: PatternType.Linear,\n      stops: [\n        { color: { r: 1, g: 1, b: 1 }, position: 0 },\n        { color: { r: 1, g: 1, b: 1 }, position: 1 },\n      ],\n      alpha: 0.5,\n    };\n    expect(hasOpacity(pattern)).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/patterns/src/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n/* eslint-disable no-restricted-imports -- Still used by other packages. */\nimport PropTypes from 'prop-types';\n/* eslint-enable no-restricted-imports -- Still used by other packages. */\n\nexport enum PatternType {\n  Solid = 'solid',\n  Linear = 'linear',\n  Radial = 'radial',\n}\n\nexport type Hex = {\n  r: number;\n  g: number;\n  b: number;\n  a?: number;\n};\n\nexport type Solid = {\n  type?: PatternType.Solid;\n  color: Hex;\n};\n\nexport type ColorStop = {\n  color: Hex;\n  position: number;\n};\n\ntype AbstractGradient = {\n  type: PatternType.Linear | PatternType.Radial;\n  stops: ColorStop[];\n  alpha?: number;\n};\n\nexport type Linear = AbstractGradient & {\n  type: PatternType.Linear;\n  rotation?: number;\n};\n\nexport type Radial = AbstractGradient & {\n  type: PatternType.Radial;\n  size?: {\n    w: number;\n    h: number;\n  };\n  center?: {\n    x: number;\n    y: number;\n  };\n  rotation?: number;\n};\n\nexport type Gradient = Linear | Radial;\nexport type Pattern = Solid | Gradient;\n\nexport const HexPropType = PropTypes.shape({\n  r: PropTypes.number.isRequired,\n  g: PropTypes.number.isRequired,\n  b: PropTypes.number.isRequired,\n  a: PropTypes.number,\n});\n\nexport const ColorStopPropType = PropTypes.shape({\n  color: HexPropType.isRequired,\n  position: PropTypes.number.isRequired,\n});\n\nexport const PatternPropType = PropTypes.shape({\n  type: PropTypes.oneOf(Object.values(PatternType)),\n  color: HexPropType,\n  stops: PropTypes.arrayOf(ColorStopPropType),\n  rotation: PropTypes.number,\n  alpha: PropTypes.number,\n  center: PropTypes.shape({\n    x: PropTypes.number.isRequired,\n    y: PropTypes.number.isRequired,\n  }),\n  size: PropTypes.shape({\n    w: PropTypes.number.isRequired,\n    h: PropTypes.number.isRequired,\n  }),\n});\n"
  },
  {
    "path": "packages/patterns/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../i18n\" }],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/react/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/react/README.md",
    "content": "# React\n\nGeneric package that re-exports parts of `react` and `react-dom` alongside some other helpful utils and hooks.\n"
  },
  {
    "path": "packages/react/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/react\",\n  \"description\": \"A tiny wrapper package that re-exports React and provides additional utilities and custom hooks.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/react/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/react\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"prop-types\": \"^15.8.1\",\n    \"shallow-equal\": \"^3.1.0\",\n    \"use-context-selector\": \"^1.2.11\",\n    \"use-debounce\": \"^10.0.6\",\n    \"use-reduction\": \"^2.1.2\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@types/react\": \"^17.0.91\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/react/src/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { createContext, useContext } from 'use-context-selector';\n\nexport const identity = <T>(state: T) => state;\n"
  },
  {
    "path": "packages/react/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { useDebouncedCallback } from 'use-debounce';\nexport { default as useReduction } from 'use-reduction';\n\nexport * from './context';\nexport * from './react';\nexport * from './react-dom';\n\nexport { default as useBatchingCallback } from './useBatchingCallback';\nexport { default as useCombinedRefs } from './useCombinedRefs';\nexport { default as useContextSelector } from './useContextSelector';\nexport { default as useFocusOut } from './useFocusOut';\nexport { default as usePrevious } from './usePrevious';\nexport { default as useResizeEffect } from './useResizeEffect';\nexport { default as renderToStaticMarkup } from './renderToStaticMarkup';\nexport { default as useUnmount } from './useUnmount';\nexport { default as useWhyDidYouUpdate } from './useWhyDidYouUpdate';\nexport { default as useInitializedValue } from './useInitializedValue';\nexport { default as shallowEqual } from './shallowEqual';\n"
  },
  {
    "path": "packages/react/src/react-dom.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { createPortal, render, unmountComponentAtNode } from 'react-dom';\n"
  },
  {
    "path": "packages/react/src/react.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  forwardRef,\n  lazy,\n  memo,\n  useLayoutEffect,\n  useReducer,\n  createRef,\n  Fragment,\n  Component,\n  StrictMode,\n  Suspense,\n  cloneElement,\n  createElement,\n  useImperativeHandle,\n  useContext as useContextReact,\n} from 'react';\n"
  },
  {
    "path": "packages/react/src/renderToStaticMarkup.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup as _renderToStaticMarkup } from 'react-dom/server';\nimport type { ReactElement } from 'react';\n\n/* eslint-disable no-console -- Deliberately overriding console.error  */\n\n/**\n * Render a React element to static markup.\n *\n * Silences any `useLayoutEffect` warnings.\n *\n * Similar to `renderToString`, except this doesn't create extra DOM attributes\n * such as `data-reactid`, that React uses internally. This is useful if you want\n * to use React as a simple static page generator, as stripping away the extra\n * attributes can save lots of bytes.\n *\n * @param element React element.\n * @return Markup.\n */\nfunction renderToStaticMarkup(\n  element: ReactElement | ReactElement[] | null | string\n): string {\n  const originalConsoleError = console.error;\n  console.error = (error, ...args) => {\n    if (\n      typeof error === 'string' &&\n      !error.startsWith('Warning: useLayoutEffect does nothing on the server')\n    ) {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- OK to pass through here.\n      originalConsoleError(error, ...args);\n    }\n  };\n\n  const markup = _renderToStaticMarkup(element as ReactElement);\n\n  console.error = originalConsoleError;\n\n  return markup;\n}\n\n/* eslint-enable no-console -- Deliberately overriding console.error */\n\nexport default renderToStaticMarkup;\n"
  },
  {
    "path": "packages/react/src/shallowEqual.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { shallowEqualArrays, shallowEqualObjects } from 'shallow-equal';\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n  if (a === b) {\n    return true;\n  }\n\n  if (Array.isArray(a) && Array.isArray(b)) {\n    return shallowEqualArrays(a, b);\n  }\n\n  if (typeof a === 'object' && typeof b === 'object') {\n    return shallowEqualObjects(a, b);\n  }\n\n  return false;\n}\n\nexport default shallowEqual;\n"
  },
  {
    "path": "packages/react/src/test/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, fireEvent, screen } from '@testing-library/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { createContext } from '../context';\nimport useContextSelector from '../useContextSelector';\nimport { useCallback, useState } from '../react';\n\ndescribe('useContextSelector', () => {\n  let context;\n\n  beforeEach(() => (context = createContext(null)));\n\n  const StateProvider = ({ children }) => {\n    const [state, setState] = useState({ count: 0, ignore: 0 });\n    const value = { ...state, setState };\n    return <context.Provider value={value}>{children}</context.Provider>;\n  };\n\n  StateProvider.propTypes = {\n    children: PropTypes.node,\n  };\n\n  it('counter', () => {\n    let renderCount = 0;\n\n    const Counter = () => {\n      renderCount++;\n\n      const { count, setState } = useContextSelector(context, (state) => ({\n        count: state.count,\n        setState: state.setState,\n      }));\n      const incIgnore = useCallback(\n        () => setState((s) => ({ ...s, ignore: s.ignore + 1 })),\n        [setState]\n      );\n      const incCount = useCallback(\n        () => setState((s) => ({ ...s, count: s.count + 1 })),\n        [setState]\n      );\n\n      return (\n        <div>\n          <span>{count}</span>\n          <button onClick={incIgnore} data-testid=\"ignore++\">\n            {'ignore++'}\n          </button>\n          <button onClick={incCount} data-testid=\"count++\">\n            {'count++'}\n          </button>\n        </div>\n      );\n    };\n\n    render(\n      <StateProvider>\n        <Counter />\n      </StateProvider>\n    );\n    expect(renderCount).toBe(1);\n\n    fireEvent.click(screen.getByTestId('ignore++'));\n    expect(renderCount).toBe(1);\n\n    fireEvent.click(screen.getByTestId('count++'));\n    expect(renderCount).toBe(2);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/test/useCombinedRefs.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport { useRef } from '..';\nimport useCombinedRefs from '../useCombinedRefs';\n\ndescribe('useCombinedRefs', () => {\n  it('composes all refs into one callback ref', () => {\n    const testNode = 'value';\n    const testCallbackRef = jest.fn();\n\n    // handling all the refs in one hook just so everything\n    // can be accessed in one result.current scope\n    const useTestRefs = () => {\n      const ref1 = useRef();\n      const ref2 = useRef();\n      const ref3 = testCallbackRef;\n      const composedCallbackRef = useCombinedRefs(ref1, ref2, ref3);\n      return {\n        ref1,\n        ref2,\n        ref3,\n        composedCallbackRef,\n      };\n    };\n\n    const { result } = renderHook(() => useTestRefs());\n    // simulating how react would call this if there was a new\n    // node for something like <div ref={composedCallbackRef} />\n    result.current.composedCallbackRef(testNode);\n\n    // see that all refs were set or called depending\n    // on if they're callback refs or traditional refs\n    const { ref1, ref2, ref3 } = result.current;\n    expect(ref1.current).toBe(testNode);\n    expect(ref2.current).toBe(testNode);\n    expect(ref3).toHaveBeenCalledWith(testNode);\n  });\n});\n"
  },
  {
    "path": "packages/react/src/typings/global.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare global {\n  var WEB_STORIES_ENV: string;\n}\n\nexport type {};\n"
  },
  {
    "path": "packages/react/src/useBatchingCallback.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { unstable_batchedUpdates as batchedUpdates } from 'react-dom';\nimport { useCallback } from 'react';\nimport type { DependencyList } from 'react';\n\n/**\n * The same as `useCallback` except that it ensures the updates\n * are batched. Use anywhere where the native DOM events are handled\n * or for microtasks.\n * See https://blog.logrocket.com/simplifying-state-management-in-react-apps-with-batched-updates/.\n *\n * @param callback The callback to be batched and memoized.\n * @param [deps] The optional callback dependencies.\n * @return The memoized batching function.\n */\nfunction useBatchingCallback<T, S = void>(\n  callback: (arg: T) => S,\n  deps: DependencyList\n): (arg: T) => S;\nfunction useBatchingCallback<T, U>(\n  callback: (arg1: T, arg2: U) => void,\n  deps: DependencyList\n): (arg1: T, arg2: U) => void;\nfunction useBatchingCallback<T, U, V, S = void>(\n  callback: (arg1: T, arg2: U, arg3: V) => S,\n  deps: DependencyList\n): (arg1: T, arg2: U, arg3: V) => S;\nfunction useBatchingCallback<T extends (...args: unknown[]) => void>(\n  callback: T,\n  deps: DependencyList\n) {\n  return useCallback(\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- Just passing through\n    (...args) => batchedUpdates(() => callback(...args)),\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n    deps\n  );\n}\n\nexport default useBatchingCallback;\n"
  },
  {
    "path": "packages/react/src/useCombinedRefs.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useRef } from 'react';\nimport type { ForwardedRef, MutableRefObject, RefCallback } from 'react';\n\n/**\n * Synchronize multiple refs to a single ref\n *\n * This is used when receiving a forwarded ref, but also needing an internal one.\n *\n * @param refs  List of refs to synchronize\n * @return A callback to be used as `ref` for element.\n */\nfunction useCombinedRefs<T>(\n  ...refs: Array<RefCallback<T> | MutableRefObject<T> | ForwardedRef<T>>\n) {\n  const refsRef = useRef(refs);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  refsRef.current = refs;\n  return useCallback((node: T) => {\n    refsRef.current.forEach((ref) => {\n      if (typeof ref === 'function') {\n        ref(node);\n        return;\n      }\n\n      if (ref) {\n        ref.current = node;\n        return;\n      }\n    });\n  }, []);\n}\n\nexport default useCombinedRefs;\n"
  },
  {
    "path": "packages/react/src/useContextSelector.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextSelector as useContextSelectorOrig } from 'use-context-selector';\nimport { useRef } from 'react';\nimport type { MutableRefObject, Context } from 'react';\n\n/**\n * Internal dependencies\n */\nimport shallowEqual from './shallowEqual';\n\ntype EqualityFn = (a: unknown, b: unknown) => boolean;\n\n/**\n * This hook returns a part of the context value by selector.\n * It will trigger a re-render only if the selected value has changed.\n *\n * By default, a shallow equals of the selected context value is used to\n * determine if a re-render is needed.\n *\n * @param context Context.\n * @param selector Returns a fragment of the context\n * that the consumer is interested in.\n * @param equalityFn Used to compare the\n * selected context value. If the context fragment has not changed, a re-render\n * will not be triggered. This is {shallowEqual} by default.\n * @return The selected context value fragment.\n */\nfunction useContextSelector<T, S>(\n  context: Context<T>,\n  selector: (value: T) => S,\n  equalityFn: EqualityFn = shallowEqual\n) {\n  const ref: MutableRefObject<S | undefined> = useRef();\n\n  const equalityFnCallback = (state: T) => {\n    const selected = selector(state);\n    if (ref.current && equalityFn(ref.current, selected)) {\n      return ref.current;\n    }\n    ref.current = selected;\n    return selected;\n  };\n\n  // Update the selector fn to memoize the selected value by [equalityFn].\n  return useContextSelectorOrig(context, equalityFnCallback);\n}\n\nexport default useContextSelector;\n"
  },
  {
    "path": "packages/react/src/useFocusOut.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useLayoutEffect } from 'react';\nimport type { DependencyList, RefObject } from 'react';\n\nfunction useFocusOut(\n  ref: RefObject<HTMLElement>,\n  callback: (evt: FocusEvent | MouseEvent) => void | undefined,\n  deps: DependencyList\n) {\n  useLayoutEffect(() => {\n    const node = ref?.current;\n    if (!node) {\n      return undefined;\n    }\n\n    const onFocusOut = (evt: FocusEvent) => {\n      // If focus moves somewhere outside the node, callback time!\n      if (evt.relatedTarget && !node.contains(<HTMLElement>evt.relatedTarget)) {\n        callback(evt);\n      }\n    };\n\n    const onDocumentClick = (evt: MouseEvent) => {\n      // If something outside the target node is clicked, callback time!\n      const isInNode = node.contains(<HTMLElement>evt.target);\n      if (!isInNode) {\n        callback(evt);\n      }\n    };\n\n    node.addEventListener('focusout', onFocusOut);\n    // Often elements are removed in pointerdown handlers elsewhere, causing them\n    // to fail the node.contains check regardless of being inside target ref or not.\n    // By checking the click target in the capture phase, we circumvent that completely.\n    const opts = { capture: true };\n    const doc = node.ownerDocument;\n    doc.addEventListener('pointerdown', onDocumentClick, opts);\n\n    return () => {\n      node.removeEventListener('focusout', onFocusOut);\n      doc.removeEventListener('pointerdown', onDocumentClick, opts);\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n  }, deps || []);\n}\n\nexport default useFocusOut;\n"
  },
  {
    "path": "packages/react/src/useInitializedValue.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from 'react';\n\n/**\n * Takes an initialization function and returns a memoized result of\n * that function. This value is not subject to cache purging\n * and will only call your initialization function once.\n *\n * ie\n * ```js\n * function SomeComponent() {\n *   const id = useInitializedValue(() => generateId());\n *   // ...\n * }\n * ```\n *\n * @param initializer Initialization function\n * @return result of initializer\n */\nfunction useInitializedValue(initializer: unknown) {\n  return useState(initializer)[0];\n}\n\nexport default useInitializedValue;\n"
  },
  {
    "path": "packages/react/src/usePrevious.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from 'react';\nimport type { MutableRefObject } from 'react';\n\nexport default function usePrevious<V>(value: V) {\n  const ref: MutableRefObject<V | undefined> = useRef();\n\n  useEffect(() => {\n    ref.current = value;\n  }, [value]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  return ref.current;\n}\n"
  },
  {
    "path": "packages/react/src/useResizeEffect.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from 'react';\nimport type { DependencyList, MutableRefObject } from 'react';\n\ntype ResizeHandler = (dimensions: { width: number; height: number }) => void;\n\n/**\n * @param ref Target node ref.\n * @param handler The resize handler.\n * @param [deps] The effect's dependencies.\n */\nfunction useResizeEffect(\n  ref: MutableRefObject<Element>,\n  handler: ResizeHandler,\n  deps: DependencyList | undefined = undefined\n) {\n  useEffect(\n    () => {\n      if (!ref?.current || !ResizeObserver) {\n        return undefined;\n      }\n\n      const observer = new ResizeObserver((entries) => {\n        // requestAnimationFrame prevents the 'ResizeObserver loop limit exceeded' error\n        // https://stackoverflow.com/a/58701523/13078978\n        window.requestAnimationFrame(() => {\n          if (!ref?.current) {\n            return;\n          }\n\n          const last =\n            entries?.length !== undefined && entries?.length > 0\n              ? entries[entries.length - 1]\n              : null;\n\n          if (last) {\n            const { width, height } = last.contentRect;\n            handler({ width, height });\n          }\n        });\n      });\n\n      observer.observe(ref?.current);\n\n      return () => {\n        observer.disconnect();\n      };\n    },\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n    deps || []\n  );\n}\n\nexport default useResizeEffect;\n"
  },
  {
    "path": "packages/react/src/useUnmount.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from 'react';\n\n/**\n * @param callback The identity-stable callback to be executed on unmount\n */\nfunction useUnmount(callback: () => void | undefined) {\n  useEffect(() => callback, [callback]);\n}\n\nexport default useUnmount;\n"
  },
  {
    "path": "packages/react/src/useWhyDidYouUpdate.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from 'react';\nimport type { MutableRefObject } from 'react';\n\n/**\n * Hook to see which prop changes are causing a component to re-render.\n *\n * Only used for development, and removed for production builds.\n *\n * @see https://github.com/gragland/usehooks\n * @param name Component name.\n * @param props Component props.\n */\nfunction useWhyDidYouUpdate(name: string, props: Record<string, unknown>) {\n  const previousProps: MutableRefObject<Record<string, unknown> | undefined> =\n    useRef();\n\n  useEffect(() => {\n    if (previousProps.current) {\n      const allKeys = Object.keys({ ...previousProps.current, ...props });\n      const changesObj: Record<string, { from: unknown; to: unknown }> = {};\n\n      allKeys.forEach((key) => {\n        if (\n          previousProps.current &&\n          previousProps.current[key] !== props[key]\n        ) {\n          changesObj[key] = {\n            from: previousProps.current[key],\n            to: props[key],\n          };\n        }\n      });\n\n      if (Object.keys(changesObj).length) {\n        // eslint-disable-next-line no-console -- Needed for debugging.\n        console.log('[why-did-you-update]', name, changesObj);\n      }\n    }\n\n    previousProps.current = props;\n  });\n}\n\nconst isDevelopment =\n  typeof WEB_STORIES_ENV !== 'undefined' && WEB_STORIES_ENV === 'development';\n\nexport default isDevelopment ? useWhyDidYouUpdate : () => null;\n"
  },
  {
    "path": "packages/react/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/rich-text/README.md",
    "content": "# Rich-Text\n\n---\n\nA wrapper around `draft-js` and utilities for rich-text editor.\n"
  },
  {
    "path": "packages/rich-text/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/rich-text\",\n  \"description\": \"A wrapper around draft-js and utilities for rich-text editor.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/rich-text/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/rich-text\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"draft-js\": \"^0.11.7\",\n    \"draft-js-export-html\": \"https://github.com/swissspidy/draft-js-export-html\",\n    \"draft-js-import-element\": \"https://github.com/swissspidy/draft-js-import-element\",\n    \"draft-js-import-html\": \"^1.4.1\",\n    \"draftjs-filters\": \"^3.0.1\",\n    \"immutable\": \"^5.1.5\",\n    \"prop-types\": \"^15.7.2\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@types/draft-js\": \"^0.11.9\"\n  }\n}\n"
  },
  {
    "path": "packages/rich-text/src/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { State } from './types';\n\nconst RichTextContext = createContext<State>({\n  state: {\n    editorState: null,\n    hasCurrentEditor: false,\n    selectionInfo: undefined,\n  },\n  actions: {\n    setStateFromContent: () => undefined,\n    updateEditorState: () => undefined,\n    getHandleKeyCommand: () => () => 'not-handled',\n    handlePastedText: () => 'not-handled',\n    clearState: () => undefined,\n    selectionActions: {},\n    getContentFromState: () => null,\n  },\n});\n\nexport default RichTextContext;\n"
  },
  {
    "path": "packages/rich-text/src/customConstants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const NONE = 'NONE';\nexport const ITALIC = 'CUSTOM-ITALIC';\nexport const UNDERLINE = 'CUSTOM-UNDERLINE';\nexport const WEIGHT = 'CUSTOM-WEIGHT';\nexport const COLOR = 'CUSTOM-COLOR';\nexport const LETTERSPACING = 'CUSTOM-LETTERSPACING';\nexport const UPPERCASE = 'CUSTOM-UPPERCASE';\nexport const GRADIENT_COLOR = 'CUSTOM-GRADIENT-COLOR';\n\nexport const MULTIPLE_VALUE = '((MULTIPLE))';\n"
  },
  {
    "path": "packages/rich-text/src/customExport.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { stateToHTML } from 'draft-js-export-html';\nimport type { EditorState } from 'draft-js';\nimport type { RenderConfig } from 'draft-js-export-html';\nimport type { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport formatters from './formatters';\n\nfunction inlineStyleFn(styles: OrderedSet<string>): RenderConfig | null {\n  const inlineCSS = formatters.reduce(\n    (css, { stylesToCSS }) => ({ ...css, ...stylesToCSS(styles) }),\n    {}\n  );\n\n  if (Object.keys(inlineCSS).length === 0) {\n    return null;\n  }\n\n  return {\n    element: 'span',\n    style: inlineCSS,\n  };\n}\n\nfunction exportHTML(editorState: EditorState) {\n  if (!editorState) {\n    return null;\n  }\n\n  const html = stateToHTML(editorState.getCurrentContent(), {\n    inlineStyleFn,\n    defaultBlockTag: null,\n  });\n\n  return html.replace(/<br ?\\/?>/g, '').replace(/&nbsp;$/, '');\n}\n\nexport default exportHTML;\n"
  },
  {
    "path": "packages/rich-text/src/customImport.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { stateFromHTML } from 'draft-js-import-html';\nimport type { InlineCreators } from 'draft-js-import-html';\n\n/**\n * Internal dependencies\n */\nimport getValidHTML from './utils/getValidHTML';\nimport formatters from './formatters';\n\nfunction customInlineFn(element: Element, { Style }: InlineCreators) {\n  const styleStrings = formatters\n    .map(({ elementToStyle }) => elementToStyle(element as HTMLElement))\n    .filter((style) => Boolean(style));\n\n  if (styleStrings.length === 0) {\n    return null;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- The defined type is `string` but it actually accepts arrays of strings, too.\n  // @ts-ignore\n  return Style(styleStrings);\n}\n\nfunction importHTML(html = '') {\n  const htmlWithBreaks = html\n    .split('\\n')\n    .map((s) => `<p>${getValidHTML(s === '' ? '<br />' : s)}</p>`)\n    .join('');\n\n  return stateFromHTML(htmlWithBreaks, { customInlineFn });\n}\n\nexport default importHTML;\n"
  },
  {
    "path": "packages/rich-text/src/customInlineDisplay.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { CSSProperties } from 'react';\nimport type { DraftInlineStyle } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport formatters from './formatters';\nimport { fauxStylesToCSS } from './fauxSelection';\n\nfunction customInlineDisplay(styles: DraftInlineStyle): CSSProperties {\n  const stylesToCSSConverters = [\n    ...formatters.map(({ stylesToCSS }) => stylesToCSS),\n    fauxStylesToCSS,\n  ];\n\n  return stylesToCSSConverters.reduce(\n    (css, stylesToCSS) => ({ ...css, ...stylesToCSS(styles, css) }),\n    {}\n  );\n}\n\nexport default customInlineDisplay;\n"
  },
  {
    "path": "packages/rich-text/src/draftUtils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\n\n/* Ignore reason: This is lifted from elsewhere - a combo of these basically:\n *\n * https://github.com/webdeveloperpr/draft-js-custom-styles/blob/f3e6b533905de8eee6da54f9727b5e5803d53fc4/src/index.js#L8-L52\n * https://github.com/facebook/draft-js/issues/602#issuecomment-584676405\n */\n/* istanbul ignore next */\n\n/**\n * This returns *an array of sets of styles* for all currently selected\n * characters.\n *\n * If you have the following states with html tags representing styles\n * and [] representing selection),you get the following returns:\n *\n * <example>\n * input: Hel[lo w]orld\n * output: [Set(), Set(), Set(), Set()]\n *\n * input: <b>Hel[lo</b> w]orld\n * output: [Set(\"BOLD\"), Set(\"BOLD\"), Set(), Set()]\n *\n * input: <b>Hel[l<b><i>o</i></b></b> <u>w]or</u>ld\n * output: [Set(\"BOLD\"), Set(\"BOLD\", \"ITALIC\"), Set(), Set(\"UNDERLINE\")]\n * </example>\n *\n * @param editorState  The current state of the editor including\n * selection\n * @return list of sets of styles as described\n */\nexport function getAllStyleSetsInSelection(editorState: EditorState) {\n  const styleSets = [];\n  const contentState = editorState.getCurrentContent();\n  const selection = editorState.getSelection();\n  let key = selection.getStartKey();\n  let startOffset = selection.getStartOffset();\n  const endKey = selection.getEndKey();\n  const endOffset = selection.getEndOffset();\n  do {\n    const hasMoreRounds = key !== endKey;\n    const block = contentState.getBlockForKey(key);\n    const offsetEnd = hasMoreRounds ? block.getLength() : endOffset;\n    const characterList = block.getCharacterList();\n    for (\n      let offsetIndex = startOffset;\n      offsetIndex < offsetEnd;\n      offsetIndex++\n    ) {\n      const styleSet = characterList.get(offsetIndex);\n      if (styleSet) {\n        styleSets.push(styleSet.getStyle());\n      }\n    }\n    if (!hasMoreRounds) {\n      break;\n    }\n    key = contentState.getKeyAfter(key);\n    startOffset = 0;\n  } while (key !== endKey);\n\n  return styleSets;\n}\n"
  },
  {
    "path": "packages/rich-text/src/editor.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Editor, getDefaultKeyBinding, KeyBindingUtil } from 'draft-js';\nimport {\n  useEffect,\n  useRef,\n  useImperativeHandle,\n  forwardRef,\n  useUnmount,\n} from '@googleforcreators/react';\nimport type { ForwardedRef, KeyboardEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport useRichText from './useRichText';\nimport customInlineDisplay from './customInlineDisplay';\n\nexport interface RichTextEditorProps {\n  content: string;\n  onChange: (content: string | null) => void;\n}\n\nfunction RichTextEditor(\n  { content, onChange }: RichTextEditorProps,\n  ref: ForwardedRef<Partial<HTMLElement>>\n) {\n  const editorRef = useRef<Editor | null>(null);\n  const {\n    state: { editorState },\n    actions: {\n      setStateFromContent,\n      updateEditorState,\n      getHandleKeyCommand,\n      getContentFromState,\n      handlePastedText,\n      clearState,\n    },\n  } = useRichText();\n\n  // Load state from parent when content changes\n  useEffect(() => {\n    setStateFromContent(content);\n  }, [setStateFromContent, content]);\n\n  // Push updates to parent when state changes\n  useEffect(() => {\n    if (!editorState) {\n      return;\n    }\n    const newContent = getContentFromState(editorState);\n    onChange(newContent);\n  }, [onChange, getContentFromState, editorState]);\n\n  const hasEditorState = editorState !== null;\n\n  // On unmount, clear state in provider\n  useUnmount(clearState);\n\n  // Allow parent to focus editor and access main node\n  useImperativeHandle(\n    ref,\n    () => ({\n      focus: () => editorRef.current?.focus?.(),\n      getNode: () => editorRef.current?.editorContainer,\n    }),\n    []\n  );\n\n  if (!hasEditorState) {\n    return null;\n  }\n\n  const { hasCommandModifier } = KeyBindingUtil;\n\n  function bindKeys(e: KeyboardEvent) {\n    if (e.code === 'KeyA' && hasCommandModifier(e)) {\n      return 'selectall';\n    }\n    return getDefaultKeyBinding(e);\n  }\n\n  // Handle basic key commands such as bold, italic and underscore.\n  const handleKeyCommand = getHandleKeyCommand();\n  return (\n    <Editor\n      ref={editorRef}\n      onChange={updateEditorState}\n      editorState={editorState}\n      handleKeyCommand={handleKeyCommand}\n      handlePastedText={handlePastedText}\n      keyBindingFn={bindKeys}\n      customStyleFn={customInlineDisplay}\n      spellCheck\n      stripPastedStyles\n    />\n  );\n}\n\nconst RichTextEditorWithRef = forwardRef(RichTextEditor);\n\nexport default RichTextEditorWithRef;\n"
  },
  {
    "path": "packages/rich-text/src/fauxSelection.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useState } from '@googleforcreators/react';\nimport { EditorState, Modifier } from 'draft-js';\nimport type { DraftInlineStyle, SelectionState } from 'draft-js';\nimport type { CSSProperties, Dispatch, SetStateAction } from 'react';\n\nconst FAUX_SELECTION = 'CUSTOM-FAUX';\n\nfunction isEqualSelectionIgnoreFocus(\n  a: SelectionState | null,\n  b: SelectionState | null\n) {\n  if (!a || !b) {\n    return false;\n  }\n  const aWithoutFocus = a.serialize().replace(/has focus: .*$/i, '');\n  const bWithoutFocus = b.serialize().replace(/has focus: .*$/i, '');\n  return aWithoutFocus === bWithoutFocus;\n}\n\n/**\n * A hook to properly set and remove faux selection style.\n *\n * If current selection in editor is unfocused, set faux style on current selection\n * else, if current selection in editor is focused, remove faux style from entire editor\n *\n * @param editorState  Current editor state\n * @param setEditorState  Callback to update current editor state\n */\nexport function useFauxSelection(\n  editorState: EditorState | null,\n  setEditorState: Dispatch<SetStateAction<EditorState | null>>\n) {\n  const [fauxSelection, setFauxSelection] = useState<SelectionState | null>(\n    null\n  );\n  useEffect(() => {\n    if (!editorState) {\n      setFauxSelection(null);\n      return;\n    }\n    const content = editorState.getCurrentContent();\n    const currentSelection = editorState.getSelection();\n    const isFocused = currentSelection?.getHasFocus();\n    const hasSelectionChanged = !isEqualSelectionIgnoreFocus(\n      fauxSelection,\n      currentSelection\n    );\n    const hasFauxSelection = fauxSelection !== null;\n\n    if (!isFocused && !hasFauxSelection) {\n      // Get new content with style applied to selection\n      const contentWithFaux = Modifier.applyInlineStyle(\n        content,\n        currentSelection,\n        FAUX_SELECTION\n      );\n\n      // Push to get a new state\n      const stateWithFaux = EditorState.push(\n        editorState,\n        contentWithFaux,\n        'change-inline-style'\n      );\n\n      // Save that as the next editor state\n      setEditorState(stateWithFaux);\n\n      // And remember what we marked\n      setFauxSelection(currentSelection);\n    }\n\n    if (isFocused && hasSelectionChanged && hasFauxSelection) {\n      setEditorState((oldEditorState: EditorState | null) => {\n        try {\n          if (!oldEditorState) {\n            return null;\n          }\n          // Get new content with style removed from old selection\n          const contentWithoutFaux = Modifier.removeInlineStyle(\n            oldEditorState.getCurrentContent(),\n            fauxSelection,\n            FAUX_SELECTION\n          );\n\n          // Push to get a new state\n          const stateWithoutFaux = EditorState.push(\n            oldEditorState,\n            contentWithoutFaux,\n            'change-inline-style'\n          );\n\n          // Force selection\n          const selectedState = EditorState.forceSelection(\n            stateWithoutFaux,\n            oldEditorState.getSelection()\n          );\n\n          // Save that as the next editor state\n          return selectedState;\n        } catch {\n          // If the component has unmounted/remounted, some of the above might throw\n          // if so, just ignore it and return old state\n          return oldEditorState;\n        }\n      });\n\n      // And forget that we ever marked anything\n      setFauxSelection(null);\n    }\n  }, [fauxSelection, editorState, setEditorState]);\n}\n\nexport function fauxStylesToCSS(styles: DraftInlineStyle, css: CSSProperties) {\n  const hasFauxSelection = styles.includes(FAUX_SELECTION);\n  if (!hasFauxSelection) {\n    return null;\n  }\n  const style: CSSProperties = {\n    backgroundColor: 'rgba(169, 169, 169, 0.7)',\n  };\n  if (css?.color) {\n    style.WebkitTextFillColor = 'unset';\n    style.color = `var(--faux-selection-color, ${css.color})`;\n  }\n  return style;\n}\n"
  },
  {
    "path": "packages/rich-text/src/formatters/color.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createSolid,\n  generatePatternStyles,\n  isPatternEqual,\n  createSolidFromString,\n} from '@googleforcreators/patterns';\nimport type { Pattern, Solid } from '@googleforcreators/patterns';\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\nimport type { CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { NONE, COLOR, MULTIPLE_VALUE } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\nimport { isStyle, styleToColor, colorToStyle } from './util';\n\nfunction elementToStyle(element: HTMLElement): string | null {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const rawColor = element.style.color;\n  const hasColor = Boolean(rawColor);\n  if (isSpan && hasColor) {\n    const solid = createSolidFromString(rawColor);\n    return colorToStyle(solid);\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle): null | CSSProperties {\n  const style = styles.find((someStyle) => isStyle(someStyle, COLOR));\n  if (!style) {\n    return null;\n  }\n  let color: Pattern;\n  try {\n    color = styleToColor(style);\n  } catch {\n    return null;\n  }\n\n  return generatePatternStyles(color, 'color');\n}\n\nfunction getColor(editorState: EditorState): Pattern | '((MULTIPLE))' {\n  const styles = getPrefixStylesInSelection(editorState, COLOR);\n  if (styles.length > 1) {\n    return MULTIPLE_VALUE;\n  }\n  const colorStyle = styles[0];\n  if (colorStyle === NONE) {\n    return createSolid(0, 0, 0);\n  }\n  return styleToColor(colorStyle);\n}\n\nfunction setColor(editorState: EditorState, color: Solid) {\n  // opaque black is default, and isn't necessary to set\n  const isBlack = isPatternEqual(createSolid(0, 0, 0), color);\n  const shouldSetStyle = () => !isBlack;\n\n  // the style util manages conversion\n  const getStyleToSet = () => colorToStyle(color);\n\n  return togglePrefixStyle(editorState, COLOR, shouldSetStyle, getStyleToSet);\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: false,\n  getters: {\n    color: getColor,\n  },\n  setters: {\n    setColor,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/convert.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Modifier } from 'draft-js';\nimport type {\n  ContentBlock,\n  SelectionState,\n  ContentState,\n  CharacterMetadata,\n} from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { ITALIC, UNDERLINE } from '../customConstants';\nimport { weightToStyle } from './util';\n\nfunction convertStyles(\n  contentBlock: ContentBlock,\n  blockSelection: SelectionState,\n  contentState: ContentState\n): ContentState {\n  let updatedContentState: ContentState = contentState;\n  let lastMetadata: CharacterMetadata | null = null;\n  contentBlock.findStyleRanges(\n    (metadata: CharacterMetadata) => {\n      lastMetadata = metadata;\n      return true;\n    },\n    (start, end) => {\n      // Get new list of styles for this range\n      const oldStyles = lastMetadata?.getStyle().toArray() ?? [];\n      const newStyles = getNewStyles(oldStyles);\n      // Create a selection for this range\n      const rangeSelection = blockSelection.merge({\n        anchorOffset: start,\n        focusOffset: end,\n      });\n      // Update content by removing all the old styles and applying all the new styles\n      oldStyles.forEach((oldStyle) => {\n        updatedContentState = Modifier.removeInlineStyle(\n          updatedContentState,\n          rangeSelection,\n          oldStyle\n        );\n      });\n      newStyles.forEach((newStyle) => {\n        updatedContentState = Modifier.applyInlineStyle(\n          updatedContentState,\n          rangeSelection,\n          newStyle\n        );\n      });\n    }\n  );\n  return updatedContentState;\n}\n\nconst styleMap = {\n  BOLD: weightToStyle(700),\n  ITALIC: ITALIC,\n  UNDERLINE: UNDERLINE,\n};\ntype StyleMapKey = keyof typeof styleMap;\n\nfunction getNewStyles(oldStyles: string[]): string[] {\n  return oldStyles\n    .map((oldStyle) =>\n      oldStyle in styleMap ? styleMap[oldStyle as StyleMapKey] : ''\n    )\n    .filter(Boolean);\n}\n\nexport default convertStyles;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/gradientColor.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createSolid,\n  generatePatternStyles,\n  isPatternEqual,\n  getColorFromGradientStyle,\n  type Gradient,\n  type Pattern,\n  DEFAULT_GRADIENT,\n} from '@googleforcreators/patterns';\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\nimport type { CSSProperties } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { NONE, MULTIPLE_VALUE, GRADIENT_COLOR } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\nimport {\n  isStyle,\n  styleToGradientColor as styleToColor,\n  gradientColorToStyle as colorToStyle,\n} from './util';\n\nfunction elementToStyle(element: HTMLElement): string | null {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const rawBackground = element.style.backgroundImage;\n  const hasBackground = Boolean(rawBackground);\n\n  if (isSpan && hasBackground) {\n    const gradient = getColorFromGradientStyle(rawBackground);\n    return colorToStyle(gradient);\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle): null | CSSProperties {\n  const colorStyle = styles.find((someStyle) =>\n    isStyle(someStyle, GRADIENT_COLOR)\n  );\n\n  if (!colorStyle) {\n    return null;\n  }\n\n  let color: Pattern;\n  try {\n    color = styleToColor(colorStyle);\n  } catch {\n    return null;\n  }\n\n  const { backgroundImage } = generatePatternStyles(color);\n\n  return {\n    WebkitBackgroundClip: 'text',\n    WebkitTextFillColor: 'transparent',\n    backgroundImage,\n    backgroundClip: 'text',\n  };\n}\n\nfunction getColor(editorState: EditorState): Pattern | '((MULTIPLE))' {\n  const styles = getPrefixStylesInSelection(editorState, GRADIENT_COLOR);\n  if (styles.length > 1) {\n    return MULTIPLE_VALUE;\n  }\n  const colorStyle = styles[0];\n  if (colorStyle === NONE) {\n    return createSolid(0, 0, 0);\n  }\n  return styleToColor(colorStyle);\n}\n\nfunction setColor(editorState: EditorState, color: Gradient) {\n  const isBlack = isPatternEqual(DEFAULT_GRADIENT, color);\n  const shouldSetStyle = () => !isBlack;\n  const getStyleToSet = () => colorToStyle(color);\n  return togglePrefixStyle(\n    editorState,\n    GRADIENT_COLOR,\n    shouldSetStyle,\n    getStyleToSet\n  );\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: false,\n  getters: {\n    gradientColor: getColor,\n  },\n  setters: {\n    setGradientColor: setColor,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Formatter } from '../types';\nimport weightFormatter from './weight';\nimport italicFormatter from './italic';\nimport underlineFormatter from './underline';\nimport colorFormatter from './color';\nimport gradientColorFormatter from './gradientColor';\nimport letterSpacingFormatter from './letterSpacing';\nimport uppercaseFormatter from './uppercase';\n\nconst formatters: Formatter[] = [\n  weightFormatter,\n  italicFormatter,\n  underlineFormatter,\n  colorFormatter,\n  letterSpacingFormatter,\n  uppercaseFormatter,\n  gradientColorFormatter,\n];\n\nexport default formatters;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/italic.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { NONE, ITALIC } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\n\nfunction elementToStyle(element: HTMLElement) {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const isItalicFontStyle = element.style.fontStyle === 'italic';\n  if (isSpan && isItalicFontStyle) {\n    return ITALIC;\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle) {\n  const hasItalic = styles.includes(ITALIC);\n  if (!hasItalic) {\n    return null;\n  }\n  return { fontStyle: 'italic' };\n}\n\nfunction isItalic(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, ITALIC);\n  return !styles.includes(NONE);\n}\n\nfunction toggleItalic(editorState: EditorState, flag?: boolean): EditorState {\n  if (typeof flag === 'boolean') {\n    return togglePrefixStyle(editorState, ITALIC, () => flag);\n  }\n  return togglePrefixStyle(editorState, ITALIC);\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: true,\n  getters: {\n    isItalic,\n  },\n  setters: {\n    toggleItalic,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/letterSpacing.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { NONE, LETTERSPACING, MULTIPLE_VALUE } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\nimport { isStyle, numericToStyle, styleToNumeric } from './util';\n\nfunction letterSpacingToStyle(weight: number) {\n  return numericToStyle(LETTERSPACING, weight);\n}\n\nfunction styleToLetterSpacing(style: string) {\n  return styleToNumeric(LETTERSPACING, style);\n}\n\nfunction elementToStyle(element: HTMLElement) {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  // This will implicitly strip any trailing unit from the value - it's assumed to be em\n  const letterSpacing = Number.parseFloat(element.style.letterSpacing);\n  const hasLetterSpacing = letterSpacing && !isNaN(letterSpacing);\n  if (isSpan && hasLetterSpacing) {\n    return letterSpacingToStyle(letterSpacing * 100);\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle) {\n  const style = styles.find((someStyle) => isStyle(someStyle, LETTERSPACING));\n  if (!style) {\n    return null;\n  }\n  const letterSpacing = styleToLetterSpacing(style);\n  if (!letterSpacing) {\n    return null;\n  }\n  return { letterSpacing: `${letterSpacing / 100}em` };\n}\n\nfunction getLetterSpacing(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, LETTERSPACING);\n  if (styles.length > 1) {\n    return MULTIPLE_VALUE;\n  }\n  const spacingStyle = styles[0];\n  if (spacingStyle === NONE) {\n    return 0;\n  }\n  return styleToLetterSpacing(spacingStyle);\n}\n\nfunction setLetterSpacing(editorState: EditorState, letterSpacing: number) {\n  // if the spacing to set to non-0, set a style\n  const shouldSetStyle = () => letterSpacing !== 0;\n\n  // and if we're setting a style, it's the style for the spacing of course\n  const getStyleToSet = () => letterSpacingToStyle(letterSpacing);\n\n  return togglePrefixStyle(\n    editorState,\n    LETTERSPACING,\n    shouldSetStyle,\n    getStyleToSet\n  );\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: false,\n  getters: {\n    letterSpacing: getLetterSpacing,\n  },\n  setters: {\n    setLetterSpacing,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/_utils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@googleforcreators/react';\n\nexport function getDOMElement(jsx: JSX.Element): HTMLElement {\n  const el = document.createElement('div');\n  render(jsx, el);\n  return el.firstChild as HTMLElement;\n}\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/color.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport type { EditorState } from 'draft-js';\nimport { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../../styleManipulation';\nimport { NONE, COLOR, MULTIPLE_VALUE } from '../../customConstants';\nimport formatter from '../color';\nimport type { SetStyleCallback, StyleGetter } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Color formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without color style property', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should extract color without opacity from span elements and return correct style', () => {\n      const element = <span style={{ color: 'red' }} />;\n      const style = setupFormatter(element);\n      const expected = `${COLOR}-ff000064`;\n\n      expect(style).toBe(expected);\n    });\n\n    it('should extract color with opacity from span elements and return correct style', () => {\n      const element = <span style={{ color: 'rgba(0, 255, 0, 0.5)' }} />;\n      const style = setupFormatter(element);\n      const expected = `${COLOR}-00ff0032`;\n\n      expect(style).toBe(expected);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without a color style', () => {\n      const css = stylesToCSS(OrderedSet<string>([]));\n\n      expect(css).toBeNull();\n    });\n\n    it('should ignore invalid color style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${COLOR}-invalid`));\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS for a valid color style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${COLOR}-ff000032`));\n\n      expect(css).toStrictEqual({ color: 'rgba(255,0,0,0.5)' });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain color property with getter', () => {\n      expect(getters).toContainAllKeys(['color']);\n      expect(getters.color).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.color(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(state, COLOR);\n    });\n\n    function setupFormatter(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.color({} as EditorState);\n    }\n\n    it('should return multiple if more than one style matches', () => {\n      const styles = [`${COLOR}-ff000064`, `${COLOR}-ffff0064`];\n      const result = setupFormatter(styles);\n      expect(result).toBe(MULTIPLE_VALUE);\n    });\n\n    it('should return default black if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFormatter(styles);\n      expect(result).toStrictEqual(createSolid(0, 0, 0));\n    });\n\n    it('should return parsed color if exactly one style matches', () => {\n      const styles = [`${COLOR}-ffff0032`];\n      const result = setupFormatter(styles);\n      expect(result).toStrictEqual(createSolid(255, 255, 0, 0.5));\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain setColor property with function', () => {\n      expect(setters).toContainAllKeys(['setColor']);\n      expect(setters.setColor).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle correctly with non-black color', () => {\n      const state: EditorState = {} as EditorState;\n      const color = createSolid(255, 0, 255);\n      setters.setColor(state, color);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        COLOR,\n        expect.any(Function),\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n\n      // Fourth argument is actual style to set\n      const styleToSet = jest.mocked(togglePrefixStyle).mock\n        .calls[0][3] as StyleGetter;\n      expect(styleToSet()).toBe(`${COLOR}-ff00ff64`);\n    });\n\n    it('should invoke togglePrefixStyle correctly with black color', () => {\n      const state = {};\n      const color = createSolid(0, 0, 0);\n      setters.setColor(state as EditorState, color);\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as StyleGetter;\n      expect(shouldSetStyle()).toBeFalse();\n\n      // Fourth argument is ignored\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/italic.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  getPrefixStylesInSelection,\n  togglePrefixStyle,\n} from '../../styleManipulation';\nimport { ITALIC, NONE } from '../../customConstants';\nimport formatter from '../italic';\nimport type { SetStyleCallback } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Italic formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without italic font style', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should detect italic from span elements and return correct style', () => {\n      const element = <span style={{ fontStyle: 'italic' }} />;\n      const style = setupFormatter(element);\n      expect(style).toBe(ITALIC);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without italic style', () => {\n      const css = stylesToCSS(OrderedSet.of('NOT-ITALIC', 'ALSO-NOT-ITALIC'));\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS if italic is present', () => {\n      const css = stylesToCSS(OrderedSet.of(ITALIC));\n\n      expect(css).toStrictEqual({ fontStyle: 'italic' });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain isItalic property with getter', () => {\n      expect(getters).toContainAllKeys(['isItalic']);\n      expect(getters.isItalic).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.isItalic(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(state, ITALIC);\n    });\n\n    function setupFormatter(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.isItalic({} as EditorState);\n    }\n\n    it('should return false if both italic and non-italic', () => {\n      const styles = [NONE, ITALIC];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return false if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return true if only italic', () => {\n      const styles = [ITALIC];\n      const result = setupFormatter(styles);\n      expect(result).toBeTrue();\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain toggleItalic property with function', () => {\n      expect(setters).toContainAllKeys(['toggleItalic']);\n      expect(setters.toggleItalic).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle with state and prefix', () => {\n      const state = {};\n      setters.toggleItalic(state as EditorState);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(state, ITALIC);\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting italic to false', () => {\n      const state = {};\n      setters.toggleItalic(state as EditorState, false);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        ITALIC,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting italic to true', () => {\n      const state = {};\n      setters.toggleItalic(state as EditorState, true);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        ITALIC,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/letterSpacing.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../../styleManipulation';\nimport { NONE, LETTERSPACING, MULTIPLE_VALUE } from '../../customConstants';\nimport formatter from '../letterSpacing';\nimport type { SetStyleCallback, StyleGetter } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Color formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without letter spacing style property', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should extract letter spacing from span elements and return correct style', () => {\n      const element = <span style={{ letterSpacing: '1.5em' }} />;\n      const style = setupFormatter(element);\n      const expected = `${LETTERSPACING}-150`;\n\n      expect(style).toBe(expected);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without a letter spacing style', () => {\n      const css = stylesToCSS(\n        OrderedSet.of('NOT-LETTERSPACING', 'ALSO-NOT-LETTERSPACING')\n      );\n\n      expect(css).toBeNull();\n    });\n\n    it('should ignore invalid letter spacing style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${LETTERSPACING}-invalid`));\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS for a positive style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${LETTERSPACING}-150`));\n\n      expect(css).toStrictEqual({ letterSpacing: '1.5em' });\n    });\n\n    it('should return correct CSS for a negative style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${LETTERSPACING}-N250`));\n\n      expect(css).toStrictEqual({ letterSpacing: '-2.5em' });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain letterSpacing property with getter', () => {\n      expect(getters).toContainAllKeys(['letterSpacing']);\n      expect(getters.letterSpacing).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.letterSpacing(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(\n        state,\n        LETTERSPACING\n      );\n    });\n\n    function setupFormatter(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.letterSpacing({} as EditorState);\n    }\n\n    it('should return multiple if more than one style matches', () => {\n      const styles = [`${LETTERSPACING}-150`, `${LETTERSPACING}-N100`];\n      const result = setupFormatter(styles);\n      expect(result).toBe(MULTIPLE_VALUE);\n    });\n\n    it('should return default 0 if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFormatter(styles);\n      expect(result).toBe(0);\n    });\n\n    it('should return parsed letter spacing if exactly one style matches', () => {\n      const styles = [`${LETTERSPACING}-34`];\n      const result = setupFormatter(styles);\n      expect(result).toBe(34);\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain setLetterSpacing property with function', () => {\n      expect(setters).toContainAllKeys(['setLetterSpacing']);\n      expect(setters.setLetterSpacing).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle with state and prefix', () => {\n      const state = {};\n      const letterSpacing = 0;\n      setters.setLetterSpacing(state as EditorState, letterSpacing);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        LETTERSPACING,\n        expect.any(Function),\n        expect.any(Function)\n      );\n    });\n\n    it('should invoke togglePrefixStyle correctly for trivial letter spacing', () => {\n      const state = {};\n      // 0 letter spacing is the trivial case, that doesn't need to be added\n      const letterSpacing = 0;\n      setters.setLetterSpacing(state as EditorState, letterSpacing);\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for non-trivial letter spacing', () => {\n      const state = {};\n      // A non-zero letter spacing should be added as a style\n      const letterSpacing = -150;\n      setters.setLetterSpacing(state as EditorState, letterSpacing);\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n\n      // Fourth argument is actual style to set\n      const styleToSet = jest.mocked(togglePrefixStyle).mock\n        .calls[0][3] as StyleGetter;\n      expect(styleToSet()).toBe(`${LETTERSPACING}-N150`);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/underline.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  getPrefixStylesInSelection,\n  togglePrefixStyle,\n} from '../../styleManipulation';\nimport { NONE, UNDERLINE } from '../../customConstants';\nimport formatter from '../underline';\nimport type { SetStyleCallback } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Underline formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without underline text decoration', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should detect underline from span elements and return correct style', () => {\n      const element = <span style={{ textDecoration: 'underline' }} />;\n      const style = setupFormatter(element);\n      expect(style).toBe(UNDERLINE);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without underline style', () => {\n      const css = stylesToCSS(\n        OrderedSet.of('NOT-UNDERLINE', 'ALSO-NOT-UNDERLINE')\n      );\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS if underline is present', () => {\n      const css = stylesToCSS(OrderedSet.of(UNDERLINE));\n\n      expect(css).toStrictEqual({ textDecoration: 'underline' });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain isUnderline property with getter', () => {\n      expect(getters).toContainAllKeys(['isUnderline']);\n      expect(getters.isUnderline).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.isUnderline(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(state, UNDERLINE);\n    });\n\n    function setupFormatter(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.isUnderline({} as EditorState);\n    }\n\n    it('should return false if both underline and non-underline', () => {\n      const styles = [NONE, UNDERLINE];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return false if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return true if only underline', () => {\n      const styles = [UNDERLINE];\n      const result = setupFormatter(styles);\n      expect(result).toBeTrue();\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain toggleUnderline property with function', () => {\n      expect(setters).toContainAllKeys(['toggleUnderline']);\n      expect(setters.toggleUnderline).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle with state and prefix', () => {\n      const state = {};\n      setters.toggleUnderline(state as EditorState);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(state, UNDERLINE);\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting underline to false', () => {\n      const state = {};\n      setters.toggleUnderline(state as EditorState, false);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        UNDERLINE,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting underline to true', () => {\n      const state = {};\n      setters.toggleUnderline(state as EditorState, true);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        UNDERLINE,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/uppercase.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { OrderedSet } from 'immutable';\nimport type { EditorState } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport {\n  getPrefixStylesInSelection,\n  togglePrefixStyle,\n} from '../../styleManipulation';\nimport { NONE, UPPERCASE } from '../../customConstants';\nimport formatter from '../uppercase';\nimport type { SetStyleCallback } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Uppercase formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without uppercase text transform', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should detect uppercase from span elements and return correct style', () => {\n      const element = <span style={{ textTransform: 'uppercase' }} />;\n      const style = setupFormatter(element);\n      expect(style).toBe(UPPERCASE);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without uppercase style', () => {\n      const css = stylesToCSS(\n        OrderedSet.of('NOT-UPPERCASE', 'ALSO-NOT-UPPERCASE')\n      );\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS if uppercase is present', () => {\n      const css = stylesToCSS(OrderedSet.of(UPPERCASE));\n\n      expect(css).toStrictEqual({ textTransform: 'uppercase' });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain isUppercase property with getter', () => {\n      expect(getters).toContainAllKeys(['isUppercase']);\n      expect(getters.isUppercase).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.isUppercase(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(state, UPPERCASE);\n    });\n\n    function setupFormatter(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.isUppercase({} as EditorState);\n    }\n\n    it('should return false if both uppercase and non-uppercase', () => {\n      const styles = [NONE, UPPERCASE];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return false if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFormatter(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return true if only uppercase', () => {\n      const styles = [UPPERCASE];\n      const result = setupFormatter(styles);\n      expect(result).toBeTrue();\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain toggleUppercase property with function', () => {\n      expect(setters).toContainAllKeys(['toggleUppercase']);\n      expect(setters.toggleUppercase).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle with state and prefix', () => {\n      const state = {};\n      setters.toggleUppercase(state as EditorState);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(state, UPPERCASE);\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting uppercase to false', () => {\n      const state = {};\n      setters.toggleUppercase(state as EditorState, false);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        UPPERCASE,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting uppercase to true', () => {\n      const state = {};\n      setters.toggleUppercase(state as EditorState, true);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        UPPERCASE,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/test/weight.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../../styleManipulation';\nimport { NONE, WEIGHT, MULTIPLE_VALUE } from '../../customConstants';\nimport formatter from '../weight';\nimport type { SetStyleCallback, StyleGetter } from '../../types';\nimport { getDOMElement } from './_utils';\n\njest.mock('../../styleManipulation', () => {\n  return {\n    togglePrefixStyle: jest.fn(),\n    getPrefixStylesInSelection: jest.fn(),\n  };\n});\n\nconst { elementToStyle, stylesToCSS, getters, setters } = formatter;\n\ndescribe('Color formatter', () => {\n  beforeAll(() => {\n    jest.mocked(getPrefixStylesInSelection).mockImplementation(() => [NONE]);\n  });\n\n  beforeEach(() => {\n    jest.mocked(togglePrefixStyle).mockClear();\n    jest.mocked(getPrefixStylesInSelection).mockClear();\n  });\n\n  describe('elementToStyle', () => {\n    function setupFormatter(element: JSX.Element) {\n      return elementToStyle(getDOMElement(element));\n    }\n\n    it('should ignore non-span elements', () => {\n      const element = <div />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should ignore span elements without font weight style property', () => {\n      const element = <span style={{ backgroundColor: 'red' }} />;\n      const style = setupFormatter(element);\n\n      expect(style).toBeNull();\n    });\n\n    it('should extract font weight from span elements and return correct style', () => {\n      const element = <span style={{ fontWeight: 600 }} />;\n      const style = setupFormatter(element);\n      const expected = `${WEIGHT}-600`;\n\n      expect(style).toBe(expected);\n    });\n  });\n\n  describe('stylesToCSS', () => {\n    it('should ignore styles without a font weight style', () => {\n      const css = stylesToCSS(OrderedSet.of('NOT-WEIGHT', 'ALSO-NOT-WEIGHT'));\n\n      expect(css).toBeNull();\n    });\n\n    it('should ignore invalid font weight style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${WEIGHT}-invalid`));\n\n      expect(css).toBeNull();\n    });\n\n    it('should return correct CSS for a valid style', () => {\n      const css = stylesToCSS(OrderedSet.of(`${WEIGHT}-500`));\n\n      expect(css).toStrictEqual({ fontWeight: 500 });\n    });\n  });\n\n  describe('getters', () => {\n    it('should contain weight and isBold properties with getters', () => {\n      expect(getters).toContainAllKeys(['fontWeight', 'isBold']);\n      expect(getters.fontWeight).toStrictEqual(expect.any(Function));\n      expect(getters.isBold).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke getPrefixStylesInSelection with given state and correct style prefix', () => {\n      const state = {};\n      getters.fontWeight(state as EditorState);\n      expect(getPrefixStylesInSelection).toHaveBeenCalledWith(state, WEIGHT);\n    });\n\n    function setupFontWeight(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.fontWeight({} as EditorState);\n    }\n\n    it('should return multiple if more than one style matches', () => {\n      const styles = [`${WEIGHT}-400`, `${WEIGHT}-600`];\n      const result = setupFontWeight(styles);\n      expect(result).toBe(MULTIPLE_VALUE);\n    });\n\n    it('should return default 400 if no style matches', () => {\n      const styles = [NONE];\n      const result = setupFontWeight(styles);\n      expect(result).toBe(400);\n    });\n\n    it('should return parsed font weight if exactly one style matches', () => {\n      const styles = [`${WEIGHT}-700`];\n      const result = setupFontWeight(styles);\n      expect(result).toBe(700);\n    });\n\n    function setupIsBold(styleArray: string[]) {\n      jest\n        .mocked(getPrefixStylesInSelection)\n        .mockImplementationOnce(() => styleArray);\n      return getters.isBold({} as EditorState);\n    }\n\n    it('should return false if mix of bold and non-bold', () => {\n      const styles = [`${WEIGHT}-300`, `${WEIGHT}-700`];\n      const result = setupIsBold(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return false if no style matches', () => {\n      const styles = [NONE];\n      const result = setupIsBold(styles);\n      expect(result).toBeFalse();\n    });\n\n    it('should return true if all are bold', () => {\n      const styles = [`${WEIGHT}-800`, `${WEIGHT}-600`];\n      const result = setupIsBold(styles);\n      expect(result).toBeTrue();\n    });\n  });\n\n  describe('setters', () => {\n    it('should contain setWeight and toggleBold properties with functions', () => {\n      expect(setters).toContainAllKeys(['setFontWeight', 'toggleBold']);\n      expect(setters.setFontWeight).toStrictEqual(expect.any(Function));\n      expect(setters.toggleBold).toStrictEqual(expect.any(Function));\n    });\n\n    it('should invoke togglePrefixStyle with state and prefix', () => {\n      const state = {};\n      const weight = 0;\n      setters.setFontWeight(state as EditorState, weight);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        WEIGHT,\n        expect.any(Function),\n        expect.any(Function)\n      );\n    });\n\n    it('should invoke togglePrefixStyle correctly for trivial font weight', () => {\n      const state = {};\n      // 400 font weight is the trivial case, that doesn't need to be added\n      const weight = 400;\n      setters.setFontWeight(state as EditorState, weight);\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for non-trivial font weight', () => {\n      const state = {};\n      // A non-400 font weight should be added as a style\n      const weight = 900;\n      setters.setFontWeight(state as EditorState, weight);\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n\n      // Fourth argument is actual style to set\n      const styleToSet = jest.mocked(togglePrefixStyle).mock\n        .calls[0][3] as StyleGetter;\n      expect(styleToSet()).toBe(`${WEIGHT}-900`);\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting bold to false', () => {\n      const state = {};\n      setters.toggleBold(state as EditorState, false);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        WEIGHT,\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeFalse();\n    });\n\n    it('should invoke togglePrefixStyle correctly for explicitly setting bold to true', () => {\n      const state = {};\n      setters.toggleBold(state as EditorState, true);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        WEIGHT,\n        expect.any(Function),\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle()).toBeTrue();\n\n      // Fourth argument is actual style to set\n      const styleToSet = jest.mocked(togglePrefixStyle).mock\n        .calls[0][3] as SetStyleCallback;\n      expect(styleToSet()).toBe(`${WEIGHT}-700`);\n    });\n\n    it('should correctly determine if setting bold when toggling without explicit flag', () => {\n      const state = {};\n      setters.toggleBold(state as EditorState);\n      expect(togglePrefixStyle).toHaveBeenCalledWith(\n        state,\n        WEIGHT,\n        expect.any(Function),\n        expect.any(Function)\n      );\n\n      // Third argument is tester\n      const shouldSetStyle = jest.mocked(togglePrefixStyle).mock\n        .calls[0][2] as SetStyleCallback;\n      expect(shouldSetStyle([NONE])).toBeTrue();\n      expect(shouldSetStyle([`${WEIGHT}-300`, `${WEIGHT}-900`])).toBeTrue();\n      expect(shouldSetStyle([`${WEIGHT}-600`, `${WEIGHT}-900`])).toBeFalse();\n\n      // Fourth argument is actual style to set\n      const styleToSet = jest.mocked(togglePrefixStyle).mock\n        .calls[0][3] as StyleGetter;\n      expect(styleToSet([NONE])).toBe(`${WEIGHT}-700`);\n      expect(styleToSet([`${WEIGHT}-300`, `${WEIGHT}-600`])).toBe(\n        `${WEIGHT}-700`\n      );\n      expect(styleToSet([`${WEIGHT}-300`, `${WEIGHT}-900`])).toBe(\n        `${WEIGHT}-900`\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/formatters/underline.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DraftInlineStyle, EditorState } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { NONE, UNDERLINE } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\n\nfunction elementToStyle(element: HTMLElement) {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const isUnderlineDecoration = element.style.textDecoration === 'underline';\n  if (isSpan && isUnderlineDecoration) {\n    return UNDERLINE;\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle) {\n  const hasUnderline = styles.includes(UNDERLINE);\n  if (!hasUnderline) {\n    return null;\n  }\n  return { textDecoration: 'underline' };\n}\n\nfunction isUnderline(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, UNDERLINE);\n  return !styles.includes(NONE);\n}\n\nfunction toggleUnderline(editorState: EditorState, flag?: boolean) {\n  if (typeof flag === 'boolean') {\n    return togglePrefixStyle(editorState, UNDERLINE, () => flag);\n  }\n  return togglePrefixStyle(editorState, UNDERLINE);\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: true,\n  getters: {\n    isUnderline,\n  },\n  setters: {\n    toggleUnderline,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/uppercase.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { NONE, UPPERCASE } from '../customConstants';\nimport {\n  togglePrefixStyle,\n  getPrefixStylesInSelection,\n} from '../styleManipulation';\n\nfunction elementToStyle(element: HTMLElement) {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const isUppercaseTransform = element.style.textTransform === 'uppercase';\n  if (isSpan && isUppercaseTransform) {\n    return UPPERCASE;\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle) {\n  const hasUppercase = styles.includes(UPPERCASE);\n  if (!hasUppercase) {\n    return null;\n  }\n  return { textTransform: 'uppercase' as const };\n}\n\nfunction isUppercase(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, UPPERCASE);\n  return !styles.includes(NONE);\n}\n\nfunction toggleUppercase(editorState: EditorState, flag?: boolean) {\n  if (typeof flag === 'boolean') {\n    return togglePrefixStyle(editorState, UPPERCASE, () => flag);\n  }\n  return togglePrefixStyle(editorState, UPPERCASE);\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: true,\n  getters: {\n    isUppercase,\n  },\n  setters: {\n    toggleUppercase,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/util.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { FontWeight, FontVariantStyle } from '@googleforcreators/elements';\nimport {\n  getColorFromGradientStyle,\n  getGradientStyleFromColor,\n  getHexFromSolid,\n  getSolidFromHex,\n  type Gradient,\n  type Pattern,\n  type Solid,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport {\n  COLOR,\n  GRADIENT_COLOR,\n  type LETTERSPACING,\n  WEIGHT,\n} from '../customConstants';\n\nexport const isStyle = (style: string | undefined, prefix: string) =>\n  Boolean(style?.startsWith(prefix));\n\nexport const getVariable = (style: string, prefix: string) =>\n  style.slice(prefix.length + 1);\n\n/*\n * Numerics use PREFIX-123 for the number 123\n * and PREFIX-N123 for the number -123.\n */\nexport const numericToStyle = (prefix: string, num: number) =>\n  `${prefix}-${num < 0 ? 'N' : ''}${Math.abs(num)}`;\n\nexport function styleToNumeric(\n  prefix: typeof LETTERSPACING,\n  style: string\n): number;\nexport function styleToNumeric(\n  prefix: typeof WEIGHT,\n  style: string\n): FontWeight;\nexport function styleToNumeric(\n  prefix: string,\n  style: string\n): FontWeight | FontVariantStyle {\n  const raw = getVariable(style, prefix);\n  // Negative numbers are prefixed with an N:\n  if (raw.charAt(0) === 'N') {\n    return -Number.parseInt(raw.slice(1));\n  }\n  return Number.parseInt(raw);\n}\n\nexport function weightToStyle(weight: number) {\n  return numericToStyle(WEIGHT, weight);\n}\n\n/*\n * Color uses PREFIX-XXXXXXXX where XXXXXXXX is the 8 digit\n * hex representation of the RGBA color.\n */\nexport const styleToColor = (style: string): Pattern =>\n  getSolidFromHex(getVariable(style, COLOR));\n\nexport const colorToStyle = (color: Solid): string =>\n  `${COLOR}-${getHexFromSolid(color)}`;\n\nexport const styleToGradientColor = (style: string): Gradient =>\n  getColorFromGradientStyle(getVariable(style, GRADIENT_COLOR));\n\nexport const gradientColorToStyle = (color: Gradient): string =>\n  `${GRADIENT_COLOR}-${getGradientStyleFromColor(color)}`;\n"
  },
  {
    "path": "packages/rich-text/src/formatters/weight.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DraftInlineStyle, EditorState } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE, NONE, WEIGHT } from '../customConstants';\nimport {\n  getPrefixStylesInSelection,\n  togglePrefixStyle,\n} from '../styleManipulation';\nimport { isStyle, styleToNumeric, weightToStyle } from './util';\n\nconst NORMAL_WEIGHT = 400;\nconst SMALLEST_BOLD = 600;\nconst DEFAULT_BOLD = 700;\n\nfunction styleToWeight(style: string) {\n  return styleToNumeric(WEIGHT, style);\n}\n\nfunction elementToStyle(element: HTMLElement) {\n  const isSpan = element.tagName.toLowerCase() === 'span';\n  const fontWeight = Number.parseInt(element.style.fontWeight);\n  const hasFontWeight = fontWeight && !isNaN(fontWeight);\n  if (isSpan && hasFontWeight && fontWeight !== 400) {\n    return weightToStyle(fontWeight);\n  }\n\n  return null;\n}\n\nfunction stylesToCSS(styles: DraftInlineStyle) {\n  const style = styles.find((someStyle) => isStyle(someStyle, WEIGHT));\n  if (!style) {\n    return null;\n  }\n  const fontWeight = styleToWeight(style);\n  if (!fontWeight) {\n    return null;\n  }\n  return { fontWeight };\n}\n\n// convert a set of weight styles to a set of weights\nfunction getWeights(styles: string[]) {\n  return styles.map((style) =>\n    style === NONE ? NORMAL_WEIGHT : styleToWeight(style)\n  );\n}\n\nfunction isBold(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, WEIGHT);\n  const weights = getWeights(styles);\n  return weights.every((w) => w >= SMALLEST_BOLD);\n}\n\nfunction toggleBold(editorState: EditorState, flag?: boolean) {\n  if (typeof flag === 'boolean') {\n    if (flag) {\n      const getDefault = () => weightToStyle(DEFAULT_BOLD);\n      return togglePrefixStyle(editorState, WEIGHT, () => true, getDefault);\n    }\n\n    // No fourth arg needed as we're not setting a style\n    return togglePrefixStyle(editorState, WEIGHT, () => false);\n  }\n\n  // if no flag is set, determine these values from current weights present\n\n  // if any character has weight less than SMALLEST_BOLD,\n  // everything should be bolded\n  const shouldSetBold = (styles: string[] = []) =>\n    getWeights(styles).some((w) => w < SMALLEST_BOLD);\n\n  // if setting a bold, it should be the boldest current weight,\n  // though at least DEFAULT_BOLD\n  const getBoldToSet = (styles: string[] = []) =>\n    weightToStyle(Math.max(...[DEFAULT_BOLD].concat(getWeights(styles))));\n\n  return togglePrefixStyle(editorState, WEIGHT, shouldSetBold, getBoldToSet);\n}\n\nfunction getFontWeight(editorState: EditorState) {\n  const styles = getPrefixStylesInSelection(editorState, WEIGHT);\n  const weights = getWeights(styles);\n  if (weights.length > 1) {\n    return MULTIPLE_VALUE;\n  }\n  return weights[0];\n}\n\nfunction setFontWeight(editorState: EditorState, weight = 0) {\n  // if the weight to set is non-400, set a style\n  // (if 400 is target, all other weights are just removed, and we're good)\n  const shouldSetStyle = () => weight !== 400;\n\n  // and if we're setting a style, it's the style for the weight of course\n  const getBoldToSet = () => weightToStyle(weight);\n\n  return togglePrefixStyle(editorState, WEIGHT, shouldSetStyle, getBoldToSet);\n}\n\nconst formatter = {\n  elementToStyle,\n  stylesToCSS,\n  autoFocus: true,\n  getters: {\n    isBold,\n    fontWeight: getFontWeight,\n  },\n  setters: {\n    toggleBold,\n    setFontWeight,\n  },\n};\n\nexport default formatter;\n"
  },
  {
    "path": "packages/rich-text/src/getFontVariants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport type { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport {\n  FontVariantStyle,\n  type FontVariant,\n} from '@googleforcreators/elements';\nimport { ITALIC, WEIGHT } from './customConstants';\nimport { styleToNumeric } from './formatters/util';\nimport { getAllStyleSetsInSelection } from './draftUtils';\nimport { getSelectAllStateFromHTML } from './htmlManipulation';\n\n/**\n * Gets font styles for a characters, considers italic and weight only.\n *\n * @param styles Set of styles.\n * @return Array of found styles for the character.\n */\nfunction getFontStylesForCharacter(styles: OrderedSet<string>): string[] {\n  return styles\n    .toArray()\n    .filter((style) => style === ITALIC || style.startsWith(WEIGHT));\n}\n\n/**\n * Gets an array of all found font variants (unique).\n * Font variants are in the format of [italic, weight] where italic is 0 or 1.\n *\n * @param editorState Editor state.\n * @return Array of variants.\n */\nfunction getVariants(editorState: EditorState) {\n  const styleSets = getAllStyleSetsInSelection(editorState);\n  if (styleSets.length === 0) {\n    return getFontStylesForCharacter(editorState.getCurrentInlineStyle());\n  }\n  const styles = styleSets.map((styleSet) => {\n    const [style = ''] = getFontStylesForCharacter(styleSet);\n\n    return style;\n  });\n\n  return [...new Set(styles)];\n}\n\nexport default function getFontVariants(html: string): FontVariant[] {\n  const htmlState = getSelectAllStateFromHTML(html);\n  const variants: FontVariant[] = getVariants(htmlState).map((variant) => [\n    variant.startsWith(ITALIC)\n      ? FontVariantStyle.Italic\n      : FontVariantStyle.Normal,\n    variant.startsWith(WEIGHT) ? styleToNumeric(WEIGHT, variant) : 400,\n  ]);\n\n  // Return default variant or the found variants.\n  return variants.length > 0 ? variants : [[0, 400]];\n}\n"
  },
  {
    "path": "packages/rich-text/src/getPastedBlocks.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Modifier,\n  convertFromHTML,\n  ContentState,\n  SelectionState,\n} from 'draft-js';\nimport type { ContentBlock } from 'draft-js';\nimport { Map } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport convertStyles from './formatters/convert';\n\nconst RENDER_MAP = Map({\n  unstyled: {\n    element: 'div',\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- aliasedElements actually does exist on the type when looking at the module but the correct type is not imported.\n    // @ts-ignore\n    aliasedElements: ['p', 'h1', 'h2', 'h3', 'blockquote', 'pre'],\n  },\n  'unordered-list-item': {\n    element: 'li',\n  },\n  'ordered-list-item': {\n    element: 'li',\n  },\n});\n\n// Overriding this since entityMap is marked as `any` in there, however, it seems to be an object in this case.\ntype ConvertFromHTMLReturn = {\n  contentBlocks: ContentBlock[];\n  entityMap: Record<string, unknown>;\n};\nfunction getPastedBlocks(html: string, existingStyles: string[] = []) {\n  const { contentBlocks, entityMap } = convertFromHTML(\n    html,\n    undefined /* This has to be undefined to trigger default argument */,\n    RENDER_MAP\n  ) as ConvertFromHTMLReturn;\n  const pastedContentState = ContentState.createFromBlockArray(\n    contentBlocks,\n    entityMap\n  );\n\n  // Now select everything and remove entity from it all\n  const entireSelection = selectEverything(pastedContentState);\n  const noEntityContent = Modifier.applyEntity(\n    pastedContentState,\n    entireSelection,\n    null\n  );\n\n  // Then walk through entire content, building a new parallel document in `updatedContentState`\n  // with corrected styles and the required added list styles\n  const newContentBlocks = noEntityContent.getBlocksAsArray();\n  let updatedContentState = noEntityContent;\n  let lastBlockType: string | null = null;\n  let lastBlockNumber = 0;\n\n  newContentBlocks.forEach((contentBlock) => {\n    const blockSelection = SelectionState.createEmpty(contentBlock.getKey());\n    updatedContentState = convertStyles(\n      contentBlock,\n      blockSelection,\n      updatedContentState\n    );\n\n    // Then, if it is some list item block, prefix with proper symbol and change type to unstyled\n    const blockType = contentBlock.getType();\n    if (blockType !== 'unstyled') {\n      let replacementText = null;\n      switch (blockType) {\n        case 'unordered-list-item':\n          replacementText = '– ';\n          break;\n        case 'ordered-list-item':\n          lastBlockNumber =\n            lastBlockType === blockType ? lastBlockNumber + 1 : 1;\n          replacementText = `${lastBlockNumber}. `;\n          break;\n        default:\n          break;\n      }\n      if (replacementText) {\n        // Insert text at start of block\n        updatedContentState = Modifier.insertText(\n          updatedContentState,\n          blockSelection,\n          replacementText\n        );\n      }\n      // Reset block type for entire block\n      const entireBlockSelection = blockSelection.merge({\n        focusOffset: contentBlock.getLength(),\n      });\n      updatedContentState = Modifier.setBlockType(\n        updatedContentState,\n        entireBlockSelection,\n        'unstyled'\n      );\n    }\n    lastBlockType = blockType;\n  });\n\n  // Finally, apply existing styles if any\n  const everythingSelection = selectEverything(updatedContentState);\n  existingStyles.forEach((existingStyle) => {\n    updatedContentState = Modifier.applyInlineStyle(\n      updatedContentState,\n      everythingSelection,\n      existingStyle\n    );\n  });\n\n  return updatedContentState.getBlockMap();\n}\n\nexport default getPastedBlocks;\n\nfunction selectEverything(contentState: ContentState) {\n  const firstBlock = contentState.getFirstBlock();\n  const lastBlock = contentState.getLastBlock();\n  return SelectionState.createEmpty(firstBlock.getKey()).merge({\n    focusKey: lastBlock.getKey(),\n    focusOffset: lastBlock.getLength(),\n  });\n}\n"
  },
  {
    "path": "packages/rich-text/src/getStateInfo.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { EditorState } from 'draft-js';\nimport type { Pattern } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport formatters from './formatters';\nimport type { StateInfo } from './types';\n\ntype Getter = (state: EditorState) => boolean | string | number | Pattern;\n\nfunction getStateInfo(state: EditorState): StateInfo {\n  const stateInfo = formatters.reduce(\n    (aggr, { getters }) => ({\n      ...aggr,\n      ...Object.fromEntries(\n        Object.entries(getters).map(([key, getter]: [string, Getter]) => [\n          key,\n          getter(state),\n        ])\n      ),\n    }),\n    {}\n  );\n  return stateInfo;\n}\n\nexport default getStateInfo;\n"
  },
  {
    "path": "packages/rich-text/src/getTextColors.ts",
    "content": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createSolid,\n  getHexFromSolid,\n  type Solid,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { COLOR, NONE } from './customConstants';\nimport { getSelectAllStateFromHTML } from './htmlManipulation';\nimport { getPrefixStylesInSelection } from './styleManipulation';\nimport { styleToColor } from './formatters/util';\n\nexport default function getTextColors(html: string): string[] {\n  const htmlState = getSelectAllStateFromHTML(html);\n  return getPrefixStylesInSelection(htmlState, COLOR)\n    .map((color) => {\n      if (color === NONE) {\n        return createSolid(0, 0, 0);\n      }\n\n      return styleToColor(color) as Solid;\n    })\n    .map(\n      // To remove the alpha channel.\n      (color) => '#' + getHexFromSolid(color).slice(0, 6)\n    );\n}\n"
  },
  {
    "path": "packages/rich-text/src/htmlManipulation.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { EditorState } from 'draft-js';\nimport { filterEditorState } from 'draftjs-filters';\n\n/**\n * Internal dependencies\n */\nimport formatters from './formatters';\nimport getStateInfo from './getStateInfo';\nimport customImport from './customImport';\nimport customExport from './customExport';\nimport { getSelectionForAll } from './util';\nimport type { StyleSetter, AllowedSetterArgs } from './types';\nimport {\n  ITALIC,\n  UNDERLINE,\n  WEIGHT,\n  COLOR,\n  LETTERSPACING,\n  UPPERCASE,\n  GRADIENT_COLOR,\n} from './customConstants';\nimport { getPrefixStylesInSelection } from './styleManipulation';\n\n/**\n * Return an editor state object with content set to parsed HTML\n * and selection set to everything.\n *\n * @param html  HTML string to parse into content\n * @return New editor state with selection\n */\nexport function getSelectAllStateFromHTML(html: string) {\n  const contentState = customImport(html);\n  const initialState = EditorState.createWithContent(contentState);\n  const selection = getSelectionForAll(initialState.getCurrentContent());\n  return EditorState.forceSelection(initialState, selection);\n}\n\n/**\n * Convert HTML via updater function. As updater function works on the\n * current selection in an editor state, first parse HTML to editor state\n * with entire body selected, then run updater and then export back to\n * HTML again.\n *\n * @param html  HTML string to parse into content\n * @param updater  A function converting a state to a new state\n * @param args  Extra args to supply to updater other than state\n * @return New HTML with updates applied\n */\nfunction updateAndReturnHTML(\n  html: string,\n  updater: StyleSetter,\n  ...args: [AllowedSetterArgs]\n) {\n  const stateWithUpdate = updater(getSelectAllStateFromHTML(html), ...args);\n  return customExport(stateWithUpdate);\n}\n\nconst getHTMLFormatter =\n  (setter: StyleSetter) =>\n  (html: string, ...args: [AllowedSetterArgs]) =>\n    updateAndReturnHTML(html, setter, ...args);\n\nexport const getHTMLFormatters = (): {\n  [p: string]: (html: string, args: AllowedSetterArgs) => string;\n} => {\n  return formatters.reduce(\n    (aggr, { setters }) => ({\n      ...aggr,\n      ...Object.fromEntries(\n        Object.entries(setters).map(([key, setter]) => [\n          key,\n          getHTMLFormatter(setter as StyleSetter),\n        ])\n      ),\n    }),\n    {}\n  );\n};\n\nexport function getHTMLInfo(html: string) {\n  const htmlStateInfo = getStateInfo(getSelectAllStateFromHTML(html));\n  return htmlStateInfo;\n}\n\nexport function sanitizeEditorHtml(html: string) {\n  const editorState = getSelectAllStateFromHTML(html);\n\n  const styles: string[] = [\n    ...getPrefixStylesInSelection(editorState, ITALIC),\n    ...getPrefixStylesInSelection(editorState, UNDERLINE),\n    ...getPrefixStylesInSelection(editorState, WEIGHT),\n    ...getPrefixStylesInSelection(editorState, COLOR),\n    ...getPrefixStylesInSelection(editorState, LETTERSPACING),\n    ...getPrefixStylesInSelection(editorState, UPPERCASE),\n    ...getPrefixStylesInSelection(editorState, GRADIENT_COLOR),\n  ];\n\n  return (\n    customExport(\n      filterEditorState(\n        {\n          blocks: [],\n          styles,\n          entities: [],\n          maxNesting: 1,\n          whitespacedCharacters: [],\n          blockTextRules: [],\n        },\n        editorState\n      )\n    ) || ''\n  );\n}\n"
  },
  {
    "path": "packages/rich-text/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as RichTextProvider } from './provider';\nexport { default as RichTextEditor } from './editor';\nexport { default as RichTextContext } from './context';\nexport { default as useRichText } from './useRichText';\nexport { default as usePasteTextContent } from './usePasteTextContent';\nexport { default as getFontVariants } from './getFontVariants';\nexport { default as getTextColors } from './getTextColors';\nexport { default as getCaretCharacterOffsetWithin } from './utils/getCaretCharacterOffsetWithin';\nexport * from './htmlManipulation';\n\nexport * from './types';\n"
  },
  {
    "path": "packages/rich-text/src/provider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useMemo,\n  useRef,\n} from '@googleforcreators/react';\nimport type { ReactNode } from 'react';\nimport { EditorState } from 'draft-js';\nimport type { DraftInlineStyle } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport RichTextContext from './context';\nimport {\n  getSelectionForAll,\n  getSelectionForOffset,\n  getFilteredState,\n  getHandleKeyCommandFromState,\n} from './util';\nimport getStateInfo from './getStateInfo';\nimport { useFauxSelection } from './fauxSelection';\nimport customImport from './customImport';\nimport customExport from './customExport';\nimport useHandlePastedText from './useHandlePastedText';\nimport useSelectionManipulation from './useSelectionManipulation';\nimport type { EditingState, State } from './types';\n\nconst INITIAL_SELECTION_INFO = {\n  isBold: false,\n  isItalic: false,\n  isUnderline: false,\n  isUppercase: false,\n};\n\nexport interface RichTextProviderProps {\n  children: ReactNode;\n  editingState: EditingState;\n}\nfunction RichTextProvider({ children, editingState }: RichTextProviderProps) {\n  const [editorState, setEditorState] = useState<EditorState | null>(null);\n  const lastKnownStyleRef = useRef<DraftInlineStyle | null>(null);\n\n  const selectionInfo = useMemo(() => {\n    if (editorState) {\n      return getStateInfo(editorState);\n    }\n    return INITIAL_SELECTION_INFO;\n  }, [editorState]);\n\n  const setStateFromContent = useCallback(\n    (content: string) => {\n      const { offset, selectAll } = editingState || {};\n      let state = EditorState.createWithContent(customImport(content));\n\n      let selection;\n      if (selectAll) {\n        selection = getSelectionForAll(state.getCurrentContent());\n      } else if (offset) {\n        selection = getSelectionForOffset(state.getCurrentContent(), offset);\n      }\n      if (selection) {\n        state = EditorState.forceSelection(state, selection);\n      }\n      lastKnownStyleRef.current = state.getCurrentInlineStyle();\n      setEditorState(state);\n    },\n    [editingState, setEditorState]\n  );\n\n  useFauxSelection(editorState, setEditorState);\n\n  // This filters out illegal content (see `getFilteredState`)\n  // on paste and updates state accordingly.\n  // Furthermore it also sets initial selection if relevant.\n  const updateEditorState = useCallback(\n    (newEditorState: EditorState) => {\n      if (!newEditorState || !editorState) {\n        return;\n      }\n      let filteredState = getFilteredState(newEditorState, editorState);\n      const isEmpty =\n        filteredState?.getCurrentContent().getPlainText('') === '';\n      if (isEmpty && lastKnownStyleRef.current) {\n        // Copy last known current style as inline style\n        filteredState = EditorState.setInlineStyleOverride(\n          filteredState,\n          lastKnownStyleRef.current\n        );\n      } else {\n        lastKnownStyleRef.current = filteredState.getCurrentInlineStyle();\n      }\n      setEditorState(filteredState);\n    },\n    [editorState, setEditorState]\n  );\n\n  const getHandleKeyCommand = useCallback(\n    () => getHandleKeyCommandFromState(updateEditorState),\n    [updateEditorState]\n  );\n\n  const handlePastedText = useHandlePastedText(setEditorState);\n\n  const clearState = useCallback(() => {\n    setEditorState(null);\n  }, [setEditorState]);\n\n  const hasCurrentEditor = Boolean(editorState);\n\n  const selectionActions = useSelectionManipulation(\n    editorState,\n    setEditorState\n  );\n\n  const value: State = {\n    state: {\n      editorState,\n      hasCurrentEditor,\n      selectionInfo,\n    },\n    actions: {\n      setStateFromContent,\n      updateEditorState,\n      getHandleKeyCommand,\n      handlePastedText,\n      clearState,\n      selectionActions,\n      // These actually don't work on the state at all, just pure functions\n      getContentFromState: customExport,\n    },\n  };\n\n  return (\n    <RichTextContext.Provider value={value}>\n      {children}\n    </RichTextContext.Provider>\n  );\n}\n\nexport default RichTextProvider;\n"
  },
  {
    "path": "packages/rich-text/src/styleManipulation.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ContentState } from 'draft-js';\nimport { EditorState, Modifier } from 'draft-js';\nimport type { OrderedSet } from 'immutable';\n\n/**\n * Internal dependencies\n */\nimport { NONE } from './customConstants';\nimport { getAllStyleSetsInSelection } from './draftUtils';\nimport type { SetStyleCallback, StyleGetter } from './types';\n\n/**\n * Get a first style in the given set that match the given prefix,\n * or NONE if there's no match.\n *\n * @param styles  Set (ImmutableSet even) of styles to check\n * @param prefix  Prefix to test styles for\n * @return First match or NONE\n */\nexport function getPrefixStyleForCharacter(\n  styles: OrderedSet<string>,\n  prefix: string\n): string {\n  const list = styles.toArray();\n  const matcher = (style: string) => style && style.startsWith(prefix);\n  if (!list.some(matcher)) {\n    return NONE;\n  }\n  // If there are no matches, we return NONE, so the value is not `undefined` here, thus casting to `string`.\n  return list.find(matcher) as string;\n}\n\n/**\n * Get a deduped list of all matching styles for every character in the\n * current selection for the current content.\n *\n * A style is matching, if it matches the current prefix. If for any given\n * character in the current selection, there's no prefix match, NONE will\n * be part of the returned set.\n *\n * If selection is collapsed, it'll get the style matching at the current\n * insertion point (or NONE).\n *\n * <example>\n * // In all examples below,\n * // - first character is WEIGHT-700, ITALIC\n * // - second character is WEIGHT-900, ITALIC\n * // - third character is ITALIC\n * // - all other characters have no styling\n *\n * // This is the text: Hello\n * // Editor state with selection \"[He]llo\":\n * const editorStateEl = {};\n * // Editor state with selection \"[Hel]lo\":\n * const editorStateHel = {};\n * // Editor state with selection \"[Hello]\":\n * const editorStateHello = {};\n * // Editor state with selection \"Hel[lo]\":\n * const editorStateLo = {};\n *\n * const styles = getPrefixStylesInSelection(editorStateEl, 'ITALIC');\n * // styles are now: ['ITALIC']\n *\n * const styles = getPrefixStylesInSelection(editorStateHello, 'ITALIC');\n * // styles are now: ['ITALIC', 'NONE']\n *\n * const styles = getPrefixStylesInSelection(editorStateLo, 'ITALIC');\n * // styles are now: ['NONE']\n *\n * const styles = getPrefixStylesInSelection(editorStateHel, 'WEIGHT');\n * // styles are now: ['WEIGHT-700', 'WEIGHT-900', 'NONE']\n *\n * const styles = getPrefixStylesInSelection(editorStateLo, 'WEIGHT');\n * // styles are now: ['NONE']\n * </example>\n *\n * @param editorState  Current editor state\n * @param prefix  Prefix to test styles for\n * @return Deduped array of all matching styles\n */\nexport function getPrefixStylesInSelection(\n  editorState: EditorState,\n  prefix: string\n): string[] {\n  const selection = editorState.getSelection();\n  const styleSets = getAllStyleSetsInSelection(editorState);\n  if (selection.isCollapsed() || styleSets.length === 0) {\n    return [\n      getPrefixStyleForCharacter(editorState.getCurrentInlineStyle(), prefix),\n    ];\n  }\n\n  const styles = new Set<string>();\n  styleSets.forEach((styleSet) =>\n    styles.add(getPrefixStyleForCharacter(styleSet, prefix))\n  );\n\n  return [...styles];\n}\n\nfunction applyContent(editorState: EditorState, contentState: ContentState) {\n  return EditorState.push(editorState, contentState, 'change-inline-style');\n}\n\n/**\n * Toggle prefix style in selection. This is a pretty complex function and\n * it's probably easiest to understand how it works by following the inline\n * comments and reading through the corresponding exhaustive unit tests.\n *\n * @param editorState  Current editor state\n * @param prefix  Style (prefix) to remove from state and potentially\n * replace with different style\n * @param shouldSetStyle  Optional function to get if new style\n * should be added or not\n * @param getStyleToSet  Optional function to get what new style\n * should be added\n * @return New editor state\n */\nexport function togglePrefixStyle(\n  editorState: EditorState,\n  prefix: string,\n  shouldSetStyle: SetStyleCallback | null = null,\n  getStyleToSet: StyleGetter | null = null\n): EditorState {\n  if (editorState.getSelection().isCollapsed()) {\n    // A different set of rules apply here\n    // First find all styles that apply at cursor - we'll reapply those as override\n    // with modifications at the end\n    let inlineStyles = editorState.getCurrentInlineStyle();\n\n    // See if there's a matching style for our prefix\n    const foundMatch = getPrefixStyleForCharacter(inlineStyles, prefix);\n\n    // Then remove potentially found style from list\n    if (foundMatch !== NONE) {\n      inlineStyles = inlineStyles.remove(foundMatch);\n    }\n\n    // Then figure out whether to apply new style or not\n    const willAddStyle = shouldSetStyle\n      ? shouldSetStyle([foundMatch])\n      : foundMatch === NONE;\n\n    // If so, add to list\n    if (willAddStyle) {\n      const styleToAdd = getStyleToSet ? getStyleToSet([foundMatch]) : prefix;\n      inlineStyles = inlineStyles.add(styleToAdd);\n    }\n\n    // Finally apply to style override\n    return EditorState.setInlineStyleOverride(editorState, inlineStyles);\n  }\n\n  const matchingStyles = getPrefixStylesInSelection(editorState, prefix);\n\n  // First remove all old styles matching prefix\n  // (except NONE, it's not actually a style)\n  const stylesToRemove = matchingStyles.filter((s) => s !== NONE);\n  const strippedContentState = stylesToRemove.reduce(\n    (contentState, styleToRemove) =>\n      Modifier.removeInlineStyle(\n        contentState,\n        editorState.getSelection(),\n        styleToRemove\n      ),\n    editorState.getCurrentContent()\n  );\n\n  // Should we add a style to everything now?\n  // If no function is given, we simply add the style if any\n  // character did not have a match (NONE is in the list)\n  const willSetStyle = shouldSetStyle\n    ? shouldSetStyle(matchingStyles)\n    : matchingStyles.includes(NONE);\n\n  if (!willSetStyle) {\n    // we're done!\n    return applyContent(editorState, strippedContentState);\n  }\n\n  // Add style to entire selection\n  // If no function is given, we simply add the prefix as a style\n  const styleToSet = getStyleToSet ? getStyleToSet(matchingStyles) : prefix;\n  const newContentState = Modifier.applyInlineStyle(\n    strippedContentState,\n    editorState.getSelection(),\n    styleToSet\n  );\n\n  return applyContent(editorState, newContentState);\n}\n"
  },
  {
    "path": "packages/rich-text/src/test/getFontVariants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFontVariants from '../getFontVariants';\n\ndescribe('getFontVariants', () => {\n  it('should produce correct variants', () => {\n    const htmlContent =\n      '<span style=\"font-weight: 700\">F</span>ill in some text';\n    const expected = [\n      [0, 700],\n      [0, 400],\n    ];\n    const actual = getFontVariants(htmlContent);\n\n    expect(actual).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/test/getPastedBlocks.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { EditorState, ContentState, type BlockMap } from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport getPastedBlocks from '../getPastedBlocks';\nimport customExport from '../customExport';\n\ndescribe('getPastedBlocks', () => {\n  function blockMapToHTML(blockMap: BlockMap) {\n    const blockArray = blockMap.toArray();\n    const contentState = ContentState.createFromBlockArray(blockArray);\n    const editorState = EditorState.createWithContent(contentState);\n    return customExport(editorState);\n  }\n\n  it('should convert various types of bold content correctly', () => {\n    const blockMap = getPastedBlocks(\n      [\n        '<strong>This</strong>',\n        '<b>is</b>',\n        '<span style=\"font-weight: 800\">also</span>',\n        '<span style=\"font-weight: bolder\">bold</span>',\n      ].join(' ')\n    );\n    const expected = [\n      '<span style=\"font-weight: 700\">This</span>',\n      '<span style=\"font-weight: 700\">is</span>',\n      '<span style=\"font-weight: 700\">also</span>',\n      '<span style=\"font-weight: 700\">bold</span>',\n    ].join(' ');\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n\n  it('should convert italic and underline correctly', () => {\n    const blockMap = getPastedBlocks(\n      ['<u>Underline</u>', '<em>Italic</em>', '<i>Also italic</i>'].join(' ')\n    );\n    const expected = [\n      '<span style=\"text-decoration: underline\">Underline</span>',\n      '<span style=\"font-style: italic\">Italic</span>',\n      '<span style=\"font-style: italic\">Also italic</span>',\n    ].join(' ');\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n\n  it('should convert nested types', () => {\n    const blockMap = getPastedBlocks('<em>Mi<b>xed</b></em>');\n    const expected1 =\n      '<span style=\"font-style: italic\">Mi</span><span style=\"font-weight: 700; font-style: italic\">xed</span>';\n    const expected2 =\n      '<span style=\"font-style: italic\">Mi</span><span style=\"font-style: italic; font-weight: 700\">xed</span>';\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toBeOneOf([expected1, expected2]);\n  });\n\n  it('should ignore various irrelevant inline styles and attributes', () => {\n    const blockMap = getPastedBlocks(\n      [\n        '<code>Ignore</code>',\n        '<ins>Ignore</ins>',\n        '<sup>Ignore</sup>',\n        '<date>Ignore</date>',\n        '<label>Ignore</label>',\n        '<button>Ignore</button>',\n        '<svg><text>Ignore</text></svg>',\n        '<a href=\"http://ignore-me.example\">Ignore</a>',\n        // The following 4 would normally be considered block level, but are inlined\n        // in the draftjs parser, so that's how it is.\n        '<footer>Ignore</footer>',\n        '<aside>Ignore</aside>',\n        '<chapter>Ignore</chapter>',\n        '<main>Ignore</main>',\n      ].join(' ')\n    );\n    // Note they're joined by a space, as they're all inlined\n    const expected = Array(12).fill('Ignore').join(' ');\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n\n  it('should ignore various irrelevant block level styles and attributes', () => {\n    const blockMap = getPastedBlocks(\n      [\n        '<h1>Ignore</h1>',\n        '<h5 class=\"ignore-me\">Ignore</h5>',\n        '<pre>Ignore</pre>',\n        '<p>Ignore</p>',\n        '<nav>Ignore</nav>',\n      ].join('\\n')\n    );\n    // Note they're joined by a newline, as they're treated as separate paragraphs\n    const expected = Array(5).fill('Ignore').join('\\n');\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n\n  it('should remove irrelevant elements completely', () => {\n    const blockMap = getPastedBlocks(\n      [\n        'Some actual content',\n        '<input value=\"hello\" />',\n        '<hr />',\n        '<br />',\n        '<img src=\"\" alt=\"image\" />',\n      ].join('\\n')\n    );\n    const expected = 'Some actual content';\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n\n  it('should prefix list items correctly', () => {\n    const blockMap = getPastedBlocks(\n      [\n        '<ol>',\n        '<li>Ordered 1</li>',\n        '<li>Ordered 2</li>',\n        '</ol>',\n        '<ul>',\n        '<li>Unordered 1</li>',\n        '<li>Unordered 2</li>',\n        '</ul>',\n        '<ol>',\n        '<li>Extra ordered</li>',\n        '</ol>',\n      ].join('\\n')\n    );\n    const expected = [\n      '1. Ordered 1',\n      '2. Ordered 2',\n      '– Unordered 1',\n      '– Unordered 2',\n      '1. Extra ordered',\n    ].join('\\n');\n    const actual = blockMapToHTML(blockMap);\n\n    expect(actual).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/test/getTextColors.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getTextColors from '../getTextColors';\n\ndescribe('getTextColors', () => {\n  it('should return a list of text colors', () => {\n    const htmlContent =\n      'Fill in <span style=\"color: #eb0404\">some</span> <span style=\"color: #026111\">text</span>';\n    const expected = ['#000000', '#eb0404', '#026111'];\n\n    const actual = getTextColors(htmlContent);\n\n    expect(actual).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/rich-text/src/test/styleManipulation.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  convertFromRaw,\n  EditorState,\n  type RawDraftContentState,\n  SelectionState,\n} from 'draft-js';\n\n/**\n * Internal dependencies\n */\nimport type { OrderedSet } from 'immutable';\nimport {\n  getPrefixStyleForCharacter,\n  getPrefixStylesInSelection,\n  togglePrefixStyle,\n} from '../styleManipulation';\n\nexpect.extend({\n  toHaveStyleAtCursor(received: EditorState, style: string) {\n    const styles = received.getCurrentInlineStyle().toArray();\n    const stylesList = styles.join(', ');\n    const pass = styles.includes(style);\n    if (pass) {\n      return {\n        message: () => `expected ${stylesList} to not include ${style}`,\n        pass: true,\n      };\n    } else {\n      return {\n        message: () => `expected ${stylesList} to include ${style}`,\n        pass: false,\n      };\n    }\n  },\n  toHaveStyleInSelection(\n    received: EditorState,\n    style: string,\n    stylePrefix: string | null = null\n  ) {\n    stylePrefix = stylePrefix ?? style;\n    const styles = getPrefixStylesInSelection(received, stylePrefix);\n    const stylesList = styles.join(', ');\n    const pass = styles.includes(style);\n    if (pass) {\n      return {\n        message: () =>\n          `expected selection ${stylesList} to not include ${style}`,\n        pass: true,\n      };\n    } else {\n      return {\n        message: () => `expected selection ${stylesList} to include ${style}`,\n        pass: false,\n      };\n    }\n  },\n  toHaveStyleInEntireSelection(\n    received: EditorState,\n    style: string,\n    stylePrefix: string | null = null\n  ) {\n    stylePrefix = stylePrefix ?? style;\n    const styles = getPrefixStylesInSelection(received, stylePrefix);\n    const stylesList = styles.join(', ');\n    const pass = styles.includes(style) && styles.length === 1;\n    if (pass) {\n      return {\n        message: () =>\n          `expected selection ${stylesList} to not only include ${style}`,\n        pass: true,\n      };\n    } else {\n      return {\n        message: () =>\n          `expected selection ${stylesList} to only include ${style}`,\n        pass: false,\n      };\n    }\n  },\n});\n\ndescribe('getPrefixStyleForCharacter', () => {\n  it('should return a direct match', () => {\n    const match = getPrefixStyleForCharacter(\n      { toArray: () => ['ALPHA', 'BRAVO', 'CHARLIE'] } as OrderedSet<string>,\n      'BRAVO'\n    );\n    expect(match).toBe('BRAVO');\n  });\n\n  it('should return a prefix match', () => {\n    const match = getPrefixStyleForCharacter(\n      {\n        toArray: () => ['ALPHA-1', 'BRAVO-2', 'CHARLIE-3'],\n      } as OrderedSet<string>,\n      'BRAVO'\n    );\n    expect(match).toBe('BRAVO-2');\n  });\n\n  it('should return first match if multiple', () => {\n    const match = getPrefixStyleForCharacter(\n      {\n        toArray: () => ['ALPHA-1', 'BRAVO-2', 'BRAVO-3'],\n      } as OrderedSet<string>,\n      'BRAVO'\n    );\n    expect(match).toBe('BRAVO-2');\n  });\n\n  it('should return NONE if no match', () => {\n    const match = getPrefixStyleForCharacter(\n      {\n        toArray: () => ['ALPHA-1', 'BRAVO-2', 'CHARLIE-3'],\n      } as OrderedSet<string>,\n      'DELTA'\n    );\n    expect(match).toBe('NONE');\n  });\n});\n\ndescribe('getPrefixStylesInSelection', () => {\n  it('should return all different matched styles for non-collapsed selection', () => {\n    // Let's select \"World\"\n    const editorState = getEditorState(6, 11);\n    const matches = getPrefixStylesInSelection(editorState, 'CUSTOM-WEIGHT');\n    expect(matches).toIncludeSameMembers([\n      'CUSTOM-WEIGHT-700',\n      'CUSTOM-WEIGHT-900',\n    ]);\n  });\n\n  it('should include NONE if at least one character did not match for non-collapsed selection', () => {\n    // Let's select \"Hello World\"\n    const editorState = getEditorState(0, 11);\n    const matches = getPrefixStylesInSelection(editorState, 'CUSTOM-WEIGHT');\n    expect(matches).toIncludeSameMembers([\n      'NONE',\n      'CUSTOM-WEIGHT-700',\n      'CUSTOM-WEIGHT-900',\n    ]);\n  });\n\n  it('should return matched style for collapsed selection', () => {\n    // Let's place selection where the * is: \"Hello W*orld\"\n    const editorState = getEditorState(7);\n    const matches = getPrefixStylesInSelection(editorState, 'CUSTOM-WEIGHT');\n    expect(matches).toIncludeSameMembers(['CUSTOM-WEIGHT-700']);\n  });\n\n  it('should return NONE if no match for collapsed selection', () => {\n    // Let's place selection where the * is: \"H*ello World\"\n    const editorState = getEditorState(1);\n    const matches = getPrefixStylesInSelection(editorState, 'CUSTOM-WEIGHT');\n    expect(matches).toIncludeSameMembers(['NONE']);\n  });\n});\n\ndescribe('togglePrefixStyle', () => {\n  describe('on collapsed selection', () => {\n    it('should toggle simple style off if selection is not inside matching style', () => {\n      // Let's place selection where the * is: \"H*ello World\"\n      // So, inside italic style\n      const editorState = getEditorState(1);\n\n      // Verify that it doesn't include italic:\n      expect(editorState).not.toHaveStyleAtCursor('CUSTOM-ITALIC');\n\n      // Now toggle italic\n      const newState = togglePrefixStyle(editorState, 'CUSTOM-ITALIC');\n\n      // And verify that it now has italic\n      expect(newState).toHaveStyleAtCursor('CUSTOM-ITALIC');\n    });\n\n    it('should toggle simple style off if selection is inside matching style', () => {\n      // Let's place selection where the * is: \"Hel*lo World\"\n      // So, inside italic style\n      const editorState = getEditorState(3);\n\n      // Verify that it includes italic:\n      expect(editorState).toHaveStyleAtCursor('CUSTOM-ITALIC');\n\n      // Now toggle italic\n      const newState = togglePrefixStyle(editorState, 'CUSTOM-ITALIC');\n\n      //And verify that it doesn't have italic anymore\n      expect(newState).not.toHaveStyleAtCursor('CUSTOM-ITALIC');\n    });\n\n    it('should do nothing when toggling simple style *on* in selection *with style*', () => {\n      // Let's place selection where the * is: \"Hel*lo World\"\n      // So, inside italic style\n      const editorState = getEditorState(3);\n\n      // Verify that it already includes italic:\n      expect(editorState).toHaveStyleAtCursor('CUSTOM-ITALIC');\n\n      // Now toggle italic\n      const newState = togglePrefixStyle(\n        editorState,\n        'CUSTOM-ITALIC',\n        () => true\n      );\n\n      // And verify that it still includes italic\n      expect(newState).toHaveStyleAtCursor('CUSTOM-ITALIC');\n    });\n\n    it('should do nothing when toggling simple style *off* in selection *without style*', () => {\n      // Let's place selection where the * is: \"H*ello World\"\n      // So, inside italic style\n      const editorState = getEditorState(1);\n\n      // Verify that it doesn't include italic:\n      expect(editorState).not.toHaveStyleAtCursor('CUSTOM-ITALIC');\n\n      // Now toggle italic\n      const newState = togglePrefixStyle(\n        editorState,\n        'CUSTOM-ITALIC',\n        () => false\n      );\n\n      // And verify that it still doesn't have italic\n      expect(newState).not.toHaveStyleAtCursor('CUSTOM-ITALIC');\n    });\n\n    it('should toggle complex style based on callbacks', () => {\n      // Let's place selection where the * is: \"Hel*lo World\"\n      // So, inside bold style\n      const editorState = getEditorState(3);\n\n      // Verify that it has custom weight 700:\n      expect(editorState).toHaveStyleAtCursor('CUSTOM-WEIGHT-700');\n\n      // Now toggle according to callbacks:\n      const shouldSetStyle = jest.fn().mockImplementation(() => true);\n      const styleToSet = jest\n        .fn()\n        .mockImplementation(() => 'CUSTOM-WEIGHT-900');\n      const newState = togglePrefixStyle(\n        editorState,\n        'CUSTOM-WEIGHT',\n        shouldSetStyle,\n        styleToSet\n      );\n\n      // And verify that it now has given style\n      expect(newState).toHaveStyleAtCursor('CUSTOM-WEIGHT-900');\n\n      // And verify given callbacks have been invoked correctly\n      expect(shouldSetStyle).toHaveBeenCalledWith(['CUSTOM-WEIGHT-700']);\n      expect(styleToSet).toHaveBeenCalledWith(['CUSTOM-WEIGHT-700']);\n    });\n  });\n\n  describe('on non-collapsed selection', () => {\n    it('should toggle simple style off if selection contains style throughout', () => {\n      // Let's place selection here: \"Hel[lo] World\"\n      // So, everything is underlined\n      const editorState = getEditorState(3, 5);\n\n      // Verify that it is underline throughout:\n      expect(editorState).toHaveStyleInEntireSelection('CUSTOM-UNDERLINE');\n\n      // Now toggle underline\n      const newState = togglePrefixStyle(editorState, 'CUSTOM-UNDERLINE');\n\n      // And verify that it doesn't have underline anywhere\n      expect(newState).not.toHaveStyleInSelection('CUSTOM-UNDERLINE');\n    });\n\n    it('should toggle simple style on if selection contains style somewhere but not everywhere', () => {\n      // Let's place selection here: \"H[ello] World\"\n      // So, some is underlined, some not\n      const editorState = getEditorState(1, 5);\n\n      // Verify that it is underline somewhere, but not everywhere:\n      expect(editorState).not.toHaveStyleInEntireSelection('CUSTOM-UNDERLINE');\n      expect(editorState).toHaveStyleInSelection('CUSTOM-UNDERLINE');\n\n      // Now toggle underline\n      const newState = togglePrefixStyle(editorState, 'CUSTOM-UNDERLINE');\n\n      // And verify that now has underline throughout\n      expect(newState).toHaveStyleInEntireSelection('CUSTOM-UNDERLINE');\n    });\n\n    it('should toggle simple style on if selection does not contain style at all', () => {\n      // Let's place selection here: \"[He]llo World\"\n      // So, no underline at all\n      const editorState = getEditorState(0, 2);\n\n      // Verify that it is underline nowhere:\n      expect(editorState).not.toHaveStyleInSelection('CUSTOM-UNDERLINE');\n\n      // Now toggle underline\n      const newState = togglePrefixStyle(editorState, 'CUSTOM-UNDERLINE');\n\n      // And verify that now has underline throughout\n      expect(newState).toHaveStyleInEntireSelection('CUSTOM-UNDERLINE');\n    });\n\n    it('should toggle complex style according to callbacks', () => {\n      // Let's place selection here: \"Hell[o Worl]d\"\n      // So, some regular weight, some bold, some black\n      const editorState = getEditorState(4, 10);\n\n      // Verify that it is both none, bold and black somewhere:\n      expect(editorState).toHaveStyleInSelection('NONE', 'CUSTOM-WEIGHT');\n      expect(editorState).toHaveStyleInSelection(\n        'CUSTOM-WEIGHT-700',\n        'CUSTOM-WEIGHT'\n      );\n      expect(editorState).toHaveStyleInSelection(\n        'CUSTOM-WEIGHT-900',\n        'CUSTOM-WEIGHT'\n      );\n\n      // Now toggle font weight according to callbacks\n      const shouldSetStyle = jest.fn().mockImplementation(() => true);\n      const styleToSet = jest\n        .fn()\n        .mockImplementation(() => 'CUSTOM-WEIGHT-300');\n      const newState = togglePrefixStyle(\n        editorState,\n        'CUSTOM-WEIGHT',\n        shouldSetStyle,\n        styleToSet\n      );\n\n      // And verify that now has new font weight throughout\n      expect(newState).toHaveStyleInEntireSelection(\n        'CUSTOM-WEIGHT-300',\n        'CUSTOM-WEIGHT'\n      );\n\n      // And verify given callbacks have been invoked correctly\n      expect(shouldSetStyle).toHaveBeenCalledWith([\n        'NONE',\n        'CUSTOM-WEIGHT-700',\n        'CUSTOM-WEIGHT-900',\n      ]);\n      expect(styleToSet).toHaveBeenCalledWith([\n        'NONE',\n        'CUSTOM-WEIGHT-700',\n        'CUSTOM-WEIGHT-900',\n      ]);\n    });\n  });\n});\n\n/* Editor state has this content:\n *   Hello World\n *\n * With 7 different sections with styles as follows:\n *\n * 1. \"He\"  is unstyled\n * 2. \"l\"   is bold (700) and italic\n * 3. \"l\"   is bold (700), italic and underline\n * 4. \"o\"   is underline\n * 5. \" \"   is unstyled\n * 6. \"Wo\"  is bold (700)\n * 7. \"rld\" is black (900)\n */\nfunction getEditorState(\n  selectionStart: number,\n  selectionEnd: number | null = null\n) {\n  const raw: RawDraftContentState = {\n    blocks: [\n      {\n        key: '65t0d',\n        text: 'Hello world',\n        type: 'unstyled',\n        depth: 0,\n        inlineStyleRanges: [\n          { offset: 2, length: 2, style: 'CUSTOM-WEIGHT-700' },\n          { offset: 2, length: 2, style: 'CUSTOM-ITALIC' },\n          { offset: 3, length: 2, style: 'CUSTOM-UNDERLINE' },\n          { offset: 6, length: 2, style: 'CUSTOM-WEIGHT-700' },\n          { offset: 8, length: 3, style: 'CUSTOM-WEIGHT-900' },\n        ],\n        entityRanges: [],\n        data: {},\n      },\n    ],\n    entityMap: {},\n  };\n  const contentState = convertFromRaw(raw);\n  const unselectedState = EditorState.createWithContent(contentState);\n  const selection = new SelectionState({\n    anchorKey: raw.blocks[0].key,\n    anchorOffset: selectionStart,\n    focusKey: raw.blocks[0].key,\n    focusOffset: selectionEnd ?? selectionStart,\n  });\n  return EditorState.forceSelection(unselectedState, selection);\n}\n"
  },
  {
    "path": "packages/rich-text/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { EditorState, DraftInlineStyle } from 'draft-js';\nimport type { CSSProperties } from 'react';\n\nexport type AllowedSetterArgs = undefined | boolean | Pattern | number;\n\nexport type StyleSetter = (\n  state: EditorState | null,\n  arg: AllowedSetterArgs\n) => EditorState;\n\nexport type SetStyleCallback = (styles?: string[]) => unknown;\nexport type StyleGetter = (styles?: string[]) => string;\n\nexport interface SelectionInfo {\n  isBold: boolean;\n  isItalic: boolean;\n  isUnderline: boolean;\n  isUppercase: boolean;\n}\n\n// Partial to make the props optional.\nexport interface StateInfo extends Partial<SelectionInfo> {\n  color?: Pattern;\n  letterSpacing?: number;\n  fontWeight?: number;\n}\n\nexport interface State {\n  state: {\n    editorState: EditorState | null;\n    hasCurrentEditor: boolean;\n    selectionInfo: StateInfo | undefined;\n  };\n  actions: {\n    setStateFromContent: (content: string) => void;\n    updateEditorState: (state: EditorState) => void;\n    getHandleKeyCommand: () => (\n      command: string,\n      currentEditorState: EditorState\n    ) => 'handled' | 'not-handled';\n    handlePastedText: (\n      text: string,\n      html: string,\n      state: EditorState\n    ) => 'handled' | 'not-handled';\n    clearState: () => void;\n    selectionActions: Record<string, StyleSetter>;\n    getContentFromState: (editorState: EditorState) => string | null;\n  };\n}\n\n// @todo Figure out a better type for setters.\ntype AllowedGetterArgs = '((MULTIPLE))' | boolean | Pattern | number;\ntype Getter = (state: EditorState) => AllowedGetterArgs;\nexport interface Formatter {\n  elementToStyle: (element: HTMLElement) => string | null;\n  stylesToCSS: (styles: DraftInlineStyle) => CSSProperties | null;\n  getters: Record<string, Getter>;\n  autoFocus: boolean;\n  setters: Record<string, unknown>;\n}\n\nexport interface EditingState {\n  hasEditMenu?: boolean;\n  showOverflow?: boolean;\n  selectAll?: boolean;\n  offset?: number;\n}\n"
  },
  {
    "path": "packages/rich-text/src/typings/jest.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare global {\n  namespace jest {\n    interface Matchers<R> {\n      toHaveStyleAtCursor(style: string): R;\n      toHaveStyleInSelection(style: string, stylePrefix?: string | null): R;\n      toHaveStyleInEntireSelection(\n        style: string,\n        stylePrefix?: string | null\n      ): R;\n    }\n  }\n}\n\nexport type {};\n"
  },
  {
    "path": "packages/rich-text/src/useHandlePastedText.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { EditorState, Modifier } from 'draft-js';\nimport type { DraftHandleValue, EditorChangeType } from 'draft-js';\nimport { useCallback } from '@googleforcreators/react';\nimport type { Dispatch, SetStateAction } from 'react';\n\n/**\n * Internal dependencies\n */\nimport getPastedBlocks from './getPastedBlocks';\nimport { COLOR } from './customConstants';\nimport { getPrefixStylesInSelection } from './styleManipulation';\n\n/*\n * This hook returns a function to handle text pasted while in edit-mode.\n *\n * Compare this with `usePasteTextContent` that handles generally pasting\n * text without being in text edit-mode anywhere.\n */\nfunction useHandlePastedText(\n  setEditorState: Dispatch<SetStateAction<EditorState | null>>\n) {\n  return useCallback(\n    (\n      text: string,\n      html: string | undefined,\n      state: EditorState\n    ): DraftHandleValue => {\n      const content = state.getCurrentContent();\n      const selection = state.getSelection();\n      let newState, stateChange: EditorChangeType;\n      if (html) {\n        // Get the styles of the current selection context (collapsed or not),\n        // that should be applied to the entirety of the pasted HTML.\n        // In this instance, we only care about the text color - all other existing\n        // styles will be ignored and overwritten by pasted content.\n        let existingStyles = getPrefixStylesInSelection(state, COLOR);\n        if (existingStyles.length > 1) {\n          // If selection has multiple colors, use only the first one\n          existingStyles = existingStyles.slice(0, 1);\n        }\n        const blocks = getPastedBlocks(html, existingStyles);\n        newState = Modifier.replaceWithFragment(content, selection, blocks);\n        stateChange = 'insert-fragment';\n      } else {\n        const style = state.getCurrentInlineStyle();\n        newState = Modifier.replaceText(content, selection, text, style);\n        stateChange = 'insert-characters';\n      }\n      const result = EditorState.push(state, newState, stateChange);\n      setEditorState(result);\n      return 'handled';\n    },\n    [setEditorState]\n  );\n}\n\nexport default useHandlePastedText;\n"
  },
  {
    "path": "packages/rich-text/src/usePasteTextContent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { EditorState, ContentState } from 'draft-js';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport getPastedBlocks from './getPastedBlocks';\nimport customExport from './customExport';\n\n/*\n * This hook returns a function to handle text pasted with no specific focus.\n *\n * Compare this with `useHandlePastedText` that handles pasting text while being\n * in text edit-mode.\n */\nfunction usePasteTextContent(insertElement: (content: string) => void) {\n  return useCallback(\n    (html: string) => {\n      const blockMap = getPastedBlocks(html);\n      const blockArray = blockMap.toArray();\n      const contentState = ContentState.createFromBlockArray(blockArray);\n      const editorState = EditorState.createWithContent(contentState);\n      const validContent = customExport(editorState);\n      if (!validContent) {\n        return false;\n      }\n      insertElement(validContent);\n      return true;\n    },\n    [insertElement]\n  );\n}\n\nexport default usePasteTextContent;\n"
  },
  {
    "path": "packages/rich-text/src/useRichText.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { State } from './types';\n\nfunction useRichText(): State;\nfunction useRichText<T>(selector: (state: State) => T): T;\nfunction useRichText<T>(selector: (state: State) => T | State = identity) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useRichText;\n"
  },
  {
    "path": "packages/rich-text/src/useSelectionManipulation.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useEffect,\n  useMemo,\n} from '@googleforcreators/react';\nimport { EditorState } from 'draft-js';\nimport type { SelectionState } from 'draft-js';\nimport type { Dispatch, SetStateAction } from 'react';\n\n/**\n * Internal dependencies\n */\nimport formatters from './formatters';\nimport type { AllowedSetterArgs, StyleSetter } from './types';\n\nfunction useSelectionManipulation(\n  editorState: EditorState | null,\n  setEditorState: Dispatch<SetStateAction<EditorState | null>>\n): Record<string, StyleSetter> {\n  const lastKnownStateRef = useRef<EditorState | null>(null);\n  const lastKnownSelectionRef = useRef<SelectionState | null>(null);\n  useEffect(() => {\n    lastKnownStateRef.current = editorState;\n    if (!editorState) {\n      lastKnownSelectionRef.current = null;\n    } else if (editorState.getSelection().getHasFocus()) {\n      lastKnownSelectionRef.current = editorState.getSelection();\n    }\n  }, [editorState]);\n\n  const updateWhileUnfocused = useCallback(\n    (\n      updater: (state: EditorState | null) => EditorState,\n      shouldForceFocus = true\n    ) => {\n      const oldState = lastKnownStateRef.current;\n      const selection = lastKnownSelectionRef.current;\n      const workingState =\n        shouldForceFocus && oldState && selection\n          ? EditorState.forceSelection(oldState, selection)\n          : oldState;\n      const newState = updater(workingState);\n      setEditorState(newState);\n    },\n    [setEditorState]\n  );\n\n  const getSetterName = useCallback(\n    (setterName: string) => `${setterName}InSelection`,\n    []\n  );\n\n  const getSetterCallback = useCallback(\n    (setter: StyleSetter, autoFocus) =>\n      (...args: [AllowedSetterArgs]) =>\n        updateWhileUnfocused((state) => setter(state, ...args), autoFocus),\n    [updateWhileUnfocused]\n  );\n\n  const selectionFormatters = useMemo(\n    () =>\n      formatters.reduce(\n        (aggr, { setters, autoFocus }) => ({\n          ...aggr,\n          ...Object.fromEntries(\n            Object.entries(setters).map(([key, setter]) => [\n              getSetterName(key),\n              getSetterCallback(setter as StyleSetter, autoFocus),\n            ])\n          ),\n        }),\n        {}\n      ),\n    [getSetterName, getSetterCallback]\n  );\n\n  return selectionFormatters;\n}\n\nexport default useSelectionManipulation;\n"
  },
  {
    "path": "packages/rich-text/src/util.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { EditorState, SelectionState } from 'draft-js';\nimport type { ContentState } from 'draft-js';\nimport { filterEditorState } from 'draftjs-filters';\n\n/**\n * Internal dependencies\n */\nimport weightFormatter from './formatters/weight';\nimport italicFormatter from './formatters/italic';\nimport underlineFormatter from './formatters/underline';\nimport uppercaseFormatter from './formatters/uppercase';\n\nexport function getFilteredState(\n  editorState: EditorState,\n  oldEditorState: EditorState\n) {\n  const shouldFilterPaste =\n    oldEditorState.getCurrentContent() !== editorState.getCurrentContent() &&\n    editorState.getLastChangeType() === 'insert-fragment';\n\n  if (!shouldFilterPaste) {\n    return editorState;\n  }\n\n  return filterEditorState(\n    {\n      blocks: [],\n      styles: ['BOLD', 'ITALIC', 'UNDERLINE'],\n      entities: [],\n      maxNesting: 1,\n      whitespacedCharacters: [],\n    },\n    editorState\n  );\n}\n\nfunction getStateFromCommand(command: string, oldEditorState: EditorState) {\n  switch (command) {\n    case 'bold':\n      return weightFormatter.setters.toggleBold(oldEditorState);\n\n    case 'italic':\n      return italicFormatter.setters.toggleItalic(oldEditorState);\n\n    case 'underline':\n      return underlineFormatter.setters.toggleUnderline(oldEditorState);\n\n    case 'uppercase':\n      return uppercaseFormatter.setters.toggleUppercase(oldEditorState);\n\n    case 'selectall':\n      return EditorState.forceSelection(\n        oldEditorState,\n        getSelectionForAll(oldEditorState.getCurrentContent())\n      );\n\n    default:\n      return null;\n  }\n}\n\nexport const getHandleKeyCommandFromState =\n  (setEditorState: (state: EditorState) => void) =>\n  (command: string, currentEditorState: EditorState) => {\n    const newEditorState = getStateFromCommand(command, currentEditorState);\n    if (newEditorState) {\n      setEditorState(newEditorState);\n      return 'handled';\n    }\n    return 'not-handled';\n  };\n\nexport function getSelectionForAll(content: ContentState) {\n  const firstBlock = content.getFirstBlock();\n  const lastBlock = content.getLastBlock();\n  return new SelectionState({\n    anchorKey: firstBlock.getKey(),\n    anchorOffset: 0,\n    focusKey: lastBlock.getKey(),\n    focusOffset: lastBlock.getLength(),\n  });\n}\n\nexport function getSelectionForOffset(content: ContentState, offset: number) {\n  const blocks = content.getBlocksAsArray();\n  let countdown = offset;\n  for (let i = 0; i < blocks.length && countdown >= 0; i++) {\n    const block = blocks[i];\n    const length = block.getLength();\n    if (countdown <= length) {\n      const selection = new SelectionState({\n        anchorKey: block.getKey(),\n        anchorOffset: countdown,\n        focusKey: block.getKey(),\n        focusOffset: countdown,\n      });\n      return selection;\n    }\n    // +1 char for the delimiter.\n    countdown -= length + 1;\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/rich-text/src/utils/getCaretCharacterOffsetWithin.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * This function finds the character offset within a certain element.\n *\n * For instance, given the following node with `_` marking the current selection start offset:\n *\n * ```\n * <p>Corgies are the <em>b_est</em>!</p>\n * ```\n *\n * This function would return 17 (`'Corgies are the b'.length`).\n *\n * If optional coordinates are given, the point under the coordinates will be used,\n * otherwise the current on-page selection will be used.\n *\n * This function includes some cross-browser optimization for older browsers even\n * though they aren't really supported by the editor at large (IE).\n *\n * @param element    DOM node to find current selection within.\n * @param clientX  Optional x coordinate of click.\n * @param clientY  Optional y coordinate of click.\n * @return Current selection start offset as seen in `element` or 0 if not found.\n */\n\ninterface CaretPosition {\n  readonly offset: number;\n  readonly offsetNode: Node;\n  getClientRect(): DOMRect | null;\n}\n\ninterface SelectionDocument extends Document {\n  caretPositionFromPoint: (\n    x: number,\n    y: number,\n    options?: CaretPositionFromPointOptions\n  ) => CaretPosition | null;\n}\n\n// Extend for wider browser support.\ninterface SelectionElement extends Node {\n  document?: SelectionDocument;\n}\n\nfunction getCaretCharacterOffsetWithin(\n  element: SelectionElement,\n  clientX: number,\n  clientY: number\n): number {\n  const doc = (element.ownerDocument || element.document) as SelectionDocument;\n  const win = doc?.defaultView;\n  if (typeof win?.getSelection !== 'undefined') {\n    let range;\n    if (clientX && clientY) {\n      if (doc.caretPositionFromPoint) {\n        const caretPosition = doc.caretPositionFromPoint(clientX, clientY);\n        // Create a range from the caret position.\n        if (caretPosition) {\n          range = document.createRange();\n          range.setStart(caretPosition.offsetNode, caretPosition.offset);\n        }\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- caretRangeFromPoint does not exist in FF, even though TS claims it always exists.\n        // @ts-ignore\n      } else if (doc.caretRangeFromPoint) {\n        // Change 'user-select' temporarily to make getting the correct range work for Safari.\n        // See https://github.com/googleforcreators/web-stories-wp/issues/7745.\n        const elementsToAdjust =\n          document.querySelectorAll<HTMLElement>('[data-fix-caret]');\n        for (const elementToAdjust of elementsToAdjust) {\n          elementToAdjust.style.webkitUserSelect = 'auto';\n        }\n        range = document.caretRangeFromPoint(clientX, clientY);\n        for (const elementToAdjust of elementsToAdjust) {\n          elementToAdjust.style.webkitUserSelect = 'none';\n        }\n      }\n    }\n    if (!range) {\n      const sel = win.getSelection();\n      if (sel && sel.rangeCount > 0) {\n        range = win.getSelection()?.getRangeAt(0);\n      }\n    }\n    if (range) {\n      const preCaretRange = range.cloneRange();\n      preCaretRange.selectNodeContents(element);\n      preCaretRange.setEnd(range.endContainer, range.endOffset);\n      // This is for ensuring that if the logic fails to get the correct offset, it won't cause unexpected behaviour.\n      if (\n        element.textContent &&\n        preCaretRange.toString().length <= element.textContent.length\n      ) {\n        return preCaretRange.toString().length;\n      }\n    }\n  }\n\n  return 0;\n}\n\nexport default getCaretCharacterOffsetWithin;\n"
  },
  {
    "path": "packages/rich-text/src/utils/getValidHTML.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst contentBuffer = document.createElement('template');\n\nexport default function getValidHTML(string: string) {\n  contentBuffer.innerHTML = string;\n  return contentBuffer.innerHTML;\n}\n"
  },
  {
    "path": "packages/rich-text/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../patterns\" }],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/stickers/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/stickers/README.md",
    "content": "# Stickers\n\nThis package contains The **SVGs** used in templates.\n\nSee [documentation](../../docs/external-template-creation.md) on how to add **SVGs**.\n"
  },
  {
    "path": "packages/stickers/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/stickers\",\n  \"description\": \"A large set of stickers to be used by a collection of Web Stories templates.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/stickers/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/stickers\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"prop-types\": \"^15.8.1\"\n  }\n}\n"
  },
  {
    "path": "packages/stickers/src/12-hours-in-barcelona/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as travelList } from './list';\nimport { default as yellowLocationPin } from './yellowLocationPin';\nimport { default as travelToolTip } from './tooltip';\n\nexport { travelList, yellowLocationPin, travelToolTip };\n"
  },
  {
    "path": "packages/stickers/src/12-hours-in-barcelona/list.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('List', 'sticker name', 'web-stories');\n\nconst List = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 30 38\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M3.51724 1C2.3841 1 1.46552 1.91859 1.46552 3.05172V34.9483C1.46552 36.0814 2.3841 37 3.51724 37H26.4828C27.6159 37 28.5345 36.0814 28.5345 34.9483V3.05172C28.5345 1.91859 27.6159 1 26.4828 1H3.51724ZM0.465515 3.05172C0.465515 1.3663 1.83182 0 3.51724 0H26.4828C28.1682 0 29.5345 1.3663 29.5345 3.05172V34.9483C29.5345 36.6337 28.1682 38 26.4828 38H3.51724C1.83182 38 0.465515 36.6337 0.465515 34.9483V3.05172ZM7.48276 13.8966C7.48276 13.6204 7.70661 13.3966 7.98276 13.3966H15.6379C15.9141 13.3966 16.1379 13.6204 16.1379 13.8966C16.1379 14.1727 15.9141 14.3966 15.6379 14.3966H7.98276C7.70661 14.3966 7.48276 14.1727 7.48276 13.8966ZM7.48276 19C7.48276 18.7239 7.70661 18.5 7.98276 18.5H22.0172C22.2934 18.5 22.5172 18.7239 22.5172 19C22.5172 19.2761 22.2934 19.5 22.0172 19.5H7.98276C7.70661 19.5 7.48276 19.2761 7.48276 19ZM7.48276 24.1034C7.48276 23.8273 7.70661 23.6034 7.98276 23.6034H22.0172C22.2934 23.6034 22.5172 23.8273 22.5172 24.1034C22.5172 24.3796 22.2934 24.6034 22.0172 24.6034H7.98276C7.70661 24.6034 7.48276 24.3796 7.48276 24.1034ZM7.48276 29.2069C7.48276 28.9308 7.70661 28.7069 7.98276 28.7069H22.0172C22.2934 28.7069 22.5172 28.9308 22.5172 29.2069C22.5172 29.483 22.2934 29.7069 22.0172 29.7069H7.98276C7.70661 29.7069 7.48276 29.483 7.48276 29.2069Z\"\n      fill=\"#FFC700\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 30 / 38,\n  svg: List,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/12-hours-in-barcelona/tooltip.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Tooltip', 'sticker name', 'web-stories');\n\nconst ToolTip = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    xmlns=\"http://www.w3.org/2000/svg\"\n    viewBox=\"0 0 80 33.6\"\n    fill=\"none\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M80,2v23c0,1.1-0.9,2-2,2H45.7l-5,6.2c-0.4,0.5-1.2,0.5-1.6,0l-5-6.2H2c-1.1,0-2-0.9-2-2V2c0-1.1,0.9-2,2-2h76 C79.1,0,80,0.9,80,2z\"\n      fill=\"#fff\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 80 / 33.6,\n  svg: ToolTip,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/12-hours-in-barcelona/yellowLocationPin.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Location Pin', 'sticker name', 'web-stories');\n\nconst YellowLocationPin = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 32 38\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M16.046 0.5C20.2759 0.5 23.8774 1.99493 26.8506 4.98485C29.8238 7.97476 31.3103 11.5875 31.3103 15.8232C31.3103 20.0589 29.8238 23.6717 26.8506 26.6616L16 37.5L5.1954 26.6616C2.19155 23.6717 0.689651 20.0589 0.689651 15.8232C0.689651 11.5875 2.19155 7.97476 5.1954 4.98485C8.19924 1.99493 11.8161 0.5 16.046 0.5ZM16 20.9154C17.3487 20.9154 18.4827 20.4482 19.4023 19.5139C20.3525 18.5484 20.8276 17.4038 20.8276 16.0802C20.8276 14.7565 20.3525 13.612 19.4023 12.6465C18.4521 11.681 17.318 11.1982 16 11.1982C14.7126 11.1982 13.5939 11.681 12.6437 12.6465C11.6935 13.612 11.2184 14.7565 11.2184 16.0802C11.2184 17.4038 11.6935 18.5484 12.6437 19.5139C13.5632 20.4482 14.682 20.9154 16 20.9154Z\"\n      fill=\"#FFC700\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 32 / 38,\n  svg: YellowLocationPin,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/alarmClock.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Alarm Clock', 'sticker name', 'web-stories');\n\nfunction AlarmClock({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 36 46\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18 39C24.6274 39 30 33.6274 30 27C30 20.3726 24.6274 15 18 15C11.3726 15 6 20.3726 6 27C6 33.6274 11.3726 39 18 39ZM18 41C25.732 41 32 34.732 32 27C32 19.268 25.732 13 18 13C10.268 13 4 19.268 4 27C4 34.732 10.268 41 18 41Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18 43C26.8366 43 34 35.8366 34 27C34 18.1634 26.8366 11 18 11C9.16344 11 2 18.1634 2 27C2 35.8366 9.16344 43 18 43ZM18 45C27.9411 45 36 36.9411 36 27C36 17.0589 27.9411 9 18 9C8.05887 9 0 17.0589 0 27C0 36.9411 8.05887 45 18 45Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.5 12C6.32843 12 7 11.3284 7 10.5C7 9.67157 6.32843 9 5.5 9C4.67157 9 4 9.67157 4 10.5C4 11.3284 4.67157 12 5.5 12ZM5.5 14C7.433 14 9 12.433 9 10.5C9 8.567 7.433 7 5.5 7C3.567 7 2 8.567 2 10.5C2 12.433 3.567 14 5.5 14Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30.5 12C31.3284 12 32 11.3284 32 10.5C32 9.67157 31.3284 9 30.5 9C29.6716 9 29 9.67157 29 10.5C29 11.3284 29.6716 12 30.5 12ZM30.5 14C32.433 14 34 12.433 34 10.5C34 8.567 32.433 7 30.5 7C28.567 7 27 8.567 27 10.5C27 12.433 28.567 14 30.5 14Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18 8C19.6569 8 21 6.65685 21 5C21 3.34315 19.6569 2 18 2C16.3431 2 15 3.34315 15 5C15 6.65685 16.3431 8 18 8ZM18 10C20.7614 10 23 7.76142 23 5C23 2.23858 20.7614 0 18 0C15.2386 0 13 2.23858 13 5C13 7.76142 15.2386 10 18 10Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.5 44C6.77614 44 7 43.7761 7 43.5C7 43.2239 6.77614 43 6.5 43C6.22386 43 6 43.2239 6 43.5C6 43.7761 6.22386 44 6.5 44ZM6.5 46C7.88071 46 9 44.8807 9 43.5C9 42.1193 7.88071 41 6.5 41C5.11929 41 4 42.1193 4 43.5C4 44.8807 5.11929 46 6.5 46Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M29.5 44C29.7761 44 30 43.7761 30 43.5C30 43.2239 29.7761 43 29.5 43C29.2239 43 29 43.2239 29 43.5C29 43.7761 29.2239 44 29.5 44ZM29.5 46C30.8807 46 32 44.8807 32 43.5C32 42.1193 30.8807 41 29.5 41C28.1193 41 27 42.1193 27 43.5C27 44.8807 28.1193 46 29.5 46Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18 29C18.5523 29 19 28.5523 19 28C19 27.4477 18.5523 27 18 27C17.4477 27 17 27.4477 17 28C17 28.5523 17.4477 29 18 29ZM18 31C19.6569 31 21 29.6569 21 28C21 26.3431 19.6569 25 18 25C16.3431 25 15 26.3431 15 28C15 29.6569 16.3431 31 18 31Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.6999 21.7858L16.9928 25.9929L15.593 27.4213L11.3001 23.2142L12.6999 21.7858Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 36 / 46,\n  svg: AlarmClock,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/brownRice.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Brown Rice', 'sticker name', 'web-stories');\n\nfunction BrownRice({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 46\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M22.1749 23.394C22.0866 23.4786 21.9909 23.5652 21.8885 23.6515C21.2136 24.2207 20.471 24.5937 19.8021 24.5937C18.8456 24.5937 18.2002 24.3466 17.8383 24.0821C17.4936 23.8301 17.4125 23.5824 17.4125 23.394C17.4125 23.2056 17.4936 22.9579 17.8383 22.7059C18.2002 22.4414 18.8456 22.1943 19.8021 22.1943C20.471 22.1943 21.2136 22.5673 21.8885 23.1365C21.9909 23.2228 22.0866 23.3094 22.1749 23.394ZM19.8021 26.1937C22.2374 26.1937 24.2116 23.6094 24.2116 23.394C24.2116 23.1786 22.2374 20.5943 19.8021 20.5943C17.3667 20.5943 15.8125 21.8478 15.8125 23.394C15.8125 24.9402 17.3667 26.1937 19.8021 26.1937Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M38.9733 12.1953C38.885 12.2799 38.7893 12.3665 38.687 12.4528C38.0121 13.022 37.2695 13.395 36.6005 13.395C35.6441 13.395 34.9986 13.1479 34.6368 12.8833C34.2921 12.6313 34.2109 12.3837 34.2109 12.1953C34.2109 12.0069 34.2921 11.7592 34.6368 11.5072C34.9986 11.2427 35.6441 10.9956 36.6005 10.9956C37.2695 10.9956 38.0121 11.3685 38.687 11.9377C38.7893 12.024 38.885 12.1107 38.9733 12.1953ZM36.6005 14.995C39.0358 14.995 41.0101 12.4106 41.0101 12.1953C41.0101 11.9799 39.0358 9.39556 36.6005 9.39556C34.1652 9.39556 32.6109 10.649 32.6109 12.1953C32.6109 13.7415 34.1652 14.995 36.6005 14.995Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M44.4247 27.0784C44.3833 27.1935 44.3362 27.3137 44.2831 27.4365C43.9324 28.2468 43.4337 28.9116 42.8348 29.2096C41.9786 29.6357 41.2906 29.702 40.8488 29.6264C40.4279 29.5543 40.2449 29.3687 40.161 29.2C40.0771 29.0314 40.0394 28.7735 40.2357 28.3943C40.4418 27.9963 40.9096 27.4875 41.7659 27.0614C42.3648 26.7634 43.1958 26.7665 44.0536 26.9754C44.1837 27.0071 44.308 27.042 44.4247 27.0784ZM43.5476 30.642C45.7279 29.5571 46.3441 26.3639 46.2482 26.1711C46.1522 25.9783 43.2334 24.544 41.0531 25.629C38.8728 26.7139 38.0397 28.5285 38.7286 29.9128C39.4174 31.2972 41.3673 31.727 43.5476 30.642Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.7278 8.88017C15.6864 8.99524 15.6393 9.11547 15.5862 9.23831C15.2355 10.0486 14.7368 10.7133 14.1379 11.0113C13.2817 11.4374 12.5937 11.5037 12.1519 11.4281C11.731 11.356 11.548 11.1705 11.4641 11.0018C11.3802 10.8331 11.3425 10.5753 11.5388 10.1961C11.7449 9.79804 12.2127 9.28926 13.069 8.86317C13.6679 8.56516 14.4989 8.56823 15.3567 8.77717C15.4868 8.80884 15.6111 8.84378 15.7278 8.88017ZM14.8507 12.4438C17.031 11.3589 17.6472 8.16563 17.5513 7.97282C17.4553 7.78001 14.5365 6.34579 12.3562 7.43072C10.1759 8.51564 9.34282 10.3303 10.0317 11.7146C10.7205 13.0989 12.6704 13.5287 14.8507 12.4438Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M17.8567 38.0071C17.8154 38.1222 17.7683 38.2424 17.7151 38.3653C17.3645 39.1755 16.8657 39.8403 16.2668 40.1383C15.4106 40.5644 14.7226 40.6307 14.2808 40.5551C13.8599 40.483 13.677 40.2974 13.593 40.1288C13.5091 39.9601 13.4714 39.7022 13.6678 39.323C13.8738 38.925 14.3416 38.4162 15.1979 37.9901C15.7968 37.6921 16.6278 37.6952 17.4856 37.9041C17.6157 37.9358 17.74 37.9707 17.8567 38.0071ZM16.9796 41.5707C19.1599 40.4858 19.7761 37.2926 19.6802 37.0998C19.5842 36.907 16.6654 35.4727 14.4851 36.5577C12.3048 37.6426 11.4717 39.4572 12.1606 40.8415C12.8494 42.2259 14.7993 42.6557 16.9796 41.5707Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M24.1275 17.3695C24.2427 17.4106 24.363 17.4574 24.486 17.5102C25.2971 17.8588 25.9632 18.3558 26.2627 18.9539C26.691 19.8091 26.7591 20.4969 26.6846 20.9388C26.6136 21.3599 26.4285 21.5434 26.2601 21.6277C26.0916 21.7121 25.8338 21.7504 25.4541 21.5551C25.0556 21.35 24.5456 20.8835 24.1173 20.0284C23.8178 19.4302 23.8187 18.5992 24.0254 17.7409C24.0568 17.6107 24.0914 17.4863 24.1275 17.3695ZM27.6933 18.2374C26.6028 16.0599 23.408 15.452 23.2154 15.5484C23.0229 15.6448 21.5962 18.5673 22.6867 20.7448C23.7772 22.9223 25.594 23.7508 26.9766 23.0584C28.3591 22.366 28.7839 20.4149 27.6933 18.2374Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M40.9258 6.17078C41.041 6.21185 41.1613 6.25865 41.2843 6.31149C42.0955 6.66005 42.7615 7.15706 43.0611 7.75517C43.4894 8.61035 43.5575 9.29814 43.4829 9.74011C43.412 10.1612 43.2269 10.3446 43.0584 10.429C42.89 10.5134 42.6322 10.5517 42.2525 10.3564C41.8539 10.1513 41.344 9.68481 40.9157 8.82963C40.6161 8.23151 40.617 7.40048 40.8238 6.54214C40.8551 6.41201 40.8897 6.28761 40.9258 6.17078ZM44.4917 7.03869C43.4011 4.86119 40.2063 4.25324 40.0138 4.34968C39.8212 4.44612 38.3945 7.3686 39.485 9.54611C40.5756 11.7236 42.3924 12.552 43.7749 11.8596C45.1574 11.1672 45.5822 9.2162 44.4917 7.03869Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M43.489 20.8145C43.6104 20.8 43.739 20.7882 43.8727 20.7808C44.7542 20.7315 45.5719 20.8797 46.1065 21.2817C46.8709 21.8566 47.2383 22.442 47.3685 22.8709C47.4925 23.2795 47.4086 23.5262 47.2953 23.6768C47.1821 23.8274 46.9684 23.9765 46.5414 23.9708C46.0933 23.9647 45.4289 23.7743 44.6644 23.1995C44.1298 22.7974 43.7604 22.053 43.5631 21.1924C43.5332 21.062 43.5088 20.9352 43.489 20.8145ZM47.0681 20.003C45.1217 18.5393 41.9906 19.4183 41.8612 19.5904C41.7318 19.7625 41.7564 23.0146 43.7028 24.4782C45.6492 25.9419 47.6448 25.8742 48.5741 24.6384C49.5034 23.4026 49.0145 21.4666 47.0681 20.003Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.7919 2.61626C14.9133 2.60173 15.0419 2.59001 15.1755 2.58253C16.057 2.53322 16.8747 2.68147 17.4094 3.0835C18.1738 3.65833 18.5412 4.24376 18.6714 4.67264C18.7954 5.08124 18.7114 5.32795 18.5982 5.47853C18.4849 5.62911 18.2713 5.77827 17.8443 5.77252C17.3961 5.76649 16.7317 5.57604 15.9673 5.00122C15.4327 4.59918 15.0633 3.85475 14.866 2.9942C14.836 2.86374 14.8116 2.73694 14.7919 2.61626ZM18.371 1.80472C16.4246 0.341062 13.2935 1.22005 13.164 1.39218C13.0346 1.5643 13.0593 4.81634 15.0057 6.28C16.9521 7.74366 18.9477 7.67596 19.877 6.44015C20.8063 5.20433 20.3174 3.26837 18.371 1.80472Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M17.0234 31.7544C17.1449 31.7399 17.2734 31.7282 17.4071 31.7207C18.2886 31.6714 19.1063 31.8197 19.6409 32.2217C20.4054 32.7965 20.7727 33.3819 20.9029 33.8108C21.027 34.2194 20.943 34.4661 20.8298 34.6167C20.7165 34.7673 20.5028 34.9165 20.0758 34.9107C19.6277 34.9047 18.9633 34.7142 18.1989 34.1394C17.6642 33.7374 17.2948 32.9929 17.0975 32.1324C17.0676 32.0019 17.0432 31.8751 17.0234 31.7544ZM20.6026 30.9429C18.6561 29.4792 15.525 30.3582 15.3956 30.5304C15.2662 30.7025 15.2908 33.9545 17.2372 35.4182C19.1836 36.8818 21.1792 36.8141 22.1085 35.5783C23.0378 34.3425 22.549 32.4066 20.6026 30.9429Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.7702 28.0844C15.6514 28.1135 15.5252 28.1407 15.3934 28.1643C14.5243 28.3197 13.6947 28.2714 13.1154 27.937C12.2871 27.4587 11.8516 26.922 11.6706 26.512C11.498 26.1214 11.5516 25.8664 11.6458 25.7032C11.74 25.54 11.9341 25.3661 12.3586 25.3202C12.8042 25.272 13.4868 25.3808 14.3151 25.859C14.8944 26.1935 15.3511 26.8878 15.6509 27.7182C15.6964 27.8441 15.736 27.967 15.7702 28.0844ZM12.3154 29.3226C14.4244 30.5403 17.4263 29.2893 17.534 29.1028C17.6417 28.9162 17.2241 25.691 15.1151 24.4734C13.006 23.2557 11.0333 23.5641 10.2602 24.9032C9.48704 26.2423 10.2063 28.1049 12.3154 29.3226Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M32.5684 16.8852C32.4496 16.9143 32.3234 16.9415 32.1916 16.965C31.3225 17.1205 30.4929 17.0722 29.9136 16.7377C29.0853 16.2595 28.6499 15.7228 28.4688 15.3128C28.2963 14.9222 28.3498 14.6671 28.444 14.504C28.5382 14.3408 28.7323 14.1669 29.1569 14.121C29.6025 14.0728 30.285 14.1816 31.1133 14.6598C31.6926 14.9942 32.1493 15.6886 32.4492 16.519C32.4946 16.6449 32.5342 16.7678 32.5684 16.8852ZM29.1136 18.1234C31.2227 19.341 34.2245 18.09 34.3322 17.9035C34.4399 17.717 34.0224 14.4918 31.9133 13.2741C29.8043 12.0565 27.8315 12.3649 27.0584 13.704C26.2853 15.043 27.0045 16.9057 29.1136 18.1234Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M40.7799 34.1302C40.6865 34.2091 40.5856 34.2897 40.4782 34.3695C39.7694 34.8959 39.0051 35.2222 38.3374 35.1809C37.3828 35.1217 36.7539 34.8352 36.4091 34.5488C36.0806 34.276 36.0149 34.0238 36.0266 33.8357C36.0382 33.6477 36.1345 33.4055 36.4942 33.1753C36.8717 32.9336 37.5312 32.7269 38.4858 32.7861C39.1534 32.8274 39.8716 33.2456 40.51 33.8554C40.6068 33.9479 40.697 34.0403 40.7799 34.1302ZM38.2385 36.7778C40.6692 36.9284 42.7994 34.4711 42.8127 34.2561C42.826 34.0412 41.0154 31.3397 38.5847 31.1891C36.154 31.0385 34.5253 32.1935 34.4296 33.7368C34.334 35.2801 35.8078 36.6272 38.2385 36.7778Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.083 15.9319C11.9896 16.0109 11.8887 16.0915 11.7813 16.1713C11.0725 16.6977 10.3082 17.024 9.64052 16.9826C8.68592 16.9235 8.05696 16.637 7.71219 16.3506C7.38372 16.0777 7.31804 15.8255 7.32969 15.6375C7.34134 15.4494 7.43764 15.2073 7.79728 14.977C8.17476 14.7354 8.83428 14.5287 9.78888 14.5878C10.4565 14.6292 11.1747 15.0473 11.8131 15.6572C11.9099 15.7496 12.0001 15.8421 12.083 15.9319ZM9.54159 18.5796C11.9723 18.7302 14.1025 16.2728 14.1158 16.0579C14.1291 15.8429 12.3185 13.1415 9.88781 12.9909C7.45715 12.8403 5.82835 13.9953 5.73275 15.5385C5.63714 17.0818 7.11093 18.429 9.54159 18.5796Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M19.2634 16.967C19.2151 17.0793 19.1607 17.1964 19.1001 17.3158C18.7006 18.103 18.1621 18.736 17.5461 18.9968C16.6653 19.3697 15.9746 19.3938 15.5383 19.2912C15.1226 19.1935 14.9513 18.9971 14.8778 18.8236C14.8044 18.6501 14.7826 18.3904 15.0018 18.024C15.2318 17.6393 15.7299 17.1601 16.6106 16.7872C17.2267 16.5264 18.0559 16.5804 18.8993 16.8414C19.0272 16.881 19.1491 16.9235 19.2634 16.967ZM18.1698 20.4702C20.4125 19.5208 21.223 16.3713 21.139 16.1729C21.055 15.9746 18.2295 14.3644 15.9869 15.3138C13.7442 16.2633 12.8016 18.0235 13.4044 19.4474C14.0073 20.8713 15.9272 21.4196 18.1698 20.4702Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M36.0617 5.76774C36.0133 5.88006 35.9589 5.99718 35.8984 6.11654C35.4988 6.90382 34.9603 7.5368 34.3443 7.79758C33.4635 8.17045 32.7728 8.19455 32.3365 8.092C31.9208 7.99431 31.7495 7.79789 31.6761 7.62439C31.6026 7.45089 31.5808 7.1912 31.8 6.82473C32.03 6.44008 32.5281 5.96089 33.4089 5.58802C34.0249 5.32723 34.8542 5.38116 35.6976 5.64222C35.8254 5.68179 35.9474 5.72427 36.0617 5.76774ZM34.9681 9.27099C37.2107 8.32156 38.0212 5.17204 37.9372 4.97372C37.8533 4.7754 35.0277 3.16519 32.7851 4.11461C30.5425 5.06404 29.5999 6.82427 30.2027 8.24816C30.8055 9.67205 32.7254 10.2204 34.9681 9.27099Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M38.9549 22.6215C38.9617 22.7436 38.9652 22.8727 38.9641 23.0066C38.9571 23.8894 38.757 24.696 38.3217 25.2039C37.6992 25.9301 37.0916 26.2594 36.6553 26.362C36.2396 26.4597 35.9987 26.3601 35.8557 26.2375C35.7126 26.1149 35.5774 25.8922 35.6104 25.4664C35.645 25.0195 35.8774 24.3686 36.4998 23.6424C36.9351 23.1345 37.7016 22.8134 38.573 22.6714C38.7051 22.6498 38.8332 22.6335 38.9549 22.6215ZM39.5365 26.2451C41.1213 24.3961 40.4438 21.2153 40.2803 21.0751C40.1168 20.935 36.8698 20.7521 35.285 22.6012C33.7002 24.4503 33.6404 26.4461 34.8144 27.4524C35.9885 28.4586 37.9517 28.0942 39.5365 26.2451Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M10.258 4.4233C10.2648 4.5454 10.2683 4.67448 10.2672 4.80832C10.2602 5.69118 10.0601 6.49776 9.62475 7.00567C9.00234 7.73187 8.39467 8.06115 7.95836 8.16373C7.54267 8.26145 7.30183 8.1619 7.15878 8.0393C7.01573 7.91669 6.8805 7.69391 6.91347 7.26817C6.94808 6.8213 7.18052 6.1704 7.80293 5.44421C8.23825 4.9363 9.00472 4.61514 9.87611 4.47313C10.0082 4.4516 10.1363 4.43531 10.258 4.4233ZM10.8396 8.0469C12.4244 6.19781 11.7469 3.01702 11.5834 2.87687C11.4199 2.73672 8.17292 2.55389 6.58809 4.40298C5.00326 6.25206 4.94353 8.2479 6.11755 9.25414C7.29157 10.2604 9.25477 9.89598 10.8396 8.0469Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.9798 32.3618C12.9866 32.4839 12.9901 32.613 12.989 32.7468C12.982 33.6297 12.7819 34.4362 12.3466 34.9441C11.7241 35.6703 11.1165 35.9996 10.6802 36.1022C10.2645 36.1999 10.0236 36.1004 9.88058 35.9778C9.73753 35.8552 9.6023 35.6324 9.63528 35.2066C9.66988 34.7598 9.90232 34.1089 10.5247 33.3827C10.9601 32.8748 11.7265 32.5536 12.5979 32.4116C12.73 32.3901 12.8581 32.3738 12.9798 32.3618ZM13.5614 35.9854C15.1462 34.1363 14.4688 30.9555 14.3052 30.8153C14.1417 30.6752 10.8947 30.4924 9.30989 32.3415C7.72506 34.1905 7.66533 36.1864 8.83935 37.1926C10.0134 38.1989 11.9766 37.8345 13.5614 35.9854Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M22.5516 29.2263C22.5789 29.1071 22.6114 28.9821 22.6496 28.8538C22.9013 28.0076 23.3173 27.2882 23.8765 26.921C24.6759 26.3961 25.3511 26.2483 25.7988 26.2708C26.2252 26.2923 26.429 26.4548 26.5324 26.6122C26.6358 26.7697 26.7039 27.0213 26.5541 27.4212C26.3969 27.8409 25.993 28.4017 25.1935 28.9267C24.6343 29.2939 23.8088 29.3897 22.9323 29.2844C22.7994 29.2684 22.6718 29.2485 22.5516 29.2263ZM22.9982 25.5836C20.9626 26.9203 20.7309 30.1642 20.8491 30.3442C20.9673 30.5242 24.0361 31.6009 26.0717 30.2641C28.1074 28.9274 28.7186 27.0265 27.8699 25.734C27.0211 24.4415 25.0339 24.2469 22.9982 25.5836Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M39.3498 18.0276C39.3772 17.9084 39.4096 17.7834 39.4478 17.6551C39.6995 16.8089 40.1155 16.0895 40.6747 15.7223C41.4742 15.1973 42.1493 15.0496 42.597 15.0721C43.0235 15.0936 43.2272 15.256 43.3306 15.4135C43.4341 15.571 43.5022 15.8225 43.3523 16.2224C43.1951 16.6421 42.7912 17.203 41.9917 17.728C41.4326 18.0951 40.6071 18.191 39.7305 18.0857C39.5976 18.0697 39.47 18.0498 39.3498 18.0276ZM39.7965 14.3849C37.7608 15.7216 37.5291 18.9655 37.6473 19.1455C37.7655 19.3255 40.8343 20.4021 42.8699 19.0654C44.9056 17.7287 45.5168 15.8278 44.6681 14.5353C43.8194 13.2428 41.8321 13.0481 39.7965 14.3849Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M47.3601 32.1327C47.3315 32.0138 47.3049 31.8874 47.2819 31.7556C47.1303 30.8858 47.1823 30.0564 47.5193 29.4786C48.0012 28.6524 48.5399 28.2194 48.9507 28.0401C49.342 27.8693 49.5968 27.924 49.7596 28.0189C49.9223 28.1138 50.0954 28.3087 50.1394 28.7334C50.1856 29.1793 50.0738 29.8613 49.5919 30.6875C49.2549 31.2653 48.5586 31.7189 47.7269 32.0151C47.6008 32.06 47.4777 32.099 47.3601 32.1327ZM46.1372 28.6725C44.9102 30.7761 46.1479 33.7835 46.334 33.892C46.52 34.0005 49.747 33.5973 50.974 31.4936C52.201 29.39 51.9014 27.4159 50.5657 26.6368C49.2301 25.8578 47.3642 26.5688 46.1372 28.6725Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.6631 13.934C18.6345 13.8151 18.6079 13.6887 18.5849 13.5569C18.4333 12.6871 18.4853 11.8577 18.8223 11.2799C19.3042 10.4537 19.8428 10.0206 20.2536 9.84137C20.645 9.67058 20.8998 9.72526 21.0626 9.82018C21.2253 9.91511 21.3983 10.11 21.4424 10.5347C21.4886 10.9805 21.3768 11.6626 20.8949 12.4888C20.5579 13.0666 19.8616 13.5202 19.0298 13.8164C18.9037 13.8613 18.7807 13.9003 18.6631 13.934ZM17.4402 10.4737C16.2132 12.5774 17.4509 15.5848 17.6369 15.6933C17.823 15.8018 21.05 15.3985 22.277 13.2949C23.504 11.1913 23.2043 9.21714 21.8687 8.4381C20.5331 7.65906 18.6672 8.37009 17.4402 10.4737Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M19.9572 43.599C19.9286 43.4801 19.902 43.3537 19.879 43.2219C19.7273 42.3521 19.7793 41.5227 20.1164 40.9449C20.5982 40.1187 21.1369 39.6857 21.5477 39.5064C21.9391 39.3356 22.1939 39.3903 22.3566 39.4852C22.5194 39.5801 22.6924 39.775 22.7364 40.1998C22.7826 40.6456 22.6709 41.3276 22.189 42.1538C21.852 42.7316 21.1556 43.1852 20.3239 43.4814C20.1978 43.5263 20.0747 43.5653 19.9572 43.599ZM18.7343 40.1388C17.5073 42.2424 18.745 45.2498 18.931 45.3583C19.117 45.4668 22.3441 45.0636 23.5711 42.9599C24.7981 40.8563 24.4984 38.8822 23.1628 38.1031C21.8271 37.3241 19.9613 38.0351 18.7343 40.1388Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7.15312 22.2273C7.1805 22.1081 7.21296 21.9831 7.25112 21.8548C7.50283 21.0086 7.91888 20.2892 8.47804 19.922C9.27751 19.397 9.95269 19.2493 10.4003 19.2718C10.8268 19.2933 11.0306 19.4557 11.134 19.6132C11.2374 19.7707 11.3055 20.0223 11.1557 20.4221C10.9985 20.8418 10.5945 21.4027 9.79506 21.9277C9.2359 22.2948 8.41041 22.3907 7.53384 22.2854C7.40095 22.2694 7.27336 22.2495 7.15312 22.2273ZM7.59981 18.5846C5.56414 19.9213 5.33243 23.1652 5.45064 23.3452C5.56885 23.5252 8.63762 24.6018 10.6733 23.2651C12.709 21.9284 13.3201 20.0275 12.4714 18.735C11.6227 17.4425 9.63548 17.2479 7.59981 18.5846Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.9513 11.028C23.9787 10.9089 24.0112 10.7839 24.0493 10.6556C24.301 9.80936 24.7171 9.08997 25.2763 8.72279C26.0757 8.19782 26.7509 8.05007 27.1985 8.07259C27.625 8.09405 27.8288 8.25651 27.9322 8.414C28.0356 8.57149 28.1037 8.82303 27.9539 9.22291C27.7967 9.64263 27.3927 10.2035 26.5933 10.7285C26.0341 11.0956 25.2086 11.1915 24.3321 11.0861C24.1992 11.0702 24.0716 11.0503 23.9513 11.028ZM24.398 7.38537C22.3624 8.72209 22.1306 11.966 22.2489 12.146C22.3671 12.326 25.4358 13.4026 27.4715 12.0659C29.5072 10.7292 30.1183 8.82826 29.2696 7.53577C28.4209 6.24328 26.4337 6.04864 24.398 7.38537Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M28.851 39.7248C28.8784 39.6056 28.9108 39.4807 28.949 39.3524C29.2007 38.5061 29.6168 37.7867 30.1759 37.4196C30.9754 36.8946 31.6506 36.7468 32.0982 36.7694C32.5247 36.7908 32.7284 36.9533 32.8319 37.1108C32.9353 37.2683 33.0034 37.5198 32.8536 37.9197C32.6963 38.3394 32.2924 38.9002 31.4929 39.4252C30.9338 39.7924 30.1083 39.8883 29.2317 39.7829C29.0988 39.767 28.9712 39.7471 28.851 39.7248ZM29.2977 36.0821C27.262 37.4189 27.0303 40.6627 27.1485 40.8428C27.2667 41.0228 30.3355 42.0994 32.3712 40.7627C34.4068 39.4259 35.018 37.525 34.1693 36.2325C33.3206 34.9401 31.3334 34.7454 29.2977 36.0821Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30.4561 32.726C30.4275 32.6071 30.4009 32.4807 30.3779 32.3488C30.2262 31.4791 30.2782 30.6497 30.6153 30.0718C31.0971 29.2457 31.6358 28.8126 32.0466 28.6334C32.438 28.4626 32.6928 28.5172 32.8555 28.6122C33.0183 28.7071 33.1913 28.902 33.2353 29.3267C33.2815 29.7725 33.1698 30.4546 32.6879 31.2808C32.3509 31.8586 31.6545 32.3122 30.8228 32.6084C30.6967 32.6533 30.5736 32.6923 30.4561 32.726ZM29.2332 29.2657C28.0062 31.3694 29.2439 34.3768 29.4299 34.4853C29.6159 34.5938 32.843 34.1905 34.07 32.0869C35.297 29.9833 34.9973 28.0091 33.6617 27.2301C32.326 26.451 30.4602 27.1621 29.2332 29.2657Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M1.75893 14.5277C1.73035 14.4088 1.70373 14.2825 1.68074 14.1506C1.52909 13.2808 1.58109 12.4514 1.91812 11.8736C2.40001 11.0474 2.93866 10.6144 3.34946 10.4351C3.74084 10.2643 3.99564 10.319 4.15839 10.4139C4.32113 10.5089 4.49416 10.7037 4.53819 11.1285C4.58439 11.5743 4.47263 12.2563 3.99074 13.0825C3.65371 13.6603 2.95738 14.1139 2.12566 14.4101C1.99957 14.455 1.87648 14.494 1.75893 14.5277ZM0.536041 11.0675C-0.690954 13.1711 0.546732 16.1785 0.732762 16.287C0.918792 16.3955 4.14583 15.9923 5.37283 13.8886C6.59982 11.785 6.30016 9.81089 4.96452 9.03185C3.62888 8.2528 1.76304 8.96384 0.536041 11.0675Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M29.5508 23.6272C29.5782 23.508 29.6107 23.383 29.6488 23.2547C29.9005 22.4085 30.3166 21.6891 30.8757 21.3219C31.6752 20.7969 32.3504 20.6492 32.798 20.6717C33.2245 20.6932 33.4283 20.8556 33.5317 21.0131C33.6351 21.1706 33.7032 21.4222 33.5534 21.822C33.3962 22.2417 32.9922 22.8026 32.1928 23.3276C31.6336 23.6947 30.8081 23.7906 29.9315 23.6853C29.7986 23.6693 29.6711 23.6494 29.5508 23.6272ZM29.9975 19.9845C27.9618 21.3212 27.7301 24.5651 27.8483 24.7451C27.9666 24.9251 31.0353 26.0017 33.071 24.665C35.1067 23.3283 35.7178 21.4274 34.8691 20.1349C34.0204 18.8424 32.0332 18.6478 29.9975 19.9845Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M46.3492 12.428C46.3765 12.3088 46.409 12.1838 46.4472 12.0555C46.6989 11.2093 47.1149 10.4899 47.6741 10.1227C48.4736 9.59772 49.1487 9.44997 49.5964 9.47249C50.0229 9.49395 50.2266 9.65641 50.33 9.8139C50.4334 9.97139 50.5015 10.2229 50.3517 10.6228C50.1945 11.0425 49.7906 11.6034 48.9911 12.1284C48.4319 12.4955 47.6065 12.5914 46.7299 12.486C46.597 12.4701 46.4694 12.4502 46.3492 12.428ZM46.7959 8.78527C44.7602 10.122 44.5285 13.3659 44.6467 13.5459C44.7649 13.7259 47.8337 14.8025 49.8693 13.4658C51.905 12.1291 52.5162 10.2282 51.6675 8.93567C50.8187 7.64318 48.8315 7.44854 46.7959 8.78527Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M51.132 24.0009C51.1034 23.882 51.0768 23.7556 51.0538 23.6237C50.9021 22.754 50.9541 21.9246 51.2912 21.3468C51.773 20.5206 52.3117 20.0875 52.7225 19.9083C53.1139 19.7375 53.3687 19.7922 53.5314 19.8871C53.6942 19.982 53.8672 20.1769 53.9112 20.6016C53.9574 21.0474 53.8457 21.7295 53.3638 22.5557C53.0268 23.1335 52.3304 23.5871 51.4987 23.8833C51.3726 23.9282 51.2495 23.9672 51.132 24.0009ZM49.9091 20.5406C48.6821 22.6443 49.9198 25.6517 50.1058 25.7602C50.2918 25.8687 53.5189 25.4654 54.7459 23.3618C55.9729 21.2582 55.6732 19.284 54.3376 18.505C53.0019 17.7259 51.1361 18.437 49.9091 20.5406Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M22.4348 5.8031C22.4063 5.6842 22.3796 5.55785 22.3566 5.42599C22.205 4.55623 22.257 3.72682 22.594 3.149C23.0759 2.32283 23.6146 1.88977 24.0254 1.71051C24.4167 1.53972 24.6715 1.5944 24.8343 1.68932C24.997 1.78425 25.1701 1.97912 25.2141 2.40386C25.2603 2.84968 25.1485 3.53173 24.6666 4.3579C24.3296 4.93573 23.6333 5.38931 22.8016 5.6855C22.6755 5.73041 22.5524 5.76944 22.4348 5.8031ZM21.2119 2.34286C19.9849 4.4465 21.2226 7.45391 21.4087 7.56242C21.5947 7.67092 24.8217 7.26767 26.0487 5.16403C27.2757 3.0604 26.9761 1.08628 25.6404 0.30724C24.3048 -0.471805 22.4389 0.239229 21.2119 2.34286Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M24.4568 36.5995C24.4282 36.4806 24.4016 36.3542 24.3786 36.2224C24.227 35.3526 24.279 34.5232 24.616 33.9454C25.0979 33.1192 25.6365 32.6862 26.0473 32.5069C26.4387 32.3361 26.6935 32.3908 26.8563 32.4857C27.019 32.5806 27.192 32.7755 27.2361 33.2002C27.2823 33.6461 27.1705 34.3281 26.6886 35.1543C26.3516 35.7321 25.6553 36.1857 24.8235 36.4819C24.6974 36.5268 24.5744 36.5658 24.4568 36.5995ZM23.2339 33.1393C22.0069 35.2429 23.2446 38.2503 23.4306 38.3588C23.6167 38.4673 26.8437 38.0641 28.0707 35.9604C29.2977 33.8568 28.998 31.8827 27.6624 31.1036C26.3268 30.3246 24.4609 31.0356 23.2339 33.1393Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 46,\n  svg: BrownRice,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/dumbbells.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dumbbells', 'sticker name', 'web-stories');\n\nfunction Dumbells({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 10.5C0 8.567 1.567 7 3.5 7C5.433 7 7 8.567 7 10.5V19.5C7 21.433 5.433 23 3.5 23C1.567 23 0 21.433 0 19.5V10.5ZM3.5 9C2.67157 9 2 9.67157 2 10.5V19.5C2 20.3284 2.67157 21 3.5 21C4.32843 21 5 20.3284 5 19.5V10.5C5 9.67157 4.32843 9 3.5 9Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M52 10.5C52 8.567 50.433 7 48.5 7C46.567 7 45 8.567 45 10.5V19.5C45 21.433 46.567 23 48.5 23C50.433 23 52 21.433 52 19.5V10.5ZM48.5 9C49.3284 9 50 9.67157 50 10.5V19.5C50 20.3284 49.3284 21 48.5 21C47.6716 21 47 20.3284 47 19.5V10.5C47 9.67157 47.6716 9 48.5 9Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5 6.5C5 4.567 6.567 3 8.5 3C10.433 3 12 4.567 12 6.5V22.5C12 24.433 10.433 26 8.5 26C6.567 26 5 24.433 5 22.5V6.5ZM8.5 5C7.67157 5 7 5.67157 7 6.5V22.5C7 23.3284 7.67157 24 8.5 24C9.32843 24 10 23.3284 10 22.5V6.5C10 5.67157 9.32843 5 8.5 5Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M47 6.5C47 4.567 45.433 3 43.5 3C41.567 3 40 4.567 40 6.5V22.5C40 24.433 41.567 26 43.5 26C45.433 26 47 24.433 47 22.5V6.5ZM43.5 5C44.3284 5 45 5.67157 45 6.5V22.5C45 23.3284 44.3284 24 43.5 24C42.6716 24 42 23.3284 42 22.5V6.5C42 5.67157 42.6716 5 43.5 5Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M10 3.5C10 1.567 11.567 0 13.5 0C15.433 0 17 1.567 17 3.5V26.5C17 28.433 15.433 30 13.5 30C11.567 30 10 28.433 10 26.5V3.5ZM13.5 2C12.6716 2 12 2.67157 12 3.5V26.5C12 27.3284 12.6716 28 13.5 28C14.3284 28 15 27.3284 15 26.5V3.5C15 2.67157 14.3284 2 13.5 2Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M42 3.5C42 1.567 40.433 0 38.5 0C36.567 0 35 1.567 35 3.5V26.5C35 28.433 36.567 30 38.5 30C40.433 30 42 28.433 42 26.5V3.5ZM38.5 2C39.3284 2 40 2.67157 40 3.5V26.5C40 27.3284 39.3284 28 38.5 28C37.6716 28 37 27.3284 37 26.5V3.5C37 2.67157 37.6716 2 38.5 2Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15 11H37V18H15V11ZM17 13V16H35V13H17Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 30,\n  svg: Dumbells,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/fish.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Fish', 'sticker name', 'web-stories');\n\nfunction Fish({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 28\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.5223 14.7C12.5274 14.6906 12.5326 14.681 12.538 14.6713C12.7495 14.2854 13.0845 13.7476 13.5397 13.1023C14.4483 11.8146 15.7886 10.1657 17.4698 8.52761C20.8716 5.21291 25.4514 2.15098 30.5182 1.87193C41.3448 1.27565 47.6896 6.61238 48.0273 12.7446C48.3651 18.8768 42.6447 24.878 31.8181 25.4743C26.7513 25.7533 21.863 23.2128 18.1177 20.2918C16.2668 18.8482 14.7535 17.3565 13.709 16.1763C13.1857 15.5849 12.7937 15.0872 12.541 14.7268C12.5347 14.7178 12.5284 14.7088 12.5223 14.7ZM30.4302 0.274346C19.1638 0.894839 10.7118 13.7659 10.7685 14.7966C10.8253 15.8273 20.6397 27.6923 31.9061 27.0719C43.1725 26.4514 50.0325 20.0565 49.6249 12.6566C49.2174 5.25667 41.6966 -0.346147 30.4302 0.274346Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M40.9366 12.6866L49.5519 11.3171L49.8031 12.8973L41.1878 14.2668L40.9366 12.6866Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M10.7224 14.4702L2.97357 4.60783L6.60492 15.5006L4.40468 21.7856L10.7224 14.4702ZM2.86412 26.0173L1.50359 25.2301L4.91413 15.488L0 0.747258L1.388 0L12.7949 14.5183L2.86412 26.0173Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M36.8585 11.9945C36.8585 13.9827 35.2467 15.5945 33.2585 15.5945C31.2703 15.5945 29.6585 13.9827 29.6585 11.9945C29.6585 10.0063 31.2703 8.39451 33.2585 8.39451C35.2467 8.39451 36.8585 10.0063 36.8585 11.9945ZM33.2585 13.9945C34.3631 13.9945 35.2585 13.0991 35.2585 11.9945C35.2585 10.8899 34.3631 9.99451 33.2585 9.99451C32.1539 9.99451 31.2585 10.8899 31.2585 11.9945C31.2585 13.0991 32.1539 13.9945 33.2585 13.9945Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 28,\n  svg: Fish,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as dayInTheLifeBrownRice } from './brownRice';\nimport { default as dayInTheLifeFish } from './fish';\nimport { default as dayInTheLifeLeaves } from './yellowLeaves';\nimport { default as dayInTheLifeJumpRope } from './jumpRope';\nimport { default as dayInTheLifeDumbells } from './dumbbells';\nimport { default as dayInTheLifeBag } from './whiteBag';\nimport { default as dayInTheLifeAlarmClock } from './alarmClock';\n\nexport {\n  dayInTheLifeBrownRice,\n  dayInTheLifeFish,\n  dayInTheLifeLeaves,\n  dayInTheLifeJumpRope,\n  dayInTheLifeDumbells,\n  dayInTheLifeBag,\n  dayInTheLifeAlarmClock,\n};\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/jumpRope.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Jump Rope', 'sticker name', 'web-stories');\n\nfunction JumpRope({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 44 46\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 30H6V46H0V30ZM2 32V44H4V32H2Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.3295 27.598L38.0921 31.2473L28.3606 43.9477L23.598 40.2984L33.3295 27.598ZM33.7006 30.402L26.402 39.9273L27.9895 41.1437L35.2881 31.6184L33.7006 30.402Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M3.53055 31.464C3.52022 31.5409 3.49176 31.7526 3.39443 31.9472L1.60557 31.0528C1.57006 31.1238 1.55267 31.1847 1.54601 31.2132C1.54696 31.2073 1.54808 31.1998 1.54932 31.1906C1.55626 31.1393 1.56432 31.0546 1.57271 30.9271C1.58939 30.6735 1.60305 30.3212 1.61982 29.8656C1.62135 29.824 1.6229 29.7816 1.62448 29.7385C1.65711 28.8487 1.70119 27.6466 1.79931 26.2428C2.00479 23.3029 2.44899 19.4455 3.53787 15.6024C4.62452 11.7672 6.37331 7.87349 9.23602 4.92804C12.1264 1.95408 16.1034 0 21.5 0C24.1868 0 26.2949 0.531636 27.8692 1.52163C29.4616 2.52293 30.4328 3.94692 30.9055 5.57228C30.914 5.60131 30.9223 5.63041 30.9304 5.65956C32.1785 5.46965 33.4165 5.39161 34.6018 5.43827C38.7686 5.60232 42.6673 7.36789 43.58 11.6919C44.0194 13.7737 43.7203 16.3148 42.5725 19.3348C41.4229 22.3592 39.3995 25.9252 36.3029 30.0961L34.6971 28.9039C37.7255 24.8248 39.6396 21.422 40.7029 18.6242C41.768 15.8219 41.9571 13.6873 41.6231 12.105C40.989 9.10086 38.2939 7.58518 34.5232 7.43673C33.4712 7.39531 32.3653 7.46504 31.2457 7.63458C31.3919 10.3401 30.5039 13.3161 29.2052 15.8882C27.5671 19.1322 25.109 22.0624 22.7032 23.2076C21.4749 23.7923 20.0893 23.9821 18.861 23.248C17.6737 22.5384 16.9191 21.1282 16.5207 19.2026C15.6468 14.9785 18.3468 11.4094 21.9432 9.04701C24.0038 7.69342 26.4577 6.65974 28.9609 6.04968C28.606 4.8905 27.9226 3.91775 26.8046 3.2147C25.6426 2.48399 23.9382 2 21.5 2C16.6466 2 13.1861 3.73342 10.6702 6.32196C8.12669 8.93901 6.50048 12.4828 5.46213 16.1476C4.42601 19.8045 3.99521 23.5096 3.79444 26.3822C3.69868 27.7523 3.65564 28.9257 3.623 29.8157L3.61846 29.9391C3.60203 30.3858 3.58737 30.7699 3.5684 31.0583C3.55897 31.2017 3.54738 31.3395 3.53131 31.4584L3.53055 31.464ZM29.2591 8.03634C27.0433 8.59604 24.8671 9.51921 23.0412 10.7186C19.7157 12.9031 17.8532 15.7715 18.4793 18.7974C18.8309 20.4968 19.4044 21.2428 19.887 21.5313C20.3287 21.7952 20.9548 21.8249 21.8436 21.4018C23.6722 20.5313 25.8704 18.0553 27.4198 14.9868C28.5965 12.6565 29.3027 10.1747 29.2591 8.03634ZM1.54265 31.2304C1.54265 31.2304 1.54351 31.2239 1.54601 31.2132C1.54403 31.2254 1.54265 31.2304 1.54265 31.2304Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 44 / 46,\n  svg: JumpRope,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/whiteBag.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Bag', 'sticker name', 'web-stories');\n\nfunction WhiteBag({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 31 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.3846 0C20.4826 0 24.6154 4.13276 24.6154 9.23077H30.7692V27.6923C30.7692 34.4897 25.2589 40 18.4615 40H12.3077C5.51034 40 0 34.4897 0 27.6923V9.23077H6.15385C6.15385 4.13276 10.2866 0 15.3846 0ZM9.23077 9.23077H21.5385C21.5385 5.83209 18.7833 3.07692 15.3846 3.07692C11.9859 3.07692 9.23077 5.83209 9.23077 9.23077ZM9.23077 18.4615C10.9301 18.4615 12.3077 17.084 12.3077 15.3846C12.3077 13.6853 10.9301 12.3077 9.23077 12.3077C7.53143 12.3077 6.15385 13.6853 6.15385 15.3846C6.15385 17.084 7.53143 18.4615 9.23077 18.4615ZM24.6154 15.3846C24.6154 17.084 23.2378 18.4615 21.5385 18.4615C19.8391 18.4615 18.4615 17.084 18.4615 15.3846C18.4615 13.6853 19.8391 12.3077 21.5385 12.3077C23.2378 12.3077 24.6154 13.6853 24.6154 15.3846Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 31 / 40,\n  svg: WhiteBag,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/a-day-in-the-life/yellowLeaves.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Leaves', 'sticker name', 'web-stories');\n\nfunction YellowLeaves({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M35.5389 25.2094C35.7056 25.4353 35.9086 25.733 36.1353 26.097C36.7325 27.0561 37.4508 28.4062 38.0667 29.9801C39.3186 33.1793 40.0397 37.0215 38.8366 40.3756C36.196 47.737 30.9779 50.2347 27.0656 48.8313C23.1533 47.4279 20.7126 42.183 23.3532 34.8216C24.5563 31.4675 27.5551 28.9597 30.5551 27.2856C32.031 26.462 33.4437 25.8764 34.5143 25.5156C34.9207 25.3786 35.2667 25.2778 35.5389 25.2094ZM40.3426 40.9158C43.1319 33.1398 36.8567 23.774 36.1453 23.5189C35.434 23.2637 24.6364 26.5053 21.8471 34.2813C19.0578 42.0573 21.418 48.5053 26.5254 50.3373C31.6328 52.1694 37.5533 48.6918 40.3426 40.9158Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M34.7474 30.3245L27.4495 50.6695L25.9435 50.1293L33.2414 29.7843L34.7474 30.3245Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M36.2648 37.1311L30.0335 43.4652L28.8929 42.3431L35.1242 36.009L36.2648 37.1311Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27.1382 36.9886L30.0267 44.245L28.5401 44.8367L25.6517 37.5803L27.1382 36.9886Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.42387 22.2959C5.69665 22.3622 6.04337 22.4602 6.45088 22.594C7.52433 22.9463 8.94163 23.5207 10.424 24.3325C13.4372 25.9828 16.4558 28.4667 17.6855 31.8111C20.3844 39.1514 17.9854 44.4155 14.0843 45.8498C10.1833 47.2842 4.94557 44.828 2.24666 37.4878C1.01698 34.1434 1.70752 30.2956 2.934 27.0865C3.53739 25.5077 4.245 24.152 4.83456 23.1883C5.05838 22.8224 5.25902 22.5231 5.42387 22.2959ZM19.1872 31.259C16.3363 23.5053 5.5134 20.3495 4.80408 20.6103C4.09477 20.8711 -2.10594 30.2863 0.744955 38.0399C3.59585 45.7935 9.54378 49.2241 14.6365 47.3516C19.7292 45.479 22.0381 39.0126 19.1872 31.259Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.09984 26.7268L15.5589 47.0133L14.0572 47.5654L6.59813 27.2789L8.09984 26.7268Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13.6315 30.9726L12.9173 39.8292L11.3225 39.7006L12.0367 30.844L13.6315 30.9726Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.54052 36.7204L13.4124 40.432L12.6521 41.8398L5.78017 38.1282L6.54052 36.7204Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M26.4497 1.74726C26.6376 1.95586 26.8686 2.23236 27.1297 2.57262C27.8175 3.46893 28.6639 4.74261 29.4302 6.24905C30.9877 9.31116 32.0796 13.0649 31.2089 16.5201C29.2979 24.1038 24.3479 27.0978 20.3176 26.0822C16.2872 25.0666 13.3471 20.0843 15.2582 12.5007C16.1288 9.04543 18.8692 6.2574 21.6918 4.29907C23.0805 3.33564 24.4294 2.61517 25.4598 2.15182C25.851 1.97592 26.1854 1.84193 26.4497 1.74726ZM32.7604 16.9111C34.779 8.90038 27.6214 0.190406 26.8886 0.00573779C26.1557 -0.17893 15.7253 4.09902 13.7067 12.1097C11.688 20.1204 14.665 26.3078 19.9266 27.6337C25.1881 28.9595 30.7418 24.9218 32.7604 16.9111Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M26.1607 6.91352L20.8792 27.8727L19.3277 27.4817L24.6092 6.52256L26.1607 6.91352Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M28.334 13.5409L22.7493 20.4518L21.5049 19.4461L27.0896 12.5352L28.334 13.5409Z\"\n        fill=\"#FFC864\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M19.2371 14.2883L22.8187 21.2289L21.3968 21.9626L17.8153 15.022L19.2371 14.2883Z\"\n        fill=\"#FFC864\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 51,\n  svg: YellowLeaves,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/ace-hotel-kyoto-review/greenCup.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Cup', 'sticker name', 'web-stories');\n\nfunction GreenCup({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <circle cx=\"25\" cy=\"25\" r=\"25\" fill=\"white\" />\n      <path\n        d=\"M14.5833 20.8335H34.0651C35.0133 20.8335 35.8228 21.1381 36.4936 21.7472C37.1645 22.3564 37.4999 23.0915 37.4999 23.9524C37.4999 24.8134 37.1645 25.5484 36.4936 26.1576C35.8228 26.7667 35.0133 27.0713 34.0651 27.0713H32.616C32.3656 27.981 31.9541 28.8176 31.3817 29.5811C30.8271 30.3445 30.1607 31.0024 29.3825 31.5547C28.6043 32.1071 27.7411 32.5456 26.7929 32.8705C25.8269 33.1792 24.8161 33.3335 23.7607 33.3335C22.4905 33.3335 21.3008 33.1142 20.1917 32.6756C19.0825 32.237 18.112 31.64 17.2801 30.8847C16.4482 30.1293 15.7908 29.2481 15.3078 28.2409C14.8248 27.2338 14.5833 26.1535 14.5833 25.0002V20.8335ZM32.9112 25.0002H34.0651C34.3692 25.0002 34.6331 24.8986 34.8567 24.6956C35.0803 24.4925 35.1922 24.2448 35.1922 23.9524C35.1922 23.6762 35.0803 23.4366 34.8567 23.2336C34.6331 23.0305 34.3692 22.929 34.0651 22.929H32.9112V25.0002Z\"\n        fill=\"#19584D\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: GreenCup,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/ace-hotel-kyoto-review/greenCutlery.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Cutlery', 'sticker name', 'web-stories');\n\nfunction GreenCutlery({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <circle cx=\"25\" cy=\"25\" r=\"25\" fill=\"white\" />\n      <path\n        d=\"M23.4817 14.5835C23.2766 14.5835 23.0991 14.6584 22.9492 14.8083C22.7994 14.9582 22.7244 15.1356 22.7244 15.3407V20.6412C22.7244 21.1775 22.5825 21.6232 22.2985 21.9781C22.0146 22.3331 21.6517 22.5973 21.21 22.7708V15.3407C21.21 15.1356 21.1351 14.9582 20.9852 14.8083C20.8354 14.6584 20.6579 14.5835 20.4528 14.5835C20.2477 14.5835 20.0703 14.6584 19.9204 14.8083C19.7705 14.9582 19.6956 15.1356 19.6956 15.3407V22.7708C19.2539 22.5973 18.8911 22.3331 18.6071 21.9781C18.3231 21.6232 18.1812 21.1775 18.1812 20.6412V15.3407C18.1812 15.1356 18.1062 14.9582 17.9564 14.8083C17.8065 14.6584 17.629 14.5835 17.424 14.5835C17.2189 14.5835 17.0414 14.6584 16.8915 14.8083C16.7417 14.9582 16.6667 15.1356 16.6667 15.3407V20.6412C16.6667 21.5562 16.9546 22.3607 17.5304 23.0548C18.1062 23.7489 18.828 24.1827 19.6956 24.3563V35.9737C19.6956 36.1788 19.7705 36.3563 19.9204 36.5061C20.0703 36.656 20.2477 36.7309 20.4528 36.7309C20.6579 36.7309 20.8354 36.656 20.9852 36.5061C21.1351 36.3563 21.21 36.1788 21.21 35.9737V24.3563C22.0777 24.1827 22.7994 23.7489 23.3752 23.0548C23.951 22.3607 24.2389 21.5562 24.2389 20.6412V15.3407C24.2389 15.1356 24.1639 14.9582 24.0141 14.8083C23.8642 14.6584 23.6867 14.5835 23.4817 14.5835Z\"\n        fill=\"#19584D\"\n      />\n      <path\n        d=\"M35.4178 21.7229C35.4178 23.03 35.1609 24.1275 34.6471 25.0154C34.1333 25.9034 33.4482 26.5141 32.5918 26.8476L33.2003 35.8655C33.2183 36.0999 33.1462 36.3027 32.9839 36.474C32.8217 36.6453 32.6234 36.7309 32.389 36.7309H29.7928C29.5585 36.7309 29.3602 36.6453 29.1979 36.474C29.0356 36.3027 28.9635 36.0999 28.9815 35.8655L29.59 26.8476C28.7336 26.5141 28.0486 25.9034 27.5347 25.0154C27.0209 24.1275 26.764 23.03 26.764 21.7229C26.764 20.5691 26.9556 19.4445 27.3387 18.3493C27.7218 17.254 28.2514 16.3526 28.9275 15.6449C29.6035 14.9373 30.3247 14.5835 31.0909 14.5835C31.8572 14.5835 32.5783 14.9373 33.2544 15.6449C33.9305 16.3526 34.4601 17.254 34.8432 18.3493C35.2263 19.4445 35.4178 20.5691 35.4178 21.7229Z\"\n        fill=\"#19584D\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: GreenCutlery,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/ace-hotel-kyoto-review/greenHandBag.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Handbag', 'sticker name', 'web-stories');\n\nfunction GreenHandBag({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <circle cx=\"25\" cy=\"25\" r=\"25\" fill=\"white\" />\n      <path\n        d=\"M16.6584 33.3333H31.2581C31.8277 33.3333 32.316 33.13 32.7229 32.7233C33.1298 32.3167 33.3333 31.8206 33.3333 31.235V19.7916C33.3333 19.4988 33.2315 19.2507 33.0281 19.0474C32.8246 18.8441 32.5764 18.7424 32.2834 18.7424H29.1584V17.9372C29.1584 17.254 29.0445 16.6034 28.8166 15.9853C28.5725 15.3672 28.2429 14.81 27.8279 14.3139C27.4128 13.8178 26.9205 13.4152 26.3508 13.1061C25.7812 12.7808 25.1545 12.5856 24.4709 12.5205C23.706 12.4555 22.9736 12.5449 22.2737 12.7889C21.5738 13.0329 20.9635 13.3908 20.4426 13.8625C19.9218 14.3342 19.5068 14.9036 19.1975 15.5705C18.9045 16.2374 18.7581 16.9531 18.7581 17.7176V18.7424H15.6331C15.3401 18.7424 15.0919 18.8441 14.8884 19.0474C14.685 19.2507 14.5833 19.4988 14.5833 19.7916V31.235C14.5833 31.8206 14.7867 32.3167 15.1936 32.7233C15.6005 33.13 16.0888 33.3333 16.6584 33.3333ZM29.1584 20.8408V22.9147H27.0833V20.8408H29.1584ZM20.8333 17.7176C20.8333 16.8555 21.1384 16.1195 21.7488 15.5095C22.3591 14.8995 23.0956 14.5945 23.9583 14.5945C24.8209 14.5945 25.5574 14.8995 26.1677 15.5095C26.7781 16.1195 27.0833 16.8555 27.0833 17.7176V18.7424H20.8333V17.7176ZM18.7581 20.8408H20.8333V22.9147H18.7581V20.8408Z\"\n        fill=\"#19584D\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: GreenHandBag,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/ace-hotel-kyoto-review/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as greenCup } from './greenCup';\nimport { default as greenCutlery } from './greenCutlery';\nimport { default as greenHandBag } from './greenHandBag';\n\nexport { greenCup, greenCutlery, greenHandBag };\n"
  },
  {
    "path": "packages/stickers/src/all-about-cars/blueRings.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Blue Rings', 'sticker name', 'web-stories');\n\nconst BlueRings = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 60 60\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <g filter=\"url(#filter0_d)\">\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30.377 44.528c7.816 0 14.151-6.335 14.151-14.15 0-7.816-6.335-14.152-14.15-14.152-7.816 0-14.152 6.336-14.152 14.151 0 7.816 6.336 14.151 14.151 14.151zm0 .566c8.128 0 14.717-6.589 14.717-14.717S38.505 15.66 30.377 15.66 15.66 22.25 15.66 30.377c0 8.128 6.59 14.717 14.717 14.717z\"\n        fill=\"#00F0FF\"\n      />\n    </g>\n    <g filter=\"url(#filter1_d)\">\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30 49.434c10.733 0 19.434-8.7 19.434-19.434 0-10.733-8.7-19.434-19.434-19.434-10.733 0-19.434 8.7-19.434 19.434 0 10.733 8.7 19.434 19.434 19.434zM30 50c11.046 0 20-8.954 20-20s-8.954-20-20-20-20 8.954-20 20 8.954 20 20 20z\"\n        fill=\"#00F0FF\"\n        fillOpacity=\".4\"\n      />\n    </g>\n    <defs>\n      <filter\n        id=\"filter0_d\"\n        x=\"5.66\"\n        y=\"5.66\"\n        width=\"49.434\"\n        height=\"49.434\"\n        filterUnits=\"userSpaceOnUse\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feColorMatrix\n          in=\"SourceAlpha\"\n          values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n        />\n        <feOffset />\n        <feGaussianBlur stdDeviation=\"5\" />\n        <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0.941176 0 0 0 0 1 0 0 0 1 0\" />\n        <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n        <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n      </filter>\n      <filter\n        id=\"filter1_d\"\n        x=\"0\"\n        y=\"0\"\n        width=\"60\"\n        height=\"60\"\n        filterUnits=\"userSpaceOnUse\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feColorMatrix\n          in=\"SourceAlpha\"\n          values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n        />\n        <feOffset />\n        <feGaussianBlur stdDeviation=\"5\" />\n        <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0.941176 0 0 0 0 1 0 0 0 1 0\" />\n        <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n        <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n      </filter>\n    </defs>\n  </svg>\n);\n\nexport default {\n  aspectRatio: 60 / 60,\n  svg: BlueRings,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/all-about-cars/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as selfDrivingCarsBlueRings } from './blueRings';\nimport { default as selfDrivingCarsMultipleBlueRings } from './multipleBlueRings';\n\nexport { selfDrivingCarsBlueRings, selfDrivingCarsMultipleBlueRings };\n"
  },
  {
    "path": "packages/stickers/src/all-about-cars/multipleBlueRings.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Multiple Blue Rings', 'sticker name', 'web-stories');\n\nconst MultipleBlueRings = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 60 60\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <g filter=\"url(#filter0_d)\">\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30 38.115a8.115 8.115 0 100-16.23 8.115 8.115 0 000 16.23zm0 .245a8.36 8.36 0 100-16.72 8.36 8.36 0 000 16.72z\"\n        fill=\"#00F0FF\"\n      />\n    </g>\n    <g opacity=\".5\" filter=\"url(#filter1_d)\">\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30 43.36c7.379 0 13.36-5.981 13.36-13.36S37.38 16.64 30 16.64 16.64 22.62 16.64 30 22.62 43.36 30 43.36zm0 .247c7.515 0 13.606-6.092 13.606-13.607S37.515 16.394 30 16.394 16.393 22.485 16.393 30 22.485 43.607 30 43.607z\"\n        fill=\"#00F0FF\"\n      />\n    </g>\n    <g opacity=\".2\" filter=\"url(#filter2_d)\">\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M30 49.754c10.91 0 19.754-8.844 19.754-19.754 0-10.91-8.844-19.754-19.754-19.754-10.91 0-19.754 8.844-19.754 19.754 0 10.91 8.844 19.754 19.754 19.754zM30 50c11.046 0 20-8.954 20-20s-8.954-20-20-20-20 8.954-20 20 8.954 20 20 20z\"\n        fill=\"#00F0FF\"\n      />\n    </g>\n    <defs>\n      <filter\n        id=\"filter0_d\"\n        x=\"11.639\"\n        y=\"11.639\"\n        width=\"36.721\"\n        height=\"36.721\"\n        filterUnits=\"userSpaceOnUse\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feColorMatrix\n          in=\"SourceAlpha\"\n          values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n        />\n        <feOffset />\n        <feGaussianBlur stdDeviation=\"5\" />\n        <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0.941176 0 0 0 0 1 0 0 0 1 0\" />\n        <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n        <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n      </filter>\n      <filter\n        id=\"filter1_d\"\n        x=\"6.393\"\n        y=\"6.394\"\n        width=\"47.213\"\n        height=\"47.213\"\n        filterUnits=\"userSpaceOnUse\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feColorMatrix\n          in=\"SourceAlpha\"\n          values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n        />\n        <feOffset />\n        <feGaussianBlur stdDeviation=\"5\" />\n        <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0.941176 0 0 0 0 1 0 0 0 1 0\" />\n        <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n        <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n      </filter>\n      <filter\n        id=\"filter2_d\"\n        x=\"0\"\n        y=\"0\"\n        width=\"60\"\n        height=\"60\"\n        filterUnits=\"userSpaceOnUse\"\n        colorInterpolationFilters=\"sRGB\"\n      >\n        <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n        <feColorMatrix\n          in=\"SourceAlpha\"\n          values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n        />\n        <feOffset />\n        <feGaussianBlur stdDeviation=\"5\" />\n        <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0.941176 0 0 0 0 1 0 0 0 1 0\" />\n        <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n        <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n      </filter>\n    </defs>\n  </svg>\n);\n\nexport default {\n  aspectRatio: 60 / 60,\n  svg: MultipleBlueRings,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/almodos-films/heptagram.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Heptagram', 'sticker name', 'web-stories');\n\nconst Heptagram = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 79 77\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M39.5 0.5L47.8653 23.1293L70.7733 15.5604L58.2966 36.2098L78.4971 49.4008L54.5737 52.5209L56.8554 76.5388L39.5 59.78L22.1446 76.5388L24.4263 52.5209L0.502884 49.4008L20.7034 36.2098L8.22674 15.5604L31.1347 23.1293L39.5 0.5Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 79 / 77,\n  svg: Heptagram,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/almodos-films/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as heptagram } from './heptagram';\n\nexport { heptagram };\n"
  },
  {
    "path": "packages/stickers/src/an-artists-legacy/brushStroke.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Brush Stroke', 'sticker name', 'web-stories');\n\nconst BrushStroke = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 54 30\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M44.8406 28.933C44.4544 28.8747 44.0681 28.8201 43.6782 28.7619C43.2847 28.0954 42.8037 27.3999 41.8635 26.2164C41.3534 25.5754 40.8104 24.9309 40.2529 24.2827C40.3221 24.8107 40.3221 25.3606 40.2055 25.8886L40.1545 26.1108L40.129 26.2236L40.1144 26.2783C40.0816 26.3729 40.1327 26.2309 40.1035 26.3183C40.3294 26.7371 40.5408 27.1523 40.7193 27.5638C40.4934 27.2433 40.2529 26.9192 40.0088 26.5951C40.0088 26.5987 40.0051 26.6024 40.0051 26.606L39.9905 26.6424L39.9395 26.7699L39.8739 26.9338C39.7865 27.1231 39.6881 27.3125 39.5788 27.4982C39.4731 27.6766 39.3456 27.8769 39.2326 28.0299C39.1852 28.0918 39.1306 28.1501 39.0832 28.2083C38.7042 28.1792 38.3326 28.1537 37.9827 28.1391C37.1373 28.0809 37.2212 28.4778 37.2612 28.6745C36.9515 28.6344 36.6673 28.6089 36.3976 28.5907C35.7308 28.1501 35.0931 27.7458 34.5137 27.3999C35.2024 28.1719 35.4648 28.4268 34.8052 28.2921C33.7339 27.1377 33.989 26.8828 30.6511 24.6213L30.4689 24.7451C29.8422 24.3701 29.281 23.9804 28.7454 23.6126C28.7089 23.5871 28.6761 23.5653 28.6433 23.5434C28.6688 23.5471 28.6907 23.5543 28.7162 23.558L30.2576 23.8129C30.3815 23.8311 30.5017 23.8457 30.6256 23.8566L30.2867 23.6162C24.0083 19.1662 16.724 15.2587 8.49603 12.309C8.04418 12.0505 7.50124 11.7846 6.91821 11.5224C6.75059 11.4496 6.58297 11.3731 6.41534 11.3003C6.08739 10.9543 5.77037 10.5902 5.47885 10.1823C4.66261 9.55595 3.37995 8.35422 2.76048 7.37827C2.93174 7.6441 3.07021 7.8626 2.81514 7.65867C1.94788 6.71549 2.17381 6.39139 1.73653 5.37538C1.73653 5.37538 1.54705 5.29526 1.35757 5.21514C1.17537 5.13139 0.989528 5.04763 0.989528 5.04763C0.934869 4.90561 0.887498 4.76722 0.851058 4.62884C8.95881 6.56618 16.6876 9.22821 23.9208 12.4984C25.1743 13.081 26.4169 13.671 27.6485 14.2755C27.6704 14.2864 27.6886 14.2973 27.7105 14.3046C26.6246 13.5217 25.5205 12.7861 24.4054 12.0905C24.0775 11.8866 23.7532 11.6863 23.4252 11.4897C23.3341 11.435 23.2394 11.3768 23.1483 11.3221C20.9437 10.0221 18.6881 8.87497 16.3924 7.84803C11.7573 5.78688 7.03117 4.21006 2.27584 3.47445L2.10822 3.42711L1.22274 3.18312C1.07698 3.13942 0.923937 3.10664 0.774536 3.07387C0.821907 2.83352 0.891142 2.6041 0.993172 2.39289C1.36485 1.66092 2.00254 1.14746 2.76412 0.765085L2.74226 0.710461C3.5002 0.313524 4.47313 0.0658932 5.56995 0.0112705C6.66677 -0.0397129 7.83648 0.0841007 8.91873 0.346298C9.49811 0.389997 9.70946 0.379072 9.98275 0.386356C10.256 0.389997 10.5986 0.404564 11.444 0.553871C11.393 0.77965 12.4716 0.987223 13.7251 1.31861C14.9604 1.63907 16.4544 2.13069 17.1285 2.58954C17.1285 2.58954 17.9083 2.77162 18.6918 2.9537C19.0817 3.04474 19.4752 3.13578 19.7704 3.20497C20.0619 3.2778 20.255 3.32514 20.255 3.32514C20.8125 3.76214 23.8042 4.81821 25.1233 5.40087C24.8464 5.24792 25.003 5.26612 25.3929 5.37901C27.4299 6.51156 29.4304 7.76792 31.3654 9.0789C35.1806 11.6899 38.7443 14.5049 42.1186 17.0176C42.483 17.3344 43.3247 17.7023 44.2977 18.1538C44.3159 18.1611 44.3305 18.1684 44.345 18.1757C45.1649 18.9914 45.9812 19.8253 46.7755 20.6847C46.75 20.6847 46.7245 20.6847 46.699 20.6847C45.8099 20.601 44.8479 20.4845 43.8495 20.3461C42.8 20.2004 41.7105 20.0511 40.6209 19.9018C38.4018 19.6032 36.077 19.341 34.0145 19.2536C35.4429 19.5085 36.7511 19.6141 38.0629 19.7379C38.7188 19.9018 38.0811 19.9819 37.4544 20.0729C36.8276 20.1603 36.2081 20.266 36.8677 20.4116C38.1576 20.6155 39.7173 20.7831 41.255 20.9542C42.8 21.1254 44.2904 21.3038 45.4564 21.475L45.4309 21.861C43.6891 21.5988 42.1696 21.3839 40.6465 21.1946C39.1196 21.0052 37.5673 20.8377 35.6652 20.7175C33.7813 20.7029 32.5715 20.896 32.0358 21.1072C31.4965 21.3111 31.6022 21.5114 32.2435 21.6061C34.7323 21.7772 37.407 22.0321 40.0707 22.3453C42.7381 22.6621 45.3508 23.019 47.6756 23.3723C46.5132 23.1938 46.4986 23.3868 46.484 23.5798C45.3253 23.4087 43.0041 23.0591 41.8344 22.9098C44.5855 23.2958 47.1472 23.6745 49.6652 24.0714C49.8692 24.3264 50.1353 24.6796 50.3539 25.0001L51.1118 26.0671C51.5564 26.7954 52.0483 27.5091 52.4164 28.2484C52.7297 28.791 52.9812 29.3372 53.2253 29.8835V30C51.6001 29.8944 49.5668 29.6249 47.3258 29.2972C46.5168 29.1806 45.686 29.0605 44.8406 28.933ZM2.5054 6.95584C2.54549 7.04688 2.6293 7.18526 2.7204 7.32364C2.64023 7.19618 2.56371 7.06873 2.5054 6.95584ZM33.0853 17.1633L34.5465 18.0118L34.7396 18.1247C34.5319 17.8953 34.3315 17.6731 34.1238 17.4437C33.7048 17.1232 33.3477 17.1123 32.9104 17.065C32.9687 17.1014 33.027 17.1342 33.0853 17.1633ZM32.8667 24.8981L32.8557 24.8508L32.8448 24.7998L32.8375 24.7743C32.8339 24.7051 32.8339 24.7269 32.8375 24.7743C32.8375 24.7888 32.8375 24.8034 32.8375 24.818C32.8375 24.8435 32.8411 24.8653 32.8411 24.8908C32.8484 24.8981 32.8594 24.9017 32.8667 24.909V24.8981Z\"\n      fill=\"#EAEEF4\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 54 / 30,\n  svg: BrushStroke,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/an-artists-legacy/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as baquosBrushStroke } from './brushStroke';\n\nexport { baquosBrushStroke };\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/books.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Books', 'sticker name', 'web-stories');\n\nfunction Books({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 33 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M9.38432 21.5733L31.044 21.2222C31.044 21.2222 32.8889 22.5821 32.8889 25.3621C32.8877 29.7463 31.1155 29.9721 31.1155 29.9721H16.826L9.38432 21.5733Z\"\n        fill=\"#AC3F3B\"\n      />\n      <path\n        d=\"M3.53208 22.2158C3.53208 22.2158 4.95998 24.2116 4.95998 25.7657C4.95998 27.8619 3.53208 29.211 3.53208 29.211L20.3166 29.1204C20.3166 29.1204 22.2481 29.284 21.9459 25.3895C21.6437 21.4939 19.9277 22.2278 19.9277 22.2278L3.53208 22.2158Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        opacity=\"0.32\"\n        d=\"M21.946 25.3817C21.6438 21.486 19.9277 22.22 19.9277 22.22L3.53331 22.208C3.53331 22.208 3.79804 22.5777 4.09908 23.122L18.1543 23.7709C18.1543 23.7709 20.7781 23.9323 21.071 26.2934C21.235 27.6142 21.0171 28.4746 20.7676 29.0265C21.317 28.8084 22.1521 28.0417 21.946 25.3817Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        d=\"M3.45599 21.5787L19.9031 21.4707C22.5211 21.9451 22.7683 24.5887 22.7952 26.1101C22.8432 28.7265 21.6567 29.9709 20.2733 29.9709L3.55322 29.9382C3.1245 29.9371 2.77777 29.6132 2.77777 29.2151L20.3166 29.1202C21.1366 29.2107 21.9776 28.4299 21.9835 25.6586C21.987 23.7577 21.1366 22.401 19.9277 22.2276L2.77777 22.2156C2.7766 21.8655 3.07998 21.5819 3.45599 21.5787Z\"\n        fill=\"#EA765C\"\n      />\n      <path\n        opacity=\"0.29\"\n        d=\"M25.6091 21.4142C25.6091 21.4142 26.6116 23.2478 26.6356 25.0651C26.6879 29.0103 25.87 30.0002 25.87 30.0002H28.1477C28.1477 30.0002 28.9677 29.0103 28.8115 24.7958C28.733 22.6787 27.836 21.3335 27.836 21.3335L25.6091 21.4142Z\"\n        fill=\"#294756\"\n      />\n      <path\n        opacity=\"0.25\"\n        d=\"M21.9798 21.4163L31.0461 21.2222C31.0461 21.2222 31.9364 22.0488 32.2222 22.8755C32.221 22.8755 30.8646 21.4905 21.9798 21.4163Z\"\n        fill=\"#294756\"\n      />\n      <path\n        d=\"M25.2392 6.68467L3.38889 6.3335C3.38889 6.3335 0 7.69347 0 10.4734C0.00125781 14.8577 3.55555 15.0834 3.55555 15.0834H17.2484L25.2392 6.68467Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M30.4445 7.37625C30.4445 7.37625 28.9909 9.36124 28.9909 10.9069C28.9909 12.9917 30.4445 14.3335 30.4445 14.3335L13.3581 14.2435C13.3581 14.2435 11.3918 14.4062 11.6994 10.5327C12.0071 6.65818 13.754 7.38818 13.754 7.38818L30.4445 7.37625Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        opacity=\"0.32\"\n        d=\"M11.6994 10.4517C12.007 6.54045 13.7541 7.27737 13.7541 7.27737L30.4445 7.26532C30.4445 7.26532 30.175 7.63652 29.8685 8.18291L15.5595 8.83441C15.5595 8.83441 12.8883 8.99647 12.5902 11.3671C12.4232 12.6931 12.645 13.557 12.899 14.1111C12.3397 13.8921 11.4895 13.1223 11.6994 10.4517Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        d=\"M30.5334 6.77425L13.8279 6.66699C11.1688 7.13829 10.9177 9.76459 10.8903 11.276C10.8416 13.8752 12.0468 15.1114 13.4519 15.1114L30.4346 15.0789C30.8701 15.0779 31.2223 14.7561 31.2223 14.3606L13.4079 14.2663C12.5751 14.3563 11.7208 13.5805 11.7149 10.8275C11.7113 8.939 12.5751 7.59118 13.8029 7.41891L31.2223 7.40699C31.2234 7.0592 30.9153 6.7775 30.5334 6.77425Z\"\n        fill=\"#C9544F\"\n      />\n      <path\n        opacity=\"0.29\"\n        d=\"M7.98569 6.52549C7.98569 6.52549 6.70996 8.35912 6.67938 10.1764C6.6128 14.1216 7.65371 15.1115 7.65371 15.1115H4.75499C4.75499 15.1115 3.71137 14.1216 3.9102 9.90713C4.01006 7.79007 5.15174 6.44482 5.15174 6.44482L7.98569 6.52549Z\"\n        fill=\"#294756\"\n      />\n      <path\n        d=\"M9.66659 15.0359L28.3888 14.8335C28.3888 14.8335 31.3333 15.7227 31.3333 17.8429C31.3322 21.1865 27.7777 21.6668 27.7777 21.6668H18.2827L9.66659 15.0359Z\"\n        fill=\"#232429\"\n      />\n      <path\n        d=\"M24.889 0.144451L7.77786 0C7.77786 0 4.66675 0.820028 4.66675 2.9054C4.66772 6.1942 6.70741 6.61996 6.70741 6.61996L16.8473 6.66667L24.889 0.144451Z\"\n        fill=\"#412C47\"\n      />\n      <path\n        d=\"M6.81116 15.6812C6.81116 15.6812 7.93667 17.064 7.93667 18.2604C7.93667 19.8745 6.47417 21.2356 6.47417 21.2356L22.409 20.9935C22.409 20.9935 24.3012 21.0404 24.0198 18.0401C23.7384 15.0399 21.7372 15.4892 21.7372 15.4892L6.81116 15.6812Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        d=\"M27.7899 0.776365C27.7899 0.776365 26.6644 2.15925 26.6644 3.35564C26.6644 4.96973 28.1269 6.33081 28.1269 6.33081L12.1921 6.08869C12.1921 6.08869 10.2999 6.13559 10.5813 3.13534C10.8626 0.13509 12.8639 0.584417 12.8639 0.584417L27.7899 0.776365Z\"\n        fill=\"#DDDDDD\"\n      />\n      <g opacity=\"0.32\">\n        <path\n          opacity=\"0.32\"\n          d=\"M21.7494 16.6179C21.7494 16.6179 23.7419 16.1707 24.0299 19.1502C24.0669 18.8362 24.0724 18.4708 24.032 18.0411C23.7507 15.0408 21.7494 15.4902 21.7494 15.4902L6.82232 15.6821C6.82232 15.6821 7.21275 16.162 7.53338 16.8011L21.7494 16.6179Z\"\n          fill=\"#DDDDDD\"\n        />\n      </g>\n      <g opacity=\"0.32\">\n        <path\n          opacity=\"0.32\"\n          d=\"M12.8519 1.71356C12.8519 1.71356 10.8594 1.26642 10.5715 4.24595C10.5344 3.93186 10.5289 3.5665 10.5693 3.1368C10.8507 0.136549 12.8519 0.585883 12.8519 0.585883L27.779 0.777824C27.779 0.777824 27.3886 1.25769 27.0679 1.89678L12.8519 1.71356Z\"\n          fill=\"#DDDDDD\"\n        />\n      </g>\n      <path\n        d=\"M5.92345 15.2108C5.92345 15.2108 20.242 14.6557 22.0873 15.0396C23.9424 15.4257 24.5368 17.0594 24.6109 18.21C24.7451 20.2952 23.9413 21.4469 22.6239 21.6181L5.92236 21.5712V21.0717C5.92236 21.0717 22.3359 21.1033 22.7395 20.9419C23.143 20.7805 24.166 20.3476 24.0198 18.0387C23.9391 16.7616 23.3535 15.8161 22.06 15.5958C21.4275 15.4878 5.92236 15.6928 5.92236 15.6928V15.2108H5.92345Z\"\n        fill=\"#525560\"\n      />\n      <path\n        d=\"M28.6776 0.306507C28.6776 0.306507 14.3591 -0.248611 12.5138 0.135281C10.6587 0.521355 10.0643 2.15508 9.99013 3.30567C9.85599 5.3909 10.6598 6.54258 11.9772 6.7138L28.6787 6.6669V6.16741C28.6787 6.16741 12.2651 6.19904 11.8616 6.03763C11.4581 5.87622 10.4351 5.44325 10.5812 3.13444C10.6619 1.85734 11.2476 0.911788 12.5411 0.691486C13.1736 0.583517 28.6787 0.788552 28.6787 0.788552V0.306507H28.6776Z\"\n        fill=\"#9A9FAF\"\n      />\n      <path\n        d=\"M23.6665 13.4443C22.8702 12.6665 21.1665 11.0998 20.7221 11.0554L20.0554 10.6665H23.3888C23.9258 11.2406 25.0332 12.5109 25.1665 12.9998C25.2999 13.4887 24.0369 12.3517 23.3888 11.7221L23.6665 13.4443Z\"\n        fill=\"#42A08C\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 33 / 30,\n  svg: Books,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/handHeldSign.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Handheld Sign', 'sticker name', 'web-stories');\n\nfunction HandHeldSign({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 36 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.94 38.8113L15.4375 36.7549L2.26593 41.6118L0.050293 50.0343L7.19563 49.1513L18.94 38.8113Z\"\n        fill=\"#35A0CD\"\n      />\n      <g clipPath=\"url(#clip0_handheld)\">\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M22.2486 28.2316C22.553 28.4953 22.6608 28.6815 22.4031 28.96C22.2417 29.1347 21.7371 29.1373 21.3832 29.1149C21.3905 28.467 21.4641 27.96 21.1061 27.6539C21.0839 27.6348 21.0618 27.6179 21.0398 27.6026L21.1214 27.482C21.1214 27.482 21.9444 27.9679 22.2486 28.2316Z\"\n          fill=\"#B9242A\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M21.6075 31.2198C21.6075 31.2198 22.1251 31.7542 22.2036 32.0622C22.282 32.3699 21.9559 32.6575 21.9559 32.6575C21.9559 32.6575 22.4419 33.0387 22.1687 33.4062C21.9377 33.7173 21.0514 34.0626 20.4033 33.9273C20.4981 33.1091 20.5755 32.2244 20.5593 32.0162C20.5309 31.6525 21.3941 30.0421 21.3835 29.3037C21.3835 29.3037 21.9362 30.1271 22.0333 30.3087C22.1303 30.4904 21.6075 31.2198 21.6075 31.2198Z\"\n          fill=\"#B9242A\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M20.6784 31.5411C20.7947 31.5588 20.9631 31.5611 21.1184 31.4783C21.3907 31.3328 21.9992 30.55 21.9992 30.55C21.8866 30.8306 21.6076 31.2199 21.6076 31.2199L21.1163 31.6322C20.9682 31.7566 20.7168 31.8397 20.5744 31.8795C20.5938 31.7891 20.6307 31.6737 20.6784 31.5411Z\"\n          fill=\"#852124\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M21.3834 29.2948L22.8599 19.7075L21.2541 19.525C20.8048 22.648 20.457 25.796 19.7653 28.876C19.7653 28.876 19.8734 28.7575 20.098 28.1676C20.3227 27.5778 20.7141 27.3184 21.1062 27.6538C21.4969 27.9875 21.3737 28.5605 21.3834 29.2948ZM20.5614 32.1053C20.672 32.1129 20.7829 32.1176 20.8938 32.1196L21.2747 29.9212C21.0459 30.713 20.5373 31.7353 20.5593 32.0159C20.5612 32.0382 20.5619 32.0684 20.5614 32.1053Z\"\n          fill=\"#452A49\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M19.5388 36.8033C19.5388 36.8033 20.0569 35.8703 20.1934 35.3404C20.33 34.8104 20.5877 32.3797 20.5593 32.0159C20.531 31.6522 21.3942 30.0419 21.3836 29.3034C21.373 28.565 21.4986 27.9889 21.1065 27.6537C20.7144 27.3183 20.323 27.5777 20.0983 28.1675C19.8735 28.7574 19.7656 28.8759 19.7656 28.8759L19.8344 27.5725C19.8344 27.5725 19.1287 27.6387 18.9078 27.7548C18.6869 27.8709 18.1012 28.8884 17.5612 29.3831C17.0212 29.8778 16.852 30.0058 16.7507 30.5615C16.6495 31.1172 16.6294 34.7051 16.5334 35.2837C16.4377 35.8623 15.9612 37.0096 15.9612 37.0096L19.1185 37.7373L19.5388 36.8033Z\"\n          fill=\"#B9242A\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M22.1521 32.401C22.0751 32.5522 21.9559 32.6575 21.9559 32.6575C21.9559 32.6575 20.8407 33.2335 20.6088 33.3035C20.5559 33.3193 20.5088 33.3314 20.4673 33.3403C20.4732 33.2834 20.4787 33.2273 20.484 33.1718C20.7844 33.0596 21.3525 32.8437 21.5185 32.7547C21.6532 32.6822 21.9396 32.5211 22.1521 32.401Z\"\n          fill=\"#852124\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M20.0648 27.5366L19.7655 28.8761C19.7655 28.8761 19.1958 30.1846 18.8933 30.6322C18.5907 31.0799 18.1899 31.3609 18.1899 31.3609C18.1899 31.3609 18.6441 30.8136 18.6409 30.6778C18.6378 30.5451 18.2941 30.2747 18.2788 30.2626C18.2943 30.2747 18.6482 30.5477 18.8123 30.437C18.9802 30.3238 19.1798 29.9349 19.1783 29.8669C19.1767 29.799 18.9311 29.4239 18.9311 29.4239C18.9311 29.4239 19.2351 29.3903 19.3755 29.1618C19.5159 28.9332 19.6052 28.0831 19.5926 27.9692C19.585 27.9012 19.2284 27.8052 18.9421 27.739C19.1939 27.6327 20.0648 27.5366 20.0648 27.5366Z\"\n          fill=\"#852124\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M20.5612 32.0578L20.8149 32.1006L20.7562 32.3226C20.7375 32.3941 20.6574 32.4467 20.5438 32.4741C20.5566 32.2899 20.5631 32.144 20.5612 32.0578Z\"\n          fill=\"#B9242A\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M15.014 35.3574L19.8342 37.3664L19.1812 39.4337L14.055 37.0215L15.014 35.3574Z\"\n          fill=\"#23799F\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M14.9989 37.1349C15.118 37.1753 15.2215 37.239 15.3109 37.3267C15.3375 37.3527 15.3724 37.3071 15.3462 37.2814C15.253 37.19 15.1447 37.1238 15.021 37.0819C14.9861 37.07 14.964 37.123 14.9989 37.1349Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M14.8598 36.2126C14.9593 36.2663 15.0587 36.32 15.1582 36.3737C15.1908 36.3913 15.2129 36.3382 15.1803 36.3207C15.0808 36.267 14.9814 36.2133 14.8819 36.1596C14.8494 36.142 14.8278 36.1953 14.8598 36.2126Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M16.2196 36.2038C16.329 36.2591 16.4304 36.3264 16.524 36.4054C16.5527 36.4294 16.5875 36.3839 16.5593 36.3601C16.4618 36.2778 16.356 36.2085 16.2417 36.1508C16.2088 36.1342 16.1867 36.1872 16.2196 36.2038Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M14.6828 36.6754C14.7771 36.7148 14.872 36.7543 14.9663 36.7936C15.0008 36.808 15.0229 36.7549 14.9884 36.7406C14.8941 36.7013 14.7992 36.6617 14.7049 36.6224C14.671 36.6083 14.6489 36.6613 14.6828 36.6754Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M15.388 35.9312C15.4765 35.9409 15.5553 35.9782 15.6167 36.0431C15.6419 36.0697 15.6879 36.0352 15.6627 36.0085C15.5903 35.9322 15.5001 35.8858 15.3953 35.8742C15.3584 35.8701 15.351 35.9271 15.388 35.9312Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M15.7971 36.8163C15.8976 36.8435 15.982 36.8969 16.0476 36.9784C16.0708 37.0073 16.1163 36.9725 16.0932 36.9437C16.0223 36.8551 15.9292 36.7931 15.8192 36.7633C15.7839 36.7538 15.7612 36.8067 15.7971 36.8163Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M16.0217 37.5562C16.1242 37.6154 16.2335 37.6525 16.3509 37.6688C16.3875 37.6739 16.3948 37.6169 16.3582 37.6118C16.2458 37.5962 16.142 37.5599 16.0438 37.5032C16.0122 37.4848 15.9901 37.5379 16.0217 37.5562Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M16.6132 37.2545C16.7081 37.2941 16.8024 37.3334 16.8972 37.3729C16.9312 37.387 16.9533 37.334 16.9193 37.3199C16.8245 37.2804 16.7302 37.2411 16.6353 37.2015C16.6014 37.1874 16.5793 37.2404 16.6132 37.2545Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M16.7972 36.8749C16.9149 36.9467 17.0432 36.9792 17.181 36.9705C17.2177 36.9681 17.2103 36.9113 17.1736 36.9136C17.0521 36.9211 16.9362 36.8928 16.8325 36.8296C16.8012 36.8106 16.7654 36.8556 16.7972 36.8749Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M17.0105 37.6815C17.0985 37.7024 17.177 37.7418 17.2477 37.7984C17.2767 37.8216 17.312 37.7763 17.283 37.7531C17.2044 37.69 17.116 37.6479 17.0174 37.6244C16.9817 37.6159 16.9748 37.6731 17.0105 37.6815Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M17.2139 38.2508C17.3462 38.3059 17.4785 38.361 17.6108 38.4162C17.6452 38.4305 17.6673 38.3775 17.6329 38.3632C17.5006 38.308 17.3683 38.2529 17.236 38.1978C17.2016 38.1834 17.1795 38.2364 17.2139 38.2508Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M17.3983 37.5107C17.4689 37.5536 17.5395 37.5965 17.6101 37.6394C17.6409 37.6582 17.6767 37.6131 17.6454 37.5941C17.5748 37.5511 17.5042 37.5082 17.4336 37.4653C17.4023 37.4463 17.367 37.4916 17.3983 37.5107Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M17.8648 36.8895C17.9497 36.9248 18.035 36.9604 18.1199 36.9958C18.1543 37.0101 18.1764 36.9571 18.142 36.9428C18.0571 36.9074 17.9718 36.8718 17.8869 36.8364C17.8525 36.8221 17.8304 36.8751 17.8648 36.8895Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M18.1924 37.6213C18.2884 37.6551 18.3723 37.7096 18.4401 37.7859C18.4649 37.8135 18.511 37.779 18.4862 37.7513C18.411 37.6673 18.3202 37.6055 18.2144 37.5683C18.1797 37.5561 18.1571 37.6089 18.1924 37.6213Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M17.9558 37.9498C18.0747 37.9838 18.1904 38.0238 18.3045 38.0705C18.3386 38.0843 18.3607 38.0313 18.3266 38.0174C18.2125 37.9708 18.0968 37.9308 17.978 37.8967C17.9429 37.8867 17.9203 37.9396 17.9558 37.9498Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M18.1024 38.3965C18.2016 38.424 18.2926 38.4658 18.3773 38.5241C18.4078 38.5452 18.443 38.4999 18.4126 38.4788C18.3238 38.4176 18.2285 38.3723 18.1245 38.3435C18.0893 38.3338 18.0667 38.3866 18.1024 38.3965Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M18.927 38.3277C18.9781 38.3374 19.0291 38.347 19.0806 38.357C19.117 38.3639 19.1238 38.3067 19.088 38.3C19.0365 38.2901 18.9854 38.2804 18.9339 38.2705C18.898 38.2638 18.8907 38.3207 18.927 38.3277Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M19.1928 37.5273C19.2298 37.5116 19.2776 37.5249 19.2975 37.5614C19.3152 37.5934 19.3687 37.572 19.3511 37.5397C19.3156 37.4758 19.2393 37.4454 19.1705 37.474C19.1364 37.4884 19.1582 37.5415 19.1928 37.5273Z\"\n          fill=\"#FFFFFE\"\n        />\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M18.5575 38.8421C18.5993 38.8486 18.6406 38.855 18.6824 38.8616C18.7187 38.8671 18.7261 38.8102 18.6897 38.8046C18.6479 38.798 18.6062 38.7915 18.5649 38.7851C18.5281 38.7792 18.5207 38.8362 18.5575 38.8421Z\"\n          fill=\"#FFFFFE\"\n        />\n      </g>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.69629 23.1002L35.6194 23.1002L35.6194 3.32518e-07L8.69629 0L8.69629 23.1002Z\"\n        fill=\"#FFFFFE\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M35.6194 23.1002L8.69629 23.1002L8.69629 0L35.6194 3.32518e-07L35.6194 23.1002ZM34.8501 0.769231L9.46552 0.769231L9.46552 22.3309L34.8501 22.331L34.8501 0.769231Z\"\n        fill=\"#C4C3DC\"\n      />\n      <defs>\n        <clipPath id=\"clip0_handheld\">\n          <rect\n            width=\"6.32377\"\n            height=\"20.4792\"\n            fill=\"white\"\n            transform=\"translate(18.321 19.0107) rotate(9.95116)\"\n          />\n        </clipPath>\n      </defs>\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 36 / 51,\n  svg: HandHeldSign,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as artBooks } from './books';\nimport { default as artPhotoFrame } from './photoFrame';\nimport { default as artHands } from './openHands';\nimport { default as artHandHeldSign } from './handHeldSign';\nimport { default as artManReading } from './manReading';\nimport { default as artWomanReading } from './womanReading';\nimport { default as artWomanReading02 } from './womanReading02';\n\nexport {\n  artBooks,\n  artPhotoFrame,\n  artHands,\n  artHandHeldSign,\n  artManReading,\n  artWomanReading,\n  artWomanReading02,\n};\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/manReading.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Man Reading', 'sticker name', 'web-stories');\n\nfunction ManReading({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M57.1429 40.251C57.1429 45.6352 44.351 50 28.5714 50C12.7919 50 0 45.6352 0 40.251C0 34.8667 12.7919 30.502 28.5714 30.502C44.351 30.502 57.1429 34.8667 57.1429 40.251Z\"\n        fill=\"#C9625B\"\n      />\n      <path\n        d=\"M8.76143 32.9323L27.3626 32.6333C27.3626 32.6333 30.2476 33.791 30.2476 36.1576C30.2465 39.8899 27.2207 40.0821 27.2207 40.0821H15.564L8.76143 32.9323Z\"\n        fill=\"#4A7F9B\"\n      />\n      <path\n        d=\"M4.33018 33.5208C4.33018 33.5208 5.56761 35.2106 5.56761 36.5264C5.56761 38.3012 4.33018 39.4435 4.33018 39.4435L18.8758 39.3668C18.8758 39.3668 20.5498 39.5053 20.2879 36.2079C20.026 32.9095 18.5388 33.5309 18.5388 33.5309L4.33018 33.5208Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        opacity=\"0.32\"\n        d=\"M20.2879 36.1394C20.026 32.8098 18.5387 33.4371 18.5387 33.4371L4.33018 33.4269C4.33018 33.4269 4.5596 33.7429 4.82051 34.208L17.0017 34.7626C17.0017 34.7626 19.2758 34.9006 19.5296 36.9187C19.6717 38.0475 19.4829 38.783 19.2666 39.2547C19.7428 39.0682 20.4666 38.4129 20.2879 36.1394Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        d=\"M4.25448 33.0083L18.4758 32.917C20.7396 33.3182 20.9533 35.554 20.9766 36.8406C21.0181 39.0533 19.9921 40.1057 18.7959 40.1057L4.33855 40.0781C3.96785 40.0771 3.66805 39.8032 3.66805 39.4665L18.8334 39.3863C19.5424 39.4628 20.2696 38.8025 20.2747 36.4588C20.2777 34.8511 19.5424 33.7037 18.4971 33.5571L3.66805 33.547C3.66704 33.2509 3.92936 33.0111 4.25448 33.0083Z\"\n        fill=\"#578CA8\"\n      />\n      <path\n        opacity=\"0.29\"\n        d=\"M23.4495 32.7967C23.4495 32.7967 24.5356 34.3577 24.5616 35.9047C24.6183 39.2633 23.7321 40.1059 23.7321 40.1059H26.1998C26.1998 40.1059 27.0882 39.2633 26.919 35.6755C26.834 33.8732 25.8621 32.728 25.8621 32.728L23.4495 32.7967Z\"\n        fill=\"#294756\"\n      />\n      <path\n        d=\"M9.05952 27.3642L23.6262 27.2412C23.6262 27.2412 26.2747 27.9393 26.2747 29.7146C26.2738 32.5143 24.5374 32.8768 24.5374 32.8768L15.9054 32.9165L9.05952 27.3642Z\"\n        fill=\"#412C47\"\n      />\n      <path\n        d=\"M6.58993 27.9025C6.58993 27.9025 7.54807 29.0797 7.54807 30.0982C7.54807 31.4723 6.30305 32.631 6.30305 32.631L19.8683 32.4248C19.8683 32.4248 21.4792 32.4648 21.2396 29.9107C21.0001 27.3566 19.2964 27.7391 19.2964 27.7391L6.58993 27.9025Z\"\n        fill=\"#DDDDDD\"\n      />\n      <g opacity=\"0.32\">\n        <path\n          opacity=\"0.32\"\n          d=\"M19.3066 28.7005C19.3066 28.7005 21.0029 28.3199 21.248 30.8563C21.2795 30.5889 21.2842 30.2779 21.2498 29.9121C21.0103 27.358 19.3066 27.7405 19.3066 27.7405L6.59922 27.9039C6.59922 27.9039 6.93159 28.3124 7.20455 28.8565L19.3066 28.7005Z\"\n          fill=\"#DDDDDD\"\n        />\n      </g>\n      <path\n        d=\"M5.83435 27.5021C5.83435 27.5021 18.0237 27.0296 19.5946 27.3564C21.1739 27.685 21.6799 29.0758 21.743 30.0553C21.8572 31.8305 21.1729 32.8109 20.0514 32.9567L5.83342 32.9167V32.4915C5.83342 32.4915 19.8063 32.5185 20.1498 32.381C20.4933 32.2436 21.3642 31.875 21.2398 29.9096C21.1711 28.8224 20.6725 28.0174 19.5714 27.8299C19.0329 27.738 5.83342 27.9125 5.83342 27.9125V27.5021H5.83435Z\"\n        fill=\"#9A9FAF\"\n      />\n      <path\n        d=\"M10.0999 38.687C10.7778 38.0248 12.2282 36.6912 12.6065 36.6533L13.1741 36.3223H10.3364C9.87923 36.811 8.9365 37.8924 8.82299 38.3086C8.70949 38.7248 9.78464 37.7568 10.3364 37.2209L10.0999 38.687Z\"\n        fill=\"#42A08C\"\n      />\n      <path\n        d=\"M27.1237 39.3944C26.2766 38.6488 26.8066 37.505 27.1775 37.0263C27.8433 37.0248 29.1279 37.1132 28.9402 37.4788C28.7057 37.9357 28.8863 38.9555 29.0188 39.4062C29.1512 39.8569 30.8178 40.9539 31.2089 41.6779C31.5219 42.2571 31.1429 42.1953 30.9142 42.092C30.0037 41.5034 27.9709 40.1399 27.1237 39.3944Z\"\n        fill=\"#068A9C\"\n      />\n      <path\n        d=\"M28.5761 3.23926L28.4647 4.54007L29.6665 5.14216L28.5761 3.23926Z\"\n        fill=\"#EA2832\"\n      />\n      <path\n        d=\"M27.7133 3.53955L29.4272 5.04731L26.251 4.31396L26.2953 3.90305L27.7133 3.53955Z\"\n        fill=\"#DDDDDD\"\n      />\n      <path\n        d=\"M29.2219 5.00628C29.2189 5.00628 29.216 5.0053 29.213 5.00431L26.317 3.90232L26.2767 4.31618C26.2757 4.32995 26.263 4.34174 26.2492 4.33879C26.2354 4.33781 26.2256 4.32503 26.2266 4.31127L26.2738 3.83154L29.2307 4.95614C29.2435 4.96106 29.2504 4.97581 29.2455 4.98859C29.2415 4.9994 29.2317 5.00628 29.2219 5.00628Z\"\n        fill=\"#1E1E1E\"\n      />\n      <path\n        d=\"M25.9829 4.25049L29.6899 5.12146L28.2213 10.1635L25.2097 9.49883L25.9829 4.25049Z\"\n        fill=\"#FF3031\"\n      />\n      <path\n        d=\"M27.6423 7.3021C27.2058 7.35026 26.2955 11.9666 26.2955 11.9666L28.0827 12.7442C28.0827 12.7442 28.2644 11.6023 28.3646 11.0014L28.5457 9.80394C28.5457 9.80394 29.6595 6.97474 29.1267 6.69654C28.5948 6.41736 27.4093 9.04601 27.4093 9.04601C27.4093 9.04601 28.0778 7.25393 27.6423 7.3021Z\"\n        fill=\"#D780A0\"\n      />\n      <path\n        d=\"M28.1476 9.0682C28.1446 9.0682 28.1407 9.06721 28.1377 9.06623C28.1249 9.06131 28.119 9.04657 28.124 9.03379C28.1436 8.98562 28.6086 7.8443 28.8809 7.44715C28.9487 7.34885 28.9674 7.26333 28.9369 7.19255C28.8721 7.04313 28.6056 6.99987 28.6037 6.99987C28.5899 6.99791 28.5801 6.98513 28.583 6.97137C28.585 6.9576 28.5988 6.94777 28.6115 6.95072C28.6233 6.95269 28.9074 6.99791 28.9841 7.17289C29.0215 7.26038 29.0018 7.36163 28.9242 7.47567C28.6558 7.8679 28.177 9.04067 28.1721 9.05246C28.1672 9.06229 28.1584 9.0682 28.1476 9.0682Z\"\n        fill=\"#1E1E1E\"\n      />\n      <path\n        d=\"M11.2386 27.5631C11.9997 27.483 12.1566 26.6283 12.14 26.211C11.7727 25.944 11.0283 25.4799 10.9882 25.7604C10.9381 26.1109 10.4374 26.6117 10.187 26.812C9.93659 27.0123 8.58452 26.9622 8.08376 27.2126C7.68315 27.4129 7.91684 27.5297 8.08376 27.5631C8.81821 27.5965 10.4774 27.6432 11.2386 27.5631Z\"\n        fill=\"#D780A0\"\n      />\n      <path\n        d=\"M15.2827 15.2032L12.19 26.4745L10.6878 26.0238C11.3572 23.3519 12.5085 14.0747 13.0826 11.965C13.8061 9.30591 14.9455 8.61877 16.9784 8.18328C19.0113 7.7478 21.2733 9.59591 21.8061 10.3224C22.3379 11.0488 24.7533 14.632 24.7533 14.632L26.3617 11.051L28.4148 11.9023C27.8967 13.4663 26.4736 18.9673 25.4473 19.1727C23.9954 19.4637 21.6233 15.2042 21.6233 15.2042C21.8169 16.4143 21.7206 16.8202 21.8169 17.1102C21.8169 17.611 21.8435 20.14 21.8169 21.1575C21.7688 22.9967 16.6855 25.5153 16.1536 24.6905C15.0919 23.0429 15.2827 15.2032 15.2827 15.2032Z\"\n        fill=\"#558BBA\"\n      />\n      <path\n        d=\"M24.891 22.3667C24.891 22.3667 31.7664 22.0413 32.5371 22.1878C33.2665 22.3264 34.5464 23.2908 33.8937 25.5144C33.2399 27.739 29.0568 38.3926 29.0568 38.3926L26.8034 37.5914L30.0677 26.5442L21.1888 27.45L24.891 22.3667Z\"\n        fill=\"#3F2B45\"\n      />\n      <path\n        d=\"M16.1546 24.6898L21.758 20.5994C21.758 20.5994 27.6415 17.0801 28.9332 18.1555C29.5564 18.6746 30.7725 22.1732 30.7725 22.1732C30.7725 22.1732 27.6872 22.197 27.2684 22.3936C26.3316 22.834 26.5445 25.2411 21.1888 27.4502C20.0268 27.6665 17.1957 27.2644 16.1546 24.6898Z\"\n        fill=\"#573C5F\"\n      />\n      <path\n        d=\"M17.8326 6.16534C17.8326 6.16534 16.7011 5.09973 16.6864 3.68316C16.6677 1.84389 17.2487 1.34352 17.9447 0.681935C18.913 -0.238193 22.5315 -0.624531 22.5188 2.15453C22.507 4.93556 20.2371 6.66375 17.8326 6.16534Z\"\n        fill=\"#F4A637\"\n      />\n      <path\n        d=\"M16.9772 8.18474L18.1874 5.329L18.4774 4.65168C18.4774 4.65168 17.9445 3.68339 18.5737 3.48973C19.2028 3.29607 18.9128 4.89762 19.3965 5.04213C19.8802 5.18762 21.2671 3.74167 21.6544 2.33789C22.0417 0.934103 21.7676 4.16704 22.1067 4.6507C22.2719 4.88761 22.4036 5.13534 22.4941 5.32703C22.5707 5.49022 22.4606 5.67896 22.2807 5.69076L21.9131 5.71533C21.9131 5.71533 21.3321 7.65193 20.8003 7.74826C20.2675 7.8446 19.8084 7.60277 19.8084 7.60277L19.3965 8.66741C19.3975 8.6684 18.1874 9.78218 16.9772 8.18474Z\"\n        fill=\"#D780A0\"\n      />\n      <path\n        d=\"M21.585 4.62003C21.5575 4.74685 21.4867 4.84023 21.4277 4.82745C21.3687 4.81467 21.3441 4.70064 21.3717 4.57383C21.3992 4.44701 21.47 4.35362 21.529 4.3664C21.5879 4.37918 21.6135 4.49322 21.585 4.62003Z\"\n        fill=\"#1E1E1E\"\n      />\n      <path\n        opacity=\"0.35\"\n        d=\"M18.9445 6.44336C18.9445 6.44336 19.0123 7.30155 19.8086 7.60335L19.5933 8.15975C19.5933 8.15975 18.8167 7.6702 18.9445 6.44336Z\"\n        fill=\"#C46255\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 50,\n  svg: ManReading,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/openHands.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Open Hands', 'sticker name', 'web-stories');\n\nfunction OpenHands({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 57 31\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M5.94735 2.22957C4.91878 0.858138 4.37592 1.94385 4.23306 2.65814C3.89973 3.56297 3.83306 5.74406 6.23306 7.22977C9.23306 9.08691 10.3759 9.51549 11.233 9.51549H12.0902C10.3759 8.94406 7.23306 3.94385 5.94735 2.22957Z\"\n        fill=\"#C44440\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.4809 2.1281C4.39697 2.30242 4.33791 2.49827 4.30311 2.67229L4.30201 2.67775L4.30009 2.68297C3.97617 3.56225 3.90487 5.70464 6.27066 7.16918C7.76992 8.09729 8.80226 8.66662 9.56549 9.00386C10.328 9.3408 10.8178 9.4442 11.2331 9.4442H11.7591C11.3854 9.23608 10.9694 8.87529 10.5366 8.4268C9.97786 7.84787 9.38211 7.11308 8.80108 6.34431C8.21987 5.57529 7.65226 4.77076 7.14996 4.0519C7.06431 3.92933 6.98059 3.80928 6.89904 3.69235C6.50182 3.12279 6.1561 2.62709 5.89021 2.27256C5.63641 1.93417 5.41918 1.75673 5.23889 1.68388C5.06359 1.61304 4.91972 1.63941 4.79786 1.72117C4.67183 1.80572 4.56538 1.95267 4.4809 2.1281ZM5.29241 1.55143C5.50766 1.6384 5.744 1.83953 6.00449 2.18685C6.27202 2.54355 6.61956 3.04187 7.01676 3.6114C7.09819 3.72817 7.18171 3.84793 7.26706 3.97008C7.76923 4.68875 8.33555 5.49142 8.91505 6.25817C9.49473 7.02516 10.0865 7.75471 10.6394 8.3276C11.1948 8.90317 11.7022 9.31101 12.1128 9.44786L12.0902 9.58706H11.2331C10.7911 9.58706 10.2809 9.47617 9.50776 9.13453C8.73528 8.7932 7.69621 8.21967 6.19547 7.29065C3.76581 5.78657 3.82307 3.57227 4.16412 2.63882C4.20089 2.45703 4.26291 2.25157 4.35219 2.06613C4.44183 1.87996 4.56216 1.70727 4.71827 1.60253C4.87856 1.495 5.07219 1.46244 5.29241 1.55143Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M50.7226 2.22957C51.7511 0.858138 52.294 1.94385 52.4369 2.65814C52.7702 3.56297 52.8369 5.74406 50.4369 7.22977C47.4369 9.08691 46.294 9.51549 45.4369 9.51549H44.5797C46.294 8.94406 49.4369 3.94385 50.7226 2.22957Z\"\n        fill=\"#C44440\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M52.189 2.1281C52.2729 2.30242 52.332 2.49827 52.3668 2.67229L52.3679 2.67775L52.3698 2.68297C52.6938 3.56225 52.765 5.70464 50.3993 7.16918C48.9 8.09729 47.8677 8.66662 47.1044 9.00386C46.3419 9.3408 45.8521 9.4442 45.4369 9.4442H44.9108C45.2845 9.23608 45.7005 8.87529 46.1333 8.4268C46.6921 7.84787 47.2878 7.11308 47.8688 6.34431C48.4501 5.57529 49.0177 4.77076 49.52 4.0519C49.6056 3.92933 49.6893 3.80928 49.7709 3.69235C50.1681 3.12279 50.5138 2.62709 50.7797 2.27256C51.0335 1.93417 51.2507 1.75673 51.431 1.68388C51.6063 1.61304 51.7502 1.63941 51.8721 1.72117C51.9981 1.80572 52.1045 1.95267 52.189 2.1281ZM51.3775 1.55143C51.1623 1.6384 50.9259 1.83953 50.6654 2.18685C50.3979 2.54355 50.0504 3.04187 49.6532 3.6114C49.5717 3.72817 49.4882 3.84793 49.4029 3.97008C48.9007 4.68875 48.3344 5.49142 47.7549 6.25817C47.1752 7.02516 46.5834 7.75471 46.0306 8.3276C45.4751 8.90317 44.9677 9.31101 44.5571 9.44786L44.5797 9.58706H45.4369C45.8788 9.58706 46.389 9.47617 47.1622 9.13453C47.9346 8.7932 48.9737 8.21967 50.4745 7.29065C52.9041 5.78657 52.8469 3.57227 52.5058 2.63882C52.469 2.45703 52.407 2.25157 52.3177 2.06613C52.2281 1.87996 52.1078 1.70727 51.9517 1.60253C51.7914 1.495 51.5977 1.46244 51.3775 1.55143Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M3.66146 1.65828C2.63289 0.286849 2.09003 1.37256 1.94717 2.08685C1.61384 2.99168 1.54717 5.17277 3.94717 6.65848C6.94717 8.51562 8.09 8.9442 8.94716 8.9442H9.80432C8.09003 8.37277 4.94717 3.37256 3.66146 1.65828Z\"\n        fill=\"#C44440\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M2.19526 1.55682C2.11133 1.73113 2.05226 1.92698 2.01746 2.101L2.01637 2.10646L2.01445 2.11168C1.69053 2.99096 1.61923 5.13335 3.98502 6.59789C5.48428 7.526 6.51662 8.09533 7.27985 8.43257C8.04238 8.76951 8.53221 8.87291 8.94741 8.87291H9.47346C9.09975 8.66479 8.68376 8.304 8.25093 7.85552C7.69221 7.27658 7.09647 6.5418 6.51544 5.77302C5.93422 5.004 5.36661 4.19947 4.86432 3.48061C4.77867 3.35804 4.69495 3.23799 4.6134 3.12106C4.21617 2.5515 3.87046 2.0558 3.60456 1.70127C3.35077 1.36288 3.13354 1.18544 2.95325 1.11259C2.77794 1.04175 2.63407 1.06813 2.51222 1.14988C2.38618 1.23443 2.27973 1.38138 2.19526 1.55682ZM3.00677 0.980138C3.22202 1.06711 3.45836 1.26824 3.71885 1.61556C3.98637 1.97226 4.33391 2.47058 4.73111 3.04011C4.81255 3.15688 4.89607 3.27664 4.98142 3.39879C5.48359 4.11746 6.04991 4.92013 6.6294 5.68688C7.20909 6.45387 7.80084 7.18342 8.35373 7.75631C8.9092 8.33188 9.4166 8.73972 9.82715 8.87657L9.80456 9.01577H8.94741C8.50545 9.01577 7.99528 8.90488 7.22211 8.56324C6.44964 8.22192 5.41056 7.64839 3.90982 6.71936C1.48017 5.21528 1.53743 3.00098 1.87848 2.06753C1.91524 1.88574 1.97726 1.68028 2.06655 1.49484C2.15618 1.30867 2.27652 1.13598 2.43263 1.03124C2.59291 0.92371 2.78654 0.891152 3.00677 0.980138Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M53.0082 1.65828C54.0368 0.286849 54.5796 1.37256 54.7225 2.08685C55.0558 2.99168 55.1225 5.17277 52.7225 6.65848C49.7225 8.51562 48.5797 8.9442 47.7225 8.9442H46.8654C48.5796 8.37277 51.7225 3.37256 53.0082 1.65828Z\"\n        fill=\"#C44440\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M54.4749 1.55682C54.5588 1.73113 54.6179 1.92698 54.6527 2.101L54.6538 2.10646L54.6557 2.11168C54.9796 2.99096 55.0509 5.13335 52.6851 6.59789C51.1859 7.526 50.1535 8.09533 49.3903 8.43257C48.6278 8.76951 48.138 8.87291 47.7228 8.87291H47.1967C47.5704 8.66479 47.9864 8.304 48.4192 7.85552C48.978 7.27658 49.5737 6.5418 50.1547 5.77302C50.7359 5.004 51.3036 4.19947 51.8059 3.48061C51.8915 3.35804 51.9752 3.23799 52.0568 3.12106C52.454 2.5515 52.7997 2.0558 53.0656 1.70127C53.3194 1.36288 53.5366 1.18544 53.7169 1.11259C53.8922 1.04175 54.0361 1.06813 54.158 1.14988C54.284 1.23443 54.3904 1.38138 54.4749 1.55682ZM53.6634 0.980138C53.4482 1.06711 53.2118 1.26824 52.9513 1.61556C52.6838 1.97226 52.3363 2.47058 51.9391 3.04011C51.8576 3.15688 51.7741 3.27664 51.6887 3.39879C51.1866 4.11746 50.6203 4.92013 50.0408 5.68688C49.4611 6.45387 48.8693 7.18342 48.3164 7.75631C47.761 8.33188 47.2536 8.73972 46.843 8.87657L46.8656 9.01577H47.7228C48.1647 9.01577 48.6749 8.90488 49.4481 8.56324C50.2205 8.22192 51.2596 7.64839 52.7603 6.71936C55.19 5.21528 55.1327 3.00098 54.7917 2.06753C54.7549 1.88574 54.6929 1.68028 54.6036 1.49484C54.514 1.30867 54.3937 1.13598 54.2375 1.03124C54.0773 0.92371 53.8836 0.891152 53.6634 0.980138Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M10.6353 5.71415C9.60675 4.91415 10.0163 3.47605 10.3496 2.85701L23.0639 5.71415C26.6068 7.6569 27.1115 13.4761 26.921 16.1429L24.921 31H15.4925L17.921 15.5714C15.6353 15.0476 10.5782 13.8857 8.63532 13.4286C6.20675 12.8571 3.49243 8 1.921 6.28571C0.349572 4.57143 -0.650428 2.14272 0.49243 1.42843C1.40672 0.857006 2.20672 1.85701 2.49243 2.42843C5.77814 7.71415 9.06386 8.99986 12.4924 9.14272C15.921 9.28558 16.4924 7.71415 16.2067 7.85701C15.921 7.99986 11.921 6.71415 10.6353 5.71415Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M46.0346 5.71415C47.0632 4.91415 46.6536 3.47605 46.3203 2.85701L33.606 5.71415C30.0632 7.6569 29.5584 13.4761 29.7489 16.1429L31.7489 31H41.1775L38.7489 15.5714C41.0346 15.0476 46.0917 13.8857 48.0346 13.4286C50.4632 12.8571 53.1775 8 54.7489 6.28571C56.3203 4.57143 57.3203 2.14272 56.1775 1.42843C55.2632 0.857006 54.4632 1.85701 54.1775 2.42843C50.8918 7.71415 47.6061 8.99986 44.1775 9.14272C40.7489 9.28558 40.1775 7.71415 40.4632 7.85701C40.7489 7.99986 44.7489 6.71415 46.0346 5.71415Z\"\n        fill=\"#CE635F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 57 / 31,\n  svg: OpenHands,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/photoFrame.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Photo Frame', 'sticker name', 'web-stories');\n\nfunction PhotoFrame({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M11.0345 8.1033C11.0345 9.53162 10.031 10.6895 8.79314 10.6895C7.55526 10.6895 6.55176 9.53162 6.55176 8.1033C6.55176 6.67497 7.55526 5.51709 8.79314 5.51709C10.031 5.51709 11.0345 6.67497 11.0345 8.1033Z\"\n        fill=\"#CE635E\"\n      />\n      <path\n        d=\"M8.79312 17.627C6.0345 15.0408 3.62071 27.4546 3.27588 27.9719H38.2759L37.5862 22.7998C37.2414 20.2136 36.7242 21.9377 34.8276 23.6619C32.9311 25.386 33.1035 20.2136 30.5173 19.0067C27.9311 17.7998 27.2414 21.4204 25.5173 21.9377C23.7931 22.4551 23.1035 17.627 21.5517 12.9721C20 8.31715 18.1035 14.6962 14.6552 21.4204C11.2069 28.1445 11.5517 20.2133 8.79312 17.627Z\"\n        fill=\"#AD3E3C\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M38.9655 2.41379H2.41379V27.5862H38.9655V2.41379ZM0 0V30H41.3793V0H0Z\"\n        fill=\"#573C5F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 30,\n  svg: PhotoFrame,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/womanReading.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Woman Reading', 'sticker name', 'web-stories');\n\nfunction Woman({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 43 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M20.9318 2.84781C20.9318 4.42062 19.6872 5.69563 18.1518 5.69563C16.6165 5.69563 15.3718 4.42062 15.3718 2.84781C15.3718 1.27501 16.6165 0 18.1518 0C19.6872 0 20.9318 1.27501 20.9318 2.84781Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M16.1855 5.01774C16.1855 6.59054 14.9409 7.86555 13.4055 7.86555C11.8701 7.86555 10.6255 6.59054 10.6255 5.01774C10.6255 3.44493 11.8701 2.16992 13.4055 2.16992C14.9409 2.16992 16.1855 3.44493 16.1855 5.01774Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M26.4919 13.0187C26.4919 14.5915 25.2472 15.8665 23.7119 15.8665C22.1765 15.8665 20.9319 14.5915 20.9319 13.0187C20.9319 11.4459 22.1765 10.1709 23.7119 10.1709C25.2472 10.1709 26.4919 11.4459 26.4919 13.0187Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M23.644 4.06803C23.644 5.64083 22.3994 6.91584 20.864 6.91584C19.3286 6.91584 18.084 5.64083 18.084 4.06803C18.084 2.49522 19.3286 1.22021 20.864 1.22021C22.3994 1.22021 23.644 2.49522 23.644 4.06803Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M28.6616 14.5104C28.6616 16.0832 27.4169 17.3582 25.8816 17.3582C24.3462 17.3582 23.1016 16.0832 23.1016 14.5104C23.1016 12.9376 24.3462 11.6626 25.8816 11.6626C27.4169 11.6626 28.6616 12.9376 28.6616 14.5104Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M25.4072 7.18717C25.4072 8.75997 24.1625 10.035 22.6272 10.035C21.0918 10.035 19.8472 8.75997 19.8472 7.18717C19.8472 5.61437 21.0918 4.33936 22.6272 4.33936C24.1625 4.33936 25.4072 5.61437 25.4072 7.18717Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M17.5415 8.40787C17.5415 9.98068 16.2968 11.2557 14.7615 11.2557C13.2261 11.2557 11.9814 9.98068 11.9814 8.40787C11.9814 6.83507 13.2261 5.56006 14.7615 5.56006C16.2968 5.56006 17.5415 6.83507 17.5415 8.40787Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M17.8127 3.66178C17.8127 5.23458 16.5681 6.50959 15.0327 6.50959C13.4973 6.50959 12.2527 5.23458 12.2527 3.66178C12.2527 2.08897 13.4973 0.813965 15.0327 0.813965C16.5681 0.813965 17.8127 2.08897 17.8127 3.66178Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M24.3222 11.2555C24.3222 12.8283 23.0776 14.1033 21.5422 14.1033C20.0069 14.1033 18.7622 12.8283 18.7622 11.2555C18.7622 9.68272 20.0069 8.40771 21.5422 8.40771C23.0776 8.40771 24.3222 9.68272 24.3222 11.2555Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M26.0849 9.35709C26.0849 10.9299 24.8403 12.2049 23.3049 12.2049C21.7696 12.2049 20.5249 10.9299 20.5249 9.35709C20.5249 7.78429 21.7696 6.50928 23.3049 6.50928C24.8403 6.50928 26.0849 7.78429 26.0849 9.35709Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M19.9826 15.4596C19.9826 17.0324 18.738 18.3075 17.2026 18.3075C15.6673 18.3075 14.4226 17.0324 14.4226 15.4596C14.4226 13.8868 15.6673 12.6118 17.2026 12.6118C18.738 12.6118 19.9826 13.8868 19.9826 15.4596Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M18.7622 12.4762C18.7622 14.049 17.5175 15.324 15.9822 15.324C14.4468 15.324 13.2021 14.049 13.2021 12.4762C13.2021 10.9034 14.4468 9.62842 15.9822 9.62842C17.5175 9.62842 18.7622 10.9034 18.7622 12.4762Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M5.95175 33.6516C5.95175 33.6516 0.179661 33.5237 0.00930023 35.8584C-0.205364 38.8002 3.35923 43.1193 10.4103 43.6834C15.5632 44.097 26.3339 43.8427 26.3339 43.8427C26.3339 43.8427 38.4624 41.3075 41.0531 38.0799C43.8625 34.5797 42.2415 29.4807 35.6277 29.7722C29.0139 30.0638 23.2554 33.6516 23.2554 33.6516H5.95175Z\"\n        fill=\"#558BBA\"\n      />\n      <path\n        d=\"M14.3671 17.8873C14.3671 17.8873 18.7213 16.0888 20.168 15.5231C21.6147 14.9591 25.9356 14.3569 26.945 14.7531C27.9559 15.1492 25.9103 33.3548 24.8645 34.174C23.8188 34.9932 13.4733 33.835 13.4733 33.835L14.3671 17.8873Z\"\n        fill=\"#4A7F9B\"\n      />\n      <path\n        d=\"M41.6203 50L0.325195 50L0.325195 43.8429L41.6203 43.8429V50Z\"\n        fill=\"#B4433B\"\n      />\n      <path\n        d=\"M21.3644 12.5439L21.9332 15L23.0429 14.862C23.0429 14.862 23.8869 21.4553 20.3899 22.8798C16.8073 24.3391 16.1949 20.8498 16.7796 16.6667L18.0654 15.8762L17.6534 13.6246L21.3644 12.5439Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        d=\"M14.9237 30.942C14.8343 31.9227 14.9908 33.9682 13.1204 34.4546C11.6301 34.8428 9.0664 34.5196 9.13508 30.8343C9.1862 28.144 11.0455 21.2186 11.7595 19.3664C13.6698 14.4057 15.0451 12.308 15.8581 13.0178C16.6712 13.726 18.6502 14.9793 18.318 16.0772C18.1423 16.6555 15.8358 15.0807 15.6377 14.6275C15.2655 13.7751 17.5449 16.8837 16.8149 17.8882C16.085 18.8927 13.7445 19.3664 13.7445 19.3664C13.7445 19.3664 15.1889 28.0156 14.9237 30.942Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        d=\"M5.06533 26.5117L12.7206 29.1037L21.9314 26.7697L27.9114 30.2715L15.8579 33.3566L10.1283 32.3076L5.06533 26.5117Z\"\n        fill=\"#DA9BB2\"\n      />\n      <path\n        d=\"M12.6877 4.08219C13.0489 2.23464 15.6507 1.04466 16.2354 1.03516C16.6625 1.04089 17.5954 1.08949 17.9102 1.23797C18.8229 1.19678 21.2203 2.09203 21.7036 3.60842C22.1869 5.1248 21.8969 7.84859 22.0522 8.25899C22.2074 8.66938 14.3752 10.2222 13.6304 8.94983C12.8857 7.67746 12.1664 6.74577 12.6877 4.08219Z\"\n        fill=\"#D898A9\"\n      />\n      <path\n        d=\"M15.4683 4.31558C16.1813 7.03303 14.5286 9.58253 13.6302 8.9503L14.4225 10.7133C15.191 13.3801 17.1273 14.7417 19.1174 14.363C21.0743 13.9907 22.3047 12.0573 22.0845 9.35725L21.8571 7.55434C21.8571 7.55434 21.8523 7.55909 21.8428 7.56543C21.8428 7.56543 18.6769 8.33709 17.4648 7.74131C16.1971 7.11701 15.5079 4.29181 15.4683 4.31558Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        opacity=\"0.34\"\n        d=\"M12.8651 29.1035L22.0775 26.7695L28.0559 30.2713L16.0025 33.3564L12.8651 29.1035Z\"\n        fill=\"#DA9BB2\"\n      />\n      <path\n        d=\"M5.20237 26.3628L6.4215 25.4949L12.6859 28.0151L20.5451 25.2295L27.2334 29.0688L27.0591 29.7723L21.9316 26.7696L12.7208 29.1036L5.20237 26.3628Z\"\n        fill=\"white\"\n      />\n      <g opacity=\"0.21\">\n        <path\n          opacity=\"0.21\"\n          d=\"M16.183 30.3029C16.5871 29.7579 18.1684 28.777 17.3492 28.72C16.8406 28.6836 16.1434 29.9623 15.3543 30.707C15.3559 30.707 15.7948 30.6927 16.183 30.3029Z\"\n          fill=\"#F78E66\"\n        />\n        <path\n          opacity=\"0.21\"\n          d=\"M9.33637 31.033C9.21595 30.808 7.70432 30.0617 7.70432 30.0617C7.70432 30.0617 5.61433 29.2853 5.65712 29.3122C6.37332 29.7717 8.01647 30.7066 9.20169 31.3879C9.00521 31.3103 9.72775 31.7666 9.33637 31.033Z\"\n          fill=\"#F78E66\"\n        />\n      </g>\n      <path\n        opacity=\"0.29\"\n        d=\"M26.5552 19.4728L25.69 22.1982C25.69 22.1982 25.2749 21.3283 25.3462 19.5758C25.4048 18.1133 25.9245 16.0376 25.9245 16.0376C25.9245 16.0376 25.6235 19.2098 25.9467 19.5758C26.1559 19.8119 26.5552 19.4728 26.5552 19.4728Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        d=\"M13.0874 28.7494L13.076 28.7447L5.76835 26.0945C5.74987 26.0883 5.73849 26.0647 5.7456 26.0444C5.75129 26.0224 5.77261 26.0114 5.7911 26.0193L13.0874 28.6647L20.8187 25.6304L23.082 26.9649C23.1005 26.9758 23.1062 26.9994 23.0977 27.0197C23.0877 27.0386 23.0664 27.0464 23.0479 27.037L20.813 25.7198L13.0874 28.7494Z\"\n        fill=\"#1E1E1E\"\n      />\n      <path\n        d=\"M17.7828 38.6758L19.2976 38.9277L18.5196 43.8889H16.3266L17.7828 38.6758Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        d=\"M23.4362 39.4475L24.9922 38.6362L27.3706 43.8889L26.0555 43.8715L23.4362 39.4475Z\"\n        fill=\"#CA553F\"\n      />\n      <path\n        d=\"M19.2976 38.9277L18.5196 43.8889C18.5196 43.8889 22.1434 43.7494 22.4286 44.2597C23.6091 46.3702 24.3681 48.9483 26.3266 48.3762C28.2834 47.8042 25.803 42.1974 25.2855 40.6438C24.6353 39.3311 19.2976 38.9277 19.2976 38.9277Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.9809 13.9605C16.3924 13.5558 15.7205 13.2012 15.2817 12.9987L15.3262 12.9023C15.769 13.1067 16.4464 13.4641 17.0411 13.873C17.3384 14.0775 17.6163 14.2957 17.8341 14.515C18.0509 14.7333 18.213 14.9575 18.2709 15.1744C18.3399 15.4333 18.3503 15.6376 18.3148 15.7922C18.2789 15.9485 18.1957 16.0543 18.0815 16.109C17.969 16.1627 17.8343 16.1632 17.7001 16.126C17.5654 16.0887 17.4273 16.0124 17.3036 15.9064L17.3727 15.8258C17.4863 15.9233 17.6109 15.9911 17.7284 16.0237C17.8463 16.0564 17.9532 16.0527 18.0357 16.0132C18.1163 15.9746 18.1815 15.8982 18.2113 15.7684C18.2415 15.637 18.2349 15.4514 18.1683 15.2018C18.1177 15.0118 17.9713 14.8038 17.7588 14.5898C17.5473 14.3769 17.2752 14.1629 16.9809 13.9605Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.7993 16.3914C16.5576 15.8036 16.1968 15.1932 15.9382 14.8109L16.0262 14.7515C16.2874 15.1377 16.6522 15.7545 16.8975 16.351C17.0201 16.6491 17.1139 16.9446 17.1491 17.2049C17.1842 17.4635 17.1628 17.6978 17.0422 17.8637L16.9563 17.8012C17.0527 17.6687 17.0777 17.4685 17.0439 17.2191C17.0104 16.9715 16.9203 16.6855 16.7993 16.3914Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.3457 17.4313C16.0771 17.0536 15.7745 16.751 15.7411 16.7176L15.8162 16.6426L15.8162 16.6426C15.8508 16.6772 16.1584 16.9847 16.4322 17.3698C16.569 17.5622 16.6988 17.776 16.7816 17.986C16.8639 18.1951 16.9024 18.4077 16.8466 18.5939C16.8242 18.6685 16.7901 18.7268 16.7435 18.7677C16.6964 18.809 16.6402 18.8291 16.58 18.8329C16.4632 18.8403 16.3295 18.7866 16.199 18.709C15.9356 18.5524 15.65 18.2764 15.4678 18.0715L15.5471 18.0009C15.7265 18.2028 16.0037 18.4693 16.2533 18.6178C16.3794 18.6928 16.4898 18.7323 16.5733 18.727C16.6133 18.7244 16.6463 18.7117 16.6735 18.6879C16.7012 18.6635 16.7266 18.6245 16.7449 18.5634C16.7907 18.4106 16.7615 18.2249 16.6828 18.0249C16.6045 17.8261 16.48 17.6202 16.3457 17.4313Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M30.1532 17.6293C29.7193 14.8629 27.3506 14.5781 26.2205 14.7815C22.7625 19.2566 25.7459 24.681 25.8137 27.3254C25.8815 29.9698 18.8976 30.58 18.2195 30.58C17.5415 30.58 17.2703 30.7157 18.0161 29.2917C18.6128 28.1526 17.6771 28.6363 17.1347 29.0205C16.5922 29.4274 15.9142 30.7835 13.4054 30.7835C10.8966 30.7835 10.761 31.7327 12.2527 32.004C13.7444 32.2752 23.8474 32.1396 27.6444 30.7835C31.4415 29.4274 30.6957 21.0874 30.1532 17.6293Z\"\n        fill=\"#CF6450\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.067 32.0129C14.1889 32.0185 14.2908 32.0281 14.3614 32.0458L14.3485 32.0972C14.2835 32.081 14.1862 32.0715 14.0645 32.066C13.9433 32.0604 13.7997 32.0588 13.6428 32.0578C13.6156 32.0576 13.588 32.0574 13.5601 32.0573C13.2663 32.0555 12.9346 32.0535 12.624 32.0302C12.2846 32.0047 11.9666 31.9537 11.7498 31.8474C11.641 31.7942 11.5554 31.7259 11.5062 31.6376C11.4567 31.5485 11.4462 31.4426 11.4816 31.3184L11.5327 31.3329C11.5004 31.4461 11.5111 31.5371 11.5526 31.6118C11.5946 31.6872 11.6699 31.7492 11.7731 31.7998C11.9801 31.9012 12.2892 31.9518 12.6279 31.9772C12.9366 32.0004 13.2665 32.0024 13.5606 32.0042C13.5885 32.0044 13.616 32.0045 13.6432 32.0047C13.8 32.0058 13.9445 32.0074 14.067 32.0129Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M19.2078 12.1054C18.4792 12.89 17.5045 12.6642 17.1099 12.4553L17.1595 12.3614C17.5333 12.5593 18.4482 12.7674 19.13 12.0332L19.2078 12.1054Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M17.6221 11.8391C17.5867 11.1667 17.5053 9.65251 17.4629 8.97342L17.5688 8.9668C17.6094 9.61626 17.6856 11.0281 17.7231 11.7389L18.4943 11.2087L18.5544 11.2962L17.6271 11.9338L17.6221 11.8391Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.3675 9.63643C15.3442 9.6197 15.3268 9.60722 15.3159 9.60179L15.3634 9.50684C15.3839 9.51708 15.4107 9.53562 15.4434 9.55817C15.6164 9.67767 15.9525 9.90979 16.3708 9.61698L16.4317 9.70395C15.941 10.0474 15.523 9.74785 15.3675 9.63643Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.6053 9.10567C18.582 9.08894 18.5646 9.07645 18.5537 9.07102L18.6012 8.97607C18.6217 8.98632 18.6485 9.00486 18.6812 9.02741C18.8542 9.14691 19.1903 9.37902 19.6086 9.08622L19.6695 9.17319C19.1788 9.51666 18.7608 9.21709 18.6053 9.10567Z\"\n        fill=\"black\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 43 / 50,\n  svg: Woman,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/art-books-gift-guide/womanReading02.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Woman Reading 02', 'sticker name', 'web-stories');\n\nfunction Woman02({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M21.2541 9.47732C21.2541 10.9739 20.0698 12.1871 18.6088 12.1871C17.1479 12.1871 15.9636 10.9739 15.9636 9.47732C15.9636 7.98077 17.1479 6.76758 18.6088 6.76758C20.0698 6.76758 21.2541 7.98077 21.2541 9.47732Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M24.9914 9.67946C24.9914 11.176 23.8071 12.3892 22.3461 12.3892C20.8852 12.3892 19.7009 11.176 19.7009 9.67946C19.7009 8.18292 20.8852 6.96973 22.3461 6.96973C23.8071 6.96973 24.9914 8.18292 24.9914 9.67946Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M23.5773 6.64919C23.5773 8.14574 22.393 9.35893 20.9321 9.35893C19.4712 9.35893 18.2869 8.14574 18.2869 6.64919C18.2869 5.15264 19.4712 3.93945 20.9321 3.93945C22.393 3.93945 23.5773 5.15264 23.5773 6.64919Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M19.5368 5.3362C19.5368 6.83275 18.3525 8.04594 16.8916 8.04594C15.4306 8.04594 14.2463 6.83275 14.2463 5.3362C14.2463 3.83966 15.4306 2.62646 16.8916 2.62646C18.3525 2.62646 19.5368 3.83966 19.5368 5.3362Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M13.7792 4.32595C13.7792 5.8225 12.5949 7.03569 11.134 7.03569C9.67308 7.03569 8.48877 5.8225 8.48877 4.32595C8.48877 2.8294 9.67308 1.61621 11.134 1.61621C12.5949 1.61621 13.7792 2.8294 13.7792 4.32595Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M17.7187 2.70974C17.7187 4.20628 16.5344 5.41948 15.0734 5.41948C13.6125 5.41948 12.4282 4.20628 12.4282 2.70974C12.4282 1.21319 13.6125 0 15.0734 0C16.5344 0 17.7187 1.21319 17.7187 2.70974Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M21.557 3.3157C21.557 4.81224 20.3727 6.02543 18.9118 6.02543C17.4509 6.02543 16.2666 4.81224 16.2666 3.3157C16.2666 1.81915 17.4509 0.605957 18.9118 0.605957C20.3727 0.605957 21.557 1.81915 21.557 3.3157Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M24.4862 4.72976C24.4862 6.2263 23.3019 7.4395 21.841 7.4395C20.3801 7.4395 19.1958 6.2263 19.1958 4.72976C19.1958 3.23321 20.3801 2.02002 21.841 2.02002C23.3019 2.02002 24.4862 3.23321 24.4862 4.72976Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M25.7995 7.65945C25.7995 9.15599 24.6152 10.3692 23.1543 10.3692C21.6933 10.3692 20.509 9.15599 20.509 7.65945C20.509 6.1629 21.6933 4.94971 23.1543 4.94971C24.6152 4.94971 25.7995 6.1629 25.7995 7.65945Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M22.3651 13.4168C22.3651 14.9133 21.1808 16.1265 19.7199 16.1265C18.259 16.1265 17.0747 14.9133 17.0747 13.4168C17.0747 11.9202 18.259 10.707 19.7199 10.707C21.1808 10.707 22.3651 11.9202 22.3651 13.4168Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M25.5976 13.4168C25.5976 14.9133 24.4133 16.1265 22.9523 16.1265C21.4914 16.1265 20.3071 14.9133 20.3071 13.4168C20.3071 11.9202 21.4914 10.707 22.9523 10.707C24.4133 10.707 25.5976 11.9202 25.5976 13.4168Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M21.456 15.5379C21.456 17.0344 20.2717 18.2476 18.8107 18.2476C17.3498 18.2476 16.1655 17.0344 16.1655 15.5379C16.1655 14.0413 17.3498 12.8281 18.8107 12.8281C20.2717 12.8281 21.456 14.0413 21.456 15.5379Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M26.0014 18.1643C26.0014 19.6609 24.8171 20.8741 23.3562 20.8741C21.8952 20.8741 20.7109 19.6609 20.7109 18.1643C20.7109 16.6678 21.8952 15.4546 23.3562 15.4546C24.8171 15.4546 26.0014 16.6678 26.0014 18.1643Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M26.4054 19.8816C26.4054 21.3782 25.2211 22.5914 23.7602 22.5914C22.2993 22.5914 21.115 21.3782 21.115 19.8816C21.115 18.3851 22.2993 17.1719 23.7602 17.1719C25.2211 17.1719 26.4054 18.3851 26.4054 19.8816Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M13.3752 15.4368C13.3752 16.9333 12.1909 18.1465 10.7299 18.1465C9.26902 18.1465 8.08472 16.9333 8.08472 15.4368C8.08472 13.9402 9.26902 12.7271 10.7299 12.7271C12.1909 12.7271 13.3752 13.9402 13.3752 15.4368Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M16.6076 6.54812C16.6076 8.04466 15.4233 9.25785 13.9624 9.25785C12.5014 9.25785 11.3171 8.04466 11.3171 6.54812C11.3171 5.05157 12.5014 3.83838 13.9624 3.83838C15.4233 3.83838 16.6076 5.05157 16.6076 6.54812Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M14.7895 9.47732C14.7895 10.9739 13.6052 12.1871 12.1442 12.1871C10.6833 12.1871 9.49902 10.9739 9.49902 9.47732C9.49902 7.98077 10.6833 6.76758 12.1442 6.76758C13.6052 6.76758 14.7895 7.98077 14.7895 9.47732Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M12.163 11.8006C12.163 13.2971 10.9787 14.5103 9.51778 14.5103C8.05686 14.5103 6.87256 13.2971 6.87256 11.8006C6.87256 10.304 8.05686 9.09082 9.51778 9.09082C10.9787 9.09082 12.163 10.304 12.163 11.8006Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M11.456 12.1038C11.456 13.6003 10.2717 14.8135 8.81075 14.8135C7.34983 14.8135 6.16553 13.6003 6.16553 12.1038C6.16553 10.6072 7.34983 9.39404 8.81075 9.39404C10.2717 9.39404 11.456 10.6072 11.456 12.1038Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M9.53678 17.1541C9.53678 18.6506 8.35247 19.8638 6.89156 19.8638C5.43064 19.8638 4.24634 18.6506 4.24634 17.1541C4.24634 15.6575 5.43064 14.4443 6.89156 14.4443C8.35247 14.4443 9.53678 15.6575 9.53678 17.1541Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M16.442 16.1058L16.2862 19.0739L12.7871 18.8958L13.0717 15.5303L16.442 16.1058Z\"\n        fill=\"#FF8B76\"\n      />\n      <path\n        opacity=\"0.24\"\n        d=\"M13.0717 15.3555L16.442 15.9294L16.3769 17.1805C15.7616 17.4969 15.1003 17.6225 14.4405 17.5032C13.8793 17.4015 13.3786 17.1344 12.9541 16.7402L13.0717 15.3555Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M20.2565 27.9295C20.2565 27.9295 23.154 36.0622 26.8057 35.1926C28.7897 34.7201 27.4192 30.4095 26.2666 27.9295C25.1156 25.4495 24.6198 19.8625 19.4514 18.5414C14.2831 17.2203 8.16093 17.2282 6.27546 17.9325C4.39 18.6368 3.0424 24.7349 0.155495 27.9295C-0.548771 32.5653 1.22478 34.3468 3.74932 32.8858C5.8351 31.6776 8.71417 27.0546 8.71417 27.0546L8.90812 37.0653L22.2939 40.717L20.2565 27.9295Z\"\n        fill=\"#3D789B\"\n      />\n      <path\n        d=\"M24.6197 14.6941L14.8856 17.4699L12.9286 17.2187L4.97656 13.0996V22.2728L12.3776 26.3637L14.0443 26.6162L23.3372 23.5354L24.6197 14.6941Z\"\n        fill=\"#AC3E3B\"\n      />\n      <path\n        d=\"M10.04 9.82772C10.571 9.25223 11.7522 10.2458 11.7522 10.2458C12.3436 11.0614 13.2736 8.24431 13.2736 8.24431C13.2736 8.24431 15.0668 9.02807 15.3689 6.53373C15.4134 6.52737 15.4579 6.51942 15.5024 6.51465C15.593 6.79604 15.7711 7.0822 16.124 7.19348C16.9062 7.43989 17.4388 7.68631 17.2162 8.30314C16.9952 8.91996 17.3004 9.88018 17.7472 10.5924C18.1907 11.2983 19.2686 11.6178 19.2686 11.6178C19.2781 11.6146 19.2861 11.613 19.2861 11.613C19.2861 11.613 20.8361 11.2696 21.003 12.0121C21.1652 12.7306 20.4482 13.4397 19.0015 12.8562C18.2607 15.1773 16.3371 16.7273 14.4405 16.4078C12.5105 16.0835 11.2832 13.9389 11.5185 11.4699C9.8047 11.3905 9.50901 10.4032 10.04 9.82772Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M23.9074 14.8978L22.6992 13.9217L14.6136 16.858L5.99075 12.1968L5.36279 13.3001L12.9285 17.2188L14.8855 17.47L23.9074 14.8978Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M19.4945 12.2379H20.407C20.4292 12.2379 20.4483 12.2189 20.4483 12.1966C20.4483 12.1744 20.4308 12.1553 20.407 12.1553H19.4945C19.4722 12.1553 19.4531 12.1744 19.4531 12.1966C19.4531 12.2189 19.4722 12.2379 19.4945 12.2379Z\"\n        fill=\"#C15849\"\n      />\n      <path\n        d=\"M11.2165 10.7146C11.2308 10.7146 11.2451 10.7067 11.2515 10.694C11.2626 10.6749 11.2547 10.6494 11.2356 10.6383L10.3151 10.1359C10.296 10.1248 10.2706 10.1328 10.2595 10.1518C10.2484 10.1709 10.2563 10.1964 10.2754 10.2075L11.1959 10.7099C11.2038 10.713 11.2102 10.7146 11.2165 10.7146Z\"\n        fill=\"#C15849\"\n      />\n      <path\n        opacity=\"0.24\"\n        d=\"M15.4007 6.59769C15.4452 6.58974 15.4897 6.58338 15.5342 6.57861C15.6248 6.86 15.8029 7.14616 16.1558 7.25744C16.938 7.50386 17.4706 7.75027 17.248 8.3671C17.0254 8.98393 17.3323 9.94415 17.779 10.6564C18.0508 11.0904 18.5627 11.3781 18.9173 11.5339C18.2162 11.2414 16.779 10.5212 16.5723 9.46245C16.2957 8.05392 15.2322 7.35919 15.2322 7.35919C15.3069 7.14934 15.3641 6.89816 15.4007 6.59769Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M4.9767 27.053L2.45215 25.2804C2.45215 25.2804 3.60314 23.3314 4.1373 22.7956L5.55378 21.4697C5.55378 21.4697 7.14832 19.9642 7.6793 19.6097C8.21028 19.2552 9.09578 19.4332 10.0242 19.6097C10.9526 19.7862 9.18481 21.3823 9.53932 21.5588C9.89384 21.7368 10.4248 21.8258 9.53932 22.3568C8.65382 22.8894 4.9767 27.053 4.9767 27.053Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M22.3437 40.5892C22.3437 40.5892 22.9432 44.292 22.4082 46.0156C21.8732 47.7408 20.7082 49.9168 18.7009 49.9962C15.893 50.1073 14.7648 47.8742 14.7648 47.8742C14.7648 47.8742 14.2664 48.936 12.7828 48.8026C11.2991 48.6693 9.07804 47.2853 9.07804 47.2853C9.07804 47.2853 4.57773 32.5187 5.90582 28.4604C6.66093 26.1543 8.21162 24.2592 11.6014 27.0447C14.9912 29.8301 22.3437 40.5892 22.3437 40.5892Z\"\n        fill=\"#A2A4AD\"\n      />\n      <path\n        d=\"M5.10221 22.1151C5.11333 22.1151 5.12605 22.1103 5.134 22.0992C5.15149 22.077 6.87797 19.9483 7.88589 19.5572C8.77456 19.2106 9.99868 19.6446 10.0098 19.6494C10.0321 19.6573 10.0543 19.6462 10.0623 19.6255C10.0702 19.6049 10.0591 19.581 10.0384 19.5731C9.98756 19.554 8.77298 19.1264 7.85727 19.4825C6.83028 19.8815 5.14354 21.9609 5.072 22.0483C5.05769 22.0658 5.06087 22.0913 5.07836 22.1056C5.08313 22.1119 5.09267 22.1151 5.10221 22.1151Z\"\n        fill=\"#C15849\"\n      />\n      <path\n        d=\"M7.56334 23.0627C7.57447 23.0627 7.58559 23.0579 7.59354 23.05C7.60626 23.0357 8.94643 21.6017 9.53624 21.6017C9.53783 21.6017 9.53783 21.6017 9.53942 21.6017C9.72224 21.6033 9.8526 21.6526 9.92573 21.7464C10.0291 21.8799 9.98455 22.0627 9.98455 22.0643C9.97978 22.0866 9.9925 22.1088 10.0148 22.1136C10.037 22.1184 10.0593 22.1057 10.064 22.0834C10.0656 22.0739 10.1181 21.8608 9.99091 21.6955C9.90188 21.581 9.75085 21.5206 9.53942 21.519C9.53783 21.519 9.53624 21.519 9.53465 21.519C8.90987 21.519 7.58877 22.9339 7.53313 22.9943C7.51723 23.0102 7.51882 23.0373 7.53472 23.0516C7.54267 23.0595 7.55221 23.0627 7.56334 23.0627Z\"\n        fill=\"#C15849\"\n      />\n      <path\n        d=\"M22.3778 25.2022C22.3778 25.2022 20.4911 23.0985 19.701 22.6263C18.9109 22.1541 17.0192 20.9119 16.0971 21.0883C15.175 21.2648 15.6679 21.6193 15.6679 21.6193C15.6679 21.6193 15.0288 21.6781 14.9048 21.8562C14.7808 22.0326 15.3102 22.5064 15.3102 22.5064C15.3102 22.5064 14.8587 22.3887 14.8857 22.7433C14.9127 23.0978 17.6841 24.906 18.5394 25.9091C19.3947 26.9139 20.5091 28.0303 20.5091 28.0303C20.5091 28.0303 23.1027 27.2689 22.3778 25.2022Z\"\n        fill=\"#CE635F\"\n      />\n      <path\n        d=\"M18.3197 22.5348C18.334 22.5348 18.3483 22.5269 18.3547 22.5141C18.3658 22.4951 18.3594 22.4696 18.3388 22.4585C18.2418 22.4029 15.9366 21.1199 14.881 21.8226C14.8619 21.8353 14.8572 21.8608 14.8699 21.8798C14.8826 21.8989 14.908 21.9037 14.9271 21.891C15.9414 21.2153 18.2768 22.5173 18.299 22.53C18.307 22.5316 18.3133 22.5348 18.3197 22.5348Z\"\n        fill=\"#C15849\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.812 10.4937L14.8931 10.5168L14.3074 12.5666L14.9932 12.3837L15.0149 12.4651L14.1855 12.6863L14.812 10.4937Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13.7257 10.2816C13.5229 10.2604 13.3447 10.2439 13.2869 10.2439V10.1597C13.3502 10.1597 13.534 10.1769 13.7344 10.1978C13.9363 10.2188 14.1587 10.2441 14.3019 10.261L14.292 10.3447C14.1491 10.3278 13.927 10.3026 13.7257 10.2816Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.2003 10.6859C15.9975 10.6647 15.8193 10.6482 15.7615 10.6482V10.564C15.8249 10.564 16.0086 10.5812 16.209 10.6021C16.4109 10.6231 16.6333 10.6484 16.7765 10.6653L16.7667 10.749C16.6237 10.7321 16.4016 10.7069 16.2003 10.6859Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.1505 14.6455C13.8404 14.5586 13.6155 14.3114 13.5027 14.1118L13.5761 14.0703C13.6821 14.2579 13.8916 14.4854 14.1732 14.5644C14.4507 14.6421 14.8102 14.5788 15.2267 14.1623L15.2863 14.2219C14.8544 14.6538 14.4647 14.7336 14.1505 14.6455Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M11.86 7.15407C11.86 8.65062 10.6757 9.86381 9.2148 9.86381C7.75389 9.86381 6.56958 8.65062 6.56958 7.15407C6.56958 5.65753 7.75389 4.44434 9.2148 4.44434C10.6757 4.44434 11.86 5.65753 11.86 7.15407Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M12.3651 10.0833C12.3651 11.5798 11.1808 12.793 9.71993 12.793C8.25901 12.793 7.07471 11.5798 7.07471 10.0833C7.07471 8.58673 8.25901 7.37354 9.71993 7.37354C11.1808 7.37354 12.3651 8.58673 12.3651 10.0833Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M23.2743 11.6995C23.2743 13.196 22.09 14.4092 20.6291 14.4092C19.1682 14.4092 17.9839 13.196 17.9839 11.6995C17.9839 10.2029 19.1682 8.98975 20.6291 8.98975C22.09 8.98975 23.2743 10.2029 23.2743 11.6995Z\"\n        fill=\"#573C5E\"\n      />\n      <path\n        d=\"M20.3449 6.14431C20.3449 7.64086 19.1606 8.85405 17.6997 8.85405C16.2387 8.85405 15.0544 7.64086 15.0544 6.14431C15.0544 4.64776 16.2387 3.43457 17.6997 3.43457C19.1606 3.43457 20.3449 4.64776 20.3449 6.14431Z\"\n        fill=\"#573C5E\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 50,\n  svg: Woman02,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/breadBun.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Bread bun', 'sticker name', 'web-stories');\n\nfunction BreadBun({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 93 67\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.4525 11.3725C38.0326 12.0523 37.9542 13.0756 37.2774 13.6582C36.5334 14.2986 34.9513 16.6873 37.073 20.2386C40.1165 25.3328 37.9667 29.4281 36.1996 30.9487C35.5226 31.5312 34.5037 31.4523 33.9237 30.7724C33.3437 30.0926 33.4223 29.0693 34.0993 28.4868C34.8439 27.8461 36.4264 25.4575 34.305 21.9066C31.2617 16.8128 33.4099 12.7176 35.1766 11.1967C35.8534 10.6141 36.8723 10.6928 37.4525 11.3725Z\"\n        fill=\"#2D2A35\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M51.4408 0.566085C52.0209 1.2458 51.9425 2.26912 51.2657 2.85173C50.5217 3.49218 48.9396 5.88086 51.0613 9.43218C54.1048 14.5264 51.955 18.6217 50.1879 20.1423C49.5109 20.7247 48.492 20.6458 47.912 19.966C47.3321 19.2861 47.4106 18.2628 48.0876 17.6804C48.8322 17.0397 50.4147 14.6511 48.2933 11.1001C45.25 6.0063 47.3982 1.9111 49.1649 0.390267C49.8417 -0.192345 50.8607 -0.113628 51.4408 0.566085Z\"\n        fill=\"#2D2A35\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M35.8687 37.124C39.0358 36.8469 42.1771 36.7419 45.155 36.7419C49.8483 36.7419 54.9548 37.0027 59.9323 37.7897C71.1426 39.5623 82.345 44.1237 85.9627 55.1458C87.1182 58.6663 85.7216 61.6568 84.2545 63.5998C84.2142 63.6532 84.1737 63.7059 84.1331 63.7581H90.886C91.7774 63.7581 92.5 64.4838 92.5 65.379C92.5 66.2743 91.7774 67 90.886 67H2.11404C1.22263 67 0.5 66.2743 0.5 65.379C0.5 64.4838 1.22263 63.7581 2.11404 63.7581H6.1768C6.13619 63.7059 6.09571 63.6532 6.0554 63.5998C4.58836 61.6568 3.19169 58.6663 4.34722 55.1458C6.44407 48.7573 11.1185 44.5209 16.8281 41.7648C22.5023 39.0259 29.2864 37.6998 35.8687 37.124ZM10.7148 63.7581H79.5951C79.7112 63.6666 79.8498 63.5535 80.004 63.4202C80.4921 62.998 81.1164 62.3905 81.6823 61.6409C82.8278 60.1239 83.5832 58.2514 82.8969 56.1607C80.3089 48.2757 72.9308 44.0117 63.9083 41.8692L70.5934 49.7382C71.1719 50.4193 71.0912 51.4424 70.4131 52.0235C69.735 52.6045 68.7162 52.5235 68.1376 51.8424L58.8433 40.902C54.2646 40.2187 49.5512 39.9839 45.155 39.9839C43.3227 39.9839 41.4341 40.0247 39.5222 40.1219L48.4822 49.6792C49.0932 50.331 49.0624 51.3568 48.4134 51.9705C47.7644 52.5842 46.7429 52.5533 46.1319 51.9015L35.3728 40.4251C30.0655 40.9385 24.821 41.9594 20.2843 43.7804L25.8786 49.6716C26.4938 50.3195 26.4695 51.3455 25.8244 51.9634C25.1794 52.5812 24.1577 52.5569 23.5425 51.909L17.1855 45.2145C12.5437 47.6849 9.0422 51.1971 7.41302 56.1607C6.72678 58.2514 7.48215 60.1239 8.6276 61.6409C9.19353 62.3905 9.81783 62.998 10.3059 63.4202C10.4601 63.5535 10.5987 63.6666 10.7148 63.7581Z\"\n        fill=\"#2D2A35\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 93 / 67,\n  svg: BreadBun,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/dough.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dough', 'sticker name', 'web-stories');\n\nfunction Dough({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 47 21\"\n      fill=\"none\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M16.6458 6.87563C16.8125 8.5 20.3125 9.5 23.3125 8.5M13.9792 20H33.3125C37.3125 20 45.3125 18.95 45.3125 14.7499C45.3125 9.49975 37.3125 2.28173 31.3125 2.28173C25.3125 2.28173 17.3125 -0.999746 9.3125 2.93842C5.09625 5.01396 1.3125 10.1547 1.3125 13.4361C1.3125 16.7174 2.64583 20 13.9792 20Z\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 47 / 21,\n  svg: Dough,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/flourBag.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Flour Bag', 'sticker name', 'web-stories');\n\nfunction FlourBag({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 37 39\"\n      fill=\"none\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M34.4269 3.61157C33.8305 2.73352 33.5322 1.85547 31.4445 1.85547M31.4445 1.85547H9.37429C7.39769 1.85547 5.79537 3.42793 5.79537 5.36766V6.5384M31.4445 1.85547C29.0585 1.85547 29.0585 4.97742 29.3568 6.5384M5.79537 6.5384L1.382 15.4712C1.14603 15.9488 1.02344 16.4727 1.02344 17.0035V33.1725C1.02344 35.7588 3.1599 37.8555 5.79537 37.8555H24.5848M5.79537 6.5384H29.3568M29.3568 6.5384L34.5899 15.9985C34.8744 16.5129 35.0234 17.0889 35.0234 17.6741V33.1725C35.0234 35.7588 32.887 37.8555 30.2515 37.8555H24.5848M29.3568 6.5384L24.9088 16.0868C24.6953 16.5451 24.5848 17.0431 24.5848 17.547V37.8555M13.5498 32.5872V17.075M13.5498 17.075C11.7603 16.4896 10.448 12.6262 13.5498 10.0506C17.1287 12.9774 14.7427 16.7823 13.5498 17.075ZM13.8506 18.9077C13.8415 17.0829 16.4899 14.4667 20.0842 15.7341C19.3559 19.8698 15.461 20.1033 14.166 19.4426C13.9647 19.3399 13.8517 19.1303 13.8506 18.9077ZM12.9739 18.9077C12.9831 17.0829 10.3347 14.4667 6.74032 15.7341C7.46869 19.8698 11.3636 20.1033 12.6586 19.4426C12.8599 19.3399 12.9728 19.1303 12.9739 18.9077ZM13.8506 23.5906C13.8415 21.7658 16.4899 19.1497 20.0842 20.417C19.3559 24.5528 15.461 24.7862 14.166 24.1255C13.9647 24.0228 13.8517 23.8133 13.8506 23.5906ZM12.9739 23.5906C12.9831 21.7658 10.3347 19.1497 6.74032 20.417C7.46869 24.5528 11.3636 24.7862 12.6586 24.1255C12.8599 24.0228 12.9728 23.8133 12.9739 23.5906ZM13.8506 28.2735C13.8415 26.4488 16.4899 23.8326 20.0842 25.1C19.3559 29.2357 15.461 29.4691 14.166 28.8084C13.9647 28.7057 13.8517 28.4962 13.8506 28.2735ZM12.9739 28.2735C12.9831 26.4488 10.3347 23.8326 6.74032 25.1C7.46869 29.2357 11.3636 29.4691 12.6586 28.8084C12.8599 28.7057 12.9728 28.4962 12.9739 28.2735Z\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 37 / 39,\n  svg: FlourBag,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/flourBowl.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Flour Bowl', 'sticker name', 'web-stories');\n\nfunction FlourBowl({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 43 31\"\n      fill=\"none\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.50086 8.73349H35.9135C34.0836 6.03019 29.4915 2.14453 20.9045 2.14453C12.2733 2.14453 8.05412 6.06523 6.50086 8.73349ZM3.99963 9.43366C5.04078 6.12089 9.90224 0.144531 20.9045 0.144531C31.8977 0.144531 37.2169 6.10393 38.5201 9.3621L39.0687 10.7335H3.59111L3.99963 9.43366Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.756545 11.857C0.5559 10.3321 1.74276 8.97889 3.2808 8.97889H39.8398C41.3334 8.97889 42.4843 10.2958 42.2843 11.7759C41.6071 16.7874 39.5029 21.6347 35.6248 25.0576C34.4329 26.1096 33.1199 27.1854 31.7782 28.1359C28.6647 30.3416 25.3545 30.8562 21.7359 30.8562C18.4001 30.8562 14.2604 30.4496 11.2573 28.4098C9.93125 27.5091 8.64744 26.4784 7.48349 25.459C3.49921 21.9695 1.42914 16.9687 0.756545 11.857ZM3.2808 10.9789C2.95096 10.9789 2.69642 11.2691 2.73945 11.5961C3.36822 16.3748 5.28112 20.8715 8.8012 23.9544C9.9229 24.9368 11.141 25.9131 12.3811 26.7554C14.851 28.433 18.4556 28.8562 21.7359 28.8562C25.1591 28.8562 27.9895 28.3689 30.6221 26.5039C31.8893 25.6062 33.1453 24.5784 34.3013 23.5581C37.7371 20.5256 39.6731 16.164 40.3023 11.5081C40.3401 11.228 40.1224 10.9789 39.8398 10.9789H3.2808Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.09757 14.1357C6.64795 14.0899 7.1313 14.4988 7.17716 15.0492C7.30922 16.634 8.91372 20.8175 14.6398 23.034C15.1548 23.2334 15.4107 23.8126 15.2113 24.3276C15.012 24.8427 14.4328 25.0986 13.9178 24.8992C7.47205 22.4041 5.3792 17.5569 5.18407 15.2153C5.1382 14.6649 5.54719 14.1816 6.09757 14.1357Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 43 / 31,\n  svg: FlourBowl,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as breadBun } from './breadBun';\nimport { default as yeastPackage } from './yeastPackage';\nimport { default as thermometer } from './thermometer';\nimport { default as jar } from './jar';\nimport { default as dough } from './dough';\nimport { default as flourBag } from './flourBag';\nimport { default as flourBowl } from './flourBowl';\n\nexport { breadBun, yeastPackage, thermometer, jar, dough, flourBag, flourBowl };\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/jar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Jar', 'sticker name', 'web-stories');\n\nfunction Jar({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 28 37\"\n      fill=\"none\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M3.02875 2C3.02875 0.895434 3.92418 0 5.02875 0H23.1744C24.2789 0 25.1744 0.89543 25.1744 2V5.51187C26.6949 6.66731 27.6016 8.47432 27.6016 10.4057V31C27.6016 34.3137 24.9153 37 21.6016 37H6.60156C3.28785 37 0.601562 34.3137 0.601562 31V10.4057C0.601562 8.47432 1.50823 6.66731 3.02875 5.51187V2ZM4.33134 7.03597C3.25004 7.81144 2.60156 9.0641 2.60156 10.4057V31C2.60156 33.2091 4.39242 35 6.60156 35H21.6016C23.8107 35 25.6016 33.2091 25.6016 31V10.4057C25.6016 9.0641 24.9531 7.81144 23.8718 7.03597H4.33134ZM23.1744 5.03597V2L5.02875 2V5.03597H23.1744Z\"\n        fill=\"white\"\n      />\n      <path d=\"M7.60156 13H20.6016V27H7.60156V13Z\" fill=\"white\" />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 37,\n  svg: Jar,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/thermometer.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Thermometer', 'sticker name', 'web-stories');\n\nfunction Thermometer({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.0943 45.6548C12.6419 49.0381 8.58462 50.5445 5.03213 49.0195C1.47964 47.4944 -0.222811 43.5155 1.22959 40.1322C2.14138 38.0082 4.07976 36.6239 6.27538 36.265C6.48111 36.2314 16.5651 12.468 20.4589 3.27544C21.2952 1.30095 23.5736 0.39225 25.5441 1.23812C27.5145 2.084 28.425 4.3617 27.5696 6.32801C23.5872 15.4825 13.3051 39.1608 13.4224 39.3331C14.6745 41.1721 15.0061 43.5309 14.0943 45.6548ZM5.82108 47.1817C8.44411 48.3077 11.2756 47.1507 12.2565 44.8659C12.8764 43.4218 12.6698 41.7814 11.7692 40.4587C11.492 40.0516 11.4447 39.6585 11.4319 39.5335C11.4147 39.365 11.4226 39.23 11.4283 39.161C11.4399 39.0199 11.4641 38.9093 11.474 38.8656C11.4969 38.7649 11.5239 38.679 11.5376 38.6366C11.5692 38.5384 11.6089 38.4295 11.6469 38.3288C11.7263 38.1185 11.8406 37.8314 11.981 37.4866C12.2639 36.7919 12.6758 35.8071 13.1814 34.6116C14.1938 32.2181 15.5947 28.951 17.1219 25.4073C20.177 18.3187 23.7442 10.1079 25.7357 5.53018C26.1463 4.58627 25.7131 3.48721 24.7551 3.07594C23.7971 2.66467 22.7019 3.10766 22.3005 4.05549C20.3534 8.65226 16.8579 16.8938 13.8231 23.9912C12.3059 27.5392 10.9023 30.8051 9.86435 33.1877C9.34595 34.3777 8.91563 35.3545 8.60691 36.0381C8.45366 36.3774 8.32424 36.6581 8.22646 36.8604C8.1796 36.9573 8.12806 37.0612 8.07865 37.1517C8.05727 37.1909 8.01365 37.2696 7.95635 37.3555C7.93151 37.3928 7.86799 37.4866 7.77368 37.5921C7.72761 37.6437 7.6352 37.7425 7.50119 37.8461C7.40174 37.9229 7.08417 38.1593 6.59804 38.2388C5.01884 38.497 3.68734 39.477 3.06741 40.9211C2.08656 43.2059 3.19805 46.0556 5.82108 47.1817Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M20.6794 10.0327C20.4616 10.5402 20.6964 11.1282 21.2038 11.3461L23.0417 12.135L23.8306 10.2972L21.9928 9.50828C21.4853 9.29041 20.8973 9.52521 20.6794 10.0327Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M19.2315 15.9406C18.724 15.7228 18.4892 15.1347 18.707 14.6272C18.9249 14.1197 19.5129 13.8849 20.0204 14.1028L21.8582 14.8918L21.0693 16.7296L19.2315 15.9406Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M16.7347 19.2218C16.5168 19.7293 16.7516 20.3173 17.2591 20.5352L19.0969 21.3241L19.8859 19.4863L18.048 18.6973C17.5406 18.4795 16.9525 18.7143 16.7347 19.2218Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M13.1844 27.4919C13.4023 26.9844 13.9903 26.7496 14.4978 26.9675C15.0053 27.1854 15.2401 27.7734 15.0222 28.2809L10.1205 39.6992C11.5306 40.7878 12.0842 42.7298 11.349 44.4425C10.4775 46.4725 8.12545 47.4117 6.09546 46.5402C4.06547 45.6688 3.12628 43.3167 3.99773 41.2867C4.73297 39.574 6.52216 38.6378 8.28264 38.9103L13.1844 27.4919Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 50,\n  svg: Thermometer,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/baking-bread-guide/yeastPackage.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yeast Package', 'sticker name', 'web-stories');\n\nfunction YeastPackage({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 34 42\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M7.59889 5L8.99889 2C13.9978 5 24.5 8.5 32 9.5C31.6024 10.4278 31.2486 11.3491 30.9349 12.2613M7.59889 5C10.8559 7.17421 20.0828 11.6704 30.9349 12.2613M7.59889 5C5.2445 10.0451 2.30835 16.9736 1.16508 32.5M30.9349 12.2613C26.5148 25.113 30.0331 36.1657 30.5 38.5C11.5 43.5 2.5 38.5 1 36.5C1 35.2902 1.05971 33.9311 1.16508 32.5M1.16508 32.5C4.61005 34.6667 15.1 38.1 29.5 34.5M15.5 22C13 20 8.5 20.9 10.5 24.5C10.5 27.7 10.5 29.8333 10.5 30.5L20.5 31.5L21 26.5C22.3333 24.6667 22 20 15.5 22Z\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 34 / 42,\n  svg: YeastPackage,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/beauty-quiz/greenBlob.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Blob', 'sticker name', 'web-stories');\n\nfunction GreenBlob({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M18.6648 0.413819C28.4376 -0.281989 39.8526 -0.359574 46.08 2.27109C53.3085 5.32466 54.6329 11.6826 55.3965 19.5262C56.818 34.1272 52.0334 30.0514 36.162 36.2538C20.2906 42.4563 2.48594 41.9093 1.06444 27.3084C-0.357053 12.7075 -1.59013 2.81963 18.6648 0.413819Z\"\n        fill=\"#397165\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 40,\n  svg: GreenBlob,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/beauty-quiz/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as beautyQuizGreenBlob } from './greenBlob';\nimport { default as beautyQuizTiltedGreenBlob } from './tiltedGreenBlob';\nimport { default as beautyQuizPinkBlob } from './pinkBlob';\n\nexport { beautyQuizGreenBlob, beautyQuizTiltedGreenBlob, beautyQuizPinkBlob };\n"
  },
  {
    "path": "packages/stickers/src/beauty-quiz/pinkBlob.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Pink Blob', 'sticker name', 'web-stories');\n\nfunction PinkBlob({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 49 36\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M16.0652 0.528706C24.6408 -0.081876 34.6577 -0.149955 40.1223 2.15848C46.4654 4.83803 47.6275 10.4172 48.2976 17.3001C49.545 30.1126 45.3465 26.536 31.4192 31.9788C17.4918 37.4215 1.86799 36.9415 0.620611 24.129C-0.62677 11.3166 -1.70881 2.63983 16.0652 0.528706Z\"\n        fill=\"#F8DFDC\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 49 / 36,\n  svg: PinkBlob,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/beauty-quiz/tiltedGreenBlob.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Tilted Green Blob', 'sticker name', 'web-stories');\n\nfunction TiltedGreenBlob({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 49\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M11.1754 3.67825C19.4854 1.13738 29.5191 -0.998853 36.1829 0.859482C43.9179 3.01657 47.9165 9.97117 52.0818 18.707C59.8356 34.9688 53.8011 31.2168 42.5634 41.0813C31.3258 50.9459 15.3782 53.5223 7.62443 37.2605C-0.129372 20.9987 -5.61884 10.0346 11.1754 3.67825Z\"\n        fill=\"#397165\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 49,\n  svg: TiltedGreenBlob,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/belly-fat-workout/blackSectionSeparator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Black Section Separator', 'sticker name', 'web-stories');\n\nfunction BlackSectionSeparator({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M0.385451 0H0.347076V40H57.4701V0H57.2931C48.5117 3.57576 38.9056 5.54593 28.8393 5.54593C18.773 5.54593 9.16686 3.57576 0.385451 0Z\"\n        fill=\"black\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 40,\n  svg: BlackSectionSeparator,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/belly-fat-workout/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as homeWorkoutSectionSeparator } from './blackSectionSeparator';\n\nexport { homeWorkoutSectionSeparator };\n"
  },
  {
    "path": "packages/stickers/src/buying-art-on-the-internet/blackInstagram.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Black Instagram', 'sticker name', 'web-stories');\n\nconst BlackInstagram = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 41\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M10.9091 4.59657C6.89247 4.59657 3.63636 7.85268 3.63636 11.8693V30.0511C3.63636 34.0677 6.89247 37.3238 10.9091 37.3238H29.0909C33.1075 37.3238 36.3636 34.0677 36.3636 30.0511V11.8693C36.3636 7.85268 33.1075 4.59657 29.0909 4.59657H10.9091ZM0 11.8693C0 5.84437 4.88417 0.960205 10.9091 0.960205H29.0909C35.1158 0.960205 40 5.84437 40 11.8693V30.0511C40 36.076 35.1158 40.9602 29.0909 40.9602H10.9091C4.88417 40.9602 0 36.076 0 30.0511V11.8693Z\"\n      fill=\"black\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M20.8788 15.486C19.7439 15.3177 18.5848 15.5116 17.5665 16.04C16.5481 16.5684 15.7223 17.4044 15.2065 18.4292C14.6907 19.454 14.5111 20.6154 14.6934 21.7481C14.8757 22.8808 15.4105 23.9272 16.2217 24.7385C17.033 25.5497 18.0794 26.0845 19.2121 26.2668C20.3448 26.4491 21.5062 26.2695 22.531 25.7537C23.5558 25.2379 24.3918 24.4121 24.9202 23.3937C25.4487 22.3754 25.6425 21.2163 25.4742 20.0814C25.3026 18.9238 24.7631 17.8521 23.9356 17.0246C23.1081 16.1971 22.0364 15.6577 20.8788 15.486ZM15.8917 12.8122C17.5889 11.9316 19.5207 11.6085 21.4122 11.889C23.3415 12.1751 25.1277 13.0741 26.5069 14.4533C27.8861 15.8325 28.7851 17.6187 29.0712 19.5481C29.3517 21.4395 29.0286 23.3713 28.148 25.0685C27.2673 26.7658 25.8738 28.1422 24.1658 29.0019C22.4578 29.8615 20.5223 30.1608 18.6344 29.857C16.7465 29.5532 15.0025 28.6619 13.6504 27.3098C12.2983 25.9577 11.407 24.2137 11.1032 22.3258C10.7994 20.4379 11.0987 18.5024 11.9583 16.7944C12.818 15.0864 14.1944 13.6929 15.8917 12.8122Z\"\n      fill=\"black\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M28.1818 10.9602C28.1818 9.95605 28.9958 9.14202 30 9.14202H30.0182C31.0223 9.14202 31.8364 9.95605 31.8364 10.9602C31.8364 11.9644 31.0223 12.7784 30.0182 12.7784H30C28.9958 12.7784 28.1818 11.9644 28.1818 10.9602Z\"\n      fill=\"black\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 40 / 41,\n  svg: BlackInstagram,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/buying-art-on-the-internet/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as artOnTheInternetInstagramBlack } from './blackInstagram';\n\nexport { artOnTheInternetInstagramBlack };\n"
  },
  {
    "path": "packages/stickers/src/celebrity-life-story/blackStar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Black Star', 'sticker name', 'web-stories');\n\nconst BlackStar = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M20 0L23.8268 10.7612L34.1421 5.85786L29.2388 16.1732L40 20L29.2388 23.8268L34.1421 34.1421L23.8268 29.2388L20 40L16.1732 29.2388L5.85786 34.1421L10.7612 23.8268L0 20L10.7612 16.1732L5.85786 5.85786L16.1732 10.7612L20 0Z\"\n      fill=\"#020202\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 40 / 40,\n  svg: BlackStar,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/celebrity-life-story/greenStar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Star', 'sticker name', 'web-stories');\n\nconst GreenStar = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M20 0L23.8268 10.7612L34.1421 5.85786L29.2388 16.1732L40 20L29.2388 23.8268L34.1421 34.1421L23.8268 29.2388L20 40L16.1732 29.2388L5.85786 34.1421L10.7612 23.8268L0 20L10.7612 16.1732L5.85786 5.85786L16.1732 10.7612L20 0Z\"\n      fill=\"#80FF44\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 40 / 40,\n  svg: GreenStar,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/celebrity-life-story/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as popularGreenStar } from './greenStar';\nimport { default as popularBlackStar } from './blackStar';\n\nexport { popularGreenStar, popularBlackStar };\n"
  },
  {
    "path": "packages/stickers/src/diy-home-office/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as atHomeOfficeArrow } from './offWhiteArrow';\n\nexport { atHomeOfficeArrow };\n"
  },
  {
    "path": "packages/stickers/src/diy-home-office/offWhiteArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Off-White Arrow', 'sticker name', 'web-stories');\n\nfunction OffWhiteArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 51 8\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M50.3536 4.35355C50.5488 4.15829 50.5488 3.84171 50.3536 3.64645L47.1716 0.464466C46.9763 0.269204 46.6597 0.269204 46.4645 0.464466C46.2692 0.659728 46.2692 0.976311 46.4645 1.17157L49.2929 4L46.4645 6.82843C46.2692 7.02369 46.2692 7.34027 46.4645 7.53553C46.6597 7.7308 46.9763 7.7308 47.1716 7.53553L50.3536 4.35355ZM0 4.5H50V3.5H0V4.5Z\"\n        fill=\"#F6F2ED\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 51 / 8,\n  svg: OffWhiteArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/facebookIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Facebook', 'sticker name', 'web-stories');\n\nfunction FacebookIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 13 25\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M7.84372 24.144V13.1313H11.407L11.9415 8.83951H7.84372V6.0976C7.84372 4.85581 8.1772 4.0074 9.89487 4.0074H12.0854V0.168259C11.7062 0.116122 10.4065 0 8.89214 0C5.73318 0 3.57239 2.00015 3.57239 5.6734V8.83951H0V13.1313H3.57239V24.144H7.84372Z\"\n        fill=\"#FAF4EA\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 13 / 25,\n  svg: FacebookIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as diyFacebookIcon } from './facebookIcon';\nimport { default as diyInstagramIcon } from './instagramIcon';\nimport { default as diyOrangeCross } from './orangeCross';\nimport { default as diyOrangeDot } from './orangeDot';\nimport { default as diyPlus } from './plus';\nimport { default as diyRightArrow } from './rightArrow';\nimport { default as diyTwitterIcon } from './twitterIcon';\nimport { default as diyYouTubeIcon } from './youTubeIcon';\n\nexport {\n  diyFacebookIcon,\n  diyInstagramIcon,\n  diyOrangeCross,\n  diyOrangeDot,\n  diyPlus,\n  diyRightArrow,\n  diyTwitterIcon,\n  diyYouTubeIcon,\n};\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/instagramIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Instagram', 'sticker name', 'web-stories');\n\nfunction InstagramIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 25 25\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M17.1462 24.8165H7.0347C3.16584 24.8165 0 21.6541 0 17.7895V7.02693C0 3.16234 3.16584 0 7.0347 0H17.1462C21.0151 0 24.1809 3.16234 24.1809 7.02693V17.7895C24.1809 21.6541 21.0151 24.8165 17.1462 24.8165ZM17.1462 22.9608C18.5211 22.9608 19.8182 22.4208 20.7993 21.4408C21.7804 20.4608 22.321 19.1651 22.321 17.7918V7.02693C22.321 5.65354 21.7804 4.35794 20.7993 3.3779C19.8182 2.39787 18.5211 1.85785 17.1462 1.85785H7.0347C5.65979 1.85785 4.36276 2.39787 3.38164 3.3779C2.40052 4.35794 1.8599 5.65354 1.8599 7.02693V17.7895C1.8599 19.1629 2.40052 20.4585 3.38164 21.4386C4.36276 22.4186 5.65979 22.9586 7.0347 22.9586H17.1462V22.9608Z\"\n        fill=\"#FAF4EA\"\n      />\n      <path\n        d=\"M18.7859 12.3116C18.7859 15.985 15.8047 18.9629 12.1272 18.9629C8.44966 18.9629 5.46848 15.985 5.46848 12.3116C5.46848 8.63814 8.44966 5.66028 12.1272 5.66028C15.8047 5.66028 18.7859 8.63814 18.7859 12.3116ZM12.0961 7.96257C9.68885 7.96257 7.73551 9.91151 7.73551 12.3183C7.73551 14.725 9.68663 16.6739 12.0961 16.6739C14.5055 16.6739 16.4566 14.725 16.4566 12.3183C16.4566 9.91151 14.5032 7.96257 12.0961 7.96257Z\"\n        fill=\"#FAF4EA\"\n      />\n      <path\n        d=\"M18.8929 7.13361C19.764 7.13361 20.4702 6.42818 20.4702 5.55798C20.4702 4.68779 19.764 3.98236 18.8929 3.98236C18.0217 3.98236 17.3155 4.68779 17.3155 5.55798C17.3155 6.42818 18.0217 7.13361 18.8929 7.13361Z\"\n        fill=\"#FAF4EA\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 25 / 25,\n  svg: InstagramIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/orangeCross.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cross', 'sticker name', 'web-stories');\n\nfunction OrangeCross({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 18 19\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M3.17925e-05 16.3241L15.5375 0.786638L17.0913 2.34039L1.55378 17.8779L3.17925e-05 16.3241Z\"\n        fill=\"#FF7324\"\n      />\n      <path\n        d=\"M1.55375 0.786621L9.79375 9.02662L8.24 10.5804L0 2.34037L1.55375 0.786621Z\"\n        fill=\"#FF7324\"\n      />\n      <path\n        d=\"M11.6948 10.9278L17.4843 16.7174L15.9306 18.2711L10.1411 12.4816L11.6948 10.9278Z\"\n        fill=\"#FF7324\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 18 / 19,\n  svg: OrangeCross,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/orangeDot.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dot', 'sticker name', 'web-stories');\n\nfunction OrangeDot({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 64 64\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <rect opacity=\"0.2\" width=\"64\" height=\"64\" rx=\"32\" fill=\"#F96302\" />\n      <rect\n        x=\"18.2861\"\n        y=\"18.2858\"\n        width=\"27.4286\"\n        height=\"27.4286\"\n        rx=\"13.7143\"\n        fill=\"#F96302\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 64 / 64,\n  svg: OrangeDot,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/plus.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Plus', 'sticker name', 'web-stories');\n\nfunction Plus({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 23 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M0.5 10.4H10.4V0.5L12.6 0.5V10.4H22.5V12.6H0.5L0.5 10.4Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M12.6 23.0566L12.6 14.8591H10.4L10.4 23.0566H12.6Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 23 / 24,\n  svg: Plus,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/rightArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\n\nfunction RightArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 18 17\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M16.8371 7.04675L10.4371 0.24707L8.83708 1.75308L13.4942 6.70109H0.0371094V8.89842H16.0371C16.4754 8.89842 16.8718 8.63788 17.0457 8.23551C17.2195 7.83314 17.1376 7.36593 16.8371 7.04675Z\"\n        fill=\"#F9F3E9\"\n      />\n      <path\n        d=\"M14.1383 9.78401L8.85498 15.3973L10.3635 17L15.6468 11.3867L14.1383 9.78401Z\"\n        fill=\"#F9F3E9\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 18 / 17,\n  svg: RightArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/twitterIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Twitter', 'sticker name', 'web-stories');\n\nfunction TwitterIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 27 21\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M26.368 2.46776C25.3977 2.88621 24.3546 3.16946 23.2608 3.29607C24.3767 2.64372 25.2345 1.6137 25.6403 0.384112C24.595 0.987104 23.4372 1.42486 22.2045 1.66091C21.2166 0.639472 19.8118 0 18.2549 0C15.269 0 12.8455 2.35617 12.8455 5.26384C12.8455 5.67585 12.894 6.07713 12.9866 6.46339C8.49015 6.24451 4.50309 4.14798 1.83475 0.963499C1.36945 1.74031 1.10262 2.64587 1.10262 3.60937C1.10262 5.43551 2.05748 7.04707 3.50853 7.99125C2.62202 7.96336 1.78844 7.72731 1.05851 7.33247C1.05851 7.35393 1.05851 7.37538 1.05851 7.39899C1.05851 9.95044 2.92414 12.077 5.39841 12.5598C4.94413 12.68 4.4656 12.7444 3.97383 12.7444C3.6254 12.7444 3.2858 12.7122 2.95501 12.65C3.64305 14.7422 5.64099 16.2636 8.00941 16.3065C6.15701 17.7185 3.82608 18.5597 1.29006 18.5597C0.853426 18.5597 0.423405 18.534 0 18.4867C2.39488 19.9803 5.23743 20.8515 8.29168 20.8515C18.2417 20.8515 23.6842 12.8302 23.6842 5.87327C23.6842 5.64581 23.6798 5.41834 23.6688 5.19303C24.7251 4.45055 25.6425 3.52353 26.368 2.46776Z\"\n        fill=\"#FAF4EA\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 27 / 21,\n  svg: TwitterIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/doers-get-more-done/youTubeIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('YouTube', 'sticker name', 'web-stories');\n\nfunction YouTubeIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 19\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M20.2878 0H7.17684C0 0 0 2.00053 0 6.92327V11.7335C0 16.4156 1.01677 18.6567 7.17684 18.6567H20.2898C25.8533 18.6567 27.4666 17.345 27.4666 11.7335V6.92327C27.4647 1.74246 27.1931 0 20.2878 0ZM10.9268 12.985V5.43306L18.3296 9.19739L10.9268 12.985Z\"\n        fill=\"#FAF4EA\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 19,\n  svg: YouTubeIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/floralFrame.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Floral Frame', 'sticker name', 'web-stories');\n\nfunction FloralFrame({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 270 500\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M253.569 486.199C253.387 486.102 253.336 485.99 253.358 485.692C253.387 485.178 253.125 484.823 252.914 484.011C252.397 482.038 249.486 481.753 248.569 483.58C248.212 484.295 248.103 484.351 247.07 484.344C246.022 484.344 246.065 484.212 245.483 482.725L245.134 482.864C244.02 483.316 243.998 483.865 243.54 482.635C243.285 481.954 243.263 481.829 243.387 481.607C243.736 480.968 243.685 480.023 243.292 479.988C242.718 479.94 242.637 480.1 242.703 481.142C242.768 482.135 242.674 482.267 241.764 482.406C240.716 482.559 239.515 481.329 240.512 481.114C241.262 480.954 241.662 479.995 241.153 479.572C240.272 478.842 239.435 480.725 240.047 482.079C240.36 482.774 241.917 483.066 242.557 482.559C242.943 482.246 243.067 482.302 243.292 482.892C243.598 483.691 243.584 483.712 242.703 483.955C240.454 484.573 243.984 484.851 242.703 486.032C241.852 486.81 241.182 487.595 241.051 487.949C240.971 488.158 240.862 488.359 240.804 488.394C239.799 489.096 239.435 493.903 240.316 494.827C240.716 495.243 240.745 495.327 240.753 495.882C240.753 496.626 240.847 496.633 241.109 497.154C241.706 498.349 243.256 499.523 244.697 499.87C247.506 500.551 251.24 498.453 251.524 496.042C251.567 495.681 251.684 495.32 251.807 495.174C252.128 494.778 252.033 492.694 251.633 491.596C250.134 487.421 244.755 487.157 243.307 491.18C242.528 493.333 243.664 495.785 245.592 496.14C246.043 496.223 246.073 496.362 245.767 497.029C245.476 497.675 245.338 497.696 244.872 497.168C244.348 496.57 243.882 496.355 243.54 496.529C242.703 496.959 243.555 498.244 244.639 498.168C245.148 498.133 245.156 498.14 245.228 498.939C245.301 499.71 245.33 499.696 244.268 499.307C242.47 498.647 240.927 497.001 241.08 495.917C241.167 495.334 241.073 495.028 240.651 494.465C239.697 493.208 240.127 489.742 241.459 487.845C242.077 486.963 243.169 486.025 243.387 486.178C243.875 486.525 243.889 486.893 243.424 487.387C242.761 488.102 242.688 489.262 243.307 489.262C243.642 489.262 244.129 488.47 244.188 487.817C244.26 487.039 244.406 486.873 245.127 486.741C245.665 486.643 245.709 486.366 245.301 485.685C244.959 485.108 245.017 484.969 245.672 484.872C246.32 484.775 246.509 484.921 246.866 485.789C247.164 486.511 247.164 486.511 247.994 486.463L248.685 486.421C248.372 484.4 248.256 484.448 249.813 484.844C250.832 485.101 252.353 485.81 252.732 486.192C252.943 486.414 251.975 487.414 251.349 487.616C250.374 487.935 249.573 486.616 250.381 486.018C250.709 485.775 251 485.956 251.211 486.511C251.385 486.984 251.611 486.991 251.662 486.525C251.727 485.886 250.767 485.31 250.134 485.615C249.588 485.872 249.522 486.532 249.944 487.477C250.41 488.505 252.259 488.193 252.914 486.984C253.154 486.546 253.365 486.449 253.51 486.713C253.649 486.956 254.5 487.616 254.595 487.546C254.857 487.387 254.216 486.539 253.569 486.199ZM240.367 480.204C240.745 479.815 241.175 480.072 240.847 480.489C240.643 480.746 240.178 480.794 240.178 480.558C240.178 480.468 240.265 480.308 240.367 480.204ZM243.052 481.35C242.943 481.225 242.958 480.628 243.074 480.544C243.125 480.509 243.191 480.516 243.22 480.572C243.3 480.711 243.14 481.447 243.052 481.35ZM245.825 494.465C245.49 494.021 245.49 494.021 245.956 493.937C246.779 493.798 247.019 493.639 247.019 493.882C247.019 493.979 247.157 494.285 247.324 494.57C247.717 495.23 247.725 495.202 247.142 495.417C246.866 495.521 246.575 495.632 246.487 495.667C246.327 495.737 246.087 495.313 246.087 494.966C246.087 494.889 245.971 494.653 245.825 494.465ZM247.121 492.882C247.121 491.652 248.132 490.207 248.613 490.749C249.006 491.194 248.496 492.229 247.535 492.958C247.201 493.215 247.121 493.201 247.121 492.882ZM246.247 496.619C246.349 495.848 246.393 496.195 247.31 495.723C247.725 495.507 248.263 495.507 248.263 495.723C248.263 496.133 249.624 496.334 249.857 495.952C250.221 495.368 249.53 494.827 248.598 494.959C248.038 495.042 247.994 495.021 247.615 494.354C247.23 493.687 247.252 493.597 247.848 493.159C248.809 492.451 249.326 491.2 248.933 490.527C248.314 489.457 246.582 491.346 246.859 492.791C246.975 493.396 245.934 493.868 245.017 493.625C243.678 493.271 245.971 494.604 245.854 495.514C245.811 495.82 245.396 495.924 245.156 495.688C245.068 495.598 244.894 495.494 244.784 495.452C242.164 494.535 243.358 489.54 246.378 488.776C249.355 488.019 252.703 492.145 251.436 495.014C251.116 495.751 251.305 497.779 247.79 499.293C247.244 499.53 245.65 499.717 245.614 499.557C245.141 497.716 246.094 497.772 246.247 496.619ZM249.457 495.619C249.457 495.876 248.976 495.883 248.678 495.619C248.052 495.077 249.457 495.278 249.457 495.619ZM243.838 496.931C244.137 496.89 244.843 497.439 244.843 497.703C244.843 498.237 242.812 497.07 243.838 496.931ZM242.95 484.962C242.55 484.504 242.572 484.233 242.994 484.233C243.591 484.233 243.525 483.67 244.028 484.351C244.413 484.872 244.399 485.032 243.962 485.24C243.453 485.476 243.373 485.456 242.95 484.962ZM243.744 488.45C243.242 489.13 242.95 488.7 243.409 487.949C243.809 487.303 244.013 487.234 244.013 487.748C244.013 487.942 243.904 488.241 243.744 488.45ZM244.923 486.553C244.268 486.914 243.707 486.623 243.707 485.921C243.707 485.636 244.493 485.219 244.704 485.393C245.119 485.726 245.243 486.372 244.923 486.553ZM244.966 484.775C244.617 484.858 244.006 484.018 244.253 483.788C244.413 483.642 245.257 483.253 245.294 483.316C246.124 484.726 246.022 484.525 244.966 484.775ZM248.241 485.594C248.19 486.261 247.463 486.359 247.179 485.733C246.728 484.754 246.451 484.587 247.557 484.587C248.234 484.587 248.307 484.698 248.241 485.594ZM252.099 485.337C251.407 484.941 249.544 484.351 248.991 484.351C248.54 484.351 248.583 483.997 249.093 483.497C250.563 482.072 252.564 483.038 252.979 485.372C253.059 485.851 252.986 485.851 252.099 485.337Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M26.7647 485.664C26.3426 485.435 26.3353 485.275 26.7283 484.9C27.3251 484.33 28.0747 484.212 28.0747 484.691C28.0747 485.205 28.817 485.511 29.1081 485.115C29.2901 484.872 29.1591 484.393 28.8461 484.163C28.4604 483.872 28.5332 483.608 29.1591 483.045C30.3599 481.961 30.258 479.544 29.0135 479.544C28.2057 479.544 28.3512 481.079 29.1736 481.253C29.7849 481.385 29.7558 481.718 29.0644 482.475C28.8607 482.705 28.5477 483.107 28.3803 483.385C28.1475 483.76 28.0019 483.886 27.7908 483.886C27.4197 483.886 26.5027 484.49 26.2771 484.886C26.0078 485.351 25.1345 485.025 25.2436 484.497C25.2655 484.386 25.2946 484.094 25.3091 483.837C25.331 483.399 25.3601 483.365 25.8258 483.191C26.852 482.802 27.4852 481.697 27.2086 480.787C26.7137 479.162 24.8434 480.127 24.8215 482.017L24.8142 482.85C22.6164 482.441 23.4169 481.836 23.4169 484.351L22.7182 484.282C22.0196 484.212 21.5538 483.886 21.5538 483.455C21.5538 483.198 20.7751 482.621 20.1055 482.371C18.3443 481.718 16.4958 483.184 16.4812 485.254C16.4739 485.706 16.4375 485.775 15.9572 486.164C15.6734 486.4 15.4114 486.657 15.3823 486.734C15.3313 486.88 13.7084 486.803 13.49 486.65C13.4464 486.616 12.9879 486.491 12.4857 486.359C11.9763 486.234 11.1757 485.963 10.7099 485.754L9.85845 485.386L9.91667 484.719C10.0404 483.288 8.78134 482.329 7.50773 482.885L7.0274 483.094L6.59073 482.545C6.19773 482.045 6.03762 481.656 6.23412 481.656C6.27779 481.656 6.33601 481.551 6.36512 481.419C6.48157 480.926 6.99101 481.1 7.19479 481.69C7.31123 482.045 7.55867 481.899 7.84251 481.315C8.11178 480.746 8.11906 480.746 8.49751 480.843C9.40723 481.079 9.85845 480.822 9.85845 480.072C9.85845 479.704 9.82206 479.655 9.47273 479.544C8.94873 479.377 8.94145 479.377 8.49751 479.724C8.03901 480.086 7.93712 480.037 7.66056 479.342C7.43495 478.759 7.2894 478.787 7.04923 479.454C6.77995 480.218 6.64168 480.294 6.31418 479.884C6.15407 479.683 6.02307 479.474 6.02307 479.412C6.02307 479.162 5.73924 479.328 5.3899 479.794L5.01874 480.287C4.19635 479.009 4.05807 478.814 5.20796 477.953L4.77129 477.015C4.53113 476.501 4.30552 475.862 4.27641 475.605C4.20363 475.035 4.07263 475.022 3.60685 475.522C3.19202 475.966 3.18474 475.959 2.96641 474.827C2.6098 472.917 2.76263 470.346 3.22113 470.569C3.30847 470.61 3.54863 470.68 3.74513 470.722L4.10902 470.798L4.17452 471.791C4.24002 472.785 4.33463 473.389 4.46563 473.611C4.50202 473.674 4.66941 474.098 4.82952 474.549C6.02307 477.856 9.13067 479.523 11.9326 478.363C13.0388 477.904 14.407 475.591 13.9995 474.855C13.8612 474.598 13.5847 474.806 13.5774 475.167C13.5701 477.272 11.1102 478.898 8.96328 478.196C7.29668 477.654 5.0624 475.355 5.07696 474.188C5.07696 474.118 5.00418 473.882 4.90229 473.667C4.70579 473.215 4.5748 472.59 4.48746 471.687L4.42924 471.055C5.59368 471.784 5.73196 472 6.95462 473.459L6.79451 473.841C6.5034 474.542 6.65623 475.07 7.15112 475.07C7.55868 475.07 7.70423 474.744 7.6169 474.007C7.5514 473.452 7.5514 473.431 7.84251 473.361C8.00262 473.32 8.19912 473.264 8.2719 473.243C8.70128 473.09 9.72745 473.771 10.0113 474.389C10.4989 475.445 9.57461 476.904 8.81773 476.272C8.26462 475.807 8.50478 474.952 9.18889 474.952C9.56734 474.952 9.62556 474.834 9.37811 474.598C9.13067 474.362 8.42473 474.674 8.22823 475.105C7.58779 476.501 9.42178 477.453 10.2005 476.126C11.1976 474.424 9.50911 472.298 7.73334 473.014C7.4859 473.111 7.28212 473.139 7.20934 473.076C7.15112 473.021 6.81634 472.667 6.48157 472.291C5.82657 471.569 5.51363 471.291 4.89502 470.895C4.48018 470.631 4.36374 470.221 4.56752 469.784C4.70579 469.485 5.10607 469.547 5.4554 469.916C5.79746 470.277 6.12496 470.214 6.12496 469.784C6.12496 469.471 6.3724 468.735 6.48157 468.735C6.5034 468.735 6.64896 468.811 6.81634 468.908C7.46406 469.291 8.08267 468.901 7.7479 468.325C7.58051 468.033 7.38401 467.978 6.74357 468.026C5.88479 468.089 5.70285 466.866 6.46701 466.165C9.68378 463.198 14.7491 466.248 12.3474 469.707C12.0054 470.201 11.7798 470.131 12.0491 469.617C12.8569 468.061 10.9647 466.581 9.6765 467.769C7.78429 469.506 10.2514 472.965 12.5949 471.854C16.1173 470.18 15.3459 464.157 11.4159 462.649C10.5498 462.316 7.82795 462.406 7.62417 462.775C7.59506 462.83 7.50045 462.872 7.40584 462.872C7.14384 462.872 6.23412 463.434 5.72468 463.914C5.04057 464.553 5.02602 464.56 4.65485 464.261C3.62869 463.434 1.88202 464.338 1.88202 465.699C1.88202 466.686 2.40602 467.686 2.92274 467.686C3.07558 467.686 3.12652 467.769 3.12652 468.005C3.12652 468.575 3.0028 468.665 2.31869 468.596C1.59819 468.526 1.45264 468.617 1.45264 469.117C1.45264 469.297 1.39442 469.68 1.32892 469.971C1.18336 470.596 1.21247 470.652 1.6273 470.513C1.80197 470.458 2.05669 470.437 2.18769 470.464L2.43513 470.52L2.44241 472.417C2.44969 473.785 2.50063 474.542 2.62436 475.119C2.90091 476.397 2.15858 476.571 1.30708 475.424C0.950472 474.952 0.95775 474.917 1.45992 474.66C2.3478 474.209 2.32597 472.944 1.43808 472.965C0.914083 472.979 0.200863 475.188 0.717584 475.188C0.783084 475.188 0.834028 475.258 0.834028 475.348C0.834028 475.945 1.83108 476.633 2.53702 476.522C2.89363 476.466 3.01736 476.487 3.04647 476.612C3.22113 477.328 3.49041 478.12 3.65052 478.377C3.94163 478.849 3.88341 479.113 3.37397 479.704C2.82086 480.343 2.82086 480.343 3.22841 480.76C3.40308 480.94 3.64324 481.315 3.75241 481.6C4.00713 482.253 4.2473 482.274 4.55296 481.649C4.86591 481.017 4.95324 480.982 5.30257 481.364C5.73924 481.836 5.36807 483.066 4.82224 482.962C3.74513 482.76 2.93002 483.392 3.18474 484.219C3.42491 484.983 4.21091 484.921 4.78585 484.101C5.14974 483.58 5.26618 483.608 5.74651 484.358C6.1104 484.928 6.16135 484.928 6.4379 484.372C6.82362 483.594 7.64601 483.58 7.68967 484.344C7.69695 484.448 7.71151 484.608 7.72606 484.705C7.74062 484.802 7.75517 485.053 7.76973 485.261C7.79884 485.956 8.59939 486.31 9.26167 485.921C9.57461 485.733 9.60372 485.74 10.3169 486.15C11.5542 486.852 14.5162 487.519 15.1057 487.227C15.2076 487.178 15.3823 487.144 15.4914 487.164C15.6079 487.178 15.8335 487.018 16.0373 486.761C16.4303 486.275 16.5831 486.275 16.7214 486.768C17.0707 488.012 18.9556 488.72 19.7198 487.901C20.6805 486.873 19.9018 485.122 18.7519 485.713C18.2788 485.956 17.944 486.609 18.1478 486.887C18.3516 487.164 18.5554 487.088 18.5626 486.734C18.5699 486.032 19.1085 485.775 19.5597 486.254C19.8217 486.539 19.8581 486.824 19.6761 487.206C19.1958 488.22 17.9659 487.998 17.2308 486.761L16.8815 486.178L17.2235 485.851C17.4128 485.671 17.6602 485.525 17.7839 485.525C17.9004 485.525 18.0459 485.476 18.0969 485.421C18.3734 485.129 21.1608 484.476 21.5029 484.622C21.6702 484.698 21.5829 485.393 21.3282 485.942L21.1462 486.303L22.1287 486.275C23.2641 486.24 23.3223 486.206 23.5042 485.414C23.6498 484.768 23.708 484.74 24.3703 484.948C24.8215 485.087 24.8579 485.282 24.545 485.865C24.2975 486.331 24.3485 486.428 24.9962 486.713C25.3819 486.887 25.4401 486.956 25.5056 487.38C25.6366 488.248 25.986 488.79 26.5682 489.04C27.3906 489.394 27.3251 488.331 26.459 487.352C25.8622 486.678 25.7676 486.24 26.1461 485.886C26.4299 485.615 27.6744 486.852 28.4822 488.206C30.6728 491.867 29.8723 496.911 26.8302 498.64C25.8258 499.21 24.8797 499.432 24.8506 499.113C24.7269 497.668 24.9525 497.001 25.4911 497.237C26.6846 497.765 28.3367 496.674 28.3367 495.361C28.3367 493.493 26.0369 493.798 25.1126 495.799C24.7706 496.542 24.7342 496.556 24.0355 496.126C23.4242 495.744 23.4315 495.757 23.7954 494.903C24.0501 494.299 24.1229 494.222 24.545 494.09C27.7181 493.083 26.1097 488.311 22.5945 488.304C16.3648 488.297 16.6268 498.321 22.8929 499.682C23.8681 499.898 24.5304 499.842 25.986 499.425C30.9858 498.001 31.5316 488.241 26.7647 485.664ZM29.1372 480.766C28.8971 480.572 28.8316 480.197 29.0135 480.065C29.1809 479.947 29.5229 480.364 29.5229 480.676C29.5302 480.996 29.4502 481.017 29.1372 480.766ZM28.8025 484.65C28.8025 484.844 28.5332 484.879 28.4313 484.691C28.2857 484.42 28.8025 484.177 28.8025 484.65ZM8.74495 479.947C9.23984 479.579 9.75656 479.975 9.34173 480.398C9.23984 480.502 9.087 480.586 9.00695 480.579C8.44656 480.53 8.33012 480.252 8.74495 479.947ZM7.70423 480.058C7.86434 480.336 7.86434 480.377 7.66056 480.766C7.41312 481.246 7.39129 481.253 7.04923 480.947L6.78723 480.718C7.10018 480.086 7.34762 479.447 7.70423 480.058ZM7.3549 474.146C7.52229 474.494 7.26029 474.848 7.04923 474.563C6.79451 474.216 7.10745 473.618 7.3549 474.146ZM7.43495 468.596C7.45679 468.679 7.39856 468.742 7.2894 468.735C7.02012 468.721 6.83818 468.624 6.83818 468.492C6.83818 468.325 7.38401 468.422 7.43495 468.596ZM1.29253 473.604C1.73647 473.271 1.94752 473.695 1.55453 474.139C1.26342 474.466 1.03781 474.438 1.03781 474.084C1.03781 473.903 1.13242 473.722 1.29253 473.604ZM6.06674 468.7C5.99396 468.818 5.90662 469.061 5.87024 469.242C5.83385 469.422 5.76835 469.561 5.72468 469.561C5.55729 469.554 4.77129 469.096 4.77129 469.006C4.77129 468.818 5.46268 467.401 5.57185 467.359C5.7829 467.283 6.21229 468.457 6.06674 468.7ZM10.8628 463.045C14.6982 464.199 15.6879 470.089 12.2965 471.548C10.3824 472.368 8.46112 469.429 10.0113 468.047C10.7318 467.401 11.8598 468.082 11.7943 469.117C11.7652 469.589 11.7361 469.638 11.2703 469.881C10.7463 470.166 10.6881 470.27 10.9356 470.499C11.6997 471.215 13.2644 469.582 13.2644 468.068C13.2644 464.504 9.04334 463.08 6.31418 465.727C5.75379 466.269 5.77562 466.269 5.55729 465.595C5.06968 464.06 8.60667 462.365 10.8628 463.045ZM5.08424 467.443C4.96779 467.63 4.87318 467.839 4.87318 467.915C4.87318 467.985 4.82952 468.047 4.77857 468.047C4.72763 468.047 4.64757 468.242 4.59663 468.485C4.49474 468.971 4.39285 469.013 3.7888 468.832C3.2648 468.672 3.30119 468.714 3.38124 468.367C3.42491 468.158 3.57774 468.019 3.89796 467.873C4.54568 467.595 5.0624 466.498 4.66941 466.227C4.5093 466.116 4.54568 465.873 4.76402 465.567C5.33168 464.761 5.63735 466.553 5.08424 467.443ZM4.06535 466.748C4.18907 466.748 4.07991 466.394 4.29824 466.394C4.52385 466.394 4.49474 466.936 4.2473 467.213C3.54863 468.005 3.89796 466.748 4.06535 466.748ZM2.86452 467.234C2.29686 466.811 2.09308 465.581 2.50063 465.025C2.83541 464.567 3.92707 464.219 4.09446 464.518C4.13085 464.581 4.24002 464.636 4.34918 464.636C4.70579 464.636 4.79313 464.921 4.55296 465.275C4.35646 465.553 4.28368 465.581 3.92707 465.518C3.30119 465.4 2.63163 466.13 2.90819 466.637C3.0028 466.811 3.22113 466.692 3.22113 466.463C3.22113 466.213 3.51952 465.935 3.79607 465.935C4.10902 465.935 4.10902 465.9 3.73058 466.755C3.37397 467.512 3.30119 467.554 2.86452 467.234ZM3.67963 469.131C4.21091 469.228 4.27641 469.332 4.19635 469.957C4.08719 470.784 4.10174 470.409 3.29391 470.214C2.64619 470.062 3.01736 469.013 3.67963 469.131ZM1.76558 469.707C1.77286 469.11 2.14402 468.832 2.63163 469.047C2.82086 469.131 2.84269 469.471 2.68986 469.805C2.50063 470.2 1.7583 470.124 1.76558 469.707ZM3.56319 476.077C3.83246 475.883 4.03624 475.925 4.04352 476.175C4.04352 476.251 4.20363 476.675 4.39285 477.106L4.74218 477.897C4.23274 478.349 4.00713 478.613 3.83974 477.925C3.67235 477.224 3.01736 476.48 3.56319 476.077ZM4.54568 481.051C4.22546 481.51 4.21819 481.503 3.83974 480.926C3.45402 480.329 3.45402 480.329 3.79607 479.822C4.07991 479.398 4.15269 479.405 4.40741 479.912C4.80768 480.69 4.80768 480.676 4.54568 481.051ZM3.62869 483.865C3.62869 483.49 4.55296 483.108 4.72035 483.413C4.83679 483.635 3.62869 484.844 3.62869 483.865ZM5.49907 480.232C5.76835 479.801 5.9139 479.801 6.19773 480.239L6.42334 480.586C5.7829 481.683 5.92846 481.635 5.55729 481.197C5.22979 480.808 5.21524 480.676 5.49907 480.232ZM6.41607 483.691C6.15407 484.073 6.14679 484.073 5.70285 483.649L5.34624 483.309C5.81929 482.309 5.81201 482.177 6.27779 482.753C6.69262 483.246 6.69262 483.288 6.41607 483.691ZM9.00695 485.594C8.73767 485.963 8.16273 485.629 8.03901 485.025C7.95167 484.608 8.08267 484.615 8.66489 485.066C9.04334 485.358 9.10156 485.455 9.00695 485.594ZM9.47273 484.719C9.39995 484.99 9.13067 484.99 8.84684 484.726C8.56301 484.462 8.04628 484.004 7.62417 483.629C7.34762 483.378 7.43495 483.281 8.02445 483.205C8.79589 483.107 9.66922 484.017 9.47273 484.719ZM20.3748 484.33C19.7853 484.407 19.1885 484.511 19.0503 484.573C18.6136 484.768 17.995 484.907 17.5583 485.198C16.9179 485.629 16.7068 485.379 16.9688 484.483C17.5292 482.559 19.7853 482.003 21.0516 483.483C21.6193 484.136 21.5829 484.177 20.3748 484.33ZM23.053 485.817L22.3907 485.851C21.743 485.886 21.7285 485.879 21.8012 485.615C21.8376 485.469 21.8959 485.164 21.9322 484.948L21.9977 484.552C23.4751 484.726 23.3951 484.636 23.053 485.817ZM25.2363 481.934C25.3601 480.829 26.1097 480.169 26.6773 480.655C27.1941 481.1 26.7647 482.253 25.935 482.656C25.2509 482.989 25.1345 482.864 25.2363 481.934ZM24.2466 484.539C23.8972 484.393 23.8827 484.365 23.8536 483.726C23.8099 482.871 23.8536 482.955 24.9816 483.337L24.9525 483.99C24.9161 484.719 24.8361 484.782 24.2466 484.539ZM25.7458 486.039C25.4692 486.782 24.7415 486.477 24.9671 485.706C25.0835 485.296 25.1199 485.268 25.4183 485.337C25.8331 485.435 25.9132 485.594 25.7458 486.039ZM26.6482 488.693C26.4372 488.693 26.2188 488.477 26.2188 488.276C26.2188 488.199 26.1533 488.074 26.0733 488.005C25.9205 487.859 25.7822 487.289 25.8986 487.289C26.066 487.282 27.1358 488.693 26.6482 488.693ZM25.5711 495.73C26.4663 494.285 27.9801 494.118 27.9801 495.473C27.9801 495.959 27.3396 496.723 26.8447 496.834C25.28 497.182 24.8797 496.841 25.5711 495.73ZM23.8026 493.708C23.4242 494.25 22.1724 493.069 22.1724 492.166C22.1724 490.839 23.5625 491.034 23.7881 492.395C23.8972 493.083 23.9045 493.562 23.8026 493.708ZM24.4576 498.606L24.3994 499.307C20.7896 499.446 18.6427 496.397 18.4971 494.187C18.468 493.798 18.257 493.368 18.7228 491.652C19.7416 487.88 25.1199 487.609 25.7967 491.298C25.9787 492.27 25.6512 492.965 24.7123 493.625C24.2029 493.986 24.152 493.93 24.1738 492.986C24.1884 492.11 24.0865 491.819 23.5261 491.117C23.235 490.756 22.5872 490.735 22.2525 491.082C21.3937 491.958 21.9541 493.66 23.2422 494.097C23.6935 494.25 23.7007 494.306 23.3951 495.014C23.1695 495.535 23.1622 495.542 22.6455 495.542C21.6921 495.542 21.0371 495.98 21.0371 496.612C21.0371 497.14 22.1069 497.202 22.6164 496.695C23.2422 496.077 23.0821 496.014 23.7007 496.327C24.9671 496.98 24.6177 496.813 24.4576 498.606ZM21.4956 496.549C21.3282 496.244 22.056 495.834 22.5654 495.945C23.1695 496.077 21.7357 496.987 21.4956 496.549Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M160.646 481.003C160.413 481.051 160.137 481.225 159.962 481.447L159.664 481.809C158.725 480.836 157.233 480.565 156.556 480.621C156.105 480.655 155.938 480.544 155.938 480.218C155.938 478.446 153.128 475.424 151.061 474.959C145.159 473.646 140.88 480.947 145.29 484.803C148.718 487.797 153.718 483.052 150.865 479.509C149.031 477.238 145.734 478.662 146.338 481.461C146.724 483.267 149.177 483.26 148.929 481.454C148.842 480.794 147.968 480.315 147.968 480.933C147.968 481.489 147.452 481.586 147.015 481.114C145.814 479.808 148.121 478.148 149.795 479.12C152.764 480.836 150.996 485.706 147.525 485.386C144.963 485.15 143.136 481.802 144.169 479.266C144.271 479.009 144.453 478.571 144.562 478.3C145.829 475.23 151.898 473.952 154.387 478.134C154.686 478.627 156.287 480.968 155.268 480.968C154.045 480.968 152.583 483.052 152.633 484.726C152.655 485.518 152.655 485.525 152.182 485.796C151.018 486.456 147.292 490.561 144.104 488.859C143.667 488.623 142.896 488.429 142.306 487.734L142.095 487.484C143.66 487.553 143.835 487.526 144.133 487.845C144.446 488.179 144.643 488.206 144.643 487.922C144.643 487.609 145.028 486.852 145.348 486.546C145.712 486.192 145.581 486.06 145.072 486.247C144.81 486.345 144.308 486.379 143.624 486.352C140.625 486.213 145.05 487.672 142.91 487.373C141.44 487.164 140.611 485.685 139.002 484.483C138.376 484.018 138.224 483.858 138.384 483.823C138.98 483.705 139.453 483.413 139.577 483.094C139.643 482.906 139.781 482.719 139.876 482.684C141.237 482.1 141.659 480.239 140.64 479.335C140.152 478.905 139.315 479.051 138.762 479.662C138.289 480.183 139.075 481.704 139.672 481.419C139.985 481.274 140.203 481.01 140.203 480.78C140.203 480.544 139.912 480.6 139.788 480.864C139.592 481.288 138.857 480.871 139.01 480.419C139.039 480.329 139.068 480.211 139.068 480.148C139.068 479.891 139.497 479.572 139.854 479.572C141.047 479.572 141.171 481.545 140.021 482.239C139.672 482.455 139.497 482.364 139.359 481.899C139.315 481.746 138.667 481.746 138.529 481.899C138.347 482.107 138.609 482.621 138.966 482.781C139.344 482.941 139.352 483.031 139.01 483.288C138.435 483.719 135.88 482.906 135.363 483.052C135.043 483.142 135.101 483.49 135.443 483.538C136.411 483.67 137.307 484.935 136.426 484.935C136.062 484.935 135.647 485.24 135.647 485.504C135.647 485.9 136.404 486.102 136.622 485.768C137.001 485.178 137.554 485.643 137.678 486.657C137.838 487.956 136.186 488.463 135.902 487.199C135.807 486.768 136.186 486.324 136.484 486.504C136.601 486.574 136.724 486.734 136.753 486.859C136.819 487.144 137.088 487.151 137.088 486.873C137.088 486.261 136.419 485.99 135.873 486.372C135.167 486.866 135.48 488.095 136.368 488.318C137.787 488.672 138.558 486.741 137.503 485.469C136.892 484.733 137.256 484.816 136.826 484.094C136.171 483.003 138.114 483.99 139.403 485.407C140.363 486.456 140.858 488.908 139.97 488.206C139.126 487.533 137.911 488.714 138.711 489.422C139.01 489.686 139.468 489.665 139.999 489.36C140.356 489.158 140.509 489.325 140.509 489.929C140.509 490.374 140.501 490.381 140.174 490.353C139.679 490.311 139.381 490.457 139.308 490.784C139.17 491.395 139.621 491.583 140.29 491.194L140.683 490.964C141.44 491.596 141.564 491.652 141.491 491.999C140.865 494.979 143.129 496.966 145.036 495.118C146.324 493.868 145.232 491.263 143.813 492.208C143.34 492.527 143.092 493.542 143.449 493.694C143.653 493.785 143.733 493.611 143.653 493.257C143.551 492.812 144.031 492.312 144.461 492.409C145.501 492.645 145.618 494.167 144.65 494.889C143.245 495.938 141.418 494.57 141.695 492.687L141.79 492.062L142.255 492.027C143.005 491.965 143.318 491.485 142.838 491.124C142.583 490.936 142.146 491.027 142.001 491.291C141.804 491.652 141.455 491.166 141.091 490.895C140.567 490.506 140.996 489.971 140.64 489.123C140.305 488.318 141.033 488.498 140.501 486.775C139.817 484.573 142.335 489.429 145.814 490.707C146.819 491.075 147.779 492.666 146.804 492.354C146.287 492.187 146.236 492.381 146.688 492.854C146.993 493.173 147.132 493.451 147.284 494.049C147.495 494.889 147.597 495 147.699 494.5C147.852 493.729 147.976 493.43 148.361 492.937C148.929 492.215 148.82 491.951 148.085 492.298C147.706 492.479 147.532 492.444 147.532 492.201C147.532 492.124 147.394 491.874 147.226 491.652C146.702 490.957 146.782 490.943 148.762 491.319C150.436 491.631 150.668 491.763 150.581 492.312C150.494 492.819 150.792 492.895 150.96 492.409C151.214 491.659 152.51 492.451 152.51 493.361C152.51 494.403 150.778 494.841 150.749 493.805C150.741 493.569 150.436 493.639 150.436 493.875C150.436 494.729 151.847 495.132 152.452 494.451C153.296 493.493 152.663 491.909 151.411 491.846C150.734 491.812 150.887 491.513 150.043 491.305C149.54 491.187 149.388 490.957 149.795 490.957C150.945 490.957 152.968 489.867 154.111 488.616C154.671 488.012 154.722 487.984 155.203 488.005C156.352 488.067 157.371 487.526 157.75 486.65C158.099 485.852 158.157 485.858 159.031 486.88C160.785 488.929 161.17 491.541 160.006 493.486C159.868 493.715 159.758 493.944 159.758 494C159.758 494.639 157.932 495.591 156.869 495.507C153.951 495.271 153.238 490.77 155.989 489.894C157.837 489.311 159.322 491.548 158.019 492.93C157.226 493.771 155.799 492.847 156.294 491.819C156.483 491.423 156.462 491.214 156.251 491.36C155.959 491.562 155.814 492.131 155.938 492.576C156.483 494.5 159.023 493.604 158.79 491.576C158.55 489.519 155.996 488.672 154.846 490.277C153.201 492.548 153.951 495.209 156.425 495.883C160.93 497.112 162.75 488.637 158.572 485.858C158.121 485.56 158.106 485.532 158.106 484.983C158.106 484.073 157.204 482.857 156.527 482.857C156.425 482.857 156.338 482.816 156.331 482.767C156.331 482.767 156.272 482.253 156.192 481.725C156.098 481.1 156.17 481.058 157.095 481.204C158.609 481.44 159.526 482.079 159.285 482.719C158.987 483.517 159.351 484.268 160.028 484.268C160.617 484.268 160.799 483.163 160.319 482.517C159.977 482.052 160.042 481.871 160.617 481.704C161.396 481.454 161.403 480.836 160.646 481.003ZM148.478 481.044L148.58 481.357C148.725 481.795 148.718 481.864 148.427 482.191C147.903 482.781 146.731 482.274 146.542 481.371L146.469 481.024C147.561 482.184 147.837 481.815 148.478 481.044ZM143.427 486.692C144.81 486.623 144.839 486.636 144.592 487.171C144.417 487.553 144.257 487.623 144.162 487.345C144.133 487.248 143.922 487.109 143.696 487.032C143.318 486.9 143.158 486.706 143.427 486.692ZM138.842 482.281C138.842 482.038 139.191 482.135 139.235 482.392C139.308 482.788 138.842 482.503 138.842 482.281ZM136.106 485.532C135.997 485.337 136.142 485.171 136.426 485.171C137.03 485.171 136.317 485.921 136.106 485.532ZM138.864 488.679C138.929 488.158 140.094 488.269 140.094 488.804C140.087 489.353 138.784 489.318 138.864 488.679ZM140.181 490.936C139.992 491.075 139.803 491.068 139.73 490.923C139.635 490.749 139.766 490.568 139.992 490.568C140.239 490.568 140.363 490.804 140.181 490.936ZM142.67 491.583C142.517 491.791 142.161 491.791 142.161 491.583C142.161 491.214 142.91 491.249 142.67 491.583ZM147.597 492.666C148.143 492.618 148.129 492.583 147.837 493.166C147.568 493.715 147.546 493.722 147.313 493.264C147.059 492.75 147.081 492.708 147.597 492.666ZM155.275 481.357C155.807 481.176 155.843 481.211 155.945 481.996C156.032 482.621 155.916 482.941 155.596 482.941C155.195 482.948 154.693 483.566 154.693 484.045C154.693 484.351 154.868 484.254 155.093 483.816C155.581 482.885 156.076 483.031 155.894 484.052L155.77 484.754C154.977 484.782 154.176 484.768 153.55 485.046C153.259 485.178 153.005 485.282 152.976 485.282C152.946 485.282 152.925 485.053 152.925 484.775C152.939 483.198 153.863 481.843 155.275 481.357ZM143.849 489.283C143.231 488.825 143.209 488.727 143.784 488.984C146.156 490.04 148.143 489.533 150.923 487.164C152 486.247 152.415 486.095 152.837 485.893L153.005 486.359C153.165 486.803 153.536 487.255 154.067 487.651C154.991 488.331 149.118 493.194 143.849 489.283ZM154.642 487.477C154.22 487.623 152.881 486.032 153.092 485.636C153.187 485.462 154.162 485.171 154.926 485.087C155.799 484.997 155.814 485.06 155.181 486.456C154.941 487.005 154.693 487.463 154.642 487.477ZM156.251 483.83C156.403 483.01 156.585 482.983 157.226 483.677C157.655 484.15 157.983 484.942 157.852 485.192C157.772 485.337 157.604 485.303 157.138 485.053C156.913 484.928 156.614 484.83 156.491 484.83C156.163 484.816 156.112 484.601 156.251 483.83ZM157.524 485.615C157.895 485.99 157.364 487.005 156.614 487.352C154.264 488.443 155.479 486.581 155.799 485.678C156.039 485.004 156.891 484.976 157.524 485.615ZM160.173 483.253C160.137 483.649 159.824 483.767 159.729 483.427C159.657 483.163 159.758 482.587 159.882 482.587C160.05 482.594 160.202 482.941 160.173 483.253Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M110.561 491.756C110.553 493.521 112.722 494.299 113.421 492.777C113.727 492.11 113.399 490.804 112.933 490.804C112.664 490.804 112.686 490.971 112.999 491.319C113.523 491.909 113.217 492.986 112.475 493.201C110.903 493.646 110.299 491.117 111.725 490.033C113.137 488.957 115.073 490.277 115.073 492.319C115.073 495.924 110.837 496.605 109.469 493.222C109.2 492.562 109.054 492.416 108.945 492.729C108.734 493.361 110.299 495.32 111.31 495.674C113.741 496.535 116.106 493.958 115.284 491.353C114.374 488.484 110.575 488.804 110.561 491.756Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M131.47 483.483C131.048 483.392 130.64 483.073 130.829 482.982C131.128 482.844 131.484 482.434 131.484 482.239C131.484 481.656 130.837 481.649 130.502 482.232C130.254 482.663 129.992 482.684 129.774 482.309C129.563 481.94 129.665 481.503 130.058 481.093C131.128 479.968 130.56 477.508 129.417 478.307C129.272 478.412 129.49 478.717 129.716 478.717C129.978 478.724 130.24 478.995 130.364 479.405C130.495 479.822 130.407 480.03 129.767 480.829C129.126 481.635 129.199 482.552 129.927 482.92C130.604 483.26 130.458 483.573 131.23 483.802L131.746 483.955C130.473 484.816 129.359 485.865 128.755 486.504C127.86 487.449 127.147 487.671 126.666 487.164C126.208 486.671 126.244 486.053 126.739 485.97C127.263 485.886 126.776 485.171 126.193 485.171C125.895 485.171 125.466 485.664 125.429 486.053C125.386 486.518 125.444 486.511 125.065 486.289C124.097 485.719 123.21 486.963 123.974 487.824C124.265 488.151 124.439 488.109 124.439 487.706C124.439 487.102 125.582 487.102 125.582 487.255C125.582 487.477 126.484 487.797 127.059 487.776C127.838 487.748 127.809 487.887 126.928 488.387C122.154 491.089 118.865 486.282 116.019 485.115C115.328 484.83 115.248 484.705 115.233 483.858C115.226 483.476 115.269 483.385 115.612 483.142C116.325 482.635 116.703 481.725 116.412 481.232C116.026 480.565 115.182 481.287 114.993 482.448C114.869 483.219 114.782 483.302 114.163 483.302C113.45 483.309 113.967 480.475 114.957 478.912C117.955 474.188 124.214 474.466 125.728 479.391C126.761 482.753 124.461 485.851 121.259 485.414C118.333 485.018 117.504 480.815 120.022 479.141C121.907 477.891 124.578 480.28 123.166 481.954C122.496 482.746 121.448 482.253 121.412 481.128C121.368 479.94 120.298 480.94 120.298 482.17C120.298 483.038 121.077 483.747 121.863 483.601C122.242 483.531 122.249 483.538 122.285 483.913C122.365 484.844 123.603 484.664 123.865 483.677C123.923 483.462 123.894 483.413 123.719 483.413C123.297 483.413 123.231 482.92 123.544 482.093C124.803 478.745 120.517 476.869 118.705 479.975C117.205 482.559 118.901 485.761 121.776 485.761C127.307 485.761 128.006 477.481 122.656 475.362C118.617 473.764 113.559 477.599 113.559 482.26C113.559 483.358 113.37 483.434 111.994 482.885C111.369 482.635 111.332 482.67 111.703 483.149C112.031 483.573 112.526 484.684 112.526 484.997C112.526 485.191 112.3 485.303 111.922 485.296C111.478 485.289 110.051 482.434 110.037 481.538C110.037 481.503 110.241 481.308 110.488 481.107C111.303 480.454 111.347 479.315 110.561 479.315C110.219 479.315 109.738 479.87 109.709 480.294C109.702 480.433 109.68 480.628 109.666 480.725C109.607 481.142 110.866 481.135 96.3983 481.162C89.1278 481.176 83.1309 481.225 83.08 481.26C82.7015 481.524 83.7058 481.551 92.0898 481.489C107.235 481.385 108.632 481.385 108.85 481.51C108.96 481.572 109.2 481.607 109.374 481.572C110.182 481.433 109.309 482.434 110.954 484.823C111.42 485.497 111.42 485.483 110.823 485.99C109.586 487.025 108.414 489.29 108.858 489.79C108.981 489.929 109.207 489.617 109.207 489.318C109.207 488.609 110.211 486.914 111.012 486.296C111.783 485.692 112.067 486.498 111.39 487.366C110.881 488.019 110.837 488.498 111.281 488.554C111.66 488.602 111.878 488.366 112.104 487.637C112.3 487.005 112.446 486.866 112.948 486.824C113.137 486.81 113.355 487.498 113.355 488.13C113.355 488.658 113.406 488.707 113.807 488.519C115.575 487.692 115.692 489.047 117.154 489.901L117.482 490.096C116.914 491.298 116.907 491.18 117.111 491.798C117.264 492.277 117.271 492.374 117.133 492.743C116.667 494.007 117.547 495.473 118.574 495.139C119.105 494.965 119.527 494.146 119.338 493.66C119.192 493.291 118.792 493.284 118.894 493.653C119.17 494.66 118.224 495.25 117.671 494.417C117.045 493.465 117.242 492.52 118.042 492.638C119.534 492.861 119.199 491.416 118.02 491.86C117.511 492.048 117.402 491.958 117.402 491.332C117.402 490.638 117.766 490.117 118.108 490.325C119.483 491.159 121.514 491.075 122.955 491.075L122.504 491.548C121.616 492.479 121.616 493.382 120.968 493.625C120.524 493.792 120.524 493.889 120.961 494.264C121.557 494.778 122.402 494.583 122.402 493.93C122.402 493.666 122.438 493.639 122.817 493.66C123.413 493.687 123.857 492.882 123.297 492.784C123.028 492.743 122.78 492.305 122.649 492.103L122.867 491.666C123.1 491.2 123.377 491.006 125.204 490.061C126.353 489.464 127.591 488.429 128.573 487.234C129.985 485.525 128.741 487.394 129.003 488.366C129.126 488.839 129.061 490.422 128.901 490.707C128.646 491.18 127.896 490.804 127.853 490.186C127.751 488.797 126.499 489.742 127.234 490.624C127.627 491.096 127.125 492.173 126.652 491.888C125.495 491.186 123.886 493.034 124.294 494.597C124.519 495.452 125.837 496.035 126.557 495.355C127.227 494.722 126.761 493.416 125.931 493.583C125.509 493.666 125.182 493.93 125.182 494.181C125.182 494.389 125.436 494.382 125.597 494.16C125.953 493.68 126.761 494.25 126.463 494.778C126.106 495.417 124.92 495.278 124.658 494.556C124.134 493.132 126.179 491.332 126.907 492.576C127.263 493.187 127.394 493.173 127.307 492.541C127.198 491.701 127.562 491.18 128.268 491.173C128.908 491.166 128.959 491.325 128.602 492.367C128.355 493.104 128.362 493.118 129.25 493.215L129.949 493.291C129.949 492.048 129.912 491.756 130.211 491.124C130.553 490.395 130.334 490.075 129.803 490.534C129.359 490.916 129.206 490.77 129.286 490.033C129.366 489.241 129.447 489.116 129.73 489.29C130.626 489.832 131.477 488.554 130.611 487.977C130.262 487.748 130.116 487.79 129.476 488.304C128.821 488.839 129.323 486.935 130.123 485.824C131.208 484.33 133.755 483.038 133.296 484.219C133.18 484.525 133.049 484.921 133.02 485.101C132.962 485.393 132.918 485.421 132.496 485.421C131.957 485.421 131.659 485.817 131.928 486.178C132.074 486.379 132.816 486.428 132.918 486.24C133.151 485.81 133.689 486.72 133.689 487.567C133.689 488.172 133.311 488.616 132.838 488.568C132.19 488.498 132.096 487.477 132.707 487.164C133.056 486.984 133.034 486.831 132.663 486.831C131.819 486.831 131.659 488.456 132.467 488.832C133.369 489.255 134.046 488.63 134.024 487.394C134.01 486.831 133.595 485.893 133.362 485.893C132.802 485.893 133.711 483.774 134.374 483.524C134.657 483.42 134.89 483.26 134.89 483.17C134.854 482.607 132.096 483.622 131.47 483.483ZM130.815 482.239C130.938 482.121 130.982 482.135 131.04 482.295C131.077 482.413 131.048 482.538 130.96 482.6C130.647 482.823 130.516 482.517 130.815 482.239ZM126.201 486.928C126.361 487.276 126.273 487.345 125.895 487.164C125.691 487.067 124.716 486.824 124.301 487.262C123.588 488.019 124.003 485.587 125.233 486.685C125.582 486.991 125.946 487.018 125.837 486.72C125.56 485.99 125.713 485.518 126.215 485.518C126.528 485.518 126.623 485.713 126.361 485.824C126.15 485.921 126.055 486.616 126.201 486.928ZM123.311 484.045C123.006 484.462 122.402 484.038 122.504 483.469C122.569 483.08 122.453 483.01 122.031 483.184C121.092 483.566 120.175 482.26 120.757 481.357C120.932 481.093 121.135 481.211 121.135 481.579C121.135 482.184 121.907 482.642 122.787 482.552C123.231 482.51 122.977 483.01 123.311 483.601C123.421 483.816 123.421 483.893 123.311 484.045ZM110.59 479.69C110.808 479.773 110.786 480.225 110.546 480.593C110.233 481.072 110.044 481.051 110.044 480.537C110.037 480.107 110.364 479.606 110.59 479.69ZM118.617 492.242C118.574 492.402 118.108 492.506 117.991 492.381C117.722 492.076 118.69 491.985 118.617 492.242ZM122.838 492.875C123.224 493.312 122.969 493.618 122.569 493.201C122.343 492.972 122.169 493.076 122.169 493.43C122.169 493.576 122.096 493.805 122.009 493.951C121.739 494.389 120.983 494.236 121.39 493.764C121.761 493.326 122.591 491.305 122.591 492.27C122.576 492.444 122.693 492.708 122.838 492.875ZM115.743 481.531C116.267 481.211 116.31 481.961 115.801 482.538C115.604 482.76 115.4 482.934 115.335 482.934C115.044 482.941 115.386 481.746 115.743 481.531ZM115.219 485.393C115.219 485.497 115.284 485.692 115.357 485.817C115.43 485.942 115.524 486.143 115.561 486.254C115.633 486.491 115.16 486.532 114.724 486.338C114.331 486.157 114.054 485.254 114.352 485.122C114.644 484.997 115.219 485.178 115.219 485.393ZM114.964 484.761C113.923 484.844 114.04 484.976 113.858 483.684C115.08 483.49 114.876 483.274 114.964 484.761ZM111.339 488.109C111.267 487.984 111.762 487.317 111.849 487.414C111.973 487.553 111.521 488.45 111.339 488.109ZM112.642 486.56C112.118 486.741 112.147 486.748 112.016 486.324C111.849 485.775 111.878 485.553 112.133 485.476C112.599 485.337 112.737 485.4 112.89 485.81C113.101 486.379 113.093 486.407 112.642 486.56ZM112.693 484.365C112.431 483.462 112.446 483.427 113.006 483.545C113.668 483.684 113.566 483.566 113.61 484.879L113.239 484.914C112.875 484.948 112.861 484.935 112.693 484.365ZM113.115 485.567C113.072 484.9 113.807 485.018 114.018 485.713C114.112 486.018 114.171 486.282 114.149 486.303C113.785 486.72 113.159 486.275 113.115 485.567ZM113.858 488.151C113.683 488.241 113.414 487.081 113.53 486.734C113.697 486.24 114.425 486.685 114.796 487.505L115.007 487.97C114.753 487.991 114.069 488.047 113.858 488.151ZM116.201 488.595C116.376 488.401 117.169 488.491 117.496 488.741C117.926 489.075 118.377 489.297 118.654 489.443L118.413 489.651C117.955 490.047 115.823 489.026 116.201 488.595ZM123.188 490.617C122.569 490.818 120.801 490.86 120.24 490.686C119.978 490.603 117.096 490.04 118.952 489.707C119.36 489.631 119.578 489.436 119.338 489.353C119.265 489.325 119.01 489.248 118.77 489.172C118.53 489.096 118.093 488.832 117.795 488.575C117.271 488.123 117.227 488.116 116.645 488.186C115.91 488.276 115.444 488.04 115.058 487.373C114.636 486.65 114.695 486.595 115.633 486.824C116.325 486.991 116.347 486.935 115.903 486.275C114.84 484.698 116.216 485.254 119.221 487.623C121.39 489.332 124.33 489.985 125.968 489.123C126.099 489.054 126.222 489.026 126.259 489.061C126.361 489.179 124.134 490.304 123.188 490.617ZM127.307 489.929C127.401 489.658 127.656 489.929 127.656 490.29C127.656 490.95 127.183 490.283 127.307 489.929ZM130.509 488.387C130.706 488.547 130.706 488.554 130.516 488.797C130.254 489.123 129.527 489.089 129.527 488.741C129.519 488.387 130.203 488.137 130.509 488.387ZM129.396 491.027C129.716 490.888 129.84 491.055 129.716 491.492C129.439 492.513 129.49 492.986 128.93 492.722C128.631 492.59 129.017 491.187 129.396 491.027ZM132.27 485.997C132.168 485.817 132.299 485.636 132.54 485.636C132.991 485.643 132.474 486.379 132.27 485.997Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M267.84 477.071C268.976 477.071 270.169 475.605 269.98 474.445C269.915 474.056 269.42 473.431 269.179 473.431C268.452 473.431 268.539 474.452 269.303 474.799C269.987 475.105 269.667 475.834 268.575 476.453C267.644 476.981 267.484 476.939 267.738 476.223C268.182 474.952 268.059 471.687 268.372 471.771C268.619 471.84 268.757 471.833 268.852 471.937C269.085 472.201 269.325 472.014 269.245 471.639C269.201 471.43 269.15 470.951 269.136 470.576C269.107 469.77 269.078 469.714 268.728 469.888C268.292 470.11 267.964 470.062 267.913 469.763C267.644 468.165 267.527 467.929 267.105 466.72L267.44 466.331C268.648 464.921 267.003 462.601 265.65 463.81C265.308 464.115 265.322 464.122 264.784 463.58C264.238 463.032 263.11 462.483 262.127 462.281C261.567 462.163 261.4 462.08 261.341 461.885L261.261 461.635C261.138 462.066 261.218 462.115 260.373 462.191C259.1 462.302 257.972 462.775 257.077 463.58C256.866 463.768 256.618 463.921 256.523 463.921C256.269 463.921 256.203 464.247 256.407 464.504C256.502 464.629 256.553 464.782 256.516 464.852C256.356 465.15 256.625 464.928 257.106 464.379C258.94 462.254 262.63 462.08 264.645 464.011L265.002 464.351C264.733 464.706 264.252 465.289 264.121 465.824C263.91 466.706 262.855 466.192 262.535 465.053C262.44 464.72 262.106 464.859 262.149 465.213C262.258 466.06 262.186 466.519 261.887 466.943C261.465 467.533 261.378 467.533 261.123 466.922C260.432 465.248 258.263 464.775 257.768 466.185C257.295 467.519 258.401 468.575 260.162 468.471L261.239 468.408C260.606 471.27 258.656 471.882 257.44 470.729C256.014 469.381 256.902 469.888 256.196 468.707C255.861 468.151 255.818 467.144 256.101 466.449C256.604 465.199 256.596 465.206 256.4 465.241C255.956 465.324 256.458 463.997 255.767 464.838C254.959 465.824 255.315 469.089 256.232 469.089C256.327 469.089 256.363 469.166 256.334 469.298C255.81 471.395 256.96 470.312 257.2 471.034C257.615 472.264 261.451 471.868 261.451 468.582C261.451 468.068 261.501 467.95 261.96 467.373C262.237 467.019 262.491 466.574 262.528 466.387C262.644 465.72 262.921 466.206 263.641 466.616C264.143 466.901 263.816 467.769 264.201 468.443C264.376 468.742 264.376 468.79 264.209 469.311C263.998 469.992 263.99 470.791 264.194 471.444C264.398 472.097 264.398 472.097 264.049 472.451C263.503 473.007 263.263 474.07 263.576 474.542C263.852 474.959 263.765 475.188 263.183 475.494C262.309 475.952 261.654 475.876 261.654 475.306C261.654 474.709 261.123 474.167 260.788 474.417C260.315 474.772 260.432 475.39 261.065 475.834C261.356 476.036 261.356 476.043 261.167 476.362C260.614 477.314 259.143 478.162 258.641 477.807C258.328 477.585 258.219 477.641 258.256 477.988C258.365 479.051 260.905 477.891 261.472 476.522L261.683 476.008C262.055 476.064 263.117 476.355 263.83 475.383C263.932 475.244 264.078 475.216 264.456 475.272C265.439 475.418 266.137 474.098 265.431 473.431C265.22 473.236 265.126 473.389 265.257 473.702C265.504 474.278 265.497 474.389 265.191 474.737C264.624 475.383 264.18 475.084 264.514 474.285C264.616 474.042 264.718 473.507 264.733 473.083C264.776 472.18 264.755 472.208 265.555 471.972C266.56 471.68 266.523 471.652 266.523 472.694C266.516 475.369 266.072 476.869 265.402 476.473C264.937 476.196 264.66 476.23 264.66 476.571C264.66 476.925 264.078 477.515 264.245 477.696C264.391 477.863 264.733 477.474 264.871 476.994C264.937 476.779 265.024 476.599 265.075 476.599C265.279 476.599 265.759 476.856 265.875 477.029C265.977 477.175 266.035 477.189 266.152 477.078C266.341 476.897 267.149 477.036 267.229 477.265C267.331 477.557 266.974 478.238 266.727 478.238C266.516 478.238 266.516 478.252 266.676 478.453C266.989 478.842 266.69 479.329 266.203 479.245C265.737 479.162 265.686 479.342 266.123 479.516C266.407 479.627 266.559 479.884 266.341 479.884C266.29 479.884 266.217 480.023 266.181 480.19C266.108 480.53 264.893 480.544 264.667 480.211C264.42 479.843 262.193 481.35 262.338 481.781C262.528 482.33 263.139 482.114 263.896 481.225C264.463 480.558 264.565 480.516 265.315 480.655C265.948 480.773 265.075 482.191 263.874 482.989C263.627 483.156 263.357 483.441 263.27 483.629C263.023 484.177 262.71 484.372 262.426 484.156C261.865 483.74 260.73 484.066 260.73 484.643C260.73 484.983 260.97 485.011 261.167 484.705C261.48 484.205 262.331 484.254 262.222 484.768C262.164 485.032 262.186 485.046 262.433 484.976C263.001 484.816 262.608 486.247 262.004 486.56C261.647 486.741 260.977 486.706 260.686 486.491C259.959 485.949 261.159 486.115 261.159 485.615C261.159 484.879 260.017 486.595 260.017 485.33C260.017 484.775 259.813 484.782 259.813 484.914C259.813 485.212 259.253 484.733 259.66 485.636C259.959 486.296 259.718 486.129 258.154 486.511C256.873 486.824 254.602 486.768 255.475 487.401C256.029 487.797 259.085 486.789 259.726 486.553C260.075 486.421 260.133 486.435 260.432 486.72C261.545 487.783 263.146 486.831 262.993 485.192C262.899 484.177 263.081 484.782 263.597 483.795C263.772 483.455 263.939 483.288 264.151 483.246C264.42 483.184 265.621 481.836 265.621 481.593C265.621 481.496 266.021 481.024 266.116 480.905L266.421 481.149C266.589 481.281 266.785 481.475 266.858 481.572C267.091 481.892 267.353 481.795 267.418 481.364C267.615 480.162 268.241 480.704 268.277 482.107C268.292 482.795 268.313 482.871 268.524 482.913C268.968 482.989 268.648 481.308 268.044 480.377C267.869 480.114 267.884 480.093 268.452 479.467C269.165 478.689 269.165 478.759 268.444 478.683C267.564 478.592 267.244 478.398 267.316 477.988C267.345 477.529 267.629 477.071 267.84 477.071ZM269.136 474.32C268.961 474.014 269.005 473.785 269.245 473.785C269.405 473.785 269.711 474.223 269.711 474.459C269.711 474.716 269.31 474.626 269.136 474.32ZM268.437 470.291C268.816 470.249 268.925 470.492 268.859 471.215C268.823 471.646 268.728 471.715 268.386 471.562C267.899 471.333 267.935 470.346 268.437 470.291ZM258.277 467.332C257.55 465.935 259.194 465.248 260.381 466.456C262.63 468.763 258.918 468.554 258.277 467.332ZM255.519 465.935C255.519 465.81 255.563 465.678 255.614 465.644C255.737 465.553 255.97 465.887 255.89 466.04C255.767 466.248 255.519 466.171 255.519 465.935ZM260.963 475.32C260.781 475.091 260.803 474.73 260.999 474.73C261.123 474.73 261.421 475.202 261.421 475.404C261.421 475.626 261.167 475.577 260.963 475.32ZM263.146 481.593C262.629 481.885 262.484 481.753 262.877 481.35C263.117 481.1 263.83 480.704 263.896 480.78C263.976 480.864 263.474 481.413 263.146 481.593ZM265.875 464.164C266.989 463.49 268 465.004 267.149 466.067C266.69 466.637 266.72 465.859 266.035 465.004C265.621 464.476 265.592 464.338 265.875 464.164ZM265.031 464.831C265.3 464.56 265.504 464.678 265.875 465.345C266.05 465.657 266.261 465.977 266.348 466.053C266.574 466.262 266.53 466.595 266.268 466.679C265.737 466.838 264.34 466.699 264.267 466.477C264.209 466.297 264.762 465.102 265.031 464.831ZM264.187 474.348C264.034 474.709 263.845 474.681 263.714 474.264C263.525 473.639 263.99 472.493 264.369 472.66C264.645 472.771 264.58 473.403 264.187 474.348ZM266.334 470.742C266.53 471.479 266.538 471.458 265.788 471.639C264.413 471.965 264.573 472 264.434 471.402C264.129 470.034 264.413 468.818 264.951 469.193C265.453 469.548 266.392 469.193 266.392 468.638C266.392 468.04 265.337 467.797 264.871 468.297C264.529 468.658 264.332 468.401 264.245 467.512C264.18 466.831 264.187 466.831 264.434 466.915C264.886 467.075 265.817 467.123 266.254 467.005C266.792 466.866 266.821 466.894 267.091 467.686C267.848 469.951 267.804 470.298 266.8 470.041C266.21 469.895 266.137 469.992 266.334 470.742ZM264.842 468.749C264.842 468.394 265.912 468.242 266.021 468.582C266.057 468.686 266.035 468.846 265.97 468.936C265.773 469.2 264.842 469.047 264.842 468.749ZM267.28 480.829C267.062 481.385 266.982 481.399 266.509 480.954C265.97 480.447 266.312 479.606 266.945 479.877C267.404 480.079 267.484 480.315 267.28 480.829ZM267.848 479.627C267.68 479.836 267.527 480.002 267.513 480.002C266.916 479.822 266.734 479.474 266.967 478.96L267.12 478.627C268.204 479.016 268.357 478.988 267.848 479.627ZM266.887 476.814C266.297 476.856 266.247 476.765 266.399 475.952C266.647 474.619 266.821 472.854 266.771 472.139C266.741 471.722 266.705 471.138 266.69 470.847L266.654 470.326C268.008 470.437 267.848 470.256 267.848 471.562L267.447 471.493C267.2 471.451 267.018 471.472 266.974 471.548C266.931 471.632 267.04 471.68 267.309 471.68C267.993 471.68 268.066 472.896 267.549 475.834L267.382 476.786L266.887 476.814Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M19.0648 486.463C18.9265 486.463 18.9265 486.699 19.0648 486.699C19.2031 486.699 19.2031 486.463 19.0648 486.463Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M268.008 483.517C267.782 484.677 265.883 484.657 265.883 483.497C265.883 482.746 266.756 482.149 267.127 482.649C267.2 482.746 267.324 482.823 267.404 482.823C267.695 482.823 267.345 482.364 266.96 482.246C265.664 481.843 265.075 483.788 266.247 484.601C267.083 485.185 268.466 484.441 268.299 483.497C268.219 483.08 268.088 483.087 268.008 483.517Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M260.49 481.67C260.49 480.947 262.731 479.44 263.961 479.335C265.162 479.231 265.672 478.537 263.081 479.197C262.549 479.329 261.523 479.884 261.523 480.03C261.523 480.086 261.465 480.127 261.392 480.134C261.247 480.141 260.577 480.94 259.966 481.857C259.653 482.323 259.522 482.67 259.398 483.323L259.238 484.177C259.26 484.198 259.798 484.705 259.828 484.705C259.842 484.705 259.835 484.309 259.82 483.823C259.798 482.989 259.813 482.899 260.133 482.357C260.337 482.038 260.49 481.725 260.49 481.67Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M37.4848 481.197C37.3829 480.829 36.4077 480.53 36.0001 480.746C35.5053 481.017 35.2651 480.989 34.9594 480.641C34.4718 480.086 33.7877 479.961 33.3583 480.336C33.22 480.454 32.8853 480.586 32.6087 480.628C32.3322 480.669 31.9683 480.815 31.8009 480.954C31.3497 481.315 31.1823 481.079 31.5462 480.586C32.5068 479.294 30.3817 478.53 30.6073 480.391C30.6583 480.843 30.6364 480.94 30.4399 481.107C30.2143 481.294 30.2216 481.301 30.6364 481.239C31.8518 481.058 30.782 482.225 31.3278 483.024C31.7063 483.58 32.6233 482.559 32.0265 481.885C31.7572 481.579 31.7645 481.371 32.0483 481.197C32.5287 480.912 32.7979 480.968 32.827 481.35C32.9071 482.246 33.482 482.851 33.8605 482.427C34.0643 482.198 33.9114 481.454 33.5839 481.121C32.9944 480.516 34.2389 480.419 34.5737 480.836C34.9667 481.343 35.3233 481.503 35.7381 481.378C36.415 481.176 36.7643 481.142 36.8371 481.274C36.939 481.454 37.3538 481.447 37.4703 481.308C37.3756 481.274 37.3684 481.232 37.4848 481.197ZM30.8766 479.836C31.1968 479.398 31.6408 479.843 31.4006 480.357C31.1022 480.975 30.6292 480.169 30.8766 479.836ZM31.437 482.413C31.3424 481.982 31.5607 481.746 31.7645 482.059C32.1429 482.635 31.5534 482.948 31.437 482.413ZM33.6713 482.01C33.6713 482.246 33.2783 482.114 33.22 481.857C33.1254 481.447 33.14 481.301 33.2928 481.301C33.4238 481.301 33.6713 481.767 33.6713 482.01Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M239.035 481.065C238.613 481.065 238.518 480.871 238.686 480.336C239.181 478.745 237.099 478.821 237.9 480.509C238.162 481.065 237.987 481.336 237.398 481.281C237.041 481.246 237.019 481.218 236.961 480.753C236.779 479.217 235.389 479.669 236.189 481.003C236.517 481.545 236.517 481.635 236.168 481.788C235.818 481.94 235.36 481.746 235.134 481.35C234.901 480.954 234.261 480.78 233.868 481.01C233.475 481.239 233.307 481.239 232.856 480.996C232.572 480.843 232.478 480.836 232.412 480.947C232.369 481.03 232.303 481.051 232.274 480.989C232.208 480.871 232.711 480.954 195.47 480.954C164.569 480.954 161.214 480.982 161.432 481.225C161.505 481.308 219.807 481.378 226.503 481.308L232.354 481.246C233.096 481.649 233.482 481.954 234.13 481.399C234.268 481.274 234.807 481.531 235.229 481.92C235.622 482.281 236.255 482.281 236.546 481.92C236.91 481.475 237.237 481.843 237.965 481.371C238.438 481.065 238.817 481.204 238.453 481.545C238.242 481.746 238.074 482.218 238.169 482.385C238.205 482.455 238.322 482.323 238.431 482.079C238.657 481.586 238.722 481.565 238.977 481.885C239.261 482.246 238.948 482.76 238.504 482.649C238.14 482.559 238.082 482.781 238.431 482.941C238.678 483.052 239.006 482.996 239.181 482.809C239.457 482.531 239.319 481.065 239.035 481.065ZM236.713 480.933C236.612 481.121 236.517 481.093 236.371 480.829C236.204 480.523 236.204 480.239 236.379 480.239C236.561 480.245 236.808 480.767 236.713 480.933ZM238.482 480.19C238.402 480.537 238.264 480.558 238.118 480.252C237.951 479.898 237.987 479.655 238.213 479.655C238.467 479.655 238.562 479.836 238.482 480.19Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M0.586584 482.649C0.506529 482.885 0.724862 482.885 0.724862 482.649C0.724862 482.427 0.66664 482.406 0.586584 482.649Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M70.6132 481.169C65.5406 481.176 56.0431 481.149 49.5004 481.107C40.7671 481.058 37.9724 481.051 37.4848 481.197C37.4994 481.246 37.4994 481.274 37.463 481.322C37.5212 481.357 37.6085 481.392 37.7177 481.433C38.0088 481.545 82.767 481.545 82.8325 481.433C82.9853 481.149 83.1091 481.155 70.6132 481.169Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M265.999 477.251C265.723 477.585 265.592 477.814 265.3 477.731C264.929 477.627 265.031 478.016 265.206 478.016C265.41 478.016 265.402 478.189 265.191 478.551C264.944 478.974 265.271 478.953 265.541 478.53C265.904 477.967 266.669 478.425 266.247 478.071C265.948 477.821 265.839 477.988 265.926 477.578L265.999 477.251Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M257.994 476.46C257.644 476.23 257.542 476.55 257.863 476.856C258.75 477.689 259.828 475.952 258.998 475.015C257.921 473.792 255.934 475.668 256.916 476.988C257.062 477.182 257.178 477.432 257.178 477.543C257.178 477.654 257.208 477.779 257.244 477.821C257.339 477.932 258.168 477.196 257.804 477.196C257.644 477.196 257.178 476.612 257.164 476.397C257.091 475.147 258.634 474.445 258.896 475.612C259.042 476.258 258.481 476.779 257.994 476.46Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M0.593862 471.59C0.615695 471.444 0.615695 471.208 0.593862 471.062C0.528362 470.708 0.528362 471.937 0.593862 471.59Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M261.218 461.295C261.218 460.975 261.618 460.718 261.894 460.864C262.477 461.163 262.979 460.975 262.979 460.454C262.979 459.892 262.324 459.621 261.887 459.996C261.778 460.093 261.56 460.17 261.4 460.17C261.152 460.17 261.123 460.204 261.218 460.399C261.385 460.76 261.058 461.003 260.854 460.67C260.403 459.933 258.983 460.468 259.726 461.302C260.162 461.809 261.218 461.503 261.218 461.295ZM261.989 460.295C262.171 460.128 262.586 460.176 262.644 460.371C262.695 460.552 262.367 460.725 262.076 460.67C261.8 460.621 261.778 460.496 261.989 460.295ZM260.701 461.17C260.534 461.399 259.988 461.406 259.908 461.17C259.624 460.336 261.108 460.614 260.701 461.17Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M10.8628 457.203C10.8191 456.495 10.3388 456.272 9.742 456.682C9.23256 457.037 9.01423 456.835 9.01423 456.022C9.01423 455.529 9.04334 455.48 9.31989 455.48C9.97489 455.48 10.5353 454.661 10.2951 454.063C10.1204 453.633 9.69106 453.653 9.22528 454.112C8.48295 454.841 8.28645 453.654 8.96328 452.542C9.85117 451.076 8.81045 450.382 9.19617 449.187C9.56006 448.048 9.26895 446.95 9.06517 419.309C8.84684 389.042 8.85412 377.365 8.74495 364.409C8.65034 353.031 8.68673 321.506 8.43201 245.926C8.17728 170.964 8.42473 80.706 8.43201 80.4976C8.59212 75.9892 8.44656 51.4326 8.74495 50.5365C9.2835 48.9109 8.0754 49.0499 8.8905 47.5841C10.0477 45.4862 8.825 45.2222 8.8905 43.9996C8.91234 43.6245 8.83956 43.2633 8.65762 42.8465C8.21367 41.8253 8.35923 41.4918 8.92689 42.2351C9.611 43.1313 10.5935 42.0267 9.9385 41.1028C9.56006 40.5679 8.38834 40.6582 8.38834 41.2209C8.38834 41.8114 8.25734 41.8948 7.64601 41.6655C7.14384 41.478 7.10745 41.4918 6.86729 41.86C6.3069 42.7284 7.05651 43.6453 7.77701 42.9645C8.22095 42.5408 8.23551 42.5477 8.38106 43.1035C8.59939 43.9093 8.49751 44.2775 8.04629 44.3192C7.40584 44.3747 6.93279 45.2986 7.26756 45.8196C7.47134 46.1392 7.8134 46.0419 8.25734 45.5418C9.01423 44.6943 9.27623 45.9169 8.58484 47.0562C7.52229 48.8067 8.75223 49.0568 8.23551 50.6059C7.98806 51.3423 8.31556 49.9251 8.12634 63.7769C7.90801 79.6223 7.89345 215.145 7.87162 218.272C7.87162 218.272 8.06084 243.391 8.12634 287.398C8.22823 349.175 8.37378 373.371 8.42473 383.374C8.58484 415.502 8.62851 412.446 8.7595 430.076C8.89778 448.117 9.11612 448.166 8.57756 449.52C8.47567 449.77 8.49751 449.958 8.70128 450.562C8.94145 451.285 8.87595 452.097 8.58484 452.097C8.18456 452.097 7.99534 453.904 8.32284 454.577C8.45384 454.848 8.59212 455.383 8.62123 455.751C8.65034 456.127 8.77406 456.62 8.89778 456.856C9.0215 457.092 9.11611 457.384 9.11611 457.502C9.11611 457.801 8.81045 457.78 8.73767 457.481C8.59939 456.925 7.86434 456.814 7.59506 457.301C7.11473 458.162 7.58779 459.1 8.41745 458.947C8.80317 458.877 8.92689 458.912 8.96328 459.093C9.03606 459.454 9.07973 459.808 9.218 459.808C9.42178 459.808 9.44361 459.364 9.26895 458.836C8.59939 456.835 10.9938 459.35 10.8628 457.203ZM10.3169 456.988C10.5134 457.106 10.5062 457.509 10.3024 457.634C10.0913 457.759 10.1204 457.766 9.89484 457.509C9.66922 457.259 10.0258 456.814 10.3169 456.988ZM9.70561 454.202C9.873 454.195 9.98945 454.515 9.88028 454.675C9.71289 454.918 9.34173 455.015 9.26895 454.834C9.19617 454.647 9.49456 454.209 9.70561 454.202ZM9.09428 41.2209C9.48 40.9361 9.77111 41.1792 9.72017 41.7419C9.6765 42.2143 9.29078 42.256 9.00695 41.8183L8.77406 41.4571L9.09428 41.2209ZM7.43495 42.7284C7.23845 42.8465 7.03468 42.4505 7.14384 42.1726C7.26029 41.8878 7.76973 42.0754 7.76973 42.4019C7.76973 42.7075 7.66056 42.5894 7.43495 42.7284ZM8.1409 45.3056C7.91528 45.6529 7.56595 45.5974 7.56595 45.2153C7.56595 44.8054 7.71151 44.9374 8.06084 44.7915C8.32284 44.6804 8.36651 44.9513 8.1409 45.3056ZM8.50478 458.377C8.45384 458.377 8.34467 458.419 8.25734 458.468C8.17728 458.516 8.02445 458.433 7.92984 458.287C7.66056 457.87 7.95895 457.439 8.3374 457.703C8.58484 457.877 8.70856 458.377 8.50478 458.377Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M260.388 44.9235C259.682 45.0277 259.245 45.778 259.58 46.299C259.798 46.6324 260.65 46.292 260.788 45.8057C260.854 45.5835 261.196 45.6807 261.261 45.9377C261.676 47.6188 260.184 47.6327 260.65 49.7654C260.803 50.46 260.803 50.599 260.664 51.1408C260.548 51.5923 260.541 51.7938 260.628 51.9327C260.715 52.0717 260.708 52.1134 260.606 52.1134C260.49 52.1134 260.475 55.3019 260.533 71.446C260.752 134.168 260.774 163.907 260.963 187.157C261.516 254.304 260.861 451.688 260.861 451.688C261.116 452.216 261.043 452.848 260.65 453.521C260.184 454.32 260.133 455.355 260.541 455.946C260.963 456.557 260.686 457.287 260.854 457.71C260.992 458.058 261.138 457.884 261.072 457.446C260.992 456.835 261.094 456.668 261.618 456.557C262.964 456.286 262.44 454.452 261.749 455.098C260.89 455.904 260.905 455.897 260.745 455.564C260.504 455.064 260.57 454.557 260.956 453.897C261.996 452.111 260.803 451.736 261.276 450.382C261.436 449.923 261.45 449.77 261.341 449.506C261.269 449.333 261.239 449.131 261.269 449.062C261.385 448.777 261.64 235.381 261.276 168.512C261.203 155.307 261.138 109.319 261.065 98.8994C260.992 87.3956 260.934 62.6307 260.846 56.4342C260.781 52.0369 260.781 51.9814 261.021 51.2589C261.247 50.5503 261.254 50.5017 261.087 49.8279C260.846 48.8623 260.861 48.7373 261.298 47.8759C261.734 47.0006 261.785 46.1878 261.436 45.6112C261.116 45.0833 261.37 44.6456 260.948 43.4369C260.592 42.4088 260.73 42.0406 261.232 42.6936C261.953 43.6314 262.913 42.6658 262.258 41.6586C261.793 40.9361 260.905 41.8461 260.832 41.0681C260.788 40.6027 260.555 40.5679 260.657 41.0681C260.846 42.0198 260.592 42.6589 260.14 42.3393C259.522 41.9017 258.845 42.3532 258.998 43.1104C259.122 43.7287 260.119 43.8468 260.344 43.2702C260.512 42.8465 260.912 43.687 260.912 44.4511C260.905 44.8124 260.854 44.8541 260.388 44.9235ZM259.878 46.028C259.653 45.8057 259.813 45.4306 260.191 45.3125C261.232 44.993 260.352 46.4865 259.878 46.028ZM261.851 455.48C262.229 455.48 262.251 455.911 261.88 456.126C261.567 456.314 261.611 456.314 261.429 456.133C261.203 455.911 261.48 455.48 261.851 455.48ZM261.4 41.735C261.778 41.3668 262.317 42.0476 262.047 42.5616C261.887 42.8673 261.734 42.8603 261.45 42.5477C261.167 42.249 261.152 41.9712 261.4 41.735ZM259.973 43.1521C259.616 43.5967 259.354 43.5133 259.354 42.9507C259.354 42.5894 259.835 42.3949 260.046 42.6658C260.184 42.8395 260.17 42.902 259.973 43.1521Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M251.531 454.834C251.611 455.008 251.807 454.848 251.727 454.675C251.647 454.501 251.451 454.661 251.531 454.834Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M244.224 204.454C244.362 204.454 244.362 204.218 244.224 204.218C244.086 204.225 244.086 204.454 244.224 204.454Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M0.637529 26.0077C0.200863 25.8131 0.66664 24.8684 1.37986 24.5072C2.95913 23.7083 1.91841 24.1251 1.81653 27.8346C1.78014 29.1198 1.75103 29.1684 1.18336 28.8975C0.66664 28.6543 0.586584 28.7794 0.790361 29.5366C1.08147 30.6619 0.557473 31.5094 1.40897 31.0093C1.88202 30.7314 1.90386 30.7522 2.24591 32.1485C2.42058 32.8779 2.63163 33.6421 2.71169 33.8574C2.84997 34.2325 2.84269 34.2603 2.56613 34.4826C2.05669 34.9064 1.83108 35.8442 2.10764 36.4555C2.44241 37.2196 3.58502 37.5461 4.14541 37.0529C4.5093 36.7334 4.64029 36.7611 5.0624 37.2474C7.20934 39.7552 14.2906 39.0049 14.2979 32.9266C14.3052 28.4737 8.64306 27.6193 8.31556 32.0235C8.25734 32.7598 8.2064 32.9335 7.92984 33.2739C7.54412 33.7532 7.36218 34.1075 7.3549 34.3854C7.34762 34.7258 7.06379 34.7535 6.6999 34.4409C6.00851 33.8435 5.9794 34.3923 5.89207 33.3225C5.7829 32.0165 5.3899 32.5376 5.73196 31.3636C5.94301 30.6342 5.80474 30.0576 5.55001 28.7308L5.95029 28.3348C6.4379 27.8555 6.59801 26.7648 6.27051 26.1883C5.95757 25.6464 6.67079 25.0837 7.67512 25.0837C8.01717 25.0837 8.05356 25.1185 8.17001 25.5422C8.34467 26.2091 8.61395 26.5425 8.8905 26.4383C9.44361 26.2369 9.42906 25.4797 8.86139 25.0837C8.50478 24.8337 8.50478 24.8267 8.65762 24.4933C9.49456 22.6593 12.0782 22.3259 12.5221 24.0001C12.8933 25.3894 11.314 26.5217 10.9137 25.1532C10.6881 24.3891 11.2267 23.875 11.7871 24.3196C12.0199 24.5072 12.1655 24.403 12.0709 24.1181C11.9981 23.8959 11.4013 23.6666 11.1175 23.75C10.4843 23.9375 10.266 25.2227 10.7682 25.7993C11.6269 26.7718 13.2135 25.6534 12.9952 24.2293C12.6313 21.8049 9.23256 21.8952 8.32284 24.3474C7.98078 25.2713 7.58051 23.9862 6.1759 25.2921C5.92846 25.5214 5.80474 25.5561 5.47724 25.4936C4.6403 25.3269 3.97074 26.2577 4.29096 27.1261C4.53841 27.8068 4.98963 27.6054 4.60391 26.9802C4.10174 26.1674 6.08857 24.9795 5.39718 26.5495C5.12063 27.1816 5.12063 27.8624 5.08424 28.4459C5.07696 28.6057 4.90957 28.6821 4.15996 28.9114C3.35213 29.1545 3.27935 28.9044 3.53408 26.7857C3.81063 24.528 3.95619 24.1737 4.5093 24.4377C5.0624 24.7017 5.09879 24.6808 5.36079 23.9375C5.77562 22.7844 5.7829 22.8538 5.17885 22.8538C4.56752 22.8538 4.42924 22.6732 4.69124 22.2078C4.83679 21.9647 4.93868 21.916 5.36807 21.916C8.47567 21.916 11.1321 18.2621 10.1859 15.2889C10.1059 15.0319 10.0331 14.7887 10.0331 14.7471C10.0331 14.7123 10.3024 14.6081 10.6299 14.5248C11.7507 14.2399 12.1218 14.0802 13.3809 13.9829C14.4362 13.8996 14.538 13.8579 14.4216 13.5244C14.3634 13.3508 14.2324 13.3299 13.41 13.3786C11.2485 13.5105 9.90211 14.6151 9.60372 14.2122C8.65034 12.9131 6.69262 13.976 6.86001 15.6987C6.92551 16.3865 6.92551 16.4073 6.65623 16.5254C6.27051 16.6921 4.51657 18.7484 4.27641 19.3249C4.02896 19.9154 3.7888 19.9432 3.30847 19.45C2.20225 18.3038 2.64619 21.1797 1.96936 19.6653C1.17608 17.9009 2.58069 15.6571 3.73785 16.838C4.40741 17.5257 3.5268 18.7692 2.79174 18.1718C2.37691 17.8383 2.22408 18.0954 2.61708 18.4774C3.30119 19.1443 4.33463 18.5538 4.33463 17.4841C4.33463 16.2892 3.15563 15.6293 2.25319 16.317C1.15425 17.1576 0.972305 18.8526 1.83108 20.2072L2.13675 20.6865C1.9548 20.9713 1.65641 21.4854 1.25614 21.7841C0.0116414 22.708 2.82086 21.8396 2.64619 22.833C2.52247 23.5902 2.39875 23.7917 2.06397 23.7917C0.382807 23.7917 -0.825301 26.9524 0.695751 27.39C1.54725 27.6262 1.4963 26.3828 0.637529 26.0077ZM8.69401 25.3686C8.83228 25.4172 8.91234 25.5422 8.91234 25.7298C8.91234 26.098 8.75223 26.091 8.54117 25.7159C8.33739 25.3755 8.38834 25.2644 8.69401 25.3686ZM1.55453 30.5994C1.21975 30.5994 0.972305 29.6825 1.22703 29.3976C1.65641 28.9114 2.4133 30.5994 1.55453 30.5994ZM2.71897 29.4254C3.1338 29.4254 3.31574 29.6825 3.31574 30.2521C3.31574 30.5925 2.57341 30.5716 2.2823 30.2243C1.90386 29.7589 2.0858 29.4254 2.71897 29.4254ZM3.76696 36.7473C3.49769 36.8515 3.27208 36.9279 3.27208 36.9209C3.20658 36.8445 2.48608 36.7681 2.48608 35.7886C2.48608 34.8161 2.98097 34.2464 3.2648 34.8925C3.32302 35.0314 3.57046 35.4274 3.81063 35.7817C4.34918 36.5736 4.34918 36.518 3.76696 36.7473ZM3.81791 35.1704C3.23569 34.2673 3.3303 34.1145 4.5093 34.1145C5.74651 34.1145 5.81929 34.2812 5.11335 35.483C4.61846 36.3235 4.54568 36.3096 3.81791 35.1704ZM5.76835 34.9133C5.87751 34.2742 6.99829 34.7327 7.16568 35.483C7.3549 36.2957 7.90801 35.8025 7.6824 35.3926C7.50045 35.0592 7.52956 34.7536 7.8134 34.1283C8.22095 33.2253 8.34467 33.1697 8.60667 33.8088C9.39995 35.7191 12.0199 35.9206 12.0199 34.0797C12.0199 32.7668 10.6663 31.9471 9.04334 32.2805C8.52662 32.3847 8.51206 32.343 8.77406 31.4608C9.49456 28.9947 12.3838 28.8766 13.4464 31.2802C15.3386 35.5802 9.82206 40.3179 5.47724 37.0112C4.77129 36.4694 4.78585 36.5875 5.30257 35.8511C5.5209 35.5246 5.73924 35.1009 5.76835 34.9133ZM9.8075 32.5931C11.1393 32.5931 12.231 34.1492 11.3286 34.7535C10.5862 35.2537 9.69106 34.8994 8.99967 33.8366C8.43201 32.9613 8.67217 32.5931 9.8075 32.5931ZM5.89207 26.2508C6.26323 26.2508 6.19046 27.5151 5.7829 28.0083C5.03329 28.9183 5.60824 26.2508 5.89207 26.2508ZM3.61413 30.259C3.43946 29.6894 3.56319 29.3073 3.92707 29.3073C4.62574 29.3073 5.70285 28.1889 5.46996 30.9607C5.40446 31.7178 5.29529 31.8429 4.88774 31.5997C4.06535 31.1204 3.09013 31.961 3.68691 32.6348C3.93435 32.9127 4.64757 32.871 4.94596 32.5584C5.2589 32.2249 5.47724 32.4334 5.60096 33.1836C5.81201 34.4826 4.91685 33.4128 3.88341 33.7393C3.04647 34.0033 3.03919 33.9894 2.64619 32.3986C2.48608 31.7526 2.34052 31.1899 2.31869 31.1482C2.20225 30.919 2.60252 30.7314 3.01736 30.8217C3.7233 30.9815 3.81063 30.8912 3.61413 30.259ZM3.89069 32.2736C3.79608 31.9818 4.12357 31.7387 4.50202 31.822C5.7174 32.093 4.08719 32.8502 3.89069 32.2736ZM3.23569 23.8125C2.75536 23.7708 2.72625 23.7013 2.91547 23.09C3.09741 22.4996 4.04352 22.7358 4.04352 23.3679C4.04352 23.7013 3.76696 23.8542 3.23569 23.8125ZM3.3958 21.8188C3.56319 21.5757 3.61413 21.5687 3.94163 21.6868C4.45107 21.8813 4.51657 21.9786 4.35646 22.319C4.21091 22.6177 3.81063 22.7288 3.67963 22.4996C3.64324 22.437 3.5268 22.3815 3.41763 22.3815C3.16291 22.3815 3.15563 22.1731 3.3958 21.8188ZM4.75674 23.1526C5.25163 23.2498 5.28802 23.3054 5.12063 23.7569C4.97507 24.1459 4.85135 24.1946 4.35646 24.0278C3.79607 23.8472 4.16724 23.0345 4.75674 23.1526ZM8.57756 14.1357C9.50911 14.2955 9.52367 14.5525 8.63578 15.0527C7.34034 15.7821 7.34034 16.185 7.20206 15.7057C7.02012 15.0527 7.92984 14.0176 8.57756 14.1357ZM7.07107 16.6504L7.8134 16.713C8.65762 16.7824 9.12339 16.5254 9.12339 15.9766C9.12339 15.6154 9.04334 15.6154 8.70856 15.9836C8.4029 16.3101 7.90073 16.4629 7.67512 16.2892C7.4859 16.1503 7.43495 16.192 8.54117 15.539C9.58189 14.9138 9.72017 14.886 9.83661 15.2542C10.5644 17.4354 8.97784 20.5614 6.78723 21.2631C6.08129 21.4923 5.36079 21.5826 5.20796 21.4715C4.98963 21.3117 5.48451 20.6448 5.93574 20.5059C7.14384 20.1307 7.95895 19.1165 7.3549 18.7484C6.99829 18.533 6.00851 19.1999 6.00851 19.6584C6.00851 19.8251 6.03035 19.8251 6.19046 19.6584C6.48157 19.3666 7.0274 19.0887 7.08562 19.1999C7.19479 19.4013 6.20501 20.1168 6.00851 19.9779C5.95757 19.9432 5.76107 19.9988 5.56457 20.103C5.2589 20.2697 5.15702 20.2697 4.72035 20.1307L4.22546 19.971C6.01579 17.6647 5.80474 17.9217 7.07107 16.6504ZM4.23274 20.4295C4.32735 20.4572 4.60391 20.5198 4.85135 20.5614C5.52818 20.6795 5.10607 20.7004 4.93868 21.2353C4.85863 21.4923 4.07991 21.5131 3.79607 21.27C3.54863 21.0616 3.92707 20.3322 4.23274 20.4295ZM2.71169 20.1516C2.88636 19.5958 2.98097 19.6028 3.71602 20.2211C3.73785 20.2349 3.68691 20.4156 3.61413 20.6101C3.34485 21.2978 2.49336 20.8601 2.71169 20.1516ZM2.25319 21.9925C1.89658 21.8327 1.89658 21.7007 2.23136 21.2908C2.6753 20.749 3.30847 21.2631 3.0028 21.916C2.88636 22.1661 2.68986 22.187 2.25319 21.9925ZM3.25752 24.1043C3.89069 24.2224 3.51952 24.4724 3.38124 25.4936C3.25024 26.48 3.10469 27.133 3.10469 28.2723C3.10469 28.7655 3.0683 29.1892 3.02463 29.2101C2.8063 29.3143 2.18041 29.1545 2.1513 28.9878C2.10036 28.6752 2.26047 26.2369 2.37691 25.6047C2.63891 24.2015 2.49336 23.9653 3.25752 24.1043ZM0.521084 26.4245C0.673917 26.3203 0.928639 26.5912 0.928639 26.8551C0.928639 27.1052 0.724862 27.1469 0.53564 26.9316C0.382807 26.7579 0.375529 26.5287 0.521084 26.4245Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M259.42 33.5379C262.164 32.7529 260.468 28.3279 257.688 29.0156C253.474 30.0506 254.267 37.0112 258.758 38.4006C260.366 38.9007 262.782 38.2547 264.274 36.9209L264.922 36.3443C265.817 36.8098 266.523 37.3238 267.68 36.2957C268.415 35.6427 267.971 33.2947 267.12 33.2947C266.836 33.2947 266.865 33.3781 267.236 33.5935C267.993 34.038 268.073 35.3023 267.382 36.0873L266.916 36.6153L266.312 36.5527C265.322 36.4485 265.031 36.1082 265.482 35.5663C265.664 35.344 265.773 35.3093 266.13 35.3649C267.36 35.5524 267.273 33.6073 266.829 34.6216C266.545 35.2607 265.643 35.1842 266.101 34.4618C266.407 33.9755 266.196 34.1492 266.494 33.6699C267.134 32.6348 266.538 32.1833 267.833 32.1833C268.474 32.1833 268.532 32.1624 268.561 31.9193C268.597 31.6136 268.51 31.5928 268.226 31.8359C267.789 32.2111 267.236 32.0652 267.229 31.565L267.222 31.1274L267.047 31.5233C266.88 31.9054 266.858 31.9123 266.407 31.8429C265.708 31.7317 265.628 31.5928 265.81 30.7661C266.035 29.7519 265.766 29.8631 265.854 29.2448C266.057 27.6888 264.529 24.4863 263.015 23.3054C260.927 21.6799 257.601 21.9786 256.531 23.8889C255.847 25.1115 255.737 25.9868 255.767 26.0841C255.876 26.4106 256.08 26.1952 256.167 25.6534C256.793 21.8188 261.763 21.4089 264.187 25.0004C266.057 27.7721 265.737 31.0301 265.024 29.5921C264.98 29.4949 264.762 29.3212 264.551 29.1962C263.721 28.7169 262.884 27.4526 263.124 27.0566C263.496 26.4522 263.226 25.6742 262.71 25.8687C262.346 26.0077 262.229 26.4106 262.411 26.9316C262.782 27.9944 260.723 27.8972 259.973 26.8204C259.355 25.9312 259.828 24.5002 260.737 24.5002C261.116 24.5002 261.523 24.924 261.523 25.313C261.523 25.6464 261.13 26.0215 260.788 26.0215C260.453 26.0215 260.41 26.2716 260.737 26.3272C261.625 26.4731 262.149 25.2088 261.487 24.5072C260.628 23.5902 259.355 24.6044 259.486 26.098C259.617 27.5498 261.13 28.4251 262.433 27.7999C262.768 27.6401 262.775 27.6471 263.314 28.2723C264.1 29.1823 264.558 29.6199 264.798 29.7102C265.482 29.9534 265.672 30.3354 265.511 31.1691C265.446 31.5094 264.987 31.44 264.442 31.0093C264.041 30.6967 263.918 30.7245 263.918 31.1413C263.918 31.5164 263.648 32.2458 263.51 32.2458C263.452 32.2458 263.241 32.1555 263.044 32.0513C262.608 31.8151 262.156 31.9749 262.156 32.3569C262.156 32.6765 262.528 32.871 263.103 32.8571C264.005 32.8363 264.449 34.0589 263.75 34.6494C263.532 34.8369 263.328 35.0245 263.299 35.0731C262.666 36.0943 259.828 36.4902 258.503 35.74C256.866 34.8161 256.378 31.7734 257.739 31.0023C258.161 30.7661 258.19 30.787 257.906 31.1274C257.055 32.1485 258.161 33.8991 259.42 33.5379ZM262.564 26.8482C262.433 26.5703 262.593 26.091 262.797 26.1674C263.379 26.3897 262.855 27.4665 262.564 26.8482ZM262.426 32.5098C262.302 32.3708 262.353 32.1207 262.506 32.1207C262.717 32.1207 263.183 32.3778 263.183 32.4889C263.183 32.607 262.528 32.6279 262.426 32.5098ZM266.079 34.0519C265.81 34.6285 265.599 34.8022 265.504 34.5174C265.388 34.177 265.613 33.5934 265.912 33.4754C266.312 33.3156 266.356 33.4615 266.079 34.0519ZM266.239 32.0027C267.04 32.1902 266.967 32.9335 266.137 33.1072C265.526 33.2392 265.133 34.0797 265.359 34.7535C265.446 35.0106 265.431 35.1426 265.308 35.3579C265.068 35.7678 264.856 35.6983 264.631 35.1356C264.362 34.4618 264.354 34.4757 264.958 33.1905C265.628 31.7595 265.548 31.8429 266.239 32.0027ZM263.867 32.8293C263.663 32.6348 263.663 32.3083 263.859 32.1207C263.947 32.0374 264.012 31.8985 264.012 31.8081C264.012 31.4469 264.216 31.1829 264.405 31.301C265.017 31.7039 265.49 31.4678 265.002 32.607C264.696 33.3295 264.5 33.5796 264.332 33.8227L264.18 33.4059C264.092 33.1697 263.954 32.9127 263.867 32.8293ZM258.656 30.9745C259.224 30.8078 259.071 30.5438 258.379 30.5022C257.091 30.4258 256.196 32.3569 256.756 34.0241C257.717 36.914 261.145 37.4628 263.619 35.1356C264.5 34.302 264.202 35.0523 264.478 35.4691C265.053 36.3305 263.212 37.6642 260.905 38.0532C260.366 38.1435 259.871 38.213 259.82 38.2061C255.032 37.6712 253.532 30.7522 257.877 29.2518C258.576 29.0086 259.879 29.6894 260.221 30.4744C260.846 31.8985 260.09 33.4823 258.903 33.2253C257.739 32.9821 257.564 31.2941 258.656 30.9745Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M258.881 14.9832C259.631 15.3584 260.199 15.018 260.104 16.2475C259.929 18.4357 262.52 18.0815 262.615 17.9217C262.775 17.623 264.012 18.5261 264.012 18.9359C264.012 19.5403 263.35 19.8737 263.008 19.443C262.127 18.3246 262.535 20.4642 261.37 20.0335C260.417 19.6792 259.558 20.7837 260.424 21.2492C260.897 21.4992 261.014 21.4923 261.458 21.145C261.953 20.7629 262.455 21.0408 262.455 21.6937C262.455 22.0758 262.637 21.9299 262.95 21.2908C263.117 20.9504 263.335 20.6031 263.423 20.5128C263.517 20.4294 263.59 20.3044 263.59 20.2419C263.59 20.0821 264.114 19.3249 264.231 19.3249C264.747 19.3249 264.929 20.2072 264.529 20.7351L264.216 21.138C264.121 21.0199 263.707 20.4433 263.612 20.5475C263.576 20.5892 263.619 20.6934 263.714 20.7768C263.808 20.8601 263.94 21.0616 263.998 21.2353C264.143 21.666 264.252 21.6312 264.638 21.0199C265.068 20.3391 265.133 20.353 265.541 21.1936C265.919 21.9716 265.89 22.2009 265.373 22.576C264.937 22.8955 264.937 22.9303 265.402 23.9445C266.166 25.5978 265.839 26.0215 266.436 25.306C267.003 24.6392 267.069 24.7503 267.28 26.6051C267.6 29.4602 267.389 30.5161 266.545 30.259C266.29 30.1826 266.079 30.1757 266.028 30.2382C265.919 30.3563 266.035 30.4188 266.61 30.523C267.251 30.6411 267.244 31.0648 267.447 30.8356C267.571 30.6897 268.03 30.655 268.292 30.7731C268.386 30.8148 268.459 30.9954 268.466 31.2107C268.474 31.5581 268.481 31.5511 268.619 31.0579C268.794 30.4188 268.786 30.4119 268.102 30.4466L267.542 30.4744C267.564 27.6818 267.615 26.8135 267.258 25.1602C267.018 24.0487 269.078 25.0073 269.078 25.5561C269.078 25.7506 269.26 25.959 269.34 25.8618C269.703 25.4519 268.437 24.3613 267.593 24.3613C266.734 24.3613 267.244 24.4377 266.516 22.7496C266.043 21.659 266.123 21.6868 267.2 20.5823L266.807 20.0404C266.079 19.0332 266.217 18.1718 265.555 19.2624C264.835 20.4503 264.726 19.2068 264.5 19.2068C264.303 19.2068 264.434 18.7345 264.776 18.2343C265.119 17.7272 265.155 17.7063 265.468 17.8036C266.145 18.0259 266.902 17.491 266.902 16.7894C266.902 15.9836 266.116 15.8933 265.482 16.6296C264.849 17.3729 264.776 17.1367 264.012 16.1017L263.554 16.6574C262.87 17.491 262.156 17.1298 262.222 15.9766C262.273 15.0388 261.531 14.5178 260.803 14.9832C260.424 15.2264 260.381 15.2333 260.141 15.0527C258.991 14.1983 255.039 13.2466 254.682 13.7328C253.962 14.754 256.713 13.8787 258.881 14.9832ZM260.475 21.013C260.184 20.617 260.876 20.1099 261.363 20.3669C262.055 20.7143 260.803 21.4576 260.475 21.013ZM262.913 20.8462C262.586 21.2908 262.528 21.2908 262.287 20.8879C261.975 20.36 262.164 20.2141 262.702 19.5681L262.942 19.8251C263.255 20.1516 263.248 20.4017 262.913 20.8462ZM266.341 23.0067C266.902 24.396 266.923 24.6044 266.516 24.8753C266.348 24.9865 266.188 25.0768 266.167 25.0768C266.116 25.0768 265.366 23.1178 265.366 22.9719C265.366 22.8677 266.196 22.0897 266.196 22.5065C266.188 22.5829 266.254 22.8052 266.341 23.0067ZM265.351 20.0613C265.468 19.8251 265.97 19.2693 266.014 19.3388C266.05 19.4083 266.676 20.4225 266.734 20.5198L266.428 20.9435C266.261 21.1797 266.072 21.3881 266.014 21.4089C265.824 21.4853 265.242 20.2905 265.351 20.0613ZM265.679 16.838C266.108 16.4351 266.538 16.4281 266.581 16.8311C266.603 17.0186 266.523 17.1576 266.268 17.3312C265.533 17.8453 265.046 17.4424 265.679 16.838ZM263.976 16.7477L264.325 17.0395C264.842 17.4702 264.856 17.5605 264.522 18.1162C264.151 18.7275 264.216 18.7275 263.765 18.1301C263.234 17.4285 263.314 17.4632 263.976 16.7477ZM261.436 15.1083C261.793 15.1083 262.142 15.6918 262.142 16.3031C262.142 16.4629 262.018 16.4004 261.48 15.9836C260.621 15.3167 260.614 15.1083 261.436 15.1083ZM260.439 16.1642C260.534 15.6849 260.745 15.7126 261.414 16.2823C262.52 17.227 262.71 17.4563 262.484 17.6091C261.691 18.1648 260.25 17.1437 260.439 16.1642Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M269.405 26.2508C269.405 26.0563 269.361 26.0146 269.223 26.0771C268.779 26.2786 267.68 26.5356 268.168 27.5498C268.277 27.786 268.888 27.8833 268.888 27.661C268.888 27.5984 268.801 27.5429 268.692 27.5429C268.423 27.5429 268.262 27.2858 268.335 26.9732C268.408 26.6537 268.925 26.3272 269.201 26.4314C269.354 26.487 269.405 26.4522 269.405 26.2508Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M269.194 27.2511C269.252 27.2094 269.296 27.0913 269.296 26.9802C269.296 26.619 268.917 27.4456 269.194 27.2511Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M109.105 11.8364C109.222 11.9406 109.316 12.0865 109.316 12.149C109.316 12.3365 110.685 13.8509 111.056 14.0732C111.347 14.2469 111.39 14.3372 111.39 14.7401C111.39 15.6293 112.002 16.6157 112.715 16.8727C113.224 17.0603 113.217 17.0464 113.297 17.9356C113.377 18.8595 113.348 18.8803 112.293 18.7206C111.056 18.533 110.073 17.9008 110.19 17.366C110.437 16.2406 110.241 15.6849 109.578 15.6849C108.909 15.6849 108.727 16.6018 109.244 17.3729C109.586 17.88 109.549 17.9842 108.974 18.1718C108.501 18.3315 108.37 18.4566 108.458 18.6997C108.552 18.9915 109.396 18.6719 109.724 18.2273C109.84 18.0676 109.898 18.0884 110.233 18.3871C110.765 18.8595 111.5 19.1165 112.562 19.186C113.275 19.2346 113.486 19.2902 113.53 19.4361C114.112 21.4715 115.633 23.1595 115.859 23.3054C116.085 23.4513 117.395 24.653 118.77 24.8267C126.521 25.8131 128.311 15.8585 122.867 14.2191C118.588 12.927 115.786 19.4569 119.862 21.2075C122.336 22.2703 124.782 18.6303 122.496 17.2895C121.208 16.5393 120.066 17.616 120.873 18.8178C121.186 19.2832 121.543 19.3458 121.543 18.9429C121.543 18.3524 122.111 18.1996 122.533 18.6789C123.77 20.0821 121.434 21.7563 119.68 20.7351C116.092 18.6441 119.665 12.8367 123.341 14.7818C128.559 17.5396 124.52 25.7228 118.625 24.3404C116.07 23.743 112.635 19.3597 114.323 18.8595C115.837 18.4149 116.798 17.0464 116.849 15.2819C116.885 14.1496 116.9 14.3164 117.664 13.8092C118.392 13.323 118.959 12.7881 119.891 12.0795C120.255 11.8016 120.793 11.2181 122.402 10.7596C123.915 10.3289 127.154 11.3084 127.431 12.274C127.46 12.3782 127.431 12.406 127.351 12.3435C127.278 12.2949 126.841 12.2601 126.375 12.2671C125.597 12.281 125.524 12.2601 125.429 12.017C125.255 11.5655 124.993 11.621 124.869 12.1351C124.811 12.3852 124.6 12.7881 124.396 13.0382C123.26 14.4414 124.883 12.9756 126.455 13.4689C127.205 13.705 127.212 13.2188 126.463 12.8159C125.924 12.5241 126.019 12.3852 126.703 12.4685C128.027 12.6283 128.966 14.1566 130.56 15.3306C132.168 16.5115 130.662 15.5737 130.116 16.6088C130.021 16.7963 129.738 17.0811 129.49 17.2479C127.947 18.269 128.056 20.5475 129.65 20.7004C130.902 20.8185 131.477 19.0262 130.349 18.4983C129.949 18.3107 129.476 18.533 129.476 18.9081C129.476 19.2207 129.701 19.2693 129.781 18.9776C129.861 18.6789 130.225 18.658 130.414 18.9429C130.902 19.6723 130.145 20.5823 129.366 20.2072C128.835 19.9571 128.624 19.3874 128.799 18.6858C129.017 17.7897 129.927 17.0881 130.094 17.6786C130.233 18.1718 131.011 18.144 131.062 17.6438C131.135 16.9283 129.687 17.0811 130.56 16.5671C131.499 16.0183 134.286 17.2062 134.468 16.6782C134.548 16.442 134.388 16.3239 133.893 16.2336C133.056 16.0808 132.43 14.8721 133.187 14.8721C134.723 14.8721 133.566 13.323 132.765 14.1705C132.343 14.622 131.914 13.9968 131.914 12.927C131.914 11.8572 133.347 11.489 133.675 12.4755C133.915 13.1979 133.1 13.7467 132.823 13.0521C132.707 12.7603 132.532 12.7186 132.46 12.9548C132.307 13.4689 133.355 13.837 133.77 13.4133C134.657 12.5033 133.435 11.0375 132.299 11.6558C131.433 12.1212 131.353 13.7676 132.161 14.49C132.299 14.6151 132.46 14.9138 132.525 15.1638C132.583 15.4139 132.736 15.7335 132.867 15.8863C133.784 16.9908 131.302 15.7126 130.254 14.5386C129.075 13.2257 128.653 11.0236 129.701 11.6419C130.502 12.1142 131.397 11.4404 131.033 10.6346C130.815 10.1483 129.949 10.0997 129.476 10.5373C129.236 10.7596 129.003 10.447 129.039 9.95382C129.068 9.54397 129.083 9.53007 129.578 9.4745C130.145 9.41198 130.327 9.20358 130.225 8.73815C130.131 8.32135 129.832 8.24493 129.417 8.52975C128.741 8.99518 127.809 8.34913 128.086 7.60584C129.046 4.97998 125.378 2.62505 124.185 5.10503C123.362 6.80697 124.847 8.75899 125.924 7.39744C126.186 7.07094 126.375 6.19566 126.186 6.19566C126.164 6.19566 126.07 6.16787 125.982 6.12619C125.851 6.07062 125.837 6.13314 125.888 6.48047C126.041 7.52248 124.774 7.81424 124.381 6.82781C123.595 4.87578 126.31 3.6879 127.46 5.48015C128.02 6.35543 127.998 7.76561 127.423 7.78645C126.732 7.81424 126.652 7.84203 126.55 8.05737C126.288 8.60616 126.914 9.0577 127.387 8.66174C128.369 7.84203 129.024 9.25221 128.915 11.9267C128.901 12.2532 128.966 12.7256 129.075 13.0521C129.366 13.9204 129.236 13.837 127.816 12.2532C126.172 10.4193 125.749 10.0928 123.748 9.09938C122.613 8.5367 121.856 7.39744 122.664 7.4669C123.224 7.51553 123.231 7.4669 122.773 6.89033C122.132 6.08451 122.052 4.11859 121.718 5.61908C121.557 6.32765 121.325 6.82781 121.004 7.10568C120.509 7.55026 120.997 7.77951 121.696 7.43217C122.052 7.25156 122.147 8.48807 122.918 8.80762C123.552 9.07159 117.933 8.27272 118.974 7.54332C119.221 7.36965 118.719 6.81391 118.595 7.3627C118.399 8.22409 117.009 7.39744 117.009 6.41795C117.009 5.50099 118.064 5.11197 118.595 5.83443C118.894 6.23734 119.076 6.28597 119.076 5.96642C119.076 5.34121 118.057 4.8341 117.38 5.12587C116.121 5.66771 116.645 7.91844 118.05 7.98096C118.319 7.99485 118.639 8.106 118.836 8.25883C119.025 8.39776 119.36 8.55059 119.585 8.59922C120.109 8.69647 120.029 8.85624 119.403 8.96044C117.999 9.19663 116.638 9.94688 115.561 11.0722C114.826 11.8433 114.702 11.9336 114.425 11.8711C113.457 11.6488 112.016 12.4685 111.652 13.4411C111.456 13.969 111.281 13.9204 110.583 13.1493C109.003 11.3918 108.37 9.07854 109.062 7.57805C109.207 7.2585 109.324 6.90422 109.324 6.79307C109.324 5.84138 110.874 4.47288 112.096 4.34784C115.109 4.04218 116.485 8.3144 113.858 9.84962C111.98 10.9472 109.84 8.01569 111.623 6.78613C112.526 6.16092 113.661 7.08484 113.203 8.07821C113.028 8.46028 113.05 8.63395 113.246 8.49502C114.425 7.66836 112.962 5.76496 111.623 6.38322C109.396 7.41133 111.238 11.0375 113.617 10.2942C117.067 9.22442 115.488 3.3614 111.922 3.99355C109.003 4.49372 107.06 9.93298 109.105 11.8364ZM109.367 16.9075C109.222 16.5254 109.222 16.442 109.353 16.2962C110.059 15.5042 109.862 18.2621 109.367 16.9075ZM122.802 18.5608C122.62 18.3107 122.154 18.0398 121.9 18.0398C121.499 18.0398 120.917 19.311 120.917 18.1092C120.917 17.0742 122.365 17.1784 122.918 18.2482C123.151 18.6928 123.064 18.9151 122.802 18.5608ZM126.324 13.0312C126.463 13.1493 126.346 13.1771 125.626 13.1771C124.694 13.1701 124.687 13.1701 124.883 12.7464C125.167 12.1351 125.175 12.1351 125.487 12.5172C125.648 12.7186 125.866 12.8853 125.968 12.8853C126.07 12.8784 126.23 12.9479 126.324 13.0312ZM130.764 17.5188C130.764 17.7828 130.596 17.8105 130.407 17.5813C130.036 17.1159 130.764 17.1992 130.764 17.5188ZM133.136 14.1844C133.457 14.1357 133.675 14.365 133.457 14.5178C133.369 14.5803 133.195 14.629 133.064 14.629C132.736 14.6359 132.802 14.2399 133.136 14.1844ZM130.043 10.6485C130.589 10.6485 130.938 11.0514 130.633 11.3223C130.298 11.621 129.796 11.5585 129.527 11.1903C129.323 10.8986 129.563 10.6485 130.043 10.6485ZM129.57 8.82846C129.796 8.82846 130 9.23831 129.57 9.23831C129.141 9.23831 129.345 8.82846 129.57 8.82846ZM126.856 8.25883C126.907 8.09211 127.452 8.0018 127.452 8.16157C127.445 8.51586 126.776 8.52975 126.856 8.25883ZM121.667 7.11262C121.332 7.32102 121.325 7.2724 121.623 6.71666C122.162 5.70939 121.972 6.43185 122.351 6.92506C122.562 7.20293 122.431 7.32102 122.125 7.14041C121.943 7.02231 121.827 7.01537 121.667 7.11262ZM114.818 18.2968C113.756 18.8456 113.566 18.7345 113.566 17.5535C113.566 16.9908 113.661 16.8658 114.083 16.8658C114.338 16.8658 114.811 16.2128 114.811 15.8585C114.811 15.4556 114.673 15.5042 114.469 15.9905C114.127 16.8102 113.457 16.9075 113.545 16.1294C113.654 15.1638 113.676 15.15 114.571 15.0666C115.015 15.0249 115.641 14.8929 115.954 14.7609C117.453 14.1566 116.383 17.484 114.818 18.2968ZM124.41 9.77321C126.011 10.5999 126.55 11.1487 125.255 10.6346C123.704 10.0233 121.587 10.3984 119.935 11.5863C118.464 12.6352 118.224 13.1771 117.154 13.7328C116.652 13.9899 116.754 14.0593 116.521 13.4827C116.303 12.934 115.801 12.3643 115.386 12.1837L115.08 12.0517C117.984 8.62006 121.958 8.50196 124.41 9.77321ZM115.881 13.0312C116.623 13.9204 116.601 14.2399 115.772 14.5039C114.025 15.0666 113.705 14.8304 114.309 13.455C114.906 12.0795 115.051 12.0378 115.881 13.0312ZM114.069 12.1698C114.585 12.1698 114.585 12.149 114.141 13.1701C113.945 13.6217 113.727 14.1635 113.661 14.3719C113.501 14.879 112.482 14.754 111.834 14.1427C111.296 13.6425 112.97 12.1698 114.069 12.1698ZM112.053 14.6151C112.082 14.6706 112.402 14.8096 112.759 14.9277C113.115 15.0458 113.421 15.15 113.435 15.1569C113.45 15.1638 113.399 15.5112 113.326 15.921C113.173 16.7894 113.137 16.8172 112.599 16.4629C112.118 16.1433 111.703 15.4209 111.703 14.8929C111.696 14.5386 111.914 14.365 112.053 14.6151Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M138.398 17.0464C137.954 17.366 137.918 17.9634 138.34 18.0189C138.602 18.0537 139.06 17.6021 139.184 17.1992C139.221 17.0881 139.301 17.102 139.512 17.2618C140.043 17.6577 139.999 18.1093 139.366 18.8525C138.398 19.9779 138.704 21.5618 139.883 21.5618C140.087 21.5618 139.985 21.2214 139.759 21.145C138.922 20.8601 138.849 20.1377 139.57 19.186C140.902 17.4215 139.701 17.1645 138.988 16.4004C138.405 15.7821 137.27 15.9697 138.151 15.5668C138.966 15.1986 140.225 13.6634 141.353 12.7811C143.027 11.4752 143.645 13.9273 142.721 13.9273C142.466 13.9273 142.459 14.1705 142.699 14.3928C143.252 14.9138 144.3 14.3302 144.068 13.6286C144.002 13.4341 144.286 13.3716 144.388 13.5522C144.482 13.7189 144.977 13.7815 145.276 13.6634C145.814 13.455 145.967 12.5033 145.538 12.0448C145.268 11.76 145.065 11.8016 145.065 12.149C145.065 12.7047 144.366 12.8506 143.733 12.4338C143.362 12.1907 143.063 12.0934 142.474 12.0448L141.695 11.9823C144.162 10.3845 146.462 9.76626 150.428 12.8089C152.299 14.2399 152.568 14.4206 153.39 14.747C154.147 15.0527 154.213 15.1361 154.315 16.0044C154.373 16.4837 154.358 16.5185 153.943 16.845C153.136 17.4702 152.764 18.4427 153.179 18.8317C153.601 19.2277 154.431 18.401 154.526 17.484C154.591 16.8519 154.584 16.8588 155.13 16.7199C155.799 16.5532 155.879 17.0603 155.486 19.0262C155.035 21.2978 152.561 23.8333 150.275 24.3752C147.503 25.0282 143.718 22.7705 143.718 20.4572C143.718 20.36 143.675 20.2419 143.616 20.2002C143.42 20.0682 143.5 18.2273 143.733 17.3729C144.57 14.3164 148.674 13.3924 150.392 15.8724C152.16 18.4288 149.882 22.2286 147.328 20.9782C146.025 20.3391 145.538 18.79 146.353 17.9217C147.124 17.102 148.434 17.9356 148.07 19.0193C147.939 19.4152 148.092 19.5055 148.456 19.2624C149.038 18.8664 149.366 17.9703 149.126 17.4076C149.067 17.2687 148.987 17.0603 148.958 16.9422C148.864 16.6088 148.267 16.2684 147.772 16.2684C147.364 16.2684 147.313 16.2336 147.212 15.9071C147.008 15.2403 146.156 15.2611 145.734 15.9419C145.516 16.2962 145.53 16.3726 145.829 16.5046C147.095 17.0464 143.98 19.3597 147.124 21.2978C148.369 22.0619 150.618 20.9227 151.061 19.3041C151.855 16.3934 150.37 14.2122 147.597 14.2191C141.651 14.226 141.702 23.4721 147.648 24.7295C150.559 25.3477 154.118 23.361 155.224 20.4989C155.377 20.103 155.938 18.9845 155.938 17.5118C155.938 16.6782 156.039 16.6227 157.037 16.9561C158.019 17.2826 158.099 17.2756 157.779 16.8866C157.451 16.4907 156.84 15.1291 156.92 14.9763C157.131 14.5873 157.961 14.622 158.07 15.018C158.179 15.407 160.122 18.3941 159.154 18.8456C158.15 19.318 158.179 20.9643 159.191 20.6795C159.518 20.5892 159.678 20.2627 159.758 19.4986L159.824 18.9012L160.268 18.8664C160.85 18.8178 160.894 18.4913 160.312 18.4913C159.256 18.4913 160.261 18.0189 158.499 15.1777C158.266 14.8026 158.099 14.4831 158.121 14.4692C158.143 14.4483 158.478 14.1844 158.863 13.8787C159.78 13.1493 159.336 13.4341 159.955 12.6769C161.098 11.2598 161.17 7.62668 160.086 5.94558C158.332 3.22942 155.042 3.68095 154.242 6.74445C153.9 8.05043 154.751 10.2734 155.603 10.2873C155.705 10.2873 155.872 10.3706 155.989 10.4609C156.491 10.8916 157.866 10.5373 158.47 9.82878C159.824 8.23104 158.434 5.74412 156.694 6.64719C155.814 7.09873 155.719 9.11327 156.578 9.11327C156.84 9.11327 156.825 8.90487 156.542 8.64784C155.639 7.82119 156.942 6.31375 158.019 6.9459C159.569 7.85592 158.317 10.5165 156.44 10.2873C153.405 9.91909 154.118 4.54234 157.197 4.5354C160.806 4.52845 161.716 11.364 158.427 13.844C157.968 14.1913 157.961 14.0385 157.611 13.2466L158.07 12.7395C159.387 11.2806 157.662 10.8638 157.422 12.531C157.364 12.927 157.313 12.9965 156.986 13.1007C156.323 13.3091 156.316 13.3091 156.185 12.01C156.003 10.2247 155.537 12.934 153.427 10.9472C152.99 10.5373 152.495 10.1344 152.313 10.0511C152.029 9.91909 151.862 9.5787 152.073 9.5787C152.444 9.5787 152.612 8.17547 152.291 7.74477C152.219 7.64752 152.255 7.45301 152.408 7.10568C152.946 5.9039 151.891 4.39646 150.85 4.88273C150.261 5.1606 150.021 6.04978 150.421 6.45963C150.639 6.68193 150.858 6.49437 150.647 6.25818C150.465 6.05672 150.508 5.61214 150.741 5.35511C151.28 4.7438 152.19 5.36205 152.19 6.33459C152.19 7.07789 152.029 7.51553 151.797 7.39744C151.142 7.07094 150.319 7.3627 150.487 7.86287C150.552 8.05737 150.647 8.07821 151.273 8.02264C152.219 7.94623 152.466 8.40471 151.971 9.32862C151.738 9.75932 151.782 9.75932 150.785 9.34251C147.67 8.04348 145.822 9.5787 147.182 8.13379C147.481 7.82119 147.772 7.39049 147.837 7.1682C147.961 6.75139 148.471 6.17482 148.725 6.17482C148.805 6.17482 148.871 6.09841 148.871 6.00115C148.871 5.22312 147.343 5.11197 147.168 5.87611C147.117 6.11925 147.044 6.17482 146.746 6.17482C146.142 6.17482 145.705 6.89728 146.222 7.04316C147.321 7.35576 146.833 8.50196 145.276 9.27999C144.089 9.87046 142.969 10.5373 142.619 10.8569C141.499 11.885 140.152 13.455 140.152 13.455C140.087 13.455 140.087 13.3785 140.152 13.2327C140.465 12.5727 140.582 11.9128 140.465 11.5029C140.174 10.4957 140.582 8.82151 141.091 8.94655C141.579 9.06465 141.608 9.09938 141.608 9.49534C141.608 10.9194 143.02 10.1275 142.212 9.15495L141.979 8.87014C141.979 8.86319 142.481 7.82119 142.488 7.82119C142.488 7.82119 142.656 7.87676 142.852 7.93928C144.81 8.58532 146.251 5.34121 144.424 4.40341C143.223 3.78515 142.117 4.93136 142.918 5.95947C143.252 6.39017 144.119 6.28597 144.257 5.7997C144.351 5.45236 144.22 5.40373 143.958 5.68855C143.66 6.0081 143.471 6.0081 143.18 5.70244C142.692 5.18144 143.034 4.66044 143.886 4.61876C145.283 4.55624 145.443 6.57078 144.097 7.31408C143.172 7.82813 142.75 7.78645 142.532 7.14736C142.386 6.70971 142.226 6.8417 142.226 7.39049C142.226 7.92539 141.862 8.71036 141.63 8.68952C141.564 8.68258 141.317 8.66868 141.091 8.66174C139.897 8.61311 141.753 6.64719 140.618 6.64719C140.414 6.64719 140.152 6.59162 140.043 6.52215C139.781 6.36238 139.504 6.58467 139.592 6.89728C139.686 7.23766 139.453 8.43944 139.228 8.78678C138.886 9.31473 139.126 9.64817 139.599 9.29389C139.883 9.08549 140.414 9.05075 140.305 9.24526C140.269 9.31473 140.203 9.64817 140.167 9.98161C140.116 10.4262 140.058 10.5721 139.948 10.5443C139.301 10.3637 139.068 10.3915 138.784 10.6902C138.122 11.3848 139.06 12.3365 139.774 11.6974C140.152 11.3571 140.334 11.3918 140.305 11.8016C140.203 13.5244 138.995 14.8721 136.448 16.1086C135.829 16.4143 135.764 16.2962 136.164 15.6154C136.673 14.7679 136.157 14.2399 136.928 14.358C137.372 14.4275 137.598 14.2122 137.547 13.7815C137.51 13.5105 137.139 13.4411 136.491 13.5869C135.938 13.712 135.596 12.1004 136.062 11.5446C136.528 10.9889 137.256 11.1973 137.256 11.885C137.256 12.2949 137.074 12.5936 136.797 12.6491C136.455 12.7186 136.477 12.9826 136.826 12.9826C137.51 12.9826 137.838 11.753 137.321 11.1626C136.128 9.81489 134.89 11.9962 135.924 13.6286C136.491 14.5248 136.062 15.9488 135.123 16.2892C134.614 16.4698 134.439 16.6643 134.687 16.7685C134.832 16.8311 135.261 16.7685 136.892 16.449C138.384 16.1711 139.177 16.4907 138.398 17.0464ZM138.828 17.3034C138.791 17.5188 138.529 17.6369 138.405 17.4979C138.311 17.3868 138.529 17.102 138.718 17.102C138.798 17.102 138.849 17.1853 138.828 17.3034ZM143.9 12.802C144.257 13.0104 145.036 12.8784 145.232 12.5797C145.392 12.3226 145.581 12.4546 145.581 12.8159C145.581 13.5314 144.606 13.6634 144.046 13.0243C143.857 12.8089 143.66 12.8992 143.704 13.1771C143.726 13.3021 143.762 13.5314 143.784 13.6911C143.813 13.8509 143.791 14.0454 143.747 14.1218C143.645 14.2886 143.172 14.4344 143.071 14.3302C143.034 14.2886 143.092 14.1149 143.202 13.9551C143.434 13.6147 143.449 13.4411 143.26 12.8506C143.107 12.3782 143.165 12.3713 143.9 12.802ZM153.762 18.5122C153.449 18.6997 153.194 18.4635 153.318 18.0815C153.412 17.7758 153.987 17.095 154.155 17.095C154.431 17.102 154.096 18.3038 153.762 18.5122ZM146.098 15.8724C146.389 15.4765 147.088 15.8655 147.001 16.3726C146.92 16.8588 147.015 17.0117 147.27 16.8033C148.26 16.0183 149.388 17.6716 148.703 18.6303C148.492 18.922 148.434 18.8734 148.332 18.3177C148.216 17.6994 147.845 17.4076 147.088 17.359L146.426 17.3104L146.353 16.8866C146.229 16.1086 145.865 16.185 146.098 15.8724ZM159.533 19.1374C159.627 19.2485 159.453 19.9015 159.242 20.2072C158.987 20.5684 158.929 20.5753 158.761 20.2627C158.543 19.8668 159.256 18.8248 159.533 19.1374ZM158.135 11.8225C158.296 11.8225 158.223 12.2532 158.026 12.4477C157.823 12.6561 157.764 12.6769 157.67 12.5727C157.539 12.413 157.895 11.8225 158.135 11.8225ZM150.938 7.57805C151.025 7.4808 151.156 7.4669 151.404 7.55026L151.746 7.66141C150.821 8.03653 150.799 7.73783 150.938 7.57805ZM146.673 6.99453C146.535 6.8417 146.447 6.68193 146.469 6.6333C146.549 6.48047 146.891 6.5291 147.022 6.71666C147.226 6.99453 147.335 6.92506 147.335 6.50131C147.335 6.05672 147.685 5.54962 147.925 5.64687C148.012 5.6816 148.121 5.71634 148.172 5.71634C148.485 5.71634 147.976 6.22345 147.612 7.0501C147.219 7.96012 146.92 8.16852 146.92 7.52942C146.928 7.38354 146.811 7.14736 146.673 6.99453ZM153.871 13.5105C153.871 13.4202 154.86 13.6217 154.991 13.7328C155.122 13.8509 155.428 14.5664 155.428 14.7679C155.428 14.8235 155.195 14.8721 154.919 14.8721H154.409C154.358 14.7609 153.871 13.5661 153.871 13.5105ZM154.649 16.3378C154.38 15.0458 154.366 15.1013 154.897 15.1083C155.421 15.1083 155.545 15.2403 155.603 15.8446L155.654 16.3726C155.399 16.3934 154.679 16.4837 154.649 16.3378ZM157.415 13.4411C157.742 13.8092 157.757 14.3372 157.444 14.497C156.898 14.7748 156.687 14.6915 156.585 14.1357C156.476 13.5175 157.051 13.0312 157.415 13.4411ZM157.102 16.3726C157.175 16.8727 155.989 16.5324 155.901 16.0252C155.756 15.2125 155.799 15.1083 156.243 15.1083C156.658 15.1083 156.986 15.5876 157.102 16.3726ZM156.44 14.6151C156.36 15.1013 155.668 14.9207 155.501 14.3719C155.304 13.7189 155.363 13.5731 155.799 13.5731C156.178 13.58 156.52 14.1357 156.44 14.6151ZM155.537 11.885L155.908 11.7947C155.938 12.0309 156.076 13.0173 156.083 13.1632C156.112 13.6425 155.232 13.3855 154.89 12.8159C154.242 11.7252 154.606 12.1073 155.537 11.885ZM152.284 10.3498C152.954 10.7874 153.456 11.2181 153.456 11.3501C153.456 11.5655 152.255 11.4752 151.993 11.2459C151.855 11.1278 151.549 10.9125 151.302 10.7735C150.792 10.4818 150.814 10.3567 151.382 10.1622C151.746 10.0372 151.826 10.058 152.284 10.3498ZM144.046 10.2664C145.778 9.25915 147.299 8.89098 148.769 9.11327C150.96 9.44671 152.095 10.2942 150.348 10.2942C149.97 10.2942 150.13 10.4957 150.719 10.7457C152.139 11.364 151.527 11.753 152.961 11.7669C153.893 11.7808 154.184 11.9475 154.562 12.7047C154.853 13.2882 154.773 13.3716 154.031 13.2118C152.917 12.9756 153.463 13.2535 153.856 14.1288L154.074 14.629C153.267 14.6151 152.153 13.7398 151.214 13.0243C149.031 11.364 147.488 9.95382 144.206 10.5651C143.296 10.7388 143.282 10.711 144.046 10.2664ZM142.219 9.59954C142.314 9.94688 142.11 10.1483 141.964 9.84268C141.666 9.21747 142.117 9.24526 142.219 9.59954ZM139.817 8.27272C139.97 7.13346 140.181 6.82086 140.582 7.11262C140.727 7.21682 140.574 8.34914 140.37 8.627C140.094 9.01602 139.745 8.79372 139.817 8.27272ZM139.825 11.3084C139.519 11.5655 138.944 11.5168 138.944 11.239C138.944 10.968 139.235 10.7666 139.614 10.7666C139.963 10.7666 140.087 11.0931 139.825 11.3084ZM137.088 13.6981C137.328 13.6981 137.357 13.9968 137.125 14.0941C136.906 14.1844 136.899 14.1844 136.819 14.0454C136.732 13.8718 136.863 13.6981 137.088 13.6981Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M30.7966 20.7143C31.2987 21.2839 32.0483 20.3322 31.6117 19.6653C31.3278 19.2346 31.3424 19.0401 31.6626 18.8734C32.223 18.5816 32.434 18.6858 32.434 19.2346C32.434 20.0891 33.0235 20.6309 33.4238 20.1377C33.6203 19.8876 33.5039 19.4569 33.0308 18.6997C32.6742 18.1301 33.6931 18.1093 34.2389 18.6719C34.6756 19.1304 35.2578 19.2207 35.7454 18.9151C35.9638 18.7761 36.0584 18.7761 36.364 18.929C37.1573 19.3041 64.7619 18.9151 93.7128 18.79C113.123 18.7067 109.811 18.3246 101.442 18.4288C91.9734 18.5469 77.7526 18.5052 64.9584 18.6303C44.9736 18.8248 36.5605 18.7831 36.4004 18.4913C36.3131 18.3246 35.7673 18.3732 35.3815 18.5886L35.0177 18.7831C34.7338 18.5677 33.9697 17.9425 33.7222 17.9147C32.6597 17.7966 33.0963 18.3871 32.2958 18.3871C31.8809 18.3871 31.2842 18.665 31.2842 18.8595C31.2842 19.0471 30.9712 18.9915 30.9057 18.79C30.8693 18.6858 30.9348 18.5122 31.0586 18.3871C31.4006 18.0259 31.4588 17.484 31.175 17.2062C30.6146 16.6574 30.0906 17.095 30.1707 18.0328C30.2143 18.5538 30.1925 18.658 29.9814 18.8456L29.7413 19.0609L30.1852 19.0054C31.5389 18.8387 30.2871 20.1377 30.7966 20.7143ZM32.7543 19.0262C32.8634 18.9498 33.089 19.179 33.1837 19.4639C33.271 19.7278 33.0163 19.971 32.878 19.7695C32.7179 19.5472 32.6451 19.1026 32.7543 19.0262ZM31.3933 20.3252C31.1604 20.6448 30.9785 20.5128 30.9785 20.0196C30.9785 19.1096 31.6117 20.0335 31.3933 20.3252ZM30.52 17.5188C30.8548 17.1367 31.2114 17.6091 30.9712 18.1093C30.8111 18.4496 30.6073 18.4705 30.4618 18.1579C30.3235 17.8592 30.3308 17.7341 30.52 17.5188Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M16.3866 14.5178C16.4448 14.5178 16.6195 14.622 16.7723 14.7401C17.2017 15.0874 19.1958 15.8099 19.9454 15.8863C20.7314 15.9697 20.7969 16.1156 20.302 16.7199C19.1085 18.1579 16.7141 17.4007 16.3648 15.4765C16.1974 14.5456 16.1828 14.497 16.0445 14.5873C15.8772 14.7054 16.0009 15.6988 16.2556 16.2684C17.2017 18.3732 20.0109 18.5191 20.8333 16.5046C21.0007 16.1017 21.0371 16.0808 21.6484 16.0044C23.0457 15.8377 23.1549 15.8933 23.4606 16.838C23.7226 17.6369 23.708 17.6299 24.5304 17.1506C25.3965 16.6435 25.4256 16.6574 25.7603 17.6925C25.9641 18.3246 25.9641 18.3454 25.7749 18.7484C25.3164 19.707 25.7895 20.6656 26.4008 20.0196C26.6191 19.7904 26.6337 19.7 26.5755 18.9984C26.4881 17.9564 26.7574 17.616 27.2377 18.1579C27.4925 18.4427 27.8563 18.2968 27.8563 17.9009C27.8563 17.4007 28.9043 18.0259 29.0426 18.6094C29.1227 18.9429 29.1008 18.9706 28.7369 19.0471C28.0674 19.186 27.7472 19.6931 27.9509 20.3044C28.2566 21.2144 29.2973 20.4711 29.3847 19.2832C29.5011 17.6925 28.1911 16.8241 26.7865 17.5744C26.2916 17.8383 25.986 17.7758 25.986 17.4146C25.986 17.3451 25.9132 17.1298 25.8331 16.9492C25.6221 16.4976 25.673 16.449 26.5609 16.2267C27.4342 16.0044 27.5361 15.921 27.2086 15.671C24.9452 13.9482 27.376 14.6081 28.7224 11.1626C29.6903 8.68258 29.6321 6.17482 28.555 3.7921C25.804 -2.30015 16.9324 0.145087 17.3181 6.89728C17.6311 12.3991 24.0501 14.2677 26.0806 8.62701C26.6846 6.95285 25.3673 4.41036 23.7517 4.13249C23.2495 4.04913 23.184 3.86157 23.446 3.27805C23.7444 2.63201 23.89 2.59033 24.3121 3.0627C24.938 3.75042 25.6002 3.92409 25.9423 3.50034C26.3571 2.98629 25.5857 2.13184 24.6468 2.06932L24.0792 2.03459L24.0064 1.45107C23.7517 -0.591264 27.3105 1.74977 28.3439 4.30616C28.7733 5.36901 28.7806 5.38985 28.9334 6.4388C29.3337 9.16191 28.424 11.9267 26.5318 13.6634C25.9132 14.2399 25.804 14.226 25.5711 13.587C25.4474 13.2535 25.462 13.2049 25.8258 12.7881C26.5755 11.9197 26.459 10.6138 25.673 11.0584C25.1854 11.3362 24.8797 12.4199 25.5784 11.6627C26.5245 10.6346 25.9132 12.9062 25.1854 12.7186C25.0035 12.67 24.9525 12.7117 24.9525 12.8992C24.9525 13.1702 24.4212 13.4828 23.97 13.4828C23.5697 13.4828 23.5479 13.7745 23.9045 14.3997C24.3703 15.2264 24.363 15.2542 23.446 15.4139C22.7983 15.5251 22.6527 15.1083 22.0487 13.7398L21.35 13.8023C20.4912 13.8787 20.5567 13.7884 20.7096 14.6429C20.8479 15.4209 20.7387 15.7752 20.4039 15.6571C20.3384 15.6362 17.2381 15.0458 16.5758 14.1496C16.2629 13.7259 17.4637 12.6561 18.257 12.6561C18.7155 12.6561 19.254 13.1702 19.254 13.6217C19.254 14.4761 18.4244 14.7123 18.0896 13.9482C17.864 13.4411 17.6384 13.4063 17.6675 13.8787C17.7403 15.011 19.6761 14.9971 19.6616 13.8648C19.6398 12.0378 17.3618 11.6975 16.4375 13.3786C16.1392 13.9273 16.0009 13.9343 15.4259 13.4133C14.9529 12.9826 14.6909 12.8923 14.6909 13.1563C14.7127 13.3994 16.0809 14.5178 16.3866 14.5178ZM28.8316 19.9849C28.5623 20.2211 28.2857 20.1863 28.2857 19.9223C28.2857 19.6862 28.6423 19.3319 28.8752 19.3319C29.079 19.3319 29.0426 19.8112 28.8316 19.9849ZM26.3207 19.1929C26.3207 19.582 26.1461 19.7973 26.0515 19.5194C25.8841 19.0401 26.3207 18.5469 26.3207 19.1929ZM21.7867 5.00778C21.8595 5.00778 22.0996 4.90358 22.3325 4.77854C22.9075 4.46593 22.9584 4.47983 23.104 5.03556C23.2568 5.61214 23.577 6.03589 23.759 6.30681H23.4533C22.6964 6.30681 22.1797 6.56384 22.1797 6.27902C22.1724 5.9039 21.3646 5.02167 21.7867 5.00778ZM22.0705 7.65447C22.0705 8.35609 21.7212 9.1758 21.2991 9.46756C20.2802 10.1831 20.2656 8.93266 21.2772 7.81424C22.0341 6.98759 22.0705 6.98064 22.0705 7.65447ZM22.9584 3.75042C22.8565 4.39647 22.7401 4.09081 21.9322 4.5493C21.4155 4.84106 21.3791 4.83411 20.8406 4.42425C20.3166 4.02135 19.8217 3.97272 19.4796 4.28532C18.9338 4.78548 19.6543 5.41069 20.7096 5.34122L21.2845 5.30649L21.6266 5.89001C22.0632 6.6472 22.0632 6.66109 21.4446 7.11263C19.8726 8.26578 19.778 10.447 21.3136 9.98162C21.7576 9.84963 22.2889 8.73121 22.3616 7.78646C22.4417 6.74445 22.6091 6.61941 23.839 6.62636C24.7851 6.63331 24.8142 6.59163 24.1956 6.09146C23.4824 5.52183 23.053 4.41731 23.5479 4.41731C26.4517 4.41731 26.5245 9.71069 23.6425 11.1973C22.7983 11.6349 21.219 11.6905 20.4549 11.3084C16.7723 9.4884 16.7796 3.39614 20.4549 1.50664C21.6921 0.87449 23.4679 0.464635 23.5552 0.798077C23.577 0.888384 23.6571 1.24267 23.7226 1.59695L23.8536 2.2291C23.2859 2.79178 23.0894 2.91682 22.9584 3.75042ZM20.7241 4.89663C20.7241 5.02167 19.9673 5.0564 19.8581 4.93136C19.698 4.75075 19.8071 4.54235 20.0546 4.54235C20.3602 4.54235 20.7241 4.73686 20.7241 4.89663ZM24.6032 2.43055C25.2218 2.43055 25.8113 2.88903 25.5857 3.20164C25.3673 3.50034 24.8943 3.27805 24.5231 2.71537C24.3412 2.43055 24.3412 2.43055 24.6032 2.43055ZM25.8477 14.754C26.0369 14.754 26.6628 15.6571 26.5827 15.8099C26.4881 15.9905 26.0587 15.8724 25.9568 16.0461C25.7603 16.4004 25.3018 16.1086 24.938 15.3861C24.8652 15.2403 25.5784 14.754 25.8477 14.754ZM24.4576 13.6495C25.0835 13.3647 25.2218 13.4063 25.4183 13.9134C25.6512 14.5039 25.6512 14.49 25.2218 14.6915C24.6614 14.9555 24.5158 14.9138 24.2684 14.4136C23.9773 13.8301 23.97 13.8718 24.4576 13.6495ZM23.4897 15.6918C23.6862 15.4903 24.494 15.3584 24.6468 15.4973C24.7924 15.6293 25.1199 16.4073 25.0544 16.442C25.0398 16.4559 24.7997 16.581 24.5304 16.7199C24.2611 16.8658 24.021 16.9839 23.9991 16.9839C23.9045 16.9839 23.4242 15.7613 23.4897 15.6918ZM21.0298 14.7818C21.1099 14.0246 21.7139 13.8787 22.0632 14.5387C22.3762 15.1361 22.8565 15.5737 22.0487 15.5737C21.8085 15.5737 21.5101 15.6084 21.3864 15.6432C21.0735 15.7404 20.957 15.4626 21.0298 14.7818Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M238.897 18.5816C238.336 18.6719 238.242 18.5261 238.424 17.9009C238.664 17.0672 238.147 16.3865 237.638 16.8658C237.441 17.0534 237.448 17.8453 237.645 18.0328C238.038 18.401 237.703 18.8525 237.034 18.8525C236.67 18.8525 236.662 18.8456 236.662 18.3524C236.655 16.6713 234.923 17.2687 236.051 18.7483C236.531 19.3736 235.498 19.5681 234.945 18.9567C234.53 18.5052 233.941 18.3871 233.468 18.665C232.827 19.0401 232.449 18.2204 232.107 18.5469C231.626 19.0054 160.719 18.1301 161.352 18.7831C161.367 18.797 229.632 19.0262 229.661 19.0262C232.601 19.1096 231.997 18.6511 232.732 19.0262C233.751 19.5472 233.562 18.2412 234.748 19.2693C235.92 20.2836 236.197 19.1999 236.823 19.1999C236.975 19.1999 237.325 19.0609 237.609 18.8873C238.227 18.5052 238.467 18.6303 238.133 19.1582C237.798 19.6931 237.776 19.9501 238.023 20.3044C238.489 20.9713 239.086 20.4433 238.991 19.4569C238.933 18.8942 238.948 18.8248 239.144 18.7692C239.537 18.658 239.355 18.5122 238.897 18.5816ZM236.044 17.7411C236.219 17.616 236.451 17.9286 236.451 18.2899C236.451 19.1304 235.665 18.0051 236.044 17.7411ZM237.798 17.748C237.66 17.4563 237.776 17.102 238.009 17.102C238.3 17.102 238.213 18.6233 237.798 17.748ZM238.671 20.0821C238.22 20.5962 237.892 19.9988 238.315 19.4291C238.518 19.1582 238.526 19.1582 238.678 19.3805C238.875 19.6723 238.875 19.8529 238.671 20.0821Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M240.585 16.7347C239.523 17.8253 239.341 19.0618 240.105 20.0066C240.338 20.2914 240.789 20.3539 240.985 20.1316C241.357 19.7148 240.913 18.6311 240.374 18.6311C239.799 18.6311 239.916 18.0059 240.643 17.2209C240.854 16.9917 241.16 16.5888 241.328 16.3109C241.575 15.9149 241.699 15.8107 241.946 15.8107C242.376 15.8107 243.009 15.4217 243.322 14.9702C243.62 14.5395 243.598 14.5951 244.377 14.8104V15.6162C244.377 16.4915 244.413 16.4429 243.62 16.8111C242.572 17.3043 242.077 18.777 242.718 19.5064C243.569 20.472 245.097 18.9993 244.85 17.4432C244.748 16.8111 244.886 16.7486 245.658 17.075C246.327 17.3529 246.509 17.2765 246.32 16.7972C245.971 15.9358 246.218 15.3106 246.837 15.4634C247.062 15.519 247.295 15.5329 247.353 15.4981C247.565 15.3453 247.943 15.5746 248.067 15.9288C249.093 18.7423 253.016 17.6377 253.285 14.4492C253.314 14.1296 253.336 13.8518 253.343 13.8448C253.379 13.7476 254.384 13.2405 254.384 12.8653C254.384 12.518 254.224 12.5736 253.758 13.1015C253.307 13.6156 253.19 13.6156 253.096 13.1224C252.863 11.9345 250.869 11.0036 250.141 11.74C249.217 12.6847 249.893 14.5395 250.978 14.0254C251.538 13.7615 251.924 12.8723 251.538 12.7056C251.342 12.6222 251.269 12.7264 251.269 13.0737C251.269 13.8865 250.41 14.0602 250.075 13.3169C249.34 11.7122 251.56 11.2815 252.564 12.8306C253.241 13.8726 252.222 14.5742 249.377 15.0327C247.943 15.262 247.79 15.1369 248.263 14.088C248.38 13.8379 248.467 13.5947 248.467 13.5531C248.467 12.9209 246.407 13.6364 246.233 14.3242C246.058 15.0188 246 15.0536 245.33 14.8382C244.886 14.6993 244.835 14.477 245.105 13.8865C245.316 13.4141 245.258 13.2752 244.741 13.0876C244.217 12.8931 244.151 12.8028 244.086 12.1776C244.013 11.5524 243.664 10.9897 243.205 10.7744C242.259 10.3298 242.397 11.6844 243.387 12.5527C243.831 12.9487 243.838 12.9626 243.686 13.5809C243.562 14.0949 243.489 14.1158 243.031 13.7545C242.383 13.2544 241 11.6497 241 11.3996C241 11.3579 240.884 11.1426 240.745 10.9064C238.919 7.85677 240.076 2.58423 242.907 1.06985C244.653 0.132041 244.886 0.173721 244.872 1.43802C244.857 2.59812 244.799 2.70232 244.231 2.50781C242.739 2.0007 240.993 3.45951 241.422 4.84885C241.844 6.21735 243.904 5.53657 244.624 3.7999C244.901 3.13302 244.966 3.11912 245.651 3.51508C246.509 4.0083 246.247 5.24481 245.192 5.63383C241.721 6.92591 243.831 11.7678 247.71 11.3926C254.107 10.7813 252.302 -0.0277333 245.811 5.34806e-05C241.08 0.0208936 237.499 6.82171 240.221 10.6146C240.432 10.9064 240.381 11.1634 240.665 11.5038C241.051 11.9762 241.437 12.9487 242.929 14.1088C243.438 14.5048 243.271 14.8313 242.303 15.2967C241.721 15.5746 241.67 15.5607 241.509 15.0188C241.306 14.3242 240.469 14.3311 240.469 15.0258C240.469 15.2828 240.825 15.776 241.007 15.776C241.269 15.8107 241.051 16.2553 240.585 16.7347ZM240.127 18.902C240.309 18.8256 240.804 19.2702 240.804 19.5133C240.804 19.812 240.549 19.9024 240.323 19.694C240.018 19.4161 239.916 18.9993 240.127 18.902ZM252.295 14.4561C252.95 14.0393 253.074 14.0741 253.008 14.6229C252.899 15.5676 252.346 16.4221 251.553 16.8875C250.578 17.4571 249.122 17.1376 248.482 16.2067C247.601 14.9424 249.893 15.9705 252.295 14.4561ZM246.677 14.0324C246.91 13.7406 248.03 13.7545 247.972 14.0532C247.783 14.9841 247.987 15.3801 246.677 15.1439C246.327 15.0813 246.327 14.4631 246.677 14.0324ZM243.824 19.2424C242.907 19.8607 242.368 18.6936 243.089 17.6516C243.343 17.2834 244.144 16.8319 244.37 16.9361C244.814 17.1306 244.406 18.8534 243.824 19.2424ZM245.92 16.4846C245.818 16.9153 245.439 16.686 245.025 16.5818C244.748 16.5124 244.741 16.4776 244.741 15.7899V15.0744C245.774 15.2689 246.189 15.3384 245.92 16.4846ZM244.217 13.2266C244.712 13.2266 244.937 13.6434 244.748 14.1991C244.602 14.6298 243.809 14.609 243.809 14.1713C243.809 13.9629 244.129 13.2266 244.217 13.2266ZM242.929 11.4621C242.819 11.0731 243.038 10.9064 243.3 11.1842C243.525 11.4135 243.911 12.1846 243.911 12.3999C243.911 12.8167 243.089 12.0317 242.929 11.4621ZM243.46 4.86969C242.317 5.73108 241.306 5.00168 241.888 3.73043C242.23 2.98019 244.501 2.38277 244.61 3.01492C244.668 3.36226 243.977 4.47373 243.46 4.86969ZM246.662 6.05758C247.434 6.52301 247.71 7.18989 247.506 8.07907C247.23 9.30169 245.883 8.218 245.883 6.76614C245.883 5.77971 246.007 5.66856 246.662 6.05758ZM245.257 1.12542C245.265 -0.791871 249.508 0.944805 250.701 3.35531C251.553 5.0642 251.596 7.42608 250.803 8.66259C250.476 9.17665 250.235 10.0311 248.882 10.7466C245.905 12.3304 242.281 8.92656 244.442 6.57858C245.258 5.6894 245.665 5.71024 245.6 6.6411C245.505 7.91235 246.16 8.89183 247.106 8.89183C247.71 8.89183 248.052 7.58585 247.674 6.69667C247.492 6.26598 246.713 5.60604 246.371 5.60604C246.058 5.60604 246.058 5.32123 246.371 4.70992L246.669 4.13334L247.31 4.1125C248.314 4.08471 249.078 3.34142 248.576 2.88293C247.914 2.27162 247.179 3.04271 246.502 3.62623L246.051 3.43172C244.624 2.81347 245.25 2.52865 245.257 1.12542ZM246.917 3.73738C246.917 3.54287 247.703 3.01492 247.987 3.01492C248.409 3.01492 248.532 3.31363 248.212 3.54982C247.885 3.7999 246.917 3.93189 246.917 3.73738ZM240.971 15.3939C240.876 15.2828 240.811 15.1369 240.833 15.0605C240.891 14.859 241.131 14.9007 241.255 15.13C241.429 15.4426 241.196 15.651 240.971 15.3939Z\"\n        fill=\"#C89D4F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 270 / 500,\n  svg: FloralFrame,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/floralSeparator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Floral Separator', 'sticker name', 'web-stories');\n\nfunction FloralSeparator({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 60 10\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M25.9499 4.99974C25.9499 5.52058 25.2079 5.62945 25.0518 5.13651H5.13657C6.3072 6.85991 5.30206 7.16193 6.05621 7.7922H5.30152C5.07644 8.46515 5.07533 9.19281 5.30152 9.86849C5.17189 10.0447 4.9104 10.043 4.78185 9.86849C4.98377 9.18898 4.98321 8.46898 4.78185 7.7922H4.02717C4.83978 7.11159 3.81533 6.61154 4.93411 5.13651C4.91095 5.13651 4.88943 5.13213 4.86571 5.11955C3.16107 6.24058 2.85709 5.26398 2.22599 6.00642V5.25742C1.54743 5.03419 0.814269 5.03309 0.132406 5.25742C-0.0452432 5.12885 -0.043024 4.87007 0.132406 4.74258C0.816465 4.94229 1.54246 4.94229 2.22599 4.74258V3.99358C2.9084 4.7951 3.41098 3.79608 4.87785 4.87388C4.90432 4.86294 4.92087 4.86294 4.9468 4.86294C3.77617 3.13954 4.78131 2.83807 4.02717 2.2078H4.78185C5.00693 1.5343 5.00804 0.807194 4.78185 0.131511C4.91148 -0.0451985 5.17297 -0.0424703 5.30152 0.131511C5.0996 0.811022 5.10016 1.53102 5.30152 2.2078H6.05621C5.2436 2.88787 6.26804 3.38847 5.14926 4.86294H25.0518C25.2079 4.37055 25.9499 4.47889 25.9499 4.99974Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M7.32322 3.23333C16.658 5.01604 21.4186 4.47562 24.2949 4.47562C24.6909 4.47562 25.012 4.15718 25.012 3.76438C25.012 3.37157 24.6909 3.05314 24.2949 3.05314C23.8096 3.05314 23.4627 3.52268 23.6125 3.98295C18.4776 4.44662 13.1367 4.10097 7.93729 2.83503C8.21357 2.36331 7.87071 1.76743 7.31728 1.76743C6.71489 1.76743 6.33241 2.49419 6.82573 2.98069C6.98223 3.13512 7.11185 3.19296 7.32322 3.23333Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M24.0078 5.51979C22.9953 5.53882 16.0447 5.00986 7.86057 6.6626C7.40872 6.75385 6.82159 6.7618 6.64033 7.27983C6.49322 7.70026 6.77669 8.23247 7.31725 8.23247C7.86961 8.23247 8.21416 7.63765 7.93725 7.16488C12.858 5.96677 18.1879 5.52713 23.6125 6.01695C23.4625 6.47766 23.81 6.94676 24.2948 6.94676C24.6909 6.94676 25.012 6.62833 25.012 6.23552C25.012 5.99552 24.8861 5.767 24.6826 5.63705C24.483 5.50952 24.2357 5.5155 24.0078 5.51979Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M33.228 4.99974C33.228 5.52058 33.97 5.62945 34.1261 5.13651H54.0413C52.8707 6.85991 53.8758 7.16193 53.1217 7.7922H53.8764C54.1015 8.46515 54.1026 9.19281 53.8764 9.86849C54.006 10.0447 54.2675 10.043 54.3961 9.86849C54.1941 9.18898 54.1947 8.46898 54.3961 7.7922H55.1507C54.3381 7.11159 55.3626 6.61154 54.2438 5.13651C54.2669 5.13651 54.2885 5.13213 54.3122 5.11955C56.0168 6.24058 56.3208 5.26398 56.9519 6.00642V5.25742C57.6305 5.03419 58.3636 5.03309 59.0455 5.25742C59.2231 5.12885 59.2209 4.87007 59.0455 4.74258C58.3614 4.94229 57.6354 4.94229 56.9519 4.74258V3.99358C56.2695 4.7951 55.7669 3.79608 54.3001 4.87388C54.2736 4.86294 54.257 4.86294 54.2311 4.86294C55.4017 3.13954 54.3966 2.83807 55.1507 2.2078H54.3961C54.171 1.5343 54.1699 0.807194 54.3961 0.131511C54.2664 -0.0451985 54.0049 -0.0424703 53.8764 0.131511C54.0783 0.811022 54.0777 1.53102 53.8764 2.2078H53.1217C53.9343 2.88787 52.9099 3.38847 54.0286 4.86294H34.1261C33.97 4.37055 33.228 4.47889 33.228 4.99974Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M51.8546 3.23333C42.5198 5.01604 37.7592 4.47562 34.883 4.47562C34.4869 4.47562 34.1658 4.15718 34.1658 3.76438C34.1658 3.37157 34.4869 3.05314 34.883 3.05314C35.3682 3.05314 35.7151 3.52268 35.5653 3.98295C40.7002 4.44662 46.0412 4.10097 51.2406 2.83503C50.9643 2.36331 51.3071 1.76743 51.8606 1.76743C52.4629 1.76743 52.8455 2.49412 52.3521 2.98069C52.1956 3.13507 52.0661 3.19294 51.8546 3.23333Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M35.17 5.51979C36.1825 5.53882 43.1331 5.00986 51.3172 6.6626C51.7691 6.75385 52.3562 6.7618 52.5375 7.27983C52.6846 7.70028 52.4011 8.23247 51.8606 8.23247C51.3082 8.23247 50.9636 7.63765 51.2406 7.16488C46.3198 5.96677 40.9899 5.52713 35.5653 6.01695C35.7153 6.47766 35.3678 6.94676 34.883 6.94676C34.4869 6.94676 34.1658 6.62833 34.1658 6.23552C34.1658 5.99552 34.2917 5.767 34.4952 5.63705C34.6948 5.50954 34.9421 5.5155 35.17 5.51979Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        d=\"M30.1368 5.15769L31.818 5.09109L30.1368 5.02449C30.9442 4.78561 31.6944 4.65943 32.3788 4.66307L32.8224 4.04915L32.0997 3.81107C31.5482 4.21295 30.8664 4.54821 30.0716 4.82564L31.3923 3.79167L29.9927 4.71789C30.5043 4.05396 31.0365 3.51453 31.5923 3.11851L31.5874 2.36323L30.8615 2.59196C30.6535 3.2386 30.3007 3.90724 29.8221 4.59498L30.2778 2.98859L29.6944 4.55383C29.7148 3.71845 29.8257 2.97181 30.0406 2.32742L29.589 1.71928L29.1373 2.32742C29.3523 2.97179 29.4631 3.71843 29.4836 4.55383L28.9001 2.98859L29.3558 4.59498C28.8773 3.90722 28.5244 3.23857 28.3164 2.59196L27.5906 2.36323L27.5856 3.11851C28.1414 3.5145 28.6736 4.05394 29.1853 4.71789L27.7856 3.79167L29.1063 4.82564C28.3115 4.54821 27.6298 4.21295 27.0783 3.81107L26.3555 4.04915L26.7992 4.66307C27.4835 4.65943 28.2338 4.78561 29.0412 5.02449L27.3599 5.09109L29.0412 5.15769C28.2337 5.39657 27.4835 5.52275 26.7992 5.51911L26.3555 6.13303L27.0783 6.37111C27.6298 5.96923 28.3115 5.63397 29.1063 5.35654L27.7856 6.39051L29.1853 5.46429C28.6736 6.12822 28.1414 6.66765 27.5856 7.06367L27.5906 7.81895L28.3164 7.59022C28.5244 6.94361 28.8773 6.27496 29.3558 5.5872L28.9001 7.19359L29.4835 5.62837C29.4631 6.46375 29.3523 7.21039 29.1373 7.85478L29.5889 8.46292L30.0406 7.85478C29.8256 7.21039 29.7148 6.46375 29.6943 5.62837L30.2777 7.19361L29.822 5.58722C30.3006 6.27496 30.6535 6.94363 30.8615 7.59024L31.5873 7.81897L31.5923 7.06369C31.0365 6.6677 30.5043 6.12826 29.9926 5.46432L31.3923 6.39053L30.0716 5.35657C30.8664 5.63399 31.5481 5.96925 32.0996 6.37113L32.8224 6.13305L32.3788 5.51913C31.6944 5.52273 30.9442 5.39655 30.1368 5.15769ZM29.5889 5.43321C29.3984 5.43321 29.2439 5.28002 29.2439 5.09107C29.2439 4.90211 29.3984 4.74893 29.5889 4.74893C29.7794 4.74893 29.9339 4.90211 29.9339 5.09107C29.9339 5.28002 29.7794 5.43321 29.5889 5.43321Z\"\n        fill=\"#C89D4F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 60 / 10,\n  svg: FloralSeparator,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as elegantTravelBridge } from './yellowBridge';\nimport { default as elegantTravelFloralSeparator } from './floralSeparator';\nimport { default as elegantTravelFloralFrame } from './floralFrame';\nimport { default as elegantTravelStationClock } from './stationClock';\nimport { default as elegantTravelTrainTracks } from './trainTracks';\n\nexport {\n  elegantTravelBridge,\n  elegantTravelFloralSeparator,\n  elegantTravelFloralFrame,\n  elegantTravelStationClock,\n  elegantTravelTrainTracks,\n};\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/stationClock.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Station Clock', 'sticker name', 'web-stories');\n\nfunction StationClock({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 24 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 30L1.31134e-06 0L1.5 6.55673e-08L1.5 30H0Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M9 8V3H10.5V8H9Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18 8V3H19.5V8H18Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M1 2H24V3.5H1V2Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14 24.5C18.6944 24.5 22.5 20.6944 22.5 16C22.5 11.3056 18.6944 7.5 14 7.5C9.30558 7.5 5.5 11.3056 5.5 16C5.5 20.6944 9.30558 24.5 14 24.5ZM14 26C19.5229 26 24 21.5228 24 16C24 10.4772 19.5229 6 14 6C8.47715 6 4 10.4772 4 16C4 21.5228 8.47715 26 14 26Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13.4822 15.7904V11.5757C13.4822 11.2577 13.7352 11 14.0473 11C14.3594 11 14.6124 11.2577 14.6124 11.5757V15.7908C14.7392 15.8737 14.8471 15.9837 14.9286 16.1128H18.6884C19.0005 16.1128 19.2535 16.3705 19.2535 16.6885C19.2535 17.0064 19.0005 17.2642 18.6884 17.2642H14.9289C14.7428 17.5597 14.4174 17.7554 14.0471 17.7554C13.4687 17.7554 13 17.278 13 16.6888C13 16.3115 13.1921 15.9801 13.4822 15.7904ZM14.0471 16.7735C14.0012 16.7735 13.9639 16.7354 13.9639 16.6888C13.9639 16.6769 13.9663 16.6656 13.9706 16.6553C13.9957 16.6588 14.0213 16.6606 14.0473 16.6606C14.0566 16.6606 14.0658 16.6604 14.075 16.6599C14.0745 16.6694 14.0743 16.6789 14.0743 16.6885C14.0743 16.715 14.076 16.7412 14.0795 16.7668C14.0695 16.7711 14.0585 16.7735 14.0471 16.7735Z\"\n        fill=\"#C89D4F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 24 / 30,\n  svg: StationClock,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/trainTracks.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Train Tracks', 'sticker name', 'web-stories');\n\nfunction TrainTracks({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 30 35\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M28.5 26.5V14.5C28.5 7.3203 22.6797 1.5 15.5 1.5C8.3203 1.5 2.5 7.3203 2.5 14.5V26.5H28.5ZM15.5 0C7.49187 0 1 6.49187 1 14.5V28H30V14.5C30 6.49187 23.5081 0 15.5 0Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.9377 17.391C13.2741 17.6327 13.3508 18.1014 13.109 18.4377L1.60901 34.4377C1.36726 34.7741 0.898621 34.8508 0.562273 34.609C0.225925 34.3673 0.149238 33.8986 0.390988 33.5623L11.891 17.5623C12.1327 17.2259 12.6014 17.1492 12.9377 17.391Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.5623 17.391C16.2259 17.6327 16.1492 18.1014 16.391 18.4377L27.891 34.4377C28.1327 34.7741 28.6014 34.8508 28.9377 34.609C29.2741 34.3673 29.3508 33.8986 29.109 33.5623L17.609 17.5623C17.3673 17.2259 16.8986 17.1492 16.5623 17.391Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7 20.25C7 19.8358 7.33579 19.5 7.75 19.5H21.25C21.6642 19.5 22 19.8358 22 20.25C22 20.6642 21.6642 21 21.25 21H7.75C7.33579 21 7 20.6642 7 20.25Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5 23.25C5 22.8358 5.33579 22.5 5.75 22.5H24.25C24.6642 22.5 25 22.8358 25 23.25C25 23.6642 24.6642 24 24.25 24H5.75C5.33579 24 5 23.6642 5 23.25Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M3 27.25C3 26.8358 3.33579 26.5 3.75 26.5H27.25C27.6642 26.5 28 26.8358 28 27.25C28 27.6642 27.6642 28 27.25 28H3.75C3.33579 28 3 27.6642 3 27.25Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 31.25C3.62117e-08 30.8358 0.335786 30.5 0.75 30.5L29.25 30.5C29.6642 30.5 30 30.8358 30 31.25C30 31.6642 29.6642 32 29.25 32H0.75C0.335786 32 -3.62117e-08 31.6642 0 31.25Z\"\n        fill=\"#C89D4F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 30 / 35,\n  svg: TrainTracks,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/elegant-travel-itinerary/yellowBridge.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Bridge', 'sticker name', 'web-stories');\n\nfunction YellowBridge({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 37 25\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7 0.75C7 0.335786 7.33579 -3.62108e-08 7.75 0L29.25 1.87959e-06C29.6642 1.9158e-06 30 0.335788 30 0.750002C30 1.16422 29.6642 1.5 29.25 1.5L7.75 1.5C7.33579 1.5 7 1.16421 7 0.75Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 10.75C-3.62108e-08 10.3358 0.335786 10 0.75 10L36.25 10C36.6642 10 37 10.3358 37 10.75C37 11.1642 36.6642 11.5 36.25 11.5L0.75 11.5C0.335786 11.5 3.62126e-08 11.1642 0 10.75Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7.75 10.5C8.16421 10.5 8.5 10.8358 8.5 11.25L8.5 23.75C8.5 24.1642 8.16421 24.5 7.75 24.5C7.33579 24.5 7 24.1642 7 23.75L7 11.25C7 10.8358 7.33579 10.5 7.75 10.5Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M29.75 10.5C30.1642 10.5 30.5 10.8358 30.5 11.25V23.75C30.5 24.1642 30.1642 24.5 29.75 24.5C29.3358 24.5 29 24.1642 29 23.75V11.25C29 10.8358 29.3358 10.5 29.75 10.5Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5 11.75C5 11.3358 5.33579 11 5.75 11H9.25C9.66421 11 10 11.3358 10 11.75C10 12.1642 9.66421 12.5 9.25 12.5H5.75C5.33579 12.5 5 12.1642 5 11.75Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27 11.75C27 11.3358 27.3358 11 27.75 11H31.25C31.6642 11 32 11.3358 32 11.75C32 12.1642 31.6642 12.5 31.25 12.5H27.75C27.3358 12.5 27 12.1642 27 11.75Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7.5 0.5L1.87083 11H13.1292L7.5 0.5ZM7.5 3.67465L4.37697 9.5H10.623L7.5 3.67465Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.5 0.5L12.8708 11H24.1292L18.5 0.5ZM18.5 3.67465L15.377 9.5H21.623L18.5 3.67465Z\"\n        fill=\"#C89D4F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M29.5 0.5L23.8708 11H35.1292L29.5 0.5ZM29.5 3.67465L26.377 9.5H32.623L29.5 3.67465Z\"\n        fill=\"#C89D4F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 37 / 25,\n  svg: YellowBridge,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/facebookIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Facebook', 'sticker name', 'web-stories');\n\nconst FacebookIcon = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 14 26\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M8.68442 25.349V13.7867h3.74108l.5612-4.506H8.68442V6.40194c0-1.30378.35013-2.19452 2.15348-2.19452h2.2999V.176657C12.7397.121918 11.3751 0 9.78517 0 6.46854 0 4.19991 2.09998 4.19991 5.95657V9.2807H.449219v4.506H4.19991V25.349h4.48451z\"\n      fill=\"#094228\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 14 / 26,\n  svg: FacebookIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as travelFacebookIcon } from './facebookIcon';\nimport { default as travelInstagramIcon } from './instagramIcon';\nimport { default as travelMap } from './mapFill';\nimport { default as travelTwitterIcon } from './twitterIcon';\nimport { default as travelYouTubeIcon } from './youTubeIcon';\n\nexport {\n  travelFacebookIcon,\n  travelInstagramIcon,\n  travelMap,\n  travelTwitterIcon,\n  travelYouTubeIcon,\n};\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/instagramIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Instagram', 'sticker name', 'web-stories');\n\nconst InstagramIcon = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 27 27\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M18.6524 26.4359H8.03621c-4.06197 0-7.385819-3.3202-7.385819-7.3776V7.7585c0-4.05747 3.323849-7.377641 7.385819-7.377641H18.6524c4.062 0 7.3859 3.320171 7.3859 7.377641v11.2998c0 4.0574-3.3239 7.3776-7.3859 7.3776zm0-1.9482c1.4436 0 2.8054-.567 3.8354-1.5959 1.0301-1.029 1.5977-2.3893 1.5977-3.8312V7.7585c0-1.44193-.5676-2.8022-1.5977-3.83115-1.03-1.02895-2.3918-1.59592-3.8354-1.59592H8.03621c-1.44353 0-2.8053.56697-3.83539 1.59592s-1.5977 2.38922-1.5977 3.83115v11.2998c0 1.4419.56761 2.8022 1.5977 3.8311 1.03009 1.029 2.39186 1.5959 3.83539 1.5959H18.6524v.0024z\"\n      fill=\"#094228\"\n    />\n    <path\n      d=\"M20.3738 13.3076c0 3.8568-3.13 6.9834-6.9911 6.9834-3.86107 0-6.99105-3.1266-6.99105-6.9834s3.12998-6.98332 6.99105-6.98332c3.8611 0 6.9911 3.12652 6.9911 6.98332zM13.35 8.7415c-2.5273 0-4.57816 2.0462-4.57816 4.5731 0 2.5269 2.04846 4.5731 4.57816 4.5731 2.5297 0 4.5782-2.0462 4.5782-4.5731 0-2.5269-2.0508-4.5731-4.5782-4.5731zM20.4862 7.87085c.9146 0 1.6561-.74063 1.6561-1.65424 0-.91361-.7415-1.65423-1.6561-1.65423-.9146 0-1.6561.74062-1.6561 1.65423 0 .91361.7415 1.65424 1.6561 1.65424z\"\n      fill=\"#094228\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 27 / 27,\n  svg: InstagramIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/mapFill.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Map', 'sticker name', 'web-stories');\n\nconst MapFill = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 256 430\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M.791885 18.644c3.924175 4.9232 7.913745.9847 11.837915 0 .4578-.1313 1.0464-1.0502.981-1.5097-.5886-3.2821 1.0465-7.15501-2.8777-9.71504 1.7005-2.0349 3.401-3.87288 4.8398-5.84214.5233-.722059.8503-1.903612.7195-2.75696-.2616-1.70669-.9811-3.41338-1.3735-5.12008-.1308-.72206.0654-1.5754.2616-2.29746.5232-1.44412 1.1773-2.88822 2.0275-4.98882 2.6815-1.0502 6.3441-2.4944 3.9242-7.9426.327 0 .654 0 1.0464-.0657 1.8313 1.1816 3.6626 2.4288 5.5593 3.5447.7194.3938 1.635.6564 2.4853.6564 2.6161.0656 5.2976 0 8.1753 0 .9157-2.1662 3.3356-1.9693 5.6247-2.6913 2.4853-.7877 4.382-.5908 7.2597 1.1815.5886-3.1508 1.2426-5.7765 1.4389-8.4021.327-3.8073 1.962-5.1201 5.8208-4.3981 2.0275.3939 4.055.919 6.0825.7878 2.6161-.1313 3.6625-3.0852 2.4199-6.433-.1962-.8533-.8503-1.7067-1.2427-2.3631 2.8778.3282 5.8863.8534 8.9602 1.0503.8503.0656 2.1583-.7221 2.6161-1.5098 1.8313-3.3477 3.9242-3.5446 6.0825-.3282.3924.5252.7848 1.0503 1.1118 1.6411 1.9621 3.8728 1.8313 3.8072 4.5782.3938.7195-.8533 1.9621-1.7067 3.0086-1.7067.5886 0 1.2426 1.5754 1.8967 2.4288 1.5042 2.0349 1.8966 5.317 6.0826 4.9231-2.2239 3.5447-.5234 8.074-4.3168 11.0279-.7848.5908-.654 2.9539-.3924 4.398.327 1.7723 1.1119 3.479 2.0275 4.9888.3924.5908 2.1583 1.1815 2.4853.8533 2.2894-2.0349 3.7284 0 6.2784 1.3785.589-.8533 1.308-1.9692 2.028-3.0195 1.766-2.5601 4.055-2.2975 6.605-1.3785 1.243.4595 2.617.3282 3.99.5251.85.1313 2.355.3282 2.355.5252 0 1.0502.065 2.6913-.589 3.1508-1.766 1.24718-2.289 2.23181-.981 4.13543.588.85335.458 2.10054.785 3.15081.719 2.428755 1.504 4.79187 2.485 7.74576-1.831 2.69132-4.317 6.1047-2.224 10.5684.197.4594-.327 1.3784-.785 1.9036-1.046 1.1815-2.289 2.2318-3.27 3.4133-2.616 3.2165-2.42 4.1355 1.178 6.1704 0 2.2975-.262 4.5949.065 6.8268.458 3.2164-1.504 4.9887-3.205 7.0893-.981 1.1815-1.504 2.8226-1.831 4.3324-.458 2.1661-.458 4.4636-.719 6.8267 1.831 1.1159 3.858 2.3631 5.82 3.5447 2.944-3.676 4.775-8.3365 10.138-9.2555.915-.197 1.635-1.838 2.42-2.8883.327-.4595.523-1.1815.915-1.3128 2.747-.919 4.513-2.6257 5.363-5.3827.131-.3282 2.224-.0656 4.186-.0656.785-.8533 2.486-2.1005 3.467-3.8072 1.504-2.6914 3.335-1.9036 4.578-.3939 3.008 3.7416 6.867 5.7109 11.38 6.5642 2.551.5252 2.485 1.9693 1.373 3.7416.981.7221 1.766 1.2472 2.093 1.4441 1.504-1.3128 2.878-2.3631 4.186-3.5446 1.831-1.6411 3.663-2.9539 6.409-1.9693.524.1969 2.224-1.3128 2.42-2.2318.654-3.8073 2.551-6.4329 6.017-8.0083-.981-3.5447.524-5.6452 4.055-4.7919 4.382 1.0503 8.568 2.9539 12.819 4.4637.589.1969 1.374.8533 1.701.6564 3.532-2.1662 4.186.5907 5.755 2.8226 2.878 4.0698 5.167 8.4678 8.437 12.4063 3.205 3.8072 6.671 6.4986 10.661 9.1242 3.074 1.9693 4.186 9.8463 2.878 13.6536-.851 2.3631-1.112 4.9231-1.308 7.4832-.197 2.7569-.72 5.8421.13 8.3365 1.178 3.3477 3.467 6.3016 5.363 9.4524 1.112 1.838 2.028 3.8073 3.532 5.2514 1.504 1.5097 3.336 2.8226 5.298 3.6098 1.831.788 3.989.788 6.409 1.248-2.616 2.757-1.766 5.054.131 7.089.523.591 1.439.985 2.224.985 3.205.131 5.232 2.954 4.186 5.973-.981 2.757-.72 6.236-5.625 6.499.327.393.719.722 1.046 1.116 1.047.393 2.028.787 3.336 1.247-1.374 1.838-2.747 3.676-3.99 5.382.393.526.458.788.654.919 2.878 1.444 4.709 3.479 2.486 6.565-1.832 2.56-1.178 5.382-.851 7.877.589 4.004-1.831 5.907-4.251 7.745-1.308 1.051-3.27 1.248-4.84 1.97-.85.393-1.504 1.181-2.158 1.903-.719.722-1.373 1.51-2.093 2.232-.785-.919-2.289-1.838-2.289-2.757 0-2.56-1.439-2.954-3.401-3.413-3.532-.788-6.932-1.051-10.268.919-.981.59-2.485.394-3.728.262-4.12-.394-8.175-.722-12.296.788-3.597 1.313-9.352-.656-10.857-3.02-5.101 1.116-10.268 2.101-15.238 3.414-4.579 1.247-8.634 3.348-9.484 8.861-.131.854-.915 1.642-1.439 2.429-.915 1.379-1.7 2.954-2.812 4.136-1.374 1.509-3.009 2.954-4.644 4.201-1.308.984-2.877 1.706.131 4.004-3.401.328-5.755.525-8.502.853.719 4.201 1.439 8.337 2.158 12.407.131.722.392 1.509.85 2.1 2.682 3.545 2.878 7.549 2.355 11.75-.066.788.654 1.904 1.308 2.56 2.42 2.363 4.905 4.529 7.587 6.958-4.317 3.939-2.813 8.008-1.505 12.406-1.831-1.969-3.662-3.938-5.494-5.907-.261.131-.523.262-.784.394.196 1.641.457 3.216.523 4.135-2.028-.985-4.317-2.101-6.606-3.216-.719-.329-1.831-.723-1.896-1.248-.066-.59.654-1.378 1.111-2.035.458-.656.981-1.312 1.112-2.363-.458.263-.915.525-1.439.788-.457-.788-.915-1.575-1.373-2.363-.196.066-.393.131-.589.197v2.035c-2.877-1.773-6.148-3.676-9.287-5.777-.85-.591-1.57-1.444-2.158-2.363-2.355-3.545-2.878-3.151-6.737-2.1-3.074.853-6.082 2.166-10.006.919-3.532-1.182-8.437-3.086-11.969 1.247-.654-.591-1.243-1.379-1.962-1.641-2.485-.854-1.439-1.97-.523-3.414.588-.919.981-2.035 1.177-3.15 1.046-5.186-1.243-10.831 2.224-15.755.523-.722.261-2.1.327-3.15-6.214-1.576-12.165-2.363-18.3132-1.182-1.1119.197-2.4853-1.05-3.5972-1.575-.2616.59-.5232 1.706-1.1772 2.166-3.1394 1.903-6.4749 3.61-10.0067 5.514 1.5043 1.575 2.5507 2.625 3.4664 3.676 1.635 1.903 2.7469 3.938 1.1772 6.564-3.0739 5.317-3.5317 10.962-2.6161 17.067.7848 5.186 1.7659 10.896-3.728 14.769-.3924.263-.9156.919-.9156 1.313.2616 6.958-5.5592 11.159-7.4559 17.133-.5886 1.706-.7195 3.61-1.1119 5.842-1.8312.656-2.6161 4.857-1.1772 9.19-2.8123 4.266-5.5593 8.336-8.1754 12.472-.2616.394.2616 1.378.5232 2.1.2617.854.5887 1.707.7195 2.166-1.5697.263-2.6815.394-3.8588.591.4578 1.379.9156 2.823 1.1119 3.414-1.1773 9.583-3.0086 18.511 2.9431 26.125-.654 1.904-1.4389 3.282-1.4389 4.595 0 .459 2.0275.919 3.401 1.444-.0654.263-.1962.853-.4579 1.904 1.9621-.985 3.4664-1.707 5.0361-2.495 2.9431-1.509 5.9516-3.282 9.2872-1.706 1.0464.459 1.8967 2.1 2.0929 3.282.7848 4.463 1.4388 8.993 1.7658 13.522.3271 4.135 2.4199 7.286 4.8398 10.371.9811 1.248 1.9621 2.429 3.401 3.545-.5886-1.838-1.1773-3.61-1.7659-5.711 2.8777 2.56 3.5972 4.661 3.4664 8.14-.0654.788 1.1772 1.641 1.4388 2.56 2.0275 8.139 3.9242 16.345 5.8863 24.484 0 .132 0 .263.0654.329 3.6629 4.332 5.6249 9.977 10.9219 12.997 2.813 1.641 5.363 3.216 8.699 2.625 2.027-.328 4.12-.59 6.148-.984 3.335-.657 6.082.065 7.979 3.15 2.158 3.414 4.447 6.762 6.606 10.109l6.082 5.12c2.551 1.313 2.878 4.727.654 7.221-1.373 1.575-3.139 2.691-2.747 5.514.131.919-2.812 2.297-4.316 3.479.196.197.457.328.654.525-1.243-.328-2.486-.591-4.317-1.05-.131-.328-.327-1.641-1.046-2.232-.916-.722-2.224-1.116-3.401-1.182-.981-.065-2.224.329-3.009.985-1.962 1.51-5.821.919-5.755 5.12 0 .854-1.962 1.707-3.009 2.56h-.654c-.588-1.181-.915-2.822-1.897-3.544-2.55-1.97-2.55-4.005.131-5.646.72-.459 1.308-1.706 1.308-2.625.131-1.773-.85-3.808-.196-5.252.916-2.231.066-2.494-1.635-2.56-2.027-.065-4.12 0-6.148 0-.261-1.116-.523-2.363-.785-3.61-.457-2.494-1.766-2.626-4.251-2.823-3.6624-.328-7.1288-2.297-10.6605-3.544-.2616-.066-.5232-.525-.5232-.788.2616-3.545-2.3545-3.085-4.382-3.479-.4578 2.888-.8503 5.58-1.3081 8.205-.3924-.065-.7194-.131-1.1118-.197v-3.282c-.8503.46-1.4389.788-1.8313 1.05-1.5697-1.903-2.8123-3.872-4.5128-5.448-1.8967-1.772-4.2512-3.151-6.2787-4.857-.327-.263.0654-1.379-.0654-2.035-.5886-2.363-.654-5.974-2.1583-6.827-2.5507-1.378-3.0085-2.626-2.0275-5.186l-.7848-.591c-1.4389.919-2.8123 1.904-3.9896 2.692-1.7004-5.711-2.7469-12.21-9.2872-16.87.1962 2.035.5232 3.479.5232 4.923-.0654 1.51-.4578 2.954-.7194 4.464-.3924 0-.7194.065-1.1118.065-.1962-2.035-.7195-4.135-.4578-6.104.2616-2.56-.7849-4.924-2.5508-4.595 1.4389-4.924 1.1119-5.58-3.7933-6.302-.7849-.131-1.5697-.394-1.8313-.459-.7848-3.02-1.5043-5.777-2.2237-8.665-.8502.591-1.5043 1.05-2.7469 1.903.7848-2.166 1.3734-3.676 1.9621-5.382-2.2891 1.181-4.6436 1.772-5.8863 3.216-1.3081 1.51-1.5043 3.939-2.2237 6.236-1.0464-.919-1.7005-1.444-2.3545-1.969-.1962.263-.3924.459-.654.722 1.1772 1.116 2.4199 2.232 3.6625 3.413-.3924.854-.9156 1.773-1.3734 2.823.654.788 1.2426 1.51 1.7004 1.969-1.308 1.576-2.4853 2.954-3.7279 4.398-.2616-.131-.5886-.197-.8502-.328-.1309-2.954-.1963-5.842-.3925-8.796-.1962-2.888.1308-5.908-.7848-8.533-2.2891-6.433-.3924-12.407 1.1118-18.446.2617-1.116-.4578-2.429-.4578-3.676.0654-2.232.327-4.398.4578-6.63 3.1394.394 2.8778-2.363 3.5318-4.069.5886-1.51.8502-3.151 1.3735-4.989.654.788 1.0464 1.313 1.4388 1.838.2616-.132.4578-.197.7195-.328-.4579-1.379-.8503-2.823-1.3081-4.201.7848-1.707 1.1118-3.676 1.3735-5.58.0654-.591.0654-1.247.2616-1.838 1.7658-3.807 3.7279-7.549 5.4284-11.356.981-2.166 1.6351-4.464 2.2237-6.696.3924-1.509.9156-3.347.327-4.595-1.1118-2.494-.1308-3.872 1.5043-5.316 1.8967-1.707 5.5592-1.838 5.2322-5.711 0-.132.2616-.329.4578-.394 3.728-1.904 6.3441-4.595 7.6522-8.665.5232-1.575 1.8312-2.888 2.6815-4.398 1.308-2.494 2.4853-5.054 3.8588-7.746 2.3545-.197 5.7554-4.463 4.7744-6.564-1.0465-2.232-2.2891-4.464-3.2702-6.761-.2616-.656.327-1.641.4578-2.494.0654-.263-.0654-.591-.1308-.985-.654.066-1.308.066-1.5042.066-.5233-1.838-1.1773-3.479-1.5043-5.186-.3924-2.298-.7194-4.661-.5886-6.958.1308-1.576.1962-2.495-1.5697-3.217-3.9242-1.641-5.4938-5.054-6.2133-9.124-.1962-1.181-.9156-2.297-1.1772-3.545-.3924-1.641-.5886-3.347-.8503-4.988 1.2427-.263 2.1583-.46 3.2048-.722-.1962-1.313-.654-2.364-.5232-3.414.9156-9.19-2.4199-17.067-7.2598-24.484-.1308-.263-.327-.525-.5886-.657-5.7554-3.085-11.1185-6.564-13.6692-13.062-.1308-.263-.4578-.394-.654-.657-2.6815-4.332-7.5213-7.417-7.7175-13.259-.0654-1.051-.1308-2.167-.4579-3.151-1.3734-5.186.6541-7.68 5.5593-7.352.327-.919.5232-2.232.981-2.298 1.3735-.262 2.8777-.131 4.7744-.131V101.55c1.2427-.985 2.4199-1.9694 3.2702-2.6915 1.635-.1313 3.9241.3282 4.3166-.3938 1.308-2.2319 2.0275-4.8575 2.6815-7.3519.1308-.5252-.654-1.7067-1.2427-1.9693-.5232-.1969-1.5696.2626-2.1583.7221-1.1772.919-2.2891 2.1005-2.9431 2.7569-2.4199-4.5293-4.8398-8.8616-7.0635-13.3253-.2616-.4595.0654-1.5098.4578-1.9693 1.7005-1.7723 1.3735-3.7415.1308-5.2513-2.8123-3.479-6.8019-5.8421-9.091-9.7807-.981-1.641-1.9621-3.2821-3.2047-4.6605-3.0085-3.2821-6.4749-6.1704-9.2872-9.5838-1.5697-1.9692-3.4664-5.0544-2.9432-6.958.6541-2.2975.9811-3.7416-.327-5.7765-.9156-1.4441-1.50423-3.0852-1.96205-4.7262-1.11185-3.8073-1.04645-3.8073-4.12038-1.9693C3.4734 25.799 1.96914 23.042.530273 20.2194c.261612-.6564.261612-1.1159.261612-1.5754z\"\n      fill=\"#fff\"\n      fillOpacity=\".5\"\n    />\n    <circle\n      cx=\"49.97\"\n      cy=\"30.762\"\n      r=\"6.592\"\n      fill=\"#FEC85A\"\n      stroke=\"#fff\"\n      strokeWidth=\"2.19733\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 256 / 430,\n  svg: MapFill,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/twitterIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Twitter', 'sticker name', 'web-stories');\n\nconst TwitterIcon = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 28 23\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M27.7837 3.04797c-1.0187.43934-2.1139.73673-3.2623.86966 1.1716-.68491 2.0722-1.76635 2.4982-3.057313-1.0974.633093-2.3129 1.092703-3.6072 1.340533C22.3751 1.12842 20.9003.457031 19.2657.457031c-3.1349 0-5.6794 2.473789-5.6794 5.526589 0 .43258.0509.85389.1481 1.25943-4.72087-.22981-8.90694-2.43098-11.70846-5.77442-.48853.81558-.76868 1.76634-.76868 2.77794 0 1.91729 1.00253 3.60929 2.526 4.60061-.93076-.02929-1.80594-.27712-2.5723-.69167v.06984c0 2.67885 1.95874 4.91155 4.55651 5.41845-.47695.1262-.97937.1938-1.49568.1938-.36582 0-.72238-.0338-1.06967-.0992.72237 2.1967 2.82004 3.7941 5.30667 3.8391-1.94485 1.4825-4.39213 2.3657-7.05473 2.3657-.458428 0-.909912-.0271-1.3544506-.0766C2.61403 21.4347 5.59845 22.3494 8.80515 22.3494c10.44665 0 16.16085-8.4217 16.16085-15.72593 0-.23881-.0047-.47763-.0162-.7142 1.109-.77953 2.0722-1.75282 2.8339-2.8613z\"\n      fill=\"#094228\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 28 / 23,\n  svg: TwitterIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/experience-thailand/youTubeIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('YouTube', 'sticker name', 'web-stories');\n\nconst YouTubeIcon = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 30 20\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M21.9665.0332031H8.20109C.666016.0332031.666016 2.13357.666016 7.30199v5.05021c0 4.9158 1.067524 7.2688 7.535074 7.2688H21.9686c5.8411 0 7.535-1.3771 7.535-7.2688V7.30199c-.002-5.43937-.2871-7.2687869-7.5371-7.2687869zM12.1382 13.6663V5.73741l7.7723 3.9522-7.7723 3.97669z\"\n      fill=\"#094228\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 30 / 20,\n  svg: YouTubeIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-inspiration/curvedArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Curved Arrow', 'sticker name', 'web-stories');\n\nfunction CurvedArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 21 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M20.1679 49.1312L19.0613 45.477L18.8983 45.5263L19.9523 49.0068L16.4112 49.8342L16.4499 50L20.1679 49.1312Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.7609 47.0622C16.2977 46.786 15.8274 46.4905 15.3528 46.1758L15.2587 46.3176C15.7356 46.6339 16.2082 46.9309 16.6738 47.2084L16.7609 47.0622ZM18.9535 48.255C18.7113 48.1361 18.4655 48.0111 18.2166 47.8798L18.1372 48.0305C18.3875 48.1624 18.6348 48.2882 18.8785 48.4078L18.9535 48.255ZM13.9837 45.222C13.5426 44.8995 13.0999 44.5609 12.6578 44.2065L12.5513 44.3393C12.9954 44.6954 13.4401 45.0354 13.8833 45.3594L13.9837 45.222ZM11.3797 43.1345C10.9676 42.773 10.5578 42.3976 10.152 42.0084L10.0342 42.1313C10.4418 42.5222 10.8535 42.8993 11.2674 43.2625L11.3797 43.1345ZM8.97551 40.8279C8.59589 40.4293 8.22154 40.0182 7.85397 39.5946L7.72538 39.7062C8.09471 40.1318 8.47084 40.5449 8.85223 40.9453L8.97551 40.8279ZM6.79152 38.3099C6.45029 37.8766 6.11682 37.4318 5.79247 36.9755L5.6537 37.0741C5.97971 37.5327 6.31486 37.9798 6.65776 38.4153L6.79152 38.3099ZM4.86133 35.593C4.56481 35.1276 4.2782 34.6514 4.00274 34.1646L3.85457 34.2484C4.13152 34.7379 4.41967 35.2166 4.71774 35.6845L4.86133 35.593ZM3.22132 32.6928C2.97594 32.1987 2.74229 31.6947 2.52155 31.1807L2.36511 31.2479C2.58712 31.7648 2.82209 32.2717 3.06885 32.7685L3.22132 32.6928ZM1.90755 29.6321C1.71911 29.1143 1.54388 28.5873 1.38295 28.051L1.21988 28.1C1.38177 28.6394 1.55802 29.1695 1.74757 29.6903L1.90755 29.6321ZM0.950637 26.4424C0.823369 25.9072 0.71039 25.3634 0.612656 24.8112L0.445011 24.8408C0.543327 25.3964 0.656979 25.9434 0.785005 26.4818L0.950637 26.4424ZM0.37007 23.1625C0.305847 22.6167 0.256525 22.063 0.222951 21.5017L0.0530041 21.5118C0.0867734 22.0764 0.136383 22.6333 0.200986 23.1824L0.37007 23.1625ZM0.170427 19.8333C0.168551 19.286 0.181619 18.7317 0.210358 18.1706L0.0403309 18.1619C0.0114338 18.7261 -0.00170908 19.2835 0.000177417 19.8339L0.170427 19.8333ZM0.339473 16.5128C0.39624 15.9687 0.467703 15.4184 0.554478 14.8621L0.386261 14.8358C0.299045 15.395 0.22721 15.9481 0.170142 16.4952L0.339473 16.5128ZM0.851924 13.2204C0.962969 12.6819 1.08831 12.1379 1.22847 11.5886L1.06351 11.5465C0.922698 12.0984 0.796764 12.6449 0.685183 13.186L0.851924 13.2204ZM1.67396 9.99027C1.8319 9.4676 2.0032 8.94022 2.1883 8.40818L2.0275 8.35223C1.84164 8.88647 1.66961 9.41607 1.51099 9.94103L1.67396 9.99027ZM2.76951 6.83856C2.96937 6.32942 3.18181 5.81616 3.4072 5.29882L3.25112 5.23082C3.02491 5.75005 2.81166 6.26523 2.61103 6.77635L2.76951 6.83856ZM4.09722 3.78754C4.33459 3.29033 4.58387 2.78947 4.84536 2.28499L4.69421 2.20664C4.43187 2.71275 4.18176 3.21528 3.94358 3.7142L4.09722 3.78754ZM5.63175 0.823394C5.76853 0.578134 5.90818 0.332043 6.05073 0.0851252L5.90329 0C5.76031 0.247644 5.62025 0.49447 5.48306 0.740474L5.63175 0.823394Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 21 / 50,\n  svg: CurvedArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-inspiration/cutout.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cutout', 'sticker name', 'web-stories');\n\nfunction Cutout({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 48 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.50447 41.1145C6.69971 41.3366 6.89813 41.5543 7.09961 41.7679L6.97157 41.8887C6.76867 41.6737 6.56887 41.4543 6.37227 41.2308C6.17566 41.0072 5.9837 40.781 5.79635 40.5523L5.93254 40.4407C6.11858 40.6679 6.30922 40.8925 6.50447 41.1145ZM3.89702 37.5643C4.20055 38.0648 4.52293 38.5565 4.86426 39.0388L4.72057 39.1405C4.37683 38.6548 4.05218 38.1596 3.74651 37.6556L3.89702 37.5643ZM8.35345 43.0066C8.78811 43.4068 9.23464 43.7894 9.69216 44.1544L9.58237 44.2921C9.12162 43.9245 8.67194 43.5392 8.23421 43.1362L8.35345 43.0066ZM11.109 45.2051C11.5945 45.5393 12.0904 45.8553 12.5957 46.1533L12.5063 46.3049C11.9974 46.0049 11.4981 45.6866 11.0092 45.3501L11.109 45.2051ZM2.28582 34.4291C2.51673 34.9684 2.76679 35.5006 3.03612 36.0248L2.87954 36.1053C2.60831 35.5774 2.3565 35.0414 2.12399 34.4983L2.28582 34.4291ZM1.1255 31.1005C1.28065 31.6676 1.45494 32.2294 1.64849 32.7849L1.48225 32.8428C1.28737 32.2835 1.11189 31.7179 0.955692 31.1469L1.1255 31.1005ZM14.1449 46.9956C14.6711 47.2585 15.206 47.5032 15.7487 47.7296L15.6809 47.8921C15.1346 47.6642 14.596 47.4178 14.0662 47.153L14.1449 46.9956ZM17.3983 48.3537C17.9544 48.5431 18.5173 48.7142 19.0861 48.8671L19.0404 49.0371C18.4679 48.8832 17.9014 48.7109 17.3416 48.5203L17.3983 48.3537ZM0.424034 27.645C0.502961 28.2286 0.600743 28.8088 0.717487 29.3845L0.544957 29.4195C0.427439 28.84 0.329019 28.256 0.249581 27.6686L0.424034 27.645ZM20.8036 49.2699C21.3789 49.3855 21.959 49.4832 22.5431 49.5628L22.5193 49.7372C21.9316 49.6571 21.3478 49.5589 20.769 49.4425L20.8036 49.2699ZM0.176036 24.1274C0.180324 24.7169 0.202981 25.3048 0.244106 25.89L0.068499 25.9024C0.0271102 25.3134 0.00431376 24.7219 0 24.1287L0.176036 24.1274ZM0.366768 20.6047C0.299256 21.1912 0.249533 21.7777 0.217699 22.3635L0.0419167 22.3539C0.0739453 21.7646 0.123967 21.1745 0.191882 20.5846L0.366768 20.6047ZM24.2979 49.747C24.8829 49.7903 25.471 49.816 26.0612 49.824L26.0588 50C25.4651 49.9919 24.8735 49.9661 24.2849 49.9225L24.2979 49.747ZM0.975972 17.1306C0.840325 17.7052 0.721785 18.2815 0.62045 18.8588L0.447062 18.8283C0.548986 18.2477 0.668213 17.668 0.804641 17.0902L0.975972 17.1306ZM27.8253 49.7956C28.4108 49.7689 28.9976 49.725 29.5847 49.6639L29.603 49.839C29.0124 49.9005 28.4223 49.9446 27.8333 49.9715L27.8253 49.7956ZM1.98127 13.7478C1.78124 14.3039 1.59763 14.8633 1.43055 15.4253L1.26181 15.3751C1.42984 14.81 1.61447 14.2474 1.81562 13.6883L1.98127 13.7478ZM31.3342 49.4311C31.9129 49.3372 32.4912 49.2267 33.0683 49.0994L33.1062 49.2713C32.5259 49.3993 31.9444 49.5105 31.3624 49.6049L31.3342 49.4311ZM34.7806 48.6714C35.3446 48.5136 35.9067 48.3398 36.4661 48.1497L36.5227 48.3164C35.9603 48.5075 35.3951 48.6823 34.828 48.8409L34.7806 48.6714ZM3.35753 10.4993C3.09752 11.0299 2.85321 11.5651 2.62468 12.1044L2.46259 12.0357C2.69238 11.4935 2.93803 10.9553 3.19945 10.4219L3.35753 10.4993ZM38.1211 47.5368C38.6647 47.3186 39.2049 47.0848 39.7411 46.8353L39.8154 46.995C39.2763 47.2457 38.7332 47.4808 38.1867 47.7002L38.1211 47.5368ZM5.07982 7.4192C4.76387 7.9191 4.4629 8.42501 4.177 8.93623L4.02335 8.8503C4.3108 8.33634 4.61338 7.82771 4.93101 7.32515L5.07982 7.4192ZM41.3218 46.0481C41.8388 45.7733 42.3513 45.4834 42.8585 45.1785L42.9492 45.3294C42.4394 45.6359 41.9242 45.9273 41.4044 46.2036L41.3218 46.0481ZM7.12163 4.53921C6.75438 5.00328 6.40135 5.47449 6.06264 5.95216L5.91903 5.85033C6.25953 5.37014 6.61441 4.89646 6.98359 4.42997L7.12163 4.53921ZM44.3465 44.2303C44.8314 43.9032 45.3107 43.5618 45.7836 43.206L45.8895 43.3467C45.4141 43.7043 44.9324 44.0475 44.4449 44.3762L44.3465 44.2303ZM9.45185 1.8903C9.03853 2.31388 8.63866 2.74555 8.2523 3.18467L8.12013 3.06838C8.50849 2.62699 8.91042 2.1931 9.32586 1.76736L9.45185 1.8903ZM47.1711 42.1055L46.8979 41.7877L47.8967 41.5994L47.7313 42.0799L47.7291 42.0774L47.5604 42.5585L47.2858 42.2391C47.2837 42.2408 47.2816 42.2426 47.2794 42.2444L47.1666 42.1093C47.1681 42.108 47.1696 42.1068 47.1711 42.1055ZM10.7207 0.654955L10.7164 0.658923L10.5969 0.529714C10.5989 0.527833 10.6009 0.525949 10.603 0.524068L10.3212 0.21088L10.82 0.1051L10.8178 0.102626L11.3155 0L11.001 0.966494L10.7207 0.654955Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M10.1221 45.1277C10.064 45.1515 10.0104 45.1872 9.96447 45.2364C9.79245 45.4205 9.80229 45.709 9.98645 45.881C10.1706 46.053 10.4591 46.0432 10.6311 45.859C10.8031 45.6749 10.7933 45.3864 10.6091 45.2144C10.56 45.1684 10.504 45.1365 10.4445 45.1167L10.4315 44.7364L10.8118 44.7234C10.8356 44.7815 10.8713 44.8351 10.9205 44.881C11.1046 45.0531 11.3931 45.0432 11.5651 44.8591C11.7372 44.6749 11.7273 44.3864 11.5432 44.2144C11.359 44.0424 11.0705 44.0522 10.8985 44.2364C10.8526 44.2855 10.8206 44.3415 10.8008 44.4011L10.4205 44.414L10.382 43.2859L10.132 43.0524L10.0542 43.1357L10.1221 45.1277ZM10.4535 45.381C10.5451 45.4667 10.5509 45.6109 10.4645 45.7034C10.3781 45.7959 10.2338 45.8 10.1421 45.7144C10.0505 45.6287 10.0447 45.4845 10.1311 45.392C10.2175 45.2995 10.3618 45.2954 10.4535 45.381ZM11.3875 44.3811C11.4792 44.4667 11.4849 44.6109 11.3985 44.7034C11.3121 44.7959 11.1678 44.8 11.0761 44.7144C10.9845 44.6288 10.9788 44.4845 11.0652 44.3921C11.1516 44.2996 11.2958 44.2954 11.3875 44.3811ZM10.3037 44.539C10.3271 44.5608 10.3283 44.5963 10.3065 44.6196C10.2847 44.6429 10.2492 44.6442 10.2259 44.6224C10.2026 44.6006 10.2014 44.5651 10.2232 44.5418C10.2449 44.5184 10.2804 44.5172 10.3037 44.539ZM8.98098 44.7858L9.94798 44.7529L9.93699 44.4305L8.80882 44.469L8.73099 44.5523L8.98098 44.7858Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 48 / 50,\n  svg: Cutout,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-inspiration/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as fashionInspirationCurvedArrow } from './curvedArrow';\nimport { default as fashionInspirationCutout } from './cutout';\n\nexport { fashionInspirationCurvedArrow, fashionInspirationCutout };\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/arrowDark.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\n\nconst FashionArrowDark = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 16 9\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M15.8206 4.43678c.2145-.21453.2145-.56235 0-.77688L12.3246.163967c-.2145-.2145284-.5623-.2145284-.7769 0-.2145.214528-.2145.562346 0 .776874l3.1075 3.107499-3.1075 3.1075c-.2145.21453-.2145.56235 0 .77687.2146.21453.5624.21453.7769 0l3.496-3.49593zM.0507812 4.59767H15.4321V3.49901H.0507812v1.09866z\"\n      fill=\"#212121\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 16 / 9,\n  svg: FashionArrowDark,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/arrowLight.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\n\nconst FashionArrowLight = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 17 9\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M15.9436 4.43653c.2145-.21452.2145-.56234 0-.77687L12.4477.163723c-.2146-.2145286-.5624-.2145286-.7769 0-.2145.214527-.2145.562346 0 .776874L14.7783 4.0481l-3.1075 3.10749c-.2145.21453-.2145.56235 0 .77688s.5623.21453.7769 0l3.4959-3.49594zm-15.769772.1609H15.5552V3.49876H.173828v1.09867z\"\n      fill=\"#FFECE3\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 17 / 9,\n  svg: FashionArrowLight,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as fashionArrowDark } from './arrowDark';\nimport { default as fashionArrowLight } from './arrowLight';\nimport { default as fashionStarburst } from './starburst';\nimport { default as fashionStarburstSolid } from './starburstSolid';\nimport { default as fashionStarburstWithArrow } from './starburstWithArrow';\n\nexport {\n  fashionArrowDark,\n  fashionArrowLight,\n  fashionStarburst,\n  fashionStarburstSolid,\n  fashionStarburstWithArrow,\n};\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/starburst.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Burst', 'sticker name', 'web-stories');\n\nconst FashionStarburst = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 134 134\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M66.6245 8.27711l.3753.35155.3755-.35137L75.3094.853325 81.146 10.0211l.2762.4338.4511-.247 9.5222-5.21576 3.3821 10.33326.1597.488.4976-.1264 10.5181-2.6728.715 10.8524.034.5121.513.0011 10.853.0229-2.007 10.6924-.095.5038.497.1291 10.504 2.7339-4.599 9.8554-.217.4644.448.2484 9.502 5.2624-6.894 8.3924-.325.3956.371.352 7.891 7.4716-8.765 6.4126-.413.3025.273.4335 5.792 9.2004-10.078 4.0286-.476.1902.157.488 3.329 10.3571-10.77 1.386-.509.066.031.512.654 10.86-10.769-1.34-.51-.064-.097.505-2.0601 10.684-10.1077-3.982-.4784-.189-.2197.465-4.6435 9.83-8.8003-6.373-.4167-.302-.3283.396L67 133.139l-6.9383-8.368-.3283-.396-.4167.302-8.8003 6.373-4.6435-9.83-.2197-.465-.4785.189-10.0996 3.982-2.0596-10.684-.0973-.505-.5099.064-10.7769 1.34.6536-10.86.0309-.512-.509-.066-10.7618-1.385 3.3294-10.3581.1569-.4881-.4761-.1902-10.08654-4.0287 5.79226-9.2002.27298-.4335-.41347-.3025-8.764068-6.4124 7.898068-7.4716.37228-.3522-.32551-.3958-6.90164-8.3924 9.50094-5.2622.4484-.2484-.2168-.4644-4.59885-9.8553 10.51205-2.7339.4965-.1292-.095-.5042-2.0142-10.692 10.8604-.0229.5136-.0011.0334-.5125.7069-10.8519 10.5181 2.6727.4976.1264.1597-.488 3.3821-10.33326 9.5222 5.21576.4508.2469.2763-.4334L58.6982.853326l7.9263 7.423784z\"\n      stroke=\"#FF3000\"\n      strokeWidth=\"1.09867\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 134 / 134,\n  svg: FashionStarburst,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/starburstSolid.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Burst', 'sticker name', 'web-stories');\n\nconst FashionStarburstSolid = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 48 47\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M27.3533 2.78839l-.6471-1.01633-.8797.82319-1.8291 1.71147-1.827-1.71114-.8792-.82352-.6476 1.01584-1.3478 2.11428-2.195-1.20228-1.0562-.57853-.3746 1.14452-.7802 2.38391-2.425-.6162-1.166-.29628-.0782 1.20048-.163 2.50318-2.50427.00527-1.20339.00253.22278 1.18262.46488 2.4677-2.42461.6306-1.16236.3023.50788 1.0884 1.0615 2.2748-2.19217 1.2141-1.05092.5821.76306.9279 1.59278 1.9368-1.82291 1.7245-.87187.8248.9686.7087 2.02237 1.4797-1.3371 2.1238-.63971 1.016 1.11504.4454 2.32704.9295-.76855 2.3909-.36782 1.1443 1.19212.1536 2.48134.3195-.15084 2.5061-.07229 1.2009 1.19392-.1485 2.4845-.309.4751 2.4647.2281 1.1829 1.1206-.4419 2.3275-.9177 1.0706 2.2665.5147 1.0896.9761-.7068 2.0284-1.469 1.5996 1.9291.7698.9284.7698-.9284 1.5995-1.9291 2.0285 1.469.976.7068.5147-1.0896 1.0707-2.2667 2.33.918 1.1205.4415.228-1.1826.4752-2.4646 2.482.3089 1.194.1486-.0723-1.201-.1509-2.506 2.4837-.3196 1.1922-.1535-.3678-1.1444-.7686-2.3912 2.3249-.9293 1.1146-.4455-.6395-1.0158-1.3371-2.1238 2.0224-1.4797.9681-.7084-.8711-.8248-1.8215-1.7248 1.5914-1.9372.7621-.9278-1.0503-.5818-2.1922-1.2141 1.0615-2.2748.5078-1.0882-1.1621-.3024-2.423-.6307.4632-2.4684.2219-1.18192-1.2026-.00253-2.5025-.00527-.1648-2.50388-.079-1.19957-1.1651.29607-2.425.6162-.7803-2.38391-.3746-1.14452-1.0562.57853-2.1945 1.20202-1.3455-2.11353z\"\n      fill=\"#FF3000\"\n      stroke=\"#FFECE3\"\n      strokeWidth=\"2\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 48 / 47,\n  svg: FashionStarburstSolid,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fashion-on-the-go/starburstWithArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Burst with Arrow', 'sticker name', 'web-stories');\n\nconst FashionStarburstWithArrow = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 280 270\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M157.588 0L140 15.8699 122.428 0l-12.955 19.5973L88.3634 8.44767l-7.497 22.08763-23.3165-5.7131-1.5667 23.1944-24.0747.0489 4.4645 22.8526-23.2996 5.8434 10.1925 21.0622L2.20698 109.071l15.29722 17.937L0 142.976l19.4248 13.705-12.83756 19.662 22.35616 8.611-7.379 22.136 23.8556 2.962-1.4489 23.211 23.8893-2.865 4.5656 22.837 22.3899-8.513 10.2941 21.013 19.509-13.623L140 270l15.381-17.888 19.51 13.623 10.293-21.013 22.407 8.513 4.565-22.837 23.873 2.865-1.449-23.211 23.872-2.962-7.379-22.136 22.34-8.611-12.838-19.662L280 142.976l-17.487-15.968 15.28-17.937-21.059-11.2473 10.193-21.0622-23.283-5.8434 4.447-22.8526-24.057-.0489-1.584-23.1944-23.316 5.7131-7.497-22.08763-21.11 11.14963L157.588 0zm-11.889 109.488c0 10.932 6.756 20.317 16.382 24.413h-57.199v2.198h57.199c-9.626 4.096-16.382 13.481-16.382 24.413h2.197c0-13.443 11.192-24.413 25.017-24.413v-2.198c-13.825 0-25.017-10.97-25.017-24.413h-2.197z\"\n      fill=\"#FF3000\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 280 / 270,\n  svg: FashionStarburstWithArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/dumbbells.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dumbbells', 'sticker name', 'web-stories');\n\nfunction Dumbbells({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 48 28\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M47.656 14.143C47.656 13.7509 47.5787 13.2803 47.5787 12.8881C47.5787 12.4176 47.656 11.8686 47.347 11.4764C46.8835 10.849 45.9566 10.9274 45.2614 10.9274C45.2614 9.8294 45.1841 8.73139 45.1841 7.63338C45.1841 6.84909 45.4159 5.59422 44.9524 4.88836C44.1799 3.79035 42.017 3.94721 40.7039 3.86878C40.7039 3.71193 40.7039 3.47664 40.7039 3.31978C40.4721 0.496332 38.9272 0.0257568 36.2236 0.0257568C33.2883 0.0257568 32.5158 1.04534 32.2841 4.02564C32.1296 6.37852 32.0524 8.73139 32.0524 11.0058C29.1943 11.2411 26.1817 10.9274 23.4008 10.9274C20.929 10.9274 18.5344 11.0058 16.0625 11.0843C16.0625 8.73139 15.9853 6.45694 15.8308 4.10407C15.599 1.20219 14.8266 0.104186 11.8912 0.104186C9.80561 0.104186 7.71997 0.339473 7.41099 2.69235C7.33375 3.16292 7.33375 3.6335 7.2565 4.02564C5.94332 4.02564 3.93494 3.94721 3.23973 4.88836C2.23553 6.14323 2.69901 9.43725 2.69901 10.849C2.69901 10.9274 2.69901 10.9274 2.69901 11.0058C2.08104 11.0058 1.38583 10.9274 0.922356 11.1627C0.0726539 11.5548 0.381637 13.045 0.381637 13.8293C0.381637 14.6136 0.1499 15.8684 1.07685 16.0253C1.54032 16.1037 2.08104 16.1822 2.54451 16.1037C2.54451 17.9076 2.62176 19.7899 3.08523 21.3585C3.54871 23.3976 5.47985 23.3976 7.33375 23.3976C7.33375 23.6329 7.33375 23.9466 7.41099 24.1819C7.64273 26.6917 9.03315 26.9269 11.196 26.9269C12.5865 26.9269 14.8266 27.476 15.6763 25.9858C16.1398 25.1231 16.0625 23.6329 16.0625 22.6918C16.1398 20.6526 16.1398 18.6135 16.0625 16.5743C16.0625 16.4174 16.0625 16.2606 16.0625 16.1037C21.3152 16.0253 26.7224 16.339 31.9751 16.0253C31.9751 17.8292 31.9751 19.7115 31.9751 21.5153C31.9751 22.6918 31.8206 24.1819 32.2068 25.3584C32.8248 27.3191 35.0649 26.8485 36.7643 26.8485C38.6182 26.8485 40.2404 26.9269 40.7039 24.7309C40.7811 24.2604 40.8584 23.7898 40.8584 23.3192C42.635 23.3192 44.5662 23.2408 45.0296 21.3585C45.4159 19.8683 45.4931 18.0645 45.4159 16.339C46.0338 16.339 46.729 16.339 47.1925 16.1037C47.8105 15.7116 47.656 14.7704 47.656 14.143ZM1.46308 15.0057C1.38583 14.5351 1.46308 13.9861 1.46308 13.5156C1.46308 13.2018 1.46308 12.9666 1.46308 12.6528C1.46308 12.5744 1.54032 12.1823 1.46308 12.1823C1.61757 12.1038 2.08104 12.1823 2.15829 12.1823C2.31278 12.1823 2.54451 12.1823 2.69901 12.1823C2.69901 13.1234 2.62176 14.143 2.62176 15.1626C2.23553 15.0841 1.77206 15.0841 1.46308 15.0057ZM4.08943 20.4958C3.85769 19.633 3.93494 18.6919 3.93494 17.8292C3.78045 15.5547 3.78045 13.2018 3.78045 10.849C3.78045 9.51568 3.62595 7.86867 3.93494 6.53537C4.32117 4.96679 5.78883 5.12365 7.2565 5.12365C7.17925 7.71181 7.41099 10.3 7.41099 12.8097C7.33375 15.9469 7.17925 19.1625 7.33375 22.2996C5.5571 22.2996 4.5529 22.3781 4.08943 20.4958ZM14.9811 23.5545C14.9038 24.7309 15.0583 25.5937 13.8224 25.9074C13.1272 26.0642 12.123 25.9074 11.4278 25.9074C10.1146 25.9074 8.87866 25.2799 8.49243 23.9466C8.26069 22.9271 8.49243 21.4369 8.49243 20.4173C8.49243 17.9076 8.41518 15.3979 8.49243 12.8881C8.49243 11.2411 8.49243 9.59411 8.41518 7.9471C8.41518 6.6138 8.49243 5.35894 8.49243 4.02564C8.49243 1.82963 9.88285 1.35905 11.814 1.35905C12.7409 1.35905 13.9769 1.82963 14.5176 2.69235C14.8266 3.16292 14.6721 4.41779 14.6721 5.04522C14.7493 6.30009 14.7493 7.63338 14.8266 8.88825C14.9038 11.3196 14.9811 13.8293 14.9811 16.2606C15.0583 18.6135 15.1356 21.1232 14.9811 23.5545ZM16.0625 15.0841C16.0625 14.143 16.0625 13.2018 16.0625 12.2607C18.4571 12.1823 20.929 12.1823 23.4008 12.1038C26.2589 12.1038 29.2715 12.4176 32.0524 12.1823C32.0524 13.1234 32.0524 14.0646 32.0524 15.0057C26.7224 15.241 21.3925 15.0057 16.0625 15.0841ZM39.6997 7.71181C39.6224 9.35882 39.6224 11.0058 39.6224 12.6528C39.6997 15.0057 39.6224 17.3586 39.6224 19.7115C39.6224 22.2996 40.3949 25.6721 36.7643 25.7505C36.1464 25.7505 35.0649 25.9858 34.447 25.7505C32.8248 25.0446 33.1338 23.7114 33.0565 22.3781C32.9793 20.0252 32.9793 17.7507 33.0565 15.3979C33.0565 12.9666 33.1338 10.6137 33.211 8.18239C33.2883 5.59422 32.5158 1.12376 36.2236 1.12376C38.3865 1.12376 39.2362 1.90806 39.6224 4.1825C39.8542 5.35894 39.6997 6.53537 39.6997 7.71181ZM44.1799 17.986C44.1799 18.7703 44.2572 19.7115 44.0254 20.4173C43.562 22.2212 42.4033 22.1428 40.8584 22.1428C40.8584 20.9663 40.7039 19.7899 40.7811 18.6919C40.7811 16.6527 40.7811 14.6136 40.7811 12.5744C40.7039 9.98626 40.9356 7.47652 40.8584 4.88836C41.5536 4.88836 42.2488 4.88836 42.8667 5.04522C44.1027 5.35894 44.1027 5.5158 44.1799 6.84909C44.3344 8.57453 44.1799 10.3784 44.2572 12.0254C44.1799 14.143 44.1799 16.1037 44.1799 17.986ZM45.3386 15.1626C45.2614 14.143 45.2614 13.1234 45.2614 12.1823C45.2614 12.1038 45.2614 12.0254 45.2614 12.0254C45.4931 12.0254 45.7248 12.0254 46.0338 12.0254C46.42 12.0254 46.42 11.947 46.4973 12.2607C46.5745 12.496 46.4973 12.8881 46.4973 13.1234C46.4973 13.4371 46.5745 13.7509 46.5745 14.0646C46.5745 14.2999 46.5745 14.5351 46.5745 14.8489C46.5745 14.8489 46.5745 15.0057 46.5745 15.0841H46.4973C46.1111 15.0841 45.7248 15.1626 45.3386 15.1626Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M9.57278 3.86881C9.03206 5.12367 9.18655 6.69225 9.34104 8.02555C9.41829 8.73141 10.4997 8.73141 10.4225 8.02555C10.268 6.84911 10.1135 5.35896 10.577 4.18252C10.886 3.55509 9.88176 3.24137 9.57278 3.86881Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M11.0405 2.30007C10.3453 2.30007 10.3453 3.39808 11.0405 3.39808C11.7357 3.39808 11.7357 2.30007 11.0405 2.30007Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M34.5231 3.39831C34.1369 3.94731 34.1369 4.7316 34.0597 5.35904C33.9824 6.14333 33.9052 6.92762 33.9824 7.71191C34.0597 8.41777 35.1411 8.41777 35.0639 7.71191C34.9866 7.08448 35.0639 6.37861 35.0639 5.75118C35.1411 5.20218 35.1411 4.41789 35.4501 3.94731C35.9136 3.39831 34.9866 2.8493 34.5231 3.39831Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M36.068 1.98648C35.3728 1.98648 35.3728 3.08449 36.068 3.08449C36.7633 3.08449 36.7633 1.98648 36.068 1.98648Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 48 / 28,\n  svg: Dumbbells,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as technologyMuscle } from './muscle';\nimport { default as technologyPieChart } from './piechart';\nimport { default as technologyRunningFigure } from './running';\nimport { default as technologyShoe } from './shoe';\nimport { default as technologySwimmer } from './swimmer';\nimport { default as technologyDumbbells } from './dumbbells';\n\nexport {\n  technologyMuscle,\n  technologyPieChart,\n  technologyRunningFigure,\n  technologyShoe,\n  technologySwimmer,\n  technologyDumbbells,\n};\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/muscle.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Muscle', 'sticker name', 'web-stories');\n\nfunction Muscle({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M30.6997 7.20663C30.8119 7.40443 30.9242 7.59532 31.0296 7.78852C31.1945 8.08982 31.3686 8.38882 31.5198 8.69702C31.671 9.00752 31.7741 9.33411 31.8451 9.67451C31.9711 10.284 31.8612 10.8498 31.5817 11.3903C31.4236 11.6985 31.2243 11.9814 30.9815 12.2275C30.0834 13.1383 29.1831 14.0468 28.1591 14.8196C27.6872 15.1761 27.1855 15.4843 26.6334 15.7028C25.8682 16.0064 25.0847 16.1697 24.26 16.0225C23.8018 15.9397 23.3437 15.8569 22.8855 15.7741C22.6197 15.7258 22.3563 15.6706 22.0905 15.6223C21.6507 15.5395 21.2131 15.5372 20.7733 15.6269C20.6771 15.6476 20.5808 15.6798 20.4846 15.6798C20.0585 15.6798 19.834 15.9075 19.6576 16.2847C19.2476 17.1725 19.0482 18.1017 19.0162 19.0723C18.9772 20.2821 19.0643 21.4849 19.2407 22.6809C19.3758 23.6078 19.5156 24.5324 19.6439 25.4593C19.8088 26.6369 19.8386 27.8145 19.6118 28.9898C19.5889 29.1094 19.5843 29.2336 19.5729 29.3555C19.5683 29.4038 19.6553 29.5142 19.7011 29.5165C19.8959 29.5349 20.0906 29.5556 20.2853 29.5625C21.2567 29.597 22.1753 29.827 23.0298 30.2985C23.1146 30.3468 23.2062 30.3836 23.3001 30.4112C23.3391 30.4227 23.4078 30.402 23.4284 30.3721C23.5315 30.2341 23.6254 30.0915 23.7148 29.9466C24.3196 28.9507 25.0549 28.0629 25.9255 27.2924C27.5062 25.894 29.3274 24.9786 31.3961 24.5646C33.6893 24.1069 35.9344 24.307 38.1382 25.0706C38.3696 25.1511 38.5964 25.2385 38.7728 25.3029C38.995 25.3075 39.0866 25.1695 39.2149 25.1005C39.3455 25.0315 39.4692 24.9533 39.5975 24.8774C40.6857 24.2334 41.854 23.8079 43.0911 23.5595C44.4267 23.2927 45.7737 23.2605 47.1185 23.4238C47.9455 23.5227 48.7542 23.7504 49.5376 24.0379C51.6384 24.8084 53.4001 26.0711 54.7998 27.8168C56.5386 29.9834 57.4229 32.4697 57.4275 35.2596C57.432 37.6953 56.7287 39.9193 55.4115 41.9525C54.2958 43.6775 52.8365 45.046 51.0794 46.0948C50.9328 46.1822 50.7793 46.265 50.6258 46.3386C50.3784 46.4582 50.1447 46.3984 49.934 46.2443C49.769 46.1224 49.6751 45.9476 49.6453 45.7452C49.6132 45.5336 49.698 45.3519 49.8584 45.2208C50.0096 45.0989 50.1791 44.9931 50.3463 44.8919C51.0015 44.4986 51.6224 44.057 52.1905 43.5487C53.9201 42.0031 55.1412 40.1309 55.7116 37.8631C56.4424 34.9629 55.9819 32.2443 54.4218 29.7074C53.8514 28.7782 53.1572 27.9525 52.3211 27.251C51.0405 26.1723 49.588 25.4294 47.9638 25.0292C47.0566 24.8061 46.1334 24.6773 45.1941 24.7256C43.634 24.8038 42.1358 25.135 40.7384 25.8618C40.6513 25.9078 40.5734 25.963 40.4909 26.0182C40.4337 26.055 40.4382 26.1562 40.5001 26.2022C40.5986 26.2758 40.6948 26.3517 40.7979 26.4184C41.46 26.8485 42.0716 27.3407 42.6375 27.8904C43.508 28.7368 44.2365 29.689 44.8184 30.7562C44.878 30.8643 44.9353 30.9724 44.9811 31.0874C45.0865 31.3427 45.0246 31.5704 44.8528 31.7728C44.7543 31.8878 44.6237 31.9545 44.484 32.0051C44.2709 32.081 44.0166 32.0281 43.8792 31.8602C43.7875 31.7475 43.7096 31.621 43.6295 31.4945C43.4324 31.1817 43.2515 30.8597 43.0407 30.5561C41.4485 28.2584 39.3066 26.7427 36.6056 26.055C34.4842 25.5145 32.3743 25.595 30.3011 26.3172C28.867 26.8163 27.607 27.6098 26.5142 28.6701C25.7308 29.4291 25.0893 30.2962 24.5693 31.2553C24.4754 31.4278 24.3837 31.6026 24.2898 31.7751C24.1913 31.9545 24.0424 32.0741 23.8522 32.15C23.7079 32.2075 23.5636 32.2213 23.4261 32.15C23.252 32.0603 23.0848 31.9568 22.9176 31.8533C22.4365 31.552 21.9256 31.3105 21.3758 31.1725C20.732 31.0092 20.0791 30.9149 19.4102 30.9724C19.1147 30.9977 18.8993 31.0943 18.7802 31.3864C18.6863 31.6118 18.5649 31.828 18.4412 32.0419C17.9372 32.9205 17.3392 33.7324 16.6314 34.4569C16.5122 34.5788 16.3794 34.6915 16.2373 34.7812C16.0357 34.91 15.8204 34.9031 15.6119 34.7766C15.3828 34.6363 15.266 34.4316 15.2706 34.1648C15.2729 33.9877 15.3256 33.8244 15.4447 33.6887C15.5753 33.5415 15.7104 33.3989 15.841 33.2517C16.7551 32.2305 17.4492 31.0828 17.8776 29.7741C18.2579 28.6149 18.3999 27.4212 18.3564 26.2045C18.3266 25.342 18.2167 24.4864 18.0471 23.64C17.7585 22.2094 17.6393 20.7604 17.7149 19.3023C17.7631 18.3915 17.857 17.4853 18.0173 16.586C18.0815 16.2226 18.1754 15.8638 18.3197 15.5211C18.6313 14.7851 19.1742 14.3389 19.9623 14.194C20.5213 14.0905 21.0803 14.0468 21.6438 14.1411C22.2234 14.2377 22.8076 14.3182 23.3872 14.4263C23.8477 14.5114 24.3127 14.5436 24.7778 14.5551C25.5337 14.5735 26.2279 14.3596 26.8647 13.9479C27.7994 13.3453 28.6516 12.6484 29.4122 11.8365C29.6848 11.5467 29.8956 11.2178 30.0697 10.8613C30.1224 10.7509 30.1636 10.6336 30.2049 10.5186C30.3309 10.1575 30.3423 9.79411 30.2209 9.43071C30.1659 9.26741 30.1109 9.10412 30.0468 8.94542C29.9529 8.71542 29.82 8.68552 29.6711 8.86492C29.0686 9.58711 28.3767 10.2104 27.6047 10.744C27.1992 11.0246 26.7708 11.2615 26.3195 11.457C26.0011 11.5927 25.6735 11.6893 25.3321 11.7399C24.1523 11.9147 22.9313 11.2868 22.3769 10.2288C22.0585 9.61931 22.0379 9.00522 22.3059 8.37732C22.4319 8.08062 22.6106 7.81612 22.8168 7.56772C23.2749 7.01573 23.8064 6.54193 24.3631 6.09343C24.6792 5.83813 25.0664 5.90023 25.3436 6.21993C25.5521 6.45913 25.5635 6.80183 25.3528 7.02723C25.2016 7.18823 25.0297 7.32853 24.8671 7.47802C24.6518 7.67812 24.4295 7.87132 24.2211 8.08062C24.0286 8.27382 23.8728 8.49922 23.7675 8.74992C23.6048 9.13861 23.6231 9.52041 23.8637 9.87461C24.0951 10.2127 24.4181 10.3507 24.819 10.2886C25.1374 10.2403 25.4421 10.1391 25.717 9.97351C26.0538 9.77111 26.3928 9.57101 26.7044 9.33412C27.2336 8.93392 27.7215 8.48312 28.1774 7.99782C28.4317 7.72872 28.6585 7.43892 28.8235 7.10313C29.0777 6.58563 29.0915 6.06353 28.8578 5.53454C28.6952 5.17114 28.4798 4.84224 28.2003 4.56164C27.4535 3.81185 26.6746 3.09885 25.7972 2.50085C25.41 2.23635 24.9954 2.02476 24.5601 1.85226C24.1936 1.70506 23.8133 1.61536 23.4147 1.59926C22.7847 1.57626 22.1936 1.70506 21.6759 2.08455C21.3987 2.28695 21.1261 2.49855 20.8603 2.71475C20.1547 3.28745 19.456 3.87164 18.7481 4.43974C18.0586 4.99404 17.3599 5.53684 16.668 6.08883C15.5134 7.00653 14.3199 7.87132 13.0965 8.69472C12.7094 8.95462 12.3268 9.22141 11.9488 9.49511C11.1378 10.0816 10.4941 10.813 10.0451 11.7123C9.82514 12.1539 9.60979 12.5955 9.41278 13.0463C7.96036 16.4227 6.61102 19.8313 5.40602 23.2996C4.39574 26.2091 3.49771 29.1485 2.80128 32.1523C2.61801 32.9435 2.38663 33.7232 2.18732 34.5121C2.06591 34.9882 1.96052 35.4712 1.85514 35.9519C1.77496 36.3153 1.75893 36.6833 1.7658 37.0536C1.77038 37.3388 1.87118 37.5826 2.043 37.7987C2.24459 38.0494 2.48056 38.2634 2.73484 38.4588C3.28008 38.882 3.87112 39.2339 4.45988 39.5881C5.11278 39.9814 5.76798 40.3678 6.40943 40.7749C9.4059 42.6747 12.5513 44.2686 15.8616 45.5428C17.5111 46.1776 19.1926 46.7181 20.9016 47.1666C22.3975 47.5599 23.9072 47.8888 25.4398 48.0958C26.3882 48.2246 27.3367 48.3396 28.2851 48.4615C28.3103 48.4638 28.3332 48.4661 28.3584 48.4684C30.4889 48.6087 32.6195 48.7191 34.7546 48.565C35.4876 48.5121 36.223 48.4799 36.9561 48.4086C38.2275 48.2821 39.4852 48.0912 40.7406 47.8589C42.6971 47.4978 44.6214 47.0102 46.5137 46.4007C46.7473 46.3248 46.9787 46.2397 47.2193 46.1914C47.4552 46.1431 47.6568 46.2443 47.7966 46.4375C48.0852 46.84 47.9501 47.3552 47.5102 47.553C47.4209 47.5921 47.3269 47.622 47.233 47.6519C45.1323 48.3373 42.9995 48.8962 40.8208 49.2757C38.885 49.6115 36.9378 49.8346 34.9791 49.9611C34.8073 49.9726 34.6354 49.9841 34.4636 49.9864C33.506 49.9933 32.5507 50.0071 31.5931 49.9956C30.2919 49.9818 28.9976 49.8668 27.7032 49.7449C25.9415 49.5816 24.2027 49.2849 22.4731 48.9238C21.1055 48.6386 19.7561 48.2637 18.416 47.8612C16.274 47.2172 14.1961 46.4053 12.1618 45.4784C10.462 44.7056 8.80569 43.85 7.19749 42.9001C6.4163 42.4378 5.61449 42.01 4.82413 41.5638C4.09792 41.1521 3.38546 40.7174 2.70048 40.2367C2.29728 39.9538 1.91013 39.6525 1.56191 39.3029C0.734901 38.4772 0.531012 37.9529 0.57912 36.7914C0.597448 36.3728 0.65472 35.9588 0.730319 35.5448C1.07853 33.6565 1.42446 31.7659 1.90325 29.9052C2.27209 28.4746 2.68903 27.0578 3.14949 25.6548C3.88945 23.41 4.6569 21.1744 5.50453 18.9688C6.08641 17.4531 6.69808 15.9466 7.31433 14.4424C7.82748 13.1889 8.36355 11.9469 8.89046 10.7003C9.12183 10.1552 9.41507 9.64231 9.76328 9.16391C9.98321 8.86262 10.2421 8.60272 10.5513 8.39572C10.8377 8.20482 11.1287 8.02312 11.4242 7.84832C11.7838 7.63672 12.1504 7.43662 12.5169 7.23883C13.0347 6.95593 13.5295 6.63623 14.0014 6.27973C15.8822 4.85604 17.7608 3.43005 19.637 2.00176C20.0081 1.71886 20.3586 1.40836 20.7343 1.13236C21.0711 0.886262 21.4193 0.651663 21.7813 0.446964C22.2326 0.189366 22.7228 0.0352665 23.2474 0.00536664C23.8247 -0.0268332 24.3746 0.0858662 24.8877 0.343465C25.1924 0.497564 25.4948 0.672363 25.7651 0.879362C26.8395 1.69816 27.93 2.49625 29.0319 3.27825C29.4947 3.60485 29.9185 3.97974 30.2782 4.42134C30.5141 4.70884 30.702 5.02164 30.8028 5.38734C30.9242 5.82433 30.9563 6.25903 30.8257 6.69833C30.7822 6.86393 30.7432 7.02953 30.6997 7.20663Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 50,\n  svg: Muscle,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/piechart.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Pie Chart', 'sticker name', 'web-stories');\n\nfunction PieChart({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M27.6146 0V22.3854H50C49.7258 19.4477 48.962 16.6863 47.7086 14.1011C46.416 11.4767 44.7807 9.17549 42.8026 7.19742C40.8245 5.21934 38.5233 3.58403 35.8989 2.29142C33.3137 1.03799 30.5523 0.274188 27.6146 0ZM40.0705 45.0059C41.4414 43.9483 42.6949 42.7928 43.8308 41.5394C44.9667 40.2468 45.9655 38.8563 46.8273 37.3678C47.689 35.8793 48.394 34.293 48.9424 32.6087C49.4908 30.9244 49.8433 29.2009 50 27.4383H29.4947L40.0705 45.0059ZM22.5617 24.9119V0C19.4281 0.313358 16.4904 1.17508 13.7485 2.5852C10.9675 3.99531 8.56836 5.81668 6.55112 8.04936C4.53387 10.282 2.93773 12.8476 1.76263 15.7462C0.587539 18.6056 0 21.6608 0 24.9119C0 28.3588 0.665878 31.6099 1.99765 34.6651C3.29025 37.7203 5.07245 40.3839 7.3443 42.6557C9.61615 44.9275 12.2797 46.7097 15.3349 48.0024C18.3901 49.3341 21.6412 50 25.0881 50C27.0075 50 28.8582 49.7846 30.6404 49.3537C32.4226 48.9228 34.1363 48.3353 35.7814 47.5911C35.7814 47.5911 35.096 46.416 33.725 44.0658C32.3541 41.7548 30.8363 39.1892 29.1716 36.369C27.5068 33.5488 25.989 30.9636 24.6181 28.6134C23.2472 26.224 22.5617 24.9902 22.5617 24.9119Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: PieChart,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/running.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Running', 'sticker name', 'web-stories');\n\nfunction RunningFigure({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 48 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M41.8398 5.21845C41.8398 6.63431 41.3341 7.84789 40.3228 8.85922C39.3115 9.87055 38.0777 10.3762 36.6214 10.3762C35.2055 10.3762 33.9919 9.87055 32.9806 8.85922C31.9692 7.84789 31.4636 6.63431 31.4636 5.21845C31.4636 3.76213 31.9692 2.52832 32.9806 1.51699C33.9919 0.505657 35.2055 0 36.6214 0C38.0777 0 39.3115 0.505657 40.3228 1.51699C41.3341 2.52832 41.8398 3.76213 41.8398 5.21845ZM32.3738 21.6019L27.8228 29.2476L35.6505 30.8252C36.5809 31.0275 37.39 31.432 38.0777 32.0388C38.7654 32.6456 39.271 33.394 39.5947 34.284L44.267 48.3617L39.3519 50L34.6796 35.9223L21.2694 33.2524L16.2937 41.5049C15.8487 42.2735 15.2318 42.8904 14.443 43.3556C13.6541 43.8208 12.7945 44.0534 11.8641 44.0534H0.39563V38.835H11.8641L25.0316 16.9296L19.9345 15.8981L15.6869 24.4539L11.0146 22.1481L15.3228 13.5922C15.8487 12.5404 16.6375 11.7516 17.6893 11.2257C18.7411 10.6998 19.8333 10.5583 20.966 10.801L30.9175 12.8034C31.6052 12.9248 32.2322 13.1776 32.7985 13.5619C33.3649 13.9462 33.8301 14.4215 34.1942 14.9879L37.7743 20.3883L46.3908 18.2039L47.6044 23.2403L39.0485 25.3641C38.8463 25.445 38.6339 25.4955 38.4114 25.5158C38.1889 25.536 37.9765 25.5461 37.7743 25.5461C36.9248 25.5461 36.1157 25.3439 35.3471 24.9393C34.5785 24.5348 33.9515 23.9685 33.466 23.2403L32.3738 21.6019Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 48 / 50,\n  svg: RunningFigure,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/shoe.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Shoe', 'sticker name', 'web-stories');\n\nfunction Shoe({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 38\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M33.4469 36.0935C33.4556 36.0352 33.4794 35.9726 33.4621 35.9575C33.3582 35.8689 33.25 35.7804 33.1353 35.7092C31.5188 34.7116 29.9413 33.6558 28.3702 32.5891C25.3817 30.5594 22.4473 28.4542 19.5086 26.3533C17.0979 24.6302 14.6786 22.918 12.2614 21.2014C11.7139 20.8127 11.1405 20.4629 10.5562 20.1304C9.65163 19.6144 8.74276 19.1048 7.8685 18.5348C7.28639 18.1548 6.72158 17.751 6.22603 17.2587C6.06156 17.0967 5.90792 16.9218 5.75861 16.7448C5.4405 16.3712 5.34095 15.9264 5.37125 15.4493C5.39505 15.0757 5.48378 14.7173 5.63742 14.3783C6.18924 13.1648 7.01589 12.1932 8.1931 11.5389C8.41599 11.4137 8.6497 11.3165 8.90073 11.2582C9.0349 11.228 9.16257 11.1805 9.3054 11.1351C9.34867 11.0185 9.39412 10.9149 9.42658 10.8048C9.69491 9.88928 10.0996 9.03423 10.5583 8.20293C11.1058 7.20969 11.7161 6.25316 12.348 5.31174C13.0058 4.33146 13.6658 3.35333 14.3237 2.37521C14.5682 2.00814 14.8344 1.66051 15.1439 1.34526C15.3884 1.0948 15.6589 0.878875 15.9727 0.721252C16.5764 0.416803 17.178 0.427599 17.7709 0.747163C18.3531 1.06025 18.814 1.51152 19.2057 2.03837C19.593 2.5609 19.922 3.11798 20.199 3.70529C20.4175 4.1652 20.6339 4.62511 20.8546 5.08287C20.9758 5.33333 21.1035 5.57948 21.2247 5.82779C21.9907 7.39107 23.2221 8.46851 24.7736 9.21128C25.4034 9.51357 26.0612 9.73165 26.745 9.872C26.903 9.90439 27.0632 9.9411 27.2125 9.99724C27.4267 10.0771 27.5609 10.3211 27.5414 10.5565C27.5068 10.9775 27.1649 11.2906 26.7537 11.2733C26.6606 11.269 26.5676 11.2582 26.4789 11.2388C24.4058 10.7767 22.6356 9.78347 21.203 8.21373C20.5603 7.50982 20.0518 6.70659 19.6212 5.85802C19.4329 5.48664 19.2576 5.10878 19.0758 4.73523C18.8421 4.25589 18.5868 3.7895 18.2795 3.35333C18.1042 3.10718 17.9094 2.87831 17.6714 2.69046C17.204 2.32339 16.6911 2.28668 16.1847 2.59545C15.8861 2.77682 15.6221 3.0057 15.4079 3.28208C15.1525 3.61028 14.9037 3.94496 14.6786 4.29475C14.4665 4.62511 14.2739 4.97059 14.0965 5.32038C13.1595 7.18162 12.0883 8.96729 11.0193 10.753C10.8786 10.9905 10.7271 11.2215 10.5692 11.4698C10.6492 11.5886 10.7142 11.7095 10.8029 11.8131C11.1058 12.1694 11.4759 12.4501 11.8611 12.7071C12.2657 12.977 12.6769 13.2382 13.0902 13.4908C13.6226 13.8169 14.1441 14.1624 14.6461 14.5381C21.4108 19.6036 28.1754 24.6691 34.9444 29.7303C35.5201 30.16 36.0719 30.6177 36.6172 31.0863C36.9872 31.4015 37.3703 31.7017 37.7555 31.9975C38.554 32.6128 39.4693 32.9043 40.4691 32.9238C41.1638 32.9367 41.8627 32.9562 42.553 32.9C43.8017 32.8007 45.0525 32.7964 46.3032 32.7985C47.7639 32.8007 49.2225 32.7985 50.6832 32.8007C50.8693 32.8007 51.0554 32.8007 51.2372 32.8223C51.4254 32.8439 51.5942 32.9216 51.7154 33.0771C51.8647 33.2736 51.9253 33.4873 51.8236 33.727C51.7154 33.9775 51.5423 34.1524 51.2588 34.1804C51.0987 34.1977 50.9342 34.1977 50.7741 34.1977C47.3679 34.1977 43.9618 34.1999 40.5557 34.1956C40.0926 34.1956 39.6316 34.1804 39.1729 34.0833C38.6211 33.9688 38.106 33.7723 37.6343 33.4701C37.0889 33.1203 36.5415 32.7726 36.0091 32.4034C34.1459 31.1079 32.326 29.754 30.5342 28.3592C28.4524 26.7376 26.3728 25.1117 24.2846 23.4966C22.9645 22.4775 21.5926 21.5296 20.2228 20.5795C18.6993 19.5259 17.1737 18.4765 15.6589 17.4077C13.6875 16.0171 11.807 14.5186 10.0736 12.8366C10.0065 12.7718 9.94377 12.7006 9.86587 12.6531C9.79013 12.6077 9.69491 12.5689 9.60835 12.5667C9.24913 12.5581 8.9202 12.6552 8.64538 12.8949C8.52419 13.0007 8.41166 13.1195 8.30779 13.2425C8.2169 13.3483 8.13467 13.4606 8.06326 13.5794C7.66076 14.2574 7.2193 14.9073 6.7086 15.5076C6.68047 15.5421 6.66748 15.5896 6.63502 15.6565C6.69994 15.7343 6.75837 15.8379 6.84709 15.9027C7.10894 16.0927 7.36862 16.2913 7.6521 16.4447C8.65187 16.9888 9.58239 17.6365 10.5151 18.2821C16.492 22.4235 22.4668 26.5649 28.4481 30.6955C29.7443 31.5915 31.0254 32.5049 32.2611 33.4809C33.0055 34.0703 33.7824 34.6144 34.596 35.1067C35.3145 35.5407 36.0762 35.8668 36.9072 36.0287C37.1366 36.0741 37.3616 36.1043 37.5953 36.1043C39.2638 36.1021 40.9322 36.1043 42.6006 36.1021C42.8776 36.1021 43.1568 36.0935 43.4338 36.0654C44.1501 35.9942 44.8664 35.9812 45.5848 35.9726C46.6062 35.9618 47.6211 35.8841 48.6274 35.7005C49.6791 35.5105 50.707 35.2449 51.6808 34.7915C52.1872 34.554 52.6611 34.269 53.0895 33.9105C53.6132 33.4744 54.0309 32.954 54.2776 32.3127C54.3425 32.1421 54.3944 31.9608 54.4247 31.7815C54.494 31.3519 54.3403 31.0086 53.9724 30.771C53.8556 30.6955 53.7322 30.6328 53.6067 30.5724C53.5245 30.5314 53.4379 30.4968 53.3492 30.4687C51.7955 29.9959 50.3045 29.3589 48.7962 28.7673C46.6841 27.9381 44.5569 27.15 42.421 26.3835C40.9171 25.8437 39.4217 25.2823 37.9719 24.6043C37.6581 24.4575 37.3443 24.3064 37.0262 24.1682C36.2147 23.8141 35.5915 23.2397 35.0981 22.5228C34.9011 22.2378 34.7129 21.9442 34.5527 21.6354C33.3496 19.3121 31.9733 17.0881 30.677 14.8188C30.1036 13.8147 29.5193 12.8172 28.9393 11.8153C28.8463 11.6555 28.7576 11.4936 28.6667 11.3316C28.4979 11.0337 28.5368 10.7551 28.7467 10.4939C28.9069 10.2952 29.0584 10.0879 29.238 9.91087C30.2767 8.88956 31.5123 8.54193 32.9362 8.85501C33.5313 8.98457 34.0745 9.23935 34.6025 9.53301C34.6826 9.57835 34.7605 9.62801 34.8362 9.68415C35.2582 9.99724 35.2625 10.537 34.8449 10.8652C34.6674 11.0056 34.4554 11.0293 34.2541 10.9365C34.0875 10.8588 33.9425 10.74 33.7888 10.6364C33.4599 10.4161 33.1115 10.2434 32.7285 10.1289C32.01 9.91519 31.3565 10.0577 30.7463 10.4636C30.6511 10.5284 30.5623 10.604 30.4736 10.6795C30.1101 10.9862 30.1425 11.0768 30.3351 11.4461C30.6359 12.0204 30.9454 12.5883 31.3024 13.1303C31.4929 13.4196 31.6703 13.7176 31.8456 14.0177C33.0985 16.1791 34.3515 18.3404 35.6001 20.504C35.7494 20.7631 35.8858 21.033 36.0243 21.3007C36.1195 21.4864 36.2039 21.6764 36.3034 21.86C36.6475 22.4991 36.5847 22.4084 37.2296 22.7366C37.3724 22.81 37.5304 22.8597 37.684 22.9072C38.6146 23.1922 39.5234 23.542 40.4172 23.922C43.9769 25.4335 47.5973 26.7938 51.196 28.208C51.5834 28.3592 51.9816 28.4844 52.3754 28.6205C52.8775 28.7954 53.3838 28.9616 53.8816 29.1516C54.1607 29.2596 54.4291 29.4021 54.6931 29.5424C54.9614 29.685 55.1864 29.8836 55.392 30.1082C55.9633 30.7279 56.0888 31.4447 55.8465 32.235C55.7166 32.6604 55.4894 33.0361 55.2232 33.3902C54.7169 34.0617 54.1088 34.6274 53.4293 35.1175C52.5399 35.7567 51.5769 36.2425 50.5187 36.5599C48.7074 37.104 46.8659 37.402 44.9745 37.3826C44.6521 37.3782 44.3275 37.3502 44.0137 37.4732C43.9315 37.5056 43.832 37.4948 43.7389 37.497C43.5766 37.5013 43.4143 37.4991 43.252 37.4991C32.6636 37.4991 22.0751 37.4991 11.4845 37.4991C11.2768 37.4991 11.0669 37.5035 10.8591 37.4927C10.7466 37.4862 10.6298 37.4581 10.5216 37.4214C10.2619 37.3307 10.0844 37.0457 10.1017 36.765C10.1212 36.467 10.3766 36.1712 10.6557 36.1324C10.7466 36.1194 10.8397 36.1129 10.9327 36.1108C11.1643 36.1065 11.3958 36.1086 11.6274 36.1086C18.6474 36.1086 25.6695 36.1086 32.6895 36.1086C32.9406 36.1021 33.1959 36.0957 33.4469 36.0935Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M13.7199 31.9694C16.1068 31.9694 18.4915 31.9694 20.8784 31.9716C21.11 31.9716 21.3437 31.9672 21.5709 32.0039C22.0405 32.0817 22.272 32.615 22.0318 33.0296C21.9474 33.1764 21.8241 33.28 21.6596 33.3211C21.5493 33.3491 21.4324 33.3664 21.3177 33.3729C21.1554 33.3815 20.9931 33.3772 20.8308 33.3772C16.0592 33.3772 11.2876 33.3772 6.51382 33.375C6.26063 33.375 6.00312 33.3707 5.75209 33.3405C5.53353 33.3146 5.37772 33.185 5.26952 32.9864C5.0423 32.5675 5.33877 32.099 5.73045 32.0061C5.81918 31.9845 5.91439 31.9759 6.00528 31.9737C6.19138 31.9694 6.37532 31.9716 6.56143 31.9716C8.94615 31.9694 11.333 31.9694 13.7199 31.9694Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M36.1108 13.9141C35.9399 13.8989 35.7819 13.8752 35.6217 13.873C34.9747 13.8687 34.3277 13.8709 33.6785 13.8709C33.4945 13.8709 33.3106 13.8666 33.131 13.8018C32.7804 13.6765 32.5965 13.344 32.6895 12.9726C32.7523 12.7287 32.9146 12.5602 33.1548 12.5106C33.356 12.4674 33.5681 12.4695 33.7759 12.4652C34.1913 12.4544 34.6068 12.4523 35.0223 12.4436C35.1132 12.4415 35.1781 12.3465 35.163 12.2471C35.1586 12.2234 35.1565 12.2018 35.15 12.1802C35.1392 12.1349 35.1283 12.0917 35.1154 12.0463C35.0072 11.6577 35.414 11.1654 35.9139 11.2582C36.1086 11.2949 36.258 11.3964 36.364 11.5562C36.5306 11.8067 36.6799 12.0658 36.8422 12.3184C36.8942 12.4005 36.9786 12.4415 37.0738 12.4523C37.1647 12.4609 37.2577 12.4609 37.3508 12.4652C37.5131 12.4717 37.6754 12.4674 37.8355 12.4868C38.1125 12.5192 38.3051 12.6768 38.3938 12.9403C38.489 13.221 38.3982 13.5103 38.1796 13.6917C38.1623 13.7068 38.1428 13.7197 38.1233 13.7327C38.013 13.8061 37.8333 13.8299 37.8312 13.9896C37.829 14.0933 37.9069 14.2034 37.9632 14.3027C38.3073 14.903 38.6557 15.4989 38.9846 16.0625C39.1988 16.1791 39.3871 16.1445 39.5689 16.1532C39.7766 16.1618 39.9865 16.1488 40.1899 16.1834C40.4583 16.2266 40.6574 16.3842 40.7418 16.6519C40.824 16.9154 40.7656 17.1529 40.573 17.3537C40.4734 17.4573 40.3544 17.5264 40.2116 17.5415C40.0514 17.5567 39.8891 17.5696 39.7268 17.5696C38.502 17.5718 37.275 17.5718 36.0502 17.5696C35.8879 17.5696 35.7256 17.561 35.5676 17.5394C35.295 17.5027 35.0699 17.263 35.0245 16.9823C34.9769 16.6908 35.1067 16.4123 35.3512 16.2741C35.4962 16.192 35.652 16.1575 35.8165 16.1575C36.1411 16.1575 36.4635 16.1575 36.7881 16.1532C36.9266 16.151 37.063 16.138 37.2015 16.1273C37.2556 16.1229 37.3075 16.0215 37.2837 15.9653C37.275 15.9437 37.2729 15.92 37.2621 15.9005C36.8834 15.2398 36.5133 14.5748 36.1108 13.9141Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M6.0053 26.6642C7.57853 26.6642 9.14959 26.6642 10.7228 26.6642C10.9306 26.6642 11.1405 26.6642 11.346 26.688C11.6663 26.7247 11.9087 27.0291 11.9152 27.3724C11.9195 27.6639 11.6836 27.9619 11.3915 28.0267C11.3244 28.0418 11.2552 28.0504 11.1859 28.0526C11.002 28.0569 10.8159 28.0569 10.6319 28.0569C7.53309 28.0569 4.43641 28.0569 1.33756 28.0569C1.12982 28.0569 0.922075 28.0548 0.714331 28.0483C0.545539 28.044 0.402715 27.9727 0.27504 27.8669C0.0651319 27.692 -0.0127719 27.4329 0.0672959 27.1824C0.151692 26.9212 0.322648 26.7376 0.599639 26.6944C0.803055 26.6621 1.01513 26.6664 1.22287 26.6664C2.81557 26.6621 4.41044 26.6621 6.0053 26.6642Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M41.1031 19.69C41.3412 19.7806 41.5511 19.7418 41.7567 19.7504C41.919 19.7591 42.0813 19.7526 42.2414 19.7742C42.5357 19.813 42.7976 20.0916 42.83 20.3787C42.8603 20.6486 42.7023 20.9401 42.4535 21.0675C42.4124 21.0891 42.3669 21.0999 42.3236 21.1172C41.9969 21.2489 41.9861 21.2683 42.1397 21.5382C42.2977 21.8211 42.4665 22.0975 42.6244 22.3803C42.6915 22.5013 42.7586 22.6243 42.8062 22.7539C42.9079 23.0281 42.7802 23.3757 42.5249 23.5442C42.2782 23.7083 41.9017 23.6759 41.6939 23.4556C41.5836 23.339 41.4905 23.203 41.4104 23.067C41.1269 22.5898 40.8521 22.1083 40.573 21.6289C40.5037 21.5102 40.4301 21.3893 40.3436 21.2813C40.3046 21.2316 40.2332 21.1906 40.1705 21.1798C40.0341 21.1604 39.8935 21.1582 39.755 21.1582C39.1988 21.1561 38.6448 21.1604 38.0887 21.1561C37.9264 21.1539 37.7641 21.1496 37.604 21.1237C37.2794 21.0719 37.024 20.7501 37.0413 20.4306C37.0565 20.1369 37.2967 19.8411 37.5867 19.7871C37.7446 19.7569 37.9091 19.7569 38.0692 19.7526C38.4609 19.7418 38.8548 19.7353 39.2464 19.7267C39.2962 19.7245 39.3698 19.6209 39.3546 19.5777C39.3308 19.5129 39.3049 19.4503 39.2767 19.3855C39.2313 19.2797 39.1794 19.1761 39.1426 19.0659C39.0625 18.8176 39.1837 18.5089 39.4196 18.3361C39.6316 18.1828 39.9151 18.172 40.138 18.3059C40.2808 18.3923 40.3869 18.511 40.4691 18.6535C40.5989 18.8716 40.7244 19.094 40.8565 19.3099C40.943 19.4481 41.0317 19.582 41.1031 19.69Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M17.0374 10.3298C17.0352 11.662 16.5094 12.7438 15.4815 13.5902C15.3127 13.7305 15.1244 13.7975 14.908 13.791C14.5985 13.7845 14.3821 13.6226 14.2523 13.3548C14.1657 13.1778 14.1852 12.9942 14.3021 12.8301C14.341 12.774 14.3886 12.72 14.4362 12.6725C14.5012 12.6077 14.5704 12.5451 14.6397 12.4825C15.5918 11.6102 15.8039 10.5263 15.5291 9.3171C15.3538 8.53978 14.9729 7.85315 14.5185 7.20538C14.4124 7.05424 14.2913 6.91173 14.1896 6.75843C13.9039 6.32658 14.1549 5.74144 14.6808 5.62484C14.763 5.60541 14.8626 5.63347 14.9491 5.65939C15.1093 5.70905 15.2196 5.83212 15.3213 5.96168C16.0463 6.87934 16.5916 7.88769 16.8772 9.02776C16.9833 9.46392 17.0374 9.89793 17.0374 10.3298Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M3.57083 37.4927C2.85455 37.4927 2.13827 37.4948 1.42199 37.4927C1.25969 37.4927 1.09739 37.4927 0.939414 37.4689C0.495795 37.3998 0.324839 37.0479 0.344315 36.7413C0.365955 36.4152 0.65593 36.1432 0.984858 36.1151C1.07575 36.1065 1.1688 36.1043 1.26185 36.1043C2.83291 36.1043 4.40397 36.1043 5.97503 36.1043C6.08973 36.1043 6.20658 36.1043 6.32127 36.1216C6.59394 36.1648 6.7822 36.3224 6.87526 36.5837C6.97047 36.8514 6.90555 37.0932 6.70646 37.2811C6.61125 37.3718 6.47275 37.4322 6.34291 37.4624C6.18711 37.497 6.02264 37.4927 5.86034 37.4927C5.09645 37.4948 4.33472 37.4927 3.57083 37.4927Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 38,\n  svg: Shoe,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fitness-apps-ranked/swimmer.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Swimmer', 'sticker name', 'web-stories');\n\nfunction Swimmer({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M47.5768 15.2342C45.7882 15.2254 44.2614 14.7517 42.8859 13.7801C42.6372 13.6053 42.3972 13.4194 42.1485 13.2467C41.3829 12.7089 40.5848 12.2308 39.7414 11.8347C38.7531 11.3677 37.7604 10.9117 36.772 10.4492C35.4204 9.81838 34.1314 9.07251 32.9506 8.14515C32.8035 8.03007 32.6457 7.93047 32.4921 7.82645C32.4229 7.77997 32.291 7.81981 32.2456 7.89063C32.2196 7.93047 32.1872 7.96588 32.1699 8.00793C31.7763 8.91094 31.1621 9.64796 30.5068 10.3562C30.3792 10.4934 30.2516 10.6306 30.1261 10.7679C30.085 10.8121 30.1045 10.9162 30.1586 10.9538C30.2559 11.018 30.3511 11.0866 30.4505 11.1441C33.2966 12.7797 36.1427 14.4153 38.991 16.0465C39.7025 16.4537 40.3729 16.9207 40.9612 17.4962C41.4629 17.9875 42.036 18.2155 42.7194 18.1889C43.1109 18.1734 43.5045 18.2 43.8916 18.0893C44.1879 18.0052 44.456 17.8813 44.6918 17.6799C44.921 17.4807 45.1481 17.2793 45.3817 17.0845C46.2511 16.3586 47.1962 15.7743 48.2688 15.4179C48.6192 15.3006 48.976 15.2099 49.348 15.17C50.4229 15.0572 51.4739 15.1612 52.512 15.4533C53.2495 15.6614 53.9697 15.9159 54.6552 16.2678C54.7785 16.332 54.9018 16.4006 55.0142 16.4825C55.2002 16.6175 55.2759 16.892 55.1981 17.1221C55.0488 17.5559 54.6423 17.7662 54.2638 17.6223C54.0908 17.5559 53.9221 17.4785 53.7512 17.4077C52.9986 17.0934 52.2309 16.8366 51.4242 16.7149C49.9254 16.4892 48.5197 16.768 47.2091 17.536C46.5019 17.9499 45.8596 18.4523 45.3189 19.0853C45.1048 19.3354 44.8821 19.5744 44.6528 19.809C44.3371 20.1344 43.9543 20.3491 43.5347 20.504C43.1952 20.6302 42.8535 20.6457 42.514 20.5306C42.2739 20.4487 42.0382 20.3424 41.8132 20.2229C41.2315 19.9153 40.7362 19.4881 40.2864 19.0034C40.0139 18.7113 39.7436 18.4191 39.4624 18.138C38.6947 17.37 37.7712 16.9097 36.7201 16.7061C36.0973 16.5865 35.4788 16.5821 34.8602 16.7304C34.1552 16.9008 33.4913 17.1664 32.8836 17.5714C32.1807 18.0384 31.5362 18.574 30.948 19.1827C30.7036 19.435 30.457 19.6851 30.2083 19.933C29.9553 20.1831 29.6655 20.3756 29.3368 20.5018C28.861 20.6855 28.3895 20.7032 27.9267 20.4553C27.784 20.3779 27.6347 20.307 27.5028 20.2163C26.8886 19.7913 26.2896 19.3465 25.764 18.8064C25.4699 18.5054 25.1671 18.2111 24.8579 17.9256C24.6524 17.7352 24.4383 17.5515 24.2091 17.3899C22.866 16.4382 21.43 16.3077 19.9183 16.9052C19.4382 17.0934 19.0013 17.3612 18.5861 17.6644C17.6799 18.3239 16.7954 19.0123 16.0428 19.8599C15.9022 20.0171 15.7487 20.1632 15.5886 20.2982C15.2902 20.5483 14.9398 20.6523 14.557 20.6523C14.1029 20.6523 13.6855 20.5328 13.3351 20.2251C13.1059 20.0237 12.8853 19.8157 12.6647 19.6076C11.5942 18.6095 10.4198 17.7773 9.06383 17.235C8.30257 16.9296 7.50886 16.7747 6.69137 16.7547C5.65113 16.7282 4.6736 16.9938 3.73283 17.4187C3.15972 17.6777 2.62338 18.0052 2.11299 18.3793C1.96376 18.4899 1.81237 18.6006 1.65234 18.6936C1.42525 18.8264 1.13978 18.7577 0.964604 18.5431C0.689944 18.2044 0.709409 17.7441 1.01651 17.4541C1.11815 17.359 1.23278 17.2771 1.34524 17.193C1.49446 17.0801 1.65234 16.9805 1.79724 16.861C1.87077 16.8012 1.90321 16.7038 1.87077 16.6042C1.80589 16.4006 1.73452 16.2014 1.66964 16C1.46418 15.3405 1.33226 14.6676 1.34091 13.9749C1.36903 11.7683 2.39413 10.1946 4.27999 9.18981C5.05423 8.77815 5.88902 8.61215 6.76274 8.62101C7.72081 8.63207 8.64643 8.81799 9.55043 9.14334C10.8286 9.60591 11.9878 10.2854 13.0864 11.0866C13.5579 11.4318 14.0315 11.7705 14.5116 12.1025C14.8576 12.3437 15.2361 12.5208 15.6297 12.6668C15.8936 12.7664 16.1661 12.8151 16.445 12.8262C17.0571 12.8505 17.5848 12.6469 18.0065 12.1888C18.1492 12.0339 18.279 11.8656 18.3958 11.6886C18.6164 11.3522 18.7786 10.9848 18.9148 10.6063C18.9948 10.3828 19.0511 10.1504 19.0359 9.91134C19.0035 9.42442 19.1354 8.96849 19.2911 8.52362C19.5615 7.75783 19.9616 7.0673 20.5022 6.46529C20.9521 5.96509 21.5144 5.63753 22.1264 5.40292C22.5589 5.23693 23.0023 5.09528 23.45 4.97576C24.1052 4.80092 24.7173 4.53533 25.3099 4.20334C26.203 3.70314 27.0919 3.19188 27.9527 2.63192C28.675 2.1605 29.3952 1.68464 30.124 1.22871C30.5587 0.956482 31.0063 0.706383 31.4562 0.467351C31.826 0.270371 32.2261 0.157494 32.637 0.0645373C33.3593 -0.0970308 34.0146 0.053471 34.6396 0.418659C35.2257 0.761715 35.7578 1.18223 36.2465 1.65587C36.6661 2.06311 37.077 2.48142 37.4814 2.90415C37.9356 3.37779 38.3811 3.86028 38.8309 4.33835C38.9434 4.45786 39.0537 4.5818 39.1748 4.69025C40.0355 5.45162 40.7968 6.31257 41.5818 7.1514C42.302 7.92162 43.0243 8.68962 43.8289 9.37352C44.2052 9.69222 44.6053 9.96888 45.014 10.2411C45.7212 10.7125 46.5041 10.8697 47.3324 10.8453C48.0742 10.8232 48.8073 10.7081 49.5383 10.5797C50.0877 10.4846 50.6413 10.4292 51.1949 10.416C51.8481 10.4005 52.4882 10.5067 53.07 10.8431C53.6085 11.153 53.7145 11.4031 53.5696 12.0095C53.4549 12.4809 53.2192 12.8837 52.8991 13.2379C52.5985 13.5721 52.2438 13.8377 51.8589 14.059C51.3333 14.3622 50.7819 14.6035 50.2001 14.7739C49.6659 14.931 49.1253 15.0638 48.5759 15.1457C48.1996 15.2032 47.8277 15.2143 47.5768 15.2342ZM11.9618 12.2862C11.8018 12.4013 11.7693 12.596 11.6915 12.762C11.3282 13.5411 10.8524 14.2361 10.2447 14.8336C10.1106 14.9642 9.97215 15.0904 9.83374 15.2143C9.76454 15.2763 9.69101 15.3338 9.6218 15.398C9.50934 15.4976 9.51583 15.6083 9.64126 15.6769C10.396 16.0974 11.0881 16.6153 11.7888 17.1177C12.2257 17.432 12.6755 17.7242 13.1599 17.9543C13.4108 18.0738 13.6682 18.1912 13.9342 18.262C14.7322 18.4744 15.4978 18.408 16.1855 17.8946C16.4104 17.7264 16.631 17.5537 16.843 17.3722C17.109 17.1443 17.3663 16.903 17.6237 16.6662C18.4174 15.9358 19.3495 15.4799 20.3854 15.2475C21.6809 14.9554 22.9179 15.1125 24.0771 15.7942C24.4188 15.9956 24.7476 16.2147 25.0741 16.4405C25.5737 16.7857 26.0625 17.1443 26.5599 17.4918C26.7502 17.6246 26.9492 17.7507 27.1503 17.8658C27.7602 18.2155 28.4133 18.3262 29.0967 18.1712C29.3433 18.1159 29.5855 18.0296 29.8234 17.9388C30.1953 17.7994 30.5284 17.5825 30.855 17.359C31.4129 16.9783 31.9709 16.5954 32.5289 16.2103C33.0501 15.8517 33.6102 15.5706 34.2028 15.356C34.2677 15.3316 34.3369 15.3161 34.3953 15.2807C34.4255 15.2608 34.4407 15.2077 34.4537 15.1678C34.458 15.1523 34.4407 15.1214 34.4255 15.1103C34.2309 14.9841 34.0384 14.8558 33.8373 14.7385C32.1634 13.7735 30.4873 12.8107 28.8134 11.8457C28.6317 11.7417 28.4479 11.6377 28.2835 11.5093C27.9743 11.2659 27.9462 10.7922 28.21 10.5001C28.2576 10.4492 28.3073 10.3983 28.3614 10.354C28.9194 9.91355 29.3497 9.35802 29.7304 8.75823C29.9834 8.36205 30.2408 7.96809 30.5024 7.57635C30.7122 7.26206 30.948 6.96991 31.2161 6.70654C31.3827 6.54054 31.5665 6.39668 31.7741 6.28823C32.0531 6.14215 32.3386 6.10231 32.6478 6.19306C32.9419 6.27938 33.2166 6.39889 33.4588 6.58702C33.8459 6.88581 34.2352 7.18681 34.6072 7.50552C35.0008 7.84194 35.4117 8.14073 35.8616 8.39083C36.5363 8.76266 37.237 9.06808 37.9442 9.36466C38.5865 9.63468 39.2267 9.91134 39.8647 10.1902C40.5697 10.4979 41.2358 10.8785 41.8781 11.3035C42.5983 11.7793 43.3163 12.2574 44.0689 12.6757C44.9513 13.1648 45.8726 13.5367 46.8696 13.6894C47.8969 13.8465 48.9047 13.7491 49.8735 13.3618C50.4553 13.1294 51.0198 12.8505 51.5583 12.5252C51.7356 12.4167 51.9043 12.2884 52.0708 12.1622C52.0989 12.1401 52.1054 12.0803 52.1097 12.0361C52.1141 11.9785 52.0795 11.9453 52.0276 11.9431C51.7724 11.9409 51.5172 11.921 51.2663 11.9409C50.5743 11.9962 49.8844 12.0715 49.1923 12.1357C48.338 12.2131 47.4816 12.2508 46.6252 12.2198C45.8401 12.191 45.1221 11.9453 44.4842 11.4805C44.1641 11.2481 43.857 10.9936 43.565 10.7236C41.8132 9.10128 40.0615 7.47896 38.3184 5.84558C37.1916 4.78985 36.0324 3.76954 34.9705 2.64077C34.7954 2.45486 34.5942 2.28887 34.3909 2.13172C33.7724 1.65366 33.0955 1.543 32.3559 1.79088C31.9147 1.93917 31.4973 2.145 31.0907 2.37076C30.0915 2.92407 29.1356 3.55042 28.1776 4.17014C27.3558 4.70132 26.5188 5.21037 25.6451 5.64638C25.165 5.88542 24.6784 6.10231 24.1658 6.25724C23.7657 6.37897 23.3721 6.51619 22.9763 6.6512C22.6454 6.76408 22.3254 6.9013 22.0269 7.085C21.1337 7.62946 20.6125 8.43067 20.4655 9.47975C20.4222 9.78518 20.4114 10.0928 20.3898 10.4005C20.3703 10.6594 20.3725 10.9228 20.3379 11.1817C20.1324 12.7443 19.0619 14.1298 17.2604 14.36C16.2893 14.4839 15.3702 14.3312 14.4986 13.8775C13.7525 13.4902 13.0432 13.0453 12.3771 12.5296C12.2538 12.4322 12.1435 12.2994 11.9618 12.2862ZM7.2926 10.0397C6.70219 10.0176 6.19828 10.0751 5.70736 10.23C4.24755 10.697 3.28516 11.662 2.91318 13.2002C2.7553 13.8532 2.77693 14.5171 2.90885 15.1723C2.96076 15.4246 3.05159 15.6702 3.14242 15.9137C3.15972 15.9602 3.26353 16.0155 3.30895 16C3.48412 15.9469 3.65281 15.8672 3.82583 15.7964C4.6909 15.4445 5.57759 15.1988 6.51403 15.159C6.81465 15.1457 7.11526 15.1368 7.41371 15.128C7.55644 15.1236 7.6862 15.0837 7.80083 14.9974C8.32636 14.6101 8.8454 14.2139 9.30821 13.7469C9.58936 13.4636 9.84672 13.1604 10.0716 12.8284C10.2836 12.5141 10.4501 12.1777 10.5539 11.8125C10.5928 11.6775 10.6037 11.5359 10.6188 11.3942C10.6296 11.2946 10.5842 11.2083 10.5128 11.1441C10.4436 11.0822 10.3679 11.0268 10.2901 10.9759C9.35363 10.3628 8.33285 10.0286 7.2926 10.0397Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M45.8507 29.9813C45.5176 29.9835 45.2127 29.8795 44.9185 29.729C44.419 29.4722 43.9562 29.158 43.5409 28.7773C43.1279 28.3988 42.7364 27.9938 42.3363 27.5998C41.986 27.2568 41.6334 26.9115 41.2831 26.5684C41.2009 26.4866 41.1014 26.4135 41.0452 26.3139C40.9479 26.1413 40.7986 26.0284 40.6429 25.931C39.4664 25.1984 38.1948 24.8111 36.8107 24.8996C36.0429 24.9483 35.299 25.1232 34.5939 25.4441C34.2976 25.5791 34.0078 25.7274 33.7202 25.8801C33.5169 25.9908 33.3223 26.1103 33.1839 26.3161C33.1082 26.4268 32.9806 26.5043 32.8681 26.5862C32.1998 27.062 31.5965 27.6131 31.0493 28.2284C30.8006 28.5095 30.5497 28.7906 30.2816 29.0495C30.0631 29.2598 29.8274 29.4567 29.5765 29.6227C28.8261 30.1141 28.0518 30.1141 27.2711 29.6891C27.0051 29.5431 26.765 29.3549 26.5509 29.1358C26.3217 28.9012 26.0968 28.6622 25.8827 28.4143C25.2793 27.7193 24.611 27.1041 23.8649 26.5751C23.733 26.4821 23.601 26.3936 23.5102 26.2431C23.4518 26.1479 23.348 26.0749 23.2507 26.0129C22.1218 25.3091 20.9063 24.8797 19.5741 24.8864C18.3198 24.893 17.1584 25.2648 16.0966 25.9509C15.9992 26.0129 15.8889 26.0771 15.8262 26.1701C15.5191 26.626 15.0477 26.9071 14.6843 27.3055C14.321 27.7038 13.9382 28.0845 13.5489 28.4541C13.125 28.857 12.6838 29.2398 12.1864 29.5519C11.9485 29.7024 11.702 29.8286 11.4295 29.8972C10.679 30.0897 10.0065 29.9348 9.42037 29.4213C9.22789 29.2531 9.06353 29.0495 8.88619 28.8636C8.69155 28.66 8.50556 28.4475 8.3001 28.2594C7.65779 27.6795 7.02845 27.0841 6.3299 26.5707C6.23691 26.502 6.12661 26.4334 6.07255 26.3383C5.94927 26.1192 5.75031 26.0019 5.55134 25.8845C4.62139 25.329 3.62872 24.9572 2.55171 24.8332C2.39167 24.8155 2.23163 24.7846 2.07592 24.7425C1.77531 24.6606 1.60878 24.4504 1.56553 24.1383C1.49416 23.6337 1.79261 23.2972 2.2857 23.3504C3.32595 23.4632 4.33592 23.6978 5.30696 24.1139C6.36883 24.5677 7.2923 25.2272 8.15088 25.9974C8.22008 26.0594 8.29578 26.1236 8.34119 26.201C8.58774 26.6127 8.97918 26.8827 9.29926 27.2214C9.36198 27.2878 9.442 27.3453 9.52634 27.3829C10.1795 27.6618 10.8542 27.8012 11.5614 27.6884C11.9572 27.6264 12.3162 27.4604 12.6255 27.1992C12.7855 27.0642 12.9347 26.9137 13.0775 26.761C13.4105 26.4025 13.7436 26.0461 14.1415 25.754C14.481 25.5061 14.7903 25.2184 15.1212 24.9594C16.4166 23.9479 17.8808 23.4411 19.5071 23.4145C20.1105 23.4057 20.7095 23.4411 21.3 23.5805C21.9574 23.7377 22.5889 23.9612 23.1663 24.3264C23.4626 24.5123 23.7524 24.7071 24.0336 24.9174C24.5007 25.267 24.9592 25.63 25.4199 25.9886C25.4934 26.0461 25.5777 26.0948 25.634 26.1678C26.0362 26.7035 26.6353 26.9115 27.2127 27.1461C27.7404 27.3608 28.2984 27.3674 28.8563 27.3099C29.2283 27.2723 29.5873 27.166 29.9204 27C30.3551 26.7876 30.8136 26.6061 31.1099 26.1767C31.1618 26.1014 31.2483 26.0528 31.3218 25.9974C31.8019 25.6278 32.2799 25.2516 32.7665 24.8886C33.4823 24.3552 34.2436 23.9103 35.1086 23.6801C36.7999 23.2309 38.4543 23.3238 40.072 24.0188C40.6732 24.2777 41.2312 24.6097 41.7394 25.028C42.172 25.3843 42.6196 25.723 43.0435 26.0882C43.2706 26.2851 43.4652 26.522 43.6728 26.7411C43.7853 26.8606 43.8913 26.9868 44.0146 27.0952C44.4687 27.4958 44.9899 27.7105 45.5976 27.726C46.1405 27.7393 46.6552 27.6197 47.1548 27.4205C47.2802 27.3696 47.41 27.2944 47.5029 27.1948C47.823 26.8562 48.2145 26.5861 48.4589 26.1723C48.5043 26.0948 48.5843 26.035 48.6535 25.9731C49.5142 25.2051 50.4399 24.5522 51.5039 24.1007C52.4555 23.6978 53.4438 23.4765 54.4581 23.3526C54.4819 23.3504 54.5035 23.3482 54.5273 23.3482C54.975 23.3238 55.2713 23.6514 55.2172 24.1117C55.1805 24.4393 54.9728 24.685 54.6592 24.7602C54.5014 24.7978 54.3413 24.82 54.1791 24.8399C53.0805 24.9727 52.0684 25.3578 51.1233 25.9377C50.9654 26.035 50.8162 26.1391 50.708 26.3051C50.6345 26.4179 50.5134 26.5065 50.4031 26.5884C49.7456 27.0775 49.1379 27.6264 48.541 28.1863C48.3031 28.4099 48.0825 28.6555 47.8576 28.8924C47.7127 29.0451 47.5722 29.2044 47.4251 29.3527C46.9904 29.7932 46.4519 29.9702 45.8507 29.9813Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 30,\n  svg: Swimmer,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/arrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\n\nfunction Arrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 19 10\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M17.9472 5.38801C18.1615 5.17372 18.1615 4.82628 17.9472 4.61199L14.4552 1.11992C14.2409 0.905633 13.8934 0.905633 13.6791 1.11992C13.4649 1.33421 13.4649 1.68165 13.6791 1.89594L16.7832 5L13.6791 8.10406C13.4649 8.31835 13.4649 8.66579 13.6791 8.88008C13.8934 9.09437 14.2409 9.09437 14.4552 8.88008L17.9472 5.38801ZM0 5.54873H17.5592V4.45127H0V5.54873Z\"\n        fill=\"#3A566E\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 19 / 10,\n  svg: Arrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/artichoke.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Artichoke', 'sticker name', 'web-stories');\n\nfunction Artichoke({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 105 111\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M99.6984 42.801C99.6823 42.6506 99.6068 42.4629 99.6586 42.3468C100.628 40.3691 101.005 38.2546 101.121 36.0791C101.144 35.6281 101.112 35.1853 101.146 34.74C101.159 34.5471 101.279 34.3662 101.346 34.1794C101.407 34.3528 101.511 34.5265 101.527 34.7053C101.742 37.0842 101.319 39.3743 100.555 41.6199C100.404 42.056 100.127 42.4488 99.911 42.859C99.8373 42.8359 99.7693 42.8156 99.6984 42.801Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M98.8814 29.9988C98.4018 30.8867 97.9653 31.6897 97.5259 32.4984C97.4607 32.4725 97.3956 32.4466 97.3276 32.4263C97.4543 32.1491 97.5894 31.8691 97.7161 31.5919C97.8599 31.2949 97.9697 30.9807 98.1559 30.7123C98.3221 30.4693 98.107 29.9263 98.8814 29.9988Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M69.5 33.5735C69.6022 33.5684 69.7074 33.5577 69.8153 33.5555C69.7718 33.6971 69.7622 33.8701 69.6764 33.9689C69.0787 34.6407 68.4696 35.3069 67.8464 35.9587C67.4863 36.3311 67.0979 36.6751 66.7151 37.036C66.6728 36.9932 66.6304 36.9504 66.5852 36.9133C67.2576 36.1085 67.9328 35.3123 68.6052 34.5075C68.9026 34.1886 69.1998 33.8839 69.5 33.5735Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M46.2166 84.4565C46.117 84.4843 46.0118 84.495 45.9207 84.5342C45.4676 84.7671 45.2048 83.6589 44.5781 84.4016C44.3635 84.6558 43.5864 84.4754 43.0783 84.4242C41.7868 84.2891 40.564 84.5375 39.3153 84.8226C37.2703 85.2876 35.593 86.43 33.8961 87.5411C31.9225 88.8322 29.9799 90.1746 28.0345 91.5085C27.5438 91.8433 27.1096 92.2494 26.6303 92.59C26.4876 92.6885 26.2717 92.693 26.0925 92.7373C26.1362 92.5673 26.1263 92.3346 26.2349 92.233C27.1549 91.3615 28.0553 90.4587 29.0485 89.6812C30.4443 88.5882 31.8796 87.5295 33.3711 86.5705C35.7722 85.0264 38.3167 83.7329 41.2318 83.5737C42.5871 83.4992 43.9576 83.7029 45.3115 83.8412C45.6436 83.8743 45.9459 84.1342 46.263 84.295C46.2428 84.3488 46.2282 84.4054 46.2166 84.4565Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M78.176 84.7925C78.0841 84.9594 78.0288 85.1663 77.8946 85.2762C76.3359 86.5216 74.6589 87.6074 72.752 88.2066C70.5548 88.9006 68.3186 89.461 65.9754 89.4333C65.1176 89.4255 64.256 89.5795 63.3983 89.5576C62.2623 89.5227 61.115 89.482 60 89.2798C58.1274 88.9427 56.2697 88.4921 54.4177 88.0445C53.5356 87.8322 52.6854 87.5152 51.8179 87.2463C51.8184 87.1753 51.816 87.0959 51.8165 87.0249C52.0863 87.0265 52.3735 86.9799 52.623 87.0494C53.3518 87.2409 54.0602 87.5288 54.7948 87.6947C57.5461 88.3207 60.2853 89.0686 63.1194 89.1814C64.3831 89.2312 65.6597 89.0455 66.9298 88.9847C68.9386 88.8856 70.8566 88.3347 72.7464 87.7411C74.4 87.2199 75.9138 86.3432 77.2391 85.1788C77.4676 84.9814 77.7327 84.8241 77.9781 84.6495C78.0488 84.7067 78.111 84.7524 78.176 84.7925Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M11.0876 88.131C11.6622 87.5044 12.2369 86.8779 12.806 86.2485C13.7952 85.1703 14.7845 84.0922 15.771 83.0056C16.6917 81.9923 17.604 80.9676 18.5247 79.9544C20.2689 78.0351 21.852 75.9844 22.6826 73.5094C23.1253 72.1898 23.3075 70.7524 23.4043 69.3571C23.4852 68.2312 23.3136 67.0698 23.1447 65.9453C23.0411 65.2524 22.7215 64.5923 22.4623 63.8134C22.652 63.9167 22.8504 63.9604 22.9235 64.0828C23.3704 64.8145 23.5584 65.6214 23.6894 66.4704C23.9596 68.2084 23.9232 69.9332 23.6795 71.6596C23.4564 73.2756 22.7232 74.7183 21.9222 76.1124C20.4438 78.6716 18.2958 80.6851 16.3342 82.8499C14.7015 84.6478 13.0096 86.3802 11.3374 88.1438C11.303 88.1833 11.2461 88.2114 11.1976 88.2366C11.1637 88.2052 11.1271 88.1653 11.0876 88.131Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M6.2912 91.2343C6.70057 90.7089 7.0845 90.1635 7.52207 89.6667C8.30567 88.7831 9.15424 87.9539 9.91807 87.0532C10.3329 86.5591 10.598 85.9393 10.9903 85.4195C11.4771 84.7697 12.012 84.1514 12.5413 83.5303C14.1462 81.6329 15.7144 79.6956 16.983 77.5494C17.4307 76.7945 17.7851 75.9851 18.1791 75.1958C18.2078 75.1392 18.2422 75.0855 18.2455 75.0231C18.258 74.8444 18.211 74.6427 18.2716 74.4813C18.3207 74.3568 18.4747 74.2498 18.6085 74.1825C18.7368 74.1123 18.893 74.099 19.1035 74.0492C18.932 75.1292 18.5511 76.0888 18.0228 77.0163C16.5241 79.6435 14.6465 81.9933 12.6898 84.2887C11.105 86.1464 9.47503 87.9671 7.8648 89.8048C7.40718 90.3271 6.96656 90.858 6.5146 91.3831C6.43822 91.3372 6.36471 91.2858 6.2912 91.2343Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.745 74.9437C27.202 75.9421 26.7128 76.9749 26.0934 77.9275C25.4281 78.9564 24.692 79.9566 23.8883 80.8798C22.8271 82.0994 21.6755 83.2447 20.5606 84.4157C20.1519 84.8418 19.76 85.2907 19.3372 85.7025C17.277 87.7391 15.2083 89.7644 13.1424 91.7982C13.0881 91.8489 13.0112 91.8882 12.8892 91.8762C13.1751 91.5657 13.4554 91.2524 13.7526 90.9477C14.6958 89.9743 15.6419 88.9952 16.5992 88.036C16.9765 87.658 17.3988 87.3313 17.7647 86.9475C19.6115 84.9805 21.4922 83.045 23.274 81.0238C24.8213 79.2679 26.1906 77.372 27.195 75.2413C27.2727 75.0743 27.4127 74.9389 27.5273 74.7836C27.5979 74.8407 27.6714 74.8922 27.745 74.9437Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M55.3473 86.1166C55.5491 86.0837 55.7656 85.9941 55.9557 86.0264C56.9007 86.1709 57.8365 86.4175 58.7876 86.4939C60.4712 86.6284 62.1668 86.6552 63.8564 86.7359C65.1825 86.8031 66.4983 86.6943 67.7675 86.327C68.5273 86.1071 69.2454 85.7452 69.9884 85.4742C70.145 85.4183 70.335 85.479 70.5167 85.4857C70.4136 85.6185 70.3387 85.794 70.2075 85.8699C68.4856 86.8618 66.6027 87.2596 64.6375 87.1887C62.4423 87.108 60.2475 86.9705 58.0613 86.8019C57.15 86.7314 56.2509 86.5105 55.3457 86.3578C55.3519 86.2755 55.3496 86.196 55.3473 86.1166Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.7664 79.3246C24.2572 85.5918 18.3792 90.4893 12.6537 95.5352C12.617 95.4952 12.5775 95.461 12.5408 95.421C15.3571 92.8354 18.1819 90.2612 20.9841 87.6613C23.7748 85.0698 26.3595 82.2814 28.7664 79.3246Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M50.6838 86.9216C49.9288 86.8237 49.1824 86.7087 48.4245 86.6305C46.8661 86.4598 45.3077 86.3033 43.752 86.1553C41.5774 85.9498 39.4795 86.2102 37.5187 87.2377C37.3934 87.3022 37.2427 87.3184 37.1033 87.3545C37.064 87.2776 37.0333 87.198 36.994 87.1211C37.4841 86.8714 37.9576 86.5562 38.4756 86.3918C40.1036 85.8789 41.7844 85.5566 43.4992 85.6998C45.4241 85.8641 47.3369 86.122 49.2527 86.3742C49.7466 86.4395 50.234 86.6154 50.7219 86.7346C50.7044 86.7969 50.6955 86.8564 50.6838 86.9216Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.7196 88.9058C35.4312 88.6545 36.1372 88.4003 36.846 88.1546C38.3291 87.6325 39.8066 87.1075 41.2868 86.591C41.9273 86.3677 42.5694 86.3373 43.1868 86.636C43.3369 86.705 43.4207 86.9183 43.5335 87.0608C43.3567 87.1705 43.1564 87.3963 43.0146 87.3671C41.3839 86.9605 39.9619 87.7128 38.485 88.1385C37.3098 88.4751 36.1514 88.8629 34.9818 89.2166C34.9078 89.236 34.7977 89.1304 34.7043 89.076C34.7188 89.0193 34.7192 88.9625 34.7196 88.9058Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M18.0525 93.8797C15.7349 96.1844 13.3973 98.5146 10.9597 100.944C11.0807 100.663 11.1134 100.445 11.2363 100.315C13.3518 98.0859 15.422 95.8195 17.8817 93.9496C17.9387 93.9074 18.024 93.8937 18.0525 93.8797Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M10.9459 104.167C13.1861 101.972 15.4293 99.7721 17.6723 97.5861C17.6895 97.5663 17.8083 97.6407 18.015 97.7384C15.6695 99.9579 13.3839 102.13 11.0956 104.293C11.0448 104.253 10.9968 104.207 10.9459 104.167Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M78.9813 84.7695C79.375 84.0088 80.332 83.9604 80.8025 83.1604C81.0215 84.004 80.6505 84.3139 78.9813 84.7695Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M7.5924 94.1124C7.18504 93.8917 7.18934 93.6591 7.46367 93.3714C7.66658 93.1542 7.83285 92.897 8.05553 92.6969C8.1697 92.5983 8.37405 92.6023 8.53897 92.5579C8.52936 92.7308 8.57625 92.9467 8.4875 93.0653C8.2183 93.4409 7.89835 93.7625 7.5924 94.1124Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.5366 82.5386C32.5927 81.6934 33.6573 80.8455 34.7134 80.0003C34.7755 80.0744 34.8289 80.1514 34.8909 80.2255C33.8038 81.0336 32.7195 81.8502 31.6324 82.6583C31.6014 82.6212 31.5732 82.5785 31.5366 82.5386Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M5.03984 93.3878C4.38504 94.1442 3.84458 94.7736 3.2584 95.451C3.41055 94.7314 4.42338 93.4666 5.03984 93.3878Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.6879 57.7481C37.7855 57.584 37.8549 57.3915 37.992 57.2618C39.6748 55.6598 41.3605 54.0522 43.0687 52.4702C45.0083 50.6711 46.9452 48.8635 48.9299 47.1157C50.0065 46.1742 51.1705 45.3268 52.3288 44.4908C54.5797 42.8637 56.8672 41.2908 59.121 39.6722C60.5246 38.6617 61.8944 37.6055 63.2867 36.575C63.3467 36.5271 63.4544 36.5533 63.7415 36.5209C63.4213 36.8567 63.2578 37.1083 63.0268 37.2687C60.9531 38.7152 58.8653 40.1332 56.7972 41.5826C55.5336 42.472 54.3008 43.4126 53.0568 44.3332C52.0753 45.0597 51.0853 45.7747 50.1292 46.5353C49.2187 47.2621 48.342 48.0345 47.4766 48.8126C45.8372 50.2872 44.1893 51.7503 42.5866 53.2648C41.1668 54.6015 39.7977 55.9925 38.4117 57.3607C38.2374 57.5356 38.0827 57.7418 37.9225 57.931C37.8433 57.8766 37.7642 57.8081 37.6879 57.7481Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M65.6795 37.8109C65.2388 38.356 64.8066 38.8982 64.3715 39.4462C63.9593 39.963 63.5359 40.4741 63.1406 41.0138C62.3558 42.0817 61.5851 43.164 60.8117 44.2377C59.8635 45.543 58.907 46.837 57.9758 48.151C56.4401 50.3183 54.7265 52.3314 52.7475 54.1104C52.162 54.6319 51.5455 55.1447 51.0646 55.7548C50.7611 56.1418 50.6161 56.6233 49.8648 56.4345C50.2276 56.0848 50.559 55.7689 50.8876 55.4445C52.0477 54.2964 53.2756 53.2111 54.3453 51.9888C55.6468 50.4925 56.8183 48.8877 58.0293 47.3171C58.7995 46.32 59.5272 45.2943 60.2776 44.28C61.6322 42.4549 62.9812 40.627 64.3386 38.8104C64.5935 38.4629 64.8682 38.1325 65.157 37.8164C65.237 37.7289 65.4018 37.7128 65.5242 37.6682C65.5836 37.7054 65.6287 37.7567 65.6795 37.8109Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M55.4471 57.279C56.0304 56.6354 56.6335 56.0091 57.1942 55.3399C58.3072 54.0043 59.4908 52.7117 60.4652 51.2845C61.9355 49.1197 63.2954 46.8777 64.5988 44.6069C65.2936 43.3938 65.7734 42.0574 66.3634 40.7841C66.5591 40.371 66.8057 39.9837 67.0241 39.5821C67.092 39.6165 67.1599 39.6509 67.2279 39.6854C66.6858 40.9902 66.2033 42.318 65.5934 43.5884C64.9662 44.8927 64.2512 46.1597 63.5108 47.4066C62.7733 48.6337 61.9849 49.835 61.157 51.0019C60.3175 52.1916 59.5259 53.4552 58.4805 54.4337C57.4694 55.3869 56.9238 56.8108 55.6445 57.4929C55.574 57.4216 55.512 57.3474 55.4471 57.279Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.4206 35.1405C59.1904 36.186 56.0978 37.4933 53.1954 39.2671C50.3329 41.0185 47.4114 42.6616 44.8811 44.8802C44.9119 44.9457 44.9456 45.0055 44.9765 45.0709C44.8147 45.0529 44.6587 45.0237 44.4997 45.0142C44.3691 45.005 44.2327 45.0212 44.074 44.955C49.7404 40.8391 55.5078 36.9309 62.2608 34.8104C62.3112 34.9213 62.3673 35.0352 62.4206 35.1405Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M59.4597 58.9143C59.9235 58.3098 60.3902 57.6997 60.8426 57.0895C61.2836 56.5019 61.7585 55.9315 62.1316 55.3095C63.1676 53.5649 64.1667 51.8088 65.1404 50.0326C65.4334 49.4981 65.5991 48.8919 65.8496 48.3287C65.913 48.1901 66.0953 48.0975 66.2238 47.9848C66.2313 48.138 66.287 48.3086 66.2436 48.4502C65.6139 50.5999 64.4945 52.5086 63.2422 54.3427C62.2764 55.7529 61.3474 57.1888 60.3732 58.5876C60.2099 58.825 59.9024 58.9537 59.6599 59.1368C59.5979 59.0626 59.5274 58.9913 59.4597 58.9143Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M61.3294 32.3253C61.2603 32.4753 61.1883 32.6309 61.1825 32.6423C58.5371 33.2939 56.1867 34.4438 53.8141 35.5113C51.433 36.5815 49.0434 37.6404 46.9738 39.3027C46.9344 39.2542 46.8921 39.1972 46.8527 39.1487C46.9955 39.0077 47.1188 38.8211 47.2899 38.7228C49.0313 37.7623 50.7474 36.7535 52.5365 35.8813C54.4596 34.9418 56.4387 34.1161 58.4066 33.2704C59.335 32.8728 60.2885 32.5378 61.2281 32.1743C61.2675 32.2228 61.2985 32.274 61.3294 32.3253Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M68.6557 41.3489C68.5526 41.93 68.4552 42.5139 68.3323 43.092C68.1714 43.843 68.002 44.5967 67.8156 45.3419C67.7777 45.4864 67.6519 45.6218 67.5405 45.729C67.4891 45.7741 67.3386 45.7761 67.2764 45.7303C67.2142 45.6846 67.1499 45.531 67.1814 45.4829C67.885 44.2386 68.0187 42.8405 68.2686 41.4801C68.2833 41.4092 68.4 41.3617 68.4686 41.2968C68.5395 41.3114 68.6018 41.3288 68.6557 41.3489Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M48.2769 57.8476C48.2594 58.3724 45.0561 61.5374 44.5427 61.4409C45.7569 60.2704 46.9712 59.0998 48.2769 57.8476Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M53.8511 59.0587C53.7839 59.8216 52.4297 61.0991 51.711 61.1404C52.491 60.3901 53.1711 59.7244 53.8511 59.0587Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M41.9997 47.394C42.0274 47.9558 40.801 49.3187 40.031 49.4334C40.7568 48.6774 41.3597 48.0512 41.9997 47.394Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M39.3466 43.8285C40.0089 43.2395 40.6628 42.6391 41.5415 42.3804C41.0366 43.2198 40.0847 43.3704 39.3353 43.8228L39.3466 43.8285Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M43.1362 41.3601C43.7122 40.955 44.2967 40.5471 44.8727 40.1419C44.9346 40.2302 44.9992 40.327 45.0611 40.4153C44.4683 40.7976 43.8698 41.1771 43.2769 41.5595C43.2234 41.4968 43.1812 41.4256 43.1362 41.3601Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M55.7526 79.1789C56.2513 78.9122 56.7471 78.6512 57.243 78.3759C59.6967 77.0365 62.1785 75.7541 64.5788 74.3378C66.1637 73.4048 67.642 72.2755 69.1596 71.223C70.2407 70.4687 71.3022 69.6832 72.389 68.9318C72.5744 68.8052 72.8329 68.7868 73.0577 68.7228C73.0857 68.7939 73.1108 68.8565 73.1388 68.9276C72.8419 69.1614 72.5536 69.4066 72.2483 69.629C71.1183 70.4653 70.0137 71.3357 68.8416 72.1008C66.9909 73.3046 65.1091 74.4713 63.2021 75.5755C61.3008 76.6826 59.3461 77.6985 57.4166 78.7628C57.1202 78.9257 56.8856 79.2053 56.5781 79.334C56.3502 79.432 56.0524 79.3736 55.7854 79.3805C55.7715 79.3237 55.7578 79.2527 55.7526 79.1789Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M51.0934 65.6681C51.7544 65.3343 52.4015 64.9719 53.0765 64.6807C54.4264 64.0982 55.7765 63.5015 57.1599 63.0214C58.4665 62.5663 59.8036 62.2193 61.1465 61.8751C63.3342 61.3116 65.5247 60.7709 67.7206 60.2613C68.9324 59.9789 70.1664 59.7646 71.3977 59.5418C71.6252 59.5006 71.8688 59.5956 72.1044 59.6225C72.1067 59.7162 72.1089 59.8098 72.1083 59.9091C71.0847 60.0735 70.0556 60.2208 69.0432 60.4193C67.1037 60.8026 65.1391 61.1092 63.2412 61.6488C60.4327 62.4528 57.5685 63.0861 54.9078 64.3421C53.8566 64.8412 52.6818 65.1069 51.7904 65.936C51.6847 66.0319 51.3843 65.9224 51.1743 65.9013C51.1492 65.8245 51.1241 65.7478 51.0934 65.6681Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.4015 80.0743C70.8668 79.7535 70.8671 79.7109 71.3578 79.3477C72.8728 78.2159 74.2043 76.9127 75.2311 75.2985C75.8505 74.3317 76.5407 73.4079 77.1885 72.4554C77.3576 72.2067 77.4843 71.9294 77.6307 71.6692C78.1041 71.8024 78.071 72.1059 77.8817 72.3942C77.1937 73.4258 76.4972 74.4603 75.7667 75.4633C75.2225 76.212 74.6329 76.9378 74.0406 77.6551C73.7602 77.9968 73.4345 78.3014 73.1061 78.5974C72.5606 79.0964 71.9811 79.5783 71.4015 80.0743Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.6534 63.2299C71.1922 63.3947 70.7479 63.5965 70.2756 63.7129C69.3795 63.9348 68.4586 64.0515 67.5736 64.3075C66.4838 64.6162 65.4276 65.0131 64.3517 65.3787C63.3156 65.7359 62.2711 66.0676 61.2517 66.4761C60.5284 66.7642 59.8612 67.1803 59.152 67.4969C58.9668 67.581 58.7116 67.5086 58.456 67.5071C58.796 66.7401 66.7343 64.0814 69.3736 63.5261C70.1159 63.3687 70.8231 62.9159 71.6123 62.9885C71.6288 63.068 71.6397 63.1447 71.6534 63.2299Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.7384 70.2617C76.2201 70.4347 76.0559 70.8139 75.8723 71.1051C75.4193 71.8005 74.9463 72.4929 74.4282 73.1482C73.4321 74.4079 72.3682 75.6048 71.0785 76.5734C70.9044 76.7058 70.6487 76.7327 70.3621 76.6941C72.5629 74.8994 74.4045 72.8586 75.7384 70.2617Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M79.4022 60.4576C79.5555 60.4642 79.7031 60.4678 80.0325 60.4782C78.4496 62.9064 76.1293 64.2919 74.1277 66.0168C74.0712 65.9598 74.0119 65.9083 73.9611 65.8541C74.167 65.6312 74.3616 65.3883 74.5901 65.191C75.7694 64.1593 76.9911 63.1704 78.1338 62.0988C78.6366 61.6279 78.9927 60.9972 79.4193 60.4378C79.4222 60.4322 79.4022 60.4576 79.4022 60.4576Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M46.6525 78.077C46.5097 78.2039 46.3864 78.3904 46.2184 78.4547C44.9258 78.9524 43.6276 79.433 42.3267 79.9051C42.1701 79.961 41.9717 79.9031 41.7956 79.8992C41.879 79.7351 41.9147 79.4828 42.0428 79.4268C42.789 79.1075 43.5519 78.8253 44.3149 78.5431C44.8245 78.3531 45.3398 78.1659 45.8663 77.9987C46.0883 77.9262 46.3269 77.919 46.56 77.8807C46.5852 77.9432 46.6217 78.0115 46.6525 78.077Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.2583 79.9602C64.4096 79.8305 64.5443 79.6355 64.7236 79.577C66.0215 79.1389 67.1423 78.4048 68.1816 77.5226C68.2987 77.4183 68.5314 77.4509 68.7105 77.4207C68.6471 77.5735 68.6343 77.7948 68.5203 77.8651C67.4737 78.5372 66.4131 79.1951 65.3468 79.8359C65.0618 80.0045 64.7289 80.0991 64.4157 80.225C64.3594 80.1395 64.3117 80.0513 64.2583 79.9602Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M50.5055 66.5836C49.8703 66.9232 49.2323 67.2542 48.5972 67.5938C48.5467 67.4971 48.4933 67.406 48.4428 67.3093C49.0809 66.9641 49.7104 66.6217 50.3484 66.2764C50.396 66.3788 50.4522 66.4784 50.5055 66.5836Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M53.1891 80.31C52.4279 81.2898 51.9555 81.4629 51.3793 81.0144C51.9484 80.7907 52.4891 80.5811 53.1891 80.31Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.5806 17.6942C75.5107 17.9718 75.4896 18.1675 75.4062 18.3316C74.3882 20.3629 72.9014 21.9858 71.1742 23.4371C70.3549 24.1247 69.668 24.9719 68.9107 25.7336C68.2991 26.3486 67.6846 26.9693 67.0392 27.5529C66.9192 27.6629 66.6413 27.6074 66.323 27.6453C69.439 24.3577 73.0564 21.7228 75.1968 17.7629C75.2198 17.7177 75.3475 17.7326 75.5806 17.6942Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M63.1885 15.615C61.6287 16.148 60.0605 16.6554 58.5062 17.2197C55.9981 18.1332 53.5013 19.0666 51.0073 20.0228C50.1759 20.3415 49.3753 20.7398 48.5635 21.1041C48.3983 21.1769 48.0805 21.1297 48.3227 21.4659C48.1915 21.5418 48.0686 21.6716 47.935 21.6822C47.719 21.7008 47.495 21.6513 47.0834 21.6063C47.3205 21.392 47.438 21.2168 47.6004 21.1496C49.8701 20.1865 52.1203 19.1779 54.4179 18.3001C56.5134 17.4977 58.6649 16.8234 60.7967 16.1035C61.3375 15.9222 61.8783 15.7408 62.4331 15.5879C62.675 15.5184 62.9419 15.5398 63.1948 15.5185C63.1889 15.5582 63.1887 15.5866 63.1885 15.615Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M63.9542 24.8082C65.572 23.6003 67.2631 22.4722 68.7936 21.1559C70.3298 19.8425 71.7108 18.3438 73.3024 16.7953C73.2665 17.0901 73.3188 17.3515 73.2102 17.4672C72.3495 18.3901 71.5002 19.3329 70.5605 20.173C69.3554 21.2414 68.0656 22.2243 66.804 23.2357C66.1418 23.7681 65.4851 24.3176 64.7948 24.8074C64.6036 24.9453 64.2887 24.9066 64.0328 24.9477C64.0047 24.905 63.9794 24.8566 63.9542 24.8082Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M42.2933 29.3493C42.1757 29.5245 42.0975 29.7624 41.935 29.858C41.0029 30.4031 40.0455 30.8998 39.1106 31.4364C38.6146 31.7258 38.1523 32.075 37.6675 32.3844C37.5705 32.4491 37.437 32.4597 37.3061 32.493C37.0046 32.1195 37.2504 31.8741 37.5016 31.6598C38.267 30.9946 41.0849 29.5551 42.2933 29.3493Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M74.2241 22.258C73.9903 24.2172 71.4233 27.3773 70.0825 27.4377C70.2143 27.2625 70.2833 27.1268 70.3889 27.0451C71.6445 26.0593 72.6148 24.8505 73.3251 23.4246C73.538 22.9917 73.9207 22.6449 74.2241 22.258Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M63.5441 15.4931C64.7665 14.4189 70.2902 13.6674 70.7998 14.3883C69.5608 14.4861 68.3222 14.5131 67.111 14.6963C65.9084 14.8766 64.7359 15.2218 63.5441 15.4931Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M70.574 10.4033C70.2018 10.4069 69.827 10.3877 69.4548 10.4054C68.1107 10.4857 66.7611 10.5489 65.4253 10.6831C64.5186 10.7715 63.6198 10.9707 62.6331 11.1325C63.1004 10.4512 69.7743 9.73469 70.5782 10.1849C70.5777 10.2558 70.5773 10.3267 70.574 10.4033Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M61.6579 11.241C60.7897 11.5481 59.9214 11.8553 59.0503 12.1681C59.0528 12.2334 59.0552 12.2987 59.0605 12.3583C58.9534 12.2328 58.8548 12.1046 58.7476 11.9791C58.8646 11.889 58.9735 11.7449 59.1043 11.7116C59.938 11.4865 60.7771 11.2785 61.6107 11.0676C61.6274 11.1188 61.6469 11.1785 61.6579 11.241Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.275 26.3032C62.3137 26.4651 62.4261 26.6501 62.377 26.7746C62.2211 27.1935 61.1639 27.8313 60.6284 27.6808C61.1421 27.2441 61.6586 26.8159 62.275 26.3032Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M63.2832 13.5379C62.0549 13.7409 60.8664 13.9355 59.6778 14.1302C60.4794 13.5899 62.9506 13.1274 63.2832 13.5379Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M54.7777 15.5593C55.5692 15.263 56.3495 14.9327 57.1493 14.6762C57.8466 14.4532 58.5718 14.3013 59.2774 14.1181C59.2912 14.1749 59.3078 14.2402 59.3217 14.2971C57.7995 14.714 56.2801 15.1252 54.7579 15.5421C54.7551 15.5478 54.7777 15.5593 54.7777 15.5593Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M76.3724 20.2307C75.9904 19.5818 76.0941 19.3498 77.021 18.6602C76.822 19.1498 76.6145 19.6421 76.3724 20.2307Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M93.3329 38.3989C93.354 38.6657 93.4062 38.9412 93.3846 39.2078C93.2259 41.4114 92.7666 43.5622 92.1229 45.6693C91.9345 46.2782 91.5477 46.8293 91.3593 47.4382C90.8088 49.1941 89.9668 50.7809 88.9068 52.2785C88.4513 52.9228 88.1144 53.6557 87.6843 54.32C87.5696 54.5037 87.3022 54.5817 87.1083 54.7111C87.0547 54.6483 87.0041 54.5799 86.9505 54.5172C87.3835 53.8473 87.8448 53.1917 88.2523 52.5018C88.9841 51.2718 89.8179 50.0793 90.377 48.7689C91.1378 46.9915 91.794 45.1539 92.2856 43.2899C92.6638 41.8451 92.7217 40.3162 92.9327 38.8222C92.9565 38.6635 93.0539 38.5136 93.1202 38.3551C93.1882 38.3754 93.262 38.3843 93.3329 38.3989Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M87.2249 38.3037C82.929 44.5297 77.2838 49.4741 71.5384 54.5456C71.6025 54.2793 71.5925 54.0749 71.6867 53.9875C72.3552 53.3586 73.0433 52.761 73.7315 52.1493C75.2708 50.7735 76.8355 49.4177 78.3465 48.0133C79.3034 47.125 80.2548 46.2055 81.1016 45.2116C82.7981 43.2182 84.4156 41.1562 86.0668 39.1256C86.2815 38.8573 86.4623 38.5576 86.6883 38.295C86.777 38.1905 86.9475 38.1631 87.0786 38.1014C87.1264 38.1613 87.1771 38.2297 87.2249 38.3037Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M86.2965 36.3457C85.0964 37.0539 83.8401 37.6766 82.7132 38.4789C80.9332 39.7399 79.2404 41.1234 77.511 42.4529C76.4465 43.2725 75.3539 44.0636 74.312 44.9089C73.644 45.4527 73.0521 46.0849 72.4011 46.6515C72.224 46.8037 71.9624 46.8562 71.7346 46.9542C71.6952 46.9057 71.6528 46.8629 71.6134 46.8144C71.6823 46.6928 71.7174 46.5256 71.8202 46.4496C72.9503 45.5707 74.0974 44.7147 75.2275 43.8359C76.5688 42.7937 77.8651 41.7001 79.2289 40.6978C80.8951 39.4645 82.6037 38.2881 84.3038 37.1004C84.7544 36.7881 85.2474 36.5327 85.7403 36.2773C85.9055 36.1902 86.127 36.2029 86.3203 36.1727C86.3057 36.2294 86.3025 36.2918 86.2965 36.3457Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M85.042 46.9888C87.0843 44.6088 88.575 41.8994 89.7942 39.0238C89.8678 39.047 89.9386 39.0757 90.0123 39.0989C89.9828 39.2831 89.9759 39.4788 89.9123 39.6459C89.1855 41.4404 88.3143 43.1689 87.2168 44.7685C86.701 45.5173 86.2361 46.292 85.7175 47.0324C85.6402 47.1426 85.3734 47.1212 85.1971 47.1599C85.1378 47.1085 85.0899 47.0487 85.042 46.9888Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M72.0183 39.9034C72.3204 38.8325 80.9269 34.1859 81.838 34.7189C78.1306 35.7929 75.1826 38.0346 72.0183 39.9034Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M81.9821 52.3243C80.854 54.2358 79.1019 55.5962 77.6208 57.1936C77.5473 57.1421 77.4738 57.0906 77.3974 57.0447C77.5178 56.8638 77.6128 56.6629 77.7558 56.5077C78.7305 55.4862 79.7222 54.4875 80.6913 53.4631C80.9715 53.164 81.1669 52.7934 81.4217 52.4743C81.5219 52.3472 81.6899 52.2687 81.8325 52.1702C81.8891 52.2131 81.937 52.2729 81.9821 52.3243Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M85.7501 56.3475C85.4749 57.2252 84.6378 58.0741 84.0277 58.0423C84.5056 57.4239 84.9579 56.828 85.4271 56.2549C85.4585 56.2211 85.6396 56.3129 85.7501 56.3475Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M82.9491 33.4761C83.4324 32.9173 84.3598 32.5907 84.7414 32.8481C83.7971 33.5858 83.2992 33.7673 82.9491 33.4761Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.1942 46.5483C19.6286 44.7407 19.9441 42.8871 20.5259 41.1257C21.0902 39.4267 21.8078 37.7484 22.678 36.1759C23.6143 34.4733 24.7714 32.8827 25.8804 31.2747C26.6598 30.1472 27.4986 29.0569 28.3487 27.9723C28.7265 27.495 29.1891 27.0749 29.6319 26.6519C29.7261 26.5645 29.9134 26.5741 30.0528 26.538C30.0294 26.6542 30.0425 26.8245 29.9711 26.8808C28.3102 28.2161 27.2849 30.0657 25.9686 31.6895C24.5722 33.4149 23.4275 35.2894 22.5119 37.3013C21.5185 39.4944 20.5223 41.6931 20.155 44.1111C20.0572 44.7659 19.9651 45.4236 19.8191 46.0611C19.7694 46.285 19.561 46.471 19.4234 46.6716C19.3498 46.6343 19.2706 46.5942 19.1942 46.5483Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.0969 28.9148C34.1325 29.125 34.2022 29.3382 34.1952 29.5481C34.1546 31.9397 34.1537 34.3372 34.0223 36.7255C33.9327 38.3309 33.6557 39.9267 33.4412 41.5257C33.334 42.311 33.2523 43.1164 33.0119 43.8697C32.4527 45.6285 31.8029 47.3555 31.1843 49.0912C31.1236 49.2526 30.9723 49.3822 30.8663 49.5348C30.8153 49.509 30.7644 49.4832 30.7134 49.4574C30.7859 49.2166 30.8442 48.9758 30.9224 48.7379C31.4983 47.0161 32.1026 45.3087 32.6417 43.5753C32.9171 42.6832 33.1302 41.7594 33.2922 40.8382C33.4039 40.226 33.3852 39.5903 33.4261 38.9635C33.5358 37.3185 33.6739 35.6737 33.741 34.0284C33.813 32.5137 33.8084 30.9957 33.8434 29.4836C33.8475 29.2936 33.8628 29.1092 33.8725 28.922C33.9464 28.9168 34.023 28.92 34.0969 28.9148Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M26.9495 51.1345C26.8869 51.1597 26.7219 51.2183 26.46 51.3133C28.0589 46.7659 29.8867 42.3986 30.4701 37.6638C30.3071 42.3698 28.3154 46.6113 26.9495 51.1345Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M25.8059 27.9849C25.3315 28.456 24.8403 28.9043 24.3941 29.404C23.0758 30.8774 21.7433 32.3366 20.4815 33.853C19.8033 34.6691 19.2438 35.5879 18.642 36.464C18.5216 36.6449 18.452 36.8658 18.3455 37.1036C17.9545 36.9623 18.1125 36.6795 18.2644 36.4505C18.7518 35.7156 19.2222 34.958 19.7746 34.2774C20.968 32.7975 22.1616 31.3034 23.4539 29.9093C24.1343 29.1726 25.0238 28.6273 25.82 27.9992L25.8059 27.9849Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.071 47.9575C18.955 48.802 18.8539 49.519 18.732 50.389C18.407 49.7122 18.5883 48.4312 19.071 47.9575Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.8845 53.2029C29.1378 52.6484 29.3939 52.0883 29.6416 51.531C29.7237 51.5655 29.8001 51.5971 29.8822 51.6316C29.6543 52.2061 29.4237 52.772 29.1958 53.3465C29.0911 53.3005 28.9892 53.2489 28.8845 53.2029Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M25.8296 27.9966C26.361 27.4551 26.901 26.9108 27.4324 26.3692C27.4916 26.4348 27.5508 26.5004 27.6128 26.5745C27.0108 27.0447 26.4089 27.5149 25.8127 27.988L25.8296 27.9966Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M83.738 78.1961C83.8328 78.0094 83.8742 77.76 84.0225 77.6502C85.9507 76.2937 87.4723 74.5462 88.9575 72.7446C90.3166 71.1068 91.5654 69.4059 92.3079 67.3844C92.3512 67.2712 92.5418 67.2042 92.6616 67.1226C92.6891 67.2646 92.7847 67.4269 92.7441 67.5486C92.1893 69.0747 91.3827 70.4518 90.3101 71.6799C89.2776 72.8571 88.3553 74.1257 87.2918 75.2658C86.254 76.3692 85.0949 77.3613 83.9894 78.4019C83.899 78.3276 83.8199 78.259 83.738 78.1961Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M98.227 52.9612C97.1461 55.9709 96.0738 58.9778 94.9929 61.9875C94.9617 61.9788 94.9362 61.973 94.9021 61.97C95.1785 60.9218 95.4576 59.8822 95.7339 58.834C95.7056 58.8197 95.6688 58.8081 95.6405 58.7937C95.5318 58.9236 95.423 59.0535 95.2972 59.2032C95.2749 59.1349 95.2355 59.0723 95.2556 59.0327C95.4396 58.6706 95.6378 58.3086 95.8162 57.9436C95.9254 57.7286 96.0319 57.5051 96.1072 57.2729C96.2983 56.6867 96.3502 56.1082 96.8221 55.5718C97.2683 55.058 97.3162 54.2071 97.5705 53.5107C97.6572 53.27 97.8317 53.0525 97.9666 52.8292C98.0572 52.8751 98.1421 52.9181 98.227 52.9612Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M97.5171 57.9165C97.0297 58.6656 96.5422 59.4147 96.052 60.1552C96.0039 60.1237 95.9586 60.1007 95.9106 60.0693C96.2413 59.4044 96.5324 58.7195 96.9028 58.0747C97.5947 56.8672 97.7451 55.5204 98.0231 54.2027C98.0934 53.8683 98.1159 53.4457 98.7888 53.4666C98.3592 54.9565 97.9324 56.4408 97.4971 57.9278L97.5171 57.9165Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M85.6774 62.2387C87.8161 60.4123 90.0927 58.7768 92.5973 57.4775C92.6423 57.543 92.6873 57.6085 92.7267 57.6712C91.5292 58.4162 90.2951 59.1071 89.1399 59.9092C88.0017 60.7056 86.9394 61.6189 85.8406 62.478C85.7928 62.4039 85.7337 62.3241 85.6774 62.2387Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M97.5037 57.9313C97.6381 57.7789 97.7696 57.6321 97.9126 57.4627C98.1561 58.4826 95.4491 63.6278 94.2448 64.5968C94.4141 64.3197 94.5806 64.0341 94.7555 63.76C95.8912 61.9592 96.8202 60.0609 97.5624 58.0678C97.5769 58.0254 97.5375 57.9627 97.5208 57.9115C97.518 57.9172 97.5037 57.9313 97.5037 57.9313Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M88.1551 64.9881C87.4518 65.7416 86.7569 66.5065 86.0281 67.2401C85.9138 67.3529 85.6527 67.3202 85.4594 67.3503C85.5541 67.1919 85.6149 67.0022 85.7435 66.8753C86.2578 66.3817 86.7834 65.8938 87.3146 65.423C87.5488 65.2144 87.8083 65.04 88.0566 64.8456C88.0904 64.8912 88.1213 64.9425 88.1551 64.9881Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M83.4484 64.6364C83.469 64.5117 83.4558 64.3557 83.5245 64.2625C83.7822 63.9236 84.054 63.5848 84.3596 63.2916C84.4566 63.1985 84.6722 63.2224 84.8371 63.1922C84.7992 63.3366 84.8094 63.5267 84.718 63.6226C84.3579 63.9949 83.9668 64.3444 83.5871 64.6996C83.5418 64.6767 83.4936 64.6594 83.4484 64.6364Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M50.6268 8.629C50.3853 9.09009 50.2033 9.5884 49.8997 10.0037C48.8858 11.3683 47.8889 12.7557 46.7592 14.026C45.4722 15.4798 44.0384 16.8022 42.6893 18.196C42.1033 18.8027 41.585 19.4863 40.9709 20.0644C40.4881 20.5241 39.9093 20.8925 39.3024 21.2181C43.2183 17.155 47.4166 13.3488 50.3666 8.45444C50.4514 8.51167 50.5419 8.57177 50.6268 8.629Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M29.5153 18.1924C29.6731 17.938 29.7998 17.6606 29.9858 17.4347C31.4278 15.7462 33.1545 14.38 34.9433 13.0879C36.9405 11.6381 38.87 10.0971 40.9206 8.7242C42.4236 7.7142 44.0673 6.91781 45.6547 6.03598C45.7545 5.97981 45.8907 5.99194 46.1286 6.09829C45.9028 6.3325 45.7158 6.71448 45.4455 6.78386C43.5879 7.27258 42.0366 8.29365 40.5103 9.39148C39.2864 10.2726 38.0146 11.0796 36.8245 12.0063C34.7155 13.6484 32.4569 15.1222 30.6494 17.1377C30.3176 17.5104 30.0225 17.9229 29.7133 18.3212C29.6482 18.2811 29.5775 18.2382 29.5153 18.1924Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M33.8334 18.0902C34.5187 17.5125 35.2011 16.9262 35.8891 16.357C37.1509 15.3173 38.4325 14.2946 39.6774 13.2321C41.0251 12.0793 42.2855 10.8183 43.6952 9.73963C44.9508 8.78213 46.3529 8.01274 47.693 7.16921C47.827 7.0877 47.9975 7.07449 48.1539 7.03283C48.1819 7.10393 48.2127 7.16936 48.2407 7.24046C47.4625 7.69281 46.6618 8.1195 45.9005 8.60883C44.2723 9.65499 42.6751 10.7382 41.3088 12.1377C40.4827 12.9785 39.5466 13.7137 38.6359 14.4689C37.4483 15.4466 36.2326 16.3817 35.0479 17.3538C34.691 17.6497 34.3821 18.0054 34.0534 18.3298C33.9744 18.2471 33.9011 18.1672 33.8334 18.0902Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M43.5274 14.4729C45.8766 12.54 47.4038 9.91295 49.3802 7.66301C49.4426 7.68039 49.5106 7.70064 49.573 7.71803C49.5435 7.88809 49.5706 8.10104 49.4761 8.21683C47.9164 10.1372 46.3596 12.0519 44.7716 13.9438C44.5027 14.2628 44.0812 14.4618 43.7331 14.7124C43.6598 14.6325 43.595 14.5498 43.5274 14.4729Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.376 19.6189C27.8354 20.2343 27.3264 20.8017 26.8258 21.3804C26.4253 21.8463 26.0051 22.295 25.6527 22.7923C25.5209 22.9817 25.553 23.2826 25.4862 23.5262C25.3556 23.9794 25.056 24.2047 24.5652 24.1338C24.7076 23.1671 27.6089 19.6713 28.376 19.6189Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M39.8098 18.6216C40.5364 17.7944 41.24 16.9983 41.9379 16.1994C41.9918 16.2054 42.0372 16.2141 42.0911 16.2201C42.0042 16.4892 41.9541 16.784 41.8163 17.0272C41.38 17.7595 40.2497 18.6667 39.8098 18.6216Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M92.2465 21.4701C92.5724 22.9302 89.2188 28.8434 87.9041 29.3153C87.9764 29.1029 87.9917 28.9186 88.0862 28.8028C89.3733 27.3065 90.4343 25.6529 91.2915 23.8818C91.5792 23.2877 91.6942 22.6131 91.9083 21.9816C91.9632 21.8316 92.0946 21.699 92.2465 21.4701Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M76.1523 29.3844C76.3781 29.1501 76.5241 28.9751 76.6897 28.8313C77.712 27.9406 78.7062 27.0071 79.7877 26.1819C81.1975 25.1033 82.672 24.1073 84.1353 23.0914C84.5318 22.8156 84.9677 22.5883 85.3924 22.3552C85.4921 22.2991 85.6397 22.3169 85.7619 22.3006C85.7043 22.428 85.6861 22.618 85.592 22.677C84.9421 23.0592 84.25 23.3701 83.6254 23.7865C81.2355 25.3787 78.8652 27.0023 76.8134 29.0363C76.6819 29.1689 76.5702 29.3187 76.4358 29.4569C76.4244 29.4654 76.3621 29.4338 76.1523 29.3844Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M77.4791 24.5716C77.5311 24.4414 77.538 24.2456 77.635 24.1809C79.1095 23.1991 80.5841 22.2031 82.0895 21.2725C82.9905 20.7187 83.9476 20.2645 84.8906 19.7961C85.1299 19.6755 85.4226 19.6601 85.7403 19.7215C82.8743 21.1295 79.9551 22.418 77.4791 24.5716Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M88.4729 23.0214C87.537 24.6531 86.4003 26.1475 85.1986 27.5875C85.1421 27.5446 85.0799 27.4989 85.0205 27.4617C86.095 25.9216 87.1723 24.39 88.2468 22.8499C88.3231 22.9099 88.3966 22.9614 88.4729 23.0214Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M83.4195 17.828C83.5822 17.2557 85.9836 16.1316 86.5807 16.4841C85.4814 16.9517 84.4191 17.4024 83.4195 17.828Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M82.6303 30.1197C83.0938 29.5295 83.5231 28.9789 84.0154 28.3464C84.101 29.1722 83.3428 30.1039 82.6303 30.1197Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M81.7226 18.9946C81.0048 19.3847 80.2899 19.7692 79.5721 20.1593C79.5384 20.0996 79.5133 20.0371 79.4796 19.9773C80.2058 19.5985 80.9235 19.2226 81.6497 18.8438C81.675 18.8922 81.7002 18.9406 81.7226 18.9946Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M67.8848 5.56177C68.8175 5.40822 69.7501 5.25465 70.6827 5.1011C70.7022 5.1608 70.716 5.21764 70.7356 5.27735C70.414 5.37766 70.0895 5.48363 69.7651 5.57541C69.3013 5.70329 68.8346 5.83682 68.3626 5.92492C68.1977 5.95519 68.0081 5.83775 67.8323 5.79134C67.8413 5.7176 67.8616 5.63542 67.8848 5.56177Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.4303 6.58191C63.1503 6.37037 63.8591 6.12471 64.5873 5.96714C64.9769 5.88708 65.4053 5.969 65.8143 5.97702C65.8281 6.03386 65.8391 6.09635 65.8529 6.15319C65.7559 6.23209 65.6384 6.39317 65.5618 6.3757C64.5949 6.10623 63.6975 6.52675 62.7652 6.63775C62.6515 6.65129 62.5353 6.59954 62.419 6.57617C62.4219 6.57051 62.4303 6.58191 62.4303 6.58191Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M41.8778 69.5163C40.1463 71.6627 37.8986 73.2699 36.9873 75.9458C36.9135 75.9369 36.8029 75.9164 36.6921 75.9243C36.604 75.9294 36.5213 75.98 36.4189 76.0135C36.423 74.9127 40.8557 69.4963 41.8778 69.5163Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M38.337 75.4633C38.9801 73.9037 40.3351 72.9184 41.3511 71.6617C41.4162 71.7018 41.4841 71.7362 41.5492 71.7763C41.5 71.915 41.4876 72.0937 41.3989 72.1982C40.8182 72.8644 40.2009 73.4908 39.64 74.1742C39.3997 74.465 39.2836 74.8616 39.0714 75.181C38.9453 75.3732 38.7315 75.4996 38.5516 75.6575C38.4782 75.5918 38.4104 75.529 38.337 75.4633Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M40.8322 65.3643C40.4697 65.6573 40.0959 65.9445 39.7361 66.2461C39.0737 66.8069 38.3746 67.342 37.7573 67.9541C36.7114 68.9894 35.7135 70.0704 34.6958 71.1343C34.3785 71.4644 34.1988 72.0422 33.343 71.7507C35.9097 69.5863 37.756 66.8078 40.6545 65.1675C40.7137 65.2331 40.773 65.2987 40.8322 65.3643Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.8798 72.2305C36.3524 70.6217 37.7992 69.0355 39.2432 67.4549C38.6637 69.2958 35.9078 72.2251 34.8798 72.2305Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.4221 6.57031L62.422 6.584C62.4166 6.58123 62.4138 6.58669 62.4083 6.58392C62.4165 6.58123 62.4193 6.57577 62.4221 6.57031Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M54.7554 15.547L54.7751 15.5641C54.7609 15.564 54.7383 15.5667 54.7184 15.5779C54.7326 15.5639 54.7496 15.5583 54.7554 15.547Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M39.3455 43.8286C39.3226 43.8455 39.2969 43.854 39.2739 43.8709C39.2912 43.8511 39.3084 43.8312 39.3342 43.8228L39.3455 43.8286Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M14.5025 50.317C15.117 50.1587 15.2065 49.9266 14.9352 49.2696C14.7938 49.6178 14.6439 49.9688 14.5025 50.317ZM15.6786 53.8592C15.7697 53.82 15.8637 53.7751 15.9548 53.7359C15.4065 52.8674 15.4192 51.7636 14.8112 50.9146C14.7485 50.9398 14.6859 50.965 14.6204 50.9958C14.9721 51.9569 15.3267 52.9123 15.6786 53.8592ZM15.4737 42.7179C15.5261 41.6201 15.1547 40.6277 14.2536 39.8508C14.2693 40.5205 14.3902 41.1511 14.2842 41.7521C14.0482 43.1411 13.6987 44.5154 13.4173 45.8956C13.1184 47.3524 12.6434 48.8053 13.4009 50.271C13.499 50.4702 13.5857 50.692 13.6184 50.9078C13.9632 52.9613 14.9489 54.7205 16.1169 56.4013C16.1985 56.5209 16.3086 56.6265 16.4636 56.8119C16.4504 56.6557 16.4592 56.6104 16.4424 56.5734C16.0417 55.7085 15.6468 54.8465 15.2263 53.9787C14.6348 52.7466 13.9524 51.5255 14.0154 50.1127C14.0822 48.5241 14.2485 46.936 14.4232 45.3594C14.4626 44.9737 14.712 44.6091 14.8705 44.2411C14.93 44.2641 14.9924 44.2815 15.0546 44.3131C14.8633 45.8244 14.672 47.3357 14.4777 48.8527C14.5969 48.8704 14.7161 48.8881 14.8267 48.9086C14.91 48.3103 15.0132 47.715 15.0738 47.1195C15.2251 45.6449 15.4077 44.1789 15.4737 42.7179ZM18.4969 54.5903C18.2051 54.9263 17.9905 55.1805 17.7616 55.4487C17.9643 55.7365 18.1529 55.9958 18.3443 56.2636C19.0006 55.7707 18.7002 55.2271 18.4969 54.5903ZM29.1621 68.3363C29.2579 68.4561 29.3453 68.5502 29.427 68.6556C29.6711 68.2314 29.9009 67.8213 30.1278 67.4168C30.0883 67.3825 30.0459 67.3539 30.0034 67.3253C29.7345 67.6444 29.4683 67.972 29.1621 68.3363ZM30.1841 63.019C29.5572 63.3559 28.9359 63.6957 28.3146 64.0355C28.3426 64.0924 28.3792 64.1465 28.4129 64.2063C29.023 63.8466 29.6415 63.4982 30.2515 63.1385C30.229 63.0987 30.2066 63.0588 30.1841 63.019ZM31.865 70.6955C30.98 70.9799 30.5974 70.85 30.4817 70.279C30.2432 70.7203 30.5781 71.2103 31.3851 71.5837C31.5402 71.3066 31.6897 71.0265 31.865 70.6955ZM31.6801 66.2679C32.0227 65.9861 32.3653 65.7043 32.7278 65.4113C32.3624 65.2616 31.9257 65.6025 31.6801 66.2679ZM36.6633 63.734C34.0904 65.0558 31.8826 66.5698 30.6311 69.1165C31.5544 68.1683 32.4299 67.1603 33.421 66.275C34.4035 65.3924 35.4989 64.6382 36.6633 63.734ZM33.6069 61.5799C34.375 60.9232 35.0501 60.1694 35.7617 59.4556C33.7446 60.0201 32.1655 61.3759 30.4105 62.2513C30.5308 62.5329 30.6092 62.7149 30.7016 62.9254C31.2371 62.6703 31.8325 62.3814 32.425 62.0982C32.3884 62.0582 32.346 62.0154 32.3121 61.984C32.395 61.905 32.4611 61.7891 32.5634 61.7698C32.9161 61.6923 33.3757 61.7687 33.6069 61.5799ZM38.6606 63.1665C38.2334 63.3627 37.789 63.5645 37.4208 63.8546C35.9878 65.007 34.5464 66.148 33.1783 67.3689C32.2757 68.1781 31.4577 69.0871 31.098 70.2854C33.6151 67.9105 36.1378 65.5385 38.6606 63.1665ZM42.6298 76.7921C42.5902 76.7579 42.5536 76.7179 42.514 76.6837C41.639 77.6207 40.7584 78.5549 39.8176 79.5654C39.8543 79.6054 39.8966 79.6482 39.9333 79.6881C41.1526 79.0963 41.8615 77.9256 42.6298 76.7921ZM36.4016 66.0422C37.9949 64.6864 39.715 63.4875 41.3589 62.2284C39.5722 62.7177 32.22 68.9042 31.6819 70.4675C33.3132 68.9388 34.7911 67.4178 36.4016 66.0422ZM42.0709 62.8028C42.0058 62.7769 41.9434 62.7595 41.8726 62.7308C37.9456 64.8536 34.4218 67.4441 32.0373 71.2952C32.1895 71.472 32.2854 71.5775 32.3813 71.6831C32.1362 71.815 31.8855 71.9441 31.555 72.1182C31.7502 72.2243 31.9941 72.2909 32.1407 72.4507C32.6089 72.9584 33.2397 73.3564 33.3142 74.1627C33.3595 74.6198 33.5185 75.0775 33.6291 75.5605C33.9743 75.3156 34.1963 75.2289 34.3167 75.0622C34.7982 74.3669 35.2515 73.6431 35.7189 72.9335C35.7734 72.8544 35.8816 72.8096 35.953 72.7391C36.1931 72.5049 36.4303 72.2764 36.6618 72.0309C37.125 71.5398 37.5968 71.0459 38.0459 70.5406C38.575 69.9477 39.2061 69.4065 39.5938 68.7277C40.438 67.2626 41.1805 65.7318 41.903 64.1979C42.0732 63.7931 42.0168 63.2735 42.0709 62.8028ZM36.1306 32.6289C36.1542 30.691 36.1977 28.7561 36.2101 26.8124C36.2112 26.628 36.0449 26.4369 35.9666 26.2407C35.9108 26.0843 35.8295 25.9079 35.8476 25.7463C35.9048 25.2415 35.9989 24.7342 36.0816 24.221C36.0135 24.215 35.9483 24.2032 35.8774 24.1887C35.7102 25.0219 35.5374 25.8523 35.3646 26.6828C35.3362 26.6684 35.3107 26.6626 35.2795 26.6539C35.3048 25.3573 35.3443 24.0608 35.3735 22.5883C35.0239 23.9767 34.7208 25.1894 34.415 26.3936C34.3441 26.379 34.2732 26.3644 34.2108 26.347C34.4135 25.2898 34.6247 24.2298 34.8244 23.1782C34.7961 23.1638 34.7621 23.1608 34.7394 23.1493C34.2926 24.1967 33.8457 25.2582 33.3988 26.3055C33.3506 26.2882 33.3025 26.2709 33.2572 26.248C33.7105 25.0758 34.1525 23.8979 34.6058 22.7258C34.5266 22.6714 34.4332 22.617 34.3541 22.5626C34.1897 22.9561 34.0253 23.3496 33.8524 23.7458C33.8015 23.7058 33.7535 23.6743 33.7026 23.6343C33.8492 23.3599 33.9929 23.0912 34.1395 22.8168C34.1111 22.8024 34.0828 22.7881 34.0517 22.7652C33.5673 23.4661 33.0971 24.1672 32.6098 24.8738C32.5731 24.848 32.5363 24.8223 32.5052 24.7994C32.7836 24.3498 33.059 23.9059 33.3317 23.4534C33.3063 23.4334 33.2808 23.4134 33.2525 23.3991C32.8436 23.8394 32.4375 24.2883 32.0314 24.7371C31.9975 24.7057 31.9551 24.6771 31.9297 24.6429C32.4452 23.9648 32.9692 23.2982 33.4903 22.623C33.4508 22.5887 33.4056 22.5515 33.3604 22.5144C32.7686 23.1324 32.1796 23.759 31.5934 24.3799C31.5397 24.3456 31.4887 24.3198 31.435 24.2854C31.6589 23.9008 31.8603 23.4905 32.1267 23.1345C32.3874 22.7756 32.7103 22.4625 33.0248 22.1379C33.3306 21.8304 33.6507 21.5229 33.9621 21.2182C33.9311 21.1812 33.8945 21.1412 33.8549 21.107C33.0614 21.7437 32.282 22.3806 31.4912 23.0259C31.5638 22.7851 31.6956 22.5957 31.85 22.432C32.0159 22.2457 32.2016 22.0765 32.3731 21.893C32.3308 21.8502 32.2856 21.8131 32.2433 21.7703C30.6714 22.8736 29.0798 23.9599 27.539 25.1003C26.3434 25.9817 25.2099 26.9371 24.034 27.8498C21.7222 29.6527 19.6503 31.6839 18.0019 34.1148C17.268 35.1945 16.5878 36.3228 15.9784 37.4799C15.6392 38.1193 15.4783 38.8561 15.275 39.5643C15.2315 39.706 15.3325 39.8995 15.3798 40.0587C15.617 40.7268 16.0246 41.3818 16.0516 42.0572C16.1089 43.3174 15.9446 44.5934 15.86 45.8528C15.832 46.23 15.7615 46.607 15.7108 46.9869C16.0025 46.6651 16.1581 46.317 16.3758 46.0146C16.4675 45.8903 16.6863 45.866 16.8458 45.7903C16.8872 45.9891 17.0277 46.2311 16.9615 46.3613C16.6827 46.8818 16.3161 47.3649 16.026 47.8797C15.868 48.1625 15.7921 48.4941 15.6794 48.7999C15.7502 48.8287 15.821 48.8575 15.8862 48.8834C16.1243 48.513 16.3397 48.1312 16.6202 47.7894C16.7289 47.6595 16.9761 47.6354 17.1612 47.5655C17.1939 47.7814 17.3313 48.0574 17.2452 48.1988C16.9983 48.6145 16.7004 49.0185 16.3575 49.3571C15.8201 49.896 15.5864 50.482 15.8261 51.2013C16.588 50.6268 16.5284 49.2729 17.827 49.1555C17.5213 49.8972 17.2098 50.6502 16.6838 51.1948C16.0749 51.8185 15.9805 52.3684 16.4614 53.1174C16.9459 52.4023 17.4189 51.7098 17.8947 51.0258C17.9692 50.9212 18.0975 50.851 18.2003 50.7608C18.2932 50.8862 18.4373 50.9948 18.4592 51.134C18.4896 51.2704 18.4287 51.4601 18.3428 51.5731C17.8903 52.1693 17.3982 52.7453 16.9598 53.3557C16.8309 53.5253 16.7097 53.8339 16.774 53.9875C16.9223 54.3402 17.1987 54.6368 17.4802 55.0357C17.9306 54.3175 18.3095 53.6841 18.728 53.0849C18.8283 52.9436 19.0727 52.9109 19.2465 52.8211C19.2568 52.9971 19.3152 53.1904 19.2603 53.3405C19.0608 53.9012 18.6342 54.4322 19.1756 55.0482C19.4272 54.7914 19.4286 54.1161 20.2503 54.4187C20.0634 54.7865 19.9529 55.1859 19.7068 55.474C19.2547 56.0134 19.3284 56.4848 19.7116 56.9637C20.5105 56.8349 20.0696 55.5867 21.0469 55.5412C21.1992 56.6004 20.4768 57.2234 19.8643 57.9662C20.2348 58.2038 20.5431 58.4099 20.8599 58.6132C21.3187 57.9206 21.7344 57.2987 22.1474 56.6683C22.1789 56.6202 22.1652 56.5492 22.1684 56.4868C22.2146 55.9195 22.2551 55.3494 22.3127 54.7737C22.4793 53.1431 22.5721 51.4894 22.8521 49.8736C23.1289 48.3344 23.5504 46.8045 24.0114 45.3089C24.5941 43.4338 25.225 41.576 25.9579 39.7556C26.9303 37.3521 28.0329 35.0004 29.0647 32.6199C29.8947 30.7065 31.1548 29.0537 32.3837 27.3922C32.4382 27.3131 32.5887 27.3111 32.694 27.272C32.601 27.6091 32.4236 27.8181 32.249 28.0356C30.5146 30.1453 29.1989 32.51 28.1634 35.0238C27.0038 37.8519 25.8922 40.7115 24.8658 43.5857C24.2846 45.2197 23.8649 46.9141 23.4594 48.6087C22.8963 50.9776 22.6679 53.4024 22.6127 55.8367C22.6076 56.197 22.7748 56.6945 22.6003 56.8978C21.9881 57.5981 22.1565 58.3595 22.2423 59.1573C22.3944 58.9142 22.4871 58.6338 22.6278 58.3849C22.6996 58.2576 22.8796 58.0855 22.976 58.1059C23.115 58.1408 23.2985 58.3121 23.309 58.4455C23.3306 58.6272 23.2298 58.8395 23.1379 59.0063C22.9254 59.3683 22.6761 59.7188 22.421 60.0947C22.5624 60.1948 22.749 60.3179 22.995 60.4924C23.0678 60.2091 23.0979 59.9397 23.2044 59.7161C23.2936 59.5407 23.4846 59.4169 23.6304 59.2702C23.7115 59.4608 23.8495 59.6517 23.8568 59.8475C23.8583 60.0546 23.797 60.3154 23.6653 60.4763C23.2533 60.9649 23.5071 61.2501 23.9255 61.5476C24.1239 61.1713 23.5586 60.2941 24.6818 60.5218C24.6626 60.8679 24.7368 61.2542 24.5986 61.54C24.2591 62.2361 24.5832 62.6352 25.075 62.9984C26.0545 60.8191 26.0986 58.3365 27.4237 56.2897C26.6029 58.5352 25.8417 60.7895 26.2489 63.2945C26.4376 63.1055 26.5633 62.9842 26.8433 62.7134C26.9145 63.1337 27.0122 63.4038 26.9907 63.6563C26.9453 64.0958 26.7552 64.526 26.7467 64.963C26.7441 65.8227 27.5066 66.0597 28.0775 66.4914C28.0118 66.1023 28.0055 65.7505 27.8997 65.4264C27.3312 63.7008 27.5125 61.9851 28.0259 60.3025C28.3361 59.2998 28.8419 58.3606 29.2769 57.3927C29.611 56.6511 30.1438 55.9391 30.2594 55.1651C30.3691 54.445 30.7464 54.0669 31.1723 53.621C31.2895 53.5025 31.4039 53.3755 31.4815 53.2369C31.8549 52.5722 32.1746 51.8731 32.5791 51.2313C32.9061 50.7139 33.335 50.2624 33.713 49.7708C33.7445 49.7369 33.7364 49.6688 33.7451 49.6376C33.5835 49.5913 33.4361 49.545 33.1215 49.4496C33.6014 49.0097 33.9813 48.6685 34.3869 48.3048C34.0917 48.2691 33.8817 48.248 33.6745 48.2213C33.8435 48.0009 34.0011 47.7748 34.1758 47.5573C34.2329 47.5009 34.3324 47.4873 34.3867 47.4365C34.5238 47.3068 34.7007 47.1829 34.7557 47.0186C34.9147 46.5797 35.0596 46.1266 35.1363 45.6673C35.2632 44.9133 35.3192 44.1446 35.4376 43.3933C35.5677 42.5769 35.7915 41.7723 35.8648 40.9555C35.9352 40.1586 35.6935 39.3031 35.9084 38.558C36.2163 37.4759 36.1237 36.4113 36.156 35.3389C36.1789 34.4111 36.1193 33.5198 36.1306 32.6289ZM45.534 67.1129C44.9421 67.7451 44.6608 68.6628 43.7186 69.0037C43.9052 68.6926 44.0861 68.3787 44.2726 68.0676C44.2472 68.0476 44.2218 68.0276 44.1935 68.0132C43.8451 68.3064 43.511 68.5995 43.1684 68.8814C43.1261 68.8386 43.0781 68.7929 43.033 68.7416C43.259 68.479 43.4794 68.2135 43.7054 67.9509C43.6715 67.9195 43.6489 67.8938 43.6151 67.8624C43.2298 68.1581 42.8416 68.4596 42.4535 68.761C42.4253 68.7324 42.3942 68.7095 42.3659 68.681C42.6093 68.3703 42.8442 68.0623 43.1305 67.6951C42.2118 67.9055 40.3474 69.0242 39.6466 69.8005C38.4797 71.102 37.3155 72.412 36.1796 73.7363C35.6103 74.3942 35.1059 75.1064 34.6134 75.7392C36.3435 77.0004 38.2717 77.9279 39.8092 79.554C39.7111 78.8923 40.2063 78.7306 40.4497 78.4198C40.7016 78.1063 40.9563 77.8013 41.211 77.4963C41.1629 77.4648 41.1206 77.422 41.0725 77.3905C40.5637 77.9012 40.0521 78.4176 39.5405 78.9339C39.4896 78.8939 39.4331 78.851 39.3851 78.8053C39.9558 77.9204 40.8092 77.2642 41.4846 76.4536C42.1914 75.6092 42.9831 74.8221 43.6107 73.9233C44.2412 73.0331 44.7274 72.0484 45.273 71.1009C45.1938 71.0466 45.1118 70.9837 45.0383 70.9322C43.707 73.9721 41.1553 75.9807 38.9735 78.3263C38.9862 78.1051 39.0134 77.8555 39.145 77.7087C40.0085 76.7801 40.9144 75.8942 41.7752 74.9571C42.3385 74.3531 42.8624 73.7006 43.4031 73.0709C43.3608 73.0281 43.3184 72.9995 43.276 72.9567C42.2897 73.9867 41.309 75.0197 40.3198 76.0554C40.286 76.024 40.2577 75.9955 40.2295 75.967C41.3598 74.6256 42.4845 73.2813 43.612 71.9314C43.5555 71.8885 43.5075 71.8428 43.4595 71.7971C43.1251 72.1329 42.785 72.4658 42.4477 72.8072C42.4393 72.7958 42.4308 72.7844 42.4309 72.7702C43.0589 71.8147 43.6869 70.8592 44.3235 69.9009C44.2839 69.8808 44.2499 69.8636 44.2131 69.8379C44.0592 69.9306 43.8967 70.0262 43.7342 70.1217C44.3796 69.1181 45.1802 68.2572 45.534 67.1129ZM56.2169 91.0514C57.6115 91.4736 58.8999 90.7318 60.3738 90.7459C58.8506 90.0023 57.5431 90.6134 56.2169 91.0514ZM66.0398 96.5354C65.4883 96.6259 64.9305 96.7987 64.3796 96.7899C63.4426 96.7703 62.4885 96.7422 61.5867 96.5271C60.0215 96.1465 58.583 95.4743 57.1538 94.6859C55.6141 93.8486 54.3345 92.7517 53.0552 91.6264C51.9283 90.6354 50.6279 90.1258 49.2439 89.8228C49.087 89.9354 48.919 89.9997 48.7772 89.9705C47.5494 89.6684 46.3273 89.3692 45.1139 89.0246C44.7227 88.9117 44.4723 88.9983 44.1725 89.2378C43.93 89.4208 43.6965 89.516 43.4805 89.5346C43.6367 89.5355 43.7929 89.5364 43.9405 89.5543C45.5583 89.7195 46.9823 90.4342 48.314 91.3583C49.2047 91.9734 50.1096 92.5886 51.0578 93.1048C52.7446 94.0167 54.4458 94.9145 56.1874 95.7047C57.1984 96.1673 58.31 96.4319 59.3815 96.7472C60.8584 97.1756 62.3921 97.156 63.9147 97.1022C64.6334 97.0751 65.3447 96.8805 66.0639 96.7682C66.0644 96.6831 66.0507 96.6121 66.0398 96.5354ZM51.7181 7.29621C52.4586 6.51159 53.1992 5.72697 53.9397 4.94235C53.9172 4.90249 53.8948 4.86264 53.8751 4.83132C52.7519 5.50026 51.6258 6.17486 50.4085 6.90285C51.4844 5.6406 52.9813 5.14687 54.2222 4.28849C52.466 4.89991 50.6595 5.38621 49.1134 6.46702C51.0597 4.97704 53.3506 4.23813 55.6474 3.45953C53.5204 3.89008 51.3904 4.32629 49.2605 4.76251C49.2579 4.7256 49.2411 4.68862 49.2385 4.65172C50.863 4.20128 52.4932 3.75371 54.1888 3.2753C54.0611 3.26039 54.0016 3.23735 53.9448 3.25121C52.5312 3.58084 51.1093 3.87069 49.7068 4.24862C47.192 4.92383 44.7691 5.86629 42.4329 7.03057C41.2307 7.63096 40.0031 8.18297 38.8317 8.83461C37.515 9.56204 36.2152 10.3123 35.1602 11.4356C34.5225 12.1158 33.7943 12.7501 33.0016 13.245C31.0941 14.4344 29.5082 15.9719 28.035 17.6376C27.3857 18.3688 26.7618 19.1201 26.1718 19.9027C25.3241 21.0244 24.4309 22.1373 23.7048 23.3419C22.792 24.8576 22.0066 26.4592 21.2042 28.038C20.8937 28.6349 20.6766 29.2863 20.4141 29.9148C21.1388 29.3854 21.7617 28.7903 22.4325 28.255C24.0767 26.9392 25.735 25.6377 27.4074 24.3505C28.2151 23.728 29.0763 23.1682 29.8783 22.5428C31.0885 21.5906 32.3942 20.8149 33.8262 20.2669C34.128 20.1494 34.509 20.0721 34.4058 20.6816C34.3527 20.9821 34.4557 21.3118 34.4748 21.4425C34.8728 21.3738 35.2941 21.2173 35.6629 21.2903C35.8103 21.3224 35.8437 21.8872 35.9211 22.2112C35.9377 22.2907 35.9457 22.373 35.9707 22.4498C36.2668 23.2403 36.5657 24.0252 36.8842 24.8555C36.9699 24.7709 37.0957 24.6354 37.2243 24.5226C38.7777 23.1893 40.3451 21.8845 41.8618 20.5254C43.6127 18.9435 45.3185 17.3245 47.0355 15.7112C48.2954 14.5351 49.1064 12.9394 50.5442 11.9317C50.6098 11.8867 50.636 11.7932 50.6903 11.7282C52.0417 10.0079 53.2233 8.18723 53.9863 6.11167C54.1278 5.73509 54.3771 5.38465 54.5697 5.01971C54.5358 4.9883 54.4991 4.96256 54.4623 4.93681C53.6049 5.78319 52.739 6.63236 51.8817 7.47874C51.8394 7.42175 51.7773 7.36181 51.7181 7.29621ZM57.2279 5.92581C56.0478 6.16029 54.6065 6.83877 54.479 7.22962C55.3792 6.80344 56.2508 6.39128 57.2279 5.92581ZM68.0612 54.5346C66.6271 54.5122 65.9741 54.9285 65.9805 55.7145C66.6189 55.3549 67.2631 54.9841 68.0612 54.5346ZM68.0306 53.0816C67.6983 53.0911 67.3546 53.0948 66.9769 53.0955C66.8906 53.2652 66.7554 53.5312 66.5657 53.8905C67.1243 53.59 67.5803 53.3373 68.0306 53.0816ZM70.8775 34.0722C70.3757 34.8355 70.1794 35.7821 69.4627 36.3938C69.4061 36.3651 69.3494 36.3364 69.2956 36.3162C69.4517 35.883 69.6164 35.4469 69.7812 34.9825C69.1356 35.5662 68.5244 36.1104 67.9132 36.6545C68.5556 35.6707 69.2966 34.8152 70.0066 33.9226C70.1984 33.6853 70.2856 33.3595 70.4181 33.0708C70.3333 33.0136 70.2542 32.945 70.1693 32.8878C69.9464 33.1164 69.7263 33.3393 69.5033 33.5678C69.2088 33.8811 68.9058 34.183 68.6142 34.4906C67.6897 35.1749 66.7709 35.862 65.8464 36.5463C65.8154 36.5092 65.7758 36.4749 65.7448 36.4379C66.7616 35.53 67.7813 34.6164 68.7952 33.7142C68.4663 33.6329 68.1541 33.6027 67.9289 33.7376C67.4613 34.0131 67.05 34.3881 66.5908 34.7033C66.0403 35.0719 65.4616 35.4119 64.8971 35.7662C64.8774 35.7349 64.852 35.7007 64.8324 35.6694C65.9999 34.7312 67.1532 33.7928 68.3207 32.8546C68.2868 32.8232 68.2615 32.789 68.2361 32.7548C66.953 33.5704 65.667 34.3774 64.3838 35.193C64.3557 35.1503 64.3276 35.1075 64.2966 35.0705C65.6089 34.1274 66.9213 33.1843 68.2252 32.244C68.1885 32.204 68.1604 32.1613 68.1322 32.1186C66.9947 32.8158 65.8599 33.5074 64.7224 34.2046C64.6858 34.1505 64.6521 34.0907 64.6155 34.0366C65.782 33.2544 66.9514 32.4665 68.1265 31.6816C68.1517 31.7299 68.1827 31.7812 68.2079 31.8296C68.1859 31.7188 68.1696 31.5967 68.1368 31.395C66.9749 31.902 65.8472 32.3837 64.728 32.8625C64.7028 32.8141 64.6832 32.7686 64.6579 32.7202C65.8261 32.131 66.98 31.5417 68.2365 30.9047C67.0299 30.8411 66.1303 31.6305 65.028 31.6838C66.0076 31.2694 66.9843 30.8607 67.9639 30.4463C67.9472 30.3951 67.9305 30.344 67.9109 30.2985C66.8982 30.5538 65.8884 30.8176 64.8757 31.0729C64.873 31.0501 64.8618 31.0302 64.8591 31.0075C65.6789 30.7114 66.4959 30.4068 67.3186 30.105C67.3131 30.0737 67.3105 30.0368 67.3021 30.0112C66.3554 30.1648 65.4058 30.3239 64.4193 30.4857C64.6786 30.3539 64.9009 30.2388 65.1288 30.1266C65.1149 30.0697 65.0982 30.0186 65.0929 29.959C63.0488 30.2963 61.0049 30.6054 58.9634 30.9796C57.7635 31.197 56.5886 31.5195 55.4025 31.7936C54.1198 32.0899 52.8261 32.3238 51.5657 32.6883C49.2468 33.3561 46.9224 34.0069 44.665 34.8481C42.5128 35.6503 40.439 36.6486 38.368 37.6413C37.6815 37.9694 36.9549 38.3483 36.5893 39.1237C36.9253 38.9809 37.2163 38.7726 37.5411 38.6099C39.6237 37.5662 41.7177 36.5282 43.8173 35.5073C44.0053 35.4176 44.2691 35.473 44.4991 35.4686C44.51 35.5453 44.5322 35.6277 44.5431 35.7044C42.0875 36.8935 39.6262 38.0798 37.1705 39.2689C37.1929 39.323 37.221 39.3799 37.2462 39.4283C37.5367 39.3051 37.8186 39.1847 38.1119 39.07C38.8891 38.7594 39.6608 38.446 40.4464 38.1611C40.5774 38.1136 40.764 38.2366 40.9256 38.283C40.8196 38.4356 40.7557 38.6594 40.6103 38.7352C39.6586 39.2348 38.6983 39.7373 37.7128 40.1914C37.297 40.3791 37.2498 40.6541 37.2982 41.0913C38.9681 40.1872 40.5697 39.3195 42.1826 38.4575C42.8865 38.0813 43.596 37.708 44.2998 37.3459C45.4794 36.7482 46.6338 36.088 47.8412 35.5756C49.4757 34.8812 51.1355 34.2493 52.8091 33.6601C53.6431 33.3641 54.5244 33.2272 55.3919 33.0194C55.4198 33.1047 55.4505 33.1843 55.4812 33.2639C55.2848 33.3422 55.0995 33.4547 54.8975 33.5018C54.1154 33.6818 53.3195 33.7907 52.5625 34.0333C51.595 34.3399 50.6467 34.7346 49.7043 35.118C48.3974 35.644 47.0849 36.153 45.8201 36.7644C44.6635 37.3168 43.5575 37.966 42.4402 38.5952C41.7989 38.9604 41.0643 39.257 40.5924 39.7793C40.0374 40.4089 39.3625 40.7002 38.6421 40.9968C38.2263 41.1704 37.8329 41.4122 37.4368 41.6171C37.7858 41.673 38.0787 41.6151 38.3771 41.5742C38.6785 41.5277 38.9825 41.5038 39.2838 41.4573C39.3345 41.5257 39.371 41.594 39.4188 41.6681C39.2701 41.8346 39.1523 42.0525 38.9642 42.1564C38.2971 42.5442 37.602 42.8892 36.9181 43.2542C37.2129 43.3325 37.4607 43.2232 37.7049 43.2331C37.952 43.2374 38.2039 43.358 38.4506 43.4332C38.2988 43.6338 38.161 43.8628 37.9894 44.0463C37.7635 44.2947 37.5037 44.5117 37.258 44.743C37.32 44.8171 37.3763 44.8884 37.4327 44.9596C37.715 44.7825 37.9973 44.5911 38.2881 44.4254C38.6045 44.2371 38.9436 44.0602 39.2685 43.8833C38.9315 44.168 38.5917 44.4583 38.2576 44.7515C38.4828 45.0649 38.4559 45.2861 38.0656 45.4655C37.684 45.6421 37.3415 45.8955 36.9196 46.1513C37.5346 46.3563 38.1566 45.4547 38.6335 46.3796C38.0691 46.7055 37.5448 46.9806 37.0486 47.2984C36.5638 47.622 36.1099 47.9968 35.639 48.3488C35.0027 48.8304 34.5668 49.0436 34.5883 49.6878C34.8221 49.5359 35.0133 49.398 35.2185 49.2743C35.9968 48.8077 36.7752 48.3269 37.5703 47.8831C37.8725 47.7089 38.1935 47.6937 38.4353 48.0866C38.3154 48.1824 38.2097 48.2783 38.09 48.3457C37.155 48.8965 36.2172 49.4389 35.2849 49.9982C35.1339 50.0853 34.9768 50.2121 34.9021 50.3592C34.7296 50.6846 34.6138 51.0386 34.4812 51.3415C35.1225 50.9762 35.824 50.5347 36.5506 50.1558C36.884 49.9761 37.2739 49.8535 37.6462 49.8073C37.7826 49.7911 37.957 50.0645 38.1037 50.21C37.9526 50.3113 37.8013 50.4268 37.639 50.494C37.4796 50.5555 37.2753 50.5231 37.1356 50.6018C36.275 51.0622 35.4257 51.5426 34.5734 52.0287C34.5078 52.0737 34.4787 52.187 34.4299 52.269C34.7825 52.1916 35.1098 52.0941 35.3326 51.8798C35.8099 51.4171 36.0846 51.535 36.198 52.0124C36.6813 51.93 37.1107 51.8416 37.5483 51.8072C37.6677 51.7966 37.8001 51.9562 37.9303 52.0364C37.8215 52.1663 37.7408 52.3531 37.6069 52.4205C37.3961 52.5271 37.1319 52.5284 36.9042 52.6123C35.4523 53.1715 34.1463 53.9898 32.9782 55.0274C33.5195 54.7609 34.0327 54.4517 34.5571 54.1482C34.7367 54.0471 35.0192 53.8415 35.0728 53.8901C35.2367 54.0301 35.3089 54.2802 35.4352 54.5221C36.0587 54.2759 36.6589 53.6835 37.438 53.9716C37.4632 54.0342 37.4855 54.1024 37.505 54.1621C36.4194 54.715 35.331 55.2734 34.217 55.8403C34.4317 56.0203 34.5871 56.1488 34.864 56.3746C34.177 56.7736 33.5669 57.1333 32.8315 57.5576C34.1128 57.04 35.2574 56.5811 36.4077 56.1251C36.5244 56.0776 36.6859 56.1381 36.8221 56.1502C36.7674 56.2719 36.7465 56.4392 36.6553 56.4926C36.3303 56.6837 35.9799 56.8548 35.6381 57.0089C34.8605 57.362 34.0859 57.6953 33.2942 58.0483C33.5606 58.5747 33.3889 58.7866 32.9589 58.9743C32.3495 59.2347 31.6719 59.489 31.209 59.9376C30.4975 60.623 29.6738 61.0809 28.7772 61.4021C28.2221 61.5975 28.1575 61.9348 28.1889 62.3635C29.2803 61.7852 30.3658 61.2323 31.4261 60.6312C31.9164 60.353 32.3345 59.7964 32.8406 59.7113C33.648 59.5797 34.3062 59.2373 35.0014 58.878C35.4004 58.6675 35.9045 58.4462 36.1158 59.1511C36.2812 59.0499 36.4181 58.9627 36.5635 58.8727C36.6114 58.9326 36.6622 58.9868 36.7129 59.041C36.0273 59.6755 35.3417 60.3101 34.6561 60.9446C34.6757 60.976 34.704 61.0045 34.7236 61.0358C35.3472 60.7897 35.9707 60.5435 36.5942 60.2974C36.6392 60.3629 36.6928 60.4256 36.7464 60.4883C36.6516 60.6609 36.5905 60.879 36.4507 60.9861C36.2623 61.1325 36.0093 61.168 35.7985 61.2746C33.8239 62.3019 31.8578 63.3264 29.8944 64.3595C29.4898 64.5671 29.0852 64.789 28.7058 65.045C28.586 65.1266 28.5535 65.3308 28.4844 65.4808C28.6063 65.507 28.7506 65.6015 28.836 65.5594C29.4627 65.265 30.1006 64.9906 30.6879 64.6335C31.3664 64.2231 31.9776 63.6931 32.6674 63.2885C33.4057 62.8585 34.1822 62.2273 34.9576 62.2147C35.8637 62.1972 36.4887 61.7098 37.2428 61.4729C38.2104 61.1663 39.1588 60.7432 40.151 60.5701C40.9812 60.4358 41.8198 60.747 42.3176 61.5188C42.9139 62.4331 42.9558 63.4435 42.566 64.4486C42.1301 65.5584 41.6489 66.6595 41.2048 67.7153C42.7622 67.1028 44.2229 66.0498 45.9776 65.6796C46.0345 65.6657 46.0746 65.6007 46.126 65.5698C47.9529 64.5388 49.7181 63.4053 51.6095 62.5137C53.2873 61.7203 55.0632 61.126 56.8389 60.5743C58.3016 60.1201 59.8393 59.9103 61.3158 59.513C62.1579 59.2851 63.0391 59.1624 63.6126 58.286C64.6652 56.6633 65.4375 54.9056 66.1502 53.1248C66.6985 51.7517 67.0543 50.2953 67.631 48.9224C68.2077 47.5494 68.413 46.0666 68.9559 44.6623C68.8344 44.5651 68.6875 44.4337 68.4841 44.2595C68.7354 44.0453 68.9608 43.882 69.141 43.6815C69.2754 43.5291 69.4989 43.2296 69.4369 43.1413C69.1895 42.7454 69.5145 42.5543 69.6384 42.2684C70.3126 40.7599 70.8251 39.205 70.62 37.507C70.6148 37.4332 70.6153 37.3481 70.6413 37.2829C70.8203 36.8186 71.0022 36.3628 71.1812 35.8985C71.116 35.8726 71.0537 35.841 70.9915 35.8094C70.628 36.2443 70.2731 36.6765 69.9097 37.1114C70.1154 36.0201 71.0179 35.2251 70.8775 34.0722ZM97.4882 6.77625C97.65 6.34587 97.8551 5.80223 98.063 5.25294C98.0121 5.22711 97.964 5.19562 97.913 5.1698C97.5927 5.51983 97.2667 5.88118 96.8406 6.34127C96.8627 5.98954 96.8783 5.76263 96.8823 5.58672C96.6094 5.63341 96.3308 5.67722 96.0351 5.72662C96.0816 5.99928 96.1197 6.26055 96.1582 6.46507C96.6431 6.57566 97.0317 6.66583 97.4882 6.77625ZM97.9646 48.5558C97.8435 48.4019 97.7196 48.2394 97.5985 48.0713C97.1478 48.3837 96.7057 48.6792 96.2236 49.0112C96.37 49.2135 96.5052 49.3959 96.646 49.5953C97.114 49.2348 97.5365 48.8939 97.9646 48.5558ZM94.7386 28.3541C94.6652 28.2885 94.5974 28.2257 94.524 28.16C94.2236 28.513 93.9175 28.8631 93.6142 29.2217C93.6621 29.2674 93.7187 29.3103 93.7667 29.3559C94.0925 29.023 94.4184 28.69 94.7386 28.3541ZM95.9522 42.5543C96.3799 41.8389 96.7501 41.2224 97.1176 40.5974C96.5296 41.0679 95.6502 41.3552 95.9522 42.5543ZM96.2112 40.2234C96.673 39.4967 97.8831 39.4696 97.9157 38.3546C97.4228 39.0442 96.2665 39.1199 96.2112 40.2234ZM95.4451 23.5315C95.3659 23.4772 95.2726 23.4227 95.1934 23.3684C94.9639 23.7359 94.7372 24.0979 94.5049 24.4569C94.5926 24.5085 94.6774 24.5657 94.7623 24.6229C94.9889 24.261 95.2185 23.8935 95.4451 23.5315ZM94.5876 27.5304C95.3233 27.0636 95.9171 26.5817 96.0534 25.683C95.1513 25.973 94.826 26.6692 94.5876 27.5304ZM95.0002 22.936C95.702 22.4235 95.6993 22.415 95.9871 20.9099C95.132 21.4016 95.2719 22.1771 95.0002 22.936ZM96.9204 23.7669C96.8582 23.7212 96.796 23.6754 96.7367 23.624C95.6019 24.3298 95.5104 24.4399 95.6385 25.2806C96.0648 24.7779 96.4855 24.2724 96.9204 23.7669ZM94.4295 14.8401C95.4369 13.6285 96.3566 12.3512 97.2933 11.0967C97.4164 10.9385 97.4744 10.7402 97.5636 10.5648C97.5014 10.519 97.4392 10.4733 97.3799 10.4219C96.9537 10.8961 96.4909 11.3305 96.1298 11.8449C95.7142 12.4384 95.4174 13.1205 95.0104 13.7112C94.7925 14.0278 94.4614 14.287 94.1363 14.5065C93.9309 14.6443 93.6298 14.6483 93.3878 14.7462C93.3394 14.7715 93.3553 14.9503 93.3404 15.0638C93.7015 14.9977 94.2378 15.0632 94.4295 14.8401ZM97.2227 21.7852C96.8557 22.3251 96.0594 22.505 95.9543 23.3982C96.6586 22.9511 97.5115 22.8141 97.2227 21.7852ZM96.1431 10.6418C96.6553 10.0403 97.0572 9.36162 97.5325 8.74858C97.69 8.55085 98.0509 8.51318 98.3157 8.39835C98.1948 8.66439 98.0823 8.92764 97.9614 9.19368C97.9441 9.22763 97.9467 9.26453 97.8912 9.51392C98.293 9.29771 98.5609 9.14885 98.9485 8.93256C98.8657 9.44568 98.7892 9.87655 98.6947 10.4407C99.3438 10.1862 99.3438 10.1862 100.442 11.1912C100.082 9.79878 99.7409 8.48023 99.3582 7.01957C99.2069 7.59756 99.102 8.01408 98.9943 8.42207C98.9489 8.4133 98.8979 8.40166 98.8611 8.3901C98.8414 7.46212 98.8274 6.53701 98.8105 5.61755C98.7537 5.61723 98.7054 5.61412 98.6515 5.60814C98.6019 5.81783 98.5607 6.03892 98.4998 6.24288C98.3779 6.65079 98.2533 7.05017 98.1059 7.45226C98.0885 7.5004 97.9267 7.49664 97.8385 7.516C97.8415 7.49616 97.8473 7.47065 97.8503 7.45081C97.6137 7.59417 97.3741 7.7432 97.2287 7.83317C97.3409 8.95747 96.2943 9.62968 96.1431 10.6418ZM96.3502 12.9102C95.7064 13.6726 95.0682 14.438 94.4044 15.2259C95.446 16.2164 95.5115 17.5306 95.6539 18.8196C95.8441 18.8377 96.0172 18.8614 96.2186 18.8852C96.2069 18.5021 96.2006 18.1502 96.1971 17.8069C96.1897 17.1769 96.1897 17.1769 96.661 17.2023C96.8075 18.7354 96.7552 20.2531 96.2806 21.6493C96.6283 21.4697 96.9816 21.2788 97.3379 21.0822C97.4114 21.1337 97.4764 21.188 97.5414 21.2422C97.6701 20.2044 97.7959 19.1723 97.9416 18.1431C97.9654 17.9702 98.1197 17.8206 98.2144 17.6623C98.288 17.6996 98.3645 17.7312 98.4352 17.7742C98.1304 20.6157 97.4483 23.3727 96.4917 25.9834C96.6584 26.1178 96.8651 26.2154 96.8645 26.3147C96.8607 26.4622 96.7432 26.6375 96.6232 26.7475C96.169 27.1649 95.5594 27.4536 95.421 28.2303C95.7027 28.1525 95.9781 28.1569 96.1181 28.0215C96.684 27.4686 97.3008 26.9273 97.7395 26.2743C98.1323 25.6835 98.5618 25.1326 98.7628 24.3449C99.1385 22.863 99.2018 21.3936 99.234 19.9012C99.2422 19.4927 99.2931 19.0843 99.3269 18.6816C99.4291 18.6907 99.5313 18.6998 99.6335 18.7089C99.675 20.6727 99.8953 22.6489 99.0138 24.6216C100.25 23.9959 100.66 23.0363 100.608 21.8357C100.588 21.3702 100.494 20.8958 100.469 20.4275C100.464 20.2828 100.567 20.1358 100.619 19.9914C100.724 20.1083 100.893 20.2086 100.918 20.3421C101.168 21.6431 101.194 22.923 100.293 23.9394C100.68 24.3275 101.03 24.6756 101.411 25.0609C102.136 21.379 101.99 17.854 100.137 14.5519C100.146 14.884 100.164 15.2416 100.144 15.6019C100.125 15.9196 100.064 16.237 100.025 16.5518C99.9511 16.5428 99.8773 16.5339 99.8035 16.525C99.7468 15.6138 99.6674 14.7053 99.6419 13.7887C99.5823 11.5524 99.5965 11.5524 99.0909 11.1041C99.1117 12.7585 99.1359 14.3079 99.1543 15.897C99.1401 15.8969 98.9212 15.9354 98.9185 15.9127C98.7796 15.4153 98.6635 14.9153 98.5361 14.3953C98.1239 15.8089 98.1239 15.8089 97.7393 15.9911C98.0017 14.4802 98.2494 13.0402 98.4943 11.5916C98.4348 11.5685 98.3724 11.5512 98.3129 11.5281C97.5362 12.6502 97.632 14.1149 97.0025 15.2974C96.9357 13.7477 97.2885 12.2969 98.1263 10.9567C97.8722 10.7141 97.6647 10.7441 97.566 11.0784C97.4936 11.305 97.5373 11.5691 97.4338 11.7728C96.7756 13.0119 96.1005 14.2282 95.4338 15.4559C95.3606 14.4652 96.1145 13.8083 96.3502 12.9102ZM92.7209 3.91161C93.5932 3.84848 94.4712 3.78821 95.3463 3.71941C95.3438 3.66832 95.3413 3.61723 95.3444 3.56901C94.9753 3.55272 94.6091 3.53078 94.1776 3.5113C94.3201 3.42698 94.4056 3.3849 94.4768 3.34275C94.4656 3.32282 94.4572 3.31142 94.4403 3.28863C93.857 3.45556 93.2652 3.62528 92.6791 3.78369C92.6987 3.8292 92.7127 3.87184 92.7209 3.91161ZM94.6785 5.13153C95.1442 5.13986 95.6793 4.95563 96.0193 5.53358C96.4704 5.15024 96.9102 4.77535 97.4984 4.27645C96.49 4.29909 95.6748 4.31999 94.8596 4.34089C94.7999 4.34623 94.7288 4.36001 94.675 4.33984C94.1114 4.08977 93.7585 4.20978 93.4483 4.74998C93.3852 4.86029 93.2001 4.93017 93.0579 4.95774C92.8702 5.00491 92.6686 4.99525 92.4697 5.00831C92.4696 5.03668 92.4637 5.06218 92.4635 5.09056C92.5486 5.11942 92.6363 5.17099 92.7243 5.16582C93.3776 5.15535 94.0282 5.12216 94.6785 5.13153ZM72.1817 31.7302C72.5819 32.2177 73.7293 31.7673 74.5874 30.8075C73.7247 31.1459 72.9675 31.431 72.1817 31.7302ZM80.1005 59.3843C79.8567 59.7518 79.6388 60.0825 79.418 60.4189L79.4151 60.4246C78.4074 61.2446 77.4166 62.0874 76.3976 62.8874C75.6612 63.4678 74.8826 63.9911 74.1265 64.5401C74.0729 64.4774 74.0279 64.4119 73.98 64.352C75.3043 63.3154 76.6344 62.2674 77.9702 61.2222C77.9533 61.1994 77.9364 61.1767 77.9195 61.1539C76.7631 61.6779 75.6068 62.2019 74.4475 62.7316C74.411 62.6633 74.3802 62.5979 74.3437 62.5296C76.0163 61.6623 77.8266 61.0143 79.2562 59.5043C77.6829 60.3864 76.1791 61.0617 74.6054 61.5663C75.5463 60.99 76.5403 60.5331 77.5176 60.0393C78.1245 59.7277 78.816 59.5018 79.2525 58.741C77.6008 59.4552 76.0629 60.1275 74.3656 60.8612C74.8672 60.1405 75.5836 60.0339 76.1733 59.7422C76.82 59.4224 77.475 59.1424 78.1301 58.8481C78.1302 58.8198 78.1333 58.7857 78.1307 58.7488C77.0029 58.7963 75.8723 58.8353 74.7531 58.88C74.7506 58.8289 74.7452 58.7835 74.7427 58.7324C76.007 58.6403 77.2629 58.5509 78.5216 58.456C76.9745 58.3478 75.4351 58.3646 73.8902 58.3643C72.2912 58.3723 70.717 58.4995 69.1356 58.8651C67.085 59.3415 64.9597 59.4883 62.8952 59.9078C61.1179 60.2666 59.3821 60.81 57.6213 61.2484C56.6229 61.5037 55.5742 61.6056 54.6177 61.9747C52.8241 62.6597 51.0165 63.3304 49.3823 64.4022C48.3357 65.0886 47.2386 65.6783 46.3206 66.2235C46.3991 67.288 46.5498 68.1543 46.4989 69.011C46.4452 69.8733 46.1927 70.7203 46.034 71.5649C47.1089 71.3412 47.1089 71.3412 47.3327 71.8816C46.6834 72.1645 45.7336 71.9179 45.4712 72.9805C45.8213 72.8661 46.1288 72.7374 46.4388 72.6739C46.6151 72.6351 46.9189 72.6397 46.978 72.7337C47.0707 72.8874 47.0152 73.1368 47.0192 73.3951C46.0243 73.0971 45.0265 73.7015 44.7278 74.6674C45.2091 74.463 45.6959 74.2757 46.1687 74.0599C46.7412 73.8021 46.795 73.8223 46.9082 74.328C46.1674 74.7068 45.4852 75.2506 44.7318 75.3882C43.9299 75.5368 43.9121 76.1042 43.6369 76.5198C44.3915 76.1978 45.1462 75.8616 45.9122 75.5453C46.3479 75.3605 46.5569 75.5376 46.5462 75.8809C45.7432 76.2282 45.0141 76.5418 44.2908 76.8583C44.3188 76.9152 44.3354 76.9806 44.3635 77.0375C45.0945 76.8601 45.8311 76.6855 46.5906 76.5082C46.6599 76.764 46.7072 76.9232 46.7183 76.9573C45.5285 77.3932 44.4069 77.8067 43.2767 78.2231C43.2232 78.1604 43.1809 78.1034 43.133 78.0435C43.3562 77.7866 43.5822 77.524 43.7825 77.2981C43.1544 77.357 43.1573 77.3513 42.8012 77.9678C42.6893 78.1602 42.549 78.3381 42.403 78.5132C41.9507 79.081 41.4956 79.6402 41.0433 80.208C41.0798 80.2763 41.1191 80.339 41.1556 80.4073C41.778 80.3456 42.3974 80.3037 43.017 80.2192C43.2984 80.184 43.5717 80.0805 43.8477 79.9998C44.7184 79.7437 45.6283 79.5644 46.4401 79.186C47.1664 78.8496 47.7581 78.2458 48.4453 77.8184C50.6237 76.4602 52.8106 75.0993 55.0227 73.801C56.0518 73.1911 57.1567 72.7121 58.2392 72.1934C59.5809 71.5569 60.9255 70.9147 62.2867 70.3238C63.312 69.8756 64.3708 69.5014 65.4212 69.1158C67.5449 68.3277 69.6771 67.5368 71.8034 66.7714C71.977 66.71 72.2037 66.7964 72.4081 66.8146C70.9158 67.4672 69.4528 67.964 68.001 68.509C65.715 69.3643 63.415 70.2053 61.1653 71.1573C59.3741 71.9217 57.6078 72.7913 55.8866 73.7122C54.4903 74.4562 53.15 75.3141 51.8239 76.1861C50.3038 77.1877 48.6206 77.9357 47.2411 79.165C47.1698 79.2214 47.0448 79.215 46.9565 79.2627C46.8682 79.3104 46.8023 79.398 46.7337 79.4629C46.5453 79.6094 46.385 79.8128 46.1772 79.8854C45.1812 80.206 44.1627 80.4868 43.1554 80.7875C43.1747 80.8756 43.1912 80.9693 43.2105 81.0574C43.6926 80.7253 44.212 80.768 44.7208 80.7056C45.6388 80.5945 46.5355 80.2591 47.4235 79.9549C47.805 79.8208 48.0035 79.8645 48.1398 80.3108C46.8306 80.7574 45.5185 81.2096 44.2121 81.6505C44.2259 81.7073 44.237 81.7556 44.2623 81.804C45.9904 81.584 47.5438 80.699 49.2507 80.2405C49.2972 80.5274 49.3355 80.7461 49.3656 80.9392C49.8209 80.7857 50.2734 80.6379 50.7288 80.4844C50.7737 80.5641 50.813 80.641 50.8552 80.7122C50.2406 81.3329 49.3474 81.5633 48.6455 82.0758C49.3993 81.8814 50.1252 81.616 50.8621 81.4131C51.0698 81.3547 51.3305 81.4441 51.5575 81.4738C51.42 81.6603 51.3163 81.8923 51.1421 82.0389C51.0194 82.1404 50.8092 82.1335 50.63 82.1779C51.0217 82.2198 51.4652 82.1457 51.7282 82.3288C52.0024 82.5177 52.1752 82.5981 52.4993 82.5347C53.4406 82.3357 54.3903 82.1624 55.3398 82.0174C57.1535 81.7411 58.9589 81.4251 60.7776 81.251C62.4912 81.0876 64.2259 81.1628 65.9395 80.9994C68.625 80.7309 71.3181 80.6157 74.015 80.7871C74.7474 80.831 75.2579 80.4991 75.6108 79.9308C76.2795 78.8393 76.9282 77.7449 77.5459 76.6276C77.9883 75.8412 78.3853 75.032 78.771 74.217C78.8401 74.0812 78.7448 73.8763 78.7657 73.709C78.7897 73.5077 78.7972 73.2268 78.92 73.1254C79.4566 72.7 79.5767 72.1133 79.68 71.5038C79.6979 71.3705 79.7045 71.2315 79.7422 71.1012C79.9483 70.4015 80.1571 69.7104 80.3689 69.0135C80.0056 69.4201 79.7924 69.8956 79.5114 70.3224C79.2419 70.7267 78.8931 71.0907 78.5812 71.4663C79.6889 69.2026 80.6545 66.9665 80.9808 64.3209C80.4065 65.325 79.9605 66.2304 79.3931 67.0387C78.8543 67.8046 78.7201 68.8112 78.0654 69.497C77.9664 69.4397 77.873 69.3852 77.774 69.3279C78.8496 67.1974 79.9282 65.0612 81.0067 62.925C79.7101 64.5095 78.4251 66.0713 77.1486 67.6304C77.1005 67.5989 77.0496 67.5589 77.0044 67.5217C77.6548 65.7236 79.4252 64.6639 80.1577 62.9003C78.5777 64.398 77.0373 65.9159 75.2712 67.1912C75.2352 67.052 75.2359 66.9385 75.2874 66.8792C75.7563 66.391 76.2506 65.9227 76.7166 65.4402C77.5571 64.5568 78.7791 63.9878 79.0603 62.6359C79.075 62.5508 79.1522 62.469 79.2039 62.3813C79.5371 61.7958 79.9354 61.2363 80.1722 60.6162C80.2967 60.2452 80.5412 59.75 80.1005 59.3843ZM80.4693 71.9822C80.9146 71.6385 81.3199 71.3173 81.728 71.0047C80.5439 71.4151 80.5439 71.4151 80.4693 71.9822ZM85.142 80.3567C85.5396 79.9107 85.8581 79.396 86.2076 78.9185C85.6133 79.0371 85.1321 79.2415 84.6704 79.4914C83.408 80.1681 82.1798 80.8194 80.7379 81.1347C79.0828 81.4913 77.4152 81.5641 75.7507 81.6171C73.9611 81.6778 72.1616 81.5058 70.3693 81.5439C68.8781 81.578 67.3944 81.7653 65.9027 81.8703C63.3598 82.0545 60.8031 82.1535 58.271 82.4143C56.4153 82.6052 54.5753 82.9891 52.7387 83.3107C50.4272 83.7118 48.1319 83.8009 45.8526 83.158C44.2424 82.6977 42.7139 81.8945 40.9458 82.1512C40.0475 82.2794 39.1416 82.2686 38.3516 82.7862C37.3735 83.4219 36.3811 84.0575 35.4002 84.6847C35.3289 84.7269 35.2098 84.695 35.1273 84.7172C34.8941 84.7698 34.6412 84.7911 34.4474 84.9063C33.1503 85.6793 31.856 86.4607 30.5729 87.2621C29.3097 88.0523 27.9677 88.7455 26.8343 89.6868C24.9985 91.2114 23.3065 92.9015 21.5525 94.5174C21.2611 94.7825 20.9641 95.0447 20.6727 95.3098C20.5943 95.1277 20.5892 95.0397 20.6351 94.9775C21.9698 92.7435 23.8354 90.992 25.8842 89.4686C27.7647 88.0662 29.7888 86.8576 31.7846 85.6204C33.5781 84.5013 35.4222 83.4505 37.2213 82.3343C37.8971 81.9153 38.5166 81.4109 39.1332 80.9122C39.2531 80.8164 39.3457 80.536 39.2869 80.3995C38.974 79.5862 38.4068 79.0069 37.6142 78.6052C37.0027 78.2952 36.3601 77.9624 35.9117 77.4718C35.5252 77.0553 35.1232 76.8658 34.6184 76.7523C33.5066 76.5161 32.6706 75.7793 32.6396 74.8455C32.6108 74.0055 32.1452 73.5346 31.5833 73.015C30.8295 72.3127 30.093 71.5622 29.519 70.7162C28.8128 69.668 28.2806 68.5016 27.6743 67.383C26.9396 67.6938 26.4621 68.199 26.2674 68.8902C25.9711 69.9356 25.8732 71.053 25.489 72.061C24.8825 73.6607 24.2841 75.3144 23.3634 76.7478C21.4245 79.7502 19.0363 82.4039 16.4249 84.8662C15.0335 86.1749 13.7352 87.5948 12.3833 88.952C11.5715 89.7645 10.7344 90.5571 9.77708 91.4881C9.8444 91.1735 9.82561 91.0003 9.90578 90.8986C10.2867 90.4013 10.6788 89.9099 11.1021 89.4412C12.0431 88.4024 13.001 87.3721 13.9532 86.3532C15.929 84.2448 17.9613 82.1935 19.8778 80.0337C20.9847 78.7943 21.9929 77.4551 22.9133 76.0784C24.3755 73.8877 24.8547 71.3196 25.3365 68.8026C25.6184 67.3372 25.1846 65.8791 24.7363 64.4635C24.6389 64.1508 24.7012 63.734 24.5095 63.5088C23.9429 62.8444 23.642 61.9233 22.724 61.5861C22.6446 61.5601 22.5886 61.4321 22.5608 61.3327C22.3998 60.7529 22.0521 60.4984 21.4144 60.7444C21.363 60.327 21.4791 59.9446 21.0125 59.6299C19.6748 58.7313 18.4375 57.6914 17.5374 56.3101C17.2365 55.8515 16.867 55.4436 16.4162 54.8736C16.5638 55.3398 16.59 55.6804 16.759 55.9084C17.643 57.125 18.3445 58.4768 19.454 59.516C20.0187 60.0442 20.5776 60.5836 21.0966 61.1456C21.2009 61.2625 21.1311 61.526 21.144 61.7247C20.9966 61.6785 20.7978 61.6773 20.7019 61.586C19.8779 60.7414 19.0483 59.8939 18.2531 59.0069C17.8244 58.5335 17.4757 57.9867 17.087 57.4765C17.0234 57.6578 17.0596 57.7687 17.1243 57.8655C18.032 59.3859 18.9852 60.8867 19.8444 62.4465C20.667 63.9523 21.4296 65.5059 21.532 67.2799C21.5831 68.174 21.6825 69.0713 21.6456 69.9564C21.5827 71.3691 20.5548 72.2429 19.6855 73.1828C19.6054 73.2703 19.2986 73.2856 19.2394 73.22C19.1153 73.0718 18.9892 72.8157 19.0327 72.6598C19.1111 72.3936 19.2972 72.1534 19.4719 71.9359C20.1187 71.1536 20.4733 68.5224 20.0137 67.5494C19.8997 68.0538 19.854 68.5501 19.6807 69.0031C18.9849 70.7925 18.173 72.5443 17.5565 74.3596C16.5438 77.3191 14.8379 79.849 12.9029 82.2413C10.7962 84.8455 8.64985 87.4155 6.48378 89.9683C5.00729 91.7106 3.47428 93.4101 1.92993 95.1038C1.59247 95.4736 1.30632 95.8125 1.32573 96.3347C1.38495 97.7453 1.8626 99.005 2.59684 100.11C2.76265 99.938 2.87445 99.7741 3.03424 99.6558C3.21398 99.5263 3.48126 99.4768 3.63278 99.3187C4.74781 98.1475 5.84306 96.9591 6.96097 95.7822C7.06109 95.6693 7.2233 95.6163 7.49705 95.4419C7.4159 95.6997 7.40682 95.7876 7.36386 95.8441C6.29062 97.1433 5.18629 98.4195 4.14981 99.7444C3.76327 100.239 3.32497 100.835 3.28156 101.411C3.23815 101.987 3.55755 102.675 3.91217 103.182C5.70544 105.678 7.68726 107.999 10.5299 109.383C11.6652 109.937 12.7794 110.238 13.8508 109.223C14.1108 108.978 14.4524 108.866 14.4552 108.412C14.4593 108.222 14.6622 108.019 14.8109 107.852C15.5692 106.963 16.3585 106.096 17.1026 105.192C18.9745 102.91 21.2864 101.093 23.477 99.1507C25.6504 97.2279 27.9648 95.4761 30.4959 94.0263C31.8385 93.248 33.1277 92.3785 34.5068 91.6685C35.6665 91.0678 36.9019 90.6123 38.1233 90.1426C38.6557 89.9356 39.2132 89.7913 39.7732 89.7122C40.3076 89.6414 40.861 89.7013 41.3979 89.6817C42.037 89.6569 42.688 89.567 43.3214 89.5536C42.9894 89.5063 42.7413 89.224 42.6819 88.7384C42.0592 88.8427 41.4392 88.9839 40.8112 89.0427C38.2424 89.2636 35.9185 90.2776 33.5892 91.2603C32.752 91.6187 32.0043 92.1792 31.1532 92.495C29.5391 93.093 28.1751 94.1096 26.8171 95.0865C25.1082 96.3054 23.5316 97.7124 21.9156 99.0567C20.4881 100.24 19.0238 101.398 17.6838 102.676C16.698 103.621 15.8927 104.757 14.9831 105.79C14.4624 106.38 13.9023 106.936 13.3533 107.512C14.0502 106.449 14.8034 105.457 15.6103 104.514C16.3313 103.67 17.0524 102.811 17.8722 102.067C19.5061 100.589 21.2189 99.1946 22.9008 97.7627C23.9088 96.9001 24.9026 96.0233 25.9304 95.1779C26.4528 94.7524 27.0456 94.4267 27.5794 94.0069C29.7342 92.3308 32.0378 90.9365 34.5805 89.8983C36.286 89.2043 37.9657 88.5612 39.8047 88.3191C41.0583 88.1503 42.2655 87.6663 43.5133 87.4946C44.9687 87.2929 46.4371 87.2757 47.9032 87.1791C48.0424 87.1714 48.1813 87.2062 48.3232 87.2212C48.7347 87.2661 49.1432 87.3451 49.5606 87.3503C49.9866 87.3527 50.4074 87.2813 50.8422 87.2384C50.8247 87.7632 50.6081 87.8812 50.2333 87.862C49.8699 87.8486 49.5061 87.8919 49.1367 87.9182C49.9458 87.9654 50.7274 87.8705 51.5232 87.7757C51.6682 87.7567 51.822 87.6923 51.9524 87.7299C52.0572 87.7617 52.1302 87.8983 52.2233 87.9953C52.132 88.0629 52.0547 88.159 51.9608 88.1896C51.6877 88.2647 51.4033 88.3198 51.1161 88.3806C51.1299 88.4516 51.1323 88.5169 51.1375 88.5907C52.099 88.7863 53.0447 88.3405 54.0299 88.3915C54.012 88.5248 54.0055 88.6638 53.999 88.7886C53.3106 88.9663 52.6392 89.1384 51.9594 89.3133C53.3651 89.7696 54.7999 89.2301 56.2107 89.3403C56.216 89.3999 56.2184 89.4652 56.2181 89.5219C55.4924 89.759 54.7724 89.9848 54.0808 90.2107C54.558 90.6589 55.1442 90.4721 55.7157 90.3703C56.3014 90.2687 56.8813 90.1784 57.4556 90.0851C57.4304 90.0226 57.3801 89.8974 57.2512 89.6186C60.4423 90.2468 63.5235 90.7127 66.6709 90.6143C69.8636 90.5246 72.8065 89.5397 75.7166 88.339C75.7389 88.4072 75.7611 88.4754 75.7834 88.5436C75.2049 88.8553 74.6546 89.2097 74.0565 89.4759C72.2053 90.2882 70.265 90.8277 68.2701 91.0263C66.6588 91.1845 65.0125 91.0333 63.3853 91.0127C63.2433 91.0119 62.9823 90.965 62.9793 90.999C62.7964 91.6251 62.216 91.338 61.8288 91.4976C61.1881 91.7635 60.5166 91.964 59.8534 92.19C59.8588 92.2355 59.8699 92.2838 59.8725 92.3207C60.1759 92.3962 60.4821 92.466 60.6098 92.4951C61.8349 91.4295 63.354 91.929 64.5959 91.3487C64.5745 91.587 64.4995 91.7766 64.3656 91.8298C63.6653 92.1011 62.9481 92.3353 62.245 92.5839C63.889 92.6556 65.3282 91.8551 67.0279 91.6492C66.879 91.8441 66.7243 92.0504 66.5925 92.2255C67.0704 92.1119 67.6136 91.9816 68.2223 91.8347C68.221 92.0475 68.2226 92.2405 68.224 92.476C71.6187 91.8767 74.7197 90.5806 77.7596 89.0685C80.4348 87.7415 84.4667 83.4089 85.057 82.1212C84.5489 82.5326 84.1432 82.9105 83.6898 83.2002C83.5187 83.3127 83.2266 83.2429 82.9937 83.253C83.0121 83.0346 82.9458 82.7448 83.0659 82.6064C83.7383 81.8157 84.467 81.1105 85.142 80.3567ZM75.9308 7.4992C75.4213 7.67507 74.909 7.8424 74.3427 8.03213C75.0259 8.22897 75.7147 7.98035 75.9308 7.4992ZM72.2873 2.08719C73.5922 1.87328 74.8914 1.65651 76.1878 1.44539C76.185 1.43687 76.1879 1.43121 76.1851 1.42268C74.6449 1.56714 73.1047 1.71161 71.4537 1.86395C71.6105 1.76553 71.6647 1.72895 71.7816 1.65301C70.9574 1.74763 70.2185 1.82855 69.4825 1.90382C69.4801 1.82435 69.4721 1.74202 69.4698 1.66256C71.0128 1.52662 72.5529 1.39634 74.0988 1.25475C68.9096 1.33589 62.3997 2.32037 61.1532 3.17588C61.7506 3.02322 62.2172 2.88967 62.6865 2.77884C63.4289 2.59295 64.1572 2.39279 64.9021 2.25799C65.0556 2.23616 65.2532 2.43591 65.4315 2.5334C65.3341 2.66905 65.2503 2.8899 65.1194 2.9232C64.5676 3.05627 63.9657 3.03582 63.4616 3.25712C62.7895 3.55691 61.8852 3.29071 61.4228 4.10245C61.3711 4.19012 61.2091 4.21473 61.0981 4.25099C60.6458 4.37043 60.171 4.45002 59.741 4.6235C59.3054 4.79411 58.8977 5.05 58.4788 5.27178C59.5451 5.06504 60.5355 4.74152 61.5453 4.49188C63.6161 3.97589 65.7008 3.50253 67.7855 3.02917C67.9533 2.99324 68.1544 3.08802 68.3302 3.12023C68.327 3.18264 68.3124 3.23931 68.3092 3.30172C67.9791 3.40483 67.6545 3.53918 67.3248 3.58554C66.58 3.69197 65.8159 3.71032 65.0795 3.84234C62.6086 4.30498 60.1848 4.95517 57.861 5.95495C57.6959 6.02779 57.439 6.22495 57.4554 6.33287C57.5317 6.84122 57.2246 6.89906 56.8578 6.96224C56.7327 6.98423 56.6269 7.09429 56.587 7.11676C56.7791 7.28527 56.9542 7.43098 57.1265 7.58235C57.0037 7.69799 56.9031 7.88185 56.7607 7.93779C56.0775 8.20347 55.3746 8.42364 54.6941 8.69784C54.2129 8.88806 53.7485 9.12944 53.2699 9.35656C53.2951 9.40494 53.3204 9.45332 53.3457 9.50171C53.7812 9.34528 54.2391 9.2429 54.6522 9.03243C55.9429 8.37012 57.4229 8.31611 58.7503 7.69374C59.8926 7.15543 61.1861 6.93579 62.4181 6.58527C62.3437 6.67564 62.2804 6.80013 62.1894 6.82515C61.2048 7.12317 60.201 7.33311 59.2501 7.70509C57.9916 8.20585 56.7778 8.82887 55.5558 9.39794C55.5725 9.4633 55.5863 9.52012 55.6029 9.58548C55.8696 9.63524 56.1277 9.68778 56.3943 9.73754C56.2832 9.80217 56.1805 9.86401 55.9753 9.98769C56.7969 9.85616 57.4709 9.70677 58.1643 9.63126C59.9178 9.44545 61.4958 8.70816 63.096 8.06747C63.8306 7.77087 64.6101 7.55398 65.3753 7.36538C65.5545 7.321 65.786 7.53797 65.9898 7.64128C64.3643 7.79945 62.9522 8.3504 61.5566 8.98091C62.2099 8.95625 62.8715 8.98555 63.4973 8.83305C65.9576 8.23698 68.4393 7.86519 70.9862 7.96764C71.4944 7.9904 72.0564 8.04751 72.4237 7.43669C72.8141 6.79479 73.3317 6.22456 73.8097 5.63424C73.9672 5.4365 74.2662 5.31052 74.0013 4.97702C73.9731 4.94849 74.1107 4.7478 74.2078 4.66891C74.4133 4.50266 74.6329 4.36487 74.8326 4.22413C74.6632 4.05292 74.4967 3.89023 74.4007 3.79888C74.1221 3.8427 73.889 3.8811 73.6615 3.92237C73.6393 3.85414 73.6254 3.79731 73.6031 3.72908C74.0811 3.15295 74.8176 3.00675 75.4725 2.72672C76.1475 2.43546 76.8252 2.15272 77.4972 1.86712C77.4834 1.81029 77.4696 1.75346 77.4529 1.68811C75.4706 2.128 73.4827 2.56501 71.5431 2.99096C73.0287 2.05735 74.9211 2.35471 76.4857 1.48965C75.087 1.72005 73.6968 1.94765 72.298 2.17805C72.301 2.1582 72.2927 2.11843 72.2873 2.08719ZM77.7002 16.4446C78.4186 15.5634 79.0891 14.6365 79.8696 13.8152C80.41 13.2423 80.0878 12.9936 79.6724 12.6621C78.449 13.4581 78.1373 15.1362 76.54 15.7854C77.4734 14.5791 78.2952 13.5225 79.1142 12.4574C77.7885 13.7069 76.4431 14.9393 74.7741 15.6874C76.0651 14.5342 77.3732 13.3754 78.6756 12.2138C78.6221 12.1368 78.5714 12.0684 78.5151 11.9972C77.0443 12.8316 75.7027 13.9164 74.0438 14.4063C75.0303 13.7962 76.0254 13.1833 77.0119 12.5732C76.9811 12.5077 76.9474 12.4479 76.9222 12.3854C75.7467 12.793 74.5712 13.2006 73.39 13.6053C73.3732 13.5683 73.3593 13.5257 73.3425 13.4887C75.0196 12.7945 76.6911 12.0975 78.3626 11.4004C78.346 11.3351 78.3265 11.2754 78.307 11.2157C76.4072 11.6333 74.5075 12.051 72.6077 12.4687C73.5215 12.1277 74.4551 11.8038 75.4052 11.5595C76.3866 11.3097 77.3846 11.1253 78.3799 10.9182C78.3717 10.8642 78.3579 10.8074 78.3526 10.7478C76.7292 11.0138 75.1116 11.2826 73.4883 11.5486C73.4774 11.472 73.4665 11.3953 73.45 11.3157C74.8572 11.0826 76.2617 10.855 77.6775 10.6191C77.6636 10.5622 77.6526 10.5139 77.6444 10.46C75.9689 9.98793 74.3081 10.3559 72.6401 10.4996C74.2779 9.72861 76.0165 9.65621 77.7884 9.70033C75.8492 9.17287 73.9362 8.53774 71.8805 8.91195C71.9603 8.867 72.0315 8.82484 72.1627 8.74898C71.0267 8.74252 69.9596 8.62862 68.9137 8.75319C67.0607 8.95263 65.2268 9.2827 63.3874 9.58153C61.1245 9.94321 58.8813 10.322 56.6297 10.6894C56.7237 11.0929 56.8036 11.4821 56.1257 11.3449C55.9924 11.3129 55.8387 11.3631 55.7021 11.4077C54.4131 11.8005 53.1128 12.1875 51.8264 12.6172C51.2714 12.7985 50.7501 13.0537 50.2147 13.2805C50.2343 13.326 50.251 13.3772 50.2678 13.4142C50.7772 13.2525 51.2952 13.088 51.8045 12.9263C52.6241 12.6728 53.4352 12.3936 54.263 12.1799C54.411 12.141 54.6312 12.3522 54.818 12.4469C54.6836 12.5852 54.5743 12.8002 54.4065 12.8503C53.8288 13.0343 53.2401 13.1558 52.5746 13.3166C52.8964 13.6221 53.0225 13.8923 52.5586 14.0486C51.7275 14.3248 50.8741 14.5469 50.0514 14.8487C49.3995 15.0947 48.7868 15.4317 48.1601 15.7261C48.1881 15.783 48.2162 15.8399 48.2499 15.8997C48.6343 15.7316 49.0161 15.5409 49.4118 15.3927C50.0182 15.1663 50.6302 14.9428 51.2561 14.7761C51.4125 14.7344 51.63 14.923 51.8226 15.0063C51.6827 15.1276 51.5737 15.3 51.4171 15.3559C50.5175 15.6969 49.6013 15.9727 48.71 16.3393C47.8159 16.7116 46.9638 17.1693 46.0893 17.5871C46.2448 17.7015 46.3639 17.7192 46.4693 17.68C47.6818 17.2556 48.9 16.8341 50.1042 16.3841C50.5426 16.222 50.7461 16.3679 50.8486 16.7828C48.7729 17.6165 46.541 18.0153 44.712 19.3584C46.2092 18.8363 47.712 18.317 49.1783 17.7295C50.4282 17.2315 51.6334 16.6255 52.8806 16.119C53.4757 15.8727 54.1127 15.7401 54.7272 15.5677C54.6473 15.6268 54.5759 15.6973 54.4791 15.7337C53.5592 16.1285 52.617 16.4835 51.7168 16.9097C50.7455 17.3639 49.7826 17.8294 48.8588 18.4002C47.5615 19.2015 46.0451 19.6355 44.6297 20.2489C44.0259 20.5122 43.4502 20.8324 42.8548 21.1213C43.2297 21.1262 43.5595 21.0657 43.8836 21.0165C44.1821 20.9756 44.4916 20.983 44.7733 20.891C45.4591 20.6764 46.1254 20.4021 46.8084 20.179C47.0133 20.1121 47.2547 20.1134 47.4647 20.1487C47.5696 20.1663 47.6424 20.3313 47.727 20.4311C47.6413 20.5015 47.5668 20.6061 47.4615 20.6452C46.9833 20.8156 46.4853 20.9688 46.0071 21.1392C44.6436 21.6365 43.2043 21.9887 42.2478 23.2545C43.4633 22.796 44.5484 21.8658 45.9801 22.2712C45.757 22.514 45.509 22.6658 45.2413 22.7721C44.4641 23.0826 43.6475 23.3163 42.9096 23.6895C41.223 24.5284 39.5728 25.4355 37.8917 26.3056C37.7065 26.4038 37.4762 26.4507 37.263 26.4779C37.172 26.4887 37.0108 26.3857 36.9886 26.3033C36.9635 26.2265 37.0526 26.0653 37.1353 26.0147C38.0444 25.5148 38.9733 25.032 39.8881 24.5349C40.2471 24.3469 40.5836 24.1331 40.9285 23.9308C40.8976 23.8796 40.8724 23.8312 40.8415 23.7799C40.1778 24.0911 39.4971 24.3937 38.8333 24.7191C38.292 24.9855 37.745 25.2492 37.2431 25.5783C36.8353 25.8484 36.7213 26.8011 37.0148 27.1064C37.4607 27.5459 37.6856 27.0194 37.9961 26.8566C38.0275 26.8369 38.0673 26.8287 38.1072 26.8062C39.1049 26.2302 40.1083 25.6428 41.1059 25.0668C41.2969 24.9572 41.4794 24.8363 41.6845 24.741C42.5592 24.309 43.4281 23.8741 44.3139 23.4762C44.4705 23.4061 44.6973 23.4784 44.8932 23.4852C44.8899 23.5476 44.898 23.6157 44.9061 23.6839C44.5556 23.8691 44.2051 24.0544 43.9316 24.2004C44.0789 24.2609 44.2602 24.3243 44.4416 24.3878C44.2928 24.5543 44.1919 24.7949 44.004 24.8705C42.4092 25.5708 40.7805 26.2255 39.1856 26.94C38.4849 27.2538 37.8376 27.6729 37.1763 28.0494C37.1312 27.9981 37.0861 27.9467 37.041 27.8954C37.0308 28.1536 37.0178 28.4174 37.0078 28.6472C39.1221 27.5412 41.2072 26.5628 43.5813 26.1365C43.6002 26.7438 43.1285 26.7894 42.8379 26.9267C41.4538 27.5346 40.053 28.0913 38.6718 28.6935C38.3728 28.8195 37.8329 28.859 38.0705 29.4562C38.079 29.4676 37.754 29.6587 37.5721 29.6804C37.3846 29.6992 37.1834 29.6186 36.9423 29.5747C36.9289 29.8952 36.9215 30.1761 36.905 30.5307C37.6774 30.1038 38.3304 29.6875 39.0395 29.3709C40.1645 28.8666 41.1779 28.0495 42.5065 28.1393C42.6569 28.1515 42.8039 28.2687 42.9512 28.3291C42.8369 28.4278 42.7367 28.5549 42.6086 28.6109C41.31 29.1625 40.006 29.6829 38.7243 30.2715C38.2714 30.476 37.8913 30.8456 37.4664 31.1213C37.244 31.2647 36.8612 31.1774 36.8527 31.6143C36.8435 32.1647 36.8088 32.7094 36.7886 33.2115C38.0226 32.5347 39.2255 31.8491 40.4677 31.2263C41.0232 30.9457 41.6797 30.8728 42.2325 30.5837C43.1302 30.1064 43.9803 29.5125 44.8639 29.0068C46.6739 27.9672 48.4921 26.9674 50.3078 25.9307C51.3225 25.3491 52.2782 24.6735 53.3209 24.163C55.959 22.8671 58.6166 21.6167 61.2884 20.3805C63.3278 19.4359 65.3953 18.5482 67.4487 17.632C68.7475 17.052 70.0575 16.4778 71.3731 15.9206C71.5383 15.8477 71.7622 15.9256 71.9581 15.9324C71.9662 16.0006 71.9714 16.0744 71.9738 16.1396C71.7629 16.2605 71.5632 16.4012 71.344 16.4822C70.1882 16.9212 69.0043 17.3032 67.8623 17.7989C65.567 18.7847 63.2971 19.8046 61.0298 20.8473C58.754 21.8927 56.4416 22.884 54.2388 24.0661C51.0015 25.8126 47.84 27.6901 44.6644 29.5533C43.6752 30.1407 42.7562 30.8562 41.7923 31.492C41.4586 31.7143 41.0995 31.9024 40.7294 32.0563C40.3877 32.1963 39.9561 32.1768 39.6736 32.3823C39.0888 32.8046 38.1066 32.7338 37.9555 33.7175C37.9467 33.7629 37.7788 33.813 37.6822 33.821C37.3896 33.8363 37.1028 33.8262 36.6001 33.8347C36.925 34.0919 37.1454 34.2747 37.3714 34.4605C37.4314 34.4126 37.4686 34.3674 37.5256 34.3393C38.3981 33.7853 39.2511 33.1858 40.1573 32.6915C40.4737 32.5174 40.9947 32.3189 41.2353 32.8821C40.389 33.3284 39.5371 33.7577 38.7134 34.2298C38.5195 34.345 38.4156 34.6054 38.1751 34.9105C39.2053 34.5787 40.0135 34.3194 40.8303 34.0574C41.1934 34.5758 40.6649 34.6069 40.2878 34.9566C40.7053 34.9476 40.9692 34.9888 41.1996 34.9277C41.5865 34.8249 41.9356 34.4183 42.3557 34.8946C42.3952 34.9431 42.6173 34.8564 42.7482 34.8089C43.662 34.4679 44.5619 34.0843 45.4896 33.7859C46.7987 33.3677 48.1189 32.9837 49.4418 32.6223C51.4759 32.0664 53.5073 31.4877 55.5665 31.0227C57.7535 30.5301 59.9791 30.242 62.1578 29.7238C64.1061 29.2667 66.068 29.3573 68.0304 29.3628C68.499 29.3654 68.8892 29.6344 68.9139 30.2162C68.9389 30.7555 69.0065 31.295 69.0595 31.8912C71.6503 29.9877 73.2744 27.3666 75.0425 24.8683C76.8163 22.3729 78.2673 19.7138 79.084 16.776C79.0784 16.7731 78.9878 16.7272 78.9878 16.7272C79.4247 15.8954 79.7955 15.1938 80.1663 14.4922C80.1381 14.4637 80.1041 14.4465 80.0645 14.4264C79.3215 15.1457 78.5815 15.8594 77.847 16.576C77.7848 16.5444 77.7453 16.496 77.7002 16.4446ZM81.3014 12.8473C82.0108 12.4881 82.7175 12.1204 83.4241 11.7669C83.3932 11.7015 83.3652 11.6446 83.3315 11.5848C82.6164 11.9411 81.9042 12.2917 81.1919 12.6423C81.237 12.7079 81.2678 12.7733 81.3014 12.8473ZM82.3867 2.92212C83.0158 2.69302 83.6193 2.47229 84.4077 2.19586C83.1544 2.33628 82.0716 2.4493 80.9917 2.57084C81.4731 2.7864 82.0702 2.22796 82.3867 2.92212ZM85.9858 2.35523C87.2642 2.29156 88.5397 2.23355 89.8181 2.16989C89.8127 2.12446 89.8159 2.07624 89.8076 2.03646C88.5264 2.0916 87.2509 2.14961 85.9726 2.19909C85.9807 2.25305 85.9833 2.30414 85.9858 2.35523ZM87.064 2.95156C87.7803 2.85916 88.4991 2.81785 89.2152 2.75383C89.9085 2.69251 90.5934 2.61979 91.2755 2.55273C88.8074 2.57558 86.3081 2.12722 83.9051 3.08682C83.8996 3.05558 83.8747 2.95045 83.8889 2.95053C84.3672 2.76597 84.8484 2.57576 85.3295 2.39973C84.5508 2.47475 83.7999 2.64924 83.0658 2.87491C82.0413 3.19539 81.0422 3.56426 80.0318 3.89902C79.5252 4.06922 79.0074 4.21951 78.5066 4.3784C79.6493 4.21748 80.7475 3.90593 81.8678 3.69097C82.3654 3.59449 82.8903 3.23427 83.4355 3.68854C82.2692 3.99403 81.0724 4.16315 79.9007 4.42321C78.6721 4.69714 77.4741 5.06488 76.2651 5.38431C76.2678 5.40703 76.2733 5.43827 76.2788 5.45533C76.6823 5.43209 77.0885 5.41737 77.4919 5.39413C77.5199 5.46523 77.5449 5.54198 77.5785 5.61595C77.413 5.74553 77.267 5.93482 77.0734 6.00749C76.1483 6.34273 75.2092 6.63533 74.2954 6.97631C73.9053 7.12731 73.5487 7.38066 73.1811 7.58571C73.4081 7.61538 73.5537 7.49703 73.7244 7.44125C74.4474 7.18147 75.1734 6.90185 75.9187 6.7103C76.4052 6.57971 76.9708 6.05515 77.3863 6.8208C80.0149 5.66954 80.0149 5.66954 80.2604 5.92915C79.0501 6.4472 77.7999 6.98773 76.5526 7.5226C76.5721 7.5823 76.6001 7.63921 76.6253 7.70178C76.8442 7.6633 77.0747 7.588 77.2933 7.60627C77.492 7.62158 77.6787 7.74466 77.8685 7.81952C77.7086 7.95197 77.5626 8.12707 77.3747 8.20261C77.1356 8.29489 76.8686 8.30188 76.6042 8.34578C77.7062 8.76916 77.8198 8.76981 78.5662 8.40801C78.9736 8.20887 79.3753 8.00685 79.7966 7.85035C80.2179 7.69384 80.656 7.58851 81.0913 7.46046C81.1136 7.52868 81.1331 7.58839 81.1554 7.65661C80.2186 8.04286 79.2761 8.42624 78.214 8.86285C78.7435 9.10989 79.1003 9.2765 79.3948 9.41153C79.3275 9.72612 79.2782 9.89325 79.2714 10.0606C79.2465 10.4038 79.2273 10.7499 79.2535 11.0905C79.2637 11.2807 79.3413 11.5904 79.4377 11.6109C79.7241 11.6778 80.1496 11.7511 80.3125 11.5988C80.701 11.2407 81.056 10.7943 81.2692 10.3189C81.8077 9.14718 82.7358 8.34377 83.7032 7.603C84.6763 6.86511 85.8072 6.33525 86.7549 5.57735C87.537 4.94903 88.2821 4.33753 89.2721 4.08495C89.6959 3.97953 90.0836 3.74906 90.488 3.56976C90.4797 3.54417 90.4628 3.52138 90.4572 3.50432C89.0897 3.72922 87.7308 3.95133 86.3633 4.17622C86.3523 4.12792 86.3355 4.07675 86.3245 4.02845C87.6697 3.73533 89.0063 3.44499 90.3486 3.15752C90.3322 3.06379 90.3157 2.97006 90.3049 2.8792C88.5429 3.08199 86.7751 3.28191 85.013 3.4847C85.002 3.42221 84.9911 3.35973 84.9887 3.29445C85.6682 3.1763 86.362 3.04405 87.064 2.95156ZM95.0376 48.3887C94.8229 49.1054 94.5707 49.924 94.3269 50.7398C94.69 50.3617 95.3247 50.1496 95.0537 49.4359C95.0174 49.3392 95.1324 49.127 95.2351 49.051C95.9886 48.4509 96.7731 47.9021 97.5013 47.2819C97.9752 46.8817 98.6273 46.6073 98.7238 45.7311C97.4427 46.6545 96.2531 47.5104 95.0376 48.3887ZM95.638 46.4229C95.1133 46.7548 95.2784 47.1444 95.0453 47.6312C96.378 46.6201 97.5738 45.6962 98.7865 44.7951C98.9263 44.688 99.1422 44.6836 99.3186 44.6307C99.3628 44.8239 99.4553 45.0202 99.4258 45.2045C99.3813 45.5022 99.2546 45.7795 99.1589 46.0798C99.6209 46.2214 99.5313 46.482 99.271 46.7699C98.9821 47.1003 98.6903 47.4221 98.3471 47.8032C98.5231 47.8212 98.5599 47.8328 98.5912 47.8273C98.8219 47.7236 99.0469 47.6171 99.2776 47.5134C99.2078 47.7769 99.2198 48.1174 99.054 48.2896C98.568 48.7976 98.0086 49.2399 97.4802 49.7051C97.2945 49.8743 97.0976 50.0235 96.9092 50.1842C96.9486 50.2327 96.9881 50.2811 97.0275 50.3296C97.4528 49.9972 97.8695 49.6676 98.3005 49.338C98.5088 49.1803 98.7032 48.9799 98.934 48.8621C99.0735 48.7976 99.2662 48.8668 99.4337 48.8734C99.4015 49.035 99.4313 49.2565 99.3257 49.3382C98.7488 49.8428 98.1325 50.299 97.5527 50.8093C97.2814 51.0489 97.0638 51.3371 96.8178 51.6109C96.8827 51.6794 96.9475 51.7479 97.0097 51.8078C97.9085 51.1319 98.8018 50.4532 99.7093 49.7603C100.286 50.1665 100.082 50.5115 98.6506 51.4511C98.9158 51.7279 99.1781 52.0103 99.5618 52.4182C100.196 50.0071 100.799 47.7292 101.409 45.4342C101.424 45.4343 101.435 45.4401 101.455 45.443C101.557 45.018 101.702 44.5648 101.843 44.2166C101.844 44.1598 101.847 44.0974 101.864 44.0351C102.302 42.179 102.762 40.3344 103.257 38.4928C103.716 36.7759 103.949 35.0435 103.77 33.2662C103.708 32.6586 103.579 32.0592 103.458 31.3434C103.357 32.0891 103.262 32.7242 103.17 33.3678C103.102 33.3617 103.031 33.3471 102.96 33.3325C102.981 31.4145 103.303 29.4783 102.934 27.5694C102.875 27.5605 102.818 27.5602 102.761 27.5599C102.577 29.1961 102.402 30.8295 102.227 32.4629C102.165 32.4597 102.099 32.4622 102.043 32.4619C102.024 31.8262 101.977 31.1903 101.998 30.5605C102.028 29.8569 102.109 29.165 102.199 28.4704C102.285 27.8381 102.417 27.2146 102.526 26.5796C102.429 26.5592 102.324 26.5416 102.228 26.5212C101.843 28.1051 101.458 29.6891 101.079 31.276C101.025 31.27 100.98 31.2612 100.926 31.2552C101.045 30.3479 101.153 29.4348 101.281 28.5247C101.34 28.0994 101.454 27.6801 101.513 27.2548C101.528 27.1414 101.467 27.0105 101.433 26.894C101.308 26.9728 101.117 27.0256 101.071 27.1303C100.806 27.807 100.582 28.4981 100.331 29.1748C100.204 29.5231 100.046 29.8627 99.856 30.1936C99.9853 28.6223 100.886 27.2002 100.815 25.4207C100.167 26.8074 99.5942 28.0328 99.0213 29.2581C98.9704 29.2323 98.9165 29.2121 98.8683 29.1948C99.3827 27.8045 99.8969 26.4284 100.403 25.0409C100.338 25.015 100.275 24.9835 100.219 24.9548C99.5817 25.9698 98.9448 26.9849 98.3136 28.0028C98.2626 27.9769 98.2089 27.9426 98.1579 27.9168C98.4195 27.416 98.6699 26.8953 98.9485 26.4032C99.2358 25.8941 99.5541 25.4078 99.8611 24.9158C99.8187 24.873 99.7763 24.8444 99.7311 24.8073C99.4137 25.1516 99.0707 25.4902 98.7788 25.8546C97.7256 27.1283 96.7119 28.4363 95.6276 29.6872C95.2128 30.1672 95.0603 30.4813 95.4225 31.1275C96.1666 32.4653 96.6601 33.9181 96.4848 35.5941C96.6563 35.4106 96.7283 35.255 96.8451 35.2074C97.0073 35.1544 97.2059 35.1839 97.3792 35.1792C97.3753 35.3409 97.4279 35.5597 97.3562 35.6586C97.0872 35.9919 96.7645 36.2767 96.5415 36.5053C96.7831 36.4641 97.0532 36.423 97.3261 36.3764C97.2222 36.651 97.1663 36.9571 97.0001 37.186C96.7135 37.5958 96.2458 37.8996 96.4345 38.5931C96.7488 38.2969 97.1138 38.0691 97.3232 37.7412C97.5814 37.3312 97.8547 37.2278 98.3529 37.4803C98.6179 36.4404 98.8456 35.4742 99.1215 34.511C99.3771 33.6158 98.9829 32.6261 99.5363 31.7893C99.7581 35.3318 98.5339 38.4972 96.9291 41.6689C97.3603 41.2968 97.7346 40.9386 98.1455 40.6345C98.311 40.5049 98.5582 40.4949 98.7631 40.428C98.7275 40.6661 98.7793 40.9984 98.6393 41.1338C98.2563 41.5232 97.8028 41.8271 97.369 42.1623C96.8095 42.6046 96.2332 43.0241 95.6963 43.4921C95.585 43.5851 95.6202 43.852 95.5496 44.229C96.8877 43.2634 98.0576 42.4046 99.2387 41.5515C99.3037 41.6058 99.3745 41.6488 99.4394 41.703C99.3471 41.9267 99.314 42.2301 99.1483 42.3739C98.5629 42.8813 97.9465 43.3517 97.316 43.7936C96.7855 44.1651 96.1731 44.4454 95.6848 44.8597C95.4449 45.0655 95.3996 45.505 95.212 45.9722C96.853 45.153 97.8955 43.7742 99.3517 42.9965C99.4167 43.0507 99.4816 43.1192 99.5465 43.1735C99.426 43.3686 99.3563 43.6179 99.1765 43.7474C98.046 44.683 96.8954 45.6441 95.638 46.4229ZM97.9871 63.8246C97.1462 65.6614 96.1382 67.4206 95.1473 69.1742C93.6997 71.7283 92.0033 74.1135 90.1966 76.4215C89.0313 77.9159 87.6882 79.2277 86.3591 80.5679C86.2705 80.6582 86.3004 80.8656 86.2427 81.0071C85.9367 81.7914 85.7607 82.67 85.2794 83.3227C84.4488 84.4388 83.471 85.4661 82.468 86.4308C81.0364 87.8187 79.4722 89.0612 77.638 89.8821C75.6016 90.7928 73.5622 91.7374 71.456 92.4632C70.1382 92.9125 68.697 93.1143 67.2963 93.2085C65.191 93.3441 63.0719 93.4086 60.974 93.2775C59.8924 93.2061 58.851 92.6213 57.7852 92.2946C56.7081 91.9622 55.6222 91.6751 54.548 91.337C54.222 91.2358 53.9194 91.0326 53.6137 90.8777C53.5764 90.937 53.5391 90.9964 53.5018 91.0558C53.7504 91.2672 54.0189 91.4673 54.2589 91.6957C56.0514 93.4084 58.1625 94.6065 60.4688 95.4624C62.0215 96.0359 63.6275 96.2663 65.277 95.9068C66.2923 95.6884 67.3022 95.4104 68.3118 95.1892C68.4342 95.1587 68.7033 95.2595 68.7057 95.3248C68.733 95.5094 68.7253 95.8186 68.6142 95.8832C67.5879 96.4875 66.5949 97.2224 65.4822 97.5907C63.8884 98.1207 62.2028 97.9068 60.5456 97.6931C57.7108 97.3166 55.1738 96.1019 52.6714 94.8193C52.0826 94.5208 51.4766 94.2421 50.9136 93.8928C49.9716 93.3086 49.061 92.6905 48.1276 92.0893C46.8068 91.2277 45.4633 90.3688 43.8361 90.334C42.723 90.3106 41.6083 90.5285 40.4915 90.6384C40.3125 90.6544 40.1364 90.6648 39.9546 90.6581C38.2484 90.5689 36.8368 91.4689 35.3617 92.1018C34.1942 92.5917 33.0797 93.2295 31.985 93.8844C30.571 94.7333 29.1399 95.5878 27.8271 96.5876C26.0635 97.9282 24.4491 99.4655 22.6883 100.815C20.4794 102.513 18.6234 104.54 16.77 106.589C16.3496 107.052 15.7844 107.506 15.8591 108.27C15.8673 108.324 15.8384 108.394 15.7928 108.428C14.8337 109.195 13.9447 110.103 12.8847 110.648C12.3747 110.909 11.4622 110.603 10.8134 110.352C8.41664 109.422 6.57853 107.729 4.94074 105.796C4.54612 105.325 4.17432 104.838 3.78824 104.365C3.24713 103.706 2.91956 102.964 2.67484 102.142C2.49421 101.517 2.13158 100.928 1.79438 100.358C1.06104 99.1111 0.592377 97.7777 0.482201 96.3413C0.424327 95.6145 0.697987 95.006 1.2808 94.4617C2.19784 93.61 3.05008 92.6756 3.88534 91.7326C5.43571 89.985 6.95498 88.2145 8.47146 86.4355C9.32982 85.4331 10.1655 84.4192 10.973 83.3767C12.1757 81.8229 13.4038 80.2891 14.5018 78.661C15.2472 77.5586 15.8343 76.3333 16.3873 75.1191C17.2139 73.3106 17.9639 71.4705 18.697 69.6218C18.9135 69.0697 18.9998 68.4516 19.0973 67.8535C19.1681 67.4339 19.1509 67.0053 19.1934 66.5856C19.2026 66.4693 19.2408 66.2681 19.2977 66.2542C20.2762 66.0101 19.827 65.1847 19.6988 64.8065C19.2721 63.5726 18.6633 62.3887 18.0943 61.2108C17.6514 60.2889 17.1943 59.3669 16.6716 58.49C15.9859 57.3454 15.1435 56.2851 14.5318 55.1069C13.9511 53.9799 13.5584 52.749 13.106 51.5519C12.902 51.0144 12.7636 50.4603 12.5767 49.9173C12.1471 48.689 12.4047 47.4817 12.6651 46.2829C12.9927 44.7837 13.3883 43.3048 13.6676 41.8025C13.8028 41.074 13.7934 40.322 13.3206 39.6412C13.1574 39.4019 12.8186 39.0878 13.2326 38.7355C13.6267 38.3944 13.9429 38.697 14.2657 38.8464C14.4384 38.9268 14.5737 39.095 14.7036 39.2036C15.0333 38.2747 15.2241 37.2969 15.7007 36.4852C16.5963 34.9751 17.6617 33.5652 18.6422 32.1123C18.8544 31.7929 19.0468 31.4563 19.2137 31.1139C19.994 29.4385 20.7432 27.7403 21.5404 26.0735C22.0614 24.9783 22.6107 23.8975 23.1996 22.8368C23.5702 22.1636 24.0201 21.5306 24.4813 20.9174C25.3376 19.7788 26.18 18.6117 27.1352 17.5587C28.6396 15.9016 30.2426 14.3586 32.0686 13.0354C33.3982 12.0725 34.5615 10.8902 35.8629 9.88463C36.7277 9.21989 37.6742 8.64643 38.6261 8.11839C40.0113 7.34027 41.4302 6.62194 42.8546 5.92066C43.5669 5.57002 44.3156 5.28769 45.0613 5.02521C46.6809 4.4584 48.3033 3.88594 49.9396 3.37031C51.0835 3.01078 52.2417 2.65132 53.43 2.47081C54.2771 2.3451 55.1711 2.43531 56.031 2.53668C56.7348 2.62297 56.951 3.0101 56.8893 3.79007C57.0484 3.77111 57.2102 3.78906 57.3526 3.73312C58.719 3.21595 60.0773 2.65901 61.455 2.16177C61.9844 1.97466 62.5556 1.91549 63.1101 1.80514C64.8162 1.47434 66.5143 1.06121 68.2367 0.852523C70.0586 0.63021 71.9049 0.583962 73.7402 0.475227C74.6351 0.423567 75.533 0.352061 76.4304 0.365678C77.7849 0.390409 79.1722 0.182649 80.4517 0.831208C80.6075 0.903032 80.7625 1.08835 80.8012 1.25031C80.8316 1.38669 80.6969 1.58171 80.5854 1.70309C80.4852 1.81602 80.3146 1.85761 80.18 2.02426C81.2118 1.8996 82.2322 1.75502 83.2639 1.64455C84.8013 1.49156 86.3419 1.27616 87.8842 1.25372C89.2532 1.23597 90.6208 1.44521 91.9917 1.56367C92.0854 1.57556 92.1926 1.68683 92.2403 1.77506C92.7202 2.68013 93.5728 2.58566 94.4047 2.63012C95.6851 2.70267 96.9679 2.84049 98.2478 2.98397C98.3613 2.9988 98.4479 3.23481 98.535 3.37151C98.5773 3.4285 98.5681 3.5306 98.6162 3.56208C99.4557 4.19395 99.6652 5.1826 99.9037 6.08629C100.52 8.36265 101.031 10.6639 101.536 12.9624C101.66 13.5164 101.744 14.0929 101.468 14.6929C101.344 14.9504 101.56 15.3801 101.677 15.7241C102.449 18.0439 102.678 20.423 102.385 22.8503C102.37 22.9495 102.392 23.0603 102.366 23.1538C102.054 24.3409 102.366 25.2819 103.056 26.3357C103.686 27.3098 103.905 28.6163 104.067 29.809C104.309 31.5894 104.442 33.4006 104.434 35.1967C104.43 36.2976 104.124 37.4025 103.868 38.4821C103.403 40.4884 102.877 42.4774 102.367 44.4749C102.309 44.7016 102.177 44.9052 102.073 45.1231C102.067 45.1202 102.062 45.1173 102.059 45.123C101.998 45.3269 101.946 45.5281 101.902 45.7265C101.93 45.8118 101.92 45.928 101.874 46.0753C101.854 46.1575 101.828 46.2368 101.801 46.3161C101.801 46.3445 101.798 46.3785 101.801 46.4012L101.781 46.3983C101.592 47.0498 101.421 47.71 101.243 48.3673C100.932 49.5261 100.632 50.6906 100.304 51.8408C100.208 52.1977 100.001 52.52 99.86 52.8682C99.8167 52.9673 99.7732 53.1089 99.8096 53.1914C100.397 54.5426 100.227 55.9434 100.121 57.3417C99.9843 59.6847 98.9403 61.753 97.9871 63.8246ZM84.1826 14.4215C86.5847 13.6037 88.9227 12.604 91.5707 12.8716C92.8224 13.0008 92.7183 12.8413 93.1998 13.9393C95.1221 12.2165 95.4756 9.75555 96.1647 7.68524C96.0274 7.82918 95.722 8.07998 95.5099 8.38522C94.968 9.18516 94.4913 10.0252 93.9523 10.8195C93.7574 11.1049 93.4522 11.3132 93.2064 11.5587C93.1838 11.533 93.1642 11.5017 93.1416 11.476C93.5523 10.7519 93.9545 10.0307 94.3652 9.30658C94.1007 9.36467 93.9351 9.50844 93.7865 9.64663C93.6179 9.81025 93.4521 9.98239 93.2751 10.1346C93.1351 10.2558 92.9726 10.3514 92.8243 10.4612C92.8046 10.4299 92.7849 10.3986 92.7596 10.3644C93.2033 9.81356 93.6526 9.26564 94.0963 8.71485C94.0681 8.68631 94.0341 8.66909 94.0059 8.64056C93.1727 9.25724 92.3338 9.87104 91.4921 10.4905C91.464 10.4478 91.4386 10.4136 91.4105 10.3709C92.3043 9.60699 93.1838 8.84302 94.0747 8.0848C94.0494 8.0506 94.0268 8.02494 93.9986 7.9964C92.767 8.7385 91.544 9.47781 90.3124 10.2199C90.2815 10.1687 90.2562 10.1203 90.2253 10.069C91.2292 9.41076 92.2358 8.76101 93.2397 8.10275C93.2172 8.06289 93.1891 8.02017 93.1638 7.97179C92.3003 8.43791 91.4255 8.89828 90.562 9.3644C90.534 9.30749 90.4946 9.24484 90.4638 9.1794C91.6153 8.52481 92.7641 7.86169 93.9127 7.21275C93.8987 7.1843 93.8847 7.15584 93.8621 7.13018C93.0107 7.48854 92.1536 7.84403 91.3021 8.20239C91.2854 8.15122 91.2629 8.11136 91.2406 8.05732C92.3859 7.48498 93.534 6.92117 94.685 6.3517C94.6682 6.30053 94.643 6.25215 94.6234 6.20664C93.3653 6.65065 92.1101 7.089 90.8492 7.52448C90.8352 7.49603 90.8212 7.46757 90.8043 7.44477C90.9384 7.33487 91.0726 7.22497 91.2981 7.04749C90.9481 7.16184 90.709 7.23993 90.4756 7.32089C90.4617 7.27825 90.4421 7.23274 90.4338 7.19296C91.6206 6.8053 92.8157 6.42903 94.0025 6.04137C93.9998 6.01865 93.9943 5.98741 93.9916 5.96469C92.2745 6.24719 90.5573 6.52969 88.8345 6.80931C88.8263 6.75536 88.8152 6.70705 88.8127 6.65596C90.1262 6.43927 91.4311 6.22537 92.7446 6.00868C92.7307 5.95185 92.7141 5.88649 92.7003 5.82966C88.8947 5.8222 85.3432 6.5057 82.7133 9.6489C82.8465 9.69506 82.9657 9.69858 83.0683 9.65092C84.0197 9.19382 84.8731 8.53753 85.9674 8.38769C86.3881 8.3305 86.768 7.98932 87.1781 7.81289C87.2891 7.76244 87.4562 7.84001 87.5952 7.86066C87.6061 7.93734 87.6113 8.01114 87.6222 8.08782C87.0842 8.29189 86.5152 8.44472 86.0136 8.71711C85.341 9.08783 84.7161 9.56098 84.0401 10.0083C84.0948 10.3491 84.1659 10.7837 84.2397 11.2267C84.781 10.9602 85.2028 10.7328 85.6527 10.5481C85.7638 10.4976 85.9449 10.6037 86.0951 10.6442C86.0035 10.7544 85.9401 10.9073 85.8205 10.9605C85.4729 11.1259 85.0945 11.2401 84.7526 11.4084C84.5162 11.5234 84.1029 11.7622 84.1307 11.8475C84.2751 12.3761 83.8717 12.3852 83.5896 12.534C82.7434 12.9661 81.765 13.1961 81.052 14.1085C82.3392 13.5512 83.504 13.0386 84.6772 12.5515C84.8651 12.476 85.0865 12.5028 85.2939 12.4869C85.2993 12.5323 85.2933 12.5862 85.2987 12.6317C84.546 13.0899 83.7962 13.5425 83.0179 14.0091C83.7813 14.1042 83.2449 14.4871 83.1321 14.8212C83.3655 14.7261 83.5165 14.6532 83.6646 14.6001C83.8354 14.5301 84.0118 14.4772 84.1826 14.4215ZM91.7234 17.9091C91.1094 18.4447 90.5913 19.0859 90.0112 19.653C89.4312 20.2058 88.8229 20.7301 88.2317 21.2631C88.195 21.2231 88.164 21.1861 88.1244 21.1518C88.4703 20.8076 88.8104 20.4605 89.1619 20.1192C89.5135 19.7636 89.8877 19.4196 90.2365 19.0555C90.571 18.7056 90.897 18.3442 91.2061 17.9743C91.5152 17.6043 91.7846 17.2143 92.0824 16.8386C92.0399 16.8099 92.0032 16.7842 91.9636 16.7499C90.4022 18.0009 88.8351 19.249 87.2737 20.5C87.2342 20.4657 87.1975 20.4258 87.1636 20.3944C87.2208 20.3379 87.2723 20.2787 87.3266 20.2279C88.7373 19.0073 90.1564 17.798 91.5446 16.5518C91.9702 16.1626 92.5574 15.8198 92.5003 14.9795C90.9469 16.2987 89.4678 17.5558 87.9916 18.8072C87.9663 18.773 87.9325 18.7274 87.9015 18.6904C89.3755 17.3311 90.8468 15.9633 92.3552 14.5644C91.5343 14.5825 91.02 15.0761 90.4352 15.4842C89.8618 15.8839 89.2349 16.2208 88.6362 16.5863C88.6109 16.5379 88.5857 16.4895 88.5575 16.4468C89.8486 15.7277 90.8109 14.4648 92.3801 14.2212C92.3552 14.1161 92.319 14.0052 92.2856 13.9029C91.372 14.2013 90.5027 14.6929 89.5919 15.0141C89.5752 14.9629 89.5556 14.9174 89.536 14.8719C89.9292 14.6726 90.328 14.4763 90.7241 14.2714C90.7073 14.2344 90.6933 14.1918 90.668 14.1576C90.1012 14.4182 89.523 14.6732 88.9533 14.9395C88.9309 14.8996 88.9084 14.8598 88.8945 14.8171C89.3419 14.5671 89.7894 14.3172 90.2425 14.07C90.2342 14.0444 90.2229 14.0245 90.2146 13.9989C89.7992 14.1157 89.381 14.224 88.9571 14.3436C88.9488 14.3039 88.9349 14.2612 88.9152 14.2299C89.3736 14.0566 89.8318 13.8974 90.2873 13.7298C89.1819 13.8313 88.1156 14.0381 87.0601 14.3215C85.8624 14.6467 84.6477 14.9632 83.5003 15.4277C82.4098 15.8642 81.3808 16.4599 80.366 17.0415C80.0753 17.2072 79.8233 17.535 79.668 17.8405C78.7478 19.6371 77.8672 21.4538 76.9754 23.2647C76.9121 23.3892 76.8658 23.5223 76.8167 23.6611C76.808 23.6781 76.8476 23.7123 76.8756 23.7693C77.0152 23.7048 77.1547 23.6403 77.4424 23.5086C77.395 23.8261 77.3709 24.0416 77.3326 24.2571C77.3178 24.3563 77.2177 24.4692 77.2514 24.529C77.5039 25.0128 77.176 25.2096 76.8285 25.375C76.481 25.5405 76.0884 25.6404 75.7549 25.8343C75.3102 26.0928 74.9134 26.4112 74.4969 26.7124C74.5335 26.7665 74.5757 26.8235 74.6151 26.8862C75.2421 26.5351 75.8719 26.1925 76.5331 25.8302C76.6727 26.214 76.6569 26.4551 76.2867 26.6233C76.036 26.7382 75.8217 26.9498 75.5822 27.0988C75.3455 27.2422 75.0977 27.3656 74.8555 27.4919C74.9943 27.541 75.0856 27.4734 75.1822 27.4796C75.4321 27.4782 75.679 27.5108 75.9259 27.5292C75.7884 27.7157 75.6931 27.9734 75.5078 28.0717C74.7612 28.476 73.9724 28.8092 73.2116 29.2135C72.8183 29.4269 72.4643 29.7171 72.0935 29.9704C72.1159 30.0103 72.1442 30.0388 72.161 30.0758C73.2004 29.6277 74.237 29.1853 75.2878 28.7287C75.595 29.5533 74.9304 29.5581 74.6084 29.7293C73.7735 30.1672 72.9022 30.5226 72.0477 30.915C72.0673 30.9606 72.0869 31.0061 72.1065 31.0516C72.6987 30.8251 73.3048 30.6271 73.8632 30.355C74.3987 30.0999 74.8086 29.966 74.9058 30.7554C74.9168 30.8179 74.9931 30.8637 75.0242 30.9008C74.8638 31.1041 74.6124 31.3467 74.6489 31.4009C75.0118 31.9477 74.4549 31.9928 74.2297 32.1277C73.728 32.4143 73.1814 32.6212 72.6516 32.865C72.9624 33.1222 73.3054 33.2319 73.75 32.9734C73.904 32.8807 74.1817 32.9787 74.3947 32.9799C74.2572 33.1664 74.1535 33.3985 73.9794 33.5309C73.6913 33.7335 73.3581 33.8707 73.0419 34.0306C73.3228 34.0663 73.5423 33.9427 73.7725 33.9099C73.9913 33.8856 74.2124 33.955 74.4338 33.9818C74.2877 34.1711 74.1333 34.349 73.9985 34.544C73.9212 34.6542 73.8777 34.7958 73.7655 35.0165C75.4941 34.2772 77.0434 33.5965 78.6151 32.9557C79.7654 32.4855 80.9888 32.152 82.0914 31.5936C85.1143 30.0728 88.3248 29.4158 91.6667 29.5511C92.4134 29.5809 92.5033 29.292 92.6454 28.8303C93.1562 27.0966 93.6641 25.3686 94.1466 23.6348C94.2629 23.2099 94.5111 22.5813 94.3307 22.3618C93.9614 21.9256 94.0966 21.6596 94.2723 21.2719C94.3847 21.0228 94.3979 20.7306 94.4564 20.4614C94.4422 20.4613 94.4166 20.4555 94.4024 20.4554C94.1983 20.8572 93.9941 21.2589 93.787 21.6664C93.736 21.6405 93.6851 21.6147 93.6313 21.5945C93.9872 20.1097 94.6068 18.6803 94.6422 17.1255C93.8835 18.5343 93.0034 19.8317 91.9028 20.9746C92.7274 19.4641 93.555 17.9479 94.4256 16.361C94.1257 16.1805 93.8937 16.0345 93.707 15.9256C93.7452 16.1585 93.8462 16.3662 93.7859 16.4709C93.2405 17.3758 92.6923 18.2863 92.0819 19.1511C91.7523 19.6175 91.3041 19.9951 90.9152 20.41C91.7589 19.0301 92.8175 17.8018 93.3018 16.2184C92.4848 16.5231 92.3032 17.3988 91.7234 17.9091ZM94.6491 45.6086C94.7907 44.3354 95.3155 43.0785 94.8978 41.7709C94.8868 41.7226 94.9071 41.6546 94.9302 41.5951C95.106 41.179 95.2876 40.7657 95.4433 40.3892C95.1967 40.3141 95.055 40.2707 94.9047 40.2301C94.9683 40.0631 95.012 39.8931 95.0896 39.7403C95.2679 39.3894 95.4972 39.0644 95.6301 38.7048C95.6793 38.5661 95.4705 38.3464 95.4914 38.1791C95.5697 37.4787 95.7246 36.7815 95.7774 36.0753C95.872 35.0344 95.9099 33.9933 95.3714 32.9233C95.1652 34.0855 95.7064 35.1782 95.146 36.2249C95.0613 35.691 94.9738 35.1627 94.8808 34.6032C94.7417 35.0308 94.6201 35.4104 94.4984 35.7899C94.4417 35.7754 94.3878 35.7552 94.3255 35.7379C94.3456 34.3533 94.36 32.98 94.3716 31.5982C94.3176 31.5922 94.2637 31.5862 94.2127 31.5746C93.9998 32.4558 93.7614 33.3313 93.5796 34.2212C93.4596 34.7795 93.439 35.3526 93.3502 35.9196C93.3353 36.033 93.1728 36.1286 93.0869 36.2274C93.0502 36.2016 92.9992 36.1758 92.9596 36.1557C93.1357 34.8146 93.3061 33.4706 93.4766 32.0982C92.6692 33.5748 92.5047 35.3416 91.3944 36.6576C91.3491 36.6346 91.3009 36.6173 91.25 36.5915C91.8997 34.9069 92.5466 33.2137 93.1991 31.5234C93.151 31.4919 93.0973 31.4576 93.0521 31.4204C91.7098 33.0529 90.7771 35.0282 89.2115 36.4834C89.1296 36.4205 89.042 36.3548 88.9543 36.289C89.724 35.391 90.4908 34.4988 91.2547 33.6121C91.1784 33.5521 91.0992 33.4977 91.0286 33.4406C90.2393 34.293 89.4501 35.1455 88.6552 35.995C88.5987 35.938 88.5507 35.8923 88.4971 35.8438C89.742 34.3469 90.9783 32.8529 92.2147 31.3589C92.1808 31.3275 92.1469 31.2961 92.113 31.2647C90.8323 32.1456 89.5544 33.0208 88.2765 33.896C88.2371 33.8475 88.2005 33.7934 88.1554 33.742C89.4451 32.7875 90.7235 31.8271 92.0047 30.8753C91.9794 30.8411 91.9569 30.8013 91.9288 30.7586C90.5897 31.432 89.2479 32.0968 87.9088 32.7702C87.8863 32.7304 87.8639 32.6905 87.8414 32.6506C88.7222 32.1364 89.5974 31.6193 90.4782 31.105C90.4502 31.0481 90.4279 30.9799 90.3998 30.923C89.4146 31.3345 88.4265 31.7516 87.4497 32.1604C88.3956 31.2379 89.7882 31.0897 90.8859 30.415C90.8691 30.3638 90.8524 30.3126 90.8357 30.2615C89.2913 30.6244 87.7496 30.9958 86.1996 31.3559C86.1911 31.3445 86.1855 31.3275 86.1771 31.3161C87.1477 30.9754 88.1183 30.6347 89.1259 30.2773C88.8474 30.3069 88.5973 30.3367 88.3415 30.3636C85.8374 30.6955 83.5282 31.6387 81.23 32.6301C79.9001 33.2014 78.5366 33.6987 77.1898 34.233C75.3249 34.9743 73.5218 35.8323 71.9461 37.0974C71.7748 37.2383 71.6228 37.4673 71.5703 37.6827C71.3306 38.7567 71.1165 39.8366 70.8881 40.9164C70.8266 41.2055 70.7425 41.4831 70.6464 41.8542C70.9823 41.7398 71.2157 41.6588 71.4547 41.5807C71.5054 41.6491 71.5561 41.7175 71.6011 41.783C71.3755 41.9889 71.1469 42.2004 70.9185 42.3977C70.6815 42.5979 70.4502 42.7867 70.2132 42.9868C70.2527 43.0352 70.2893 43.0894 70.3287 43.1378C70.5938 42.9946 70.8531 42.8485 71.1209 42.7139C71.2492 42.6436 71.3914 42.6019 71.5253 42.5487C71.5184 42.7303 71.5849 43.0059 71.4878 43.0848C71.1366 43.3836 70.7234 43.6082 70.3552 43.8842C70.1241 44.0588 69.9182 44.2818 69.6983 44.4764C69.7462 44.5362 69.797 44.5904 69.8449 44.6503C70.2384 44.3943 70.6319 44.1383 71.0597 43.857C71.1759 44.3429 71.1054 44.7199 70.6891 44.9786C70.4411 45.1304 70.2154 45.3362 69.9479 45.4142C69.3333 45.6008 69.3018 46.0972 69.1677 46.6412C69.729 46.3493 70.2021 46.091 70.6978 45.8441C70.8232 45.7795 70.9822 45.7889 71.1243 45.7614C71.0808 45.9172 71.0823 46.1243 70.9823 46.2231C70.725 46.477 70.4396 46.7024 70.143 46.9078C69.5925 47.2764 68.8785 47.4625 68.6887 48.2843C69.5406 47.8408 70.3498 47.4254 71.1534 47.0072C71.3519 47.4992 71.3487 47.5616 70.9352 47.8147C70.3022 48.2197 69.6157 48.5477 69.0052 48.9784C68.1579 49.5808 68.0286 49.8071 68.002 50.434C69.1247 49.836 70.2246 49.2549 71.3274 48.6682C71.3895 48.7281 71.4488 48.7937 71.5136 48.8622C71.3931 49.0573 71.3176 49.3179 71.1436 49.4361C70.5134 49.8496 69.8156 50.1578 69.2164 50.6084C68.7912 50.9266 68.4251 51.3246 67.8849 51.4208C67.3533 51.5143 67.3936 51.8692 67.3542 52.2691C68.3374 51.7213 69.2553 51.1903 70.1928 50.6905C70.4265 50.567 70.7247 50.5687 70.9835 50.5077C70.8143 50.7707 70.6394 51.0307 70.4702 51.2937C70.4444 51.3304 70.4045 51.3529 70.3731 51.3726C69.6749 51.7516 68.974 52.108 68.3011 52.5213C68.1586 52.6056 68.1256 52.8807 68.042 53.0732C68.6574 52.773 69.2671 52.4701 69.9394 52.1419C69.9702 52.2073 70.1645 52.4695 70.113 52.5288C69.8438 52.8763 69.504 53.1666 69.3011 53.3697C69.4933 53.5099 69.8674 53.6425 69.9624 53.8899C70.1133 54.2653 69.7855 54.4621 69.4463 54.6531C68.9561 54.9313 68.5135 55.3118 68.0513 55.6468C68.0906 55.7095 68.1329 55.7665 68.1694 55.8348C68.48 55.6578 68.8953 55.5552 69.0788 55.2923C69.3827 54.8344 69.6551 54.8728 69.9713 55.1754C70.454 55.6265 70.4631 55.9869 70.0519 56.3477C69.8691 56.5113 69.516 56.6597 69.5235 56.8129C69.5479 57.4515 69.0283 57.4372 68.6609 57.5855C68.1142 57.8207 67.545 58.0019 66.9871 58.2031C68.1067 58.1016 69.1927 57.9262 70.2816 57.7451C70.6199 57.6818 70.9615 57.556 71.3023 57.558C72.3673 57.564 73.4262 57.6381 74.4882 57.6499C75.9308 57.6694 77.3795 57.6351 78.8248 57.6774C80.1025 57.713 80.7722 58.2588 80.9891 59.4291C81.0688 59.8466 80.9409 60.3084 80.887 60.7508C80.8627 60.9947 80.7931 61.2298 80.7461 61.4764C85.4033 58.4071 90.0233 55.3831 93.9084 51.3532C93.4001 51.3446 93.2884 51.0461 93.4953 50.667C94.363 49.0858 94.465 47.3299 94.6491 45.6086ZM93.1918 55.089C94.3334 53.7533 95.4439 52.3948 96.167 50.7759C96.2333 50.6173 96.1807 50.4127 96.1819 50.2283C95.1666 52.24 93.4146 53.5296 92.1769 55.2364C92.1374 55.2022 92.0836 55.1678 92.047 55.1279C93.0203 53.9133 93.9936 52.6987 94.964 51.4897C93.4562 52.7893 92.0077 54.1544 90.4944 55.4368C89.2752 56.4628 87.9855 57.4032 86.6988 58.3379C85.3149 59.3515 83.9199 60.3452 82.4882 61.2848C81.8893 61.6787 81.5353 61.9689 81.6718 62.8351C81.839 63.7952 81.6365 64.8241 81.5791 65.8197C81.544 66.4211 81.4806 67.0222 81.4191 67.7597C81.8213 67.4867 82.098 67.2925 82.4945 67.0167C82.4632 67.4705 82.3246 67.8414 82.4365 68.0974C82.5988 68.4786 82.5095 68.6824 82.2243 68.8794C81.959 69.0651 81.6937 69.2509 81.4143 69.4082C80.9583 69.661 80.743 70.0287 80.7843 70.6758C81.3349 70.2931 81.8141 69.9667 82.3247 69.6064C82.7795 70.0005 82.2692 70.3041 82.094 70.6067C82.498 70.9466 82.3651 71.3063 82.0937 71.5601C81.6966 71.921 81.2065 72.185 80.7953 72.5316C80.3756 72.8811 79.8315 73.1391 79.6874 73.9271C80.1551 73.6233 80.5115 73.3983 80.8596 73.1478C80.9965 73.0464 81.1167 72.908 81.2226 72.7696C81.3201 72.6339 81.4355 72.3367 81.4667 72.3454C81.6907 72.409 81.9429 72.5013 82.0781 72.6695C82.1514 72.7635 82.0782 73.1036 81.9612 73.1937C81.2848 73.712 80.586 74.1904 79.8728 74.6971C79.8948 74.8079 79.9192 74.984 79.9658 75.2566C80.6161 74.8177 81.2122 74.4153 81.8055 74.0044C82.1636 74.4207 82.2267 74.7729 81.6201 75.0277C81.4123 75.1145 81.2324 75.2582 81.0527 75.3877C80.425 75.8381 79.5742 76.0971 79.5217 77.2092C80.2861 76.6999 80.9935 76.2187 81.7036 75.746C81.7806 75.6926 81.869 75.6448 81.9515 75.6226C82.1364 75.5669 82.3891 75.5882 82.5006 75.4668C83.2151 74.7473 83.9269 74.0193 84.5907 73.2456C85.5435 72.1273 86.4851 70.9892 87.3786 69.8195C88.1862 68.7629 89.042 67.7094 89.6771 66.5439C90.4817 65.0588 91.0911 63.4534 91.7967 61.911C91.8428 61.8062 91.9739 61.7304 92.0625 61.6401C92.11 61.7709 92.1943 61.899 92.1992 62.0296C92.2014 62.1374 92.1154 62.2504 92.0636 62.3665C91.7261 63.1846 91.4142 64.0086 91.0342 64.8122C90.5938 65.7348 90.1817 66.6858 89.5914 67.511C88.5656 68.941 87.4267 70.2994 86.3019 71.6578C85.4033 72.7395 84.4538 73.7811 83.5354 74.8456C83.1034 75.3454 82.6912 75.8623 82.2733 76.3764C82.1186 76.5826 81.8396 76.6974 81.5661 76.8292C81.1843 77.02 80.8139 77.2165 80.4406 77.4187C79.9248 77.691 79.2625 77.7752 79.0562 78.5174C79.8481 78.136 80.6112 77.8254 81.3182 77.401C81.7059 77.1705 81.8697 77.3247 81.9502 77.6145C81.9891 77.7481 81.8168 78.0451 81.6687 78.1123C80.8399 78.4964 79.9915 78.8207 79.1542 79.1791C79.0261 79.2352 78.9344 79.3595 78.8202 79.4581C78.8483 79.5009 78.8736 79.5493 78.9074 79.5948C79.0554 79.5418 79.2061 79.5114 79.3513 79.4498C80.254 79.0747 81.1622 78.7167 82.0368 78.2847C82.3673 78.1248 82.5771 78.1743 82.6577 78.4641C82.6882 78.5722 82.4508 78.8432 82.2771 78.9188C81.3287 79.3277 80.3579 79.7109 79.2872 80.1503C79.568 80.2144 79.7463 80.3118 79.9083 80.2872C80.5792 80.1861 81.3034 80.1902 81.893 79.9126C83.4483 79.1922 84.9418 78.3409 86.4691 77.5494C86.6144 77.4737 86.8419 77.4324 86.9721 77.4984C87.091 77.5587 87.1833 77.7833 87.1823 77.9394C87.189 78.2204 87.1304 78.5038 87.0911 78.8895C91.1654 74.5854 94.3085 69.7738 96.855 64.5531C96.1736 65.4175 95.4922 66.2819 94.7106 67.2734C94.6922 67.0435 94.6838 67.0179 94.6925 67.0009C95.2719 66.0849 95.7921 65.1174 96.4479 64.2614C97.1122 63.4025 97.2017 62.2879 98.0759 61.4643C98.6988 60.8691 98.7944 59.6864 99.0502 58.7487C99.2566 58.0064 99.3921 57.2354 99.4794 56.4612C99.5545 55.809 99.5133 55.1476 99.5259 54.4923C99.4465 54.4804 99.3699 54.463 99.2905 54.4512C99.0822 59.078 97.2852 62.9921 94.0893 66.2682C94.1102 66.1151 94.1962 65.9879 94.2793 65.8664C94.9156 64.9507 95.5773 64.0549 96.1683 63.1162C96.5356 62.5196 96.7219 61.8028 97.1006 61.2119C97.8607 60.0245 98.1163 58.6809 98.4513 57.3492C98.7543 56.1507 98.4672 54.8381 99.1957 53.7271C99.2215 53.6903 99.2221 53.591 99.1939 53.5483C98.9212 53.1183 98.6602 52.6231 98.2878 52.2351C98.0988 52.0325 97.7184 52.0105 97.568 52.4324C97.1222 53.7578 96.77 55.1235 95.9191 56.2792C95.5066 56.8387 95.1054 57.4039 94.6929 57.9634C94.6421 57.9234 94.5827 57.8862 94.5289 57.8518C95.496 56.2712 96.5906 54.748 96.7705 52.7968C96.4503 53.1326 96.1839 53.4886 95.9401 53.8703C95.7106 54.2379 95.5404 54.6427 95.2997 54.9903C94.8755 55.6008 94.4174 56.1799 93.9735 56.7591C93.9227 56.719 93.8689 56.6847 93.8095 56.6475C94.7704 55.149 95.8162 53.6937 96.1941 51.8855C95.0323 53.2607 93.9021 54.5879 92.7661 55.9265C92.7125 55.8779 92.6588 55.8294 92.6079 55.7894C92.8083 55.5493 92.9972 55.3177 93.1918 55.089Z\"\n        fill=\"#676461\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 105 / 111,\n  svg: Artichoke,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/carrot.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Carrot', 'sticker name', 'web-stories');\n\nfunction Carrot({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 135 186\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M5.04142 12.8291C5.58282 12.6752 5.77291 12.5662 5.96247 12.5742C7.22389 12.6203 8.47817 12.6922 9.73959 12.7384C10.2919 12.7599 10.6816 13.0215 11.0379 13.4186C11.6854 14.1329 12.3681 14.8123 13.032 15.5056C14.0216 14.6055 15.8472 14.6147 16.6504 15.5661C17.7097 16.8227 18.6586 18.1701 19.6991 19.4407C21.7359 21.9185 23.7845 24.3848 25.8706 26.8231C27.8706 29.1651 29.9199 31.4676 31.9575 33.7817C32.3323 34.2117 32.7543 34.595 33.2302 34.9296C28.6544 25.6467 23.1277 16.9789 17.0857 8.40195C17.1374 8.34608 17.2935 7.99137 17.4809 7.96894C19.174 7.78808 20.2931 6.71321 21.4053 5.59386C21.5229 5.47751 21.6777 5.40344 21.9266 5.2363C23.5919 7.05738 24.5576 9.33335 25.9671 11.3005C27.351 13.2371 28.5399 15.3154 29.9659 17.2615C29.4011 15.874 28.902 14.4495 28.2574 13.1037C27.3323 11.1647 26.2923 9.279 25.3085 7.37484C24.972 6.72994 25.1187 6.39389 25.9269 6.24596C27.0982 6.04141 28.2439 5.80633 29.2685 4.8947C30.7514 7.20368 32.1877 9.44224 33.6218 11.6738C33.7015 11.6321 33.7813 11.5904 33.8634 11.5557C33.3723 10.4166 32.9094 9.26816 32.3856 8.14752C31.4536 6.1641 30.4818 4.20153 29.5171 2.23666C29.2921 1.78879 28.9943 1.3803 28.7482 0.939343C28.4835 0.465547 28.6771 0.106353 29.2179 0.0927265C30.2058 0.0649977 31.1573 0.306054 32.0142 0.780518C32.271 0.922154 32.4614 1.26459 32.5958 1.55529C34.3394 5.20343 36.0431 8.87241 37.8148 12.5113C38.6659 14.2488 39.6859 15.9075 40.5581 17.6381C42.2027 20.9138 43.8098 24.2175 45.4075 27.5164C46.4 29.5656 47.4346 31.601 48.3051 33.7057C49.8935 37.5215 51.3786 41.3788 52.8848 45.2292C53.572 46.9892 54.1889 48.7722 54.8547 50.5859C55.2415 50.4592 55.4898 50.409 55.7104 50.2978C57.3527 49.4408 59.1172 49.0264 60.9545 49.0475C62.1294 49.0674 63.3133 49.1857 64.4639 49.4161C66.4095 49.8142 68.3169 50.3806 70.0704 51.332C70.5444 51.5894 71.0041 51.8981 71.4333 52.2324C75.4287 55.3377 78.3039 59.2769 80.2535 63.9318C80.712 65.0194 81.2338 66.0862 81.8073 67.1206C83.0145 69.3018 84.2593 71.4552 85.5181 73.604C87.0371 76.1892 88.5985 78.7371 90.1105 81.3246C90.942 82.7415 91.6937 84.2001 92.4924 85.6355C92.7988 86.1891 93.1241 86.7287 93.4493 87.2683C95.4263 90.5364 96.7208 94.1214 98.1607 97.6277C99.1376 100.009 99.927 102.459 100.897 104.843C101.971 107.496 103.056 110.161 104.306 112.733C106.187 116.609 108.201 120.417 110.195 124.233C112.074 127.821 114.074 131.346 115.892 134.962C117.732 138.618 119.463 142.324 121.141 146.056C122.279 148.595 123.233 151.217 124.289 153.79C125.479 156.678 126.683 159.561 127.906 162.43C128.482 163.782 129.153 165.088 129.716 166.446C130.718 168.857 131.678 171.283 132.639 173.709C133.215 175.155 133.815 176.577 134.051 178.15C134.194 179.084 134.281 179.966 134.111 180.894C134.013 181.424 134.048 181.981 133.952 182.519C133.846 183.098 133.768 183.715 133.49 184.219C132.727 185.597 131.827 185.846 130.273 185.358C129.02 184.959 128.06 184.145 127.075 183.354C124.475 181.271 121.774 179.283 119.34 177.021C117.31 175.132 115.612 172.902 113.748 170.834C112.023 168.924 110.175 167.116 108.588 165.106C107.536 163.777 106.152 162.836 105.067 161.572C103.225 159.428 101.341 157.32 99.4502 155.215C96.0175 151.38 92.6483 147.479 89.1005 143.744C86.1956 140.686 83.058 137.845 80.0379 134.887C78.5255 133.413 77.0766 131.872 75.5478 130.418C73.0121 128.011 71.0215 125.152 68.803 122.477C67.3993 120.788 65.9156 119.164 64.6058 117.406C61.9071 113.79 59.3071 110.095 56.66 106.447C54.4549 103.41 52.1981 100.404 50.0165 97.3435C49.2094 96.2144 48.6466 94.9041 47.7972 93.8122C45.3817 90.7033 43.1776 87.4551 41.18 84.077C40.0139 82.1157 39.2748 79.9368 38.8732 77.6708C38.2138 73.9088 38.2007 70.1221 38.6229 66.333C38.9475 63.4087 40.311 61.0861 42.6597 59.3205C42.8594 59.1694 43.0544 59.0044 43.2285 58.8228C43.4025 58.6413 43.5532 58.4362 43.9857 58.0455C43.7713 57.8433 43.5521 57.6504 43.3447 57.4458C41.5341 55.6801 39.6576 53.9749 37.9292 52.1278C35.926 49.9893 33.6755 48.1652 31.2815 46.5205C28.6051 44.6803 25.9099 42.8539 23.1015 41.2282C19.3802 39.0763 15.5505 37.1155 11.749 35.0989C9.39996 33.852 7.06278 32.5701 4.64749 31.4773C3.48655 30.9545 2.13183 30.8377 0.738281 30.5079C0.778914 30.3233 0.743147 29.9536 0.898182 29.8327C2.58237 28.5339 3.23665 27.7513 5.27775 28.7721C7.46601 29.8614 9.72985 30.8014 11.9653 31.7975C14.8572 33.0845 17.7705 34.3178 20.6387 35.6515C22.2831 36.413 23.8637 37.3121 25.4773 38.1459C26.2572 38.5522 27.0536 38.9375 27.9864 39.1925C26.9788 37.9033 25.9899 36.6002 24.9588 35.3343C22.375 32.1637 19.8008 28.9745 17.163 25.8527C15.3145 23.6635 13.3132 21.6021 11.4717 19.4106C9.95852 17.602 8.35599 15.8771 6.71346 14.1965C6.28011 13.7546 5.76205 13.4105 5.04142 12.8291ZM31.297 18.4447C31.3821 18.7749 31.4649 19.0981 31.55 19.4283C31.6391 19.3914 31.7283 19.3544 31.8103 19.3197C31.6291 19.0288 31.4431 18.7472 31.2619 18.4562C31.1582 18.0932 31.0522 17.7231 30.9485 17.3601C30.8477 17.4087 30.7491 17.4643 30.6553 17.5106C30.8692 17.8298 31.0878 18.1396 31.297 18.4447ZM40.6548 39.5819C40.5678 40.1708 40.76 40.6372 41.1491 41.0158C41.2359 40.9718 41.3227 40.9278 41.4095 40.8838C41.1447 40.4568 40.8868 40.0274 40.6219 39.6004C40.4812 39.1483 40.3452 38.6869 40.2045 38.2347C40.1224 38.2694 40.0333 38.3064 39.9512 38.341C40.0332 38.8279 40.2701 39.2408 40.6548 39.5819ZM46.801 53.0289C47.2099 53.7045 47.8189 54.1123 48.5836 54.2822C49.4058 55.1728 50.7321 55.8672 51.5634 55.7895C50.5288 55.2721 49.5433 54.7852 48.5577 54.2984C47.9604 53.8791 47.3725 53.4645 46.7752 53.0451C46.6017 52.5881 46.2751 52.3526 45.7267 52.4855C46.084 52.6721 46.439 52.8516 46.801 53.0289ZM53.6746 56.3358C53.8728 56.4889 54.0711 56.6419 54.2506 56.7855C56.3579 55.6127 56.8598 54.8879 56.718 53.1283C55.8693 54.4572 54.8511 55.4835 53.6792 56.3499C53.4324 56.5708 53.2065 56.8317 52.9388 57.0127C50.8163 58.4474 48.7124 59.9149 46.3621 60.9882C45.9141 61.1894 45.5665 61.4589 45.8727 62.0592C46.807 61.9868 47.5024 61.4243 48.2373 60.9345C48.4932 60.7651 48.8195 60.5492 49.0932 60.5764C49.8887 60.6506 50.2489 60.2057 50.5209 59.5872C50.6817 59.2232 50.7259 58.765 51.3368 58.7751C51.3263 59.0277 51.3229 59.2545 51.3072 59.6099C52.6427 58.8145 53.357 57.7165 53.6746 56.3358ZM25.1681 40.24C23.5688 39.3548 21.9789 38.4509 20.3677 37.6008C19.7559 37.2796 19.0898 37.054 18.4497 36.7888C20.7104 36.8891 22.4599 38.2078 24.368 39.132C26.2925 40.0586 28.2123 40.9945 30.1507 41.9399C29.9293 41.2184 29.4161 40.8416 28.7714 40.539C27.057 39.7304 25.371 38.8658 23.6708 38.0292C21.6343 37.0225 19.6262 35.9598 17.5636 35.0161C14.7303 33.7177 11.8732 32.4893 9.00443 31.2725C7.37611 30.5837 5.71704 29.9671 4.06741 29.3319C3.39914 29.076 2.86236 29.244 2.43092 29.9224C2.73708 30.0245 2.966 30.1286 3.20919 30.1813C4.83669 30.5357 6.28678 31.2985 7.72259 32.1127C9.87977 33.3446 12.077 34.5088 14.272 35.666C17.0227 37.116 19.7971 38.5194 22.5454 39.9858C26.4706 42.0709 30.0681 44.6526 33.6775 47.2226C33.9434 47.4158 34.2094 47.6089 34.4753 47.802C34.5318 47.7368 34.5883 47.6717 34.6495 47.5971C34.0952 46.9768 33.621 46.2681 32.9843 45.7526C31.6131 44.6371 30.1712 43.6147 28.7317 42.5759C28.3631 42.3074 27.9286 42.1228 27.5058 41.9265C26.4758 41.4465 25.4315 40.9944 24.4062 40.5051C24.2404 40.4271 24.1501 40.1997 23.8638 39.8498C24.4857 40.012 24.8457 40.1121 25.2034 40.2051C26.2495 40.7577 27.305 41.315 28.3511 41.8676C28.3889 41.793 28.4243 41.7113 28.4621 41.6367C27.4044 41.0723 26.3796 40.466 25.1681 40.24ZM27.5461 9.96597C27.6064 10.0785 27.6668 10.1911 27.7271 10.3037C28.1119 11.143 28.3084 12.1918 28.9283 12.775C29.9632 13.7438 30.4751 14.9229 31.029 16.1349C31.8332 17.8955 32.6492 19.6444 33.4534 21.405C34.2042 23.0507 35.077 24.6643 35.631 26.3745C35.9887 27.4873 36.3349 28.5649 36.9225 29.5712C37.7284 30.9576 38.5155 32.3579 39.3472 33.728C39.5819 34.1105 39.941 34.421 40.239 34.7593L40.2159 34.6891C40.4459 36.1006 41.3585 37.1951 41.945 38.4354C42.2 38.9746 42.5911 39.4537 42.9212 39.9606C42.3895 37.9862 41.7333 36.1071 41.0959 34.2141C40.0866 31.2128 39.0774 28.2116 37.5852 25.3997C36.9911 24.2787 36.3383 23.1925 35.7324 22.0832C35.5909 21.8181 35.2832 21.5219 35.6848 21.2269C38.9035 25.8087 40.6656 31.031 42.4582 36.2511C42.4602 33.7672 42.0286 31.3864 41.1496 29.0899C41.0918 28.9375 41.004 28.6938 40.887 28.6699C39.933 28.4686 39.7848 27.5907 39.4391 26.9177C37.3857 22.9429 35.3276 18.9774 32.887 15.2228C32.7452 15.0046 32.6879 14.7353 32.5907 14.4869C32.7081 14.4173 32.8184 14.3501 32.9358 14.2805C33.7746 15.6249 34.5759 16.9972 35.3749 18.3625C36.2343 19.817 36.9365 21.3619 37.7889 22.8186C38.5925 24.198 39.504 25.5264 40.3662 26.871C36.9551 19.8534 33.8208 12.6829 29.2384 6.36802C28.2213 6.63884 27.298 6.88676 26.1965 7.18523C26.6788 8.17936 27.1125 9.07266 27.5461 9.96597ZM34.937 8.63527C34.8929 8.54851 34.8418 8.46404 34.7978 8.37728C34.7382 8.10099 34.7372 7.78992 34.6166 7.54138C33.7378 5.71962 32.8309 3.90706 31.945 2.08759C31.5555 1.28104 30.8467 1.18622 29.9622 1.1256C30.073 1.46296 30.1281 1.70182 30.2324 1.92454C30.8792 3.30074 31.5658 4.65609 32.1915 6.0392C33.5216 8.99761 34.8188 11.9746 36.1489 14.933C36.5753 15.8754 37.0509 16.8016 37.5031 17.7278L37.4822 17.6879C37.5834 18.0907 37.6283 18.512 37.7834 18.8893C38.5151 20.6425 39.2515 22.3864 40.0323 24.1234C41.6195 27.6749 42.963 31.2906 43.4156 35.2058C43.8456 38.9572 44.7042 42.6617 44.6678 46.5347C45.1394 46.8084 45.6296 47.0915 46.2576 47.4619C46.2478 47.0292 46.2534 46.8327 46.2356 46.6362C45.9872 44.1253 45.7833 41.6077 45.467 39.1035C45.0175 35.5297 43.9634 32.1073 42.6046 28.7768C41.9124 27.0963 41.1334 25.4598 40.4083 23.7979C40.3342 23.6198 40.3422 23.407 40.3151 23.2057C40.6281 23.3523 40.7863 23.5496 40.9024 23.7606C41.1485 24.2016 41.3828 24.6542 41.6031 25.1114C41.8234 25.5686 42.0156 26.035 42.2218 26.4968C42.4141 26.9164 42.6088 27.3431 42.8012 27.7627C43.0074 28.2246 43.2277 28.6817 43.4198 29.1482C43.6049 29.6169 43.7642 30.1018 43.9353 30.5752C44.6858 30.2515 44.6569 30.946 44.8519 31.3025C45.3509 32.2289 45.8171 33.1738 46.3043 34.1119C48.1586 37.6226 49.8158 41.2212 51.0696 44.9908C51.693 46.865 52.1969 48.7785 52.7755 50.7297C53.1451 50.7877 53.4819 50.8409 53.9333 50.911C53.3075 49.0531 52.7582 47.3335 52.1387 45.6371C51.4637 43.7719 50.7207 41.9368 50.0128 40.0901C49.3628 38.3958 48.8019 36.6646 48.051 35.0189C45.787 30.0232 43.4572 25.0647 41.1274 20.1061C40.8098 19.4239 40.3304 18.818 39.919 18.1821C39.8744 18.2123 39.8298 18.2425 39.7781 18.275C41.8663 22.83 43.9475 27.3873 46.0357 31.9424C45.9559 31.9841 45.8784 32.0328 45.7987 32.0745C45.5965 31.7437 45.3663 31.4221 45.204 31.0704C43.7667 28.0226 42.3692 24.9539 40.8967 21.9176C39.4381 18.9234 37.8856 15.9756 36.4317 12.9721C36.1372 12.3602 35.1968 11.7262 36.1789 10.922C36.2094 10.8964 36.1866 10.7559 36.1472 10.6832C35.7267 9.99582 35.3318 9.31555 34.937 8.63527ZM10.3741 16.8042C11.0908 17.7294 11.777 18.6801 12.529 19.5703C15.2971 22.8518 18.1146 26.0938 20.8709 29.3869C23.2804 32.2642 25.5419 35.2601 28.0407 38.0537C30.2345 40.5113 32.1604 43.1734 34.1663 45.7703C36.7422 49.107 39.1749 52.5528 42.1549 55.5546C42.3297 55.731 42.5467 55.87 42.745 56.0231C42.3986 54.9922 42.4014 53.8626 41.4753 53.1772C41.3499 52.938 41.2176 52.7011 41.09 52.4549C39.5084 49.7268 37.894 47.0172 35.8452 44.5977C34.2923 42.7632 32.6971 40.9658 31.2312 39.0639C29.2766 36.528 27.4958 33.8573 25.5271 31.326C23.1326 28.2336 20.6324 25.2224 18.1558 22.188C17.49 21.3707 16.7515 20.6162 16.0247 19.85C14.161 17.8993 12.2856 15.9602 10.4032 14.0234C10.2145 13.8283 9.9251 13.6351 9.67004 13.6174C8.9751 13.5648 8.27039 13.601 7.24513 13.6098C8.44265 14.8368 9.41652 15.8334 10.3927 16.837L10.3741 16.8042ZM69.5862 64.1092C69.2149 64.4254 68.832 64.7298 68.4631 65.0531C68.2516 65.2391 67.9675 65.4178 67.8985 65.6583C67.6563 66.4149 67.5077 67.1953 67.3005 67.9637C67.2386 68.202 67.1018 68.4258 66.8889 68.9159C66.5062 67.6323 67.2124 66.7471 67.1866 65.7436C64.0203 67.6524 61.5488 68.6175 60.6023 68.2969C62.2 67.4935 63.7554 66.7038 65.2194 65.9675C65.8874 62.1679 67.5742 58.7663 67.5539 54.9819C66.242 58.3152 64.9278 61.6414 63.6088 64.977C63.513 64.9461 63.4219 64.9059 63.3261 64.875C64.0232 62.9185 64.7951 60.9765 65.3963 58.9892C65.9976 57.0018 66.8861 55.154 67.642 53.116C68.4494 54.6965 68.4424 54.6988 68.2397 56.0262C67.9142 58.1179 67.273 60.126 66.6203 62.1225C66.2927 63.1172 66.0658 64.11 66.201 65.2568C66.9756 64.7929 67.7399 64.5115 68.027 63.6546C68.6867 61.7026 69.4842 59.7911 69.6832 57.7175C69.7348 57.1869 69.5899 56.6272 69.5159 55.9041C69.5371 55.8738 69.6903 55.6524 69.8788 55.3726C69.5468 55.2868 69.3318 55.2248 69.0255 55.1461C69.6196 54.2042 70.4204 53.6306 71.2888 53.1204C67.7559 50.214 59.5026 48.6822 56.2537 51.2642C56.4064 51.6579 56.5707 52.0634 56.7628 52.5532C57.2148 51.9848 57.5679 51.5422 57.9517 51.0507C58.1448 51.3066 58.2402 51.431 58.3285 51.5578C58.5214 51.3623 58.7189 51.1575 59.0505 50.8153C59.104 51.405 59.1374 51.7677 59.1887 52.3269C59.4323 51.7879 59.5765 51.4682 59.787 50.9945C59.9822 51.3042 60.0938 51.4779 60.1681 51.6092C60.3675 51.505 60.5669 51.4007 60.9329 51.2108C60.8665 51.9332 60.8242 52.4686 60.77 53.0624C61.582 52.594 61.4709 51.3071 62.8122 51.2882C62.2331 53.0347 61.6967 54.6505 61.1604 56.2663C61.8062 55.2919 62.286 54.2629 62.7868 53.2504C63.0491 52.7208 63.3277 52.1936 63.6599 51.7111C63.7871 51.5293 64.0777 51.4653 64.5563 51.2152C64.2825 52.7528 63.774 53.9079 63.3917 55.0918C62.9239 56.5606 62.1103 57.9013 61.8807 59.4789C61.7479 60.3787 61.2991 61.2651 60.484 61.8902C61.3511 59.0996 62.515 56.4065 63.1039 53.528C61.7348 55.5488 61.1619 57.9783 59.7041 59.9426C59.8529 57.5975 60.9929 55.5193 61.3147 53.2265C60.855 53.9375 60.5215 54.7007 60.202 55.4592C59.892 56.199 59.6101 56.953 59.2627 57.674C58.9248 58.3763 58.874 59.2414 57.9625 59.9759C58.2483 58.9014 58.4578 58.1166 58.6674 57.3318C58.2435 57.891 58.1138 58.6107 57.3291 59.2569C57.5023 57.1996 58.3103 55.5572 58.4962 53.7993C57.2226 57.4625 55.9489 61.1257 54.6278 64.929C56.1625 64.5977 57.1965 63.6908 58.3675 63.0348C58.54 63.2041 58.6821 63.3522 58.8568 63.5285C57.4452 65.1117 55.7948 66.1816 53.8047 66.81C53.6079 66.3295 53.4458 65.9545 53.2815 65.549C54.597 65.0248 54.3902 63.6602 54.8674 62.6943C55.3541 61.7098 55.4881 60.5527 55.8073 59.3428C55.5744 59.5825 55.4309 59.7385 55.2804 59.8968C55.2314 59.8661 55.1871 59.8261 55.1381 59.7955C55.3668 58.9266 55.6025 58.0554 55.8311 57.1865C54.4585 59.9791 53.0928 62.7695 52.1103 65.7302C52.4327 63.8186 53.0309 61.988 53.9525 60.0514C52.7446 60.5949 52.0234 61.1736 51.7587 62.2411C51.5393 63.1381 51.2334 64.009 50.9368 64.8846C50.8443 65.1484 50.6925 65.5873 50.5333 65.6006C49.6411 65.6826 49.5887 66.4003 49.3519 66.9838C49.0868 67.6467 48.8239 68.3167 48.5844 68.9867C48.3616 69.6124 48.1808 70.2477 47.986 70.8641C48.7196 71.1766 48.8175 70.7397 48.9622 70.3265C49.4269 69.0378 49.8985 67.7468 50.9402 66.6972C50.1087 68.8845 49.2238 70.9569 48.5329 73.0982C47.8326 75.2581 47.3496 77.4869 47.2783 79.7833C47.9755 79.843 48.1761 79.5049 48.204 79.0209C48.3232 77.0124 48.9661 75.1282 49.63 73.2605C50.3604 71.1685 51.1633 69.1074 51.9453 67.0064C52.7579 67.4408 52.4749 67.9072 52.2785 68.3763C51.358 70.5538 50.3886 72.7006 49.5569 74.9113C49.0451 76.27 48.6127 77.6805 48.655 79.1846C49.3568 79.2817 49.4847 78.9362 49.5902 78.4035C50.2051 75.4619 51.166 72.6251 52.2672 69.8357C52.4661 69.3268 52.6302 68.7593 53.1445 68.3807C53.2397 68.5519 53.3119 68.6295 53.2999 68.6879C53.2594 68.8491 53.1838 68.9984 53.1269 69.1571C52.1785 71.8186 51.2278 74.4731 50.3051 77.1417C50.0703 77.8258 49.8259 78.552 50.5044 79.1238C49.4977 80.2086 49.437 80.6877 50.2511 81.293C50.6178 79.9196 50.9563 78.5788 51.3323 77.2335C51.7868 75.6056 52.2506 73.9825 52.7659 72.3736C52.9629 71.7641 53.1882 71.1221 53.8708 70.8051C53.7537 71.3261 53.5175 71.7927 53.3514 72.283C52.9031 73.5975 52.4406 74.9166 52.0694 76.2526C51.2459 79.2468 50.1183 82.1928 50.4335 85.4524C49.6718 85.1492 49.7464 85.7319 49.7588 86.0781C49.8111 87.9682 49.9195 89.8633 49.9881 91.7558C49.9968 91.9008 49.8744 92.0499 49.7467 92.3486C49.6145 92.0649 49.5284 91.9686 49.5242 91.861C49.5061 89.6717 49.4154 87.4751 49.5166 85.2934C49.5946 83.5864 49.7427 81.9032 49.1043 80.244C48.4673 80.3203 48.4744 80.8162 48.4512 81.2675C48.3588 83.0726 48.2756 84.8825 48.1855 86.6713C47.0805 87.2433 45.9824 87.8131 44.8633 88.3898C46.6493 90.9342 48.3517 93.366 50.0796 95.8282C50.8932 95.5072 51.7256 95.1957 52.5417 94.8584C53.0084 94.6666 53.3467 94.3924 53.0056 93.7334C52.6985 93.8418 52.27 93.8653 52.1146 94.0797C51.6458 94.7392 51.1441 94.3976 50.4 94.3376C50.7904 93.9373 51.0326 93.6789 51.2843 93.4253C51.2456 92.6673 51.1765 91.9115 51.1612 91.1536C51.1238 89.0952 50.9062 87.0102 51.1518 84.9836C51.4535 82.4872 52.1177 80.0278 52.6954 77.5655C52.8481 76.9161 53.1857 76.284 53.7964 75.8193C51.6028 81.5665 50.9159 87.4429 51.8522 93.6129C52.3326 93.4867 52.717 93.3764 53.0193 93.3008C53.1237 90.939 53.2157 88.7293 53.3124 86.5102C53.406 86.5106 53.4996 86.5111 53.5932 86.5116C53.5954 87.5852 53.5975 88.6587 53.6019 89.7393C54.1527 88.0487 54.4764 86.3547 54.7767 84.6605C54.9065 83.9174 54.9685 83.1576 55.1123 82.4099C55.1794 82.0688 55.2587 81.6224 55.8383 81.8219C55.225 84.9107 54.6165 87.9669 54.0081 91.0231C53.9864 91.1469 53.9716 91.3152 53.8871 91.3662C53.1521 91.8794 53.6996 92.4552 53.6712 93.0328C55.1802 92.6709 55.1896 92.6756 55.2871 91.3126C55.3218 90.8964 55.2675 90.4705 55.2928 90.0496C55.3107 89.7246 55.3637 89.388 55.4378 89.068C55.5905 88.4186 55.7924 87.7764 55.9452 87.127C56.1434 86.2603 56.2925 85.3863 56.5094 84.529C56.5572 84.3187 56.792 84.1562 57.1098 83.7485C56.7909 85.4332 56.4991 86.7977 56.2821 88.1765C56.07 89.5226 55.6497 90.8513 55.7952 92.2904C56.6606 91.937 56.6933 91.9418 56.7802 91.3763C56.932 90.4157 57.0206 89.4526 57.1655 88.4944C57.2571 87.8961 57.3699 87.2909 58.0377 86.6207C57.8841 88.477 57.2779 90.0222 57.3382 91.6761C58.3086 91.3817 58.3063 91.3747 58.4079 90.6408C58.4565 90.2668 58.393 89.8127 59.0233 89.6686C59.0421 90.1528 59.0521 90.5388 59.0727 91.147C60.9987 90.2049 62.7606 89.332 64.5247 88.4663C64.2302 88.8741 63.8615 89.1505 63.4812 89.3918C62.1689 90.2342 60.8474 91.0484 59.5491 91.9096C59.2556 92.1069 58.8984 92.4185 58.8432 92.7246C58.5117 94.5846 58.496 96.4814 58.0943 98.3411C57.9533 98.9789 58.0484 99.6951 58.1554 100.353C58.2259 100.805 58.4885 101.225 58.6065 101.513C58.5656 102.266 58.5394 102.897 58.493 103.823C58.2032 103.202 58.0317 102.845 57.8555 102.475C56.981 102.777 56.1372 103.03 55.6258 103.797C56.6704 105.198 57.6894 106.546 58.6827 107.91C60.7436 110.746 62.7905 113.586 64.8444 116.424C65.4538 117.26 65.8115 117.353 66.7655 117.056C67.45 116.84 68.16 116.678 68.8537 116.489C68.9026 116.543 68.9515 116.597 69.0004 116.651C68.711 116.98 68.4286 117.306 68.0992 117.678C68.9846 118.073 69.5266 117.257 70.3743 117.182C69.855 118.66 68.1635 118.467 67.4117 119.593C69.8466 122.547 72.1075 125.684 74.9097 128.666C75.7221 128.127 76.4922 127.603 77.2832 127.118C77.5038 126.983 77.7828 126.884 78.045 126.876C78.8527 126.845 79.0147 126.745 78.9151 125.992C78.5305 123.066 78.1108 120.152 77.7192 117.229C77.6874 117.014 77.7587 116.78 77.7854 116.553C77.8791 116.554 77.9727 116.554 78.0593 116.557C78.6632 118.087 78.6744 119.734 78.8825 121.34C79.0973 122.99 79.2606 124.649 79.4471 126.355C80.0264 126.103 80.4416 125.92 80.7629 125.784C80.7972 123.896 80.4089 122.311 79.9292 120.732C79.8693 120.526 79.9664 120.276 79.9908 120.042C80.0985 120.038 80.2062 120.034 80.3139 120.03C81.0882 121.676 80.9486 123.551 81.3784 125.286C81.4673 125.296 81.5492 125.308 81.6381 125.318C81.8363 124.949 82.0276 124.583 82.2212 124.224C83.593 124.701 84.2155 123.182 85.47 123.207C84.6729 124.005 83.8664 124.798 82.98 125.68C83.1125 126.392 83.3028 127.256 83.4252 128.127C83.5475 129.044 83.5947 129.971 83.6865 130.89C83.8638 132.568 83.8731 132.573 83.5318 133.502C83.2371 130.897 83.1057 128.387 82.3521 125.808C81.9601 126.038 81.6386 126.221 81.357 126.383C81.4782 128.033 81.5838 129.516 81.6917 131.006C81.5863 131.017 81.4716 131.024 81.3662 131.035C81.2134 129.645 81.0629 128.262 80.8873 126.731C80.3826 127.045 80.0023 127.286 79.6784 127.485C79.7486 128.007 79.803 128.387 79.8504 128.768C79.7801 128.791 79.7098 128.814 79.6395 128.837C79.4326 128.516 79.2258 128.194 79.0049 127.854C78.4605 128.165 77.9466 128.45 77.4396 128.756C76.9537 129.055 76.4771 129.382 75.9911 129.705C78.2636 132.331 86.3637 140.25 87.6332 141.103C88.8451 140.714 90.2737 141.056 91.4698 140.026C91.1017 138.099 90.7501 136.151 90.3493 134.219C90.1476 133.274 89.8218 132.353 89.6061 131.411C89.5624 131.231 89.7578 130.996 89.8453 130.788C90.9085 133.764 91.4848 136.728 91.8033 139.784C92.0773 139.741 92.2905 139.702 92.499 139.673C91.7099 140.235 91.9235 141.146 91.6755 142.146C91.5027 141.548 91.4105 141.22 91.2814 140.78C90.4527 141.316 89.6898 141.815 88.7906 142.398C90.186 143.871 91.5674 145.326 93.0536 146.887C93.5115 146.573 93.927 146.297 94.4506 145.946C94.6752 145.966 95.094 146.008 95.5619 146.057C95.557 145.592 95.5912 145.293 95.5386 145.014C95.0455 142.28 94.5359 139.543 94.0335 136.804C93.9628 136.399 93.6066 135.978 94.1781 135.371C95.3417 138.913 95.7752 142.391 96.0071 145.966C96.2621 145.984 96.5406 146.001 96.8822 146.022C96.6611 146.273 96.4893 146.462 96.1341 146.851C96.7156 146.629 97.0204 146.514 97.2831 146.412C97.3352 146.263 97.3848 146.176 97.3828 146.099C97.1502 143.708 97.0278 141.296 96.069 139.041C95.9393 138.741 95.716 138.44 96.1572 138.195C97.2846 139.398 98.5495 147.399 97.9446 149.683C97.8 149.053 97.6831 148.507 97.5455 147.899C96.6197 148.163 95.848 148.517 95.203 149.304C95.583 149.655 95.9046 149.97 96.2496 150.261C96.3686 150.363 96.5838 150.378 96.6769 150.495C97.4122 151.453 98.1075 152.455 98.8663 153.39C99.3388 153.975 99.91 154.481 100.455 155.003C100.49 155.038 100.666 154.933 100.882 154.855C100.707 154.655 100.577 154.496 100.4 154.289C100.753 153.963 101.086 153.652 101.399 153.37C101.372 149.066 100.93 145.755 100.077 144.579C99.9484 146.559 100.481 148.299 100.189 150.256C99.6265 146.836 99.0956 143.654 98.5811 140.476C98.5698 140.394 98.713 140.285 98.8615 140.072C99.6372 141.391 99.4594 142.913 100.022 144.223C100.658 143.882 100.307 143.429 100.346 143.05C100.353 142.954 100.443 142.871 100.547 142.689C100.772 143.043 100.937 143.308 101.1 143.566C101.327 143.5 101.533 143.44 101.732 143.382C101.758 143.436 101.793 143.495 101.818 143.549C101.571 143.817 101.334 144.089 101.15 144.289C101.42 147.198 101.69 150.036 101.958 152.915C102.396 152.872 102.82 152.835 103.387 152.781C103.243 151.42 103.095 150.09 102.97 148.761C102.847 147.462 102.234 146.215 102.407 144.843C102.603 144.895 102.746 144.903 102.751 144.941C103.158 147.415 103.557 149.884 103.964 152.429C104.241 152.253 104.513 152.086 104.708 151.967C104.862 151.154 104.153 150.444 104.843 149.533C104.993 149.99 105.095 150.276 105.19 150.564C105.287 150.859 105.377 151.157 105.471 151.445C106.249 151.206 106.668 150.368 107.535 150.543C107.523 150.695 107.543 150.805 107.503 150.849C107.369 151.01 107.242 151.215 107.064 151.289C105.45 151.997 105.493 153.244 105.725 154.732C105.953 156.16 105.876 157.633 105.933 159.086C105.848 159.09 105.757 159.097 105.673 159.101C105.392 157.06 105.453 154.969 104.91 152.866C104.478 153.14 104.161 153.337 103.877 153.516C103.882 154.55 103.884 155.53 103.885 156.503C103.784 156.505 103.683 156.506 103.583 156.508C103.559 156.104 103.544 155.704 103.504 155.296C103.466 154.873 103.405 154.449 103.342 153.902C102.41 154.503 101.64 155.004 100.874 155.496C103.76 159.276 107.077 162.759 108.497 163.501C108.922 163.206 109.368 162.904 109.805 162.598L109.767 162.625C110.294 162.429 110.831 162.238 111.345 162.046C111.293 160.561 110.536 159.322 110.952 157.956C111.151 158.28 111.302 158.62 111.371 158.971C111.522 159.715 111.619 160.462 111.742 161.216C111.847 161.843 111.996 162.44 112.634 162.652C112.302 163.111 112.029 163.488 111.814 163.784C110.807 163.421 110.29 164.408 109.264 164.604C112.459 168.236 115.519 171.718 118.53 175.145C119.234 174.564 119.824 174.083 120.501 173.535C120.197 172.443 119.886 171.307 119.568 170.174C119.469 169.801 119.333 169.41 120.106 169.32C120.397 170.681 120.693 172.032 121.05 173.666C121.5 173.067 121.759 172.718 122.056 172.317C122.341 172.379 122.652 172.449 122.879 172.499C122.883 174.195 122.887 175.82 122.892 177.446C122.831 177.45 122.763 177.457 122.704 177.468C122.505 176.412 122.316 175.361 122.115 174.298C121.383 174.514 121.222 175.042 121.224 175.664C120.357 175.279 120.169 175.94 119.776 176.403C120.266 176.873 120.671 177.301 121.121 177.675C122.147 178.546 123.185 179.405 124.25 180.231C124.5 180.422 124.863 180.817 125.168 180.25C125.008 179.999 124.84 179.75 124.68 179.499L124.67 179.518C125.13 179.235 125.586 178.961 126.13 178.627C125.934 178.1 125.679 177.607 125.578 177.087C125.496 176.647 124.718 176.271 125.409 175.625C126.24 176.59 126.267 177.811 126.633 178.758C127.331 178.631 127.907 178.535 128.627 178.401C128.439 178.945 128.332 179.26 128.204 179.629C128.602 179.584 128.881 179.555 129.169 179.531C128.335 180.217 128.301 180.967 128.646 181.828C128.676 181.896 128.547 182.024 128.424 182.243C128.209 181.729 128.037 181.326 127.797 180.759C127.24 181.081 126.715 181.378 126.1 181.735C126.935 182.38 127.731 182.882 128.378 183.527C129.092 184.227 129.937 184.526 130.859 184.699C131.79 184.877 132.674 184.416 132.793 183.521C133.006 181.941 133.081 180.344 133.14 178.744C133.161 178.286 132.936 177.815 132.775 177.159C132.137 178.014 132.271 178.826 132.078 179.614C132.687 179.664 132.819 179.971 132.688 180.473C132.423 181.447 132.194 182.433 131.93 183.407C131.887 183.561 131.748 183.684 131.529 183.989C131.499 183.353 131.643 182.722 131.44 182.578C130.751 182.096 131.103 181.552 131.147 181.001C131.179 180.671 131.254 180.117 131.112 180.039C130.157 179.527 130.638 178.739 130.636 178.046C130.636 177.05 131.132 176.07 130.711 175.048C130.676 174.966 130.97 174.746 131.111 174.583C131.936 175.48 131.034 176.507 131.484 177.566C131.975 177.071 132.351 176.699 132.727 176.326C131.568 173.413 130.441 170.575 129.279 167.631C128.937 167.845 128.595 167.941 128.554 168.103C128.27 169.418 128.036 170.748 127.801 172.07C127.784 172.138 127.824 172.234 127.875 172.295C128.434 172.976 127.823 172.966 127.213 173.29C127.394 171.542 127.555 170.018 127.726 168.405C127.258 168.449 126.947 168.473 126.537 168.506C126.466 169.261 126.397 169.953 126.328 170.645C126.216 170.635 126.104 170.625 125.991 170.616C126.039 169.837 126.062 169.051 126.149 168.275C126.237 167.522 126.355 166.768 126.543 166.036C126.729 165.298 126.384 164.462 127.035 163.548C127.164 164.035 127.277 164.286 127.292 164.546C127.314 164.92 127.251 165.299 127.252 165.68C127.254 165.78 127.349 165.882 127.445 166.053C127.759 165.802 128.046 165.583 128.311 165.372C124.753 157.266 121.567 149.108 118.069 141.162C117.249 141.228 117.123 141.65 117.044 142.214C116.763 144.088 116.434 145.955 116.105 147.822C116.033 148.243 115.893 148.647 115.779 149.058C115.688 149.041 115.596 149.024 115.507 149.014C115.561 148.631 115.616 148.255 115.669 147.871C115.921 146.123 116.186 144.37 116.419 142.613C116.443 142.426 116.313 142.219 116.251 142.029C116.183 142.036 116.113 142.036 116.052 142.04C115.626 143.635 115.202 145.238 114.775 146.833C114.234 145.399 115.343 144.102 115.003 142.687C114.665 142.915 114.41 143.349 114.021 144.371C113.91 144.104 113.775 143.93 113.783 143.764C113.894 141.875 114.535 140.077 114.796 138.217C114.803 138.144 115.047 138.103 115.288 138.009C115.272 138.621 115.253 139.11 115.236 139.676C115.795 139.314 116.29 138.996 116.826 138.657C112.83 130.5 108.357 122.764 104.171 114.739C103.208 115.008 102.254 115.281 101.391 115.525C100.854 117.849 100.348 120.031 99.844 122.22C99.727 122.196 99.6031 122.174 99.4885 122.158C100.214 119.032 100.921 115.897 100.859 112.671C100.857 112.57 100.97 112.463 101.031 112.365C101.045 112.337 101.108 112.34 101.331 112.283C101.39 113.174 101.442 114.045 101.506 115.044C102.36 114.632 103.099 114.273 103.899 113.886C103.233 112.501 102.691 111.207 102.009 110.006C100.815 107.89 100.093 105.597 99.3707 103.303C98.5816 100.806 97.5954 98.3966 96.4362 95.9583C95.8582 96.4512 94.9735 96.414 94.8734 97.342C94.4942 100.93 93.1681 104.291 92.3237 107.767C92.2831 107.929 92.1841 108.078 92.1179 108.232C92.0314 108.206 91.9497 108.17 91.8632 108.144C92.6029 104.539 93.9506 101.054 94.2229 97.2826C93.8669 97.3369 93.553 97.3774 93.2415 97.4249C92.9843 98.3966 92.7578 99.2959 92.4986 100.19C92.2275 101.12 91.9331 102.049 91.6456 102.976C91.382 103.81 91.2819 104.715 90.6491 105.42C90.6545 104.749 90.7791 104.109 90.9622 103.48C91.1953 102.672 91.5125 101.883 91.7199 101.068C92.1513 99.37 92.5429 97.6693 92.9299 95.9545C93.023 95.5504 93.1964 94.9876 93.0174 94.7271C92.4499 93.9243 93.0056 93.719 93.5197 93.3871C94.0526 93.0413 94.6857 92.8107 94.9813 92.1456C94.5337 92.2532 94.1742 92.5578 93.7711 92.682C92.6319 93.0318 92.3026 93.9025 92.0427 94.9373C91.4756 97.147 90.8313 99.3353 90.2033 101.526C90.132 101.783 89.967 102.016 89.8465 102.266C89.76 102.239 89.6665 102.216 89.58 102.189C89.6879 101.64 89.7677 101.077 89.9176 100.537C90.4315 98.7111 90.9969 96.899 91.4757 95.0607C91.6401 94.423 91.8144 93.6732 91.6322 93.0711C91.3463 92.1295 91.7583 91.6053 92.637 90.8894C92.6988 91.1961 92.7535 91.5051 92.8269 91.847C93.4044 91.471 93.8598 91.1739 94.4491 90.7863C93.4276 88.9568 92.4454 87.2 91.4564 85.4221C90.7787 85.7064 90.1827 86.0261 89.5405 86.2053C88.4976 86.4923 88.0964 87.2154 87.8719 88.1919C87.3991 90.2383 86.8679 92.2728 86.3507 94.3026C86.2959 94.5152 86.171 94.704 86.0788 94.8977C86.1283 92.2503 87.139 89.802 87.4763 87.1771C86.4056 87.4032 85.9069 87.948 85.6242 88.8424C85.0804 90.554 84.4244 92.2323 83.8128 93.9272C83.7469 91.9482 84.7238 90.2271 85.1963 88.2508C84.1676 88.4865 83.3402 88.7419 83.1267 89.8705C83.0188 90.443 82.7985 91.0055 82.6158 91.5636C82.5612 91.7293 82.4435 91.8691 82.2287 92.2586C81.993 91.0903 82.5231 90.3328 82.7048 89.4871C82.4028 89.4926 82.1641 89.5007 81.923 89.5018C82.2825 89.1973 82.6467 88.8834 83.0062 88.5788C82.9247 88.4965 82.8454 88.4213 82.7639 88.339C82.4345 88.7116 82.1051 89.0841 81.7827 89.4543C81.5071 89.8482 81.2314 90.2421 80.9935 90.5847C80.4849 90.7201 79.937 90.7594 79.5006 90.9958C78.2851 91.6585 77.0997 92.3893 75.9353 93.1365C75.717 93.278 75.5775 93.5884 75.485 93.8522C75.2667 94.4919 75.1092 95.1507 74.9167 95.7976C74.6243 96.7808 74.3132 97.7545 74.0115 98.733C73.9273 98.7138 73.8409 98.6877 73.7567 98.6685C74.1878 97.0405 74.6188 95.4125 75.0903 93.6467C74.4649 93.7581 74.0666 93.8263 73.7293 93.8901C73.138 94.722 73.3508 95.7967 72.7225 96.5162C72.636 96.49 72.5496 96.4639 72.4608 96.4307C73.03 94.2748 73.6086 92.1236 74.1969 89.907C74.7393 91.0605 73.7961 92.0778 73.9452 93.2433C74.2381 93.1863 74.6475 93.2235 74.7771 93.0487C75.2222 92.4592 75.9385 92.4348 76.4994 92.1032C77.443 91.5373 78.3446 90.9151 79.2836 90.3351C80.2084 89.7598 80.783 88.9955 81.1483 87.9262C82.2634 84.6574 83.6215 81.4647 83.9814 77.984C84.0181 77.645 84.2068 77.3185 84.3253 76.9917C84.5983 77.1825 84.7051 77.3655 84.688 77.5268C84.6126 78.1509 84.5395 78.782 84.3916 79.3987C83.7209 82.2417 82.8492 85.0182 81.6878 87.695C81.5813 87.9401 81.545 88.2089 81.4806 88.4635C81.567 88.513 81.6534 88.5626 81.7327 88.6144C82.3694 88.0867 82.9992 87.5614 83.6359 87.0337C84.0716 84.8981 85.6906 83.0212 85.0461 80.6323C84.9954 80.4543 85.3243 80.1753 85.4729 79.9398C85.6429 80.1255 85.9324 80.2953 85.9618 80.5036C86.0187 80.8665 85.9794 81.2685 85.8865 81.6259C85.6411 82.5626 85.3467 83.4919 85.0849 84.4262C84.9232 85.0007 84.6327 85.5629 84.7466 86.2418C86.5416 85.2802 86.7499 84.7761 86.3448 82.7603C86.2441 82.2639 86.4702 81.9563 87.1724 81.9599C87.2197 82.3648 87.3138 82.7699 87.2956 83.165C87.2796 83.5906 87.1607 84.011 87.0717 84.5228C87.379 84.391 87.5361 84.324 87.6955 84.264C87.0109 85.0253 86.3968 85.7403 86.4668 86.8071C87.8092 87.0525 87.4795 85.4557 88.3567 85.0439C88.498 85.379 88.6091 85.6462 88.7619 86.0166C89.6277 85.5695 90.3926 85.1712 91.2912 84.7056C89.6133 82.0401 88.0121 79.513 86.425 76.9813C84.8238 74.4308 83.7062 71.5975 81.8962 69.1699C80.1779 70.2464 80.1847 70.2908 79.9618 71.4381C79.6192 73.1695 79.2345 74.8913 78.8335 76.6106C78.621 77.5287 78.357 78.4325 78.0785 79.4579C79.215 79.1713 79.9777 78.7425 80.1328 77.5785C80.3098 76.2439 80.5522 74.919 80.7619 73.5893C80.8149 73.2527 80.6836 72.8053 81.2901 72.7312C81.619 74.5385 80.9911 76.2076 80.6369 77.9038C82.2411 77.7366 81.8093 76.4223 82.2372 75.4959C82.395 75.8101 82.5434 76.1196 82.7452 76.5206C83.1904 76.4059 83.6731 76.2867 84.3715 76.1125C84.0892 76.4151 83.9831 76.59 83.8211 76.6898C82.9126 77.2675 82.4875 78.1074 82.2113 79.1397C81.7515 80.8939 81.1375 82.6052 80.5842 84.3355C80.2305 85.4166 79.8675 86.493 79.5068 87.5764C79.3462 87.3721 79.2863 87.1659 79.3315 86.9954C79.6245 85.8953 79.9174 84.7952 80.243 83.6999C80.6946 82.2053 81.1812 80.7226 81.6327 79.228C81.7087 78.9852 81.6725 78.709 81.6856 78.4167C80.6803 78.6525 80.0488 79.0773 79.8734 80.0611C79.7846 80.5495 79.5297 81.0066 79.3683 81.4876C79.0575 82.4145 78.7583 83.3532 78.4568 84.2849C77.9353 82.6264 79.1446 81.2806 79.2907 79.5202C78.6169 79.9588 78.012 80.1803 77.6777 80.6089C77.3269 81.0586 77.2209 81.7082 77.0077 82.2685C76.9422 82.2588 76.8838 82.2468 76.8159 82.2301C76.7756 81.8463 76.7422 81.4602 76.6995 81.0694C76.226 81.2167 75.7736 81.3571 75.3119 81.4927C75.2701 81.413 75.2261 81.3262 75.1913 81.2442C75.5552 81.0004 75.9099 80.7286 76.2924 80.5177C76.8673 80.2049 77.2623 79.8186 77.4947 79.1509C78.3011 76.8395 79.021 74.5019 79.3013 72.0592C79.3793 71.372 79.3778 70.6797 79.424 69.7771C79.8915 69.3982 80.5329 68.8846 81.1719 68.364C79.4624 69.064 78.3242 70.2229 77.9084 72.0872C77.4758 74.0661 76.8911 76.009 76.3485 77.9616C76.2843 78.1928 76.1031 78.4001 75.9781 78.6123C75.8158 78.2606 75.8241 77.9776 75.8932 77.7137C76.3054 76.123 76.7456 74.5465 77.1437 72.9604C77.6302 71.0029 78.0838 69.0406 78.5632 67.0854C78.5918 66.9826 78.6975 66.9013 78.8858 66.6684C78.9931 67.256 79.0549 67.5627 79.1211 67.9302C79.656 67.6616 80.1581 67.4116 80.5123 67.2333C79.9732 65.8529 79.4431 64.5709 78.9785 63.2751C78.2966 61.3889 77.1524 59.7552 76.048 58.1241C75.211 56.8802 74.1182 55.8058 73.1403 54.6548C72.3214 55.102 71.6364 55.4354 71.0072 55.8438C70.756 56.0039 70.5322 56.3185 70.449 56.6105C69.923 58.5187 69.4461 60.4341 68.9459 62.3494C68.8672 62.6554 68.7816 62.9637 68.6434 63.4916C69.7439 62.8821 70.6917 62.4238 70.91 61.2625C71.1738 59.8605 71.3792 58.4465 71.5917 57.0302C71.6545 56.6049 71.6983 56.2169 72.4662 56.1833C72.2084 57.8169 71.9602 59.3616 71.688 61.07C72.5472 60.5083 73.1697 60.032 73.263 59.0595C73.2976 58.6668 73.2953 58.1382 73.8675 57.9119C74.0247 58.343 74.1657 58.725 74.2119 58.8655C73.9245 59.7692 73.7061 60.4557 73.4472 61.28C74.6811 61.1951 75.1229 59.7893 76.4393 60.0977C75.3808 60.7168 75.1377 61.6839 74.9271 62.6792C74.8268 63.1324 74.7194 63.588 74.5746 64.0246C73.5067 67.2234 72.4318 70.4246 71.3405 73.6233C71.3002 73.7377 71.1431 73.8047 70.8352 74.0768C71.9808 69.7393 73.8405 65.892 74.5598 61.6318C73.5965 61.9006 73.1516 62.4433 72.9303 63.2397C72.7637 63.847 72.5129 64.4351 72.2949 65.0281C71.4416 67.3626 70.4294 69.6402 69.8165 72.1374C69.2286 71.6994 69.8447 71.085 69.5426 70.5923C68.7702 71.11 68.0284 71.5787 67.3075 72.0872C65.2598 73.5363 63.0174 74.5821 60.6427 75.3676C60.2418 75.4988 59.8408 75.6535 59.4714 75.0505C61.5826 73.534 63.919 72.4185 66.2066 71.2256C64.6924 72.2119 63.1781 73.1983 61.5817 74.2427C61.8294 74.3328 61.9227 74.4034 61.979 74.385C64.8002 73.2042 67.3752 71.6058 69.7876 69.7492C69.8885 69.6772 69.978 69.5701 70.0276 69.4604C70.8614 67.3036 71.6881 65.149 72.5669 62.8683C71.299 63.2057 70.559 63.7984 70.2495 64.9429C69.8567 66.4027 69.3703 67.8386 68.9166 69.2794C68.9048 69.3144 68.7877 69.3138 68.6237 69.3598C68.6154 69.1211 68.5416 68.8728 68.5987 68.6673C68.9386 67.544 69.3135 66.4326 69.6697 65.3118C69.8003 64.9032 70.1862 64.442 69.4924 64.1555C69.763 63.8411 70.0406 63.5244 70.3112 63.2101C70.2576 63.1654 70.2017 63.1136 70.148 63.0689C69.6875 63.4455 69.22 63.8243 68.588 64.3427C69.0989 64.2143 69.3472 64.1641 69.5862 64.1092ZM34.0642 26.5606C34.1721 26.5097 34.2707 26.4541 34.3786 26.4032C30.3082 19.7027 26.3271 12.9419 21.9726 6.4434C20.7561 7.31664 19.6853 8.08771 18.5933 8.86569C18.8462 9.35112 19.0731 9.89958 19.3822 10.39C21.8365 14.2335 24.2766 18.0817 26.7755 21.895C29.723 26.3866 32.2505 31.1169 34.7521 35.8635C35.1071 36.5412 35.563 37.1704 35.9768 37.8133C36.0753 37.7577 36.1669 37.7044 36.2654 37.6487C35.2059 35.4191 34.2284 33.1548 33.0703 30.9807C31.9239 28.8185 30.5733 26.7698 29.3682 24.6423C28.1677 22.5289 26.6269 20.6125 25.6869 18.3437C25.9159 18.4244 26.0557 18.5655 26.1626 18.7251C26.7018 19.5838 27.2198 20.4495 27.7496 21.3035C29.5851 24.2832 31.5544 27.1958 33.2257 30.2682C34.7298 33.045 35.9031 36.0003 37.2218 38.8768C37.6043 39.7091 38.0713 40.4669 39.0355 41.0074C38.5278 39.9359 38.0966 39.0263 37.6724 38.1143C37.225 37.1554 36.7518 36.2128 36.3747 35.2309C36.037 34.3451 35.2655 33.6325 35.2772 32.6011C35.4686 32.7331 35.606 32.8904 35.6941 33.064C37.153 36.0113 38.64 38.9495 40.0449 41.9223C40.5016 42.8859 41.1349 43.6282 42.1192 44.3957C41.3056 42.6304 40.6153 41.0505 39.857 39.5006C39.2238 38.2134 38.5297 36.9539 37.8238 35.706C37.3316 34.8241 36.7666 33.9816 36.2581 33.0972C36.1629 32.926 36.1921 32.6829 36.1696 32.4723C37.1361 33.5414 37.6262 34.8911 38.6775 35.839C38.7018 35.652 38.6674 35.4998 38.5908 35.3614C37.6113 33.5415 36.6201 31.7332 35.6476 29.9109C35.5107 29.66 35.2998 29.1841 35.3515 29.1516C35.8093 28.8382 35.4502 28.551 35.3601 28.2769C35.1292 27.5975 34.7901 27.0157 33.9189 27.1142C33.1089 26.1184 32.4608 25.0229 31.8948 23.8927C31.9911 23.83 32.0803 23.7696 32.1766 23.707C32.7948 24.6644 33.4342 25.6149 34.0642 26.5606ZM52.5618 54.9877C50.1113 53.4082 47.5324 52.2678 45.4885 50.3138C48.0638 51.7512 50.4996 53.4757 53.3813 54.4235C53.3822 54.2364 53.3966 54.1616 53.3872 54.1569C50.4777 53.1481 48.1272 51.1855 45.5715 49.5704C45.2471 49.3653 44.9414 49.1462 45.0774 48.5879C45.5801 48.7191 46.0593 48.8502 46.6298 48.9981C46.5322 48.8433 46.5183 48.8011 46.488 48.7799C44.6025 47.498 42.6465 46.3092 41.0671 44.6313C37.9201 41.2871 34.759 37.9475 31.6613 34.5638C29.4044 32.1035 27.2156 29.5898 25.0386 27.0645C23.113 24.8304 21.2368 22.5569 19.3512 20.2786C18.3037 19.0103 17.3055 17.7024 16.2767 16.4202C15.9346 15.9951 15.55 15.6306 14.781 15.9214C15.7397 17.1565 16.6145 18.3258 17.5338 19.4648C18.8 21.0429 20.1155 22.5816 21.3769 24.1691C22.1356 25.1272 22.8051 26.1456 23.5402 27.127C25.2339 29.3903 27.0239 31.5909 28.6214 33.9168C30.5886 36.7756 32.9058 39.3484 35.0751 42.0398C35.2077 42.2065 35.4203 42.3082 35.5975 42.4447C35.3058 41.7462 34.8847 41.1758 34.4589 40.6146C34.0588 40.084 33.6234 39.5649 33.3711 38.9391C33.7516 39.1726 34.0499 39.4641 34.3106 39.7836C36.9199 42.9847 39.4281 46.2812 42.6933 48.8705C44.3469 50.1817 45.9345 51.5767 47.6375 52.825C48.685 53.5951 49.862 54.1905 51.0084 54.8114C51.4123 55.045 51.8887 55.286 52.5618 54.9877ZM40.8646 67.5138C40.7663 67.4993 40.6774 67.4894 40.5792 67.4749C40.5402 67.2853 40.4615 67.0931 40.4601 66.8989C40.4621 64.9132 40.8451 63.0441 42.1864 61.4839C42.3958 61.244 42.6145 61.0323 42.1965 60.8033C40.5833 62.4604 39.6263 64.4319 39.3451 66.5635C38.9257 69.7446 39.2576 72.9131 39.5358 76.0837C39.5492 76.2194 39.6095 76.3554 39.6555 76.5193C41.015 76.1052 42.269 75.7257 43.516 75.3484C43.9402 75.2173 44.2663 75.0482 44.3459 74.5317C44.4787 73.6553 44.7751 72.8031 44.854 71.9288C45.0492 69.6774 45.761 67.5761 46.571 65.4892C46.7747 64.971 46.8101 64.3912 46.9346 63.7743C47.1797 63.406 47.4767 62.9585 47.7784 62.5016C47.671 62.4356 47.5613 62.3625 47.4539 62.2965C46.6248 63.4477 45.9683 64.7214 45.4286 66.0424C44.8959 67.3612 44.3001 68.6773 43.9638 70.0485C43.6322 71.4104 43.5882 72.8415 43.4157 74.237C43.3198 74.2295 43.2145 74.2172 43.1186 74.2097C43.1709 73.5154 43.1741 72.8137 43.2755 72.1266C43.3843 71.367 43.3126 70.6743 43.0937 69.9131C42.7271 68.6786 42.485 67.3723 42.4136 66.0879C42.329 64.621 42.5861 63.1512 43.18 61.7579C41.3288 63.236 41.1153 65.3843 40.8646 67.5138ZM53.7073 94.8737C53.8056 95.3864 53.8997 95.7915 53.9564 96.2011C53.9925 96.5006 54.6577 96.9133 53.7368 97.1215C53.5807 96.4564 53.4291 95.8288 53.25 95.0701C52.2533 95.4744 51.3411 95.851 50.2975 96.2784C51.4345 97.9611 52.483 99.5171 53.5504 101.059C53.6527 101.205 53.9188 101.374 54.0711 101.34C55.1231 101.105 56.3782 101.511 57.1419 100.35C57.2149 100.24 57.5237 100.279 57.7462 100.245C57.7302 98.6316 57.714 97.0411 57.719 95.4437C57.7178 95.1794 57.7709 94.8428 57.9356 94.6566C58.4038 94.114 58.3854 93.5362 58.2295 92.8244C57.8427 92.951 57.5004 93.0709 57.1277 93.193C57.0604 94.0791 56.9911 94.9114 56.9241 95.7507C56.8304 95.7502 56.7368 95.7497 56.6432 95.7493C56.6018 95.0778 56.5581 94.3993 56.517 93.6577C55.9457 93.6969 55.8319 94.0144 55.8507 94.4986C55.8971 96.1337 55.8545 97.7824 56.3036 99.3868C56.3658 99.6 56.3273 99.8384 56.331 100.063C55.3537 98.2734 55.5405 96.305 55.3183 94.2293C54.718 94.4648 54.2373 94.6612 53.7073 94.8737ZM49.075 63.0344C49.0214 62.9897 48.9748 62.9427 48.9212 62.898C48.7096 63.084 48.4093 63.2369 48.2983 63.4678C47.5443 65.0615 46.599 66.5465 46.1182 68.2842C45.3281 71.143 44.8795 74.0456 44.6811 76.9986C44.6687 77.1505 44.5604 77.295 44.4942 77.449C44.4193 77.4346 44.3445 77.4202 44.2626 77.4081C44.265 76.8936 44.2673 76.379 44.2771 75.7686C42.7157 76.3267 41.2246 76.8618 39.6725 77.4246C40.1607 79.1718 40.3378 80.8965 41.2696 82.3817C41.6212 82.29 41.9047 82.2282 42.1812 82.1454C42.4156 82.0765 42.6385 81.9724 43.0675 81.8085C41.6379 81.7006 41.6379 81.7006 41.7538 80.9154C42.9774 81.5578 44.0615 80.9692 45.0013 80.7003C45.1004 79.508 45.18 78.4699 45.2737 77.4273C45.3674 76.3846 45.4915 75.3398 45.5689 74.2947C45.6189 73.5933 45.5309 72.8748 45.6323 72.1877C45.7553 71.4001 45.9719 70.613 46.2398 69.8636C47.0148 67.7415 47.4558 65.4797 48.8991 63.637C49.0262 63.4786 49.0249 63.2377 49.075 63.0344ZM47.8693 86.2065C47.9949 84.3361 48.1225 82.5194 48.2502 80.7028C46.8352 80.9716 46.7882 81.0181 46.7401 82.3183C46.7216 82.7836 46.7265 83.2491 46.6893 83.705C46.6722 83.8663 46.5591 84.0201 46.4859 84.1764C46.4204 84.1667 46.3526 84.15 46.2941 84.138C46.2864 83.2609 46.2857 82.3815 46.2763 81.357C44.5907 81.9402 43.0575 82.4657 41.4352 83.0281C42.2137 84.26 42.9551 85.4261 43.7499 86.6838C44.686 86.2138 45.5821 85.7646 46.5511 85.276C46.4484 86.742 44.93 86.6009 44.0829 87.5789C45.615 87.2874 46.7505 86.7131 47.8693 86.2065ZM49.8131 62.8628C48.2819 65.5283 47.2414 68.3601 46.659 71.3532C46.0718 74.3557 45.3724 77.3482 45.6555 80.4627C46.412 80.3473 46.2999 79.7924 46.3299 79.3622C46.4345 77.9734 46.4339 76.5725 46.6111 75.1911C46.8026 73.7349 47.0527 72.2674 47.4454 70.8544C47.8665 69.362 48.4559 67.9078 49.0523 66.4748C49.334 65.7909 49.7302 65.124 50.2033 64.5487C50.6717 63.9828 50.9178 63.404 50.9797 62.6675C50.5065 62.7447 50.1387 62.8106 49.8131 62.8628ZM47.8357 48.3774C47.8537 48.029 47.9113 47.7065 47.8776 47.3906C47.779 46.4265 47.6453 45.4739 47.5233 44.5097C47.0315 40.4516 46.2421 36.4598 45.0428 32.5478C44.8998 32.0886 44.6208 31.6662 44.4052 31.2231C44.7518 33.2269 45.3401 35.1127 45.7175 37.0442C46.3833 40.4225 46.8007 43.8511 46.9418 47.2923C46.9742 47.8889 47.1154 48.2475 47.8357 48.3774ZM50.0163 49.6094C50.041 48.2857 47.9833 40.1243 47.2954 39.0496C47.3497 39.4521 47.3884 39.6886 47.4201 39.9273C47.7965 42.5908 48.2245 45.2453 48.54 47.9132C48.6862 49.212 48.6345 49.2679 50.0163 49.6094ZM48.8339 41.4571C48.9992 42.1736 49.1574 42.8924 49.3368 43.6044C49.8147 45.5574 50.3091 47.5129 50.794 49.4636C50.9412 50.0538 51.206 50.5042 52.0863 50.4572C51.0915 47.3578 50.4456 44.2532 48.8339 41.4571ZM45.3405 62.7629C45.1464 63.239 45.0779 63.8842 44.7895 64.002C44.4049 64.1591 44.2821 64.4017 44.1638 64.6818C43.7757 65.6107 43.3455 66.53 43.093 67.4924C42.9406 68.0482 43.0032 68.7128 43.6647 69.4225C43.714 66.8219 45.2575 65.0475 46.2102 62.9918C45.8782 62.9059 45.6398 62.8439 45.3405 62.7629ZM93.5835 96.3555C94.6038 95.8812 95.4154 95.5064 96.2739 95.1085C96.0541 94.5343 95.8807 94.0774 95.6841 93.5501C95.0416 93.7995 94.5046 94.0143 93.9044 94.2498C93.8103 94.8644 93.7162 95.4791 93.5835 96.3555ZM36.4603 43.1741C36.3945 43.2346 36.3309 43.3021 36.2722 43.3603C37.5377 45.0788 38.8032 46.7973 40.078 48.5205C40.3005 48.4865 40.5394 48.455 40.9189 48.4008C39.5677 46.469 37.8871 44.9332 36.4603 43.1741ZM43.8488 55.2101C43.9148 56.6441 44.6823 57.7239 45.532 58.7456C45.6368 58.8748 45.9976 58.7878 46.4095 58.8086C45.4676 57.4823 44.6582 56.3462 43.8488 55.2101ZM43.4574 44.0119C43.5783 42.6489 42.6177 40.8151 41.451 40.0139C42.1817 41.4561 42.8196 42.734 43.4574 44.0119ZM50.7166 52.0734C52.864 53.3941 53.5817 53.5872 54.6348 53.1178C53.3303 52.7743 52.1427 52.4549 50.7166 52.0734ZM44.7501 61.8664C43.558 62.5293 42.9395 64.1797 43.1193 65.8179C43.6803 64.4431 44.2152 63.1548 44.7501 61.8664ZM71.2449 62.7564C72.7403 62.3056 72.8345 62.1891 72.9656 60.6438C72.2792 61.2811 71.4233 61.6159 71.2449 62.7564ZM48.0382 71.7345C47.3314 72.76 46.8553 75.5315 47.0577 76.8352C47.3791 75.1342 47.7098 73.4378 48.0382 71.7345ZM83.8908 88.1179C85.0904 87.8573 85.8789 87.4123 85.9948 86.1054C85.1358 86.6203 84.3217 87.0348 83.8908 88.1179ZM50.2595 61.9926C51.4628 61.9332 51.8451 61.2709 51.876 60.1321C51.113 60.6311 50.2972 60.8982 50.2595 61.9926ZM53.0324 59.5977C53.5454 59.0015 54.8 59.0032 54.6584 57.7184C53.5085 57.8459 53.4523 58.8841 53.0324 59.5977ZM53.8168 94.4719C54.29 93.8732 55.2952 94.159 55.2436 93.1483C53.637 93.3554 53.6064 93.3809 53.8168 94.4719ZM56.0222 58.4083C56.1016 58.4368 56.1811 58.4653 56.2605 58.4937C56.7242 57.4155 57.3281 56.3848 57.2684 55.1122C56.8514 56.214 56.4321 57.3088 56.0222 58.4083ZM57.8723 100.843C57.1773 101.311 56.6678 101.657 56.1653 102.001C56.1465 102.015 56.1509 102.076 56.1484 102.116C57.2197 102.271 57.7103 101.962 57.8723 100.843ZM39.2201 17.4535C39.335 17.4003 39.4406 17.3424 39.5556 17.2892C39.0472 16.358 38.5365 15.4199 38.0352 14.4865C37.9484 14.5305 37.8545 14.5768 37.77 14.6278C38.2503 15.5681 38.7305 16.5085 39.2201 17.4535ZM75.3908 128.897C75.4675 129.036 75.537 129.176 75.616 129.322C76.1792 128.997 76.7401 128.666 77.3034 128.341C77.2593 128.254 77.2152 128.168 77.1712 128.081C76.5824 128.351 75.9866 128.624 75.3908 128.897ZM126.932 167.598C126.978 167.692 127.032 167.784 127.076 167.871C127.69 167.584 128.303 167.29 128.917 167.003C128.159 166.971 127.41 166.944 126.932 167.598ZM42.8811 44.1306C42.9064 44.7295 42.6829 45.4955 43.7384 45.5313C43.4201 45.0127 43.1506 44.5717 42.8811 44.1306ZM31.7016 44.2188C31.4815 43.1933 31.2974 43.0357 30.1669 43.0089C30.722 43.4421 31.2048 43.8211 31.7016 44.2188ZM48.2656 62.4199C48.878 62.1025 49.3027 61.8778 49.8141 61.6091C48.7758 61.4121 48.7758 61.4121 48.2656 62.4199ZM43.5012 50.3341C43.9131 51.3746 43.9131 51.3746 44.893 51.5597C44.3335 51.0657 43.9185 50.7034 43.5012 50.3341ZM131.756 177.944C131.017 178.731 131.017 178.731 131.505 179.506C131.585 178.989 131.65 178.594 131.756 177.944ZM95.7275 147.225C95.6857 147.145 95.6439 147.066 95.5999 146.979C95.2571 147.192 94.9121 147.399 94.5694 147.612C94.6042 147.671 94.6414 147.737 94.6762 147.795C95.0259 147.603 95.3755 147.41 95.7275 147.225ZM56.795 92.7493C56.7439 92.6648 56.695 92.5874 56.6439 92.5029C56.2315 92.599 55.6559 92.554 55.9912 93.4562C56.3132 93.1795 56.5529 92.9609 56.795 92.7493ZM59.4208 53.7923C59.3787 53.7827 59.3366 53.7731 59.3039 53.7683C59.2014 54.1677 59.0919 54.5694 58.9871 54.9618C59.062 54.9762 59.1368 54.9907 59.214 55.0121C59.2837 54.6078 59.3511 54.1965 59.4208 53.7923ZM41.6032 41.5443C41.5422 41.5721 41.4882 41.5975 41.4272 41.6253C41.4826 41.794 41.5263 41.9743 41.6075 42.1267C41.6748 42.2604 41.7913 42.3779 41.8797 42.5047C41.936 42.4629 41.9994 42.4187 42.0558 42.3769C41.9096 42.0979 41.7564 41.8211 41.6032 41.5443ZM70.7263 54.8226C70.7821 54.8978 70.8332 54.9822 70.8891 55.0573C71.0863 54.9227 71.2812 54.781 71.4714 54.6487C71.4249 54.5783 71.3784 54.5079 71.3249 54.4398C71.1324 54.5651 70.9329 54.6927 70.7263 54.8226ZM66.6626 118.592C67.183 118.422 67.4314 118.348 67.6636 118.249C67.6965 118.231 67.6761 118.074 67.6823 117.737C67.3346 118.03 67.116 118.218 66.6626 118.592ZM49.599 55.9035C49.5354 55.9944 49.4718 56.0853 49.4082 56.1762C49.7165 56.3321 50.027 56.4951 50.3353 56.651C50.3684 56.5857 50.4085 56.5181 50.4438 56.4598C50.1568 56.2736 49.8768 56.085 49.599 55.9035ZM115.628 140.964C115.584 140.878 115.54 140.791 115.501 140.695C115.322 140.816 115.153 140.941 114.977 141.069C114.97 141.071 115.075 141.247 115.079 141.238C115.272 141.159 115.45 141.062 115.628 140.964ZM125.885 180.63C125.908 180.7 125.933 180.778 125.956 180.848C126.174 180.777 126.392 180.705 126.61 180.634C126.583 180.549 126.557 180.472 126.53 180.388C126.323 180.471 126.1 180.552 125.885 180.63ZM127.07 179.876C127.137 180.056 127.202 180.253 127.216 180.249C127.399 180.212 127.579 180.145 127.741 180.069C127.755 180.064 127.672 179.764 127.64 179.76C127.462 179.763 127.288 179.828 127.07 179.876Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M41.4807 53.1942C41.3101 53.647 41.124 53.3888 40.961 53.2009C39.9926 52.0312 39.0242 50.8615 38.0746 49.6779C36.5664 47.8132 35.037 45.9554 33.5781 44.0512C31.9121 41.8722 30.3143 39.6399 28.6811 37.4424C28.2042 36.7968 27.6898 36.1791 27.2011 35.5451C26.9568 35.2281 26.7195 34.9088 26.4799 34.5825C26.5504 34.5127 26.6303 34.4476 26.7008 34.3778C27.1085 34.8125 27.5678 35.2148 27.9261 35.6891C29.478 37.7341 30.9946 39.8141 32.5347 41.8707C32.9908 42.4765 33.4656 43.0683 33.9333 43.6624C36.0838 46.3677 38.2272 49.0753 40.3824 51.7712C40.5918 52.0296 40.8554 52.2391 41.0954 52.4718C41.223 52.7181 41.3554 52.955 41.4807 53.1942Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M40.2398 34.7703C39.3301 32.593 38.479 30.3809 37.4871 28.2383C36.5347 26.1683 35.4346 24.1701 34.5244 22.0864C37.2398 26.0152 39.0805 30.3629 40.9851 35.0477C40.5461 34.849 40.3803 34.771 40.2145 34.693L40.2398 34.7703Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.556 9.97828C27.6502 9.83848 27.7374 9.70098 27.9352 9.40272C28.1815 9.79682 28.3743 10.0994 28.5694 10.4091C28.5083 10.4836 28.4471 10.5581 28.386 10.6326C28.1712 10.5239 27.9588 10.4223 27.737 10.3159C27.6767 10.2034 27.6164 10.0908 27.556 9.97828Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.9483 8.64655C34.7935 8.79048 34.6317 8.9367 34.4769 9.08063C34.3934 8.9448 34.3052 8.81829 34.2217 8.68246C34.4137 8.58074 34.608 8.48603 34.807 8.38201C34.8533 8.47563 34.8973 8.56225 34.9483 8.64655Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M97.4819 99.7357C97.899 101.195 97.4126 103.651 95.5978 109.913C96.677 109.404 97.5293 108.868 97.6802 107.596C97.8503 106.217 98.1094 104.847 98.3451 103.478C98.3714 103.345 98.5218 103.233 98.6325 103.072C98.9984 103.949 98.9891 103.944 98.4227 106.489C98.1694 107.615 97.9348 108.75 97.686 109.914C98.3698 109.861 98.5522 109.397 98.6625 108.831C98.8184 108.002 99.0001 107.179 99.2075 106.364C99.26 106.144 99.4388 105.954 99.552 105.753C99.6362 105.772 99.7157 105.801 99.7999 105.82C99.6151 106.822 99.4373 107.822 99.2236 108.998C99.6083 108.817 99.8523 108.706 100.157 108.568C100.641 112.341 99.5645 115.869 98.7146 119.495C98.18 119.149 98.4418 118.736 98.5137 118.362C98.8472 116.579 99.2392 114.808 99.4932 113.02C99.6504 111.91 99.5947 110.768 99.6373 109.641C99.5556 109.605 99.4691 109.579 99.3873 109.544C99.2599 109.749 99.0625 109.93 99.0123 110.157C98.5236 112.084 98.0653 114.009 97.593 115.939C97.5596 116.074 97.4865 116.207 97.3104 116.312C97.0879 114.283 98.028 112.449 98.2853 110.434C97.5804 110.494 97.293 110.876 97.171 111.453C97.0705 111.93 96.9256 112.39 96.7827 112.927C96.2064 112.501 96.6839 112.009 96.4944 111.456C93.6701 113.246 90.8668 115.028 87.979 116.861C87.9777 116.122 88.2813 115.765 88.7228 115.45C90.5925 114.074 92.4273 112.664 94.2993 111.296C94.809 110.926 95.1223 110.504 95.2515 109.878C95.8334 107.025 96.4433 104.186 97.0509 101.34C97.1583 100.885 97.2937 100.444 97.4819 99.7357ZM97.1715 109.794C97.1087 109.722 97.0435 109.642 96.9736 109.571C95.7116 110.638 94.4426 111.708 93.1806 112.775C93.2574 112.867 93.3343 112.958 93.4088 113.043C94.5777 111.858 96.4869 111.576 97.1715 109.794Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M68.7836 108.555C68.7578 109.591 68.7391 110.625 68.7133 111.661C67.9959 110.331 68.2532 108.838 67.9156 107.407C66.2832 108.035 64.8389 109.022 63.1281 109.387C63.1175 109.142 63.1135 108.987 63.1002 108.828C62.2806 108.871 61.4914 108.911 60.7115 108.956C60.7025 108.882 60.6865 108.809 60.6774 108.734C61.8846 108.424 63.1148 108.185 64.2966 107.798C65.5253 107.388 66.6984 106.832 67.9134 106.333C67.7697 105.516 67.6556 104.86 67.5278 104.139C68.8274 104.087 68.1595 105.256 68.6844 105.668C68.7645 105.556 68.8311 105.332 68.9295 105.323C71.0075 105.032 72.48 103.514 74.2749 102.669C74.6808 102.482 75.1053 102.327 75.5181 102.161C75.5787 102.227 75.6322 102.295 75.6928 102.361C75.563 102.582 75.482 102.881 75.2918 103.014C74.6012 103.497 73.8688 103.924 73.162 104.381C72.0631 105.091 70.9735 105.806 69.6515 106.667C69.92 107.841 70.3394 109.33 70.5713 110.843C70.8055 112.362 70.8476 113.913 70.8499 115.462C70.1393 113.678 70.4619 111.719 69.9089 109.775C69.6804 110.076 69.5108 110.295 69.3413 110.514L69.3694 110.505C69.2693 109.868 69.1692 109.231 69.0622 108.573C68.999 108.57 68.8749 108.572 68.7578 108.572C69.2941 108.022 69.3529 107.442 68.6908 106.826C68.721 107.392 68.7558 107.973 68.7836 108.555Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M103.674 118.918C103.913 120.311 103.577 121.682 103.367 123.152C104.161 123.032 104.635 122.651 104.819 121.883C104.967 121.266 104.998 120.578 105.645 119.962C105.991 121.133 105.228 121.967 105.329 123.008C105.757 122.65 106.112 122.355 106.57 121.971C106.732 124.884 105.555 127.301 104.9 129.836C104.788 129.826 104.673 129.809 104.568 129.797C104.592 129.516 104.589 129.221 104.656 128.95C105.011 127.565 105.401 126.192 105.749 124.809C105.835 124.454 105.804 124.075 105.837 123.605C104.742 123.807 104.774 124.661 104.572 125.327C104.372 125.976 104.217 126.642 104.043 127.298C103.942 127.277 103.844 127.262 103.744 127.241C103.869 126.413 103.992 125.579 104.118 124.728C102.882 124.712 102.749 125.729 102.281 126.536C102.278 126.218 102.275 125.9 102.265 125.537C101.423 125.774 100.778 126.585 99.5693 126.272C100.356 125.68 100.988 125.161 101.667 124.713C102.432 124.221 102.894 123.611 102.917 122.661C102.937 121.822 103.044 120.985 103.134 120.146C103.181 119.718 103.26 119.295 103.332 118.874C103.449 118.898 103.561 118.908 103.674 118.918ZM103.154 124.164C104.316 123.885 104.316 123.885 104.282 123.187C103.887 123.527 103.516 123.843 103.154 124.164Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M108.45 127.106C108.674 128.901 107.987 130.606 108.239 132.345C109.15 132.226 109.238 131.543 109.355 130.905C109.456 130.381 109.358 129.799 110.088 129.318C109.953 131.823 109.42 134.091 108.818 136.336C108.736 136.324 108.656 136.319 108.575 136.307C108.763 135.124 108.948 133.934 109.168 132.516C107.049 134.105 105.146 135.522 103.264 136.933C102.836 136.481 102.595 136.412 101.986 136.479C101.974 136.397 101.926 136.273 101.956 136.248C102.708 135.643 103.76 135.408 104.105 134.298C104.167 134.107 104.706 133.33 105.284 134.021C105.296 134.033 105.366 134.01 105.396 133.984C106.033 133.503 106.728 133.081 107.274 132.513C107.558 132.217 107.645 131.675 107.687 131.233C107.788 130.188 107.799 129.133 107.858 128.079C107.89 127.726 107.798 127.304 108.45 127.106Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M74.3491 110.266C76.6431 108.853 78.9349 107.433 81.2289 106.019C81.2174 105.984 81.2035 105.942 81.192 105.907C80.3265 106.237 79.461 106.567 78.4148 106.964C78.5358 106.621 78.5557 106.373 78.6471 106.343C81.2711 105.507 83.6491 104.16 85.99 102.747C86.0557 102.71 86.154 102.724 86.325 102.699C86.2098 103.321 85.8825 103.724 85.3706 104.04C83.464 105.21 81.576 106.412 79.6578 107.57C78.1809 108.458 76.6739 109.302 75.1668 110.146C74.9085 110.309 74.6144 110.623 74.3491 110.266Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M121.377 162.647C121.605 161.56 121.841 160.479 122.133 159.067C121.492 159.511 121.005 159.709 120.736 160.078C120.361 160.597 119.969 160.399 119.269 160.402C121.045 158.956 121.066 157.097 121.252 155.292C121.316 154.656 121.403 154.021 121.628 153.402C122.112 155.112 121.358 156.729 121.238 158.427C122.383 158.168 122.329 157.22 122.489 156.475C122.924 156.566 123.308 156.643 123.785 156.744C123.947 157.095 124.076 157.583 123.576 157.957C122.451 158.8 122.405 160.131 122.013 161.31C121.857 161.781 121.747 162.277 121.618 162.763C121.541 162.718 121.459 162.682 121.377 162.647Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M78.0789 63.5166C77.5271 68.5006 75.2405 73.0173 74.186 77.8701C74.0807 77.8579 73.9754 77.8456 73.8702 77.8334C73.8902 77.5388 73.8495 77.2252 73.9281 76.9426C74.4775 75.0344 75.0714 73.1428 75.6045 71.2322C76.2161 69.0389 76.7669 66.8267 77.3528 64.6263C77.4647 64.2082 77.6117 63.802 77.7423 63.3933C77.8521 63.443 77.9667 63.4833 78.0789 63.5166Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M76.6001 61.8372C76.0709 67.0084 73.5534 71.3205 72.4667 76.0516C72.3614 76.0393 72.2609 76.0178 72.1556 76.0055C72.2068 75.545 72.1857 75.0537 72.3304 74.617C72.9455 72.6951 73.6518 70.7901 74.2482 68.8587C74.8565 66.8923 75.3689 64.8951 75.9186 62.9167C75.9876 62.6761 76.0403 62.4332 76.1186 62.1973C76.1399 62.1436 76.2383 62.1114 76.6001 61.8372Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.1194 54.601C64.7481 53.7879 65.0784 52.73 66.2096 52.0948C66.2878 52.4039 66.4574 52.6832 66.3864 52.8699C65.4644 55.3517 64.5026 57.8309 63.555 60.3055C63.2706 61.0525 62.9863 61.7996 62.6833 62.5372C62.5318 62.906 62.3359 63.2582 62.0302 63.5607C62.1125 62.4361 62.618 61.4609 63.0275 60.4548C63.4726 59.3671 63.9154 58.2723 64.3067 57.1632C64.6767 56.1079 64.9859 55.0335 65.4016 53.714C64.8098 54.118 64.4693 54.3619 64.1194 54.601Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M91.3374 88.6338C91.431 92.7603 89.8041 96.3448 88.5583 100.022C88.4484 99.9961 88.3385 99.9698 88.2379 99.9483C88.4118 99.2919 88.5693 98.6331 88.7689 97.9839C89.1538 96.7368 89.5645 95.4968 89.9634 94.2452C90.455 92.7063 90.6566 91.1144 90.706 89.5101C90.7054 89.1288 90.6324 88.7168 91.3374 88.6338Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M87.0453 97.6926C87.0096 97.3229 86.9099 97.0908 86.974 96.9064C87.4247 95.5988 87.9947 94.3223 88.359 92.9885C88.8518 91.1689 89.1997 89.3112 89.592 87.47C89.6663 87.1032 89.6493 86.7195 90.1459 86.6425C90.3906 88.4307 88.6199 94.8026 87.0453 97.6926Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M85.9509 137.554C85.7856 137.359 85.6643 137.274 85.6484 137.178C85.149 133.263 85.1507 129.284 84.0635 125.453C84.052 125.417 84.167 125.341 84.2775 125.227C84.8585 125.62 84.907 126.266 84.9839 126.856C85.2326 128.775 85.4602 130.701 85.6621 132.62C85.8169 134.087 85.932 135.551 86.0563 137.021C86.0697 137.157 86.0082 137.301 85.9509 137.554Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M96.1186 99.3502C96.1475 99.6988 96.2535 100.069 96.1911 100.401C95.6501 103.544 94.777 106.601 93.8011 109.63C93.7169 109.611 93.6234 109.587 93.5392 109.568C93.9659 107.879 94.4347 106.2 94.8171 104.494C95.2041 102.779 95.5093 101.052 95.8542 99.3278C95.9408 99.3306 96.0297 99.3404 96.1186 99.3502Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M89.4255 139.949C89.1599 139.685 89.0105 139.61 89.0039 139.519C88.6447 135.651 87.6086 131.927 86.7669 128.155C86.7601 128.11 86.8704 128.043 87.0467 127.869C88.3675 131.772 88.9603 135.734 89.4255 139.949Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M76.7423 125.361C76.3173 121.554 76.3887 117.693 75.3173 113.98C75.3127 113.966 75.4487 113.906 75.5238 113.874C76.3961 115.036 77.336 122.948 76.7423 125.361Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M92.326 133.861C92.5368 134.336 92.874 134.794 92.9443 135.293C93.2781 137.542 93.551 139.796 93.8099 142.054C93.9045 142.864 93.9101 143.687 93.7494 144.526C93.6619 144.212 93.5183 143.893 93.4987 143.572C93.3356 140.325 92.9407 137.108 91.8713 133.994C92.0283 133.95 92.1783 133.909 92.326 133.861Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M54.9931 78.0703C54.5168 79.8455 54.0078 81.6159 53.5829 83.4054C53.1581 85.1949 52.8197 87.0106 52.432 88.8891C52.0235 88.1199 52.2984 87.3681 52.4375 86.6531C52.7542 84.9613 53.1107 83.272 53.4508 81.5803C53.7047 80.3139 53.9001 79.0354 54.7173 77.966C54.8084 78.0062 54.9043 78.0371 54.9931 78.0703Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M120.322 166.977C121.21 166.43 122.088 165.878 123.027 165.298C123.437 163.061 123.85 160.808 124.256 158.558C124.315 158.546 124.376 158.542 124.441 158.528C124.489 158.91 124.644 159.311 124.574 159.668C124.212 161.531 123.799 163.379 123.388 165.234C123.349 165.426 123.236 165.65 123.092 165.759C122.447 166.235 121.796 166.697 121.115 167.115C120.927 167.231 120.621 167.152 120.368 167.165C120.347 167.102 120.334 167.036 120.322 166.977Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M60.3461 100.345C59.8321 100.132 59.33 99.884 59.3471 99.2245C59.4169 97.2555 59.5031 95.289 59.5963 93.3201C59.6063 93.1845 59.752 93.0589 59.9477 92.7535C60.09 95.4159 60.2146 97.8817 60.3461 100.345Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M102.629 115.735C102.96 118.663 102.188 121.127 101.238 123.571C101.401 122.739 101.592 121.921 101.722 121.084C101.855 120.208 101.882 119.319 102.057 118.452C102.22 117.644 101.793 116.725 102.629 115.735Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.1989 109.601C72.2899 110.552 73.033 115.944 72.4193 119.15C72.3692 118.831 72.3028 118.511 72.2739 118.185C72.1729 116.716 72.1562 115.243 71.9733 113.785C71.8063 112.423 71.4824 111.081 71.1989 109.601Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M73.5851 112.003C74.1341 112.726 74.2331 113.596 74.2994 114.462C74.4228 116.142 74.4947 117.831 74.6181 119.511C74.6664 120.203 74.7874 120.88 74.8732 121.568C74.7772 121.584 74.6905 121.604 74.5945 121.62C74.516 121.381 74.3836 121.144 74.3637 120.894C74.1786 118.884 74.0521 116.863 73.8295 114.857C73.7465 114.083 73.4433 113.326 73.2619 112.56C73.2229 112.394 73.2705 112.207 73.276 112.034C73.3837 112.03 73.482 112.021 73.5851 112.003Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M124.886 167.755C124.391 167.551 124.444 167.168 124.506 166.789C124.648 165.918 124.84 165.053 124.935 164.181C125.008 163.574 125.034 162.942 124.946 162.341C124.871 161.828 124.978 161.466 125.467 160.917C125.629 161.362 125.838 161.644 125.807 161.903C125.709 162.815 125.532 163.721 125.387 164.633C125.221 165.645 125.064 166.661 124.886 167.755Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.8396 104.284C62.0412 101.284 61.6572 98.2419 61.6924 95.1479C62.3577 96.0354 62.1305 97.0984 62.2524 98.0859C62.3834 99.125 62.4301 100.168 62.5307 101.21C62.6196 102.239 62.7296 103.262 62.8396 104.284Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M120.017 149.042C120.308 151.446 119.437 153.677 118.811 155.945C118.589 154.749 119.221 153.662 119.283 152.498C119.342 151.326 119.52 150.162 119.645 149.001C119.765 149.008 119.888 149.03 120.017 149.042Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M119.397 158.656C119.814 156.13 120.182 153.884 120.564 151.634C120.579 151.536 120.708 151.454 120.797 151.347C121.218 152.603 120.519 156.428 119.397 158.656Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M116.922 151.543C117.101 149.102 117.274 146.664 117.468 144.218C117.473 144.139 117.655 144.079 117.756 144.007C118.245 145.162 118.025 147.29 116.922 151.543Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M73.4619 87.4933C72.8474 89.8198 72.2234 92.1416 71.6019 94.4704C71.3545 93.7885 72.4053 89.2328 73.4619 87.4933Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M70.2625 91.0565C70.2544 90.7711 70.2206 90.4786 70.243 90.191C70.3718 88.6386 71.1938 84.9753 71.6484 84.3437C71.6584 86.7926 70.6775 88.8577 70.6112 91.0747C70.5012 91.0718 70.3818 91.0641 70.2625 91.0565Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M70.197 82.912C69.7479 84.8885 69.2918 86.8673 68.845 88.8509C68.7444 88.8293 68.6345 88.803 68.5339 88.7814C68.7796 86.7548 69.051 84.7353 69.8556 82.8214C69.9655 82.8477 70.0778 82.881 70.197 82.912Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M67.1319 86.1742C66.6977 84.3546 67.4186 81.3083 68.5555 79.9317C68.234 81.1346 67.9463 82.1085 67.7218 83.0851C67.4948 84.1014 67.3215 85.139 67.1319 86.1742Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M109.862 162.582C109.578 161.196 109.262 159.805 109.029 158.41C108.849 157.317 108.78 156.203 108.629 154.82C109.405 155.975 110.019 160.499 109.822 162.602C109.829 162.6 109.862 162.582 109.862 162.582Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M107.641 125.208C107.861 127.16 107.289 128.998 106.641 130.821C106.386 129.831 106.943 128.94 106.989 127.991C107.029 127.044 107.124 126.102 107.187 125.155C107.339 125.167 107.493 125.187 107.641 125.208Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M117.764 154.42C118.051 152.115 118.338 149.81 118.639 147.501C118.653 147.403 118.759 147.322 118.957 147.047C119.368 149.769 118.43 152.061 117.764 154.42Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M128.386 175.497C128.331 175.282 128.241 175.124 128.262 174.977C128.466 173.369 128.687 171.763 128.914 170.155C128.928 170.057 129.058 169.976 129.189 169.831C129.683 170.292 129.578 170.872 129.475 171.342C129.169 172.711 128.77 174.056 128.386 175.497Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M116.008 168.936C115.651 167.068 115.295 165.2 114.959 163.325C114.934 163.2 115.087 163.049 115.278 162.66C116.137 164.846 116.09 166.885 116.008 168.936Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M124.738 179.479C124.588 178.975 124.415 178.471 124.286 177.961C124.017 176.905 123.755 175.846 123.5 174.786C123.404 174.373 123.099 173.92 123.733 173.526C124.206 174.352 124.317 175.211 124.491 176.049C124.676 176.992 124.803 177.947 124.914 178.9C124.936 179.087 124.795 179.296 124.726 179.49L124.738 179.479Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M112.441 134.96C112.148 136.582 111.85 138.213 111.557 139.835C110.988 138.932 111.425 138.08 111.52 137.232C111.605 136.425 111.341 135.453 112.16 134.842C112.252 134.882 112.35 134.92 112.441 134.96Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M110.063 137.515C110.333 135.683 110.584 134.004 110.845 132.331C110.862 132.193 111.01 132.075 111.127 131.911C111.462 133.071 110.929 135.884 110.063 137.515Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M114.57 154.851C115.516 154.479 116.349 153.957 116.922 153.092C117.108 152.805 117.315 152.651 117.609 152.976C117.157 153.879 114.653 155.766 113.432 156.057C113.677 155.712 113.849 155.453 114.023 155.201C114.209 155.078 114.389 154.964 114.57 154.851Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M113.616 136.023C113.878 137.65 113.498 139.175 112.694 140.638C112.821 139.864 112.965 139.093 113.06 138.315C113.155 137.536 113.193 136.753 113.249 135.972C113.372 135.994 113.494 136.009 113.616 136.023Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.5063 99.9781C75.9398 98.357 76.3709 96.7289 76.802 95.1008C77.1868 95.9401 76.4872 98.9329 75.5063 99.9781Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M106.959 153.554C107.795 155.553 107.933 157.446 107.863 159.532C107.461 158.496 106.778 154.26 106.959 153.554Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M118.557 172.996C118.431 172.018 118.358 171.038 118.173 170.071C117.997 169.155 117.703 168.263 117.411 167.16C118.493 168.176 118.751 169.414 118.557 172.996Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M63.5363 97.8673C63.8983 99.5859 63.7576 101.197 63.6332 102.81C63.5255 102.814 63.4178 102.818 63.3101 102.822C63.2953 101.971 63.2968 101.122 63.2656 100.268C63.1973 98.3053 63.1902 98.3076 63.5363 97.8673Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M95.8434 128.218C96.053 126.911 95.5164 125.491 96.4067 124.289C96.5316 125.641 96.439 126.972 95.8434 128.218Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M112.803 160.342C113.805 161.283 113.961 162.018 113.945 165.525C113.578 163.863 113.212 162.201 112.803 160.342Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M78.1231 97.4629C78.524 98.873 77.8417 100.14 77.3209 101.423C77.4604 100.093 77.6046 98.7537 77.7441 97.4235C77.8728 97.4359 78.0014 97.4482 78.1231 97.4629Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M97.7538 127.085C98.0545 128.38 97.6908 129.597 97.03 130.787C97.169 129.55 97.3011 128.316 97.4401 127.079C97.5478 127.075 97.6508 127.08 97.7538 127.085Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M129.817 172.739C130.015 172.986 130.253 173.141 130.262 173.31C130.278 173.764 130.218 174.219 130.148 174.67C130.02 175.514 129.866 176.351 129.705 177.306C129.582 177.098 129.459 176.936 129.389 176.748C129.345 176.638 129.379 176.503 129.391 176.374C129.52 175.25 129.661 174.114 129.817 172.739Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M94.5164 127.165C94.4879 124.683 94.5647 124.253 95.1627 123.513C95.2921 124.903 95.1534 126.069 94.5164 127.165Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.9288 105C64.8664 103.791 64.7946 102.577 64.7238 101.153C65.3126 101.832 65.4771 103.755 65.2212 105.014C65.1253 105.006 65.0247 105.008 64.9288 105Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M66.4442 102.715C66.5748 103.847 66.7148 104.984 66.8454 106.117C66.7495 106.132 66.6441 106.144 66.5481 106.159C66.2818 105.04 65.8234 103.953 66.0229 102.759C66.1587 102.746 66.3014 102.73 66.4442 102.715Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M60.3446 100.345C60.466 101.948 60.5968 103.555 60.7182 105.158C60.6666 105.167 60.6174 105.183 60.5659 105.192C60.476 104.895 60.3322 104.599 60.2961 104.3C60.1835 103.34 60.0685 102.374 60.0401 101.41C60.0253 101.057 60.2353 100.7 60.3446 100.345Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M98.622 129.634C99.5669 130.212 99.6031 130.488 99.1158 132.726C98.9338 131.579 98.7904 130.692 98.622 129.634Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M114.57 154.851C114.389 154.964 114.208 155.079 114.035 155.19C113.806 155.133 113.581 155.066 113.326 155.002C113.837 154.351 113.837 154.351 114.57 154.851Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M69.3385 110.507C69.4384 111.19 69.543 111.864 69.6429 112.547C69.5516 112.554 69.4673 112.558 69.3761 112.565C69.0469 111.894 69.0851 111.205 69.3666 110.498L69.3385 110.507Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.1194 54.6022C63.9814 55.1066 63.8412 55.6039 63.6962 56.1105C63.6075 56.0773 63.521 56.0511 63.4253 56.0203C63.659 55.5468 63.8927 55.0734 64.1194 54.6022Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M29.9502 22.3493C27.0407 17.7832 24.1289 13.2101 21.1915 8.60641C21.3977 8.54665 21.4775 8.50496 21.55 8.51234C21.6296 8.51742 21.7347 8.55304 21.7696 8.61168C24.5276 13.025 27.2857 17.4383 30.032 21.8633C30.1017 21.9805 30.0728 22.1535 30.0909 22.3032C30.0417 22.3194 29.9995 22.3332 29.9502 22.3493Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.9848 13.0886C22.7805 13.544 23.3415 14.1618 23.3512 15.1393C22.9004 14.4542 22.4426 13.7714 21.9848 13.0886Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M10.3998 16.8666C10.5912 16.4769 10.7983 16.2301 11.2153 16.6696C12.5687 18.1102 13.9434 19.5205 15.2968 20.9612C16.4383 22.1832 17.5655 23.4333 18.6834 24.6786C18.9513 24.9723 19.1463 25.3288 19.1979 25.8179C18.9997 25.6415 18.7945 25.4673 18.6151 25.277C16.6281 23.1642 14.648 21.0491 12.661 18.9363C12.0856 18.3229 11.4984 17.7212 10.8995 17.1311C10.7597 16.99 10.5494 16.9188 10.3743 16.8127C10.3766 16.8197 10.3998 16.8666 10.3998 16.8666Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M24.1904 31.887C23.4693 30.9714 22.7552 30.0535 22.034 29.1378C22.1091 29.0821 22.1819 29.0193 22.25 28.9659C23.112 29.7654 23.8497 30.66 24.4182 31.7035C24.3454 31.7662 24.2703 31.822 24.1904 31.887Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.4982 17.7354C37.5854 17.5979 37.6749 17.4674 37.8116 17.2436C38.7253 18.5086 39.1775 19.9093 39.6602 21.3077C39.0411 21.1291 38.8983 20.6233 38.6782 20.1428C38.3053 19.3155 37.8761 18.5066 37.4703 17.6978C37.4774 17.6955 37.4982 17.7354 37.4982 17.7354Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.6943 15.13C30.72 13.2306 29.7504 11.3219 28.7901 9.44134C29.3764 9.68522 29.3904 9.68061 30.6205 11.9555C31.1427 12.9287 31.5921 13.9414 32.0744 14.9355C31.9477 15.0003 31.821 15.0652 31.6943 15.13Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M33.6444 17.5344C34.0667 18.3223 34.4982 19.1148 34.9205 19.9027C34.8408 19.9443 34.7563 19.9953 34.6766 20.037C33.9049 19.4415 33.6844 18.5331 33.2528 17.7405C33.3864 17.6734 33.5201 17.6063 33.6444 17.5344Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M38.472 43.01C36.8606 42.1832 29.3085 33.6336 28.823 32.298C32.037 35.8694 35.258 39.4385 38.472 43.01Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M39.37 44.1772C40.6108 45.1799 41.8539 46.1896 43.1297 47.2276C42.3822 47.3946 42.3471 47.3827 40.9929 46.1058C40.3938 45.539 39.7924 44.9652 39.1981 44.3892C39.2546 44.324 39.3088 44.2517 39.37 44.1772Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M17.1197 35.7917C16.1417 35.6604 15.1348 35.1805 14.5369 34.3564C15.4247 34.7586 16.3032 35.156 17.191 35.5582C17.1695 35.6353 17.1481 35.7123 17.1197 35.7917Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.0314 38.4007C21.459 38.5877 21.8819 38.784 22.4193 39.0206C21.6279 39.5523 21.274 39.1154 20.8918 38.7345C20.9391 38.6178 20.9888 38.5081 21.0314 38.4007Z\"\n        fill=\"#676461\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 135 / 186,\n  svg: Carrot,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as cookingArrow } from './arrow';\nimport { default as cookingArtichoke } from './artichoke';\nimport { default as cookingCarrot } from './carrot';\nimport { default as cookingPersimmon } from './persimmon';\nimport { default as cookingRadish } from './radish';\nimport { default as cookingRadishLarge } from './radishLarge';\n\nexport {\n  cookingArrow,\n  cookingArtichoke,\n  cookingCarrot,\n  cookingPersimmon,\n  cookingRadish,\n  cookingRadishLarge,\n};\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/persimmon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Persimmon', 'sticker name', 'web-stories');\n\nfunction Persimmon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 41 43\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M40.9302 19.7642C40.998 21.3444 40.6766 22.8889 40.4337 24.4298C40.3265 25.1055 39.9728 25.7598 39.6549 26.3818C38.8512 27.9585 37.8689 29.4279 36.8544 30.8723C36.64 31.1798 36.465 31.5123 36.2757 31.8376C35.7006 32.8315 35.1326 33.829 34.5468 34.8193C33.7859 36.0992 32.675 37.0288 31.4926 37.9047C29.9244 39.0702 28.1776 39.9247 26.4701 40.8328C25.7879 41.1939 24.9734 41.3226 24.209 41.5157C22.923 41.841 21.6192 42.0948 20.2868 42.0412C18.9472 41.9876 17.5898 41.9804 16.2717 41.7588C13.6533 41.3119 11.3314 40.175 9.37745 38.3516C8.50584 37.5365 7.60924 36.7428 6.81979 35.8561C6.11965 35.0696 5.54454 34.1686 4.93013 33.307C4.53362 32.7493 4.1264 32.1951 3.80491 31.5981C2.86901 29.8462 1.9724 28.0729 1.0615 26.3103C0.6257 25.463 0.218476 24.605 0.0934511 23.6468C-0.0387182 22.635 -0.035146 21.6233 0.132745 20.6151C0.361362 19.2672 0.586407 17.9158 0.793591 16.5644C0.915044 15.7599 1.28297 15.052 1.66877 14.362C2.44035 12.9749 3.22265 11.6056 3.76919 10.0932C4.07639 9.23877 4.66222 8.48083 5.14803 7.69429C5.89461 6.49302 7.04127 5.7029 8.14863 4.89133C10.7456 2.9929 13.6569 1.78448 16.7396 0.912135C18.1828 0.504562 19.6581 0.318652 21.1262 0.0934141C22.7444 -0.153275 24.3447 0.114865 25.895 0.590367C27.4561 1.08017 29.0064 1.595 30.521 2.19563C31.1782 2.45662 31.7569 2.9357 32.3285 3.37187C32.7964 3.72939 33.1929 4.17987 33.6323 4.57314C34.3039 5.17735 35.029 5.72793 35.6541 6.37861C36.415 7.17231 37.1401 8.0089 37.8046 8.88483C38.9191 10.3542 39.3656 12.1347 39.9478 13.8436C40.3836 15.12 40.6837 16.4321 40.8194 17.7799C40.8837 18.4378 40.8945 19.1027 40.9302 19.7642ZM26.6916 29.7676C26.7916 29.9749 26.8952 30.1823 26.9953 30.3897C27.0345 30.3682 27.0703 30.3432 27.106 30.3217C26.9631 30.1394 26.8202 29.9606 26.6738 29.7783C26.9202 29.4172 26.7059 29.0704 26.6559 28.6557C26.5166 28.7522 26.4237 28.8201 26.3416 28.8773C26.4701 29.2063 26.5809 29.4887 26.6916 29.7676ZM25.5057 27.365C25.6021 27.576 25.6986 27.7869 25.8379 28.0908C25.9522 27.9156 26.0558 27.8298 26.0594 27.7369C26.0808 27.3078 25.645 27.5581 25.495 27.3758C24.8198 26.2067 23.9768 25.1842 22.9552 24.2939C22.5194 23.915 22.1657 23.4001 21.8871 22.8889C21.6299 22.4134 21.3477 22.0702 20.7904 22.0201C20.5761 22.8496 20.9012 23.7505 21.587 24.2439C21.98 24.5263 22.3979 24.7802 22.773 25.0841C23.691 25.8348 24.5948 26.6035 25.5057 27.365ZM27.331 24.7158L27.3453 24.7265C26.9488 24.6264 26.5523 24.5084 26.1522 24.4262C25.8414 24.3619 25.4807 24.4155 25.3914 23.9722C25.3842 23.9328 25.227 23.9257 25.002 23.8649C25.4128 24.5263 25.7379 25.0698 26.0844 25.5989C26.4344 26.1316 26.8309 26.6321 27.1631 27.1755C27.3989 27.5617 27.6239 27.9764 27.7418 28.409C27.8561 28.8237 27.8597 29.2813 27.8669 29.7211C27.874 30.4683 27.899 31.2191 27.8097 31.9592C27.7561 32.4025 27.5239 32.8279 27.3453 33.2498C27.2203 33.5466 27.0238 33.8147 26.9059 34.1114C26.8095 34.3581 26.7131 34.5548 26.4166 34.5619C26.3773 34.1615 26.4309 33.7861 26.563 33.3964C26.9417 32.2702 27.0238 31.1512 26.3344 30.0893C26.2415 29.9427 26.1915 29.7676 26.1201 29.6067C25.6021 28.4733 24.9484 27.458 23.9625 26.6428C22.8016 25.6847 21.4549 24.9482 20.4332 23.6575C20.4332 24.1366 20.4332 24.5156 20.4332 24.891C20.4082 24.891 20.3832 24.891 20.3618 24.8946C20.3368 24.798 20.3082 24.7051 20.2582 24.5156C20.1867 24.7694 20.0617 24.9625 20.0974 25.1198C20.2296 25.7061 19.9117 26.1566 19.6616 26.5999C18.9579 27.8513 18.2078 29.074 17.4576 30.2967C17.0754 30.9188 16.6503 31.5087 16.0109 31.9091C15.543 32.2023 15.1036 32.5383 14.6392 32.8315C14.1605 33.1354 13.7569 33.4893 13.6712 34.0936C13.4961 34.1257 13.3532 34.1543 13.1996 34.1829C13.2604 34.2795 13.3104 34.3581 13.3282 34.3867C13.0639 34.6298 12.846 34.8336 12.6352 35.0267C12.721 35.184 12.7817 35.2912 12.8496 35.42C12.6674 35.4843 12.5138 35.5093 12.3888 35.5844C12.0887 35.7703 12.5674 35.9491 12.4388 36.042C12.0351 36.3424 12.4888 36.539 12.5281 36.7714C12.2066 36.825 11.928 36.8751 11.5922 36.9323C11.9101 37.1253 12.1423 37.2648 12.3745 37.4042C12.3602 37.4507 12.3459 37.4971 12.3316 37.5472C12.0816 37.5079 11.8315 37.4721 11.4814 37.4185C11.7529 37.6366 11.9422 37.7903 12.1351 37.9405C12.1209 37.9798 12.1066 38.0227 12.0923 38.062C11.8887 38.0799 11.6815 38.0978 11.3707 38.1264C11.6422 38.3373 11.8172 38.4767 12.0887 38.6841C11.8315 38.7306 11.6958 38.752 11.5422 38.7806C11.7208 38.9522 11.8637 39.0917 12.0387 39.2561C11.8708 39.3348 11.7815 39.3777 11.6208 39.4528C11.8851 39.6137 12.103 39.7495 12.378 39.9176C12.821 39.5672 13.2747 39.2561 13.6712 38.8843C14.0677 38.5161 14.4035 38.0871 14.7678 37.6831C14.7142 38.2944 14.307 38.6412 13.9355 39.0059C13.5676 39.367 13.1818 39.7102 12.7888 40.0749C13.5033 40.4932 13.7426 40.4646 14.2499 39.9783C14.95 39.3133 15.4715 38.5304 15.8287 37.633C16.0181 37.1611 16.2395 36.6999 16.4467 36.2351C16.4896 36.253 16.5324 36.2709 16.5753 36.2887C16.4039 36.8036 16.2574 37.3291 16.0502 37.8296C15.8323 38.3588 15.5894 38.8843 15.2858 39.3705C15.0036 39.8174 14.6285 40.2071 14.2606 40.6648C14.9178 40.8614 15.5037 41.0473 16.0931 41.2118C16.2288 41.2511 16.4039 41.2726 16.5289 41.2189C17.6041 40.7577 18.4078 40.0284 18.8401 38.9093C18.9972 38.5018 19.2294 38.1192 19.4366 37.7295C19.4866 37.6366 19.5759 37.5651 19.6474 37.4793C19.3937 38.3874 19.0758 39.2526 18.6579 40.0677C18.4543 40.4646 18.0756 40.772 17.7648 41.1081C17.6755 41.2046 17.5505 41.2654 17.4219 41.3584C18.0542 41.5872 18.4543 41.319 18.7972 40.9007C18.8936 40.7827 19.0079 40.6719 19.0937 40.5432C19.6938 39.6458 20.2903 38.7556 20.7261 37.751C21.1727 36.7213 21.4906 35.6881 21.487 34.5583C21.487 34.4296 21.5406 34.3045 21.5727 34.1758C21.6228 34.1794 21.6763 34.1865 21.7263 34.1901C21.7442 34.3939 21.8049 34.6048 21.7764 34.8014C21.6656 35.6094 21.5763 36.4174 21.2441 37.1825C20.719 38.4017 20.1867 39.6101 19.3366 40.6505C19.1615 40.865 19.0222 41.1045 18.8222 41.3941C19.3044 41.4477 19.6938 41.5157 20.0867 41.5228C20.2332 41.5264 20.3904 41.4048 20.5261 41.319C20.6333 41.2475 20.7047 41.1224 20.8119 41.0545C21.3406 40.722 21.6513 40.225 21.8978 39.6709C21.9907 39.4599 22.1014 39.2561 22.2014 39.0488C22.1157 39.9104 21.6013 40.5754 21.1155 41.4013C21.4656 41.4013 21.7049 41.4334 21.9335 41.3941C22.7551 41.2511 23.5696 41.0402 24.3983 40.9472C24.977 40.8793 25.1806 40.511 25.3414 40.0713C25.4307 39.8246 25.4342 39.5493 25.4914 39.2919C25.5307 39.1274 25.595 38.9665 25.6486 38.8057L25.6378 38.7985C25.595 39.3884 25.5521 39.9783 25.5057 40.579C26.1522 40.6362 26.4523 39.9855 26.9667 39.914C26.9667 39.6816 26.931 39.4885 26.9738 39.3098C27.3239 37.7653 27.0095 36.3388 26.2665 34.9731C26.1558 34.7728 26.0701 34.5583 25.9736 34.3474C26.0093 34.3224 26.0451 34.3009 26.0844 34.2759C26.1987 34.3617 26.313 34.4439 26.4273 34.5297C26.8131 35.3234 27.1989 36.1278 27.2882 37.0181C27.3739 37.894 27.3882 38.7806 27.4346 39.6637C28.4205 39.4456 28.7777 38.7842 28.8063 37.8797C28.817 37.4828 28.8099 37.0896 28.8099 36.6927C28.8528 36.6927 28.8921 36.6927 28.9349 36.6927C28.9349 37.4221 28.9349 38.1478 28.9349 38.8843C29.4029 38.7842 29.5529 38.4839 29.5636 38.1014C29.5708 37.8153 29.5743 37.5222 29.5243 37.2433C29.4207 36.6677 29.2778 36.0957 29.1528 35.5236C29.6708 36.3817 29.6922 37.3613 29.8315 38.3909C30.5495 37.8976 31.1961 37.4542 31.7605 37.0681C31.9963 36.4282 31.314 36.2565 31.264 35.7739C31.5604 35.731 31.7355 35.8812 31.8677 36.0385C32.0177 36.2101 32.1106 36.4282 32.232 36.6319C32.8714 36.1707 32.9071 36.0957 32.6464 35.4736C32.4428 34.9874 32.1927 34.519 31.9605 34.0435C31.9891 34.0185 32.0177 33.9899 32.0463 33.9648C32.3963 34.5834 32.75 35.2054 33.1393 35.8919C33.443 35.4843 33.7037 35.1339 33.9574 34.7943C33.5001 33.5036 32.7357 32.449 31.8534 31.4944C30.9675 30.5362 29.9208 29.7568 28.6813 29.2599C29.0992 29.0847 29.4315 29.2563 29.7422 29.4494C31.4319 30.5112 32.8571 31.8305 33.7537 33.6574C33.8573 33.8683 34.0217 34.0471 34.1788 34.2723C34.6896 33.7003 33.9288 33.332 34.0467 32.8208C34.2467 33.0925 34.4217 33.3285 34.6325 33.6145C35.1755 32.6849 35.9649 31.9091 35.4577 30.7472C35.4505 30.7293 35.4934 30.69 35.5398 30.6256C35.6613 30.8437 35.772 31.0403 35.9149 31.2906C36.1507 30.9259 36.3471 30.6149 36.515 30.3575C36.1721 29.6317 35.8613 28.981 35.5541 28.3268C35.5755 28.3053 35.597 28.2874 35.6184 28.266C35.9935 28.8201 36.365 29.3743 36.7401 29.932C37.0723 29.7175 37.0651 29.4672 36.9294 29.1705C36.7543 28.7951 36.5972 28.409 36.4293 28.0264C36.465 28.0121 36.4972 27.9943 36.5329 27.98C36.7615 28.3661 36.9937 28.7558 37.2723 29.2277C37.6581 28.6164 37.9832 28.0765 38.3332 27.5474C38.5047 27.2864 38.4833 27.0576 38.3154 26.818C38.0546 26.4391 37.7938 26.0601 37.5331 25.6811C37.5652 25.6525 37.5938 25.6275 37.6259 25.5989C37.9796 25.9993 38.3332 26.3997 38.7155 26.8323C38.8119 26.6965 38.8619 26.6035 38.9333 26.5213C39.312 26.0815 39.3834 25.6561 38.9476 25.1985C38.8369 25.0805 38.8012 24.891 38.7297 24.7337C38.9869 24.9339 39.2406 25.1341 39.5049 25.3415C40.0657 24.798 39.3227 24.5907 39.1548 24.1652C39.4263 24.2939 39.6085 24.3833 39.7942 24.4727C40.2229 23.3608 40.1229 23.3215 39.3691 22.7065C39.0977 22.4849 38.769 22.3419 38.4583 22.1667C38.126 21.9808 37.7903 21.8056 37.4545 21.6233C37.4759 21.5804 37.5009 21.5375 37.5224 21.4946C38.3689 21.92 39.212 22.3454 40.1264 22.8067C40.1693 22.4491 40.205 22.1738 40.2443 21.8378C39.3549 21.5661 38.5011 21.3051 37.6009 21.0334C38.5618 20.9189 39.3834 21.4016 40.3229 21.5089C40.3443 21.1227 40.3622 20.7831 40.3801 20.4041C39.7764 20.4041 39.2298 20.4077 38.6869 20.4041C38.1368 20.397 37.5867 20.4041 37.0401 20.3648C36.4686 20.3219 35.897 20.254 35.3326 20.1574C34.7897 20.0645 34.2574 19.9215 33.718 19.8106C32.7535 19.6104 32.407 19.496 32.2499 19.2779C33.6144 19.5353 34.9433 19.8035 36.2793 20.0359C37.6367 20.2718 38.9941 20.136 40.3658 20.0001C40.3658 19.6033 40.3658 19.2672 40.3658 18.9311C39.6906 19.0134 39.0834 19.1421 38.4761 19.1421C37.8617 19.1385 37.2259 19.4138 36.49 19.0455C37.408 18.9776 38.1975 18.9419 38.9798 18.8489C39.3656 18.8024 39.7478 18.6701 40.1157 18.5307C40.3479 18.4449 40.4515 18.2447 40.2765 18.0016C39.0155 18.427 36.7794 18.781 35.922 18.6523C36.2685 18.5736 36.4971 18.5093 36.7293 18.4699C37.5545 18.3234 38.3832 18.2054 39.2013 18.0373C39.6049 17.9551 40.0121 17.8264 40.3086 17.4903C40.255 17.3151 40.205 17.1507 40.1443 16.9648C39.2084 17.1507 38.3439 17.5475 37.3973 17.3974C38.3011 17.1507 39.2548 17.0649 40.0943 16.5536C40.0764 16.1353 40.0693 15.7528 39.855 15.406C38.8262 15.9029 38.8262 15.9029 38.5761 15.6956C38.9048 15.5097 39.2334 15.3345 39.5513 15.145C39.805 14.9948 39.7692 14.8161 39.5942 14.623C38.5368 15.3559 36.1721 16.2855 35.4469 16.2211C35.6398 16.1353 35.7756 16.071 35.9149 16.0138C36.6543 15.7278 37.4045 15.4596 38.1368 15.1522C38.4797 15.0091 38.8155 14.8232 39.112 14.6051C39.4656 14.3477 39.6156 13.9974 39.3477 13.5755C37.3187 14.8447 36.9615 14.9948 35.5327 15.1593C35.7684 15.0485 36.0113 14.9555 36.2614 14.8804C37.1366 14.6194 37.9439 14.2226 38.6762 13.672C39.2798 13.218 39.3084 13.0678 38.8833 12.3349C38.1832 12.9427 37.4902 13.554 36.6472 14.0331C36.6472 13.9366 36.6365 13.9044 36.6472 13.8973C37.1044 13.5183 37.5616 13.1393 38.0225 12.7603C38.8155 12.1132 38.8583 11.8379 38.2689 10.8583C38.1046 11.0872 37.9582 11.3017 37.801 11.509C37.183 12.3242 36.5079 13.0821 35.6648 13.6649C34.8683 14.2154 34.0359 14.7231 33.2215 15.2487C33.0715 15.3452 32.9322 15.4668 32.7678 15.5168C32.6714 15.549 32.5392 15.4668 32.2999 15.4024C33.1608 14.8661 33.8681 14.3763 34.6182 13.9616C35.7006 13.3646 36.6115 12.5852 37.3545 11.5984C38.2189 10.4508 38.3547 10.4293 37.3187 9.11364C37.308 9.09934 37.2794 9.09934 37.258 9.09219C36.7293 10.4114 36.2578 11.1408 35.7184 11.4268C36.2578 10.6546 36.7579 9.90733 36.9758 9.00281C37.0651 8.63099 36.958 8.49156 36.6722 8.3557C36.2757 9.04929 35.947 9.725 35.5255 10.3399C34.6575 11.5984 34.436 11.795 34.0288 11.9345C34.4432 11.391 34.8968 10.8726 35.2576 10.297C35.6398 9.6821 35.9542 9.02069 36.2542 8.36285C36.3364 8.18766 36.3471 7.90165 36.2578 7.74434C36.1006 7.47262 35.8399 7.26169 35.5934 6.99355C35.1147 8.69177 34.6539 9.56412 34.0359 9.96811C35.2719 7.97315 35.4219 7.22951 34.9683 6.45012C34.8611 6.6682 34.7611 6.85769 34.6718 7.05433C34.2967 7.85517 33.9609 8.67389 33.5394 9.44971C32.4785 11.391 30.9103 12.932 29.4172 14.5265C29.2528 14.7017 29.11 14.6302 29.0242 14.3835C31.6033 12.1132 33.5716 9.42111 34.6825 6.11405C34.5896 6.04612 34.4932 5.97104 34.3682 5.87809C34.0967 6.45369 33.8538 6.97925 33.6073 7.50123C33.6644 6.9578 33.8288 6.46084 34.0181 5.97462C34.161 5.61352 34.0502 5.43476 33.6037 5.34181C33.3429 7.015 32.4963 8.3843 31.4104 9.62132C31.5569 9.25665 31.7462 8.91343 31.9748 8.59881C32.65 7.66926 33.0858 6.65033 33.2572 5.50984C33.3501 4.89848 33.3287 4.83055 32.6857 4.52309C32.4571 5.08439 32.2284 5.6457 32.0034 6.207C31.9605 6.1927 31.9177 6.17483 31.8712 6.16053C31.9427 5.92456 32.0141 5.69218 32.1106 5.37756C30.946 5.74223 29.8744 6.18198 28.8099 6.68251C28.8778 6.50017 28.9778 6.35716 29.1135 6.29281C29.5922 6.07115 30.0852 5.87451 30.5745 5.6743C30.8996 5.53844 31.3068 5.48481 31.5319 5.25243C31.7676 5.01289 31.9891 4.90921 32.2999 4.93781C32.332 4.8091 32.3499 4.7233 32.3713 4.64107C32.5535 3.98323 32.0998 3.47555 31.3926 3.87955C30.8353 4.19774 30.1673 4.29785 29.6708 4.86273C29.535 4.39438 29.8101 4.2764 30.0244 4.16557C30.3388 4.00468 30.6781 3.901 30.9961 3.74727C31.1532 3.67219 31.2818 3.54348 31.4247 3.44338C31.3961 3.39332 31.3711 3.34685 31.3426 3.29679C30.6531 3.17524 30.1637 3.70437 29.4886 4.04758C29.7387 3.32182 30.3852 3.31824 30.8067 3.01078C30.2816 2.68901 30.2852 2.69616 29.8744 3.00005C29.7958 3.06083 29.6636 3.0501 29.4493 3.09658C29.6172 2.83917 29.7208 2.68186 29.8494 2.48522C29.2957 2.28144 28.7956 2.09553 28.2526 1.89531C28.1562 2.51025 28.074 3.04295 27.9955 3.57566C27.9633 3.57208 27.9276 3.56851 27.8954 3.56493C27.9312 2.98217 27.9704 2.39942 28.0097 1.79878C27.6097 1.68795 27.281 1.595 26.9381 1.49847C26.8988 2.546 26.8667 3.5256 26.8309 4.50521C26.7131 4.22277 26.7202 3.94033 26.7131 3.66146C26.6952 3.02508 26.6702 2.38869 26.6416 1.75588C26.6273 1.41981 26.4844 1.2053 26.0772 1.28038C26.0629 1.42696 26.0415 1.57712 26.0272 1.73086C25.9379 2.69973 25.9165 3.67934 25.745 4.63034C25.4878 6.06042 25.1306 7.4762 24.8091 8.89555C24.7448 9.17442 24.6591 9.44971 24.5769 9.725C24.5126 9.93236 24.3947 9.95024 24.2304 9.78935C24.4983 8.88483 24.7912 7.98388 25.0306 7.0722C25.5021 5.27388 25.8343 3.45053 25.7271 1.57355C25.7093 1.23748 25.6307 1.01939 25.2771 0.962187C25.1485 0.940736 25.0234 0.912135 24.8377 0.872807C24.8377 1.55925 24.8377 2.21351 24.8377 2.86777C24.8127 2.86777 24.7877 2.87134 24.7627 2.87134C24.6734 2.20278 24.5841 1.53422 24.4948 0.847781C24.3411 0.829905 24.2197 0.812029 24.0447 0.790578C24.0447 1.18027 24.0447 1.53064 24.0447 1.87744L24.0554 1.87029C23.9232 1.49132 23.791 1.11235 23.6482 0.701198C23.4374 0.711923 23.2481 0.722649 23.0659 0.729799C23.0159 1.00151 22.973 1.22318 22.9337 1.44484C22.898 1.44841 22.8587 1.44841 22.823 1.45199C22.7623 1.21603 22.7015 0.976488 22.6337 0.708348C22.4122 0.708348 22.205 0.708348 21.9585 0.708348C22.005 1.67723 22.2836 2.5889 22.1193 3.5256C22.0193 2.546 21.955 1.56282 21.5585 0.636844C21.3941 0.65472 21.2691 0.669021 21.1262 0.686897C21.0869 1.28038 21.4834 1.78806 21.3191 2.36009C21.1691 1.94537 21.0762 1.51992 20.944 1.10162C20.8083 0.676171 20.6726 0.64757 20.2653 0.883533C20.5404 2.42802 20.8119 3.95463 21.0834 5.48481C21.0298 5.50626 20.9762 5.52414 20.9226 5.54559C20.8619 5.43834 20.7583 5.33466 20.744 5.22025C20.6726 4.71972 20.6368 4.21204 20.5654 3.70794C20.4261 2.73191 20.2903 1.75231 19.801 0.819179C19.5366 0.879958 19.2901 0.937161 19.0508 0.994364C19.1615 1.69153 19.5116 2.26356 19.4545 2.92855C19.208 2.27786 18.9615 1.62717 18.7043 0.940736C18.4293 1.04442 18.2364 1.11592 18.0292 1.19458C18.4185 2.10625 18.8472 2.94285 18.9579 3.88312C18.7579 3.48985 18.6222 3.07155 18.4471 2.67113C18.2614 2.24926 18.0542 1.83454 17.8327 1.43054C17.6791 1.15167 17.4862 1.2482 17.304 1.41624C18.9258 5.11299 19.2437 6.09975 19.0258 6.96852C18.6614 5.00931 17.9613 3.18239 16.9004 1.43769C16.7039 1.49132 16.511 1.54137 16.2252 1.61645C16.7825 2.41729 17.2719 3.13948 17.5041 3.99038C17.1147 3.44695 16.7646 2.86777 16.3931 2.29931C15.9573 1.63075 15.8895 1.6236 15.1215 2.04547C15.8323 2.83917 16.4467 3.69006 16.9182 4.64107C16.8897 4.66609 16.8575 4.69469 16.8289 4.71972C16.7325 4.59816 16.6325 4.48376 16.5432 4.35863C16.1074 3.74727 15.6823 3.13233 15.2429 2.52455C14.9536 2.1277 14.8714 2.11698 14.2891 2.32791C15.718 3.56851 16.6825 5.10227 17.4755 6.76473C18.34 8.57378 19.1151 11.2731 18.9044 12.1669C18.8258 11.8058 18.7686 11.577 18.7257 11.3446C18.2292 8.52731 17.1076 5.98892 15.3179 3.75442C14.8928 3.22529 14.3999 2.74621 13.7748 2.44232C13.4747 2.57818 13.1996 2.70331 12.8603 2.85347C13.8569 3.89743 14.7678 4.91278 15.4429 6.11405C15.4251 6.13193 15.4037 6.14622 15.3858 6.1641C14.9071 5.56704 14.432 4.96641 13.9498 4.37293C13.664 4.02256 13.3604 3.69364 12.8317 3.34685C12.9353 4.13339 13.0139 4.75547 13.0996 5.37756C13.1603 5.80658 13.2318 6.23561 13.2997 6.66463C13.0818 5.98534 12.8639 5.30248 12.6495 4.63034C12.6067 4.65537 12.5174 4.70542 12.4281 4.7519C12.5674 5.76368 12.9532 6.72541 12.8817 7.75506C12.8031 7.71216 12.7638 7.66211 12.7531 7.60848C12.5602 6.61458 12.3923 5.60995 12.1637 4.62319C12.0816 4.27282 11.8422 3.9582 11.6743 3.62929C11.7672 4.80553 12.2745 5.89596 12.2459 7.06863C12.1887 7.07935 12.1316 7.09008 12.078 7.10438C11.9851 6.54307 11.8922 5.98534 11.7994 5.42404C11.5957 5.87093 11.903 6.32141 11.6851 6.76473C11.5672 6.57167 11.4993 6.37146 11.46 6.16768C11.3528 5.62782 11.2707 5.08439 11.1528 4.54811C11.1207 4.40868 11.0028 4.28712 10.9206 4.15841C10.8635 4.17987 10.8099 4.20489 10.7527 4.22634C10.8313 4.58386 10.9063 4.94138 10.9921 5.29533C11.1742 6.064 11.1778 6.064 10.9385 6.33571C10.6241 4.54096 10.6241 4.54096 10.2205 4.35148C10.2562 4.90563 10.7706 5.35611 10.567 6.12835C10.2598 5.52414 10.2955 4.89491 9.77038 4.49806C9.79539 5.00216 10.1669 5.37041 10.074 5.89954C9.65965 5.57062 9.78824 4.99144 9.38102 4.68039C9.22027 5.14875 9.80253 5.42404 9.57034 5.98892C9.36316 5.60637 9.2167 5.32751 9.0631 5.05221C9.05595 5.03791 8.9988 5.04864 8.93093 5.04864C8.95951 5.14159 8.98094 5.22025 9.00237 5.2989C9.02381 5.37756 9.04167 5.45621 9.0631 5.53844C8.91307 5.57419 8.77733 5.57062 8.68445 5.63497C8.59158 5.69575 8.54157 5.82088 8.47012 5.92456C8.28794 5.81731 8.14506 5.73508 7.9986 5.64927C7.71283 5.87451 7.45564 6.0783 7.10914 6.35359C8.65945 6.71826 9.974 7.36894 11.1992 8.19481C12.4388 9.02784 13.5854 9.96454 14.2891 11.3338C14.107 11.2623 13.9748 11.1336 13.8605 10.9978C13.689 10.794 13.5426 10.5723 13.364 10.3793C12.1852 9.08146 10.7349 8.16979 9.15955 7.44045C8.52013 7.14728 7.89858 6.81836 7.18058 6.73256C6.88052 6.69681 6.67334 6.76473 6.46972 7.04003C7.20201 7.29744 7.9093 7.5334 8.60586 7.79082C9.84183 8.25202 10.1848 8.45938 10.4384 8.8455C9.88469 8.58809 9.32029 8.28419 8.72732 8.06253C8.00932 7.79439 7.26631 7.57988 6.52688 7.36894C6.26611 7.29386 5.94105 7.22236 5.89104 7.66569C7.54494 8.0089 10.5098 9.51764 10.867 10.2506C10.7027 10.1826 10.5813 10.154 10.4848 10.0861C9.4346 9.34245 8.29866 8.76327 7.09842 8.30207C5.4981 7.68714 5.5374 7.80869 4.77296 9.2066C4.74438 9.26022 4.7551 9.33173 4.74081 9.42111C6.2554 9.51406 7.6271 10.0289 8.9345 10.7368C8.7166 10.7261 8.51299 10.6653 8.30938 10.5938C7.83071 10.4257 7.35562 10.2506 6.87338 10.0897C6.20181 9.86443 5.51953 9.68925 4.80153 9.70712C4.49076 9.71427 4.28357 9.7965 4.30143 10.1612C6.21253 10.6259 8.09505 11.1587 9.83111 12.1097C9.44175 12.1704 9.44175 12.174 9.09525 11.9988C7.74855 11.3124 6.28397 10.9727 4.8444 10.5509C4.51576 10.4543 4.1907 10.558 4.02281 10.8333C3.82991 11.1551 3.73704 11.5376 3.58343 11.938C5.40523 11.8737 7.10199 11.9631 8.7166 12.6316C8.13434 12.5566 7.56637 12.4135 6.99126 12.3099C5.88032 12.1132 4.76224 12.031 3.64416 12.2705C3.4977 12.3027 3.32981 12.4278 3.2548 12.5601C2.87258 13.2287 2.51894 13.9116 2.16172 14.5944C2.151 14.6159 2.1903 14.6659 2.21173 14.7053C3.64059 14.4049 5.08731 14.3692 6.54474 14.43C5.98391 14.5229 5.41951 14.5551 4.85512 14.623C4.06925 14.7124 3.2798 14.8089 2.50107 14.9412C2.01526 15.0234 1.62947 15.2666 1.6259 15.8779C1.96525 16.0459 2.3189 16.2247 2.67254 16.3999C3.08691 16.6573 3.4977 16.9183 3.91207 17.1757C3.88349 17.2293 3.85492 17.2794 3.82991 17.333C3.24408 17.2079 2.78327 16.7681 2.17958 16.6394C2.4725 16.9111 2.76899 17.1793 3.0619 17.451C3.04047 17.4903 3.01546 17.5332 2.99403 17.5726C2.64396 17.451 2.29746 17.3294 1.94739 17.2079C1.9331 17.2365 1.91524 17.2651 1.90095 17.2937C2.02955 17.4474 2.15458 17.6047 2.35819 17.8514C2.01526 17.8514 1.7795 17.8514 1.52231 17.8514C1.60804 18.2661 1.86166 18.3448 2.17244 18.3234C3.18335 18.259 4.20141 18.2948 5.18733 17.9944C5.26591 17.9694 5.36236 18.0052 5.60169 18.023C5.00157 18.4199 4.4729 18.52 3.92993 18.5486C3.05118 18.5915 2.17244 18.6022 1.29726 18.6451C1.18653 18.6487 1.07936 18.7595 0.972198 18.8203C0.986486 18.8739 1.00078 18.9276 1.01864 18.9776C1.2794 18.9812 1.53302 18.9705 1.79022 18.9562C1.98669 18.9454 2.18673 18.9061 2.37962 18.9168C2.90115 18.9454 3.42269 19.0062 3.94422 19.0312C4.32287 19.0491 4.70151 19.0348 5.08016 19.0348C3.70846 19.4567 2.29032 19.2386 0.872178 19.3387C0.872178 19.5532 0.872178 19.7177 0.872178 19.9143C3.28337 19.9894 5.51953 19.3459 7.74855 18.6129C7.46635 18.9168 7.10557 19.0634 6.73406 19.1707C6.28754 19.2958 5.83031 19.3709 5.38737 19.5067C4.17998 19.875 2.94402 20.0752 1.68305 20.111C1.42229 20.1181 1.15438 20.1682 0.904327 20.2432C0.818596 20.2683 0.772158 20.4327 0.657849 20.6079C2.72255 20.7044 4.64793 20.6258 6.66262 20.1968C6.52688 20.3147 6.49116 20.3648 6.44472 20.3827C6.30183 20.4363 6.15538 20.5006 6.00535 20.5221C4.84797 20.6651 3.68703 20.8045 2.52608 20.9261C2.02241 20.9797 1.51516 20.9869 1.00792 21.0083C0.750725 21.0191 0.572118 21.0798 0.697143 21.4624C1.86523 21.4445 3.0619 21.5303 4.23356 21.3873C5.89461 21.1871 7.53422 20.8224 9.18098 20.5221C9.5882 20.447 9.99186 20.3433 10.4705 20.2361C10.2741 20.6437 9.96328 20.6973 9.66679 20.7652C9.30243 20.8474 8.9345 20.9297 8.56657 20.9976C6.20539 21.4409 3.85134 21.9593 1.42229 21.8378C1.16509 21.8235 0.907899 21.8378 0.629272 21.8378C0.614984 22.0273 0.597123 22.1345 0.600695 22.2418C0.607839 22.3419 0.636417 22.442 0.661422 22.5707C2.48679 22.6887 4.25857 22.442 6.03749 22.2954C5.16589 22.5421 4.29072 22.7351 3.38339 22.778C2.46178 22.821 1.54374 22.8996 0.597123 22.964C0.597123 23.0998 0.597123 23.2285 0.597123 23.418C1.60804 23.418 2.60467 23.4824 3.58343 23.4001C4.57292 23.3143 5.54811 23.0784 6.52688 22.9103C6.59475 23.3322 6.27326 23.3465 6.06964 23.3966C4.65508 23.7434 3.23336 24.0472 1.77236 24.0615C1.45801 24.0651 1.14366 23.9936 0.747153 23.9471C0.843601 24.3011 0.943621 24.6836 1.04721 25.0733C2.93688 24.891 4.73009 24.7194 6.48401 24.2618C6.24825 24.4048 6.00177 24.5049 5.7553 24.5871C4.51219 25.0018 3.20836 25.0912 1.92596 25.3021C1.69734 25.3415 1.4723 25.3915 1.20439 25.4416C1.28297 25.6382 1.32584 25.7598 1.38299 25.8777C1.42943 25.9743 1.49016 26.0672 1.56517 26.1924C3.00475 26.1816 4.40503 25.892 5.79459 25.5417C7.20201 25.1877 8.64873 24.941 10.0133 24.4655C11.3493 24.0008 12.6031 23.3072 13.8962 22.7101C13.7676 22.8996 13.6069 23.0569 13.4175 23.1677C11.56 24.2653 9.54891 24.9732 7.44849 25.4344C6.59118 25.6239 5.73029 25.8027 4.8694 25.9814C4.44075 26.0708 4.00495 26.1423 3.57272 26.221C2.97974 26.3282 2.38319 26.4391 1.72235 26.5606C1.86523 26.8574 1.98311 27.1076 2.10457 27.3615C3.87992 27.2757 5.62313 27.2828 7.2806 26.6428C5.76244 27.576 4.02638 27.5152 2.34747 27.7118C2.54751 28.3303 2.6261 28.384 3.17264 28.3125C3.32267 28.291 3.4727 28.2553 3.6263 28.241C5.34807 28.0479 7.01983 27.6403 8.59515 26.9253C9.67751 26.4355 10.717 25.8456 11.7744 25.3021C11.9387 25.2199 12.1137 25.0412 12.2387 25.3522C9.39888 27.2506 6.28397 28.3661 2.82257 28.6593C2.96903 28.9917 3.07976 29.2456 3.20836 29.5352C4.66579 29.4672 6.05178 29.192 7.43063 28.813C6.20896 29.5709 4.77296 29.5745 3.39411 29.9284C3.54414 30.218 3.66202 30.4468 3.81562 30.74C4.29786 30.6542 4.77296 30.5863 5.24091 30.4826C5.73386 30.3718 6.22325 30.2323 6.71263 30.1001C7.14843 29.9856 7.4985 29.5852 8.13077 29.6567C7.94145 29.814 7.84857 29.8998 7.74855 29.9678C7.18415 30.3503 6.53045 30.454 5.88389 30.597C5.27663 30.7329 4.64793 30.7972 4.04067 31.0725C4.20856 31.3764 4.34787 31.6231 4.4979 31.902C6.17324 31.498 7.92001 31.4014 9.34173 30.2073C9.37745 30.5648 9.13454 30.6935 8.91664 30.8222C8.17006 31.262 7.38062 31.6016 6.52688 31.7697C6.07322 31.8591 5.61955 31.9556 5.17304 32.07C5.04087 32.1022 4.92656 32.1987 4.64436 32.3489C4.94442 32.4561 5.09088 32.5491 5.23376 32.5491C7.04127 32.5526 8.73446 32.1594 10.2026 31.0368C10.9385 30.4755 11.66 29.8963 12.3923 29.3314C12.4745 29.267 12.5924 29.2492 12.6924 29.2098C12.7174 29.2456 12.746 29.2813 12.771 29.3135C12.646 29.4529 12.5174 29.5924 12.3959 29.7354C11.8922 30.3324 11.21 30.6971 10.6027 31.1619C9.37745 32.1022 7.98788 32.5812 6.46258 32.7314C6.07679 32.7672 5.70171 32.8708 5.26948 32.9531C5.37308 33.1533 5.41594 33.2784 5.49453 33.3821C5.88747 33.9148 6.27683 34.4511 6.69834 34.9623C6.80908 35.0946 7.02698 35.1339 7.19844 35.2162C7.40205 35.5379 7.71997 35.6845 8.03432 35.8347C8.0629 35.7882 8.09148 35.7381 8.12005 35.6917C7.80928 35.5379 7.4985 35.3806 7.1913 35.2269C7.08413 35.1053 6.97697 34.9838 6.83765 34.8229C6.95553 34.8014 7.01626 34.7728 7.06984 34.7836C7.53422 34.8658 7.99503 34.9552 8.45941 35.041C8.8702 34.6584 9.27743 34.9373 9.68822 35.0374C9.72037 35.0446 9.75967 35.0267 9.7811 35.0231C9.72752 34.9158 9.67394 34.8122 9.5632 34.5941C9.96328 34.6334 10.2562 34.6584 10.5741 34.687C10.5062 34.544 10.4491 34.4225 10.3455 34.208C10.7027 34.2294 10.9706 34.2437 11.2528 34.258C11.185 34.1222 11.1349 34.022 11.0242 33.8004C11.8494 34.1186 12.1351 33.1712 12.8317 33.3428C12.8353 32.8315 13.1175 32.5097 13.414 32.1629C13.9605 32.3918 14.2427 32.0807 14.4999 31.6338C14.9286 30.8902 15.1465 30.0929 15.2643 29.2563C15.3286 28.7987 15.4215 28.3446 15.5108 27.8942C15.793 26.4426 16.1359 25.0018 16.336 23.5396C16.4682 22.5814 16.8289 21.8664 17.6791 21.4052C17.8863 21.2908 18.0685 21.137 18.3149 20.9618C18.1399 20.851 18.0399 20.7652 17.9256 20.7187C16.9254 20.329 16.0538 19.7391 15.2036 19.0992C14.7821 18.781 14.3249 18.5093 13.8748 18.234C13.2175 17.83 12.5781 17.3831 11.8851 17.0577C11.0742 16.6788 10.3169 16.1139 9.32386 16.2319C8.88449 16.2819 8.42369 16.1353 7.98074 16.1604C7.62353 16.1818 7.27703 16.2533 6.93053 16.1175C6.64833 15.8708 6.35899 15.6348 5.93033 15.6849C6.26611 15.8243 6.60189 15.9673 6.94125 16.1067C7.00912 16.2211 7.07342 16.3355 7.20201 16.5572C6.93767 16.4893 6.78407 16.475 6.65905 16.407C6.27683 16.1997 5.89818 15.978 5.53025 15.7421C5.36593 15.6384 5.22662 15.5669 5.06587 15.7242C5.01229 15.5776 4.95871 15.431 4.91941 15.3238C5.16947 15.2594 5.34093 15.2129 5.51239 15.1736C5.61241 15.1522 5.74458 15.0949 5.81602 15.1343C6.2554 15.3738 6.72692 15.0771 7.17344 15.2308C7.36633 15.2952 7.59138 15.2809 7.80571 15.2809C8.4344 15.288 9.0631 15.2666 9.6918 15.2916C10.2169 15.313 10.742 15.3845 11.2671 15.4382C11.9851 15.5097 12.7067 15.5561 13.4175 15.6634C14.5892 15.8386 15.7573 16.0281 16.9182 16.2533C17.6148 16.3892 18.2757 16.6323 18.7222 17.2579C18.7936 17.358 18.9365 17.4117 19.083 17.5082C18.9829 17.0899 18.9651 16.7145 18.8008 16.4213C18.4435 15.785 18.4042 15.0914 18.3221 14.4014L18.3114 14.4085C18.3685 14.4657 18.4578 14.5158 18.4793 14.5837C18.8222 15.6241 19.6366 16.4607 19.7795 17.5869C19.7867 17.6476 19.8403 17.7048 19.9081 17.8371C19.9903 17.3974 20.101 17.0542 20.1082 16.7145C20.1224 15.8994 20.1296 15.0771 20.0582 14.2619C19.9724 13.3216 20.3189 12.4851 20.5725 11.6234C20.6333 11.4196 20.769 11.2159 20.9226 11.0657C21.6263 10.39 22.0193 9.52479 22.4336 8.67032C22.5301 8.47368 22.6408 8.26632 22.6694 8.05538C22.8694 6.66105 23.1623 5.27745 23.0016 3.85095C22.9659 3.53276 22.9945 3.20384 22.9945 2.87849C23.0409 2.87134 23.0909 2.86777 23.1373 2.86062C23.1766 3.08228 23.2516 3.30037 23.2481 3.52203C23.2409 4.16199 23.1981 4.80195 23.1766 5.44191C23.1695 5.6886 23.1766 5.93529 23.1766 6.23203C23.3517 6.03539 23.4838 5.88881 23.616 5.74223C23.666 5.76368 23.7125 5.78513 23.7625 5.80658C23.7446 5.96389 23.7625 6.13908 23.6982 6.27136C23.5374 6.59313 23.3981 6.90774 23.4946 7.28314C23.5124 7.35464 23.4624 7.45117 23.4338 7.5334C22.973 8.76685 22.6944 10.0468 22.823 11.3517C22.9587 12.7282 23.2516 14.0939 23.466 15.4632C23.5589 16.0638 23.6267 16.6645 23.7089 17.2687C23.7517 17.283 23.7946 17.2973 23.8375 17.3116C23.9839 17.0649 24.134 16.8182 24.2804 16.5715C24.3912 16.4178 24.7484 16.2998 24.7412 16.214C24.7162 15.9029 24.8591 15.7456 25.0913 15.6849C25.4378 15.5955 25.2842 15.17 25.5021 15.0878C25.8807 14.9484 25.77 14.4872 26.0736 14.3334C26.513 14.1082 26.9595 13.8973 27.4025 13.6792C27.4239 13.7185 27.4453 13.7614 27.4703 13.8007C27.3239 13.9151 27.0345 14.0581 27.0524 14.1332C27.1596 14.5908 26.7381 14.5801 26.5523 14.7696C26.3273 14.9126 26.1022 15.052 25.8736 15.1951C25.9022 15.2344 25.9308 15.2737 25.9593 15.313C26.1129 15.0771 26.538 15.1951 26.5344 14.7553C26.6202 14.8161 26.7023 14.8769 26.8631 14.9913C26.2773 15.3309 25.7593 15.6348 25.2378 15.9387C25.252 15.9709 25.2663 16.0066 25.2806 16.0388C25.5235 15.9494 25.7664 15.8636 26.0093 15.7742C26.0236 15.81 26.0343 15.8457 26.0486 15.8815C25.7486 16.0567 25.4485 16.2319 25.1485 16.407C25.2128 16.4678 25.2699 16.5179 25.2949 16.5429C25.0949 16.8182 24.7627 17.072 24.7591 17.333C24.7519 17.6834 24.5698 17.7978 24.3662 17.948C24.184 18.0802 23.9768 18.1732 23.8482 18.5379C24.134 18.3877 24.309 18.3055 24.4769 18.2089C24.977 17.9229 25.4807 17.619 26.0808 17.6941C26.6845 17.7692 27.231 17.9444 27.6561 18.4699C27.9026 18.7774 28.3205 18.974 28.6956 19.1528C29.8351 19.6998 30.9925 20.2146 32.1427 20.7402C32.2177 20.7759 32.3035 20.801 32.3856 20.8153C33.1322 20.9583 33.8895 21.0262 34.5896 21.3766C36.2292 22.2024 37.5688 23.3858 38.744 24.7766C38.644 24.7408 38.519 24.7301 38.444 24.6658C37.6938 24.0151 36.9508 23.3608 36.2114 22.703C35.279 21.8735 34.1503 21.4767 32.8714 21.1013C33.0893 21.3873 33.2072 21.6018 33.3787 21.7484C33.9073 22.2024 34.0609 22.846 34.1145 23.4573C34.1717 24.1009 34.4324 24.4763 34.979 24.7265C35.1397 24.8016 35.2969 24.8874 35.4327 24.9982C35.697 25.202 35.9685 25.4058 36.1149 25.7848C35.4327 25.345 34.8111 24.9446 34.1181 24.5013C34.0145 24.8195 33.9109 25.0412 33.8788 25.2735C33.8395 25.5989 33.8466 25.9278 33.8502 26.2567C33.8538 26.4891 33.7966 26.6428 33.4644 26.5999C33.3715 25.8527 33.2322 25.1019 33.1965 24.344C33.1679 23.7612 32.9643 23.275 32.6535 22.8138C31.9855 21.8127 30.8782 21.8163 29.8708 21.5947C30.7853 22.349 31.9927 22.6672 32.8464 23.6075C32.5035 23.7577 32.4035 23.536 32.257 23.4287C31.957 23.2071 31.6748 22.9497 31.3533 22.7673C30.6496 22.3705 29.978 21.8842 29.1457 21.7663C28.7206 21.3408 28.2419 21.4981 27.8026 21.6948C26.8631 22.1166 25.9057 22.3919 24.8627 22.2668C24.8412 22.2632 24.8127 22.3097 24.7627 22.3562C25.3628 22.5993 26.0486 22.3919 26.6166 22.6744C26.6095 22.7351 26.6023 22.7995 26.5916 22.8603C25.6807 22.8102 24.7698 22.7602 23.8589 22.7101C24.3626 22.8674 24.877 22.9354 25.3949 22.9961C25.8915 23.0533 26.4273 22.9211 26.9917 23.3108C26.0915 23.5646 25.3163 23.0891 24.4126 23.2214C24.8234 23.6754 25.2842 23.4931 25.6486 23.6182C26.0379 23.7505 26.4701 23.7612 26.8845 23.8149C27.281 23.8685 27.6775 23.9114 28.2026 23.9722C27.6847 24.3654 27.2846 24.058 26.9024 24.0508C26.5094 24.0437 26.1237 23.8721 25.5878 23.9185C25.7557 24.0115 25.7986 24.0508 25.8522 24.0651C26.6988 24.3261 27.5632 24.487 28.4527 24.4798C28.6313 24.4798 28.8599 24.4083 28.9206 24.7265C28.3777 24.7158 27.8526 24.7158 27.331 24.7158ZM17.7148 23.6254C17.6398 23.7255 17.5791 23.8113 17.5148 23.8935C17.4505 23.9757 17.3112 24.1188 17.3219 24.1295C17.6505 24.487 17.229 24.6121 17.1183 24.8302C17.0754 24.916 17.004 25.059 17.0361 25.0948C17.2504 25.32 17.054 25.4809 16.9468 25.6132C16.4431 26.2281 16.1788 26.9467 16.0216 27.7118C15.8609 28.4805 15.6894 29.2456 15.7216 30.0643C16.1824 29.8998 16.2324 29.5066 16.3503 29.1598C16.4467 28.8666 16.5074 28.577 16.9254 28.5377C17.0897 28.5234 17.2326 28.3017 17.3862 28.1766C17.3612 28.1373 17.3362 28.0979 17.3112 28.0586C17.1219 28.0693 16.9325 28.0836 16.7146 28.0979C16.8897 27.7118 17.0754 27.3865 17.1826 27.0397C17.5398 25.8634 17.6863 24.63 18.1613 23.4752C18.44 22.7959 18.7079 22.1309 19.2151 21.5875C19.4044 21.3837 19.5795 21.1656 19.7688 20.9404C19.5473 20.6651 19.3544 20.4184 19.1615 20.1753C19.1294 20.2003 19.0937 20.2254 19.0615 20.2504C19.1723 20.4828 19.2794 20.7116 19.3937 20.9547C19.0365 21.5053 18.3542 21.5875 17.872 21.9844C18.0828 22.0201 18.2649 22.0523 18.5507 22.0988C18.2399 22.3312 18.0327 22.4885 17.8184 22.6458C17.9149 22.7351 17.9863 22.8031 18.072 22.8853C17.847 23.0962 17.6541 23.275 17.4612 23.4573C17.5505 23.511 17.6184 23.5574 17.7148 23.6254ZM16.4289 18.7631C16.1931 18.091 15.5108 17.8049 15.15 17.1221C16.3788 17.4117 17.3469 17.8693 18.1935 18.6094C18.5328 18.9061 18.9686 19.0956 19.3616 19.3316C19.3902 19.3494 19.4437 19.3244 19.533 19.3173C19.6331 19.1957 19.7545 19.0527 19.8903 18.8918C19.4437 18.4985 19.0222 18.1446 18.6222 17.7692C18.0435 17.2293 17.3719 16.8718 16.6003 16.7288C15.9573 16.6073 15.3072 16.5322 14.6571 16.4642C13.9748 16.3892 13.2854 16.3463 12.5745 16.2891C12.9567 16.8289 12.9567 16.8289 13.5176 16.6359C13.7926 16.5429 14.0748 16.7181 14.2713 16.9827C14.4856 17.2722 14.7678 17.5118 15.0214 17.7728C15.5394 17.5726 15.6144 18.0588 15.8573 18.2983C16.0145 18.4485 16.0216 18.7703 16.4289 18.7631ZM33.6644 24.344C33.768 23.0927 32.9929 21.6876 32.007 21.2264C31.932 21.1907 31.8284 21.1478 31.7605 21.1692C31.3783 21.3015 31.0782 21.0655 30.7531 20.9654C30.4388 20.8689 30.1387 20.7116 29.8208 20.6329C28.3562 20.2575 26.8988 20.3684 25.4378 20.6866C24.9877 20.7831 24.5269 20.8331 24.0732 20.9118C23.8375 20.9547 23.591 20.9833 23.3695 21.0691C23.2731 21.1084 23.2266 21.2729 23.1623 21.3766C23.9875 21.2157 24.6626 21.5339 25.3985 21.827C25.3128 21.6662 25.2663 21.5768 25.1985 21.4481C25.52 21.5303 25.8129 21.609 26.2058 21.7091C26.0629 21.5196 26.0022 21.4374 25.9415 21.3587C25.9808 21.3194 25.9951 21.2979 26.0093 21.2943C26.0522 21.2872 26.1058 21.2729 26.1379 21.2908C26.6809 21.5947 27.181 21.4087 27.7168 21.23C28.1883 21.0763 28.7027 21.0048 29.2028 20.9976C30.1673 20.9761 31.0675 21.2908 31.9641 21.6125C32.4035 21.7698 32.725 22.0058 32.9572 22.4205C33.2715 22.9997 33.5716 23.5753 33.6644 24.344ZM19.9153 21.3873C19.5545 21.8735 19.158 22.2739 18.9186 22.7566C18.2292 24.1474 17.9363 25.6704 17.5969 27.172C17.5827 27.2435 17.5934 27.3186 17.5934 27.4687C17.7648 27.3329 17.9649 27.2256 17.9542 27.1791C17.7898 26.6035 18.3471 26.482 18.5721 26.153C18.5936 26.1209 18.5971 26.078 18.6079 26.0315C18.5114 26.0243 18.415 26.0172 18.3078 26.0065C18.2899 25.5882 18.6614 25.4773 18.8722 25.2485C18.5721 24.9232 18.5686 24.8266 18.8615 24.512C19.0722 24.2868 19.4295 24.0937 19.4723 23.8435C19.5652 23.3215 19.8903 22.9783 20.1582 22.5778C20.3618 22.2739 20.2903 21.752 19.9153 21.3873ZM22.3336 15.9172C22.4015 15.6241 22.4515 15.4417 22.4872 15.2558C22.5051 15.1557 22.5229 14.9734 22.4908 14.9591C22.1479 14.8268 22.3479 14.6016 22.3836 14.4121C22.4301 14.1654 22.4944 13.9187 22.5479 13.672C22.5122 13.6649 22.4765 13.6613 22.4408 13.6541C22.3408 13.8651 22.2443 14.0724 22.1264 14.3191C22.055 14.1475 22.005 14.0295 21.9585 13.9116C21.7942 14.3334 21.9157 14.7088 22.0228 15.0735C22.2157 15.7313 22.3872 16.3927 22.3407 17.0863C22.3193 17.4153 22.2872 17.7406 22.2586 18.0945C22.5479 18.2733 22.8301 18.4485 23.1945 18.6701C23.1302 17.9408 23.0802 17.333 23.023 16.6931C22.9409 16.6752 22.823 16.6502 22.6658 16.6144C22.7123 16.2819 22.7587 15.9601 22.8051 15.6241C22.6658 15.7135 22.5479 15.785 22.3336 15.9172ZM20.619 18.3341C20.9262 18.2876 21.1762 18.2197 21.4299 18.2161C21.7656 18.2089 21.8764 18.0445 21.9264 17.7334C22.0764 16.7717 21.8764 15.8708 21.4906 14.977C21.4049 15.1843 21.2798 15.4489 21.362 15.6062C21.5299 15.928 21.4727 16.1782 21.3298 16.475C21.0905 16.9684 20.8762 17.476 20.6618 17.9837C20.6226 18.0659 20.6368 18.1768 20.619 18.3341ZM21.3263 19.7785C20.7833 20.3183 21.0655 20.9654 22.0478 21.4624C22.5837 20.7295 22.5336 20.4363 21.7942 20.0073C21.6442 19.9179 21.4799 19.8535 21.3263 19.7785ZM15.2 31.6982C15.3036 31.5695 15.4715 31.4551 15.5001 31.312C15.5894 30.8651 15.9073 30.6042 16.2074 30.3181C16.3217 30.2109 16.4039 30.0679 16.5003 29.9427C15.9073 30.3932 15.2036 30.74 15.2 31.6982ZM12.2137 3.19311C12.2709 3.44338 12.328 3.69364 12.3816 3.9296C12.6995 3.78659 12.846 3.59711 12.7281 3.30037C12.6531 3.10373 12.5174 3.03223 12.2137 3.19311ZM17.0147 19.0598C16.9361 18.3806 16.7611 18.1303 16.3788 18.0695C16.6039 18.4199 16.8075 18.7416 17.0147 19.0598ZM11.6208 35.5022C11.6243 35.4593 11.6279 35.4164 11.635 35.3735C11.2921 35.327 10.9492 35.2805 10.6063 35.2376C10.5991 35.2948 10.5955 35.3484 10.5884 35.4057C10.9313 35.4378 11.2778 35.47 11.6208 35.5022ZM18.0578 20.3362C18.1042 20.2933 18.1506 20.2504 18.1935 20.2111C18.0292 20.0001 17.8649 19.7928 17.7005 19.5818C17.6755 19.5997 17.6541 19.6176 17.6291 19.6355C17.772 19.8678 17.9149 20.1038 18.0578 20.3362ZM1.51516 16.2533C1.47944 16.2926 1.44372 16.3355 1.40443 16.3749C1.52945 16.6359 1.77236 16.7324 2.08313 16.7431C1.89381 16.5787 1.70449 16.4178 1.51516 16.2533ZM27.3132 31.8555C27.3632 31.8519 27.4132 31.8519 27.4632 31.8483C27.4418 31.6338 27.4203 31.4229 27.3989 31.2084C27.3703 31.2119 27.3417 31.2155 27.3167 31.2191C27.3132 31.43 27.3132 31.6445 27.3132 31.8555ZM16.8932 19.2565C16.8539 19.2851 16.8182 19.3137 16.7789 19.3423C16.9147 19.5353 17.0468 19.7284 17.1826 19.9215C17.2219 19.8929 17.2647 19.8607 17.304 19.8321C17.1683 19.639 17.029 19.446 16.8932 19.2565ZM11.3564 4.47303C11.3778 4.46946 11.4029 4.46231 11.4243 4.45873C11.4029 4.33717 11.385 4.21204 11.3564 4.09406C11.3278 3.99038 11.285 3.89385 11.2457 3.79374C11.2278 3.8009 11.21 3.80805 11.1885 3.8152C11.2457 4.03686 11.2993 4.25495 11.3564 4.47303ZM1.35442 17.0863C1.32227 17.1364 1.29012 17.1864 1.25797 17.2365C1.36871 17.2901 1.47944 17.3402 1.59375 17.3938C1.61161 17.358 1.63304 17.3223 1.65091 17.2865C1.55089 17.2186 1.45086 17.1507 1.35442 17.0863ZM22.1514 12.0668C22.0693 12.1168 22.0443 12.124 22.0335 12.1383C21.9657 12.2455 21.9014 12.3563 21.8407 12.4708C21.8371 12.4743 21.8657 12.4994 21.8799 12.5137C21.9585 12.4135 22.0371 12.317 22.1157 12.2133C22.1264 12.199 22.1264 12.174 22.1514 12.0668ZM9.08096 36.9609C9.0631 37.0002 9.04524 37.0395 9.02381 37.0788C9.14883 37.1182 9.27386 37.1611 9.39888 37.2004C9.4096 37.1754 9.42031 37.1504 9.42746 37.1253C9.30958 37.0717 9.19527 37.0181 9.08096 36.9609ZM11.2564 16.1747C11.2635 16.1318 11.2707 16.0853 11.2778 16.0424C11.1707 16.0281 11.0671 16.0102 10.9599 15.9959C10.9563 16.0138 10.9528 16.0352 10.9492 16.0531C11.0528 16.096 11.1564 16.1353 11.2564 16.1747ZM25.0413 25.9314C25.0806 25.9135 25.1163 25.8992 25.1556 25.8813C25.1199 25.7776 25.0806 25.6775 25.0449 25.5739C25.0163 25.581 24.9877 25.5917 24.9627 25.5989C24.9877 25.7097 25.0127 25.8205 25.0413 25.9314Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.2363 16.5467C37.0327 16.9578 36.6612 17.0508 36.3111 17.1366C34.6822 17.537 33.0497 17.9053 31.3637 17.9768C30.7243 18.0054 30.0884 18.059 29.449 18.1019C29.274 18.1126 29.0882 18.1305 29.0418 17.823C31.8352 17.7444 34.5893 17.5013 37.2363 16.5467Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M11.5203 14.4981C10.9238 14.2979 10.3344 14.0798 9.73067 13.9082C9.35559 13.8009 8.95908 13.7616 8.56972 13.7079C7.83029 13.6078 7.08728 13.5185 6.34785 13.4219C6.31927 13.4184 6.30141 13.3576 6.23711 13.2575C6.88367 13.0251 7.49093 13.3218 8.08748 13.3468C8.69474 13.3755 9.29844 13.5328 9.89499 13.6758C10.4915 13.8188 11.0881 13.9797 11.5703 14.3694C11.556 14.4158 11.5382 14.4587 11.5203 14.4981Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M16.3678 11.4269C16.2713 10.9585 16.1785 10.4938 16.082 10.0254C15.9891 9.57494 15.9891 9.06368 15.7605 8.69186C15.5748 8.38439 15.5319 8.1234 15.5426 7.80878C15.5426 7.76946 15.5783 7.73013 15.5998 7.68723C15.907 7.79091 15.8177 8.09122 15.8891 8.30216C15.9784 8.5703 16.0177 8.85989 16.082 9.13876C16.0999 9.22099 16.1392 9.36042 16.1785 9.364C16.6178 9.41048 16.5571 9.76085 16.6071 10.0397C16.7929 11.0801 16.9786 12.1205 17.1572 13.1609C17.168 13.2217 17.143 13.286 17.1358 13.3611C16.9 13.0858 16.8965 13.0858 16.7607 12.1991C16.6964 11.7844 16.6643 11.3697 16.6036 10.955C16.5428 10.5367 16.55 10.0969 16.2642 9.67147C16.2964 10.3043 16.3285 10.8692 16.3571 11.434L16.3678 11.4269Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.2735 9.73595C28.7736 9.53932 29.2772 9.34626 29.7773 9.14963C29.7452 9.46067 29.7452 9.45352 29.1093 9.73953C28.7914 9.88253 28.4842 10.0434 28.2127 10.308C28.6343 10.1578 29.0522 10.0112 29.4737 9.86108C29.0058 10.569 28.0663 10.4295 27.5626 11.0731C27.7698 10.5833 27.6984 9.97191 28.2842 9.72523L28.2735 9.73595Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M13.4563 4.49133C13.9278 6.1538 14.3279 7.827 14.5136 9.54668C14.4636 9.5574 14.4136 9.5717 14.3672 9.58243C14.3243 9.38222 14.2743 9.182 14.235 8.98179C14.0564 8.03079 13.8921 7.07621 13.7027 6.12878C13.6349 5.79271 13.5992 5.45664 13.3277 5.17062C13.2062 5.04191 13.2634 4.7416 13.2419 4.51993C13.3134 4.50921 13.3848 4.49848 13.4563 4.49133Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.4985 17.0222C28.6414 16.94 28.7736 16.8256 28.9236 16.7791C29.7523 16.5181 30.5882 16.2678 31.4241 16.0211C31.4348 16.0175 31.467 16.0891 31.5384 16.1999C30.6168 16.7719 29.5595 16.8899 28.57 17.1974C28.545 17.1438 28.52 17.083 28.4985 17.0222Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M15.1246 10.5725C14.946 9.61439 14.8174 8.80282 14.6388 8.00198C14.4673 7.22974 14.2494 6.46465 14.1279 5.67453C14.4673 6.11785 14.5423 6.65056 14.6566 7.16896C14.7781 7.72669 14.9424 8.28084 15.0138 8.84572C15.0817 9.3677 15.3139 9.88253 15.1246 10.5725Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M4.04028 15.7209C4.45108 15.9712 4.86188 16.2143 5.26553 16.4717C5.3584 16.5289 5.41913 16.6362 5.42627 16.8293C5.27982 16.7721 5.12979 16.7256 4.99047 16.6576C4.44751 16.3895 3.90811 16.1178 3.36515 15.8461C3.27942 15.8568 3.19369 15.8711 3.10438 15.8818C3.04366 15.7174 2.98293 15.5529 2.86148 15.2419C3.28299 15.3706 3.56876 15.4528 3.85453 15.5386C3.91526 15.5994 3.97956 15.6602 4.04028 15.7209Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M4.04028 15.7209C3.97598 15.6602 3.9153 15.5991 3.851 15.5419C3.851 15.4418 3.851 15.3417 3.851 15.1379C4.30466 15.3488 4.68688 15.5276 5.0691 15.7028C5.28343 15.8422 5.50133 15.9781 5.71566 16.1175C5.93713 16.2641 6.1586 16.4142 6.48009 16.6288C6.10145 16.7396 5.93356 16.6395 5.74781 16.5143C5.38702 16.2712 5.00837 16.0603 4.64044 15.8315C4.45469 15.7135 4.27247 15.5922 4.04028 15.7209Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M32.1923 4.20896C31.3172 4.82389 30.2419 4.78457 29.6847 5.66763C29.4525 5.38519 29.5775 5.23146 29.7168 5.13851C29.9669 4.9669 30.2455 4.83819 30.5099 4.68804C30.7885 4.53073 31.06 4.36627 31.3422 4.21611C31.5672 4.10171 31.8065 4.01233 32.1923 4.20896Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M15.6639 11.4019C15.571 10.6761 15.5138 9.94321 15.3781 9.22459C15.2423 8.51313 15.0244 7.81597 14.8101 6.97937C15.2281 7.38694 15.3567 7.78379 15.5424 9.21029C15.6389 9.93248 15.8532 10.6475 15.8139 11.384C15.7639 11.3876 15.7139 11.3947 15.6639 11.4019Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M3.1077 15.882C3.19343 15.8712 3.27916 15.8569 3.36847 15.8462C3.43991 15.9606 3.48992 16.1108 3.58994 16.1823C3.90429 16.3968 4.24007 16.5827 4.66158 16.833C4.2615 17.001 4.05432 16.8044 3.85428 16.7007C3.50778 16.5183 3.18629 16.2931 2.85765 16.0786C2.71834 15.9892 2.62189 15.9856 2.55759 16.1537C2.3004 16.0786 2.11822 15.9463 2.14679 15.621C2.53616 15.4458 2.79335 15.7783 3.1077 15.882Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.8236 7.60522C28.7522 7.56231 28.6843 7.52299 28.5521 7.44433C29.2058 6.70069 30.1882 6.60416 30.9026 6.07146C30.924 6.05716 31.0062 6.12151 31.1562 6.20017C30.9169 6.3825 30.7276 6.52908 30.5347 6.67924L30.5454 6.67209C29.9096 6.88303 29.288 7.12257 28.8022 7.61237L28.8236 7.60522Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M30.5347 6.67536C30.7025 6.80049 30.7704 6.93635 30.5847 7.09723C30.5347 7.14013 30.4811 7.17946 30.4239 7.20806C29.7131 7.562 28.9986 7.90879 28.2449 8.28061C28.2128 7.83729 28.6128 7.79796 28.8236 7.60133L28.8057 7.61205C29.188 7.45475 29.5809 7.32246 29.9488 7.13656C30.1703 7.02573 30.3489 6.8294 30.5454 6.67209L30.5347 6.67536Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.8413 8.93134C28.4414 8.15552 29.5166 8.21272 30.349 7.54416C30.2882 7.77655 30.2847 7.89096 30.2311 7.96961C30.1882 8.03396 30.0882 8.06972 30.0096 8.10547C29.3166 8.42009 28.6236 8.73113 27.9306 9.04218C27.902 9.00642 27.8699 8.97067 27.8413 8.93134Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M3.16148 13.2575C3.52584 12.8642 4.44745 12.8285 5.09401 13.1753C4.75108 13.3183 3.68301 13.3648 3.16148 13.2575Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.288 9.72515C28.2237 9.63934 28.1273 9.55711 28.1058 9.46058C28.0916 9.40695 28.1916 9.31042 28.2559 9.25679C28.7524 8.87424 29.2954 8.57749 29.9705 8.34152C29.8776 8.7491 29.6026 8.80273 29.3954 8.94216C29.0132 9.19601 28.6485 9.47138 28.2735 9.73595L28.288 9.72515Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.2128 11.8454C27.6093 11.1447 28.3808 10.9945 29.0238 10.6548C29.0488 10.6942 29.0738 10.7299 29.0988 10.7693C28.5023 11.1697 27.9058 11.5737 27.3092 11.9741C27.2806 11.9312 27.2449 11.8883 27.2128 11.8454Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M26.652 13.0608C26.8734 12.3636 27.4057 12.0132 28.488 11.838C28.1916 12.0097 27.8808 12.1634 27.595 12.3529C27.3092 12.5424 27.0413 12.764 26.652 13.0608Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.9664 12.8037C27.402 13.1934 26.8376 13.5866 26.2589 13.9871C26.2125 13.5044 26.5304 13.2649 27.9664 12.8037Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.7153 4.51279C27.6261 5.1742 27.4512 5.82131 27.0444 6.39692C26.7376 6.22888 26.8268 6.10733 26.9267 5.93572C27.205 5.47094 27.4548 4.98829 27.7153 4.51279Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M24.0406 1.89186C24.1049 2.29943 24.2083 2.70701 24.2298 3.11458C24.2619 3.72594 24.2369 4.34087 24.2155 4.95581C24.162 3.92972 24.1084 2.90722 24.0513 1.88113L24.0406 1.89186Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M9.63433 6.91501C8.97348 6.67547 8.30906 6.4395 7.67322 6.2071C8.06973 6.04622 8.91275 6.30721 9.63433 6.91501Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.0662 15.9248C27.4484 15.6209 27.7235 15.4028 28.0021 15.1776C28.1414 15.6423 27.827 15.9355 27.0662 15.9248Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M13.2922 6.67929C13.6204 7.3693 13.7168 8.05574 13.5491 8.50264C13.5205 8.47762 13.467 8.45617 13.4634 8.42756C13.4063 7.84481 13.3493 7.26205 13.2922 6.67929Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.115 8.10582C21.0579 7.53736 21.015 7.11907 20.9687 6.63641C21.3861 6.94746 21.4646 7.56597 21.115 8.10582Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.6528 19.3569C31.2527 19.3676 30.8562 19.3819 30.5133 19.1209C30.5204 19.0744 30.5312 19.0244 30.5383 18.9779C30.9205 19.0351 31.3027 19.0959 31.685 19.1531C31.6742 19.221 31.6635 19.289 31.6528 19.3569Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M17.3998 12.4463C17.5068 13.0362 17.6138 13.6261 17.7173 14.216C17.6531 14.2267 17.5924 14.2374 17.5282 14.2482C17.4283 13.6583 17.3284 13.0719 17.2321 12.482C17.2891 12.4677 17.3427 12.457 17.3998 12.4463Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M15.4388 6.12518C15.8028 6.48628 15.9776 6.93318 15.9954 7.45516C15.7921 7.02971 15.5887 6.60426 15.3817 6.17524C15.3996 6.15736 15.421 6.14306 15.4388 6.12518Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M17.7823 13.7366C18.0607 14.1371 18.2676 14.5554 18.0678 15.0666C17.9715 14.6233 17.8751 14.18 17.7823 13.7366Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.695 3.66874C28.6522 3.24329 28.613 2.81784 28.5666 2.34949C28.8592 2.75706 28.8806 2.90722 28.695 3.66874Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M26.1767 8.73111C26.2731 8.34499 26.373 7.95887 26.4693 7.57632C26.6442 8.03395 26.48 8.41292 26.2945 8.78474C26.2552 8.76687 26.216 8.74899 26.1767 8.73111Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M16.9178 4.64514C17.139 5.00624 17.3638 5.37091 17.585 5.732C17.5351 5.7606 17.4887 5.78921 17.4387 5.81781C17.2353 5.45314 17.032 5.08847 16.8286 4.72737C16.8607 4.69877 16.8892 4.67374 16.9178 4.64514Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M12.5275 11.6234C12.2489 11.3875 11.9703 11.1479 11.6916 10.912C11.7202 10.8762 11.7523 10.8369 11.7809 10.8011C12.1489 10.9191 12.3525 11.2552 12.624 11.4983C12.5918 11.5376 12.5597 11.5805 12.5275 11.6234Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M11.581 12.8784C11.3203 12.7819 11.0631 12.6853 10.6808 12.5459C11.1702 12.3135 11.3953 12.528 11.6346 12.7032C11.6203 12.764 11.5989 12.8212 11.581 12.8784Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.7437 4.07657C21.7437 4.36616 21.7437 4.65218 21.7437 4.94177C21.7223 4.94534 21.7009 4.94534 21.6795 4.94892C21.6616 4.65933 21.6474 4.37331 21.6295 4.08372C21.6688 4.08014 21.7045 4.07657 21.7437 4.07657Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M16.3606 11.4378C16.4213 11.8132 16.4819 12.1885 16.539 12.5675C16.4819 12.5711 16.4248 12.5782 16.3678 12.5818C16.2893 12.2029 16.3535 11.8132 16.3642 11.427C16.3678 11.427 16.3606 11.4378 16.3606 11.4378Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.5862 8.43478C19.8181 8.66002 19.7895 8.83163 19.5862 9.1534C19.5862 8.83878 19.5862 8.67075 19.5862 8.43478Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.8808 6.4253C27.9414 6.25727 28.0021 6.09281 28.0592 5.92477C28.0913 5.9355 28.127 5.94623 28.1591 5.96053C28.102 6.13571 28.0449 6.30732 27.9878 6.48251C27.9521 6.46105 27.9165 6.44318 27.8808 6.4253Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M10.6023 7.33356C10.7414 7.41221 10.8842 7.49444 11.0233 7.5731C11.009 7.60527 10.9912 7.63745 10.9769 7.66605C10.8271 7.59455 10.6736 7.52662 10.5238 7.45511C10.5487 7.41579 10.5737 7.37646 10.6023 7.33356Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M18.325 14.391C18.2715 14.1908 18.2144 13.9906 18.1609 13.7904C18.2108 13.7832 18.2643 13.7797 18.3143 13.7725C18.3143 13.9835 18.3143 14.1908 18.3143 14.4018L18.325 14.391Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M10.1807 32.9173C11.1452 32.5311 11.9954 32.0306 12.6098 31.194C12.3168 32.2344 11.481 32.6741 10.6201 33.0924C10.4593 33.1711 10.2879 33.2712 10.1807 32.9173Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M11.9311 27.6799C11.0988 28.5558 9.50922 29.3352 8.9984 29.1171C9.01269 29.0778 9.01983 29.0135 9.04841 29.0063C10.0343 28.681 10.9202 28.1482 11.8168 27.6406C11.8383 27.6263 11.8918 27.6656 11.9311 27.6799Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M10.613 22.0918C9.83787 22.5494 8.9627 22.6924 8.07323 22.7961C8.8984 22.5101 9.72356 22.224 10.5487 21.938C10.5702 21.9881 10.5916 22.0417 10.613 22.0918Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M6.54422 34.2334C7.21935 34.0296 7.89806 33.8258 8.5732 33.622C8.04809 34.262 7.26936 34.1798 6.60494 34.4193C6.58708 34.3585 6.56565 34.2942 6.54422 34.2334Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M13.7636 30.8156C14.1423 30.5117 14.4745 30.2436 14.8067 29.9755C14.7567 30.5904 14.5138 30.7978 13.7636 30.8156Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M23.0942 30.6153C23.5585 31.2124 23.7979 31.931 24.0051 32.6353C24.3944 33.9545 24.5659 35.3203 24.4194 36.6931C24.2694 38.1232 23.9443 39.5211 23.4014 40.8582C23.3764 40.919 23.2728 40.9512 23.1084 41.0584C23.3871 40.1074 23.6907 39.2673 23.8622 38.4056C24.0336 37.5476 24.1587 36.6609 24.1515 35.785C24.1444 34.8877 24.0229 33.976 23.8122 33.1072C23.6085 32.2706 23.2263 31.4769 22.9227 30.6653C22.9798 30.6475 23.037 30.6332 23.0942 30.6153Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M18.0609 36.3426C18.0252 37.6368 15.9176 40.3325 14.8103 40.64C14.746 40.3576 14.9532 40.2289 15.121 40.1252C15.9748 39.5782 16.6106 38.8238 17.1607 37.9944C17.4036 37.6297 17.6001 37.2364 17.8144 36.8539C17.9037 36.6858 17.9788 36.5107 18.0609 36.3426Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M15.5853 36.5391C15.596 36.4641 15.5889 36.3961 15.6139 36.3497C15.8601 35.8741 16.1098 35.3987 16.3917 34.8588C16.456 35.4952 16.092 36.2209 15.5853 36.5391Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.164 33.7901C19.164 34.3336 18.9642 34.8019 18.6538 35.3346C18.6395 34.8985 18.7822 34.4087 19.0927 33.7329C19.1176 33.7508 19.1426 33.7687 19.164 33.7901Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M25.6482 38.8239C25.6482 38.4377 25.6482 38.0516 25.6482 37.6619C25.6874 37.6655 25.7267 37.6655 25.7659 37.6691C25.7231 38.0516 25.6803 38.4306 25.6375 38.8131C25.6375 38.8167 25.6482 38.8239 25.6482 38.8239Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.4005 32.6996C19.4112 32.3385 19.3042 31.9631 19.4862 31.627C19.5361 31.6342 19.5896 31.6449 19.6396 31.652C19.5575 31.9988 19.4719 32.3456 19.3898 32.6924L19.4005 32.6996Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M19.3857 32.6891C19.3107 33.0538 19.2358 33.422 19.1609 33.7867C19.1395 33.7688 19.1145 33.7509 19.0931 33.7295C19.193 33.3862 19.2965 33.0395 19.3964 32.6962L19.3857 32.6891Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.6544 32.8567C21.6437 33.0211 21.6365 33.1856 21.6258 33.3501C21.5866 33.3501 21.5473 33.3501 21.5045 33.3501C21.4974 33.1749 21.4867 32.9961 21.4795 32.8209C21.5366 32.8352 21.5937 32.8459 21.6544 32.8567Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M33.2066 29.2424C33.8139 29.7036 34.2068 30.3257 34.5212 31.005C34.6641 31.3196 34.7855 31.6414 34.9284 31.9846C34.5641 32.2313 34.3176 32.1169 34.0068 31.7558C34.2247 31.7451 34.3354 31.7379 34.4569 31.7308C34.4533 31.695 34.4605 31.6485 34.4426 31.6235C34.3033 31.4269 33.8675 31.5198 33.9354 31.1337C33.9854 30.8584 33.4353 30.8763 33.6675 30.5295C33.671 30.5223 33.5246 30.4079 33.446 30.3507C33.3531 30.2792 33.2531 30.2077 33.1245 30.1112C33.2638 30.0361 33.3495 29.9896 33.4674 29.9217C33.1816 29.7894 32.9173 29.6643 32.5351 29.4855C32.8494 29.3675 33.0352 29.2996 33.2174 29.2317L33.2066 29.2424Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M30.7741 35.3701C30.1526 34.3905 29.2274 33.6862 28.4844 32.8103C28.8094 32.7102 28.9738 32.9175 29.1309 33.0641C29.6703 33.5753 30.1954 34.1009 30.6991 34.6479C30.842 34.8016 30.892 35.0447 30.9849 35.2485C30.9134 35.2879 30.842 35.3272 30.7741 35.3701Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.7816 27.2368C31.4494 27.5371 31.1351 27.4049 30.8421 27.3262C30.5849 27.2547 30.2027 27.362 30.1456 26.8864C30.1313 26.7577 29.8241 26.6648 29.6383 26.5468C29.9741 26.4217 30.66 26.5003 31.2708 26.7291C31.1922 26.8328 31.1208 26.9258 31.0493 27.0259C31.2922 27.0938 31.5387 27.1653 31.7816 27.2368Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.331 24.7158C27.899 25.0269 28.5238 25.1164 29.156 25.1485C29.3632 25.1593 29.574 25.1736 29.9062 25.195C29.5526 25.549 29.2346 25.4596 28.9703 25.4024C28.2702 25.2558 27.5271 25.2594 26.8663 24.9519C26.8699 24.9019 26.8734 24.8518 26.877 24.8017C27.0342 24.7767 27.1878 24.7553 27.345 24.7302L27.331 24.7158Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.0491 23.9759C31.7814 24.4908 32.5208 24.9949 32.8423 25.8565C32.7923 25.9173 32.7816 25.9387 32.7638 25.9494C32.7495 25.9602 32.728 25.9745 32.7102 25.9745C32.6673 25.9673 32.603 25.9602 32.5923 25.9351C32.2351 25.1593 31.5814 24.6159 31.0491 23.9759Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.5167 25.6419C29.2311 25.7599 29.8705 25.8672 30.6385 25.9959C29.9884 26.3069 28.9275 26.1138 28.5167 25.6419Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M32.4424 28.3197C31.9351 28.3733 31.5136 28.1195 31.0707 27.9407C31.0885 27.8835 31.1028 27.8228 31.1207 27.7656C31.5779 27.8907 32.0352 28.0122 32.496 28.1374C32.4745 28.1981 32.4602 28.2589 32.4424 28.3197Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M33.2175 29.2282C32.7603 29.1639 32.3388 29.0245 31.9244 28.6133C32.5388 28.6205 33.0211 28.6312 33.2068 29.239C33.2068 29.2425 33.2175 29.2282 33.2175 29.2282Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.3933 27.2939C37.0968 26.9686 36.7967 26.6432 36.5002 26.3179C36.536 26.2857 36.5717 26.2535 36.6074 26.2249C36.9432 26.5145 37.2754 26.8041 37.4719 27.226C37.4469 27.2439 37.4183 27.2689 37.3933 27.2939Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M35.0242 27.6764C34.7031 27.4619 34.4212 27.208 34.2071 26.8219C34.6139 26.9578 34.7387 27.0865 35.0492 27.6513L35.0242 27.6764Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M30.0704 23.3538C30.3273 23.3788 30.5557 23.436 30.545 23.9437C30.2952 23.7578 30.1311 23.6362 29.9669 23.5147C30.0026 23.461 30.0383 23.4074 30.0704 23.3538Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.5318 25.699C37.2855 25.4952 37.0393 25.2914 36.7931 25.0876C37.207 25.0769 37.4211 25.3379 37.621 25.6168C37.5924 25.6454 37.5603 25.6704 37.5318 25.699Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M37.4717 27.2184C37.7572 27.4365 37.8107 27.7368 37.882 28.1516C37.3932 27.9406 37.5502 27.5366 37.3896 27.2899C37.4182 27.2685 37.4467 27.2435 37.4717 27.2184Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.9559 34.0655C31.749 33.7902 31.542 33.5185 31.3386 33.2432C31.7097 33.3754 31.8846 33.6758 32.0451 33.9868C32.0166 34.0118 31.9845 34.0404 31.9559 34.0655Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M35.0535 27.6514C35.239 27.8659 35.4246 28.0769 35.6101 28.2914C35.5887 28.3128 35.5673 28.3307 35.5459 28.3522C35.3746 28.1269 35.1998 27.9017 35.0285 27.6765C35.0249 27.6765 35.0535 27.6514 35.0535 27.6514Z\"\n        fill=\"#676461\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 41 / 43,\n  svg: Persimmon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/radish.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Radish', 'sticker name', 'web-stories');\n\nfunction Radish({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 109 170\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M43.7888 70.1018C44.1301 70.1235 44.4864 70.0857 44.8001 70.184C46.1127 70.602 47.4134 71.0609 48.553 71.8698C48.9038 72.1136 49.278 72.3327 49.657 72.524C50.5312 72.9557 51.4128 73.178 52.2073 72.4079C52.6485 72.7107 53.0503 72.9922 53.6197 73.3846C53.5534 72.5492 53.4866 71.91 53.4625 71.2736C53.3699 68.8722 53.3402 66.4675 53.1995 64.0672C52.9156 59.1705 53.0171 54.2889 53.3965 49.4083C53.5635 47.3065 53.1946 45.3115 52.5267 43.3548C50.7076 38.0248 48.2782 33.0089 44.8277 28.522C42.7921 25.8838 40.5949 23.4327 37.6017 21.8424C36.4695 21.2407 35.3269 20.6708 34.2017 20.056C34.0006 19.9439 33.8734 19.6821 33.7109 19.4858C33.9066 19.3239 34.0748 19.0997 34.2965 19.0094C36.2277 18.2336 38.1704 17.4741 40.0051 16.7579C42.2251 17.7475 44.1218 18.9723 45.712 20.5837C46.6574 21.5452 47.4639 22.6451 48.29 23.7149C48.9552 24.5792 49.6039 25.4549 50.1725 26.3788C51.2129 28.0659 52.1895 29.7895 53.1971 31.4996C53.3715 31.7937 53.5551 32.0894 53.791 32.471C54.3889 28.9316 54.8667 25.4765 55.5754 22.0715C56.2867 18.624 57.27 15.2387 59.0535 12.0757C61.3605 12.9225 63.6769 13.771 66.124 14.6665C65.9808 15.1346 65.859 15.6448 65.6737 16.1342C64.3221 19.7372 63.2502 23.4134 62.3819 27.159C61.8976 29.2385 61.3685 31.3005 60.94 33.3898C60.6491 34.7945 60.4458 36.2195 60.2998 37.6449C60.1033 39.6123 59.9626 41.5894 59.8793 43.5671C59.8489 44.2418 59.957 44.9745 60.2139 45.5944C61.7259 49.2371 62.7031 53.0347 63.476 56.8777C63.9151 59.0767 64.1111 61.3239 64.5693 63.6891C64.6217 63.4971 64.6609 63.2981 64.7226 63.1078C66.516 57.7818 68.352 52.4585 69.3173 46.9053C70.0312 42.7781 70.6334 38.6312 71.1837 34.48C71.4798 32.2141 71.5603 29.9199 71.7487 27.6398C71.7874 27.1389 71.8091 26.6255 71.9222 26.1378C72.2002 24.9463 72.047 23.8369 71.4724 22.7539C71.3596 22.5473 71.3591 22.2455 71.3916 22.0022C71.445 21.638 71.5821 21.2886 71.7138 20.8041C71.9078 21.0681 72.0555 21.2666 72.3418 21.6618C72.8354 15.0677 72.1803 8.79804 70.3584 2.51454C71.843 2.07672 73.3056 2.70783 74.7666 2.57238C75.4896 4.01675 75.6211 5.50064 75.8623 6.93201C76.2603 9.25785 76.4244 11.6335 76.8224 13.9594C77.189 16.0785 77.2151 18.2 77.3264 20.3269C77.3697 21.1295 77.5852 21.9338 77.8202 22.7079C78.8112 25.8997 79.9748 29.0356 80.6183 32.3243C80.86 33.5593 81.0557 34.8103 81.4586 36.0546C81.5159 35.6959 81.5879 35.335 81.6227 34.9676C81.9408 31.4939 82.2162 28.0175 81.9634 24.5199C81.8449 22.8227 82.0313 21.1075 82.0254 19.3966C82.0197 17.7673 81.9751 16.1406 81.9027 14.5091C81.8529 13.3844 81.6975 12.2603 81.6755 11.1405C81.6376 9.0601 81.1003 7.06891 80.6663 5.06239C80.4067 3.84809 80.1416 2.63762 79.9077 1.41347C79.8626 1.17564 79.9557 0.91426 79.9795 0.693359C82.0559 0.934464 84.0338 1.16302 86.2699 1.42267C86.6924 1.99994 86.6291 2.97539 86.7487 3.86331C87.2279 7.52051 87.6683 11.1805 88.0403 14.8475C88.6177 20.4856 89.1563 26.1265 89.1182 31.8047C89.1067 33.2011 89.0619 34.5965 89.041 35.9913C89.0374 36.2062 89.0765 36.4238 89.1173 36.8525C89.9125 35.3306 90.652 34.0192 91.298 32.6675C93.0181 29.0671 94.7831 25.4842 96.3701 21.822C97.2309 19.8376 97.7697 17.7198 98.4339 15.6528C98.5264 15.3674 98.5013 15.0421 98.5117 14.7326C98.5634 13.7407 98.7668 13.5898 99.6192 14.0368C100.883 14.7095 102.102 15.3888 103.438 16.1173C103.376 16.4465 103.344 16.8287 103.231 17.1775C101.761 21.8758 100.309 26.5866 98.786 31.2657C98.1401 33.2545 97.3262 35.1897 96.5943 37.149C95.4919 40.087 94.4065 43.0377 93.2817 45.967C92.1514 48.9002 90.8447 51.7449 89.1667 54.4092C88.2015 55.9442 87.2704 57.5044 86.3825 59.0914C86.0853 59.6185 85.9573 60.2473 85.773 60.8423C85.428 61.9501 85.1016 63.0612 84.7477 64.2489C85.2144 64.1826 85.3759 63.7752 85.6599 63.5187C89.0402 60.4597 91.9012 56.9405 94.5845 53.2846C96.3651 50.8587 98.0825 48.3546 99.5956 45.757C101.389 42.6771 102.973 39.4743 103.977 36.0255C103.999 35.9528 104.03 35.8817 104.049 35.8035C104.499 34.2785 104.504 34.2506 106.023 34.8915C106.8 35.2199 107.532 35.6697 108.301 36.0686C108.25 36.3901 108.257 36.6307 108.173 36.8363C106.981 39.7394 105.847 42.6671 104.553 45.5189C103.217 48.4827 101.754 51.3958 100.271 54.2908C98.7409 57.2924 97.2337 60.3268 95.1576 62.9929C93.6618 64.9086 92.0986 66.7981 90.4114 68.5461C87.9652 71.0799 85.3764 73.4689 82.8524 75.9268C80.4548 78.2632 77.8071 80.2443 74.8899 81.9002C73.7205 82.5659 72.6963 83.4727 71.6121 84.2828C71.5014 84.3687 71.4369 84.5201 71.4173 84.5502C72.4174 85.9715 73.4188 87.3021 74.3089 88.6945C75.7901 91.0195 77.2587 93.3614 78.6214 95.7614C80.7418 99.516 81.7802 103.597 81.9428 107.893C82.0576 110.998 82.0706 114.108 81.5067 117.175C80.7534 121.281 79.5094 125.176 77.213 128.756C75.0731 132.096 72.1917 134.625 69.1991 137.077C65.4072 140.188 61.0038 142.152 56.3713 143.64C56.1839 143.698 55.9982 143.746 55.817 143.825C55.0329 144.146 54.2308 144.767 53.4684 144.714C52.6579 144.662 51.8746 144.73 51.0946 144.78C50.0133 144.853 48.9438 145.162 47.8684 145.174C46.2746 145.19 44.7093 145.375 43.1497 145.636C42.088 145.818 41.0502 146.138 39.9808 146.309C37.7643 146.656 35.5334 146.948 33.3086 147.261C30.6761 147.63 28.1724 148.392 25.8807 149.755C25.2827 150.11 24.6677 150.452 24.112 150.866C22.7769 151.853 21.7818 153.09 20.9257 154.549C20.3268 155.573 19.9689 156.756 19.1487 157.674C18.341 158.576 17.4689 159.352 16.4361 160.003C15.4306 160.636 14.5511 161.482 13.6479 162.271C13.3601 162.522 13.1261 162.85 12.9348 163.18C12.3028 164.285 11.68 165.392 11.1044 166.531C10.7401 167.252 10.4716 168.029 10.1505 168.777C10.0632 168.977 9.94956 169.163 9.75022 169.54C9.56467 169.172 9.45186 168.965 9.36471 168.749C9.341 168.692 9.39044 168.6 9.42575 168.534C10.5986 165.882 11.5332 163.11 13.4663 160.855C14.3 159.886 15.4245 159.341 16.4842 158.728C17.635 158.059 17.9538 157.158 17.769 155.899C17.6453 155.063 17.669 154.205 17.7098 153.36C17.7234 153.032 17.8763 152.647 18.0958 152.403C19.2674 151.115 19.3165 149.529 19.058 148.003C18.4857 144.607 17.8576 141.202 16.5183 138.001C16.0877 136.972 15.4954 135.992 14.8764 135.054C13.0933 132.37 11.2191 129.741 9.4578 127.041C8.50295 125.579 7.66809 124.034 6.86275 122.484C6.23686 121.282 5.83523 119.947 5.13845 118.794C4.3471 117.496 4.05876 116.032 3.48427 114.672C2.896 113.28 2.43766 111.829 1.94113 110.406C1.02047 107.777 0.540225 105.068 0.604313 102.287C0.667832 99.3432 0.891707 96.442 1.8895 93.61C3.60569 88.7302 6.00841 84.2586 9.27502 80.2504C11.5497 77.4613 14.2311 75.1461 17.2309 73.1791C17.4802 73.0123 17.6872 72.7853 17.9019 72.5693C17.9776 72.4916 18.0075 72.2909 18.0665 72.2822C19.7402 72.1363 20.9432 70.9161 22.4542 70.3536C25.6082 69.1849 28.8042 68.2725 32.1535 68.0529C34.9944 67.8635 37.8052 68.2914 40.5392 69.1081C40.6213 69.1321 40.6693 69.2699 40.727 69.3519L40.7466 69.3218C39.9111 69.1651 39.0827 68.9953 38.244 68.8572C37.6286 68.7584 37.0105 68.7022 36.3864 68.6259C36.354 68.7303 36.3231 68.8255 36.2907 68.9299C37.5191 69.6682 38.7437 70.4011 39.9667 71.1433C39.5318 71.22 39.1684 71.132 38.8365 70.973C37.4021 70.2894 35.9693 69.5965 34.9335 68.4371C30.6026 68.2923 26.5868 69.2901 22.4578 70.9146C24.1693 72.351 25.6932 73.6251 27.2155 74.9085C25.0798 74.0966 23.5592 72.3873 21.6632 71.1866C20.7466 71.7484 19.7262 72.0237 18.955 72.908C20.1366 73.8344 21.2671 74.7232 22.3938 75.6064C22.3383 75.6781 22.2828 75.7497 22.2273 75.8214C20.9174 74.9442 19.5983 74.0653 18.2281 73.1488C18.0347 73.3254 17.8287 73.519 17.5938 73.7411C18.9481 74.8321 20.162 75.9318 21.4933 76.8511C22.8076 77.7579 24.2487 78.4858 25.6102 79.2859C25.5939 79.2973 25.522 79.3805 25.4678 79.3614C25.1307 79.2876 24.7811 79.2309 24.4646 79.0937C22.6133 78.3271 20.9969 77.1996 19.4637 75.9238C18.6291 75.2357 17.739 74.6192 16.8855 73.9851C16.4366 74.3084 16.0968 74.5551 15.7243 74.8247C17.3335 77.019 19.5623 78.4843 21.3913 80.3773C20.2674 79.6717 19.1975 78.9038 18.1939 78.0566C17.1602 77.1897 16.1875 76.2473 15.1388 75.3011C14.6748 75.684 14.2997 75.9963 13.9012 76.3332C15.3495 77.5461 16.6627 78.764 18.1065 79.8084C19.5542 80.8584 21.1271 81.7388 22.6444 82.6908C22.0848 82.6019 21.5238 82.4648 21.0319 82.2058C19.0056 81.121 17.1523 79.7841 15.422 78.2629C14.7984 77.7125 14.1533 77.12 13.2428 76.9261C12.3937 77.8733 11.2285 78.4871 10.5964 79.5923C12.2564 81.4651 14.2576 82.7227 16.4662 83.6958C13.9806 83.2438 12.0237 81.8408 10.101 80.1852C8.8786 81.6557 7.62743 83.0159 6.91943 84.7543C9.07396 86.7045 11.4908 88.1359 13.9737 89.4064C16.466 90.6786 19.069 91.7261 21.6264 92.8708C16.0804 91.4393 11.2195 88.5958 6.43072 85.2525C5.95595 86.1411 5.5502 86.9078 5.07382 87.8057C5.68049 88.2047 6.19093 88.6059 6.75787 88.9021C8.97753 90.088 11.1994 91.2886 13.456 92.3996C17.0238 94.1581 20.4914 96.1911 24.4892 96.9047C24.5422 97.3738 24.3119 97.4865 23.9386 97.3728C22.869 97.0456 21.7501 96.8103 20.7342 96.3392C16.8973 94.5573 13.0848 92.7174 9.28479 90.8605C7.73369 90.1036 6.23908 89.2418 4.65595 88.3931C4.34579 89.1335 4.01989 89.9094 3.66799 90.7526C6.00276 92.0211 8.27082 93.2873 10.5687 94.4918C12.8705 95.7017 15.1831 96.9039 17.5289 98.0258C19.8522 99.1389 22.2265 100.151 24.5742 101.206C24.5488 101.297 24.5289 101.385 24.4997 101.471C24.2229 101.436 23.9272 101.456 23.6764 101.354C22.2336 100.775 20.7555 100.261 19.3709 99.5666C15.1698 97.4523 11.011 95.2593 6.83269 93.0963C5.7065 92.5149 4.56939 91.9411 3.30627 91.2924C3.09687 91.9212 2.92537 92.4418 2.73652 93.0072C5.77809 94.539 8.41277 96.5116 11.5594 97.7409C11.3498 97.8717 11.2382 97.9909 11.1599 97.9723C10.7873 97.8827 10.3998 97.7954 10.0603 97.6254C7.51731 96.397 5.06616 94.9979 2.62564 93.5097C2.41044 94.1998 2.17308 94.9626 1.90712 95.8353C3.66817 96.9022 5.30314 98.033 7.05432 98.9352C10.2976 100.603 13.5989 102.157 16.8878 103.727C17.3303 103.939 17.8374 104 18.32 104.118C18.9855 104.288 19.6189 104.505 20.1885 105.396C19.6638 105.298 19.3822 105.292 19.1423 105.183C16.0602 103.802 12.9445 102.477 9.91508 100.986C7.61906 99.8536 5.4338 98.4966 3.20134 97.2462C2.75593 96.9954 2.2839 96.7877 1.71919 96.5063C1.62547 97.3806 1.55622 98.058 1.50275 98.5611C1.96326 98.7523 2.32116 98.8441 2.60943 99.0337C3.61017 99.7033 4.52232 100.525 5.58116 101.08C8.29594 102.506 11.0531 103.854 13.8221 105.16C16.8743 106.603 19.9689 107.967 23.0423 109.37C23.344 109.51 23.7096 109.612 23.5669 110.243C22.2097 109.889 21.1263 109.033 19.9042 108.535C18.6092 108.015 17.3647 107.37 16.0958 106.782C14.8625 106.211 13.6292 105.639 12.3958 105.067C11.1269 104.48 9.84932 103.915 8.60159 103.288C7.38945 102.677 6.17508 102.051 5.01783 101.345C3.85288 100.627 2.75374 99.8063 1.45279 99.127C1.43785 99.5458 1.43486 99.7848 1.41487 100.011C1.33717 100.931 1.65602 101.581 2.57031 101.92C2.96668 102.066 3.31809 102.334 3.68846 102.548C6.5478 104.191 9.39686 105.866 12.2758 107.479C14.4124 108.674 16.5717 109.821 18.7468 110.932C22.8232 113.019 26.9175 115.086 31.2565 116.597C31.5593 116.703 31.8414 116.873 32.1339 117.011C32.114 117.098 32.0924 117.195 32.0725 117.282C31.8506 117.291 31.5971 117.371 31.4137 117.296C28.9371 116.266 26.4344 115.303 24.0229 114.145C20.4169 112.414 16.844 110.602 13.3228 108.712C10.3499 107.116 7.46333 105.353 4.52735 103.682C3.59325 103.153 2.63091 102.677 1.6641 102.172C1.49874 102.574 1.34016 102.881 1.24508 103.209C1.00576 104.039 1.35819 104.91 2.11045 105.354C3.68073 106.277 5.25645 107.196 6.84469 108.099C9.30513 109.499 11.7325 110.98 14.2565 112.263C17.2346 113.774 20.2952 115.113 23.3243 116.522C23.6655 116.683 24.0567 116.776 24.1492 117.405C23.7941 117.352 23.4852 117.365 23.2415 117.25C21.1254 116.269 18.9794 115.35 16.9322 114.247C12.8287 112.04 8.78158 109.728 4.70081 107.472C3.72951 106.937 2.72836 106.464 1.68875 105.936C1.58078 107.114 2.67433 111.181 3.36204 112.552C3.88925 112.746 4.30779 112.819 4.6448 113.032C5.82897 113.777 7.01153 114.531 8.14564 115.344C10.8798 117.296 13.7834 118.932 16.8728 120.243C19.4081 121.321 21.9717 122.348 24.5314 123.368C28.9697 125.136 33.286 127.194 37.836 128.704C40.4548 129.577 43.0422 130.521 45.8525 130.509C45.9969 130.505 46.143 130.713 46.2883 130.815C45.6182 131.033 45.0007 131.139 44.4202 131.032C42.7493 130.719 41.0565 130.421 39.4363 129.925C35.8676 128.837 32.4196 127.411 28.9928 125.945C26.9536 125.073 24.8867 124.278 22.8497 123.422C19.9104 122.186 16.8955 121.109 14.0903 119.624C10.842 117.902 7.7875 115.808 4.65213 113.876C4.41869 113.73 4.16952 113.619 3.66831 113.358C4.23379 114.799 4.67141 115.953 5.14946 117.096C5.23052 117.292 5.43669 117.458 5.61977 117.591C8.3141 119.579 11.1628 121.311 14.2735 122.582C17.7657 124.002 21.2304 125.498 24.7464 126.835C28.8422 128.395 32.7843 130.372 37.1043 131.301C37.3166 131.348 37.4961 131.556 37.7394 131.729C37.555 131.825 37.4793 131.903 37.4289 131.889C35.7789 131.455 34.1121 131.09 32.4984 130.557C30.9892 130.056 29.5455 129.371 28.0639 128.794C25.8974 127.938 23.7151 127.118 21.5501 126.253C18.9231 125.206 16.2819 124.186 13.6895 123.049C12.1348 122.368 10.6425 121.521 9.16326 120.681C8.10315 120.078 7.11045 119.362 6.08565 118.693C6.49818 120.02 7.06987 121.203 7.58316 122.419C7.98945 123.367 8.70445 123.943 9.58854 124.401C9.84318 123.732 10.2167 124.066 10.5306 124.246C12.1189 125.148 13.6647 126.129 15.2844 126.96C17.4897 128.091 19.7428 129.139 21.9991 130.169C24.4054 131.272 26.8876 132.16 29.5593 132.367C30.0603 132.407 30.5705 132.449 31.0587 132.564C31.3624 132.636 31.751 132.772 31.569 133.243C30.4115 133.091 29.2941 132.986 28.1911 132.796C24.9737 132.254 22.06 130.869 19.1518 129.48C16.6281 128.279 14.1728 126.932 11.6821 125.651C11.44 125.527 11.0831 125.263 10.9538 125.345C10.3035 125.753 9.95642 125.155 9.49431 124.973C9.31472 124.903 9.13898 124.839 8.95394 124.773C9.52437 125.908 10.1965 126.898 10.8796 127.88C10.945 127.973 11.0476 128.072 11.1444 128.094C12.434 128.341 13.2518 129.375 14.3321 129.973C15.8277 130.801 17.3233 131.63 18.8243 132.454L18.8455 132.415C18.3548 132.343 17.8114 132.381 17.3859 132.182C16.1635 131.603 14.9757 130.934 13.7957 130.276C13.1585 129.915 12.5567 129.488 11.9446 129.092C12.6243 130.371 13.3987 131.518 14.184 132.657C14.6555 133.339 15.1656 133.937 15.9685 134.337C18.1562 135.431 20.2542 136.71 22.7302 137.079C23.0666 137.129 23.4993 137.176 23.703 137.744C20.7574 137.541 18.3489 136.145 15.7567 134.73C16.103 135.72 16.5251 136.355 17.3072 136.737C18.384 137.271 19.4467 137.832 20.5056 138.387C20.6201 138.446 20.6954 138.565 20.7887 138.662C20.7566 138.709 20.73 138.753 20.6979 138.8C19.544 138.295 18.3902 137.79 17.036 137.197C17.4108 138.216 17.6863 138.978 17.9695 139.751C18.8356 140.368 20.0938 140.408 20.7675 141.527C20.4624 141.684 20.2469 141.795 20.022 141.904C20.3156 142.229 20.5939 142.531 20.8991 142.872C20.4937 143.443 20.1346 143.94 19.7684 144.45C20.1256 144.796 20.8854 144.752 20.9954 145.557C20.7843 145.697 20.5584 145.839 20.3419 145.983C20.6086 146.27 20.826 146.509 21.1081 146.817C20.7321 147.024 20.4767 147.171 20.1264 147.368C21.2055 147.778 20.5757 148.898 21.1303 149.57C21.409 149.538 21.6637 149.506 21.9479 149.47C21.711 149.122 21.511 148.838 21.2511 148.456C21.8159 148.321 22.2246 148.23 22.6901 148.116C22.6429 147.447 22.9932 147.25 23.6218 147.356C24.0179 147.421 24.4278 147.378 24.7188 147.386C24.7786 146.209 23.6066 146.28 23.0959 145.659C24.8197 146.082 26.5051 146.451 28.1634 146.92C29.1223 147.194 29.9416 146.946 31.0281 146.51C30.1623 146.252 29.5225 146.072 28.8843 145.883C30.3947 145.656 31.7719 146.698 33.535 146.007C32.8205 145.733 32.3266 145.541 31.8405 145.359C31.3543 145.178 30.7769 145.191 30.4182 144.716C32.636 145.054 34.6923 146.575 37.1766 145.427C35.7742 144.975 34.4577 144.551 33.1467 144.124C33.1721 144.033 33.1991 143.932 33.2245 143.841C35.4219 144.462 37.5528 145.441 39.9313 145.127C38.4118 144.658 36.8962 144.195 35.3713 143.73C35.3982 143.63 35.4307 143.525 35.4577 143.425C36.2097 143.648 36.9618 143.871 37.7116 144.08C38.5303 144.306 39.3481 144.565 40.1906 144.708C40.9402 144.835 41.7122 144.832 42.4746 144.885C42.489 144.802 42.4942 144.716 42.5087 144.633C42.1075 144.514 41.6976 144.418 41.3121 144.264C40.9344 144.121 40.5717 143.918 40.2097 143.739L40.1955 143.766C41.1721 143.937 42.1449 144.104 43.099 144.267C43.2861 143.989 43.4357 143.761 43.6157 143.496C43.1395 143.34 42.6831 143.236 42.2653 143.048C41.9 142.887 41.3473 143.063 41.0596 142.399C42.9653 142.769 44.6106 143.59 46.4202 143.683C45.1674 142.864 43.6887 142.465 42.5643 141.458C42.8892 141.491 43.1678 141.597 43.4542 141.715C44.8133 142.28 46.1582 142.871 47.5237 143.399C48.3187 143.706 49.1468 143.795 49.9838 143.305C48.0396 142.383 46.1518 141.495 44.2694 140.604C44.3095 140.51 44.3497 140.417 44.3898 140.323C44.8618 140.531 45.3339 140.738 45.8075 140.937C47.3035 141.569 48.7876 142.242 50.3064 142.826C51.1238 143.142 51.9911 143.309 53.017 142.752C52.2227 142.469 51.5691 142.258 50.9383 141.998C50.2588 141.716 49.5411 141.46 48.9415 141.048C48.4153 140.682 47.5745 140.889 47.3055 140.089C48.4693 140.481 49.581 141.007 50.722 141.448C51.949 141.917 53.175 142.421 54.5179 142.442C54.7383 142.442 54.9609 142.319 55.1794 142.247C55.1775 142.175 55.1756 142.103 55.1682 142.034C53.8762 141.553 52.5857 141.062 51.2937 140.581C51.5195 140.439 51.7027 140.433 51.8707 140.486C53.0438 140.879 54.2349 141.252 55.3875 141.709C55.9301 141.924 56.4272 141.959 56.9651 141.785C60.4672 140.683 63.7567 139.174 66.596 136.805C66.7247 136.698 66.9948 136.55 67.0272 136.584C67.3988 136.985 67.575 136.575 67.7762 136.409C68.9974 135.389 70.2225 134.374 71.4151 133.324C72.1679 132.657 72.9184 131.975 73.5801 131.224C74.5762 130.092 75.502 128.895 76.4564 127.727C77.7196 126.187 78.814 124.569 79.1924 122.548C79.3271 121.825 79.4259 121.004 79.8489 120.47C80.2414 119.974 80.3709 119.475 80.4789 118.933C81.3647 114.726 81.4772 110.474 81.1244 106.197C80.8778 103.218 80.1137 100.349 78.8021 97.7089C77.3908 94.8694 75.6067 92.218 74.0144 89.5382C72.897 89.4325 71.8571 89.4601 70.9099 88.9245C71.7379 88.6536 72.5998 89.1838 73.4518 88.9123C72.2503 86.7994 72.2371 86.7923 71.6803 86.881C71.7376 87.0204 71.8065 87.1762 71.9818 87.5759C69.8879 87.0204 68.0179 86.5283 66.1533 86.0323C66.1279 86.1236 66.108 86.2111 66.0865 86.3079C68.0949 87.1357 70.1201 87.8946 72.4999 87.988C72.0395 88.4337 71.6459 88.465 71.2376 88.3596C70.3002 88.1275 69.3644 87.8861 68.4334 87.6168C67.8997 87.4605 67.4585 87.1577 66.8345 87.5795C66.4652 87.8305 65.7936 87.7793 65.373 87.2742C65.2066 87.0725 64.9585 86.9282 64.7202 86.8097C61.8184 85.3839 59.0749 83.7083 56.402 81.9014C56.2436 81.7921 56.0569 81.7353 55.8806 81.6467C59.5449 84.7585 63.4957 87.3507 68.0482 88.957C67.3968 88.8998 66.7708 88.7512 66.1817 88.5277C62.8972 87.2645 59.8849 85.508 57.0726 83.3988C56.576 83.0288 56.0649 82.4647 55.5213 82.4216C54.1742 82.3137 53.4484 80.8305 52.006 80.9693C51.7474 80.9956 51.4105 80.5052 51.1477 80.2243C48.9606 77.8803 47.4251 75.177 46.6929 72.0404C46.5802 71.5559 46.4024 71.199 45.9008 70.9957C45.1896 70.7028 44.5152 70.335 43.8213 69.9973L43.7888 70.1018ZM66.8642 68.097C67.2218 67.6092 67.5809 67.1121 67.9384 66.6243C68.0834 66.5061 68.2663 66.4186 68.3735 66.2699C70.2295 63.6848 71.9354 61.0254 72.5738 57.8332C72.641 57.5002 72.6171 57.0841 73.0172 56.8768C73.0963 57.0009 73.1682 57.0566 73.1755 57.125C73.195 57.2338 73.1927 57.3579 73.1696 57.464C72.8205 59.2607 72.2863 60.9914 71.3689 62.5827C70.7738 63.613 70.1601 64.64 69.5502 65.6725C69.4286 65.766 69.2917 65.8377 69.204 65.9563C67.9444 67.5593 66.7133 69.1912 65.4236 70.7744C64.559 71.8386 63.6111 72.8307 62.701 73.8534C62.9708 73.9009 63.1373 73.8249 63.2544 73.7018C64.7334 72.1328 66.2749 70.6178 67.6574 68.9695C68.4654 68.0102 69.0086 66.8367 69.6747 65.7566C69.8697 65.7096 70.074 65.6641 70.5084 65.5634C69.7751 66.4783 70.2455 67.3323 70.0389 68.1388C70.3033 67.9124 70.5196 67.687 70.6756 67.4224C73.2348 63.1268 75.7638 58.8116 76.9752 53.886C77.0452 53.5918 77.1034 53.1997 77.7495 53.1219C76.8504 57.4608 74.8246 61.1941 72.9187 64.9821C73.4645 64.4029 73.9731 63.8172 74.3689 63.1637C76.1131 60.3386 77.3403 57.2884 78.0906 54.0584C78.7452 51.2714 79.2433 48.4472 79.9351 45.6667C80.6085 42.9644 80.8073 40.2359 80.644 37.4677C80.4287 33.9192 79.5742 30.4929 78.4951 27.118C78.1075 25.8955 77.7199 24.673 77.2865 23.4664C76.9095 22.4326 76.5448 22.2966 75.4916 22.7337C76.6141 25.9965 77.4902 29.3261 77.5724 32.8128C77.3996 32.6483 77.3223 32.4575 77.2801 32.2585C76.9223 30.4761 76.5792 28.6915 76.2121 26.9075C76.1404 26.574 76.0472 26.1984 75.8424 25.942C75.3317 25.3205 74.754 24.7542 74.2035 24.1688C74.5119 25.2672 74.9509 26.331 75.3494 27.407C75.4212 27.6016 75.3351 27.8499 75.3141 28.2485C74.0239 27.0634 74.2861 25.2705 73.088 24.1352C73.0507 24.4064 73.0112 24.524 73.0323 24.6235C73.449 26.6748 73.969 28.7108 74.2584 30.7781C74.5599 32.8858 74.779 35.0269 74.7903 37.1505C74.7982 39.4316 74.471 41.7112 74.3773 43.9984C74.2558 46.9176 73.7118 49.7577 73.0213 52.5863C71.7816 57.7033 69.6081 62.3733 66.5464 66.6378C66.4572 66.7658 66.4189 66.9314 66.3598 67.0791C66.9611 66.706 67.4062 66.2384 67.7701 65.7134C68.1482 65.1622 68.4435 64.5628 68.7745 63.9793C68.8643 64.0143 68.9595 64.0455 69.0532 64.0859C68.9988 64.3445 68.9971 64.6316 68.8809 64.8602C68.574 65.4431 68.2145 65.9976 67.8775 66.5609C67.5068 67.0416 67.1362 67.5223 66.76 68.0068C65.2478 69.2971 63.9648 70.7857 62.9303 72.5001C63.3821 72.2157 63.7636 71.8662 64.0957 71.4697C65.0203 70.3633 65.9403 69.2274 66.8642 68.097ZM57.2305 79.4659C58.2437 80.2573 59.2515 81.0526 60.2647 81.844C59.9167 81.9168 59.602 81.8519 59.3625 81.6852C58.052 80.7839 56.7595 79.8619 55.4507 78.9513C55.1771 78.7595 54.8574 78.6409 54.5573 78.4923C54.0726 78.5793 53.5108 78.1978 52.9611 78.7715C54.2401 79.7439 55.4528 80.6567 56.6638 81.5787C56.7286 81.5087 56.7935 81.4387 56.8583 81.3687C56.6695 81.1583 56.5041 80.9232 56.2831 80.7598C55.7525 80.3646 55.1881 80.0258 54.6575 79.6306C54.1005 79.2212 54.1009 79.0249 54.5829 78.4824C54.4557 78.9964 54.8909 79.1401 55.1852 79.35C56.4563 80.2299 57.7453 81.0891 59.0218 81.9652C59.2404 82.1139 59.623 82.368 59.5905 82.4725C59.376 83.1866 59.9783 83.2783 60.3377 83.4996C61.0605 83.9478 61.8202 84.321 62.557 84.7429C62.98 84.985 63.3818 85.2665 63.7922 85.5255C63.85 85.4687 63.9077 85.4118 63.96 85.3587C63.1913 83.6525 62.2824 82.0365 60.9436 80.6896C60.8503 80.5918 60.5423 80.71 60.3335 80.7259C60.338 80.6165 60.3965 80.4448 60.3378 80.3962C59.7027 79.8293 59.0332 79.2948 58.1201 79.1436C58.8579 79.671 59.6012 80.1946 60.3351 80.7166C60.3623 80.8363 60.3841 80.9599 60.4113 81.0796C60.1627 80.9927 59.8892 80.9398 59.6673 80.8097C58.8717 80.3392 58.0903 79.8424 57.3034 79.3494C57.0284 79.028 56.8403 78.5638 56.0454 78.7543C56.5588 79.0554 56.8974 79.2587 57.2305 79.4659ZM99.2 48.1826C98.9568 48.3696 98.6588 48.5135 98.489 48.747C97.7691 49.7505 97.0477 50.7634 96.4012 51.8133C95.1774 53.7913 93.8175 55.6687 92.2746 57.4134C92.0426 57.6742 91.8523 57.9712 91.6411 58.2501C91.8916 58.2702 92.0023 58.1844 92.096 58.0859C94.1494 55.9666 96.0421 53.7233 97.6036 51.2061C97.776 50.9299 97.8955 50.5439 98.4519 50.6514C98.4095 50.8691 98.4344 51.1129 98.3256 51.271C97.253 52.7344 96.2375 54.2558 95.0515 55.6274C92.7785 58.2684 90.4391 60.8497 88.0712 63.4022C86.6468 64.9329 85.1159 66.3588 83.6498 67.8535C83.2259 68.2817 82.8629 68.7734 82.4676 69.2306C82.5323 69.2995 82.6064 69.37 82.6711 69.4389C84.262 68.1098 85.6293 66.521 87.3157 65.3046C87.1115 65.7092 86.8519 66.0467 86.5599 66.3496C85.3177 67.63 84.0563 68.883 82.818 70.1688C82.0286 70.9924 81.1334 71.7352 80.757 72.9141C81.2225 72.6608 81.6743 72.3764 82.0272 71.9979C83.8095 70.0608 85.6126 68.1417 87.306 66.1362C88.5579 64.6612 89.6639 63.06 90.8269 61.5167C91.0326 61.2416 91.2364 61.0332 91.5993 61.4563C90.5204 62.8181 89.4639 64.1886 88.3718 65.5432C87.1055 67.1019 85.826 68.6534 84.5311 70.183C83.9583 70.8628 83.3383 71.5104 82.72 72.1486C82.3577 72.5254 82.5109 72.7201 82.9233 72.9124C83.49 72.3513 84.0557 71.8235 84.5929 71.2667C88.1624 67.5849 91.0888 63.3827 94.2005 59.3282C96.9306 55.7619 99.1516 51.8426 101.405 47.9578C102.452 46.145 103.371 44.2666 103.951 42.2423C103.975 42.1603 104.112 42.1127 104.267 41.9961C104.354 42.2126 104.497 42.3816 104.464 42.5194C104.373 42.9344 104.226 43.3396 104.081 43.7355C102.959 46.7277 101.245 49.4095 99.6069 52.1192C98.2652 54.3351 96.8671 56.517 95.4953 58.7132L95.5165 58.6739C93.9732 60.6148 92.2901 62.4496 91.1206 64.6671C91.7935 63.9906 92.3298 63.1894 92.9841 62.5096C93.6095 61.8582 93.9621 60.9002 94.8444 60.5095C94.9277 60.5817 95.0149 60.6593 95.0928 60.7353C92.7722 63.6792 90.4517 66.6231 88.1311 69.567C88.4733 69.5554 88.6511 69.4143 88.8003 69.2442C89.8134 68.1247 90.8396 67.0123 91.8318 65.8747C94.1077 63.2726 96.2306 60.5573 97.8103 57.4638C99.5242 54.1209 101.255 50.7906 102.93 47.4265C103.739 45.7969 104.463 44.1285 105.152 42.4443C105.895 40.6162 106.553 38.7494 107.238 36.8967C107.271 36.8163 107.196 36.6977 107.172 36.5834C106.573 36.9713 106.73 38.0046 105.674 38.1826C105.946 37.3542 106.524 36.728 106.283 35.7706C105.701 36.8895 105.44 38.0361 104.478 38.7767C104.582 37.7318 105.688 36.8824 105.047 35.6583C104.33 37.3617 103.693 39.0503 102.91 40.6701C101.794 42.9641 100.568 45.205 99.4037 47.4761C99.2875 47.7047 99.2556 47.972 99.1827 48.2274L99.2 48.1826ZM66.7354 74.4106C65.8921 75.4355 64.6971 75.9722 63.9566 77.0391C64.3335 76.9379 64.6659 76.7617 64.9374 76.5222C66.4794 75.1701 68.01 73.8017 69.5537 72.4404C69.8088 72.2123 70.1643 71.7912 70.3401 71.8557C70.9379 72.0567 71.1353 71.6077 71.3798 71.3299C74.3998 67.9441 77.3612 64.5096 79.1342 60.2432C79.2074 60.0693 79.4246 59.9495 79.5744 59.8035C79.7603 60.114 79.7984 60.3649 79.7034 60.5541C78.9532 61.9546 78.3011 63.4251 77.3832 64.7146C75.9027 66.7911 74.2962 68.7927 72.6458 70.7434C71.254 72.3901 69.7108 73.9144 68.2395 75.4944C70.1301 75.1473 70.9616 73.3875 72.4298 72.4631C72.2959 72.7939 72.1335 73.0958 71.9008 73.3326C70.5175 74.7365 69.1226 76.1241 67.7277 77.5116C66.9011 78.3287 66.0537 79.1277 65.2364 79.9465C65.1084 80.0772 65.0714 80.291 64.9927 80.4687C65.0591 80.5283 65.1255 80.5879 65.1918 80.6475C65.5849 80.3144 66.0065 80.0102 66.371 79.6482C67.6128 78.4253 68.7937 77.1389 70.0717 75.9559C73.242 73.0036 75.9604 69.6988 78.0248 65.8812C78.5952 64.8274 79.0961 63.7327 79.6364 62.6592C81.7067 58.5027 83.2635 54.1839 83.7579 49.5247C84.0375 46.9111 84.2465 44.2898 84.4968 41.6232C84.868 41.4443 85.1037 41.6055 85.0846 42.0763C85.0344 43.1977 85.0044 44.3131 84.8743 45.4253C84.6061 47.6961 84.3472 49.9685 83.962 52.2235C83.0751 57.3787 80.7429 61.9968 78.318 66.5411C76.8568 69.2819 75.0005 71.7855 72.83 74.0278C71.9954 74.8914 71.1168 75.7041 70.2822 76.5677C69.9847 76.8745 69.7482 77.2448 69.4456 77.6369C70.4151 77.6831 70.9247 77.2029 71.3826 76.6609C72.2767 75.5923 73.1461 74.5002 74.0193 73.4135C74.2686 73.1078 74.4747 72.7753 74.7424 72.3914C74.8894 72.7046 74.9753 72.873 75.0558 73.0452C75.8708 72.3506 76.0233 71.2472 76.8953 70.6105C76.9796 70.7882 77.0944 70.9281 77.0607 70.9845C75.2412 74.3279 73.2086 77.5188 70.4968 80.231C70.5538 80.2889 70.6016 80.3452 70.6587 80.4032C71.2202 79.9274 71.7817 79.4515 72.3612 78.9549C72.4422 79.1512 72.488 79.2742 72.6165 79.5841C74.1378 77.4382 75.6718 75.4957 76.9647 73.3957C78.3641 71.123 79.5997 68.7448 80.7811 66.3474C82.33 63.2102 83.4098 59.9041 84.2388 56.4964C85.2921 52.18 85.6414 47.7778 86.076 43.3812C86.203 42.1487 86.2593 40.9086 86.3343 39.6718C86.3798 38.9375 86.4494 38.2026 86.4376 37.4678C86.3677 34.5196 86.4902 31.567 85.995 28.6398C85.8788 27.9536 85.9228 27.2286 86.2836 26.4444C86.3823 26.6773 86.4516 26.7757 86.4579 26.8774C86.6303 29.4269 86.8175 31.9743 86.9418 34.5249C87.0107 35.9547 87.0541 37.3943 86.9601 38.8242C86.7625 41.8784 86.4516 44.9224 86.2168 47.9701C85.8997 52.0475 85.1548 56.0495 83.948 59.951C82.9889 63.058 81.6739 66.0065 80.1744 68.913C78.726 71.7183 77.1015 74.3777 75.3231 76.9573C75.1431 77.2225 75.014 77.5255 74.8587 77.8142C76.6205 76.2997 77.9437 74.4398 79.2724 72.576C79.4064 72.7433 79.4927 72.8543 79.6151 73.0052C79.7827 72.7569 79.9438 72.5458 80.084 72.3167C82.0022 69.0672 83.4856 65.6167 84.6338 62.0258C84.8631 61.3095 85.3096 60.6122 85.0174 59.7801C84.9716 59.6571 85.1661 59.4471 85.2393 59.2732C85.4541 58.7794 85.7471 58.3042 85.8558 57.7869C86.2222 56.0842 86.5103 54.3629 86.8636 52.653C87.5794 49.235 88.0315 45.7897 88.1325 42.2969C88.1554 41.3335 88.1115 40.3679 88.1344 39.4045C88.2101 36.5011 88.3913 33.5972 88.356 30.6982C88.3262 27.7955 88.1 24.8916 87.9445 21.9955C87.8411 20.0998 87.7928 18.19 87.573 16.3026C87.165 12.6771 86.6537 9.06693 86.1867 5.45019C86.0457 4.38129 85.8845 3.31842 85.7215 2.18338C84.9373 2.14586 84.2663 2.11871 83.5154 2.08228C83.7504 3.77118 83.9031 5.35458 84.2048 6.90677C84.8842 10.4316 84.9519 14.002 85.1935 17.5646C85.205 17.7199 85.006 17.9004 84.7701 18.2947C84.6513 17.7901 84.545 17.5462 84.5403 17.2964C84.4337 12.3159 83.7549 7.40227 82.8324 2.51277C82.7917 2.30446 82.574 2.12245 82.4394 1.93112C82.374 2.61405 82.5675 3.21325 82.5592 3.81525C82.5503 4.39318 83.085 5.01417 82.5093 5.65513C81.6718 2.10246 81.6718 2.10246 80.746 1.74786C80.8397 2.28641 80.8895 2.77411 81.0038 3.24922C81.2619 4.33394 81.6659 5.40604 81.7966 6.50665C82.1724 9.5422 82.5079 12.5898 82.7323 15.6418C82.8592 17.3739 82.709 19.1291 82.7047 20.8716C82.699 23.6197 82.8158 26.3797 82.7062 29.1191C82.4916 34.3495 81.9815 39.5423 80.8272 44.6648C80.1455 47.6913 79.529 50.7293 78.8978 53.7695C78.1196 57.4927 76.6751 60.9404 74.6632 64.1494C74.1924 64.9046 73.5823 65.5779 73.1378 66.3473C72.0496 68.2055 70.6095 69.7719 69.1577 71.3218C68.1293 72.4194 67.0098 73.434 65.9358 74.4901C65.9014 74.5224 65.9072 74.6 65.8683 74.7416C66.2019 74.6136 66.4695 74.5074 66.7354 74.4106ZM62.7866 79.8695C62.6379 78.7897 62.6634 77.7836 62.3421 76.8985C61.8734 75.6186 61.696 74.2895 61.3601 72.9899C61.1849 72.3125 61.0005 71.6335 60.8953 70.9397C60.4852 68.2956 60.0807 65.6477 59.7149 62.9971C59.1365 58.8052 58.5636 54.6094 58.7893 50.3675C58.9924 46.5336 59.2847 42.7105 59.5731 38.8819C59.6928 37.3034 59.8289 35.7133 60.1083 34.1533C60.516 31.9071 60.9811 29.6614 61.5639 27.4556C62.547 23.711 63.6401 19.9954 64.6922 16.2678C64.7937 15.9026 64.927 15.5477 65.0622 15.1261C64.2136 14.8234 63.4286 14.5415 62.6156 14.2547C60.3253 18.4922 59.4576 23.0377 58.4558 27.5548C58.8489 23.6202 59.8307 19.8275 61.1371 16.1256C60.9694 16.0146 60.8489 15.9359 60.7376 15.8588C60.8925 15.2683 61.0457 14.687 61.199 14.1058C61.1223 14.0779 61.0457 14.0501 60.969 14.0222C60.6717 14.6882 60.3706 15.3488 59.9892 16.1964C59.6766 15.15 60.4659 14.4652 60.1404 13.632C59.4743 15.6268 58.7989 17.62 58.1328 19.6148C58.2026 18.4632 58.4946 17.3844 58.7626 16.3061C59.0219 15.2502 59.5904 14.2631 59.5004 13.0931C59.1744 13.3709 58.918 13.6898 58.7739 14.0523C58.3144 15.2406 57.8811 16.443 57.4704 17.6542C56.2098 21.3403 55.6158 25.163 55.0945 29.008C54.9313 30.2005 54.8798 31.4127 54.6066 32.5763C54.3271 33.7771 54.6784 34.9596 54.429 36.1801C54.1275 37.674 54.2506 39.2617 54.2079 40.8107C54.1518 42.9082 54.0771 45.0023 54.0893 47.0926C54.0958 48.3294 53.7838 49.6346 54.6227 50.7689C54.7243 50.9017 54.6918 51.1451 54.7023 51.3337C54.7928 52.8056 54.8925 54.2791 54.9496 55.7499C55.0064 57.1392 54.9747 58.5417 55.0555 59.9304C55.1256 61.0491 55.288 62.1601 55.4357 63.2733C55.6272 64.715 55.5608 66.2072 56.3229 67.7303C56.2951 66.8106 56.2963 66.0829 56.2457 65.3508C56.1946 64.6761 56.5458 64.0866 56.4788 63.3659C56.1325 60.0482 55.8748 56.7174 55.6745 53.3871C55.5564 51.4937 55.5989 49.5854 55.5917 47.6876C55.5838 44.6306 55.5851 41.5753 55.6051 38.5232C55.6071 38.3176 55.7704 38.1213 55.8594 37.9119C55.9469 37.9321 56.0345 37.9523 56.1236 37.9632C56.1404 38.5313 56.1719 39.0972 56.1646 39.6658C56.1376 42.731 55.9903 45.799 56.0797 48.8559C56.1948 52.6789 56.4859 56.5089 56.7344 60.3362C56.9584 63.8623 57.3873 67.3669 58.0615 70.8382C58.1617 71.3395 58.3668 71.8163 58.5221 72.3034C58.6068 72.2848 58.6969 72.2623 58.7778 72.2383C58.7738 71.8736 58.6682 71.2372 58.7802 71.1994C59.5927 70.9067 59.1042 70.3513 59.0546 69.945C58.9735 69.2507 58.73 68.5804 58.6139 67.8942C58.3055 66.02 58.0212 64.1452 57.7478 62.2628C57.7209 62.0856 57.8323 61.8849 57.8754 61.6914C58.352 63.2025 58.5694 64.7159 58.8475 66.2112C59.1422 67.7765 59.4314 69.3457 59.8349 70.8918C60.2278 72.3882 60.7901 73.8474 61.2234 75.3318C61.6682 76.8325 61.757 78.4526 62.7866 79.8695ZM95.5005 35.8261C95.8306 35.9129 96.032 35.9675 96.2837 36.0358C97.0002 34.0547 97.7294 32.1381 98.382 30.1936C99.078 28.137 99.7236 26.0668 100.351 23.9932C101.027 21.7704 101.659 19.5302 102.317 17.3041C102.464 16.8174 102.553 16.3876 101.821 16.2397C101.567 17.0714 101.357 17.8965 101.058 18.6867C100.768 19.4451 100.385 20.1631 100.029 20.8953C99.679 21.6144 99.3031 22.3193 98.9349 23.0351C98.8599 22.998 98.7887 22.9663 98.7082 22.933C99.5915 20.6795 100.888 18.561 101.067 16.083C100.557 17.1761 100.272 18.3807 99.4734 19.423C99.141 18.9622 99.9194 18.2851 99.0811 18.0896C99.0718 18.0879 99.1107 17.8074 99.1496 17.6658C99.2556 17.3301 99.4158 17.0135 99.4884 16.6766C99.5955 16.1686 99.8205 15.6431 99.5011 14.8302C99.1018 16.1967 98.805 17.3034 98.4539 18.391C97.0346 22.8011 94.7479 26.8237 92.8078 31.0032C91.8456 33.0752 90.7279 35.0767 89.7882 37.1574C89.3785 38.0575 89.1792 39.0712 88.9995 40.0549C88.8648 40.7783 88.9254 41.5361 88.9023 42.2792C89.513 41.4911 89.9127 40.7042 90.3139 39.908C90.7152 39.1118 91.1335 38.3282 91.4937 37.52C91.8751 36.6724 92.1854 35.7931 92.535 34.9351C92.869 34.1127 93.1821 33.2722 93.5609 32.4673C93.9224 31.7072 93.9667 30.7858 94.6973 30.1913C94.7167 30.5779 94.6486 30.9442 94.5185 31.2805C93.6949 33.4104 92.9107 35.5616 91.9972 37.6565C91.1901 39.4972 90.2444 41.2799 89.3343 43.0784C88.7147 44.3056 88.6115 45.5949 88.7075 46.924C89.2143 45.9884 89.6375 45.038 90.0924 44.098C90.5316 43.1935 91.0195 42.312 91.4641 41.4037C91.9283 40.4653 92.3925 39.5269 92.7894 38.5623C93.1824 37.5922 93.4577 36.5823 93.8469 35.6067C94.2306 34.635 94.7003 33.6928 95.1196 32.7369C95.5232 31.8166 95.9453 30.8996 96.3095 29.9579C96.6839 28.9846 96.9701 27.967 97.3445 26.9936C97.7071 26.0613 97.8352 25.0158 98.5097 24.1911C98.6376 24.477 98.6888 24.7351 98.6284 24.9735C98.5583 25.2677 98.3837 25.5291 98.2765 25.8167C97.5199 27.8914 96.8044 29.978 96.0122 32.0368C95.5684 33.1895 94.9807 34.2882 94.5144 35.4321C93.4417 38.0881 92.5507 40.8287 91.0579 43.2814C90.0266 44.9772 89.8771 47.1156 88.3802 48.5666C88.335 48.6065 88.3491 48.7192 88.3362 48.7935C88.0684 50.2311 87.8099 51.6702 87.5421 53.1078C91.0758 47.7769 93.2415 41.822 95.5005 35.8261ZM64.8274 67.5995C66.0382 66.2514 66.8368 64.7924 67.7352 63.394C70.3982 59.2461 71.8009 54.6271 72.8499 49.8645C73.3741 47.4712 73.5269 45.0364 73.7426 42.5983C74.1661 37.85 74.0168 33.1446 73.0961 28.4661C73.0215 28.0938 73.014 27.6662 72.5943 27.2667C72.5441 27.6122 72.5081 27.7927 72.4946 27.9819C72.0991 33.0942 71.4044 38.1635 70.6484 43.2268C69.8326 48.6914 68.4126 53.9922 66.7113 59.229C66.0876 61.1451 65.518 63.0802 64.8177 64.9684C64.4959 65.8313 64.4516 66.6138 64.8274 67.5995ZM53.3028 42.8018C53.3987 41.4441 53.6038 40.2302 52.8795 39.0155C52.1843 37.8538 51.6605 36.5882 51.0712 35.3685C50.7991 34.8082 50.562 34.2396 50.2681 33.6945C49.0403 31.4285 47.7978 29.1647 46.4326 26.6685C46.8219 26.8281 47.1003 26.8531 47.2134 27.0024C47.4721 27.3353 47.6637 27.7234 47.857 28.1023C49.5439 31.4262 51.2254 34.7539 52.9216 38.0794C53.0251 38.2845 53.18 38.4698 53.3668 38.7469C53.8171 37.4182 53.3214 36.3778 52.781 35.4014C51.068 32.2837 49.4003 29.126 47.3446 26.2161C45.8237 24.0661 44.2382 21.9286 41.9128 20.523C41.8432 20.482 41.8285 20.3453 41.7205 20.1108C42.0117 20.2004 42.1939 20.2277 42.3385 20.3058C43.5109 20.9529 44.4746 21.8362 45.3437 22.8513C47.4755 25.3483 49.2397 28.0872 50.8512 30.9332C51.5966 32.2474 52.3841 33.5403 53.1553 34.8447C53.2697 35.042 53.3677 35.2509 53.5103 35.5346C54.0535 34.3611 53.4436 33.4826 53.0404 32.6549C51.2071 28.903 48.9821 25.3933 46.2584 22.2173C44.7745 20.4905 42.9491 19.1585 40.9279 18.1273C39.9463 17.624 39.0212 17.7916 38.152 18.4671C38.5473 18.9246 38.9516 19.3023 39.2336 19.7495C39.5173 20.1874 40.3098 20.2599 40.1988 21.179C39.8233 20.9118 39.5536 20.7254 39.284 20.539C38.971 20.3259 38.6581 20.1127 38.3358 19.8979C38.2751 20.1937 38.232 20.3873 38.1825 20.6181C36.6494 19.7015 35.9394 19.4568 35.3142 19.6915C35.96 20.0303 36.5417 20.3243 37.1164 20.6315C38.7296 21.4998 40.3179 22.4021 41.6352 23.7069C45.2888 27.3244 48.1936 31.4758 50.3761 36.1178C51.3826 38.2778 52.2887 40.492 53.3028 42.8018ZM76.6793 21.3528C76.5055 19.0329 76.3506 16.7978 76.1608 14.5708C76.0752 13.5692 75.9028 12.5714 75.808 11.5681C75.5653 9.09237 75.0943 6.66266 74.4647 4.26252C74.2403 3.39924 74.2053 3.40745 73.1658 3.37766C73.2639 4.99935 73.2639 4.99935 72.6308 5.63979C72.4706 5.18055 72.3111 4.74536 72.1663 4.30799C72.0276 3.89084 71.9457 3.45017 71.3857 3.27973C72.8241 9.48133 73.4997 15.6875 73.1424 22.1859C74.3919 21.8887 75.4299 21.65 76.6793 21.3528ZM62.4405 68.2951C63.1116 67.9056 63.0586 67.4365 62.9854 66.9734C62.7004 65.2134 62.4891 63.4425 62.1047 61.7033C61.5474 59.1626 60.8797 56.6504 60.2378 54.1284C60.0997 53.5964 59.8957 53.0863 59.7227 52.5626C59.7803 58.5737 60.7403 64.466 61.7577 70.3588C62.3685 69.4318 61.7703 68.5123 61.7425 67.5927C61.7106 66.5861 61.5622 65.5877 61.4526 64.5866C61.3459 63.6243 61.243 62.6675 61.103 61.7041C60.9546 60.7058 60.7713 59.7156 60.5972 58.7271C60.4366 57.8272 60.2596 56.9387 60.0935 56.0426C61.6381 59.9401 61.9888 64.0632 62.4405 68.2951ZM87.1227 56.2523C88.7994 53.6788 90.3812 51.1556 91.5143 48.4001C92.6387 45.667 93.86 42.9558 94.5804 40.0654C94.2729 40.4854 94.0197 40.9245 93.871 41.3964C92.7921 44.808 91.0949 47.9431 89.51 51.1219C88.9752 52.1915 88.441 53.2852 87.7385 54.2439C87.2934 54.8504 87.0131 55.3901 87.1227 56.2523ZM59.8559 50.019C59.769 50.0228 59.6805 50.036 59.5936 50.0398C59.6018 50.3526 59.4829 50.7627 59.6362 50.9573C60.3052 51.827 60.4144 52.8855 60.6863 53.8625C61.7322 57.5956 62.7431 61.3368 63.2645 65.193C63.2853 65.3499 63.3263 65.5008 63.3728 65.6479C63.4192 65.795 63.4929 65.9229 63.5541 66.0678C63.2612 60.475 61.6331 55.2314 59.8559 50.019ZM54.183 63.091C54.453 59.4795 54.6586 55.8806 54.0665 52.2945C53.9462 55.8989 53.5816 59.5033 54.183 63.091ZM49.3423 77.1142C49.2697 75.8993 49.2144 74.6395 49.1188 73.3918C49.0977 73.1535 48.9785 72.8451 48.7954 72.7123C48.4123 72.4341 47.9649 72.25 47.4637 71.9893C47.4963 73.6569 48.1143 75.2648 49.3423 77.1142ZM59.7864 47.0134C59.7523 47.266 59.6319 47.5465 59.7027 47.7745C60.8092 51.3506 61.9361 54.9207 63.0574 58.4946C62.3307 54.5783 61.4183 50.7107 59.7864 47.0134ZM74.1358 74.6792C74.0733 74.6251 74.0162 74.5672 73.9575 74.5185C72.5523 76.0767 71.1526 77.6309 69.7435 79.1836C71.8788 78.2809 72.9883 76.4647 74.1358 74.6792ZM53.9653 81.1945C52.0945 79.4044 50.5959 77.402 49.8196 74.9089C50.0085 77.8062 51.7024 79.7041 53.9653 81.1945ZM68.6925 68.692C67.2001 70.3113 65.8552 71.7699 64.3736 73.3817C65.7052 72.8307 68.1591 70.1689 68.6925 68.692ZM52.4302 76.1062C52.9647 75.094 52.3508 74.3489 52.2155 73.4965C51.8909 73.5447 51.6493 73.5836 51.3744 73.6214C51.4244 74.6072 51.5776 75.4388 52.4302 76.1062ZM65.645 82.1832C66.8002 81.6826 67.6053 80.8234 68.2354 79.7849C67.2915 80.5047 66.2882 81.1518 65.645 82.1832ZM54.5194 70.4827C54.4456 70.4936 54.368 70.4991 54.2888 70.5139C54.2118 71.9563 54.3966 73.3538 54.9612 74.6888C55.0442 74.6795 55.1289 74.6609 55.212 74.6516C54.9791 73.2552 54.7539 71.8698 54.5194 70.4827ZM67.779 84.9728C67.4609 84.706 67.1428 84.4393 66.6542 84.0228C66.813 85.3487 65.7877 84.3779 65.3933 84.8017C65.7871 84.9908 66.1267 85.1608 66.4904 85.3302C66.6566 84.3968 67.4038 85.424 67.779 84.9728ZM68.8438 82.7225C70.0273 82.3083 70.8862 81.5257 71.4438 80.4074C70.5772 81.1791 69.7105 81.9508 68.8438 82.7225ZM84.3176 73.5507C84.2545 73.4725 84.1859 73.3981 84.1134 73.3183C83.4049 73.979 82.6948 74.649 81.9863 75.3097C82.0511 75.3786 82.112 75.442 82.1713 75.5147C82.8929 74.8611 83.6053 74.2059 84.3176 73.5507ZM64.4542 79.7034C65.1142 79.1012 65.5808 78.6757 66.0473 78.2502C65.0853 78.4927 64.7741 78.7683 64.4542 79.7034ZM18.5535 141.473C18.9589 141.401 19.2961 141.335 19.8452 141.236C19.2324 140.955 18.837 140.776 18.331 140.543C18.4241 140.918 18.4725 141.138 18.5535 141.473ZM18.9448 142.064C18.9232 142.438 18.9061 142.703 18.887 143.035C19.3159 142.938 19.636 142.861 20.1457 142.74C19.6779 142.48 19.3678 142.306 18.9448 142.064ZM67.6668 71.6579C67.5857 71.6005 67.51 71.5393 67.4289 71.4819C66.9909 71.9364 66.549 72.3854 66.111 72.8399C66.1773 72.8995 66.2421 72.9684 66.3085 73.0279C66.7612 72.5713 67.214 72.1146 67.6668 71.6579ZM50.9305 75.8278C51.0168 75.7998 51.0976 75.7758 51.1839 75.7479C50.9931 75.106 50.8006 74.4734 50.6097 73.8316C50.5289 73.8557 50.448 73.8798 50.3672 73.9038C50.5542 74.5402 50.7396 75.1859 50.9305 75.8278ZM57.0327 68.5306C56.9768 68.5207 56.9265 68.5071 56.8707 68.4973C56.9872 68.9871 57.1021 69.4863 57.2187 69.9762C57.2684 69.9658 57.3181 69.9554 57.3678 69.945C57.2574 69.4753 57.1431 69.0002 57.0327 68.5306ZM37.4571 19.5756C37.3978 18.727 37.3978 18.727 36.6526 19.046C36.9053 19.2198 37.1124 19.352 37.4571 19.5756ZM77.1449 77.8671C77.9375 77.6619 77.9375 77.6619 77.8694 77.1135C77.5954 77.3957 77.3721 77.6342 77.1449 77.8671ZM60.5582 78.8449C60.6111 78.8159 60.6695 78.7831 60.7225 78.7541C60.6219 78.4491 60.5213 78.144 60.4207 77.8389C60.3896 77.8526 60.3639 77.8624 60.329 77.8707C60.4077 78.191 60.4811 78.5152 60.5582 78.8449ZM63.99 67.5095C63.7578 68.187 63.7578 68.187 64.1348 68.7227C64.0824 68.2777 64.0447 67.9693 63.99 67.5095ZM52.9186 77.0782C52.8384 77.1264 52.762 77.18 52.6873 77.2243C52.8158 77.3954 52.935 77.5648 53.0636 77.7359C53.1181 77.6976 53.1711 77.6687 53.2256 77.6304C53.1227 77.4494 53.0253 77.2646 52.9186 77.0782ZM88.9105 67.3048C88.9653 67.3479 89.024 67.3966 89.0788 67.4398C89.1709 67.3506 89.2948 67.2719 89.3513 67.1669C89.4203 67.0449 89.4383 66.8852 89.4772 66.7436C89.4416 66.7278 89.4006 66.7158 89.365 66.6999C89.2148 66.9033 89.0646 67.1068 88.9105 67.3048Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M40.7341 69.3725C41.8461 69.2044 42.8496 69.5197 43.7888 70.1018L43.8055 70.0666C42.7882 69.8252 41.7709 69.5838 40.7537 69.3425L40.7341 69.3725Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M99.1731 48.2212C99.371 48.0742 99.5781 47.9287 99.8305 47.7434C100.111 48.4199 99.7621 48.6648 99.2093 49.0365C99.2063 48.6387 99.2038 48.4037 99.2014 48.1687L99.1731 48.2212Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M2.98724 109.147C6.01464 110.926 8.95031 112.736 11.9653 114.392C14.9841 116.054 18.0844 117.577 21.1581 119.143C24.2186 120.702 27.3767 122.029 30.599 123.401C30.4094 123.444 30.207 123.561 30.0466 123.519C29.4944 123.359 28.9519 123.144 28.4061 122.947C24.4193 121.508 20.637 119.606 16.8781 117.68C12.8678 115.628 8.87331 113.541 5.09285 111.075C4.50707 110.694 3.88759 110.369 3.26105 110.058C2.8859 109.872 2.66982 109.681 2.98724 109.147Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.0451 108.644C74.7097 109.336 74.2379 109.21 73.7989 109.2C70.9916 109.113 68.2441 108.624 65.5137 108.009C59.4028 106.631 53.5103 104.545 47.6211 102.44C47.1426 102.27 46.6609 102.118 46.1966 101.921C46.0093 101.84 45.8622 101.666 45.7632 101.351C46.0346 101.39 46.3178 101.387 46.5701 101.479C49.242 102.405 51.9075 103.367 54.5826 104.274C60.4764 106.27 66.4435 107.953 72.6664 108.517C73.4604 108.58 74.2517 108.604 75.0451 108.644Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M77.5956 111.816C77.5745 112.354 77.3794 112.54 76.9365 112.524C76.2399 112.507 75.549 112.567 74.8486 112.544C72.5525 112.466 70.3136 112.028 68.088 111.459C66.2854 110.993 64.459 110.61 62.6634 110.131C60.5286 109.563 58.4034 108.94 56.282 108.322C55.3882 108.059 54.5016 107.783 53.6197 107.48C53.4122 107.405 53.2529 107.19 53.1642 106.844C53.3627 106.86 53.5824 106.836 53.7675 106.902C58.467 108.544 63.2627 109.824 68.1091 110.922C70.497 111.467 72.8982 111.88 75.3456 111.942C76.0625 111.954 76.7822 111.865 77.5956 111.816Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M56.4261 101.624C57.3625 101.889 58.2399 102.163 59.1254 102.391C61.4889 102.994 63.8454 103.61 66.2201 104.148C68.2951 104.619 70.3835 105.039 72.4815 105.404C73.4488 105.574 74.4498 105.549 75.5014 105.619C75.4495 106.252 74.9399 106.234 74.5784 106.218C73.6531 106.166 72.7115 106.124 71.8135 105.913C67.4662 104.923 63.1284 103.876 58.7858 102.858C58.1823 102.718 57.5723 102.616 56.9774 102.453C56.6753 102.371 56.2285 102.35 56.4261 101.624Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M56.8318 95.1576C57.3898 95.2559 57.732 95.2443 58.002 95.3732C60.8767 96.7606 63.9165 97.6647 66.973 98.4998C69.8227 99.2841 72.7364 99.6152 75.6858 99.6844C76.0674 99.6941 76.5393 99.5426 76.8078 100.04C73.9756 101.122 59.4305 97.6697 56.8318 95.1576Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.4071 102.648C74.8081 103.035 74.1218 102.986 73.4492 102.968C71.1855 102.924 68.9698 102.52 66.8144 101.877C63.6198 100.926 60.4472 99.9031 57.2715 98.8985C57.0268 98.8171 56.8303 98.5957 56.6078 98.4416C56.6533 98.3443 56.6951 98.2415 56.7407 98.1441C57.0854 98.2288 57.4388 98.291 57.7733 98.4074C59.791 99.0979 61.7741 99.8781 63.8172 100.477C66.713 101.327 69.6139 102.231 72.6663 102.342C73.2038 102.365 73.7433 102.321 74.2857 102.316C74.6503 102.313 75.0172 102.325 75.3858 102.328C75.3905 102.439 75.4007 102.546 75.4071 102.648Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M59.541 111.888C59.8945 111.951 60.2543 111.976 60.5959 112.079C64.1892 113.19 67.8288 114.09 71.5706 114.509C73.1082 114.68 74.6599 114.685 76.2026 114.769C76.6012 114.792 77.0005 114.838 77.6038 114.896C77.1016 115.445 76.694 115.364 76.2812 115.368C71.5831 115.407 67.0464 114.402 62.5435 113.202C61.6821 112.974 60.8165 112.798 59.9551 112.569C59.7631 112.516 59.6066 112.34 59.4258 112.222C59.4691 112.11 59.5032 111.997 59.541 111.888Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M55.8643 83.4744C60.6029 87.7425 66.2974 89.6982 72.4548 91.1656C72.0821 91.2149 71.8861 91.2953 71.711 91.2549C70.1669 90.9016 68.5865 90.6473 67.0884 90.1392C64.2639 89.1821 61.4838 88.0796 58.9322 86.5145C58.0139 85.9505 57.1858 85.2252 56.3388 84.5541C56.0531 84.3218 55.7848 84.0447 55.8643 83.4744Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.8534 114.928C64.9761 115.455 67.0728 115.911 69.1362 116.504C71.194 117.101 73.3925 116.775 75.4095 117.58C71.3364 117.801 67.4496 116.863 63.6277 115.577C63.3326 115.482 62.8175 115.468 62.8534 114.928Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M9.08265 82.1373C13.1074 84.7424 17.1385 87.3103 21.4126 89.4708C19.8779 88.9803 18.417 88.3399 17.031 87.5164C15.6279 86.6803 14.2037 85.8836 12.8202 85.0174C11.4839 84.1835 10.0702 83.4365 9.08265 82.1373Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M74.6983 120.496C74.5527 120.59 74.4667 120.699 74.3704 120.702C71.0103 120.929 67.7284 120.538 64.5505 119.38C64.2532 119.27 63.8026 119.243 64.0322 118.608C64.3529 118.693 64.6822 118.756 64.9943 118.864C67.5431 119.753 70.1366 120.301 72.8588 120.105C73.4409 120.064 74.1575 119.855 74.6983 120.496Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M51.8379 82.8495C50.9708 82.6824 50.5029 81.9249 49.9648 81.38C47.7027 79.0566 45.8109 76.4489 44.6751 73.3758C44.4201 72.6892 44.288 71.9572 44.1341 71.2406C44.1069 71.1209 44.2157 70.9628 44.32 70.6364C44.4386 70.9207 44.5062 71.0284 44.5334 71.1481C45.5163 75.5207 48.0517 78.9505 51.1757 82.0242C51.4209 82.2685 51.6481 82.5336 51.8879 82.7817L51.8379 82.8495Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.4284 122.078C64.9762 121.432 65.3994 121.756 65.7737 121.836C67.0568 122.119 68.3265 122.453 69.6026 122.75C70.7873 123.021 71.9701 123.08 73.1532 122.724C73.4967 122.621 73.8707 122.62 74.2325 122.578C74.2585 122.65 74.2882 122.727 74.3196 122.795C74.1769 122.928 74.06 123.132 73.8929 123.184C72.817 123.531 71.7039 123.733 70.5818 123.516C69.2178 123.257 67.8705 122.928 66.5162 122.613C65.8606 122.469 65.217 122.284 64.4284 122.078Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.8238 94.3971C63.0743 94.4172 63.3508 94.3701 63.5682 94.4707C66.6835 95.8525 70.0471 96.1862 73.3327 96.8606C73.3792 96.8687 73.3881 97.0667 73.4531 97.3559C71.5663 97.2104 69.7948 96.7309 68.0046 96.3869C66.1866 96.038 64.4902 95.3179 62.7528 94.7246C62.7814 94.6147 62.8007 94.5031 62.8238 94.3971Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M11.9299 79.42C12.7381 79.3181 13.1141 79.7483 13.5149 80.0631C15.1348 81.3349 16.7353 82.6367 18.612 83.5323C19.5194 83.965 20.4268 84.3978 21.3435 84.8322C19.8494 85.3257 13.7924 81.2565 11.9299 79.42Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M65.6553 124.402C66.6892 124.713 67.7177 125.028 68.7532 125.33C69.867 125.651 70.974 126.066 72.1624 125.844C72.6727 125.748 73.1802 125.612 73.7543 125.478C73.936 125.841 73.6749 126.049 73.3566 126.198C72.5248 126.603 71.6174 126.668 70.7451 126.447C69.1346 126.034 67.5478 125.54 65.9556 125.048C65.7782 124.993 65.6561 124.785 65.508 124.644C65.5597 124.567 65.6075 124.484 65.6553 124.402Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M18.8045 132.51C19.3907 132.695 19.9926 132.844 20.5615 133.074C22.036 133.664 23.5319 134.157 25.1149 134.369C25.7615 134.454 26.3599 134.679 26.9475 135.132C26.7724 135.23 26.6678 135.337 26.595 135.314C24.2074 134.712 21.7621 134.305 19.4998 133.255C19.1455 133.088 18.7488 132.999 18.8202 132.475C18.8257 132.471 18.8045 132.51 18.8045 132.51Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M20.6694 72.3132C23.3487 73.6662 25.5325 75.7508 28.4054 76.6493C28.3761 76.7352 28.3415 76.8248 28.3084 76.9052C27.7786 76.7545 27.1831 76.7071 26.7224 76.4344C24.7572 75.2742 22.8219 74.0523 20.8905 72.8358C20.7552 72.7593 20.7389 72.4931 20.6694 72.3132Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M39.2753 139.738C38.0229 139.637 36.8236 139.23 35.6342 138.848C34.4262 138.463 33.2397 137.981 32.032 137.538C32.0621 136.921 32.4209 137.118 32.7384 137.222C34.1654 137.699 35.5876 138.203 37.0249 138.648C37.6483 138.839 38.3128 138.903 38.9449 139.072C39.1277 139.123 39.263 139.339 39.4204 139.481C39.3725 139.564 39.3247 139.646 39.2753 139.738Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.6428 74.9148C28.8692 74.5509 26.9817 72.6095 24.797 71.1952C24.6463 71.0968 24.6044 70.8404 24.5866 70.5835C27.0192 71.9217 29.0109 73.9533 31.6428 74.9148Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M72.3454 95.202C69.7079 94.7423 67.3 94.4237 64.998 93.2712C65.2219 93.0569 65.2932 92.9497 65.3249 92.9601C67.5033 93.7747 69.762 94.2634 72.0374 94.6832C72.1025 94.6947 72.1457 94.8603 72.3454 95.202Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M65.7876 127.068C68.0393 127.431 70.1942 128.409 72.6026 127.756C72.4954 127.905 72.4039 128.157 72.2695 128.186C71.6308 128.332 70.9434 128.594 70.3366 128.473C68.9037 128.196 67.5084 127.73 66.098 127.324C65.9787 127.293 65.8918 127.158 65.7876 127.068Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.4197 73.3249C33.2621 73.5904 32.384 72.9329 31.5062 72.3569C28.9893 70.7022 29.0018 70.6852 28.7703 69.8352C30.7704 70.9871 32.3145 72.6142 34.4197 73.3249Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.7248 68.961C33.7372 69.8757 35.1267 71.5379 37.4 72.0244C36.5365 72.4183 35.9963 72.0789 35.4377 71.8177C33.417 70.8681 31.9277 69.7822 31.7248 68.961Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.0331 129.764C69.7183 130.744 67.2411 130.466 65.9738 129.232C67.6089 129.947 69.3265 129.713 71.0331 129.764Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M66.4733 91.6967C68.1865 92.0702 69.7897 92.4147 71.475 92.7833C71.3656 92.9173 71.2587 93.1475 71.1586 93.1443C69.5668 93.0939 68.04 92.6957 66.5742 92.0832C66.5107 92.0624 66.5172 91.8864 66.4733 91.6967Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M64.7071 131.011C66.0692 131.198 67.3367 131.378 68.6282 131.558C68.0316 132.32 65.8857 132.038 64.7071 131.011Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M29.633 103.957C28.3361 103.92 27.4764 102.907 26.3297 102.528C26.253 102.5 26.2435 102.278 26.1644 102.015C27.6039 102.335 28.5307 103.293 29.633 103.957Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M20.8783 140.543C18.9778 139.73 18.3231 139.332 17.8644 138.715C18.9629 138.736 20.6448 139.76 20.8783 140.543Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M50.2467 132.443C50.968 131.986 51.6685 132.507 52.3796 132.58C52.4261 132.588 52.5074 132.865 52.4695 132.974C52.4262 133.086 52.2375 133.235 52.139 133.222C51.4896 133.098 50.8466 132.937 50.2059 132.791C50.2175 132.668 50.2368 132.557 50.2467 132.443Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M51.8839 82.7757C53.108 83.7047 54.332 84.6338 55.5768 85.5809C54.5488 85.3472 52.8233 84.076 51.8393 82.8396L51.8839 82.7757Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M65.6603 135.054C64.7669 135.51 63.9895 135.239 63.2578 134.732C64.0863 134.624 64.8968 134.675 65.6603 135.054Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M66.7826 133.637C65.6897 133.972 64.7889 133.722 64.101 132.906C65.1397 133.19 65.9639 133.412 66.7826 133.637Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.1973 145.725C26.0985 145.599 25.635 145.426 25.1646 144.989C25.9972 144.772 26.6914 144.995 27.1973 145.725Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M62.0534 135.937C62.7355 135.981 63.4321 135.941 64.0958 136.34C63.3173 136.854 62.9493 136.794 62.0534 135.937Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M30.4188 143.006C29.6288 142.728 28.9656 142.492 28.3025 142.256C29.0062 142.064 29.6695 142.022 30.2626 142.414C30.3716 142.476 30.3522 142.727 30.4188 143.006Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M41.9194 132.793C41.7683 132.89 41.6176 133.07 41.4625 133.081C40.9008 133.116 40.3861 132.963 39.9824 132.389C40.5219 132.427 41.0614 132.464 41.6009 132.502C41.7089 132.598 41.8168 132.693 41.9194 132.793Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M40.1953 143.802C39.3492 144.069 38.7202 143.441 37.9879 143.245C38.7925 143.162 39.5313 143.321 40.1757 143.832C40.1811 143.828 40.1953 143.802 40.1953 143.802Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M61.4223 123.527C61.8665 123.673 62.3069 123.812 62.9284 124.013C62.1473 124.431 61.7526 124.055 61.3196 123.844C61.3558 123.745 61.3883 123.641 61.4223 123.527Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M32.2979 85.6319C31.9429 85.3587 31.7333 85.2692 31.7061 85.1495C31.675 85.0244 31.8335 84.856 31.9018 84.7101C32.0819 84.804 32.3204 84.8652 32.4187 85.0165C32.4879 85.1149 32.3625 85.3417 32.2979 85.6319Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M61.6455 132.671C61.588 132.312 61.7134 132.085 62.0932 132.104C62.1785 132.109 62.3377 132.324 62.3156 132.397C62.2244 132.73 62.0003 132.863 61.6455 132.671Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M32.4708 142.423C32.4143 141.892 32.6413 141.659 33.1725 141.662C33.1568 142.334 33.1568 142.334 32.4708 142.423Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M45.7051 79.4369C45.468 79.285 45.2497 79.2179 45.2094 79.0911C45.1729 78.9698 45.3143 78.7889 45.3788 78.6375C45.5397 78.7042 45.7698 78.7303 45.8358 78.8472C45.8925 78.9625 45.7703 79.1708 45.7051 79.4369Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.6535 140.408C27.4956 140.241 27.311 140.118 27.3277 140.049C27.3665 139.907 27.4884 139.757 27.6176 139.674C27.6612 139.643 27.9362 139.826 27.9211 139.885C27.9031 140.045 27.7828 140.187 27.6535 140.408Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M42.3923 73.8836C42.2152 74.0487 42.1104 74.2121 41.9744 74.2504C41.8936 74.2745 41.7581 74.1166 41.6469 74.0396C41.747 73.904 41.824 73.7357 41.9571 73.6586C42.0209 73.622 42.1875 73.7662 42.3923 73.8836Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M22.1876 143.388C22.0413 143.597 21.9588 143.769 21.828 143.861C21.7844 143.892 21.4947 143.711 21.506 143.646C21.524 143.487 21.625 143.318 21.7443 143.21C21.7841 143.173 21.978 143.299 22.1876 143.388Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M48.029 85.5551C47.8449 85.7333 47.7416 85.8874 47.597 85.9481C47.5348 85.9754 47.3877 85.8011 47.2765 85.7241C47.375 85.5979 47.4575 85.4257 47.5851 85.3525C47.662 85.3229 47.821 85.4562 48.029 85.5551Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M40.1993 79.2687C40.0133 79.3747 39.8235 79.4753 39.6375 79.5814C39.5889 79.4196 39.5348 79.2617 39.4823 79.0945C39.6887 79.0639 39.9006 79.0294 40.1071 78.9987C40.1391 79.0905 40.1673 79.1769 40.1993 79.2687Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M25.4887 138.687C25.3053 138.889 25.2091 139.03 25.0821 139.127C25.0548 139.146 24.8292 139.011 24.8411 138.97C24.8684 138.812 24.9307 138.646 25.0291 138.52C25.0487 138.49 25.2589 138.603 25.4887 138.687Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M53.4669 89.2417C53.2719 89.4275 53.1632 89.5855 53.0186 89.6461C52.9618 89.6697 52.7157 89.4588 52.7292 89.4085C52.7681 89.267 52.8822 89.1052 53.0082 89.0412C53.0906 89.0079 53.2496 89.1412 53.4669 89.2417Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M54.5885 136.703C54.4171 136.448 54.2713 136.321 54.2736 136.197C54.2714 136.044 54.3933 135.893 54.4633 135.738C54.5838 135.816 54.7665 135.868 54.8046 135.98C54.8388 136.086 54.7355 136.24 54.5885 136.703Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M41.945 92.8803C41.8611 92.7841 41.7044 92.6656 41.7172 92.5913C41.7468 92.4481 41.861 92.2863 41.9886 92.213C42.0322 92.1824 42.2879 92.3376 42.3129 92.4425C42.3468 92.6064 42.272 92.7895 42.2377 92.9605C42.1409 92.9387 42.0457 92.9076 41.945 92.8803Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.2127 76.4008C34.0802 76.5019 33.9583 76.6528 33.8147 76.6802C33.7208 76.6971 33.4878 76.4934 33.4975 76.4376C33.5341 76.2813 33.6454 76.0807 33.7791 76.0277C33.9221 75.9763 34.1246 76.079 34.2996 76.1194C34.2688 76.2145 34.2435 76.3057 34.2127 76.4008Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M42.645 134.693C42.4859 134.837 42.381 135.001 42.2756 135.001C42.1646 135.006 42.057 134.853 41.942 134.77C42.0404 134.644 42.112 134.48 42.2434 134.412C42.298 134.373 42.4581 134.555 42.645 134.693Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M34.3718 134.655C34.4148 134.462 34.4485 134.267 34.514 134.082C34.5227 134.059 34.7108 134.107 34.8185 134.121C34.7815 134.335 34.7391 134.552 34.7022 134.766C34.5884 134.732 34.4801 134.693 34.3718 134.655Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M27.9924 137.403C28.1918 137.246 28.299 137.098 28.4044 137.097C28.5192 137.098 28.6323 137.247 28.7435 137.324C28.6537 137.428 28.5728 137.591 28.4625 137.62C28.3631 137.64 28.2266 137.516 27.9924 137.403Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M28.0336 144.469C28.1276 144.313 28.1911 144.195 28.2639 144.079C28.3768 144.146 28.4989 144.216 28.6117 144.283C28.5296 144.398 28.4683 144.531 28.3669 144.618C28.3342 144.641 28.1929 144.545 28.0336 144.469Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M24.9746 142.126C25.3122 142.721 25.3122 142.721 24.6252 142.844C24.7516 142.584 24.8482 142.386 24.9746 142.126Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M43.19 139.185C42.9866 138.977 42.8157 138.885 42.8171 138.794C42.8194 138.67 42.9303 138.527 43.0278 138.434C43.0567 138.406 43.2887 138.504 43.2861 138.547C43.296 138.711 43.2446 138.87 43.19 139.185Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M22.8913 140.623C22.6775 140.447 22.5073 140.379 22.4824 140.274C22.459 140.16 22.5646 140.02 22.6204 139.891C22.7332 139.959 22.9027 140.003 22.9572 140.104C23.0078 140.199 22.934 140.349 22.8913 140.623Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M52.463 125.956C52.697 125.849 52.9404 125.743 53.3758 125.552C53.1252 126.087 52.9638 126.355 52.5552 126.226C52.5232 126.134 52.495 126.048 52.463 125.956Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M21.8686 147.556C21.6875 147.357 21.5353 147.268 21.5328 147.171C21.5296 147.051 21.6307 146.882 21.731 146.828C21.7948 146.792 22.0406 146.921 22.048 146.989C22.0572 147.13 21.9648 147.276 21.8686 147.556Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M31.7491 139.672C31.7883 139.474 31.8237 139.269 31.8629 139.07C31.9937 139.117 32.1206 139.159 32.2568 139.202C32.182 139.385 32.1111 139.573 32.0418 139.753C31.945 139.731 31.8443 139.704 31.7491 139.672Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M58.1237 87.1149C58.4025 87.3028 58.6512 87.4711 58.9053 87.6355C58.845 87.7349 58.7754 87.8328 58.7151 87.9322C58.5101 87.7334 58.305 87.5345 58.1015 87.3264C58.0807 87.3084 58.1083 87.2319 58.1237 87.1149Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M35.7988 140.888C35.9854 140.667 36.057 140.503 36.1673 140.474C36.2535 140.446 36.3906 140.595 36.5034 140.663C36.4409 140.747 36.4036 140.88 36.3267 140.909C36.2017 140.94 36.0693 140.902 35.7988 140.888Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M82.6464 43.7296C82.8422 44.0658 82.9673 44.174 82.9743 44.2998C83.069 45.4419 82.1665 51.2693 81.6341 52.7129C81.2969 51.5041 81.7393 50.5811 81.8333 49.6494C81.9322 48.6899 82.0163 47.7325 82.171 46.7827C82.328 45.8478 82.1664 44.8424 82.6464 43.7296Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M84.6546 39.6091C84.5624 39.0613 84.417 38.7388 84.4723 38.4468C84.6227 37.6879 84.2715 36.8646 84.7023 36.0641C85.1933 36.8545 85.1942 38.3728 84.6546 39.6091Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M77.5032 69.6487C77.7218 68.6623 78.5364 68.0251 79.0555 66.991C79.4039 67.7755 78.9809 68.1704 78.7287 68.5762C78.4606 69.0175 78.123 69.4178 77.8117 69.8324C77.7081 69.7662 77.603 69.7094 77.5032 69.6487Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M84.9734 23.8464C84.5556 22.882 84.5686 21.893 84.7926 20.9028C85.2601 21.8567 85.0678 22.8573 84.9734 23.8464Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M80.4779 58.5292C80.0569 57.4445 80.5576 55.9905 81.4831 55.4878C81.1456 56.5251 80.8539 57.4077 80.4779 58.5292Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M57.6737 54.0048C57.6192 53.7654 57.5446 53.5319 57.5049 53.2903C57.049 50.1641 57.2463 47.0285 57.3808 43.8961C57.4554 42.0798 57.63 40.2668 57.7325 38.4554C57.9034 35.5833 58.4742 32.7816 59.0544 29.9816C59.6152 27.2931 60.1296 24.5964 60.6773 21.9008C60.8364 21.1195 61.042 20.3464 61.2236 19.5738C61.3034 19.583 61.3778 19.5961 61.4577 19.6054C61.4627 19.7979 61.5011 19.9914 61.469 20.1773C60.5666 24.8123 59.6047 29.432 58.7767 34.0801C58.4266 36.049 58.3167 38.0698 58.1432 40.0698C57.8169 44.0065 57.5798 47.954 57.85 51.9047C57.894 52.5925 57.9434 53.2765 57.9928 53.9604C57.8895 53.9758 57.7808 53.9949 57.6737 54.0048Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M57.1613 56.3626C57.8263 57.3657 57.5558 58.4865 57.7946 59.5438C57.2862 59.7129 57.1818 59.4024 57.1736 59.0897C57.1441 58.1794 57.1574 57.2718 57.1613 56.3626Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M56.2831 33.0959C56.1842 34.0555 56.0853 35.015 55.9822 36.0265C55.3708 35.5166 55.3887 34.9977 56.0396 33.0626C56.1233 33.0774 56.2032 33.0866 56.2831 33.0959Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M77.8348 36.2795C77.9408 37.4954 78.1074 38.5544 78.1166 39.6097C78.1436 42.3347 77.6713 45.0101 77.13 47.6685C76.7822 49.3745 76.5034 51.0974 76.2354 52.8126C75.8318 55.4235 74.6222 57.7344 73.5923 60.1152C73.5537 60.1994 73.4216 60.2432 73.3266 60.2935C73.3048 60.3088 73.2615 60.2821 73.053 60.2406C73.1542 59.9327 73.2182 59.6183 73.3517 59.3449C74.2541 57.5354 75.0891 55.6998 75.5317 53.7231C75.8164 52.4371 76.0043 51.1292 76.2239 49.8317C76.6349 47.4281 77.1443 45.037 77.4087 42.6219C77.5826 41.0625 77.4293 39.4551 77.3675 37.8734C77.3497 37.3387 77.2047 36.8198 77.8348 36.2795Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.8731 63.9408C71.8507 64.5687 71.6852 64.889 71.153 65.0585C70.959 64.4356 71.2675 64.2027 71.8731 63.9408Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M96.028 34.6691C95.5443 34.0047 95.6011 33.7036 96.428 32.4947C96.6912 33.3547 96.3486 33.9788 96.028 34.6691Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M95.4951 58.6996C95.7676 58.5082 96.0364 58.3115 96.3689 58.078C96.6741 58.778 95.9806 59.077 95.89 59.5732C95.1453 59.4756 95.6572 58.9531 95.5201 58.6657L95.4951 58.6996Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M91.8323 59.9562C92.1613 59.5212 92.2241 59.0201 92.9141 59.2948C92.7353 59.7467 92.6598 60.1834 91.8323 59.9562Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M71.7583 44.4486C72.0264 45.2813 71.9304 46.1408 71.7386 46.9452C70.9558 50.1407 70.311 53.37 69.1178 56.4453C68.0546 59.1843 66.9504 61.9113 65.8834 64.6449C65.6525 65.2316 65.489 65.8446 65.2786 66.5068C64.7396 66.2155 64.8238 65.8951 64.9669 65.5659C65.4518 64.4252 65.9366 63.2845 66.4083 62.1367C67.0421 60.6056 67.7076 59.0849 68.2703 57.5221C68.8383 55.9555 69.3747 54.3785 69.7878 52.7654C70.4719 50.1129 71.3419 47.4931 71.4207 44.7101C71.4253 44.6007 71.4779 44.4903 71.5104 44.3858C71.587 44.4137 71.6746 44.4339 71.7583 44.4486Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M72.5717 39.5099C72.4986 40.1815 72.4436 40.6936 72.3812 41.2761C71.7153 40.7233 71.792 39.8369 72.5717 39.5099Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M45.6143 26.1903C45.2049 25.539 44.9207 25.0773 44.5713 24.5228C45.5515 24.6427 45.9525 25.259 45.6143 26.1903Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M75.0135 20.9596C74.7659 17.3769 75.1633 13.7498 74.4625 10.1831C74.9795 10.1305 75.0223 10.4924 75.0517 10.7658C75.167 11.8444 75.2916 12.9247 75.3309 13.9996C75.3834 15.5796 75.3529 17.169 75.3869 18.7457C75.3991 19.2843 75.5169 19.8222 75.5347 20.3569C75.5365 20.568 75.3978 20.7878 75.3237 20.995C75.2143 20.9901 75.112 20.9721 75.0135 20.9596Z\"\n        fill=\"#676461\"\n      />\n      <path\n        d=\"M74.534 8.91692C74.3661 8.72461 74.2101 8.63012 74.2014 8.51373C74.1935 8.42138 74.3497 8.23827 74.4365 8.23443C74.5327 8.23221 74.6955 8.37097 74.7259 8.47206C74.7524 8.56768 74.6338 8.69995 74.534 8.91692Z\"\n        fill=\"#676461\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 109 / 170,\n  svg: Radish,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/food-and-stuff/radishLarge.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Large Radish', 'sticker name', 'web-stories');\n\nfunction RadishLarge({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 509 718\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <g opacity=\".15\" fill=\"#FFF9EE\">\n        <path d=\"M303.267 347.665c-.93-1.158-1.686-2.519-2.82-3.387-4.768-3.619-9.652-7.093-15.38-9.12-1.744-.637-3.459-1.419-5.087-2.287-3.722-2.027-6.716-4.604-5.96-9.352-2.181-.811-4.187-1.534-7.007-2.577 3.14-1.853 5.582-3.213 7.908-4.719 8.78-5.675 17.415-11.581 26.311-17.082 18.141-11.233 35.265-23.799 51.692-37.348 7.064-5.849 15.089-9.526 23.723-12.044 23.52-6.862 47.447-10.771 72.043-9.728 14.478.637 28.695 2.316 41.836 8.975 4.972 2.519 9.856 5.153 14.856 7.614.902.435 2.152.232 3.257.319.087-1.1.465-2.259.232-3.272-2.064-8.801-4.215-17.603-6.251-25.912-9.07-5.414-18.17-9.091-27.881-10.713-5.785-.955-11.716-1.071-17.589-1.331-4.739-.203-9.478-.319-14.187-.029-8.606.521-17.182 1.361-25.788 2.055-1.483.116-2.995.203-4.942.319 11.105-10.973 22.211-21.309 32.561-32.34 10.496-11.147 20.09-23.104 26.893-37.348-8.78-6.08-17.589-12.189-26.893-18.646-1.308 1.68-2.82 3.388-4.099 5.27-9.449 13.81-19.857 26.809-31.021 39.259-6.192 6.92-12.211 13.955-18.578 20.701-4.273 4.545-8.838 8.83-13.548 12.913-6.512 5.616-13.199 11.059-20.031 16.3-2.326 1.795-5.204 3.242-8.053 3.879-16.746 3.735-32.707 9.757-48.319 16.619-8.926 3.937-17.415 8.859-26.98 13.144.552-.666 1.163-1.303 1.686-1.997 14.479-19.688 28.841-39.52 46.197-56.834 12.909-12.855 26.166-25.362 39.569-37.696 7.326-6.717 15.292-12.739 22.938-19.108 1.686-1.39 3.46-2.751 4.913-4.372 3.547-3.966 7.879-6.196 13.17-6.862 1.018-.115 2.094-.868 2.879-1.592 1.163-1.1 2.064-2.461 3.459-4.14-1.424-.029-2.5-.058-4.622-.087 22.241-18.24 46.197-31.587 73.118-40.8228-2.151-6.3695-8.053-9.9886-11.222-15.5185-6.948 1.0423-12.559 4.285-18.258 7.0065-9.274 4.4008-18.141 9.7569-27.415 14.1577-8.461 3.9954-16.078 9.2068-23.928 14.1291-2.965 1.853-6.367 3.098-9.71 4.198-13.839 4.458-27.91 8.164-41.225 14.099-5.001 2.23-9.943 4.662-15.38 6.341 1.134-1.1 2.239-2.258 3.46-3.301 11.571-9.814 23.258-19.484 36.341-27.3305 6.338-3.8217 11.978-8.7726 18.083-13.0286 5.815-4.0533 11.717-7.9618 17.706-11.7835 4.128-2.6347 8.518-4.893 12.559-7.6145 7.501-5.0667 15.932-8.1356 24.16-11.6099 4.971-2.1135 9.943-4.1981 14.885-6.4274.96-.4343 1.657-1.4186 2.384-2.0556-6.047-6.7748-11.803-13.2312-18.316-20.5272-3.111-.0579-6.425 2.6057-9.885 4.4008-14.216 7.4407-28.346 15.0262-42.33 22.8723-21.514 12.0441-42.941 24.2331-63.059 38.5645-4.942 3.5321-9.798 7.1801-14.711 10.7416-.756.55-1.628.955-3.256 1.882 3.43-6.6305 6.251-12.5368 9.449-18.2114 8.518-15.1131 16.862-30.3421 25.933-45.1367 4.913-8.0198 11.106-15.2289 16.804-22.7565.785-1.0423 2.006-1.7661 3.082-2.5767 3.401-2.6637 3.43-3.7638-.291-5.67469-5.553-2.80838-11.019-5.44304-16.95-8.367221-1.017 1.042281-2.296 2.113521-3.256 3.387421-13.054 16.96609-26.195 33.90319-39.045 51.01399-5.466 7.267-10.321 14.9973-15.467 22.4959-7.704 11.2625-15.496 22.4959-23.113 33.8159-7.617 11.35-14.478 23.104-19.769 35.728-3.053 7.267-6.28 14.476-9.711 21.598-1.134 2.374-3.052 4.401-4.71 6.543-3.081 3.996-6.221 7.933-9.565 12.16-.93-1.824.117-3.416.32-5.067 2.442-19.658 7.821-38.622 14.13-57.296 4.186-12.392 8.809-24.754 14.275-36.6248 6.483-14.0708 13.925-27.7073 23.694-39.8963.204-.2605.378-.55.611-.8106 4.302-5.4141 4.39-5.501-1.687-9.2937-3.11-1.9398-6.541-3.4164-9.885-5.1535-1.017.9844-1.889 1.5634-2.413 2.3741-7.355 11.494-14.943 22.8433-21.862 34.569-7.211 12.16-13.926 24.6384-20.526 37.1458-6.861 12.942-13.897 25.883-18.2 39.925-3.081 10.105-5.901 20.383-7.907 30.748-2.908 15.026-4.943 30.197-7.385 45.31-2.326 14.36-2.762 28.721-1.366 43.226.552 5.819-.117 11.725-.291 17.603-.029.608-.407 1.216-.465 1.36-7.559 0-14.798-.231-21.98.087-11.978.55-23.985 1.187-35.934 2.345-18.664 1.853-35.7885 8.368-51.4879 18.53-11.3385 7.354-22.4443 15.084-31.9512 24.754-12.7339 12.942-23.4909 27.1-30.4975 44.21-6.54144 15.953-8.34397 32.514-9.59411 49.277-1.599013 21.251 2.41307 41.807 8.69281 61.987.2617.811.5524 1.592.7268 2.432.8141 3.59.6106 7.991 2.7038 10.568 2.2096 2.75 3.9249 5.703 5.6983 8.598 2.4422 4.025 4.0121 8.599 6.6577 12.45 3.9249 5.704 7.1811 11.726 10.1465 17.921 2.006 4.227 3.4597 8.715 5.5239 12.942 4.3028 8.744 8.8382 17.4 13.2863 26.086 5.2622 10.278 8.8091 21.077 9.6813 32.629.2326 3.011.5524 6.051.4652 9.062-.1745 7.21-2.0933 13.84-5.1459 20.528-2.1514 4.69-5.4658 8.917-6.6868 14.128-1.192 5.125-1.7735 10.163-1.5118 15.461.2616 5.153-.5524 10.394-1.1048 15.576-.1744 1.651-.7559 3.301-1.4536 4.806-2.3549 5.009-4.7389 9.989-7.3555 14.882-1.6572 3.098-3.7504 5.993-5.6111 9.004-.4942.811-.8722 1.679-1.7153 3.33 1.7735-.261 2.791-.377 3.7795-.609.2617-.057.4652-.463.6105-.752 6.5124-10.799 14.0423-21.049 17.2403-33.556 1.3665-5.385.4942-10.741.0291-16.04-.4943-5.761 1.9188-9.148 6.8612-11.638 3.2853-1.651 6.2798-3.88 9.1871-6.138 1.1338-.869 2.1223-2.374 2.4421-3.764 1.6571-7.383 7.181-11.523 13.2573-14.418 13.5188-6.457 27.2118-12.739 41.9518-15.982 4.739-1.042 9.711-1.39 14.595-1.535 14.013-.376 28.055-.289 42.069-.781 7.588-.261 15.176-1.158 22.706-2.172 5.843-.781 11.6-2.692 17.443-3.098 6.6-.434 12.531-3.068 18.811-4.429 6.425-1.39 12.734-3.388 19.042-5.183 11.659-3.3 22.503-8.367 32.242-15.547 10.321-7.586 20.09-15.634 27.678-26.26 13.083-18.298 22.997-38.014 29.102-59.642 4.245-15.055 5.785-30.37 5.291-45.947-.029-1.303.262-2.606.494-3.908.088-.464.727-1.072.611-1.303-3.663-6.312-2.326-13.637-4.099-20.412-3.722-14.128-8.461-27.765-16.049-40.214-6.425-10.568-14.972-19.485-24.712-27.158-.29-.231-.901-.058-1.337-.058l.058-.144c2.646 2.576 5.32 5.095 7.908 7.73 1.89 1.94 3.634 3.995 5.466 6.022-.291.376-.553.724-.843 1.1-5.699-2.519-11.368-5.037-17.066-7.527.814 1.737 2.035 2.808 3.43 3.59 6.018 3.387 12.066 6.746 18.781 7.527 11.339 15.027 17.822 31.79 22.358 50.522-9.391-2.49-17.735-4.719-26.108-6.92 8.228 5.559 18.113 6.688 27.125 10.423.291 4.662 1.861 8.976.64 13.926-6.251-1.882-12.24-3.677-18.2-5.472-.116.377-.233.753-.349 1.13 6.396 2.46 12.821 4.95 19.508 7.527-.145 1.129-.32 2.345-.523 3.735-7.268-2.085-14.217-3.648-20.816-6.08-6.513-2.403-12.705-5.704-18.956-8.541 0 .087-.116.55.087.695 1.105 1.013 2.181 2.113 3.46 2.895 7.355 4.661 15.409 7.586 23.782 9.844 4.535 1.245 8.954 2.866 13.344 4.314-.029 2.403-.058 4.227-.087 6.225-11.833-.232-22.619-4.488-33.928-6.254 5.32 2.229 10.728 4.111 16.252 5.559 5.669 1.505 11.454 2.605 17.443 3.966-.203 2.606-.378 4.719-.581 6.978-7.937-2.114-15.554-3.735-22.881-6.254-7.355-2.519-14.42-5.906-21.601-8.917 1.716 1.766 3.605 3.416 5.757 4.516 8.925 4.488 18.316 7.73 28.055 10.076 3.518.839 7.239 1.65 10.205 4.4-1.25 5.386-.524 11.06-2.879 16.069-10.815-1.216-20.292-5.183-29.276-10.597 7.821 7.702 17.705 11.147 28.404 13.84-2.18 8.019-3.896 15.865-8.315 22.727-12.327-2.779-23.461-7.788-34.189-13.434-10.757-5.674-20.991-12.305-31.457-18.529 18.955 16.126 41.225 26.288 65.094 34.945-1.977 3.909-3.692 7.267-5.698 11.205-2.937-1.158-5.64-1.969-8.112-3.243-9.768-4.922-19.595-9.815-29.189-15.055-15.176-8.28-31.079-15.519-43.609-27.939-1.803.984-1.628 2.084-.291 3.127 3.838 2.982 7.472 6.369 11.687 8.801 15.932 9.178 32.01 18.124 48.116 26.984 6.57 3.619 13.374 6.775 20.351 10.278-1.861 2.953-3.808 6.051-5.931 9.409-10.35-5.124-20.525-10.017-30.556-15.171-10.059-5.153-20.118-10.365-29.974-15.894-9.768-5.472-19.304-11.379-28.927-17.082-.262.318-.524.608-.756.926.814.898 1.482 1.998 2.471 2.635 5.669 3.677 11.193 7.643 17.124 10.828 18.025 9.641 36.225 18.935 54.366 28.373 4.885 2.548 9.769 5.154 15.235 8.02-1.716 2.316-3.14 4.227-4.681 6.312-13.054-6.978-26.66-11.408-38.9-19.514.058 1.071-.087 1.766.175 1.998 1.25 1.1 2.529 2.258 3.983 3.039 10.728 5.965 21.833 11.176 33.23 16.127-1.919 2.49-4.041 5.24-6.483 8.367-8.199-3.59-16.31-6.572-23.898-10.539-14.042-7.353-27.823-15.199-41.633-22.959-1.86-1.042-3.343-2.692-4.971-4.111-2.268-1.94-4.623-3.648-9.216-3.445 1.657 1.621 2.384 2.605 3.372 3.185 12.618 7.498 25.119 15.257 37.999 22.293 9.768 5.327 20.06 9.699 30.09 14.505 2.006.955 3.925 2.113 6.338 3.416-2.878 2.519-5.117 4.459-6.774 5.907-1.832-1.159-3.053-2.201-4.448-2.751-4.884-1.882-10.088-3.069-14.711-5.443-11.862-6.08-23.549-12.507-35.12-19.08-12.763-7.238-25.352-14.823-38.028-22.235-1.25-.724-2.529-1.766-4.419.319 4.652 3.937 10.408 5.645 15.234 8.743 5.088 3.301 10.496 6.109 15.758 9.149l15.351 8.859c5.262 3.04 10.466 6.167 15.815 9.034 5.204 2.779 10.467 5.53 15.874 7.875 5.466 2.345 11.135 4.198 16.804 7.122-1.453 1.1-2.296 1.708-3.052 2.345-3.082 2.577-6.193 3.069-9.682.666-1.511-1.042-3.343-1.621-5.029-2.403-12.996-6.051-26.079-11.986-39.016-18.182-9.594-4.604-19.072-9.41-28.463-14.361-17.618-9.264-35.207-18.645-51.43-30.284-1.134-.81-2.442-1.389-3.663-2.084-.262.289-.552.608-.814.897.523.811.872 1.911 1.599 2.374 9.856 6.225 19.537 12.711 29.684 18.385 15.176 8.483 30.555 16.648 46.08 24.436 13.112 6.572 26.602 12.42 39.888 18.674 4.216 1.998 8.315 4.227 12.531 6.399-1.018 1.592-1.716 2.924-2.646 4.082-2.355 2.924-6.338 3.851-9.798 2.287-7.21-3.271-14.42-6.572-21.601-9.959-11.135-5.241-22.473-10.163-33.346-15.924-12.822-6.804-25.236-14.332-37.824-21.57-1.425-.81-2.733-1.968-5.204-.723 1.075 1.129 1.802 2.258 2.82 2.837 8.78 5.066 17.414 10.394 26.456 14.91 18.113 9.062 36.458 17.661 54.686 26.521 4.332 2.113 8.519 4.487 12.996 6.861-3.925 3.33-21.136 9.612-27.736 10.597-2.006-1.39-3.314-2.693-4.913-3.359-5.611-2.345-11.251-4.661-16.979-6.659-13.78-4.835-26.863-11.059-39.248-18.761-10.176-6.311-20.235-12.855-30.265-19.398-17.386-11.349-35.498-21.54-52.244-33.932-9.6524-7.122-19.4791-13.955-26.4566-23.972-.3489-.522-1.4536-.522-2.1805-.782.9013 2.924 2.0642 5.385 3.8958 7.18 5.2913 5.154 10.5826 10.423 16.3973 14.939 12.792 9.96 26.485 18.646 40.266 27.158 8.198 5.066 16.194 10.422 24.334 15.518 11.745 7.354 23.113 15.374 35.411 21.627 14.246 7.239 29.334 12.855 44.045 19.167 1.105.463 2.123 1.071 4.303 2.2-6.541 1.593-11.745 2.924-17.007 4.083-.902.202-2.007-.116-2.937-.435-13.809-4.603-27.096-10.394-39.394-18.269-13.78-8.859-27.764-17.429-41.312-26.578-15.787-10.654-32.678-19.716-46.779-32.745-.698-.637-1.89-.753-3.1106-1.187.1163.898.0291 1.361.2035 1.506 5.6691 4.777 11.1351 9.785 17.0661 14.186 5.553 4.111 11.6 7.528 17.356 11.349 8.461 5.559 16.834 11.263 25.323 16.793 10.292 6.717 20.525 13.549 31.05 19.919 6.309 3.822 13.054 7.006 19.74 10.162 4.797 2.259 9.827 3.996 14.769 5.964-5.756 1.853-11.396 2.78-17.007 3.996-4.39.926-8.228-.174-12.066-2.172 1.745-2.576-.378-3.068-1.802-3.734-7.181-3.388-14.537-6.428-21.543-10.105-9.536-5.008-18.898-10.394-28.201-15.837-9.943-5.79-19.304-12.391-26.718-21.366-1.396-1.68-2.82-3.388-4.448-4.836-1.018-.897-2.471-1.939-3.692-.115 3.43 3.735 6.599 7.44 10.03 10.886 9.972 10.075 22.182 16.966 34.393 23.828 10.583 5.964 21.514 11.32 32.3 16.966 1.047.55 2.878 1.158 2.907 1.824.175 3.329 3.169 3.068 4.972 4.256.698.463 1.366.926 2.064 1.418-5.466.811-10.67.898-15.874.927-.494 0-1.105-.116-1.424-.406-4.1-3.966-9.827-4.285-14.653-6.63-6.687-3.242-13.374-6.485-20.06-9.757l.087-.173c1.482 1.563 2.704 3.59 4.477 4.603 5.117 2.895 10.466 5.443 15.758 7.991 2.878 1.361 5.901 2.432 8.838 3.619-6.251.782-12.269.897-18.287.955-3.605.029-7.007-.289-10.437-2.142-9.362-5.038-19.159-9.294-26.66-17.169-1.018-1.071-2.268-2.49-4.797-1.795 8.082 9.96 19.072 15.026 30.584 20.701-4.39 1.245-7.704 1.332-11.018-.492-4.594-2.49-9.245-4.864-13.868-7.238-.494-.261-1.105-.232-1.686-.319-.087.232-.175.435-.262.666 4.681 2.838 9.362 5.675 14.856 9.004-4.564 1.216-7.966 2.143-11.425 3.069-4.361-1.534-7.646-5.906-13.316-5.501.204 1.477.349 2.519.524 3.59-1.89-.231-3.664-.463-5.641-.694-1.017 2.866-1.8893 5.385-2.7905 7.961-2.1224-.405-3.8668-3.213-7.0066-1.592.029 1.1.0872 2.258.1162 3.387-1.6862-.231-3.0817-.405-4.8842-.636.2035 1.852.3198 3.126.4942 4.864-4.1574-2.809-6.5704 2.229-10.3499 1.939-.5815-1.071-1.1048-2.055-1.6863-3.155 1.8316-.029 3.3434-.029 5.3494-.058-.9303-2.346-1.628-4.025-2.3839-5.965 2.5003-1.505 2.3258-3.242.3779-5.211-1.2211-1.245-2.0932-2.808-2.8491-3.822 4.0411-3.155 6.7158 1.187 10.2046 1.448-5.8146-5.067-11.3385-10.133-17.1531-14.853-3.3724-2.721-4.5354-6.253-5.6983-11.204 3.0817 2.432 5.3204 4.256 7.5881 6.051-2.9655-5.935-10.1174-8.223-12.0653-16.213 2.7619 1.853 4.6807 3.126 6.5414 4.4 1.8607 1.274 3.2562 3.359 5.8437 3.446-6.745-7.036-17.2984-10.539-19.4208-22.236 5.1169 3.851 9.9139 7.47 14.7109 11.06.2617-.318.5524-.666.8141-.984-7.7043-6.254-16.5134-11.379-21.3396-20.614 5.4658 4.227 10.9024 8.454 16.3681 12.71.2908-.348.5815-.724.8722-1.071-2.6747-2.114-5.3494-4.228-7.966-6.37-2.8491-2.345-5.8146-4.603-8.4312-7.238-2.3258-2.345-4.2446-5.096-6.3378-7.672.2616-.261.5523-.493.814-.753 1.4246 1.129 2.791 2.345 4.3028 3.329 1.4536.985 3.0817 1.766 4.6226 2.606l-.0581.116c-3.0527-3.04-6.0763-6.08-9.0417-9.062.5233-1.361.9594-2.461 1.4536-3.764 1.7444 1.303 3.2562 2.664 4.9715 3.677 1.4827.897 2.2386 3.3 5.3203 2.664-6.0762-5.849-13.1119-9.642-17.9671-15.837 6.0472 2.403 11.164 6.659 17.5601 8.135-.9303-1.071-2.006-1.795-3.1399-2.519-5.4076-3.416-10.8733-6.717-16.1645-10.249-3.0818-2.055-5.4658-4.777-5.8146-8.975 8.1404 4.603 16.0192 9.091 23.8979 13.55.2326-.377.4652-.753.6978-1.129-1.9188-1.158-3.8376-2.317-5.7274-3.504-5.989-3.735-12.0943-7.325-17.9671-11.262-3.1689-2.114-5.9308-4.777-6.5123-9.815 2.9945 2.114 5.3785 3.909 7.8787 5.501 2.7038 1.708 5.4076 3.619 8.3731 4.719 2.6165.956 3.983 4.459 7.5008 3.417-4.3028-3.156-8.9545-5.791-13.3736-8.744-4.7389-3.185-9.594-6.283-13.0247-11.002-.5523-.782-.6686-1.882-.9594-2.837.2617-.174.5234-.348.785-.492 4.9424 3.387 9.9139 6.745 14.8563 10.133-.0581-1.158-.4943-1.824-1.1048-2.287-4.3319-3.185-8.6347-6.486-13.141-9.439-2.1223-1.389-3.4887-3.069-4.2155-5.414-4.8262-15.2-7.67529-30.66-6.33794-46.671.05815-.724-.08723-2.056-.29074-2.084-2.35491-.319-1.33734-1.969-1.25012-3.098.58146-6.891 1.13383-13.782 1.88973-20.643.49424-4.343 1.04667-8.715 2.06417-12.942 1.5409-6.37 3.4888-12.652 5.2622-18.964 2.3259-8.338 5.3494-16.271 11.6001-22.669 2.2386-2.288 4.9134-4.691 5.7565-7.528.785-2.635 2.2386-4.343 3.8958-6.08 12.763-13.666 27.6193-24.696 43.7257-34.135 11.2221-6.572 23.3456-11.031 36.0216-12.97 13.635-2.085 27.532-2.375 41.051-3.417 3.169 3.706 5.669 7.47 9.943 9.497-1.105-3.62-5.146-5.357-6.309-9.063 10.524-1.013 10.582-.984 11.658 1.216-.639.145-1.366.29-3.227.666 7.21 6.051 13.635 11.465 20.06 16.851-.261.318-.523.608-.814.926-7.966-5.067-15.728-10.365-22.008-18.587-.436 2.75.436 4.227 1.832 5.414 3.169 2.75 6.367 5.472 9.652 8.106 1.89 1.506 4.07 2.317 4.128 5.588.029 1.94 1.89 4.198 4.739 4.43 1.134.087 2.268.608 3.285 1.158 12.327 6.746 25.149 12.305 38.261 17.285.785.289 1.453.81 2.209 1.215-20.235-5.24-39.336-12.796-56.431-24.956 1.832 2.171 3.925 4.024 6.193 5.558 12.705 8.512 26.485 14.824 41.022 19.543 2.558.84 5.844 1.245 7.355 3.069 3.751 4.517 10.845 3.388 13.955 8.86.553.984 3.14.955 4.797 1.187 13.81 1.911 27.271.608 40.267-4.633 2.006-.81 3.721-1.071 5.698.203 2.82 1.795 5.814 3.272 8.751 4.893l-.291.376zm-50.529-87.001c.843-2.49 1.716-5.009 2.559-7.499.058-.811-.088-1.679.174-2.432 4.565-13.058 9.769-25.768 19.537-36.017 1.018-1.071 2.559-2.026 2.297-3.966-.64.029-1.018-.087-1.279.058-.436.202-.873.521-1.192.868-5.524 5.733-10.35 11.958-13.723 19.196-2.18 4.69-4.303 9.438-6.454 14.186-.029.666.058 1.332-.145 1.94-2.559 8.483-5.292 16.937-7.705 25.478-1.628 5.733-2.791 11.581-4.157 17.372-.843-.84-.989-1.622-.843-2.346 1.89-9.177 3.43-18.442 5.843-27.475 1.396-5.27 4.216-10.134 6.397-15.2-.32-.811-.669-1.651-1.396-3.446-1.425 4.893-5.64 5.357-7.995 8.107.145-1.505.407-2.837.959-4.053 8.897-19.833 17.938-39.607 32.446-56.226.872-.984 2.122-2.171.785-4.661-13.199 14.042-21.427 30.574-30.149 46.816.698-3.388 1.512-6.659 2.849-9.699 5.699-13.26 13.49-25.247 23.113-35.988 8.286-9.294 17.095-18.124 25.265-27.533 7.937-9.149 17.153-16.677 27.415-23.018 13.171-8.106 27.504-13.636 42.214-18.24 5.321-1.679 10.641-3.358 16.02-4.835 4.622-1.245 6.018-.289 7.093 4.546-14.42 4.169-28.462 9.38-41.08 17.806 1.018.202 1.89 0 2.704-.348 7.239-3.185 14.449-6.427 21.718-9.583 1.366-.579 2.936-1.187 4.361-1.1 3.488.26 6.948.897 10.408 1.39-4.681 1.65-9.565 2.75-14.391 4.024-.873.231-1.541 1.158-2.908 2.229 7.443 1.622 13.17-3.793 20.206-2.374-.872.811-1.192 1.245-1.599 1.419-8.344 3.648-16.891 6.89-24.974 11.031-8.256 4.198-16.426 8.772-24.014 14.041-8.14 5.675-15.438 12.537-23.346 18.588-10.088 7.73-18.839 16.763-27.183 26.289-15.118 17.197-26.311 36.595-33.841 58.136-.232.637-.727 1.187-1.105 1.766-.174-3.069.378-5.82 1.338-8.425 1.017-2.722 2.413-5.27 3.663-7.904-.349-.232-.698-.492-1.076-.724-.785.84-1.802 1.563-2.325 2.548-1.309 2.548-2.384 5.211-3.547 7.817-.785 2.519-1.57 5.038-2.355 7.585-.814 8.599-2.908 16.88-6.425 24.841-.117-2.316.174-4.545.755-6.716 1.629-6.052 3.373-12.16 5.088-18.269zm-16.397 62.652c-5.349-1.621-10.699-3.213-16.048-4.835.61 1.419 1.628 2.374 2.82 2.809 6.483 2.403 12.996 4.69 19.508 7.064 1.366.492 2.587 1.332 3.867 2.027.901 1.94 3.663 2.982 2.994 6.369-6.658-2.113-12.937-4.14-19.246-6.138.087-.405.174-.81.261-1.216 1.221.145 2.472.145 3.605.522 2.733.897 5.35 2.055 8.083 2.953 2.849.955 3.547.463 4.273-2.606-1.511 1.737-3.11.55-4.593.029-6.309-2.316-12.589-4.748-18.897-7.093-1.076-.406-2.937-1.13-3.228-.753-2.006 2.548-3.837.637-5.523-.087-3.402-1.448-6.629-3.214-9.972-4.777-1.919-.898-3.925-1.622-5.873-2.432.058-.348.116-.695.174-1.013 7.995-1.535 16.019-2.346 24.16-.956.581.087.93 1.477 1.395 2.258.378-.289.843-.926 1.163-.839 3.605.839 7.181 1.882 10.001 4.748-3.721-1.303-7.442-2.635-11.135-3.938-.494.203-.988.435-1.482.637.93.666 1.802 1.506 2.82 1.969 3.663 1.65 7.384 3.185 11.106 4.748 1.831.174 3.954-.318 5.262 2.982-2.355-1.071-3.925-1.766-5.495-2.432zm6.483-227.3331c-.058 1.3318.175 2.7505-.232 3.9375-1.774 5.0666-3.576 10.1626-5.699 15.0846-3.983 9.293-7.268 18.819-9.623 28.662-.349 1.477-.93 2.896-1.395 4.343-.698-.839-.669-1.447-.553-2.026 2.413-12.595 5.67-24.928 10.728-36.77.553-1.303 1.628-2.692-.145-4.401-.669.695-1.599 1.216-1.89 1.998-2.529 7.47-5.407 14.882-7.326 22.525-3.721 14.679-7.065 29.444-10.234 44.239-1.89 8.888-3.14 17.893-4.797 26.839-.465 2.577-1.308 5.095-1.948 7.643-.407-.058-.843-.144-1.25-.202.756-8.976 2.995-17.806 3.111-26.839-.93 1.737-1.483 3.503-1.832 5.298-1.453 7.615-2.762 15.229-4.244 22.843-.96 4.864-1.367 9.902-4.623 14.187-.262-2.287-.378-4.603.087-6.804 2.442-11.175 4.768-22.38 7.676-33.411 2.122-8.135 5.058-16.068 7.646-24.059.465-1.419.697-2.664-1.716-2.895-2.151 7.238-4.39 14.418-6.483 21.685-2.384 8.396-4.71 16.821-6.919 25.246-.989 3.735-1.745 7.557-2.471 11.35-.437 2.229-1.512 2.171-3.228 1.187.582-3.417 1.047-6.746 1.687-10.047 4.186-21.888 11.832-42.791 18.49-63.984 5.873-18.617 14.275-36.306 22.474-54.0253 3.837-8.2514 8.227-16.2132 13.984-23.3355.232-.2895.058-.8975.087-1.7372-.989.2317-1.948.1448-2.355.6081-1.25 1.3607-2.326 2.8952-3.373 4.4007-7.849 11.4651-13.111 24.262-18.664 36.8562-4.536 10.307-8.809 20.73-13.2 31.095l.088-.174c-3.053 10.336-5.379 20.904-10.35 30.603.727-4.083 2.238-7.991 3.023-12.015.756-3.851 3.286-7.499 2.472-11.61-.466-.116-.96-.232-1.425-.319-4.681 15.605-9.362 31.211-14.042 46.816-.814-1.245-.756-2.229-.524-3.185 1.454-6.398 2.85-12.826 4.419-19.195 3.576-14.592 7.937-28.923 15.002-42.27 7.617-14.448 15.147-28.9238 22.939-43.2841 3.779-6.9486 7.908-13.6945 12.181-20.3535 4.652-7.2091 9.653-14.2156 14.537-21.28.203-.3184.814-.3474 1.279-.55.116 3.0978-3.954 5.1245-1.948 9.3226 2.268-3.04 3.053-6.659 7.065-8.1935-2.53 4.864-5.96 8.6567-6.193 13.9261 3.46-2.9821 3.722-9.0332 9.682-9.8149-4.274 6.8038-8.693 13.2891-12.502 20.1219-5.378 9.699-10.292 19.6586-15.467 29.4734-.523.9844-1.395 1.7661-2.122 2.6636l.116-.1737zM230.585 276.906c-1.541 5.559-.466 11.146-2.413 16.445-.582-1.593-.785-3.214-.611-4.777.959-8.86 2.006-17.719 2.995-26.608.174-1.476.785-3.792.116-4.256-2.21-1.621-1.105-3.445-.727-5.008 4.506-19.196 9.332-38.304 20.089-55.27.437-.695.32-1.766.466-2.664-1.57.116-2.559.608-2.995 1.419-3.111 6.167-6.716 12.16-9.013 18.645-3.692 10.452-6.803 21.164-9.623 31.906-2.384 9.062-3.954 18.355-5.901 27.533-3.489-7.585.697-14.939.319-22.467-.843 1.303-1.511 2.635-1.773 4.054-1.541 8.425-2.995 16.85-4.448 25.275-.843 4.98-1.57 9.988-2.442 14.939-.146.782-.814 1.448-1.251 2.172-.378-.087-.755-.174-1.133-.261.203-2.229.232-4.487.61-6.688 1.25-7.47 2.878-14.881 3.896-22.38 2.587-18.645 7.559-36.567 15.99-53.446 2.326-4.661 4.972-9.178 7.443-13.781 9.623-17.748 21.107-34.077 36.457-47.482 8.606-7.528 17.415-14.824 26.282-22.38-.291-1.766-1.453-2.201-3.082-.956-3.866 2.983-7.762 5.878-11.396 9.12-7.414 6.63-14.856 13.232-21.921 20.238-16.136 16.04-26.747 35.872-36.865 55.849-6.105 12.044-10.379 24.899-12.937 38.217-.989 5.125-1.686 10.278-2.675 15.403-.349 1.824-1.076 3.59-1.715 5.645-2.588-3.329-2.152-6.34-1.367-9.322 1.57-5.849 3.286-11.668 4.972-17.487.465-1.651 1.134-3.214 1.831-5.125-1.482.261-2.296.376-3.11.521.436-4.632 3.983-7.933 4.07-12.623-.843.145-1.628.087-1.745.347-7.355 14.824-13.635 30.024-16.513 46.44-.349-.058-.669-.087-1.018-.145.291-3.185.582-6.369.902-9.67-.902.203-1.454.347-2.878.666 3.837-10.77 6.919-21.077 11.164-30.921 4.593-10.655 9.972-20.991 15.554-31.182 7.297-13.347 16.368-25.449 26.427-36.914 12.734-14.534 27.532-26.781 42.098-39.317 4.07-3.532 8.344-6.833 12.559-10.191 2.5-1.998 4.943-4.083 7.588-5.878 10.67-7.122 20.875-14.939 32.533-20.4979 2.733-1.3028 5.204-3.2716 7.094-6.5143-1.076.2317-1.599.2317-1.977.4633-9.507 5.7615-19.043 11.4651-28.434 17.3999-5.262 3.33-10.495 6.775-15.35 10.684-10.379 8.338-20.439 17.053-30.701 25.507-13.723 11.32-26.108 23.972-36.981 38.014-8.664 11.176-15.874 23.22-22.474 35.814-6.367 12.16-11.774 24.581-16.513 37.349-.494 1.302-1.25 2.518-1.89 3.792.989-10.046 4.303-19.398 7.617-28.778-.93-.058-1.54-.087-2.384-.145.466-1.216.814-2.316 1.28-3.387 6.774-14.94 15.35-28.837 25.264-41.894 1.977-2.606 3.343-5.936 7.036-6.978.552-.145.814-1.361 1.25-2.055 1.221-1.998 2.18-4.228 3.75-5.907 5.146-5.559 10.554-10.886 15.758-16.416 10.379-11.088 21.514-21.309 33.695-30.4 3.373-2.49 6.92-4.748 10.292-7.238 10.147-7.527 20.031-15.4313 30.44-22.5535 10.408-7.1513 21.31-13.6076 32.009-20.2956 7.007-4.3718 13.926-8.9752 21.194-12.9127 13.926-7.6145 28.056-14.8236 42.098-22.2065 4.157-2.1714 8.344-4.2559 12.792-6.5142 2.093 2.6925 3.867 5.0087 5.873 7.5855-6.6 3.3874-12.618 6.8038-18.898 9.6121-14.246 6.3985-27.125 15.0842-40.411 23.1329-.582.3475-.727 1.5056-1.541 3.3295 2.093-.8396 3.227-1.0712 4.128-1.6792 17.996-12.0731 37.185-21.9458 56.896-30.8921.843-.3764 2.035-.0579 3.053-.0579-2.268 1.9398-4.885 2.7505-7.007 4.2849-2.035 1.4766-5.582 1.1292-6.425 4.7772 14.74-5.9063 14.74-5.9063 18.316-3.5033-2.151 1.0134-4.012 2.0557-5.989 2.8374-4.506 1.795-9.332 3.04-13.577 5.3272-11.746 6.2537-23.433 12.6811-34.859 19.5138-6.483 3.8797-12.356 8.8015-18.548 13.1733-9.769 6.8907-19.886 13.376-29.364 20.6142-18.083 13.839-35.294 28.634-50.645 45.542-9.071 9.988-18.345 19.774-27.59 29.618-11.31 12.073-19.973 25.826-26.369 40.997-1.512 3.561-2.384 7.411-4.012 10.915-3.896 8.512-5.873 17.545-7.763 26.578-1.337 6.398-2.151 12.912-3.227 19.369-.029.203-.32.376-.727.868-.378-1.505-.669-2.721-.988-3.908zm-9.565 27.678c4.215-2.171 7.733-4.777 11.687-5.848 5.727-1.535 10.902-4.227 16.368-6.283 2.849-1.071 5.727-2.113 8.46-3.474 10.437-5.154 20.875-10.336 31.225-15.663 16.368-8.425 32.736-16.879 47.272-28.287 13.141-10.307 26.021-20.903 38.929-31.5 5.32-4.372 10.641-8.83 15.496-13.723 6.977-7.064 13.81-14.332 20.206-21.917 10.873-12.855 21.368-26.028 32.009-39.086 1.047-1.274 1.977-2.634 3.14-4.169 3.198 2.259 6.163 4.343 9.216 6.515-9.362 18.732-23.375 33.179-36.952 48.031 13.025-11.233 24.073-24.204 33.987-38.101.814.319 1.395.55 1.947.753 1.716-2.027 3.402-4.024 5.088-6.022.291.202.582.405.872.608-1.628 2.721-3.227 5.443-5.291 8.917 4.506-1.505 4.972-6.022 8.751-6.948-5.437 7.353-10.844 14.736-16.281 22.09 3.925-3.127 7.036-6.861 10.205-10.509 3.111-3.562 5.204-8.049 9.594-10.655-.175 1.853-.669 3.561-1.599 4.98-3.082 4.603-6.28 9.149-9.565 13.636-9.972 13.695-22.096 25.363-34.481 36.828-3.837 3.561-8.024 6.775-11.484 10.654-3.575 3.996-8.663 5.704-12.385 9.641-4.564 4.806-10.524 8.339-15.932 12.363-7.326 5.443-14.594 10.944-22.066 16.126-4.419 3.069-8.286 7.441-14.42 7.296-.727-.029-1.512.695-2.21 1.129-5.465 3.359-10.96 6.688-16.339 10.163-5.087 3.271-10.001 6.89-15.147 10.075-4.157 2.548-8.518 4.748-12.85 7.007-5.611 2.924-10.757 6.89-18.083 7.99 3.343-2.2 5.93-4.024 8.663-5.674 2.53-1.506 3.751-4.227 6.484-5.791 12.675-7.064 25.177-14.476 37.533-22.09 7.036-4.314 13.722-9.236 20.496-13.955 10.903-7.615 21.776-15.258 32.591-22.959.727-.522 1.018-1.593 1.541-2.432-.291-.261-.581-.522-.843-.811-2.064 1.361-4.158 2.663-6.164 4.111-10.844 7.759-21.397 15.953-32.503 23.278-13.897 9.149-28.259 17.69-42.505 26.375-13.112 8.02-26.66 15.258-40.702 21.541-2.035.897-4.245 1.361-6.367 2.026-.145-.347-.291-.723-.407-1.071 1.308-.897 3.838-2.113 3.692-2.605-.988-3.62 2.21-3.272 3.78-4.112 2.674-1.447 5.669-2.258 8.402-3.561 7.442-3.59 14.827-7.267 22.212-11.002.697-.347 1.133-1.245 1.715-1.882-6.571 2.085-12.502 5.096-18.52 7.846-6.308 2.867-12.617 5.762-19.13 8.194-6.308 2.345-12.908 3.995-19.275 6.167-6.454 2.171-12.443 5.906-20.06 5.79zm75.037-226.3488c-1.134-.9555-1.832-1.5345-2.704-2.2583 5.262-7.4987 10.263-14.8815 15.554-22.0617 5.582-7.6144 11.339-15.0841 17.153-22.4959 6.222-7.9619 12.618-15.808 18.898-23.71196 1.366-1.73714 2.674-3.12685 5.029-.89752-2.326 2.98209-4.739 5.79048-6.803 8.83048-1.977 2.9242-3.576 6.08-5.291 9.1779-1.686 3.0399-3.256 6.1378-4.884 9.2357.32.1737.61.3475.93.5501 5.815-8.7725 10.117-18.6742 18.49-25.50695-2.616 4.54555-6.192 8.56985-7.907 14.01295 2.471.0289 2.936-4.4297 5.727-1.9398.029.0289.93-.8107 1.337-1.3029.931-1.216 1.657-2.5767 2.675-3.6769 1.541-1.6503 2.849-3.7638 6.541-4.6614-3.866 4.8351-7.064 8.6568-10.059 12.6233-12.152 16.0685-20.758 34.2505-30.788 51.593-4.972 8.5988-9.303 17.574-14.362 26.1147-2.181 3.706-5.291 6.949-8.344 10.047-2.239 2.287-5.088 3.966-7.675 5.906 1.279-4.14 3.081-7.528 4.913-10.944 1.832-3.416 3.576-6.862 5.553-10.1623 2.064-3.4743 4.419-6.7748 6.6-10.1622 2.093-3.2427 4.302-6.4564 6.221-9.8149 1.803-3.1847 4.972-5.6457 5.262-9.7279-1.424.8975-2.558 2.0556-3.43 3.3584-5.524 8.2514-11.222 16.416-16.397 24.899-4.536 7.4699-8.519 15.2869-12.647 23.0169-2.82 5.27-7.152 8.86-12.124 11.842 2.065-4.141 4.39-8.02 6.6-11.987 2.122-3.821 4.041-7.759 6.163-11.609 2.181-3.996 4.361-7.9913 6.804-11.813 2.471-3.8217 5.378-7.3249 7.878-11.1466 2.501-3.7928 4.681-7.8171 7.036-11.6968 2.268-3.7348 4.477-7.5276 6.919-11.1755 2.53-3.7638 5.437-7.325 7.966-11.0888 2.413-3.619 5.815-6.688 7.065-11.1466-1.337.2606-2.384.7238-3.082 1.5345-.872.9843-1.366 2.2582-2.122 3.3584-5.495 7.8751-11.135 15.6343-16.484 23.5962-2.995 4.4586-5.437 9.2936-8.344 13.8102-6.774 10.4518-14.304 20.469-19.305 31.905-3.459 7.904-10.699 13.782-12.123 22.728-.029.261-.465.492-.698.724-4.448 4.545-8.925 9.062-13.374 13.607 10.147-25.883 25.934-48.466 41.633-71.4828zM259.599 266.657c1.774-7.673 4.972-14.158 7.705-20.846 8.111-19.832 21.049-36.364 35.382-51.998 7.21-7.846 15.495-14.476 23.636-21.338 15.845-13.376 32.969-24.61 51.924-33.035 1.512-.666 3.053-1.708 5.524-1.216-1.105 1.043-1.657 1.622-2.297 2.143-17.211 14.186-33.521 29.328-49.656 44.673-17.415 16.561-32.736 34.859-47.128 53.996-5.262 7.007-10.728 13.868-15.699 21.078-2.268 3.3-4.942 5.414-9.391 6.543zm117.077-21.049c4.594-3.734 8.402-7.498 14.537-7.961 5.873-.435 11.687-1.738 17.502-2.693 2.674-.434 5.291-1.013 7.966-1.332 11.135-1.303 22.299-2.548 34.597-3.937-1.541-.985-2.326-1.911-3.14-1.94-1.832-.087-3.693.202-5.524.463-16.048 2.316-32.097 4.661-48.174 6.949-.989.144-2.035.058-3.489.086 3.605-4.921 8.548-5.761 13.374-6.282 15.379-1.708 30.788-3.677 46.284-3.648 11.455.029 23.026.318 33.841 5.067.32.144.843-.145 1.948-.348-1.047-.811-1.599-1.39-2.239-1.708-5.233-2.548-10.786-3.764-16.572-4.314-14.216-1.332-28.375-.753-42.533.637-6.542.637-13.112 1.071-19.683 1.592-.988.087-1.977.261-3.343.464 2.82-4.864 7.472-4.893 11.426-5.53 17.938-2.867 35.992-3.735 54.104-1.998 9.856.955 19.16 4.111 27.881 8.715 4.245 2.229 5.96 5.935 5.728 10.712-2.617-.261-4.972-.753-7.268-.637-2.268.087-4.507-2.548-7.501.145 1.889.666 3.227 1.158 4.564 1.65 1.541.579 3.082 1.158 4.652 1.766-.901.956-1.483 1.593-2.181 2.345 7.094 3.156 9.74 5.067 10.467 7.875-2.82-1.447-5.321-2.779-7.85-4.053-7.123-3.561-14.304-6.949-22.241-8.367-22.008-3.938-44.045-3.88-66.025-.029-10.204 1.824-20.351 4.14-31.108 6.311zm17.938-136.683c8.693-5.183 17.037-10.2206 25.439-15.1135 3.78-2.2004 7.763-4.0823 11.571-6.2537 9.42-5.3272 19.247-9.728 29.364-13.4918 3.634-1.3607 3.692-1.216 6.396 2.4031-6.018 3.7059-6.018 3.7059-6.716 7.5565 2.035-.579 3.983-1.1002 5.902-1.6792 1.832-.5501 3.605-1.3608 5.611.2026-25.671 10.3939-49.453 23.509-71.694 41.025-2.064-5.182-3.809-9.467-5.873-14.649zM263.088 276.877c-.291-3.359 1.512-4.343 3.344-5.24 6.977-3.388 13.809-7.065 20.961-10.047 10.437-4.372 21.049-8.28 31.632-12.305 2.238-.839 4.564-1.389 6.861-2.084-21.543 14.823-44.918 26.144-68.438 37.261 1.774-4.487 6.541-4.661 9.885-6.861 3.663-2.403 7.588-4.372 11.426-6.486 3.692-2.026 7.355-4.053 11.134-5.964 3.925-1.969 7.908-3.793 11.862-5.645 3.605-1.68 7.21-3.272 10.815-4.922-17.734 4.256-33.288 13.318-49.482 22.293zm-18.81-117.807c4.971-12.392 10.001-24.32 16.979-35.235 6.919-10.828 13.519-21.946 22.008-31.7317-.727 2.1425-1.657 4.1402-2.966 5.8484-9.448 12.3623-16.368 26.2303-23.723 39.8093-2.471 4.575-5.03 9.207-6.687 14.1-1.047 3.098-2.268 5.443-5.611 7.209zm90.33 81.298c.203.319.378.666.581.984-1.134.753-2.297 2.201-3.372 2.143-4.768-.203-8.809 2.056-12.967 3.532-15.903 5.617-31.747 11.378-46.778 19.167-.611.318-1.25.55-1.89.752-.64.203-1.279.261-1.948.406 20.642-12.942 43.377-20.267 66.374-26.984zm-32.358 52.838c12.181-9.989 24.479-19.717 38.725-26.578-12.531 9.438-24.451 19.745-38.725 26.578zm-37.824 52.259c4.506-2.78 9.128-5.733 13.809-8.512.901-.521 2.297-.869 3.227-.55 1.948.666 3.722 1.795 5.902 2.924-6.018 4.053-13.286 5.877-22.938 6.138zm81.055-112.364c-.814.753-1.512 1.882-2.5 2.2-15.496 5.009-31.021 9.931-46.546 14.882 15.757-7.209 31.806-13.637 49.046-17.082zm-134.346 18.182c.349.087.698.145 1.017.232-2.035 8.888-4.07 17.747-6.076 26.636-2.122-9.844 1.57-18.327 5.059-26.868zm27.212 87.957c11.048 2.172 21.921 2.49 32.736-.984-10.786 6.572-21.775 5.298-32.736.984zm7.704-83.585c-2.035 9.351-3.866 17.777-5.901 27.07-1.367-6.109 1.977-21.482 5.901-27.07zm14.246 76.318c2.268-4.43 6.454-4.111 9.827-5.761.639 1.274 1.105 2.229 1.657 3.3-3.634 2.287-6.977 3.822-11.484 2.461zm-54.657-31.761c-1.105-5.356-.058-10.364 2.064-15.199-.203 5.153 0 10.335-2.064 15.199zm69.455 10.279c.146.289.32.579.466.897-4.943 3.88-10.38 6.717-16.543 8.049-.174-.319-.32-.666-.494-.985 5.553-2.663 11.048-5.327 16.571-7.961zm-84.718-10.887c1.744.464 3.488.927 6.192 1.622-5.117 2.75.902 3.966.378 6.427-1.657-.926-3.111-1.708-4.622-2.577 2.907-2.924-2.617-3.011-1.948-5.472zm5.349-9.409c-1.483-5.24-.843-10.249 1.745-15.026-.582 5.008-1.163 10.017-1.745 15.026zm-6.018-77.911c.436.029.872.087 1.337.145-.581 4.169-1.192 8.367-1.773 12.536-.407-.057-.785-.115-1.192-.144.523-4.198 1.076-8.368 1.628-12.537zm27.736 85.96c.494-3.851.843-6.572 1.192-9.294 1.541 4.024 1.337 5.819-1.192 9.294zm-105.186 317.52c-.756-1.622-1.367-2.982-2.384-5.183 2.529 1.477 4.157 2.432 6.25 3.648-1.57.608-2.471.985-3.866 1.535zm-3.082.086c-1.279 1.014-2.181 1.738-3.314 2.635-.727-1.766-1.251-3.098-2.094-5.211 2.094 1.013 3.489 1.679 5.408 2.576zm128.88-349.135c.407.144.814.26 1.221.405-.523 2.693-1.017 5.385-1.54 8.078-.378-.087-.785-.145-1.163-.232.494-2.75.988-5.501 1.482-8.251zm26.98 69.89c-.116-.376-.232-.723-.349-1.1 2.762-.926 5.495-1.824 8.257-2.75.116.347.233.695.349 1.042-2.733.927-5.495 1.882-8.257 2.808zm10.728-39.925c.174.174.349.319.523.492-2.035.811-4.099 1.651-6.134 2.461-.087-.202-.174-.405-.262-.608 1.948-.781 3.925-1.563 5.873-2.345zm223.193-52.838c3.169-1.911 3.169-1.911 3.896 1.535-1.25-.463-2.239-.869-3.896-1.535zm-306.691 4.72c-1.25-3.33-1.25-3.33.873-4.459-.32 1.679-.611 3.069-.873 4.459zm37.97 61.378c-.029-.26-.058-.55-.087-.81 1.337-.406 2.674-.811 4.012-1.216.029.145.058.26.116.405-1.337.521-2.675 1.071-4.041 1.621zm31.777-40.533c-1.832 2.519-1.832 2.519-4.681 2.519 1.715-.926 2.907-1.563 4.681-2.519zm-6.397 63.261c.03.405.03.811.059 1.187-.931-.029-1.832-.029-2.762-.058 0-.289-.029-.55-.029-.839.901-.087 1.802-.203 2.732-.29zM200.465 180.35c-.291-.087-.611-.174-.901-.261.087-.55.058-1.187.29-1.65.262-.55.785-1.013 1.192-1.505.146.086.291.202.437.289-.349 1.042-.698 2.085-1.018 3.127z\" />\n        <path d=\"M313.507 356.699c-2.18-4.372-5.814-7.152-10.233-9.033l.087-.145c3.401 3.011 6.803 6.022 10.205 9.033l-.059.145zM242.743 96.2149c.029-1.0712.029-2.1714.058-3.5322-3.11.6949-3.11 2.5478-3.052 5.4431 1.424-.9844 2.267-1.5635 3.111-2.1425l-.117.2316zM266.233 590.228c-13.897-6.311-27.678-12.218-41.109-18.79-13.461-6.572-26.631-13.781-39.889-20.787-13.199-6.978-25.816-14.882-38.754-22.902.32.782.407 1.795.96 2.259 1.947 1.563 4.07 2.953 6.134 4.4 15.089 10.568 31.312 19.254 47.563 27.795 17.328 9.119 34.743 18.095 52.971 25.362 2.82 1.129 5.524 2.519 8.199 3.966 1.599.869 2.82 1.158 3.925-1.303zM87.9287 332.958c-1.6281 2.924 0 4.285 1.1339 5.819 7.3263 9.757 15.9324 18.298 24.9444 26.462 20.177 18.269 42.33 33.99 64.542 49.654 1.803 1.274 3.547 2.605 5.408 3.763.756.464 1.744.551 3.111.116-.814-.868-1.512-1.882-2.472-2.548-9.972-7.18-20.06-14.244-29.974-21.482-21.834-15.953-42.737-32.948-60.2972-53.649-2.2096-2.663-4.2738-5.414-6.3961-8.135zM70.254 331.829c-1.8606 1.419-2.0351 2.577-.8721 4.111 1.8025 2.432 3.3143 5.038 5.1458 7.47 6.0181 7.962 13.1701 14.824 20.7581 21.309 6.1632 5.24 12.0942 10.77 18.2872 15.953 7.355 6.166 14.885 12.16 22.386 18.153 3.169 2.519 6.367 4.979 9.652 7.354.785.55 1.948.579 3.402.028-.553-.665-1.018-1.505-1.716-1.997-17.589-12.594-34.131-26.434-50.1505-40.91-7.9078-7.122-15.3796-14.621-21.7175-23.162-1.8316-2.519-3.3143-5.298-5.175-8.309zM159.448 381.569c-3.285-2.664-6.454-5.096-9.478-7.673-8.053-6.89-16.135-13.723-23.985-20.816-6.861-6.196-13.577-12.566-20.119-19.109-3.023-3.011-5.436-6.63-8.3145-10.191-2.1223 1.766-.7849 3.532.1745 4.777 2.5 3.156 5.001 6.398 7.995 9.062 14.391 12.971 28.957 25.768 43.435 38.651 2.006 1.795 3.896 3.706 5.96 5.414 1.047.869 2.239 2.403 4.332-.115zM181.456 363.966c-1.744-1.737-2.558-2.982-3.692-3.619-12.124-6.746-22.939-15.287-33.55-24.06-9.914-8.164-18.375-17.69-25.992-27.997-.988-1.331-1.628-3.387-4.07-3.097 3.227 12.768 51.866 55.82 67.304 58.773zM108.369 316.686c.116 3.098 2.006 5.415 3.75 7.76 5.815 7.933 12.792 14.794 20.468 20.845 11.367 8.975 22.938 17.69 34.451 26.463.901.666 2.181.81 3.285 1.216.233-.406.495-.811.727-1.216-1.163-1.014-2.267-2.114-3.518-3.011-7.5-5.443-15.234-10.539-22.473-16.3-10.263-8.165-20.729-16.214-28.753-26.781-1.425-1.853-2.617-3.88-3.954-5.82-.901-1.303-1.861-2.577-2.791-3.879-.407.26-.814.492-1.192.723zM115.113 396.161c-1.105-1.1-2.093-2.316-3.314-3.272-12.9377-9.988-25.2356-20.672-36.0798-32.919-4.4482-5.037-8.3439-10.538-12.5014-15.808-1.0757-1.36-2.2386-2.663-3.9539-4.661-.6978 3.156.6105 4.401 1.6281 5.877 11.6001 16.793 26.5145 30.4 42.039 43.4 2.966 2.49 5.757 5.124 8.722 7.614.669.55 1.687.666 2.559 1.014.291-.435.61-.84.901-1.245zM225.474 338.198c-27.038-6.167-48.232-21.512-68.845-39.723.756 1.448.96 2.345 1.541 2.866 5.117 4.604 9.972 9.584 15.525 13.637 10.466 7.643 21.34 14.766 33.289 19.919 4.303 1.853 8.954 2.982 13.461 4.314 1.54.434 3.198.695 5.029-1.013zM96.0105 391.991c-7.1811-6.225-14.0423-12.537-21.3105-18.385-7.2683-5.819-11.6001-14.447-19.508-19.601 9.3906 15.027 22.4444 26.492 36.5738 36.857 1.0757.81 2.4131 2.605 4.2447 1.129zM347.173 501.054c-19.334-7.788-38.551-15.692-56.925-25.478 5.582 4.227 11.513 7.818 17.909 10.684 6.483 2.895 12.879 5.964 19.421 8.714 6.309 2.664 12.501 5.82 19.595 6.08zM46.5872 363.821c.029.752-.1454 1.332.0872 1.679 7.588 12.507 17.1821 23.191 29.2474 31.587 1.1338.782 2.3549 2.316 4.0411-.087-1.1048-.926-2.1514-1.94-3.3143-2.779-9.5359-6.833-17.9671-14.679-24.0724-24.841-1.3083-2.172-2.3549-5.241-5.989-5.559zM237.771 350.937c2.762 2.663 6.628 2.432 9.914 2.982 13.926 2.229 27.939 2.432 41.719-1.216 3.082-.811 6.019-2.171 8.955-3.416.494-.203.785-.985 1.686-2.172-1.308.29-1.861.319-2.355.521-18.025 7.441-36.574 7.007-55.326 3.59-1.482-.26-2.994-.405-4.477-.637l-.116.348zM66.6181 404.267c.9304-3.562-1.2792-4.256-2.5002-5.385-4.2156-3.851-8.5765-7.528-12.8212-11.321-3.9248-3.532-7.0938-7.585-8.78-12.681-.4943-1.477-1.4246-2.808-2.1805-4.198-.3198.087-.6687.174-.9885.232-.1163.839-.5524 1.766-.3198 2.49 1.4537 4.69 3.5179 9.148 7.0938 12.594 4.3319 4.198 8.8673 8.164 13.3736 12.189 2.1514 1.968 4.4191 3.792 7.1228 6.08zM169.189 340.775c-.698-.84-1.221-1.94-2.122-2.461-12.705-7.615-22.299-18.732-32.911-28.721-.145-.145-.872.318-2.064.811 5.233 6.34 11.367 11.436 17.066 16.937 5.785 5.588 12.588 9.815 19.042 14.505.32-.377.669-.724.989-1.071zM349.732 484.146c-1.657-3.126-4.128-3.387-6.25-4.024-8.577-2.577-17.211-5.009-25.09-9.438-3.809-2.143-7.617-4.285-11.455-6.457 1.977 6.544 31.602 17.893 42.795 19.919zM55.2787 405.715c-3.6923-2.895-7.3845-5.762-11.0477-8.686-3.9249-3.156-8.1695-6.051-10.35-10.828-.9304-2.056-1.7153-4.198-2.6747-6.572-1.7444.26-1.8317 1.708-1.57 3.213.6396 3.967 2.6747 7.354 5.6402 9.902 5.4948 4.69 11.2221 9.091 16.9495 13.521.6396.492 1.6863.405 2.5585.579.1453-.376.3198-.753.4942-1.129zM143.518 592.429c-2.122-1.622-4.157-3.388-6.396-4.836-5.785-3.763-11.28-7.846-15.99-12.941-1.919-2.085-4.216-3.648-7.297-4.604.087.869-.029 1.506.232 1.709 8.112 6.977 15.671 14.649 25.061 20.063 1.483.84 2.791 2.027 4.477.464 0-.029-.087.145-.087.145zM353.191 435.333c-11.513-6.138-24.392-8.685-34.771-16.647-.233.318-.465.666-.669.984 1.861 1.506 3.518 3.503 5.641 4.459 9.041 4.082 18.228 7.904 27.386 11.725.611.29 1.599-.318 2.413-.521zM66.6178 537.767c3.4888 4.198 7.9369 7.441 12.2688 10.712 4.39 3.33 9.0708 6.341 13.6643 9.526 2.1223-1.651.5234-2.432-.6396-3.301-5.2622-3.88-10.6116-7.672-15.7866-11.668-2.2386-1.737-4.1284-3.937-6.3088-5.761-.6396-.521-1.7444-.464-2.6457-.666-.1744.376-.3489.753-.5524 1.158zM316.502 402.849c8.228 8.946 19.857 10.799 30.352 15.026.727.29 1.745-.203 2.704-.782-10.844-5.298-23.055-7.296-33.056-14.244zM142.528 308.957c8.227 8.222 15.379 15.981 25.235 21.28.204-1.332.407-1.853.291-1.94-8.344-5.704-15.729-12.508-22.91-19.543-.203-.203-.901.058-2.616.203zM45.4544 411.911c-6.9194-7.094-15.7866-12.305-19.4789-22.496-.2616.752-.9303 1.708-.6978 2.258 1.0757 2.635 1.8607 5.733 3.8086 7.585 4.5645 4.401 9.7103 8.194 14.6818 12.189.407.348 1.1048.319 1.6863.464zM315.222 389.009c1.948 4.777 6.483 6.254 10.728 7.933 12.181 4.806 12.211 4.719 15.816 3.416-9.1-4.227-18.752-5.645-26.544-11.349zM337.493 387.678c-8.286-4.864-17.677-5.646-25.09-12.508.756 4.054 3.314 5.125 5.64 6.457 8.431 4.806 16.019 7.383 19.45 6.051zM22.747 400.011c-.2035 7.122 6.9775 15.229 14.5365 16.647-6.6286-4.024-10.0883-10.712-14.5365-16.647zM169.682 321.059c-5.611-5.154-10.844-9.989-16.368-15.055-.203.723-.756 1.679-.494 2.026 4.157 5.53 9.39 9.96 15.234 13.637.233.173.843-.29 1.628-.608zM34.1159 425.605c-4.0702-4.372-7.8787-8.425-11.7455-12.566-1.221 4.025 5.146 10.944 11.7455 12.566zM218.119 482.584c3.372 4.516 9.129 5.038 13.344 8.165.291.202 1.105-.319 2.239-.695-4.739-4.314-10.466-5.212-15.583-7.47zM109.735 605.139c7.646 4.719 10.699 6.051 14.042 6.138-2.82-3.851-10.67-7.267-14.042-6.138zM65.1638 480.556c-.1744-3.706-3.7795-4.893-5.8146-7.238-.1453-.145-1.3373.261-1.628.666-.2908.434-.3489 1.477-.0582 1.795 2.0642 1.998 4.2447 3.88 6.367 5.791.407-.348.7559-.695 1.1338-1.014z\" />\n        <path d=\"M237.916 350.589c-6.367-2.026-12.734-4.053-19.217-6.109 3.401 3.069 12.239 6.022 19.101 6.428l.116-.319zM17.3408 432.323c.6105 4.313 3.5178 6.398 7.1519 7.73-1.6862-3.214-3.8958-5.964-7.1519-7.73zM19.5798 424.794c1.5408 4.719 4.6807 7.296 9.3033 7.701-3.605-2.982-6.4542-5.356-9.3033-7.701zM75.4861 595.642c3.1981 3.59 4.9715 4.806 7.7044 5.385-1.3083-3.503-3.8377-5.414-7.7044-5.385zM23.2119 447.348c-1.8606-2.316-3.4596-4.893-6.5414-6.254.1163 4.053 1.2502 5.211 6.5414 6.254zM77.1131 577.402c2.9655 2.113 5.4657 3.879 7.966 5.646-1.0757-2.983-2.5875-5.443-5.4657-6.573-.4942-.231-1.3374.464-2.5003.927zM84.7324 511.014c.0291.781-.2326 1.766.1163 2.345 1.2792 2.084 3.1107 3.532 6.1634 3.532-1.4827-1.824-2.9654-3.648-4.4482-5.472-.6105-.145-1.221-.289-1.8315-.405zM49.8442 544.657c1.1629 3.677 4.9715 4.343 7.5008 6.456-1.7153-3.069-4.1283-5.298-7.559-6.311 0-.029.0582-.145.0582-.145zM68.9746 418.57c-1.6281-1.216-3.2271-2.432-5.4948-4.141.4652 3.822 2.791 4.285 4.6226 5.299.2617-.377.5524-.753.8722-1.158zM276.701 427.314c1.861.579 2.704 1.1 3.198.897.524-.203.727-1.187 1.076-1.795-.785-.405-1.599-1.1-2.384-1.071-.523 0-1.017 1.013-1.89 1.969zM35.8594 440.631c1.4246-.695 1.9189-1.708.9013-3.011-.2326-.289-1.3955-.318-1.599-.058-.9594 1.158-.8722 2.288.6977 3.069zM74.0621 568.658c2.0351-1.129 2.2968-2.519.9594-4.401-2.3549 1.737-2.3549 1.737-.9594 4.401zM265.247 364.197c1.134.463 1.919 1.071 2.471.897.523-.173.814-1.129 1.192-1.737-.64-.405-1.308-1.158-1.89-1.1-.552.087-.988 1.042-1.773 1.94zM93.2798 580.732c.9885.145 1.8898.492 2.0933.26.407-.492.6396-1.303.6105-1.968 0-.232-1.3373-.753-1.5118-.551-.5233.464-.7268 1.245-1.192 2.259zM293.301 362.083c-.145 1.043-.465 1.824-.261 2.403.116.348 1.017.435 1.57.637.232-.694.639-1.389.581-2.055-.029-.319-.959-.55-1.89-.985zM96.3317 607.599c-.3779 1.042-.7849 1.766-.7849 2.461 0 .232 1.3664.811 1.5699.608.5234-.463.8722-1.245.9595-1.94.029-.231-.9013-.608-1.7445-1.129zM237.654 371.232c-.175 1.1-.465 1.853-.32 2.519.058.29 1.047.377 1.599.579.203-.666.61-1.39.552-2.026-.087-.348-.959-.58-1.831-1.072zM279.608 383.335c.087.926.204 1.853.291 2.779.698-.231 1.395-.434 2.122-.666-.407-.81-.814-1.65-1.221-2.46-.407.115-.785.231-1.192.347zM104.82 584.119c-.262 1.158-.524 1.853-.553 2.548 0 .145 1.047.608 1.163.463.494-.492.931-1.129 1.134-1.795.058-.145-.872-.608-1.744-1.216zM210.936 361.128c-.175 1.158-.465 1.94-.32 2.606.058.26 1.425.608 1.57.434.407-.492.698-1.303.61-1.911-.087-.376-.959-.608-1.86-1.129zM39.1444 475.779c1.3373-.029 2.1514.174 2.5874-.145.5524-.376.785-1.187 1.163-1.824-.5815-.231-1.2211-.752-1.7153-.608-.4652.145-.7559.898-2.0351 2.577zM226.781 411.158c.552.058 1.366.319 1.599.087.436-.463.726-1.274.668-1.911 0-.231-1.192-.753-1.628-.579-.668.29-1.134 1.014-1.657 1.564.32.289.669.55 1.018.839zM304.785 397.435c-.029.724-.262 1.534 0 2.114.174.376 1.483.694 1.657.521.465-.521.902-1.419.756-2.027-.174-.637-1.047-1.1-1.628-1.621-.262.347-.523.666-.785 1.013zM76.1542 513.186c-.1163.926-.436 1.708-.1744 2.084.2617.405 1.0757.405 1.6571.608.2035-.666.6105-1.332.5233-1.969 0-.289-1.0466-.405-2.006-.723zM96.9695 542.485c.5815-.636 1.192-1.244 1.6862-1.939.0582-.087-.5814-.637-.9012-.985-.6687.666-1.3374 1.361-2.006 2.027.407.318.814.608 1.221.897zM103.134 572.016c.058-1.1.32-1.853.058-2.229-.29-.405-1.104-.434-1.657-.637-.145.579-.523 1.274-.348 1.737.174.406.959.579 1.947 1.129zM77.871 589.533c.3198-.724.5815-1.245.814-1.795-.5233-.232-1.0757-.493-1.599-.724-.2035.579-.5233 1.129-.5814 1.708 0 .174.6977.434 1.3664.811zM93.86 594.542c-2.9654.289-2.9654.289-1.6862 3.04.6105-1.101 1.0756-1.94 1.6862-3.04zM58.798 522.48c1.2501.202 2.006.579 2.3258.347.4361-.318.6688-1.071.756-1.65.029-.174-.9013-.753-1.0467-.637-.6105.376-1.0466.955-2.0351 1.94zM104.415 598.19c1.163.318 1.831.753 2.268.579.465-.203.697-.926 1.017-1.448-.523-.231-1.105-.723-1.599-.665-.465.057-.814.694-1.686 1.534zM82.7245 456.469c-.2035-1.1-.4361-2.23-.8432-4.256-1.2792 2.229-1.8315 3.474-.3488 4.603.407-.116.7849-.232 1.192-.347zM82.2885 619.151c1.1629.145 1.8607.464 2.2095.232.4361-.289.785-1.071.7269-1.563-.0291-.319-1.1048-.869-1.3665-.724-.5233.318-.814 1.013-1.5699 2.055zM85.6604 564.345c.6105-.637 1.2501-1.274 1.8606-1.911-.4942-.348-.9594-.695-1.4536-1.072-.4652.724-.9594 1.448-1.4245 2.143.3198.289.6686.579 1.0175.84zM206.868 339.269c-1.366-.521-2.587-.984-3.808-1.476-.204.463-.378.955-.582 1.418 1.221.232 2.442.464 3.692.666.117.029.32-.26.698-.608zM71.2116 552.995c.3198-1.216.7268-1.882.5524-2.345-.1163-.377-.9885-.492-1.5118-.724-.1454.434-.5233.898-.4361 1.245.2035.521.6687.898 1.3955 1.824zM300.045 143.697c-1.686.144-2.384-.029-2.849.26-4.303 2.519-22.793 20.296-26.602 25.797 5.146-1.824 7.327-5.704 10.408-8.368 3.169-2.75 6.367-5.443 9.362-8.367 2.936-2.895 6.919-4.835 9.681-9.322zM309.699 126.267c2.18-1.042 3.692-1.332 4.593-2.258 2.326-2.432 6.135-3.243 7.908-6.775-4.041.232-9.448 4.025-12.501 9.033zM220.617 226.761c2.965-3.243 3.198-7.731 5.582-12.16-3.663.723-4.012 3.213-4.826 5.124-.901 2.056-1.483 4.256-2.181 6.399.495.202.96.434 1.425.637zM365.025 85.7335c4.477-.9265 7.966-3.4453 10.931-6.7169-4.564.7238-7.646 3.9085-10.931 6.7169zM252.772 188.399c4.914-1.216 8.839-6.63 8.315-11.176-2.849 3.793-5.262 7.036-8.315 11.176zM325.891 258.115c.988-.405 2.006-.723 2.965-1.187 12.269-6.195 22.939-14.736 33.754-23.046 6.279-4.806 12.298-9.959 18.49-14.852 9.798-7.788 18.345-16.821 26.864-25.884 8.169-8.714 16.484-17.284 24.712-25.97 2.384-2.519 4.622-5.182 6.919-7.759-.233-.261-.465-.492-.698-.753-.698.464-1.483.811-2.064 1.39-14.246 14.795-28.288 29.763-42.766 44.326-6.135 6.167-13.054 11.61-19.741 17.227-13.199 11.001-26.66 21.714-41.4 30.631-2.558 1.564-5.117 3.098-7.675 4.633.203.405.407.839.64 1.244zM318.769 265.817c-5.233.145-8.547 3.908-12.908 5.704.668 2.229 2.035 1.823 3.169 1.071 3.314-2.172 6.512-4.488 9.739-6.775zM403.806 210.779c-3.169 2.751-6.338 5.501-9.681 8.396 3.343.898 5.146-.463 10.408-7.614-.262-.261-.494-.521-.727-.782zM338.596 142.162c-4.593 2.664-8.78 4.72-12.559 7.325-9.769 6.717-18.113 15.084-26.224 23.654-5.204 5.501-10.641 10.8-16.078 16.04-8.285 7.962-13.49 18.037-19.391 27.649-.204.348-.029.927.029 1.39 0 .116.203.203.872.84.843-1.129 1.802-2.143 2.442-3.301 4.187-7.73 8.635-15.287 14.566-21.801 3.866-4.227 8.053-8.165 12.123-12.189 7.53-7.47 14.769-15.258 22.706-22.235 5.117-4.517 11.222-7.991 17.008-11.726 1.948-1.274 4.157-2.056 4.506-5.646zM255.013 232.494c-2.18 1.65-2.907 3.04-2.18 5.356 2.704-.869 2.762-2.548 2.18-5.356zM298.855 73.5161c3.576.0579 4.506-.8975 6.745-6.8617-3.722 1.216-5.088 3.9955-6.745 6.8617zM214.629 135.474c0-1.448.029-2.895.029-4.661-3.256.666-2.588 3.879-4.129 5.443 2.21 2.403 2.791-.724 4.158-.956l-.058.174zM219.309 151.63c.727-2.259 2.355-3.735-.349-5.501-1.163 1.766-2.529 3.126.349 5.501zM324.698 184.172c-3.634 1.129-6.454 3.619-8.838 6.312-9.42 10.77-19.304 21.135-27.27 33.063-7.094 10.626-14.043 21.367-21.107 31.992-1.512 2.288-3.286 4.401-5.117 6.804 2.384 1.187 3.314.087 4.128-1.245 2.849-4.574 5.698-9.149 8.606-13.694 3.866-6.08 7.617-12.247 11.774-18.153 4.158-5.935 8.432-11.784 13.141-17.285 7.734-9.062 14.886-18.703 24.596-25.941.378-.29.64-.753.93-1.129-.29-.203-.581-.463-.843-.724zM340.254 168.943c-2.21 1.94-3.896 3.417-5.815 5.096 3.634.984 6.6-1.506 5.815-5.096zM455.062 231.422c3.343-.174 5.698-.319 8.547-.464-2.878-3.184-6.076-3.069-8.547.464zM400.201 113.904c13.374-8.078 25.294-18.5585 39.743-24.9859-1.105-1.9687-2.5-1.216-3.547-.6369-4.128 2.2872-8.286 4.5455-12.211 7.0933-5.756 3.7638-11.338 7.8465-17.036 11.6675-1.948 1.303-4.158 2.23-6.106 3.503-.756.522-1.192 1.564-1.744 2.346.291.376.611.694.901 1.013zM444.276 85.5027c1.105.1158 1.832.4343 2.268.1737.349-.2026.61-1.216.407-1.5344-.233-.3475-1.134-.5791-1.57-.4343-.407.1447-.581.8975-1.105 1.795z\" />\n      </g>\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 509 / 718,\n  svg: RadishLarge,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fresh-and-bright/cta.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Heart', 'sticker name', 'web-stories');\n\nfunction HeartCta({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 60 60\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <circle cx=\"30\" cy=\"30\" r=\"30\" fill=\"#fff\" fillOpacity=\".5\" />\n      <path\n        d=\"M44.5424 28.0704C43.0928 32.0251 29.9933 41.999 29.9933 41.999s-13.0994-9.9739-14.5491-13.9286c-1.4496-3.9548.7644-8.2826 4.9552-9.6506 3.7163-1.2187 7.7489.2985 9.6203 3.4076 1.845-3.1091 5.8776-4.6263 9.594-3.4076 4.1907 1.368 6.4047 5.6958 4.9287 9.6506z\"\n        fill=\"#F3D9E1\"\n        stroke=\"#28292B\"\n        strokeWidth=\"1.5\"\n        strokeMiterlimit=\"10\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 60 / 60,\n  svg: HeartCta,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fresh-and-bright/heart.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Heart', 'sticker name', 'web-stories');\n\nfunction BeautyHeart({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 62 54\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M27.9885 51C27.3612 51.7788 27.3611 51.7787 27.3609 51.7785L27.36 51.7778L27.3567 51.7752L27.3439 51.7649L27.2943 51.7248C27.2506 51.6894 27.1861 51.6372 27.102 51.5688C26.9339 51.4321 26.6874 51.231 26.3731 50.9728C25.7445 50.4563 24.8445 49.711 23.7569 48.7942C21.5824 46.9611 18.6549 44.4396 15.6467 41.6889C12.6412 38.9407 9.54187 35.9517 7.03007 33.1851C5.77429 31.8019 4.65477 30.4627 3.76408 29.2281C2.8818 28.0052 2.1864 26.834 1.82516 25.7916C-0.867927 18.0208 3.24427 9.51561 11.0319 6.82644C17.4039 4.61654 24.2738 6.98478 28.0292 12.1671C31.7503 6.9824 38.6214 4.61781 44.9901 6.82621C52.7769 9.51469 56.8923 18.0204 54.1508 25.7943C53.7893 26.8359 53.0944 28.0063 52.2128 29.2281C51.3222 30.4627 50.2026 31.8019 48.9469 33.1851C46.4351 35.9517 43.3358 38.9407 40.3302 41.6889C37.322 44.4396 34.3945 46.9611 32.22 48.7942C31.1324 49.711 30.2324 50.4563 29.6038 50.9728C29.2895 51.231 29.0431 51.4321 28.8749 51.5688C28.7908 51.6372 28.7263 51.6894 28.6826 51.7248L28.633 51.7649L28.6202 51.7752L28.6169 51.7778L28.616 51.7785C28.6158 51.7787 28.6157 51.7788 27.9885 51ZM27.9885 51L27.3612 51.7788L27.9885 52.284L28.6157 51.7788L27.9885 51Z\"\n        fill=\"#28292B\"\n        stroke=\"#28292B\"\n        strokeWidth=\"2\"\n        strokeMiterlimit=\"10\"\n      />\n      <path\n        d=\"M33.9885 46C33.3612 46.7788 33.3611 46.7787 33.3609 46.7785L33.36 46.7778L33.3567 46.7752L33.3439 46.7649L33.2943 46.7248C33.2506 46.6894 33.1861 46.6372 33.102 46.5688C32.9339 46.4321 32.6874 46.231 32.3731 45.9728C31.7445 45.4563 30.8445 44.711 29.7569 43.7942C27.5824 41.9611 24.6549 39.4396 21.6467 36.6889C18.6412 33.9407 15.5419 30.9517 13.0301 28.1851C11.7743 26.8019 10.6548 25.4627 9.76408 24.2281C8.8818 23.0052 8.1864 21.834 7.82516 20.7916C5.13207 13.0208 9.24427 4.51561 17.0319 1.82644C23.4039 -0.383456 30.2738 1.98478 34.0292 7.16706C37.7503 1.9824 44.6214 -0.382192 50.9901 1.82621C58.7769 4.51469 62.8923 13.0204 60.1508 20.7943C59.7893 21.8359 59.0944 23.0063 58.2128 24.2281C57.3222 25.4627 56.2026 26.8019 54.9469 28.1851C52.4351 30.9517 49.3358 33.9407 46.3302 36.6889C43.322 39.4396 40.3945 41.9611 38.22 43.7942C37.1324 44.711 36.2324 45.4563 35.6038 45.9728C35.2895 46.231 35.0431 46.4321 34.8749 46.5688C34.7908 46.6372 34.7263 46.6894 34.6826 46.7248L34.633 46.7649L34.6202 46.7752L34.6169 46.7778L34.616 46.7785C34.6158 46.7787 34.6157 46.7788 33.9885 46ZM33.9885 46L33.3612 46.7788L33.9885 47.284L34.6157 46.7788L33.9885 46Z\"\n        fill=\"#28292B\"\n        stroke=\"#28292B\"\n        strokeWidth=\"2\"\n        strokeMiterlimit=\"10\"\n      />\n      <path\n        d=\"M59.2069 20.4641C56.6942 27.7145 33.9885 46 33.9885 46C33.9885 46 11.2827 27.7145 8.77002 20.4641C6.25732 13.2138 10.0949 5.27944 17.3589 2.77145C23.8006 0.537066 30.7905 3.31865 34.0341 9.01862C37.2321 3.31865 44.222 0.537066 50.6637 2.77145C57.9277 5.27944 61.7653 13.2138 59.2069 20.4641Z\"\n        fill=\"#F3D9E1\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 62 / 54,\n  svg: BeautyHeart,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/fresh-and-bright/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as beautyCta } from './cta';\nimport { default as beautyHeart } from './heart';\n\nexport { beautyCta, beautyHeart };\n"
  },
  {
    "path": "packages/stickers/src/hawaii-travel-packing-list/cartBag.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cart Bag', 'sticker name', 'web-stories');\n\nfunction CartBag({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 31\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.72728 1.38579C4.98481 1.04241 5.38898 0.840332 5.81819 0.840332H22.1818C22.611 0.840332 23.0152 1.04241 23.2727 1.38579L27.3637 6.84033C27.5407 7.07637 27.6364 7.36346 27.6364 7.65851V26.7494C27.6364 27.8344 27.2054 28.8749 26.4382 29.6421C25.671 30.4093 24.6304 30.8403 23.5455 30.8403H4.45456C3.36958 30.8403 2.32904 30.4093 1.56185 29.6421C0.794652 28.8749 0.363647 27.8344 0.363647 26.7494V7.65851C0.363647 7.36346 0.459345 7.07637 0.636375 6.84033L4.72728 1.38579ZM6.50001 3.56761L4.45456 6.29488H23.5455L21.5 3.56761H6.50001ZM24.9091 9.02215H3.09092V26.7494C3.09092 27.1111 3.23459 27.4579 3.49032 27.7137C3.74605 27.9694 4.0929 28.1131 4.45456 28.1131H23.5455C23.9071 28.1131 24.254 27.9694 24.5097 27.7137C24.7654 27.4579 24.9091 27.1111 24.9091 26.7494V9.02215ZM8.54491 11.7489C9.29802 11.7489 9.90854 12.3594 9.90854 13.1125C9.90854 14.1975 10.3395 15.238 11.1067 16.0052C11.8739 16.7724 12.9145 17.2034 13.9995 17.2034C15.0844 17.2034 16.125 16.7724 16.8922 16.0052C17.6594 15.238 18.0904 14.1975 18.0904 13.1125C18.0904 12.3594 18.7009 11.7489 19.454 11.7489C20.2071 11.7489 20.8176 12.3594 20.8176 13.1125C20.8176 14.9208 20.0993 16.655 18.8206 17.9337C17.542 19.2123 15.8077 19.9307 13.9995 19.9307C12.1912 19.9307 10.4569 19.2123 9.17827 17.9337C7.89961 16.655 7.18127 14.9208 7.18127 13.1125C7.18127 12.3594 7.79179 11.7489 8.54491 11.7489Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 31,\n  svg: CartBag,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/hawaii-travel-packing-list/greenLeaf.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Leaf', 'sticker name', 'web-stories');\n\nfunction GreenLeaf({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M2.20444 47.4851C2.246 48.4718 2.36837 49.5956 2.47611 49.9824C2.77764 51.0647 3.49895 51.1332 4.02676 50.1296C4.1611 49.8741 4.51855 49.4695 4.82106 49.2304C5.12358 48.9913 5.4032 48.7347 5.44245 48.66C5.538 48.4783 7.22562 47.3276 9.28055 46.043C10.9907 44.9739 11.3058 44.7108 13.4251 42.5825C15.6134 40.385 19.6439 33.804 20.6967 30.7095C21.7183 27.7066 21.7171 27.7116 21.8572 25.7546C22.0013 23.741 21.0913 20.4832 20.2633 20.0478C20.0925 19.958 19.9619 19.5213 20.0537 19.3467C20.1367 19.189 20.844 19.5757 21.2309 19.9901C21.4045 20.1761 21.7581 20.5451 22.0166 20.8101C22.275 21.0751 22.6187 21.5681 22.7804 21.9057C23.7123 23.8524 25.6696 18.5304 25.0409 15.7592C25.0062 15.6061 24.9843 15.3426 24.9925 15.1736C25.0006 15.0047 24.7672 14.4216 24.4736 13.8779C23.6748 12.3984 23.7951 11.4981 24.6535 12.5319C24.8332 12.7484 25.0775 12.9767 25.1966 13.0393C25.3156 13.1019 25.5696 13.4048 25.7609 13.7124C26.2818 14.5496 26.746 14.1907 27.0357 12.7269C27.5488 10.1352 26.5963 8.01553 24.3119 6.66462L22.9019 5.83085L23.7122 4.3179C24.1578 3.48578 24.7556 2.52039 25.0408 2.1727C25.61 1.47849 25.6713 1.10074 25.2506 0.879525C24.766 0.624675 23.8964 1.61153 22.6123 3.87377L21.706 5.47044L20.5594 5.5382C17.9079 5.6949 15.5267 7.41923 12.5207 11.3595C12.0897 11.9245 11.6334 12.4823 10.6722 13.6191C10.1725 14.2099 9.47927 15.1087 8.64537 16.2467C7.20285 18.2153 3.35792 24.8882 3.13303 25.8131C3.05647 26.1283 2.90082 26.7425 2.78707 27.178C2.53245 28.1539 2.63109 28.2882 3.6191 28.3098C4.04958 28.3192 4.74703 28.3348 5.16914 28.3442C6.86242 28.3824 6.82354 29.0997 5.11063 29.424C2.98651 29.8261 2.71522 30.0051 1.9144 31.5332C0.983667 33.3089 0.602202 35.5369 0.963716 37.0843C1.05269 37.465 1.14476 38.0775 1.16842 38.4455C1.19208 38.8134 1.31546 39.5431 1.44259 40.067C1.56971 40.5909 1.69133 41.3197 1.71272 41.6864C1.73425 42.0532 1.76842 42.4036 1.7888 42.4651C1.80918 42.5266 1.84223 42.8764 1.86224 43.2424C1.88225 43.6084 1.9153 43.9582 1.93567 44.0197C1.95605 44.0812 1.9891 44.431 2.00911 44.797C2.02912 45.163 2.06417 45.5138 2.08706 45.5766C2.10996 45.6395 2.16275 46.4982 2.20444 47.4851Z\"\n        fill=\"#4B8C74\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 51,\n  svg: GreenLeaf,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/hawaii-travel-packing-list/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as travelBag } from './cartBag';\nimport { default as travelPalmLeaf } from './palmLeaf';\nimport { default as travelGreenLeaf } from './greenLeaf';\nimport { default as palmTree } from './palmTree';\n\nexport { travelBag, travelPalmLeaf, travelGreenLeaf, palmTree };\n"
  },
  {
    "path": "packages/stickers/src/hawaii-travel-packing-list/palmLeaf.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Palm Leaf', 'sticker name', 'web-stories');\n\nfunction PalmLeaf({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 36 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.2413 20.7409C15.4811 18.6829 11.9493 20.9522 8.84331 21.6855C11.6552 21.4174 15.3998 19.3236 17.7692 21.2407C17.8242 21.2923 17.8918 21.3223 17.9603 21.3319C17.8799 21.4463 17.7982 21.5617 17.7179 21.6765C17.6916 21.642 17.6599 21.6111 17.6211 21.5872C13.9421 19.7521 11.2998 21.1694 7.7223 23.1453L7.72256 23.1458C11.5479 21.867 13.5843 20.1507 17.264 22.1744C17.2889 22.1907 17.3167 22.2022 17.3447 22.2104C17.1738 22.455 17.0045 22.6994 16.8356 22.9446C16.801 22.896 16.7529 22.8557 16.6942 22.8298C13.4213 21.1051 11.5428 22.3502 8.05944 23.8105C11.8341 23.0361 13.0895 21.515 16.4168 23.4585C16.4343 23.4663 16.4527 23.4724 16.4705 23.4772C16.3406 23.6682 16.2109 23.8595 16.0813 24.0512C16.0577 24.0227 16.0289 23.9979 15.9953 23.9776C12.3371 22.1203 9.7415 23.4964 6.167 25.4674L6.16726 25.4679C9.995 24.1942 11.9783 22.5167 15.6381 24.5647C15.6621 24.5792 15.6865 24.5907 15.7127 24.5986C15.6083 24.7548 15.504 24.9113 15.3997 25.068C15.3733 25.052 15.3435 25.04 15.312 25.0318C12.389 24.0113 10.7269 25.0013 7.65093 25.8071L7.65139 25.8081C11.091 25.7436 11.9368 24.3816 15.0163 25.6472C14.8934 25.8345 14.7705 26.0219 14.6478 26.2098C14.6244 26.174 14.594 26.142 14.5562 26.1165C11.5001 24.2765 9.03441 26.9445 5.47938 27.6956C8.09789 27.5074 11.723 25.1853 14.1688 26.6833C14.2101 26.7127 14.2568 26.7312 14.3053 26.7387C14.184 26.9259 14.0642 27.1126 13.9446 27.2996C13.9166 27.2465 13.8744 27.2002 13.8192 27.167C11.1789 26.0574 9.42005 27.9393 6.5997 28.3576C9.19989 28.4894 11.142 26.6142 13.4642 27.7551C13.5146 27.7853 13.5689 27.8017 13.6238 27.8044C13.5429 27.9326 13.4618 28.0607 13.3809 28.1891C13.3328 28.1339 13.2659 28.094 13.188 28.0792C9.63846 27.1045 8.09709 28.3632 4.57001 29.7814L4.57074 29.783C8.54034 29.0369 9.25694 27.523 13.0337 28.7454C12.9074 28.948 12.7827 29.1501 12.658 29.3524C12.636 29.2936 12.5975 29.2404 12.5428 29.2008C10.3748 28.0149 7.26112 30.0348 4.90715 30.4541C6.95636 30.4919 10.3146 28.6301 12.1332 29.7533C12.206 29.8059 12.2905 29.8274 12.3731 29.8188C12.2519 30.0174 12.1323 30.2157 12.0127 30.414C11.985 30.3278 11.9228 30.2532 11.8343 30.2116C8.38724 28.9643 6.85572 30.7873 3.38952 31.9177L3.38959 31.9178C6.85215 31.39 8.32394 29.4866 11.5414 30.833C11.6064 30.8649 11.6778 30.8731 11.7451 30.8614C11.6232 31.066 11.503 31.2704 11.3827 31.4748C11.3656 31.3779 11.3071 31.2889 11.2165 31.2353C9.22555 30.406 6.21118 32.4271 3.94061 32.2853L3.94081 32.2857C6.34416 32.9618 9.10647 30.9724 10.8714 31.8298C10.9618 31.8829 11.067 31.8894 11.1591 31.8563C11.0701 32.0085 10.9825 32.16 10.8951 32.3118C10.865 32.2767 10.8257 32.2478 10.7814 32.2269C8.60491 31.5171 7.17734 33.576 4.94465 33.5648L2.39955 33.3125L4.92464 33.9821C6.97115 34.2312 8.54788 32.1015 10.4885 32.8482C10.5152 32.861 10.5435 32.8697 10.5719 32.8749C10.4886 33.0207 10.4068 33.1659 10.3237 33.3119C10.2857 33.2673 10.2363 33.2316 10.1779 33.2103C8.11184 32.9713 5.52135 34.6955 3.46255 34.7831C5.72655 35.2702 7.84733 33.4854 9.94781 33.8587C9.96842 33.8658 9.98823 33.8712 10.0087 33.8743C9.88023 34.1058 9.7532 34.3367 9.62767 34.5671C6.72533 33.4451 5.33247 35.5791 2.17245 36.4277L2.17311 36.4292C5.25997 36.1451 6.73923 34.0144 9.29956 35.1721C9.22012 35.3187 9.14223 35.4649 9.06565 35.6101C7.23929 34.781 5.04372 36.303 3.13151 36.846C4.85869 36.8129 7.20489 35.3732 8.73106 36.2087L8.7451 36.2165C8.68189 36.3383 8.61867 36.46 8.55553 36.5819L8.55357 36.5814C5.70398 35.3487 4.3441 37.5016 1.143 38.7221L1.1421 38.7239C4.20123 38.1215 5.69824 35.928 8.24242 37.1932C8.18879 37.2982 8.13653 37.4024 8.08433 37.5067C8.0695 37.4971 8.0548 37.4878 8.039 37.4799C6.23051 36.7942 4.10242 38.4284 2.32511 39.0871C3.88844 38.9094 6.3304 37.4408 7.7244 38.0916C7.74404 38.1004 7.76172 38.1087 7.78154 38.1141L7.671 38.3394C7.62384 38.2899 7.56062 38.2543 7.48825 38.2402C4.7369 37.8378 3.41942 39.9775 0.955256 41.4131L0.955982 41.4147C3.4827 40.5263 4.90386 38.3935 7.35674 38.9145C7.36801 38.9164 7.37914 38.918 7.39008 38.9192C7.31756 39.0695 7.24646 39.2191 7.17544 39.3689C7.12399 39.3213 7.05581 39.29 6.98094 39.2817C4.86962 39.1284 2.9858 40.6615 1.4452 42.1541L1.44566 42.1551C3.52402 41.2372 4.53239 39.6051 6.89793 39.9635C6.85361 40.0587 6.81064 40.153 6.76775 40.2475C6.71006 40.2015 6.63792 40.1728 6.55907 40.1708C3.46264 40.3069 2.34448 42.4356 0.0775757 44.6422L0.0784341 44.6441C2.57868 42.9682 3.69547 40.8177 6.49211 40.8574C6.43601 40.9833 6.38006 41.1095 6.32546 41.2348C6.26776 41.1663 6.18528 41.119 6.08959 41.1106C3.70496 41.1528 1.46927 44.1459 0.362789 46.2213C1.89075 44.6677 3.72412 41.6998 6.03062 41.7957C6.04846 41.7969 6.0644 41.7976 6.08124 41.7966C6.03973 41.8941 5.99822 41.9916 5.95806 42.0883C5.86312 41.9953 5.71926 41.9614 5.58774 42.0141C3.10676 43.2786 1.97875 46.6442 1.21227 49.3536L1.21233 49.3537C2.07516 47.5605 3.58064 44.0896 5.14995 43.0336C3.72948 45.5274 2.9863 47.7253 3.50387 50.8403L3.50549 50.8401C3.52106 48.7729 4.42487 46.2107 4.80766 45.1172L5.33832 43.9951C5.49108 43.7299 5.67113 43.4414 5.88563 43.1188C7.19658 44.691 5.59508 48.5085 5.59077 50.5364C6.09387 48.0365 7.87372 44.4624 6.24178 42.4845C6.19954 42.4418 6.14829 42.4134 6.09432 42.3978C6.16285 42.2539 6.2315 42.1102 6.30023 41.9667C7.74286 44.2206 7.05049 46.903 6.29743 49.4578C7.76828 47.1067 8.10254 43.7662 6.7902 41.4607C6.74313 41.3964 6.67805 41.353 6.60643 41.333C6.69366 41.1546 6.78102 40.9765 6.86988 40.7979C8.5664 43.0689 7.16771 45.0668 7.27462 48.0878L7.27644 48.088C7.73712 44.9572 9.11241 42.9612 7.40917 40.3723C7.34395 40.2874 7.24788 40.2408 7.14903 40.2368L7.28875 39.9584C7.29766 39.9964 7.31319 40.0337 7.33462 40.0688C8.83854 41.9984 8.16907 43.6741 8.33972 46.0316L8.34128 46.0312C8.93367 43.8929 9.11982 41.5018 7.91391 39.6997C7.82233 39.5541 7.63886 39.502 7.48642 39.5694L7.63606 39.275C7.65081 39.2919 7.66698 39.3082 7.68568 39.3224C9.51356 40.7278 8.48504 43.5259 9.22053 45.8201L9.22203 45.8196C8.88447 43.0713 10.0937 40.5104 8.11436 38.7849C8.05767 38.741 7.99271 38.7167 7.92775 38.711C7.99975 38.5709 8.07324 38.4302 8.14674 38.2895C8.16003 38.3033 8.17456 38.3159 8.19038 38.3277C9.87253 39.8599 9.05035 42.4788 9.90733 44.5712C9.47322 42.0673 10.3944 39.6287 8.59768 37.774C8.55296 37.741 8.50352 37.7202 8.45122 37.712C8.49666 37.6267 8.54202 37.5413 8.58751 37.4562L8.5994 37.4631C10.4391 38.8231 9.26908 41.8507 10.7198 43.9611C9.80728 41.595 10.8759 38.479 8.95913 36.8778C8.9443 36.8682 8.92843 36.8601 8.91154 36.8535L9.04742 36.6043C9.05979 36.6161 9.07483 36.6261 9.08972 36.6358C10.5179 37.6303 10.3231 40.864 11.064 42.4247C10.6963 40.4613 11.0295 37.3245 9.45435 36.0536C9.42743 36.0366 9.39898 36.0237 9.36913 36.0154C9.42976 35.9068 9.48903 35.799 9.54837 35.6914C9.56098 35.6999 9.57359 35.7084 9.58737 35.7158C11.5643 36.7993 10.856 40.0164 11.9742 42.0257C11.0869 39.437 12.1627 36.5201 9.92104 35.1152C9.9074 35.1082 9.89402 35.1017 9.88097 35.096C9.98822 34.9047 10.097 34.7131 10.2045 34.5223C12.3777 37.2883 11.048 37.342 13.4301 40.3014C11.5546 36.9394 12.7481 37.0668 10.6608 33.9997C10.6265 33.9667 10.5875 33.9423 10.5455 33.9264C10.5996 33.8336 10.6524 33.7417 10.7051 33.6497C11.946 34.4002 12.5786 38.7938 13.8121 40.1947C12.6972 38.406 12.6708 34.1659 11.0501 33.0587C11.1361 32.9114 11.2235 32.7634 11.3097 32.6163C12.8132 33.8111 12.2535 37.136 13.9064 38.9606L13.9077 38.9598C12.7773 37.0065 13.2621 33.4335 11.6613 32.0248C11.7534 31.8717 11.844 31.7193 11.9361 31.5665C14.6346 33.566 13.6218 35.7502 14.9298 38.9489C14.1282 35.4295 15.052 33.24 12.2909 30.9817C12.3874 30.8234 12.4855 30.6647 12.5823 30.5069C14.3873 31.6383 14.1945 35.4531 15.1384 37.2654C14.4724 34.994 14.9175 31.339 12.9401 29.9286C13.0744 29.7134 13.2089 29.4987 13.3437 29.2845C16.0547 32.1163 15.0067 33.438 16.0578 37.3208L16.0595 37.3207C15.8019 33.5283 16.265 31.5934 13.8432 28.8216C13.8063 28.7718 13.7596 28.7345 13.7058 28.7117C13.8045 28.5582 13.9018 28.4054 14.0007 28.2521C14.0173 28.2694 14.0365 28.2847 14.0582 28.2979C16.037 29.8947 15.2561 32.6627 16.4849 34.9188L16.485 34.919C15.6309 32.1962 16.5513 29.6435 14.4255 27.7177C14.406 27.7054 14.3857 27.6952 14.3647 27.6873C14.4819 27.5063 14.6007 27.325 14.7183 27.1447C14.7407 27.1669 14.7656 27.1871 14.7953 27.2028C17.5001 28.9086 14.8184 32.5741 18.0582 35.7138L18.0581 35.7137C15.7037 32.2712 17.714 28.3863 15.1363 26.6067C15.1201 26.5979 15.1044 26.5903 15.0876 26.584C15.2102 26.3995 15.3328 26.2153 15.4556 26.0313C15.4595 26.0361 15.4634 26.0407 15.4672 26.0452C18.066 28.3309 17.1885 29.6356 18.6824 32.783L18.6839 32.7825C18.0338 29.6693 18.1991 27.7537 15.9831 25.5915C15.9386 25.5402 15.8826 25.5053 15.8209 25.4881C15.9349 25.3188 16.0504 25.1491 16.166 24.9796C16.1922 25.025 16.2297 25.065 16.2767 25.0954C19.7129 27.4989 19.0634 30.0155 19.5815 34.0154L19.5831 34.0151C19.8028 29.9402 19.9135 27.0039 16.6492 24.5188C16.6073 24.4919 16.5629 24.4746 16.5164 24.4676C16.6448 24.2808 16.7747 24.0936 16.9034 23.9076C16.91 23.9144 16.918 23.9204 16.9245 23.9269C20.148 26.0391 19.3248 27.8282 20.3146 31.5522C20.0684 27.7843 20.366 25.5593 17.364 23.3979C17.3415 23.3792 17.317 23.3638 17.2922 23.3514C17.4298 23.1545 17.5689 22.9572 17.7083 22.7604C17.735 22.8031 17.7714 22.8408 17.8162 22.8702C21.2384 25.3033 20.5782 27.8829 21.0912 31.8831L21.0914 31.8835C21.3148 27.8015 21.4421 24.8076 18.1886 22.2935C18.1534 22.2699 18.115 22.2541 18.0748 22.246C18.2169 22.0476 18.3592 21.8496 18.5017 21.6522C18.5401 21.7127 18.5988 21.7611 18.6717 21.7877C21.421 23.2716 21.9062 28.4884 22.8847 31.2744C22.3481 28.0695 21.8589 22.8439 18.9086 21.1425C18.8983 21.1391 18.8882 21.136 18.8783 21.1332C19.0269 20.9302 19.1742 20.7282 19.3232 20.5261C19.3488 20.5627 19.3814 20.5956 19.421 20.6215C23.022 23.2016 22.9043 26.0066 23.5252 30.2775L23.5253 30.2776C23.6432 25.9377 23.1967 22.6729 19.7949 20.0442C19.7677 20.0267 19.7392 20.0136 19.7091 20.0048C19.8543 19.8094 20.0012 19.6139 20.1469 19.4197C20.1654 19.4371 20.1865 19.4528 20.2086 19.4668C23.5605 22.1637 23.3748 25.185 25.0343 29.1137C23.8585 24.8227 23.9489 21.7903 20.5608 18.8766L20.5583 18.8748C20.7357 18.6405 20.9149 18.4062 21.093 18.1735C21.1198 18.2202 21.158 18.2616 21.2055 18.2931C24.8009 21.1083 24.7907 24.3703 25.4202 28.7646C25.5184 24.2921 24.9852 20.5705 21.5795 17.716C21.5476 17.6958 21.5147 17.6809 21.4795 17.6722C21.7398 17.3362 22.0022 17.0009 22.2639 16.668C22.2843 16.6897 22.306 16.7104 22.3315 16.728C24.9666 19.4929 25.4228 23.7372 26.9453 27.16C26.1018 23.6436 25.1276 18.8224 22.7231 16.1629C22.7102 16.1538 22.6964 16.1463 22.6827 16.1393C22.9379 15.8184 23.1951 15.4982 23.4516 15.1802C27.2212 18.4694 26.382 21.8079 27.9421 26.3304L27.5948 24.4674C26.701 20.6476 26.7417 17.3165 23.8811 14.6519C24.1002 14.3842 24.3183 14.1182 24.5384 13.8524C27.0752 17.0002 27.4714 22.0923 29.954 24.8345C27.8593 21.4218 27.4231 16.5166 24.968 13.3358C25.1608 13.1048 25.3553 12.8736 25.5488 12.6442C27.9142 16.6009 27.8647 21.0926 30.7605 24.953C28.6465 21.1689 28.0667 15.721 26.0155 12.0952C26.1223 11.9703 26.2292 11.8457 26.3362 11.7214C29.6998 15.2975 29.545 18.363 31.3448 22.977C30.2223 18.2994 29.9577 14.7689 26.7852 11.2017C26.9297 11.0348 27.0758 10.8676 27.2208 10.7017C30.9978 15.0704 31.7128 17.5336 33.4218 23.7075C32.544 17.6791 31.2135 14.4995 27.6773 10.1832C30.2962 7.22108 33.0008 4.40277 35.7519 1.77142C35.9696 1.56788 35.98 1.22719 35.7759 1.01067C35.5733 0.793491 35.2323 0.78269 35.0161 0.98572C32.4528 3.48759 29.701 6.46596 26.9255 9.74494C26.9044 9.73685 26.8838 9.72975 26.8611 9.72554C21.3787 8.41417 17.9404 8.575 12.1021 10.4152C18.3767 9.27506 20.9218 8.83073 26.4391 10.3222C26.305 10.4818 26.1726 10.6411 26.039 10.8017C25.9936 10.7597 25.9376 10.7286 25.8725 10.7151C21.216 9.44811 17.9185 10.7634 13.205 11.8484C18.1566 11.4019 20.8469 9.91209 25.5887 11.3448C25.4656 11.4944 25.3414 11.6452 25.2174 11.7966C25.1717 11.7539 25.1141 11.723 25.0478 11.7107C19.8189 10.4868 16.6385 11.4114 11.5104 13.1727C17.0227 12.0698 19.3828 10.9222 24.77 12.3459C24.6166 12.5349 24.4635 12.7244 24.3107 12.9146C24.2826 12.8838 24.2493 12.8566 24.2104 12.8361C20.5138 12.0529 16.2711 13.8599 12.4914 13.5824C16.3349 14.3874 20.2494 12.5822 23.887 13.444C23.6994 13.6787 23.5122 13.9144 23.3268 14.1502C23.3045 14.1281 23.2781 14.1086 23.2498 14.0924C19.7871 12.7361 16.399 15.4885 12.6965 15.5573L10.9105 15.5495L10.9106 15.5497C15.1976 16.2275 19.6275 13.2937 22.9037 14.6885C22.6403 15.0252 22.3777 15.3637 22.1145 15.7046C22.0849 15.6632 22.0474 15.6269 21.999 15.6011C18.303 14.5419 15.6033 15.7116 11.8736 16.4035C15.331 16.2577 18.3204 15.1262 21.6679 16.2032C21.6839 16.2116 21.6994 16.219 21.7159 16.2247C21.4868 16.5234 21.2598 16.8227 21.0333 17.1232C21.0076 17.0899 20.9766 17.0604 20.9382 17.0375C16.9597 15.2401 13.6084 16.5291 9.73778 18.5564C13.8484 17.2201 16.5712 15.6435 20.5811 17.6246C20.5998 17.6352 20.6179 17.6443 20.6369 17.6516C20.4293 17.9293 20.2222 18.208 20.0155 18.4876C19.9922 18.4599 19.9651 18.435 19.9331 18.4145C16.2545 16.76 14.0649 18.3136 10.1756 19.2334C13.9809 18.9148 16.108 17.2709 19.5616 18.993C19.5811 19.0052 19.6013 19.0152 19.6222 19.023C19.4615 19.2411 19.304 19.4586 19.1453 19.6771C19.1197 19.6441 19.0873 19.6153 19.0504 19.5918C15.2486 17.686 12.2536 18.7904 8.46451 20.7804L8.4647 20.7808C12.5103 19.4876 14.8564 18.0738 18.6933 20.179C18.7149 20.1921 18.7371 20.2027 18.7599 20.2107C18.6102 20.4188 18.4607 20.6274 18.3129 20.8357C18.2951 20.8012 18.2715 20.7688 18.2413 20.7409Z\"\n        fill=\"#4B8C74\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 36 / 51,\n  svg: PalmLeaf,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/hawaii-travel-packing-list/palmTree.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Palm Tree', 'sticker name', 'web-stories');\n\nfunction PalmTree({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 30 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.7353 0.950319C14.8874 1.56724 15.3216 4.19328 15.2782 4.233C15.2627 4.24714 15.1754 4.12568 15.0841 3.96309C14.829 3.50841 14.1914 2.6138 14.0101 2.45593L13.8477 2.31457L13.89 2.50569C13.951 2.78046 14.3051 3.6015 14.5468 4.02824C14.7355 4.36142 14.7391 4.3764 14.5881 4.19657C14.3363 3.89672 13.8367 3.40228 13.8102 3.42652C13.7972 3.43834 13.8375 3.57127 13.8997 3.72185C13.9618 3.87249 14.0329 4.04628 14.0576 4.10808C14.085 4.17639 14.0301 4.14295 13.9179 4.0229C13.8164 3.91426 13.7321 3.84031 13.7306 3.85855C13.7242 3.93626 13.9661 4.53485 14.1851 4.98296L14.4215 5.46688L14.0131 5.06549C13.7884 4.84476 13.6035 4.69213 13.6022 4.72627C13.6008 4.76047 13.746 5.06406 13.9246 5.40091C14.1901 5.9012 14.2169 5.97584 14.0715 5.80837C13.9736 5.69561 13.7989 5.53511 13.6833 5.45166L13.4731 5.29993L13.6251 5.6267C13.8228 6.05189 14.0034 6.34497 14.4595 6.98104C14.665 7.26767 14.826 7.50207 14.8172 7.502C14.8084 7.50193 14.6174 7.29823 14.3926 7.04929C14.1679 6.8004 13.8932 6.53122 13.7824 6.45116L13.5807 6.30566L13.6753 6.52142C13.7274 6.64011 13.8786 6.92712 14.0113 7.15921L14.2526 7.58119L13.9731 7.32686C13.7444 7.11876 13.7037 7.09803 13.7497 7.21298C13.8908 7.56625 14.1223 8.01228 14.4052 8.47572C14.7653 9.06579 14.7803 9.20819 14.4576 8.97292C14.2974 8.8561 14.1944 8.70663 14.0763 8.41957C13.8632 7.90124 13.5009 7.18231 13.3112 6.90131L13.1591 6.67605L13.1958 6.95632C13.216 7.11047 13.2949 7.47592 13.3711 7.76839C13.4474 8.06087 13.5083 8.31334 13.5065 8.32946C13.5047 8.34557 13.4394 8.20044 13.3612 8.00706C13.0404 7.21312 12.2519 5.97607 11.886 5.69256C11.745 5.58324 11.7593 5.66623 11.962 6.13397C12.2022 6.68797 12.1823 6.69838 11.8988 6.16714C11.7684 5.92281 11.5413 5.55145 11.3941 5.34185C11.109 4.9359 10.594 4.36585 10.5493 4.40668C10.5048 4.44729 10.8193 5.15584 11.22 5.9177C11.4275 6.31208 11.5878 6.63471 11.5764 6.63462C11.4801 6.6338 10.9081 5.79355 10.5588 5.13986C10.1174 4.31404 9.51005 3.40144 9.13626 3.00246L8.92477 2.7767L8.9818 2.98318C9.03264 3.16709 9.1308 3.40404 9.47807 4.18118C9.56816 4.38267 9.49895 4.33248 8.811 3.69685C7.32334 2.32229 6.42964 1.68592 7.62393 2.85149C8.39492 3.60395 9.12151 4.3772 9.71424 5.07602L9.95082 5.35496L9.63706 5.12167C9.22315 4.81396 8.61821 4.46784 8.53699 4.49223C8.43832 4.52191 8.94908 5.14153 9.39921 5.5383C9.6197 5.73262 9.79231 5.89158 9.78285 5.89145C9.77333 5.89137 9.62037 5.83861 9.44287 5.77423C9.26542 5.70979 9.10978 5.66664 9.09703 5.67829C9.08429 5.68994 9.66967 6.16843 10.3978 6.74158C12.2215 8.177 12.3164 8.26162 11.4873 7.71309C11.1177 7.46863 10.462 7.15299 10.4142 7.19665C10.3844 7.22389 11.7867 8.53294 12.1799 8.8449L12.4492 9.0585L11.9813 8.8197C11.7239 8.6884 11.5004 8.59283 11.4844 8.60736C11.4685 8.6219 11.7405 8.92163 12.0888 9.27336C12.6699 9.86027 12.9928 10.2843 12.9136 10.3567C12.832 10.4312 13.5599 11.6189 14.1636 12.3961C14.2814 12.5478 14.1779 12.4737 13.8462 12.169C13.4447 11.8002 13.3123 11.6328 13.1276 11.2604C13.0032 11.0093 12.7853 10.6422 12.6436 10.4444C12.2479 9.89257 11.3713 9.0704 10.7774 8.69403C10.238 8.35232 10.0562 8.27738 10.2012 8.45666C10.3844 8.68313 10.9831 9.33206 11.5939 9.96625C11.9527 10.3388 12.3423 10.7437 12.4596 10.8658C12.6342 11.0477 12.6024 11.0313 12.284 10.7754C12.0702 10.6035 11.749 10.355 11.5703 10.2232C11.3616 10.0693 11.1643 9.85202 11.0187 9.6159C10.5739 8.89493 9.94897 8.24791 9.17791 7.71017C8.78061 7.43312 8.10825 7.08189 8.05987 7.1261C8.04506 7.13958 8.52477 7.62798 9.12589 8.21136L10.2187 9.2721L9.70932 8.96923C9.42914 8.80263 9.13246 8.62905 9.05002 8.5835C8.96759 8.53796 8.77946 8.34901 8.63195 8.16366C8.01333 7.38618 6.7477 6.4859 5.77894 6.13422C5.64323 6.08497 5.63771 6.08907 5.70929 6.18576C5.80493 6.31501 6.59285 6.99472 7.17733 7.45226C7.4159 7.639 7.61108 7.79939 7.611 7.80869C7.61092 7.81792 7.38187 7.72343 7.102 7.59865C6.72576 7.43096 6.51204 7.29079 6.28197 7.06078C5.74198 6.52092 4.84485 6.07551 4.09094 5.97297C3.72171 5.92275 3.76749 5.97924 4.44751 6.41318C4.75125 6.60697 4.94637 6.74692 4.88121 6.72414C4.2881 6.51675 1.79558 5.90673 1.74185 5.95583C1.73329 5.96365 2.09743 6.08802 2.55097 6.23224C3.50352 6.53506 4.66978 6.95913 4.75564 7.03383C4.79187 7.06538 4.74531 7.07982 4.63486 7.07138C4.2708 7.04348 3.87619 7.07395 3.91098 7.12727C3.96931 7.21663 5.20044 7.57551 5.96918 7.72728C6.36455 7.80533 6.79343 7.92431 6.92236 7.9917C7.11192 8.09073 7.12599 8.10804 6.99604 8.08219C6.57602 7.99861 5.63839 7.93197 5.33147 7.96386L4.98922 7.99942L5.34972 8.10612C5.54799 8.1648 6.3593 8.38216 7.15262 8.58918C8.5755 8.96044 9.1336 9.12621 9.09111 9.16499C9.07921 9.17592 8.94512 9.14891 8.79322 9.10501C8.41906 8.99691 7.39177 8.87811 7.23031 8.92427C7.10532 8.96 7.10456 8.96414 7.2128 9.02161C7.27498 9.05466 7.71848 9.21739 8.19834 9.38328L9.07079 9.68486L8.60429 9.64882C8.30488 9.62567 8.13761 9.63327 8.1373 9.66988C8.13657 9.75627 11.4473 11.0008 11.6832 11.0028C11.7184 11.0031 11.7277 10.9735 11.7039 10.9371C11.6801 10.9007 11.7581 10.9445 11.8774 11.0345C12.1292 11.2247 12.127 11.2758 11.8724 11.1508C11.6451 11.0391 10.8455 10.8451 10.4166 10.7974L10.0856 10.7606L10.3253 10.906C10.6822 11.1226 11.8609 11.6825 12.557 11.9661C12.8937 12.1033 13.161 12.2231 13.1508 12.2324C13.1407 12.2416 12.949 12.208 12.7247 12.1576C12.5005 12.1073 12.246 12.0731 12.1593 12.0818C12.0031 12.0972 12.0036 12.0985 12.2206 12.2264C12.4505 12.3619 14.074 13.9127 14.2991 14.2118C14.4013 14.3476 14.4104 14.3855 14.3405 14.3849C14.2914 14.3845 14.1056 14.1875 13.9276 13.9473C13.3761 13.2026 12.5989 12.5995 11.6395 12.1719C11.0576 11.9125 10.2141 11.7054 9.82295 11.726L9.54569 11.7406L10.0278 11.9278C10.4376 12.0869 10.5565 12.1656 10.8203 12.4524C11.2367 12.9051 11.1278 12.8928 10.4604 12.4116C9.51422 11.7296 8.11438 11.2561 7.00961 11.2446L6.52779 11.2396L7.33737 11.5034C8.07788 11.7447 9.46952 12.3191 9.42102 12.3633C9.34914 12.429 8.06395 12.0658 7.56336 11.8383C6.81699 11.4991 6.0262 11.306 5.15431 11.2501C4.05745 11.1798 4.08403 11.2633 5.26379 11.5942C5.8159 11.749 6.24012 11.884 6.20649 11.894C6.08849 11.9295 5.07402 11.7899 4.74705 11.6932C4.31199 11.5646 2.76267 11.5347 2.27896 11.6456C1.8775 11.7377 1.9437 11.7727 2.72761 11.8834L3.26906 11.9598L2.69608 12.0493C1.89584 12.1743 0.281985 12.56 0.462911 12.583C0.479458 12.5851 0.805106 12.5395 1.18658 12.4815C1.56804 12.4235 1.96146 12.3769 2.06084 12.3778C2.23273 12.3795 2.22652 12.3874 1.93224 12.5411C1.60983 12.7095 1.24359 13.0517 1.34962 13.0856C1.55056 13.1497 2.90867 12.6784 3.35081 12.3912C3.44711 12.3286 3.603 12.2787 3.69725 12.2804C3.83348 12.2827 3.78628 12.3152 3.46708 12.4386C3.0675 12.5933 2.32637 13.0289 2.32568 13.1096C2.32504 13.1851 3.11321 12.9994 4.30729 12.6426C4.94938 12.4508 5.56055 12.297 5.66545 12.3006C5.81358 12.3058 5.76857 12.3288 5.46381 12.4039C4.96235 12.5273 4.582 12.6798 4.18087 12.9182C3.78743 13.1521 3.41597 13.4644 3.49952 13.4911C3.56302 13.5114 4.08104 13.3604 4.81279 13.1083C5.03843 13.0306 5.20755 12.9898 5.18864 13.0177C5.15436 13.0684 5.39478 13.0501 5.83548 12.9686C5.95988 12.9455 6.06166 12.9331 6.06159 12.941C6.06152 12.9488 5.89124 13.0559 5.68311 13.179C5.23949 13.4415 4.89702 13.7448 5.04295 13.746C5.09517 13.7465 5.4466 13.6517 5.82398 13.5353C6.20131 13.419 6.64575 13.3085 6.81155 13.2897L7.11301 13.2556L6.80429 13.4136C6.29667 13.6734 5.90626 13.9471 6.01348 13.9679C6.09075 13.983 6.88977 13.8101 7.36537 13.6754C7.42352 13.659 7.30766 13.7403 7.10791 13.8561C6.87244 13.9927 6.77978 14.0734 6.84443 14.0856C6.89927 14.0959 7.42846 14.0202 8.02041 13.9173C10.3402 13.5143 10.8629 13.4572 11.3268 13.556L11.5072 13.5944L11.3261 13.6436C11.2264 13.6705 10.7382 13.7119 10.2411 13.7353C9.27834 13.7807 8.67001 13.8983 8.16932 14.1359C7.64855 14.383 7.65555 14.3953 8.30273 14.37L8.89979 14.3466L8.63285 14.5081C8.48602 14.5969 8.39301 14.6699 8.42613 14.6702C8.45926 14.6705 8.83925 14.609 9.27056 14.5337C9.88188 14.4268 10.141 14.406 10.4459 14.4389C10.8626 14.484 10.8641 14.4817 10.3002 14.6651C10.0666 14.7411 10.0286 14.7694 10.1183 14.8008C10.2048 14.8311 10.1745 14.8495 9.99044 14.8783C9.54339 14.9481 8.78551 15.1147 8.54213 15.1964C8.31362 15.2731 8.36748 15.2788 9.53511 15.2996C10.641 15.3193 10.7132 15.326 10.2272 15.3641C8.88224 15.4696 7.46666 15.7148 6.45711 16.017L5.88343 16.1888L6.335 16.2106L6.78657 16.2323L6.09062 16.4394C5.70789 16.5534 5.16525 16.7515 4.8848 16.8797C4.32825 17.1341 3.59386 17.5418 3.63025 17.5762C3.64279 17.5882 3.78535 17.562 3.94696 17.5183C4.34319 17.4111 4.35028 17.4482 3.96162 17.5946C3.63295 17.7183 2.76442 18.1902 2.76395 18.2452C2.76326 18.3267 3.89325 18.0988 4.42321 17.9106C4.50967 17.8799 4.49767 17.902 4.38099 17.9884C4.29128 18.0549 4.01522 18.1556 3.76748 18.2123C3.24931 18.3308 2.84631 18.5047 2.42272 18.7924C2.12841 18.9923 1.67509 19.4178 1.67092 19.498C1.66775 19.5585 2.43175 19.2891 2.80097 19.0995C2.97514 19.0101 3.13634 18.937 3.15911 18.9372C3.18194 18.9374 2.99616 19.1312 2.74629 19.3677C2.27491 19.8139 1.7728 20.3746 1.41516 20.8541C1.26144 21.0602 1.39939 20.9524 1.94675 20.4387L2.68592 19.7451L2.56974 20.0285C2.43879 20.3479 2.33553 21.0032 2.41657 21.0002C2.44567 20.9991 2.60102 20.7925 2.76175 20.5412C2.92247 20.2898 3.10672 20.0216 3.17115 19.9452L3.28834 19.8062L3.19629 20.0851C3.14565 20.2385 3.1114 20.3998 3.12018 20.4436C3.12896 20.4873 3.46465 20.1393 3.86617 19.6703C4.2677 19.2012 4.63022 18.7782 4.67183 18.7301C4.71337 18.6821 4.65483 18.831 4.54168 19.061C4.35775 19.435 4.24345 19.7303 4.2826 19.7307C4.29037 19.7307 4.5499 19.4558 4.85928 19.1197C5.16866 18.7835 5.43265 18.5086 5.4459 18.5087C5.45909 18.5088 5.37426 18.6677 5.25726 18.8617C5.14027 19.0557 5.04442 19.2347 5.04421 19.2593C5.04401 19.2839 5.25616 19.1198 5.51569 18.8947C5.95853 18.5105 6.89228 17.7433 7.22481 17.4904C7.30659 17.4282 7.22162 17.5398 7.03604 17.7383C6.67667 18.1228 6.2419 18.6912 6.27979 18.7269C6.29234 18.7388 6.70729 18.4538 7.20204 18.0936C8.47439 17.1671 9.15951 16.7382 9.87192 16.4222C10.5355 16.128 10.6701 16.0949 10.2039 16.3409C9.54204 16.69 8.78333 17.2798 7.88187 18.1461C6.47727 19.4958 6.00867 20.047 5.45528 21.0004C5.20698 21.4282 5.20413 21.4384 5.3852 21.2523L5.57381 21.0586L5.53686 21.2536C5.51649 21.361 5.48951 21.4951 5.47687 21.5517C5.45457 21.6516 5.45747 21.6517 5.57823 21.5525C5.64659 21.4964 5.89127 21.1899 6.1219 20.8715C6.35259 20.553 6.54083 20.3026 6.54031 20.3151C6.53978 20.3275 6.48413 20.497 6.41664 20.6916C6.34916 20.8863 6.29361 21.0861 6.29319 21.1356C6.29277 21.1852 6.5271 20.9204 6.81397 20.5472C7.10077 20.174 7.34683 19.8687 7.36068 19.8688C7.37453 19.8689 7.28762 20.0319 7.16757 20.2311C7.04752 20.4302 6.96867 20.5933 6.99228 20.5935C7.01595 20.5937 7.25728 20.3988 7.52855 20.1604C7.79981 19.922 8.1717 19.6311 8.35489 19.5141L8.68799 19.3013L8.3276 19.6576C6.77506 21.1925 5.64424 23.0504 5.02727 25.0799C4.90662 25.4769 4.73423 25.9667 4.64422 26.1685C4.5114 26.4662 4.47466 26.6513 4.44897 27.1509C4.41477 27.816 4.4944 28.249 4.74186 28.7438L4.87115 29.0022L4.90657 28.5266C4.93186 28.1868 4.95715 28.0817 4.99511 28.1584C5.04633 28.2618 5.05007 28.2615 5.09639 28.1478C5.1229 28.0829 5.19625 27.609 5.25947 27.0947L5.37438 26.1596L5.44416 26.6745C5.53893 27.3743 5.60791 27.4715 5.66505 26.9854C5.79977 25.8386 6.38826 22.8149 6.49381 22.7268C6.5185 22.7062 6.52106 22.7522 6.49945 22.829C6.30405 23.5244 6.28016 24.9551 6.45875 25.2679C6.51062 25.3587 6.55429 25.4159 6.55579 25.3951C6.55729 25.3741 6.71336 24.6574 6.90264 23.8023C7.33396 21.8533 7.48591 21.351 7.74306 21.0239C7.85302 20.884 7.94904 20.7696 7.95633 20.7697C7.96368 20.7698 7.86053 21.0222 7.72714 21.3307C7.4455 21.9823 7.26437 22.6778 7.21159 23.311L7.17424 23.7586L7.38615 23.3684L7.59799 22.9783L7.602 23.2863C7.60934 23.862 7.68012 23.8538 7.86759 23.2554C8.04775 22.6804 8.30907 22.0591 9.14435 20.2199C9.59875 19.2192 9.79991 18.8816 9.9409 18.8828C9.97054 18.8831 9.94158 18.9522 9.87654 19.0363C9.30125 19.7805 8.95939 20.9343 9.04492 21.8428L9.08448 22.263L9.352 21.5934C9.66783 20.8029 10.2782 19.4384 10.3468 19.3694C10.3733 19.3428 10.3678 19.4295 10.3345 19.562C10.3013 19.6945 10.2817 19.8675 10.2909 19.9463C10.3055 20.0712 10.337 20.043 10.5356 19.7278C10.6611 19.5286 10.7637 19.4016 10.7639 19.4455C10.764 19.5014 10.8087 19.487 10.913 19.3975L11.0619 19.2697L10.9405 19.5597C10.7182 20.0905 10.4046 21.2944 10.4884 21.2951C10.5005 21.2952 10.8537 20.662 11.2732 19.888C11.9817 18.5804 12.0665 18.4512 12.4682 18.0644C12.706 17.8355 12.8839 17.6942 12.8635 17.7504C12.843 17.8066 12.8258 17.9101 12.8252 17.9802C12.8246 18.0552 12.6595 18.2883 12.4245 18.5461C12.0276 18.9815 11.4471 19.7751 11.4935 19.8189C11.5068 19.8315 11.8581 19.5646 12.2741 19.2257C12.6902 18.8868 12.9194 18.72 12.7834 18.8552C12.2592 19.3759 11.419 20.4439 11.4177 20.5911C11.4164 20.7399 12.4663 19.9042 12.9902 19.3394C13.2052 19.1076 13.4038 18.9312 13.4315 18.9475C13.4593 18.9637 13.2597 19.1938 12.988 19.4587C12.4542 19.9793 11.8834 20.6513 11.5157 21.1922C11.2369 21.6023 11.3092 21.5779 12.0044 21.0279L12.5078 20.6294L12.0576 21.1557C11.6385 21.6456 11.1622 22.3014 11.1615 22.3897C11.1607 22.4742 11.9179 21.8776 12.4632 21.3641C12.7815 21.0642 13.0417 20.8565 13.0413 20.9023C13.0409 20.9482 12.8655 21.1824 12.6515 21.4226C12.4375 21.6628 12.1513 22.0089 12.0154 22.1916C11.7025 22.6125 11.2551 23.4066 11.2842 23.4898C11.3224 23.5995 12.3998 22.515 12.8004 21.9637C13.0112 21.6734 13.1938 21.4455 13.2062 21.4571C13.2791 21.526 13.104 21.8646 12.8392 22.1667C12.2195 22.8741 11.5186 23.9101 11.1711 24.6324L11.0101 24.967L11.3538 24.6619C11.6893 24.3642 12.5626 23.3418 12.8377 22.9248C12.9863 22.6997 13.0263 22.672 13.0253 22.7953C13.0249 22.8387 12.9045 23.0088 12.7579 23.1733C12.0105 24.0118 11.3138 25.2763 11.0753 26.2273C11.0263 26.423 11.0296 26.4524 11.0934 26.3892C11.1821 26.3016 11.7356 25.4886 12.4424 24.4079C12.7068 24.0036 12.932 23.6812 12.9428 23.6913C12.9535 23.7014 12.9345 23.8626 12.9005 24.0494C12.8475 24.3407 12.7909 24.4419 12.5021 24.7618C12.1423 25.1605 11.7529 25.7999 11.5852 26.2672C11.4639 26.6053 11.3635 27.1256 11.4193 27.1261C11.4843 27.1267 12.0577 26.3022 12.426 25.6789L12.7716 25.0939L12.7299 25.4015C12.707 25.5707 12.5907 25.9476 12.4715 26.2392C12.2234 26.8461 11.9935 27.6339 11.9336 28.0823C11.8952 28.3702 11.8987 28.3828 11.9892 28.2788C12.0425 28.2176 12.1804 27.9983 12.2958 27.7914C12.4112 27.5846 12.5134 27.4154 12.523 27.4154C12.5439 27.4156 12.5407 27.4449 12.3373 29.1216C12.2478 29.8599 12.1183 30.8415 12.0495 31.3028C11.9263 32.13 11.8124 33.2767 11.6411 35.4147C11.5876 36.0814 11.5461 37.551 11.5343 39.1932C11.515 41.8986 11.5231 42.0974 11.7837 45.3264C11.904 46.8168 11.9024 48.7805 11.7806 48.9896C11.7293 49.0777 11.4297 49.2994 11.0835 49.5053C10.3682 49.9308 10.1136 50.1366 9.95448 50.4178C9.72437 50.8247 9.51965 50.7943 12.6669 50.821C14.2238 50.8343 15.4978 50.8301 15.4979 50.8117C15.4984 50.7559 15.2622 50.4489 14.7996 49.9043C14.0918 49.0709 13.9101 48.4928 13.4616 45.6486C13.0381 42.9629 12.9615 41.4542 13.0123 36.7981C13.0457 33.7337 13.057 33.4754 13.2128 32.2086C13.3492 31.1003 13.6854 28.0815 13.7129 27.7196C13.7169 27.6657 13.7428 27.7328 13.7703 27.8687C13.7978 28.0047 13.8642 28.2572 13.9179 28.4299C14.0151 28.7424 14.0158 28.7431 14.0735 28.5764C14.1054 28.4843 14.1484 28.0311 14.1691 27.5694C14.2012 26.8529 14.1884 26.6435 14.0816 26.1409C13.9564 25.552 13.9356 25.0627 14.0231 24.7682C14.0539 24.6642 14.1116 25.0799 14.1949 26.0072C14.264 26.7747 14.335 27.4406 14.3528 27.487C14.4468 27.7305 14.7297 26.0408 14.6631 25.6336C14.6092 25.303 14.6683 25.3755 14.8181 25.8234L14.9537 26.2286L14.9864 25.9228L15.0191 25.6169L15.147 25.9539L15.2749 26.291L15.2821 26.0022C15.3015 25.2287 14.8417 22.7367 14.423 21.3452C14.1723 20.5122 14.1619 20.464 14.2419 20.5108C14.2708 20.5278 14.3257 20.6608 14.3638 20.8065C14.4064 20.9693 14.451 21.045 14.4795 21.003C14.5049 20.9653 14.6759 21.652 14.8594 22.5288C15.0428 23.4057 15.2528 24.3467 15.326 24.6199C15.4442 25.0616 15.4643 25.0987 15.5073 24.9547C15.5959 24.6583 15.4921 23.3405 15.2821 22.094C15.1373 21.2347 15.0951 20.8566 15.1425 20.8423C15.1799 20.8311 15.211 20.7499 15.2118 20.662C15.2125 20.574 15.2362 20.4889 15.2645 20.473C15.3256 20.4386 15.472 21.7969 15.5617 23.2284C15.597 23.7911 15.6468 24.2323 15.6724 24.2088C15.7296 24.1565 15.8902 23.3111 15.951 22.7424L15.9957 22.324L16.1567 22.8442C16.2452 23.1303 16.3363 23.382 16.359 23.4035C16.4387 23.4788 16.2794 21.7495 16.08 20.3735C15.9412 19.4158 15.9375 19.2137 16.0585 19.2147C16.1365 19.2154 16.1871 19.5868 16.5823 23.0546C16.5858 23.0854 16.6156 23.0227 16.6485 22.9152C16.7366 22.6274 16.7996 20.4942 16.7349 19.9928C16.6772 19.5464 16.7658 18.6082 16.857 18.7001C16.882 18.7253 16.9424 19.162 16.9912 19.6706C17.04 20.1791 17.0959 20.7213 17.1154 20.8754C17.1484 21.1355 17.1556 21.1456 17.2162 21.0163C17.2767 20.8871 17.2839 20.8975 17.3154 21.1571C17.3475 21.421 17.3534 21.429 17.4171 21.2946C17.4543 21.2162 17.5197 21.0466 17.5624 20.9179C17.6554 20.6375 17.7109 20.6185 17.7122 20.8665C17.7127 20.9666 17.7179 21.2627 17.7238 21.5245C17.7337 21.9635 17.7411 21.9897 17.819 21.8613L17.9035 21.7221L17.9338 21.8623C17.9504 21.9394 17.9784 22.2184 17.9959 22.4824C18.0134 22.7463 18.0486 23.0363 18.0741 23.1269C18.1161 23.276 18.1276 23.2572 18.1951 22.9283C18.3367 22.2373 18.3915 21.7698 18.4412 20.8265L18.4911 19.8793L18.5785 20.1805C18.6569 20.4505 18.6541 20.6122 18.5521 21.7366C18.4895 22.4268 18.3967 23.2986 18.3458 23.674C18.295 24.0494 18.2536 24.4448 18.2539 24.5525L18.2544 24.7485L18.4017 24.4978L18.549 24.2471L18.5531 24.6671L18.5573 25.087L18.7163 24.7804C18.9233 24.3812 19.0973 23.7876 19.1464 23.3125C19.168 23.1038 19.205 22.9222 19.2287 22.9088C19.2791 22.8805 19.4217 23.6675 19.374 23.7111C19.3563 23.7273 19.3423 23.6809 19.3429 23.6081C19.3451 23.3449 19.2222 23.5876 19.1006 24.0867C18.9287 24.792 18.7819 25.8262 18.7774 26.364C18.7737 26.7977 18.7785 26.815 18.8701 26.6956C18.9232 26.6263 19.0478 26.376 19.1471 26.1395C19.2463 25.903 19.3122 25.7849 19.2936 25.8772C19.2439 26.1236 19.221 27.7463 19.2666 27.7894C19.3637 27.8812 19.737 26.8458 19.7402 26.4757C19.7437 26.054 19.8195 26.4072 19.9995 27.6841L20.1877 29.0203L20.2054 28.0406L20.223 27.0609L20.3861 27.3973C20.5131 27.6594 20.5585 27.7113 20.5919 27.6324C20.7273 27.3121 20.5658 26.3642 20.2625 25.6988C20.1173 25.3804 20.0575 25.1507 20.0336 24.8196L20.0011 24.3714L20.2245 24.9612C20.3473 25.2856 20.553 25.7409 20.6816 25.9729C20.9055 26.377 20.9163 26.3872 20.9358 26.2137C20.9642 25.9605 20.7988 25.1456 20.5975 24.5475C20.5043 24.2705 20.4361 24.0367 20.4459 24.0278C20.4556 24.0189 20.5779 24.2904 20.7176 24.6312C20.8573 24.9721 20.9837 25.2399 20.9984 25.2265C21.0585 25.1715 20.8826 24.0571 20.7187 23.4536C20.6222 23.0987 20.4796 22.54 20.4018 22.2121C20.324 21.8842 20.1701 21.3601 20.0598 21.0474C19.9495 20.7347 19.8671 20.4789 19.8765 20.4789C19.9119 20.4792 20.4724 21.2973 20.4614 21.3325C20.4551 21.3526 20.4896 21.3836 20.5381 21.4014C20.5895 21.4202 20.6265 21.4013 20.6269 21.3559C20.6278 21.254 20.2875 20.3342 20.1689 20.1175C20.118 20.0247 20.0582 19.8604 20.0359 19.7524C20.0137 19.6444 19.9745 19.4803 19.9489 19.3877C19.9052 19.23 19.9091 19.2247 20.0105 19.3038C20.1111 19.3823 20.1157 19.3783 20.0744 19.2484C20.0499 19.1714 19.9752 19.0198 19.9085 18.9115L19.787 18.7145L20.0506 18.9426C20.1955 19.068 20.3778 19.2208 20.4556 19.282L20.597 19.3932L20.499 19.1684C20.26 18.6199 19.7172 17.8448 19.1055 17.1786C18.7477 16.7889 18.738 16.7711 18.9374 16.8692C19.0824 16.9406 19.2926 17.168 19.6064 17.5931C20.0629 18.2115 21.027 19.3276 21.3359 19.5955L21.4988 19.7368L21.4576 19.5965C21.3976 19.3926 21.0335 18.6616 20.8882 18.4534L20.7636 18.2748L20.9208 18.4441C21.0073 18.5372 21.3875 19.0444 21.7658 19.5711L22.4536 20.5288L22.4183 20.2397C22.3988 20.0807 22.332 19.8093 22.2697 19.6366C22.2074 19.4638 22.1663 19.3226 22.1782 19.3227C22.1901 19.3228 22.2857 19.4559 22.3905 19.6184C22.6169 19.9694 23.4555 21.0692 23.497 21.0696C23.5129 21.0697 23.5107 20.9753 23.492 20.8596L23.4581 20.6493L23.6249 20.8467C23.8739 21.1413 24.3747 21.641 24.3988 21.619C24.4768 21.5477 23.9413 20.4331 23.5528 19.8583C23.3263 19.5231 23.3251 19.5228 23.8937 19.9364C24.1892 20.1513 24.2805 20.2783 24.839 21.2507C25.3349 22.114 25.4688 22.3082 25.5157 22.2318C25.588 22.1139 25.5357 21.6338 25.4149 21.3072L25.3245 21.0629L25.4694 21.1916C25.5622 21.274 25.6286 21.4138 25.654 21.5798C25.7096 21.9447 25.9034 22.307 26.1856 22.5738L26.4272 22.8022L26.4473 22.623C26.4584 22.5245 26.4403 22.3494 26.4071 22.2339C26.3739 22.1184 26.353 22.0182 26.3606 22.0112C26.3889 21.9854 27.2568 22.9761 27.4617 23.2682C27.5783 23.4344 27.685 23.56 27.6988 23.5474C27.7369 23.5126 27.3806 22.9246 26.9958 22.3871C26.287 21.397 25.0827 20.2552 23.5671 19.1365C22.8149 18.5813 21.2767 17.6007 20.5787 17.2315C20.2358 17.05 20.0655 16.9197 19.9581 16.7562C19.7662 16.4644 19.5526 16.2454 19.2625 16.0432C19.0849 15.9194 19.0571 15.8807 19.1467 15.8815C19.2114 15.882 19.357 15.9739 19.4702 16.0857C19.6913 16.3039 21.0646 17.3799 21.3369 17.5482C21.555 17.683 21.5505 17.5977 21.3178 17.1837C21.1441 16.8749 20.6878 16.4112 20.2798 16.1293L20.1001 16.0051L20.4723 16.0065C20.7323 16.0075 20.8727 16.0346 20.9383 16.0966C21.0642 16.2157 21.0586 16.2229 20.8679 16.1873C20.706 16.1571 20.707 16.1602 20.9538 16.439C21.3629 16.901 22.7152 17.9834 22.8851 17.9849C22.9115 17.9851 22.9182 17.9305 22.8999 17.8635C22.8749 17.7714 22.9889 17.835 23.3683 18.1248C23.8819 18.5171 24.0135 18.5372 23.786 18.1886C23.6302 17.9499 23.6708 17.9413 23.9583 18.1519C24.2325 18.3527 24.6254 18.5788 24.6538 18.5522C24.709 18.5004 24.189 17.8611 23.7064 17.3872C23.2871 16.9756 23.2094 16.8758 23.3471 16.9257C23.4437 16.9608 24.1094 17.5377 24.8264 18.2076C25.5435 18.8776 26.1451 19.4121 26.1633 19.3954C26.2302 19.3342 25.7494 18.5651 25.35 18.0943C25.1241 17.8282 24.9512 17.6105 24.9658 17.6106C24.9804 17.6107 25.1143 17.6672 25.2634 17.7361C25.4249 17.8106 25.5067 17.877 25.4658 17.9001C25.4218 17.9248 25.6936 18.293 26.2166 18.9174C26.6674 19.4555 27.0623 19.905 27.0942 19.9162C27.2333 19.9651 26.9885 19.1339 26.7743 18.8298C26.7088 18.7368 26.9215 18.9026 27.2469 19.1982C27.5723 19.4938 27.996 19.8754 28.1883 20.0461L28.5381 20.3565L28.4962 20.1602C28.4449 19.9192 28.2696 19.5787 28.0627 19.318L27.9073 19.122L28.2054 19.2865C28.3694 19.377 28.7677 19.6128 29.0905 19.8106C29.4133 20.0084 29.6904 20.1703 29.7061 20.1705C29.8257 20.1715 28.0538 18.8189 27.4055 18.4144C27.2737 18.3322 27.2804 18.3293 27.5589 18.3477L27.8502 18.3668L27.611 18.1617C27.2029 17.8116 26.4619 17.5137 25.9848 17.5079C25.8824 17.5067 25.6527 17.4266 25.4743 17.33C25.2959 17.2334 25.1948 17.1679 25.2497 17.1845C25.5291 17.2687 26.8947 17.5187 27.0003 17.5049C27.1728 17.4823 26.3636 17.0573 25.7709 16.8591C25.5154 16.7737 25.3197 16.6842 25.3359 16.6603C25.3741 16.604 24.5296 16.3137 23.8214 16.1396C23.5172 16.0648 23.2996 15.986 23.3379 15.9645C23.3804 15.9405 23.3473 15.9108 23.2529 15.8879C23.1679 15.8673 23.0633 15.7883 23.0204 15.7123C22.923 15.5398 22.5572 15.2548 22.1263 15.0157C21.8191 14.8453 21.811 14.8355 22.0071 14.8725C22.1228 14.8944 22.6367 15.0289 23.149 15.1714C24.3742 15.5122 24.3529 15.5081 24.1111 15.3604C23.7056 15.1127 22.6949 14.6802 22.0861 14.4938C21.4714 14.3057 21.3281 14.2202 21.6312 14.2228C21.8929 14.225 22.5556 14.1108 22.556 14.0634C22.5567 13.9897 21.6194 13.8786 20.5218 13.8224C19.9486 13.7929 19.4666 13.7564 19.4505 13.7413C19.4345 13.7261 19.5447 13.6975 19.6956 13.6778C19.8464 13.6581 20.1125 13.5979 20.2868 13.5442L20.6037 13.4465L20.2851 13.3796C20.1098 13.3429 19.882 13.3121 19.7787 13.3112C19.5129 13.309 19.5956 13.2638 19.9779 13.2023C20.1578 13.1735 20.4253 13.1206 20.5723 13.085L20.8396 13.0201L20.6036 12.9501L20.3676 12.8801L20.6989 12.8737C20.8811 12.8703 21.1388 12.8491 21.2715 12.8266L21.5128 12.7857L21.2424 12.7081C20.8301 12.5899 20.8379 12.5549 21.2854 12.5173C21.5113 12.4983 21.8454 12.4517 22.0279 12.4138L22.3598 12.3448L21.9991 12.2632C21.7477 12.2063 21.2334 12.1777 20.3014 12.169C18.2675 12.15 18.6019 12.0748 21.742 11.8452C22.6924 11.7757 23.5453 11.7195 23.6374 11.7202C24.1282 11.7244 23.0587 11.4697 22.3977 11.4251C22.1628 11.4092 22.9844 11.2621 23.5741 11.2144C23.9387 11.185 24.4271 11.1258 24.6594 11.0828C24.8917 11.0398 25.1075 11.0049 25.1389 11.0052C25.1751 11.0054 25.1752 10.986 25.1394 10.9524C25.1082 10.923 24.8164 10.8716 24.491 10.838C24.1656 10.8044 23.8643 10.7493 23.8214 10.7156C23.7784 10.6819 23.5574 10.6374 23.3301 10.6168C22.4462 10.5365 22.8239 10.4948 24.6109 10.4752C26.5331 10.4541 27.0442 10.4274 27.0449 10.3477C27.0453 10.3007 26.6008 10.1971 26.053 10.1166C25.7536 10.0726 25.7543 10.0724 26.1825 10.0691C26.7436 10.0647 27.7964 9.97267 27.9682 9.91287C28.0996 9.86718 28.0984 9.8642 27.9229 9.79771C27.7596 9.73585 27.5941 9.70113 26.8407 9.57066C26.6286 9.53392 26.6969 9.51535 27.4142 9.41405C27.862 9.35083 28.5538 9.27031 28.9517 9.23505L29.675 9.17098L29.2237 9.12218C28.9754 9.09527 28.3792 9.08349 27.8988 9.09587L27.0252 9.11841L27.6588 8.88975C28.2519 8.67574 28.2817 8.65769 28.1243 8.60742C27.6613 8.45964 26.0258 8.81155 25.2859 9.21815C24.9737 9.38969 24.2355 9.63073 24.1807 9.57892C24.1727 9.57135 24.3623 9.45969 24.6019 9.33076C25.1075 9.05885 25.8072 8.59598 25.7682 8.55914C25.7262 8.51931 24.899 8.75859 24.4736 8.93359C24.0223 9.11924 23.9613 9.12801 24.1569 8.97922C24.2356 8.91931 24.2707 8.87005 24.2348 8.86975C24.1142 8.86873 22.8116 9.39854 22.2923 9.65981L21.7781 9.9185L22.3245 9.40891L22.8709 8.89938L22.3841 9.13136C21.7713 9.42348 21.0026 9.92306 20.2476 10.52C19.9249 10.775 19.6923 10.9468 19.7306 10.9017C20.1368 10.4248 20.6007 9.82474 20.5791 9.80423C20.5184 9.74694 19.7341 10.3574 18.8565 11.1448L17.926 11.9797L18.2603 11.493C18.6394 10.9409 18.7739 10.659 18.6348 10.7072C18.5315 10.7431 18.5269 10.7028 18.6157 10.5401C18.7222 10.3449 16.6739 12.2934 16.5356 12.5188C16.5044 12.5697 16.453 12.6111 16.4215 12.6108C16.2883 12.6097 16.3899 12.4598 16.7758 12.0884C17.0016 11.8712 17.3171 11.5137 17.4771 11.2939C17.7915 10.8619 18.277 9.95843 18.3402 9.68757C18.3787 9.52239 18.3756 9.5236 18.1277 9.76976C17.9893 9.90716 17.7428 10.1797 17.58 10.3754C17.2318 10.7936 17.2107 10.7656 17.4993 10.2683C18.0833 9.26199 18.3555 8.54867 18.3186 8.12098C18.3025 7.93394 18.2766 7.9653 17.8736 8.65976C17.3889 9.49501 16.5879 10.7513 16.4621 10.8734C16.3902 10.9433 16.3787 10.9185 16.3806 10.6982C16.3828 10.4378 16.4503 10.3066 17.1222 9.2573C17.6791 8.38772 18.1287 7.34097 18.2484 6.63527L18.2911 6.38367L18.1151 6.63414C17.9661 6.84625 17.3755 7.83324 16.6071 9.15449C16.4327 9.4543 16.3301 9.55158 16.3312 9.41581C16.3315 9.38357 16.4672 9.15163 16.6327 8.90046C17.0027 8.33915 17.2725 7.73684 17.4289 7.12327C17.5574 6.61865 17.6387 6.12617 17.5935 6.12579C17.578 6.12565 17.4924 6.23204 17.4033 6.36213C17.3142 6.49229 17.1501 6.69185 17.0388 6.80568C16.9274 6.91958 16.7054 7.19238 16.5454 7.41202L16.2547 7.81135L16.2186 7.59413C16.1811 7.36895 16.2783 7.06882 16.352 7.18177C16.4108 7.27185 16.7859 6.85096 17.0408 6.409C17.3115 5.93952 17.4988 5.33399 17.5523 4.756C17.5911 4.33583 17.5872 4.31195 17.4919 4.39451C17.4358 4.44314 17.2567 4.76368 17.0938 5.10676L16.7977 5.73062L16.8265 5.35113L16.8553 4.9717L16.6054 5.38951C16.4679 5.61931 16.3728 5.75708 16.394 5.69567C16.5547 5.22934 16.7415 4.38674 16.7717 3.99114L16.8081 3.51552L16.5945 3.88482C16.4769 4.08796 16.2755 4.52719 16.1469 4.86087C15.9589 5.34847 15.9097 5.43372 15.8963 5.29502C15.8872 5.2001 15.9377 4.93597 16.0087 4.70807C16.1646 4.20698 16.2586 3.2029 16.1496 3.20198C16.0737 3.20133 15.7161 3.84074 15.7149 3.97937C15.7131 4.17683 15.6058 3.91607 15.5079 3.47649C15.3841 2.91995 14.7884 0.884924 14.7363 0.840417C14.7168 0.823733 14.7164 0.87317 14.7353 0.950319ZM15.3903 5.35266C15.3717 5.36974 15.3382 5.33838 15.3161 5.28299C15.2841 5.20293 15.291 5.19655 15.3501 5.25192C15.3909 5.29029 15.409 5.33562 15.3903 5.35266ZM15.5748 6.28323C15.5745 6.31402 15.5473 6.32342 15.5144 6.3041C15.4814 6.28479 15.4546 6.2438 15.4549 6.21301C15.4552 6.18221 15.4823 6.17281 15.5153 6.19213C15.5483 6.21145 15.575 6.25244 15.5748 6.28323ZM12.5115 7.34245C12.6573 7.65164 12.9018 8.15763 13.0547 8.46689C13.2077 8.77614 13.3196 9.01645 13.3033 9.00091C13.2871 8.98538 13.1134 8.74129 12.9173 8.45855C12.6444 8.06497 12.5315 7.83556 12.4356 7.48005C12.3667 7.2247 12.2849 6.97059 12.2538 6.91545C12.1971 6.81503 12.1766 6.71256 12.2221 6.75673C12.2354 6.76972 12.3656 7.03326 12.5115 7.34245ZM15.376 8.13665C15.3812 8.24778 15.2671 8.1444 15.0618 7.85189L14.836 7.53016L15.105 7.8124C15.253 7.96763 15.3749 8.11357 15.376 8.13665ZM14.0214 9.60875C14.4146 10.5161 14.4288 10.8047 14.0507 10.2008C13.9118 9.97893 13.7983 9.72623 13.7985 9.63922C13.7988 9.55221 13.761 9.32955 13.7146 9.14438C13.6317 8.81384 13.6059 8.61406 13.6676 8.78004C13.6849 8.82638 13.8441 9.19929 14.0214 9.60875ZM15.4843 9.15554C15.4683 9.17013 15.4199 9.12622 15.3765 9.05799C15.3014 8.93938 15.3027 8.93821 15.4056 9.03142C15.4649 9.08511 15.5003 9.14095 15.4843 9.15554ZM14.6935 10.0486L14.6905 10.3285L14.5761 9.90758C14.5131 9.67608 14.448 9.43617 14.4314 9.37443C14.4149 9.3127 14.4677 9.37614 14.5489 9.51541C14.6512 9.69092 14.6956 9.85451 14.6935 10.0486ZM15.2306 9.72064C15.2103 9.73922 15.1617 9.69531 15.1226 9.62308C15.0547 9.49748 15.0564 9.49598 15.1596 9.58924C15.2191 9.64294 15.251 9.70205 15.2306 9.72064ZM25.1246 9.90934C25.0647 9.97518 25.0866 9.99311 25.2518 10.0134C25.3615 10.0269 25.2074 10.0375 24.9092 10.0368L24.3671 10.0357L24.6992 9.93753C25.1308 9.80995 25.2202 9.80399 25.1246 9.90934ZM15.4906 10.0133C15.5647 10.1028 15.5626 10.1047 15.4676 10.0343C15.3679 9.96027 15.3364 9.91404 15.386 9.91446C15.3985 9.91456 15.4456 9.95903 15.4906 10.0133ZM10.7903 10.2534C10.866 10.3447 10.8632 10.3458 10.7524 10.2689C10.6865 10.2232 10.6214 10.1785 10.6076 10.1697C10.5939 10.1608 10.611 10.1539 10.6456 10.1542C10.6802 10.1545 10.7453 10.1991 10.7903 10.2534ZM16.4651 11.3794C16.4126 11.5937 16.4686 11.5912 16.7243 11.3676L16.9304 11.1874L16.6957 11.5328C16.5665 11.7228 16.4406 11.8792 16.4157 11.8804C16.3598 11.883 16.3602 11.2994 16.4161 11.2483C16.4931 11.1779 16.5061 11.2125 16.4651 11.3794ZM14.5588 11.9213C14.7245 12.1934 14.86 12.4356 14.8598 12.4596C14.8592 12.5303 14.2928 11.746 14.146 11.4712C14.0171 11.2298 14.0166 11.2232 14.1343 11.3226C14.202 11.3798 14.393 11.6492 14.5588 11.9213ZM15.3048 12.1534C15.3379 12.3356 15.3341 12.3419 15.2521 12.2403C15.2035 12.1801 15.1652 12.0537 15.167 11.9596C15.1711 11.7487 15.2519 11.8624 15.3048 12.1534ZM17.9353 12.0289C17.9352 12.0405 17.8874 12.0842 17.8291 12.126C17.733 12.1948 17.7309 12.1928 17.8065 12.1047C17.886 12.0121 17.9357 11.9829 17.9353 12.0289ZM15.0335 12.711C15.1 12.8436 15.0988 12.8453 15.0113 12.7421C14.9603 12.6819 14.9187 12.6081 14.919 12.578C14.9196 12.5069 14.9472 12.5389 15.0335 12.711ZM8.58851 12.6918C8.60221 12.7032 8.43954 12.7085 8.22701 12.7036C7.94271 12.6971 7.88048 12.6833 7.99152 12.6514C8.12726 12.6124 8.52559 12.6393 8.58851 12.6918ZM15.8732 13.2435C15.8171 13.2912 15.8095 13.2621 15.8401 13.1168C15.8619 13.0131 15.8847 12.8873 15.8907 12.8373C15.8967 12.7873 15.9116 12.8443 15.9238 12.9639C15.9366 13.0892 15.9152 13.2077 15.8732 13.2435ZM12.2648 13.0425C12.6758 13.3018 13.5329 13.9388 13.5051 13.9641C13.4288 14.0338 12.7398 13.6029 12.3178 13.2216C11.8126 12.7653 11.8096 12.7551 12.2648 13.0425ZM15.2463 13.0488C15.2969 13.1416 15.3247 13.2174 15.3082 13.2173C15.2916 13.2171 15.2366 13.1411 15.1861 13.0483C15.1355 12.9555 15.1076 12.8796 15.1242 12.8798C15.1407 12.8799 15.1957 12.956 15.2463 13.0488ZM14.6012 13.4546C14.6784 13.5216 14.794 13.6456 14.858 13.73C14.9717 13.8803 14.9673 13.8793 14.6594 13.6873C14.4863 13.5792 14.3299 13.4839 14.3118 13.4755C14.2938 13.467 14.213 13.3895 14.1323 13.3031L13.9856 13.146L14.2232 13.2394C14.3539 13.2908 14.524 13.3876 14.6012 13.4546ZM8.64881 13.2727C8.56549 13.3323 8.46563 13.3813 8.42695 13.3816C8.38822 13.3819 8.3068 13.3947 8.24601 13.4101C8.18517 13.4254 8.27147 13.3773 8.43774 13.3031C8.8071 13.1385 8.84425 13.1331 8.64881 13.2727ZM18.548 14.3646C18.5945 14.4359 18.5147 14.4352 18.3974 14.3633C18.3199 14.3159 18.3216 14.3083 18.4094 14.3083C18.4654 14.3083 18.5277 14.3336 18.548 14.3646ZM20.9469 14.7568C21.0085 14.8341 21.2509 15.0264 21.4853 15.1843C21.8181 15.4083 21.8721 15.4624 21.7313 15.4308C21.6321 15.4085 21.3484 15.2781 21.1008 15.1409C20.8532 15.0038 20.4416 14.7997 20.186 14.6874C19.9306 14.5751 19.7216 14.475 19.7217 14.4649C19.7217 14.455 19.9722 14.4849 20.2783 14.5315C20.7461 14.6027 20.8526 14.6386 20.9469 14.7568ZM11.7606 15.676C11.5446 15.745 11.2115 15.8649 11.0204 15.9424C10.8293 16.0199 10.673 16.0757 10.673 16.0664C10.6735 16.0095 11.462 15.6201 11.6385 15.5894C12.084 15.5123 12.1426 15.5538 11.7606 15.676ZM9.12569 16.273C8.96823 16.359 8.83378 16.3958 8.76671 16.3712C8.68529 16.3414 8.73122 16.3092 8.95825 16.2371C9.37528 16.1045 9.41761 16.1136 9.12569 16.273ZM12.1779 16.1815C12.1778 16.1942 12.062 16.2638 11.9206 16.3361C11.7792 16.4084 11.5818 16.5141 11.4819 16.5711C11.3192 16.6638 11.3106 16.6644 11.3992 16.5763C11.5612 16.4154 12.1786 16.1023 12.1779 16.1815ZM22.0108 16.43C22.1171 16.4728 22.2577 16.5669 22.3234 16.639L22.4427 16.7701L22.2029 16.6356C21.6929 16.3496 21.6211 16.2728 22.0108 16.43ZM8.80266 16.4356C8.80254 16.4499 8.74124 16.4913 8.66636 16.5276C8.54297 16.5874 8.53806 16.5849 8.6137 16.5011C8.69141 16.415 8.80317 16.3763 8.80266 16.4356ZM18.316 16.9779C18.486 17.098 18.5907 17.2088 18.5603 17.2366C18.5094 17.2831 17.9466 16.9223 17.9048 16.8164C17.8629 16.7105 18.0312 16.7766 18.316 16.9779ZM10.5397 17.0815C10.392 17.1954 10.1237 17.4136 9.9434 17.5664L9.61566 17.8442L9.79036 17.6009C9.93025 17.406 10.6572 16.8732 10.7818 16.8743C10.7964 16.8744 10.6874 16.9677 10.5397 17.0815ZM18.5518 18.186C18.6921 18.4491 18.8648 18.924 18.9874 19.3842C19.0992 19.8034 19.2054 20.176 19.2235 20.2121C19.2415 20.2482 19.2099 20.2184 19.1533 20.1459C19.0967 20.0734 18.9125 19.6687 18.744 19.2465C18.5753 18.8244 18.322 18.2513 18.181 17.9729C18.0399 17.6946 17.9133 17.4415 17.8996 17.4106C17.8859 17.3797 17.9748 17.4435 18.0971 17.5523C18.2194 17.6611 18.4241 17.9463 18.5518 18.186ZM11.1727 17.5173C10.9511 17.6802 10.658 17.8423 10.6583 17.8017C10.6586 17.7693 11.2737 17.3822 11.3236 17.3831C11.3406 17.3834 11.2727 17.4438 11.1727 17.5173ZM20.2969 17.655C20.3741 17.7326 20.4237 17.796 20.4071 17.7959C20.3905 17.7957 20.3138 17.7321 20.2367 17.6544C20.1595 17.5768 20.1099 17.5134 20.1265 17.5135C20.1431 17.5137 20.2198 17.5773 20.2969 17.655ZM17.8555 18.4399C17.8352 18.5749 17.8154 18.7889 17.8116 18.9155C17.8056 19.1098 17.7875 19.073 17.6954 18.6786C17.6076 18.3036 17.6007 18.1904 17.6601 18.1035C17.7304 18.0007 17.7381 18.0003 17.8132 18.0948C17.8656 18.1607 17.8799 18.2776 17.8555 18.4399ZM26.544 18.3818C26.5544 18.3901 26.5375 18.4111 26.5064 18.4286C26.4754 18.4461 26.3994 18.4065 26.3376 18.3407C26.2254 18.2212 26.2255 18.2211 26.3751 18.2939C26.4576 18.334 26.5335 18.3736 26.544 18.3818ZM21.73 18.5778C21.77 18.6624 21.7805 18.7062 21.7531 18.6752C21.7257 18.6441 21.6229 18.5327 21.5247 18.4275C21.3525 18.2432 21.3516 18.2397 21.5016 18.3301C21.5872 18.3818 21.69 18.4932 21.73 18.5778ZM14.9976 20.0036C15.0545 20.475 15.0269 20.5522 14.9428 20.1571C14.8469 19.7066 14.847 19.7084 14.9103 19.7089C14.9388 19.7091 14.9781 19.8418 14.9976 20.0036ZM15.0703 20.7321C15.0533 20.7705 15.0399 20.7388 15.0406 20.6619C15.0412 20.5849 15.0552 20.5535 15.0715 20.5921C15.088 20.6308 15.0874 20.6938 15.0703 20.7321ZM19.8556 22.439C20.4226 23.9167 20.407 23.8661 20.1848 23.5051C20.08 23.3348 19.9038 23.0669 19.7932 22.9098C19.6726 22.7383 19.5928 22.5543 19.5936 22.4498C19.595 22.2888 19.4648 21.6036 19.3832 21.3426C19.3639 21.2809 19.3629 21.2433 19.3809 21.2591C19.399 21.275 19.6126 21.8059 19.8556 22.439ZM14.0445 22.6551C14.0474 22.776 14.0207 22.8369 13.965 22.8364C13.8344 22.8353 13.8211 22.7282 13.8954 22.2759L13.9643 21.8565L14.0022 22.1648C14.023 22.3344 14.042 22.555 14.0445 22.6551ZM19.4395 24.0167C19.4225 24.0551 19.4091 24.0234 19.4098 23.9464C19.4104 23.8695 19.4243 23.8381 19.4407 23.8767C19.4571 23.9154 19.4566 23.9784 19.4395 24.0167ZM19.5709 24.721C19.5722 24.7936 19.547 24.8349 19.5133 24.8152C19.4804 24.7959 19.4577 24.6367 19.463 24.4615C19.4726 24.145 19.4729 24.1444 19.5206 24.3673C19.5469 24.4907 19.5696 24.6499 19.5709 24.721Z\"\n        fill=\"#4B8C74\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 30 / 51,\n  svg: PalmTree,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/honeymooning-in-italy/floralPattern.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Floral Pattern', 'sticker name', 'web-stories');\n\nfunction FloralPattern({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M46.714 26.085c-.165-.08-.332-.127-.428-.116-.093.01-.168-.005-.214-.042-.059-.048-.11-.14-.098-.178.01-.032-.018-.067-.059-.073-.023-.003-.08.088-.083.13 0 .015-.006.058-.012.096-.01.056-.003.093.037.197.066.176.145.266.328.379.072.044.137.086.146.093.03.025.27.077.334.072a.624.624 0 01.116.007.525.525 0 00.183-.02.6.6 0 00.235-.112.811.811 0 00.131-.106c.008-.013.02-.024.03-.024.008 0 .03-.026.047-.056.018-.03.057-.086.087-.125a.377.377 0 00.07-.124c.047-.17.063-.257.05-.278a.05.05 0 010-.045c.014-.025-.026-.125-.057-.143-.025-.014-.06-.003-.076.026a.69.69 0 00-.033.122c-.02.096-.022.1-.094.188-.112.134-.21.197-.327.21-.12.013-.142.007-.313-.078zM37.508 40.847c0 .02.08.05.13.048.026 0 .037-.009.044-.034a.738.738 0 01.196-.231.923.923 0 00.086-.068 1.91 1.91 0 01.139-.104c.062-.044.116-.085.12-.092a.32.32 0 01.058-.047.279.279 0 00.062-.054.455.455 0 01.086-.071c.041-.029.101-.077.133-.108.032-.03.08-.072.107-.092.082-.062.319-.385.46-.629.062-.107.112-.415.09-.558a2.397 2.397 0 01-.015-.144c-.009-.12-.069-.224-.139-.24l-.046-.012-.041.081a.282.282 0 01-.061.09.306.306 0 00-.066.059.468.468 0 01-.208.145c-.03.008-.06.023-.067.034-.007.011-.035.021-.063.022a.457.457 0 00-.098.017 1.54 1.54 0 01-.393.03c-.139-.01-.288-.07-.345-.141a.35.35 0 00-.056-.06.537.537 0 01-.111-.18.477.477 0 00-.049-.099c-.052-.08-.1-.093-.206-.052-.12.045-.147.068-.235.203l-.078.12-.115-.072a1.16 1.16 0 00-.355-.154 1.112 1.112 0 01-.386-.13c-.08-.045-.082-.045-.11-.014a.151.151 0 00-.031.052.982.982 0 01-.022.073c-.036.106-.03.224.023.41.036.13.093.244.132.267.029.016.083.109.073.125-.005.009-.042.024-.082.035a1.2 1.2 0 00-.29.12.686.686 0 00-.119.099.847.847 0 00-.188.26l-.117.203a.878.878 0 00-.074.207.492.492 0 01-.018.069c-.051.154-.05.148-.058.287-.008.138-.007.166.007.216.009.03.012.06.007.068-.01.016.023.097.044.11.027.015.068-.032.1-.116.03-.073.041-.09.112-.153a.506.506 0 01.157-.104c.016-.028.335-.094.5-.103.06-.004.125-.01.145-.015.07-.016.17-.017.178-.002.006.011-.006.037-.038.08a.485.485 0 00-.085.24.232.232 0 01-.01.064c-.012.04-.009.051.02.072.025.018.04.02.059.009a.129.129 0 01.071-.01c.026.004.12.007.21.007.182 0 .35-.04.436-.102a.917.917 0 00.146-.12c.03-.034.107-.063.131-.049.009.005.02.03.026.056a.413.413 0 00.048.106c.021.032.038.066.039.076zM44.355 39.097a.475.475 0 00.193-.097.123.123 0 01.04-.04c.022-.011.025-.023.02-.068-.017-.15-.052-.2-.172-.247-.07-.028-.194-.006-.246.042a.342.342 0 00-.084.178c-.008.097.159.252.249.232zM44.523 40.618c.087.1.101.112.156.129.033.01.072.018.086.019.014 0 .034.006.044.011.045.027.326-.028.409-.08.045-.027.088-.09.151-.221a.322.322 0 01.06-.093c.012-.008.025-.03.03-.053a.832.832 0 01.02-.076c.022-.06-.039-.307-.093-.384a.484.484 0 01-.024-.039c-.048-.086-.196-.17-.315-.179a.956.956 0 01-.11-.014c-.05-.011-.242.038-.313.08a.892.892 0 00-.109.079.865.865 0 01-.085.065c-.051.033-.06.05-.068.143a.379.379 0 01-.021.103c-.018.031.023.267.058.342.016.032.072.108.124.168zM44.523 33.88c-.042.03-.056.049-.19.255a.693.693 0 01-.081.108.714.714 0 00-.081.115.641.641 0 01-.09.122l-.088.057c-.074.049-.073.048-.066.077.008.029.036.044.088.047l.093.007a.844.844 0 00.1.002.18.18 0 01.063.006c.01.004.05-.004.092-.018a.392.392 0 01.115-.024.12.12 0 00.065-.014 3.66 3.66 0 01.236-.124.486.486 0 00.098-.084l.089-.095a.486.486 0 00.117-.225.243.243 0 01.018-.078.063.063 0 00.004-.046.083.083 0 01.002-.05c.007-.018.001-.038-.017-.056a.392.392 0 00-.226-.075.432.432 0 01-.085-.003c-.054-.012-.157.027-.256.097zM45.569 39.372a.232.232 0 00.05-.077c.011-.033.021-.044.036-.042.02.003.111.13.202.28.024.04.082.114.129.164s.1.11.12.133c.018.023.048.05.066.06.018.01.034.025.036.033a.919.919 0 00.172.157.776.776 0 01.083.07c.118.116.54.369.675.404l.113.032c.043.014.125-.023.133-.059.004-.02-.005-.033-.03-.048a1.252 1.252 0 01-.12-.092 50.226 50.226 0 00-.15-.128.332.332 0 01-.075-.082.205.205 0 00-.055-.064.419.419 0 01-.113-.178.433.433 0 00-.047-.081.564.564 0 01-.06-.126 1.052 1.052 0 00-.06-.143c-.039-.068-.074-.19-.11-.383a4.002 4.002 0 00-.04-.19c-.008-.028-.01-.056-.007-.062a.856.856 0 00-.015-.22 1.013 1.013 0 01-.015-.115 2.55 2.55 0 00-.026-.188.594.594 0 01-.014-.129.408.408 0 00-.023-.112 16.315 16.315 0 01-.085-.316 1.666 1.666 0 00-.066-.223c-.006-.003-.017-.031-.024-.062a.532.532 0 00-.062-.132.792.792 0 01-.065-.123 1.132 1.132 0 00-.092-.16 4.012 4.012 0 01-.094-.148.144.144 0 00-.038-.045c-.01-.007-.02-.019-.02-.027a.707.707 0 00-.125-.182.245.245 0 01-.05-.061.24.24 0 00-.06-.066c-.016-.01-.03-.024-.03-.033 0-.008-.014-.024-.032-.034-.017-.01-.033-.026-.036-.036a.827.827 0 00-.25-.192c-.047 0-.069.054-.061.154.009.115-.009.28-.038.361-.03.087-.139.266-.164.273a.232.232 0 01-.091-.028.979.979 0 00-.232-.07c-.044 0-.031.087.024.168.049.072.109.27.105.348-.001.026.002.05.008.053.007.004.01.036.007.07a.748.748 0 00.007.134c.005.037.009.098.008.136-.007.213-.015.315-.026.334a.278.278 0 00-.005.103.433.433 0 01.002.09c-.003.005 0 .03.007.056l.035.143a.64.64 0 00.087.192c.034.053.067.105.072.116.01.018.07.093.125.155.06.068.124.174.162.269l.041.103.043-.01a.211.211 0 00.084-.052c.021-.022.055-.055.074-.072zM47.532 29.926c-.044-.067-.059-.081-.1-.094a.328.328 0 00-.23.037c-.064.04-.11.118-.106.175.007.072.107.203.157.204.015 0 .042.005.06.011a.37.37 0 00.188-.023c.042-.025.079-.104.075-.16a.243.243 0 01.002-.064.318.318 0 00-.047-.086zM28.258 32.812a.657.657 0 00.23-.093.83.83 0 01.202-.101c.108-.038.545-.157.556-.15a.25.25 0 00.075-.01 2.22 2.22 0 01.366-.045.73.73 0 01.113-.006l.09.004c.021 0 .064.002.095.005.084.006.116-.014.13-.082l.012-.054-.066-.032c-.081-.04-.156-.043-.414-.016a4.296 4.296 0 00-.184.023.176.176 0 01-.064.003 1.836 1.836 0 00-.35.09 1.044 1.044 0 01-.175.062 1.243 1.243 0 00-.219.083 1.137 1.137 0 01-.157.075 1.278 1.278 0 00-.194.1.584.584 0 00-.095.071c-.012.02.019.067.049.073zM37.23 34.65c.042.034.08.04.342.055.023.001.05.007.061.013a.532.532 0 00.27.026.448.448 0 01.12-.01c.04.008.108-.02.127-.054a.154.154 0 00.007-.082c-.01-.051-.014-.057-.063-.077a.665.665 0 00-.265-.018.172.172 0 01-.07-.003.356.356 0 00-.133.02 1.11 1.11 0 01-.202.035l-.144.01a.241.241 0 00-.067.014c-.035.016-.032.03.017.07z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M35.92 37.384a.432.432 0 01-.033.112.445.445 0 00-.032.113.29.29 0 01-.112.167c-.063.034.03.12.152.142.11.02.162.003.24-.078.13-.14.134-.14.18-.013.074.205.226.503.27.528.024.014.096-.01.112-.037.014-.026-.011-.147-.063-.297a8.618 8.618 0 01-.054-.165 1.052 1.052 0 00-.053-.137 1.845 1.845 0 01-.06-.133.44.44 0 00-.045-.093c-.006-.003-.015-.035-.02-.071a.346.346 0 00-.048-.122 1.615 1.615 0 01-.141-.306.338.338 0 00-.053-.098.114.114 0 01-.03-.05.115.115 0 00-.034-.05c-.016-.014-.03-.035-.03-.045 0-.027-.017-.055-.119-.213a1.68 1.68 0 01-.097-.164.168.168 0 00-.033-.052.518.518 0 01-.057-.088 3.261 3.261 0 00-.105-.177c-.076-.12-.104-.141-.17-.127-.019.005-.04.024-.056.051-.032.055-.025.094.035.193.026.043.056.095.066.117.01.022.02.042.025.044.004.002.032.052.063.112.032.06.07.124.085.145.016.02.03.047.033.06a.054.054 0 00.02.034c.01.006.027.036.037.068.01.032.025.062.032.066.028.016.106.346.088.376a.164.164 0 00.01.064c.008.03.011.06.007.068a.177.177 0 00-.01.056zM40.104 37.08c-.12-.028-.195.001-.274.107-.023.03-.058.086-.078.124-.044.086-.042.142.01.244.032.063.048.08.11.118.086.05.16.087.171.083l.077-.033c.07-.03.089-.052.158-.19a.586.586 0 01.044-.065c.028-.036.038-.064.043-.125.006-.073.003-.081-.047-.136a.372.372 0 00-.214-.126zM41.974 34.765c-.07.062-.092.098-.08.133.009.023.015.025.043.01.017-.009.039-.012.048-.007a.243.243 0 00.083.006c.092-.005.137-.004.152.005.008.005.039-.002.07-.015a.434.434 0 01.115-.026c.05-.002.203-.035.345-.073a1.01 1.01 0 00.109-.042.995.995 0 01.11-.043.36.36 0 00.079-.035c.021-.013.048-.03.06-.036a.767.767 0 00.07-.053 1.13 1.13 0 01.072-.056.119.119 0 00.033-.032.243.243 0 01.057-.05c.042-.028.068-.059.177-.206.093-.127.227-.42.235-.514a.491.491 0 00-.019-.187c-.006-.01-.006-.026-.001-.035.012-.022-.03-.179-.068-.258a6.707 6.707 0 01-.052-.106c-.036-.076-.07-.069-.223.048a3.52 3.52 0 01-.158.117.735.735 0 00-.181.127.194.194 0 01-.063.052c-.044.024-.05.024-.085-.006a1.64 1.64 0 00-.116-.085c-.077-.053-.08-.053-.123-.033a.16.16 0 00-.061.05.43.43 0 01-.098.082c-.08.053-.086.06-.16.19-.083.146-.107.219-.1.31a.34.34 0 01-.007.094.228.228 0 00-.002.084.15.15 0 01.001.06.182.182 0 00-.002.064c.004.049-.003.065-.1.235-.084.146-.115.192-.16.231zM44.873 30.625c.019.01.041.012.056.003.013-.009.051-.008.087.002.035.01.08.02.102.024.105.017.266.14.328.25.018.033.053.08.077.106l.109.12c.086.101.182.17.274.2.04.013.082.022.09.02a.066.066 0 01.04.01.22.22 0 00.067.017c.077.008.249.056.293.081.044.026.081.013.071-.025a.062.062 0 01.006-.04c.053-.092-.04-.376-.175-.537-.081-.095-.388-.286-.483-.3a.506.506 0 01-.103-.035.496.496 0 00-.178-.05c-.016 0-.06-.004-.098-.007a.274.274 0 00-.082.001c-.008.004-.023.002-.034-.004a.195.195 0 00-.086-.003.235.235 0 01-.078.001c-.007-.003-.028-.001-.047.005s-.04.008-.047.004a.512.512 0 00-.193.045c-.048.04-.047.082.004.112zM34.827 43.697c-.032.053-.032.056.006.134.036.074.043.08.104.106a.29.29 0 00.092.024c.051-.005.17-.056.182-.08.027-.045-.038-.204-.103-.253a.199.199 0 00-.208-.01.258.258 0 00-.073.079zM36.743 37.122c.026-.046.017-.132-.018-.178a.238.238 0 01-.04-.078.138.138 0 00-.036-.063.113.113 0 01-.032-.05.065.065 0 00-.029-.04.402.402 0 01-.073-.09.612.612 0 00-.06-.081.333.333 0 01-.045-.057.268.268 0 00-.052-.06c-.01-.007-.02-.02-.02-.028 0-.01-.026-.031-.057-.05-.047-.026-.06-.029-.07-.011-.014.026-.01.09.007.1.007.005.053.105.102.224.049.119.094.219.1.222.006.003.019.031.029.062a.695.695 0 00.139.223c.03.017.137-.014.155-.045zM36.306 35.978a.707.707 0 00.09.091.114.114 0 01.035.036c.038.065.217.242.24.236.026-.008.045-.165.03-.261-.018-.12-.023-.129-.137-.24a4.435 4.435 0 01-.118-.118.32.32 0 00-.062-.05 1.158 1.158 0 01-.21-.188l-.053-.06-.082.009a.339.339 0 00-.096.02.057.057 0 00-.017.027.963.963 0 01-.02.063c-.022.06-.009.079.116.18.195.157.216.176.284.255zM35.885 43.515a1.036 1.036 0 00.445-.097l.085-.053c.018-.01.04-.018.05-.017.01.002.061.06.114.128.098.128.24.257.314.282a.11.11 0 01.05.035.05.05 0 00.04.023.6.6 0 01.085.015c.032.008.068.01.08.005a.055.055 0 01.041.003c.027.016.145-.023.188-.061a.403.403 0 00.066-.083c.023-.04.025-.057.012-.078a.97.97 0 00-.178-.125c-.166-.1-.2-.13-.237-.219a1.128 1.128 0 00-.063-.112.449.449 0 01-.064-.178 5.177 5.177 0 00-.023-.138 2.751 2.751 0 01-.014-.345l-.003-.128a.24.24 0 01.002-.067c.005-.008.015-.11.027-.264a.126.126 0 01.012-.044.32.32 0 00-.008-.118.395.395 0 01-.013-.113.787.787 0 00.025-.209.654.654 0 01.015-.126c.005-.008.002-.039-.007-.068-.008-.03-.012-.06-.007-.068.004-.007.002-.033-.005-.057-.008-.024-.009-.052-.003-.062.016-.028-.001-.081-.033-.1-.078-.044-.16.033-.16.154-.001.036-.005.08-.009.097a.169.169 0 00-.002.058c.018.1-.016.448-.06.6l-.03.107a.732.732 0 00-.02.083 3.107 3.107 0 01-.156.396.969.969 0 01-.103.16c-.034.04-.082.1-.108.134a.248.248 0 01-.117.09 2.563 2.563 0 00-.152.069.358.358 0 01-.091.037.248.248 0 00-.068.004c-.033.004-.09.009-.125.01a.192.192 0 00-.088.019.152.152 0 00-.059.115.853.853 0 01-.003.07c-.002.021.015.05.054.09.093.096.226.16.304.146zM38.51 27.357a.986.986 0 00.174-.229.24.24 0 01.02-.049l.193-.31c.102-.165.21-.329.238-.364.062-.078.218-.24.245-.257a.547.547 0 00.049-.035.352.352 0 01.05-.033c.012-.006.078-.05.146-.096a.852.852 0 01.161-.093c.02-.005.043-.018.05-.03.013-.023-.018-.102-.048-.12a.263.263 0 01-.05-.047c-.023-.027-.039-.036-.064-.038a.421.421 0 01-.102-.03.966.966 0 00-.324-.039c-.03.008-.056-.016-.074-.067a.187.187 0 00-.025-.054.226.226 0 01-.029-.056.176.176 0 00-.033-.058.441.441 0 01-.056-.057c-.093-.107-.264-.168-.361-.129a.135.135 0 00-.056.04c-.019.032 0 .086.043.123a.39.39 0 01.071.098c.04.08.103.334.098.403-.01.146-.017.211-.023.222a.36.36 0 00-.006.09c.002.09-.008.142-.061.33a5.172 5.172 0 00-.054.202.663.663 0 01-.062.15.45.45 0 00-.049.105.447.447 0 01-.065.115c-.19.268-.207.298-.194.328.032.074.117.068.198-.015zM30.38 30.93c.132.273.152.309.193.342.087.07.138.063.156-.024.008-.036 0-.063-.035-.12a2.351 2.351 0 01-.159-.286l-.074-.156a1.012 1.012 0 01-.046-.133.335.335 0 00-.033-.09c-.017-.01-.149-.53-.15-.597a.391.391 0 00-.013-.09c-.005-.014-.005-.033 0-.042a.486.486 0 000-.191.187.187 0 01-.004-.069c.01-.016-.054-.05-.08-.043-.032.01-.034.015-.037.161-.005.232-.005.257.007.317a.174.174 0 01.003.07.83.83 0 00.037.177c.024.09.041.168.038.173-.02.035.102.405.197.602zM26.762 31.672c.007.007.045.014.085.015.04 0 .08.005.087.009a.14.14 0 00.057.003.727.727 0 01.154.017c.11.023.305.018.36-.008a.164.164 0 01.064-.014c.03 0 .076-.02.178-.084a.865.865 0 01.112-.052c.078-.03.132-.056.2-.094.06-.034.187-.073.293-.09a1.4 1.4 0 00.101-.022.258.258 0 01.099-.002.194.194 0 00.08 0 .215.215 0 01.09.002.305.305 0 00.074.01c.01-.003.036.007.059.02.052.03.089.02.09-.025.001-.017-.008-.037-.02-.044-.012-.007-.022-.02-.023-.028 0-.024-.158-.11-.262-.144-.13-.043-.3-.077-.427-.088-.296-.024-.318-.023-.527.03-.113.03-.208.051-.213.048a1.335 1.335 0 00-.378.189.47.47 0 00-.092.072.75.75 0 01-.081.072c-.02.015-.056.044-.079.064-.054.048-.097.125-.081.144z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M39.193 25.375c.022.024.098.024.103-.001.001-.01.016-.072.032-.14a.728.728 0 00.021-.184.536.536 0 01-.001-.1 1.127 1.127 0 00-.02-.186 1.203 1.203 0 01-.02-.152.638.638 0 00-.05-.227c-.028-.058-.036-.065-.078-.074a.178.178 0 00-.087.007c-.077.032-.103.125-.065.233.041.116.096.328.088.341-.004.007 0 .037.008.067.008.03.011.06.006.069-.013.023.041.323.063.347zM29.58 30.656a.845.845 0 01.067.11c.022.049.053.084.18.208.095.093.14.122.2.126.028.002.046-.006.057-.026.014-.024.01-.035-.018-.06-.138-.123-.202-.199-.23-.273a.215.215 0 00-.035-.066c-.032-.018-.12-.431-.1-.468.002-.005.009-.07.014-.147.006-.075.014-.143.017-.15.004-.006.012-.072.018-.147l.018-.207c.016-.176-.113-.522-.243-.65-.038-.037-.057-.042-.082-.019a.342.342 0 00-.029.116.847.847 0 01-.038.166.912.912 0 00-.084.359l-.015.25c-.007.115.052.37.121.524.097.214.137.292.181.354zM27.454 32.49c.08.046.257.042.462-.01a.673.673 0 00.285-.13c.07-.048.142-.102.158-.12a.178.178 0 01.052-.04.839.839 0 00.112-.075 1.428 1.428 0 01.183-.126c.055-.038.345-.133.368-.12a.225.225 0 00.08-.005c.096-.018.23-.004.267.028.016.014.035.022.044.017.008-.004.034.003.058.017.078.045.13.001.082-.069-.036-.052-.066-.069-.21-.117-.147-.05-.285-.074-.342-.062a.21.21 0 01-.074.003.9.9 0 00-.153.003l-.15.01c-.144.005-.517.094-.537.128-.004.008-.023.018-.04.021a.218.218 0 00-.075.046.197.197 0 01-.066.042c-.012.002-.025.009-.028.015a.38.38 0 01-.06.048 1.347 1.347 0 00-.198.184.789.789 0 01-.148.149.073.073 0 00-.031.029.113.113 0 01-.045.037.087.087 0 00-.041.039c-.01.021-.002.03.047.058zM38.469 23.256c.096.063.159.07.277.032.07-.023.084-.033.111-.08.038-.067.037-.184-.003-.293l-.026-.07-.098-.043c-.11-.049-.121-.048-.229.018-.095.059-.146.136-.15.23-.003.097.024.145.118.206zM28.364 28.925a1.927 1.927 0 00-.049.524c.008.137.122.512.189.623l.05.083c.125.215.388.488.572.592.075.043.09.047.123.034.052-.02.052-.038 0-.088a1.48 1.48 0 01-.22-.34 2.724 2.724 0 01-.053-.173.465.465 0 00-.04-.114c-.007-.003-.013-.044-.014-.09a6.412 6.412 0 00-.013-.29.513.513 0 01-.008-.172c.025-.045-.127-.397-.196-.453a.192.192 0 01-.05-.055.644.644 0 00-.102-.147.309.309 0 01-.056-.087c-.006-.037-.032-.047-.062-.024-.038.03-.04.037-.07.177zM45.456 24.289c.053-.011.063-.018.074-.054a.231.231 0 00.011-.073.117.117 0 01.012-.057.108.108 0 00.01-.057.108.108 0 01.005-.05.185.185 0 000-.079c-.007-.033-.006-.07 0-.08a.304.304 0 00.006-.103.413.413 0 01.011-.129c.03-.085-.037-.169-.138-.173-.025 0-.047.002-.049.005-.01.018-.041.16-.043.197a.187.187 0 01-.019.071.14.14 0 00-.014.068.66.66 0 01-.013.125c-.025.13-.023.281.004.339.028.059.055.068.143.05zM44.236 25.606c.028.016.103-.05.149-.132.078-.14.067-.207-.046-.29-.046-.032-.06-.037-.09-.027-.02.007-.043.009-.05.005-.017-.01-.09.012-.13.038a.353.353 0 00-.07.089c-.039.065-.04.075-.028.147.014.076.018.08.087.127.061.04.08.047.117.041.025-.004.053-.003.061.002zM44.735 26.043c-.157.004-.22.047-.257.174-.017.06-.016.083.006.132.024.052.034.062.097.091.095.044.182.044.244 0l.058-.037c.04-.024.108-.138.13-.222a.691.691 0 00-.065-.391 2.33 2.33 0 01-.038-.063.406.406 0 00-.024-.037 3.127 3.127 0 01-.048-.064c-.027-.038-.05-.054-.113-.08-.043-.02-.087-.03-.097-.024-.026.014-.016.048.027.092a.667.667 0 01.138.257c.014.075-.018.171-.058.172zM45.771 24.027l.119.03.182.045c.237.057.281.075.488.194.206.12.314.201.407.308.03.036.07.079.09.096.02.018.047.054.062.08.014.027.04.058.057.068.027.015.035.013.051-.015.026-.045.016-.107-.033-.206-.104-.209-.179-.311-.276-.379a.246.246 0 01-.068-.062 1.467 1.467 0 00-.302-.217.895.895 0 00-.342-.096.115.115 0 01-.057-.01.183.183 0 00-.07-.015.948.948 0 01-.13-.02.287.287 0 00-.17.005c-.1.03-.126.066-.098.131.018.043.022.046.09.063zM45.662 28.943a1.755 1.755 0 00-.024.112.396.396 0 01-.09.209.677.677 0 01-.091.11.464.464 0 00-.073.083 1.064 1.064 0 01-.219.206.154.154 0 00-.043.045.088.088 0 01-.05.036.503.503 0 00-.177.118.801.801 0 01-.13.1c-.1.07-.117.085-.12.116-.003.027.005.042.032.057.048.028.039.058-.026.086a.244.244 0 00-.057.03 1.926 1.926 0 01-.168.091c-.09.046-.187.101-.216.123a.23.23 0 01-.069.04c-.01 0-.022.01-.028.02a1.02 1.02 0 01-.18.137.176.176 0 00-.05.05.253.253 0 01-.074.06.22.22 0 00-.081.08.828.828 0 01-.143.186c-.026.015-.049.082-.04.117.012.056.104.012.274-.131.133-.112.292-.232.394-.297.24-.152.324-.202.37-.215.047-.014.21-.09.25-.116a.49.49 0 01.106-.04.84.84 0 00.133-.048 2.86 2.86 0 01.453-.138c.222-.055.501-.116.51-.11.005.002.034 0 .066-.006.115-.02.156-.023.172-.014.01.006.028.006.04.001a.329.329 0 01.166.008c.012.008.028.01.036.006a.033.033 0 01.03.001c.016.01.136.003.234-.013.074-.012.096-.04.094-.119 0-.062-.049-.112-.119-.125a.253.253 0 01-.06-.016.25.25 0 00-.094.005.698.698 0 01-.115.012 1.9 1.9 0 00-.108 0l-.123.002c-.028 0-.092.009-.14.018a.807.807 0 01-.145.014c-.031 0-.06.003-.063.01-.004.005-.027.01-.051.009a.959.959 0 00-.18.034c-.073.02-.22.056-.325.08a1.72 1.72 0 00-.246.073c-.03.016-.062.024-.07.02-.008-.005-.035 0-.06.012-.099.046-.086-.016.018-.086a.623.623 0 00.083-.062 1.52 1.52 0 01.257-.13 1.713 1.713 0 00.27-.142 3.308 3.308 0 00.454-.317l.089-.066a.883.883 0 00.151-.156c.01-.018.025-.033.032-.033.013 0 .13-.158.157-.209.122-.24.166-.349.175-.427a.477.477 0 01.02-.102c.005-.01.002-.028-.006-.042-.009-.014-.01-.048-.004-.077a.663.663 0 00-.023-.304 1.251 1.251 0 00-.126-.28.39.39 0 01-.05-.098c-.003-.02-.016-.041-.027-.048-.011-.006-.02-.018-.021-.026 0-.009-.023-.033-.05-.054a.328.328 0 01-.065-.061c-.021-.036-.067-.057-.087-.04-.013.01-.012.04.004.096a.3.3 0 01.017.092.492.492 0 01.003.157c-.009.097-.011.102-.122.303a2.082 2.082 0 00-.113.221c0 .009-.01.051-.022.094a.716.716 0 00-.024.11c-.002.049-.029.063-.088.047-.07-.018-.206-.006-.227.021-.035.044-.035.164 0 .287.028.103.03.133.013.203zM35.617 29.86a.741.741 0 01.126-.021c.007.004.132-.047.189-.077.012-.007.06-.03.106-.05.047-.02.11-.053.141-.072a.264.264 0 01.092-.036c.027-.002.046-.017.082-.066a.468.468 0 01.071-.08c.041-.029.063-.117.04-.158-.02-.03-.028-.036-.08-.045-.057-.01-.089.003-.202.086l-.06.041a.217.217 0 00-.05.044.205.205 0 01-.064.043.213.213 0 00-.062.04c-.004.008-.024.018-.043.023-.02.004-.039.014-.044.022a.39.39 0 01-.104.047.405.405 0 00-.104.047.379.379 0 01-.096.047.313.313 0 00-.1.053c-.012.022.008.116.028.128a.483.483 0 00.134-.017zM37.892 22.65a.367.367 0 01.202.005c.058.014.119.032.136.04.02.008.036.005.048-.01.043-.054-.094-.151-.287-.203-.109-.03-.13-.03-.269-.006.055-.063.092-.118.092-.14a.33.33 0 01.027-.087.5.5 0 00.004-.316c-.034-.076-.064-.064-.069.029a.38.38 0 01-.022.113c-.01.023-.026.057-.034.078a.428.428 0 01-.146.169c-.056.033-.102.024-.133-.025a.41.41 0 00-.135-.132.385.385 0 00-.233-.005c-.037.02-.093.114-.105.175a.506.506 0 00.046.225c.034.062.125.117.225.136a.48.48 0 00.095.006c-.098.18-.067.355.087.474.049.038.06.04.138.036a.485.485 0 00.114-.017c.038-.017.12-.159.123-.215a.33.33 0 00-.057-.177c-.02-.024-.019-.031.016-.079.034-.046.05-.054.137-.073zM38.522 24.126c.095.055.16.086.175.084a.194.194 0 01.07.01c.064.021.152.023.22.005a.767.767 0 00.286-.19c.12-.14.207-.438.163-.56-.005-.015-.005-.034 0-.042.009-.017-.044-.158-.065-.17-.008-.004-.016-.019-.018-.032-.006-.04-.06-.072-.123-.073a.22.22 0 00-.18.107c-.103.185-.128.238-.134.287-.01.076-.033.08-.14.031-.11-.05-.212-.072-.242-.053-.013.008-.043.011-.066.007-.023-.004-.046 0-.051.008-.005.01-.03.021-.055.027a.202.202 0 00-.076.041c-.085.08-.078.18.023.333.062.093.062.093.213.18zM32.215 29.395c-.01.018.013.115.033.137a.838.838 0 01.047.057c.062.083.134.15.274.251.16.115.48.296.527.297a.15.15 0 01.058.02c.017.009.056.024.086.032a30 30 0 01.108.03c.03.007.066.016.081.018.016.002.056.01.09.02.033.007.125.017.204.021.079.005.149.011.156.015.007.004.024 0 .038-.009.014-.009.033-.012.042-.007.009.005.04.005.067 0a.178.178 0 01.06-.005.7.7 0 00.215-.046.19.19 0 01.05-.027.241.241 0 00.08-.072c.037-.05.044-.067.04-.1-.006-.035-.01-.039-.055-.047-.056-.012-.135 0-.308.045a.494.494 0 01-.138.024c-.008-.005-.033-.003-.056.005a1.055 1.055 0 01-.478-.055 1.037 1.037 0 00-.16-.035.283.283 0 01-.08-.019 12.583 12.583 0 00-.166-.056 1.454 1.454 0 01-.425-.21.712.712 0 01-.239-.25.12.12 0 00-.115-.05c-.017.004-.033.011-.036.016zM47.416 25.294c.098.007.147-.074.103-.172-.026-.057-.113-.095-.178-.077-.053.015-.06.027-.062.105 0 .08.055.138.137.144zM47.775 32.856c.127.066.193.08.384.085a.607.607 0 00.32-.1c.05-.031.1-.062.113-.067a.517.517 0 00.162-.148.044.044 0 01.025-.031c.028-.011.091-.115.13-.217a.902.902 0 00.063-.252.076.076 0 01.01-.042.237.237 0 00.013-.087l.001-.149a1.548 1.548 0 00-.183-.673c-.07-.128-.133-.201-.204-.24-.02-.01-.037-.027-.041-.037a.33.33 0 00-.071-.065.339.339 0 01-.07-.064.228.228 0 00-.077-.049c-.056-.026-.072-.028-.081-.011-.013.021.01.052.063.083.05.028.157.155.172.202a.72.72 0 00.05.105c.075.132.14.392.14.561 0 .04.005.088.01.107.007.019.006.044-.001.056a.272.272 0 00-.018.085.284.284 0 01-.016.08.524.524 0 00-.026.1c-.015.076-.018.083-.068.128-.054.048-.12.07-.278.088-.042.004-.079.013-.082.019a.358.358 0 01-.077.044c-.1.047-.13.075-.205.192a.446.446 0 01-.195.189c-.07.04-.066.054.037.108zM47.868 30.509c.008.004.016.019.018.032.005.026.087.073.154.088.06.013.136-.029.176-.096.03-.052.03-.066.014-.13-.017-.065-.023-.074-.08-.106-.08-.046-.127-.05-.204-.017-.055.023-.065.033-.086.083-.023.056-.019.13.008.146zM49.457 41.2c-.004.064.036.07.14.021.064-.03.1-.057.13-.096a.207.207 0 01.058-.06c.01-.002.029-.022.041-.043a.226.226 0 01.051-.06c.056-.04.101-.36.07-.5a.075.075 0 00-.047-.057l-.039-.017-.06.083c-.032.045-.098.123-.147.173a.712.712 0 00-.105.127l-.062.133c-.047.1-.058.157-.04.216.007.02.011.056.01.08zM48.47 35.978c-.058.068-.065.094-.043.15.013.03.019.061.014.07-.025.042.114.238.23.326a.132.132 0 01.046.06c.005.028.001.036-.037.07a.728.728 0 00-.188.294c-.021.103-.02.118.025.174.041.05.043.051.11.055l.105.007a.204.204 0 00.078-.016l.091-.035a.895.895 0 00.227-.155c.02-.02.073-.095.116-.167l.08-.133.007-.122a.458.458 0 00-.12-.373c-.058-.07-.082-.09-.106-.097-.014-.004-.03-.017-.034-.028-.01-.028-.243-.126-.337-.141-.078-.013-.23.022-.263.06zM47.544 35.509a.11.11 0 01-.06-.002c-.038-.012-.098.001-.184.042-.046.021-.06.037-.114.13-.06.1-.062.11-.065.208a.9.9 0 00.115.41c.087.12.247.24.327.245.025 0 .043-.008.054-.027.014-.025.011-.033-.022-.056a.471.471 0 01-.147-.158.707.707 0 00-.036-.07.275.275 0 01-.008-.186c.013-.023.035-.034.083-.04a.596.596 0 00.127-.032c.054-.022.065-.032.109-.109.057-.1.058-.137.001-.233-.041-.07-.14-.137-.18-.122zM43.94 39.775c.04-.027.088-.126.092-.192a.264.264 0 00-.03-.11c-.032-.062-.035-.064-.122-.1-.114-.044-.163-.047-.218-.012a.223.223 0 00-.08.098c-.049.098-.047.162.007.218.024.025.056.059.07.076.053.059.206.07.28.022zM43.272 40.534c.046.075.072.094.16.114.098.023.12.02.173-.025.08-.065.098-.13.071-.253l-.022-.103-.071-.04c-.097-.057-.175-.066-.233-.028a.245.245 0 00-.078.335zM44.164 37.603c.009.005.015.03.013.054-.001.025.002.048.006.05.03.017.07.019.078.005a.106.106 0 01.036-.03c.02-.012.034-.036.059-.101a.395.395 0 01.048-.1.043.043 0 00.014-.033.476.476 0 01.009-.087.253.253 0 00.003-.09.07.07 0 01.007-.051c.018-.03-.027-.228-.066-.289-.04-.064.001-.086.12-.064.028.005.092-.001.142-.014a.284.284 0 01.107-.013c.01.005.023.006.03.002.008-.004.03.001.049.012.018.01.041.014.05.007.02-.016.025-.096.01-.172a.178.178 0 01-.003-.07c.018-.032-.042-.303-.08-.365a.183.183 0 01-.025-.075.113.113 0 00-.028-.064.334.334 0 01-.052-.079.196.196 0 00-.042-.063.395.395 0 01-.059-.059.856.856 0 00-.083-.083c-.03-.026-.038-.04-.029-.057.008-.012.023-.021.035-.02a.402.402 0 01.138.027c.024.01.068.024.098.032.03.007.098.032.152.056.192.083.274.109.32.099a.372.372 0 01.112.002c.05.008.114 0 .242-.035.095-.025.177-.044.182-.041.004.002.018 0 .03-.004.018-.007.02-.025.01-.084a.466.466 0 00-.034-.116c-.025-.046-.013-.066.036-.063a.286.286 0 00.064-.006.316.316 0 01.085 0c.03.004.056.002.059-.004.003-.005.033-.011.066-.014.134-.01.42-.103.511-.168a.848.848 0 01.092-.054c.07-.036.193-.204.216-.296a.258.258 0 00.005-.107.257.257 0 01-.01-.075.134.134 0 00-.019-.07l-.041-.06c-.032-.045-.064-.049-.103-.01a.464.464 0 01-.065.05.135.135 0 00-.04.038c-.022.037-.24.154-.38.203-.244.086-.592.166-.63.144-.009-.005-.024-.004-.034.004-.01.008-.038.013-.063.01a.597.597 0 00-.137.003.954.954 0 01-.157-.019 31.955 31.955 0 00-.272-.045 2.788 2.788 0 01-.31-.076 4.009 4.009 0 00-.212-.062.344.344 0 01-.086-.034 2.108 2.108 0 00-.501-.178.33.33 0 01-.074-.013c-.014-.008-.026-.01-.16-.015a.72.72 0 00-.142.005.336.336 0 01-.098.003c-.03-.003-.057 0-.062.007a.336.336 0 01-.094.044.376.376 0 00-.093.041c-.004.006-.027.018-.052.025a.56.56 0 00-.211.185c-.018.051-.147.077-.268.053-.102-.019-.283-.025-.292-.01-.003.006-.037.01-.075.011-.039 0-.073.006-.077.013a.26.26 0 01-.073.04 1.338 1.338 0 00-.093.042c-.073.04-.223.126-.252.144-.025.015-.057.064-.128.193-.092.167-.095.176-.092.24.003.053.011.073.035.086.042.024.065.022.116-.012a.153.153 0 01.075-.027.21.21 0 00.067-.01.45.45 0 01.153.014c.108.023.13.033.253.109a.64.64 0 01.163.126c.017.023.044.059.062.08.074.086.098.132.162.31.025.067.043.139.041.16-.002.02.002.04.008.043a.286.286 0 01.034.086c.013.044.04.108.061.141a.775.775 0 01.056.107c.01.024.036.063.058.086.023.022.044.049.048.058.008.024.453.267.476.26.022-.006.13-.186.142-.236.01-.043.006-.043.115-.004.045.016.076.033.085.048.01.016.034.027.078.036.035.006.08.022.101.034.057.032.227.209.244.252.008.02.022.042.03.047zM43.328 38.387c.063.057.134.087.18.077a.285.285 0 01.065-.005.157.157 0 00.079-.028c.036-.025.048-.042.063-.088.024-.076.016-.13-.03-.207-.045-.076-.062-.088-.153-.107a.234.234 0 00-.182.026.315.315 0 00-.071.084c-.035.058-.037.07-.023.13a.196.196 0 00.072.118zM50.162 42.368c0-.031-.194-.112-.4-.166-.056-.015-.264.028-.282.058a.621.621 0 01-.109.083.827.827 0 00-.105.075c-.013.023.023.047.127.081.059.02.129.044.156.055a.19.19 0 00.084.015c.048-.009.1-.007.118.003.013.007.046-.002.257-.077.064-.022.155-.097.154-.127zM51.064 41.593a.316.316 0 01.062-.055l.051-.037-.025-.04a.42.42 0 00-.107-.091.508.508 0 01-.09-.066c-.011-.023-.193-.074-.241-.07a.147.147 0 01-.055-.001.78.78 0 00-.26.05.757.757 0 01-.108.05.802.802 0 00-.112.053c-.046.029-.047.03-.046.058.001.03.258.181.29.172a.073.073 0 01.048.01c.014.007.032.01.04.006.007-.004.025 0 .039.008a.455.455 0 00.224.028c.026-.007.055-.008.064-.003a.521.521 0 00.226-.072zM50.134 42.875c.225.12.366.136.549.066.086-.034.1-.044.135-.1a1.63 1.63 0 01.057-.085c.013-.017.01-.027-.014-.045a.862.862 0 00-.282-.087.797.797 0 01-.107-.015c-.073-.015-.188-.005-.218.02a.174.174 0 01-.062.028.09.09 0 00-.052.035.12.12 0 01-.054.04c-.09.035-.076.077.048.143zM49.513 36.515c.053.03.094.03.166.002l.09-.034c.057-.018.283-.124.29-.135.003-.006.018-.013.033-.015a.465.465 0 00.103-.056.93.93 0 01.114-.066.118.118 0 00.049-.036.207.207 0 01.052-.047.131.131 0 00.049-.059c.01-.034.001-.086-.016-.096a.727.727 0 00-.217.058c-.004.006-.032.017-.063.024a.36.36 0 00-.105.05c-.045.033-.15.066-.473.15-.079.021-.089.028-.118.079-.028.047-.03.063-.014.106a.129.129 0 00.06.075z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M50.836 40.08c-.025-.014-.107.016-.124.046a.26.26 0 01-.063.059 1.249 1.249 0 00-.106.086c-.032.03-.068.061-.081.07-.068.053-.191.232-.177.259.004.007.003.022-.003.032-.006.01-.006.045 0 .078.007.033.007.07 0 .08a.118.118 0 00-.008.058c.002.03-.004.042-.04.078a.858.858 0 00-.052.053c-.015.02-.099.099-.12.113a.119.119 0 00-.034.033.304.304 0 01-.06.055l-.168.126a.846.846 0 01-.162.101 1.152 1.152 0 00-.134.058c-.144.072-.23.11-.316.137a.39.39 0 00-.085.035c-.011.018-.628.173-.683.17a.466.466 0 00-.105.01c-.026.006-.05.02-.053.03-.01.028.057.075.094.066a.39.39 0 01.095 0 .298.298 0 00.101-.004c.02-.007.044-.008.052-.003.01.005.024.002.033-.005.01-.008.039-.014.065-.012a.337.337 0 00.083-.008l.209-.055a4.36 4.36 0 00.259-.076c.107-.038.14-.023.108.053l-.022.05.088.055c.086.054.268.115.312.104.01-.002.028.002.04.01.032.018.245-.026.269-.055a.12.12 0 01.043-.031.17.17 0 00.05-.034.438.438 0 01.054-.045c.044-.03.022-.074-.052-.103-.031-.013-.1-.043-.154-.068a.567.567 0 00-.31-.046c-.083.007-.06-.051.038-.093a.815.815 0 00.08-.047.98.98 0 01.079-.046c.023-.01.13-.093.2-.154a1.33 1.33 0 01.097-.076.458.458 0 00.086-.08c.02-.026.042-.047.05-.047.007 0 .021-.016.032-.034.01-.019.027-.035.035-.035.009 0 .024-.014.033-.03.01-.017.04-.037.068-.045a.71.71 0 00.233-.11c.077-.056.194-.192.193-.226a.543.543 0 00.036-.348c-.018-.07-.073-.171-.103-.188z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M48.624 41.543c.02.013.22-.051.277-.088.068-.046.211-.235.217-.288.002-.023.011-.04.026-.049.017-.01.022-.022.018-.043a.437.437 0 01-.002-.082c.003-.057-.017-.151-.035-.162-.006-.003-.013-.018-.015-.032-.006-.035-.044-.055-.067-.035-.01.01-.074.06-.141.11a2.093 2.093 0 00-.184.144 1.041 1.041 0 00-.067.102c-.045.076-.052.096-.05.148a.304.304 0 010 .068.723.723 0 00.023.207zM43.612 29.415c.013 0 .05-.03.082-.066.05-.056.058-.072.06-.109a.18.18 0 01.012-.059c.037-.066-.012-.257-.084-.318-.032-.028-.046-.032-.082-.023-.04.01-.05.02-.1.107-.067.117-.076.17-.045.273.026.087.115.197.157.195zM48.745 42.153a.514.514 0 01-.136-.02.684.684 0 00-.13-.024c-.047.006-.127-.017-.233-.069-.077-.037-.115-.05-.133-.042a.077.077 0 00-.045.09c.005.023.023.041.071.069.061.035.246.234.304.326a.16.16 0 00.035.042c.008.005.021.02.029.035.01.02.024.027.057.032.077.01.108-.017.193-.163a.846.846 0 00.076-.15.292.292 0 00-.03-.076c-.025-.05-.032-.056-.058-.05zM47.862 36.775a.356.356 0 00.107.084l.085.05.242-.062.043-.075c.046-.079.048-.103.022-.202-.021-.084-.069-.133-.172-.178-.095-.042-.111-.042-.212.002-.065.03-.07.035-.102.105a.262.262 0 00-.028.103c.003.015.002.034-.003.042-.014.025-.005.094.018.13zM41.64 32.628c-.042.042-.045.05-.037.083a.13.13 0 00.053.066c.041.027.047.026.092-.005.026-.018.093-.053.149-.076a.387.387 0 00.113-.065c.006-.012.019-.021.027-.022.008 0 .079-.043.156-.094.078-.052.166-.104.197-.117a.396.396 0 00.097-.061c.054-.05.192-.148.226-.16a.808.808 0 00.105-.065.677.677 0 01.113-.066c.031-.01.085-.04.168-.093a.546.546 0 01.093-.038c.191-.062.259-.078.328-.076.042 0 .084 0 .093-.002a.654.654 0 01.108.014.817.817 0 01.325.163c.022.023.035.025.075.012.045-.014.051-.021.082-.09.085-.195-.056-.4-.36-.523-.121-.05-.318-.088-.381-.076-.057.012-.075-.017-.069-.106a1.05 1.05 0 00-.108-.454l-.06-.123-.114-.065c-.098-.056-.124-.065-.18-.066a.232.232 0 00-.109.028c-.07.045-.089.09-.067.167.01.037.03.085.042.107.061.102.09.201.07.237a.276.276 0 00.01.105c.02.09.01.155-.032.229-.014.023-.041.088-.06.144-.024.067-.042.103-.054.107a.262.262 0 00-.063.082c-.024.042-.084.12-.132.174a6.515 6.515 0 00-.132.151c-.109.13-.449.398-.524.411-.013.002-.027.011-.032.02-.005.007-.02.016-.034.019a.061.061 0 00-.038.025.123.123 0 01-.051.036.328.328 0 00-.085.063zM41.89 29.243c.084.019.162.003.185-.038.019-.032.028-.178.014-.197a.398.398 0 00-.16-.086.222.222 0 00-.111.009c-.052.018-.064.028-.079.066-.02.052-.004.135.036.189.026.033.039.04.114.057zM36.525 34.112c-.046.079-.043.088.043.139a.14.14 0 00.102.024c.1-.015.166-.018.27-.012a.586.586 0 00.131-.003c.013-.005.03-.005.037 0 .019.01.107.016.142.01a.313.313 0 01.086.005.441.441 0 00.112.003c.03-.004.11-.004.176 0a.698.698 0 00.203-.018c.044-.013.088-.02.097-.014a.24.24 0 00.092-.002 3.91 3.91 0 00.506-.058.097.097 0 01.063.004c.016.009.035.006.052-.008a.248.248 0 01.102-.03.254.254 0 00.08-.016.677.677 0 01.13-.031c.068-.013.146-.033.173-.045.047-.02.048-.023.053-.073.004-.05.003-.051-.055-.074a.21.21 0 00-.094-.017.392.392 0 01-.074.007.44.44 0 00-.161.014.94.94 0 01-.178.023c-.192.015-.212.005-.171-.077.061-.122.075-.19.046-.237a.948.948 0 01-.033-.06.25.25 0 00-.048-.064c-.097-.086-.097-.086-.134-.078-.027.006-.039.017-.049.048a.458.458 0 01-.092.18.723.723 0 00-.085.086.774.774 0 01-.185.145.694.694 0 01-.263.107 1.24 1.24 0 01-.278.038.868.868 0 00-.088.007.124.124 0 01-.051 0 .562.562 0 00-.11 0 .513.513 0 01-.113-.003c-.006-.003-.023-.002-.037.003a.252.252 0 01-.079.007 2.873 2.873 0 00-.257-.002c-.013.002-.037.03-.061.072z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M38.84 33.471a.837.837 0 01.266.209.622.622 0 00.081.103c.068.068.268.203.363.243.083.036.095.055.05.083-.044.028-.12.182-.126.258-.017.195.06.303.196.275a.712.712 0 01.212-.009l.081.005c.017 0 .085.03.152.067.109.058.127.072.166.127a1.112 1.112 0 01.224.444c.034.12.042.193.035.31a.308.308 0 00.003.087c.004.008-.002.032-.014.052a.156.156 0 00-.02.076c.003.026-.01.063-.041.116-.07.121-.054.146.098.15a.323.323 0 00.142-.023c.027-.015.085-.04.128-.057a.507.507 0 00.117-.065.434.434 0 01.08-.054.142.142 0 00.054-.043.134.134 0 01.036-.04 1.19 1.19 0 00.093-.076c.06-.054.073-.072.087-.121.011-.038.025-.063.04-.073a.051.051 0 00.025-.042.52.52 0 01.059-.127.623.623 0 00.064-.14.301.301 0 01.03-.083.174.174 0 00.025-.066c0-.015.008-.03.023-.039.018-.011.023-.023.018-.047-.003-.017.001-.037.01-.045.01-.008.016-.042.014-.075a.2.2 0 01.011-.088.192.192 0 00.018-.07 1.21 1.21 0 01.028-.146c.032-.131.03-.121.03-.186 0-.03.008-.104.02-.164a.693.693 0 00.016-.137.909.909 0 01.043-.248c.05-.177.054-.186.085-.208.038-.027.035-.073-.005-.084a.081.081 0 01-.042-.032c-.022-.037-.193-.04-.264-.007-.062.03-.079.028-.072-.01a.47.47 0 000-.079.687.687 0 01.011-.134c.008-.044.016-.108.017-.14.002-.085-.06-.306-.096-.34-.016-.014-.029-.034-.03-.042a.381.381 0 00-.052-.09.603.603 0 01-.072-.142c-.012-.038-.03-.074-.04-.08-.026-.016-.093.008-.126.044a.293.293 0 01-.062.05.356.356 0 00-.094.117c-.059.098-.06.1-.085.081a.303.303 0 01-.058-.1.713.713 0 00-.109-.212.343.343 0 01-.048-.11 40.262 40.262 0 00-.05-.176c-.045-.153-.047-.251-.006-.322a.072.072 0 00.005-.053c-.008-.022.001-.042.056-.124.058-.085.065-.1.056-.129-.01-.03-.016-.03-.123.008a.915.915 0 00-.255.124c-.024.017-.057.04-.075.05a.588.588 0 00-.09.09.931.931 0 01-.08.086c-.08.064-.117.113-.233.316-.115.201-.169.326-.158.368.002.007-.004.027-.013.043-.034.059-.033.243.003.372.019.068.03.131.024.14-.01.018-.126.013-.162-.008-.05-.029-.345.025-.464.084a.833.833 0 00-.27.229c-.019.028 0 .066.04.08zM42.354 29.518c.028-.005.058-.005.066 0 .018.01.114-.02.198-.064.058-.03.076-.05.21-.248.08-.117.08-.119.07-.167a.17.17 0 00-.046-.079c-.019-.016-.034-.036-.034-.044 0-.007-.011-.02-.024-.027a.431.431 0 01-.069-.065.306.306 0 00-.098-.074 3.051 3.051 0 00-.277-.095c-.04-.006-.044.052-.012.188a.576.576 0 00.076.2c.023.031.04.067.038.08a.22.22 0 01-.048.07c-.053.055-.123.178-.119.206a.119.119 0 01-.01.05c-.018.047.019.08.08.07zM43.387 29.358c-.01-.006-.023-.027-.027-.047-.009-.044-.06-.097-.13-.138-.072-.042-.095-.044-.138-.011-.056.042-.047.074.072.239.058.08.113.16.122.176.01.016.024.034.033.039.01.005.02.024.023.042a.36.36 0 00.046.091.82.82 0 01.06.108.188.188 0 00.03.055c.02.01.072.297.066.353-.008.072.01.19.03.202a.029.029 0 00.03-.003c.024-.02.042-.206.033-.35a1.061 1.061 0 01-.003-.145 1.15 1.15 0 00-.05-.172 1.802 1.802 0 00-.108-.27 2.246 2.246 0 01-.04-.09.233.233 0 00-.049-.08zM42.86 29.863c.025.07.066.113.13.133.055.018.222-.016.241-.049.035-.06-.036-.247-.108-.288-.032-.018-.185-.021-.204-.004a.432.432 0 00-.048.078c-.03.06-.031.072-.011.13zM36.35 34.762c-.035.061-.032.113.012.18l.035.054h.058c.035-.001.064.006.076.02.01.011.04.026.068.032.027.007.098.029.158.049.198.067.214.072.264.078l.096.013a.13.13 0 00.085-.019.724.724 0 01.094-.049c.073-.03.146-.084.145-.105 0-.018-.123-.077-.155-.075a.76.76 0 01-.103-.022 9.757 9.757 0 00-.155-.038 2.725 2.725 0 01-.541-.182.153.153 0 00-.061.006c-.038.009-.055.022-.076.058zM34.45 44.197c.042.07.247.15.291.113.01-.008.029-.008.042 0 .083.048.634-.06.77-.15a.3.3 0 01.077-.04.46.46 0 00.153-.1c.06-.066.063-.073.04-.092-.018-.014-.038-.01-.082.013a.636.636 0 00-.077.046c-.02.018-.143.068-.246.101a.9.9 0 01-.26.032 2.105 2.105 0 01-.46-.023.098.098 0 01-.051-.007.212.212 0 00-.145 0c-.047.022-.073.074-.053.107z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M39.755 36.84a.218.218 0 01.062-.028c.026-.005.093-.064.198-.176.063-.068.11-.165.109-.223 0-.02.004-.045.011-.057a.066.066 0 00.009-.038.25.25 0 01.008-.07c.006-.028.005-.063-.004-.076-.008-.014-.01-.033-.005-.042.005-.01 0-.034-.01-.055a2.023 2.023 0 00-.115-.208.866.866 0 01-.137-.342c-.03-.133-.03-.165-.012-.226.04-.125.008-.143-.166-.1-.05.014-.112.029-.137.035a.274.274 0 00-.074.03.507.507 0 00-.138.12c-.022.033-.032.037-.057.026-.032-.014-.042-.028-.092-.132a.337.337 0 00-.062-.089.164.164 0 01-.042-.054c-.015-.043-.145-.137-.26-.189a.62.62 0 01-.11-.057.341.341 0 00-.095-.03.633.633 0 01-.114-.034c-.014-.008-.047-.008-.075-.001-.042.01-.056.022-.085.073-.02.033-.033.068-.031.077a.263.263 0 01-.008.07.416.416 0 00.013.219c.035.089-.004.1-.137.038a.307.307 0 00-.103-.034c-.01.003-.03 0-.042-.008a.169.169 0 00-.072-.012.394.394 0 01-.081-.006.618.618 0 00-.22.01 1.026 1.026 0 01-.175.057c-.093.026-.21.06-.258.077a.321.321 0 01-.1.023c-.007-.003-.024-.002-.039.004a.557.557 0 01-.114.014.989.989 0 00-.163.024c-.043.01-.083.03-.09.041-.015.026.018.18.05.228.065.102.176.447.234.727.014.073.132.268.178.294a.061.061 0 01.026.032c.003.01.036.04.073.063.062.04.113.103.1.126a.246.246 0 01-.073.025.417.417 0 00-.115.05.57.57 0 00-.147.118c-.041.044-.049.06-.056.113-.007.055-.003.065.03.084.021.012.053.039.071.059.038.043.139.123.247.198.077.053.24.12.263.107.006-.003.026.002.044.013.018.01.044.014.059.009a.144.144 0 01.056-.007c.033.003.069.003.138-.002.044-.003.047-.002.05.025a.245.245 0 01-.02.084c-.012.031-.019.063-.015.07.004.007 0 .024-.007.037-.016.028.055.313.094.374.025.04.027.04.062.027a.11.11 0 00.048-.034.483.483 0 01.183-.117c.025-.006.08-.02.122-.033a.275.275 0 01.086-.016.232.232 0 00.072-.004.366.366 0 01.104 0c.067.013.305-.009.317-.03a.197.197 0 01.054-.031.98.98 0 00.134-.086.41.41 0 00.14-.157c.029-.052.05-.1.045-.107-.004-.008 0-.026.009-.041.042-.074.041-.257-.002-.391-.01-.03-.014-.062-.01-.069.008-.014-.01-.093-.044-.19l-.02-.056.127-.036c.176-.049.263-.079.306-.107zM42.264 39.918c-.01.086.006.134.076.213l.058.066.078.006a.364.364 0 00.108-.004.432.432 0 00.14-.119c.027-.048.013-.116-.038-.197-.053-.084-.068-.094-.185-.133-.057-.02-.141.006-.185.057l-.042.047a.514.514 0 00-.01.064zM34.421 35.303a.822.822 0 01.097.086c.01.013.053.052.096.087.168.138.194.176.287.423.03.08.061.102.109.077a.686.686 0 01.107-.04.294.294 0 00.106-.056.507.507 0 00.16-.219c.048-.111.051-.145.027-.316-.007-.052-.005-.092.004-.094a.34.34 0 01.083.01.546.546 0 00.125.008.193.193 0 01.078.006c.01.006.046.007.079.002l.157-.022c.277-.038.306-.062.26-.21a1.399 1.399 0 00-.118-.288c-.006-.003-.014-.02-.018-.038a.351.351 0 00-.052-.095 1.353 1.353 0 01-.056-.082.887.887 0 00-.038-.058c-.035-.048-.034-.069.002-.073a.425.425 0 00.168-.071.077.077 0 01.036-.027c.044-.016.148-.154.17-.227.042-.135.045-.165.024-.243a.574.574 0 01-.02-.123c.001-.023-.003-.045-.009-.048a.39.39 0 00-.098.01c-.165.028-.228.034-.248.024a.358.358 0 00-.084-.018.837.837 0 01-.14-.032 4.73 4.73 0 00-.128-.041 3.639 3.639 0 01-.154-.053.764.764 0 00-.18-.042.525.525 0 01-.086-.01.859.859 0 00-.216.021.482.482 0 00-.168.077.37.37 0 00-.142.148c-.043.071-.052.098-.053.154a.33.33 0 01-.009.079.147.147 0 00.002.06c.006.038-.002.068-.04.147l-.048.1-.07.03a.297.297 0 00-.078.043.17.17 0 01-.052.032c-.04.019-.05.033-.09.115a.54.54 0 00-.058.265c-.003.155.13.406.276.522zM42.95 38.534a.61.61 0 00.102-.144l.05-.094-.12-.072a4.378 4.378 0 01-.28-.19c-.174-.127-.223-.149-.412-.184a1.046 1.046 0 01-.265-.09.136.136 0 01-.051-.06l-.014-.038.042.006a.25.25 0 00.068.002.244.244 0 01.073.004c.046.009.068.006.173-.024a.443.443 0 00.22-.117c.1-.084.2-.22.18-.243a1.217 1.217 0 00-.103-.081.592.592 0 01-.186-.211.625.625 0 00-.258-.241l-.134-.08.029-.077c.032-.085.034-.231.003-.265-.013-.014-.035-.016-.076-.005a.212.212 0 01-.066.01.539.539 0 00-.096 0 .767.767 0 01-.14-.005 1.258 1.258 0 00-.484.024.772.772 0 00-.273.135.603.603 0 01-.063.057.275.275 0 00-.05.057c-.052.074-.169.302-.165.32.002.009-.006.034-.019.056a.462.462 0 00.001.25c.013.022.079.22.108.325a.28.28 0 01-.098.298c-.102.073-.129.083-.311.11-.154.023-.272.078-.334.154-.02.025-.042.045-.05.046-.007 0-.02.013-.03.028-.008.016-.021.028-.028.029a.511.511 0 00-.076.117 1.171 1.171 0 00-.114.276c-.021.07-.002.276.035.378.037.1.051.125.232.41.063.097.12.198.126.223.008.025.022.05.032.056.01.006.054-.005.099-.025.07-.03.086-.044.123-.103.053-.085.061-.09.1-.053.097.09.126.108.227.138.144.043.192.051.267.046a.36.36 0 01.24.06c.102.059.133.06.145.01.005-.022.025-.092.045-.157a.652.652 0 00.032-.231.48.48 0 00-.105-.312c-.078-.108-.08-.118-.033-.125.05-.007.15.048.193.106a.256.256 0 00.054.055.22.22 0 01.052.06c.043.068.156.16.24.195.118.048.173.075.35.172.197.108.18.11.27-.043.05-.085.058-.107.053-.145l-.006-.045.05.006c.029.003.059.01.067.014a.185.185 0 00.075-.003.185.185 0 01.073-.005c.015.01.08-.019.15-.065.03-.02.071-.036.093-.038a.11.11 0 00.071-.04c.029-.033.03-.043.01-.11a.23.23 0 01-.015-.083c.011-.02-.005-.16-.02-.17-.007-.003-.015-.02-.017-.034a.33.33 0 00-.092-.138c-.03-.018-.025-.033.031-.087zM33.03 33.278l-.035.09c-.04.099-.015.148.113.232.043.028.113.085.156.127a.845.845 0 00.117.1.406.406 0 01.124.12.065.065 0 00.026.03.852.852 0 01.102.113c.044.056.095.115.113.13.018.016.036.04.041.054.005.014.03.046.054.071.053.053.112.067.134.032a.255.255 0 01.067-.051.938.938 0 00.084-.053.418.418 0 01.05-.034c.012-.006.057-.035.1-.064.068-.045.08-.058.083-.09.002-.02.01-.04.018-.045.008-.004.011-.02.009-.037a.62.62 0 01.006-.191c.005-.01.005-.032 0-.05a.199.199 0 01.006-.09.182.182 0 00.007-.083c-.013-.036-.093-.063-.194-.065a.36.36 0 01-.104-.013.474.474 0 00-.106-.021 1.307 1.307 0 01-.176-.035.473.473 0 00-.101-.021c-.008.002-.036-.01-.063-.025a.767.767 0 00-.132-.053 2.4 2.4 0 01-.2-.076c-.148-.064-.195-.074-.246-.053a.09.09 0 00-.053.05zM25.515 43.225a.013.013 0 00-.019.005.013.013 0 00.005.019.013.013 0 00.018-.005.013.013 0 00-.004-.019zM43.078 44.328c-.03-.056-.196-.142-.286-.149a.309.309 0 01-.084-.015c-.01-.006-.038-.004-.063.004-.024.007-.049.01-.055.007a.412.412 0 00-.114.024.844.844 0 00-.29.172.156.156 0 00-.03.046l-.034.085a.326.326 0 00.133.387c.033.02.066.031.074.027.008-.004.024-.002.035.005.012.007.05.006.084-.003.052-.012.07-.026.109-.077.066-.087.075-.147.04-.273-.04-.14-.023-.17.104-.203a.32.32 0 01.15-.008c.033.008.07.011.083.007.012-.005.04.001.06.013.08.046.123.02.084-.05zM43.175 44.85c.016.045.027.056.107.1.12.069.17.075.271.036.074-.03.088-.04.118-.092.036-.062.039-.098.017-.198-.023-.1-.042-.126-.14-.187l-.089-.056-.09.03c-.08.025-.096.036-.137.092a.928.928 0 01-.057.073c-.02.018-.022.024-.013.075a.16.16 0 01.002.064c-.004.006.001.035.011.063zM43.222 45.743c.077.06.246.157.283.163a1.8 1.8 0 01.1.024.308.308 0 00.116.01l.112-.023a.434.434 0 00.155-.07c.072-.05.09-.072.16-.182a.642.642 0 00.121-.384c.001-.05.005-.095.008-.1.003-.006-.001-.022-.01-.036a.082.082 0 01-.009-.052c.007-.03-.097-.198-.135-.22-.034-.02-.153-.02-.177 0a.707.707 0 00-.21.393c-.004.083-.023.095-.08.05a.581.581 0 00-.325-.089.659.659 0 00-.237.077c-.035.037-.062.12-.053.163a.572.572 0 00.18.276zM44.314 47.31a.236.236 0 01-.057-.013.144.144 0 00-.06.002.29.29 0 01-.166-.023.097.097 0 01-.035-.05.948.948 0 00-.163-.252c-.015-.009-.028-.024-.028-.033 0-.02-.054-.044-.162-.074a.214.214 0 00-.136.001c-.102.033-.111.078-.03.144.025.02.045.042.045.05s.009.02.02.025c.055.033.125.375.105.518a.521.521 0 00-.005.105c.002.015.002.032-.002.038a.207.207 0 00-.008.057.962.962 0 01-.049.229.06.06 0 00-.007.037.717.717 0 01-.042.209.126.126 0 00-.011.061.283.283 0 01-.04.118.841.841 0 00-.057.139c-.009.032-.022.061-.03.066-.016.008-.077.101-.182.274-.051.085-.067.12-.062.139.01.035.072.054.112.033a.662.662 0 00.191-.199c.008-.021.023-.042.033-.046.012-.005.03-.034.046-.077a.257.257 0 01.045-.082c.01-.007.085-.126.166-.263.08-.138.155-.253.165-.257a.33.33 0 00.065-.09.4.4 0 01.072-.1.592.592 0 00.07-.06.313.313 0 01.061-.05.072.072 0 00.03-.028c.02-.035.263-.198.353-.237.087-.038.112-.066.097-.11-.033-.1-.176-.183-.344-.202z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M44.18 46.644a1.95 1.95 0 01-.014-.126 1.816 1.816 0 00-.012-.113.438.438 0 01-.003-.095c.003-.022 0-.043-.006-.046-.006-.004-.014-.04-.018-.08-.004-.042-.013-.079-.02-.083-.008-.005-.017-.02-.019-.034-.007-.044-.073-.072-.135-.057-.048.012-.06.022-.09.074l-.035.06.057.22c.05.191.093.455.079.478a.25.25 0 00.018.074c.012.036.02.077.017.09-.005.023.031.1.053.112.005.003.028-.006.05-.02.036-.023.04-.03.058-.118a.696.696 0 00.017-.134.52.52 0 01.005-.089.475.475 0 00-.002-.113zM45.678 41.593a10.486 10.486 0 01-.168-.068 1.822 1.822 0 00-.395-.116 26.87 26.87 0 01-.223-.04.696.696 0 00-.13-.016 1.085 1.085 0 01-.24-.014c-.047-.014-.048-.04-.005-.146a.499.499 0 00.036-.146c0-.077-.037-.096-.146-.077a.826.826 0 01-.3-.012.78.78 0 00-.13-.017c-.292-.017-.645.069-.771.189-.053.05-.205.153-.272.184a.552.552 0 00-.12.068.116.116 0 01-.056.018c-.022.001-.042.008-.046.014-.011.02-.196.11-.277.134a.796.796 0 01-.256.027c-.004-.003-.027 0-.05.005-.023.006-.043.017-.044.024-.01.047.08.155.171.204.024.013.044.033.045.044.016.14-.225.413-.453.512-.06.026-.08.058-.068.107.009.033.017.039.112.079a.784.784 0 00.146.047c.024.003.08.014.125.024.044.011.094.021.11.024.015.002.055.01.088.02a.29.29 0 00.077.011.058.058 0 01.034.008c.01.005.045.008.078.005a.546.546 0 01.125.009c.037.007.083.01.102.005a.265.265 0 01.094.006c.04.01.067.007.085-.007.017-.015.035-.016.055-.005.016.01.037.011.046.003a.488.488 0 01.198-.018c.007.004.025 0 .04-.009a.252.252 0 01.092-.02c.036-.001.124-.019.194-.038.071-.02.161-.043.2-.051a3.4 3.4 0 00.399-.133c.059-.033.22-.102.298-.128a.723.723 0 00.142-.065.628.628 0 01.124-.059c.182-.06.428-.125.49-.129.037-.003.07-.01.074-.015.003-.005.026-.007.052-.004s.063 0 .084-.007c.02-.007.042-.009.05-.005a.323.323 0 00.091.004c.204-.012.24-.012.28.002a.492.492 0 00.088.02c.091.01.284.076.367.123.096.056.117.051.123-.028.005-.049-.003-.06-.137-.2-.043-.045-.493-.293-.628-.347zM38.572 42.51c.003-.007.02-.013.036-.015.063-.006.181-.097.226-.174a.9.9 0 00.216-.323c.015-.042.046-.117.068-.168a.619.619 0 00.045-.157.304.304 0 01.016-.083.06.06 0 00.007-.034.324.324 0 01.009-.072.314.314 0 00.006-.09.621.621 0 01-.004-.089c.004-.13-.086-.502-.144-.594-.02-.034-.036-.072-.033-.085.006-.028-.056-.152-.142-.282-.06-.092-.065-.096-.095-.088-.024.007-.032.016-.031.036.001.073-.12.392-.158.416a.165.165 0 00-.042.049.377.377 0 01-.143.116 1.81 1.81 0 00-.309.213.519.519 0 00-.103.144c-.07.141-.097.208-.094.233a.482.482 0 010 .112c-.02.138-.006.16.137.217.121.05.138.066.113.11a.202.202 0 00-.02.079c-.005.132-.01.185-.02.203a.736.736 0 00-.017.15.834.834 0 01-.016.148.137.137 0 00-.002.061c.005.039.012.05.046.06a.265.265 0 00.102.003.214.214 0 01.075-.003c.03.017.25-.059.27-.094zM38.107 47.644c-.046-.027-.061-.028-.132-.008-.09.025-.109.047-.114.137-.006.102.022.155.106.206.07.042.074.043.139.022.058-.02.07-.03.102-.085.03-.053.034-.07.021-.11a.274.274 0 00-.122-.162zM40.304 46.806c-.035-.134-.107-.257-.174-.295a.06.06 0 01-.026-.032c-.006-.026-.2-.144-.216-.132-.006.006-.009.05-.006.099.004.087.003.09-.07.225-.04.075-.076.15-.08.168-.007.054.028.266.055.328.047.105.068.19.055.213a.134.134 0 00-.015.052c-.001.04-.085.127-.197.206a.282.282 0 00-.058.05c-.016.027-.174.107-.256.13a.294.294 0 00-.084.032c-.011.02-.337.091-.359.078a.647.647 0 00-.107.003.56.56 0 01-.298-.049c-.027-.015-.054-.026-.06-.024-.028.007-.035.045-.013.066.013.012.07.04.125.06.057.02.111.045.122.055.01.01.03.015.042.01.017-.006.038.002.07.026.029.021.054.031.063.026.008-.004.028-.001.043.008.015.008.034.012.041.008.008-.004.024-.002.035.004a.062.062 0 00.047.003.24.24 0 01.074-.009.936.936 0 00.291-.04c.17-.045.38-.117.411-.14l.123-.087a.66.66 0 00.109-.087.3.3 0 01.066-.057c.05-.033.066-.057.155-.21a.882.882 0 00.096-.195.302.302 0 01.01-.08.214.214 0 00.005-.09.079.079 0 01.002-.055c.014-.024.002-.179-.021-.268z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M41.995 41.88c.012-.019-.03-.085-.066-.106-.017-.01-.035-.044-.047-.087-.02-.076-.104-.22-.142-.241-.044-.026-.022-.041.075-.052a.476.476 0 00.102-.018.355.355 0 01.076-.029.322.322 0 00.096-.043.401.401 0 01.075-.047.197.197 0 00.062-.042.487.487 0 01.061-.064.274.274 0 00.065-.083.11.11 0 01.033-.049c.032-.02.049-.112.026-.144-.016-.023-.03-.025-.091-.011a.447.447 0 01-.159.009.615.615 0 01-.291-.095 2.509 2.509 0 01-.317-.224c0-.007.016-.023.036-.035a.39.39 0 00.092-.121c.054-.093.056-.099.034-.126-.035-.043-.442-.28-.468-.273a.06.06 0 01-.04-.004.754.754 0 00-.147-.018c-.111-.007-.162 0-.385.058a2.139 2.139 0 01-.27.06.18.18 0 00-.066 0 .164.164 0 01-.07 0 .053.053 0 00-.033-.006.743.743 0 01-.133-.022.764.764 0 01-.255-.103c-.13-.073-.143-.084-.187-.148a.627.627 0 00-.056-.074c-.004-.003-.013-.022-.018-.043a.536.536 0 00-.036-.088c-.014-.027-.02-.062-.015-.076.006-.015.003-.044-.007-.064-.026-.054-.074-.054-.153.001-.058.041-.071.058-.136.176-.089.163-.11.23-.104.328a.4.4 0 010 .087.173.173 0 00.01.063c.009.03.01.062.005.072-.019.033.008.18.05.274.045.102.118.217.18.285.047.05.084.12.082.155 0 .013-.008.05-.017.084a.699.699 0 00-.017.1.162.162 0 01-.01.051.529.529 0 00-.009.188c.005.014.006.031.002.038-.009.016.03.18.068.287.026.072.09.175.122.193.01.006.018.017.018.026 0 .009.008.02.017.026.01.005.033.033.052.061a.268.268 0 00.053.062c.01.006.02.019.023.029.002.01.1.09.218.18s.238.186.268.216c.03.029.071.068.093.087a.356.356 0 01.054.054.997.997 0 00.087.091c.041.039.085.089.098.112a.359.359 0 00.07.079c.053.042.1.107.168.229.067.12.089.158.11.19.032.043.118.304.144.43.012.061.031.145.04.185.024.095.035.264.025.402a.958.958 0 00-.003.127c.002.009-.004.032-.014.05a.067.067 0 00-.003.064c.028.058.105.063.227.017a.37.37 0 00.118-.063.124.124 0 01.035-.035c.027-.018.115-.238.117-.293 0-.023.004-.064.008-.092.022-.145-.056-.481-.15-.65a.644.644 0 01-.044-.097.158.158 0 00-.034-.06c-.037-.032-.006-.071.056-.072.03 0 .058-.007.062-.014.004-.007.023-.01.042-.007.02.003.04-.003.047-.014.016-.027-.064-.326-.108-.403a.405.405 0 01-.04-.088.058.058 0 00-.024-.037.267.267 0 01-.053-.062.26.26 0 00-.062-.067.438.438 0 01-.074-.067 2.091 2.091 0 00-.27-.221.21.21 0 01-.06-.056.058.058 0 00-.024-.029c-.01-.006-.026-.029-.033-.05-.014-.039-.013-.04.019-.044a.107.107 0 01.059.01.141.141 0 00.053.018c.038.002.12.02.14.032.01.005.044.005.077-.002.033-.006.069-.007.08 0 .01.005.042.005.07 0a.173.173 0 01.06-.004.528.528 0 00.117-.027.446.446 0 01.119-.025c.006.004.04-.01.075-.03.035-.021.108-.058.163-.081a.44.44 0 00.107-.06zM51.698 34.23c-.04.013-.044.018-.086.12-.082.196-.28.515-.34.548a.148.148 0 00-.05.046.152.152 0 01-.038.045c-.032.02-.19.167-.201.185a.079.079 0 01-.035.026.433.433 0 00-.084.062.64.64 0 01-.093.07c-.061.033-.097.057-.107.074-.018.032-.376.164-.402.15a.21.21 0 00-.073-.004.191.191 0 01-.098-.017.08.08 0 00-.08-.006.137.137 0 00-.05.03.227.227 0 00.014.083.18.18 0 00.074.112c.03.023.053.048.053.056 0 .017.062.052.095.054a.832.832 0 00.277.023.645.645 0 01.145 0 .456.456 0 01.061.104c.054.112.121.189.226.26.081.055.137.07.204.056.05-.011.06-.029.046-.078a.363.363 0 01-.009-.099c.007-.139.009-.224.005-.248a.411.411 0 01.015-.101l.044-.186c.035-.148.117-.324.32-.691.11-.195.189-.351.217-.427.072-.188.053-.278-.05-.246zM46.318 40.53a.966.966 0 00-.25-.047.754.754 0 00-.233.083.437.437 0 00-.083.111c-.068.117-.074.166-.037.325.02.092.033.117.083.168l.085.09c.035.037.117.06.19.051a.176.176 0 01.064 0c.006.004.018.004.026 0 .017-.01.008-.074-.011-.085-.012-.007-.019-.026-.05-.142-.017-.062.007-.156.05-.196a.825.825 0 00.056-.056.12.12 0 01.055-.035.734.734 0 01.173-.021c.014.002.031-.007.04-.02.02-.037-.097-.204-.158-.225zM38.038 46.022c.104-.05.114-.12.023-.157a.523.523 0 01-.186-.18.825.825 0 00-.147-.165.692.692 0 00-.38-.153 1.475 1.475 0 01-.127-.018.441.441 0 00-.087-.01c-.07.01-.344-.11-.38-.169a.871.871 0 00-.042-.06 1.313 1.313 0 01-.057-.08c-.03-.05-.063-.075-.087-.069-.007.002-.021.024-.03.048-.018.046.005.176.033.193.009.005.023.035.031.068.008.032.027.079.042.104.106.174.2.313.22.325a.957.957 0 01.093.08c.13.119.3.24.365.26.2.06.316.085.367.083.06-.003.297-.06.305-.074a.178.178 0 01.044-.026zM50.094 43.653c-.002-.013-.024-.04-.048-.06a.218.218 0 01-.05-.052c-.019-.048-.234-.19-.288-.189-.019 0-.024.017-.033.107-.009.088-.007.102.028.236.02.08.15.279.202.309a.651.651 0 01.084.073c.08.078.1.075.144-.024a.42.42 0 00.034-.106.85.85 0 00-.055-.262c-.008-.005-.016-.02-.018-.032zM48.96 44.375a.2.2 0 01-.048-.056c-.012-.033-.283-.2-.315-.194-.031.006-.028 0-.035.068-.009.081.055.444.08.46a.55.55 0 01.055.07.716.716 0 00.386.26c.053.017.064.016.078-.008.008-.015.012-.034.008-.041-.004-.008.001-.029.011-.046.025-.042.002-.18-.046-.285a.687.687 0 00-.173-.228zM51.308 43.862a.714.714 0 01-.077-.107.572.572 0 00-.082-.11.456.456 0 01-.07-.072.584.584 0 00-.114-.101.251.251 0 01-.067-.054c-.002-.008-.021-.024-.043-.036a.18.18 0 01-.054-.048c-.011-.018-.032-.03-.07-.04-.04-.01-.057-.02-.062-.036-.006-.016-.023-.026-.06-.036a.596.596 0 01-.113-.05 2.08 2.08 0 00-.342-.132.152.152 0 01-.062-.03c-.008-.01-.033-.018-.057-.019-.064-.003-.471-.18-.54-.236a.238.238 0 00-.087-.037c-.037-.007-.12-.05-.274-.14-.196-.115-.223-.128-.244-.116-.036.02-.048.05-.03.078.008.014.106.081.218.149.274.166.489.307.51.335.01.013.075.067.146.121.126.097.185.147.274.23.092.087.283.227.422.31.135.082.242.126.32.132.017.002.049.017.07.034a.14.14 0 00.08.034.19.19 0 01.074.02c.017.009.071.016.12.014a.38.38 0 01.108.007c.023.014.12-.018.12-.039 0-.01-.007-.02-.014-.025zM49.214 43.025c-.014-.008-.026-.022-.026-.03a.52.52 0 00-.161-.134c-.025.001-.032.022-.035.098a3.078 3.078 0 01-.014.21.443.443 0 00.094.267c.071.076.28.247.305.25.017.003.027-.01.048-.058.03-.071.023-.185-.022-.32-.038-.113-.127-.247-.19-.283zM47.75 43.481c.029-.005.044-.024.12-.15.085-.141.087-.146.097-.248a.678.678 0 00-.018-.22l-.029-.118-.056.022a.465.465 0 00-.096.052l-.058.045a.63.63 0 01-.05.033.399.399 0 00-.098.13c-.059.102-.064.116-.07.217a1.7 1.7 0 01-.02.171.322.322 0 00-.007.095c.013.066.138.069.217.005a.182.182 0 01.068-.034zM47.503 42.584c.033.019.045.018.081-.008.038-.026.048-.042.088-.14a.751.751 0 00.05-.169.246.246 0 01.015-.077c.007-.012.005-.05-.005-.084a.194.194 0 01-.01-.075.399.399 0 00-.021-.111.419.419 0 01-.021-.11.66.66 0 01.127-.054 1.455 1.455 0 00.202-.082.1.1 0 00.048-.038.096.096 0 01.045-.037c.06-.02.208-.231.21-.302.003-.059-.056-.069-.22-.038a.422.422 0 01-.124.012c-.009-.004-.026-.004-.038 0-.07.026-.322-.028-.508-.11a9.182 9.182 0 00-.36-.154c-.027-.01-.054-.014-.06-.01-.007.003-.023 0-.036-.007a.433.433 0 00-.091-.028c-.075-.015-.166.01-.21.06-.015.015-.032.029-.04.029-.019 0-.113.18-.114.219a.138.138 0 01-.012.054c-.023.038.001.135.049.201.066.093.234.232.486.404.042.03.087.066.1.081.012.016.05.054.084.086.034.032.07.078.081.103.011.024.023.046.027.048a.839.839 0 01.093.2c.005.026.016.05.024.055.007.004.016.02.018.034.002.014.021.036.042.048zM47.837 44.353a.162.162 0 00.066-.047.203.203 0 01.062-.052c.026-.015.047-.035.047-.044 0-.009.02-.058.047-.11a.356.356 0 00.042-.11c-.003-.011.002-.032.011-.047a.614.614 0 00.006-.274c-.015-.038-.016-.039-.04-.024a.704.704 0 01-.092.037.434.434 0 00-.117.067.643.643 0 00-.103.13c-.055.094-.144.301-.16.379a.736.736 0 01-.036.106c-.014.032-.02.065-.014.072.016.02.102.028.111.011a.176.176 0 01.06-.036.237.237 0 00.055-.029.231.231 0 01.055-.03z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M48.745 43.897c.023.02.078.056.123.081l.081.045.025-.05a.345.345 0 00.028-.11.273.273 0 01.01-.07c.015-.025-.04-.186-.086-.25a.847.847 0 00-.21-.225 15.218 15.218 0 01-.103-.059c-.071-.042-.096-.033-.105.037-.008.053-.023.075-.046.062a.521.521 0 01-.037-.127 5.362 5.362 0 00-.152-.562.216.216 0 01-.034-.064.67.67 0 00-.048-.097.46.46 0 01-.042-.1.476.476 0 00-.036-.093c-.019-.032-.064-.05-.09-.037-.022.011-.03.059-.014.078.07.088.233.715.28 1.084.013.096.021.238.015.249a.594.594 0 01.005.165l-.007.131c.002.085-.078.403-.126.506-.023.048-.038.062-.113.101a.508.508 0 00-.122.086c-.058.068-.133.213-.13.254a.13.13 0 01-.012.06.729.729 0 00-.034.201.35.35 0 01-.012.074.244.244 0 00-.001.09c.007.045.015.057.043.065.018.005.05.005.07 0 .02-.005.066-.014.101-.02.035-.007.067-.017.07-.023.007-.01.025-.02.134-.074.027-.013.05-.033.052-.045a.061.061 0 01.026-.036.67.67 0 00.11-.252.316.316 0 01.009-.086.488.488 0 00-.008-.166c-.023-.12-.022-.139.02-.267a.714.714 0 00.033-.133.395.395 0 01.02-.09.223.223 0 00.011-.087.556.556 0 01.014-.131c.019-.095.023-.187.014-.303-.005-.055-.001-.069.02-.077.013-.005.03-.005.037-.001.015.008.07.092.082.123.007.02.054.069.135.143zM39.449 43.497c.073.058.093.062.139.029a.89.89 0 01.071-.045c.057-.032.16-.184.195-.287l.042-.125c.027-.08.018-.31-.017-.423a2.674 2.674 0 01-.032-.114c-.018-.071-.067-.171-.091-.185a.058.058 0 01-.023-.037.123.123 0 00-.038-.055.124.124 0 01-.039-.054c-.004-.025-.046-.056-.067-.05-.022.006-.034.04-.037.102a.69.69 0 01-.08.29 5.472 5.472 0 00-.132.27c-.096.208-.1.23-.078.38a.597.597 0 00.187.304zM43.668 25.284l.093-.07a.483.483 0 00.128-.207c.015-.11-.026-.157-.167-.19-.056-.014-.088-.011-.158.014-.096.034-.138.057-.154.085a.381.381 0 01-.076.063.502.502 0 00-.233.433.487.487 0 010 .1c-.011.08.08.225.2.32.07.057.1.075.129.078a.23.23 0 01.077.026.26.26 0 00.1.026.248.248 0 01.075.013c.024.013.101-.026.137-.07.032-.039.046-.131.032-.2a.51.51 0 00-.189-.29c-.08-.046-.08-.068.006-.131zM31.163 37.29a.294.294 0 01.014.106.69.69 0 00.01.142.711.711 0 01.01.139.307.307 0 000 .074.406.406 0 01-.007.105.406.406 0 00-.007.106.518.518 0 01-.01.123c-.027.146.02.226.125.215l.05-.005.049-.105c.05-.108.055-.127.046-.227a1.222 1.222 0 01-.004-.11c.003-.13-.044-.432-.074-.468-.012-.015-.018-.039-.015-.053.004-.014-.008-.056-.027-.095-.034-.066-.037-.07-.08-.071-.024-.001-.05.003-.058.01-.035.027-.04.057-.022.114zM29.804 34.843c.005.014.023.028.04.032.03.008.173.12.315.246a.638.638 0 01.134.147.11.11 0 00.029.03c.063.037.327.38.328.426 0 .01.017.05.037.09.02.041.058.143.082.228.044.147.047.154.09.166a.093.093 0 00.077-.012c.03-.02.037-.034.05-.111.023-.133.001-.21-.123-.45-.058-.11-.067-.125-.082-.134-.01-.005-.019-.02-.021-.035a.063.063 0 00-.027-.039.31.31 0 01-.061-.09.296.296 0 00-.067-.094.217.217 0 01-.053-.049 3.091 3.091 0 00-.28-.255 2.784 2.784 0 00-.332-.199c-.276-.15-.369-.187-.494-.192a.19.19 0 01-.065-.012c-.01-.006-.043-.005-.072.004-.03.008-.06.024-.066.035-.017.03-.002.083.03.101a.575.575 0 00.187.03.285.285 0 01.17.05.551.551 0 00.12.054c.034.007.048.016.054.033zM33.922 43.044c-.067-.054-.11-.064-.19-.044-.07.018-.074.02-.098.078-.018.045-.02.073-.009.107.052.147.187.21.294.137.07-.049.076-.063.061-.159-.011-.07-.021-.09-.058-.12zM42.816 25.341a.221.221 0 01-.063.003c-.024-.014-.422.108-.437.133a.18.18 0 01-.044.038c-.02.013-.054.038-.077.055-.057.042-.075.077-.055.11.026.043.07.045.172.008.052-.02.122-.043.156-.053a.212.212 0 00.066-.028.639.639 0 01.196-.026c.005.003.043 0 .084-.009.082-.015.097-.036.112-.148.006-.043.001-.057-.024-.072a.162.162 0 00-.086-.01zM31.622 47.184c.025.033.113.06.163.051.046-.008.12-.072.154-.13a.234.234 0 00.02-.086.246.246 0 01.01-.072c.016-.028-.03-.096-.095-.142-.06-.04-.073-.045-.134-.04-.081.007-.092.013-.137.068-.054.065-.068.09-.06.106.004.008.002.023-.005.035-.011.02.044.158.084.21zM27.062 43.078c-.067-.042-.078-.045-.134-.034a.24.24 0 00-.142.07c-.05.043-.058.055-.079.141a.343.343 0 00-.001.146c.016.073.017.074.096.118.102.057.146.061.26.024.078-.024.098-.037.13-.083a.152.152 0 00.036-.116c-.006-.136-.036-.185-.166-.266z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M30.798 48.503c.012.006.021.019.021.028 0 .026.077.062.11.051a.461.461 0 00.169-.102c.025-.031.024-.041-.011-.127a.58.58 0 00-.06-.118.542.542 0 01-.08-.18.62.62 0 00-.042-.12c-.047-.115-.163-.537-.153-.556.004-.005-.005-.027-.018-.05a.15.15 0 01-.019-.085.401.401 0 00-.011-.118.63.63 0 01-.018-.099c0-.014-.006-.073-.013-.13a.758.758 0 01-.01-.11.763.763 0 00-.012-.112.416.416 0 01-.007-.12.5.5 0 00.002-.125.466.466 0 01.003-.126c.006-.009.006-.037 0-.062a.402.402 0 010-.11.421.421 0 00.003-.101.196.196 0 01.008-.079.711.711 0 00.02-.132.397.397 0 01.021-.112.243.243 0 00.018-.08.825.825 0 01.02-.118 2.21 2.21 0 01.1-.364.253.253 0 00.016-.078.718.718 0 01.057-.197c.023-.06.052-.06.092-.001a.933.933 0 00.112.115c.171.152.322.182.445.087.044-.033.037-.051-.037-.1a.782.782 0 01-.09-.07c-.05-.05-.179-.395-.16-.43a.207.207 0 00.001-.074.758.758 0 01-.004-.114.577.577 0 00-.003-.156.107.107 0 01.012-.064.313.313 0 00.023-.107.348.348 0 01.014-.092.314.314 0 00.013-.089c.004-.083.013-.106.044-.1.027.003.047.063.03.093a.143.143 0 00-.005.075c.005.028.003.06-.003.072-.006.01-.004.048.006.083s.013.07.008.078a.839.839 0 00.035.186c.024.094.05.207.056.25.006.044.025.1.042.127a.177.177 0 01.027.088c-.001.022.005.044.014.05.009.005.024.04.034.078.024.095.103.314.116.321a.378.378 0 01.04.093c.032.091.13.272.157.287.009.005.023.027.031.047a.24.24 0 00.039.064c.013.014.048.06.078.104.03.043.067.092.083.108.017.016.06.063.094.105.089.104.175.175.338.277.172.108.224.116.206.03-.005-.022-.023-.042-.058-.062a.162.162 0 01-.072-.078.797.797 0 00-.068-.114 1.361 1.361 0 01-.156-.307 3.216 3.216 0 00-.057-.151c-.041-.101-.08-.26-.07-.279.005-.008-.005-.036-.021-.062a.321.321 0 01-.035-.13c-.003-.046-.01-.086-.017-.09-.007-.004-.018-.035-.024-.068a13.4 13.4 0 00-.03-.153.386.386 0 01-.01-.127.378.378 0 00-.014-.178 1.769 1.769 0 01-.024-.345l.001-.136c0-.125.01-.24.024-.264a.113.113 0 00.01-.058.106.106 0 01.01-.055c.006-.012.008-.046.003-.074-.004-.028-.004-.059.001-.068.006-.01.025-.08.044-.158a8.9 8.9 0 01.07-.267.933.933 0 00.033-.145.376.376 0 01.035-.102.483.483 0 00.04-.11.52.52 0 01.06-.174c.007-.003.015-.028.018-.054.005-.042.054-.171.12-.32a2.518 2.518 0 01.123-.305c.04-.084.077-.175.085-.2.008-.026.038-.108.067-.181.087-.22.1-.264.105-.33.002-.036.01-.07.019-.077.017-.014.072.011.073.034 0 .008.013.025.029.039.015.013.052.053.082.088.067.08.218.172.257.157a.04.04 0 01.043.011c.011.012.04.019.077.016a.657.657 0 01.09 0 .335.335 0 00.11-.03.242.242 0 00.134-.106.34.34 0 00.064-.126c.018-.087.016-.09-.066-.102-.068-.01-.082-.018-.164-.082a.48.48 0 01-.095-.088.059.059 0 00-.025-.029c-.022-.013-.065-.139-.12-.355-.034-.14-.044-.37-.017-.418.007-.01.005-.03-.003-.043-.008-.013-.009-.054-.002-.091a.699.699 0 00.012-.092 5.182 5.182 0 01.047-.512.988.988 0 00.05-.269.814.814 0 01.03-.132 3.11 3.11 0 00.09-.429c.004-.06.006-.065.035-.073.03-.008.033-.006.058.032.035.056.216.19.332.247.084.042.102.045.157.034a.187.187 0 01.075-.005c.008.004.045 0 .083-.008a.31.31 0 00.147-.088.413.413 0 00.078-.084.79.79 0 01.037-.107.326.326 0 00.03-.13.397.397 0 01-.004-.084c.006-.094-.06-.15-.126-.104-.08.055-.125.063-.223.039-.196-.048-.271-.13-.394-.43a.34.34 0 01-.031-.1c.003-.005-.004-.025-.016-.045-.046-.075-.131-.433-.118-.498.005-.024.004-.047-.002-.05-.006-.003-.011-.033-.012-.066a3.137 3.137 0 00-.073-.338 5.78 5.78 0 01-.086-.379 2.618 2.618 0 00-.065-.27 11.857 11.857 0 01-.088-.317c-.061-.237-.198-.607-.233-.627-.017-.01-.05-.079-.106-.214a.454.454 0 00-.046-.093.455.455 0 01-.044-.094 1.346 1.346 0 00-.1-.189 3.102 3.102 0 00-.24-.346.26.26 0 01-.05-.058.456.456 0 00-.074-.081.173.173 0 01-.05-.063.08.08 0 00-.027-.04c-.031-.018-.025-.05.035-.175.105-.22.34-.644.363-.657.009-.005.02-.03.026-.055a.115.115 0 01.042-.074.898.898 0 00.108-.158l.076-.132.072-.006a.255.255 0 01.09.005c.008.005.028.01.042.01.014.001.072.013.127.026.056.013.123.027.15.03.026.002.054.009.062.013.008.005.03.004.048-.002a.136.136 0 01.068 0c.036.01.22.012.294.002a.616.616 0 01.093-.002.868.868 0 00.152-.014.377.377 0 01.114-.008c.008.004.026.004.039 0a.475.475 0 01.107-.01.842.842 0 00.15-.014.305.305 0 01.093-.008.467.467 0 00.124-.016 4.1 4.1 0 01.145-.03c.026-.004.095-.022.153-.04l.297-.082c.29-.076.325-.087.368-.117.022-.016.047-.024.056-.019.009.005.036.001.06-.009.023-.01.104-.036.178-.06.252-.078.412-.136.42-.152.007-.01.313-.114.34-.115.01 0 .038-.005.061-.011.145-.037.323-.071.365-.07.028.002.058-.004.067-.012.01-.007.028-.008.04 0a.21.21 0 00.063.018l.069.01a.43.43 0 01.185.095c.08.09.102.136.107.224.005.09.022.115.072.107a.51.51 0 00.186-.088.505.505 0 01.063-.068.24.24 0 00.075-.121l.041-.115c.029-.072-.02-.21-.111-.319-.055-.063-.074-.076-.216-.15-.127-.066-.167-.081-.218-.083-.05-.002-.064-.007-.07-.027-.013-.033.006-.062.054-.081a.135.135 0 00.058-.047c.009-.016.024-.03.032-.03.01 0 .025-.015.035-.033.01-.018.024-.034.03-.036.018-.005.15-.127.19-.175a.2.2 0 01.061-.051.202.202 0 00.06-.051.311.311 0 01.049-.05c.007-.003.064-.051.127-.106.134-.116.194-.16.26-.19a.163.163 0 00.056-.04.125.125 0 01.05-.033.164.164 0 00.045-.024c.002-.004.08-.06.172-.124.12-.083.2-.128.278-.156.144-.05.207-.069.218-.062.005.003.03 0 .056-.008a.514.514 0 01.175-.032c.006.004.032.01.057.013a.713.713 0 01.2.058c.017.01.044.04.061.067.042.065.047.067.094.035a.28.28 0 00.115-.152 1.3 1.3 0 01.023-.082c.012-.039-.005-.155-.025-.167a.166.166 0 01-.032-.054c-.032-.074-.057-.103-.142-.17-.081-.062-.207-.122-.245-.116a.337.337 0 01-.084-.014.206.206 0 00-.086-.008c-.03.011-.055-.005-.051-.031a.203.203 0 01.053-.067c.123-.112.197-.19.266-.281.04-.054.086-.109.101-.122.028-.023.1-.124.176-.242a.735.735 0 01.08-.103c.022-.022.081-.097.131-.167s.116-.147.146-.172c.03-.025.054-.052.054-.06 0-.015.076-.102.13-.149a.894.894 0 00.091-.11.356.356 0 01.08-.086c.01-.003.026-.017.034-.032a.316.316 0 01.057-.062l.114-.103c.04-.037.083-.073.095-.081a.129.129 0 00.036-.038.454.454 0 01.09-.078c.041-.03.101-.078.133-.107a.986.986 0 01.102-.082l.098-.068a.91.91 0 01.097-.061c.024-.012.073-.04.108-.063a1.03 1.03 0 01.113-.063.266.266 0 00.053-.027.684.684 0 01.1-.034.754.754 0 00.172-.078.496.496 0 01.14-.064c.037-.008.07-.02.075-.028.004-.008.042-.02.083-.024a.28.28 0 00.079-.017c.006-.012.477-.147.488-.141.005.003.026.001.047-.004a.677.677 0 01.171-.026.478.478 0 00.106-.014.455.455 0 01.154-.005c.032.007.07.006.083-.003.014-.009.035-.01.046-.004a.26.26 0 00.082.016.265.265 0 01.091.022c.066.038.116.016.097-.041-.01-.03-.093-.08-.29-.173a1.628 1.628 0 00-.667-.15 29.481 29.481 0 01-.194-.01 1.15 1.15 0 00-.186.004c-.032.005-.069.004-.08-.002-.011-.007-.029-.006-.038.002a.27.27 0 01-.099.019 2.522 2.522 0 00-.283.05 7.1 7.1 0 01-.272.058c-.1.016-.488.13-.526.154-.153.096-.275.153-.3.138-.031-.018-.021-.05.025-.081a.211.211 0 00.054-.052.171.171 0 01.067-.049.177.177 0 00.069-.053.17.17 0 01.05-.05.927.927 0 00.062-.039c.014-.01.032-.016.039-.012.007.004.032-.008.057-.026a.662.662 0 01.093-.054.184.184 0 00.053-.033c.007-.012.273-.082.285-.075.004.003.028 0 .053-.005.048-.01.098-.003.217.034.043.013.083.018.091.012.022-.018.01-.16-.016-.196a.466.466 0 00-.236-.15c-.144-.05-.201-.063-.238-.055-.016.003-.033 0-.037-.009-.01-.019.026-.082.047-.083.008 0 .024-.016.034-.034a.305.305 0 01.072-.071.31.31 0 00.07-.07c.031-.052.238-.25.329-.316.047-.033.1-.08.119-.103a.482.482 0 01.086-.079.277.277 0 00.065-.058.205.205 0 01.07-.05.856.856 0 00.107-.065.48.48 0 01.095-.054.223.223 0 00.075-.048.372.372 0 01.106-.064.803.803 0 00.13-.067.87.87 0 01.23-.113c.012 0 .025-.006.029-.012.008-.015.103-.055.238-.101a.47.47 0 00.107-.046c.006-.009.064-.026.249-.07l.21-.06c.233-.065.485-.108.555-.093a.25.25 0 00.09.002c.02-.005.058-.012.084-.016.044-.007.049-.01.065-.063.019-.059.01-.218-.013-.23a.655.655 0 00-.083-.027c-.068-.018-.134-.013-.299.02a.33.33 0 01-.096.012 2.02 2.02 0 00-.568.15 1.37 1.37 0 01-.165.06 1.845 1.845 0 00-.359.138 1.004 1.004 0 00-.215.107 3.782 3.782 0 00-.28.177c-.078.054-.159.105-.18.115a.252.252 0 00-.066.053.283.283 0 01-.09.06.202.202 0 00-.07.04.473.473 0 01-.084.067.923.923 0 00-.122.102.361.361 0 01-.064.057.239.239 0 00-.052.052c-.02.024-.047.046-.06.049a.06.06 0 00-.036.025c-.007.012-.018.022-.026.022a.43.43 0 00-.086.08c-.04.044-.093.098-.118.12a.412.412 0 00-.055.058 1.25 1.25 0 01-.187.172.347.347 0 01-.076-.062c-.075-.073-.256-.18-.293-.172-.04.007-.051.041-.035.102a.65.65 0 010 .177c-.009.067-.018.143-.02.168a.225.225 0 01-.015.062.234.234 0 00-.012.071.656.656 0 01-.045.162c-.045.113-.233.439-.259.45a.576.576 0 00-.116.113c-.032.044-.06.02-.11-.092a.762.762 0 00-.139-.232c-.041-.048-.044-.05-.084-.04-.038.01-.045.017-.085.1a.294.294 0 01-.064.1.479.479 0 00-.078.06c-.031.03-.068.061-.08.071-.049.038-.18.206-.217.277l-.038.074-.1-.053a3.467 3.467 0 00-.138-.07c-.048-.023-.095-.015-.098.016a1.725 1.725 0 01-.105.207c-.138.247-.177.402-.148.588.007.042.008.099.003.125a.379.379 0 00-.004.103.168.168 0 01-.003.073.444.444 0 00-.005.183.285.285 0 01-.008.105.602.602 0 00-.019.11.665.665 0 01-.028.132.391.391 0 00-.022.096c.002.01-.004.03-.012.044a.44.44 0 00-.03.1c-.022.121-.065.258-.102.33a1.689 1.689 0 00-.074.176c-.052.15-.265.555-.35.667a5.21 5.21 0 01-.217.254.578.578 0 00-.065.085.196.196 0 01-.045.055.98.98 0 00-.105.115 1.642 1.642 0 01-.213.223 2.185 2.185 0 01-.296.269.112.112 0 00-.032.03c-.023.04-.377.241-.447.254-.016.003-.028-.002-.03-.013-.006-.02.038-.063.115-.116a.269.269 0 00.06-.052 1.13 1.13 0 01.168-.15c.007-.003.02-.02.031-.038a.267.267 0 01.058-.063.568.568 0 00.083-.089.582.582 0 01.067-.077.392.392 0 00.1-.102c0-.006.027-.046.059-.088a1.69 1.69 0 00.149-.209c.014-.025.034-.049.045-.053.013-.005.03-.033.047-.077a.25.25 0 01.045-.082 2.25 2.25 0 00.202-.361c.01-.029.034-.11.053-.18.02-.07.05-.163.067-.205a.95.95 0 00.07-.303c.002-.016.01-.057.02-.091a.308.308 0 00.01-.096.32.32 0 01.009-.096.325.325 0 00.011-.079.064.064 0 01.009-.036.06.06 0 00.002-.044.062.062 0 01.003-.046.059.059 0 00.004-.043c-.005-.012 0-.046.012-.075.026-.069.027-.107.003-.121a.496.496 0 00-.202.007c-.021.006-.044.007-.052.003-.007-.005-.026.002-.041.015-.05.042-.07.01-.083-.136a1.567 1.567 0 00-.118-.441.673.673 0 01-.061-.132.337.337 0 00-.045-.095.287.287 0 01-.04-.062.246.246 0 00-.049-.067.123.123 0 01-.036-.054c-.002-.013-.017-.032-.033-.041a.096.096 0 01-.039-.044c-.008-.025-.073-.085-.206-.19a.568.568 0 00-.13-.076.285.285 0 01-.08-.041.744.744 0 00-.23-.089c-.011.002-.031.021-.043.043-.02.034-.018.045.012.091a.52.52 0 01.047.327c-.01.028-.016.056-.013.063.004.007-.003.03-.015.05-.012.022-.02.047-.018.056.003.016-.04.16-.081.265a7.73 7.73 0 00-.059.154c-.026.066-.05.156-.062.242-.007.046-.018.083-.025.083a.834.834 0 01-.108-.03c-.185-.06-.212-.068-.229-.063-.018.005-.034.08-.027.125.003.025-.013.063-.135.314-.05.104-.06.142-.056.218a.286.286 0 01-.013.087.273.273 0 00-.008.098.17.17 0 01-.001.065.461.461 0 00.019.127.63.63 0 01.022.122c-.003.004.003.016.012.027.009.01.029.06.043.112.015.051.03.096.036.099a.232.232 0 01.017.08c.005.04.014.08.02.09.018.02-.01.061-.04.06a.462.462 0 01-.104-.034c-.1-.043-.137-.028-.205.079a.373.373 0 00-.07.216c-.004.041-.01.095-.015.12a.204.204 0 00.003.078c.006.018.007.04.002.047a.224.224 0 00-.004.076.707.707 0 01-.048.255.072.072 0 00-.008.046c.014.053-.194.46-.27.528a.196.196 0 00-.051.068.897.897 0 01-.173.199.216.216 0 00-.041.048c-.009.015-.027.03-.04.032-.013.002-.044.03-.068.063-.025.033-.052.06-.06.06s-.022.014-.03.03c-.01.015-.023.027-.03.028-.008 0-.027.015-.042.032a.218.218 0 01-.069.05.133.133 0 00-.047.027.335.335 0 01-.08.045.585.585 0 00-.125.079.495.495 0 01-.09.064.148.148 0 00-.046.03c-.003.006-.022.015-.041.019-.02.004-.04.014-.043.021-.009.015-.266.1-.54.18-.227.065-.343.076-.482.045-.083-.018-.234-.089-.235-.109 0-.022.079-.052.102-.039.01.006.056.006.1 0 .11-.017.456-.11.532-.143.033-.015.11-.044.17-.064a.516.516 0 00.117-.049.175.175 0 01.055-.033.625.625 0 00.114-.076l.109-.086a.912.912 0 00.121-.133l.145-.187a.492.492 0 00.064-.098.37.37 0 01.064-.083l.125-.137a.322.322 0 01.099-.078c.058-.018.075-.07.042-.129a.39.39 0 00-.243-.143c-.08-.006-.096-.027-.068-.085a.173.173 0 00.02-.07c-.002-.012.005-.03.016-.04a.041.041 0 00.011-.043c-.005-.014-.005-.031 0-.039a.378.378 0 00.008-.158.408.408 0 01-.004-.103c.006-.125-.081-.325-.196-.452-.094-.103-.25-.21-.29-.2-.01.003-.034-.004-.054-.016-.072-.042-.122.023-.084.111.033.078.06.286.043.335a.62.62 0 00-.02.09l-.015.093c-.016.1-.256.469-.33.507a.137.137 0 00-.048.041.293.293 0 01-.065.061c-.028.02-.074.058-.101.083a1.333 1.333 0 01-.355.212c-.136.069-.638.18-.686.152-.008-.004-.034-.005-.057-.002a.484.484 0 01-.111-.003 1.512 1.512 0 00-.144-.012.303.303 0 01-.095-.014.175.175 0 00-.063-.014 1.176 1.176 0 01-.27-.08.723.723 0 01-.2-.12 1.455 1.455 0 01-.133-.109 1.485 1.485 0 00-.154-.16.622.622 0 01-.088-.1 14.677 14.677 0 00-.196-.274.612.612 0 01-.083-.166 2.108 2.108 0 01-.108-.303.737.737 0 00-.04-.134.98.98 0 01-.054-.368 1.14 1.14 0 00-.01-.131.627.627 0 01.023-.24.126.126 0 00.007-.055.44.44 0 01.04-.132.582.582 0 00.04-.113c0-.016.081-.183.131-.268.07-.12.096-.157.131-.183a.263.263 0 00.056-.06c.009-.015.027-.03.04-.032.014-.002.04-.023.06-.046a.226.226 0 01.07-.057.219.219 0 00.063-.041.3.3 0 01.091-.05.409.409 0 00.089-.042.805.805 0 01.277-.062c.01.005.043.01.075.01.132-.001.361.11.396.19.01.024.007.032-.02.05-.017.013-.037.02-.044.016a.255.255 0 00-.088.005c-.179.03-.3.126-.415.323l-.075.13-.01.158c-.022.321.058.552.243.702.1.08.179.123.217.118a.115.115 0 01.062.013c.016.01.053.016.081.015.028 0 .058.003.067.008.038.022.462-.066.482-.1a.216.216 0 01.067-.046.354.354 0 00.15-.117.11.11 0 01.052-.043c.024-.008.043-.03.07-.078a72.708 72.708 0 00.099-.18.706.706 0 00.076-.214.422.422 0 01.015-.062.897.897 0 00.053-.387l-.016-.155a2.074 2.074 0 00-.095-.379 1.88 1.88 0 00-.215-.333.658.658 0 01-.112-.123c-.104-.143-.535-.377-.773-.42a.463.463 0 01-.107-.03c-.017-.01-.042-.014-.055-.009a.058.058 0 01-.044-.001.15.15 0 00-.056-.012c-.237-.005-.352-.003-.358.006-.002.005-.035.01-.073.012a.5.5 0 00-.23.095.743.743 0 01-.092.044.281.281 0 00-.064.031.874.874 0 01-.11.06.68.68 0 00-.146.093c-.022.023-.048.042-.056.042s-.021.01-.028.023a.284.284 0 01-.072.06.45.45 0 00-.119.123.819.819 0 01-.089.11.795.795 0 00-.091.123.565.565 0 01-.087.114.28.28 0 00-.061.077 2.3 2.3 0 00-.163.364c0 .015-.01.042-.02.06a.87.87 0 00-.049.14 4.574 4.574 0 01-.049.167 1.4 1.4 0 00-.069.289.551.551 0 01-.022.114.151.151 0 00-.006.08.276.276 0 01-.002.098.385.385 0 00-.006.094.417.417 0 01-.002.085 1.142 1.142 0 00-.005.114 1.193 1.193 0 00.049.531c.013.026.02.053.015.061-.012.02.103.427.144.51a.46.46 0 01.038.108.45.45 0 00.061.125c.031.047.062.105.07.13.017.057.22.375.294.46.03.036.06.077.065.092.005.014.016.03.024.035a.135.135 0 01.032.048c.01.021.034.052.053.069a.464.464 0 01.06.067.99.99 0 00.22.216c.027.014.05.033.05.042 0 .01.014.025.031.035.018.01.034.028.037.039a.636.636 0 00.15.11c.078.048.161.106.183.129a.48.48 0 00.126.08c.075.034.087.043.093.073.008.04.015.029-.267.51-.137.234-.23.383-.239.384a.979.979 0 01-.146-.071 1.528 1.528 0 00-.2-.094.249.249 0 01-.081-.038 1.221 1.221 0 00-.28-.117.46.46 0 01-.1-.038.388.388 0 00-.126-.035.735.735 0 01-.205-.031.257.257 0 00-.08-.014.12.12 0 01-.048-.005.14.14 0 00-.057-.002.558.558 0 01-.146-.02.514.514 0 00-.126-.02.76.76 0 01-.132-.008.703.703 0 00-.157-.003c-.028.005-.06.005-.07 0-.016-.01-.09-.005-.211.014a.155.155 0 01-.059.001c-.006-.003-.035.001-.064.01-.03.009-.058.013-.064.01-.03-.018-.423.076-.64.153-.035.013-.09.03-.122.037a.488.488 0 00-.123.056.574.574 0 01-.11.057c-.024.007-.05.025-.059.039a.055.055 0 01-.045.024c-.017 0-.036.01-.042.02a.333.333 0 01-.097.062.438.438 0 00-.092.053c-.007.01-.12.096-.164.122a.587.587 0 00-.153.124.39.39 0 01-.073.07.587.587 0 00-.098.105.353.353 0 01-.079.084c-.01.003-.03.022-.041.042a.508.508 0 01-.085.093.291.291 0 00-.072.087.387.387 0 01-.062.093c-.11.13-.27.448-.287.567a.517.517 0 01-.057.137.318.318 0 00-.056.163.367.367 0 01-.013.09c-.005.009-.005.026 0 .038a.113.113 0 01-.006.06.67.67 0 00-.005.166l.009.153c0 .015.006.062.014.106.007.044.009.1.004.127-.01.045.057.278.083.293.006.003.013.018.015.032.003.014.012.03.02.035a.338.338 0 01.054.085c.06.117.12.185.363.417.086.083.334.23.446.266.05.016.105.038.121.048.017.01.04.015.054.01a.068.068 0 01.05.007c.015.008.034.012.041.008.008-.005.025-.002.04.007.031.018.19.049.251.048l.107.001c.07.002.412-.094.53-.149.151-.071.233-.12.263-.157a.46.46 0 01.073-.069.655.655 0 00.137-.141.114.114 0 01.044-.039c.017-.006.027-.022.035-.054.006-.025.018-.049.025-.053a.76.76 0 00.127-.212c-.003-.008 0-.026.009-.04a.071.071 0 00.007-.053c-.005-.013-.005-.032 0-.04a.816.816 0 00.017-.15.632.632 0 00-.037-.275 5.544 5.544 0 01-.056-.19.26.26 0 00-.043-.085 3.454 3.454 0 01-.09-.112 1.4 1.4 0 00-.074-.085c-.05-.053-.06-.059-.186-.102a.932.932 0 00-.21-.048.761.761 0 00-.331.074 1.31 1.31 0 01-.103.049.329.329 0 00-.072.044.656.656 0 01-.094.06c-.052.028-.06.038-.152.195l-.096.166.006.113c.007.137.041.267.082.313.034.038.028.083-.01.074a.45.45 0 00-.068-.006c-.056-.001-.184-.06-.184-.084 0-.01-.017-.027-.036-.038a.28.28 0 01-.07-.07 7.224 7.224 0 00-.076-.108c-.059-.081-.123-.392-.092-.445a.242.242 0 00.006-.071 1.141 1.141 0 01.066-.352c.061-.159.253-.46.347-.548l.093-.087a.616.616 0 01.105-.08 1.32 1.32 0 00.175-.102c.034-.024.118-.064.186-.089l.167-.063a.279.279 0 01.078-.018c.019 0 .093-.015.166-.033.12-.03.228-.044.378-.047.09-.002.122 0 .135.006a.439.439 0 00.09.012c.042.002.115.013.16.023.047.01.096.014.11.009.014-.006.041.001.07.02a.497.497 0 00.107.044l.118.036c.032.01.089.026.126.035.077.016.206.1.268.172.02.023.047.049.062.057.023.014.044.04.121.158.013.02.03.04.04.045.021.012.14.186.14.206a.17.17 0 00.025.052l.046.076c.013.02.035.07.048.11.014.04.033.093.043.117.023.056.073.3.085.411a.983.983 0 01.002.168c-.005.043-.003.085.004.094.006.008.003.036-.007.062a.757.757 0 00-.03.121l-.025.155c-.024.144-.208.523-.26.537-.013.004-.032.02-.041.037a.12.12 0 01-.048.044.102.102 0 00-.04.028c-.027.046-.173.122-.297.155a.59.59 0 00-.144.05c-.016.027.006.078.044.1a.66.66 0 01.089.068c.1.091.384.159.513.123.03-.008.06-.011.07-.007.018.01.13-.03.185-.066.02-.014.047-.024.058-.023.032.005.24-.14.266-.186.05-.087.104-.1.143-.036a.618.618 0 00.098.086c.09.07.126.079.198.055.033-.011.038-.017.046-.065a.363.363 0 00.005-.092.12.12 0 01.007-.063.128.128 0 00.014-.048c.004-.062.035-.144.108-.279a1.55 1.55 0 00.15-.382l.013-.079c.019-.096.031-.324.019-.34-.008-.008-.01-.022-.005-.03a.487.487 0 00-.015-.13 4.532 4.532 0 01-.035-.209.711.711 0 00-.037-.152.194.194 0 01-.02-.086c.004-.015-.005-.045-.019-.067a.585.585 0 01-.049-.115.459.459 0 00-.052-.115c-.031-.04-.038-.095-.013-.109.019-.01.161.092.189.136a.156.156 0 00.039.044.12.12 0 01.034.05c.008.022.026.05.04.064.027.026.127.373.13.451a.288.288 0 00.03.096c.015.03.032.096.038.15.006.052.016.113.022.136.006.023.007.047.003.054a.344.344 0 00-.003.093c.007.14.007.194 0 .206a.157.157 0 00.002.064c.005.028.005.058 0 .067-.005.008-.005.026 0 .04a.063.063 0 01-.004.046.186.186 0 00-.011.074.196.196 0 01-.008.066.431.431 0 00-.016.092.642.642 0 01-.027.13.23.23 0 00-.017.068c.002.017-.005.039-.055.18-.072.197-.1.262-.153.342-.012.018-.04.073-.063.12a1.245 1.245 0 01-.258.328c-.056.05-.234.174-.274.19a.174.174 0 00-.045.036.088.088 0 01-.056.027c-.017 0-.035.007-.04.017a.255.255 0 01-.06.05c-.082.053-.158.206-.134.268a.316.316 0 00.068.085c.056.052.081.1.067.125-.008.013-.098.038-.435.12-.141.035-.287.09-.301.116a.188.188 0 01-.043.036c-.02.013-.057.04-.082.06-.026.02-.064.047-.085.06a.79.79 0 00-.14.185c-.094.146-.108.164-.164.195-.072.041-.094.073-.08.114.014.043.087.113.167.162.098.06.098.073.004.137a.403.403 0 00-.101.093.49.49 0 01-.071.087c-.026.025-.079.08-.117.123a5.61 5.61 0 01-.126.138 11.17 11.17 0 00-.136.145.47.47 0 01-.11.094c-.017.006-.034.017-.038.023a.457.457 0 01-.131.034c-.088.015-.13.029-.145.05-.028.037-.011.063.093.145.046.035.112.088.147.117.054.045.086.06.204.1a.94.94 0 00.158.044.428.428 0 01.096.018c.098.026.28.037.387.023a.929.929 0 01.137-.008.471.471 0 00.234-.052c.026-.016.05-.022.064-.013a.04.04 0 00.043-.003.437.437 0 01.085-.043.283.283 0 00.073-.037c.003-.006.028-.014.055-.017l.048-.006.013.067a.971.971 0 00.064.171c.043.09.055.105.078.1.018-.003.032-.018.043-.043a.492.492 0 01.19-.15.287.287 0 00.066-.047.893.893 0 01.091-.073l.072-.048a.116.116 0 00.031-.03.156.156 0 01.04-.035.957.957 0 00.09-.073c.033-.029.07-.06.082-.072a.685.685 0 00.072-.084.343.343 0 01.064-.07c.016-.007.066-.061.188-.205.085-.1.064-.066.252-.41.085-.153.157-.298.162-.32a.736.736 0 01.05-.129 1.143 1.143 0 00.102-.3.384.384 0 01.019-.068c.036-.098.077-.231.078-.256.001-.031.046-.216.064-.267.014-.04.044-.045.057-.009.024.065.002.484-.03.596a.197.197 0 00-.011.075c.003.007-.002.025-.01.041a.512.512 0 00-.034.11c-.009.043-.027.105-.04.137a.298.298 0 00-.021.09.33.33 0 01-.024.094c-.014.036-.035.101-.045.147-.011.045-.038.128-.06.184a9.736 9.736 0 00-.077.198c-.052.142-.436.778-.479.794a.302.302 0 00-.07.08 1.09 1.09 0 01-.087.113 3.827 3.827 0 00-.089.097.59.59 0 01-.094.086.61.61 0 00-.1.092c-.066.078-.268.259-.302.271a1.34 1.34 0 00-.216.148c-.005.008-.033.02-.063.028-.03.007-.058.02-.063.03a.147.147 0 01-.048.035 2.516 2.516 0 00-.18.103.75.75 0 00-.325.377.26.26 0 01-.083.12c-.026.02-.049.047-.05.058-.006.03.079.108.187.171l.097.058-.065.105c-.063.101-.068.115-.108.314-.036.178-.047.213-.077.246-.034.036-.073.133-.067.166.003.015.107.048.178.056a.23.23 0 01.058.013c.006.004.024 0 .038-.01.014-.009.031-.013.038-.009.008.004.056 0 .108-.01.09-.018.095-.017.098.012a.19.19 0 01-.028.085.695.695 0 00-.053.135.81.81 0 01-.125.24c-.057.087-.11.173-.12.189-.008.016-.023.033-.032.036a.405.405 0 00-.07.07.788.788 0 01-.237.203.3.3 0 00-.081.053.199.199 0 01-.072.042c-.073.029-.097.07-.06.108a.554.554 0 00.25.128c.11.01.14.048.097.124-.01.016-.014.035-.01.043.004.008-.004.034-.019.059-.014.025-.022.055-.017.07a.061.061 0 01-.002.044c-.007.01-.01.026-.008.034.002.007-.006.03-.017.052a.87.87 0 00-.055.26c-.008.084-.017.12-.058.254a.587.587 0 00-.023.158.433.433 0 01-.012.12.188.188 0 00-.012.057 8.828 8.828 0 01-.032.585.958.958 0 00-.005.184.062.062 0 01-.002.044.408.408 0 00.007.134c.01.063.017.12.013.125-.003.006.015.104.04.219.048.227.06.301.05.32-.005.007-.003.021.003.031.006.01.015.048.02.084.011.08.118.376.14.39.01.005.017.024.017.042a.95.95 0 00.123.289zM26.512 42.247a.504.504 0 00-.216-.073c-.071-.002-.164.05-.231.127a.49.49 0 00-.053.08c-.106-.176-.273-.236-.453-.162-.057.023-.066.032-.1.102a.491.491 0 00-.042.107c-.005.042.077.184.124.214a.327.327 0 00.181.039c.032-.005.037 0 .06.054.024.052.023.07-.004.155a.37.37 0 01-.105.173 1.28 1.28 0 01-.102.098c-.018.014-.023.029-.016.047.026.064.178-.007.32-.148.079-.08.09-.097.14-.23.026.079.055.139.074.15a.33.33 0 01.062.067c.052.07.19.153.271.162.083.008.087-.024.01-.075a.378.378 0 01-.087-.076 1.465 1.465 0 00-.05-.068.43.43 0 01-.074-.211c0-.065.03-.1.088-.104a.408.408 0 00.182-.05c.046-.03.119-.15.12-.2.002-.042-.05-.138-.099-.178zM27.855 42.693a.618.618 0 00-.297-.1.257.257 0 01-.078-.006c-.022-.006-.05 0-.077.02a.185.185 0 01-.057.03c-.009 0-.03.029-.046.064-.026.055-.029.078-.015.15a.766.766 0 00.039.135c.027.06.191.228.24.245.042.014.044.05.005.064-.04.016-.149.152-.193.243-.086.18-.076.227.06.291.069.033.095.038.145.03.143-.025.206-.056.346-.17.084-.066.244-.34.23-.393a.066.066 0 01.006-.043c.006-.011.009-.026.005-.033-.003-.007-.002-.029.004-.048a.496.496 0 00-.06-.238 1.062 1.062 0 00-.257-.24z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M30.514 41.318a.4.4 0 00.057-.108.232.232 0 01.021-.074c.048-.112.053-.142.033-.193-.026-.062-.033-.066-.087-.05-.041.013-.046.02-.098.128-.109.228-.285.508-.344.546a.197.197 0 00-.052.05.69.69 0 01-.158.154.152.152 0 00-.053.05.416.416 0 01-.14.11.307.307 0 00-.037.026.494.494 0 01-.06.036.18.18 0 00-.054.041c-.023.038-.14.099-.24.126a1.033 1.033 0 00-.138.046c-.044.022-.178.015-.246-.012-.027-.01-.06-.015-.074-.009-.014.006-.027.019-.029.027a1.04 1.04 0 01-.015.052c-.008.024-.001.057.018.095.025.049.047.07.138.129.095.062.116.07.174.075.109.006.157.005.23-.007a.207.207 0 01.086 0c.01.006.027.036.037.068.01.032.024.061.03.064a.383.383 0 01.047.067.64.64 0 00.15.15l.112.088.074.001c.089.002.11-.014.103-.07a.731.731 0 01-.006-.234.41.41 0 00.005-.112c-.006-.052.01-.148.046-.295.006-.022.026-.081.045-.13l.054-.149c.013-.035.03-.064.044-.072.013-.009.023-.023.023-.032 0-.01.05-.116.112-.237.13-.25.116-.226.192-.345zM32.98 47.037c0-.118-.023-.167-.109-.227-.106-.073-.182-.068-.264.02-.06.063-.07.127-.033.245l.026.089-.047.05a.215.215 0 01-.113.066.485.485 0 01-.238-.016.114.114 0 00-.055-.007c-.043.004-.058.024-.045.06.012.033.162.12.192.112a.073.073 0 01.047.01.055.055 0 00.052-.001c.014-.01.035-.012.045-.005.025.014.183-.012.25-.042a.42.42 0 01.075-.027c.036-.005.144-.11.182-.179a.272.272 0 00.035-.148zM34.462 43.456a.28.28 0 00-.037-.088c-.007-.004-.016-.024-.02-.043-.012-.057-.055-.072-.101-.036a.487.487 0 00-.156.239c-.018.087-.037.103-.117.098a1.113 1.113 0 00-.354.089c-.042.033-.037.052.028.103.035.027.092.076.126.108.059.055.07.06.16.083a.99.99 0 00.124.024c.015 0 .037.007.05.014.013.008.052.007.086 0l.063-.015.021-.07c.016-.05.03-.075.05-.09.033-.024.055-.087.083-.237a.333.333 0 00-.006-.179zM34.172 48.644c-.012-.036-.029-.069-.039-.075a.224.224 0 01-.061-.092 1.015 1.015 0 00-.207-.215 2.927 2.927 0 00-.177-.107.64.64 0 00-.483-.087.36.36 0 00-.252.138.28.28 0 01-.053.053c-.02.005-.04.052-.035.075.013.048.056.054.11.013.041-.03.06-.035.093-.026.022.007.046.01.053.006.032-.017.11.05.183.16.04.061.087.127.102.145a.795.795 0 00.174.159.713.713 0 01.118.073c.09.064.097.073.131.157.05.124.053.195.018.355-.035.156-.07.212-.168.275-.065.04-.075.073-.04.123.016.023.029.028.06.026a.399.399 0 00.187-.093.246.246 0 01.061-.055.893.893 0 00.23-.325c.02-.038.033-.078.03-.091-.003-.013.002-.037.012-.053a.134.134 0 00.015-.063.503.503 0 01.006-.082.691.691 0 00-.025-.282 1.24 1.24 0 01-.043-.112zM32.034 46.319c-.01-.05-.098-.184-.118-.183a.508.508 0 01-.098-.063c-.098-.073-.266-.138-.326-.126a.35.35 0 01-.077.004.443.443 0 00-.148.048.34.34 0 00-.162.126.554.554 0 00-.124.263 2.05 2.05 0 01-.016.115.306.306 0 00-.005.075c.002.014 0 .04-.003.056-.012.05.04.196.086.243.065.066.131.087.195.063.05-.02.058-.028.097-.106a.494.494 0 00.076-.258c.001-.068.006-.083.027-.091.017-.007.035-.001.054.016a.29.29 0 00.188.055.163.163 0 01.07.002c.038.01.1-.013.188-.071.075-.05.109-.11.096-.169zM34.768 44.778c.055-.026.064-.036.124-.141.072-.124.076-.158.027-.187-.08-.046-.287-.007-.36.069-.063.067-.136.194-.134.236.005.096.165.107.343.023zM36.824 46.503a1.253 1.253 0 01-.08-.15.734.734 0 00-.051-.102.375.375 0 01-.041-.116 1.304 1.304 0 00-.035-.146 7.292 7.292 0 01-.06-.21.897.897 0 00-.045-.14.632.632 0 01-.032-.122 5.72 5.72 0 00-.035-.157.352.352 0 01-.007-.089.558.558 0 00-.018-.13 1.04 1.04 0 01-.025-.151l-.009-.136a.287.287 0 00-.016-.084c-.006-.01-.007-.025-.003-.032.004-.007.005-.026.002-.041a.925.925 0 010-.135l.007-.191c.004-.161.013-.257.026-.28.008-.013.01-.03.007-.037-.004-.007 0-.032.007-.055a.792.792 0 00.023-.132c.004-.049.012-.104.016-.122a.683.683 0 00.01-.095c.004-.071-.03-.112-.075-.091-.034.015-.05.046-.097.177-.072.2-.095.286-.087.325.002.009-.003.028-.011.042a.576.576 0 00-.024.144 4.205 4.205 0 01-.02.197c-.012.09-.011.282.001.391.005.04.006.079.003.085a.17.17 0 00-.003.06c.006.06-.01.073-.078.068-.029-.002-.057.003-.062.012a.99.99 0 00-.022.16 1.038 1.038 0 01-.022.156.76.76 0 00-.017.135 1.723 1.723 0 01-.106.518c-.01.02-.02.049-.023.065a.492.492 0 01-.07.194.402.402 0 01-.077.112.577.577 0 00-.082.077.216.216 0 01-.133.079c-.232.056-.28.081-.333.172-.02.035-.017.044.031.114.029.041.063.09.077.107.02.026.02.039.001.07-.012.022-.03.042-.038.045-.05.018-.151.146-.267.34a.694.694 0 01-.188.231c-.09.077-.108.087-.18.097-.085.011-.132.037-.132.07 0 .023.016.029.206.07.09.021.17.027.263.021.074-.004.138-.006.142-.004a.828.828 0 00.25-.078.168.168 0 01.073-.029c.018 0 .038-.012.046-.025.018-.032.08-.072.106-.068.011.002.034-.012.051-.03a.625.625 0 01.08-.07.954.954 0 00.2-.242l.053-.089c.04-.064.112-.232.14-.333a2.7 2.7 0 00.07-.41c0-.015.006-.036.013-.048a.065.065 0 00.008-.038.244.244 0 01.008-.068.197.197 0 000-.084c-.005-.018-.005-.043.002-.055.007-.011.009-.027.005-.035a.408.408 0 01-.002-.102 1.02 1.02 0 00-.01-.194.45.45 0 01-.01-.12.195.195 0 00-.003-.075.203.203 0 01-.004-.072c.003-.006.003-.028-.001-.048-.014-.067 0-.253.019-.269.032-.026.051 0 .067.093.028.166.159.622.182.635.006.004.014.024.018.044.004.021.03.093.059.16.028.069.057.154.064.191a.43.43 0 00.054.133c.06.091.076.12.09.17a.429.429 0 00.06.123c.008.01.023.04.034.066.012.03.05.073.093.11l.072.06.054-.015c.042-.012.06-.025.078-.058.035-.067.034-.07-.112-.313l-.125-.203zM33.108 49.778c-.076.034-.078.037-.072.099.003.042.01.052.064.082.068.04.13.041.185.006.044-.029.051-.057.028-.112-.041-.096-.106-.12-.206-.075zM30.988 45.725c.042.092.1.18.12.18a.41.41 0 00.143-.128.355.355 0 00-.066-.164c-.015-.009-.084-.274-.104-.398a.433.433 0 00-.035-.119c-.018-.03-.025-.033-.063-.03-.035.001-.044.008-.056.041a.818.818 0 00-.019.254c.005.012.004.03 0 .038-.013.021.04.236.08.326zM37.417 47.187a.327.327 0 00-.186-.001.235.235 0 00-.109.145.441.441 0 00.047.212c.075.102.076.103.106.097a.48.48 0 01.088-.003c.07.003.147-.042.207-.12.038-.05.038-.052.012-.12-.041-.106-.108-.192-.165-.21zM31.31 48.828a.056.056 0 00.035-.038c.003-.015.013-.027.021-.028.027 0 .094-.053.1-.077.003-.013-.015-.055-.039-.093l-.044-.068-.064.005a.222.222 0 00-.1.035.374.374 0 01-.082.047.147.147 0 00-.065.05c-.01.02-.027.035-.035.035-.009 0-.022.012-.03.026a.09.09 0 01-.044.034.297.297 0 00-.078.058 2.642 2.642 0 01-.11.099c-.077.066-.095.096-.076.127.017.029.118.09.143.087a.204.204 0 00.108-.066.783.783 0 01.225-.152.323.323 0 00.081-.047.18.18 0 01.054-.034zM32.786 49.834a.176.176 0 00-.084-.015.265.265 0 01-.09-.01 1.563 1.563 0 00-.121-.03c-.21-.046-.314-.093-.664-.304a.857.857 0 01-.17-.165.199.199 0 00-.049-.042c-.015-.008-.028-.022-.028-.03 0-.007-.023-.03-.05-.053a.32.32 0 01-.074-.08.34.34 0 00-.088-.089c-.055-.039-.071-.044-.105-.037a.096.096 0 00-.055.036c-.03.052.03.243.087.276.013.007.03.023.037.036.008.012.047.06.087.106.04.046.08.095.09.108.026.043.12.13.173.162.029.016.06.042.069.056.012.02.025.027.048.028.018.001.079.022.137.047.225.097.367.139.455.134a.8.8 0 01.117.003c.03.003.056 0 .06-.006.003-.006.034-.009.069-.005a.185.185 0 00.168-.08c.017-.023.014-.029-.019-.046z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M29.262 42.66c-.042-.013-.203.032-.314.086a.79.79 0 01-.115.05c-.014.002-.028.01-.032.016a.763.763 0 01-.245.089c-.027-.016-.16.02-.211.058l-.05.036-.007.05c-.013.092.034.163.11.166.04 0 .228-.056.273-.084a4.48 4.48 0 01.202-.091c.099-.043.203-.096.232-.117.073-.055.157-.128.183-.16.03-.036.017-.088-.026-.1zM20.825 45.618a.29.29 0 00-.034.078c-.027.079-.017.102.072.172.035.026.05.029.074.014a.163.163 0 00.052-.069.219.219 0 01.03-.056c.023-.014.118-.42.103-.445a.183.183 0 01-.01-.057 2.187 2.187 0 00-.01-.094c-.008-.071-.029-.104-.067-.103-.05.001-.075.038-.093.145-.01.055-.024.127-.032.161a.211.211 0 00-.009.072.642.642 0 01-.076.182zM1.89 42.703c-.072-.052-.085-.058-.217-.094-.08-.022-.318-.009-.369.021a.644.644 0 01-.105.037c-.108.029-.115.048-.051.136.025.035.059.072.074.083.047.03.238.092.254.083.008-.005.025-.005.037 0 .013.005.046 0 .075-.011a.216.216 0 01.07-.018c.052.009.282-.108.308-.155.01-.016-.002-.029-.076-.082zM1.812 41.368c-.065-.047-.411-.174-.437-.16a.554.554 0 01-.089.013.716.716 0 00-.417.205c-.041.037-.046.047-.032.071.008.015.023.028.031.028.009 0 .024.015.034.033.025.042.155.091.27.102.093.008.2-.005.284-.036a.199.199 0 01.073-.015c.034.006.313-.145.324-.175.011-.03.015-.025-.04-.066zM20.323 45.987c-.085.033-.115.05-.132.074a.23.23 0 01-.061.054.26.26 0 00-.072.073.251.251 0 01-.05.06c-.023.013-.028.1-.008.152.018.047.091.107.158.129a.508.508 0 00.345-.02c.08-.046.098-.035.11.072l.014.115a.483.483 0 00.115.215c.088.068.149.056.249-.05.04-.042.053-.071.066-.144.019-.101.02-.149.004-.177a.373.373 0 01-.017-.097.502.502 0 00-.258-.418.49.49 0 01-.087-.052c-.063-.048-.234-.042-.377.014zM20.748 48.984c-.046-.006-.05-.004-.1.047-.027.03-.066.069-.084.088l-.13.136a1.35 1.35 0 01-.412.325c-.206.12-.331.173-.47.2a1.318 1.318 0 00-.128.03.345.345 0 01-.1.013.195.195 0 00-.087.016c-.027.016-.03.023-.012.052.025.045.084.067.194.074.232.014.358 0 .465-.05a.245.245 0 01.088-.028 1.467 1.467 0 00.339-.153.898.898 0 00.254-.248.115.115 0 01.038-.045.184.184 0 00.047-.053.937.937 0 01.083-.103.288.288 0 00.08-.15c.024-.101.006-.142-.064-.15zM3.882 41.997c-.023-.008-.048-.001-.095.026a1.6 1.6 0 01-.434.1.16.16 0 00-.055.01.102.102 0 01-.044.008c-.023-.001-.036.007-.056.034-.047.061-.04.101.044.248a.841.841 0 00.092.142c.01.005.046.01.08.012.057.002.065 0 .073-.026a.517.517 0 01.086-.108.682.682 0 00.086-.101c.017-.044.078-.102.175-.167.07-.048.1-.076.103-.095a.077.077 0 00-.055-.083zM2.664 42.36a3.13 3.13 0 01-.174-.118.44.44 0 00-.278-.053c-.101.025-.354.12-.37.14-.01.013-.004.029.027.071.046.062.149.112.288.14.116.025.277.014.34-.022.014-.008.03-.011.038-.007a.52.52 0 00.196-.073c.012-.022-.003-.039-.067-.079zM1.749 36.037a.253.253 0 01-.086-.03c-.018-.015-.102-.023-.124-.01-.005.003-.009.027-.007.052.002.044.007.051.073.11a.698.698 0 00.107.083.51.51 0 01.074.048.478.478 0 00.1.055c.034.014.086.036.115.05.03.015.076.036.104.047a.435.435 0 01.083.045c.018.013.038.021.044.018.006-.004.041.007.078.024.038.018.074.028.082.024.008-.005.025-.004.039 0 .04.017.098-.027.116-.088.014-.048.011-.063-.019-.115l-.034-.06-.22-.06c-.189-.054-.438-.148-.452-.172a.247.247 0 00-.073-.02zM20.444 46.865c-.037-.066-.045-.073-.114-.097-.072-.026-.078-.025-.153.012-.066.032-.08.045-.094.08a.131.131 0 01-.032.053c-.029.016-.008.114.04.195.082.137.145.161.272.104.052-.023.063-.033.07-.064.004-.021.013-.041.02-.046.017-.01.035-.083.032-.13a.355.355 0 00-.041-.107z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M.78 35.55a.6.6 0 00.017.09.31.31 0 01.013.079.072.072 0 00.01.04c.02.034.04.327.028.425-.011.094.001.13.047.139.102.02.246-.062.346-.198a.236.236 0 01.04-.043.146.146 0 00.028-.053.292.292 0 01.103-.133.097.097 0 01.06-.005c.057.013.27.002.3-.015.015-.01.034-.012.043-.008.017.01.064-.025.144-.104a.214.214 0 00.067-.118c.022-.105-.011-.135-.11-.098-.029.011-.058.017-.065.014-.007-.004-.02-.002-.032.004-.056.031-.386-.079-.5-.167a.517.517 0 00-.088-.057c-.014-.005-.03-.015-.033-.02a.208.208 0 00-.044-.036.956.956 0 01-.174-.157.06.06 0 00-.028-.024.717.717 0 01-.16-.142.126.126 0 00-.048-.04.281.281 0 01-.082-.093.85.85 0 00-.091-.12c-.023-.023-.042-.049-.042-.058 0-.018-.05-.118-.146-.295-.048-.087-.07-.118-.09-.123-.035-.01-.082.035-.084.08-.003.06.046.231.076.266.015.017.026.04.024.051-.002.013.014.042.043.078a.255.255 0 01.049.08c.001.013.066.137.145.276.078.139.141.26.14.271a.328.328 0 00.045.101.399.399 0 01.049.113zM4.242 35.706c-.014.05-.012.074.013.133.043.1.09.138.216.17.14.037.159.066.123.193a.321.321 0 01-.068.134.196.196 0 00-.047.068c-.002.013-.02.034-.042.046-.08.046-.079.096.001.097.064.002.22-.098.271-.173.021-.03.046-.06.056-.066.01-.006.022-.031.028-.056.006-.025.015-.048.022-.051a.417.417 0 00.035-.111.847.847 0 00-.003-.339.158.158 0 00-.025-.048 6.775 6.775 0 01-.056-.072.325.325 0 00-.402-.078c-.033.02-.06.042-.06.05 0 .01-.01.022-.022.029-.012.007-.03.04-.04.074zM2.073 43.287c.012-.002.032-.02.045-.04.034-.054.391-.318.474-.35a.239.239 0 00.075-.057c.025-.028.103-.08.258-.168.198-.112.223-.13.223-.153 0-.042-.02-.067-.053-.066-.016 0-.123.052-.237.115-.281.155-.51.27-.545.275a1.57 1.57 0 00-.178.066c-.146.06-.22.087-.337.123-.12.036-.337.132-.478.21-.138.077-.23.148-.274.212a.162.162 0 01-.065.044.14.14 0 00-.069.053.19.19 0 01-.053.054.318.318 0 00-.074.097.378.378 0 01-.06.09c-.022.013-.044.113-.026.123a.033.033 0 00.03 0 .712.712 0 01.13-.012.583.583 0 00.136-.017.456.456 0 01.097-.025.583.583 0 00.145-.047.248.248 0 01.08-.032c.008.002.031-.006.053-.019a.18.18 0 01.069-.023c.02 0 .04-.013.068-.04.03-.03.046-.04.063-.037.016.003.034-.007.06-.033a.593.593 0 01.1-.073c.061-.035.213-.158.286-.231a.152.152 0 01.057-.039zM2.046 40.74c.007.014.014.05.014.08s.006.059.014.063c.008.005.04.048.071.096.031.048.065.09.076.092.01.003.025.018.034.033a.61.61 0 00.234.142c.04.006.042.005.041-.023 0-.016.006-.06.013-.098a.434.434 0 00.001-.135.642.642 0 00-.061-.155 1.916 1.916 0 00-.247-.328.74.74 0 01-.074-.084c-.02-.028-.046-.05-.056-.048-.024.004-.075.074-.065.091a.177.177 0 01.002.07.236.236 0 00-.003.062.235.235 0 01-.002.063c-.004.03 0 .066.008.08z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M2.378 41.397a.587.587 0 01-.145-.078l-.11-.073a2.071 2.071 0 01-.375-.362c-.03-.044-.034-.063-.03-.148a.509.509 0 00-.014-.149c-.03-.084-.118-.222-.154-.24a.128.128 0 01-.046-.04.726.726 0 00-.158-.13.35.35 0 01-.058-.047.241.241 0 00-.077-.047c-.042-.015-.057-.014-.077.005a.162.162 0 00-.036.062c-.005.02-.02.064-.032.097-.013.034-.02.066-.016.072.006.01.005.032-.003.153-.002.03.004.06.013.068.01.008.017.026.018.04.001.034.13.208.163.221a.32.32 0 01.07.051.488.488 0 00.148.077c.115.039.13.05.22.15a.716.716 0 00.099.095c.02.014.05.041.068.063a.22.22 0 00.07.053c.02.009.068.043.106.077.072.064.15.114.255.164.05.024.06.034.057.055-.003.014-.01.03-.018.034a.468.468 0 01-.147.01.668.668 0 00-.192.045.823.823 0 00-.131.066l-.08.048.032.047a.343.343 0 00.08.078.273.273 0 01.055.045c.015.025.182.058.26.05a.844.844 0 00.3-.07l.102-.06c.072-.04.077-.067.021-.11-.042-.032-.053-.057-.031-.07a.517.517 0 01.128.031c.186.06.55.156.562.15a.216.216 0 01.073.002.688.688 0 00.108.007.46.46 0 01.107.014.472.472 0 00.099.015c.036 0 .075-.03.076-.06.001-.024-.035-.055-.06-.051-.111.017-.735-.155-1.078-.298a1.388 1.388 0 01-.222-.112zM4.054 36.422a.158.158 0 01-.056-.03c-.004-.007-.031-.017-.06-.022-.047-.01-.063-.005-.141.042-.119.07-.15.11-.166.218-.012.078-.01.096.02.148.036.062.066.082.164.113.097.03.13.027.23-.027l.094-.05.02-.093c.017-.081.016-.101-.012-.164a.918.918 0 01-.034-.086c-.006-.027-.01-.031-.06-.05zM14.783 47.172c-.066-.03-.23-.01-.255.033a.252.252 0 01-.04.047.37.37 0 00-.074.174c0 .05.05.12.102.146a.24.24 0 01.054.033.317.317 0 00.098.003c.079-.004.098-.01.13-.04a.33.33 0 00.084-.218c-.003-.074-.047-.154-.1-.178zM17.497 47.737a.298.298 0 01-.087-.031c-.004-.006-.018-.013-.032-.015a.494.494 0 01-.106-.061c-.08-.056-.083-.06-.2-.258a2.074 2.074 0 00-.136-.208.64.64 0 01-.07-.066.725.725 0 00-.083-.075c-.041-.027-.04-.057.003-.101.051-.051.108-.175.096-.207-.021-.052-.125-.112-.248-.144-.104-.026-.131-.04-.183-.09a1.738 1.738 0 00-.084-.076.395.395 0 01-.136-.183.68.68 0 01-.05-.135.459.459 0 00-.035-.104 1.07 1.07 0 01-.069-.292.152.152 0 00-.017-.06.088.088 0 01-.006-.062.504.504 0 00-.014-.212.811.811 0 01-.022-.163c-.01-.122-.015-.144-.04-.162-.022-.016-.038-.016-.064-.001-.049.028-.071.005-.063-.065a.246.246 0 00.003-.066c-.003-.004 0-.09.005-.19.006-.101.007-.213.002-.248a.228.228 0 010-.08c.004-.009.003-.024-.003-.035a1.012 1.012 0 01-.03-.224.174.174 0 00-.016-.069.258.258 0 01-.016-.095.22.22 0 00-.028-.109.834.834 0 01-.09-.217c0-.03-.046-.084-.08-.094-.055-.017-.063.084-.025.303.03.172.055.37.06.49.012.284.012.383.001.43a1.876 1.876 0 00-.025.274.483.483 0 01-.019.112.852.852 0 00-.024.139c-.004.072-.039.222-.108.462-.063.22-.15.493-.16.498a.228.228 0 00-.027.06c-.04.11-.058.146-.074.156-.01.005-.02.02-.021.035a.33.33 0 01-.09.138c-.012.007-.022.02-.022.029a.797.797 0 00-.123.235c-.026.07-.012.104.056.142.055.03.122.013.168-.042a.261.261 0 01.044-.043.252.252 0 00.043-.084.707.707 0 01.047-.106c.011-.018.036-.06.054-.094l.059-.108c.014-.025.039-.084.055-.13a.811.811 0 01.06-.133c.017-.027.027-.053.024-.06-.004-.006.004-.028.017-.048a.954.954 0 00.06-.172c.02-.074.062-.22.093-.323.032-.104.059-.216.06-.25.002-.034.01-.066.019-.07.008-.005.017-.031.019-.059.01-.108.057-.066.066.058a.64.64 0 00.012.104c.007.013 0 .147-.016.288a1.785 1.785 0 00-.012.304 3.352 3.352 0 00.046.553c.005.044.01.094.013.11a.878.878 0 00.06.21c.01.018.015.038.012.044-.006.011.071.191.102.24.147.226.219.318.282.365a.47.47 0 01.079.068c.005.01.023.017.039.016.016 0 .046.016.068.036.06.055.187.116.274.131.155.028.23.036.305.031a.388.388 0 01.11.007c.02.006.044.006.055 0 .011-.007.027-.01.034-.005.007.004.04-.004.072-.018a.33.33 0 01.085-.024c.041-.001.082-.03.078-.056-.003-.017-.03-.03-.086-.045zM17.842 44.034c.024-.008.049-.012.055-.008.007.004.023 0 .036-.007a.428.428 0 01.09-.027.304.304 0 00.114-.048c.052-.04.203-.172.22-.193.025-.032-.023-.063-.157-.104a.575.575 0 00-.21-.034c-.039.004-.078 0-.088-.007a.22.22 0 01-.037-.077c-.022-.073-.093-.196-.119-.206a.12.12 0 01-.038-.033c-.032-.04-.08-.025-.1.033-.01.027-.024.053-.032.057-.018.01-.04.11-.044.204-.003.066.006.091.11.306.06.127.062.129.11.144a.17.17 0 00.09 0zM19.608 47.437a.379.379 0 00.045-.003l.08-.009c.046-.004.071-.016.126-.057.037-.029.068-.061.069-.073 0-.03-.034-.038-.094-.023a.662.662 0 01-.29-.008c-.073-.025-.14-.102-.121-.137.076-.138.07-.214-.022-.31-.043-.044-.064-.055-.116-.06-.058-.006-.071-.002-.128.038-.085.06-.129.136-.122.212.002.017.003.047.003.069 0 .047.065.162.127.224a.69.69 0 00.37.139l.073-.002zM3.026 43.134a.632.632 0 01-.017-.136.834.834 0 00-.013-.128c-.013-.024-.051-.004-.133.07a3.26 3.26 0 01-.126.107.191.191 0 00-.054.066c-.017.045-.044.09-.061.1-.014.008-.021.04-.063.261-.013.068.006.183.033.198.027.015.194-.113.343-.264.042-.042.108-.244.09-.274zM3.856 30.606a.273.273 0 00.201-.025c.046-.027.054-.04.073-.11.023-.092.013-.119-.062-.169-.085-.055-.145-.058-.231-.01-.072.039-.074.042-.088.109-.012.06-.01.076.022.131.03.053.043.064.085.074zM2.993 32.015a.66.66 0 00.02.138.3.3 0 01.017.086c.005.06.016.086.105.24.06.103.108.175.12.18.012.004.04.027.064.05a.213.213 0 00.076.048.078.078 0 01.046.03c.014.024.154.09.242.115.133.037.276.035.343-.003a.061.061 0 01.04-.006c.026.007.225-.103.222-.122-.002-.008-.039-.033-.082-.055-.077-.04-.08-.042-.16-.173a1.076 1.076 0 00-.105-.153 1.088 1.088 0 00-.312-.117c-.114-.012-.197-.035-.21-.059a.133.133 0 00-.038-.038c-.034-.022-.068-.138-.08-.275a.282.282 0 00-.014-.075c-.016-.027-.006-.204.015-.287a.295.295 0 00.015-.088 1.32 1.32 0 01.111-.351.638.638 0 00.052-.095.56.56 0 01.19-.233c.027-.016.05-.034.052-.04.007-.028-.022-.053-.051-.044a.533.533 0 00-.114.079.555.555 0 01-.11.077.044.044 0 00-.029.032c-.003.017-.02.031-.057.048-.033.014-.054.03-.054.04 0 .01-.013.026-.028.034-.015.01-.028.023-.028.032 0 .009-.01.021-.021.028a.063.063 0 00-.026.04.242.242 0 01-.03.068.939.939 0 00-.11.272c-.047.17-.09.39-.085.427.002.018.009.085.014.15z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M14.98 45.806a.507.507 0 01.082-.072.495.495 0 00.132-.129l.055-.082a.27.27 0 00.04-.072c0-.008.01-.02.021-.026a.195.195 0 00.046-.073.236.236 0 01.037-.069c.007-.004.016-.024.02-.043.004-.02.013-.04.02-.043a.514.514 0 00.058-.19c-.01-.062-.048-.082-.099-.052-.019.01-.031.03-.03.046 0 .016-.02.05-.046.075-.026.026-.058.06-.071.076-.068.083-.255.161-.38.16a.624.624 0 00-.131.014 3.927 3.927 0 01-.159.034.64.64 0 00-.31.138.341.341 0 00-.062.069.067.067 0 01-.027.028.216.216 0 00-.05.05 1.211 1.211 0 01-.216.214c-.045.025-.052.064-.014.074a.061.061 0 01.032.025c.053.092.345.154.551.116.124-.022.442-.192.501-.268zM19.079 48.197a1.095 1.095 0 01-.076-.06c-.044-.035-.08-.048-.19-.066-.185-.03-.302-.007-.49.096-.075.04-.144.076-.154.08a1.068 1.068 0 00-.23.253.614.614 0 01-.064.097.527.527 0 00-.075.169.602.602 0 00-.02.26.812.812 0 00.026.167c.008.013.01.03.007.037-.004.008.007.039.024.07.017.03.046.092.064.137a.375.375 0 00.073.123c.123.126.19.183.215.183a.05.05 0 01.04.022c.013.024.12.04.151.022.025-.015.032-.05.015-.079a.69.69 0 00-.089-.09c-.073-.065-.075-.069-.115-.175-.06-.164-.066-.28-.018-.389.049-.11.065-.127.224-.233.152-.102.276-.224.315-.313.037-.085.088-.143.143-.164.071-.027.176-.025.203.004.023.024.067.017.092-.014.015-.019-.035-.115-.071-.137zM18.182 43.347a.4.4 0 00.155-.096c.02-.02.04-.064.048-.1.01-.054.007-.07-.018-.102-.036-.043-.115-.07-.181-.063-.042.005-.055.013-.107.07-.059.064-.084.14-.06.181.018.031.14.113.163.11zM2.905 41.203c.08.145.083.149.166.208.056.04.125.072.2.094l.116.034.01-.059a.463.463 0 00.002-.11l-.01-.072a.613.613 0 01-.003-.061.4.4 0 00-.064-.149c-.058-.102-.069-.113-.152-.17a1.692 1.692 0 01-.138-.103.324.324 0 00-.08-.053c-.063-.022-.127.085-.112.186a.183.183 0 01-.004.076c-.01.027-.002.05.07.179zM2.747 36.806a.64.64 0 00.271.297c.043.026.08.051.084.057.003.006.019.01.035.01.016-.001.038.007.05.018.022.02.22.014.257-.008.034-.02.094-.122.09-.153a.706.706 0 00-.236-.379c-.07-.044-.07-.067-.003-.094a.583.583 0 00.24-.238.661.661 0 00.051-.244c-.015-.048-.073-.113-.114-.127a.57.57 0 00-.33.019c-.09.036-.258.135-.282.164-.007.01-.039.042-.07.074a.308.308 0 00-.068.096l-.035.109a.434.434 0 00-.017.17c.008.087.016.114.077.229zM18.924 49.778c-.068-.04-.147-.022-.193.046-.055.082-.01.165.097.175.062.007.139-.05.156-.115.014-.054.007-.066-.06-.106zM2.314 43.422c.015-.096-.028-.104-.148-.03-.216.135-.301.25-.331.443-.014.091-.012.108.019.168.019.036.039.077.045.091.008.02.018.022.046.01a.865.865 0 00.216-.2.78.78 0 01.066-.086c.05-.055.099-.16.092-.2a.174.174 0 01.007-.067.09.09 0 00-.004-.062.12.12 0 01-.008-.067zM13.518 47.872a.63.63 0 01-.26.048.722.722 0 00-.116-.01c-.152 0-.41-.074-.556-.159a.463.463 0 00-.097-.044c-.02-.004-.041-.018-.048-.03a.276.276 0 00-.064-.057.28.28 0 01-.062-.054.534.534 0 00-.073-.073c-.059-.051-.063-.057-.077-.123-.015-.07 0-.138.064-.285.016-.038.027-.075.024-.08a.358.358 0 010-.089c.01-.111 0-.15-.064-.274a.446.446 0 01-.065-.264c0-.08-.014-.084-.112-.022-.12.077-.167.128-.266.29a.607.607 0 00-.074.328c.003.059.004.118.002.132a.518.518 0 00.047.214c.01.008.017.025.015.037-.005.03.053.137.122.222.06.075.16.172.187.18a.075.075 0 01.03.03c.008.013.04.038.07.055a1.54 1.54 0 00.802.253c.145.003.24-.015.31-.057.018-.01.041-.019.051-.017a.325.325 0 00.092-.029.34.34 0 01.091-.029.227.227 0 00.08-.042c.05-.035.06-.048.051-.065-.012-.021-.05-.017-.104.014zM8.706 25.026a2.066 2.066 0 01-.091-.072.303.303 0 00-.063-.042.176.176 0 01-.046-.03c-.038-.036-.19-.064-.254-.048-.09.024-.14.07-.152.139-.008.052-.005.063.043.136a.494.494 0 00.185.195c.059.035.07.047.066.07-.003.017-.016.03-.041.038a.29.29 0 00-.142.135.166.166 0 01-.036.06c-.028.028-.04.094-.033.2.006.09.04.148.098.166.047.016.207.007.217-.011a.512.512 0 01.103-.053c.112-.049.253-.162.272-.22a.349.349 0 01.035-.069.445.445 0 00.032-.152.34.34 0 00-.028-.203.555.555 0 00-.165-.24zM20.855 37.34a.318.318 0 00.004-.113c-.013-.022-.105-.051-.125-.04a.481.481 0 00-.052.124.743.743 0 01-.046.12 1.009 1.009 0 00-.027.203l-.011.117c-.005.05-.009.121-.008.158 0 .036-.006.08-.014.097-.013.025-.009.05.015.105a.47.47 0 01.034.102c.004.05.07.112.117.112.036 0 .045-.005.078-.045.038-.045.042-.08.027-.219a2.486 2.486 0 01-.006-.072.222.222 0 00-.012-.067.203.203 0 01-.006-.076.216.216 0 00-.004-.074c-.004-.008-.003-.03.003-.049.006-.019.007-.04.003-.048a.387.387 0 01.01-.114.408.408 0 00.012-.114.38.38 0 01.008-.107zM21.044 36.147c.024.057.036.072.066.083.033.013.04.011.069-.023.038-.043.067-.117.115-.29a.499.499 0 01.048-.131c.008-.005.019-.028.024-.052a1.057 1.057 0 01.286-.387c.057-.056.106-.11.11-.12a.285.285 0 01.057-.061c.028-.024.087-.075.131-.115.141-.126.245-.196.394-.264a.71.71 0 01.336-.082.12.12 0 00.1-.075c.006-.017.008-.035.005-.04-.01-.018-.106-.045-.135-.039a.814.814 0 01-.073.012 1.143 1.143 0 00-.354.112c-.179.08-.496.268-.52.309a.148.148 0 01-.046.04.445.445 0 00-.071.059l-.08.078a.942.942 0 00-.056.062l-.061.067c-.024.025-.079.1-.122.166a1.092 1.092 0 01-.09.128c-.008.004-.013.021-.012.038 0 .017-.006.035-.015.04-.009.005-.024.032-.033.059a.179.179 0 01-.026.054.703.703 0 00-.067.21.188.188 0 01-.003.057.244.244 0 00.023.105zM13.912 42.384a3.416 3.416 0 01-.021-.196c0-.112-.008-.2-.02-.22a.195.195 0 01-.013-.08c0-.051.004-.056.047-.071.026-.01.085-.035.132-.058.084-.041.086-.043.09-.091a.16.16 0 00-.012-.078.434.434 0 01-.023-.126c-.006-.095-.01-.104-.084-.232-.085-.146-.136-.203-.218-.244a.338.338 0 01-.078-.052.227.227 0 00-.071-.044.151.151 0 01-.053-.03.18.18 0 00-.055-.033c-.043-.02-.054-.035-.152-.204-.085-.145-.109-.196-.12-.255-.019-.09-.04-.128-.076-.135-.024-.004-.028 0-.03.031 0 .02-.009.04-.018.046a.243.243 0 00-.046.07c-.042.082-.066.12-.081.129-.007.004-.017.034-.022.067a.441.441 0 01-.035.113 2.593 2.593 0 00-.11.336.976.976 0 00-.017.115 1.03 1.03 0 01-.018.118.362.362 0 00-.01.085l.002.07c0 .013.005.052.01.088.006.035.012.076.013.09 0 .015.006.035.012.045.005.01.012.043.014.074.003.05.017.089.09.257.063.144.25.407.326.46a.488.488 0 00.172.078c.012 0 .026.007.031.016.013.022.169.064.257.07l.117.008c.084.007.095-.026.07-.217zM25.327 43.331c-.003-.112-.045-.195-.124-.245-.082-.052-.137-.052-.237-.001-.102.052-.14.103-.166.224-.015.072-.013.089.014.137.039.066.14.124.255.143l.074.013.086-.064c.097-.071.102-.08.098-.207zM25.594 30.112a.19.19 0 01.035-.044c.012-.008.105-.198.105-.217 0-.008.022-.04.047-.07.031-.037.045-.066.042-.088-.003-.018.003-.038.014-.045a.248.248 0 00.049-.082c.016-.039.043-.094.06-.122a.952.952 0 00.05-.095c.008.034.027.07.057.1.021.023.043.051.048.065a.857.857 0 00.053.094.946.946 0 01.07.134c.04.105.143.308.187.367.103.14.38.35.579.438.134.059.376.135.405.127.007-.002.025.003.04.011.014.009.032.012.04.008.007-.004.023-.002.035.005.012.007.034.006.047-.003.016-.01.062-.007.124.007.054.012.114.02.133.015a.552.552 0 01.14.014l.16.03c.1.016.186.048.311.113l.231.117c.06.029.18.092.266.14.301.163.384.201.48.22.066.012.104.01.13-.004.036-.02.037-.023.027-.068-.022-.1-.083-.151-.46-.39a58.174 58.174 0 01-.473-.303c-.158-.1-.218-.149-.265-.212a.324.324 0 00-.053-.06 1.474 1.474 0 01-.12-.164 1.547 1.547 0 00-.12-.163.198.198 0 01-.04-.062.874.874 0 00-.188-.226.092.092 0 01-.036-.045c-.006-.019-.047-.057-.111-.104a1.158 1.158 0 01-.132-.108c-.017-.02-.042-.036-.055-.038a.664.664 0 01-.114-.048 1.72 1.72 0 00-.192-.08 10.75 10.75 0 01-.16-.055.415.415 0 00-.104-.022.199.199 0 01-.056-.008 1.173 1.173 0 00-.24.017.263.263 0 01-.084-.006c-.047-.009-.08-.006-.097.008-.013.011-.034.016-.046.01a.245.245 0 00-.096-.001 1.04 1.04 0 01-.135.008.93.93 0 00-.107.005.215.215 0 00.059-.1.265.265 0 01.031-.074.862.862 0 00.055-.093.933.933 0 01.082-.127c.07-.087.194-.279.223-.346.07-.16.112-.505.089-.721-.016-.146-.07-.394-.093-.415-.005-.005-.01-.023-.01-.04s-.005-.034-.013-.039c-.007-.004-.013-.02-.013-.033 0-.014-.012-.032-.026-.04-.016-.008-.037-.05-.056-.11a.48.48 0 00-.054-.123.552.552 0 01-.058-.128 8.957 8.957 0 00-.054-.153 1.009 1.009 0 01-.058-.328c-.003-.076-.01-.192-.014-.258a8.838 8.838 0 01-.013-.3c-.008-.344-.017-.435-.05-.527-.021-.064-.04-.095-.067-.111-.035-.02-.038-.02-.073.011-.074.069-.089.147-.107.593a47.121 47.121 0 01-.025.562c-.008.187-.02.263-.051.336a.317.317 0 00-.025.076c0 .01-.037.094-.082.186a1.538 1.538 0 00-.08.186.2.2 0 01-.034.066.877.877 0 00-.102.275c0 .017-.01.042-.021.054-.013.015-.026.07-.034.148-.007.069-.02.145-.028.17-.008.023-.01.053-.005.066a.67.67 0 01.015.122c.003.055.015.148.027.207l.032.167c.006.033.021.078.033.1a.197.197 0 01.021.053c0 .015.118.19.135.2a.263.263 0 01.036.075c.017.046.036.073.056.08.017.006.031.022.031.035 0 .013.022.051.048.084.025.033.059.084.075.113a.91.91 0 00.057.09.216.216 0 00-.116 0 .263.263 0 01-.079.01.868.868 0 00-.108-.002.934.934 0 01-.15-.007 2.377 2.377 0 00-.412-.02c-.172.019-.492.155-.668.283-.118.086-.305.258-.312.287-.002.008-.016.02-.03.029-.015.008-.027.022-.027.03 0 .01-.01.022-.022.03-.012.006-.022.025-.02.041 0 .019-.026.058-.069.104a.48.48 0 00-.08.108.55.55 0 01-.08.114c-.039.045-.087.1-.106.124a1.007 1.007 0 01-.255.214l-.216.142c-.055.037-.17.11-.254.16-.292.18-.367.233-.43.307-.044.05-.062.084-.062.114 0 .041.001.043.046.058.096.03.172.003.566-.204a55.03 55.03 0 01.499-.259c.166-.087.238-.115.316-.124a.318.318 0 00.079-.016c.009-.005.1-.015.201-.023.102-.007.193-.017.201-.022a.199.199 0 01.074-.004.874.874 0 00.29-.05.092.092 0 01.056-.008c.02.004.073-.012.145-.044.063-.029.135-.056.16-.06.025-.006.052-.019.06-.03a.669.669 0 01.099-.074c.046-.03.12-.087.165-.127l.128-.112a.415.415 0 00.07-.078zm.406-.845h.003l-.001.002-.002-.002zM9.84 25.62a.82.82 0 00-.21-.143c-.013-.002-.027-.011-.032-.02-.013-.021-.225-.082-.323-.092-.1-.01-.206-.005-.215.012-.011.022.02.171.039.189.02.018.154.037.175.025.014-.009.278.063.395.108.045.017.099.03.12.03.036 0 .043-.006.06-.04.015-.03.013-.042-.01-.069zM23.566 42.925a1.825 1.825 0 01-.339-.094c-.004-.008-.031-.02-.061-.027-.03-.008-.058-.02-.063-.029a1.22 1.22 0 00-.331-.12c-.033.008-.07.074-.051.09l.106.098a.732.732 0 00.147.111c.03.013.07.035.088.048.018.014.095.048.17.077.076.028.14.055.142.059.01.018.158.064.222.069.064.005.073.002.102-.03a.177.177 0 00.037-.08c.011-.082-.056-.151-.169-.172zM3.432 44.178c-.002-.054-.002-.055-.028-.069-.025-.013-.285.133-.294.166a.073.073 0 01-.031.037c-.014.008-.026.022-.026.03 0 .009-.012.023-.026.03a.456.456 0 00-.137.181c-.007.026-.02.052-.03.057a.524.524 0 00-.05.232c.005.01.013.047.017.081l.006.063.047-.002a.423.423 0 00.133-.047.509.509 0 01.102-.044c.025 0 .16-.131.18-.176a.148.148 0 01.03-.046.784.784 0 00.086-.252.76.76 0 01.01-.118.804.804 0 00.011-.123zM21.194 48.868a.187.187 0 01-.052-.051.139.139 0 00-.051-.047.639.639 0 01-.102-.074c-.1-.086-.231-.16-.295-.165-.065-.005-.087.013-.115.099-.017.051-.015.063.01.09a.232.232 0 00.058.047.117.117 0 01.043.038c.008.014.027.03.044.038.016.007.035.02.041.03.006.01.037.026.069.038.031.011.062.03.069.04.006.011.045.037.086.058a.41.41 0 01.106.074c.058.068.164.052.218-.034.013-.021.022-.04.02-.045a1.115 1.115 0 00-.149-.136zM24.75 42.75c-.027-.114-.117-.158-.3-.146-.111.007-.112.007-.262.094a.618.618 0 00-.16.11.194.194 0 01-.044.055.426.426 0 00-.115.189.769.769 0 00.021.342c.061.175.276.4.404.423.015.002.032.011.036.02.01.016.159.04.18.029.007-.005.024-.004.036 0 .038.015.093-.015.125-.07a.22.22 0 00-.003-.21c-.108-.181-.142-.23-.18-.259-.062-.046-.054-.07.043-.138.098-.07.168-.147.166-.183a.11.11 0 01.027-.06c.015-.018.023-.04.018-.049-.005-.009-.003-.036.004-.06a.202.202 0 00.003-.087z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M24.86 36.322c.017-.01.032-.03.034-.044a.058.058 0 01.023-.037.15.15 0 00.039-.044c.123-.202.179-.303.173-.313-.003-.004.009-.036.026-.069a.504.504 0 00.034-.247.73.73 0 01.007-.102.28.28 0 00.005-.07.88.88 0 01.004-.125.684.684 0 00-.008-.174c-.008-.03-.012-.063-.008-.07.004-.007.001-.023-.006-.036a.284.284 0 01-.015-.091.452.452 0 00-.048-.166.818.818 0 01-.05-.131.798.798 0 00-.06-.141.562.562 0 01-.056-.133.285.285 0 00-.037-.091 2.298 2.298 0 00-.233-.323.166.166 0 01-.042-.048.878.878 0 00-.097-.113 4.68 4.68 0 01-.12-.125 1.405 1.405 0 00-.215-.204.545.545 0 01-.087-.077.152.152 0 00-.065-.045.277.277 0 01-.085-.05.382.382 0 00-.078-.053.416.416 0 01-.073-.044 1.124 1.124 0 00-.096-.062 1.19 1.19 0 00-.484-.223c-.028 0-.055-.008-.06-.017-.012-.02-.42-.124-.513-.13a.462.462 0 01-.112-.021.445.445 0 00-.14-.01.709.709 0 01-.146-.004 3.054 3.054 0 00-.545.025.454.454 0 01-.112.01.073.073 0 00-.042.004.133.133 0 01-.058.004.246.246 0 00-.086.01.463.463 0 01-.089.02.99.99 0 00-.296.082c-.026.016-.053.026-.061.022-.008-.005-.029 0-.046.01-.018.01-.041.016-.052.013a.636.636 0 00-.17.074 1.463 1.463 0 01-.203.095.478.478 0 00-.133.07c-.067.047-.08.053-.11.044-.039-.014-.032-.002-.307-.487-.134-.236-.217-.391-.212-.4a.98.98 0 01.134-.09c.07-.044.152-.1.18-.127a.246.246 0 01.075-.051 1.22 1.22 0 00.24-.184.464.464 0 01.084-.068.387.387 0 00.093-.092.735.735 0 01.13-.163.262.262 0 00.051-.062.12.12 0 01.029-.038.141.141 0 00.03-.05.56.56 0 01.09-.116.516.516 0 00.08-.1.771.771 0 01.073-.11.703.703 0 00.081-.135c.01-.027.026-.054.036-.06.017-.009.049-.075.093-.19a.151.151 0 01.028-.052c.006-.003.017-.03.024-.06.007-.03.018-.057.024-.061.03-.017.145-.405.187-.63.006-.038.02-.095.029-.126a.491.491 0 00.013-.134.574.574 0 01.006-.123c.005-.026.003-.058-.005-.072a.055.055 0 01.002-.051c.008-.014.01-.035.003-.047a.333.333 0 01-.004-.115.44.44 0 000-.106 1.355 1.355 0 01-.024-.203.592.592 0 00-.03-.195.389.389 0 01-.024-.098.585.585 0 00-.042-.137.354.354 0 01-.033-.11c.003-.012-.005-.037-.016-.058a.51.51 0 01-.038-.12.292.292 0 00-.039-.106.392.392 0 01-.05-.1c-.058-.16-.253-.458-.347-.532a.52.52 0 01-.09-.118.317.317 0 00-.113-.13.372.372 0 01-.071-.057c-.005-.008-.02-.017-.032-.02a.112.112 0 01-.05-.034.67.67 0 00-.14-.086 5.422 5.422 0 01-.137-.07 1.044 1.044 0 00-.099-.04.44.44 0 01-.112-.06c-.034-.03-.269-.09-.295-.075-.006.004-.022.002-.035-.003-.014-.005-.032-.005-.04 0a.336.336 0 01-.1.005c-.132-.008-.22.01-.543.105a1.706 1.706 0 00-.453.254.764.764 0 01-.102.081c-.018.01-.034.028-.036.042a.068.068 0 01-.03.04c-.015.009-.028.023-.028.032 0 .008-.012.022-.026.03a.894.894 0 00-.167.194 3.422 3.422 0 01-.055.092c-.037.06-.124.405-.135.534-.015.168-.014.262.004.307.01.025.02.069.023.098.006.057.03.141.053.19a.114.114 0 01.012.056c-.003.019.005.035.03.058.017.018.032.04.032.049 0 .026.104.215.12.216.009 0 .022.013.031.028a.07.07 0 00.041.032c.015.002.03.012.036.02.005.01.06.05.12.09.092.06.136.078.257.105.08.018.167.04.192.046a.26.26 0 00.095.006 3.59 3.59 0 01.142-.022c.02-.002.07-.012.11-.022.072-.017.082-.023.182-.11a.934.934 0 00.146-.158.764.764 0 00.102-.325 1.27 1.27 0 01.01-.113.33.33 0 00-.003-.085.664.664 0 01-.006-.112c.003-.058-.002-.071-.092-.228l-.095-.167-.1-.051c-.123-.063-.253-.098-.313-.085-.05.01-.085-.017-.059-.047a.453.453 0 00.04-.055c.029-.048.143-.13.164-.118.009.005.032 0 .051-.012a.28.28 0 01.096-.025 8.1 8.1 0 00.13-.012c.1-.01.4.089.432.143a.24.24 0 00.058.04c.081.044.208.153.272.233.106.133.272.45.3.575l.029.124c.01.046.018.105.017.131a1.332 1.332 0 000 .204c.004.04-.004.133-.016.204l-.029.178a.28.28 0 01-.024.076c-.009.016-.033.088-.053.16-.034.12-.076.22-.149.352-.043.08-.06.106-.073.113a.434.434 0 00-.055.072 1.3 1.3 0 01-.1.129.304.304 0 00-.062.09c-.003.015-.023.035-.053.051a.504.504 0 00-.092.07 2.732 2.732 0 01-.09.084 1.514 1.514 0 00-.093.093.626.626 0 01-.283.146.318.318 0 00-.08.025c-.024.014-.057.018-.197.026a.98.98 0 01-.307.031.168.168 0 00-.058-.005l-.088.003a.674.674 0 01-.12-.014 2.54 2.54 0 00-.122-.021 2.643 2.643 0 01-.399-.132.993.993 0 01-.146-.083c-.035-.025-.072-.045-.082-.043-.01.002-.034-.015-.051-.037a.75.75 0 00-.09-.086c-.031-.026-.086-.07-.12-.1-.113-.093-.35-.442-.335-.495.003-.012-.002-.036-.012-.053a.12.12 0 01-.014-.063.101.101 0 00-.005-.048c-.026-.048-.018-.212.015-.337a.586.586 0 00.03-.148c-.017-.028-.072-.035-.11-.013a.656.656 0 01-.103.043c-.128.04-.329.253-.363.384-.008.03-.02.058-.029.063-.018.01-.04.13-.035.194.002.025-.003.053-.01.062-.02.025.002.278.028.324.05.087.036.14-.04.142-.014 0-.07.02-.124.042-.105.044-.13.07-.146.144-.007.034-.004.041.033.072.022.02.057.042.078.05a.12.12 0 01.05.039.129.129 0 00.035.036c.052.033.107.102.187.232.079.128.2.279.256.322l.061.05c.074.065.265.19.285.186.011-.001.024.004.028.011a.486.486 0 00.12.053c.062.021.15.054.198.074.048.02.115.039.15.043a.194.194 0 01.084.027c.012.01.042.017.068.016a.589.589 0 01.124.016c.043.01.099.015.126.011.05-.006.101.016.1.044 0 .021-.16.094-.211.095a.155.155 0 00-.058.013.119.119 0 01-.06.004.219.219 0 00-.076.003c-.035.01-.386-.077-.455-.112a.286.286 0 00-.098-.023.536.536 0 01-.148-.041 1.4 1.4 0 00-.13-.05c-.022-.006-.044-.017-.048-.024a.349.349 0 00-.078-.049c-.126-.064-.172-.09-.179-.103a.157.157 0 00-.056-.03c-.027-.01-.053-.026-.057-.034-.005-.008-.02-.017-.035-.02a.063.063 0 01-.038-.026.184.184 0 00-.058-.047.193.193 0 01-.053-.04.44.44 0 00-.072-.06.632.632 0 01-.099-.088.226.226 0 00-.05-.05c-.016-.006-.032-.022-.128-.137-.135-.16-.177-.218-.22-.303a1.368 1.368 0 00-.072-.115 1.246 1.246 0 01-.155-.388 1.995 1.995 0 01-.027-.332.174.174 0 00-.008-.058.088.088 0 01.004-.062c.01-.014.012-.033.006-.043a.255.255 0 01-.014-.077c-.005-.097-.1-.24-.165-.25a.315.315 0 00-.107.016c-.073.023-.127.021-.142-.004-.007-.013.016-.104.114-.437.04-.14.065-.294.05-.32a.187.187 0 01-.01-.055 1.688 1.688 0 00-.01-.1 1.643 1.643 0 01-.01-.104.79.79 0 00-.09-.215c-.08-.154-.087-.175-.087-.24 0-.082-.016-.117-.058-.125-.045-.01-.141.018-.224.064-.1.055-.112.048-.12-.066a.403.403 0 00-.03-.134.49.49 0 01-.04-.104 2.679 2.679 0 00-.048-.163 5.55 5.55 0 01-.056-.18l-.057-.19a.471.471 0 01-.027-.141c.003-.018.003-.039-.001-.046a.459.459 0 01.036-.13c.032-.084.04-.127.03-.15-.019-.043-.05-.042-.172.008a6.623 6.623 0 01-.175.069.505.505 0 00-.188.127.946.946 0 00-.117.115.422.422 0 01-.064.074 1.22 1.22 0 00-.214.324.932.932 0 01-.061.123.473.473 0 00-.072.228c.001.031-.006.055-.02.063a.039.039 0 00-.02.038.445.445 0 01-.005.096.278.278 0 00-.004.082c.003.006-.003.03-.013.055l-.02.045-.063-.021a.982.982 0 00-.18-.03c-.1-.008-.118-.006-.126.016-.006.017 0 .038.016.06a.492.492 0 01.034.239.292.292 0 00.008.081c.008.03.015.082.017.116l.006.086c0 .015.005.033.01.041.005.009.01.032.01.053.001.021.01.073.018.115a.696.696 0 00.058.21c.018.041.032.082.03.091-.002.018.02.088.083.266.044.124.025.088.228.424.09.15.18.285.197.3a.728.728 0 01.085.108 1.143 1.143 0 00.21.239c.012.01.034.032.049.05.066.08.161.182.182.195.026.017.164.148.199.19.027.032.017.06-.021.054-.068-.012-.42-.24-.5-.325a.196.196 0 00-.06-.047c-.007 0-.021-.014-.03-.03a.512.512 0 00-.078-.083 1.016 1.016 0 01-.1-.103.296.296 0 00-.065-.063.326.326 0 01-.07-.07c-.024-.029-.07-.08-.105-.111a1.6 1.6 0 01-.129-.145 9.376 9.376 0 00-.133-.165c-.097-.116-.455-.767-.447-.812a.303.303 0 00-.035-.101 1.103 1.103 0 01-.053-.132 3.824 3.824 0 00-.04-.126.593.593 0 01-.027-.125.614.614 0 00-.03-.131 2.091 2.091 0 01-.083-.398 1.334 1.334 0 00-.02-.262c-.004-.008-.001-.038.007-.067.008-.03.011-.061.006-.07a.146.146 0 01-.007-.06 2.57 2.57 0 000-.207.751.751 0 00-.162-.47.26.26 0 01-.062-.133c-.005-.033-.016-.066-.025-.073-.024-.02-.133.015-.242.077l-.098.056-.06-.11c-.055-.104-.065-.116-.217-.25-.136-.12-.16-.147-.174-.19-.014-.048-.079-.13-.11-.14-.015-.005-.095.068-.138.125a.23.23 0 01-.039.044c-.007.004-.012.021-.011.038 0 .017-.005.034-.012.038a.372.372 0 00-.044.099c-.03.087-.033.091-.06.079a.188.188 0 01-.06-.067.698.698 0 00-.09-.114.81.81 0 01-.144-.228 5.902 5.902 0 00-.104-.198c-.01-.016-.017-.037-.015-.047a.414.414 0 00-.025-.095.79.79 0 01-.058-.307.298.298 0 00-.005-.097.2.2 0 010-.083c.01-.078-.014-.12-.063-.107a.554.554 0 00-.237.154c-.064.09-.111.097-.155.021-.01-.016-.024-.03-.033-.03-.008 0-.027-.02-.041-.045-.015-.026-.037-.047-.052-.05a.061.061 0 01-.037-.024c-.006-.011-.018-.022-.025-.024-.008-.002-.024-.02-.037-.04a.873.873 0 00-.198-.178 1.059 1.059 0 01-.19-.178.586.586 0 00-.125-.098.433.433 0 01-.098-.07.184.184 0 00-.043-.04 8.687 8.687 0 01-.49-.32.956.956 0 00-.157-.096.06.06 0 01-.037-.024.407.407 0 00-.12-.061.598.598 0 01-.114-.051 1.699 1.699 0 00-.209-.076c-.22-.07-.291-.098-.302-.117-.004-.007-.017-.012-.029-.012a.341.341 0 01-.082-.024c-.075-.03-.384-.087-.407-.074-.009.006-.03.003-.045-.006a.947.947 0 00-.312-.038c-.01.007-.026.009-.034.005-.023-.013-.093.035-.1.069a.462.462 0 00.005.197c.014.038.023.042.115.054.055.008.114.01.132.007a.542.542 0 01.195.021.609.609 0 00.125.024c.123.016.546.127.557.145.003.006.027.01.052.008a.15.15 0 01.083.027.4.4 0 00.108.05.617.617 0 01.095.034c.012.007.066.031.119.053a.757.757 0 01.1.046.76.76 0 00.103.046.422.422 0 01.108.054.494.494 0 00.106.064.467.467 0 01.107.066c.006.01.03.024.054.032a.402.402 0 01.096.055.418.418 0 00.085.052.196.196 0 01.064.047.71.71 0 00.104.084c.04.027.08.06.088.074a.241.241 0 00.06.056.812.812 0 01.091.075 2.166 2.166 0 01.265.268.25.25 0 00.06.053.715.715 0 01.142.149c.04.049.025.075-.045.08a.916.916 0 00-.156.04c-.217.072-.318.188-.298.342.007.054.026.058.105.018a.778.778 0 01.105-.043c.069-.02.432.043.452.077a.207.207 0 00.064.037.765.765 0 01.101.054.577.577 0 00.136.075c.017.006.04.025.05.042.01.018.046.05.08.073.035.023.067.05.073.059.005.01.037.035.07.056.07.044.085.064.066.088-.018.022-.08.009-.096-.021-.008-.013-.035-.031-.063-.041-.026-.01-.054-.028-.06-.039-.007-.011-.04-.027-.075-.037-.035-.009-.067-.023-.072-.031a.836.836 0 00-.179-.063 3.483 3.483 0 01-.243-.076.395.395 0 00-.131-.027.177.177 0 01-.09-.02c-.018-.013-.04-.019-.05-.014-.008.005-.046 0-.084-.01a1.967 1.967 0 00-.336-.06.384.384 0 01-.1-.01c-.095-.02-.3-.024-.328-.009a.114.114 0 01-.056.004.239.239 0 00-.074.002 1.302 1.302 0 01-.129.015.94.94 0 00-.135.019c-.022.006-.084.02-.138.029a1.293 1.293 0 00-.408.154c-.18.095-.212.136-.13.163.022.008.049.002.083-.018a.162.162 0 01.103-.024.778.778 0 00.133-.002c.096-.01.244-.002.343.018.04.008.112.02.16.026.108.015.264.06.276.08.004.007.033.013.064.012a.32.32 0 01.13.035c.041.02.08.033.087.03.007-.005.039.001.07.012.032.012.098.034.148.05.049.017.1.042.114.057a.378.378 0 00.16.076c.034.004.205.087.312.151l.117.07a1 1 0 01.216.152c.008.014.029.03.045.038a.104.104 0 01.043.035c.007.013.035.031.062.041.027.01.053.026.059.035.005.01.057.062.114.117.058.055.146.142.197.194.05.051.1.097.109.101.01.004.04.04.07.082a.49.49 0 00.075.09c.032.02.12.122.12.138 0 .008.017.027.039.043.033.026.12.132.215.264a2.516 2.516 0 01.202.259c.054.076.114.155.132.174.019.02.074.086.123.148.146.185.178.22.233.256.03.02.055.045.057.056.004.021-.046.057-.066.046-.007-.004-.028-.001-.048.005-.02.007-.072.02-.118.027-.102.019-.258.104-.264.145a.04.04 0 01-.03.032c-.017.003-.037.025-.053.058a.65.65 0 01-.045.078.336.336 0 00-.03.111.244.244 0 00.025.169.34.34 0 00.078.119c.065.058.07.058.121-.007.043-.053.056-.062.153-.101a.48.48 0 01.123-.038c.01.002.026 0 .038-.007.022-.013.152.013.367.074.137.04.342.146.37.194.005.01.023.018.038.018s.052.02.08.044c.029.025.062.05.073.056a5.177 5.177 0 01.42.297.981.981 0 00.207.178c.027.02.071.06.1.092.068.075.26.246.326.291.05.035.053.039.045.069-.007.03-.01.031-.057.033-.066.003-.272.092-.38.165-.077.052-.089.066-.107.119a.19.19 0 01-.033.068.211.211 0 00-.034.076.31.31 0 00.003.171.408.408 0 00.033.11.81.81 0 01.074.086.328.328 0 00.097.09.395.395 0 01.075.04c.078.051.16.021.153-.058-.007-.098.008-.14.078-.213.14-.146.248-.17.568-.127a.343.343 0 01.102.023c.003.005.024.01.047.009.088-.003.44.103.49.146.019.017.039.027.044.024.006-.003.034.007.063.022.03.016.178.064.33.106.152.043.318.094.37.115.051.02.17.055.265.078s.238.06.319.083c.236.065.624.131.66.111.016-.009.093-.004.237.015.051.007.098.01.103.007a.453.453 0 01.104.008c.05.008.147.012.213.009.223-.01.403-.026.42-.036a.26.26 0 01.075-.014.454.454 0 00.107-.023.17.17 0 01.079-.012.08.08 0 00.048-.004c.031-.018.056.003.134.118.139.202.388.617.387.644 0 .01.015.032.035.05a.115.115 0 01.042.072c.004.023.041.101.083.174l.076.131-.031.066a.256.256 0 01-.048.075.11.11 0 00-.031.032 1.2 1.2 0 01-.086.097c-.04.042-.084.093-.1.115a.228.228 0 01-.043.047c-.009.005-.019.024-.022.043a.137.137 0 01-.034.06c-.027.025-.12.184-.149.252a.603.603 0 01-.045.083.885.885 0 00-.064.138.373.373 0 01-.05.104c-.008.004-.016.02-.018.033a.481.481 0 01-.046.098.839.839 0 00-.063.136.305.305 0 01-.04.085.467.467 0 00-.048.116 3.901 3.901 0 01-.046.14 1.86 1.86 0 00-.042.154c-.014.059-.05.193-.078.298-.079.29-.087.325-.082.378.002.027-.003.053-.012.058-.009.005-.019.03-.022.056-.004.025-.02.108-.038.184-.057.258-.087.426-.078.442.006.01-.057.327-.07.35a.388.388 0 00-.021.06c-.04.144-.1.315-.123.351-.014.023-.025.052-.023.064.002.012-.007.028-.02.036a.208.208 0 00-.047.045l-.042.054a.43.43 0 01-.176.113c-.117.025-.168.021-.246-.019-.08-.04-.11-.038-.13.01a.51.51 0 00-.016.204.514.514 0 01.027.09.24.24 0 00.067.125l.079.093c.048.06.193.088.332.062.082-.015.103-.025.237-.111.121-.078.154-.104.181-.148.027-.042.038-.052.059-.048.035.006.05.037.043.089a.136.136 0 00.011.072c.01.017.014.036.01.044s.001.029.012.047c.01.017.017.037.015.044-.004.017.035.194.056.252a.2.2 0 01.014.078.201.201 0 00.014.078c.01.029.02.059.019.067 0 .008.012.082.028.163.034.175.042.25.036.32-.003.029 0 .06.005.07.005.009.007.036.004.06a.161.161 0 00-.002.05c.002.004.012.099.021.211.012.146.011.237-.004.32-.028.15-.044.214-.055.22-.005.003-.015.026-.021.052a.515.515 0 01-.06.167.229.229 0 00-.04.044.713.713 0 01-.15.145.24.24 0 01-.088.019c-.078.004-.082.007-.078.064a.28.28 0 00.074.175l.06.06c.027.031.137.075.156.063a.167.167 0 01.064 0c.08.009.117.002.217-.04.094-.038.21-.117.224-.154a.337.337 0 01.053-.065.205.205 0 00.05-.07c.005-.032.032-.046.053-.03a.2.2 0 01.03.08c.036.163.067.266.111.371.027.063.051.13.055.149.006.035.057.15.121.274.02.036.041.09.049.12s.043.12.079.198c.035.078.07.174.076.212.007.039.018.073.024.077.014.007.051.117.065.187a.884.884 0 00.049.134c.022.05.038.1.035.112-.003.01.002.031.01.046.009.015.02.05.026.08.005.03.02.097.031.15.012.054.023.11.023.124 0 .015.008.037.015.05a.46.46 0 01.022.116c.006.051.017.127.027.17.009.041.018.1.02.129.001.029.006.083.01.12a.952.952 0 01.004.114 1.606 1.606 0 000 .125c.002.042.001.1-.002.13a.265.265 0 00-.003.059.713.713 0 01-.02.104.764.764 0 00-.019.188.5.5 0 01-.015.153c-.012.036-.017.071-.013.08.005.007-.004.045-.02.083a.28.28 0 00-.025.077c.006.011-.112.487-.123.494-.005.003-.014.022-.02.043a.68.68 0 01-.063.161.48.48 0 00-.041.1.457.457 0 01-.072.136c-.023.023-.04.056-.04.072.001.017-.008.036-.019.042a.264.264 0 00-.055.063.265.265 0 01-.064.069c-.065.038-.072.092-.013.104.031.006.115-.04.294-.164a1.63 1.63 0 00.463-.505l.106-.163c.038-.058.078-.132.09-.163.011-.03.03-.062.042-.068a.036.036 0 00.017-.034.271.271 0 01.033-.096 2.5 2.5 0 00.098-.27c.033-.11.072-.228.086-.265.035-.094.131-.488.13-.533-.007-.181.006-.315.03-.33.032-.018.054.007.058.063a.21.21 0 00.018.073c.008.014.012.05.009.082a.176.176 0 00.01.086c.01.017.018.048.018.07 0 .02.002.053.004.072.002.018-.002.036-.009.04-.007.004-.01.032-.006.063.003.03.003.079 0 .107a.183.183 0 00.002.063c.007.012-.065.277-.078.284a.151.151 0 00-.021.048c-.015.048-.047.087-.139.172-.032.03-.057.063-.055.073.004.028.133.089.178.084a.465.465 0 00.247-.13c.115-.1.155-.143.167-.179.005-.015.017-.028.026-.028.021.001.058.064.048.083-.004.007.002.028.012.047.01.018.022.062.026.097a.31.31 0 00.025.097c.03.052.098.33.109.442a.738.738 0 00.03.155.48.48 0 01.025.114.28.28 0 00.018.085c.007.013.01.051.008.086a.842.842 0 00.003.125.484.484 0 01-.001.11.224.224 0 00.005.089.375.375 0 010 .124.805.805 0 00-.005.146.873.873 0 01-.018.256c-.006.01-.008.024-.004.031.009.015-.004.117-.032.258a.478.478 0 00-.014.115c.005.01-.01.069-.063.251l-.054.212c-.06.235-.15.475-.197.528a.251.251 0 00-.047.078 1.12 1.12 0 01-.028.08c-.016.042-.015.047.022.088.042.045.184.117.206.104a.65.65 0 00.064-.059c.05-.05.08-.11.132-.27a.332.332 0 01.039-.088c.013-.008.088-.233.119-.358.012-.05.028-.145.035-.21.008-.064.021-.142.03-.173a1.855 1.855 0 00.06-.38c.012-.038.021-.186.015-.24a3.694 3.694 0 00-.013-.33 2.74 2.74 0 01-.01-.215.255.255 0 00-.012-.084.28.28 0 01-.006-.108.204.204 0 000-.081.477.477 0 01-.017-.106.921.921 0 00-.027-.157.371.371 0 01-.017-.084.235.235 0 00-.018-.071c-.012-.03-.017-.064-.013-.077a.06.06 0 00-.004-.043c-.007-.012-.01-.027-.006-.033a.436.436 0 00-.026-.115 2.441 2.441 0 01-.045-.163.409.409 0 00-.023-.076 1.263 1.263 0 01-.054-.249.35.35 0 01.091-.034c.1-.029.283-.133.296-.169.013-.037-.011-.065-.071-.081a.645.645 0 01-.153-.09l-.136-.1a.23.23 0 01-.046-.044.23.23 0 00-.056-.046.655.655 0 01-.117-.12c-.075-.096-.263-.421-.26-.45a.58.58 0 00-.04-.157c-.022-.05.012-.062.135-.049a.76.76 0 00.27-.004c.063-.012.065-.014.077-.054.01-.037.007-.047-.045-.123a.292.292 0 01-.053-.105.491.491 0 00-.014-.098 2.16 2.16 0 01-.02-.105 1.398 1.398 0 00-.132-.327l-.045-.07.096-.06c.053-.033.111-.07.13-.084.043-.031.06-.076.035-.094a1.71 1.71 0 01-.127-.194c-.144-.244-.26-.355-.434-.422a.434.434 0 01-.11-.06.383.383 0 00-.087-.055.166.166 0 01-.062-.04.442.442 0 00-.156-.095.286.286 0 01-.087-.06.606.606 0 00-.085-.071.66.66 0 01-.1-.09.392.392 0 00-.072-.068c-.01-.003-.023-.018-.032-.032a.446.446 0 00-.073-.076 1.369 1.369 0 01-.232-.254 1.673 1.673 0 00-.117-.152 4.117 4.117 0 01-.401-.636 5.22 5.22 0 01-.111-.316.583.583 0 00-.042-.098.195.195 0 01-.025-.068.987.987 0 00-.046-.148 1.646 1.646 0 01-.087-.297 2.213 2.213 0 01-.084-.391.11.11 0 00-.01-.042c-.023-.04-.02-.448.004-.515.005-.015.015-.023.026-.02.02.005.035.065.043.159.002.032.009.066.015.077.012.023.05.205.046.222-.002.006.006.026.016.045a.27.27 0 01.026.082.56.56 0 00.035.116c.016.037.031.08.033.097.01.066.028.133.038.138a.437.437 0 01.047.094c.066.16.08.189.107.234.014.025.025.055.023.066-.002.013.013.042.043.079a.248.248 0 01.049.08c.002.028.162.298.211.356.02.023.078.084.129.136.051.053.116.124.143.16a.944.944 0 00.228.213c.013.01.044.038.069.062a.31.31 0 00.078.057.319.319 0 01.078.056.324.324 0 00.062.05.063.063 0 01.028.025.06.06 0 00.037.024.06.06 0 01.037.025.059.059 0 00.036.025c.013.002.04.024.059.048.046.057.08.077.103.063a.497.497 0 00.095-.178c.005-.021.016-.042.023-.047.008-.004.011-.023.008-.043-.01-.065.027-.066.159-.005.117.055.367.123.44.12a.665.665 0 01.145.012c.04.009.087.013.105.009a.285.285 0 01.073-.004.249.249 0 00.082-.01.123.123 0 01.065-.003c.013.005.037 0 .053-.008a.096.096 0 01.057-.012c.026.005.11-.02.268-.083a.566.566 0 00.13-.075.28.28 0 01.075-.049.744.744 0 00.192-.155c.004-.012-.003-.038-.015-.06-.02-.033-.03-.037-.085-.034a.518.518 0 01-.306-.123c-.019-.023-.04-.042-.048-.042s-.025-.018-.037-.039c-.012-.02-.03-.04-.038-.043a1.49 1.49 0 01-.19-.203 9.942 9.942 0 00-.103-.128 1.158 1.158 0 00-.178-.175c-.036-.029-.063-.057-.06-.064a.837.837 0 01.081-.078c.144-.13.164-.15.168-.167.005-.018-.05-.07-.094-.087-.023-.009-.048-.042-.204-.273-.065-.096-.093-.123-.16-.157a.287.287 0 01-.07-.055.274.274 0 00-.08-.056.167.167 0 01-.056-.034.46.46 0 00-.119-.046.618.618 0 01-.116-.042c-.003-.005-.016-.006-.03-.004a.458.458 0 01-.118-.018.433.433 0 00-.104-.019.23.23 0 01-.078-.024.285.285 0 00-.087-.027c-.027.004-.049-.04-.032-.067a.453.453 0 01.08-.072c.088-.065.094-.105.035-.217a.372.372 0 00-.152-.17 2.2 2.2 0 01-.096-.072.206.206 0 00-.07-.037c-.018-.004-.037-.014-.041-.021a.222.222 0 00-.064-.042.707.707 0 01-.196-.169.073.073 0 00-.036-.03c-.053-.015-.3-.398-.32-.498a.197.197 0 00-.035-.079.902.902 0 01-.085-.248.21.21 0 00-.021-.06c-.009-.016-.012-.038-.008-.05.005-.013-.005-.054-.02-.092-.017-.038-.027-.075-.023-.082.004-.007 0-.025-.01-.04-.008-.016-.012-.034-.009-.04.004-.008 0-.031-.007-.053a.217.217 0 01-.008-.084.136.136 0 000-.055.336.336 0 010-.092.584.584 0 00-.005-.148.493.493 0 01-.01-.11.15.15 0 00-.004-.055c-.003-.006-.001-.026.005-.045.006-.02.007-.04.003-.048-.009-.015.046-.28.115-.558.056-.23.105-.335.201-.44.057-.064.194-.16.212-.15.02.01.006.094-.017.108a.253.253 0 00-.05.087c-.04.104-.133.45-.142.532a2.51 2.51 0 01-.03.18.522.522 0 00-.017.126.173.173 0 01.001.064c-.003.028.001.09.009.137.008.047.017.109.02.137a.916.916 0 00.055.172l.09.219a.49.49 0 00.051.105.37.37 0 01.04.097c.017.05.042.13.056.176a.327.327 0 01.018.125c-.013.06.024.1.09.102.07 0 .202-.074.247-.14.044-.066.07-.07.107-.016.017.025.04.048.05.052.012.004.023.02.027.034a.041.041 0 00.032.031c.014.003.03.011.034.019a.377.377 0 00.132.087.405.405 0 01.091.047c.105.068.322.093.49.056.135-.03.305-.11.316-.151.003-.01.021-.027.041-.039.073-.042.041-.117-.053-.129-.084-.01-.277-.09-.312-.13a.612.612 0 00-.067-.062 6.194 6.194 0 01-.073-.06c-.079-.063-.278-.456-.274-.538a.138.138 0 00-.012-.063.295.295 0 01-.02-.087 1.457 1.457 0 00-.02-.13 1.335 1.335 0 01-.007-.413c.009-.152.163-.643.212-.671a.12.12 0 00.03-.048.489.489 0 01.059-.095c.024-.03.06-.084.082-.119a.304.304 0 01.06-.075.176.176 0 00.043-.047 1.18 1.18 0 01.205-.194.722.722 0 01.203-.115c.072-.03.145-.058.16-.06.068-.012.169-.037.216-.054a.622.622 0 01.131-.026 16.496 16.496 0 00.335-.033.611.611 0 01.184.011c.177.025.313.05.317.058a.732.732 0 00.135.032c.12.022.206.056.345.137.03.017.084.044.12.058a.623.623 0 01.196.14.127.127 0 00.043.033.44.44 0 01.094.1.584.584 0 00.077.092c.015.008.118.161.167.247.07.122.087.162.093.205a.259.259 0 00.023.078c.01.016.013.039.008.052-.004.013 0 .046.01.073.011.028.017.069.014.09a.218.218 0 00.005.076.302.302 0 01-.003.104.41.41 0 00-.007.098.808.808 0 01-.086.272.226.226 0 00-.045.06c-.066.114-.276.257-.363.247-.026-.003-.031-.009-.035-.042-.002-.021.003-.042.01-.046a.254.254 0 00.04-.079c.062-.17.041-.323-.073-.521l-.074-.13-.132-.088c-.267-.18-.506-.225-.728-.14-.12.046-.197.093-.212.13a.116.116 0 01-.041.047.183.183 0 00-.054.062.182.182 0 01-.04.054c-.039.022-.175.434-.155.468.006.01.009.047.006.081a.354.354 0 00.027.19.11.11 0 01.011.065c-.005.025.004.052.033.1a34.495 34.495 0 00.106.176c.037.062.1.137.147.173.013.01.033.03.046.044.101.115.198.19.308.24l.142.063c.077.035.277.092.375.107.067.01.37-.005.396-.02a.666.666 0 01.162-.035c.176-.019.594-.276.75-.46a.456.456 0 01.08-.078zM14.124 47.678c-.036-.048-.102-.082-.13-.066-.007.005-.024.004-.036 0-.025-.01-.106.038-.153.089-.042.045-.043.133-.004.2.03.052.04.06.104.078.065.018.076.017.133-.017.08-.047.106-.085.116-.168.007-.06.004-.073-.03-.116z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M22.778 42.572c.03.004.06.004.068 0a.446.446 0 01.076-.02c.14-.027.279-.145.293-.249a.137.137 0 00-.007-.068c-.018-.033-.074-.043-.128-.025a.386.386 0 01-.12.013 1.377 1.377 0 01-.397-.116 1.269 1.269 0 01-.181-.132.359.359 0 00-.076-.05c-.078-.043-.117-.077-.253-.217a5.138 5.138 0 00-.148-.148.667.667 0 01-.098-.129.443.443 0 00-.068-.095.45.45 0 01-.066-.113c-.138-.3-.154-.33-.187-.333-.08-.01-.117.067-.086.179.03.106.084.237.11.265.016.016.03.035.034.042l.171.323c.091.171.18.346.196.388.036.093.1.31.1.341 0 .013.002.04.005.06.003.02.005.047.004.06-.001.014.003.092.01.174a.852.852 0 010 .187c-.006.02-.006.046 0 .057.014.024.098.036.128.019a.264.264 0 01.066-.02c.035-.006.05-.015.065-.036a.43.43 0 01.077-.074.968.968 0 00.195-.26c.008-.03.043-.041.096-.032a.19.19 0 00.059.006.221.221 0 01.062.003zM5.498 41.26c.01-.018-.1-.19-.132-.21a.138.138 0 01-.04-.037c-.022-.039-.118-.067-.2-.058-.112.011-.316.087-.592.22a.622.622 0 01-.12.045 1.15 1.15 0 00-.116.03.424.424 0 01-.13.02.205.205 0 00-.054-.001.834.834 0 01-.22-.02c-.025-.008-.052-.011-.06-.007-.007.005-.024.004-.038-.001-.013-.005-.042 0-.063.013-.032.019-.038.03-.034.074.004.046.013.063.078.147a.75.75 0 00.121.126.246.246 0 01.06.053c.006.011.04.028.075.037.035.01.066.022.07.028a.401.401 0 00.106.038.414.414 0 01.106.037.656.656 0 01-.017.137 1.48 1.48 0 00-.03.217.1.1 0 00.009.06.095.095 0 01.01.057c-.014.063.095.297.155.334.05.032.087-.014.143-.172a.426.426 0 01.051-.114c.009-.005.017-.02.02-.033.011-.073.185-.265.348-.385.234-.174.277-.206.314-.236.021-.018.04-.039.04-.047 0-.007.01-.02.023-.027a.43.43 0 00.07-.066c.05-.057.073-.148.053-.211-.006-.02-.01-.043-.006-.049zM5.585 40.762c.012-.007.032-.003.148.028.062.016.131.084.144.141a.837.837 0 00.021.077.12.12 0 01.003.066.741.741 0 01-.069.16c-.008.01-.01.03-.001.044.02.037.223.018.272-.024a.97.97 0 00.166-.194.756.756 0 00.045-.243.44.44 0 00-.055-.127c-.066-.117-.106-.147-.261-.194-.09-.028-.12-.03-.187-.013a5.307 5.307 0 01-.12.03c-.05.01-.11.07-.14.138a.178.178 0 01-.033.056c-.006.003-.011.014-.012.023 0 .019.06.043.079.032zM8.498 48.365a.146.146 0 00-.016-.065.154.154 0 01-.019-.056 1.984 1.984 0 00-.06-.267.078.078 0 01-.005-.043.437.437 0 00-.012-.104.635.635 0 01-.014-.116c.003-.069 0-.112-.01-.13-.019-.03.046-.408.072-.423a.212.212 0 00.039-.061.192.192 0 01.064-.077.081.081 0 00.045-.067.138.138 0 000-.057.225.225 0 00-.08-.03.18.18 0 00-.134.008c-.034.014-.068.023-.074.019-.016-.009-.077.027-.095.055a.84.84 0 00-.158.229.646.646 0 01-.072.125.458.458 0 01-.121.001.616.616 0 00-.338.066c-.088.043-.13.084-.15.15-.016.048-.006.066.044.078a.364.364 0 01.09.041c.116.076.19.12.212.129.013.005.05.034.08.063l.139.131c.11.105.222.264.437.624.115.192.21.339.26.401.128.157.215.186.24.08.009-.041.006-.047-.06-.134-.13-.169-.306-.5-.304-.57zM4.515 43.322a2.041 2.041 0 00-.033-.231 1.03 1.03 0 00-.054-.11c-.043-.077-.057-.093-.103-.116a.305.305 0 01-.058-.035.721.721 0 00-.192-.084c-.02.012-.065.217-.061.284.005.083.097.301.14.333.019.013.028.029.029.047 0 .02.008.03.029.037a.422.422 0 01.072.039c.047.031.139.061.156.05.006-.003.022-.001.036.004.033.012.07-.01.063-.04a5.35 5.35 0 01-.024-.178zM4.337 44.09a.712.712 0 00-.057-.154 7.306 7.306 0 01-.084-.12c-.064-.092-.107-.13-.168-.143a.268.268 0 01-.073-.032c-.054-.035-.08-.004-.089.111a.314.314 0 00.02.16c.014.034.023.07.02.08-.002.011.006.037.018.058a.227.227 0 01.026.074c.007.07.26.268.397.31.028.01.05.006.074-.011l.034-.025-.042-.093a1.778 1.778 0 01-.076-.215zM12.114 43.065l.038.125c.024.08.09.181.136.214a.245.245 0 01.06.054.062.062 0 00.037.027.084.084 0 01.042.027c.012.014.032.019.056.013a.392.392 0 00.178-.16.437.437 0 01.046-.071c.037-.041.055-.15.044-.27-.005-.051-.014-.073-.124-.293a.698.698 0 01-.054-.124.712.712 0 00-.059-.127.637.637 0 01-.06-.14c-.002-.015-.004-.062-.006-.104-.005-.089-.004-.087-.033-.095-.029-.008-.056.009-.085.052-.012.02-.036.054-.052.077a.862.862 0 00-.051.085.18.18 0 01-.037.053c-.009.005-.023.045-.03.088a.394.394 0 01-.038.112.123.123 0 00-.02.064c.002.027-.002.13-.01.266a.481.481 0 00.022.127z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M4.236 45.181a1.258 1.258 0 00-.022-.135 1.8 1.8 0 01-.02-.106c-.012-.085-.105-.28-.135-.282-.009 0-.02-.009-.026-.019-.006-.01-.037-.027-.069-.038-.032-.011-.063-.03-.07-.04a.117.117 0 00-.044-.037c-.027-.013-.035-.025-.047-.074a.866.866 0 00-.02-.07.983.983 0 01-.038-.163.12.12 0 00-.012-.044.303.303 0 01-.018-.08 26.426 26.426 0 00-.024-.209.848.848 0 01-.007-.191 1.15 1.15 0 00.017-.145c.01-.161.02-.255.04-.343a.386.386 0 00.012-.09c-.01-.02.165-.632.194-.678a.465.465 0 00.045-.096c.007-.025.007-.053 0-.062-.02-.022-.093.013-.105.05a.391.391 0 01-.048.081.298.298 0 00-.046.09c-.004.021-.015.042-.023.047-.009.006-.015.02-.013.032s-.007.04-.021.061a.338.338 0 00-.035.076l-.057.209a4.406 4.406 0 00-.064.263c-.02.112-.05.132-.1.067l-.032-.044-.092.049c-.09.047-.233.175-.246.218-.002.01-.015.023-.028.03-.031.019-.1.226-.087.26a.118.118 0 01.005.054.168.168 0 00.005.06c.005.019.01.05.011.07.004.052.053.055.116.006.026-.02.087-.066.135-.1a.568.568 0 00.194-.245c.037-.077.076-.027.063.078a.842.842 0 000 .094.994.994 0 010 .091c-.002.026.016.16.033.25.007.035.015.09.018.123a.461.461 0 00.026.114c.013.03.02.06.016.066-.003.007.003.028.013.046.011.019.017.04.013.048-.004.008 0 .027.01.044.009.016.011.052.004.081a.714.714 0 00-.02.256c.009.095.068.266.097.281.01.006.029.027.04.048.03.05.16.135.243.158.07.019.185.022.215.005.025-.015.04-.101.023-.13a.262.262 0 01-.02-.085zM10.13 42.328a1.07 1.07 0 01-.293-.213c-.059-.07-.16-.254-.153-.279a.234.234 0 01.07-.066.979.979 0 00.176-.165c.022-.038-.06-.071-.157-.064a.847.847 0 01-.354-.082c-.021-.015-.044-.023-.05-.02-.006.004-.035-.01-.065-.029a.752.752 0 00-.118-.061.918.918 0 01-.121-.061c-.182-.113-.266-.17-.277-.19a.276.276 0 00-.086-.056.43.43 0 01-.08-.043.147.147 0 00-.05-.022l-.143-.04a.636.636 0 00-.209-.022 1.547 1.547 0 00-.333.036.998.998 0 01-.313.006l-.11-.016-.013.043a.212.212 0 00.003.098l.026.1a.231.231 0 00.041.082c.023.026.028.04.018.052-.012.016-.168.032-.343.035a1.27 1.27 0 00-.206.03 4.272 4.272 0 01-.175.038.315.315 0 00-.085.028c-.018.01-.039.017-.046.014a.912.912 0 00-.223.07.78.78 0 01-.101.038c-.16.044-.589.283-.687.383a3.73 3.73 0 01-.084.082c-.033.03-.043.12-.016.144.015.014.031.013.057-.002.02-.011.083-.037.14-.057l.184-.066a.333.333 0 01.11-.024.207.207 0 00.082-.016.418.418 0 01.211-.01.435.435 0 00.093 0 .559.559 0 01.14.012c.048.01.117.018.153.018.078.002.201.032.387.097.073.026.156.053.184.06.027.008.053.019.057.025.008.015.139.079.197.097a.998.998 0 01.107.044c.035.017.114.05.176.072a.593.593 0 01.119.052.408.408 0 00.107.037c.056.014.199.052.317.085.118.032.22.056.225.053.006-.003.036.002.066.01a.53.53 0 00.145.013c.049-.002.112 0 .139.005.027.005.11.005.185 0 .074-.004.153-.007.174-.007a.143.143 0 00.059-.01c.01-.007.025-.008.033-.004a.702.702 0 00.22-.018.245.245 0 01.077-.013.241.241 0 00.088-.02c.016-.008.035-.012.042-.008.008.004.029 0 .046-.011.017-.01.04-.016.05-.013a.826.826 0 00.29-.121c.025-.04-.012-.087-.102-.13z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M11.821 42.372a.346.346 0 01.073-.058c.108-.062.352-.271.405-.345a.337.337 0 01.048-.058c.013-.008.02-.018.093-.131a.715.715 0 00.066-.126.335.335 0 01.047-.087c.018-.023.029-.049.025-.056a.338.338 0 01.01-.104.37.37 0 00.01-.102c-.004-.006-.002-.032.004-.057a.561.561 0 00-.054-.276c-.035-.04.007-.165.087-.258.068-.08.164-.233.155-.249-.003-.005.01-.037.029-.07.018-.034.03-.067.027-.074a.259.259 0 01.002-.082c.005-.04.01-.085.01-.103.002-.083.003-.255.002-.29-.001-.029-.027-.081-.104-.208-.098-.162-.104-.17-.162-.2-.046-.023-.067-.026-.092-.012-.042.025-.05.045-.047.107a.152.152 0 01-.014.078.214.214 0 00-.025.064.45.45 0 01-.088.126.593.593 0 01-.22.164.64.64 0 01-.192.079 1.262 1.262 0 00-.1.014c-.11.02-.163.018-.349-.015A.61.61 0 0111.31 40c-.017-.012-.035-.019-.042-.015a.283.283 0 01-.092-.014.649.649 0 00-.152-.017.777.777 0 01-.12-.005.302.302 0 00-.103.008.28.28 0 01-.075.011 2.995 2.995 0 00-.463.283c-.006.022.096.206.134.241.032.03.033.027-.055.102-.036.032-.066.05-.084.05-.018 0-.04.016-.07.05a.4.4 0 01-.08.07 1.145 1.145 0 01-.34.086.114.114 0 00-.055.003c-.009.005-.033-.003-.054-.016-.02-.014-.042-.023-.046-.02-.028.017-.05.051-.043.065.005.01.01.03.009.047 0 .022.013.047.057.1.032.04.06.08.061.092a.042.042 0 00.023.029c.01.005.042.028.07.051a.251.251 0 00.077.048.07.07 0 01.04.032c.018.03.212.09.283.087.076-.003.075.044-.004.136a.43.43 0 00-.06.13.286.286 0 01-.041.1c-.01.005-.017.016-.017.025 0 .008-.016.025-.035.035-.019.011-.033.03-.03.04.003.026.07.07.142.096.03.01.059.025.063.032.018.031.283.115.355.112.024 0 .058.007.077.016.02.01.051.014.07.008a.332.332 0 01.094-.005c.032.003.066 0 .076-.005a.399.399 0 01.08-.022.848.848 0 00.114-.03c.038-.014.054-.013.063.003.007.013.007.03 0 .041a.403.403 0 01-.092.106.864.864 0 00-.076.069 1.285 1.285 0 01-.125.104c-.168.125-.231.183-.245.227a.375.375 0 01-.058.096c-.033.04-.057.1-.091.228a1.43 1.43 0 01-.055.178c-.005.003-.01.015-.012.029-.003.018.011.03.068.05.039.015.092.028.117.029.051.001.063.02.036.062a.297.297 0 00-.027.058.313.313 0 01-.042.074c-.018.024-.03.048-.027.053.004.006-.006.035-.02.065-.06.121-.12.416-.11.527.002.03.003.078 0 .107-.004.079.08.27.149.335a.258.258 0 00.09.058c.02.004.05.018.069.03.018.01.05.019.07.017l.073-.006c.055-.004.074-.03.06-.084a.454.454 0 01-.011-.081.136.136 0 00-.012-.054c-.022-.037-.014-.285.014-.43.047-.256.152-.597.19-.619.01-.005.015-.02.014-.032-.002-.012.008-.039.022-.06a.597.597 0 00.067-.12.965.965 0 01.094-.126 30.6 30.6 0 00.176-.214c.05-.06.149-.164.22-.23.072-.067.144-.136.16-.153zM9.715 44.275a.897.897 0 00-.412-.105c-.148.014-.332.093-.375.16-.014.021-.015.042-.004.06.015.026.023.027.06.01a.47.47 0 01.21-.049.732.732 0 00.077.003.274.274 0 01.166.087c.014.023.012.047-.008.092a.597.597 0 00-.035.125c-.008.059-.004.073.04.15.057.1.09.118.2.118.082-.001.19-.053.196-.096a.111.111 0 01.033-.05c.03-.028.047-.087.055-.182.005-.05-.002-.07-.055-.163-.057-.102-.064-.109-.148-.16zM8.81 44.622a.26.26 0 00-.075-.076.075.075 0 01-.035-.023c-.014-.026-.079-.052-.122-.05a.354.354 0 00-.127.05l-.085.05-.068.24.043.075c.046.079.065.093.164.12.084.024.15.007.24-.06.084-.062.092-.076.104-.185.008-.071.006-.078-.04-.141zM8.963 45.397c-.03-.085-.048-.105-.108-.113-.032-.005-.062-.015-.067-.023-.024-.043-.263-.02-.397.036a.13.13 0 01-.076.01c-.026-.01-.031-.017-.04-.067a.727.727 0 00-.161-.31c-.08-.07-.093-.076-.163-.065-.065.01-.066.01-.104.068l-.057.087a.203.203 0 00-.026.076 1.42 1.42 0 01-.015.096c-.01.05 0 .18.02.274.007.028.046.111.087.185l.075.135.102.067c.136.09.23.11.383.083.089-.016.119-.026.136-.043.011-.011.03-.018.042-.016.029.005.23-.148.29-.222.05-.061.096-.21.08-.258zM7.842 46.743a.93.93 0 010 .132c-.002.023 0 .05.007.061a.206.206 0 01.015.068.131.131 0 00.026.073c.024.025.074.043.09.033a.73.73 0 00.06-.216c-.004-.006 0-.036.01-.067a.362.362 0 00.01-.117c-.007-.054.017-.162.106-.485.021-.078.02-.09-.009-.141-.027-.048-.04-.058-.085-.066a.129.129 0 00-.095.015c-.053.031-.073.066-.085.143a2.332 2.332 0 00-.043.414c.003.005.002.022-.003.036a.465.465 0 00-.004.117zM17.548 44.14c-.009-.07-.041-.077-.243-.056-.099.01-.195.017-.214.017a.126.126 0 00-.05.01c-.009.005-.03.005-.047-.001a.36.36 0 00-.102-.006.835.835 0 01-.123-.002.186.186 0 00-.063 0c-.019.01-.292-.088-.338-.121-.059-.043-.17-.087-.19-.076a.029.029 0 00-.012.028c.005.031.157.14.285.204.067.034.125.065.127.07.003.005.081.024.175.042.152.03.21.039.287.042l.098.01c.04.005.082.004.093-.002.01-.007.035-.007.054 0 .042.014.113-.003.184-.044.073-.042.086-.061.079-.115zM12.621 37.737c.027.088.088.178.138.206.018.009.037.026.044.038.007.012.02.024.03.027.008.002.033.021.055.041s.052.036.068.035c.016 0 .034.007.04.016.005.01.028.018.052.019l.099.004c.03.002.093.002.138 0 .15-.005.21.004.364.053.13.041.158.056.201.103.089.097.12.079.17-.095l.038-.136a.274.274 0 00.011-.08.508.508 0 00-.035-.179c-.017-.035-.016-.046.007-.062.028-.02.045-.022.16-.014a.333.333 0 00.108-.01.162.162 0 01.068-.008c.044.008.19-.057.293-.131a.61.61 0 01.104-.067c.006 0 .04-.03.074-.068a.634.634 0 01.086-.082c.014-.008.03-.036.039-.064.011-.042.008-.06-.02-.11-.02-.033-.043-.063-.052-.066a.26.26 0 01-.057-.042.414.414 0 00-.196-.098c-.094-.014-.084-.053.036-.138a.307.307 0 00.08-.072c.003-.01.016-.025.029-.033a.168.168 0 00.046-.056.403.403 0 01.046-.067.62.62 0 00.101-.196 1.038 1.038 0 01.038-.18 6.02 6.02 0 00.063-.263.322.322 0 01.03-.098c.006-.004.013-.02.016-.035a.558.558 0 01.044-.106.974.974 0 00.062-.154c.012-.042.016-.086.009-.098-.015-.026-.164-.074-.222-.071-.121.006-.474-.07-.746-.16-.07-.025-.297-.02-.343.007-.011.006-.03.01-.04.006-.011-.003-.052.012-.092.032-.065.035-.145.046-.158.024a.248.248 0 01.014-.075.42.42 0 00.014-.126.57.57 0 00-.028-.186c-.018-.058-.027-.072-.07-.105-.044-.033-.054-.035-.088-.016a.355.355 0 01-.086.032 1.694 1.694 0 00-.295.116c-.084.04-.223.148-.224.174 0 .007-.015.021-.033.032-.018.01-.034.03-.037.046a.146.146 0 01-.022.052.78.78 0 00-.067.121c-.02.04-.023.042-.047.03a.247.247 0 01-.063-.059c-.02-.026-.044-.047-.052-.048-.009 0-.022-.01-.03-.024-.015-.028-.297-.108-.37-.106-.047.002-.049.004-.054.04a.11.11 0 00.006.059c.017.03.023.167.009.217l-.032.122a.278.278 0 01-.03.084.229.229 0 00-.033.064.369.369 0 01-.05.09c-.046.051-.146.268-.134.29a.198.198 0 010 .062c-.003.03 0 .1.008.16.01.09.02.12.066.199.03.051.06.093.07.093.008 0 .022.013.03.028.043.074.202.165.34.194.03.007.06.018.064.026.008.014.086.037.186.056l.06.012-.034.127c-.046.177-.063.268-.06.319a.214.214 0 01-.007.068c-.009.025.01.113.053.26zM17.316 44.428c-.088-.02-.228 0-.247.038-.007.012 0 .06.016.105.024.07.033.086.064.106.02.013.04.03.045.04.038.065.229.117.317.087.04-.015.05-.025.061-.06.012-.04.008-.053-.043-.14-.067-.117-.11-.152-.213-.176z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M12.787 39.072a.134.134 0 01.015.05c0 .016.01.07.02.12.017.08.026.1.061.136.028.029.042.053.043.071 0 .018.01.033.024.043.013.008.05.06.08.114a.62.62 0 00.09.125.296.296 0 01.056.069.174.174 0 00.046.054c.012.007.02.022.02.04.002.021.01.031.033.038.016.006.032.02.034.032.002.012.028.034.058.05a.2.2 0 01.07.053.191.191 0 00.052.05c.02.014.07.057.112.098.098.093.09.087.146.118.027.015.086.06.132.1a.7.7 0 00.11.083.902.902 0 01.193.16c.128.134.134.141.138.179.005.046.046.066.075.037a.08.08 0 01.048-.02c.043-.001.132-.147.138-.226.005-.068.016-.082.045-.058.01.01.042.027.068.04a.687.687 0 01.111.077c.034.03.085.067.113.084.072.045.295.102.34.087.022-.006.045-.008.053-.004a.378.378 0 00.103 0 .597.597 0 01.16.008c.039.009.079.011.089.005.026-.015.04-.084.024-.131a.29.29 0 01-.01-.079.359.359 0 00-.056-.14c-.055-.1-.056-.102-.027-.114a.303.303 0 01.115 0c.117.018.2.022.238.011a.34.34 0 01.12.014l.176.044c.155.038.24.085.282.156a.072.072 0 00.043.03c.023.005.036.023.079.111.045.093.055.107.084.113.03.007.033.001.055-.11a.918.918 0 00.02-.284.594.594 0 00-.039-.213.944.944 0 01-.034-.112c-.015-.101-.04-.158-.157-.36-.116-.2-.197-.31-.24-.32-.007-.003-.02-.018-.03-.034-.034-.06-.194-.15-.323-.184a.45.45 0 01-.134-.048c-.01-.018.053-.116.088-.137.05-.028.152-.311.16-.444a.836.836 0 00-.063-.35c-.014-.03-.057-.031-.089-.004a.834.834 0 01-.313.126.626.626 0 00-.13.02c-.093.024-.31.13-.391.192-.073.055-.096.055-.098.003-.002-.053-.097-.196-.159-.239-.16-.112-.292-.099-.336.032a.71.71 0 01-.098.189 3.999 3.999 0 00-.045.068.707.707 0 01-.134.098c-.104.065-.126.074-.193.08-.041.003-.104.01-.14.014a1.108 1.108 0 01-.355-.042.805.805 0 01-.286-.124.307.307 0 00-.078-.041c-.008 0-.025-.018-.037-.039a.156.156 0 00-.057-.054c-.023-.011-.048-.041-.079-.094-.07-.121-.1-.12-.179.01a.325.325 0 00-.05.134 1.771 1.771 0 01-.015.14.505.505 0 00-.002.134.44.44 0 01.006.096.143.143 0 00.01.069zM8.204 39.315a3.568 3.568 0 01-.1.023c-.077.016-.164.143-.16.232.003.048.065.14.12.176.022.014.071.027.11.03.07.003.074.001.147-.057.096-.076.123-.117.12-.183a.223.223 0 00-.045-.118c-.06-.091-.116-.121-.192-.103zM9.59 39.728a.195.195 0 00-.138.004c-.081.026-.143.073-.157.118a.278.278 0 01-.028.058.16.16 0 00-.015.083c.003.044.012.062.044.098.054.059.104.08.194.078.088 0 .108-.01.17-.08a.234.234 0 00.068-.17.314.314 0 00-.037-.104c-.033-.059-.043-.067-.102-.085zM10.701 39.003a.247.247 0 01-.04.061c-.03.035-.039.056-.066.161a.445.445 0 00-.009.25c.024.128.09.282.12.278.01-.002.065-.024.122-.05a.59.59 0 01.276-.055.625.625 0 00.337-.103l.136-.077.052.064c.058.07.183.145.228.135.019-.004.032-.022.043-.063a.214.214 0 01.024-.062.551.551 0 00.048-.084.785.785 0 01.074-.12c.089-.105.172-.266.221-.43a.776.776 0 00.02-.304.62.62 0 01-.018-.084.272.272 0 00-.024-.072 1.83 1.83 0 00-.194-.302c-.009-.003-.027-.023-.04-.045a.46.46 0 00-.216-.124c-.026 0-.23-.042-.335-.07a.28.28 0 01-.209-.233c-.012-.125-.007-.153.06-.325.058-.144.07-.274.034-.366-.011-.03-.018-.06-.014-.066.003-.007-.001-.025-.01-.04-.009-.016-.014-.033-.01-.04a.506.506 0 00-.064-.124 1.167 1.167 0 00-.181-.236c-.05-.054-.239-.14-.345-.16-.106-.017-.134-.018-.47-.003-.116.005-.231.004-.256-.002-.026-.006-.054-.007-.064-.001-.01.006-.023.05-.028.098-.009.076-.005.097.027.158.047.089.047.099-.004.114-.127.039-.157.055-.233.128-.11.104-.14.14-.173.208a.361.361 0 01-.172.178c-.102.06-.119.085-.08.121l.112.117a.652.652 0 00.184.144.479.479 0 00.322.066c.132-.014.142-.012.124.033-.018.046-.116.105-.188.114a.251.251 0 00-.074.02.218.218 0 01-.078.015.624.624 0 00-.288.11c-.101.078-.152.112-.324.217-.192.118-.186.102-.098.256.048.086.063.104.099.119l.042.017-.031.041a.285.285 0 01-.045.05.186.186 0 00-.035.067.186.186 0 01-.032.065c-.016.01-.024.08-.02.164a.243.243 0 01-.013.1.11.11 0 00-.001.08c.015.043.023.048.09.064a.23.23 0 01.08.029c.012.02.141.076.156.068.007-.005.025-.004.039.001a.329.329 0 00.165-.01c.03-.017.04-.005.06.07.01.044.038.105.073.16l.057.09.122-.067c.067-.038.204-.105.304-.149.197-.086.24-.118.366-.264a1.05 1.05 0 01.21-.184.135.135 0 01.077-.015l.04.007-.027.033a.248.248 0 00-.035.059zM9.603 32.062a.708.708 0 00-.063-.058 3.103 3.103 0 01-.263-.334.969.969 0 01-.087-.17 6.37 6.37 0 00-.062-.16.25.25 0 01-.02-.146 2.61 2.61 0 00.016-.166.353.353 0 01.014-.098.251.251 0 00.03-.061c.013-.031.038-.082.055-.113a.194.194 0 00.027-.087.152.152 0 00-.07-.108.9.9 0 01-.06-.038c-.017-.012-.05-.011-.104.002-.13.033-.252.116-.279.19a1.038 1.038 0 00-.138.434l.003.101c0 .02-.004.044-.01.052a.657.657 0 01-.168.035c-.16.02-.342.08-.4.131a.11.11 0 01-.056.027.05.05 0 00-.04.023.605.605 0 01-.055.066.193.193 0 00-.045.066.055.055 0 01-.023.035c-.027.015-.053.137-.04.194.005.026.022.07.038.098.023.04.037.05.061.05.018 0 .103-.04.197-.093.17-.094.213-.107.308-.096.023.003.081.004.13.002a.446.446 0 01.184.034l.132.049c.04.014.153.073.305.16.034.02.084.047.112.06.028.015.054.031.057.037.005.008.088.068.215.154a.125.125 0 01.032.034c.006.01.054.033.107.051a.394.394 0 01.103.046c.01.017.056.051.168.125a.664.664 0 01.102.076c.005.009.033.021.062.029.03.008.058.02.062.027.004.007.028.018.053.024.024.006.049.02.055.029.016.028.07.04.102.021.077-.045.051-.154-.052-.216a.57.57 0 01-.08-.055.17.17 0 00-.05-.032c-.094-.033-.378-.237-.488-.35l-.077-.08zM10.496 33.478c-.009.005-.037.002-.062-.005a.41.41 0 00-.115-.011.284.284 0 01-.085-.005c-.018-.01-.085.044-.107.088-.013.024-.01.037.007.056a.738.738 0 01.102.285c.004.041.011.09.016.109.005.018.014.096.02.172.008.076.016.144.02.15.004.007.009.04.012.074.002.034.01.07.016.081.006.01.014.06.018.11.004.05.016.126.027.17.01.042.022.104.026.138.012.102.173.469.313.714.062.107.303.304.439.357.026.01.085.037.13.059.109.052.23.052.279 0l.032-.035-.05-.076a.281.281 0 01-.046-.098.307.307 0 00-.018-.086.47.47 0 01-.021-.253c.008-.03.01-.064.003-.076-.006-.01 0-.04.013-.065a.45.45 0 00.034-.094c.017-.073.106-.26.17-.356.078-.115.206-.214.296-.228a.357.357 0 00.079-.02.537.537 0 01.21-.005c.026.006.075.01.111.007.096-.005.13-.04.149-.152.02-.127.014-.162-.059-.306l-.064-.128.119-.063c.127-.068.268-.173.31-.23.07-.095.186-.198.307-.27.078-.048.079-.05.066-.088a.154.154 0 00-.028-.054.95.95 0 01-.053-.056c-.074-.084-.179-.137-.366-.185-.13-.033-.258-.041-.297-.019-.029.017-.136.017-.145.001-.005-.008 0-.048.012-.089a1.208 1.208 0 00.04-.31.689.689 0 00-.026-.154.848.848 0 00-.13-.292 12.632 12.632 0 01-.118-.204.886.886 0 00-.142-.168.472.472 0 01-.05-.05c-.108-.121-.103-.117-.22-.193-.115-.076-.14-.089-.19-.102-.03-.007-.058-.02-.062-.028-.01-.016-.096-.029-.116-.017-.028.016-.008.075.048.145.05.062.057.08.077.174a.506.506 0 01.011.187c.017.028-.086.338-.16.485a1.296 1.296 0 00-.06.133c-.02.07-.07.157-.087.156-.013 0-.029-.024-.05-.073a.485.485 0 00-.165-.194.233.233 0 01-.05-.04c-.03-.03-.04-.033-.073-.019-.027.013-.038.026-.037.047a.128.128 0 01-.028.067c-.016.02-.065.1-.11.177-.09.16-.14.325-.13.43.01.102.019.153.03.187.015.043.002.124-.022.138zM19.02 33.356a3.393 3.393 0 01-.06-.075c-.066-.084-.12-.088-.257-.018-.046.023-.13.056-.188.071a.847.847 0 00-.144.052.403.403 0 01-.167.047.065.065 0 00-.038.01.865.865 0 01-.15.03 1.41 1.41 0 00-.169.033.161.161 0 01-.067.01.278.278 0 00-.088.01c-.072.02-.114.063-.095.1a.26.26 0 01.011.084c0 .034.002.079.005.099.002.02.004.047.003.06l.005.12c.006.081.011.098.037.117.017.012.03.029.03.037 0 .009.012.02.027.026a.622.622 0 01.163.101c.005.01.025.02.043.025a.2.2 0 01.075.05.182.182 0 00.068.048c.037.007.101-.05.153-.135a.365.365 0 01.063-.084.476.476 0 00.072-.082c.028-.039.081-.1.117-.135a.47.47 0 00.07-.077c.002-.008.025-.026.052-.042a.78.78 0 00.113-.088 2.32 2.32 0 01.165-.135c.13-.097.161-.133.169-.188a.09.09 0 00-.017-.071zM10.24 28.982c-.03-.038-.053-.054-.087-.061-.154-.03-.277.056-.266.185.007.086.016.099.107.133.065.025.088.027.132.01.08-.031.11-.064.133-.144.02-.069.019-.073-.02-.123zM8.479 38.428c.098-.004.114-.011.207-.093.045-.04.065-.127.043-.19a1.102 1.102 0 01-.02-.06.49.49 0 00-.05-.04c-.07-.053-.12-.062-.222-.041l-.087.017-.044.065a.366.366 0 00-.05.095.434.434 0 00.032.182c.03.047.094.069.19.065zM17.36 33.756a.54.54 0 00-.2-.182c-.132-.08-.416-.09-.59-.022a.82.82 0 01-.122.041.856.856 0 00-.123.04c-.203.076-.25.08-.51.037-.084-.014-.119.002-.12.056a.7.7 0 01-.02.113.292.292 0 00-.004.12.509.509 0 00.11.248c.071.098.099.117.259.182.049.02.082.04.08.05a.34.34 0 01-.05.067.553.553 0 00-.07.105.191.191 0 01-.044.064.179.179 0 00-.041.067l-.06.148c-.105.259-.1.296.052.33.115.027.292.05.307.042.006-.004.025-.002.043.004a.352.352 0 00.107.002c.042-.005.087-.008.1-.008a.884.884 0 00.068-.004c.06-.006.077.005.063.039a.426.426 0 00-.023.18c.006.01.008.03.005.045-.008.047.06.205.111.261.097.104.12.122.199.143a.569.569 0 01.116.044c.02.012.04.02.046.016a.39.39 0 00.041-.09c.058-.157.084-.215.103-.227a.36.36 0 00.058-.064.838.838 0 01.098-.106l.1-.09c.021-.02.076-.068.122-.107a.774.774 0 00.126-.135.536.536 0 01.05-.07.863.863 0 00.091-.197.48.48 0 00.018-.184.37.37 0 00-.057-.198c-.04-.072-.059-.094-.106-.123a.33.33 0 01-.065-.047.147.147 0 00-.052-.028c-.037-.014-.059-.036-.108-.108l-.063-.092.01-.077a.304.304 0 00.002-.088.17.17 0 01-.003-.061c.004-.044-.002-.06-.053-.136z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M13.441 33.931c-.214-.038-.548-.055-.592-.03-.024.014-.039.09-.023.116.014.025.132.064.288.094l.169.036c.052.011.117.021.146.022.028 0 .093.007.144.015a.44.44 0 00.103.007c.006-.004.038.005.072.018a.345.345 0 00.13.02c.067-.006.193.006.335.03a.336.336 0 00.11.003.115.115 0 01.059-.001.114.114 0 00.06-.004c.02-.007.045-.008.054-.003.023.012.056.012.243.003.09-.005.176-.006.19-.003a.17.17 0 00.062-.002.504.504 0 01.105-.006c.039.002.132 0 .206-.002.141-.006.174-.02.194-.084.006-.018 0-.047-.016-.074-.032-.055-.069-.068-.184-.066-.05.001-.11 0-.134-.002a.177.177 0 00-.05 0 1.039 1.039 0 01-.13 0 1.426 1.426 0 00-.167 0 .183.183 0 01-.069-.002.053.053 0 00-.04.002c-.01.005-.044.004-.077-.003a.18.18 0 00-.072-.005c-.028.016-.352-.081-.37-.112a.163.163 0 00-.06-.023c-.029-.008-.057-.02-.061-.028a.179.179 0 00-.044-.038.426.426 0 01-.081-.084.44.44 0 00-.082-.084.292.292 0 01-.088-.18c.002-.072-.118-.035-.199.06-.072.087-.083.14-.051.247.054.183.052.187-.08.163zM9.098 37.125a.06.06 0 01.023-.032.746.746 0 00.09-.118c.061-.094.08-.142.142-.364.039-.141.076-.26.082-.264a.18.18 0 00.033-.058.165.165 0 01.037-.06.052.052 0 00.02-.026.758.758 0 01.086-.104.768.768 0 01.217-.17c.127-.076.144-.082.221-.088a.62.62 0 00.092-.011c.005-.003.026 0 .047.006a.537.537 0 00.093.012c.03.002.064.013.074.026.01.013.036.024.059.026.06.004.083-.038.075-.134-.006-.07-.015-.09-.084-.206-.096-.158-.143-.21-.232-.254a.402.402 0 01-.076-.043.169.169 0 00-.059-.023c-.03-.008-.059-.022-.064-.032-.02-.032-.16-.083-.262-.094a1.137 1.137 0 00-.337.014c-.067.016-.146.013-.175-.006a.727.727 0 01-.064-.057.68.68 0 00-.078-.065.16.16 0 01-.04-.035.528.528 0 00-.157-.1c-.015-.003-.03-.011-.034-.019-.01-.015-.172-.063-.282-.083a.511.511 0 00-.229.009c-.009.005-.023.006-.03.002-.008-.004-.022-.003-.032.002a.273.273 0 01-.078.014.27.27 0 00-.08.015.055.055 0 01-.037.006c-.01-.003-.129.042-.265.1-.136.056-.28.112-.32.123-.04.011-.095.028-.122.038a.353.353 0 01-.074.019c-.013 0-.068.014-.122.03a.712.712 0 01-.146.03.361.361 0 00-.103.021.765.765 0 01-.282.03 2.338 2.338 0 00-.22.002 2.204 2.204 0 01-.443-.09 5.563 5.563 0 00-.181-.058 1.53 1.53 0 01-.36-.18.957.957 0 00-.108-.066c-.01-.003-.025-.02-.036-.038a.067.067 0 00-.054-.034c-.064-.004-.107.06-.128.189a.37.37 0 00-.005.133.125.125 0 01.013.048c.002.033.148.22.195.248a.94.94 0 01.075.053c.115.091.445.192.637.194.034.001.082.006.106.011a.156.156 0 00.07 0c.045-.016.064.031.034.085-.015.027-.023.054-.02.06.004.008-.002.026-.015.041-.012.016-.017.037-.01.048.015.027.313.107.402.107.04 0 .083.005.096.01a.057.057 0 00.043-.002.265.265 0 01.081-.016.262.262 0 00.089-.02.44.44 0 01.095-.03c.062-.014.182-.06.327-.124a.214.214 0 01.078-.024c.01.003.026 0 .036-.007.011-.006.038-.007.06-.003.04.008.041.008.03.038a.108.108 0 01-.04.046.14.14 0 00-.04.038.52.52 0 01-.099.105c-.01.006-.026.036-.037.068-.01.032-.028.063-.039.07-.01.006-.027.033-.036.06a.173.173 0 01-.027.055.527.527 0 00-.035.114.45.45 0 01-.037.116c-.007.003-.012.04-.011.08 0 .041-.005.122-.012.181a.444.444 0 00-.003.123c.011.02.089.017.126-.004.017-.01.055-.009.099.003.075.021.241.02.28-.003.043-.025.046.002.007.091a.478.478 0 00-.036.098.356.356 0 01-.014.08.324.324 0 00-.01.105.404.404 0 01.003.089.195.195 0 00.006.074c.006.01.016.048.025.086a.275.275 0 00.039.097.11.11 0 01.026.053c.001.038.073.098.111.095.029-.003.037-.013.056-.074a.448.448 0 01.07-.142.615.615 0 01.229-.205 2.51 2.51 0 01.352-.163c.006.003.011.025.013.049a.39.39 0 00.058.14c.053.094.057.097.091.092.055-.008.464-.242.47-.27zM11.837 37.684c.06.042.069.044.141.028a.371.371 0 00.216-.123c.085-.09.098-.17.046-.291a1.067 1.067 0 00-.069-.13c-.051-.08-.101-.107-.216-.113a.227.227 0 00-.157.037.616.616 0 00-.157.107l-.01.083c-.01.076 0 .103.086.232a.59.59 0 01.034.071c.017.042.036.064.086.099zM8.296 33.868a.9.9 0 00.172.349c.028.034.077.098.11.143a.616.616 0 00.113.118c.03.02.059.045.064.055a.06.06 0 00.026.023.317.317 0 01.058.044c.023.021.057.044.075.05a.6.6 0 01.078.042c.112.068.478.176.586.172.04-.002.081.004.09.013.022.02.16.027.315.018.11-.006.116-.008.124-.038.006-.025.003-.035-.016-.046-.063-.035-.279-.3-.28-.344a.166.166 0 00-.021-.061.377.377 0 01-.03-.182 1.82 1.82 0 00-.03-.374.52.52 0 00-.072-.161c-.087-.132-.132-.19-.155-.199a.48.48 0 01-.097-.055c-.11-.087-.135-.086-.256.009-.103.08-.126.087-.152.043a.2.2 0 00-.058-.057c-.112-.07-.155-.1-.165-.118a.736.736 0 00-.122-.09.833.833 0 01-.12-.088.136.136 0 00-.052-.033c-.035-.014-.048-.013-.074.01a.264.264 0 00-.054.088.215.215 0 01-.035.066c-.03.018-.074.247-.054.282.003.006 0 .023-.006.038-.026.058-.006.206.038.283zM6.936 30.465c-.009.005-.042.002-.074-.007a.46.46 0 00-.112-.016c-.203.005-.37.016-.39.028a.937.937 0 01-.116.042c-.168.052-.359.139-.408.186-.151.143-.232.23-.255.277a1.424 1.424 0 00-.089.3.18.18 0 01.001.052c-.01.115.047.159.125.098a.523.523 0 01.247-.071.818.818 0 00.217-.045.692.692 0 00.322-.253c.018-.027.054-.072.08-.101a.448.448 0 00.052-.07c.026-.067.267-.244.335-.246.017 0 .05-.003.073-.007.024-.003.068-.007.099-.008.058-.002.096-.018.102-.041.002-.008-.01-.03-.026-.05-.03-.039-.154-.084-.183-.068zM6.876 33.918a.9.9 0 01.003.085c0 .065.08.23.151.313l.087.099c.056.063.26.17.374.196.034.007.085.02.115.029.071.02.182.028.206.014a.058.058 0 01.043-.002.123.123 0 00.067-.005c.023-.009.053-.012.066-.007.023.01.071-.011.077-.033.005-.022-.018-.05-.07-.083a.688.688 0 01-.211-.214 5.531 5.531 0 00-.168-.25c-.131-.187-.148-.202-.289-.257a.595.595 0 00-.356.01c-.087.034-.101.05-.095.105zM14.784 34.587c-.014-.026-.073-.055-.09-.045a1.829 1.829 0 01-.244-.023 2.089 2.089 0 00-.242-.025.187.187 0 01-.068-.005.697.697 0 00-.262.008c-.03.018-.057.127-.039.158.026.045.106.081.162.073a.234.234 0 01.088.005c.02.006.052.006.072 0a.112.112 0 01.06-.003.065.065 0 00.049-.005.403.403 0 01.114-.02.608.608 0 00.1-.01.341.341 0 01.072-.01.268.268 0 00.079-.015c.01-.006.026-.008.034-.004.007.005.04-.007.07-.025.047-.027.055-.037.045-.054zM4.4 25.965a.894.894 0 00.166.362c.023.036.051.069.064.072.013.004.03.02.04.037.01.017.03.037.046.044a.49.49 0 01.069.047c.065.051.199.114.256.119.03.003.083.011.119.019.036.007.074.01.083.004.018-.01.066-.014.111-.008.039.006.222-.04.29-.072.033-.015.114-.06.18-.1a.641.641 0 00.317-.375.362.362 0 00.007-.287.274.274 0 01-.02-.073c.006-.02-.024-.061-.047-.068-.048-.013-.074.022-.067.089.006.05.001.07-.023.093-.017.016-.032.035-.032.043 0 .037-.098.07-.23.08a2.61 2.61 0 00-.176.015.794.794 0 00-.225.072.706.706 0 01-.122.066c-.1.046-.111.048-.202.035-.131-.019-.195-.051-.315-.162-.118-.108-.149-.166-.154-.284-.003-.076-.026-.1-.087-.095-.027.002-.038.01-.052.038a.4.4 0 00-.012.21.245.245 0 01.016.08zM15.313 36.315c.015.009.127-.068.142-.097a.77.77 0 01.07-.079c.035-.035.085-.087.11-.115.144-.153.3-.291.429-.379a.154.154 0 00.025-.055c.011-.037.009-.06-.012-.095-.035-.06-.082-.084-.162-.08l-.064.004-.028.05c-.018.031-.039.052-.056.056a.16.16 0 00-.062.043 2.45 2.45 0 01-.121.112c-.158.139-.17.15-.2.19a2.129 2.129 0 01-.059.077.13.13 0 00-.027.084.734.734 0 01-.004.106c-.01.078 0 .168.019.178z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M4.65 40.56c.04.027.053.026.24-.02.062-.015.501-.28.615-.372l.143-.111c.115-.089.21-.179.298-.284.043-.051.108-.13.146-.173a.697.697 0 00.078-.105c.015-.039.104-.174.133-.2.036-.035.058-.023.129.067.032.042.081.09.108.105.066.038.102.016.14-.089a.829.829 0 01.16-.255.786.786 0 00.08-.103c.16-.245.263-.594.222-.764a1.525 1.525 0 01-.023-.328.553.553 0 000-.137.117.117 0 01.013-.058c.01-.02.014-.04.01-.047-.011-.02.004-.225.024-.307a.798.798 0 01.104-.235.126.126 0 00.02-.046c.007-.023.008-.046.002-.051-.035-.032-.175-.007-.262.047-.023.014-.05.021-.06.017-.13-.057-.245-.402-.217-.65.008-.064-.01-.098-.058-.111-.033-.01-.042-.006-.124.057a.79.79 0 00-.114.103 1.37 1.37 0 01-.084.096 1.723 1.723 0 00-.074.083.984.984 0 01-.062.068.288.288 0 00-.049.06.058.058 0 01-.023.026.194.194 0 00-.044.065.552.552 0 01-.07.104.324.324 0 00-.055.086.266.266 0 01-.053.078c-.027.03-.04.055-.035.078.003.022-.004.038-.024.05-.017.009-.028.026-.026.038a.49.49 0 01-.083.181c-.007.004-.013.021-.012.038a.25.25 0 01-.03.09 1.18 1.18 0 00-.063.189c-.018.07-.044.16-.056.2a3.416 3.416 0 00-.084.41 2.509 2.509 0 01-.04.323.728.728 0 00-.014.156.626.626 0 01-.01.137 3.555 3.555 0 01-.134.489c-.016.034-.027.066-.024.071.003.006-.007.028-.022.048a.228.228 0 00-.036.076c-.004.02-.014.041-.021.045a.324.324 0 00-.049.079c-.092.182-.11.213-.142.24a.497.497 0 00-.061.067 1.328 1.328 0 01-.29.257c-.096.055-.103.076-.037.121zM7.734 39.034c.096-.056.143-.119.14-.189a.245.245 0 00-.251-.235c-.088.002-.118.016-.179.082-.068.074-.076.094-.065.163.017.102.064.15.184.188l.1.032.07-.04zM9.567 28.672a2.244 2.244 0 01-.157.056c-.077.023-.087.03-.151.097-.038.04-.076.083-.083.095a.124.124 0 01-.037.036c-.013.008-.032.042-.043.076l-.018.061.05.054c.035.039.05.063.052.088.004.04.048.091.163.19.059.05.096.07.159.085.045.01.087.016.094.012.007-.005.029-.003.048.004.054.018.089-.012.081-.07a.488.488 0 00-.129-.255c-.066-.058-.07-.083-.026-.15.037-.054.107-.303.1-.351-.008-.054-.026-.059-.103-.027zM4.87 29.951a.237.237 0 00-.05-.071.44.44 0 00-.207-.066c-.125.014-.127.014-.137.043a.472.472 0 01-.041.078c-.038.059-.037.148 0 .24.024.058.026.06.097.07.114.018.221.002.265-.038a.328.328 0 00.094-.16.205.205 0 00-.02-.096zM8.324 40.54c0 .025.008.034.049.052.138.06.2.055.3-.026.06-.047.103-.165.086-.235a.343.343 0 00-.112-.162c-.079-.055-.296.013-.324.1a.475.475 0 00-.013.217.123.123 0 01.014.054zM6.675 40.556c0 .015.013.037.031.053.017.015.041.04.055.056.042.048.285.119.38.11a.515.515 0 01.045-.001c.098.002.245-.085.312-.183a.968.968 0 01.067-.09c.035-.036.089-.227.087-.31a.898.898 0 00-.013-.134.865.865 0 01-.014-.106c-.003-.062-.014-.077-.09-.131a.383.383 0 01-.078-.07c-.018-.03-.243-.114-.325-.12a1.081 1.081 0 00-.208.023c-.13.025-.147.032-.189.07a.515.515 0 00-.06.066.116.116 0 01-.031.032c-.046.027-.139.297-.136.395.002.053.035.122.116.242.028.04.05.084.05.098zM21.909 29.564a.588.588 0 00-.015-.118c-.012-.021-.067-.017-.087.005a.658.658 0 00-.034.246.838.838 0 01-.015.226c-.02.113-.136.552-.147.558a.249.249 0 00-.03.07 2.217 2.217 0 01-.144.34.74.74 0 01-.051.1 2.657 2.657 0 01-.1.156c-.048.07-.046.108.005.154l.041.037.061-.04c.076-.051.115-.114.22-.352.03-.066.062-.143.073-.171a.174.174 0 01.03-.057c.014-.009.104-.333.096-.348a1.043 1.043 0 01.034-.183c.023-.094.04-.198.038-.231a1.14 1.14 0 01.014-.174c.009-.063.014-.16.01-.218zM8.867 29.129c-.082.002-.254.14-.244.196.002.012-.008.028-.021.036-.083.048-.266.58-.256.744a.3.3 0 01-.003.087.463.463 0 00.01.182c.026.084.031.091.06.08.02-.009.028-.028.03-.077a.65.65 0 00-.003-.09 1.374 1.374 0 01.036-.264.905.905 0 01.102-.241 2.115 2.115 0 01.25-.388.098.098 0 01.032-.041.212.212 0 00.073-.125c.004-.052-.028-.1-.066-.1zM8.532 29.063c-.026-.09-.1-.216-.137-.235-.086-.044-.175.09-.192.286-.005.06 0 .073.06.178.071.124.098.145.148.116.08-.046.15-.245.12-.345zM17.572 30.01a.092.092 0 00-.03.073c.004.037.012.049.072.099.103.086.182.106.451.118.123.005.141.005.157-.005.009-.005.027-.005.04 0a.062.062 0 00.047-.003.313.313 0 01.11-.008c.047.002.099-.003.114-.012a.218.218 0 01.068-.021c.037-.005.169-.047.361-.116a2.78 2.78 0 00.338-.188c.269-.164.346-.226.413-.332a.19.19 0 01.044-.05c.01-.006.025-.035.032-.065.008-.03.009-.063.002-.074-.017-.03-.07-.044-.102-.026a.578.578 0 00-.119.149.285.285 0 01-.13.122.555.555 0 00-.105.077c-.023.025-.038.033-.056.03-.014-.003-.035.005-.047.018-.022.022-.19.09-.37.15a.638.638 0 01-.195.043.11.11 0 00-.04.01c-.064.036-.492.094-.533.072a.432.432 0 00-.097-.013 1.763 1.763 0 01-.237-.042c-.15-.036-.157-.037-.188-.006zM12.989 24.454a2.785 2.785 0 00-.007-.061.74.74 0 00-.04-.032c-.073-.057-.157-.051-.197.013a1.063 1.063 0 00-.065.279c0 .014-.01.113-.022.22a1.74 1.74 0 00-.014.26c.01.091.031.2.046.239.016.044.067.059.1.027.03-.03.073-.192.08-.316a.782.782 0 01.016-.124c.005-.013.006-.03.002-.036a.761.761 0 01.046-.257c.027-.016.061-.15.055-.212zM4.823 24.867a.176.176 0 00.054-.065.268.268 0 01.055-.074 1.51 1.51 0 00.087-.09c.143-.158.236-.225.594-.423a.855.855 0 01.228-.066.201.201 0 00.06-.02c.015-.01.033-.014.04-.01.006.004.038-.004.071-.018a.32.32 0 01.107-.023c.026.001.08-.013.12-.032.061-.028.074-.039.084-.072a.097.097 0 00-.003-.066c-.03-.052-.225-.095-.282-.062a.123.123 0 01-.05.014c-.014 0-.075.01-.135.023a1.41 1.41 0 01-.138.022.688.688 0 00-.227.07.235.235 0 01-.083.032c-.023 0-.036.008-.048.027a.66.66 0 01-.109.096c-.197.146-.304.249-.344.327a.806.806 0 01-.06.101c-.018.023-.03.047-.025.054.003.006-.01.035-.03.063a.185.185 0 00-.015.185c.011.026.017.027.049.007zM13.768 23.75c.004-.008-.01-.04-.033-.073-.034-.05-.053-.063-.122-.087a.754.754 0 00-.136-.034.856.856 0 00-.332.086c-.033.029-.065.013-.058-.028.007-.043-.057-.206-.114-.29-.112-.163-.158-.179-.282-.093-.062.044-.08.064-.097.112-.05.136-.055.206-.028.384.017.106.174.382.226.396a.065.065 0 01.035.027c.006.011.018.02.025.02.008.001.026.013.04.028a.494.494 0 00.236.067c.073-.002.244-.054.336-.103a.618.618 0 00.235-.207c.01-.021.03-.05.044-.064.017-.017.025-.044.022-.077a.182.182 0 01.003-.064zM16.55 35.971c-.045-.078-.053-.08-.14-.032a.141.141 0 00-.073.077 1.198 1.198 0 01-.125.241.579.579 0 00-.062.115c-.002.013-.01.028-.018.032a.368.368 0 00-.08.118.318.318 0 01-.047.072.445.445 0 00-.06.096c-.01.027-.05.096-.087.153a.696.696 0 00-.086.184c-.01.044-.027.086-.037.091a.24.24 0 00-.044.08 3.938 3.938 0 00-.203.468.098.098 0 01-.034.054c-.016.009-.024.027-.02.048a.246.246 0 01-.025.103.257.257 0 00-.026.078.687.687 0 01-.037.128 1.075 1.075 0 00-.049.173c-.005.05-.004.054.037.082.041.029.043.029.092-.01a.212.212 0 00.061-.074.395.395 0 01.032-.067.44.44 0 00.067-.147.95.95 0 01.07-.166c.083-.173.101-.186.152-.109.075.114.127.16.181.158.016 0 .048 0 .07.002a.25.25 0 00.078-.01c.123-.04.124-.041.135-.077.008-.027.004-.043-.017-.066a.459.459 0 01-.109-.17.715.715 0 00-.033-.117.775.775 0 01-.033-.233.7.7 0 01.04-.282c.041-.13.06-.175.105-.26a.856.856 0 00.038-.08.124.124 0 01.026-.044.563.563 0 00.056-.096.514.514 0 01.058-.096c.006-.003.013-.018.016-.033a.253.253 0 01.033-.072c.045-.068.122-.2.131-.222.005-.012-.008-.048-.032-.09zM22.882 31.678c-.053-.005-.1.003-.27.052-.128.035-.176.06-.209.11-.016.024-.018.043-.006.063.013.024.025.027.062.014.174-.058.272-.075.35-.063a.217.217 0 00.074.003c.032-.019.434.111.456.147.003.005.056.043.119.086s.117.083.12.09c.005.006.058.046.12.09l.17.118c.144.102.507.163.683.114.052-.014.065-.028.058-.062a.338.338 0 00-.087-.083.854.854 0 01-.124-.116.91.91 0 00-.268-.252 45.44 45.44 0 01-.21-.138c-.095-.063-.346-.14-.512-.156a2.117 2.117 0 00-.397-.02.837.837 0 01-.13.003z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M12.558 25.61a.638.638 0 00-.204.055l-.133.054-.038.063c-.046.076-.044.103.01.125a.728.728 0 01.204.111.41.41 0 00.095.06c.047.021.123.083.232.188.016.016.057.063.09.104l.101.121c.025.029.04.058.042.075 0 .015.007.03.016.036.008.004.075.101.148.215.152.237.138.213.202.339.027.053.057.1.066.103a.23.23 0 01.053.056c.073.098.096.117.15.124.067.01.075.005.087-.05.01-.042.007-.05-.061-.148-.143-.209-.297-.501-.301-.572a.194.194 0 00-.016-.07.693.693 0 01-.055-.214.152.152 0 00-.017-.07.416.416 0 01-.026-.177.33.33 0 00-.003-.046.483.483 0 01-.002-.07.179.179 0 00-.008-.067c-.02-.039-.015-.171.012-.271.015-.057.028-.12.03-.143.002-.048.075-.162.132-.207.023-.018.043-.045.045-.06.001-.015-.003-.032-.01-.038a.94.94 0 01-.037-.04c-.016-.018-.049-.029-.09-.031-.056-.002-.084.006-.18.055-.102.052-.12.065-.152.114a.885.885 0 00-.11.201.208.208 0 01-.043.076c-.01.006-.045.005-.078-.002a.203.203 0 00-.07-.007.377.377 0 01-.081.008zM4.544 25.315c.104.013.158-.032.168-.14.008-.083.007-.086-.05-.112-.038-.018-.05-.017-.103.014-.068.04-.1.093-.097.158.002.053.023.073.082.08zM22.722 30.775c.015.009.037.01.05.004.011-.007.027-.01.035-.005.02.011.174-.082.256-.156.102-.092.216-.221.289-.327.169-.244.179-.264.237-.472.031-.112.06-.205.065-.208a1.34 1.34 0 00.03-.313 1.027 1.027 0 01-.004-.11.472.472 0 00-.016-.115.764.764 0 01-.022-.107 1.222 1.222 0 00-.016-.1c-.015-.07-.06-.147-.083-.142-.01.002-.036.032-.056.066a.337.337 0 01-.051.07.139.139 0 00-.032.05.727.727 0 01-.092.123c-.074.085-.168.257-.173.318a.165.165 0 01-.02.062c-.015.026-.02.076-.016.196 0 .025-.004.08-.01.123a1.437 1.437 0 00-.02.22c0 .07-.03.199-.068.3-.01.028-.025.072-.032.098a.26.26 0 01-.047.087.195.195 0 00-.04.07.216.216 0 01-.047.076.3.3 0 00-.045.06c-.003.009-.024.027-.048.04-.052.03-.062.068-.024.092zM23.145 31.372c.081-.023.321-.036.404-.022.038.007.117.025.176.04a.46.46 0 00.119.022c.006-.004.044.011.084.033a6.363 6.363 0 00.258.135.517.517 0 01.153.078c.026.044.407.088.49.056a.193.193 0 01.072-.015c.034.005.084 0 .178-.015a.306.306 0 01.103-.005c.035.014.058-.005.052-.042-.007-.048-.012-.054-.118-.15a1.923 1.923 0 00-.428-.305 2.192 2.192 0 00-.633-.147l-.097.002c-.249 0-.617.092-.798.2-.075.043-.086.054-.091.09-.008.055.007.064.076.044zM22.566 30.375c.068-.128.178-.496.158-.53-.004-.008-.003-.028.002-.046a.218.218 0 00-.002-.088.198.198 0 01-.004-.077c.005-.012.005-.027.002-.033a.38.38 0 01-.012-.075 1.335 1.335 0 00-.06-.264.798.798 0 01-.054-.203.073.073 0 00-.01-.041.113.113 0 01-.01-.058.086.086 0 00-.013-.055c-.014-.019-.025-.017-.074.012-.08.046-.165.202-.222.405a.675.675 0 00-.03.312c.006.086.017.175.024.197a.18.18 0 01.008.066.845.845 0 00.01.135 1.443 1.443 0 01.018.221c.005.067-.058.366-.081.379a.223.223 0 00-.036.073c-.032.091-.111.201-.157.216-.02.007-.037.02-.037.03 0 .01-.02.029-.044.042-.077.045-.065.112.019.105.063-.004.093-.022.207-.123.115-.103.206-.21.224-.266a.208.208 0 01.034-.065.902.902 0 00.075-.134 7.02 7.02 0 01.065-.135zM23.395 32.506a.174.174 0 01-.063-.033.833.833 0 00-.171-.056.998.998 0 01-.17-.053c-.02-.035-.4-.115-.618-.13-.301-.022-.342-.022-.392-.004-.104.04-.123.088-.057.147.028.026.054.032.121.03.143-.005.204-.004.327.006l.172.013c.03.003.091.014.138.026.046.013.089.02.094.017.017-.01.534.136.592.168.03.016.068.032.084.034.015.003.032.013.037.021.012.021.1.072.165.096.03.01.058.024.061.03.01.017.07-.021.077-.047.009-.033.005-.037-.12-.113-.198-.12-.22-.132-.277-.152zM15.76 29.637c.029.014.072.037.097.051.112.069.396.178.442.171.02-.003.043.003.053.013.01.01.053.021.096.024.074.004.078.003.101-.033.013-.02.023-.046.021-.056-.006-.044-.03-.063-.088-.076a.294.294 0 01-.098-.04.69.69 0 00-.128-.064.701.701 0 01-.125-.06.31.31 0 00-.065-.037.407.407 0 01-.087-.059.407.407 0 00-.087-.059.523.523 0 01-.102-.07c-.113-.096-.206-.095-.249.001l-.02.046.066.095c.068.098.082.111.173.153zM17.103 43.922c.031-.019.11-.15.105-.175a.427.427 0 00-.044-.08c-.037-.057-.047-.064-.107-.075-.073-.014-.13 0-.18.045-.043.04-.097.202-.078.234.034.06.232.093.304.05zM15.247 37.097c.008.014.039.035.068.046.048.018.056.017.098-.016a.667.667 0 00.147-.22.176.176 0 01.038-.059.356.356 0 00.05-.126c.013-.056.045-.143.07-.193l.063-.13c.01-.02.02-.05.021-.065.004-.038-.01-.042-.069-.02-.05.018-.076.049-.219.268a.183.183 0 01-.042.047.532.532 0 00-.158.222.451.451 0 01-.05.108c-.027.03-.037.104-.017.138zM6.428 23.934a.326.326 0 000 .093.183.183 0 01.003.064.056.056 0 00.015.049c.011.01.017.025.013.033-.013.024-.001.108.017.125.01.01.055.015.1.013l.081-.004.027-.059a.223.223 0 00.02-.104.377.377 0 01.001-.094.148.148 0 00-.012-.082c-.01-.019-.016-.04-.012-.048s.001-.025-.007-.039a.09.09 0 01-.008-.054.298.298 0 00-.01-.097 2.583 2.583 0 01-.032-.145c-.018-.1-.035-.13-.072-.13-.033 0-.136.058-.147.08a.205.205 0 00.004.127c.018.03.029.194.019.272zM7.336 25.647a.114.114 0 00.034-.044c.018-.04.008-.063-.03-.07-.034-.005-.185.081-.192.111a.073.073 0 01-.032.036.056.056 0 00-.025.046c0 .017-.008.036-.019.042-.024.014-.08.164-.088.237a.417.417 0 01-.015.078c-.013.035.025.181.064.248a.27.27 0 00.11.104c.102.06.157.064.251.02.117-.056.15-.124.116-.24-.025-.084-.075-.123-.196-.15l-.09-.022-.02-.066a.216.216 0 010-.131.487.487 0 01.132-.2zM6.226 28.42l-.131.013c-.032.005-.044-.002-.062-.034-.012-.021-.021-.046-.02-.055.01-.053-.05-.204-.159-.401a.694.694 0 01-.107-.279c-.021-.116-.02-.137.006-.204.033-.08.035-.134.006-.15-.02-.011-.033 0-.164.143a.898.898 0 00-.15.218 1.215 1.215 0 01-.067.125.83.83 0 00-.058.256.17.17 0 01-.01.078c-.01.015-.01.039-.002.052.018.032.022.106.005.126-.007.01-.006.036.002.06s.017.07.02.104c.008.07.06.21.11.295l.05.09c.034.067.144.213.217.288.065.068.242.214.32.265a.126.126 0 01.035.035c.007.012.02.024.029.027.009.003.033.02.054.04a.2.2 0 00.073.043c.019.004.04.017.047.029.006.011.019.02.028.021a.4.4 0 01.089.05c.04.028.118.067.173.088.055.02.104.044.109.051a.194.194 0 00.066.035.2.2 0 01.064.032c.004.007.023.017.042.024.065.021.22.126.223.15.007.042-.026.045-.114.013-.157-.059-.617-.174-.64-.16-.006.003-.027 0-.047-.007a1.395 1.395 0 00-.169-.029 1.204 1.204 0 01-.196-.04.427.427 0 00-.142-.018.57.57 0 01-.192-.007.423.423 0 00-.136-.01.5.5 0 01-.075-.004.354.354 0 00-.14.026l-.089.033-.014.054c-.01.042-.008.064.012.096.04.065.043.065.326.06l.238-.007c.061-.002.138 0 .17.005a.739.739 0 00.114.007c.03-.002.084.009.12.023.037.013.102.032.144.042.043.01.138.033.212.053.074.02.138.034.143.03a.64.64 0 01.122.034l.153.049a.359.359 0 01.08.038.552.552 0 00.122.05c.044.013.109.037.143.054.035.017.09.043.122.06a.284.284 0 00.08.028c.012 0 .026.006.03.013.004.007.02.017.035.022a.907.907 0 01.116.067c.05.032.122.078.162.102.137.084.216.14.23.163.007.013.02.024.027.024.008 0 .028.015.045.034a.792.792 0 00.102.085c.04.029.084.063.097.075a.674.674 0 00.077.058c.06.038.112.03.117-.02.004-.038-.015-.068-.104-.174-.137-.161-.2-.225-.238-.237-.009-.003-.023-.017-.031-.031a.578.578 0 00-.113-.093 3.968 3.968 0 01-.16-.115 2.026 2.026 0 00-.339-.195.294.294 0 01-.074-.04.17.17 0 00-.05-.032c-.055-.025-.06-.046-.021-.102.016-.024.026-.051.02-.06a.988.988 0 00-.126-.099 1.048 1.048 0 01-.125-.097.757.757 0 00-.107-.083 1.72 1.72 0 01-.395-.35.281.281 0 00-.045-.052.492.492 0 01-.134-.158.4.4 0 01-.058-.123.586.586 0 00-.025-.11.217.217 0 01-.002-.155c.067-.229.07-.283.017-.374-.02-.035-.028-.037-.113-.03zM15.228 43.665c.103-.08.235-.231.255-.292.019-.055.053-.057.127-.006.094.064.282.12.447.132l.135.01.114-.066c.097-.057.118-.075.147-.123a.236.236 0 00.03-.109c-.003-.084-.032-.122-.11-.142a.547.547 0 00-.114-.016c-.119.001-.22-.023-.24-.058a.274.274 0 00-.095-.044.292.292 0 01-.182-.143 1.162 1.162 0 00-.095-.124c-.047-.054-.069-.088-.066-.1a.263.263 0 00-.04-.095 1.319 1.319 0 01-.084-.202 6.84 6.84 0 00-.064-.19c-.06-.16-.12-.588-.094-.66.004-.012.004-.029 0-.037-.005-.008-.005-.026 0-.04a.06.06 0 00-.003-.044.124.124 0 01-.006-.064.33.33 0 00-.011-.105c-.016-.057-.02-.063-.054-.073a.13.13 0 00-.083.014c-.044.021-.047.027-.043.081.003.032 0 .107-.008.167a.39.39 0 000 .13c.007.012.009.028.005.035-.004.008-.002.09.003.183.006.093.007.196.003.229a.395.395 0 00.005.114c.016.072.032.24.025.276a.81.81 0 00.003.124.682.682 0 010 .131.973.973 0 00-.003.192.55.55 0 01-.013.1c-.042.197-.063.263-.098.323a.666.666 0 01-.11.168.819.819 0 01-.305.2c-.03.008-.039.018-.048.06-.01.045-.007.054.037.115.127.172.374.152.633-.05zM7.949 25.238c-.009 0-.022-.01-.028-.021-.012-.02-.159-.041-.224-.033-.041.006-.109.068-.126.116-.015.044.002.14.036.199.009.016.038.043.065.06a.246.246 0 01.056.044c.017.028.098.023.17-.011.066-.031.076-.04.102-.096.035-.074.036-.086.01-.153-.03-.079-.044-.104-.061-.105zM8.845 29.683a.292.292 0 00-.066.067c-.022.047-.036.175-.023.198.026.046.196.069.271.037a.199.199 0 00.112-.175.259.259 0 00-.03-.103c-.031-.055-.033-.056-.12-.062-.082-.006-.091-.003-.144.038zM14.177 21.85a.013.013 0 00-.019-.005.013.013 0 00-.005.018.013.013 0 00.019.005.013.013 0 00.005-.018zM13.55 22.885a.342.342 0 00-.125-.074c-.071-.022-.073-.022-.15.025-.1.06-.126.096-.151.213-.018.08-.016.103.007.154a.152.152 0 00.082.089c.12.063.179.061.313-.01.07-.038.078-.046.097-.1a.242.242 0 00.01-.158c-.011-.065-.019-.078-.083-.139zM15.62 34.718c-.04-.048-.064-.047-.213.011-.233.09-.26.1-.363.12a.697.697 0 00-.124.031.115.115 0 01-.048.013c-.075 0-.318.068-.324.09-.007.027.12.122.21.157.112.044.123.044.277 0 .065-.018.137-.037.16-.042a.322.322 0 00.075-.029c.05-.028.178-.07.267-.089l.079-.015.033-.076a.346.346 0 00.03-.093.057.057 0 00-.014-.028.874.874 0 01-.044-.05zM19.003 13.205c-.102.05-.245.185-.338.322l-.077.112v.132c.002.113.006.14.034.188a.235.235 0 00.078.082c.075.039.123.032.179-.026a.55.55 0 00.07-.09c.059-.104.13-.179.17-.18.012 0 .05-.027.087-.06a.292.292 0 01.214-.086c.027 0 .097-.01.155-.02.07-.014.11-.016.119-.007a.26.26 0 00.102.013c.049 0 .147.013.217.028.071.015.16.033.197.039.167.029.568.19.617.248.008.01.023.019.032.019.01 0 .025.009.034.02a.06.06 0 00.04.02c.014 0 .04.011.058.026a.327.327 0 00.097.043c.057.015.065.014.09-.01a.131.131 0 00.03-.08c.003-.048 0-.053-.05-.077a1.09 1.09 0 01-.14-.09.39.39 0 00-.112-.066c-.014 0-.028-.006-.033-.013a1.195 1.195 0 00-.16-.088 1.775 1.775 0 01-.199-.112.395.395 0 00-.101-.053 1.346 1.346 0 01-.252-.116.801.801 0 00-.108-.06.674.674 0 01-.114-.065.97.97 0 00-.164-.099.547.547 0 01-.08-.061c-.149-.135-.196-.186-.23-.247a.678.678 0 01-.09-.18.82.82 0 01-.021-.363c.008-.031.004-.043-.027-.072-.035-.031-.044-.033-.119-.025-.211.023-.318.248-.272.574.018.13.082.32.125.368.038.043.022.074-.058.112zM27.012 18.947a.818.818 0 01.026-.126.886.886 0 00.028-.127c.035-.215.055-.256.222-.461.054-.066.057-.104.012-.133a.697.697 0 01-.088-.073.293.293 0 00-.101-.063.506.506 0 00-.27-.03c-.12.014-.15.028-.287.134-.041.033-.076.051-.083.044a.341.341 0 01-.033-.076.551.551 0 00-.056-.113.193.193 0 01-.034-.07.177.177 0 00-.037-.07l-.097-.125c-.172-.221-.207-.234-.313-.12a1.4 1.4 0 00-.189.245c0 .007-.011.023-.025.035a.352.352 0 00-.055.092 1.368 1.368 0 01-.043.09.93.93 0 00-.031.062c-.025.055-.043.064-.065.035a.424.424 0 00-.145-.11.078.078 0 01-.04-.018c-.037-.03-.208-.051-.282-.034-.138.031-.165.044-.223.1a.57.57 0 01-.096.08c-.02.01-.037.025-.037.031a.39.39 0 00.057.081c.107.129.144.18.145.203 0 .012.013.049.027.082a.835.835 0 01.042.138l.028.13c.007.03.021.102.031.16.01.06.035.139.054.177.02.039.035.075.035.08 0 .015.07.112.126.177a.481.481 0 00.15.107.367.367 0 00.2.05c.082.001.11-.004.159-.031a.327.327 0 01.073-.032c.007 0 .03-.014.05-.032.03-.025.06-.033.148-.04l.11-.008.062.047a.303.303 0 00.075.046.17.17 0 01.055.028c.036.026.053.028.144.022a.538.538 0 00.258-.083c.136-.075.286-.316.313-.5zM25.956 21.17l.095-.016c.105-.015.136-.06.144-.214a1.23 1.23 0 01.032-.199.841.841 0 00.027-.15c0-.051.025-.149.043-.17a.065.065 0 00.011-.036c0-.014.022-.079.048-.146.027-.066.052-.14.056-.163a.16.16 0 01.026-.062.278.278 0 00.035-.082c.019-.072.002-.13-.04-.132a.256.256 0 01-.077-.033.987.987 0 00-.088-.046.417.417 0 01-.054-.027 1.831 1.831 0 00-.106-.055c-.073-.036-.09-.04-.12-.027-.018.009-.04.012-.047.008-.007-.005-.024 0-.036.01a.62.62 0 01-.169.09c-.01 0-.03.012-.042.026a.198.198 0 01-.082.04.182.182 0 00-.075.035c-.025.029-.008.112.04.2.023.04.041.084.041.097 0 .013.016.059.035.103.02.044.046.12.058.17.013.048.027.093.033.098.005.005.01.035.01.067 0 .031.008.095.019.141.01.046.026.141.035.21.018.161.033.207.077.241a.09.09 0 00.07.021zM28.71 15.593c.047.107.078.259.08.4.003.092.003.093.044.102.022.004.05.005.06.002a.969.969 0 01.075-.018c.11-.022.208-.087.342-.225.095-.096.166-.202.166-.248 0-.033.052-.126.072-.126.009 0 .04.024.07.054a1.204 1.204 0 00.25.19c.01.01.076.035.144.055.111.031.145.035.318.033h.235a.881.881 0 00.217-.04.471.471 0 01.068-.018c.16-.033.153-.03.277-.094.123-.062.147-.077.183-.114.021-.022.047-.04.056-.04.018 0 .073-.069.073-.092 0-.031-.062-.044-.15-.03-.078.011-.098.01-.189-.02a.506.506 0 01-.168-.085c-.032 0-.249-.243-.34-.381a1.289 1.289 0 00-.084-.119c-.05-.052-.1-.139-.091-.153.006-.01.035-.013.088-.007a.483.483 0 00.25-.046.229.229 0 01.06-.023c.04-.01.049-.019.052-.054.003-.03-.003-.046-.021-.056a.129.129 0 01-.044-.057 2.403 2.403 0 00-.1-.184c-.09-.158-.209-.284-.306-.328a.92.92 0 00-.176-.067c-.045-.01-.108-.06-.108-.089 0-.01.016-.033.035-.05.02-.018.05-.06.067-.095a.283.283 0 01.047-.071c.018-.011.004-.096-.023-.137-.014-.023-.027-.028-.052-.022a.736.736 0 01-.297-.054.937.937 0 00-.102-.04 1.88 1.88 0 01-.16-.069 1.154 1.154 0 00-.14-.058.32.32 0 01-.069-.027.278.278 0 00-.078-.027.452.452 0 01-.104-.039 1.253 1.253 0 00-.16-.061 1.343 1.343 0 01-.133-.047c-.095-.04-.492-.084-.774-.085-.124 0-.415.11-.528.202a2.307 2.307 0 01-.116.084c-.1.068-.16.172-.14.241l.014.045.091-.004a.28.28 0 01.108.008c.009.007.046.02.084.027.097.02.183.061.23.109.02.022.05.04.062.04.013 0 .036.02.051.044a.452.452 0 00.063.077c.055.05.173.222.223.325.061.125.083.286.05.37a.354.354 0 00-.023.079c0 .029-.064.147-.1.186a.477.477 0 00-.062.092c-.043.085-.03.133.058.205.099.081.133.093.294.102l.142.008-.005.135c-.005.144.015.32.044.385z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M28.569 15.544c0-.027-.057-.078-.088-.078-.03 0-.121.083-.226.203l-.115.129c-.035.039-.077.09-.092.115a1.773 1.773 0 01-.085.118.44.44 0 00-.057.086c0 .006-.024.03-.053.053a.345.345 0 00-.08.102c-.03.061-.103.165-.195.276a.337.337 0 00-.058.095.113.113 0 01-.028.05.115.115 0 00-.027.054c-.004.022-.015.044-.024.05-.022.014-.039.042-.124.209-.041.08-.083.155-.093.166a.17.17 0 00-.029.055.507.507 0 01-.048.093c-.02.033-.066.114-.1.18-.066.126-.07.16-.025.21.013.014.041.024.072.024.064 0 .093-.026.149-.127a1.55 1.55 0 01.069-.116.171.171 0 00.025-.043c0-.005.03-.055.065-.111.036-.057.073-.123.083-.147a.18.18 0 01.036-.058.054.054 0 00.02-.035c0-.011.017-.04.04-.066a.185.185 0 00.04-.06c0-.033.247-.265.282-.265a.163.163 0 00.05-.04c.021-.022.046-.04.055-.04a.179.179 0 00.054-.019.426.426 0 01.113-.028.437.437 0 00.114-.029.29.29 0 01.2.014c.061.037.089-.085.047-.203-.038-.106-.079-.142-.187-.168-.186-.044-.188-.048-.102-.15.141-.167.322-.448.322-.499zM21.182 12.646c-.006.094-.006.096.034.124a.158.158 0 00.073.028c.018 0 .072.02.12.044.085.042.095.044.244.043.168 0 .243-.017.32-.068a.34.34 0 01.084-.041.226.226 0 00.073-.04.149.149 0 01.052-.031.18.18 0 00.056-.03c.04-.028.058-.03.253-.03.168-.002.224.003.28.022.088.03.13.03.155.003.016-.02.014-.025-.012-.042-.017-.011-.03-.028-.03-.039a.243.243 0 00-.038-.075c-.05-.077-.07-.116-.07-.134 0-.009-.022-.032-.049-.053a.433.433 0 01-.08-.087 2.603 2.603 0 00-.235-.262 1 1 0 00-.091-.074 1.019 1.019 0 01-.093-.074.365.365 0 00-.069-.05.781.781 0 00-.142-.068 1.133 1.133 0 01-.084-.036.12.12 0 00-.045-.012.242.242 0 01-.071-.024c-.046-.023-.086-.03-.267-.05-.156-.019-.477.012-.562.052a.488.488 0 00-.153.11c-.006.01-.02.019-.03.019-.025 0-.14.114-.188.187a6.263 6.263 0 01-.066.098c-.048.07-.025.096.153.17.085.035.166.071.18.079a.735.735 0 00.2.093c.017 0 .05.013.076.029.044.026.046.032.038.076a1.65 1.65 0 00-.016.143zM23.39 15.052c.046.025.217.013.285-.019.177-.083.232-.204.14-.307a.712.712 0 01-.113-.18 3.845 3.845 0 00-.037-.073.717.717 0 01-.018-.165c-.004-.123-.001-.146.027-.207l.059-.129a1.11 1.11 0 01.213-.287.806.806 0 01.25-.186.309.309 0 00.075-.046c.005-.008.028-.014.052-.014.024 0 .058-.01.075-.022.021-.015.06-.021.121-.021.14 0 .153-.027.08-.16a.324.324 0 00-.09-.111 1.748 1.748 0 01-.114-.083.507.507 0 00-.115-.07.43.43 0 01-.086-.042.142.142 0 00-.064-.025.133.133 0 01-.052-.012 1.161 1.161 0 00-.114-.042c-.076-.025-.098-.028-.148-.015-.038.01-.066.01-.082.001a.051.051 0 00-.05 0 .518.518 0 01-.138.013.615.615 0 00-.153.014.297.297 0 01-.088.015.173.173 0 00-.069.012c-.012.008-.03.007-.045-.001-.02-.01-.032-.008-.05.008-.013.012-.033.018-.044.014-.012-.005-.044.007-.072.026a.2.2 0 01-.082.034.19.19 0 00-.069.02c-.02.01-.084.031-.14.048-.13.038-.12.034-.176.067a1.061 1.061 0 01-.152.065.695.695 0 00-.126.054.904.904 0 01-.236.087c-.18.045-.188.046-.223.03-.042-.018-.08.007-.07.047a.082.082 0 01-.006.052c-.021.037.06.188.126.233.056.038.063.054.027.067a.463.463 0 00-.068.04.685.685 0 01-.122.057c-.042.015-.1.04-.13.056-.074.04-.235.204-.245.252-.005.021-.015.042-.022.047a.38.38 0 00-.052.09.602.602 0 01-.087.135c-.027.029-.049.062-.049.074 0 .03.053.076.102.087a.288.288 0 01.073.03c.022.013.072.02.149.022.114.002.116.002.113.033a.304.304 0 01-.058.1.717.717 0 00-.13.2.345.345 0 01-.07.098l-.127.13c-.11.116-.194.167-.276.167a.072.072 0 00-.048.022c-.015.018-.037.02-.135.013-.103-.007-.12-.005-.14.017-.02.023-.017.028.069.103.092.08.15.12.235.159l.08.04c.02.009.074.024.123.032.048.01.1.021.115.027.095.037.156.044.389.044.232 0 .366-.017.397-.047.006-.006.025-.01.044-.01.068 0 .227-.093.32-.189a.453.453 0 01.11-.091c.02 0 .073.103.073.144 0 .058.194.287.305.362a.835.835 0 00.333.12c.034.002.057-.035.049-.076a.838.838 0 01.047-.334.62.62 0 00.049-.123c.025-.093.04-.333.029-.435-.01-.09 0-.11.046-.086zM21.618 10.864a.871.871 0 00-.048-.086.179.179 0 01-.027-.059c0-.01-.028-.041-.061-.07a.39.39 0 01-.078-.088.122.122 0 00-.045-.05 3.593 3.593 0 01-.225-.142.481.481 0 00-.122-.043l-.126-.03a.485.485 0 00-.254.011.245.245 0 01-.076.024.062.062 0 00-.042.02.082.082 0 01-.045.022c-.018.003-.032.018-.039.043a.394.394 0 00.049.234.43.43 0 01.04.075c.016.053.102.122.211.173.046.022.07.025.315.039.066.004.126.01.134.016.008.005.07.01.14.012.069.002.136.01.15.017l.094.047c.079.04.077.04.099.02.02-.021.02-.054-.003-.1a3.778 3.778 0 01-.041-.085zM33.963 14.374c.022.012.069.023.104.024.062 0 .064 0 .113-.072.046-.07.049-.078.04-.144a.289.289 0 00-.026-.091c-.03-.042-.133-.119-.16-.119-.052 0-.157.136-.167.217a.199.199 0 00.096.185zM25.924 3.59c.006.086.015.125.03.137.03.023.07.02.1-.006.018-.016.024-.04.024-.096 0-.07.08-.33.13-.427a.161.161 0 00.02-.052c0-.009.006-.028.015-.041.012-.02.012-.035-.001-.066-.03-.072-.068-.085-.237-.086a.837.837 0 00-.168.009.287.287 0 00-.051.064c-.03.047-.032.055-.014.075.01.012.034.07.05.129a.686.686 0 00.045.125c.029.037.049.118.057.235zM26.965 3.31a.676.676 0 00-.182.127l-.087.083.047.038a.46.46 0 00.093.057.605.605 0 01.122.056c.023.012.075.019.16.019.118 0 .133-.003.224-.047.053-.027.124-.057.158-.069a.32.32 0 00.085-.042c.05-.044-.01-.153-.104-.19a.183.183 0 01-.063-.042c-.019-.022-.043-.026-.19-.03-.165-.003-.17-.002-.263.04zM25.401 4.216c0 .01.01.025.02.033.056.047.136.294.158.495.033.29.04.343.047.39.005.028.014.054.02.058.007.004.013.019.013.034 0 .014.01.056.022.093.024.072.091.138.156.152.02.005.041.013.045.02.01.016.212.007.246-.01a.138.138 0 01.053-.017c.044 0 .117-.069.15-.144.047-.103.083-.318.106-.623a.628.628 0 01.02-.127 1.14 1.14 0 00.033-.116c.01-.045.032-.1.047-.122a.21.21 0 00.029-.047c0-.017.094-.15.127-.18.02-.018.035-.04.035-.049 0-.009.01-.023.02-.032.012-.01.02-.037.02-.062 0-.037-.006-.047-.046-.066-.042-.02-.061-.02-.166-.006a.746.746 0 00-.17.042.244.244 0 01-.075.025c-.013 0-.045.02-.07.047a.195.195 0 01-.06.046.4.4 0 00-.085.074.41.41 0 01-.085.073.659.659 0 01-.11-.083 1.464 1.464 0 00-.172-.135.1.1 0 00-.057-.022.096.096 0 01-.054-.02c-.048-.043-.304-.066-.367-.033-.052.028-.031.084.078.21.04.047.072.093.072.102zM24.176 3.095l.146-.012c.111-.01.165-.028.207-.074a.27.27 0 01.064-.048c.058-.03.044-.067-.051-.132a.313.313 0 00-.148-.064.208.208 0 01-.08-.022c-.008-.007-.034-.013-.058-.013a.226.226 0 01-.078-.015c-.063-.028-.362.093-.467.19a.075.075 0 00-.026.07l.004.042.102.01c.055.005.156.024.223.041a.71.71 0 00.162.027zM24.423 3.539c.013.004.088.034.166.067.189.08.193.081.216.087.01.003.066.006.122.008.088.001.109-.003.152-.031a.304.304 0 01.06-.033.72.72 0 00.168-.124c0-.025-.156-.166-.216-.196-.073-.037-.309-.066-.357-.044-.021.01-.04.01-.055 0-.017-.009-.03-.007-.047.007a.43.43 0 01-.07.043c-.05.026-.122.09-.122.11 0 .008-.009.021-.02.03-.028.023-.026.066.003.076zM38.513 15.626c.004-.007.019-.013.032-.013.023 0 .115-.117.14-.178.016-.038-.004-.128-.037-.167-.03-.035-.122-.068-.19-.068a.231.231 0 00-.084.026.248.248 0 01-.067.027c-.032 0-.068.073-.075.153-.006.072-.003.086.032.136.047.068.057.074.127.086.083.013.113.013.122-.002zM27.477 2.996c.029.025.081.056.116.068a.639.639 0 00.164.024c.109.001.332-.026.408-.05a.74.74 0 01.109-.022c.034-.004.066-.015.07-.024.009-.024-.027-.102-.047-.102a.176.176 0 01-.06-.034.235.235 0 00-.053-.033.235.235 0 01-.053-.033.163.163 0 00-.073-.034.202.202 0 01-.076-.027c-.026-.016-.054-.024-.062-.02a.568.568 0 01-.118.015.352.352 0 00-.118.019c-.007.007-.028.013-.045.013a.611.611 0 00-.24.132c-.025.032-.025.034 0 .047.013.008.048.035.078.06zM38.029 16.413a.553.553 0 00.29-.023c.033-.015.08-.035.107-.044a.304.304 0 00.068-.033.174.174 0 01.049-.025c.05-.015.15-.133.168-.196.024-.09.01-.158-.044-.201-.041-.034-.052-.036-.14-.032a.493.493 0 00-.26.064c-.06.033-.076.037-.093.022-.014-.011-.019-.03-.013-.055a.291.291 0 00-.046-.19.164.164 0 01-.034-.062c-.01-.038-.062-.08-.156-.128-.08-.04-.148-.04-.193.001-.037.034-.11.177-.099.194a.512.512 0 01-.005.116c-.014.122.013.3.053.346a.343.343 0 01.043.065c.01.02.062.068.115.104a.34.34 0 00.19.077zM37.654 16.46a.354.354 0 00-.108.14c0 .016-.195.209-.292.288a.435.435 0 00-.086.09c-.017.03-.016.039.005.07.02.03.03.034.064.027a.82.82 0 00.229-.11c.008-.01.023-.018.033-.018.025 0 .184-.154.241-.233.06-.082.107-.177.097-.194a.41.41 0 00-.183-.06zM38.66 13.62c.07.09.135.13.244.15a.276.276 0 01.073.02c.014.014.065.01.082-.007.036-.035.019-.075-.043-.102-.047-.02-.062-.035-.069-.068-.005-.022-.015-.044-.022-.048-.03-.02-.01-.121.047-.24.033-.066.066-.138.074-.16a.797.797 0 00.05-.231.712.712 0 01.005-.139c.01-.11.014-.12.07-.192.083-.105.142-.144.298-.193.153-.048.218-.046.322.009.067.035.1.028.126-.028.012-.025.01-.039-.006-.064-.027-.04-.141-.116-.175-.116a.244.244 0 01-.078-.026.892.892 0 00-.396-.036c-.042.001-.085.01-.094.019-.01.01-.033.017-.052.017a.131.131 0 00-.061.017.508.508 0 01-.075.037.688.688 0 00-.231.162c-.017.024-.05.066-.076.094-.024.027-.044.059-.044.07 0 .02-.022.064-.05.1a1.02 1.02 0 00-.082.287 2.87 2.87 0 00-.004.206c.002.2.038.3.166.463zM40.082 15.094c.024.01.06.03.082.048.02.017.055.03.077.03.021 0 .042.007.047.014.004.007.021.013.037.013a.09.09 0 01.051.02.298.298 0 00.09.04c.036.01.099.03.14.045.095.034.13.035.148.003.016-.03.019-.147.004-.168a.204.204 0 00-.111-.06.782.782 0 01-.244-.12.324.324 0 00-.081-.046.181.181 0 01-.057-.03.056.056 0 00-.05-.011c-.014.005-.03.002-.035-.005-.014-.023-.093-.055-.117-.047-.012.004-.04.04-.06.08l-.038.072.037.053c.02.028.057.06.08.069zM40.51 14.343a.2.2 0 00-.012.063c0 .017-.006.035-.012.039-.007.004-.016.035-.02.07a.32.32 0 01-.034.105.34.34 0 00-.032.12c-.006.067-.003.084.02.11.016.016.042.03.06.03.059 0 .194-.149.194-.214 0-.015.005-.038.012-.05.007-.013.029-.071.048-.13.02-.057.042-.116.05-.13a.69.69 0 00.052-.232c0-.033.007-.072.015-.088.01-.02.01-.035 0-.055a.667.667 0 01-.028-.142c-.029-.244-.063-.389-.112-.462a.801.801 0 01-.056-.103c-.011-.027-.027-.049-.034-.049-.008 0-.026-.026-.04-.057a.185.185 0 00-.153-.106c-.028-.003-.032.002-.03.04.001.023.014.059.029.08.014.02.031.058.037.083.005.026.02.08.033.12.066.204.077.318.07.727a.86.86 0 01-.057.231zM40.185 12.851c.068.048.071.049.122.013.035-.024.04-.035.04-.096 0-.08-.03-.134-.089-.164-.047-.024-.075-.016-.11.031-.063.085-.051.153.037.216zM34.733 15.313c.007-.044.02-.118.031-.164.018-.078.018-.09-.008-.18a1.003 1.003 0 00-.041-.12.124.124 0 01-.013-.05c0-.014-.02-.048-.044-.074l-.044-.047-.07.016c-.052.012-.08.013-.104.002-.037-.016-.102-.004-.246.047a.332.332 0 00-.152.095.278.278 0 00-.058.076c0 .008-.012.026-.027.039-.043.038-.035.083.02.105.08.033.211.04.284.016.084-.028.108-.02.143.053.03.058.209.244.254.262.05.02.064.006.075-.076zM37.739 14.537c-.01.13.032.192.149.22.085.02.144-.003.228-.094l.064-.067.067.015c.047.012.08.03.114.066.045.047.105.17.105.214 0 .012.01.035.021.052.025.035.05.037.075.008.023-.027.023-.2 0-.222a.074.074 0 01-.014-.046.056.056 0 00-.028-.044c-.015-.008-.027-.025-.027-.037 0-.03-.101-.152-.16-.195a.418.418 0 01-.06-.052c-.024-.03-.17-.07-.247-.069a.27.27 0 00-.145.044c-.103.058-.134.103-.142.207zM34.69 14.477c.039-.071.005-.29-.048-.31-.011-.004-.02-.02-.02-.036 0-.095-.37-.52-.516-.593a.301.301 0 01-.074-.046.462.462 0 00-.162-.083c-.087-.02-.095-.018-.1.012-.002.022.01.038.053.064.03.02.066.039.078.043.026.01.13.091.21.163.05.045.158.189.158.21a2.102 2.102 0 01.21.411c.011.014.02.035.02.047 0 .035.04.104.072.127.043.029.1.025.119-.009zM34.2 15.373c-.078-.037-.094-.034-.169.027-.054.044-.067.063-.074.11-.013.084 0 .127.057.187.05.051.055.053.117.045.047-.006.073-.019.096-.045.102-.119.09-.268-.027-.324zM35.863 11.88a.124.124 0 01-.048.011.065.065 0 00-.037.012.235.235 0 01-.062.027.198.198 0 00-.074.042c-.013.014-.034.026-.048.026-.013 0-.028.006-.032.013a.408.408 0 01-.088.053c-.044.021-.117.07-.163.106a.447.447 0 01-.099.069.195.195 0 00-.063.04.2.2 0 01-.06.04c-.007 0-.026.01-.04.024-.052.045-.22.127-.243.118-.039-.015-.025-.045.047-.105.129-.107.458-.449.458-.475 0-.007.013-.024.03-.038.015-.014.064-.073.108-.131.045-.059.104-.127.133-.15a.427.427 0 00.087-.115.573.573 0 01.103-.163.43.43 0 00.075-.113.505.505 0 01.041-.062.356.356 0 00.048-.136l.017-.093-.04-.039c-.031-.03-.052-.039-.09-.038-.075.003-.077.005-.214.254l-.113.209c-.03.054-.07.12-.09.145a.738.738 0 00-.062.095.375.375 0 01-.08.094c-.03.024-.08.07-.109.103-.03.032-.098.103-.152.157a.883.883 0 00-.098.109c0 .005-.04.045-.09.089l-.118.108a.356.356 0 01-.073.05.558.558 0 00-.105.081 1.034 1.034 0 01-.118.098l-.112.075a.288.288 0 00-.065.056c-.006.01-.017.019-.026.019-.008 0-.025.008-.037.019a.91.91 0 01-.116.068 8.834 8.834 0 00-.169.09c-.14.076-.228.116-.255.116-.015 0-.03.006-.035.013-.004.006-.028.016-.052.021a.793.793 0 00-.125.046c-.044.02-.096.042-.113.047a.681.681 0 00-.088.038c-.064.033-.082.082-.041.111.03.022.065.021.202-.003.208-.038.295-.062.324-.088.007-.006.026-.011.042-.011a.577.577 0 00.136-.052 4.08 4.08 0 01.18-.081c.085-.035.25-.13.338-.196a.294.294 0 01.073-.045c.007 0 .03-.012.052-.028.05-.034.07-.028.099.034.012.026.031.048.041.048.01 0 .078-.027.149-.06a1.04 1.04 0 01.146-.06.77.77 0 00.125-.052 1.71 1.71 0 01.501-.167.281.281 0 00.068-.014.49.49 0 01.203-.037.4.4 0 01.135.012.583.583 0 00.108.033c.065.014.09.029.135.076.164.172.21.202.315.202.04 0 .046-.007.083-.084.022-.045.046-.1.054-.12.013-.03.024-.036.06-.036.025 0 .051.005.058.01.041.036.202.06.427.063a.694.694 0 01.295.047c.11.039.129.05.173.107.053.068.098.097.127.08.02-.012.017-.028-.042-.214a.896.896 0 00-.114-.239 1.22 1.22 0 01-.074-.12.828.828 0 00-.193-.178.17.17 0 01-.061-.049c-.01-.015-.03-.027-.045-.027-.037 0-.102-.035-.112-.059-.004-.01-.027-.023-.052-.028a.623.623 0 01-.1-.034.95.95 0 00-.31-.054h-.102a1.695 1.695 0 00-.359.043 2.703 2.703 0 00-.389.146zM35.186 14.219c.081-.053.01-.197-.151-.31-.05-.034-.064-.037-.184-.037-.143 0-.175.013-.175.07 0 .093.137.253.238.278.09.022.237.021.272-.001zM26.247 2.502c.013.021.035.017.102-.019.059-.031.121-.062.188-.092a.442.442 0 00.184-.215c.03-.1.073-.366.064-.39-.006-.016-.022-.018-.075-.012-.076.009-.17.072-.265.179-.079.089-.15.233-.15.306 0 .016-.006.032-.013.036a.523.523 0 00-.035.207zM13.562 15.65c.075 0 .085-.003.141-.05.058-.05.06-.056.066-.139.005-.073.001-.092-.023-.123a.131.131 0 01-.029-.053c0-.033-.094-.064-.188-.063-.16.003-.213.045-.227.184-.006.056-.003.071.021.092.016.014.029.033.029.041 0 .02.055.072.098.093a.357.357 0 00.112.017zM14.117 16.366a.492.492 0 01.088-.05c.074-.03.154-.18.177-.333.013-.09.014-.124.002-.15a.229.229 0 01-.016-.081.26.26 0 00-.027-.099.249.249 0 01-.027-.072c0-.028-.073-.075-.128-.084-.05-.008-.138.026-.19.073a.509.509 0 00-.156.308c0 .094-.019.103-.117.06l-.107-.045a.48.48 0 00-.243-.008c-.103.043-.122.101-.081.24.016.056.035.082.091.13.079.067.12.092.151.092.012 0 .054.015.093.034a.5.5 0 00.49-.015zM14.829 17.066c.024-.045.004-.085-.079-.154a3.419 3.419 0 01-.124-.108.212.212 0 00-.057-.044.637.637 0 01-.12-.157.29.29 0 00-.05-.069c-.054-.062-.08-.066-.184-.022-.04.016-.05.027-.05.056 0 .02.015.056.033.08a.219.219 0 01.034.053c0 .028.304.313.334.313.009 0 .033.008.054.019l.086.04c.066.028.105.026.123-.007zM18.253 13.43a.029.029 0 00-.017-.025c-.03-.012-.2.066-.32.145a1.04 1.04 0 01-.124.075c-.005 0-.06.059-.123.13-.103.118-.14.164-.18.229a2.294 2.294 0 01-.058.08.23.23 0 00-.044.081c0 .013-.012.034-.027.047-.033.03-.054.1-.054.183 0 .083.01.104.06.125.064.027.086.003.17-.182.04-.091.082-.179.091-.195a.124.124 0 00.017-.048c0-.01.011-.028.025-.04a.366.366 0 00.056-.086.828.828 0 01.063-.106.187.187 0 00.032-.054c0-.021.221-.21.273-.233.067-.03.16-.103.16-.127zM34.658 19.588c.044 0 .18.038.213.06.017.01.049.02.07.02.034 0 .1.026.166.066a.31.31 0 00.04.02.49.49 0 01.061.033.18.18 0 00.063.027c.044.002.156.073.229.146.041.04.09.084.108.096.041.027.103.147.113.219.004.029.018.06.03.069.012.008.029.014.037.01a1.14 1.14 0 01.053-.012c.024-.005.05-.027.073-.063.03-.046.036-.075.042-.184.006-.113.004-.135-.022-.188a.887.887 0 00-.12-.196.206.206 0 01-.044-.075c0-.011.018-.041.04-.066a.203.203 0 00.041-.058c0-.006.016-.04.034-.075a.64.64 0 00.055-.204l.02-.141-.036-.065c-.043-.078-.067-.09-.113-.054a.728.728 0 01-.198.122.411.411 0 00-.1.052 1 1 0 01-.278.107 1.706 1.706 0 01-.135.026l-.156.027c-.036.007-.07.007-.084-.001-.014-.007-.031-.009-.04-.004a2.293 2.293 0 01-.26.02c-.281.014-.253.014-.394.007a.4.4 0 00-.122.005.23.23 0 01-.075.018c-.12.014-.15.025-.183.069-.041.053-.041.061 0 .1.032.029.04.03.16.02.251-.02.581-.006.644.026a.194.194 0 00.068.02zM27.082 9.839c.08-.034.112-.073.146-.172l.029-.084-.035-.07a.367.367 0 00-.057-.092.432.432 0 00-.173-.063c-.055.002-.107.047-.152.133-.045.088-.047.105-.022.226.012.06.076.12.141.133l.062.013c.002 0 .03-.01.061-.024zM18.137 14.17c-.012-.056-.125-.184-.163-.184-.069 0-.196.154-.195.238 0 .037.074.17.099.179.009.003.05.004.09.002.068-.004.08-.01.119-.055.049-.057.065-.114.05-.18z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M11.908 15.263c-.06.014-.194.101-.194.127 0 .009.009.047.019.085.018.068.056.123.167.249.032.036.058.07.058.078a2.02 2.02 0 00.413.418c.052.038.113.09.135.113a1.842 1.842 0 00.3.242c.026.029.15.11.2.133a3.712 3.712 0 00.293.154c.085.04.17.085.189.098a.256.256 0 00.079.031.281.281 0 01.097.049c.028.022.06.04.07.04.01 0 .055.017.1.039a.912.912 0 00.148.055.364.364 0 01.082.027c.007.006.04.015.07.02.032.005.064.017.072.027a.06.06 0 00.04.019c.014 0 .028.005.032.01a.432.432 0 00.113.036c.058.013.131.032.163.042.032.01.067.018.077.018.029 0 .235.066.242.077a.349.349 0 01-.016.097c-.025.101-.026.311-.002.34.026.03.062.024.106-.02a.65.65 0 01.154-.089l.155-.066a.225.225 0 01.061-.019c.01 0 .04-.011.067-.025a.648.648 0 01.163-.042c.12-.017.496-.018.519 0 .018.012.112.04.156.044.053.005.047.041-.025.14a.764.764 0 00-.132.237c-.02.06-.02.064.008.094.027.028.038.03.13.023a.293.293 0 01.117.006c.01.007.05.024.091.037.041.013.087.028.102.035.057.023.268.052.348.049l.083-.004.004.113c.002.063.005.132.008.155.005.053.035.09.063.077.012-.005.116-.01.232-.012.282-.004.436-.048.582-.166a.433.433 0 01.107-.065.383.383 0 00.09-.049.166.166 0 01.066-.033c.026 0 .11-.046.16-.088a.285.285 0 01.095-.046.606.606 0 00.105-.038.663.663 0 01.128-.042.39.39 0 00.094-.028c.007-.006.027-.011.044-.011a.441.441 0 00.102-.026c.115-.04.256-.071.336-.075.04-.001.126-.012.19-.024.154-.03.611-.048.75-.03.06.007.237.04.329.061.032.008.08.014.106.014.026 0 .058.005.07.012a.99.99 0 00.152.033c.133.023.149.027.3.074a2.192 2.192 0 01.38.122.112.112 0 00.042.012c.046 0 .398.207.443.26.01.014.012.026.004.034-.014.014-.073-.002-.158-.043a.272.272 0 00-.075-.025c-.026 0-.202-.059-.214-.071-.005-.005-.026-.008-.048-.008a.265.265 0 01-.083-.019.568.568 0 00-.118-.027.575.575 0 01-.1-.02.39.39 0 00-.14-.037.442.442 0 01-.104-.006 1.691 1.691 0 00-.256-.024c-.028 0-.06-.006-.068-.013-.01-.009-.043-.01-.09-.002a.248.248 0 01-.094.002 2.26 2.26 0 00-.413.005 3.57 3.57 0 00-.183.044c-.07.018-.165.038-.21.044a.944.944 0 00-.297.092 1.045 1.045 0 01-.088.028.306.306 0 00-.088.04.318.318 0 01-.088.04.328.328 0 00-.074.028.064.064 0 01-.036.012.06.06 0 00-.04.02.061.061 0 01-.04.02.059.059 0 00-.04.018c-.008.01-.04.022-.07.027-.073.011-.107.03-.106.058 0 .026.064.13.107.171.015.016.028.035.028.044 0 .009.015.021.034.028.061.023.043.057-.076.14-.106.075-.29.258-.323.323a.67.67 0 01-.083.119.334.334 0 00-.06.087.288.288 0 01-.034.065.252.252 0 00-.033.076.123.123 0 01-.028.058c-.011.009-.02.031-.02.05a.096.096 0 01-.018.055c-.018.02-.038.106-.063.274a.566.566 0 000 .15c.007.04.009.08.005.09a.746.746 0 00.038.244c.008.01.034.017.059.017.039 0 .048-.007.072-.057a.519.519 0 01.26-.204c.03-.004.057-.014.06-.02.005-.007.028-.013.052-.013.024 0 .05-.005.057-.011.013-.012.159-.045.27-.063a8.313 8.313 0 00.163-.026c.07-.01.16-.035.24-.067.043-.017.08-.026.084-.02a.853.853 0 01.028.11c.04.19.047.216.06.229.013.013.086-.01.122-.039.02-.015.06-.02.339-.04.115-.008.152-.019.216-.06a.288.288 0 01.081-.033.274.274 0 00.09-.041.167.167 0 01.057-.032.458.458 0 00.1-.08.626.626 0 01.094-.08c.005 0 .013-.01.017-.024a.462.462 0 01.076-.094.436.436 0 00.068-.08.23.23 0 01.06-.055.288.288 0 00.067-.063c.01-.025.059-.022.074.006.006.012.016.06.022.106.012.108.044.134.17.139a.372.372 0 00.223-.048c.037-.017.087-.038.11-.047a.206.206 0 00.067-.041c.013-.014.03-.026.04-.026.008 0 .039-.015.067-.034a.704.704 0 01.244-.086.072.072 0 00.044-.016c.04-.039.494-.061.592-.03.03.01.067.015.085.01a.897.897 0 01.257.05.212.212 0 00.063.013c.017 0 .039.008.047.018.009.01.049.023.09.028.04.005.077.015.081.021.005.007.022.013.04.013.018 0 .036.005.04.011.004.007.026.016.049.02a.22.22 0 01.077.035c.019.015.04.027.047.027.008 0 .043.021.079.047a.58.58 0 00.13.069.49.49 0 01.101.046.15.15 0 00.05.025c.006 0 .023.012.036.027.014.014.032.026.04.026.017 0 .22.18.425.379.17.163.238.258.28.395.026.08.041.247.024.258-.02.012-.085-.042-.085-.07a.253.253 0 00-.05-.085 3.969 3.969 0 00-.39-.39 2.513 2.513 0 01-.14-.116.518.518 0 00-.1-.077.173.173 0 01-.056-.031.628.628 0 00-.124-.061 2.86 2.86 0 01-.128-.052.906.906 0 00-.176-.038l-.234-.032a.494.494 0 00-.117-.007.37.37 0 01-.104-.014l-.18-.04a.323.323 0 01-.117-.046c-.045-.042-.1-.03-.133.027a.391.391 0 00-.003.283c.035.072.025.096-.04.102a.173.173 0 00-.07.017c-.009.008-.028.01-.042.006a.041.041 0 00-.043.012c-.01.011-.024.02-.033.02a.377.377 0 00-.141.072.41.41 0 01-.087.055c-.11.057-.24.232-.293.396-.043.133-.057.321-.028.35.007.007.013.032.013.056 0 .083.081.094.138.018.051-.068.217-.195.268-.206a.623.623 0 00.088-.026l.088-.035c.095-.035.534-.012.603.033a.137.137 0 00.06.021c.016 0 .054.012.086.026.031.014.086.035.122.046a1.33 1.33 0 01.36.202c.128.083.475.463.475.519 0 .01.012.032.027.05a.487.487 0 01.052.099c.015.036.042.095.062.13.02.036.035.076.035.09 0 .012.009.04.02.06.02.04.04.124.065.276a.72.72 0 01-.003.232c-.01.08-.022.155-.028.17a1.47 1.47 0 00-.06.214.627.627 0 01-.044.127 14.782 14.782 0 00-.139.307.613.613 0 01-.102.154c-.11.141-.199.246-.208.246a.752.752 0 00-.095.1.977.977 0 01-.292.232c-.03.017-.08.05-.109.074a.623.623 0 01-.219.1c-.01 0-.033.01-.05.021a.44.44 0 01-.134.032.579.579 0 00-.118.021 1.869 1.869 0 01-.298.021c-.14 0-.183-.005-.224-.022a.258.258 0 00-.078-.019c-.018 0-.04-.008-.05-.019-.008-.01-.039-.023-.068-.028a.224.224 0 01-.085-.033.218.218 0 00-.067-.034.3.3 0 01-.089-.054.41.41 0 00-.08-.055.806.806 0 01-.193-.21.224.224 0 00-.03-.07c-.065-.113-.084-.368-.032-.439.016-.02.024-.022.054-.008.02.009.035.023.035.032 0 .008.022.041.048.073.116.14.259.197.487.198h.15l.142-.07c.288-.142.448-.326.485-.562.02-.127.018-.216-.006-.247a.115.115 0 01-.02-.06.185.185 0 00-.027-.078.183.183 0 01-.027-.062c0-.044-.288-.368-.328-.368a.215.215 0 01-.073-.035.354.354 0 00-.176-.072.11.11 0 01-.063-.023c-.02-.017-.047-.023-.103-.022l-.103.003-.102.001a.706.706 0 00-.223.041.402.402 0 01-.061.018.895.895 0 00-.361.148l-.126.09c-.07.05-.218.195-.28.273-.043.053-.18.322-.18.353a.67.67 0 01-.052.159c-.071.161-.058.652.024.88.014.04.027.09.027.108 0 .02.01.043.02.052.012.01.021.026.021.038a.15.15 0 00.018.055c.114.209.173.307.184.307.006 0 .027.026.047.058a.502.502 0 00.198.152c.018.01.056.036.084.058a.28.28 0 00.058.04.88.88 0 01.106.065.675.675 0 00.154.08c.031.008.06.02.065.028.004.007.02.013.034.013.014 0 .053.014.087.032a.449.449 0 00.166.042.82.82 0 01.14.022.797.797 0 00.152.018c.065.003.129.01.142.018a.283.283 0 00.097.014c.105 0 .369-.026.397-.04a.166.166 0 01.062-.013.872.872 0 00.146-.028 4.6 4.6 0 01.168-.041c.125-.026.225-.056.284-.084a.543.543 0 01.11-.038.15.15 0 00.071-.034.278.278 0 01.087-.049.38.38 0 00.084-.04.408.408 0 01.075-.042c.03-.013.075-.037.1-.053a1.191 1.191 0 00.435-.308c.016-.024.036-.043.046-.043.023 0 .317-.303.37-.38a.459.459 0 01.073-.086.452.452 0 00.078-.116.705.705 0 01.077-.126c.04-.044.215-.379.25-.484a.453.453 0 01.048-.103.073.073 0 00.018-.038c0-.01.011-.033.025-.052a.246.246 0 00.034-.08.466.466 0 01.028-.087.994.994 0 00.077-.298c-.001-.03.004-.06.012-.064.007-.005.014-.025.014-.045 0-.02.007-.043.015-.052a.637.637 0 00.02-.183c.003-.093.012-.194.02-.225a.482.482 0 00.006-.149c-.008-.082-.006-.097.017-.117.03-.028.018-.027.575-.024.27.002.446.008.451.016.005.007.01.08.012.162s.01.181.018.22a.25.25 0 01.008.09c-.01.024.018.234.039.3a.461.461 0 01.017.107c0 .033.015.09.032.126.06.127.068.147.077.194.005.025.017.06.028.076a.12.12 0 01.019.044c0 .008.012.03.027.05.015.02.04.082.055.137a.513.513 0 00.046.12c.01.01.037.064.06.118a.699.699 0 00.076.138c.018.021.033.049.033.06 0 .02.042.08.119.177.017.02.03.043.03.05 0 .006.019.03.04.05.023.021.042.044.042.051 0 .035.277.329.451.478.03.025.072.064.094.088a.484.484 0 00.11.078c.038.02.084.05.103.067.02.018.048.032.064.032s.036.012.044.027c.008.014.025.026.039.026.013 0 .059.024.101.054.043.029.084.053.092.053.012 0 .143.056.188.08.07.04.135.065.183.072.03.004.074.017.097.028a.588.588 0 00.14.033.35.35 0 01.112.026c.008.008.034.015.057.015.024 0 .079.012.123.027a.29.29 0 00.11.02.39.39 0 01.113.006c.166.03.523.01.633-.035a.516.516 0 01.147-.018.317.317 0 00.17-.034.366.366 0 01.084-.033c.01 0 .024-.008.033-.019a.114.114 0 01.055-.026.66.66 0 00.145-.078l.128-.084c.013-.007.05-.037.085-.065a.436.436 0 01.107-.067c.044-.015.212-.188.212-.218 0-.008.01-.021.02-.03.012-.01.021-.025.021-.035 0-.01.02-.05.046-.089.072-.11.101-.196.18-.523a1.71 1.71 0 00.007-.52.756.756 0 01-.019-.13c0-.019-.008-.042-.018-.05a.068.068 0 01-.02-.048c0-.017-.006-.035-.014-.04-.007-.004-.013-.02-.013-.037a.895.895 0 00-.084-.242 2.999 2.999 0 01-.052-.094c-.034-.062-.288-.31-.394-.384-.138-.096-.22-.142-.268-.15a.45.45 0 01-.096-.029.657.657 0 00-.19-.048.114.114 0 01-.056-.019c-.014-.011-.032-.012-.065-.003-.024.007-.05.009-.058.004a.752.752 0 00-.247-.004c-.004.007-.022.013-.04.013a.07.07 0 00-.047.02c-.01.011-.026.02-.037.02a.798.798 0 00-.137.06.627.627 0 00-.22.17l-.135.144a.262.262 0 00-.052.08 3.512 3.512 0 01-.053.133 1.42 1.42 0 00-.036.107c-.02.07-.02.082.005.213a.936.936 0 00.063.206c.048.09.147.197.23.25.037.023.079.052.094.065.015.012.048.03.074.04.026.01.071.033.1.051.049.032.063.034.243.034l.192.001.095-.062c.115-.075.21-.17.23-.228.015-.048.057-.065.069-.028a.438.438 0 00.028.062c.027.05.04.19.02.202-.009.005-.015.028-.015.05a.28.28 0 01-.026.096 7.58 7.58 0 00-.055.12c-.041.09-.278.302-.34.302a.243.243 0 00-.064.03 1.138 1.138 0 01-.337.12c-.168.025-.525.01-.647-.028a42.978 42.978 0 00-.122-.037.624.624 0 01-.122-.05 1.317 1.317 0 00-.176-.102 1.11 1.11 0 01-.17-.116 27.92 27.92 0 00-.138-.114.278.278 0 01-.054-.06 1.268 1.268 0 00-.112-.126 1.585 1.585 0 01-.23-.304c-.046-.078-.06-.106-.06-.12a.437.437 0 00-.036-.084 1.29 1.29 0 01-.06-.151.302.302 0 00-.047-.099c-.013-.01-.02-.037-.019-.072a.5.5 0 00-.014-.114 2.93 2.93 0 01-.028-.12 1.52 1.52 0 00-.034-.127.628.628 0 01.016-.319.32.32 0 00.018-.082c0-.027.013-.058.076-.184a.987.987 0 01.127-.282.168.168 0 00.033-.047l.042-.078a.675.675 0 01.071-.097c.029-.032.064-.075.08-.095.037-.048.223-.214.313-.28a.985.985 0 01.145-.085c.04-.018.075-.04.078-.05.004-.01.03-.022.058-.026a.763.763 0 00.12-.035l.146-.055c.136-.05.556-.081.595-.043.01.01.033.017.052.017.02 0 .047.009.062.02.014.01.034.02.044.02.054 0 .192.09.283.18.054.055.105.1.114.1.032 0 .066-.045.066-.088 0-.024.006-.074.014-.111.029-.132-.055-.412-.15-.507-.023-.021-.04-.047-.04-.056 0-.021-.093-.1-.151-.128-.023-.01-.044-.029-.048-.04-.012-.03-.241-.137-.294-.137-.101 0-.14-.04-.104-.105a.622.622 0 00.026-.129c.015-.113.006-.148-.051-.199-.027-.023-.034-.024-.08-.008a.364.364 0 00-.082.043.119.119 0 01-.058.024.128.128 0 00-.049.012c-.054.029-.141.042-.294.047-.15.004-.34.033-.406.06a1.503 1.503 0 01-.075.028c-.092.032-.295.135-.303.154-.004.01-.014.02-.023.02a.482.482 0 00-.106.077c-.049.043-.122.104-.163.135a.712.712 0 00-.112.108.193.193 0 01-.065.06c-.015.005-.037.027-.049.05a.596.596 0 01-.075.1.456.456 0 00-.073.104c-.02.047-.064.08-.087.065-.02-.01-.002-.186.023-.231a.155.155 0 00.018-.056c0-.012.012-.037.026-.055a.218.218 0 00.035-.067c.01-.036.26-.296.325-.339a.29.29 0 00.069-.073.536.536 0 01.11-.108 1.41 1.41 0 00.107-.087c.017-.017.037-.03.045-.03s.045-.02.082-.044c.118-.076.164-.103.178-.103a.157.157 0 00.054-.033c.023-.019.049-.034.058-.034.01 0 .026-.009.035-.02a.063.063 0 01.042-.02.185.185 0 00.07-.026.193.193 0 01.06-.027c.01 0 .049-.014.088-.032a.638.638 0 01.126-.041.225.225 0 00.067-.02c.014-.01.036-.015.183-.041.207-.037.277-.045.372-.04.023.002.084 0 .136-.005.103-.009.285.018.413.06.072.023.267.116.301.142.01.008.033.017.054.022.02.005.043.02.05.035.009.015.024.027.036.027.01 0 .044.012.073.026.087.044.257.034.3-.018a.313.313 0 00.038-.101c.017-.075.046-.12.075-.12.015 0 .081.065.321.316.1.105.222.203.252.203.007 0 .031.01.052.02.021.01.063.029.093.041s.072.032.094.043a.785.785 0 00.23.03c.173.008.195.012.25.044.072.042.11.045.139.013.03-.035.054-.132.056-.227.003-.114.015-.121.117-.071a.403.403 0 00.131.04c.026 0 .075.01.11.02s.11.027.165.038c.056.012.139.03.183.041.045.012.132.032.193.046a.469.469 0 01.136.047c.014.012.032.022.04.022s.05.044.095.097c.056.069.09.098.115.1.047.006.06-.021.078-.153.008-.057.02-.14.029-.186a.508.508 0 00-.016-.226.946.946 0 00-.041-.16.427.427 0 01-.032-.091 1.22 1.22 0 00-.173-.348.943.943 0 01-.076-.115.471.471 0 00-.162-.177c-.027-.014-.044-.032-.044-.049a.04.04 0 00-.023-.035.442.442 0 01-.08-.053.275.275 0 00-.069-.044c-.007 0-.025-.018-.041-.04l-.03-.038.05-.045a.966.966 0 00.117-.141c.056-.082.063-.1.048-.118-.011-.014-.032-.019-.059-.015a.49.49 0 01-.224-.09.291.291 0 00-.075-.034.89.89 0 01-.108-.043l-.078-.038a.115.115 0 00-.04-.012.158.158 0 01-.051-.017.968.968 0 00-.108-.042.703.703 0 00-.211-.055.343.343 0 01-.094-.02c-.014-.01-.085-.027-.27-.06-.13-.025-.09-.023-.481-.015a3.066 3.066 0 00-.36.02.726.726 0 01-.134.02 1.158 1.158 0 00-.312.063.386.386 0 01-.067.018 1.843 1.843 0 00-.26.06c-.029.014-.211.068-.264.078-.042.007-.061-.016-.036-.046.044-.052.417-.244.53-.272a.197.197 0 00.071-.027c.004-.007.022-.012.04-.012a.508.508 0 00.111-.026c.043-.014.106-.03.14-.034a.292.292 0 00.087-.026.328.328 0 01.095-.026c.037-.006.104-.021.149-.034.045-.014.13-.032.19-.04a9.62 9.62 0 00.21-.033c.148-.026.89-.011.925.018.01.008.057.017.104.02.048.004.112.013.141.02.03.008.088.02.129.029.04.008.096.025.122.038a.608.608 0 00.128.04c.101.02.359.104.386.127.028.023.217.114.236.114.01 0 .034.018.055.04.022.022.047.04.057.04.01 0 .035.01.055.024.043.027.06.037.18.104.158.088.3.116.488.094a.26.26 0 01.145.012c.031.012.065.02.076.015.029-.01.053-.123.054-.248l.001-.113.124.004c.119.003.134 0 .325-.064.172-.058.208-.066.252-.056.048.011.152-.003.176-.025.012-.01-.011-.117-.04-.183a.233.233 0 01-.018-.056c0-.008-.012-.02-.027-.028s-.027-.021-.027-.03a.376.376 0 00-.063-.087c-.06-.07-.063-.074-.038-.092a.19.19 0 01.087-.018c.035 0 .099-.01.143-.021a.808.808 0 01.27-.011c.105.005.205.01.224.009.018 0 .04.004.047.01.008.005.05.017.095.026a.788.788 0 01.295.103.297.297 0 00.086.044.2.2 0 01.072.041c.062.05.11.049.124 0a.555.555 0 00-.015-.283c-.046-.1-.028-.145.06-.145.018 0 .037-.006.041-.013.005-.007.032-.013.06-.013.03 0 .06-.009.069-.02a.06.06 0 01.04-.02c.013 0 .028-.005.033-.01.006-.006.03-.011.053-.012a.87.87 0 00.253-.083 1.05 1.05 0 01.249-.076.588.588 0 00.148-.06.432.432 0 01.11-.049.186.186 0 00.055-.018 8.599 8.599 0 01.523-.265.962.962 0 00.16-.087.06.06 0 01.04-.02.406.406 0 00.112-.074.604.604 0 01.102-.073c.006 0 .083-.065.17-.144.171-.156.23-.203.252-.203.007 0 .019-.009.025-.02a.34.34 0 01.061-.058c.064-.05.267-.29.267-.316 0-.01.013-.027.029-.036a.947.947 0 00.188-.252c0-.013.006-.027.014-.032.022-.014.015-.098-.01-.12a.46.46 0 00-.174-.096c-.039-.006-.047 0-.104.073a.584.584 0 00-.071.111.544.544 0 01-.116.159.615.615 0 00-.084.097c-.075.098-.383.41-.404.41-.006 0-.021.018-.033.04a.149.149 0 01-.065.06.4.4 0 00-.096.069.62.62 0 01-.077.064c-.013.008-.06.042-.106.077a.756.756 0 01-.09.063.757.757 0 00-.09.067.417.417 0 01-.102.067.494.494 0 00-.108.06c-.05.033-.1.06-.11.06-.011 0-.036.014-.055.03a.401.401 0 01-.095.056.422.422 0 00-.088.048.196.196 0 01-.073.032.702.702 0 00-.124.049.394.394 0 01-.108.038c-.015 0-.05.011-.078.024a.794.794 0 01-.112.042 2.182 2.182 0 01-.364.096.25.25 0 00-.076.025.72.72 0 01-.199.049c-.062.01-.077-.016-.047-.08a.932.932 0 00.044-.155c.046-.224-.004-.37-.147-.43-.05-.02-.063-.005-.069.083a.785.785 0 01-.015.113c-.017.069-.253.353-.292.353a.206.206 0 00-.065.037.753.753 0 01-.096.06.576.576 0 00-.133.081.107.107 0 01-.062.022.315.315 0 00-.103.034.345.345 0 01-.087.033.316.316 0 00-.084.033c-.073.039-.098.042-.109.013-.01-.026.032-.073.067-.073.014 0 .044-.015.066-.033.023-.018.051-.033.064-.033.013 0 .044-.021.07-.047.025-.026.053-.047.063-.047.01 0 .074-.055.143-.123a3.44 3.44 0 01.188-.173.396.396 0 00.089-.1.177.177 0 01.062-.068c.02-.01.036-.026.036-.036 0-.01.023-.041.051-.069.07-.069.22-.247.22-.261 0-.007.027-.044.06-.081.063-.074.17-.25.17-.28 0-.01.012-.033.026-.05a.24.24 0 00.035-.066c.005-.018.029-.072.051-.12a.953.953 0 00.052-.126 1.96 1.96 0 01.043-.134c.046-.13.064-.239.071-.432.008-.203-.011-.251-.077-.193-.017.015-.025.04-.025.08 0 .041-.01.073-.03.102a.788.788 0 00-.065.116c-.04.088-.12.213-.188.289-.026.03-.073.087-.102.125-.067.086-.184.2-.207.2-.009 0-.028.022-.043.05a.32.32 0 01-.095.095c-.038.025-.069.052-.069.06s-.02.033-.046.055l-.117.102a.384.384 0 01-.106.071.38.38 0 00-.147.102c-.02.026-.177.134-.286.194l-.118.067a.998.998 0 01-.24.111c-.016 0-.041.01-.056.02a.105.105 0 01-.052.02c-.014 0-.044.015-.066.033-.022.018-.049.033-.06.033a1.5 1.5 0 00-.157.041 8.979 8.979 0 01-.266.074.922.922 0 00-.142.044.373.373 0 01-.106.02.485.485 0 00-.115.02.516.516 0 01-.18.035c-.007-.004-.032.001-.057.012a1.814 1.814 0 01-.336.055 2.544 2.544 0 01-.325.046c-.093.008-.19.02-.216.027a3.11 3.11 0 01-.19.032c-.233.035-.279.044-.338.075-.032.015-.066.025-.076.02-.021-.007-.026-.068-.007-.08.006-.004.015-.023.019-.044.004-.02.02-.072.035-.115.036-.099.04-.276.008-.302-.012-.01-.017-.027-.012-.042.005-.016-.005-.045-.025-.075a.641.641 0 01-.045-.078.336.336 0 00-.08-.082.243.243 0 00-.16-.062.34.34 0 00-.141.008c-.083.028-.085.031-.055.108.025.064.026.08.011.183a.478.478 0 01-.028.126.059.059 0 00-.013.037c0 .026-.088.125-.248.28-.102.1-.298.224-.352.224-.012 0-.028.011-.035.025-.008.014-.043.035-.079.047a.708.708 0 00-.085.035 5.178 5.178 0 01-.466.216.984.984 0 00-.258.09.8.8 0 01-.129.041c-.1.022-.343.102-.415.137-.055.027-.06.027-.082.006-.022-.022-.022-.026 0-.067.03-.058.056-.282.047-.411-.007-.094-.012-.11-.05-.153a.19.19 0 01-.042-.063.211.211 0 00-.048-.067.31.31 0 00-.15-.084.411.411 0 00-.112-.026.792.792 0 01-.11.022.327.327 0 00-.128.039.397.397 0 01-.07.045c-.084.042-.099.127-.028.162.089.042.118.077.146.174.056.194.023.3-.174.556a.346.346 0 01-.071.077c-.006 0-.02.016-.031.036-.043.078-.31.33-.372.352-.024.008-.043.02-.043.026 0 .007-.023.026-.05.044a3.112 3.112 0 00-.257.233c-.113.11-.24.229-.284.263-.043.035-.134.12-.2.191-.068.07-.171.177-.231.235-.175.172-.426.476-.426.516 0 .02-.043.083-.132.2a.45.45 0 00-.058.085.456.456 0 01-.058.085c-.033.041-.084.123-.114.181-.103.2-.18.363-.18.383 0 .01-.011.043-.025.072a.45.45 0 00-.033.104.172.172 0 01-.03.074.08.08 0 00-.02.044c0 .036-.031.047-.17.058-.243.019-.726.027-.75.013-.008-.005-.035-.003-.06.006a.115.115 0 01-.084 0 .901.901 0 00-.191-.015h-.152l-.041-.06a.253.253 0 01-.041-.08c0-.01-.006-.03-.012-.042a1.205 1.205 0 01-.042-.123 1.65 1.65 0 00-.049-.144.228.228 0 01-.02-.061c0-.01-.01-.028-.025-.04a.136.136 0 01-.035-.06c-.009-.036-.099-.196-.144-.255a.606.606 0 01-.049-.08.875.875 0 00-.088-.125.376.376 0 01-.064-.095c0-.01-.009-.024-.02-.033a.476.476 0 01-.061-.089.846.846 0 00-.087-.122.305.305 0 01-.054-.077.473.473 0 00-.076-.1 4.078 4.078 0 01-.098-.11 1.84 1.84 0 00-.111-.114c-.044-.041-.143-.139-.22-.216-.21-.213-.238-.238-.285-.26-.024-.012-.044-.03-.044-.04 0-.01-.017-.031-.037-.047a3.456 3.456 0 01-.141-.124c-.195-.18-.325-.29-.343-.29a2.72 2.72 0 01-.269-.235.363.363 0 00-.04-.048 2.31 2.31 0 01-.243-.282c-.012-.025-.032-.048-.044-.052-.011-.005-.02-.02-.02-.035a.215.215 0 00-.016-.063l-.026-.064a.432.432 0 01-.01-.21c.038-.113.067-.156.14-.204.075-.049.089-.076.057-.116a.509.509 0 00-.17-.117.505.505 0 01-.09-.02.24.24 0 00-.142-.006 2.996 2.996 0 01-.12.022c-.076.011-.172.123-.22.257-.027.078-.03.102-.022.261.007.144.013.186.037.231.024.045.026.06.013.075-.023.027-.058.025-.099-.007a.134.134 0 00-.068-.026c-.02 0-.038-.006-.043-.014-.005-.007-.025-.013-.046-.013-.02 0-.041-.004-.046-.008a1.336 1.336 0 00-.246-.078.2.2 0 01-.075-.027.2.2 0 00-.074-.027.317.317 0 01-.067-.017 2.496 2.496 0 00-.156-.057 1.145 1.145 0 01-.294-.13.164.164 0 00-.062-.03.126.126 0 01-.054-.026.16.16 0 00-.043-.027 3.46 3.46 0 01-.193-.087 1.175 1.175 0 01-.274-.163c-.116-.1-.164-.146-.164-.159 0-.005-.015-.025-.034-.044a.513.513 0 01-.115-.136.228.228 0 00-.018-.056.718.718 0 01-.05-.203c0-.018.013-.057.028-.086.035-.068.034-.074-.016-.099a.278.278 0 00-.19-.023 1.305 1.305 0 01-.082.021c-.04.009-.132.082-.132.105a.168.168 0 01-.03.055c-.049.065-.062.1-.076.208-.014.101-.002.24.022.271.007.009.02.044.03.079.01.035.025.07.035.078.025.02.024.051-.001.06a.2.2 0 01-.085-.012 1.967 1.967 0 00-.376-.09 1.17 1.17 0 01-.155-.027 1.66 1.66 0 00-.298-.032.729.729 0 01-.129-.018 1.958 1.958 0 00-.21-.03 1.227 1.227 0 01-.222-.04c-.036-.013-.071-.021-.078-.017a.615.615 0 01-.194-.038.888.888 0 00-.14-.024.355.355 0 01-.115-.025c-.008-.008-.028-.015-.045-.015a.316.316 0 01-.082-.018 4.924 4.924 0 00-.146-.048 1.163 1.163 0 01-.118-.041.129.129 0 00-.05-.013.454.454 0 01-.112-.038 1.675 1.675 0 00-.16-.062.982.982 0 01-.121-.048 3.09 3.09 0 00-.109-.051.923.923 0 01-.101-.054 1.652 1.652 0 00-.109-.061 1.022 1.022 0 01-.11-.067.273.273 0 00-.05-.032.688.688 0 01-.08-.07.758.758 0 00-.153-.11.498.498 0 01-.126-.09c-.024-.028-.052-.05-.061-.05-.01 0-.037-.027-.063-.06a.278.278 0 00-.054-.06 4.76 4.76 0 01-.365-.354c0-.006-.013-.023-.028-.039a.679.679 0 01-.108-.135.48.48 0 00-.065-.085.458.458 0 01-.081-.131c-.01-.031-.03-.063-.044-.07-.014-.008-.026-.025-.026-.038a.266.266 0 00-.027-.08.265.265 0 01-.027-.09c0-.075-.045-.108-.084-.062-.021.023-.022.12-.005.336.017.217.076.404.205.654l.088.173c.032.063.075.135.096.16.02.026.038.057.038.07 0 .014.01.028.021.033a.271.271 0 01.066.076c.024.038.108.137.185.22.078.084.161.177.186.207.064.078.356.358.396.38.16.084.27.162.27.19 0 .037-.033.044-.083.02a.21.21 0 00-.072-.022.172.172 0 01-.075-.033.176.176 0 00-.081-.034.169.169 0 01-.068-.019.914.914 0 00-.065-.033c-.017-.007-.03-.02-.03-.028s-.023-.024-.051-.037a.664.664 0 01-.094-.052.186.186 0 00-.055-.03c-.014 0-.206-.196-.206-.21a.15.15 0 00-.031-.043c-.034-.037-.052-.084-.08-.206-.01-.043-.026-.081-.035-.085-.027-.01-.144.072-.161.113a.466.466 0 00-.012.28c.03.149.046.205.071.233.011.012.016.029.011.037-.011.018-.084.018-.095 0-.005-.007-.026-.013-.047-.013a.307.307 0 01-.097-.026.312.312 0 00-.096-.027c-.06 0-.335-.08-.437-.127a.746.746 0 00-.149-.05.483.483 0 01-.111-.036.277.277 0 00-.083-.027.206.206 0 01-.078-.036.857.857 0 00-.11-.06.484.484 0 01-.095-.056.222.222 0 00-.078-.04.371.371 0 01-.108-.061.8.8 0 00-.123-.078.871.871 0 01-.213-.144c-.006-.01-.017-.019-.025-.019-.018 0-.1-.062-.207-.156a.474.474 0 00-.093-.07c-.01 0-.054-.043-.185-.18l-.156-.153c-.173-.17-.336-.367-.359-.435a.255.255 0 00-.043-.08 1.059 1.059 0 01-.056-.064c-.027-.035-.033-.037-.086-.025zM12.127 12.451c.015 0 .07-.014.122-.032.092-.03.098-.031.21-.012.171.03.275.083.344.178.071.097.077.12.09.31.012.184.056.352.113.43.055.075.08.148.07.206-.012.076-.066.166-.104.175-.033.007-.049.049-.034.087.009.022.116.027.154.007.013-.007.053-.024.09-.037.052-.02.08-.044.152-.131.118-.145.157-.258.162-.473.003-.085.006-.163.008-.174a1.07 1.07 0 00-.104-.326.613.613 0 01-.052-.104.527.527 0 00-.109-.149.601.601 0 00-.214-.147.805.805 0 00-.158-.06c-.015 0-.031-.007-.036-.014-.004-.008-.037-.014-.072-.014a1.36 1.36 0 01-.151-.013.374.374 0 00-.142.002c-.17.044-.254.074-.266.095a.05.05 0 01-.039.023c-.028 0-.095.085-.095.12 0 .03.028.054.06.053zM13.465 14.68a3.522 3.522 0 01-.031.073c-.02.043-.022.07-.014.138.006.047.019.09.028.096.026.016.05-.01.067-.07a.666.666 0 01.153-.247c.058-.05.157-.07.178-.037.082.135.15.168.279.136.06-.015.08-.028.11-.07.035-.048.038-.061.031-.13-.01-.105-.053-.18-.122-.212a.97.97 0 01-.061-.032c-.041-.023-.173-.024-.258-.002a.69.69 0 00-.305.252 2.375 2.375 0 01-.035.064.383.383 0 00-.02.04zM17.746 11.466l.05-.155a.643.643 0 00.036-.337.344.344 0 00-.028-.089.066.066 0 01-.012-.038.219.219 0 00-.018-.067 1.21 1.21 0 01-.076-.295c0-.051-.03-.077-.058-.05a.061.061 0 01-.037.016c-.107 0-.306.223-.377.42-.042.118-.054.48-.018.569.008.019.017.067.02.106a.497.497 0 00.047.18l.043.089a.272.272 0 00.042.07c.007.005.013.019.013.032 0 .013.018.047.04.076.022.028.04.059.04.067 0 .008.013.025.028.038.015.014.027.031.027.04 0 .018.108.134.136.144.058.022.094 0 .094-.06 0-.021-.01-.041-.025-.05-.014-.007-.032-.04-.042-.076a1.242 1.242 0 00-.03-.1c-.038-.1-.012-.302.052-.41a.63.63 0 00.053-.12zM15.921 10.582c.066.035.158.037.205.004.059-.042.122-.194.098-.238a.256.256 0 01-.02-.058.372.372 0 00-.114-.151c-.043-.024-.13-.017-.177.015a.249.249 0 01-.056.03.316.316 0 00-.051.084c-.036.07-.041.09-.031.133a.329.329 0 00.146.181zM15.904 9.73c.048.036.062.04.115.033.06-.008.122-.048.122-.08 0-.009.009-.023.02-.031.02-.017.019-.112-.002-.178-.018-.058-.093-.104-.171-.104-.06 0-.072.006-.12.052-.047.048-.052.058-.051.124 0 .092.02.134.087.184zM17.591 4.517c.21-.027.586-.015.645.021.016.01.045.019.064.019.02 0 .045.005.058.012.033.017.24.081.261.081.01 0 .027.008.04.018.01.01.054.028.095.041a.63.63 0 01.108.046c.058.037.097.055.117.055.036 0 .33.245.33.275a.21.21 0 00.034.064c.02.029.034.068.034.095 0 .032.01.052.035.072.02.016.042.028.05.028a.226.226 0 00.065-.053.181.181 0 00.06-.12c.006-.038.015-.071.022-.075.015-.01.015-.08 0-.109a.838.838 0 00-.119-.251.648.648 0 01-.073-.126c0-.01.027-.058.06-.106.07-.102.103-.199.112-.326.007-.098-.008-.154-.054-.205-.035-.037-.055-.037-.09 0a.36.36 0 01-.081.057 2.247 2.247 0 00-.218.12.414.414 0 01-.094.037l-.183.055c-.146.044-.339.06-.758.067a4.264 4.264 0 00-.478.026c-.198.032-.267.093-.187.167.03.029.036.03.145.015zM16.084 9.16c.005.062.011.077.03.077.025 0 .04-.035.04-.096 0-.057.056-.214.09-.25a.724.724 0 00.065-.096c.077-.132.27-.318.416-.403a.465.465 0 00.086-.062c.014-.015.036-.027.05-.027.015 0 .051-.012.082-.026a.28.28 0 01.078-.027.536.536 0 00.1-.027c.073-.025.08-.026.144-.005.069.022.12.069.215.197a.223.223 0 00.057.062c.007 0 .041.02.076.044.092.064.13.075.27.082a.445.445 0 01.26.075c.07.041.08.03.075-.086-.006-.143-.026-.208-.118-.376a.606.606 0 00-.246-.228 1.147 1.147 0 01-.115-.064.516.516 0 00-.209-.066.045.045 0 01-.04-.006c-.023-.02-.144-.022-.252-.005a.897.897 0 00-.25.072.075.075 0 01-.04.012.237.237 0 00-.082.032l-.13.074a1.545 1.545 0 00-.49.495c-.075.125-.108.216-.106.297 0 .022-.005.046-.011.054a.326.326 0 00-.021.094.344.344 0 01-.02.093.227.227 0 00-.004.09z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M14.2 12.71c.016.006.041-.01.081-.052a.3.3 0 01.071-.06c.007 0 .02-.009.029-.02a.495.495 0 01.106-.06c.088-.042.094-.043.323-.047.128-.002.24-.008.247-.012a.625.625 0 01.092-.028.723.723 0 00.108-.035c.043-.022.069-.006.085.054.019.07.097.18.131.186.056.008.16-.052.248-.143.075-.077.1-.094.17-.114.044-.013.093-.028.108-.034a.396.396 0 01.226-.027.69.69 0 01.141.024.456.456 0 00.108.021c.076.009.222.053.288.087a.154.154 0 00.06.015c.018 0 .043.011.056.026a.503.503 0 00.19.094c.014 0 .082.028.152.062.11.053.132.06.16.047.025-.011.034-.026.034-.056 0-.056.03-.063.087-.021a.24.24 0 00.055.035c.005 0 .078.045.163.1.084.055.18.111.213.125a.23.23 0 01.07.04c.005.008.019.015.03.015.022 0 .138.048.21.087.02.01.05.02.067.02.018 0 .058.014.09.033.037.02.077.032.109.03a.831.831 0 01.232.031c.026.015.096.002.122-.023.042-.04-.041-.097-.25-.173a4.233 4.233 0 01-.454-.193c-.251-.131-.337-.18-.372-.214a1.853 1.853 0 00-.225-.159.489.489 0 01-.087-.071.843.843 0 00-.108-.09 2.85 2.85 0 01-.346-.326 5.56 5.56 0 01-.35-.387.23.23 0 00-.038-.054c-.075-.09-.098-.123-.098-.143 0-.01-.009-.026-.02-.035a.33.33 0 01-.075-.147c0-.014-.006-.03-.014-.034-.007-.004-.013-.016-.013-.026a.8.8 0 00-.129-.198c-.047-.057-.083-.062-.15-.022-.053.033-.072.1-.048.166.008.023.015.05.015.06 0 .01.023.046.052.08a.708.708 0 01.068.094l.054.093.063.105c.015.025.054.076.086.113.032.038.07.091.085.119.015.027.032.05.04.05.006 0 .021.018.033.04a.964.964 0 00.119.138c.054.054.158.163.232.242.074.079.158.158.186.177.029.018.052.041.052.05 0 .01.018.03.04.046.09.063.03.084-.082.028a.63.63 0 00-.096-.04c-.015 0-.127-.074-.241-.159a1.756 1.756 0 00-.257-.162 3.32 3.32 0 00-.501-.236.878.878 0 00-.313-.097c-.02 0-.04-.006-.045-.012a1.118 1.118 0 00-.258-.031c-.27.014-.385.03-.457.062a.475.475 0 01-.098.034c-.01 0-.026.011-.034.025-.007.015-.036.033-.064.042a.662.662 0 00-.252.172c-.1.12-.145.182-.178.25a.392.392 0 01-.061.091c-.015.013-.027.035-.027.048 0 .013-.006.027-.013.032-.007.004-.017.036-.021.07a.334.334 0 01-.021.087c-.02.036-.015.086.01.095zM17.91 15.36c-.036 0-.168.064-.176.086a.4.4 0 00.005.183.223.223 0 00.063.091c.041.036.057.041.097.035.055-.009.118-.064.145-.126.016-.038.016-.053-.008-.127-.026-.083-.078-.142-.126-.142zM16.974 14.252c.135 0 .186-.019.259-.097.062-.066.113-.198.09-.234-.007-.011-.051-.028-.098-.038-.073-.014-.091-.014-.124.003a.179.179 0 01-.057.02c-.075 0-.216.138-.233.23-.008.043-.005.056.021.084.028.029.042.032.142.032zM18.043 14.961c-.019-.021-.034-.047-.034-.057 0-.02-.075-.088-.154-.14-.055-.035-.082-.04-.32-.058-.14-.01-.142-.01-.179.024a.169.169 0 00-.045.078c-.005.025-.014.048-.02.052-.007.004-.013.02-.013.034 0 .015-.01.056-.021.092a.305.305 0 00-.015.123c.008.066.046.262.056.287.015.038.066.012.168-.084a.575.575 0 00.135-.165c.016-.035.038-.068.05-.073a.22.22 0 01.085.007c.075.018.216.017.238 0a.118.118 0 01.047-.017c.051-.007.061-.056.021-.103zM24.335 27.417c.046.018.053.017.19-.027a1.92 1.92 0 00.477-.22c.115-.075.382-.361.444-.475l.047-.085c.124-.216.228-.58.227-.792-.001-.086-.005-.1-.033-.123-.044-.035-.06-.027-.077.043-.021.082-.13.296-.184.361-.025.03-.08.09-.123.133a.463.463 0 00-.077.092c0 .007-.032.032-.072.056a6.965 6.965 0 00-.245.157.514.514 0 01-.144.093c-.051 0-.28.309-.293.396a.195.195 0 01-.024.071.643.643 0 00-.076.162.305.305 0 01-.047.092c-.029.024-.024.052.01.066zM36.515 20.236c0 .03.099.128.156.154l.056.024a.82.82 0 00.048-.019c.085-.035.122-.11.087-.177a1.06 1.06 0 00-.209-.196 4.224 4.224 0 01-.18-.13 1.733 1.733 0 00-.216-.141 1.452 1.452 0 00-.23-.08c-.047-.008-.085.03-.074.073.01.042.13.16.232.228.046.03.091.065.1.076.01.01.023.02.03.02.024 0 .2.148.2.168zM14.449 21.665c.086-.045.114-.093.12-.204.005-.115-.02-.173-.112-.257-.054-.049-.07-.056-.125-.056-.077 0-.177.06-.251.15l-.048.057.012.107c.013.12.02.128.13.189.098.053.19.058.274.014zM18.207 19.54c.048-.065 0-.135-.111-.164a.979.979 0 00-.285-.037.246.246 0 01-.053.008l-.365-.013a6.71 6.71 0 01-.434-.024 2.33 2.33 0 01-.345-.085.532.532 0 00-.054-.024.348.348 0 01-.054-.027 2.786 2.786 0 00-.156-.079.853.853 0 01-.16-.093c-.015-.015-.038-.028-.05-.028-.028 0-.08.066-.08.1a.26.26 0 01-.017.068c-.012.033-.012.052 0 .075.008.017.019.063.024.104a.971.971 0 00.128.299c.022.022.014.057-.02.098a.19.19 0 00-.035.049.224.224 0 01-.033.053.175.175 0 00-.034.058c0 .009-.01.043-.021.077-.047.134-.014.313.069.377.02.016.048.029.062.029.037 0 .074-.043.085-.099a.387.387 0 01.049-.11c.048-.076.237-.257.3-.287.13-.064.19-.09.203-.09a.363.363 0 00.081-.041c.077-.047.126-.064.316-.112.074-.018.165-.043.202-.054a.66.66 0 01.16-.02.44.44 0 00.116-.012.45.45 0 01.131 0c.328.03.362.03.381.004zM23.006 23.817c.02 0 .092-.07.101-.098a.818.818 0 01.026-.07c.041-.094.063-.19.08-.362.02-.195.017-.564-.006-.606a.15.15 0 01-.013-.06c0-.02-.006-.06-.014-.09a69.53 69.53 0 01-.029-.108.926.926 0 00-.024-.08 1.553 1.553 0 00-.11-.275 1.087 1.087 0 01-.066-.144c0-.008-.013-.02-.027-.028-.015-.008-.028-.023-.028-.033 0-.01-.015-.037-.034-.058a.178.178 0 01-.033-.05.7.7 0 00-.148-.163.19.19 0 01-.049-.03.242.242 0 00-.102-.033c-.061-.008-.08-.005-.105.015-.028.023-.03.03-.015.072.019.054.069.117.194.244.05.05.09.099.09.108 0 .009.014.03.032.046a1.056 1.056 0 01.192.442c.02.077.042.147.049.155a.282.282 0 01.024.08l.034.172c.038.185.047.31.031.473a.712.712 0 01-.097.332.12.12 0 00.015.125c.012.013.026.024.032.024zM15.245 21.255c.05-.1.05-.1.05-.275a.621.621 0 00-.016-.194.194.194 0 01-.025-.065.428.428 0 00-.106-.194.767.767 0 00-.307-.153c-.181-.034-.484.04-.567.139-.01.011-.026.021-.035.021-.02 0-.116.117-.116.14 0 .01-.008.024-.018.032-.032.027-.033.089-.002.144.033.06.112.104.183.102.211-.003.27-.008.314-.027.071-.03.087-.012.098.107.012.12.043.219.075.236a.11.11 0 01.039.053c.008.022.023.04.033.04.01 0 .033.015.05.034a.2.2 0 00.074.046c.111.034.194-.022.276-.186zM11.68 12.873c.04.04.054.04.122.001.07-.038.092-.116.056-.19-.042-.089-.137-.09-.2-.003-.036.05-.025.145.023.192z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M15.409 20.328c.08-.093.236-.247.25-.247.009 0 .033-.018.054-.04.022-.022.047-.04.057-.04.026 0 .259-.197.269-.228.01-.032-.029-.097-.052-.089l-.138.043a.73.73 0 00-.17.073.539.539 0 01-.085.051c-.021.01-.09.059-.151.11a1.192 1.192 0 01-.122.093.639.639 0 00-.17.159c-.037.052-.04.062-.026.103.008.024.03.057.05.072.066.05.16.027.234-.06zM11.146 14.099c0 .095.05.291.088.344.01.016.02.04.02.055s.01.046.021.068a.955.955 0 01.049.124c.02.065.04.098.089.143.076.072.12.077.163.02.028-.037.028-.042.009-.11a41.721 41.721 0 01-.086-.298 1.353 1.353 0 01-.076-.52c0-.239.017-.373.063-.507.016-.044.033-.1.038-.126a.347.347 0 01.039-.094.195.195 0 00.03-.083c0-.032-.006-.037-.04-.037-.051 0-.1.04-.16.132-.13.194-.18.31-.19.428a.244.244 0 01-.02.09 1.474 1.474 0 00-.037.37zM21.69 20.828c.025 0 .096-.065.096-.089a.48.48 0 00-.08-.107.734.734 0 01-.082-.1c0-.008-.106-.09-.16-.124a2.717 2.717 0 01-.097-.068c-.041-.03-.1-.069-.132-.086a.267.267 0 01-.078-.061c-.015-.023-.038-.032-.098-.039a.467.467 0 01-.105-.021c-.045-.022-.132.003-.155.044-.018.032-.018.042 0 .091.02.055.047.076.175.133l.066.031a.215.215 0 00.063.022c.01 0 .041.015.069.034a.214.214 0 00.066.033c.009 0 .027.012.04.027.014.014.033.026.041.026.01 0 .051.03.094.067a.408.408 0 00.092.067c.008 0 .048.027.089.06.04.033.083.06.095.06zM11.761 14.893a.108.108 0 00-.054.02.108.108 0 01-.047.02.187.187 0 00-.067.04c-.026.022-.057.04-.07.04a.301.301 0 00-.092.046.413.413 0 01-.117.055c-.089.016-.127.116-.08.206.011.022.024.04.028.04.02 0 .16-.045.192-.061a.185.185 0 01.071-.02c.019 0 .048-.01.066-.021a.643.643 0 01.115-.05c.125-.044.254-.122.29-.174.037-.054.032-.082-.028-.15-.036-.04-.047-.045-.083-.037a.23.23 0 00-.069.027.116.116 0 01-.055.019zM15.023 22.409c.008-.061.005-.073-.038-.138a.49.49 0 00-.071-.09c-.034-.025-.198-.025-.248 0a.329.329 0 00-.124.139c-.012.03-.018.031-.077.025-.057-.006-.071-.015-.131-.082a.37.37 0 01-.098-.178 1.284 1.284 0 01-.034-.137c-.002-.022-.013-.034-.032-.037-.069-.01-.084.158-.032.35.029.11.04.129.129.237-.081-.016-.148-.02-.167-.01a.327.327 0 01-.09.02.499.499 0 00-.274.155c-.049.067-.023.087.06.045a.377.377 0 01.109-.037l.084-.01a.428.428 0 01.219.042c.056.032.072.076.045.128a.41.41 0 00-.047.183c.003.054.07.178.112.204.036.023.145.025.204.004.044-.016.14-.1.171-.152.038-.06.04-.167.006-.263a.486.486 0 00-.042-.086c.204-.005.34-.12.366-.312zM29.044 22.546a.11.11 0 00.012-.04c0-.073.165-.473.204-.497a.426.426 0 00.06-.078 1.77 1.77 0 01.155-.185c.106-.11.11-.117.099-.16a.093.093 0 00-.05-.062c-.032-.015-.046-.014-.12.013-.126.046-.183.104-.327.332-.066.104-.075.12-.075.138 0 .01-.009.026-.02.035a.063.063 0 00-.02.043.309.309 0 01-.048.098.296.296 0 00-.047.106.22.22 0 01-.016.07 3.1 3.1 0 00-.08.37c-.01.051-.012.193-.007.387.008.316.023.414.081.524a.187.187 0 01.022.063c0 .012.018.04.04.061.021.022.05.04.063.04.034 0 .073-.04.073-.076 0-.03-.04-.13-.07-.178a.288.288 0 01-.04-.174.554.554 0 00-.014-.13c-.01-.032-.01-.05.002-.063.01-.011.013-.034.008-.05-.008-.03.017-.21.055-.397a.642.642 0 01.06-.19zM27.926 26.43c.015 0 .04.01.054.021.015.011.04.018.055.016.023-.003.027-.013.026-.07 0-.092-.092-.244-.24-.395a.672.672 0 00-.254-.183 1.52 1.52 0 00-.182-.077.18.18 0 01-.061-.026.841.841 0 00-.122-.059 1.404 1.404 0 01-.122-.055.939.939 0 00-.078-.04c-.06-.028-.287-.233-.287-.26a.222.222 0 00-.046-.067c-.063-.073-.118-.197-.108-.244.004-.022 0-.042-.008-.047-.008-.005-.014-.032-.014-.06 0-.089-.064-.112-.1-.036-.028.057-.027.092.003.242.031.151.079.283.117.326a.208.208 0 01.04.063.91.91 0 00.079.131l.084.125c.076.122.34.402.38.402.008 0 .025.01.038.024a.217.217 0 00.076.042c.03.01.061.026.07.036.008.01.02.018.027.018.006 0 .038.012.071.027.061.029.163.06.259.08.13.027.19.043.202.054.007.007.025.012.04.013zM19.738 4.877c.007 0 .03.02.053.042a.361.361 0 00.096.067c.05.022.13.096.366.335.057.058.068.063.127.063.055 0 .069-.006.099-.04a.129.129 0 00.035-.09c-.001-.062-.02-.097-.082-.145a2.328 2.328 0 00-.336-.245c-.007 0-.02-.01-.03-.021a.465.465 0 00-.1-.062.925.925 0 01-.114-.066.118.118 0 00-.055-.024.206.206 0 01-.067-.022.13.13 0 00-.075-.013c-.035.008-.075.042-.075.062 0 .016.141.16.158.16zM37.682 21.138a.152.152 0 00-.118.027c-.115.073-.142.124-.148.277-.002.079.001.09.038.133a.24.24 0 00.132.089c.062.022.077.022.161-.003a.342.342 0 00.127-.072c.055-.05.056-.052.054-.143-.002-.116-.02-.157-.109-.237-.06-.055-.081-.066-.137-.07zM38.328 22.722a.013.013 0 00.014-.013.013.013 0 00-.014-.013.014.014 0 00-.013.013c0 .007.006.013.014.013zM31.023 20.127c-.119.01-.138.016-.22.074a1.226 1.226 0 01-.092.058c-.115.063-.352.255-.369.299-.007.018-.024.035-.038.039-.014.003-.044.035-.068.071-.04.063-.042.067-.022.105.011.021.029.042.038.046.04.016.07.006.11-.04a.295.295 0 01.084-.064.686.686 0 00.118-.08.713.713 0 01.115-.077.304.304 0 00.064-.038.404.404 0 01.095-.046.405.405 0 00.095-.047.517.517 0 01.111-.052c.14-.05.186-.131.123-.217l-.029-.04-.115.01zM27.635 27.245a.14.14 0 00-.026-.052.733.733 0 01-.062-.141c-.035-.107-.137-.274-.188-.31a.165.165 0 01-.043-.047c-.014-.027-.056-.056-.161-.113a.867.867 0 01-.102-.07 1.428 1.428 0 00-.181-.127 1.069 1.069 0 01-.225-.209 1.38 1.38 0 00-.069-.077.262.262 0 01-.051-.084.196.196 0 00-.04-.07.214.214 0 01-.043-.079.296.296 0 00-.03-.069c-.006-.007-.01-.034-.01-.061 0-.06-.028-.088-.067-.067-.016.009-.028.027-.028.04 0 .015-.007.03-.014.034-.02.013-.016.192.007.3.028.134.083.298.138.414.127.269.139.287.29.442.08.083.147.155.147.16 0 .015.2.158.256.183.027.012.07.035.096.05a.471.471 0 00.108.045.76.76 0 01.104.034c.023.01.065.027.094.037.069.022.157.021.165-.002.003-.01-.01-.046-.03-.082a.336.336 0 01-.035-.08zM24.068 26.44a.85.85 0 01.162-.05.91.91 0 00.352-.106l.224-.113c.103-.051.294-.23.392-.367a2.11 2.11 0 00.216-.334.84.84 0 01.062-.113c.03-.044.046-.088.09-.26.033-.13.035-.183.009-.237-.013-.026-.029-.037-.052-.037-.027 0-.035.008-.043.047-.037.18-.07.273-.12.336a.214.214 0 00-.04.062c0 .037-.313.32-.355.322-.005 0-.066.027-.134.06s-.13.06-.138.06c-.007 0-.069.026-.137.058a36.09 36.09 0 01-.188.088c-.16.074-.394.36-.44.536-.014.052-.008.07.025.08a.338.338 0 00.115-.032zM24.234 25.552c.203-.111.225-.124.27-.164a.173.173 0 01.06-.038.83.83 0 00.135-.12c.065-.066.124-.12.13-.12.04 0 .3-.291.422-.472.17-.25.19-.286.199-.338.017-.11-.015-.15-.099-.123-.035.011-.054.031-.085.09a2.373 2.373 0 01-.17.281l-.097.143a1.008 1.008 0 01-.092.106.336.336 0 00-.06.073c0 .02-.386.395-.442.43a.396.396 0 00-.072.055c-.01.012-.026.021-.036.021a.485.485 0 00-.166.096.187.187 0 01-.057.038c-.019 0-.016.071.003.09.024.024.029.022.157-.048zM27.94 25.538a.655.655 0 00-.196-.153.833.833 0 01-.188-.125 6.207 6.207 0 01-.408-.406.244.244 0 00-.046-.061 2.234 2.234 0 01-.222-.295.728.728 0 01-.061-.095 2.548 2.548 0 01-.085-.165c-.037-.076-.07-.093-.136-.072l-.053.017.005.073c.006.091.04.157.194.367.042.059.093.125.112.148a.176.176 0 01.034.055c0 .017.236.257.252.257.008 0 .071.055.142.121.07.067.152.134.181.149.03.015.094.06.144.098.05.04.131.093.182.119.051.026.1.047.11.047.024 0 .048-.05.039-.08zM36.971 21.425c.06-.005.081-.014.137-.062a.768.768 0 00.097-.101.86.86 0 00.091-.331c-.008-.043.021-.063.054-.037.033.028.206.054.307.046.197-.014.234-.047.221-.198-.006-.075-.015-.1-.048-.14-.092-.11-.15-.15-.318-.215-.1-.04-.417-.04-.456-.002a.066.066 0 01-.04.016c-.013 0-.027.005-.03.012-.005.006-.025.016-.044.02a.495.495 0 00-.176.172 1.061 1.061 0 00-.08.343.62.62 0 00.063.307c.013.02.028.05.033.07.006.024.025.044.055.058a.18.18 0 01.054.035c.005.007.04.01.08.007zM23.755 16.182c-.136.008-.202.03-.228.078a.917.917 0 01-.036.06.25.25 0 00-.03.073c-.026.127-.026.127-.001.155.019.02.034.025.066.018a.456.456 0 01.201-.009c.016.007.069.02.117.03.06.011.13.04.219.088a.697.697 0 01.224.175c.091.101.121.14.171.221a.852.852 0 00.05.074.126.126 0 01.027.044c0 .006.024.05.054.096a.52.52 0 01.054.098c0 .008.01.021.021.03.012.01.032.04.045.066.037.072.112.206.127.224.008.01.045.017.093.017.091 0 .097-.007.099-.106a.142.142 0 00-.03-.101 1.19 1.19 0 01-.146-.23.588.588 0 00-.068-.11c-.01-.01-.02-.024-.02-.033 0-.02-.038-.1-.062-.128a.314.314 0 01-.038-.076.44.44 0 00-.053-.1 1.337 1.337 0 01-.089-.152.7.7 0 00-.116-.167c-.033-.032-.06-.066-.06-.078a.24.24 0 00-.049-.078 3.931 3.931 0 00-.303-.41.097.097 0 01-.028-.057c0-.018-.012-.033-.032-.04a.248.248 0 01-.077-.074.253.253 0 00-.054-.06.685.685 0 01-.092-.098 1.069 1.069 0 00-.125-.128c-.042-.03-.045-.03-.09-.01-.045.022-.046.023-.037.085a.21.21 0 00.033.09.397.397 0 01.042.061.442.442 0 00.094.133c.006 0 .055.064.108.142.109.159.11.182.019.187zM30.15 11.65a.304.304 0 01-.08.028.06.06 0 00-.033.01.312.312 0 01-.067.029.312.312 0 00-.081.04.607.607 0 01-.075.047c-.115.063-.39.326-.442.422-.019.036-.044.068-.056.072-.028.009-.104.124-.174.264-.049.098-.05.104-.028.126.018.018.03.02.047.01.062-.038.399-.093.438-.072a.167.167 0 00.064.013c.041 0 .102.023.171.065.107.065.265.14.339.161a.514.514 0 00.176.018c.157-.01.23-.02.248-.035a.485.485 0 01.097-.056c.13-.052.142-.075.12-.227-.018-.13-.012-.153.039-.153a.2.2 0 00.078-.022c.117-.063.165-.085.185-.085a.725.725 0 00.14-.06.83.83 0 01.134-.06c.01 0 .035-.013.055-.029.03-.023.035-.035.029-.07a.265.265 0 00-.05-.09.213.213 0 01-.04-.063c0-.035-.175-.188-.216-.188-.007 0-.02-.011-.03-.025-.037-.051-.175-.108-.264-.108a.897.897 0 00-.388-.025 3.934 3.934 0 01-.178.024.614.614 0 00-.159.039zM30.458 11.024a.685.685 0 01.29-.077c.049 0 .184-.01.301-.02.227-.02.248-.028.367-.122a.597.597 0 00.17-.314c.013-.092.007-.112-.045-.135a.89.89 0 01-.074-.04c-.056-.033-.239-.046-.346-.025l-.13.026c-.082.016-.276.14-.356.226-.023.025-.06.064-.083.085-.053.052-.115.144-.115.171a.057.057 0 01-.02.039.124.124 0 00-.028.06c-.005.025-.017.053-.028.061-.02.016-.025.068-.01.083.016.016.052.01.107-.018zM25.043 16.84c.009-.054-.005-.09-.123-.324a.183.183 0 01-.02-.06.532.532 0 00-.113-.248.452.452 0 01-.068-.098c-.013-.039-.072-.083-.11-.083a.153.153 0 00-.075.035c-.04.033-.042.041-.035.093a.667.667 0 00.118.238.175.175 0 01.031.062c.005.02.042.068.084.107.041.04.1.11.132.157l.08.12c.013.019.034.042.046.05.031.023.042.013.053-.05zM20.38 5.683c-.031.085-.038.116-.032.14.004.014 0 .034-.007.043-.019.023.013.274.047.364.028.073.134.187.184.197.088.017.115.01.152-.037.02-.026.044-.047.053-.047.049 0 .15-.218.167-.363a.132.132 0 01.03-.07c.02-.018.03-.019.078-.002.094.033.274.04.348.016.1-.034.112-.043.138-.11.024-.06.024-.062-.007-.123a6.803 6.803 0 01-.046-.093.203.203 0 00-.053-.06 1.406 1.406 0 01-.076-.062.892.892 0 00-.247-.119 1.103 1.103 0 00-.204-.017l-.154-.003-.109.055a.458.458 0 00-.263.29zM35.92 9.394a.273.273 0 00-.08.187c0 .053.007.067.06.118.067.066.095.071.176.03.09-.045.123-.096.125-.195.001-.08 0-.085-.051-.13-.046-.041-.061-.047-.124-.047-.061 0-.078.006-.107.037zM31.784 13.649a.713.713 0 00.082-.025c.034-.015.295-.053.42-.062a.966.966 0 01.19.01l.17.026a.25.25 0 01.136.056c.032.025.093.07.136.097a.356.356 0 01.078.061c0 .005.017.031.037.057.02.027.053.073.071.104.019.03.046.06.061.066a.152.152 0 00.129-.007.89.89 0 01.062-.032c.02-.008.036-.038.05-.091.038-.129.026-.277-.024-.337a1.038 1.038 0 00-.306-.337l-.09-.048c-.017-.01-.035-.025-.039-.035A.663.663 0 0133 12.99c.062-.15.102-.338.087-.414a.11.11 0 01.005-.06.05.05 0 000-.048.611.611 0 01-.03-.08.192.192 0 00-.034-.072.055.055 0 01-.018-.037c0-.031-.093-.115-.148-.133a.405.405 0 00-.104-.015c-.046 0-.062.006-.074.028a.989.989 0 00-.018.217c-.004.194-.014.238-.072.315a1.094 1.094 0 00-.065.111.447.447 0 01-.122.144 5.115 5.115 0 00-.108.09c-.032.027-.14.096-.291.184l-.11.067a.237.237 0 01-.059.031c-.01 0-.102.042-.24.109a.127.127 0 01-.046.011.322.322 0 00-.098.067.393.393 0 01-.09.067.78.78 0 00-.193.083.653.653 0 01-.117.05c-.01 0-.035.018-.056.04-.021.022-.046.04-.054.04-.009 0-.03.015-.047.034-.018.018-.041.033-.052.033-.033 0-.07.041-.07.078 0 .09.108.122.212.063a.578.578 0 01.088-.042.171.171 0 00.052-.027c.077-.066.395-.21.548-.248l.108-.027zM36 10.111c-.061-.008-.063-.007-.108.05-.072.089-.113.19-.1.248.013.06.055.133.092.162a.235.235 0 00.18.022.441.441 0 00.16-.147c.05-.115.051-.117.031-.14a.476.476 0 01-.047-.075c-.032-.062-.11-.107-.208-.12zM25.728 17.446l.029-.058-.03-.049c-.018-.03-.026-.06-.02-.076a.16.16 0 00-.006-.075 2.418 2.418 0 01-.037-.162c-.04-.205-.045-.222-.065-.268a2.14 2.14 0 01-.036-.09.13.13 0 00-.059-.064.721.721 0 01-.09-.057c-.062-.048-.145-.085-.163-.073-.015.009-.005.145.012.172.005.008.02.053.033.1l.045.154c.06.2.102.405.113.56 0 .007.017.03.036.05.026.028.047.037.088.037.07 0 .113-.03.15-.1zM34.197 10.973a.695.695 0 00.058.405c.013.03.035.083.047.12a.438.438 0 00.034.08c.045.055.078.353.045.414a.894.894 0 00-.03.066 1.286 1.286 0 01-.042.09c-.027.051-.033.092-.016.11.005.005.03.006.056.002.05-.008.15-.092.15-.125 0-.01.02-.038.044-.061a.46.46 0 00.069-.089c.098-.178.172-.33.172-.353 0-.015.01-.07.021-.12.04-.173.06-.381.043-.447-.048-.204-.084-.317-.111-.36-.033-.051-.2-.227-.217-.227a.175.175 0 01-.045-.026c-.094-.065-.16-.038-.147.06a.524.524 0 01-.062.25.82.82 0 00-.07.21zM24.581 10.761c-.003.01-.011.068-.018.13a.593.593 0 01-.09.267.626.626 0 00-.08.344v.156l-.082.014c-.09.015-.217.086-.231.13-.006.018.004.038.033.068a.209.209 0 01.042.052.54.54 0 00.049.083.78.78 0 01.066.124c.046.13.144.283.262.408a.773.773 0 00.253.17c.03.007.066.018.081.025a.277.277 0 00.075.016c.089.007.345-.005.358-.017.007-.007.033-.012.058-.012a.46.46 0 00.216-.126c.013-.022.152-.179.227-.256a.28.28 0 01.307-.064c.114.052.136.07.25.215.097.121.204.197.3.212.032.005.06.014.065.02.004.007.022.012.04.012.017 0 .035.005.038.01a.505.505 0 00.14.008c.12-.003.16-.009.295-.04.07-.015.24-.136.31-.219.068-.082.082-.106.238-.406.053-.103.112-.202.13-.22.018-.02.033-.044.033-.056 0-.011-.032-.044-.071-.073-.062-.046-.082-.053-.15-.055-.1-.004-.109-.01-.097-.061.03-.13.03-.164.006-.266-.035-.147-.052-.192-.094-.254a.363.363 0 01-.068-.238c0-.118-.014-.146-.064-.13l-.157.038a.652.652 0 00-.217.088.48.48 0 00-.217.247c-.054.121-.062.129-.092.09-.03-.038-.033-.152-.004-.22a.253.253 0 00.02-.073c0-.015.012-.049.026-.076a.626.626 0 00.048-.305 2.985 2.985 0 01-.025-.39c-.006-.225.005-.211-.172-.213-.099 0-.122.004-.153.027l-.036.028-.02-.047a.286.286 0 01-.02-.065.185.185 0 00-.041-.063.186.186 0 01-.04-.06c0-.019-.057-.061-.132-.099a.243.243 0 01-.08-.061.11.11 0 00-.069-.042c-.044-.008-.052-.004-.1.046a.23.23 0 01-.065.055c-.023 0-.136.084-.136.101 0 .01-.01.024-.021.033a.33.33 0 00-.074.148c0 .036-.016.039-.09.017a.613.613 0 00-.176-.016l-.106.004-.002.14a4.39 4.39 0 01-.024.338c-.024.214-.018.268.046.45.029.082.054.21.054.274a.136.136 0 01-.026.074l-.026.031-.015-.04a.252.252 0 00-.033-.06.244.244 0 01-.033-.065c-.015-.044-.029-.061-.107-.138a.443.443 0 00-.212-.132c-.122-.044-.289-.063-.3-.035zM25.856 6.419a.437.437 0 00.138.017c.134 0 .18-.02.298-.13.07-.065.085-.089.104-.156l.035-.12c.016-.048-.006-.13-.05-.19a.177.177 0 01-.032-.056c0-.007-.006-.017-.014-.022-.016-.01-.067.03-.067.052 0 .014-.013.03-.098.115-.045.046-.139.072-.194.054a.835.835 0 00-.077-.02.12.12 0 01-.058-.03.743.743 0 01-.105-.14c-.005-.013-.021-.024-.037-.024-.042 0-.127.185-.115.25a.967.967 0 00.084.24.754.754 0 00.188.16zM25.092 8.301c-.021-.013-.033-.01-.07.017-.12.09-.146.146-.127.273.011.075.092.172.16.192.05.015.146.007.196-.016.087-.041.138-.263.075-.331a.473.473 0 00-.18-.12.123.123 0 01-.054-.015zM26.12 8.457c-.043-.022-.153-.013-.212.016a.264.264 0 00-.08.08c-.038.06-.038.063-.025.157.018.12.04.165.098.195a.222.222 0 00.125.02c.11-.007.163-.04.185-.115l.03-.099c.025-.075-.041-.213-.121-.254zM27.02 8.323c-.096-.036-.162-.02-.255.065l-.077.07v.083c0 .112.03.184.093.216.119.062.265.018.329-.1.042-.077.045-.11.018-.196-.03-.096-.043-.113-.108-.138zM26.474 7.722c.02-.03.058-.116.084-.191.043-.126.046-.144.033-.2a.513.513 0 00-.026-.084.117.117 0 01-.012-.044c0-.052-.188-.269-.274-.315-.046-.025-.123-.03-.267-.02a.324.324 0 01-.11-.005c-.013-.007-.039-.007-.062 0a.823.823 0 01-.076.02c-.062.012-.245.188-.285.274a.517.517 0 01-.021.04c-.05.084-.05.255.002.362.02.04.039.086.044.103.014.048.152.19.225.23.035.02.09.046.122.056.032.011.077.03.1.041.054.028.072.027.157-.012a.38.38 0 01.1-.033c.035 0 .22-.153.266-.222zM26.412 17.553a.993.993 0 01.065-.014c.062-.011.073-.032.097-.19.039-.248.045-.277.079-.375a.707.707 0 00.034-.123c0-.014.006-.035.013-.048.038-.066.1-.31.084-.326-.02-.02-.165.043-.24.104-.094.075-.1.084-.14.239a4.85 4.85 0 01-.043.16.323.323 0 00-.012.08c0 .056-.028.19-.057.276l-.026.076.049.066c.027.037.056.07.065.073a.057.057 0 00.032.002zM27.423 16.026c-.052 0-.122.051-.144.105a.24.24 0 01-.048.074.138.138 0 00-.036.062.113.113 0 01-.028.054.066.066 0 00-.02.044.404.404 0 01-.04.108.619.619 0 00-.04.094.335.335 0 01-.027.066.268.268 0 00-.027.076c0 .013-.007.027-.014.031-.008.005-.014.038-.014.074 0 .055.005.066.024.066.03 0 .085-.036.085-.056 0-.008.064-.098.142-.2.078-.101.142-.19.142-.197 0-.007.018-.032.04-.057a.699.699 0 00.122-.231c0-.035-.08-.113-.117-.113zM27.356 14.646c.013-.01.05-.021.083-.026.033-.005.064-.014.068-.021.005-.007.02-.013.036-.013.032 0 .242-.204.276-.269.022-.041.022-.043-.008-.067a.109.109 0 00-.053-.024.483.483 0 01-.192-.1 4.488 4.488 0 00-.09-.09.276.276 0 01-.057-.067.231.231 0 00-.04-.06.371.371 0 01-.052-.09c-.021-.065-.16-.26-.183-.26a.198.198 0 01-.055-.031.982.982 0 00-.14-.073.408.408 0 00-.207-.043c-.059 0-.11.006-.115.014-.005.007-.023.013-.04.013-.085 0-.243.092-.337.197-.021.024-.046.043-.055.043-.016 0-.075.056-.141.133l-.04.046-.094-.093c-.13-.128-.2-.188-.245-.211a.216.216 0 01-.056-.04c-.017-.02-.102-.05-.251-.084-.09-.021-.198-.014-.247.017a.127.127 0 01-.055.019.065.065 0 00-.037.011.253.253 0 01-.064.028c-.028.009-.057.028-.065.042-.008.014-.023.025-.034.025-.01 0-.03.017-.042.037a2.052 2.052 0 00-.122.204.866.866 0 01-.228.289c-.1.092-.127.109-.19.123-.127.028-.127.065-.002.194l.098.101a.274.274 0 00.064.05c.08.039.129.055.172.059.04.003.048.01.051.037.004.034-.004.05-.068.145a.337.337 0 00-.046.099.162.162 0 01-.026.064c-.03.033-.046.194-.033.32a.619.619 0 01.005.122.338.338 0 00.022.098.64.64 0 01.028.117c0 .015.016.044.036.065.03.031.047.037.105.037.039 0 .075-.005.083-.011a.263.263 0 01.065-.029.414.414 0 00.182-.12c.06-.075.089-.046.102.1.004.05.014.098.022.105a.066.066 0 01.014.041c0 .015.011.046.025.069a.4.4 0 01.036.073.622.622 0 00.118.186c.007 0 .07.055.138.123s.156.152.194.186c.04.034.07.067.07.075 0 .007.011.02.023.031.013.01.044.051.07.092.026.04.072.099.102.13.03.03.066.056.08.056.03 0 .147-.105.173-.156.055-.108.298-.377.512-.567.055-.049.165-.249.165-.3 0-.014.006-.032.014-.04.008-.007.016-.05.018-.095.003-.074.033-.149.06-.149.005 0 .03.023.057.05a.419.419 0 00.102.075l.08.04c.015.007.058.02.095.029.059.013.076.012.125-.009.051-.021.058-.029.058-.068a.35.35 0 01.015-.09 1.71 1.71 0 00.048-.314c.007-.093-.017-.268-.038-.281-.007-.004-.012-.024-.012-.045 0-.02-.01-.045-.021-.055a.146.146 0 01-.034-.045.784.784 0 00-.071-.12c-.025-.035-.025-.04-.004-.054zM34.368 7.877a.214.214 0 00-.08.042.078.078 0 01-.048.024c-.028 0-.156.089-.221.153-.099.097-.169.221-.169.299a.06.06 0 01-.015.038c-.019.019-.023.246-.005.253.008.002.047-.017.088-.044.073-.047.077-.048.23-.052.086-.002.169-.009.185-.015.05-.02.216-.156.257-.211.067-.093.129-.154.156-.154a.134.134 0 00.052-.013c.035-.019.153.01.277.068.03.014.063.025.073.025.03 0 .18.097.24.157a.296.296 0 00.07.057c.023 0 .247.246.247.272 0 .005.025.046.056.092a.56.56 0 01.106.282c0 .031.005.06.01.065.02.02.056.007.063-.022a.539.539 0 00-.011-.139.554.554 0 01-.012-.133.044.044 0 00-.013-.042c-.014-.01-.018-.033-.013-.074.004-.035 0-.061-.008-.067-.009-.005-.016-.023-.016-.04 0-.018-.006-.036-.013-.041-.008-.005-.014-.02-.014-.032a.062.062 0 00-.021-.042.243.243 0 01-.044-.06.936.936 0 00-.18-.233 2.493 2.493 0 00-.327-.286 6.005 6.005 0 01-.137-.063.658.658 0 00-.13-.051.3.3 0 01-.082-.029c-.053-.026-.082-.029-.26-.029a.876.876 0 00-.216.015.301.301 0 01-.075.03zM24.83 9.498c-.043.077-.045.099-.016.187.024.071.06.117.113.145.02.01.068.018.109.02.067 0 .08-.004.124-.046a.195.195 0 00.066-.121c.017-.084.008-.16-.024-.196a.274.274 0 01-.036-.053.16.16 0 00-.064-.054c-.04-.02-.06-.021-.108-.01-.077.016-.12.05-.164.128z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M25.936 13.318c.037.005.103.007.146.005.096-.004.144-.034.206-.13a.227.227 0 00.047-.156.616.616 0 00-.014-.189 20.974 20.974 0 01-.066-.05c-.06-.047-.09-.052-.244-.041a.585.585 0 01-.079-.007c-.044-.006-.073 0-.128.025-.066.031-.073.038-.095.109a.373.373 0 00-.002.249c.035.118.098.169.23.185zM25.306 1.376c.023.07.09.165.126.179.016.006.041.024.055.04a.09.09 0 00.056.027c.017 0 .045.012.062.027.075.06.104.028.1-.113-.01-.255-.065-.386-.218-.509-.072-.058-.087-.065-.154-.068a1.527 1.527 0 01-.102-.006c-.02-.003-.028.005-.031.034a.864.864 0 00.065.289c.013.025.032.07.041.1zM24.02 1.9c0 .023.137.183.173.201.02.01.064.041.097.068.034.028.08.06.102.071.048.026.049.026.073.01.025-.015.028-.314.003-.337a.073.073 0 01-.015-.046c0-.016-.006-.033-.014-.038-.007-.004-.013-.021-.013-.038a.457.457 0 00-.088-.208c-.019-.02-.034-.044-.034-.054a.522.522 0 00-.175-.16.315.315 0 01-.079-.026l-.057-.026-.022.041a.422.422 0 00-.026.139.513.513 0 01-.012.11c-.014.022.032.205.06.245a.15.15 0 01.027.048zM25.63 2.02c0-.016-.024-.04-.194-.185-.052-.045-.161-.086-.187-.07-.027.016 0 .224.056.429.016.057.157.216.192.216a.63.63 0 01.126.053c.057.03.11.053.117.053.027 0 .029-.043.007-.15a3.258 3.258 0 01-.03-.163.19.19 0 00-.03-.08c-.03-.037-.056-.083-.056-.103z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M23.038 2.41c.017 0 .054.01.083.025.03.013.087.035.128.048l.102.035c.079.033.295.05.31.025.005-.007.019-.013.03-.013.012 0 .042-.018.068-.04.025-.022.057-.04.07-.04.012 0 .037-.01.053-.021.025-.017.039-.018.088-.004a.869.869 0 00.07.017.983.983 0 01.16.049.118.118 0 00.045.012c.011 0 .046.011.078.025.03.014.117.05.192.082.074.032.15.073.169.09.019.018.071.057.117.088.134.089.21.145.277.205a.389.389 0 00.072.057c.021 0 .463.458.489.507a.468.468 0 00.06.086c.018.02.042.033.054.03.029-.005.035-.086.01-.114a.388.388 0 01-.047-.082.3.3 0 00-.056-.086c-.015-.014-.028-.033-.028-.044 0-.01-.01-.021-.021-.026-.012-.004-.03-.026-.043-.05a.339.339 0 00-.048-.068l-.152-.153a4.367 4.367 0 00-.195-.187c-.087-.074-.09-.11-.008-.12l.054-.007.004-.104c.004-.1-.035-.29-.066-.322-.007-.007-.013-.025-.013-.04 0-.036-.144-.2-.181-.205a.118.118 0 01-.049-.022.166.166 0 00-.054-.026.446.446 0 01-.066-.025c-.047-.023-.074.018-.063.097l.019.168c.01.105.041.184.114.29.048.07-.014.08-.099.015a.839.839 0 00-.081-.047 1.736 1.736 0 00-.311-.141 1.331 1.331 0 01-.116-.047.46.46 0 00-.112-.033c-.031-.005-.06-.013-.065-.02-.004-.006-.024-.011-.046-.011-.021 0-.043-.006-.047-.014-.005-.007-.024-.013-.043-.013-.02 0-.051-.016-.073-.037a.713.713 0 00-.211-.146c-.087-.04-.264-.073-.292-.055a.152.152 0 01-.061.011.542.542 0 00-.258.132c-.052.05-.111.149-.111.183 0 .03.066.086.1.086zM25.765.951a.595.595 0 01.014.124c0 .07.03.262.057.363.007.026.009.057.005.069-.005.01 0 .037.012.058.03.057.08.499.067.587a.239.239 0 00.01.093c.013.036.018.13.016.308-.001.228.001.258.021.27.037.02.069.015.084-.013.008-.015.017-.133.02-.263.006-.322.02-.579.034-.611.006-.015.02-.099.032-.187.02-.157.034-.234.062-.353.029-.123.055-.359.057-.52.003-.159-.013-.273-.046-.343a.163.163 0 01-.005-.079.14.14 0 00-.012-.086.189.189 0 01-.02-.074c0-.02-.021-.07-.047-.112a.38.38 0 01-.048-.096c0-.027-.075-.096-.093-.085a.033.033 0 00-.015.025.72.72 0 01-.054.12.579.579 0 00-.054.126.453.453 0 01-.027.097.59.59 0 00-.031.149.248.248 0 01-.013.085c-.006.006-.01.03-.01.056a.183.183 0 01-.014.07c-.01.019-.01.043 0 .08.011.04.011.06 0 .073-.01.013-.011.033-.002.07zM20.954 7.689c.117 0 .127-.001.213-.049a.9.9 0 00.297-.304c.061-.136.085-.334.048-.406-.011-.022-.028-.033-.05-.033-.029 0-.034.006-.037.046a.472.472 0 01-.063.207.717.717 0 00-.042.066.274.274 0 01-.158.1c-.026 0-.046-.013-.076-.052a.595.595 0 00-.09-.094c-.047-.036-.061-.04-.15-.04-.114 0-.147.019-.202.115-.04.071-.049.19-.015.218a.11.11 0 01.027.053c.01.04.051.084.13.139.04.029.061.033.168.034zM21.41 6.143h-.086c-.091 0-.113.01-.187.082-.062.06-.08.126-.068.238.012.104.02.118.109.183.057.042.065.044.142.036a.262.262 0 00.102-.027c.012-.01.03-.019.038-.019.03 0 .084-.042.104-.08a.356.356 0 00.02-.136v-.098l-.174-.18zM21.523 8.793c-.012-.027-.027-.05-.033-.05-.006 0-.027-.022-.045-.05a1.49 1.49 0 00-.401-.36.857.857 0 01-.093-.05c-.066-.045-.273-.067-.364-.04a.256.256 0 00-.095.048.255.255 0 01-.06.046.132.132 0 00-.05.052l-.032.066c-.024.05-.01.08.042.095a.46.46 0 01.077.03c.016.01.04.017.052.017.043 0 .253.13.365.227.197.169.44.43.44.474 0 .01.01.023.02.028.012.004.03.026.042.05.025.052.05.093.07.117.009.01.037.076.062.145.025.07.069.186.097.26.027.073.068.21.09.306.02.095.044.192.052.214a.35.35 0 01.014.092c0 .125.058.441.096.524a.33.33 0 01.025.07c0 .016.006.027.068.147a.71.71 0 00.075.12c.017.019.04.056.052.084.011.027.028.05.036.05.009 0 .047.027.085.06.038.033.076.06.083.06a.557.557 0 00.313.123c.053-.01.14.089.18.205.034.099.12.259.137.259.006 0 .027.027.047.06s.042.06.05.06.04.02.07.043c.031.024.069.05.084.06.071.043.22.13.25.146.026.014.084.018.232.015.189-.004.199-.006.253-.041.044-.029.057-.045.057-.073 0-.049-.014-.067-.069-.094a.153.153 0 01-.06-.052.209.209 0 00-.043-.053.45.45 0 01-.065-.14.595.595 0 01-.032-.273.644.644 0 01.027-.205c.012-.026.03-.068.038-.094.038-.107.066-.151.187-.295a.614.614 0 01.118-.116c.019-.008.034-.021.034-.028 0-.008.026-.04.058-.073a.652.652 0 00.091-.124.78.78 0 01.064-.101.304.304 0 00.045-.094.272.272 0 01.027-.07c.016-.02.004-.527-.012-.543-.017-.016-.227-.02-.276-.005-.042.013-.04.016-.061-.098-.01-.047-.01-.082-.001-.098.009-.016.006-.043-.008-.085a.401.401 0 01-.022-.105c0-.065.068-.3.097-.337a.114.114 0 00.025-.05c0-.01.018-.027.04-.039.023-.011.041-.025.041-.03 0-.033-.019-.07-.035-.07a.106.106 0 01-.044-.015c-.02-.012-.048-.012-.116-.001a.396.396 0 01-.11.007.042.042 0 00-.037.006.475.475 0 01-.08.035.253.253 0 00-.079.042.07.07 0 01-.047.02c-.035 0-.184.138-.217.201-.035.067-.075.043-.116-.071a.43.43 0 00-.082-.117.284.284 0 01-.065-.086c0-.01-.007-.023-.014-.027-.007-.005-.014-.026-.014-.048 0-.022-.008-.043-.019-.047-.024-.01-.095.027-.154.077a.177.177 0 01-.059.038c-.036 0-.24.187-.274.252a.184.184 0 01-.053.058.112.112 0 00-.042.057.331.331 0 01-.042.084.194.194 0 00-.034.069c0 .01-.01.047-.021.08a.849.849 0 00-.03.113c-.008.04-.017.054-.035.054-.014 0-.03-.01-.036-.02a.404.404 0 01-.044-.134.851.851 0 00-.022-.1 1.28 1.28 0 01-.028-.16c-.024-.209-.043-.292-.074-.327a.374.374 0 01-.054-.098c-.018-.048-.058-.099-.151-.193a1.45 1.45 0 01-.127-.136c0-.005-.009-.016-.019-.025-.015-.012-.031-.005-.077.033a.468.468 0 00-.084.088c-.027.044-.05.044-.072 0a.286.286 0 00-.037-.053.315.315 0 01-.043-.073z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M22.64 8.974c.096-.066.248-.134.332-.149.09-.016.299-.012.317.007.009.008.018.05.022.093a.983.983 0 00.055.236c.022.038.092-.017.134-.105a.848.848 0 01.248-.265c.023-.012.042-.027.042-.034 0-.007.026-.026.058-.041a.76.76 0 00.111-.072.917.917 0 01.114-.075c.189-.101.28-.145.302-.145a.277.277 0 00.092-.047.43.43 0 01.077-.047.146.146 0 00.044-.034l.107-.102a.639.639 0 00.123-.171 1.55 1.55 0 00.136-.307.996.996 0 01.15-.274l.07-.088-.031-.032a.211.211 0 00-.086-.047 2.656 2.656 0 01-.1-.027.23.23 0 00-.092-.006c-.034.007-.048.004-.054-.01-.007-.019.057-.162.142-.316.022-.04.056-.127.076-.193.02-.066.046-.143.056-.17a.314.314 0 00.018-.088c0-.021.005-.042.01-.048a.915.915 0 00.051-.228.793.793 0 01.018-.106c.042-.16.05-.652.013-.787a3.909 3.909 0 01-.029-.114c-.01-.045-.082-.097-.117-.086-.02.006-.027.02-.027.05 0 .024-.01.09-.02.15l-.035.193a.335.335 0 01-.034.107.205.205 0 00-.027.08.42.42 0 01-.098.187.432.432 0 00-.047.08.563.563 0 01-.079.116 1.07 1.07 0 00-.093.124c-.04.067-.128.158-.277.287-.059.05-.123.11-.144.13-.02.02-.043.036-.05.036a.852.852 0 00-.182.123c-.019.017-.06.048-.092.07-.032.023-.1.075-.15.117a.59.59 0 01-.105.077.407.407 0 00-.085.075c-.04.042-.144.146-.232.232-.087.086-.159.162-.159.17 0 .006-.018.03-.042.05a.532.532 0 00-.083.12.781.781 0 01-.073.118c-.018.021-.06.093-.093.16-.034.067-.07.137-.081.155a.145.145 0 00-.02.056c0 .013-.006.026-.013.03a.706.706 0 00-.096.2.243.243 0 01-.027.075.241.241 0 00-.027.085c0 .018-.006.037-.013.041-.008.005-.014.025-.014.045 0 .02-.006.043-.013.05a.829.829 0 00-.04.312c.022.042.08.033.163-.023zM31.36 7.25c0-.014-.02-.046-.044-.071-.037-.038-.058-.048-.121-.056-.11-.013-.165.01-.257.102-.101.104-.135.105-.227.011a.321.321 0 01-.082-.126.195.195 0 00-.036-.075c-.01-.008-.018-.035-.018-.059 0-.092-.044-.117-.085-.048-.033.055-.024.24.015.322.015.033.029.07.029.081 0 .012.015.035.034.052.019.018.034.038.034.045 0 .007.035.046.078.086.07.066.21.145.294.167.015.003.04.005.054.002a6.03 6.03 0 01.09-.013.326.326 0 00.269-.31c0-.037-.006-.072-.014-.077-.007-.004-.013-.02-.013-.033zM30.527 5.904c.11.044.344.036.445-.016.073-.037.093-.026.083.045a.584.584 0 00.086.327c.062.076.154.16.185.167.05.01.134-.007.167-.036a.571.571 0 00.149-.295 1.31 1.31 0 00-.001-.327 1.73 1.73 0 01-.03-.098.307.307 0 00-.048-.106 2.529 2.529 0 01-.077-.086.433.433 0 00-.139-.099c-.079-.037-.106-.043-.236-.048a.64.64 0 00-.393.087.547.547 0 01-.09.044c-.007 0-.019.011-.026.025a.082.082 0 01-.041.035c-.029.008-.122.183-.122.226 0 .04.059.143.088.155zM30.623 6.67c.043.005.084.01.092.013.026.009.032.007.072-.027a.16.16 0 01.054-.033c.008 0 .03-.018.049-.04.031-.038.035-.053.034-.144-.002-.138-.021-.185-.106-.253-.062-.05-.078-.056-.138-.056-.072 0-.104.015-.18.084-.075.07-.088.1-.092.214l-.003.106.07.064c.062.056.08.064.148.072zM32.468 4.421c0 .008.014.031.031.052.035.04.063.112.063.155 0 .015-.011.04-.025.055a.951.951 0 00-.137.268c0 .017-.007.035-.015.04-.016.01-.01.069.018.178a.215.215 0 00.069.117c.08.072.122.058.14-.046.004-.031.014-.06.02-.064.007-.004.012-.017.012-.03.001-.064.261-.295.395-.35a.521.521 0 00.093-.048c.012-.01.027-.018.034-.018.007 0 .03-.01.053-.02a.959.959 0 01.223-.073.059.059 0 00.035-.012.716.716 0 01.202-.068c.016 0 .042-.01.059-.021a.281.281 0 01.121-.025.85.85 0 00.149-.02c.032-.008.064-.011.072-.007.016.01.126.017.328.021.1.002.137-.002.151-.016.026-.026.01-.089-.027-.113a.66.66 0 00-.267-.067c-.023.005-.048.002-.057-.005-.01-.008-.044-.008-.09-.001a.255.255 0 01-.093.002 2.902 2.902 0 00-.31-.012 2.158 2.158 0 01-.305-.015.328.328 0 00-.11-.011.398.398 0 01-.122-.014.598.598 0 00-.087-.03.311.311 0 01-.074-.028.071.071 0 00-.04-.011c-.04 0-.302-.13-.381-.189-.076-.056-.113-.064-.145-.028-.068.078-.069.243-.002.399.01.023.019.048.019.055z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M31.507 5.33c.034.035.048.04.108.04h.069l.162-.159c.14-.138.347-.307.375-.307.005 0 .03-.024.054-.053a.252.252 0 01.07-.06c.022-.007.07-.076.07-.101 0-.007-.019-.022-.041-.033-.04-.02-.048-.02-.133.008a.697.697 0 00-.124.052.51.51 0 01-.08.04.477.477 0 00-.096.059 1.996 1.996 0 01-.102.074 1.843 1.843 0 00-.092.068.432.432 0 01-.08.05c-.02.008-.037.021-.037.028 0 .007-.028.032-.061.056-.034.024-.061.05-.061.06 0 .008-.01.023-.02.032-.035.028-.025.099.019.145zM26.44 1.64c.08-.036.091-.044.189-.14.06-.06.166-.272.166-.33a.65.65 0 01.02-.11c.03-.108.016-.124-.091-.113a.42.42 0 00-.109.023.85.85 0 00-.2.178c0 .01-.008.024-.018.033-.01.008-.022.04-.027.07a.222.222 0 01-.02.07c-.033.04-.048.298-.02.345.01.016.026.012.11-.025zM29.503 9.663c-.022-.025-.04-.056-.04-.068 0-.012-.016-.04-.035-.062a.174.174 0 01-.034-.05.524.524 0 00-.08-.088.447.447 0 01-.082-.09c0-.008-.029-.03-.064-.05a1.91 1.91 0 01-.151-.1.443.443 0 00-.105-.065c-.022 0-.059.069-.059.111 0 .02-.02.053-.052.084-.056.055-.137.2-.137.244 0 .051-.025.04-.083-.039a.473.473 0 00-.067-.08.358.358 0 01-.062-.051.323.323 0 00-.086-.062.404.404 0 01-.078-.041.194.194 0 00-.067-.032c-.01 0-.05-.01-.086-.022a.274.274 0 00-.104-.014.109.109 0 01-.06-.005c-.032-.017-.12.014-.137.05-.012.025-.007.038.036.084a.446.446 0 01.088.133c.04.07.067.194.063.3a2.52 2.52 0 01-.035.388c-.006.003-.027-.003-.049-.014a.388.388 0 00-.15-.02c-.108 0-.113.001-.125.034-.02.052-.022.523-.003.543a.06.06 0 01.016.036c0 .011.026.073.058.136.05.1.082.14.243.305.103.105.187.196.187.204 0 .007.015.033.033.057a.166.166 0 01.034.062c0 .01.006.024.012.031a.754.754 0 01.048.126c.03.094.036.141.038.274.002.148 0 .165-.034.235a.62.62 0 00-.037.086c0 .005-.012.022-.028.037a.538.538 0 00-.058.075c-.016.026-.043.048-.059.05-.016.003-.039.02-.051.04-.034.05-.01.09.078.131.064.03.085.033.22.03.185-.004.253-.02.336-.074a.398.398 0 01.075-.044.17.17 0 00.05-.04c.02-.022.048-.04.06-.04.037 0 .151-.097.211-.18.066-.09.129-.21.156-.299.02-.066.063-.133.093-.148a.742.742 0 01.082-.028.698.698 0 00.094-.034.158.158 0 01.05-.018.528.528 0 00.167-.086c.01-.011.024-.02.032-.02.018 0 .14-.118.213-.203a.513.513 0 00.107-.203c0-.01.006-.023.014-.028.007-.004.013-.017.013-.028 0-.01.012-.045.027-.075a.272.272 0 00.027-.077c0-.012.006-.027.013-.034.008-.007.029-.133.047-.28.019-.146.043-.3.053-.34.01-.04.024-.096.029-.125a.36.36 0 01.02-.073.998.998 0 00.035-.121.715.715 0 01.047-.141.359.359 0 00.033-.1.77.77 0 01.115-.26c.07-.119.092-.157.108-.191.023-.049.205-.254.3-.339.048-.042.111-.1.141-.129.07-.067.211-.16.335-.222a.952.952 0 00.111-.06c.007-.007.03-.013.05-.013.025 0 .045-.01.058-.03.035-.053.002-.123-.1-.205a.369.369 0 00-.112-.071.124.124 0 01-.048-.012c-.03-.015-.264.018-.312.045a.918.918 0 01-.083.038c-.137.054-.389.29-.488.455a.648.648 0 01-.062.087.158.158 0 00-.035.06c-.008.047-.058.04-.09-.012-.016-.027-.035-.048-.043-.048-.008 0-.02-.015-.027-.033-.007-.019-.023-.034-.036-.034-.031 0-.25.22-.294.296a.407.407 0 01-.056.078.058.058 0 00-.02.04.267.267 0 01-.027.077.263.263 0 00-.027.087c0 .017-.01.061-.021.097-.02.061-.04.188-.056.346a.214.214 0 01-.02.08.058.058 0 00-.012.034c0 .013-.012.037-.027.054-.026.031-.027.032-.047.006a.109.109 0 01-.02-.057.14.14 0 00-.012-.054.524.524 0 01-.042-.138c0-.01-.019-.04-.04-.066zM26.797 2.663c0 .083.02.1.085.073.05-.02.076-.017.076.008a.52.52 0 01-.09.096c-.145.131-.41.4-.41.413a.215.215 0 01-.04.062.685.685 0 00-.06.09.456.456 0 01-.065.086.48.48 0 00-.062.078c-.018.032-.011.08.013.096.02.013.066-.003.075-.027.04-.105.501-.56.797-.785.077-.059.195-.137.207-.137a.592.592 0 01.14-.086c.054-.026.107-.053.118-.06.072-.044.387-.134.501-.144.053-.004.072.002.143.048a.507.507 0 00.136.062c.087.017.25.009.285-.013a.13.13 0 01.057-.02.726.726 0 00.191-.072.346.346 0 01.07-.026.242.242 0 00.08-.044c.034-.029.04-.042.033-.07a.16.16 0 00-.035-.061 1.689 1.689 0 01-.068-.077c-.023-.028-.048-.05-.055-.05-.012 0-.03-.011-.13-.079-.025-.017-.055-.027-.066-.022a.062.062 0 01-.043-.005.667.667 0 00-.273.031.318.318 0 01-.08.035.487.487 0 00-.14.09c-.09.08-.108.088-.24.115a.718.718 0 00-.131.039.391.391 0 01-.088.028.222.222 0 00-.081.033.555.555 0 01-.12.054c-.091.031-.174.074-.27.14-.045.03-.058.035-.075.021-.011-.01-.02-.024-.02-.032 0-.018.044-.107.065-.133a.668.668 0 00.056-.189.822.822 0 00.009-.146l-.002-.094-.056.004a.343.343 0 00-.108.03.271.271 0 01-.066.026c-.03 0-.141.13-.174.2a.848.848 0 00-.089.295v.119z\"\n        fill=\"#F0D7C6\"\n      />\n      <path\n        d=\"M27.553 2.242c.021.025.014.025.077-.003.074-.033.357-.27.357-.299 0-.005.015-.043.034-.083.06-.13.07-.282.031-.465-.011-.054-.018-.063-.045-.063-.018 0-.036.006-.04.013-.005.008-.025.014-.046.014-.048 0-.156.088-.223.182a.688.688 0 00-.11.264.199.199 0 01-.024.07c-.023.028-.032.346-.01.37zM28.976 7.599c0-.008-.013-.021-.028-.03a.25.25 0 01-.063-.07 1.175 1.175 0 00-.13-.15 4.266 4.266 0 01-.145-.147 3.414 3.414 0 00-.314-.28 2.507 2.507 0 01-.26-.194.73.73 0 00-.127-.09.626.626 0 01-.113-.079 3.556 3.556 0 01-.356-.36c-.021-.031-.044-.056-.05-.056-.006 0-.02-.02-.03-.044a.228.228 0 00-.048-.069c-.015-.014-.029-.032-.029-.04a.323.323 0 00-.043-.082c-.112-.17-.13-.202-.137-.243a.508.508 0 00-.027-.087 1.328 1.328 0 01-.077-.38c0-.11-.014-.126-.086-.093-.045.021-.05.033-.104.219-.018.06-.008.574.014.719l.025.18c.019.144.05.27.097.4l.076.213c.02.055.043.11.052.12.026.033.098.177.107.215.012.049-.01.062-.123.078a.498.498 0 00-.145.042c-.066.038-.064.08.007.165a.829.829 0 01.14.267.785.785 0 00.05.12c.131.263.382.526.55.575.069.02.234.101.294.144.055.039.091.06.118.07a.116.116 0 01.045.04c.011.017.027.032.035.032.023 0 .193.116.254.174a.797.797 0 01.151.208c0 .005.013.023.03.04.016.018.036.03.043.027.045-.015.093-.148.09-.25 0-.027.007-.055.016-.062.114-.084.47-.01.67.137.052.04.09.041.125.006.025-.024.026-.034.013-.137a.8.8 0 00-.032-.15 1.373 1.373 0 01-.041-.12 1.633 1.633 0 00-.035-.107 1.01 1.01 0 01-.028-.086.29.29 0 00-.027-.073.058.058 0 01-.012-.034.192.192 0 00-.033-.07.553.553 0 01-.056-.113.323.323 0 00-.046-.09.264.264 0 01-.042-.085c-.012-.04-.027-.062-.049-.07-.021-.008-.03-.022-.03-.046 0-.019-.01-.037-.021-.042a.489.489 0 01-.115-.162z\"\n        fill=\"#F0D7C6\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 50,\n  svg: FloralPattern,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/honeymooning-in-italy/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as floralPattern } from './floralPattern';\n\nexport { floralPattern };\n"
  },
  {
    "path": "packages/stickers/src/how-contact-tracing-works/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as contactTracingRings } from './rings';\nimport { default as contactTracingPhone } from './phoneInHand';\n\nexport { contactTracingRings, contactTracingPhone };\n"
  },
  {
    "path": "packages/stickers/src/how-contact-tracing-works/phoneInHand.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Phone', 'sticker name', 'web-stories');\n\nconst PhoneInHand = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 36 51\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M6.63249 31.6062C6.7549 27.2132 9.56206 16.4426 16.5677 14.0109C20.6833 12.5822 25.1679 11.9638 28.3332 12.0185L28.6446 15.7685L27.2741 15.8823L22.6 31.3034C22.6 35.3687 20.2372 36.1723 20.2372 39.6989L19.6869 49.4142L4.35262 48.1605C4.35262 48.1605 4.23974 48.1162 6.23159 37.1106C6.65439 33.9367 6.60924 32.4357 6.63249 31.6062Z\"\n      fill=\"#1FC1BE\"\n    />\n    <path\n      d=\"M22.2024 33.8086C20.8788 33.651 18.1749 33.3359 17.948 33.3359V33.0522H22.5333L22.2024 33.8086Z\"\n      fill=\"#1DAFAC\"\n    />\n    <path\n      d=\"M32.3604 19.5648C32.3604 22.0614 28.6751 21.274 28.1214 20.9742C27.5681 20.6744 27.7905 17.1925 27.7905 17.1925C27.7905 17.1925 32.3604 16.3889 32.3604 19.5648Z\"\n      fill=\"url(#paint0_linear)\"\n    />\n    <path\n      d=\"M32.0313 24.1909C31.8287 26.0089 28.3815 25.5051 27.8278 25.2054C26.4569 24.4632 27.4969 21.7545 27.4969 21.7545C27.4969 21.7545 32.351 21.3229 32.0313 24.1909Z\"\n      fill=\"url(#paint1_linear)\"\n    />\n    <path\n      d=\"M30.3923 27.7716C30.7185 29.9764 27.3318 29.6251 26.7786 29.3253C26.2253 29.0254 26.5742 25.4187 26.5742 25.4187C26.5742 25.4187 30.066 25.5669 30.3923 27.7716Z\"\n      fill=\"url(#paint2_linear)\"\n    />\n    <path\n      d=\"M31.8912 13.0398C32.8727 13.8864 32.555 16.4599 29.3878 16.4599C26.4633 17.0316 28.1114 12.7728 28.1114 12.7728C28.1114 12.7728 29.6241 12.6309 31.8912 13.0398Z\"\n      fill=\"url(#paint3_linear)\"\n    />\n    <path\n      d=\"M13.8221 17.5558L14.0439 17.9726C14.0248 17.994 10.6719 21.3714 9.62107 23.3179L9.33244 22.9977C9.55312 20.9034 13.7423 17.6451 13.8221 17.5558Z\"\n      fill=\"#1DAFAD\"\n    />\n    <path\n      d=\"M29.0417 2.23144C29.0417 1.60486 28.5338 1.09692 27.9072 1.09692H15.6167C14.9901 1.09692 14.4822 1.60486 14.4822 2.23144V31.3506C14.4822 31.9772 14.9901 32.4851 15.6167 32.4851H27.9072C28.5338 32.4851 29.0417 31.9772 29.0417 31.3506V2.23144Z\"\n      fill=\"#1D1D1D\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M27.9073 0.435059H15.6168C14.6247 0.435059 13.8204 1.23929 13.8204 2.23137V31.3506C13.8204 32.3426 14.6247 33.1469 15.6167 33.1469H27.9073C28.8994 33.1469 29.7036 32.3426 29.7036 31.3506V2.23137C29.7036 1.2393 28.8994 0.435059 27.9073 0.435059ZM27.9073 1.09686C28.5339 1.09686 29.0418 1.6048 29.0418 2.23137V31.3506C29.0418 31.9771 28.5339 32.4851 27.9073 32.4851H15.6167C14.9902 32.4851 14.4822 31.9771 14.4822 31.3506V2.23137C14.4822 1.6048 14.9902 1.09686 15.6168 1.09686H27.9073Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M20.1543 1.94681C20.8446 1.95225 22.9608 1.96967 23.634 1.9703C23.7472 1.9706 23.8376 2.06358 23.8348 2.17704L23.8346 2.18288C23.8318 2.29291 23.7416 2.38011 23.6318 2.37922L20.1518 2.34984C20.0479 2.3491 19.9615 2.26877 19.9529 2.16528C19.9426 2.04647 20.0358 1.94592 20.1543 1.94681Z\"\n      fill=\"#74747C\"\n    />\n    <path\n      d=\"M15.1201 41.6529C15.1191 41.6533 15.1186 41.6537 15.1176 41.6541C15.1176 41.6541 15.1268 41.6635 15.1268 41.6639L15.1261 41.6702L15.115 41.6597L15.1173 41.6517C15.1183 41.6518 15.1192 41.6524 15.1201 41.6529Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M15.1175 41.6519C15.1166 41.6517 15.1157 41.6507 15.1143 41.6505C15.1153 41.6506 15.1167 41.6508 15.1176 41.6509L15.1175 41.6519Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M15.1002 41.6661L15.0585 41.6581L15.0609 41.6496C15.0613 41.6501 15.0903 41.6621 15.1002 41.6661Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M15.6056 16.6693C16.5692 15.7262 18.0967 13.7074 19.3933 15.5162C21.5407 18.2565 16.6903 22.4049 15.3009 24.7327C13.741 28.0417 15.2355 29.999 15.8846 31.306C17.0523 33.6574 19.3233 33.4562 19.3233 33.4562L7.90046 36.2313C7.82932 35.5309 7.4374 31.9248 7.4374 31.9248C7.4374 31.9248 7.52051 25.3082 9.24398 22.8114C10.9679 20.3145 14.6419 17.6124 15.6056 16.6693Z\"\n      fill=\"#1FC1BE\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M18.2476 16.9362C18.8045 16.6543 19.125 16.078 19.2851 15.6697L19.109 15.6007C18.9544 15.995 18.6563 16.5174 18.1622 16.7675C17.6789 17.0122 16.9756 17.0112 15.9715 16.2917L15.8613 16.4454C16.9004 17.1899 17.6801 17.2235 18.2476 16.9362Z\"\n      fill=\"#1DAFAC\"\n    />\n    <path\n      d=\"M5.51554 35.8887L21.3042 40.3322L20.6424 44.2084L4.28648 40.8049L5.51554 35.8887Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M4.02441 38.2522L21.3042 43.0997L19.8861 49.7864L0.977512 48.3683L4.02441 38.2522Z\"\n      fill=\"#4D5777\"\n    />\n    <defs>\n      <linearGradient\n        id=\"paint0_linear\"\n        x1=\"32.242\"\n        y1=\"18.5259\"\n        x2=\"27.7638\"\n        y2=\"19.0407\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stopColor=\"#23D4D1\" />\n        <stop offset=\"1\" stopColor=\"#1DAFAC\" />\n      </linearGradient>\n      <linearGradient\n        id=\"paint1_linear\"\n        x1=\"31.9129\"\n        y1=\"23.152\"\n        x2=\"27.4347\"\n        y2=\"23.6668\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stopColor=\"#23D4D1\" />\n        <stop offset=\"1\" stopColor=\"#1DAFAC\" />\n      </linearGradient>\n      <linearGradient\n        id=\"paint2_linear\"\n        x1=\"30.3231\"\n        y1=\"27.16\"\n        x2=\"26.4007\"\n        y2=\"27.6109\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stopColor=\"#23D4D1\" />\n        <stop offset=\"1\" stopColor=\"#1DAFAC\" />\n      </linearGradient>\n      <linearGradient\n        id=\"paint3_linear\"\n        x1=\"32.354\"\n        y1=\"13.9801\"\n        x2=\"27.8388\"\n        y2=\"14.4992\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop stopColor=\"#23D4D1\" />\n        <stop offset=\"1\" stopColor=\"#1EB3B0\" />\n      </linearGradient>\n    </defs>\n  </svg>\n);\nexport default {\n  aspectRatio: 36 / 51,\n  svg: PhoneInHand,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/how-contact-tracing-works/rings.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Rings', 'sticker name', 'web-stories');\n\nconst Rings = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 52 51\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      opacity=\"0.5\"\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M25.7349 16.8552C25.8045 16.8536 25.8743 16.8528 25.9443 16.8528C26.0143 16.8528 26.0841 16.8536 26.1537 16.8552C26.2014 16.8564 26.2391 16.8959 26.238 16.9436C26.2369 16.9913 26.1973 17.029 26.1497 17.0279C26.0814 17.0263 26.013 17.0255 25.9443 17.0255C25.8757 17.0255 25.8072 17.0263 25.739 17.0279C25.6913 17.029 25.6517 16.9913 25.6506 16.9436C25.6495 16.8959 25.6873 16.8564 25.7349 16.8552ZM26.8904 16.9896C26.896 16.9423 26.9389 16.9084 26.9863 16.914C27.1251 16.9305 27.2629 16.9501 27.3996 16.973C27.4467 16.9808 27.4784 17.0253 27.4706 17.0724C27.4627 17.1194 27.4182 17.1512 27.3712 17.1433C27.2371 17.1209 27.1021 17.1016 26.966 17.0855C26.9186 17.0799 26.8848 17.037 26.8904 16.9896ZM24.9982 16.9896C25.0038 17.037 24.97 17.0799 24.9226 17.0855C24.7866 17.1016 24.6515 17.1209 24.5175 17.1433C24.4704 17.1512 24.4259 17.1194 24.4181 17.0724C24.4102 17.0253 24.442 16.9808 24.489 16.973C24.6257 16.9501 24.7635 16.9305 24.9023 16.914C24.9497 16.9084 24.9926 16.9423 24.9982 16.9896ZM23.7788 17.2108C23.7912 17.2569 23.7638 17.3042 23.7177 17.3165C23.5855 17.3519 23.4546 17.3903 23.325 17.4317C23.2795 17.4462 23.2309 17.4211 23.2164 17.3757C23.2019 17.3302 23.227 17.2817 23.2724 17.2671C23.4046 17.2249 23.5382 17.1857 23.6731 17.1497C23.7192 17.1374 23.7665 17.1647 23.7788 17.2108ZM28.1098 17.2108C28.1221 17.1647 28.1695 17.1374 28.2155 17.1497C28.3504 17.1857 28.484 17.2249 28.6162 17.2671C28.6617 17.2817 28.6867 17.3302 28.6722 17.3757C28.6577 17.4211 28.6091 17.4462 28.5637 17.4317C28.4341 17.3903 28.3031 17.3519 28.1709 17.3165C28.1249 17.3042 28.0975 17.2569 28.1098 17.2108ZM22.6036 17.6044C22.6224 17.6482 22.6021 17.699 22.5583 17.7178C22.4326 17.7716 22.3085 17.8284 22.186 17.888C22.1431 17.9089 22.0915 17.891 22.0706 17.8482C22.0497 17.8053 22.0676 17.7536 22.1105 17.7327C22.2354 17.6719 22.362 17.614 22.4902 17.559C22.534 17.5402 22.5848 17.5605 22.6036 17.6044ZM29.2851 17.6044C29.3038 17.5605 29.3546 17.5402 29.3984 17.559C29.5266 17.614 29.6532 17.6719 29.7782 17.7327C29.8211 17.7536 29.8389 17.8053 29.818 17.8482C29.7972 17.891 29.7455 17.9089 29.7026 17.888C29.5801 17.8284 29.456 17.7716 29.3304 17.7178C29.2866 17.699 29.2663 17.6482 29.2851 17.6044ZM21.4967 18.1622C21.5216 18.2029 21.5087 18.256 21.468 18.2809C21.3515 18.3521 21.2367 18.426 21.1239 18.5025C21.0844 18.5293 21.0307 18.519 21.0039 18.4795C20.9772 18.44 20.9875 18.3863 21.0269 18.3596C21.142 18.2815 21.2591 18.2061 21.378 18.1335C21.4187 18.1086 21.4719 18.1215 21.4967 18.1622ZM30.3919 18.1622C30.4168 18.1215 30.4699 18.1086 30.5106 18.1335C30.6295 18.2061 30.7466 18.2815 30.8617 18.3596C30.9012 18.3863 30.9115 18.44 30.8847 18.4795C30.8579 18.519 30.8042 18.5293 30.7648 18.5025C30.6519 18.426 30.5372 18.3521 30.4206 18.2809C30.3799 18.256 30.3671 18.2029 30.3919 18.1622ZM20.4805 18.8719C20.5109 18.9087 20.5058 18.9631 20.469 18.9935C20.3638 19.0805 20.2606 19.1699 20.1597 19.2617C20.1244 19.2938 20.0698 19.2912 20.0377 19.2559C20.0056 19.2207 20.0082 19.166 20.0435 19.1339C20.1465 19.0403 20.2516 18.9491 20.359 18.8604C20.3957 18.83 20.4502 18.8352 20.4805 18.8719ZM31.4081 18.8719C31.4385 18.8352 31.4929 18.83 31.5297 18.8604C31.637 18.9491 31.7422 19.0403 31.8451 19.134C31.8804 19.166 31.883 19.2207 31.8509 19.2559C31.8188 19.2912 31.7642 19.2938 31.7289 19.2617C31.628 19.1699 31.5249 19.0805 31.4196 18.9935C31.3829 18.9631 31.3777 18.9087 31.4081 18.8719ZM19.5752 19.7185C19.6104 19.7506 19.613 19.8052 19.5809 19.8405C19.4891 19.9414 19.3997 20.0446 19.3127 20.1498C19.2823 20.1865 19.2279 20.1917 19.1911 20.1613C19.1544 20.1309 19.1492 20.0765 19.1796 20.0397C19.2683 19.9324 19.3595 19.8272 19.4532 19.7243C19.4853 19.689 19.5399 19.6864 19.5752 19.7185ZM32.3135 19.7185C32.3488 19.6864 32.4034 19.689 32.4355 19.7243C32.5291 19.8272 32.6203 19.9324 32.709 20.0397C32.7394 20.0765 32.7343 20.1309 32.6975 20.1613C32.6607 20.1917 32.6063 20.1865 32.5759 20.1498C32.489 20.0446 32.3995 19.9414 32.3077 19.8405C32.2756 19.8052 32.2782 19.7506 32.3135 19.7185ZM18.7987 20.6847C18.8382 20.7115 18.8485 20.7652 18.8217 20.8047C18.7452 20.9175 18.6713 21.0323 18.6001 21.1488C18.5752 21.1895 18.5221 21.2024 18.4814 21.1775C18.4407 21.1527 18.4278 21.0995 18.4527 21.0588C18.5253 20.9399 18.6007 20.8228 18.6788 20.7077C18.7055 20.6683 18.7592 20.658 18.7987 20.6847ZM33.0899 20.6847C33.1294 20.658 33.1831 20.6683 33.2099 20.7077C33.2879 20.8228 33.3633 20.9399 33.4359 21.0588C33.4608 21.0995 33.448 21.1527 33.4073 21.1775C33.3666 21.2024 33.3134 21.1895 33.2886 21.1488C33.2173 21.0323 33.1434 20.9175 33.0669 20.8047C33.0402 20.7652 33.0505 20.7115 33.0899 20.6847ZM18.1674 21.7514C18.2103 21.7723 18.2281 21.8239 18.2072 21.8668C18.1476 21.9893 18.0908 22.1134 18.037 22.239C18.0182 22.2829 17.9674 22.3032 17.9236 22.2844C17.8797 22.2656 17.8594 22.2148 17.8782 22.171C17.9332 22.0428 17.9911 21.9162 18.0519 21.7912C18.0728 21.7484 18.1245 21.7305 18.1674 21.7514ZM33.7213 21.7514C33.7642 21.7305 33.8158 21.7484 33.8367 21.7912C33.8975 21.9162 33.9554 22.0428 34.0104 22.171C34.0292 22.2148 34.0089 22.2656 33.9651 22.2844C33.9212 22.3032 33.8705 22.2829 33.8517 22.239C33.7978 22.1134 33.741 21.9893 33.6814 21.8668C33.6605 21.8239 33.6784 21.7723 33.7213 21.7514ZM17.6949 22.8972C17.7403 22.9117 17.7654 22.9603 17.7509 23.0058C17.7095 23.1354 17.6711 23.2663 17.6357 23.3985C17.6234 23.4446 17.5761 23.4719 17.53 23.4596C17.4839 23.4473 17.4566 23.4 17.4689 23.3539C17.5049 23.219 17.5441 23.0854 17.5864 22.9532C17.6009 22.9078 17.6495 22.8827 17.6949 22.8972ZM34.1937 22.8972C34.2392 22.8827 34.2878 22.9078 34.3023 22.9532C34.3445 23.0854 34.3837 23.219 34.4198 23.3539C34.4321 23.4 34.4047 23.4473 34.3586 23.4596C34.3126 23.4719 34.2652 23.4446 34.2529 23.3985C34.2176 23.2663 34.1792 23.1354 34.1378 23.0058C34.1232 22.9603 34.1483 22.9117 34.1937 22.8972ZM17.3916 24.0989C17.4386 24.1067 17.4704 24.1512 17.4625 24.1983C17.4401 24.3323 17.4209 24.4674 17.4048 24.6034C17.3992 24.6508 17.3562 24.6846 17.3089 24.679C17.2615 24.6734 17.2276 24.6305 17.2332 24.5831C17.2497 24.4443 17.2693 24.3065 17.2922 24.1698C17.3 24.1228 17.3445 24.091 17.3916 24.0989ZM34.4971 24.0989C34.5441 24.091 34.5886 24.1228 34.5965 24.1698C34.6193 24.3065 34.639 24.4443 34.6554 24.5831C34.661 24.6305 34.6271 24.6734 34.5798 24.679C34.5324 24.6846 34.4895 24.6508 34.4839 24.6034C34.4678 24.4674 34.4485 24.3323 34.4261 24.1983C34.4183 24.1512 34.45 24.1067 34.4971 24.0989ZM17.2628 25.3314C17.3105 25.3325 17.3482 25.3721 17.3471 25.4198C17.3455 25.488 17.3447 25.5565 17.3447 25.6251C17.3447 25.6937 17.3455 25.7622 17.3471 25.8305C17.3482 25.8781 17.3105 25.9177 17.2628 25.9188C17.2151 25.9199 17.1756 25.8822 17.1744 25.8345C17.1728 25.7649 17.172 25.6951 17.172 25.6251C17.172 25.5551 17.1728 25.4853 17.1744 25.4157C17.1756 25.368 17.2151 25.3303 17.2628 25.3314ZM34.6258 25.3314C34.6735 25.3303 34.7131 25.368 34.7142 25.4157C34.7158 25.4853 34.7166 25.5551 34.7166 25.6251C34.7166 25.6951 34.7158 25.7649 34.7142 25.8345C34.7131 25.8822 34.6735 25.9199 34.6258 25.9188C34.5782 25.9177 34.5404 25.8781 34.5415 25.8305C34.5431 25.7622 34.5439 25.6937 34.5439 25.6251C34.5439 25.5565 34.5431 25.488 34.5415 25.4198C34.5404 25.3721 34.5782 25.3325 34.6258 25.3314ZM34.5798 26.5712C34.6271 26.5768 34.661 26.6197 34.6554 26.6671C34.639 26.8059 34.6193 26.9437 34.5965 27.0804C34.5886 27.1275 34.5441 27.1592 34.4971 27.1514C34.45 27.1435 34.4183 27.099 34.4261 27.052C34.4485 26.9179 34.4678 26.7829 34.4839 26.6468C34.4895 26.5994 34.5324 26.5656 34.5798 26.5712ZM17.3089 26.5712C17.3562 26.5656 17.3992 26.5994 17.4048 26.6468C17.4209 26.7829 17.4401 26.9179 17.4625 27.052C17.4704 27.099 17.4386 27.1435 17.3916 27.1514C17.3445 27.1592 17.3 27.1275 17.2922 27.0804C17.2693 26.9437 17.2497 26.8059 17.2332 26.6671C17.2276 26.6197 17.2615 26.5768 17.3089 26.5712ZM17.53 27.7906C17.5761 27.7783 17.6234 27.8056 17.6357 27.8517C17.6711 27.9839 17.7095 28.1149 17.7509 28.2445C17.7654 28.2899 17.7403 28.3385 17.6949 28.353C17.6495 28.3675 17.6009 28.3424 17.5864 28.297C17.5441 28.1648 17.5049 28.0312 17.4689 27.8963C17.4566 27.8502 17.4839 27.8029 17.53 27.7906ZM34.3586 27.7906C34.4047 27.8029 34.4321 27.8502 34.4198 27.8963C34.3837 28.0312 34.3445 28.1648 34.3023 28.297C34.2878 28.3424 34.2392 28.3675 34.1937 28.353C34.1483 28.3385 34.1232 28.2899 34.1378 28.2445C34.1792 28.1149 34.2176 27.9839 34.2529 27.8517C34.2652 27.8056 34.3126 27.7783 34.3586 27.7906ZM17.9236 28.9658C17.9674 28.947 18.0182 28.9673 18.037 29.0112C18.0908 29.1368 18.1476 29.2609 18.2072 29.3834C18.2281 29.4263 18.2103 29.478 18.1674 29.4988C18.1245 29.5197 18.0728 29.5019 18.0519 29.459C17.9911 29.334 17.9332 29.2074 17.8782 29.0792C17.8594 29.0354 17.8797 28.9846 17.9236 28.9658ZM33.9651 28.9658C34.0089 28.9846 34.0292 29.0354 34.0104 29.0792C33.9554 29.2074 33.8975 29.334 33.8367 29.459C33.8158 29.5019 33.7642 29.5197 33.7213 29.4988C33.6784 29.478 33.6605 29.4263 33.6814 29.3834C33.741 29.2609 33.7978 29.1368 33.8517 29.0112C33.8705 28.9673 33.9212 28.947 33.9651 28.9658ZM18.4814 30.0727C18.5221 30.0478 18.5752 30.0607 18.6001 30.1014C18.6713 30.218 18.7452 30.3327 18.8217 30.4456C18.8485 30.485 18.8382 30.5387 18.7987 30.5655C18.7592 30.5923 18.7055 30.582 18.6788 30.5425C18.6007 30.4274 18.5253 30.3103 18.4527 30.1914C18.4278 30.1507 18.4407 30.0976 18.4814 30.0727ZM33.4073 30.0727C33.448 30.0976 33.4608 30.1507 33.4359 30.1914C33.3633 30.3103 33.2879 30.4274 33.2099 30.5425C33.1831 30.582 33.1294 30.5923 33.0899 30.5655C33.0505 30.5387 33.0402 30.485 33.0669 30.4456C33.1434 30.3327 33.2173 30.218 33.2886 30.1014C33.3134 30.0607 33.3666 30.0478 33.4073 30.0727ZM19.1911 31.0889C19.2279 31.0585 19.2823 31.0637 19.3127 31.1004C19.3997 31.2057 19.4891 31.3088 19.5809 31.4097C19.613 31.445 19.6104 31.4996 19.5752 31.5317C19.5399 31.5638 19.4853 31.5612 19.4532 31.5259C19.3595 31.423 19.2683 31.3178 19.1796 31.2105C19.1492 31.1737 19.1544 31.1193 19.1911 31.0889ZM32.6975 31.0889C32.7343 31.1193 32.7394 31.1737 32.709 31.2105C32.6203 31.3178 32.5291 31.423 32.4355 31.5259C32.4034 31.5612 32.3488 31.5638 32.3135 31.5317C32.2782 31.4996 32.2756 31.445 32.3077 31.4097C32.3995 31.3088 32.4889 31.2057 32.5759 31.1004C32.6063 31.0637 32.6607 31.0585 32.6975 31.0889ZM20.0377 31.9943C20.0698 31.959 20.1244 31.9564 20.1597 31.9885C20.2606 32.0803 20.3638 32.1697 20.469 32.2567C20.5058 32.2871 20.5109 32.3415 20.4805 32.3783C20.4502 32.4151 20.3957 32.4202 20.359 32.3898C20.2516 32.3011 20.1464 32.2099 20.0435 32.1163C20.0082 32.0842 20.0056 32.0296 20.0377 31.9943ZM31.8509 31.9943C31.883 32.0296 31.8804 32.0842 31.8451 32.1163C31.7422 32.2099 31.637 32.3011 31.5297 32.3898C31.4929 32.4202 31.4385 32.4151 31.4081 32.3783C31.3777 32.3415 31.3829 32.2871 31.4196 32.2567C31.5249 32.1697 31.628 32.0803 31.7289 31.9885C31.7642 31.9564 31.8188 31.959 31.8509 31.9943ZM21.0039 32.7707C21.0307 32.7313 21.0844 32.721 21.1239 32.7477C21.2367 32.8242 21.3515 32.8981 21.468 32.9694C21.5087 32.9942 21.5216 33.0474 21.4967 33.0881C21.4719 33.1288 21.4187 33.1416 21.378 33.1167C21.2591 33.0441 21.142 32.9687 21.0269 32.8907C20.9875 32.8639 20.9772 32.8102 21.0039 32.7707ZM30.8847 32.7707C30.9115 32.8102 30.9012 32.8639 30.8617 32.8907C30.7466 32.9687 30.6295 33.0441 30.5106 33.1167C30.4699 33.1416 30.4168 33.1288 30.3919 33.0881C30.3671 33.0474 30.3799 32.9942 30.4206 32.9694C30.5372 32.8981 30.6519 32.8242 30.7648 32.7477C30.8042 32.721 30.8579 32.7313 30.8847 32.7707ZM22.0706 33.4021C22.0915 33.3592 22.1431 33.3413 22.186 33.3622C22.3085 33.4218 22.4326 33.4786 22.5583 33.5325C22.6021 33.5513 22.6224 33.602 22.6036 33.6459C22.5848 33.6897 22.534 33.71 22.4902 33.6912C22.362 33.6362 22.2354 33.5783 22.1105 33.5175C22.0676 33.4966 22.0497 33.4449 22.0706 33.4021ZM29.818 33.4021C29.8389 33.4449 29.8211 33.4966 29.7782 33.5175C29.6532 33.5783 29.5266 33.6362 29.3984 33.6912C29.3546 33.71 29.3038 33.6897 29.2851 33.6459C29.2663 33.602 29.2866 33.5513 29.3304 33.5325C29.456 33.4786 29.5801 33.4218 29.7026 33.3622C29.7455 33.3413 29.7972 33.3592 29.818 33.4021ZM23.2164 33.8745C23.2309 33.8291 23.2795 33.804 23.325 33.8186C23.4546 33.86 23.5855 33.8984 23.7177 33.9337C23.7638 33.946 23.7912 33.9934 23.7788 34.0394C23.7665 34.0855 23.7192 34.1129 23.6731 34.1006C23.5382 34.0645 23.4046 34.0253 23.2724 33.9831C23.227 33.9686 23.2019 33.92 23.2164 33.8745ZM28.6722 33.8745C28.6867 33.92 28.6617 33.9686 28.6162 33.9831C28.484 34.0253 28.3504 34.0645 28.2155 34.1006C28.1695 34.1129 28.1221 34.0855 28.1098 34.0394C28.0975 33.9934 28.1249 33.946 28.1709 33.9337C28.3031 33.8984 28.4341 33.86 28.5637 33.8186C28.6091 33.804 28.6577 33.8291 28.6722 33.8745ZM24.4181 34.1779C24.4259 34.1308 24.4704 34.0991 24.5175 34.1069C24.6515 34.1293 24.7866 34.1486 24.9226 34.1647C24.97 34.1703 25.0038 34.2132 24.9982 34.2606C24.9926 34.3079 24.9497 34.3418 24.9023 34.3362C24.7635 34.3198 24.6257 34.3001 24.489 34.2773C24.442 34.2694 24.4102 34.2249 24.4181 34.1779ZM27.4706 34.1779C27.4784 34.2249 27.4467 34.2694 27.3996 34.2773C27.2629 34.3001 27.1251 34.3198 26.9863 34.3362C26.9389 34.3418 26.896 34.3079 26.8904 34.2606C26.8848 34.2132 26.9186 34.1703 26.966 34.1647C27.1021 34.1486 27.2371 34.1293 27.3712 34.1069C27.4182 34.0991 27.4627 34.1308 27.4706 34.1779ZM25.6506 34.3066C25.6517 34.259 25.6913 34.2212 25.739 34.2223C25.8072 34.2239 25.8757 34.2247 25.9443 34.2247C26.013 34.2247 26.0814 34.2239 26.1497 34.2223C26.1973 34.2212 26.2369 34.259 26.238 34.3066C26.2391 34.3543 26.2014 34.3939 26.1537 34.395C26.0841 34.3966 26.0143 34.3974 25.9443 34.3974C25.8743 34.3974 25.8045 34.3966 25.7349 34.395C25.6873 34.3939 25.6495 34.3543 25.6506 34.3066Z\"\n      fill=\"white\"\n    />\n    <path\n      opacity=\"0.3\"\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M25.7191 13.6254C25.794 13.624 25.8691 13.6233 25.9444 13.6233C26.0196 13.6233 26.0947 13.624 26.1696 13.6254C26.2173 13.6262 26.2552 13.6656 26.2543 13.7133C26.2535 13.761 26.2141 13.7989 26.1664 13.798C26.0926 13.7967 26.0185 13.796 25.9444 13.796C25.8702 13.796 25.7962 13.7967 25.7223 13.798C25.6746 13.7989 25.6352 13.761 25.6344 13.7133C25.6335 13.6656 25.6714 13.6262 25.7191 13.6254ZM24.9172 13.753C24.9216 13.8005 24.8867 13.8425 24.8392 13.8469C24.6918 13.8606 24.5451 13.877 24.3993 13.896C24.352 13.9022 24.3086 13.8688 24.3025 13.8215C24.2963 13.7742 24.3296 13.7309 24.3769 13.7247C24.5249 13.7054 24.6737 13.6888 24.8233 13.675C24.8708 13.6706 24.9128 13.7055 24.9172 13.753ZM26.9715 13.753C26.9759 13.7055 27.0179 13.6706 27.0654 13.675C27.215 13.6888 27.3638 13.7054 27.5118 13.7247C27.5591 13.7309 27.5924 13.7742 27.5862 13.8215C27.5801 13.8688 27.5367 13.9022 27.4894 13.896C27.3436 13.877 27.1969 13.8606 27.0495 13.8469C27.002 13.8425 26.9671 13.8005 26.9715 13.753ZM23.5944 13.941C23.6041 13.9877 23.5741 14.0334 23.5274 14.0431C23.3826 14.0732 23.2387 14.1059 23.0958 14.1412C23.0495 14.1527 23.0027 14.1244 22.9913 14.0781C22.9798 14.0318 23.0081 13.985 23.0544 13.9736C23.1993 13.9377 23.3453 13.9045 23.4923 13.874C23.539 13.8643 23.5847 13.8943 23.5944 13.941ZM28.2943 13.941C28.304 13.8943 28.3497 13.8643 28.3964 13.874C28.5434 13.9045 28.6894 13.9377 28.8343 13.9736C28.8806 13.985 28.9089 14.0318 28.8974 14.0781C28.886 14.1244 28.8392 14.1527 28.7929 14.1412C28.65 14.1059 28.5061 14.0732 28.3613 14.0431C28.3146 14.0334 28.2846 13.9877 28.2943 13.941ZM22.3006 14.2767C22.3155 14.322 22.2909 14.3709 22.2456 14.3858C22.1053 14.4319 21.9661 14.4806 21.8282 14.5318C21.7835 14.5484 21.7338 14.5256 21.7172 14.4809C21.7006 14.4362 21.7234 14.3865 21.7681 14.3699C21.9081 14.3179 22.0493 14.2685 22.1916 14.2217C22.2369 14.2068 22.2857 14.2314 22.3006 14.2767ZM29.5881 14.2767C29.603 14.2314 29.6518 14.2068 29.6971 14.2217C29.8395 14.2685 29.9806 14.3179 30.1206 14.3699C30.1653 14.3865 30.1881 14.4362 30.1715 14.4809C30.1549 14.5256 30.1052 14.5484 30.0605 14.5318C29.9226 14.4806 29.7834 14.4319 29.6431 14.3858C29.5978 14.3709 29.5732 14.322 29.5881 14.2767ZM21.0533 14.7562C21.0732 14.7995 21.0542 14.8508 21.0109 14.8707C20.8767 14.9324 20.7439 14.9965 20.6124 15.063C20.5699 15.0845 20.5179 15.0674 20.4964 15.0249C20.4749 14.9823 20.4919 14.9304 20.5345 14.9088C20.6678 14.8414 20.8026 14.7764 20.9388 14.7138C20.9821 14.6939 21.0334 14.7129 21.0533 14.7562ZM30.8354 14.7562C30.8553 14.7129 30.9066 14.6939 30.9499 14.7138C31.0861 14.7764 31.2209 14.8414 31.3542 14.9088C31.3968 14.9304 31.4138 14.9823 31.3923 15.0249C31.3708 15.0674 31.3188 15.0845 31.2763 15.063C31.1449 14.9965 31.012 14.9324 30.8778 14.8707C30.8345 14.8508 30.8155 14.7995 30.8354 14.7562ZM19.8679 15.373C19.8926 15.4138 19.8795 15.4669 19.8386 15.4915C19.7123 15.5678 19.5874 15.6464 19.4642 15.7273C19.4243 15.7535 19.3708 15.7423 19.3446 15.7025C19.3184 15.6626 19.3296 15.609 19.3694 15.5829C19.4945 15.5009 19.6211 15.4211 19.7494 15.3437C19.7902 15.319 19.8433 15.3321 19.8679 15.373ZM32.0208 15.373C32.0454 15.3321 32.0985 15.319 32.1393 15.3437C32.2676 15.4211 32.3942 15.5009 32.5193 15.5829C32.5591 15.6091 32.5703 15.6626 32.5441 15.7025C32.5179 15.7423 32.4644 15.7535 32.4245 15.7273C32.3013 15.6464 32.1764 15.5678 32.0501 15.4915C32.0092 15.4669 31.9961 15.4138 32.0208 15.373ZM18.7589 16.1187C18.788 16.1566 18.7809 16.2108 18.7431 16.2398C18.6261 16.3297 18.5108 16.4218 18.3974 16.5159C18.3607 16.5463 18.3062 16.5413 18.2758 16.5046C18.2453 16.4678 18.2504 16.4134 18.2871 16.383C18.4022 16.2875 18.5192 16.1941 18.6378 16.1029C18.6757 16.0738 18.7299 16.0809 18.7589 16.1187ZM33.1298 16.1188C33.1588 16.0809 33.213 16.0738 33.2509 16.1029C33.3695 16.1941 33.4865 16.2875 33.6016 16.383C33.6383 16.4134 33.6434 16.4678 33.6129 16.5046C33.5825 16.5413 33.528 16.5463 33.4913 16.5159C33.3779 16.4218 33.2626 16.3297 33.1456 16.2398C33.1078 16.2108 33.1007 16.1566 33.1298 16.1188ZM17.7401 16.9836C17.7732 17.0179 17.7722 17.0726 17.7379 17.1057C17.6316 17.208 17.5273 17.3123 17.425 17.4185C17.3919 17.4529 17.3372 17.4539 17.3029 17.4208C17.2686 17.3877 17.2675 17.333 17.3006 17.2987C17.4045 17.1909 17.5103 17.0851 17.618 16.9813C17.6524 16.9482 17.707 16.9492 17.7401 16.9836ZM34.1486 16.9836C34.1817 16.9492 34.2363 16.9482 34.2707 16.9813C34.3784 17.0851 34.4843 17.1909 34.5881 17.2987C34.6212 17.333 34.6201 17.3877 34.5858 17.4208C34.5515 17.4539 34.4968 17.4529 34.4637 17.4185C34.3614 17.3123 34.2571 17.208 34.1509 17.1057C34.1165 17.0726 34.1155 17.0179 34.1486 16.9836ZM16.8239 17.9564C16.8606 17.9869 16.8657 18.0413 16.8352 18.078C16.7411 18.1915 16.6491 18.3068 16.5592 18.4237C16.5301 18.4616 16.4759 18.4687 16.4381 18.4396C16.4003 18.4105 16.3932 18.3563 16.4222 18.3185C16.5134 18.1998 16.6068 18.0829 16.7023 17.9678C16.7327 17.9311 16.7872 17.926 16.8239 17.9564ZM35.0648 17.9564C35.1015 17.926 35.156 17.9311 35.1864 17.9678C35.2819 18.0829 35.3753 18.1998 35.4665 18.3185C35.4955 18.3563 35.4884 18.4105 35.4506 18.4396C35.4128 18.4687 35.3586 18.4616 35.3295 18.4237C35.2396 18.3068 35.1476 18.1915 35.0535 18.078C35.023 18.0413 35.0281 17.9869 35.0648 17.9564ZM16.0218 19.0253C16.0617 19.0514 16.0728 19.105 16.0466 19.1448C15.9658 19.2681 15.8872 19.3929 15.8109 19.5193C15.7862 19.5601 15.7331 19.5732 15.6923 19.5486C15.6515 19.5239 15.6383 19.4709 15.663 19.43C15.7404 19.3018 15.8202 19.1751 15.9022 19.0501C15.9284 19.0102 15.9819 18.9991 16.0218 19.0253ZM35.8669 19.0253C35.9068 18.9991 35.9603 19.0102 35.9865 19.0501C36.0685 19.1751 36.1483 19.3018 36.2257 19.43C36.2504 19.4709 36.2372 19.5239 36.1964 19.5486C36.1556 19.5732 36.1025 19.5601 36.0779 19.5193C36.0015 19.3929 35.9229 19.2681 35.8421 19.1448C35.8159 19.105 35.827 19.0514 35.8669 19.0253ZM15.3442 20.1771C15.3868 20.1986 15.4038 20.2505 15.3823 20.2931C15.3158 20.4245 15.2517 20.5573 15.1901 20.6915C15.1702 20.7349 15.1189 20.7539 15.0755 20.7339C15.0322 20.714 15.0132 20.6628 15.0331 20.6194C15.0957 20.4833 15.1607 20.3485 15.2282 20.2151C15.2497 20.1726 15.3017 20.1555 15.3442 20.1771ZM36.5445 20.1771C36.587 20.1555 36.639 20.1726 36.6605 20.2151C36.728 20.3485 36.793 20.4833 36.8556 20.6194C36.8755 20.6628 36.8565 20.714 36.8132 20.7339C36.7698 20.7539 36.7185 20.7349 36.6986 20.6915C36.637 20.5573 36.5729 20.4245 36.5064 20.2931C36.4849 20.2505 36.5019 20.1986 36.5445 20.1771ZM14.8002 21.3979C14.8449 21.4145 14.8677 21.4642 14.8511 21.5089C14.7999 21.6468 14.7512 21.7859 14.7051 21.9262C14.6902 21.9715 14.6414 21.9962 14.5961 21.9813C14.5508 21.9664 14.5261 21.9176 14.541 21.8723C14.5879 21.7299 14.6373 21.5887 14.6892 21.4488C14.7058 21.4041 14.7555 21.3813 14.8002 21.3979ZM37.0885 21.3979C37.1332 21.3813 37.1829 21.4041 37.1995 21.4488C37.2514 21.5887 37.3008 21.7299 37.3477 21.8723C37.3626 21.9176 37.3379 21.9664 37.2926 21.9813C37.2473 21.9962 37.1985 21.9715 37.1836 21.9262C37.1375 21.7859 37.0888 21.6468 37.0376 21.5089C37.021 21.4642 37.0438 21.4145 37.0885 21.3979ZM14.3974 22.6719C14.4437 22.6834 14.472 22.7302 14.4606 22.7765C14.4252 22.9193 14.3925 23.0632 14.3624 23.2081C14.3527 23.2548 14.307 23.2848 14.2603 23.2751C14.2136 23.2654 14.1836 23.2197 14.1933 23.173C14.2239 23.026 14.2571 22.88 14.2929 22.735C14.3043 22.6887 14.3511 22.6605 14.3974 22.6719ZM37.4913 22.6719C37.5376 22.6605 37.5844 22.6887 37.5958 22.735C37.6316 22.88 37.6649 23.026 37.6954 23.173C37.7051 23.2197 37.6751 23.2654 37.6284 23.2751C37.5817 23.2848 37.536 23.2548 37.5263 23.2081C37.4962 23.0632 37.4635 22.9193 37.4281 22.7765C37.4167 22.7302 37.445 22.6834 37.4913 22.6719ZM14.1409 23.9831C14.1882 23.9893 14.2215 24.0326 14.2153 24.0799C14.1963 24.2258 14.1799 24.3724 14.1663 24.5199C14.1619 24.5674 14.1198 24.6023 14.0723 24.5979C14.0248 24.5935 13.9899 24.5514 13.9943 24.5039C14.0082 24.3543 14.0248 24.2055 14.0441 24.0576C14.0502 24.0103 14.0936 23.977 14.1409 23.9831ZM37.7478 23.9831C37.7951 23.977 37.8385 24.0103 37.8446 24.0576C37.8639 24.2055 37.8805 24.3543 37.8944 24.5039C37.8988 24.5514 37.8639 24.5935 37.8164 24.5979C37.7689 24.6023 37.7268 24.5674 37.7224 24.5199C37.7088 24.3724 37.6924 24.2258 37.6734 24.0799C37.6672 24.0326 37.7005 23.9893 37.7478 23.9831ZM14.0326 25.315C14.0803 25.3159 14.1183 25.3553 14.1174 25.403C14.116 25.4768 14.1153 25.5508 14.1153 25.625C14.1153 25.6992 14.116 25.7732 14.1174 25.8471C14.1183 25.8947 14.0803 25.9341 14.0326 25.935C13.9849 25.9359 13.9456 25.8979 13.9447 25.8502C13.9433 25.7753 13.9426 25.7003 13.9426 25.625C13.9426 25.5498 13.9433 25.4747 13.9447 25.3998C13.9456 25.3521 13.9849 25.3142 14.0326 25.315ZM37.8561 25.315C37.9038 25.3142 37.9431 25.3521 37.944 25.3998C37.9454 25.4747 37.9461 25.5498 37.9461 25.625C37.9461 25.7003 37.9454 25.7753 37.944 25.8503C37.9431 25.8979 37.9038 25.9359 37.8561 25.935C37.8084 25.9341 37.7704 25.8948 37.7713 25.8471C37.7727 25.7732 37.7734 25.6992 37.7734 25.625C37.7734 25.5508 37.7727 25.4768 37.7713 25.403C37.7704 25.3553 37.8084 25.3159 37.8561 25.315ZM14.0723 26.6521C14.1198 26.6477 14.1619 26.6827 14.1663 26.7302C14.1799 26.8776 14.1963 27.0243 14.2153 27.1701C14.2215 27.2174 14.1882 27.2607 14.1409 27.2669C14.0936 27.2731 14.0502 27.2397 14.0441 27.1924C14.0248 27.0445 14.0082 26.8957 13.9943 26.7461C13.9899 26.6986 14.0248 26.6565 14.0723 26.6521ZM37.8164 26.6521C37.8639 26.6565 37.8988 26.6986 37.8944 26.7461C37.8805 26.8957 37.8639 27.0445 37.8446 27.1924C37.8385 27.2397 37.7951 27.2731 37.7478 27.2669C37.7005 27.2607 37.6672 27.2174 37.6734 27.1701C37.6924 27.0243 37.7088 26.8776 37.7224 26.7302C37.7268 26.6827 37.7689 26.6477 37.8164 26.6521ZM14.2603 27.9749C14.307 27.9653 14.3527 27.9952 14.3624 28.0419C14.3925 28.1868 14.4252 28.3307 14.4606 28.4736C14.472 28.5199 14.4437 28.5667 14.3974 28.5781C14.3511 28.5896 14.3043 28.5613 14.2929 28.515C14.2571 28.37 14.2238 28.224 14.1933 28.0771C14.1836 28.0304 14.2136 27.9846 14.2603 27.9749ZM37.6284 27.975C37.6751 27.9846 37.7051 28.0304 37.6954 28.0771C37.6649 28.224 37.6316 28.37 37.5958 28.515C37.5844 28.5613 37.5376 28.5896 37.4913 28.5781C37.445 28.5667 37.4167 28.5199 37.4281 28.4736C37.4635 28.3307 37.4962 28.1868 37.5263 28.042C37.536 27.9953 37.5817 27.9653 37.6284 27.975ZM14.5961 29.2687C14.6414 29.2538 14.6902 29.2785 14.7051 29.3238C14.7512 29.4641 14.7999 29.6032 14.8511 29.7412C14.8677 29.7859 14.8449 29.8356 14.8002 29.8522C14.7555 29.8688 14.7058 29.846 14.6892 29.8013C14.6373 29.6613 14.5879 29.5201 14.541 29.3777C14.5261 29.3324 14.5508 29.2836 14.5961 29.2687ZM37.2926 29.2687C37.3379 29.2836 37.3626 29.3324 37.3477 29.3778C37.3008 29.5201 37.2514 29.6613 37.1995 29.8013C37.1829 29.846 37.1332 29.8688 37.0885 29.8522C37.0438 29.8356 37.021 29.7859 37.0376 29.7412C37.0888 29.6032 37.1375 29.4641 37.1836 29.3238C37.1985 29.2785 37.2473 29.2538 37.2926 29.2687ZM15.0755 30.5161C15.1189 30.4962 15.1702 30.5152 15.1901 30.5585C15.2517 30.6927 15.3158 30.8255 15.3823 30.9569C15.4038 30.9995 15.3868 31.0515 15.3442 31.073C15.3017 31.0945 15.2497 31.0775 15.2282 31.0349C15.1607 30.9015 15.0957 30.7668 15.0331 30.6306C15.0132 30.5873 15.0322 30.536 15.0755 30.5161ZM36.8132 30.5161C36.8565 30.536 36.8755 30.5873 36.8556 30.6306C36.793 30.7668 36.728 30.9016 36.6605 31.0349C36.639 31.0775 36.587 31.0945 36.5445 31.073C36.5019 31.0515 36.4849 30.9995 36.5064 30.9569C36.5729 30.8255 36.637 30.6927 36.6986 30.5585C36.7185 30.5152 36.7698 30.4962 36.8132 30.5161ZM15.6923 31.7014C15.7331 31.6768 15.7862 31.6899 15.8108 31.7307C15.8872 31.8571 15.9658 31.982 16.0466 32.1052C16.0728 32.1451 16.0617 32.1986 16.0218 32.2248C15.9819 32.2509 15.9284 32.2398 15.9022 32.1999C15.8202 32.0749 15.7404 31.9482 15.663 31.82C15.6383 31.7792 15.6515 31.7261 15.6923 31.7014ZM36.1964 31.7014C36.2372 31.7261 36.2504 31.7792 36.2257 31.82C36.1483 31.9482 36.0685 32.0749 35.9865 32.1999C35.9603 32.2398 35.9068 32.2509 35.8669 32.2248C35.827 32.1986 35.8159 32.1451 35.8421 32.1052C35.9229 31.982 36.0015 31.8571 36.0779 31.7307C36.1025 31.6899 36.1556 31.6768 36.1964 31.7014ZM16.4381 32.8104C16.4759 32.7814 16.5301 32.7885 16.5592 32.8263C16.6491 32.9433 16.7411 33.0585 16.8352 33.172C16.8657 33.2087 16.8606 33.2631 16.8239 33.2936C16.7872 33.324 16.7327 33.319 16.7023 33.2823C16.6068 33.1671 16.5134 33.0502 16.4222 32.9315C16.3932 32.8937 16.4003 32.8395 16.4381 32.8104ZM35.4506 32.8104C35.4884 32.8395 35.4955 32.8937 35.4665 32.9315C35.3753 33.0502 35.2819 33.1671 35.1864 33.2823C35.156 33.319 35.1015 33.324 35.0648 33.2936C35.0281 33.2631 35.023 33.2087 35.0535 33.172C35.1476 33.0585 35.2396 32.9433 35.3295 32.8263C35.3586 32.7885 35.4128 32.7814 35.4506 32.8104ZM17.3029 33.8292C17.3372 33.7962 17.3919 33.7972 17.425 33.8315C17.5273 33.9377 17.6316 34.042 17.7379 34.1444C17.7722 34.1775 17.7732 34.2321 17.7401 34.2665C17.707 34.3008 17.6524 34.3018 17.618 34.2687C17.5103 34.1649 17.4045 34.0591 17.3006 33.9513C17.2675 33.917 17.2686 33.8623 17.3029 33.8292ZM34.5858 33.8292C34.6201 33.8623 34.6212 33.917 34.5881 33.9514C34.4842 34.0591 34.3784 34.1649 34.2707 34.2687C34.2363 34.3018 34.1817 34.3008 34.1486 34.2665C34.1155 34.2321 34.1165 34.1775 34.1508 34.1444C34.2571 34.042 34.3614 33.9377 34.4637 33.8315C34.4968 33.7972 34.5515 33.7962 34.5858 33.8292ZM18.2758 34.7455C18.3062 34.7088 18.3607 34.7037 18.3974 34.7341C18.5108 34.8283 18.6261 34.9203 18.7431 35.0102C18.7809 35.0393 18.788 35.0935 18.7589 35.1313C18.7299 35.1691 18.6757 35.1762 18.6378 35.1471C18.5192 35.0559 18.4022 34.9626 18.2871 34.8671C18.2504 34.8366 18.2453 34.7822 18.2758 34.7455ZM33.6129 34.7455C33.6434 34.7822 33.6383 34.8366 33.6016 34.8671C33.4865 34.9626 33.3695 35.0559 33.2509 35.1471C33.213 35.1762 33.1588 35.1691 33.1298 35.1313C33.1007 35.0935 33.1078 35.0393 33.1456 35.0102C33.2626 34.9203 33.3779 34.8283 33.4913 34.7341C33.528 34.7037 33.5825 34.7088 33.6129 34.7455ZM19.3446 35.5476C19.3708 35.5077 19.4243 35.4966 19.4642 35.5227C19.5874 35.6036 19.7123 35.6822 19.8386 35.7585C19.8795 35.7832 19.8926 35.8363 19.8679 35.8771C19.8433 35.9179 19.7902 35.931 19.7494 35.9064C19.6211 35.8289 19.4945 35.7492 19.3694 35.6671C19.3296 35.641 19.3184 35.5874 19.3446 35.5476ZM32.5441 35.5476C32.5703 35.5874 32.5591 35.641 32.5193 35.6671C32.3942 35.7492 32.2676 35.8289 32.1393 35.9064C32.0985 35.931 32.0454 35.9179 32.0208 35.8771C31.9961 35.8363 32.0092 35.7832 32.0501 35.7585C32.1764 35.6822 32.3013 35.6036 32.4245 35.5227C32.4644 35.4966 32.5179 35.5077 32.5441 35.5476ZM20.4964 36.2251C20.5179 36.1826 20.5699 36.1655 20.6124 36.1871C20.7438 36.2535 20.8767 36.3176 21.0109 36.3793C21.0542 36.3992 21.0732 36.4505 21.0533 36.4938C21.0334 36.5372 20.9821 36.5562 20.9388 36.5362C20.8026 36.4737 20.6678 36.4086 20.5345 36.3412C20.4919 36.3197 20.4749 36.2677 20.4964 36.2251ZM31.3923 36.2252C31.4138 36.2677 31.3968 36.3197 31.3542 36.3412C31.2209 36.4086 31.0861 36.4737 30.9499 36.5362C30.9066 36.5562 30.8553 36.5372 30.8354 36.4938C30.8155 36.4505 30.8345 36.3992 30.8778 36.3793C31.012 36.3176 31.1448 36.2535 31.2763 36.1871C31.3188 36.1655 31.3708 36.1826 31.3923 36.2252ZM21.7172 36.7691C21.7338 36.7244 21.7835 36.7016 21.8282 36.7182C21.9661 36.7694 22.1053 36.8181 22.2456 36.8643C22.2909 36.8792 22.3155 36.928 22.3006 36.9733C22.2857 37.0186 22.2369 37.0432 22.1916 37.0283C22.0492 36.9815 21.9081 36.9321 21.7681 36.8801C21.7234 36.8636 21.7006 36.8139 21.7172 36.7691ZM30.1715 36.7691C30.1881 36.8139 30.1653 36.8636 30.1206 36.8801C29.9806 36.9321 29.8394 36.9815 29.6971 37.0283C29.6518 37.0432 29.603 37.0186 29.5881 36.9733C29.5732 36.928 29.5978 36.8792 29.6431 36.8643C29.7834 36.8181 29.9226 36.7694 30.0605 36.7182C30.1052 36.7016 30.1549 36.7244 30.1715 36.7691ZM22.9913 37.1719C23.0027 37.1256 23.0495 37.0974 23.0958 37.1088C23.2387 37.1441 23.3826 37.1769 23.5274 37.2069C23.5741 37.2166 23.6041 37.2623 23.5944 37.309C23.5847 37.3557 23.539 37.3857 23.4923 37.376C23.3453 37.3455 23.1993 37.3123 23.0544 37.2765C23.0081 37.265 22.9798 37.2182 22.9913 37.1719ZM28.8974 37.1719C28.9089 37.2182 28.8806 37.265 28.8343 37.2765C28.6894 37.3123 28.5434 37.3455 28.3964 37.376C28.3497 37.3857 28.304 37.3557 28.2943 37.309C28.2846 37.2623 28.3146 37.2166 28.3613 37.2069C28.5061 37.1769 28.65 37.1441 28.7929 37.1088C28.8392 37.0974 28.886 37.1256 28.8974 37.1719ZM24.3025 37.4285C24.3086 37.3812 24.352 37.3479 24.3993 37.354C24.5451 37.3731 24.6918 37.3894 24.8392 37.4031C24.8867 37.4075 24.9216 37.4496 24.9172 37.497C24.9128 37.5445 24.8708 37.5795 24.8233 37.5751C24.6737 37.5612 24.5249 37.5446 24.3769 37.5253C24.3296 37.5191 24.2963 37.4758 24.3025 37.4285ZM27.5862 37.4285C27.5924 37.4758 27.5591 37.5191 27.5118 37.5253C27.3638 37.5446 27.215 37.5612 27.0654 37.5751C27.0179 37.5795 26.9759 37.5445 26.9715 37.497C26.9671 37.4496 27.002 37.4075 27.0495 37.4031C27.1969 37.3894 27.3436 37.3731 27.4894 37.354C27.5367 37.3479 27.5801 37.3812 27.5862 37.4285ZM25.6344 37.5367C25.6352 37.4891 25.6746 37.4511 25.7223 37.452C25.7961 37.4533 25.8702 37.454 25.9444 37.454C26.0185 37.454 26.0925 37.4533 26.1664 37.452C26.2141 37.4511 26.2535 37.4891 26.2543 37.5367C26.2552 37.5844 26.2173 37.6238 26.1696 37.6247C26.0947 37.626 26.0196 37.6267 25.9444 37.6267C25.8691 37.6267 25.794 37.626 25.7191 37.6247C25.6714 37.6238 25.6335 37.5844 25.6344 37.5367Z\"\n      fill=\"white\"\n    />\n    <path\n      opacity=\"0.1\"\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M25.7243 9.72732C25.7975 9.72633 25.8709 9.72583 25.9443 9.72583C26.0178 9.72583 26.0911 9.72633 26.1643 9.72732C26.212 9.72797 26.2501 9.76715 26.2495 9.81484C26.2488 9.86253 26.2096 9.90066 26.162 9.90002C26.0895 9.89903 26.017 9.89854 25.9443 9.89854C25.8717 9.89854 25.7991 9.89903 25.7267 9.90002C25.679 9.90066 25.6398 9.86253 25.6392 9.81484C25.6385 9.76715 25.6766 9.72797 25.7243 9.72732ZM26.9478 9.84328C26.9511 9.7957 26.9923 9.75975 27.0398 9.76299C27.1858 9.77292 27.3312 9.78482 27.4761 9.79867C27.5235 9.80321 27.5583 9.84538 27.5538 9.89285C27.5493 9.94033 27.5071 9.97514 27.4596 9.9706C27.3163 9.9569 27.1725 9.94513 27.0281 9.9353C26.9805 9.93206 26.9446 9.89086 26.9478 9.84328ZM24.9408 9.84328C24.944 9.89086 24.9081 9.93206 24.8605 9.9353C24.7161 9.94513 24.5723 9.9569 24.429 9.9706C24.3815 9.97514 24.3394 9.94033 24.3348 9.89285C24.3303 9.84538 24.3651 9.80321 24.4126 9.79867C24.5574 9.78482 24.7028 9.77292 24.8488 9.76299C24.8964 9.75975 24.9376 9.7957 24.9408 9.84328ZM28.2471 9.97842C28.2543 9.93126 28.2983 9.89883 28.3455 9.90597C28.4904 9.92793 28.6348 9.95185 28.7785 9.97771C28.8254 9.98615 28.8566 10.0311 28.8482 10.078C28.8397 10.1249 28.7948 10.1561 28.7479 10.1477C28.6058 10.1221 28.463 10.0985 28.3196 10.0767C28.2724 10.0696 28.24 10.0256 28.2471 9.97842ZM23.6415 9.97842C23.6486 10.0256 23.6162 10.0696 23.5691 10.0767C23.4256 10.0985 23.2829 10.1221 23.1408 10.1477C23.0938 10.1561 23.0489 10.1249 23.0405 10.078C23.032 10.0311 23.0632 9.98615 23.1102 9.97771C23.2539 9.95185 23.3982 9.92793 23.5432 9.90597C23.5903 9.89883 23.6344 9.93126 23.6415 9.97842ZM29.5322 10.2207C29.5432 10.1743 29.5898 10.1457 29.6362 10.1567C29.7785 10.1905 29.92 10.2263 30.0608 10.2639C30.1069 10.2762 30.1342 10.3236 30.1219 10.3696C30.1096 10.4157 30.0623 10.4431 30.0162 10.4308C29.8769 10.3935 29.7369 10.3582 29.5962 10.3247C29.5498 10.3137 29.5211 10.2671 29.5322 10.2207ZM22.3565 10.2207C22.3675 10.2671 22.3388 10.3137 22.2924 10.3247C22.1517 10.3582 22.0117 10.3935 21.8724 10.4308C21.8264 10.4431 21.779 10.4157 21.7667 10.3696C21.7544 10.3236 21.7818 10.2762 21.8278 10.2639C21.9686 10.2263 22.1102 10.1905 22.2525 10.1567C22.2989 10.1457 22.3454 10.1743 22.3565 10.2207ZM30.7919 10.5688C30.8068 10.5235 30.8555 10.4988 30.9009 10.5137C31.0398 10.5592 31.1779 10.6066 31.3151 10.6559C31.36 10.672 31.3834 10.7214 31.3673 10.7663C31.3512 10.8112 31.3017 10.8345 31.2568 10.8184C31.1211 10.7697 30.9845 10.7228 30.8471 10.6778C30.8018 10.6629 30.7771 10.6141 30.7919 10.5688ZM21.0967 10.5688C21.1116 10.6141 21.0869 10.6629 21.0416 10.6778C20.9041 10.7228 20.7675 10.7697 20.6318 10.8184C20.5869 10.8345 20.5375 10.8112 20.5214 10.7663C20.5053 10.7214 20.5286 10.672 20.5735 10.6559C20.7107 10.6066 20.8488 10.5592 20.9878 10.5137C21.0331 10.4988 21.0819 10.5235 21.0967 10.5688ZM32.0181 11.0205C32.0367 10.9765 32.0873 10.956 32.1313 10.9745C32.2661 11.0315 32.3999 11.0903 32.5328 11.1509C32.5762 11.1707 32.5953 11.2219 32.5755 11.2653C32.5558 11.3087 32.5045 11.3279 32.4611 11.3081C32.3297 11.2482 32.1973 11.19 32.064 11.1336C32.0201 11.115 31.9995 11.0644 32.0181 11.0205ZM19.8706 11.0205C19.8891 11.0644 19.8686 11.115 19.8246 11.1336C19.6913 11.19 19.5589 11.2482 19.4275 11.3081C19.3841 11.3279 19.3329 11.3087 19.3131 11.2653C19.2933 11.2219 19.3125 11.1707 19.3558 11.1509C19.4887 11.0903 19.6226 11.0315 19.7574 10.9745C19.8013 10.956 19.852 10.9765 19.8706 11.0205ZM33.2031 11.5727C33.2253 11.5305 33.2775 11.5142 33.3197 11.5363C33.4491 11.6042 33.5775 11.6739 33.7048 11.7452C33.7465 11.7685 33.7613 11.8212 33.738 11.8628C33.7147 11.9044 33.662 11.9192 33.6204 11.8959C33.4945 11.8253 33.3675 11.7565 33.2395 11.6893C33.1972 11.6671 33.1809 11.6149 33.2031 11.5727ZM18.6855 11.5727C18.7077 11.6149 18.6914 11.6671 18.6492 11.6893C18.5211 11.7565 18.3941 11.8253 18.2682 11.8959C18.2266 11.9192 18.174 11.9044 18.1507 11.8628C18.1274 11.8212 18.1422 11.7685 18.1838 11.7452C18.3111 11.6739 18.4395 11.6042 18.5689 11.5363C18.6112 11.5142 18.6634 11.5305 18.6855 11.5727ZM34.338 12.2211C34.3636 12.1808 34.417 12.1689 34.4572 12.1945C34.5805 12.2728 34.7027 12.3528 34.8237 12.4344C34.8632 12.4611 34.8737 12.5147 34.847 12.5543C34.8203 12.5938 34.7667 12.6042 34.7271 12.5776C34.6074 12.4969 34.4866 12.4178 34.3646 12.3403C34.3244 12.3147 34.3125 12.2613 34.338 12.2211ZM17.5506 12.2211C17.5762 12.2613 17.5643 12.3147 17.524 12.3403C17.402 12.4178 17.2812 12.4969 17.1615 12.5776C17.122 12.6042 17.0683 12.5938 17.0416 12.5543C17.015 12.5147 17.0254 12.4611 17.0649 12.4344C17.1859 12.3528 17.3081 12.2728 17.4314 12.1945C17.4717 12.1689 17.525 12.1808 17.5506 12.2211ZM35.4155 12.9609C35.4443 12.9229 35.4985 12.9154 35.5365 12.9442C35.6529 13.0324 35.7682 13.1222 35.8821 13.2136C35.9193 13.2434 35.9253 13.2978 35.8955 13.335C35.8656 13.3722 35.8113 13.3782 35.7741 13.3483C35.6614 13.258 35.5474 13.1691 35.4322 13.0819C35.3942 13.0531 35.3867 12.9989 35.4155 12.9609ZM16.4731 12.9609C16.5019 12.9989 16.4945 13.0531 16.4565 13.0819C16.3412 13.1691 16.2273 13.258 16.1146 13.3483C16.0774 13.3782 16.023 13.3722 15.9932 13.335C15.9633 13.2978 15.9693 13.2434 16.0065 13.2136C16.1205 13.1222 16.2357 13.0324 16.3522 12.9442C16.3902 12.9154 16.4443 12.9229 16.4731 12.9609ZM36.4285 13.7869C36.4604 13.7514 36.5149 13.7484 36.5505 13.7802C36.6593 13.8777 36.7667 13.9767 36.8728 14.0771C36.9074 14.1099 36.9089 14.1645 36.8761 14.1991C36.8433 14.2338 36.7887 14.2353 36.754 14.2025C36.6491 14.1032 36.5428 14.0053 36.4352 13.9088C36.3997 13.877 36.3967 13.8224 36.4285 13.7869ZM15.4601 13.7869C15.4919 13.8224 15.4889 13.877 15.4534 13.9088C15.3458 14.0053 15.2395 14.1032 15.1346 14.2025C15.1 14.2353 15.0453 14.2338 15.0125 14.1991C14.9797 14.1645 14.9812 14.1099 15.0159 14.0771C15.1219 13.9767 15.2294 13.8777 15.3382 13.7802C15.3737 13.7484 15.4283 13.7514 15.4601 13.7869ZM37.3703 14.6933C37.4049 14.6605 37.4596 14.662 37.4924 14.6967C37.5928 14.8027 37.6917 14.9102 37.7892 15.019C37.821 15.0545 37.818 15.1091 37.7825 15.1409C37.747 15.1727 37.6924 15.1697 37.6606 15.1342C37.5641 15.0266 37.4663 14.9203 37.3669 14.8154C37.3341 14.7808 37.3356 14.7261 37.3703 14.6933ZM14.5184 14.6933C14.553 14.7261 14.5545 14.7808 14.5217 14.8154C14.4224 14.9203 14.3245 15.0266 14.2281 15.1342C14.1962 15.1697 14.1416 15.1727 14.1061 15.1409C14.0706 15.1091 14.0676 15.0545 14.0994 15.019C14.1969 14.9102 14.2959 14.8027 14.3963 14.6967C14.4291 14.662 14.4837 14.6605 14.5184 14.6933ZM38.2344 15.674C38.2716 15.6441 38.326 15.6501 38.3558 15.6873C38.4472 15.8013 38.537 15.9165 38.6252 16.033C38.654 16.071 38.6466 16.1251 38.6085 16.1539C38.5705 16.1827 38.5164 16.1753 38.4876 16.1372C38.4003 16.022 38.3114 15.9081 38.2211 15.7954C38.1912 15.7581 38.1972 15.7038 38.2344 15.674ZM13.6542 15.674C13.6914 15.7038 13.6974 15.7581 13.6676 15.7954C13.5772 15.9081 13.4884 16.022 13.4011 16.1372C13.3723 16.1753 13.3181 16.1827 13.2801 16.1539C13.2421 16.1251 13.2346 16.071 13.2634 16.033C13.3517 15.9165 13.4415 15.8013 13.5328 15.6873C13.5626 15.6501 13.617 15.6441 13.6542 15.674ZM39.0151 16.7224C39.0547 16.6958 39.1084 16.7062 39.135 16.7457C39.2166 16.8667 39.2966 16.9889 39.3749 17.1122C39.4005 17.1525 39.3886 17.2058 39.3483 17.2314C39.3081 17.257 39.2547 17.2451 39.2291 17.2048C39.1517 17.0828 39.0726 16.962 38.9918 16.8423C38.9652 16.8028 38.9756 16.7491 39.0151 16.7224ZM12.8735 16.7224C12.913 16.7491 12.9235 16.8028 12.8968 16.8423C12.8161 16.962 12.737 17.0828 12.6595 17.2048C12.6339 17.2451 12.5806 17.257 12.5403 17.2314C12.5 17.2058 12.4881 17.1525 12.5137 17.1122C12.592 16.9889 12.672 16.8667 12.7536 16.7457C12.7803 16.7062 12.8339 16.6958 12.8735 16.7224ZM39.7067 17.8315C39.7483 17.8081 39.8009 17.823 39.8242 17.8646C39.8955 17.9919 39.9652 18.1203 40.0331 18.2497C40.0552 18.292 40.039 18.3442 39.9967 18.3663C39.9545 18.3885 39.9023 18.3722 39.8801 18.33C39.813 18.2019 39.7441 18.0749 39.6735 17.949C39.6502 17.9074 39.665 17.8548 39.7067 17.8315ZM12.182 17.8315C12.2236 17.8548 12.2384 17.9074 12.2151 17.949C12.1445 18.0749 12.0757 18.2019 12.0085 18.33C11.9863 18.3722 11.9341 18.3885 11.8919 18.3663C11.8497 18.3442 11.8334 18.292 11.8556 18.2497C11.9235 18.1203 11.9931 17.9919 12.0644 17.8646C12.0877 17.823 12.1404 17.8081 12.182 17.8315ZM40.3041 18.9939C40.3475 18.9741 40.3987 18.9932 40.4185 19.0366C40.4791 19.1695 40.5379 19.3034 40.5949 19.4382C40.6134 19.4821 40.5929 19.5328 40.549 19.5513C40.505 19.5699 40.4544 19.5494 40.4358 19.5054C40.3794 19.3721 40.3213 19.2397 40.2613 19.1083C40.2416 19.0649 40.2607 19.0137 40.3041 18.9939ZM11.5845 18.9939C11.6279 19.0137 11.6471 19.0649 11.6273 19.1083C11.5674 19.2397 11.5092 19.3721 11.4528 19.5054C11.4343 19.5494 11.3836 19.5699 11.3397 19.5513C11.2957 19.5328 11.2752 19.4821 11.2938 19.4382C11.3508 19.3034 11.4096 19.1695 11.4701 19.0366C11.4899 18.9932 11.5411 18.9741 11.5845 18.9939ZM40.8031 20.2022C40.848 20.186 40.8974 20.2094 40.9136 20.2543C40.9628 20.3915 41.0102 20.5296 41.0558 20.6686C41.0706 20.7139 41.0459 20.7627 41.0006 20.7775C40.9553 20.7924 40.9065 20.7677 40.8916 20.7224C40.8466 20.5849 40.7997 20.4483 40.751 20.3126C40.7349 20.2677 40.7582 20.2183 40.8031 20.2022ZM11.0855 20.2022C11.1304 20.2183 11.1537 20.2677 11.1376 20.3126C11.0889 20.4483 11.042 20.5849 10.997 20.7224C10.9821 20.7677 10.9334 20.7924 10.888 20.7775C10.8427 20.7627 10.818 20.7139 10.8329 20.6686C10.8784 20.5296 10.9258 20.3915 10.9751 20.2543C10.9912 20.2094 11.0406 20.1861 11.0855 20.2022ZM41.1998 21.4475C41.2459 21.4352 41.2932 21.4626 41.3055 21.5086C41.3431 21.6494 41.3789 21.791 41.4127 21.9333C41.4238 21.9797 41.3951 22.0262 41.3487 22.0372C41.3023 22.0483 41.2557 22.0196 41.2447 21.9732C41.2112 21.8325 41.1759 21.6925 41.1387 21.5532C41.1263 21.5072 41.1537 21.4598 41.1998 21.4475ZM10.6889 21.4475C10.7349 21.4598 10.7623 21.5072 10.75 21.5532C10.7128 21.6925 10.6774 21.8325 10.6439 21.9732C10.6329 22.0196 10.5863 22.0483 10.5399 22.0372C10.4935 22.0262 10.4649 21.9797 10.4759 21.9333C10.5097 21.791 10.5455 21.6494 10.5831 21.5086C10.5954 21.4626 10.6428 21.4352 10.6889 21.4475ZM41.4914 22.7213C41.5384 22.7128 41.5833 22.744 41.5917 22.791C41.6176 22.9346 41.6415 23.079 41.6635 23.224C41.6706 23.2711 41.6382 23.3151 41.591 23.3223C41.5439 23.3294 41.4998 23.297 41.4927 23.2498C41.471 23.1064 41.4473 22.9637 41.4217 22.8216C41.4133 22.7746 41.4445 22.7297 41.4914 22.7213ZM10.3972 22.7213C10.4441 22.7297 10.4753 22.7746 10.4669 22.8216C10.4413 22.9637 10.4177 23.1064 10.3959 23.2498C10.3888 23.297 10.3448 23.3294 10.2976 23.3223C10.2505 23.3151 10.218 23.2711 10.2252 23.224C10.2471 23.079 10.2711 22.9346 10.2969 22.791C10.3054 22.744 10.3503 22.7128 10.3972 22.7213ZM41.6766 24.0156C41.724 24.0111 41.7662 24.0459 41.7708 24.0934C41.7846 24.2382 41.7965 24.3836 41.8064 24.5296C41.8097 24.5772 41.7737 24.6184 41.7261 24.6216C41.6786 24.6248 41.6374 24.5889 41.6341 24.5413C41.6243 24.3969 41.6125 24.2531 41.5988 24.1098C41.5943 24.0623 41.6291 24.0201 41.6766 24.0156ZM10.2121 24.0156C10.2595 24.0202 10.2944 24.0623 10.2898 24.1098C10.2761 24.2531 10.2643 24.3969 10.2545 24.5413C10.2513 24.5889 10.2101 24.6248 10.1625 24.6216C10.1149 24.6184 10.079 24.5772 10.0822 24.5296C10.0921 24.3836 10.104 24.2382 10.1179 24.0934C10.1224 24.0459 10.1646 24.0111 10.2121 24.0156ZM41.7546 25.3199C41.8023 25.3193 41.8415 25.3574 41.8421 25.4051C41.8431 25.4783 41.8436 25.5517 41.8436 25.6251C41.8436 25.6985 41.8431 25.7719 41.8421 25.8451C41.8415 25.8928 41.8023 25.9309 41.7546 25.9303C41.7069 25.9296 41.6688 25.8904 41.6694 25.8427C41.6704 25.7703 41.6709 25.6978 41.6709 25.6251C41.6709 25.5524 41.6704 25.4799 41.6694 25.4075C41.6688 25.3598 41.7069 25.3206 41.7546 25.3199ZM10.1341 25.3199C10.1817 25.3206 10.2199 25.3598 10.2192 25.4075C10.2182 25.4799 10.2178 25.5524 10.2178 25.6251C10.2178 25.6978 10.2182 25.7703 10.2192 25.8427C10.2199 25.8904 10.1817 25.9296 10.1341 25.9303C10.0864 25.9309 10.0472 25.8928 10.0465 25.8451C10.0455 25.7719 10.045 25.6985 10.045 25.6251C10.045 25.5517 10.0455 25.4783 10.0465 25.4051C10.0472 25.3574 10.0864 25.3193 10.1341 25.3199ZM41.7261 26.6286C41.7737 26.6318 41.8097 26.673 41.8064 26.7206C41.7965 26.8666 41.7846 27.012 41.7708 27.1569C41.7662 27.2043 41.724 27.2391 41.6766 27.2346C41.6291 27.2301 41.5943 27.1879 41.5988 27.1404C41.6125 26.9971 41.6243 26.8533 41.6341 26.7089C41.6374 26.6613 41.6786 26.6254 41.7261 26.6286ZM10.1625 26.6286C10.2101 26.6254 10.2513 26.6613 10.2545 26.7089C10.2643 26.8533 10.2761 26.9971 10.2898 27.1404C10.2944 27.1879 10.2595 27.2301 10.2121 27.2346C10.1646 27.2391 10.1224 27.2043 10.1179 27.1569C10.104 27.012 10.0921 26.8666 10.0822 26.7206C10.079 26.6731 10.1149 26.6319 10.1625 26.6286ZM41.591 27.9279C41.6382 27.9351 41.6706 27.9791 41.6635 28.0262C41.6415 28.1712 41.6176 28.3156 41.5917 28.4592C41.5833 28.5062 41.5384 28.5374 41.4914 28.5289C41.4445 28.5205 41.4133 28.4756 41.4217 28.4287C41.4473 28.2865 41.471 28.1438 41.4927 28.0004C41.4998 27.9532 41.5439 27.9208 41.591 27.9279ZM10.2976 27.9279C10.3448 27.9208 10.3888 27.9532 10.3959 28.0004C10.4177 28.1438 10.4413 28.2866 10.4669 28.4287C10.4753 28.4756 10.4441 28.5205 10.3972 28.5289C10.3503 28.5374 10.3054 28.5062 10.2969 28.4592C10.2711 28.3156 10.2471 28.1712 10.2252 28.0262C10.218 27.9791 10.2505 27.9351 10.2976 27.9279ZM41.3487 29.213C41.3951 29.224 41.4238 29.2706 41.4127 29.317C41.3789 29.4592 41.3431 29.6008 41.3055 29.7416C41.2932 29.7876 41.2459 29.815 41.1998 29.8027C41.1537 29.7904 41.1263 29.743 41.1387 29.697C41.1759 29.5577 41.2112 29.4177 41.2447 29.277C41.2557 29.2306 41.3023 29.2019 41.3487 29.213ZM10.5399 29.213C10.5863 29.2019 10.6329 29.2306 10.6439 29.277C10.6774 29.4177 10.7128 29.5577 10.75 29.697C10.7623 29.7431 10.7349 29.7904 10.6889 29.8027C10.6428 29.815 10.5954 29.7877 10.5831 29.7416C10.5455 29.6008 10.5097 29.4592 10.4759 29.317C10.4649 29.2706 10.4935 29.224 10.5399 29.213ZM41.0006 30.4727C41.0459 30.4876 41.0706 30.5363 41.0558 30.5817C41.0102 30.7206 40.9628 30.8587 40.9136 30.9959C40.8974 31.0408 40.848 31.0642 40.8031 31.048C40.7582 31.0319 40.7349 30.9825 40.751 30.9376C40.7997 30.8019 40.8466 30.6653 40.8916 30.5279C40.9065 30.4825 40.9553 30.4578 41.0006 30.4727ZM10.888 30.4727C10.9334 30.4578 10.9821 30.4825 10.997 30.5279C11.042 30.6653 11.0889 30.8019 11.1376 30.9376C11.1538 30.9825 11.1304 31.0319 11.0855 31.048C11.0406 31.0642 10.9912 31.0408 10.9751 30.9959C10.9258 30.8587 10.8784 30.7206 10.8329 30.5817C10.818 30.5363 10.8427 30.4876 10.888 30.4727ZM40.549 31.6989C40.5929 31.7174 40.6135 31.7681 40.5949 31.812C40.5379 31.9468 40.4791 32.0807 40.4185 32.2136C40.3987 32.257 40.3475 32.2761 40.3041 32.2563C40.2607 32.2365 40.2416 32.1853 40.2613 32.1419C40.3213 32.0105 40.3794 31.8781 40.4358 31.7448C40.4544 31.7009 40.505 31.6803 40.549 31.6989ZM11.3397 31.6989C11.3836 31.6803 11.4343 31.7009 11.4528 31.7448C11.5092 31.8781 11.5674 32.0105 11.6273 32.1419C11.6471 32.1853 11.6279 32.2365 11.5845 32.2563C11.5411 32.2761 11.4899 32.257 11.4701 32.2136C11.4096 32.0807 11.3508 31.9468 11.2938 31.812C11.2752 31.7681 11.2957 31.7174 11.3397 31.6989ZM39.9967 32.8839C40.039 32.906 40.0552 32.9582 40.0331 33.0005C39.9652 33.1299 39.8955 33.2583 39.8242 33.3856C39.8009 33.4272 39.7483 33.4421 39.7067 33.4188C39.6651 33.3954 39.6502 33.3428 39.6735 33.3012C39.7441 33.1753 39.813 33.0483 39.8801 32.9202C39.9023 32.878 39.9545 32.8617 39.9967 32.8839ZM11.8919 32.8839C11.9342 32.8617 11.9863 32.878 12.0085 32.9202C12.0757 33.0483 12.1445 33.1753 12.2151 33.3012C12.2384 33.3428 12.2236 33.3954 12.182 33.4188C12.1404 33.4421 12.0877 33.4272 12.0644 33.3856C11.9931 33.2583 11.9235 33.1299 11.8556 33.0005C11.8334 32.9582 11.8497 32.906 11.8919 32.8839ZM39.3483 34.0188C39.3886 34.0444 39.4005 34.0977 39.3749 34.138C39.2966 34.2613 39.2166 34.3835 39.135 34.5045C39.1084 34.544 39.0547 34.5544 39.0151 34.5278C38.9756 34.5011 38.9652 34.4474 38.9918 34.4079C39.0726 34.2882 39.1517 34.1674 39.2291 34.0454C39.2547 34.0051 39.3081 33.9932 39.3483 34.0188ZM12.5403 34.0188C12.5806 33.9932 12.6339 34.0051 12.6595 34.0454C12.737 34.1674 12.8161 34.2882 12.8968 34.4079C12.9235 34.4474 12.913 34.5011 12.8735 34.5278C12.8339 34.5545 12.7803 34.544 12.7536 34.5045C12.672 34.3835 12.592 34.2613 12.5137 34.138C12.4881 34.0977 12.5 34.0444 12.5403 34.0188ZM13.2801 35.0963C13.3181 35.0675 13.3723 35.0749 13.4011 35.113C13.4884 35.2282 13.5772 35.3422 13.6676 35.4549C13.6974 35.4921 13.6914 35.5464 13.6542 35.5762C13.617 35.6061 13.5626 35.6001 13.5328 35.5629C13.4415 35.449 13.3517 35.3337 13.2634 35.2173C13.2346 35.1792 13.2421 35.1251 13.2801 35.0963ZM38.6085 35.0963C38.6466 35.1251 38.654 35.1792 38.6252 35.2173C38.537 35.3337 38.4472 35.449 38.3558 35.5629C38.326 35.6001 38.2717 35.6061 38.2344 35.5762C38.1972 35.5464 38.1912 35.4921 38.2211 35.4549C38.3114 35.3421 38.4003 35.2282 38.4876 35.113C38.5164 35.0749 38.5705 35.0675 38.6085 35.0963ZM14.1061 36.1093C14.1416 36.0775 14.1962 36.0805 14.2281 36.116C14.3245 36.2236 14.4224 36.3299 14.5217 36.4348C14.5545 36.4695 14.553 36.5241 14.5184 36.5569C14.4837 36.5897 14.4291 36.5882 14.3963 36.5536C14.2959 36.4475 14.1969 36.34 14.0994 36.2313C14.0676 36.1957 14.0706 36.1411 14.1061 36.1093ZM37.7825 36.1093C37.818 36.1411 37.821 36.1957 37.7892 36.2312C37.6917 36.34 37.5928 36.4475 37.4924 36.5535C37.4596 36.5882 37.4049 36.5897 37.3703 36.5569C37.3356 36.5241 37.3341 36.4694 37.3669 36.4348C37.4663 36.3299 37.5641 36.2236 37.6606 36.116C37.6924 36.0805 37.747 36.0775 37.7825 36.1093ZM15.0125 37.0511C15.0453 37.0164 15.1 37.0149 15.1346 37.0477C15.2395 37.147 15.3458 37.2449 15.4534 37.3414C15.4889 37.3732 15.4919 37.4278 15.4601 37.4633C15.4283 37.4988 15.3737 37.5018 15.3382 37.47C15.2294 37.3725 15.1219 37.2735 15.0159 37.1731C14.9812 37.1404 14.9797 37.0857 15.0125 37.0511ZM36.8761 37.0511C36.9089 37.0857 36.9074 37.1404 36.8728 37.1731C36.7667 37.2735 36.6593 37.3725 36.5505 37.47C36.5149 37.5018 36.4604 37.4988 36.4285 37.4633C36.3967 37.4278 36.3997 37.3732 36.4352 37.3414C36.5428 37.2449 36.6491 37.147 36.754 37.0477C36.7887 37.0149 36.8433 37.0164 36.8761 37.0511ZM35.8955 37.9152C35.9253 37.9524 35.9193 38.0068 35.8821 38.0366C35.7682 38.128 35.6529 38.2178 35.5365 38.306C35.4985 38.3348 35.4443 38.3273 35.4155 38.2893C35.3867 38.2513 35.3942 38.1971 35.4322 38.1683C35.5474 38.0811 35.6614 37.9922 35.7741 37.9019C35.8113 37.872 35.8656 37.878 35.8955 37.9152ZM15.9932 37.9152C16.023 37.878 16.0774 37.872 16.1146 37.9019C16.2273 37.9922 16.3412 38.0811 16.4565 38.1683C16.4945 38.1971 16.5019 38.2513 16.4731 38.2893C16.4443 38.3273 16.3902 38.3348 16.3522 38.306C16.2357 38.2178 16.1205 38.128 16.0065 38.0366C15.9693 38.0068 15.9633 37.9524 15.9932 37.9152ZM34.847 38.6959C34.8737 38.7355 34.8632 38.7891 34.8237 38.8158C34.7027 38.8974 34.5805 38.9774 34.4572 39.0557C34.417 39.0813 34.3636 39.0694 34.338 39.0291C34.3125 38.9889 34.3244 38.9355 34.3646 38.9099C34.4866 38.8325 34.6074 38.7533 34.7271 38.6726C34.7667 38.646 34.8203 38.6564 34.847 38.6959ZM17.0416 38.6959C17.0683 38.6564 17.122 38.646 17.1615 38.6726C17.2812 38.7533 17.402 38.8325 17.524 38.9099C17.5643 38.9355 17.5762 38.9889 17.5506 39.0291C17.525 39.0694 17.4717 39.0813 17.4314 39.0557C17.3081 38.9774 17.1859 38.8974 17.0649 38.8158C17.0254 38.7891 17.015 38.7355 17.0416 38.6959ZM18.1507 39.3874C18.174 39.3458 18.2266 39.331 18.2682 39.3543C18.3941 39.4249 18.5211 39.4938 18.6492 39.5609C18.6914 39.5831 18.7077 39.6353 18.6855 39.6775C18.6634 39.7197 18.6112 39.736 18.5689 39.7139C18.4395 39.646 18.3111 39.5763 18.1838 39.505C18.1422 39.4817 18.1274 39.4291 18.1507 39.3874ZM33.738 39.3874C33.7613 39.4291 33.7465 39.4817 33.7048 39.505C33.5775 39.5763 33.4491 39.646 33.3197 39.7139C33.2775 39.736 33.2253 39.7197 33.2031 39.6775C33.1809 39.6353 33.1972 39.5831 33.2395 39.5609C33.3675 39.4938 33.4945 39.4249 33.6204 39.3543C33.662 39.331 33.7147 39.3458 33.738 39.3874ZM19.3131 39.9849C19.3329 39.9415 19.3841 39.9223 19.4275 39.9421C19.5589 40.0021 19.6913 40.0602 19.8246 40.1166C19.8686 40.1352 19.8891 40.1858 19.8706 40.2298C19.852 40.2737 19.8013 40.2942 19.7574 40.2757C19.6226 40.2187 19.4887 40.1599 19.3559 40.0993C19.3125 40.0795 19.2933 40.0283 19.3131 39.9849ZM32.5755 39.9849C32.5953 40.0283 32.5762 40.0795 32.5328 40.0993C32.3999 40.1599 32.2661 40.2187 32.1313 40.2757C32.0873 40.2942 32.0367 40.2737 32.0181 40.2298C31.9995 40.1858 32.0201 40.1352 32.064 40.1166C32.1973 40.0602 32.3297 40.0021 32.4611 39.9421C32.5045 39.9223 32.5558 39.9415 32.5755 39.9849ZM20.5214 40.4839C20.5375 40.439 20.5869 40.4157 20.6318 40.4318C20.7675 40.4805 20.9041 40.5274 21.0416 40.5724C21.0869 40.5873 21.1116 40.6361 21.0967 40.6814C21.0819 40.7267 21.0331 40.7514 20.9878 40.7365C20.8488 40.691 20.7107 40.6436 20.5735 40.5943C20.5286 40.5782 20.5053 40.5288 20.5214 40.4839ZM31.3673 40.4839C31.3834 40.5288 31.36 40.5782 31.3151 40.5943C31.1779 40.6436 31.0398 40.691 30.9009 40.7365C30.8555 40.7514 30.8068 40.7267 30.7919 40.6814C30.7771 40.6361 30.8018 40.5873 30.8471 40.5724C30.9845 40.5274 31.1211 40.4805 31.2568 40.4318C31.3017 40.4157 31.3512 40.439 31.3673 40.4839ZM21.7667 40.8806C21.779 40.8345 21.8264 40.8071 21.8724 40.8194C22.0117 40.8567 22.1517 40.892 22.2924 40.9255C22.3388 40.9365 22.3675 40.9831 22.3565 41.0295C22.3454 41.0759 22.2989 41.1045 22.2525 41.0935C22.1102 41.0597 21.9686 41.0239 21.8278 40.9863C21.7818 40.974 21.7544 40.9266 21.7667 40.8806ZM30.1219 40.8806C30.1342 40.9266 30.1069 40.974 30.0608 40.9863C29.92 41.0239 29.7785 41.0597 29.6362 41.0935C29.5898 41.1045 29.5432 41.0759 29.5322 41.0295C29.5211 40.9831 29.5498 40.9365 29.5962 40.9255C29.7369 40.892 29.8769 40.8567 30.0162 40.8194C30.0623 40.8071 30.1096 40.8345 30.1219 40.8806ZM28.8482 41.1722C28.8566 41.2192 28.8254 41.2641 28.7785 41.2725C28.6348 41.2984 28.4904 41.3223 28.3455 41.3442C28.2983 41.3514 28.2543 41.3189 28.2471 41.2718C28.24 41.2246 28.2724 41.1806 28.3196 41.1735C28.463 41.1518 28.6058 41.1281 28.7479 41.1025C28.7948 41.0941 28.8397 41.1253 28.8482 41.1722ZM23.0405 41.1722C23.0489 41.1253 23.0938 41.0941 23.1408 41.1025C23.2829 41.1281 23.4256 41.1518 23.5691 41.1735C23.6162 41.1806 23.6486 41.2246 23.6415 41.2718C23.6344 41.3189 23.5903 41.3514 23.5432 41.3442C23.3982 41.3223 23.2539 41.2984 23.1102 41.2725C23.0632 41.2641 23.032 41.2192 23.0405 41.1722ZM24.3348 41.3574C24.3394 41.3099 24.3815 41.2751 24.429 41.2796C24.5723 41.2933 24.7161 41.3051 24.8605 41.3149C24.9081 41.3181 24.9441 41.3593 24.9408 41.4069C24.9376 41.4545 24.8964 41.4905 24.8488 41.4872C24.7028 41.4773 24.5574 41.4654 24.4126 41.4515C24.3651 41.447 24.3303 41.4048 24.3348 41.3574ZM27.5538 41.3574C27.5584 41.4048 27.5235 41.447 27.4761 41.4515C27.3312 41.4654 27.1858 41.4773 27.0398 41.4872C26.9923 41.4905 26.9511 41.4545 26.9478 41.4069C26.9446 41.3593 26.9805 41.3181 27.0281 41.3149C27.1725 41.3051 27.3163 41.2933 27.4596 41.2796C27.5071 41.2751 27.5493 41.3099 27.5538 41.3574ZM25.6392 41.4354C25.6398 41.3877 25.679 41.3495 25.7267 41.3502C25.7991 41.3512 25.8717 41.3517 25.9443 41.3517C26.017 41.3517 26.0895 41.3512 26.162 41.3502C26.2097 41.3495 26.2488 41.3877 26.2495 41.4354C26.2501 41.4831 26.212 41.5222 26.1643 41.5229C26.0911 41.5239 26.0178 41.5244 25.9443 41.5244C25.8709 41.5244 25.7975 41.5239 25.7243 41.5229C25.6766 41.5222 25.6385 41.4831 25.6392 41.4354Z\"\n      fill=\"white\"\n    />\n    <path\n      opacity=\"0.07\"\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M25.7286 5.94061C25.8004 5.93984 25.8723 5.93945 25.9443 5.93945C26.0163 5.93945 26.0882 5.93984 26.16 5.94061C26.2077 5.94112 26.2459 5.9802 26.2454 6.02789C26.2449 6.07558 26.2058 6.11382 26.1582 6.11331C26.087 6.11255 26.0157 6.11216 25.9443 6.11216C25.8729 6.11216 25.8017 6.11255 25.7305 6.11331C25.6828 6.11382 25.6437 6.07558 25.6432 6.02789C25.6427 5.9802 25.6809 5.94112 25.7286 5.94061ZM26.927 6.04983C26.9295 6.0022 26.9702 5.96567 27.0178 5.96823C27.1614 5.97595 27.3046 5.98521 27.4474 5.99599C27.495 5.99958 27.5306 6.04104 27.527 6.0886C27.5234 6.13616 27.482 6.1718 27.4344 6.16821C27.2929 6.15752 27.1509 6.14834 27.0086 6.14069C26.9609 6.13813 26.9244 6.09745 26.927 6.04983ZM24.9616 6.04983C24.9642 6.09745 24.9277 6.13813 24.8801 6.14069C24.7377 6.14834 24.5957 6.15752 24.4542 6.16821C24.4066 6.1718 24.3652 6.13616 24.3616 6.0886C24.358 6.04104 24.3936 5.99958 24.4412 5.99599C24.584 5.98521 24.7272 5.97595 24.8708 5.96823C24.9184 5.96567 24.9591 6.0022 24.9616 6.04983ZM28.2061 6.15472C28.2118 6.10736 28.2548 6.07356 28.3021 6.07921C28.4445 6.0962 28.5864 6.11471 28.7278 6.13473C28.775 6.14141 28.8079 6.18511 28.8012 6.23233C28.7945 6.27956 28.7508 6.31242 28.7036 6.30573C28.5634 6.2859 28.4228 6.26755 28.2816 6.2507C28.2343 6.24505 28.2005 6.20208 28.2061 6.15472ZM23.6825 6.15472C23.6881 6.20208 23.6543 6.24505 23.607 6.2507C23.4659 6.26755 23.3252 6.2859 23.1851 6.30574C23.1378 6.31242 23.0941 6.27956 23.0874 6.23233C23.0808 6.18511 23.1136 6.14141 23.1609 6.13473C23.3023 6.11471 23.4441 6.0962 23.5865 6.07921C23.6339 6.07356 23.6768 6.10736 23.6825 6.15472ZM29.4749 6.34276C29.4836 6.29588 29.5287 6.26496 29.5756 6.2737C29.7164 6.29996 29.8566 6.32771 29.9964 6.35695C30.0431 6.36671 30.073 6.41248 30.0632 6.45916C30.0534 6.50584 30.0077 6.53577 29.961 6.526C29.8225 6.49702 29.6835 6.46951 29.5439 6.44349C29.497 6.43474 29.4661 6.38965 29.4749 6.34276ZM22.4138 6.34276C22.4225 6.38965 22.3916 6.43474 22.3447 6.44349C22.2051 6.46951 22.0661 6.49702 21.9276 6.526C21.8809 6.53577 21.8352 6.50584 21.8254 6.45916C21.8156 6.41248 21.8456 6.36672 21.8923 6.35695C22.032 6.32771 22.1722 6.29996 22.313 6.2737C22.3599 6.26496 22.405 6.29588 22.4138 6.34276ZM30.7279 6.61354C30.7397 6.56734 30.7867 6.53945 30.8329 6.55126C30.9721 6.58681 31.1106 6.62384 31.2485 6.66234C31.2944 6.67516 31.3213 6.72279 31.3085 6.76873C31.2956 6.81467 31.248 6.84151 31.2021 6.82869C31.0654 6.79053 30.9281 6.75383 30.7902 6.71859C30.744 6.70678 30.7161 6.65975 30.7279 6.61354ZM21.1607 6.61355C21.1725 6.65975 21.1446 6.70679 21.0984 6.71859C20.9605 6.75383 20.8232 6.79054 20.6866 6.82869C20.6406 6.84151 20.593 6.81467 20.5802 6.76873C20.5673 6.7228 20.5942 6.67516 20.6401 6.66234C20.778 6.62384 20.9166 6.58681 21.0557 6.55126C21.1019 6.53945 21.1489 6.56734 21.1607 6.61355ZM31.9615 6.9666C31.9763 6.92127 32.0251 6.89654 32.0704 6.91137C32.2067 6.95594 32.3422 7.00196 32.4771 7.0494C32.5221 7.06522 32.5458 7.11452 32.53 7.15951C32.5141 7.2045 32.4648 7.22815 32.4198 7.21233C32.2861 7.1653 32.1518 7.1197 32.0167 7.07552C31.9714 7.06069 31.9467 7.01193 31.9615 6.9666ZM19.9271 6.9666C19.9419 7.01193 19.9172 7.0607 19.8719 7.07553C19.7369 7.1197 19.6025 7.16531 19.4688 7.21233C19.4238 7.22815 19.3745 7.20451 19.3587 7.15952C19.3428 7.11452 19.3665 7.06522 19.4115 7.0494C19.5464 7.00196 19.6819 6.95594 19.8182 6.91138C19.8635 6.89655 19.9123 6.92127 19.9271 6.9666ZM33.1687 7.40006C33.1865 7.35581 33.2368 7.33435 33.2811 7.35214C33.4139 7.40554 33.5461 7.46034 33.6775 7.51654C33.7214 7.53529 33.7417 7.58604 33.723 7.62989C33.7042 7.67374 33.6535 7.69409 33.6096 7.67534C33.4793 7.61964 33.3484 7.56532 33.2167 7.51239C33.1724 7.49461 33.151 7.44432 33.1687 7.40006ZM18.7199 7.40007C18.7377 7.44432 18.7162 7.49461 18.672 7.5124C18.5403 7.56532 18.4093 7.61964 18.279 7.67534C18.2352 7.69409 18.1844 7.67374 18.1657 7.62989C18.1469 7.58604 18.1673 7.53529 18.2111 7.51654C18.3425 7.46034 18.4747 7.40554 18.6076 7.35214C18.6518 7.33436 18.7021 7.35581 18.7199 7.40007ZM34.3444 7.91191C34.3651 7.86892 34.4167 7.85082 34.4597 7.87147C34.5889 7.93358 34.7174 7.99706 34.845 8.06189C34.8876 8.08348 34.9045 8.13546 34.8829 8.17798C34.8613 8.22051 34.8094 8.23747 34.7668 8.21588C34.6403 8.15162 34.513 8.08871 34.3848 8.02715C34.3419 8.00649 34.3238 7.9549 34.3444 7.91191ZM17.5442 7.91191C17.5649 7.9549 17.5468 8.00649 17.5038 8.02715C17.3757 8.08871 17.2483 8.15163 17.1218 8.21588C17.0793 8.23748 17.0273 8.22051 17.0057 8.17798C16.9841 8.13546 17.0011 8.08348 17.0436 8.06189C17.1712 7.99706 17.2997 7.93358 17.429 7.87148C17.472 7.85082 17.5236 7.86892 17.5442 7.91191ZM35.4845 8.50021C35.508 8.45867 35.5606 8.44399 35.6022 8.46743C35.7269 8.5378 35.8508 8.6095 35.9739 8.6825C36.0149 8.70683 36.0284 8.75981 36.0041 8.80083C35.9798 8.84184 35.9268 8.85537 35.8858 8.83104C35.7638 8.75868 35.641 8.68761 35.5173 8.61785C35.4758 8.59442 35.4611 8.54175 35.4845 8.50021ZM16.4041 8.50021C16.4275 8.54175 16.4128 8.59442 16.3713 8.61786C16.2476 8.68761 16.1248 8.75868 16.0028 8.83104C15.9618 8.85537 15.9089 8.84185 15.8845 8.80083C15.8602 8.75981 15.8737 8.70683 15.9147 8.6825C16.0378 8.6095 16.1617 8.5378 16.2864 8.46743C16.328 8.444 16.3807 8.45867 16.4041 8.50021ZM36.5834 9.1618C36.6095 9.12189 36.663 9.11068 36.7029 9.13678C36.8228 9.21515 36.9417 9.29478 37.0597 9.37567C37.0991 9.40263 37.1091 9.45638 37.0822 9.49572C37.0552 9.53506 37.0014 9.5451 36.9621 9.51813C36.8451 9.43795 36.7272 9.35902 36.6084 9.28134C36.5685 9.25524 36.5573 9.20172 36.5834 9.1618ZM15.3052 9.16181C15.3313 9.20173 15.3201 9.25524 15.2802 9.28134C15.1614 9.35902 15.0435 9.43796 14.9265 9.51814C14.8872 9.5451 14.8334 9.53507 14.8065 9.49573C14.7795 9.45639 14.7895 9.40264 14.8289 9.37567C14.9469 9.29479 15.0658 9.21515 15.1857 9.13679C15.2256 9.11069 15.2791 9.12189 15.3052 9.16181ZM37.6366 9.89371C37.6652 9.85558 37.7194 9.84789 37.7575 9.87654C37.872 9.96258 37.9856 10.0498 38.0981 10.1383C38.1356 10.1678 38.1422 10.2221 38.1127 10.2596C38.0832 10.2971 38.0289 10.3036 37.9914 10.2741C37.8798 10.1864 37.7673 10.0999 37.6538 10.0146C37.6156 9.98597 37.6079 9.93184 37.6366 9.89371ZM14.252 9.89371C14.2807 9.93184 14.273 9.98598 14.2349 10.0146C14.1213 10.0999 14.0088 10.1864 13.8972 10.2741C13.8597 10.3036 13.8054 10.2971 13.7759 10.2596C13.7465 10.2221 13.753 10.1678 13.7905 10.1383C13.903 10.0499 14.0166 9.96259 14.1311 9.87654C14.1693 9.8479 14.2234 9.85558 14.252 9.89371ZM38.64 10.6928C38.6711 10.6567 38.7256 10.6525 38.7618 10.6836C38.8704 10.7769 38.978 10.8713 39.0846 10.9669C39.1201 10.9987 39.123 11.0533 39.0912 11.0888C39.0593 11.1243 39.0047 11.1273 38.9692 11.0954C38.8636 11.0007 38.757 10.9071 38.6493 10.8146C38.6131 10.7835 38.609 10.729 38.64 10.6928ZM13.2486 10.6928C13.2797 10.729 13.2755 10.7836 13.2393 10.8146C13.1317 10.9071 13.025 11.0007 12.9194 11.0954C12.8839 11.1273 12.8293 11.1243 12.7974 11.0888C12.7656 11.0533 12.7686 10.9987 12.8041 10.9669C12.9106 10.8713 13.0182 10.7769 13.1268 10.6836C13.163 10.6525 13.2175 10.6567 13.2486 10.6928ZM39.5893 11.5555C39.6226 11.5214 39.6773 11.5208 39.7114 11.5542C39.8137 11.6543 39.9149 11.7555 40.0151 11.8579C40.0484 11.8919 40.0478 11.9466 40.0137 11.98C39.9796 12.0133 39.925 12.0127 39.8916 11.9787C39.7924 11.8772 39.692 11.7769 39.5906 11.6776C39.5565 11.6443 39.5559 11.5896 39.5893 11.5555ZM12.2994 11.5555C12.3327 11.5896 12.3321 11.6443 12.298 11.6776C12.1966 11.7769 12.0963 11.8772 11.997 11.9787C11.9637 12.0127 11.909 12.0133 11.8749 11.98C11.8408 11.9466 11.8402 11.8919 11.8736 11.8579C11.9737 11.7555 12.0749 11.6543 12.1773 11.5542C12.2113 11.5208 12.266 11.5214 12.2994 11.5555ZM40.4804 12.478C40.5159 12.4462 40.5705 12.4492 40.6024 12.4847C40.6979 12.5912 40.7924 12.6988 40.8857 12.8074C40.9167 12.8436 40.9126 12.8981 40.8764 12.9292C40.8402 12.9603 40.7857 12.9561 40.7546 12.9199C40.6622 12.8123 40.5685 12.7056 40.4738 12.6C40.4419 12.5645 40.4449 12.5099 40.4804 12.478ZM11.4082 12.478C11.4437 12.5099 11.4467 12.5645 11.4148 12.6C11.3201 12.7056 11.2265 12.8123 11.134 12.92C11.1029 12.9561 11.0484 12.9603 11.0122 12.9292C10.9761 12.8981 10.9719 12.8436 11.003 12.8074C11.0963 12.6988 11.1907 12.5912 11.2863 12.4847C11.3181 12.4492 11.3727 12.4462 11.4082 12.478ZM41.3097 13.4565C41.3472 13.4271 41.4014 13.4336 41.4309 13.4711C41.5194 13.5836 41.6066 13.6972 41.6927 13.8117C41.7213 13.8499 41.7136 13.904 41.6755 13.9326C41.6374 13.9613 41.5833 13.9536 41.5546 13.9155C41.4693 13.8019 41.3828 13.6894 41.2951 13.5778C41.2657 13.5403 41.2722 13.486 41.3097 13.4565ZM10.579 13.4565C10.6165 13.486 10.623 13.5403 10.5935 13.5778C10.5058 13.6894 10.4193 13.802 10.334 13.9155C10.3054 13.9536 10.2512 13.9613 10.2131 13.9327C10.175 13.904 10.1673 13.8499 10.1959 13.8117C10.282 13.6972 10.3692 13.5837 10.4577 13.4711C10.4872 13.4336 10.5415 13.4271 10.579 13.4565ZM42.0735 14.4871C42.1129 14.4601 42.1666 14.4701 42.1936 14.5095C42.2744 14.6275 42.3541 14.7464 42.4324 14.8663C42.4585 14.9062 42.4473 14.9597 42.4074 14.9858C42.3675 15.0119 42.314 15.0007 42.2879 14.9608C42.2102 14.842 42.1313 14.7241 42.0511 14.6071C42.0241 14.5678 42.0342 14.514 42.0735 14.4871ZM9.81512 14.4871C9.85446 14.514 9.86449 14.5678 9.83753 14.6071C9.75735 14.7241 9.67841 14.842 9.60074 14.9608C9.57464 15.0007 9.52112 15.0119 9.4812 14.9858C9.44128 14.9597 9.43008 14.9062 9.45618 14.8663C9.53454 14.7465 9.61418 14.6275 9.69507 14.5095C9.72203 14.4701 9.77578 14.4601 9.81512 14.4871ZM42.7684 15.5651C42.8094 15.5408 42.8624 15.5543 42.8867 15.5953C42.9597 15.7184 43.0314 15.8423 43.1018 15.9671C43.1252 16.0086 43.1106 16.0613 43.069 16.0847C43.0275 16.1081 42.9748 16.0934 42.9514 16.0519C42.8816 15.9282 42.8106 15.8054 42.7382 15.6835C42.7139 15.6424 42.7274 15.5895 42.7684 15.5651ZM9.12022 15.5651C9.16124 15.5895 9.17477 15.6424 9.15043 15.6835C9.07807 15.8054 9.00701 15.9283 8.93725 16.0519C8.91382 16.0935 8.86115 16.1081 8.81961 16.0847C8.77807 16.0613 8.76339 16.0086 8.78682 15.9671C8.8572 15.8423 8.92889 15.7184 9.00189 15.5953C9.02623 15.5543 9.07921 15.5408 9.12022 15.5651ZM43.3912 16.6863C43.4338 16.6647 43.4857 16.6817 43.5073 16.7242C43.5722 16.8519 43.6357 16.9803 43.6978 17.1096C43.7184 17.1526 43.7003 17.2042 43.6573 17.2248C43.6143 17.2455 43.5627 17.2274 43.5421 17.1844C43.4805 17.0563 43.4176 16.9289 43.3534 16.8024C43.3318 16.7599 43.3487 16.7079 43.3912 16.6863ZM8.49738 16.6863C8.5399 16.7079 8.55687 16.7599 8.53528 16.8024C8.47102 16.9289 8.4081 17.0563 8.34654 17.1844C8.32589 17.2274 8.27429 17.2455 8.23131 17.2248C8.18832 17.2042 8.17021 17.1526 8.19087 17.1096C8.25298 16.9803 8.31645 16.8519 8.38128 16.7242C8.40288 16.6817 8.45485 16.6647 8.49738 16.6863ZM43.9393 17.8463C43.9832 17.8275 44.0339 17.8479 44.0527 17.8917C44.1089 18.0231 44.1637 18.1553 44.2171 18.2882C44.2349 18.3324 44.2134 18.3827 44.1692 18.4005C44.1249 18.4183 44.0746 18.3968 44.0568 18.3526C44.0039 18.2209 43.9496 18.0899 43.8939 17.9596C43.8751 17.9158 43.8955 17.865 43.9393 17.8463ZM7.94929 17.8463C7.99314 17.865 8.01349 17.9158 7.99474 17.9596C7.93904 18.0899 7.88472 18.2209 7.83179 18.3526C7.814 18.3968 7.76371 18.4183 7.71946 18.4005C7.67521 18.3827 7.65375 18.3324 7.67153 18.2882C7.72493 18.1553 7.77974 18.0231 7.83593 17.8917C7.85468 17.8479 7.90543 17.8275 7.94929 17.8463ZM44.4097 19.0393C44.4547 19.0234 44.504 19.0471 44.5198 19.0921C44.5673 19.227 44.6133 19.3626 44.6579 19.4988C44.6727 19.5441 44.648 19.5929 44.6026 19.6077C44.5573 19.6225 44.5085 19.5978 44.4937 19.5525C44.4495 19.4175 44.4039 19.2831 44.3569 19.1494C44.3411 19.1044 44.3647 19.0551 44.4097 19.0393ZM7.47891 19.0393C7.5239 19.0551 7.54755 19.1044 7.53172 19.1494C7.4847 19.2831 7.43909 19.4175 7.39492 19.5525C7.38009 19.5978 7.33132 19.6225 7.28599 19.6077C7.24066 19.5929 7.21594 19.5441 7.23077 19.4988C7.27534 19.3626 7.32135 19.227 7.36879 19.0921C7.38462 19.0471 7.43392 19.0235 7.47891 19.0393ZM44.8005 20.2608C44.8464 20.2479 44.8941 20.2748 44.9069 20.3207C44.9454 20.4586 44.9824 20.5972 45.018 20.7363C45.0298 20.7825 45.0019 20.8295 44.9557 20.8413C44.9095 20.8531 44.8624 20.8252 44.8506 20.779C44.8154 20.6412 44.7787 20.5039 44.7405 20.3672C44.7277 20.3212 44.7546 20.2736 44.8005 20.2608ZM7.08813 20.2608C7.13406 20.2736 7.16091 20.3212 7.14809 20.3672C7.10993 20.5039 7.07322 20.6412 7.03799 20.779C7.02618 20.8253 6.97915 20.8531 6.93294 20.8413C6.88673 20.8295 6.85885 20.7825 6.87065 20.7363C6.9062 20.5972 6.94324 20.4586 6.98173 20.3207C6.99456 20.2748 7.04219 20.248 7.08813 20.2608ZM45.1101 21.506C45.1568 21.4963 45.2025 21.5262 45.2123 21.5729C45.2415 21.7126 45.2693 21.8528 45.2955 21.9936C45.3043 22.0405 45.2734 22.0856 45.2265 22.0944C45.1796 22.1031 45.1345 22.0722 45.1257 22.0253C45.0997 21.8857 45.0722 21.7467 45.0432 21.6082C45.0335 21.5615 45.0634 21.5158 45.1101 21.506ZM6.77856 21.506C6.82524 21.5158 6.85516 21.5616 6.84539 21.6082C6.81642 21.7467 6.78891 21.8858 6.76288 22.0253C6.75414 22.0722 6.70904 22.1031 6.66216 22.0944C6.61527 22.0856 6.58435 22.0405 6.5931 21.9936C6.61935 21.8528 6.64711 21.7126 6.67634 21.5729C6.68611 21.5262 6.73187 21.4963 6.77856 21.506ZM45.3369 22.7681C45.3841 22.7614 45.4278 22.7942 45.4345 22.8415C45.4545 22.9829 45.473 23.1248 45.49 23.2671C45.4957 23.3145 45.4619 23.3574 45.4145 23.3631C45.3672 23.3687 45.3242 23.3349 45.3185 23.2876C45.3017 23.1465 45.2833 23.0058 45.2635 22.8657C45.2568 22.8184 45.2897 22.7747 45.3369 22.7681ZM6.55173 22.7681C6.59895 22.7747 6.63182 22.8184 6.62513 22.8657C6.60529 23.0058 6.58694 23.1465 6.5701 23.2876C6.56445 23.3349 6.52147 23.3688 6.47412 23.3631C6.42676 23.3574 6.39295 23.3145 6.39861 23.2671C6.4156 23.1248 6.43411 22.9829 6.45412 22.8415C6.46081 22.7942 6.50451 22.7614 6.55173 22.7681ZM45.4806 24.0422C45.5282 24.0386 45.5697 24.0742 45.5732 24.1218C45.584 24.2646 45.5933 24.4078 45.601 24.5514C45.6036 24.599 45.567 24.6397 45.5194 24.6423C45.4718 24.6448 45.4311 24.6083 45.4285 24.5607C45.4209 24.4183 45.4117 24.2763 45.401 24.1348C45.3974 24.0872 45.4331 24.0458 45.4806 24.0422ZM6.408 24.0422C6.45555 24.0458 6.4912 24.0873 6.4876 24.1348C6.47692 24.2764 6.46774 24.4183 6.46009 24.5607C6.45753 24.6083 6.41685 24.6448 6.36922 24.6423C6.3216 24.6397 6.28507 24.599 6.28763 24.5514C6.29534 24.4078 6.3046 24.2646 6.31538 24.1218C6.31897 24.0743 6.36044 24.0386 6.408 24.0422ZM45.5413 25.3238C45.589 25.3233 45.6281 25.3615 45.6286 25.4092C45.6294 25.481 45.6298 25.5529 45.6298 25.6249C45.6298 25.6969 45.6294 25.7688 45.6286 25.8406C45.6281 25.8883 45.589 25.9265 45.5413 25.926C45.4937 25.9255 45.4554 25.8864 45.4559 25.8388C45.4567 25.7676 45.4571 25.6963 45.4571 25.6249C45.4571 25.5535 45.4567 25.4823 45.4559 25.4111C45.4554 25.3634 45.4937 25.3243 45.5413 25.3238ZM6.34729 25.3238C6.39498 25.3243 6.43322 25.3634 6.43271 25.4111C6.43194 25.4823 6.43156 25.5535 6.43156 25.6249C6.43156 25.6963 6.43194 25.7676 6.43271 25.8388C6.43322 25.8865 6.39498 25.9255 6.34729 25.926C6.2996 25.9266 6.26052 25.8883 6.26001 25.8406C6.25924 25.7688 6.25885 25.6969 6.25885 25.6249C6.25885 25.5529 6.25924 25.481 6.26001 25.4092C6.26052 25.3615 6.2996 25.3233 6.34729 25.3238ZM45.5194 26.6076C45.567 26.6101 45.6036 26.6508 45.601 26.6984C45.5933 26.8421 45.584 26.9853 45.5732 27.128C45.5697 27.1756 45.5282 27.2112 45.4806 27.2076C45.4331 27.204 45.3974 27.1626 45.401 27.115C45.4117 26.9735 45.4209 26.8315 45.4285 26.6892C45.4311 26.6415 45.4718 26.605 45.5194 26.6076ZM6.36922 26.6076C6.41685 26.605 6.45753 26.6416 6.46009 26.6892C6.46774 26.8315 6.47692 26.9735 6.48761 27.115C6.4912 27.1626 6.45555 27.2041 6.408 27.2076C6.36044 27.2112 6.31898 27.1756 6.31538 27.128C6.3046 26.9853 6.29535 26.8421 6.28763 26.6985C6.28507 26.6508 6.3216 26.6101 6.36922 26.6076ZM45.4145 27.8867C45.4619 27.8924 45.4957 27.9354 45.49 27.9827C45.473 28.1251 45.4545 28.267 45.4345 28.4084C45.4278 28.4556 45.3841 28.4885 45.3369 28.4818C45.2897 28.4751 45.2568 28.4314 45.2635 28.3842C45.2833 28.244 45.3017 28.1034 45.3185 27.9623C45.3242 27.9149 45.3672 27.8811 45.4145 27.8867ZM6.47412 27.8868C6.52147 27.8811 6.56445 27.9149 6.5701 27.9623C6.58694 28.1034 6.60529 28.244 6.62513 28.3842C6.63182 28.4314 6.59895 28.4751 6.55173 28.4818C6.50451 28.4885 6.46081 28.4556 6.45413 28.4084C6.43411 28.267 6.4156 28.1251 6.39861 27.9827C6.39295 27.9354 6.42676 27.8924 6.47412 27.8868ZM45.2265 29.1555C45.2734 29.1642 45.3043 29.2093 45.2955 29.2562C45.2693 29.397 45.2415 29.5373 45.2123 29.677C45.2025 29.7237 45.1568 29.7536 45.1101 29.7438C45.0634 29.734 45.0335 29.6883 45.0432 29.6416C45.0722 29.5031 45.0997 29.3641 45.1257 29.2245C45.1345 29.1777 45.1796 29.1467 45.2265 29.1555ZM6.66216 29.1555C6.70904 29.1467 6.75414 29.1777 6.76288 29.2245C6.78891 29.3641 6.81642 29.5031 6.8454 29.6416C6.85516 29.6883 6.82524 29.7341 6.77856 29.7438C6.73187 29.7536 6.68611 29.7237 6.67635 29.677C6.64711 29.5373 6.61936 29.397 6.5931 29.2562C6.58436 29.2093 6.61528 29.1642 6.66216 29.1555ZM44.9557 30.4085C45.0019 30.4203 45.0298 30.4673 45.018 30.5136C44.9824 30.6527 44.9454 30.7912 44.9069 30.9291C44.8941 30.975 44.8464 31.0019 44.8005 30.9891C44.7546 30.9762 44.7277 30.9286 44.7405 30.8827C44.7787 30.746 44.8154 30.6087 44.8506 30.4708C44.8624 30.4246 44.9095 30.3967 44.9557 30.4085ZM6.93294 30.4085C6.97915 30.3967 7.02618 30.4246 7.03799 30.4708C7.07323 30.6087 7.10993 30.746 7.14809 30.8827C7.16091 30.9286 7.13407 30.9763 7.08813 30.9891C7.04219 31.0019 6.99456 30.9751 6.98174 30.9291C6.94324 30.7912 6.90621 30.6527 6.87066 30.5136C6.85885 30.4674 6.88674 30.4203 6.93294 30.4085ZM44.6026 31.6421C44.648 31.657 44.6727 31.7057 44.6579 31.751C44.6133 31.8873 44.5673 32.0229 44.5198 32.1578C44.504 32.2027 44.4547 32.2264 44.4097 32.2106C44.3647 32.1947 44.3411 32.1454 44.3569 32.1005C44.4039 31.9667 44.4495 31.8324 44.4937 31.6973C44.5085 31.652 44.5573 31.6273 44.6026 31.6421ZM7.286 31.6421C7.33133 31.6273 7.38009 31.652 7.39492 31.6974C7.4391 31.8324 7.4847 31.9668 7.53173 32.1005C7.54755 32.1455 7.5239 32.1948 7.47891 32.2106C7.43392 32.2264 7.38462 32.2028 7.3688 32.1578C7.32136 32.0229 7.27534 31.8873 7.23077 31.7511C7.21594 31.7057 7.24067 31.657 7.286 31.6421ZM44.1692 32.8493C44.2134 32.8671 44.2349 32.9174 44.2171 32.9617C44.1637 33.0945 44.1089 33.2267 44.0527 33.3581C44.0339 33.402 43.9832 33.4223 43.9393 33.4036C43.8955 33.3848 43.8751 33.3341 43.8939 33.2902C43.9496 33.16 44.0039 33.029 44.0568 32.8973C44.0746 32.853 44.1249 32.8316 44.1692 32.8493ZM7.71946 32.8494C7.76372 32.8316 7.81401 32.853 7.83179 32.8973C7.88472 33.029 7.93904 33.16 7.99474 33.2902C8.01349 33.3341 7.99314 33.3848 7.94929 33.4036C7.90544 33.4223 7.85469 33.402 7.83594 33.3581C7.77974 33.2267 7.72494 33.0946 7.67154 32.9617C7.65375 32.9174 7.67521 32.8671 7.71946 32.8494ZM43.6573 34.025C43.7003 34.0457 43.7184 34.0973 43.6978 34.1403C43.6357 34.2695 43.5722 34.398 43.5074 34.5256C43.4858 34.5682 43.4338 34.5851 43.3913 34.5635C43.3487 34.542 43.3318 34.49 43.3534 34.4475C43.4176 34.3209 43.4805 34.1936 43.5421 34.0655C43.5627 34.0225 43.6143 34.0044 43.6573 34.025ZM8.23131 34.025C8.2743 34.0044 8.32589 34.0225 8.34655 34.0655C8.40811 34.1936 8.47102 34.3209 8.53528 34.4475C8.55687 34.49 8.53991 34.542 8.49738 34.5636C8.45486 34.5851 8.40288 34.5682 8.38129 34.5257C8.31646 34.398 8.25298 34.2695 8.19087 34.1403C8.17022 34.0973 8.18832 34.0457 8.23131 34.025ZM43.069 35.1651C43.1106 35.1886 43.1252 35.2412 43.1018 35.2828C43.0314 35.4075 42.9597 35.5315 42.8867 35.6545C42.8624 35.6955 42.8094 35.709 42.7684 35.6847C42.7274 35.6604 42.7139 35.6074 42.7382 35.5664C42.8106 35.4444 42.8816 35.3216 42.9514 35.1979C42.9748 35.1564 43.0275 35.1417 43.069 35.1651ZM8.81961 35.1651C8.86115 35.1417 8.91382 35.1564 8.93725 35.1979C9.00701 35.3216 9.07808 35.4444 9.15044 35.5664C9.17477 35.6074 9.16125 35.6604 9.12023 35.6847C9.07921 35.7091 9.02623 35.6955 9.0019 35.6545C8.9289 35.5315 8.8572 35.4075 8.78683 35.2828C8.76339 35.2412 8.77807 35.1886 8.81961 35.1651ZM42.4074 36.264C42.4473 36.2901 42.4585 36.3436 42.4324 36.3835C42.3541 36.5034 42.2745 36.6223 42.1936 36.7404C42.1666 36.7797 42.1129 36.7897 42.0735 36.7628C42.0342 36.7358 42.0241 36.6821 42.0511 36.6427C42.1313 36.5257 42.2102 36.4078 42.2879 36.289C42.314 36.2491 42.3675 36.2379 42.4074 36.264ZM9.4812 36.264C9.52112 36.2379 9.57464 36.2491 9.60074 36.289C9.67842 36.4078 9.75735 36.5257 9.83753 36.6427C9.8645 36.6821 9.85446 36.7358 9.81512 36.7628C9.77578 36.7897 9.72203 36.7797 9.69507 36.7404C9.61418 36.6223 9.53455 36.5034 9.45618 36.3835C9.43009 36.3436 9.44129 36.2901 9.4812 36.264ZM41.6755 37.3172C41.7137 37.3458 41.7213 37.4 41.6927 37.4381C41.6066 37.5526 41.5194 37.6662 41.4309 37.7788C41.4014 37.8163 41.3472 37.8228 41.3097 37.7933C41.2722 37.7638 41.2657 37.7095 41.2951 37.672C41.3828 37.5604 41.4693 37.4479 41.5546 37.3344C41.5833 37.2962 41.6374 37.2885 41.6755 37.3172ZM10.2131 37.3172C10.2512 37.2885 10.3054 37.2962 10.334 37.3344C10.4193 37.4479 10.5058 37.5605 10.5935 37.672C10.623 37.7095 10.6165 37.7638 10.579 37.7933C10.5415 37.8228 10.4872 37.8163 10.4577 37.7788C10.3693 37.6662 10.282 37.5526 10.1959 37.4381C10.1673 37.4 10.175 37.3458 10.2131 37.3172ZM40.8764 38.3206C40.9126 38.3517 40.9167 38.4062 40.8857 38.4424C40.7924 38.551 40.6979 38.6586 40.6024 38.7652C40.5705 38.8007 40.5159 38.8036 40.4804 38.7718C40.4449 38.7399 40.4419 38.6854 40.4738 38.6498C40.5685 38.5442 40.6622 38.4376 40.7546 38.3299C40.7857 38.2937 40.8402 38.2896 40.8764 38.3206ZM11.0122 38.3206C11.0484 38.2896 11.1029 38.2937 11.134 38.3299C11.2265 38.4376 11.3201 38.5442 11.4148 38.6499C11.4467 38.6854 11.4437 38.74 11.4082 38.7718C11.3727 38.8036 11.3181 38.8007 11.2863 38.7652C11.1907 38.6586 11.0963 38.551 11.003 38.4424C10.9719 38.4062 10.9761 38.3517 11.0122 38.3206ZM40.0137 39.2699C40.0478 39.3032 40.0484 39.3579 40.0151 39.392C39.9149 39.4943 39.8137 39.5955 39.7114 39.6957C39.6773 39.729 39.6226 39.7284 39.5893 39.6943C39.5559 39.6603 39.5565 39.6056 39.5906 39.5722C39.692 39.473 39.7924 39.3726 39.8916 39.2712C39.925 39.2371 39.9797 39.2365 40.0137 39.2699ZM11.8749 39.2699C11.909 39.2365 11.9637 39.2371 11.997 39.2712C12.0963 39.3726 12.1966 39.473 12.2981 39.5722C12.3321 39.6056 12.3327 39.6603 12.2994 39.6943C12.266 39.7284 12.2113 39.729 12.1773 39.6957C12.0749 39.5955 11.9737 39.4943 11.8736 39.392C11.8402 39.3579 11.8408 39.3032 11.8749 39.2699ZM39.0912 40.161C39.123 40.1965 39.1201 40.2511 39.0846 40.283C38.978 40.3785 38.8704 40.473 38.7618 40.5663C38.7256 40.5973 38.6711 40.5932 38.64 40.557C38.609 40.5208 38.6131 40.4663 38.6493 40.4352C38.757 40.3428 38.8636 40.2491 38.9692 40.1544C39.0048 40.1225 39.0593 40.1255 39.0912 40.161ZM12.7974 40.161C12.8293 40.1255 12.8839 40.1226 12.9194 40.1544C13.025 40.2491 13.1317 40.3428 13.2393 40.4352C13.2755 40.4663 13.2797 40.5208 13.2486 40.557C13.2175 40.5932 13.163 40.5973 13.1268 40.5663C13.0182 40.473 12.9106 40.3785 12.8041 40.283C12.7686 40.2511 12.7656 40.1965 12.7974 40.161ZM38.1127 40.9903C38.1422 41.0278 38.1357 41.0821 38.0982 41.1115C37.9856 41.2 37.872 41.2873 37.7575 41.3733C37.7194 41.4019 37.6652 41.3943 37.6366 41.3561C37.6079 41.318 37.6156 41.2639 37.6538 41.2352C37.7673 41.1499 37.8798 41.0634 37.9914 40.9757C38.0289 40.9463 38.0832 40.9528 38.1127 40.9903ZM13.7759 40.9903C13.8054 40.9528 13.8597 40.9463 13.8972 40.9757C14.0088 41.0634 14.1214 41.1499 14.2349 41.2352C14.273 41.2639 14.2807 41.318 14.252 41.3561C14.2234 41.3943 14.1693 41.4019 14.1311 41.3733C14.0166 41.2873 13.9031 41.2 13.7905 41.1115C13.753 41.0821 13.7465 41.0278 13.7759 40.9903ZM37.0822 41.7541C37.1091 41.7935 37.0991 41.8472 37.0598 41.8742C36.9417 41.9551 36.8228 42.0347 36.7029 42.1131C36.663 42.1392 36.6095 42.1279 36.5834 42.088C36.5573 42.0481 36.5685 41.9946 36.6084 41.9685C36.7272 41.8908 36.8451 41.8119 36.9621 41.7317C37.0015 41.7047 37.0552 41.7148 37.0822 41.7541ZM14.8065 41.7541C14.8334 41.7148 14.8872 41.7047 14.9265 41.7317C15.0435 41.8119 15.1614 41.8908 15.2802 41.9685C15.3201 41.9946 15.3313 42.0481 15.3052 42.088C15.2791 42.128 15.2256 42.1392 15.1857 42.1131C15.0659 42.0347 14.9469 41.9551 14.8289 41.8742C14.7895 41.8472 14.7795 41.7935 14.8065 41.7541ZM36.0041 42.449C36.0284 42.49 36.0149 42.543 35.9739 42.5673C35.8509 42.6403 35.7269 42.712 35.6022 42.7824C35.5606 42.8058 35.508 42.7912 35.4845 42.7496C35.4611 42.7081 35.4758 42.6554 35.5173 42.632C35.641 42.5622 35.7638 42.4912 35.8858 42.4188C35.9268 42.3945 35.9798 42.408 36.0041 42.449ZM15.8845 42.449C15.9089 42.408 15.9618 42.3945 16.0029 42.4188C16.1248 42.4912 16.2476 42.5622 16.3713 42.632C16.4128 42.6554 16.4275 42.7081 16.4041 42.7496C16.3807 42.7912 16.328 42.8058 16.2865 42.7824C16.1617 42.712 16.0378 42.6403 15.9147 42.5673C15.8737 42.543 15.8602 42.49 15.8845 42.449ZM34.8829 43.0719C34.9045 43.1144 34.8876 43.1664 34.845 43.188C34.7174 43.2528 34.5889 43.3163 34.4597 43.3784C34.4167 43.399 34.3651 43.3809 34.3444 43.3379C34.3238 43.2949 34.3419 43.2433 34.3849 43.2227C34.513 43.1611 34.6403 43.0982 34.7669 43.034C34.8094 43.0124 34.8614 43.0293 34.8829 43.0719ZM17.0057 43.0719C17.0273 43.0293 17.0793 43.0124 17.1218 43.034C17.2483 43.0982 17.3757 43.1611 17.5038 43.2227C17.5468 43.2434 17.5649 43.2949 17.5442 43.3379C17.5236 43.3809 17.472 43.399 17.429 43.3784C17.2997 43.3163 17.1713 43.2528 17.0436 43.188C17.0011 43.1664 16.9841 43.1144 17.0057 43.0719ZM33.723 43.6199C33.7417 43.6638 33.7214 43.7146 33.6775 43.7333C33.5461 43.7895 33.4139 43.8443 33.2811 43.8977C33.2368 43.9155 33.1865 43.894 33.1687 43.8498C33.151 43.8055 33.1724 43.7552 33.2167 43.7374C33.3484 43.6845 33.4794 43.6302 33.6096 43.5745C33.6535 43.5557 33.7042 43.5761 33.723 43.6199ZM18.1657 43.6199C18.1844 43.5761 18.2352 43.5557 18.279 43.5745C18.4093 43.6302 18.5403 43.6845 18.672 43.7374C18.7162 43.7552 18.7377 43.8055 18.7199 43.8498C18.7021 43.894 18.6518 43.9155 18.6076 43.8977C18.4747 43.8443 18.3425 43.7895 18.2111 43.7333C18.1673 43.7146 18.1469 43.6638 18.1657 43.6199ZM32.53 44.0903C32.5458 44.1353 32.5221 44.1846 32.4772 44.2004C32.3423 44.2479 32.2067 44.2939 32.0705 44.3385C32.0251 44.3533 31.9764 44.3286 31.9615 44.2832C31.9467 44.2379 31.9714 44.1891 32.0168 44.1743C32.1518 44.1301 32.2861 44.0845 32.4199 44.0375C32.4648 44.0217 32.5141 44.0453 32.53 44.0903ZM19.3587 44.0903C19.3745 44.0453 19.4238 44.0217 19.4688 44.0375C19.6025 44.0845 19.7369 44.1301 19.8719 44.1743C19.9172 44.1891 19.9419 44.2379 19.9271 44.2832C19.9123 44.3286 19.8635 44.3533 19.8182 44.3385C19.682 44.2939 19.5464 44.2479 19.4115 44.2004C19.3665 44.1846 19.3428 44.1353 19.3587 44.0903ZM31.3085 44.4811C31.3213 44.527 31.2944 44.5747 31.2485 44.5875C31.1106 44.626 30.9721 44.663 30.833 44.6986C30.7867 44.7104 30.7397 44.6825 30.7279 44.6363C30.7161 44.5901 30.744 44.5431 30.7902 44.5312C30.9281 44.496 31.0654 44.4593 31.2021 44.4211C31.248 44.4083 31.2956 44.4352 31.3085 44.4811ZM20.5802 44.4811C20.593 44.4352 20.6406 44.4083 20.6866 44.4212C20.8233 44.4593 20.9606 44.496 21.0984 44.5312C21.1447 44.5431 21.1725 44.5901 21.1607 44.6363C21.1489 44.6825 21.1019 44.7104 21.0557 44.6986C20.9166 44.663 20.778 44.626 20.6401 44.5875C20.5942 44.5747 20.5673 44.527 20.5802 44.4811ZM30.0632 44.7907C30.073 44.8374 30.0431 44.8831 29.9964 44.8929C29.8567 44.9221 29.7164 44.9499 29.5756 44.9761C29.5287 44.9849 29.4836 44.954 29.4749 44.9071C29.4661 44.8602 29.4971 44.8151 29.5439 44.8064C29.6835 44.7803 29.8225 44.7528 29.961 44.7238C30.0077 44.7141 30.0534 44.744 30.0632 44.7907ZM21.8254 44.7907C21.8352 44.744 21.881 44.7141 21.9276 44.7238C22.0661 44.7528 22.2051 44.7803 22.3447 44.8064C22.3916 44.8151 22.4225 44.8602 22.4138 44.9071C22.405 44.954 22.3599 44.9849 22.313 44.9761C22.1722 44.9499 22.032 44.9221 21.8923 44.8929C21.8456 44.8831 21.8157 44.8374 21.8254 44.7907ZM23.0875 45.0175C23.0941 44.9703 23.1378 44.9374 23.1851 44.9441C23.3252 44.9639 23.4659 44.9823 23.607 44.9991C23.6543 45.0048 23.6881 45.0478 23.6825 45.0951C23.6768 45.1425 23.6339 45.1763 23.5865 45.1706C23.4442 45.1536 23.3023 45.1351 23.1609 45.1151C23.1136 45.1084 23.0808 45.0647 23.0875 45.0175ZM28.8012 45.0175C28.8079 45.0647 28.775 45.1084 28.7278 45.1151C28.5864 45.1351 28.4445 45.1536 28.3021 45.1706C28.2548 45.1763 28.2118 45.1425 28.2061 45.0951C28.2005 45.0478 28.2343 45.0048 28.2817 44.9991C28.4228 44.9823 28.5634 44.9639 28.7036 44.9441C28.7508 44.9374 28.7945 44.9703 28.8012 45.0175ZM24.3616 45.1612C24.3652 45.1137 24.4067 45.078 24.4542 45.0816C24.5957 45.0923 24.7377 45.1015 24.8801 45.1091C24.9277 45.1117 24.9642 45.1524 24.9617 45.2C24.9591 45.2476 24.9184 45.2842 24.8708 45.2816C24.7272 45.2739 24.584 45.2646 24.4412 45.2539C24.3937 45.2503 24.358 45.2088 24.3616 45.1612ZM27.527 45.1612C27.5306 45.2088 27.495 45.2503 27.4474 45.2539C27.3047 45.2646 27.1615 45.2739 27.0178 45.2816C26.9702 45.2842 26.9295 45.2476 26.927 45.2C26.9244 45.1524 26.961 45.1117 27.0086 45.1091C27.1509 45.1015 27.2929 45.0923 27.4344 45.0816C27.482 45.078 27.5235 45.1137 27.527 45.1612ZM25.6432 45.222C25.6437 45.1743 25.6828 45.136 25.7305 45.1365C25.8017 45.1373 25.8729 45.1377 25.9443 45.1377C26.0157 45.1377 26.087 45.1373 26.1582 45.1365C26.2059 45.136 26.2449 45.1743 26.2454 45.222C26.246 45.2696 26.2077 45.3087 26.16 45.3092C26.0882 45.31 26.0163 45.3104 25.9443 45.3104C25.8723 45.3104 25.8004 45.31 25.7286 45.3092C25.6809 45.3087 25.6427 45.2696 25.6432 45.222Z\"\n      fill=\"white\"\n    />\n    <path\n      opacity=\"0.05\"\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M25.78 0.483855C25.8533 0.483225 25.9266 0.48291 26 0.48291C26.0734 0.48291 26.1467 0.483225 26.2199 0.483854C26.2676 0.484264 26.306 0.523257 26.3055 0.570949C26.3051 0.61864 26.2661 0.656969 26.2185 0.65656C26.1457 0.655935 26.0729 0.655622 26 0.655622C25.9271 0.655622 25.8543 0.655935 25.7815 0.65656C25.7338 0.656969 25.6948 0.61864 25.6944 0.570949C25.694 0.523258 25.7323 0.484264 25.78 0.483855ZM27.0053 0.588961C27.0073 0.541312 27.0476 0.504345 27.0953 0.506392C27.2414 0.512669 27.3872 0.520196 27.5326 0.528963C27.5802 0.531833 27.6165 0.572751 27.6136 0.620358C27.6108 0.667965 27.5698 0.704231 27.5222 0.701362C27.3778 0.692655 27.233 0.685179 27.0878 0.678944C27.0402 0.676897 27.0032 0.63661 27.0053 0.588961ZM24.9947 0.588962C24.9967 0.636611 24.9598 0.676898 24.9121 0.678945C24.767 0.68518 24.6222 0.692656 24.4777 0.701363C24.4301 0.704233 24.3892 0.667966 24.3863 0.620359C24.3835 0.572753 24.4197 0.531834 24.4673 0.528965C24.6128 0.520198 24.7586 0.51267 24.9047 0.506393C24.9524 0.504345 24.9926 0.541313 24.9947 0.588962ZM28.3113 0.674539C28.3158 0.627061 28.358 0.592233 28.4054 0.59675C28.5511 0.610606 28.6964 0.625707 28.8413 0.642043C28.8887 0.647386 28.9228 0.690136 28.9174 0.737529C28.9121 0.784922 28.8693 0.81901 28.8219 0.813668C28.678 0.797444 28.5337 0.782446 28.3891 0.768685C28.3416 0.764169 28.3068 0.722018 28.3113 0.674539ZM23.6887 0.674541C23.6932 0.722019 23.6584 0.76417 23.6109 0.768687C23.4662 0.782448 23.322 0.797446 23.178 0.81367C23.1306 0.819012 23.0879 0.784924 23.0826 0.737531C23.0772 0.690139 23.1113 0.647388 23.1587 0.642045C23.3036 0.625709 23.4489 0.610608 23.5945 0.596752C23.642 0.592235 23.6842 0.627062 23.6887 0.674541ZM29.6111 0.827994C29.6181 0.780817 29.662 0.74824 29.7092 0.755232C29.8539 0.776688 29.9983 0.799381 30.1423 0.823301C30.1893 0.831118 30.2211 0.875595 30.2133 0.922643C30.2055 0.969691 30.161 1.00149 30.1139 0.993676C29.971 0.969922 29.8276 0.947386 29.6838 0.926077C29.6367 0.919085 29.6041 0.875172 29.6111 0.827994ZM22.3889 0.827996C22.3959 0.875174 22.3633 0.919087 22.3161 0.926079C22.1724 0.947388 22.029 0.969925 21.886 0.993679C21.839 1.0015 21.7945 0.969693 21.7867 0.922646C21.7789 0.875598 21.8107 0.83112 21.8577 0.823303C22.0017 0.799384 22.146 0.776691 22.2908 0.755234C22.338 0.748242 22.3819 0.780819 22.3889 0.827996ZM30.901 1.04932C30.9105 1.00258 30.956 0.972351 31.0028 0.981812C31.1463 1.01085 31.2893 1.04112 31.4319 1.07259C31.4785 1.08288 31.5079 1.12896 31.4976 1.17554C31.4874 1.22211 31.4413 1.25153 31.3947 1.24125C31.2531 1.20999 31.111 1.17993 30.9685 1.15109C30.9218 1.14163 30.8916 1.09607 30.901 1.04932ZM21.099 1.04932C21.1084 1.09607 21.0782 1.14163 21.0314 1.15109C20.8889 1.17993 20.7469 1.20999 20.6053 1.24125C20.5587 1.25153 20.5126 1.22211 20.5023 1.17554C20.492 1.12897 20.5215 1.08288 20.568 1.0726C20.7106 1.04112 20.8537 1.01085 20.9972 0.981814C21.0439 0.972354 21.0895 1.00258 21.099 1.04932ZM32.1776 1.33821C32.1895 1.29203 32.2366 1.26424 32.2828 1.27615C32.4246 1.31272 32.5659 1.35049 32.7067 1.38945C32.7526 1.40217 32.7796 1.44975 32.7669 1.49571C32.7541 1.54168 32.7066 1.56863 32.6606 1.55591C32.5208 1.51721 32.3805 1.4797 32.2397 1.44339C32.1935 1.43148 32.1657 1.38439 32.1776 1.33821ZM19.8223 1.33821C19.8343 1.3844 19.8065 1.43149 19.7603 1.4434C19.6195 1.47971 19.4792 1.51721 19.3394 1.55591C19.2934 1.56863 19.2458 1.54168 19.2331 1.49572C19.2204 1.44975 19.2473 1.40218 19.2933 1.38946C19.4341 1.35049 19.5754 1.31272 19.7172 1.27616C19.7633 1.26425 19.8104 1.29203 19.8223 1.33821ZM33.4375 1.69409C33.4519 1.6486 33.5004 1.62334 33.5459 1.63767C33.6854 1.68163 33.8244 1.72678 33.9629 1.77309C34.0081 1.78822 34.0325 1.83715 34.0174 1.88238C34.0023 1.92761 33.9534 1.95202 33.9081 1.93689C33.7706 1.89089 33.6325 1.84606 33.494 1.80241C33.4485 1.78808 33.4232 1.73958 33.4375 1.69409ZM18.5624 1.6941C18.5768 1.73959 18.5515 1.78808 18.506 1.80241C18.3674 1.84606 18.2294 1.89089 18.0919 1.93689C18.0466 1.95202 17.9977 1.92762 17.9826 1.88239C17.9674 1.83716 17.9918 1.78823 18.0371 1.7731C18.1755 1.72678 18.3146 1.68163 18.4541 1.63768C18.4996 1.62335 18.5481 1.64861 18.5624 1.6941ZM34.6769 2.11594C34.6936 2.07127 34.7433 2.0486 34.788 2.06531C34.925 2.11653 35.0613 2.16892 35.1971 2.22246C35.2415 2.23995 35.2633 2.2901 35.2458 2.33447C35.2283 2.37884 35.1782 2.40062 35.1338 2.38313C34.9989 2.32997 34.8635 2.27794 34.7275 2.22707C34.6828 2.21036 34.6602 2.16061 34.6769 2.11594ZM17.3231 2.11594C17.3398 2.16061 17.3171 2.21037 17.2725 2.22708C17.1365 2.27794 17.001 2.32997 16.8662 2.38313C16.8218 2.40063 16.7717 2.37884 16.7542 2.33447C16.7367 2.2901 16.7585 2.23995 16.8028 2.22246C16.9386 2.16892 17.075 2.11654 17.212 2.06531C17.2566 2.0486 17.3064 2.07127 17.3231 2.11594ZM35.8922 2.60252C35.9112 2.55879 35.9621 2.53878 36.0058 2.55782C36.1398 2.61616 36.2732 2.67563 36.4059 2.73623C36.4493 2.75603 36.4684 2.80726 36.4486 2.85064C36.4288 2.89403 36.3776 2.91315 36.3342 2.89334C36.2024 2.83317 36.0699 2.77411 35.9369 2.71617C35.8932 2.69713 35.8731 2.64625 35.8922 2.60252ZM16.1078 2.60252C16.1268 2.64625 16.1068 2.69713 16.0631 2.71617C15.93 2.77411 15.7976 2.83317 15.6658 2.89334C15.6224 2.91315 15.5712 2.89403 15.5513 2.85065C15.5315 2.80726 15.5507 2.75603 15.594 2.73623C15.7268 2.67563 15.8602 2.61616 15.9941 2.55782C16.0379 2.53878 16.0888 2.5588 16.1078 2.60252ZM37.0801 3.1524C37.1014 3.10974 37.1533 3.09243 37.196 3.11374C37.3266 3.17901 37.4567 3.2454 37.586 3.31287C37.6283 3.33493 37.6447 3.38709 37.6226 3.42937C37.6006 3.47166 37.5484 3.48806 37.5061 3.466C37.3777 3.39899 37.2486 3.33307 37.1188 3.26825C37.0761 3.24693 37.0588 3.19507 37.0801 3.1524ZM14.9198 3.1524C14.9412 3.19507 14.9238 3.24693 14.8812 3.26825C14.7514 3.33307 14.6223 3.39899 14.4938 3.466C14.4516 3.48806 14.3994 3.47166 14.3773 3.42938C14.3553 3.38709 14.3717 3.33493 14.414 3.31287C14.5433 3.2454 14.6733 3.17902 14.804 3.11374C14.8467 3.09243 14.8985 3.10974 14.9198 3.1524ZM38.2375 3.76393C38.261 3.72244 38.3137 3.70787 38.3552 3.7314C38.4822 3.80341 38.6086 3.87651 38.7342 3.95066C38.7753 3.97491 38.7889 4.02786 38.7647 4.06893C38.7404 4.11 38.6875 4.12364 38.6464 4.09939C38.5216 4.02575 38.3962 3.95316 38.27 3.88164C38.2286 3.85812 38.214 3.80541 38.2375 3.76393ZM13.7625 3.76393C13.786 3.80542 13.7714 3.85812 13.7299 3.88164C13.6038 3.95316 13.4783 4.02575 13.3536 4.09939C13.3125 4.12364 13.2596 4.11 13.2353 4.06893C13.2111 4.02786 13.2247 3.97491 13.2658 3.95066C13.3914 3.87651 13.5177 3.80342 13.6448 3.7314C13.6862 3.70788 13.7389 3.72244 13.7625 3.76393ZM12.6388 4.43527C12.6644 4.47547 12.6526 4.52886 12.6124 4.55453C12.4902 4.63253 12.3688 4.71158 12.248 4.79165C12.2083 4.81801 12.1547 4.80715 12.1284 4.76741C12.102 4.72766 12.1128 4.67407 12.1526 4.64771C12.2742 4.56709 12.3965 4.4875 12.5195 4.40895C12.5597 4.38329 12.6131 4.39507 12.6388 4.43527ZM39.3612 4.43527C39.3869 4.39507 39.4403 4.38329 39.4805 4.40895C39.6035 4.4875 39.7258 4.56709 39.8474 4.64771C39.8871 4.67407 39.898 4.72766 39.8716 4.76741C39.8453 4.80715 39.7917 4.81801 39.7519 4.79165C39.6312 4.71158 39.5097 4.63253 39.3875 4.55453C39.3473 4.52886 39.3356 4.47547 39.3612 4.43527ZM11.5517 5.16446C11.5795 5.20326 11.5705 5.2572 11.5317 5.28493C11.4137 5.3692 11.2966 5.45447 11.1802 5.54074C11.1419 5.56914 11.0878 5.5611 11.0594 5.52278C11.031 5.48446 11.039 5.43038 11.0773 5.40198C11.1945 5.31512 11.3125 5.22926 11.4313 5.1444C11.4701 5.11668 11.524 5.12566 11.5517 5.16446ZM40.4483 5.16446C40.476 5.12566 40.5299 5.11668 40.5687 5.1444C40.6875 5.22926 40.8055 5.31512 40.9226 5.40198C40.961 5.43038 40.969 5.48446 40.9406 5.52278C40.9122 5.5611 40.8581 5.56914 40.8198 5.54074C40.7034 5.45447 40.5862 5.3692 40.4683 5.28493C40.4295 5.2572 40.4205 5.20326 40.4483 5.16446ZM10.5042 5.94939C10.5339 5.98669 10.5278 6.04102 10.4905 6.07073C10.3771 6.16103 10.2645 6.2523 10.1528 6.34453C10.116 6.37488 10.0616 6.36967 10.0312 6.33289C10.0009 6.2961 10.0061 6.24167 10.0429 6.21132C10.1554 6.11846 10.2687 6.02656 10.3829 5.93564C10.4202 5.90592 10.4745 5.91208 10.5042 5.94939ZM41.4958 5.94939C41.5255 5.91208 41.5798 5.90592 41.6171 5.93564C41.7313 6.02656 41.8446 6.11846 41.9571 6.21132C41.9939 6.24167 41.9991 6.2961 41.9688 6.33289C41.9384 6.36967 41.884 6.37488 41.8472 6.34453C41.7354 6.2523 41.6229 6.16104 41.5095 6.07074C41.4722 6.04102 41.466 5.98669 41.4958 5.94939ZM42.5009 6.78783C42.5325 6.75212 42.5871 6.7488 42.6228 6.78042C42.7321 6.87717 42.8405 6.97486 42.9481 7.07348C42.9833 7.10571 42.9856 7.16034 42.9534 7.19549C42.9212 7.23065 42.8665 7.23302 42.8314 7.20079C42.7246 7.10284 42.6169 7.00582 42.5083 6.90973C42.4726 6.87811 42.4693 6.82354 42.5009 6.78783ZM9.49905 6.78783C9.53067 6.82354 9.52735 6.87811 9.49164 6.90973C9.38311 7.00582 9.27542 7.10284 9.16859 7.20079C9.13344 7.23302 9.07881 7.23065 9.04658 7.19549C9.01435 7.16034 9.01672 7.10571 9.05188 7.07348C9.15944 6.97486 9.26787 6.87717 9.37715 6.78042C9.41286 6.7488 9.46743 6.75212 9.49905 6.78783ZM8.53886 7.67746C8.57229 7.71147 8.57181 7.76615 8.5378 7.79958C8.43441 7.90119 8.33191 8.00369 8.23031 8.10707C8.19688 8.14109 8.1422 8.14156 8.10818 8.10813C8.07417 8.0747 8.0737 8.02002 8.10713 7.98601C8.20943 7.88191 8.31264 7.77871 8.41673 7.6764C8.45075 7.64297 8.50543 7.64344 8.53886 7.67746ZM43.4611 7.67746C43.4946 7.64344 43.5492 7.64297 43.5832 7.6764C43.6873 7.77871 43.7906 7.88191 43.8929 7.98601C43.9263 8.02002 43.9258 8.0747 43.8918 8.10813C43.8578 8.14156 43.8031 8.14109 43.7697 8.10707C43.6681 8.00369 43.5656 7.90119 43.4622 7.79958C43.4282 7.76615 43.4277 7.71147 43.4611 7.67746ZM44.3738 8.61585C44.4089 8.58362 44.4635 8.58599 44.4958 8.62115C44.5944 8.72871 44.6921 8.83714 44.7888 8.94642C44.8205 8.98213 44.8171 9.03671 44.7814 9.06833C44.7457 9.09994 44.6911 9.09662 44.6595 9.06091C44.5634 8.95238 44.4664 8.8447 44.3685 8.73786C44.3362 8.70271 44.3386 8.64808 44.3738 8.61585ZM7.62622 8.61586C7.66137 8.64808 7.66374 8.70271 7.63151 8.73787C7.53357 8.8447 7.43654 8.95238 7.34045 9.06091C7.30884 9.09662 7.25426 9.09994 7.21855 9.06833C7.18284 9.03671 7.17953 8.98213 7.21114 8.94642C7.3079 8.83714 7.40559 8.72872 7.50421 8.62115C7.53644 8.586 7.59106 8.58362 7.62622 8.61586ZM6.76361 9.60049C6.8004 9.63085 6.80561 9.68528 6.77525 9.72206C6.68303 9.83381 6.59176 9.94638 6.50146 10.0598C6.47175 10.0971 6.41742 10.1032 6.38011 10.0735C6.34281 10.0438 6.33665 9.98946 6.36636 9.95216C6.45729 9.838 6.54918 9.72465 6.64204 9.61213C6.6724 9.57535 6.72683 9.57014 6.76361 9.60049ZM45.2364 9.60049C45.2732 9.57014 45.3276 9.57535 45.3579 9.61213C45.4508 9.72465 45.5427 9.838 45.6336 9.95216C45.6633 9.98946 45.6572 10.0438 45.6199 10.0735C45.5826 10.1032 45.5282 10.0971 45.4985 10.0598C45.4082 9.94638 45.317 9.83381 45.2247 9.72206C45.1944 9.68528 45.1996 9.63085 45.2364 9.60049ZM5.95351 10.6287C5.99182 10.657 5.99986 10.7111 5.97146 10.7494C5.8852 10.8658 5.79992 10.983 5.71565 11.1009C5.68792 11.1397 5.63399 11.1487 5.59519 11.121C5.55638 11.0933 5.5474 11.0393 5.57513 11.0005C5.65998 10.8818 5.74585 10.7638 5.83271 10.6466C5.86111 10.6083 5.91519 10.6003 5.95351 10.6287ZM46.0465 10.6287C46.0848 10.6003 46.1389 10.6083 46.1673 10.6466C46.2541 10.7638 46.34 10.8818 46.4249 11.0005C46.4526 11.0393 46.4436 11.0933 46.4048 11.121C46.366 11.1487 46.3121 11.1397 46.2843 11.1009C46.2001 10.983 46.1148 10.8658 46.0285 10.7494C46.0001 10.7111 46.0082 10.657 46.0465 10.6287ZM5.19813 11.6976C5.23788 11.724 5.24873 11.7776 5.22237 11.8173C5.1423 11.9381 5.06326 12.0595 4.98525 12.1817C4.95959 12.2219 4.9062 12.2337 4.866 12.208C4.8258 12.1824 4.81401 12.129 4.83968 12.0888C4.91822 11.9657 4.99781 11.8434 5.07844 11.7219C5.1048 11.6821 5.15839 11.6713 5.19813 11.6976ZM46.8018 11.6976C46.8416 11.6713 46.8952 11.6821 46.9215 11.7219C47.0022 11.8434 47.0818 11.9657 47.1603 12.0888C47.186 12.129 47.1742 12.1824 47.134 12.208C47.0938 12.2337 47.0404 12.2219 47.0147 12.1817C46.9367 12.0595 46.8577 11.9381 46.7776 11.8173C46.7513 11.7776 46.7621 11.724 46.8018 11.6976ZM47.5003 12.8046C47.5414 12.7804 47.5943 12.794 47.6186 12.8351C47.6927 12.9607 47.7658 13.087 47.8379 13.214C47.8614 13.2555 47.8468 13.3082 47.8053 13.3317C47.7638 13.3553 47.7111 13.3407 47.6876 13.2992C47.6161 13.1731 47.5435 13.0476 47.4699 12.9229C47.4456 12.8818 47.4593 12.8288 47.5003 12.8046ZM4.49965 12.8046C4.54072 12.8288 4.55436 12.8818 4.53012 12.9229C4.45647 13.0476 4.38389 13.1731 4.31237 13.2992C4.28884 13.3407 4.23614 13.3553 4.19465 13.3317C4.15316 13.3082 4.1386 13.2555 4.16212 13.214C4.23414 13.087 4.30723 12.9607 4.38139 12.8351C4.40563 12.794 4.45858 12.7804 4.49965 12.8046ZM3.8601 13.9466C3.90239 13.9687 3.91878 14.0208 3.89673 14.0631C3.82972 14.1916 3.76379 14.3207 3.69897 14.4505C3.67766 14.4931 3.62579 14.5104 3.58313 14.4891C3.54046 14.4678 3.52315 14.4159 3.54447 14.3733C3.60974 14.2426 3.67612 14.1126 3.7436 13.9832C3.76565 13.941 3.81781 13.9246 3.8601 13.9466ZM48.1399 13.9466C48.1822 13.9246 48.2343 13.941 48.2564 13.9832C48.3239 14.1126 48.3902 14.2426 48.4555 14.3733C48.4768 14.4159 48.4595 14.4678 48.4169 14.4891C48.3742 14.5104 48.3223 14.4931 48.301 14.4505C48.2362 14.3207 48.1703 14.1916 48.1033 14.0631C48.0812 14.0208 48.0976 13.9687 48.1399 13.9466ZM48.7186 15.1206C48.762 15.1008 48.8132 15.1199 48.833 15.1633C48.8936 15.2961 48.9531 15.4294 49.0114 15.5634C49.0305 15.6071 49.0105 15.658 48.9667 15.6771C48.923 15.6961 48.8721 15.6761 48.8531 15.6324C48.7952 15.4993 48.7361 15.3669 48.6759 15.235C48.6561 15.1917 48.6752 15.1404 48.7186 15.1206ZM3.28137 15.1206C3.32476 15.1404 3.34387 15.1917 3.32407 15.235C3.26389 15.3669 3.20483 15.4993 3.1469 15.6324C3.12786 15.6761 3.07697 15.6961 3.03325 15.6771C2.98952 15.658 2.96951 15.6071 2.98855 15.5634C3.04688 15.4294 3.10636 15.2961 3.16695 15.1633C3.18676 15.1199 3.23798 15.1008 3.28137 15.1206ZM49.2348 16.3235C49.2792 16.306 49.3293 16.3278 49.3468 16.3721C49.4003 16.5079 49.4527 16.6443 49.5039 16.7812C49.5207 16.8259 49.498 16.8757 49.4533 16.8924C49.4086 16.9091 49.3589 16.8864 49.3422 16.8417C49.2913 16.7057 49.2393 16.5703 49.1861 16.4355C49.1686 16.3911 49.1904 16.341 49.2348 16.3235ZM2.76519 16.3235C2.80956 16.341 2.83135 16.3911 2.81386 16.4355C2.76069 16.5703 2.70867 16.7058 2.6578 16.8417C2.64109 16.8864 2.59133 16.9091 2.54666 16.8924C2.50199 16.8757 2.47932 16.8259 2.49603 16.7812C2.54726 16.6443 2.59964 16.5079 2.65318 16.3721C2.67067 16.3278 2.72082 16.306 2.76519 16.3235ZM49.6869 17.5518C49.7321 17.5367 49.781 17.5611 49.7962 17.6063C49.8425 17.7448 49.8876 17.8838 49.9316 18.0234C49.9459 18.0689 49.9207 18.1174 49.8752 18.1317C49.8297 18.146 49.7812 18.1208 49.7668 18.0753C49.7232 17.9367 49.6784 17.7986 49.6324 17.6611C49.6172 17.6159 49.6416 17.567 49.6869 17.5518ZM2.31311 17.5518C2.35834 17.567 2.38274 17.6159 2.36761 17.6611C2.32161 17.7987 2.27678 17.9367 2.23313 18.0753C2.2188 18.1208 2.17031 18.146 2.12482 18.1317C2.07933 18.1174 2.05407 18.0689 2.0684 18.0234C2.11236 17.8838 2.1575 17.7448 2.20382 17.6063C2.21895 17.5611 2.26788 17.5367 2.31311 17.5518ZM50.0735 18.8024C50.1195 18.7897 50.1671 18.8166 50.1798 18.8626C50.2188 19.0034 50.2565 19.1447 50.2931 19.2864C50.305 19.3326 50.2772 19.3797 50.231 19.3916C50.1849 19.4035 50.1378 19.3757 50.1259 19.3296C50.0896 19.1888 50.052 19.0485 50.0133 18.9086C50.0006 18.8627 50.0276 18.8151 50.0735 18.8024ZM1.92644 18.8024C1.9724 18.8151 1.99935 18.8627 1.98663 18.9087C1.94794 19.0485 1.91043 19.1888 1.87412 19.3296C1.86221 19.3758 1.81512 19.4035 1.76894 19.3916C1.72275 19.3797 1.69497 19.3326 1.70688 19.2864C1.74344 19.1447 1.78121 19.0034 1.82018 18.8626C1.8329 18.8166 1.88047 18.7897 1.92644 18.8024ZM50.3937 20.0716C50.4403 20.0613 50.4864 20.0907 50.4967 20.1373C50.5281 20.2799 50.5584 20.423 50.5874 20.5665C50.5969 20.6132 50.5667 20.6588 50.5199 20.6682C50.4732 20.6777 50.4276 20.6475 50.4182 20.6007C50.3893 20.4582 50.3593 20.3162 50.328 20.1745C50.3177 20.128 50.3471 20.0819 50.3937 20.0716ZM1.60626 20.0716C1.65283 20.0819 1.68225 20.128 1.67197 20.1746C1.64071 20.3162 1.61066 20.4582 1.58182 20.6007C1.57236 20.6475 1.52679 20.6777 1.48005 20.6682C1.4333 20.6588 1.40308 20.6132 1.41254 20.5665C1.44158 20.423 1.47184 20.2799 1.50332 20.1373C1.5136 20.0908 1.55969 20.0613 1.60626 20.0716ZM50.6466 21.356C50.6937 21.3481 50.7381 21.3799 50.746 21.427C50.7699 21.5709 50.7926 21.7153 50.814 21.8601C50.821 21.9073 50.7884 21.9512 50.7413 21.9582C50.6941 21.9652 50.6502 21.9326 50.6432 21.8854C50.6219 21.7416 50.5993 21.5983 50.5756 21.4553C50.5678 21.4082 50.5996 21.3638 50.6466 21.356ZM1.35337 21.356C1.40042 21.3638 1.43222 21.4083 1.4244 21.4553C1.40065 21.5983 1.37811 21.7416 1.3568 21.8854C1.34981 21.9326 1.3059 21.9652 1.25872 21.9582C1.21154 21.9512 1.17896 21.9073 1.18596 21.8601C1.20741 21.7153 1.23011 21.571 1.25403 21.427C1.26184 21.38 1.30632 21.3482 1.35337 21.356ZM50.8317 22.6518C50.8791 22.6465 50.9219 22.6806 50.9272 22.728C50.9435 22.8729 50.9586 23.0182 50.9725 23.1638C50.977 23.2113 50.9422 23.2534 50.8947 23.2579C50.8472 23.2625 50.8051 23.2276 50.8006 23.1802C50.7868 23.0355 50.7718 22.8912 50.7556 22.7473C50.7502 22.6999 50.7843 22.6572 50.8317 22.6518ZM1.16825 22.6518C1.21565 22.6572 1.24974 22.6999 1.24439 22.7473C1.22817 22.8912 1.21317 23.0355 1.19941 23.1802C1.19489 23.2276 1.15274 23.2625 1.10526 23.258C1.05779 23.2534 1.02296 23.2113 1.02748 23.1638C1.04133 23.0182 1.05643 22.8729 1.07277 22.728C1.07811 22.6806 1.12086 22.6465 1.16825 22.6518ZM50.9489 23.9556C50.9965 23.9527 51.0374 23.989 51.0403 24.0366C51.0491 24.1821 51.0566 24.3279 51.0629 24.474C51.0649 24.5216 51.0279 24.5619 50.9803 24.564C50.9326 24.566 50.8924 24.529 50.8903 24.4814C50.8841 24.3363 50.8766 24.1915 50.8679 24.047C50.865 23.9994 50.9013 23.9585 50.9489 23.9556ZM1.05108 23.9556C1.09869 23.9585 1.13496 23.9994 1.13209 24.047C1.12338 24.1915 1.1159 24.3363 1.10967 24.4814C1.10762 24.5291 1.06734 24.566 1.01969 24.564C0.972037 24.5619 0.93507 24.5217 0.937117 24.474C0.943394 24.3279 0.950922 24.1821 0.959689 24.0366C0.962558 23.989 1.00348 23.9528 1.05108 23.9556ZM50.9983 25.2637C51.046 25.2633 51.085 25.3016 51.0854 25.3493C51.086 25.4225 51.0863 25.4959 51.0863 25.5693C51.0863 25.6427 51.086 25.716 51.0854 25.7892C51.085 25.8369 51.046 25.8752 50.9983 25.8748C50.9506 25.8744 50.9123 25.8354 50.9127 25.7877C50.9133 25.715 50.9136 25.6422 50.9136 25.5693C50.9136 25.4964 50.9133 25.4235 50.9127 25.3508C50.9123 25.3031 50.9506 25.2641 50.9983 25.2637ZM1.00167 25.2637C1.04936 25.2641 1.08769 25.3031 1.08728 25.3508C1.08666 25.4235 1.08635 25.4964 1.08635 25.5693C1.08635 25.6422 1.08666 25.715 1.08728 25.7878C1.08769 25.8354 1.04937 25.8744 1.00167 25.8748C0.953983 25.8753 0.914989 25.8369 0.91458 25.7892C0.91395 25.716 0.913635 25.6427 0.913635 25.5693C0.913635 25.4959 0.91395 25.4226 0.914579 25.3493C0.914989 25.3016 0.953983 25.2633 1.00167 25.2637ZM50.9803 26.5745C51.0279 26.5766 51.0649 26.6169 51.0629 26.6645C51.0566 26.8106 51.0491 26.9564 51.0403 27.1019C51.0374 27.1495 50.9965 27.1858 50.9489 27.1829C50.9013 27.18 50.865 27.1391 50.8679 27.0915C50.8766 26.947 50.8841 26.8022 50.8903 26.6571C50.8924 26.6095 50.9326 26.5725 50.9803 26.5745ZM1.01969 26.5746C1.06734 26.5725 1.10762 26.6095 1.10967 26.6571C1.1159 26.8023 1.12338 26.9471 1.13209 27.0915C1.13496 27.1391 1.09869 27.1801 1.05108 27.1829C1.00348 27.1858 0.962559 27.1495 0.95969 27.1019C0.950923 26.9565 0.943395 26.8107 0.937118 26.6645C0.935071 26.6169 0.972038 26.5766 1.01969 26.5746ZM50.8947 27.8806C50.9422 27.8851 50.977 27.9272 50.9725 27.9747C50.9586 28.1204 50.9435 28.2656 50.9272 28.4105C50.9219 28.4579 50.8791 28.492 50.8317 28.4867C50.7843 28.4813 50.7502 28.4386 50.7556 28.3912C50.7718 28.2473 50.7868 28.103 50.8006 27.9584C50.8051 27.9109 50.8472 27.8761 50.8947 27.8806ZM1.10527 27.8806C1.15274 27.8761 1.1949 27.9109 1.19941 27.9584C1.21317 28.103 1.22817 28.2473 1.24439 28.3912C1.24974 28.4386 1.21565 28.4814 1.16826 28.4867C1.12086 28.492 1.07811 28.458 1.07277 28.4106C1.05643 28.2657 1.04133 28.1204 1.02748 27.9747C1.02296 27.9273 1.05779 27.8851 1.10527 27.8806ZM50.7413 29.1803C50.7884 29.1873 50.821 29.2313 50.814 29.2784C50.7926 29.4232 50.7699 29.5676 50.746 29.7115C50.7381 29.7586 50.6937 29.7904 50.6466 29.7826C50.5996 29.7747 50.5678 29.7303 50.5756 29.6832C50.5993 29.5403 50.6219 29.3969 50.6432 29.2531C50.6502 29.2059 50.6941 29.1734 50.7413 29.1803ZM1.25872 29.1804C1.3059 29.1734 1.34981 29.2059 1.3568 29.2531C1.37811 29.3969 1.40065 29.5403 1.4244 29.6832C1.43222 29.7303 1.40042 29.7748 1.35337 29.7826C1.30632 29.7904 1.26185 29.7586 1.25403 29.7115C1.23011 29.5676 1.20742 29.4232 1.18596 29.2784C1.17897 29.2313 1.21154 29.1874 1.25872 29.1804ZM50.5199 30.4703C50.5667 30.4798 50.5969 30.5253 50.5874 30.5721C50.5584 30.7156 50.5281 30.8586 50.4967 31.0012C50.4864 31.0478 50.4403 31.0772 50.3937 31.0669C50.3471 31.0566 50.3177 31.0105 50.328 30.964C50.3593 30.8224 50.3893 30.6803 50.4182 30.5378C50.4276 30.4911 50.4732 30.4608 50.5199 30.4703ZM1.48005 30.4703C1.5268 30.4608 1.57236 30.4911 1.58182 30.5378C1.61066 30.6803 1.64071 30.8224 1.67197 30.964C1.68225 31.0106 1.65283 31.0566 1.60626 31.0669C1.55969 31.0772 1.5136 31.0478 1.50332 31.0012C1.47184 30.8586 1.44158 30.7156 1.41254 30.5721C1.40308 30.5253 1.4333 30.4798 1.48005 30.4703ZM50.231 31.7469C50.2772 31.7588 50.305 31.8059 50.2931 31.8521C50.2565 31.9939 50.2188 32.1352 50.1798 32.2759C50.1671 32.3219 50.1195 32.3489 50.0735 32.3361C50.0276 32.3234 50.0006 32.2758 50.0134 32.2299C50.052 32.0901 50.0896 31.9497 50.1259 31.809C50.1378 31.7628 50.1849 31.735 50.231 31.7469ZM1.76894 31.7469C1.81512 31.735 1.86221 31.7628 1.87412 31.809C1.91043 31.9498 1.94794 32.0901 1.98663 32.2299C1.99936 32.2759 1.97241 32.3234 1.92644 32.3361C1.88048 32.3489 1.8329 32.3219 1.82018 32.276C1.78121 32.1352 1.74344 31.9939 1.70688 31.8521C1.69497 31.8059 1.72276 31.7588 1.76894 31.7469ZM49.8752 33.0068C49.9207 33.0212 49.9459 33.0696 49.9316 33.1151C49.8876 33.2547 49.8425 33.3937 49.7962 33.5322C49.781 33.5774 49.7321 33.6018 49.6869 33.5867C49.6416 33.5716 49.6172 33.5226 49.6324 33.4774C49.6784 33.3399 49.7232 33.2018 49.7669 33.0632C49.7812 33.0178 49.8297 32.9925 49.8752 33.0068ZM2.12482 33.0068C2.17031 32.9925 2.2188 33.0178 2.23313 33.0633C2.27679 33.2018 2.32162 33.3399 2.36761 33.4774C2.38274 33.5226 2.35834 33.5716 2.31311 33.5867C2.26788 33.6018 2.21895 33.5774 2.20382 33.5322C2.1575 33.3937 2.11236 33.2547 2.0684 33.1151C2.05407 33.0697 2.07933 33.0212 2.12482 33.0068ZM49.4533 34.2462C49.498 34.2629 49.5207 34.3126 49.5039 34.3573C49.4527 34.4942 49.4003 34.6306 49.3468 34.7664C49.3293 34.8108 49.2792 34.8326 49.2348 34.8151C49.1904 34.7976 49.1686 34.7474 49.1861 34.7031C49.2393 34.5682 49.2913 34.4328 49.3422 34.2968C49.3589 34.2521 49.4086 34.2294 49.4533 34.2462ZM2.54666 34.2462C2.59133 34.2295 2.64109 34.2521 2.6578 34.2968C2.70867 34.4328 2.76069 34.5682 2.81386 34.7031C2.83135 34.7474 2.80956 34.7976 2.7652 34.8151C2.72083 34.8326 2.67068 34.8108 2.65318 34.7664C2.59965 34.6306 2.54726 34.4942 2.49604 34.3573C2.47933 34.3126 2.50199 34.2629 2.54666 34.2462ZM48.9667 35.4615C49.0105 35.4805 49.0305 35.5314 49.0114 35.5751C48.9531 35.7091 48.8936 35.8425 48.833 35.9752C48.8132 36.0186 48.762 36.0377 48.7186 36.0179C48.6752 35.9981 48.6561 35.9469 48.6759 35.9035C48.7361 35.7717 48.7952 35.6392 48.8531 35.5062C48.8721 35.4624 48.923 35.4424 48.9667 35.4615ZM3.03325 35.4615C3.07698 35.4424 3.12786 35.4624 3.1469 35.5062C3.20483 35.6392 3.26389 35.7717 3.32407 35.9035C3.34387 35.9469 3.32476 35.9981 3.28137 36.0179C3.23799 36.0377 3.18676 36.0186 3.16695 35.9752C3.10636 35.8425 3.04688 35.7091 2.98855 35.5751C2.96951 35.5314 2.98952 35.4805 3.03325 35.4615ZM48.4169 36.6494C48.4595 36.6707 48.4768 36.7226 48.4555 36.7653C48.3902 36.8959 48.3239 37.0259 48.2564 37.1553C48.2343 37.1976 48.1822 37.214 48.1399 37.1919C48.0976 37.1699 48.0812 37.1177 48.1033 37.0754C48.1703 36.9469 48.2362 36.8178 48.301 36.6881C48.3223 36.6454 48.3742 36.6281 48.4169 36.6494ZM3.58313 36.6494C3.62579 36.6281 3.67766 36.6454 3.69897 36.6881C3.7638 36.8178 3.82972 36.9469 3.89673 37.0754C3.91878 37.1177 3.90239 37.1699 3.8601 37.1919C3.81781 37.214 3.76565 37.1976 3.7436 37.1553C3.67612 37.0259 3.60974 36.8959 3.54447 36.7653C3.52315 36.7226 3.54046 36.6707 3.58313 36.6494ZM4.19465 37.8068C4.23614 37.7833 4.28884 37.7978 4.31237 37.8393C4.38389 37.9655 4.45647 38.0909 4.53012 38.2157C4.55436 38.2567 4.54072 38.3097 4.49965 38.3339C4.45858 38.3582 4.40563 38.3445 4.38139 38.3035C4.30723 38.1778 4.23414 38.0515 4.16212 37.9245C4.1386 37.883 4.15316 37.8303 4.19465 37.8068ZM47.8053 37.8068C47.8468 37.8303 47.8614 37.883 47.8379 37.9245C47.7658 38.0515 47.6927 38.1778 47.6186 38.3035C47.5943 38.3445 47.5414 38.3582 47.5003 38.3339C47.4593 38.3097 47.4456 38.2567 47.4699 38.2157C47.5435 38.0909 47.6161 37.9655 47.6876 37.8393C47.7111 37.7978 47.7638 37.7833 47.8053 37.8068ZM4.866 38.9305C4.9062 38.9048 4.95959 38.9166 4.98525 38.9568C5.06326 39.079 5.1423 39.2005 5.22237 39.3212C5.24873 39.361 5.23788 39.4145 5.19813 39.4409C5.15839 39.4673 5.1048 39.4564 5.07844 39.4167C4.99781 39.2951 4.91822 39.1728 4.83968 39.0497C4.81401 39.0095 4.8258 38.9562 4.866 38.9305ZM47.134 38.9305C47.1742 38.9562 47.186 39.0095 47.1603 39.0497C47.0818 39.1728 47.0022 39.2951 46.9215 39.4167C46.8952 39.4564 46.8416 39.4673 46.8018 39.4409C46.7621 39.4145 46.7513 39.361 46.7776 39.3212C46.8577 39.2005 46.9367 39.079 47.0147 38.9568C47.0404 38.9166 47.0938 38.9048 47.134 38.9305ZM5.59519 40.0175C5.63399 39.9898 5.68792 39.9988 5.71565 40.0376C5.79992 40.1555 5.8852 40.2727 5.97146 40.3891C5.99986 40.4274 5.99182 40.4815 5.95351 40.5099C5.91519 40.5383 5.86111 40.5302 5.83271 40.4919C5.74585 40.3747 5.65998 40.2567 5.57513 40.138C5.5474 40.0992 5.55638 40.0453 5.59519 40.0175ZM46.4048 40.0175C46.4436 40.0453 46.4526 40.0992 46.4249 40.138C46.34 40.2567 46.2541 40.3747 46.1673 40.4919C46.1389 40.5302 46.0848 40.5383 46.0465 40.5099C46.0082 40.4815 46.0001 40.4274 46.0285 40.3891C46.1148 40.2727 46.2001 40.1555 46.2843 40.0376C46.3121 39.9988 46.366 39.9898 46.4048 40.0175ZM6.38011 41.065C6.41742 41.0353 6.47175 41.0415 6.50146 41.0788C6.59176 41.1921 6.68303 41.3047 6.77525 41.4165C6.80561 41.4532 6.8004 41.5077 6.76361 41.538C6.72683 41.5684 6.6724 41.5632 6.64204 41.5264C6.54918 41.4139 6.45729 41.3005 6.36636 41.1864C6.33665 41.1491 6.3428 41.0947 6.38011 41.065ZM45.6199 41.065C45.6572 41.0947 45.6633 41.1491 45.6336 41.1864C45.5427 41.3005 45.4508 41.4139 45.3579 41.5264C45.3276 41.5632 45.2732 41.5684 45.2364 41.538C45.1996 41.5077 45.1944 41.4532 45.2247 41.4165C45.317 41.3047 45.4082 41.1921 45.4985 41.0788C45.5282 41.0415 45.5826 41.0353 45.6199 41.065ZM44.7814 42.0702C44.8171 42.1018 44.8205 42.1564 44.7888 42.1921C44.6921 42.3014 44.5944 42.4098 44.4958 42.5174C44.4635 42.5525 44.4089 42.5549 44.3738 42.5227C44.3386 42.4904 44.3362 42.4358 44.3685 42.4007C44.4664 42.2938 44.5634 42.1861 44.6595 42.0776C44.6911 42.0419 44.7457 42.0386 44.7814 42.0702ZM7.21855 42.0702C7.25426 42.0386 7.30884 42.0419 7.34045 42.0776C7.43655 42.1861 7.53357 42.2938 7.63151 42.4007C7.66374 42.4358 7.66137 42.4904 7.62622 42.5227C7.59106 42.5549 7.53644 42.5525 7.50421 42.5174C7.40559 42.4098 7.3079 42.3014 7.21114 42.1921C7.17953 42.1564 7.18285 42.1018 7.21855 42.0702ZM8.10818 43.0304C8.1422 42.997 8.19687 42.9974 8.2303 43.0315C8.33191 43.1348 8.43441 43.2373 8.5378 43.3389C8.57181 43.3724 8.57228 43.4271 8.53885 43.4611C8.50542 43.4951 8.45075 43.4956 8.41673 43.4621C8.31264 43.3598 8.20943 43.2566 8.10712 43.1525C8.07369 43.1185 8.07417 43.0638 8.10818 43.0304ZM43.8918 43.0304C43.9258 43.0638 43.9263 43.1185 43.8929 43.1525C43.7906 43.2566 43.6873 43.3598 43.5832 43.4621C43.5492 43.4956 43.4946 43.4951 43.4611 43.4611C43.4277 43.4271 43.4282 43.3724 43.4622 43.3389C43.5656 43.2373 43.6681 43.1348 43.7697 43.0315C43.8031 42.9974 43.8578 42.997 43.8918 43.0304ZM42.9534 43.943C42.9856 43.9782 42.9833 44.0328 42.9481 44.065C42.8405 44.1637 42.7321 44.2614 42.6228 44.3581C42.5871 44.3897 42.5325 44.3864 42.5009 44.3507C42.4693 44.315 42.4726 44.2604 42.5083 44.2288C42.6169 44.1327 42.7246 44.0357 42.8314 43.9377C42.8665 43.9055 42.9212 43.9079 42.9534 43.943ZM9.04658 43.943C9.07881 43.9079 9.13344 43.9055 9.16859 43.9377C9.27542 44.0357 9.38311 44.1327 9.49164 44.2288C9.52735 44.2604 9.53067 44.315 9.49905 44.3507C9.46744 44.3864 9.41286 44.3897 9.37715 44.3581C9.26787 44.2614 9.15944 44.1637 9.05188 44.065C9.01672 44.0328 9.01435 43.9782 9.04658 43.943ZM10.0312 44.8056C10.0616 44.7689 10.116 44.7636 10.1528 44.794C10.2645 44.8862 10.3771 44.9775 10.4905 45.0678C10.5278 45.0975 10.5339 45.1518 10.5042 45.1891C10.4745 45.2264 10.4202 45.2326 10.3829 45.2029C10.2687 45.112 10.1554 45.0201 10.0429 44.9272C10.0061 44.8969 10.0009 44.8424 10.0312 44.8056ZM41.9688 44.8056C41.9991 44.8424 41.9939 44.8969 41.9571 44.9272C41.8446 45.0201 41.7313 45.112 41.6171 45.2029C41.5798 45.2326 41.5255 45.2264 41.4958 45.1891C41.466 45.1518 41.4722 45.0975 41.5095 45.0678C41.6229 44.9775 41.7354 44.8862 41.8472 44.794C41.884 44.7636 41.9384 44.7689 41.9688 44.8056ZM11.0594 45.6157C11.0878 45.5774 11.1419 45.5694 11.1802 45.5978C11.2966 45.6841 11.4137 45.7693 11.5317 45.8536C11.5705 45.8813 11.5795 45.9353 11.5517 45.9741C11.524 46.0129 11.4701 46.0219 11.4313 45.9941C11.3125 45.9093 11.1945 45.8234 11.0773 45.7365C11.039 45.7081 11.031 45.6541 11.0594 45.6157ZM40.9406 45.6157C40.969 45.6541 40.961 45.7081 40.9226 45.7365C40.8055 45.8234 40.6875 45.9093 40.5687 45.9941C40.5299 46.0219 40.476 46.0129 40.4483 45.9741C40.4205 45.9353 40.4295 45.8813 40.4683 45.8536C40.5862 45.7693 40.7034 45.6841 40.8198 45.5978C40.8581 45.5694 40.9122 45.5774 40.9406 45.6157ZM12.1284 46.3711C12.1547 46.3314 12.2083 46.3205 12.248 46.3469C12.3688 46.427 12.4902 46.506 12.6124 46.584C12.6526 46.6097 12.6644 46.6631 12.6388 46.7033C12.6131 46.7435 12.5597 46.7552 12.5195 46.7296C12.3965 46.651 12.2742 46.5714 12.1526 46.4908C12.1128 46.4645 12.102 46.4109 12.1284 46.3711ZM39.8716 46.3711C39.898 46.4109 39.8871 46.4645 39.8474 46.4908C39.7258 46.5714 39.6035 46.651 39.4805 46.7296C39.4403 46.7552 39.3869 46.7435 39.3612 46.7033C39.3356 46.6631 39.3473 46.6097 39.3875 46.584C39.5097 46.506 39.6312 46.427 39.7519 46.3469C39.7917 46.3205 39.8453 46.3314 39.8716 46.3711ZM13.2353 47.0696C13.2596 47.0285 13.3125 47.0149 13.3536 47.0391C13.4783 47.1128 13.6038 47.1854 13.7299 47.2569C13.7714 47.2804 13.786 47.3331 13.7625 47.3746C13.7389 47.4161 13.6862 47.4307 13.6448 47.4071C13.5177 47.3351 13.3914 47.262 13.2658 47.1879C13.2247 47.1636 13.2111 47.1107 13.2353 47.0696ZM38.7647 47.0696C38.7889 47.1107 38.7753 47.1636 38.7342 47.1879C38.6086 47.262 38.4822 47.3351 38.3552 47.4071C38.3137 47.4307 38.261 47.4161 38.2375 47.3746C38.214 47.3331 38.2286 47.2804 38.27 47.2569C38.3962 47.1854 38.5216 47.1128 38.6464 47.0391C38.6875 47.0149 38.7404 47.0285 38.7647 47.0696ZM14.3773 47.7092C14.3994 47.6669 14.4516 47.6505 14.4938 47.6725C14.6223 47.7395 14.7514 47.8055 14.8812 47.8703C14.9239 47.8916 14.9412 47.9435 14.9198 47.9861C14.8985 48.0288 14.8467 48.0461 14.804 48.0248C14.6733 47.9595 14.5433 47.8931 14.414 47.8257C14.3717 47.8036 14.3553 47.7514 14.3773 47.7092ZM37.6226 47.7092C37.6447 47.7514 37.6283 47.8036 37.586 47.8257C37.4567 47.8931 37.3266 47.9595 37.196 48.0248C37.1533 48.0461 37.1015 48.0288 37.0801 47.9861C37.0588 47.9435 37.0761 47.8916 37.1188 47.8703C37.2486 47.8055 37.3777 47.7395 37.5061 47.6725C37.5484 47.6505 37.6006 47.6669 37.6226 47.7092ZM36.4486 48.2879C36.4684 48.3313 36.4493 48.3825 36.4059 48.4023C36.2732 48.4629 36.1398 48.5224 36.0058 48.5807C35.9621 48.5997 35.9112 48.5797 35.8922 48.536C35.8731 48.4923 35.8932 48.4414 35.9369 48.4224C36.0699 48.3644 36.2024 48.3054 36.3342 48.2452C36.3776 48.2254 36.4288 48.2445 36.4486 48.2879ZM15.5514 48.2879C15.5712 48.2445 15.6224 48.2254 15.6658 48.2452C15.7976 48.3054 15.93 48.3644 16.0631 48.4224C16.1068 48.4414 16.1268 48.4923 16.1078 48.536C16.0888 48.5797 16.0379 48.5997 15.9941 48.5807C15.8602 48.5224 15.7268 48.4629 15.5941 48.4023C15.5507 48.3825 15.5315 48.3313 15.5514 48.2879ZM16.7542 48.8041C16.7717 48.7597 16.8218 48.7379 16.8662 48.7554C17.0011 48.8086 17.1365 48.8606 17.2725 48.9115C17.3171 48.9282 17.3398 48.9779 17.3231 49.0226C17.3064 49.0673 17.2566 49.0899 17.212 49.0732C17.075 49.022 16.9387 48.9696 16.8029 48.9161C16.7585 48.8986 16.7367 48.8484 16.7542 48.8041ZM35.2458 48.8041C35.2633 48.8484 35.2415 48.8986 35.1971 48.9161C35.0613 48.9696 34.925 49.022 34.788 49.0732C34.7434 49.0899 34.6936 49.0673 34.6769 49.0226C34.6602 48.9779 34.6828 48.9282 34.7275 48.9115C34.8635 48.8606 34.9989 48.8086 35.1338 48.7554C35.1782 48.7379 35.2283 48.7597 35.2458 48.8041ZM34.0174 49.2561C34.0325 49.3014 34.0081 49.3503 33.9629 49.3654C33.8244 49.4118 33.6854 49.4569 33.5459 49.5009C33.5004 49.5152 33.4519 49.4899 33.4376 49.4444C33.4232 49.3989 33.4485 49.3505 33.494 49.3361C33.6326 49.2925 33.7706 49.2476 33.9081 49.2016C33.9534 49.1865 34.0023 49.2109 34.0174 49.2561ZM17.9826 49.2561C17.9977 49.2109 18.0466 49.1865 18.0919 49.2016C18.2294 49.2476 18.3674 49.2925 18.506 49.3361C18.5515 49.3505 18.5768 49.3989 18.5624 49.4444C18.5481 49.4899 18.4996 49.5152 18.4541 49.5009C18.3146 49.4569 18.1756 49.4118 18.0371 49.3654C17.9918 49.3503 17.9674 49.3014 17.9826 49.2561ZM32.7669 49.6428C32.7796 49.6888 32.7526 49.7364 32.7067 49.7491C32.5659 49.788 32.4246 49.8258 32.2828 49.8624C32.2366 49.8743 32.1895 49.8465 32.1776 49.8003C32.1657 49.7541 32.1935 49.707 32.2397 49.6951C32.3805 49.6588 32.5208 49.6213 32.6606 49.5826C32.7066 49.5699 32.7542 49.5968 32.7669 49.6428ZM19.2331 49.6428C19.2458 49.5968 19.2934 49.5699 19.3394 49.5826C19.4792 49.6213 19.6195 49.6588 19.7603 49.6951C19.8065 49.707 19.8343 49.7541 19.8224 49.8003C19.8104 49.8465 19.7634 49.8743 19.7172 49.8624C19.5754 49.8258 19.4341 49.788 19.2933 49.7491C19.2473 49.7364 19.2204 49.6888 19.2331 49.6428ZM31.4977 49.963C31.5079 50.0096 31.4785 50.0556 31.4319 50.0659C31.2893 50.0974 31.1463 50.1277 31.0028 50.1567C30.9561 50.1662 30.9105 50.1359 30.901 50.0892C30.8916 50.0425 30.9218 49.9969 30.9685 49.9874C31.111 49.9586 31.2531 49.9285 31.3947 49.8973C31.4413 49.887 31.4874 49.9164 31.4977 49.963ZM20.5023 49.963C20.5126 49.9164 20.5587 49.887 20.6053 49.8973C20.7469 49.9285 20.889 49.9586 21.0315 49.9874C21.0782 49.9969 21.1084 50.0425 21.099 50.0892C21.0895 50.136 21.0439 50.1662 20.9972 50.1567C20.8537 50.1277 20.7106 50.0974 20.5681 50.0659C20.5215 50.0557 20.4921 50.0096 20.5023 49.963ZM30.2133 50.2159C30.2211 50.2629 30.1893 50.3074 30.1423 50.3152C29.9983 50.3391 29.8539 50.3618 29.7092 50.3833C29.662 50.3903 29.6181 50.3577 29.6111 50.3105C29.6041 50.2634 29.6367 50.2194 29.6839 50.2124C29.8276 50.1911 29.971 50.1686 30.114 50.1448C30.161 50.137 30.2055 50.1688 30.2133 50.2159ZM21.7867 50.2159C21.7945 50.1688 21.839 50.137 21.886 50.1449C22.029 50.1686 22.1724 50.1911 22.3161 50.2124C22.3633 50.2194 22.3959 50.2634 22.3889 50.3105C22.3819 50.3577 22.338 50.3903 22.2908 50.3833C22.1461 50.3618 22.0017 50.3391 21.8577 50.3152C21.8107 50.3074 21.7789 50.2629 21.7867 50.2159ZM23.0826 50.401C23.0879 50.3536 23.1307 50.3195 23.1781 50.3249C23.322 50.3411 23.4663 50.3561 23.6109 50.3698C23.6584 50.3744 23.6932 50.4165 23.6887 50.464C23.6842 50.5115 23.642 50.5463 23.5945 50.5418C23.4489 50.5279 23.3036 50.5128 23.1587 50.4965C23.1113 50.4911 23.0772 50.4484 23.0826 50.401ZM28.9174 50.401C28.9228 50.4484 28.8887 50.4911 28.8413 50.4965C28.6964 50.5128 28.5511 50.5279 28.4055 50.5418C28.358 50.5463 28.3158 50.5115 28.3113 50.464C28.3068 50.4165 28.3416 50.3744 28.3891 50.3698C28.5337 50.3561 28.678 50.3411 28.8219 50.3249C28.8693 50.3195 28.9121 50.3536 28.9174 50.401ZM24.3864 50.5182C24.3892 50.4706 24.4301 50.4343 24.4777 50.4372C24.6222 50.4459 24.767 50.4534 24.9121 50.4596C24.9598 50.4616 24.9968 50.5019 24.9947 50.5496C24.9927 50.5972 24.9524 50.6342 24.9047 50.6321C24.7586 50.6259 24.6128 50.6183 24.4674 50.6096C24.4197 50.6067 24.3835 50.5658 24.3864 50.5182ZM27.6137 50.5182C27.6165 50.5658 27.5803 50.6067 27.5326 50.6096C27.3872 50.6183 27.2414 50.6259 27.0953 50.6321C27.0476 50.6342 27.0073 50.5972 27.0053 50.5496C27.0032 50.5019 27.0402 50.4616 27.0879 50.4596C27.233 50.4534 27.3778 50.4459 27.5223 50.4372C27.5699 50.4343 27.6108 50.4706 27.6137 50.5182ZM25.6944 50.5676C25.6948 50.5199 25.7338 50.4816 25.7815 50.482C25.8543 50.4826 25.9271 50.4829 26 50.4829C26.0729 50.4829 26.1457 50.4826 26.2185 50.482C26.2662 50.4816 26.3052 50.5199 26.3056 50.5676C26.306 50.6153 26.2677 50.6543 26.22 50.6547C26.1467 50.6553 26.0734 50.6556 26 50.6556C25.9266 50.6556 25.8533 50.6553 25.78 50.6547C25.7324 50.6543 25.694 50.6153 25.6944 50.5676Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 52 / 51,\n  svg: Rings,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/how-video-calls-saved-the-day/chatBox.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Chat Box', 'sticker name', 'web-stories');\n\nfunction Chatbox({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 44 20\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.69329 0C0.834158 0 0.137695 0.696461 0.137695 1.55559V15.3878C0.137695 16.2469 0.834159 16.9434 1.69329 16.9434H30.8417L33.8983 20L36.955 16.9434H42.3069C43.166 16.9434 43.8625 16.2469 43.8625 15.3878V1.55559C43.8625 0.696463 43.166 0 42.3069 0H1.69329Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 44 / 20,\n  svg: Chatbox,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/how-video-calls-saved-the-day/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as videoCallsBrowserIcon } from './yellowBrowser';\nimport { default as videoCallsTooltip } from './chatBox';\n\nexport { videoCallsBrowserIcon, videoCallsTooltip };\n"
  },
  {
    "path": "packages/stickers/src/how-video-calls-saved-the-day/yellowBrowser.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Browser', 'sticker name', 'web-stories');\n\nfunction YellowBrowserIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 37\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path d=\"M0 0H52V37H0V0Z\" fill=\"#FFBF0B\" />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M51.6286 0.37H0.371429V36.63H51.6286V0.37ZM0 0V37H52V0H0Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M47.7812 2.99921L49.2274 1.55322L49.4339 1.75981L47.9879 3.2058L47.7812 2.99921Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M47.9888 1.55298L49.4348 2.99912L49.2282 3.20569L47.7822 1.75955L47.9888 1.55298Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M40.7705 2.23242L42.8156 2.23253V2.52468L40.7705 2.52457V2.23242Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M45.3132 2.26853L44.4075 2.26848V3.02816L45.3132 3.0282V2.26853ZM44.13 1.99097L44.1299 3.30564L45.5907 3.30572L45.5908 1.99104L44.13 1.99097Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M45.0059 1.40674L46.4667 1.40682L46.4666 2.72149L45.0059 2.72141V1.40674Z\"\n        fill=\"#FFBF0B\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M46.1892 1.6843L45.2834 1.68425V2.44393L46.1891 2.44398L46.1892 1.6843ZM45.0059 1.40674V2.72141L46.4666 2.72149L46.4667 1.40682L45.0059 1.40674Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M3.09463 2.62129C3.09463 2.82298 2.93113 2.98648 2.72945 2.98648C2.52776 2.98648 2.36426 2.82298 2.36426 2.62129C2.36426 2.4196 2.52776 2.2561 2.72945 2.2561C2.93113 2.2561 3.09463 2.4196 3.09463 2.62129Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M4.70205 2.62129C4.70205 2.82298 4.53855 2.98648 4.33686 2.98648C4.13518 2.98648 3.97168 2.82298 3.97168 2.62129C3.97168 2.4196 4.13518 2.2561 4.33686 2.2561C4.53855 2.2561 4.70205 2.4196 4.70205 2.62129Z\"\n        fill=\"#398F5E\"\n      />\n      <path\n        d=\"M6.3085 2.62129C6.3085 2.82298 6.145 2.98648 5.94331 2.98648C5.74163 2.98648 5.57812 2.82298 5.57812 2.62129C5.57812 2.4196 5.74163 2.2561 5.94331 2.2561C6.145 2.2561 6.3085 2.4196 6.3085 2.62129Z\"\n        fill=\"#398F5E\"\n      />\n      <path d=\"M0 4.57617H51.8V4.94617H0V4.57617Z\" fill=\"#398F5E\" />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 37,\n  svg: YellowBrowserIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as beautyStickers from './fresh-and-bright';\nimport * as cookingStickers from './food-and-stuff';\nimport * as doersGetMoreDoneStickers from './doers-get-more-done';\nimport * as weeklyEntertainmentStickers from './weekly-entertainment';\nimport * as fashionOnTheGoStickers from './fashion-on-the-go';\nimport * as noDaysOffStickers from './no-days-off';\nimport * as experienceThailandStickers from './experience-thailand';\nimport * as wellbeingSleepStickers from './sleep';\nimport * as guideTobakingBreadStickers from './baking-bread-guide';\nimport * as sangriaArtichokeStickers from './sangria-artichoke';\nimport * as crispyChickenThighStickers from './kitchen-stories';\nimport * as almondosFilmsStickers from './almodos-films';\nimport * as bestPizzaInNYCStickers from './pizzas-in-nyc';\nimport * as twelveHoursInBarcelonaStickers from './12-hours-in-barcelona';\nimport * as bestFitnessAppsStickers from './fitness-apps-ranked';\nimport * as streetStyleOnTheGoStickers from './street-style-on-the-go';\nimport * as plantBasedDyesStickers from './plant-based-dyes';\nimport * as indoorGardenOasisStickers from './indoor-garden-oasis';\nimport * as killBellyFatStickers from './belly-fat-workout';\nimport * as crownSeasonsRecappedStickers from './tv-show-recap';\nimport * as honeymooningInItalyStickers from './honeymooning-in-italy';\nimport * as stayAtAceHotelKyotoStickers from './ace-hotel-kyoto-review';\nimport * as videoCallsSavedTheDayStickers from './how-video-calls-saved-the-day';\nimport * as pickTheRightLaptopStickers from './laptop-buying-guide';\nimport * as quizForYourBestSkinStickers from './beauty-quiz';\nimport * as atHomeOfficeStickers from './diy-home-office';\nimport * as rockMusicFestivalStickers from './rock-music-festival';\nimport * as losAngelesCityGuideStickers from './los-angeles-city-guide';\nimport * as hawaiiTravelPackingListStickers from './hawaii-travel-packing-list';\nimport * as howContactTracingWorksStickers from './how-contact-tracing-works';\nimport * as summerFashionCollectionStickers from './summer-fashion-collection';\nimport * as artOnTheInternetStickers from './buying-art-on-the-internet';\nimport * as newYorkPartyRoundUpStickers from './new-york-party-round-up';\nimport * as aDayInTheLifeStickers from './a-day-in-the-life';\nimport * as elegantTravelItineraryStickers from './elegant-travel-itinerary';\nimport * as modernistTravelGuideStickers from './modernist-travel-guide';\nimport * as magazineArticleStickers from './magazine-article';\nimport * as fashionInspirationStickers from './fashion-inspiration';\nimport * as skinCareAtHomeStickers from './skin-care-at-home';\nimport * as artBooksGiftGuideStickers from './art-books-gift-guide';\nimport * as vintageChairsWhatToLookForStickers from './vintage-chairs-what-to-look-for';\nimport * as celebrityLifeStoryStickers from './celebrity-life-story';\nimport * as summerAdventureGuideStickers from './summer-adventure-guide';\nimport * as oneDayCityItineraryStickers from './one-day-city-itinerary';\nimport * as technologyAdviceStickers from './technology-advice';\nimport * as allAboutCarsStickers from './all-about-cars';\nimport * as sustainabilityTipsStickers from './sustainability-tips';\nimport * as anArtistsLegacyStickers from './an-artists-legacy';\nimport * as tipsForThrowingAnOutdoorLuauStickers from './tips-for-throwing-an-outdoor-luau';\n\nexport default {\n  ...beautyStickers,\n  ...cookingStickers,\n  ...doersGetMoreDoneStickers,\n  ...weeklyEntertainmentStickers,\n  ...fashionOnTheGoStickers,\n  ...noDaysOffStickers,\n  ...experienceThailandStickers,\n  ...wellbeingSleepStickers,\n  ...guideTobakingBreadStickers,\n  ...sangriaArtichokeStickers,\n  ...crispyChickenThighStickers,\n  ...almondosFilmsStickers,\n  ...bestPizzaInNYCStickers,\n  ...twelveHoursInBarcelonaStickers,\n  ...bestFitnessAppsStickers,\n  ...streetStyleOnTheGoStickers,\n  ...plantBasedDyesStickers,\n  ...indoorGardenOasisStickers,\n  ...killBellyFatStickers,\n  ...crownSeasonsRecappedStickers,\n  ...honeymooningInItalyStickers,\n  ...stayAtAceHotelKyotoStickers,\n  ...videoCallsSavedTheDayStickers,\n  ...pickTheRightLaptopStickers,\n  ...quizForYourBestSkinStickers,\n  ...atHomeOfficeStickers,\n  ...rockMusicFestivalStickers,\n  ...losAngelesCityGuideStickers,\n  ...hawaiiTravelPackingListStickers,\n  ...howContactTracingWorksStickers,\n  ...summerFashionCollectionStickers,\n  ...artOnTheInternetStickers,\n  ...newYorkPartyRoundUpStickers,\n  ...aDayInTheLifeStickers,\n  ...elegantTravelItineraryStickers,\n  ...modernistTravelGuideStickers,\n  ...magazineArticleStickers,\n  ...fashionInspirationStickers,\n  ...skinCareAtHomeStickers,\n  ...artBooksGiftGuideStickers,\n  ...vintageChairsWhatToLookForStickers,\n  ...celebrityLifeStoryStickers,\n  ...summerAdventureGuideStickers,\n  ...oneDayCityItineraryStickers,\n  ...technologyAdviceStickers,\n  ...allAboutCarsStickers,\n  ...sustainabilityTipsStickers,\n  ...anArtistsLegacyStickers,\n  ...tipsForThrowingAnOutdoorLuauStickers,\n};\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/curvedScissor.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Curved Scissors', 'sticker name', 'web-stories');\n\nfunction CurvedScissor({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 26 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M16.9717 33.125C16.2578 33.4375 15.9901 34.1407 16.0794 35.3125C16.5255 38.2813 16.5255 40.9375 16.0794 44.7656C15.9009 46.0938 16.704 46.7188 17.507 46.875C17.6855 46.875 17.864 46.9531 18.0424 46.9531C19.2024 46.9531 20.5409 46.25 21.1655 44.9219C23.1286 40.625 22.504 36.4844 19.5593 33.9063C18.5778 33.125 17.5963 32.8125 16.9717 33.125ZM20.0947 44.6094C19.5594 45.7031 18.3994 46.25 17.6855 46.0938C16.9717 45.9375 16.9717 45.2344 17.0609 44.8438C17.507 40.8594 17.507 38.2032 17.0609 35.1563C16.9717 34.2969 17.1501 33.9063 17.3286 33.8282C17.5963 33.75 18.1317 33.9063 18.7563 34.4532C21.4332 36.7969 21.9686 40.625 20.0947 44.6094Z\"\n        fill=\"#235524\"\n      />\n      <path\n        d=\"M24.0209 35.2344C22.6824 32.5781 20.184 30.625 16.7932 29.5312L15.9901 27.7344C22.8609 21.4844 27.144 9.29688 22.5932 0.703125C22.504 0.546875 22.3255 0.46875 22.147 0.46875C21.9686 0.46875 21.7901 0.625 21.7009 0.78125L12.4209 25.625C12.3317 25.7031 12.2424 25.7031 12.1532 25.7812C11.707 26.0156 11.4394 26.3281 11.2609 26.7188C5.37166 20.5469 2.07012 9.53125 6.08551 1.64062L12.2424 21.7969C12.3317 22.0312 12.5994 22.1875 12.867 22.1094C13.1347 22.0312 13.3132 21.7969 13.224 21.5625L6.62089 0.3125C6.62089 0.15625 6.44243 0 6.26397 0C6.08551 0 5.90705 0.078125 5.72858 0.234375C0.731662 8.59375 4.21166 21.0156 10.7255 27.5781C10.4578 28.125 10.1009 28.75 9.8332 29.375C6.3532 30.3125 3.76551 32.1875 2.24859 34.7656C0.46397 37.8125 0.285509 41.7187 1.7132 45.5469C2.69474 48.2031 5.72858 49.7656 8.22705 49.7656C8.58397 49.7656 8.85166 49.7656 9.20858 49.6875C11.2609 49.375 12.4209 47.9688 12.3317 45.9375C12.1532 42.5 12.1532 38.5156 13.1347 34.5312C13.9378 38.6719 13.6701 42.5781 13.224 45.9375C12.9563 47.9688 14.027 49.4531 16.0794 49.8437C16.4363 49.9219 16.8824 50 17.3286 50C19.827 50 22.6824 48.6719 23.8424 46.0938C25.627 42.2656 25.7163 38.2812 24.0209 35.2344ZM22.2363 2.03125C25.7163 10.0781 21.8794 20.8594 15.7224 26.7188C15.7224 26.6406 15.6332 26.6406 15.6332 26.5625C15.6332 26.4844 15.544 26.4844 15.544 26.4062C15.4547 26.3281 15.4547 26.25 15.3655 26.1719L15.2763 26.0938C15.187 26.0156 15.0978 25.9375 15.0086 25.8594C14.9194 25.7812 14.7409 25.7031 14.5624 25.625H14.4732C14.2055 25.5469 13.9378 25.4687 13.5809 25.4687L22.2363 2.03125ZM11.3501 45.8594C11.4394 48.0469 9.92243 48.5938 9.03012 48.75C6.71012 49.1406 3.58705 47.8125 2.60551 45.2344C1.26705 41.6406 1.35628 37.9688 3.05166 35.1562C4.47935 32.7344 6.97782 31.0156 10.2794 30.1562C10.4578 30.1562 10.547 30 10.547 29.9219C10.9932 28.9844 11.5286 28.0469 11.9747 27.1094C12.1532 26.7969 12.4209 26.5625 12.867 26.4062C13.0455 26.3281 13.224 26.3281 13.4024 26.3281C13.5809 26.3281 13.8486 26.4062 14.027 26.4844C14.1163 26.5625 14.2947 26.5625 14.384 26.6406C14.384 26.6406 14.384 26.6406 14.4732 26.7188C14.6517 26.875 14.8301 27.1094 14.9194 27.3438C14.9194 27.4219 15.0086 27.5781 15.0086 27.6562C15.0086 27.6562 15.0086 27.6562 15.0086 27.7344C15.0086 27.8125 15.0086 27.8906 15.0086 27.9687V28.0469C15.0086 28.125 14.9194 28.2031 14.9194 28.2813L13.224 31.4844C13.1347 31.7969 12.9563 32.1875 12.867 32.5C12.867 32.5 12.867 32.5 12.867 32.5781C11.1717 37.1875 11.1717 41.875 11.3501 45.8594ZM23.0394 45.7031C21.8794 48.2812 18.667 49.4531 16.4363 48.9062C15.544 48.6719 14.027 48.0469 14.2947 45.8594C14.7409 41.9531 15.0978 37.3438 13.7594 32.5C13.8486 32.1875 13.9378 31.9531 14.027 31.6406L15.4547 28.8281L15.9901 29.9219C16.0794 30 16.1686 30.1562 16.2578 30.1562C19.4701 31.1719 21.8794 33.0469 23.2178 35.4688C24.7347 38.4375 24.6455 42.1094 23.0394 45.7031Z\"\n        fill=\"#235524\"\n      />\n      <path\n        d=\"M9.47629 32.8907C8.76245 32.5782 7.87014 32.8126 6.8886 33.5938C3.76552 36.0938 2.96245 40.1563 4.65783 44.5313C5.19322 45.9376 6.62091 46.7188 7.78091 46.7188C7.87014 46.7188 8.0486 46.7188 8.13783 46.7188C9.11937 46.5626 9.74399 45.7813 9.65475 44.6876C9.47629 41.4063 9.47629 38.5157 10.1901 35.2344C10.3686 33.9844 10.1009 33.2032 9.47629 32.8907ZM9.2086 35.0001C8.49475 38.3594 8.40552 41.3282 8.67322 44.6876C8.67322 45.0782 8.67322 45.7813 7.95937 45.8594C7.15629 46.0157 5.99629 45.3907 5.55014 44.2188C4.03322 40.1563 4.74706 36.4063 7.51322 34.1407C8.0486 33.8282 8.49476 33.5938 8.85168 33.5938C8.94091 33.5938 9.03014 33.5938 9.03014 33.5938C9.2086 33.7501 9.38706 34.1407 9.2086 35.0001Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 26 / 50,\n  svg: CurvedScissor,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/floral.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Floral', 'sticker name', 'web-stories');\n\nfunction Floral({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 46 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M7.18499 49.7447C7.10993 49.3876 7.10274 49.1657 7.15837 48.9236L7.21289 48.6865L7.37122 48.5167C7.4583 48.4234 7.56562 48.3202 7.60973 48.2874C7.65383 48.2546 7.71125 48.2029 7.73733 48.1725C7.76341 48.1421 7.84734 48.0842 7.92384 48.0439L8.06293 47.9707L8.11287 47.8381C8.14034 47.7651 8.19095 47.6507 8.22534 47.5839C8.25973 47.517 8.30137 47.4238 8.31787 47.3768C8.37646 47.2097 8.53525 46.9165 8.65909 46.7465C8.67057 46.7308 8.68634 46.6881 8.69413 46.6517C8.70192 46.6153 8.71887 46.582 8.73179 46.5777C8.74472 46.5734 8.75561 46.553 8.756 46.5324C8.75674 46.4933 8.83179 46.3391 8.92577 46.1834C9.00241 46.0565 9.07609 45.847 9.03988 45.859C9.02332 45.8645 9.00833 45.8796 9.00656 45.8925C8.99391 45.9853 8.62578 46.5135 8.56612 46.5244C8.38732 46.557 8.33443 46.1634 8.46852 45.7981C8.48561 45.7516 8.50621 45.6906 8.5143 45.6626C8.56337 45.4929 8.84781 45.1062 8.97095 45.0418C9.02112 45.0155 9.03788 44.9912 9.05396 44.9214C9.06503 44.8733 9.09095 44.7982 9.11154 44.7546C9.13213 44.7109 9.16744 44.6338 9.19001 44.5831C9.21258 44.5324 9.25185 44.4595 9.27728 44.421C9.39564 44.2417 9.45563 44.1365 9.46488 44.092C9.47042 44.0654 9.54628 43.9154 9.63344 43.7587C9.87743 43.3203 9.95358 43.1744 9.98045 43.094C9.99403 43.0533 10.0997 42.8713 10.2152 42.6896C10.4591 42.3057 10.5163 42.2102 10.6441 41.9731C10.6958 41.8772 10.8059 41.6917 10.8887 41.5609C10.9715 41.4302 11.0658 41.2812 11.0981 41.23C11.1305 41.1788 11.1939 41.0682 11.2391 40.9843C11.2842 40.9003 11.407 40.7183 11.5118 40.5798C11.6167 40.4413 11.7582 40.2464 11.8263 40.1468C11.8944 40.0471 11.9636 39.9484 11.9801 39.9274C12.072 39.8105 12.4317 39.2922 12.4304 39.2787C12.4179 39.1499 12.1631 39.4333 11.1489 40.7044C11.1115 40.7513 10.9674 40.9155 10.8288 41.0692C10.6902 41.2229 10.5731 41.3672 10.5685 41.3901C10.5639 41.4129 10.4437 41.583 10.3014 41.7681C10.1592 41.9533 10.0251 42.1425 10.0035 42.1887C9.9819 42.2348 9.8722 42.3922 9.75972 42.5384C9.64723 42.6845 9.53145 42.8483 9.50241 42.9023C9.43105 43.035 9.4347 43.0298 9.22132 43.2999C8.96896 43.6193 8.86849 43.7703 8.69506 44.0911C8.61458 44.2399 8.5347 44.3724 8.51755 44.3854C8.50039 44.3984 8.47816 44.4437 8.46814 44.4861C8.45812 44.5285 8.38034 44.6623 8.29531 44.7834C8.10441 45.0554 8.09709 45.0734 8.15342 45.1323C8.22151 45.2036 8.18537 45.4161 8.08025 45.5624C8.03533 45.625 7.9514 45.7655 7.89372 45.8746C7.70863 46.2248 7.57843 46.4213 7.53521 46.4156C7.4455 46.4037 7.42931 46.3584 7.48886 46.2861C7.52071 46.2475 7.54814 46.1957 7.54987 46.1711C7.55227 46.1371 7.54212 46.144 7.50746 46.1998C7.42723 46.3291 7.29659 46.3195 7.27078 46.1825C7.23896 46.0136 7.24055 45.9852 7.29072 45.828C7.39613 45.4976 7.68644 45.0987 7.89101 45.0031C8.02427 44.9409 8.10049 44.8469 8.28093 44.5224C8.45301 44.2129 8.58689 43.9994 8.69393 43.8636C8.75191 43.7901 8.77262 43.7475 8.75682 43.7344C8.74029 43.7207 8.76631 43.6741 8.84404 43.5781C9.03813 43.3385 9.25048 43.0585 9.28076 43.0021C9.39504 42.7895 9.47882 42.6644 9.63352 42.4752C9.73082 42.3562 9.83313 42.2138 9.86086 42.1588C9.88861 42.1037 10.0345 41.9055 10.1851 41.7182C10.3357 41.5309 10.4778 41.3436 10.5007 41.3019C10.5398 41.2312 10.8727 40.8137 11.7193 39.774C12.0539 39.363 12.0661 39.3452 11.9603 39.422C11.8846 39.4769 11.8233 39.5427 11.7696 39.6265C11.726 39.6944 11.6507 39.7951 11.6022 39.8503C11.5537 39.9055 11.4133 40.0687 11.2902 40.213C11.1429 40.3856 11.0495 40.4795 11.0173 40.4874C10.9791 40.4969 10.9478 40.534 10.8759 40.655C10.8243 40.7418 10.7056 40.8958 10.6072 41.0035C10.4256 41.2022 9.60927 42.1917 9.4138 42.4501C9.18362 42.7543 8.99154 43.0321 8.98235 43.0741C8.96917 43.1343 8.90205 43.2357 8.68356 43.5254C8.58053 43.662 8.48621 43.8037 8.47397 43.8403C8.46173 43.8769 8.39946 43.9771 8.3356 44.0629C8.20512 44.2382 8.11746 44.3652 7.96148 44.605C7.8821 44.727 7.82206 44.7951 7.72877 44.8692C7.65961 44.9241 7.60273 44.9829 7.60235 45C7.60197 45.017 7.57436 45.0651 7.54098 45.1068C7.5076 45.1485 7.44128 45.2922 7.3936 45.4261C7.30961 45.662 7.27649 45.7344 7.13736 45.9863C7.03599 46.1698 6.99568 46.2254 6.9507 46.2435C6.92793 46.2526 6.87666 46.2956 6.83676 46.339C6.63727 46.5559 6.35484 46.4185 6.41735 46.135C6.46218 45.9317 6.82969 45.4763 7.05256 45.348C7.1713 45.2796 7.24793 45.2103 7.46495 44.9749C7.72079 44.6975 7.77293 44.6323 7.88682 44.4474C7.91511 44.4015 7.99694 44.2849 8.06866 44.1883C8.14037 44.0917 8.24908 43.9335 8.31021 43.8367C8.37135 43.74 8.51089 43.5294 8.62031 43.3686C8.72973 43.2079 8.8737 42.9938 8.94021 42.8928C9.22373 42.4627 9.4824 42.1146 9.70229 41.8674C9.83155 41.7221 9.98986 41.527 10.0541 41.4339C10.1183 41.3408 10.2234 41.2159 10.2875 41.1563C10.3516 41.0968 10.7184 40.6773 11.1025 40.224C11.4866 39.7708 11.8159 39.3912 11.8343 39.3805C11.9584 39.3081 12.1602 39.0374 12.0669 39.0683C12.0122 39.0864 11.9645 39.0187 12.0008 38.9745C12.0209 38.9499 12.0223 38.9361 12.0042 38.9416C11.8928 38.9751 11.5572 38.6054 11.5757 38.4696C11.5777 38.455 11.5651 38.4311 11.5476 38.4164C11.4647 38.3468 11.3921 37.496 11.4542 37.3217C11.4806 37.2476 11.4328 37.2441 11.371 37.3157C11.1303 37.5947 10.9871 37.7199 10.626 37.9669C10.5171 38.0414 10.4104 38.1231 10.3889 38.1486C10.3673 38.1741 10.3361 38.1979 10.3196 38.2015C10.2944 38.207 10.2249 38.2543 10.1316 38.3294C10.121 38.3379 10.0386 38.3901 9.94843 38.4454C9.8583 38.5007 9.75034 38.5743 9.70854 38.609C9.66673 38.6437 9.58661 38.6955 9.5305 38.7241C9.47439 38.7527 9.41555 38.7916 9.39976 38.8107C9.38396 38.8297 9.34171 38.8609 9.30588 38.88C9.20052 38.9361 8.82419 39.1588 8.74429 39.2123C8.7038 39.2394 8.58047 39.3024 8.47022 39.3523C8.35997 39.4023 8.25903 39.456 8.24591 39.4718C8.23279 39.4876 8.20926 39.4987 8.19362 39.4965C8.17799 39.4942 8.14518 39.5165 8.12071 39.5459C8.09623 39.5754 8.05303 39.6016 8.02469 39.6041C7.99635 39.6066 7.9636 39.6201 7.9519 39.6342C7.94021 39.6483 7.91652 39.6616 7.89927 39.6637C7.88201 39.6659 7.77376 39.7193 7.65871 39.7824C7.31029 39.9736 7.19388 40.0079 7.01116 39.9732C6.89448 39.951 6.89106 39.8274 7.00585 39.7812C7.03805 39.7682 7.06425 39.7538 7.06408 39.749C7.06391 39.7443 7.12699 39.6902 7.20425 39.6288C7.2815 39.5674 7.47127 39.4164 7.62597 39.2932C7.87273 39.0968 8.12536 38.8452 8.43796 38.4847C8.52916 38.3795 8.86342 37.8148 8.93252 37.6491C8.94866 37.6105 8.9947 37.528 9.03484 37.4659C9.07498 37.4038 9.11155 37.3344 9.1161 37.3117C9.12066 37.2891 9.1446 37.2628 9.1693 37.2534C9.20078 37.2414 9.20748 37.2307 9.1917 37.2176C9.17503 37.2037 9.21252 37.1522 9.33594 37.0194L9.5027 36.8398L9.40596 36.8544C9.35275 36.8624 9.25588 36.8789 9.1907 36.8911C9.00221 36.9264 8.90529 36.9354 8.82205 36.9257C8.77936 36.9206 8.73195 36.9316 8.71668 36.95C8.68182 36.9919 8.4222 37.0397 8.40114 37.0081C8.39256 36.9951 8.3866 36.9955 8.3879 37.009C8.39175 37.0486 8.26172 37.0908 8.18493 37.0748C8.14583 37.0666 8.07045 37.0745 8.01742 37.0923C7.96439 37.1101 7.86767 37.128 7.80248 37.1321C7.7373 37.1361 7.67777 37.1469 7.67021 37.156C7.6497 37.1807 7.48122 37.1847 7.47887 37.1605C7.47776 37.1491 7.46522 37.1537 7.451 37.1708C7.43679 37.1879 7.39507 37.2046 7.35829 37.2078C7.32151 37.2111 7.25624 37.2285 7.21324 37.2465C7.17024 37.2645 7.10632 37.2714 7.0712 37.2617C7.03608 37.252 6.95705 37.2661 6.89558 37.2929C6.8341 37.3198 6.76831 37.3346 6.74937 37.3258C6.73043 37.3169 6.66919 37.3313 6.61329 37.3577C6.55738 37.3841 6.47648 37.4119 6.43351 37.4196C6.30386 37.4428 6.09051 37.5059 6.07393 37.5258C6.06538 37.5361 6.04969 37.5421 6.03908 37.539C6.00643 37.5297 5.66619 37.5952 5.65077 37.6137C5.64279 37.6233 5.60703 37.6323 5.57129 37.6337C5.53556 37.6351 5.50493 37.6463 5.50324 37.6588C5.50155 37.6712 5.48786 37.6796 5.47281 37.6774C5.45777 37.6752 5.34865 37.7169 5.23032 37.7701C5.112 37.8232 4.99481 37.8685 4.9699 37.8708C4.945 37.873 4.90803 37.8949 4.88774 37.9193C4.86745 37.9437 4.83151 37.96 4.80786 37.9556C4.74082 37.9429 4.56486 38.1164 4.49722 38.2618C4.42866 38.4092 4.28972 38.5034 4.24868 38.4303C4.23628 38.4082 4.20484 38.3641 4.17881 38.3322C4.10615 38.2432 4.05847 38.0746 4.09387 38.032C4.11082 38.0115 4.11673 37.9882 4.10701 37.9802C4.09728 37.9721 4.1173 37.9213 4.15149 37.8672C4.18569 37.8132 4.23407 37.7259 4.25901 37.6731C4.29176 37.6039 4.34371 37.5419 4.44613 37.4499C4.52412 37.3799 4.62134 37.2899 4.66218 37.2499C4.70302 37.21 4.75015 37.1728 4.7669 37.1672C4.78366 37.1616 4.85878 37.0968 4.93385 37.023C5.00891 36.9493 5.13582 36.8471 5.21587 36.7959C5.29592 36.7448 5.42787 36.6587 5.50909 36.6047C5.5903 36.5506 5.67722 36.495 5.70224 36.4811C5.79336 36.4304 6.09038 36.2327 6.15565 36.1793C6.19251 36.1492 6.24462 36.1144 6.27145 36.1019C6.29829 36.0895 6.39267 36.033 6.48119 35.9764C6.58437 35.9104 6.6492 35.8827 6.66183 35.8994C6.67746 35.9201 6.68154 35.9158 6.68134 35.879C6.68124 35.8531 6.69255 35.8342 6.70686 35.8363C6.721 35.8383 6.82096 35.7887 6.92899 35.7261C7.03702 35.6634 7.14547 35.6042 7.16998 35.5946C7.19449 35.5849 7.29116 35.5303 7.3848 35.4732C7.47844 35.4162 7.57722 35.3659 7.60431 35.3614C7.63141 35.357 7.762 35.3022 7.89453 35.2396C8.25755 35.0682 8.57579 34.9357 8.68485 34.9107C8.78677 34.8873 8.86514 34.8593 9.07606 34.7711C9.19939 34.7195 9.24563 34.7012 9.3397 34.6666C9.36506 34.6573 9.40171 34.6416 9.42115 34.6317C9.44059 34.6218 9.49583 34.6038 9.54391 34.5917C9.59198 34.5796 9.70181 34.543 9.78795 34.5104C9.8741 34.4778 10.0065 34.4344 10.0822 34.4139C10.1579 34.3934 10.2431 34.3648 10.2716 34.3503C10.3 34.3358 10.3675 34.3098 10.4215 34.2926C10.6947 34.2054 10.8894 34.145 11.1341 34.0716C11.2823 34.0271 11.446 33.9727 11.4979 33.9506C11.5497 33.9285 11.6001 33.9171 11.6098 33.9251C11.6195 33.9332 11.6794 33.9212 11.743 33.8984C11.8066 33.8757 11.888 33.8559 11.924 33.8546C11.96 33.8532 11.9973 33.8426 12.0069 33.8311C12.0165 33.8196 12.0506 33.8087 12.0827 33.8069C12.1148 33.8051 12.2306 33.7821 12.34 33.7558C12.4494 33.7294 12.5872 33.7042 12.6461 33.6997C12.705 33.6952 12.8035 33.6694 12.865 33.6423C12.97 33.5961 13.2416 33.5203 13.5475 33.4519C13.6215 33.4353 13.7163 33.4075 13.7579 33.39C13.846 33.3532 13.9344 33.3225 13.9589 33.3203C13.9684 33.3195 14.0268 33.29 14.0888 33.2547C14.1508 33.2194 14.2567 33.159 14.3242 33.1205C14.4181 33.067 14.452 33.0354 14.4688 32.9863C14.4843 32.9411 14.5185 32.9035 14.5843 32.8596C14.6357 32.8253 14.7352 32.7456 14.8054 32.6824C14.8756 32.6192 14.9701 32.5344 15.0153 32.4939C15.3152 32.2252 15.8249 31.5434 16.0484 31.1117C16.1396 30.9358 16.2383 30.7551 16.2678 30.7102C16.3638 30.5646 16.634 30.1362 16.7184 29.9959C16.7636 29.9206 16.8558 29.7842 16.9231 29.6926C16.9905 29.6011 17.0829 29.472 17.1286 29.4058C17.3083 29.1451 17.4801 28.9318 17.5855 28.8387C17.6462 28.785 17.7523 28.6814 17.8213 28.6086C17.8902 28.5357 18.0158 28.4057 18.1003 28.3197C18.5406 27.8716 18.7592 27.5199 18.6104 27.4991C18.493 27.4827 18.3528 27.1649 18.3727 26.9601C18.3785 26.9001 18.3797 26.7455 18.3754 26.6166C18.3618 26.2121 18.3777 25.9216 18.4234 25.7406C18.4351 25.6939 18.4383 25.6504 18.4304 25.6439C18.4226 25.6374 18.426 25.5869 18.438 25.5318C18.45 25.4767 18.4757 25.2603 18.4951 25.0508C18.5145 24.8413 18.5398 24.5921 18.5512 24.4969C18.5627 24.4017 18.5677 24.3012 18.5624 24.2736C18.5571 24.246 18.5591 24.2157 18.5669 24.2064C18.5747 24.197 18.5892 24.0847 18.5991 23.9568C18.6091 23.8288 18.622 23.7184 18.6279 23.7113C18.6656 23.6659 18.6264 23.5874 18.5726 23.6007C18.5084 23.6166 18.491 23.6329 18.5024 23.6666C18.516 23.7065 18.2897 23.9244 18.1857 23.9716C18.1324 23.9957 18.0771 24.0296 18.0626 24.047C18.0482 24.0643 18.015 24.0784 17.9889 24.0783C17.9627 24.0782 17.9286 24.0935 17.913 24.1122C17.8974 24.131 17.8683 24.1441 17.8483 24.1414C17.8283 24.1387 17.7825 24.1511 17.7465 24.1689C17.7106 24.1868 17.6725 24.1942 17.6619 24.1854C17.6513 24.1766 17.6267 24.1887 17.6071 24.2122C17.5503 24.2806 17.1865 24.2945 16.9411 24.2377C16.8178 24.2092 16.809 24.2113 16.7755 24.2763C16.7561 24.3141 16.7215 24.3734 16.6987 24.408C16.6318 24.5097 16.5161 24.7157 16.513 24.7387C16.5114 24.7503 16.4083 24.9023 16.2838 25.0764C16.0308 25.4303 16.0109 25.4606 15.9953 25.5147C15.9892 25.5357 15.9607 25.5972 15.9318 25.6513C15.903 25.7055 15.8668 25.7748 15.8514 25.8054C15.836 25.836 15.7942 25.9149 15.7585 25.9807C15.7229 26.0465 15.6771 26.1363 15.6568 26.1802C15.6366 26.2241 15.5963 26.2971 15.5673 26.3425C15.4427 26.5371 15.315 26.7784 15.2599 26.9233C15.2274 27.0091 15.1679 27.1264 15.1279 27.1842C15.0879 27.2419 15.0436 27.3258 15.0295 27.3707C15.0155 27.4155 14.9654 27.5195 14.9182 27.6018C14.871 27.6841 14.8268 27.7681 14.82 27.7885C14.8132 27.8089 14.7902 27.8537 14.7689 27.888C14.7476 27.9223 14.6857 28.037 14.6315 28.1429C14.5772 28.2487 14.5169 28.3441 14.4975 28.355C14.478 28.3658 14.4563 28.3947 14.4492 28.4192C14.4317 28.4801 14.4107 28.5228 14.3694 28.5817C14.3502 28.6091 14.3375 28.6429 14.3412 28.6569C14.3488 28.6857 14.1056 29.1531 14.0416 29.2327C14.0184 29.2614 13.9954 29.3062 13.9904 29.3322C13.9798 29.3874 13.8988 29.5815 13.8439 29.6836C13.8228 29.7227 13.7969 29.7925 13.7862 29.8387C13.7756 29.8849 13.7351 29.9683 13.6962 30.0239C13.6574 30.0796 13.6124 30.1737 13.5962 30.2331C13.58 30.2925 13.5417 30.3814 13.5111 30.4306C13.4113 30.5907 13.403 30.616 13.4124 30.7304C13.4247 30.8814 13.4211 31.0532 13.4051 31.0733C13.398 31.0823 13.3912 31.1432 13.3899 31.2088C13.3846 31.4899 13.1139 31.8117 12.8711 31.8254C12.6021 31.8407 12.5881 31.675 12.814 31.1491C12.9404 30.8547 13.0404 30.7077 13.2639 30.4874C13.304 30.4479 13.4814 30.0879 13.557 29.8927C13.5853 29.8197 13.6942 29.5765 13.799 29.3523C13.9039 29.1281 14.0058 28.9083 14.0255 28.864C14.074 28.7551 14.2134 28.5035 14.2949 28.3778C14.3871 28.2357 14.5026 28.0105 14.552 27.8765C14.6029 27.7387 14.6699 27.6116 14.857 27.2986C14.9055 27.2174 14.9836 27.0806 15.0307 26.9945C15.0777 26.9085 15.1242 26.8374 15.134 26.8366C15.1438 26.8357 15.1517 26.8169 15.1517 26.7947C15.1516 26.7375 15.3116 26.4433 15.4679 26.2134C15.6026 26.0154 15.6398 25.9495 15.7774 25.6651C15.8679 25.4783 15.9331 25.3684 16.1727 24.9995C16.2715 24.8473 16.3691 24.687 16.3896 24.6432C16.4101 24.5995 16.4702 24.4933 16.5232 24.4072C16.7465 24.0447 16.7382 24.0696 16.6605 23.9914C16.6224 23.953 16.5882 23.9063 16.5846 23.8877C16.5739 23.8329 16.5455 23.8508 16.4904 23.9471C16.462 23.9967 16.3654 24.1468 16.2758 24.2806C16.1862 24.4144 16.0485 24.6266 15.9698 24.7522C15.7149 25.1589 15.5071 25.4683 15.4776 25.4847C15.4617 25.4935 15.448 25.5379 15.4469 25.5833C15.4456 25.6423 15.4226 25.6931 15.3661 25.7616C15.3227 25.8143 15.2333 25.9475 15.1674 26.0577C15.1015 26.1678 14.997 26.3295 14.9353 26.417C14.8735 26.5046 14.8219 26.5834 14.8206 26.5923C14.8193 26.6012 14.7656 26.6915 14.7012 26.7929C14.6368 26.8943 14.5635 27.0099 14.5383 27.0497C14.5131 27.0895 14.456 27.1841 14.4114 27.2599C14.3669 27.3356 14.2415 27.5368 14.1328 27.7068C13.8421 28.1616 13.6286 28.5402 13.62 28.6161C13.6141 28.6683 13.6027 28.6847 13.5678 28.691C13.5339 28.6972 13.5013 28.7357 13.4317 28.8519C13.187 29.2601 13.0753 29.4366 12.9695 29.5821C12.9062 29.6693 12.8484 29.7562 12.8411 29.7752C12.8337 29.7941 12.7902 29.8636 12.7443 29.9296C12.5961 30.1426 12.5012 30.2953 12.505 30.3146C12.5332 30.4583 12.3343 31.0547 12.2083 31.204C12.1188 31.3101 12.0652 31.4032 12.0423 31.4921C11.9848 31.7153 11.5854 31.9086 11.499 31.7551C11.4092 31.5953 11.6271 31.0496 11.9165 30.7094C12.1587 30.4248 12.2177 30.3616 12.2382 30.3645C12.2591 30.3675 12.363 30.2173 12.4268 30.0919C12.5177 29.9132 12.7503 29.5161 12.8558 29.3597C12.9233 29.2595 13.0865 29.0118 13.2186 28.8091C13.3507 28.6064 13.5414 28.3318 13.6424 28.1988C13.8539 27.9205 14.1102 27.5218 14.5086 26.8515C14.5777 26.7353 14.6578 26.6032 14.6868 26.5578C14.7157 26.5124 14.7762 26.4064 14.8212 26.3223C14.8662 26.2382 14.9502 26.1022 15.008 26.02C15.0658 25.9378 15.1266 25.8393 15.1432 25.801C15.1599 25.7628 15.2104 25.6769 15.2555 25.6103C15.4777 25.282 15.7265 24.8926 15.8548 24.6725C15.9332 24.538 16.0309 24.3777 16.0719 24.3163C16.3827 23.8507 16.402 23.7978 16.2861 23.7307L16.1907 23.6754L15.914 24.0126C15.6927 24.2822 15.5989 24.4159 15.4459 24.6799C15.3407 24.8615 15.2256 25.0531 15.1902 25.1057C15.1548 25.1583 15.1239 25.2152 15.1216 25.232C15.1193 25.2489 15.0075 25.4013 14.8732 25.5707C14.3823 26.1895 14.151 26.4992 14.005 26.733C13.9229 26.8644 13.797 27.0485 13.7253 27.1423C13.6535 27.236 13.5957 27.3216 13.5968 27.3326C13.5978 27.3437 13.5528 27.408 13.4966 27.4756C13.4405 27.5432 13.3011 27.7457 13.1869 27.9256C13.0727 28.1055 12.9675 28.2565 12.9531 28.2613C12.9387 28.2661 12.927 28.2887 12.9271 28.3115C12.9274 28.3827 12.2689 29.4402 11.8704 30.0084C11.6936 30.2605 11.5055 30.5621 11.2814 30.9527C11.201 31.0929 11.1098 31.2302 11.0787 31.2577C11.0477 31.2852 11.0174 31.3313 11.0114 31.3602C10.9875 31.4742 10.777 31.8192 10.6119 32.0148C10.5191 32.1249 10.4371 32.2355 10.4297 32.2607C10.4223 32.2859 10.3803 32.3394 10.3363 32.3796C10.2693 32.4408 10.2596 32.4607 10.2764 32.5017C10.2875 32.5286 10.2882 32.5685 10.2779 32.5904C10.1366 32.8917 10.0249 33.1922 10.0096 33.3126C9.99914 33.3942 9.9821 33.4712 9.9717 33.4837C9.9613 33.4962 9.95402 33.5326 9.95552 33.5645C9.95722 33.6007 9.92615 33.6646 9.87271 33.7348C9.82566 33.7966 9.7753 33.8728 9.76078 33.9041C9.65614 34.13 9.43007 34.3304 9.26133 34.3468C9.22899 34.3499 9.18078 34.3564 9.15422 34.3612C8.89785 34.4076 8.94958 33.6081 9.22989 33.1916C9.4496 32.8652 9.70816 32.5996 9.8925 32.5108C10.0671 32.4267 10.1242 32.3705 10.2402 32.1682C10.3448 31.986 10.468 31.8083 10.6547 31.5703C10.7454 31.4547 10.8895 31.2407 10.9749 31.0948C11.0604 30.9488 11.1971 30.7287 11.2788 30.6057C11.3604 30.4826 11.4454 30.3544 11.4676 30.3208C11.4898 30.2872 11.5674 30.16 11.64 30.0381C11.7127 29.9162 11.8272 29.7344 11.8945 29.6341C11.9618 29.5339 12.0509 29.3948 12.0923 29.3252C12.1338 29.2555 12.2173 29.119 12.278 29.0218C12.4235 28.7886 12.7621 28.2148 12.8277 28.0901C12.8563 28.0358 12.9939 27.8093 13.1334 27.5868C13.2729 27.3642 13.4439 27.0875 13.5135 26.9717C13.583 26.8559 13.726 26.641 13.8313 26.4942C14.0341 26.2111 14.113 26.0992 14.2804 25.8575C14.3376 25.7749 14.4444 25.6293 14.5177 25.534C14.591 25.4387 14.6883 25.3065 14.7338 25.2402C14.7794 25.174 14.8719 25.0449 14.9392 24.9533C15.0066 24.8618 15.1098 24.7203 15.1685 24.6389C15.2273 24.5575 15.3272 24.4205 15.3907 24.3344C15.4542 24.2483 15.5255 24.1514 15.5493 24.119C15.5797 24.0777 15.5583 24.0879 15.4771 24.1537C15.4027 24.214 15.3491 24.2745 15.3263 24.3241C15.3068 24.3664 15.2399 24.4528 15.1775 24.5161C15.1151 24.5793 15.0491 24.647 15.0307 24.6665C15.0124 24.6859 14.8934 24.8394 14.7663 25.0075C14.6219 25.1986 14.5213 25.316 14.4979 25.3209C14.4396 25.333 14.356 25.4119 14.3728 25.4389C14.3826 25.4546 14.3428 25.5136 14.2598 25.6065C14.1893 25.6853 14.1116 25.7758 14.0871 25.8075C13.869 26.0896 13.6371 26.3612 13.5952 26.3836C13.5595 26.4027 13.5419 26.431 13.5368 26.4777C13.5309 26.5315 13.4817 26.6003 13.2847 26.8297C13.15 26.9865 13.0394 27.1286 13.0389 27.1456C13.0384 27.1625 12.9422 27.3027 12.8251 27.4571C12.7081 27.6115 12.5953 27.7662 12.5745 27.8011C12.5253 27.8837 12.3081 28.1812 12.0941 28.459C11.7472 28.9094 11.7055 28.9823 11.653 29.2288C11.6358 29.3101 11.6001 29.4153 11.5738 29.4628C11.5475 29.5102 11.5134 29.5958 11.498 29.6531C11.3885 30.0604 10.8458 30.4786 10.7994 30.1914C10.7898 30.1316 10.7761 30.0779 10.769 30.0719C10.6601 29.9816 11.1822 29.1839 11.4137 29.0869C11.482 29.0583 11.522 29.0161 11.6691 28.8176C11.7651 28.6881 11.8993 28.5078 11.9674 28.4169C12.0356 28.326 12.1319 28.1931 12.1816 28.1215C12.2312 28.05 12.3474 27.8908 12.4396 27.7679C12.5319 27.645 12.6287 27.5124 12.6547 27.4733C12.6807 27.4341 12.7777 27.3017 12.8701 27.1789C12.9626 27.0561 13.107 26.8637 13.1911 26.7513C13.5657 26.2503 15.1467 24.3237 15.6201 23.7913C15.9478 23.4228 15.9739 23.3801 15.8588 23.4012C15.8044 23.4111 15.7714 23.4452 15.3136 23.9648C15.1431 24.1583 14.9386 24.3789 14.8591 24.455C14.7052 24.6024 14.466 24.86 14.0869 25.2867C13.9583 25.4315 13.8344 25.57 13.8115 25.5944C13.7887 25.6189 13.6918 25.7371 13.596 25.8571C13.4293 26.0661 13.3466 26.1587 12.9729 26.5544C12.5384 27.0144 12.3474 27.226 12.2157 27.3927C11.8862 27.8102 11.6999 28.0277 11.6331 28.0729C11.594 28.0993 11.5603 28.1333 11.5583 28.1484C11.5539 28.1807 11.3155 28.4595 11.1995 28.5681C11.1553 28.6094 11.0272 28.7516 10.9149 28.8839L10.7108 29.1246L10.7361 29.3118C10.7633 29.5135 10.7512 29.5614 10.6061 29.8244C10.554 29.9189 10.5129 30.0119 10.5148 30.031C10.5192 30.0766 10.4437 30.1655 10.3401 30.2365C10.2604 30.2912 10.2341 30.316 10.0951 30.4673C9.83924 30.7459 9.61022 30.469 9.80781 30.12C9.84336 30.0573 9.91798 29.923 9.97365 29.8217C10.0819 29.6247 10.1874 29.4832 10.2932 29.393C10.3293 29.3622 10.698 28.9373 11.1127 28.4487C12.3514 26.9889 13.2919 25.923 13.8199 25.3805C13.862 25.3374 14.0344 25.1469 14.2031 24.9573C14.3718 24.7677 14.564 24.5652 14.63 24.5073C14.6961 24.4494 14.8017 24.3454 14.8647 24.2762C14.9276 24.207 15.0754 24.0458 15.193 23.9178C15.7703 23.2897 15.9845 22.9152 15.4743 23.4258C15.325 23.5753 15.2464 23.6433 15.2242 23.642C15.2115 23.6412 15.1604 23.6849 15.1107 23.7391C14.8849 23.9852 14.6501 24.2036 14.5552 24.2559C14.5363 24.2662 14.4857 24.3127 14.4426 24.3592C14.3995 24.4057 14.3316 24.464 14.2916 24.4889C14.2517 24.5137 14.1631 24.593 14.0948 24.6649C14.0266 24.7369 13.9236 24.8277 13.866 24.8667C13.8085 24.9057 13.7411 24.9633 13.7162 24.9947C13.6914 25.0262 13.6341 25.0779 13.5888 25.1098C13.5436 25.1416 13.4528 25.2224 13.3872 25.2893C13.3215 25.3563 13.195 25.4713 13.1061 25.545C13.0172 25.6187 12.8678 25.7486 12.7741 25.8338C12.6804 25.9189 12.5914 25.987 12.5764 25.9851C12.5614 25.9832 12.5085 26.0283 12.4589 26.0855C12.4093 26.1427 12.3436 26.2035 12.3129 26.2207C12.2823 26.238 12.204 26.312 12.1389 26.3853C12.0302 26.5079 11.9756 26.5526 11.8405 26.6298C11.8133 26.6454 11.6914 26.75 11.5696 26.8624C11.4478 26.9747 11.2731 27.1321 11.1814 27.2121C11.0193 27.3535 11.0151 27.3592 11.0315 27.4149C11.0408 27.4464 11.0399 27.4825 11.0294 27.4951C11.019 27.5077 11.0018 27.5555 10.9912 27.6015C10.9806 27.6474 10.9566 27.6971 10.938 27.712C10.9193 27.7269 10.9089 27.7595 10.9148 27.7845C10.9237 27.8224 10.9132 27.8371 10.8512 27.8737C10.8058 27.9005 10.7195 27.9921 10.6287 28.1098C10.5453 28.2181 10.4548 28.3154 10.4219 28.3325C10.3897 28.3491 10.35 28.3822 10.3338 28.4061C10.2494 28.5301 9.90742 28.694 9.84357 28.641C9.83338 28.6325 9.79906 28.6266 9.76729 28.6278C9.6962 28.6305 9.64843 28.5641 9.65807 28.4759C9.67439 28.3266 10.3663 27.5673 10.5489 27.4984C10.652 27.4594 10.8861 27.3196 10.8895 27.2949C10.8934 27.2658 11.0808 27.1039 11.2583 26.9763C11.3199 26.932 11.4498 26.8269 11.547 26.7428C11.6443 26.6587 11.7618 26.5576 11.8083 26.5181C11.8548 26.4786 12.037 26.3175 12.2132 26.1602C12.6759 25.7472 12.7641 25.6702 13.0373 25.4405C13.5341 25.0228 13.7376 24.8433 14.0505 24.5467C14.1188 24.4819 14.202 24.4139 14.2353 24.3954C14.2686 24.377 14.3454 24.313 14.4059 24.2532C14.4665 24.1934 14.5546 24.1126 14.6018 24.0737C14.8231 23.8913 15.5797 23.2038 15.643 23.1276C15.6482 23.1213 15.6438 23.1091 15.6333 23.1003C15.6228 23.0916 15.5959 23.1083 15.5735 23.1375C15.5512 23.1667 15.481 23.2326 15.4175 23.284C15.354 23.3354 15.2706 23.4081 15.2322 23.4456C15.1487 23.5271 14.8307 23.7615 14.7894 23.7721C14.7735 23.7761 14.7262 23.8079 14.6845 23.8427C14.4605 24.0293 14.1785 24.2551 14.0364 24.3614C13.954 24.4231 13.9199 24.436 13.9001 24.413C13.8856 24.3962 13.8613 24.3865 13.8461 24.3915C13.8303 24.3968 13.834 24.4059 13.8549 24.4131C13.9029 24.4295 13.8707 24.4868 13.7633 24.5763C13.7164 24.6155 13.6279 24.691 13.5665 24.7442C13.5052 24.7974 13.4046 24.8771 13.343 24.9214C13.1274 25.0761 12.9713 25.1976 12.8875 25.2759C12.841 25.3194 12.7907 25.3531 12.7757 25.351C12.7608 25.3488 12.7469 25.3584 12.745 25.3724C12.7431 25.3863 12.6507 25.4612 12.5396 25.5388C12.4286 25.6164 12.3165 25.6978 12.2907 25.7197C12.2649 25.7417 12.1825 25.801 12.1077 25.8517C12.0329 25.9024 11.8833 26.0124 11.7752 26.0962C11.6672 26.18 11.566 26.2503 11.5504 26.2525C11.5347 26.2546 11.5174 26.2697 11.512 26.286C11.5065 26.3023 11.4257 26.3648 11.3325 26.425C11.2392 26.4851 11.0973 26.5869 11.017 26.6513C10.8773 26.7633 10.7435 26.8468 10.6431 26.8847C10.6174 26.8944 10.5948 26.9135 10.593 26.9272C10.5911 26.9408 10.5605 26.9681 10.525 26.9878C10.4895 27.0075 10.4245 27.0677 10.3806 27.1216C10.3367 27.1756 10.2689 27.2329 10.23 27.249C10.1371 27.2876 10.1146 27.3176 10.104 27.4176C10.0961 27.492 10.0858 27.5067 10.0066 27.5576C9.95795 27.5888 9.829 27.6824 9.72007 27.7654C9.47636 27.9513 9.38888 27.9986 9.31697 27.9837C9.28631 27.9773 9.25158 27.988 9.23979 28.0075C9.20824 28.0596 9.05552 28.147 8.97961 28.1565C8.94334 28.161 8.90871 28.1706 8.90265 28.1779C8.86882 28.2186 8.68643 28.1452 8.65884 28.0797C8.61545 27.9767 8.83626 27.6723 8.93087 27.7047C8.94847 27.7107 9.03068 27.663 9.11356 27.5986C9.19644 27.5342 9.32572 27.4474 9.40084 27.4057C9.47597 27.364 9.55972 27.3149 9.58694 27.2967C9.61417 27.2785 9.68147 27.2508 9.7365 27.2351C9.79152 27.2194 9.8528 27.187 9.87267 27.1631C9.91779 27.1088 10.0967 27.0329 10.166 27.0387C10.1945 27.0411 10.2419 27.0275 10.2713 27.0085L10.3247 26.974L10.2463 26.9878C10.1351 27.0075 10.1834 26.9526 10.3743 26.8423C10.8328 26.5775 11.4549 26.1521 11.8957 25.8019C11.9971 25.7213 12.0939 25.6455 12.1108 25.6334C12.1276 25.6214 12.1972 25.5656 12.2655 25.5095C12.3337 25.4534 12.4035 25.4056 12.4206 25.4033C12.4377 25.401 12.4782 25.3672 12.5106 25.3281C12.5501 25.2805 12.578 25.2642 12.5953 25.2786C12.6129 25.2932 12.6876 25.2475 12.8303 25.1346C12.9454 25.0437 13.0626 24.9562 13.0907 24.9403C13.1189 24.9244 13.1904 24.8702 13.2497 24.8199C13.3468 24.7374 13.5983 24.5365 13.8351 24.3521C13.8837 24.3143 13.9696 24.2437 14.0262 24.1952C14.3795 23.8922 14.4659 23.8204 14.634 23.6903C14.7367 23.6108 14.9106 23.4712 15.0203 23.3801C15.13 23.289 15.2621 23.1811 15.3137 23.1402C15.4895 23.0013 15.5183 22.9499 15.4611 22.877C15.4335 22.8418 15.4037 22.7876 15.395 22.7565C15.3862 22.7254 15.366 22.6891 15.35 22.6759C15.3008 22.635 15.2676 22.2417 15.3022 22.109C15.3201 22.0407 15.3376 21.9417 15.3413 21.889C15.3462 21.8184 15.4804 21.4114 15.5131 21.3679C15.5336 21.3406 15.4643 21.3387 15.417 21.3652C15.3834 21.3841 15.2898 21.4307 15.209 21.4688C15.1282 21.507 15.0397 21.5525 15.0123 21.5699C14.9849 21.5874 14.8657 21.6445 14.7475 21.6968C14.6293 21.7491 14.5123 21.805 14.4876 21.8209C14.4628 21.8369 14.3988 21.8513 14.3453 21.8529C14.2918 21.8545 14.2346 21.872 14.2182 21.8917C14.2018 21.9115 14.1676 21.9294 14.1421 21.9317C14.1166 21.9339 14.061 21.9574 14.0186 21.9837C13.9418 22.0315 13.6047 22.1458 13.5089 22.1566C13.4813 22.1597 13.4044 22.1843 13.338 22.2113C13.2717 22.2383 13.1928 22.2626 13.1628 22.2653C13.1328 22.2679 13.1 22.2801 13.0898 22.2923C13.0797 22.3045 13.0314 22.3195 12.9825 22.3257C12.9336 22.3319 12.8833 22.3493 12.8708 22.3643C12.8583 22.3794 12.8061 22.3991 12.7549 22.4081C12.7037 22.4171 12.6574 22.4297 12.652 22.4361C12.6373 22.4539 11.9948 22.6038 11.8671 22.6193C11.8054 22.6268 11.741 22.6372 11.7239 22.6425C11.7068 22.6478 11.6357 22.6463 11.566 22.6393C11.4962 22.6322 11.4077 22.6396 11.3693 22.6557C11.2598 22.7016 10.5261 22.757 10.098 22.7518C10.0374 22.751 9.98024 22.754 9.97107 22.7585C9.96189 22.7629 9.91693 22.7517 9.87115 22.7335C9.69535 22.664 9.77229 22.5151 10.0068 22.4709C10.2794 22.4196 10.6771 22.2844 10.725 22.2268C10.7386 22.2104 10.7851 22.1821 10.8283 22.164C10.8714 22.1459 10.9725 22.085 11.0528 22.0287C11.1332 21.9723 11.2204 21.9157 11.2466 21.9028C11.2728 21.8898 11.384 21.791 11.4936 21.6831C11.6032 21.5753 11.7077 21.4843 11.7259 21.481C11.7441 21.4776 11.7932 21.4327 11.835 21.3811C11.9133 21.2844 12.3368 20.9061 12.4661 20.8173C12.5061 20.7898 12.6285 20.6928 12.7382 20.6016C13.0938 20.3058 13.4218 20.0567 13.6609 19.9008C13.8627 19.7692 14.1941 19.5296 14.2807 19.4526C14.2957 19.4393 14.3234 19.4234 14.3423 19.4172C14.3612 19.411 14.4647 19.3408 14.5723 19.2612C14.8225 19.0759 15.2205 18.8284 15.3337 18.7877C15.4745 18.7371 15.4826 18.7066 15.3609 18.6853C15.2143 18.6597 14.8501 18.6392 14.8363 18.6558C14.83 18.6634 14.7962 18.6547 14.761 18.6365C14.7259 18.6182 14.6195 18.6041 14.5245 18.605C14.2537 18.6077 14.0431 18.5932 14.0135 18.5698C13.9987 18.558 13.9173 18.5543 13.8327 18.5616C13.7481 18.5689 13.6686 18.5663 13.656 18.5558C13.6435 18.5454 13.6173 18.5421 13.598 18.5485C13.512 18.577 12.7023 18.521 12.657 18.4834C12.6479 18.4759 12.6321 18.4742 12.6219 18.4795C12.599 18.4914 12.2129 18.4617 12.1947 18.4466C12.1876 18.4407 12.1365 18.4337 12.0812 18.4312C12.0259 18.4287 11.9708 18.4184 11.9587 18.4083C11.9297 18.3843 11.8332 18.3666 11.7337 18.3671C11.6897 18.3674 11.5804 18.3524 11.4907 18.3339C11.4011 18.3154 11.306 18.3005 11.2794 18.3009C11.2176 18.3018 11.0129 18.2539 10.9872 18.2326C10.9764 18.2237 10.9385 18.2189 10.9029 18.2221C10.8672 18.2252 10.7785 18.2071 10.7055 18.1818C10.5787 18.1377 10.3307 18.0697 10.2424 18.0547C10.0496 18.0219 9.77552 17.9231 9.74423 17.8751C9.72902 17.8518 9.68944 17.8369 9.6472 17.8386C9.54216 17.8429 9.24739 17.7504 9.15072 17.6827C9.1341 17.6711 9.08169 17.6375 9.03422 17.6081C8.76798 17.443 9.33769 17.2852 9.88313 17.3729C10.0155 17.3942 10.1609 17.4102 10.2062 17.4083C10.2963 17.4047 10.6989 17.4721 10.863 17.5183C10.9647 17.5469 11.474 17.6778 11.5643 17.6986C11.5898 17.7044 11.6225 17.719 11.6369 17.731C11.6906 17.7756 12.0757 17.8649 12.2729 17.8784C12.3852 17.8861 12.4804 17.895 12.4843 17.8983C12.4927 17.9053 12.8563 17.9452 12.9175 17.9459C12.94 17.9462 13.0289 17.9478 13.115 17.9495C13.4348 17.9557 13.5606 17.9522 13.7172 17.9326C13.8056 17.9216 13.973 17.9014 14.0894 17.8878C14.2057 17.8742 14.363 17.8486 14.439 17.8309C14.515 17.8132 14.6562 17.7901 14.7529 17.7795C14.8496 17.769 14.9917 17.7446 15.0685 17.7253C15.1454 17.706 15.2981 17.6781 15.4079 17.6633C15.5176 17.6485 15.6752 17.619 15.7581 17.5977C15.8411 17.5765 15.982 17.5591 16.0713 17.5592C16.1606 17.5592 16.2695 17.5471 16.3132 17.5322C16.357 17.5173 16.5204 17.4892 16.6762 17.4697C16.8321 17.4502 17.0143 17.4229 17.0812 17.409C17.2061 17.3831 17.9259 17.3091 18.2168 17.2922C18.3065 17.287 18.445 17.2742 18.5245 17.2638C18.6041 17.2534 18.8997 17.2304 19.1815 17.2127C20.231 17.1468 20.2207 17.1538 21.4915 15.6448C21.8957 15.1649 22.2554 14.7466 22.2909 14.7153C22.3263 14.684 22.3998 14.6173 22.4543 14.5671C22.5088 14.5168 22.5657 14.4648 22.5809 14.4513C22.5961 14.4379 22.6526 14.3832 22.7066 14.3298C22.7606 14.2764 22.8436 14.2105 22.891 14.1832C22.9385 14.156 23.0294 14.0918 23.093 14.0405C23.3581 13.8273 23.4086 13.7889 23.5318 13.7078C23.6786 13.6111 23.7962 13.4438 23.7866 13.3453C23.7816 13.2933 23.7769 13.2942 23.7235 13.3585C23.6918 13.3967 23.6229 13.4452 23.5703 13.4664C23.5178 13.4875 23.4666 13.5145 23.4567 13.5265C23.3914 13.6051 23.0034 13.7182 22.8213 13.7117C22.7796 13.7102 22.7574 13.7312 22.6922 13.8339C22.6307 13.9307 22.5986 13.9626 22.5458 13.9798C22.5023 13.9939 22.4509 14.0379 22.4019 14.1028C22.36 14.1583 22.3011 14.2137 22.271 14.2258C22.2409 14.2379 22.1804 14.2845 22.1366 14.3292C21.9901 14.4787 21.8665 14.5753 21.7938 14.5973C21.7542 14.6093 21.7063 14.6377 21.6874 14.6604C21.5849 14.7839 21.3465 14.863 21.2355 14.8104C21.171 14.7798 21.1482 14.785 21.0483 14.8527C20.9857 14.8952 20.9028 14.9461 20.8641 14.966C20.8253 14.9859 20.75 15.0399 20.6968 15.0859C20.6435 15.132 20.5733 15.1802 20.5408 15.193C20.5083 15.2059 20.4399 15.2545 20.3887 15.3012C20.2444 15.4326 19.991 15.5525 19.8015 15.579C19.7066 15.5922 19.6529 15.5851 19.616 15.5545C19.5621 15.5097 19.4175 15.5497 19.3024 15.6411C19.2121 15.7129 19.034 15.8121 18.9578 15.833C18.9161 15.8445 18.8689 15.8696 18.8528 15.889C18.7253 16.0425 18.3311 16.1911 18.2437 16.1186C18.1868 16.0713 18.1756 16.0743 17.8615 16.2188C17.7844 16.2543 17.7027 16.2832 17.6799 16.2831C17.6571 16.283 17.6126 16.303 17.5809 16.3276C17.5493 16.3522 17.516 16.3662 17.507 16.3587C17.491 16.3454 17.4061 16.373 17.2896 16.4296C17.257 16.4454 17.1544 16.4725 17.0615 16.4899C16.9687 16.5072 16.8585 16.5335 16.8167 16.5483C16.7717 16.5642 16.7097 16.5611 16.6645 16.5406C16.5623 16.4943 16.292 16.4966 16.1873 16.5448C16.1409 16.5661 16.0417 16.583 15.9669 16.5821C15.892 16.5813 15.7928 16.5941 15.7462 16.6105C15.6997 16.6269 15.6263 16.6324 15.5832 16.6226C15.5401 16.6129 15.461 16.6082 15.4073 16.6122C15.3536 16.6162 15.281 16.6039 15.2461 16.585C15.2112 16.566 15.172 16.5541 15.159 16.5584C15.146 16.5627 15.1109 16.5459 15.0809 16.521C15.041 16.4879 14.999 16.482 14.9241 16.4989C14.7899 16.5292 14.6547 16.476 14.5044 16.3339C14.3432 16.1814 14.1234 16.0771 13.8595 16.0279C13.7387 16.0053 13.6254 15.9749 13.6078 15.9602C13.5901 15.9456 13.549 15.9323 13.5164 15.9307C13.4837 15.9291 13.4411 15.915 13.4217 15.8994C13.4023 15.8838 13.3436 15.8746 13.2913 15.8788C13.239 15.8831 13.1593 15.8844 13.1143 15.8818C13.0694 15.8791 13.0124 15.878 12.9879 15.8792C12.9288 15.8821 12.8966 15.8212 12.9255 15.7609C12.9644 15.6796 13.211 15.4748 13.289 15.459C13.3531 15.446 13.6226 15.2492 13.6956 15.1622C13.7376 15.1121 13.8079 15.0443 13.8518 15.0114C13.9675 14.9247 14.1312 14.7304 14.131 14.68C14.1306 14.5606 14.2331 14.3633 14.3677 14.2247C14.4726 14.1166 14.5033 14.0721 14.509 14.019C14.5228 13.8937 14.7284 13.5913 14.9189 13.4164C15.1409 13.2126 15.1767 13.1625 15.1712 13.063C15.1659 12.9674 15.2586 12.8529 15.3836 12.8005C15.5072 12.7487 15.9994 12.3034 15.9846 12.2569C15.9623 12.1869 16.0264 12.1237 16.1986 12.0459C16.6193 11.8559 16.6582 11.823 16.5278 11.7679C16.3024 11.6727 16.0583 11.7693 15.8529 12.0352C15.7415 12.1795 15.5004 12.3963 15.4152 12.4289C15.3345 12.4597 15.0992 12.7297 14.9366 12.9779C14.4619 13.7027 14.2766 13.917 14.091 13.956C14.0341 13.9679 14.0048 13.9915 13.9627 14.0592C13.9327 14.1075 13.8592 14.186 13.7992 14.2336C13.7392 14.2813 13.6568 14.3539 13.616 14.3951C13.2781 14.7358 13.104 14.8598 12.9553 14.8655C12.9007 14.8676 12.8708 14.8897 12.7957 14.9834C12.7449 15.0468 12.6719 15.1152 12.6334 15.1353C12.5949 15.1554 12.5473 15.1948 12.5275 15.2228C12.5077 15.2509 12.4177 15.3039 12.3275 15.3407C12.2372 15.3774 12.1395 15.4232 12.1103 15.4424C12.0812 15.4616 12.019 15.4809 11.972 15.4853C11.7822 15.5032 11.6703 15.5366 11.6031 15.5953C11.5642 15.6293 11.474 15.6714 11.4027 15.689C11.3315 15.7066 11.24 15.7299 11.1995 15.7408C11.1589 15.7518 11.107 15.7454 11.084 15.7266C11.0344 15.6863 10.9306 15.6808 10.8516 15.7143C10.8204 15.7275 10.7794 15.7253 10.7603 15.7095C10.7412 15.6936 10.7045 15.6845 10.6788 15.6892C10.6531 15.6939 10.6213 15.6888 10.6081 15.6778C10.5765 15.6515 10.374 15.6836 10.2695 15.7315C10.2239 15.7524 10.1797 15.7637 10.1712 15.7567C10.1628 15.7497 10.147 15.7544 10.1362 15.7671C10.1254 15.7798 10.0676 15.7976 10.0078 15.8067C9.94801 15.8158 9.89467 15.8283 9.88927 15.8345C9.88389 15.8407 9.79172 15.8567 9.68447 15.8703C9.57723 15.8838 9.48381 15.9016 9.47687 15.91C9.46992 15.9184 9.42584 15.9166 9.3789 15.9062C9.20646 15.8677 9.30816 15.74 9.51619 15.7337C9.57213 15.732 9.88072 15.5289 10.0251 15.3987C10.4589 15.0076 10.5469 14.9041 10.5396 14.7933L10.5343 14.7134L10.7113 14.5783C10.9813 14.3722 11.176 14.1998 11.2961 14.0605C11.356 13.991 11.4156 13.9307 11.4285 13.9264C11.4917 13.9054 11.5332 13.7684 11.497 13.7002C11.4533 13.6179 11.4598 13.6106 11.7766 13.3827C11.8886 13.3022 12.1141 13.1203 12.2778 12.9785C12.4415 12.8368 12.6592 12.6695 12.7617 12.6068C12.8642 12.5441 12.9846 12.4594 13.0292 12.4187C13.2626 12.2055 13.3522 12.1472 13.6643 12.0061C13.9849 11.8612 13.9439 11.842 13.551 11.953C13.4884 11.9707 13.3575 12.0042 13.2601 12.0275C13.1628 12.0507 13.0096 12.0939 12.9197 12.1234C12.8298 12.1529 12.7395 12.1744 12.7189 12.1713C12.6982 12.1681 12.6344 12.186 12.5769 12.2112C12.5195 12.2363 12.4343 12.2606 12.3876 12.2652C12.301 12.2737 11.9648 12.3772 11.7432 12.4636C11.6757 12.49 11.6111 12.5038 11.5997 12.4944C11.5884 12.4849 11.5453 12.4953 11.504 12.5174C11.4627 12.5395 11.361 12.5887 11.278 12.6268C11.1032 12.707 11.0946 12.7154 11.0435 12.8567C10.9889 13.0076 10.9472 13.0798 10.848 13.1952C10.743 13.3174 10.4789 13.5547 10.4373 13.5641C10.4209 13.5678 10.3714 13.6048 10.3274 13.6463C10.1278 13.8342 9.99602 13.9425 9.91712 13.9834C9.87015 14.0078 9.82819 14.0345 9.82389 14.0428C9.80328 14.0823 9.65597 14.1833 9.60791 14.1908C9.54914 14.2001 9.48786 14.2803 9.37107 14.5007C9.32229 14.5928 9.27526 14.6508 9.19639 14.7164C9.13703 14.7657 9.05951 14.841 9.02412 14.8836C8.98873 14.9262 8.94954 14.962 8.93705 14.9631C8.92455 14.9642 8.77662 15.1241 8.60831 15.3185C8.14006 15.8592 8.03166 15.9794 7.99402 15.9995C7.97496 16.0097 7.89418 16.0775 7.81451 16.1502C7.53429 16.4058 7.48436 16.445 7.38531 16.4879C7.33034 16.5116 7.27672 16.5482 7.26615 16.5691C7.25558 16.59 7.21086 16.6238 7.16678 16.6443C6.97742 16.7323 6.32925 17.4466 6.29715 17.6027C6.2717 17.7265 5.21895 18.9874 5.01339 19.1403C4.96379 19.1772 4.88227 19.2481 4.83223 19.2978C4.7822 19.3476 4.70644 19.423 4.66388 19.4654C4.62132 19.5078 4.57559 19.5461 4.56226 19.5505C4.54894 19.5549 4.50656 19.5873 4.46807 19.6224C4.27981 19.7943 4.16024 19.8844 4.12047 19.8842C4.09636 19.8841 4.07501 19.8959 4.07303 19.9105C4.07104 19.925 4.02814 19.9694 3.97769 20.0091C3.92724 20.0488 3.83451 20.1238 3.77161 20.1757C3.70872 20.2276 3.61691 20.3004 3.56758 20.3375C3.51825 20.3747 3.38541 20.4754 3.27238 20.5614C3.15935 20.6474 3.05122 20.7209 3.03209 20.7247C3.01295 20.7285 2.96247 20.7617 2.91991 20.7985C2.87735 20.8353 2.81784 20.8711 2.78766 20.878C2.75748 20.8849 2.7201 20.9053 2.70457 20.9233C2.68905 20.9413 2.65962 20.9504 2.63916 20.9434C2.61871 20.9364 2.58613 20.9497 2.56677 20.9731C2.5474 20.9964 2.51016 21.0154 2.484 21.0152C2.45784 21.0151 2.42488 21.0285 2.41076 21.045C2.38009 21.0809 1.9907 21.2527 1.86693 21.2849C1.8189 21.2974 1.76888 21.3206 1.75578 21.3364C1.74267 21.3521 1.72164 21.3636 1.70904 21.3618C1.69644 21.3599 1.59932 21.3951 1.49322 21.4398C1.26072 21.5378 1.04083 21.5106 1.02837 21.3822C1.02539 21.3517 0.956904 21.2669 0.763854 21.0551C0.745536 21.035 0.725335 21.0124 0.718968 21.0049C0.69628 20.9782 0.658962 20.6256 0.676574 20.6044C0.686437 20.5925 0.688022 20.5285 0.680097 20.4621C0.666005 20.344 0.676749 20.2685 0.754968 19.9359C0.776144 19.8458 0.78992 19.7617 0.785584 19.749C0.781248 19.7363 0.793266 19.6969 0.812296 19.6616C0.831322 19.6262 0.860673 19.5474 0.87752 19.4863C0.918409 19.3382 1.00053 19.1409 1.04224 19.0907C1.0608 19.0684 1.12629 18.9479 1.18775 18.8231C1.34208 18.5097 1.93624 17.7167 2.17338 17.5076C2.20885 17.4764 2.31462 17.3772 2.40841 17.2874C2.50221 17.1975 2.60383 17.1115 2.63422 17.0963C2.66463 17.081 2.75644 17.0035 2.83826 16.9239C2.92007 16.8444 3.11508 16.6798 3.27159 16.5581C3.4281 16.4365 3.61415 16.2907 3.68503 16.234C3.7559 16.1774 3.83507 16.1225 3.86097 16.112C3.88687 16.1015 3.96018 16.0509 4.02388 15.9997C4.08758 15.9485 4.18237 15.8852 4.23451 15.8591C4.28665 15.833 4.38263 15.7778 4.44779 15.7365C4.51296 15.6952 4.58034 15.6596 4.59753 15.6574C4.61472 15.6552 4.63824 15.642 4.6498 15.628C4.69427 15.5745 5.36545 15.2749 5.47174 15.2611C5.50606 15.2567 5.55619 15.2265 5.58314 15.1941C5.68117 15.076 5.963 14.8574 6.42645 14.5401C6.53524 14.4656 6.66172 14.3753 6.70752 14.3394C6.75331 14.3036 6.86077 14.2366 6.94631 14.1907C7.03185 14.1447 7.17706 14.0631 7.26899 14.0093C7.6567 13.7824 7.8905 13.6607 8.12137 13.5655C8.17724 13.5425 8.23902 13.5157 8.25868 13.506C8.39668 13.4379 8.70497 13.3088 8.78432 13.286C8.85383 13.266 8.93255 13.2102 9.07211 13.082C9.27956 12.8914 9.35259 12.837 9.46692 12.788C9.50746 12.7706 9.57439 12.7277 9.61566 12.6925C9.81092 12.5262 10.4579 12.3711 10.7655 12.4169C10.9332 12.4418 10.9681 12.4368 11.1375 12.363C11.2403 12.3182 11.3993 12.2571 11.4909 12.2271C11.5824 12.1971 11.662 12.1669 11.6678 12.16C11.6735 12.1531 11.7621 12.1217 11.8647 12.0903C11.9672 12.0588 12.1204 12.0055 12.2051 11.9717C12.3701 11.9059 12.3774 11.904 12.6988 11.8415C12.8153 11.8189 12.9664 11.7829 13.0346 11.7614C13.1424 11.7275 13.5508 11.635 13.778 11.5929C14.0027 11.5513 14.5503 11.4815 14.9 11.4499C15.017 11.4394 15.3682 11.4209 15.5328 11.4166C15.577 11.4155 15.6317 11.4112 15.6543 11.4071C15.8285 11.3754 16.7347 11.3634 16.7695 11.3923C16.8663 11.4728 17.1487 11.4081 17.3891 11.2505C17.5562 11.1409 17.5705 11.1188 17.4858 11.1012C17.4556 11.0949 17.4164 11.0777 17.3987 11.063C17.3809 11.0482 17.2966 11.0284 17.2113 11.0189C17.126 11.0094 16.9865 10.9772 16.9012 10.9475C16.816 10.9178 16.7102 10.8851 16.6661 10.8749C16.534 10.8444 15.8888 10.5753 15.8791 10.5466C15.8741 10.532 15.8108 10.4975 15.7383 10.4698C15.6659 10.4422 15.5827 10.3947 15.5536 10.3642C15.5151 10.324 15.4902 10.315 15.4624 10.3314C15.3961 10.3707 15.2496 10.3513 15.1683 10.2925C15.1256 10.2615 15.0585 10.2325 15.0192 10.2278C14.7825 10.2 14.2843 9.9225 14.0316 9.67763C13.6375 9.29588 12.9784 8.73941 12.761 8.605C12.6591 8.54194 12.537 8.44486 12.4447 8.35345C12.362 8.27157 12.2525 8.16611 12.2012 8.11909C12.1499 8.07206 12.082 7.99001 12.0502 7.93675C11.9547 7.77648 11.798 7.54791 11.7648 7.52036C11.7477 7.50615 11.7261 7.44565 11.7169 7.38593C11.7077 7.3262 11.694 7.27052 11.6866 7.26218C11.6155 7.18238 11.5815 7.10104 11.5454 6.92487C11.5248 6.82412 11.4789 6.67205 11.4434 6.58693C11.3718 6.41531 11.3685 6.37968 11.4207 6.34595C11.4402 6.3333 11.4519 6.31021 11.4466 6.29465C11.4413 6.27909 11.4512 6.24921 11.4686 6.22824C11.5035 6.1863 11.5004 5.63653 11.4647 5.50371C11.4508 5.45226 11.4551 5.41306 11.4759 5.40148C11.4944 5.39115 11.5191 5.35181 11.5307 5.31406C11.6837 4.81723 12.1615 4.80463 12.3699 5.29195C12.4437 5.46432 12.5838 5.64781 12.8063 5.86324C12.9324 5.9854 13.0618 6.12286 13.0938 6.16872C13.1257 6.21457 13.1969 6.29275 13.2519 6.34245C13.5293 6.59304 13.9302 7.26729 14.1423 7.83999C14.2606 8.15938 14.2507 8.14406 14.6014 8.55058C14.8667 8.85806 15.3733 9.58012 15.5198 9.85961C15.5367 9.89192 15.5617 9.93087 15.5752 9.94616C15.5888 9.96144 15.6354 10.0179 15.6788 10.0715C15.8032 10.2255 16.0709 10.3783 16.425 10.4973C16.5129 10.5269 16.6637 10.5856 16.76 10.6277C16.9297 10.7019 17.1538 10.7668 17.1707 10.7465C17.1788 10.7367 17.1663 10.7098 17.0563 10.5009C16.8718 10.1507 16.8702 10.1466 16.8165 9.88016C16.7526 9.56292 16.7158 9.11293 16.7457 9.01419C16.7601 8.96666 16.7714 8.88497 16.7709 8.83266C16.7703 8.78035 16.7788 8.72671 16.7899 8.71345C16.8009 8.7002 16.7947 8.63984 16.7762 8.57931C16.7576 8.51879 16.7475 8.41039 16.7538 8.33842C16.76 8.26646 16.7609 8.19932 16.7558 8.18924C16.7048 8.0884 16.7921 7.78429 16.9704 7.44182C17.0208 7.34488 17.0964 7.18758 17.1383 7.09226C17.249 6.84064 17.5041 6.53263 17.5687 6.5725C17.616 6.60164 17.6337 6.77727 17.5942 6.82487C17.5825 6.83898 17.5787 6.86673 17.5859 6.88655C17.593 6.90637 17.5953 7.00847 17.591 7.11345C17.5825 7.31625 17.5992 7.4122 17.6795 7.62292C17.7778 7.88054 17.8209 8.81351 17.7391 8.91196C17.7314 8.92127 17.7348 8.96025 17.7468 8.99859C17.7587 9.03693 17.7584 9.08042 17.7461 9.09525C17.7173 9.12994 17.7287 9.34934 17.7607 9.37592C17.8023 9.41048 17.8589 9.75014 17.8444 9.87811C17.8368 9.94496 17.8398 10.0295 17.8512 10.0659C17.8625 10.1024 17.8653 10.1399 17.8574 10.1494C17.8127 10.2033 17.9289 10.6514 18.0037 10.7135C18.0439 10.7469 18.0562 10.743 18.1086 10.6798C18.1413 10.6405 18.1975 10.5967 18.2335 10.5826C18.2695 10.5684 18.3482 10.5377 18.4083 10.5142C18.4684 10.4907 18.5159 10.468 18.5139 10.4637C18.4342 10.292 18.3887 10.177 18.3496 10.0477C18.3229 9.95972 18.2951 9.88278 18.2878 9.87671C18.2522 9.84718 18.2522 9.44296 18.2878 9.34298C18.3096 9.28158 18.3442 9.16714 18.3647 9.08869C18.3929 8.98039 18.4387 8.89348 18.5551 8.72766C18.6445 8.6002 18.7079 8.48867 18.7074 8.45978C18.7066 8.41538 18.7296 8.3288 18.7489 8.30351C18.753 8.2982 18.7565 8.2798 18.7567 8.26264C18.7573 8.21219 18.8578 8.05369 19.0187 7.84921C19.1013 7.74426 19.2196 7.57981 19.2815 7.48376C19.5566 7.05728 19.8481 6.92135 19.747 7.26673C19.729 7.32811 19.7133 7.43182 19.7121 7.49719C19.7109 7.56256 19.6839 7.68379 19.6522 7.76659C19.6204 7.84939 19.5943 7.98092 19.5942 8.05888C19.5939 8.20773 19.55 8.4179 19.5089 8.46741C19.4956 8.48345 19.4886 8.51723 19.4935 8.54247C19.4983 8.56771 19.4822 8.62355 19.4578 8.66657C19.3729 8.81592 19.3192 8.98613 19.3261 9.08426C19.3299 9.13853 19.3184 9.24969 19.3005 9.3313C19.2272 9.66535 19.3268 9.86583 19.5359 9.8048C19.7888 9.73098 20.0931 9.61938 20.165 9.57407C20.1709 9.57032 20.2059 9.55379 20.2427 9.53733C20.3 9.51167 20.3107 9.49708 20.3175 9.43492C20.3293 9.32641 20.3503 9.31428 20.5451 9.30302C20.6436 9.29733 20.7929 9.27272 20.8771 9.24833C20.9613 9.22394 21.1593 9.16931 21.3172 9.12693C21.6766 9.03049 21.7564 8.99219 21.8229 8.88422C21.884 8.78496 21.9017 8.77893 22.039 8.811C22.3492 8.88347 23.332 8.71641 23.2838 8.59937C23.2462 8.50787 23.6085 8.4267 23.7033 8.5054C23.7174 8.5171 23.7305 8.51475 23.7325 8.50019C23.7345 8.48562 23.8116 8.48229 23.9039 8.49279C23.9962 8.50329 24.0927 8.51241 24.1184 8.51306C24.5433 8.52389 24.5636 8.52141 24.5432 8.46148C24.5019 8.34022 24.641 8.34016 25.0901 8.46128C25.2142 8.49474 25.3933 8.52915 25.4882 8.53775C25.583 8.54634 25.6715 8.56238 25.6848 8.57339C25.698 8.58439 25.7945 8.60908 25.8991 8.62825C26.2855 8.69907 26.6694 8.97785 26.9228 9.37167C27.0006 9.49247 27.0684 9.67554 27.0456 9.70299C27.0374 9.71287 27.0445 9.7533 27.0614 9.79284C27.0783 9.83238 27.0914 9.9417 27.0905 10.0358C27.0883 10.2541 27.1503 10.4045 27.2744 10.4819C27.3386 10.522 27.3646 10.5511 27.3647 10.5828C27.3648 10.6073 27.3854 10.6488 27.4104 10.6749C27.4679 10.735 27.4343 10.8149 27.3729 10.764C27.3344 10.732 27.3277 10.7364 27.2714 10.8295C27.1704 10.9966 27.1852 11.0108 27.3511 10.9059C27.4355 10.8525 27.5157 10.8104 27.5292 10.8123C27.5428 10.8143 27.5675 10.7995 27.5842 10.7794C27.6009 10.7593 27.6346 10.7349 27.6591 10.7251C27.7837 10.6756 27.9863 10.5635 28.0161 10.5276C28.0347 10.5052 28.0639 10.485 28.0809 10.4827C28.098 10.4804 28.1878 10.4349 28.2804 10.3817C28.373 10.3285 28.499 10.2627 28.5603 10.2356C29.3113 9.90311 29.3417 9.88245 29.1141 9.85852C29.0297 9.84964 28.9551 9.83774 28.9483 9.83207C28.9415 9.8264 28.9142 9.8286 28.8877 9.83695C28.8612 9.8453 28.7927 9.84168 28.7355 9.8289C28.6783 9.81612 28.6029 9.80672 28.5679 9.80801C28.5329 9.8093 28.4973 9.80465 28.4889 9.79766C28.4556 9.77002 28.4482 9.8207 28.4792 9.8638C28.5308 9.93536 28.4592 9.92477 28.3391 9.84308C28.2807 9.80342 28.2109 9.76636 28.1838 9.76072C28.1529 9.75428 28.0845 9.6985 27.9997 9.61051C27.9255 9.53352 27.831 9.44939 27.7897 9.42353C27.6144 9.31378 27.4677 9.23065 27.2717 9.12993C26.9766 8.97825 26.867 8.90052 26.8668 8.84262C26.8665 8.7777 26.6669 8.62182 26.4169 8.49131C26.3087 8.43482 26.1533 8.33952 26.0716 8.27953C25.9898 8.21953 25.906 8.17036 25.8852 8.17027C25.8644 8.17017 25.8168 8.14766 25.7794 8.12024C25.7421 8.09282 25.6981 8.06937 25.6816 8.06812C25.6651 8.06688 25.593 8.02438 25.5213 7.97368C25.4496 7.92298 25.3204 7.84564 25.2343 7.80181C25.0045 7.68494 24.9718 7.65172 24.9923 7.55658C25.0115 7.46719 24.9881 7.44037 24.8455 7.38831C24.7918 7.36869 24.7332 7.34068 24.7153 7.32607C24.6974 7.31144 24.6451 7.28811 24.5992 7.27419C24.5532 7.26027 24.4207 7.20799 24.3046 7.15802C24.1886 7.10805 24.0539 7.05459 24.0054 7.03923C23.9569 7.02388 23.8892 6.99323 23.855 6.97112C23.8209 6.94901 23.7759 6.92553 23.7551 6.91894C23.6322 6.87995 23.5157 6.82798 23.5141 6.81143C23.513 6.80089 23.4786 6.78173 23.4375 6.76887C23.3554 6.74319 23.294 6.6693 23.3242 6.63282C23.4011 6.54032 23.1953 6.36833 22.9175 6.29274C22.8724 6.2805 22.8277 6.26391 22.818 6.25588C22.8084 6.24784 22.7324 6.21423 22.6493 6.18117C22.5662 6.14812 22.48 6.10672 22.4578 6.08918C22.4356 6.07164 22.3828 6.04221 22.3403 6.02379C22.2177 5.97056 22.163 5.93389 21.9018 5.72968L21.6557 5.53733L21.6575 5.45552C21.6595 5.36519 21.6415 5.34821 21.386 5.19907C21.3058 5.15231 21.2301 5.11742 21.2177 5.12153C21.2053 5.12565 21.1693 5.10765 21.1379 5.08152C21.1064 5.05539 21.0486 5.02684 21.0094 5.01808C20.9028 4.99426 20.678 4.89684 20.6217 4.85008C20.5945 4.82746 20.5615 4.8125 20.5484 4.81684C20.5354 4.82117 20.5061 4.80934 20.4833 4.79055C20.4606 4.77176 20.411 4.74962 20.3733 4.74134C20.1744 4.69778 19.8421 4.42458 19.9013 4.35328C19.9339 4.31404 19.6744 4.10149 19.5887 4.09722C19.5459 4.09509 19.5091 4.0728 19.466 4.0228C19.4282 3.97906 19.3433 3.92157 19.2466 3.87431C19.1599 3.83189 19.0657 3.7714 19.0373 3.73988C19.0089 3.70836 18.94 3.65782 18.8843 3.62758C18.7421 3.55041 18.3988 3.27771 18.3894 3.23441C18.3845 3.21181 18.3614 3.1942 18.3273 3.18711C18.2448 3.16993 18.1954 3.11804 18.2069 3.06063C18.2173 3.00869 18.1583 2.96048 18.0807 2.95759C18.0362 2.95593 17.6759 2.74242 17.4323 2.57327C17.3268 2.50002 17.1962 2.4123 17.142 2.37833C17.0605 2.32721 17.0398 2.3016 17.0218 2.22968C17.0098 2.18189 16.9855 2.14069 16.9677 2.13812C16.9499 2.13555 16.9312 2.11194 16.9261 2.08567C16.9147 2.02608 16.7538 1.90351 16.6231 1.85482C16.404 1.77318 16.4116 1.50164 16.6335 1.48207C16.6819 1.47781 16.7257 1.46922 16.7309 1.463C16.736 1.45677 16.8913 1.43994 17.0759 1.42561C17.4517 1.39645 17.7209 1.3057 17.8333 1.17035C17.8664 1.1305 17.9225 1.08199 17.9579 1.06254C17.9933 1.0431 18.0473 1.00539 18.0779 0.97875C18.1852 0.885361 18.3544 0.765563 18.4399 0.722429L18.5262 0.678889L18.4431 0.626695C18.3231 0.551313 18.3668 0.524819 18.5409 0.567507C18.6208 0.587128 18.6948 0.592928 18.7052 0.580397C18.7156 0.567864 18.7441 0.555388 18.7684 0.552674C18.8584 0.542637 18.9428 0.48568 18.965 0.419946C18.999 0.319763 19.0216 0.305212 19.1609 0.293854C19.3023 0.282313 19.7457 0.297198 19.7662 0.314186C19.7858 0.330435 20.0573 0.352545 20.1497 0.345411C20.1955 0.341874 20.3134 0.33782 20.4117 0.336403C20.6016 0.333665 20.6091 0.329754 20.8369 0.113804C20.979 -0.0209274 21.3623 -0.0374313 21.8133 0.071788C21.9135 0.0960442 22.0166 0.115987 22.0425 0.116108C22.1054 0.1164 22.2001 0.132297 22.2526 0.151412C22.2761 0.159973 22.2998 0.161641 22.3052 0.155118C22.3106 0.148595 22.3701 0.154926 22.4374 0.169188C22.5096 0.18451 22.5762 0.18178 22.6002 0.162514C22.6225 0.144582 22.6712 0.103363 22.7084 0.0709144C22.7618 0.0242559 22.7942 0.0166519 22.8633 0.0345493C22.9114 0.046996 22.9728 0.0531446 22.9998 0.048211C23.0553 0.038081 23.1687 0.0690193 23.366 0.148072C23.4401 0.177766 23.5241 0.206009 23.5526 0.210835C23.5812 0.215661 23.6926 0.251471 23.8004 0.290413C23.9081 0.329355 24.0918 0.39092 24.2086 0.427205C24.3255 0.46349 24.4393 0.501773 24.4616 0.512254C24.4839 0.522735 24.5762 0.515141 24.6667 0.495377L24.8313 0.459445L25.0589 0.610904C25.1841 0.694203 25.4157 0.848346 25.5735 0.953447C25.7313 1.05855 25.9229 1.19013 25.9992 1.24587C26.223 1.4094 26.3699 1.51002 26.5268 1.60712C26.6077 1.65722 26.7666 1.75913 26.8799 1.83361C27.1227 1.99329 27.1583 2.00378 27.2453 1.94146C27.307 1.89731 27.3155 1.89857 27.3806 1.96148C27.6185 2.19152 28.3574 2.74269 28.6274 2.89161C28.6574 2.90816 28.7391 2.96184 28.8089 3.0109C28.9577 3.11548 29.1071 3.16141 29.1803 3.12507C29.2596 3.08571 29.3106 3.12484 29.4115 3.30269C29.4623 3.39214 29.5465 3.52614 29.5985 3.60047C29.6506 3.6748 29.7245 3.78178 29.7629 3.83821C29.8012 3.89463 29.8648 3.96761 29.9043 4.00039C29.9438 4.03316 30.01 4.10438 30.0515 4.15865C30.1346 4.26733 30.2352 4.32871 30.2672 4.29024C30.3599 4.17857 30.4354 4.25878 30.7913 4.84736C30.8688 4.97545 30.9701 5.1238 31.0164 5.17699C31.0628 5.2302 31.1315 5.3372 31.1691 5.41476C31.2067 5.49234 31.2606 5.59702 31.2888 5.6474C31.317 5.69777 31.3438 5.75532 31.3484 5.77528C31.353 5.79523 31.3852 5.82629 31.4199 5.8443C31.4857 5.87845 31.4938 5.8919 31.7305 6.36133C31.7602 6.42036 31.8185 6.52668 31.8598 6.59759C31.9012 6.66851 31.9432 6.74734 31.9531 6.77278C31.993 6.87527 32.2004 7.29525 32.2185 7.31036C32.2405 7.32857 32.3602 7.56478 32.3985 7.66521C32.4853 7.89326 32.4912 7.90231 32.5455 7.88889C32.6326 7.86738 32.6404 7.88243 32.7473 8.28011C32.7794 8.39956 32.8221 8.52926 32.8422 8.56834C32.8623 8.60742 32.8854 8.68309 32.8936 8.73649C32.9187 8.90051 32.9849 9.1706 33.0203 9.25329L33.0539 9.33182L33.14 9.2871C33.2397 9.23535 33.2884 9.1518 33.266 9.07109C33.2391 8.97433 33.3979 8.81796 33.7308 8.61346C33.8149 8.56181 33.9357 8.47373 33.9992 8.41774C34.0628 8.36174 34.1949 8.27977 34.2928 8.2356C34.3907 8.19142 34.4956 8.13684 34.526 8.11432C34.5563 8.0918 34.5877 8.07884 34.5957 8.0855C34.6038 8.09217 34.6307 8.08258 34.6556 8.06418C34.6804 8.04578 34.7372 8.00424 34.7818 7.97186C34.9584 7.84364 34.9704 7.82804 34.9404 7.7665C34.882 7.64677 34.9654 7.58661 35.4956 7.36565C35.6904 7.28448 35.9143 7.18036 35.9932 7.1343C36.0721 7.08823 36.1765 7.03354 36.2253 7.01276C36.2741 6.99199 36.3233 6.96375 36.3347 6.95C36.3461 6.93625 36.3885 6.91115 36.4289 6.89422C36.4693 6.87728 36.5458 6.81668 36.5988 6.75955C36.7184 6.63067 36.8199 6.57885 36.9077 6.60192C36.9951 6.6249 37.342 6.53798 37.5972 6.42914C37.7077 6.38204 37.8212 6.34027 37.8494 6.33632C37.8776 6.33237 37.911 6.31675 37.9236 6.30161C37.9701 6.24555 38.5349 6.15566 38.6778 6.18157C38.6968 6.18503 38.8113 6.18478 38.9322 6.18101C39.6083 6.15994 40.223 6.41332 40.3811 6.77834C40.3983 6.81797 40.4369 6.88113 40.467 6.91871C40.5463 7.01783 40.62 7.2288 40.6319 7.39087C40.6532 7.68022 40.8185 7.88752 41.0746 7.94609C41.1339 7.95965 41.2061 7.99033 41.2351 8.01427C41.264 8.03821 41.3243 8.06547 41.3691 8.07484C42.0721 8.22206 42.774 8.95369 42.7235 9.48654C42.7107 9.62222 42.6421 9.61666 43.4728 9.54726C44.5196 9.45979 44.7897 9.50627 44.8777 9.789C44.8895 9.82714 44.9335 9.88677 44.9753 9.92149C45.0277 9.96502 45.0446 9.99269 45.0297 10.0106C45 10.0464 44.9471 10.0243 44.8302 9.92717C44.7461 9.85737 44.7109 9.84411 44.6039 9.8418C44.3388 9.8361 43.7538 9.86051 43.7394 9.87788C43.7148 9.90745 43.4488 9.94747 43.4225 9.92556C43.4091 9.91448 43.3929 9.91179 43.3864 9.91958C43.3579 9.95389 42.7845 9.99602 42.6817 9.97136C42.5619 9.94263 42.541 9.95867 42.4583 10.1424C42.4296 10.2061 42.4521 10.2082 42.7467 10.169C43.8595 10.021 44.8352 9.9766 44.7512 10.0777C44.7321 10.1007 44.4084 10.1126 44.3369 10.0929C44.3035 10.0837 44.2561 10.089 44.2315 10.1047C44.1825 10.136 43.7756 10.1873 43.7494 10.1655C43.7405 10.1581 43.6422 10.1628 43.5309 10.176C43.4196 10.1892 43.0913 10.2228 42.8012 10.2505C42.3186 10.2968 42.1931 10.3244 42.2503 10.3719C42.285 10.4008 42.9933 10.3096 43.0717 10.2662C43.1156 10.2419 43.8293 10.1986 44.1391 10.2015C44.3567 10.2035 44.4276 10.2028 44.637 10.1961C44.7089 10.1938 44.7867 10.1994 44.8098 10.2084C44.8329 10.2175 44.8583 10.217 44.8663 10.2075C44.8743 10.1979 44.8935 10.2006 44.909 10.2135C44.9246 10.2264 44.9441 10.2287 44.9525 10.2187C44.9609 10.2086 44.9923 10.2122 45.0224 10.2267C45.0524 10.2412 45.1132 10.2487 45.1573 10.2435C45.2395 10.2336 45.3056 10.27 45.3277 10.3374C45.3393 10.3727 45.0058 10.4201 44.9679 10.3886C44.9504 10.3741 44.7489 10.3701 44.4886 10.3791C44.1602 10.3905 43.8829 10.3987 43.6932 10.4028C43.0474 10.4167 42.1978 10.4704 42.085 10.5045C41.9578 10.543 41.6622 10.8317 41.6809 10.8992C41.7008 10.9706 41.6177 11.0781 41.4268 11.2279C41.3549 11.2843 41.2667 11.3559 41.2309 11.3869C41.1951 11.4179 41.1316 11.4575 41.0898 11.4748C41.0437 11.4938 40.9849 11.5445 40.9406 11.6033C40.9004 11.6567 40.8522 11.7089 40.8335 11.7194C40.768 11.756 40.6965 11.8124 40.5801 11.9192C40.5156 11.9784 40.4074 12.0732 40.3397 12.1297C40.197 12.2488 40.1063 12.3611 40.091 12.4378C40.085 12.4675 39.9874 12.6078 39.8742 12.7497C39.7609 12.8916 39.6263 13.0794 39.5752 13.1671C39.5241 13.2548 39.3656 13.471 39.223 13.6476C39.0804 13.8242 38.9311 14.0209 38.8913 14.0847C38.8096 14.2154 38.7414 14.2415 38.6594 14.1735C38.6232 14.1433 38.6032 14.1464 38.5553 14.1895C38.481 14.2564 38.0699 14.6663 37.9813 14.7619C37.9449 14.8011 37.8927 14.85 37.8653 14.8706C37.6874 15.004 37.6064 15.1217 37.5888 15.2722C37.5793 15.3532 37.5272 15.5344 37.4729 15.6748C37.3664 15.9505 37.3542 15.9761 37.2078 16.2321C37.1215 16.3829 37.113 16.4134 37.1331 16.5004C37.1816 16.7109 37.1733 16.7919 37.0613 17.2003C37.0438 17.2639 37.0227 17.3457 37.0143 17.3821C36.9511 17.6551 36.4658 18.4666 36.2812 18.608C36.2448 18.6359 36.1888 18.6866 36.1568 18.7208C36.1249 18.755 36.0423 18.8213 35.9733 18.8681C35.8402 18.9585 35.755 19.0881 35.6109 19.419C35.5832 19.4828 35.5156 19.6249 35.4608 19.7349C35.406 19.845 35.357 19.9552 35.3521 19.98C35.3377 20.0516 35.1437 20.4116 34.942 20.7408C34.8398 20.9076 34.7378 21.084 34.7154 21.1328C34.6929 21.1816 34.6252 21.2957 34.5649 21.3865C34.5047 21.4772 34.3992 21.6396 34.3305 21.7474C34.2618 21.8552 34.1696 21.9916 34.1256 22.0505C34.0817 22.1095 34.0017 22.2206 33.948 22.2974C33.8942 22.3742 33.7911 22.5158 33.7188 22.6119C33.63 22.7301 33.576 22.8263 33.552 22.9087C33.5325 22.9758 33.4888 23.0712 33.455 23.1208C33.4211 23.1705 33.39 23.2398 33.3859 23.2749C33.377 23.3507 33.2588 23.6052 33.1509 23.7809C33.1085 23.8499 33.0122 24.0255 32.9369 24.1711C32.7273 24.5762 32.6063 24.7727 32.3906 25.0584C32.2819 25.2024 32.1383 25.3955 32.0714 25.4874C31.902 25.7205 31.9239 25.6942 31.5758 26.0827C31.4028 26.2758 31.2417 26.4417 31.2179 26.4513C31.1941 26.4609 31.1185 26.5413 31.05 26.63C30.9815 26.7188 30.8937 26.8147 30.8548 26.8433C30.816 26.8718 30.7309 26.9503 30.6659 27.0178C30.6008 27.0852 30.5325 27.1492 30.5141 27.1599C30.4956 27.1706 30.4275 27.2365 30.3627 27.3063C30.2978 27.376 30.1876 27.4761 30.1176 27.5287C30.0477 27.5812 29.9623 27.6579 29.9279 27.6989C29.8935 27.74 29.81 27.8056 29.7423 27.8446C29.6746 27.8835 29.5709 27.9676 29.5117 28.0313C29.4526 28.095 29.3441 28.1842 29.2706 28.2296C29.197 28.2749 29.0977 28.3469 29.0499 28.3895C29.0021 28.4321 28.9104 28.4961 28.8463 28.5317C28.7821 28.5673 28.6726 28.6343 28.6029 28.6805C28.4242 28.7989 28.3528 28.8357 28.3332 28.8194C28.3117 28.8015 28.2137 28.856 28.117 28.9396C28.0761 28.975 28.0207 29.0071 27.994 29.011C27.9279 29.0205 27.6616 29.1406 27.5931 29.1917C27.5626 29.2146 27.5016 29.2339 27.4576 29.2347C27.4079 29.2356 27.3611 29.2561 27.3339 29.2888C27.3099 29.3178 27.2824 29.335 27.2728 29.327C27.2633 29.3191 27.2233 29.3326 27.1841 29.357C27.1139 29.4006 27.0009 29.4167 26.9663 29.388C26.9566 29.3799 26.9331 29.3782 26.9141 29.3842C26.725 29.4439 26.4646 29.2814 26.3889 29.0566C26.37 29.0003 26.3447 28.9375 26.3328 28.9172C26.2611 28.7942 26.3811 28.413 26.639 27.9441C26.734 27.7714 26.7781 27.6572 26.8143 27.4902C26.8409 27.3674 26.8758 27.2281 26.8917 27.1807C26.9077 27.1333 26.9447 27.0242 26.9739 26.9384C27.003 26.8526 27.0404 26.7318 27.057 26.67C27.0736 26.6082 27.0997 26.5424 27.115 26.5238C27.1302 26.5051 27.1637 26.4397 27.1894 26.3784C27.215 26.317 27.2392 26.2625 27.2431 26.2573C27.2634 26.23 27.3148 26.1202 27.3281 26.0759C27.3454 26.0179 27.3946 25.9182 27.447 25.835C27.6201 25.5602 27.7052 25.4172 27.7579 25.3129C27.8039 25.2219 27.9999 24.9771 28.5242 24.3559C29.7656 22.885 29.7567 22.8948 30.0785 22.6494C30.23 22.5339 30.4202 22.3787 30.5385 22.2741C30.5689 22.2473 30.6768 22.1665 30.7783 22.0947C30.8799 22.0228 30.9842 21.9461 31.0101 21.9243C31.1695 21.7896 31.3132 21.6999 31.59 21.5623C31.6455 21.5347 31.7088 21.4905 31.7307 21.4641C31.7527 21.4376 31.7918 21.4075 31.8175 21.3971C31.8433 21.3868 32.0558 21.156 32.2898 20.8843C32.7388 20.363 33.0138 20.0746 33.303 19.8215C33.3997 19.7369 33.5108 19.6375 33.55 19.6006C33.8329 19.3339 33.9058 19.2681 34.0416 19.157C34.1258 19.0881 34.2338 18.9932 34.2815 18.9461C34.3293 18.899 34.4471 18.7839 34.5432 18.6902C34.7155 18.5225 34.7726 18.4449 34.8064 18.333C34.8159 18.3018 34.8313 18.2507 34.8407 18.2195C34.8606 18.1538 34.9315 18.0135 34.9527 17.9981C34.9606 17.9923 34.9758 17.9621 34.9863 17.931C34.9968 17.8999 35.0655 17.7896 35.139 17.686C35.2124 17.5823 35.2736 17.4897 35.2751 17.4803C35.284 17.4211 35.7684 16.8806 35.8749 16.8111C35.9145 16.7852 36.0183 16.7167 36.1054 16.6589C36.1925 16.6011 36.353 16.5127 36.462 16.4625C36.571 16.4122 36.6674 16.3626 36.6761 16.3521C36.6848 16.3415 36.7246 16.3368 36.7645 16.3415C36.8461 16.3511 36.9036 16.2968 36.9073 16.2066C36.9089 16.1674 36.9471 16.1024 37.0206 16.0138C37.3133 15.6615 37.3298 15.1891 37.0427 15.3864C36.9912 15.4218 36.8834 15.4956 36.8032 15.5504C36.7229 15.6052 36.6236 15.686 36.5825 15.7299C36.5414 15.7739 36.4731 15.8309 36.4308 15.8567C36.3588 15.9005 36.2642 15.9859 36.0577 16.1933C35.6912 16.5615 35.5634 16.6505 35.4896 16.5892C35.4207 16.532 35.3595 16.586 35.084 16.9469C34.9199 17.1618 34.8123 17.2878 34.7951 17.2853C34.7785 17.2829 34.7432 17.3226 34.7059 17.3856C34.6251 17.522 34.4747 17.6264 34.4277 17.5786C34.3975 17.5479 34.1653 17.6124 34.123 17.6633C34.1144 17.6736 34.062 17.7047 34.0066 17.7322C33.8114 17.8293 33.7757 17.8515 33.7331 17.9028C33.7095 17.9312 33.6262 18.0001 33.5479 18.0558C33.3927 18.1664 33.3103 18.2713 33.2743 18.4042C33.2389 18.5347 33.1809 18.5625 33.0562 18.5086C32.9893 18.4796 32.9396 18.4731 32.9219 18.4911C32.8268 18.5878 32.7365 18.6862 32.5584 18.8876C32.4236 19.04 32.3375 19.1212 32.2974 19.1338C32.2488 19.149 32.2376 19.1616 32.2378 19.2011C32.2379 19.2278 32.2207 19.2607 32.1995 19.2744C32.1783 19.288 32.1328 19.3254 32.0983 19.3574C31.9104 19.5321 31.8034 19.5776 31.6519 19.5472C31.6084 19.5384 31.5777 19.5584 31.4942 19.65C31.4373 19.7125 31.3742 19.7784 31.354 19.7964C31.2505 19.8888 31.1673 19.9444 31.1379 19.9407C31.1199 19.9385 31.0798 19.9653 31.0488 20.0004C30.88 20.191 30.7814 20.2888 30.7611 20.2859C30.7486 20.2841 30.7142 20.3117 30.6847 20.3471C30.6357 20.4062 30.5129 20.5024 30.2951 20.6523C30.2494 20.6838 30.1384 20.7264 30.0484 20.7471C29.8664 20.7889 29.686 20.8598 29.6495 20.9037C29.6364 20.9195 29.6181 20.9262 29.6088 20.9185C29.5995 20.9108 29.5616 20.9325 29.5246 20.9668C29.4875 21.0011 29.388 21.0676 29.3035 21.1146C29.219 21.1616 29.1265 21.2241 29.0981 21.2535C29.0696 21.2828 29.028 21.3068 29.0056 21.3067C28.9832 21.3066 28.9482 21.3266 28.9278 21.3512C28.751 21.5641 28.2993 21.8101 28.0377 21.836C27.8869 21.851 27.7802 21.8767 27.7429 21.9072C27.7108 21.9335 27.5929 21.998 27.4808 22.0506C27.3274 22.1226 27.2575 22.1699 27.198 22.2417C27.1545 22.2942 27.0876 22.3572 27.0494 22.3817C27.0112 22.4062 26.9201 22.4938 26.8471 22.5765C26.774 22.6591 26.7042 22.7326 26.6919 22.7397C26.6428 22.7682 26.4296 23.1044 26.4275 23.1566C26.4233 23.2615 26.3148 23.3258 26.2428 23.266C26.2318 23.2569 26.2299 22.9223 26.2403 22.835C26.2657 22.6208 26.2789 22.4552 26.273 22.4234C26.2603 22.3555 26.2832 21.8526 26.3 21.8324C26.309 21.8216 26.3041 21.8025 26.2891 21.79C26.2741 21.7776 26.2636 21.7191 26.2657 21.6602C26.2679 21.6013 26.2576 21.543 26.2427 21.5307C26.2279 21.5184 26.2287 21.4658 26.2444 21.4138C26.2602 21.3618 26.2805 21.2545 26.2896 21.1752C26.2987 21.096 26.319 20.9597 26.3348 20.8723C26.3629 20.7169 26.3394 20.2859 26.3011 20.2541C26.2403 20.2036 26.2305 19.965 26.2849 19.8604C26.316 19.8008 26.3643 19.6896 26.3923 19.6133C26.4204 19.5371 26.5115 19.3748 26.5948 19.2526C26.6782 19.1305 26.7649 18.9899 26.7877 18.9403C26.827 18.8544 26.8995 18.7202 26.9943 18.558C27.066 18.4352 27.0756 18.3583 27.0258 18.3063C26.9534 18.2306 27.0455 17.9064 27.1884 17.7343C27.2258 17.6893 27.2556 17.6384 27.2548 17.6212C27.2539 17.604 27.2956 17.5186 27.3474 17.4315C27.5392 17.109 27.6092 16.8303 27.5039 16.8084C27.4049 16.7878 27.4234 16.7113 27.5748 16.5168C27.6491 16.4212 27.7113 16.3334 27.7129 16.3216C27.7145 16.3098 27.791 16.1997 27.883 16.077C27.9749 15.9543 28.0627 15.8288 28.0782 15.7983C28.0936 15.7677 28.1406 15.6932 28.1826 15.6326C28.2719 15.5037 28.4286 15.2473 28.4557 15.1856C28.4704 15.1522 28.4607 15.1352 28.4114 15.1085C28.3184 15.058 28.3396 15.0157 28.5943 14.744C29.2355 14.0602 29.2718 14.0058 29.2419 13.7737L29.2224 13.6217L29.3406 13.5243C29.4789 13.4103 29.5474 13.3584 29.8216 13.1603C29.9333 13.0795 30.0392 12.9964 30.057 12.9755C30.0747 12.9547 30.1054 12.9363 30.1251 12.9345C30.1448 12.9328 30.2137 12.8771 30.2781 12.8108L30.3953 12.6902L30.2666 12.7095C30.1957 12.7201 30.1323 12.7348 30.1255 12.7422C30.1187 12.7495 30.1004 12.745 30.0849 12.7321C30.0693 12.7192 30.0452 12.7224 30.0312 12.7392C30.0172 12.7561 29.9398 12.7805 29.8592 12.7936C29.6042 12.835 29.4054 12.8639 29.3066 12.8739C29.254 12.8793 29.2033 12.8929 29.194 12.9042C29.1846 12.9154 29.1685 12.9176 29.1581 12.909C29.1477 12.9004 29.1321 12.902 29.1233 12.9126C29.0982 12.9428 28.3581 13.0019 28.3271 12.9762C28.2655 12.925 28.117 12.9794 28.0711 13.0699C27.9753 13.2587 27.8405 13.5718 27.8231 13.6461C27.8019 13.7365 27.5124 14.2012 27.2207 14.613C27.1418 14.7244 27.1043 14.797 27.1105 14.8265C27.1181 14.8627 27.109 14.8756 27.0626 14.8943C26.994 14.9219 26.8768 15.0933 26.8658 15.182C26.8596 15.2324 26.8475 15.2472 26.7948 15.2689C26.7598 15.2833 26.7151 15.3241 26.6953 15.3598C26.6278 15.4811 25.9829 16.4845 25.8293 16.7072C25.6736 16.9328 25.3714 17.4045 25.2422 17.6236C25.1597 17.7634 25.029 17.9721 24.9517 18.0874C24.8744 18.2027 24.81 18.3053 24.8086 18.3156C24.8072 18.3258 24.7461 18.4263 24.6728 18.539C24.5995 18.6517 24.5259 18.768 24.5092 18.7976C24.4606 18.8836 24.2019 19.3093 24.1715 19.3532C24.0959 19.4624 23.9632 19.6748 23.6914 20.1219C23.6213 20.2372 23.4939 20.4438 23.4084 20.581C23.3229 20.7182 23.2358 20.866 23.215 20.9094C23.1678 21.0073 23.1482 21.0411 22.8439 21.5478C22.7083 21.7736 22.5726 21.9884 22.5423 22.0252C22.512 22.0621 22.4686 22.1416 22.4457 22.202C22.4229 22.2623 22.3524 22.386 22.2891 22.4767C22.1831 22.6289 22.1771 22.6452 22.2121 22.6844C22.2331 22.7079 22.2907 22.8197 22.3401 22.9328C22.6002 23.5277 22.6396 23.6082 22.791 23.8539C22.8507 23.9507 22.9257 24.0846 22.9577 24.1515C22.9897 24.2184 23.0549 24.3296 23.1026 24.3986C23.1503 24.4677 23.2492 24.6159 23.3225 24.728C23.3957 24.8401 23.4957 24.9698 23.5447 25.0162C23.5937 25.0627 23.6764 25.1528 23.7286 25.2165C23.7807 25.2802 23.8547 25.3567 23.893 25.3864C23.9314 25.4162 23.9787 25.4687 23.9982 25.503C24.0741 25.6362 24.6145 26.0581 24.7349 26.078C24.7944 26.0878 24.8521 26.1025 24.8633 26.1106C24.8745 26.1188 24.9285 26.1514 24.9833 26.183C25.1597 26.2849 25.1198 26.5397 24.9262 26.5471C24.893 26.5483 24.8547 26.5627 24.841 26.5791C24.8274 26.5954 24.7767 26.6222 24.7285 26.6385C24.6802 26.6548 24.6451 26.6718 24.6503 26.6761C24.6806 26.7013 24.2728 26.7119 24.1898 26.6881C24.1349 26.6723 24.0352 26.6471 23.9682 26.6321C23.9012 26.617 23.7967 26.579 23.736 26.5475C23.6754 26.516 23.5421 26.4639 23.4398 26.4317C23.1216 26.3317 22.5747 25.9096 22.1278 25.4191C22.0271 25.3085 21.8829 25.1538 21.8075 25.0753C21.5962 24.8553 21.3223 24.461 21.3094 24.3582C21.2885 24.1917 21.4857 24.3273 21.6516 24.5935C21.7631 24.7725 21.8618 24.8968 21.9512 24.9711C22.0611 25.0624 22.5027 25.5164 22.514 25.5497C22.5287 25.5926 22.8599 25.8601 22.9802 25.926C23.0403 25.959 23.1298 26.0185 23.179 26.0583C23.2577 26.1218 23.5137 26.2445 23.5111 26.2175C23.5105 26.2119 23.2762 26.0061 22.9904 25.7601C22.2678 25.1382 21.685 24.4654 21.5806 24.1327C21.5197 23.9386 21.5637 23.9553 21.6955 24.1764C21.7468 24.2623 21.8143 24.3621 21.8456 24.3982C21.8769 24.4342 21.9111 24.4845 21.9215 24.5099C21.932 24.5352 21.973 24.5893 22.0127 24.6301C22.1515 24.7725 22.3145 24.9647 22.3216 24.9942C22.3335 25.0441 22.4309 25.1475 22.6598 25.3535C22.7801 25.4617 22.9968 25.6567 23.1415 25.787C23.2861 25.9172 23.4076 26.0332 23.4115 26.0446C23.4155 26.0561 23.4604 26.0784 23.5115 26.0942C23.5625 26.1101 23.6494 26.1604 23.7045 26.2062C23.7606 26.2528 23.8772 26.317 23.9694 26.3521C24.0599 26.3866 24.1955 26.4413 24.2705 26.4737C24.4549 26.5532 24.8073 26.505 24.9054 26.3868C24.927 26.3607 24.8817 26.2957 24.8417 26.2956C24.5842 26.2944 23.858 25.7469 23.6452 25.3935C23.6231 25.3569 23.5425 25.2642 23.4661 25.1875C23.3036 25.0245 23.1208 24.7847 23.1081 24.7179C23.1032 24.6921 23.0771 24.6445 23.0501 24.612C23.0231 24.5795 22.9347 24.4358 22.8538 24.2926C22.6828 23.99 22.6228 23.8889 22.588 23.8441C22.5741 23.8264 22.5416 23.762 22.5157 23.7011C22.4899 23.6402 22.4547 23.5741 22.4376 23.5542C22.4205 23.5343 22.4032 23.5033 22.3993 23.4853C22.3865 23.4275 22.113 22.8006 22.101 22.8016C22.0766 22.8038 21.6858 23.5135 21.4131 24.051C21.3419 24.1914 21.2007 24.4504 21.0994 24.6266C20.9022 24.9695 20.8643 25.0447 20.7701 25.28C20.7036 25.4462 20.7011 25.5421 20.762 25.5926C20.8115 25.6338 20.8429 26.0221 20.803 26.0999C20.7873 26.1303 20.7647 26.1896 20.7527 26.2317C20.7406 26.2737 20.7102 26.3617 20.685 26.4271C20.6598 26.4925 20.6392 26.5619 20.6393 26.5814C20.6394 26.6008 20.6216 26.6438 20.5997 26.6769C20.5779 26.71 20.5582 26.7503 20.556 26.7664C20.5538 26.7826 20.5137 26.8607 20.4669 26.9401C20.42 27.0194 20.3769 27.1082 20.3711 27.1374C20.3652 27.1666 20.3246 27.2408 20.2809 27.3024C20.2371 27.364 20.1617 27.4809 20.1132 27.5621C20.0647 27.6434 19.9445 27.8133 19.846 27.9397C19.4839 28.4044 19.3582 28.6155 19.3586 28.7585C19.3588 28.8068 19.338 28.8818 19.3124 28.9252C19.2868 28.9685 19.2618 29.0252 19.2568 29.0512C19.2518 29.0771 19.2261 29.1244 19.1997 29.1562C19.1717 29.1899 19.1445 29.2758 19.1344 29.3626C19.1248 29.4444 19.0972 29.5588 19.073 29.6168C19.0489 29.6748 19.0214 29.7625 19.012 29.8116C19.0027 29.8608 18.9452 29.9858 18.8844 30.0894C18.8235 30.1929 18.7688 30.2997 18.7627 30.3265C18.7395 30.4296 18.6856 30.5495 18.599 30.6902C18.5495 30.7706 18.4917 30.8646 18.4705 30.899C18.4494 30.9335 18.4078 30.9984 18.3781 31.0431C18.3484 31.0879 18.2858 31.1992 18.2389 31.2904C18.1921 31.3816 18.0897 31.5664 18.0114 31.7009C17.9331 31.8354 17.8582 31.9649 17.845 31.9886C17.8318 32.0124 17.7961 32.075 17.7656 32.1278C17.7352 32.1806 17.7026 32.2587 17.6932 32.3014C17.6839 32.3441 17.6475 32.4275 17.6125 32.4868C17.4193 32.8139 17.3209 33.0239 17.3031 33.1477C17.2986 33.1787 17.2626 33.2532 17.2229 33.3132C17.1833 33.3732 17.151 33.4393 17.1511 33.4601C17.1511 33.4809 17.127 33.5313 17.0975 33.5723C17.068 33.6132 17.0473 33.657 17.0516 33.6696C17.0615 33.6987 16.9958 33.9347 16.9529 34.0242C16.935 34.0614 16.9187 34.1357 16.9167 34.1892C16.9146 34.2428 16.8918 34.312 16.8659 34.3432C16.8348 34.3807 16.826 34.4171 16.84 34.4511C16.8516 34.4793 16.8543 34.5105 16.8461 34.5204C16.8318 34.5376 16.8399 34.6226 16.8837 34.916C16.9037 35.0501 17.0417 35.502 17.0698 35.5253C17.0785 35.5325 17.0888 35.5555 17.0926 35.5764C17.1079 35.6595 17.1674 35.8781 17.1978 35.9629C17.302 36.2535 17.3659 36.4459 17.3644 36.4645C17.3635 36.4762 17.3785 36.5098 17.3978 36.5393C17.4171 36.5688 17.4459 36.6372 17.4619 36.6914C17.4778 36.7456 17.5005 36.7979 17.5122 36.8077C17.524 36.8174 17.5411 36.8597 17.5503 36.9015C17.5669 36.9776 17.6178 37.1163 17.6991 37.3072C17.7229 37.363 17.7622 37.4607 17.7865 37.5243C17.8108 37.588 17.8417 37.6492 17.8551 37.6603C17.8686 37.6715 17.8937 37.7288 17.911 37.7876C17.9283 37.8465 17.9609 37.933 17.9835 37.9799C18.0061 38.0268 18.0325 38.1046 18.042 38.1527C18.0516 38.2007 18.0724 38.2509 18.0884 38.2642C18.1135 38.2851 18.1938 38.5113 18.2647 38.7616C18.2768 38.8042 18.2993 38.8495 18.3147 38.8623C18.3622 38.9017 18.4316 39.0996 18.4528 39.2555C18.4638 39.337 18.4874 39.4159 18.5053 39.4307C18.5231 39.4455 18.5355 39.4984 18.5329 39.5483C18.5303 39.5982 18.5434 39.6516 18.5619 39.667C18.5805 39.6824 18.5922 39.726 18.5881 39.7639C18.5839 39.8018 18.6022 39.8595 18.6287 39.8921C18.659 39.9294 18.6869 40.0408 18.7042 40.1926C18.7192 40.3253 18.7531 40.533 18.7794 40.6542C18.8057 40.7753 18.8219 40.8809 18.8153 40.8889C18.8086 40.8969 18.8178 40.9462 18.8356 40.9986C18.8534 41.0509 18.8621 41.1008 18.855 41.1094C18.8478 41.1181 18.8513 41.2345 18.8629 41.3682C18.8744 41.502 18.8799 41.616 18.8751 41.6218C18.8704 41.6275 18.8779 41.7584 18.8918 41.9127C18.9057 42.0669 18.9122 42.2532 18.9062 42.3266C18.9001 42.4 18.8958 42.5241 18.8965 42.6023C18.8972 42.6806 18.8926 42.7507 18.8864 42.7582C18.8802 42.7657 18.875 42.8323 18.8748 42.9063C18.8747 42.9803 18.8641 43.0534 18.8514 43.0687C18.8387 43.084 18.8326 43.1258 18.8379 43.1616C18.8432 43.1974 18.842 43.2334 18.8352 43.2415C18.8285 43.2496 18.8109 43.357 18.7961 43.4802C18.7814 43.6034 18.7575 43.7184 18.7431 43.7357C18.7287 43.7531 18.7208 43.7788 18.7256 43.7927C18.7303 43.8067 18.7144 43.876 18.6902 43.9467C18.666 44.0173 18.6259 44.1529 18.6012 44.248C18.519 44.564 18.2879 44.6871 18.2079 44.4576C18.1756 44.3648 18.1352 44.0846 18.1513 44.0647C18.1609 44.0528 18.1494 43.9166 18.0943 43.393C18.0841 43.2962 18.0595 43.1714 18.0395 43.1158C18.0196 43.0601 18.0007 42.996 17.9974 42.9733C17.9906 42.9254 17.9734 42.879 17.8756 42.6437C17.8362 42.5487 17.801 42.4563 17.7976 42.4383C17.786 42.3783 17.5738 41.8482 17.5418 41.7994C17.5087 41.7488 17.4079 41.506 17.3804 41.4104C17.3715 41.3795 17.3461 41.3391 17.3239 41.3207C17.3017 41.3023 17.249 41.21 17.2068 41.1156C16.9668 40.5784 16.7696 40.1666 16.7077 40.0728C16.6689 40.0141 16.5979 39.9099 16.5499 39.8412C16.5019 39.7725 16.449 39.6916 16.4324 39.6614C16.3919 39.5877 16.3692 39.5945 16.3347 39.6909C16.3188 39.7354 16.2532 39.8687 16.1889 39.987C16.1245 40.1053 16.0489 40.2547 16.0208 40.319C15.9619 40.4535 15.9162 40.5324 15.7518 40.7834C15.6867 40.8829 15.6321 40.9737 15.6305 40.9852C15.6289 40.9968 15.5407 41.1275 15.4344 41.2757C15.3282 41.4239 15.2392 41.5602 15.2367 41.5787C15.2341 41.5972 15.2128 41.6403 15.1892 41.6746C15.1656 41.7089 15.1307 41.7901 15.1117 41.855C15.0927 41.92 15.0494 42.0189 15.0155 42.0747C14.9816 42.1306 14.9574 42.1874 14.9617 42.2009C14.9659 42.2145 14.9497 42.2566 14.9256 42.2946C14.9015 42.3325 14.8545 42.4487 14.8213 42.5527C14.7881 42.6567 14.7401 42.785 14.7147 42.8379C14.6894 42.8908 14.6699 42.9812 14.6716 43.0387C14.6732 43.0963 14.6654 43.1658 14.6541 43.1933C14.5751 43.3866 14.567 43.656 14.6379 43.7332C14.6643 43.762 14.6748 43.8227 14.6669 43.9021C14.6602 43.9702 14.6669 44.0361 14.6817 44.0484C14.6966 44.0608 14.6993 44.0822 14.6879 44.096C14.6629 44.126 14.5474 44.1341 14.5447 44.1059C14.539 44.0473 14.3773 44.0509 14.3453 44.1104C14.2736 44.2435 14.1338 44.1019 14.1883 43.9514C14.196 43.9302 14.188 43.8829 14.1706 43.8462C14.066 43.6271 13.9829 43.4182 13.9722 43.3479C13.9654 43.3033 13.945 43.233 13.9269 43.1916C13.9087 43.1502 13.8804 42.9773 13.8639 42.8075C13.8315 42.475 13.8305 42.4508 13.8435 42.3045C13.8482 42.2514 13.8465 42.1521 13.8396 42.0838C13.8327 42.0156 13.8365 41.9362 13.8481 41.9075C13.8597 41.8787 13.8684 41.8093 13.8675 41.7532C13.8665 41.6972 13.8784 41.5625 13.8939 41.4539C13.9094 41.3453 13.9269 41.1911 13.9329 41.1113C13.9388 41.0314 13.9564 40.9396 13.972 40.9071C13.9876 40.8747 14.0041 40.7777 14.0088 40.6915C14.0166 40.546 14.0582 40.3573 14.1282 40.1498C14.1442 40.1024 14.1777 40.0024 14.2027 39.9277C14.2859 39.6782 14.3253 39.582 14.3449 39.5803C14.3556 39.5793 14.3566 39.5507 14.3471 39.5167C14.3284 39.4493 14.1838 39.452 14.1264 39.5208C14.1126 39.5372 14.0411 39.5631 13.9675 39.5781C13.8939 39.5932 13.8259 39.6146 13.8165 39.6258C13.7788 39.6704 13.6264 39.7189 13.4918 39.7291C13.3221 39.742 13.2822 39.762 13.2779 39.8362C13.2761 39.8669 13.2651 39.8953 13.2533 39.8992C13.2416 39.9031 13.2174 39.9483 13.1995 39.9997C13.1817 40.0511 13.143 40.1441 13.1136 40.2065C13.0841 40.2688 13.0569 40.3455 13.053 40.377C13.0491 40.4085 13.0036 40.5197 12.9518 40.6243C12.8402 40.8497 12.7572 41.0443 12.6538 41.3233C12.612 41.4361 12.5401 41.6177 12.494 41.727C12.1631 42.5111 12.0824 42.7238 11.9801 43.0828C11.9571 43.1634 11.8564 43.4815 11.7943 43.67C11.7741 43.7313 11.7345 43.8712 11.7063 43.9808C11.6781 44.0905 11.6408 44.2085 11.6233 44.2431C11.6058 44.2778 11.5595 44.4357 11.5205 44.5941C11.4814 44.7526 11.4344 44.9123 11.4159 44.949C11.3975 44.9858 11.3834 45.0386 11.3847 45.0664C11.3859 45.0942 11.3631 45.1888 11.334 45.2767C11.3048 45.3646 11.2646 45.508 11.2446 45.5955C11.2246 45.683 11.1937 45.7725 11.1759 45.7944C11.1582 45.8162 11.1302 45.9007 11.1138 45.9822C11.0973 46.0637 11.0623 46.1679 11.0358 46.2138C11.0094 46.2597 10.968 46.3803 10.9437 46.4818C10.9195 46.5833 10.8764 46.7037 10.848 46.7493C10.7576 46.8945 10.743 46.9303 10.749 46.992C10.7564 47.0683 10.7322 47.3262 10.7158 47.3459C10.7091 47.3541 10.6942 47.4011 10.6828 47.4503C10.6556 47.5684 10.5305 47.7464 10.4527 47.7777C10.4195 47.791 10.3866 47.819 10.3796 47.8399C10.3727 47.8607 10.3547 47.876 10.3397 47.8738C10.3248 47.8717 10.2996 47.8855 10.2838 47.9046C10.2679 47.9237 10.2463 47.9368 10.2357 47.9338C10.2041 47.9248 9.99992 47.9781 9.98164 48.0001C9.97235 48.0113 9.93757 48.0129 9.90435 48.0038C9.78322 47.9704 9.74705 47.6316 9.85119 47.5057C9.90773 47.4372 9.8741 47.3802 9.78375 47.3914C9.67739 47.4046 9.61824 47.341 9.63898 47.2358C9.71037 46.8737 10.0171 46.2451 10.2299 46.0247C10.3656 45.8843 10.4174 45.7924 10.5245 45.5023C10.5637 45.3961 10.6333 45.2267 10.6792 45.126C10.725 45.0252 10.7629 44.9289 10.7633 44.9119C10.7644 44.8682 11.0299 44.2078 11.0619 44.1693C11.0764 44.1518 11.0869 44.1228 11.0852 44.1049C11.0834 44.087 11.1096 44.0131 11.1433 43.9408C11.177 43.8685 11.2138 43.7641 11.225 43.7089C11.2362 43.6536 11.2829 43.5118 11.3287 43.3938C11.3746 43.2757 11.4239 43.1392 11.4384 43.0904C11.4528 43.0417 11.4843 42.9684 11.5083 42.9277C11.5324 42.8869 11.5641 42.8039 11.5788 42.7432C11.5935 42.6825 11.6169 42.6192 11.6308 42.6025C11.6447 42.5858 11.679 42.5035 11.707 42.4197C11.7349 42.3358 11.8049 42.1643 11.8624 42.0385C11.9199 41.9128 11.9765 41.7823 11.9882 41.7487C11.9999 41.715 12.0324 41.6523 12.0603 41.6092C12.0882 41.5662 12.1113 41.5143 12.1115 41.494C12.1117 41.4736 12.1304 41.4227 12.153 41.3807C12.1756 41.3387 12.2442 41.204 12.3054 41.0813C12.533 40.625 12.7548 40.217 12.8548 40.0705C13.0602 39.7696 13.1201 39.6598 13.0918 39.6362C13.0216 39.5779 12.9057 39.7047 12.7329 40.0286C12.6809 40.126 12.6277 40.2093 12.6147 40.2136C12.6017 40.2179 12.5619 40.2737 12.5262 40.3376C12.4203 40.5275 12.1261 41.0174 12.0662 41.1035C12.0356 41.1475 11.9847 41.233 11.953 41.2935C11.9214 41.354 11.8843 41.4225 11.8705 41.4459C11.8568 41.4692 11.8309 41.5257 11.813 41.5716C11.7779 41.6615 11.6516 41.9282 11.62 41.9793C11.6094 41.9965 11.5927 42.0394 11.583 42.0747C11.5732 42.1099 11.4959 42.2754 11.4112 42.4423C11.3266 42.6093 11.2427 42.7952 11.2248 42.8554C11.207 42.9157 11.1653 43.0277 11.1322 43.1043C11.099 43.1809 11.0676 43.2646 11.0623 43.2903C11.0569 43.3161 11.0418 43.3501 11.0286 43.366C11.0154 43.3819 11.001 43.4277 10.9966 43.4678C10.9922 43.5079 10.9654 43.5667 10.9369 43.5986C10.9085 43.6304 10.8719 43.7073 10.8557 43.7695C10.8394 43.8317 10.8087 43.8986 10.7875 43.9183C10.7662 43.9379 10.7463 43.9869 10.7432 44.027C10.74 44.0671 10.7247 44.1153 10.7091 44.1341C10.6936 44.1528 10.6737 44.2006 10.665 44.2402C10.6563 44.2798 10.6245 44.3547 10.5943 44.4065C10.5642 44.4584 10.5324 44.5405 10.5237 44.589C10.515 44.6375 10.4799 44.723 10.4458 44.7789C10.4116 44.8348 10.3831 44.8943 10.3823 44.911C10.3815 44.9277 10.3647 44.9706 10.345 45.0062C10.3253 45.0419 10.2873 45.1168 10.2606 45.1728C10.234 45.2287 10.1835 45.3217 10.1485 45.3794C10.1135 45.4371 10.0771 45.5205 10.0677 45.5647C10.0582 45.6089 10.024 45.6868 9.99166 45.7379C9.95787 45.7912 9.93765 45.8549 9.94412 45.8877C9.96053 45.9708 9.93356 46.1326 9.87872 46.2801C9.85234 46.351 9.81049 46.486 9.78571 46.58C9.74274 46.743 9.69143 46.8298 9.52745 47.017C9.42498 47.1339 9.25296 47.0783 9.17734 46.9037C9.09276 46.7085 9.41777 46.0769 9.6776 45.9316C9.78064 45.8739 9.90074 45.683 9.93357 45.5247C9.9389 45.499 9.95849 45.4597 9.9771 45.4372C10.0237 45.3812 10.2016 45.0014 10.3532 44.6344C10.4226 44.4664 10.4953 44.2926 10.5149 44.2481C10.5344 44.2036 10.5636 44.1284 10.5796 44.081C10.5957 44.0336 10.6277 43.9537 10.6509 43.9035C10.7504 43.6875 10.8198 43.5306 10.855 43.442C10.8757 43.3898 10.9265 43.2687 10.9679 43.1729C11.0092 43.0771 11.061 42.9427 11.083 42.8742C11.1049 42.8056 11.1498 42.6938 11.1826 42.6256C11.2154 42.5574 11.2777 42.4246 11.321 42.3304C11.3643 42.2362 11.432 42.1007 11.4713 42.0292C11.5106 41.9578 11.5683 41.8353 11.5995 41.7571C11.6665 41.5889 11.7743 41.3591 11.8498 41.2236C11.9633 41.0199 11.9803 40.9835 11.9723 40.9602C11.9615 40.9283 11.9311 40.9669 11.8886 41.0667C11.854 41.148 11.6732 41.4673 11.4816 41.7854C11.4259 41.878 11.3691 41.9941 11.3555 42.0435C11.3418 42.0928 11.3192 42.1521 11.3052 42.1753C11.1589 42.417 11.1092 42.5064 11.0904 42.5619C11.0782 42.5978 11.052 42.6452 11.032 42.6671C10.9838 42.7202 10.8706 42.9349 10.8686 42.977C10.8678 42.9953 10.8284 43.0777 10.7812 43.16C10.5458 43.5705 10.417 43.8243 10.3617 43.9867C10.3292 44.0823 10.2965 44.1347 10.2357 44.1889C10.1791 44.2393 10.1464 44.2884 10.1307 44.3464C10.1182 44.3928 10.0824 44.4735 10.0513 44.5257C10.0201 44.5779 9.9775 44.6728 9.95664 44.7365C9.93577 44.8003 9.88684 44.9017 9.84789 44.9617C9.80894 45.0218 9.74411 45.143 9.70381 45.231C9.55653 45.5527 9.21571 46.2075 9.06617 46.456C9.02711 46.521 8.99048 46.597 8.98476 46.6251C8.96984 46.6982 8.87338 46.9197 8.83778 46.9626C8.80652 47.0002 8.72823 47.1783 8.67698 47.3283C8.66081 47.3756 8.59986 47.5095 8.54154 47.626C8.32586 48.0565 8.31917 48.0825 8.3275 48.4578C8.34112 49.0713 8.11226 49.5258 7.56948 49.9633C7.44289 50.0653 7.22646 49.9425 7.18495 49.7451L7.18499 49.7447ZM7.39628 49.3011C7.406 49.2788 7.45364 49.1658 7.50216 49.0499C7.63073 48.7428 7.76132 48.4891 7.84708 48.3799C7.8868 48.3293 7.93631 48.3182 7.9199 48.3635C7.89657 48.428 7.93757 48.4118 7.98894 48.3363C8.03662 48.2661 8.03585 48.1836 7.98756 48.1879C7.95479 48.1908 7.68476 48.4815 7.64679 48.5548C7.54265 48.7557 7.41929 49.0204 7.40294 49.0779C7.35565 49.2442 7.34395 49.3129 7.36056 49.3267C7.37049 49.3349 7.38657 49.3234 7.39628 49.3011ZM7.5747 49.2145C7.5902 49.1526 7.59013 49.1269 7.57455 49.1573C7.52709 49.2501 7.49658 49.3579 7.52227 49.3421C7.53561 49.3338 7.5592 49.2764 7.5747 49.2145ZM7.8386 49.3347C7.89674 49.2329 7.9724 49.0779 8.00671 48.9902C8.05218 48.8741 8.07695 48.8339 8.09795 48.8421C8.14828 48.8619 8.17706 48.7926 8.15698 48.7C8.13408 48.5944 8.12669 48.6005 8.05382 48.785C8.0233 48.8623 7.9336 49.0597 7.85446 49.2237C7.69048 49.5635 7.68465 49.6043 7.8386 49.3347ZM7.33662 48.9964C7.35217 48.9545 7.35724 48.9138 7.34789 48.906C7.32443 48.8865 7.31653 48.9 7.29631 48.9939C7.27429 49.0961 7.2991 49.0977 7.33662 48.9964ZM7.91598 48.8569C7.98073 48.7026 8.06773 48.5146 8.10932 48.4392C8.15889 48.3493 8.17864 48.2859 8.16668 48.2552C8.13101 48.1636 8.09812 48.2108 7.97614 48.5285C7.94583 48.6074 7.8702 48.7996 7.80807 48.9556C7.65653 49.336 7.75137 49.2493 7.91598 48.8569ZM7.69717 48.9248C7.73885 48.8397 7.78017 48.7476 7.78899 48.7202C7.79781 48.6928 7.82224 48.6387 7.84328 48.6C7.86432 48.5613 7.87767 48.5182 7.87295 48.5044C7.86101 48.4693 7.77241 48.6218 7.74988 48.7162C7.73984 48.7582 7.72044 48.806 7.70678 48.8224C7.67785 48.8569 7.59376 49.0822 7.61027 49.0807C7.61638 49.0802 7.65549 49.01 7.69717 48.9248ZM7.43581 48.7818C7.44764 48.7526 7.47084 48.6902 7.48736 48.6432L7.51738 48.5577L7.43724 48.6516C7.35297 48.7502 7.34473 48.7772 7.38792 48.813C7.40669 48.8286 7.42052 48.8196 7.43581 48.7818ZM8.31922 47.8748C8.34862 47.8255 8.38273 47.7479 8.39501 47.7025C8.40729 47.6571 8.44883 47.5638 8.48731 47.4952C8.5258 47.4266 8.55613 47.3561 8.55471 47.3384C8.55329 47.3207 8.5662 47.2889 8.58342 47.2676C8.62751 47.2131 8.67732 47.0092 8.63502 47.0564C8.61719 47.0764 8.59528 47.1272 8.58633 47.1695C8.57738 47.2118 8.55006 47.2704 8.52562 47.2999C8.50118 47.3293 8.46658 47.3948 8.44872 47.4454C8.40539 47.5682 8.34368 47.7019 8.2828 47.8049C8.22548 47.9018 8.21936 47.926 8.24639 47.9484C8.25858 47.9585 8.28558 47.9313 8.31922 47.8748ZM6.89255 46.1064C6.93415 46.0412 6.99023 45.9541 7.01718 45.9129C7.04412 45.8718 7.07613 45.8087 7.08831 45.7728C7.10049 45.7368 7.12703 45.6875 7.14729 45.6631C7.23042 45.563 7.12456 45.5262 7.0006 45.6121C6.89513 45.6852 6.6562 46.06 6.69469 46.0919C6.70334 46.0991 6.73104 46.056 6.75624 45.9961C6.8053 45.8795 6.93054 45.714 6.97259 45.7103C6.98664 45.7091 6.97076 45.761 6.9373 45.8256C6.74785 46.1917 6.71778 46.3804 6.89255 46.1064ZM7.62251 45.9869C7.64747 45.9252 7.67216 45.8527 7.67738 45.8258C7.69861 45.7164 7.9088 45.3649 7.93835 45.3894C7.94837 45.3978 7.93778 45.4493 7.91481 45.504C7.89184 45.5587 7.86861 45.6139 7.86319 45.6268C7.85776 45.6396 7.89088 45.6063 7.93677 45.5527C8.0322 45.4412 8.06382 45.3117 7.9957 45.3114C7.97358 45.3113 7.94598 45.2993 7.93437 45.2847C7.90618 45.2493 7.77736 45.4205 7.7531 45.5256C7.74348 45.5673 7.71117 45.658 7.68128 45.7272C7.62032 45.8684 7.55454 46.0803 7.56819 46.0917C7.57311 46.0958 7.59756 46.0486 7.62251 45.9869ZM10.0716 47.5505L10.1326 47.4482L10.0522 47.5021C10.008 47.5318 9.96562 47.5711 9.95802 47.5895C9.90983 47.7064 9.90992 47.7086 9.96156 47.68C9.98852 47.6651 10.038 47.6068 10.0716 47.5505ZM10.1835 47.8232C10.2179 47.812 10.2335 47.7962 10.2275 47.7786C10.2224 47.7637 10.2706 47.6909 10.3346 47.6169C10.3985 47.5428 10.4528 47.4677 10.4553 47.4498C10.4577 47.4319 10.4893 47.4084 10.5255 47.3974C10.583 47.38 10.5903 47.3717 10.5827 47.3323C10.5722 47.2773 10.5589 47.2843 10.4082 47.4247C10.1147 47.6979 10.0126 47.879 10.1835 47.8232ZM8.64173 46.2399C8.6806 46.1931 8.73396 46.1132 8.76033 46.0623C8.78669 46.0115 8.85207 45.8973 8.90562 45.8087C9.06666 45.5422 9.1387 45.2644 9.02589 45.3449C8.99887 45.3642 8.9772 45.3625 8.96456 45.3401C8.91275 45.2485 8.73189 45.4471 8.67711 45.6559C8.64079 45.7943 8.66738 45.7691 8.76438 45.5731C8.8348 45.4308 8.91692 45.3645 8.90383 45.4605C8.90032 45.4863 8.91832 45.4822 8.96172 45.4472C9.04599 45.3792 9.04781 45.4331 8.96568 45.5642C8.89698 45.6739 8.83681 45.781 8.72545 45.9918C8.66363 46.1088 8.6524 46.1203 8.60307 46.117C8.55119 46.1136 8.54845 46.1176 8.54235 46.2047C8.53352 46.3305 8.55901 46.3395 8.64173 46.2399ZM9.53373 46.7988C9.56482 46.7521 9.60841 46.6722 9.6306 46.6212C9.65279 46.5702 9.68353 46.5034 9.69892 46.4728C9.71431 46.4422 9.72955 46.3839 9.73279 46.3432C9.73603 46.3025 9.75757 46.2246 9.78064 46.17C9.82309 46.0696 9.80515 46.0159 9.74107 46.0516C9.72181 46.0623 9.70179 46.0918 9.69657 46.1172C9.68651 46.166 9.6096 46.382 9.56039 46.4998C9.54423 46.5384 9.54171 46.5789 9.55479 46.5898C9.58114 46.6116 9.57804 46.6825 9.54918 46.7182C9.5389 46.7309 9.52194 46.7259 9.51123 46.707C9.48722 46.6645 9.48346 46.6691 9.44889 46.7832C9.41332 46.9007 9.46016 46.9093 9.53373 46.7988ZM9.3715 46.6821C9.41034 46.6083 9.50965 46.3788 9.50459 46.3746C9.48011 46.3542 9.3607 46.5445 9.34583 46.6275C9.32359 46.7517 9.32891 46.763 9.3715 46.6821ZM9.96574 47.1125C10.0062 47.0281 10.0444 46.8924 10.0198 46.9202C9.98178 46.9631 9.90545 47.1491 9.92065 47.1618C9.92906 47.1688 9.94936 47.1466 9.96574 47.1125ZM10.4771 46.9641C10.6542 46.8217 10.7352 46.6992 10.7947 46.4836C10.8103 46.4271 10.8558 46.2945 10.8958 46.1889C10.9358 46.0833 10.9689 45.983 10.9694 45.9661C10.9699 45.9491 10.9937 45.8804 11.0224 45.8134C11.0696 45.7028 11.145 45.4463 11.1809 45.2741C11.1886 45.2371 11.2112 45.1658 11.2312 45.1156C11.2512 45.0655 11.2743 44.9924 11.2826 44.9532C11.2909 44.9141 11.3053 44.8727 11.3147 44.8612C11.3242 44.8498 11.3361 44.7947 11.3413 44.739C11.3464 44.6832 11.3699 44.5836 11.3935 44.5176C11.417 44.4517 11.4575 44.316 11.4835 44.216C11.6426 43.6032 11.6444 43.5971 11.8098 43.1146C11.8724 42.9323 11.9296 42.7597 11.937 42.7312C11.9498 42.6823 12.0886 42.3382 12.2421 41.975C12.2801 41.885 12.321 41.777 12.333 41.7349C12.345 41.6928 12.3735 41.6242 12.3963 41.5824C12.4191 41.5406 12.4383 41.4927 12.439 41.4759C12.4409 41.4312 12.7045 40.7887 12.8012 40.5935C12.9708 40.2509 12.8937 40.2657 12.7144 40.6102C12.5968 40.8361 12.5827 40.8642 12.4269 41.1819C12.3725 41.2929 12.2878 41.4639 12.2386 41.5619C12.0393 41.9592 11.755 42.6177 11.7272 42.7463C11.7116 42.8181 11.6587 42.9374 11.5969 43.0402C11.5847 43.0604 11.5565 43.1435 11.5342 43.2248C11.4744 43.443 11.3027 43.9172 11.2687 43.9581C11.2524 43.9777 11.243 44.0049 11.2477 44.0187C11.2524 44.0325 11.2396 44.076 11.2192 44.1153C11.1988 44.1545 11.1552 44.2708 11.1223 44.3736C11.0894 44.4764 11.0301 44.633 10.9904 44.7215C10.9507 44.8101 10.9114 44.9051 10.9029 44.9328C10.8944 44.9605 10.8354 45.1103 10.7719 45.2657C10.7083 45.4212 10.6397 45.5914 10.6195 45.644C10.5993 45.6966 10.5625 45.7824 10.5377 45.8347C10.5105 45.8919 10.4938 46.003 10.4958 46.1143C10.4976 46.2159 10.4924 46.3294 10.4841 46.3666C10.4759 46.4037 10.4671 46.4821 10.4646 46.5408C10.4604 46.6413 10.3311 47.0038 10.2757 47.0705C10.2144 47.1444 10.327 47.0849 10.4771 46.9641ZM9.27473 45.482C9.29167 45.4395 9.35939 45.3217 9.42521 45.2202C9.49103 45.1186 9.57184 44.987 9.60479 44.9276C9.63774 44.8682 9.71044 44.744 9.76637 44.6516C9.8223 44.5592 9.87258 44.4633 9.87814 44.4385C9.88369 44.4136 9.9235 44.3331 9.9666 44.2595C10.148 43.9498 10.1719 43.905 10.1819 43.8548C10.1877 43.8258 10.2587 43.702 10.3397 43.5795C10.4207 43.4571 10.5098 43.2969 10.5378 43.2236C10.5658 43.1502 10.6111 43.0634 10.6383 43.0305C10.6656 42.9977 10.7213 42.8961 10.7621 42.8048C10.8029 42.7135 10.8662 42.6027 10.9028 42.5588C10.9393 42.5148 10.9738 42.4579 10.9793 42.4324C10.9967 42.3527 11.1002 42.1294 11.1442 42.0764C11.1673 42.0485 11.1934 41.9933 11.2021 41.9537C11.2199 41.8727 11.2841 41.7599 11.3935 41.6173C11.4342 41.5643 11.4681 41.503 11.4688 41.481C11.4696 41.4591 11.5078 41.3914 11.5536 41.3306C11.7581 41.0596 11.9426 40.7534 12.0578 40.494C12.0865 40.4295 12.1281 40.3549 12.1502 40.3282C12.1724 40.3016 12.2003 40.2479 12.2123 40.209C12.2243 40.1702 12.2969 40.0414 12.3737 39.923C12.5319 39.679 12.5741 39.6013 12.5893 39.5259C12.5951 39.4968 12.6295 39.4486 12.6658 39.4186C12.731 39.3647 12.731 39.3636 12.6644 39.3183C12.5983 39.2732 12.5961 39.2739 12.5324 39.3607C12.4968 39.4092 12.3983 39.5404 12.3136 39.6522C12.2289 39.764 12.1408 39.8863 12.1178 39.924C11.9329 40.2271 11.8558 40.3402 11.7612 40.447C11.6086 40.6192 11.3259 41.0172 11.325 41.0611C11.3246 41.0812 11.3131 41.1071 11.2994 41.1187C11.2858 41.1304 11.2557 41.1739 11.2325 41.2154C11.2094 41.2569 11.1718 41.3207 11.149 41.357C11.1262 41.3934 11.106 41.4343 11.1041 41.4479C11.1023 41.4615 11.0504 41.5364 10.9888 41.6144C10.9273 41.6924 10.8502 41.8191 10.8174 41.8961C10.7466 42.0624 10.6097 42.3245 10.5185 42.4682C10.4825 42.525 10.4329 42.6045 10.4084 42.6449C10.3839 42.6853 10.3312 42.7622 10.2913 42.8158C10.2515 42.8695 10.1936 42.9703 10.1626 43.0398C10.1317 43.1093 10.0966 43.1694 10.0845 43.1734C10.0724 43.1774 10.0625 43.1978 10.0624 43.2187C10.0624 43.2396 10.044 43.2841 10.0217 43.3176C9.99928 43.3511 9.97995 43.3924 9.9787 43.4094C9.97434 43.469 9.84345 43.7204 9.69466 43.9549C9.66721 43.9982 9.64292 44.047 9.6407 44.0633C9.63847 44.0796 9.61532 44.127 9.58925 44.1686C9.56318 44.2102 9.53758 44.262 9.53235 44.2837C9.52713 44.3054 9.495 44.3601 9.46095 44.4054C9.4269 44.4506 9.38396 44.5288 9.36552 44.5792C9.34708 44.6295 9.30155 44.7198 9.26434 44.7798C9.17296 44.9272 9.13822 45.0802 9.18249 45.1404C9.24093 45.2199 9.25494 45.3415 9.22042 45.4698C9.18534 45.6002 9.22412 45.6089 9.27473 45.482ZM4.37421 38.026C4.40928 37.9871 4.46767 37.9389 4.50397 37.9188C4.54027 37.8987 4.67254 37.7672 4.79791 37.6265C4.92327 37.4858 5.06293 37.3377 5.10825 37.2972C5.15359 37.2568 5.20309 37.2127 5.21825 37.1993C5.23342 37.1859 5.31528 37.1121 5.40017 37.0354C5.48505 36.9587 5.58004 36.8882 5.61124 36.8788C5.64245 36.8693 5.71492 36.8157 5.77227 36.7595C5.93284 36.6024 6.14872 36.4768 6.14516 36.5427C6.14279 36.5867 6.14708 36.5912 6.17433 36.5735C6.1919 36.562 6.25052 36.5255 6.30461 36.4923C6.47635 36.387 6.51109 36.3525 6.51907 36.2795C6.52523 36.223 6.53483 36.2096 6.57206 36.2053C6.59706 36.2024 6.62464 36.1918 6.63336 36.1817C6.65492 36.1567 6.85617 36.0067 6.9237 35.9653C6.95376 35.9469 7.00238 35.9131 7.03174 35.8903C7.06111 35.8674 7.11757 35.847 7.15721 35.8449C7.19685 35.8428 7.22835 35.8315 7.22721 35.8198C7.22607 35.8081 7.26691 35.7817 7.31797 35.7612C7.36902 35.7407 7.41638 35.7172 7.4232 35.709C7.43002 35.7008 7.46838 35.6841 7.50844 35.672C7.54849 35.6599 7.59077 35.6423 7.60238 35.6328C7.71986 35.5373 8.19942 35.3209 8.23262 35.3485C8.24133 35.3557 8.26999 35.3479 8.2963 35.3311C8.35764 35.292 8.52058 35.2415 8.53866 35.256C8.5591 35.2724 8.4686 35.3183 8.3149 35.3695C8.08601 35.4458 7.69495 35.625 7.61192 35.6916C7.57438 35.7218 7.41977 35.8012 7.35871 35.8217C7.25955 35.855 7.00835 35.9786 6.98668 36.0047C6.97354 36.0205 6.93813 36.0434 6.908 36.0555C6.85995 36.0748 6.73491 36.1871 6.74868 36.1985C6.75872 36.2069 7.03528 36.0705 7.17308 35.9893C7.29951 35.9148 7.41319 35.8744 7.3784 35.9163C7.34878 35.9519 7.17879 36.0526 7.01196 36.1332C6.81906 36.2265 6.65082 36.3307 6.24492 36.6086C6.19043 36.6459 6.13493 36.6801 6.12158 36.6845C6.08839 36.6955 5.8078 36.9217 5.73424 36.9967C5.56158 37.1729 5.42783 37.3013 5.39062 37.3266C5.29478 37.3919 5.42893 37.3464 5.56653 37.267C5.64642 37.2209 5.75749 37.1643 5.81334 37.1413C6.02248 37.055 6.16415 36.9871 6.24689 36.9334C6.29381 36.903 6.40522 36.8496 6.49447 36.8149C6.62389 36.7645 6.88325 36.6276 6.90983 36.5956C6.91276 36.592 6.90243 36.5786 6.88689 36.5657C6.83582 36.5233 6.91098 36.4756 7.27653 36.3186C7.59138 36.1834 7.76854 36.0919 7.97757 35.9564C8.02576 35.9252 8.41952 35.7951 8.46633 35.7949C8.47673 35.7949 8.5262 35.7756 8.57625 35.7521C8.62631 35.7286 8.74184 35.6874 8.83299 35.6604C8.92414 35.6335 9.04041 35.5916 9.09137 35.5674C9.19378 35.5186 9.57047 35.4105 9.68545 35.3968C9.7258 35.3919 9.76268 35.3834 9.7674 35.3777C9.78194 35.3602 10.1064 35.2734 10.1565 35.2737C10.1825 35.2738 10.2108 35.2654 10.2194 35.255C10.228 35.2447 10.339 35.2189 10.466 35.1976C10.593 35.1764 10.7973 35.1331 10.92 35.1013C11.0426 35.0695 11.1683 35.0389 11.1993 35.0332C11.3542 35.0049 12.0293 34.8158 12.6746 34.6201C12.891 34.5545 12.908 34.5486 13.108 34.4691C13.1743 34.4428 13.2831 34.4054 13.3499 34.386C13.4166 34.3667 13.5077 34.3315 13.5522 34.3077C13.5968 34.284 13.6995 34.2416 13.7806 34.2134C13.8616 34.1852 13.9349 34.1539 13.9435 34.1436C13.9615 34.1222 14.2642 33.9596 14.3512 33.9246C14.3833 33.9116 14.4369 33.8809 14.4704 33.8562C14.5039 33.8316 14.6374 33.7362 14.767 33.6443C14.8967 33.5524 15.0314 33.4529 15.0664 33.4232C15.2175 33.2952 15.3234 33.32 15.2068 33.4561C15.1681 33.5013 15.1365 33.5577 15.1366 33.5815C15.1367 33.6053 15.1149 33.641 15.0881 33.6609C15.0613 33.6808 15.0234 33.7128 15.0037 33.7321C14.9841 33.7513 14.9566 33.7711 14.9426 33.7759C14.9286 33.7808 14.8996 33.8057 14.8782 33.8313C14.8213 33.8995 14.5112 34.1179 14.3853 34.1786C14.3255 34.2074 14.2221 34.2557 14.1554 34.286C14.0887 34.3163 14.0265 34.3498 14.017 34.3604C14.0076 34.371 13.9556 34.3997 13.9015 34.4242C13.8474 34.4487 13.7905 34.4832 13.7751 34.5011C13.7597 34.5189 13.7275 34.5418 13.7035 34.552C13.6795 34.5623 13.6004 34.5994 13.5278 34.6345C13.1832 34.8011 12.8661 34.9339 12.6692 34.9942C12.6311 35.0059 12.5602 35.0323 12.5118 35.0528C12.3223 35.1331 11.9977 35.2253 11.9739 35.2056C11.9562 35.1908 12.14 35.1144 12.3664 35.0425C12.7893 34.9082 13.8579 34.4038 13.8078 34.3622C13.8035 34.3586 13.7271 34.3907 13.6381 34.4336C13.5491 34.4764 13.4476 34.5164 13.4127 34.5225C13.3462 34.534 13.2935 34.5522 13.1285 34.6207C13.0738 34.6435 13.0215 34.6557 13.0122 34.648C13.0028 34.6402 12.9806 34.6516 12.9626 34.6731C12.9447 34.6947 12.876 34.7171 12.8099 34.7229C12.7438 34.7288 12.683 34.7415 12.6749 34.7513C12.6595 34.7698 12.4588 34.8548 12.4271 34.8562C12.4172 34.8566 12.3669 34.8684 12.3155 34.8823C12.2641 34.8962 12.2182 34.8962 12.2134 34.8824C12.2087 34.8686 12.194 34.8704 12.1807 34.8864C12.1674 34.9024 12.1274 34.9181 12.0917 34.9213C12.056 34.9244 11.9493 34.9565 11.8546 34.9926C11.7599 35.0287 11.6765 35.0533 11.6693 35.0473C11.6621 35.0413 11.62 35.0491 11.5759 35.0648C11.4948 35.0935 11.258 35.1407 11.1309 35.1534C11.093 35.1573 11.0537 35.1703 11.0436 35.1825C11.0335 35.1947 10.9834 35.2021 10.9323 35.199C10.8812 35.1959 10.802 35.2106 10.7562 35.2317C10.7104 35.2527 10.6078 35.2782 10.5282 35.2883C10.3345 35.3129 10.319 35.3162 10.2386 35.35C10.2004 35.366 10.1631 35.374 10.1556 35.3678C10.1481 35.3616 10.12 35.3726 10.0931 35.3921C10.0662 35.4117 9.96925 35.4404 9.87762 35.4558C9.78598 35.4713 9.70245 35.4942 9.69199 35.5068C9.68153 35.5194 9.66331 35.5264 9.6515 35.5224C9.6397 35.5183 9.54364 35.5435 9.43804 35.5782C9.33245 35.6129 9.22196 35.6489 9.19252 35.6583C9.16308 35.6676 9.09435 35.693 9.03978 35.7146C8.98522 35.7363 8.89015 35.7609 8.82852 35.7693C8.7669 35.7777 8.6754 35.8102 8.62519 35.8415C8.57498 35.8728 8.51415 35.8977 8.48999 35.8969C8.46584 35.8962 8.43934 35.9036 8.43111 35.9135C8.42287 35.9235 8.37855 35.9337 8.33262 35.9363C8.28668 35.9389 8.23918 35.953 8.22705 35.9676C8.21493 35.9822 8.17515 36.007 8.13865 36.0228C8.01018 36.0782 7.85463 36.1562 7.75002 36.2176C7.69188 36.2518 7.63653 36.2732 7.62703 36.2653C7.61752 36.2574 7.59734 36.2659 7.58218 36.2842C7.56702 36.3024 7.52916 36.3242 7.49805 36.3326C7.3926 36.3611 7.23976 36.4244 7.24118 36.439C7.24285 36.4562 7.51636 36.3777 7.60838 36.3336C7.64355 36.3167 7.67943 36.3088 7.68813 36.3161C7.69683 36.3233 7.71388 36.3172 7.72602 36.3026C7.73816 36.288 7.78739 36.2686 7.83543 36.2594C7.88347 36.2502 8.03894 36.2043 8.18091 36.1574C8.67368 35.9944 9.23081 35.8624 9.12924 35.9326C9.1017 35.9517 9.04238 35.9705 8.99742 35.9745C8.95246 35.9784 8.90592 35.9934 8.89399 36.0078C8.88207 36.0221 8.84585 36.0316 8.81351 36.0288C8.78116 36.026 8.71609 36.0438 8.6689 36.0682C8.62172 36.0927 8.57578 36.1067 8.56681 36.0993C8.55784 36.0918 8.51885 36.1023 8.48015 36.1225C8.44146 36.1428 8.33842 36.1785 8.25118 36.2019C8.16393 36.2254 8.08747 36.2507 8.08126 36.2582C8.07506 36.2656 8.02175 36.2811 7.96282 36.2925C7.90388 36.3039 7.83734 36.3238 7.81496 36.3367C7.79258 36.3495 7.77007 36.3478 7.76494 36.3327C7.75982 36.3176 7.74888 36.3134 7.74064 36.3234C7.72364 36.3438 7.44489 36.4758 7.3619 36.5027C7.33183 36.5124 7.24141 36.5415 7.16097 36.5672C7.08053 36.593 6.96811 36.6487 6.91114 36.6911C6.85418 36.7334 6.71742 36.8067 6.60723 36.854C6.36626 36.9575 6.13462 37.0691 6.11725 37.09C6.1103 37.0984 6.06315 37.112 6.01248 37.1204C5.96181 37.1287 5.90898 37.1492 5.89509 37.1659C5.88119 37.1826 5.84808 37.1962 5.8215 37.196C5.79491 37.1959 5.77382 37.2025 5.77461 37.2107C5.77588 37.2237 5.66112 37.2887 5.50842 37.3614C5.27615 37.4719 5.21158 37.6272 5.43835 37.5298C5.49595 37.505 5.64118 37.4636 5.76107 37.4377C5.88097 37.4118 6.07184 37.3651 6.18523 37.3339C6.29863 37.3028 6.54492 37.2477 6.73258 37.2115C6.92022 37.1753 7.14747 37.129 7.23758 37.1088C7.32769 37.0885 7.45569 37.068 7.52202 37.0633C7.58835 37.0586 7.64896 37.0471 7.65671 37.0377C7.66447 37.0284 7.71274 37.0134 7.76399 37.0044C7.81524 36.9954 7.86454 36.9791 7.87357 36.9682C7.88259 36.9574 7.8533 36.9562 7.80847 36.9656C7.76365 36.975 7.72622 36.975 7.72531 36.9656C7.7228 36.9398 8.10773 36.8316 8.15027 36.8462C8.20776 36.8658 8.173 36.8868 8.05419 36.9041C7.99444 36.9128 7.93984 36.9268 7.93285 36.9352C7.90254 36.9717 7.96608 36.9783 8.09989 36.9525C8.17906 36.9373 8.28976 36.9192 8.34588 36.9123C8.402 36.9054 8.52081 36.8822 8.60991 36.8607C8.69901 36.8393 8.78877 36.8195 8.80939 36.8169C8.83001 36.8142 8.90638 36.8007 8.97909 36.7869C9.05181 36.7731 9.15593 36.7551 9.21047 36.7469C9.31275 36.7315 9.63382 36.6684 9.9055 36.6105C9.99061 36.5923 10.077 36.5747 10.0976 36.5714C10.1181 36.5681 10.1957 36.5522 10.2701 36.5362C10.3444 36.5201 10.427 36.5035 10.4535 36.4992C10.5049 36.4909 10.6576 36.4535 10.8121 36.4113C10.8639 36.3972 11.0446 36.3514 11.2137 36.3097C11.6306 36.2067 11.8769 36.1339 11.8991 36.1071C11.9093 36.0949 11.9552 36.0827 12.0012 36.0801C12.0471 36.0775 12.0943 36.0637 12.1062 36.0495C12.1255 36.0262 12.2529 35.9889 12.4856 35.9383C12.5311 35.9284 12.6343 35.8934 12.715 35.8606C12.7957 35.8278 12.8715 35.8043 12.8834 35.8084C12.8953 35.8125 12.9139 35.8051 12.9247 35.7921C12.9355 35.779 12.9844 35.7633 13.0333 35.7571C13.0823 35.7509 13.1325 35.7336 13.1449 35.7185C13.1574 35.7035 13.188 35.6835 13.2129 35.674C13.3606 35.6178 13.6731 35.4659 13.6948 35.4397C13.7089 35.4227 13.7601 35.3922 13.8085 35.372C13.857 35.3517 13.9491 35.3007 14.0133 35.2586C14.0776 35.2165 14.1928 35.1418 14.2695 35.0927C14.4567 34.9726 14.4503 34.9778 14.6074 34.8212C14.6833 34.7455 14.7743 34.6649 14.8096 34.6421C14.8448 34.6193 14.9516 34.5233 15.0467 34.4288C15.4083 34.0697 15.4983 33.9993 15.5456 34.0385C15.5707 34.0594 15.5453 34.1304 15.4929 34.1855C15.4787 34.2005 15.4423 34.3153 15.412 34.4407C15.3817 34.5661 15.3459 34.6889 15.3324 34.7135C15.3015 34.7699 15.2809 35.0561 15.2886 35.3221C15.2918 35.4342 15.2941 35.6125 15.2937 35.7184C15.2933 35.8243 15.3182 35.9964 15.3491 36.1009C15.3799 36.2053 15.4034 36.3033 15.4014 36.3186C15.3993 36.3339 15.414 36.4159 15.4341 36.5008C15.4542 36.5858 15.4803 36.7207 15.4921 36.8007C15.5038 36.8806 15.5223 36.9534 15.5331 36.9624C15.544 36.9714 15.5583 37.0188 15.5649 37.0676C15.5715 37.1165 15.5842 37.1625 15.593 37.1699C15.6019 37.1772 15.613 37.2125 15.6178 37.2482C15.6225 37.2839 15.6381 37.35 15.6523 37.3952C15.6666 37.4404 15.682 37.499 15.6866 37.5255C15.7169 37.7026 15.7755 37.8832 15.8273 37.9589C15.8606 38.0076 15.902 38.105 15.9194 38.1753C15.9584 38.3333 16.0066 38.4598 16.0375 38.4855C16.0504 38.4962 16.1154 38.6222 16.1819 38.7656C16.3792 39.1905 16.5103 39.4322 16.7116 39.7417C16.7846 39.854 16.8845 40.0215 16.9336 40.1138C16.9826 40.2061 17.0321 40.2895 17.0435 40.299C17.055 40.3085 17.1118 40.44 17.1698 40.5911C17.2277 40.7423 17.2891 40.8876 17.3063 40.9141C17.3234 40.9405 17.3741 41.0403 17.4189 41.1357C17.4637 41.2312 17.5051 41.3132 17.5109 41.3181C17.5211 41.3266 17.7171 41.7482 17.7481 41.8284C17.7985 41.9589 17.879 42.1286 17.8979 42.1443C17.9176 42.1606 17.9746 42.3531 17.9993 42.4867C18.0043 42.5137 18.0263 42.5777 18.0483 42.629C18.0702 42.6803 18.0822 42.7294 18.075 42.738C18.0679 42.7467 18.0775 42.7666 18.0964 42.7824C18.1711 42.8443 18.2428 43.2167 18.2602 43.6329C18.2616 43.6662 18.268 43.7475 18.2743 43.8135C18.2807 43.8795 18.2892 43.9995 18.2932 44.0802C18.3011 44.2374 18.3412 44.278 18.3509 44.1386C18.3542 44.0923 18.3738 43.9871 18.3946 43.9049C18.4154 43.8227 18.4261 43.7503 18.4185 43.7439C18.4109 43.7376 18.3987 43.6884 18.3914 43.6347C18.3841 43.5809 18.3663 43.4705 18.3517 43.3893C18.3372 43.3081 18.3324 43.2331 18.3411 43.2227C18.3586 43.2015 18.2946 42.9166 18.2031 42.6085C18.1467 42.4186 18.0876 42.2771 17.9814 42.0774C17.9563 42.0302 17.9114 41.9118 17.8817 41.8142C17.852 41.7166 17.813 41.6113 17.7951 41.5801C17.7184 41.4471 17.6729 41.344 17.6845 41.33C17.6914 41.3217 17.6842 41.3043 17.6686 41.2913C17.6529 41.2783 17.6223 41.2032 17.6006 41.1244C17.5789 41.0456 17.5538 40.9751 17.5449 40.9678C17.5361 40.9604 17.5274 40.9248 17.5257 40.8887C17.5225 40.8202 17.5516 40.8267 17.5864 40.9024C17.6737 41.0921 17.7247 41.2289 17.72 41.2604C17.7169 41.281 17.7311 41.3116 17.7514 41.3285C17.7718 41.3454 17.7965 41.3794 17.8065 41.4041C17.8164 41.4287 17.8499 41.5046 17.881 41.5726C17.9526 41.7297 17.9775 41.7946 18.0313 41.9645C18.0552 42.04 18.0816 42.1075 18.0901 42.1145C18.1131 42.1337 18.2094 42.3406 18.2634 42.4871C18.3183 42.636 18.3478 42.6546 18.323 42.5248C18.2989 42.3987 18.1635 41.9259 18.0696 41.6401C18.0618 41.6162 18.0507 41.5682 18.045 41.5333C18.0393 41.4984 18.0229 41.4515 18.0084 41.4291C17.9772 41.3807 17.8126 40.9166 17.799 40.8385C17.7619 40.6257 17.9565 40.9917 18.0216 41.257C18.0343 41.3088 18.0525 41.3577 18.062 41.3656C18.0715 41.3735 18.0848 41.42 18.0914 41.4689C18.098 41.5178 18.1149 41.5673 18.129 41.5789C18.143 41.5906 18.1656 41.659 18.1791 41.731C18.1927 41.803 18.2156 41.8717 18.2301 41.8838C18.2446 41.8958 18.253 41.9312 18.2489 41.9625C18.2448 41.9938 18.2548 42.0305 18.2711 42.044C18.2873 42.0575 18.3046 42.0973 18.3094 42.1323C18.3142 42.1674 18.3394 42.2655 18.3654 42.3504C18.3914 42.4352 18.4151 42.536 18.4182 42.5743C18.4285 42.7037 18.4853 42.9791 18.5051 42.9955C18.5159 43.0045 18.5163 42.9125 18.506 42.7912C18.4957 42.6699 18.4905 42.5527 18.4944 42.5308C18.5044 42.4754 18.4618 42.1271 18.4088 41.8319C18.3769 41.6544 18.2291 41.1209 18.195 41.0604C18.1774 41.029 18.1529 40.9605 18.1406 40.9081C18.1283 40.8557 18.1102 40.8061 18.1005 40.798C18.0907 40.7899 18.0826 40.7624 18.0825 40.7369C18.0824 40.7114 18.0459 40.6152 18.0015 40.523C17.9571 40.4309 17.9267 40.3484 17.934 40.3396C17.9412 40.3309 17.9339 40.3126 17.9176 40.2991C17.8757 40.2643 17.797 40.0405 17.8236 40.0317C17.8357 40.0277 17.8271 40.0157 17.8043 40.005C17.7807 39.9939 17.744 39.9217 17.7185 39.8361C17.694 39.7539 17.6669 39.6808 17.6581 39.6735C17.6423 39.6604 17.5355 39.4159 17.4282 39.1471C17.2872 38.7939 17.2476 38.6876 17.2323 38.6207C17.2233 38.5813 17.208 38.5425 17.1983 38.5345C17.1887 38.5265 17.1698 38.4733 17.1565 38.4164C17.1431 38.3595 17.1135 38.2675 17.0907 38.2119C17.0357 38.0781 16.9537 37.7577 16.974 37.7559C17.0117 37.7526 17.0636 37.8658 17.143 38.1248C17.1896 38.2768 17.2299 38.403 17.2326 38.4052C17.24 38.4113 17.4058 38.8341 17.5108 39.1146C17.5611 39.2491 17.671 39.5147 17.7516 39.6967C17.7882 39.7792 17.8336 39.9001 17.8525 39.9655C17.8714 40.0308 17.898 40.0937 17.9115 40.1052C17.925 40.1168 17.9657 40.194 18.0018 40.2771C18.0378 40.3602 18.0869 40.465 18.1108 40.51L18.1542 40.5919L18.1363 40.4985C18.1264 40.4471 18.1093 40.397 18.0983 40.3872C18.0873 40.3774 18.0768 40.3399 18.0751 40.3038C18.0734 40.2676 18.0645 40.2319 18.0554 40.2242C18.0389 40.2106 18.0314 40.1883 17.9546 39.9252C17.9333 39.8525 17.9022 39.7816 17.8855 39.7676C17.8687 39.7537 17.8606 39.7257 17.8674 39.7053C17.8742 39.685 17.869 39.6594 17.8559 39.6484C17.8427 39.6375 17.8318 39.6064 17.8317 39.5792C17.8316 39.5521 17.8155 39.4961 17.796 39.4547C17.7764 39.4133 17.7432 39.3312 17.722 39.2723C17.6685 39.123 17.6268 39.0181 17.5159 38.7539C17.463 38.6279 17.3978 38.465 17.3709 38.3919C17.344 38.3189 17.3113 38.2375 17.2982 38.2112C17.213 38.0401 16.9863 37.5259 16.956 37.4349C16.9359 37.3748 16.9058 37.2989 16.889 37.2664C16.7986 37.0907 16.6943 36.8247 16.6698 36.7074C16.6545 36.6339 16.6232 36.5086 16.6003 36.4288C16.5037 36.0921 16.4658 35.8935 16.4303 35.538C16.3473 34.7076 16.3482 34.5908 16.4408 34.1145C16.4858 33.883 16.5178 33.8047 16.5549 33.8355C16.5652 33.8441 16.5643 33.8624 16.5529 33.8763C16.5414 33.8901 16.5361 33.9293 16.5412 33.9635C16.5462 33.9977 16.539 34.0495 16.5252 34.0786C16.4081 34.3239 16.4719 35.6045 16.6284 36.1524C16.7273 36.4987 16.7383 36.5438 16.7437 36.6284C16.7465 36.6732 16.7596 36.7188 16.7727 36.7297C16.7858 36.7406 16.8161 36.8112 16.84 36.8866C16.864 36.9621 16.9125 37.0924 16.9479 37.1763C17.1822 37.7323 17.2938 37.9827 17.3152 38.0005C17.3288 38.0118 17.3543 38.0826 17.3719 38.158C17.3896 38.2334 17.4147 38.304 17.4278 38.3148C17.4408 38.3257 17.465 38.3806 17.4815 38.4368C17.498 38.4931 17.5526 38.6254 17.6028 38.7308C17.7211 38.979 17.9269 39.5431 17.9076 39.5663C17.8994 39.5762 17.9057 39.5951 17.9216 39.6083C17.9481 39.6303 17.999 39.7558 17.9995 39.8007C17.9997 39.811 18.0237 39.8709 18.0529 39.9337C18.0821 39.9965 18.1109 40.0833 18.1169 40.1266C18.1228 40.1699 18.1546 40.2672 18.1873 40.3428C18.3072 40.6194 18.3917 40.8646 18.4063 40.9783C18.4109 41.0149 18.4355 41.132 18.4608 41.2385C18.4861 41.3451 18.5065 41.4413 18.506 41.4524C18.5047 41.4828 18.5666 41.5711 18.5788 41.5564C18.5901 41.5427 18.571 41.3729 18.5233 41.0624C18.4939 40.8715 18.3242 40.1635 18.3038 40.1465C18.2978 40.1415 18.2889 40.1093 18.2841 40.075C18.2739 40.0018 18.2339 39.8528 18.2212 39.8404C18.1912 39.811 18.1708 39.7109 18.1867 39.6714C18.1971 39.6456 18.1983 39.6214 18.1895 39.6175C18.1731 39.6104 18.0638 39.3915 17.996 39.2299C17.8476 38.8763 17.7871 38.7266 17.758 38.6403C17.7395 38.5858 17.6682 38.4191 17.5995 38.27C17.3403 37.7074 17.1586 37.2823 17.1615 37.2452C17.1624 37.2334 17.1447 37.1899 17.1223 37.1484C17.0998 37.107 17.0875 37.0657 17.095 37.0566C17.1025 37.0476 17.0996 37.0327 17.0886 37.0235C17.0775 37.0144 17.0581 36.9628 17.0455 36.9089C17.0328 36.855 17.017 36.8064 17.0103 36.8008C16.9966 36.7894 16.8962 36.45 16.8695 36.325C16.8599 36.2802 16.8437 36.2048 16.8335 36.1575C16.8233 36.1102 16.8051 36.0632 16.7932 36.053C16.7691 36.0325 16.7529 35.7332 16.7758 35.7312C16.7837 35.7305 16.8031 35.7737 16.819 35.8272C16.8348 35.8806 16.8798 36.0308 16.9189 36.1608C16.958 36.2908 16.9938 36.4272 16.9983 36.4639C17.0029 36.5006 17.0301 36.6058 17.0589 36.6976C17.0877 36.7895 17.1111 36.8734 17.111 36.8841C17.1108 36.8948 17.1302 36.9395 17.154 36.9836C17.2134 37.0933 17.311 37.3439 17.3731 37.546C17.392 37.6076 17.4302 37.6938 17.4581 37.7376C17.4859 37.7815 17.5088 37.838 17.5089 37.8632C17.509 37.8884 17.5216 37.9195 17.537 37.9323C17.5524 37.945 17.588 38.0078 17.6161 38.0719C17.8373 38.5753 17.9786 38.9211 17.9861 38.9775C17.991 39.0143 18.0043 39.0547 18.0156 39.0673C18.0585 39.1149 18.2041 39.4623 18.2142 39.5412C18.22 39.5864 18.2316 39.6242 18.2399 39.6253C18.2691 39.6288 18.3002 39.7792 18.2804 39.8217C18.269 39.8464 18.2741 39.8665 18.2927 39.8692C18.3103 39.8717 18.329 39.8978 18.3343 39.927C18.3395 39.9563 18.3755 40.0728 18.4143 40.1858C18.4531 40.2989 18.4788 40.4218 18.4713 40.4591C18.4639 40.4963 18.4682 40.5354 18.4809 40.546C18.4937 40.5566 18.5231 40.629 18.5464 40.707C18.5964 40.8751 18.6264 40.8324 18.5798 40.6593C18.5621 40.5936 18.5361 40.4587 18.5222 40.3596C18.5082 40.2605 18.4817 40.1284 18.4634 40.0662C18.4451 40.0039 18.4166 39.8811 18.4001 39.7933C18.3836 39.7055 18.3643 39.6288 18.3572 39.6229C18.3501 39.617 18.3264 39.5439 18.3046 39.4604C18.2643 39.3064 18.1716 39.0271 18.1566 39.0147C18.1521 39.011 18.1184 38.9155 18.0818 38.8027C17.9423 38.3734 17.9066 38.2707 17.8929 38.2593C17.8851 38.2529 17.8684 38.2035 17.8557 38.1496C17.8431 38.0957 17.823 38.0436 17.8111 38.0337C17.7992 38.0238 17.7692 37.9492 17.7444 37.8679C17.7196 37.7866 17.6899 37.7122 17.6783 37.7026C17.6528 37.6813 17.5831 37.5077 17.572 37.4375C17.5676 37.4096 17.5593 37.3829 17.5537 37.3782C17.548 37.3735 17.4779 37.1946 17.3978 36.9806C17.3177 36.7666 17.2437 36.5845 17.2334 36.5759C17.2231 36.5673 17.2046 36.5265 17.1924 36.4853C17.1802 36.444 17.1516 36.3671 17.129 36.3143C17.1063 36.2615 17.0813 36.1709 17.0733 36.113C17.0653 36.0551 17.0296 35.9394 16.9939 35.8558C16.9156 35.6726 16.8589 35.4976 16.8233 35.3291C16.8087 35.2601 16.7869 35.1955 16.7749 35.1855C16.7628 35.1755 16.7489 35.0906 16.744 34.9967C16.739 34.9029 16.7321 34.7735 16.7286 34.7092C16.7251 34.6449 16.7265 34.5871 16.7317 34.5809C16.7496 34.5593 16.7283 34.3356 16.7046 34.2963C16.6915 34.2747 16.6883 34.238 16.6973 34.2147C16.7698 34.0286 16.7758 33.9489 16.7172 33.9511C16.5481 33.9576 16.5744 33.521 16.7605 33.233C16.7969 33.1766 16.8421 33.078 16.8608 33.0139C16.8795 32.9497 16.9166 32.8599 16.9433 32.8142C17.0018 32.7135 17.0257 32.6685 17.0779 32.5598C17.0999 32.5139 17.1261 32.4756 17.136 32.4747C17.146 32.4739 17.154 32.4544 17.1539 32.4316C17.1538 32.4087 17.1929 32.3237 17.2408 32.2427C17.2887 32.1617 17.3485 32.0557 17.3737 32.0072C17.3989 31.9587 17.4511 31.8601 17.4898 31.7881C17.5285 31.7162 17.5874 31.6017 17.6206 31.5339C17.7968 31.1735 17.8938 30.9932 17.9962 30.8349C18.0586 30.7386 18.1352 30.6034 18.1664 30.5346C18.2335 30.387 18.3769 30.1155 18.4092 30.0749C18.4378 30.0391 18.6383 29.6139 18.6658 29.5308C18.6834 29.4776 18.8157 29.2504 18.9259 29.0842C18.9444 29.0562 18.9684 29.0052 18.9793 28.9708C18.9901 28.9364 19.012 28.8776 19.0278 28.8401C19.0437 28.8027 19.0481 28.7583 19.0376 28.7416C19.0258 28.7228 19.0169 28.7238 19.0141 28.7442C19.008 28.7891 18.7772 29.1633 18.6898 29.27C18.6509 29.3175 18.6071 29.3876 18.5925 29.4258C18.5683 29.4888 18.4323 29.7201 18.3133 29.9006C18.2413 30.0098 18.1785 30.1399 18.1502 30.2384C18.1361 30.2874 18.085 30.3869 18.0365 30.4595C17.9881 30.5321 17.9246 30.646 17.8954 30.7126C17.8661 30.7792 17.8312 30.8374 17.8176 30.8419C17.8041 30.8463 17.7802 30.8923 17.7646 30.9439C17.7489 30.9955 17.7219 31.0457 17.7044 31.0554C17.687 31.0651 17.6653 31.0987 17.6563 31.1301C17.6472 31.1614 17.596 31.2642 17.5425 31.3586C17.489 31.453 17.4192 31.5867 17.3874 31.6557C17.3557 31.7248 17.2934 31.8363 17.249 31.9036C17.2046 31.9708 17.1424 32.0895 17.1107 32.1674C17.079 32.2452 17.0142 32.3901 16.9666 32.4894C16.8364 32.7612 16.6322 33.3237 16.5977 33.5056C16.5663 33.6716 16.524 33.7156 16.4532 33.6561C16.421 33.6289 16.5424 33.1604 16.5995 33.0917C16.6159 33.072 16.6283 33.0465 16.6272 33.035C16.6185 32.9453 17.0143 32.0759 17.2184 31.7362C17.2706 31.6494 17.3465 31.5137 17.387 31.4346C17.4276 31.3555 17.5102 31.2111 17.5706 31.1137C17.6309 31.0164 17.6988 30.8907 17.7214 30.8344C17.7439 30.7781 17.772 30.7288 17.7837 30.725C17.7954 30.7211 17.8197 30.682 17.8377 30.6381C17.8557 30.5942 17.9075 30.4896 17.9527 30.4057C17.998 30.3218 18.0608 30.2036 18.0923 30.143C18.1239 30.0825 18.1636 30.009 18.1806 29.9797C18.3857 29.6265 18.4823 29.4699 18.6838 29.1643C18.9626 28.7415 18.9676 28.7331 19.025 28.5802C19.0579 28.4928 19.1238 28.3962 19.2782 28.2093C19.4801 27.9649 19.4831 27.9597 19.372 28.0506C19.2029 28.1889 19.0535 28.1989 19.1879 28.063C19.2521 27.998 19.2732 27.924 19.2227 27.9407C19.2054 27.9465 19.1268 27.9441 19.048 27.9355C18.9617 27.926 18.8992 27.933 18.8907 27.9531C18.8829 27.9713 18.8531 28.0094 18.8244 28.0376C18.7956 28.0658 18.7554 28.1105 18.735 28.1369C18.3313 28.6582 17.8157 29.2034 17.7656 29.1618C17.7593 29.1566 17.6846 29.2359 17.5998 29.338C17.4275 29.5455 17.3201 29.6054 17.4213 29.4377C17.4523 29.3864 17.4901 29.3344 17.5054 29.3222C17.5206 29.31 17.5466 29.2709 17.5631 29.2352C17.58 29.1986 17.6093 29.1673 17.6301 29.1635C17.6505 29.1598 17.6909 29.1272 17.7199 29.0912C17.7488 29.0551 17.9018 28.8987 18.0599 28.7436C18.3419 28.4669 18.7476 27.9796 18.7781 27.8809C18.8021 27.8035 18.7426 27.7981 18.7035 27.8741C18.6743 27.9308 18.228 28.4269 18.0943 28.5514C18.0499 28.5926 17.9923 28.6512 17.9661 28.6816C17.94 28.7119 17.8163 28.8364 17.6913 28.9581C17.452 29.1911 17.2734 29.4041 17.2659 29.4654C17.2635 29.4854 17.184 29.6021 17.0893 29.7247C16.9946 29.8473 16.9037 29.9809 16.8873 30.0216C16.8709 30.0624 16.7908 30.1936 16.7093 30.3132C16.6277 30.4328 16.556 30.5557 16.5498 30.5864C16.5436 30.6176 16.5097 30.666 16.4726 30.6967C16.434 30.7286 16.4066 30.7687 16.4067 30.7931C16.4069 30.8415 16.2972 31.0464 16.1989 31.1811C16.1616 31.2323 16.1287 31.304 16.1259 31.3404C16.123 31.3769 16.1007 31.4331 16.0763 31.4653C16.0417 31.5111 16.0414 31.5162 16.0751 31.4887C16.0988 31.4693 16.1426 31.397 16.1723 31.328C16.2021 31.259 16.259 31.1635 16.2987 31.1157C16.3384 31.0679 16.3922 30.9871 16.4184 30.936C16.4446 30.885 16.519 30.7595 16.5839 30.6572C16.6487 30.5549 16.7216 30.4237 16.7457 30.3657C16.7698 30.3077 16.8304 30.2023 16.8802 30.1315C16.9301 30.0607 17.0255 29.916 17.0923 29.8099C17.1853 29.662 17.2231 29.6161 17.2541 29.6134C17.285 29.6107 17.2878 29.6187 17.2658 29.6476C17.25 29.6683 17.2267 29.705 17.2138 29.729C17.1166 29.9112 16.9703 30.1554 16.8981 30.2556C16.8747 30.2882 16.8407 30.3538 16.8228 30.4014C16.776 30.5251 16.5334 30.9544 16.46 31.0434C16.4473 31.0589 16.4001 31.1333 16.3552 31.2088C16.3103 31.2843 16.2593 31.3697 16.2419 31.3986C16.2244 31.4275 16.1795 31.5038 16.142 31.5681C16.1046 31.6324 16.0658 31.6878 16.0559 31.6912C16.0461 31.6946 15.9965 31.767 15.9457 31.8521C15.8458 32.0197 15.805 32.0788 15.5742 32.3901C15.4906 32.5029 15.3963 32.6376 15.3646 32.6893C15.3329 32.7411 15.2911 32.8058 15.2718 32.8331C15.2525 32.8605 15.2005 32.9395 15.1562 33.0088C15.098 33.1 15.0662 33.1335 15.0412 33.1299C14.9868 33.122 14.995 33.0694 15.0678 32.9614C15.1048 32.9065 15.1803 32.7926 15.2355 32.7083C15.2908 32.6241 15.3531 32.5338 15.3739 32.5077C15.3947 32.4816 15.4583 32.3925 15.5153 32.3096C15.5723 32.2268 15.6578 32.1062 15.7054 32.0415C15.8244 31.8798 16.0281 31.5628 16.0261 31.5424C16.0229 31.509 15.639 32.0205 15.6159 32.089C15.5928 32.1576 15.5156 32.2458 15.4457 32.2834C15.4267 32.2937 15.3506 32.3677 15.2766 32.4479C15.2026 32.5281 15.1267 32.5989 15.1079 32.6051C15.0892 32.6113 15.0099 32.6888 14.9317 32.7773C14.8416 32.8793 14.7605 32.9509 14.7099 32.973C14.6539 32.9974 14.6139 33.0347 14.5758 33.0979C14.5406 33.1562 14.5143 33.1821 14.5013 33.1713C14.4902 33.1621 14.4497 33.1817 14.4114 33.2149C14.3448 33.2725 14.2769 33.3137 14.1811 33.3546C14.1571 33.3648 14.1302 33.3821 14.1212 33.3929C14.1027 33.4152 13.9307 33.4649 13.9012 33.4565C13.8906 33.4535 13.8714 33.4637 13.8585 33.4792C13.8457 33.4947 13.8004 33.5147 13.758 33.5236C13.7156 33.5325 13.6723 33.5501 13.6618 33.5628C13.6512 33.5755 13.5968 33.5815 13.5409 33.5761C13.485 33.5707 13.4186 33.5813 13.3934 33.5996C13.3682 33.618 13.3393 33.6261 13.3291 33.6177C13.3189 33.6092 13.3012 33.6136 13.2898 33.6275C13.2783 33.6413 13.2393 33.6537 13.2032 33.6551C13.167 33.6565 13.1291 33.6676 13.119 33.6798C13.1088 33.692 13.0709 33.7032 13.0348 33.7045C12.9986 33.7059 12.9564 33.7223 12.9409 33.7409C12.9152 33.7719 12.7858 33.8011 12.604 33.8171C12.5644 33.8205 12.5041 33.8348 12.4701 33.8487C12.3912 33.8809 11.9547 33.9716 11.926 33.9617C11.9141 33.9576 11.8961 33.9641 11.8861 33.9762C11.8761 33.9883 11.8422 33.9945 11.8108 33.9902C11.7794 33.9858 11.7458 33.9918 11.736 34.0036C11.7262 34.0154 11.6772 34.035 11.6272 34.0471C11.5771 34.0592 11.5069 34.0838 11.471 34.1018C11.4352 34.1198 11.3973 34.1274 11.3869 34.1187C11.3764 34.11 11.3311 34.122 11.2861 34.1454C11.2411 34.1688 11.1962 34.1812 11.1863 34.173C11.1764 34.1648 11.1398 34.1734 11.105 34.1923C11.0702 34.2111 10.9977 34.2406 10.9439 34.258C10.89 34.2753 10.7967 34.3073 10.7365 34.329C10.6762 34.3507 10.6234 34.3582 10.6192 34.3457C10.6149 34.3331 10.5933 34.3446 10.5712 34.3713C10.5492 34.3979 10.5143 34.4139 10.4939 34.4069C10.4734 34.3999 10.4436 34.41 10.4275 34.4294C10.4114 34.4487 10.3726 34.461 10.3412 34.4566C10.3098 34.4522 10.2759 34.4586 10.2658 34.4707C10.2557 34.4829 10.2056 34.5002 10.1543 34.5092C10.1031 34.5182 10.0504 34.5384 10.0374 34.5542C10.0243 34.5699 9.99338 34.5848 9.96872 34.5873C9.94406 34.5898 9.88994 34.6097 9.84845 34.6317C9.80696 34.6536 9.76556 34.6654 9.75646 34.6578C9.74735 34.6502 9.72943 34.6567 9.71664 34.6721C9.70385 34.6875 9.68491 34.693 9.67454 34.6844C9.66418 34.6758 9.6451 34.6816 9.63214 34.6972C9.61917 34.7128 9.55889 34.7415 9.49818 34.761C9.43747 34.7805 9.36175 34.8111 9.32993 34.8289C9.2981 34.8468 9.2079 34.8812 9.12947 34.9054C8.71827 35.0324 8.6273 35.0639 8.60947 35.0854C8.59874 35.0983 8.58307 35.1032 8.57465 35.0962C8.55843 35.0827 8.3333 35.188 8.30471 35.2224C8.29545 35.2335 8.25406 35.2523 8.21273 35.264C8.17139 35.2757 8.09226 35.308 8.03686 35.3358C7.98147 35.3635 7.92934 35.3806 7.92102 35.3737C7.9127 35.3668 7.87621 35.3857 7.83993 35.4157C7.80365 35.4456 7.75405 35.4701 7.72972 35.47C7.70538 35.4699 7.67287 35.4849 7.65746 35.5035C7.64206 35.522 7.60864 35.5391 7.58321 35.5413C7.55777 35.5435 7.50635 35.5707 7.46894 35.6016C7.43153 35.6325 7.34055 35.6844 7.26678 35.7169C7.19301 35.7494 7.1288 35.7842 7.1241 35.7942C7.1194 35.8042 7.09211 35.8145 7.06347 35.8171C7.03482 35.8196 6.98773 35.84 6.95882 35.8625C6.92991 35.885 6.8573 35.9293 6.79748 35.9609C6.73765 35.9926 6.67137 36.0393 6.65019 36.0648C6.62901 36.0903 6.57994 36.125 6.54115 36.142C6.45762 36.1784 6.24845 36.3186 6.21176 36.3628C6.19758 36.3799 6.17751 36.3868 6.16715 36.3782C6.15679 36.3696 6.13808 36.3749 6.12559 36.3899C6.11309 36.405 6.05654 36.4455 5.99991 36.4801C5.94328 36.5146 5.8693 36.5688 5.83551 36.6005C5.80173 36.6322 5.7508 36.6675 5.72234 36.6789C5.65019 36.708 5.24621 36.9948 5.15162 37.0842C4.99373 37.2333 4.92594 37.2934 4.77105 37.4218C4.57919 37.5807 4.40625 37.7788 4.39101 37.8571C4.38484 37.8887 4.3534 37.9513 4.32115 37.9962C4.24765 38.0983 4.28834 38.1212 4.37421 38.026ZM7.50017 39.7451C7.77024 39.6338 7.87084 39.5678 8.04324 39.3892C8.11242 39.3175 8.21743 39.2272 8.27659 39.1886C8.39455 39.1116 8.44398 39.0691 8.59067 38.9191C8.64452 38.864 8.70165 38.8146 8.71762 38.8093C8.73359 38.804 8.80038 38.7424 8.86603 38.6723C8.96863 38.5628 9.06041 38.4748 9.17777 38.3734C9.19313 38.3601 9.24208 38.3156 9.28654 38.2744C9.331 38.2333 9.49279 38.0908 9.64607 37.9578C9.79936 37.8248 9.98328 37.6651 10.0548 37.603C10.3474 37.3489 10.8646 36.8391 10.8394 36.8297C10.8252 36.8245 10.8024 36.8366 10.7887 36.8567C10.7749 36.8767 10.6985 36.9324 10.6189 36.9805C10.3675 37.132 10.2772 37.2014 10.0847 37.3913C10.0417 37.4337 9.96544 37.509 9.91518 37.5586C9.86492 37.6082 9.78598 37.6776 9.73975 37.7127C9.69353 37.7478 9.60958 37.8234 9.55321 37.8807C9.49683 37.938 9.36122 38.0738 9.25189 38.1826C9.14254 38.2913 9.03382 38.3998 9.01028 38.4236C8.98675 38.4475 8.94887 38.4728 8.92612 38.4799C8.90336 38.4871 8.8477 38.5338 8.80244 38.5837C8.75719 38.6337 8.69525 38.6887 8.66481 38.7061C8.63437 38.7234 8.55221 38.8032 8.48222 38.8833C8.41224 38.9635 8.33985 39.0318 8.32134 39.0352C8.30283 39.0386 8.21239 39.113 8.12037 39.2006C7.933 39.3789 7.80628 39.4695 7.81298 39.4203C7.8169 39.3915 7.96032 39.2446 8.11247 39.1136C8.14325 39.0871 8.26844 38.972 8.39068 38.8578C8.51292 38.7436 8.62121 38.6475 8.63132 38.6441C8.64143 38.6408 8.69591 38.5927 8.75237 38.5374C8.80884 38.482 8.96584 38.337 9.10126 38.2152C9.5337 37.8262 9.93234 37.4488 10.2108 37.1647C10.3162 37.0572 10.2941 37.0692 10.0957 37.2269C10.0103 37.2948 9.90855 37.3736 9.86964 37.402C9.81445 37.4423 9.61365 37.5984 9.55566 37.646C9.55041 37.6504 9.52188 37.6632 9.49225 37.6745C9.3996 37.71 9.12179 37.9639 8.86522 38.2477C8.76896 38.3541 8.6641 38.4516 8.63219 38.4643C8.55443 38.4953 8.17813 38.8654 8.15407 38.9346C8.13091 39.0012 7.95211 39.1739 7.85082 39.2276C7.83169 39.2378 7.80777 39.2534 7.79768 39.2624C7.78758 39.2714 7.74968 39.2943 7.71346 39.3134C7.67724 39.3325 7.64593 39.3604 7.64388 39.3755C7.64183 39.3905 7.62223 39.4121 7.60031 39.4234C7.57839 39.4347 7.53286 39.4736 7.49914 39.5098C7.46541 39.546 7.41971 39.579 7.39759 39.5832C7.36285 39.5898 7.21773 39.7322 7.15891 39.8174C7.12071 39.8728 7.26434 39.8423 7.50017 39.7451ZM5.18782 37.4027C5.19892 37.3903 5.20105 37.3743 5.19255 37.3672C5.17441 37.3522 4.90942 37.5982 4.87722 37.66C4.85901 37.6949 5.12061 37.4783 5.18782 37.4027ZM5.42336 37.1746C5.73771 36.9036 5.75637 36.8826 5.64242 36.9284C5.61072 36.9411 5.51932 37.0178 5.43931 37.0989C5.3593 37.1799 5.26725 37.2668 5.23477 37.2918C5.18838 37.3277 5.18564 37.3343 5.222 37.3229C5.24746 37.3149 5.33806 37.2481 5.42336 37.1746ZM8.25706 39.352C8.44723 39.2515 8.68412 39.0733 8.876 38.8864C8.91732 38.8462 8.97211 38.8048 8.99775 38.7945C9.02339 38.7842 9.0437 38.7689 9.04289 38.7606C9.04208 38.7522 9.14158 38.6662 9.26401 38.5693C9.38644 38.4725 9.51594 38.3679 9.55178 38.3369C9.58762 38.306 9.65314 38.2539 9.69736 38.2212C9.74157 38.1885 9.80855 38.1251 9.84619 38.0802C9.91386 37.9997 10.0173 37.9054 10.3101 37.6574C10.4422 37.5455 10.546 37.453 10.6787 37.3289C10.6994 37.3096 10.7181 37.2754 10.7202 37.253C10.7235 37.2192 10.721 37.2177 10.7054 37.2442C10.6771 37.2924 10.4739 37.4305 10.4548 37.4146C10.4369 37.3998 10.4721 37.369 10.7236 37.18C10.8942 37.0517 11.0706 36.8975 11.2971 36.6786C11.3743 36.6039 11.4731 36.512 11.5166 36.4744C11.5806 36.4189 11.5902 36.4014 11.567 36.3821C11.5402 36.3599 11.4721 36.394 11.3893 36.4712C11.3696 36.4895 11.3309 36.5213 11.3033 36.5418C11.2758 36.5623 11.1606 36.6725 11.0474 36.7867C10.9341 36.9009 10.8168 37.0164 10.7865 37.0434C10.7563 37.0703 10.7039 37.1191 10.6701 37.1517C10.498 37.3176 10.3919 37.4159 10.3557 37.4428C10.3229 37.4671 10.3235 37.4704 10.3586 37.461C10.3961 37.4509 10.3983 37.4535 10.3761 37.4808C10.3621 37.498 10.3399 37.508 10.3269 37.503C10.3139 37.498 10.256 37.5327 10.1982 37.5802C10.1069 37.6552 10.0427 37.7107 9.80749 37.9183C9.65625 38.0518 9.47852 38.2134 9.42148 38.2694C9.38519 38.305 9.33892 38.3375 9.31865 38.3417C9.28408 38.3489 8.88472 38.7147 8.86625 38.7561C8.86158 38.7665 8.8231 38.7985 8.78076 38.8271C8.73841 38.8556 8.65395 38.9299 8.59308 38.9922C8.49069 39.0969 8.44918 39.1291 8.32797 39.1979C8.17655 39.2839 8.10926 39.4301 8.25706 39.352ZM14.4017 43.5614C14.406 43.4914 14.4155 43.427 14.4226 43.4184C14.4298 43.4097 14.448 43.3102 14.4631 43.1972C14.4781 43.0842 14.4969 42.9839 14.5049 42.9743C14.5129 42.9647 14.5455 42.8494 14.5774 42.7181C14.7323 42.0796 14.8301 41.7212 14.8726 41.6354C14.8909 41.5985 14.9175 41.5212 14.9317 41.4635C14.9607 41.3456 15.086 41.0543 15.2215 40.7892C15.2713 40.6918 15.3393 40.5566 15.3726 40.4888C15.4058 40.4209 15.5014 40.2377 15.585 40.0815C15.6686 39.9253 15.7556 39.7491 15.7782 39.6898C15.8193 39.5824 15.9945 39.1996 16.0506 39.0948C16.0848 39.0308 16.0389 38.8737 15.9934 38.8991C15.978 38.9076 15.9352 38.996 15.8983 39.0954C15.8613 39.1949 15.8108 39.3091 15.7861 39.3493C15.7614 39.3895 15.7185 39.4913 15.6909 39.5754C15.6633 39.6595 15.6171 39.7567 15.5882 39.7914C15.5594 39.8261 15.5372 39.8692 15.5389 39.887C15.5405 39.9049 15.5224 39.9601 15.4985 40.0097C15.4747 40.0593 15.4255 40.1618 15.3893 40.2375C15.3084 40.4063 15.2666 40.4873 15.225 40.5555C15.2074 40.5843 15.1602 40.7013 15.1202 40.8155C15.0407 41.042 15.0035 41.134 14.958 41.2172C14.9416 41.247 14.916 41.3039 14.9011 41.3435C14.8861 41.3831 14.8442 41.4761 14.808 41.5502C14.7407 41.6877 14.6994 41.7932 14.6573 41.9346C14.6443 41.9785 14.6194 42.0315 14.602 42.0524C14.5846 42.0734 14.5741 42.1016 14.5787 42.1152C14.5876 42.1413 14.4888 42.5662 14.4399 42.7116C14.3796 42.8913 14.3575 43.1333 14.3686 43.4905C14.3757 43.7157 14.3902 43.7468 14.4017 43.5614ZM8.9975 38.9494C9.01076 38.9344 9.08449 38.882 9.16134 38.833C9.34711 38.7147 9.69287 38.456 9.83968 38.3255C9.9047 38.2677 9.97929 38.2118 10.0054 38.2013C10.0316 38.1907 10.0865 38.1503 10.1275 38.1115C10.1685 38.0726 10.2385 38.0127 10.2831 37.9782C10.3277 37.9438 10.4451 37.8283 10.5438 37.7215C10.8683 37.3709 11.2185 37.039 11.3707 36.938C11.5346 36.8292 11.5396 36.8221 11.6269 36.5739L11.6871 36.403L11.4817 36.6674C11.3456 36.8425 11.2024 37.0005 11.0574 37.1354C10.9371 37.2474 10.8224 37.3547 10.8026 37.3738C10.7828 37.393 10.7525 37.4133 10.7351 37.4191C10.7178 37.4248 10.6019 37.5178 10.4776 37.6257C10.3532 37.7335 10.2402 37.8256 10.2263 37.8302C10.2124 37.8348 10.1441 37.8987 10.0744 37.9721C10.0047 38.0456 9.90903 38.1287 9.86182 38.1567C9.80891 38.1881 9.78333 38.2138 9.79511 38.2236C9.80563 38.2323 9.80147 38.2437 9.78587 38.2488C9.77027 38.254 9.73198 38.2825 9.70077 38.3123C9.66956 38.342 9.59957 38.4003 9.54523 38.442C9.49089 38.4836 9.42284 38.5407 9.394 38.5688C9.36517 38.5969 9.28688 38.6597 9.22003 38.7083C9.15318 38.7569 9.06317 38.8276 9.02001 38.8654C8.97685 38.9032 8.93042 38.9326 8.91683 38.9306C8.90324 38.9286 8.88654 38.9437 8.87973 38.964C8.86493 39.0081 8.95563 38.9968 8.9975 38.9494ZM8.85302 38.1466C9.22175 37.7403 9.8298 37.1467 10.1858 36.8454C10.2733 36.7713 10.3444 36.7047 10.3437 36.6974C10.3415 36.6743 10.281 36.674 10.2779 36.6971C10.2762 36.7091 10.2435 36.7413 10.2051 36.7686C10.1667 36.7958 10.1026 36.8477 10.0626 36.8839C9.96306 36.9741 9.81182 37.0891 9.69582 37.163C9.64259 37.1969 9.52842 37.2867 9.44209 37.3625C9.35577 37.4383 9.25352 37.5167 9.21487 37.5366C9.10894 37.5913 9.10626 37.5946 8.9848 37.8169C8.92261 37.9307 8.83216 38.0799 8.7838 38.1484C8.73543 38.2169 8.69006 38.2812 8.68297 38.2912C8.63008 38.366 8.73461 38.2771 8.85302 38.1466ZM14.0884 42.5943C14.0924 42.5896 14.0947 42.5382 14.0935 42.4802C14.0923 42.4222 14.1042 42.3358 14.12 42.2882C14.1358 42.2406 14.1849 42.0575 14.2291 41.8815C14.2734 41.7054 14.3137 41.5564 14.3187 41.5504C14.3237 41.5444 14.3382 41.5034 14.3509 41.4593C14.3636 41.4151 14.3991 41.3006 14.4299 41.2046C14.4607 41.1087 14.5017 40.9653 14.5211 40.8859C14.5404 40.8066 14.5792 40.6826 14.6073 40.6105C14.6353 40.5384 14.6658 40.4571 14.6749 40.43C14.6841 40.4029 14.7193 40.3186 14.7531 40.2426C14.787 40.1666 14.8275 40.0653 14.8432 40.0176C14.8588 39.9699 14.8895 39.8889 14.9112 39.8375C14.933 39.7862 14.964 39.7055 14.9802 39.6582C15.0192 39.5442 15.1842 39.2136 15.2537 39.1102C15.3198 39.0118 15.3506 38.8926 15.2922 38.961C15.2732 38.9832 15.2463 38.9998 15.2324 38.9978C15.186 38.9911 15.1016 39.0692 15.1018 39.1186C15.1019 39.1448 15.0771 39.1974 15.0466 39.2354C15.0162 39.2734 14.9862 39.3327 14.9801 39.3671C14.9739 39.4015 14.9492 39.4591 14.9252 39.4951C14.9012 39.531 14.8758 39.577 14.8689 39.5973C14.8619 39.6175 14.8223 39.7039 14.7808 39.7891C14.7393 39.8743 14.6887 40.0027 14.6683 40.0743C14.6479 40.1459 14.6185 40.2121 14.6029 40.2214C14.5873 40.2308 14.5606 40.2932 14.5434 40.3602C14.5263 40.4272 14.4884 40.5123 14.4591 40.5494C14.4298 40.5864 14.4097 40.6342 14.4144 40.6554C14.4238 40.6978 14.31 41.0748 14.2316 41.2608C14.2046 41.3251 14.1788 41.442 14.1743 41.5205C14.1653 41.6793 14.1391 41.8439 14.0974 42.0046C14.0821 42.0633 14.0721 42.1488 14.0751 42.1947C14.078 42.2406 14.0744 42.3457 14.0671 42.4284C14.0554 42.5588 14.0638 42.624 14.0884 42.5943ZM14.2874 42.4677C14.3127 42.3884 14.34 42.2743 14.3481 42.2142C14.3671 42.0725 14.4743 41.6558 14.523 41.5344C14.5439 41.4823 14.5683 41.4174 14.5773 41.3901C14.5863 41.3629 14.608 41.3029 14.6256 41.2567C14.8209 40.7435 14.8973 40.5341 14.9171 40.4576C14.9301 40.4076 14.9818 40.2691 15.032 40.1498C15.0823 40.0304 15.1248 39.9221 15.1266 39.909C15.1304 39.8816 15.2028 39.7197 15.3695 39.3662C15.4342 39.229 15.5155 39.0377 15.5501 38.9409C15.5847 38.8442 15.6251 38.7505 15.6399 38.7328C15.6546 38.715 15.6244 38.7185 15.5728 38.7405C15.4653 38.7863 15.4513 38.8039 15.4407 38.9068C15.4365 38.9478 15.4039 39.0272 15.3683 39.0833C15.3327 39.1394 15.2715 39.258 15.2323 39.3468C15.193 39.4357 15.1436 39.5438 15.1225 39.5869C15.036 39.7633 15.0072 39.8355 14.9359 40.0545C14.8949 40.1806 14.8441 40.3044 14.8231 40.3297C14.8021 40.355 14.7888 40.3869 14.7935 40.4007C14.7982 40.4145 14.7736 40.4978 14.7388 40.5859C14.704 40.674 14.6518 40.8399 14.6227 40.9545C14.5936 41.0692 14.5523 41.2053 14.5308 41.2568C14.5093 41.3084 14.477 41.4181 14.459 41.5006C14.4409 41.5831 14.4021 41.7212 14.3726 41.8075C14.2711 42.1048 14.1774 42.6176 14.2254 42.6134C14.2341 42.6126 14.262 42.5471 14.2874 42.4677ZM12.488 40.1483C12.5424 40.0656 12.5857 39.988 12.5842 39.9758C12.5806 39.9468 12.3795 40.228 12.3738 40.27C12.3663 40.3246 12.3854 40.3042 12.488 40.1483ZM14.5402 41.9666C14.5723 41.8834 14.5785 41.8127 14.5508 41.8461C14.5193 41.884 14.4783 42.0178 14.4942 42.031C14.503 42.0383 14.5237 42.0093 14.5402 41.9666ZM14.8884 42.0784C14.9035 42.028 14.9702 41.8757 15.0366 41.74C15.103 41.6042 15.1839 41.4372 15.2165 41.3688C15.249 41.3003 15.3352 41.1447 15.408 41.023C15.4807 40.9012 15.5452 40.7915 15.5513 40.7792C15.5574 40.7669 15.5803 40.722 15.6023 40.6795C15.6242 40.637 15.674 40.5293 15.713 40.4402C15.7519 40.351 15.7977 40.2471 15.8148 40.2092C15.841 40.1514 16.1182 39.6812 16.2519 39.4678C16.2844 39.416 16.2809 39.3846 16.2315 39.2824C16.1618 39.1385 16.1566 39.1367 16.1095 39.2408C16.0572 39.3561 15.8336 39.7963 15.7831 39.8832C15.7593 39.9241 15.7092 40.0294 15.6718 40.1172C15.6344 40.2049 15.5882 40.2854 15.569 40.2961C15.5499 40.3067 15.5343 40.333 15.5344 40.3544C15.5344 40.3758 15.5116 40.4367 15.4835 40.4896C15.3096 40.8178 15.061 41.3429 15.0506 41.4043C15.0454 41.4346 15.0266 41.49 15.0088 41.5274C14.991 41.5647 14.9422 41.7089 14.9004 41.8477C14.8586 41.9865 14.8158 42.1284 14.8053 42.1631C14.7887 42.2182 14.791 42.2226 14.8236 42.1981C14.8441 42.1827 14.8733 42.1288 14.8884 42.0784ZM9.26204 37.4338C9.28709 37.4163 9.28557 37.4142 9.25404 37.4226C9.1364 37.4542 9.40172 37.1518 9.68284 36.9339C9.87245 36.787 9.9006 36.7504 9.81653 36.7603C9.62549 36.7828 9.08337 37.3741 9.19664 37.4364C9.21558 37.4469 9.24501 37.4457 9.26204 37.4338ZM14.6037 41.821C14.6083 41.8154 14.6221 41.7665 14.6343 41.7123C14.6465 41.658 14.7103 41.5022 14.7761 41.3659C14.8419 41.2297 14.9221 41.0457 14.9543 40.957C14.9866 40.8684 15.0552 40.7194 15.1067 40.6258C15.1583 40.5323 15.2115 40.4224 15.225 40.3817C15.2384 40.341 15.2989 40.1996 15.3593 40.0676C15.5053 39.7483 15.7859 39.0971 15.8048 39.0335C15.8335 38.9366 15.8846 38.8218 15.9165 38.7825C15.9461 38.746 15.9041 38.5954 15.8524 38.5525C15.8284 38.5326 15.7715 38.6024 15.7833 38.6371C15.7884 38.6521 15.7819 38.6773 15.7687 38.6931C15.7556 38.7089 15.7342 38.7577 15.7212 38.8016C15.6479 39.0488 15.3122 39.7868 15.2598 39.816C15.2429 39.8254 15.2379 39.8406 15.2488 39.8496C15.2596 39.8586 15.2366 39.9425 15.1977 40.0359C15.1587 40.1293 15.0805 40.3377 15.0239 40.4989C14.9673 40.6602 14.8963 40.8437 14.866 40.9068C14.8358 40.9699 14.7978 41.0732 14.7816 41.1364C14.7348 41.3184 14.6551 41.5292 14.6145 41.578C14.594 41.6027 14.5816 41.6359 14.587 41.6518C14.5924 41.6677 14.5878 41.7073 14.5768 41.7398C14.5596 41.7907 14.5793 41.8504 14.6037 41.821ZM9.43892 37.2899C9.48216 37.2528 9.53501 37.2151 9.55638 37.2062C9.57774 37.1972 9.67929 37.1177 9.78204 37.0295C9.8848 36.9413 10.0039 36.8435 10.0467 36.8123C10.1379 36.7456 10.1408 36.7348 10.0687 36.7301C10.029 36.7275 9.97419 36.7658 9.85891 36.8767C9.7731 36.9593 9.68809 37.0354 9.67002 37.0459C9.65194 37.0564 9.58026 37.118 9.51072 37.1828C9.44119 37.2477 9.36505 37.3115 9.34152 37.3246C9.31334 37.3403 9.30924 37.3499 9.32952 37.3529C9.34645 37.3553 9.39568 37.3269 9.43892 37.2899ZM9.7023 37.461C9.70822 37.4433 9.73329 37.4252 9.75801 37.4207C9.78274 37.4162 9.80435 37.4024 9.80605 37.39C9.80774 37.3776 9.90237 37.2959 10.0163 37.2083C10.3767 36.9314 10.4057 36.8631 10.0653 37.093C9.82224 37.2573 9.47752 37.5923 9.61931 37.5266C9.65904 37.5081 9.69638 37.4786 9.7023 37.461ZM10.495 37.9115C10.5356 37.8603 10.5357 37.8546 10.4959 37.8747C10.43 37.9081 10.3843 37.9632 10.4184 37.9681C10.434 37.9703 10.4685 37.9449 10.495 37.9115ZM12.8404 39.5803C12.8724 39.5066 12.8696 39.5079 12.7859 39.6054C12.7373 39.662 12.6987 39.72 12.6999 39.7342C12.7036 39.7752 12.803 39.6662 12.8404 39.5803ZM10.8103 37.6467C10.9707 37.4543 10.887 37.4901 10.6956 37.6957C10.5594 37.842 10.5535 37.8519 10.6207 37.8206C10.6627 37.801 10.7431 37.7272 10.8103 37.6467ZM12.1635 38.9203C12.1823 38.9142 12.2061 38.9021 12.2165 38.8934C12.227 38.8847 12.2535 38.8679 12.2755 38.8561C12.3117 38.8367 12.2869 38.7461 12.2336 38.7027C12.1746 38.6546 12.0059 38.7885 12.0531 38.8458C12.1172 38.9237 12.129 38.9316 12.1635 38.9203ZM12.5199 39.1847C12.5338 39.1489 12.4661 39.0672 12.4443 39.0935C12.428 39.1131 12.4452 39.1556 12.4844 39.1922C12.4975 39.2044 12.5135 39.2011 12.5199 39.1847ZM12.0555 38.6542C12.1772 38.6015 12.2231 38.536 12.1695 38.4915C12.1267 38.4559 11.8611 38.5788 11.8766 38.6271C11.9008 38.7023 11.9332 38.7072 12.0555 38.6542ZM14.3724 40.4743C14.4008 40.4261 14.4626 40.2892 14.5096 40.1701C14.6722 39.7585 14.7955 39.4882 14.8761 39.3666C15.0245 39.1428 15.0205 39.1057 14.8579 39.1967C14.7778 39.2415 14.7505 39.2683 14.7405 39.3122C14.7333 39.3436 14.6991 39.431 14.6645 39.5064C14.6299 39.5818 14.5954 39.6667 14.5878 39.6951C14.5603 39.7975 14.4907 39.9629 14.4599 39.999C14.4318 40.032 14.3 40.5364 14.3148 40.5545C14.3181 40.5585 14.344 40.5224 14.3724 40.4743ZM11.9463 38.4459C12.0431 38.4014 12.0776 38.343 12.019 38.323C11.9981 38.3159 11.9798 38.3192 11.9782 38.3303C11.9767 38.3415 11.9437 38.3639 11.9049 38.3801C11.8166 38.417 11.7997 38.4368 11.8329 38.4644C11.8473 38.4763 11.8983 38.468 11.9463 38.4459ZM11.8081 38.3255C11.8471 38.2777 11.8499 38.2145 11.8132 38.2092C11.7785 38.2042 11.7253 38.2576 11.7288 38.2938C11.7332 38.3385 11.7817 38.3579 11.8081 38.3255ZM13.0468 39.2279C13.0537 39.2033 13.0908 39.1351 13.1293 39.0765C13.1833 38.9943 13.1906 38.9687 13.1611 38.9645C13.1169 38.9583 12.9824 39.2296 13.0159 39.2574C13.0264 39.2662 13.0396 39.2535 13.0468 39.2279ZM13.2939 39.4489C13.3237 39.4111 13.3205 39.3053 13.2888 39.2788C13.2659 39.2594 13.2816 39.2271 13.3652 39.1214C13.4719 38.9866 13.4972 38.8999 13.4431 38.855C13.4248 38.8398 13.4099 38.849 13.394 38.8852C13.3815 38.9139 13.3409 38.9831 13.3039 39.0391C13.2004 39.1954 13.1875 39.2254 13.1855 39.3143C13.1836 39.3993 13.2591 39.493 13.2939 39.4489ZM11.0842 37.3983C11.1407 37.3512 11.2219 37.2809 11.2648 37.2422C11.3109 37.2006 11.3658 37.1737 11.3988 37.1765C11.4529 37.1812 11.4562 37.1757 11.4984 37.0159C11.5455 36.8375 11.5427 36.8381 11.3593 37.0457C11.2076 37.2176 10.99 37.4361 10.9423 37.4645C10.9133 37.4817 10.9134 37.4871 10.9426 37.4858C10.9641 37.4848 11.0278 37.4454 11.0842 37.3983ZM11.7666 38.1263C11.8191 38.1089 11.9231 37.9973 11.8966 37.9869C11.8823 37.9813 11.8698 37.9834 11.8687 37.9915C11.8677 37.9996 11.8325 38.0166 11.7907 38.0293C11.7178 38.0513 11.6882 38.0918 11.7236 38.1212C11.7327 38.1288 11.7521 38.1311 11.7666 38.1263ZM12.7478 38.7903C12.7908 38.7263 12.9128 38.5523 13.0188 38.4038C13.1248 38.2552 13.2274 38.1061 13.2467 38.0725C13.2661 38.0388 13.3116 37.972 13.3478 37.924C13.3841 37.876 13.416 37.8244 13.4187 37.8093C13.4244 37.778 13.4144 37.7942 13.6191 37.4867C13.7047 37.3582 13.7786 37.2337 13.7835 37.2099C13.7883 37.1862 13.8457 37.0848 13.911 36.9845C14.1058 36.6854 14.1449 36.5953 14.0137 36.7478C13.9518 36.8198 13.912 36.8833 13.918 36.9008C13.9239 36.9181 13.9041 36.9502 13.8714 36.9766C13.8401 37.0018 13.7931 37.064 13.767 37.1148C13.7408 37.1656 13.6861 37.2576 13.6454 37.3193C13.3809 37.7202 13.1886 38.0046 13.0716 38.1679C12.9975 38.2712 12.9326 38.3761 12.9274 38.401C12.9222 38.4259 12.8939 38.4752 12.8645 38.5106C12.8059 38.5811 12.6452 38.8865 12.6602 38.899C12.6653 38.9032 12.7047 38.8543 12.7478 38.7903ZM10.5506 36.885C10.567 36.8672 10.5698 36.8512 10.5567 36.8493C10.5437 36.8474 10.5061 36.8774 10.4732 36.9159C10.4107 36.9889 10.4795 36.9615 10.5506 36.885ZM12.0314 38.221C12.0535 38.2052 12.073 38.1689 12.0746 38.1403C12.0788 38.0667 11.9885 38.1024 11.9601 38.1855C11.9385 38.2489 11.9702 38.2647 12.0314 38.221ZM12.5864 38.7304C12.5898 38.7263 12.6692 38.597 12.7627 38.443C12.8563 38.289 12.9946 38.0795 13.0701 37.9773C13.1455 37.8751 13.231 37.7545 13.26 37.7091C13.289 37.6638 13.347 37.577 13.3887 37.5163C13.4897 37.3695 13.7876 36.7749 13.7682 36.7587C13.7599 36.7518 13.7516 36.7563 13.7499 36.7688C13.7482 36.7813 13.7003 36.8586 13.6434 36.9406C13.5865 37.0226 13.4926 37.1711 13.4349 37.2706C13.3165 37.4746 13.2263 37.5919 13.1955 37.5819C13.184 37.5782 13.1297 37.6442 13.0746 37.7287C13.0196 37.8131 12.9397 37.9314 12.8971 37.9915C12.6423 38.3509 12.5263 38.5635 12.5389 38.6484C12.5476 38.7066 12.5717 38.7482 12.5864 38.7304ZM11.7901 37.9253C11.8977 37.8795 11.9569 37.8217 11.9654 37.7543C11.9729 37.695 11.9252 37.7061 11.8117 37.7903C11.6258 37.9282 11.6143 38.0001 11.7901 37.9253ZM13.0241 38.8778C13.0623 38.8184 13.1278 38.72 13.1696 38.6591C13.2113 38.5982 13.2582 38.5164 13.2736 38.4773C13.3112 38.3821 13.0276 38.7637 12.9726 38.8823C12.9153 39.0058 12.9434 39.0033 13.0241 38.8778ZM13.6061 39.4843C13.6122 39.4661 13.6507 39.3985 13.6918 39.3342C13.7813 39.1938 13.7797 39.1377 13.69 39.271C13.6361 39.351 13.6241 39.359 13.6061 39.3272C13.5863 39.2923 13.5353 39.3559 13.5215 39.4328C13.5146 39.4708 13.5943 39.5194 13.6061 39.4843ZM18.6343 43.5523C18.6456 43.5139 18.6553 43.4616 18.6558 43.436C18.6563 43.4104 18.6654 43.3506 18.6761 43.303C18.6924 43.2303 18.6607 43.1453 18.6308 43.1814C18.6129 43.2029 18.592 43.6039 18.6081 43.6173C18.6112 43.6199 18.623 43.5906 18.6343 43.5523ZM11.7911 37.6882C11.8867 37.6124 11.9285 37.519 11.8417 37.5751C11.8191 37.5896 11.7648 37.6175 11.7209 37.637C11.655 37.6664 11.6412 37.6811 11.6414 37.7222C11.6416 37.7881 11.6745 37.7807 11.7911 37.6882ZM12.5431 38.2733C12.6012 38.1963 12.6067 38.1757 12.5765 38.148C12.5567 38.1297 12.533 38.1065 12.5239 38.0964C12.5148 38.0862 12.5378 38.0433 12.575 38.0009C12.6121 37.9585 12.6598 37.881 12.6809 37.8286C12.702 37.7762 12.7337 37.7052 12.7513 37.6709C12.7935 37.5888 12.7372 37.5669 12.6865 37.6457C12.6653 37.6787 12.6441 37.7245 12.6394 37.7476C12.6271 37.8087 12.5542 37.829 12.5487 37.7729C12.5465 37.7494 12.5372 37.7242 12.5283 37.7167C12.5063 37.6984 12.4653 37.7983 12.4752 37.8461C12.4795 37.8671 12.4755 37.9198 12.4663 37.9633C12.4534 38.0247 12.4569 38.3343 12.4709 38.3603C12.4724 38.3631 12.5049 38.3239 12.5431 38.2733ZM13.8819 39.3686C13.9072 39.3502 13.9751 39.254 14.0328 39.1548C14.3884 38.5435 14.33 38.5215 13.9619 39.128C13.8954 39.2376 13.8323 39.3379 13.8217 39.3508C13.7888 39.3907 13.8335 39.4039 13.8819 39.3686ZM11.745 37.5158C11.7903 37.4884 11.8635 37.4484 11.9077 37.427C12.0033 37.3807 12.0845 37.2535 12.0413 37.2176C12.0202 37.2002 11.9997 37.2132 11.9604 37.2688C11.913 37.3361 11.9033 37.3397 11.8616 37.3057C11.8207 37.2724 11.6814 37.2912 11.6443 37.3352C11.6291 37.3532 11.6334 37.5415 11.6493 37.5547C11.6566 37.5608 11.6997 37.5433 11.745 37.5158ZM13.8462 39.0743C13.8869 38.9889 13.8431 39.0064 13.799 39.093C13.7784 39.1336 13.7743 39.159 13.79 39.1496C13.8057 39.1402 13.831 39.1063 13.8462 39.0743ZM11.1289 36.5535L11.1953 36.4994L11.1201 36.5114C11.0664 36.52 11.0248 36.5485 10.9743 36.6112L10.9037 36.6989L10.9831 36.6533C11.0268 36.6282 11.0924 36.5833 11.1289 36.5535ZM13.4455 38.5967C13.4832 38.5369 13.5648 38.3953 13.627 38.2821C13.6892 38.1689 13.7893 38.0035 13.8494 37.9146C13.9095 37.8257 13.9624 37.7454 13.967 37.7362C13.9715 37.7269 13.9986 37.6891 14.0272 37.6521C14.0557 37.615 14.0697 37.577 14.0583 37.5675C14.0347 37.5479 13.905 37.7294 13.7328 38.0229C13.6746 38.122 13.5866 38.2619 13.5372 38.3337C13.4597 38.4464 13.4229 38.5155 13.3656 38.6565C13.3352 38.7312 13.3839 38.6948 13.4455 38.5967ZM13.7064 38.8607C13.8018 38.6944 13.8166 38.6604 13.7998 38.6464C13.7732 38.6243 13.6916 38.7347 13.6619 38.8326C13.6271 38.9474 13.6488 38.9611 13.7064 38.8607ZM14.5265 39.5259C14.6289 39.3583 14.6416 39.2829 14.5599 39.3285C14.528 39.3463 14.4566 39.5704 14.4773 39.5876C14.4815 39.5911 14.5036 39.5633 14.5265 39.5259ZM11.8406 37.123C11.9992 37.0416 12.0137 36.9588 11.8585 37.0208C11.8082 37.0409 11.7439 37.0525 11.7157 37.0467C11.6687 37.0369 11.6647 37.0408 11.6672 37.0935C11.6687 37.1251 11.6572 37.1533 11.6416 37.1562C11.6261 37.159 11.6475 37.1615 11.6892 37.1616C11.7309 37.1617 11.7991 37.1444 11.8406 37.123ZM14.2983 39.1321C14.3502 39.0422 14.4971 38.6891 14.4864 38.6802C14.4753 38.671 14.3256 38.9067 14.2568 39.0417C14.1928 39.1674 14.2305 39.2497 14.2983 39.1321ZM11.9039 36.8845C12.0571 36.8203 12.0821 36.8023 12.1019 36.7414C12.127 36.6644 12.1346 36.6633 11.9599 36.7627C11.9199 36.7855 11.8518 36.8086 11.8085 36.814C11.7507 36.8214 11.7249 36.8379 11.7115 36.8763C11.682 36.9608 11.7181 36.9623 11.9039 36.8845ZM12.6649 37.4358C12.6846 37.3827 12.6931 37.333 12.6838 37.3253C12.6564 37.3025 12.558 37.4631 12.5545 37.5362L12.5513 37.6036L12.5902 37.5679C12.6115 37.5483 12.6451 37.4888 12.6649 37.4358ZM18.7425 42.5993C18.7293 42.5605 18.7343 42.1753 18.7482 42.1586C18.7538 42.1517 18.7465 42.0153 18.7319 41.8555C18.7173 41.6956 18.7049 41.5032 18.7043 41.4278C18.7033 41.2854 18.6474 40.9766 18.6271 41.0011C18.6207 41.0088 18.6279 41.1363 18.6431 41.2845C18.6583 41.4327 18.6675 41.619 18.6635 41.6986C18.6596 41.7782 18.6694 41.9578 18.6854 42.0979C18.7014 42.2379 18.707 42.3614 18.698 42.3723C18.6768 42.3978 18.7098 42.6336 18.7343 42.6314C18.7445 42.6305 18.7482 42.6161 18.7425 42.5993ZM11.8776 36.7028C11.9023 36.6801 11.9845 36.6311 12.0603 36.5939C12.1908 36.5298 12.2277 36.4913 12.1671 36.4826C12.1521 36.4804 12.1148 36.497 12.0841 36.5194C12.0535 36.5418 11.9871 36.5695 11.9367 36.581C11.8469 36.6013 11.8115 36.6219 11.7748 36.6753C11.7425 36.7223 11.8309 36.7459 11.8776 36.7028ZM12.8098 36.9479C12.8702 36.8532 12.8734 36.8378 12.8325 36.8376C12.7944 36.8374 12.7861 36.8296 12.7905 36.7975C12.7935 36.7756 12.7858 36.7585 12.7734 36.7596C12.7611 36.7607 12.7487 36.7785 12.746 36.799C12.7433 36.8196 12.7305 36.8542 12.7176 36.8758C12.7047 36.8975 12.6877 36.9473 12.6799 36.9865C12.672 37.0257 12.6582 37.08 12.6491 37.1071C12.6238 37.1826 12.7225 37.0849 12.8098 36.9479ZM18.58 41.968C18.5633 41.8446 18.5391 41.8371 18.5482 41.9582C18.5524 42.0135 18.564 42.0581 18.5739 42.0572C18.5838 42.0564 18.5866 42.0162 18.58 41.968ZM9.26606 34.2195C9.3023 34.2242 9.31039 34.2156 9.31719 34.1652C9.32436 34.1121 9.33534 34.1048 9.41436 34.1008C9.60543 34.0913 9.90897 33.5223 9.90838 33.1749L9.90825 33.0959L9.87147 33.16C9.85125 33.1953 9.79869 33.2936 9.75468 33.3785C9.71068 33.4634 9.64298 33.5705 9.60426 33.6164L9.53384 33.6999L9.56445 33.6126C9.58129 33.5646 9.6173 33.488 9.64448 33.4424C9.67165 33.3969 9.74307 33.2586 9.80318 33.1353C9.8633 33.0119 9.92182 32.9079 9.93323 32.9041C9.94465 32.9003 9.94609 32.8907 9.93644 32.8827C9.91312 32.8633 9.76246 32.996 9.77201 33.0275C9.77612 33.041 9.7399 33.1035 9.69153 33.1665C9.64316 33.2294 9.60233 33.2901 9.60079 33.3013C9.59926 33.3126 9.54455 33.4015 9.47922 33.4988C9.39622 33.6225 9.36513 33.6878 9.376 33.7157C9.38456 33.7377 9.37516 33.7876 9.35513 33.8265C9.33509 33.8655 9.30423 33.9468 9.28654 34.0072C9.25879 34.102 9.24933 34.1154 9.21766 34.1045C9.19746 34.0976 9.17122 34.1037 9.15934 34.118C9.13468 34.1477 9.20123 34.211 9.26606 34.2195ZM12.0106 36.2809C12.0282 36.2598 12.0197 36.2562 11.9761 36.2662C11.9444 36.2735 11.9079 36.2921 11.8951 36.3075C11.8775 36.3287 11.886 36.3323 11.9296 36.3222C11.9614 36.3149 11.9978 36.2964 12.0106 36.2809ZM14.9124 38.701L14.9615 38.6172L14.901 38.6598C14.8633 38.6863 14.8406 38.7183 14.8407 38.7446C14.841 38.8054 14.8569 38.7957 14.9124 38.701ZM9.23883 33.8888C9.30388 33.6851 9.42042 33.4326 9.51663 33.287C9.55834 33.2238 9.60456 33.1501 9.61933 33.1231C9.63411 33.0961 9.71173 32.9871 9.79181 32.8808C9.95857 32.6595 9.97503 32.6146 9.84134 32.7458C9.57089 33.0112 9.48997 33.1078 9.49496 33.1591C9.49777 33.1881 9.46211 33.2653 9.41268 33.337C9.33358 33.4519 9.27597 33.5823 9.24898 33.7075C9.24346 33.733 9.2263 33.7692 9.21083 33.7878C9.18097 33.8237 9.17933 33.8946 9.2078 33.9182C9.2172 33.926 9.23116 33.9128 9.23883 33.8888ZM12.7418 36.6655C12.7669 36.6353 12.7833 36.5983 12.7782 36.5834C12.7731 36.5684 12.7597 36.5671 12.7484 36.5804C12.7371 36.5937 12.707 36.6193 12.6816 36.6372C12.6476 36.6612 12.6434 36.6765 12.6658 36.6951C12.6869 36.7126 12.7102 36.7036 12.7418 36.6655ZM12.7694 36.4401C12.8292 36.3671 12.8325 36.3131 12.7765 36.3233C12.7442 36.3292 12.7256 36.351 12.7047 36.4072C12.6722 36.4951 12.7089 36.5137 12.7694 36.4401ZM13.0128 36.4232C13.0709 36.3457 13.1104 36.2756 13.1006 36.2674C13.0839 36.2536 12.9832 36.39 12.9147 36.519C12.8703 36.6026 12.8999 36.5737 13.0128 36.4232ZM15.817 38.4963C15.8203 38.4665 15.7525 38.4833 15.7222 38.5199C15.6643 38.5896 15.6868 38.6184 15.7538 38.5603C15.7879 38.5307 15.8164 38.5019 15.817 38.4963ZM12.9989 36.1663C13.0241 36.1183 13.0654 36.0429 13.0906 35.9988C13.1391 35.9141 13.1069 35.8428 13.0507 35.9105C13.0336 35.931 13.012 35.9415 13.0027 35.9337C12.9933 35.9259 12.9559 35.9374 12.9195 35.9592C12.867 35.9907 12.8586 36.0033 12.879 36.0203C12.8931 36.032 12.9156 36.0348 12.929 36.0266C12.9424 36.0183 12.9476 36.0665 12.9406 36.1337C12.9255 36.2778 12.937 36.2843 12.9989 36.1663ZM14.5189 36.5398C14.5615 36.4504 14.5163 36.4754 14.4654 36.5694C14.4381 36.62 14.4342 36.6421 14.4558 36.6252C14.4754 36.6098 14.5038 36.5713 14.5189 36.5398ZM13.6775 35.7526C13.7483 35.6673 13.755 35.6506 13.7172 35.6539C13.6856 35.6567 13.6557 35.685 13.6195 35.7463C13.546 35.8709 13.5765 35.8742 13.6775 35.7526ZM10.1419 32.6283C10.1682 32.5966 10.1694 32.5785 10.1457 32.5704C10.1258 32.5636 10.1026 32.5772 10.0908 32.6027C10.0616 32.6655 10.0965 32.683 10.1419 32.6283ZM14.7039 36.2191C14.7092 36.1754 14.7061 36.176 14.6817 36.2237C14.6662 36.2542 14.6375 36.3013 14.6179 36.3285C14.5903 36.3669 14.5952 36.3659 14.6401 36.3239C14.6718 36.2942 14.7005 36.2471 14.7039 36.2191ZM14.4306 35.4709C14.5205 35.3546 14.6002 35.2082 14.5459 35.2591C14.5183 35.2849 14.4392 35.3903 14.3927 35.4631C14.3782 35.4858 14.3553 35.52 14.3417 35.5391C14.2746 35.633 14.3498 35.5755 14.4306 35.4709ZM15.2243 34.6266C15.2714 34.5077 15.275 34.4788 15.2408 34.4918C15.1833 34.5137 15.1342 34.5981 15.1683 34.6165C15.1831 34.6244 15.1827 34.6461 15.1674 34.6646C15.1426 34.6944 15.1339 34.7806 15.1559 34.7787C15.1605 34.7783 15.1913 34.7098 15.2243 34.6266ZM11.7517 31.6215C11.892 31.5506 11.9099 31.5256 12.0332 31.2299C12.0497 31.1903 12.0822 31.135 12.1055 31.107C12.1287 31.079 12.1555 31.0201 12.165 30.9763C12.1744 30.9324 12.1922 30.8932 12.2045 30.8891C12.2347 30.8791 12.284 30.7306 12.263 30.7131C12.2538 30.7055 12.2403 30.7191 12.2329 30.7434C12.2256 30.7677 12.1499 30.8858 12.0647 31.0059C11.9795 31.126 11.8931 31.2531 11.8727 31.2882C11.7574 31.4869 11.7061 31.542 11.6556 31.5213C11.6068 31.5013 11.6065 31.5018 11.6209 31.5722C11.6407 31.6693 11.6502 31.6729 11.7517 31.6215ZM10.1346 30.042C10.1851 29.9755 10.2598 29.8707 10.3005 29.8091C10.3893 29.6745 10.4979 29.5224 10.5667 29.436C10.6001 29.394 10.607 29.3688 10.5869 29.3612C10.5703 29.3548 10.538 29.3753 10.5152 29.4067C10.4923 29.4381 10.409 29.5522 10.3301 29.6601C10.0863 29.9936 9.91042 30.3371 10.1346 30.042ZM10.2857 30.1297C10.3584 30.0633 10.3838 30.0164 10.4548 29.8169C10.4611 29.7994 10.4527 29.783 10.4362 29.7806C10.4159 29.7777 10.4063 29.7888 10.4064 29.8148C10.4065 29.836 10.3551 29.9269 10.2923 30.017C10.1657 30.1985 10.1632 30.2417 10.2857 30.1297ZM11.7497 31.3043C11.8061 31.2306 12.0262 30.8207 12.0236 30.794C12.0214 30.7709 12.0082 30.7789 11.9838 30.8182C11.9637 30.8505 11.9097 30.9284 11.8638 30.9913C11.8178 31.0543 11.7819 31.1232 11.784 31.1444C11.7861 31.1656 11.7682 31.2065 11.7443 31.2352C11.7205 31.264 11.7094 31.2945 11.7198 31.3031C11.7301 31.3118 11.7436 31.3123 11.7497 31.3043ZM10.9734 29.9971C10.9911 29.9641 11.0381 29.8805 11.0779 29.8113C11.1177 29.7421 11.1797 29.6265 11.2156 29.5543C11.2938 29.3973 11.2872 29.4091 11.3159 29.3745C11.3287 29.3591 11.3316 29.3402 11.3224 29.3326C11.2586 29.2796 10.916 29.8295 10.924 29.9719C10.9294 30.0674 10.9344 30.0699 10.9734 29.9971ZM12.8144 31.5949C12.8193 31.5891 12.8285 31.5577 12.8349 31.5251C12.8413 31.4925 12.8806 31.3948 12.9223 31.3079C13.1038 30.9292 13.1405 30.8424 13.1248 30.8293C13.1072 30.8147 12.9426 31.0411 12.9361 31.0888C12.934 31.1039 12.9072 31.1688 12.8764 31.233C12.8049 31.3825 12.761 31.5146 12.7704 31.552C12.7794 31.5872 12.8023 31.6095 12.8144 31.5949ZM11.1833 29.9506C11.3131 29.7899 11.3404 29.7375 11.372 29.5898C11.3804 29.5506 11.3998 29.5029 11.4153 29.4837C11.4415 29.451 11.4404 29.4498 11.3971 29.4654C11.3499 29.4825 11.2489 29.6186 11.2411 29.6758C11.2388 29.6933 11.2018 29.7734 11.1591 29.8539C10.9933 30.166 10.9971 30.1812 11.1833 29.9506ZM13.0315 31.4721C13.0504 31.437 13.0809 31.3477 13.0992 31.2738C13.1175 31.1999 13.1425 31.1361 13.1546 31.1321C13.1668 31.1281 13.1635 31.1138 13.1473 31.1004C13.11 31.0694 13.0813 31.104 13.0571 31.209C13.0466 31.2545 13.0166 31.3275 12.9904 31.3714C12.9641 31.4152 12.9423 31.4683 12.9418 31.4894C12.9404 31.5516 12.9943 31.5411 13.0315 31.4721ZM8.93327 28.0501C8.98763 28.056 9.06151 28.0146 9.15969 27.9231C9.28077 27.8103 9.26877 27.8051 9.08114 27.889C8.88567 27.9764 8.82844 28.0387 8.93327 28.0501ZM13.2276 31.4395C13.2667 31.3421 13.2929 31.2106 13.273 31.2124C13.2635 31.2132 13.1677 31.4436 13.1388 31.5351C13.1127 31.6178 13.1891 31.5356 13.2276 31.4395ZM9.94184 28.5095C10.1352 28.4824 10.8333 27.7904 10.8154 27.6436C10.8106 27.6047 10.8049 27.6082 10.7785 27.6662C10.7614 27.704 10.7293 27.7555 10.7073 27.7806C10.6853 27.8058 10.5997 27.905 10.517 28.0012C10.3442 28.2021 10.0561 28.4302 9.94577 28.4533C9.83064 28.4775 9.82728 28.5256 9.94184 28.5095ZM9.09884 27.7894C9.11066 27.7752 9.15298 27.75 9.19289 27.7334C9.2328 27.7169 9.27981 27.6862 9.29735 27.6652C9.3149 27.6441 9.34294 27.6248 9.35965 27.6222C9.40314 27.6155 9.57187 27.4974 9.56971 27.4753C9.56781 27.4556 9.51836 27.4808 9.30507 27.61C9.12259 27.7206 9.04055 27.7848 9.06049 27.8013C9.06976 27.809 9.08703 27.8037 9.09884 27.7894ZM1.13547 21.102C1.18765 20.9949 1.20855 20.9217 1.21799 20.8128C1.22909 20.6845 1.3297 20.4478 1.44672 20.2745C1.49426 20.2042 1.56293 20.0861 1.59932 20.0122C1.69546 19.817 1.94036 19.4354 2.13507 19.1774C2.22814 19.054 2.3475 18.8834 2.4003 18.7982C2.53487 18.5811 2.693 18.3687 2.72899 18.3568C2.7457 18.3512 2.8092 18.2768 2.8701 18.1913C2.931 18.1059 3.03602 17.9836 3.10349 17.9195C3.17095 17.8554 3.2798 17.747 3.34537 17.6786C3.48218 17.536 3.78063 17.2476 3.83843 17.2022C3.85991 17.1853 3.9131 17.1432 3.95664 17.1086C4.00017 17.074 4.04705 17.0419 4.0608 17.0373C4.07456 17.0328 4.15437 16.9581 4.23816 16.8715C4.32195 16.785 4.42194 16.6905 4.46038 16.6617C4.49881 16.6329 4.57068 16.5719 4.6201 16.5262C4.66952 16.4804 4.81898 16.3561 4.95224 16.2498C5.21228 16.0425 5.213 16.0419 5.4197 15.8335C5.49521 15.7574 5.5872 15.6813 5.62412 15.6644C5.66886 15.6439 5.68807 15.6243 5.68172 15.6056C5.66493 15.5563 6.06535 15.1419 6.28017 14.9863C6.47727 14.8435 6.49896 14.829 6.74314 14.6767C6.82069 14.6283 6.89933 14.5773 6.91788 14.5635C6.93644 14.5497 6.97465 14.5291 7.00278 14.5178C7.03092 14.5065 7.07088 14.4768 7.09158 14.4519C7.11228 14.4269 7.20082 14.3721 7.28834 14.3299C7.37585 14.2878 7.4584 14.2401 7.47177 14.224C7.48515 14.2079 7.57793 14.1566 7.67795 14.1099C7.77798 14.0632 7.86519 14.0192 7.87175 14.012C7.87831 14.0048 7.92797 13.9789 7.9821 13.9545C8.03624 13.93 8.09014 13.899 8.10188 13.8856C8.11362 13.8722 8.2034 13.826 8.30138 13.7831C8.39936 13.7401 8.56181 13.6558 8.66236 13.5957C8.76292 13.5356 8.87009 13.4843 8.90053 13.4816C8.9383 13.4783 8.95479 13.4656 8.95246 13.4416C8.94842 13.4 8.81353 13.4165 8.77282 13.4635C8.7586 13.4799 8.72738 13.4933 8.70346 13.4932C8.67954 13.4931 8.63139 13.5178 8.59646 13.5482C8.56153 13.5785 8.4605 13.6184 8.37194 13.6368C8.19953 13.6726 8.12774 13.7045 8.04219 13.7835C8.01251 13.8109 7.9704 13.8328 7.94862 13.832C7.89706 13.8303 7.7839 13.8865 7.74528 13.933C7.72858 13.9531 7.65653 13.9955 7.58516 14.0273C7.5138 14.059 7.38968 14.132 7.30935 14.1894C7.22902 14.2469 7.10414 14.3192 7.03184 14.3502C6.89294 14.4098 6.7355 14.5042 6.65444 14.5764C6.62767 14.6003 6.49625 14.697 6.36241 14.7914C6.22857 14.8858 6.1057 14.9732 6.08933 14.9856C6.07297 14.9981 5.9989 15.0538 5.92472 15.1095C5.83308 15.1783 5.76478 15.249 5.71165 15.3302C5.62277 15.4661 5.53891 15.5168 5.50433 15.4556C5.49104 15.4321 5.48153 15.4293 5.47896 15.4482C5.47313 15.4909 5.40758 15.4631 5.403 15.4159C5.40015 15.3866 5.39001 15.3938 5.36263 15.4447C5.33554 15.495 5.30929 15.5141 5.26125 15.5183C5.18198 15.5253 5.03912 15.5893 4.95955 15.6535C4.92707 15.6797 4.89731 15.6917 4.89341 15.6803C4.88952 15.6689 4.87818 15.6703 4.86825 15.6836C4.83322 15.7302 4.7191 15.8039 4.70282 15.7904C4.69375 15.7828 4.67279 15.793 4.65623 15.8129C4.63968 15.8329 4.61538 15.8476 4.60223 15.8457C4.58908 15.8438 4.51571 15.8867 4.43918 15.9409C4.36264 15.9952 4.27611 16.0434 4.24689 16.0482C4.21766 16.0529 4.13697 16.1099 4.06757 16.1748C3.99817 16.2396 3.89763 16.3113 3.84416 16.3341C3.79068 16.3569 3.73724 16.3963 3.7254 16.4218C3.71356 16.4473 3.69053 16.4662 3.67421 16.4639C3.6579 16.4615 3.63948 16.4747 3.63327 16.4932C3.62707 16.5117 3.58161 16.5552 3.53226 16.5897C3.48291 16.6243 3.42315 16.672 3.39944 16.6957C3.37574 16.7194 3.26882 16.8081 3.16184 16.8928C3.05486 16.9775 2.93037 17.08 2.88521 17.1206C2.84006 17.1611 2.74281 17.2314 2.66912 17.2767C2.58655 17.3274 2.52968 17.3771 2.52092 17.406C2.50984 17.4427 2.53432 17.4351 2.63211 17.3714C2.74711 17.2965 2.9 17.2418 2.79435 17.3133C2.70627 17.3729 2.36735 17.7224 2.31133 17.8114C2.27904 17.8627 2.19061 17.9878 2.11482 18.0894C2.03903 18.191 1.96431 18.3065 1.94877 18.3459C1.93324 18.3853 1.83486 18.5556 1.73017 18.7242C1.59789 18.9372 1.53512 19.0605 1.52449 19.1281C1.51606 19.1817 1.4996 19.2286 1.4879 19.2325C1.47621 19.2364 1.45801 19.2821 1.44746 19.3341C1.43582 19.3914 1.43915 19.4161 1.45593 19.3969C1.51219 19.3324 1.6685 19.0541 1.72769 18.913C1.76128 18.8329 1.84372 18.6926 1.91091 18.6012C1.97809 18.5098 2.08988 18.3502 2.15934 18.2466C2.31898 18.0084 2.96994 17.2515 3.1533 17.0907C3.22954 17.0239 3.32697 16.9309 3.36979 16.8841C3.41262 16.8373 3.4757 16.7832 3.50996 16.7639C3.54423 16.7446 3.63878 16.6775 3.72007 16.6149C3.95463 16.4342 3.94861 16.4375 3.93831 16.4945C3.93031 16.5386 3.712 16.7777 3.66561 16.7931C3.50222 16.8473 2.52553 17.9675 2.31865 18.338C2.25907 18.4447 2.17152 18.585 2.1241 18.6497C2.07668 18.7144 1.99113 18.8597 1.934 18.9726C1.87687 19.0855 1.80256 19.2111 1.76886 19.2516C1.73516 19.2922 1.71175 19.3377 1.71684 19.3526C1.72193 19.3676 1.70275 19.4079 1.67421 19.4423C1.64567 19.4767 1.61197 19.5508 1.59932 19.607C1.58667 19.6632 1.54242 19.7875 1.50097 19.8833C1.45952 19.979 1.41535 20.0935 1.4028 20.1378C1.39026 20.1821 1.37532 20.2239 1.3696 20.2308C1.36388 20.2377 1.36142 20.2661 1.36412 20.2939C1.36767 20.3304 1.34705 20.3646 1.29018 20.4166C1.2329 20.4689 1.20986 20.5074 1.20597 20.5573C1.20302 20.595 1.18665 20.6431 1.16959 20.6641C1.10331 20.7458 1.04121 21.1105 1.0871 21.1486C1.09748 21.1573 1.11834 21.1371 1.13547 21.102ZM13.2744 31.135C13.3017 31.0697 13.312 30.8801 13.2882 30.8822C13.2786 30.8831 13.268 30.9235 13.2646 30.9721C13.2611 31.0206 13.2484 31.0724 13.2362 31.0871C13.2109 31.1175 13.2106 31.153 13.2355 31.1736C13.2448 31.1813 13.2623 31.164 13.2744 31.135ZM9.41842 27.7354C9.4825 27.6896 9.53419 27.6444 9.53327 27.635C9.53043 27.6057 9.3598 27.7052 9.30998 27.7652C9.2449 27.8436 9.28072 27.8337 9.41842 27.7354ZM0.917738 20.7161C0.929989 20.6872 0.948422 20.6294 0.958701 20.5875C0.968981 20.5457 0.990275 20.4959 1.00602 20.477C1.02177 20.458 1.02617 20.4355 1.01581 20.4268C1.00545 20.4182 1.00493 20.4016 1.01466 20.3899C1.03358 20.3671 1.08775 20.1748 1.10729 20.0611C1.11381 20.0231 1.12943 19.9616 1.14201 19.9243C1.15458 19.887 1.15619 19.8493 1.14557 19.8405C1.13248 19.8296 1.12629 19.8372 1.12634 19.864C1.12639 19.8857 1.1046 19.9421 1.07793 19.9894C1.05127 20.0367 1.02139 20.1112 1.01154 20.1551C1.00169 20.199 0.986383 20.2679 0.977525 20.3083C0.968667 20.3487 0.939391 20.412 0.912468 20.449C0.885544 20.4861 0.864836 20.5445 0.866452 20.5789C0.868071 20.6133 0.861802 20.6506 0.852523 20.6618C0.836636 20.6809 0.849516 20.7224 0.881286 20.7543C0.889095 20.7622 0.905485 20.745 0.917738 20.7161ZM1.59792 21.2208C1.60777 21.209 1.6599 21.1893 1.71376 21.1772C1.76762 21.165 1.81925 21.146 1.82849 21.1348C1.84525 21.1146 2.20502 20.8875 2.29361 20.8412C2.31925 20.8277 2.42936 20.7559 2.53828 20.6815C2.64721 20.6071 2.78358 20.5145 2.84132 20.4757C2.89906 20.4368 2.97348 20.378 3.00671 20.3448C3.08483 20.2669 3.21502 20.1738 3.50687 19.9872C3.63673 19.9041 3.77435 19.8055 3.81269 19.7679C3.85104 19.7303 3.91101 19.6807 3.94595 19.6577C3.9809 19.6347 4.15001 19.4911 4.32176 19.3388C4.79928 18.9151 4.83763 18.8881 4.63013 19.1216C4.53253 19.2314 4.42741 19.3429 4.39654 19.3693C4.23793 19.5051 4.09968 19.6434 4.11218 19.6538C4.11994 19.6602 4.18911 19.6108 4.26591 19.5439C4.3427 19.477 4.41651 19.4239 4.42992 19.4258C4.44334 19.4278 4.49757 19.3774 4.55043 19.3139C4.60329 19.2503 4.69774 19.1557 4.76031 19.1035C4.90129 18.986 5.74666 17.9878 5.91828 17.7362C6.22807 17.282 6.60412 16.8305 6.75219 16.7349C7.09706 16.5124 7.41529 16.2656 7.93096 15.8208C7.98733 15.7722 8.23244 15.5001 8.47564 15.2162C8.72054 14.9303 8.963 14.665 9.01907 14.6217C9.07475 14.5786 9.14647 14.5033 9.17844 14.4543C9.21042 14.4053 9.24298 14.3563 9.2508 14.3454C9.25862 14.3346 9.23566 14.3379 9.19978 14.3528C9.15845 14.3699 9.04237 14.4817 8.88306 14.6577C8.74475 14.8105 8.57323 14.9864 8.5019 15.0487C8.43058 15.1109 8.32492 15.2149 8.26711 15.2796C8.08785 15.4805 7.87585 15.6911 7.80008 15.7436C7.71495 15.8026 7.53185 15.9579 7.36777 16.1103C7.30365 16.1698 7.1954 16.2574 7.12721 16.3049C7.05903 16.3524 6.98788 16.4069 6.9691 16.426C6.95032 16.4451 6.9224 16.4646 6.90704 16.4694C6.89169 16.4741 6.84503 16.5064 6.80336 16.541C6.73314 16.5995 6.68407 16.6136 6.64879 16.5855C6.61862 16.5614 6.76615 16.4376 7.12079 16.1892C7.2058 16.1296 7.32755 16.0319 7.39135 15.9721C7.45515 15.9123 7.55111 15.8287 7.6046 15.7864C7.78449 15.644 8.18667 15.264 8.42207 15.0139C8.50459 14.9263 8.59696 14.8326 8.62733 14.8058C8.65771 14.7789 8.74664 14.6895 8.82496 14.6071C8.90328 14.5246 9.03385 14.3945 9.1151 14.318C9.25011 14.1908 9.2931 14.1598 9.43441 14.0878C9.53235 14.0378 9.69177 13.9321 9.6904 13.918C9.68962 13.91 9.64276 13.9292 9.58628 13.9608C9.49198 14.0136 9.3677 14.0301 9.3546 13.9916C9.35162 13.9829 9.33354 13.9933 9.31445 14.0148C9.241 14.0976 9.02874 14.298 8.88497 14.4203C8.74403 14.5401 8.68779 14.5849 8.45334 14.7638C8.40162 14.8033 8.30686 14.8914 8.24275 14.9597C8.10913 15.1019 8.02364 15.1792 7.93355 15.2393C7.89877 15.2624 7.79897 15.3464 7.71176 15.4258C7.62456 15.5053 7.547 15.5651 7.5394 15.5588C7.53181 15.5525 7.51054 15.5667 7.49214 15.5905C7.4385 15.6598 7.1211 15.9443 7.07756 15.9621C7.00981 15.9898 6.8554 16.1163 6.78333 16.203C6.70866 16.293 6.64098 16.3093 6.60526 16.2461C6.5812 16.2035 6.71335 16.0587 6.83959 15.9893C6.9283 15.9405 7.08667 15.8234 7.2328 15.6985C7.30489 15.6369 7.4223 15.5428 7.4937 15.4893C7.56511 15.4358 7.64382 15.3734 7.66862 15.3506C7.69341 15.3278 7.74997 15.2754 7.7943 15.2341C7.83863 15.1928 7.89991 15.1443 7.93049 15.1263C7.96106 15.1083 8.05829 15.0258 8.14655 14.9429C8.23481 14.86 8.38277 14.7274 8.47536 14.6481C9.07258 14.1365 9.30197 13.9033 9.3328 13.7761C9.34353 13.7319 9.36202 13.7136 9.41118 13.6988C9.44656 13.6881 9.50578 13.655 9.54276 13.6252C9.57975 13.5954 9.68268 13.5249 9.7715 13.4685C10.1449 13.2314 10.6618 12.8306 10.6048 12.8224C10.5914 12.8204 10.5687 12.8329 10.5545 12.85C10.5214 12.8899 10.0106 13.1998 9.96916 13.2052C9.95198 13.2074 9.91918 13.2318 9.89628 13.2593C9.86118 13.3016 9.72532 13.4006 9.59441 13.4792C9.57622 13.4902 9.5291 13.5337 9.48969 13.5761C9.45028 13.6184 9.40067 13.6546 9.37944 13.6565C9.35821 13.6584 9.32828 13.675 9.31292 13.6935C9.29757 13.712 9.27615 13.7198 9.26532 13.7108C9.21625 13.67 9.0761 13.7104 9.01623 13.7825C8.9809 13.825 8.90791 13.874 8.84192 13.8994C8.77947 13.9235 8.69495 13.9722 8.65409 14.0077C8.57654 14.0751 8.49632 14.127 8.37663 14.1875C8.33765 14.2072 8.26653 14.251 8.21859 14.285C8.17065 14.3189 8.12236 14.3392 8.11129 14.33C8.0998 14.3204 8.10831 14.3038 8.13111 14.2912C8.15308 14.2791 8.21767 14.2305 8.27464 14.1833C8.33162 14.1361 8.41809 14.076 8.46681 14.0497C8.51553 14.0235 8.55448 13.9927 8.55338 13.9814C8.55228 13.97 8.53248 13.9719 8.50938 13.9856C8.48628 13.9993 8.4224 14.0327 8.36743 14.0598C8.31245 14.0869 8.26291 14.1146 8.25734 14.1214C8.25176 14.1281 8.21178 14.1499 8.16849 14.1698C8.07497 14.2128 7.67912 14.4536 7.12494 14.8045C7.02416 14.8683 6.93787 14.9302 6.93319 14.942C6.92851 14.9539 6.88411 14.9951 6.83453 15.0336C6.78495 15.0722 6.69709 15.1425 6.63929 15.1899C6.58149 15.2374 6.46783 15.3303 6.38671 15.3965C6.3056 15.4627 6.19146 15.5762 6.13308 15.6487C6.01951 15.7899 5.98428 15.8134 5.94066 15.7772C5.89845 15.7421 5.94835 15.6279 6.04183 15.5457C6.08748 15.5055 6.15192 15.4454 6.18503 15.4122C6.37577 15.2206 6.90442 14.804 7.05113 14.7295C7.11251 14.6984 7.18188 14.6498 7.20529 14.6216C7.2287 14.5934 7.31487 14.5348 7.39678 14.4914C7.47869 14.448 7.64081 14.3494 7.75705 14.2724C7.87328 14.1954 7.98222 14.1297 7.99913 14.1264C8.01604 14.1231 8.10106 14.0801 8.18805 14.0309C8.27504 13.9817 8.43084 13.9077 8.53427 13.8664C8.6377 13.8252 8.73095 13.781 8.74148 13.7683C8.75202 13.7557 8.80648 13.7246 8.86251 13.6993C8.96857 13.6514 9.05591 13.5685 9.02625 13.5438C9.01681 13.536 8.95928 13.552 8.89841 13.5795C8.83753 13.6069 8.77604 13.6277 8.76176 13.6256C8.74748 13.6236 8.71001 13.6529 8.6785 13.6907C8.64421 13.732 8.55284 13.7891 8.45094 13.8331C8.3573 13.8736 8.25278 13.9288 8.21868 13.9558C8.18459 13.9828 8.09118 14.0357 8.01112 14.0733C7.68002 14.2289 7.58675 14.2773 7.56361 14.3051C7.55021 14.3213 7.50578 14.3514 7.46488 14.3721C7.37492 14.4177 7.15164 14.5344 7.08826 14.569C7.04821 14.5908 6.89269 14.6952 6.55238 14.9285C6.50088 14.9638 6.40652 15.0345 6.3427 15.0857C6.27887 15.1368 6.20155 15.1932 6.17087 15.2111C6.10702 15.2484 6.02895 15.3328 5.88531 15.5198C5.80831 15.6201 5.77065 15.6527 5.7248 15.6591C5.68048 15.6652 5.62387 15.7125 5.50723 15.8406C5.35306 16.01 5.09639 16.2408 4.6941 16.572C4.58391 16.6627 4.42948 16.7971 4.35093 16.8707C4.27238 16.9443 4.13594 17.0652 4.04773 17.1395C3.95951 17.2137 3.81641 17.3434 3.72973 17.4275C3.64303 17.5117 3.54302 17.6061 3.50748 17.6374C3.44875 17.6889 3.33195 17.8135 2.95023 18.2316C2.8372 18.3553 2.65821 18.5961 2.34843 19.0411C2.30633 19.1016 2.22163 19.2174 2.16021 19.2984C2.05755 19.4338 1.90534 19.6832 1.75908 19.9557C1.72687 20.0158 1.66016 20.1307 1.61085 20.2113C1.56154 20.2918 1.48758 20.4139 1.44649 20.4826C1.40539 20.5514 1.36173 20.611 1.34945 20.615C1.33718 20.6191 1.33505 20.629 1.34474 20.6371C1.35527 20.6458 1.5057 20.4758 1.71887 20.2142C1.91496 19.9736 2.10461 19.7543 2.14034 19.7269C2.17605 19.6995 2.21729 19.6508 2.23198 19.6187C2.24666 19.5867 2.31772 19.5007 2.38987 19.4277C2.46203 19.3547 2.62098 19.1862 2.7431 19.0534C2.86522 18.9205 3.00454 18.7735 3.05269 18.7268C3.10084 18.68 3.24819 18.5184 3.38012 18.3677C3.51206 18.2169 3.65006 18.071 3.68677 18.0434C3.72349 18.0158 3.81802 17.9027 3.89683 17.792C4.04942 17.5776 5.18515 16.2353 5.22515 16.222C5.23821 16.2177 5.31698 16.1489 5.4002 16.0693C5.65408 15.8262 5.75049 15.8042 5.53376 16.0388C5.4385 16.1419 5.32836 16.2492 5.28899 16.2772C5.24962 16.3053 4.89968 16.7104 4.51134 17.1774C3.52123 18.3683 3.12915 18.8189 2.73447 19.2197C2.5509 19.4061 2.00321 20.0428 1.92089 20.1655C1.80955 20.3314 1.86675 20.3141 2.04794 20.1271C2.12088 20.0518 2.20051 19.9713 2.22488 19.9481C2.24926 19.925 2.33764 19.8351 2.42128 19.7484C2.50492 19.6617 2.65584 19.5173 2.75667 19.4275C2.85749 19.3377 3.02896 19.1819 3.1377 19.0813C3.24643 18.9807 3.35386 18.8854 3.37644 18.8694C3.66743 18.6635 4.38535 17.8925 4.56928 17.5883C4.72441 17.3317 4.98476 17.0173 4.99198 17.0777C5.01136 17.2397 3.70462 18.8137 3.49234 18.8841C3.47622 18.8894 3.29887 19.0494 3.10835 19.2305C2.91843 19.411 2.8746 19.4495 2.77609 19.5225C2.74848 19.5429 2.61931 19.677 2.48904 19.8205C2.35876 19.9639 2.21838 20.1171 2.17706 20.1608C1.57153 20.8022 1.53215 20.8823 2.02289 20.4745C2.19521 20.3313 2.40899 20.1539 2.49795 20.0802C2.58691 20.0066 2.70301 19.9015 2.75598 19.8466C2.80894 19.7917 2.91615 19.6961 2.99423 19.6342C3.07231 19.5723 3.17536 19.4745 3.22324 19.4169C3.27112 19.3593 3.35335 19.2766 3.40596 19.2333C3.45857 19.19 3.5801 19.0629 3.67601 18.9509C3.77192 18.8388 3.89194 18.7131 3.94272 18.6715C4.07219 18.5655 4.61511 17.9297 4.74392 17.7333C4.80286 17.6434 4.87525 17.5419 4.90479 17.5076C4.93433 17.4734 5.06171 17.2952 5.18787 17.1117C5.54619 16.5904 6.02387 15.9907 6.08048 15.9909C6.14523 15.9912 6.13339 16.0323 6.03533 16.1475C5.8211 16.3992 5.28502 17.1077 5.27978 17.146C5.27735 17.1638 4.9442 17.6365 4.71564 17.9465C4.67199 18.0056 4.4707 18.236 4.26831 18.4584C4.06593 18.6808 3.84115 18.9361 3.76881 19.0259C3.69647 19.1156 3.59374 19.2219 3.54052 19.2622C3.4873 19.3025 3.38913 19.3965 3.32238 19.4712C3.25563 19.546 3.15006 19.65 3.0878 19.7024C3.02553 19.7548 2.92054 19.8522 2.85448 19.9188C2.78843 19.9854 2.70281 20.0634 2.6642 20.0921C2.6256 20.1207 2.55909 20.1843 2.5164 20.2333C2.47371 20.2822 2.4274 20.3261 2.41349 20.3307C2.38509 20.3401 2.12175 20.5602 1.99998 20.6763L1.92039 20.7522L1.99624 20.7241C2.03795 20.7087 2.08931 20.6804 2.11037 20.6612C2.13142 20.6419 2.20754 20.5825 2.27953 20.529C2.35152 20.4755 2.44954 20.3948 2.49736 20.3496C2.54519 20.3044 2.61855 20.2496 2.66041 20.2279C2.70227 20.2062 2.79576 20.1265 2.86817 20.0508C2.94058 19.9752 3.03337 19.8914 3.07435 19.8648C3.16837 19.8035 3.51613 19.5142 3.6437 19.391C3.69685 19.3397 3.78638 19.2579 3.84263 19.2092C4.12871 18.9615 4.56741 18.4969 4.93641 18.0509C5.13214 17.8144 5.30447 17.6025 5.31938 17.5802C5.37914 17.4906 5.56628 17.2871 5.56843 17.3094C5.58073 17.436 4.61598 18.602 3.96477 19.2475C3.65066 19.5589 3.52227 19.6781 3.46923 19.7077C3.45207 19.7172 3.44565 19.7314 3.45498 19.7391C3.47454 19.7554 3.63941 19.6441 3.69505 19.5771C3.71574 19.5522 3.74355 19.5333 3.75684 19.5353C3.77013 19.5372 3.85309 19.4635 3.94121 19.3715C4.02933 19.2795 4.12935 19.1885 4.16347 19.1694C4.19759 19.1502 4.24944 19.1114 4.27869 19.0832C4.30793 19.0549 4.44014 18.93 4.57247 18.8057C5.00932 18.3951 5.7992 17.4884 6.06358 17.0939C6.12335 17.0048 6.20492 16.8889 6.24484 16.8364C6.28569 16.7827 6.31027 16.7296 6.30105 16.7148C6.29203 16.7004 6.30547 16.6635 6.3309 16.6329C6.35634 16.6023 6.38167 16.5547 6.3872 16.5271C6.40276 16.4495 6.50887 16.3752 6.55248 16.4115C6.57253 16.4281 6.57742 16.4455 6.56335 16.4502C6.53942 16.4581 6.49161 16.5366 6.3329 16.8286C6.29715 16.8943 6.24239 16.9837 6.2112 17.0273C6.18002 17.0708 6.09494 17.1918 6.02214 17.2962C5.88266 17.4962 5.33302 18.1619 5.05632 18.466C4.90192 18.6357 4.56772 18.9568 4.28126 19.2106C4.1501 19.3269 4.13146 19.3449 3.8989 19.5795C3.82574 19.6534 3.75529 19.7122 3.74234 19.7104C3.71138 19.7059 3.51473 19.8615 3.42175 19.964C3.32322 20.0726 3.18628 20.1788 3.0189 20.2762C2.84927 20.375 2.7432 20.4497 2.69723 20.5029C2.66794 20.5367 2.6284 20.5676 2.60936 20.5716C2.55486 20.583 2.28932 20.7332 2.25879 20.77C2.24364 20.7883 2.19632 20.8208 2.15363 20.8423C2.11095 20.8639 2.03712 20.901 1.98957 20.9249C1.94203 20.9488 1.89337 20.9801 1.88144 20.9944C1.86951 21.0088 1.84442 21.0219 1.8257 21.0236C1.80697 21.0252 1.75303 21.0578 1.70583 21.096C1.65862 21.1341 1.6016 21.1749 1.57911 21.1866C1.55452 21.1994 1.54653 21.2148 1.55907 21.2252C1.57054 21.2347 1.58806 21.2327 1.59792 21.2208ZM16.8159 33.79C16.8342 33.7672 16.8504 33.7219 16.8517 33.6894C16.853 33.6568 16.8684 33.6128 16.8858 33.5915C16.9032 33.5702 16.9353 33.5037 16.9571 33.4437C16.9789 33.3838 17.0239 33.2792 17.0572 33.2114C17.1424 33.0377 17.415 32.4638 17.5057 32.2672C17.5475 32.1765 17.6049 32.0744 17.6332 32.0403C17.6616 32.0062 17.6842 31.9643 17.6835 31.9473C17.6829 31.9303 17.7243 31.8447 17.7756 31.7572C17.827 31.6697 17.8859 31.5624 17.9065 31.5188C17.9272 31.4753 17.9979 31.3565 18.0636 31.2549C18.1704 31.0899 18.2436 30.9648 18.4484 30.5964C18.4814 30.5371 18.5582 30.3666 18.6191 30.2176C18.68 30.0686 18.7546 29.8892 18.7849 29.8189C18.8328 29.7079 18.868 29.597 18.9435 29.3195C18.9809 29.182 18.778 29.5325 18.5549 29.9907C18.4948 30.1143 18.4095 30.2698 18.3656 30.3362C18.3216 30.4027 18.276 30.4855 18.2642 30.5203C18.2394 30.5939 18.1779 30.7128 18.0391 30.9556C17.9842 31.0517 17.9192 31.1744 17.8946 31.2283C17.87 31.2823 17.8252 31.3706 17.7951 31.4245C17.7649 31.4785 17.6986 31.6089 17.6478 31.7142C17.597 31.8195 17.5114 31.9826 17.4576 32.0768C17.1972 32.5324 16.799 33.3791 16.785 33.5067C16.7809 33.5447 16.7655 33.5798 16.7508 33.5846C16.7168 33.5959 16.7226 33.8228 16.757 33.8277C16.771 33.8298 16.7975 33.8128 16.8159 33.79ZM1.6639 20.5362C1.74505 20.4366 1.81081 20.3485 1.81004 20.3405C1.80709 20.3101 1.59178 20.5354 1.53713 20.626C1.4484 20.773 1.50187 20.7352 1.6639 20.5362ZM1.06481 19.8307C1.11455 19.7451 1.16216 19.6453 1.17062 19.6089C1.19227 19.5159 1.3314 19.2403 1.38947 19.1754C1.44748 19.1106 1.50025 19.022 1.50601 18.9798C1.51616 18.9053 1.84793 18.3511 2.17764 17.858C2.20375 17.819 2.26273 17.7402 2.30871 17.6829C2.37321 17.6026 2.38172 17.5826 2.34595 17.5955C2.32046 17.6047 2.23932 17.6864 2.16565 17.7771C2.09198 17.8677 2.00942 17.966 1.98219 17.9954C1.95496 18.0249 1.89611 18.1038 1.85143 18.1708C1.80674 18.2378 1.72581 18.3536 1.67159 18.4281C1.52383 18.6311 1.43071 18.7801 1.3656 18.9177C1.33341 18.9857 1.27388 19.0813 1.23332 19.1302C1.16365 19.214 1.14719 19.2539 1.07225 19.5201C1.05532 19.5803 1.02506 19.6493 1.00501 19.6734C0.984961 19.6976 0.972587 19.7383 0.977512 19.764C0.982437 19.7897 0.978407 19.8204 0.968557 19.8323C0.944755 19.861 0.935372 19.9898 0.957228 19.9879C0.966661 19.9871 1.01507 19.9163 1.06481 19.8307ZM1.39198 19.609C1.43692 19.4795 1.44172 19.4159 1.40303 19.4624C1.38903 19.4793 1.38175 19.5053 1.38684 19.5203C1.39193 19.5352 1.3786 19.5685 1.35722 19.5943C1.30843 19.653 1.28233 19.7667 1.32346 19.7413C1.33929 19.7315 1.37012 19.672 1.39198 19.609ZM2.93329 20.5647C3.05884 20.4826 3.26584 20.3297 3.65516 20.0315C3.88574 19.8548 3.88407 19.8563 3.84497 19.8594C3.8249 19.861 3.7256 19.9276 3.6243 20.0074C3.523 20.0873 3.41952 20.1602 3.39435 20.1694C3.36918 20.1786 3.32523 20.2143 3.29668 20.2487C3.26814 20.283 3.23419 20.3121 3.22125 20.3132C3.17796 20.3171 3.03162 20.4114 2.96009 20.4816C2.92118 20.5198 2.86126 20.5668 2.82695 20.5861C2.74902 20.6299 2.7179 20.6648 2.76118 20.6599C2.77868 20.658 2.85612 20.6151 2.93329 20.5647ZM3.14853 20.039C3.25602 19.9608 3.35576 19.8459 3.33276 19.8268C3.31848 19.815 3.16566 19.9427 3.05407 20.0597C2.99408 20.1227 3.05061 20.1103 3.14853 20.039ZM14.3461 28.521C14.3901 28.4227 14.3814 28.3919 14.335 28.4821C14.287 28.5754 14.2757 28.6088 14.2926 28.6073C14.301 28.6066 14.3251 28.5677 14.3461 28.521ZM3.99814 19.7642C4.05163 19.7181 4.06074 19.7034 4.03028 19.712C4.0069 19.7186 3.96728 19.7484 3.94225 19.7782C3.88229 19.8497 3.90557 19.8438 3.99814 19.7642ZM14.5646 25.8144C14.7026 25.6547 14.7255 25.6181 14.7193 25.5666C14.7123 25.5084 14.708 25.5119 14.6081 25.6564C14.3372 26.0481 14.3254 26.091 14.5646 25.8144ZM10.6117 22.5707C10.7075 22.5528 10.7928 22.5298 10.8014 22.5194C10.8285 22.4867 11.2255 22.3026 11.3904 22.2462C11.4777 22.2164 11.5956 22.1652 11.6525 22.1325C11.7093 22.0998 11.7765 22.069 11.8017 22.0639C11.827 22.0589 11.8863 22.03 11.9334 21.9997C11.9805 21.9695 12.0327 21.9418 12.0493 21.9382C12.0659 21.9346 12.1408 21.894 12.2158 21.848C12.2908 21.8019 12.42 21.7318 12.503 21.692C12.5859 21.6523 12.7519 21.5665 12.8719 21.5013C12.9919 21.4361 13.1033 21.3795 13.1194 21.3755C13.1355 21.3715 13.1857 21.3423 13.2311 21.3105C13.2765 21.2788 13.3735 21.2174 13.4468 21.1741C13.52 21.1308 13.5958 21.0829 13.6152 21.0677C13.6583 21.0337 14.1012 20.7638 14.1673 20.7313C14.2378 20.6965 14.4519 20.5384 14.489 20.4937C14.5067 20.4723 14.5656 20.436 14.6197 20.4129C14.6739 20.3898 14.7298 20.357 14.744 20.3399C14.7582 20.3228 14.8136 20.2831 14.867 20.2515C14.9205 20.22 15.0551 20.1277 15.1662 20.0464C15.3781 19.8913 15.6754 19.7061 15.7339 19.6926C15.7528 19.6883 15.8284 19.6446 15.9018 19.5955C16.1822 19.408 16.6864 19.0654 16.7343 19.0296C16.7619 19.0091 16.872 18.9302 16.9791 18.8543C17.0861 18.7783 17.1908 18.6959 17.2116 18.6712L17.2495 18.6261L17.1629 18.6307C16.9904 18.64 16.9298 18.6701 16.7585 18.832C16.6667 18.9189 16.5594 19.0058 16.5201 19.0252C16.4808 19.0447 16.3912 19.0942 16.3209 19.1352C16.2506 19.1763 16.173 19.2183 16.1484 19.2286C16.1238 19.2389 16.0195 19.3194 15.9166 19.4075C15.8138 19.4957 15.7098 19.576 15.6856 19.5859C15.6613 19.596 15.624 19.6252 15.6026 19.651C15.5812 19.6768 15.5073 19.7327 15.4383 19.7753C15.3694 19.8179 15.1982 19.9278 15.0578 20.0194C14.9174 20.1111 14.732 20.2269 14.6458 20.2768C14.5596 20.3267 14.4139 20.4116 14.3221 20.4654C14.2302 20.5193 14.1256 20.5788 14.0895 20.5977C14.0534 20.6166 14.0151 20.6427 14.0043 20.6557C13.9935 20.6687 13.9291 20.703 13.8611 20.7319C13.7931 20.7608 13.7026 20.8088 13.66 20.8385C13.6173 20.8681 13.5743 20.8856 13.5644 20.8774C13.5544 20.8691 13.5329 20.8784 13.5166 20.8981C13.4807 20.9412 13.1617 21.1274 12.9881 21.2065C12.9193 21.2379 12.8558 21.2721 12.847 21.2827C12.8383 21.2933 12.8097 21.3018 12.7835 21.3017C12.7574 21.3015 12.7222 21.318 12.7054 21.3383C12.6885 21.3586 12.6446 21.3877 12.6076 21.4031C12.5167 21.4411 12.4325 21.4849 12.3764 21.5235C12.3508 21.5411 12.3107 21.5575 12.2873 21.5599C12.2273 21.566 12.0879 21.635 12.0075 21.6984C11.9083 21.7768 11.6919 21.8714 11.6148 21.8702C11.5702 21.8695 11.5256 21.8932 11.4795 21.9419C11.4081 22.0174 11.1876 22.1596 11.0008 22.2507C10.9416 22.2796 10.8288 22.342 10.7501 22.3895C10.6714 22.437 10.5637 22.4957 10.5106 22.5199C10.3459 22.5953 10.3822 22.6136 10.6117 22.5707ZM11.2583 22.5515C11.3247 22.5378 11.4513 22.5186 11.5397 22.5088C11.887 22.4702 12.3093 22.3519 12.3729 22.2753C12.3789 22.268 12.4297 22.2472 12.4857 22.229C12.5417 22.2108 12.655 22.1561 12.7375 22.1075C12.82 22.0589 12.8939 22.0244 12.9018 22.0309C12.9097 22.0375 12.927 22.0297 12.9402 22.0137C12.9652 21.9837 13.2598 21.8243 13.514 21.7033C13.713 21.6085 14.1078 21.3797 14.3755 21.204C14.4981 21.1235 14.7445 20.9733 14.9232 20.87C15.1019 20.7668 15.27 20.665 15.2967 20.6438C15.4684 20.5075 16.0621 20.072 16.144 20.0222C16.1983 19.9893 16.2745 19.9367 16.3133 19.9054C16.3957 19.839 16.6544 19.6965 16.8007 19.6369C16.8789 19.605 16.9251 19.5663 16.9994 19.4706C17.0541 19.4002 17.1466 19.3122 17.2118 19.2684C17.3447 19.1793 17.5534 19.0191 17.6463 18.935L17.7099 18.8774L17.6105 18.9211C17.5558 18.9451 17.4818 18.9901 17.446 19.0211C17.4102 19.0522 17.3484 19.0931 17.3086 19.1121C17.2688 19.1311 17.2044 19.1771 17.1656 19.2142C17.1268 19.2514 17.0461 19.3051 16.9863 19.3335C16.8664 19.3905 16.697 19.5028 16.6815 19.5355C16.667 19.5662 16.4726 19.6865 16.3255 19.7558C16.2552 19.789 16.1917 19.8232 16.1846 19.8318C16.1682 19.8515 15.9431 19.9762 15.8745 20.0036C15.8463 20.0149 15.7845 20.0664 15.7373 20.118C15.69 20.1697 15.601 20.2449 15.5394 20.285C15.4779 20.3252 15.3943 20.3801 15.3537 20.4072C15.3131 20.4342 15.2582 20.4667 15.2318 20.4795C15.2054 20.4923 15.1066 20.5593 15.0122 20.6284C14.9178 20.6975 14.7899 20.7758 14.7278 20.8024C14.6658 20.829 14.5667 20.8816 14.5077 20.9194C14.1993 21.1168 14.085 21.1805 13.7688 21.3311C13.6824 21.3723 13.5882 21.4217 13.5592 21.4411C13.4656 21.5038 12.8827 21.8091 12.8498 21.8127C12.8322 21.8146 12.8077 21.8284 12.7953 21.8433C12.7829 21.8583 12.7277 21.8807 12.6727 21.8931C12.6177 21.9055 12.5429 21.9335 12.5066 21.9552C12.4702 21.977 12.4327 21.9885 12.4234 21.9808C12.414 21.973 12.3934 21.9822 12.3776 22.0013C12.3618 22.0204 12.2872 22.0498 12.2118 22.0668C12.1365 22.0838 12.0606 22.1147 12.0433 22.1356C12.0043 22.1825 11.7976 22.2858 11.6437 22.3352C11.5803 22.3555 11.5179 22.3849 11.5049 22.4006C11.492 22.4162 11.474 22.4228 11.4649 22.4153C11.4559 22.4078 11.4156 22.4303 11.3755 22.4654C11.2987 22.5324 11.2363 22.5427 11.2439 22.4871C11.2498 22.4438 11.1721 22.4181 11.1426 22.4536C11.1299 22.4689 11.0848 22.4886 11.0424 22.4975C11 22.5064 10.9554 22.5256 10.9434 22.5402C10.913 22.5767 11.1033 22.5835 11.2583 22.5515ZM19.1345 28.6816C19.1763 28.6583 19.2546 28.4648 19.2349 28.4334C19.2229 28.4141 19.2035 28.4288 19.1668 28.4849C19.07 28.6332 19.0547 28.7262 19.1345 28.6816ZM11.7877 21.7289C11.8305 21.708 11.9293 21.6517 12.0073 21.6036C12.0852 21.5556 12.2063 21.4889 12.2764 21.4555C12.3464 21.422 12.4099 21.3872 12.4174 21.3781C12.425 21.3691 12.4965 21.333 12.5763 21.298C12.6561 21.263 12.7693 21.2067 12.8278 21.1729C12.8863 21.139 12.9415 21.1174 12.9504 21.1248C12.9594 21.1323 12.9811 21.121 12.9987 21.0998C13.0164 21.0786 13.0557 21.0512 13.0861 21.039C13.1165 21.0267 13.1691 20.9968 13.203 20.9725C13.2642 20.9285 13.4432 20.8254 13.6857 20.6942C13.8295 20.6165 13.9792 20.5275 14.1507 20.4179C14.2157 20.3763 14.3194 20.3134 14.3813 20.278C14.6234 20.1396 15.3223 19.6889 15.472 19.5747C15.5264 19.5331 15.5932 19.4821 15.6205 19.4613C15.6477 19.4406 15.7051 19.396 15.748 19.3622C15.9091 19.2356 15.9941 19.1781 16.2465 19.025C16.6555 18.777 16.8459 18.6062 16.6606 18.6538C16.5724 18.6764 16.3171 18.8287 16.2678 18.8881C16.2253 18.9393 16.0506 19.0624 15.8774 19.1633C15.8125 19.2011 15.7398 19.2556 15.7158 19.2844C15.6919 19.3133 15.6443 19.3379 15.6101 19.3392C15.5735 19.3406 15.5396 19.3596 15.5276 19.3855C15.4996 19.4457 15.131 19.7271 14.9783 19.8047C14.9358 19.8264 14.8889 19.8585 14.8742 19.876C14.8595 19.8936 14.8184 19.92 14.7829 19.9348C14.7474 19.9495 14.6861 19.9896 14.6467 20.0238C14.6073 20.0581 14.4719 20.132 14.3459 20.1881C14.2199 20.2442 14.1056 20.3035 14.0921 20.3198C14.0785 20.3361 14.0477 20.3578 14.0236 20.3679C13.9995 20.378 13.9037 20.4296 13.8107 20.4825C13.7177 20.5355 13.6168 20.5862 13.5865 20.5952C13.5562 20.6043 13.516 20.6302 13.4973 20.6528C13.4785 20.6754 13.4212 20.7012 13.37 20.7102C13.3163 20.7197 13.2573 20.7502 13.2307 20.7821C13.1792 20.8441 12.9755 20.9592 12.86 20.9915C12.8186 21.0031 12.7749 21.0237 12.7631 21.0372C12.7513 21.0508 12.6973 21.0818 12.6432 21.1063C12.589 21.1308 12.5376 21.1589 12.5287 21.1687C12.5199 21.1786 12.4487 21.2047 12.3705 21.2266C12.2479 21.261 12.2093 21.2858 12.0918 21.4056C12.0168 21.4822 11.9299 21.5528 11.8987 21.5627C11.8675 21.5725 11.8276 21.6069 11.8099 21.639C11.7923 21.6711 11.7591 21.7008 11.7362 21.705C11.7133 21.7092 11.6956 21.7228 11.6968 21.7352C11.7001 21.7697 11.7042 21.7695 11.7877 21.7289ZM19.5217 27.6225C19.6186 27.4862 19.7472 27.2879 19.8073 27.1817C19.8675 27.0755 19.9873 26.8697 20.0736 26.7245C20.2724 26.3897 20.4668 25.8917 20.2828 26.1883C20.2473 26.2456 20.1995 26.3195 20.1766 26.3525C20.1536 26.3855 20.1291 26.429 20.122 26.4491C20.0988 26.5149 19.9761 26.7202 19.9266 26.7759C19.8686 26.8412 19.7275 27.0839 19.605 27.3292C19.556 27.4273 19.4897 27.5497 19.4575 27.6011C19.2481 27.9365 19.2886 27.95 19.5217 27.6225ZM18.7896 27.2769C18.8009 27.2376 18.7897 27.1175 18.7648 27.0101C18.7399 26.9026 18.7133 26.6924 18.7057 26.5429C18.698 26.3934 18.6806 26.2618 18.6669 26.2504C18.6532 26.239 18.6443 26.2001 18.6471 26.1639C18.655 26.0635 18.6277 26.1163 18.6117 26.2324C18.5956 26.35 18.5952 26.4305 18.6099 26.6282C18.6157 26.7056 18.6157 26.8263 18.6099 26.8965C18.589 27.152 18.7361 27.4634 18.7896 27.2769ZM13.1162 22.1144C13.1509 22.0998 13.27 22.0609 13.3809 22.028C13.4919 21.9951 13.5918 21.9574 13.603 21.9442C13.6143 21.9311 13.7242 21.8762 13.8473 21.8223C13.9705 21.7684 14.0768 21.7176 14.0837 21.7095C14.0906 21.7013 14.2099 21.6372 14.349 21.5669C14.6575 21.4111 15.0817 21.1619 15.3773 20.9631C15.4985 20.8816 15.6561 20.7782 15.7275 20.7333C15.9399 20.5999 15.9744 20.5687 16.0548 20.4372C16.1536 20.2757 16.4563 19.9624 16.5816 19.8921C16.6607 19.8477 16.7067 19.7902 16.6455 19.8122C16.5919 19.8315 16.1707 20.1342 16.0577 20.2346C16.0123 20.275 15.8564 20.394 15.7113 20.499C15.5661 20.604 15.412 20.7216 15.3687 20.7602C15.2899 20.8306 15.2774 20.838 15.1235 20.9048C15.0778 20.9247 15.0307 20.9526 15.0189 20.9668C15.0071 20.9811 14.9539 21.0108 14.9007 21.0329C14.8475 21.055 14.7625 21.1074 14.7119 21.1493C14.6613 21.1912 14.6055 21.2234 14.588 21.2209C14.5705 21.2184 14.4972 21.263 14.4252 21.3201C14.3531 21.3771 14.2776 21.4271 14.2575 21.4311C14.2374 21.4351 14.1903 21.4627 14.153 21.4924C14.1157 21.5222 14.0537 21.563 14.0153 21.5831C13.9768 21.6033 13.9067 21.6444 13.8595 21.6747C13.8123 21.7049 13.693 21.7596 13.5944 21.7964C13.4958 21.8332 13.4032 21.8775 13.3887 21.895C13.3742 21.9125 13.3167 21.9451 13.261 21.9676C13.0438 22.0552 12.9784 22.0864 12.9226 22.1292L12.8646 22.1736L12.9589 22.1572C13.0108 22.1483 13.0816 22.129 13.1162 22.1144ZM19.16 27.3461C19.1662 27.3295 19.2058 27.2666 19.248 27.2062C19.2902 27.1458 19.3751 27.0061 19.4366 26.8958C19.5142 26.7565 19.5643 26.6872 19.6006 26.6692C19.6326 26.6534 19.7042 26.5695 19.7851 26.4533C19.8578 26.3488 19.9786 26.1821 20.0537 26.0829C20.1287 25.9837 20.1894 25.8952 20.1886 25.8863C20.1831 25.8297 19.8336 26.2227 19.6384 26.5051C19.6079 26.5491 19.5312 26.6558 19.4679 26.7421C19.3584 26.8912 19.3138 26.9676 19.2012 27.1989C19.1393 27.3259 19.1274 27.3585 19.1392 27.3683C19.1444 27.3726 19.1537 27.3626 19.16 27.3461ZM18.9542 26.9472C18.9873 26.897 19.0161 26.8432 19.0182 26.8276C19.0203 26.812 19.0614 26.7429 19.1095 26.674C19.2198 26.516 19.3081 26.3198 19.2903 26.2724C19.2745 26.2304 19.3111 25.9785 19.3451 25.8956C19.3579 25.8645 19.3708 25.8056 19.3739 25.7648C19.3844 25.6265 19.539 24.9535 19.5684 24.9181C19.5845 24.8988 19.6057 24.8495 19.6155 24.8085C19.6645 24.6054 19.6948 24.5148 19.8744 24.035C19.9809 23.7504 20.0884 23.4633 20.1131 23.3971C20.1378 23.3309 20.1875 23.1947 20.2235 23.0944C20.2594 22.9941 20.3161 22.8495 20.3494 22.7731C20.4407 22.5639 20.467 22.4584 20.4543 22.3518C20.4431 22.2577 20.48 22.1716 20.5179 22.2031C20.547 22.2273 20.589 22.1633 20.6464 22.0071C20.6753 21.9286 20.7317 21.7922 20.7717 21.704C20.8735 21.4797 21.0423 21.051 21.0535 20.9884C21.0714 20.8888 21.1319 20.697 21.1538 20.6706C21.1761 20.6438 21.2324 20.4274 21.3147 20.0527C21.3394 19.9408 21.3874 19.7961 21.4215 19.7312C21.4556 19.6664 21.487 19.5593 21.4911 19.4934C21.5298 18.8798 21.5961 18.644 21.6452 18.945L21.6634 19.0569L21.6815 18.9785C21.6915 18.9354 21.6954 18.8784 21.6903 18.8518C21.6852 18.8252 21.6918 18.7549 21.7049 18.6956C21.718 18.6363 21.7304 18.5391 21.7324 18.4797C21.7353 18.395 21.7674 18.3159 21.881 18.1134C22.0825 17.7544 22.1294 17.6885 22.7626 16.8736C23.2841 16.2025 23.5137 15.8859 23.6695 15.6233C23.7316 15.5186 23.8374 15.3431 23.9048 15.2331C24.0272 15.0333 24.1938 14.7391 24.2956 14.5431C24.3739 14.3924 24.3889 14.3662 24.4214 14.3231C24.4579 14.2748 24.4648 14.2254 24.4398 14.191C24.4247 14.1703 24.3364 14.2633 24.0185 14.6353C23.7973 14.8941 23.611 15.1085 23.6045 15.1119C23.5981 15.1152 23.5878 15.1279 23.5817 15.1402C23.5335 15.2373 23.3462 15.4622 23.2662 15.5188C23.2133 15.5563 23.0588 15.7147 22.9228 15.8709C22.3483 16.5308 21.9485 17.0083 21.9177 17.0712C21.8065 17.2978 21.7815 17.3383 21.7487 17.3443C21.7258 17.3485 21.7167 17.3675 21.7227 17.3986C21.7283 17.4278 21.7153 17.4569 21.6892 17.4736C21.6658 17.4885 21.6514 17.5149 21.6573 17.5322C21.6636 17.5507 21.6144 17.6342 21.5371 17.736C21.4294 17.8779 21.4167 17.8898 21.4656 17.8035C21.4983 17.7457 21.5349 17.6697 21.547 17.6345C21.5684 17.5725 21.7098 17.2873 21.832 17.0599C21.9146 16.906 22.5392 16.1539 22.8848 15.792C23.0419 15.6275 23.3193 15.3183 23.5013 15.105C23.6833 14.8917 23.9402 14.598 24.0722 14.4524C24.2304 14.2779 24.3271 14.155 24.3557 14.0922C24.3875 14.0226 24.4094 13.996 24.4372 13.9936C24.4649 13.9911 24.4688 14.0039 24.4515 14.0411C24.423 14.1024 24.4498 14.1332 24.4898 14.0851C24.5264 14.041 24.5117 13.9319 24.4695 13.9345C24.4522 13.9356 24.4196 13.9261 24.397 13.9133C24.367 13.8964 24.3402 13.907 24.2978 13.9523C23.8381 14.4442 23.799 14.482 23.7628 14.4696C23.7302 14.4585 23.754 14.4262 23.9533 14.2114C24.0786 14.0763 24.2103 13.9334 24.2458 13.8938C24.2906 13.844 24.3212 13.8277 24.3451 13.8409C24.4126 13.8781 24.6022 13.6835 25.3142 12.846C25.6919 12.4016 26.027 12.0136 26.0589 11.9836C26.1443 11.9035 26.0999 11.8928 26.0053 11.9706C25.8678 12.0838 25.6732 12.2936 25.0921 12.9554C24.8806 13.1963 24.6801 13.4214 24.6466 13.4557C24.6131 13.4901 24.5583 13.5686 24.525 13.6302C24.46 13.7503 24.3556 13.811 24.2972 13.7625C24.2604 13.732 24.2432 13.7405 24.1048 13.8575C23.919 14.0146 23.6839 14.2621 23.2181 14.7909C22.8976 15.1548 22.6049 15.4571 22.5582 15.4726C22.5432 15.4776 22.4395 15.594 22.3277 15.7313C22.0865 16.0276 22.1612 15.94 21.7695 16.3857C21.4502 16.7491 21.3487 16.8552 21.2343 16.9454C21.2021 16.9707 21.1532 17.0153 21.1255 17.0443C21.0552 17.1183 20.8705 17.261 20.8323 17.271C20.8147 17.2755 20.7782 17.3009 20.7509 17.3275C20.7237 17.354 20.6609 17.3902 20.6114 17.4077C20.5618 17.4253 20.5194 17.4532 20.5172 17.4698C20.5135 17.4965 20.2952 17.5919 20.2433 17.5895C20.2322 17.589 20.1784 17.6131 20.1236 17.643C19.9801 17.7213 19.7413 17.7915 19.6535 17.7812C19.6119 17.7763 19.5319 17.7899 19.4757 17.8115C19.4194 17.833 19.3416 17.862 19.3027 17.876C19.215 17.9074 18.9852 17.933 18.9621 17.9138C18.9527 17.906 18.9188 17.9121 18.8869 17.9275C18.8549 17.9428 18.8067 17.9463 18.7797 17.9353C18.7528 17.9243 18.7233 17.9242 18.7142 17.9352C18.7051 17.9462 18.6638 17.9572 18.6223 17.9596C18.5809 17.962 18.5144 17.9777 18.4745 17.9944C18.4345 18.0111 18.3777 18.0181 18.3483 18.0099C18.2938 17.9949 17.4922 18.0777 17.4098 18.1069C17.3148 18.1405 17.2099 18.1499 17.0915 18.1356C17.0239 18.1274 16.9623 18.1283 16.9546 18.1376C16.9469 18.1468 16.7968 18.1681 16.6209 18.1848C16.4451 18.2015 16.2373 18.2277 16.1592 18.2429C16.0811 18.258 15.956 18.2741 15.881 18.2786C15.8061 18.2831 15.6466 18.2939 15.5265 18.3026C15.1844 18.3274 15.2072 18.2746 15.5582 18.2288C15.7285 18.2065 15.8835 18.1937 15.9027 18.2003C15.9219 18.2069 15.9479 18.1999 15.9605 18.1847C15.9731 18.1696 16.0091 18.1594 16.0404 18.1621C16.0718 18.1648 16.18 18.1509 16.2809 18.1313C16.3818 18.1116 16.4745 18.0985 16.4869 18.1023C16.4993 18.106 16.5842 18.0986 16.6756 18.0859C16.9001 18.0546 17.1004 18.0374 17.1967 18.0411C17.2405 18.0428 17.3235 18.0304 17.3811 18.0135C17.4387 17.9967 17.6189 17.968 17.7815 17.9498C17.944 17.9316 18.1274 17.9097 18.189 17.9011C18.2506 17.8924 18.3898 17.88 18.4983 17.8735C18.6069 17.867 18.7459 17.8534 18.8073 17.8432C18.8686 17.8331 18.9305 17.8287 18.9447 17.8334C18.9589 17.8381 19.0391 17.8275 19.1229 17.8098C19.2067 17.792 19.2961 17.774 19.3215 17.7696C19.347 17.7653 19.4369 17.741 19.5214 17.7157C19.6058 17.6904 19.7188 17.6635 19.7724 17.656C19.8261 17.6485 19.9364 17.6126 20.0176 17.5762C20.0989 17.5399 20.2269 17.4922 20.3021 17.4701C20.3773 17.4481 20.4504 17.4161 20.4646 17.399C20.4788 17.3819 20.5452 17.3362 20.6121 17.2975C20.861 17.1535 21.1264 16.9196 21.4954 16.5189C21.6077 16.3971 21.708 16.2946 21.7184 16.2911C21.7288 16.2877 21.8605 16.1399 22.0111 15.9628C22.3009 15.6218 22.6 15.297 23.1125 14.7663C23.1729 14.7037 23.3445 14.5144 23.4939 14.3456C23.6432 14.1768 23.776 14.0352 23.7889 14.0309C23.8018 14.0266 23.86 13.9738 23.9182 13.9135C23.9764 13.8532 24.0561 13.7837 24.0953 13.7592C24.1704 13.7122 24.204 13.6535 24.1714 13.6264C24.1607 13.6175 24.1384 13.6266 24.1218 13.6465C24.1053 13.6665 24.0806 13.6812 24.067 13.6792C24.0535 13.6772 24.0054 13.7181 23.9603 13.77C23.9151 13.8219 23.8574 13.8682 23.832 13.8728C23.8066 13.8775 23.7489 13.9271 23.7037 13.9831C23.6586 14.0391 23.6138 14.0784 23.6042 14.0704C23.5945 14.0624 23.5776 14.0782 23.5666 14.1055C23.5489 14.1494 23.5226 14.1832 23.4076 14.3094C23.3918 14.3267 23.2979 14.4155 23.1989 14.5068C23.0999 14.5982 23.0013 14.6937 22.9797 14.7192C22.9581 14.7446 22.8832 14.8173 22.8132 14.8807C22.7433 14.944 22.5549 15.1426 22.3947 15.3219C22.2345 15.5012 22.0477 15.7011 21.9797 15.766C21.9116 15.831 21.7016 16.0683 21.513 16.2935C21.3244 16.5186 21.1178 16.7588 21.0538 16.8271C20.9898 16.8955 20.9103 16.9834 20.8771 17.0225C20.8439 17.0616 20.8009 17.0969 20.7816 17.1009C20.7623 17.105 20.7008 17.1534 20.6451 17.2085C20.5893 17.2635 20.5235 17.3083 20.499 17.308C20.4744 17.3076 20.3895 17.3316 20.3102 17.3613C20.1539 17.4198 19.8055 17.4705 19.6796 17.4531C19.6364 17.4471 19.5914 17.4538 19.5796 17.4681C19.5678 17.4823 19.5497 17.4869 19.5393 17.4783C19.5289 17.4697 19.5113 17.4737 19.5 17.4873C19.4887 17.5009 19.4086 17.5197 19.3219 17.5293C19.2352 17.5388 19.1572 17.5551 19.1486 17.5654C19.14 17.5758 19.0124 17.5957 18.8652 17.6097C18.7179 17.6237 18.5086 17.6482 18.4001 17.6643C18.2917 17.6804 18.1923 17.6848 18.1794 17.6741C18.1664 17.6633 18.1365 17.6668 18.1128 17.6819C18.0892 17.697 18.062 17.7028 18.0523 17.6947C18.0426 17.6867 18.0268 17.6898 18.017 17.7015C17.9958 17.7271 17.8057 17.7424 17.7794 17.7206C17.7693 17.7121 17.7292 17.7179 17.6904 17.7334C17.6272 17.7586 17.3392 17.7946 17.1844 17.7966C17.1521 17.7971 17.0064 17.8109 16.8606 17.8274C16.7148 17.8439 16.5512 17.8562 16.4971 17.8546C16.443 17.8531 16.389 17.8629 16.3771 17.8764C16.3651 17.8898 16.3129 17.9046 16.2609 17.9092C16.1647 17.9176 16.0154 17.9451 15.8381 17.9872C15.51 18.0649 15.3457 18.0974 15.3333 18.0871C15.3255 18.0806 15.3098 18.0867 15.2983 18.1005C15.2734 18.1305 14.9398 18.1705 14.9114 18.1469C14.875 18.1167 15.0888 18.0468 15.2682 18.0302C15.2947 18.0277 15.4262 17.9927 15.5605 17.9524C15.6947 17.912 15.8168 17.8891 15.8316 17.9015C15.8465 17.9138 15.8664 17.9147 15.8757 17.9035C15.9233 17.8462 17.2746 17.6484 17.3261 17.6912C17.3326 17.6965 17.4245 17.6842 17.5305 17.6637C17.6364 17.6432 17.8686 17.6124 18.0464 17.5952C18.4278 17.5585 18.9781 17.4852 19.1069 17.454C19.277 17.4129 19.1713 17.3834 18.948 17.4098C18.8271 17.424 18.718 17.4272 18.7055 17.4169C18.693 17.4065 18.6751 17.4074 18.6655 17.4188C18.656 17.4303 18.4102 17.459 18.1192 17.4826C17.8282 17.5062 17.587 17.5294 17.5831 17.5341C17.5792 17.5388 17.5006 17.5515 17.4084 17.5624C17.2048 17.5864 16.8689 17.6345 16.7198 17.6609C16.6125 17.6799 15.9961 17.7716 15.8015 17.7976C15.7475 17.8048 15.6737 17.8147 15.6376 17.8196C15.6014 17.8246 15.4706 17.8523 15.3468 17.8812C15.2231 17.9102 15.0318 17.9428 14.9218 17.9538C14.8118 17.9647 14.6712 17.9884 14.6093 18.0065C14.5114 18.035 14.2618 18.0676 13.7148 18.1234C13.6357 18.1314 13.5602 18.1291 13.5471 18.1182C13.534 18.1074 13.4558 18.1027 13.3733 18.108C13.0908 18.1259 13.0009 18.1263 12.9543 18.1099C12.9286 18.1009 12.9084 18.1016 12.9094 18.1115C12.9111 18.1287 13.0659 18.1735 13.2113 18.1988C13.2496 18.2054 13.3475 18.2256 13.429 18.2436C13.5638 18.2733 13.9925 18.255 14.355 18.204C14.6267 18.1658 14.8587 18.1699 14.8235 18.2123C14.7949 18.2468 14.6484 18.2764 14.4662 18.2845C14.3457 18.2898 14.2062 18.3049 14.1561 18.3179L14.065 18.3416L14.2298 18.3721C14.3204 18.3889 14.4602 18.4024 14.5404 18.4021C14.6207 18.4019 14.6937 18.4078 14.7027 18.4153C14.7117 18.4228 14.7846 18.4288 14.8646 18.4287C14.9447 18.4285 15.0618 18.4352 15.1249 18.4436C15.188 18.4519 15.3288 18.4548 15.4378 18.4501C15.5468 18.4453 15.734 18.4464 15.8538 18.4525C16.0825 18.4641 16.4595 18.4559 16.7631 18.4328C16.8622 18.4252 17.0099 18.4201 17.0914 18.4214C17.4105 18.4266 17.7238 18.3987 17.7545 18.3625C17.7675 18.3472 17.8463 18.3203 17.9297 18.3028C18.0131 18.2853 18.1348 18.2551 18.2002 18.2356C18.2655 18.2162 18.3254 18.2056 18.3332 18.212C18.3654 18.2387 18.2778 18.3007 18.198 18.3077C18.1508 18.3119 18.1055 18.3233 18.0974 18.3331C18.0892 18.3429 18.075 18.3446 18.0657 18.3369C18.0565 18.3293 18.0311 18.333 18.0093 18.3453C17.9774 18.3633 18.2594 18.3597 18.3468 18.341C18.3595 18.3383 18.43 18.3258 18.5033 18.3132C18.7159 18.2769 19.2061 18.1419 19.423 18.06L19.5535 18.0107L19.3358 18.0349C19.216 18.0483 19.0737 18.0756 19.0195 18.0957C18.9653 18.1157 18.9147 18.1269 18.907 18.1206C18.8994 18.1142 18.8075 18.1343 18.7029 18.1652C18.5064 18.2232 18.3641 18.2419 18.394 18.2058C18.4091 18.1877 18.4985 18.1564 18.7108 18.0949C18.744 18.0853 18.8802 18.0495 19.0133 18.0153C19.2346 17.9586 19.3304 17.9392 19.4988 17.9171C19.5317 17.9128 19.5825 17.8996 19.6117 17.8879C19.6835 17.859 19.7585 17.9192 19.6984 17.9575C19.6272 18.0029 19.665 18.002 19.8258 17.9545C19.9097 17.9296 19.9981 17.9073 20.0224 17.9048C20.0466 17.9023 20.1255 17.8783 20.1977 17.8515C20.5358 17.7259 20.6129 17.7436 20.5592 17.9349C20.541 18 20.5125 18.0696 20.496 18.0895C20.4795 18.1094 20.4614 18.1481 20.456 18.1755C20.4505 18.2028 20.3986 18.2901 20.3406 18.3694C20.2826 18.4488 20.2188 18.5426 20.1987 18.578C20.1787 18.6134 20.1349 18.6835 20.1014 18.7338C20.0679 18.7841 20.0188 18.8782 19.9922 18.9428C19.9655 19.0075 19.921 19.0879 19.8933 19.1216C19.8655 19.1553 19.821 19.2521 19.7944 19.3368C19.7679 19.4215 19.7299 19.5104 19.71 19.5344C19.6901 19.5583 19.6651 19.6217 19.6544 19.6753C19.6437 19.7289 19.6225 19.7796 19.6073 19.7881C19.592 19.7966 19.5631 19.8669 19.543 19.9445C19.5229 20.022 19.4883 20.1075 19.4661 20.1344C19.4439 20.1614 19.4249 20.2177 19.424 20.2597C19.4231 20.3017 19.4079 20.3655 19.3902 20.4015C19.3725 20.4376 19.3577 20.485 19.3573 20.507C19.3568 20.529 19.318 20.6944 19.271 20.8747C19.2241 21.0549 19.1856 21.2176 19.1855 21.2363C19.1853 21.3015 19.0736 21.7957 19.0536 21.8198C19.0425 21.8331 19.0378 21.8734 19.0431 21.9092C19.0483 21.945 19.0461 21.9821 19.0381 21.9918C19.0301 22.0015 19.0207 22.0448 19.0174 22.088C19.014 22.1313 18.9969 22.24 18.9794 22.3295C18.9619 22.4191 18.9447 22.5717 18.9411 22.6685C18.9376 22.7654 18.9287 22.8519 18.9213 22.8607C18.914 22.8696 18.9073 22.9314 18.9065 22.9982C18.9041 23.1874 18.8894 23.3277 18.8383 23.6479C18.82 23.7628 18.8124 23.9056 18.8215 23.9652C18.839 24.0801 18.8023 24.3841 18.7655 24.4284C18.7535 24.4428 18.7521 24.4696 18.7624 24.4879C18.7727 24.5061 18.7684 24.5733 18.7529 24.6372C18.7373 24.7012 18.7332 24.7743 18.7436 24.7998C18.7541 24.8253 18.7558 24.9081 18.7474 24.9838C18.7391 25.0596 18.7295 25.1676 18.7263 25.2238C18.723 25.2801 18.7087 25.3401 18.6946 25.3571C18.6804 25.3742 18.6702 25.4641 18.6718 25.557C18.6735 25.6499 18.6669 25.7359 18.6572 25.7481C18.6476 25.7603 18.6405 25.8207 18.6415 25.8823C18.6452 26.0982 18.7066 25.7818 18.7398 25.3757C18.7517 25.2307 18.7975 24.9714 18.8534 24.7332C18.8755 24.6388 18.8929 24.5538 18.892 24.5444C18.8888 24.5113 18.9065 24.4123 18.9533 24.202C18.9793 24.0853 18.9985 23.9594 18.9962 23.9221C18.9938 23.8848 19.0002 23.8258 19.0105 23.7909C19.0208 23.7561 19.0317 23.7084 19.0348 23.6849C19.0378 23.6614 19.0641 23.5413 19.0933 23.4179C19.1224 23.2946 19.1488 23.1582 19.152 23.1148C19.1552 23.0714 19.1655 23.0267 19.1748 23.0154C19.1842 23.0042 19.1851 22.9894 19.1769 22.9826C19.1569 22.966 19.2264 22.6292 19.2742 22.5113C19.2953 22.4594 19.3099 22.4076 19.3068 22.3964C19.2985 22.3668 19.3353 22.2089 19.3563 22.1836C19.3661 22.1719 19.3766 22.1258 19.3797 22.0813C19.3828 22.0367 19.4 21.9707 19.4178 21.9345C19.4357 21.8983 19.4494 21.8397 19.4485 21.8041C19.4475 21.7686 19.4722 21.6614 19.5034 21.5658C19.5346 21.4703 19.5765 21.3063 19.5965 21.2014C19.6165 21.0966 19.6629 20.9505 19.6996 20.8768C19.7363 20.8031 19.7774 20.6927 19.7909 20.6315C19.8044 20.5703 19.8524 20.4398 19.8974 20.3415C19.9425 20.2432 19.9921 20.1165 20.0075 20.0599C20.023 20.0033 20.0629 19.8945 20.0963 19.8181C20.1296 19.7417 20.1903 19.5793 20.231 19.4573C20.2718 19.3353 20.3481 19.1573 20.4007 19.0618C20.4533 18.9664 20.5034 18.8657 20.512 18.8382C20.5748 18.6376 20.861 18.2088 20.8955 18.2635C20.9084 18.2839 20.878 18.3528 20.805 18.4687C20.6766 18.6728 20.6384 18.7484 20.6074 18.8609C20.5949 18.9062 20.5578 18.9819 20.5251 19.0291C20.4597 19.1235 20.456 19.1311 20.3915 19.306C20.297 19.5622 20.2447 19.6953 20.1898 19.8196C20.1584 19.8905 20.1306 19.9754 20.1281 20.0083C20.1255 20.0412 20.0832 20.154 20.0342 20.2589C19.9851 20.3638 19.9273 20.513 19.9058 20.5906C19.8589 20.7595 19.8067 20.8958 19.7507 20.9955C19.728 21.036 19.7077 21.1114 19.7057 21.1632C19.7036 21.215 19.685 21.3001 19.6642 21.3523C19.6435 21.4045 19.6054 21.5462 19.5797 21.6672C19.5539 21.7882 19.519 21.9229 19.502 21.9665C19.485 22.0101 19.464 22.1124 19.4552 22.194C19.4465 22.2755 19.4138 22.404 19.3824 22.4796C19.3201 22.6297 19.2441 22.9788 19.258 23.0511C19.2628 23.0761 19.2584 23.1064 19.2483 23.1186C19.2383 23.1307 19.2276 23.1866 19.2246 23.2427C19.2216 23.2988 19.188 23.479 19.1499 23.6432C19.1119 23.8073 19.0845 23.9612 19.0891 23.9851C19.0937 24.0091 19.0909 24.0365 19.083 24.0461C19.075 24.0556 19.0613 24.1383 19.0524 24.2298C19.0436 24.3213 19.0091 24.5297 18.9757 24.6929C18.8717 25.2019 18.8176 25.5553 18.8406 25.5745C18.8493 25.5817 18.8464 25.6254 18.8341 25.6716C18.7843 25.8576 18.7711 26.0675 18.7966 26.266C18.8114 26.381 18.8227 26.5218 18.8217 26.5789C18.8202 26.6639 18.8717 27.0097 18.8892 27.0323C18.8918 27.0358 18.9211 26.9974 18.9542 26.9472ZM19.5324 27.2072C19.5971 27.0948 19.6937 26.9434 19.7469 26.8707C19.8002 26.7981 19.85 26.7225 19.8577 26.7029C19.8705 26.67 19.9281 26.5795 20.077 26.359C20.1083 26.3125 20.1388 26.2501 20.1448 26.2202C20.1508 26.1903 20.1806 26.1358 20.211 26.0992C20.2415 26.0626 20.26 26.0273 20.2522 26.0209C20.2363 26.0076 20.1207 26.149 19.9987 26.331C19.9539 26.3978 19.88 26.5069 19.8346 26.5733C19.7136 26.7502 19.5166 27.1068 19.4668 27.2391C19.443 27.3024 19.4122 27.3679 19.3982 27.3846C19.3843 27.4014 19.3823 27.4143 19.3938 27.4133C19.4053 27.4123 19.4677 27.3195 19.5324 27.2072ZM19.1337 27.0718C19.2348 26.8716 19.2712 26.8107 19.3449 26.7188C19.4335 26.6082 19.4932 26.478 19.4235 26.5474C19.4045 26.5663 19.3838 26.5917 19.3775 26.6039C19.3712 26.616 19.3333 26.6709 19.2932 26.7259C19.1898 26.8678 19.0718 27.0915 19.0916 27.1079C19.1009 27.1156 19.1198 27.0993 19.1337 27.0718ZM12.8527 21.6826C13.0092 21.6068 13.0509 21.5847 13.1604 21.52C13.2593 21.4615 13.4678 21.3519 13.6954 21.2387C13.7935 21.1899 13.933 21.1141 14.0055 21.0702C14.3229 20.878 14.3939 20.8365 14.4674 20.8001C14.5104 20.7788 14.6144 20.716 14.6987 20.6606C14.783 20.6051 14.8633 20.5613 14.8773 20.5633C14.8912 20.5653 14.9079 20.5514 14.9143 20.5324C14.9206 20.5133 15.0324 20.4327 15.1627 20.3532C15.2929 20.2737 15.4601 20.1596 15.5342 20.0996C15.6082 20.0396 15.69 19.9737 15.7159 19.9532C15.8177 19.8723 16.0585 19.734 16.2453 19.649C16.3533 19.5998 16.4502 19.5495 16.4607 19.5371C16.4711 19.5247 16.5214 19.4884 16.5724 19.4564C16.9385 19.2269 17.2309 19.0333 17.2761 18.9905C17.3242 18.9451 17.5605 18.7895 17.7795 18.6592C17.8841 18.597 17.8655 18.5812 17.7068 18.5975C17.5475 18.6139 17.404 18.6806 17.2823 18.7947C17.2296 18.8441 17.1593 18.8934 17.1261 18.9042C17.0928 18.9151 17.0371 18.9583 17.0023 19.0002C16.9674 19.0422 16.9051 19.0906 16.8638 19.108C16.8225 19.1253 16.782 19.1513 16.7738 19.1658C16.7567 19.1961 16.5921 19.3116 16.5282 19.3382C16.5045 19.3481 16.4496 19.3871 16.4064 19.4249C16.3631 19.4626 16.2761 19.5223 16.2129 19.5574C16.1497 19.5925 15.9958 19.6855 15.8709 19.7639C15.7459 19.8424 15.6091 19.9226 15.5669 19.9422C15.5247 19.9618 15.4777 19.9928 15.4626 20.0111C15.4334 20.0462 15.2894 20.1378 15.2599 20.14C15.2503 20.1407 15.1744 20.1912 15.0911 20.2522C15.0079 20.3132 14.8944 20.3852 14.839 20.4122C14.7837 20.4391 14.6747 20.5119 14.5968 20.5738C14.4684 20.676 14.4165 20.711 14.2759 20.7899C14.2509 20.8039 14.1924 20.8405 14.1458 20.8712C14.0992 20.9019 14.0406 20.9384 14.0156 20.9524C13.9496 20.9891 13.6263 21.1886 13.5903 21.2148C13.5614 21.2359 13.3714 21.3316 13.2775 21.3723C13.2537 21.3827 13.2211 21.407 13.2049 21.4264C13.1888 21.4458 13.115 21.4916 13.0409 21.5282C12.9668 21.5647 12.8973 21.6053 12.8864 21.6184C12.8756 21.6314 12.8487 21.6437 12.8268 21.6456C12.7882 21.649 12.6895 21.7284 12.7064 21.7424C12.711 21.7463 12.7768 21.7193 12.8527 21.6826ZM12.5975 21.0302C12.6796 20.9806 12.7584 20.9266 12.7726 20.9104C12.7868 20.8942 12.8344 20.8734 12.8784 20.8641C12.9223 20.8549 12.9538 20.8436 12.9482 20.839C12.9427 20.8344 13.0179 20.7943 13.1154 20.75C13.2128 20.7056 13.3034 20.6565 13.3165 20.6409C13.3503 20.6011 13.4944 20.5184 13.6542 20.4472C13.7289 20.4138 13.847 20.3486 13.9165 20.3022C13.986 20.2558 14.1393 20.1702 14.2573 20.112C14.3753 20.0538 14.5189 19.9691 14.5766 19.9237C14.6341 19.8784 14.7415 19.8044 14.8152 19.7591C14.9487 19.6772 15.3033 19.4284 15.3741 19.3672C15.4386 19.3113 15.5266 19.2476 15.6583 19.1615C15.7284 19.1156 15.8265 19.048 15.8764 19.0113C16.1559 18.8052 16.2338 18.7506 16.2729 18.7336C16.3287 18.7093 16.3363 18.6991 16.3131 18.6799C16.2709 18.6448 16.1281 18.6919 16.0651 18.7617C16.0296 18.801 15.9843 18.8368 15.9644 18.8412C15.9445 18.8456 15.8655 18.9037 15.7889 18.9702C15.7123 19.0367 15.591 19.1206 15.5195 19.1566C15.4479 19.1926 15.3381 19.2668 15.2754 19.3215C15.2127 19.3761 15.1166 19.4399 15.0618 19.4633C15.007 19.4866 14.918 19.5383 14.864 19.5783C14.8101 19.6182 14.7454 19.6552 14.7204 19.6604C14.6954 19.6657 14.6536 19.6926 14.6276 19.7203C14.6015 19.7479 14.5434 19.7802 14.4985 19.7919C14.4535 19.8036 14.3881 19.8367 14.3532 19.8655C14.3182 19.8943 14.2763 19.9211 14.2602 19.9251C14.2441 19.929 14.2055 19.9537 14.1744 19.98C13.9934 20.1329 13.5325 20.3619 13.485 20.3225C13.4575 20.2997 13.3369 20.3666 13.2117 20.4741C13.1809 20.5006 13.1346 20.5332 13.1089 20.5465C13.0832 20.5599 12.9887 20.6376 12.8991 20.7194C12.8094 20.8011 12.7222 20.8699 12.7053 20.8724C12.6884 20.8748 12.6524 20.9035 12.6253 20.9361C12.5982 20.9688 12.5392 21.0146 12.4943 21.0379C12.4494 21.0612 12.4135 21.09 12.4147 21.1018C12.4179 21.1349 12.4368 21.1275 12.5975 21.0302ZM16.7899 23.8171C16.8535 23.6775 16.8521 23.6275 16.7867 23.7063C16.7347 23.7689 16.6863 23.9311 16.7206 23.9281C16.7313 23.9272 16.7624 23.8772 16.7899 23.8171ZM19.4993 26.1134C19.5854 26.0103 19.979 25.6691 20.1267 25.5696C20.2095 25.5138 20.267 25.4546 20.3304 25.3601C20.379 25.2877 20.4463 25.1874 20.48 25.1373C20.5137 25.0872 20.5875 24.9852 20.6439 24.9106C20.7003 24.836 20.7592 24.75 20.7747 24.7195C20.7903 24.6891 20.8557 24.5801 20.9201 24.4774C20.9846 24.3748 21.054 24.2478 21.0744 24.1954C21.0948 24.1429 21.1431 24.0515 21.1818 23.9923C21.2766 23.8469 21.3058 23.7076 21.2197 23.8112C21.1872 23.8504 21.1687 23.8283 21.1334 23.708C21.1166 23.6506 21.0971 23.5984 21.0901 23.5919C21.0831 23.5854 21.0687 23.5309 21.0581 23.4707C21.0475 23.4105 21.0316 23.3553 21.0229 23.3481C21.0142 23.3409 20.9747 23.2326 20.935 23.1076C20.8393 22.8058 20.8127 22.723 20.7941 22.6694C20.7855 22.6447 20.7684 22.5833 20.7562 22.5329C20.7167 22.3703 20.6695 22.488 20.7067 22.6561C20.7665 22.9255 20.8204 23.1157 20.8498 23.1606C20.866 23.1853 20.8882 23.2378 20.8992 23.2773C20.9302 23.3892 21.0282 23.6177 21.1068 23.7614C21.1775 23.8907 21.1766 23.9612 21.1036 24.0018C21.0494 24.032 20.9387 23.8762 20.9383 23.769C20.9382 23.7421 20.9277 23.7186 20.915 23.7167C20.9023 23.7149 20.8657 23.6417 20.8335 23.554C20.8014 23.4664 20.7689 23.3896 20.7615 23.3834C20.754 23.3772 20.7162 23.2703 20.6775 23.1459C20.5681 22.7942 20.5558 22.7874 20.4573 23.0232C20.4308 23.0865 20.3964 23.1537 20.3808 23.1728C20.3652 23.1918 20.3517 23.2428 20.3507 23.2861C20.3498 23.3294 20.3263 23.3921 20.2987 23.4254C20.271 23.4587 20.2521 23.5054 20.2567 23.5292C20.2613 23.553 20.2427 23.6193 20.2154 23.6766C20.1882 23.7339 20.1557 23.8267 20.1433 23.8829C20.1309 23.939 20.0935 24.0373 20.0602 24.1012C20.027 24.1651 19.9966 24.2461 19.9928 24.2813C19.9889 24.3164 19.9722 24.3665 19.9555 24.3926C19.9259 24.4389 19.9125 24.4778 19.8492 24.7013C19.8117 24.8335 19.6835 25.1629 19.6572 25.1946C19.6468 25.2071 19.6426 25.2466 19.6479 25.2824C19.6532 25.3182 19.6497 25.357 19.6401 25.3685C19.6305 25.38 19.6078 25.4592 19.5896 25.5444C19.5713 25.6296 19.5469 25.7107 19.5354 25.7246C19.5238 25.7385 19.5203 25.7596 19.5276 25.7714C19.5348 25.7833 19.5184 25.8282 19.4911 25.8712C19.4638 25.9143 19.4388 25.988 19.4355 26.035C19.4322 26.082 19.4219 26.1296 19.4125 26.1409C19.4032 26.1521 19.404 26.1684 19.4144 26.177C19.4247 26.1856 19.463 26.157 19.4993 26.1134ZM16.3911 23.5482C16.3997 23.5076 16.422 23.4559 16.4406 23.4334C16.4593 23.4108 16.4703 23.3801 16.4652 23.3652C16.4537 23.3314 16.453 23.3324 16.3823 23.4682C16.3472 23.5355 16.3345 23.5879 16.35 23.6007C16.3712 23.6183 16.3782 23.6093 16.3911 23.5482ZM16.5902 23.5213C16.7266 23.357 16.7412 23.2946 16.6592 23.2265C16.6483 23.2175 16.5841 23.3334 16.518 23.4817C16.4881 23.5488 16.4488 23.612 16.4307 23.6221C16.4112 23.633 16.4091 23.6498 16.4255 23.6634C16.4477 23.6819 16.48 23.654 16.5902 23.5213ZM17.2633 24.1503C17.4914 24.1691 17.916 23.9948 18.0577 23.8241C18.1041 23.7683 18.0042 23.777 17.9558 23.833C17.9419 23.8491 17.9009 23.8634 17.8647 23.8648C17.8286 23.8662 17.7867 23.8821 17.7717 23.9002C17.7567 23.9183 17.735 23.93 17.7235 23.9263C17.712 23.9225 17.6389 23.9446 17.5609 23.9753C17.4829 24.0059 17.3958 24.0401 17.3674 24.0513C17.339 24.0624 17.299 24.0824 17.2784 24.0957C17.2578 24.109 17.1993 24.1092 17.1484 24.0961C17.0975 24.083 17.0462 24.0839 17.0345 24.098C17.0096 24.1279 17.0196 24.1302 17.2633 24.1503ZM15.9977 23.068C16.0124 23.0373 16.0119 23.0104 15.9967 23.0082C15.9651 23.0037 15.8819 23.0959 15.8854 23.1317C15.8894 23.1724 15.9697 23.1268 15.9977 23.068ZM16.0108 22.7749C16.0669 22.7189 16.1024 22.6695 16.0925 22.6613C16.0829 22.6533 16.0694 22.6421 16.0625 22.6364C16.047 22.6235 15.8595 22.8342 15.8204 22.9086C15.7829 22.98 15.8591 22.9265 16.0108 22.7749ZM9.70162 17.7104C9.81968 17.7474 9.99879 17.7991 10.0996 17.8252C10.2005 17.8514 10.437 17.9201 10.6253 17.9779C10.8137 18.0358 11.0012 18.086 11.0421 18.0894C11.083 18.0929 11.1828 18.1131 11.2639 18.1344C11.345 18.1557 11.4557 18.1784 11.51 18.1848C11.5642 18.1911 11.6558 18.2077 11.7136 18.2216C11.7713 18.2355 11.8778 18.2531 11.9502 18.2608C12.0961 18.2763 12.194 18.2937 12.3523 18.3325C12.4105 18.3467 12.5371 18.3617 12.6338 18.3658C12.7304 18.3699 12.8644 18.3781 12.9315 18.384C13.0228 18.3921 13.0525 18.385 13.0495 18.3558C13.0464 18.3268 13.0337 18.3192 12.9998 18.3264C12.9555 18.3357 12.5126 18.237 12.4804 18.2107C12.4716 18.2034 12.4312 18.1902 12.3908 18.1814C12.348 18.172 12.3187 18.1542 12.3208 18.1388C12.3266 18.096 12.2721 18.0648 12.2462 18.0961C12.2176 18.1305 11.9873 18.0689 11.6929 17.948C11.5787 17.9012 11.4741 17.8665 11.4605 17.871C11.4468 17.8756 11.4204 17.8665 11.4017 17.851C11.383 17.8355 11.3321 17.8217 11.2887 17.8203C11.2453 17.819 11.1982 17.8083 11.1841 17.7965C11.17 17.7848 11.0868 17.7669 10.9992 17.7569C10.8031 17.7343 10.6038 17.6933 10.5753 17.6696C10.5636 17.6599 10.4987 17.6543 10.4311 17.6573C10.3635 17.6603 10.2518 17.6503 10.1829 17.6351C9.98823 17.5922 9.9277 17.5837 9.8378 17.5866C9.79193 17.5881 9.7317 17.5785 9.70396 17.5653C9.67622 17.5521 9.59057 17.5533 9.51361 17.5678C9.3495 17.5989 9.35185 17.6006 9.70162 17.7104ZM16.2663 22.838C16.2871 22.813 16.2803 22.7981 16.2377 22.7745C16.2001 22.7536 16.178 22.7552 16.1699 22.7795C16.1633 22.7992 16.143 22.8338 16.1249 22.8564C16.092 22.8972 16.0921 22.8973 16.1655 22.884C16.206 22.8767 16.2514 22.856 16.2663 22.838ZM14.8746 21.4457C14.9011 21.4165 14.7815 21.4566 14.7265 21.4954C14.6882 21.5224 14.6984 21.5229 14.767 21.4974C14.8175 21.4786 14.8659 21.4554 14.8746 21.4457ZM17.0522 23.3756C17.0676 23.366 17.0562 23.3492 17.0212 23.3298C16.9863 23.3105 16.9728 23.2907 16.9848 23.2763C16.9971 23.2615 16.9846 23.2442 16.9497 23.2273C16.9136 23.2099 16.8898 23.1748 16.8781 23.1214L16.8606 23.0416L17.0372 22.9689C17.1344 22.929 17.2523 22.8993 17.2993 22.903C17.3615 22.9079 17.3984 22.8938 17.4352 22.8513C17.4631 22.8192 17.5387 22.7516 17.6033 22.7011C17.6679 22.6507 17.7229 22.597 17.7254 22.5819C17.7302 22.5538 17.64 22.6131 17.5242 22.7143C17.4885 22.7454 17.4178 22.7802 17.3669 22.7917C17.316 22.8032 17.2687 22.8194 17.2618 22.8278C17.2328 22.8627 16.9255 22.9113 16.8948 22.8858C16.8526 22.8507 16.793 22.8828 16.78 22.9474C16.7559 23.0674 16.9801 23.4201 17.0522 23.3756ZM17.4851 23.5938C17.4928 23.5845 17.4834 23.5639 17.4643 23.548C17.4154 23.5074 17.262 23.4741 17.2581 23.5033C17.254 23.5331 17.4655 23.6174 17.4851 23.5938ZM16.417 22.6397C16.4198 22.6035 16.4444 22.547 16.4717 22.5142C16.5358 22.437 16.5536 22.3816 16.5227 22.3559C16.506 22.3421 16.5261 22.2943 16.5841 22.2097C16.6315 22.1406 16.7386 21.9847 16.8222 21.8632C16.9058 21.7417 17.0913 21.4912 17.2345 21.3064C17.3778 21.1217 17.5191 20.9338 17.5486 20.8889C17.5781 20.844 17.6721 20.7208 17.7574 20.6151C17.9581 20.3666 17.9842 20.2412 17.7944 20.4373C17.5762 20.6627 17.5659 20.6758 17.14 21.2753C17.0702 21.3735 16.9949 21.4714 16.9727 21.4929C16.9504 21.5144 16.9321 21.5489 16.932 21.5696C16.932 21.5903 16.8745 21.6874 16.8044 21.7854C16.7343 21.8833 16.6429 22.0204 16.6013 22.0899C16.5597 22.1595 16.4831 22.2876 16.4311 22.3745C16.3145 22.5696 16.3039 22.6159 16.3644 22.6661C16.4097 22.7038 16.4121 22.7026 16.417 22.6397ZM14.9729 21.4063C14.9832 21.3942 15.0703 21.3502 15.1665 21.3086C15.2626 21.267 15.3923 21.1976 15.4546 21.1545C15.517 21.1113 15.5904 21.0728 15.6178 21.069C15.6701 21.0618 15.7937 20.8672 15.7625 20.8413C15.7412 20.8236 15.6309 20.8818 15.5882 20.9331C15.5445 20.9857 15.3762 21.1077 15.2331 21.1904C15.1372 21.2458 14.9221 21.3903 14.9052 21.4106C14.9009 21.4158 14.9101 21.422 14.9257 21.4242C14.9414 21.4265 14.9626 21.4184 14.9729 21.4063ZM16.1562 22.3427C16.2044 22.2903 16.1921 22.2523 16.1391 22.2902C15.9677 22.4125 16.0275 22.1208 16.2358 21.818C16.3818 21.6059 16.3843 21.6018 16.3982 21.5585C16.4354 21.4429 16.726 20.9709 16.9228 20.7066C16.9253 20.7033 16.9143 20.6987 16.8984 20.6964C16.8825 20.6941 16.8682 20.7008 16.8666 20.7113C16.865 20.7217 16.7818 20.8398 16.6818 20.9737C16.4388 21.2988 16.341 21.4415 16.296 21.5367C16.2754 21.5803 16.2276 21.6826 16.1898 21.764C16.152 21.8454 16.1084 21.9299 16.093 21.9518C15.9589 22.1422 16.016 22.4951 16.1562 22.3427ZM17.718 23.6619C17.8551 23.6727 17.898 23.6003 17.7643 23.5839C17.7089 23.577 17.6512 23.5861 17.6362 23.604C17.601 23.6457 17.6123 23.6536 17.718 23.6619ZM13.8877 20.0416C13.9682 19.9957 14.135 19.8929 14.2584 19.8131C14.3818 19.7334 14.496 19.6649 14.512 19.6609C14.5592 19.6491 15.2339 19.2123 15.2712 19.1694C15.2838 19.1549 15.3502 19.1185 15.4187 19.0886C15.4872 19.0588 15.6072 18.981 15.6855 18.9158C15.7637 18.8506 15.8473 18.7868 15.8712 18.7739C15.9031 18.7567 15.9057 18.7469 15.881 18.737C15.8625 18.7296 15.8052 18.7513 15.7536 18.7854C15.5943 18.8905 15.5326 18.92 15.4365 18.9369C15.3815 18.9466 15.3061 18.9863 15.251 19.0345C15.1999 19.0793 15.125 19.1258 15.0845 19.138C15.0439 19.1501 14.999 19.1716 14.9847 19.1857C14.9703 19.1998 14.8654 19.276 14.7514 19.3549C14.6375 19.4338 14.5075 19.5279 14.4625 19.5641C14.4175 19.6002 14.3495 19.6432 14.3114 19.6595C14.2734 19.6758 14.1947 19.735 14.1367 19.7909C14.0787 19.8469 13.9545 19.9425 13.8606 20.0033C13.572 20.1905 13.5878 20.2128 13.8877 20.0416ZM15.9957 21.8789C16.0432 21.7979 16.1082 21.6634 16.1773 21.5029C16.1999 21.4505 16.1984 21.448 16.1583 21.4714C16.1344 21.4853 16.1109 21.5147 16.106 21.5367C16.1012 21.5587 16.0613 21.6282 16.0174 21.6911C15.9471 21.7919 15.9018 21.935 15.9322 21.9603C15.9381 21.9651 15.9667 21.9285 15.9957 21.8789ZM18.0342 23.4691C18.2509 23.2422 18.1771 23.2601 17.9313 23.4942C17.855 23.5669 17.8544 23.569 17.9177 23.546C17.9541 23.5327 18.0065 23.4982 18.0342 23.4691ZM16.3881 21.952C16.435 21.8653 16.5026 21.7561 16.5382 21.7091C16.5738 21.6622 16.6072 21.6022 16.6125 21.5757C16.6178 21.5493 16.6486 21.4955 16.6808 21.4561C16.7131 21.4167 16.7621 21.3393 16.7898 21.2842C16.8174 21.229 16.8657 21.152 16.8971 21.113C16.9285 21.074 16.9467 21.0359 16.9374 21.0282C16.9219 21.0153 16.8925 21.0539 16.6874 21.3569C16.6461 21.418 16.5723 21.5244 16.5235 21.5932C16.4747 21.662 16.4254 21.7462 16.4138 21.7802C16.4023 21.8143 16.3787 21.8592 16.3614 21.8801C16.3441 21.9009 16.3049 21.9776 16.2745 22.0503C16.2003 22.2273 16.2729 22.1645 16.3881 21.952ZM20.5008 25.5225C20.4969 25.483 20.4424 25.4754 20.4135 25.5102C20.395 25.5325 20.401 25.5386 20.4474 25.5451C20.4802 25.5497 20.5025 25.5403 20.5008 25.5225ZM15.9777 21.5327C16.007 21.4919 16.0317 21.4433 16.0327 21.4247C16.0337 21.4061 16.0687 21.3171 16.1105 21.2268C16.1829 21.0706 16.2144 20.9554 16.153 21.071C16.0545 21.2566 16.042 21.2707 16.0124 21.2296C15.992 21.2013 15.9806 21.2002 15.972 21.2257C15.9655 21.2453 15.9753 21.2666 15.9938 21.2729C16.0322 21.286 15.9949 21.3844 15.9399 21.415C15.911 21.4311 15.8927 21.5804 15.9171 21.6006C15.9212 21.604 15.9485 21.5735 15.9777 21.5327ZM17.0257 21.9454C17.1739 21.7519 17.3169 21.5618 17.3433 21.523C17.3697 21.4842 17.4447 21.3765 17.5099 21.2838C17.575 21.191 17.6295 21.1084 17.6309 21.1003C17.6323 21.0922 17.7071 20.9835 17.7972 20.8587C17.8872 20.7339 17.9768 20.6095 17.9961 20.5822C18.0155 20.5549 18.0541 20.5018 18.082 20.4643C18.1235 20.4085 18.1244 20.399 18.0873 20.4124C18.0178 20.4375 17.4436 21.1814 17.2001 21.5618C17.1457 21.6468 17.0607 21.7749 17.0112 21.8467C16.9617 21.9184 16.9011 22.0171 16.8764 22.066C16.8518 22.115 16.8092 22.1825 16.7817 22.2161C16.7542 22.2497 16.7372 22.2817 16.7439 22.2872C16.7506 22.2928 16.8774 22.139 17.0257 21.9454ZM16.63 21.8298C16.6983 21.717 16.6994 21.7117 16.64 21.779C16.5676 21.8611 16.478 22.0164 16.5247 21.979C16.5406 21.9662 16.588 21.8991 16.63 21.8298ZM17.5585 22.3371C17.8003 22.126 18.3114 21.5016 18.5219 21.1603C18.6208 20.9998 18.761 20.7756 18.8333 20.6622C18.945 20.4869 18.9545 20.4639 18.8969 20.5092C18.8596 20.5385 18.8282 20.5695 18.827 20.578C18.8259 20.5864 18.757 20.6858 18.674 20.7987C18.591 20.9116 18.4592 21.1001 18.3812 21.2175C18.3032 21.3349 18.0472 21.6642 17.8124 21.9492C17.5776 22.2343 17.3913 22.467 17.3985 22.4664C17.4058 22.4657 17.4777 22.4076 17.5585 22.3371ZM18.0394 22.7696C18.0603 22.746 18.0641 22.7258 18.0481 22.7235C18.0325 22.7212 17.9946 22.7509 17.9638 22.7894C17.9013 22.8677 17.9682 22.8502 18.0394 22.7696ZM18.351 22.4382C18.4596 22.3063 18.5477 22.1906 18.5468 22.1809C18.5459 22.1713 18.4718 22.2504 18.3822 22.3568C18.2927 22.4631 18.1874 22.5804 18.1483 22.6173C18.0961 22.6666 18.0874 22.6836 18.1153 22.6812C18.1395 22.6791 18.2257 22.5903 18.351 22.4382ZM10.1829 15.5745C10.236 15.5652 10.287 15.5484 10.2962 15.5372C10.3055 15.5261 10.3942 15.4796 10.4934 15.434C10.5925 15.3884 10.6787 15.3451 10.6848 15.3378C10.6909 15.3305 10.7521 15.3005 10.8209 15.2711C10.8896 15.2416 11.001 15.1779 11.0684 15.1296C11.1358 15.0812 11.2048 15.0389 11.2217 15.0356C11.2386 15.0322 11.2941 15.0003 11.345 14.9645C11.396 14.9287 11.4578 14.8877 11.4824 14.8735C11.7698 14.7067 11.879 14.6213 11.8052 14.6209C11.779 14.6208 11.7413 14.6404 11.7213 14.6645C11.6784 14.7161 11.3556 14.847 11.3278 14.824C11.3173 14.8153 11.3217 14.8012 11.3377 14.7927C11.7497 14.5737 11.8494 14.511 11.755 14.53C11.7223 14.5366 11.6867 14.5528 11.6758 14.566C11.6648 14.5791 11.5575 14.6328 11.4372 14.6852C11.2037 14.7868 10.8668 14.9693 10.7818 15.04C10.719 15.0923 10.6253 15.0995 10.644 15.0506C10.6725 14.9762 10.5217 15.0819 10.3669 15.2447C10.2759 15.3405 10.1674 15.4509 10.1258 15.4901C10.0358 15.5749 10.0511 15.5976 10.1829 15.5745ZM18.1983 21.9829C18.2433 21.9235 18.3858 21.7374 18.515 21.5693C18.6443 21.4012 18.7511 21.2557 18.7525 21.246C18.7539 21.2362 18.8174 21.143 18.8936 21.0389C19.0321 20.8496 19.1548 20.5564 19.1402 20.4496C19.1356 20.416 19.1309 20.4173 19.1172 20.4562C19.1077 20.483 19.0382 20.5957 18.9627 20.7066C18.8873 20.8174 18.8122 20.9325 18.7958 20.9623C18.7596 21.0281 18.6268 21.2563 18.5453 21.3928C18.5125 21.4478 18.453 21.5261 18.4131 21.5669C18.3731 21.6077 18.3211 21.6903 18.2974 21.7503C18.2737 21.8103 18.2263 21.8917 18.1921 21.9311C18.0697 22.0721 18.0248 22.1412 18.0725 22.1151C18.0968 22.1018 18.1534 22.0423 18.1983 21.9829ZM26.592 29.0206C26.6362 29.0264 26.7189 28.9793 26.8844 28.854C26.9578 28.7984 27.0867 28.7211 27.1708 28.6823C27.2549 28.6434 27.3293 28.6048 27.3362 28.5965C27.3431 28.5882 27.3923 28.5617 27.4456 28.5376C27.4989 28.5135 27.6474 28.4106 27.7758 28.3089C27.904 28.2072 28.1844 27.9999 28.3988 27.8483C28.6132 27.6966 28.8857 27.4827 29.0043 27.373C29.2271 27.1668 29.4332 27.0018 29.5845 26.9083C29.7362 26.8146 29.9357 26.6325 30.2247 26.3236C30.3217 26.2199 30.4504 26.0837 30.5106 26.0209C31.0673 25.4404 31.2348 25.2495 31.7116 24.652C32.1888 24.0539 32.5141 23.6105 32.7758 23.201C32.8912 23.0206 32.9485 22.9582 32.9857 22.9728C33.0327 22.9913 32.8763 23.2653 32.5794 23.6847C32.5175 23.7722 32.4452 23.8754 32.4188 23.9142C32.0404 24.4689 31.058 25.6486 30.5239 26.1899C30.4533 26.2614 30.3646 26.3582 30.3267 26.4048C30.1985 26.563 29.6932 26.9907 29.6023 27.018C29.587 27.0226 29.541 27.0625 29.5001 27.1066C29.4593 27.1508 29.3909 27.2119 29.3482 27.2425C29.3054 27.273 29.2606 27.3139 29.2486 27.3333C29.1884 27.4306 28.8344 27.7212 28.7632 27.7319C28.7329 27.7364 28.7025 27.7569 28.6956 27.7773C28.6842 27.8114 28.6146 27.8646 28.4965 27.9296C28.4187 27.9725 28.3075 28.0492 28.1956 28.1372C28.1366 28.1836 28.059 28.2409 28.0232 28.2645C27.9875 28.2881 27.9363 28.3338 27.9095 28.3661C27.8827 28.3983 27.8059 28.4542 27.7389 28.4903C27.6718 28.5264 27.6052 28.5674 27.5908 28.5815C27.5445 28.6266 27.2601 28.7938 27.2021 28.8099C27.1427 28.8265 27.0496 28.9217 27.0746 28.9402C27.0951 28.9554 27.279 28.8953 27.304 28.8653C27.3281 28.8363 27.4037 28.8045 27.5576 28.759C27.6852 28.7212 28.1091 28.5091 28.1461 28.4645C28.1596 28.4482 28.1953 28.4228 28.2253 28.4079C28.2554 28.393 28.3694 28.3059 28.4786 28.2144C28.5878 28.1229 28.7358 28.0045 28.8075 27.9512C29.0438 27.7755 29.3263 27.5492 29.4449 27.4407C29.509 27.382 29.6884 27.2257 29.8435 27.0934C30.2809 26.7202 30.3267 26.6761 30.6096 26.3557C30.7554 26.1905 30.9229 26.018 30.9817 25.9722C31.11 25.8724 31.5352 25.3715 31.9721 24.8055C32.4771 24.1514 32.589 23.9934 32.6812 23.8045C32.7287 23.7071 32.7859 23.6055 32.8082 23.5787C32.8446 23.5349 32.8989 23.4357 33.0589 23.1207C33.0867 23.0658 33.1044 22.9991 33.098 22.9724C33.0884 22.9321 33.097 22.9189 33.1489 22.894C33.1833 22.8775 33.2127 22.8544 33.2143 22.8427C33.2182 22.8139 33.3725 22.5515 33.4585 22.4272C33.4967 22.3722 33.5442 22.291 33.5642 22.2468C33.5841 22.2026 33.6317 22.1097 33.6699 22.0402C33.7081 21.9708 33.7332 21.9145 33.7259 21.9152C33.7044 21.917 33.099 22.6503 33.035 22.7519C33.0002 22.8072 32.954 22.8531 32.9192 22.8671C32.8732 22.8856 32.8561 22.9074 32.836 22.9731C32.8216 23.0202 32.7397 23.1465 32.6459 23.2664C32.5553 23.3823 32.4546 23.5118 32.4223 23.5544C32.3899 23.5969 32.3126 23.6889 32.2506 23.7589C32.1886 23.8288 32.0574 23.9897 31.9592 24.1163C31.5363 24.6613 31.3311 24.8996 30.7553 25.5144C30.406 25.8875 30.2971 25.9968 30.1533 26.1187C30.0137 26.2371 29.8805 26.3531 29.7732 26.4499C29.7281 26.4905 29.5874 26.608 29.4606 26.7109C29.2403 26.8899 29.174 26.9509 28.9017 27.2249C28.8356 27.2914 28.7681 27.349 28.7518 27.3528C28.7355 27.3566 28.6747 27.4052 28.6167 27.4608C28.5588 27.5164 28.4819 27.5709 28.4459 27.5818C28.4099 27.5927 28.3752 27.6172 28.3688 27.6362C28.3624 27.6553 28.2869 27.7215 28.2012 27.7835C28.1154 27.8454 28.0223 27.9237 27.9943 27.9574C27.9663 27.9911 27.9306 28.0168 27.915 28.0145C27.8994 28.0123 27.8571 28.0455 27.8212 28.0883C27.7414 28.1833 27.6082 28.2246 27.6015 28.1564C27.5981 28.1221 27.6126 28.1045 27.674 28.0687C27.754 28.022 27.9164 27.8887 28.0414 27.767C28.0816 27.7279 28.2003 27.6349 28.3052 27.5602C28.4102 27.4854 28.525 27.3987 28.5604 27.3674C28.5959 27.3361 28.6725 27.272 28.7308 27.2249C28.7891 27.1779 28.8888 27.0832 28.9524 27.0146C29.016 26.9459 29.1258 26.8454 29.1963 26.7912C29.4514 26.5952 29.7327 26.3621 29.9284 26.1844C30.0382 26.0847 30.1736 25.9629 30.2294 25.9137C30.2851 25.8646 30.4411 25.7031 30.576 25.5548C30.711 25.4066 30.9163 25.1866 31.0322 25.066C31.3631 24.722 32.7925 22.9497 32.8035 22.87C32.8052 22.8571 33.0735 22.5183 33.3997 22.1171C33.9676 21.4187 34.236 21.0743 34.3511 20.8966C34.3804 20.8515 34.4486 20.752 34.5027 20.6755C34.6116 20.5216 34.7038 20.3792 34.7485 20.2959C34.7646 20.2659 34.8153 20.1802 34.8612 20.1055C34.9771 19.9168 34.998 19.8721 34.9783 19.8557C34.9592 19.8399 34.8381 20.0024 34.8312 20.0531C34.8198 20.1361 33.9668 21.2284 33.5776 21.6583C33.4265 21.8253 32.9647 22.4548 32.9016 22.5798C32.858 22.6664 32.7438 22.7327 32.7004 22.6966C32.6799 22.6796 32.6546 22.714 32.5682 22.8763C32.4164 23.1618 31.2608 24.6203 30.8821 25.0044C30.6804 25.209 30.4409 25.4328 30.414 25.4417C30.4016 25.4458 30.3267 25.5194 30.2474 25.6054C30.095 25.7706 29.8122 26.0553 29.7194 26.137C29.689 26.1638 29.606 26.2439 29.5349 26.315C29.4638 26.3862 29.3661 26.4754 29.3178 26.5133C29.2694 26.5513 29.2053 26.6045 29.1753 26.6317C29.1453 26.6588 29.0497 26.7333 28.9629 26.7972C28.876 26.8611 28.7956 26.9336 28.7841 26.9583C28.7325 27.0694 28.3135 27.4147 28.2721 27.3802C28.2564 27.3672 28.2049 27.4183 28.0945 27.5561C27.9503 27.7361 27.6872 27.9967 27.4421 28.2024C27.3859 28.2495 27.3386 28.2984 27.3368 28.311C27.3323 28.3442 27.0926 28.5433 27.0624 28.5389C27.0484 28.5369 27.0225 28.5526 27.0049 28.5739C26.9872 28.5951 26.9079 28.6402 26.8285 28.6742C26.5131 28.809 26.3871 28.9937 26.592 29.0206ZM27.0227 29.2049C27.1532 29.2079 27.3123 29.1448 27.2382 29.1194C27.2187 29.1127 27.2061 29.0977 27.2103 29.086C27.2145 29.0743 27.1529 29.0878 27.0734 29.116C26.9364 29.1646 26.9149 29.2024 27.0227 29.2049ZM10.8252 15.5689C10.9905 15.5648 11.0208 15.5527 11.2432 15.4005C11.3536 15.325 11.6634 15.0786 11.6945 15.0416C11.6966 15.0391 11.708 15.045 11.7198 15.0548C11.735 15.0674 11.7111 15.1005 11.6379 15.1682C11.581 15.2207 11.5229 15.2787 11.5086 15.2969C11.4944 15.3151 11.4706 15.3283 11.4557 15.3261C11.4408 15.324 11.4271 15.3338 11.4251 15.348C11.4232 15.3622 11.4012 15.382 11.3763 15.3921C11.3514 15.4021 11.3012 15.4365 11.2647 15.4684C11.2283 15.5003 11.1814 15.5359 11.1606 15.5475C11.1356 15.5614 11.1324 15.5766 11.1511 15.5921C11.1903 15.6247 11.3935 15.5898 11.4585 15.5393C11.488 15.5163 11.5389 15.4804 11.5717 15.4594C11.6045 15.4384 11.6369 15.4046 11.6437 15.3842C11.6505 15.3639 11.7594 15.2524 11.8858 15.1365C12.0707 14.9668 12.1388 14.8901 12.2357 14.7423C12.3086 14.631 12.3731 14.5518 12.3995 14.5412C12.4598 14.5169 12.568 14.3768 12.6038 14.2765L12.6337 14.1929L12.5332 14.2651C12.4778 14.3049 12.4116 14.3483 12.386 14.3618C12.3286 14.3918 12.1724 14.5332 12.1191 14.6034C12.0974 14.632 12.0667 14.6535 12.0509 14.6512C12.0351 14.6489 12.0092 14.6627 11.9934 14.6818C11.9775 14.7008 11.9124 14.7417 11.8486 14.7726C11.7409 14.8248 11.6395 14.8933 11.4264 15.0577C11.3796 15.0938 11.2924 15.1474 11.2326 15.1769C11.1728 15.2064 11.1143 15.242 11.1026 15.2561C11.0836 15.2789 10.8279 15.4097 10.712 15.4558C10.5632 15.515 10.6222 15.5738 10.8252 15.5689ZM18.4635 20.576C18.6474 20.3296 18.8263 20.0877 18.8609 20.0383C18.8955 19.989 18.9439 19.9234 18.9685 19.8926C19.0024 19.85 19.0035 19.8374 18.9731 19.8401C18.9427 19.8428 18.8693 19.9325 18.6665 20.2149C18.5198 20.4191 18.3499 20.6512 18.2889 20.7307C18.2278 20.8101 18.1081 20.9734 18.0228 21.0934L17.8677 21.3117L17.9984 21.1678C18.0703 21.0887 18.2796 20.8223 18.4635 20.576ZM16.9262 20.069C17.0259 19.9288 17.0132 19.9067 16.9066 20.035C16.8583 20.0932 16.8267 20.1475 16.8365 20.1556C16.8462 20.1637 16.8866 20.1247 16.9262 20.069ZM9.4929 13.8918C9.54284 13.8595 9.6155 13.8169 9.65436 13.7971C9.69323 13.7774 9.75408 13.7458 9.78958 13.7269C9.82508 13.7081 9.95259 13.601 10.0729 13.489C10.1933 13.3769 10.3241 13.2625 10.3637 13.2346C10.4825 13.1511 10.5349 13.0778 10.4719 13.0833C10.4436 13.0858 10.3957 13.1177 10.3655 13.154C10.291 13.2438 9.94153 13.515 9.87095 13.5379C9.83964 13.5481 9.77367 13.5927 9.72434 13.637C9.675 13.6814 9.61142 13.7268 9.58304 13.7379C9.45918 13.7866 9.38143 13.8455 9.38283 13.8899C9.38489 13.9553 9.39446 13.9554 9.4929 13.8918ZM10.7327 14.9734C10.7463 14.957 10.7909 14.9266 10.8318 14.9059C10.8727 14.8851 10.9677 14.8341 11.0429 14.7924C11.1181 14.7507 11.2445 14.6854 11.3238 14.6471C11.4032 14.6089 11.5056 14.559 11.5515 14.5364C11.6437 14.4909 11.8512 14.4622 11.8619 14.4935C11.8656 14.5045 11.9 14.4939 11.9384 14.47C11.9767 14.4461 12.0793 14.3849 12.1664 14.3339C12.3813 14.2081 12.6225 14.0364 12.6344 14.0008C12.6398 13.9847 12.7089 13.9199 12.7879 13.8568C12.8669 13.7937 12.9812 13.691 13.0419 13.6286C13.1025 13.5662 13.2128 13.459 13.287 13.3905C13.3612 13.322 13.4313 13.2551 13.4428 13.242C13.4812 13.1979 13.415 13.2102 13.3555 13.2582C13.3233 13.2842 13.2496 13.3189 13.1919 13.3353C13.1341 13.3517 13.0689 13.3867 13.047 13.4131C13.0251 13.4395 12.9917 13.4624 12.9728 13.4641C12.9538 13.4657 12.8868 13.504 12.8238 13.549C12.6664 13.6616 12.3125 13.8122 12.3302 13.7591C12.3376 13.7369 12.408 13.6855 12.4867 13.6449C12.6806 13.545 12.8319 13.4514 12.8301 13.4326C12.8284 13.4147 12.5486 13.5127 12.4668 13.5598C12.4365 13.5773 12.3458 13.6155 12.2652 13.6448C12.0492 13.7233 11.8794 13.8123 11.7575 13.9112C11.723 13.9391 11.6731 13.9639 11.6467 13.9662C11.6148 13.969 11.5273 14.044 11.3865 14.1895C11.2699 14.3099 11.1537 14.417 11.1283 14.4275C11.1029 14.4379 11.038 14.4878 10.984 14.5384C10.93 14.589 10.8567 14.6493 10.8212 14.6724C10.7705 14.7052 10.7516 14.7369 10.7334 14.8191C10.7206 14.8767 10.7012 14.9347 10.6902 14.9479C10.6792 14.9612 10.6787 14.979 10.6891 14.9876C10.6994 14.9962 10.7191 14.9899 10.7327 14.9734ZM27.7944 28.9214C27.902 28.8627 27.9893 28.8074 27.9884 28.7986C27.9876 28.7898 27.9384 28.81 27.8791 28.8436C27.8198 28.8772 27.7371 28.914 27.6953 28.9253C27.6535 28.9366 27.6081 28.9593 27.5945 28.9757C27.5399 29.0414 27.6084 29.0228 27.7944 28.9214ZM21.3906 23.5766C21.4404 23.4823 21.4381 23.473 21.3179 23.2902C21.2715 23.2196 21.2068 23.0931 21.1742 23.0092C21.1415 22.9252 21.1108 22.8532 21.106 22.8491C21.1011 22.8451 21.0868 22.7977 21.0741 22.7438C21.0615 22.6899 21.0433 22.6393 21.0336 22.6313C21.024 22.6233 20.9968 22.5542 20.9732 22.4778C20.9125 22.2813 20.8353 22.0886 20.8236 22.1042C20.8045 22.1294 20.8096 22.2244 20.8309 22.2421C20.8427 22.2519 20.847 22.2664 20.8405 22.2742C20.834 22.282 20.8377 22.3099 20.8487 22.3362C20.8597 22.3624 20.8836 22.4501 20.9018 22.5309C20.9521 22.7537 21.0402 23.0233 21.1165 23.1877C21.1541 23.2689 21.1926 23.3748 21.202 23.4231C21.2113 23.4714 21.2393 23.5278 21.264 23.5483C21.2912 23.5709 21.3044 23.61 21.2975 23.6471C21.2823 23.7283 21.3291 23.6928 21.3906 23.5766ZM27.1009 28.1855C27.2472 28.0543 27.25 28.05 27.26 27.9424C27.2656 27.8822 27.2798 27.8214 27.2916 27.8072C27.3033 27.793 27.3191 27.7335 27.3266 27.675C27.3529 27.4688 27.4286 27.2157 27.5437 26.9489C27.5877 26.8466 27.6545 26.6749 27.692 26.5672C27.8218 26.1943 27.9156 25.9622 27.9878 25.8348C28.261 25.3532 28.5002 24.9649 28.6307 24.7912C28.8502 24.499 29.3543 23.8954 29.4164 23.8503C29.4443 23.8301 29.561 23.6999 29.6758 23.561C29.7906 23.422 29.9378 23.2603 30.003 23.2016C30.0681 23.1429 30.2396 22.9801 30.3841 22.8398C30.6677 22.5641 31.0104 22.265 31.1899 22.1365C31.2516 22.0923 31.3487 22.0177 31.4056 21.9708C31.4626 21.9239 31.5314 21.8816 31.5584 21.8768C31.6747 21.8563 31.8544 21.6969 31.8233 21.6419C31.7874 21.5782 31.69 21.6062 31.6743 21.6846C31.6673 21.7195 31.6385 21.7444 31.5726 21.7724C31.522 21.794 31.4334 21.8566 31.3757 21.9116C31.318 21.9665 31.2511 22.0114 31.227 22.0113C31.2029 22.0112 31.154 22.0353 31.1183 22.0648C31.0826 22.0943 31.042 22.1168 31.0282 22.1148C31.0143 22.1128 30.9868 22.1307 30.967 22.1545C30.9472 22.1783 30.9101 22.1977 30.8846 22.1976C30.859 22.1975 30.8168 22.2245 30.7908 22.2576C30.7318 22.3327 30.5994 22.4518 30.5144 22.5064C30.4791 22.529 30.4148 22.5822 30.3716 22.6244C30.3284 22.6666 30.2342 22.7542 30.1623 22.8191C30.0904 22.884 29.9268 23.0534 29.7989 23.1957C29.671 23.3379 29.4978 23.5181 29.4141 23.596C29.2417 23.7567 28.8782 24.1983 28.89 24.2329C28.8943 24.2455 28.8292 24.3479 28.7454 24.4605C28.5187 24.7654 28.2167 25.2238 28.1904 25.3031C28.1777 25.3414 28.1451 25.3995 28.1181 25.4324C28.0911 25.4652 28.0432 25.5487 28.0117 25.618C27.9802 25.6873 27.8893 25.8672 27.8097 26.0177C27.7301 26.1683 27.6579 26.3245 27.6492 26.3648C27.6406 26.4051 27.5909 26.531 27.5389 26.6446C27.487 26.7581 27.4359 26.89 27.4254 26.9376C27.3978 27.0627 27.3094 27.2845 27.2058 27.4889C27.1562 27.5868 27.0978 27.7333 27.0761 27.8146C27.0545 27.8959 27.0187 27.9938 26.9967 28.0322C26.8306 28.3217 26.8755 28.3877 27.1009 28.1855ZM9.30978 13.3059L9.34855 13.2592L9.2947 13.2934C9.26508 13.3122 9.2234 13.3486 9.20208 13.3742L9.16331 13.4209L9.21716 13.3868C9.24678 13.368 9.28846 13.3316 9.30978 13.3059ZM9.76037 13.2309C9.77564 13.2125 9.80851 13.1898 9.83341 13.1803C9.89019 13.1587 10.1046 13.0125 10.103 12.9964C10.1007 12.9731 9.88812 13.0791 9.76626 13.1644C9.6982 13.212 9.60137 13.2755 9.55107 13.3055C9.50078 13.3355 9.42165 13.3976 9.37523 13.4434C9.29984 13.5179 9.3144 13.5128 9.51172 13.3956C9.63321 13.3234 9.7451 13.2493 9.76037 13.2309ZM12.1792 15.2876C12.3306 15.2178 12.5538 15.039 12.7166 14.8572C12.8423 14.7168 12.8761 14.6984 12.9564 14.7261C13.047 14.7574 13.4698 14.4064 13.7929 14.0315C13.9918 13.8007 13.9958 13.7972 14.0675 13.7935C14.1653 13.7883 14.5831 13.2871 14.7625 12.9594C14.858 12.7852 14.8904 12.7216 14.9038 12.6823C14.9107 12.662 14.9659 12.59 15.0264 12.5222C15.1522 12.3812 15.2249 12.1535 15.1717 12.0669C15.0777 11.9139 15.0674 11.9071 14.994 11.9492C14.9556 11.9713 14.9043 11.9975 14.88 12.0075C14.8031 12.0389 14.7699 12.0979 14.8102 12.1314C14.8985 12.2047 14.8533 12.6867 14.746 12.8159C14.6859 12.8883 14.6366 12.8716 14.68 12.7936C14.7829 12.609 14.797 12.1654 14.7015 12.1193C14.6257 12.0828 14.7462 11.9572 14.9504 11.8598C15.0261 11.8237 15.0825 11.7895 15.0757 11.7839C15.0499 11.7625 14.7701 11.7979 14.7472 11.8255C14.734 11.8414 14.6879 11.8443 14.6447 11.8319C14.6015 11.8194 14.5151 11.8258 14.4528 11.8459C14.3906 11.866 14.3149 11.8805 14.2846 11.8781C14.2544 11.8757 14.2196 11.8858 14.2073 11.9007C14.195 11.9155 14.1774 11.9214 14.1683 11.9138C14.1508 11.8993 13.8936 12.0101 13.8651 12.0445C13.856 12.0555 13.8107 12.0743 13.7645 12.0863C13.7183 12.0983 13.6851 12.112 13.6906 12.1166C13.7097 12.1325 14.0126 12.0521 14.1657 11.9905C14.412 11.8915 14.5611 11.8486 14.6263 11.8581C14.7136 11.8709 14.7036 11.8887 14.5916 11.9199C14.5377 11.935 14.3779 11.9892 14.2365 12.0405C14.0952 12.0917 13.954 12.1359 13.9229 12.1386C13.8178 12.1479 13.4141 12.3193 13.3687 12.3739C13.3564 12.3887 13.3195 12.41 13.2867 12.4212C13.2539 12.4324 13.2145 12.4595 13.1993 12.4816C13.184 12.5036 13.1573 12.5417 13.1398 12.5663C13.0861 12.6421 13.1381 12.6444 13.3001 12.5732C13.4538 12.5057 13.5685 12.476 13.5711 12.5031C13.5719 12.5107 13.5177 12.5405 13.4508 12.5692C13.3839 12.5979 13.2436 12.6781 13.1391 12.7474C12.7917 12.9777 12.6084 13.0557 12.7939 12.8942L12.8634 12.8337L12.7717 12.8493C12.6786 12.8651 12.6316 12.8927 12.506 13.0049C12.4675 13.0394 12.4055 13.0803 12.3684 13.0957C12.3312 13.1111 12.2749 13.1548 12.2433 13.1927C12.1451 13.3107 11.8845 13.51 11.7507 13.5697C11.6718 13.6049 11.6619 13.6678 11.7226 13.7487C11.758 13.7959 11.7696 13.7967 11.8219 13.7562C11.8545 13.7309 11.9014 13.7104 11.9263 13.7105C11.9511 13.7106 11.9727 13.7019 11.9741 13.6912C11.9776 13.6658 12.1993 13.5705 12.8149 13.3298C12.9002 13.2964 13.009 13.267 13.0568 13.2643C13.178 13.2576 13.361 13.1882 13.4086 13.1309C13.4446 13.0875 13.4593 13.0868 13.4984 13.1266C13.5314 13.1604 13.6979 12.9747 13.7896 12.8018L13.8173 12.7496L13.7233 12.7558C13.5868 12.7649 12.4783 13.2546 12.4111 13.3354C12.3986 13.3505 12.3551 13.3687 12.3144 13.3759L12.2405 13.389L12.3063 13.3333C12.4085 13.2468 12.6175 13.1245 12.8077 13.0398C13.2176 12.8574 13.6875 12.6414 13.9938 12.4945C14.0799 12.4532 14.1877 12.3865 14.2333 12.3463C14.3485 12.2447 14.517 12.1402 14.5378 12.1575C14.5598 12.1758 14.5068 12.2384 14.4045 12.315C14.3232 12.3758 13.9809 12.7765 13.709 13.129C13.6265 13.2359 13.4993 13.3744 13.4263 13.4367C13.3533 13.499 13.2447 13.605 13.185 13.6723C13.1254 13.7395 12.9943 13.8602 12.8936 13.9404C12.6749 14.1148 12.6436 14.1497 12.6793 14.1794C12.7713 14.2558 12.3244 14.8773 11.9355 15.2137C11.7815 15.3469 11.7871 15.3417 11.7755 15.3613C11.7533 15.3988 12.0596 15.3429 12.1792 15.2876ZM21.5569 23.2179C21.5742 23.1668 21.5635 23.1406 21.4959 23.0694C21.4508 23.0219 21.3827 22.9084 21.3445 22.8174C21.3064 22.7263 21.2427 22.5787 21.2031 22.4893C21.1635 22.4 21.1245 22.309 21.1165 22.287C21.0392 22.0759 20.963 21.9559 21.007 22.1145C21.0226 22.1708 21.0543 22.2533 21.0775 22.298C21.1006 22.3426 21.1234 22.4263 21.128 22.4839C21.1326 22.5416 21.1432 22.5947 21.1514 22.6021C21.1596 22.6094 21.1764 22.6582 21.1887 22.7106C21.201 22.763 21.2248 22.8324 21.2416 22.8649C21.2583 22.8973 21.2781 22.9424 21.2855 22.9651C21.3072 23.0319 21.3804 23.1663 21.4368 23.2429C21.496 23.3235 21.523 23.3179 21.5569 23.2179ZM28.1988 28.7155C28.275 28.6789 28.3794 28.6201 28.4309 28.5848C28.4825 28.5495 28.5371 28.5168 28.5524 28.5122C28.612 28.494 28.7896 28.3791 28.9902 28.2289C29.1055 28.1425 29.2179 28.0619 29.2398 28.0497C29.2619 28.0376 29.2712 28.0206 29.2606 28.0118C29.2414 27.9959 29.0426 28.0751 29.0134 28.1103C29.0049 28.1205 28.9666 28.1327 28.9282 28.1375C28.8787 28.1436 28.8033 28.1952 28.6691 28.3148C28.4837 28.4799 28.26 28.6408 28.1076 28.7186C27.9731 28.7873 28.055 28.7845 28.1988 28.7155ZM9.65253 13.0848C9.74112 13.0199 9.86766 12.9513 9.9507 12.9232C10.0779 12.8801 10.402 12.6977 10.3803 12.6814C10.3735 12.6763 10.312 12.6856 10.2436 12.702C10.1343 12.7284 10.028 12.7816 9.72885 12.9598C9.68626 12.9852 9.63089 13.0173 9.60579 13.0311C9.5807 13.045 9.51721 13.0988 9.46471 13.1506L9.36925 13.2449L9.46519 13.1983C9.51795 13.1727 9.60225 13.1217 9.65253 13.0848ZM18.6194 20.6581L18.6895 20.5428L18.5871 20.6613C18.5238 20.7346 18.4971 20.7786 18.517 20.7766C18.536 20.7747 18.5781 20.726 18.6194 20.6581ZM10.3933 13.3854C10.4692 13.3183 10.552 13.2486 10.5773 13.2306C10.6048 13.211 10.6148 13.1908 10.6023 13.1803C10.5907 13.1707 10.5599 13.1886 10.5337 13.2201C10.5076 13.2516 10.4664 13.2853 10.4423 13.295C10.4182 13.3047 10.3413 13.3713 10.2716 13.443C10.1199 13.599 10.189 13.5663 10.3933 13.3854ZM21.755 22.8415C21.7602 22.7947 21.7411 22.7467 21.6981 22.6976C21.6625 22.6571 21.615 22.5845 21.5925 22.5363C21.5593 22.465 21.5449 22.4508 21.5158 22.4605C21.4705 22.4755 21.4415 22.4308 21.3507 22.2067C21.3116 22.1101 21.2542 21.9769 21.2232 21.9108C21.1409 21.7353 21.1497 21.8484 21.235 22.064C21.2723 22.1582 21.3104 22.2734 21.3196 22.3199C21.3288 22.3665 21.3767 22.49 21.426 22.5943C21.4752 22.6987 21.5412 22.8394 21.5725 22.9071L21.6295 23.0302L21.6884 22.971C21.7218 22.9375 21.7507 22.8813 21.755 22.8415ZM18.7986 20.4362C18.8696 20.3469 18.8696 20.3464 18.8015 20.3895C18.7636 20.4134 18.7268 20.4503 18.7197 20.4715C18.6964 20.541 18.7258 20.5279 18.7986 20.4362ZM13.3703 15.7669C13.4357 15.7713 13.5143 15.7854 13.5448 15.7982C13.5754 15.811 13.6458 15.826 13.7012 15.8316C13.7565 15.8372 13.834 15.8586 13.8734 15.879C13.9802 15.9347 14.1888 15.9474 14.2319 15.901C14.3557 15.7672 14.3876 15.7261 14.433 15.6419C14.4933 15.5298 14.4645 15.5093 14.332 15.5699C14.2791 15.5941 14.2032 15.6207 14.1634 15.6291C14.1237 15.6374 14.072 15.6673 14.0486 15.6954C13.9843 15.7729 13.8872 15.8459 13.8793 15.8227C13.8754 15.8114 13.908 15.7679 13.9516 15.726C14.0131 15.6671 14.0264 15.6419 14.0107 15.6142C13.9898 15.5772 14.0878 15.5068 14.1213 15.5346C14.1293 15.5412 14.2052 15.5145 14.2901 15.4753C14.3749 15.4361 14.4877 15.3964 14.5407 15.3871C14.5937 15.3778 14.6438 15.362 14.6521 15.3521C14.6603 15.3422 14.7103 15.3217 14.7632 15.3067C14.8161 15.2916 14.9221 15.2534 14.9987 15.2217C15.0753 15.1901 15.1954 15.145 15.2657 15.1215C15.3359 15.0981 15.4396 15.0461 15.496 15.006C15.5524 14.9659 15.6233 14.9309 15.6535 14.9283C15.6837 14.9256 15.7163 14.9139 15.726 14.9022C15.7449 14.8794 16.474 14.5284 16.5258 14.5172C16.58 14.5055 17.0314 14.2502 17.061 14.2146C17.1052 14.1613 16.6903 14.0201 16.6102 14.061C16.5921 14.0703 16.2188 14.0583 16.2065 14.0481C16.2031 14.0452 16.0277 14.0557 15.8168 14.0714C15.6058 14.0872 15.4268 14.0946 15.4188 14.088C15.4108 14.0814 15.3487 14.0901 15.2807 14.1074C15.2127 14.1247 15.1154 14.1441 15.0645 14.1504C15.0136 14.1567 14.9658 14.1693 14.9583 14.1784C14.9508 14.1874 14.9258 14.1873 14.9029 14.178C14.8558 14.159 14.792 14.1846 14.5755 14.3095L14.4248 14.3964L14.3557 14.5845C14.2576 14.8514 13.8317 15.3662 13.6222 15.4709C13.5781 15.4929 13.4958 15.5365 13.4393 15.5677C13.3829 15.5989 13.3131 15.6375 13.2843 15.6534C13.167 15.7182 13.1949 15.7549 13.3703 15.7669ZM27.1909 27.2159C27.2158 27.1715 27.2495 27.0895 27.2657 27.0335C27.3427 26.7683 27.3777 26.6795 27.5343 26.3521C27.5621 26.2942 27.5837 26.2352 27.5823 26.221C27.5809 26.2069 27.5949 26.1771 27.6135 26.1547C27.632 26.1324 27.6831 26.038 27.727 25.9449C27.7709 25.8518 27.8244 25.7458 27.846 25.7094C27.8677 25.6729 27.887 25.6307 27.8891 25.6154C27.8912 25.6002 27.9288 25.5347 27.9727 25.47C28.0167 25.4052 28.0648 25.3217 28.0797 25.2844C28.0946 25.2471 28.1152 25.2138 28.1254 25.2104C28.1534 25.2011 28.1585 25.1232 28.131 25.1257C28.1178 25.1268 28.0887 25.1519 28.0663 25.1814C27.9309 25.3595 27.8492 25.488 27.839 25.5391C27.8288 25.5897 27.7262 25.7657 27.5854 25.9739C27.5628 26.0072 27.5261 26.1035 27.5037 26.1878C27.4516 26.3841 27.3983 26.5274 27.3598 26.5753C27.3199 26.6247 27.2542 26.8032 27.245 26.8866C27.2411 26.9228 27.2293 26.9531 27.2189 26.954C27.2084 26.9549 27.1953 27.0052 27.1896 27.0657C27.184 27.1263 27.1676 27.19 27.1532 27.2074C27.1288 27.2367 27.1217 27.2768 27.1385 27.2907C27.1424 27.294 27.166 27.2603 27.1909 27.2159ZM27.538 27.5357C27.5396 27.5241 27.577 27.4602 27.621 27.3939C27.6651 27.3275 27.7155 27.2221 27.733 27.1595C27.7506 27.0969 27.7797 27.0278 27.7977 27.006C27.8159 26.9842 27.8616 26.8784 27.8995 26.7711C27.9374 26.6637 27.9825 26.5379 27.9997 26.4915C28.017 26.4451 28.0387 26.385 28.0479 26.358C28.0572 26.331 28.0763 26.2758 28.0903 26.2354C28.1043 26.195 28.1334 26.134 28.155 26.0998C28.1765 26.0657 28.2545 25.9104 28.3283 25.7547C28.4984 25.3956 28.5183 25.359 28.6635 25.1394C28.6992 25.0853 28.7895 24.9402 28.8641 24.8169C28.9386 24.6937 29.0318 24.5451 29.071 24.4869C29.1531 24.3649 29.1295 24.3392 29.0359 24.4487C29.0012 24.4894 28.9599 24.527 28.9442 24.5322C28.9285 24.5374 28.9158 24.5595 28.9159 24.5813C28.916 24.6031 28.8506 24.708 28.7707 24.8143C28.6908 24.9206 28.6067 25.0418 28.5839 25.0836C28.5612 25.1255 28.5195 25.1903 28.4914 25.2276C28.4633 25.265 28.4383 25.3105 28.4359 25.3287C28.4335 25.3469 28.4062 25.3882 28.3753 25.4204C28.2885 25.5109 27.9252 26.2663 27.862 26.4876C27.8303 26.5988 27.7562 26.7929 27.7112 26.8829C27.6397 27.0258 27.5538 27.2718 27.5475 27.3513C27.5441 27.3946 27.5351 27.4375 27.5274 27.4467C27.5198 27.4559 27.5154 27.4819 27.5175 27.5046C27.522 27.5507 27.5336 27.5682 27.538 27.5357ZM19.1505 20.0011C19.3599 19.7544 19.5323 19.4916 19.5015 19.466C19.493 19.459 18.9042 20.2098 18.8658 20.2765C18.8106 20.3726 18.9488 20.2389 19.1505 20.0011ZM27.7778 27.4903C27.8162 27.4441 27.8391 27.3992 27.8287 27.3906C27.8078 27.3732 27.7531 27.4321 27.7171 27.5109C27.6811 27.5896 27.7009 27.5828 27.7778 27.4903ZM21.8539 22.638C21.8711 22.6284 21.8842 22.6074 21.883 22.5912C21.8818 22.575 21.8953 22.5386 21.913 22.5101C21.9455 22.4581 21.916 22.4044 21.7737 22.2563C21.7487 22.2303 21.6982 22.1272 21.6616 22.0272C21.6249 21.9272 21.5607 21.7572 21.5189 21.6495C21.4771 21.5417 21.4319 21.4203 21.4185 21.3798C21.2641 20.9108 21.238 20.86 21.2361 21.0253C21.2355 21.0722 21.2295 21.136 21.2227 21.167C21.216 21.198 21.2282 21.2721 21.25 21.3316C21.2717 21.3912 21.2947 21.4796 21.301 21.5282C21.3073 21.5769 21.3381 21.6792 21.3695 21.7557C21.4008 21.8322 21.4357 21.9274 21.447 21.9672C21.4802 22.0845 21.734 22.5548 21.8121 22.6435C21.8179 22.6501 21.8367 22.6476 21.8539 22.638ZM14.4255 16.0755C14.5203 16.1217 14.5758 16.1356 14.5934 16.1175C14.7031 16.0047 14.8147 15.8452 14.8632 15.7321C14.9383 15.5567 14.9858 15.5317 14.9406 15.6913C14.8819 15.8982 14.7696 16.0777 14.6471 16.1606C14.5628 16.2176 14.798 16.3407 14.959 16.3239L15.1097 16.3081L15.2796 16.1337C15.373 16.0377 15.468 15.9391 15.4905 15.9144L15.5315 15.8696L15.5137 15.9337C15.5039 15.9689 15.4808 16.0137 15.4625 16.0331C15.4441 16.0526 15.3709 16.1337 15.2997 16.2134L15.1703 16.3584L15.2287 16.4002C15.3462 16.4841 15.6951 16.4816 16.1721 16.3934L16.3665 16.3575L16.535 16.1782C16.6779 16.0262 16.701 15.9928 16.6875 15.958C16.6787 15.9355 16.6952 15.8764 16.7241 15.8266C16.8612 15.5908 16.85 15.4609 16.7059 15.6161C16.6609 15.6645 16.5803 15.7299 16.5267 15.7614C16.4732 15.7929 16.4142 15.8369 16.3956 15.8592C16.3771 15.8815 16.3474 15.9012 16.3297 15.903C16.311 15.9048 16.2625 15.9603 16.2144 16.0349C16.1687 16.1056 16.1225 16.1643 16.1118 16.1653C16.101 16.1663 16.0464 16.2223 15.9903 16.2898C15.9276 16.3653 15.8778 16.4084 15.8607 16.4019C15.8405 16.3941 15.8887 16.3291 16.0405 16.1597C16.2722 15.9012 16.2572 15.885 15.9598 16.0726C15.8464 16.1441 15.6491 16.1839 15.6966 16.1257C15.7031 16.1177 15.6732 16.1218 15.6301 16.1347L15.5516 16.1581L15.7564 15.9071C16.0614 15.5331 16.2474 15.221 16.3635 14.8884C16.4144 14.7427 16.1854 14.7645 15.9662 14.9262C15.9514 14.9372 15.9168 14.9493 15.8893 14.9532C15.8021 14.9656 15.6623 15.0475 15.6895 15.0703C15.7701 15.138 15.6588 15.4454 15.4559 15.7156C15.257 15.9802 15.1767 16.009 15.3599 15.7499C15.5493 15.4821 15.5701 15.4438 15.6052 15.297C15.6558 15.0849 15.6416 15.0613 15.5118 15.1418C15.4514 15.1791 15.3869 15.2078 15.3683 15.2054C15.3497 15.2031 15.2566 15.2359 15.1613 15.2782C15.066 15.3206 14.9342 15.3715 14.8683 15.3915C14.6371 15.4614 14.5066 15.5584 14.4905 15.6721C14.4866 15.7004 14.3283 15.8695 14.2453 15.9342C14.1953 15.9732 14.1942 15.9802 14.2362 15.9925C14.2625 16.0001 14.3476 16.0375 14.4255 16.0755ZM21.7625 21.8138C21.7477 21.6958 21.7187 21.5205 21.6979 21.4243C21.6771 21.328 21.6643 21.2442 21.6694 21.2379C21.6744 21.2317 21.6656 21.182 21.6497 21.1275C21.6338 21.073 21.6303 21.0169 21.642 21.0028C21.6537 20.9888 21.6552 20.9705 21.6452 20.9622C21.6215 20.9425 21.5526 20.1818 21.5596 20.0166C21.568 19.8199 21.5451 19.8424 21.4821 20.0932C21.3998 20.4206 21.3874 20.5044 21.3973 20.6666C21.4091 20.8617 21.5838 21.522 21.6945 21.7897C21.7275 21.8696 21.7528 21.948 21.7506 21.964C21.7484 21.9799 21.7563 22.0009 21.768 22.0107C21.7797 22.0204 21.7773 21.9319 21.7625 21.8138ZM22.2013 21.9984C22.2515 21.9043 22.3129 21.7953 22.3377 21.7562C22.3625 21.7171 22.416 21.6283 22.4566 21.5589C22.4971 21.4895 22.5392 21.4297 22.55 21.4262C22.5608 21.4226 22.5797 21.3898 22.5921 21.3533C22.6088 21.3039 22.6325 21.2791 22.6845 21.2564C22.7313 21.236 22.7533 21.2145 22.751 21.1914C22.7492 21.1724 22.7888 21.1012 22.839 21.0331C22.9522 20.8796 23.099 20.6389 23.1369 20.5445C23.1526 20.5055 23.2065 20.4154 23.2568 20.3443C23.6042 19.8526 23.7732 19.5821 24.0872 19.0147C24.454 18.3519 24.7535 17.8653 25.0831 17.3966C25.336 17.0368 25.3902 16.9534 25.4409 16.846C25.4652 16.7945 25.5631 16.6255 25.6585 16.4705C25.7539 16.3154 25.8436 16.1627 25.8579 16.1312C25.8721 16.0996 25.9272 16.0176 25.9803 15.9489C26.0794 15.8208 26.1526 15.7133 26.3216 15.4476C26.3748 15.3639 26.4323 15.2876 26.4494 15.2781C26.4665 15.2685 26.4932 15.225 26.5088 15.1813C26.553 15.0574 26.6577 14.8795 26.7928 14.6991C26.8609 14.6081 26.9225 14.5101 26.9296 14.4813C26.9367 14.4525 27.0187 14.329 27.1118 14.2067C27.3295 13.9209 27.4051 13.7975 27.3949 13.7443C27.3904 13.7208 27.3994 13.6863 27.4149 13.6677C27.4304 13.649 27.4389 13.6215 27.4338 13.6065C27.4287 13.5916 27.4482 13.5509 27.477 13.5162C27.5059 13.4814 27.5257 13.4419 27.521 13.4282C27.5164 13.4146 27.5485 13.3125 27.5923 13.2013L27.6721 12.9992L27.5608 13.0469C27.4426 13.0975 27.3822 13.1111 27.2032 13.1272C27.1417 13.1328 27.0854 13.1444 27.0782 13.1532C27.0709 13.1619 26.9999 13.1741 26.9204 13.1802C26.8409 13.1863 26.7463 13.2011 26.7101 13.2131C26.6739 13.225 26.5621 13.2432 26.4616 13.2536C26.3611 13.2639 26.2741 13.2781 26.2682 13.2852C26.2623 13.2923 26.2279 13.2993 26.1917 13.3007C26.1555 13.3021 26.1166 13.3145 26.1051 13.3283C26.0936 13.3421 26.0763 13.3469 26.0667 13.3388C26.057 13.3308 26.0321 13.335 26.0113 13.3481C25.9905 13.3612 25.8942 13.3821 25.7973 13.3946C25.6232 13.417 25.6196 13.4189 25.4831 13.5595C25.3621 13.6841 25.1782 13.8605 25.018 14.0056C24.8962 14.1159 24.753 14.2252 24.7025 14.2461C24.6592 14.2642 24.636 14.2997 24.591 14.4179C24.5597 14.4998 24.525 14.5699 24.5138 14.5736C24.5026 14.5773 24.4851 14.6167 24.4748 14.6611C24.4529 14.7563 24.4002 14.8483 24.298 14.9701C24.2572 15.0187 24.1593 15.1717 24.0804 15.31C23.9009 15.625 23.8673 15.6792 23.7609 15.8253C23.7137 15.8902 23.6552 15.9761 23.6309 16.0162C23.6067 16.0563 23.4235 16.296 23.2239 16.5488C23.0242 16.8016 22.8175 17.0739 22.7644 17.1539C22.7114 17.2339 22.6561 17.3004 22.6416 17.3016C22.6271 17.3029 22.5546 17.3955 22.4805 17.5073C22.4065 17.6192 22.3361 17.7203 22.3242 17.7321C22.2248 17.8303 22.0906 18.037 22.073 18.1188C22.0633 18.1635 22.0231 18.2497 21.9835 18.3103C21.9439 18.371 21.9061 18.4608 21.8994 18.5099C21.8927 18.5591 21.8788 18.6093 21.8686 18.6216C21.8584 18.634 21.8496 18.7235 21.8491 18.8207C21.8486 18.9179 21.8293 19.078 21.8062 19.1766C21.783 19.2751 21.7628 19.4082 21.7612 19.4724C21.7595 19.5365 21.7452 19.6148 21.7293 19.6465C21.7135 19.6781 21.7053 19.7848 21.7113 19.8836C21.7172 19.9823 21.7153 20.0718 21.707 20.0825C21.6899 20.1046 21.6873 20.24 21.7038 20.2537C21.7248 20.271 21.737 20.3901 21.7199 20.4107C21.7105 20.4221 21.7146 20.4602 21.7291 20.4955C21.7436 20.5307 21.7476 20.569 21.738 20.5806C21.7284 20.5922 21.7364 20.6694 21.7559 20.7522C21.7753 20.8351 21.7886 20.9307 21.7854 20.9647C21.7822 20.9987 21.7923 21.0796 21.8079 21.1446C21.8611 21.3667 21.9313 21.7469 21.9259 21.7833C21.9209 21.8174 21.9856 22.0463 22.0328 22.1614C22.0622 22.2331 22.0909 22.2054 22.2013 21.9984ZM28.1676 26.9701C28.3119 26.7689 28.3891 26.6476 28.4466 26.5313C28.4935 26.4367 28.6717 26.1388 28.8565 25.8463C28.9176 25.7495 29.002 25.6138 29.0441 25.5446C29.0862 25.4754 29.1606 25.3597 29.2095 25.2875C29.2584 25.2153 29.3585 25.0429 29.4318 24.9043C29.5052 24.7656 29.6293 24.5653 29.7076 24.459C29.7858 24.3527 29.851 24.2576 29.8523 24.2475C29.8636 24.1646 30.4845 23.397 30.6138 23.3061C30.6561 23.2764 30.7482 23.2005 30.8186 23.1374C30.889 23.0744 31.0154 22.965 31.0995 22.8943C31.1837 22.8236 31.2917 22.7287 31.3395 22.6834C31.5108 22.5212 31.8454 22.2527 31.9307 22.2091C32.0305 22.1579 32.0592 22.1011 32.0072 22.0579C31.9828 22.0377 31.9537 22.0418 31.918 22.0706C31.8888 22.0941 31.8239 22.1432 31.7738 22.1796C31.7237 22.2161 31.6268 22.2989 31.5586 22.3637C31.4903 22.4285 31.3583 22.5389 31.2654 22.6092C31.1724 22.6795 31.0855 22.7494 31.0724 22.7645C31.0173 22.8276 30.7704 23.0426 30.7014 23.0874C30.6388 23.1281 30.5412 23.2351 30.3657 23.4554C30.349 23.4763 30.1646 23.6994 29.9558 23.9511C29.5467 24.4443 29.3674 24.6794 29.361 24.7308C29.3588 24.7487 29.3205 24.8181 29.2758 24.8851C29.1742 25.0374 28.9722 25.3832 28.8663 25.5862C28.8221 25.671 28.7563 25.7939 28.7202 25.8593C28.5652 26.1406 28.5046 26.2631 28.4491 26.4072C28.3719 26.6075 28.3371 26.6701 28.206 26.8445C28.0646 27.0326 28.02 27.1078 28.0401 27.1245C28.0459 27.1293 28.1033 27.0598 28.1676 26.9701ZM29.1721 27.9303C29.1965 27.9116 29.2988 27.8439 29.3992 27.7798C29.5983 27.6529 29.627 27.6336 29.8716 27.4622C30.149 27.2679 30.4963 26.9534 30.3487 27.0302C30.1982 27.1085 30.2482 27.0268 30.4671 26.8367C30.607 26.7151 31.3506 25.9283 31.4611 25.7848C31.5164 25.713 31.9289 25.1629 31.9932 25.0752C32.0367 25.0158 32.1274 24.8923 32.1947 24.8007C32.3786 24.5505 32.5179 24.3442 32.5482 24.2773C32.5855 24.1949 32.1395 24.7561 31.8625 25.1402C31.7373 25.3138 31.6019 25.4996 31.5617 25.5529C31.4845 25.6554 31.1291 26.0097 30.9826 26.1303C30.9349 26.1696 30.8092 26.3101 30.7033 26.4427C30.5974 26.5752 30.5007 26.6822 30.4885 26.6805C30.4763 26.6787 30.4282 26.7275 30.3816 26.7889C30.335 26.8502 30.2786 26.9081 30.2563 26.9174C30.2137 26.9353 29.8108 27.2831 29.5931 27.49C29.5229 27.5567 29.4559 27.6147 29.4444 27.6189C29.4328 27.623 29.3584 27.6926 29.279 27.7736C29.1996 27.8546 29.125 27.924 29.1133 27.9279C29.1016 27.9318 29.1 27.9416 29.1098 27.9497C29.1195 27.9578 29.1476 27.9491 29.1721 27.9303ZM18.0972 18.6154C18.1583 18.5636 18.1589 18.5606 18.105 18.5727C18.0731 18.5799 18.0295 18.6068 18.0081 18.6326C17.9549 18.6967 18.0149 18.6851 18.0972 18.6154ZM28.3552 27.1968C28.3831 27.22 28.4612 27.1704 28.5597 27.0669C28.7109 26.9079 28.9879 26.6572 29.0687 26.6062C29.1854 26.5327 29.5248 26.2258 29.8327 25.9155C29.8799 25.868 29.9687 25.7784 30.03 25.7165C30.0912 25.6546 30.17 25.578 30.2049 25.5463C30.2399 25.5146 30.3002 25.4582 30.339 25.421C30.3777 25.3837 30.4776 25.2892 30.561 25.2109C30.9839 24.8136 31.3611 24.3637 32.2519 23.1938C32.4754 22.9003 32.5177 22.8299 32.5919 22.6283C32.67 22.4159 32.7303 22.3641 32.7215 22.5169C32.7162 22.6086 32.7628 22.5706 32.8738 22.3928C33.0135 22.1688 33.4546 21.6151 33.6422 21.4279C33.8409 21.2297 33.9799 21.0667 34.1778 20.8C34.2694 20.6765 34.4005 20.5015 34.4693 20.411C34.6983 20.1096 34.8198 19.9313 34.9084 19.7661C34.9903 19.6136 35.1018 19.4136 35.2735 19.1115C35.3724 18.9375 35.5561 18.91 35.4818 19.0803C35.4443 19.1661 35.4673 19.2332 35.5065 19.1524C35.5204 19.1239 35.531 19.0745 35.5302 19.0427C35.5293 19.0046 35.5581 18.9506 35.6149 18.8843C35.711 18.7719 35.7066 18.7308 35.6071 18.813C35.5715 18.8424 35.5097 18.8733 35.4697 18.8817C35.3866 18.8992 35.095 19.1876 35.0783 19.2689C35.0628 19.3447 34.9552 19.5033 34.6851 19.8489C33.8101 20.9681 33.1574 21.7528 33.0801 21.7784C33.0624 21.7843 33.048 21.8076 33.0481 21.8301C33.0483 21.8905 32.5517 22.4362 32.4968 22.4359C32.4261 22.4356 32.4369 22.3945 32.536 22.2864C32.5886 22.229 32.7754 22.0175 32.951 21.8163C33.1267 21.6151 33.3091 21.4116 33.3564 21.3641C33.528 21.1917 34.8051 19.6236 34.8017 19.5893C34.7975 19.5455 34.8119 19.533 34.3311 19.9966C34.0566 20.2613 32.9278 21.5998 32.4726 22.2003C32.2964 22.4328 32.2656 22.4651 32.2313 22.4534C32.165 22.4307 32.1803 22.4 32.3869 22.1418C32.4967 22.0045 32.627 21.8406 32.6763 21.7774C32.7257 21.7143 32.8549 21.559 32.9635 21.4322C33.072 21.3054 33.2346 21.1139 33.3247 21.0065C33.4148 20.8991 33.5237 20.773 33.5667 20.7263C33.674 20.6097 33.6403 20.5991 33.5053 20.7069C33.444 20.7558 33.3775 20.799 33.3574 20.8029C33.3373 20.8068 33.2723 20.8689 33.2129 20.9408C33.1536 21.0128 33.0734 21.0926 33.0348 21.1183C32.8197 21.2613 32.1921 22.0258 32.1164 22.237C32.0844 22.3265 32.0352 22.3388 31.9856 22.2698C31.963 22.2386 31.9395 22.2506 31.8241 22.3526C31.7498 22.4182 31.6452 22.5066 31.5918 22.549C31.5383 22.5913 31.4679 22.6536 31.4353 22.6872C31.3253 22.8009 30.9834 23.0848 30.9519 23.0887C30.9346 23.0909 30.9014 23.1156 30.8781 23.1437C30.8548 23.1718 30.808 23.2103 30.7742 23.2293C30.6517 23.2981 29.9644 24.1589 29.841 24.3982C29.8116 24.4552 29.7677 24.5145 29.7434 24.5301C29.6958 24.5604 29.6523 24.6456 29.6748 24.6643C29.6824 24.6705 29.7876 24.5769 29.9087 24.4562C30.0297 24.3355 30.1532 24.2167 30.1831 24.1923C30.213 24.1679 30.4757 23.8678 30.7669 23.5255C31.1743 23.0467 31.3559 22.8486 31.5543 22.6667C31.8179 22.425 31.937 22.3471 31.7927 22.5108C31.7227 22.5902 31.4369 22.886 31.3952 22.9221C31.1455 23.1388 30.4837 23.9288 30.6533 23.8078C30.7415 23.7449 30.8229 23.7992 30.7434 23.8679C30.7038 23.9021 30.6521 23.9531 30.6286 23.9813C30.6009 24.0142 30.5757 24.0241 30.5574 24.009C30.5403 23.9948 30.516 24.0025 30.4956 24.0286C30.4648 24.0683 30.4656 24.0698 30.5063 24.0475C30.5381 24.0301 30.5492 24.0331 30.5458 24.0581C30.5432 24.0773 30.5234 24.1025 30.5018 24.1141C30.4394 24.1476 30.1349 24.4983 30.181 24.4835C30.2028 24.4765 30.2352 24.4536 30.2529 24.4326C30.2707 24.4116 30.3111 24.3884 30.3429 24.3811C30.4208 24.3632 30.3904 24.4009 30.1803 24.583C30.0946 24.6573 30.0102 24.7345 29.9926 24.7547C29.6512 25.1472 29.1366 25.7823 29.0971 25.8601C29.0688 25.9157 29.0026 26.0166 28.9501 26.0844C28.8976 26.1521 28.8388 26.2494 28.8194 26.3005C28.8 26.3517 28.7506 26.434 28.7096 26.4834C28.6686 26.5328 28.6251 26.6024 28.613 26.6382C28.6009 26.674 28.5321 26.7917 28.4601 26.8998C28.312 27.1222 28.2615 27.216 28.3025 27.1924C28.3179 27.1835 28.3416 27.1855 28.3552 27.1968ZM28.2035 26.5702C28.2371 26.5003 28.2842 26.4098 28.3082 26.369C28.3322 26.3282 28.3583 26.2718 28.3661 26.2436C28.3799 26.1943 28.713 25.5719 28.7577 25.5119C28.7792 25.4831 28.8624 25.3418 28.9949 25.1093C29.1916 24.7641 29.2809 24.636 29.6148 24.2201C30.1814 23.5144 30.2173 23.4729 30.4995 23.1979C30.6454 23.0556 30.7716 22.9369 30.7799 22.9339C30.7882 22.931 30.8426 22.8829 30.9008 22.8271C30.959 22.7713 31.0466 22.695 31.0955 22.6575C31.1961 22.5804 31.2316 22.5511 31.6731 22.1811C31.9544 21.9454 32.0035 21.8955 32.1006 21.7473C32.161 21.6552 32.2449 21.5446 32.287 21.5016C32.3292 21.4585 32.4746 21.3024 32.6102 21.1547C32.7457 21.007 32.8695 20.8826 32.8852 20.8783C32.901 20.874 32.9674 20.8102 33.0328 20.7366C33.0983 20.663 33.175 20.5898 33.2033 20.5739C33.2317 20.558 33.2542 20.5376 33.2533 20.5286C33.2517 20.5125 33.5085 20.3048 33.5753 20.2682C33.5942 20.2579 33.62 20.2333 33.6326 20.2136C33.6452 20.1939 33.7081 20.1397 33.7725 20.0931C33.8368 20.0466 33.9369 19.9627 33.995 19.9068C34.166 19.742 34.2422 19.673 34.2595 19.6672C34.2685 19.6642 34.3263 19.6125 34.388 19.5523C34.4496 19.4921 34.5076 19.4401 34.5168 19.4368C34.526 19.4334 34.597 19.3646 34.6746 19.2838C34.7522 19.203 34.8746 19.0794 34.9467 19.0091C35.2097 18.7525 35.2682 18.6544 35.1797 18.6182C35.1337 18.5994 35.1218 18.6094 35.0036 18.7667C34.8391 18.9855 34.2336 19.5747 34.1306 19.6161C34.1021 19.6275 34.0797 19.6455 34.0807 19.6559C34.0827 19.6759 33.8758 19.8662 33.7255 19.9827C33.6768 20.0204 33.5513 20.1291 33.4466 20.2243C33.3418 20.3195 33.2386 20.4113 33.2173 20.4283C33.1675 20.468 33.032 20.5848 32.9588 20.6512C32.6622 20.9204 32.1006 21.5672 32.0371 21.7127C31.9778 21.8487 31.9115 21.9097 31.8587 21.8772C31.8236 21.8555 31.7946 21.8621 31.7449 21.9032C31.7082 21.9334 31.6471 21.9779 31.6091 22.0021C31.5712 22.0263 31.4947 22.1048 31.4392 22.1765C31.3498 22.2921 31.1639 22.4548 30.8227 22.7163C30.7733 22.7542 30.6302 22.8909 30.5047 23.0202C30.3792 23.1494 30.2083 23.3192 30.1249 23.3975C29.7913 23.7109 28.9994 24.701 29.0084 24.7936C29.0097 24.8067 28.9893 24.8434 28.963 24.8751C28.9367 24.9068 28.8986 24.9686 28.8783 25.0125C28.8579 25.0563 28.7968 25.1549 28.7426 25.2317C28.6883 25.3085 28.6262 25.4202 28.6045 25.4799C28.5828 25.5396 28.5351 25.6488 28.4985 25.7225C28.462 25.7962 28.3878 25.9547 28.3338 26.0747C28.2798 26.1947 28.2224 26.3174 28.2063 26.3474C28.1902 26.3775 28.1678 26.4441 28.1566 26.4955C28.1454 26.5469 28.1216 26.6187 28.1037 26.655C28.0808 26.7012 28.0818 26.7174 28.1068 26.7091C28.1265 26.7025 28.1699 26.6402 28.2035 26.5702ZM22.4776 21.7253C22.4844 21.6835 22.4782 21.6847 22.4373 21.733C22.4107 21.7644 22.3899 21.8018 22.3912 21.8161C22.3949 21.8574 22.4687 21.7799 22.4776 21.7253ZM11.4851 12.4347C11.6922 12.3592 11.9452 12.276 12.0221 12.2582C12.0726 12.2465 12.1216 12.2278 12.1308 12.2167C12.1401 12.2056 12.1678 12.1944 12.1923 12.1919C12.2169 12.1894 12.3037 12.1646 12.3851 12.1368C12.6688 12.0399 12.7955 12.0043 12.8111 12.0173C12.8197 12.0244 12.8363 12.0188 12.8479 12.0048C12.8596 11.9908 12.9038 11.972 12.9462 11.9631C13.0646 11.9383 13.0756 11.8983 12.9619 11.9059C12.9063 11.9096 12.8511 11.9243 12.8393 11.9386C12.8274 11.9528 12.7714 11.9686 12.7147 11.9736C12.658 11.9786 12.6047 11.991 12.5963 12.0012C12.5879 12.0113 12.5369 12.0296 12.483 12.0418C12.4292 12.0539 12.3783 12.072 12.3701 12.0819C12.3618 12.0919 12.3085 12.103 12.2515 12.1067C12.1946 12.1104 12.0893 12.1413 12.0176 12.1755C11.9459 12.2096 11.8324 12.2528 11.7653 12.2714C11.6983 12.29 11.6376 12.3123 11.6305 12.3209C11.6233 12.3295 11.5697 12.3501 11.5113 12.3667C11.453 12.3833 11.4034 12.4102 11.4011 12.4266C11.3966 12.4599 11.412 12.4613 11.4851 12.4347ZM15.8777 15.9846C15.8912 15.9683 15.9989 15.9134 16.1171 15.8627C16.5935 15.658 17.3907 14.749 17.5398 14.2403C17.5576 14.1797 17.5637 14.1634 17.5828 14.1261C17.5874 14.117 17.5242 14.139 17.4422 14.175C17.3602 14.2111 17.2751 14.2468 17.253 14.2545C17.1257 14.2988 16.9899 14.441 16.9386 14.5837C16.8771 14.7549 16.7722 14.9732 16.7133 15.0526C16.6894 15.0848 16.6389 15.1564 16.6011 15.2118C16.4518 15.4304 16.2088 15.7194 16.1715 15.7227C16.1439 15.7252 16.1618 15.6911 16.2373 15.5976C16.5773 15.1762 16.9384 14.5612 16.8762 14.5096C16.8698 14.5042 16.8044 14.5346 16.731 14.5772C16.6576 14.6198 16.5852 14.6528 16.5702 14.6507C16.5241 14.644 16.4894 14.7064 16.431 14.9006C16.3329 15.2271 16.1577 15.5303 15.8533 15.9002C15.7482 16.0278 15.7429 16.0395 15.7953 16.0275C15.8271 16.0201 15.8642 16.0008 15.8777 15.9846ZM16.6898 16.2714C16.6962 16.2638 16.7129 16.2669 16.7268 16.2785C16.7621 16.3078 16.8923 16.216 17.0762 16.0323C17.1622 15.9464 17.244 15.8754 17.258 15.8746C17.2993 15.8722 16.9425 16.2462 16.8706 16.2806C16.558 16.4305 17.1711 16.3284 17.5979 16.1596C17.6659 16.1327 17.7854 16.0856 17.8634 16.055C17.9415 16.0243 18.071 15.9707 18.1513 15.9358C18.236 15.899 18.3162 15.8812 18.3421 15.8934C18.3934 15.9175 18.4249 15.8849 18.8093 15.4104C18.9402 15.2487 19.0394 15.141 19.0442 15.1551C19.0555 15.1884 18.8904 15.4292 18.7041 15.6508C18.5475 15.8371 18.5183 15.9171 18.6312 15.8505C18.6655 15.8302 18.7141 15.806 18.7393 15.7968C18.7645 15.7876 18.7963 15.7665 18.81 15.75C18.8237 15.7335 18.8666 15.7134 18.9054 15.7052C18.9673 15.6922 19.0011 15.6587 19.1849 15.4276C19.3913 15.1678 19.4591 15.0647 19.6588 14.7064C19.8163 14.4238 19.8797 14.3328 19.9153 14.3379C19.9327 14.3404 19.942 14.3499 19.936 14.3589C19.8905 14.4265 19.8537 14.4916 19.817 14.5695C19.7935 14.6194 19.7479 14.7023 19.7158 14.7537C19.6837 14.8051 19.6276 14.9076 19.5912 14.9815C19.5548 15.0554 19.4845 15.1674 19.4349 15.2303C19.3853 15.2933 19.3333 15.3671 19.3192 15.3945L19.2937 15.4442L19.3684 15.4285C19.5416 15.3921 19.7482 15.1879 20.1409 14.665C20.3382 14.4023 20.4113 14.3757 20.2329 14.6316C20.0267 14.9273 19.921 15.071 19.8551 15.1454C19.8046 15.2023 19.7938 15.2286 19.8142 15.2456C19.8294 15.2582 19.8443 15.2932 19.8472 15.3234C19.8529 15.3823 19.9258 15.4029 19.9644 15.3565C19.9745 15.3443 20.028 15.3139 20.0833 15.2889C20.1385 15.264 20.2231 15.2133 20.2712 15.1763C20.3194 15.1393 20.3775 15.0985 20.4004 15.0858C20.4293 15.0697 20.4319 15.061 20.4089 15.0577C20.3684 15.0519 20.3456 15.0852 20.6554 14.6979C21.1128 14.1262 21.4781 13.5023 21.286 13.621C21.1733 13.6906 21.3225 13.3789 21.5807 13.0053C21.8479 12.6188 22.1107 12.0965 22.1518 11.8705C22.1573 11.8403 22.1775 11.7479 22.1967 11.6652C22.2469 11.449 22.1856 11.4 22.0175 11.5221C21.9897 11.5423 21.9472 11.5624 21.9231 11.5667C21.8289 11.5837 21.6853 11.7165 21.7137 11.7605C21.7843 11.87 21.6129 12.4744 21.4099 12.832C21.3831 12.8791 21.3605 12.9313 21.3595 12.9479C21.3579 12.9774 21.292 13.0986 21.2 13.2413C21.1745 13.2809 21.1406 13.345 21.1246 13.3838C21.0492 13.5666 20.7175 14.0399 20.6145 14.1118C20.5473 14.1586 20.5695 14.1196 20.8832 13.6408C21.0924 13.3214 21.2738 12.9901 21.37 12.7515C21.3884 12.706 21.4463 12.5624 21.4986 12.4324C21.6098 12.1563 21.6561 11.9716 21.6443 11.8505L21.6359 11.7639L21.5515 11.7909C21.4796 11.8139 21.4659 11.8267 21.4593 11.8769C21.4501 11.9468 21.3881 11.9762 21.3007 11.9521C21.2698 11.9436 21.2338 11.9495 21.2207 11.9653C21.2075 11.9812 21.1719 12.0014 21.1414 12.0104C21.111 12.0193 21.0437 12.0554 20.992 12.0905C20.9403 12.1256 20.8843 12.1573 20.8677 12.1608C20.7646 12.1828 20.7156 12.2629 20.7319 12.3831C20.7465 12.4915 20.7003 12.7307 20.5972 13.0801C20.5797 13.1394 20.569 13.2068 20.5734 13.2298C20.5778 13.2529 20.5628 13.2942 20.5399 13.3217C20.5171 13.3492 20.5 13.3881 20.502 13.4081C20.5039 13.4281 20.4581 13.51 20.4001 13.5902C20.246 13.8032 20.1618 13.9276 20.1178 14.0071C20.0963 14.0459 20.0614 14.0808 20.0403 14.0848C20.018 14.089 19.911 14.2021 19.7857 14.3542C19.5805 14.603 19.2474 14.9216 19.1323 14.979C19.0922 14.999 18.8038 15.2415 18.6509 15.3838C18.6263 15.4067 18.5684 15.4604 18.5222 15.503C18.3958 15.6198 18.3138 15.6095 18.433 15.4918C18.5149 15.4109 18.5192 15.4006 18.4833 15.3708C18.4404 15.3352 18.4412 15.3342 18.6432 15.1966C18.7653 15.1133 19.1227 14.6257 19.3155 14.2793C19.3684 14.1844 19.4502 14.0422 19.4974 13.9634C19.7123 13.6046 20.0103 12.9483 20.0581 12.7287C20.074 12.6559 20.1263 12.6328 20.1212 12.7008C20.1064 12.8992 19.8677 13.4807 19.6457 13.8594C19.6046 13.9294 19.5213 14.0732 19.4606 14.1789C19.3999 14.2847 19.2833 14.478 19.2015 14.6086C18.996 14.9366 19.0226 14.9489 19.325 14.6654C19.8427 14.1802 20.3287 13.5173 20.396 13.2046C20.4166 13.1089 20.458 12.9587 20.488 12.8709C20.565 12.6456 20.5864 12.5401 20.5779 12.4297L20.5704 12.3337L20.3866 12.4539C20.2855 12.52 20.1877 12.5689 20.1693 12.5626C20.1508 12.5563 20.1069 12.5749 20.0717 12.604C20.0366 12.633 19.9971 12.6526 19.9839 12.6474C19.9708 12.6423 19.9252 12.671 19.8826 12.7112C19.84 12.7514 19.7759 12.7931 19.7401 12.804C19.5481 12.862 19.4843 12.9357 19.4264 13.1661C19.3452 13.4894 19.2258 13.7815 18.9818 14.2545C18.8551 14.5 18.837 14.5297 18.7098 14.6989C18.6415 14.7899 18.5777 14.8574 18.5621 14.8551C18.5458 14.8528 18.5342 14.8656 18.5335 14.8868C18.532 14.9307 18.3899 15.0724 18.3667 15.0531C18.3574 15.0454 18.4032 14.9734 18.4684 14.8931C18.6233 14.7023 18.7041 14.5841 18.8225 14.3747C18.9276 14.1887 18.9413 14.1627 19.0098 14.0175C19.0349 13.9646 19.0762 13.8782 19.1017 13.8256C19.1272 13.773 19.166 13.681 19.1879 13.6212C19.4147 13.002 19.4284 12.9017 19.2685 13.0338C19.1603 13.1231 18.9805 13.2373 18.8113 13.324C18.721 13.3703 18.634 13.4187 18.6179 13.4316C18.4902 13.5339 18.2537 13.684 18.1483 13.7296L18.0208 13.7848L18.0155 13.9287C18.01 14.0786 17.9727 14.2843 17.9539 14.2687C17.948 14.2637 17.937 14.2936 17.9295 14.3351C17.915 14.4159 17.8165 14.6293 17.7058 14.8198C17.6684 14.8841 17.6251 14.9618 17.6097 14.9924C17.5579 15.095 17.2442 15.5 17.1841 15.5419L17.1246 15.5834L17.1641 15.5061C17.186 15.4632 17.2189 15.4259 17.2379 15.4225C17.2567 15.419 17.2712 15.4061 17.27 15.3937C17.2674 15.3668 17.3026 15.3123 17.4608 15.0981C17.5261 15.0095 17.5811 14.9263 17.5829 14.9132C17.5847 14.9001 17.6213 14.8295 17.6644 14.7564C17.796 14.5328 17.9248 14.1792 17.9343 14.0157L17.943 13.8652L17.8841 13.9121C17.8518 13.9378 17.8032 13.9673 17.7762 13.9776C17.737 13.9925 17.7281 14.0135 17.7321 14.0817C17.7375 14.1725 17.718 14.2288 17.6083 14.4391C17.5704 14.5117 17.5344 14.5923 17.5284 14.6182C17.5224 14.6441 17.3818 14.8379 17.2158 15.049L16.914 15.4326L16.9311 15.5253C16.9464 15.6081 16.9313 15.7578 16.9054 15.7801C16.9 15.7847 16.8658 15.8448 16.8295 15.9135C16.7931 15.9823 16.7039 16.1022 16.6313 16.1799L16.4992 16.3213L16.5886 16.3033C16.6378 16.2934 16.6833 16.2791 16.6898 16.2714ZM15.6821 14.0069C16.4782 13.9481 16.8551 13.974 17.0582 14.1015C17.1693 14.1713 17.7165 13.9214 17.8801 13.7261C17.9217 13.6765 17.8989 13.6199 17.8445 13.6379C17.8312 13.6423 17.7921 13.6323 17.7577 13.6156C17.7232 13.5989 17.67 13.5862 17.6394 13.5873C17.6088 13.5884 17.5184 13.5592 17.4386 13.5224C17.2551 13.4379 17.0658 13.3902 16.9486 13.3988C16.8985 13.4025 16.8095 13.4028 16.7509 13.3995C16.5794 13.3898 16.2523 13.4257 16.1704 13.4632C16.0933 13.4985 16.0612 13.5103 15.888 13.5668C15.8339 13.5845 15.7853 13.6043 15.7799 13.6108C15.7745 13.6173 15.9573 13.6077 16.1861 13.5894C16.4149 13.5712 16.6076 13.5608 16.6142 13.5663C16.6208 13.5718 16.669 13.5749 16.7213 13.5732C17.099 13.5609 17.6644 13.6936 17.6846 13.7993C17.6912 13.8338 17.6696 13.8314 17.5775 13.7875C17.514 13.7573 17.3636 13.7215 17.2432 13.7079C17.1228 13.6943 16.986 13.6734 16.9392 13.6614C16.8512 13.6388 16.779 13.6397 16.2078 13.6705C16.0214 13.6806 15.8588 13.6852 15.8465 13.6807C15.8341 13.6763 15.8153 13.6831 15.8047 13.6959C15.7856 13.7189 15.5249 13.7344 15.5004 13.7141C15.4935 13.7084 15.4625 13.7241 15.4315 13.7491C15.3771 13.793 15.2292 13.8195 15.226 13.7859C15.2229 13.7548 15.8268 13.4685 16.0016 13.4182C16.0675 13.3993 16.1421 13.3706 16.1673 13.3545C16.1926 13.3383 16.2811 13.3182 16.364 13.3097C16.4469 13.3012 16.5554 13.2871 16.6052 13.2783C16.7623 13.2507 17.2141 13.2762 17.2617 13.3153C17.2756 13.3268 17.3225 13.3373 17.3659 13.3387C17.4093 13.34 17.4567 13.3509 17.4712 13.3629C17.5727 13.4473 18.2464 13.567 18.2674 13.5044C18.2732 13.4873 18.3371 13.439 18.4094 13.397C18.4818 13.355 18.5883 13.2889 18.6461 13.2501C18.7851 13.1568 18.9749 13.0263 18.9994 13.0071C19.0101 12.9987 19.0556 12.9769 19.1005 12.9586C19.1454 12.9403 19.1901 12.9157 19.1999 12.9039C19.2097 12.8921 19.2519 12.8661 19.2936 12.8461C19.5246 12.7355 19.544 12.7206 19.5227 12.6688C19.4911 12.592 19.3847 12.5527 19.1084 12.5157C19.0848 12.5126 19.0423 12.5034 19.014 12.4953C18.9857 12.4872 18.9211 12.4827 18.8705 12.4854C18.8198 12.4881 18.7192 12.4799 18.6468 12.4672C18.5745 12.4545 18.4859 12.4451 18.4499 12.4462C18.414 12.4474 18.3341 12.4457 18.2725 12.4425C18.2109 12.4393 18.0839 12.4334 17.9903 12.4294C17.8966 12.4254 17.8128 12.4162 17.8039 12.4088C17.7951 12.4014 17.7415 12.4006 17.6848 12.4068C17.6282 12.4131 17.5353 12.4096 17.4785 12.399C17.4216 12.3884 17.3698 12.3862 17.3633 12.394C17.3568 12.4018 17.2821 12.4117 17.1973 12.416C17.1125 12.4203 16.9794 12.4312 16.9015 12.4402C16.7528 12.4575 16.6667 12.4303 16.756 12.3944C16.8077 12.3736 17.3273 12.3215 17.4541 12.3243C17.4964 12.3253 17.6016 12.3274 17.6878 12.3291C17.9672 12.3345 18.199 12.3448 18.3413 12.358C18.6203 12.3841 18.7879 12.4056 18.8018 12.4172C18.8097 12.4237 18.8424 12.4246 18.8746 12.4193C19.0833 12.3845 19.5422 12.517 19.5866 12.6249C19.6106 12.6834 19.837 12.5969 20.1963 12.392C20.2706 12.3496 20.3674 12.2951 20.4113 12.2708C20.5193 12.211 20.6258 12.1225 20.5979 12.1157C20.5224 12.0973 20.4312 12.0685 20.3242 12.0292C20.2198 11.9907 19.5287 11.8227 19.3299 11.7874C19.2937 11.781 19.1808 11.7716 19.079 11.7667C18.9771 11.7617 18.8634 11.7512 18.8263 11.7434C18.7892 11.7356 18.7421 11.7323 18.7215 11.7359C18.7009 11.7396 18.5857 11.7424 18.4653 11.7422C18.1522 11.7415 17.9277 11.775 17.7648 11.8465C17.6179 11.911 17.5301 11.9006 17.6173 11.8289C17.6777 11.7794 17.6405 11.7743 17.5126 11.8147C17.4571 11.8322 17.3755 11.8519 17.3312 11.8585C17.2869 11.8651 17.2098 11.8863 17.1598 11.9055C16.9796 11.9748 16.7685 12.0136 16.7651 11.978C16.7625 11.9515 16.8952 11.904 17.1821 11.8287C17.3177 11.7931 17.4463 11.7542 17.4677 11.7422C17.4892 11.7303 17.5684 11.7256 17.6437 11.7319C17.719 11.7382 17.8174 11.7264 17.8624 11.7057C17.9074 11.6849 18.0402 11.6662 18.1574 11.6641C18.2747 11.6619 18.4307 11.6568 18.5041 11.6528C18.8226 11.6351 19.2296 11.6759 19.6061 11.7631C19.7897 11.8056 19.9551 11.8407 19.9738 11.8411C19.9925 11.8416 20.0506 11.8578 20.103 11.8773C20.1553 11.8967 20.256 11.9292 20.3266 11.9496C20.5913 12.0258 20.6236 12.037 20.6561 12.064C20.6877 12.0902 20.966 11.9556 20.9621 11.916C20.9594 11.8874 20.8657 11.8623 20.7501 11.8593C20.6863 11.8577 20.6231 11.8473 20.6098 11.8362C20.5965 11.8252 20.5417 11.82 20.488 11.8247C20.4071 11.8319 19.9437 11.7247 19.9005 11.6889C19.8935 11.6831 19.8399 11.6656 19.7816 11.6501C19.7233 11.6347 19.6343 11.6107 19.5839 11.5968C19.5335 11.5829 19.4074 11.5795 19.3037 11.5892C19.2 11.599 19.0463 11.6 18.9623 11.5914C18.8783 11.5829 18.7929 11.586 18.7726 11.5983C18.7321 11.6228 18.4959 11.6087 18.4933 11.5816C18.4876 11.5231 19.2092 11.4383 19.3934 11.4758C19.4185 11.4809 19.4864 11.4843 19.5441 11.4834C19.6019 11.4825 19.8312 11.5255 20.0537 11.5789C20.4235 11.6677 20.5522 11.6863 20.8289 11.6911C20.8814 11.692 20.9926 11.7105 21.076 11.7322C21.1618 11.7545 21.2486 11.7601 21.2755 11.7451C21.3017 11.7306 21.3825 11.6899 21.4551 11.6547C21.5276 11.6195 21.6372 11.5615 21.6986 11.5256C21.7599 11.4898 21.8231 11.4571 21.8389 11.4529C21.8547 11.4487 21.8906 11.4304 21.9185 11.4122C21.9464 11.394 22.0596 11.3374 22.1701 11.2864C22.2805 11.2354 22.3808 11.1821 22.3929 11.168C22.405 11.154 22.5375 11.089 22.6873 11.0237C22.8371 10.9584 22.9591 10.8987 22.9584 10.8911C22.9569 10.8755 22.6454 10.6833 22.5888 10.663C22.5685 10.6557 22.5372 10.6417 22.5191 10.6319C22.384 10.5586 21.9539 10.4155 21.864 10.4139C21.8336 10.4134 21.792 10.4011 21.7717 10.3865C21.7293 10.3563 21.3575 10.2943 21.2911 10.3064C21.2668 10.3109 21.2368 10.3061 21.2244 10.2958C21.212 10.2855 21.151 10.279 21.0889 10.2815C20.931 10.2878 20.5125 10.2373 20.5031 10.2109C20.4859 10.1622 21.2536 10.1937 21.5771 10.2549C21.7691 10.2912 22.2766 10.4439 22.3171 10.4775C22.3321 10.4899 22.373 10.5037 22.4081 10.5081C22.4877 10.5181 22.7432 10.6366 22.8497 10.7129C22.8936 10.7444 22.9308 10.7685 22.9325 10.7666C22.9341 10.7646 22.9624 10.7805 22.9954 10.802C23.0685 10.8498 23.1184 10.8479 23.1355 10.7968C23.1454 10.7673 23.1346 10.7536 23.0887 10.7378C23.0559 10.7264 22.9629 10.6697 22.882 10.6116C22.8011 10.5536 22.6772 10.4808 22.6065 10.45C22.5358 10.4191 22.4257 10.3643 22.3619 10.3282C22.2981 10.2921 22.211 10.2548 22.1685 10.2453C22.1259 10.2358 22.084 10.2235 22.0753 10.218C21.9844 10.1606 21.6387 10.0906 21.4656 10.0947C21.4092 10.096 21.3278 10.0944 21.2848 10.091C21.2418 10.0877 21.149 10.0884 21.0787 10.0925C21.0083 10.0967 20.9444 10.0949 20.9367 10.0885C20.929 10.0821 20.8628 10.0909 20.7895 10.1081C20.7163 10.1253 20.6125 10.135 20.559 10.1297C20.5055 10.1243 20.4537 10.1295 20.4439 10.1412C20.434 10.1529 20.4093 10.1567 20.3888 10.1497C20.3684 10.1427 20.3416 10.1492 20.3292 10.164C20.3169 10.1789 20.293 10.186 20.2763 10.1799C20.2595 10.1737 20.2466 10.1815 20.2477 10.1972C20.2487 10.213 20.2623 10.2224 20.278 10.2182C20.305 10.211 20.4379 10.2421 20.4607 10.2611C20.4665 10.2659 20.2142 10.2921 19.8999 10.3192C19.3654 10.3653 19.1429 10.4043 19.0966 10.46C19.086 10.4729 19.1998 10.4695 19.3495 10.4525C19.4993 10.4356 19.706 10.4239 19.8089 10.4265C19.9117 10.4292 20.0044 10.4268 20.0148 10.4213C20.0252 10.4158 20.0431 10.419 20.0545 10.4285C20.0659 10.438 20.106 10.4443 20.1437 10.4425C20.1813 10.4407 20.2513 10.4455 20.2991 10.4533C20.347 10.461 20.4241 10.4715 20.4706 10.4767C20.8392 10.518 21.0641 10.5588 21.5745 10.6769L21.9483 10.7634L22.1803 10.944C22.3865 11.1045 22.4039 11.1224 22.3371 11.1048C22.2957 11.0939 22.2246 11.0502 22.179 11.0077C22.0744 10.9102 21.8033 10.7978 21.6078 10.7709C21.5345 10.7608 21.2421 10.6891 21.2286 10.6779C21.2216 10.6721 21.1598 10.6633 21.0913 10.6585C21.0228 10.6537 20.956 10.6408 20.9429 10.6299C20.9298 10.619 20.9106 10.6146 20.9002 10.62C20.8899 10.6254 20.807 10.616 20.716 10.599C20.6251 10.582 20.5083 10.5658 20.4565 10.563C20.4046 10.5602 20.3564 10.5531 20.3493 10.5472C20.3422 10.5413 20.2693 10.5339 20.1872 10.5309C20.1052 10.5278 20.0088 10.5223 19.973 10.5186C19.9372 10.5149 19.8464 10.5141 19.7711 10.5168C19.6959 10.5195 19.5943 10.5182 19.5453 10.5139C19.4964 10.5095 19.4118 10.5165 19.3574 10.5293C19.303 10.5422 19.2325 10.5475 19.2008 10.5411C19.1692 10.5348 19.0889 10.547 19.0224 10.5683C18.9088 10.6047 18.8267 10.5985 18.8978 10.5589C18.9256 10.5434 18.9187 10.5372 18.8494 10.5159C18.7946 10.499 18.7477 10.505 18.7038 10.5346C18.6682 10.5586 18.6318 10.5723 18.623 10.5649C18.6141 10.5575 18.5972 10.5631 18.5855 10.5773C18.5737 10.5914 18.5023 10.6325 18.4269 10.6685C18.2369 10.7591 18.2584 10.7838 18.5044 10.7579C18.6201 10.7457 18.7213 10.7412 18.7294 10.7479C18.7375 10.7547 18.774 10.7446 18.8104 10.7255C18.885 10.6865 19.2114 10.6529 19.2144 10.6839C19.2154 10.6949 19.1687 10.712 19.1105 10.7219C18.8009 10.7745 18.7957 10.8256 19.1018 10.8076C19.2172 10.8009 19.4115 10.7955 19.5337 10.7956C19.656 10.7957 19.7847 10.7949 19.8199 10.7937C19.855 10.7925 19.8938 10.7999 19.9062 10.8102C19.9185 10.8204 19.9495 10.8249 19.9751 10.8203C20.0007 10.8156 20.0865 10.8221 20.1658 10.8348C20.2452 10.8475 20.3646 10.8612 20.4312 10.8653C20.4979 10.8694 20.6005 10.8852 20.6594 10.9005C20.7183 10.9157 20.7867 10.9245 20.8114 10.92C20.8361 10.9155 20.8924 10.9238 20.9366 10.9384C20.9807 10.9531 21.0461 10.9643 21.0819 10.9634C21.1176 10.9625 21.2086 10.9824 21.2839 11.0076C21.3593 11.0329 21.4553 11.0638 21.4973 11.0765C21.6552 11.124 21.6995 11.1433 21.7693 11.1949C21.846 11.2517 21.8489 11.3294 21.7743 11.3335C21.7465 11.335 21.7387 11.3271 21.7465 11.3051C21.7606 11.265 21.7008 11.2172 21.6004 11.1882C21.5558 11.1754 21.4731 11.1487 21.4165 11.1289C21.3598 11.1091 21.1851 11.0721 21.0282 11.0466C20.8713 11.0211 20.7389 10.9969 20.734 10.9928C20.7291 10.9887 20.6701 10.9794 20.6029 10.9721C20.5358 10.9648 20.4493 10.9495 20.4107 10.938C20.3721 10.9265 20.3334 10.9257 20.3247 10.9361C20.316 10.9466 20.3013 10.949 20.2921 10.9414C20.2767 10.9285 19.9275 10.8824 19.8873 10.8879C19.8774 10.8892 19.8207 10.8875 19.7612 10.8841C19.6305 10.8766 19.5178 10.8759 19.3401 10.8814L19.2061 10.8856L19.3398 11.0074C19.4771 11.1325 19.5574 11.1577 19.7706 11.1427C19.978 11.1281 20.7334 11.263 21.0141 11.3647C21.1669 11.4201 21.2561 11.5011 21.2166 11.5487C21.1921 11.5783 21.1464 11.5615 21.1289 11.5166C21.1139 11.4781 21.0113 11.4245 20.9311 11.4133C20.9154 11.4111 20.8702 11.3923 20.8306 11.3715C20.7909 11.3507 20.7522 11.3413 20.7445 11.3505C20.7369 11.3598 20.705 11.355 20.6737 11.34C20.6425 11.3249 20.6105 11.3203 20.6026 11.3298C20.5947 11.3393 20.5689 11.3402 20.5451 11.3319C20.4652 11.3039 20.0907 11.2563 20.0773 11.2724C20.07 11.2812 20.0528 11.279 20.0391 11.2676C20.0171 11.2493 19.8535 11.2366 19.5554 11.23C19.1945 11.2221 18.9636 11.2151 18.926 11.2109C18.9018 11.2082 18.8192 11.2136 18.7423 11.2228C18.6654 11.2321 18.5821 11.2313 18.5572 11.2211C18.5323 11.2109 18.5026 11.2137 18.4913 11.2274C18.4799 11.241 18.4192 11.2534 18.3563 11.2548C18.2931 11.2563 18.2161 11.2784 18.184 11.3042C18.1522 11.3299 18.0486 11.3612 17.9538 11.3737C17.6366 11.4154 17.5567 11.43 17.4836 11.4591C17.4377 11.4775 17.404 11.4759 17.3921 11.4547C17.3631 11.4034 17.2514 11.478 17.0785 11.6644C17.0695 11.6743 17.0447 11.714 17.0235 11.7529C16.9974 11.8006 16.9627 11.8302 16.9163 11.8442C16.8786 11.8556 16.8349 11.8804 16.8193 11.8992C16.8036 11.9181 16.7771 11.9355 16.7602 11.9381C16.7434 11.9406 16.6615 11.9854 16.5782 12.0377C16.4949 12.0901 16.4052 12.1362 16.3788 12.1403C16.2809 12.1556 16.2013 12.217 16.1677 12.3033L16.1358 12.3851L16.2181 12.3805C16.2633 12.3779 16.335 12.3598 16.3775 12.3403C16.4658 12.2996 16.7168 12.2529 16.7191 12.2766C16.721 12.2968 16.3562 12.4089 16.1745 12.4439C16.0638 12.4653 16.0152 12.4904 15.9337 12.5684C15.8141 12.6827 15.6895 12.7773 15.5212 12.8816C15.3692 12.9757 15.3565 12.9914 15.3623 13.0786C15.3692 13.1849 15.279 13.33 15.1341 13.4455C14.9511 13.5913 14.8103 13.7616 14.7417 13.9201C14.6481 14.1362 14.6525 14.1409 14.9026 14.0917C15.0243 14.0678 15.375 14.0296 15.6821 14.0069ZM30.7421 26.7258C30.7674 26.6992 30.8408 26.6217 30.9052 26.5537C31.1949 26.2476 32.2123 25.0055 32.2153 24.9544C32.2181 24.9053 32.0501 25.0692 32.0201 25.1448C32.0149 25.1578 31.9565 25.2371 31.8904 25.321C31.6898 25.5754 31.5132 25.7957 31.5031 25.8039C31.4979 25.8083 31.3776 25.9427 31.2359 26.1027C30.9237 26.4552 30.7717 26.6216 30.7442 26.6409C30.7329 26.6488 30.7089 26.675 30.691 26.6992C30.6444 26.7617 30.6869 26.7839 30.7421 26.7258ZM13.891 12.6752C13.9525 12.6247 13.9198 12.6005 13.8459 12.642C13.7707 12.6842 13.7687 12.6875 13.8099 12.7015C13.8289 12.708 13.8654 12.6962 13.891 12.6752ZM26.5958 22.6433C26.8098 22.41 26.9175 22.3067 27.0108 22.2457C27.0463 22.2225 27.1326 22.1593 27.2025 22.1052C27.2724 22.0512 27.3869 21.975 27.457 21.9359L27.5844 21.8649L27.6312 21.6862C27.7449 21.2525 27.7567 21.1843 27.7495 21.0054C27.7408 20.7936 27.7721 20.7523 27.8088 20.9269C27.8387 21.0686 27.8186 21.3204 27.7642 21.4845C27.7417 21.5525 27.7102 21.6522 27.6942 21.7061L27.6652 21.8041L27.7631 21.7647C27.8169 21.7431 27.9344 21.7113 28.0242 21.694C28.2587 21.649 28.5863 21.4924 28.6843 21.3786C28.7055 21.3541 28.8024 21.2865 28.8997 21.2285L29.0767 21.1231L29.141 20.9555C29.1763 20.8634 29.2166 20.7371 29.2305 20.6748C29.2444 20.6125 29.2653 20.5606 29.2768 20.5596C29.2946 20.5581 29.2674 20.6871 29.1896 20.9729C29.1669 21.0566 29.1927 21.0467 29.5201 20.8473C29.9355 20.5942 29.9524 20.5666 30.0671 19.9539C30.1085 19.7327 30.1567 19.5747 30.1775 19.5921C30.2043 19.6143 30.0541 20.3988 30.0225 20.4016C29.9702 20.4062 30.0091 20.5159 30.0757 20.5517C30.1431 20.5879 30.4355 20.4374 30.4696 20.349C30.4753 20.3344 30.5564 20.2656 30.6501 20.1962C30.7437 20.1267 30.8384 20.048 30.8605 20.0214C30.8826 19.9947 30.939 19.9513 30.9858 19.9247C31.0326 19.8982 31.1073 19.8428 31.1517 19.8016C31.1961 19.7603 31.2964 19.6677 31.3746 19.5958C31.4898 19.4896 31.5207 19.4497 31.538 19.3845C31.5498 19.3402 31.585 19.2259 31.6164 19.1305C31.6967 18.8858 31.8176 18.3669 31.798 18.3506C31.7758 18.3322 31.7561 18.3591 31.7603 18.4022C31.7622 18.4216 31.7092 18.5118 31.6426 18.6026C31.4089 18.9211 31.2356 19.1892 31.2357 19.232C31.2358 19.2557 31.2193 19.2997 31.1989 19.3296C31.1786 19.3596 31.1509 19.4104 31.1373 19.4425C31.1158 19.4935 31.1115 19.4948 31.1031 19.4528C31.0923 19.3979 30.9736 19.4809 30.9727 19.544C30.9719 19.5967 30.8706 19.7222 30.8256 19.7262C30.7323 19.7344 30.8014 19.5814 31.0399 19.2512C31.2583 18.949 31.3272 18.8386 31.3424 18.7669C31.3593 18.687 31.3788 18.6533 31.3896 18.6852C31.4027 18.7237 31.621 18.4104 31.6731 18.2784C31.7014 18.2065 31.7447 18.1004 31.7692 18.0427C31.8258 17.9093 31.9704 17.3351 31.973 17.2334C31.974 17.1911 31.9873 17.1029 32.0024 17.0374C32.0174 16.9718 32.0277 16.8809 32.0251 16.8354C32.0225 16.7899 32.0323 16.6953 32.0468 16.6252C32.0613 16.5551 32.071 16.4758 32.0684 16.4489C32.0658 16.422 32.0696 16.2933 32.0768 16.1628C32.084 16.0323 32.0767 15.8757 32.0606 15.8148L32.0312 15.7041L31.8996 15.85C31.7587 16.0064 31.7476 16.033 31.7588 16.1884C31.7688 16.3266 31.6876 17.1171 31.6356 17.3888C31.6221 17.4592 31.6052 17.5476 31.5981 17.5851C31.591 17.6225 31.5721 17.6691 31.5561 17.6885C31.5192 17.7332 31.5178 17.6105 31.5537 17.4791C31.581 17.3794 31.5835 17.3605 31.6115 17.0374C31.6233 16.902 31.6418 16.7805 31.6527 16.7673C31.6637 16.7541 31.6714 16.6821 31.67 16.6073C31.6671 16.4574 31.6664 16.3795 31.6667 16.239L31.667 16.1455L31.5573 16.2744C31.497 16.3453 31.3986 16.4512 31.3386 16.5098C31.265 16.5817 31.2361 16.6219 31.2499 16.6333C31.2915 16.6679 31.2964 16.896 31.2657 17.3689C31.2492 17.6229 31.1589 18.1588 31.0881 18.4236C31.0634 18.5158 31.0396 18.6239 31.0353 18.6637C31.031 18.7035 30.9994 18.8335 30.9652 18.9525C30.931 19.0716 30.9003 19.1881 30.8971 19.2114C30.8728 19.3842 30.7901 19.5958 30.7573 19.5687C30.738 19.5526 30.858 19.0341 30.9105 18.9071C30.9238 18.8747 30.9316 18.8385 30.9278 18.8265C30.924 18.8145 30.9565 18.6569 30.9999 18.4762C31.0434 18.2955 31.0854 18.1013 31.0933 18.0445C31.1012 17.9877 31.123 17.8425 31.1417 17.7219C31.1902 17.4097 31.2085 17.1246 31.1946 16.8962L31.1826 16.6985L31.0885 16.8043C30.9095 17.0056 30.7939 17.1065 30.7676 17.0847C30.7499 17.0699 30.7216 17.0905 30.6714 17.1546C30.6322 17.2045 30.5129 17.3361 30.4061 17.447C30.1237 17.7404 29.8864 18.0249 29.9086 18.0435C29.9278 18.0597 29.933 18.3991 29.9155 18.5034C29.8855 18.6829 29.8226 18.6137 29.8044 18.3812C29.7865 18.1515 29.7738 18.153 29.5553 18.4121C29.4648 18.5195 29.3722 18.6274 29.3496 18.652C29.327 18.6766 29.2615 18.7571 29.204 18.8308C29.1466 18.9046 28.9239 19.1669 28.7092 19.4138C28.2988 19.8857 28.2829 19.9044 28.1949 20.02C28.1646 20.0598 28.0809 20.1572 28.0089 20.2363C27.8874 20.3698 27.757 20.5497 27.6876 20.6793C27.6618 20.7273 27.6129 20.8001 27.4154 21.0843C27.3886 21.1228 27.3605 21.174 27.3529 21.198C27.3453 21.2221 27.3231 21.2507 27.3036 21.2616C27.284 21.2725 27.2606 21.3162 27.2514 21.3587C27.2336 21.4412 27.0584 21.6713 27.0308 21.6483C26.9929 21.6168 27.3924 20.9116 27.6872 20.4897C27.737 20.4183 27.79 20.3376 27.8048 20.3104C27.8197 20.2832 27.8763 20.2037 27.9306 20.1338C28.0441 19.9876 27.9805 19.9678 27.8069 20.0952C27.7608 20.129 27.6912 20.1798 27.6521 20.2081C27.5085 20.3121 27.3462 20.4472 27.2631 20.5319C27.2161 20.5796 27.1622 20.6272 27.1432 20.6374C27.0852 20.6689 27.0536 20.6965 26.9302 20.8233C26.7787 20.9791 26.7284 21.0186 26.7053 20.9994C26.6848 20.9824 26.8447 20.7874 26.9976 20.6427C27.0716 20.5727 27.1186 20.5007 27.1911 20.3459C27.2818 20.1524 27.308 20.117 27.6826 19.6814C28.1669 19.1182 28.2781 19.0301 28.7954 18.7991C28.8764 18.7629 28.8901 18.7909 28.828 18.8657C28.7982 18.9016 28.7673 18.9257 28.7595 18.9192C28.7293 18.8941 28.2906 19.1946 28.0734 19.3892C27.9976 19.4572 27.9066 19.5337 27.8713 19.5594C27.8359 19.585 27.8083 19.6191 27.8098 19.6351C27.8114 19.6511 27.6923 19.8189 27.5453 20.008C27.3982 20.1971 27.2785 20.3589 27.2794 20.3677C27.2825 20.3999 27.3164 20.3783 27.4429 20.2638C27.514 20.1995 27.6016 20.1311 27.6375 20.1118C27.6735 20.0925 27.7233 20.0653 27.7481 20.0513C27.9131 19.9582 28.0029 19.9214 28.0541 19.9258C28.1118 19.9308 28.2511 19.7969 28.4939 19.5031C28.5279 19.462 28.7232 19.2266 28.9279 18.9802C29.7029 18.0471 29.869 17.8438 29.8677 17.83C29.8669 17.8222 29.7614 17.8607 29.6331 17.9156C29.5048 17.9704 29.3653 18.0243 29.3231 18.0353C29.2808 18.0463 29.2395 18.0635 29.2312 18.0735C29.2229 18.0835 29.1532 18.1228 29.0763 18.1609C28.9994 18.199 28.9046 18.2462 28.8656 18.2659C28.8266 18.2855 28.6867 18.3681 28.5547 18.4494C28.4227 18.5306 28.2933 18.6078 28.2672 18.6208C28.241 18.6338 28.18 18.6754 28.1317 18.7133C28.0833 18.7513 27.9914 18.8169 27.9274 18.8593C27.8635 18.9016 27.7648 18.9829 27.7082 19.0399C27.6515 19.0969 27.5882 19.1467 27.5675 19.1505C27.5468 19.1543 27.528 19.1708 27.5258 19.1873C27.5204 19.2267 27.2922 19.3799 27.2823 19.3508C27.2781 19.3384 27.2933 19.3115 27.3162 19.2911C27.339 19.2706 27.4534 19.1663 27.5703 19.0593C27.6872 18.9523 27.8133 18.8442 27.8505 18.819C27.9517 18.7503 27.9679 18.7217 27.9386 18.6631C27.9134 18.6127 27.9188 18.5624 27.9649 18.4172C28.004 18.2942 28.0222 18.2634 28.2138 17.9956C28.3206 17.8463 28.4479 17.6517 28.4966 17.5631C28.5464 17.4726 28.702 17.2572 28.8519 17.0714C28.9986 16.8895 29.1426 16.711 29.1719 16.6746C29.2492 16.5788 29.4822 16.3473 29.613 16.2363C29.675 16.1837 29.7506 16.1187 29.7809 16.0918C29.8112 16.0649 29.8616 16.0216 29.8929 15.9955C29.9242 15.9695 29.9783 15.922 30.013 15.8901C30.0477 15.8582 30.1373 15.7906 30.212 15.7399C30.2868 15.6892 30.3695 15.6301 30.3959 15.6087C30.798 15.282 31.7524 14.7336 32.1587 14.5958C32.1883 14.5857 32.2725 14.5562 32.3458 14.5303C32.419 14.5043 32.5536 14.4683 32.6448 14.4502L32.8107 14.4173L32.9281 14.2667C33.0538 14.1055 33.0827 14.0344 33.0124 14.059C32.9902 14.0669 32.9306 14.0785 32.8801 14.0849C32.8297 14.0913 32.7834 14.1025 32.7774 14.1098C32.7713 14.117 32.7296 14.1278 32.6848 14.1338C32.6399 14.1397 32.5502 14.1572 32.4854 14.1726C32.4207 14.188 32.3171 14.2054 32.2553 14.2113C32.1935 14.2172 32.1331 14.2339 32.121 14.2485C32.1089 14.263 32.0829 14.2729 32.0631 14.2703C32.0433 14.2678 31.9959 14.2775 31.9577 14.2918C31.9195 14.3062 31.7998 14.3488 31.6917 14.3865C31.5837 14.4242 31.4373 14.4753 31.3666 14.5001C31.2958 14.525 31.2284 14.5567 31.2168 14.5707C31.2052 14.5847 31.1692 14.5985 31.1369 14.6013C31.1045 14.6042 31.0681 14.6155 31.0558 14.6265C31.0339 14.6461 30.8568 14.7314 30.7792 14.7596C30.5904 14.8284 30.2042 15.054 29.9651 15.2352C29.8668 15.3097 29.766 15.3784 29.7412 15.388C29.7164 15.3975 29.6861 15.4173 29.6739 15.432C29.6481 15.4631 29.4347 15.5744 29.4037 15.5729C29.3365 15.5696 29.0873 15.7164 28.9255 15.8547C28.8843 15.8899 28.8293 15.9223 28.8032 15.9267C28.7598 15.934 28.6392 16.0225 28.5813 16.0894C28.5539 16.121 28.3308 16.3279 28.2537 16.3931C28.2252 16.4172 28.1347 16.5029 28.0524 16.5836C27.8971 16.736 27.8198 16.7739 27.8276 16.6938C27.83 16.6699 27.8677 16.6162 27.9116 16.5745C27.9554 16.5328 28.1018 16.3917 28.237 16.261C28.532 15.9759 28.5668 15.9475 28.7067 15.8794C28.7665 15.8502 28.8359 15.8079 28.861 15.7853C28.9563 15.6995 29.1278 15.6015 29.3675 15.4961C29.507 15.4348 29.6656 15.3451 29.7291 15.2916C29.8862 15.1593 30.2842 14.9076 30.4646 14.8265C30.5473 14.7892 30.6202 14.7525 30.6266 14.7448C30.6594 14.7053 31.5968 14.3188 31.6435 14.3256C31.6563 14.3274 31.7141 14.308 31.772 14.2824C31.8791 14.2352 32.2769 14.1334 32.4392 14.1118C32.4882 14.1052 32.5625 14.0888 32.6042 14.0753C32.6459 14.0617 32.7857 14.0346 32.9149 14.015L33.1498 13.9792L33.3876 13.7083C33.6585 13.3996 33.663 13.3822 33.4656 13.4024C33.2366 13.4259 33.1472 13.4443 32.896 13.5201C32.7657 13.5594 32.627 13.6004 32.5878 13.6112C32.5485 13.622 32.4777 13.6471 32.4304 13.6669C32.3831 13.6867 32.3291 13.7057 32.3104 13.7092C32.1994 13.7294 32.0043 13.7859 31.9478 13.8142C31.9115 13.8323 31.8651 13.8414 31.8445 13.8343C31.8239 13.8273 31.7956 13.8353 31.7815 13.8522C31.7675 13.869 31.7162 13.8962 31.6676 13.9127C31.619 13.9291 31.5719 13.9514 31.563 13.9621C31.5541 13.9729 31.4909 13.9972 31.4227 14.0161C31.3544 14.0351 31.2934 14.0568 31.2872 14.0642C31.281 14.0717 31.1754 14.1235 31.0525 14.1792C30.765 14.3097 30.688 14.3489 30.5537 14.4335C30.4151 14.5209 30.3331 14.5429 30.328 14.4944C30.3254 14.4696 30.3793 14.4278 30.505 14.3574C30.7152 14.2396 30.6981 14.2529 31.0039 13.9681C31.1443 13.8374 31.6365 13.4992 31.7694 13.4422C31.7925 13.4323 31.8692 13.394 31.9398 13.3571C32.0103 13.3202 32.1272 13.2612 32.1996 13.2258C32.3928 13.1314 33.0988 12.8726 33.2408 12.8442C33.3081 12.8307 33.3977 12.8057 33.4397 12.7886C33.4818 12.7714 33.5691 12.7504 33.6337 12.7418C33.6984 12.7332 33.8268 12.7128 33.9191 12.6965C34.0114 12.6803 34.1296 12.6622 34.1818 12.6563C34.2722 12.6461 34.2868 12.6345 34.4902 12.4112L34.7037 12.1769L34.3844 12.2242C33.601 12.3403 33.1628 12.419 33.1387 12.4479C33.1324 12.4556 33.0966 12.4658 33.0593 12.4706C33.022 12.4754 32.9336 12.5023 32.8629 12.5304C32.7922 12.5584 32.7171 12.5813 32.696 12.5811C32.675 12.581 32.5593 12.634 32.4389 12.6989C32.3185 12.7638 32.1882 12.833 32.1492 12.8527C32.1103 12.8725 32.0068 12.9356 31.9192 12.993C31.8316 13.0504 31.7461 13.1008 31.7292 13.1049C31.7122 13.1091 31.6632 13.1432 31.6202 13.1808C31.5772 13.2183 31.5309 13.2475 31.5173 13.2455C31.5037 13.2435 31.476 13.262 31.4557 13.2864C31.4354 13.3109 31.4076 13.3293 31.3941 13.3273C31.3805 13.3254 31.3338 13.3549 31.2903 13.3929C31.2468 13.4309 31.1826 13.4706 31.1478 13.4812C31.1129 13.4918 31.0829 13.5113 31.081 13.5247C31.0775 13.5507 30.9643 13.6296 30.8863 13.6604C30.8603 13.6707 30.7692 13.7654 30.6839 13.8709C30.5986 13.9764 30.4351 14.1666 30.3206 14.2937C30.1513 14.4816 30.1158 14.5307 30.1305 14.5568C30.1571 14.6038 29.9416 14.7746 29.6732 14.9192C29.5909 14.9635 29.5194 15.0049 29.5142 15.0111C29.509 15.0173 29.4755 15.038 29.4396 15.0571C29.4038 15.0762 29.3619 15.1027 29.3464 15.1159C29.2239 15.2209 29.103 15.3081 29.0721 15.3138C29.0517 15.3175 29.0358 15.3289 29.0368 15.3391C29.0378 15.3494 28.9616 15.4126 28.8674 15.4796C28.7733 15.5466 28.6595 15.6418 28.6145 15.6912C28.5695 15.7406 28.4661 15.8393 28.3847 15.9105C28.3033 15.9817 28.2175 16.0631 28.1941 16.0914C28.1627 16.1293 28.1421 16.135 28.116 16.1134C28.0617 16.0683 27.9795 16.1272 27.9289 16.2475C27.9051 16.304 27.8404 16.4065 27.785 16.4753C27.6522 16.6403 27.627 16.7168 27.6886 16.7681C27.7762 16.8407 27.688 17.1783 27.5363 17.3515C27.4471 17.4533 27.3656 17.6246 27.3522 17.7385C27.3501 17.7561 27.324 17.7983 27.2942 17.8323C27.2643 17.8663 27.2221 17.9432 27.2003 18.0032C27.1786 18.0632 27.1493 18.1265 27.1352 18.1438C27.1188 18.1638 27.1277 18.1982 27.1598 18.2392C27.1875 18.2744 27.2195 18.3374 27.2309 18.3792L27.2517 18.4552L27.3531 18.3584C27.5774 18.1439 27.8075 17.9711 27.8366 17.9952C27.8477 18.0044 27.842 18.0201 27.8241 18.0301C27.8061 18.0401 27.7458 18.0929 27.69 18.1475C27.6343 18.2021 27.5666 18.264 27.5396 18.285C27.3297 18.4486 26.9718 18.8519 26.9097 18.9948C26.8852 19.0512 26.8332 19.1311 26.794 19.1723C26.7549 19.2135 26.731 19.2541 26.7409 19.2623C26.7509 19.2706 26.7281 19.3262 26.6902 19.3859C26.4245 19.8048 26.3648 19.9919 26.4455 20.1527C26.4801 20.2217 26.5081 20.3484 26.5163 20.4736C26.5238 20.5873 26.5383 20.6589 26.5485 20.6327C26.6956 20.2538 27.1533 19.7533 27.6799 19.3952C28.1744 19.059 27.9732 19.2792 27.4299 19.6688C27.3913 19.6965 27.3708 19.7222 27.3807 19.7305C27.4059 19.7514 27.3593 19.7985 27.281 19.8314C27.207 19.8624 26.8296 20.2375 26.8321 20.2775C26.833 20.2907 26.8065 20.343 26.7734 20.3936C26.5473 20.7387 26.5076 20.8174 26.4833 20.9695C26.4696 21.0554 26.4481 21.1724 26.4356 21.2295C26.4231 21.2866 26.4217 21.4304 26.4326 21.5491C26.4434 21.6678 26.4469 21.7717 26.4403 21.78C26.4337 21.7882 26.4313 21.8613 26.4348 21.9423C26.4384 22.0233 26.4377 22.1364 26.4334 22.1935C26.429 22.2506 26.4231 22.3522 26.4203 22.4192C26.4174 22.4862 26.4089 22.6108 26.4014 22.6959C26.3848 22.886 26.3696 22.89 26.5958 22.6433ZM13.61 11.8209C13.7276 11.7927 13.88 11.7536 13.9486 11.734C14.0173 11.7143 14.1394 11.688 14.2201 11.6755C14.4646 11.6376 14.4747 11.6342 14.4203 11.6086C14.3943 11.5964 14.3662 11.5948 14.3578 11.6049C14.3426 11.6233 14.1256 11.6759 14.0555 11.6782C14.0354 11.6789 13.9665 11.6926 13.9024 11.7087C13.8382 11.7249 13.7486 11.7428 13.7033 11.7485C13.658 11.7543 13.5868 11.7732 13.5451 11.7907C13.5034 11.8081 13.4441 11.8263 13.4132 11.831C13.3824 11.8358 13.366 11.847 13.3767 11.8559C13.3874 11.8648 13.4924 11.849 13.61 11.8209ZM20.2114 17.2822C20.219 17.273 20.2884 17.2472 20.3655 17.2249C20.4433 17.2024 20.5412 17.1526 20.5857 17.1128C20.6297 17.0734 20.7205 16.9923 20.7875 16.9325C20.8544 16.8727 21.1053 16.5952 21.345 16.3158C21.5847 16.0365 21.7907 15.8046 21.8027 15.8006C21.8148 15.7966 21.9839 15.6207 22.1785 15.4097C22.3732 15.1987 22.5927 14.9696 22.6664 14.9007C22.7401 14.8317 22.9296 14.6555 23.0876 14.509C23.2456 14.3626 23.4589 14.1492 23.5616 14.035C23.6643 13.9207 23.7803 13.8056 23.8193 13.7792C23.864 13.7491 23.8931 13.7146 23.8976 13.6865C23.9033 13.6515 23.8932 13.6545 23.8515 13.7C23.8222 13.732 23.7915 13.7633 23.7833 13.7695C23.7751 13.7757 23.7294 13.8149 23.6817 13.8564C23.634 13.898 23.5634 13.9388 23.5248 13.9471C23.4863 13.9553 23.4066 14.0073 23.3479 14.0626C23.2891 14.1179 23.187 14.1893 23.121 14.2212C23.0438 14.2586 22.9319 14.3459 22.8076 14.4658C22.7013 14.5684 22.5939 14.6674 22.5691 14.6858C22.5442 14.7042 22.5321 14.7261 22.5423 14.7346C22.5629 14.7516 22.6423 14.6939 22.7754 14.5653C22.8237 14.5187 22.8952 14.4644 22.9343 14.4448C22.9733 14.4252 23.0206 14.4006 23.0394 14.3901C23.0966 14.3581 22.9278 14.5248 22.8311 14.5958C22.7812 14.6324 22.6729 14.7156 22.5905 14.7806C22.4665 14.8784 22.4366 14.8926 22.4173 14.8626C22.4006 14.8366 22.3968 14.8368 22.4037 14.8631C22.4098 14.8864 22.3879 14.9241 22.3437 14.9662C22.2262 15.0781 21.969 15.3587 21.762 15.601C21.6535 15.7278 21.5375 15.8504 21.5041 15.8734C21.4651 15.9002 21.4434 15.9307 21.4435 15.9586C21.4439 16.0344 20.8681 16.7591 20.7775 16.7969C20.7541 16.8067 20.7276 16.8352 20.7187 16.8604C20.692 16.9356 20.4152 17.1616 20.2827 17.2164C20.2149 17.2445 20.1679 17.2745 20.1784 17.2832C20.1889 17.2919 20.2037 17.2915 20.2114 17.2822ZM15.4175 12.2492C15.7434 12.0098 15.5563 11.6511 15.2015 11.8353L15.1193 11.8779L15.1882 11.9571C15.241 12.0179 15.2587 12.0693 15.2641 12.1787C15.2725 12.3471 15.2797 12.3504 15.4175 12.2492ZM14.8576 11.6422C15.1406 11.6112 15.235 11.5796 15.0592 11.5747C14.9901 11.5729 14.9243 11.5635 14.9128 11.554C14.9014 11.5445 14.8838 11.5466 14.8737 11.5587C14.8636 11.5708 14.8034 11.583 14.7398 11.5858C14.6243 11.5909 14.5711 11.6172 14.6103 11.6498C14.6217 11.6593 14.733 11.6559 14.8576 11.6422ZM15.6039 11.5842C15.8556 11.5757 16.0678 11.5454 15.9219 11.5388C15.8897 11.5373 15.8319 11.5394 15.7935 11.5435C15.7552 11.5475 15.6614 11.5483 15.5852 11.5452C15.5091 11.542 15.3955 11.5451 15.3328 11.5521C15.0847 11.5795 15.2307 11.5968 15.6039 11.5842ZM15.9241 11.7664C15.9232 11.75 15.7851 11.7318 15.6897 11.7356C15.607 11.7389 15.578 11.7593 15.6139 11.7891C15.627 11.8 15.6542 11.8492 15.6743 11.8985L15.7109 11.988L15.8179 11.8836C15.8767 11.8261 15.9245 11.7734 15.9241 11.7664ZM32.3907 24.721C32.4667 24.6161 32.5266 24.5132 32.5239 24.4925C32.5201 24.4642 32.4948 24.4905 32.4236 24.5964C32.3712 24.6744 32.3177 24.7507 32.3048 24.766C32.2651 24.8129 32.228 24.8915 32.2406 24.902C32.2471 24.9074 32.3146 24.8259 32.3907 24.721ZM20.7186 14.8765C20.8859 14.7897 20.9076 14.7765 21.0853 14.6533C21.1733 14.5922 21.2627 14.5214 21.2839 14.4959C21.3411 14.427 21.4272 14.4522 21.4326 14.5393C21.439 14.6434 21.5143 14.6203 21.5931 14.4902C21.6262 14.4355 21.759 14.2494 21.8881 14.0766C22.1134 13.7752 22.1957 13.6268 22.101 13.6925C22.0091 13.7563 21.9385 13.8131 21.8902 13.8618C21.8619 13.8904 21.807 13.93 21.7682 13.9498C21.7293 13.9696 21.6868 14.0026 21.6737 14.0232C21.6607 14.0438 21.6186 14.0702 21.5803 14.0817C21.5382 14.0945 21.4982 14.126 21.4792 14.1614C21.4091 14.2919 21.3095 14.4234 21.2715 14.4356C21.216 14.4534 21.2324 14.4148 21.3502 14.2495C21.769 13.6618 22.1888 12.9413 22.4032 12.4421C22.6425 11.8849 22.6947 11.7396 22.7384 11.5088C22.7748 11.3168 22.8019 11.2712 22.8174 11.3759C22.8428 11.5479 22.5672 12.3611 22.4581 12.4364C22.4481 12.4433 22.4409 12.4728 22.4421 12.5021C22.4449 12.5687 22.3102 12.8307 21.9405 13.4776C21.7621 13.7897 21.764 13.7831 21.8756 13.7077C22.0205 13.6099 22.301 13.2522 22.445 12.9817C22.5123 12.8553 22.5938 12.703 22.6263 12.6431C22.6587 12.5833 22.6937 12.4846 22.7041 12.4238C22.7145 12.363 22.7423 12.2788 22.766 12.2366C22.7897 12.1945 22.8177 12.09 22.8282 12.0043C22.8386 11.9186 22.8555 11.8382 22.8656 11.8255C22.9091 11.7707 22.9504 11.4345 22.9386 11.2304C22.932 11.1158 22.8834 11.0936 22.7614 11.1494C22.7223 11.1673 22.6487 11.1998 22.5978 11.2218C22.5469 11.2437 22.4947 11.2744 22.4818 11.29C22.4688 11.3056 22.42 11.3359 22.3732 11.3573C22.2927 11.3942 22.2879 11.4004 22.2834 11.475C22.2688 11.7177 22.2535 11.8333 22.2326 11.8584C22.2196 11.8739 22.1977 11.9339 22.1838 11.9918C22.1235 12.2427 21.8968 12.6599 21.4337 13.3723C21.3761 13.4608 21.357 13.5294 21.3836 13.5516C21.4168 13.5791 21.406 13.7355 21.3678 13.7815C21.3516 13.801 21.3398 13.8315 21.3414 13.8494C21.3431 13.8673 21.3079 13.9296 21.2632 13.9879C21.2185 14.0463 21.1728 14.1198 21.1617 14.1512C21.1386 14.2161 20.9745 14.44 20.7066 14.7719C20.606 14.8966 20.5412 14.9848 20.5627 14.9679C20.5841 14.951 20.6543 14.9099 20.7186 14.8765ZM16.5347 11.5909C16.5608 11.5861 16.6264 11.6035 16.6806 11.6296C16.7891 11.6818 16.8584 11.6804 16.8768 11.6256C16.8869 11.5953 16.8731 11.5861 16.7876 11.5657C16.6521 11.5333 16.4175 11.5388 16.4573 11.5733C16.4738 11.5877 16.5087 11.5956 16.5347 11.5909ZM12.8305 8.43984C12.8243 8.39075 12.6533 8.21438 12.6341 8.23741C12.6253 8.24811 12.6599 8.2969 12.7112 8.34585C12.7625 8.3948 12.8112 8.44309 12.8195 8.45316C12.8289 8.46473 12.833 8.45982 12.8305 8.43984ZM13.8602 9.29093C13.9573 9.36512 13.82 9.18379 13.5701 8.90776C13.4661 8.79286 13.3376 8.63037 13.2845 8.54665C13.2315 8.46294 13.1617 8.36329 13.1295 8.32519C13.0972 8.2871 13.0633 8.22169 13.0542 8.17982C13.045 8.13796 13.016 8.08588 12.9898 8.06408C12.9635 8.04228 12.9438 8.01169 12.9459 7.9961C12.948 7.98051 12.9333 7.95409 12.9132 7.93739C12.8782 7.90832 12.8819 7.87772 12.9209 7.87428C12.9456 7.87211 13.1676 8.19485 13.1777 8.24763C13.1821 8.27058 13.1933 8.28869 13.2026 8.28787C13.2119 8.28705 13.259 8.34889 13.3072 8.4253C13.4041 8.57876 13.457 8.64379 13.7711 8.99569C13.889 9.12778 14.0343 9.29789 14.0939 9.37368C14.2159 9.52888 14.4668 9.74872 14.49 9.72076C14.4983 9.71073 14.4724 9.67729 14.4324 9.64645C14.3923 9.61561 14.3129 9.53448 14.2558 9.46617C14.1987 9.39785 14.0998 9.28567 14.036 9.21687C13.912 9.08309 13.7553 8.88107 13.6656 8.7394C13.6353 8.69154 13.5741 8.59601 13.5295 8.52711C13.4849 8.45821 13.4529 8.37973 13.4583 8.35272C13.4712 8.28873 13.4918 8.30671 13.6078 8.48313C13.7447 8.69125 14.0649 9.09728 14.29 9.34831C14.3218 9.38379 14.391 9.46353 14.4439 9.52551C14.4967 9.5875 14.5635 9.65362 14.5924 9.67245C14.6717 9.7242 14.5355 9.5169 14.3961 9.3738C14.3347 9.31073 14.2439 9.2045 14.1943 9.13772C14.1447 9.07095 14.0744 8.97899 14.0381 8.93336C14.0019 8.88773 13.9584 8.81933 13.9415 8.78136C13.9247 8.74339 13.8437 8.61645 13.7615 8.49927C13.6291 8.31028 13.5714 8.16881 13.6248 8.16409C13.6349 8.1632 13.6908 8.23233 13.7491 8.3177C13.8074 8.40307 13.8844 8.50959 13.9203 8.55441C13.9563 8.59922 14.0042 8.67081 14.027 8.71348C14.0497 8.75616 14.1192 8.85913 14.1814 8.94232C14.2437 9.0255 14.321 9.13072 14.3533 9.17614C14.3856 9.22156 14.4259 9.26792 14.4429 9.27915C14.4598 9.29037 14.5282 9.37193 14.5948 9.46038C14.7274 9.63649 15.0351 9.94216 14.9959 9.85893C14.9833 9.83201 14.9427 9.78391 14.9058 9.75206C14.869 9.72021 14.7837 9.60728 14.7164 9.50108C14.649 9.39489 14.5608 9.27032 14.5203 9.22425C14.4797 9.17818 14.4435 9.12696 14.4397 9.11043C14.4323 9.07812 14.2985 8.89598 14.253 8.85615C14.2024 8.81197 14.1332 8.69366 14.1478 8.67618C14.1556 8.6667 14.1298 8.6322 14.0905 8.5995C14.0511 8.5668 14.0172 8.52295 14.0152 8.50205C14.0132 8.48114 13.988 8.43482 13.9592 8.3991C13.9103 8.33833 13.9187 8.23598 13.9691 8.27789C13.981 8.28774 14.0125 8.29388 14.039 8.29153C14.0716 8.28866 14.1113 8.31198 14.1605 8.36296L14.2336 8.43864L14.1835 8.33184C14.156 8.2731 14.1218 8.21538 14.1076 8.20358C14.077 8.17814 13.9499 7.76442 13.9666 7.74435C13.9729 7.73673 13.9572 7.69957 13.9317 7.66178C13.9053 7.62256 13.8927 7.56777 13.9025 7.53412C13.9162 7.48663 13.9077 7.4687 13.8584 7.44183C13.8248 7.42348 13.7893 7.38863 13.7795 7.36437C13.7697 7.34011 13.7287 7.26969 13.6883 7.20787C13.6479 7.14606 13.6165 7.08371 13.6185 7.06931C13.6204 7.05491 13.5984 7.02353 13.5696 6.99957C13.5407 6.97561 13.4829 6.90016 13.4412 6.83191C13.3531 6.68794 13.31 6.63426 13.1252 6.43845C13.0507 6.3595 12.9674 6.27012 12.94 6.23984C12.839 6.12805 12.5711 5.87982 12.5724 5.89919C12.5732 5.9102 12.6282 5.97333 12.6947 6.03946C12.7612 6.10559 12.819 6.16942 12.8233 6.1813C12.8275 6.19319 12.8694 6.24629 12.9163 6.2993C12.9632 6.35232 13.0345 6.4509 13.0748 6.51838C13.1976 6.72419 13.4656 7.1279 13.5556 7.2426C13.6691 7.38713 13.9081 7.91854 13.9332 8.08191C13.944 8.15203 13.9402 8.1608 13.9044 8.14854C13.8817 8.14077 13.8591 8.10974 13.8542 8.07956C13.8492 8.04939 13.8292 8.00084 13.8097 7.97168C13.7901 7.94252 13.745 7.84155 13.7095 7.7473C13.6268 7.52813 13.4711 7.27151 13.3343 7.12917C13.3023 7.09583 13.2478 7.01038 13.2133 6.93929C13.1788 6.8682 13.119 6.77471 13.0806 6.73155C13.0421 6.68838 13.007 6.63597 13.0024 6.61509C12.9979 6.59421 12.9896 6.58265 12.9839 6.5894C12.9783 6.59616 12.9642 6.57843 12.9525 6.55001C12.9408 6.52159 12.903 6.46801 12.8684 6.43094C12.8337 6.39387 12.7832 6.33856 12.7561 6.30802C12.6378 6.17503 12.3842 5.9527 12.3989 5.99493C12.4151 6.04119 12.6504 6.42516 12.6935 6.47577C12.7076 6.49228 12.8046 6.60124 12.9091 6.71789C13.1203 6.9537 13.2736 7.16052 13.2544 7.18362C13.2475 7.19194 13.2584 7.2044 13.2786 7.21131C13.3092 7.22178 13.5022 7.51293 13.6428 7.76056C13.6868 7.83822 13.6491 7.90157 13.6023 7.8285C13.5851 7.80172 13.5177 7.70352 13.4524 7.61028C13.3872 7.51703 13.3159 7.40447 13.2941 7.36013C13.2723 7.3158 13.2323 7.25434 13.2054 7.22357C13.1784 7.1928 13.0906 7.09157 13.0102 6.99862C12.9298 6.90568 12.8176 6.78206 12.7608 6.72392C12.6244 6.58416 12.4851 6.41373 12.4766 6.37618C12.4729 6.3596 12.4453 6.31526 12.4152 6.27764C12.3852 6.24001 12.3576 6.19561 12.3539 6.17897C12.3502 6.16233 12.3152 6.10102 12.2761 6.04273C12.2093 5.94332 12.0832 5.70598 12.0433 5.60479C12.0335 5.57997 12.0159 5.55166 12.0041 5.54188C11.9631 5.50777 11.9815 5.60638 12.0355 5.70928C12.0644 5.76427 12.1171 5.86901 12.1528 5.94203C12.3176 6.27959 12.3527 6.34741 12.4214 6.46189C12.4618 6.5292 12.5112 6.60277 12.5312 6.62539C12.5512 6.64802 12.5973 6.71329 12.6336 6.77045C12.7055 6.88377 12.8571 7.07745 13.0703 7.32874C13.3145 7.61648 13.545 8.02038 13.393 7.89415C13.3769 7.88077 13.3627 7.85955 13.3615 7.84699C13.3603 7.83444 13.3401 7.80449 13.3167 7.78043C13.2932 7.75638 13.1967 7.64402 13.1022 7.53076C12.9315 7.32622 12.894 7.28203 12.7334 7.09607C12.6874 7.0428 12.6286 6.967 12.6027 6.92762C12.5768 6.88824 12.5292 6.81886 12.4969 6.77343C12.2789 6.4669 12.1795 6.31214 12.1832 6.28509C12.1855 6.26794 12.1731 6.25185 12.1556 6.24932C12.1381 6.2468 12.1296 6.22737 12.1368 6.20615C12.1439 6.18493 12.1354 6.15568 12.1179 6.14115C12.1004 6.12663 12.0396 6.01221 11.9827 5.88691C11.8631 5.62348 11.8515 5.60781 11.8589 5.721C11.8619 5.76689 11.8729 5.81148 11.8832 5.82009C11.8936 5.82871 11.9412 5.91938 11.9889 6.0216C12.0366 6.12381 12.0898 6.23353 12.1071 6.26542C12.1244 6.29731 12.1478 6.34506 12.159 6.37152C12.1882 6.43982 12.4623 6.90031 12.5325 6.99891C12.5649 7.0443 12.6453 7.1664 12.7112 7.27024C12.7771 7.37408 12.8444 7.47011 12.8607 7.48364C12.877 7.49717 12.8987 7.52813 12.9089 7.55243C12.9191 7.57673 12.9597 7.64406 12.9991 7.70205C13.0446 7.76912 13.0633 7.82119 13.0503 7.84517C13.0264 7.88943 12.9796 7.83876 12.8436 7.62098C12.7985 7.54879 12.744 7.47054 12.7225 7.4471C12.701 7.42365 12.6483 7.35774 12.6054 7.30063C12.5625 7.24351 12.5228 7.19877 12.5171 7.20119C12.5115 7.20362 12.5083 7.18134 12.51 7.15169C12.512 7.11714 12.4845 7.07045 12.4336 7.02167C12.3335 6.92591 12.0387 6.44958 12.011 6.33891C11.9995 6.29329 11.9768 6.24489 11.9605 6.23134C11.9442 6.2178 11.9065 6.15098 11.8767 6.08285C11.8469 6.01473 11.8045 5.94403 11.7825 5.92575C11.7599 5.90694 11.7344 5.81727 11.7238 5.71925C11.7044 5.53874 11.6811 5.48246 11.663 5.57243C11.6473 5.65094 11.7662 6.14751 11.8342 6.28733C11.8569 6.33386 11.9138 6.45502 11.9608 6.55658C12.0333 6.71339 12.264 7.09247 12.5128 7.46354C12.5875 7.57497 12.6989 7.72404 12.7993 7.84675C12.8982 7.96755 12.907 7.98694 12.8721 8.00639C12.8386 8.02505 12.6439 7.85635 12.6323 7.79867C12.6289 7.78169 12.5985 7.73643 12.5646 7.69811C12.2159 7.30304 12.3961 7.58334 12.952 8.30048C12.9677 8.32085 13.0905 8.47258 13.2248 8.63766C13.3591 8.80273 13.4933 8.96892 13.5229 9.00696C13.5526 9.04501 13.6253 9.11274 13.6844 9.15748C13.7436 9.20221 13.8227 9.26228 13.8602 9.29093ZM12.2457 7.88407C12.2129 7.84088 12.1828 7.79084 12.1788 7.77288C12.1749 7.75491 12.1542 7.71811 12.1329 7.69109C12.0676 7.60847 11.9175 7.33593 11.8856 7.24221C11.8494 7.13594 11.8389 7.12515 11.8079 7.16248C11.7948 7.17821 11.7947 7.20856 11.8076 7.22993C11.8205 7.25129 11.8599 7.32887 11.8952 7.40232C12.0121 7.64568 12.1164 7.80446 12.2114 7.88401L12.3053 7.9626L12.2457 7.88407ZM15.4617 10.1355C15.5431 10.1108 15.5417 10.0593 15.4581 10.0081C15.4281 9.98966 15.3777 9.93171 15.3462 9.87928C15.2475 9.71525 15.223 9.72775 15.2988 9.90344C15.3387 9.9961 15.3696 10.085 15.3675 10.1009C15.3612 10.1469 15.3895 10.1573 15.4617 10.1355ZM14.9645 9.60924C14.9572 9.58638 14.9385 9.55688 14.9229 9.54369C14.9074 9.53049 14.8776 9.4801 14.8568 9.43169C14.8302 9.36983 14.7963 9.33108 14.7427 9.30127C14.7008 9.27795 14.6737 9.26748 14.6825 9.27799C14.6913 9.28851 14.7448 9.362 14.8015 9.44131C14.9211 9.60857 14.9853 9.67479 14.9645 9.60924ZM11.7261 6.87612C11.7171 6.80299 11.656 6.71858 11.6407 6.75821C11.634 6.77565 11.6443 6.81269 11.6636 6.84053C11.7196 6.92104 11.7325 6.92837 11.7261 6.87612ZM15.2036 9.64221C15.2147 9.56871 15.1765 9.49342 15.0892 9.41712C14.978 9.31986 14.961 9.33143 15.0415 9.44951C15.075 9.49871 15.1179 9.56349 15.1368 9.59346C15.1872 9.67338 15.1978 9.68111 15.2036 9.64221ZM32.8507 23.8371C32.9487 23.6859 32.9778 23.6218 32.9725 23.5694L32.9654 23.5005L32.8931 23.614C32.8534 23.6764 32.8141 23.7575 32.8058 23.7942C32.7975 23.8309 32.7623 23.9082 32.7276 23.9659C32.6188 24.1469 32.7156 24.0455 32.8507 23.8371ZM14.9577 9.27682C14.9576 9.25317 14.9104 9.18568 14.8528 9.12683C14.7952 9.06797 14.7316 8.98508 14.7115 8.94261C14.6913 8.90015 14.6016 8.78971 14.5121 8.6972C14.4226 8.60469 14.3389 8.51293 14.326 8.49331C14.3131 8.47368 14.2913 8.46139 14.2774 8.46599C14.2635 8.47059 14.2875 8.51354 14.3307 8.56144C14.374 8.60935 14.4383 8.69123 14.4738 8.74341C14.5092 8.79558 14.6018 8.90834 14.6795 8.99398C14.8014 9.1283 14.9363 9.28512 14.9528 9.31166C14.9556 9.31615 14.9578 9.30046 14.9577 9.27682ZM17.6815 11.3203C17.7793 11.3218 18.0883 11.2565 18.0914 11.2337C18.0978 11.1867 18.6684 11.1167 18.957 11.1274C19.1668 11.1352 19.24 11.1289 19.2639 11.1007C19.2983 11.0604 19.0748 10.9204 18.9655 10.9138C18.9171 10.9109 18.8656 10.892 18.8511 10.8719C18.834 10.8482 18.8173 10.8459 18.8035 10.8654C18.7918 10.882 18.767 10.8898 18.7483 10.8828C18.7239 10.8737 18.7262 10.8615 18.7563 10.84C18.7942 10.813 18.7922 10.8082 18.7366 10.7929C18.7026 10.7835 18.6625 10.7906 18.6475 10.8087C18.6325 10.8267 18.6107 10.8382 18.599 10.8343C18.5502 10.8178 18.1985 10.8894 18.1721 10.9212C18.1267 10.9759 18.1653 10.9852 18.3535 10.9651C18.5622 10.9428 18.5965 10.9822 18.393 11.0105C18.2236 11.0341 17.9139 11.1171 17.8906 11.1453C17.8813 11.1564 17.8134 11.1952 17.7397 11.2316C17.6061 11.2975 17.592 11.3189 17.6815 11.3203ZM21.8396 14.3656C21.8842 14.328 21.984 14.2505 22.0613 14.1932C22.1387 14.136 22.2473 14.0487 22.3027 13.9993C22.4301 13.8857 22.6074 13.7083 22.5483 13.7536C22.5 13.7906 22.4608 13.7758 22.4788 13.7275C22.4982 13.6756 22.6461 13.4718 22.6655 13.4701C22.6963 13.4674 23.1462 12.9036 23.1673 12.8413C23.1781 12.8094 23.2501 12.6889 23.3272 12.5735C23.5038 12.3095 23.6139 12.1233 23.6883 11.9633C23.7203 11.8945 23.8071 11.714 23.8811 11.5624C23.9551 11.4107 24.0284 11.2373 24.0441 11.1771C24.0907 10.998 24.1543 10.7642 24.1809 10.6744C24.2099 10.5763 24.1558 10.5269 24.0873 10.5889C24.0631 10.6108 23.9791 10.6472 23.9007 10.6699C23.8222 10.6925 23.7461 10.7254 23.7316 10.7429C23.7171 10.7604 23.6938 10.773 23.6799 10.771C23.6297 10.7638 23.5483 10.8436 23.5503 10.898C23.5535 10.9855 23.4629 11.4881 23.4387 11.5173C23.4263 11.5322 23.42 11.5555 23.4247 11.5691C23.4347 11.5987 23.2838 11.9814 23.2328 12.0556C23.2132 12.0842 23.1715 12.1644 23.1402 12.2338C23.1089 12.3033 23.0544 12.4071 23.019 12.4645C22.9486 12.5788 22.9007 12.729 22.9275 12.7512C22.9542 12.7735 22.9039 12.9413 22.8638 12.9637C22.8054 12.9962 22.7727 12.9458 22.7981 12.8626C22.8141 12.8104 22.8109 12.789 22.7881 12.7966C22.7658 12.804 22.7639 12.7766 22.7825 12.7152C22.8259 12.5719 22.7762 12.5498 22.7206 12.6877C22.6549 12.8509 22.5445 13.0677 22.4151 13.288C22.3397 13.4163 22.2592 13.5797 22.2363 13.6511C22.2133 13.7225 22.1786 13.7897 22.1593 13.8005C22.1399 13.8113 22.1241 13.8403 22.1242 13.865C22.1243 13.8939 22.0481 14.0043 21.9106 14.1745C21.6988 14.4366 21.6731 14.5057 21.8396 14.3656ZM17.601 10.8326C17.6637 10.817 17.695 10.8268 17.7736 10.8867C17.9021 10.9847 17.9869 10.9204 17.8753 10.8097C17.7755 10.7106 17.7264 10.54 17.7127 10.2445C17.6966 9.89664 17.6492 9.47314 17.6241 9.45188C17.5995 9.43102 17.5841 9.19564 17.5958 9.01789C17.6007 8.94384 17.6073 8.79315 17.6105 8.68303C17.6137 8.5729 17.6242 8.45383 17.6338 8.41843C17.65 8.35847 17.583 7.79772 17.5598 7.79977C17.554 7.80028 17.4913 7.86844 17.4205 7.95124C17.2786 8.11703 17.2664 8.15599 17.2786 8.4036C17.2864 8.56209 17.2989 8.58485 17.3213 8.48121C17.3431 8.37993 17.4152 8.25437 17.4777 8.20883C17.5474 8.158 17.5563 8.20121 17.4954 8.29544C17.468 8.33787 17.4232 8.42381 17.3959 8.48641C17.3549 8.58023 17.3406 8.59805 17.3144 8.58779C17.2912 8.57869 17.2841 8.59683 17.2879 8.65516C17.2955 8.77158 17.3149 8.77231 17.4041 8.65958C17.4482 8.60398 17.5053 8.54498 17.5312 8.52849C17.6182 8.47296 17.614 8.52684 17.5228 8.63674C17.473 8.69673 17.4126 8.79231 17.3887 8.84914C17.3648 8.90597 17.3351 8.95875 17.3227 8.96643C17.3102 8.97411 17.3055 9.02591 17.3121 9.08153C17.3258 9.19746 17.3352 9.19487 17.3673 9.06625C17.38 9.01564 17.4001 8.97336 17.4121 8.9723C17.4493 8.96902 17.4751 9.0391 17.4486 9.07109C17.4347 9.08776 17.4226 9.13685 17.4217 9.18017C17.4196 9.27367 17.3868 9.32328 17.3592 9.27454C17.326 9.2157 17.3104 9.27053 17.3338 9.36395L17.3561 9.45327L17.3826 9.39765C17.4104 9.33934 17.5033 9.28816 17.5345 9.31401C17.5445 9.32231 17.5318 9.35414 17.5064 9.38474C17.4489 9.45403 17.3897 9.63367 17.4151 9.66186C17.4255 9.6734 17.458 9.70401 17.4875 9.72988C17.5301 9.76735 17.5352 9.7914 17.5127 9.8481C17.4972 9.88725 17.4862 9.95387 17.4882 9.99614L17.492 10.073L17.5441 10.0294C17.6361 9.95242 17.6573 10.1997 17.5679 10.3073C17.5588 10.3183 17.5755 10.41 17.605 10.5111C17.6345 10.6122 17.6474 10.7016 17.6336 10.7097C17.6198 10.7178 17.6102 10.7415 17.6122 10.7624C17.6174 10.8166 17.5735 10.8121 17.4797 10.749C17.4713 10.7433 17.4574 10.7471 17.4489 10.7574C17.4161 10.7968 17.5261 10.8512 17.601 10.8326ZM17.3541 10.584C17.369 10.5791 17.4211 10.608 17.4697 10.6483L17.5582 10.7216L17.5398 10.6287C17.5173 10.5151 17.504 10.5006 17.4766 10.5595C17.4573 10.6011 17.4457 10.5972 17.3437 10.5148C17.2334 10.4258 17.2324 10.4255 17.2671 10.4971C17.3102 10.586 17.3197 10.5954 17.3541 10.584ZM33.0936 23.4141C33.087 23.3657 33.102 23.2949 33.1284 23.2494C33.2194 23.0926 33.2462 22.9365 33.1654 23.0337C33.0792 23.1376 33.007 23.5547 33.0827 23.5117C33.095 23.5047 33.0999 23.4608 33.0936 23.4141ZM17.4774 10.4837C17.4964 10.4821 17.4597 10.1985 17.4382 10.1806C17.429 10.1729 17.4048 10.0726 17.3844 9.95771C17.3641 9.84279 17.3314 9.69903 17.3119 9.63824C17.2923 9.57744 17.2617 9.44658 17.2439 9.34743C17.2234 9.23388 17.1982 9.16526 17.1759 9.16203C17.0755 9.14754 16.9297 8.89095 16.9844 8.82508C17.0234 8.77811 17.0506 8.80096 17.0784 8.90401C17.1045 9.00068 17.1897 9.11454 17.2141 9.08521C17.244 9.04921 17.2199 8.82191 17.1874 8.83271C17.1 8.86169 16.9538 8.62968 16.9734 8.49315C16.9907 8.37265 17.0565 8.3613 17.0599 8.47822C17.0627 8.57392 17.1522 8.79911 17.1863 8.79609C17.2509 8.7904 17.2189 8.46362 17.1449 8.37274C17.1166 8.33804 17.095 8.29834 17.0969 8.28452C17.0988 8.2707 17.0838 8.24572 17.0637 8.22902C17.0161 8.18946 17.0048 8.06807 17.0465 8.04479C17.0665 8.03367 17.0678 8.00906 17.0498 7.98127C16.9967 7.89885 17.0052 7.76516 17.0684 7.68899C17.1401 7.60271 17.1967 7.6313 17.1467 7.72851C17.068 7.88157 17.1593 8.1088 17.257 8.00304C17.362 7.88945 17.4004 7.8522 17.4648 7.80178C17.5324 7.74876 17.5334 7.74319 17.4904 7.65359C17.4658 7.60239 17.4403 7.51973 17.4337 7.46991C17.4176 7.34813 17.39 7.35827 17.3073 7.51633C17.2387 7.64737 17.1955 7.68533 17.1892 7.62013C17.185 7.57702 17.2931 7.37196 17.3809 7.25648C17.4307 7.1909 17.4497 7.13745 17.4503 7.06169C17.4506 7.00427 17.4513 6.91495 17.4516 6.86321C17.4525 6.74557 17.4137 6.78165 17.3667 6.94222C17.3443 7.01865 17.3203 7.05924 17.2908 7.07046C17.2614 7.08168 17.236 7.1247 17.2105 7.20655C17.1901 7.27238 17.1628 7.33875 17.1499 7.35405C17.1028 7.40976 17.0035 7.61327 16.9878 7.68593C16.979 7.72692 16.9526 7.79503 16.9292 7.83727C16.901 7.8882 16.8911 7.9755 16.8998 8.09643C16.907 8.19673 16.9092 8.31151 16.9047 8.3515C16.9001 8.39149 16.91 8.47036 16.9267 8.52678C16.948 8.59918 16.9446 8.65628 16.9152 8.72091C16.863 8.83538 16.8574 8.9615 16.891 9.26298C16.9785 10.0487 17.008 10.1316 17.274 10.3382C17.3781 10.4189 17.4696 10.4844 17.4774 10.4837ZM28.1631 18.5897C28.2177 18.5526 28.3191 18.4946 28.3884 18.4608C28.4578 18.4269 28.5183 18.392 28.523 18.3832C28.5276 18.3743 28.5469 18.3586 28.5657 18.3482C28.5845 18.3378 28.6382 18.3043 28.685 18.2738C28.8886 18.1408 29.5669 17.8444 29.6585 17.8482C29.683 17.8493 29.7155 17.835 29.7308 17.8166C29.7461 17.7982 29.8035 17.773 29.8584 17.7606C29.9734 17.7346 30.0077 17.7029 30.393 17.266L30.6644 16.9583L30.4595 17.0214C30.3467 17.0562 30.1326 17.1395 29.9835 17.2066C29.611 17.3744 29.6286 17.3647 29.1618 17.6601C28.7773 17.9033 28.6817 17.9684 28.6464 18.0108C28.6298 18.0308 28.5916 18.0572 28.5615 18.0693C28.5314 18.0814 28.4793 18.1188 28.4457 18.1524C28.2955 18.3027 28.203 18.3831 28.1557 18.4044C28.118 18.4215 28.0968 18.4551 28.0741 18.5338C28.0353 18.668 28.042 18.6722 28.1631 18.5897ZM32.4124 21.6294C32.6454 21.355 32.7632 21.2336 32.9254 21.101C33.0412 21.0063 33.2019 20.8651 33.2825 20.7874C33.363 20.7096 33.443 20.6414 33.4601 20.6357C33.4772 20.63 33.5028 20.6135 33.5171 20.599C33.5313 20.5845 33.6088 20.5209 33.6893 20.4576C33.8344 20.3435 33.9158 20.2696 34.116 20.0704C34.173 20.0137 34.3047 19.8887 34.4086 19.7928C34.8063 19.4258 34.9051 19.326 35.0858 19.109C35.1884 18.9859 35.2983 18.8642 35.3302 18.8387C35.3621 18.8131 35.4047 18.7775 35.4247 18.7594C35.4448 18.7414 35.4903 18.7108 35.526 18.6915C35.6619 18.618 36.4049 17.6089 36.3671 17.549C36.3443 17.5128 36.2327 17.6349 35.8151 18.1529C35.6936 18.3036 35.5726 18.4436 35.5462 18.4641C35.4978 18.5015 35.3219 18.7058 35.2286 18.8331C35.2009 18.8709 35.0913 18.9928 34.9851 19.1042C34.8788 19.2155 34.7461 19.3553 34.69 19.4148C34.634 19.4743 34.5312 19.5663 34.4615 19.6194C34.3918 19.6724 34.2811 19.7706 34.2156 19.8376C34.1055 19.9501 34.0092 20.0328 33.8046 20.1905C33.4848 20.4369 33.0098 20.879 32.8372 21.0908C32.7697 21.1736 32.653 21.2968 32.5778 21.3644C32.443 21.4857 32.0744 21.956 32.0984 21.976C32.1048 21.9813 32.2461 21.8253 32.4124 21.6294ZM18.6717 10.3164C18.6568 10.3905 18.6868 10.3961 18.8122 10.3427C18.9826 10.2701 19.0278 10.1755 18.9306 10.0948C18.8049 9.99042 18.7463 9.57738 18.813 9.26548C18.8414 9.1325 18.8291 8.93487 18.7923 8.9344C18.7679 8.93409 18.7482 8.88774 18.7319 8.79216C18.7186 8.71418 18.6998 8.65107 18.6901 8.65192C18.6804 8.65278 18.6782 8.67021 18.6852 8.69067C18.6938 8.71607 18.6772 8.74581 18.6327 8.78451C18.5968 8.81566 18.5685 8.851 18.5696 8.86304C18.5717 8.88406 18.5233 9.00076 18.4334 9.19192C18.3468 9.3759 18.3523 9.66343 18.4487 9.99374C18.525 10.2553 18.5429 10.2839 18.621 10.2687L18.6837 10.2564L18.6717 10.3164ZM22.7164 13.5935C23.178 13.2164 23.2856 13.1187 23.4285 12.9465C23.5096 12.8489 23.6128 12.7075 23.658 12.6322C23.733 12.5073 23.8171 12.3708 24.1143 11.8915C24.1711 11.8 24.239 11.6719 24.2654 11.6068C24.4795 11.0767 24.6147 10.6883 24.6086 10.6213C24.6064 10.5977 24.6132 10.5572 24.6237 10.5313C24.6592 10.4431 24.6115 10.4422 24.4082 10.5272L24.2809 10.5805L24.2135 10.8732C24.1765 11.0343 24.1286 11.1936 24.1073 11.2272C24.0859 11.2609 24.0542 11.3397 24.0368 11.4025C24.0085 11.5047 23.9545 11.6178 23.7623 11.9774C23.7302 12.0375 23.6871 12.1224 23.6664 12.166C23.6458 12.2095 23.5889 12.3028 23.5401 12.3733C23.4913 12.4437 23.4502 12.509 23.4488 12.5184C23.4475 12.5277 23.4057 12.595 23.3561 12.6679C23.3065 12.7408 23.2507 12.8353 23.2321 12.8779C23.2135 12.9205 23.0685 13.1078 22.9098 13.2941C22.6276 13.6253 22.5719 13.7114 22.7164 13.5935ZM28.4018 18.111C28.8156 17.7582 29.7111 17.1938 29.9418 17.1405C29.9581 17.1367 30.041 17.1061 30.1259 17.0725C30.2108 17.0389 30.3106 17.0073 30.3477 17.0022C30.3847 16.9972 30.4204 16.9866 30.4269 16.9787C30.4335 16.9708 30.5011 16.9526 30.5772 16.9382C30.7095 16.9132 30.7216 16.9052 30.8567 16.7549C31.1771 16.3982 32.5834 14.7194 32.6207 14.6491L32.6611 14.573L32.5809 14.5943C32.5368 14.606 32.4646 14.6238 32.4206 14.6339C32.3765 14.6439 32.3104 14.6673 32.2737 14.6857C32.2369 14.7042 32.1568 14.73 32.0956 14.743C32.0345 14.756 31.9345 14.7982 31.8734 14.8368C31.8044 14.8804 31.7468 14.8996 31.7211 14.8875C31.6934 14.8745 31.655 14.8897 31.6049 14.9335C31.5637 14.9695 31.4782 15.0246 31.4149 15.056C31.3516 15.0874 31.2836 15.128 31.2636 15.1461C31.1881 15.2149 30.8786 15.4322 30.7696 15.4931C30.7071 15.5279 30.6312 15.5785 30.6009 15.6054C30.5147 15.6821 30.3782 15.7809 30.2255 15.8773C30.1483 15.926 30.04 16.014 29.9849 16.0728C29.9297 16.1316 29.8539 16.1964 29.8164 16.2169C29.7565 16.2496 29.689 16.3116 29.5146 16.4938C29.4892 16.5204 29.463 16.5377 29.4564 16.5322C29.4261 16.5071 28.6198 17.5607 28.5485 17.7186C28.5257 17.7691 28.4712 17.8588 28.4275 17.9179C28.3837 17.977 28.3301 18.0532 28.3084 18.0872C28.2868 18.1213 28.2575 18.1652 28.2434 18.1849C28.1891 18.2607 28.2709 18.2225 28.4018 18.111ZM32.4491 21.0209C32.8012 20.6425 32.8952 20.5483 33.0174 20.4516C33.1121 20.3766 33.5569 20.0016 33.7621 19.8239C33.8183 19.7751 33.9622 19.6532 34.0817 19.5529C34.5442 19.1651 34.9828 18.6964 34.9915 18.5808C34.9949 18.536 35.0091 18.4733 35.023 18.4416C35.037 18.4098 35.0582 18.3479 35.0701 18.3042C35.1333 18.0726 35.6958 17.3013 36.011 17.014C36.1303 16.9053 36.1233 16.8723 35.9935 16.9317C35.9251 16.9631 35.8828 17.004 35.8048 17.1142C35.7495 17.1923 35.61 17.3767 35.4947 17.5239C35.3795 17.6711 35.2747 17.8229 35.2619 17.8611C35.2492 17.8994 35.2026 17.9743 35.1584 18.0276C35.1142 18.0808 35.0708 18.1591 35.0619 18.2013C35.0529 18.2436 35.0363 18.2894 35.025 18.303C35.0137 18.3166 34.9975 18.3719 34.989 18.4258C34.9663 18.5701 34.7654 18.8082 34.5585 18.9359C34.5153 18.9626 34.4356 19.0387 34.3813 19.1051C34.3258 19.173 34.2458 19.2447 34.1986 19.2689C34.1524 19.2926 34.0547 19.3617 33.9815 19.4224C33.9083 19.483 33.8262 19.5497 33.799 19.5705C33.7717 19.5913 33.7246 19.629 33.6942 19.6544C33.6638 19.6797 33.6296 19.7036 33.6183 19.7073C33.5827 19.7191 33.3783 19.9642 33.3733 20.0011C33.3706 20.0203 33.3521 20.0396 33.332 20.0439C33.2435 20.0627 32.4593 20.881 32.2089 21.2159C32.0246 21.4623 32.0811 21.4165 32.4491 21.0209ZM33.7561 22.193C33.807 22.1182 33.9617 21.9031 34.0999 21.7152C34.3593 21.3622 34.4052 21.2931 34.4922 21.1244C34.5203 21.0699 34.5977 20.9354 34.6642 20.8256C34.8982 20.4394 34.942 20.364 34.945 20.3419C34.9467 20.3297 34.984 20.2656 35.028 20.1995C35.0999 20.0911 35.116 20.0065 35.0722 19.9663C35.0593 19.9544 34.937 20.1284 34.9186 20.1848C34.912 20.2053 34.8795 20.2564 34.8465 20.2984C34.8135 20.3404 34.7847 20.3875 34.7824 20.403C34.7783 20.4314 34.7225 20.5305 34.625 20.6825C34.596 20.7277 34.4985 20.8621 34.4084 20.981C34.3183 21.1 34.2352 21.2247 34.2239 21.2582C34.2125 21.2917 34.134 21.4301 34.0495 21.5656C33.9649 21.7011 33.8597 21.8817 33.8158 21.9668C33.7718 22.052 33.7122 22.1515 33.6831 22.1879C33.6228 22.2637 33.6148 22.2887 33.6433 22.3124C33.6569 22.3236 33.694 22.2843 33.7561 22.193ZM20.1971 10.1603C20.1873 10.1174 20.2075 10.1071 20.3775 10.0688C20.4829 10.0451 20.5705 10.0146 20.5724 10.0012C20.5742 9.98776 20.6244 9.97533 20.684 9.97359C20.8187 9.96964 21.3771 9.97689 21.5913 9.98535C21.6791 9.98882 21.7791 9.99155 21.8135 9.99142C21.8479 9.9913 21.9684 10.0216 22.0812 10.0588C22.194 10.096 22.3006 10.1271 22.3182 10.1279C22.3357 10.1288 22.4203 10.165 22.506 10.2084C22.7205 10.3168 22.8827 10.3938 22.9274 10.4086C22.9965 10.4313 23.2919 10.5623 23.3675 10.6037C23.4313 10.6387 23.4367 10.6478 23.4045 10.6657C23.3838 10.6773 23.373 10.6917 23.3805 10.6977C23.3977 10.7115 23.7757 10.5753 23.7993 10.5469C23.8393 10.4987 24.2654 10.3661 24.3248 10.3833C24.3355 10.3864 24.3513 10.3804 24.3599 10.37C24.3685 10.3597 24.4102 10.3439 24.4527 10.335C24.6946 10.2842 24.4733 10.14 23.9426 10.0026C23.7957 9.96454 23.6623 9.92248 23.6462 9.9091C23.6301 9.89573 23.6109 9.89206 23.6035 9.90096C23.5961 9.90985 23.5213 9.89205 23.4374 9.8614C23.2968 9.81009 23.175 9.77354 22.8942 9.69837C22.836 9.68278 22.7791 9.66236 22.7679 9.653C22.7439 9.6331 22.4802 9.58292 22.2963 9.56323C22.0115 9.53276 22.0013 9.53041 22.0258 9.50093C22.0449 9.47795 22.1365 9.46984 22.3546 9.47185C22.4048 9.47231 22.7063 9.53893 22.7239 9.55342C22.7362 9.5636 23.1164 9.68188 23.6776 9.85007C23.7266 9.86477 23.8484 9.89631 23.9482 9.92014C24.0479 9.94398 24.1416 9.97348 24.1563 9.9857C24.1711 9.99792 24.189 10.0009 24.1961 9.99224C24.2243 9.95829 24.4 10.0532 24.5132 10.1635L24.6283 10.2757L24.7547 10.2335C24.8242 10.2103 24.9515 10.1863 25.0376 10.1802C25.1237 10.1741 25.1982 10.1646 25.2031 10.159C25.2248 10.1344 24.7802 9.90369 24.6001 9.84606C24.5218 9.82102 24.408 9.76496 24.3915 9.74335C24.3844 9.73395 24.3624 9.72595 24.3426 9.72557C24.3229 9.7252 24.206 9.68617 24.0828 9.63885C23.9596 9.59153 23.7826 9.53137 23.6895 9.50513C23.5964 9.47891 23.5083 9.44754 23.4937 9.43544C23.44 9.39081 23.4989 9.38035 23.6185 9.41327C23.6862 9.43189 23.774 9.45386 23.8137 9.46209C23.8533 9.47031 23.9016 9.49023 23.921 9.50635C23.9405 9.52247 23.9825 9.53815 24.0145 9.5412C24.0465 9.54425 24.1843 9.59349 24.3207 9.65063C24.4571 9.70776 24.6121 9.77113 24.6653 9.79145C24.7548 9.82565 24.9445 9.9182 25.1297 10.018L25.2067 10.0594L25.1636 9.97723C25.0829 9.82353 24.7232 9.55778 24.5177 9.50002C24.4575 9.48311 24.387 9.4516 24.361 9.42999C24.335 9.40839 24.3073 9.39846 24.2994 9.40794C24.2915 9.41741 24.2474 9.41023 24.2012 9.39198C24.1551 9.37372 24.1125 9.36473 24.1064 9.37199C24.1004 9.37925 24.0559 9.37867 24.0076 9.37071C23.9593 9.36274 23.888 9.35902 23.8493 9.36244C23.8106 9.36585 23.7208 9.35002 23.6497 9.32724C23.4968 9.27827 23.1473 9.26736 23.109 9.31035C23.0766 9.34676 22.9422 9.34913 22.7987 9.31582C22.7407 9.30234 22.677 9.29368 22.6571 9.29657C22.6371 9.29945 22.5421 9.29322 22.4457 9.28271C22.3494 9.2722 22.196 9.26719 22.1048 9.2716C22.0136 9.27599 21.9331 9.27478 21.9258 9.26891C21.9185 9.26306 21.8382 9.26488 21.7473 9.273C21.6565 9.28112 21.5551 9.28576 21.5221 9.28332C21.4329 9.27673 21.2776 9.3239 21.2543 9.36468C21.2418 9.38658 21.2145 9.39117 21.1837 9.37656C21.1259 9.34915 20.9042 9.38065 20.8328 9.42638C20.8062 9.44338 20.7785 9.4523 20.7711 9.44619C20.7094 9.39498 20.5394 9.44893 20.4821 9.53791C20.4435 9.59769 20.3971 9.64206 20.3536 9.66063C20.1808 9.73444 20.1713 9.76055 20.3209 9.75064C20.4374 9.74292 20.4672 9.73098 20.4942 9.68122C20.5233 9.62759 20.5796 9.6153 21.0171 9.56705C21.2867 9.53732 21.5281 9.49789 21.5534 9.47943C21.6423 9.41464 21.9094 9.49518 22.0855 9.63984C22.2335 9.76141 22.2449 9.76616 22.5948 9.85066C23.1261 9.97899 23.2816 10.0235 23.393 10.079C23.4483 10.1066 23.5666 10.1619 23.6559 10.202C23.8263 10.2783 23.97 10.3797 23.947 10.4073C23.9396 10.4162 23.8856 10.3933 23.827 10.3564C23.7684 10.3195 23.6802 10.2748 23.631 10.257C23.5818 10.2393 23.4942 10.2041 23.4365 10.1788C23.3787 10.1535 23.2335 10.1057 23.1138 10.0726C22.9941 10.0395 22.8954 10.005 22.8945 9.99599C22.8936 9.98695 22.8581 9.97639 22.8156 9.97252C22.773 9.96865 22.7023 9.95697 22.6585 9.94656C22.4332 9.89312 22.3369 9.87921 22.2471 9.88712C22.1928 9.89191 22.1381 9.88725 22.1255 9.87678C22.1018 9.85708 21.873 9.79547 21.841 9.80013C21.7958 9.80672 21.5558 9.7486 21.5493 9.72952C21.5453 9.71778 21.5268 9.71669 21.5081 9.7271C21.4894 9.73752 21.4572 9.73196 21.4364 9.71475C21.3717 9.66097 21.4474 9.6513 21.6584 9.68639C21.7692 9.70481 21.8952 9.72047 21.9384 9.72118L22.0169 9.72248L21.9481 9.69742C21.9103 9.68363 21.8565 9.65347 21.8287 9.63039C21.7728 9.584 21.6655 9.58963 20.9898 9.67438C20.8632 9.69026 20.7832 9.70425 20.812 9.70546C20.949 9.71125 20.9084 9.76933 20.7512 9.79246C20.3115 9.85714 20.0636 9.90457 19.9599 9.94384C19.8254 9.9948 19.7692 9.96985 19.8476 9.89396C19.8916 9.85134 19.8635 9.85378 19.6761 9.90882C19.4396 9.97827 19.4399 9.97811 19.3948 10.0803C19.3778 10.1186 19.3429 10.1565 19.3099 10.1723C19.0948 10.2754 19.2079 10.2985 19.7079 10.2535C20.1437 10.2144 20.2067 10.2024 20.1971 10.1603ZM23.2156 13.4636C23.2917 13.4405 23.3649 13.4084 23.3784 13.3922C23.3918 13.376 23.4246 13.354 23.4512 13.3433C23.4778 13.3326 23.5616 13.2576 23.6376 13.1767C23.7135 13.0958 23.8211 12.9822 23.8767 12.9242C23.9894 12.8067 24.3028 12.3608 24.4709 12.0787C24.8037 11.5203 25.0661 10.5834 24.923 10.4646C24.9049 10.4495 24.8884 10.42 24.8863 10.3989C24.8772 10.3051 24.7291 10.4154 24.7095 10.5305C24.661 10.8154 24.5751 11.1074 24.52 11.1743C24.5082 11.1887 24.4917 11.2324 24.4835 11.2713C24.4607 11.3791 24.3836 11.5621 24.3174 11.6654C24.2848 11.7164 24.2118 11.8475 24.1553 11.9567C24.0988 12.066 24.029 12.1926 24.0001 12.238C23.9713 12.2835 23.8975 12.3997 23.8361 12.4962C23.7747 12.5927 23.6944 12.7213 23.6577 12.7821C23.5825 12.9065 23.4426 13.0642 23.2137 13.2825C22.9952 13.4908 22.9956 13.5304 23.2156 13.4636ZM19.1707 10.0867C19.2687 10.0057 19.2774 9.93469 19.2062 9.79852L19.1436 9.67889L19.1063 9.74709C19.0857 9.78459 19.0666 9.84135 19.0637 9.87321C19.0567 9.9523 19.041 9.9656 18.9974 9.92943C18.945 9.88591 18.97 9.79915 19.0628 9.70235C19.1289 9.63343 19.1432 9.60037 19.1466 9.50883C19.1489 9.44811 19.154 9.39451 19.158 9.38972C19.162 9.38493 19.1754 9.29932 19.1879 9.19947C19.215 8.98262 19.2707 8.75572 19.3078 8.71103C19.3225 8.69327 19.3457 8.62418 19.3593 8.55749C19.3728 8.49081 19.4021 8.39338 19.4242 8.34099C19.4464 8.28859 19.4634 8.18916 19.4621 8.12003L19.4597 7.99434L19.3114 8.17091C19.1759 8.33219 19.0825 8.40754 19.0925 8.34751C19.1014 8.29446 19.3707 7.94578 19.4372 7.90117C19.4962 7.86163 19.5124 7.83334 19.5351 7.73003L19.5623 7.60626L19.4981 7.64182C19.4629 7.66138 19.4114 7.70384 19.3838 7.73618C19.2981 7.83654 19.1763 7.92532 19.1171 7.93053C19.0545 7.93605 19.0036 7.98575 18.9892 8.05535C18.9841 8.08029 18.956 8.13769 18.9269 8.1829C18.8471 8.3066 18.7874 8.59181 18.8055 8.762C18.8235 8.93074 18.8389 8.92708 18.9026 8.73891C18.9568 8.57902 19.0392 8.46845 19.0081 8.59739C18.9905 8.67 19.0017 8.65931 19.1493 8.46228C19.3116 8.24565 19.3973 8.17471 19.3755 8.27511C19.3694 8.30282 19.3272 8.37259 19.2816 8.43017C19.0302 8.7476 18.884 8.99827 18.9166 9.05597C18.937 9.09209 18.9613 9.06389 19.0624 8.887C19.1195 8.78714 19.1511 8.74883 19.1786 8.7464C19.2333 8.74158 19.2286 8.76965 19.1535 8.89662C18.934 9.26759 18.9012 9.33137 18.9132 9.3641C18.9204 9.38401 18.9132 9.4161 18.8972 9.43542C18.8418 9.50215 18.8808 9.80643 18.9635 9.95263C19.0702 10.1411 19.0896 10.1537 19.1707 10.0867ZM17.1973 8.26267C17.2267 8.22726 17.1888 8.0739 17.1515 8.07725C17.1182 8.08023 17.113 8.09685 17.1266 8.15607C17.1425 8.22512 17.1807 8.28267 17.1973 8.26267ZM22.9416 12.4619C22.9685 12.4295 23.1405 12.0968 23.1865 11.9883C23.3203 11.6724 23.3555 11.5632 23.422 11.257C23.461 11.0776 23.4951 10.9143 23.4979 10.894C23.5037 10.8515 23.3663 10.893 23.1534 10.998L23.0222 11.0627L23.064 11.142C23.1281 11.2635 23.076 11.7633 22.9884 11.8689C22.9783 11.881 22.9625 11.9521 22.9532 12.027C22.9438 12.1019 22.9262 12.1665 22.914 12.1705C22.8906 12.1783 22.8794 12.3218 22.8961 12.4008C22.9065 12.4502 22.9276 12.4787 22.9416 12.4619ZM24.4942 13.161C24.6438 12.9547 24.9236 12.6515 25.126 12.4763C25.3044 12.3219 25.3524 12.2542 25.2375 12.3191C25.077 12.4097 24.8246 12.6051 24.7991 12.6585C24.7855 12.6871 24.706 12.7734 24.6223 12.8505C24.4687 12.992 24.3517 13.1605 24.2478 13.3902L24.2063 13.4819L24.2771 13.4224C24.316 13.3897 24.4137 13.2721 24.4942 13.161ZM24.7382 13.7482C24.7762 13.7025 24.7899 13.6708 24.7727 13.6683C24.7571 13.6661 24.7203 13.6932 24.691 13.7285C24.6616 13.7638 24.6461 13.7998 24.6565 13.8084C24.6668 13.817 24.7036 13.7899 24.7382 13.7482ZM31.7024 19.3149C31.7894 19.2101 31.8771 19.209 31.8872 19.3126C31.8933 19.3757 31.937 19.3352 32.4011 18.8357C32.483 18.7475 32.631 18.5936 32.73 18.4936C32.829 18.3936 32.9418 18.2761 32.9805 18.2325C33.0458 18.1592 33.2168 17.7837 33.2686 17.5999C33.2805 17.5577 33.3258 17.4249 33.3693 17.3049C33.4127 17.1848 33.4478 17.064 33.4472 17.0363C33.4466 17.0086 33.4594 16.9502 33.4756 16.9064C33.5067 16.8225 33.5805 16.3039 33.5703 16.2414C33.563 16.197 33.581 16.056 33.5962 16.0377C33.6023 16.0304 33.612 16.0617 33.6179 16.1073C33.6327 16.2225 33.6542 16.2086 33.6822 16.0657C33.6953 15.9987 33.7175 15.9038 33.7315 15.8547C33.7456 15.8056 33.7597 15.7464 33.7629 15.723C33.7662 15.6997 33.7796 15.6256 33.7927 15.5584C33.8403 15.3146 33.889 14.954 33.9093 14.6939C33.9208 14.5477 33.933 14.4073 33.9366 14.382C33.951 14.2795 33.952 13.9283 33.9385 13.7315C33.9305 13.6137 33.9364 13.5324 33.952 13.5454C33.9816 13.5699 34.0364 13.936 34.0145 13.9624C34.0074 13.9709 34.0056 14.0271 34.0105 14.0872C34.0241 14.2541 33.9791 14.8611 33.9367 15.0824C33.896 15.295 33.8928 15.3162 33.893 15.3687C33.8931 15.3958 33.8839 15.4333 33.8724 15.4521C33.861 15.4709 33.855 15.4986 33.8591 15.5136C33.8713 15.5584 33.6675 16.4878 33.6375 16.5244C33.6273 16.5368 33.6082 16.6203 33.595 16.71C33.5818 16.7996 33.5561 16.9104 33.538 16.956C33.5198 17.0016 33.5047 17.0601 33.5045 17.086C33.5043 17.1118 33.4814 17.1993 33.4536 17.2803C33.4258 17.3614 33.3966 17.4507 33.3886 17.4788C33.3652 17.5611 33.2798 17.7865 33.2276 17.9038C33.1675 18.0386 33.1676 18.0386 33.3414 17.8804C33.5135 17.7238 33.6186 17.6728 33.6576 17.7271C33.6874 17.7684 33.683 17.7703 33.9787 17.5901C34.2163 17.4453 34.3506 17.3852 34.4229 17.3915C34.4835 17.3967 34.5537 17.1935 34.5542 17.0111C34.5542 16.9851 34.5848 16.8614 34.6221 16.7362C34.7872 16.1815 34.8259 15.533 34.7101 15.2596C34.6462 15.1087 34.637 15.0922 34.599 15.0606C34.5413 15.0127 34.4953 15.1843 34.5229 15.3445C34.5247 15.3546 34.5046 15.4515 34.4783 15.5598C34.452 15.6681 34.423 15.8002 34.4139 15.8534C34.3903 15.9911 34.3517 16.1093 34.2884 16.2383C34.2582 16.2999 34.2207 16.3895 34.2051 16.4373C34.1896 16.4851 34.1452 16.5796 34.1065 16.6473C34.0678 16.715 34.0316 16.8196 34.026 16.8797C34.0205 16.9397 34.0019 17.0059 33.9848 17.0267C33.9676 17.0474 33.9463 17.1009 33.9373 17.1455C33.9159 17.2516 33.8703 17.3581 33.8526 17.3434C33.8449 17.337 33.8493 17.2874 33.8624 17.2332C33.9018 17.07 33.8275 17.1595 33.7308 17.3917C33.7148 17.4299 33.697 17.4401 33.6653 17.4293C33.5832 17.4012 33.6242 17.2741 33.8995 16.704C34.0555 16.3811 34.0846 16.2903 34.1183 16.0229C34.1309 15.9231 34.1443 15.8377 34.148 15.8332C34.1518 15.8286 34.1525 15.7846 34.1496 15.7354C34.1467 15.6862 34.1496 15.6396 34.1561 15.6318C34.1841 15.5981 34.1987 15.6537 34.2016 15.8046C34.2054 16.0069 34.2248 16.0077 34.2689 15.8074C34.2878 15.7214 34.316 15.5989 34.3315 15.5351C34.3471 15.4714 34.3629 15.3424 34.3665 15.2487C34.3702 15.1549 34.3806 15.0275 34.3896 14.9656C34.3987 14.9037 34.3954 14.7519 34.3823 14.6283C34.3692 14.5046 34.36 14.3687 34.3619 14.3263C34.3673 14.2015 34.2423 13.5503 34.1907 13.4346C34.1074 13.2479 34.0913 13.2415 33.9788 13.3501C33.9246 13.4024 33.8658 13.45 33.8481 13.4559C33.7676 13.4826 33.5763 13.8062 33.5921 13.889C33.6278 14.0768 33.6391 14.355 33.6194 14.5626C33.6156 14.6029 33.6101 14.6906 33.6072 14.7576C33.6043 14.8246 33.5971 14.8967 33.5913 14.9179C33.5854 14.939 33.5782 15.0003 33.5754 15.0541C33.5726 15.1078 33.5551 15.2099 33.5366 15.2808C33.518 15.3517 33.5029 15.4287 33.503 15.4517C33.5034 15.5349 33.3943 16.0029 33.3582 16.0731C33.3378 16.1126 33.3284 16.1509 33.3371 16.1581C33.3458 16.1654 33.3393 16.2066 33.3225 16.2496C33.3057 16.2927 33.2887 16.4007 33.2848 16.4897C33.2808 16.5786 33.2708 16.6595 33.2626 16.6694C33.2544 16.6793 33.2456 16.731 33.2432 16.7842C33.239 16.8765 33.123 17.3742 33.0989 17.4032C33.0926 17.4108 33.0731 17.4763 33.0556 17.5488C32.9964 17.7938 32.7544 18.3244 32.7162 18.2928C32.702 18.281 32.7741 18.0823 32.8614 17.8927C32.8729 17.8676 32.8922 17.8126 32.9041 17.7704C32.916 17.7283 32.9531 17.61 32.9864 17.5075C33.0775 17.2277 33.1172 17.0647 33.1686 16.7596C33.221 16.4487 33.3694 15.7745 33.3912 15.748C33.399 15.7385 33.4047 15.7078 33.4039 15.6797C33.4031 15.6516 33.4189 15.543 33.4392 15.4383C33.4594 15.3337 33.4871 15.1386 33.5008 15.005C33.5145 14.8713 33.5307 14.7144 33.5369 14.6563C33.543 14.5982 33.5463 14.5421 33.5441 14.5316C33.5419 14.5211 33.5424 14.4506 33.5452 14.3748C33.5514 14.2101 33.538 13.9903 33.5208 13.976C33.5053 13.9631 33.1624 14.3138 33.087 14.4197C33.0398 14.486 33.0338 14.5316 33.0497 14.7042C33.0672 14.8953 33.066 15.1049 33.0466 15.2271C33.0421 15.2555 33.0397 15.3055 33.0413 15.3383C33.0428 15.3711 33.0356 15.4472 33.0254 15.5074C32.9973 15.6716 32.9795 15.7932 32.9675 15.9035C32.9616 15.9581 32.948 16.0133 32.9373 16.0262C32.9265 16.0391 32.9196 16.0683 32.9218 16.091C32.9299 16.1742 32.8405 16.6083 32.7765 16.7969C32.7604 16.8442 32.7528 16.8989 32.7595 16.9184C32.7663 16.9379 32.7523 16.976 32.7284 17.003L32.6851 17.0522L32.7088 16.9851C32.7218 16.9482 32.725 16.9118 32.7158 16.9042C32.7066 16.8965 32.7154 16.8198 32.7355 16.7337C32.7556 16.6476 32.7862 16.4895 32.8035 16.3824C32.8209 16.2753 32.8397 16.182 32.8455 16.1751C32.8512 16.1682 32.8587 16.1204 32.8621 16.0689C32.8655 16.0173 32.8723 15.953 32.8772 15.926C32.973 15.4021 33.0116 14.6062 32.941 14.6124C32.9308 14.6133 32.8623 14.6885 32.7888 14.7795C32.7153 14.8705 32.6172 14.9916 32.571 15.0486C32.4882 15.1506 32.4876 15.1539 32.5331 15.2482C32.6357 15.461 32.6165 16.3367 32.4987 16.8215C32.4782 16.9058 32.4553 17.0199 32.4478 17.075C32.4403 17.13 32.4263 17.1685 32.4167 17.1606C32.3913 17.1395 32.3922 17.0495 32.4189 16.9137C32.4318 16.8482 32.4449 16.7739 32.4479 16.7484C32.4671 16.589 32.5054 16.2317 32.5078 16.1887C32.5094 16.1604 32.5166 16.0614 32.5237 15.9685C32.5458 15.6788 32.4865 15.2407 32.4259 15.2462C32.4112 15.2476 32.281 15.3887 32.2103 15.4799C32.18 15.5191 32.1811 15.5864 32.2149 15.7676C32.2391 15.8978 32.2528 16.0488 32.2453 16.1033C32.2378 16.1578 32.2321 16.2196 32.2327 16.2408C32.2413 16.5391 32.2276 16.8283 32.1995 16.9405C32.1835 17.0047 32.1929 17.0457 32.2383 17.1097C32.391 17.3249 32.4498 17.7149 32.3662 17.9575C32.3434 18.0238 32.3243 18.0937 32.3238 18.1129C32.3219 18.1848 32.1401 18.9693 32.1118 19.0272C32.0595 19.1345 32.0303 19.0841 32.061 18.9395C32.1707 18.4213 32.1969 18.2748 32.1969 18.1776C32.1968 18.1173 32.2049 18.0582 32.2147 18.0464C32.2245 18.0346 32.228 18.0017 32.2225 17.9733C32.2169 17.9449 32.2253 17.8755 32.241 17.8192C32.2746 17.6984 32.236 17.3576 32.1838 17.3142C32.1375 17.2758 32.1432 17.2645 32.0933 17.4952C32.0698 17.6038 32.0226 17.783 31.9885 17.8934C31.9543 18.0039 31.9201 18.1518 31.9125 18.2222C31.9049 18.2927 31.8927 18.3574 31.8855 18.3661C31.8783 18.3748 31.8659 18.4331 31.858 18.4956C31.8501 18.5581 31.8379 18.6045 31.831 18.5988C31.8241 18.593 31.8197 18.6149 31.8212 18.6474C31.8227 18.68 31.7995 18.7862 31.7695 18.8835C31.7395 18.9808 31.7043 19.0999 31.6912 19.1482C31.6782 19.1964 31.6572 19.2594 31.6447 19.2881C31.6124 19.3624 31.6488 19.3794 31.7024 19.3149ZM25.1573 12.7178C25.411 12.4382 25.6165 12.2078 25.614 12.2057C25.5966 12.1913 25.4283 12.3025 25.4057 12.3434C25.3903 12.3713 25.2811 12.4865 25.1632 12.5995C24.8219 12.9263 24.6407 13.1306 24.5818 13.2551L24.529 13.3667L24.6125 13.2964C24.6585 13.2577 24.9036 12.9974 25.1573 12.7178ZM25.1209 13.5372C25.1162 13.4887 25.0431 13.5451 25.0182 13.6164L24.9916 13.6924L25.0573 13.6254C25.0934 13.5886 25.122 13.5489 25.1209 13.5372ZM25.569 12.837C25.9687 12.3678 26.1595 12.1041 26.1523 12.0305C26.1503 12.0098 26.0498 12.1123 26.0292 12.1561C26.0233 12.1686 25.8538 12.3828 25.6525 12.6321C25.4512 12.8814 25.2802 13.0943 25.2724 13.1053C25.2364 13.1563 25.1184 13.2655 25.0885 13.2754C25.0702 13.2814 25.0504 13.3102 25.0446 13.3393C25.0388 13.3684 25.0015 13.4336 24.9618 13.4841C24.7592 13.7422 25.1786 13.2952 25.569 12.837ZM28.4846 15.6738C28.628 15.529 28.7497 15.429 28.885 15.3448C28.9919 15.2782 29.1234 15.1826 29.1772 15.1323C29.231 15.0819 29.3757 14.9871 29.4987 14.9216C29.806 14.7579 29.9943 14.6258 29.9896 14.5773C29.9872 14.5525 30.0957 14.4056 30.3045 14.1509C30.4796 13.9372 30.7128 13.6452 30.8225 13.5021C31.3529 12.8103 32.1157 12.15 32.785 11.8032C33.5364 11.4137 33.8347 11.2835 34.1528 11.206C34.2831 11.1742 34.399 11.1511 34.4102 11.1546C34.4215 11.1582 34.4395 11.1505 34.4503 11.1375C34.4675 11.1168 34.9053 11.0302 35.0047 11.0278C35.025 11.0273 35.0863 11.0143 35.1409 10.9989C35.2479 10.9686 35.2897 10.9617 35.6164 10.9205C35.7343 10.9056 35.8436 10.8779 35.8593 10.859C35.875 10.8401 35.9086 10.8343 35.934 10.8462C35.9893 10.8722 36.0228 10.8469 36.358 10.5267C36.4308 10.4571 36.5117 10.3823 36.5376 10.3604C36.6306 10.282 36.8518 10.0534 36.8423 10.0455C36.8369 10.0411 36.8124 10.0385 36.7878 10.0397C36.7323 10.0425 36.5559 10.0285 36.5463 10.0206C36.5424 10.0174 36.4237 10.0217 36.2824 10.0302C36.1411 10.0387 35.9046 10.0517 35.7569 10.0592C35.4047 10.077 34.9181 10.117 34.6378 10.1512C34.4119 10.1788 34.3215 10.1585 34.5117 10.1228C34.5678 10.1123 34.6761 10.0916 34.7523 10.0768C34.9301 10.0424 35.1651 10.0221 35.5098 10.0116C35.6608 10.0069 35.9091 9.99255 36.0615 9.97961C36.359 9.95433 36.7369 9.95799 36.7712 9.98649C36.7828 9.9961 36.7992 9.99555 36.8077 9.98528C36.8163 9.97501 36.8394 9.98005 36.8592 9.99648C36.8892 10.0214 36.9176 10.007 37.0304 9.9099C37.1048 9.84585 37.1784 9.78273 37.194 9.76964C37.2095 9.75655 37.299 9.67464 37.3927 9.58764C37.4864 9.50062 37.6237 9.38744 37.6977 9.3361C37.7717 9.28477 37.8991 9.19177 37.9807 9.12942C38.0623 9.06707 38.169 8.99193 38.2178 8.96242C38.3078 8.908 38.3837 8.83308 38.3649 8.81741C38.341 8.79761 38.2016 8.7763 38.1535 8.7851C38.1249 8.79032 38.0777 8.78812 38.0485 8.78019C38.0193 8.77227 37.9691 8.76128 37.9368 8.75577C37.8017 8.7327 36.5929 8.83456 36.4313 8.88261C36.3691 8.90111 36.3115 8.91061 36.3032 8.90373C36.2949 8.89685 36.271 8.90215 36.25 8.91551C36.2291 8.92886 36.1631 8.94633 36.1034 8.95434C36.0437 8.96234 35.9534 8.98643 35.9028 9.00787C35.8521 9.02931 35.746 9.05408 35.6669 9.0629C35.5878 9.07172 35.5206 9.08195 35.5176 9.08562C35.5145 9.08929 35.434 9.11763 35.3386 9.14859C35.1232 9.21847 34.7649 9.37873 34.7297 9.42097C34.7152 9.4383 34.6466 9.46923 34.5772 9.48971C34.5079 9.51018 34.4381 9.5425 34.4222 9.56152C34.4064 9.58054 34.3534 9.60312 34.3046 9.6117C34.2503 9.62124 34.1716 9.66466 34.1019 9.72365C34.0392 9.77665 33.9527 9.83704 33.9096 9.85785C33.6362 9.99002 33.2157 10.461 33.443 10.3805C33.5169 10.3544 33.588 10.3615 33.5378 10.39C33.4398 10.4458 33.162 10.5534 33.1468 10.5415C33.1362 10.5331 33.0882 10.5392 33.0401 10.555C32.992 10.5707 32.9202 10.5926 32.8806 10.6037C32.7927 10.6283 32.7926 10.6283 32.6302 10.7281C32.5581 10.7724 32.4305 10.8393 32.3466 10.8767C32.0758 10.9975 31.923 11.084 31.8307 11.1685C31.7811 11.2141 31.7118 11.2701 31.6769 11.2932C31.6419 11.3162 31.5326 11.4242 31.4339 11.5331C31.3353 11.6421 31.1796 11.8039 31.088 11.8927C30.7593 12.2115 30.5829 12.445 30.5783 12.5673C30.5742 12.6791 30.4805 12.8489 30.4003 12.8899C30.3772 12.9018 30.345 12.9218 30.3288 12.9344C30.3127 12.947 30.1988 13.037 30.0756 13.1343C29.9525 13.2316 29.7965 13.3505 29.7289 13.3985C29.4907 13.5677 29.4071 13.6629 29.4153 13.756C29.4192 13.8012 29.4189 13.8687 29.4147 13.906C29.4071 13.9717 29.414 13.9689 29.6195 13.8237C30.1556 13.445 30.2804 13.365 30.485 13.2692C30.6053 13.2129 30.6988 13.1809 30.6928 13.1982C30.6868 13.2154 30.6545 13.2383 30.6211 13.2491C30.5878 13.2599 30.5179 13.2972 30.4659 13.3321C30.4139 13.367 30.3139 13.4323 30.2437 13.4771C30.1735 13.522 30.1042 13.5729 30.0898 13.5903C30.0754 13.6076 30.0172 13.6524 29.9605 13.6898C29.73 13.8417 29.4904 14.0364 29.3487 14.187C29.2662 14.2747 29.1845 14.3494 29.1672 14.3531C29.1499 14.3568 29.0676 14.4304 28.9844 14.5168C28.9012 14.6032 28.8204 14.6754 28.8049 14.6773C28.7894 14.6792 28.7627 14.7128 28.7456 14.7521C28.7285 14.7914 28.6827 14.8512 28.6439 14.8851C28.5653 14.9537 28.5521 15.0241 28.6088 15.0712C28.6596 15.1134 28.6087 15.2551 28.4744 15.445C28.4116 15.5337 28.3515 15.6319 28.3408 15.6631C28.3301 15.6944 28.3014 15.744 28.277 15.7733C28.0956 15.9917 28.2369 15.924 28.4846 15.6738ZM24.7539 12.542C24.8816 12.426 25.0262 12.3021 25.0752 12.2669C25.1243 12.2315 25.1635 12.194 25.1625 12.1835C25.1539 12.0952 24.8127 12.3552 24.5981 12.6136C24.4335 12.8118 24.4812 12.7899 24.7539 12.542ZM24.8068 12.0532C24.9288 11.9087 24.9323 11.9008 24.9025 11.8396C24.8605 11.7536 24.8576 11.7557 24.7585 11.94C24.7107 12.0288 24.66 12.1132 24.6459 12.1275C24.6317 12.1417 24.5803 12.2055 24.5316 12.2692L24.4431 12.385L24.5616 12.2941C24.6268 12.2441 24.7371 12.1357 24.8068 12.0532ZM25.8135 13.3253C25.9913 13.3088 26.1126 13.2316 25.9603 13.2319C25.9063 13.232 25.8543 13.2256 25.8448 13.2177C25.8352 13.2097 25.8064 13.2284 25.7809 13.2593C25.7269 13.3242 25.7312 13.333 25.8135 13.3253ZM26.0443 13.1201C26.1024 13.1104 26.2872 13.0686 26.455 13.0274C26.6229 12.9862 26.9839 12.9182 27.2573 12.8762C27.5935 12.8247 27.758 12.7877 27.7655 12.7619C27.7716 12.7409 27.7893 12.6879 27.8049 12.6441C27.8311 12.5701 27.7539 12.5316 27.7028 12.5931C27.674 12.6278 27.4257 12.6704 27.3644 12.6511C27.3252 12.6389 27.2766 12.6395 27.2563 12.6524C27.2361 12.6653 27.1913 12.6799 27.1568 12.6848C27.1223 12.6897 27.0424 12.7146 26.9792 12.7401C26.916 12.7656 26.8436 12.7906 26.8184 12.7957C26.7931 12.8007 26.7218 12.8267 26.6598 12.8533C26.5035 12.9206 26.5094 12.9186 26.3099 12.9724C26.2115 12.9989 26.0951 13.0141 26.0513 13.0062C25.9764 12.9926 25.9036 13.0366 25.909 13.0922C25.913 13.1332 25.9371 13.1382 26.0443 13.1201ZM19.4832 7.52358C19.5667 7.44527 19.5924 7.37151 19.5388 7.36377C19.5046 7.35884 19.4082 7.46489 19.369 7.55044C19.3351 7.62469 19.3889 7.61202 19.4832 7.52358ZM25.2336 11.8741C25.2857 11.848 25.3367 11.8176 25.3468 11.8066C25.357 11.7957 25.4306 11.7574 25.5104 11.7216C25.7417 11.6179 25.7957 11.5887 25.8416 11.5429C25.9407 11.444 26.213 10.984 26.2486 10.8555C26.2565 10.8273 26.2953 10.7176 26.3349 10.6117C26.4106 10.4095 26.4417 10.2209 26.4023 10.2033C26.3895 10.1976 26.3228 10.1918 26.2541 10.1904L26.1291 10.1878L26.1464 10.2813C26.1658 10.3859 26.1322 10.6405 26.0893 10.7147C26.0739 10.7413 26.056 10.78 26.0496 10.8006C26.0079 10.934 25.8793 11.1495 25.7088 11.3715C25.4728 11.6789 25.4428 11.6617 25.6558 11.3413C26.1144 10.6515 26.2085 10.099 25.8499 10.201C25.7837 10.2198 25.7105 10.2374 25.6872 10.2402C25.6538 10.2441 25.6422 10.2787 25.6325 10.4032C25.6257 10.4901 25.605 10.611 25.5864 10.6718C25.5679 10.7326 25.54 10.8286 25.5244 10.8851C25.474 11.0683 25.3324 11.3841 25.2539 11.4885C25.2118 11.5445 25.1821 11.5944 25.188 11.5994C25.1939 11.6044 25.1428 11.6997 25.0744 11.8111L24.9501 12.0136L25.0444 11.9676C25.0964 11.9423 25.1815 11.9002 25.2336 11.8741ZM21.9661 9.17319C22.023 9.16657 22.2056 9.16859 22.3719 9.17767C22.5381 9.18675 22.6982 9.18372 22.7276 9.17093C22.757 9.15815 22.8465 9.15849 22.9265 9.17169C23.0066 9.1849 23.1768 9.18952 23.3049 9.18196C23.4444 9.17372 23.6105 9.18597 23.7189 9.21251C23.8783 9.25148 24.2765 9.29672 24.2474 9.27254C24.221 9.25065 23.9241 9.17892 23.8412 9.17441C23.6713 9.16517 23.38 9.08705 23.3642 9.04652C23.3532 9.01824 23.3989 9.01773 23.5386 9.04455C23.6427 9.06455 23.7923 9.08949 23.8712 9.09998C23.95 9.11048 24.1263 9.1454 24.2629 9.17759C24.5413 9.24318 24.575 9.22034 24.4279 9.06583C24.3179 8.95033 24.0778 8.89699 23.76 8.91747C23.6035 8.92755 23.5386 8.92165 23.5506 8.89842C23.5794 8.84307 23.9288 8.80131 24.066 8.8368C24.1344 8.85448 24.1828 8.85647 24.1736 8.84122C24.1348 8.77715 24.2019 8.76763 24.2948 8.82401C24.3484 8.85657 24.4765 8.90502 24.5794 8.93169C25.1377 9.07639 25.9226 9.49823 26.2483 9.82859C26.3875 9.96983 26.3886 9.97045 26.515 9.97685C26.5849 9.98039 26.6999 10.0034 26.7706 10.0279C26.9427 10.0876 26.9446 10.0711 26.7839 9.91437C26.4484 9.587 26.2488 9.47207 26.2397 9.6011C26.2271 9.78054 26.188 9.75998 26.1369 9.54719L26.0989 9.38848L25.9681 9.32539C25.8142 9.25119 25.4872 9.04672 25.4849 9.02333C25.4821 8.99462 25.5963 9.04598 25.7762 9.1544C25.9175 9.23956 25.9554 9.25337 25.9717 9.22556C25.9875 9.19858 26.0056 9.20381 26.0548 9.24951C26.0894 9.28166 26.1949 9.37022 26.2893 9.44632C26.3836 9.52242 26.5651 9.67046 26.6925 9.77531C26.8199 9.88016 26.9294 9.95964 26.9358 9.95194C26.9653 9.91636 26.8387 9.64762 26.7342 9.52387C26.7165 9.50297 26.6989 9.48102 26.6951 9.47509C26.6838 9.45754 26.4768 9.29712 26.4321 9.2712C26.3857 9.24433 26.1033 9.05453 26.0816 9.03564C26.0738 9.02891 26.0469 9.01911 26.0217 9.01385C25.994 9.0081 25.9772 8.99385 25.9794 8.978C25.9814 8.96353 26.0402 8.98223 26.1101 9.01956C26.18 9.05688 26.2703 9.10356 26.3107 9.12331C26.3512 9.14305 26.4836 9.24406 26.605 9.34779C26.7766 9.49439 26.823 9.52601 26.8138 9.48982C26.8072 9.46421 26.7932 9.44201 26.7826 9.44048C26.772 9.43895 26.7478 9.4105 26.7289 9.37726C26.5733 9.10389 26.1225 8.77297 25.8387 8.7239C25.7775 8.71331 25.6882 8.69573 25.6404 8.68484C25.5925 8.67395 25.5477 8.67188 25.5407 8.68025C25.5338 8.68862 25.5153 8.68481 25.4996 8.67179C25.4686 8.64607 25.3626 8.62125 25.3241 8.63067C25.3109 8.63389 25.2866 8.62867 25.27 8.61907C25.1206 8.5323 24.7493 8.51699 24.7057 8.59581C24.6668 8.66594 24.4881 8.71524 24.4344 8.67064C24.4219 8.66027 24.3808 8.65808 24.343 8.66577C24.3053 8.67346 24.228 8.66916 24.1713 8.6562C24.1146 8.64325 24.0169 8.63306 23.9541 8.63356C23.8505 8.63438 23.7978 8.63337 23.5487 8.62581C23.4864 8.62392 23.4719 8.632 23.475 8.66674C23.4771 8.69055 23.4526 8.74154 23.4206 8.78006C23.3887 8.81858 23.3463 8.84801 23.3265 8.84547C23.3068 8.84293 23.2471 8.85938 23.194 8.88202C23.1409 8.90467 23.0618 8.92418 23.0183 8.92537C22.9747 8.92657 22.8531 8.93427 22.7481 8.94249C22.6431 8.95071 22.4947 8.95937 22.4183 8.96173C22.3419 8.96408 22.2735 8.97312 22.2663 8.9818C22.2591 8.99049 22.2125 8.98704 22.1626 8.97414C22.0513 8.94531 22.0564 8.94337 21.9316 9.0611C21.8147 9.17135 21.8204 9.19013 21.9661 9.17319ZM25.0519 11.6996C25.1222 11.5846 25.3671 11.1158 25.3823 11.0668C25.3887 11.0462 25.3959 11.0237 25.3982 11.017C25.4005 11.0102 25.4157 10.966 25.4319 10.9187C25.5721 10.5093 25.5788 10.2504 25.4487 10.2737C25.4038 10.2818 25.3315 10.2837 25.2881 10.278C25.1835 10.2644 25.1736 10.2811 25.1511 10.509C25.1406 10.616 25.1093 10.757 25.0815 10.8223C25.0537 10.8876 25.0307 10.9567 25.0303 10.9758C25.0299 10.9949 25.014 11.0497 24.995 11.0976C24.9759 11.1454 24.9693 11.2133 24.9803 11.2485C24.9912 11.2836 24.9856 11.376 24.9678 11.4536C24.9423 11.5645 24.9544 11.7156 24.9941 11.7826C24.996 11.7858 25.022 11.7485 25.0519 11.6996ZM26.4153 12.6345C26.436 12.6344 26.5269 12.6105 26.6172 12.5813C26.7074 12.5522 26.8624 12.5105 26.9616 12.4887C27.0607 12.4669 27.2239 12.4255 27.3242 12.3968C27.4246 12.3681 27.5469 12.3415 27.5961 12.3377C27.6453 12.3339 27.7041 12.3205 27.7268 12.3078C27.7495 12.2952 27.7886 12.2945 27.8138 12.3063C27.8726 12.334 27.8739 12.3318 27.8978 12.1635C27.9154 12.0399 27.849 11.7306 27.8003 11.709C27.7939 11.7062 27.7757 11.6657 27.7598 11.6191C27.7165 11.492 27.6613 11.4534 27.6679 11.555C27.6733 11.6372 27.641 11.6957 27.5941 11.6889C27.5752 11.6862 27.5619 11.7029 27.5548 11.7386C27.5488 11.7682 27.4709 11.8837 27.3816 11.9952C27.2113 12.2078 27.1532 12.2516 26.9551 12.3171C26.8993 12.3355 26.846 12.3598 26.8367 12.3711C26.8273 12.3824 26.739 12.4052 26.6406 12.4218C26.3182 12.4763 26.2807 12.4919 26.2434 12.5876L26.2108 12.6714L26.2941 12.6531C26.34 12.643 26.3945 12.6346 26.4153 12.6345ZM33.1338 18.3024C33.1826 18.2155 33.1665 18.2034 33.1033 18.2796C33.0684 18.3215 33.0569 18.3508 33.0742 18.3533C33.0899 18.3555 33.1167 18.3326 33.1338 18.3024ZM35.1869 19.5155C35.2384 19.4295 35.2619 19.3689 35.2459 19.3633C35.2313 19.3581 35.2129 19.3681 35.2051 19.3854C35.1973 19.4028 35.1711 19.4574 35.147 19.5068C35.046 19.7135 35.0657 19.7178 35.1869 19.5155ZM25.9374 11.8303C25.9424 11.8155 25.9206 11.8175 25.8889 11.8346C25.8573 11.8517 25.8296 11.8773 25.8274 11.8914C25.8224 11.9238 25.9252 11.8667 25.9374 11.8303ZM26.4844 11.9962C26.5717 11.8765 26.6534 11.8069 26.6804 11.8293C26.6899 11.8372 26.6847 11.8577 26.6687 11.8748C26.5272 12.0271 26.4972 12.218 26.6205 12.1818C26.6552 12.1716 26.7183 12.1579 26.7607 12.1514C26.8549 12.137 26.8599 12.1316 26.8468 12.0571C26.8354 11.9926 26.9588 11.7944 27.1351 11.594C27.2706 11.44 27.2642 11.5496 27.1281 11.7134C27.0756 11.7766 27.0202 11.8592 27.0049 11.8969C26.9897 11.9346 26.962 11.9952 26.9433 12.0317C26.8638 12.187 27.201 11.9443 27.4113 11.6948C27.633 11.4318 27.6394 11.4033 27.5068 11.264L27.4196 11.1725L27.3083 11.229C27.2471 11.26 27.1875 11.297 27.1758 11.311C27.1641 11.3251 27.064 11.3935 26.9534 11.463C26.8428 11.5324 26.6701 11.6549 26.5695 11.7352L26.3867 11.8811L26.3959 11.993C26.401 12.0545 26.4051 12.1049 26.405 12.1051C26.4049 12.1052 26.4406 12.0562 26.4844 11.9962ZM26.1135 11.5579C26.1486 11.5382 26.1717 11.5113 26.1719 11.49C26.1723 11.4575 26.2732 11.2996 26.4504 11.0546C26.4896 11.0004 26.532 10.9247 26.5447 10.8863C26.5574 10.848 26.5794 10.8024 26.5936 10.785C26.6621 10.7014 26.7867 10.3085 26.7534 10.2809C26.7025 10.2386 26.5576 10.2156 26.5326 10.2457C26.4803 10.309 26.4754 10.4602 26.5245 10.5009C26.5834 10.5498 26.5661 10.7395 26.5022 10.745C26.4711 10.7477 26.4623 10.7306 26.4642 10.6717C26.4673 10.5795 26.4364 10.6094 26.3864 10.747C26.3674 10.7995 26.3435 10.8452 26.3334 10.8485C26.3232 10.8519 26.3034 10.9003 26.2894 10.9561C26.2634 11.0595 26.2255 11.1361 26.1191 11.3001C25.9384 11.5789 25.9433 11.5671 26.0016 11.5792C26.0312 11.5854 26.0816 11.5758 26.1135 11.5579ZM26.33 11.5778C26.5498 11.4399 26.7964 11.0397 26.8777 10.6891C26.9064 10.5649 26.9475 10.5376 26.9509 10.6405C26.9546 10.7505 26.8772 10.9815 26.7914 11.1169C26.7086 11.2476 26.735 11.2642 26.8914 11.1801C27.0222 11.1097 27.0539 11.0677 27.2035 10.7663C27.2652 10.6422 27.2289 10.5605 27.0814 10.4915C27.0416 10.4729 26.9773 10.4383 26.9384 10.4145C26.8443 10.3569 26.8286 10.3615 26.8144 10.4508C26.8015 10.5316 26.7313 10.7005 26.6758 10.7843C26.6573 10.8123 26.6067 10.9052 26.5634 10.9907C26.5201 11.0762 26.4273 11.2335 26.3572 11.3401C26.1589 11.6418 26.1536 11.6884 26.33 11.5778ZM27.6713 12.5654C27.7951 12.5305 27.8268 12.5078 27.8549 12.4339C27.9013 12.3118 27.7029 12.3629 27.5865 12.5031C27.517 12.5867 27.5388 12.6027 27.6713 12.5654ZM28.1618 12.8072C28.1554 12.8561 28.3858 12.8344 28.6877 12.7578C29.1467 12.6413 29.9192 12.5581 30.2108 12.5937C30.3933 12.616 30.4281 12.6015 30.4189 12.5068C30.4125 12.4416 30.4748 12.3351 30.5937 12.208C30.6074 12.1933 30.6992 12.0949 30.7977 11.9892C30.8963 11.8835 30.9991 11.7843 31.0262 11.7687C31.0533 11.7531 31.1254 11.6838 31.1864 11.6146L31.2972 11.4889L31.2234 11.4797C31.1828 11.4747 31.1141 11.4659 31.0707 11.4602C31.0272 11.4546 30.9704 11.4497 30.9444 11.4494C30.9183 11.4492 30.8703 11.447 30.8376 11.4445C30.7824 11.4405 30.7841 11.4465 30.8615 11.5308C31.0301 11.7141 31.0292 11.8097 30.8603 11.6752C30.6268 11.4893 30.4905 11.3982 30.4168 11.3786C30.3726 11.3669 30.2564 11.3362 30.1586 11.3104C30.0576 11.2838 29.9679 11.2457 29.951 11.2222C29.9347 11.1995 29.8765 11.1628 29.8217 11.1407C29.767 11.1185 29.6812 11.0807 29.6312 11.0566C29.5812 11.0325 29.4866 10.9929 29.4209 10.9687L29.3015 10.9246L29.2519 10.7965C29.2235 10.7231 29.1849 10.6624 29.1617 10.6544C29.1393 10.6468 29.0661 10.5778 28.999 10.5012C28.853 10.3345 28.8472 10.3342 28.5856 10.4797C28.4927 10.5314 28.3643 10.5959 28.3001 10.6231C28.236 10.6502 28.1725 10.6858 28.159 10.702C28.1455 10.7182 28.0992 10.7488 28.056 10.7699C27.8937 10.8493 27.6803 10.9758 27.6123 11.0328L27.5419 11.0919L27.6186 11.1102C27.8953 11.1761 28.0897 11.5113 28.1008 11.9413C28.108 12.2247 28.1396 12.3156 28.2151 12.2702C28.2611 12.2426 28.7218 12.1593 29.2948 12.0751C29.3945 12.0604 29.551 12.0359 29.6424 12.0206C29.7339 12.0053 29.8257 11.9902 29.8464 11.9871C29.8672 11.984 29.946 11.9654 30.0215 11.9457C30.0971 11.926 30.1641 11.9142 30.1703 11.9194C30.1766 11.9246 30.3261 11.9068 30.5026 11.8798C30.6792 11.8529 30.8314 11.8374 30.841 11.8453C30.8793 11.8771 30.7858 11.9388 30.6241 11.9884C30.5286 12.0177 30.4343 12.0637 30.4101 12.0928C30.3601 12.153 30.1602 12.2154 30.0961 12.1907C30.072 12.1815 30.0238 12.188 29.9889 12.2053C29.954 12.2225 29.9092 12.2386 29.8895 12.2411C29.8697 12.2435 29.7647 12.2628 29.656 12.2838C29.5474 12.3049 29.3692 12.3384 29.2599 12.3584C29.0687 12.3932 28.9489 12.423 28.8834 12.4519C28.8663 12.4594 28.8413 12.4564 28.8279 12.4453C28.8145 12.4341 28.7761 12.4413 28.7425 12.4611C28.6703 12.5039 28.494 12.5305 28.4342 12.5076C28.411 12.4987 28.3813 12.5043 28.3682 12.52C28.3365 12.5582 28.3021 12.5269 28.3193 12.4756C28.3288 12.4474 28.374 12.4336 28.4652 12.4311C28.5379 12.429 28.6699 12.4095 28.7586 12.3877C28.8473 12.3659 28.9619 12.3418 29.0135 12.3342C29.065 12.3265 29.1122 12.3142 29.1184 12.3067C29.1246 12.2993 29.1739 12.2892 29.228 12.2844C29.3593 12.2727 29.4834 12.2324 29.4568 12.2103C29.4452 12.2007 29.4296 12.2002 29.4221 12.2093C29.4146 12.2183 29.2952 12.237 29.1568 12.2508C28.7582 12.2907 28.4775 12.3355 28.3979 12.372C28.3517 12.3931 28.3096 12.3939 28.2848 12.3739C28.1763 12.2866 28.1422 12.3216 28.0994 12.5643C28.0628 12.772 28.064 12.7904 28.1134 12.7782C28.1601 12.7666 28.1667 12.7706 28.1618 12.8072ZM35.2044 18.4897C35.2328 18.4395 35.2834 18.3502 35.3169 18.2912C35.4509 18.0555 35.6348 17.7971 35.952 17.3989C36.3579 16.8894 36.3391 16.9155 36.2761 16.9493C36.1404 17.022 35.5427 17.7014 35.5296 17.7979C35.5277 17.8117 35.4845 17.8717 35.4337 17.9312C35.3706 18.005 35.3145 18.1079 35.2572 18.2546C35.211 18.373 35.1591 18.4869 35.1418 18.5077C35.1245 18.5285 35.1199 18.5535 35.1316 18.5632C35.1463 18.5754 35.1688 18.5527 35.2044 18.4897ZM24.6625 9.41157C24.8729 9.47789 25.1698 9.7237 25.4171 10.0362C25.4605 10.091 25.4773 10.0918 25.6621 10.0478C25.7712 10.0218 25.965 9.99058 26.0926 9.97844C26.3525 9.95374 26.3527 9.97202 26.0905 9.76188C26.0064 9.69448 25.8643 9.59829 25.7746 9.54813C25.685 9.49796 25.5792 9.43562 25.5395 9.4096C25.4999 9.38358 25.4506 9.3566 25.4301 9.34968C25.3973 9.33859 25.181 9.23154 25.0249 9.14907C24.9948 9.13323 24.9237 9.10681 24.8667 9.09037C24.7565 9.05859 24.6874 9.03455 24.6618 9.01908C24.639 9.00528 24.5686 9.00715 24.5564 9.02188C24.5506 9.02883 24.5662 9.0688 24.5909 9.11071C24.6157 9.15261 24.636 9.20661 24.6361 9.2307C24.6363 9.26738 24.6807 9.29134 24.9095 9.37796C25.2395 9.50297 25.5867 9.68411 25.6983 9.78963C25.7754 9.86253 25.7685 9.86078 25.5825 9.76035C25.4737 9.7016 25.3015 9.61891 25.1997 9.57658C25.098 9.53424 25.0023 9.48929 24.9871 9.47668C24.9719 9.46406 24.9274 9.44997 24.8882 9.44536C24.849 9.44075 24.8088 9.42247 24.7988 9.40473C24.7887 9.387 24.7522 9.37641 24.7176 9.38121C24.683 9.38601 24.6443 9.38127 24.6315 9.37068C24.6188 9.36009 24.5736 9.34382 24.5312 9.33451C24.4085 9.3076 24.4965 9.35924 24.6625 9.41157ZM32.193 15.3948C32.2196 15.3189 32.155 15.3421 32.1168 15.4222C32.0924 15.4733 32.0946 15.4802 32.1308 15.4664C32.155 15.4572 32.1822 15.426 32.193 15.3948ZM35.9983 18.4238C36.0219 18.3867 35.9994 18.4068 35.9481 18.4683C35.8967 18.5298 35.8774 18.5602 35.905 18.5357C35.9326 18.5112 35.9746 18.4608 35.9983 18.4238ZM35.7036 18.0997C35.7862 17.9991 35.9945 17.7568 36.1664 17.5611C36.4827 17.2012 36.6529 16.9741 36.6109 16.9681C36.5111 16.9537 35.4781 18.22 35.5446 18.2753C35.5494 18.2792 35.621 18.2002 35.7036 18.0997ZM34.6686 17.214C34.758 17.1642 35.0844 16.7055 35.0672 16.6539C35.0618 16.6377 35.078 16.5557 35.1033 16.4718C35.1502 16.3159 35.3155 15.6797 35.3293 15.602C35.3336 15.5783 35.3717 15.3969 35.414 15.199C35.5029 14.7835 35.5414 14.5821 35.5424 14.5261C35.5429 14.5043 35.5513 14.4858 35.5611 14.485C35.58 14.4833 35.5816 14.7085 35.5634 14.8033C35.4392 15.4506 35.3078 16.0307 35.2555 16.1634C35.2289 16.2311 35.2108 16.3059 35.2154 16.3298C35.22 16.3537 35.2094 16.4099 35.1919 16.4547C35.1527 16.5554 35.179 16.5843 35.2414 16.5091C35.267 16.4783 35.2947 16.4587 35.303 16.4656C35.3113 16.4725 35.3533 16.4575 35.3964 16.4324C35.4414 16.4062 35.5063 16.3938 35.5489 16.4033C35.6264 16.4205 35.6439 16.407 36.0514 16.0144C36.1676 15.9025 36.5637 15.572 36.7432 15.4373C36.9124 15.3102 36.968 15.2627 37.0399 15.1836C37.0565 15.1653 37.1136 15.148 37.1667 15.1451L37.2633 15.1399L37.2893 15.0371C37.3036 14.9805 37.3202 14.9278 37.3262 14.9199C37.338 14.9042 37.4581 14.4751 37.5215 14.2221C37.5431 14.1359 37.5616 13.9772 37.5625 13.8695C37.5644 13.6518 37.57 13.6323 37.6128 13.6918C37.6571 13.7533 37.6827 13.7027 37.6853 13.5486C37.6921 13.1374 37.6848 13.0458 37.6218 12.7515C37.5735 12.5256 37.5692 12.5167 37.5395 12.5806C37.5159 12.6315 37.4675 12.608 37.4611 12.5426C37.4583 12.5131 37.4509 12.5168 37.4316 12.5574C37.4174 12.5872 37.4116 12.6278 37.4187 12.6475C37.4258 12.6672 37.4188 12.6988 37.4032 12.7175C37.3876 12.7363 37.3789 12.773 37.3839 12.799C37.3953 12.8581 37.3674 13.2223 37.3478 13.2719C37.3352 13.3036 37.2822 13.4981 37.2477 13.6393C37.2416 13.6644 37.2267 13.6968 37.2145 13.7114C37.2024 13.726 37.1712 13.8174 37.1452 13.9145C37.0942 14.1047 36.8412 14.6206 36.7126 14.7966C36.6692 14.856 36.6098 14.9486 36.5805 15.0024C36.4854 15.1773 36.1355 15.5949 36.0443 15.6422C35.9738 15.6788 35.9639 15.6906 35.9713 15.7289C35.976 15.7533 35.9681 15.7874 35.9538 15.8046C35.9395 15.8218 35.9282 15.8498 35.9287 15.8667C35.9314 15.9566 35.7401 16.2606 35.7012 16.2283C35.6813 16.2118 35.7159 16.1306 35.7719 16.0625C35.794 16.0355 35.8311 15.9314 35.8542 15.8311C35.8773 15.7308 35.9074 15.616 35.9211 15.5758C35.9348 15.5357 35.9689 15.3582 35.9969 15.1813C36.0249 15.0045 36.064 14.7738 36.0837 14.6686C36.1034 14.5635 36.1177 14.4573 36.1156 14.4326C36.1135 14.4079 36.1177 14.3805 36.125 14.3717C36.1324 14.3629 36.137 14.3358 36.1353 14.3114C36.1286 14.213 36.1443 13.9652 36.1583 13.9484C36.2255 13.8674 36.2185 14.2704 36.1452 14.7061C36.1235 14.8345 36.0946 15.0295 36.0809 15.1396C36.0671 15.2496 36.0481 15.3652 36.0386 15.3963C36.0181 15.4637 36.048 15.4979 36.089 15.454C36.2428 15.2891 36.3713 15.1032 36.3718 15.0447C36.372 15.0217 36.3894 14.97 36.4103 14.9299C36.4312 14.8897 36.4552 14.8244 36.4636 14.7848C36.472 14.7452 36.4876 14.7021 36.4984 14.689C36.5093 14.6759 36.5388 14.5884 36.5641 14.4947C36.5895 14.4009 36.6172 14.3158 36.6257 14.3055C36.6475 14.2792 36.7437 13.8736 36.7871 13.6249C36.8072 13.5097 36.8313 13.4062 36.8407 13.395C36.85 13.3837 36.8704 13.2211 36.886 13.0337C36.9016 12.8462 36.9229 12.6826 36.9333 12.6701C36.9673 12.6292 36.9865 12.9679 36.9576 13.0983C36.942 13.1682 36.9324 13.2427 36.9361 13.2637C36.9399 13.2847 36.9292 13.3609 36.9123 13.4332C36.8955 13.5054 36.8572 13.6806 36.8272 13.8226C36.7973 13.9645 36.7563 14.1221 36.7361 14.1728C36.7159 14.2235 36.6984 14.2783 36.6971 14.2946C36.6958 14.3109 36.6754 14.3791 36.6517 14.4462C36.6281 14.5134 36.6051 14.5937 36.6007 14.6247C36.5963 14.6558 36.5789 14.7087 36.562 14.7425C36.5452 14.7762 36.5403 14.8112 36.5512 14.8202C36.562 14.8292 36.5789 14.8184 36.5887 14.7962C36.5985 14.774 36.6327 14.7136 36.6647 14.6621C36.7598 14.5091 36.8769 14.2643 36.9121 14.1451C36.9303 14.0838 36.9623 13.9968 36.9834 13.9519C37.0967 13.7098 37.2219 13.2677 37.2208 13.1137C37.2198 12.9748 37.2627 12.5801 37.2812 12.5578C37.2904 12.5467 37.2909 12.5318 37.2823 12.5247C37.2737 12.5175 37.2715 12.4483 37.2774 12.3708C37.2984 12.0965 37.2246 11.5303 37.1611 11.4775C37.1452 11.4644 37.115 11.3311 37.0659 11.0584C37.0523 10.9825 37.0237 10.8962 37.0025 10.8665L36.9638 10.8126L36.9828 10.8818C37.0364 11.0766 37.0746 11.7041 37.0434 11.8763C37.028 11.9612 36.9756 12.0233 36.9781 11.9538C36.9942 11.4922 36.8784 10.5802 36.7948 10.5108C36.7635 10.4848 36.718 10.5219 36.5168 10.7375C36.4255 10.8352 36.3127 10.9464 36.2661 10.9844C36.1683 11.0641 36.1569 11.1052 36.1953 11.2382C36.2259 11.3441 36.256 11.7125 36.2526 11.9378C36.2513 12.0235 36.2517 12.102 36.2537 12.1122C36.2556 12.1225 36.2443 12.2551 36.2285 12.4068C36.2127 12.5586 36.1967 12.7186 36.1928 12.7624C36.1889 12.8062 36.1794 12.8496 36.1717 12.8589C36.164 12.8682 36.1569 12.91 36.156 12.9518C36.155 12.9936 36.1343 13.1238 36.1099 13.2412C36.0855 13.3586 36.0683 13.464 36.0716 13.4755C36.0749 13.4869 36.0631 13.5813 36.0452 13.6853C36.0127 13.8747 36.0042 13.9401 35.9938 14.0811C35.9907 14.1227 35.9659 14.193 35.9387 14.2373L35.8893 14.3179L35.9006 14.224C35.9068 14.1723 35.9182 14.1225 35.9259 14.1132C35.9336 14.1039 35.9375 14.0714 35.9346 14.0409C35.9278 13.9707 36.0124 13.3042 36.0507 13.1268C36.0665 13.0532 36.0827 12.9601 36.0865 12.9199C36.0904 12.8798 36.1094 12.711 36.1288 12.5449C36.1962 11.968 36.1628 11.0845 36.0768 11.1687C36.0696 11.1757 36.0286 11.2163 35.9857 11.2587C35.9429 11.3012 35.8717 11.3628 35.8275 11.3955C35.7833 11.4283 35.7008 11.4946 35.6441 11.5429C35.5873 11.5913 35.523 11.6407 35.501 11.6528C35.4739 11.6678 35.4701 11.6824 35.4889 11.698C35.6306 11.8157 35.7762 12.7219 35.6733 12.8458C35.6691 12.8509 35.6604 12.9562 35.6539 13.0799C35.6475 13.2036 35.6392 13.3085 35.6354 13.3131C35.6317 13.3176 35.6206 13.3979 35.6109 13.4915C35.6011 13.5852 35.5646 13.7943 35.5297 13.9562C35.4949 14.1181 35.4674 14.2739 35.4687 14.3024C35.4715 14.3622 35.4434 14.4051 35.4162 14.3826C35.406 14.3741 35.4121 14.2975 35.4297 14.2123C35.4473 14.1272 35.4714 13.9945 35.4832 13.9176C35.4949 13.8406 35.5093 13.7602 35.515 13.7389C35.5208 13.7177 35.5274 13.6579 35.5297 13.6062C35.532 13.5544 35.5409 13.5036 35.5494 13.4933C35.5579 13.4831 35.5606 13.4454 35.5553 13.4096C35.55 13.3738 35.5553 13.3329 35.567 13.3188C35.5788 13.3046 35.5797 13.2777 35.569 13.2589C35.5584 13.24 35.5557 13.2174 35.563 13.2086C35.6832 13.0639 35.5739 11.8972 35.4286 11.7745C35.3959 11.7468 35.1725 11.9645 34.8246 12.363L34.6799 12.5287L34.7116 12.7581C34.7638 13.137 34.7789 13.3862 34.7517 13.419C34.7431 13.4293 34.7454 13.4677 34.7568 13.5043C34.7749 13.5623 34.7651 13.7458 34.7285 14.035C34.7068 14.2071 34.6883 14.0785 34.6905 13.77C34.6941 13.2582 34.6575 12.7113 34.6174 12.678C34.6026 12.6657 34.5366 12.733 34.4008 12.899L34.2055 13.1376L34.261 13.207C34.3402 13.3062 34.4265 13.5124 34.4433 13.6425C34.4512 13.7037 34.4754 13.8533 34.497 13.9747C34.5187 14.0962 34.5352 14.2403 34.5336 14.2949C34.5234 14.6478 34.5597 14.8386 34.6515 14.9149C34.7959 15.0348 34.8805 15.2165 34.8964 15.4406C34.9129 15.675 34.9123 15.8705 34.895 15.8913C34.8821 15.9068 34.8762 16.178 34.8878 16.2197C34.8918 16.234 34.8754 16.2695 34.8513 16.2984C34.8273 16.3274 34.783 16.4476 34.753 16.5655C34.7229 16.6834 34.6888 16.7913 34.6771 16.8053C34.6528 16.8346 34.6022 17.2087 34.6205 17.2239C34.6272 17.2294 34.6489 17.225 34.6686 17.214ZM31.3225 13.9646C31.5027 13.8886 31.673 13.8231 31.701 13.819C31.729 13.8148 31.759 13.8029 31.7677 13.7924C31.7763 13.782 31.813 13.7723 31.8492 13.771C31.8853 13.7696 31.922 13.76 31.9306 13.7496C31.9392 13.7392 32.0668 13.6948 32.2141 13.6508C32.3615 13.6068 32.5683 13.5431 32.6737 13.5092C33.0553 13.3865 33.4336 13.3196 33.6134 13.343C33.65 13.3477 33.7098 13.292 33.9314 13.0467C34.2251 12.7216 34.2357 12.6955 34.0539 12.7444C34.0084 12.7567 33.8914 12.7769 33.7937 12.7894C33.6181 12.8119 33.1159 12.9449 32.9193 13.0211C32.8632 13.0428 32.7577 13.0819 32.6847 13.1081C32.6117 13.1343 32.5183 13.1702 32.477 13.188C32.4357 13.2058 32.3269 13.2504 32.2353 13.2871C32.1437 13.3237 32.0608 13.3632 32.0511 13.3747C32.0414 13.3862 31.9759 13.4241 31.9056 13.4589C31.7129 13.5543 31.4555 13.7175 31.3232 13.8282C31.2584 13.8825 31.1791 13.9339 31.1471 13.9425C31.0973 13.9559 30.9407 14.108 30.9807 14.1041C30.9885 14.1033 31.1423 14.0406 31.3225 13.9646ZM36.2586 18.103C36.6615 17.5334 36.9379 17.0344 36.8779 16.9846C36.8691 16.9773 36.8477 16.9986 36.8304 17.0319C36.7186 17.2469 36.6795 17.3176 36.5403 17.5561C36.455 17.7022 36.334 17.8998 36.2714 17.9953C36.0943 18.2652 36.0843 18.3494 36.2586 18.103ZM17.5487 2.49882C17.8114 2.66966 17.7769 2.66495 18.3385 2.60687C18.5939 2.58046 18.6924 2.59037 18.6524 2.63847C18.6329 2.662 18.3175 2.70912 18.0941 2.72185C17.9109 2.7323 17.9186 2.75051 18.1337 2.8156C18.2167 2.8407 18.2399 2.8582 18.2903 2.93378C18.4748 3.21036 19.0179 3.63943 19.2243 3.67169C19.3244 3.68734 19.7627 3.71681 19.9465 3.72028C20.0046 3.72138 20.1137 3.72794 20.189 3.73488C20.4249 3.75661 20.5327 3.74939 20.4629 3.71651C20.4315 3.70169 20.3573 3.66345 20.2981 3.63153C20.2389 3.59961 20.1632 3.57002 20.1299 3.56578C20.0966 3.56153 20.0218 3.52898 19.9638 3.49344C19.9058 3.4579 19.8416 3.43167 19.8212 3.43515C19.7634 3.44502 19.4662 3.41552 19.4357 3.3969C19.4206 3.38771 19.3824 3.38037 19.3508 3.38059C19.2589 3.38122 18.9331 3.33032 18.8212 3.29781C18.7647 3.28144 18.6918 3.26111 18.6591 3.25265C18.5533 3.22527 18.5755 3.15832 18.6824 3.1826C19.2172 3.3041 19.7057 3.3621 19.7502 3.30934C19.7759 3.27874 19.801 3.27937 19.8597 3.31209C19.9603 3.36827 20.9355 3.33911 20.9859 3.27842C20.9932 3.26962 21.016 3.27637 21.0365 3.29343C21.057 3.31048 21.1288 3.3204 21.196 3.31546C21.2632 3.31053 21.3296 3.31597 21.3436 3.32756C21.3575 3.33915 21.3868 3.33723 21.4086 3.3233C21.4305 3.30936 21.4773 3.30593 21.5126 3.31567C21.548 3.3254 21.5833 3.32561 21.5912 3.31613C21.5991 3.30665 21.6448 3.30413 21.6928 3.31053C21.9481 3.34457 22.982 3.2512 23.0333 3.18947C23.0558 3.16243 22.7525 3.03345 22.5938 3.00257C22.5609 2.99617 22.5223 2.98127 22.5081 2.96947C22.4939 2.95766 22.438 2.94528 22.384 2.94195C22.3299 2.93861 22.2421 2.91488 22.1887 2.8892C22.1139 2.8532 22.054 2.84935 21.927 2.87238C21.8364 2.8888 21.7438 2.89953 21.7214 2.89623C21.6989 2.89293 21.4161 2.91377 21.0928 2.94253C20.5917 2.98715 20.3619 3.00037 19.9728 3.00702C19.9379 3.00761 19.873 3.00543 19.8285 3.00216C19.7841 2.9989 19.6895 3.00104 19.6182 3.00691C19.5083 3.01598 19.4326 3.0023 19.4535 2.97713C19.4681 2.9596 19.7177 2.94453 20.0065 2.94375C20.1819 2.94328 20.3884 2.9376 20.4653 2.93115C20.5422 2.92469 20.6248 2.92011 20.6488 2.92098C20.6729 2.92185 20.75 2.91494 20.8203 2.90562C20.8906 2.8963 21.1648 2.8735 21.4298 2.85494C21.6948 2.83639 21.8993 2.81096 21.8842 2.79845C21.8691 2.78593 21.8358 2.77954 21.8101 2.78423C21.7844 2.78892 21.7557 2.78636 21.7463 2.77853C21.7216 2.75806 21.5798 2.72206 21.448 2.70281C21.3855 2.69369 21.3191 2.67412 21.3004 2.65932C21.2817 2.64452 21.2177 2.62667 21.1583 2.61963C21.0988 2.6126 21.0248 2.59438 20.9936 2.57914C20.9562 2.56081 20.9024 2.56723 20.8346 2.59811C20.5598 2.72337 20.0279 2.77727 19.7604 2.70697C19.6444 2.67649 19.5442 2.66597 19.5121 2.68093C19.4826 2.69473 19.4028 2.69898 19.3349 2.69036C19.2669 2.68175 19.1411 2.673 19.0553 2.67093C18.9695 2.66885 18.895 2.6666 18.8898 2.66594C18.8846 2.66527 18.8194 2.71117 18.745 2.76793C18.5991 2.87919 18.4989 2.92143 18.4591 2.88839C18.4152 2.85195 18.4383 2.81846 18.5441 2.76521C18.7651 2.65396 18.7998 2.59336 18.6604 2.56226C18.616 2.55236 18.5789 2.5369 18.5781 2.5279C18.5772 2.5189 18.4569 2.47614 18.3107 2.43287C18.1646 2.3896 18.0339 2.34519 18.0203 2.33418C18.0067 2.32315 17.9608 2.3064 17.9184 2.29694C17.8759 2.28748 17.7936 2.24512 17.7355 2.20281C17.6474 2.13866 17.6081 2.1266 17.499 2.13014C17.427 2.13248 17.317 2.1356 17.2545 2.13708C17.0588 2.14172 17.1252 2.22333 17.5487 2.49882ZM17.2752 2.04176C17.4637 2.05102 17.5092 2.05081 18.0809 2.03807C18.3149 2.03286 18.5144 2.02462 18.5243 2.01977C18.5484 2.00791 18.58 2.03567 18.5642 2.05475C18.5573 2.06308 18.3949 2.08438 18.2033 2.10207C17.9325 2.12709 17.8639 2.14171 17.8952 2.16768C17.984 2.24149 18.1225 2.24822 18.6369 2.20373C19.0969 2.16395 19.2386 2.16259 19.209 2.19822C19.2057 2.20219 19.0157 2.22532 18.7868 2.24961C18.5578 2.27391 18.3708 2.29657 18.3711 2.29996C18.3741 2.33044 18.6852 2.45279 18.8156 2.47474C18.9066 2.49004 19.0128 2.51356 19.0517 2.527C19.2308 2.58887 20.2847 2.4447 20.2764 2.35945C20.2756 2.35121 20.1775 2.32547 20.0585 2.30224C19.6776 2.22791 19.2965 2.1142 18.8493 1.94146C18.7896 1.91842 18.7072 1.89122 18.6661 1.88101C18.625 1.8708 18.5803 1.85321 18.5667 1.84192C18.5531 1.83063 18.5265 1.83003 18.5075 1.84059C18.4886 1.85115 18.4475 1.85132 18.4163 1.84096C18.385 1.83061 18.3314 1.82141 18.2971 1.82052C18.157 1.81687 17.9836 1.80495 17.8605 1.7905C17.7887 1.78207 17.6612 1.78257 17.577 1.79162C17.4929 1.80066 17.4167 1.80191 17.4076 1.79439C17.3986 1.78687 17.3753 1.79985 17.3558 1.82324C17.3124 1.87555 17.2022 1.90773 17.1669 1.87841C17.0461 1.77812 17.5152 1.65679 17.8863 1.69232C18.0657 1.70949 18.0886 1.68175 17.9368 1.63134C17.758 1.57195 17.6192 1.55498 17.5743 1.58699C17.5497 1.60456 17.5269 1.60297 17.5155 1.5829C17.5006 1.55655 17.2594 1.55489 17.0431 1.57966C16.5848 1.63215 16.594 1.61489 16.8946 1.85796L17.112 2.03375L17.2752 2.04176ZM20.4818 4.64461C20.6139 4.71105 20.7401 4.77451 20.7622 4.78563C21.1042 4.9576 21.2321 4.99717 21.4386 4.99493C21.5181 4.99406 21.6589 5.00133 21.7515 5.01109C21.844 5.02084 21.9257 5.02165 21.933 5.0129C21.9403 5.00414 21.9816 5.00488 22.0249 5.01453C22.0683 5.02419 22.1946 5.03162 22.3057 5.03105C22.4168 5.03048 22.537 5.03621 22.5728 5.04377C22.6868 5.06783 23.0759 5.06491 23.3248 5.03815C23.4571 5.02392 23.5707 5.02084 23.5772 5.0313C23.5967 5.06245 23.3415 5.11797 23.0922 5.13681C22.9643 5.14648 22.8673 5.16084 22.8768 5.16871C22.9718 5.2476 23.5023 5.4198 23.7733 5.45976C23.8665 5.4735 24.0014 5.50943 24.0731 5.53962C24.1448 5.56981 24.251 5.60153 24.3092 5.61011C24.3674 5.61869 24.4221 5.63164 24.4308 5.63887C24.4452 5.6508 24.5853 5.67199 25.182 5.75246C25.29 5.76703 25.3884 5.78245 25.4005 5.78672C25.4127 5.79099 25.519 5.78696 25.6367 5.77776C25.7544 5.76857 26.0019 5.75879 26.1867 5.75604C26.3714 5.75328 26.6145 5.74556 26.7268 5.73889C26.8391 5.73222 26.9792 5.72789 27.0381 5.72926C27.0971 5.73064 27.2456 5.72296 27.3681 5.7122L27.5909 5.69262L27.5338 5.62766C27.5024 5.59193 27.3741 5.48793 27.2486 5.39654C26.9939 5.21098 27.0278 5.21732 26.6697 5.28869C26.5963 5.30333 26.5014 5.316 26.4589 5.31685C26.4163 5.3177 26.2801 5.32654 26.1561 5.3365C26.032 5.34646 25.8758 5.3516 25.8089 5.34794C25.742 5.34427 25.6633 5.34417 25.634 5.34772C25.5482 5.35811 25.1056 5.34736 25.0902 5.33451C25.0824 5.32805 25.0029 5.32431 24.9135 5.32622C24.8242 5.32812 24.7192 5.32239 24.6802 5.31349C24.6177 5.29922 24.3952 5.28126 24.3477 5.28666C24.2962 5.2925 24.0719 5.27773 24.0599 5.2677C24.0521 5.26126 23.9697 5.25672 23.8767 5.25762C23.7838 5.25851 23.7002 5.25296 23.6909 5.24529C23.6817 5.23761 23.6035 5.23655 23.5171 5.24293C23.3675 5.25398 23.2591 5.21574 23.3023 5.16709C23.3208 5.14628 23.765 5.16111 24.0555 5.19224C24.1221 5.19938 24.2242 5.20607 24.2823 5.2071C24.3405 5.20814 24.4365 5.21365 24.4956 5.21936C24.5547 5.22506 24.7336 5.23601 24.8933 5.24368C25.0529 5.25136 25.2592 5.26131 25.3518 5.26582C25.4443 5.27032 25.5678 5.27109 25.6261 5.26755C25.6845 5.264 25.7367 5.27448 25.7423 5.29083C25.7479 5.30717 25.7705 5.30982 25.7926 5.2967C25.8147 5.28358 25.9092 5.26882 26.0026 5.2639C26.3303 5.24663 26.5623 5.22634 26.5726 5.21407C26.5783 5.20725 26.6478 5.19203 26.7272 5.18026C26.8816 5.15733 26.9057 5.10771 26.7831 5.06533C26.7501 5.05394 26.6834 5.01165 26.6349 4.97137C26.4492 4.81721 26.388 4.79634 26.2287 4.83296C25.8302 4.92455 25.1421 4.96787 25.0686 4.90601C25.0344 4.87719 25.061 4.8701 25.2197 4.86579C26.099 4.8419 26.4157 4.69795 25.9614 4.52867C25.9035 4.5071 25.8492 4.47734 25.8409 4.46254C25.8167 4.4198 25.7032 4.42094 25.6672 4.46428C25.6179 4.52367 24.987 4.60865 24.6523 4.60094C24.583 4.59935 24.4898 4.60183 24.4453 4.60645C24.4008 4.61107 24.3684 4.61009 24.3732 4.60426C24.3781 4.59844 24.3166 4.59858 24.2367 4.60459C23.9108 4.62905 23.6916 4.6201 23.722 4.58355C23.7293 4.57472 23.7613 4.56638 23.793 4.56502C23.8248 4.56367 23.9267 4.55702 24.0194 4.55025C24.1121 4.54348 24.2451 4.53858 24.3149 4.53936C25.022 4.54724 25.8215 4.39695 25.5664 4.30415C25.5221 4.28803 25.4635 4.25631 25.4362 4.23366C25.3624 4.1724 25.2776 4.15642 25.1756 4.18461C25.0133 4.2295 24.4781 4.26513 23.5714 4.29144C23.3612 4.29753 23.2982 4.28842 23.3259 4.2559C23.3372 4.24255 23.511 4.22756 24.6031 4.14577C25.1521 4.10465 25.1775 4.09723 25.0444 4.01641C24.995 3.98637 24.9312 3.9467 24.9027 3.92824C24.8193 3.87429 24.6354 3.86141 24.4362 3.89557C24.2534 3.92692 23.7664 3.97125 23.5725 3.97418C23.5177 3.97501 23.4169 3.99721 23.3485 4.02351C23.2309 4.06872 22.8288 4.11926 22.797 4.09283C22.7889 4.08607 22.7343 4.10109 22.6757 4.12621C22.6172 4.15132 22.4807 4.17889 22.3725 4.18746C22.0813 4.21055 21.7289 4.22626 21.5802 4.22277C21.5081 4.22109 21.4399 4.22985 21.4287 4.24224C21.4175 4.25464 21.4009 4.25858 21.3918 4.25102C21.3827 4.24345 21.2469 4.24075 21.0901 4.24501C20.8165 4.25245 20.3989 4.2383 20.1692 4.2138C20.0654 4.20273 20.0181 4.2146 20.0525 4.24311C20.0612 4.25033 20.0601 4.28671 20.0501 4.32395C20.0285 4.40439 20.0794 4.44214 20.4818 4.64461ZM19.6863 4.0074C19.8326 4.09122 19.9182 4.12609 19.9718 4.1236C20.0139 4.12164 20.0869 4.12577 20.1341 4.13276C20.3114 4.15906 20.6612 4.16783 20.6789 4.14643C20.6891 4.1342 20.8015 4.11298 20.9288 4.09929C21.13 4.07762 21.3496 4.0288 21.3731 4.0005C21.3837 3.98769 21.3182 3.96374 21.1655 3.92465C21.0933 3.90617 20.9934 3.87124 20.9435 3.84703C20.8819 3.81716 20.7877 3.80739 20.6504 3.81662C20.4148 3.83247 20.1974 3.82714 20.1706 3.80488C20.1603 3.7963 20.1026 3.79144 20.0424 3.79408C19.9823 3.79672 19.8804 3.7938 19.8162 3.78759C19.7519 3.78138 19.6757 3.77799 19.6468 3.78007C19.618 3.78214 19.5381 3.78325 19.4693 3.78254L19.3443 3.78124L19.4108 3.83446C19.4474 3.86372 19.5714 3.94153 19.6863 4.0074ZM29.8042 12.1675C29.8127 12.1572 29.7547 12.1587 29.6754 12.1709C29.596 12.1831 29.5249 12.2004 29.5174 12.2094C29.5099 12.2185 29.5679 12.2169 29.6462 12.206C29.7246 12.1951 29.7957 12.1777 29.8042 12.1675ZM31.1943 13.3928C31.2582 13.3636 31.3073 13.33 31.3032 13.3182C31.2898 13.2786 32.0918 12.7646 32.3341 12.6574C32.5875 12.5453 32.9746 12.4073 33.13 12.3737C33.1466 12.3701 33.2005 12.3565 33.2499 12.3433C33.3493 12.3169 33.427 12.3027 33.8033 12.2423C34.0664 12.2001 34.1916 12.1809 34.4785 12.1388C34.7532 12.0985 34.7803 12.0916 34.8221 12.0513C35.0986 11.7845 35.2553 11.5934 35.206 11.5831C35.1079 11.5627 34.608 11.6152 34.3738 11.6705C34.244 11.7012 34.1142 11.7284 34.0853 11.7311C33.9628 11.7423 33.6951 11.8239 33.4875 11.9134C33.405 11.9489 33.3191 11.9841 33.2966 11.9915C33.1136 12.0517 32.4797 12.3797 32.368 12.472C32.2909 12.5357 32.1332 12.6296 32.1505 12.6014C32.3164 12.3319 33.3843 11.8024 34.0189 11.6749C34.7199 11.5341 35.095 11.4858 35.241 11.5173C35.3067 11.5316 35.3397 11.5236 35.3733 11.4853C35.398 11.4572 35.4362 11.4208 35.4582 11.4044C35.4802 11.388 35.5622 11.307 35.6405 11.2245L35.7828 11.0745L35.7096 11.0768C35.6693 11.0781 35.5601 11.0832 35.4669 11.0883C35.3737 11.0933 35.2908 11.0919 35.2827 11.0851C35.2745 11.0783 35.2591 11.0832 35.2483 11.096C35.2306 11.1172 35.1218 11.1394 34.8852 11.1699C34.7755 11.1841 34.4193 11.2654 34.357 11.2906C34.3141 11.3078 34.1129 11.3528 33.9923 11.3721C33.926 11.3827 33.4721 11.587 33.4466 11.6177C33.4356 11.631 33.3596 11.6715 33.2779 11.7077C33.0546 11.8067 32.7695 11.9546 32.6115 12.0535C32.2093 12.3053 32.0587 12.4074 32.0191 12.455C31.9951 12.4839 31.9517 12.5171 31.9228 12.5288C31.8938 12.5405 31.8207 12.6031 31.7605 12.668C31.7002 12.7329 31.5729 12.8633 31.4776 12.9576C31.197 13.2354 30.9602 13.5127 31.044 13.4653C31.0627 13.4547 31.1303 13.4221 31.1943 13.3928ZM22.5379 5.99031C22.8172 6.12309 22.8466 6.13546 23.0332 6.19885C23.1287 6.23132 23.2921 6.29337 23.3961 6.33672C23.7085 6.46687 23.9959 6.56645 24.0798 6.57354C24.1232 6.57722 24.1652 6.58562 24.1732 6.59222C24.1811 6.59882 24.2106 6.60375 24.2387 6.60319C24.3205 6.60154 25.1146 6.77452 25.1464 6.80092C25.193 6.83965 24.8873 6.81439 24.6372 6.75885C24.5633 6.74244 24.4512 6.72407 24.3881 6.71803C24.325 6.71199 24.2586 6.6947 24.2404 6.67961C24.2222 6.66452 24.1945 6.65921 24.1787 6.66782C24.1403 6.68876 23.689 6.5789 23.5704 6.51974C23.4973 6.48326 23.4845 6.49372 23.4837 6.5906C23.4832 6.66274 23.4839 6.66349 23.6101 6.71638C23.7937 6.79337 24.1509 6.94177 24.4205 7.05308C24.5492 7.10621 24.6726 7.16463 24.6947 7.18288C24.7168 7.20115 24.7652 7.22278 24.8022 7.23095C24.8392 7.23912 24.9209 7.27005 24.9839 7.29968C25.1636 7.38429 25.3066 7.43295 25.4455 7.45666C25.516 7.4687 25.5993 7.48916 25.6306 7.50212C25.6618 7.51508 25.696 7.52404 25.7064 7.52202C25.7168 7.52001 25.7804 7.52966 25.8478 7.54347C25.9151 7.55728 25.9788 7.56684 25.9893 7.56472C25.9998 7.5626 26.0825 7.57508 26.1731 7.59247C26.2637 7.60985 26.3468 7.62194 26.3577 7.61932C26.3687 7.61671 26.4638 7.63018 26.5691 7.64926C26.8375 7.69789 26.8884 7.70579 27.0301 7.72081C27.0988 7.7281 27.156 7.74414 27.1572 7.75646C27.16 7.78503 26.9484 7.79259 26.9153 7.76509C26.9017 7.75374 26.8839 7.75239 26.8758 7.7621C26.8678 7.77181 26.832 7.77404 26.7963 7.76705C26.7606 7.76007 26.6801 7.74423 26.6173 7.73186C26.5545 7.71949 26.4765 7.71153 26.444 7.71417C26.4115 7.71681 26.3374 7.70797 26.2795 7.69454C26.2215 7.6811 26.1492 7.67075 26.1188 7.67154C26.0532 7.67323 25.7579 7.61097 25.7459 7.59291C25.7413 7.586 25.6945 7.57838 25.6419 7.57598C25.5893 7.57357 25.4804 7.55449 25.3999 7.53358C25.155 7.46994 25.0792 7.52493 25.2562 7.63791C25.309 7.67168 25.4113 7.74031 25.4835 7.79044C25.6627 7.91487 25.7302 7.95562 25.9606 8.07839C26.0699 8.13659 26.2522 8.24478 26.3658 8.31881C26.4794 8.39285 26.6654 8.50239 26.7792 8.56224C26.893 8.62208 26.995 8.68684 27.0059 8.70616C27.0289 8.74694 27.8278 8.94041 27.9675 8.93902C27.994 8.93876 28.0644 8.94884 28.124 8.96141C28.2555 8.98915 28.3172 8.99829 28.441 9.00839C28.4932 9.01264 28.5455 9.02414 28.5573 9.03393C28.5691 9.04373 28.6019 9.04969 28.6303 9.0472C28.6834 9.04251 28.7635 9.09218 28.7428 9.11698C28.7364 9.12466 28.7005 9.12681 28.663 9.12174C28.6256 9.11667 28.4434 9.09669 28.2581 9.07734C28.0729 9.05799 27.9138 9.03623 27.9046 9.02896C27.8954 9.02171 27.853 9.01461 27.8104 9.01318C27.7679 9.01175 27.718 8.99845 27.6997 8.98362C27.6814 8.96879 27.6603 8.96403 27.6528 8.97303C27.6453 8.98204 27.5836 8.97437 27.5157 8.95598C27.4478 8.9376 27.3612 8.91688 27.3232 8.90994C27.2852 8.903 27.2402 8.88599 27.2232 8.87213C27.2062 8.85827 27.1713 8.85078 27.1456 8.85548C27.0881 8.86599 27.1199 8.89623 27.2847 8.98783C27.3458 9.02175 27.4408 9.07783 27.4959 9.11244C27.6799 9.22796 28.054 9.33807 28.3858 9.37439C28.4661 9.38318 28.6274 9.40254 28.7442 9.41742C28.8611 9.4323 29.0436 9.44543 29.1497 9.44659C29.6677 9.45228 29.7661 9.46082 29.7699 9.50043C29.7736 9.5381 29.5096 9.56906 29.4669 9.53597C29.4582 9.52919 29.3787 9.52803 29.2902 9.5334C29.2018 9.53876 29.0665 9.53637 28.9894 9.52807C28.8352 9.51148 28.7865 9.50751 28.5936 9.49575C28.5218 9.49137 28.4336 9.47251 28.3976 9.45383C28.3616 9.43515 28.3272 9.42586 28.3211 9.43318C28.315 9.4405 28.2254 9.43217 28.1219 9.41467L27.9338 9.38285L27.9988 9.45755C28.0982 9.57182 28.2769 9.68268 28.3791 9.69339C28.4291 9.69865 28.5675 9.71319 28.6865 9.72571C28.8055 9.73822 28.9238 9.74697 28.9494 9.74513C28.975 9.7433 29.0901 9.75127 29.2053 9.76285C29.5116 9.79365 29.7875 9.73678 29.8823 9.62325C29.9304 9.56569 30.0826 9.53644 30.0915 9.58304C30.0985 9.61932 30.1084 9.62346 30.1421 9.60417C30.1651 9.59098 30.3075 9.55501 30.4585 9.52424C30.9256 9.42909 30.9119 9.43998 30.805 9.24905C30.737 9.12747 30.7013 9.0968 30.6708 9.13354C30.6511 9.15728 30.6434 9.14867 30.6255 9.08265C30.5812 8.9192 30.5256 8.88307 30.3456 8.90082C30.1479 8.9203 30.0577 8.91646 29.8703 8.88053C29.791 8.86534 29.7209 8.85921 29.7145 8.8669C29.6959 8.88923 29.7167 8.8975 29.8472 8.91946C29.9759 8.94114 30.0722 9.02195 29.9876 9.03739C29.9054 9.0524 29.4653 8.93694 29.4902 8.90692C29.5031 8.89134 29.5533 8.87662 29.6016 8.8742C29.7155 8.86851 29.6939 8.85226 29.5511 8.83613C29.4888 8.82909 29.4219 8.81365 29.4026 8.80183C29.3832 8.79 29.3552 8.78342 29.3404 8.78721C29.2731 8.80431 29.0788 8.75842 29.0762 8.72486C29.0741 8.69582 29.1843 8.69672 29.3658 8.72723C29.7839 8.79749 30.4437 8.84515 30.4492 8.80547C30.4615 8.71513 30.2667 8.58615 30.0886 8.56679C29.9898 8.55604 29.9014 8.54101 29.8923 8.53338C29.8831 8.52576 29.8686 8.52792 29.8601 8.53819C29.8515 8.54846 29.8334 8.54764 29.8198 8.53635C29.8063 8.52507 29.7661 8.51653 29.7305 8.51739C29.695 8.51824 29.6419 8.51426 29.6125 8.50854C29.4702 8.48083 29.283 8.43475 29.2108 8.40965C29.1667 8.3943 29.1244 8.38912 29.1169 8.39815C29.1094 8.40717 29.0948 8.40753 29.0845 8.39895C29.0741 8.39036 29.0018 8.37829 28.9237 8.37211C28.8457 8.36594 28.7278 8.34823 28.6619 8.33276C28.596 8.31729 28.5013 8.3019 28.4516 8.29856C28.3301 8.29041 28.0398 8.20026 28.0593 8.17676C28.0679 8.16646 28.094 8.16514 28.1175 8.17382C28.1409 8.18251 28.1864 8.18926 28.2186 8.18884C28.2507 8.18841 28.32 8.19483 28.3724 8.2031C28.4249 8.21136 28.538 8.22486 28.6239 8.2331C28.7097 8.24134 28.842 8.25966 28.9178 8.27382C29.429 8.36937 29.6404 8.40462 29.8262 8.42526C29.9302 8.43682 30.0245 8.45392 30.0358 8.46327C30.047 8.47262 30.0908 8.47613 30.133 8.47107L30.2098 8.46188L30.1273 8.34091C29.9622 8.09882 29.9729 8.10644 29.8157 8.11959C29.6522 8.13326 29.3967 8.12188 29.3701 8.09974C29.3602 8.09154 29.3374 8.093 29.3195 8.10298C29.2912 8.11877 29.2202 8.11446 28.8864 8.07671C28.8501 8.07261 28.7636 8.06342 28.6942 8.05631C28.6248 8.04919 28.5154 8.03778 28.451 8.03095C28.3867 8.02412 28.2361 7.99838 28.1165 7.97376C27.9969 7.94914 27.8729 7.92642 27.841 7.92329C27.7774 7.91705 27.728 7.88577 27.7465 7.86348C27.7602 7.84697 27.9701 7.87554 28.1612 7.91993C28.2346 7.93698 28.3088 7.95115 28.3261 7.95142C28.4863 7.95398 28.7687 7.97898 28.7844 7.992C28.7952 8.00098 28.8106 8.00039 28.8187 7.99068C28.8268 7.98097 28.863 7.97914 28.8993 7.9866C29.2016 8.04887 29.8881 8.05242 29.8674 7.99161C29.8521 7.94664 29.6856 7.79004 29.6714 7.8072C29.665 7.81483 29.5884 7.81825 29.5011 7.8148C29.4137 7.81135 29.3177 7.80942 29.2877 7.81052C29.2022 7.81365 28.999 7.80359 28.9101 7.79183C28.8657 7.78596 28.8043 7.78219 28.7738 7.78346C28.6593 7.78825 28.3553 7.76127 28.3347 7.74449C28.3229 7.7349 28.2915 7.73103 28.2648 7.73591C28.2381 7.74078 28.1782 7.73297 28.1316 7.71855C28.0851 7.70412 28.0312 7.70113 28.0118 7.7119C27.9925 7.72267 27.9649 7.72167 27.9505 7.70968C27.936 7.6977 27.9172 7.69629 27.9087 7.70656C27.9002 7.71683 27.8837 7.71732 27.872 7.70765C27.8604 7.69798 27.7733 7.68164 27.6786 7.67133C27.5838 7.66102 27.4827 7.64262 27.4539 7.63044C27.425 7.61825 27.38 7.60824 27.3538 7.6082C27.2728 7.60805 27.0457 7.55785 27.0166 7.53367C27.0014 7.52107 26.9832 7.51784 26.976 7.52649C26.9688 7.53514 26.9178 7.53185 26.8627 7.51918C26.8075 7.5065 26.7223 7.49272 26.6732 7.48855C26.5343 7.47674 26.4048 7.43969 26.4355 7.42049C26.4759 7.39521 26.7593 7.41494 26.7964 7.44562C26.8146 7.46062 26.8355 7.46567 26.8428 7.45683C26.8502 7.44799 26.932 7.45718 27.0248 7.47726C27.1175 7.49734 27.2147 7.51397 27.2408 7.51421C27.2669 7.51444 27.3672 7.53163 27.4638 7.55239C27.8015 7.62503 28.1809 7.66476 28.7573 7.68786C28.8984 7.69351 29.1492 7.70512 29.3146 7.71368C29.6525 7.73115 29.6608 7.72333 29.5013 7.53765L29.3938 7.41253L29.2246 7.42831C29.0107 7.44825 28.9205 7.45016 28.8146 7.43697C28.7682 7.43119 28.7092 7.42586 28.6836 7.42511C28.5704 7.42184 28.3447 7.40612 28.1118 7.38532C27.9732 7.37294 27.8036 7.36292 27.7348 7.36305C27.666 7.36318 27.5556 7.34948 27.4895 7.33261C27.4234 7.31573 27.3322 7.2994 27.2868 7.29632C27.2415 7.29323 27.2035 7.28162 27.2024 7.27053C27.2013 7.25943 27.2937 7.25576 27.4077 7.26239C27.5217 7.26901 27.6324 7.27438 27.6537 7.27432C27.675 7.27426 27.736 7.27842 27.7893 7.28355C27.8798 7.29228 27.9976 7.29886 28.3764 7.31638C28.461 7.32029 28.6161 7.33195 28.721 7.34229C28.9353 7.3634 29.3125 7.34065 29.3006 7.30731C29.2963 7.29535 29.2378 7.23007 29.1707 7.16224L29.0486 7.03891L28.9226 7.06308C28.8533 7.07637 28.7856 7.07811 28.7722 7.06695C28.7588 7.05579 28.7105 7.05474 28.6649 7.06462C28.5784 7.08338 28.4052 7.08163 28.2068 7.05999C28.1426 7.05298 28.0734 7.05013 28.0529 7.05365C28.0179 7.0597 27.866 7.04941 27.7637 7.03406C27.6493 7.01688 27.5403 7.01072 27.4493 7.01629C27.395 7.01961 27.3428 7.01579 27.3332 7.0078C27.3236 6.99981 27.2658 6.99443 27.2048 6.99584C27.1438 6.99726 27.0822 6.98868 27.0679 6.97679C27.0536 6.9649 27.0333 6.95971 27.0229 6.96525C26.9915 6.98189 26.5411 6.96497 26.4723 6.94459C26.4372 6.93417 26.3498 6.92493 26.278 6.92406C26.0262 6.92097 25.754 6.89539 25.726 6.87216C25.7105 6.85926 25.6894 6.85305 25.6792 6.85835C25.6435 6.87685 25.3611 6.85302 25.3322 6.82907C25.2909 6.79477 25.474 6.77597 25.6569 6.79572C25.7373 6.80438 25.8537 6.8142 25.9157 6.81752C25.9777 6.82084 26.1044 6.82979 26.1971 6.83739C26.2899 6.845 26.3989 6.8504 26.4395 6.84939C26.4801 6.84837 26.636 6.85719 26.7861 6.86899C26.9361 6.88078 27.3136 6.90323 27.625 6.91889C27.9364 6.93455 28.2431 6.95146 28.3064 6.95645C28.4788 6.97007 28.9259 6.94153 28.9475 6.91552C28.9608 6.89958 28.9219 6.85587 28.8177 6.76928C28.7116 6.68117 28.6627 6.62578 28.6472 6.576C28.6257 6.50689 28.6249 6.50672 28.5616 6.55902C28.5018 6.60843 27.9888 6.66882 27.9441 6.6317C27.9358 6.62476 27.8331 6.61672 27.716 6.61386C27.5988 6.61099 27.4996 6.59877 27.4955 6.5867C27.4914 6.57463 27.4815 6.57271 27.4734 6.58242C27.4576 6.60144 27.0351 6.60254 27.0124 6.58362C27.0048 6.57734 26.9395 6.57283 26.8673 6.57359C26.7951 6.57435 26.7252 6.56603 26.7121 6.5551C26.6989 6.54417 26.6716 6.54131 26.6514 6.54874C26.5683 6.57937 26.0641 6.47794 26.0978 6.43737C26.1104 6.42217 26.1524 6.41905 26.191 6.43044C26.2297 6.44184 26.3014 6.45476 26.3502 6.45917C26.3991 6.46357 26.4717 6.47499 26.5116 6.48455C26.5515 6.49411 26.6105 6.50076 26.6426 6.49933C26.6747 6.4979 26.7927 6.49848 26.9047 6.50063C27.0167 6.50277 27.1303 6.50395 27.1572 6.50325C27.184 6.50255 27.3222 6.50865 27.4642 6.51681C27.6063 6.52496 27.7386 6.5294 27.7584 6.52667C27.7782 6.52394 27.8655 6.52663 27.9524 6.53265C28.0393 6.53866 28.1151 6.53802 28.1208 6.53122C28.1265 6.52442 28.1698 6.52298 28.2169 6.52804C28.2641 6.5331 28.3458 6.52091 28.3985 6.50095L28.4944 6.46466L28.4356 6.3916C28.2714 6.18733 28.1195 6.10742 27.9294 6.12536C27.8326 6.13451 27.666 6.14048 27.5593 6.13863C27.4526 6.13678 27.3387 6.13806 27.3063 6.14147C27.2738 6.14489 27.2393 6.14104 27.2295 6.13292C27.2197 6.12479 27.1876 6.11992 27.158 6.12208C27.1285 6.12424 27.045 6.11984 26.9725 6.11232C26.7354 6.08772 26.1387 6.05596 26.0122 6.06122C25.9022 6.06579 25.4979 6.03585 25.42 6.01735C25.3258 5.995 25.3208 5.94798 25.4127 5.94946C25.6286 5.95293 25.2925 5.87982 25.0015 5.86001C24.9187 5.85437 24.7966 5.83745 24.7304 5.82241C24.4908 5.76807 24.2206 5.72085 24.0424 5.70219C23.9422 5.6917 23.9088 5.70009 23.8714 5.7452C23.7885 5.84498 23.5649 5.89783 23.4898 5.8354C23.4452 5.79843 23.5049 5.76028 23.5959 5.76744C23.6738 5.77356 23.84 5.70186 23.8363 5.66376C23.8355 5.65571 23.7706 5.633 23.692 5.61329C23.6134 5.59358 23.467 5.55554 23.3667 5.52875C23.2664 5.50197 23.1492 5.4844 23.1062 5.4897C23.0632 5.49501 22.9979 5.50266 22.961 5.50671C22.8852 5.51504 22.5294 5.5338 22.3358 5.53967C22.1821 5.54434 21.8863 5.51346 21.8578 5.48978C21.8142 5.45357 21.8875 5.41879 21.9691 5.43698C22.0164 5.44753 22.0728 5.4549 22.0943 5.45338C22.1159 5.45185 22.1869 5.45233 22.2522 5.45444C22.6932 5.4687 23.1113 5.42602 22.9788 5.38025C22.944 5.36822 22.8855 5.33949 22.8488 5.3164C22.6822 5.21157 22.4928 5.13446 22.4023 5.13464C22.3484 5.13476 22.297 5.12885 22.2882 5.12152C22.2793 5.11419 22.2518 5.10982 22.2271 5.1118C22.2023 5.11378 22.1071 5.11078 22.0155 5.10513C21.9239 5.09948 21.7899 5.09401 21.7178 5.09298C21.6457 5.09194 21.555 5.08972 21.5163 5.08803C21.4482 5.08506 21.4517 5.08903 21.6274 5.21523C21.8023 5.34085 21.8084 5.34771 21.7964 5.40741C21.7801 5.48872 22.235 5.84638 22.5379 5.99031ZM17.7941 1.48743C17.8138 1.4636 18.0273 1.57337 18.0762 1.63249C18.1053 1.66773 18.1638 1.68723 18.2809 1.7007C18.568 1.73376 18.8808 1.7868 18.892 1.80434C18.8979 1.81367 18.9483 1.83518 19.0038 1.85215C19.0594 1.86912 19.2269 1.92555 19.376 1.97755C19.5252 2.02954 19.6615 2.07235 19.679 2.0727C19.7064 2.07323 19.9011 2.11434 20.3779 2.22026C20.4401 2.23408 20.6057 2.28842 20.7459 2.34101C20.886 2.39359 21.0505 2.4457 21.1113 2.4568C21.1721 2.46789 21.2542 2.4939 21.2937 2.51459C21.4566 2.59994 21.3978 2.5252 21.1549 2.33815C20.9902 2.21135 20.8698 2.10347 20.8213 2.03935C20.6639 1.83098 20.0517 1.37068 19.9405 1.37704C19.923 1.37804 19.8946 1.36718 19.8775 1.3529C19.8603 1.33863 19.7754 1.31058 19.6889 1.29057C19.6024 1.27056 19.5227 1.24696 19.5118 1.23812C19.5008 1.2293 19.4231 1.22879 19.3389 1.237C19.2548 1.24521 19.1755 1.24326 19.1627 1.23265C19.15 1.22204 19.1274 1.21737 19.1127 1.22226C19.0979 1.22716 19.0997 1.23694 19.1166 1.244C19.305 1.32249 19.7773 1.59525 19.9944 1.75094C20.4271 2.06111 20.5487 2.15682 20.5334 2.17525C20.5089 2.20479 20.3188 2.09519 20.0061 1.87112C19.6422 1.61046 19.5689 1.56281 19.4893 1.53531C19.4529 1.52275 19.4192 1.50073 19.4143 1.48638C19.4094 1.47202 19.3882 1.46016 19.3672 1.46002C19.3462 1.45988 19.29 1.43777 19.2423 1.41088C19.1946 1.384 19.0975 1.34562 19.0266 1.32561C18.9557 1.30559 18.8171 1.26551 18.7186 1.23655C18.45 1.15754 18.2751 1.12991 18.2331 1.15988C18.2124 1.17463 18.1858 1.17864 18.174 1.16881C18.1357 1.13701 18.0466 1.18382 17.9369 1.29344C17.8779 1.35236 17.8097 1.40859 17.7854 1.41839C17.7247 1.44279 17.719 1.45351 17.7518 1.48079C17.7674 1.4937 17.7864 1.49667 17.7941 1.48743ZM20.4411 3.58985C20.8745 3.75808 20.9665 3.77761 21.3003 3.77235C21.5043 3.76913 21.5416 3.79011 21.3888 3.82218L21.3053 3.83972L21.3625 3.86353C21.3939 3.87662 21.47 3.89569 21.5315 3.9059C21.5931 3.91612 21.6702 3.93227 21.7029 3.9418C21.8017 3.97063 22.3245 3.98767 22.745 3.97577C22.8695 3.97225 23.028 3.96784 23.0974 3.96598C23.1667 3.96413 23.255 3.94934 23.2937 3.93313C23.3323 3.91693 23.4707 3.89584 23.601 3.88627C23.7314 3.87669 23.8463 3.85898 23.8564 3.84691C23.8665 3.83483 23.9094 3.82602 23.9518 3.82733C24.3484 3.83955 24.5977 3.72239 24.333 3.64811C24.2864 3.63503 24.1905 3.59819 24.12 3.56624C23.9989 3.51138 23.9774 3.51151 23.7322 3.56863C23.4678 3.63021 22.9959 3.69954 22.8861 3.69296C22.8528 3.69095 22.7701 3.69137 22.7024 3.69387C22.5069 3.70111 22.5818 3.6717 22.844 3.63825C23.2588 3.58534 23.4636 3.54764 23.7506 3.4714L23.8454 3.44621L23.7811 3.41442C23.7458 3.39693 23.6827 3.37463 23.6409 3.36488C23.5992 3.35512 23.5483 3.33872 23.5279 3.32843C23.3921 3.25985 23.1991 3.21912 23.1476 3.24813C23.0626 3.29598 22.7382 3.35541 22.6888 3.33217C22.665 3.32099 22.6379 3.3211 22.6285 3.33241C22.6086 3.35632 22.2587 3.39336 22.2354 3.37402C22.2268 3.36686 22.1853 3.36445 22.1432 3.36867C21.9327 3.38979 21.6076 3.39491 21.4679 3.37932C21.3817 3.36971 21.2671 3.3683 21.2133 3.37619C21.1595 3.38408 21.1035 3.38061 21.0889 3.36849C21.0743 3.35637 21.052 3.35283 21.0394 3.36064C21.0268 3.36844 21.0008 3.3653 20.9818 3.35365C20.9627 3.342 20.877 3.34703 20.7913 3.36481C20.7055 3.3826 20.5679 3.40445 20.4854 3.41338C20.4029 3.4223 20.29 3.43498 20.2345 3.44154L20.1336 3.45348L20.2091 3.49129C20.2507 3.51209 20.3551 3.55644 20.4411 3.58985ZM21.9567 4.12972C22.162 4.11413 22.187 4.10828 22.0675 4.10382C21.9826 4.10066 21.9041 4.10032 21.893 4.10307C21.882 4.10582 21.7932 4.08763 21.6958 4.06266C21.5532 4.02612 21.5117 4.02561 21.4831 4.06005C21.4636 4.08359 21.4289 4.11332 21.406 4.12613C21.3539 4.15532 21.5987 4.15691 21.9567 4.12972ZM29.5277 10.831C29.5484 10.838 29.5702 10.8293 29.5761 10.8117C29.589 10.7732 29.6978 10.7793 29.9372 10.8319C30.0343 10.8532 30.1448 10.8734 30.1827 10.8766C30.2206 10.8799 30.2667 10.8951 30.2851 10.9104C30.3035 10.9257 30.3256 10.9298 30.3341 10.9195C30.3426 10.9093 30.3649 10.9135 30.3835 10.929C30.4022 10.9445 30.4318 10.9563 30.4493 10.9552C30.4668 10.9542 30.6104 10.9788 30.7683 11.01C30.9262 11.0411 31.098 11.0688 31.15 11.0714C31.202 11.074 31.2528 11.083 31.2628 11.0913C31.2729 11.0996 31.3264 11.1015 31.3817 11.0954C31.4371 11.0893 31.4979 11.0972 31.5169 11.113C31.5451 11.1364 31.5569 11.1303 31.5814 11.0798C31.6284 10.9828 31.6058 10.9634 31.4257 10.9457C31.3332 10.9366 31.2509 10.9237 31.243 10.9171C31.235 10.9105 31.2092 10.9092 31.1855 10.9142C31.1619 10.9193 30.9522 10.8811 30.7195 10.8295C30.4867 10.7779 30.2851 10.7394 30.2714 10.7439C30.2577 10.7484 30.2267 10.7357 30.2025 10.7156C30.1783 10.6955 30.1212 10.6833 30.0756 10.6886C30.03 10.6938 29.9865 10.6932 29.9789 10.6871C29.9449 10.6603 29.6494 10.5914 29.4829 10.5716L29.3 10.5499L29.3745 10.6639C29.4612 10.7964 29.4769 10.8136 29.5277 10.831ZM29.9913 11.0674C30.235 11.1818 30.3456 11.2119 30.8331 11.296C31.3466 11.3847 31.3458 11.3847 31.4154 11.3026L31.4753 11.2319L31.3791 11.2232C31.3262 11.2184 31.2411 11.214 31.1901 11.2134C31.139 11.2128 31.0732 11.2041 31.044 11.194C31.0147 11.1839 30.9091 11.1633 30.8095 11.1484C30.7098 11.1334 30.4314 11.0736 30.1908 11.0154C29.5699 10.8653 29.5641 10.8668 29.9913 11.0674ZM29.2663 10.4804C29.3061 10.4325 29.458 10.428 29.6502 10.4691C29.741 10.4885 29.91 10.525 30.0259 10.5503C30.1418 10.5755 30.4061 10.6281 30.6133 10.6673C30.8204 10.7064 30.9968 10.7442 31.0053 10.7512C31.0137 10.7582 31.0868 10.7692 31.1676 10.7756C31.2485 10.782 31.322 10.7934 31.331 10.8008C31.3625 10.827 31.5189 10.8055 31.5231 10.7744C31.5312 10.7147 31.4317 10.6641 31.3015 10.6619C31.1874 10.66 30.7948 10.5764 30.7586 10.5464C30.7515 10.5405 30.7053 10.5377 30.6561 10.5401C30.6068 10.5426 30.5544 10.5346 30.5396 10.5222C30.5247 10.5099 30.4897 10.5001 30.4618 10.5004C30.4339 10.5008 30.2775 10.4721 30.1143 10.4368C29.9511 10.4014 29.774 10.37 29.7208 10.367C29.6676 10.3639 29.617 10.3556 29.6084 10.3484C29.5998 10.3413 29.4938 10.3456 29.3729 10.3579C29.139 10.3819 29.0613 10.3604 29.1421 10.2941C29.2343 10.2184 29.1425 10.1733 29.0366 10.2424C28.9953 10.2694 28.9974 10.2802 29.0555 10.3395C29.2112 10.4985 29.237 10.5157 29.2663 10.4804ZM19.9386 2.63477C20.0264 2.63872 20.1676 2.62754 20.2523 2.6099C20.337 2.59227 20.4507 2.56924 20.505 2.55873C20.7257 2.51602 20.7657 2.44587 20.5786 2.42971C20.5395 2.42633 20.4684 2.409 20.4205 2.3912C20.3726 2.3734 20.3283 2.36928 20.3219 2.38204C20.3114 2.40332 19.9544 2.53493 19.8002 2.57441C19.6986 2.60044 19.7587 2.62667 19.9386 2.63477ZM29.5472 10.2411C29.6642 10.2495 29.8247 10.2718 29.9039 10.2907C29.9832 10.3096 30.157 10.3384 30.2902 10.3547C30.4235 10.371 30.5806 10.3974 30.6395 10.4133C30.873 10.4767 31.4087 10.551 31.4129 10.5206C31.4247 10.4335 31.2377 10.2782 31.14 10.2942C31.1226 10.297 31.0443 10.2905 30.8752 10.272C30.8334 10.2674 30.7725 10.2559 30.7398 10.2464C30.7072 10.2369 30.637 10.2265 30.584 10.2232C30.3618 10.2097 29.9498 10.0792 29.9872 10.0341C30.0037 10.0142 30.1662 10.0229 30.1929 10.0451C30.2027 10.0532 30.24 10.0557 30.2758 10.0508C30.3116 10.0458 30.347 10.0468 30.3544 10.053C30.3891 10.0818 30.9996 10.163 31.1493 10.1588L31.2253 10.1566L31.194 10.0923C31.1532 10.0086 30.7985 9.90075 30.6367 9.92283C30.6169 9.92552 30.5329 9.92323 30.4499 9.91775C30.294 9.90744 30.1945 9.91777 30.1036 9.9537C30.0261 9.98435 29.4697 10.1517 29.4469 10.1513C29.4237 10.1508 29.2989 10.2111 29.2837 10.2302C29.2779 10.2375 29.2869 10.2396 29.3038 10.2348C29.3207 10.2299 29.4302 10.2328 29.5472 10.2411ZM18.5323 1.08582C18.6526 1.11232 18.7776 1.12205 18.8252 1.10863C18.8709 1.09575 18.9827 1.09047 19.0737 1.09689C19.1647 1.10331 19.2531 1.10893 19.2702 1.10937C19.2874 1.10981 19.3647 1.11159 19.442 1.11332C19.5194 1.11506 19.5992 1.12237 19.6195 1.12958C19.6523 1.14123 19.6534 1.13992 19.6293 1.11781C19.5745 1.06746 19.212 0.869352 19.1366 0.84859C19.0939 0.83681 19.0127 0.80521 18.9562 0.778366C18.8215 0.714345 18.7966 0.715902 18.6236 0.799161C18.4947 0.861249 18.292 1.01434 18.3143 1.03283C18.3188 1.03656 18.4169 1.0604 18.5323 1.08582ZM19.1845 0.764554C19.2951 0.814574 19.4807 0.909616 19.597 0.975743C19.8277 1.10695 19.878 1.10218 19.7319 0.962943C19.6114 0.848074 19.5785 0.795686 19.606 0.762506C19.6425 0.71865 19.9235 1.01552 19.9833 1.16104C19.9978 1.1961 20.1093 1.28708 20.3553 1.46451C20.8133 1.79485 21.1116 2.05847 21.1243 2.1441C21.1317 2.19463 21.1694 2.23639 21.3214 2.36257C21.4247 2.44837 21.511 2.53277 21.5133 2.55012C21.5157 2.56899 21.5767 2.59492 21.665 2.61462C21.7463 2.63275 21.8747 2.66357 21.9503 2.68312C22.1442 2.73321 22.161 2.69313 22.0233 2.50898C21.9205 2.37151 21.1537 1.68577 21.1073 1.68986C21.0702 1.69313 20.9599 1.59276 20.9643 1.55977C20.9669 1.5413 20.9547 1.52968 20.9323 1.52907C20.9124 1.52854 20.8319 1.48467 20.7534 1.4316C20.467 1.23788 20.2336 1.10985 20.0817 1.06304C19.9624 1.0263 19.9611 1.02496 19.9988 0.979553C20.178 0.763758 22.1232 2.27248 22.1757 2.66803C22.1866 2.74965 22.2138 2.76413 22.5 2.84042C22.6201 2.87243 22.755 2.91477 22.7999 2.93449C23.0886 3.06138 23.5941 3.21286 23.608 3.17666C23.6196 3.14675 23.5289 2.99785 23.4436 2.9068C23.4065 2.86716 23.3614 2.8094 23.3433 2.77843C23.314 2.72815 23.1501 2.55035 22.8996 2.29697C22.7589 2.15472 21.7502 1.30786 21.7179 1.30496C21.7017 1.30349 21.6165 1.25243 21.5288 1.1915C21.441 1.13056 21.3394 1.06319 21.303 1.0418C21.1948 0.97827 21.3271 1.00621 21.4483 1.07248C21.8111 1.2709 22.6992 1.96369 22.9654 2.256C23.0021 2.29622 23.0725 2.3698 23.1219 2.41952C23.3857 2.68491 23.6197 2.991 23.676 3.14444C23.7133 3.2461 23.7779 3.29151 23.9975 3.37061C24.2008 3.44381 24.2101 3.42462 24.0728 3.21487C24.0048 3.1111 23.9407 3.01063 23.9303 2.99158C23.9198 2.97254 23.9079 2.95242 23.9037 2.94686C23.8996 2.94131 23.8865 2.91194 23.8746 2.8816C23.8627 2.85126 23.8432 2.82729 23.8312 2.82835C23.8193 2.8294 23.7981 2.80514 23.7843 2.77443C23.7704 2.74372 23.7325 2.69017 23.7001 2.65543C23.6404 2.59143 23.59 2.52753 23.5478 2.46207C23.535 2.44226 23.4862 2.38709 23.4393 2.33948C23.3924 2.29187 23.3526 2.23811 23.3508 2.22002C23.349 2.20192 23.3221 2.17289 23.291 2.1555C23.2598 2.13812 23.1748 2.04898 23.102 1.95743C22.9634 1.78314 22.6384 1.50097 22.4546 1.39541C22.4012 1.36478 22.3328 1.31786 22.3024 1.29115C22.2721 1.26444 22.204 1.22768 22.1511 1.20945C22.0983 1.19123 21.9914 1.1442 21.9135 1.10494C21.8271 1.06138 21.7038 1.02598 21.5969 1.01408C21.3932 0.991423 21.3476 0.965176 21.4008 0.901122C21.5009 0.780504 21.9371 0.906974 22.3658 1.18089C22.4357 1.22558 22.507 1.26418 22.5243 1.26668C22.6504 1.28489 23.9775 2.38591 24.0185 2.50639C24.0226 2.51853 24.0661 2.56272 24.1152 2.60458C24.2329 2.70497 24.4026 2.91725 24.4062 2.96849C24.4084 2.99987 24.4024 2.9997 24.3798 2.96778C24.3637 2.94502 24.2917 2.86781 24.2199 2.79621C24.148 2.72461 24.0777 2.65221 24.0636 2.63532C24.0495 2.61842 23.9202 2.49813 23.7763 2.36799C23.6324 2.23786 23.4612 2.07926 23.3959 2.01553C23.2784 1.90075 23.202 1.88091 23.2912 1.98832C23.3153 2.01731 23.4164 2.13829 23.516 2.25717C23.6996 2.47645 23.8503 2.67587 23.902 2.76809C23.9177 2.79602 23.9969 2.92009 24.078 3.0438C24.1591 3.16751 24.2275 3.28263 24.23 3.29959C24.2325 3.31656 24.2471 3.34081 24.2623 3.35346C24.2776 3.36612 24.2936 3.39939 24.298 3.4274C24.3049 3.47136 24.3315 3.48953 24.4924 3.5605C24.5949 3.60571 24.7207 3.66993 24.7718 3.70322C24.9523 3.8207 25.1647 3.94007 25.2103 3.94968C25.2358 3.95503 25.2971 3.98463 25.3467 4.01545C25.3963 4.04626 25.4594 4.07882 25.487 4.08779C25.5145 4.09675 25.5651 4.11345 25.5994 4.12489C25.6651 4.14681 25.5251 3.77103 25.4418 3.70186C25.4235 3.68665 25.4084 3.6525 25.4083 3.62596C25.4082 3.59942 25.4013 3.57831 25.393 3.57904C25.3847 3.57977 25.3591 3.54464 25.3361 3.50097C25.313 3.4573 25.2749 3.40545 25.2513 3.38575C25.2277 3.36605 25.1945 3.31721 25.1776 3.27723C25.1607 3.23724 25.1333 3.19252 25.1169 3.17785C25.1004 3.16319 25.0614 3.09675 25.0301 3.03022C24.9988 2.96369 24.9585 2.90423 24.9406 2.8981C24.9227 2.89197 24.8991 2.85838 24.8882 2.82347C24.8774 2.78856 24.8372 2.72737 24.799 2.6875C24.7609 2.64764 24.7243 2.59924 24.7177 2.57996C24.7069 2.54825 24.5691 2.3687 24.4536 2.23594C24.4287 2.20739 24.4047 2.17317 24.4002 2.1599C24.3627 2.04963 24.0459 1.79076 23.5029 1.42669C23.3955 1.35469 23.3694 1.32872 23.3852 1.30971C23.3992 1.29287 23.4344 1.30929 23.4985 1.36247C23.5496 1.40494 23.6196 1.44942 23.6541 1.46133C23.6886 1.47324 23.7867 1.53308 23.8721 1.5943C23.9574 1.65552 24.0911 1.75037 24.1691 1.80509C24.2723 1.87747 24.3535 1.95772 24.4672 2.09971C24.6238 2.29528 24.9016 2.67231 24.9371 2.73746C24.9475 2.75656 24.9639 2.77629 24.9735 2.7813C24.9831 2.78632 25.0358 2.86094 25.0905 2.94713C25.1452 3.03333 25.2327 3.16442 25.2851 3.23847C25.4757 3.50825 25.6473 3.84902 25.7213 4.10443C25.7573 4.22903 25.79 4.25997 26.0326 4.39894C26.303 4.55388 26.3476 4.51214 26.2091 4.23397C26.1993 4.2142 26.1775 4.13693 26.1607 4.06226C26.144 3.98759 26.1217 3.91085 26.1114 3.89172C26.101 3.8726 26.0644 3.79968 26.0302 3.72967C25.9959 3.65967 25.9587 3.59479 25.9476 3.5855C25.9364 3.57621 25.8948 3.49902 25.8552 3.41397C25.8156 3.32892 25.7662 3.25355 25.7456 3.24649C25.7249 3.23942 25.6986 3.2034 25.6871 3.16643C25.6756 3.12947 25.6568 3.10005 25.6454 3.10105C25.634 3.10206 25.5735 3.03829 25.511 2.95934C25.4485 2.8804 25.332 2.73914 25.2523 2.64546C24.9943 2.34239 24.9458 2.27853 24.9315 2.22242C24.9086 2.13328 24.9525 2.15487 25.0724 2.29184C25.1341 2.36243 25.2192 2.4563 25.2613 2.50045C25.3471 2.59043 25.5089 2.78658 25.6578 2.98127C25.7124 3.0526 25.7808 3.13895 25.8099 3.17316C26.0244 3.4255 26.2877 4.0061 26.3864 4.44455C26.4272 4.62575 26.4408 4.64225 26.6893 4.81216C26.8338 4.91089 26.9384 4.90817 26.8645 4.8076C26.832 4.76343 26.7976 4.63708 26.7581 4.41624C26.7472 4.35555 26.7283 4.29748 26.7162 4.2872C26.704 4.27693 26.6969 4.22827 26.7004 4.17908C26.7038 4.12988 26.6952 4.08014 26.6812 4.06854C26.6672 4.05693 26.6585 4.03841 26.6619 4.02738C26.6652 4.01635 26.636 3.93367 26.5969 3.84365C26.5579 3.75362 26.5233 3.63996 26.5202 3.59108C26.517 3.5422 26.4946 3.46568 26.4704 3.42105C26.4462 3.37641 26.4261 3.33154 26.4259 3.32132C26.4256 3.31111 26.3828 3.23331 26.3307 3.14844C26.2786 3.06357 26.2293 2.9654 26.2212 2.93029C26.2067 2.86814 26.1659 2.8007 26.0283 2.61182C25.9914 2.56129 25.942 2.49143 25.9184 2.45659C25.8595 2.36956 25.6639 2.20084 25.3744 1.98744L25.131 1.80796L25.1733 1.76968C25.2142 1.73259 25.2218 1.73642 25.416 1.89252C25.5262 1.98113 25.6783 2.09777 25.754 2.15174C25.8642 2.23035 25.9159 2.28612 26.0143 2.4324C26.0818 2.53281 26.1617 2.64569 26.1918 2.68322C26.2827 2.79659 26.6034 3.4164 26.6243 3.51908C26.6616 3.70284 26.7129 3.90073 26.7425 3.9751C26.8026 4.12654 26.9349 4.67206 26.9587 4.86684L26.9737 4.98972L27.622 5.51738C27.9786 5.80759 28.275 6.03947 28.2807 6.03266C28.3068 6.00123 28.1631 5.39372 28.1214 5.35908C28.1058 5.34612 28.0383 5.13294 28.0386 5.09752C28.0387 5.08687 28.0228 5.05428 28.0033 5.02509C27.9837 4.99589 27.9482 4.90936 27.9242 4.83278C27.8795 4.68965 27.5883 4.03302 27.5587 4.00842C27.5496 4.00086 27.518 3.94496 27.4885 3.88421C27.459 3.82346 27.4234 3.75303 27.4095 3.7277C27.2978 3.52553 27.2693 3.46675 27.2607 3.4214C27.2553 3.39283 27.2039 3.32542 27.1464 3.2716C27.0584 3.18927 27.0458 3.16709 27.0669 3.1318C27.1328 3.02131 27.324 3.2773 27.584 3.82414C27.6851 4.03668 27.7561 4.17239 27.7742 4.18736C27.803 4.21133 27.977 4.60357 27.9861 4.66519C27.9903 4.69355 28 4.72198 28.0077 4.72835C28.0154 4.73473 28.0371 4.79344 28.056 4.85881C28.0749 4.92419 28.1093 5.02393 28.1323 5.08047C28.2611 5.3958 28.345 5.70037 28.391 6.01889C28.416 6.19198 28.4603 6.25106 28.8047 6.57073C29.0733 6.82001 29.3023 7.08255 29.6311 7.51805C29.8801 7.84788 29.9737 7.93094 29.8615 7.72262C29.8219 7.64907 29.7957 7.58147 29.8033 7.57239C29.8108 7.56331 29.8026 7.54298 29.7851 7.5272C29.7556 7.50067 29.7566 7.49964 29.7984 7.51349C29.8586 7.53349 29.8341 7.3445 29.7475 7.12199C29.714 7.03585 29.6689 6.88881 29.6473 6.79524C29.6256 6.70167 29.6001 6.61862 29.5906 6.6107C29.5811 6.60277 29.5719 6.56674 29.5702 6.53062C29.5685 6.49451 29.5557 6.45549 29.5417 6.44392C29.5278 6.43234 29.522 6.41616 29.5288 6.40795C29.5356 6.39974 29.5205 6.35797 29.4952 6.31513C29.4698 6.27229 29.4339 6.16149 29.4153 6.06892C29.3966 5.97636 29.376 5.89616 29.3694 5.8907C29.3629 5.88524 29.3471 5.83841 29.3344 5.78662C29.3086 5.68177 29.2531 5.5319 29.1559 5.30447C28.9654 4.85854 28.9766 4.77852 29.1754 5.16608C29.2833 5.37657 29.3354 5.49944 29.3906 5.67357C29.4147 5.74988 29.4681 5.89256 29.5093 5.99064C29.5504 6.08873 29.5955 6.227 29.6096 6.29792C29.6237 6.36884 29.643 6.43339 29.6526 6.44137C29.6622 6.44934 29.6716 6.48698 29.6733 6.525C29.6751 6.56303 29.6963 6.63933 29.7205 6.69457C29.7447 6.7498 29.775 6.84257 29.788 6.90073C29.801 6.95888 29.8256 7.04144 29.8426 7.0842C29.9407 7.3308 29.9685 7.48323 29.9303 7.56497C29.8985 7.63304 29.9691 7.79053 30.029 7.78525C30.0623 7.78231 30.0876 7.68601 30.061 7.66388C30.0467 7.65199 30.026 7.5709 30.015 7.48369C30.004 7.39647 29.9841 7.30827 29.9709 7.28768C29.9576 7.26709 29.9551 7.22952 29.9653 7.20418C29.9759 7.17784 29.9669 7.14409 29.9444 7.12536C29.9227 7.10735 29.903 7.05031 29.9006 6.9986C29.8982 6.9469 29.8789 6.86511 29.8577 6.81685C29.8365 6.76859 29.81 6.66121 29.7988 6.57822C29.7876 6.49524 29.7633 6.4039 29.7448 6.37525C29.7263 6.34659 29.6981 6.26107 29.6822 6.1852C29.647 6.01767 29.6328 5.97293 29.5629 5.8111C29.4258 5.49386 29.3889 5.38085 29.4028 5.32142C29.4111 5.28623 29.3909 5.19505 29.3579 5.1188C29.3249 5.04255 29.3003 4.95361 29.3033 4.92114C29.3062 4.88868 29.2944 4.85031 29.277 4.83587C29.2596 4.82143 29.2436 4.79532 29.2415 4.77785C29.234 4.71569 29.1156 4.44944 29.0836 4.42278C29.0658 4.40788 29.0372 4.35561 29.0202 4.30663C29.0032 4.25764 28.9619 4.1866 28.9285 4.14875C28.8951 4.11089 28.8408 4.02481 28.808 3.95745C28.7425 3.82314 28.5569 3.60398 28.4074 3.48434C28.2848 3.38632 28.2034 3.29859 28.1573 3.21477C28.1371 3.17815 28.1147 3.14871 28.1074 3.14935C28.0799 3.15178 28.1139 3.23615 28.234 3.46308C28.3022 3.59185 28.369 3.71833 28.3826 3.74413C28.6107 4.17709 28.7566 4.53959 28.769 4.70386C28.7826 4.88262 28.698 4.7184 28.6633 4.49855C28.6564 4.45426 28.6255 4.37934 28.5947 4.33207C28.5639 4.28481 28.5351 4.23323 28.5307 4.21746C28.5263 4.2017 28.4928 4.13848 28.4564 4.07698C28.4199 4.01548 28.3738 3.93303 28.3539 3.89375C28.334 3.85447 28.2809 3.75446 28.236 3.67151C28.1911 3.58855 28.1169 3.44089 28.0712 3.34338C28.0255 3.24586 27.9805 3.15981 27.9713 3.15215C27.9621 3.1445 27.9544 3.11865 27.9543 3.09472C27.9542 3.07079 27.914 3.0093 27.865 2.95808C27.8159 2.90687 27.7373 2.82504 27.6903 2.77624C27.6433 2.72744 27.5129 2.60711 27.4007 2.50885C27.1912 2.3255 27.1597 2.28439 27.1953 2.24144C27.2259 2.20463 27.5851 2.4829 27.7377 2.66167C28.0465 3.02337 28.0273 3.00454 28.0489 2.96766C28.0726 2.92735 28.1293 2.98176 28.1417 3.05673C28.152 3.1187 28.3053 3.26141 28.5044 3.39445C28.6042 3.46114 28.6959 3.54061 28.7543 3.61093C28.9414 3.83622 29.0179 3.93927 29.0367 3.99142C29.0473 4.02081 29.0878 4.09716 29.1266 4.16108C29.1655 4.225 29.1916 4.28405 29.1848 4.29229C29.1779 4.30053 29.1919 4.32353 29.2158 4.3434C29.2398 4.36326 29.2843 4.45191 29.3149 4.54039C29.3967 4.77737 29.4812 5.00503 29.5355 5.13493C29.73 5.59975 29.8098 5.88496 29.7549 5.91968C29.7276 5.93702 29.7277 5.94069 29.7557 5.93355C29.808 5.92014 29.8831 6.16145 30.0178 6.77618C30.0481 6.91407 30.0796 7.04677 30.088 7.07105C30.1271 7.18485 30.1859 7.49113 30.1936 7.62104C30.1983 7.70038 30.2093 7.79927 30.218 7.84079C30.2318 7.90598 30.2287 7.91343 30.1956 7.89542C30.0966 7.84164 30.1176 7.92808 30.2694 8.19937C30.5207 8.64845 30.539 8.62448 30.4753 7.92906C30.4633 7.7976 30.4409 7.5199 30.4256 7.31199C30.4103 7.10405 30.3912 6.92849 30.3832 6.92187C30.3703 6.91116 30.3635 6.78669 30.3713 6.70447C30.3729 6.68777 30.3456 6.57486 30.3106 6.45356C30.2757 6.33225 30.2524 6.22663 30.2588 6.21884C30.2653 6.21105 30.2574 6.18637 30.2413 6.16398C30.2166 6.12977 30.2104 6.13121 30.202 6.17308C30.1754 6.30564 30.1321 6.18591 30.1002 5.89202C30.0653 5.56932 30.0542 5.49305 30.0303 5.41409C30.0233 5.39093 29.9904 5.27842 29.9571 5.16406C29.9239 5.04971 29.8815 4.90391 29.8629 4.84007C29.7876 4.58204 29.6847 4.38567 29.5354 4.21506C29.235 3.87172 29.1496 3.75963 29.1699 3.73522C29.2026 3.69587 29.5446 4.03471 29.7288 4.2889C29.8506 4.45707 29.9674 4.82295 30.0823 5.3964C30.1169 5.5692 30.1629 5.69774 30.2016 5.72984C30.2205 5.74554 30.3215 6.06422 30.3999 6.35559C30.4149 6.41132 30.4606 6.74301 30.5015 7.09271C30.5423 7.44239 30.5857 7.73268 30.5978 7.73779C30.6575 7.76302 30.7847 8.23641 30.8253 8.58417C30.8717 8.98246 30.9111 9.20315 30.9539 9.30449L30.9948 9.40161L31.0677 9.38763C31.1646 9.36903 31.1646 9.36902 31.1535 9.19516C31.1481 9.11199 31.1423 9.00902 31.1404 8.96633C31.1386 8.92364 31.1136 8.77699 31.085 8.64043C31.0344 8.39911 31.0395 8.31865 31.1019 8.37048C31.1574 8.41657 31.2443 8.76514 31.2699 9.04442C31.2946 9.31286 31.3282 9.39572 31.397 9.35738C31.4791 9.31162 31.4706 9.0325 31.3659 8.33988C31.3327 8.11985 31.3411 8.04695 31.3908 8.12378C31.4288 8.18246 31.4703 8.37155 31.5108 8.66979C31.5274 8.79246 31.5516 8.90165 31.5646 8.91242C31.5949 8.93757 31.6061 9.05313 31.5937 9.21272C31.5845 9.33047 31.6535 9.40757 31.7086 9.34118C31.7148 9.33378 31.7507 9.3261 31.7885 9.32411C31.867 9.31997 31.881 9.28082 31.9044 8.99964C31.9108 8.92368 31.9233 8.85263 31.9324 8.84176C31.9414 8.83088 31.9166 8.50713 31.8773 8.12229C31.8379 7.73747 31.8141 7.41254 31.8243 7.40023C31.8345 7.38793 31.8261 7.35499 31.8055 7.32703C31.785 7.29908 31.7737 7.26953 31.7804 7.26138C31.7922 7.24722 31.7521 7.16873 31.6684 7.04186C31.608 6.95039 31.6023 7.03779 31.6397 7.4831C31.6718 7.86504 31.6681 7.93375 31.6163 7.92625C31.5943 7.92307 31.5406 7.47621 31.523 7.14971C31.5204 7.10021 31.506 7.00696 31.491 6.9425C31.4641 6.82644 31.4533 6.77311 31.3684 6.33703C31.3325 6.15263 31.3132 6.10463 31.2604 6.06789C31.212 6.03422 31.1819 5.97585 31.1387 5.83155C31.1071 5.72616 31.0773 5.63667 31.0725 5.63268C31.0677 5.62869 31.0249 5.54246 30.9774 5.44106C30.8769 5.2266 30.86 5.19499 30.7186 4.95631C30.6603 4.85799 30.5893 4.75813 30.5607 4.7344C30.5321 4.71067 30.5146 4.68417 30.5218 4.67553C30.5596 4.62995 30.4161 4.48092 30.3473 4.49436C30.2308 4.5171 30.2311 4.51942 30.3882 4.83643C30.4975 5.05705 30.522 5.09986 30.5066 5.04274C30.4834 4.95666 30.5612 4.959 30.6492 5.04703C30.8258 5.22374 30.8853 5.3205 30.9243 5.49415C30.9298 5.51905 30.9667 5.59804 31.0062 5.66967C31.0686 5.78277 31.1254 6.04131 31.1597 6.36762C31.1627 6.39614 31.1821 6.49032 31.2028 6.57691C31.2234 6.66351 31.2553 6.89938 31.2736 7.10108C31.2984 7.37528 31.3188 7.47777 31.3544 7.50738C31.4051 7.54946 31.5164 7.84767 31.4923 7.87672C31.4844 7.8862 31.4907 7.90451 31.5062 7.91742C31.5218 7.93032 31.5297 7.94752 31.5238 7.95562C31.5179 7.96373 31.5316 8.03545 31.5542 8.11501C31.7337 8.74486 31.7913 9.22684 31.6757 9.13085C31.6599 9.11776 31.6378 9.01962 31.6266 8.91276C31.6153 8.80589 31.587 8.63776 31.5635 8.53911C31.5225 8.3665 31.507 8.28536 31.4491 7.9375C31.4249 7.7927 31.3374 7.56497 31.3158 7.59095C31.311 7.59677 31.3033 7.66423 31.2987 7.74085C31.281 8.03803 31.2132 8.04474 31.2164 7.749C31.2174 7.6529 31.2075 7.47072 31.1945 7.34415C31.1814 7.21759 31.1759 7.10773 31.1823 7.10001C31.2008 7.07777 31.2035 6.87726 31.1855 6.86234C31.1501 6.83294 31.0432 6.4198 31.019 6.21854C31.0023 6.08028 30.9616 5.93546 30.9032 5.80694C30.8537 5.69789 30.7827 5.53326 30.7455 5.4411C30.7082 5.34894 30.6625 5.26083 30.6439 5.2453C30.6253 5.22976 30.5957 5.18347 30.5781 5.14241C30.5314 5.03313 30.5134 5.08196 30.5579 5.19737C30.6032 5.31481 30.6259 5.54574 30.5892 5.51525C30.575 5.50349 30.5598 5.47102 30.5553 5.4431C30.5461 5.38552 30.3726 4.99123 30.2953 4.8524C30.114 4.52672 30.041 4.38786 30.0378 4.36259C30.0357 4.34675 30.001 4.31424 29.9606 4.29037C29.8804 4.24304 29.7759 4.09822 29.7602 4.01286C29.7547 3.98329 29.7322 3.9529 29.71 3.94532C29.6651 3.92998 29.5132 3.71854 29.5185 3.67897C29.5204 3.66509 29.5068 3.64852 29.4882 3.64217C29.4368 3.62459 29.334 3.46782 29.3426 3.4202C29.3519 3.36887 29.2632 3.3201 29.1695 3.32503C29.0954 3.32893 28.9412 3.28885 28.9001 3.25506C28.8127 3.18308 28.6157 3.05846 28.5576 3.0384C28.5206 3.02563 28.45 2.98161 28.4005 2.94058C28.3511 2.89955 28.2555 2.83604 28.1879 2.79945C28.1048 2.75441 28.0528 2.71266 28.0271 2.67025C28.0017 2.62835 27.9682 2.60106 27.9261 2.58789C27.8496 2.56401 27.6756 2.44086 27.4736 2.26761C27.3296 2.14417 27.3209 2.14007 27.262 2.1683C27.2002 2.19791 27.1081 2.17917 27.0118 2.1174C26.9833 2.09908 26.9527 2.07977 26.944 2.07449C26.8878 2.04055 26.9134 2.11701 26.9897 2.21107C27.0759 2.3173 27.3132 2.64011 27.4045 2.77532C27.4281 2.8102 27.4861 2.89561 27.5334 2.96512C27.715 3.23181 27.9717 3.67031 28.0051 3.77103C28.0421 3.88225 28.022 3.92222 27.9813 3.81863C27.9681 3.78522 27.9538 3.75349 27.9495 3.74811C27.9075 3.69538 27.7717 3.49042 27.5823 3.19377C27.294 2.74252 27.2028 2.6086 27.1578 2.57069C27.1381 2.5541 27.0949 2.49551 27.0618 2.44051C27.0287 2.38551 26.9871 2.32344 26.9695 2.30257C26.9518 2.28169 26.8754 2.18392 26.7997 2.08529C26.7241 1.98666 26.6541 1.89849 26.6441 1.88935C26.5577 1.80972 25.9606 1.36454 25.8705 1.31248C25.8071 1.2759 25.6856 1.19215 25.6003 1.12638C25.5151 1.06059 25.4361 1.00984 25.4248 1.01358C25.4136 1.01732 25.3667 0.989116 25.3207 0.950903C25.2746 0.912689 25.23 0.889827 25.2215 0.900098C25.2129 0.910368 25.2118 0.923612 25.2189 0.929528C25.277 0.977733 25.8335 1.60768 25.8968 1.69685C25.9412 1.75936 26.0217 1.86939 26.0757 1.94136C26.1297 2.01333 26.1762 2.09478 26.1789 2.12237C26.1859 2.19346 26.0431 2.07209 25.937 1.91674C25.8935 1.85313 25.8197 1.75654 25.773 1.7021C25.7263 1.64765 25.6463 1.55435 25.5951 1.49477C25.5439 1.43517 25.4716 1.35407 25.4344 1.31453C25.3527 1.22772 25.276 1.13233 25.2661 1.1052C25.2395 1.03204 24.908 0.766019 24.846 0.767921C24.7808 0.769908 24.7807 0.769112 24.8389 0.716492C24.8717 0.686808 24.8897 0.656099 24.8792 0.647427C24.8476 0.621157 24.7418 0.634504 24.7137 0.668307C24.6991 0.685856 24.6464 0.703807 24.5966 0.708197C24.5163 0.715281 24.51 0.719672 24.5404 0.747122C24.5593 0.76414 24.5853 0.79125 24.5982 0.807367C24.6111 0.823486 24.6907 0.917328 24.7752 1.0159C24.9582 1.22953 24.9825 1.26456 24.9635 1.28745C24.9437 1.31126 24.9081 1.27861 24.7286 1.07203C24.6435 0.974177 24.5443 0.869437 24.508 0.839275C24.4718 0.809119 24.4138 0.748374 24.3793 0.704283C24.3152 0.622619 24.0785 0.510491 23.8931 0.474031C23.8532 0.466173 23.769 0.444129 23.706 0.425043C23.6431 0.405958 23.5744 0.385162 23.5534 0.378835C23.5324 0.372506 23.5402 0.380339 23.5708 0.396242C23.8057 0.518489 23.9185 0.601585 24.2817 0.92017C24.674 1.26433 25.0111 1.6234 25.0651 1.75469C25.1006 1.84108 25.0379 1.79722 24.9599 1.68111C24.9209 1.62303 24.8824 1.57609 24.8744 1.57679C24.8663 1.5775 24.8212 1.53118 24.774 1.47386C24.6949 1.37767 24.0069 0.792594 23.8428 0.682008C23.7302 0.606112 23.5533 0.528964 23.4188 0.497117C23.2745 0.46296 23.2582 0.452376 23.258 0.392381C23.2578 0.345235 23.268 0.342243 23.4023 0.349968C23.4589 0.353221 23.4575 0.350203 23.3824 0.306499C23.2026 0.201885 22.8346 0.171211 22.765 0.255037C22.7114 0.319481 22.6998 0.310076 23.0029 0.4477C23.1046 0.493886 23.2311 0.562115 23.2841 0.599324C23.337 0.636528 23.3937 0.668891 23.4099 0.671241C23.4975 0.683886 24.5496 1.59989 24.5871 1.69611C24.5962 1.71957 24.4305 1.59402 24.1885 1.39411C23.7463 1.02875 23.3778 0.745389 23.3485 0.747981C23.3386 0.748852 23.3137 0.735657 23.2933 0.718659C23.2364 0.671413 22.7243 0.446308 22.4719 0.357571C22.4037 0.333596 22.2499 0.303167 22.1301 0.289948C22.0104 0.276733 21.9004 0.255969 21.8857 0.243804C21.871 0.231633 21.8596 0.228695 21.8605 0.237256C21.8613 0.245819 21.9398 0.296459 22.0349 0.349789C22.8011 0.779328 23.1117 0.98117 23.1713 1.08819C23.2034 1.14575 23.1641 1.13159 22.9987 1.02595C22.8491 0.930428 22.8124 0.932415 22.8792 1.03241C22.9667 1.16328 23.0682 1.38485 23.0505 1.40617C23.0413 1.41729 23.0253 1.4081 23.0128 1.38448C23.0009 1.36193 22.9613 1.30491 22.9249 1.25775C22.8885 1.2106 22.8631 1.15885 22.8685 1.14274C22.8739 1.12664 22.8543 1.0953 22.825 1.07309C22.7957 1.05089 22.7538 0.998807 22.7319 0.957349C22.6628 0.826584 22.413 0.655263 22.0265 0.473575C21.9509 0.438059 21.844 0.385681 21.7889 0.357175C21.6562 0.288542 21.3747 0.217988 21.3309 0.24241C21.3035 0.257663 21.2915 0.250746 21.2748 0.210036C21.2565 0.16562 21.2334 0.160548 21.1119 0.174329C20.8575 0.203178 20.889 0.273881 21.2012 0.374908C21.3047 0.408395 21.4521 0.46372 21.5288 0.49785C21.6055 0.53198 21.7142 0.578576 21.7702 0.601386C21.8263 0.624196 21.8868 0.654812 21.9047 0.669419C21.9226 0.684038 21.9828 0.713138 22.0384 0.734112C22.0941 0.755085 22.2049 0.811335 22.2848 0.859106C22.3646 0.906885 22.4485 0.953834 22.4712 0.96344C22.4938 0.973044 22.5056 0.989053 22.4973 0.999015C22.4831 1.0161 22.1932 0.904841 22.1002 0.846638C22.0766 0.831856 22.041 0.813451 22.0212 0.805736C21.9203 0.766559 21.5716 0.6145 21.472 0.566293C21.4095 0.536069 21.282 0.487929 21.1885 0.45932C21.0951 0.430707 21.0045 0.395575 20.9873 0.381249C20.9435 0.344894 20.6618 0.375851 20.63 0.420511C20.5987 0.464435 20.4696 0.506944 20.4195 0.489808C20.3999 0.483093 20.3745 0.488098 20.3632 0.500933C20.3315 0.536841 19.8763 0.505266 19.6221 0.449521C19.3948 0.399693 19.106 0.435402 19.0784 0.516731C19.0652 0.555826 19.0335 0.603005 19.008 0.621571C18.9515 0.662787 18.9407 0.654235 19.1845 0.764554ZM34.1764 12.998C34.2489 12.9079 34.2505 12.9021 34.1938 12.935C34.1368 12.968 34.0656 13.0717 34.0874 13.0898C34.0924 13.0939 34.1324 13.0526 34.1764 12.998ZM25.8584 5.96449C26.1281 5.97124 26.3645 5.98293 27.0968 6.02576C27.366 6.0415 27.6908 6.04721 27.8184 6.03843L28.0506 6.02249L27.7494 5.81505L27.5393 5.8356C27.4238 5.8469 27.2553 5.85525 27.1649 5.85417C27.0746 5.85308 26.9052 5.85869 26.7885 5.86663C26.6719 5.87458 26.5132 5.88032 26.4358 5.8794C26.3585 5.87848 26.1522 5.89025 25.9773 5.90556C25.8025 5.92087 25.6507 5.92615 25.64 5.9173C25.6294 5.90846 25.6137 5.90962 25.6052 5.91989C25.5778 5.95281 25.6087 5.95824 25.8584 5.96449ZM32.0278 10.9299C32.0832 10.9022 32.1939 10.8486 32.2739 10.8108C32.3538 10.7731 32.4834 10.7039 32.5619 10.6571C32.6405 10.6103 32.7744 10.5583 32.8595 10.5414C33.138 10.4863 33.1479 10.4809 33.2519 10.326C33.6652 9.71119 35.1 8.97906 36.2539 8.79428C36.2946 8.78776 36.3809 8.77008 36.4457 8.75498C36.9172 8.64508 38.2813 8.62619 38.421 8.72761C38.4814 8.7715 38.5094 8.76038 38.7135 8.61126C38.7937 8.55267 38.8953 8.49506 38.9393 8.48324C39.1511 8.42634 39.1538 8.3708 38.9461 8.34165C38.9114 8.33678 38.8694 8.32155 38.8529 8.3078C38.8233 8.28328 38.7428 8.25924 38.312 8.14643C38.1936 8.11544 38.0915 8.08568 38.085 8.0803C38.0785 8.07492 38.0146 8.06444 37.943 8.057C37.8713 8.04956 37.8085 8.04001 37.8034 8.03578C37.7983 8.03155 37.7614 8.02982 37.7213 8.03193C37.6813 8.03403 37.6232 8.02355 37.5922 8.00864C37.5613 7.99372 37.4753 7.98565 37.4011 7.9907C37.327 7.99575 37.2582 7.99317 37.2483 7.98496C37.2384 7.97675 37.1841 7.96792 37.1276 7.96533C37.0711 7.96275 37.0201 7.94659 37.0142 7.92941C37.0079 7.91101 37.0019 7.91063 36.9994 7.92849C36.9972 7.94515 36.9536 7.9529 36.9025 7.9457C36.8515 7.93851 36.7835 7.93649 36.7514 7.94123C36.7194 7.94597 36.6256 7.95057 36.5431 7.95145C35.8797 7.95853 35.0421 8.08714 34.9519 8.19576C34.94 8.21004 34.6646 8.29002 34.6176 8.29283C34.579 8.29513 34.4349 8.35835 34.4158 8.38134C34.4047 8.39476 34.3063 8.44579 34.1973 8.49473C33.7436 8.69836 33.4896 8.90593 33.4462 9.1085C33.4257 9.20462 33.2002 9.47506 33.0821 9.54513C33.0337 9.57386 33.0037 9.60293 33.0138 9.61132C33.0237 9.61954 33.0419 9.61411 33.0543 9.59925C33.0666 9.58438 33.1265 9.55205 33.1872 9.52739C33.248 9.50274 33.3426 9.45838 33.3975 9.42882C33.4872 9.38053 33.8642 9.25253 33.9131 9.25379C33.9239 9.25407 33.9891 9.2337 34.058 9.20853C34.127 9.18336 34.1915 9.16951 34.2014 9.17775C34.2114 9.18599 34.2269 9.18383 34.2359 9.17294C34.245 9.16206 34.314 9.13927 34.3894 9.12231C34.6418 9.0655 34.4868 9.14239 34.1467 9.24271C33.9617 9.29729 33.8014 9.35231 33.7905 9.365C33.7797 9.37767 33.7643 9.38291 33.7564 9.37663C33.7421 9.36526 33.6823 9.39137 33.2213 9.61009C33.0883 9.67319 32.9613 9.73195 32.939 9.74068C32.6631 9.84868 31.9037 10.6557 31.92 10.8236C31.9249 10.8745 31.9217 10.9249 31.9127 10.9356C31.8759 10.98 31.9335 10.9771 32.0278 10.9299ZM30.7536 9.8277C30.8067 9.83093 30.8628 9.84418 30.8785 9.85716C30.8941 9.87013 30.9192 9.87666 30.9343 9.87166C30.9493 9.86666 31.0045 9.87227 31.0569 9.88413L31.1522 9.90569L31.1348 9.82622C31.1136 9.72935 31.1343 9.69873 31.1957 9.73629C31.2402 9.76352 31.2416 9.76231 31.2357 9.70272C31.2275 9.62078 31.177 9.62231 30.8768 9.71356C30.5328 9.81811 30.5367 9.8145 30.7536 9.8277ZM31.7125 10.6523C31.7209 10.6289 31.7275 10.5867 31.7269 10.5584C31.7264 10.5301 31.7402 10.499 31.7575 10.4892C31.7764 10.4785 31.7773 10.4406 31.7598 10.3948C31.7437 10.3528 31.735 10.2816 31.7404 10.2368C31.7561 10.109 31.7267 9.61504 31.7023 9.59476C31.6092 9.51744 31.5748 9.63963 31.6043 9.94323C31.6111 10.0133 31.6035 10.1295 31.5874 10.2013C31.5703 10.2781 31.5712 10.3645 31.5898 10.4109C31.6072 10.4543 31.6329 10.5302 31.647 10.5794C31.6788 10.6908 31.6928 10.7063 31.7125 10.6523ZM34.5068 12.6468C34.5243 12.5947 34.5217 12.5898 34.4864 12.6087C34.4323 12.6376 34.4068 12.7136 34.4526 12.7096C34.4744 12.7076 34.4941 12.6849 34.5068 12.6468ZM31.4975 10.0606C31.4988 9.99488 31.4956 9.91956 31.4906 9.89322C31.4855 9.86688 31.4907 9.83418 31.502 9.82056C31.5407 9.77399 31.4798 9.58646 31.426 9.58621C31.3631 9.58592 31.3487 9.60673 31.3466 9.70097C31.3457 9.7443 31.3328 9.79427 31.3181 9.81203C31.3001 9.83364 31.3121 9.87948 31.3543 9.95051C31.3889 10.0089 31.4282 10.078 31.4416 10.1041C31.4854 10.1894 31.4953 10.1817 31.4975 10.0606ZM31.9928 10.3055C31.9952 10.2589 32.0067 10.2095 32.0182 10.1956C32.0297 10.1817 32.0338 10.1247 32.0271 10.0689C32.0205 10.0132 32.0316 9.92847 32.0518 9.88067C32.0769 9.82117 32.078 9.75431 32.0553 9.66867L32.0222 9.54359L31.8759 9.56172L31.8803 9.64609C31.8903 9.83724 31.8667 10.0415 31.8334 10.0525C31.8197 10.0571 31.8228 10.066 31.8403 10.0724C31.8585 10.079 31.8696 10.169 31.8662 10.2827L31.8604 10.4815L31.9244 10.4358C31.9748 10.3998 31.9893 10.3722 31.9928 10.3055ZM37.5881 14.932C37.6175 14.9087 37.6788 14.861 37.7244 14.8261C37.8455 14.7331 37.9305 14.6223 37.9205 14.5704C37.9157 14.5456 37.9274 14.4861 37.9463 14.4381C38.0324 14.2204 38.2518 13.2828 38.3104 12.8823C38.3245 12.786 38.3405 12.7019 38.3459 12.6954C38.3512 12.689 38.3566 12.6307 38.3579 12.566C38.3591 12.5013 38.3643 12.4432 38.3695 12.437C38.3746 12.4308 38.3759 12.3948 38.3722 12.3571C38.3685 12.3193 38.3781 12.274 38.3934 12.2563C38.427 12.2176 38.4433 12.4923 38.4175 12.6629C38.4082 12.7245 38.3939 12.8437 38.3858 12.9276C38.3777 13.0115 38.326 13.2667 38.2709 13.4948C38.2159 13.7228 38.1565 13.9684 38.1391 14.0407C38.1216 14.113 38.0969 14.1848 38.0842 14.2002C38.0714 14.2157 38.0602 14.2631 38.0592 14.3056C38.0581 14.3481 38.0456 14.3973 38.0314 14.4148C37.9808 14.4775 38.0244 14.4974 38.0913 14.4421C38.3501 14.2282 38.5501 13.8706 38.6814 13.3868C38.693 13.3443 38.7138 13.2836 38.7278 13.2518C38.749 13.2032 38.9184 12.529 38.999 12.1718C39.0118 12.1153 39.0296 12.0683 39.0385 12.0675C39.0575 12.0659 39.038 12.2254 38.9951 12.4229C38.9589 12.5894 38.9345 12.7529 38.9483 12.7364C38.9538 12.7299 39.0019 12.6279 39.0553 12.5098C39.1086 12.3916 39.1753 12.2509 39.2033 12.1971C39.2314 12.1433 39.2505 12.0881 39.2459 12.0745C39.2413 12.0608 39.2636 11.9733 39.2956 11.8799C39.3276 11.7865 39.3537 11.6906 39.3536 11.6667C39.3535 11.6429 39.369 11.5639 39.388 11.4912C39.407 11.4185 39.4218 11.3128 39.4209 11.2563C39.42 11.1998 39.4255 11.1116 39.433 11.0604C39.47 10.8092 39.4735 10.7534 39.4608 10.611C39.4491 10.4789 39.4592 10.2484 39.4855 10.0481C39.4983 9.95023 39.4548 9.60208 39.4012 9.37369C39.3858 9.30794 39.337 9.20811 39.2927 9.15185C39.2484 9.09558 39.1864 8.99771 39.155 8.93435C39.0007 8.6236 39.0086 8.63403 38.9375 8.64702C38.8981 8.65422 38.8922 8.66508 38.9035 8.70934C38.9165 8.76027 38.9105 8.76494 38.7819 8.80312C38.5524 8.87127 38.3501 9.02593 38.4174 9.08179C38.5494 9.19145 38.673 9.68609 38.6584 10.0471C38.6534 10.1734 38.636 10.3753 38.6096 10.6138C38.5938 10.7569 38.5797 10.9084 38.5782 10.9506C38.5768 10.9928 38.5604 11.0662 38.5417 11.1137C38.5231 11.1611 38.512 11.2287 38.5172 11.2638C38.528 11.3368 38.5113 11.3683 38.4769 11.3397C38.464 11.3289 38.4651 11.2553 38.4794 11.1761C38.4937 11.0969 38.5108 10.9727 38.5175 10.9002C38.5242 10.8276 38.5326 10.7475 38.5361 10.7221C38.6344 10.0241 38.5645 9.37189 38.3643 9.11785C38.3173 9.05824 38.3111 9.0573 38.2724 9.10389C38.2496 9.13136 38.195 9.16878 38.1511 9.18704C37.9987 9.25041 37.9848 9.25854 37.9423 9.30994C37.9046 9.35547 37.9095 9.38469 37.9831 9.55548C38.1121 9.85477 38.1408 10.16 38.0973 10.7715C38.0882 10.8983 38.0771 11.0542 38.0726 11.1179C38.0366 11.6227 37.9673 11.7469 37.9918 11.2627C38.0008 11.0831 38.0173 10.8653 38.0284 10.7787C38.051 10.6015 38.048 10.5008 38.0065 10.0543C37.9906 9.88249 37.9627 9.70904 37.9446 9.66886C37.9265 9.62867 37.9004 9.55227 37.8865 9.49907C37.8726 9.44588 37.8565 9.40334 37.8506 9.40456C37.8117 9.4126 37.5956 9.56725 37.5227 9.63925C37.4744 9.68703 37.4132 9.73484 37.3867 9.74548C37.3544 9.7585 37.3166 9.80435 37.2714 9.88548C37.2344 9.95183 37.1941 10.0094 37.182 10.0135C37.1698 10.0175 37.1641 10.0334 37.1694 10.0489C37.1747 10.0643 37.1664 10.0811 37.1511 10.0862C37.1358 10.0913 37.0629 10.1658 36.9892 10.2518L36.8551 10.4082L36.9492 10.4978C37.0029 10.5491 37.0564 10.6262 37.074 10.6778C37.091 10.7275 37.1223 10.7828 37.1437 10.8005C37.1651 10.8183 37.2055 10.9487 37.2335 11.0903C37.2615 11.2319 37.304 11.3976 37.3279 11.4584C37.3518 11.5193 37.3661 11.5753 37.3597 11.583C37.3533 11.5907 37.3595 11.6147 37.3735 11.6363C37.3874 11.658 37.4104 11.7863 37.4245 11.9215C37.4519 12.1846 37.4842 12.2358 37.5039 12.0475C37.5106 11.9836 37.5199 11.9268 37.5246 11.9211C37.5293 11.9155 37.5298 11.8624 37.5258 11.8031C37.5218 11.7439 37.5214 11.6056 37.525 11.4958C37.5458 10.8626 37.5003 10.3181 37.4008 10.009C37.3545 9.86522 37.3575 9.81069 37.4093 9.85368C37.5601 9.97895 37.6567 10.9608 37.5933 11.7253C37.5866 11.8061 37.5826 11.9021 37.5843 11.9387C37.5861 11.9752 37.5798 12.0414 37.5704 12.0856C37.5475 12.194 37.5655 12.2866 37.618 12.3302C37.6619 12.3667 37.763 12.6134 37.7637 12.6858C37.764 12.7074 37.7779 12.7902 37.7948 12.8697C37.8237 13.0057 37.821 13.4041 37.791 13.4403C37.7834 13.4494 37.7845 13.4786 37.7934 13.5052C37.82 13.5845 37.7463 13.8475 37.684 13.8958C37.6476 13.9241 37.629 13.9617 37.6268 14.0118C37.6251 14.0526 37.5993 14.1906 37.5696 14.3186C37.54 14.4465 37.5185 14.5595 37.5219 14.5696C37.5316 14.5978 37.7681 14.169 37.7727 14.115C37.774 14.0988 37.8011 14.0149 37.8329 13.9284C37.8646 13.842 37.8899 13.7483 37.889 13.7202C37.8882 13.6921 37.8922 13.6633 37.898 13.6563C37.9039 13.6493 37.9159 13.5681 37.9247 13.4759C37.9335 13.3836 37.9525 13.2469 37.9669 13.1721C37.9813 13.0972 37.9922 13.0129 37.9911 12.9846C37.9901 12.9563 37.9949 12.9263 38.002 12.9178C38.0178 12.8988 38.0856 12.2732 38.0893 12.1128C38.0931 11.9469 38.1268 11.9635 38.1384 12.1369C38.1496 12.3059 38.1366 12.4727 38.0833 12.8428C38.062 12.99 38.0427 13.1528 38.0404 13.2045C38.038 13.2562 38.0318 13.3037 38.0265 13.3099C38.0213 13.3162 38.0128 13.3675 38.0075 13.4239C37.976 13.7638 37.8173 14.2473 37.6835 14.4117C37.6519 14.4505 37.6335 14.4885 37.6427 14.4962C37.652 14.5038 37.6393 14.5465 37.6146 14.5911C37.5899 14.6357 37.5632 14.7022 37.5553 14.7391C37.5474 14.7759 37.531 14.8368 37.5189 14.8745C37.5067 14.9121 37.5053 14.9499 37.5157 14.9586C37.5261 14.9672 37.5586 14.9552 37.5881 14.932ZM32.1958 10.135C32.2228 10.1025 32.2479 10.0043 32.2596 9.88573C32.2702 9.77809 32.2842 9.68357 32.2908 9.6757C32.3267 9.63246 32.2847 9.5429 32.2268 9.5392C32.1698 9.53557 32.1685 9.53767 32.1723 9.62776C32.1777 9.75837 32.1686 9.94613 32.1508 10.0697C32.1326 10.1967 32.138 10.2046 32.1958 10.135ZM30.7705 8.86649C30.7715 8.82288 30.7636 8.74925 30.7529 8.70286C30.7423 8.65647 30.7349 8.59437 30.7365 8.56488C30.7381 8.53538 30.7312 8.50438 30.7211 8.49601C30.711 8.48763 30.7011 8.42972 30.6991 8.36734C30.6971 8.30495 30.6869 8.24676 30.6764 8.23803C30.6659 8.2293 30.6492 8.1729 30.6394 8.11269C30.614 7.95718 30.5759 7.94246 30.5862 8.09216C30.5979 8.26204 30.5848 8.38815 30.544 8.49745C30.5117 8.58395 30.5155 8.59708 30.6161 8.74455C30.7593 8.95439 30.7684 8.96163 30.7705 8.86649ZM32.5382 9.7053C32.5568 9.52465 32.5591 9.53204 32.4867 9.53843C32.4254 9.54383 32.4205 9.55797 32.3897 9.81854L32.371 9.97655L32.4463 9.92087C32.5146 9.8704 32.5232 9.85021 32.5382 9.7053ZM32.0381 9.28997C32.0733 9.2758 32.1163 9.27603 32.1337 9.29047C32.1997 9.34527 32.3147 9.3218 32.3115 9.25417C32.3058 9.13429 32.3853 9.11651 32.4051 9.23324C32.4136 9.28326 32.4287 9.30571 32.4526 9.30361C32.4719 9.3019 32.5025 9.31277 32.5205 9.32775C32.5781 9.37551 32.6094 9.33956 32.6058 9.22974C32.604 9.17105 32.6101 9.0559 32.6195 8.97385C32.6289 8.8918 32.6286 8.81805 32.6189 8.80995C32.599 8.79347 32.5805 8.6921 32.5635 8.50748C32.5572 8.43929 32.5198 8.31026 32.4804 8.22075C32.4409 8.13123 32.3887 8.01292 32.3645 7.95784C32.3402 7.90275 32.322 7.83304 32.3242 7.80292C32.3263 7.7728 32.312 7.73478 32.2923 7.71843C32.2726 7.70209 32.2355 7.63135 32.2098 7.56123C32.1492 7.3961 32.1216 7.34831 32.1088 7.38643C32.1034 7.40276 32.1196 7.47293 32.1448 7.54237C32.2413 7.80745 32.3694 8.69939 32.3195 8.75941C32.3116 8.76901 32.3126 8.81127 32.3218 8.85331C32.3427 8.94898 32.3217 9.04968 32.2581 9.15825C32.2014 9.25524 32.1863 9.19196 32.2298 9.03893C32.2559 8.94675 32.201 8.27725 32.1574 8.1571C32.1404 8.11022 32.1339 8.05343 32.1429 8.0309C32.152 8.00838 32.1472 7.97103 32.1323 7.94791C32.1174 7.92479 32.1117 7.89803 32.1197 7.88845C32.1276 7.87888 32.1218 7.86083 32.1068 7.84835C32.0918 7.83587 32.0815 7.80948 32.0839 7.7897C32.0863 7.76992 32.075 7.70072 32.0588 7.63592C32.0426 7.57112 32.0271 7.49799 32.0244 7.47342C32.0216 7.44883 32.0092 7.42023 31.9967 7.40985C31.9842 7.39947 31.9734 7.36211 31.9727 7.32684C31.972 7.29156 31.9586 7.25207 31.943 7.23908C31.9274 7.22609 31.9256 7.20219 31.939 7.18597C31.9581 7.16297 31.9751 7.17001 32.016 7.2179L32.0684 7.27933L32.0278 7.19595C32.0054 7.1501 31.987 7.09469 31.9868 7.07282C31.9866 7.05096 31.9302 6.94558 31.8614 6.83865C31.7926 6.73172 31.7348 6.61748 31.7329 6.58479C31.731 6.55209 31.7127 6.51148 31.6923 6.49454C31.6719 6.4776 31.6254 6.4024 31.5891 6.32744C31.4913 6.12595 31.4671 6.14441 31.5068 6.3903C31.535 6.56489 31.5613 6.63755 31.6357 6.74632C31.9276 7.1733 32.114 8.44097 31.9781 9.07477C31.9303 9.29764 31.9392 9.32976 32.0381 9.28997ZM32.7575 9.63346C32.8575 9.54439 32.8587 9.53382 32.7692 9.52925C32.7074 9.5261 32.6971 9.53396 32.6713 9.60355C32.6314 9.7112 32.6593 9.72089 32.7575 9.63346ZM32.8087 9.29098C32.89 9.27866 32.9076 9.19888 32.8534 9.08851C32.8283 9.03743 32.8125 8.95253 32.8184 8.89984C32.825 8.83996 32.8116 8.78265 32.7826 8.74699C32.7571 8.71561 32.7284 8.64712 32.7187 8.59479C32.6937 8.45951 32.6734 8.4574 32.6874 8.59155C32.6939 8.65374 32.7059 8.83406 32.714 8.99224C32.7303 9.30837 32.7286 9.30311 32.8087 9.29098ZM38.6185 14.0001C38.6362 13.9902 38.6752 13.994 38.7052 14.0085C38.7675 14.0386 39.0248 13.726 39.0226 13.6229C39.0221 13.5964 39.0506 13.5129 39.086 13.4374C39.1214 13.362 39.1589 13.2653 39.1693 13.2227C39.1797 13.1801 39.2068 13.0754 39.2294 12.9901C39.2623 12.8661 39.3222 12.4838 39.3187 12.4201C39.3166 12.3799 39.2826 12.4247 39.2171 12.5539C39.1768 12.6332 39.1309 12.7228 39.1149 12.753C39.099 12.7832 39.0726 12.8566 39.0563 12.9163C39.04 12.9759 38.9829 13.0887 38.9295 13.1669C38.876 13.2451 38.8359 13.3195 38.8402 13.3323C38.8446 13.345 38.8184 13.3913 38.7821 13.435C38.622 13.6278 38.4942 14.0693 38.6185 14.0001ZM36.0248 11.1334C36.0763 11.0935 36.5429 10.6332 36.7453 10.4224C36.8102 10.3548 36.9174 10.2451 36.9836 10.1786C37.1143 10.0472 37.0917 10.002 36.9588 10.1291C36.9208 10.1655 36.8539 10.2295 36.8103 10.2713C36.7666 10.3131 36.705 10.3684 36.6734 10.3943C36.5963 10.4573 36.33 10.713 36.2594 10.7919C36.2282 10.8267 36.1163 10.9455 36.0108 11.0558C35.8183 11.2569 35.7399 11.3839 35.8936 11.2454C35.9387 11.2047 35.9977 11.1543 36.0248 11.1334ZM39.2899 13.3478C39.3247 13.2944 39.3652 13.2175 39.3797 13.1771C39.3942 13.1366 39.4379 13.0593 39.4767 13.0052C39.5156 12.9512 39.5941 12.8284 39.6512 12.7323C39.7341 12.5929 39.767 12.5528 39.8143 12.5338C39.8634 12.514 39.8785 12.4926 39.9017 12.4098C39.9172 12.3547 39.964 12.2645 40.0057 12.2092C40.0535 12.146 40.0839 12.0776 40.0877 12.0249C40.0991 11.8675 40.2223 11.3554 40.2595 11.3106C40.2999 11.262 40.3474 10.9967 40.3513 10.7982C40.3526 10.7299 40.3596 10.6575 40.3667 10.6373C40.3738 10.6171 40.38 10.519 40.3806 10.4193C40.3816 10.2226 40.4247 10.1431 40.4406 10.3088C40.4582 10.4922 40.4325 10.9532 40.3922 11.1785C40.3553 11.3847 40.2641 11.748 40.2308 11.8213C40.1048 12.0987 40.1113 12.1118 40.3005 11.9629C40.7543 11.6056 40.896 11.4726 40.9212 11.3802C40.9345 11.3314 40.9847 11.1822 41.0326 11.0485C41.0806 10.9148 41.1372 10.7255 41.1584 10.6277C41.1977 10.4465 41.2936 10.2841 41.3284 10.3396C41.3379 10.3546 41.3295 10.395 41.3097 10.4293C41.2592 10.5172 41.2093 10.6747 41.2273 10.6896C41.2356 10.6964 41.2332 10.7131 41.222 10.7266C41.2108 10.7401 41.1867 10.8122 41.1684 10.887C41.1501 10.9617 41.1294 11.0297 41.1224 11.0381C41.1155 11.0465 41.0978 11.1022 41.0832 11.162C41.0687 11.2217 41.0494 11.2794 41.0405 11.2901C40.9816 11.361 41.0793 11.3133 41.2159 11.2044C41.4337 11.0308 41.5107 10.9363 41.4851 10.8741C41.4575 10.8069 41.5059 10.7171 41.5887 10.6818C41.6515 10.6551 41.9015 10.4635 42.0084 10.3602C42.0353 10.3342 42.0598 10.2543 42.0716 10.1545C42.0822 10.0647 42.1062 9.93558 42.125 9.86757C42.2396 9.4529 42.2756 9.16225 42.2182 9.11458C42.1881 9.08961 42.2292 9.05504 42.27 9.07102C42.3072 9.08563 42.3388 9.38167 42.3072 9.41973C42.2929 9.4369 42.2881 9.45663 42.2965 9.46358C42.3048 9.47052 42.2969 9.52425 42.2788 9.58296C42.2607 9.64168 42.2434 9.70897 42.2404 9.7325C42.2374 9.75603 42.2283 9.79861 42.2202 9.82713C42.0933 10.2737 42.1209 10.3254 42.3291 10.0313C42.3894 9.946 42.4484 9.84268 42.4602 9.80167C42.5029 9.65346 42.5301 9.37675 42.5058 9.3391C42.4922 9.31793 42.477 9.27022 42.472 9.23309C42.4551 9.1059 42.3464 8.94118 42.1438 8.73567C41.9448 8.53377 41.9204 8.5165 41.6067 8.35571C41.5543 8.32887 41.4951 8.29333 41.4751 8.27674C41.4551 8.26014 41.3973 8.23947 41.3466 8.2308C41.2558 8.21528 41.1251 8.15292 41.0339 8.08156C40.9561 8.02079 40.9361 8.06809 40.9802 8.20834C41.0032 8.28158 41.0298 8.39065 41.0392 8.45071C41.0486 8.51077 41.0631 8.56559 41.0715 8.57254C41.1006 8.59675 41.1665 9.3368 41.1421 9.36618C41.0922 9.42619 41.0631 9.38472 41.0751 9.27075C41.0834 9.19081 41.0737 9.14227 41.0444 9.11793C41.0149 9.09349 41.0009 9.02262 41 8.89299C40.9992 8.78889 40.9865 8.63455 40.9717 8.55001C40.9569 8.46546 40.9417 8.37066 40.9379 8.33933C40.912 8.12521 40.848 8.00312 40.7357 7.95385C40.6289 7.90697 40.509 7.90523 40.4718 7.95003C40.4573 7.96752 40.424 7.98173 40.3979 7.98161C40.3717 7.98149 40.3409 7.99264 40.3295 8.00639C40.3181 8.02014 40.2769 8.03306 40.2379 8.03512C40.1387 8.04034 40.1325 8.08639 40.2019 8.30233C40.3144 8.65212 40.3361 9.45276 40.2364 9.57602C40.222 9.59382 40.2094 9.64317 40.2083 9.68567C40.2073 9.72817 40.1954 9.77651 40.1821 9.79308C40.1687 9.80965 40.1623 9.85405 40.1679 9.89174C40.1735 9.92943 40.1684 10.004 40.1566 10.0575C40.1448 10.1109 40.1371 10.1756 40.1396 10.2011C40.1489 10.2968 40.1108 10.6081 40.0862 10.6378C40.0721 10.6547 40.0783 10.7291 40.1 10.8032C40.2061 11.1657 40.1517 11.7825 40.0246 11.658C40.0029 11.6369 39.9886 11.6387 39.9803 11.6636C39.9149 11.8584 39.8845 11.8294 39.9174 11.6038C40.0171 10.9194 40.004 10.7987 39.8085 10.5979C39.6781 10.4639 39.6545 10.4613 39.6626 10.5816C39.6697 10.6879 39.6383 11.0578 39.6173 11.1156C39.6094 11.1372 39.6022 11.2134 39.6013 11.285C39.6004 11.3566 39.5946 11.4214 39.5884 11.4289C39.5781 11.4413 39.5198 11.6557 39.4911 11.787C39.4847 11.816 39.4561 11.9161 39.4273 12.0093C39.3978 12.1051 39.3802 12.2365 39.3868 12.3112C39.4047 12.5149 39.3303 13.0429 39.2741 13.1106C39.2432 13.1478 39.1879 13.4131 39.2076 13.4295C39.2189 13.4389 39.2518 13.4062 39.2899 13.3478ZM35.1462 8.0139C35.2635 7.9718 35.4347 7.93585 35.5448 7.93019C35.6509 7.92474 35.8372 7.9126 35.9588 7.90321C36.0804 7.89382 36.1851 7.89053 36.1915 7.89587C36.1979 7.90121 36.2703 7.90104 36.3524 7.89548C36.8201 7.8638 37.0382 7.8703 37.2772 7.92311C37.328 7.93434 37.4018 7.94191 37.4413 7.93994C37.4807 7.93798 37.5858 7.94719 37.6749 7.96042C37.764 7.97365 37.8715 7.98909 37.914 7.99473C38.0558 8.01358 38.4987 8.11983 38.6224 8.16469C38.6897 8.18908 38.8266 8.23128 38.9265 8.25845C39.0265 8.28563 39.1324 8.31774 39.1617 8.32983C39.2231 8.35504 39.2764 8.33738 39.4165 8.24547C39.5651 8.148 39.5689 8.13842 39.4714 8.11021C39.2318 8.0409 38.9621 7.93817 38.9305 7.9042C38.9103 7.88242 38.8794 7.87425 38.8594 7.8854C38.84 7.89623 38.8132 7.89611 38.7999 7.88513C38.7866 7.87414 38.7149 7.85212 38.6406 7.83619C38.3361 7.77089 38.1466 7.72116 38.1209 7.69977C38.1059 7.6873 38.0846 7.68216 38.0737 7.68834C38.0627 7.69452 37.9711 7.68069 37.8701 7.65762C37.7027 7.61937 37.5008 7.62013 36.8589 7.66142C36.6602 7.6742 36.5969 7.66898 36.5717 7.63774C36.5565 7.61878 36.6412 7.60286 36.8104 7.59291C36.9547 7.58442 37.1788 7.57062 37.3083 7.56227C37.6548 7.53986 38.1141 7.59948 38.2103 7.67936C38.2289 7.69483 38.2731 7.70347 38.3085 7.69857C38.3698 7.69007 38.4632 7.70987 38.688 7.779C38.7438 7.79615 38.8108 7.81442 38.8369 7.81958C38.863 7.82475 38.9052 7.84626 38.9306 7.86738C38.9561 7.8885 38.9878 7.90215 39.0012 7.89772C39.0301 7.88812 39.5711 8.0522 39.606 8.08113C39.6247 8.09668 39.8595 8.00868 40.0048 7.93165C40.0156 7.92588 40.0008 7.90925 39.9718 7.8947C39.9428 7.88015 39.8784 7.83929 39.8287 7.80391C39.779 7.76853 39.7143 7.73433 39.6849 7.72791C39.625 7.71483 39.3906 7.63326 39.3053 7.59581C39.2747 7.58237 39.1864 7.5685 39.1091 7.565C39.0318 7.56149 38.9458 7.55073 38.9179 7.54109C38.8632 7.52221 38.7238 7.51982 38.5307 7.53447C38.4173 7.54307 38.2234 7.53244 38.2042 7.51657C38.1732 7.49076 38.2581 7.47969 38.536 7.4733C39.1622 7.45892 39.6622 7.57565 39.9819 7.81089L40.1282 7.91856L40.2728 7.84902C40.4995 7.73995 40.5027 7.73678 40.4979 7.62059C40.4939 7.52138 40.49 7.51531 40.4247 7.50582C40.3563 7.4959 39.8116 7.15 39.6701 7.02663C39.6317 6.9932 39.5831 6.96551 39.562 6.9651C39.5409 6.96469 39.4891 6.94557 39.4469 6.92262C39.4047 6.89966 39.3388 6.86693 39.3004 6.84988C39.2621 6.83283 39.1847 6.79665 39.1285 6.76947C38.9814 6.69839 38.6209 6.60188 38.4255 6.58132C38.3529 6.57368 38.2469 6.57083 38.1899 6.57499C38.1329 6.57915 38.0583 6.58273 38.0241 6.58296C37.9423 6.5835 37.7929 6.60701 37.7255 6.62997C37.6376 6.65986 37.7041 6.59559 37.8051 6.55293C38.0905 6.43244 38.8145 6.51667 39.2017 6.7154C39.4778 6.85715 39.8939 7.0924 40.1463 7.24954C40.4774 7.45568 40.4646 7.45124 40.4584 7.35713C40.4482 7.20234 40.3435 7.0121 40.2057 6.89807C40.1203 6.82746 40.101 6.80474 40.1461 6.82808L40.2129 6.86263L40.1806 6.7866C40.1628 6.74478 40.1161 6.68882 40.0769 6.66225C40.0377 6.63569 39.9563 6.57511 39.8959 6.52765C39.8234 6.47061 39.7758 6.44719 39.7554 6.45858C39.7384 6.46805 39.7063 6.46069 39.684 6.44224C39.629 6.39651 39.419 6.34678 39.1681 6.32007C39.011 6.30334 38.8218 6.34374 38.8487 6.3883C38.8577 6.40336 38.8041 6.40602 38.7294 6.39421C38.3777 6.33863 38.1474 6.34398 37.994 6.41129C37.8327 6.48209 37.7613 6.50682 37.6916 6.51603C37.667 6.51928 37.6367 6.53427 37.6242 6.54935C37.5915 6.58867 37.3617 6.65079 37.1099 6.68836C36.8504 6.72707 36.8172 6.74183 36.7089 6.86641C36.6088 6.98155 36.6082 6.98053 36.7438 6.937C36.9881 6.85857 37.8554 6.81696 38.0488 6.8744C38.0864 6.88557 38.1658 6.89438 38.2252 6.89395C38.2846 6.89352 38.3634 6.90212 38.4004 6.91305C38.4373 6.92399 38.4999 6.93086 38.5395 6.92832C38.6064 6.92403 38.9412 6.99349 39.0515 7.03455C39.0783 7.04451 39.1717 7.07865 39.2591 7.11041C39.3465 7.14218 39.4345 7.18175 39.4546 7.19835C39.4746 7.21495 39.5399 7.24077 39.5996 7.25573C39.8554 7.31987 40.1942 7.49778 40.3369 7.64291C40.4342 7.7419 40.2379 7.68965 40.0799 7.57451C40.0177 7.52915 39.9365 7.48809 39.8995 7.48327C39.8624 7.47844 39.7647 7.44356 39.6823 7.40574C39.5999 7.36792 39.4868 7.33201 39.4308 7.32595C39.3749 7.31989 39.3112 7.3 39.2892 7.28176C39.2673 7.26352 39.2031 7.24561 39.1466 7.24197C39.0902 7.23833 39.0074 7.22576 38.9628 7.21405C38.9182 7.20233 38.8337 7.19973 38.7751 7.20827C38.6734 7.22308 38.301 7.21834 38.2813 7.20198C38.2683 7.19119 37.7587 7.22391 37.5672 7.24782C37.5172 7.25407 37.4681 7.25232 37.458 7.24396C37.4319 7.22225 37.5357 7.18379 37.6535 7.17152C37.708 7.16583 37.7572 7.15574 37.7627 7.14909C37.7715 7.13857 38.174 7.1225 38.3961 7.12377C38.7371 7.12576 38.959 7.11641 38.9496 7.1005C38.9275 7.06319 38.396 6.95932 38.196 6.95322C38.1277 6.95114 37.999 6.94171 37.9101 6.93228C37.8211 6.92286 37.7157 6.91686 37.6758 6.91896C37.6358 6.92106 37.6007 6.92079 37.5976 6.91836C37.5752 6.90076 36.9546 6.96202 36.8678 6.99041C36.8078 7.01001 36.7208 7.03072 36.6745 7.03643C36.5362 7.05347 36.2815 7.13123 36.2535 7.16495C36.2391 7.18223 36.2146 7.19452 36.199 7.19226C36.1833 7.19 36.157 7.20447 36.1404 7.2244C36.1239 7.24434 36.1022 7.25389 36.0923 7.24563C36.0823 7.23737 36.0342 7.25779 35.9854 7.291C35.9366 7.32422 35.8744 7.35532 35.8472 7.36011C35.82 7.3649 35.7923 7.37527 35.7858 7.38316C35.7792 7.39105 35.6289 7.45998 35.4517 7.53635C35.1054 7.68556 35.0746 7.70647 35.101 7.77445C35.1137 7.80704 35.0934 7.85292 35.0238 7.94854C34.9082 8.10755 34.8989 8.10264 35.1462 8.0139ZM39.8647 10.473L39.9681 10.5589L39.9785 10.4807C39.9841 10.4377 39.982 10.365 39.9737 10.3191C39.9594 10.2401 39.9607 10.2375 39.9987 10.2689C40.0208 10.2872 40.039 10.3235 40.0391 10.3496C40.0392 10.3757 40.0467 10.4033 40.0558 10.4108C40.0649 10.4184 40.0715 10.399 40.0705 10.3678C40.0677 10.2842 40.1166 9.87313 40.1316 9.85403C40.1386 9.84501 40.1419 9.78072 40.1388 9.71116C40.1356 9.63913 40.1496 9.56491 40.1713 9.53876C40.2887 9.39742 40.1832 8.16985 40.0521 8.15091C39.9986 8.14319 39.6525 8.25362 39.619 8.28911C39.6121 8.2964 39.6193 8.31303 39.635 8.32607C39.7304 8.40529 39.8776 9.12581 39.814 9.20237C39.7983 9.22132 39.79 9.3132 39.7957 9.40657C39.8013 9.49994 39.7992 9.6123 39.791 9.65626C39.7829 9.70022 39.7763 9.75771 39.7764 9.78403C39.7765 9.81034 39.7686 9.82528 39.7589 9.81723C39.7263 9.79014 39.7051 9.19975 39.7342 9.12936C39.816 8.9318 39.5875 8.27505 39.4703 8.37069C39.417 8.41417 39.276 8.50412 39.2032 8.54109C39.1719 8.55697 39.175 8.57753 39.2177 8.63862C39.2475 8.6812 39.2765 8.74691 39.2821 8.78463C39.2928 8.85713 39.403 9.04838 39.4625 9.09777C39.5996 9.21161 39.7169 9.87826 39.6564 10.1999C39.6364 10.3064 39.6405 10.3215 39.6977 10.3526C39.7327 10.3716 39.8078 10.4257 39.8647 10.473ZM42.7547 9.8519C43.0177 9.8243 43.2478 9.79627 43.5399 9.75624C43.7177 9.73188 43.9108 9.7063 43.9691 9.69941C44.5255 9.63349 44.6104 9.56132 44.0693 9.61416C43.8802 9.63263 43.7111 9.64785 43.6935 9.64798C43.4062 9.6502 43.2984 9.65328 43.2495 9.6607C43.2171 9.6656 43.1831 9.6634 43.1739 9.6558C43.146 9.63263 42.9431 9.68349 42.9389 9.71473C42.9336 9.75327 42.8052 9.79133 42.7724 9.76408C42.7583 9.75237 42.7294 9.75316 42.708 9.76582C42.6867 9.77848 42.6556 9.79524 42.6389 9.80307C42.5833 9.82913 42.6606 9.86176 42.7547 9.8519Z\"\n        fill=\"#617B62\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 46 / 50,\n  svg: Floral,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenBag.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Bag', 'sticker name', 'web-stories');\nfunction GreenBag({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 39 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M19.3719 12.8035C13.1102 12.8035 7.97003 17.9437 7.97003 24.2988C7.97003 30.6539 13.1102 35.7941 19.3719 35.7941C25.6336 35.7941 30.7738 30.6539 30.7738 24.2988C30.6803 17.9437 25.6336 12.8035 19.3719 12.8035ZM19.3719 34.7661C13.671 34.7661 8.99807 30.0932 8.99807 24.2988C8.99807 18.5044 13.671 13.8315 19.3719 13.8315C25.0728 13.8315 29.7457 18.5044 29.7457 24.2988C29.7457 30.0932 25.0728 34.7661 19.3719 34.7661Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.0261078 0V4.20561C0.0261078 4.96432 0.200513 6.13405 0.726785 7.22418C1.18822 8.18002 1.93554 9.10203 3.09413 9.60206C2.62052 10.6047 2.23808 12.1349 1.95891 13.984C1.62378 16.2037 1.42798 18.9534 1.42798 21.9626C1.42798 24.9916 1.86107 28.6049 2.48767 31.8867C3.07711 34.9739 3.84491 37.8053 4.60277 39.5977C3.97841 40.1719 3.15795 41.0209 2.45686 41.9498C2.05572 42.4813 1.68626 43.0487 1.41546 43.6138C1.14684 44.1742 0.960687 44.7624 0.960687 45.3271V50H37.4093V45.3271C37.4093 44.7624 37.2231 44.1742 36.9545 43.6138C36.6837 43.0487 36.3143 42.4813 35.9131 41.9498C35.2123 41.0213 34.3923 40.1727 33.768 39.5984C34.534 37.8157 35.412 34.9927 36.1127 31.9024C36.8565 28.6215 37.4093 25.0015 37.4093 21.9626C37.4093 18.9408 37.0946 16.1836 36.6405 13.9602C36.2614 12.1044 35.7787 10.5881 35.2826 9.59912C36.4374 9.09843 37.1827 8.17815 37.6432 7.22418C38.1695 6.13405 38.3439 4.96432 38.3439 4.20561V0H0.0261078ZM0.960687 0.934579V4.20561C0.960687 4.84876 1.11338 5.8753 1.56842 6.81787C2.01999 7.75327 2.74899 8.56968 3.8928 8.89648L4.49478 9.06848L4.15866 9.59667C3.67088 10.3632 3.21348 11.9347 2.88302 14.1235C2.55616 16.2885 2.36256 18.9905 2.36256 21.9626C2.36256 24.915 2.78616 28.4668 3.40567 31.7114C4.02649 34.963 4.836 37.8637 5.5917 39.5263L5.73546 39.8425L5.47401 40.0713C4.87008 40.5997 3.95874 41.5112 3.20283 42.5128C2.82516 43.0132 2.49368 43.5264 2.25825 44.0177C2.02064 44.5135 1.89527 44.9572 1.89527 45.3271V49.0654H36.4747V45.3271C36.4747 44.9572 36.3493 44.5135 36.1117 44.0177C35.8763 43.5264 35.5448 43.0132 35.1671 42.5128C34.4112 41.5112 33.4999 40.5997 32.896 40.0713L32.6345 39.8425L32.7783 39.5263C33.5388 37.8532 34.4649 34.9433 35.2012 31.6957C35.9371 28.4501 36.4747 24.905 36.4747 21.9626C36.4747 19.0031 36.1663 16.3086 35.7248 14.1473C35.2801 11.9701 34.7095 10.3795 34.2113 9.59667L33.8752 9.06848L34.4772 8.89648C35.621 8.56968 36.35 7.75327 36.8016 6.81787C37.2566 5.8753 37.4093 4.84876 37.4093 4.20561V0.934579H0.960687Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M36.942 45.3271H1.42798V44.3925H36.942V45.3271Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.8766 3.27103H0.493398V2.33645H37.8766V3.27103Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M9.83919 8.41121C9.83919 8.15314 10.0484 7.94393 10.3065 7.94393H27.1289C27.387 7.94393 27.5962 8.15314 27.5962 8.41121C27.5962 8.66929 27.387 8.8785 27.1289 8.8785H10.3065C10.0484 8.8785 9.83919 8.66929 9.83919 8.41121Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M9.83919 40.1869C9.83919 39.9288 10.0484 39.7196 10.3065 39.7196H27.1289C27.387 39.7196 27.5962 39.9288 27.5962 40.1869C27.5962 40.445 27.387 40.6542 27.1289 40.6542H10.3065C10.0484 40.6542 9.83919 40.445 9.83919 40.1869Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.1188 26.718C18.3117 25.8397 18.2413 24.6888 17.8055 23.4968C17.4047 22.401 16.5746 21.5412 15.7202 20.9881C15.2959 20.7134 14.891 20.5314 14.5695 20.4362C14.3481 20.3706 14.2214 20.3619 14.1707 20.36C14.1332 20.3942 14.042 20.4826 13.9151 20.6755C13.7309 20.9556 13.5389 21.3559 13.3918 21.8395C13.0957 22.8133 13.016 24.0057 13.4168 25.1016C13.8526 26.2935 14.5413 27.2184 15.2552 27.7651C15.9796 28.3198 16.6112 28.4114 17.0554 28.249C17.4995 28.0866 17.9231 27.6092 18.1188 26.718ZM17.3763 29.1268C19.073 28.5064 19.6581 25.8421 18.6832 23.1759C17.7083 20.5097 14.7236 19.1507 13.8459 19.4716C12.9681 19.7926 11.5641 22.7563 12.539 25.4225C13.5139 28.0887 15.6797 29.7472 17.3763 29.1268Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M17.3763 29.1268C17.134 29.2154 16.8656 29.0908 16.777 28.8484L15.1722 24.4597C15.0836 24.2173 15.2082 23.949 15.4506 23.8603C15.693 23.7717 15.9613 23.8964 16.05 24.1387L17.6547 28.5274C17.7434 28.7698 17.6187 29.0382 17.3763 29.1268Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.1463 28.6488C23.8874 28.1395 24.6228 27.2513 25.1194 26.0833C25.5759 25.0095 25.5577 23.8146 25.3121 22.8269C25.1901 22.3363 25.019 21.9267 24.8494 21.6375C24.7326 21.4383 24.6461 21.3453 24.6104 21.3092C24.5596 21.3086 24.4326 21.3107 24.2082 21.3648C23.8822 21.4434 23.4685 21.6043 23.0306 21.8568C22.1488 22.3652 21.2756 23.1811 20.819 24.2549C20.3225 25.4229 20.193 26.5687 20.3404 27.4558C20.49 28.3558 20.8884 28.8544 21.3236 29.0394C21.7588 29.2245 22.3944 29.1655 23.1463 28.6488ZM20.958 29.8995C22.6205 30.6064 24.8687 29.0615 25.9794 26.449C27.0902 23.8365 25.8405 20.8045 24.9805 20.4388C24.1204 20.0731 21.0698 21.2767 19.959 23.8892C18.8482 26.5018 19.2954 29.1926 20.958 29.8995Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M20.958 29.8995C20.7205 29.7985 20.6098 29.5241 20.7108 29.2866L22.5392 24.9863C22.6402 24.7488 22.9146 24.6381 23.1521 24.7391C23.3896 24.8401 23.5002 25.1145 23.3992 25.352L21.5708 29.6523C21.4698 29.8898 21.1955 30.0005 20.958 29.8995Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 39 / 50,\n  svg: GreenBag,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenBulb.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Bulb', 'sticker name', 'web-stories');\n\nfunction GreenBulb({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 26 38\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M18.2285 32.2222H7.77149C7.36673 32.2222 7.04717 31.8985 7.04717 31.4978C7.04717 29.2781 6.5998 27.3113 5.95156 25.5294C5.28811 23.7044 4.41466 22.052 3.60512 20.5044C2.23256 17.8994 1 15.5657 1 13.0409V12.9022C1.03348 9.01475 2.55212 5.9196 4.80421 3.78629C7.04717 1.65298 10.0327 0.500005 13.0183 0.500005C13.0457 0.500005 13.07 0.500005 13.0883 0.509254H13.1309C16.2716 0.536999 19.4032 1.85645 21.6614 4.23947C23.6792 6.37894 25 9.36003 25 13.0378C25 15.5627 23.7674 17.8964 22.404 20.5013C20.7819 23.578 18.9528 27.0369 18.9528 31.4947C18.9528 31.8985 18.6333 32.2222 18.2285 32.2222ZM8.228 34.8611C7.83236 34.8611 7.50368 34.5374 7.50368 34.1274C7.50368 33.7266 7.83236 33.3937 8.228 33.3937H17.769C18.1646 33.3937 18.4933 33.7266 18.4933 34.1274C18.4933 34.5374 18.1646 34.8611 17.769 34.8611H8.228ZM14.4486 20.2146V19.1911C14.4486 18.7811 14.7682 18.4574 15.1638 18.4574C15.5686 18.4574 15.8882 18.7811 15.8882 19.1911V30.761H17.5194C17.702 26.3125 19.5128 22.8782 21.1258 19.8108C22.404 17.3908 23.5574 15.2051 23.5574 13.0378C23.5574 9.77004 22.3918 7.13115 20.6145 5.25063C18.6333 3.14815 15.8821 1.99517 13.1126 1.96743H13.0183C10.3949 1.96743 7.76541 2.98168 5.78113 4.85911C3.80294 6.73038 2.47603 9.46484 2.43951 12.9084V13.0409C2.43951 15.2081 3.59599 17.3939 4.87116 19.8139C5.71722 21.4231 6.61501 23.1248 7.30281 25.0208C7.93279 26.7595 8.3893 28.6461 8.47755 30.761H10.1088V19.1911C10.1088 18.7811 10.4284 18.4574 10.8331 18.4574C11.2288 18.4574 11.5483 18.7811 11.5483 19.1911V20.2146H14.4486ZM14.4486 30.761V21.6821H11.5514V30.761H14.4486ZM9.07405 37.5C8.66929 37.5 8.34973 37.1671 8.34973 36.7663C8.34973 36.3655 8.66929 36.0326 9.07405 36.0326H16.8468C17.2516 36.0326 17.5711 36.3655 17.5711 36.7663C17.5711 37.1671 17.2516 37.5 16.8468 37.5H9.07405Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.7166 25.6148C5.07839 23.8592 4.24331 22.2633 3.45246 20.7519C3.4295 20.708 3.40658 20.6642 3.38371 20.6205C3.38367 20.6204 3.38374 20.6206 3.38371 20.6205L3.35703 20.5699C2.00225 17.9987 0.75 15.6222 0.75 13.0409V12.9C0.784063 8.9446 2.33096 5.78482 4.63212 3.60495C6.92226 1.42687 9.96968 0.250005 13.0183 0.250005L13.0207 0.250003C13.0325 0.249987 13.0566 0.249955 13.0811 0.252354C13.0928 0.253501 13.1079 0.255446 13.1251 0.259254H13.1331C16.341 0.287592 19.5375 1.63471 21.8429 4.06751C23.9047 6.25374 25.25 9.29676 25.25 13.0378C25.25 15.6037 24.0126 17.9675 22.6761 20.5207L22.6255 20.6173L22.6223 20.6234C20.9989 23.7025 19.2028 27.109 19.2028 31.4947C19.2028 32.0349 18.773 32.4722 18.2285 32.4722H7.77149C7.22769 32.4722 6.79717 32.0356 6.79717 31.4978C6.79717 29.3129 6.35701 27.3752 5.7166 25.6148ZM13.0883 0.509254C13.07 0.500005 13.0457 0.500005 13.0183 0.500005C10.0327 0.500005 7.04717 1.65298 4.80421 3.78629C2.55212 5.9196 1.03348 9.01475 1 12.9022V13.0409C1 15.5602 2.22713 17.8891 3.59604 20.4872L3.60512 20.5044C3.62884 20.5498 3.65261 20.5952 3.67643 20.6407C4.46566 22.149 5.30754 23.7579 5.95156 25.5294C6.5998 27.3113 7.04717 29.2781 7.04717 31.4978C7.04717 31.8985 7.36673 32.2222 7.77149 32.2222H18.2285C18.6333 32.2222 18.9528 31.8985 18.9528 31.4947C18.9528 27.0471 20.7735 23.5938 22.3929 20.5224L22.404 20.5013L22.4379 20.4366C23.7878 17.8577 25 15.5417 25 13.0378C25 9.36003 23.6792 6.37894 21.6614 4.23947C19.4032 1.85645 16.2716 0.536999 13.1309 0.509254H13.0883ZM4.89624 19.8616C5.73493 21.4567 6.6218 23.1435 7.30281 25.0208C7.93279 26.7595 8.3893 28.6461 8.47755 30.761H10.1088V19.1911C10.1088 18.7811 10.4284 18.4574 10.8331 18.4574C11.2288 18.4574 11.5483 18.7811 11.5483 19.1911V20.2146H14.4486V19.1911C14.4486 18.7811 14.7682 18.4574 15.1638 18.4574C15.5686 18.4574 15.8882 18.7811 15.8882 19.1911V30.761H17.5194C17.7016 26.3225 19.5046 22.8938 21.1148 19.8316L21.1258 19.8108C22.404 17.3908 23.5574 15.2051 23.5574 13.0378C23.5574 9.77004 22.3918 7.13115 20.6145 5.25063C18.6333 3.14815 15.8821 1.99517 13.1126 1.96743H13.0183C10.3949 1.96743 7.76541 2.98168 5.78113 4.85911C3.80294 6.73038 2.47603 9.46484 2.43951 12.9084V13.0409C2.43951 15.1992 3.58644 17.3758 4.85534 19.7838L4.89624 19.8616ZM2.68951 12.9097V13.0409C2.68951 15.1334 3.80781 17.2596 5.09234 19.6973L5.12043 19.7508C5.95735 21.3425 6.85097 23.0422 7.53783 24.9355C8.15077 26.6272 8.60294 28.4624 8.71574 30.511H9.8588V19.1911C9.8588 18.6461 10.2873 18.2074 10.8331 18.2074C11.3719 18.2074 11.7983 18.6482 11.7983 19.1911V19.9646H14.1986V19.1911C14.1986 18.6482 14.625 18.2074 15.1638 18.2074C15.7097 18.2074 16.1382 18.6461 16.1382 19.1911V30.511H17.2811C17.5192 26.1321 19.3081 22.7302 20.8865 19.7287L20.9045 19.6944C22.1919 17.2571 23.3074 15.1303 23.3074 13.0378C23.3074 9.83275 22.1655 7.25562 20.4328 5.42235C18.4996 3.37078 15.8139 2.24484 13.1114 2.21743H13.0183C10.4581 2.21743 7.8903 3.20767 5.95295 5.04071C4.02513 6.86433 2.72565 9.53338 2.68951 12.9097ZM8.228 35.1111C7.69331 35.1111 7.25368 34.6745 7.25368 34.1274C7.25368 33.5916 7.69126 33.1437 8.228 33.1437H17.769C18.3057 33.1437 18.7433 33.5916 18.7433 34.1274C18.7433 34.6745 18.3036 35.1111 17.769 35.1111H8.228ZM14.4486 21.6821V30.761H11.5514V21.6821H14.4486ZM11.8014 21.9321V30.511H14.1986V21.9321H11.8014ZM9.07405 37.75C8.52616 37.75 8.09973 37.3 8.09973 36.7663C8.09973 36.2326 8.52616 35.7826 9.07405 35.7826H16.8468C17.3947 35.7826 17.8211 36.2326 17.8211 36.7663C17.8211 37.3 17.3947 37.75 16.8468 37.75H9.07405ZM7.50368 34.1274C7.50368 34.5374 7.83236 34.8611 8.228 34.8611H17.769C18.1646 34.8611 18.4933 34.5374 18.4933 34.1274C18.4933 33.7266 18.1646 33.3937 17.769 33.3937H8.228C7.83236 33.3937 7.50368 33.7266 7.50368 34.1274ZM8.34973 36.7663C8.34973 37.1671 8.66929 37.5 9.07405 37.5H16.8468C17.2516 37.5 17.5711 37.1671 17.5711 36.7663C17.5711 36.3655 17.2516 36.0326 16.8468 36.0326H9.07405C8.66929 36.0326 8.34973 36.3655 8.34973 36.7663Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 26 / 38,\n  svg: GreenBulb,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenCurvedLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Curved Line', 'sticker name', 'web-stories');\n\nfunction GreenCurvedLine({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 4\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.08797 3.49363C19.6676 0.748202 38.4117 0.551989 56.7743 2.91001C57.2697 2.96143 57.488 2.22379 57.0021 2.1403C38.576 -0.233129 19.7588 -0.0202542 1.11573 2.70976C0.614194 2.79433 0.586433 3.5782 1.08797 3.49363Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 4,\n  svg: GreenCurvedLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenLightning.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Lightning', 'sticker name', 'web-stories');\n\nfunction GreenLightning({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 46 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M23 0C10.5976 0 0.5 10 0.5 22.2826C0.5 32.2554 7.08537 40.5706 16.0305 43.4511V43.6413C16.0305 43.8859 16.1951 44.1033 16.4146 44.1576C16.9085 44.3206 17.4299 44.4293 17.9512 44.5652V48.3696C17.9512 49.2663 18.6921 50 19.5976 50C20.503 50 21.2439 49.2663 21.2439 48.3696V45.0543C22.4238 45.1359 23.5488 45.1359 24.7287 45.0543V48.3696C24.7287 49.2663 25.4695 50 26.375 50C27.2805 50 28.0213 49.2663 28.0213 48.3696V44.5652C28.5427 44.4565 29.064 44.3206 29.5579 44.1576C29.7774 44.0761 29.9421 43.8859 29.9421 43.6413V43.4783C38.9146 40.5707 45.5 32.2826 45.5 22.2826C45.5 10 35.4024 0 23 0ZM29.9146 35.1902C29.7774 34.9185 29.4482 34.837 29.2012 34.9457C25.1951 36.875 20.6951 36.7935 16.8262 34.9457C16.5793 34.837 16.25 34.9185 16.1128 35.1902C11.311 32.663 8.26524 27.6902 8.26524 22.2826C8.26524 14.212 14.878 7.66304 23.0274 7.66304C31.1768 7.66304 37.7896 14.212 37.7896 22.2826C37.7622 27.6902 34.7165 32.663 29.9146 35.1902ZM20.1738 48.3696C20.1738 48.6685 19.9268 48.913 19.625 48.913C19.3232 48.913 19.0762 48.6685 19.0762 48.3696V44.7826C19.4329 44.837 19.8171 44.8913 20.2012 44.9456V48.3696H20.1738ZM26.9512 48.3696C26.9512 48.6685 26.7043 48.913 26.4024 48.913C26.1006 48.913 25.8537 48.6685 25.8537 48.3696V44.9456C26.2378 44.8913 26.5945 44.837 26.9787 44.7826V48.3696H26.9512ZM28.872 43.2337C25.0579 44.2935 20.9146 44.2935 17.1006 43.2337C17.1006 41.7391 17.1006 39.4565 17.1006 36.2772C20.8598 37.8261 25.0305 37.8533 28.872 36.2772C28.872 39.4565 28.872 41.7391 28.872 43.2337ZM29.9695 42.3098V36.3587C35.375 33.7228 38.8598 28.2337 38.8598 22.2554C38.8598 13.587 31.753 6.54891 23 6.54891C14.247 6.54891 7.14024 13.587 7.14024 22.2554C7.14024 28.2337 10.625 33.7228 16.0305 36.3587V42.2826C7.35976 39.375 1.59756 31.413 1.59756 22.2826C1.59756 10.5978 11.2012 1.08696 23 1.08696C34.7988 1.08696 44.4024 10.5978 44.4024 22.2826C44.4024 31.413 38.6402 39.375 29.9695 42.3098ZM42.7287 22.4185L40.5061 22.337C40.3689 22.337 40.2317 22.3913 40.1219 22.4728C39.7927 22.7717 40.0945 23.0435 39.7104 25.1902C39.6555 25.4891 39.8476 25.7609 40.1494 25.8152C42.5366 26.2228 42.3445 26.1957 42.4268 26.1957C42.7012 26.1957 42.9207 26.0054 42.9756 25.7337C43.1402 24.837 43.25 23.8859 43.2774 22.9348C43.2774 22.6902 43.0305 22.4185 42.7287 22.4185ZM41.9878 25.0543L40.8902 24.8641C40.9451 24.4022 41 23.9402 41.0274 23.4511L42.1524 23.4783C42.125 24.0217 42.0701 24.538 41.9878 25.0543ZM34.689 35.2174C34.4969 34.9728 34.1402 34.9456 33.9207 35.163C33.3171 35.6522 32.686 36.1141 32 36.5489C31.753 36.712 31.6707 37.038 31.8354 37.3098L33.0152 39.1576C33.1799 39.4022 33.5091 39.4837 33.7835 39.3206C34.5793 38.8315 35.3476 38.2609 36.061 37.663C36.2805 37.4728 36.3354 37.1196 36.1159 36.9022L34.689 35.2174ZM33.6189 38.0978L33.0152 37.1739C33.3994 36.9022 33.7835 36.6304 34.1677 36.3315L34.8811 37.1739C34.497 37.5 34.0579 37.7989 33.6189 38.0978ZM41.9329 27.7989L39.8201 27.1196C39.5183 27.038 39.2165 27.1739 39.1341 27.4728C38.4482 29.5652 38.064 29.6467 38.2287 30.0543C38.2835 30.1902 38.3659 30.2989 38.503 30.3533L40.4787 31.3043C40.753 31.4402 41.0823 31.3315 41.2195 31.0598C41.6311 30.2446 41.9878 29.3478 42.2896 28.4511C42.3719 28.2065 42.2348 27.9076 41.9329 27.7989ZM40.4787 30.1087L39.4634 29.6196C39.6555 29.1848 39.8476 28.75 39.9848 28.3152L41.0549 28.6685C40.8902 29.1576 40.6982 29.6467 40.4787 30.1087ZM39.6555 32.7446L37.8171 31.5217C37.5701 31.3587 37.2134 31.413 37.0488 31.6576C36.6098 32.3098 36.1159 32.9076 35.5945 33.5054C35.4024 33.7228 35.4024 34.0761 35.6219 34.2663L37.2683 35.7337C37.4878 35.9239 37.8445 35.9239 38.0366 35.7065C38.6677 35 39.2439 34.2663 39.7652 33.5054C39.9848 33.2609 39.9024 32.9348 39.6555 32.7446ZM37.625 34.5924L36.8018 33.8587C37.1037 33.5054 37.4055 33.125 37.6799 32.7446L38.6128 33.3696C38.2835 33.7772 37.9543 34.1848 37.625 34.5924ZM6.17988 27.1196L4.06707 27.7989C3.79268 27.8804 3.62805 28.2065 3.71037 28.4783C4.01219 29.375 4.3689 30.2446 4.78049 31.087C4.91768 31.3587 5.24695 31.4674 5.52134 31.3315L7.49695 30.3804C7.63415 30.3261 7.71646 30.2174 7.77134 30.0815C7.90854 29.6467 7.55183 29.5924 6.86585 27.5C6.7561 27.2011 6.45427 27.038 6.17988 27.1196ZM5.52134 30.1087C5.30183 29.6467 5.10976 29.1576 4.91768 28.6685L5.9878 28.3152C6.15244 28.75 6.31707 29.1848 6.50915 29.6196L5.52134 30.1087ZM6.17988 33.5054C6.70122 34.2935 7.30488 35.0272 7.93598 35.7065C8.12805 35.9239 8.48476 35.9511 8.70427 35.7337L10.3506 34.2663C10.4604 34.1576 10.5152 34.0217 10.5427 33.8859C10.5701 33.4239 10.186 33.4783 8.95122 31.6576C8.78658 31.413 8.42988 31.3315 8.18293 31.5217L6.34451 32.7446C6.07012 32.9348 6.01524 33.2609 6.17988 33.5054ZM8.34756 32.7446C8.62195 33.125 8.92378 33.5054 9.22561 33.8587L8.40244 34.5924C8.07317 34.1848 7.7439 33.7772 7.44207 33.3696L8.34756 32.7446ZM6.28963 25.1902C6.15244 24.4565 6.07012 23.7772 6.04268 22.8533C6.04268 22.5543 5.76829 22.3098 5.46646 22.337L3.2439 22.4185C2.94207 22.4185 2.69512 22.6902 2.72256 22.9891C2.75 24.0489 2.85976 24.8913 3.02439 25.788C3.07927 26.087 3.35366 26.2772 3.65549 26.2228L5.82317 25.8424C6.15244 25.788 6.34451 25.4891 6.28963 25.1902ZM4.0122 25.0543C3.95732 24.6739 3.875 24.0761 3.84756 23.5054L4.97256 23.4783C5 23.9946 5.05488 24.5109 5.10976 24.8913L4.0122 25.0543ZM9.96646 37.663C10.6799 38.2609 11.4482 38.8043 12.2439 39.3206C12.4909 39.4837 12.8476 39.4022 13.0122 39.1576L14.1921 37.3098C14.3567 37.0652 14.2744 36.712 14.0274 36.5489C13.3415 36.1413 12.7104 35.6793 12.1067 35.163C11.8872 34.9728 11.5305 35 11.3384 35.2174L9.91158 36.9022C9.69207 37.1196 9.74695 37.4728 9.96646 37.663ZM11.8049 36.3315C12.189 36.6304 12.5732 36.9022 12.9573 37.1467L12.3537 38.0707C11.9146 37.7717 11.4756 37.4728 11.064 37.1467L11.8049 36.3315ZM9.69207 7.85326C9.47256 7.63587 9.14329 7.63587 8.92378 7.85326C8.2378 8.50543 7.60671 9.21196 7.03049 9.94565C6.83841 10.1902 6.89329 10.5163 7.1128 10.7065L8.84146 12.0652C8.95122 12.1467 9.08841 12.2011 9.25305 12.1739C9.71951 12.1196 9.60976 11.7663 11.2012 10.2174C11.4207 10 11.4207 9.67391 11.2012 9.45652L9.69207 7.85326ZM9.11585 10.8424L8.2378 10.163C8.56707 9.75543 8.92378 9.375 9.28049 8.99456L10.0488 9.78261C9.74695 10.1359 9.41768 10.4891 9.11585 10.8424ZM14.2195 4.75543C14.0823 4.4837 13.7256 4.40217 13.4787 4.53804C12.6555 4.97283 11.8598 5.46196 11.0915 6.03261C10.8445 6.22283 10.7896 6.54891 10.9817 6.79348L12.2713 8.55978C12.436 8.80435 12.7927 8.8587 13.0396 8.66848C13.6707 8.20652 14.3567 7.77174 15.0427 7.41848C15.3171 7.28261 15.3994 6.95652 15.2622 6.68478L14.2195 4.75543ZM12.8201 7.5L12.1616 6.60326C12.6006 6.30435 13.0396 6.03261 13.5061 5.76087L14.0274 6.73913C13.6159 6.9837 13.2317 7.22826 12.8201 7.5ZM8.10061 13.1522L6.17988 12.0652C5.90549 11.9022 5.57622 12.0109 5.43902 12.2554C4.97256 13.0707 4.56098 13.913 4.20427 14.7826C4.09451 15.0543 4.23171 15.3804 4.5061 15.4891L6.56402 16.3043C6.83841 16.413 7.16768 16.2772 7.27744 16.0054C8.10061 13.9674 8.48476 13.913 8.375 13.4783C8.32012 13.3424 8.2378 13.2065 8.10061 13.1522ZM6.45427 15.0815L5.43902 14.6739C5.65854 14.1848 5.87805 13.7228 6.125 13.2609L7.08537 13.8043C6.86585 14.2391 6.64634 14.6467 6.45427 15.0815ZM3.32622 20.788C5.68598 21.0326 5.54878 21.0326 5.57622 21.0326C5.85061 21.0326 6.09756 20.8152 6.125 20.5435C6.20732 19.7826 6.34451 18.9946 6.53658 18.2337C6.6189 17.9348 6.42683 17.6359 6.125 17.5815L3.98476 17.038C3.68293 16.9565 3.3811 17.1467 3.32622 17.4457C3.10671 18.3696 2.94207 19.2935 2.83232 20.2174C2.80488 20.4891 3.02439 20.7609 3.32622 20.788ZM4.25915 18.2065L5.32927 18.4783C5.21951 18.9402 5.1372 19.4022 5.08232 19.8641L3.98476 19.7554C4.06707 19.2391 4.14939 18.7228 4.25915 18.2065ZM19.4329 3.04348C19.378 2.74457 19.0762 2.55435 18.7744 2.63587C17.8415 2.82609 16.936 3.09783 16.0579 3.39674C15.7835 3.50543 15.6189 3.80435 15.7287 4.10326L16.497 6.16848C16.5793 6.38587 16.7988 6.52174 17.0183 6.52174C17.2652 6.52174 17.814 6.19565 19.4878 5.84239C19.7896 5.78804 19.9817 5.48913 19.8994 5.19022L19.4329 3.04348ZM17.3476 5.29891L16.9634 4.23913C17.4573 4.07609 17.9787 3.94022 18.4726 3.80435L18.6921 4.8913C18.253 5 17.7866 5.13587 17.3476 5.29891ZM39.4634 16.2772L41.5213 15.462C41.7957 15.3533 41.9329 15.0272 41.8232 14.7554C41.4665 13.8859 41.0549 13.0435 40.5884 12.2283C40.4238 11.9565 40.0945 11.875 39.8476 12.038L37.9268 13.125C37.6524 13.288 37.5701 13.6141 37.7348 13.8587C38.1463 14.538 38.4756 15.2446 38.7774 15.9783C38.8598 16.25 39.1616 16.3859 39.4634 16.2772ZM39.875 13.2609C40.122 13.7228 40.3689 14.1848 40.561 14.6739L39.5183 15.0815C39.3262 14.6467 39.1067 14.2391 38.8872 13.8043L39.875 13.2609ZM38.9695 9.91848C38.3933 9.18478 37.7622 8.47826 37.0762 7.85326C36.8567 7.63587 36.5 7.66304 36.3079 7.88043L34.7713 9.45652C34.5518 9.67391 34.5793 10.0272 34.7988 10.2174C36.4177 11.7663 36.3079 12.1739 36.8293 12.1739C36.939 12.1739 37.0762 12.1467 37.1585 12.0652L38.9146 10.7065C39.1341 10.4891 39.1616 10.163 38.9695 9.91848ZM36.8841 10.8424C36.5823 10.4891 36.253 10.1359 35.9238 9.78261L36.6921 8.99456C37.0488 9.375 37.4055 9.75543 37.7622 10.163L36.8841 10.8424ZM39.4634 18.2065C39.6829 19.0489 39.7927 19.7283 39.875 20.5163C39.9024 20.8152 40.1768 21.0326 40.4787 21.0054L42.6738 20.788C42.9756 20.7609 43.1951 20.4891 43.1677 20.1902C43.0854 19.3207 42.9482 18.4783 42.6738 17.4185C42.5915 17.1196 42.2896 16.9565 42.0152 17.0109L39.875 17.5543C39.5732 17.6359 39.4085 17.9348 39.4634 18.2065ZM41.7409 18.2065C41.878 18.7772 41.9604 19.3478 42.0152 19.7554L40.9177 19.8641C40.8628 19.5109 40.7805 18.9946 40.6707 18.4783L41.7409 18.2065ZM29.9421 3.39674C29.0366 3.07065 28.1311 2.79891 27.2256 2.6087C26.9238 2.55435 26.6494 2.74457 26.5671 3.0163L26.1006 5.16304C26.0457 5.46196 26.2378 5.7337 26.5122 5.81522C27.2805 5.97826 28.0488 6.19565 28.7896 6.46739C29.064 6.57609 29.3933 6.44022 29.503 6.1413L30.2713 4.07609C30.3811 3.83152 30.2165 3.50543 29.9421 3.39674ZM28.6524 5.29891C28.186 5.16304 27.7469 5.02717 27.2805 4.91848L27.5 3.83152C27.9939 3.96739 28.5152 4.10326 29.0091 4.2663L28.6524 5.29891ZM34.9085 6.03261C34.1402 5.48913 33.3445 4.97283 32.5213 4.53804C32.2469 4.40217 31.9177 4.4837 31.7805 4.75543L30.7378 6.68478C30.6006 6.95652 30.7104 7.28261 30.9573 7.41848C31.6433 7.77174 32.3293 8.20652 32.9604 8.66848C33.2073 8.83152 33.5366 8.80435 33.7287 8.55978L35.0183 6.79348C35.2104 6.54891 35.1555 6.22283 34.9085 6.03261ZM33.1799 7.5C32.7957 7.22826 32.3841 6.9837 31.9726 6.73913L32.4939 5.76087C32.9604 6.00543 33.3994 6.30435 33.8384 6.60326L33.1799 7.5ZM24.4268 2.22826C23.4939 2.17391 22.5335 2.17391 21.5732 2.25543C21.2713 2.28261 21.0518 2.52717 21.0518 2.82609L21.2165 5C21.2165 5.13587 21.2988 5.27174 21.4085 5.38043C21.7652 5.67935 21.9848 5.35326 24.1799 5.5163C24.4817 5.54348 24.7561 5.29891 24.7561 5L24.9207 2.82609C24.9482 2.52717 24.7287 2.25543 24.4268 2.22826ZM23.7134 4.40217C23.247 4.375 22.7805 4.375 22.2866 4.40217L22.2043 3.28804C22.7256 3.26087 23.2744 3.26087 23.7957 3.28804L23.7134 4.40217Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 46 / 50,\n  svg: GreenLightning,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenSun.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Sun', 'sticker name', 'web-stories');\n\nfunction GreenSun({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 54 54\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27 16.3335C21.1089 16.3335 16.3333 21.1091 16.3333 27.0002C16.3333 32.8912 21.1089 37.6668 27 37.6668C32.891 37.6668 37.6666 32.8912 37.6666 27.0002C37.6666 21.1091 32.891 16.3335 27 16.3335ZM14.3333 27.0002C14.3333 20.0046 20.0043 14.3335 27 14.3335C33.9956 14.3335 39.6666 20.0046 39.6666 27.0002C39.6666 33.9958 33.9956 39.6668 27 39.6668C20.0043 39.6668 14.3333 33.9958 14.3333 27.0002Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M26.8022 16.1357C20.9112 16.1357 16.1355 20.9114 16.1355 26.8024C16.1355 32.6934 20.9112 37.4691 26.8022 37.4691C32.6932 37.4691 37.4689 32.6934 37.4689 26.8024C37.4689 20.9114 32.6932 16.1357 26.8022 16.1357ZM14.1355 26.8024C14.1355 19.8068 19.8066 14.1357 26.8022 14.1357C33.7978 14.1357 39.4689 19.8068 39.4689 26.8024C39.4689 33.798 33.7978 39.4691 26.8022 39.4691C19.8066 39.4691 14.1355 33.798 14.1355 26.8024Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27 0.333496C27.5523 0.333496 28 0.781211 28 1.3335V6.00016C28 6.55245 27.5523 7.00016 27 7.00016C26.4477 7.00016 26 6.55245 26 6.00016V1.3335C26 0.781211 26.4477 0.333496 27 0.333496Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27 47C27.5523 47 28 47.4477 28 48V52.6667C28 53.219 27.5523 53.6667 27 53.6667C26.4477 53.6667 26 53.219 26 52.6667V48C26 47.4477 26.4477 47 27 47Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.13936 8.14006C8.52988 7.74954 9.16305 7.74954 9.55357 8.14006L12.8669 11.4534C13.2574 11.8439 13.2574 12.4771 12.8669 12.8676C12.4764 13.2581 11.8432 13.2581 11.4527 12.8676L8.13936 9.55427C7.74884 9.16375 7.74884 8.53059 8.13936 8.14006Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M41.1333 41.1327C41.5238 40.7422 42.1569 40.7422 42.5475 41.1327L45.8608 44.4461C46.2513 44.8366 46.2513 45.4698 45.8608 45.8603C45.4703 46.2508 44.8371 46.2508 44.4466 45.8603L41.1333 42.547C40.7427 42.1564 40.7427 41.5233 41.1333 41.1327Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.333282 27C0.333282 26.4477 0.780998 26 1.33328 26H5.99995C6.55223 26 6.99995 26.4477 6.99995 27C6.99995 27.5523 6.55223 28 5.99995 28H1.33328C0.780998 28 0.333282 27.5523 0.333282 27Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M47 27C47 26.4477 47.4477 26 48 26H52.6667C53.219 26 53.6667 26.4477 53.6667 27C53.6667 27.5523 53.219 28 52.6667 28H48C47.4477 28 47 27.5523 47 27Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.8669 41.1327C13.2574 41.5233 13.2574 42.1564 12.8669 42.547L9.55357 45.8603C9.16305 46.2508 8.52988 46.2508 8.13936 45.8603C7.74884 45.4698 7.74884 44.8366 8.13936 44.4461L11.4527 41.1327C11.8432 40.7422 12.4764 40.7422 12.8669 41.1327Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M45.8608 8.14006C46.2513 8.53059 46.2513 9.16375 45.8608 9.55427L42.5475 12.8676C42.1569 13.2581 41.5238 13.2581 41.1333 12.8676C40.7427 12.4771 40.7427 11.8439 41.1333 11.4534L44.4466 8.14006C44.8371 7.74954 45.4703 7.74954 45.8608 8.14006Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 54 / 54,\n  svg: GreenSun,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/greenSunLight.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Sunlight', 'sticker name', 'web-stories');\n\nfunction GreenSunlight({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 38\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.1056 22.6062C15.9341 20.7777 18.414 19.7505 20.9999 19.7505C23.5857 19.7505 26.0657 20.7777 27.8942 22.6062C29.7226 24.4347 30.7499 26.9146 30.7499 29.5005C30.7499 30.0528 30.3022 30.5005 29.7499 30.5005C29.1976 30.5005 28.7499 30.0528 28.7499 29.5005C28.7499 27.4451 27.9334 25.4738 26.48 24.0204C25.0265 22.567 23.0553 21.7505 20.9999 21.7505C18.9445 21.7505 16.9732 22.567 15.5198 24.0204C14.0664 25.4738 13.2499 27.4451 13.2499 29.5005C13.2499 30.0528 12.8022 30.5005 12.2499 30.5005C11.6976 30.5005 11.2499 30.0528 11.2499 29.5005C11.2499 26.9146 12.2771 24.4347 14.1056 22.6062Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.0001 0.499512C21.5524 0.499512 22.0001 0.947227 22.0001 1.49951V13.7495C22.0001 14.3018 21.5524 14.7495 21.0001 14.7495C20.4478 14.7495 20.0001 14.3018 20.0001 13.7495V1.49951C20.0001 0.947227 20.4478 0.499512 21.0001 0.499512Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M6.67803 15.1786C7.06855 14.7881 7.70171 14.7881 8.09224 15.1786L10.5772 17.6636C10.9678 18.0542 10.9678 18.6873 10.5772 19.0779C10.1867 19.4684 9.55355 19.4684 9.16302 19.0779L6.67803 16.5928C6.2875 16.2023 6.2875 15.5692 6.67803 15.1786Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.749878 29.5C0.749878 28.9477 1.19759 28.5 1.74988 28.5H5.24988C5.80216 28.5 6.24988 28.9477 6.24988 29.5C6.24988 30.0523 5.80216 30.5 5.24988 30.5H1.74988C1.19759 30.5 0.749878 30.0523 0.749878 29.5Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M35.7501 29.5C35.7501 28.9477 36.1978 28.5 36.7501 28.5H40.2501C40.8024 28.5 41.2501 28.9477 41.2501 29.5C41.2501 30.0523 40.8024 30.5 40.2501 30.5H36.7501C36.1978 30.5 35.7501 30.0523 35.7501 29.5Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M35.3224 15.1786C35.7129 15.5692 35.7129 16.2023 35.3224 16.5928L32.8374 19.0779C32.4468 19.4684 31.8137 19.4684 31.4231 19.0779C31.0326 18.6873 31.0326 18.0542 31.4231 17.6636L33.9081 15.1786C34.2987 14.7881 34.9318 14.7881 35.3224 15.1786Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.749878 36.5005C0.749878 35.9482 1.19759 35.5005 1.74988 35.5005H40.2499C40.8022 35.5005 41.2499 35.9482 41.2499 36.5005C41.2499 37.0528 40.8022 37.5005 40.2499 37.5005H1.74988C1.19759 37.5005 0.749878 37.0528 0.749878 36.5005Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13.2933 6.04241C13.6838 5.65188 14.3169 5.65188 14.7075 6.04241L21.0004 12.3353L27.2933 6.04241C27.6838 5.65188 28.3169 5.65188 28.7075 6.04241C29.098 6.43293 29.098 7.06609 28.7075 7.45662L21.7075 14.4566C21.3169 14.8471 20.6838 14.8471 20.2933 14.4566L13.2933 7.45662C12.9027 7.06609 12.9027 6.43293 13.2933 6.04241Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 38,\n  svg: GreenSunlight,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as homeGardenLightYellowArrow } from './lightYellowArrow';\nimport { default as homeGardenFloral } from './floral';\nimport { default as homeGardenGreenCurvedLine } from './greenCurvedLine';\nimport { default as homeGardenLengthComparison } from './lengthComparison';\nimport { default as homeGardenGreenSun } from './greenSun';\nimport { default as homeGardenGreenBulb } from './greenBulb';\nimport { default as homeGardenScissor } from './scissor';\nimport { default as homeGardenCurvedScissor } from './curvedScissor';\nimport { default as homeGardenWaterDroplet } from './waterDroplet';\nimport { default as homeGardenGreenLightning } from './greenLightning';\nimport { default as homeGardenGreenBag } from './greenBag';\nimport { default as homeGardenGreenSunLight } from './greenSunLight';\n\nexport {\n  homeGardenLightYellowArrow,\n  homeGardenFloral,\n  homeGardenGreenCurvedLine,\n  homeGardenLengthComparison,\n  homeGardenGreenSun,\n  homeGardenGreenBulb,\n  homeGardenScissor,\n  homeGardenCurvedScissor,\n  homeGardenWaterDroplet,\n  homeGardenGreenLightning,\n  homeGardenGreenBag,\n  homeGardenGreenSunLight,\n};\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/lengthComparison.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Length Comparison', 'sticker name', 'web-stories');\n\nfunction LengthComparison({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 44 60\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M14.2151 1.52625C15.4036 0.343436 17.4443 0.343462 18.6328 1.52633C24.5817 7.23945 29.1985 15.9536 31.02 24.5581C32.8377 33.1438 31.904 41.8091 26.473 47.2402C24.0083 49.7048 20.8008 51.1728 16.4239 51.1728C15.8336 51.1728 15.2646 51.1461 14.7158 51.0939C14.7945 51.5275 14.8787 51.9479 14.9684 52.3539C15.5999 55.2142 16.4768 57.2504 17.4775 58.2511C17.7313 58.505 17.7313 58.9165 17.4775 59.1704C17.2237 59.4242 16.8121 59.4242 16.5583 59.1704C15.2786 57.8906 14.3396 55.5355 13.699 52.6342C13.5769 52.0815 13.4649 51.5048 13.363 50.9066C10.4945 50.3793 8.22525 49.0907 6.3748 47.2402C0.943711 41.8091 0.0100819 33.1438 1.82771 24.5581C3.64931 15.9536 8.26615 7.23937 14.2151 1.52625ZM16.4239 49.8728C15.7502 49.8728 15.109 49.8357 14.4979 49.7635C14.1626 47.4841 13.9679 44.9048 13.9306 42.1577C13.8258 34.4536 14.9596 25.5161 17.6279 18.2919C17.7523 17.9552 17.5801 17.5814 17.2434 17.457C16.9066 17.3326 16.5328 17.5048 16.4084 17.8415C13.6712 25.2524 12.5244 34.3564 12.6307 42.1754C12.6664 44.8033 12.8438 47.2957 13.1528 49.5385C10.7506 49.0115 8.85753 47.8845 7.29404 46.321C2.31707 41.344 1.32111 33.2278 3.09953 24.8273C4.87351 16.4478 9.37648 7.97337 15.1199 2.45973L15.1293 2.45045C15.811 1.76873 17.0367 1.76873 17.7184 2.45045L17.7279 2.45973C23.4713 7.97337 27.9742 16.4478 29.7482 24.8273C31.5266 33.2278 30.5307 41.344 25.5537 46.321C23.3406 48.5341 20.467 49.8728 16.4239 49.8728ZM34.6682 1.06641C34.3092 1.06641 34.0182 1.35742 34.0182 1.71641C34.0182 2.07539 34.3092 2.36641 34.6682 2.36641H42.3682C42.7272 2.36641 43.0182 2.07539 43.0182 1.71641C43.0182 1.35742 42.7272 1.06641 42.3682 1.06641H34.6682ZM39.1684 3.06651L39.1675 4.06653L37.8675 4.06535L37.8684 3.06533L39.1684 3.06651ZM39.1657 6.06657L39.1639 8.0666L37.8639 8.06542L37.8657 6.06538L39.1657 6.06657ZM39.1621 10.0666L39.1603 12.0667L37.8603 12.0655L37.8621 10.0655L39.1621 10.0666ZM39.1584 14.0667L39.1566 16.0667L37.8566 16.0656L37.8584 14.0655L39.1584 14.0667ZM39.1548 18.0668L39.153 20.0668L37.853 20.0656L37.8548 18.0656L39.1548 18.0668ZM39.1512 22.0668L39.1494 24.0669L37.8494 24.0657L37.8512 22.0656L39.1512 22.0668ZM39.1475 26.0669L39.1457 28.0669L37.8457 28.0658L37.8475 26.0657L39.1475 26.0669ZM39.1439 30.067L39.1421 32.067L37.8421 32.0658L37.8439 30.0658L39.1439 30.067ZM39.1403 34.067L39.1385 36.0671L37.8385 36.0659L37.8403 34.0659L39.1403 34.067ZM39.1367 38.0671L39.1348 40.0672L37.8348 40.066L37.8367 38.0659L39.1367 38.0671ZM39.133 42.0672L39.1312 44.0672L37.8312 44.066L37.833 42.066L39.133 42.0672ZM39.1294 46.0673L39.1276 48.0673L37.8276 48.0661L37.8294 46.0661L39.1294 46.0673ZM39.1258 50.0673L39.1239 52.0674L37.8239 52.0662L37.8258 50.0661L39.1258 50.0673ZM38.0147 55.0664H34.6682C34.3092 55.0664 34.0182 55.3574 34.0182 55.7164C34.0182 56.0754 34.3092 56.3664 34.6682 56.3664H42.3682C42.7272 56.3664 43.0182 56.0754 43.0182 55.7164C43.0182 55.3574 42.7272 55.0664 42.3682 55.0664H39.1212L39.1221 54.0674L37.8221 54.0662L37.8212 55.0662L38.0147 55.0664Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 44 / 60,\n  svg: LengthComparison,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/lightYellowArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Light Yellow Arrow', 'sticker name', 'web-stories');\n\nfunction YellowArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 22\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.82318 15.0943C17.6232 14.1943 33.4232 12.9943 49.1232 11.4943C50.6232 11.3943 50.6232 8.99435 49.1232 9.09435C33.4232 10.5943 17.6232 11.7943 1.82318 12.6943C0.323181 12.7943 0.323181 15.1943 1.82318 15.0943Z\"\n        fill=\"#FCEFAB\"\n      />\n      <path\n        d=\"M50.7232 9.0956C46.9232 5.6956 42.7232 2.7956 38.2232 0.395599C36.8232 -0.304401 35.6232 1.6956 37.0232 2.4956C41.4232 4.7956 45.4232 7.5956 49.0232 10.8956C50.1232 11.7956 51.8232 10.0956 50.7232 9.0956Z\"\n        fill=\"#FCEFAB\"\n      />\n      <path\n        d=\"M49.0232 9.39452C46.6232 13.0945 43.8232 16.4945 40.6232 19.6945C39.5232 20.7945 41.2232 22.4945 42.3232 21.3945C45.6232 18.0945 48.5232 14.4945 51.1232 10.6945C51.9232 9.29452 49.8232 8.09452 49.0232 9.39452Z\"\n        fill=\"#FCEFAB\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 22,\n  svg: YellowArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/scissor.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Scissors', 'sticker name', 'web-stories');\n\nfunction Scissor({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 32 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M16.1288 20.564C16.115 20.2228 16.2586 19.9256 16.3801 19.623C16.8384 18.4811 17.3023 17.342 17.7606 16.2028C19.7845 11.1868 21.8084 6.16809 23.8322 1.1521C23.9234 0.923723 24.0089 0.692596 24.1194 0.475227C24.3348 0.0542467 24.8235 -0.119098 25.2404 0.0955193C26.7369 0.865941 27.6315 2.0601 27.7999 3.75502C27.8883 4.66302 27.7751 5.55451 27.5569 6.43499C27.3526 7.25769 27.0931 8.06388 26.7866 8.85357C26.5685 9.41487 26.3476 9.97343 26.1074 10.5237C25.5662 11.7482 25.0858 12.9973 24.633 14.2575C23.0094 18.7535 21.3776 23.2467 19.7486 27.7427C19.7017 27.872 19.6547 27.9986 19.6078 28.1279C19.3344 28.9038 19.3234 28.9065 19.5443 29.7155C19.8011 30.6648 20.1048 31.6003 20.5024 32.5028C20.657 32.8522 20.8448 33.1879 21.0353 33.5181C21.3224 34.0133 21.7449 34.349 22.3026 34.4976C22.8051 34.6297 23.3132 34.7452 23.8184 34.8636C24.2188 34.9571 24.6192 35.0452 25.0223 35.125C26.1819 35.3533 27.1842 35.8926 28.0788 36.6438C30.1744 38.4075 31.4832 40.6335 31.8449 43.3492C32.0989 45.2615 31.5881 46.9812 30.1662 48.3652C29.4428 49.0696 28.5675 49.5016 27.5984 49.7657C26.6817 50.0134 25.7512 50.0436 24.8262 49.8868C22.3054 49.4548 20.287 48.1919 18.7877 46.1227C18.2217 45.344 17.8048 44.4828 17.4597 43.5886C17.1339 42.7466 16.8826 41.8799 16.6479 41.0104C16.5209 40.5372 16.4077 40.0584 16.2779 39.5824C16.2282 39.4008 16.1537 39.2247 16.0902 39.0403C15.9107 39.1532 15.8859 39.3182 15.8472 39.4723C15.7229 39.9759 15.607 40.4821 15.4855 40.9857C15.2977 41.7561 15.0796 42.5183 14.809 43.2639C14.2596 44.7745 13.4671 46.131 12.3075 47.2618C11.2914 48.2524 10.0959 48.954 8.77607 49.4576C7.84558 49.8125 6.8792 49.9913 5.88245 49.9996C5.30539 50.0051 4.73385 49.9556 4.17335 49.8042C2.93086 49.4741 1.94515 48.7807 1.20794 47.7351C0.440364 46.64 0.0924683 45.4266 0.0924683 44.1031C0.0924683 42.9062 0.374099 41.7698 0.879376 40.6968C1.93135 38.4543 3.52173 36.6906 5.69746 35.4771C6.91234 34.8003 8.22109 34.4288 9.61544 34.3848C9.72588 34.382 9.83356 34.3765 9.94401 34.3738C10.1842 34.371 10.3554 34.2555 10.4797 34.0519C10.8027 33.5098 11.0816 32.9485 11.3301 32.3707C11.6393 31.6415 11.9403 30.9069 12.2164 30.1667C12.3958 29.6825 12.5256 29.1789 12.6802 28.6699C12.4511 28.0288 12.2247 27.385 11.9927 26.7439C10.6757 23.1256 9.35037 19.5074 8.0361 15.8864C7.52254 14.4721 6.92614 13.0936 6.32423 11.7179C5.78582 10.4907 5.27502 9.25529 4.8719 7.97583C4.5102 6.82295 4.25066 5.65356 4.24237 4.44015C4.23961 3.86233 4.29759 3.29552 4.4743 2.74247C4.86362 1.5263 5.67813 0.678839 6.79085 0.0982708C7.21054 -0.12185 7.69925 0.0404892 7.91737 0.458718C8.03058 0.676087 8.12169 0.904462 8.21281 1.13284C9.70655 4.83086 11.2003 8.52889 12.694 12.2269C13.7074 14.7335 14.7234 17.2402 15.7423 19.7468C15.8555 20.0219 15.9162 20.3246 16.1482 20.5392C16.1454 20.7648 16.231 20.9685 16.3138 21.1693C16.9571 22.7652 17.606 24.3583 18.2549 25.9514C18.2852 26.0257 18.3294 26.0973 18.3846 26.1523C18.4095 26.1743 18.5089 26.1715 18.5227 26.1468C18.5917 26.0312 18.6525 25.9074 18.6994 25.7808C19.7983 22.7514 20.9 19.7248 21.9878 16.6899C22.1811 16.1478 22.3965 15.6195 22.6339 15.0967C23.2469 13.7568 23.8626 12.414 24.4093 11.0438C24.9588 9.67351 25.4475 8.284 25.7567 6.83671C25.9334 6.00576 26.0466 5.1693 25.9886 4.31633C25.9472 3.711 25.8257 3.12493 25.522 2.59114C25.4558 2.47557 25.3646 2.37652 25.2735 2.25545C25.1935 2.32974 25.1161 2.37377 25.083 2.43705C24.9974 2.60765 24.9312 2.78649 24.8594 2.96534C23.5837 6.13233 22.3081 9.29931 21.0325 12.4663C20.044 14.9234 19.0556 17.3805 18.0643 19.8376C17.9622 20.0907 17.8573 20.3439 17.733 20.586C17.6419 20.7593 17.4873 20.8694 17.294 20.9354C17.0151 21.0317 16.7501 21.0042 16.5043 20.8584C16.3718 20.7868 16.2558 20.6658 16.1288 20.564ZM13.5914 31.5728C13.4423 31.6718 13.423 31.8424 13.376 31.9882C13.1634 32.6679 12.8956 33.3255 12.5643 33.9556C12.3461 34.3655 12.1253 34.7755 11.863 35.158C11.4516 35.7578 10.8911 36.1155 10.1235 36.0274C9.76453 35.9862 9.41388 36.0219 9.06598 36.1155C8.74846 36.2008 8.42265 36.2531 8.10789 36.3466C5.6809 37.0895 3.84202 38.5341 2.75691 40.8563C2.15776 42.1385 1.84575 43.484 1.96724 44.9121C2.0059 45.3523 2.1053 45.7733 2.26268 46.1833C2.60781 47.0747 3.2401 47.6883 4.11536 48.0543C4.86085 48.3652 5.65329 48.4753 6.45124 48.401C7.38724 48.3157 8.27631 48.0433 9.10464 47.5893C10.8938 46.6097 12.1998 45.1762 13.0944 43.3602C13.2628 43.019 13.3843 42.6531 13.492 42.2871C13.6687 41.6845 13.7626 41.0627 13.8371 40.4381C13.9365 39.5989 14.0221 38.7542 14.3203 37.9507C14.6158 37.1583 14.9057 36.3631 15.2011 35.5679C15.2287 35.4909 15.2701 35.4194 15.3171 35.3506C15.4109 35.2102 15.5407 35.1084 15.7009 35.0562C16.2006 34.8883 16.6534 35.0919 16.8274 35.5789C16.993 36.0412 17.1449 36.5117 17.2747 36.985C17.6171 38.2231 17.9373 39.4641 18.2769 40.7023C18.5586 41.7313 18.8816 42.7466 19.3317 43.7152C19.6989 44.5131 20.1407 45.2643 20.7177 45.9329C21.408 46.7363 22.2419 47.3444 23.2276 47.7351C24.3375 48.1754 25.4944 48.3569 26.6872 48.2992C27.0461 48.2827 27.394 48.2111 27.7337 48.1011C28.6752 47.8011 29.3489 47.1958 29.7216 46.2796C29.8459 45.9769 29.9287 45.6577 29.9646 45.3303C30.0447 44.6452 30.0198 43.9628 29.8873 43.2887C29.5311 41.4507 28.7194 39.83 27.4769 38.4268C26.6154 37.4527 25.569 36.7951 24.2574 36.6135C24.0393 36.5832 23.8267 36.5227 23.6086 36.5035C22.9266 36.4429 22.2474 36.3549 21.5847 36.1733C21.3859 36.1182 21.2147 36.1733 21.038 36.2723C20.5355 36.553 20.2207 36.9877 19.9888 37.494C19.8977 37.6921 19.8287 37.9012 19.7238 38.0938C19.4835 38.5341 18.9175 38.6304 18.5254 38.3057C18.2714 38.0938 18.1775 37.8187 18.2466 37.4995C18.3653 36.9299 18.6221 36.4182 18.9672 35.9504C19.1633 35.6863 19.3924 35.4524 19.6382 35.2323C19.8508 35.0424 19.8535 34.9736 19.7431 34.7397C19.547 34.3188 19.3317 33.906 19.166 33.4713C18.9534 32.91 18.7795 32.3322 18.5945 31.7626C18.3266 30.9317 18.0726 30.0952 17.7965 29.2642C17.675 28.901 17.5177 28.5516 17.3713 28.1994C17.3409 28.1279 17.2857 28.0646 17.2195 27.9683C17.1366 28.2214 17.0869 28.4058 17.0179 28.5819C16.8826 28.9313 16.6286 29.1707 16.2834 29.311C16.1813 29.3523 16.0791 29.3853 15.977 29.4266C15.8417 29.4789 15.7091 29.4761 15.5794 29.4156C15.4054 29.3358 15.2232 29.267 15.0686 29.1569C14.7152 28.9093 14.497 28.5736 14.497 28.1251C14.4998 27.0878 15.5435 26.4439 16.4712 26.9475C16.5899 27.0108 16.7059 27.0768 16.8274 27.1346C16.8357 27.1401 16.8881 27.0961 16.8854 27.0851C16.8219 26.8787 16.7611 26.6696 16.681 26.4715C15.5076 23.5576 14.3314 20.6438 13.1524 17.7299C11.1644 12.8157 9.17642 7.90154 7.18845 2.9901C7.08629 2.73972 6.97032 2.49208 6.85712 2.23069C6.75772 2.26371 6.66384 2.26646 6.61414 2.31599C6.23587 2.69569 6.01223 3.15795 5.92663 3.68348C5.82447 4.31358 5.87969 4.93542 6.01775 5.55451C6.19722 6.35795 6.5037 7.11736 6.81018 7.87953C7.07524 8.53989 7.34307 9.1975 7.5888 9.86337C9.87498 16.0955 12.1529 22.3304 14.4335 28.5654C14.5081 28.769 14.5909 28.9753 14.6378 29.1872C14.7676 29.7788 15.0023 30.3318 15.1983 30.8986C15.306 31.2096 15.422 31.515 15.5324 31.8231C15.5683 31.925 15.607 32.0295 15.6208 32.1368C15.6512 32.3679 15.5821 32.5716 15.4027 32.7256C14.9913 33.0888 14.3093 32.9788 14.058 32.5028C13.9559 32.3102 13.8924 32.0983 13.8123 31.8974C13.7598 31.7819 13.7212 31.647 13.5914 31.5728Z\"\n        fill=\"#235524\"\n      />\n      <path\n        d=\"M23.3602 37.7933C24.3431 37.7933 25.2736 38.1702 26.124 38.7536C27.0876 39.4139 27.8276 40.2834 28.3688 41.3207C28.4185 41.417 28.4599 41.5188 28.5041 41.6179C28.7332 42.1214 28.3909 42.7322 27.7779 42.8368C27.5736 42.8726 27.3969 42.7818 27.2588 42.6414C27.1649 42.5451 27.0932 42.4241 27.0269 42.3085C26.8916 42.0719 26.7784 41.8215 26.6321 41.5931C25.9473 40.5448 24.9975 39.8459 23.7909 39.4965C22.9847 39.2653 22.1978 39.5763 21.7726 40.2201C21.5379 40.5751 21.455 40.9713 21.5047 41.3923C21.6483 42.6497 22.2364 43.665 23.2028 44.4657C23.628 44.8179 24.1057 45.0793 24.6358 45.2471C25.061 45.3819 25.489 45.4287 25.9307 45.3627C26.5547 45.2691 26.9855 44.9335 27.1926 44.3364C27.2561 44.1575 27.2864 43.9677 27.3417 43.7833C27.5073 43.2413 28.0595 42.9771 28.5814 43.189C28.7719 43.266 28.8906 43.4146 28.9348 43.6127C28.9569 43.7173 28.9679 43.8301 28.9597 43.9374C28.8354 45.3764 27.8387 46.5844 26.4554 46.9641C25.812 47.1402 25.1549 47.1484 24.5088 46.9503C22.5098 46.334 21.063 45.0985 20.2512 43.1615C19.9944 42.5506 19.8232 41.9123 19.8122 41.2574C19.7846 39.6753 20.7151 38.594 21.7808 38.1097C22.3027 37.8703 22.7058 37.785 23.3602 37.7933Z\"\n        fill=\"#235524\"\n      />\n      <path\n        d=\"M3.10763 43.4996C3.07173 42.7705 3.29814 42.0688 3.62395 41.4002C4.41362 39.7741 5.66162 38.646 7.3873 38.0654C7.59438 37.9966 7.80698 37.9361 8.01683 37.881C9.73698 37.4408 11.6587 38.4341 12.117 40.3629C12.2634 40.982 12.2385 41.6121 12.106 42.2339C11.9017 43.1914 11.4488 44.0252 10.8248 44.7708C10.2202 45.4917 9.49953 46.0723 8.66844 46.518C8.64359 46.5318 8.6215 46.5455 8.59665 46.5565C8.11623 46.7959 7.67445 46.6666 7.39834 46.2071C7.19679 45.8687 7.26305 45.4807 7.58058 45.2633C7.76005 45.1395 7.95884 45.0432 8.1466 44.9331C8.8203 44.5424 9.37252 44.0169 9.80601 43.373C10.1484 42.8668 10.3776 42.3137 10.499 41.7194C10.5487 41.4828 10.5543 41.2296 10.5405 40.9875C10.5046 40.3326 9.96891 39.6943 9.30073 39.5044C8.95283 39.4054 8.59389 39.4219 8.24324 39.5072C7.89258 39.5897 7.56677 39.7328 7.26857 39.9309C6.28839 40.5803 5.52633 41.4222 5.00173 42.4733C4.85539 42.7677 4.74771 43.0786 4.69525 43.4033C4.66764 43.5629 4.65383 43.7307 4.66764 43.8903C4.72286 44.5479 5.05419 45.0184 5.67543 45.2633C5.87975 45.3431 6.09235 45.3954 6.29667 45.4724C6.64181 45.6045 6.80471 45.8769 6.77434 46.2429C6.74397 46.6226 6.4789 46.9362 6.13929 47.0078C5.94602 47.0491 5.7555 47.0298 5.57051 46.9775C4.55719 46.6969 3.83379 46.0833 3.4003 45.1258C3.17113 44.6195 3.0883 44.0857 3.10763 43.4996Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 32 / 50,\n  svg: Scissor,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/indoor-garden-oasis/waterDroplet.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Water Droplet', 'sticker name', 'web-stories');\n\nfunction WaterDroplet({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 37 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M19.2489 0.168323L18.8154 0.642292L18.3795 0.170591C18.6246 -0.0559898 19.0025 -0.0569755 19.2489 0.168323ZM18.8176 1.52756C18.7293 1.61307 18.6287 1.71134 18.5164 1.82193C18.0446 2.28681 17.369 2.96905 16.5575 3.83488C14.9339 5.56729 12.7698 8.03097 10.607 10.9562C6.25997 16.8358 2.008 24.462 2.008 31.7194C2.008 41.1143 9.53774 48.7154 18.8154 48.7154C28.0931 48.7154 35.6228 41.1143 35.6228 31.7194C35.6228 24.3774 31.37 16.7509 27.0244 10.8941C24.862 7.97973 22.6983 5.53208 21.0749 3.81302C20.2636 2.95386 19.5881 2.27762 19.1165 1.81709C19.0052 1.70841 18.9052 1.61176 18.8176 1.52756ZM28.0561 10.1286C32.4353 16.0308 36.9074 23.9427 36.9074 31.7194C36.9074 41.8107 28.8155 50 18.8154 50C8.8153 50 0.723412 41.8107 0.723412 31.7194C0.723412 24.0261 5.19629 16.1138 9.57409 10.1925C11.7738 7.2173 13.9721 4.71495 15.6202 2.95643C16.4447 2.07681 17.1323 1.38236 17.6148 0.906924C17.8561 0.669183 18.0461 0.48614 18.1764 0.362023C18.2415 0.299963 18.2917 0.252628 18.3259 0.220548L18.3651 0.183933L18.3754 0.174328L18.3795 0.170591C18.3795 0.170591 18.3795 0.170591 18.8154 0.642292C19.2489 0.168323 19.2489 0.168323 19.2489 0.168323L19.2529 0.172042L19.2633 0.181568L19.3025 0.217853C19.3367 0.249637 19.387 0.296528 19.4521 0.358012C19.5825 0.480976 19.7726 0.662335 20.0139 0.897985C20.4965 1.36924 21.1843 2.05788 22.0089 2.93105C23.6573 4.67666 25.856 7.16354 28.0561 10.1286Z\"\n        fill=\"#235524\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.6673 42.2929C18.6673 41.9381 18.9548 41.6506 19.3096 41.6506C24.4929 41.6506 28.5487 37.9084 28.5487 33.3996C28.5487 33.0449 28.8363 32.7573 29.191 32.7573C29.5457 32.7573 29.8333 33.0449 29.8333 33.3996C29.8333 38.7418 25.0717 42.9352 19.3096 42.9352C18.9548 42.9352 18.6673 42.6476 18.6673 42.2929Z\"\n        fill=\"#235524\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 37 / 50,\n  svg: WaterDroplet,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/kitchen-stories/castIron.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cast Iron Pan', 'sticker name', 'web-stories');\n\nconst CastIron = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 78 76\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M17.0002 50.5C14.0002 37.5 23.5002 33.5 26.5002 33C34.5005 33 32.5 43 38 43C43.5 43 46.8483 44.5174 46.5 48C46 53 40.8872 52.1048 38.5 53C34.5 54.5 35 58.5 31.5 60.5C29.9348 61.3944 20.0002 63.5 17.0002 50.5Z\"\n      fill=\"#FFFFA8\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M9 44.9997C9 57.1499 18.8497 66.9997 31 66.9997C43.1503 66.9997 53 57.1499 53 44.9997C53 32.8494 43.1503 22.9997 31 22.9997C18.8497 22.9997 9 32.8494 9 44.9997ZM31 19.9997C17.1929 19.9997 6 31.1926 6 44.9997C6 58.8068 17.1929 69.9997 31 69.9997C44.8071 69.9997 56 58.8068 56 44.9997C56 31.1926 44.8071 19.9997 31 19.9997Z\"\n      fill=\"#005CD6\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M3 44.9997C3 60.4637 15.536 72.9997 31 72.9997C46.464 72.9997 59 60.4637 59 44.9997C59 29.5357 46.464 16.9997 31 16.9997C15.536 16.9997 3 29.5357 3 44.9997ZM31 13.9997C13.8792 13.9997 0 27.8789 0 44.9997C0 62.1205 13.8792 75.9997 31 75.9997C48.1208 75.9997 62 62.1205 62 44.9997C62 27.8789 48.1208 13.9997 31 13.9997Z\"\n      fill=\"#005CD6\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M65.9651 2.75387C68.6578 0.0612121 73.0235 0.0612078 75.7161 2.75387C78.4088 5.44653 78.4088 9.81219 75.7161 12.5049L57.6591 30.5619L55.5378 28.4406L73.5948 10.3835C75.1159 8.86244 75.1159 6.39628 73.5948 4.87519C72.0737 3.3541 69.6075 3.3541 68.0864 4.87519L50.0294 22.9322L47.9081 20.8109L65.9651 2.75387Z\"\n      fill=\"#005CD6\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M26.3759 31.4997H26.5C28.8564 31.4997 30.5982 32.2529 31.9117 33.4561C33.1669 34.6059 33.9413 36.0906 34.5424 37.3561C34.6722 37.6294 34.7928 37.889 34.9074 38.1356C35.368 39.1268 35.7317 39.9094 36.2029 40.5309C36.7015 41.1885 37.2008 41.4997 37.9998 41.4997C40.8341 41.4997 43.3519 41.8816 45.1658 42.8794C46.0969 43.3916 46.8871 44.0911 47.4034 45.0211C47.9238 45.9585 48.1051 47.0208 47.9923 48.1489C47.8401 49.6712 47.3173 50.8751 46.4746 51.7841C45.6489 52.6749 44.622 53.1679 43.6556 53.4705C42.7212 53.763 41.743 53.9057 40.9491 54.0215L40.9032 54.0282C40.0273 54.156 39.4401 54.2491 39.0264 54.4042C37.5519 54.9571 36.8995 55.9177 36.1181 57.3003C36.058 57.4066 35.9968 57.5164 35.934 57.629C35.1986 58.9489 34.2462 60.6579 32.244 61.802C31.6049 62.1672 30.4626 62.5032 29.1452 62.6352C27.7839 62.7716 26.088 62.7065 24.3267 62.1374C20.6926 60.9633 17.1374 57.7658 15.5384 50.837C13.9395 43.9082 15.6519 39.1514 18.376 36.0689C21.0227 33.0739 24.4852 31.8148 26.2534 31.5201L26.3759 31.4997ZM26.6274 34.5007C25.3423 34.7475 22.662 35.7494 20.624 38.0555C18.5981 40.348 17.0605 44.0912 18.4616 50.1624C19.8626 56.2335 22.7746 58.4833 25.2491 59.2827C26.5421 59.7005 27.8108 59.7538 28.8462 59.6501C29.9255 59.542 30.612 59.2793 30.7555 59.1973C32.01 58.4805 32.5823 57.4645 33.3681 56.0693C33.4134 55.9889 33.4595 55.9071 33.5064 55.8241C34.35 54.3317 35.4476 52.5422 37.9731 51.5952C38.7231 51.3139 39.6276 51.1822 40.3805 51.0726C40.4106 51.0683 40.4404 51.0639 40.4699 51.0596C41.3137 50.9365 42.0727 50.8224 42.7593 50.6075C43.432 50.3969 43.9263 50.1203 44.2744 49.7447C44.6056 49.3874 44.9094 48.8281 45.0072 47.8504C45.0685 47.2373 44.9619 46.8039 44.7805 46.4773C44.5951 46.1433 44.2698 45.8105 43.7199 45.508C42.5718 44.8764 40.6654 44.4997 37.9998 44.4997C36.0487 44.4997 34.7355 43.5609 33.8124 42.3435C33.1258 41.438 32.5905 40.2788 32.1233 39.2673C32.0236 39.0512 31.9269 38.8419 31.8325 38.6432C31.2462 37.4088 30.677 36.3935 29.8853 35.6683C29.1711 35.014 28.1961 34.5257 26.6274 34.5007Z\"\n      fill=\"#005CD6\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 78 / 76,\n  svg: CastIron,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/kitchen-stories/hotDish.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Hot dish', 'sticker name', 'web-stories');\n\nfunction HotDish({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 34 22\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M3 8.57622C3 8.54656 3.02426 8.52252 3.05418 8.52252H30.9458C30.9757 8.52252 31 8.54656 31 8.57622C31 15.99 24.9353 22 17.4542 22H16.5458C9.06467 22 3 15.99 3 8.57622Z\"\n        fill=\"#265ECD\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0 10.9009C0 10.5725 0.268629 10.3063 0.6 10.3063H33.4C33.7314 10.3063 34 10.5725 34 10.9009C34 11.2293 33.7314 11.4955 33.4 11.4955H0.6C0.268629 11.4955 0 11.2293 0 10.9009Z\"\n        fill=\"#265ECD\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.6 7.53153C16.2686 7.53153 16 7.26532 16 6.93694V0.594595C16 0.266209 16.2686 1.43542e-08 16.6 0C16.9314 -1.43542e-08 17.2 0.266209 17.2 0.594595V6.93694C17.2 7.26532 16.9314 7.53153 16.6 7.53153Z\"\n        fill=\"#265ECD\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13.4 6.73874C13.0686 6.73874 12.8 6.47253 12.8 6.14414V2.18018C12.8 1.85179 13.0686 1.58559 13.4 1.58559C13.7314 1.58559 14 1.85179 14 2.18018V6.14414C14 6.47253 13.7314 6.73874 13.4 6.73874Z\"\n        fill=\"#265ECD\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M20.6 6.73874C20.2686 6.73874 20 6.47253 20 6.14414V2.18018C20 1.85179 20.2686 1.58559 20.6 1.58559C20.9314 1.58559 21.2 1.85179 21.2 2.18018V6.14414C21.2 6.47253 20.9314 6.73874 20.6 6.73874Z\"\n        fill=\"#265ECD\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 34 / 22,\n  svg: HotDish,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/kitchen-stories/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as castIron } from './castIron';\nimport { default as hotDish } from './hotDish';\nimport { default as oven } from './oven';\nimport { default as potatoes } from './potatoes';\n\nexport { castIron, hotDish, oven, potatoes };\n"
  },
  {
    "path": "packages/stickers/src/kitchen-stories/oven.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Oven', 'sticker name', 'web-stories');\n\nfunction Oven({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 66 65\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path d=\"M9 23H57V57H9V23Z\" fill=\"#FFFEB2\" />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M63 18.5H3V61C3 61.5523 3.44772 62 4 62H62C62.5523 62 63 61.5523 63 61V18.5ZM63 15.5H3V4C3 3.44772 3.44772 3 4 3H62C62.5523 3 63 3.44772 63 4V15.5ZM66 4C66 1.79086 64.2091 0 62 0H4C1.79086 0 0 1.79086 0 4V61C0 63.2091 1.79086 65 4 65H62C64.2091 65 66 63.2091 66 61V4Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M57 31.4154H9V56H57V31.4154ZM57 29.4154H9V24H57V29.4154ZM59 24C59 22.8954 58.1046 22 57 22H9C7.89543 22 7 22.8954 7 24V56C7 57.1046 7.89543 58 9 58H57C58.1046 58 59 57.1046 59 56V24Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M26.7934 34.1778C27.2475 34.4921 27.3608 35.1151 27.0465 35.5692C26.8322 35.8787 26.5058 36.4519 26.2729 37.0983C26.033 37.7646 25.9411 38.375 26.038 38.8231C26.1744 39.4539 26.4899 40.0158 26.8874 40.7239C26.9401 40.8179 26.9943 40.9143 27.0496 41.0139C27.486 41.7984 28 42.7852 28 43.9655C28 44.8893 27.6765 45.8624 27.3338 46.6427C26.983 47.4412 26.563 48.1469 26.2707 48.5692C25.9564 49.0233 25.3334 49.1366 24.8793 48.8222C24.4252 48.5079 24.3119 47.8849 24.6263 47.4308C24.8511 47.106 25.2069 46.5116 25.5026 45.8384C25.8064 45.1468 26 44.4762 26 43.9655C26 43.3527 25.7382 42.7706 25.3018 41.9861C25.2536 41.8994 25.2027 41.8094 25.15 41.7163C24.7659 41.0379 24.2884 40.1944 24.0832 39.2459C23.8698 38.2595 24.1011 37.2262 24.3913 36.4206C24.6886 35.5952 25.0991 34.8684 25.402 34.4308C25.7163 33.9767 26.3393 33.8634 26.7934 34.1778Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.7934 34.1778C34.2475 34.4921 34.3608 35.1151 34.0465 35.5692C33.8322 35.8787 33.5058 36.4519 33.2729 37.0983C33.033 37.7646 32.9411 38.375 33.038 38.8231C33.1744 39.4539 33.4899 40.0158 33.8874 40.7239C33.9401 40.8179 33.9943 40.9143 34.0496 41.0139C34.486 41.7984 35 42.7852 35 43.9655C35 44.8893 34.6765 45.8624 34.3338 46.6427C33.983 47.4412 33.563 48.1469 33.2707 48.5692C32.9564 49.0233 32.3334 49.1366 31.8793 48.8222C31.4252 48.5079 31.3119 47.8849 31.6263 47.4308C31.8511 47.106 32.2069 46.5116 32.5026 45.8384C32.8064 45.1468 33 44.4762 33 43.9655C33 43.3527 32.7382 42.7706 32.3018 41.9861C32.2536 41.8994 32.2027 41.8094 32.15 41.7163C31.7659 41.0379 31.2884 40.1944 31.0832 39.2459C30.8698 38.2595 31.1011 37.2262 31.3913 36.4206C31.6886 35.5952 32.0991 34.8684 32.402 34.4308C32.7163 33.9767 33.3393 33.8634 33.7934 34.1778Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M40.7934 34.1778C41.2475 34.4921 41.3608 35.1151 41.0465 35.5692C40.8322 35.8787 40.5058 36.4519 40.2729 37.0983C40.033 37.7646 39.9411 38.375 40.038 38.8231C40.1744 39.4539 40.4899 40.0158 40.8874 40.7239C40.9401 40.8179 40.9943 40.9143 41.0496 41.0139C41.486 41.7984 42 42.7852 42 43.9655C42 44.8893 41.6765 45.8624 41.3338 46.6427C40.983 47.4412 40.563 48.1469 40.2707 48.5692C39.9564 49.0233 39.3334 49.1366 38.8793 48.8222C38.4252 48.5079 38.3119 47.8849 38.6263 47.4308C38.8511 47.106 39.2069 46.5116 39.5026 45.8384C39.8064 45.1468 40 44.4762 40 43.9655C40 43.3527 39.7382 42.7706 39.3018 41.9861C39.2536 41.8994 39.2027 41.8094 39.15 41.7163C38.7659 41.0379 38.2884 40.1944 38.0832 39.2459C37.8698 38.2595 38.1011 37.2262 38.3913 36.4206C38.6886 35.5952 39.0991 34.8684 39.402 34.4308C39.7163 33.9767 40.3393 33.8634 40.7934 34.1778Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M52 53.5H13.5V51.5H52V53.5Z\"\n        fill=\"#005CD6\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 66 / 65,\n  svg: Oven,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/kitchen-stories/potatoes.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Potatoes', 'sticker name', 'web-stories');\n\nfunction Potatoes({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 87 73\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M32.4994 18.4997C36.4994 16.8997 45.8327 26.1664 49.9994 30.9997C55.9996 30.4998 68.5 29.4 70.5 29C73 28.5 79.5 25 83.5 31.5C87.5 38 81 48 75 52.5C75 65.5 64 73 46 69.5C31.6 66.7 28.3333 53.3333 28.5 47C27.6665 46.8333 25.3994 44.6 22.9994 37C19.9994 27.5 27.4994 20.4997 32.4994 18.4997Z\"\n        fill=\"#FFFEB2\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M39.3219 19.2546C44.212 22.0006 48.8832 26.9295 51.69 30.5868L49.31 32.4132C46.6168 28.9039 42.238 24.3327 37.8531 21.8704C35.6596 20.6387 33.6245 20.0256 31.8822 20.1743C30.2361 20.3147 28.6442 21.1511 27.2634 23.3086C24.3168 27.9127 24.0862 32.5272 24.9989 36.4746C25.9214 40.4641 28.0094 43.7381 29.6077 45.4886L27.3923 47.5114C25.4906 45.4286 23.1286 41.7025 22.076 37.1504C21.0138 32.5561 21.2832 27.0873 24.7366 21.6914C26.5558 18.8489 28.9389 17.4145 31.6272 17.1851C34.2192 16.964 36.8779 17.8821 39.3219 19.2546Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M40.0384 39.0005C45.106 39.1304 50.8911 40.5516 54.8638 41.5448L54.9196 41.5587L54.9742 41.5769C57.4374 42.3978 59.9868 42.7749 62.5368 43.1521C62.9332 43.2107 63.3297 43.2694 63.7258 43.3297C66.5664 43.7621 69.495 44.291 71.7951 45.7286C74.0592 47.1436 75.3337 48.8091 75.8861 50.8606C76.4069 52.7952 76.2385 54.9385 75.991 57.1662C75.7107 59.6886 74.336 64.2097 70.2823 67.6449C66.1734 71.1271 59.5623 73.2843 49.2414 71.4781C38.9259 69.6729 33.0933 65.3532 30.1912 60.1707C27.3201 55.0435 27.4864 49.3695 28.5448 45.1362C29.1751 42.6148 30.826 40.998 32.9501 40.0769C35.0056 39.1856 37.5078 38.9356 40.0384 39.0005ZM34.1436 42.8293C32.7365 43.4395 31.8249 44.3852 31.4552 45.8638C30.5135 49.6305 30.4299 54.4568 32.8088 58.7049C35.1567 62.8977 40.074 66.8282 49.7586 68.523C59.4377 70.2169 65.0767 68.1241 68.3428 65.3562C71.6642 62.5415 72.7896 58.8126 73.0093 56.8349C73.2618 54.5626 73.3434 52.956 72.9892 51.6405C72.6665 50.4421 71.9411 49.3576 70.2051 48.2726C68.5053 47.2102 66.1837 46.7384 63.2742 46.2955C62.9002 46.2385 62.5176 46.1822 62.1279 46.1248C59.6112 45.7541 56.7975 45.3396 54.0813 44.4415C50.0592 43.4363 44.6227 42.119 39.9615 41.9995C37.6172 41.9394 35.6194 42.1894 34.1436 42.8293Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M72.2753 29.9268C69.837 30.7176 65.9744 31.7358 57.6358 32.4938C51.2126 33.0778 47.0845 34.6481 44.5472 36.2752C41.9728 37.926 41.1152 39.5726 40.9709 40.2942L38.0291 39.7058C38.3848 37.9274 39.9272 35.674 42.9278 33.7498C45.9655 31.8019 50.5874 30.1222 57.3642 29.5062C65.5256 28.7642 69.163 27.7824 71.3497 27.0732C71.6497 26.9759 71.9425 26.8763 72.2289 26.7789C72.9372 26.5379 73.6067 26.3101 74.2517 26.1627C75.2545 25.9335 76.264 25.8689 77.6493 26.0074C80.8092 26.3234 83.4368 28.6444 84.9041 31.5789C86.3892 34.5488 86.8137 38.3624 85.4 42.0379C83.1072 47.9992 78.3836 52.0519 76.639 53.5487C76.3669 53.7822 76.1673 53.9534 76.0607 54.0601L73.9393 51.9388C74.1367 51.7414 74.4376 51.4789 74.8133 51.1512C76.7402 49.47 80.6337 46.0732 82.6 40.961C83.6863 38.1365 83.3608 35.2003 82.2209 32.9206C81.0632 30.6053 79.1908 29.1766 77.3507 28.9926C76.236 28.8811 75.558 28.9415 74.9202 29.0873C74.4316 29.199 73.985 29.3511 73.3671 29.5617C73.0558 29.6678 72.7009 29.7888 72.2753 29.9268Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.8 24.4C38.1314 24.8418 38.0418 25.4686 37.6 25.8L33.6 28.8C33.1582 29.1314 32.5314 29.0418 32.2 28.6C31.8686 28.1582 31.9582 27.5314 32.4 27.2L36.4 24.2C36.8418 23.8686 37.4686 23.9582 37.8 24.4Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M58.8 60.4C59.1314 60.8418 59.0418 61.4686 58.6 61.8L54.6 64.8C54.1582 65.1314 53.5314 65.0418 53.2 64.6C52.8686 64.1582 52.9582 63.5314 53.4 63.2L57.4 60.2C57.8418 59.8686 58.4686 59.9582 58.8 60.4Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M79.8 39.4C80.1314 39.8418 80.0418 40.4686 79.6 40.8L75.6 43.8C75.1582 44.1314 74.5314 44.0418 74.2 43.6C73.8686 43.1582 73.9582 42.5314 74.4 42.2L78.4 39.2C78.8418 38.8686 79.4686 38.9582 79.8 39.4Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.3218 37.0716C33.0056 37.5244 32.3822 37.6352 31.9294 37.3191L27.4275 34.1761C26.9747 33.8599 26.8639 33.2365 27.18 32.7837C27.4962 32.3309 28.1196 32.22 28.5724 32.5362L33.0743 35.6792C33.5271 35.9953 33.6379 36.6187 33.3218 37.0716Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M57.9583 52.2901C57.7983 52.8187 57.24 53.1175 56.7114 52.9575L51.7103 51.4435C51.1817 51.2835 50.8829 50.7252 51.0429 50.1966C51.2029 49.668 51.7611 49.3692 52.2897 49.5293L57.2909 51.0433C57.8195 51.2033 58.1183 51.7615 57.9583 52.2901Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.7614 56.4638C37.2286 56.6092 36.6788 56.2951 36.5335 55.7622L35.0335 50.2641C34.8882 49.7312 35.2022 49.1815 35.7351 49.0361C36.2679 48.8908 36.8176 49.2049 36.963 49.7377L38.463 55.2359C38.6083 55.7687 38.2942 56.3184 37.7614 56.4638Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M63.7632 41.5623C63.2303 41.7076 62.6806 41.3935 62.5352 40.8607L61.0353 35.3625C60.8899 34.8297 61.204 34.2799 61.7368 34.1346C62.2696 33.9892 62.8194 34.3033 62.9647 34.8361L64.4647 40.3343C64.6101 40.8671 64.296 41.4169 63.7632 41.5623Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M34 3.5H0V0.5H34C35.933 0.5 37.5 2.067 37.5 4V11.5C37.5 13.433 35.933 15 34 15H26.5C24.567 15 23 13.433 23 11.5H0V8.5H26V11.5C26 11.7761 26.2239 12 26.5 12H34C34.2761 12 34.5 11.7761 34.5 11.5V4C34.5 3.72386 34.2761 3.5 34 3.5Z\"\n        fill=\"#005CD6\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M55.3931 13.4422C55.6769 13.8026 56.0077 14.1954 56.3769 14.6039C57.4936 15.8398 58.9048 17.1577 60.3418 18.1348C61.8309 19.1474 63.1103 19.6308 64.0254 19.5805C64.4335 19.558 64.7722 19.4307 65.0784 19.1681C65.4022 18.8904 65.7697 18.3907 66.0838 17.5008C66.688 15.7888 66.4049 14.9168 66.0227 14.4253C65.5648 13.8365 64.6246 13.3417 63.1199 13.0788C60.8084 12.6749 57.8338 12.9351 55.3931 13.4422ZM68.3908 12.5835C69.6012 14.1398 69.7316 16.1794 68.9128 18.4992C68.4769 19.7343 67.86 20.7347 67.0315 21.4453C66.1853 22.171 65.2038 22.5202 64.19 22.576C62.2613 22.682 60.2907 21.7279 58.6549 20.6156C56.9668 19.4677 55.378 17.9731 54.151 16.6152C53.5345 15.933 52.9953 15.2697 52.5702 14.6822C52.1641 14.1209 51.8013 13.5465 51.6056 13.057L50.9983 11.5387L52.5633 11.0645C55.4442 10.1915 60.0316 9.49376 63.6362 10.1236C65.4247 10.436 67.2562 11.1247 68.3908 12.5835ZM16.3271 19.7026L16.4956 21.8846C16.7682 25.4173 15.8366 29.3748 14.2021 31.9327C13.3967 33.1932 12.2598 34.3605 10.7734 34.7101C9.14087 35.0942 7.61524 34.3874 6.3789 32.9965C5.23914 31.7143 4.95306 30.2343 5.33229 28.7945C5.68263 27.4644 6.56817 26.2742 7.54454 25.2842C9.51185 23.2895 12.3594 21.6002 14.3528 20.6468L16.3271 19.7026ZM8.23335 29.5586C8.10529 30.0448 8.16088 30.4857 8.62112 31.0035C9.38478 31.8626 9.85936 31.8433 10.0864 31.7899C10.4597 31.702 11.0419 31.3068 11.6742 30.3173C12.5845 28.8926 13.2675 26.7412 13.4763 24.5245C12.1206 25.3376 10.7206 26.3362 9.68048 27.3908C8.86102 28.2217 8.39031 28.9627 8.23335 29.5586Z\"\n        fill=\"#005CD6\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 87 / 73,\n  svg: Potatoes,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/laptop-buying-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as laptopRatingsFull } from './laptopFull';\nimport { default as laptopRatingsThreeFourth } from './laptopThreeFourth';\nimport { default as laptopRatingsHalf } from './laptopHalf';\nimport { default as laptopOff } from './laptopOff';\n\nexport {\n  laptopRatingsFull,\n  laptopRatingsThreeFourth,\n  laptopRatingsHalf,\n  laptopOff,\n};\n"
  },
  {
    "path": "packages/stickers/src/laptop-buying-guide/laptopFull.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Laptop Full', 'sticker name', 'web-stories');\n\nfunction LaptopRatingsFull({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 26\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.9565 1H8.04346C6.3866 1 5.04346 2.34315 5.04346 4V22.1739H36.9565V4C36.9565 2.34315 35.6134 1 33.9565 1ZM8.04346 0C5.83432 0 4.04346 1.79087 4.04346 4V23.1739H37.9565V4C37.9565 1.79086 36.1656 0 33.9565 0H8.04346Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M6.86963 6.82611C6.86963 4.61697 8.66049 2.82611 10.8696 2.82611H31.1305C33.3396 2.82611 35.1305 4.61697 35.1305 6.82611V23.1739H6.86963V6.82611Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M31.1305 3.82611H10.8696C9.21277 3.82611 7.86963 5.16925 7.86963 6.82611V22.1739H34.1305V6.82611C34.1305 5.16926 32.7874 3.82611 31.1305 3.82611ZM10.8696 2.82611C8.66049 2.82611 6.86963 4.61697 6.86963 6.82611V23.1739H35.1305V6.82611C35.1305 4.61697 33.3396 2.82611 31.1305 2.82611H10.8696Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M41.9131 22C41.9131 24.2091 40.1222 26 37.9131 26L4.087 26C1.87786 26 0.0869981 24.2091 0.0869983 22L0.0869984 20.913L41.9131 20.913L41.9131 22Z\"\n        fill=\"#E4E4E4\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.087 25L37.9131 25C39.5699 25 40.9131 23.6569 40.9131 22L40.9131 21.913L1.087 21.913L1.087 22C1.087 23.6568 2.43015 25 4.087 25ZM37.9131 26C40.1222 26 41.9131 24.2091 41.9131 22L41.9131 20.913L0.0869984 20.913L0.0869983 22C0.0869981 24.2091 1.87786 26 4.087 26L37.9131 26Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.2609 24.1739H18.7392C18.0998 24.1739 17.5372 24.5025 17.211 25H24.7891C24.4629 24.5025 23.9003 24.1739 23.2609 24.1739ZM25.905 25C25.5011 23.9327 24.4696 23.1739 23.2609 23.1739H18.7392C17.5304 23.1739 16.499 23.9327 16.0951 25C15.9775 25.3109 15.9131 25.6479 15.9131 26H26.087C26.087 25.6479 26.0226 25.3109 25.905 25Z\"\n        fill=\"#0057FF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 26,\n  svg: LaptopRatingsFull,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/laptop-buying-guide/laptopHalf.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Laptop Half', 'sticker name', 'web-stories');\n\nfunction TechnologyLaptop03({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 43 27\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M34.4589 1H8.5459C6.88905 1 5.5459 2.34315 5.5459 4V22.1739H37.4589V4C37.4589 2.34315 36.1158 1 34.4589 1ZM8.5459 0C6.33676 0 4.5459 1.79087 4.5459 4V23.1739H38.4589V4C38.4589 1.79086 36.6681 0 34.4589 0H8.5459Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M31.6329 3.82422H11.3721C9.71522 3.82422 8.37207 5.16736 8.37207 6.82422V22.172H34.6329V6.82422C34.6329 5.16737 33.2898 3.82422 31.6329 3.82422ZM11.3721 2.82422C9.16293 2.82422 7.37207 4.61508 7.37207 6.82422V23.172H35.6329V6.82422C35.6329 4.61508 33.8421 2.82422 31.6329 2.82422H11.3721Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M7.58936 7C7.58936 4.79086 9.38022 3 11.5894 3H22.5894V23H7.58936V7Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.5894 4H11.5894C9.9325 4 8.58936 5.34315 8.58936 7V22H21.5894V4ZM11.5894 3C9.38022 3 7.58936 4.79086 7.58936 7V23H22.5894V3H11.5894Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M42.4155 22C42.4155 24.2091 40.6247 26 38.4155 26L4.58944 26C2.3803 26 0.58944 24.2091 0.58944 22L0.58944 20.913L42.4155 20.913L42.4155 22Z\"\n        fill=\"#E4E4E4\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.58944 25L38.4155 25C40.0724 25 41.4155 23.6569 41.4155 22L41.4155 21.913L1.58944 21.913L1.58944 22C1.58944 23.6568 2.93259 25 4.58944 25ZM38.4155 26C40.6247 26 42.4155 24.2091 42.4155 22L42.4155 20.913L0.58944 20.913L0.58944 22C0.58944 24.2091 2.3803 26 4.58944 26L38.4155 26Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.7634 24.1758H19.2416C18.6023 24.1758 18.0396 24.5044 17.7134 25.0019H25.2915C24.9653 24.5044 24.4027 24.1758 23.7634 24.1758ZM26.4074 25.0019C26.0036 23.9346 24.9721 23.1758 23.7634 23.1758H19.2416C18.0329 23.1758 17.0014 23.9346 16.5975 25.0019C16.4799 25.3127 16.4155 25.6498 16.4155 26.0019H26.5894C26.5894 25.6498 26.5251 25.3127 26.4074 25.0019Z\"\n        fill=\"#0057FF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 43 / 27,\n  svg: TechnologyLaptop03,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/laptop-buying-guide/laptopOff.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Laptop Off', 'sticker name', 'web-stories');\n\nfunction LaptopOff({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 26\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.9565 1H8.04346C6.3866 1 5.04346 2.34315 5.04346 4V22.1739H36.9565V4C36.9565 2.34315 35.6134 1 33.9565 1ZM8.04346 0C5.83432 0 4.04346 1.79087 4.04346 4V23.1739H37.9565V4C37.9565 1.79086 36.1656 0 33.9565 0H8.04346Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M31.1305 3.82611H10.8696C9.21277 3.82611 7.86963 5.16925 7.86963 6.82611V22.1739H34.1305V6.82611C34.1305 5.16926 32.7874 3.82611 31.1305 3.82611ZM10.8696 2.82611C8.66049 2.82611 6.86963 4.61697 6.86963 6.82611V23.1739H35.1305V6.82611C35.1305 4.61697 33.3396 2.82611 31.1305 2.82611H10.8696Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M41.9131 22C41.9131 24.2091 40.1222 26 37.9131 26L4.087 26C1.87786 26 0.0869981 24.2091 0.0869983 22L0.0869984 20.913L41.9131 20.913L41.9131 22Z\"\n        fill=\"#E4E4E4\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.087 25L37.9131 25C39.5699 25 40.9131 23.6569 40.9131 22L40.9131 21.913L1.087 21.913L1.087 22C1.087 23.6568 2.43015 25 4.087 25ZM37.9131 26C40.1222 26 41.9131 24.2091 41.9131 22L41.9131 20.913L0.0869984 20.913L0.0869983 22C0.0869981 24.2091 1.87786 26 4.087 26L37.9131 26Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.2609 24.1739H18.7392C18.0998 24.1739 17.5372 24.5025 17.211 25H24.7891C24.4629 24.5025 23.9003 24.1739 23.2609 24.1739ZM25.905 25C25.5011 23.9327 24.4696 23.1739 23.2609 23.1739H18.7392C17.5304 23.1739 16.499 23.9327 16.0951 25C15.9775 25.3109 15.9131 25.6479 15.9131 26H26.087C26.087 25.6479 26.0226 25.3109 25.905 25Z\"\n        fill=\"#0057FF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 26,\n  svg: LaptopOff,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/laptop-buying-guide/laptopThreeFourth.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Laptop 3/4', 'sticker name', 'web-stories');\n\nfunction LaptopRatingsThreeFourth({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 42 26\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M33.9567 1H8.0437C6.38685 1 5.0437 2.34315 5.0437 4V22.1739H36.9567V4C36.9567 2.34315 35.6136 1 33.9567 1ZM8.0437 0C5.83456 0 4.0437 1.79087 4.0437 4V23.1739H37.9567V4C37.9567 1.79086 36.1659 0 33.9567 0H8.0437Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M31.1307 3.82611H10.8699C9.21302 3.82611 7.86987 5.16925 7.86987 6.82611V22.1739H34.1307V6.82611C34.1307 5.16926 32.7876 3.82611 31.1307 3.82611ZM10.8699 2.82611C8.66073 2.82611 6.86987 4.61697 6.86987 6.82611V23.1739H35.1307V6.82611C35.1307 4.61697 33.3399 2.82611 31.1307 2.82611H10.8699Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M7.08716 7C7.08716 4.79086 8.87802 3 11.0872 3H30.0872V23H7.08716V7Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M29.0872 4H11.0872C9.4303 4 8.08716 5.34315 8.08716 7V22H29.0872V4ZM11.0872 3C8.87802 3 7.08716 4.79086 7.08716 7V23H30.0872V3H11.0872Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        d=\"M41.9133 22C41.9133 24.2091 40.1225 26 37.9133 26L4.08725 26C1.87811 26 0.0872423 24.2091 0.0872425 22L0.0872426 20.913L41.9133 20.913L41.9133 22Z\"\n        fill=\"#E4E4E4\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M4.08725 25L37.9133 25C39.5702 25 40.9133 23.6569 40.9133 22L40.9133 21.913L1.08724 21.913L1.08724 22C1.08724 23.6568 2.43039 25 4.08725 25ZM37.9133 26C40.1225 26 41.9133 24.2091 41.9133 22L41.9133 20.913L0.0872426 20.913L0.0872425 22C0.0872423 24.2091 1.87811 26 4.08725 26L37.9133 26Z\"\n        fill=\"#0057FF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.2612 24.1739H18.7394C18.1001 24.1739 17.5374 24.5025 17.2112 25H24.7893C24.4631 24.5025 23.9005 24.1739 23.2612 24.1739ZM25.9052 25C25.5014 23.9327 24.4699 23.1739 23.2612 23.1739H18.7394C17.5307 23.1739 16.4992 23.9327 16.0954 25C15.9777 25.3109 15.9133 25.6479 15.9133 26H26.0872C26.0872 25.6479 26.0229 25.3109 25.9052 25Z\"\n        fill=\"#0057FF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 42 / 26,\n  svg: LaptopRatingsThreeFourth,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/los-angeles-city-guide/greenLocationPin.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Location Pin', 'sticker name', 'web-stories');\n\nfunction LocationPin({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 26 31\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M13 30.6714C13 30.6714 25.3636 22.429 25.3636 12.8129C25.3636 9.53381 24.061 6.38908 21.7424 4.07044C19.4238 1.75181 16.279 0.449219 13 0.449219C9.72095 0.449219 6.57621 1.75181 4.25758 4.07044C1.93895 6.38908 0.636353 9.53381 0.636353 12.8129C0.636353 22.429 13 30.6714 13 30.6714ZM17.1211 12.8128C17.1211 15.0889 15.276 16.934 12.9999 16.934C10.7238 16.934 8.87869 15.0889 8.87869 12.8128C8.87869 10.5367 10.7238 8.69156 12.9999 8.69156C15.276 8.69156 17.1211 10.5367 17.1211 12.8128Z\"\n        fill=\"#C2CDA3\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 26 / 31,\n  svg: LocationPin,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/los-angeles-city-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as greenLocationPin } from './greenLocationPin';\n\nexport { greenLocationPin };\n"
  },
  {
    "path": "packages/stickers/src/magazine-article/flightPath.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Flight Path', 'sticker name', 'web-stories');\n\nfunction FlightPath({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 35 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M21.2338 48.3749C21.6045 48.7492 21.6016 49.3531 21.2274 49.7238C20.8531 50.0946 20.2491 50.0917 19.8784 49.7174C19.5077 49.3431 19.5105 48.7392 19.8848 48.3684C20.2591 47.9977 20.8631 48.0006 21.2338 48.3749Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M2.59424 13.4632C2.64373 13.4845 2.67836 13.5198 2.69813 13.5693C2.71791 13.6188 2.71718 13.6683 2.69594 13.7178L2.30089 14.6383L3.16999 15.8903L3.033 16.2095L2.01736 15.2989L1.74975 15.9225L1.88745 16.2672L1.78073 16.5159L1.42186 16.1949L0.945641 16.1575L1.06086 15.8993L1.38283 15.7738L1.65363 15.1428L0.290728 15.0414L0.434616 14.7163L1.94406 14.4763L2.33963 13.5649C2.36087 13.5154 2.39624 13.4808 2.44575 13.461C2.49526 13.4412 2.54476 13.442 2.59424 13.4632Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.958541 17.9835C0.888204 18.241 0.822636 18.4989 0.761787 18.757L0.607051 18.7205C0.668326 18.4606 0.734351 18.201 0.805178 17.9416C0.876005 17.6822 0.951115 17.425 1.03042 17.1701L1.18223 17.2173C1.10347 17.4705 1.02888 17.7259 0.958541 17.9835ZM2.33896 14.2528C2.11256 14.7304 1.90205 15.2179 1.70813 15.715L1.56002 15.6572C1.75531 15.1566 1.96731 14.6657 2.19531 14.1847L2.33896 14.2528ZM0.451149 20.3181C0.365514 20.8447 0.299029 21.3716 0.251267 21.898L0.0929388 21.8836C0.141038 21.3535 0.207992 20.8229 0.294232 20.2926L0.451149 20.3181ZM0.163453 23.4885C0.152873 24.0206 0.1611 24.5516 0.187688 25.0807L0.0289103 25.0887C0.00213619 24.5559 -0.006149 24.0212 0.00450506 23.4853L0.163453 23.4885ZM3.90183 11.4794C3.61 11.9216 3.33304 12.3747 3.0717 12.8384L2.9332 12.7603C3.19638 12.2934 3.47528 11.8371 3.76914 11.3919L3.90183 11.4794ZM5.83456 8.94992C5.48411 9.34883 5.1472 9.75951 4.82458 10.1816L4.69827 10.085C5.02311 9.66007 5.36231 9.24659 5.71513 8.84499L5.83456 8.94992ZM0.322755 26.6674C0.386075 27.1949 0.467498 27.7198 0.566572 28.2415L0.410386 28.2711C0.310642 27.746 0.228664 27.2175 0.164909 26.6864L0.322755 26.6674ZM0.91617 29.7955C1.04982 30.3089 1.2006 30.8183 1.36807 31.3232L1.21717 31.3732C1.04862 30.8651 0.896852 30.3523 0.762319 29.8355L0.91617 29.7955ZM8.09107 6.7033C7.69027 7.05295 7.30148 7.41507 6.92545 7.78929L6.8133 7.67661C7.19183 7.2999 7.58316 6.93541 7.98656 6.58351L8.09107 6.7033ZM1.91819 32.8183C2.11697 33.3095 2.33175 33.7954 2.56209 34.2754L2.41876 34.3441C2.187 33.8612 1.97087 33.3723 1.77082 32.878L1.91819 32.8183ZM10.6198 4.76769C10.1775 5.06397 9.74558 5.37327 9.32476 5.69523L9.22816 5.56897C9.65165 5.24497 10.0863 4.93372 10.5313 4.63561L10.6198 4.76769ZM13.3705 3.16032C12.8948 3.40094 12.4279 3.65503 11.9704 3.92223L11.8902 3.78495C12.3505 3.51613 12.8202 3.26051 13.2988 3.01846L13.3705 3.16032ZM3.29555 35.6899C3.55373 36.1525 3.82672 36.6087 4.11409 37.0577L3.98019 37.1434C3.6911 36.6917 3.41647 36.2328 3.15673 35.7674L3.29555 35.6899ZM16.2926 1.89258C15.792 2.07593 15.2986 2.27306 14.813 2.48363L14.7497 2.33778C15.2382 2.12597 15.7345 1.9277 16.238 1.7433L16.2926 1.89258ZM5.01244 38.3736C5.32363 38.8017 5.6484 39.2223 5.98634 39.6346L5.86338 39.7354C5.5235 39.3207 5.19685 38.8977 4.88384 38.467L5.01244 38.3736ZM19.3428 0.968895C18.8241 1.09451 18.3111 1.23417 17.8044 1.38755L17.7583 1.23539C18.2679 1.08114 18.7838 0.940698 19.3054 0.814382L19.3428 0.968895ZM7.03157 40.8379C7.39001 41.2275 7.76086 41.6085 8.14371 41.9803L8.03295 42.0944C7.64797 41.7205 7.27504 41.3374 6.91457 40.9455L7.03157 40.8379ZM9.31759 43.0585C9.71689 43.4054 10.1274 43.7427 10.5488 44.07L10.4513 44.1956C10.0276 43.8665 9.61483 43.5273 9.21334 43.1785L9.31759 43.0585ZM22.4761 0.391625C21.9469 0.459324 21.4219 0.541213 20.9017 0.636977L20.873 0.480626C21.396 0.384334 21.9239 0.301998 22.456 0.233932L22.4761 0.391625ZM11.8336 45.0131C12.2683 45.3145 12.7132 45.6055 13.1678 45.8858L13.0844 46.0211C12.6273 45.7394 12.1801 45.4467 11.743 45.1438L11.8336 45.0131ZM25.6545 0.158951C25.1206 0.169252 24.5895 0.193838 24.062 0.232412L24.0504 0.0738587C24.5808 0.0350772 25.1147 0.0103586 25.6515 0L25.6545 0.158951ZM14.5471 46.6862C15.0113 46.9394 15.4846 47.1816 15.9667 47.4125L15.898 47.5559C15.4135 47.3238 14.9377 47.0803 14.471 46.8258L14.5471 46.6862ZM28.8409 0.26667C28.3084 0.220478 27.7777 0.188561 27.2492 0.170648L27.2546 0.0117605C27.7859 0.0297672 28.3194 0.0618519 28.8546 0.108286L28.8409 0.26667ZM17.4213 48.0629C17.9089 48.266 18.4045 48.4576 18.9079 48.6373L18.8544 48.787C18.3485 48.6064 17.8503 48.4138 17.3602 48.2097L17.4213 48.0629ZM31.9964 0.706703C31.4716 0.60565 30.9473 0.518756 30.4242 0.445763L30.4462 0.28831C30.972 0.36168 31.4989 0.449024 32.0265 0.550592L31.9964 0.706703ZM20.4273 49.1362L20.5311 48.7723L21.1696 49.4317L20.7251 49.5459L20.7259 49.543L20.2793 49.655L20.3837 49.2891C20.3813 49.2884 20.3789 49.2877 20.3765 49.287L20.4222 49.1347C20.4239 49.1352 20.4256 49.1357 20.4273 49.1362ZM33.5585 1.04923L33.5534 1.04797L33.5914 0.893596C33.5938 0.894194 33.5963 0.894793 33.5987 0.895391L33.6947 0.527282L34.0224 0.850718L34.0232 0.847831L34.348 1.17206L33.463 1.41541L33.5585 1.04923Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 35 / 50,\n  svg: FlightPath,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/magazine-article/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as flightPath } from './flightPath';\n\nexport { flightPath };\n"
  },
  {
    "path": "packages/stickers/src/modernist-travel-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as linedCircle } from './linedCircle';\n\nexport { linedCircle };\n"
  },
  {
    "path": "packages/stickers/src/modernist-travel-guide/linedCircle.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Lined Circle', 'sticker name', 'web-stories');\n\nfunction LinedCircle({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M17.131 49.5821L1.11422 33.5654L1.35103 33.3286L17.3678 49.3453L17.131 49.5821Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M32.8691 0.417855L48.8858 16.4346L48.649 16.6714L32.6322 0.654664L32.8691 0.417855Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.1 49.7913L0.208597 28.8999L0.445406 28.6631L21.3369 49.5545L21.1 49.7913Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M28.8998 0.209134L49.7912 21.1006L49.5544 21.3374L28.663 0.445943L28.8998 0.209134Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M25.0697 50L0 24.9303L0.236809 24.6935L25.3065 49.7632L25.0697 50Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M24.9301 0L49.9998 25.0697L49.763 25.3065L24.6933 0.236809L24.9301 0Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M28.3428 49.5127L0.487502 21.6575L0.724311 21.4206L28.5796 49.2759L28.3428 49.5127Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.6575 0.487294L49.5128 28.3426L49.276 28.5794L21.4207 0.724104L21.6575 0.487294Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M31.6156 49.0254L0.974769 18.3846L1.21158 18.1478L31.8524 48.7886L31.6156 49.0254Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.3845 0.975055L49.0253 31.6158L48.7885 31.8526L18.1477 1.21186L18.3845 0.975055Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M34.8886 48.5376L1.46227 15.1113L1.69908 14.8745L35.1254 48.3008L34.8886 48.5376Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.1112 1.46235L48.5375 34.8887L48.3007 35.1255L14.8744 1.69916L15.1112 1.46235Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.4654 47.3537L2.64633 12.5346L2.88314 12.2978L37.7022 47.1169L37.4654 47.3537Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12.5351 2.64608L47.3542 37.4652L47.1174 37.702L12.2983 2.88289L12.5351 2.64608Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M39.3456 45.4735L4.5265 10.6545L4.76331 10.4177L39.5824 45.2367L39.3456 45.4735Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M10.6549 4.52624L45.474 39.3453L45.2372 39.5821L10.4181 4.76305L10.6549 4.52624Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M41.2257 43.5934L6.40666 8.7743L6.64347 8.53749L41.4625 43.3566L41.2257 43.5934Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.77455 6.40664L43.5936 41.2257L43.3568 41.4625L8.53774 6.64345L8.77455 6.40664Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: LinedCircle,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/new-york-party-round-up/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as nycPartyCircleIcon } from './partyCircleText';\nimport { default as nycPartyTwitterIcon } from './twitterIcon';\nimport { default as nycPartyInstagramIcon } from './instagramIcon';\nimport { default as nycPartyTwitchIcon } from './twitchIcon';\n\nexport {\n  nycPartyCircleIcon,\n  nycPartyTwitterIcon,\n  nycPartyInstagramIcon,\n  nycPartyTwitchIcon,\n};\n"
  },
  {
    "path": "packages/stickers/src/new-york-party-round-up/instagramIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Instagram', 'sticker name', 'web-stories');\n\nfunction InstagramIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 30 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M8.18182 2.72727C5.16936 2.72727 2.72727 5.16936 2.72727 8.18182V21.8182C2.72727 24.8306 5.16936 27.2727 8.18182 27.2727H21.8182C24.8306 27.2727 27.2727 24.8306 27.2727 21.8182V8.18182C27.2727 5.16936 24.8306 2.72727 21.8182 2.72727H8.18182ZM0 8.18182C0 3.66312 3.66312 0 8.18182 0H21.8182C26.3369 0 30 3.66312 30 8.18182V21.8182C30 26.3369 26.3369 30 21.8182 30H8.18182C3.66312 30 0 26.3369 0 21.8182V8.18182Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.6591 10.8943C14.8079 10.7681 13.9386 10.9135 13.1748 11.3098C12.4111 11.7061 11.7917 12.3332 11.4049 13.1018C11.018 13.8704 10.8833 14.7414 11.02 15.5909C11.1567 16.4405 11.5578 17.2253 12.1663 17.8337C12.7747 18.4422 13.5595 18.8433 14.4091 18.98C15.2586 19.1167 16.1296 18.982 16.8982 18.5951C17.6668 18.2083 18.2939 17.5889 18.6902 16.8252C19.0865 16.0614 19.2319 15.1921 19.1057 14.3409C18.9769 13.4727 18.5723 12.6689 17.9517 12.0483C17.3311 11.4277 16.5273 11.0231 15.6591 10.8943ZM11.9187 8.88903C13.1917 8.22852 14.6405 7.98621 16.0591 8.19657C17.5061 8.41114 18.8458 9.08543 19.8802 10.1198C20.9146 11.1542 21.5889 12.4939 21.8034 13.9409C22.0138 15.3595 21.7715 16.8083 21.111 18.0813C20.4505 19.3542 19.4054 20.3865 18.1244 21.0312C16.8434 21.676 15.3917 21.9004 13.9758 21.6726C12.5599 21.4448 11.2519 20.7763 10.2378 19.7622C9.22375 18.7481 8.55525 17.4401 8.32741 16.0242C8.09957 14.6083 8.324 13.1566 8.96876 11.8756C9.61352 10.5946 10.6458 9.54954 11.9187 8.88903Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M21.1364 7.5C21.1364 6.74688 21.7469 6.13636 22.5 6.13636H22.5136C23.2668 6.13636 23.8773 6.74688 23.8773 7.5C23.8773 8.25312 23.2668 8.86364 22.5136 8.86364H22.5C21.7469 8.86364 21.1364 8.25312 21.1364 7.5Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 30 / 30,\n  svg: InstagramIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/new-york-party-round-up/partyCircleText.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Party Text', 'sticker name', 'web-stories');\n\nfunction PartyCircleText({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M50.9298 26.6887C50.9086 27.0112 50.8029 27.2649 50.6126 27.45C50.4256 27.6352 50.1837 27.7181 49.8871 27.6987C49.5904 27.6792 49.3599 27.5653 49.1954 27.3569C49.0342 27.1488 48.9642 26.8835 48.9854 26.561L49.034 25.821L47.7861 25.739L47.8115 25.3521L51.0038 25.5617L50.9298 26.6887ZM49.352 26.5268C49.3357 26.7751 49.3737 26.9606 49.466 27.0832C49.5614 27.2093 49.7106 27.279 49.9138 27.2924C50.1169 27.3057 50.2724 27.256 50.3802 27.1433C50.491 27.0339 50.5546 26.8551 50.5709 26.6069L50.6157 25.9249L49.3968 25.8448L49.352 26.5268Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M48.0438 30.3836L48.3425 28.9654L47.5444 28.4505L47.6283 28.0521L50.5021 29.9304L50.4072 30.381L47.021 30.936L47.1059 30.5328L48.0438 30.3836ZM48.4285 30.3209L49.6273 30.1326L50.0947 30.0774L50.0967 30.0679L49.7035 29.8415L48.6693 29.1778L48.4285 30.3209Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M47.7172 32.9429L47.9782 32.2229L46.7295 31.7703L46.8616 31.4057L49.8694 32.4958L49.4565 33.6351C49.3453 33.942 49.1771 34.1594 48.952 34.2875C48.7268 34.4156 48.479 34.4306 48.2086 34.3326C47.996 34.2555 47.8382 34.1313 47.7353 33.96C47.6324 33.7887 47.5911 33.5898 47.6112 33.3634L46.0143 33.7436L46.1712 33.3106L47.7172 32.9429ZM48.32 32.3467L48.0409 33.1169C47.8867 33.5422 47.9889 33.8199 48.3474 33.9498C48.7059 34.0797 48.9622 33.932 49.1164 33.5067L49.3955 32.7365L48.32 32.3467Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M47.2037 37.5873L47.7277 36.6032L45.2248 35.2704L45.4071 34.9281L47.91 36.2609L48.434 35.2769L48.7549 35.4478L47.5246 37.7582L47.2037 37.5873Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M44.6632 38.5223L43.6438 37.7977L43.8685 37.4817L44.8878 38.2062L47.1389 38.4027L46.8721 38.7781L45.0995 38.5945L45.8555 40.2083L45.5887 40.5836L44.6632 38.5223Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M43.2297 43.1085C42.9962 43.332 42.7469 43.4477 42.4816 43.4556C42.2185 43.4659 41.9842 43.3636 41.7786 43.1489C41.573 42.9341 41.4799 42.6944 41.4994 42.4297C41.5211 42.1673 41.6487 41.9244 41.8822 41.7009L42.4179 41.1881L41.5531 40.2847L41.8332 40.0165L44.0455 42.3275L43.2297 43.1085ZM42.1756 41.9233C41.9958 42.0954 41.8986 42.2578 41.8838 42.4107C41.869 42.568 41.9319 42.7203 42.0727 42.8673C42.2135 43.0144 42.3617 43.0827 42.5174 43.0724C42.6729 43.0667 42.8405 42.9778 43.0203 42.8057L43.514 42.3331L42.6693 41.4507L42.1756 41.9233Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M38.6422 43.855L39.8173 43.0067L39.5733 42.0888L39.9034 41.8505L40.7658 45.1737L40.3924 45.4432L37.5138 43.5755L37.8479 43.3343L38.6422 43.855ZM38.9689 44.0675L39.9826 44.7347L40.3655 45.0083L40.3733 45.0026L40.2348 44.5706L39.9161 43.3837L38.9689 44.0675Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M36.6541 45.532L37.3328 45.177L36.7172 44.0001L37.0608 43.8204L38.5436 46.6553L37.4698 47.2169C37.1806 47.3682 36.9097 47.4151 36.6571 47.3575C36.4046 47.3 36.2117 47.1438 36.0784 46.8889C35.9735 46.6885 35.941 46.4903 35.9808 46.2945C36.0206 46.0986 36.1243 45.924 36.2921 45.7706L34.8574 44.9729L35.2654 44.7595L36.6541 45.532ZM37.5013 45.4992L36.7754 45.8789C36.3745 46.0885 36.2624 46.3623 36.4392 46.7002C36.6159 47.0381 36.9047 47.1022 37.3056 46.8925L38.0315 46.5128L37.5013 45.4992Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M33.1665 48.6112L34.216 48.2353L33.2599 45.5657L33.6249 45.4349L34.5811 48.1045L35.6307 47.7286L35.7533 48.0708L33.2891 48.9535L33.1665 48.6112Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M30.6442 47.5881L30.3818 46.3653L30.761 46.284L31.0234 47.5067L32.5507 49.1719L32.1005 49.2686L30.9172 47.936L30.3848 49.6367L29.9346 49.7333L30.6442 47.5881Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M26.5012 49.9995C26.1781 50.007 25.916 49.9242 25.7148 49.7511C25.5137 49.5812 25.4097 49.3476 25.4028 49.0504C25.3959 48.7532 25.489 48.5135 25.6819 48.3312C25.8749 48.1522 26.133 48.0589 26.4561 48.0514L27.1975 48.0343L27.1685 46.784L27.5562 46.775L27.6303 49.9734L26.5012 49.9995ZM26.5226 48.4136C26.2739 48.4193 26.0925 48.4736 25.9785 48.5765C25.8614 48.6826 25.8052 48.8375 25.8099 49.041C25.8146 49.2445 25.8779 49.395 25.9997 49.4924C26.1184 49.593 26.3022 49.6405 26.5509 49.6347L27.2342 49.6189L27.2059 48.3977L26.5226 48.4136Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M22.524 47.4422L23.963 47.615L24.4056 46.7747L24.8099 46.8232L23.1917 49.8511L22.7345 49.7963L21.8837 46.4719L22.2928 46.521L22.524 47.4422ZM22.6202 47.8199L22.9134 48.9975L23.0094 49.4582L23.019 49.4594L23.21 49.0478L23.7801 47.9592L22.6202 47.8199Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M19.9385 47.3358L20.6784 47.5333L21.0209 46.2501L21.3956 46.3501L20.5706 49.4411L19.3997 49.1286C19.0844 49.0444 18.8531 48.8957 18.706 48.6825C18.5589 48.4693 18.5224 48.2238 18.5966 47.9459C18.6549 47.7273 18.765 47.5594 18.9268 47.442C19.0885 47.3247 19.2831 47.2662 19.5104 47.2667L18.9931 45.7088L19.438 45.8275L19.9385 47.3358ZM20.5847 47.8846L19.7932 47.6733C19.3561 47.5566 19.0883 47.6825 18.99 48.0509C18.8917 48.4193 19.061 48.6619 19.4982 48.7786L20.2896 48.9898L20.5847 47.8846Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M15.2903 47.2374L16.3171 47.6717L17.4218 45.06L17.7789 45.2111L16.6743 47.8228L17.7011 48.2571L17.5595 48.5919L15.1487 47.5722L15.2903 47.2374Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M14.1258 44.7762L14.7619 43.6995L15.0958 43.8967L14.4597 44.9735L14.4535 47.233L14.057 46.9988L14.0906 45.2171L12.5462 46.1063L12.1498 45.8721L14.1258 44.7762Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M9.45766 43.7606C9.21471 43.5475 9.07773 43.3092 9.04672 43.0456C9.01358 42.7844 9.09503 42.5421 9.29106 42.3185C9.48709 42.095 9.7178 41.9814 9.9832 41.9778C10.2465 41.9766 10.4996 42.0825 10.7425 42.2956L11.3001 42.7846L12.1247 41.8444L12.4162 42.1001L10.3068 44.5053L9.45766 43.7606ZM10.5465 42.6073C10.3595 42.4432 10.1892 42.3605 10.0357 42.3591C9.87758 42.358 9.73142 42.434 9.59718 42.587C9.46294 42.7401 9.40774 42.8937 9.43158 43.0478C9.45086 43.2023 9.55403 43.3616 9.74111 43.5256L10.255 43.9763L11.0604 43.0579L10.5465 42.6073Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M8.31116 39.2442L9.25487 40.3442L10.149 40.0241L10.4142 40.3332L7.17492 41.4708L6.87508 41.1213L8.4952 38.0964L8.76348 38.4091L8.31116 39.2442ZM8.12677 39.5876L7.5468 40.6536L7.30618 41.058L7.31249 41.0653L7.73145 40.8911L8.88742 40.4742L8.12677 39.5876Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M6.47615 37.4271L6.88965 38.0718L8.0076 37.3547L8.21696 37.6811L5.52411 39.4084L4.86984 38.3884C4.69362 38.1137 4.62302 37.848 4.65803 37.5913C4.69304 37.3347 4.83159 37.1287 5.07368 36.9734C5.26408 36.8513 5.45859 36.8014 5.65719 36.8237C5.8558 36.8461 6.03891 36.934 6.20651 37.0876L6.87439 35.588L7.12302 35.9756L6.47615 37.4271ZM6.58365 38.2681L6.14136 37.5785C5.8971 37.1977 5.61448 37.1103 5.29351 37.3162C4.97255 37.522 4.9342 37.8154 5.17846 38.1962L5.62075 38.8857L6.58365 38.2681Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M3.10531 34.2213L3.57004 35.2347L6.1476 34.0527L6.30924 34.4052L3.73168 35.5872L4.19641 36.6006L3.86595 36.7521L2.77485 34.3729L3.10531 34.2213Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M3.90173 31.625L5.09695 31.2569L5.21107 31.6275L4.01585 31.9956L2.49018 33.6623L2.35467 33.2222L3.57891 31.9272L1.83827 31.5452L1.70275 31.1051L3.90173 31.625Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M1.13561 27.7115C1.10079 27.3902 1.16112 27.122 1.31658 26.9069C1.46883 26.6922 1.69274 26.5688 1.98831 26.5367C2.28388 26.5047 2.53064 26.5771 2.72857 26.7539C2.9233 26.9311 3.03807 27.1803 3.07288 27.5016L3.15278 28.2389L4.3961 28.1042L4.43788 28.4897L1.25728 28.8344L1.13561 27.7115ZM2.71771 27.5986C2.69091 27.3512 2.62144 27.1751 2.50931 27.0702C2.39363 26.9625 2.23458 26.9196 2.03218 26.9415C1.82978 26.9635 1.68522 27.0393 1.59851 27.1689C1.50823 27.2957 1.4765 27.4828 1.5033 27.7302L1.57694 28.4097L2.79134 28.2781L2.71771 27.5986Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M3.3401 23.522L3.28976 24.9705L4.1645 25.3404L4.15036 25.7473L0.996338 24.3912L1.01233 23.931L4.25271 22.8019L4.2384 23.2137L3.3401 23.522ZM2.97189 23.6499L1.82332 24.0416L1.37242 24.1763L1.37209 24.186L1.79835 24.3415L2.93132 24.8174L2.97189 23.6499Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M3.21373 20.9619L3.08176 21.7164L4.39006 21.9452L4.32324 22.3272L1.17187 21.7759L1.38068 20.5822C1.43692 20.2607 1.56479 20.0174 1.76428 19.8522C1.96377 19.6869 2.20517 19.6291 2.48847 19.6787C2.7113 19.7176 2.88825 19.8126 3.01933 19.9634C3.1504 20.1143 3.22566 20.303 3.24509 20.5295L4.75171 19.8777L4.67236 20.3313L3.21373 20.9619ZM2.72365 21.6537L2.86481 20.8468C2.94276 20.4011 2.79393 20.1455 2.41831 20.0797C2.0427 20.014 1.81591 20.204 1.73796 20.6497L1.5968 21.4566L2.72365 21.6537Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M2.89858 16.3294L2.55442 17.3899L5.2516 18.2652L5.1319 18.6341L2.43472 17.7587L2.09057 18.8191L1.74477 18.7069L2.55278 16.2172L2.89858 16.3294Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M5.23848 14.9565L6.36737 15.4947L6.2005 15.8447L5.07161 15.3066L2.82037 15.5007L3.01853 15.085L4.79625 14.9605L3.77362 13.501L3.97177 13.0854L5.23848 14.9565Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M5.87476 10.1606C6.06675 9.90065 6.29279 9.7442 6.55288 9.69125C6.81036 9.63636 7.05867 9.69724 7.2978 9.87388C7.53694 10.0505 7.66943 10.2709 7.69528 10.5351C7.71852 10.7973 7.63414 11.0584 7.44215 11.3183L7.00151 11.9149L8.00745 12.6579L7.77705 12.9698L5.20372 11.069L5.87476 10.1606ZM7.11516 11.1491C7.263 10.949 7.33119 10.7724 7.31973 10.6193C7.30759 10.4616 7.21964 10.3224 7.05589 10.2014C6.89213 10.0804 6.73444 10.0383 6.58282 10.0749C6.43053 10.1071 6.28046 10.2232 6.13262 10.4234L5.72654 10.9731L6.70909 11.6989L7.11516 11.1491Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M10.235 8.67024L9.22136 9.70619L9.6181 10.5691L9.33334 10.8601L7.91786 7.7323L8.23991 7.40315L11.3945 8.75358L11.1063 9.04808L10.235 8.67024ZM9.8768 8.51647L8.76435 8.03157L8.34051 7.8271L8.33373 7.83403L8.54378 8.23621L9.05982 9.35146L9.8768 8.51647Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M11.8529 6.70109L11.247 7.1695L12.0593 8.22029L11.7525 8.45746L9.79586 5.92636L10.7546 5.1852C11.0128 4.98558 11.2713 4.89197 11.53 4.90435C11.7888 4.91674 12.0061 5.0367 12.182 5.26425C12.3203 5.44321 12.3871 5.6326 12.3822 5.8324C12.3774 6.0322 12.3058 6.22231 12.1676 6.40272L13.7199 6.93661L13.3555 7.21825L11.8529 6.70109ZM11.0247 6.88187L11.6728 6.38085C12.0307 6.10416 12.0931 5.81496 11.8598 5.51328C11.6266 5.21159 11.3311 5.19909 10.9731 5.47579L10.325 5.97681L11.0247 6.88187Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M14.7247 3.06819L13.7565 3.62104L15.1627 6.08351L14.8259 6.2758L13.4198 3.81334L12.4516 4.36618L12.2713 4.05048L14.5444 2.75249L14.7247 3.06819Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M17.3475 3.63151L17.8217 4.78871L17.4629 4.93575L16.9887 3.77856L15.1912 2.40927L15.6173 2.23465L17.0174 3.33724L17.241 1.56926L17.6671 1.39464L17.3475 3.63151Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M21.0606 0.494921C21.3775 0.431951 21.65 0.468424 21.878 0.60434C22.1053 0.737086 22.2479 0.949259 22.3059 1.24086C22.3638 1.53246 22.3134 1.78463 22.1547 1.99737C21.9954 2.20694 21.7572 2.34321 21.4403 2.40618L20.7128 2.5507L20.9565 3.77732L20.5762 3.85289L19.9528 0.715L21.0606 0.494921ZM21.3124 2.06094C21.5564 2.01245 21.7257 1.92774 21.8203 1.80682C21.9175 1.68209 21.9462 1.51989 21.9065 1.3202C21.8668 1.12052 21.7786 0.983198 21.6418 0.90824C21.5076 0.829482 21.3184 0.814347 21.0743 0.862833L20.404 0.996014L20.642 2.19412L21.3124 2.06094Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M25.2531 2.3252L23.8062 2.40904L23.5187 3.31423L23.1122 3.33779L24.1709 0.0718686L24.6306 0.0452317L26.0545 3.16731L25.6431 3.19114L25.2531 2.3252ZM25.0917 1.97039L24.5954 0.86298L24.4196 0.426468L24.4099 0.427029L24.2945 0.865847L23.9255 2.03797L25.0917 1.97039Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M27.9487 1.96209L27.1856 1.89719L27.073 3.22057L26.6866 3.1877L26.9578 0L28.1652 0.102699C28.4904 0.13036 28.7441 0.23626 28.9263 0.420401C29.1085 0.604541 29.1874 0.839898 29.163 1.12647C29.1438 1.35186 29.0649 1.5365 28.9262 1.68037C28.7874 1.82425 28.6061 1.91585 28.3823 1.95519L29.1644 3.39844L28.7055 3.35942L27.9487 1.96209ZM27.2164 1.53495L28.0326 1.60437C28.4834 1.64271 28.725 1.47191 28.7573 1.09196C28.7896 0.712013 28.5804 0.502869 28.1296 0.464527L27.3134 0.395103L27.2164 1.53495Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M32.6225 1.24489L31.5362 0.994387L30.899 3.75754L30.5211 3.67041L31.1583 0.907255L30.0719 0.656749L30.1536 0.302498L32.7042 0.890642L32.6225 1.24489Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M34.0939 3.42437L33.659 4.5969L33.2954 4.46203L33.7304 3.2895L33.3355 1.06468L33.7673 1.22483L34.0504 2.98427L35.4124 1.83511L35.8442 1.99526L34.0939 3.42437Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M38.991 3.65358C39.2668 3.82201 39.4424 4.03345 39.518 4.28788C39.5953 4.53955 39.5565 4.79224 39.4015 5.04596C39.2465 5.29968 39.0386 5.45101 38.7777 5.49994C38.5186 5.54612 38.2511 5.48499 37.9753 5.31655L37.3424 4.92998L36.6905 5.99726L36.3596 5.79514L38.0271 3.06488L38.991 3.65358ZM38.1151 4.97597C38.3275 5.10567 38.5094 5.15809 38.6609 5.13324C38.8169 5.10731 38.9479 5.00747 39.054 4.83373C39.1601 4.65999 39.1883 4.49921 39.1384 4.35139C39.0931 4.2025 38.9642 4.06321 38.7518 3.93351L38.1686 3.57727L37.5319 4.61973L38.1151 4.97597Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M40.8703 7.873L39.75 6.95354L38.925 7.42398L38.6102 7.16567L41.6028 5.48297L41.9587 5.7751L40.8884 9.03534L40.5699 8.77396L40.8703 7.873ZM40.9923 7.5028L41.3784 6.35232L41.5452 5.91227L41.5377 5.90612L41.1553 6.15042L40.0893 6.76169L40.9923 7.5028Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M42.9795 9.3189L42.46 8.75613L41.4841 9.65701L41.2211 9.37206L43.5718 7.20208L44.3938 8.09252C44.6152 8.33235 44.731 8.58168 44.7412 8.8405C44.7514 9.09933 44.6509 9.32628 44.4396 9.52136C44.2733 9.67479 44.0905 9.75781 43.891 9.77042C43.6916 9.78302 43.496 9.72832 43.3042 9.6063L42.9077 11.1993L42.5954 10.8609L42.9795 9.3189ZM42.7271 8.50955L43.2828 9.11149C43.5897 9.44392 43.8832 9.48081 44.1634 9.22217C44.4436 8.96352 44.4302 8.66798 44.1234 8.33555L43.5677 7.73361L42.7271 8.50955Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M46.9287 11.9784L46.2961 11.0603L43.961 12.6692L43.741 12.3499L46.0761 10.741L45.4436 9.82296L45.7429 9.61669L47.228 11.7721L46.9287 11.9784Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M46.5774 14.634L45.465 15.2055L45.2878 14.8605L46.4002 14.2891L47.6108 12.3812L47.8212 12.7908L46.8424 14.28L48.623 14.3517L48.8334 14.7613L46.5774 14.634Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M49.9914 18.0039C50.0818 18.3141 50.0693 18.5887 49.9538 18.8277C49.8414 19.0658 49.6425 19.2264 49.3571 19.3096C49.0717 19.3928 48.8161 19.3646 48.5903 19.2251C48.3676 19.0847 48.211 18.8594 48.1206 18.5491L47.9131 17.8371L46.7125 18.187L46.604 17.8147L49.6754 16.9196L49.9914 18.0039ZM48.4534 18.3915C48.523 18.6304 48.6222 18.7917 48.7509 18.8754C48.8836 18.9612 49.0477 18.9757 49.2432 18.9187C49.4386 18.8617 49.5677 18.7619 49.6304 18.619C49.6972 18.4784 49.6957 18.2887 49.6261 18.0498L49.4349 17.3936L48.2621 17.7354L48.4534 18.3915Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M48.5389 22.4284L48.333 20.9937L47.4068 20.7838L47.3489 20.3808L50.6926 21.1595L50.7581 21.6153L47.7675 23.2981L47.709 22.8902L48.5389 22.4284ZM48.8788 22.2376L49.9403 21.6494L50.3603 21.4374L50.359 21.4278L49.912 21.3499L48.7128 21.0812L48.8788 22.2376Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 50,\n  svg: PartyCircleText,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/new-york-party-round-up/twitchIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Twitch', 'sticker name', 'web-stories');\n\nfunction TwitchIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 28 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M0.36377 1.36363C0.36377 0.61052 0.974289 0 1.7274 0H26.2728C27.0259 0 27.6365 0.61052 27.6365 1.36363V17.7272C27.6365 18.0889 27.4928 18.4358 27.2371 18.6915L21.7825 24.146C21.5268 24.4018 21.1799 24.5454 20.8183 24.5454H14.565L9.50981 29.6006C9.11982 29.9906 8.53329 30.1072 8.02374 29.8962C7.51418 29.6851 7.18194 29.1879 7.18194 28.6363V24.5454H1.7274C0.974289 24.5454 0.36377 23.9349 0.36377 23.1818V1.36363ZM3.09104 2.72727V21.8182H8.54558C9.29869 21.8182 9.90921 22.4287 9.90921 23.1818V25.3442L13.0359 22.2176C13.2916 21.9618 13.6385 21.8182 14.0001 21.8182H20.2535L24.9092 17.1624V2.72727H3.09104ZM12.6365 6.81817C13.3896 6.81817 14.0001 7.42869 14.0001 8.18181V13.6363C14.0001 14.3895 13.3896 15 12.6365 15C11.8834 15 11.2728 14.3895 11.2728 13.6363V8.18181C11.2728 7.42869 11.8834 6.81817 12.6365 6.81817ZM19.4547 6.81817C20.2078 6.81817 20.8183 7.42869 20.8183 8.18181V13.6363C20.8183 14.3895 20.2078 15 19.4547 15C18.7015 15 18.091 14.3895 18.091 13.6363V8.18181C18.091 7.42869 18.7015 6.81817 19.4547 6.81817Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 28 / 30,\n  svg: TwitchIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/new-york-party-round-up/twitterIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Twitter', 'sticker name', 'web-stories');\n\nfunction TwitterIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 39 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M38.0294 4.00652C35.647 4.11278 35.699 4.10411 35.4297 4.12593L36.8407 0.22621C36.8407 0.22621 32.4365 1.79421 31.32 2.0747C28.3878 -0.47599 24.0293 -0.588689 20.9133 1.26483C18.3616 2.78305 16.992 5.39022 17.4488 8.43757C12.4827 7.7706 8.29845 5.4923 4.99492 1.65159L3.95008 0.437066L3.16935 1.82469C2.18259 3.57809 1.85493 5.5829 2.24645 7.4697C2.4071 8.24377 2.68016 8.98205 3.05839 9.67334L2.16208 9.3372L2.05574 10.7866C1.94797 12.259 2.45449 13.9777 3.41091 15.3838C3.68021 15.7798 4.02694 16.2146 4.46643 16.6436L4.00325 16.5748L4.56843 18.2357C5.31131 20.4178 6.85429 22.106 8.8567 23.0445C6.85689 23.8658 5.24139 24.3899 2.58596 25.2353L0.156494 26.0082L2.40046 27.1956C3.25603 27.6484 6.27929 29.1605 9.26642 29.614C15.9064 30.6219 23.3824 29.8011 28.4152 25.4143C32.6544 21.7193 34.0454 16.4632 33.7564 10.9936C33.7128 10.1655 33.9471 9.37523 34.4164 8.76867C35.3563 7.55415 38.0236 4.01463 38.0294 4.00652ZM32.642 7.48228C31.8627 8.4893 31.4723 9.77541 31.5422 11.1032C31.8338 16.6204 30.2827 20.899 26.9318 23.8197C23.0174 27.2317 16.7036 28.571 9.60998 27.494C8.32532 27.2991 6.99761 26.8626 5.89874 26.4266C8.12508 25.6852 9.84432 25.0244 12.6208 23.7526L16.4967 21.9771L12.2174 21.712C10.1676 21.585 8.46084 20.6236 7.41167 19.0626C7.96876 19.0313 8.50591 18.944 9.04075 18.7997L13.1221 17.6996L9.00666 16.7241C7.00686 16.2501 5.86696 15.0921 5.26277 14.2039C4.86604 13.6203 4.60686 13.0224 4.45141 12.4712C4.86402 12.5783 5.34512 12.6547 6.12094 12.7291L9.93013 13.0937L6.91208 10.8152C4.73746 9.17361 3.866 6.70737 4.50486 4.3365C11.2917 11.1493 19.2602 10.6373 20.0624 10.8174C19.8858 9.15767 19.8812 9.15375 19.835 8.99575C18.8077 5.48139 21.0589 3.69694 22.0743 3.0929C24.1952 1.8314 27.5617 1.64124 29.8935 3.7196C30.3971 4.16815 31.0782 4.34461 31.7156 4.19136C32.2877 4.05378 32.7573 3.90808 33.217 3.74952L32.26 6.39445L33.4816 6.39529C33.2511 6.69451 32.9745 7.05274 32.642 7.48228Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 39 / 30,\n  svg: TwitterIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/no-days-off/cta.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Circled Dot', 'sticker name', 'web-stories');\n\nconst FitnessCTA = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M20 29.5652c5.2827 0 9.5652-4.2825 9.5652-9.5652 0-5.2828-4.2825-9.5653-9.5652-9.5653-5.2828 0-9.5653 4.2825-9.5653 9.5653 0 5.2827 4.2825 9.5652 9.5653 9.5652z\"\n      fill=\"#fff\"\n    />\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M40 20c0 11.0457-8.9543 20-20 20S0 31.0457 0 20 8.9543 0 20 0s20 8.9543 20 20zm-1.2903 0c0 10.3331-8.3766 18.7097-18.7097 18.7097C9.66693 38.7097 1.29032 30.3331 1.29032 20 1.29032 9.66693 9.66693 1.29032 20 1.29032c10.3331 0 18.7097 8.37661 18.7097 18.70968z\"\n      fill=\"#fff\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 40 / 40,\n  svg: FitnessCTA,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/no-days-off/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as fitnessCTA } from './cta';\n\nexport { fitnessCTA };\n"
  },
  {
    "path": "packages/stickers/src/one-day-city-itinerary/creamSectionSeparator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cream Section Separator', 'sticker name', 'web-stories');\n\nconst CreamSectionSeparator = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 32\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M10.5149 17.9471C6.42464 19.3069 1.05691 16.39 6.12656e-07 14.9808L3.03282 31.036L40 31.036L40 2.40625C37.299 1.43064 30.7046 -0.589525 25.6369 3.06902C20.5691 6.72756 20.7859 14.5324 10.5149 17.9471Z\"\n      fill=\"#F7ECE3\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 40 / 32,\n  svg: CreamSectionSeparator,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/one-day-city-itinerary/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as soloSundayOffWhiteLocation } from './offWhiteLocation';\nimport { default as soloSundayRedSectionSeparator } from './redSectionSeparator';\nimport { default as soloSundayCreamSectionSeparator } from './creamSectionSeparator';\nimport { default as soloSundayWhiteLine } from './whiteLine';\n\nexport {\n  soloSundayOffWhiteLocation,\n  soloSundayRedSectionSeparator,\n  soloSundayCreamSectionSeparator,\n  soloSundayWhiteLine,\n};\n"
  },
  {
    "path": "packages/stickers/src/one-day-city-itinerary/offWhiteLocation.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Off-white Location', 'sticker name', 'web-stories');\n\nconst OffWhiteLocation = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 14 18\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M7 0.5C3.41633 0.5 0.5 3.38008 0.5 6.92104C0.5 11.9523 6.389 17.1472 6.63961 17.3654C6.74289 17.4554 6.87144 17.5 7 17.5C7.12856 17.5 7.25711 17.4554 7.36039 17.3661C7.611 17.1472 13.5 11.9523 13.5 6.92104C13.5 3.38008 10.5837 0.5 7 0.5ZM7 10.4167C5.00883 10.4167 3.38889 8.82788 3.38889 6.875C3.38889 4.92212 5.00883 3.33333 7 3.33333C8.99117 3.33333 10.6111 4.92212 10.6111 6.875C10.6111 8.82788 8.99117 10.4167 7 10.4167Z\"\n      fill=\"#F7ECE3\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 14 / 18,\n  svg: OffWhiteLocation,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/one-day-city-itinerary/redSectionSeparator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Red Section Separator', 'sticker name', 'web-stories');\n\nconst RedSectionSeparator = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 32\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M10.5149 17.9471C6.42464 19.3069 1.05691 16.39 -6.12655e-07 14.9808L3.03282 31.036L40 31.036L40 2.40625C37.299 1.43064 30.7046 -0.589522 25.6369 3.06902C20.5691 6.72756 20.7859 14.5324 10.5149 17.9471Z\"\n      fill=\"#E0193E\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 40 / 32,\n  svg: RedSectionSeparator,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/one-day-city-itinerary/whiteLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Line', 'sticker name', 'web-stories');\n\nconst WhiteLine = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 54 3\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M1.35956 2.14847C14.6931 2.24904 28.0153 2.1033 41.2932 1.70828C45.0941 1.5944 48.8805 1.45586 52.6846 1.30721C53.2209 1.28534 53.039 0.708323 52.5192 0.731685C39.2786 1.27021 26.009 1.57254 12.6972 1.60241C8.93879 1.61498 5.18246 1.60438 1.42716 1.5822C0.877387 1.56782 0.82531 2.14717 1.35956 2.14847Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 54 / 3,\n  svg: WhiteLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/arrowRight.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow Right', 'sticker name', 'web-stories');\n\nconst ArrowRight = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 44 44\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M26.3794 27.4742L34.0047 19.831L26.3794 12.0845V17.5587H15.3536C14.7354 17.5587 14.2201 17.7825 13.808 18.23C13.3958 18.6776 13.1897 19.2113 13.1897 19.831V28.6103H17.5176V22H26.3794V27.4742ZM43.2787 20.4507C44.2404 21.5524 44.2404 22.5853 43.2787 23.5493L23.4941 43.3803C23.082 43.7934 22.5667 44 21.9485 44C21.3302 44 20.815 43.7934 20.4028 43.3803L0.618267 23.5493C0.206087 23.1361 0 22.6197 0 22C0 21.3803 0.206087 20.8639 0.618267 20.4507L20.4028 0.619718C20.815 0.206571 21.3302 0 21.9485 0C22.5667 0 23.082 0.206571 23.4941 0.619718L43.2787 20.4507Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 44 / 44,\n  svg: ArrowRight,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/cheese.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cheese', 'sticker name', 'web-stories');\n\nconst Cheese = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 50 38\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M47.0601 37.0668C45.361 37.0154 43.6691 36.8612 41.9827 36.6575C41.0024 36.5401 40.0258 36.4006 39.0474 36.2703C38.7496 36.2299 38.4864 36.1161 38.2849 35.8849C37.4118 34.8774 36.2663 34.5378 34.9974 34.5617C33.8356 34.5837 32.7192 34.804 31.7317 35.4867C31.414 35.705 31.0564 35.806 30.6643 35.8152C29.2865 35.8464 27.9086 35.8941 26.5308 35.9344C24.7028 35.9895 22.8748 36.0501 21.045 36.0996C18.4182 36.173 15.7951 36.2941 13.1811 36.5823C11.5945 36.7566 10.0007 36.8686 8.40684 36.9677C6.82571 37.0668 5.25366 37.2173 3.68705 37.4522C3.48737 37.4815 3.28224 37.5017 3.08074 37.4999C2.37096 37.4925 1.96251 37.175 1.79914 36.485C1.71926 36.1437 1.65573 35.7913 1.64121 35.4426C1.58312 33.8827 1.31082 32.3521 1.04942 30.8197C1.04034 30.761 1.02763 30.7041 1.02219 30.6454C0.933237 29.5534 0.764413 29.4561 1.53592 28.5881C1.92621 28.1495 2.06417 27.5769 2.12771 27.0024C2.26385 25.7527 2.08595 24.5708 1.30537 23.5394C0.920529 23.031 0.771675 22.4511 0.748076 21.8143C0.688171 20.3057 0.671833 18.7935 0.432213 17.296C0.32511 16.628 0.519347 16.0003 0.915084 15.4699C1.27088 14.9928 1.67388 14.5432 2.10048 14.1284C3.09889 13.1612 4.22983 12.3574 5.3535 11.5499C5.97978 11.0985 6.60606 10.647 7.22508 10.1845C7.82231 9.73673 8.48127 9.46145 9.21647 9.35501C10.0315 9.23755 10.7849 8.94025 11.491 8.51448C12.0302 8.18781 12.4314 7.73818 12.7164 7.17661C12.769 7.072 12.8271 6.96739 12.8634 6.85728C13.1121 6.06997 13.6621 5.55978 14.3302 5.12667C15.7733 4.19254 17.1929 3.22355 18.6306 2.28208C19.4711 1.73152 20.3116 1.18279 21.2392 0.782713C21.8764 0.507431 22.519 0.434022 23.1979 0.558817C24.1256 0.727657 25.0604 0.868968 25.9862 1.04698C26.5544 1.1571 27.1154 1.31676 27.6799 1.45073C28.0611 1.54066 28.4405 1.63976 28.8254 1.70766C29.1521 1.76639 29.3936 1.91504 29.5333 2.22336C29.5933 2.35733 29.655 2.48946 29.7221 2.61976C30.4174 3.95397 31.4957 4.66787 33.0006 4.71742C34.1751 4.75596 35.2425 4.41277 36.2155 3.78146C36.8363 3.37771 37.4771 3.25658 38.1651 3.46763C39.1363 3.76494 40.1166 4.05123 41.0587 4.42745C42.9975 5.20375 45.0215 5.67173 47.0311 6.1911C47.3542 6.27552 47.6719 6.37829 47.9859 6.49207C48.8173 6.79121 49.302 7.37481 49.3855 8.2759C49.4018 8.45025 49.4182 8.62826 49.4146 8.80261C49.3964 9.58257 49.449 10.3552 49.5689 11.126C49.6542 11.6747 49.558 12.1666 49.115 12.5648C48.7937 12.8548 48.6285 13.2567 48.5396 13.6806C48.3544 14.5487 48.4107 15.4039 48.7175 16.2352C48.8409 16.5729 48.9044 16.9106 48.8827 17.2685C48.7501 19.5001 48.9625 21.7244 49.0224 23.9542C49.0733 25.8609 49.0624 27.7677 49.0805 29.6745C49.0987 31.5226 49.1205 33.3725 49.1314 35.2205C49.1332 35.5564 49.1114 35.8977 49.0515 36.2262C48.9426 36.8264 48.663 37.0484 48.0621 37.0613C47.7281 37.0723 47.3941 37.0668 47.0601 37.0668ZM2.14404 28.7753C2.17672 28.7973 2.2094 28.8193 2.24207 28.8413C2.35462 28.7441 2.48714 28.6633 2.57427 28.5477C2.7322 28.3385 2.8502 28.0999 3.00813 27.8907C3.06622 27.8136 3.18966 27.7879 3.28224 27.7384C3.32218 27.8393 3.40205 27.9439 3.39297 28.0412C3.37664 28.2137 3.32218 28.3844 3.25864 28.5477C3.088 28.9845 2.77032 29.313 2.41816 29.5993C2.00064 29.9388 1.87901 30.3591 1.92802 30.8839C2.03331 31.9796 2.09503 33.077 2.19487 34.1726C2.25841 34.859 2.34917 35.5417 2.44175 36.2244C2.49803 36.6392 2.63055 36.7548 3.04262 36.764C3.25864 36.7695 3.47648 36.7456 3.6925 36.7181C4.24072 36.6502 4.7835 36.5437 5.33353 36.5107C6.57883 36.4355 7.82957 36.4244 9.07487 36.3327C10.5798 36.2226 12.0828 36.0831 13.5823 35.9124C15.5446 35.6885 17.5088 35.5032 19.4856 35.4665C21.7657 35.4224 24.0439 35.4004 26.3221 35.3343C27.5256 35.2995 28.7274 35.1949 29.9291 35.1159C30.372 35.0866 30.5064 34.9655 30.6334 34.536C30.6715 34.4094 30.6788 34.2699 30.7333 34.1543C30.8948 33.8129 31.0292 33.4459 31.2543 33.1523C31.7498 32.5063 32.456 32.1502 33.2003 31.8731C33.2402 31.8584 33.2892 31.8327 33.3255 31.8437C33.4018 31.8676 33.507 31.897 33.5306 31.9539C33.5561 32.0126 33.5216 32.1282 33.4744 32.1833C33.4108 32.2567 33.3055 32.2952 33.222 32.3521C32.8517 32.609 32.4669 32.8476 32.1147 33.1302C31.7172 33.4496 31.4848 33.8955 31.3378 34.38C31.2561 34.6498 31.3868 34.7764 31.6591 34.714C31.7988 34.6828 31.9332 34.6186 32.0693 34.569C32.5195 34.4039 32.957 34.1928 33.4199 34.0809C35.1045 33.6735 36.7056 33.857 38.1669 34.8664C38.2867 34.9489 38.4265 35.0829 38.5463 34.9398C38.6208 34.8517 38.628 34.6645 38.599 34.5378C38.5009 34.1011 38.2813 33.723 38.0017 33.3762C37.8093 33.1376 37.6242 32.8935 37.4444 32.6439C37.3918 32.5705 37.3736 32.4732 37.3355 32.3778C37.7276 32.3191 37.871 32.3576 38.1597 32.6054C38.7115 33.0807 39.0419 33.6863 39.1853 34.4002C39.2198 34.5727 39.2452 34.7471 39.2833 34.9196C39.4286 35.5692 39.6283 35.7454 40.2872 35.8078C41.9918 35.9693 43.6963 36.1363 45.4027 36.2905C46.0526 36.3492 46.7043 36.3969 47.3578 36.4208C48.1656 36.4501 48.3635 36.2923 48.447 35.4628C48.5069 34.8663 48.4887 34.2626 48.4906 33.6606C48.4924 32.5026 48.4833 31.3427 48.4797 30.1847C48.4779 29.1864 48.4996 28.188 48.4706 27.1915C48.4179 25.4315 48.3272 23.6734 48.2636 21.9134C48.2183 20.682 48.1929 19.4505 48.1547 18.2173C48.1511 18.0851 48.1329 17.9548 48.1166 17.8227C48.0712 17.4777 47.9024 17.2391 47.5847 17.0739C46.9693 16.7564 46.5228 16.2573 46.2396 15.6259C46.1397 15.4039 46.0925 15.1525 46.0617 14.9084C46.0381 14.723 46.0472 14.4826 46.265 14.4275C46.4919 14.3707 46.5137 14.6221 46.5881 14.7689C46.7515 15.0956 46.8876 15.4387 47.0728 15.7526C47.258 16.0664 47.5012 16.3362 47.9641 16.4077C47.9351 16.2462 47.9224 16.1215 47.8879 16.0058C47.612 15.0699 47.6864 14.1449 47.9895 13.2365C48.0803 12.963 48.2146 12.6859 48.3943 12.4657C48.7229 12.0675 48.8427 11.6233 48.8409 11.1223C48.8391 10.4194 48.8209 9.71655 48.8554 9.01549C48.9026 8.03365 48.4724 7.37481 47.592 7.02612C47.0528 6.81323 46.4974 6.62788 45.9328 6.50675C44.7093 6.24432 43.5039 5.92682 42.3258 5.50289C41.0533 5.04592 39.7698 4.62566 38.4447 4.34303C37.7458 4.19438 37.154 4.28614 36.6729 4.86056C36.3952 5.18907 36.0376 5.4148 35.6473 5.58731C34.3058 6.18008 32.908 6.33608 31.4703 6.11769C30.9093 6.03327 30.3593 5.87177 29.9291 5.45701C29.8147 5.3469 29.7149 5.21843 29.6314 5.08262C29.6041 5.03858 29.6241 4.92847 29.6622 4.88993C29.6985 4.85322 29.7966 4.85322 29.8547 4.87525C29.9182 4.8991 29.9708 4.9615 30.0235 5.01105C30.3811 5.34139 30.8168 5.51207 31.2833 5.56529C32.4215 5.69742 33.5452 5.61667 34.638 5.24596C34.7106 5.2221 34.7759 5.17255 34.8431 5.13401C34.8358 5.10281 34.8286 5.07161 34.8213 5.04041C34.6906 5.05877 34.5545 5.06427 34.4274 5.09914C33.8465 5.25697 33.2547 5.30469 32.6575 5.26798C31.031 5.16521 29.8002 4.45498 29.1394 2.89138C28.9851 2.52433 28.7274 2.31512 28.3498 2.20501C26.7832 1.74987 25.1784 1.48744 23.5737 1.22684C22.6897 1.08369 21.8328 1.10204 21.0359 1.55717C20.3661 1.9389 19.7017 2.3298 19.0518 2.74823C18.5381 3.07857 18.0643 3.47131 17.5523 3.80715C16.5902 4.43663 15.6082 5.03674 14.6442 5.66622C14.0379 6.0608 13.5405 6.54529 13.2773 7.2647C12.9996 8.02815 12.4913 8.62826 11.7996 9.06137C11.0118 9.55321 10.1713 9.90741 9.24914 10.023C8.67369 10.0946 8.16541 10.3001 7.67891 10.6213C6.06147 11.6931 4.55114 12.9098 3.03899 14.1229C2.53978 14.523 2.08051 14.9744 1.6285 15.4296C1.22913 15.8315 1.05305 16.3362 1.10024 16.9143C1.12384 17.2042 1.10932 17.5034 1.15289 17.7915C1.29993 18.7531 1.30356 19.7203 1.29811 20.6893C1.2963 20.9242 1.309 21.1591 1.309 21.394C1.309 22.0455 1.50687 22.6236 1.87175 23.165C2.12226 23.5376 2.36188 23.9395 2.50166 24.3634C2.94096 25.6958 2.91373 27.0171 2.28564 28.2999C2.21484 28.4468 2.18943 28.6156 2.14404 28.7753Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M27.346 10.7336C27.5475 10.5024 27.8016 10.4859 28.034 10.5428C28.3971 10.6327 28.7819 10.7189 29.0978 10.9098C29.931 11.4145 30.8078 11.4805 31.7445 11.3576C33.7086 11.1007 35.6292 10.6639 37.5153 10.0583C39.6102 9.38657 41.7595 8.9663 43.9179 8.57907C44.8746 8.4084 45.824 8.19368 46.7788 8.00465C46.9495 7.97162 47.1964 7.83948 47.2599 8.10192C47.3162 8.32948 47.0511 8.34417 46.8986 8.39922C45.7623 8.81582 44.5914 9.09477 43.4024 9.29848C41.598 9.60863 39.8063 9.972 38.0636 10.5501C36.4153 11.0952 34.7125 11.3759 32.9989 11.6109C32.1511 11.7265 31.3088 11.888 30.4738 12.0733C29.8856 12.2036 29.3664 12.1155 28.9362 11.7044C28.5151 11.3025 28.0758 10.9649 27.4949 10.8511C27.444 10.8456 27.4077 10.7868 27.346 10.7336Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M37.3338 17.1202C37.2231 17.2468 37.1142 17.3734 37.0034 17.5001C36.5042 18.0782 36.1375 18.7113 36.1575 19.5151C36.1793 20.4456 36.7311 21.1742 37.6406 21.3136C38.688 21.4751 39.6302 21.2035 40.3581 20.3722C40.7811 19.8895 40.8664 19.3298 40.6758 18.7278C40.4943 18.1589 40.1911 17.6652 39.7609 17.2505C39.2453 16.755 38.6427 16.6008 37.9528 16.7641C37.8094 16.7972 37.6206 16.9422 37.5335 16.7274C37.4464 16.5146 37.6624 16.4283 37.8022 16.3365C38.1816 16.0906 38.5864 16.0649 39.013 16.1989C40.1802 16.5659 41.3239 18.0433 41.3547 19.2766C41.3711 19.9372 41.1242 20.5245 40.6395 20.9668C39.6828 21.8422 38.5664 22.178 37.2975 21.855C36.3227 21.6073 35.6637 20.7649 35.6057 19.75C35.5675 19.0875 35.6801 18.4636 36.0232 17.891C36.2392 17.5313 36.5206 17.2395 36.9218 17.0945C37.0343 17.0523 37.1614 17.0504 37.283 17.0302C37.2993 17.0596 37.3175 17.089 37.3338 17.1202Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.6993 27.3607C24.8155 27.4598 24.9462 27.5405 25.0406 27.6543C26.1025 28.9408 27.5058 29.3207 29.0923 29.2198C29.784 29.1757 30.4338 28.9922 31.0383 28.6508C31.9696 28.126 32.6122 27.3735 32.85 26.2999C32.8555 26.2706 32.8645 26.243 32.8718 26.2155C32.9535 25.9384 33.066 25.832 33.2367 25.8742C33.4055 25.9164 33.4872 26.065 33.46 26.3403C33.3982 26.9735 33.1241 27.5148 32.7393 28.0085C31.1945 29.9997 28.29 30.6017 26.1007 29.3776C25.4763 29.0289 24.9843 28.5426 24.6739 27.8837C24.6031 27.7332 24.4905 27.5717 24.6993 27.3607Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.4979 16.9844C24.0314 16.9091 23.4232 16.8431 22.8314 16.7109C22.2651 16.5843 21.7876 16.2705 21.4173 15.8135C21.3229 15.696 21.2558 15.5327 21.234 15.3822C21.2104 15.2079 21.3647 15.1235 21.528 15.1969C21.5807 15.2207 21.6279 15.2593 21.6715 15.296C22.2415 15.7951 22.9295 16.0264 23.6574 16.1255C24.7466 16.276 25.8267 16.1842 26.8886 15.8906C27.5349 15.7126 28.0359 15.3437 28.379 14.7564C28.5043 14.5417 28.6495 14.338 28.8092 14.149C28.871 14.0737 28.998 14.0554 29.0942 14.0095C29.1196 14.1141 29.1904 14.2334 29.1614 14.3178C28.8092 15.3418 28.2574 16.1732 27.1664 16.5402C26.3386 16.8174 25.4945 16.9018 24.4979 16.9844Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M44.7167 24.2317C44.4698 24.4024 44.2719 24.5418 44.0686 24.6758C43.5422 25.0263 43.141 25.4723 43.0067 26.1164C42.9885 26.2027 42.9703 26.289 42.9613 26.3752C42.8269 27.5993 43.6311 28.3371 44.8347 28.0911C45.4265 27.97 45.9002 27.6452 46.2905 27.1882C46.3759 27.0891 46.4412 26.968 46.5356 26.8817C46.601 26.8212 46.7244 26.7514 46.7807 26.7771C46.8497 26.8102 46.9241 26.946 46.9096 27.0212C46.8624 27.2616 46.7988 27.5057 46.6954 27.7241C46.6227 27.8746 46.483 28.0012 46.3523 28.115C45.6007 28.7665 44.0958 28.9262 43.2245 28.4527C42.6981 28.1664 42.4022 27.7094 42.335 27.1221C42.2188 26.1183 42.5002 25.2282 43.2118 24.5125C43.4187 24.3033 43.7037 24.1546 43.9778 24.0371C44.1993 23.9435 44.4553 23.9601 44.7167 24.2317Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M15.7825 29.4841C15.7807 30.5503 14.933 31.4019 13.8692 31.4074C12.8 31.4129 12.0666 30.6439 12.072 29.5263C12.0775 28.416 12.9053 27.5038 13.9 27.5149C14.9221 27.5259 15.7843 28.427 15.7825 29.4841ZM12.6257 29.4418C12.6257 30.2053 13.1195 30.7632 13.7893 30.7522C14.5989 30.7412 15.1853 30.1961 15.1962 29.4455C15.2089 28.6912 14.5281 27.9994 13.7857 28.014C13.1013 28.0287 12.6239 28.616 12.6257 29.4418Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.1221 26.6009C24.0549 26.4816 23.9714 26.3697 23.9206 26.2449C23.6428 25.5604 23.5739 24.841 23.71 24.1271C24.0676 22.2588 25.1151 20.9044 26.8069 20.0749C27.2952 19.8345 27.8253 19.7354 28.3717 19.7592C28.6839 19.7739 28.9762 19.8547 29.2213 20.0547C29.2939 20.1134 29.3393 20.2034 29.4518 20.352C29.2449 20.3777 29.1123 20.3942 28.978 20.4089C28.5315 20.4566 28.0794 20.4731 27.6401 20.5576C25.8121 20.9099 24.5033 22.624 24.2201 24.3601C24.1239 24.9492 24.1511 25.5273 24.2564 26.1091C24.2818 26.2541 24.26 26.4082 24.26 26.5587C24.2165 26.5734 24.1693 26.5881 24.1221 26.6009Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.2911 11.119C25.2022 11.3136 25.0061 11.2879 24.8482 11.3338C24.2364 11.5118 23.6156 11.6641 23.0111 11.8641C22.432 12.0568 21.9637 12.4221 21.6097 12.9322C21.5262 13.0515 21.4318 13.1635 21.3446 13.2809C20.9253 13.8572 20.368 14.1692 19.6637 14.2591C19.0882 14.3325 18.5218 14.4647 17.95 14.5564C17.7667 14.5858 17.5724 14.5839 17.3891 14.5601C17.3074 14.5491 17.2366 14.45 17.1622 14.3912C17.2221 14.3197 17.2711 14.2297 17.3455 14.182C17.4145 14.138 17.5107 14.1361 17.596 14.116C18.1207 13.9985 18.6417 13.87 19.1681 13.7673C19.8561 13.6351 20.4025 13.2993 20.8309 12.734C21.0324 12.4698 21.2738 12.2294 21.5262 12.0128C22.2414 11.3998 23.1182 11.198 24.0168 11.064C24.3036 11.0218 24.5904 10.9832 24.879 10.9557C25.0914 10.9374 25.0914 10.9465 25.2911 11.119Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M19.0628 28.6894C19.0174 29.4712 18.9376 30.2291 18.5491 30.91C18.4638 31.0605 18.3567 31.2055 18.2332 31.3229C18.1769 31.3761 18.0117 31.4018 17.9664 31.3596C17.8974 31.2972 17.8484 31.1578 17.8647 31.0642C17.8901 30.9247 17.9791 30.7981 18.0426 30.6659C18.5563 29.5978 18.6489 28.5059 18.2151 27.3882C17.9773 26.7753 17.6051 26.2467 17.0805 25.8595C16.8173 25.6668 16.4942 25.5512 16.1892 25.4245C16.0313 25.3585 15.8425 25.3603 15.6863 25.2906C15.5847 25.2447 15.5175 25.1236 15.434 25.0373C15.5357 24.9676 15.641 24.8373 15.7408 24.8409C16.0113 24.8501 16.2981 24.8685 16.5486 24.9657C17.9355 25.5016 18.7742 26.5055 18.9975 28.0049C19.0319 28.2361 19.0428 28.471 19.0628 28.6894Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M18.1751 9.43614C17.6923 9.34071 17.2058 9.26547 16.7302 9.14618C16.3726 9.05625 16.1729 8.7773 16.1275 8.41576C16.1148 8.30932 16.2092 8.1882 16.2527 8.07441C16.349 8.12213 16.4815 8.14415 16.5323 8.22307C16.7592 8.56442 17.1023 8.68738 17.4672 8.71307C18.7161 8.80299 19.9342 8.7094 21.0143 7.96614C21.5698 7.58441 21.9237 7.07422 22.0309 6.39519C22.0581 6.22819 22.0454 5.97676 22.2723 5.99511C22.5228 6.0153 22.4811 6.27407 22.4738 6.45575C22.4375 7.27059 22.0781 7.91659 21.4318 8.39558C20.6839 8.94798 19.818 9.18105 18.9212 9.31686C18.678 9.35356 18.4311 9.37191 18.186 9.3976C18.1824 9.41045 18.1788 9.4233 18.1751 9.43614Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M13.5007 25.6815C13.3555 25.8265 13.2919 25.9146 13.2066 25.9714C11.6328 27.034 11.2207 28.594 11.3732 30.3833C11.4258 31.0018 11.6128 31.589 11.9704 32.1066C11.9958 32.1433 12.0267 32.1818 12.0303 32.2222C12.0376 32.3158 12.0666 32.4498 12.0194 32.4956C11.9668 32.5489 11.8324 32.547 11.7435 32.5268C11.6491 32.5048 11.5493 32.4498 11.4821 32.38C11.3532 32.2442 11.2025 32.1047 11.139 31.9359C10.3294 29.785 10.5236 27.8599 12.1719 26.2816C12.4369 26.0265 12.7982 25.8705 13.1231 25.687C13.1939 25.6484 13.3028 25.6815 13.5007 25.6815Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.14146 16.4485C6.16688 16.2008 6.34659 16.1769 6.49 16.142C7.10902 15.9971 7.72985 15.8502 8.35613 15.7346C9.35274 15.5511 10.3548 15.3896 11.3532 15.2208C11.9523 15.1198 12.5531 15.0189 13.1558 14.9326C13.301 14.9106 13.5134 14.8482 13.5588 15.0629C13.6042 15.2721 13.3936 15.3107 13.252 15.3676C12.2717 15.7493 11.2497 15.9493 10.2132 16.0907C9.1948 16.2301 8.1746 16.3623 7.1544 16.4889C6.91115 16.5183 6.66246 16.5201 6.41739 16.5201C6.32481 16.5201 6.23404 16.4742 6.14146 16.4485Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M9.32191 17.7386C9.19666 17.8744 9.09318 17.9882 8.98971 18.102C8.30171 18.86 8.08932 19.7207 8.44331 20.7007C8.75554 21.5651 9.44898 22.0386 10.353 21.9908C10.6398 21.9762 10.923 21.8936 11.2062 21.8404C11.3206 21.8183 11.4349 21.7614 11.5438 21.7706C11.6419 21.7798 11.7363 21.8587 11.8307 21.9064C11.7835 22 11.7581 22.1523 11.6854 22.1817C10.805 22.5359 9.90281 22.7708 9.0006 22.2808C8.1456 21.8147 7.77527 21.0274 7.71355 20.0767C7.66817 19.3591 7.88238 18.715 8.32713 18.1552C8.45238 17.9974 8.60668 17.8561 8.76825 17.7368C8.90621 17.6359 9.0714 17.5515 9.32191 17.7386Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M17.1785 33.0553C17.0987 33.2242 17.0823 33.3233 17.0242 33.3673C16.7719 33.56 16.5323 33.8041 16.2437 33.9069C15.3705 34.2152 14.4647 34.329 13.5425 34.1418C13.3755 34.1088 13.2121 34.0335 13.0578 33.9546C12.9344 33.8922 12.84 33.7637 12.9198 33.6298C12.967 33.5509 13.0959 33.5086 13.1976 33.4829C13.2775 33.4628 13.3719 33.4848 13.4554 33.505C14.5464 33.7509 15.5883 33.5233 16.6194 33.1783C16.7719 33.1287 16.9335 33.1086 17.1785 33.0553Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M12.9543 21.3632C12.731 21.2366 12.7728 21.0678 12.8036 20.9118C12.8345 20.7539 12.8889 20.6016 12.9343 20.4475C13.1503 19.6969 13.0378 18.9958 12.6167 18.3461C12.4587 18.1021 12.2681 17.88 12.0993 17.6414C12.0394 17.557 11.9994 17.4561 11.9504 17.3625C11.9722 17.3331 11.994 17.3056 12.0158 17.2762C12.1301 17.3074 12.2572 17.3166 12.3571 17.3753C13.6114 18.1039 14.0798 19.8418 13.1921 21.1595C13.134 21.2476 13.0269 21.3027 12.9543 21.3632Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.3648 32.8902C22.0217 32.7434 21.9382 32.6149 21.9582 32.347C21.9963 31.8111 22.4465 31.3541 22.973 31.3174C23.5212 31.2789 24.1075 31.712 24.191 32.2314C24.2037 32.3158 24.1438 32.4112 24.1166 32.5011C24.0313 32.4681 23.9278 32.4553 23.8679 32.3947C23.7771 32.3048 23.7227 32.1781 23.6464 32.0717C23.4849 31.8515 23.2997 31.6735 22.9966 31.7359C22.7043 31.7964 22.4719 32.0533 22.4193 32.3763C22.3921 32.5305 22.3848 32.6883 22.3648 32.8902Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M3.48572 26.8248C3.43308 26.678 3.38406 26.5807 3.36591 26.478C3.27877 26.0063 3.1989 25.531 3.1154 25.0575C3.09543 24.9419 3.0446 24.8263 3.05368 24.7143C3.06094 24.6281 3.12266 24.5216 3.19346 24.4757C3.23339 24.4501 3.35683 24.5069 3.41311 24.5583C3.83244 24.9346 4.01034 26.1311 3.71989 26.6193C3.68177 26.6872 3.60008 26.7276 3.48572 26.8248Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M46.9114 26.0412C46.8242 25.9347 46.7262 25.8338 46.65 25.7182C46.4267 25.3786 46.2107 25.0336 45.9928 24.6904C45.9692 24.6537 45.9257 24.6207 45.9202 24.584C45.9075 24.4775 45.8658 24.3344 45.9166 24.272C45.9674 24.2096 46.1344 24.1839 46.2161 24.2206C46.3704 24.2904 46.5211 24.395 46.6354 24.5198C46.9168 24.8299 47.0602 25.2153 47.1238 25.6246C47.1437 25.7494 47.0766 25.887 47.0493 26.0191C47.0021 26.0246 46.9568 26.032 46.9114 26.0412Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M16.4797 7.11642C16.5705 6.98612 16.6304 6.85949 16.7266 6.7659C17.1768 6.32912 17.7177 6.05567 18.3204 5.90335C18.3767 5.88866 18.4384 5.86481 18.491 5.87765C18.5691 5.89784 18.7016 5.94739 18.7016 5.98226C18.6998 6.06668 18.6472 6.16211 18.5909 6.23001C18.5473 6.2814 18.4638 6.29608 18.4003 6.33095C17.9519 6.57136 17.5017 6.80811 17.057 7.05403C16.8101 7.19167 16.8137 7.19901 16.4797 7.11642Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M46.5193 13.1157C46.5575 12.6404 47.0476 12.0164 47.4397 11.91C47.5359 11.8843 47.7065 11.899 47.7465 11.9595C47.8046 12.0458 47.8082 12.2055 47.7701 12.3101C47.7301 12.4257 47.623 12.5211 47.5323 12.6147C47.3308 12.8203 47.1275 13.0276 46.9096 13.2148C46.8352 13.2791 46.7063 13.3249 46.6174 13.3066C46.5629 13.2956 46.5339 13.1469 46.5193 13.1157Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M35.7 31.2734C35.858 31.323 36.0268 31.3578 36.1811 31.4294C36.3245 31.4955 36.4752 31.5964 36.437 31.7909C36.3989 31.9873 36.2247 32.0277 36.0649 32.0167C35.6928 31.991 35.3188 31.9506 34.9503 31.89C34.8596 31.8754 34.7833 31.7597 34.7016 31.69C34.776 31.6111 34.8378 31.4936 34.9267 31.4624C35.17 31.3798 35.4277 31.3358 35.7 31.2734Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.1042 24.2849C33.0043 24.1436 32.9099 24.05 32.8664 23.938C32.7175 23.5563 32.5832 23.1691 32.4525 22.78C32.4253 22.7011 32.4125 22.6001 32.438 22.5249C32.4833 22.3781 32.5959 22.3157 32.7447 22.3909C32.7956 22.4166 32.8446 22.457 32.8773 22.5029C33.2222 22.9911 33.3311 23.5379 33.2476 24.127C33.2403 24.1619 33.1913 24.1894 33.1042 24.2849Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M23.0202 33.4628C22.953 33.4408 22.786 33.3985 22.6299 33.3306C22.5809 33.3086 22.5337 33.2113 22.5391 33.1545C22.5445 33.0976 22.6117 33.0205 22.6662 33.004C22.9802 32.9067 23.2961 32.8131 23.6174 32.7397C23.8134 32.6956 23.9115 32.8315 23.8534 33.0297C23.7735 33.2976 23.4958 33.4628 23.0202 33.4628Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M29.1868 4.01673C29.1451 4.24613 29.0107 4.34524 28.8328 4.27733C28.6114 4.19475 28.359 3.70842 28.4153 3.47718C28.4553 3.31568 28.6386 3.22759 28.7403 3.34871C28.9127 3.55242 29.0416 3.79284 29.1868 4.01673Z\"\n      fill=\"#EE9D5B\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 50 / 38,\n  svg: Cheese,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/chili.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Chili', 'sticker name', 'web-stories');\n\nconst Chili = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 46 50\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M44.5286 44.2458C44.2901 44.3017 44.1207 44.3313 43.9595 44.3823C41.0203 45.335 38.0351 45.4683 35.0022 44.927C31.2949 44.2639 27.9182 42.7879 24.7422 40.8102C23.2027 39.8525 21.7405 38.7814 20.3885 37.572C19.8145 37.0586 19.2914 36.4827 18.7997 35.8871C17.5266 34.3453 16.0397 33.0356 14.4953 31.7785C11.5413 29.3713 9.97223 26.2499 9.75184 22.4425C9.73374 22.1364 9.67618 21.8304 9.61532 21.5276C9.45578 20.7247 8.97386 20.1586 8.22221 19.8855C7.60378 19.6617 6.95246 19.5202 6.30607 19.3919C5.82415 19.2948 5.61527 19.4511 5.45902 19.9052C5.41625 20.0303 5.4031 20.1652 5.35704 20.2886C5.27645 20.5108 5.11691 20.6078 4.88829 20.5075C4.32249 20.259 3.74847 20.0237 3.20734 19.7308C3.0182 19.6288 2.83727 19.3902 2.783 19.1813C2.232 17.0439 1.61686 14.9131 1.41127 12.7066C1.34877 12.0418 1.42114 11.3228 1.61851 10.686C2.09384 9.14757 2.66622 7.63708 3.22708 6.12495C3.67116 4.9271 4.43104 3.97605 5.53961 3.31624C5.86198 3.12373 6.1712 2.90818 6.47054 2.68441C7.14818 2.17927 7.62681 1.55237 7.74523 0.673719C7.84063 -0.0403883 8.13833 -0.158858 8.78307 0.186678C9.38177 0.505887 9.79295 1.00938 9.97388 1.63464C10.1877 2.37178 10.3193 3.13689 10.4213 3.89872C10.4854 4.37753 10.2897 4.54207 9.81105 4.54043C9.54789 4.53878 9.28473 4.49765 9.01992 4.47132C8.51333 4.42196 8.03306 4.51904 7.66628 4.87609C7.0347 5.49147 6.40311 6.11344 5.83238 6.78476C4.83894 7.95465 4.48861 9.37957 4.54124 10.8654C4.62184 13.2282 5.15145 15.4988 6.19422 17.6395C6.43765 18.1397 6.73535 18.4375 7.30444 18.528C7.79951 18.607 8.28965 18.7798 8.75182 18.9822C9.88177 19.4758 10.4788 20.3627 10.6022 21.5967C10.691 22.4968 10.7749 23.4034 10.9657 24.2853C11.5644 27.0397 12.9525 29.3449 15.1878 31.0595C16.9016 32.3725 18.4115 33.8649 19.7651 35.535C20.7734 36.7789 22.0168 37.7777 23.3046 38.7123C26.1303 40.7641 29.2044 42.3437 32.5301 43.4132C34.5811 44.073 36.6946 44.4169 38.8493 44.3856C40.8016 44.356 42.7144 44.0335 44.5483 43.3276C44.6306 43.2964 44.7112 43.2585 44.7951 43.2338C45.3296 43.0726 45.5681 43.2569 45.4859 43.8097C45.2918 45.1244 44.6141 46.1544 43.5648 46.9475C42.7473 47.5645 41.8411 48.022 40.8822 48.3708C38.3986 49.2758 35.8311 49.8253 33.1979 49.9784C31.132 50.0985 29.1041 49.7052 27.1271 49.1277C24.155 48.2606 21.2536 47.1976 18.5299 45.7036C15.0496 43.7949 11.788 41.5769 9.01663 38.7057C7.4426 37.0734 6.2337 35.1697 5.09388 33.2215C3.90143 31.1812 2.70405 29.1442 1.53627 27.0907C1.22212 26.5379 0.968827 25.9406 0.751719 25.3417C0.263226 23.9842 0.47869 22.7156 1.41456 21.6165C1.84055 21.1163 2.36358 20.6967 2.85043 20.2491C2.94418 20.1619 3.06754 20.0846 3.1909 20.0583C3.27642 20.0402 3.40471 20.0928 3.47215 20.157C3.51327 20.1965 3.51162 20.3462 3.46886 20.3956C3.31425 20.5799 3.13333 20.7411 2.96556 20.9155C2.60043 21.2956 2.20404 21.6543 1.87838 22.0673C1.24844 22.867 1.06587 23.7769 1.4014 24.751C1.5741 25.2495 1.76325 25.753 2.02312 26.2088C3.60702 28.9912 5.20079 31.7686 6.81759 34.5346C7.97879 36.5206 9.53802 38.1791 11.2601 39.6765C13.2979 41.4469 15.5019 42.9953 17.8342 44.3576C19.7076 45.4518 21.6862 46.3256 23.7257 47.0561C24.951 47.4954 26.178 47.9315 27.4149 48.3379C30.2932 49.2824 33.2242 49.414 36.1634 48.7048C37.9183 48.2803 39.6519 47.7472 41.369 47.1845C42.0286 46.9689 42.647 46.5839 43.2292 46.1923C43.9858 45.6987 44.3608 45.0734 44.5286 44.2458ZM5.74849 18.7864C5.6531 18.5774 5.56428 18.3783 5.47382 18.1792C4.39815 15.8427 3.74518 13.4108 3.80768 10.816C3.8488 9.12947 4.26986 7.59266 5.46395 6.32898C6.33896 5.40262 7.14325 4.40386 8.30445 3.81809C8.1005 3.387 7.91629 2.99703 7.74688 2.64163C7.14489 3.03817 6.58074 3.46269 5.96889 3.80328C5.07908 4.29855 4.43927 5.01101 4.06755 5.93573C3.49189 7.36888 2.94418 8.8152 2.43595 10.2747C2.0593 11.359 2.03792 12.4779 2.28792 13.6083C2.69253 15.4413 3.06425 17.2808 3.46722 19.1138C3.49847 19.2586 3.62676 19.4445 3.75669 19.4955C4.12018 19.6403 4.5067 19.7259 4.91131 19.8427C5.02645 19.6551 5.11526 19.4774 5.23533 19.3244C5.37185 19.1516 5.53632 19.0052 5.74849 18.7864ZM9.67289 3.93985C9.82421 2.93615 9.57585 2.0427 9.06104 1.58034C8.73044 1.77121 8.40807 1.99827 8.50182 2.43595C8.64162 3.07766 9.04952 3.53673 9.67289 3.93985Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M16.9005 14.6371C16.8742 14.4264 16.8035 14.2455 16.838 14.0858C16.9959 13.3503 16.7146 12.7251 16.3298 12.1541C15.8857 11.496 15.3857 10.8773 14.8906 10.257C14.2064 9.39972 13.2755 8.98015 12.2179 8.80902C11.8264 8.74485 11.43 8.7103 11.0386 8.64613C10.4975 8.55892 10.254 8.33021 10.3017 7.97151C10.3593 7.53383 10.8708 7.14552 11.3034 7.26728C12.555 7.62104 13.8051 7.97809 15.0403 8.38122C15.7821 8.62309 16.4235 9.05913 16.9548 9.64654C17.9499 10.7473 19.213 11.1406 20.6571 11.0188C20.8907 10.9991 21.1341 10.9234 21.3413 10.8131C22.4713 10.2175 23.5848 10.2718 24.6999 10.8493C25.8266 11.4334 26.6638 12.3467 27.4253 13.3224C28.0766 14.155 28.6572 15.0468 29.251 15.9238C29.9467 16.9505 30.6934 17.9377 31.6359 18.7506C33.0816 19.9962 34.3152 21.4342 35.5093 22.9118C36.7708 24.475 38.062 26.0134 39.2889 27.6029C40.3087 28.9225 41.0784 30.3951 41.5159 32.0126C41.8317 33.1824 42.0867 34.3704 42.3169 35.5617C42.4584 36.2939 42.3054 37.0113 41.9798 37.6859C41.6936 38.2799 41.1952 38.632 40.6146 38.8772C40.2248 39.0417 39.9995 38.9233 39.983 38.4988C39.9567 37.839 39.9666 37.1726 40.0192 36.5144C40.1113 35.3692 39.8564 34.3342 38.9748 33.5757C38.2774 32.9751 37.5291 32.4058 36.7248 31.9632C33.9797 30.4511 31.2 29.0064 28.4368 27.5272C27.0371 26.7785 25.6358 26.0282 24.2526 25.2499C22.9664 24.5276 22.0305 23.4548 21.3101 22.1796C20.9844 21.6037 20.6473 21.0328 20.2969 20.4717C19.7311 19.5651 18.9367 18.9316 17.9745 18.4692C17.5074 18.2454 17.0436 17.9443 16.6883 17.5708C15.9186 16.7629 15.8544 15.5371 16.7492 14.8082C16.8002 14.767 16.8364 14.7111 16.9005 14.6371ZM40.6903 37.6168C40.7462 37.6382 40.8005 37.6612 40.8564 37.6826C41.2626 37.4737 41.5373 37.1462 41.5406 36.6674C41.5456 36.0734 41.5784 35.463 41.4534 34.8904C41.2051 33.7501 40.8745 32.6247 40.5439 31.5041C40.261 30.5432 39.7939 29.6596 39.1886 28.8649C37.5702 26.7423 35.9369 24.6296 34.2889 22.5301C33.3892 21.3832 32.4287 20.2841 31.279 19.3775C30.1688 18.5021 29.3447 17.3931 28.5898 16.2183C28.1128 15.4762 27.6523 14.716 27.1144 14.02C26.524 13.2549 25.8924 12.5095 25.1983 11.8399C24.8167 11.4713 24.297 11.1669 23.7871 11.027C22.2706 10.6107 20.8002 11.0402 20.2311 12.7564C20.1538 12.9867 20.0716 13.2154 19.9762 13.4392C19.6736 14.155 19.1785 14.6387 18.3874 14.795C18.1341 14.8444 17.8791 14.9546 17.6571 15.0895C16.8841 15.5651 16.7706 16.3351 17.4054 16.9752C17.6949 17.2664 18.0452 17.528 18.417 17.7008C19.7278 18.3096 20.7213 19.231 21.3825 20.5177C21.5239 20.7925 21.6835 21.0574 21.8348 21.3273C22.5141 22.54 23.3677 23.5979 24.5897 24.3005C25.8907 25.0459 27.1934 25.7913 28.5191 26.4922C30.8974 27.7493 33.3102 28.9455 35.6771 30.2224C36.8202 30.8394 37.9402 31.5189 38.9847 32.2873C40.5357 33.4276 41.2314 34.9694 40.7791 36.9241C40.7248 37.1479 40.7182 37.3848 40.6903 37.6168ZM20.0025 11.7049C19.9038 11.6605 19.8479 11.6144 19.7887 11.6112C18.486 11.5338 17.4433 10.9217 16.5288 10.0365C15.8857 9.41453 15.1373 8.96369 14.2903 8.66916C13.3133 8.33021 12.3412 7.96987 11.3659 7.62433C11.3133 7.60623 11.2442 7.63256 11.1619 7.64079C11.1159 7.98797 11.3231 8.14263 11.5863 8.22161C11.8807 8.30882 12.185 8.37464 12.4893 8.41248C13.6126 8.55563 14.537 9.05584 15.2738 9.91309C15.4745 10.1467 15.7097 10.3524 15.9054 10.5894C16.7804 11.6457 17.7196 12.6757 17.4564 14.2076C18.3693 14.3524 18.7903 14.1615 19.1752 13.4195C19.4581 12.8732 19.7114 12.3121 20.0025 11.7049Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M10.2228 31.3429C9.71291 31.3248 9.28363 31.1685 8.99251 30.8295C8.62408 30.4017 8.26882 29.9344 8.02704 29.4293C7.35926 28.0389 6.71287 26.6354 6.34774 25.1233C6.28853 24.8797 6.10431 24.6609 5.95958 24.4421C5.66845 24.006 5.33292 23.5947 5.07963 23.1389C4.9645 22.9316 4.92667 22.6255 4.97601 22.3902C5.24246 21.0838 6.81814 20.5573 7.90532 21.3915C8.34283 21.7271 8.6356 22.1747 8.73757 22.7062C8.86093 23.3528 8.93659 24.011 8.9958 24.6675C9.04679 25.2368 9.03034 25.8127 9.06652 26.3853C9.15041 27.7345 9.92509 28.7645 10.6735 29.8061C10.7244 29.8768 10.7837 29.9427 10.8412 30.0101C11.0468 30.252 11.2393 30.5037 11.0567 30.841C10.8659 31.1833 10.5452 31.31 10.2228 31.3429Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M20.889 40.7695C20.7328 40.7053 20.4679 40.6395 20.2508 40.5012C19.6768 40.1327 19.0781 39.7822 18.5699 39.333C17.264 38.1812 15.9843 36.9982 14.7277 35.7904C14.3198 35.3972 14.0106 34.9003 13.6685 34.4412C13.5632 34.3014 13.4942 34.1352 13.4136 33.9789C13.2738 33.7074 13.1948 33.4309 13.4744 33.2006C13.7179 33.0015 13.9728 33.064 14.2047 33.2318C14.6521 33.5543 15.1307 33.8439 15.5287 34.2191C17.0584 35.6555 18.6604 37.0015 20.3331 38.2651C20.8051 38.6205 21.2032 39.0763 21.6259 39.4959C21.8578 39.7263 22.0042 39.9912 21.8265 40.3268C21.69 40.5802 21.3068 40.7843 20.889 40.7695Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M35.0192 46.8279C34.7708 47.1849 34.4731 47.1257 34.2034 47.0582C33.2626 46.8262 32.3086 46.6288 31.3941 46.3161C29.0043 45.5033 26.7756 44.3466 24.6374 43.0138C24.5174 42.9381 24.4187 42.8279 24.3447 42.6271C24.4779 42.6337 24.621 42.609 24.7411 42.6518C27.8908 43.7839 31.1194 44.7119 34.1195 46.2339C34.3547 46.354 34.5899 46.4757 34.8169 46.609C34.8859 46.6534 34.9336 46.7341 35.0192 46.8279Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.0372 47.9631C32.8628 48.4205 32.5766 48.4304 32.3217 48.4205C31.5733 48.3926 30.8085 48.4222 30.0848 48.2675C28.2526 47.8759 26.4269 47.4366 24.6242 46.9282C23.9384 46.7357 23.3134 46.3128 22.6785 45.9656C22.4893 45.8619 22.3594 45.653 22.2015 45.4917C22.236 45.4391 22.2689 45.3881 22.3035 45.3354C22.7114 45.4687 23.1242 45.5921 23.5288 45.7402C25.2937 46.3835 27.0799 46.9545 28.9368 47.2589C30.047 47.4399 31.1638 47.5715 32.2757 47.7393C32.5207 47.7772 32.7576 47.8792 33.0372 47.9631Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M12.4597 39.5403C12.7623 39.644 13.0863 39.7082 13.3626 39.8595C14.6785 40.5769 15.9926 41.2943 17.2821 42.0562C18.0782 42.5267 18.8298 43.0697 19.5946 43.5913C19.8019 43.7328 20.0897 43.8727 19.9219 44.2133C19.8117 44.4371 19.5831 44.4124 19.19 44.1162C17.7245 43.0121 16.1637 42.066 14.5271 41.2368C13.94 40.9389 13.389 40.5654 12.8363 40.2051C12.6472 40.0817 12.5008 39.8941 12.3347 39.7361C12.3758 39.672 12.4169 39.6061 12.4597 39.5403Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M8.82971 34.1467C8.93497 34.3228 9.0682 34.489 9.14386 34.6782C9.5386 35.6835 10.1356 36.5326 11.0172 37.1693C11.088 37.2204 11.1735 37.273 11.2064 37.347C11.2475 37.4375 11.2804 37.5708 11.2409 37.6449C11.1998 37.7222 11.0616 37.8045 10.9794 37.7913C10.8116 37.7666 10.6357 37.7074 10.4942 37.6153C9.44649 36.9242 8.85109 35.932 8.62082 34.7111C8.58957 34.5433 8.64714 34.3573 8.66194 34.1796C8.71786 34.1698 8.77378 34.1582 8.82971 34.1467Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.85753 29.0986C5.78516 30.0612 6.10589 30.8674 6.73254 31.5832C6.97268 31.8579 7.12893 32.2166 7.28354 32.5556C7.39045 32.7892 7.35591 32.8139 6.97761 33.1266C6.94307 33.0558 6.90853 32.9735 6.86248 32.8962C6.54998 32.3664 6.24899 31.8283 5.91675 31.31C5.53845 30.7193 5.41509 30.0941 5.57299 29.4145C5.60095 29.296 5.67332 29.1874 5.72431 29.0739C5.76872 29.0821 5.81313 29.0904 5.85753 29.0986Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M3.34261 22.67C2.73076 23.3792 2.73405 23.3775 2.76201 24.424C2.76858 24.6725 2.84095 24.9571 2.48404 25.1365C2.39522 25.0131 2.28009 24.911 2.23239 24.7827C1.98897 24.1229 2.04983 23.4779 2.41496 22.8823C2.68306 22.4479 2.98405 22.3952 3.34261 22.67Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M3.38869 25.7468C3.73738 26.6189 4.06468 27.435 4.41173 28.3021C3.9183 28.3647 3.74231 28.0356 3.56468 27.7575C3.16007 27.1306 3.09592 26.3457 3.38869 25.7468Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M23.5419 15.5503C22.4514 15.7099 21.8873 15.0403 22.2557 14.0645C22.3906 13.7091 22.6307 13.3504 22.9169 13.1036C23.6867 12.4405 24.5682 12.6018 25.0995 13.4673C25.3281 13.8424 25.4745 14.2686 25.7081 14.6404C25.9153 14.9695 26.1719 15.2723 26.44 15.5569C26.6341 15.7626 26.8841 15.9173 27.1061 16.0983C27.6456 16.5409 28.0716 17.0674 28.2624 17.7519C28.5305 18.7194 29.1176 19.417 29.9844 19.914C30.3825 20.1427 30.7805 20.4059 31.0963 20.7334C31.3775 21.0246 31.593 21.403 31.7509 21.7815C31.9121 22.1665 31.7493 22.5499 31.4269 22.772C31.1094 22.9909 30.7723 23.0304 30.4351 22.8214C29.6111 22.313 28.7871 21.8012 27.968 21.2846C27.2837 20.8535 26.8495 20.2216 26.611 19.4664C26.3693 18.7013 25.935 18.0991 25.31 17.6022C24.6028 17.0378 23.9087 16.452 23.5419 15.5503Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.3644 22.4412C24.5815 22.5416 24.6686 22.5629 24.7328 22.614C26.922 24.3301 29.4138 25.4984 31.9237 26.6469C33.3645 27.3067 34.7855 28.0158 36.1869 28.7546C37.0093 29.1874 37.7083 29.8093 38.3053 30.5284C38.4599 30.7143 38.7872 30.9595 38.5422 31.1931C38.228 31.4942 38.0537 31.0779 37.876 30.8969C36.8744 29.8817 35.7346 29.0508 34.4566 28.4354C32.8085 27.6423 31.126 26.9249 29.468 26.1532C28.4499 25.6794 27.4351 25.1972 26.4516 24.6559C25.7147 24.2511 25.0782 23.6966 24.5963 22.9908C24.5107 22.8641 24.4729 22.7061 24.3644 22.4412Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.7905 28.1755C36.3168 27.9386 35.8546 27.7954 35.5026 27.5157C34.6918 26.8724 33.9171 26.1813 33.1654 25.4688C32.9039 25.2204 32.7263 24.8633 32.5717 24.526C32.5042 24.3796 32.5404 24.1229 32.6342 23.9913C32.6934 23.9106 32.9714 23.9205 33.1128 23.9814C33.3727 24.0916 33.6227 24.2446 33.8431 24.4224C34.7543 25.1529 35.6556 25.8966 36.5536 26.6437C36.774 26.8263 36.978 27.0287 37.1786 27.2344C37.3316 27.3907 37.5372 27.5848 37.3661 27.802C37.2362 27.9699 36.9944 28.0505 36.7905 28.1755Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M17.9334 16.6099C18.5157 17.3602 19.3594 17.6465 20.1966 17.8901C21.5009 18.2685 22.366 19.0929 22.917 20.2989C23.1045 20.7086 23.3035 21.1118 23.5289 21.5807C23.1193 21.6103 22.9927 21.3948 22.8792 21.199C22.6835 20.8551 22.5075 20.4997 22.3348 20.1426C21.8858 19.2228 21.1719 18.6239 20.2098 18.2833C19.6111 18.0711 19.0255 17.8111 18.4564 17.5314C18.1143 17.3635 17.8627 17.0855 17.9334 16.6099Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.3593 11.9353C23.6488 12.3022 23.0304 12.5375 22.5123 12.911C22.0123 13.2714 21.6159 13.7732 21.1356 14.2504C21.2195 12.8863 22.958 11.5766 24.3593 11.9353Z\"\n      fill=\"#EE9D5B\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 46 / 50,\n  svg: Chili,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as nycTomatoes } from './tomatoes';\nimport { default as nycChili } from './chili';\nimport { default as nycOnion } from './onion';\nimport { default as nycVeggies } from './veggies';\nimport { default as nycArrowRight } from './arrowRight';\nimport { default as nycCheese } from './cheese';\nimport { default as nycThickBrush } from './thickBrushStroke';\nimport { default as nycMediumBrush } from './mediumBrushStroke';\nimport { default as nycTiltedBrush } from './tiltedBrushStroke';\n\nexport {\n  nycTomatoes,\n  nycChili,\n  nycOnion,\n  nycVeggies,\n  nycArrowRight,\n  nycCheese,\n  nycThickBrush,\n  nycMediumBrush,\n  nycTiltedBrush,\n};\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/mediumBrushStroke.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Medium Brush Stroke', 'sticker name', 'web-stories');\n\nconst MediumBrush = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 56 28\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M54.7903 9.72995C54.6487 9.84752 54.5071 9.61237 54.3655 9.67116L54.3183 9.61237C54.3655 9.61237 54.3655 9.55358 54.4127 9.55358C54.5543 9.436 54.6487 9.61237 54.7903 9.61237C54.7431 9.49479 54.8375 9.436 54.9319 9.436C55.1207 9.436 55.2623 9.31842 55.3095 9.08326C55.3567 8.96568 55.0735 8.73052 54.8847 8.67173C54.8375 8.67173 54.7903 8.67173 54.7903 8.67173C54.7431 8.67173 54.7431 8.67173 54.6959 8.61295C54.6959 8.55416 54.7431 8.55416 54.7431 8.49537C54.8847 8.37779 55.0735 8.26021 55.2151 8.14263C55.2623 8.14263 55.3567 7.96626 55.2623 7.96626C55.0735 7.96626 54.9791 7.84868 54.8847 7.61352C54.7903 7.37837 54.5543 7.55474 54.4127 7.43716C54.0351 7.14321 53.6103 7.26079 53.2327 7.02563C53.1855 7.02563 53.0911 7.02563 53.0911 7.08442C53.0911 7.55474 52.9023 7.202 52.8551 7.14321C52.8079 7.08442 52.8551 6.96684 52.7135 6.96684C52.2414 7.02563 52.0054 6.6141 51.675 6.37895C51.4862 6.37895 51.4862 6.26137 51.5806 6.14379C51.6278 6.085 51.675 6.02621 51.6278 5.96742C51.5806 5.90863 51.5334 5.90863 51.4862 5.96742C51.3446 6.02621 51.203 6.02621 51.0614 5.84984C51.1558 5.73226 51.2502 5.61468 51.3918 5.55589C51.7222 5.32074 51.7694 4.968 51.4862 4.73284C51.3446 4.61526 51.203 4.43889 51.0614 4.3801C50.8726 4.26253 50.8254 4.14495 51.0614 3.96858C51.1558 3.90979 51.203 3.73342 51.0614 3.61584C50.967 3.55705 51.0142 3.2631 50.7782 3.38068C50.731 3.38068 50.731 3.32189 50.731 3.32189C50.8726 3.2631 51.0142 3.14553 51.0142 3.02795C51.0142 2.91037 50.7782 2.91037 50.731 2.67521C50.731 2.61642 50.731 2.55763 50.6838 2.44005C50.6838 2.32247 50.6366 2.32247 50.5422 2.26368C50.2118 2.1461 49.8342 2.02853 49.5038 1.79337C49.4094 1.73458 49.4094 1.79337 49.3622 1.85216C49.2206 1.96974 49.0318 1.96974 48.9374 2.1461C48.9846 2.20489 49.0318 2.32247 49.1734 2.38126C49.2206 2.38126 49.315 2.38126 49.3622 2.32247C49.4094 2.32247 49.4566 2.38126 49.2678 2.38126C49.4566 2.49884 49.4566 2.61642 49.4094 2.55763C49.315 2.49884 49.2206 2.49884 49.1734 2.44005C49.1734 2.44005 49.1262 2.44005 49.1262 2.38126C48.7486 2.44005 48.5126 2.38126 48.2766 2.26368C47.9461 2.1461 47.5685 1.96974 47.2381 1.96974C46.8605 1.96974 46.4829 1.79337 46.1053 1.73458C45.6333 1.67579 45.2085 1.67579 44.7365 1.617C44.3117 1.49942 43.7925 1.49942 43.2732 1.49942C42.8484 1.44063 42.4236 1.44063 41.9516 1.44063C41.6684 1.44063 41.4324 1.32305 41.1492 1.38184C40.866 1.44063 40.5828 1.26426 40.2524 1.38184C40.2052 1.44063 40.0636 1.49942 39.9692 1.44063C39.6388 1.32305 39.3084 1.32305 38.9307 1.38184C38.5531 1.49942 38.1755 1.32305 37.8451 1.49942C37.3259 1.67579 36.8067 1.44063 36.2875 1.67579C36.0043 1.49942 35.7211 1.73458 35.5323 1.67579C35.2491 1.55821 35.0131 1.79337 34.8243 1.67579C34.541 1.49942 34.3522 1.67579 34.1162 1.73458C33.9274 1.73458 33.7858 1.79337 33.597 1.85216C32.9362 1.85216 32.3226 1.85216 31.7562 2.02853C31.6146 2.02853 31.5202 1.79337 31.4258 1.96974C31.237 2.26368 30.9538 2.1461 30.7178 2.26368C30.529 2.32247 30.3402 2.08732 30.1514 2.20489C29.9153 2.32247 29.6793 2.32247 29.4433 2.38126H29.3961C29.1129 2.1461 28.7825 2.49884 28.4993 2.38126C28.1689 2.26368 27.8857 2.44005 27.6025 2.44005C27.5081 2.44005 27.4609 2.49884 27.3665 2.49884C27.3193 2.49884 27.2249 2.55763 27.1777 2.44005C27.1777 2.38126 27.2721 2.38126 27.3193 2.38126C27.6025 2.32247 27.8385 2.26368 28.1217 2.20489C28.2633 2.20489 28.3105 1.85216 28.4521 1.96974C28.6881 2.20489 28.9241 1.96974 29.1601 1.96974C29.7265 1.85216 30.293 1.73458 30.8122 1.617C30.9538 1.617 31.0482 1.55821 31.1898 1.617C31.473 1.85216 31.8034 1.73458 32.0866 1.617C32.2282 1.55821 32.3698 1.44063 32.5114 1.617C32.5586 1.67579 32.6058 1.67579 32.653 1.617C33.597 1.20547 33.6914 1.20547 34.2106 1.32305C34.4466 1.38184 34.6355 1.49942 34.8243 1.20547C34.8243 1.14668 34.9659 1.14668 34.9659 1.20547C35.1547 1.49942 35.3435 1.32305 35.5323 1.20547C35.7683 1.14668 36.0043 1.02911 36.1459 1.08789C36.6179 1.26426 36.9955 0.970316 37.4203 0.970316C37.4675 0.970316 37.4675 0.911526 37.5147 0.911526C37.4675 0.852737 37.4203 0.852737 37.3731 0.852737C37.3259 0.852737 37.2315 0.852737 37.2315 0.793947C36.9955 0.323632 36.5707 0.676368 36.2875 0.5C36.1459 0.852737 35.7683 0.5 35.5323 0.793947C35.4379 0.911526 35.2963 0.617579 35.1075 0.735158C35.0131 0.793947 34.8715 0.617579 34.7299 0.617579C34.5882 0.617579 34.541 0.970316 34.3522 0.735158C33.9746 0.852737 33.6442 0.676368 33.2666 0.793947C33.125 0.852737 33.125 1.08789 32.9834 1.02911C32.889 0.970316 32.7474 0.970316 32.653 0.911526C32.4642 0.852737 32.2282 0.852737 32.0394 0.911526C31.7562 0.970316 31.473 1.02911 31.1898 1.08789C31.0482 1.14668 30.8594 0.911526 30.8122 1.26426C30.8122 1.32305 30.7178 1.32305 30.6706 1.26426C30.4818 1.02911 30.293 1.14668 30.1042 1.20547C29.9153 1.26426 29.6793 1.02911 29.4905 1.20547C29.2545 1.44063 29.0185 1.32305 28.8297 1.26426C28.5465 1.20547 28.2633 1.26426 27.9801 1.32305C27.7441 1.44063 27.5081 1.14668 27.3193 1.44063C27.1305 1.14668 26.9417 1.617 26.7529 1.49942C26.6113 1.73458 26.4697 1.49942 26.3281 1.55821C26.1865 1.55821 25.9977 1.617 25.8561 1.617C25.5728 1.67579 25.3368 1.73458 25.1008 1.79337C25.0536 1.79337 24.9592 1.79337 24.9592 1.73458C24.9592 1.67579 25.0064 1.617 25.0064 1.55821C24.9592 1.44063 24.8176 1.49942 24.8176 1.55821C24.676 1.73458 24.5344 1.79337 24.3456 1.79337C24.204 1.79337 24.1096 1.96974 24.0152 2.02853C23.8736 2.1461 23.7792 1.79337 23.6376 2.08732C23.5904 2.20489 23.4016 1.91095 23.26 2.1461C23.2128 2.26368 22.9768 2.08732 22.8824 2.26368C22.4104 2.08732 21.9384 2.26368 21.5136 2.49884C21.4664 2.55763 21.4192 2.55763 21.372 2.49884C21.1831 2.26368 21.0415 2.49884 20.8999 2.49884C20.7111 2.55763 20.6167 2.96916 20.4279 2.67521C20.2391 2.91037 20.0031 2.85158 19.8143 2.79279C19.7199 3.14553 19.5311 2.79279 19.3895 2.96916C19.2951 3.08674 19.0591 3.08674 18.9175 3.14553C18.4455 3.20432 17.9735 3.32189 17.5015 3.38068C17.3599 3.43947 17.3599 3.55705 17.4543 3.67463C17.5015 3.61584 17.5959 3.67463 17.6431 3.61584C17.6903 3.55705 17.7847 3.61584 17.7847 3.67463C17.7847 3.79221 17.6903 3.73342 17.5015 3.73342C17.5487 3.79221 17.4543 3.73342 17.4543 3.73342C17.2655 3.67463 17.1711 3.55705 17.0295 3.61584C16.699 3.73342 16.3686 3.73342 16.0382 3.851C15.8022 3.96858 15.519 4.02737 15.3774 4.26253C15.4246 4.26253 15.4718 4.26253 15.5662 4.3801C15.6134 4.3801 15.6134 4.43889 15.5662 4.43889C15.6134 4.49768 15.6134 4.49768 15.6134 4.49768C15.5662 4.49768 15.5662 4.49768 15.519 4.43889V4.3801C15.4246 4.3801 15.3774 4.32131 15.3774 4.26253C15.1886 4.20374 14.9998 4.08616 14.8582 4.32131C14.811 4.43889 14.6694 4.43889 14.575 4.43889C14.3862 4.26253 14.1974 4.32131 14.0558 4.55647C14.0086 4.61526 13.9142 4.61526 13.867 4.55647C13.7726 4.43889 13.631 4.49768 13.5838 4.55647C13.395 4.85042 13.0646 4.61526 12.8758 4.79163C12.687 5.08558 12.4038 5.02679 12.1205 5.08558C11.9789 5.14437 11.7901 5.08558 11.6485 5.20316C11.4597 5.43831 11.2237 5.4971 10.9405 5.4971C10.6573 5.4971 10.4685 5.79105 10.1853 5.79105C9.71329 5.84984 9.28848 6.14379 8.86367 6.37895C8.72207 6.43774 8.62767 6.6141 8.43886 6.49652C8.34446 6.43774 8.10845 6.49653 8.06125 6.6141C7.91965 6.84926 7.73085 6.79047 7.58924 6.84926C7.40044 6.84926 7.30604 7.14321 7.07003 7.14321C6.73962 7.14321 6.50362 7.49595 6.17321 7.49595C5.93721 7.67231 5.654 7.67231 5.41799 7.96626C5.37079 7.96626 5.37079 8.02505 5.37079 8.08384C5.41799 8.08384 5.41799 8.14263 5.46519 8.14263C5.7012 8.14263 5.93721 8.14263 6.17321 8.26021C6.36201 7.96626 6.64522 8.14263 6.83403 7.96626C7.16443 7.61352 7.58924 7.55474 7.96685 7.31958C8.58047 7.02563 9.24128 6.84926 9.85489 6.6141C10.2797 6.43774 10.7045 6.43774 11.1293 6.20258C11.4125 6.02621 11.6957 6.085 11.9789 5.84984C12.2149 5.73226 12.5454 5.79105 12.8286 5.55589C12.9702 5.43831 13.2062 5.43831 13.395 5.43831C13.5838 5.37952 13.7726 5.43831 13.9142 5.20316C14.103 5.32074 14.2446 5.14437 14.3862 5.08558C14.575 5.02679 14.7638 5.02679 14.9526 4.968C15.0942 4.90921 15.283 4.968 15.3774 4.85042C15.519 4.61526 15.755 4.61526 15.8494 4.67405C16.0382 4.79163 16.1326 4.55647 16.2742 4.55647C16.463 4.55647 16.6518 4.55647 16.7934 4.43889C17.0767 4.20374 17.3599 4.20374 17.6431 4.14495C17.9735 4.08616 18.2567 3.90979 18.5871 4.08616C18.7287 4.14495 18.9647 4.08616 19.1063 3.96858C19.2479 3.79221 19.3895 3.73342 19.5311 3.67463C19.6727 3.61584 19.8143 3.67463 19.9087 3.49826C20.0503 3.20432 20.1447 3.67463 20.3335 3.49826C20.3807 3.43947 20.5695 3.49826 20.6167 3.43947C20.8527 3.08674 21.1831 3.2631 21.4664 3.2631C21.5136 3.2631 21.5136 3.32189 21.5608 3.32189C21.5608 3.38068 21.5136 3.38068 21.5136 3.43947C21.372 3.67463 21.2304 3.61584 21.0887 3.67463C20.3335 3.851 19.5783 3.96858 18.8231 4.14495C18.6815 4.20374 18.4927 4.14495 18.3983 4.32131L17.3599 4.61526C17.0295 4.61526 16.699 4.67405 16.4158 4.79163C16.2742 4.968 16.0382 4.90921 15.9438 5.08558C15.755 5.32074 15.6134 5.20316 15.4718 5.14437C15.283 5.08558 15.283 5.43831 15.0942 5.26195C14.9526 5.14437 14.811 5.26195 14.7166 5.43831C14.6694 5.4971 14.6222 5.43831 14.5278 5.4971C14.339 5.61468 14.103 5.4971 13.9614 5.73226C13.867 5.90863 13.631 5.61468 13.4422 5.84984C13.3478 5.96742 13.159 5.96742 13.0174 5.96742C12.8286 5.96742 12.7342 6.20258 12.5454 6.20258C12.3093 6.20258 12.0733 6.32016 11.8373 6.32016C11.6013 6.32016 11.4597 6.67289 11.2237 6.6141C11.0349 6.55531 10.8933 7.02563 10.6573 6.79047C10.4213 7.02563 10.0909 7.08442 9.80769 7.202C9.47728 7.31958 9.19408 7.43716 8.86367 7.55474C8.15566 7.7311 7.54204 8.20142 6.83403 8.43658C6.69242 8.49537 6.59802 8.67173 6.40922 8.67173C6.36201 8.67173 6.26761 8.73053 6.31481 8.78931C6.31481 8.8481 6.40922 8.90689 6.45642 8.90689C6.55082 8.96568 6.73962 8.96568 6.83403 8.78931C7.11723 8.43658 7.49484 8.37779 7.82525 8.20142C8.20286 8.02505 8.53326 7.78989 8.95807 7.78989C9.33568 7.37837 9.90209 7.61352 10.2797 7.202C10.9405 7.202 11.4597 6.73168 12.1205 6.67289C12.2149 6.67289 12.3565 6.67289 12.4038 6.6141C12.5926 6.37895 12.8758 6.37895 13.1118 6.32016C13.395 6.32016 13.5366 6.085 13.7726 6.02621C14.0558 5.96742 14.4334 6.02621 14.7638 5.79105C15.047 5.55589 15.4718 5.67347 15.8022 5.37952C15.9438 5.26195 16.1326 5.32074 16.3214 5.26195C16.5102 5.20316 16.7462 5.26195 16.8879 5.14437C17.0295 4.968 17.2183 5.14437 17.2655 5.02679C17.4071 4.79163 17.5959 4.85042 17.7847 4.79163C18.2095 4.67405 18.6815 4.61526 19.1063 4.49768C19.8143 4.32132 20.5223 4.32131 21.1831 3.90979C21.2776 3.851 21.4192 3.79221 21.4664 3.851C21.7496 4.02737 21.9856 3.851 22.2688 3.79221C22.9768 3.73342 23.732 3.55705 24.44 3.38068C24.6288 3.32189 24.8648 3.49826 25.0064 3.38068C25.2896 3.14553 25.6201 3.20432 25.9033 3.08674C26.0449 3.2631 26.1865 3.14553 26.3281 3.14553C26.5641 3.20432 26.6585 2.85158 26.8945 2.96916C27.0833 3.08674 27.2721 2.91037 27.5081 2.91037C27.6497 2.91037 27.7913 2.85158 27.9329 2.96916C28.1217 2.61642 28.4521 2.734 28.7353 2.67521C29.0185 2.61642 29.2545 2.44005 29.5377 2.61642C30.0569 2.44005 30.5762 2.55763 31.0482 2.44005C31.2842 2.38126 31.5202 2.20489 31.7562 2.38126C31.9922 2.1461 32.2282 2.20489 32.4642 2.26368C32.6058 2.26368 32.7946 2.20489 32.9834 2.1461C33.125 2.1461 33.2666 2.08732 33.4082 2.1461C33.597 2.26368 33.833 2.26368 33.9274 2.02853C34.069 2.20489 34.2578 2.08732 34.3994 2.08732C34.9659 1.91095 35.5795 2.08732 36.1459 1.85216C36.1931 1.85216 36.2403 1.85216 36.2403 1.85216C36.9011 2.1461 37.5147 1.85216 38.1755 1.85216C38.6475 1.85216 39.1196 1.91095 39.5916 1.73458H39.6388C40.2524 1.96974 40.866 1.73458 41.5268 1.73458C41.8572 1.73458 42.1404 1.67579 42.4708 1.79337C42.5652 1.85216 42.6124 1.79337 42.7068 1.79337C42.99 1.67579 43.2732 1.79337 43.5564 1.85216C43.8397 1.85216 44.1701 1.73458 44.4061 1.96974C44.4533 2.02853 44.5005 1.96974 44.5477 1.96974C44.8309 1.85216 45.1141 2.02853 45.3501 2.02853C45.5389 2.02853 45.7277 2.1461 45.8693 2.08732C46.1525 1.96974 46.4829 2.08732 46.7661 2.08732C47.0493 2.08732 47.3325 2.38126 47.6629 2.44005C47.7101 2.44005 47.7573 2.49884 47.7573 2.55763C47.7573 2.61642 47.6629 2.67521 47.6157 2.61642C47.3797 2.44005 47.2381 2.44005 47.1909 2.79279C47.1437 2.96916 46.9077 3.02795 46.7661 2.91037C46.3413 2.67521 46.3413 2.61642 46.1053 2.67521C45.9165 2.734 45.7749 2.61642 45.5861 2.61642C45.4917 2.32247 45.2557 2.38126 45.0669 2.44005C44.6893 2.55763 44.3117 2.38126 43.9341 2.55763C43.9341 2.55763 43.8869 2.49884 43.8397 2.49884C43.6981 2.44005 43.5092 2.38126 43.3676 2.44005C42.99 2.49884 42.6596 2.32247 42.3292 2.44005C42.046 2.20489 41.6684 2.61642 41.338 2.38126C40.63 2.44005 39.922 2.32247 39.2612 2.49884C39.214 2.49884 39.1196 2.55763 39.0723 2.55763C38.8835 2.38126 38.6947 2.49884 38.5059 2.55763C38.3171 2.61642 38.1755 2.44005 37.9395 2.49884C37.6563 2.55763 37.4203 2.55763 37.0899 2.55763C36.8067 2.55763 36.5235 2.44005 36.2403 2.55763C36.0043 2.61642 35.6739 2.61642 35.3907 2.61642C35.0131 2.61642 34.6355 2.734 34.2106 2.734C33.833 2.67521 33.4554 2.91037 33.0778 2.79279C33.0306 2.79279 32.9834 2.79279 32.9834 2.79279C32.6058 3.08674 32.2282 3.14553 31.8034 3.02795C31.0954 3.2631 30.3874 3.14553 29.7265 3.32189C29.4905 3.38068 29.2545 3.43947 29.0185 3.38068C28.6409 3.32189 28.2633 3.55705 27.9329 3.43947C27.7441 3.61584 27.5553 3.49826 27.3665 3.55705C26.8473 3.61584 26.2809 3.79221 25.7617 3.73342C25.62 3.73342 25.384 3.73342 25.2896 3.90979C25.148 4.02737 24.912 3.67463 24.8648 4.02737C24.8648 4.08616 24.7232 4.14495 24.676 4.08616C24.44 3.90979 24.204 4.08616 23.968 4.08616C23.0712 4.26253 22.2216 4.43889 21.372 4.61526C21.2304 4.67405 20.9943 4.61526 20.8999 4.67405C20.6639 4.85042 20.4279 4.79163 20.1919 4.90921C19.9087 4.968 19.6727 5.02679 19.4367 5.02679C19.2007 5.08558 19.0119 5.32074 18.7759 5.20316C18.5399 5.08558 18.3511 5.43831 18.1623 5.43831C17.2183 5.55589 16.3686 6.02621 15.4718 6.14379C15.3302 6.14379 15.1886 6.14379 15.0942 6.26137C14.7166 6.55531 14.2918 6.43774 13.9614 6.67289C13.5838 6.96684 13.2062 6.90805 12.8286 7.02563C12.7342 7.08442 12.5926 7.02563 12.4982 7.08442C12.1205 7.43716 11.6957 7.43716 11.2709 7.61352C11.0349 7.7311 10.7517 7.7311 10.4685 7.96626C10.1853 8.14263 9.85489 8.319 9.47728 8.319C9.38288 8.319 9.28848 8.319 9.24128 8.37779C9.05247 8.73052 8.58046 8.49537 8.39166 8.8481C8.06125 8.8481 7.77805 9.14205 7.44764 9.20084C7.02283 9.31842 6.64522 9.61237 6.22041 9.84752C6.03161 10.0239 5.89 10.3178 5.5596 10.3178C5.46519 10.6706 5.08759 10.3766 4.94598 10.7294C4.66278 10.4942 4.52117 10.9645 4.23797 10.9057C4.09636 10.9057 3.86036 10.8469 3.76596 11.1409C3.48275 11.0821 3.29395 11.3761 3.01074 11.4348C2.63313 11.4936 2.30272 11.7288 1.97232 11.9639C1.78351 12.0227 1.64191 12.0815 1.64191 12.3755C1.4059 12.5518 1.3587 13.0222 1.02829 13.0222C0.886692 13.3161 0.556284 13.1985 0.36748 13.4925C0.273078 13.6101 0.0842735 13.7864 0.131475 13.904C0.178676 14.0216 0.36748 13.904 0.509083 13.904C0.603485 13.904 0.697887 13.8452 0.792289 13.8452C0.886692 13.8452 0.886692 13.8452 0.933893 13.9628C0.981094 14.1392 1.0755 14.1392 1.1699 13.9628C1.2643 13.8452 1.3587 13.7864 1.50031 13.904C1.54751 13.9628 1.64191 13.9628 1.59471 13.904C1.59471 13.7864 1.59471 13.6688 1.73631 13.6688C1.92511 13.7276 1.68911 13.8452 1.73631 13.904C1.78351 13.9628 1.87791 13.904 1.92511 13.8452C1.92511 13.7864 1.97232 13.7864 1.97232 13.8452C2.06672 13.7276 2.06672 13.7276 2.06672 13.7864C2.06672 13.8452 2.06672 13.8452 2.01952 13.904C2.01952 14.1979 1.97232 14.4919 2.20832 14.4919C2.49153 14.5507 2.63313 14.8446 2.77473 15.0798C2.91634 15.3149 2.91634 15.4913 2.77473 15.6089C2.72753 15.6677 2.68033 15.6089 2.63313 15.6677C2.44433 15.7853 2.25552 15.9616 2.16112 16.1968C2.11392 16.2556 2.11392 16.3144 2.16112 16.3732C2.20832 16.4907 2.30272 16.4907 2.34992 16.4319C2.63313 16.1968 3.01074 16.138 3.29395 15.9028C3.48275 15.7265 3.57715 15.9028 3.71876 15.9028C3.71876 15.9028 3.76596 15.9616 3.76596 16.0204C3.67155 16.2556 3.57715 16.3732 3.38835 16.3732C3.05794 16.3144 2.82193 16.6671 2.53873 16.7259C2.44433 16.7259 2.39713 16.7847 2.34992 16.9023C2.30272 16.961 2.25552 17.0198 2.30272 17.1374C2.30272 17.1962 2.39713 17.1962 2.44433 17.1962C2.68033 17.1374 2.86914 16.961 3.05794 16.8435C3.15234 16.7259 3.19954 16.7847 3.29395 16.8435C3.67155 17.0786 3.67155 17.0198 3.90756 17.0198C4.33237 17.0198 4.66278 16.6083 5.08759 16.6083C5.13479 16.6083 5.18199 16.4907 5.18199 16.4907C5.5596 16.2556 5.9372 16.0792 6.26761 15.9028C6.36201 15.844 6.45642 15.7853 6.50362 15.9616C6.59802 16.138 6.45642 16.138 6.40922 16.1968C5.93721 16.5495 5.93721 16.6083 5.37079 16.6671C4.99318 16.7259 4.70998 16.9611 4.42677 17.1962C4.37957 17.1962 4.37957 17.255 4.33237 17.3138C4.37957 17.3138 4.42677 17.3138 4.42677 17.3138C4.52117 17.3138 4.56837 17.255 4.66278 17.255C4.85158 17.1962 4.85158 17.255 4.75718 17.5489C4.70998 17.6077 4.75718 17.6665 4.80438 17.7253C4.99318 17.9017 4.89878 17.9605 4.70998 18.0193C4.66278 18.0193 4.56837 18.0193 4.56837 18.1368C4.56837 18.1956 4.66278 18.1956 4.70998 18.1956C4.89878 18.3132 5.08759 18.3132 5.27639 18.1368C5.41799 18.0193 5.5596 18.0193 5.7012 18.0193C5.9372 18.078 6.17321 18.078 6.45642 18.078C6.45642 18.078 6.50362 18.0193 6.50362 18.078C6.55082 18.0193 6.55082 18.0193 6.55082 18.0193C6.55082 18.078 6.55082 18.078 6.50362 18.1368C6.50362 18.1368 6.50362 18.1368 6.45642 18.1368C6.45642 18.5484 6.69242 18.6659 6.88123 18.8423C7.07003 19.0187 7.07003 19.2538 7.11723 19.489C7.16443 19.6654 6.92843 19.6654 6.88123 19.7242C6.69242 19.8417 6.59802 20.1357 6.40922 20.2533C6.36201 20.2533 6.26761 20.3708 6.31481 20.4884C6.36201 20.606 6.40922 20.5472 6.50362 20.606C6.59802 20.6648 6.64522 20.7236 6.55082 20.8999C6.45642 21.0763 6.50362 21.1939 6.69242 21.3115C6.97563 21.429 7.30604 21.429 7.58924 21.429C7.68364 21.429 7.77805 21.3703 7.87245 21.429C7.91965 21.4878 8.01405 21.4878 8.01405 21.6054C8.01405 21.723 7.91965 21.723 7.87245 21.7818C7.40044 21.9582 6.97563 22.1345 6.59802 22.546C6.55082 22.6048 6.45642 22.6048 6.40922 22.6636C5.89 23.0752 5.32359 23.3691 4.85158 23.8394C4.52117 24.1334 4.42677 24.3685 4.52117 24.8388C4.61558 24.8388 4.70998 24.78 4.85158 24.5449C4.94598 24.2509 4.99318 23.957 5.08759 24.1922C5.32359 23.7806 5.37079 23.8394 5.37079 23.957C5.32359 24.1922 5.22919 24.4273 5.08759 24.6625C5.04038 24.78 4.99318 24.6625 4.94598 24.6625C4.89878 24.8388 4.85158 24.8976 4.80438 25.0152C4.70998 25.1328 4.66278 25.2504 4.85158 25.1916C5.08759 25.1916 5.22919 25.2504 5.13479 25.5443L5.18199 25.6619C5.32359 25.6619 5.41799 25.7207 5.41799 25.9558C5.41799 26.191 5.7012 25.9558 5.7012 26.191C5.7956 26.191 5.89 26.1322 5.98441 26.1322C6.03161 26.1322 6.03161 25.8383 6.12601 26.0734C6.17321 26.191 6.22041 26.3086 6.07881 26.3674C5.98441 26.4262 5.93721 26.5437 5.89 26.6025C5.7956 26.6613 5.7484 26.6613 5.7484 26.7789C5.7484 26.8965 5.89 26.8377 5.93721 26.8965C6.07881 27.014 6.22041 26.9553 6.36201 26.9553C6.73962 26.8965 7.07003 26.7789 7.44764 26.7201C7.63644 26.6613 7.77805 26.6025 7.77805 26.9553C7.77805 27.014 7.82525 27.0728 7.91965 27.014C8.10845 26.8965 8.25006 27.1316 8.39166 27.0728C8.53326 27.014 8.53326 27.1904 8.48606 27.308C8.48606 27.4256 8.39166 27.5432 8.53326 27.4844C8.67487 27.4256 8.91087 27.6019 8.91087 27.1904C8.91087 27.0728 9.00527 27.1316 9.00527 27.1904C9.00527 27.3668 9.09968 27.3668 9.19408 27.3668C9.47728 27.308 9.80769 27.308 10.0909 27.1904C10.3741 27.0728 10.7045 27.2492 10.9877 27.1904C11.3181 27.0728 11.6957 26.9553 12.0733 27.0728C12.1677 27.1316 12.4038 27.0728 12.451 26.9553C12.5926 26.7201 12.7814 26.7789 12.923 26.7201C13.631 26.6613 14.2918 26.191 15.047 26.1322C15.1414 26.1322 15.1886 26.1322 15.2358 26.0146C15.3302 25.897 15.4246 25.9558 15.5662 25.897C15.7078 25.8383 15.8022 26.0146 15.8966 25.9558C16.0382 25.897 16.1326 25.7207 16.2742 25.7207C16.6518 25.7207 16.9823 25.6031 17.3127 25.5443C17.5487 25.4855 17.8791 25.5443 18.0207 25.1328C18.0679 25.074 18.2095 25.074 18.3511 25.0152C18.3983 25.0152 18.4927 25.074 18.5399 25.074C18.6343 24.7213 18.8703 25.074 19.0591 24.8976C19.2007 24.7213 19.4839 24.78 19.7199 24.7213C19.8143 24.7213 19.9087 24.6625 19.9559 24.5449C20.1447 24.3685 20.3335 24.4861 20.5223 24.5449C20.7111 24.5449 20.8055 24.1334 21.0887 24.3685C21.1359 24.4861 21.2776 24.4273 21.372 24.3097C21.4664 24.1334 21.608 24.1922 21.7496 24.1334C21.9384 24.0746 22.1272 24.0746 22.316 24.0158C22.5048 23.957 22.6936 23.957 22.8824 23.8982C23.0712 23.8394 23.26 23.8982 23.4016 23.7806C23.5432 23.6043 23.732 23.7806 23.9208 23.7218C24.912 23.5455 25.8561 23.0752 26.8473 22.9576C27.0361 22.7224 27.2721 22.9576 27.4609 22.84C27.5553 22.7812 27.6025 22.6048 27.7913 22.7812C27.8857 22.84 28.0273 22.6048 28.1217 22.546C28.1689 22.546 28.2633 22.4873 28.2633 22.546C28.4521 22.6636 28.5937 22.546 28.7353 22.546C28.9713 22.546 29.1601 22.546 29.3961 22.546C29.7737 22.546 30.1986 22.7812 30.5762 22.3697C30.6706 22.2521 30.8594 22.2521 31.001 22.4285C31.0954 22.546 31.1898 22.546 31.3314 22.4873C31.5202 22.4285 31.709 22.3109 31.8506 22.4285C32.0866 22.546 32.0866 22.1933 32.2754 22.3109C32.417 22.3697 32.6058 22.1933 32.7474 22.3697C32.7946 22.4285 32.9362 22.3697 33.0306 22.2521C33.125 22.1345 33.2666 22.0757 33.361 22.2521C33.5026 22.3697 33.597 22.4873 33.7386 22.2521C33.8802 21.9582 34.1162 21.9582 34.3522 22.0169C35.0131 22.1933 35.0131 22.1345 35.5323 21.8406C35.7211 21.723 35.9099 21.723 36.0515 21.7818C36.1459 21.8406 36.2403 22.0169 36.3819 21.9582C36.7595 21.7818 37.1843 22.0169 37.5619 21.8406C37.9867 21.6642 38.4587 21.8994 38.9307 21.723H38.9779C39.3084 21.8994 39.686 21.8406 40.0636 21.7818C40.4412 21.723 40.866 21.8406 41.2436 21.6642C41.3852 21.6054 41.5268 21.6642 41.6684 21.6642C41.9044 21.723 42.2348 21.723 42.3764 21.3703C42.4236 21.1939 42.5652 21.2527 42.6596 21.1939C42.7068 21.1939 42.8012 21.1351 42.8012 21.1939C42.8012 21.2527 42.754 21.3115 42.754 21.3703C42.754 21.429 42.6124 21.6054 42.7068 21.5466C43.0372 21.4878 43.3204 21.6642 43.6509 21.5466C43.7925 21.5466 44.3117 21.429 44.4061 21.5466C44.5949 21.6642 44.6893 21.5466 44.8309 21.3703C45.0197 21.1351 45.1613 21.0763 45.3029 21.3703C45.3973 21.6054 45.5389 21.5466 45.6805 21.429C45.6805 21.3115 45.6805 21.2527 45.7277 21.3703C45.8221 21.1939 45.8693 21.1939 45.9165 21.1939C45.8693 21.3115 45.8221 21.3703 45.7749 21.4878C45.7749 21.4878 45.7749 21.4878 45.7277 21.4878C45.7277 21.6054 45.7749 21.6054 45.8221 21.6054C46.1053 21.6054 46.4357 21.6642 46.7189 21.5466C46.9077 21.7818 47.1909 21.6054 47.4269 21.6642C47.6629 21.723 47.8989 21.6054 48.2294 21.4878C48.2294 21.429 48.2766 21.3703 48.3238 21.4878C48.4182 21.429 48.4654 21.429 48.4654 21.429C48.4654 21.5466 48.4182 21.5466 48.3238 21.5466C48.371 21.7818 48.5126 21.7818 48.6542 21.7818C48.8902 21.7818 49.079 21.6642 49.315 21.7818C49.4566 21.8406 49.6926 21.6054 49.8342 21.723C50.0702 21.8406 50.1174 21.6054 50.2118 21.5466C50.3062 21.4878 50.3062 21.4878 50.3534 21.6054C50.495 22.0169 50.495 22.0169 50.7782 21.9582C50.967 21.8994 51.1558 22.0757 51.3446 22.0169C51.5334 21.8994 51.675 21.9582 51.8166 22.1933C51.8166 22.1933 52.147 22.1933 52.147 22.0757C52.147 21.723 52.3358 21.7818 52.4775 21.8406C52.5247 21.8406 52.5719 21.8994 52.6191 21.8406C52.6663 21.723 52.7607 21.6054 52.8079 21.4878C52.9967 21.1351 52.8079 20.7236 52.5247 20.7824C52.2887 20.8412 52.0526 20.6648 51.8166 20.7236C51.675 20.3708 51.2974 20.7236 51.203 20.312C51.203 20.312 51.0614 20.312 51.0614 20.3708C51.0614 20.4296 51.0614 20.4884 51.0614 20.606C51.0142 20.8999 50.967 21.0175 50.731 20.8412C50.5422 20.7236 50.4006 20.606 50.1646 20.606C50.1174 20.606 49.9758 20.5472 50.023 20.4296C50.023 20.3708 50.0702 20.1357 50.2118 20.2533C50.3534 20.3708 50.3534 20.1357 50.4006 20.1357C50.5422 20.1357 50.6838 20.0181 50.6838 20.312C50.6838 20.3708 50.6838 20.4296 50.731 20.5472C50.731 20.606 50.7782 20.606 50.7782 20.6648C50.8254 20.606 50.8254 20.5472 50.8726 20.4884C50.9198 20.4296 50.9198 20.312 50.9198 20.1945C50.9198 19.8417 50.9198 19.8417 51.203 19.9593C51.3446 20.0181 51.5334 19.9593 51.675 20.2533C51.7222 20.3708 51.911 20.1357 51.9582 20.0769C52.0054 19.9005 51.8638 20.0181 51.8166 20.0181C51.7222 19.9593 51.7694 19.9593 51.8166 19.8417C51.911 19.7242 51.8166 19.489 51.8166 19.489C51.5806 19.6066 51.6278 19.1363 51.439 19.2538C51.2502 19.3714 51.1086 19.1363 50.967 19.0775C50.8254 18.9599 50.6838 18.7247 50.4478 18.9011C50.4006 18.9599 50.3534 18.8423 50.3062 18.8423C49.7398 18.7247 49.1734 18.4896 48.5598 18.7247C48.5126 18.7247 48.4654 18.7247 48.4654 18.7247C48.4182 18.6659 48.3238 18.6072 48.3238 18.5484C48.3238 18.4896 48.4182 18.4896 48.4654 18.4896C48.7486 18.4308 49.0318 18.372 49.315 18.3132C49.5038 18.2544 49.6454 18.1956 49.787 18.4308C49.9286 18.6072 50.1646 18.4896 50.2118 18.4308C50.3534 18.1956 50.5422 18.2544 50.6838 18.1956C51.203 17.9605 51.7694 18.1368 52.3359 18.0193C52.5247 17.9605 52.8079 17.6077 52.9967 18.0193H53.0911C53.2799 18.0193 53.5631 17.7841 53.7047 17.4902C53.7519 17.3726 53.8463 17.255 53.9879 17.255C54.1295 17.255 54.2239 17.1962 54.3655 17.255C54.5071 17.3138 54.7431 17.1962 54.7903 17.0198C54.8375 16.7259 55.0263 16.5495 55.0735 16.3732C55.1207 16.0792 55.2623 16.0204 55.4983 15.9616C55.5927 15.9616 55.6871 15.9028 55.7815 15.9028C55.8287 15.9028 55.8287 15.844 55.8759 15.7853C55.8287 15.7853 55.8287 15.7265 55.7815 15.7265C55.6399 15.7265 55.4511 15.7853 55.3095 15.8441C55.1207 15.9028 55.1679 15.6677 55.0735 15.6089C54.9319 15.5501 55.0263 15.4913 55.0735 15.3737C55.1679 15.2562 55.2151 15.021 55.3095 14.9622C55.5927 14.7858 55.4983 14.6683 55.3095 14.5507C55.2623 14.4919 55.1207 14.4919 55.2151 14.3743C55.2623 14.3155 55.3095 14.3743 55.4039 14.3155V14.3743C55.4039 14.3743 55.4511 14.4331 55.4983 14.4331C55.4983 14.4331 55.4983 14.3743 55.5455 14.3743L55.4983 14.3155H55.4511C55.4039 14.1392 55.4511 13.9628 55.3095 13.8452C55.2151 13.7864 55.3095 13.6688 55.4511 13.4925C55.4983 13.4337 55.5927 13.3161 55.4511 13.1985C55.2623 13.0222 55.2623 12.9046 55.4039 12.7282C55.4039 12.7282 55.4983 12.7282 55.4983 12.6694C55.5927 12.5518 55.5927 12.4343 55.4511 12.3755C55.2151 12.2579 54.8847 12.3167 54.6959 12.0227C54.4599 11.7288 54.3655 11.7288 54.0351 11.7876C53.9407 11.7876 53.8463 11.7876 53.7519 11.7288C53.7047 11.67 53.6103 11.7876 53.5631 11.67C53.5631 11.6112 53.6575 11.4936 53.7047 11.4348C53.8463 11.3761 53.9879 11.3173 54.1295 11.4348C54.2239 11.5524 54.4127 11.376 54.5543 11.5524C54.7903 11.2585 55.1207 11.376 55.4039 11.2585C55.4983 11.2585 55.5455 11.2585 55.6399 11.1997C55.8287 11.1409 55.8287 10.8469 55.6871 10.7294C55.2623 10.1415 54.9791 10.0239 54.7903 9.72995ZM6.88123 7.55474C6.88123 7.55474 6.83403 7.49595 6.83403 7.43716C6.83403 7.43716 6.83403 7.37837 6.88123 7.37837C6.88123 7.43716 6.88123 7.43716 6.88123 7.55474C6.88123 7.49595 6.88123 7.49595 6.88123 7.55474ZM22.7408 3.32189C22.552 3.38068 22.3632 3.38068 22.1744 3.43947C22.08 3.43947 21.9384 3.49826 21.844 3.49826C21.7968 3.49826 21.7024 3.55705 21.7024 3.43947C21.7024 3.38068 21.7968 3.2631 21.844 3.20432C22.08 3.08674 22.4104 3.20432 22.7408 3.20432L22.788 3.2631C22.7408 3.2631 22.7408 3.32189 22.7408 3.32189ZM23.0712 3.2631C23.0712 3.2631 23.024 3.20432 23.024 3.14553C23.024 3.14553 23.024 3.08674 23.0712 3.08674L23.1184 3.14553C23.1184 3.20432 23.0712 3.20431 23.0712 3.2631ZM26.7529 2.61642C25.5728 2.55763 24.4872 3.02795 23.4016 3.20432C23.3544 3.20432 23.3072 3.20432 23.3072 3.14553C23.3072 3.14553 23.3544 3.08674 23.4016 3.08674C23.5432 3.08674 23.732 2.79279 23.968 2.91037C24.0624 2.96916 24.204 2.91037 24.2984 2.79279C24.3456 2.61642 24.44 2.67521 24.5344 2.67521C25.0536 2.734 25.2896 2.67521 25.9033 2.38126C26.1865 2.26368 26.4697 2.32247 26.7529 2.32247C26.8001 2.32247 26.8945 2.44005 26.8945 2.49884C26.8945 2.67521 26.8001 2.55763 26.7529 2.61642ZM6.73962 25.9558C6.73962 25.9558 6.69242 25.9558 6.69242 25.897C6.69242 25.8383 6.64522 25.7207 6.73962 25.6619C6.78682 25.6619 6.83403 25.6619 6.88123 25.7207C6.83403 25.7795 6.83403 25.897 6.73962 25.9558ZM7.87245 20.6648C7.77805 20.9587 7.63644 20.9587 7.49484 20.9587C7.35324 20.9587 7.25883 21.0175 7.16443 21.0175L7.11723 20.9587C7.11723 20.9587 7.11723 20.8999 7.16443 20.8999C7.25883 20.8999 7.44764 20.8999 7.49484 20.8412C7.58924 20.6648 7.68364 20.5472 7.87245 20.6648ZM7.63644 20.1945C7.44764 19.9593 7.40044 20.3708 7.25883 20.2533C7.21163 20.2533 7.16443 20.2533 7.11723 20.1945C7.11723 20.1357 7.16443 20.1357 7.16443 20.0769C7.25883 19.8417 7.44764 19.9593 7.58924 19.9005C7.68364 19.9005 7.77805 19.7829 7.87245 19.9005C7.77805 20.0181 7.63644 20.1945 7.63644 20.1945ZM12.8286 8.02505C12.7814 7.96626 12.7814 7.90747 12.8286 7.90747C12.8286 7.90747 12.8758 7.90747 12.8758 7.96626C12.8758 7.96626 12.8758 8.02505 12.8286 8.02505ZM14.6694 7.49595C14.575 7.49595 14.5278 7.55474 14.4334 7.55474C14.3862 7.55474 14.339 7.55474 14.339 7.55474C14.2918 7.55474 14.2918 7.55474 14.2918 7.49595C14.2918 7.43716 14.6694 7.31958 14.7166 7.37837C14.7166 7.43716 14.6694 7.49595 14.6694 7.49595ZM15.047 7.43716C14.9998 7.43716 14.9998 7.43716 14.9526 7.37837C14.9998 7.31958 15.047 7.26079 15.0942 7.14321C15.0942 7.202 15.1414 7.202 15.1414 7.26079C15.1886 7.37837 15.1414 7.43716 15.047 7.43716ZM15.6606 7.31958C15.5662 7.31958 15.4246 7.202 15.4246 7.14321C15.3774 6.96684 15.5662 7.08442 15.6134 7.02563C15.7078 7.02563 15.8022 6.90805 15.8022 7.08442C15.8494 7.14321 15.755 7.31958 15.6606 7.31958ZM16.5102 6.96684C16.463 6.96684 16.4158 7.02563 16.4158 6.96684C16.3686 6.96684 16.227 7.08442 16.227 6.90805C16.227 6.79047 16.3214 6.67289 16.4158 6.67289C16.463 6.67289 16.5102 6.79047 16.5574 6.73168C16.6518 6.67289 16.7934 6.37895 16.8407 6.73168C16.8879 7.02563 16.6518 6.90805 16.5102 6.96684ZM17.1711 6.67289C17.1239 6.67289 17.1239 6.67289 17.0767 6.6141C17.0767 6.6141 17.0767 6.55532 17.1239 6.55532C17.1711 6.55532 17.1711 6.55532 17.2183 6.55532C17.2183 6.6141 17.1711 6.67289 17.1711 6.67289ZM18.3983 6.49652C18.3983 6.55531 18.3511 6.55531 18.3511 6.6141C18.2567 6.49653 18.1623 6.55531 18.1151 6.49652C18.0207 6.6141 18.0207 6.67289 17.9735 6.67289C17.9735 6.67289 17.9263 6.6141 17.9263 6.55532H17.8791C17.7375 6.55532 17.6903 6.79047 17.5015 6.79047C17.4071 6.79047 17.3599 6.73168 17.3599 6.67289C17.3599 6.6141 17.3599 6.55532 17.4543 6.55532C17.5487 6.55532 17.5959 6.49652 17.7375 6.49652C17.7847 6.49652 17.8319 6.49653 17.8319 6.55532C17.7847 6.49653 17.8319 6.49652 17.8791 6.49652C17.8791 6.49652 17.9263 6.49653 17.9263 6.55532C17.9263 6.55532 17.9263 6.55531 17.9263 6.6141C17.9735 6.6141 18.0207 6.6141 18.0207 6.6141C18.0207 6.6141 18.0207 6.6141 18.0679 6.6141C18.0679 6.6141 18.0207 6.6141 18.0207 6.55532C18.0207 6.49653 18.1151 6.43774 18.2095 6.43774C18.1623 6.37895 18.1623 6.43774 18.1623 6.43774C18.3511 6.32016 18.3511 6.37895 18.3983 6.49652ZM19.9087 5.96742C19.6255 6.02621 19.3895 6.37895 19.0591 6.32016C18.9175 6.32016 18.6343 6.55531 18.6343 6.32016C18.5399 5.96742 18.8703 6.085 19.0119 6.02621C19.2007 5.90863 19.4367 6.02621 19.5783 5.79105C19.6727 5.67347 19.7671 5.90863 19.8615 5.84984C19.9559 5.84984 19.9559 5.96742 19.9087 5.96742ZM20.6167 5.96742C20.5223 6.02621 20.4751 6.02621 20.3807 6.02621C20.3335 6.02621 20.2391 6.085 20.1919 5.96742C20.1919 5.84984 20.1919 5.79105 20.2863 5.79105C20.3807 5.79105 20.4751 5.73226 20.5695 5.73226C20.5695 5.73226 20.6167 5.79105 20.6639 5.84984C20.6639 5.84984 20.6639 5.96742 20.6167 5.96742ZM22.1272 5.55589C22.1272 5.61468 22.1272 5.67347 22.08 5.67347C21.9384 5.73226 21.7968 5.73226 21.608 5.79105C21.4664 5.79105 21.2776 5.96742 21.0887 5.79105C21.0415 5.79105 20.9943 5.73226 20.9943 5.73226C20.9943 5.61468 21.0415 5.61468 21.0887 5.55589C21.2304 5.43831 21.3248 5.20316 21.5608 5.37952C21.7024 5.4971 21.8912 5.32074 22.0328 5.32074C22.1272 5.37952 22.1744 5.4971 22.1272 5.55589ZM22.6464 5.55589C22.5992 5.55589 22.5992 5.55589 22.552 5.55589C22.5992 5.43831 22.6464 5.37953 22.6464 5.26195C22.6936 5.32074 22.6936 5.32074 22.7408 5.37952C22.7408 5.43831 22.7408 5.55589 22.6464 5.55589ZM23.6376 5.32074C23.5432 5.43831 23.4016 5.26195 23.3072 5.26195C23.1656 5.26195 23.024 5.43831 22.8352 5.26195C22.9768 5.14437 23.1656 5.14437 23.3072 5.08558C23.4016 5.02679 23.496 5.02679 23.5904 5.02679C23.6848 5.02679 23.8264 4.90921 23.8264 5.14437C23.8736 5.37953 23.732 5.32074 23.6376 5.32074ZM25.9977 5.02679C25.9505 5.02679 25.9033 5.02679 25.9033 5.02679H25.8561C25.62 5.14437 25.4312 4.968 25.2896 4.90921C25.2424 4.90921 25.4784 4.73284 25.7145 4.79163C25.7617 4.79163 25.7617 4.85042 25.8089 4.85042C25.8561 4.85042 25.9033 4.85042 25.9977 4.85042C26.0449 4.85042 26.0921 4.85042 26.0921 4.85042C26.0921 4.968 26.0449 4.968 25.9977 5.02679ZM27.9801 4.55647C27.7913 4.55647 27.6969 5.02679 27.4609 4.67405C27.4137 4.61526 27.2721 4.73284 27.1777 4.73284C27.0833 4.73284 26.9889 4.85042 26.8945 4.79163C26.7529 4.73284 26.5641 4.73284 26.4225 4.67405C26.5169 4.43889 26.7057 4.55647 26.8473 4.49768C26.8945 4.49768 26.9417 4.49768 26.9889 4.43889C27.3193 4.3801 27.6025 4.3801 27.9329 4.43889C27.9801 4.43889 27.9801 4.43889 28.0273 4.49768L27.9801 4.55647ZM34.305 3.79221C34.305 3.90979 34.2106 4.08616 34.069 4.02737C33.9274 3.90979 33.8802 3.90979 33.833 4.08616C33.6442 3.90979 33.5498 4.14495 33.4554 4.20374C33.361 4.26253 33.361 4.26253 33.2666 4.20374C33.125 4.08616 33.0778 4.08616 32.8418 4.14495C32.6058 4.14495 32.3698 4.3801 32.0866 4.20374C31.8506 4.02737 31.7562 4.55647 31.473 4.3801C31.2842 4.26253 31.0954 4.20374 30.9066 4.26253C30.7178 4.32131 30.529 4.43889 30.293 4.3801C30.1041 4.3801 29.8681 4.43889 29.6793 4.49768C29.5377 4.55647 29.3489 4.61526 29.2545 4.43889C29.2073 4.3801 29.1601 4.32131 29.1129 4.43889C29.0185 4.55647 28.9241 4.55647 28.8769 4.55647C28.6881 4.32131 28.4521 4.67405 28.2633 4.55647C28.1217 4.49768 28.2161 4.43889 28.2633 4.3801C28.2633 4.14495 28.4521 4.14495 28.4993 4.20374C28.6409 4.32131 28.7825 4.26253 28.9241 4.26253C29.5377 4.08616 30.1986 4.20374 30.8594 4.02737C31.0482 3.96858 31.237 4.08616 31.3786 3.90979C31.5202 3.73342 31.6618 4.14495 31.8506 3.90979C31.9922 3.67463 32.1338 3.851 32.3226 3.90979C32.417 3.90979 32.5586 3.90979 32.653 3.851C33.125 3.67463 33.597 3.90979 34.069 3.73342C34.1634 3.55705 34.305 3.67463 34.305 3.79221ZM34.9187 3.96858C34.8243 3.79221 34.6355 3.96858 34.4939 3.851C34.4467 3.851 34.4466 3.79221 34.4466 3.73342C34.4466 3.67463 34.4467 3.61584 34.4939 3.61584C34.6827 3.61584 34.8715 3.61584 35.0131 3.61584V3.67463H35.0603C34.9659 3.90979 34.9187 3.90979 34.9187 3.96858ZM35.1547 3.67463C35.1075 3.67463 35.0131 3.79221 35.0131 3.61584C35.0131 3.55705 35.0603 3.55705 35.1075 3.55705C35.1547 3.55705 35.2019 3.55705 35.3435 3.49826C35.2491 3.55705 35.2019 3.61584 35.1547 3.67463ZM37.5619 20.3708C37.5619 20.312 37.5619 20.312 37.6091 20.2533C37.6091 20.2533 37.6563 20.2533 37.6563 20.312C37.6091 20.312 37.6091 20.3708 37.5619 20.3708ZM39.1195 20.3708L39.0723 20.312C39.0723 20.312 39.0723 20.2533 39.1195 20.2533C39.1195 20.2533 39.1195 20.2533 39.1195 20.3708C39.1668 20.312 39.1195 20.312 39.1195 20.3708ZM38.7891 3.79221C38.7419 3.73342 38.7419 3.79221 38.7891 3.79221C38.7419 3.73342 38.7419 3.67463 38.7891 3.67463C38.7891 3.67463 38.8363 3.67463 38.8363 3.73342C38.7891 3.73342 38.7891 3.73342 38.7891 3.79221ZM39.7332 4.20374C39.7804 4.20374 39.8276 4.14495 39.8748 4.14495C39.922 4.14495 39.922 4.20374 39.8748 4.26253C39.8276 4.26253 39.7804 4.26253 39.7332 4.26253C39.686 4.26253 39.686 4.20374 39.7332 4.20374ZM42.3292 20.2533C42.2348 20.312 41.9988 20.2533 41.9044 20.1357C41.8572 20.0769 41.9044 20.0181 41.9516 19.9593C42.0932 19.7242 42.1876 20.0181 42.3292 19.9593C42.3292 19.9593 42.3764 20.0181 42.3764 20.0769C42.3292 20.1945 42.3292 20.2533 42.3292 20.2533ZM42.8956 19.9593C42.8956 20.0181 42.9428 20.1357 42.8484 20.1357C42.8012 20.1357 42.8012 20.0181 42.8012 19.9593C42.8012 19.9005 42.7068 19.7829 42.8484 19.7829C42.8956 19.7242 42.8956 19.8417 42.8956 19.9593ZM40.7244 3.73342C40.6772 3.851 40.5828 3.90979 40.4884 3.79221C40.2996 3.55705 40.0164 3.61584 39.8276 3.55705C39.6388 3.55705 39.4028 3.67463 39.2612 3.43947C39.214 3.32189 39.1195 3.43947 39.0251 3.43947C38.8363 3.49826 38.6003 3.49826 38.4115 3.55705C38.3171 3.55705 38.2227 3.61584 38.2699 3.79221C38.2699 3.851 38.2227 3.96858 38.1755 3.851C38.0811 3.49826 37.8923 3.67463 37.7507 3.73342C37.3731 3.79221 37.0427 3.90979 36.6651 3.73342C36.4763 3.67463 36.3347 3.96858 36.1931 3.851C36.0515 3.73342 35.8627 3.79221 35.7211 3.851C35.5795 3.851 35.4379 3.96858 35.3907 3.73342C36.1459 3.55705 36.7595 3.32189 37.3259 3.55705C37.3731 3.55705 37.4675 3.49826 37.5619 3.49826C37.7507 3.49826 37.9867 3.32189 38.1755 3.43947C38.4115 3.55705 38.4587 3.14553 38.6475 3.20432C38.9779 3.32189 39.4028 3.08674 39.7332 3.38068C39.8276 3.43947 39.8748 3.38068 39.9692 3.38068C40.158 3.32189 40.2996 3.32189 40.4884 3.2631C40.8188 3.20431 40.866 3.2631 40.7244 3.73342ZM43.3204 19.9005C43.2732 19.9005 43.226 19.9593 43.1788 19.9005C43.1788 19.9005 43.1788 19.7829 43.226 19.7829C43.2732 19.7829 43.3204 19.7242 43.3676 19.7829C43.3204 19.8417 43.3204 19.9005 43.3204 19.9005ZM41.3852 3.49826C41.338 3.55705 41.2908 3.67463 41.2908 3.67463C41.1492 3.67463 41.0548 3.49826 40.9132 3.43947C40.9604 3.32189 40.9604 3.2631 41.0076 3.20432C41.0076 3.20432 41.0076 3.14553 41.0548 3.14553C41.102 3.32189 41.2436 3.43947 41.3852 3.49826ZM41.6684 3.67463C41.574 3.67463 41.574 3.67463 41.574 3.61584C41.574 3.43947 41.6212 3.32189 41.7156 3.32189C41.7628 3.32189 41.81 3.43947 41.7628 3.49826C41.7156 3.55705 41.6684 3.61584 41.6684 3.67463ZM41.81 3.67463C41.7628 3.67463 41.7628 3.67463 41.81 3.67463C41.7628 3.61584 41.7628 3.55705 41.81 3.55705C41.8572 3.55705 41.8572 3.61584 41.8572 3.61584C41.8572 3.67463 41.81 3.67463 41.81 3.67463ZM41.9988 3.08674C41.9516 3.08674 41.9044 3.14553 41.8572 3.08674C41.8572 3.08674 41.8572 2.96916 41.9044 2.96916C41.9516 2.96916 41.9988 2.91037 42.046 2.96916C41.9988 3.02795 41.9988 3.08674 41.9988 3.08674ZM44.4533 20.1357C44.4061 20.1357 44.4061 20.1357 44.3589 20.1357C44.4061 20.0181 44.4533 19.9005 44.5005 19.7829C44.5005 19.8417 44.5477 19.9005 44.5477 19.9005C44.5949 20.0181 44.5949 20.1357 44.4533 20.1357ZM44.9725 20.1357C44.8781 20.1945 44.8309 20.0769 44.7837 20.0769L44.7365 20.0181C44.7837 20.0181 44.7837 19.9593 44.8309 19.9593C44.8781 19.8417 44.9253 19.9593 44.9725 20.0181L45.0197 20.0769C45.0197 20.1357 44.9725 20.1357 44.9725 20.1357ZM42.4708 3.67463C42.4236 3.73342 42.4236 3.73342 42.4236 3.73342C42.3764 3.67463 42.282 3.67463 42.282 3.61584C42.2348 3.55705 42.282 3.49826 42.3292 3.49826C42.4236 3.49826 42.518 3.43947 42.6596 3.43947C42.754 3.49826 42.8484 3.55705 42.8956 3.61584C42.754 3.55705 42.6124 3.55705 42.4708 3.67463ZM43.2732 3.851C43.226 3.851 43.226 3.79221 43.226 3.79221C43.2732 3.851 43.2732 3.851 43.2732 3.851ZM43.3204 3.79221C43.3204 3.79221 43.2732 3.79221 43.2732 3.73342H43.3204C43.3204 3.73342 43.3204 3.73342 43.3204 3.79221ZM45.6805 19.8417C45.6805 19.7829 45.6333 19.7829 45.6333 19.7242C45.6333 19.7242 45.6333 19.6654 45.6805 19.6654C45.6805 19.7242 45.6805 19.7829 45.6805 19.8417ZM46.1053 21.3703C46.0581 21.3115 46.0581 21.2527 46.1053 21.2527C46.1053 21.2527 46.1525 21.2527 46.1525 21.3115C46.1525 21.3115 46.1525 21.3703 46.1053 21.3703ZM43.8869 3.2631C43.8869 3.43947 43.8869 3.61584 43.6509 3.67463C43.462 3.73342 43.2732 3.67463 43.1316 3.61584C42.8956 3.38068 43.0372 3.32189 43.226 3.38068C43.3676 3.49826 43.6509 3.43947 43.7925 3.20432C43.7925 3.14553 43.8869 3.14553 43.9341 3.20432C43.9341 3.20432 43.9341 3.2631 43.8869 3.2631ZM44.1701 3.67463C44.1229 3.67463 44.0757 3.73342 44.0285 3.67463C44.0285 3.67463 44.0285 3.55705 44.0757 3.55705C44.1229 3.55705 44.1701 3.49826 44.2173 3.55705C44.2173 3.61584 44.2173 3.67463 44.1701 3.67463ZM44.3589 3.90979C44.3589 3.90979 44.3117 3.851 44.3117 3.79221C44.3117 3.79221 44.3117 3.73342 44.3589 3.73342L44.4061 3.79221C44.3589 3.90979 44.3589 3.90979 44.3589 3.90979ZM46.6245 19.9593C46.5773 19.9005 46.5773 19.8417 46.6245 19.8417C46.6245 19.8417 46.6717 19.8417 46.6717 19.9005C46.6717 19.9005 46.6717 19.9005 46.6245 19.9593ZM44.4061 3.61584C44.4061 3.61584 44.3589 3.55705 44.3589 3.49826C44.3589 3.49826 44.3589 3.43947 44.4061 3.43947L44.4533 3.49826C44.4533 3.61584 44.4533 3.61584 44.4061 3.61584ZM47.0965 21.4878L47.0493 21.429C47.0493 21.429 47.0493 21.3703 47.0965 21.3703C47.0965 21.3703 47.0965 21.3703 47.0965 21.4878ZM44.6893 3.96858C44.6421 3.96858 44.5949 3.96858 44.5477 3.96858C44.5005 3.96858 44.5005 3.90979 44.5477 3.851C44.5949 3.851 44.6421 3.79221 44.6893 3.79221C44.7837 3.90979 44.7837 3.90979 44.6893 3.96858ZM44.7837 3.67463C44.7837 3.67463 44.7365 3.67463 44.7365 3.61584C44.6893 3.55705 44.6893 3.43947 44.7837 3.38068C44.8309 3.38068 44.8781 3.38068 44.9253 3.43947C44.8781 3.49826 44.8309 3.61584 44.7837 3.67463ZM45.1141 3.32189L45.1613 3.38068L45.1141 3.43947C45.1141 3.43947 45.0669 3.43947 45.1141 3.32189C45.0669 3.38068 45.0669 3.38068 45.1141 3.32189ZM45.3501 3.96858C45.3501 4.08616 45.2085 4.02737 45.1613 4.08616C45.1141 4.08616 45.0197 4.08616 45.0197 4.02737C45.0197 3.90979 45.1613 3.96858 45.2085 3.90979C45.3029 3.851 45.3501 3.90979 45.3501 3.96858ZM45.6333 4.08616C45.5861 4.08616 45.5389 4.08616 45.5389 4.02737C45.5389 4.02737 45.5861 3.96858 45.6333 3.96858C45.6805 3.96858 45.7277 3.96858 45.7277 4.02737C45.6805 4.08616 45.6333 4.08616 45.6333 4.08616ZM49.551 20.0769C49.6454 20.0769 49.6926 20.0769 49.6926 20.1945C49.7398 20.2533 49.6926 20.312 49.5982 20.3708C49.5038 20.3708 49.4566 20.3708 49.4566 20.2533C49.4566 20.1357 49.4566 20.1357 49.551 20.0769ZM48.1822 2.55763C48.2294 2.49884 48.4654 2.61642 48.4654 2.67521C48.4654 2.734 48.4182 2.79279 48.371 2.79279C48.2766 2.79279 48.1822 2.91037 48.135 2.734C48.135 2.67521 48.135 2.55763 48.1822 2.55763ZM47.7573 2.91037C47.7573 2.91037 47.8046 2.96916 47.8046 3.02795C47.8046 3.02795 47.8045 3.08674 47.7573 3.08674C47.7573 3.02795 47.7573 3.02795 47.7573 2.91037C47.7101 2.96916 47.7573 2.96916 47.7573 2.91037ZM46.5773 3.49826C46.5773 3.55705 46.5773 3.55705 46.5301 3.61584C46.5301 3.61584 46.4829 3.61584 46.4829 3.55705C46.5301 3.55705 46.5301 3.49826 46.5773 3.49826ZM45.9165 3.49826C45.9165 3.43947 46.0109 3.43947 46.0581 3.43947C46.1053 3.43947 46.1997 3.32189 46.1997 3.49826C46.1997 3.55705 46.1053 3.55705 46.0581 3.55705C46.0109 3.55705 45.9165 3.67463 45.9165 3.49826ZM48.7486 21.429C48.7014 21.429 48.7014 21.429 48.6542 21.3703C48.6542 21.3703 48.6542 21.3115 48.7014 21.3115C48.7486 21.3115 48.7486 21.3115 48.7958 21.3115C48.7486 21.3703 48.7486 21.3703 48.7486 21.429ZM48.4182 19.9005C48.5126 19.9005 48.5598 19.9005 48.5598 20.0181C48.5598 20.0769 48.5598 20.0769 48.5598 20.1357C48.4654 20.0769 48.4182 20.0181 48.3238 20.0181C48.371 19.9593 48.4182 19.9005 48.4182 19.9005ZM48.607 4.32131C48.4654 4.55647 48.2766 4.67405 48.0406 4.55647C47.8045 4.43889 47.5685 4.3801 47.3325 4.49768C47.2853 4.49768 47.1909 4.55647 47.1437 4.55647C46.8133 4.26253 46.3413 4.43889 46.0109 4.20374C45.9637 4.20374 45.8693 4.20374 45.8693 4.14495C45.8693 4.08616 45.9165 3.96858 46.0109 3.90979C46.0581 3.851 46.1525 3.851 46.1997 3.851C46.3885 3.79221 46.4829 3.851 46.6717 3.96858C46.9077 4.14495 47.2381 4.14495 47.5213 4.20374C47.5685 4.20374 47.6157 4.20374 47.6157 4.14495C47.6629 4.02737 47.5685 4.02737 47.5685 4.02737C47.5685 3.96858 47.5213 3.96858 47.4741 3.96858C47.4741 3.96858 47.4269 3.90979 47.4269 3.851C47.4741 3.851 47.4741 3.79221 47.5213 3.79221C47.8517 3.90979 48.2294 4.02737 48.5598 4.02737C48.7014 3.96858 48.7014 4.14495 48.607 4.32131ZM49.0318 4.43889C49.0318 4.43889 48.9846 4.3801 48.9846 4.32131C48.9846 4.32131 48.9846 4.26253 49.0318 4.26253C49.0318 4.32131 49.0318 4.32131 49.0318 4.43889C49.079 4.3801 49.0318 4.3801 49.0318 4.43889ZM50.023 6.55532C49.9758 6.55532 49.9758 6.55531 49.9286 6.49652C50.0702 6.55531 50.023 6.55532 50.023 6.55532ZM49.9758 6.43774C49.9286 6.43774 49.9286 6.43774 49.9758 6.43774C49.8814 6.37895 49.8814 6.37895 49.8814 6.37895C49.8814 6.32016 49.9286 6.32016 49.9286 6.32016C49.9286 6.37895 49.9286 6.37895 49.9758 6.43774H50.023L50.0702 6.49652C50.023 6.49652 49.9758 6.43774 49.9758 6.43774ZM50.259 6.085C50.1646 6.085 50.1646 6.20258 50.1174 6.26137C50.1174 6.20258 50.0702 6.20258 50.0702 6.14379C50.0702 6.085 50.0702 6.02621 50.0702 6.02621C50.1174 5.90863 50.2118 5.96742 50.259 5.90863C50.3062 5.90863 50.3534 5.90863 50.3534 5.90863C50.3534 6.02621 50.3062 6.085 50.259 6.085ZM50.3534 3.49826C50.3534 3.55705 50.2118 3.55705 50.2118 3.55705C49.9758 3.38068 49.7398 3.61584 49.5038 3.49826C49.2678 3.38068 49.0318 3.2631 48.7958 3.38068C48.6542 3.14553 48.371 3.20432 48.1822 3.08674C48.135 3.02795 48.0406 3.02795 47.9934 3.02795C48.0406 2.91037 48.0878 2.91037 48.1822 2.91037C48.2294 2.91037 48.2766 2.91037 48.3238 2.85158C48.4654 2.734 48.6542 2.85158 48.843 2.91037C49.079 2.96916 49.3622 2.85158 49.5982 3.02795C49.8342 3.20432 50.0702 3.02795 50.259 3.2631C50.259 3.38068 50.4006 3.38068 50.3534 3.49826ZM50.2118 2.85158C50.2118 2.79279 50.2118 2.79279 50.259 2.734C50.259 2.734 50.3062 2.734 50.3062 2.79279C50.259 2.79279 50.259 2.79279 50.2118 2.85158ZM50.7782 5.84984L50.731 5.79105C50.731 5.79105 50.731 5.73226 50.7782 5.73226C50.7782 5.73226 50.7782 5.73226 50.7782 5.84984C50.7782 5.79105 50.7782 5.79105 50.7782 5.84984ZM51.203 6.6141C51.1558 6.55531 51.1558 6.49652 51.203 6.49652C51.203 6.49652 51.2502 6.49653 51.2502 6.55532C51.2502 6.55532 51.2502 6.55531 51.203 6.6141ZM54.1295 12.8458C54.1295 12.787 54.1767 12.787 54.1767 12.787C54.1767 12.8458 54.2239 12.8458 54.2239 12.9046C54.1767 12.8458 54.1295 12.8458 54.1295 12.8458ZM54.3655 13.3161C54.3183 13.2573 54.1767 13.2573 54.2239 13.0809C54.2239 13.0222 54.2711 12.9634 54.2711 12.9046C54.6015 13.1985 54.4127 13.3749 54.3655 13.3161ZM54.2711 12.9046C54.4127 12.9634 54.5543 12.9634 54.6015 13.0222C54.4599 12.9634 54.3183 12.9634 54.2711 12.9046ZM54.7431 14.1392C54.6959 14.0804 54.6959 14.1392 54.7431 14.1392C54.6959 14.0804 54.6959 14.0216 54.7431 14.0216C54.7431 14.0216 54.7903 14.0216 54.7903 14.0804C54.7431 14.0804 54.7431 14.0804 54.7431 14.1392ZM54.8847 13.4925C54.8847 13.4925 54.8375 13.4337 54.8375 13.3749C54.8375 13.3749 54.8375 13.3161 54.8847 13.3161C54.8847 13.3749 54.8847 13.4337 54.8847 13.4925ZM53.8463 12.0815C53.7991 12.0815 53.8463 11.9639 53.9879 11.9639C54.1767 11.8464 54.3655 11.9639 54.4599 12.0815C54.6015 12.1991 54.6487 12.3167 54.7903 12.2579C54.8375 12.2579 54.8847 12.3167 54.8847 12.3755C54.8847 12.4343 54.8847 12.493 54.7903 12.5518C54.4599 12.6694 54.1767 12.493 53.8935 12.4343C53.7519 12.3755 53.9879 12.1991 53.8463 12.0815ZM53.8935 14.1392C53.9879 14.0804 54.2711 14.1392 54.3183 14.2567V14.3155C54.2711 14.3155 54.2711 14.3743 54.2239 14.3743C54.1295 14.3743 54.0351 14.1979 53.9407 14.2567C53.8935 14.3155 53.8935 14.2567 53.8935 14.1392ZM52.6191 7.202L52.6663 7.26079C52.6191 7.37837 52.5719 7.31958 52.5247 7.31958L52.4775 7.26079C52.4775 7.202 52.5247 7.202 52.6191 7.202ZM51.7222 7.84868C51.9582 7.78989 52.147 7.37837 52.383 7.55474C52.6663 7.78989 52.8551 7.7311 53.1383 7.67231C53.2327 7.67231 53.2327 7.78989 53.1855 7.96626C53.1383 8.08384 53.1383 7.96626 53.1383 8.02505C53.1855 8.14263 53.2799 8.08384 53.3271 8.08384C53.3743 8.08384 53.4687 8.02505 53.4687 8.14263C53.4687 8.20142 53.4215 8.26021 53.3271 8.26021H53.2327C53.0911 8.26021 52.9967 8.319 52.8551 8.20142C52.5719 8.02505 52.2886 7.90747 51.9582 8.08384C51.911 8.08384 51.8638 8.02505 51.8166 8.02505C51.7694 7.96626 51.6278 7.90747 51.7222 7.84868ZM51.8638 9.90631C51.8638 9.84752 51.911 9.84752 51.911 9.84752C51.911 9.84752 51.9582 9.90631 51.9582 9.9651C51.8638 9.9651 51.8638 9.9651 51.8638 9.90631ZM52.0526 10.1415C52.0054 10.1415 51.9582 10.0827 51.9582 10.0239C52.147 10.0827 52.0998 10.1415 52.0526 10.1415ZM52.0054 9.9651C52.0054 9.9651 52.0526 9.9651 52.0998 9.9651C52.147 9.9651 52.1942 9.9651 52.2414 10.0239C52.0998 10.0239 52.0526 10.0239 52.0054 9.9651ZM54.0351 8.96568C53.9879 9.02447 53.9879 9.20084 53.8935 9.08326C53.8463 9.08326 53.7991 9.02447 53.7991 9.02447C53.3743 9.49479 52.9023 9.14205 52.4775 9.14205C52.3358 9.14205 52.147 9.14205 52.0054 9.02447C51.8638 8.90689 51.675 9.08326 51.6278 8.96568C51.5806 8.73053 51.8638 8.90689 51.9582 8.67173C52.0054 8.61295 52.147 8.61295 52.2414 8.55416C52.4302 8.55416 52.5247 8.55416 52.6663 8.55416C52.9023 8.61295 53.1383 8.73052 53.3743 8.61295C53.5631 8.49537 53.7519 8.73053 53.9407 8.78931C54.0351 8.8481 54.0823 8.8481 54.0351 8.96568Z\"\n      fill=\"#F8BC63\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 56 / 28,\n  svg: MediumBrush,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/onion.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Onion', 'sticker name', 'web-stories');\n\nconst Onion = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 64 50\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M29.9982 5.6064C31.243 6.8231 32.6318 7.74024 34.1057 8.51581C35.4559 9.22777 36.8365 9.88228 38.2131 10.545C41.9211 12.328 45.3534 14.5254 48.4005 17.3302C50.586 19.3409 52.5161 21.5691 54.1826 24.0333C54.5049 24.5093 54.7522 25.0366 55.0604 25.5208C55.2165 25.7671 55.4314 25.9763 55.6301 26.1938C55.7031 26.2718 55.8754 26.3108 55.8835 26.3826C55.9768 27.1356 56.5728 27.1007 57.0878 27.1971C57.1628 27.2115 57.2317 27.2669 57.3371 27.3223C57.3432 27.4433 57.3939 27.589 57.3533 27.7039C57.0209 28.6334 57.3392 29.4315 57.8176 30.203C57.9332 30.3897 58.071 30.5661 58.1582 30.7652C58.2069 30.876 58.2271 31.0832 58.1643 31.1386C58.0609 31.233 57.8257 31.3232 57.7446 31.2678C57.4608 31.075 57.1202 30.8677 56.9783 30.5764C56.6965 29.9957 56.5323 29.3576 56.3133 28.7216C56.3133 28.7216 56.2464 28.6949 56.2119 28.7175C54.0873 30.1825 51.6747 30.8082 49.177 31.1735C48.0214 31.3417 46.8597 31.5243 45.694 31.5756C43.618 31.6679 41.5542 31.5428 39.6221 30.6482C39.1051 30.4081 38.5902 30.1353 38.132 29.8008C36.2263 28.4118 34.4118 26.8935 33.0413 24.9525C32.1168 23.6414 31.3505 22.2011 30.6247 20.7607C29.8624 19.2486 29.7549 17.601 29.9475 15.9206C30.1037 14.5562 30.3591 13.1856 30.0084 11.815C29.8806 11.3124 29.7286 10.8056 29.5015 10.3419C28.644 8.59172 27.758 6.85388 26.8619 5.12219C26.7159 4.83904 26.4747 4.60309 26.2537 4.36714C25.9435 4.0327 25.611 3.71673 25.2664 3.37203C25.4164 3.17096 25.5117 3.0458 25.6049 2.91859C25.98 2.40975 25.9841 2.16764 25.6273 1.6588C25.5178 1.50287 25.388 1.35719 25.2846 1.19716C25.1528 0.987877 25.0008 0.764234 25.2177 0.522126C25.4306 0.282069 25.6658 0.388761 25.8807 0.524178C26.205 0.727303 26.5193 0.94479 26.8396 1.15407C28.1128 1.98709 29.465 2.59031 30.9937 2.7565C32.3439 2.90423 33.6617 2.70315 34.9511 2.36872C36.6094 1.9399 38.2455 1.41464 39.8877 0.920169C41.4041 0.464677 42.9287 0.0727893 44.5202 0.0112364C47.247 -0.0934037 49.8116 0.536489 52.2464 1.74703C55.0726 3.15249 57.5257 5.03601 59.3706 7.65407C60.9742 9.93153 61.8297 12.4696 61.9331 15.2825C62.0528 18.5428 61.3675 21.6266 60.143 24.616C60.0315 24.8868 59.9443 25.17 59.8206 25.5167C60.1085 25.5803 60.3072 25.6398 60.512 25.6686C61.4405 25.8019 62.3082 26.1118 63.109 26.6042C63.3158 26.7314 63.5125 26.8894 63.6706 27.0699C63.7395 27.1479 63.7496 27.351 63.6949 27.4433C63.6422 27.5336 63.4638 27.6136 63.3584 27.5931C63.0664 27.5377 62.7846 27.431 62.4988 27.3387C61.9291 27.152 61.3675 26.9468 60.7917 26.7806C60.5464 26.7088 60.2788 26.7109 59.9017 26.6657C60.2545 27.2423 60.9438 27.3243 61.0675 28.0609C60.8262 28.0609 60.5951 28.1307 60.4552 28.0486C59.8936 27.7162 59.3604 27.3367 58.8171 26.9735C58.7948 26.9591 58.7705 26.9386 58.7603 26.916C58.4826 26.3272 58.0771 25.7609 57.9555 25.1413C57.6737 23.6845 57.5196 22.2031 57.327 20.73C57.0776 18.8136 56.439 17.0429 55.4172 15.4138C53.6352 12.5742 51.5004 10.0505 48.802 8.07057C46.0914 6.08241 43.0645 4.92316 39.691 4.89649C38.5841 4.88828 37.4751 5.11193 36.3682 5.24119C35.3707 5.35814 34.3753 5.48945 33.2967 5.62487C33.986 5.78901 34.6206 5.9552 35.2592 6.08857C39.5532 6.98109 43.5187 8.66559 47.1294 11.1749C48.585 12.1864 50.0447 13.2102 51.401 14.351C53.3655 16.0006 54.6955 18.1427 55.6605 20.5227C56.3457 22.2113 56.8587 23.9492 57.0938 25.763C57.1263 26.0133 57.0979 26.2718 57.0979 26.5283C57.0371 26.5508 56.9763 26.5734 56.9134 26.596C56.7978 26.4421 56.6397 26.3026 56.5769 26.1302C56.362 25.5352 56.1795 24.9299 55.9849 24.3267C55.6139 23.1757 55.251 22.0185 54.8698 20.8715C54.0062 18.2699 52.4958 16.1032 50.4218 14.3613C47.3483 11.7781 44.0215 9.60529 40.281 8.13007C37.911 7.19652 35.4255 6.70615 32.944 6.20757C31.9607 6.00855 30.9795 5.80542 29.9982 5.6064ZM53.7629 25.6255C53.8156 25.566 53.8663 25.5065 53.919 25.4449C53.6757 25.09 53.4264 24.7391 53.1892 24.378C50.6874 20.5781 47.5835 17.3733 43.9383 14.6937C41.3251 12.7753 38.428 11.3801 35.5329 9.97461C34.4057 9.42679 33.2886 8.8523 32.2141 8.21009C30.9491 7.45504 29.7732 6.57278 28.9339 5.30684C28.5446 4.72004 28.1554 4.56205 27.3647 4.54769C27.5228 4.88418 27.6688 5.23914 27.8513 5.57152C30.5902 10.5614 33.5116 15.4241 37.3474 19.6589C39.7052 22.2606 42.4178 24.2898 45.7812 25.3834C48.0295 26.1138 50.3387 26.4031 52.6681 26.6226C53.177 26.6698 53.6879 26.7068 54.1967 26.7478C51.5206 25.8081 48.9966 24.5914 46.4786 23.3439C43.3443 21.7887 40.5526 19.7677 38.132 17.2235C35.8695 14.8435 33.5907 12.4778 31.391 10.0382C30.5193 9.06978 29.836 7.9249 29.0879 6.84567C28.9481 6.6446 28.7514 6.40454 28.9643 5.98393C29.1589 6.20962 29.3333 6.36556 29.4508 6.55432C30.3125 7.93516 31.3667 9.15801 32.4959 10.3152C34.4665 12.33 36.4168 14.3674 38.4341 16.3351C39.6444 17.5169 40.9074 18.6597 42.2455 19.6877C44.6621 21.5466 47.4071 22.8433 50.1522 24.1174C51.3362 24.6714 52.5586 25.129 53.7629 25.6255ZM30.941 12.8368C30.872 13.479 30.8234 13.914 30.7808 14.349C30.5091 17.0922 30.6632 19.7513 32.2648 22.1293C32.3682 22.2832 32.4878 22.4883 32.4675 22.6525C32.4108 23.1162 32.65 23.4404 32.8791 23.7809C34.4057 26.0543 36.3601 27.8558 38.7341 29.1832C40.208 30.0081 41.7873 30.5107 43.472 30.5784C46.3772 30.6933 49.2236 30.2933 52.0032 29.4233C52.5526 29.251 53.0898 29.0335 53.6311 28.8365C52.6539 28.8857 51.7335 29.0971 50.803 29.2612C48.6742 29.6387 46.5435 29.8152 44.4006 29.3412C42.6814 28.9617 41.1 28.2517 39.5775 27.3736C37.7671 26.3292 36.1127 25.0859 34.7139 23.5183C34.2232 22.9684 33.7955 22.3591 33.3657 21.7579C33.2035 21.5322 32.9967 21.245 33.4488 20.9434C33.6961 21.1855 33.9637 21.4091 34.1847 21.6717C35.8958 23.7071 37.9495 25.3116 40.1877 26.7109C42.9875 28.459 46.0083 29.134 49.25 28.7298C51.3808 28.4651 53.4993 28.0835 55.622 27.7552C55.3463 27.6937 55.0746 27.6875 54.805 27.6937C52.1491 27.7491 49.5419 27.4085 46.9794 26.7006C43.3382 25.6952 40.1188 23.9553 37.4528 21.2039C35.6951 19.3902 34.1077 17.4369 32.6601 15.3646C32.1188 14.5849 31.5897 13.7909 30.941 12.8368ZM58.7056 25.1002C58.7644 25.1084 58.8252 25.1166 58.884 25.1228C59.0036 24.7802 59.2286 24.4847 59.1131 24.0518C59.0016 23.6373 58.9347 23.1982 58.9266 22.7674C58.884 20.3073 58.6083 17.8821 57.9372 15.5103C56.8404 11.6365 54.7766 8.39886 51.6889 5.85877C48.5181 3.25097 44.9642 2.25382 40.9338 3.36998C40.0438 3.61619 39.1335 3.81111 38.2232 3.94858C37.0656 4.12503 35.8857 4.23582 34.7585 3.80085C34.3854 3.65722 34.057 3.60593 33.6657 3.64902C31.3667 3.90344 29.1609 3.63465 27.1397 2.38923C26.9836 2.2928 26.8092 2.2292 26.5923 2.12661C26.4686 2.48156 26.3652 2.77702 26.2314 3.15659C27.1802 3.48282 28.056 3.76392 28.9197 4.08194C30.6875 4.7303 32.5061 4.9683 34.3753 4.81032C35.0504 4.75287 35.7215 4.62771 36.3966 4.54974C37.5035 4.42253 38.6125 4.19068 39.7174 4.2112C41.9394 4.25224 44.0762 4.76313 46.0954 5.74182C49.2723 7.27859 51.841 9.56016 54.1096 12.2541C56.3599 14.9255 57.8136 17.9314 58.2109 21.4419C58.3488 22.6627 58.5393 23.8794 58.7056 25.1002ZM35.6059 3.30637C35.6201 3.36587 35.6323 3.42332 35.6464 3.48282C36.0235 3.46025 36.4067 3.46641 36.7777 3.40896C38.4949 3.13608 40.21 2.86114 41.9231 2.55748C43.2977 2.31332 44.6743 2.20252 46.0569 2.44053C48.7391 2.90217 51.0179 4.19684 53.027 6.00034C56.1734 8.82767 58.1906 12.3567 59.1982 16.4746C59.6098 18.1612 59.8348 19.8785 59.6524 21.6266C59.6321 21.8174 59.628 22.0123 59.6301 22.2031C59.6321 22.3652 59.6544 22.5253 59.6686 22.6874C60.6214 20.2068 61.031 17.6769 60.9174 15.0548C60.7938 12.2316 59.845 9.73866 58.0994 7.55148C56.2484 5.23298 53.9048 3.57721 51.2429 2.35846C48.7837 1.23204 46.2049 0.784752 43.5268 1.12329C40.7858 1.47209 38.2597 2.63134 35.6059 3.30637Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.6246 40.3757C34.6368 40.8414 34.2982 40.9194 33.9657 40.9296C32.7453 40.9686 31.5207 41.0486 30.3043 40.9871C28.8122 40.9112 27.3241 40.7368 25.8421 40.5501C25.1731 40.4659 24.4939 40.3223 23.8654 40.0823C22.6166 39.6022 22.3733 38.5209 23.2897 37.5381C24.2608 36.4958 25.5015 35.8392 26.8193 35.3796C27.6627 35.0862 28.5547 34.9323 29.4305 34.7497C29.7346 34.6861 30.0022 34.6389 30.1705 34.3312C31.2531 32.3348 33.098 31.7295 35.1659 31.6023C36.9277 31.4936 38.6368 31.8752 40.2992 32.4087C43.3362 33.3812 46.3062 34.5302 49.1587 35.9767C50.3366 36.5737 51.4152 37.3083 52.291 38.3177C53.035 39.1754 53.4729 40.1561 53.4365 41.3236C53.406 42.29 53.0553 43.1066 52.2667 43.6626C51.8794 43.9334 51.7173 44.2453 51.7537 44.6967C51.7619 44.8054 51.7558 44.9162 51.7517 45.027C51.6808 46.771 51.1253 47.6389 49.4953 48.1621C48.3093 48.5417 47.0746 48.8023 45.844 48.9849C43.8025 49.2885 41.7487 49.5306 39.691 49.7174C36.6844 49.9902 33.6697 50.1113 30.651 49.8712C29.0251 49.742 27.393 49.6743 25.7752 49.4835C24.1574 49.2906 22.5517 48.9992 20.9481 48.7099C20.1858 48.5725 19.5208 48.1785 18.9369 47.6656C17.9516 46.7997 17.9172 45.7041 18.9025 44.83C19.3242 44.4546 19.8553 44.2043 20.3358 43.8965C20.423 43.8411 20.5021 43.7734 20.6278 43.679C20.0418 43.1702 19.4904 42.6942 18.943 42.2141C17.8949 41.2928 17.8118 40.3018 18.7971 39.3067C19.3079 38.7897 19.9405 38.3855 20.5527 37.9854C20.9014 37.7576 21.2076 37.534 21.4428 37.1708C22.1016 36.1552 23.0403 35.4412 24.0884 34.8913C25.7509 34.0173 27.537 33.5597 29.4022 33.4161C29.6799 33.3956 29.9637 33.4469 30.2658 33.4674C30.2496 33.9885 29.9313 34.0521 29.6535 34.1157C28.8852 34.2942 28.1026 34.4173 27.3424 34.6246C26.4523 34.8667 25.5684 35.1457 24.7007 35.4596C23.7864 35.79 23.0403 36.3932 22.4017 37.1257C21.4509 38.2152 21.611 39.4975 22.8072 40.308C23.5208 40.7922 24.3358 41.0117 25.169 41.1738C28.3033 41.7832 31.468 42.0438 34.6571 42.0438C35.4984 42.0438 36.3398 42.1094 37.1811 42.1381C37.5217 42.1484 37.8643 42.1402 38.2232 42.0376C37.021 41.4857 35.8187 40.9358 34.6145 40.3839C33.6636 39.7437 32.7067 39.1138 31.764 38.4634C30.7098 37.735 29.9516 36.8035 29.836 35.4514C29.8299 35.3817 29.7569 35.316 29.6819 35.195C29.4042 35.2504 29.1021 35.2709 28.8284 35.3714C27.7073 35.7879 26.5943 36.227 25.4812 36.664C24.6075 37.0067 24.1513 37.614 24.1351 38.607C24.1229 39.3498 24.0783 39.4442 24.794 39.5406C26.2212 39.7335 27.6525 39.8976 29.0879 40.0146C30.9348 40.1643 32.7797 40.2587 34.6246 40.3757ZM48.7877 43.9396C49.2013 43.8411 49.4344 43.7303 49.6635 43.7385C50.5353 43.7734 51.1597 43.3548 51.6848 42.7065C51.8044 42.5587 51.9423 42.4192 52.0883 42.2982C52.5099 41.9473 52.662 41.4816 52.5546 40.9666C52.4674 40.5439 52.3336 40.113 52.1288 39.7376C51.6706 38.8943 50.9448 38.2808 50.1238 37.8438C48.6803 37.0764 47.2084 36.3645 45.7224 35.6833C43.4152 34.6287 41.0757 33.6602 38.5942 33.0899C37.173 32.7636 35.7397 32.7082 34.2962 32.7965C33.465 32.8477 32.6966 33.135 32.0215 33.6295C31.7417 33.8346 31.3727 34.1014 31.318 34.3927C31.1984 35.0308 31.1538 35.7202 31.2795 36.3501C31.3525 36.7153 31.7579 37.0846 32.1046 37.3124C33.3818 38.1495 34.6591 38.9989 36.0052 39.7129C39.2673 41.4405 42.7807 42.3946 46.3995 42.9896C46.7218 43.043 47.0483 43.0922 47.3544 43.1948C47.4801 43.2358 47.6544 43.4287 47.6402 43.5272C47.6159 43.6872 47.4781 43.9191 47.3463 43.9519C47.0665 44.0217 46.7543 44.0176 46.4644 43.9827C45.5217 43.8698 44.583 43.7303 43.6443 43.601C43.3017 43.9519 42.9347 44.2515 42.5191 44.352C40.6621 44.8013 38.7665 44.9921 36.8588 45.0065C33.613 45.0291 30.4057 44.6064 27.2045 44.1222C25.6515 43.8883 24.0986 43.64 22.5456 43.3979C22.872 43.6236 23.2228 43.7529 23.5877 43.8083C25.4954 44.0996 27.4011 44.4176 29.317 44.6372C31.4214 44.8793 33.538 45.0209 35.6505 45.2096C37.7995 45.4025 39.9424 45.3307 42.0751 45.0209C43.3666 44.8321 44.6539 44.6105 45.9433 44.4135C46.2211 44.3705 46.5272 44.2432 46.7279 44.5059C46.6286 44.8321 46.4867 45.105 46.4725 45.3861C46.4441 45.9647 46.1359 46.3176 45.6575 46.5146C45.2845 46.6684 44.879 46.769 44.4776 46.8203C43.399 46.9557 42.3164 47.1055 41.2338 47.1506C37.9758 47.286 34.7158 47.4091 31.4538 47.4645C29.7164 47.4953 27.9749 47.3824 26.2374 47.3209C25.1244 47.2819 24.0094 47.2286 22.8984 47.1568C22.5497 47.1342 22.1949 47.0603 21.8624 46.9495C21.4752 46.8203 21.0515 46.6438 21.017 46.1596C20.9866 45.7267 21.4022 45.5933 21.7002 45.4271C22.0327 45.2425 22.3916 45.107 22.7382 44.9511C22.9247 44.867 23.1113 44.7849 23.2958 44.7028C23.2937 44.6433 23.2937 44.5838 23.2917 44.5243C22.7991 44.4382 22.28 44.2145 21.8178 44.3027C21.165 44.4258 20.5203 44.7193 19.9344 45.0516C19.1539 45.4948 19.0728 46.3484 19.7236 46.9823C19.9871 47.2409 20.3439 47.4358 20.6926 47.563C21.1751 47.7415 21.686 47.8482 22.1908 47.9549C25.2623 48.6012 28.3864 48.8105 31.5086 48.9315C35.6991 49.0957 39.8795 48.8782 44.0376 48.2852C45.7893 48.0349 47.545 47.8174 49.2317 47.2532C50.5779 46.8038 51.0421 45.8436 50.6306 44.3684C50.0913 44.272 49.4608 44.4792 48.7877 43.9396ZM42.8131 43.5395C42.8131 43.4841 42.8131 43.4287 42.8131 43.3712C41.6048 43.281 40.5567 42.5731 39.2085 42.8398C37.8177 43.1168 36.3377 43.0553 34.9064 42.9794C32.279 42.8378 29.6535 42.6039 27.0342 42.3515C26.0388 42.2551 25.0393 42.0725 24.0743 41.8119C22.4159 41.3605 21.0961 40.4844 20.7778 38.5455C20.052 38.8266 19.533 39.2903 19.1518 39.8997C18.8396 40.4003 18.8822 40.9337 19.3302 41.3195C19.7134 41.6498 20.1655 41.976 20.6399 42.1033C21.9496 42.4541 23.2755 42.7783 24.6156 42.9732C27.168 43.3466 29.7286 43.6667 32.2932 43.9232C33.8299 44.0771 35.3849 44.1304 36.9297 44.1099C38.284 44.0894 39.6362 43.9109 40.9865 43.7836C41.5967 43.7241 42.2049 43.6216 42.8131 43.5395ZM22.3287 45.9708C22.3226 46.0385 22.3165 46.1042 22.3105 46.1719C22.5943 46.2191 22.8781 46.2991 23.1619 46.3094C26.1462 46.4181 29.1325 46.5617 32.1188 46.6007C34.3448 46.6294 36.5729 46.531 38.7989 46.4674C40.1289 46.4304 41.4609 46.3812 42.7868 46.2765C43.4862 46.2211 44.1816 46.0611 44.8688 45.9072C45.1932 45.8354 45.5338 45.7144 45.7264 45.2425C45.4548 45.304 45.2743 45.3389 45.0979 45.384C43.4578 45.8128 41.7852 45.9647 40.0985 46.0324C35.545 46.2109 31.0321 45.7533 26.5375 45.1152C24.9724 44.8937 23.6587 45.3368 22.3287 45.9708Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.49761 16.0192C5.71859 15.6786 5.82807 15.4406 6.00039 15.26C8.63393 12.4696 11.7561 10.6312 15.6405 10.4896C17.382 10.426 19.1052 10.8056 20.7778 11.3165C21.5056 11.5381 22.2233 11.8069 22.9187 12.1167C24.2993 12.7322 25.5583 13.5386 26.5578 14.7163C26.3145 14.1459 25.5502 13.3129 24.719 12.6584C22.57 10.9677 20.0925 10.1408 17.4245 9.81666C16.0723 9.65252 14.7221 9.58892 13.3577 9.7469C11.2533 9.99311 9.44082 10.8795 7.84934 12.2357C6.60252 13.2985 5.43071 14.4516 4.2224 15.5616C3.99331 15.7729 3.75611 15.9761 3.52296 16.1833C3.47634 16.1443 3.42971 16.1074 3.38308 16.0684C3.44593 15.9063 3.47836 15.7237 3.57365 15.5862C6.22543 11.7289 9.72465 9.12932 14.4545 8.86259C18.5396 8.63279 22.42 9.54788 25.6759 12.289C27.835 14.1069 29.0879 16.4746 29.5704 19.2609C30.1645 22.6894 29.757 26.0195 28.4453 29.2161C27.3849 31.7972 25.4975 33.7074 23.1741 35.1355C21.8563 35.9459 20.4129 36.5471 19.014 37.218C18.7748 37.3329 18.4058 37.5996 18.2335 37.2036C18.0713 36.8282 18.4909 36.7215 18.7383 36.5881C19.9628 35.9315 21.2238 35.3386 22.4159 34.6246C24.3378 33.4735 25.9658 31.9901 27.1153 30.0183C27.5269 29.3125 27.8533 28.576 27.9404 27.7347C27.8796 27.8476 27.8066 27.9563 27.758 28.0733C26.7078 30.558 24.8386 32.2158 22.4869 33.3586C20.3095 34.4153 17.9699 34.9385 15.6141 35.3919C15.4823 35.4165 15.3404 35.433 15.2107 35.4104C14.9248 35.3632 14.8052 35.0472 15.0302 34.8626C15.2289 34.6984 15.4965 34.5917 15.752 34.5302C16.7292 34.2922 17.7327 34.1424 18.6937 33.8469C19.9385 33.4633 21.1914 33.0632 22.3693 32.5112C25.9638 30.8309 27.6221 27.8209 27.9283 23.9287C28.0742 22.0719 27.8857 20.2561 27.4539 18.4464C26.8903 16.0889 25.5076 14.429 23.4235 13.317C21.5968 12.3403 19.6202 11.8438 17.605 11.4827C14.6045 10.9472 11.8797 11.7248 9.35972 13.3293C8.39673 13.9428 7.5351 14.7142 6.61874 15.4016C6.32477 15.617 6.10784 15.9658 5.49761 16.0192ZM28.5061 18.2084C28.4534 18.2186 28.3986 18.231 28.3459 18.2412C28.5203 19.3615 28.6926 20.4817 28.8669 21.602C28.9055 21.5959 28.944 21.5897 28.9825 21.5856C28.8244 20.4612 28.6642 19.3348 28.5061 18.2084ZM28.8548 23.5573C28.8386 23.5594 28.8223 23.5614 28.8061 23.5635C28.8061 23.7112 28.8061 23.861 28.8061 24.0087C28.8223 24.0087 28.8386 24.0087 28.8548 24.0087C28.8548 23.8569 28.8548 23.7071 28.8548 23.5573Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M15.3283 25.0161C15.4965 25.5845 15.6486 26.1569 15.8371 26.7171C16.1635 27.6855 16.0784 28.5924 15.3648 29.331C14.5234 30.203 13.4854 30.6359 12.2568 30.4225C11.1195 30.2235 10.1788 29.6613 9.36986 28.8324C7.36278 26.7766 6.42817 22.4802 7.47226 19.8949C7.64458 19.4682 7.90206 19.0681 8.16764 18.6905C8.30956 18.4895 8.55486 18.3643 8.75355 18.2043C8.8022 18.2392 8.85086 18.272 8.89952 18.3069C8.86708 18.4751 8.86505 18.6577 8.79612 18.8075C7.52699 21.5302 7.71757 24.2057 9.08806 26.8176C9.71857 28.0179 10.6167 28.9843 11.977 29.3207C12.49 29.448 13.0617 29.4644 13.5868 29.3885C14.4626 29.2612 15.0282 28.5554 15.0262 27.6568C15.0262 27.2259 14.9086 26.7909 14.8295 26.3621C14.6775 25.527 14.4666 24.7002 14.3673 23.8589C14.1727 22.236 13.8645 20.652 13.1306 19.1789C13.0211 18.9573 12.9015 18.7398 12.7576 18.5387C11.9223 17.3713 11.083 17.2133 9.89089 17.9786C9.72262 18.0873 9.54422 18.1776 9.21376 18.3664C9.31715 18.0422 9.32121 17.8555 9.41446 17.7672C9.81385 17.402 10.2031 16.9958 10.6674 16.7373C11.3323 16.3659 11.9831 16.5382 12.5427 17.0532C13.2259 17.679 13.6496 18.4751 14.0064 19.3163C14.27 19.9401 14.5133 20.5741 14.7707 21.2163C14.7707 20.2581 14.7687 19.3327 14.7788 18.4095C14.7788 18.3643 14.8964 18.3192 15.0607 18.2002C15.1884 18.4915 15.3506 18.7377 15.4012 19.0045C15.6324 20.1924 15.8351 21.3845 16.0419 22.5786C16.2771 23.9431 16.64 25.2623 17.3171 26.479C17.9213 27.5624 19.4397 28.0856 20.5447 27.5398C20.8001 27.4126 21.0251 27.1787 21.2056 26.9468C21.9902 25.9435 22.3409 24.7617 22.5011 23.5163C22.7687 21.444 22.2517 19.6508 20.6562 18.2248C19.9425 17.5887 19.3039 16.8686 18.6106 16.2079C18.1138 15.7339 17.901 15.7339 17.3049 16.0704C17.0718 16.2018 16.8305 16.372 16.5771 16.411C15.8736 16.5177 15.4073 16.8234 15.3445 17.599C15.3343 17.7139 15.2289 17.8206 15.1194 18.0155C15.014 17.8144 14.9086 17.7036 14.9045 17.5887C14.8802 16.6224 15.1884 15.7955 16.0074 15.2415C16.7981 14.706 17.6516 14.7081 18.3632 15.3092C19.5735 16.3269 20.7514 17.3938 21.8624 18.5202C22.9329 19.6056 23.3424 20.9762 23.2512 22.5253C23.1336 24.5586 22.6936 26.4483 21.2299 27.9584C19.8614 29.37 18.1564 29.3331 16.936 27.7819C16.4534 27.1684 16.1412 26.4154 15.7723 25.7158C15.6486 25.4819 15.5837 25.2152 15.4905 24.9648C15.4377 24.9833 15.383 24.9997 15.3283 25.0161Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M9.33543 14.4024C9.25636 13.8361 9.6152 13.7356 9.90714 13.6515C10.9512 13.3519 11.9973 13.0318 13.0597 12.8184C14.8843 12.4553 16.7251 12.3835 18.57 12.6994C20.5487 13.038 22.3125 13.8505 23.8249 15.1821C25.24 16.4254 26.0348 18.034 26.3064 19.8929C26.8112 23.3543 25.8523 26.4504 23.829 29.21C22.0591 31.627 19.7702 33.4038 16.8123 34.0009C12.5447 34.8647 8.57922 33.9927 5.08406 31.3315C3.10942 29.8276 2.28225 27.6691 2.11804 25.2255C2.00451 23.5389 2.2113 21.8708 2.4708 20.2089C2.48702 20.1002 2.5154 19.9935 2.55189 19.8888C2.64718 19.6159 2.79112 19.3451 3.12361 19.4272C3.43379 19.5031 3.38311 19.8006 3.35473 20.0489C3.25133 20.9783 3.14591 21.9078 3.04251 22.8393C2.89046 24.2242 2.9898 25.5948 3.36689 26.9305C3.9386 28.9556 5.2503 30.4021 7.06073 31.3459C10.0328 32.895 13.1793 33.6418 16.5285 33.0468C19.0404 32.6016 21.086 31.3007 22.7058 29.3208C24.1939 27.5009 25.1772 25.4286 25.5218 23.0855C25.8726 20.7013 25.4874 18.4731 23.9628 16.5383C22.9755 15.2847 21.6111 14.6035 20.1716 14.0618C17.309 12.9846 14.42 13.0421 11.5169 13.8895C11.0202 14.0351 10.5255 14.187 10.0247 14.3142C9.80983 14.3737 9.57871 14.3737 9.33543 14.4024Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M10.5498 15.5698C10.7566 15.3544 10.8438 15.2169 10.9675 15.141C14.2417 13.1426 18.9938 12.804 22.2842 15.6129C23.7966 16.9055 24.6278 18.551 24.7028 20.5618C24.7494 21.8031 24.6501 23.03 24.419 24.257C23.8696 27.1746 22.3288 29.3659 19.7926 30.8247C16.7414 32.579 13.5564 33.096 10.264 31.5736C7.97915 30.5169 6.2782 28.8612 5.80177 26.2513C5.35576 23.8097 5.51592 21.3661 6.16062 18.9717C6.45053 17.8965 6.93507 16.9076 7.90009 16.2592C8.33597 15.9658 8.79212 15.7524 9.32126 15.8899C9.50575 16.2777 9.25233 16.448 9.03541 16.5937C7.78453 17.4328 7.24525 18.6926 6.97967 20.1165C6.65935 21.8339 6.61677 23.5738 6.77085 25.3014C6.92493 27.0125 7.69532 28.4324 9.06784 29.5136C12.0947 31.8998 15.8392 31.9183 19.1823 30.0553C22.0348 28.4672 23.4479 25.9374 23.8554 22.7325C24.0378 21.3025 23.9162 19.9155 23.3587 18.6044C22.2173 15.9227 20.0662 14.6691 17.2786 14.4598C15.6892 14.3408 14.1383 14.6629 12.6157 15.1123C12.119 15.258 11.6284 15.4242 11.1317 15.5596C10.9959 15.6006 10.8418 15.5698 10.5498 15.5698Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M11.7621 24.8418C11.6223 24.731 11.4824 24.6181 11.2715 24.4478C11.4783 24.3329 11.6243 24.255 11.7682 24.175C12.125 24.413 12.5224 24.6058 12.8265 24.8992C13.1083 25.1721 13.1995 25.5681 12.9948 25.96C12.8083 26.319 12.4697 26.4463 11.9487 26.3621C11.8554 26.3478 11.7662 26.3108 11.675 26.2842C11.6364 26.3375 11.5979 26.3909 11.5594 26.4442C11.7642 26.6166 11.973 26.7848 12.1737 26.9613C12.4656 27.2177 12.7778 27.2854 13.1488 27.1377C13.53 26.9859 13.6739 26.7007 13.7064 26.3149C13.7935 25.2911 13.3881 24.1585 11.7621 24.1811C11.6344 24.1401 11.5006 24.0518 11.379 24.0621C10.5295 24.1401 10.1747 23.4343 9.68004 22.9665C9.4915 22.79 9.55029 22.5397 9.76722 22.4022C10.0369 22.234 10.0673 21.9898 10.1119 21.7067C10.1767 21.3045 10.2842 20.9024 10.4221 20.5187C10.6795 19.8088 10.714 19.7985 11.3769 19.659C10.6491 19.5359 10.4423 19.6221 10.1524 20.2253C9.98009 20.5844 9.84021 20.9578 9.65166 21.4071C9.2989 20.3443 9.91319 18.9901 10.8012 18.6742C11.3526 18.4772 11.8554 18.5941 12.0946 19.1892C12.492 20.174 12.8184 21.1999 13.0394 22.2401C13.1225 22.6341 12.8306 23.1101 12.6927 23.6025C12.7454 23.6271 12.863 23.6825 12.9806 23.7359C14.1017 24.257 14.6491 25.4799 14.2984 26.6802C13.978 27.7758 13.0029 28.2641 12.0014 27.7512C10.8701 27.1705 10.343 26.1323 10.1585 24.9054C10.1342 24.7474 10.3288 24.5566 10.4221 24.3801C10.5559 24.493 10.7262 24.5833 10.8133 24.7248C10.937 24.93 10.9999 25.1721 11.1093 25.447C11.3506 25.2193 11.5574 25.0264 11.7642 24.8336C12.0379 25.0716 11.8696 25.6502 12.4717 25.7507C12.4352 25.2152 12.1717 24.969 11.7621 24.8418ZM11.1215 20.6726C10.6268 21.2594 10.8154 21.8113 11.085 22.3325C10.9228 22.4822 10.7991 22.5971 10.6613 22.7244C10.9836 22.9747 11.2857 23.2886 11.6304 23.0444C12.0196 22.7695 12.2852 22.355 12.2 21.7641C11.9568 21.9673 11.7621 22.1293 11.5695 22.2914C11.6162 21.68 11.5858 21.1486 11.1215 20.6726Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M0.954276 22.6259C0.954276 22.749 0.97455 22.8762 0.950221 22.9931C0.725185 24.1298 0.79006 25.2665 1.2077 26.3272C2.07946 28.5493 2.99988 30.755 3.96085 32.9401C4.43727 34.0255 5.28471 34.8195 6.32474 35.3673C8.81028 36.6784 11.3952 37.6325 14.2598 37.5484C14.5132 37.5401 14.7667 37.6038 15.0424 37.6366C15.014 38.1844 14.6693 38.2829 14.3652 38.3034C13.5279 38.3629 12.6663 38.5004 11.8533 38.365C9.38808 37.9567 7.085 37.0559 4.99682 35.6484C4.0683 35.0226 3.41549 34.1199 2.96136 33.1124C2.34099 31.7378 1.79968 30.3261 1.27257 28.9104C0.938057 28.0117 0.650173 27.0905 0.423109 26.159C0.19199 25.2131 0.226455 24.2447 0.500148 23.3009C0.571106 23.0526 0.698829 22.8228 0.800197 22.5828C0.852908 22.5992 0.903592 22.6135 0.954276 22.6259Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M18.6248 23.6804C18.9167 24.4129 19.2066 25.1475 19.5067 25.9025C20.0703 25.7691 20.3196 25.3834 20.3744 24.9546C20.4798 24.1441 20.6035 23.305 20.5122 22.5027C20.3419 20.9885 19.7054 19.6569 18.5822 18.5941C17.751 17.8083 17.1955 17.9314 16.7961 19.0045C16.7819 19.0455 16.715 19.066 16.6724 19.0968C16.2872 18.7213 16.2061 18.3459 16.4109 17.8945C16.6157 17.4472 17.1225 17.1415 17.6314 17.3056C18.1119 17.4615 18.6187 17.6852 18.9816 18.0237C19.4925 18.5018 19.977 19.0599 20.3055 19.6754C21.2766 21.4953 21.5219 23.4301 20.8833 25.4265C20.7434 25.8656 20.5447 26.3108 20.271 26.674C19.7378 27.3839 19.089 27.2608 18.7403 26.4134C18.4261 25.6522 18.1767 24.8623 17.8402 24.1113C17.4469 23.2332 16.9826 22.3899 16.569 21.522C16.417 21.2019 16.2812 20.8593 16.2203 20.5146C16.1899 20.3443 16.2974 20.0591 16.4352 19.9709C16.6805 19.8129 16.8184 20.057 16.9076 20.2643C17.1428 20.8121 17.3698 21.3661 17.6131 21.9488C17.6131 21.325 17.5868 20.7628 17.6212 20.2048C17.6516 19.6795 17.901 19.5441 18.3957 19.7205C19.7986 20.2171 20.3825 22.2627 19.4682 23.4568C19.235 23.7625 18.9613 23.8528 18.6126 23.6846C18.5781 23.5225 18.5437 23.3624 18.5112 23.2003C18.4281 23.2865 18.416 23.3624 18.4423 23.4199C18.493 23.5143 18.564 23.5943 18.6248 23.6804ZM18.3815 20.5925C18.2031 21.3148 18.4991 21.9406 18.7099 22.5704C18.7566 22.712 18.9593 22.7982 19.1032 22.9233C19.5756 21.9652 19.31 21.1342 18.3815 20.5925Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.8933 34.2737C32.8933 34.5179 32.9217 34.6779 32.8892 34.8216C32.7088 35.632 32.9541 36.3255 33.5583 36.8261C34.2273 37.3822 34.9308 37.9177 35.691 38.3301C38.9794 40.1233 42.5273 41.1574 46.1846 41.8181C46.955 41.9576 47.7498 41.9925 48.5343 41.9925C49.1831 41.9925 49.6068 41.5821 49.7122 40.9461C49.7447 40.7491 49.7183 40.4721 49.6028 40.3326C48.7756 39.3272 47.7072 38.644 46.507 37.9608C46.3266 39.1159 46.0873 40.109 44.9439 40.5645C44.7189 40.0638 45.0473 39.871 45.2379 39.6371C45.6271 39.1569 45.7893 38.6317 45.5926 38.0244C45.469 37.6427 45.2541 37.3616 44.8628 37.1954C42.0549 35.9952 39.2288 34.8523 36.2688 34.0829C35.9282 33.9947 35.5755 33.9496 35.2288 33.8757C34.728 33.769 34.2719 33.7772 33.8705 34.1937C33.7569 34.3107 33.4934 34.2819 33.2988 34.3189C33.2866 34.1158 33.2096 33.888 33.2724 33.7136C33.4468 33.2273 33.8522 32.9791 34.3408 32.9442C34.7422 32.9155 35.17 32.9052 35.5532 33.0078C37.1021 33.4243 38.6713 33.7977 40.1715 34.3538C42.3124 35.1478 44.4249 36.0383 46.5029 36.9903C47.5085 37.4519 48.437 38.1085 49.3493 38.7507C49.8055 39.0728 50.2069 39.5222 50.5272 39.99C51.0807 40.7984 50.8638 41.7401 50.0549 42.2961C49.4264 42.7291 48.7026 42.9301 47.9606 42.8316C43.6221 42.2551 39.391 41.2969 35.5309 39.0954C34.5111 38.5127 33.5319 37.8623 32.7575 36.9472C32.356 36.4732 32.06 35.9603 32.1391 35.3017C32.1938 34.8462 32.3743 34.4871 32.8933 34.2737Z\"\n      fill=\"#EE9D5B\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 64 / 50,\n  svg: Onion,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/thickBrushStroke.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Thick Brush Stroke', 'sticker name', 'web-stories');\n\nconst ThickBrush = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 60 28\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M59.9312 17.9401C59.8753 17.7516 59.7634 17.6102 59.4839 17.563C59.372 17.563 59.372 17.4688 59.372 17.4216C59.372 17.3274 59.428 17.2802 59.428 17.1859C59.428 17.1388 59.428 17.0917 59.372 17.0445C59.1484 16.9031 58.9247 16.7146 58.8129 16.5261C58.757 16.4318 58.6452 16.3846 58.5333 16.4318C58.4774 16.4789 58.3656 16.5261 58.3097 16.4318C58.2538 16.3375 58.3656 16.3375 58.4215 16.2904C58.5333 16.1961 58.4774 16.149 58.3097 16.0547L58.2538 16.0076L58.3097 15.9604C58.5333 16.0076 58.5892 15.7719 58.8129 15.7247C59.0925 15.6776 59.0925 15.5833 59.0366 15.3005C59.0366 15.2063 59.0366 15.2063 59.1484 15.1591C59.3161 15.112 59.4839 14.9706 59.372 14.782C59.2602 14.5935 59.4839 14.4521 59.372 14.2635C59.3161 14.1693 59.4839 14.1221 59.6516 14.1221C59.7075 14.1221 59.7075 14.075 59.7075 14.0279C59.7075 13.9807 59.6516 13.9336 59.5957 13.9807C59.5398 13.9807 59.4839 14.0279 59.4839 14.0279C59.428 14.0279 59.372 14.0279 59.372 13.9807C59.3161 13.9336 59.428 13.9336 59.428 13.8865C59.5398 13.8393 59.5957 13.7922 59.4839 13.6979C59.428 13.6508 59.3161 13.6979 59.3161 13.5565C59.2602 13.368 59.1484 13.038 58.9806 12.9909C58.8688 12.9438 58.8688 12.8966 58.8688 12.8024C58.8688 12.7081 58.8129 12.5667 58.6452 12.6138C58.4774 12.6609 58.4774 12.6138 58.4215 12.5667C58.4215 12.4253 58.3656 12.3781 58.1978 12.3781C57.9742 12.3781 57.8064 12.2839 57.5828 12.3781C57.5269 12.3781 57.415 12.331 57.471 12.331C57.5828 12.2839 57.5269 12.0953 57.6946 12.1425C57.8064 12.1896 57.9183 12.1425 58.086 12.2367C58.2538 12.331 58.2538 12.331 58.3097 12.1425C58.3097 12.001 58.2538 11.9068 58.0301 11.8596C57.7505 11.8125 57.471 11.7182 57.1914 11.7182C56.8559 11.7182 56.5204 11.7654 56.2408 11.5768C56.1849 11.5768 56.129 11.5297 56.129 11.5768C55.9053 11.7182 55.6258 11.624 55.4021 11.5768C55.2344 11.5768 55.1226 11.5297 54.9548 11.5768C54.7311 11.624 54.5075 11.624 54.2279 11.5768C54.172 11.5768 54.0602 11.5297 54.0043 11.5297C53.8365 11.624 53.6129 11.4826 53.4451 11.5297C53.2215 11.5768 52.9978 11.4826 52.8301 11.4354C52.7741 11.4354 52.6623 11.4354 52.6064 11.4354C52.4387 11.4826 52.2709 11.4354 52.1032 11.3883C51.9913 11.3412 52.2709 11.294 52.1032 11.2469C51.9913 11.1997 51.8236 11.1997 51.7677 11.294C51.7118 11.4354 51.5999 11.3883 51.4881 11.3883C51.3204 11.3883 51.2085 11.1997 51.0408 11.2469C51.0408 11.3412 50.929 11.3883 50.8731 11.3883C50.5376 11.3883 50.1462 11.3883 49.8107 11.294L49.7548 11.2469C49.8107 11.2469 49.8107 11.2469 49.8666 11.2469C49.9225 11.2469 50.0343 11.294 50.0903 11.2469C50.1462 11.1997 50.258 11.1997 50.1462 11.1526C50.0903 11.1055 50.0343 11.1526 49.9784 11.1055L50.0343 11.0583C50.2021 11.0112 50.3698 11.2469 50.5376 11.0583C50.5935 11.1997 50.929 11.0583 50.9849 11.2469H51.0408C51.0408 11.1997 51.0408 11.1055 51.0967 11.1055C51.2085 11.1055 51.3763 11.0112 51.4881 11.0583C51.5999 11.1055 51.7118 11.1055 51.8236 11.1055C52.0473 11.0112 52.2709 11.1997 52.4946 11.0583C52.6623 11.1997 52.886 11.1055 53.1096 11.1526C53.2215 11.1997 53.2774 11.294 53.3333 11.294C53.5569 11.1526 53.7806 11.3412 54.0043 11.294C54.172 11.2469 54.3397 11.294 54.4516 11.3883C54.5075 11.3883 54.5634 11.3883 54.6752 11.3412C54.9548 11.294 55.2344 11.1997 55.514 11.294C55.6817 11.3412 55.8494 11.1997 55.9054 11.294C56.0172 11.4354 56.1849 11.3412 56.2968 11.3412C56.6882 11.4354 57.0796 11.3883 57.415 11.5768C57.471 11.624 57.5269 11.624 57.5828 11.5768C57.6387 11.5768 57.6946 11.5297 57.7505 11.4826L57.6946 11.3883C57.5828 11.294 57.415 11.1997 57.3032 11.1055C57.3032 11.1055 57.1914 11.0583 57.1914 11.1526C57.1914 11.1997 57.3032 11.2469 57.1914 11.2469C57.0796 11.2469 56.9677 11.2469 56.9118 11.1526C56.9118 11.1526 56.9118 11.1526 56.9677 11.1526C57.1355 10.9641 57.1914 10.8698 57.1914 10.8227C57.1914 10.6341 57.1914 10.6341 57.415 10.6341C57.5828 10.6341 57.6946 10.7284 57.8624 10.6813C58.086 10.587 58.3097 10.587 58.5333 10.6813C58.757 10.7755 58.8129 10.587 58.9247 10.5399C58.9806 10.4927 58.9806 10.4456 58.9247 10.3984C58.8129 10.3513 58.7011 10.3042 58.6452 10.1628C58.5892 10.0214 58.3097 10.0685 58.1419 10.0214C58.0301 9.97422 57.9183 10.0214 57.8624 9.87995C57.5828 9.92709 57.415 9.92709 57.3032 9.87995C57.1914 9.87995 57.0796 9.87995 57.0236 9.83282C56.9118 9.69141 56.5763 9.73855 56.5763 9.50287C56.5763 9.45573 56.4086 9.26719 56.6882 9.31433C56.8559 9.31433 57.0236 9.31433 57.1355 9.26719C57.3591 9.17292 57.415 8.51303 57.2473 8.41875C57.1914 8.37162 57.1355 8.32448 57.0796 8.27735C57.0236 8.27735 57.0236 8.23021 56.9677 8.23021C57.0236 8.18308 57.0236 8.18308 57.0796 8.23021C57.1355 8.23021 57.2473 8.27735 57.3032 8.23021C57.415 8.18308 57.2473 8.13594 57.2473 8.04167C57.3032 7.99454 57.3032 7.99454 57.3591 7.99454C57.415 7.99454 57.471 7.99454 57.471 7.9474C57.2473 7.90026 57.3591 7.75886 57.3032 7.66459C57.2473 7.57032 57.1355 7.66459 57.0796 7.57032C56.9677 7.38177 56.7441 7.33464 56.5204 7.38177C56.4645 7.38177 56.4086 7.38177 56.3527 7.38177C56.2968 7.38177 56.2968 7.38177 56.2968 7.33464C56.2968 7.33464 56.2968 7.2875 56.3527 7.2875C56.4645 7.24037 56.8559 7.24037 56.9677 7.2875C57.0236 7.33464 57.1355 7.33464 57.1355 7.24037C57.1355 7.1461 57.1914 7.05183 57.0236 7.05183C56.8559 7.05183 56.7441 7.00469 56.5763 7.00469C56.5204 7.00469 56.4645 6.95756 56.4645 6.95756C56.4645 6.91042 56.5204 6.91042 56.5763 6.95756C56.6322 6.95756 56.6322 6.95756 56.6882 6.95756C56.9118 7.05183 57.0236 6.91042 57.1914 6.81615C57.2473 6.76901 57.2473 6.67474 57.1914 6.67474C56.9118 6.62761 56.6882 6.58047 56.4086 6.58047C56.2968 6.58047 56.1849 6.67474 56.0731 6.53334C56.1849 6.53334 56.2968 6.43907 56.4086 6.4862C56.5204 6.4862 56.5763 6.43907 56.6882 6.39193C56.7441 6.3448 56.7441 6.25052 56.8559 6.25052C56.8 6.20339 56.6882 6.15625 56.6322 6.06198H56.5763C56.4645 6.01485 56.5204 6.01485 56.5763 5.96771C56.6322 5.92058 56.6882 5.92058 56.6882 5.87344C56.6322 5.8263 56.6322 5.73203 56.5204 5.73203C56.3527 5.73203 56.1849 5.6849 56.0172 5.63776C55.9613 5.63776 55.8494 5.63776 55.8494 5.59063C55.8494 5.44922 55.7935 5.44922 55.6817 5.40209L55.6258 5.35495L55.6817 5.30782C55.7376 5.30782 55.8494 5.35495 55.9054 5.30782C56.0172 5.26068 56.0731 5.21354 55.9054 5.07214C55.7935 5.07214 55.6258 4.93073 55.7376 4.74219C55.7935 4.64792 55.6817 4.64792 55.6258 4.55365C55.514 4.45938 55.4021 4.50651 55.2344 4.50651C55.1785 4.50651 55.0666 4.45938 55.1785 4.41224C55.2344 4.36511 55.1785 4.36511 55.1226 4.36511H54.7871C54.6752 4.45938 54.6193 4.45938 54.5075 4.41224C54.0602 4.27084 53.6129 4.41224 53.1655 4.41224C52.9419 4.41224 52.6623 4.41224 52.4946 4.31797C52.3268 4.2237 52.215 4.17656 52.0473 4.17656C51.8795 4.17656 51.7677 4.03516 51.5999 3.98802C50.6494 3.94089 49.7548 3.61094 48.8042 3.46953C48.4128 3.4224 48.301 3.32813 48.301 2.99818C48.301 2.95104 48.301 2.90391 48.2451 2.85677C47.9655 2.85677 47.7418 2.66823 47.4623 2.66823C47.2386 2.66823 47.015 2.62109 46.8472 2.57396C46.7913 2.57396 46.7354 2.57396 46.7354 2.52682C46.7354 2.47969 46.8472 2.47969 46.9031 2.47969C47.1268 2.52682 47.3505 2.43255 47.5741 2.47969C47.63 2.47969 47.6859 2.43255 47.7419 2.38542C47.6859 2.33828 47.6859 2.29115 47.5741 2.24401C47.4623 2.24401 47.3504 2.19688 47.2386 2.19688C47.1827 2.19688 47.015 2.19688 47.015 2.14974C47.0709 2.05547 47.1827 2.14974 47.2386 2.14974C47.2945 2.14974 47.3505 2.14974 47.3505 2.14974C47.5182 2.05547 47.5182 2.00833 47.4064 1.91406C47.2945 1.72552 47.0709 1.67839 46.8472 1.67839C46.7354 1.67839 46.6236 1.63125 46.5117 1.72552C46.4558 1.58412 46.3999 1.48984 46.2881 1.58412C46.2881 1.58412 46.2322 1.58412 46.2322 1.53698C46.2322 1.44271 46.2322 1.39557 46.1203 1.39557C45.9526 1.39557 45.7848 1.25417 45.6171 1.39557C45.5053 1.3013 45.2816 1.3013 45.1139 1.25417C45.058 1.25417 45.002 1.25417 44.9461 1.25417C44.6106 1.3013 44.2192 1.39557 43.9397 1.1599C43.8838 1.11276 43.8278 1.11276 43.7719 1.1599C43.6042 1.25417 43.4364 1.20703 43.3246 1.1599C43.1569 1.11276 42.9891 1.20703 42.8214 1.1599C42.43 1.06563 41.9827 1.1599 41.5913 1.06563C41.5354 1.06563 41.5354 1.01849 41.4794 1.06563C41.3676 1.1599 41.1999 1.11276 41.088 1.06563C40.9203 1.01849 40.8085 1.1599 40.6966 1.06563C40.4171 0.971354 40.1375 1.06563 39.9138 1.01849C39.802 0.971354 39.5784 1.01849 39.4665 1.06563C39.2429 1.20703 39.0751 1.1599 38.9074 1.06563C38.6837 0.971354 38.6278 0.924219 38.516 1.11276H38.4041C38.2923 0.971354 38.1246 0.971354 38.0127 0.971354C37.845 0.924219 37.7332 0.877084 37.6213 0.971354C37.4536 1.11276 37.3977 0.829948 37.2299 0.924219C37.0063 1.06563 36.7826 0.924219 36.5031 0.877084C36.3353 0.877084 36.1676 0.782813 36.0557 0.924219C35.9998 0.971354 35.9439 0.924219 35.9439 0.877084C35.888 0.829948 35.7762 0.829948 35.7203 0.877084C35.6084 0.971354 35.4407 0.924219 35.3289 0.877084C35.1611 0.735677 35.217 1.06563 35.0493 0.924219C34.9375 0.829948 34.7697 0.877084 34.6579 0.829948C34.5461 0.829948 34.4342 0.782813 34.3224 0.782813C34.0428 0.877084 33.8192 0.782813 33.5955 0.735677C33.4837 0.735677 33.3159 0.594271 33.26 0.829948C33.26 0.877084 33.2041 0.877084 33.1482 0.924219C33.0364 0.924219 33.0364 0.877084 33.0364 0.829948C33.0364 0.641406 32.8686 0.688542 32.7568 0.735677C32.5891 0.735677 32.4213 0.924219 32.2536 0.688542C32.2536 0.688542 32.1977 0.688542 32.1417 0.688542C32.0299 0.924219 31.9181 0.735677 31.8062 0.688542C31.6385 0.688542 31.3589 0.594271 31.0794 0.641406C30.9675 0.641406 30.7998 0.735677 30.688 0.688542C30.5202 0.547135 30.2966 0.641406 30.1288 0.641406C29.9611 0.594271 29.7374 0.641406 29.5697 0.594271L29.5138 0.641406C29.4578 0.829948 29.2901 0.735677 29.2342 0.688542C29.0664 0.641406 29.0105 0.829948 28.8987 0.735677C28.7869 0.688542 29.0664 0.641406 28.8987 0.594271C28.7869 0.547135 28.675 0.5 28.5632 0.547135C28.4514 0.641406 28.2836 0.5 28.1159 0.594271C28.0041 0.735677 27.8363 0.688542 27.7245 0.547135H27.6686C27.5568 0.735677 27.4449 0.641406 27.3331 0.547135C27.2213 0.547135 27.0535 0.5 26.9417 0.547135C26.774 0.594271 26.6621 0.547135 26.5503 0.547135C26.4385 0.5 26.3266 0.594271 26.1589 0.547135C26.0471 0.5 25.8793 0.547135 25.7675 0.547135C25.5998 0.547135 25.3761 0.641406 25.3202 0.547135C25.1524 0.405729 25.0965 0.688542 24.9847 0.594271C24.8729 0.547135 24.761 0.641406 24.7051 0.594271C24.5374 0.5 24.3696 0.547135 24.2578 0.5C24.2578 0.547135 24.2019 0.547135 24.146 0.547135C23.9782 0.547135 23.8664 0.594271 23.6987 0.594271C23.5868 0.594271 23.4191 0.594271 23.3073 0.641406C23.1954 0.5 23.0277 0.641406 22.9159 0.594271C22.7481 0.594271 22.5804 0.547135 22.4126 0.641406C22.3008 0.641406 22.1331 0.5 21.9653 0.641406C21.7417 0.547135 21.4062 0.782813 21.1825 0.547135C21.1825 0.5 21.1266 0.547135 21.1266 0.594271C21.1266 0.829948 21.1266 0.829948 20.9029 0.782813C20.5115 0.735677 20.1761 0.641406 19.7287 0.688542C19.4492 0.735677 19.1696 0.735677 18.89 0.877084C18.89 0.877084 18.8341 0.877084 18.7782 0.877084C18.6664 0.688542 18.4427 0.782813 18.2191 0.782813C17.9395 0.782813 17.6599 0.782813 17.3244 0.829948C17.1567 0.829948 17.0448 0.924219 16.8771 0.924219C16.4298 0.829948 15.9825 0.971354 15.4792 0.971354C15.3674 0.971354 15.2556 0.924219 15.0878 0.971354C14.6405 1.11276 14.1373 1.1599 13.6341 1.20703V1.25417C13.6341 1.25417 13.6341 1.25417 13.69 1.25417C13.69 1.25417 13.69 1.3013 13.7459 1.3013H13.69L13.6341 1.25417V1.20703C13.5782 1.20703 13.5222 1.20703 13.4663 1.1599C13.1868 1.06563 12.9631 1.1599 12.7954 1.3013C12.6835 1.34844 12.7954 1.34844 12.8513 1.39557L12.9072 1.44271C12.7954 1.53698 12.5158 1.58412 12.4599 1.48984C12.404 1.44271 12.404 1.39557 12.348 1.39557C12.2362 1.34844 12.1803 1.3013 12.1803 1.39557C12.1803 1.44271 12.1803 1.48984 12.1244 1.53698C12.2921 1.53698 12.4599 1.72552 12.6276 1.72552C12.8513 1.67839 13.0749 1.72552 13.2427 1.63125C13.3545 1.58412 13.4663 1.67839 13.5782 1.58412C13.7459 1.48984 13.8577 1.63125 13.9696 1.58412C14.0814 1.53698 14.1932 1.44271 14.305 1.44271C14.6405 1.44271 14.9201 1.3013 15.1997 1.34844C15.3115 1.25417 15.4792 1.53698 15.5911 1.34844C15.7588 1.44271 15.9266 1.34844 16.0384 1.3013C16.2061 1.3013 16.3739 1.3013 16.4857 1.3013C16.6535 1.3013 16.7653 1.11276 16.9889 1.20703C17.1567 1.20703 17.2685 1.20703 17.3803 1.25417C17.4922 1.3013 17.604 1.25417 17.7158 1.20703C17.9954 1.11276 18.275 1.25417 18.5545 1.06563C18.5545 1.06563 18.6105 1.06563 18.6664 1.06563C18.89 1.3013 19.1137 1.11276 19.3373 1.06563C19.3933 1.06563 19.3933 1.01849 19.4492 1.01849C19.561 1.06563 19.6728 1.20703 19.8406 1.1599C19.9524 1.11276 20.0642 1.06563 20.1761 1.06563C20.5675 1.01849 20.9589 1.01849 21.3503 1.01849C21.6857 1.01849 22.0212 0.971354 22.3567 0.971354C22.5804 0.971354 22.7481 1.06563 22.9718 0.971354C23.0836 0.924219 23.2513 1.06563 23.4191 0.971354C23.5309 1.11276 23.7546 0.971354 23.8664 1.01849C23.9782 1.01849 24.146 0.971354 24.3137 0.924219C24.5933 0.877084 24.817 0.924219 25.0965 0.971354C25.2084 0.971354 25.432 1.11276 25.5998 0.924219C25.7675 1.06563 25.8793 0.782813 26.0471 0.877084C26.2148 0.971354 26.3826 0.877084 26.5503 0.877084C26.8299 0.924219 27.0535 0.877084 27.3331 0.829948C27.6686 0.829948 27.9482 0.924219 28.2836 0.782813C28.3396 0.782813 28.3955 0.782813 28.3955 0.829948C28.4514 0.971354 28.5632 1.06563 28.731 0.924219C28.731 0.924219 28.8428 0.877084 28.8428 0.924219C29.1783 1.01849 29.5138 0.924219 29.7933 1.01849C29.9611 1.06563 30.0729 0.924219 30.2406 1.01849C30.3525 1.06563 30.5202 1.11276 30.632 1.01849C30.632 1.01849 30.688 1.01849 30.7439 1.01849C31.1353 1.1599 31.5826 1.01849 31.974 1.11276C32.1417 1.1599 32.3095 1.01849 32.4772 1.11276C32.8127 1.01849 33.0364 1.06563 33.26 1.20703C33.3159 1.25417 33.3159 1.20703 33.4278 1.11276C33.4837 1.06563 33.4837 1.06563 33.5396 1.06563C33.9869 1.1599 34.3783 1.11276 34.8256 1.1599C35.1611 1.20703 35.5525 1.1599 35.9439 1.20703C36.1117 1.06563 36.1676 1.20703 36.2794 1.25417C36.4471 1.1599 36.6708 1.3013 36.8945 1.20703C37.0622 1.1599 37.2299 1.20703 37.3418 1.25417C37.4536 1.3013 37.5095 1.44271 37.6213 1.25417C37.6213 1.20703 37.7332 1.25417 37.7891 1.25417C38.0687 1.3013 38.4041 1.39557 38.6837 1.25417C38.7955 1.20703 38.7955 1.34844 38.9074 1.34844C39.2429 1.34844 39.6343 1.34844 39.9697 1.39557C40.1375 1.39557 40.2493 1.44271 40.4171 1.44271C40.5289 1.39557 40.6407 1.53698 40.8085 1.53698C40.9762 1.53698 41.144 1.44271 41.3117 1.53698L41.3676 1.58412L41.3117 1.63125C41.1999 1.53698 41.088 1.67839 40.9203 1.63125C40.7526 1.53698 40.473 1.48984 40.3052 1.67839C40.2493 1.72552 40.1375 1.67839 40.0816 1.63125C39.9138 1.48984 39.7461 1.63125 39.6343 1.58412C39.5784 1.67839 39.4106 1.58412 39.4106 1.67839C39.4106 1.72552 39.5784 1.72552 39.6902 1.67839C39.7461 1.63125 39.802 1.77266 39.9138 1.77266C40.0816 1.81979 40.1375 1.67839 40.3052 1.72552C40.3612 1.72552 40.4171 1.72552 40.4171 1.81979C40.4171 1.86693 40.3612 1.91406 40.3052 1.91406C40.2493 1.91406 40.2493 1.91406 40.1934 1.91406C40.1375 1.91406 40.0816 1.91406 40.0816 1.9612C40.0816 2.00833 40.0816 2.05547 40.1375 2.05547C40.1934 2.05547 40.2493 2.05547 40.2493 2.10261C40.2493 2.14974 40.1934 2.14974 40.1375 2.14974C40.0257 2.10261 39.8579 2.19688 39.8579 1.9612C39.8579 1.81979 39.4665 1.81979 39.3547 1.9612C39.2429 2.10261 39.131 2.19688 38.9633 2.14974C38.6837 2.00833 38.3482 2.14974 38.0687 2.10261C37.9009 2.24401 37.845 2.05547 37.7332 2.05547C37.6213 2.05547 37.5095 2.10261 37.4536 2.14974C37.3977 2.14974 37.3977 2.10261 37.3418 2.10261C37.0622 1.9612 36.7826 1.86693 36.5031 2.05547C36.4471 2.10261 36.3912 2.05547 36.3353 2.05547C36.1676 2.05547 35.9998 1.9612 35.8321 2.05547C35.6643 1.86693 35.4966 2.00833 35.3848 1.9612C34.9375 1.91406 34.5461 1.86693 34.1547 1.9612C34.0987 1.9612 34.0428 1.9612 33.9869 1.9612C33.8751 1.9612 33.7633 1.86693 33.6514 1.86693C33.5955 1.81979 33.4837 1.91406 33.3719 1.91406C33.26 1.91406 33.2041 1.9612 33.0923 1.86693C32.8686 1.72552 32.5331 1.77266 32.3095 1.81979C32.1977 1.81979 32.0858 1.81979 31.9181 1.81979C31.6944 1.81979 31.5267 1.67839 31.303 1.77266C31.1353 1.81979 30.9116 1.67839 30.7439 1.77266C30.688 1.77266 30.632 1.77266 30.5761 1.72552C30.1847 1.72552 29.7374 1.72552 29.346 1.77266C29.2342 1.77266 29.1224 1.77266 29.0105 1.72552C28.8987 1.67839 28.731 1.58412 28.5632 1.72552C28.1718 1.67839 27.7804 1.77266 27.3331 1.67839C27.2213 1.67839 27.1094 1.58412 26.9976 1.67839C26.9417 1.72552 26.8299 1.67839 26.774 1.72552C26.718 1.81979 26.718 1.63125 26.6062 1.67839C26.6062 1.72552 26.4944 1.72552 26.4385 1.72552C26.3826 1.72552 26.2707 1.72552 26.2148 1.67839C26.0471 1.63125 25.8234 1.63125 25.6557 1.67839C25.5438 1.72552 25.4879 1.72552 25.3761 1.72552C25.1524 1.67839 24.9288 1.63125 24.7051 1.72552C24.4815 1.77266 24.2578 1.63125 24.0901 1.72552C23.6987 1.67839 23.3073 1.77266 22.9159 1.77266C22.5245 1.77266 22.189 1.86693 21.7976 1.77266C21.7417 1.77266 21.6857 1.77266 21.6857 1.77266C21.2943 1.86693 20.847 1.81979 20.4556 1.81979C19.9524 1.81979 19.4492 1.86693 18.9459 1.91406C18.7782 2.05547 18.5545 1.91406 18.3868 1.9612C18.2191 2.00833 18.0513 2.00833 17.8836 2.00833C17.4922 2.05547 17.0449 2.00833 16.6535 2.05547C16.5416 2.05547 16.4857 2.05547 16.3739 2.10261L16.318 2.14974C15.9266 2.05547 15.5911 2.29115 15.2556 2.19688C15.1438 2.14974 15.0319 2.19688 14.8642 2.24401C14.6405 2.29115 14.4169 2.33828 14.1373 2.33828C13.9136 2.33828 13.6341 2.43255 13.4104 2.38542L13.3545 2.43255C12.9631 2.57396 12.5158 2.62109 12.1244 2.66823C11.9566 2.71537 11.8448 2.7625 11.6771 2.71537C11.6212 2.66823 11.5093 2.71537 11.4534 2.71537C11.2298 2.7625 11.062 2.85677 10.8943 2.66823C10.8943 2.62109 10.7824 2.62109 10.7265 2.66823C10.5588 2.66823 10.447 2.7625 10.3351 2.80964C10.2233 2.66823 10.1115 2.7625 9.99964 2.80964C9.88781 2.85677 9.77598 2.85677 9.77598 2.99818C9.77598 3.04531 9.72007 3.04531 9.66415 3.09245C9.49641 3.13959 9.32866 3.09245 9.16092 3.18672C9.10501 2.95104 8.88135 3.04531 8.76952 2.95104C8.76952 2.95104 8.71361 2.90391 8.71361 2.85677C8.71361 2.80964 8.76952 2.80964 8.82543 2.80964C8.99318 2.85677 9.21684 2.90391 9.38458 2.90391C9.60824 2.95104 9.60824 2.95104 9.72007 2.7625C9.77598 2.66823 9.83189 2.57396 9.88781 2.57396C10.1674 2.57396 10.447 2.52682 10.6706 2.43255C10.7824 2.38542 10.8943 2.47969 11.0061 2.43255C11.4534 2.24401 11.9007 2.24401 12.404 2.19688C12.4599 2.19688 12.4599 2.19688 12.7394 2.14974V2.10261C12.7394 2.10261 12.7394 2.10261 12.7394 2.05547C12.7394 2.05547 12.7954 2.05547 12.7954 2.10261C12.8513 2.14974 12.8513 2.10261 12.9072 2.10261C13.2427 2.05547 13.5782 2.05547 13.9136 1.9612C14.2491 1.9612 14.5846 1.91406 14.976 1.86693C15.3115 1.81979 15.7029 1.72552 16.0943 1.81979C16.1502 1.81979 16.2061 1.77266 16.2061 1.77266C16.6535 1.63125 17.1567 1.72552 17.604 1.63125C17.9395 1.58412 18.3309 1.58412 18.6664 1.58412C19.2255 1.53698 19.7287 1.53698 20.2879 1.48984C20.5115 1.48984 20.7352 1.39557 20.9029 1.39557C21.2943 1.44271 21.6857 1.44271 22.0212 1.39557C22.3567 1.34844 22.6363 1.48984 22.9718 1.39557C23.2513 1.3013 23.5868 1.25417 23.9223 1.39557C23.9782 1.39557 24.0342 1.34844 24.0901 1.34844C24.2578 1.3013 24.4815 1.25417 24.6492 1.34844C24.7051 1.34844 24.817 1.34844 24.8729 1.34844C25.0965 1.3013 25.3202 1.3013 25.5438 1.3013C25.8234 1.3013 26.103 1.34844 26.3826 1.34844C26.4385 1.34844 26.4944 1.39557 26.5503 1.34844C26.6062 1.3013 26.718 1.1599 26.774 1.3013C26.8858 1.25417 26.9976 1.25417 27.1094 1.25417C27.389 1.25417 27.6686 1.20703 27.8922 1.3013C28.06 1.1599 28.2836 1.34844 28.4514 1.20703C28.675 1.25417 28.8428 1.20703 29.0664 1.20703C29.2342 1.20703 29.4578 1.25417 29.6256 1.3013C29.6815 1.3013 29.6815 1.3013 29.7374 1.3013L29.7933 1.25417C29.7933 1.25417 29.7933 1.20703 29.7933 1.1599C29.7374 1.1599 29.6815 1.11276 29.6815 1.11276C29.346 1.1599 28.9546 1.25417 28.6191 1.11276C28.4514 1.20703 28.2836 1.1599 28.1718 1.11276C28.0041 1.06563 27.8363 1.20703 27.7245 1.1599C27.5568 1.06563 27.389 1.25417 27.2772 1.06563C27.0535 1.25417 26.774 0.971354 26.4944 1.11276C26.103 1.11276 25.6557 1.06563 25.2643 1.1599C25.1524 1.01849 24.9847 1.11276 24.8729 1.11276C24.7051 1.11276 24.5374 1.11276 24.3696 1.1599C24.2019 1.20703 24.0342 1.1599 23.8664 1.11276C23.8664 1.11276 23.8664 1.11276 23.8105 1.11276C23.5309 1.25417 23.1395 1.1599 22.804 1.20703C22.5245 1.20703 22.2449 1.20703 22.0212 1.20703C21.6298 1.20703 21.2943 1.25417 20.9589 1.34844C20.847 1.34844 20.7352 1.3013 20.5675 1.34844C20.1201 1.39557 19.6728 1.44271 19.2814 1.34844C19.2255 1.34844 19.1696 1.34844 19.1137 1.34844C18.4427 1.44271 17.8277 1.34844 17.2685 1.48984C16.9889 1.53698 16.7094 1.53698 16.4298 1.53698C16.2061 1.53698 15.9266 1.53698 15.7588 1.58412C15.4233 1.67839 15.1438 1.67839 14.8083 1.67839C14.7524 1.67839 14.6405 1.63125 14.5846 1.67839C14.4728 1.81979 14.361 1.67839 14.2491 1.72552C14.1373 1.77266 13.9696 1.86693 13.8577 1.77266C13.8018 1.72552 13.69 1.77266 13.6341 1.81979C13.4663 1.91406 13.2986 1.9612 13.0749 1.91406C12.9072 1.86693 12.9072 2.05547 12.7394 2.05547C12.404 2.05547 12.348 2.05547 12.2921 2.05547C12.2362 2.05547 12.1803 2.00833 12.1244 2.05547C11.9007 2.19688 11.5652 2.14974 11.2857 2.24401L11.2298 2.29115C10.7824 2.14974 10.447 2.33828 10.0556 2.38542C9.66415 2.43255 9.27275 2.52682 8.88135 2.62109C8.71361 2.66823 8.65769 2.52682 8.60178 2.47969C8.54586 2.43255 8.60178 2.33828 8.71361 2.38542C8.76952 2.38542 8.82543 2.38542 8.82543 2.33828C8.82543 2.24401 8.76952 2.24401 8.71361 2.24401C8.65769 2.24401 8.54586 2.24401 8.54586 2.14974C8.48995 2.14974 8.48995 2.14974 8.43403 2.14974C8.37812 2.14974 8.32221 2.10261 8.21038 2.19688C8.09855 2.29115 8.21038 2.43255 8.04263 2.47969C8.15446 2.52682 8.26629 2.57396 8.21038 2.71537C8.43403 2.7625 8.37812 3.09245 8.71361 3.04531C8.76952 3.04531 8.82543 3.04531 8.82543 3.13958C8.82543 3.18672 8.76952 3.23386 8.71361 3.23386C8.65769 3.28099 8.54586 3.23386 8.48995 3.23386C8.3222 3.23386 8.15446 3.37526 8.04263 3.51667C8.04263 3.5638 8.04263 3.5638 8.09855 3.61094C8.15446 3.61094 8.21038 3.70521 8.09855 3.70521C7.98672 3.70521 7.87489 3.75235 7.76306 3.75235C7.48349 3.79948 7.148 3.89375 6.81252 3.94089C6.64477 3.94089 6.53294 4.08229 6.3652 4.03516C6.19746 3.98802 6.08563 4.12943 5.91789 4.12943C5.5824 4.12943 5.24691 4.2237 4.91143 4.31797C4.85551 4.31797 4.74368 4.36511 4.68777 4.41224C4.63186 4.60078 4.24045 4.60078 4.24045 4.8836C4.07271 4.93073 3.84905 4.97787 3.6254 5.025C3.56948 5.025 3.51357 5.07214 3.51357 5.07214C3.40174 5.16641 3.40174 5.30782 3.40174 5.40209C3.40174 5.44922 3.45765 5.54349 3.6254 5.54349C3.79314 5.54349 3.90497 5.63776 4.07271 5.6849C4.24045 5.77917 4.35228 5.63776 4.52003 5.6849C4.63186 5.73203 4.7996 5.73203 4.91143 5.73203C5.02326 5.77917 5.13508 5.8263 5.24691 5.92058C5.30283 6.01485 5.191 6.01485 5.191 6.06198C5.191 6.15625 5.24691 6.15625 5.30283 6.20339C5.35874 6.20339 5.41466 6.20339 5.41466 6.25052C5.41466 6.29766 5.35874 6.29766 5.30283 6.29766C5.07917 6.29766 4.96734 6.43907 4.85551 6.58047C4.7996 6.72188 4.68777 6.81615 4.85551 6.86329C4.96734 6.86329 4.96734 6.91042 4.91143 7.00469C4.85551 7.1461 4.96734 7.24037 5.191 7.24037C5.35874 7.24037 5.52649 7.33464 5.69423 7.2875C5.80606 7.24037 5.91789 7.2875 6.08563 7.33464L6.14154 7.38177C6.08563 7.38177 6.08563 7.38177 6.02972 7.42891C5.86197 7.42891 5.63831 7.42891 5.47057 7.47605C5.41466 7.47605 5.30283 7.52318 5.30283 7.57032C5.30283 7.61745 5.41466 7.61745 5.41466 7.66459C5.63831 7.71172 5.80606 7.85313 6.02972 7.71172C6.08563 7.71172 6.14154 7.71172 6.19746 7.75886C6.25337 7.75886 6.30929 7.80599 6.30929 7.80599C6.30929 7.85313 6.25337 7.85313 6.19746 7.90026C6.14154 7.9474 6.08563 7.90026 6.08563 7.90026C5.80606 7.85313 5.63831 7.90026 5.41466 7.99454C5.07917 8.13594 4.74368 8.18308 4.4082 8.23021C4.07271 8.23021 3.73722 8.37162 3.34582 8.37162C3.12217 8.41875 2.89851 8.41875 2.67485 8.51303C2.17162 8.70157 1.66839 8.79584 1.16516 8.93724C0.773762 9.03152 0.438276 9.22006 0.102789 9.4086C0.046875 9.4086 0.046875 9.45573 0.046875 9.45573C0.270533 9.4086 0.214618 9.69141 0.382361 9.69141C0.49419 9.69141 0.49419 9.73855 0.49419 9.83282C0.550104 9.87995 0.606019 9.92709 0.661933 9.92709C0.885591 9.83282 0.885591 9.92709 0.885591 10.0685C0.885591 10.1628 0.885591 10.2099 0.99742 10.2099C1.16516 10.257 1.27699 10.3042 1.27699 10.0685C1.50065 10.0214 1.66839 9.92709 1.89205 9.87995C1.89205 9.87995 1.94796 9.87995 1.94796 9.92709C2.05979 10.1628 2.33937 10.1628 2.50711 10.1156C2.84259 10.0685 3.17808 10.0685 3.45765 10.0685C4.0168 10.0214 4.57594 9.92709 5.191 9.87995C5.5824 9.83282 5.9738 9.83282 6.30929 9.73855C6.42112 9.69141 6.64477 9.64428 6.81252 9.73855C6.81252 9.64428 6.86843 9.64428 6.92435 9.69141C6.98026 9.69141 6.98026 9.73855 6.98026 9.78568C7.09209 9.83282 7.25983 9.78568 7.25983 9.87995C7.25983 9.97422 7.48349 10.1156 7.25983 10.2099C7.20392 10.257 7.25983 10.257 7.25983 10.3042C7.37166 10.4456 7.59532 10.4456 7.65123 10.6341C7.65123 10.6341 7.76306 10.6341 7.76306 10.6813C7.87489 10.7284 7.87489 10.7755 7.76306 10.8698C7.76306 10.7755 7.70715 10.7755 7.59532 10.8227C7.03617 10.9641 6.47703 11.1055 5.91789 11.1997C5.75014 11.2469 5.52649 11.3412 5.35874 11.4826C5.24691 11.624 5.07917 11.8125 4.85551 11.8596C4.57594 11.9068 4.4082 12.0482 4.12863 12.0953C4.0168 12.1425 3.84905 12.1896 3.84905 12.2839C3.84905 12.4724 3.68131 12.4253 3.56948 12.4724C3.51357 12.4724 3.45765 12.4724 3.51357 12.5667C3.73722 12.8495 3.34582 12.7081 3.28991 12.8024C2.89851 12.7552 2.73077 12.9438 2.56302 13.1323C2.45119 13.2266 2.45119 13.2737 2.61894 13.2737C2.78668 13.3208 2.95442 13.3208 3.12217 13.368C3.28991 13.4622 3.40174 13.5094 3.45765 13.5094C3.6254 13.6037 3.79314 13.4151 3.96088 13.5094C4.12863 13.5565 4.24045 13.6979 4.4082 13.7451C4.46411 13.7451 4.46411 13.7451 4.52003 13.7451C4.57594 13.8393 4.74368 13.8865 4.52003 13.9807C4.52003 14.0279 4.46411 14.1221 4.52003 14.1693C4.52003 14.3578 4.52003 14.3578 4.46411 14.405C4.29637 14.4521 4.18454 14.5464 4.0168 14.6406C3.96088 14.6406 3.96088 14.6878 3.96088 14.7349C3.96088 14.782 4.0168 14.782 4.07271 14.782C4.29637 14.8763 4.52003 14.7349 4.74368 14.782C4.7996 14.6406 4.96734 14.782 5.07917 14.7349C5.07917 14.7349 5.07917 14.7349 5.07917 14.6878C5.07917 14.6878 5.13508 14.6878 5.13508 14.6406V14.6878L5.07917 14.7349H5.02326C4.96734 14.8763 4.7996 14.7349 4.68777 14.782C4.63186 14.9234 4.46411 14.9234 4.29637 14.9234C4.24045 14.9234 4.18454 15.0177 4.24045 15.0649C4.24045 15.112 4.29637 15.2063 4.4082 15.2063C4.57594 15.1591 4.7996 15.2534 4.96734 15.1591C5.35874 15.0177 5.75014 15.1591 6.08563 15.2063L6.14154 15.2534L6.08563 15.3005C6.02972 15.3005 6.02971 15.3477 5.9738 15.3477C5.63831 15.3477 5.30283 15.3948 5.02326 15.5362C4.96734 15.5362 4.91143 15.5362 4.91143 15.5833C4.91143 15.6305 4.96734 15.6305 5.02326 15.6305C5.13508 15.6305 5.191 15.6776 5.30283 15.6305C5.47057 15.5833 5.63831 15.6305 5.75014 15.6776C5.91789 15.7719 6.02972 15.9133 6.19746 15.9133L6.25337 15.9604L6.19746 16.0076C6.02972 16.0076 5.91789 15.9604 5.75014 15.9604C5.63831 15.9604 5.47057 15.819 5.35874 15.9604C5.35874 16.0547 5.52649 16.1018 5.63831 16.149C5.80606 16.1961 5.69423 16.2432 5.63831 16.2432C5.41466 16.2904 5.191 16.4318 5.13508 16.6203C5.07917 16.856 4.7996 16.856 4.63186 16.856C4.4082 16.8089 4.18454 16.856 3.96088 16.856C3.73722 16.856 3.51357 16.9031 3.28991 17.0445C3.234 17.0917 3.17808 17.0917 3.17808 17.0445C2.95442 16.9503 2.78668 17.0445 2.56302 17.1388C2.39528 17.1859 2.39528 17.1859 2.50711 17.3274C2.56302 17.3745 2.56302 17.4216 2.45119 17.4216C2.33937 17.4216 2.22754 17.3745 2.22754 17.5159C2.22754 17.7044 2.05979 17.7987 1.89205 17.7987C1.61248 17.7987 1.55656 17.9872 1.38882 18.1287C1.33291 18.1758 1.33291 18.2701 1.44473 18.2701C1.66839 18.3172 1.94796 18.3172 2.11571 18.4586C2.11571 18.5057 2.22754 18.5057 2.28345 18.4586C2.50711 18.3172 2.67485 18.4586 2.89851 18.4586C3.12217 18.4586 3.234 18.5529 3.28991 18.7414C3.28991 18.7886 3.51357 18.7414 3.51357 18.8357C3.51357 18.8828 3.34582 18.93 3.28991 18.9771C3.12217 19.1185 3.06625 19.2599 2.95442 19.3542C2.89851 19.4013 2.89851 19.4013 2.95442 19.4956C3.12217 19.7784 3.40174 19.8255 3.68131 19.8255C3.73722 19.8255 3.84905 19.8255 3.84905 19.8727C3.84905 19.9669 3.79314 20.0141 3.68131 19.9669C3.6254 19.9669 3.6254 20.0141 3.56948 20.0612C3.56948 20.1555 3.6254 20.1555 3.68131 20.1555C3.73722 20.1555 3.84905 20.2026 3.79314 20.2026C3.68131 20.344 3.79314 20.5326 3.68131 20.6268C3.45765 20.7682 3.34582 21.0039 3.06625 21.0982C2.95442 21.1453 2.89851 21.2396 2.84259 21.2867C2.78668 21.381 2.84259 21.4753 2.95442 21.4753C3.12217 21.5224 3.28991 21.5224 3.51357 21.5695C3.68131 21.6167 3.90497 21.4281 4.0168 21.6167C4.0168 21.6167 4.07271 21.6167 4.07271 21.5695C4.18454 21.5224 4.24045 21.381 4.4082 21.5695C4.46411 21.6638 4.68777 21.5695 4.7996 21.7109C4.7996 21.7581 4.91143 21.8052 4.7996 21.8052C4.68777 21.8052 4.57594 21.8524 4.46411 21.7581C4.18454 21.8052 3.90497 21.8524 3.68131 21.8995C3.56948 21.9938 3.51357 22.1823 3.34582 22.1823C3.12217 22.1823 3.17808 22.3237 3.234 22.418C3.28991 22.6065 3.56948 22.6065 3.73723 22.7008C3.79314 22.7008 4.0168 22.7008 4.07271 22.6537C4.18454 22.5594 4.4082 22.5594 4.52003 22.6065C4.68777 22.7479 4.85551 22.7008 5.02326 22.7479C5.07917 22.7951 5.191 22.7951 5.30283 22.8422C5.41466 22.8422 5.52649 22.8893 5.63831 22.8422C5.69423 22.7951 5.80606 22.9365 5.91789 22.9365C6.02971 22.9836 6.14154 22.8422 6.25337 22.8893C6.47703 23.0779 6.70069 23.0307 6.98026 22.9836C7.09209 22.9836 7.148 23.0307 7.25983 23.0307V23.0779C7.25983 23.0779 7.25983 23.0779 7.20392 23.0779C7.148 23.0779 7.09209 23.0307 7.09209 23.125C7.09209 23.125 7.148 23.1721 7.20392 23.1721C7.37166 23.1721 7.48349 23.125 7.65123 23.1721C7.76306 23.2193 7.76306 23.1721 7.76306 23.125C7.81898 23.0779 7.87489 23.0779 7.9308 23.125C7.98672 23.1721 7.9308 23.2193 7.87489 23.2664C7.76306 23.3136 7.59532 23.3607 7.5394 23.5492C7.5394 23.6435 7.70715 23.6906 7.5394 23.7849C7.42758 23.832 7.31575 23.832 7.20392 23.7849C7.148 23.7849 7.09209 23.832 7.03617 23.832C6.81252 23.9263 6.53294 24.0206 6.25337 24.0206C5.91789 24.0677 5.69423 24.3034 5.35874 24.3505C5.191 24.3505 5.07917 24.4919 5.02326 24.5862C4.96734 24.6805 5.02326 24.8219 4.7996 24.8219C4.74368 24.8219 4.74368 24.9162 4.74368 24.9162C4.91143 25.1047 4.74368 25.1518 4.57594 25.199C4.29637 25.2932 4.07271 25.3875 4.07271 25.6703C4.07271 25.7646 4.18454 25.8589 4.29637 25.8117C4.4082 25.7646 4.52003 25.6703 4.63186 25.6232C4.68777 25.5761 4.68777 25.6703 4.68777 25.6703C4.68777 25.7175 4.68777 25.8117 4.7996 25.7175C4.91143 25.6232 5.07917 25.6703 5.191 25.6232C5.35874 25.5761 5.52649 25.5761 5.5824 25.6232C5.63831 25.8589 5.80606 25.6232 5.86197 25.7175C5.91789 25.7646 5.9738 25.8117 5.9738 25.8589C5.9738 26.0474 6.19746 26.0945 6.30929 26.0474C6.47703 25.9531 6.58886 26.0945 6.7566 26.0003C6.7566 26.0003 6.81252 25.9531 6.81252 26.0003C6.86843 26.0003 6.92435 26.0003 6.92435 26.0474C6.92435 26.0945 6.92435 26.1417 6.86843 26.1888C6.58886 26.236 6.3652 26.1888 6.08563 26.2831C6.02972 26.3302 5.86197 26.2831 5.86197 26.3302C5.86197 26.4245 5.63831 26.5188 5.63831 26.6602C5.63831 26.7073 5.63831 26.7544 5.69423 26.7544C5.75014 26.7544 5.80606 26.7544 5.86197 26.8016C5.91789 26.6602 5.9738 26.7544 6.08563 26.7544C6.08563 26.8487 6.02971 26.7544 5.91789 26.7544C6.08563 26.9901 6.14154 26.9901 6.3652 26.943C6.7566 26.8487 7.20392 26.7544 7.59532 26.7073C8.26629 26.6602 8.82543 26.5188 9.44049 26.4245C10.0556 26.3302 10.6706 26.236 11.2298 26.1417C11.5093 26.0945 11.7889 26.0945 12.0685 26.0003C12.4599 25.9531 12.7954 25.8589 13.1308 25.8589C13.6341 25.8117 14.1373 25.7646 14.5846 25.7175C15.1997 25.6703 15.7588 25.6232 16.3739 25.5289C16.8212 25.4818 17.3244 25.4818 17.7717 25.3875C17.8277 25.3875 17.9395 25.3875 17.9954 25.4347C18.0513 25.4347 18.0513 25.4347 18.0513 25.4818C18.0513 25.4818 18.0513 25.5289 17.9954 25.5289C17.9395 25.5761 17.8277 25.6232 17.6599 25.6232C17.3244 25.6232 16.9889 25.6232 16.6535 25.6703C16.262 25.7175 15.9266 25.7175 15.5352 25.7646C15.3674 25.8117 15.1438 25.8589 14.976 25.8589C14.6405 25.8117 14.305 25.8589 14.0255 26.0003C13.9136 26.0474 13.9136 26.0003 13.9136 25.9531C13.9136 25.906 13.8018 25.906 13.7459 25.906C13.5782 26.0003 13.2986 25.9531 13.0749 26.0945C12.9631 26.1417 12.7954 26.1888 12.6835 26.1417C12.5717 26.0945 12.4599 26.236 12.348 26.1888C12.2362 26.1417 12.1244 26.1888 12.0685 26.236C11.9007 26.3774 11.8448 26.0945 11.7889 26.1888C11.6771 26.3774 11.4534 26.236 11.3416 26.2831C11.062 26.4716 10.7824 26.4716 10.5588 26.4245C10.3351 26.4245 10.1674 26.5659 9.99964 26.5188C9.83189 26.4716 9.77598 26.5188 9.66415 26.5659C9.49641 26.6602 9.27275 26.8016 9.10501 26.7544C8.88135 26.7073 8.65769 26.7544 8.37812 26.7544C8.09855 26.7544 7.76306 26.7544 7.48349 26.8958C7.37166 26.943 7.25983 26.9901 7.148 26.8958C7.03617 26.8958 6.98026 26.9901 7.03617 27.0373C7.09209 27.0844 7.03617 27.1315 7.03617 27.1787C7.25983 27.2258 7.42758 27.0844 7.65123 27.0844C8.21038 27.0373 8.71361 27.0373 9.21684 26.8958C9.55232 26.8016 9.94372 26.7544 10.2792 26.7073C11.062 26.613 11.7889 26.4716 12.5158 26.3774C13.0749 26.3302 13.5782 26.1888 14.1373 26.1417C14.4728 26.0945 14.8083 26.0003 15.1997 26.0474C15.7029 25.906 16.2061 25.9531 16.7094 25.8589C17.4922 25.7646 18.275 25.7175 19.0578 25.6232C19.2255 25.6232 19.3373 25.5761 19.5051 25.5289C19.6169 25.5761 19.8406 25.6232 19.9524 25.4818C19.9524 25.4347 20.0642 25.4818 20.1201 25.4818C20.3438 25.5289 20.5675 25.4347 20.847 25.4818C20.9029 25.4818 21.0148 25.4818 21.1266 25.4347C21.1825 25.3875 21.1266 25.3875 21.1266 25.3404C21.1266 25.2932 21.0707 25.2932 21.0707 25.2932C20.9589 25.3875 20.9029 25.2461 20.847 25.2932C20.6234 25.3404 20.5115 25.4347 20.3438 25.3875C20.1761 25.5289 20.0083 25.3404 19.7847 25.4347C19.6169 25.5289 19.3933 25.4818 19.2255 25.4347C19.1696 25.4347 19.1137 25.4818 19.0578 25.4818C19.0019 25.5289 18.9459 25.5761 18.8341 25.5289C18.6664 25.5289 18.4986 25.4818 18.3309 25.4818L18.275 25.4347L18.3309 25.3875H18.3868C18.4986 25.2461 18.7223 25.4347 18.89 25.3404C19.0578 25.199 19.2814 25.3404 19.4492 25.2932C19.7287 25.2461 20.0642 25.2461 20.3438 25.1047H20.2879L20.232 25.0576C20.232 25.0104 20.2879 25.0104 20.2879 25.0576V25.1047C20.4556 25.1047 20.6793 25.2461 20.7911 25.0104C20.9589 24.7276 21.1266 25.199 21.2943 25.0576C21.3503 25.0104 21.4062 25.0576 21.4621 25.0576C21.5739 25.0576 21.6857 24.9633 21.8535 25.0104L21.9094 24.9633C21.9094 24.9162 21.8535 24.869 21.8535 24.869C21.9094 24.8219 21.9653 24.8219 22.0212 24.869C22.189 25.0104 22.3008 25.0104 22.4685 25.0104C23.1395 24.9162 23.8105 24.9162 24.4256 24.9633C24.5374 24.9633 24.6492 24.869 24.761 24.9162C24.817 24.9162 24.8169 24.9162 24.8169 24.8219C24.761 24.7276 24.761 24.7276 24.8169 24.7276C24.8729 24.7276 24.9847 24.7748 25.0406 24.7748C25.0406 24.6805 25.0965 24.6805 25.1524 24.7276C25.2643 24.7276 25.3202 24.7748 25.432 24.7748C25.5998 24.6805 25.6557 24.6805 25.7675 24.8219C25.8793 24.8219 25.9912 24.869 26.103 24.869C26.1589 24.869 25.9912 24.6805 26.2707 24.7276C26.4944 24.7748 26.774 24.6805 26.9976 24.8219C27.0535 24.869 27.2772 24.9633 27.389 24.8219H27.3331C27.2772 24.8219 27.2772 24.8219 27.2213 24.8219C27.1654 24.8219 27.1654 24.8219 27.1094 24.8219C27.0535 24.8219 26.9976 24.8219 26.9976 24.7748H27.0535C27.1094 24.7748 27.1654 24.7748 27.2213 24.8219C27.2772 24.8219 27.3331 24.869 27.3331 24.869C27.3331 24.869 27.3331 24.869 27.3331 24.9162C27.4449 24.9633 27.5568 24.9633 27.6686 25.0104C27.9482 25.1047 27.6686 24.869 27.8363 24.869C28.1159 24.8219 28.4514 24.9162 28.731 24.7748C28.731 24.7748 28.8428 24.869 28.9546 24.869C28.9546 24.7748 29.0105 24.7748 29.0664 24.8219C29.2342 24.869 29.4019 24.869 29.5138 24.9162V24.869C29.9052 24.8219 30.2966 24.9162 30.7439 24.869C30.8557 24.869 31.0234 24.869 31.0234 24.9162C30.9675 25.0104 30.8557 24.9162 30.7439 24.9162C30.688 24.9162 30.688 24.9162 30.632 24.9162C30.632 24.9633 30.688 24.9633 30.688 24.9633C30.9675 25.0576 31.2471 24.9162 31.4708 25.0104C31.4708 25.0104 31.5267 25.0104 31.5826 24.9633L31.5267 24.9162C31.4708 24.9162 31.3589 24.869 31.303 24.869L31.2471 24.8219C31.303 24.8219 31.303 24.7748 31.3589 24.8219C31.6385 24.8219 31.9181 24.7748 32.1977 24.9633C32.4213 25.1047 32.7568 25.0576 33.0923 25.0576C33.0923 25.0576 33.0923 25.0576 33.1482 25.0576C33.1482 25.0576 33.1482 25.0104 33.0923 25.0104C33.0364 25.0104 32.9805 25.0104 32.9245 24.9633L32.8686 24.9162L32.9245 24.869C33.0364 24.9162 33.1482 24.869 33.26 24.9633C33.3159 25.0576 33.4278 25.0104 33.4837 25.0576C33.4837 25.0576 33.5396 25.0576 33.5396 25.0104C33.5955 24.9633 33.5396 25.0104 33.4837 24.9633C33.4278 24.9162 33.3159 24.9633 33.3719 24.869C33.3719 24.8219 33.4837 24.869 33.4837 24.869C33.6514 24.9162 33.8192 24.9162 34.0428 24.9633C34.2665 24.8219 34.5461 24.869 34.7697 24.9162L34.8256 24.9633C34.8256 25.0104 34.7138 25.0104 34.7697 25.0576C34.7697 25.1047 34.8815 25.1047 34.9375 25.1047C35.1052 25.1518 35.217 25.0576 35.3289 25.1047C35.4966 25.1518 35.6084 25.199 35.7762 25.1047C35.8321 25.1047 35.888 25.1047 35.888 25.199C35.888 25.2461 35.8321 25.2932 35.7762 25.2461C35.4407 24.9162 34.9375 25.1518 34.4901 25.0576C34.2106 25.1047 33.8751 25.0576 33.5955 25.0576C33.3159 25.0576 32.9805 25.1047 32.7009 25.0104C32.645 25.0104 32.645 25.0104 32.5891 25.0104C32.0858 25.1047 31.6385 25.0576 31.1353 25.0104C31.0794 25.0104 31.0234 25.0104 31.0234 25.0576L31.0794 25.1047C31.2471 25.1518 31.4708 25.199 31.5826 25.199C31.8622 25.1047 32.0858 25.199 32.3095 25.199C32.5331 25.199 32.8127 25.199 33.0364 25.2461C33.4837 25.3404 33.931 25.2461 34.3783 25.2461C34.5461 25.1047 34.6579 25.2932 34.8256 25.2932C35.2729 25.199 35.6084 25.2461 35.9439 25.199C36.1676 25.3404 36.3912 25.2461 36.6149 25.2461C36.7826 25.2461 36.9504 25.2932 37.1181 25.2461C37.2299 25.199 37.2859 25.3404 37.3977 25.3875C37.5095 25.4347 37.5654 25.2461 37.7332 25.2932H37.7891C38.0687 25.2932 38.3482 25.199 38.6278 25.2932C38.7396 25.3404 38.8515 25.2932 38.9074 25.2461C38.9633 25.199 38.7955 25.1518 38.9074 25.1047C38.9633 25.1047 39.0751 25.1047 39.131 25.1518C39.1869 25.1518 39.2429 25.1518 39.2988 25.199C39.2988 25.199 39.2988 25.199 39.2988 25.1518C39.2988 25.1518 39.3547 25.1518 39.3547 25.1047V25.1518L39.2988 25.199H39.2429C39.2429 25.2461 39.1869 25.2461 39.131 25.2461C39.0751 25.2461 38.9633 25.199 38.9074 25.2461C38.9074 25.2932 39.0192 25.2932 39.0751 25.2932C39.187 25.2932 39.2988 25.3875 39.4106 25.3404C39.5784 25.2932 39.7461 25.2932 39.8579 25.3404C40.0257 25.3875 40.1934 25.2932 40.3612 25.3404C40.6407 25.3875 40.8644 25.4347 41.144 25.3875C41.5913 25.3875 41.8708 25.4818 42.0945 25.5289C42.3182 25.5761 42.5977 25.4818 42.8214 25.5289C42.9332 25.5761 43.1569 25.6232 43.2687 25.5761C43.4364 25.4818 43.4364 25.6703 43.6042 25.6703C43.7719 25.6703 43.8838 25.7175 44.0515 25.7175C44.1633 25.7175 44.2752 25.7646 44.3311 25.7646C44.6666 25.6703 45.002 25.8589 45.3375 25.8589L45.3934 25.906C45.3934 26.0945 45.6171 26.0945 45.7289 26.0945C45.9526 26.1888 46.2322 26.1417 46.4558 26.0003C46.5117 25.9531 46.6236 25.9531 46.6236 26.0945C46.6236 26.1888 46.6236 26.1888 46.7354 26.1417C46.9591 26.0474 47.1827 26.0945 47.4064 26.1417C47.5741 26.1888 47.6859 26.236 47.8537 26.1888C47.9655 26.1417 48.0214 26.1888 48.0773 26.236C48.2451 26.2831 48.4128 26.3302 48.5806 26.3774C48.7483 26.4245 48.8601 26.3774 49.0279 26.4245C49.1397 26.4716 49.3634 26.4716 49.5311 26.4245C49.7548 26.3774 49.9784 26.4245 50.1462 26.4716C50.4257 26.613 50.7612 26.613 51.0408 26.7073C51.2085 26.7544 51.3763 26.7544 51.4881 26.8016C51.544 26.8016 51.5999 26.8016 51.544 26.8487C51.544 26.8958 51.3763 26.8958 51.4881 26.943C51.5999 26.9901 51.6559 26.9901 51.6559 26.8958C51.6559 26.8487 51.7118 26.8016 51.7677 26.8016C52.2709 26.8958 52.7182 26.943 53.2215 27.0373C53.3333 27.0373 53.3333 27.2258 53.4451 27.1315C53.5569 27.0373 53.6129 27.0844 53.7247 27.1787C53.8365 27.2729 53.9483 27.1787 54.0602 27.1787C54.3957 27.3672 54.6752 27.4615 54.9548 27.3672C55.0666 27.3201 55.2903 27.3672 55.3462 27.4143C55.514 27.6029 55.6258 27.4143 55.7935 27.4615C55.8494 27.4615 55.8494 27.3672 55.7935 27.3201C55.5699 27.2729 55.458 27.1315 55.2344 27.1315C55.1785 27.1315 55.0666 27.1315 55.1226 27.0373H55.2344C55.2344 26.943 55.3462 26.8487 55.3462 26.7544C55.4021 26.613 55.5699 26.613 55.6817 26.5659C55.7376 26.5188 55.8494 26.5659 55.9054 26.6602C55.9613 26.7544 56.0731 26.7073 56.129 26.7073C56.2968 26.7544 56.4645 26.7544 56.6322 26.8016C56.8 26.8487 57.0236 26.8487 57.1914 26.8958C57.415 26.943 57.5828 26.8487 57.8064 26.8958C57.8624 26.8958 57.9183 26.943 57.9742 26.8487C57.9742 26.6602 58.1419 26.613 58.3097 26.613L58.3656 26.5659C58.3656 26.5188 58.3656 26.4716 58.3097 26.4716C58.2538 26.4716 58.1978 26.4245 58.1419 26.4245C58.086 26.4245 58.0301 26.3774 58.0301 26.3302C58.0301 26.2831 58.0301 26.236 58.086 26.236C58.1978 26.1888 58.2538 26.0945 58.3656 26.0945C58.4215 26.0945 58.4215 26.0945 58.4774 26.0474C58.5892 25.906 58.3656 25.7646 58.5333 25.6703C58.5333 25.6703 58.5333 25.6232 58.5333 25.5761C58.4774 25.4818 58.4215 25.4347 58.3656 25.3404H58.3097C58.1978 25.2461 58.1978 25.1518 58.3656 25.1047C58.4774 25.0576 58.5333 25.0104 58.4215 24.9633C58.2538 24.869 58.1419 24.6805 57.9742 24.6333C57.9183 24.6333 57.8624 24.5862 57.8624 24.5391C58.0301 24.3505 57.5828 24.3034 57.7505 24.1149C57.7505 24.1149 57.6946 24.0677 57.6387 24.0206C57.5269 23.9734 57.3591 24.0677 57.3591 23.8792C57.2473 23.832 57.1914 23.7378 57.1355 23.5964C57.1355 23.455 57.0796 23.4078 56.9118 23.4078C56.6882 23.3607 56.4086 23.4078 56.4086 23.125C56.4086 23.0779 56.2968 23.0779 56.2408 23.0779C56.129 23.0307 56.129 22.9836 56.1849 22.9365C56.2408 22.8893 56.2968 22.8893 56.3527 22.8422C56.5204 22.7951 56.5204 22.7479 56.4086 22.6537C56.3527 22.6065 56.2968 22.6065 56.2408 22.6065C56.129 22.6065 56.0731 22.5123 56.0731 22.4651C56.0731 22.3708 56.1849 22.3708 56.2408 22.3237C56.2968 22.2766 56.3527 22.2766 56.3527 22.2766C56.5204 22.2766 56.6322 22.1823 56.6882 22.1352C56.7441 22.088 56.6322 21.9466 56.6322 21.8524C56.6322 21.711 56.6882 21.5224 56.5204 21.381C56.3527 21.2396 56.4086 21.0511 56.3527 20.8625C56.3527 20.8154 56.3527 20.7211 56.4645 20.7211C56.4645 20.7211 56.4645 20.7211 56.4645 20.7682L56.5204 20.8154C56.5204 20.8154 56.5204 20.8154 56.5763 20.8154C56.5763 20.8154 56.5763 20.7682 56.5204 20.7682H56.4645C56.4086 20.7211 56.7441 20.674 56.4645 20.5797C56.2968 20.5326 56.129 20.4383 56.0172 20.344C55.9613 20.2969 55.9054 20.2498 55.9613 20.2026C55.9613 20.1083 55.9613 20.0612 55.9054 20.0141C55.7935 19.7784 55.7935 19.7313 56.129 19.7313H56.1849C56.2408 19.7313 56.2968 19.6841 56.2968 19.637C56.2968 19.5899 56.2968 19.5427 56.2408 19.5427C56.1849 19.5427 56.129 19.5427 56.0731 19.4956C55.9613 19.4956 55.9054 19.5899 55.7935 19.4484C55.6817 19.4484 55.514 19.4484 55.4021 19.4484C55.3462 19.4013 55.2903 19.3542 55.2344 19.307C55.2344 19.2599 55.2344 19.2128 55.2903 19.2128C55.4021 19.2128 55.6258 19.2128 55.6258 19.307C55.6817 19.5427 55.8494 19.4956 55.9613 19.4484C56.2408 19.3542 56.4086 19.4485 56.6322 19.5899C56.7441 19.637 56.7441 19.6841 56.8559 19.5899C57.0796 19.4013 57.2473 19.1656 57.415 18.9771C57.471 18.93 57.415 18.8828 57.415 18.8357C57.3591 18.6471 57.3591 18.6471 57.5828 18.6943C57.9183 18.7414 58.2538 18.93 58.5892 18.93C58.5892 18.93 58.5892 18.93 58.6452 18.93C58.9247 19.0242 58.9247 18.9771 59.2043 18.9771C59.4839 18.9771 59.5398 18.8357 59.6516 18.6943C59.7075 18.6471 59.7634 18.6471 59.7075 18.6C59.5957 18.4115 59.5957 18.3643 59.8194 18.2701C59.9312 18.1758 59.9871 18.0815 59.9312 17.9401ZM56.1849 11.1526C56.129 11.1526 56.129 11.1055 56.1849 11.1526C56.1849 11.1055 56.1849 11.1055 56.1849 11.0583C56.1849 11.0583 56.1849 11.1055 56.1849 11.1526C56.1849 11.1055 56.1849 11.1526 56.1849 11.1526ZM56.3527 10.6813C56.4086 10.6813 56.5204 10.7284 56.5763 10.6813C56.6322 10.6813 56.6322 10.587 56.6882 10.6813C56.6882 10.7284 56.7441 10.8227 56.7441 10.8698C56.7441 10.9169 56.6322 10.9169 56.5763 10.8698C56.5204 10.8698 56.4645 10.8698 56.4086 10.8227C56.3527 10.8227 56.3527 10.8227 56.2968 10.8227C56.2408 10.7755 56.0731 10.8227 56.0731 10.7284C56.129 10.5399 56.2968 10.6813 56.3527 10.6813ZM55.514 10.4456C55.514 10.5398 55.5699 10.587 55.5699 10.6813C55.514 10.6813 55.514 10.6813 55.458 10.6813C55.4021 10.6341 55.3462 10.587 55.2344 10.5399C55.3462 10.4927 55.458 10.4927 55.514 10.4456ZM55.514 11.0583C55.6258 11.0583 55.6817 11.1055 55.7935 11.0583C55.8494 11.0583 55.9054 11.0112 56.0172 11.0583V11.1055C55.9054 11.1055 55.8494 11.1997 55.7376 11.1526C55.6817 11.1526 55.5699 11.1526 55.514 11.1055C55.4021 11.0583 55.2344 11.1055 55.1785 11.0112C55.2903 10.9641 55.4021 11.0583 55.514 11.0583ZM55.0107 10.6341L55.0666 10.587C55.1226 10.587 55.1226 10.6341 55.1226 10.6813L55.0666 10.7284C55.0107 10.6813 55.0107 10.6341 55.0107 10.6341ZM31.5826 0.924219C31.5826 0.924219 31.5267 0.877084 31.5826 0.924219C31.5267 0.877084 31.5267 0.829948 31.5267 0.829948H31.4708L31.4149 0.782813C31.4149 0.735677 31.4708 0.735677 31.4708 0.782813V0.829948C31.4708 0.829948 31.4708 0.829948 31.5267 0.829948C31.5826 0.877084 31.6385 0.877084 31.5826 0.924219C31.6385 0.924219 31.5826 0.924219 31.5826 0.924219ZM12.7394 2.10261C12.7394 2.10261 12.6835 2.10261 12.7394 2.10261C12.6835 2.10261 12.7394 2.10261 12.7394 2.10261ZM9.49641 2.7625V2.80964C9.49641 2.80964 9.49641 2.80964 9.44049 2.80964C9.44049 2.80964 9.44049 2.80964 9.49641 2.7625C9.44049 2.7625 9.44049 2.7625 9.49641 2.7625ZM5.30283 6.81615C5.24691 6.76901 5.30283 6.76901 5.30283 6.76901C5.30283 6.76901 5.35874 6.81615 5.30283 6.81615C5.35874 6.81615 5.35874 6.81615 5.30283 6.81615ZM5.69423 7.1461C5.69423 7.19323 5.5824 7.1461 5.5824 7.1461C5.52649 7.1461 5.41466 7.1461 5.47057 7.05183C5.47057 7.00469 5.5824 7.05183 5.5824 7.05183C5.63831 7.05183 5.69423 7.05183 5.69423 7.1461ZM6.14154 7.57032V7.52318C6.14154 7.52318 6.14154 7.52318 6.19746 7.52318C6.19746 7.52318 6.19746 7.52318 6.14154 7.57032C6.19746 7.57032 6.14154 7.57032 6.14154 7.57032ZM6.70069 7.52318C6.70069 7.57032 6.64477 7.57032 6.53294 7.57032C6.47703 7.57032 6.47703 7.57032 6.42112 7.57032C6.3652 7.57032 6.30929 7.57032 6.30929 7.52318C6.30929 7.42891 6.42112 7.47605 6.42112 7.47605C6.47703 7.47605 6.47703 7.47605 6.53294 7.47605C6.58886 7.47605 6.58886 7.38177 6.70069 7.42891C6.7566 7.47605 6.70069 7.52318 6.70069 7.52318ZM7.31575 7.57032L7.25983 7.61745C7.20392 7.61745 7.20392 7.61745 7.148 7.61745C7.09209 7.61745 6.98026 7.61745 6.92435 7.52318C6.92435 7.47605 6.86843 7.42891 6.86843 7.42891C6.86843 7.38177 6.98026 7.38177 6.98026 7.42891C7.03617 7.52318 7.09209 7.52318 7.20392 7.57032C7.25983 7.52318 7.37166 7.47605 7.31575 7.57032ZM7.31575 7.52318C7.48349 7.33464 7.70715 7.42891 7.9308 7.38177C7.98672 7.38177 8.09855 7.38177 8.15446 7.42891C7.87489 7.47605 7.5394 7.52318 7.31575 7.52318ZM8.21038 7.38177C8.15446 7.38177 8.15446 7.38177 8.21038 7.38177C8.21038 7.33464 8.26629 7.33464 8.26629 7.2875C8.32221 7.2875 8.32221 7.33464 8.32221 7.33464C8.32221 7.42891 8.26629 7.38177 8.21038 7.38177ZM4.07271 19.7313C4.0168 19.7313 3.96088 19.7313 3.90497 19.6841C3.84905 19.6841 3.84905 19.6841 3.79314 19.6841C3.79314 19.6841 3.73723 19.637 3.79314 19.637C3.79314 19.5899 4.07271 19.637 4.07271 19.7313C4.12863 19.6841 4.07271 19.7313 4.07271 19.7313ZM4.12863 20.0612C4.07271 20.0612 4.07271 20.0612 4.12863 20.0612C4.07271 20.0141 4.12863 20.0141 4.12863 20.0141C4.12863 20.0141 4.12863 20.0141 4.12863 20.0612ZM4.91143 20.0141C4.91143 20.0141 4.85551 20.0141 4.91143 20.0141C4.85551 19.9669 4.85551 19.9198 4.91143 19.9198C4.96734 19.8727 5.07917 19.9198 5.13508 19.9198L5.191 19.9669C5.07917 20.0141 4.96734 19.9198 4.91143 20.0141ZM5.80606 22.7479L5.75014 22.7008C5.80606 22.7008 5.86197 22.7008 5.86197 22.7008L5.91789 22.7479C5.91789 22.7479 5.86197 22.7479 5.80606 22.7479ZM8.26629 8.37162V8.32448C8.26629 8.32448 8.26629 8.32448 8.32221 8.32448C8.32221 8.27735 8.32221 8.32448 8.26629 8.37162C8.32221 8.32448 8.32221 8.32448 8.26629 8.37162ZM8.82543 8.27735C8.76952 8.27735 8.71361 8.27735 8.65769 8.23021C8.60178 8.23021 8.65769 8.13594 8.65769 8.13594C8.65769 8.08881 8.71361 8.08881 8.76952 8.13594C8.82543 8.18308 8.88135 8.18308 8.93726 8.23021C8.88135 8.23021 8.88135 8.23021 8.82543 8.27735ZM6.92435 22.7479H6.86843C6.81252 22.7479 6.7566 22.7479 6.81252 22.7008H6.86843C6.92435 22.6537 6.98026 22.7008 6.92435 22.7479ZM8.09855 16.1961C8.04263 16.149 8.09855 16.149 8.09855 16.149C8.09855 16.149 8.15446 16.1961 8.09855 16.1961C8.15446 16.1961 8.15446 16.1961 8.09855 16.1961ZM7.31575 22.7008C7.31575 22.7008 7.25983 22.7008 7.31575 22.7008C7.31575 22.6537 7.31575 22.6537 7.37166 22.6537V22.7008H7.31575ZM6.81252 26.7073C6.64477 26.613 6.47703 26.8016 6.30929 26.7073C6.25337 26.7073 6.25337 26.7073 6.19746 26.7073C6.14154 26.7073 6.14154 26.7073 6.14154 26.6602C6.14154 26.6602 6.14154 26.6602 6.19746 26.6602C6.3652 26.613 6.58886 26.613 6.7566 26.5659C6.81252 26.5659 6.86843 26.613 6.86843 26.6602L6.81252 26.7073ZM9.49641 15.8662C9.49641 15.9133 9.49641 15.9133 9.49641 15.9604V15.9133C9.44049 15.9133 9.49641 15.8662 9.49641 15.8662ZM8.48995 23.125C8.48995 23.1721 8.43403 23.2193 8.43403 23.2193C8.32221 23.2193 8.26629 23.2193 8.21038 23.1721C8.15446 23.125 8.09855 23.125 8.09855 23.0779C8.09855 23.0307 8.15446 23.0307 8.21038 23.0307C8.26629 23.0307 8.26629 23.0307 8.32221 23.0307C8.37812 23.0307 8.43403 23.0307 8.48995 23.0307C8.48995 23.0779 8.48995 23.0779 8.48995 23.125ZM8.54586 23.0779C8.48995 23.125 8.48995 23.0779 8.54586 23.0779C8.54586 23.0307 8.54586 23.0307 8.60178 22.9836V23.0307C8.54586 23.0779 8.54586 23.0779 8.54586 23.0779ZM9.83189 16.1018V16.0547C9.83189 16.0547 9.83189 16.0547 9.88781 16.0547C9.88781 16.0076 9.88781 16.0547 9.83189 16.1018C9.88781 16.0547 9.83189 16.1018 9.83189 16.1018ZM11.9007 3.13958C11.9007 3.13958 11.8448 3.09245 11.9007 3.09245C11.9566 3.04531 12.0126 3.09245 12.0126 3.09245V3.13958C12.0126 3.18672 11.9566 3.18672 11.9007 3.13958ZM13.7459 2.90391H13.8018V2.95104L13.7459 2.99818C13.7459 2.90391 13.7459 2.90391 13.7459 2.90391ZM12.2362 3.13958L12.1803 3.09245C12.2362 3.04531 12.2362 3.04531 12.2921 3.09245L12.348 3.13958C12.348 3.09245 12.2921 3.13958 12.2362 3.13958ZM12.5717 3.09245C12.5158 3.09245 12.5158 3.04531 12.4599 3.04531C12.4599 3.04531 12.5158 3.04531 12.5717 2.99818C12.6276 2.99818 12.6276 3.04531 12.6835 3.04531C12.6276 3.09245 12.6276 3.09245 12.5717 3.09245ZM12.8513 3.04531C12.8513 3.04531 12.7954 2.99818 12.8513 2.99818C12.9072 2.95104 12.9631 2.99818 12.9631 2.99818V3.04531C12.9072 3.09245 12.9072 3.04531 12.8513 3.04531ZM13.1868 3.04531L13.1308 2.99818C13.1868 2.95104 13.2427 2.85677 13.3545 2.90391L13.4104 2.95104C13.3545 2.95104 13.2986 3.04531 13.1868 3.04531ZM11.3416 15.819C11.2857 15.819 11.2298 15.819 11.2298 15.7719L11.2857 15.7247C11.2857 15.7247 11.3416 15.7247 11.3416 15.819C11.3416 15.7719 11.3416 15.819 11.3416 15.819ZM10.9502 22.7951C10.7265 22.7951 10.5588 22.9365 10.391 22.8893C10.3351 22.8893 10.2792 22.8422 10.3351 22.7951C10.3351 22.7479 10.391 22.7008 10.391 22.7008C10.5588 22.7951 10.7824 22.6537 10.9502 22.7008C10.9502 22.7008 11.0061 22.7008 11.0061 22.7479C11.0061 22.7951 10.9502 22.7951 10.9502 22.7951ZM11.9007 15.819C11.9007 15.7719 11.9007 15.7247 11.9007 15.7247C11.9566 15.6776 12.0685 15.7247 12.1244 15.7247C12.1244 15.7247 12.1244 15.7719 12.1803 15.7719C12.0685 15.7719 12.0126 15.7719 11.9007 15.819ZM14.1373 2.95104C14.0814 2.95104 14.0814 2.95104 14.0255 2.95104C13.9696 2.95104 13.9136 2.90391 13.8577 2.90391C13.8018 2.90391 13.8018 2.90391 13.8018 2.85677L13.8577 2.80964C13.9696 2.80964 14.0255 2.85677 14.1373 2.85677C14.1932 2.85677 14.1932 2.90391 14.2491 2.90391C14.305 2.95104 14.1932 2.95104 14.1373 2.95104ZM15.3674 2.80964C15.3674 2.85677 15.3115 2.85677 15.3674 2.80964C15.0878 2.95104 14.8642 2.95104 14.5846 2.90391C14.5287 2.90391 14.5287 2.80964 14.5846 2.7625C14.6405 2.71537 14.6964 2.66823 14.8083 2.66823C14.9201 2.66823 14.976 2.71537 15.0878 2.71537C15.1438 2.71537 15.2556 2.7625 15.3115 2.7625C15.3674 2.7625 15.3674 2.80964 15.3674 2.80964ZM16.2061 2.7625C15.9825 2.85677 15.8147 2.90391 15.647 2.85677C15.5352 2.85677 15.4792 2.80964 15.4233 2.80964C15.3674 2.80964 15.3674 2.80964 15.3674 2.7625C15.3674 2.7625 15.3674 2.7625 15.4233 2.7625C15.7029 2.7625 15.9266 2.71537 16.2061 2.71537C16.2061 2.71537 16.262 2.71537 16.262 2.7625C16.318 2.7625 16.2061 2.7625 16.2061 2.7625ZM18.3309 2.66823C18.275 2.66823 18.2191 2.66823 18.1631 2.62109C18.0513 2.62109 17.9954 2.62109 17.8836 2.66823C17.7158 2.80964 17.5481 2.7625 17.4363 2.66823C17.3244 2.57396 17.2685 2.62109 17.2126 2.66823C16.933 2.66823 16.7653 2.80964 16.4857 2.71537C16.4298 2.71537 16.4298 2.71537 16.4298 2.66823C16.4298 2.62109 16.4857 2.62109 16.4857 2.57396C16.7094 2.43255 16.933 2.52682 17.1567 2.47969C17.5481 2.43255 17.9395 2.57396 18.2191 2.47969C18.3309 2.47969 18.3309 2.47969 18.3309 2.47969C18.3868 2.47969 18.4427 2.52682 18.4427 2.57396C18.4427 2.66823 18.3868 2.66823 18.3309 2.66823ZM16.262 25.4818V25.4347C16.262 25.4347 16.262 25.4347 16.318 25.4347C16.318 25.3875 16.318 25.4347 16.262 25.4818C16.318 25.4347 16.262 25.4818 16.262 25.4818ZM20.1761 2.52682C20.1761 2.57396 19.9524 2.62109 19.8965 2.57396C19.7847 2.43255 19.6169 2.62109 19.5051 2.52682C19.3933 2.43255 19.2814 2.52682 19.1696 2.57396C19.0019 2.66823 18.8341 2.57396 18.7223 2.52682C18.6664 2.52682 18.6664 2.43255 18.7223 2.43255C18.7782 2.38542 18.8341 2.29115 18.9459 2.38542C19.0019 2.38542 19.0019 2.47969 19.0578 2.43255C19.2814 2.24401 19.5051 2.38542 19.6728 2.38542C19.8406 2.38542 19.9524 2.43255 20.1201 2.43255C20.1761 2.47969 20.1761 2.47969 20.1761 2.52682ZM20.5675 2.43255C20.5115 2.43255 20.4556 2.47969 20.3997 2.47969C20.3438 2.47969 20.1761 2.52682 20.1761 2.38542C20.1761 2.24401 20.2879 2.24401 20.3438 2.29115C20.3997 2.29115 20.4556 2.29115 20.5675 2.19688C20.5675 2.24401 20.6234 2.29115 20.6234 2.33828C20.6793 2.47969 20.6234 2.47969 20.5675 2.43255ZM19.9524 7.19323C19.9524 7.19323 19.8965 7.1461 19.9524 7.19323C19.9524 7.1461 19.9524 7.1461 19.9524 7.19323C20.0083 7.1461 20.0083 7.1461 20.0083 7.19323C20.0083 7.1461 19.9524 7.19323 19.9524 7.19323ZM21.518 2.52682C21.4062 2.52682 21.3503 2.47969 21.2384 2.47969C21.1266 2.47969 21.0148 2.62109 21.0148 2.43255C21.0148 2.33828 21.1266 2.29115 21.2943 2.29115C21.3503 2.29115 21.4062 2.29115 21.4621 2.29115C21.518 2.29115 21.5739 2.29115 21.6298 2.33828L21.6857 2.38542C21.5739 2.47969 21.5739 2.52682 21.518 2.52682ZM31.8622 15.0177L31.9181 15.0649C31.8622 15.0649 31.8062 15.0649 31.7503 15.0649L31.6944 15.0177C31.7503 15.0177 31.8062 15.0177 31.8622 15.0177ZM33.4837 2.19688V2.24401C33.4837 2.24401 33.4837 2.24401 33.4278 2.24401C33.4837 2.24401 33.4837 2.24401 33.4837 2.19688ZM23.8664 2.33828C23.9223 2.33828 23.9782 2.33828 23.9782 2.33828C24.0342 2.33828 24.0341 2.38542 23.9223 2.38542C23.9223 2.38542 23.8664 2.38542 23.8105 2.33828C23.8105 2.33828 23.8105 2.33828 23.8664 2.33828ZM19.561 25.1518V25.1047C19.561 25.1047 19.561 25.1047 19.6169 25.1047C19.6169 25.1047 19.6169 25.1047 19.561 25.1518C19.6169 25.1518 19.561 25.1518 19.561 25.1518ZM23.475 2.38542C23.4191 2.43255 23.3073 2.33828 23.1954 2.43255C23.1395 2.43255 22.9718 2.57396 22.9159 2.43255C22.804 2.47969 22.6922 2.43255 22.6363 2.47969C22.5245 2.52682 22.4126 2.52682 22.3008 2.47969C22.2449 2.47969 22.2449 2.47969 22.189 2.47969C22.1331 2.47969 22.1331 2.47969 22.0771 2.47969C22.0212 2.47969 21.9653 2.47969 21.9653 2.38542C21.9653 2.29115 22.0771 2.29115 22.1331 2.24401C22.189 2.38542 22.3567 2.14974 22.3567 2.24401C22.4685 2.43255 22.6363 2.33828 22.7481 2.29115C22.9718 2.24401 23.1954 2.19688 23.4191 2.24401C23.475 2.24401 23.475 2.29115 23.475 2.33828C23.5309 2.33828 23.5309 2.38542 23.475 2.38542ZM20.0083 25.1047C20.0083 25.1047 19.9524 25.1047 19.9524 25.0576C19.9524 25.0576 19.9524 25.0576 20.0083 25.0104C20.0083 25.0576 20.0083 25.1047 20.0083 25.1047ZM22.5245 15.7719C22.2449 15.7247 21.9653 15.9133 21.6298 15.819C21.5739 15.819 21.518 15.7719 21.518 15.7719C21.518 15.7247 21.5739 15.7247 21.6298 15.7247C21.9094 15.7247 22.189 15.7247 22.4685 15.6776L22.5245 15.7247C22.5804 15.6776 22.5804 15.7719 22.5245 15.7719ZM23.3073 15.7247C23.1395 15.6776 22.9718 15.819 22.6922 15.6776C22.7481 15.7247 22.6922 15.6776 22.6922 15.6776C22.7481 15.6305 22.804 15.5833 22.8599 15.5833C23.0277 15.5833 23.1954 15.6305 23.3073 15.6305L23.3632 15.6776C23.3632 15.7247 23.3632 15.7247 23.3073 15.7247ZM23.6427 15.7247C23.6427 15.6776 23.6427 15.6776 23.6427 15.7247C23.6427 15.6776 23.6427 15.6776 23.6427 15.6305C23.6987 15.6305 23.6987 15.6305 23.6427 15.7247C23.6987 15.6776 23.6427 15.6776 23.6427 15.7247ZM24.761 15.6305C24.6492 15.5833 24.5933 15.6776 24.5374 15.6776C24.4815 15.6776 24.3696 15.6776 24.3696 15.6305C24.3696 15.5362 24.4815 15.6305 24.4815 15.5833C24.5374 15.5362 24.6492 15.4891 24.761 15.5362C24.761 15.5362 24.817 15.5833 24.761 15.6305C24.817 15.5833 24.761 15.6305 24.761 15.6305ZM25.4879 15.5833C25.432 15.5833 25.3761 15.5833 25.3202 15.5362C25.2643 15.5362 25.2643 15.4891 25.2084 15.4891C25.2643 15.4891 25.3202 15.4891 25.3202 15.4891C25.3761 15.4891 25.3761 15.4891 25.432 15.4891C25.4879 15.4891 25.4879 15.4891 25.5438 15.4891L25.5998 15.5362C25.5438 15.5362 25.4879 15.5833 25.4879 15.5833ZM25.8793 15.4891C25.8234 15.5362 25.7675 15.5362 25.7116 15.4891C25.6557 15.4891 25.6557 15.4419 25.7116 15.4419C25.7116 15.4419 25.7675 15.4419 25.8793 15.4891C25.8793 15.4419 25.8793 15.4891 25.8793 15.4891ZM26.8299 15.5362C26.5503 15.4891 26.3266 15.4891 26.103 15.5833C26.0471 15.5833 25.9912 15.5833 25.9912 15.5362C25.9912 15.4891 25.9352 15.4419 25.8793 15.4419C25.8793 15.3948 25.9352 15.3477 25.9912 15.3948C26.2148 15.4419 26.3826 15.3005 26.6062 15.3948C26.718 15.4419 26.774 15.3005 26.8858 15.3477L26.9417 15.3948C26.8858 15.4891 26.8858 15.5362 26.8299 15.5362ZM27.2213 15.4419C27.1654 15.4419 27.1094 15.4419 27.1094 15.3948C27.1094 15.3005 27.2213 15.3477 27.2772 15.3477C27.3331 15.3477 27.389 15.3477 27.389 15.3948C27.389 15.4891 27.2772 15.4419 27.2213 15.4419ZM28.3396 15.5362C28.3396 15.4891 28.2836 15.4419 28.3396 15.4419C28.3396 15.3477 28.4514 15.3948 28.5073 15.3948V15.4419C28.4514 15.4891 28.3955 15.4891 28.3396 15.5362ZM30.4084 15.3477C30.3525 15.3005 30.2966 15.2534 30.2966 15.2063H30.3525C30.4643 15.2063 30.4084 15.2534 30.4084 15.3005V15.3477ZM33.26 2.57396C33.0923 2.52682 32.8686 2.47969 32.7009 2.62109C32.645 2.66823 32.5891 2.62109 32.5891 2.62109C32.0299 2.52682 31.4708 2.57396 30.8557 2.52682C30.3525 2.47969 29.7933 2.52682 29.2342 2.43255C29.1224 2.43255 29.0664 2.43255 28.9546 2.47969C28.8987 2.52682 28.7869 2.47969 28.731 2.52682C28.675 2.33828 28.5632 2.52682 28.4514 2.47969C28.2836 2.43255 28.1159 2.47969 27.9482 2.47969C27.8363 2.47969 27.7245 2.57396 27.5568 2.43255C27.6127 2.33828 27.4449 2.43255 27.3331 2.43255C27.3331 2.52682 27.2772 2.52682 27.2213 2.47969C27.1654 2.47969 27.1654 2.43255 27.1654 2.38542C27.1094 2.38542 27.1094 2.38542 27.0535 2.38542C27.0535 2.43255 27.0535 2.47969 26.9976 2.43255V2.38542C26.6062 2.33828 26.2148 2.38542 25.8234 2.29115C25.432 2.38542 25.0965 2.33828 24.761 2.38542C24.5933 2.43255 24.5374 2.38542 24.3696 2.38542C24.2578 2.38542 24.2019 2.33828 24.2578 2.24401C24.3137 2.10261 24.3696 2.10261 24.4815 2.14974C24.5933 2.19688 24.761 2.24401 24.8729 2.14974C24.9847 2.29115 25.0965 2.24401 25.2084 2.19688C25.432 2.10261 25.7116 2.19688 25.9352 2.14974C26.3266 2.10261 26.718 2.14974 27.1094 2.05547C27.4449 2.00833 27.4449 2.00833 27.8363 2.19688C27.9482 2.24401 28.0041 2.33828 28.06 2.29115C28.2277 2.14974 28.4514 2.24401 28.6191 2.19688C28.8428 2.14974 28.9546 2.19688 29.1224 2.24401C29.2342 2.24401 29.2901 2.14974 29.4019 2.19688C29.5138 2.24401 29.6256 2.19688 29.7933 2.19688C29.9611 2.14974 29.9611 2.33828 30.1288 2.33828C30.3525 2.33828 30.632 2.33828 30.8557 2.33828C30.9675 2.33828 31.0234 2.33828 31.1353 2.33828C31.4708 2.38542 31.8622 2.43255 32.1977 2.33828C32.3095 2.24401 32.3095 2.52682 32.4772 2.38542C32.5891 2.29115 32.7009 2.38542 32.8127 2.38542C32.9805 2.33828 33.1482 2.33828 33.26 2.38542C33.4278 2.43255 33.5396 2.33828 33.6514 2.38542C33.7073 2.38542 33.7633 2.43255 33.8192 2.43255C33.8192 2.43255 33.8192 2.47969 33.8192 2.52682L33.7633 2.57396C33.6514 2.52682 33.4837 2.62109 33.26 2.57396ZM31.9181 15.3477C31.8622 15.3477 31.8062 15.3477 31.7503 15.3477C31.6944 15.3477 31.6385 15.3477 31.5826 15.3005C31.5826 15.3005 31.5267 15.2534 31.5826 15.2534C31.6385 15.2063 31.9181 15.2534 31.9181 15.3477C31.9181 15.3005 31.9181 15.3477 31.9181 15.3477ZM48.0773 3.28099V3.32813H48.0214C48.0773 3.32813 48.0214 3.32813 48.0773 3.28099C48.0214 3.28099 48.0773 3.28099 48.0773 3.28099ZM47.8537 3.65807H47.7978C47.7419 3.65807 47.6859 3.65807 47.7419 3.61094H47.7978C47.7978 3.5638 47.8537 3.61094 47.8537 3.65807ZM47.4064 3.18672C47.4064 3.23386 47.4623 3.23386 47.4623 3.28099C47.4623 3.32813 47.4064 3.37526 47.3505 3.37526L47.2945 3.32813C47.2945 3.23386 47.3505 3.18672 47.4064 3.18672ZM44.4988 15.5833C44.4988 15.6305 44.4429 15.6305 44.4429 15.6776C44.4429 15.6776 44.4429 15.6305 44.387 15.5833C44.387 15.5362 44.4429 15.5362 44.4429 15.4891C44.4988 15.5362 44.4988 15.5833 44.4988 15.5833ZM46.4558 2.29115H46.5117C46.5677 2.29115 46.6236 2.29115 46.5676 2.33828H46.5117C46.5117 2.33828 46.4558 2.33828 46.4558 2.29115ZM46.2881 2.29115C46.2322 2.29115 46.1762 2.29115 46.1203 2.29115L46.0644 2.24401C46.1203 2.24401 46.1763 2.24401 46.1763 2.24401C46.2322 2.19688 46.2322 2.24401 46.2881 2.29115ZM43.8838 15.6305H43.8278C43.8278 15.6305 43.8278 15.6305 43.8278 15.5833C43.8278 15.6305 43.8278 15.6305 43.8838 15.6305ZM46.0644 1.86693C46.1203 1.86693 46.1763 1.86693 46.1763 1.86693C46.2322 1.86693 46.2322 1.91406 46.1203 1.91406C46.1203 1.91406 46.0644 1.91406 46.0085 1.86693C46.0085 1.91406 46.0085 1.86693 46.0644 1.86693ZM42.8773 17.7987L42.9332 17.8458C42.9332 17.893 42.8773 17.893 42.8214 17.893L42.7655 17.8458C42.7655 17.7987 42.8214 17.7987 42.8773 17.7987ZM44.6666 2.05547C44.8343 2.05547 44.9461 2.19688 45.1139 2.14974C45.1139 2.14974 45.1139 2.14974 45.1698 2.19688C45.1698 2.19688 45.1698 2.24401 45.1139 2.24401C45.058 2.24401 44.9461 2.29115 44.8343 2.24401C44.7784 2.24401 44.6666 2.24401 44.6106 2.14974C44.6106 2.10261 44.4988 2.14974 44.5547 2.05547C44.6106 2.05547 44.6106 2.05547 44.6666 2.05547ZM42.5418 17.563C42.5418 17.563 42.4859 17.563 42.5418 17.563C42.4859 17.563 42.4859 17.563 42.4859 17.5159H42.5418C42.4859 17.5159 42.5418 17.563 42.5418 17.563ZM44.1074 1.58412C44.1633 1.53698 44.3311 1.58412 44.3311 1.58412C44.387 1.72552 44.5547 1.67839 44.6666 1.72552L44.6106 1.77266C44.4429 1.77266 44.3311 1.67839 44.1633 1.72552C44.0515 1.77266 43.9397 1.77266 43.8838 1.72552C43.9397 1.67839 43.9956 1.63125 44.1074 1.58412ZM44.2192 2.05547C44.3311 2.10261 44.5547 2.05547 44.5547 2.14974C44.5547 2.38542 44.3311 2.14974 44.2192 2.29115C44.2192 2.29115 44.1633 2.33828 44.1074 2.29115C43.7719 2.19688 43.4364 2.33828 43.101 2.19688C42.8214 2.10261 42.5977 2.24401 42.3182 2.14974C42.2622 2.14974 42.2063 2.14974 42.2063 2.14974C42.2063 2.14974 42.1504 2.10261 42.2063 2.10261L42.2622 2.05547C42.3741 2.10261 42.4859 2.10261 42.5418 1.9612C42.5418 1.9612 42.5977 1.9612 42.6536 1.9612C42.9891 2.05547 43.2687 2.05547 43.6042 2.05547C43.7719 2.00833 43.9956 2.00833 44.2192 2.05547ZM40.4171 15.3948C40.473 15.3948 40.5289 15.3477 40.5848 15.3477C41.0321 15.3948 41.4794 15.3948 41.8708 15.3477C41.9268 15.3477 41.9827 15.3477 42.0386 15.3948C42.0386 15.3948 42.0386 15.4419 41.9827 15.4891L41.9268 15.5362C41.759 15.5362 41.6472 15.4891 41.4794 15.4891C41.3676 15.4891 41.1999 15.3948 41.144 15.5833H41.088C40.9203 15.3948 40.5848 15.5362 40.3612 15.4419L40.3052 15.3948C40.3612 15.3948 40.3612 15.3477 40.4171 15.3948ZM42.3741 2.66823C42.3741 2.62109 42.43 2.62109 42.4859 2.62109L42.5418 2.66823C42.5418 2.71537 42.4859 2.71537 42.43 2.71537C42.3741 2.66823 42.3741 2.66823 42.3741 2.66823ZM42.0386 1.9612C41.9827 1.9612 41.9268 1.9612 41.9268 1.86693C41.9268 1.81979 41.9827 1.81979 42.0386 1.81979C42.1504 1.77266 42.2622 1.81979 42.3741 1.86693C42.43 1.86693 42.43 1.91406 42.3741 1.9612C42.2622 2.00833 42.1504 1.9612 42.0386 1.9612ZM42.43 1.44271C42.43 1.44271 42.4859 1.44271 42.5418 1.44271C42.7655 1.39557 42.8214 1.67839 43.101 1.58412C43.2687 1.48984 43.4924 1.63125 43.6601 1.63125C43.716 1.63125 43.7719 1.63125 43.716 1.67839C43.716 1.67839 43.6601 1.67839 43.6042 1.67839C43.3246 1.63125 42.9891 1.77266 42.7655 1.63125C42.6536 1.63125 42.5418 1.58412 42.43 1.58412C42.3741 1.58412 42.2622 1.63125 42.3182 1.53698C42.3182 1.48984 42.3741 1.44271 42.43 1.44271ZM41.9268 1.53698C41.9827 1.53698 41.9827 1.53698 42.0386 1.53698C42.0945 1.53698 42.1504 1.58412 42.2063 1.58412C42.2622 1.58412 42.2622 1.58412 42.2622 1.63125L42.2063 1.67839C42.0945 1.67839 42.0386 1.63125 41.9268 1.63125C41.8708 1.63125 41.8708 1.58412 41.8149 1.58412C41.8149 1.48984 41.8708 1.48984 41.9268 1.53698ZM40.4171 2.05547C40.5848 2.10261 40.8085 1.9612 40.9762 2.05547C40.9762 2.05547 41.0321 2.05547 41.0321 2.00833L40.9762 1.9612C40.9203 1.91406 40.8085 1.91406 40.7526 1.91406L40.6966 1.86693C40.6966 1.86693 40.6966 1.86693 40.7526 1.86693C40.8085 1.86693 40.8644 1.86693 40.9203 1.81979C41.1999 1.81979 41.4235 1.86693 41.7031 1.81979C41.759 1.81979 41.8149 1.81979 41.759 1.91406C41.7031 2.10261 41.7031 2.10261 41.9827 2.05547H42.0386L42.0945 2.10261C42.0945 2.14974 42.0945 2.19688 42.0386 2.19688C41.9827 2.19688 41.9268 2.19688 41.8708 2.19688C41.4235 2.10261 40.9762 2.14974 40.5848 2.19688C40.5289 2.19688 40.5289 2.29115 40.473 2.19688C40.473 2.14974 40.4171 2.14974 40.4171 2.14974C40.3052 2.05547 40.4171 2.00833 40.4171 2.05547ZM41.4235 2.66823C41.3676 2.66823 41.3676 2.66823 41.4235 2.66823C41.3676 2.66823 41.3676 2.66823 41.3676 2.62109C41.3676 2.62109 41.3676 2.62109 41.4235 2.62109C41.3676 2.62109 41.3676 2.66823 41.4235 2.66823ZM41.1999 2.62109C41.1999 2.66823 41.1999 2.66823 41.1999 2.62109C41.144 2.62109 41.144 2.62109 41.144 2.57396C41.144 2.57396 41.144 2.57396 41.1999 2.57396C41.1999 2.62109 41.1999 2.62109 41.1999 2.62109ZM32.0858 15.3005C32.0858 15.3005 32.0858 15.2534 32.0858 15.3005C32.0858 15.2534 32.1417 15.2534 32.0858 15.3005C32.1417 15.2534 32.1417 15.2534 32.1417 15.3005C32.1417 15.2534 32.1417 15.3005 32.0858 15.3005ZM32.645 15.3948C32.5891 15.3477 32.4772 15.3948 32.4772 15.3005C32.4772 15.2534 32.5891 15.2063 32.7009 15.2063C32.8127 15.2063 32.8686 15.3005 32.8686 15.3477C32.8127 15.4419 32.7009 15.3948 32.645 15.3948ZM33.2041 15.1591C33.0923 15.1591 32.9804 15.0649 32.8686 15.1591C32.8127 15.2063 32.8127 15.1591 32.8127 15.112C32.8127 15.0649 32.8127 15.0177 32.8686 15.0177C32.9804 15.0177 33.1482 15.0649 33.26 15.0649C33.26 15.0649 33.26 15.112 33.3159 15.112C33.26 15.112 33.26 15.1591 33.2041 15.1591ZM33.8751 15.4419V15.3948C33.8751 15.3948 33.8751 15.3948 33.931 15.3948C33.931 15.3477 33.931 15.3948 33.8751 15.4419C33.931 15.3948 33.931 15.3948 33.8751 15.4419ZM32.4772 24.7748C32.4772 24.7748 32.4213 24.7276 32.4772 24.7276C32.5331 24.6805 32.5891 24.7276 32.5891 24.7276V24.7748C32.5331 24.8219 32.4772 24.8219 32.4772 24.7748ZM34.3224 15.2534C34.2106 15.2534 34.0428 15.1591 33.931 15.2534C33.931 15.2063 33.8751 15.1591 33.8192 15.112C33.8192 15.0649 33.8751 15.0649 33.931 15.0649C34.0987 15.112 34.2106 15.112 34.3783 15.1591C34.3783 15.1591 34.3783 15.2063 34.3224 15.2534C34.3783 15.2063 34.3783 15.2534 34.3224 15.2534ZM37.3418 2.62109C37.1181 2.7625 36.8945 2.57396 36.6149 2.66823C36.4471 2.71537 36.1676 2.57396 35.9439 2.66823C35.6643 2.57396 35.3289 2.66823 35.0493 2.62109C34.8815 2.57396 34.6579 2.71537 34.5461 2.62109C34.4342 2.57396 34.3224 2.57396 34.2106 2.52682C34.1547 2.52682 34.1547 2.43255 34.2106 2.43255C34.3224 2.43255 34.4342 2.33828 34.4901 2.29115C34.5461 2.24401 34.7138 2.29115 34.7697 2.33828C34.9375 2.47969 35.1611 2.47969 35.3848 2.43255C35.7203 2.43255 36.0557 2.43255 36.3353 2.38542C36.5031 2.38542 36.559 2.52682 36.7267 2.47969C36.8945 2.43255 37.0063 2.47969 37.174 2.52682C37.3418 2.57396 37.5095 2.43255 37.6773 2.52682C37.7332 2.52682 37.7332 2.47969 37.7332 2.43255C37.7332 2.33828 37.845 2.38542 37.9009 2.38542C38.2923 2.52682 38.2923 2.47969 38.7955 2.52682C39.2988 2.57396 39.802 2.43255 40.2493 2.57396C40.3612 2.62109 40.4171 2.57396 40.473 2.52682C40.5289 2.52682 40.5289 2.62109 40.5848 2.62109C40.5848 2.66823 40.5289 2.71537 40.473 2.66823C40.1934 2.57396 39.9138 2.71537 39.6343 2.62109C39.4106 2.7625 39.0751 2.52682 38.8515 2.66823C38.3482 2.57396 37.845 2.7625 37.3418 2.62109ZM36.8945 24.9162C36.8385 24.9162 36.8385 24.9162 36.8385 24.869C36.8385 24.869 36.8945 24.869 36.8945 24.8219C36.8945 24.869 36.8945 24.869 36.8945 24.9162ZM35.7203 24.869L35.6643 24.9162C35.6084 24.9162 35.5525 24.9162 35.4966 24.9162C35.4407 24.9162 35.3289 24.9162 35.3289 24.869C35.3289 24.8219 35.4407 24.8219 35.4966 24.8219H35.5525C35.6084 24.8219 35.6643 24.8219 35.7203 24.8219C35.7203 24.8219 35.7203 24.8219 35.7203 24.869ZM36.0557 24.869C35.9998 24.869 35.9998 24.869 35.9439 24.869C35.888 24.869 35.8321 24.8219 35.7762 24.8219C35.7203 24.8219 35.7203 24.8219 35.7203 24.7748L35.7762 24.7276C35.888 24.7276 35.9439 24.7748 36.0557 24.7748C36.1117 24.7748 36.1117 24.8219 36.1676 24.8219C36.1676 24.9162 36.1117 24.869 36.0557 24.869ZM36.3353 25.0576C36.2794 25.1047 36.2235 25.0576 36.1676 25.0576C36.1117 25.0576 36.0557 25.0104 36.1117 25.0104C36.1676 24.9633 36.2235 25.0104 36.2794 25.0104C36.3353 25.0104 36.3912 25.0104 36.3353 25.0576ZM36.8945 25.1047C36.8385 25.1047 36.7826 25.1047 36.7267 25.0576C36.6708 25.0576 36.6708 25.0104 36.6149 25.0104C36.6708 25.0104 36.7267 25.0104 36.7267 25.0104C36.7826 25.0104 36.7826 25.0104 36.8385 25.0104C36.8945 25.0104 36.8945 25.0104 36.9504 25.0104L37.0063 25.0576C36.9504 25.0576 36.9504 25.1047 36.8945 25.1047ZM40.6966 2.66823C40.6407 2.66823 40.5848 2.66823 40.6407 2.62109C40.6966 2.57396 40.7526 2.57396 40.8644 2.62109L40.9203 2.66823C40.8644 2.71537 40.7526 2.66823 40.6966 2.66823ZM37.4536 25.1047C37.3977 25.1047 37.3418 25.1047 37.3418 25.0576C37.3418 24.9633 37.4536 25.0104 37.4536 25.0104C37.5095 25.0104 37.5654 25.0104 37.5654 25.0576C37.5654 25.1518 37.4536 25.1047 37.4536 25.1047ZM39.0192 15.3005C39.0751 15.1591 39.2988 15.3477 39.4106 15.2534L39.4665 15.2063C39.6343 15.3948 39.8579 15.112 39.9138 15.3005C39.9698 15.3005 40.0257 15.3005 40.0816 15.3477C40.2493 15.3948 40.2493 15.3948 40.1375 15.5362C40.0816 15.6305 40.0816 15.5833 40.0257 15.5362C39.8579 15.4419 39.5784 15.4419 39.5784 15.4419C39.7461 15.6305 39.5784 15.5833 39.4665 15.5362C39.4106 15.5362 39.3547 15.4891 39.3547 15.4419C39.2988 15.3477 38.9633 15.5362 39.0192 15.3005ZM37.9009 24.9162C37.845 24.9162 37.7891 24.9162 37.7332 24.869C37.7332 24.869 37.6773 24.8219 37.7332 24.8219L37.7891 24.7748C37.845 24.7748 37.9009 24.7748 37.9568 24.7748C38.0687 24.8219 38.2364 24.7748 38.2364 24.8219C38.1246 25.0104 38.0127 24.9162 37.9009 24.9162ZM38.516 25.0576C38.516 25.1047 38.516 25.1518 38.4041 25.1518C38.3482 25.1518 38.2923 25.1518 38.2364 25.1047C38.1805 25.1047 38.1246 25.1047 38.0687 25.0576C38.0687 25.0576 38.0127 25.0104 38.0687 25.0104L38.1246 24.9633C38.2364 24.9633 38.3482 25.0576 38.4041 24.9162C38.4041 24.869 38.516 24.869 38.5719 24.869C38.5719 24.9633 38.516 25.0104 38.516 25.0576ZM38.9633 25.0104C38.9074 25.0104 38.8515 25.0104 38.7955 25.0104C38.7396 25.0104 38.6278 24.9633 38.5719 24.9633C38.516 24.9633 38.516 24.9633 38.516 24.9162L38.5719 24.869C38.6837 24.869 38.8515 24.9162 38.9633 24.9162C39.0192 24.9162 39.0192 24.9633 39.0751 24.9633C39.0751 25.0576 39.0192 25.0104 38.9633 25.0104ZM39.6902 25.0576C39.6343 25.0576 39.5784 25.0576 39.4665 25.0104V24.9633C39.4665 24.9633 39.4665 24.9633 39.5224 24.9633C39.5784 24.9633 39.6343 24.9633 39.6902 25.0104C39.7461 24.9633 39.9138 24.9162 39.8579 25.0576C39.8579 25.1047 39.7461 25.0104 39.6902 25.0576ZM40.0816 25.2461C40.0816 25.2461 40.0257 25.199 39.9697 25.199C40.0257 25.1518 40.0816 25.1518 40.1375 25.199C40.1934 25.199 40.1934 25.2461 40.2493 25.2461C40.1934 25.2932 40.1375 25.2932 40.0816 25.2461ZM40.6407 25.2461H40.5848C40.5289 25.2461 40.473 25.2461 40.5289 25.199H40.5848C40.6407 25.199 40.6966 25.199 40.6407 25.2461ZM40.8644 25.1518C40.7526 25.1047 40.5289 25.1518 40.473 25.0104C40.6407 24.9633 40.7526 25.0104 40.9203 25.0576C41.0321 25.1047 41.2558 25.0104 41.3117 25.199C41.144 25.199 40.9762 25.1518 40.8644 25.1518ZM42.43 17.9401C42.3182 17.9401 42.2063 17.9872 42.0945 17.9401C41.9268 17.9401 41.7031 17.7987 41.5354 17.893C41.3676 17.9872 41.144 17.7987 40.9762 17.9401C40.9762 17.9401 40.8644 17.9401 40.8085 17.9401C40.5848 17.9401 40.3612 17.7987 40.0816 17.893C40.0257 17.893 40.0257 17.8458 40.0257 17.8458L40.0816 17.7987C40.3052 17.7044 40.473 17.7516 40.8085 17.7516C41.144 17.7516 41.4235 17.7987 41.759 17.8458C41.8149 17.8458 41.8149 17.8458 41.8708 17.8458C42.0386 17.7044 42.2063 17.7987 42.43 17.7987C42.5977 17.7987 42.6536 17.893 42.6536 17.9872C42.6536 17.9872 42.4859 17.893 42.43 17.9401ZM42.8773 18.5057C42.8214 18.5057 42.8214 18.5057 42.7655 18.5057C42.7096 18.5057 42.7096 18.5057 42.6536 18.5057L42.5977 18.4586C42.6536 18.4586 42.6536 18.4115 42.7096 18.4115C42.7655 18.4115 42.8214 18.4115 42.8773 18.4586C42.9332 18.4586 42.9332 18.5057 42.9891 18.5057C42.9891 18.5057 42.9332 18.5057 42.8773 18.5057ZM45.6171 2.19688C45.5612 2.19688 45.5612 2.19688 45.5053 2.19688L45.4494 2.14974C45.5053 2.14974 45.5053 2.10261 45.5612 2.10261C45.6171 2.10261 45.673 2.10261 45.7289 2.14974C45.7848 2.14974 45.7848 2.19688 45.8408 2.19688C45.7848 2.19688 45.7289 2.19688 45.7289 2.19688C45.673 2.19688 45.673 2.19688 45.6171 2.19688ZM42.3182 25.3875C42.2622 25.2932 42.1504 25.2932 42.0945 25.2461C42.0945 25.1518 42.2063 25.199 42.2063 25.199C42.3182 25.199 42.3741 25.2461 42.3741 25.3404C42.3741 25.3404 42.3182 25.3404 42.3182 25.3875ZM43.5483 18.5057V18.4586C43.5483 18.4586 43.5483 18.4586 43.6042 18.4586C43.6042 18.4586 43.6042 18.5057 43.5483 18.5057C43.6042 18.5057 43.6042 18.5057 43.5483 18.5057ZM42.7655 25.2932C42.7096 25.2932 42.6536 25.2932 42.6536 25.2461C42.6536 25.1518 42.7655 25.199 42.8214 25.199C42.8773 25.199 42.9332 25.199 42.9332 25.2461C42.8773 25.3404 42.7655 25.2461 42.7655 25.2932ZM43.4364 17.9872C43.3246 17.9872 43.2687 17.9401 43.2128 17.9401C43.2128 17.9401 43.1569 17.893 43.2128 17.893L43.2687 17.8458C43.2687 17.8458 43.2687 17.8458 43.3246 17.8458C43.5483 17.8458 43.7719 17.8458 43.9956 17.8458C44.1074 17.8458 44.1633 17.9401 44.2752 17.9872C44.3311 17.9872 44.387 17.9872 44.387 18.0344C44.387 18.0344 44.3311 18.0815 44.3311 18.0344C43.9956 17.9401 43.6601 18.0815 43.4364 17.9872ZM43.4924 25.3875C43.4364 25.3875 43.3805 25.3875 43.3246 25.3404C43.2128 25.2932 43.101 25.3404 42.9891 25.2461C43.101 25.1518 43.2128 25.2461 43.2687 25.2461C43.3805 25.2461 43.4364 25.2932 43.4924 25.2932C43.4924 25.2932 43.5483 25.3404 43.4924 25.3404C43.5483 25.3875 43.5483 25.3875 43.4924 25.3875ZM47.1268 3.89375C47.0709 3.89375 47.0709 3.84662 47.015 3.84662C47.0709 3.84662 47.0709 3.84662 47.1268 3.79948C47.1827 3.79948 47.1827 3.84662 47.2386 3.84662C47.1827 3.84662 47.1268 3.89375 47.1268 3.89375ZM43.716 25.3404V25.2932C43.716 25.2932 43.716 25.2932 43.7719 25.2932C43.7719 25.2932 43.7719 25.2932 43.716 25.3404C43.7719 25.3404 43.716 25.3404 43.716 25.3404ZM44.9461 17.9401C45.002 17.9401 45.058 17.9401 45.058 17.9401L45.1139 17.9872C45.058 17.9872 45.002 17.9872 44.9461 17.9872C45.002 17.9872 45.002 17.9872 44.9461 17.9401ZM44.0515 25.3875H43.9956C43.9397 25.3875 43.8838 25.3875 43.9397 25.3404H43.9956C44.0515 25.2932 44.0515 25.3404 44.0515 25.3875ZM47.6859 3.23386H47.7419C47.7419 3.23386 47.7419 3.23386 47.7419 3.18672C47.7419 3.18672 47.7978 3.18672 47.7978 3.13958V3.18672L47.7419 3.23386H47.6859V3.28099L47.63 3.32813C47.63 3.28099 47.63 3.23386 47.6859 3.23386ZM44.4429 25.4347C44.387 25.4818 44.3311 25.4347 44.2752 25.4347C44.2192 25.4347 44.1633 25.3875 44.2192 25.3875C44.2752 25.3404 44.3311 25.3875 44.387 25.3875C44.4429 25.3875 44.4429 25.3875 44.4429 25.4347ZM45.5053 18.0815C45.4494 18.0815 45.3934 18.0815 45.2816 18.0344V17.9872C45.2816 17.9872 45.2816 17.9872 45.3375 17.9872C45.3934 17.9872 45.4494 17.9872 45.5053 18.0344C45.5612 18.0815 45.7289 17.9872 45.7289 18.1287C45.7289 18.1287 45.5612 18.0815 45.5053 18.0815ZM49.9784 11.1055C49.9225 11.1526 49.8666 11.1526 49.8107 11.1055C49.7548 11.1055 49.7548 11.0583 49.8107 11.0583C49.8666 11.0583 49.8666 11.0583 49.9784 11.1055C49.9784 11.0583 49.9784 11.0583 49.9784 11.1055ZM53.4451 10.3513V10.3042C53.4451 10.3042 53.4451 10.3042 53.501 10.3042C53.4451 10.3042 53.4451 10.3042 53.4451 10.3513ZM54.8989 5.44922C54.9548 5.44922 55.0107 5.30782 55.0666 5.40209C55.1226 5.44922 55.1785 5.44922 55.2344 5.49636C55.3462 5.54349 55.458 5.49636 55.5699 5.59063C55.458 5.63776 55.3462 5.59063 55.2344 5.54349C55.1785 5.54349 55.0666 5.49636 55.0107 5.49636C54.9548 5.49636 54.8989 5.44922 54.8989 5.44922ZM53.7806 10.7755C53.8365 10.7284 53.8924 10.7284 53.9484 10.8227C53.9484 10.8698 53.9483 10.9641 53.8924 11.0112H53.7806C53.7247 10.8698 53.6129 10.9169 53.501 10.8698C53.3892 10.8698 53.3333 10.8227 53.3892 10.7755C53.4451 10.7284 53.501 10.6341 53.5569 10.7755C53.6688 10.8698 53.7247 10.8227 53.7806 10.7755ZM53.1655 4.8836C53.2215 4.8836 53.2774 4.8836 53.3333 4.8836C53.3892 4.8836 53.501 4.8836 53.501 4.93073C53.501 5.025 53.3892 4.93073 53.3333 4.97787C53.2774 4.97787 53.2215 4.97787 53.1655 4.93073C53.1096 4.93073 53.1096 4.93073 53.1655 4.8836C53.1096 4.8836 53.1655 4.8836 53.1655 4.8836ZM52.6623 4.8836L52.7182 4.93073C52.7182 4.93073 52.7182 4.93073 52.6623 4.93073C52.6623 4.93073 52.6064 4.93073 52.6623 4.8836C52.6064 4.8836 52.6064 4.8836 52.6623 4.8836ZM52.6064 5.40209C53.1096 5.21354 53.5569 5.21354 54.0043 5.40209C54.1161 5.44922 54.172 5.35495 54.2279 5.40209L54.5075 5.44922L54.5634 5.49636C54.5075 5.49636 54.5075 5.54349 54.4516 5.49636C54.3397 5.44922 54.2838 5.59063 54.1161 5.54349C54.0043 5.49636 53.8365 5.44922 53.7247 5.54349C53.6688 5.35495 53.501 5.54349 53.3892 5.49636C53.1655 5.44922 52.886 5.44922 52.6064 5.49636C52.5505 5.49636 52.4946 5.44922 52.4946 5.40209C52.5505 5.40209 52.6064 5.40209 52.6064 5.40209ZM51.5999 10.257H51.6559C51.7118 10.257 51.7677 10.257 51.7118 10.3042H51.6559C51.5999 10.3042 51.5999 10.3042 51.5999 10.257ZM51.8236 4.8836L51.8795 4.83646C51.9354 4.83646 51.9913 4.83646 52.0473 4.83646C52.1032 4.83646 52.215 4.83646 52.215 4.8836C52.215 4.93073 52.1032 4.93073 52.0473 4.93073H51.9913C51.9354 4.93073 51.8795 4.93073 51.8236 4.93073C51.7677 4.93073 51.7677 4.8836 51.8236 4.8836ZM51.7118 4.93073H51.7677V4.97787L51.7118 5.025C51.7118 4.93073 51.7118 4.93073 51.7118 4.93073ZM51.0408 4.27084C51.0967 4.27084 51.1526 4.27084 51.2085 4.31797C51.3204 4.36511 51.4881 4.31797 51.4322 4.36511C51.4322 4.50651 51.3204 4.31797 51.2085 4.41224C51.0967 4.50651 51.0967 4.36511 51.0408 4.36511C50.9849 4.36511 50.929 4.36511 50.929 4.31797C50.929 4.27084 50.9849 4.27084 51.0408 4.27084ZM51.2085 4.83646C51.1526 4.83646 51.1526 4.8836 51.2085 4.83646C51.1526 4.8836 51.1526 4.83646 51.1526 4.83646C51.1526 4.83646 51.1526 4.83646 51.2085 4.83646C51.1526 4.83646 51.2085 4.83646 51.2085 4.83646ZM50.6494 4.17656H50.7053C50.7612 4.17656 50.8171 4.17656 50.7612 4.2237H50.7053C50.7053 4.2237 50.6494 4.2237 50.6494 4.17656ZM48.1333 3.98802C48.1333 3.94089 48.0773 3.89375 48.0773 3.89375C48.0773 3.84662 48.1892 3.84662 48.1892 3.89375C48.2451 3.94089 48.2451 3.98802 48.3569 3.98802V4.03516C48.301 4.03516 48.301 4.03516 48.2451 4.03516C48.301 4.08229 48.1892 4.08229 48.1333 3.98802ZM46.0644 18.1758C46.0644 18.1758 46.0085 18.0815 46.0644 18.0815C46.1203 17.9872 46.1763 18.0344 46.2881 18.0344C46.344 18.0344 46.344 18.0344 46.344 18.0815C46.2881 18.1287 46.1203 18.2229 46.0644 18.1758ZM47.8537 10.5399C47.7978 10.5399 47.7978 10.5399 47.8537 10.5399C47.8537 10.4927 47.8537 10.4927 47.8537 10.4456V10.4927C47.8537 10.5398 47.8537 10.5399 47.8537 10.5399ZM47.015 18.2229H46.9591C46.9031 18.2229 46.8472 18.2229 46.9031 18.1758H46.9591C47.015 18.1287 47.015 18.1758 47.015 18.2229ZM48.1333 10.4927L48.1892 10.4456C48.1892 10.4456 48.1892 10.4456 48.2451 10.4927C48.1892 10.4927 48.1333 10.4927 48.1333 10.4927ZM47.5182 15.8662C47.4623 15.8662 47.4064 15.819 47.4064 15.7719C47.4064 15.7247 47.4623 15.7247 47.5182 15.7247C47.5741 15.7247 47.63 15.7719 47.63 15.819C47.5741 15.819 47.5182 15.8662 47.5182 15.8662ZM46.0085 26.0474V26.0003C46.0085 26.0003 46.0085 26.0003 46.0644 26.0003C46.0085 26.0003 46.0085 26.0003 46.0085 26.0474ZM47.5741 18.1758V18.1287C47.5741 18.1287 47.63 18.1287 47.63 18.0815C47.63 18.0815 47.63 18.1287 47.5741 18.1758C47.63 18.1287 47.63 18.1758 47.5741 18.1758ZM49.7548 4.2237C49.6429 4.31797 49.587 4.2237 49.5311 4.17656C49.4752 4.12943 49.3634 4.08229 49.2515 4.03516C49.0838 3.94089 49.0838 3.94089 48.8601 4.03516C48.7483 4.08229 48.6924 4.03516 48.6365 4.03516C48.5806 4.03516 48.5806 3.98802 48.6365 3.94089C48.7483 3.89375 48.7483 3.79948 48.5806 3.79948C48.5247 3.79948 48.4687 3.79948 48.4128 3.75235C48.4128 3.75235 48.3569 3.70521 48.4128 3.70521L48.4687 3.65807C48.6365 3.70521 48.8042 3.70521 49.0279 3.75235C49.0838 3.79948 49.3075 3.79948 49.4752 3.84662C49.587 3.70521 49.6989 4.03516 49.8666 3.84662C49.9225 3.79948 50.2021 3.98802 50.258 4.08229C50.258 4.12943 50.2021 4.12943 50.2021 4.12943C49.9784 4.08229 49.8666 4.17656 49.7548 4.2237ZM47.9096 18.9771C47.9096 18.9771 47.9096 18.93 47.8537 18.93C47.8537 18.8828 47.9096 18.8357 47.9655 18.8357L48.0214 18.8828C48.0214 18.8828 47.9655 18.93 47.9096 18.9771ZM48.2451 18.3643C48.1892 18.3643 48.0773 18.3172 48.0214 18.3172H47.9655C47.9096 18.2701 47.7419 18.3172 47.7419 18.2229C47.8537 18.0344 47.8537 18.3172 47.9655 18.2701C48.0214 18.2229 48.1333 18.2701 48.2451 18.3172L48.301 18.3643C48.301 18.3172 48.2451 18.3643 48.2451 18.3643ZM49.2515 11.2469H49.3075C49.3634 11.2469 49.4193 11.2469 49.3634 11.294H49.3075C49.2515 11.294 49.2515 11.294 49.2515 11.2469ZM49.587 10.8227C49.5311 10.8698 49.3075 10.8227 49.2515 10.7284C49.1956 10.6813 49.1397 10.6341 49.1956 10.587C49.1956 10.4927 49.2515 10.5399 49.3634 10.5399C49.4193 10.5399 49.4193 10.5399 49.4752 10.5399C49.5311 10.5399 49.587 10.5399 49.6429 10.587C49.6989 10.6813 49.8107 10.6341 49.9784 10.6341C50.258 10.6341 50.5376 10.587 50.8171 10.6813C50.9849 10.7284 51.0967 10.6341 51.2645 10.6813C51.3763 10.7284 51.544 10.7755 51.7118 10.6813C51.8236 10.6341 51.9354 10.7284 52.1032 10.7284C52.215 10.7284 52.2709 10.7755 52.3827 10.7284C52.4946 10.6813 52.6064 10.6813 52.6623 10.6813C52.7741 10.6341 52.8301 10.8227 52.9419 10.7755C53.1096 10.7284 53.0537 10.7755 53.0537 10.8698C53.0537 10.9169 53.0537 11.0112 52.9419 11.0112C52.8301 11.0112 52.7741 10.9641 52.7182 10.9169C52.6064 10.9169 52.4946 10.9169 52.4387 10.8698C52.215 10.7755 51.9354 10.8698 51.7118 10.8698C51.5999 10.8698 51.4322 10.8698 51.3204 10.8698C51.2085 10.8227 51.0408 10.9641 50.9849 10.8227H50.929C50.6494 10.8698 50.3698 10.9169 50.1462 10.7755C49.9784 10.9169 49.7548 10.7284 49.587 10.8227ZM49.5311 12.0482C49.587 12.001 49.6429 11.9539 49.6989 11.9539C49.6989 11.9539 49.6989 12.001 49.6989 12.0482C49.6989 12.1425 49.6429 12.1425 49.587 12.0953C49.587 12.0953 49.587 12.0953 49.5311 12.0482ZM48.8601 18.3643C48.8042 18.3643 48.7483 18.3643 48.6924 18.3643L48.6365 18.3172C48.6365 18.2701 48.6924 18.2701 48.7483 18.2701C48.8042 18.2701 48.8042 18.2701 48.8601 18.2701C48.916 18.2229 48.972 18.1758 48.972 18.3172C48.9161 18.3172 48.916 18.3643 48.8601 18.3643ZM50.4257 12.1896C50.4257 12.2367 50.3698 12.2367 50.3139 12.2367C50.2021 12.2367 50.2021 12.1896 50.258 12.0953C50.258 12.0482 50.3139 12.0482 50.3698 12.0482C50.4257 12.0953 50.4257 12.1425 50.4257 12.1896ZM51.0967 12.0953C51.1526 12.0953 51.2085 12.0953 51.2085 12.1425L51.1526 12.1896C51.1526 12.1896 51.0967 12.1896 51.0967 12.0953C51.0408 12.1425 51.0967 12.0953 51.0967 12.0953ZM50.1462 18.4115C50.0903 18.4115 50.0903 18.3643 50.0343 18.3643C50.0903 18.3643 50.0903 18.3643 50.1462 18.3172C50.2021 18.3172 50.2021 18.3643 50.258 18.3643C50.2021 18.4115 50.1462 18.4115 50.1462 18.4115ZM50.5935 18.4586H50.5376C50.4817 18.4586 50.4257 18.4586 50.4817 18.4115H50.5376C50.5376 18.3643 50.5935 18.4115 50.5935 18.4586ZM51.6559 18.5529L51.5999 18.5057C51.5999 18.4586 51.6559 18.4586 51.7118 18.4586L51.7677 18.5057C51.7677 18.6 51.7118 18.6 51.6559 18.5529ZM55.6258 16.149V16.1018C55.6258 16.1018 55.6258 16.1018 55.6817 16.1018C55.6258 16.1018 55.6258 16.1018 55.6258 16.149C55.6817 16.149 55.6258 16.149 55.6258 16.149ZM56.6322 12.1425C56.6322 12.1425 56.5763 12.1425 56.5763 12.0953C56.5763 12.0953 56.5763 12.0953 56.6322 12.0953C56.6322 12.0953 56.6882 12.0953 56.6322 12.1425C56.6882 12.1425 56.6882 12.1425 56.6322 12.1425ZM57.3591 12.2367H57.3032C57.2473 12.2367 57.1914 12.2367 57.2473 12.1896H57.3032C57.3591 12.1896 57.3591 12.1896 57.3591 12.2367ZM57.471 12.4253C57.471 12.4253 57.471 12.3781 57.471 12.4253C57.5269 12.3781 57.5269 12.3781 57.5269 12.4253H57.471ZM57.6387 12.8966C57.5828 12.8966 57.5828 12.8495 57.5269 12.8495C57.5269 12.8495 57.5828 12.8495 57.6387 12.8024C57.6946 12.8024 57.6946 12.8495 57.7505 12.8495C57.6946 12.8966 57.6946 12.9438 57.6387 12.8966ZM58.2538 12.6609C58.2538 12.6138 58.2538 12.5667 58.2538 12.5667L58.3097 12.5195C58.3097 12.5667 58.3097 12.6138 58.3097 12.6609H58.2538Z\"\n      fill=\"#F8BC63\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 60 / 28,\n  svg: ThickBrush,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/tiltedBrushStroke.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Tilted Brush Stroke', 'sticker name', 'web-stories');\n\nconst TiltedBrush = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 48 38\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M46.8535 13.1484C46.7327 13.3096 46.6119 12.9873 46.4911 13.0679L46.4508 12.9873C46.4911 12.9873 46.4911 12.9068 46.5314 12.9068C46.6522 12.7456 46.7327 12.9873 46.8535 12.9873C46.8132 12.8262 46.8937 12.7456 46.9743 12.7456C47.1353 12.7456 47.2561 12.5845 47.2964 12.2622C47.3367 12.1011 47.0951 11.7789 46.934 11.6983C46.8937 11.6983 46.8535 11.6983 46.8535 11.6983C46.8132 11.6983 46.8132 11.6983 46.7729 11.6177C46.7729 11.5372 46.8132 11.5372 46.8132 11.4566C46.934 11.2955 47.0951 11.1344 47.2159 10.9732C47.2561 10.9732 47.3367 10.7315 47.2561 10.7315C47.0951 10.7315 47.0145 10.5704 46.934 10.2482C46.8535 9.92591 46.6522 10.1676 46.5314 10.0065C46.2092 9.60366 45.8469 9.76478 45.5247 9.44253C45.4845 9.44253 45.4039 9.44253 45.4039 9.52309C45.4039 10.1676 45.2429 9.68422 45.2026 9.60366C45.1623 9.52309 45.2026 9.36197 45.0818 9.36197C44.6792 9.44253 44.4778 8.87859 44.196 8.55633C44.0349 8.55633 44.0349 8.39521 44.1155 8.23408C44.1557 8.15352 44.196 8.07295 44.1557 7.99239C44.1155 7.91183 44.0752 7.91183 44.0349 7.99239C43.9141 8.07295 43.7933 8.07295 43.6725 7.83126C43.7531 7.67014 43.8336 7.50901 43.9544 7.42845C44.2363 7.10619 44.2765 6.62281 44.0349 6.30056C43.9141 6.13943 43.7933 5.89774 43.6725 5.81718C43.5115 5.65605 43.4712 5.49493 43.6725 5.25324C43.7531 5.17267 43.7933 4.93098 43.6725 4.76986C43.592 4.68929 43.6323 4.28648 43.4309 4.4476C43.3907 4.4476 43.3907 4.36704 43.3907 4.36704C43.5115 4.28648 43.6323 4.12535 43.6323 3.96422C43.6323 3.8031 43.431 3.8031 43.3907 3.48084C43.3907 3.40028 43.3907 3.31972 43.3504 3.15859C43.3504 2.99746 43.3102 2.99746 43.2296 2.9169C42.9478 2.75577 42.6257 2.59465 42.3438 2.27239C42.2633 2.19183 42.2633 2.27239 42.223 2.35296C42.1022 2.51408 41.9411 2.51408 41.8606 2.75577C41.9009 2.83634 41.9411 2.99746 42.0619 3.07803C42.1022 3.07803 42.1827 3.07803 42.223 2.99746C42.2633 2.99746 42.3035 3.07803 42.1425 3.07803C42.3035 3.23915 42.3035 3.40028 42.2633 3.31972C42.1827 3.23915 42.1022 3.23915 42.0619 3.15859C42.0619 3.15859 42.0217 3.15859 42.0217 3.07803C41.6996 3.15859 41.4982 3.07803 41.2969 2.9169C41.015 2.75577 40.6929 2.51408 40.4111 2.51408C40.089 2.51408 39.7668 2.27239 39.4447 2.19183C39.0421 2.11127 38.6797 2.11127 38.277 2.0307C37.9146 1.86958 37.4717 1.86958 37.0288 1.86958C36.6664 1.78901 36.304 1.78901 35.9014 1.78901C35.6598 1.78901 35.4585 1.62789 35.2169 1.70845C34.9753 1.78901 34.7337 1.54732 34.4519 1.70845C34.4116 1.78901 34.2908 1.86958 34.2103 1.78901C33.9284 1.62789 33.6465 1.62789 33.3244 1.70845C33.0023 1.86958 32.6802 1.62789 32.3983 1.86958C31.9554 2.11127 31.5125 1.78901 31.0696 2.11127C30.828 1.86958 30.5864 2.19183 30.4253 2.11127C30.1838 1.95014 29.9824 2.27239 29.8214 2.11127C29.5798 1.86958 29.4187 2.11127 29.2174 2.19183C29.0563 2.19183 28.9355 2.27239 28.7745 2.35296C28.2108 2.35296 27.6873 2.35296 27.2041 2.59465C27.0833 2.59465 27.0028 2.27239 26.9223 2.51408C26.7612 2.9169 26.5196 2.75577 26.3183 2.9169C26.1573 2.99746 25.9962 2.67521 25.8351 2.83634C25.6338 2.99746 25.4325 2.99746 25.2312 3.07803H25.1909C24.9493 2.75577 24.6674 3.23915 24.4259 3.07803C24.144 2.9169 23.9024 3.15859 23.6608 3.15859C23.5803 3.15859 23.54 3.23915 23.4595 3.23915C23.4192 3.23915 23.3387 3.31972 23.2984 3.15859C23.2984 3.07803 23.379 3.07803 23.4192 3.07803C23.6608 2.99746 23.8621 2.9169 24.1037 2.83634C24.2245 2.83634 24.2648 2.35296 24.3856 2.51408C24.5869 2.83634 24.7882 2.51408 24.9896 2.51408C25.4727 2.35296 25.9559 2.19183 26.3988 2.0307C26.5196 2.0307 26.6002 1.95014 26.721 2.0307C26.9626 2.35296 27.2444 2.19183 27.486 2.0307C27.6068 1.95014 27.7276 1.78901 27.8484 2.0307C27.8886 2.11127 27.9289 2.11127 27.9692 2.0307C28.7745 1.46676 28.855 1.46676 29.2979 1.62789C29.4993 1.70845 29.6603 1.86958 29.8214 1.46676C29.8214 1.3862 29.9422 1.3862 29.9422 1.46676C30.1032 1.86958 30.2643 1.62789 30.4253 1.46676C30.6267 1.3862 30.828 1.22507 30.9488 1.30563C31.3514 1.54732 31.6736 1.14451 32.0359 1.14451C32.0762 1.14451 32.0762 1.06394 32.1165 1.06394C32.0762 0.98338 32.0359 0.98338 31.9957 0.98338C31.9554 0.98338 31.8749 0.98338 31.8749 0.902817C31.6736 0.25831 31.3112 0.74169 31.0696 0.5C30.9488 0.98338 30.6267 0.5 30.4253 0.902817C30.3448 1.06394 30.224 0.661127 30.063 0.822253C29.9824 0.902817 29.8616 0.661127 29.7408 0.661127C29.62 0.661127 29.5798 1.14451 29.4187 0.822253C29.0966 0.98338 28.8147 0.74169 28.4926 0.902817C28.3718 0.98338 28.3718 1.30563 28.251 1.22507C28.1705 1.14451 28.0497 1.14451 27.9692 1.06394C27.8081 0.98338 27.6068 0.98338 27.4457 1.06394C27.2041 1.14451 26.9626 1.22507 26.721 1.30563C26.6002 1.3862 26.4391 1.06394 26.3988 1.54732C26.3988 1.62789 26.3183 1.62789 26.278 1.54732C26.117 1.22507 25.9559 1.3862 25.7949 1.46676C25.6338 1.54732 25.4325 1.22507 25.2714 1.46676C25.0701 1.78901 24.8688 1.62789 24.7077 1.54732C24.4661 1.46676 24.2245 1.54732 23.9829 1.62789C23.7816 1.78901 23.5803 1.3862 23.4192 1.78901C23.2582 1.3862 23.0971 2.0307 22.9361 1.86958C22.8153 2.19183 22.6945 1.86958 22.5737 1.95014C22.4529 1.95014 22.2918 2.0307 22.171 2.0307C21.9294 2.11127 21.7281 2.19183 21.5268 2.27239C21.4865 2.27239 21.406 2.27239 21.406 2.19183C21.406 2.11127 21.4462 2.0307 21.4462 1.95014C21.406 1.78901 21.2852 1.86958 21.2852 1.95014C21.1644 2.19183 21.0436 2.27239 20.8825 2.27239C20.7617 2.27239 20.6812 2.51408 20.6007 2.59465C20.4799 2.75577 20.3994 2.27239 20.2786 2.67521C20.2383 2.83634 20.0772 2.43352 19.9564 2.75577C19.9162 2.9169 19.7148 2.67521 19.6343 2.9169C19.2317 2.67521 18.829 2.9169 18.4666 3.23915C18.4264 3.31972 18.3861 3.31972 18.3458 3.23915C18.1848 2.9169 18.064 3.23915 17.9432 3.23915C17.7821 3.31972 17.7016 3.88366 17.5405 3.48084C17.3795 3.8031 17.1782 3.72253 17.0171 3.64197C16.9366 4.12535 16.7755 3.64197 16.6547 3.88366C16.5742 4.04479 16.3728 4.04479 16.2521 4.12535C15.8494 4.20591 15.4468 4.36704 15.0441 4.4476C14.9233 4.52817 14.9233 4.68929 15.0038 4.85042C15.0441 4.76986 15.1246 4.85042 15.1649 4.76986C15.2052 4.68929 15.2857 4.76986 15.2857 4.85042C15.2857 5.01155 15.2052 4.93098 15.0441 4.93098C15.0844 5.01155 15.0038 4.93098 15.0038 4.93098C14.8428 4.85042 14.7622 4.68929 14.6415 4.76986C14.3596 4.93098 14.0777 4.93098 13.7959 5.09211C13.5946 5.25324 13.353 5.3338 13.2322 5.65605C13.2724 5.65605 13.3127 5.65605 13.3932 5.81718C13.4335 5.81718 13.4335 5.89774 13.3932 5.89774C13.4335 5.97831 13.4335 5.97831 13.4335 5.97831C13.3932 5.97831 13.3932 5.97831 13.353 5.89774V5.81718C13.2724 5.81718 13.2322 5.73662 13.2322 5.65605C13.0711 5.57549 12.9101 5.41436 12.7893 5.73662C12.749 5.89774 12.6282 5.89774 12.5477 5.89774C12.3866 5.65605 12.2256 5.73662 12.1048 6.05887C12.0645 6.13943 11.984 6.13943 11.9437 6.05887C11.8632 5.89774 11.7424 5.97831 11.7021 6.05887C11.541 6.46169 11.2592 6.13943 11.0981 6.38112C10.9371 6.78394 10.6955 6.70338 10.4539 6.78394C10.3331 6.8645 10.172 6.78394 10.0512 6.94507C9.89018 7.26732 9.68885 7.34788 9.44726 7.34788C9.20567 7.34788 9.04461 7.7507 8.80302 7.7507C8.40037 7.83126 8.03799 8.23408 7.6756 8.55633C7.55481 8.6369 7.47428 8.87859 7.31322 8.71746C7.23269 8.6369 7.03136 8.71746 6.9911 8.87859C6.8703 9.20084 6.70924 9.12028 6.58845 9.20084C6.42739 9.20084 6.34686 9.60366 6.14553 9.60366C5.86368 9.60366 5.66235 10.087 5.3805 10.087C5.17917 10.3287 4.93758 10.3287 4.73625 10.7315C4.69599 10.7315 4.69599 10.8121 4.69599 10.8927C4.73625 10.8927 4.73625 10.9732 4.77652 10.9732C4.97784 10.9732 5.17917 10.9732 5.3805 11.1344C5.54156 10.7315 5.78315 10.9732 5.94421 10.7315C6.22606 10.2482 6.58845 10.1676 6.91057 9.84535C7.43401 9.44253 7.99772 9.20084 8.52117 8.87859C8.88355 8.6369 9.24594 8.6369 9.60832 8.31464C9.84991 8.07295 10.0915 8.15352 10.3331 7.83126C10.5344 7.67014 10.8163 7.7507 11.0579 7.42845C11.1787 7.26732 11.38 7.26732 11.541 7.26732C11.7021 7.18676 11.8632 7.26732 11.984 6.94507C12.145 7.10619 12.2658 6.8645 12.3866 6.78394C12.5477 6.70338 12.7087 6.70338 12.8698 6.62281C12.9906 6.54225 13.1516 6.62281 13.2322 6.46169C13.353 6.13943 13.5543 6.13943 13.6348 6.22C13.7959 6.38112 13.8764 6.05887 13.9972 6.05887C14.1583 6.05887 14.3193 6.05887 14.4401 5.89774C14.6817 5.57549 14.9233 5.57549 15.1649 5.49493C15.4468 5.41436 15.6883 5.17267 15.9702 5.41436C16.091 5.49493 16.2923 5.41436 16.4131 5.25324C16.5339 5.01155 16.6547 4.93098 16.7755 4.85042C16.8963 4.76986 17.0171 4.85042 17.0976 4.60873C17.2184 4.20591 17.2989 4.85042 17.46 4.60873C17.5003 4.52817 17.6613 4.60873 17.7016 4.52817C17.9029 4.04479 18.1848 4.28648 18.4264 4.28648C18.4666 4.28648 18.4666 4.36704 18.5069 4.36704C18.5069 4.4476 18.4666 4.4476 18.4666 4.52817C18.3458 4.85042 18.225 4.76986 18.1042 4.85042C17.46 5.09211 16.8158 5.25324 16.1715 5.49493C16.0507 5.57549 15.8897 5.49493 15.8091 5.73662L14.9233 6.13943C14.6415 6.13943 14.3596 6.22 14.118 6.38112C13.9972 6.62281 13.7959 6.54225 13.7154 6.78394C13.5543 7.10619 13.4335 6.94507 13.3127 6.8645C13.1516 6.78394 13.1516 7.26732 12.9906 7.02563C12.8698 6.8645 12.749 7.02563 12.6685 7.26732C12.6282 7.34788 12.5879 7.26732 12.5074 7.34788C12.3463 7.50901 12.145 7.34788 12.0242 7.67014C11.9437 7.91183 11.7424 7.50901 11.5813 7.83126C11.5008 7.99239 11.3397 7.99239 11.2189 7.99239C11.0579 7.99239 10.9773 8.31464 10.8163 8.31464C10.615 8.31464 10.4136 8.47577 10.2123 8.47577C10.011 8.47577 9.89018 8.95915 9.68885 8.87859C9.52779 8.79802 9.407 9.44253 9.20567 9.12028C9.00435 9.44253 8.72249 9.52309 8.4809 9.68422C8.19905 9.84535 7.95746 10.0065 7.6756 10.1676C7.07163 10.4093 6.54818 11.0538 5.94421 11.376C5.82341 11.4566 5.74288 11.6983 5.58182 11.6983C5.54156 11.6983 5.46103 11.7789 5.50129 11.8594C5.50129 11.94 5.58182 12.0206 5.62209 12.0206C5.70262 12.1011 5.86368 12.1011 5.94421 11.8594C6.1858 11.376 6.50792 11.2955 6.78977 11.0538C7.11189 10.8121 7.39375 10.4899 7.75613 10.4899C8.07825 9.92591 8.56143 10.2482 8.88355 9.68422C9.44726 9.68422 9.89018 9.03971 10.4539 8.95915C10.5344 8.95915 10.6552 8.95915 10.6955 8.87859C10.8565 8.55633 11.0981 8.55633 11.2995 8.47577C11.541 8.47577 11.6618 8.15352 11.8632 8.07295C12.1048 7.99239 12.4269 8.07295 12.7087 7.7507C12.9503 7.42845 13.3127 7.58957 13.5946 7.18676C13.7154 7.02563 13.8764 7.10619 14.0375 7.02563C14.1985 6.94507 14.3999 7.02563 14.5207 6.8645C14.6415 6.62281 14.8025 6.8645 14.8428 6.70338C14.9636 6.38112 15.1246 6.46169 15.2857 6.38112C15.6481 6.22 16.0507 6.13943 16.4131 5.97831C17.0171 5.73662 17.6211 5.73662 18.1848 5.17267C18.2653 5.09211 18.3861 5.01155 18.4264 5.09211C18.668 5.3338 18.8693 5.09211 19.1109 5.01155C19.7148 4.93098 20.3591 4.68929 20.9631 4.4476C21.1241 4.36704 21.3254 4.60873 21.4462 4.4476C21.6878 4.12535 21.9697 4.20591 22.2113 4.04479C22.3321 4.28648 22.4529 4.12535 22.5737 4.12535C22.775 4.20591 22.8555 3.72253 23.0568 3.88366C23.2179 4.04479 23.379 3.8031 23.5803 3.8031C23.7011 3.8031 23.8219 3.72253 23.9427 3.88366C24.1037 3.40028 24.3856 3.56141 24.6272 3.48084C24.8688 3.40028 25.0701 3.15859 25.3117 3.40028C25.7546 3.15859 26.1975 3.31972 26.6002 3.15859C26.8015 3.07803 27.0028 2.83634 27.2041 3.07803C27.4055 2.75577 27.6068 2.83634 27.8081 2.9169C27.9289 2.9169 28.09 2.83634 28.251 2.75577C28.3718 2.75577 28.4926 2.67521 28.6134 2.75577C28.7745 2.9169 28.9758 2.9169 29.0563 2.59465C29.1771 2.83634 29.3382 2.67521 29.459 2.67521C29.9422 2.43352 30.4656 2.67521 30.9488 2.35296C30.9891 2.35296 31.0293 2.35296 31.0293 2.35296C31.593 2.75577 32.1165 2.35296 32.6802 2.35296C33.0828 2.35296 33.4855 2.43352 33.8881 2.19183H33.9284C34.4518 2.51408 34.9753 2.19183 35.539 2.19183C35.8209 2.19183 36.0625 2.11127 36.3443 2.27239C36.4248 2.35296 36.4651 2.27239 36.5456 2.27239C36.7872 2.11127 37.0288 2.27239 37.2704 2.35296C37.512 2.35296 37.7938 2.19183 37.9952 2.51408C38.0354 2.59465 38.0757 2.51408 38.116 2.51408C38.3576 2.35296 38.5991 2.59465 38.8005 2.59465C38.9615 2.59465 39.1226 2.75577 39.2434 2.67521C39.485 2.51408 39.7668 2.67521 40.0084 2.67521C40.25 2.67521 40.4916 3.07803 40.7735 3.15859C40.8137 3.15859 40.854 3.23915 40.854 3.31972C40.854 3.40028 40.7735 3.48084 40.7332 3.40028C40.5319 3.15859 40.4111 3.15859 40.3708 3.64197C40.3305 3.88366 40.1292 3.96422 40.0084 3.8031C39.646 3.48084 39.646 3.40028 39.4447 3.48084C39.2836 3.56141 39.1629 3.40028 39.0018 3.40028C38.9213 2.99746 38.7199 3.07803 38.5589 3.15859C38.2368 3.31972 37.9146 3.07803 37.5925 3.31972C37.5925 3.31972 37.5523 3.23915 37.512 3.23915C37.3912 3.15859 37.2301 3.07803 37.1093 3.15859C36.7872 3.23915 36.5054 2.99746 36.2235 3.15859C35.9819 2.83634 35.6598 3.40028 35.3779 3.07803C34.774 3.15859 34.17 2.99746 33.6063 3.23915C33.566 3.23915 33.4855 3.31972 33.4452 3.31972C33.2842 3.07803 33.1231 3.23915 32.962 3.31972C32.801 3.40028 32.6802 3.15859 32.4789 3.23915C32.2373 3.31972 32.0359 3.31972 31.7541 3.31972C31.5125 3.31972 31.2709 3.15859 31.0293 3.31972C30.828 3.40028 30.5461 3.40028 30.3046 3.40028C29.9824 3.40028 29.6603 3.56141 29.2979 3.56141C28.9758 3.48084 28.6537 3.8031 28.3316 3.64197C28.2913 3.64197 28.251 3.64197 28.251 3.64197C27.9289 4.04479 27.6068 4.12535 27.2444 3.96422C26.6404 4.28648 26.0365 4.12535 25.4727 4.36704C25.2714 4.4476 25.0701 4.52817 24.8688 4.4476C24.5467 4.36704 24.2245 4.68929 23.9427 4.52817C23.7816 4.76986 23.6206 4.60873 23.4595 4.68929C23.0166 4.76986 22.5334 5.01155 22.0905 4.93098C21.9697 4.93098 21.7684 4.93098 21.6878 5.17267C21.567 5.3338 21.3657 4.85042 21.3254 5.3338C21.3254 5.41436 21.2047 5.49493 21.1644 5.41436C20.9631 5.17267 20.7617 5.41436 20.5604 5.41436C19.7954 5.65605 19.0706 5.89774 18.3458 6.13943C18.225 6.22 18.0237 6.13943 17.9432 6.22C17.7419 6.46169 17.5405 6.38112 17.3392 6.54225C17.0976 6.62281 16.8963 6.70338 16.695 6.70338C16.4936 6.78394 16.3326 7.10619 16.1313 6.94507C15.9299 6.78394 15.7689 7.26732 15.6078 7.26732C14.8025 7.42845 14.0777 8.07295 13.3127 8.23408C13.1919 8.23408 13.0711 8.23408 12.9906 8.39521C12.6685 8.79802 12.3061 8.6369 12.0242 8.95915C11.7021 9.36197 11.38 9.2814 11.0579 9.44253C10.9773 9.52309 10.8565 9.44253 10.776 9.52309C10.4539 10.0065 10.0915 10.0065 9.72912 10.2482C9.52779 10.4093 9.2862 10.4093 9.04461 10.7315C8.80302 10.9732 8.52117 11.2149 8.19905 11.2149C8.11852 11.2149 8.03799 11.2149 7.99772 11.2955C7.83666 11.7789 7.43401 11.4566 7.27295 11.94C6.9911 11.94 6.74951 12.3428 6.46765 12.4234C6.10527 12.5845 5.78315 12.9873 5.42076 13.3096C5.2597 13.5513 5.13891 13.9541 4.85705 13.9541C4.77652 14.4375 4.4544 14.0346 4.3336 14.518C4.09201 14.1958 3.97122 14.8403 3.72963 14.7597C3.60883 14.7597 3.40751 14.6791 3.32698 15.082C3.08539 15.0014 2.92433 15.4042 2.68274 15.4848C2.36062 15.5653 2.07876 15.8876 1.79691 16.2099C1.63585 16.2904 1.51505 16.371 1.51505 16.7738C1.31373 17.0155 1.27346 17.66 0.991607 17.66C0.870812 18.0628 0.588956 17.9017 0.427896 18.3045C0.347366 18.4656 0.186306 18.7073 0.226571 18.8684C0.266836 19.0296 0.427896 18.8684 0.548691 18.8684C0.629221 18.8684 0.709751 18.7879 0.790281 18.7879C0.870812 18.7879 0.870812 18.7879 0.911077 18.949C0.951342 19.1907 1.03187 19.1907 1.1124 18.949C1.19293 18.7879 1.27346 18.7073 1.39426 18.8684C1.43452 18.949 1.51505 18.949 1.47479 18.8684C1.47479 18.7073 1.47479 18.5462 1.59558 18.5462C1.75664 18.6267 1.55532 18.7879 1.59558 18.8684C1.63585 18.949 1.71638 18.8684 1.75664 18.7879C1.75664 18.7073 1.79691 18.7073 1.79691 18.7879C1.87744 18.6267 1.87744 18.6267 1.87744 18.7073C1.87744 18.7879 1.87744 18.7879 1.83717 18.8684C1.83717 19.2713 1.79691 19.6741 1.99823 19.6741C2.23982 19.7546 2.36062 20.1575 2.48141 20.4797C2.60221 20.802 2.60221 21.0436 2.48141 21.2048C2.44115 21.2853 2.40088 21.2048 2.36062 21.2853C2.19956 21.4465 2.0385 21.6882 1.95797 22.0104C1.9177 22.091 1.9177 22.1715 1.95797 22.2521C1.99823 22.4132 2.07876 22.4132 2.11903 22.3327C2.36062 22.0104 2.68274 21.9298 2.92433 21.6076C3.08539 21.3659 3.16592 21.6076 3.28671 21.6076C3.28671 21.6076 3.32698 21.6882 3.32698 21.7687C3.24645 22.091 3.16592 22.2521 3.00486 22.2521C2.723 22.1715 2.52168 22.6549 2.28009 22.7355C2.19956 22.7355 2.15929 22.816 2.11903 22.9772C2.07876 23.0577 2.0385 23.1383 2.07876 23.2994C2.07876 23.38 2.15929 23.38 2.19956 23.38C2.40088 23.2994 2.56194 23.0577 2.723 22.8966C2.80353 22.7355 2.8438 22.816 2.92433 22.8966C3.24645 23.2189 3.24645 23.1383 3.44777 23.1383C3.81016 23.1383 4.09201 22.5744 4.4544 22.5744C4.49466 22.5744 4.53493 22.4132 4.53493 22.4132C4.85705 22.091 5.17917 21.8493 5.46103 21.6076C5.54155 21.527 5.62209 21.4465 5.66235 21.6882C5.74288 21.9298 5.62209 21.9298 5.58182 22.0104C5.17917 22.4938 5.17917 22.5744 4.69599 22.6549C4.37387 22.7355 4.13228 23.0577 3.89069 23.38C3.85042 23.38 3.85042 23.4606 3.81016 23.5411C3.85042 23.5411 3.89069 23.5411 3.89069 23.5411C3.97122 23.5411 4.01148 23.4606 4.09201 23.4606C4.25307 23.38 4.25307 23.4606 4.17254 23.8634C4.13228 23.9439 4.17254 24.0245 4.21281 24.1051C4.37387 24.3467 4.29334 24.4273 4.13228 24.5079C4.09201 24.5079 4.01148 24.5079 4.01148 24.669C4.01148 24.7496 4.09201 24.7496 4.13228 24.7496C4.29334 24.9107 4.4544 24.9107 4.61546 24.669C4.73625 24.5079 4.85705 24.5079 4.97784 24.5079C5.17917 24.5884 5.3805 24.5884 5.62209 24.5884C5.62209 24.5884 5.66235 24.5079 5.66235 24.5884C5.70262 24.5079 5.70262 24.5079 5.70262 24.5079C5.70262 24.5884 5.70262 24.5884 5.66235 24.669C5.66235 24.669 5.66235 24.669 5.62209 24.669C5.62209 25.2329 5.82341 25.3941 5.98447 25.6358C6.14553 25.8775 6.14553 26.1997 6.1858 26.522C6.22606 26.7636 6.02474 26.7636 5.98447 26.8442C5.82341 27.0053 5.74288 27.4082 5.58182 27.5693C5.54156 27.5693 5.46103 27.7304 5.50129 27.8915C5.54155 28.0527 5.58182 27.9721 5.66235 28.0527C5.74288 28.1332 5.78315 28.2138 5.70262 28.4555C5.62209 28.6972 5.66235 28.8583 5.82341 29.0194C6.065 29.1805 6.34686 29.1805 6.58845 29.1805C6.66898 29.1805 6.74951 29.1 6.83004 29.1805C6.8703 29.2611 6.95083 29.2611 6.95083 29.4222C6.95083 29.5834 6.8703 29.5834 6.83004 29.6639C6.42739 29.9056 6.065 30.1473 5.74288 30.7112C5.70262 30.7918 5.62209 30.7918 5.58182 30.8724C5.13891 31.4363 4.65572 31.8391 4.25307 32.4836C3.97122 32.8865 3.89069 33.2087 3.97122 33.8532C4.05175 33.8532 4.13228 33.7727 4.25307 33.4504C4.3336 33.0476 4.37387 32.6448 4.4544 32.967C4.65572 32.4031 4.69599 32.4836 4.69599 32.6448C4.65572 32.967 4.57519 33.2893 4.4544 33.6115C4.41413 33.7727 4.37387 33.6115 4.3336 33.6115C4.29334 33.8532 4.25307 33.9338 4.21281 34.0949C4.13228 34.256 4.09201 34.4172 4.25307 34.3366C4.4544 34.3366 4.57519 34.4172 4.49466 34.82L4.53493 34.9811C4.65573 34.9811 4.73625 35.0617 4.73625 35.3839C4.73625 35.7062 4.97784 35.3839 4.97784 35.7062C5.05837 35.7062 5.13891 35.6256 5.21944 35.6256C5.2597 35.6256 5.2597 35.2228 5.34023 35.545C5.3805 35.7062 5.42076 35.8673 5.29997 35.9479C5.21944 36.0284 5.17917 36.1896 5.13891 36.2701C5.05838 36.3507 5.01811 36.3507 5.01811 36.5118C5.01811 36.6729 5.13891 36.5924 5.17917 36.6729C5.29997 36.8341 5.42076 36.7535 5.54156 36.7535C5.86368 36.6729 6.14553 36.5118 6.46765 36.4312C6.62871 36.3507 6.74951 36.2701 6.74951 36.7535C6.74951 36.8341 6.78977 36.9146 6.8703 36.8341C7.03136 36.6729 7.15216 36.9952 7.27295 36.9146C7.39375 36.8341 7.39375 37.0758 7.35348 37.2369C7.35348 37.398 7.27295 37.5591 7.39375 37.4786C7.51454 37.398 7.71587 37.6397 7.71587 37.0757C7.71587 36.9146 7.7964 36.9952 7.7964 37.0757C7.7964 37.3174 7.87693 37.3174 7.95746 37.3174C8.19905 37.2369 8.4809 37.2369 8.72249 37.0757C8.96408 36.9146 9.24594 37.1563 9.48753 37.0757C9.76938 36.9146 10.0915 36.7535 10.4136 36.9146C10.4942 36.9952 10.6955 36.9146 10.7357 36.7535C10.8565 36.4312 11.0176 36.5118 11.1384 36.4312C11.7424 36.3507 12.3061 35.7062 12.9503 35.6256C13.0309 35.6256 13.0711 35.6256 13.1114 35.4645C13.1919 35.3034 13.2724 35.3839 13.3932 35.3034C13.514 35.2228 13.5946 35.4645 13.6751 35.3839C13.7959 35.3034 13.8764 35.0617 13.9972 35.0617C14.3193 35.0617 14.6012 34.9005 14.883 34.82C15.0844 34.7394 15.3662 34.82 15.487 34.256C15.5273 34.1755 15.6481 34.1755 15.7689 34.0949C15.8091 34.0949 15.8897 34.1755 15.9299 34.1755C16.0105 33.6921 16.2118 34.1755 16.3729 33.9338C16.4936 33.6921 16.7352 33.7727 16.9366 33.6921C17.0171 33.6921 17.0976 33.6115 17.1379 33.4504C17.2989 33.2087 17.46 33.3698 17.6211 33.4504C17.7821 33.4504 17.8627 32.8865 18.1042 33.2087C18.1445 33.3698 18.2653 33.2893 18.3458 33.1282C18.4264 32.8865 18.5472 32.967 18.668 32.8865C18.829 32.8059 18.9901 32.8059 19.1511 32.7253C19.3122 32.6448 19.4733 32.6448 19.6343 32.5642C19.7954 32.4836 19.9564 32.5642 20.0772 32.4031C20.198 32.1614 20.3591 32.4031 20.5201 32.3225C21.3657 32.0808 22.171 31.4363 23.0166 31.2752C23.1776 30.9529 23.379 31.2752 23.54 31.1141C23.6206 31.0335 23.6608 30.7918 23.8219 31.0335C23.9024 31.1141 24.0232 30.7918 24.1037 30.7112C24.144 30.7112 24.2245 30.6307 24.2245 30.7112C24.3856 30.8724 24.5064 30.7112 24.6272 30.7112C24.8285 30.7112 24.9896 30.7112 25.1909 30.7112C25.513 30.7112 25.8754 31.0335 26.1975 30.4696C26.278 30.3084 26.4391 30.3084 26.5599 30.5501C26.6404 30.7113 26.721 30.7112 26.8418 30.6307C27.0028 30.5501 27.1639 30.389 27.2847 30.5501C27.486 30.7113 27.486 30.2279 27.6471 30.389C27.7679 30.4696 27.9289 30.2279 28.0497 30.4696C28.09 30.5501 28.2108 30.4696 28.2913 30.3084C28.3718 30.1473 28.4926 30.0667 28.5732 30.3084C28.694 30.4696 28.7745 30.6307 28.8953 30.3084C29.0161 29.9056 29.2174 29.9056 29.4187 29.9862C29.9824 30.2279 29.9824 30.1473 30.4253 29.7445C30.5864 29.5834 30.7475 29.5834 30.8683 29.6639C30.9488 29.7445 31.0293 29.9862 31.1501 29.9056C31.4722 29.6639 31.8346 29.9862 32.1567 29.7445C32.5191 29.5028 32.9218 29.8251 33.3244 29.5834H33.3647C33.6465 29.8251 33.9687 29.7445 34.2908 29.6639C34.6129 29.5834 34.9753 29.7445 35.2974 29.5028C35.4182 29.4222 35.539 29.5028 35.6598 29.5028C35.8611 29.5834 36.143 29.5834 36.2638 29.1C36.304 28.8583 36.4248 28.9389 36.5054 28.8583C36.5456 28.8583 36.6262 28.7777 36.6262 28.8583C36.6262 28.9389 36.5859 29.0194 36.5859 29.1C36.5859 29.1805 36.4651 29.4222 36.5456 29.3417C36.8275 29.2611 37.0691 29.5028 37.3509 29.3417C37.4717 29.3417 37.9146 29.1805 37.9952 29.3417C38.1562 29.5028 38.2368 29.3417 38.3576 29.1C38.5186 28.7777 38.6394 28.6972 38.7602 29.1C38.8407 29.4222 38.9615 29.3417 39.0823 29.1805C39.0823 29.0194 39.0823 28.9389 39.1226 29.1C39.2031 28.8583 39.2434 28.8583 39.2836 28.8583C39.2434 29.0194 39.2031 29.1 39.1629 29.2611C39.1629 29.2611 39.1629 29.2611 39.1226 29.2611C39.1226 29.4222 39.1629 29.4222 39.2031 29.4222C39.4447 29.4222 39.7266 29.5028 39.9682 29.3417C40.1292 29.6639 40.3708 29.4222 40.5721 29.5028C40.7735 29.5834 40.9748 29.4222 41.2566 29.2611C41.2566 29.1805 41.2969 29.1 41.3372 29.2611C41.4177 29.1805 41.458 29.1805 41.458 29.1805C41.458 29.3417 41.4177 29.3417 41.3372 29.3417C41.3774 29.6639 41.4982 29.6639 41.619 29.6639C41.8203 29.6639 41.9814 29.5028 42.1827 29.6639C42.3035 29.7445 42.5049 29.4222 42.6256 29.5834C42.827 29.7445 42.8672 29.4222 42.9478 29.3417C43.0283 29.2611 43.0283 29.2611 43.0686 29.4222C43.1894 29.9862 43.1894 29.9862 43.4309 29.9056C43.592 29.8251 43.7531 30.0667 43.9141 29.9862C44.0752 29.8251 44.196 29.9056 44.3168 30.2279C44.3168 30.2279 44.5986 30.2279 44.5986 30.0667C44.5986 29.5834 44.7597 29.6639 44.8805 29.7445C44.9208 29.7445 44.961 29.8251 45.0013 29.7445C45.0415 29.5834 45.1221 29.4222 45.1623 29.2611C45.3234 28.7777 45.1623 28.2138 44.9208 28.2943C44.7194 28.3749 44.5181 28.1332 44.3168 28.2138C44.196 27.7304 43.8739 28.2138 43.7933 27.6498C43.7933 27.6498 43.6725 27.6498 43.6725 27.7304C43.6725 27.811 43.6725 27.8915 43.6725 28.0527C43.6323 28.4555 43.592 28.6166 43.3907 28.3749C43.2296 28.2138 43.1088 28.0527 42.9075 28.0527C42.8672 28.0527 42.7464 27.9721 42.7867 27.811C42.7867 27.7304 42.827 27.4082 42.9478 27.5693C43.0686 27.7304 43.0686 27.4082 43.1088 27.4082C43.2296 27.4082 43.3504 27.247 43.3504 27.6498C43.3504 27.7304 43.3504 27.811 43.3907 27.9721C43.3907 28.0527 43.4309 28.0527 43.4309 28.1332C43.4712 28.0527 43.4712 27.9721 43.5115 27.8915C43.5517 27.811 43.5517 27.6498 43.5517 27.4887C43.5517 27.0053 43.5517 27.0053 43.7933 27.1665C43.9141 27.247 44.0752 27.1665 44.196 27.5693C44.2363 27.7304 44.3973 27.4082 44.4376 27.3276C44.4778 27.0859 44.357 27.247 44.3168 27.247C44.2362 27.1665 44.2765 27.1665 44.3168 27.0053C44.3973 26.8442 44.3168 26.522 44.3168 26.522C44.1155 26.6831 44.1557 26.0386 43.9947 26.1997C43.8336 26.3608 43.7128 26.0386 43.592 25.958C43.4712 25.7969 43.3504 25.4746 43.1491 25.7163C43.1088 25.7969 43.0686 25.6358 43.0283 25.6358C42.5451 25.4746 42.0619 25.1524 41.5385 25.4746C41.4982 25.4746 41.458 25.4746 41.458 25.4746C41.4177 25.3941 41.3372 25.3135 41.3372 25.2329C41.3372 25.1524 41.4177 25.1524 41.458 25.1524C41.6996 25.0718 41.9411 24.9913 42.1827 24.9107C42.3438 24.8301 42.4646 24.7496 42.5854 25.0718C42.7062 25.3135 42.9075 25.1524 42.9478 25.0718C43.0686 24.7496 43.2296 24.8301 43.3504 24.7496C43.7933 24.4273 44.2765 24.669 44.7597 24.5079C44.9208 24.4273 45.1623 23.9439 45.3234 24.5079H45.4039C45.565 24.5079 45.8066 24.1856 45.9274 23.7828C45.9676 23.6217 46.0482 23.4606 46.169 23.4606C46.2898 23.4606 46.3703 23.38 46.4911 23.4606C46.6119 23.5411 46.8132 23.38 46.8535 23.1383C46.8937 22.7355 47.0548 22.4938 47.0951 22.2521C47.1353 21.8493 47.2561 21.7687 47.4575 21.6882C47.538 21.6882 47.6185 21.6076 47.699 21.6076C47.7393 21.6076 47.7393 21.527 47.7796 21.4465C47.7393 21.4465 47.7393 21.3659 47.699 21.3659C47.5783 21.3659 47.4172 21.4465 47.2964 21.527C47.1353 21.6076 47.1756 21.2853 47.0951 21.2048C46.9743 21.1242 47.0548 21.0436 47.0951 20.8825C47.1756 20.7214 47.2159 20.3991 47.2964 20.3186C47.538 20.0769 47.4575 19.9158 47.2964 19.7546C47.2561 19.6741 47.1353 19.6741 47.2159 19.5129C47.2561 19.4324 47.2964 19.5129 47.3769 19.4324V19.5129C47.3769 19.5129 47.4172 19.5935 47.4575 19.5935C47.4575 19.5935 47.4575 19.5129 47.4977 19.5129L47.4575 19.4324H47.4172C47.3769 19.1907 47.4172 18.949 47.2964 18.7879C47.2159 18.7073 47.2964 18.5462 47.4172 18.3045C47.4575 18.2239 47.538 18.0628 47.4172 17.9017C47.2561 17.66 47.2561 17.4989 47.3769 17.2572C47.3769 17.2572 47.4575 17.2572 47.4575 17.1766C47.538 17.0155 47.538 16.8544 47.4172 16.7738C47.2159 16.6127 46.934 16.6932 46.7729 16.2904C46.5716 15.8876 46.4911 15.8876 46.2092 15.9682C46.1287 15.9682 46.0482 15.9682 45.9676 15.8876C45.9274 15.807 45.8469 15.9682 45.8066 15.807C45.8066 15.7265 45.8871 15.5653 45.9274 15.4848C46.0482 15.4042 46.169 15.3237 46.2898 15.4848C46.3703 15.6459 46.5314 15.4042 46.6522 15.6459C46.8535 15.2431 47.1353 15.4042 47.3769 15.2431C47.4575 15.2431 47.4977 15.2431 47.5783 15.1625C47.7393 15.082 47.7393 14.6791 47.6185 14.518C47.2561 13.7124 47.0145 13.5513 46.8535 13.1484ZM5.98447 10.1676C5.98447 10.1676 5.94421 10.087 5.94421 10.0065C5.94421 10.0065 5.94421 9.92591 5.98447 9.92591C5.98447 10.0065 5.98447 10.0065 5.98447 10.1676C5.98447 10.087 5.98447 10.087 5.98447 10.1676ZM19.5135 4.36704C19.3525 4.4476 19.1914 4.4476 19.0303 4.52817C18.9498 4.52817 18.829 4.60873 18.7485 4.60873C18.7082 4.60873 18.6277 4.68929 18.6277 4.52817C18.6277 4.4476 18.7082 4.28648 18.7485 4.20591C18.9498 4.04479 19.2317 4.20591 19.5135 4.20591L19.5538 4.28648C19.5135 4.28648 19.5135 4.36704 19.5135 4.36704ZM19.7954 4.28648C19.7954 4.28648 19.7551 4.20591 19.7551 4.12535C19.7551 4.12535 19.7551 4.04479 19.7954 4.04479L19.8356 4.12535C19.8356 4.20591 19.7954 4.20591 19.7954 4.28648ZM22.9361 3.40028C21.9294 3.31972 21.0033 3.96422 20.0772 4.20591C20.037 4.20591 19.9967 4.20591 19.9967 4.12535C19.9967 4.12535 20.037 4.04479 20.0772 4.04479C20.198 4.04479 20.3591 3.64197 20.5604 3.8031C20.6409 3.88366 20.7617 3.8031 20.8423 3.64197C20.8825 3.40028 20.9631 3.48084 21.0436 3.48084C21.4865 3.56141 21.6878 3.48084 22.2113 3.07803C22.4529 2.9169 22.6945 2.99746 22.9361 2.99746C22.9763 2.99746 23.0568 3.15859 23.0568 3.23915C23.0568 3.48084 22.9763 3.31972 22.9361 3.40028ZM5.86368 35.3839C5.86368 35.3839 5.82341 35.3839 5.82341 35.3034C5.82341 35.2228 5.78315 35.0617 5.86368 34.9811C5.90394 34.9811 5.94421 34.9811 5.98447 35.0617C5.94421 35.1422 5.94421 35.3034 5.86368 35.3839ZM6.83004 28.1332C6.74951 28.536 6.62871 28.536 6.50792 28.536C6.38712 28.536 6.30659 28.6166 6.22606 28.6166L6.1858 28.536C6.1858 28.536 6.1858 28.4555 6.22606 28.4555C6.30659 28.4555 6.46765 28.4555 6.50792 28.3749C6.58845 28.1332 6.66898 27.9721 6.83004 28.1332ZM6.62871 27.4887C6.46765 27.1665 6.42739 27.7304 6.30659 27.5693C6.26633 27.5693 6.22606 27.5693 6.1858 27.4887C6.1858 27.4082 6.22606 27.4082 6.22606 27.3276C6.30659 27.0053 6.46765 27.1665 6.58845 27.0859C6.66898 27.0859 6.74951 26.9248 6.83004 27.0859C6.74951 27.247 6.62871 27.4887 6.62871 27.4887ZM11.0579 10.8121C11.0176 10.7315 11.0176 10.651 11.0579 10.651C11.0579 10.651 11.0981 10.651 11.0981 10.7315C11.0981 10.7315 11.0981 10.8121 11.0579 10.8121ZM12.6282 10.087C12.5477 10.087 12.5074 10.1676 12.4269 10.1676C12.3866 10.1676 12.3463 10.1676 12.3463 10.1676C12.3061 10.1676 12.3061 10.1676 12.3061 10.087C12.3061 10.0065 12.6282 9.84535 12.6685 9.92591C12.6685 10.0065 12.6282 10.087 12.6282 10.087ZM12.9503 10.0065C12.9101 10.0065 12.9101 10.0065 12.8698 9.92591C12.9101 9.84535 12.9503 9.76478 12.9906 9.60366C12.9906 9.68422 13.0309 9.68422 13.0309 9.76478C13.0711 9.92591 13.0309 10.0065 12.9503 10.0065ZM13.4738 9.84535C13.3932 9.84535 13.2724 9.68422 13.2724 9.60366C13.2322 9.36197 13.3932 9.52309 13.4335 9.44253C13.514 9.44253 13.5946 9.2814 13.5946 9.52309C13.6348 9.60366 13.5543 9.84535 13.4738 9.84535ZM14.1985 9.36197C14.1583 9.36197 14.118 9.44253 14.118 9.36197C14.0777 9.36197 13.9569 9.52309 13.9569 9.2814C13.9569 9.12028 14.0375 8.95915 14.118 8.95915C14.1583 8.95915 14.1985 9.12028 14.2388 9.03971C14.3193 8.95915 14.4401 8.55633 14.4804 9.03971C14.5207 9.44253 14.3193 9.2814 14.1985 9.36197ZM14.7622 8.95915C14.722 8.95915 14.722 8.95915 14.6817 8.87859C14.6817 8.87859 14.6817 8.79802 14.722 8.79802C14.7622 8.79802 14.7622 8.79802 14.8025 8.79802C14.8025 8.87859 14.7622 8.95915 14.7622 8.95915ZM15.8091 8.71746C15.8091 8.79802 15.7689 8.79802 15.7689 8.87859C15.6883 8.71746 15.6078 8.79802 15.5675 8.71746C15.487 8.87859 15.487 8.95915 15.4468 8.95915C15.4468 8.95915 15.4065 8.87859 15.4065 8.79802H15.3662C15.2454 8.79802 15.2052 9.12028 15.0441 9.12028C14.9636 9.12028 14.9233 9.03971 14.9233 8.95915C14.9233 8.87859 14.9233 8.79802 15.0038 8.79802C15.0844 8.79802 15.1246 8.71746 15.2454 8.71746C15.2857 8.71746 15.326 8.71746 15.326 8.79802C15.2857 8.71746 15.326 8.71746 15.3662 8.71746C15.3662 8.71746 15.4065 8.71746 15.4065 8.79802C15.4065 8.79802 15.4065 8.79802 15.4065 8.87859C15.4468 8.87859 15.487 8.87859 15.487 8.87859C15.487 8.87859 15.487 8.87859 15.5273 8.87859C15.5273 8.87859 15.487 8.87859 15.487 8.79802C15.487 8.71746 15.5675 8.6369 15.6481 8.6369C15.6078 8.55633 15.6078 8.6369 15.6078 8.6369C15.7689 8.47577 15.7689 8.55633 15.8091 8.71746ZM17.0976 7.99239C16.856 8.07295 16.6547 8.55633 16.3729 8.47577C16.2521 8.47577 16.0105 8.79802 16.0105 8.47577C15.9299 7.99239 16.2118 8.15352 16.3326 8.07295C16.4936 7.91183 16.695 8.07295 16.8158 7.7507C16.8963 7.58957 16.9768 7.91183 17.0574 7.83126C17.1379 7.83126 17.1379 7.99239 17.0976 7.99239ZM17.7016 7.99239C17.6211 8.07295 17.5808 8.07295 17.5003 8.07295C17.46 8.07295 17.3795 8.15352 17.3392 7.99239C17.3392 7.83126 17.3392 7.7507 17.4197 7.7507C17.5003 7.7507 17.5808 7.67014 17.6613 7.67014C17.6613 7.67014 17.7016 7.7507 17.7419 7.83126C17.7419 7.83126 17.7419 7.99239 17.7016 7.99239ZM18.9901 7.42845C18.9901 7.50901 18.9901 7.58957 18.9498 7.58957C18.829 7.67014 18.7082 7.67014 18.5472 7.7507C18.4264 7.7507 18.2653 7.99239 18.1042 7.7507C18.064 7.7507 18.0237 7.67014 18.0237 7.67014C18.0237 7.50901 18.064 7.50901 18.1042 7.42845C18.225 7.26732 18.3056 6.94507 18.5069 7.18676C18.6277 7.34788 18.7888 7.10619 18.9095 7.10619C18.9901 7.18676 19.0303 7.34788 18.9901 7.42845ZM19.433 7.42845C19.3927 7.42845 19.3927 7.42845 19.3525 7.42845C19.3927 7.26732 19.433 7.18676 19.433 7.02563C19.4733 7.10619 19.4733 7.10619 19.5135 7.18676C19.5135 7.26732 19.5135 7.42845 19.433 7.42845ZM20.2786 7.10619C20.198 7.26732 20.0772 7.02563 19.9967 7.02563C19.8759 7.02563 19.7551 7.26732 19.5941 7.02563C19.7148 6.8645 19.8759 6.8645 19.9967 6.78394C20.0772 6.70338 20.1578 6.70338 20.2383 6.70338C20.3188 6.70338 20.4396 6.54225 20.4396 6.8645C20.4799 7.18676 20.3591 7.10619 20.2786 7.10619ZM22.2918 6.70338C22.2515 6.70338 22.2113 6.70338 22.2113 6.70338H22.171C21.9697 6.8645 21.8086 6.62281 21.6878 6.54225C21.6476 6.54225 21.8489 6.30056 22.0502 6.38112C22.0905 6.38112 22.0905 6.46169 22.1307 6.46169C22.171 6.46169 22.2113 6.46169 22.2918 6.46169C22.3321 6.46169 22.3723 6.46169 22.3723 6.46169C22.3723 6.62281 22.3321 6.62281 22.2918 6.70338ZM23.9829 6.05887C23.8219 6.05887 23.7414 6.70338 23.54 6.22C23.4998 6.13943 23.379 6.30056 23.2984 6.30056C23.2179 6.30056 23.1374 6.46169 23.0568 6.38112C22.9361 6.30056 22.775 6.30056 22.6542 6.22C22.7347 5.89774 22.8958 6.05887 23.0166 5.97831C23.0568 5.97831 23.0971 5.97831 23.1374 5.89774C23.4192 5.81718 23.6608 5.81718 23.9427 5.89774C23.9829 5.89774 23.9829 5.89774 24.0232 5.97831L23.9829 6.05887ZM29.3785 5.01155C29.3785 5.17267 29.2979 5.41436 29.1771 5.3338C29.0563 5.17267 29.0161 5.17267 28.9758 5.41436C28.8147 5.17267 28.7342 5.49493 28.6537 5.57549C28.5732 5.65605 28.5732 5.65605 28.4926 5.57549C28.3718 5.41436 28.3316 5.41436 28.1302 5.49493C27.9289 5.49493 27.7276 5.81718 27.486 5.57549C27.2847 5.3338 27.2041 6.05887 26.9626 5.81718C26.8015 5.65605 26.6404 5.57549 26.4794 5.65605C26.3183 5.73662 26.1573 5.89774 25.9559 5.81718C25.7949 5.81718 25.5935 5.89774 25.4325 5.97831C25.3117 6.05887 25.1506 6.13943 25.0701 5.89774C25.0298 5.81718 24.9896 5.73662 24.9493 5.89774C24.8688 6.05887 24.7882 6.05887 24.748 6.05887C24.5869 5.73662 24.3856 6.22 24.2245 6.05887C24.1037 5.97831 24.1843 5.89774 24.2245 5.81718C24.2245 5.49493 24.3856 5.49493 24.4259 5.57549C24.5467 5.73662 24.6674 5.65605 24.7882 5.65605C25.3117 5.41436 25.8754 5.57549 26.4391 5.3338C26.6002 5.25324 26.7612 5.41436 26.882 5.17267C27.0028 4.93098 27.1236 5.49493 27.2847 5.17267C27.4055 4.85042 27.5263 5.09211 27.6873 5.17267C27.7679 5.17267 27.8886 5.17267 27.9692 5.09211C28.3718 4.85042 28.7745 5.17267 29.1771 4.93098C29.2577 4.68929 29.3785 4.85042 29.3785 5.01155ZM29.9019 5.25324C29.8214 5.01155 29.6603 5.25324 29.5395 5.09211C29.4993 5.09211 29.4993 5.01155 29.4993 4.93098C29.4993 4.85042 29.4993 4.76986 29.5395 4.76986C29.7006 4.76986 29.8616 4.76986 29.9824 4.76986V4.85042H30.0227C29.9422 5.17267 29.9019 5.17267 29.9019 5.25324ZM30.1032 4.85042C30.063 4.85042 29.9824 5.01155 29.9824 4.76986C29.9824 4.68929 30.0227 4.68929 30.063 4.68929C30.1032 4.68929 30.1435 4.68929 30.2643 4.60873C30.1838 4.68929 30.1435 4.76986 30.1032 4.85042ZM32.1567 27.7304C32.1567 27.6498 32.1567 27.6498 32.197 27.5693C32.197 27.5693 32.2373 27.5693 32.2373 27.6498C32.197 27.6498 32.197 27.7304 32.1567 27.7304ZM33.4855 27.7304L33.4452 27.6498C33.4452 27.6498 33.4452 27.5693 33.4855 27.5693C33.4855 27.5693 33.4855 27.5693 33.4855 27.7304C33.5258 27.6498 33.4855 27.6498 33.4855 27.7304ZM33.2036 5.01155C33.1634 4.93098 33.1634 5.01155 33.2036 5.01155C33.1634 4.93098 33.1634 4.85042 33.2036 4.85042C33.2036 4.85042 33.2439 4.85042 33.2439 4.93098C33.2036 4.93098 33.2036 4.93098 33.2036 5.01155ZM34.0089 5.57549C34.0492 5.57549 34.0895 5.49493 34.1297 5.49493C34.17 5.49493 34.17 5.57549 34.1297 5.65605C34.0895 5.65605 34.0492 5.65605 34.0089 5.65605C33.9687 5.65605 33.9687 5.57549 34.0089 5.57549ZM36.2235 27.5693C36.143 27.6498 35.9417 27.5693 35.8611 27.4082C35.8209 27.3276 35.8611 27.247 35.9014 27.1665C36.0222 26.8442 36.1027 27.247 36.2235 27.1665C36.2235 27.1665 36.2638 27.247 36.2638 27.3276C36.2235 27.4887 36.2235 27.5693 36.2235 27.5693ZM36.7067 27.1665C36.7067 27.247 36.747 27.4082 36.6664 27.4082C36.6262 27.4082 36.6262 27.247 36.6262 27.1665C36.6262 27.0859 36.5456 26.9248 36.6664 26.9248C36.7067 26.8442 36.7067 27.0053 36.7067 27.1665ZM34.8545 4.93098C34.8142 5.09211 34.7337 5.17267 34.6532 5.01155C34.4921 4.68929 34.2505 4.76986 34.0895 4.68929C33.9284 4.68929 33.7271 4.85042 33.6063 4.52817C33.566 4.36704 33.4855 4.52817 33.405 4.52817C33.2439 4.60873 33.0426 4.60873 32.8815 4.68929C32.801 4.68929 32.7205 4.76986 32.7607 5.01155C32.7607 5.09211 32.7205 5.25324 32.6802 5.09211C32.5997 4.60873 32.4386 4.85042 32.3178 4.93098C31.9957 5.01155 31.7138 5.17267 31.3917 4.93098C31.2306 4.85042 31.1098 5.25324 30.9891 5.09211C30.8683 4.93098 30.7072 5.01155 30.5864 5.09211C30.4656 5.09211 30.3448 5.25324 30.3046 4.93098C30.9488 4.68929 31.4722 4.36704 31.9554 4.68929C31.9957 4.68929 32.0762 4.60873 32.1567 4.60873C32.3178 4.60873 32.5191 4.36704 32.6802 4.52817C32.8815 4.68929 32.9218 4.12535 33.0828 4.20591C33.3647 4.36704 33.7271 4.04479 34.0089 4.4476C34.0895 4.52817 34.1297 4.4476 34.2103 4.4476C34.3713 4.36704 34.4921 4.36704 34.6532 4.28648C34.935 4.20591 34.9753 4.28648 34.8545 4.93098ZM37.0691 27.0859C37.0288 27.0859 36.9885 27.1665 36.9483 27.0859C36.9483 27.0859 36.9483 26.9248 36.9885 26.9248C37.0288 26.9248 37.0691 26.8442 37.1093 26.9248C37.0691 27.0053 37.0691 27.0859 37.0691 27.0859ZM35.4182 4.60873C35.3779 4.68929 35.3377 4.85042 35.3377 4.85042C35.2169 4.85042 35.1364 4.60873 35.0156 4.52817C35.0558 4.36704 35.0558 4.28648 35.0961 4.20591C35.0961 4.20591 35.0961 4.12535 35.1364 4.12535C35.1766 4.36704 35.2974 4.52817 35.4182 4.60873ZM35.6598 4.85042C35.5793 4.85042 35.5793 4.85042 35.5793 4.76986C35.5793 4.52817 35.6195 4.36704 35.7001 4.36704C35.7403 4.36704 35.7806 4.52817 35.7403 4.60873C35.7001 4.68929 35.6598 4.76986 35.6598 4.85042ZM35.7806 4.85042C35.7403 4.85042 35.7403 4.85042 35.7806 4.85042C35.7403 4.76986 35.7403 4.68929 35.7806 4.68929C35.8209 4.68929 35.8209 4.76986 35.8209 4.76986C35.8209 4.85042 35.7806 4.85042 35.7806 4.85042ZM35.9417 4.04479C35.9014 4.04479 35.8611 4.12535 35.8209 4.04479C35.8209 4.04479 35.8209 3.88366 35.8611 3.88366C35.9014 3.88366 35.9417 3.8031 35.9819 3.88366C35.9417 3.96422 35.9417 4.04479 35.9417 4.04479ZM38.0354 27.4082C37.9952 27.4082 37.9952 27.4082 37.9549 27.4082C37.9952 27.247 38.0354 27.0859 38.0757 26.9248C38.0757 27.0053 38.116 27.0859 38.116 27.0859C38.1562 27.247 38.1562 27.4082 38.0354 27.4082ZM38.4784 27.4082C38.3978 27.4887 38.3576 27.3276 38.3173 27.3276L38.277 27.247C38.3173 27.247 38.3173 27.1665 38.3576 27.1665C38.3978 27.0053 38.4381 27.1665 38.4784 27.247L38.5186 27.3276C38.5186 27.4082 38.4784 27.4082 38.4784 27.4082ZM36.3443 4.85042C36.304 4.93098 36.304 4.93098 36.304 4.93098C36.2638 4.85042 36.1832 4.85042 36.1832 4.76986C36.143 4.68929 36.1832 4.60873 36.2235 4.60873C36.304 4.60873 36.3846 4.52817 36.5054 4.52817C36.5859 4.60873 36.6664 4.68929 36.7067 4.76986C36.5859 4.68929 36.4651 4.68929 36.3443 4.85042ZM37.0288 5.09211C36.9885 5.09211 36.9885 5.01155 36.9885 5.01155C37.0288 5.09211 37.0288 5.09211 37.0288 5.09211ZM37.0691 5.01155C37.0691 5.01155 37.0288 5.01155 37.0288 4.93098H37.0691C37.0691 4.93098 37.0691 4.93098 37.0691 5.01155ZM39.0823 27.0053C39.0823 26.9248 39.0421 26.9248 39.0421 26.8442C39.0421 26.8442 39.0421 26.7636 39.0823 26.7636C39.0823 26.8442 39.0823 26.9248 39.0823 27.0053ZM39.4447 29.1C39.4044 29.0194 39.4044 28.9389 39.4447 28.9389C39.4447 28.9389 39.485 28.9389 39.485 29.0194C39.485 29.0194 39.485 29.1 39.4447 29.1ZM37.5523 4.28648C37.5523 4.52817 37.5523 4.76986 37.3509 4.85042C37.1899 4.93098 37.0288 4.85042 36.908 4.76986C36.7067 4.4476 36.8275 4.36704 36.9885 4.4476C37.1093 4.60873 37.3509 4.52817 37.4717 4.20591C37.4717 4.12535 37.5523 4.12535 37.5925 4.20591C37.5925 4.20591 37.5925 4.28648 37.5523 4.28648ZM37.7938 4.85042C37.7536 4.85042 37.7133 4.93098 37.673 4.85042C37.673 4.85042 37.6731 4.68929 37.7133 4.68929C37.7536 4.68929 37.7938 4.60873 37.8341 4.68929C37.8341 4.76986 37.8341 4.85042 37.7938 4.85042ZM37.9549 5.17267C37.9549 5.17267 37.9146 5.09211 37.9146 5.01155C37.9146 5.01155 37.9146 4.93098 37.9549 4.93098L37.9952 5.01155C37.9549 5.17267 37.9549 5.17267 37.9549 5.17267ZM39.8876 27.1665C39.8474 27.0859 39.8474 27.0053 39.8876 27.0053C39.8876 27.0053 39.9279 27.0053 39.9279 27.0859C39.9279 27.0859 39.9279 27.0859 39.8876 27.1665ZM37.9952 4.76986C37.9952 4.76986 37.9549 4.68929 37.9549 4.60873C37.9549 4.60873 37.9549 4.52817 37.9952 4.52817L38.0354 4.60873C38.0354 4.76986 38.0354 4.76986 37.9952 4.76986ZM40.2903 29.2611L40.25 29.1805C40.25 29.1805 40.25 29.1 40.2903 29.1C40.2903 29.1 40.2903 29.1 40.2903 29.2611ZM38.2368 5.25324C38.1965 5.25324 38.1562 5.25324 38.116 5.25324C38.0757 5.25324 38.0757 5.17267 38.116 5.09211C38.1562 5.09211 38.1965 5.01155 38.2368 5.01155C38.3173 5.17267 38.3173 5.17267 38.2368 5.25324ZM38.3173 4.85042C38.3173 4.85042 38.277 4.85042 38.277 4.76986C38.2368 4.68929 38.2368 4.52817 38.3173 4.4476C38.3576 4.4476 38.3978 4.4476 38.4381 4.52817C38.3978 4.60873 38.3576 4.76986 38.3173 4.85042ZM38.5991 4.36704L38.6394 4.4476L38.5991 4.52817C38.5991 4.52817 38.5589 4.52817 38.5991 4.36704C38.5589 4.4476 38.5589 4.4476 38.5991 4.36704ZM38.8005 5.25324C38.8005 5.41436 38.6797 5.3338 38.6394 5.41436C38.5991 5.41436 38.5186 5.41436 38.5186 5.3338C38.5186 5.17267 38.6394 5.25324 38.6797 5.17267C38.7602 5.09211 38.8005 5.17267 38.8005 5.25324ZM39.0421 5.41436C39.0018 5.41436 38.9615 5.41436 38.9615 5.3338C38.9615 5.3338 39.0018 5.25324 39.0421 5.25324C39.0823 5.25324 39.1226 5.25324 39.1226 5.3338C39.0823 5.41436 39.0421 5.41436 39.0421 5.41436ZM42.3841 27.3276C42.4646 27.3276 42.5049 27.3276 42.5049 27.4887C42.5451 27.5693 42.5049 27.6498 42.4243 27.7304C42.3438 27.7304 42.3035 27.7304 42.3035 27.5693C42.3035 27.4082 42.3035 27.4082 42.3841 27.3276ZM41.2164 3.31972C41.2566 3.23915 41.458 3.40028 41.458 3.48084C41.458 3.56141 41.4177 3.64197 41.3774 3.64197C41.2969 3.64197 41.2164 3.8031 41.1761 3.56141C41.1761 3.48084 41.1761 3.31972 41.2164 3.31972ZM40.854 3.8031C40.854 3.8031 40.8943 3.88366 40.8943 3.96422C40.8943 3.96422 40.8943 4.04479 40.854 4.04479C40.854 3.96422 40.854 3.96422 40.854 3.8031C40.8137 3.88366 40.854 3.88366 40.854 3.8031ZM39.8474 4.60873C39.8474 4.68929 39.8474 4.68929 39.8071 4.76986C39.8071 4.76986 39.7668 4.76986 39.7668 4.68929C39.8071 4.68929 39.8071 4.60873 39.8474 4.60873ZM39.2836 4.60873C39.2836 4.52817 39.3642 4.52817 39.4044 4.52817C39.4447 4.52817 39.5252 4.36704 39.5252 4.60873C39.5252 4.68929 39.4447 4.68929 39.4044 4.68929C39.3642 4.68929 39.2836 4.85042 39.2836 4.60873ZM41.6996 29.1805C41.6593 29.1805 41.6593 29.1805 41.619 29.1C41.619 29.1 41.619 29.0194 41.6593 29.0194C41.6996 29.0194 41.6996 29.0194 41.7398 29.0194C41.6996 29.1 41.6996 29.1 41.6996 29.1805ZM41.4177 27.0859C41.4982 27.0859 41.5385 27.0859 41.5385 27.247C41.5385 27.3276 41.5385 27.3276 41.5385 27.4082C41.458 27.3276 41.4177 27.247 41.3372 27.247C41.3774 27.1665 41.4177 27.0859 41.4177 27.0859ZM41.5788 5.73662C41.458 6.05887 41.2969 6.22 41.0956 6.05887C40.8943 5.89774 40.6929 5.81718 40.4916 5.97831C40.4513 5.97831 40.3708 6.05887 40.3305 6.05887C40.0487 5.65605 39.646 5.89774 39.3642 5.57549C39.3239 5.57549 39.2434 5.57549 39.2434 5.49493C39.2434 5.41436 39.2837 5.25324 39.3642 5.17267C39.4044 5.09211 39.485 5.09211 39.5252 5.09211C39.6863 5.01155 39.7668 5.09211 39.9279 5.25324C40.1292 5.49493 40.4111 5.49493 40.6527 5.57549C40.6929 5.57549 40.7332 5.57549 40.7332 5.49493C40.7735 5.3338 40.6929 5.3338 40.6929 5.3338C40.6929 5.25324 40.6527 5.25324 40.6124 5.25324C40.6124 5.25324 40.5721 5.17267 40.5721 5.09211C40.6124 5.09211 40.6124 5.01155 40.6527 5.01155C40.9345 5.17267 41.2566 5.3338 41.5385 5.3338C41.6593 5.25324 41.6593 5.49493 41.5788 5.73662ZM41.9411 5.89774C41.9411 5.89774 41.9009 5.81718 41.9009 5.73662C41.9009 5.73662 41.9009 5.65605 41.9411 5.65605C41.9411 5.73662 41.9411 5.73662 41.9411 5.89774C41.9814 5.81718 41.9411 5.81718 41.9411 5.89774ZM42.7867 8.79802C42.7464 8.79802 42.7464 8.79802 42.7062 8.71746C42.827 8.79802 42.7867 8.79802 42.7867 8.79802ZM42.7464 8.6369C42.7062 8.6369 42.7062 8.6369 42.7464 8.6369C42.6659 8.55633 42.6659 8.55633 42.6659 8.55633C42.6659 8.47577 42.7062 8.47577 42.7062 8.47577C42.7062 8.55633 42.7062 8.55633 42.7464 8.6369H42.7867L42.827 8.71746C42.7867 8.71746 42.7464 8.6369 42.7464 8.6369ZM42.988 8.15352C42.9075 8.15352 42.9075 8.31464 42.8672 8.39521C42.8672 8.31464 42.827 8.31464 42.827 8.23408C42.827 8.15352 42.827 8.07295 42.827 8.07295C42.8672 7.91183 42.9478 7.99239 42.988 7.91183C43.0283 7.91183 43.0686 7.91183 43.0686 7.91183C43.0686 8.07295 43.0283 8.15352 42.988 8.15352ZM43.0686 4.60873C43.0686 4.68929 42.9478 4.68929 42.9478 4.68929C42.7464 4.4476 42.5451 4.76986 42.3438 4.60873C42.1425 4.4476 41.9411 4.28648 41.7398 4.4476C41.619 4.12535 41.3774 4.20591 41.2164 4.04479C41.1761 3.96422 41.0956 3.96422 41.0553 3.96422C41.0956 3.8031 41.1358 3.8031 41.2164 3.8031C41.2566 3.8031 41.2969 3.8031 41.3372 3.72253C41.458 3.56141 41.619 3.72253 41.7801 3.8031C41.9814 3.88366 42.223 3.72253 42.4243 3.96422C42.6256 4.20591 42.827 3.96422 42.988 4.28648C42.988 4.4476 43.1088 4.4476 43.0686 4.60873ZM42.9478 3.72253C42.9478 3.64197 42.9478 3.64197 42.988 3.56141C42.988 3.56141 43.0283 3.56141 43.0283 3.64197C42.988 3.64197 42.988 3.64197 42.9478 3.72253ZM43.4309 7.83126L43.3907 7.7507C43.3907 7.7507 43.3907 7.67014 43.4309 7.67014C43.4309 7.67014 43.4309 7.67014 43.4309 7.83126C43.4309 7.7507 43.4309 7.7507 43.4309 7.83126ZM43.7933 8.87859C43.7531 8.79802 43.7531 8.71746 43.7933 8.71746C43.7933 8.71746 43.8336 8.71746 43.8336 8.79802C43.8336 8.79802 43.8336 8.79802 43.7933 8.87859ZM46.2898 17.4183C46.2898 17.3377 46.33 17.3377 46.33 17.3377C46.33 17.4183 46.3703 17.4183 46.3703 17.4989C46.33 17.4183 46.2898 17.4183 46.2898 17.4183ZM46.4911 18.0628C46.4508 17.9822 46.33 17.9822 46.3703 17.7406C46.3703 17.66 46.4106 17.5794 46.4106 17.4989C46.6924 17.9017 46.5314 18.1434 46.4911 18.0628ZM46.4106 17.4989C46.5314 17.5794 46.6522 17.5794 46.6924 17.66C46.5716 17.5794 46.4508 17.5794 46.4106 17.4989ZM46.8132 19.1907C46.7729 19.1101 46.7729 19.1907 46.8132 19.1907C46.7729 19.1101 46.7729 19.0296 46.8132 19.0296C46.8132 19.0296 46.8535 19.0296 46.8535 19.1101C46.8132 19.1101 46.8132 19.1101 46.8132 19.1907ZM46.934 18.3045C46.934 18.3045 46.8937 18.2239 46.8937 18.1434C46.8937 18.1434 46.8937 18.0628 46.934 18.0628C46.934 18.1434 46.934 18.2239 46.934 18.3045ZM46.0482 16.371C46.0079 16.371 46.0482 16.2099 46.169 16.2099C46.33 16.0487 46.4911 16.2099 46.5716 16.371C46.6924 16.5321 46.7327 16.6932 46.8535 16.6127C46.8937 16.6127 46.934 16.6932 46.934 16.7738C46.934 16.8544 46.934 16.9349 46.8535 17.0155C46.5716 17.1766 46.33 16.9349 46.0884 16.8544C45.9676 16.7738 46.169 16.5321 46.0482 16.371ZM46.0884 19.1907C46.169 19.1101 46.4106 19.1907 46.4508 19.3518V19.4324C46.4106 19.4324 46.4106 19.5129 46.3703 19.5129C46.2898 19.5129 46.2092 19.2713 46.1287 19.3518C46.0884 19.4324 46.0884 19.3518 46.0884 19.1907ZM45.0013 9.68422L45.0416 9.76478C45.0013 9.92591 44.961 9.84535 44.9208 9.84535L44.8805 9.76478C44.8805 9.68422 44.9208 9.68422 45.0013 9.68422ZM44.2363 10.5704C44.4376 10.4899 44.5986 9.92591 44.8 10.1676C45.0415 10.4899 45.2026 10.4093 45.4442 10.3287C45.5247 10.3287 45.5247 10.4899 45.4845 10.7315C45.4442 10.8927 45.4442 10.7315 45.4442 10.8121C45.4845 10.9732 45.565 10.8927 45.6053 10.8927C45.6455 10.8927 45.7261 10.8121 45.7261 10.9732C45.7261 11.0538 45.6858 11.1344 45.6053 11.1344H45.5247C45.4039 11.1344 45.3234 11.2149 45.2026 11.0538C44.961 10.8121 44.7194 10.651 44.4376 10.8927C44.3973 10.8927 44.357 10.8121 44.3168 10.8121C44.2765 10.7315 44.1557 10.651 44.2363 10.5704ZM44.357 13.3901C44.357 13.3096 44.3973 13.3096 44.3973 13.3096C44.3973 13.3096 44.4376 13.3901 44.4376 13.4707C44.357 13.4707 44.357 13.4707 44.357 13.3901ZM44.5181 13.7124C44.4778 13.7124 44.4376 13.6318 44.4376 13.5513C44.5986 13.6318 44.5584 13.7124 44.5181 13.7124ZM44.4778 13.4707C44.4778 13.4707 44.5181 13.4707 44.5584 13.4707C44.5986 13.4707 44.6389 13.4707 44.6792 13.5513C44.5584 13.5513 44.5181 13.5513 44.4778 13.4707ZM46.2092 12.1011C46.169 12.1817 46.169 12.4234 46.0884 12.2622C46.0482 12.2622 46.0079 12.1817 46.0079 12.1817C45.6455 12.8262 45.2429 12.3428 44.8805 12.3428C44.7597 12.3428 44.5986 12.3428 44.4778 12.1817C44.357 12.0206 44.196 12.2622 44.1557 12.1011C44.1155 11.7789 44.357 12.0206 44.4376 11.6983C44.4778 11.6177 44.5986 11.6177 44.6792 11.5372C44.8402 11.5372 44.9208 11.5372 45.0416 11.5372C45.2429 11.6177 45.4442 11.7789 45.6455 11.6177C45.8066 11.4566 45.9676 11.7789 46.1287 11.8594C46.2092 11.94 46.2495 11.94 46.2092 12.1011Z\"\n      fill=\"#F8BC63\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 48 / 38,\n  svg: TiltedBrush,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/tomatoes.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Tomatoes', 'sticker name', 'web-stories');\n\nconst Tomatoes = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 50 50\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M0.0241645 20.1333C-0.0425583 17.6297 0.595377 15.2984 1.785 13.1147C3.40913 10.1304 5.96575 8.46513 9.22378 7.80724C10.9976 7.44958 12.7812 7.44138 14.5632 7.73669C14.9082 7.79411 15.1361 7.73505 15.3476 7.44138C17.0792 5.03458 19.5105 3.74504 22.3096 3.07895C24.3943 2.58184 26.5001 2.50965 28.6125 2.9034C29.0014 2.97559 29.3025 2.94277 29.6117 2.62941C31.1951 1.0298 33.1887 0.232454 35.3628 0.0552665C38.3703 -0.189187 41.2703 0.380111 44.0124 1.70738C45.591 2.47191 46.6862 3.66957 47.2997 5.30364C47.6708 6.28966 47.9669 7.30521 48.2794 8.31419C48.4373 8.82115 48.6195 9.29857 48.932 9.7399C49.6253 10.7177 49.8824 11.853 49.9703 13.0343C50.0858 14.5781 49.8531 16.0744 49.264 17.4968C48.8018 18.6124 48.3022 19.7182 47.7245 20.7748C46.9124 22.2579 45.7065 23.3653 44.1898 24.1069C42.2841 25.0388 40.2776 25.5703 38.1571 25.741C36.9919 25.8345 35.8511 25.7311 34.6989 25.6327C34.458 25.6113 34.1651 25.6737 33.9666 25.8049C31.7924 27.2388 29.3806 27.7983 26.8191 27.8344C25.7694 27.8492 24.7214 27.8475 23.6929 27.6014C23.2844 27.503 23.0435 27.6638 22.8303 28.005C21.5805 30 19.8555 31.4536 17.7383 32.42C13.883 34.1787 10.0798 34.0327 6.46047 31.8113C2.69796 29.5029 0.621415 26.0363 0.0323014 21.6541C-0.032794 21.1538 0.0241645 20.6386 0.0241645 20.1333ZM18.3274 6.667C18.3697 6.69161 18.4104 6.71458 18.4527 6.73919C18.342 6.9738 18.2167 7.20185 18.1207 7.44138C17.7187 8.44052 17.2614 9.42162 16.9425 10.447C16.1271 13.0605 16.0295 15.6937 17.0596 18.2794C18.2004 21.1423 20.2542 22.9486 23.2828 23.577C24.7588 23.8838 26.2348 23.8181 27.7093 23.5786C28.2365 23.4933 28.7557 23.3588 29.3969 23.2209C29.0226 22.7616 28.7361 22.4105 28.453 22.0594C27.5481 20.9388 26.9997 19.6608 26.793 18.2334C26.7556 17.9726 26.6482 17.6789 26.9786 17.3918C27.1006 17.6723 27.2031 17.9069 27.3057 18.1416C27.6474 18.9274 27.9436 19.7379 28.3391 20.4942C29.5986 22.9027 31.5548 24.4038 34.2253 24.8878C37.62 25.5031 40.8764 25.0289 43.9847 23.5327C45.3224 22.8879 46.3689 21.892 47.1175 20.614C47.9084 19.2654 48.5382 17.8364 48.9629 16.3205C49.2444 15.3131 49.3616 14.2894 49.2737 13.2476C49.2331 12.7603 49.1257 12.278 49.0492 11.794C49.0069 11.7972 48.9645 11.8005 48.9222 11.8022C48.7904 13.177 48.4177 14.483 47.8563 15.7331C46.792 18.1087 45.285 20.1267 43.1271 21.6049C41.4639 22.7435 39.6461 23.4293 37.6152 23.4539C37.4199 23.4556 37.2164 23.4588 37.0309 23.408C36.7266 23.3243 36.6631 23.0044 36.9089 22.7993C37.0195 22.7074 37.1758 22.6517 37.3206 22.6238C37.62 22.5663 37.9244 22.5319 38.2287 22.5024C40.0351 22.3235 41.6543 21.6541 43.119 20.5927C45.3452 18.9799 46.7545 16.7766 47.6594 14.1991C48.1801 12.7144 48.2615 11.2197 47.8449 9.71857C47.4511 8.29943 46.9726 6.90325 46.5349 5.49559C46.019 3.83856 44.8928 2.77543 43.3224 2.15855C42.5494 1.85504 41.7715 1.56136 40.9773 1.32511C38.686 0.644252 36.3539 0.401439 33.9926 0.87394C32.0007 1.27261 30.3017 2.19301 29.0632 3.87629C28.2414 4.9952 27.7467 6.25684 27.4391 7.59888C26.8435 10.2042 26.9607 12.8046 27.597 15.3837C28.0998 17.4197 29.0567 19.203 30.632 20.6041C32.0153 21.833 33.6102 22.6713 35.4003 23.1324C35.6574 23.198 35.9031 23.3079 36.1749 23.4031C35.9699 23.7394 35.7388 23.6377 35.5337 23.6163C33.5792 23.4096 31.8851 22.6188 30.4286 21.2948C28.5718 19.6083 27.514 17.4722 27.0062 15.0391C26.6205 13.1918 26.614 11.3182 26.7637 9.45115C26.9216 7.47255 27.4489 5.59567 28.5408 3.91239C28.6059 3.81231 28.6385 3.68926 28.7199 3.49567C28.4269 3.49567 28.2121 3.49074 27.9973 3.49731C26.863 3.5334 25.7287 3.57113 24.5961 3.60887C23.3462 3.64988 22.1159 3.83528 20.9198 4.19785C18.1565 5.03458 16.0913 6.71294 14.918 9.40685C14.0571 11.3805 13.896 13.4576 14.2784 15.5576C14.9505 19.2539 16.7879 22.2874 19.6163 24.7057C21.1916 26.051 23.024 26.8188 25.0989 26.9731C27.8118 27.1749 30.4026 26.6745 32.899 25.6163C33.0259 25.5621 33.1382 25.4785 33.2131 25.4358C32.3294 24.9682 31.4441 24.5433 30.6044 24.038C30.2122 23.8017 29.8883 23.746 29.4489 23.8706C27.6067 24.3907 25.7417 24.6237 23.8165 24.412C18.5764 23.8395 16.0116 19.5148 15.7349 15.5969C15.582 13.4231 15.9839 11.3395 16.8448 9.34943C17.2484 8.41099 17.6813 7.47583 18.3274 6.667ZM2.52546 17.4312C2.59381 17.4492 2.66378 17.4656 2.73213 17.4837C2.72237 17.6428 2.73376 17.8052 2.69959 17.9594C2.33505 19.6148 2.58079 21.2046 3.22198 22.7419C3.56047 23.5524 3.95918 24.3382 4.33836 25.1306C4.80868 26.1134 5.54426 26.8074 6.59555 27.101C7.43528 27.3356 8.2864 27.5325 9.14078 27.7113C10.6835 28.0362 12.2409 28.2446 13.8228 28.1642C15.8391 28.0624 17.6748 27.4423 19.2875 26.197C19.3998 26.1101 19.4828 25.987 19.5918 25.8656C19.504 25.7672 19.4551 25.695 19.3901 25.6425C16.7553 23.5081 14.9831 20.7846 13.9904 17.5411C13.5233 16.0153 13.2955 14.4518 13.4778 12.8489C13.5282 12.4026 13.5624 11.9531 13.608 11.4757C13.5184 11.52 13.4713 11.5282 13.4468 11.5577C13.3915 11.625 13.3443 11.7004 13.3004 11.7759C12.6999 12.7718 12.6283 13.8513 12.8089 14.9686C12.8642 15.3164 12.9391 15.6626 12.9733 16.012C12.9863 16.1564 12.9131 16.309 12.8789 16.4583C12.8252 16.4648 12.7698 16.4714 12.7161 16.478C12.6152 16.2959 12.4964 16.1236 12.4183 15.9316C12.101 15.1491 12.0684 14.3205 12.2621 13.5265C12.5127 12.4912 12.7536 11.4101 13.7463 10.762C13.7967 10.7292 13.8342 10.6619 13.8553 10.6012C14.0945 9.94498 14.3289 9.28709 14.5746 8.60294C14.464 8.56193 14.3891 8.51599 14.3094 8.50779C11.9675 8.25677 9.63876 8.30107 7.36367 8.98357C5.6891 9.4856 4.2635 10.4093 3.2171 11.8448C1.05104 14.8111 0.278037 18.1547 0.745096 21.7756C1.25121 25.7016 3.20733 28.7449 6.51418 30.8679C9.00408 32.4675 11.7218 33.0696 14.656 32.5693C17.4909 32.0836 19.7888 30.6612 21.644 28.4792C21.9223 28.1527 22.1485 27.7835 22.4284 27.3931C21.6651 26.9993 20.993 26.6466 20.3144 26.3037C20.098 26.1938 19.945 26.3201 19.8018 26.4743C19.5788 26.7155 19.364 26.9681 19.1134 27.1765C17.2777 28.699 15.0905 28.9943 12.8236 28.9517C12.0847 28.9385 11.3378 28.8664 10.6103 28.7335C9.19448 28.4742 7.77866 28.1937 6.38399 27.841C5.28713 27.5621 4.39532 26.9156 3.86154 25.8788C3.01367 24.2299 2.3025 22.527 2.02585 20.673C1.89078 19.7658 1.95099 18.87 2.25857 18.0005C2.33017 17.8052 2.43595 17.6215 2.52546 17.4312Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M46.4828 38.5315C46.4763 40.8005 45.9246 42.8988 44.6422 44.7741C43.3273 46.6969 41.599 48.0898 39.4021 48.8757C37.7226 49.4761 35.9927 49.7911 34.2205 49.9404C32.5752 50.0783 30.951 49.9683 29.3318 49.6993C27.4717 49.3892 26.0087 48.4081 24.8581 46.9364C23.6961 45.4484 22.5488 43.9489 21.4162 42.4395C20.5732 41.3156 20.0036 40.0507 19.7725 38.6611C19.3901 36.356 19.7628 34.1773 21.0533 32.2118C22.1745 30.5039 23.618 29.1553 25.5481 28.4121C26.6271 27.997 27.7483 27.8165 28.8891 28.0708C29.4148 28.1873 29.9242 28.4105 30.414 28.6434C30.925 28.8862 31.3432 28.8944 31.8721 28.5991C33.6151 27.6295 35.511 27.1504 37.4931 26.9585C38.9773 26.8158 40.372 27.034 41.643 27.8264C43.0474 28.7008 44.1361 29.8854 44.8977 31.3685C44.9384 31.4473 44.9824 31.5276 44.9986 31.6113C45.3078 33.3422 46.1703 34.9238 46.338 36.6907C46.3949 37.3027 46.434 37.9179 46.4828 38.5315ZM44.9612 38.812C44.901 38.7891 44.8408 38.7661 44.7806 38.7431C44.792 38.6201 44.8017 38.497 44.8131 38.374C44.8522 37.9392 44.9742 37.4913 44.9156 37.0697C44.7399 35.7998 44.6862 34.5284 44.7073 33.2503C44.7171 32.6154 44.5543 32.0264 44.2354 31.4866C43.4266 30.1233 42.3997 28.9732 41.0294 28.1594C40.455 27.8182 39.8317 27.6443 39.1742 27.554C37.8316 27.3703 36.5199 27.5442 35.2229 27.8838C33.9275 28.2218 32.6972 28.7337 31.5206 29.3719C31.187 29.5523 30.9071 29.5933 30.5523 29.3653C28.8338 28.2562 27.0079 28.2644 25.2405 29.134C21.9028 30.7746 19.6602 33.9148 20.2624 38.3642C20.3844 39.2681 20.6741 40.136 21.2534 40.8497C21.6798 41.3747 22.1469 41.8866 22.679 42.2967C23.9956 43.3139 25.3317 44.3032 26.5424 45.455C27.3724 46.2441 28.3928 46.6854 29.4978 46.9397C31.2309 47.3384 32.9836 47.5254 34.7607 47.4729C35.8413 47.4418 36.8812 47.2334 37.887 46.8314C40.0221 45.9767 41.6592 44.4739 43.1027 42.7364C43.6333 42.0966 44.0743 41.3813 44.5592 40.7037C44.7057 40.4986 44.8278 40.2361 45.2623 40.3821C45.163 40.6151 45.0946 40.8317 44.9856 41.0253C43.7911 43.1531 42.1556 44.8709 40.1572 46.2425C38.3735 47.468 36.406 48.0586 34.24 48.0652C32.6126 48.0701 31.0226 47.8191 29.4294 47.5533C28.0543 47.3236 26.8744 46.7215 25.8508 45.7552C25.0876 45.0333 24.2609 44.3803 23.4569 43.7028C23.3544 43.6158 23.2209 43.5682 23.1021 43.5026C23.7629 44.5444 24.5163 45.4796 25.2405 46.4393C26.4155 47.9979 27.9762 48.8658 29.8802 49.13C33.135 49.5844 36.3247 49.3252 39.4379 48.2358C40.6258 47.8191 41.7325 47.2646 42.6275 46.3475C45.0474 43.8668 46.1183 40.9219 45.6398 37.4438C45.5617 36.8745 45.4657 36.3084 45.3778 35.7408C45.3339 36.3019 45.4413 36.8433 45.4754 37.388C45.5096 37.9327 45.412 38.4577 44.9612 38.812Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M41.5192 17.9087C42.1783 16.9325 41.9765 16.0335 40.9984 15.6381C40.2075 15.3198 39.5647 14.8686 38.987 14.2304C38.6582 13.8662 38.1212 13.6332 37.6346 13.4856C36.8128 13.2345 36.0284 12.9622 35.34 12.4159C34.6776 11.8892 33.89 11.8843 33.0893 11.9926C32.6597 12.05 32.2187 12.1025 31.789 12.073C31.0437 12.0221 30.4106 11.7252 29.9306 10.8934C30.1828 10.9934 30.3179 11.0181 30.4204 11.0919C31.1202 11.5906 31.8899 11.712 32.7248 11.5874C33.3497 11.4938 33.9795 11.4348 34.6077 11.3757C35.1073 11.3281 35.5109 11.5266 35.7713 11.9598C36.0284 12.388 36.4092 12.6045 36.8714 12.7194C37.2945 12.8244 37.7176 12.9327 38.1391 13.0426C38.7526 13.2017 39.2718 13.5151 39.6314 14.045C39.9439 14.5044 40.3605 14.7833 40.8845 14.9359C41.3516 15.072 41.7714 15.3001 42.0985 15.6791C42.8178 16.5109 42.7055 17.8824 41.7942 18.478C41.2995 18.8012 40.7136 19.0161 40.1424 19.1818C39.5012 19.3672 39.0765 18.9046 39.2018 18.245C39.249 17.9907 39.3173 17.8939 39.6802 17.5921C39.703 17.7938 39.7225 17.953 39.7388 18.1121C39.7876 18.6027 39.9422 18.6978 40.3702 18.478C40.4825 18.4206 40.5737 18.3221 40.6974 18.227C40.6713 18.1154 40.6648 18.0055 40.6225 17.912C40.5427 17.7348 40.4923 17.5379 40.7022 17.4657C40.8373 17.4181 41.0358 17.4739 41.1758 17.5461C41.2979 17.6101 41.3809 17.7578 41.5192 17.9087Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.2575 14.9015C24.1631 15.0015 24.0817 15.1262 23.9694 15.1984C23.7123 15.3641 23.4471 15.52 23.172 15.6545C22.2639 16.104 21.4568 16.7012 20.6805 17.3476C19.6032 18.2451 19.2696 18.1991 18.3875 17.0917C18.3061 16.9883 18.2183 16.8899 18.1353 16.7865C17.6503 16.1926 17.5917 15.5577 17.9579 14.8834C18.0425 14.7292 18.1222 14.5717 18.2166 14.424C18.7081 13.6644 18.8155 12.8474 18.6804 11.9565C18.6121 11.5103 18.6593 11.0378 18.713 10.585C18.7374 10.3733 18.9018 10.1781 19.0271 9.9238C19.1019 10.055 19.1459 10.0977 19.1394 10.1272C18.975 10.8327 19.0645 11.5316 19.2126 12.2207C19.3997 13.0869 19.2419 13.8662 18.7911 14.6242C18.1662 15.6791 18.3582 16.506 19.3379 17.2705C19.5706 17.4526 19.7561 17.4116 19.9807 17.2443C20.7179 16.6963 21.4535 16.1434 22.22 15.6381C22.674 15.3395 23.1818 15.1197 23.6749 14.8851C23.8311 14.8112 24.0199 14.803 24.1924 14.7653C24.2168 14.8129 24.238 14.8572 24.2575 14.9015Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M44.141 6.59337C43.9587 6.37517 43.8627 6.28822 43.7992 6.18158C43.202 5.16603 42.2678 4.5754 41.2344 4.12259C40.7462 3.9093 40.2255 3.85352 39.6949 3.95524C38.5444 4.17673 37.4003 4.1554 36.2595 3.88633C34.9674 3.58282 33.8005 3.9093 32.7167 4.62954C32.4205 4.82642 32.1195 5.01673 31.8216 5.20868C31.7923 5.17423 31.7631 5.13978 31.7321 5.10532C31.7907 5.00196 31.8314 4.8822 31.9111 4.80017C32.9706 3.71243 34.2513 3.23172 35.7583 3.39907C36.6013 3.49258 37.441 3.62711 38.2856 3.70094C38.6502 3.73376 39.0261 3.6829 39.3922 3.6304C41.1043 3.38102 42.4566 4.09469 43.6234 5.25462C43.9278 5.55486 44.2598 5.90923 44.141 6.59337Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.8903 11.9614C44.2304 11.4217 44.8017 11.2232 45.2768 11.4578C45.835 11.7334 45.9164 12.4881 45.3875 12.8786C45.0474 13.1296 44.6389 13.2969 44.2451 13.4593C44.1279 13.5069 43.9473 13.4265 43.8057 13.379C42.6389 12.9852 41.5436 12.4815 40.6176 11.6202C39.9618 11.0115 39.2148 10.5013 38.5151 9.94019C38.3588 9.81551 38.227 9.65636 38.0854 9.51363C38.1147 9.47425 38.144 9.43652 38.1733 9.39714C38.3051 9.44308 38.4451 9.47425 38.5671 9.53824C39.5436 10.0485 40.4272 10.6916 41.2019 11.4775C41.887 12.1714 42.7219 12.575 43.6283 12.8507C43.778 12.8966 43.9668 12.872 44.123 12.8293C44.3509 12.7654 44.5657 12.6522 44.7886 12.5668C44.9872 12.4914 45.189 12.3749 45.0864 12.1485C45.0197 12.0025 44.8114 11.8482 44.6552 11.8351C44.4111 11.8138 44.1605 11.9106 43.8903 11.9614Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.0723 20.2614C34.1488 20.2925 34.235 20.3073 34.2985 20.3549C34.8046 20.7388 35.3579 20.7174 35.921 20.5419C36.3799 20.3992 36.8291 20.2269 37.2864 20.0792C37.729 19.9349 38.1896 19.8528 38.6371 20.0169C40.0057 20.5206 41.2539 20.1941 42.4615 19.5067C42.7853 19.3229 43.1092 19.1392 43.4428 18.9767C43.5648 18.9177 43.7146 18.9177 43.8512 18.8914C43.8757 18.9324 43.9001 18.9735 43.9245 19.0145C43.7943 19.1375 43.682 19.2983 43.529 19.3754C42.6128 19.8348 41.7064 20.3286 40.7527 20.6928C40.3361 20.852 39.7877 20.8372 39.3466 20.7191C38.3963 20.4632 37.5093 20.5173 36.5866 20.8421C36.1049 21.0111 35.5646 21.0521 35.0487 21.0653C34.567 21.0784 34.1878 20.8257 33.9828 20.3795C34.0153 20.3401 34.0446 20.3007 34.0723 20.2614Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M26.6661 5.9321C26.5994 6.00428 26.5457 6.10272 26.4643 6.1421C25.5611 6.5703 24.6352 6.81968 23.6229 6.56538C22.5993 6.3078 21.5171 6.7721 20.9263 7.67937C20.7555 7.94187 20.5732 8.19452 20.3958 8.4521C20.3535 8.43405 20.3096 8.41765 20.2673 8.3996C20.2591 8.2864 20.2103 8.15515 20.251 8.06163C20.5472 7.36765 20.9491 6.74913 21.5903 6.32092C22.0476 6.01577 22.5505 5.92225 23.0859 5.98295C23.3235 6.0092 23.5627 6.04202 23.7938 6.10108C24.5815 6.2996 25.3431 6.24546 26.0917 5.92389C26.2528 5.85499 26.4383 5.84678 26.6124 5.81069C26.6303 5.85006 26.6482 5.89108 26.6661 5.9321Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.8771 7.19878C33.8771 7.09378 33.8689 7.01174 33.8787 6.93135C33.9503 6.2669 33.6151 5.82393 32.9625 5.77307C32.8111 5.76159 32.5833 5.82229 32.5117 5.93057C32.4401 6.04049 32.4824 6.26362 32.5394 6.41292C32.6012 6.57042 32.7477 6.69182 32.8404 6.84112C32.9153 6.96253 32.9641 7.10034 33.0406 7.2644C32.9169 7.31198 32.8372 7.37432 32.7656 7.36448C32.2595 7.29885 31.7778 6.66557 31.8038 6.11596C31.8298 5.56799 32.2611 5.17096 32.8616 5.17096C33.4068 5.17096 33.8966 5.34979 34.2725 5.75666C34.5345 6.04049 34.6794 6.38995 34.5313 6.78698C34.4288 7.06424 34.2611 7.27589 33.8771 7.19878Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M42.1946 10.2551C42.2043 10.0583 42.1832 9.97622 42.2141 9.93849C42.7316 9.28388 43.4233 8.93607 44.2353 8.87372C44.7073 8.83763 45.0116 9.20841 44.9481 9.68583C44.9237 9.87287 44.8423 10.073 44.7284 10.224C44.3199 10.7654 43.1075 10.9491 42.4387 10.5734C42.6568 10.1665 43.0603 10.1485 43.433 10.0763C43.6446 10.0353 43.8692 10.0254 44.0661 9.94833C44.1523 9.91388 44.2483 9.73341 44.2288 9.64318C44.2109 9.56443 44.0303 9.46107 43.9359 9.47419C43.7259 9.50537 43.516 9.58576 43.3207 9.67763C42.9725 9.84169 42.6323 10.0287 42.1946 10.2551Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.8178 7.81398C39.0424 7.69257 39.1905 7.61546 39.337 7.53507C39.7487 7.30703 39.9244 7.00515 39.8333 6.56218C39.7975 6.38991 39.6559 6.12577 39.542 6.11429C39.3679 6.09624 39.1075 6.21437 39.0066 6.36038C38.8504 6.58515 38.7885 6.88046 38.7072 7.15281C38.6453 7.35953 38.6388 7.59086 38.3475 7.68273C38.2857 7.5925 38.1978 7.51375 38.1783 7.42187C38.0172 6.68851 38.5867 5.74843 39.3012 5.54827C39.778 5.41538 40.1734 5.60898 40.3622 6.07163C40.6096 6.67374 40.3606 7.54492 39.8366 7.91078C39.4932 8.15031 39.293 8.14375 38.8178 7.81398Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.2115 19.0063C33.7648 18.8423 34.0528 18.4354 34.2839 17.9285C34.1358 17.8136 34.0056 17.7135 33.8689 17.6069C33.9584 17.2509 34.1814 17.1656 34.4694 17.2394C34.7607 17.3149 34.8942 17.5314 34.8877 17.8317C34.873 18.5076 33.8071 19.5871 33.1447 19.597C32.7428 19.6035 32.4498 19.3115 32.4368 18.8915C32.4205 18.3862 32.8502 17.7775 33.5076 17.4855C33.3758 17.7923 33.2733 18.0154 33.1854 18.2418C33.0894 18.4846 32.982 18.7324 33.2115 19.0063Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.6108 7.85003C30.3081 8.37503 29.9517 8.87871 29.7158 9.43324C29.47 10.0124 29.2715 10.6325 29.1771 11.2543C29.0876 11.8417 29.1576 12.452 29.1576 13.0902C28.7654 13.0246 28.7572 12.7604 28.7035 12.5422C28.4659 11.5628 28.6091 10.6046 28.9867 9.69902C29.2031 9.17894 29.54 8.7048 29.8671 8.24214C30.0185 8.02722 30.2772 7.88777 30.4855 7.7155C30.5278 7.75816 30.5685 7.80409 30.6108 7.85003Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M20.9018 20.7749C21.4763 18.7356 24.6822 16.9129 26.1697 17.7381C26.0411 17.8103 25.95 17.8858 25.8458 17.9137C25.7221 17.9449 25.5854 17.9334 25.4552 17.9432C24.0476 18.0449 22.9295 18.6913 22.0263 19.7643C21.722 20.1203 21.447 20.519 20.9018 20.7749Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M31.3856 12.616C31.0796 12.8588 30.8697 13.0245 30.5979 13.2378C31.2879 13.5282 31.6785 12.8359 32.305 12.8867C32.2611 13.0508 32.2627 13.2116 32.1846 13.3051C31.7078 13.8711 31.0698 14.0549 30.3684 13.9482C30.1732 13.9187 29.9063 13.707 29.8623 13.5299C29.8184 13.3543 29.9583 13.0541 30.1129 12.9195C30.427 12.6456 30.7851 12.3732 31.3856 12.616Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M23.4813 21.3393C23.6391 21.1884 23.7856 21.0768 23.8962 20.9358C24.0264 20.7684 24.1631 20.5879 24.2233 20.3911C24.2575 20.2795 24.1745 20.0629 24.0785 20.0055C24.002 19.9596 23.7905 20.0449 23.701 20.1368C23.535 20.3074 23.4194 20.5272 23.273 20.7175C23.159 20.8652 23.0321 21.0014 22.7945 21.0883C22.8059 20.9538 22.775 20.793 22.8368 20.6897C23.0728 20.2975 23.2941 19.8825 23.6049 19.556C23.9695 19.1721 24.4268 19.2918 24.679 19.7611C25.0452 20.4436 24.4935 21.4411 23.7221 21.487C23.67 21.4886 23.6163 21.4247 23.4813 21.3393Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.7477 17.8448C36.9267 18.2631 37.0487 18.5486 37.2261 18.9604C37.3661 18.7455 37.4686 18.6274 37.5256 18.4895C37.6069 18.2894 37.6362 18.0663 37.7241 17.8694C37.7566 17.7939 37.8982 17.7135 37.9731 17.7267C38.0528 17.7414 38.1505 17.8513 38.1798 17.9416C38.3409 18.442 37.9015 19.3525 37.4198 19.5478C37.1122 19.6724 36.8079 19.5871 36.6386 19.2787C36.4043 18.8554 36.3685 18.4223 36.7477 17.8448Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.4596 9.27246C36.0576 7.79097 35.6915 6.44073 35.3139 5.04948C35.8542 5.43667 36.5052 6.82956 36.6874 8.03378C36.7412 8.38816 36.9381 8.79339 36.4596 9.27246Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.452 21.8118C25.631 21.5231 25.7791 21.2097 25.9955 20.9538C26.2836 20.6142 26.6351 20.5765 26.9166 20.7848C27.2063 20.9997 27.3186 21.5411 27.1396 21.8561C26.9752 22.1449 26.5977 22.2581 26.2218 22.1219C26.1013 22.0776 25.9939 21.994 25.8735 21.9595C25.7775 21.9316 25.6684 21.9546 25.5643 21.9546C25.5252 21.9054 25.4894 21.8578 25.452 21.8118ZM26.1713 21.5231C26.2055 21.5707 26.238 21.6199 26.2722 21.6675C26.3666 21.5936 26.4642 21.5231 26.5505 21.4411C26.5586 21.4329 26.4935 21.3475 26.461 21.2983C26.365 21.3738 26.2673 21.4493 26.1713 21.5231Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.5535 7.09044C43.2573 8.0502 41.3989 9.17568 40.3655 9.05427C40.4387 8.97388 40.4826 8.90005 40.5477 8.8574C41.4412 8.27989 42.3362 7.70403 43.2346 7.13473C43.298 7.09536 43.3957 7.11012 43.5535 7.09044Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M21.5658 12.5177C21.3608 12.5472 21.1509 12.5636 20.9507 12.6128C20.7424 12.6637 20.5308 12.7228 20.3437 12.8228C20.2542 12.8721 20.1582 13.041 20.1793 13.128C20.2005 13.2166 20.3583 13.3183 20.4641 13.3282C20.6854 13.3495 20.9116 13.3134 21.2176 13.297C21.0256 13.7613 20.7001 13.7892 20.386 13.7908C20.0898 13.7925 19.818 13.6727 19.6927 13.3889C19.6293 13.2461 19.6211 13.0378 19.6732 12.8901C19.8587 12.3536 20.8612 11.932 21.382 12.1551C21.4698 12.1928 21.5317 12.2913 21.6049 12.3618C21.5919 12.4127 21.5789 12.4652 21.5658 12.5177Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.0329 10.5636C21.9255 10.1813 21.8783 9.92702 21.7774 9.69733C21.727 9.58248 21.5707 9.43155 21.4731 9.43811C21.2453 9.45451 21.146 9.64811 21.1916 9.87123C21.2225 10.0189 21.3006 10.1567 21.3624 10.2978C21.4487 10.4914 21.5398 10.6833 21.696 11.0197C21.4243 10.9344 21.2713 10.9278 21.1769 10.8507C20.6431 10.4159 20.5601 9.64483 20.9849 9.2199C21.3722 8.83108 21.8669 8.87701 22.1354 9.35608C22.3258 9.70061 22.4642 10.073 22.0329 10.5636Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M20.7457 14.9688C20.5651 15.2821 20.0052 15.2329 20.0231 15.7366C20.4365 16.1517 20.8775 15.5643 21.3592 15.753C21.2941 15.8859 21.2681 16.045 21.1884 16.0778C20.8515 16.2206 20.5049 16.3617 20.1485 16.4371C19.8816 16.4929 19.6293 16.3666 19.4861 16.109C19.3299 15.8268 19.3885 15.5561 19.5626 15.3035C19.8441 14.8999 20.2656 14.7752 20.7457 14.9688Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.9544 9.21827C33.864 9.52999 32.0804 8.87046 31.5499 7.90577C32.0186 7.95334 32.3343 8.24702 32.7053 8.38811C33.0715 8.52757 33.4393 8.66702 33.8136 8.77694C34.1993 8.89178 34.5947 8.97218 34.9869 9.06733C34.9755 9.11819 34.9658 9.16905 34.9544 9.21827Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.9414 6.11092C36.5687 5.65647 36.6208 5.20857 36.8014 4.77873C36.956 4.41123 37.3075 4.37677 37.5874 4.6606C37.9715 5.04943 37.9178 5.60069 37.4573 5.87959C37.314 5.96819 37.1481 6.02069 36.9414 6.11092Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.1452 21.6116C22.6481 21.8544 23.0777 22.112 23.5399 22.2727C24.0004 22.4335 24.4935 22.4959 24.9638 22.6009C25.0013 22.8913 24.8271 22.9356 24.653 22.9684C23.7986 23.1324 22.6123 22.6058 22.1468 21.8577C22.1289 21.8265 22.1452 21.7724 22.1452 21.6116Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.8385 9.24459C24.6937 9.15764 24.5782 9.1117 24.4935 9.03131C24.3845 8.92631 24.3113 8.78357 24.2022 8.67693C23.937 8.41443 23.6701 8.37013 23.5252 8.57029C23.3186 8.85412 23.5334 9.0067 23.7384 9.14779C23.81 9.19701 23.893 9.22983 23.989 9.28068C23.6766 9.64326 23.4422 9.50217 23.2437 9.33975C23.0094 9.14615 22.8857 8.86725 23.0273 8.57849C23.1168 8.3931 23.2811 8.21756 23.4553 8.10927C23.7986 7.89599 24.1404 8.0256 24.4203 8.26021C24.6921 8.4899 24.9752 8.7442 24.8385 9.24459Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.4385 15.789C32.1553 16.2303 31.6362 16.4928 31.2782 16.4141C31.0096 16.355 30.8681 16.1795 30.8534 15.9055C30.816 15.2509 31.4328 14.7209 32.1765 14.8062C32.0284 15.2049 31.3546 15.2263 31.4832 15.8382C31.7875 15.8218 32.0935 15.807 32.4385 15.789Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.5865 13.5299C33.021 13.2083 34.7037 12.5882 35.0504 12.6013C34.5784 13.2559 33.3026 13.7612 32.5865 13.5299Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.1098 13.8072C35.8641 14.5438 35.244 15.2821 34.7802 15.438C34.7884 14.972 35.5012 14.068 36.1098 13.8072Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.6514 13.4511C24.3666 13.6447 23.4797 13.8449 22.6839 13.8957C23.1379 13.3264 24.1241 13.1033 24.6514 13.4511Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.6123 10.1782C25.1802 10.6342 25.3414 11.0756 25.1558 11.5628C24.7067 11.3463 24.5195 10.9 24.6123 10.1782Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.7897 11.3183C23.4488 11.1083 23.9891 11.425 24.1046 12.1419C23.5806 11.9467 23.1786 11.6826 22.7897 11.3183Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M16.1173 26.5598C15.9627 26.8748 15.7121 26.8436 15.4599 26.7206C15.1393 26.5664 14.97 26.2891 14.9407 25.9347C14.8968 25.3884 14.8691 24.8404 14.8235 24.2941C14.7764 23.7264 14.7438 23.1555 14.651 22.5944C14.6218 22.4139 14.4183 22.1285 14.2963 22.1285C14.0684 22.1285 13.7934 22.2564 13.6274 22.4205C13.4907 22.555 13.4631 22.8175 13.4224 23.0292C13.2368 24.0136 13.3215 24.9979 13.4696 25.9774C13.5168 26.2809 13.5851 26.5828 13.6144 26.8879C13.6274 27.0192 13.5623 27.157 13.533 27.2932C13.4858 27.3079 13.4386 27.3211 13.3915 27.3358C13.2792 27.1718 13.1278 27.0208 13.0611 26.8387C12.4931 25.285 12.5843 23.733 13.1197 22.1941C13.188 21.9972 13.341 21.8102 13.4972 21.6675C14.0571 21.1572 14.7178 21.2753 14.9505 21.9939C15.1653 22.6535 15.2288 23.3639 15.3508 24.0546C15.3769 24.2055 15.3671 24.3614 15.3752 24.5156C15.4403 25.5968 15.507 25.7789 16.1173 26.5598Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.89825 26.0987C7.04635 26.0462 7.19118 25.9708 7.34416 25.9478C7.55897 25.915 7.78192 25.9445 7.99511 25.9084C8.84135 25.769 9.46139 25.3194 9.66807 24.4581C9.78524 23.9741 9.79988 23.4606 9.82104 22.9586C9.84382 22.4008 9.88776 21.8413 10.2149 21.3852C10.4346 21.0768 10.7438 20.811 11.0627 20.6059C11.3117 20.4468 11.6372 20.4336 11.9432 20.747C11.7674 20.8307 11.6453 20.9176 11.5119 20.9488C10.9602 21.0751 10.6298 21.4361 10.5143 21.966C10.3971 22.4992 10.3532 23.0488 10.2637 23.5902C10.1921 24.0217 10.1465 24.4647 10.0147 24.8797C9.67946 25.9363 8.44915 26.6647 7.37182 26.4744C7.21234 26.4465 7.06262 26.3579 6.90802 26.2972C6.90476 26.2283 6.90151 26.1644 6.89825 26.0987Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M3.32775 14.9327C3.38634 14.8195 3.42702 14.6915 3.50676 14.598C4.20328 13.7793 4.88679 12.9508 5.6126 12.16C6.53533 11.1543 7.71681 10.6063 9.03011 10.3373C9.57691 10.2257 10.1237 10.0846 10.7177 10.2142C10.5957 10.2667 10.4769 10.3373 10.3483 10.3701C9.60946 10.5604 8.85273 10.6966 8.12854 10.9378C6.93729 11.3348 5.98364 12.0993 5.19111 13.0722C4.74683 13.6169 4.30093 14.1583 3.84851 14.6948C3.7346 14.831 3.59302 14.9442 3.46282 15.0672C3.41726 15.0213 3.37169 14.977 3.32775 14.9327Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.92343 13.0229C7.7135 12.9245 7.68095 12.7161 7.80138 12.5455C7.90228 12.4028 8.09268 12.2682 8.26193 12.2403C8.61019 12.1846 9.05447 12.6521 9.08701 13.018C9.10817 13.2477 9.14072 13.4889 9.23348 13.6956C9.71519 14.7751 10.4345 15.6807 11.2824 16.4912C11.4614 16.6618 11.6111 16.8636 11.7755 17.0507C11.7478 17.0933 11.7185 17.136 11.6908 17.1786C11.5606 17.1507 11.3946 17.1672 11.3051 17.09C10.0553 16.0187 8.98937 14.8227 8.72248 13.1017C8.71597 13.059 8.73713 12.9967 8.71434 12.9737C8.5988 12.8556 8.46861 12.6538 8.35144 12.6603C8.21962 12.6685 8.09919 12.8654 7.92343 13.0229Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.45875 23.0701C6.44248 23.4934 6.13653 23.9347 6.68008 24.1546C6.97138 24.2727 7.47099 24.043 7.63535 23.7411C7.80298 23.4327 7.72161 23.2719 7.17643 22.8651C7.37334 22.573 7.63698 22.5829 7.91201 22.6928C8.20006 22.8076 8.37093 23.1161 8.34815 23.436C8.28631 24.3285 6.95185 25.0389 6.18861 24.5844C5.87127 24.3958 5.71829 24.0676 5.77362 23.6886C5.83058 23.3195 5.97217 23.1817 6.45875 23.0701Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M18.1043 25.4704C18.075 25.6279 18.0474 25.7558 18.0295 25.8854C17.9904 26.1725 17.8098 26.2398 17.5608 26.1906C16.9798 26.0757 16.4102 25.2226 16.5144 24.6287C16.5957 24.1661 17.0091 23.9626 17.3866 24.2268C17.8179 24.5303 18.0425 24.9732 18.1043 25.4704Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.37097 21.7807C6.1708 21.8168 5.96412 21.8332 5.76883 21.8923C5.43847 21.9907 5.10811 22.099 4.79566 22.2401C4.72893 22.2712 4.69476 22.4698 4.71754 22.5748C4.73219 22.6371 4.8933 22.7159 4.97792 22.7044C5.18623 22.6781 5.38803 22.6026 5.6956 22.5206C5.61911 22.7076 5.60284 22.8668 5.53124 22.8996C5.27899 23.0128 5.00559 23.1539 4.74358 23.1473C4.54829 23.1424 4.31558 22.9603 4.17888 22.7897C4.01288 22.583 4.10565 22.3303 4.26025 22.1219C4.2993 22.0694 4.34487 22.0219 4.39044 21.9759C4.84773 21.5231 5.82579 21.3558 6.37097 21.7807Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.23346 20.2975C5.00075 20.3385 4.88357 20.3762 4.76477 20.3746C4.63621 20.373 4.493 20.2893 4.38397 20.327C4.2196 20.3828 3.97387 20.4894 3.94783 20.6141C3.8925 20.8766 4.15613 20.9127 4.34654 20.9062C4.60366 20.898 4.85916 20.8455 5.11466 20.8061C5.29368 20.7782 5.47269 20.7405 5.80793 20.6781C5.64356 20.8881 5.59962 20.9931 5.52151 21.0374C5.07398 21.2901 4.58902 21.3869 4.07965 21.3426C3.77532 21.3163 3.53773 21.1834 3.44497 20.8684C3.3636 20.5895 3.50518 20.2712 3.78346 20.0809C4.20333 19.7922 4.67852 19.8398 5.23346 20.2975Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M4.4327 17.6199C4.41805 17.7496 4.41154 17.8513 4.39527 17.9497C4.34319 18.2385 4.4034 18.4829 4.69145 18.601C4.98764 18.7224 5.24151 18.6322 5.4433 18.3845C5.57187 18.227 5.70206 18.0695 5.8827 17.8513C5.93966 18.519 5.61418 18.9242 5.03971 19.0309C4.59869 19.1129 4.14628 18.8521 4.00144 18.4353C3.8745 18.0695 3.98517 17.8398 4.4327 17.6199Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.1879 15.287C7.32623 14.9835 7.5915 14.7521 7.30508 14.4782C7.09026 14.2731 6.84778 14.2386 6.58414 14.3289C6.44093 14.3781 6.30749 14.4536 6.16916 14.5126C6.0585 14.5602 5.94621 14.5996 5.77208 14.6668C6.12848 14.1172 6.70457 13.8531 7.17 13.9827C7.45968 14.0631 7.68426 14.2321 7.75586 14.5389C7.82096 14.8145 7.75261 15.0655 7.50199 15.2263C7.43852 15.2657 7.34739 15.2575 7.1879 15.287Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M8.07811 20.3467C7.60291 20.4993 6.32216 20.4025 5.84045 20.204C6.28798 19.8332 7.41251 19.8857 8.07811 20.3467Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.36116 18.2779C7.04466 18.4256 7.55566 18.5978 7.97878 19.0408C7.51172 19.1524 6.80381 18.8308 6.36116 18.2779Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.77537 16.8489C8.26196 17.1245 8.74855 17.4002 9.31163 17.7184C8.70787 17.8431 8.03087 17.4691 7.77537 16.8489Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.3261 16.1746C6.21303 15.981 6.7224 16.3583 6.64103 17.1261C6.43923 16.8915 6.29439 16.6487 6.08446 16.5011C5.86314 16.3452 5.5816 16.2796 5.3261 16.1746Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M9.82263 16.186C9.28071 16.0991 8.86411 15.8087 8.46051 15.2952C8.86736 15.2739 9.00406 15.5675 9.22701 15.6873C9.44996 15.8071 9.66641 15.9399 9.8861 16.0679C9.86495 16.1057 9.84379 16.1467 9.82263 16.186Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.39946 21.3968C7.63218 21.3574 7.79655 21.3279 8.00323 21.2934C7.81282 21.7183 7.81282 21.7183 7.39946 21.3968Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.8714 43.1909C35.2929 44.2393 34.9104 45.1875 33.9259 45.537C33.3514 45.7404 32.7493 45.7667 32.1878 45.5534C30.6988 44.9874 29.1983 44.4345 27.763 43.7503C27.182 43.4731 26.7507 42.8726 26.2625 42.4083C26.1551 42.305 26.0754 42.1622 26.0086 42.0244C24.972 39.8604 24.0704 37.6456 23.5383 35.2945C23.4667 34.9779 23.4569 34.6367 23.4764 34.3102C23.5578 32.9452 24.3585 31.9509 25.6604 31.5802C27.1006 31.17 28.4855 31.362 29.7646 32.1068C30.1812 32.348 30.5393 32.7499 30.8208 33.1519C31.13 33.5932 30.9722 33.8475 30.4612 33.9919C30.1064 34.092 29.7663 34.2511 29.4082 34.3397C28.3879 34.5891 27.8199 34.3528 27.2422 33.4734C26.8614 32.8943 26.6563 32.8533 26.1437 33.2897C26.3162 33.4685 26.4855 33.6441 26.6791 33.8442C26.3764 34.0969 26.1567 33.9131 25.95 33.7835C25.5172 33.5095 25.3007 33.1142 25.3984 32.8221C25.4976 32.5252 25.885 32.3677 26.4155 32.3972C26.8565 32.4218 27.2113 32.6154 27.4961 32.9435C27.6393 33.1092 27.7678 33.2881 27.8964 33.4652C28.1015 33.7474 28.3781 33.9394 28.7182 33.9476C29.2162 33.9591 29.7109 33.8967 30.1926 33.6572C30.1373 33.1666 29.8151 32.8877 29.4554 32.7007C28.2072 32.0576 26.8939 31.8377 25.5269 32.2561C24.8288 32.4694 24.3878 32.9731 24.1697 33.667C23.9614 34.3331 23.9386 35.0206 24.1111 35.6899C24.2901 36.3905 24.5163 37.0828 24.7751 37.7588C25.1608 38.7645 25.605 39.7472 26.0021 40.748C26.5864 42.2262 27.5742 43.2385 29.1088 43.729C29.8525 43.9669 30.5523 44.3443 31.2651 44.674C33.0308 45.4927 32.8876 45.3385 34.1488 44.1753C34.2985 44.0375 34.3767 43.8127 34.4645 43.6191C34.554 43.4255 34.5866 43.1909 34.8714 43.1909Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.1742 36.5627C42.7316 37.2238 42.7853 37.9539 42.7609 38.6774C42.7511 38.9727 42.6714 39.3074 42.5135 39.5502C41.6673 40.8562 40.8324 42.1753 39.6851 43.2499C39.2409 43.6649 38.7315 43.9373 38.131 44.039C37.1057 44.2129 36.3848 43.7421 36.1277 42.7265C36.0756 42.5198 36.0072 42.318 35.9421 42.1047C36.3457 41.7782 36.8877 42.2885 37.2554 41.8192C37.179 41.2352 36.5475 41.5666 36.2546 41.2532C36.5101 40.8824 36.8453 40.9087 37.1806 41.0104C37.5077 41.1088 37.7827 41.2942 37.8462 41.665C37.8966 41.9685 37.7241 42.1835 37.4703 42.2934C37.1594 42.4296 36.8258 42.5149 36.4938 42.6264C36.7461 43.1088 37.0976 43.2121 37.6639 43.176C38.9772 43.0907 39.9097 42.5001 40.5802 41.3894C40.8064 41.0153 41.0928 40.679 41.3548 40.3263C41.7421 39.8062 41.9586 39.2205 42.0855 38.5806C42.1881 38.0671 42.3459 37.5602 42.5282 37.068C42.66 36.7234 42.7316 36.7021 43.1742 36.5627Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M39.3531 38.6889C39.6444 38.3805 39.0488 37.9424 39.5468 37.6127C39.6574 37.7062 39.7632 37.8063 39.8804 37.8932C40.0008 37.9835 40.131 38.1229 40.2579 38.1245C40.3979 38.1278 40.5411 37.9982 40.6827 37.926C40.616 37.803 40.5769 37.6094 40.4776 37.5684C40.1782 37.447 39.856 37.3863 39.3368 37.2468C39.5695 37.132 39.6932 37.0696 39.7583 37.0368C39.5874 36.8383 39.4247 36.6644 39.2864 36.4724C39.249 36.4199 39.2571 36.2903 39.2961 36.2362C39.3368 36.182 39.4621 36.1361 39.5191 36.1607C39.7193 36.246 39.8999 36.3707 40.0968 36.4642C40.3588 36.5889 40.642 36.6874 40.9024 36.4905C41.0049 36.4134 41.0732 36.2509 41.0879 36.1197C41.0928 36.0721 40.8991 35.9688 40.7868 35.9491C40.4972 35.8999 40.2026 35.8818 39.9129 35.7899C40.3718 35.4995 40.8584 35.5012 41.3271 35.6669C41.6819 35.7932 41.7568 36.2329 41.4899 36.5479C41.3108 36.7579 41.0684 36.9154 40.8552 37.0959C41.5289 37.8899 41.415 38.2378 40.3116 38.7381C40.3637 39.4141 40.3523 39.4403 39.7437 39.9703C39.7437 40.1261 39.7583 40.3 39.7404 40.469C39.6916 40.9628 39.1822 41.4534 38.6891 41.496C38.3018 41.5289 37.8754 41.2335 37.7371 40.8267C37.6525 40.5806 37.6313 40.3476 37.9519 40.2557C38.3311 40.3853 38.3262 41.0416 38.8372 40.9202C39.0114 40.8792 39.1448 40.6659 39.384 40.4559C39.0797 40.3263 38.8942 40.2459 38.6615 40.1474C38.7331 40.0588 38.7965 39.9817 38.873 39.8882C38.7493 39.7176 38.6208 39.5388 38.4385 39.2878C38.6517 39.2549 38.7705 39.2106 38.8812 39.2254C39.0065 39.2435 39.1253 39.355 39.2473 39.355C39.4247 39.3567 39.6932 39.3567 39.7616 39.25C39.9276 38.9957 39.6981 38.8694 39.4833 38.7792C39.4442 38.766 39.4133 38.7316 39.3531 38.6889Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.5556 31.5883C34.6158 31.5112 34.6598 31.4062 34.7379 31.3603C35.4491 30.9337 36.157 30.5006 36.8844 30.1068C37.1676 29.9543 37.4963 29.8689 37.8136 29.8066C38.5948 29.654 39.2832 29.8492 39.8349 30.4514C39.9683 30.5974 40.1034 30.7417 40.2173 30.9009C40.6713 31.5325 41.2263 32.0461 41.8886 32.4529C42.2597 32.681 42.6307 32.9271 42.9448 33.224C43.8268 34.0607 43.6771 35.452 42.6567 36.1197C42.6112 36.1493 42.5347 36.1296 42.4191 36.1361C42.4305 35.9967 42.4029 35.8572 42.4549 35.7621C42.909 34.9549 42.4403 34.2297 42.2548 33.4865C42.219 33.3454 42.0269 33.2257 41.8837 33.1338C41.0473 32.5907 40.3572 31.9 39.7893 31.0781C39.6656 30.8993 39.524 30.727 39.3694 30.5744C38.9512 30.1626 38.4532 29.951 37.8804 30.1642C37.2701 30.3907 36.6745 30.6564 36.0854 30.9353C35.7517 31.0928 35.4523 31.3209 35.1268 31.4997C34.969 31.5867 34.79 31.631 34.6191 31.695C34.5996 31.6605 34.5768 31.6244 34.5556 31.5883Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.9868 34.612C31.1447 34.7711 31.3384 34.9089 31.4507 35.096C31.6297 35.3946 31.7891 35.7129 31.8933 36.0443C32.1407 36.8285 32.5589 37.5143 32.9836 38.205C33.257 38.6496 33.4816 39.127 33.6981 39.6044C33.7908 39.8079 33.8966 40.049 33.6916 40.3083C33.3286 40.2344 33.2489 39.903 33.109 39.6602C32.209 38.0819 31.0812 36.607 30.8078 34.74C30.8664 34.6989 30.9266 34.6563 30.9868 34.612Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.2383 32.2724C36.4922 31.626 36.8925 31.2913 37.4882 31.2306C37.9666 31.1814 38.2823 31.4078 38.3572 31.8278C38.4402 32.2921 38.1928 32.699 37.6118 32.8909C37.7404 32.6284 37.8706 32.4529 37.9097 32.2593C37.9455 32.087 37.9373 31.8524 37.8429 31.7228C37.7746 31.6309 37.524 31.6227 37.371 31.6555C36.9186 31.7523 36.7754 31.9951 36.7314 32.6776C36.6208 32.7023 36.502 32.7285 36.3832 32.7548C36.2269 33.0353 36.2595 33.4553 35.7404 33.5833C35.8038 33.2929 35.8689 33.073 35.8982 32.8483C35.9633 32.3676 35.7257 32.1264 35.2668 32.1838C34.8876 32.2314 34.7379 32.4316 34.803 32.8171C34.8323 32.9844 34.8843 33.1485 34.9397 33.3716C34.7916 33.3716 34.663 33.4126 34.6061 33.3651C34.1341 32.9779 34.2301 32.2002 34.7786 31.9476C35.3091 31.7048 35.7989 31.731 36.2383 32.2724Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.8632 41.3796C33.4669 39.8177 33.405 37.9605 33.7907 35.9015C33.916 36.0606 34.0527 36.1558 34.069 36.2674C34.1129 36.5906 34.1406 36.9252 34.1162 37.2501C34.0413 38.2213 34.2643 39.1237 34.6516 39.9998C34.7932 40.3197 34.9299 40.6446 35.0454 40.976C35.0829 41.0842 35.0519 41.2155 35.0519 41.3369C34.9885 41.3517 34.9266 41.3648 34.8632 41.3796Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.0966 42.108C32.7883 41.8439 33.2879 42.1687 33.3074 42.7873C33.3351 43.6748 32.2317 44.4 31.4408 43.9931C31.2911 43.916 31.1446 43.7224 31.1039 43.5567C31.0209 43.2056 31.3627 42.7512 31.8102 42.5723C31.8102 42.7282 31.8102 42.8676 31.8102 43.0087C31.8102 43.1351 31.8102 43.2614 31.8102 43.4025C32.1406 43.5682 32.4221 43.5157 32.6174 43.2269C32.8192 42.9283 32.632 42.6937 32.4221 42.4805C32.3228 42.3771 32.2333 42.2639 32.0966 42.108Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M29.7743 41.4124C29.3756 41.5026 28.9818 41.6355 28.5782 41.6716C28.2462 41.7011 27.9256 41.5682 27.797 41.2007C27.6701 40.8398 27.841 40.556 28.0737 40.3099C28.3536 40.0146 28.6937 39.8833 29.151 40.0654C28.972 40.2065 28.7735 40.3296 28.6205 40.4953C28.518 40.6085 28.4334 40.7857 28.4382 40.9284C28.4415 40.9957 28.6742 41.0941 28.8093 41.1072C29.2454 41.1515 29.4326 40.9596 29.4391 40.5018C29.4407 40.4362 29.4016 40.3624 29.4228 40.3082C29.4602 40.2147 29.5253 40.0671 29.5855 40.0638C29.6962 40.0572 29.885 40.1163 29.9094 40.1901C29.9777 40.4083 30.0217 40.6528 29.9973 40.8775C29.9777 41.0629 29.8476 41.2385 29.7662 41.4173L29.7743 41.4124Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.5611 36.0179C26.0005 35.8949 26.4415 35.7702 27.0355 35.6045C26.8988 35.8752 26.8581 36.0409 26.7556 36.1459C26.3748 36.5331 25.5351 36.6676 25.0354 36.4445C24.6807 36.2854 24.544 36.0212 24.6595 35.7161C24.7946 35.36 25.2438 35.1222 25.5595 35.2419C25.8459 35.3502 25.8329 35.5241 25.5123 35.867C25.5285 35.9179 25.5448 35.9671 25.5611 36.0179Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M40.1213 34.0115C40.4908 34.0099 40.8618 33.982 41.2263 34.0164C41.49 34.041 41.7471 34.169 41.8073 34.4692C41.8692 34.7728 41.669 34.968 41.4428 35.1124C40.9887 35.3995 40.5054 35.5898 39.9618 35.3929C39.8528 35.3535 39.7666 35.2535 39.6494 35.1632C40.0839 34.6579 40.8716 35.2239 41.2296 34.5825C41.0001 34.2461 40.7153 34.3495 40.4452 34.3872C40.1734 34.4266 39.9 34.4643 39.6266 34.5037C39.6071 34.4561 39.5876 34.4102 39.568 34.3626C39.7535 34.2445 39.9374 34.128 40.123 34.0099L40.1213 34.0115Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M29.7662 41.4189C29.924 41.3812 30.0819 41.3435 30.3781 41.2713C30.1698 41.5239 30.0184 41.6519 29.9436 41.8143C29.8801 41.9538 29.8411 42.172 29.9061 42.2885C30.0282 42.5001 30.2463 42.4132 30.4237 42.3131C30.741 42.1342 30.7996 41.9587 30.7459 41.3533C31.1706 41.2188 31.405 41.3943 31.348 41.8078C31.2797 42.3131 30.5246 42.9135 30.0119 42.8709C29.4521 42.8233 29.182 42.3262 29.457 41.8291C29.54 41.6782 29.6653 41.5502 29.7711 41.4124C29.7743 41.4124 29.7662 41.4189 29.7662 41.4189Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M26.5375 37.2633C26.3129 37.3617 26.1111 37.4519 25.8686 37.5586C26.0948 37.9425 26.3861 37.8703 26.6384 37.7784C26.8939 37.6849 27.1249 37.5225 27.3593 37.3929C27.4179 37.4749 27.4699 37.5175 27.4618 37.5405C27.2177 38.2476 26.2185 38.6217 25.6489 38.1935C25.5024 38.0836 25.3739 37.8342 25.3804 37.6554C25.395 37.3256 25.6424 37.109 25.9516 37.0024C26.2022 36.9154 26.4138 36.9614 26.5375 37.2633Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M27.0517 38.7021C26.915 38.9383 26.8206 39.0991 26.7278 39.2582C27.1591 39.5667 27.5952 39.4403 27.8214 38.9564C27.8947 38.8005 27.9158 38.62 27.9891 38.4642C28.0184 38.4035 28.142 38.3296 28.1892 38.3477C28.2739 38.3789 28.3569 38.4675 28.3959 38.5511C28.4268 38.62 28.4008 38.7218 28.3829 38.8071C28.2674 39.3616 27.6424 39.8964 27.0794 39.9293C26.6611 39.9539 26.2819 39.6881 26.2526 39.3518C26.2266 39.0171 26.474 38.7972 27.0517 38.7021Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.8964 34.8514C25.6604 35.1353 25.374 35.0631 25.1185 34.9843C24.8792 34.9105 24.6286 34.8071 24.4415 34.6464C24.2527 34.4839 24.3194 34.2428 24.4724 34.0574C24.7002 33.7801 25.0078 33.6751 25.3463 33.7489C25.7385 33.8359 26.1226 33.9671 26.2853 34.4577C25.7971 34.5233 25.4179 34.0672 24.9199 34.2739C25.1071 34.7399 25.6653 34.4971 25.8964 34.8514Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.6963 35.2731C33.1772 34.9942 32.8094 34.1476 32.8517 33.4422C32.8826 32.9188 33.2797 32.3347 33.8281 32.0985C33.75 32.3101 33.7224 32.4775 33.6345 32.6054C33.2602 33.1501 33.2846 33.703 33.5271 34.2887C33.6475 34.5775 33.8428 34.8662 33.6963 35.2731Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.3489 35.0041C29.6817 35.7375 28.1503 36.0837 27.5466 35.6784C27.8818 35.3126 29.5189 34.9041 30.3489 35.0041Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.8145 35.2042C37.5891 35.8079 36.4011 35.4831 35.2131 35.1566C35.2147 35.0975 35.2163 35.0385 35.2179 34.9794C35.6053 35.0007 35.9926 35.0303 36.3815 35.0401C36.7949 35.05 37.2099 35.0303 37.6232 35.0401C38.0203 35.05 38.4304 34.9696 38.8145 35.2042Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M40.1229 34.0115C39.9667 33.9656 39.8088 33.9197 39.6347 33.8672C39.7291 33.5112 40.0057 33.5358 40.2091 33.4521C40.4223 33.3651 40.6371 33.2552 40.5297 32.9812C40.4353 32.7384 40.2059 32.7007 39.9797 32.7926C39.7242 32.8959 39.4784 33.0239 39.2034 33.1535C39.3043 32.7286 39.4898 32.5415 39.9178 32.4283C40.2417 32.343 40.5672 32.3168 40.8389 32.5694C41.153 32.8598 41.1188 33.3537 40.7413 33.6588C40.5574 33.8065 40.3296 33.8967 40.1213 34.0132C40.1213 34.0115 40.1229 34.0115 40.1229 34.0115Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.0675 37.6488C37.6851 38.0885 37.3531 37.9212 37.0634 37.849C36.3588 37.6751 35.7143 37.3863 35.2847 36.6447C35.8624 36.5824 36.2107 36.9696 36.637 37.1156C37.0813 37.2682 37.5207 37.4437 38.0675 37.6488Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M37.4849 39.0893C36.9299 39.2911 36.4336 39.0154 35.9389 38.794C35.5141 38.6036 35.5141 38.5758 35.4327 38.0934C36.1488 38.3592 36.8355 38.6135 37.5223 38.8678C37.5109 38.94 37.4979 39.0154 37.4849 39.0893Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.004 36.817C37.3742 36.899 36.2741 36.3281 35.8168 35.7243C36.3929 35.8211 37.6672 36.4413 38.004 36.817Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M31.1919 37.6996C30.9689 38.5085 30.2675 39.0581 29.6068 39.0646C29.6068 39.022 29.5889 38.958 29.61 38.9416C30.1341 38.5249 30.663 38.1131 31.1919 37.6996Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M37.659 33.6605C37.1936 34.0838 36.2107 34.3397 35.4849 34.133C36.1911 33.9263 36.8991 33.7195 37.6053 33.5128C37.6249 33.562 37.6428 33.6113 37.659 33.6605Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.8192 36.1049C30.6434 36.6349 30.1617 37.0696 29.5254 37.278C29.5807 36.881 30.2545 36.2723 30.8192 36.1049Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.8208 40.8546C31.0893 40.2935 31.4051 39.9391 31.8103 39.6241C31.9291 40.1704 31.5792 40.6364 30.8208 40.8546Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M35.436 39.652C35.9421 39.5109 36.2773 39.6848 36.6663 39.8193C36.3001 40.0982 36.0788 40.0687 35.436 39.652Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M0.0241645 20.1333C-0.0425583 17.6297 0.595377 15.2984 1.785 13.1147C3.40913 10.1304 5.96575 8.46513 9.22378 7.80724C10.9976 7.44958 12.7812 7.44138 14.5632 7.73669C14.9082 7.79411 15.1361 7.73505 15.3476 7.44138C17.0792 5.03458 19.5105 3.74504 22.3096 3.07895C24.3943 2.58184 26.5001 2.50965 28.6125 2.9034C29.0014 2.97559 29.3025 2.94277 29.6117 2.62941C31.1951 1.0298 33.1887 0.232454 35.3628 0.0552665C38.3703 -0.189187 41.2703 0.380111 44.0124 1.70738C45.591 2.47191 46.6862 3.66957 47.2997 5.30364C47.6708 6.28966 47.9669 7.30521 48.2794 8.31419C48.4373 8.82115 48.6195 9.29857 48.932 9.7399C49.6253 10.7177 49.8824 11.853 49.9703 13.0343C50.0858 14.5781 49.8531 16.0744 49.264 17.4968C48.8018 18.6124 48.3022 19.7182 47.7245 20.7748C46.9124 22.2579 45.7065 23.3653 44.1898 24.1069C42.2841 25.0388 40.2776 25.5703 38.1571 25.741C36.9919 25.8345 35.8511 25.7311 34.6989 25.6327C34.458 25.6113 34.1651 25.6737 33.9666 25.8049C31.7924 27.2388 29.3806 27.7983 26.8191 27.8344C25.7694 27.8492 24.7214 27.8475 23.6929 27.6014C23.2844 27.503 23.0435 27.6638 22.8303 28.005C21.5805 30 19.8555 31.4536 17.7383 32.42C13.883 34.1787 10.0798 34.0327 6.46047 31.8113C2.69796 29.5029 0.621415 26.0363 0.0323014 21.6541C-0.032794 21.1538 0.0241645 20.6386 0.0241645 20.1333ZM18.3274 6.667C18.3697 6.69161 18.4104 6.71458 18.4527 6.73919C18.342 6.9738 18.2167 7.20185 18.1207 7.44138C17.7187 8.44052 17.2614 9.42162 16.9425 10.447C16.1271 13.0605 16.0295 15.6937 17.0596 18.2794C18.2004 21.1423 20.2542 22.9486 23.2828 23.577C24.7588 23.8838 26.2348 23.8181 27.7093 23.5786C28.2365 23.4933 28.7557 23.3588 29.3969 23.2209C29.0226 22.7616 28.7361 22.4105 28.453 22.0594C27.5481 20.9388 26.9997 19.6608 26.793 18.2334C26.7556 17.9726 26.6482 17.6789 26.9786 17.3918C27.1006 17.6723 27.2031 17.9069 27.3057 18.1416C27.6474 18.9274 27.9436 19.7379 28.3391 20.4942C29.5986 22.9027 31.5548 24.4038 34.2253 24.8878C37.62 25.5031 40.8764 25.0289 43.9847 23.5327C45.3224 22.8879 46.3689 21.892 47.1175 20.614C47.9084 19.2654 48.5382 17.8364 48.9629 16.3205C49.2444 15.3131 49.3616 14.2894 49.2737 13.2476C49.2331 12.7603 49.1257 12.278 49.0492 11.794C49.0069 11.7972 48.9645 11.8005 48.9222 11.8022C48.7904 13.177 48.4177 14.483 47.8563 15.7331C46.792 18.1087 45.285 20.1267 43.1271 21.6049C41.4639 22.7435 39.6461 23.4293 37.6152 23.4539C37.4199 23.4556 37.2164 23.4588 37.0309 23.408C36.7266 23.3243 36.6631 23.0044 36.9089 22.7993C37.0195 22.7074 37.1758 22.6517 37.3206 22.6238C37.62 22.5663 37.9244 22.5319 38.2287 22.5024C40.0351 22.3235 41.6543 21.6541 43.119 20.5927C45.3452 18.9799 46.7545 16.7766 47.6594 14.1991C48.1801 12.7144 48.2615 11.2197 47.8449 9.71857C47.4511 8.29943 46.9726 6.90325 46.5349 5.49559C46.019 3.83856 44.8928 2.77543 43.3224 2.15855C42.5494 1.85504 41.7715 1.56136 40.9773 1.32511C38.686 0.644252 36.3539 0.401439 33.9926 0.87394C32.0007 1.27261 30.3017 2.19301 29.0632 3.87629C28.2414 4.9952 27.7467 6.25684 27.4391 7.59888C26.8435 10.2042 26.9607 12.8046 27.597 15.3837C28.0998 17.4197 29.0567 19.203 30.632 20.6041C32.0153 21.833 33.6102 22.6713 35.4003 23.1324C35.6574 23.198 35.9031 23.3079 36.1749 23.4031C35.9699 23.7394 35.7388 23.6377 35.5337 23.6163C33.5792 23.4096 31.8851 22.6188 30.4286 21.2948C28.5718 19.6083 27.514 17.4722 27.0062 15.0391C26.6205 13.1918 26.614 11.3182 26.7637 9.45115C26.9216 7.47255 27.4489 5.59567 28.5408 3.91239C28.6059 3.81231 28.6385 3.68926 28.7199 3.49567C28.4269 3.49567 28.2121 3.49074 27.9973 3.49731C26.863 3.5334 25.7287 3.57113 24.5961 3.60887C23.3462 3.64988 22.1159 3.83528 20.9198 4.19785C18.1565 5.03458 16.0913 6.71294 14.918 9.40685C14.0571 11.3805 13.896 13.4576 14.2784 15.5576C14.9505 19.2539 16.7879 22.2874 19.6163 24.7057C21.1916 26.051 23.024 26.8188 25.0989 26.9731C27.8118 27.1749 30.4026 26.6745 32.899 25.6163C33.0259 25.5621 33.1382 25.4785 33.2131 25.4358C32.3294 24.9682 31.4441 24.5433 30.6044 24.038C30.2122 23.8017 29.8883 23.746 29.4489 23.8706C27.6067 24.3907 25.7417 24.6237 23.8165 24.412C18.5764 23.8395 16.0116 19.5148 15.7349 15.5969C15.582 13.4231 15.9839 11.3395 16.8448 9.34943C17.2484 8.41099 17.6813 7.47583 18.3274 6.667ZM2.52546 17.4312C2.59381 17.4492 2.66378 17.4656 2.73213 17.4837C2.72237 17.6428 2.73376 17.8052 2.69959 17.9594C2.33505 19.6148 2.58079 21.2046 3.22198 22.7419C3.56047 23.5524 3.95918 24.3382 4.33836 25.1306C4.80868 26.1134 5.54426 26.8074 6.59555 27.101C7.43528 27.3356 8.2864 27.5325 9.14078 27.7113C10.6835 28.0362 12.2409 28.2446 13.8228 28.1642C15.8391 28.0624 17.6748 27.4423 19.2875 26.197C19.3998 26.1101 19.4828 25.987 19.5918 25.8656C19.504 25.7672 19.4551 25.695 19.3901 25.6425C16.7553 23.5081 14.9831 20.7846 13.9904 17.5411C13.5233 16.0153 13.2955 14.4518 13.4778 12.8489C13.5282 12.4026 13.5624 11.9531 13.608 11.4757C13.5184 11.52 13.4713 11.5282 13.4468 11.5577C13.3915 11.625 13.3443 11.7004 13.3004 11.7759C12.6999 12.7718 12.6283 13.8513 12.8089 14.9686C12.8642 15.3164 12.9391 15.6626 12.9733 16.012C12.9863 16.1564 12.9131 16.309 12.8789 16.4583C12.8252 16.4648 12.7698 16.4714 12.7161 16.478C12.6152 16.2959 12.4964 16.1236 12.4183 15.9316C12.101 15.1491 12.0684 14.3205 12.2621 13.5265C12.5127 12.4912 12.7536 11.4101 13.7463 10.762C13.7967 10.7292 13.8342 10.6619 13.8553 10.6012C14.0945 9.94498 14.3289 9.28709 14.5746 8.60294C14.464 8.56193 14.3891 8.51599 14.3094 8.50779C11.9675 8.25677 9.63876 8.30107 7.36367 8.98357C5.6891 9.4856 4.2635 10.4093 3.2171 11.8448C1.05104 14.8111 0.278037 18.1547 0.745096 21.7756C1.25121 25.7016 3.20733 28.7449 6.51418 30.8679C9.00408 32.4675 11.7218 33.0696 14.656 32.5693C17.4909 32.0836 19.7888 30.6612 21.644 28.4792C21.9223 28.1527 22.1485 27.7835 22.4284 27.3931C21.6651 26.9993 20.993 26.6466 20.3144 26.3037C20.098 26.1938 19.945 26.3201 19.8018 26.4743C19.5788 26.7155 19.364 26.9681 19.1134 27.1765C17.2777 28.699 15.0905 28.9943 12.8236 28.9517C12.0847 28.9385 11.3378 28.8664 10.6103 28.7335C9.19448 28.4742 7.77866 28.1937 6.38399 27.841C5.28713 27.5621 4.39532 26.9156 3.86154 25.8788C3.01367 24.2299 2.3025 22.527 2.02585 20.673C1.89078 19.7658 1.95099 18.87 2.25857 18.0005C2.33017 17.8052 2.43595 17.6215 2.52546 17.4312Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M46.4828 38.5315C46.4763 40.8005 45.9246 42.8988 44.6422 44.7741C43.3273 46.6969 41.599 48.0898 39.4021 48.8757C37.7226 49.4761 35.9927 49.7911 34.2205 49.9404C32.5752 50.0783 30.951 49.9683 29.3318 49.6993C27.4717 49.3892 26.0087 48.4081 24.8581 46.9364C23.6961 45.4484 22.5488 43.9489 21.4162 42.4395C20.5732 41.3156 20.0036 40.0507 19.7725 38.6611C19.3901 36.356 19.7628 34.1773 21.0533 32.2118C22.1745 30.5039 23.618 29.1553 25.5481 28.4121C26.6271 27.997 27.7483 27.8165 28.8891 28.0708C29.4148 28.1873 29.9242 28.4105 30.414 28.6434C30.925 28.8862 31.3432 28.8944 31.8721 28.5991C33.6151 27.6295 35.511 27.1504 37.4931 26.9585C38.9773 26.8158 40.372 27.034 41.643 27.8264C43.0474 28.7008 44.1361 29.8854 44.8977 31.3685C44.9384 31.4473 44.9824 31.5276 44.9986 31.6113C45.3078 33.3422 46.1703 34.9238 46.338 36.6907C46.3949 37.3027 46.434 37.9179 46.4828 38.5315ZM44.9612 38.812C44.901 38.7891 44.8408 38.7661 44.7806 38.7431C44.792 38.6201 44.8017 38.497 44.8131 38.374C44.8522 37.9392 44.9742 37.4913 44.9156 37.0697C44.7399 35.7998 44.6862 34.5284 44.7073 33.2503C44.7171 32.6154 44.5543 32.0264 44.2354 31.4866C43.4266 30.1233 42.3997 28.9732 41.0294 28.1594C40.455 27.8182 39.8317 27.6443 39.1742 27.554C37.8316 27.3703 36.5199 27.5442 35.2229 27.8838C33.9275 28.2218 32.6972 28.7337 31.5206 29.3719C31.187 29.5523 30.9071 29.5933 30.5523 29.3653C28.8338 28.2562 27.0079 28.2644 25.2405 29.134C21.9028 30.7746 19.6602 33.9148 20.2624 38.3642C20.3844 39.2681 20.6741 40.136 21.2534 40.8497C21.6798 41.3747 22.1469 41.8866 22.679 42.2967C23.9956 43.3139 25.3317 44.3032 26.5424 45.455C27.3724 46.2441 28.3928 46.6854 29.4978 46.9397C31.2309 47.3384 32.9836 47.5254 34.7607 47.4729C35.8413 47.4418 36.8812 47.2334 37.887 46.8314C40.0221 45.9767 41.6592 44.4739 43.1027 42.7364C43.6333 42.0966 44.0743 41.3813 44.5592 40.7037C44.7057 40.4986 44.8278 40.2361 45.2623 40.3821C45.163 40.6151 45.0946 40.8317 44.9856 41.0253C43.7911 43.1531 42.1556 44.8709 40.1572 46.2425C38.3735 47.468 36.406 48.0586 34.24 48.0652C32.6126 48.0701 31.0226 47.8191 29.4294 47.5533C28.0543 47.3236 26.8744 46.7215 25.8508 45.7552C25.0876 45.0333 24.2609 44.3803 23.4569 43.7028C23.3544 43.6158 23.2209 43.5682 23.1021 43.5026C23.7629 44.5444 24.5163 45.4796 25.2405 46.4393C26.4155 47.9979 27.9762 48.8658 29.8802 49.13C33.135 49.5844 36.3247 49.3252 39.4379 48.2358C40.6258 47.8191 41.7325 47.2646 42.6275 46.3475C45.0474 43.8668 46.1183 40.9219 45.6398 37.4438C45.5617 36.8745 45.4657 36.3084 45.3778 35.7408C45.3339 36.3019 45.4413 36.8433 45.4754 37.388C45.5096 37.9327 45.412 38.4577 44.9612 38.812Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M41.5192 17.9087C42.1783 16.9325 41.9765 16.0335 40.9984 15.6381C40.2075 15.3198 39.5647 14.8686 38.987 14.2304C38.6582 13.8662 38.1212 13.6332 37.6346 13.4856C36.8128 13.2345 36.0284 12.9622 35.34 12.4159C34.6776 11.8892 33.89 11.8843 33.0893 11.9926C32.6597 12.05 32.2187 12.1025 31.789 12.073C31.0437 12.0221 30.4106 11.7252 29.9306 10.8934C30.1828 10.9934 30.3179 11.0181 30.4204 11.0919C31.1202 11.5906 31.8899 11.712 32.7248 11.5874C33.3497 11.4938 33.9795 11.4348 34.6077 11.3757C35.1073 11.3281 35.5109 11.5266 35.7713 11.9598C36.0284 12.388 36.4092 12.6045 36.8714 12.7194C37.2945 12.8244 37.7176 12.9327 38.1391 13.0426C38.7526 13.2017 39.2718 13.5151 39.6314 14.045C39.9439 14.5044 40.3605 14.7833 40.8845 14.9359C41.3516 15.072 41.7714 15.3001 42.0985 15.6791C42.8178 16.5109 42.7055 17.8824 41.7942 18.478C41.2995 18.8012 40.7136 19.0161 40.1424 19.1818C39.5012 19.3672 39.0765 18.9046 39.2018 18.245C39.249 17.9907 39.3173 17.8939 39.6802 17.5921C39.703 17.7938 39.7225 17.953 39.7388 18.1121C39.7876 18.6027 39.9422 18.6978 40.3702 18.478C40.4825 18.4206 40.5737 18.3221 40.6974 18.227C40.6713 18.1154 40.6648 18.0055 40.6225 17.912C40.5427 17.7348 40.4923 17.5379 40.7022 17.4657C40.8373 17.4181 41.0358 17.4739 41.1758 17.5461C41.2979 17.6101 41.3809 17.7578 41.5192 17.9087Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.2575 14.9015C24.1631 15.0015 24.0817 15.1262 23.9694 15.1984C23.7123 15.3641 23.4471 15.52 23.172 15.6545C22.2639 16.104 21.4568 16.7012 20.6805 17.3476C19.6032 18.2451 19.2696 18.1991 18.3875 17.0917C18.3061 16.9883 18.2183 16.8899 18.1353 16.7865C17.6503 16.1926 17.5917 15.5577 17.9579 14.8834C18.0425 14.7292 18.1222 14.5717 18.2166 14.424C18.7081 13.6644 18.8155 12.8474 18.6804 11.9565C18.6121 11.5103 18.6593 11.0378 18.713 10.585C18.7374 10.3733 18.9018 10.1781 19.0271 9.9238C19.1019 10.055 19.1459 10.0977 19.1394 10.1272C18.975 10.8327 19.0645 11.5316 19.2126 12.2207C19.3997 13.0869 19.2419 13.8662 18.7911 14.6242C18.1662 15.6791 18.3582 16.506 19.3379 17.2705C19.5706 17.4526 19.7561 17.4116 19.9807 17.2443C20.7179 16.6963 21.4535 16.1434 22.22 15.6381C22.674 15.3395 23.1818 15.1197 23.6749 14.8851C23.8311 14.8112 24.0199 14.803 24.1924 14.7653C24.2168 14.8129 24.238 14.8572 24.2575 14.9015Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M44.141 6.59337C43.9587 6.37517 43.8627 6.28822 43.7992 6.18158C43.202 5.16603 42.2678 4.5754 41.2344 4.12259C40.7462 3.9093 40.2255 3.85352 39.6949 3.95524C38.5444 4.17673 37.4003 4.1554 36.2595 3.88633C34.9674 3.58282 33.8005 3.9093 32.7167 4.62954C32.4205 4.82642 32.1195 5.01673 31.8216 5.20868C31.7923 5.17423 31.7631 5.13978 31.7321 5.10532C31.7907 5.00196 31.8314 4.8822 31.9111 4.80017C32.9706 3.71243 34.2513 3.23172 35.7583 3.39907C36.6013 3.49258 37.441 3.62711 38.2856 3.70094C38.6502 3.73376 39.0261 3.6829 39.3922 3.6304C41.1043 3.38102 42.4566 4.09469 43.6234 5.25462C43.9278 5.55486 44.2598 5.90923 44.141 6.59337Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.8903 11.9614C44.2304 11.4217 44.8017 11.2232 45.2768 11.4578C45.835 11.7334 45.9164 12.4881 45.3875 12.8786C45.0474 13.1296 44.6389 13.2969 44.2451 13.4593C44.1279 13.5069 43.9473 13.4265 43.8057 13.379C42.6389 12.9852 41.5436 12.4815 40.6176 11.6202C39.9618 11.0115 39.2148 10.5013 38.5151 9.94019C38.3588 9.81551 38.227 9.65636 38.0854 9.51363C38.1147 9.47425 38.144 9.43652 38.1733 9.39714C38.3051 9.44308 38.4451 9.47425 38.5671 9.53824C39.5436 10.0485 40.4272 10.6916 41.2019 11.4775C41.887 12.1714 42.7219 12.575 43.6283 12.8507C43.778 12.8966 43.9668 12.872 44.123 12.8293C44.3509 12.7654 44.5657 12.6522 44.7886 12.5668C44.9872 12.4914 45.189 12.3749 45.0864 12.1485C45.0197 12.0025 44.8114 11.8482 44.6552 11.8351C44.4111 11.8138 44.1605 11.9106 43.8903 11.9614Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.0723 20.2614C34.1488 20.2925 34.235 20.3073 34.2985 20.3549C34.8046 20.7388 35.3579 20.7174 35.921 20.5419C36.3799 20.3992 36.8291 20.2269 37.2864 20.0792C37.729 19.9349 38.1896 19.8528 38.6371 20.0169C40.0057 20.5206 41.2539 20.1941 42.4615 19.5067C42.7853 19.3229 43.1092 19.1392 43.4428 18.9767C43.5648 18.9177 43.7146 18.9177 43.8512 18.8914C43.8757 18.9324 43.9001 18.9735 43.9245 19.0145C43.7943 19.1375 43.682 19.2983 43.529 19.3754C42.6128 19.8348 41.7064 20.3286 40.7527 20.6928C40.3361 20.852 39.7877 20.8372 39.3466 20.7191C38.3963 20.4632 37.5093 20.5173 36.5866 20.8421C36.1049 21.0111 35.5646 21.0521 35.0487 21.0653C34.567 21.0784 34.1878 20.8257 33.9828 20.3795C34.0153 20.3401 34.0446 20.3007 34.0723 20.2614Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M26.6661 5.9321C26.5994 6.00428 26.5457 6.10272 26.4643 6.1421C25.5611 6.5703 24.6352 6.81968 23.6229 6.56538C22.5993 6.3078 21.5171 6.7721 20.9263 7.67937C20.7555 7.94187 20.5732 8.19452 20.3958 8.4521C20.3535 8.43405 20.3096 8.41765 20.2673 8.3996C20.2591 8.2864 20.2103 8.15515 20.251 8.06163C20.5472 7.36765 20.9491 6.74913 21.5903 6.32092C22.0476 6.01577 22.5505 5.92225 23.0859 5.98295C23.3235 6.0092 23.5627 6.04202 23.7938 6.10108C24.5815 6.2996 25.3431 6.24546 26.0917 5.92389C26.2528 5.85499 26.4383 5.84678 26.6124 5.81069C26.6303 5.85006 26.6482 5.89108 26.6661 5.9321Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.8771 7.19878C33.8771 7.09378 33.8689 7.01174 33.8787 6.93135C33.9503 6.2669 33.6151 5.82393 32.9625 5.77307C32.8111 5.76159 32.5833 5.82229 32.5117 5.93057C32.4401 6.04049 32.4824 6.26362 32.5394 6.41292C32.6012 6.57042 32.7477 6.69182 32.8404 6.84112C32.9153 6.96253 32.9641 7.10034 33.0406 7.2644C32.9169 7.31198 32.8372 7.37432 32.7656 7.36448C32.2595 7.29885 31.7778 6.66557 31.8038 6.11596C31.8298 5.56799 32.2611 5.17096 32.8616 5.17096C33.4068 5.17096 33.8966 5.34979 34.2725 5.75666C34.5345 6.04049 34.6794 6.38995 34.5313 6.78698C34.4288 7.06424 34.2611 7.27589 33.8771 7.19878Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M42.1946 10.2551C42.2043 10.0583 42.1832 9.97622 42.2141 9.93849C42.7316 9.28388 43.4233 8.93607 44.2353 8.87372C44.7073 8.83763 45.0116 9.20841 44.9481 9.68583C44.9237 9.87287 44.8423 10.073 44.7284 10.224C44.3199 10.7654 43.1075 10.9491 42.4387 10.5734C42.6568 10.1665 43.0603 10.1485 43.433 10.0763C43.6446 10.0353 43.8692 10.0254 44.0661 9.94833C44.1523 9.91388 44.2483 9.73341 44.2288 9.64318C44.2109 9.56443 44.0303 9.46107 43.9359 9.47419C43.7259 9.50537 43.516 9.58576 43.3207 9.67763C42.9725 9.84169 42.6323 10.0287 42.1946 10.2551Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.8178 7.81398C39.0424 7.69257 39.1905 7.61546 39.337 7.53507C39.7487 7.30703 39.9244 7.00515 39.8333 6.56218C39.7975 6.38991 39.6559 6.12577 39.542 6.11429C39.3679 6.09624 39.1075 6.21437 39.0066 6.36038C38.8504 6.58515 38.7885 6.88046 38.7072 7.15281C38.6453 7.35953 38.6388 7.59086 38.3475 7.68273C38.2857 7.5925 38.1978 7.51375 38.1783 7.42187C38.0172 6.68851 38.5867 5.74843 39.3012 5.54827C39.778 5.41538 40.1734 5.60898 40.3622 6.07163C40.6096 6.67374 40.3606 7.54492 39.8366 7.91078C39.4932 8.15031 39.293 8.14375 38.8178 7.81398Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.2115 19.0063C33.7648 18.8423 34.0528 18.4354 34.2839 17.9285C34.1358 17.8136 34.0056 17.7135 33.8689 17.6069C33.9584 17.2509 34.1814 17.1656 34.4694 17.2394C34.7607 17.3149 34.8942 17.5314 34.8877 17.8317C34.873 18.5076 33.8071 19.5871 33.1447 19.597C32.7428 19.6035 32.4498 19.3115 32.4368 18.8915C32.4205 18.3862 32.8502 17.7775 33.5076 17.4855C33.3758 17.7923 33.2733 18.0154 33.1854 18.2418C33.0894 18.4846 32.982 18.7324 33.2115 19.0063Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.6108 7.85003C30.3081 8.37503 29.9517 8.87871 29.7158 9.43324C29.47 10.0124 29.2715 10.6325 29.1771 11.2543C29.0876 11.8417 29.1576 12.452 29.1576 13.0902C28.7654 13.0246 28.7572 12.7604 28.7035 12.5422C28.4659 11.5628 28.6091 10.6046 28.9867 9.69902C29.2031 9.17894 29.54 8.7048 29.8671 8.24214C30.0185 8.02722 30.2772 7.88777 30.4855 7.7155C30.5278 7.75816 30.5685 7.80409 30.6108 7.85003Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M20.9018 20.7749C21.4763 18.7356 24.6822 16.9129 26.1697 17.7381C26.0411 17.8103 25.95 17.8858 25.8458 17.9137C25.7221 17.9449 25.5854 17.9334 25.4552 17.9432C24.0476 18.0449 22.9295 18.6913 22.0263 19.7643C21.722 20.1203 21.447 20.519 20.9018 20.7749Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M31.3856 12.616C31.0796 12.8588 30.8697 13.0245 30.5979 13.2378C31.2879 13.5282 31.6785 12.8359 32.305 12.8867C32.2611 13.0508 32.2627 13.2116 32.1846 13.3051C31.7078 13.8711 31.0698 14.0549 30.3684 13.9482C30.1732 13.9187 29.9063 13.707 29.8623 13.5299C29.8184 13.3543 29.9583 13.0541 30.1129 12.9195C30.427 12.6456 30.7851 12.3732 31.3856 12.616Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M23.4813 21.3393C23.6391 21.1884 23.7856 21.0768 23.8962 20.9358C24.0264 20.7684 24.1631 20.5879 24.2233 20.3911C24.2575 20.2795 24.1745 20.0629 24.0785 20.0055C24.002 19.9596 23.7905 20.0449 23.701 20.1368C23.535 20.3074 23.4194 20.5272 23.273 20.7175C23.159 20.8652 23.0321 21.0014 22.7945 21.0883C22.8059 20.9538 22.775 20.793 22.8368 20.6897C23.0728 20.2975 23.2941 19.8825 23.6049 19.556C23.9695 19.1721 24.4268 19.2918 24.679 19.7611C25.0452 20.4436 24.4935 21.4411 23.7221 21.487C23.67 21.4886 23.6163 21.4247 23.4813 21.3393Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.7477 17.8448C36.9267 18.2631 37.0487 18.5486 37.2261 18.9604C37.3661 18.7455 37.4686 18.6274 37.5256 18.4895C37.6069 18.2894 37.6362 18.0663 37.7241 17.8694C37.7566 17.7939 37.8982 17.7135 37.9731 17.7267C38.0528 17.7414 38.1505 17.8513 38.1798 17.9416C38.3409 18.442 37.9015 19.3525 37.4198 19.5478C37.1122 19.6724 36.8079 19.5871 36.6386 19.2787C36.4043 18.8554 36.3685 18.4223 36.7477 17.8448Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.4596 9.27246C36.0576 7.79097 35.6915 6.44073 35.3139 5.04948C35.8542 5.43667 36.5052 6.82956 36.6874 8.03378C36.7412 8.38816 36.9381 8.79339 36.4596 9.27246Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.452 21.8118C25.631 21.5231 25.7791 21.2097 25.9955 20.9538C26.2836 20.6142 26.6351 20.5765 26.9166 20.7848C27.2063 20.9997 27.3186 21.5411 27.1396 21.8561C26.9752 22.1449 26.5977 22.2581 26.2218 22.1219C26.1013 22.0776 25.9939 21.994 25.8735 21.9595C25.7775 21.9316 25.6684 21.9546 25.5643 21.9546C25.5252 21.9054 25.4894 21.8578 25.452 21.8118ZM26.1713 21.5231C26.2055 21.5707 26.238 21.6199 26.2722 21.6675C26.3666 21.5936 26.4642 21.5231 26.5505 21.4411C26.5586 21.4329 26.4935 21.3475 26.461 21.2983C26.365 21.3738 26.2673 21.4493 26.1713 21.5231Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.5535 7.09044C43.2573 8.0502 41.3989 9.17568 40.3655 9.05427C40.4387 8.97388 40.4826 8.90005 40.5477 8.8574C41.4412 8.27989 42.3362 7.70403 43.2346 7.13473C43.298 7.09536 43.3957 7.11012 43.5535 7.09044Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M21.5658 12.5177C21.3608 12.5472 21.1509 12.5636 20.9507 12.6128C20.7424 12.6637 20.5308 12.7228 20.3437 12.8228C20.2542 12.8721 20.1582 13.041 20.1793 13.128C20.2005 13.2166 20.3583 13.3183 20.4641 13.3282C20.6854 13.3495 20.9116 13.3134 21.2176 13.297C21.0256 13.7613 20.7001 13.7892 20.386 13.7908C20.0898 13.7925 19.818 13.6727 19.6927 13.3889C19.6293 13.2461 19.6211 13.0378 19.6732 12.8901C19.8587 12.3536 20.8612 11.932 21.382 12.1551C21.4698 12.1928 21.5317 12.2913 21.6049 12.3618C21.5919 12.4127 21.5789 12.4652 21.5658 12.5177Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.0329 10.5636C21.9255 10.1813 21.8783 9.92702 21.7774 9.69733C21.727 9.58248 21.5707 9.43155 21.4731 9.43811C21.2453 9.45451 21.146 9.64811 21.1916 9.87123C21.2225 10.0189 21.3006 10.1567 21.3624 10.2978C21.4487 10.4914 21.5398 10.6833 21.696 11.0197C21.4243 10.9344 21.2713 10.9278 21.1769 10.8507C20.6431 10.4159 20.5601 9.64483 20.9849 9.2199C21.3722 8.83108 21.8669 8.87701 22.1354 9.35608C22.3258 9.70061 22.4642 10.073 22.0329 10.5636Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M20.7457 14.9688C20.5651 15.2821 20.0052 15.2329 20.0231 15.7366C20.4365 16.1517 20.8775 15.5643 21.3592 15.753C21.2941 15.8859 21.2681 16.045 21.1884 16.0778C20.8515 16.2206 20.5049 16.3617 20.1485 16.4371C19.8816 16.4929 19.6293 16.3666 19.4861 16.109C19.3299 15.8268 19.3885 15.5561 19.5626 15.3035C19.8441 14.8999 20.2656 14.7752 20.7457 14.9688Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.9544 9.21827C33.864 9.52999 32.0804 8.87046 31.5499 7.90577C32.0186 7.95334 32.3343 8.24702 32.7053 8.38811C33.0715 8.52757 33.4393 8.66702 33.8136 8.77694C34.1993 8.89178 34.5947 8.97218 34.9869 9.06733C34.9755 9.11819 34.9658 9.16905 34.9544 9.21827Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.9414 6.11092C36.5687 5.65647 36.6208 5.20857 36.8014 4.77873C36.956 4.41123 37.3075 4.37677 37.5874 4.6606C37.9715 5.04943 37.9178 5.60069 37.4573 5.87959C37.314 5.96819 37.1481 6.02069 36.9414 6.11092Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.1452 21.6116C22.6481 21.8544 23.0777 22.112 23.5399 22.2727C24.0004 22.4335 24.4935 22.4959 24.9638 22.6009C25.0013 22.8913 24.8271 22.9356 24.653 22.9684C23.7986 23.1324 22.6123 22.6058 22.1468 21.8577C22.1289 21.8265 22.1452 21.7724 22.1452 21.6116Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.8385 9.24459C24.6937 9.15764 24.5782 9.1117 24.4935 9.03131C24.3845 8.92631 24.3113 8.78357 24.2022 8.67693C23.937 8.41443 23.6701 8.37013 23.5252 8.57029C23.3186 8.85412 23.5334 9.0067 23.7384 9.14779C23.81 9.19701 23.893 9.22983 23.989 9.28068C23.6766 9.64326 23.4422 9.50217 23.2437 9.33975C23.0094 9.14615 22.8857 8.86725 23.0273 8.57849C23.1168 8.3931 23.2811 8.21756 23.4553 8.10927C23.7986 7.89599 24.1404 8.0256 24.4203 8.26021C24.6921 8.4899 24.9752 8.7442 24.8385 9.24459Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.4385 15.789C32.1553 16.2303 31.6362 16.4928 31.2782 16.4141C31.0096 16.355 30.8681 16.1795 30.8534 15.9055C30.816 15.2509 31.4328 14.7209 32.1765 14.8062C32.0284 15.2049 31.3546 15.2263 31.4832 15.8382C31.7875 15.8218 32.0935 15.807 32.4385 15.789Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.5865 13.5299C33.021 13.2083 34.7037 12.5882 35.0504 12.6013C34.5784 13.2559 33.3026 13.7612 32.5865 13.5299Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.1098 13.8072C35.8641 14.5438 35.244 15.2821 34.7802 15.438C34.7884 14.972 35.5012 14.068 36.1098 13.8072Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.6514 13.4511C24.3666 13.6447 23.4797 13.8449 22.6839 13.8957C23.1379 13.3264 24.1241 13.1033 24.6514 13.4511Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M24.6123 10.1782C25.1802 10.6342 25.3414 11.0756 25.1558 11.5628C24.7067 11.3463 24.5195 10.9 24.6123 10.1782Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M22.7897 11.3183C23.4488 11.1083 23.9891 11.425 24.1046 12.1419C23.5806 11.9467 23.1786 11.6826 22.7897 11.3183Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M16.1173 26.5598C15.9627 26.8748 15.7121 26.8436 15.4599 26.7206C15.1393 26.5664 14.97 26.2891 14.9407 25.9347C14.8968 25.3884 14.8691 24.8404 14.8235 24.2941C14.7764 23.7264 14.7438 23.1555 14.651 22.5944C14.6218 22.4139 14.4183 22.1285 14.2963 22.1285C14.0684 22.1285 13.7934 22.2564 13.6274 22.4205C13.4907 22.555 13.4631 22.8175 13.4224 23.0292C13.2368 24.0136 13.3215 24.9979 13.4696 25.9774C13.5168 26.2809 13.5851 26.5828 13.6144 26.8879C13.6274 27.0192 13.5623 27.157 13.533 27.2932C13.4858 27.3079 13.4386 27.3211 13.3915 27.3358C13.2792 27.1718 13.1278 27.0208 13.0611 26.8387C12.4931 25.285 12.5843 23.733 13.1197 22.1941C13.188 21.9972 13.341 21.8102 13.4972 21.6675C14.0571 21.1572 14.7178 21.2753 14.9505 21.9939C15.1653 22.6535 15.2288 23.3639 15.3508 24.0546C15.3769 24.2055 15.3671 24.3614 15.3752 24.5156C15.4403 25.5968 15.507 25.7789 16.1173 26.5598Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.89825 26.0987C7.04635 26.0462 7.19118 25.9708 7.34416 25.9478C7.55897 25.915 7.78192 25.9445 7.99511 25.9084C8.84135 25.769 9.46139 25.3194 9.66807 24.4581C9.78524 23.9741 9.79988 23.4606 9.82104 22.9586C9.84382 22.4008 9.88776 21.8413 10.2149 21.3852C10.4346 21.0768 10.7438 20.811 11.0627 20.6059C11.3117 20.4468 11.6372 20.4336 11.9432 20.747C11.7674 20.8307 11.6453 20.9176 11.5119 20.9488C10.9602 21.0751 10.6298 21.4361 10.5143 21.966C10.3971 22.4992 10.3532 23.0488 10.2637 23.5902C10.1921 24.0217 10.1465 24.4647 10.0147 24.8797C9.67946 25.9363 8.44915 26.6647 7.37182 26.4744C7.21234 26.4465 7.06262 26.3579 6.90802 26.2972C6.90476 26.2283 6.90151 26.1644 6.89825 26.0987Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M3.32775 14.9327C3.38634 14.8195 3.42702 14.6915 3.50676 14.598C4.20328 13.7793 4.88679 12.9508 5.6126 12.16C6.53533 11.1543 7.71681 10.6063 9.03011 10.3373C9.57691 10.2257 10.1237 10.0846 10.7177 10.2142C10.5957 10.2667 10.4769 10.3373 10.3483 10.3701C9.60946 10.5604 8.85273 10.6966 8.12854 10.9378C6.93729 11.3348 5.98364 12.0993 5.19111 13.0722C4.74683 13.6169 4.30093 14.1583 3.84851 14.6948C3.7346 14.831 3.59302 14.9442 3.46282 15.0672C3.41726 15.0213 3.37169 14.977 3.32775 14.9327Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.92343 13.0229C7.7135 12.9245 7.68095 12.7161 7.80138 12.5455C7.90228 12.4028 8.09268 12.2682 8.26193 12.2403C8.61019 12.1846 9.05447 12.6521 9.08701 13.018C9.10817 13.2477 9.14072 13.4889 9.23348 13.6956C9.71519 14.7751 10.4345 15.6807 11.2824 16.4912C11.4614 16.6618 11.6111 16.8636 11.7755 17.0507C11.7478 17.0933 11.7185 17.136 11.6908 17.1786C11.5606 17.1507 11.3946 17.1672 11.3051 17.09C10.0553 16.0187 8.98937 14.8227 8.72248 13.1017C8.71597 13.059 8.73713 12.9967 8.71434 12.9737C8.5988 12.8556 8.46861 12.6538 8.35144 12.6603C8.21962 12.6685 8.09919 12.8654 7.92343 13.0229Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.45875 23.0701C6.44248 23.4934 6.13653 23.9347 6.68008 24.1546C6.97138 24.2727 7.47099 24.043 7.63535 23.7411C7.80298 23.4327 7.72161 23.2719 7.17643 22.8651C7.37334 22.573 7.63698 22.5829 7.91201 22.6928C8.20006 22.8076 8.37093 23.1161 8.34815 23.436C8.28631 24.3285 6.95185 25.0389 6.18861 24.5844C5.87127 24.3958 5.71829 24.0676 5.77362 23.6886C5.83058 23.3195 5.97217 23.1817 6.45875 23.0701Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M18.1043 25.4704C18.075 25.6279 18.0474 25.7558 18.0295 25.8854C17.9904 26.1725 17.8098 26.2398 17.5608 26.1906C16.9798 26.0757 16.4102 25.2226 16.5144 24.6287C16.5957 24.1661 17.0091 23.9626 17.3866 24.2268C17.8179 24.5303 18.0425 24.9732 18.1043 25.4704Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.37097 21.7807C6.1708 21.8168 5.96412 21.8332 5.76883 21.8923C5.43847 21.9907 5.10811 22.099 4.79566 22.2401C4.72893 22.2712 4.69476 22.4698 4.71754 22.5748C4.73219 22.6371 4.8933 22.7159 4.97792 22.7044C5.18623 22.6781 5.38803 22.6026 5.6956 22.5206C5.61911 22.7076 5.60284 22.8668 5.53124 22.8996C5.27899 23.0128 5.00559 23.1539 4.74358 23.1473C4.54829 23.1424 4.31558 22.9603 4.17888 22.7897C4.01288 22.583 4.10565 22.3303 4.26025 22.1219C4.2993 22.0694 4.34487 22.0219 4.39044 21.9759C4.84773 21.5231 5.82579 21.3558 6.37097 21.7807Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.23346 20.2975C5.00075 20.3385 4.88357 20.3762 4.76477 20.3746C4.63621 20.373 4.493 20.2893 4.38397 20.327C4.2196 20.3828 3.97387 20.4894 3.94783 20.6141C3.8925 20.8766 4.15613 20.9127 4.34654 20.9062C4.60366 20.898 4.85916 20.8455 5.11466 20.8061C5.29368 20.7782 5.47269 20.7405 5.80793 20.6781C5.64356 20.8881 5.59962 20.9931 5.52151 21.0374C5.07398 21.2901 4.58902 21.3869 4.07965 21.3426C3.77532 21.3163 3.53773 21.1834 3.44497 20.8684C3.3636 20.5895 3.50518 20.2712 3.78346 20.0809C4.20333 19.7922 4.67852 19.8398 5.23346 20.2975Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M4.4327 17.6199C4.41805 17.7496 4.41154 17.8513 4.39527 17.9497C4.34319 18.2385 4.4034 18.4829 4.69145 18.601C4.98764 18.7224 5.24151 18.6322 5.4433 18.3845C5.57187 18.227 5.70206 18.0695 5.8827 17.8513C5.93966 18.519 5.61418 18.9242 5.03971 19.0309C4.59869 19.1129 4.14628 18.8521 4.00144 18.4353C3.8745 18.0695 3.98517 17.8398 4.4327 17.6199Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.1879 15.287C7.32623 14.9835 7.5915 14.7521 7.30508 14.4782C7.09026 14.2731 6.84778 14.2386 6.58414 14.3289C6.44093 14.3781 6.30749 14.4536 6.16916 14.5126C6.0585 14.5602 5.94621 14.5996 5.77208 14.6668C6.12848 14.1172 6.70457 13.8531 7.17 13.9827C7.45968 14.0631 7.68426 14.2321 7.75586 14.5389C7.82096 14.8145 7.75261 15.0655 7.50199 15.2263C7.43852 15.2657 7.34739 15.2575 7.1879 15.287Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M8.07811 20.3467C7.60291 20.4993 6.32216 20.4025 5.84045 20.204C6.28798 19.8332 7.41251 19.8857 8.07811 20.3467Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M6.36116 18.2779C7.04466 18.4256 7.55566 18.5978 7.97878 19.0408C7.51172 19.1524 6.80381 18.8308 6.36116 18.2779Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.77537 16.8489C8.26196 17.1245 8.74855 17.4002 9.31163 17.7184C8.70787 17.8431 8.03087 17.4691 7.77537 16.8489Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M5.3261 16.1746C6.21303 15.981 6.7224 16.3583 6.64103 17.1261C6.43923 16.8915 6.29439 16.6487 6.08446 16.5011C5.86314 16.3452 5.5816 16.2796 5.3261 16.1746Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M9.82263 16.186C9.28071 16.0991 8.86411 15.8087 8.46051 15.2952C8.86736 15.2739 9.00406 15.5675 9.22701 15.6873C9.44996 15.8071 9.66641 15.9399 9.8861 16.0679C9.86495 16.1057 9.84379 16.1467 9.82263 16.186Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M7.39946 21.3968C7.63218 21.3574 7.79655 21.3279 8.00323 21.2934C7.81282 21.7183 7.81282 21.7183 7.39946 21.3968Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.8714 43.1909C35.2929 44.2393 34.9104 45.1875 33.9259 45.537C33.3514 45.7404 32.7493 45.7667 32.1878 45.5534C30.6988 44.9874 29.1983 44.4345 27.763 43.7503C27.182 43.4731 26.7507 42.8726 26.2625 42.4083C26.1551 42.305 26.0754 42.1622 26.0086 42.0244C24.972 39.8604 24.0704 37.6456 23.5383 35.2945C23.4667 34.9779 23.4569 34.6367 23.4764 34.3102C23.5578 32.9452 24.3585 31.9509 25.6604 31.5802C27.1006 31.17 28.4855 31.362 29.7646 32.1068C30.1812 32.348 30.5393 32.7499 30.8208 33.1519C31.13 33.5932 30.9722 33.8475 30.4612 33.9919C30.1064 34.092 29.7663 34.2511 29.4082 34.3397C28.3879 34.5891 27.8199 34.3528 27.2422 33.4734C26.8614 32.8943 26.6563 32.8533 26.1437 33.2897C26.3162 33.4685 26.4855 33.6441 26.6791 33.8442C26.3764 34.0969 26.1567 33.9131 25.95 33.7835C25.5172 33.5095 25.3007 33.1142 25.3984 32.8221C25.4976 32.5252 25.885 32.3677 26.4155 32.3972C26.8565 32.4218 27.2113 32.6154 27.4961 32.9435C27.6393 33.1092 27.7678 33.2881 27.8964 33.4652C28.1015 33.7474 28.3781 33.9394 28.7182 33.9476C29.2162 33.9591 29.7109 33.8967 30.1926 33.6572C30.1373 33.1666 29.8151 32.8877 29.4554 32.7007C28.2072 32.0576 26.8939 31.8377 25.5269 32.2561C24.8288 32.4694 24.3878 32.9731 24.1697 33.667C23.9614 34.3331 23.9386 35.0206 24.1111 35.6899C24.2901 36.3905 24.5163 37.0828 24.7751 37.7588C25.1608 38.7645 25.605 39.7472 26.0021 40.748C26.5864 42.2262 27.5742 43.2385 29.1088 43.729C29.8525 43.9669 30.5523 44.3443 31.2651 44.674C33.0308 45.4927 32.8876 45.3385 34.1488 44.1753C34.2985 44.0375 34.3767 43.8127 34.4645 43.6191C34.554 43.4255 34.5866 43.1909 34.8714 43.1909Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M43.1742 36.5627C42.7316 37.2238 42.7853 37.9539 42.7609 38.6774C42.7511 38.9727 42.6714 39.3074 42.5135 39.5502C41.6673 40.8562 40.8324 42.1753 39.6851 43.2499C39.2409 43.6649 38.7315 43.9373 38.131 44.039C37.1057 44.2129 36.3848 43.7421 36.1277 42.7265C36.0756 42.5198 36.0072 42.318 35.9421 42.1047C36.3457 41.7782 36.8877 42.2885 37.2554 41.8192C37.179 41.2352 36.5475 41.5666 36.2546 41.2532C36.5101 40.8824 36.8453 40.9087 37.1806 41.0104C37.5077 41.1088 37.7827 41.2942 37.8462 41.665C37.8966 41.9685 37.7241 42.1835 37.4703 42.2934C37.1594 42.4296 36.8258 42.5149 36.4938 42.6264C36.7461 43.1088 37.0976 43.2121 37.6639 43.176C38.9772 43.0907 39.9097 42.5001 40.5802 41.3894C40.8064 41.0153 41.0928 40.679 41.3548 40.3263C41.7421 39.8062 41.9586 39.2205 42.0855 38.5806C42.1881 38.0671 42.3459 37.5602 42.5282 37.068C42.66 36.7234 42.7316 36.7021 43.1742 36.5627Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M39.3531 38.6889C39.6444 38.3805 39.0488 37.9424 39.5468 37.6127C39.6574 37.7062 39.7632 37.8063 39.8804 37.8932C40.0008 37.9835 40.131 38.1229 40.2579 38.1245C40.3979 38.1278 40.5411 37.9982 40.6827 37.926C40.616 37.803 40.5769 37.6094 40.4776 37.5684C40.1782 37.447 39.856 37.3863 39.3368 37.2468C39.5695 37.132 39.6932 37.0696 39.7583 37.0368C39.5874 36.8383 39.4247 36.6644 39.2864 36.4724C39.249 36.4199 39.2571 36.2903 39.2961 36.2362C39.3368 36.182 39.4621 36.1361 39.5191 36.1607C39.7193 36.246 39.8999 36.3707 40.0968 36.4642C40.3588 36.5889 40.642 36.6874 40.9024 36.4905C41.0049 36.4134 41.0732 36.2509 41.0879 36.1197C41.0928 36.0721 40.8991 35.9688 40.7868 35.9491C40.4972 35.8999 40.2026 35.8818 39.9129 35.7899C40.3718 35.4995 40.8584 35.5012 41.3271 35.6669C41.6819 35.7932 41.7568 36.2329 41.4899 36.5479C41.3108 36.7579 41.0684 36.9154 40.8552 37.0959C41.5289 37.8899 41.415 38.2378 40.3116 38.7381C40.3637 39.4141 40.3523 39.4403 39.7437 39.9703C39.7437 40.1261 39.7583 40.3 39.7404 40.469C39.6916 40.9628 39.1822 41.4534 38.6891 41.496C38.3018 41.5289 37.8754 41.2335 37.7371 40.8267C37.6525 40.5806 37.6313 40.3476 37.9519 40.2557C38.3311 40.3853 38.3262 41.0416 38.8372 40.9202C39.0114 40.8792 39.1448 40.6659 39.384 40.4559C39.0797 40.3263 38.8942 40.2459 38.6615 40.1474C38.7331 40.0588 38.7965 39.9817 38.873 39.8882C38.7493 39.7176 38.6208 39.5388 38.4385 39.2878C38.6517 39.2549 38.7705 39.2106 38.8812 39.2254C39.0065 39.2435 39.1253 39.355 39.2473 39.355C39.4247 39.3567 39.6932 39.3567 39.7616 39.25C39.9276 38.9957 39.6981 38.8694 39.4833 38.7792C39.4442 38.766 39.4133 38.7316 39.3531 38.6889Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.5556 31.5883C34.6158 31.5112 34.6598 31.4062 34.7379 31.3603C35.4491 30.9337 36.157 30.5006 36.8844 30.1068C37.1676 29.9543 37.4963 29.8689 37.8136 29.8066C38.5948 29.654 39.2832 29.8492 39.8349 30.4514C39.9683 30.5974 40.1034 30.7417 40.2173 30.9009C40.6713 31.5325 41.2263 32.0461 41.8886 32.4529C42.2597 32.681 42.6307 32.9271 42.9448 33.224C43.8268 34.0607 43.6771 35.452 42.6567 36.1197C42.6112 36.1493 42.5347 36.1296 42.4191 36.1361C42.4305 35.9967 42.4029 35.8572 42.4549 35.7621C42.909 34.9549 42.4403 34.2297 42.2548 33.4865C42.219 33.3454 42.0269 33.2257 41.8837 33.1338C41.0473 32.5907 40.3572 31.9 39.7893 31.0781C39.6656 30.8993 39.524 30.727 39.3694 30.5744C38.9512 30.1626 38.4532 29.951 37.8804 30.1642C37.2701 30.3907 36.6745 30.6564 36.0854 30.9353C35.7517 31.0928 35.4523 31.3209 35.1268 31.4997C34.969 31.5867 34.79 31.631 34.6191 31.695C34.5996 31.6605 34.5768 31.6244 34.5556 31.5883Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.9868 34.612C31.1447 34.7711 31.3384 34.9089 31.4507 35.096C31.6297 35.3946 31.7891 35.7129 31.8933 36.0443C32.1407 36.8285 32.5589 37.5143 32.9836 38.205C33.257 38.6496 33.4816 39.127 33.6981 39.6044C33.7908 39.8079 33.8966 40.049 33.6916 40.3083C33.3286 40.2344 33.2489 39.903 33.109 39.6602C32.209 38.0819 31.0812 36.607 30.8078 34.74C30.8664 34.6989 30.9266 34.6563 30.9868 34.612Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M36.2383 32.2724C36.4922 31.626 36.8925 31.2913 37.4882 31.2306C37.9666 31.1814 38.2823 31.4078 38.3572 31.8278C38.4402 32.2921 38.1928 32.699 37.6118 32.8909C37.7404 32.6284 37.8706 32.4529 37.9097 32.2593C37.9455 32.087 37.9373 31.8524 37.8429 31.7228C37.7746 31.6309 37.524 31.6227 37.371 31.6555C36.9186 31.7523 36.7754 31.9951 36.7314 32.6776C36.6208 32.7023 36.502 32.7285 36.3832 32.7548C36.2269 33.0353 36.2595 33.4553 35.7404 33.5833C35.8038 33.2929 35.8689 33.073 35.8982 32.8483C35.9633 32.3676 35.7257 32.1264 35.2668 32.1838C34.8876 32.2314 34.7379 32.4316 34.803 32.8171C34.8323 32.9844 34.8843 33.1485 34.9397 33.3716C34.7916 33.3716 34.663 33.4126 34.6061 33.3651C34.1341 32.9779 34.2301 32.2002 34.7786 31.9476C35.3091 31.7048 35.7989 31.731 36.2383 32.2724Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M34.8632 41.3796C33.4669 39.8177 33.405 37.9605 33.7907 35.9015C33.916 36.0606 34.0527 36.1558 34.069 36.2674C34.1129 36.5906 34.1406 36.9252 34.1162 37.2501C34.0413 38.2213 34.2643 39.1237 34.6516 39.9998C34.7932 40.3197 34.9299 40.6446 35.0454 40.976C35.0829 41.0842 35.0519 41.2155 35.0519 41.3369C34.9885 41.3517 34.9266 41.3648 34.8632 41.3796Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M32.0966 42.108C32.7883 41.8439 33.2879 42.1687 33.3074 42.7873C33.3351 43.6748 32.2317 44.4 31.4408 43.9931C31.2911 43.916 31.1446 43.7224 31.1039 43.5567C31.0209 43.2056 31.3627 42.7512 31.8102 42.5723C31.8102 42.7282 31.8102 42.8676 31.8102 43.0087C31.8102 43.1351 31.8102 43.2614 31.8102 43.4025C32.1406 43.5682 32.4221 43.5157 32.6174 43.2269C32.8192 42.9283 32.632 42.6937 32.4221 42.4805C32.3228 42.3771 32.2333 42.2639 32.0966 42.108Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M29.7743 41.4124C29.3756 41.5026 28.9818 41.6355 28.5782 41.6716C28.2462 41.7011 27.9256 41.5682 27.797 41.2007C27.6701 40.8398 27.841 40.556 28.0737 40.3099C28.3536 40.0146 28.6937 39.8833 29.151 40.0654C28.972 40.2065 28.7735 40.3296 28.6205 40.4953C28.518 40.6085 28.4334 40.7857 28.4382 40.9284C28.4415 40.9957 28.6742 41.0941 28.8093 41.1072C29.2454 41.1515 29.4326 40.9596 29.4391 40.5018C29.4407 40.4362 29.4016 40.3624 29.4228 40.3082C29.4602 40.2147 29.5253 40.0671 29.5855 40.0638C29.6962 40.0572 29.885 40.1163 29.9094 40.1901C29.9777 40.4083 30.0217 40.6528 29.9973 40.8775C29.9777 41.0629 29.8476 41.2385 29.7662 41.4173L29.7743 41.4124Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.5611 36.0179C26.0005 35.8949 26.4415 35.7702 27.0355 35.6045C26.8988 35.8752 26.8581 36.0409 26.7556 36.1459C26.3748 36.5331 25.5351 36.6676 25.0354 36.4445C24.6807 36.2854 24.544 36.0212 24.6595 35.7161C24.7946 35.36 25.2438 35.1222 25.5595 35.2419C25.8459 35.3502 25.8329 35.5241 25.5123 35.867C25.5285 35.9179 25.5448 35.9671 25.5611 36.0179Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M40.1213 34.0115C40.4908 34.0099 40.8618 33.982 41.2263 34.0164C41.49 34.041 41.7471 34.169 41.8073 34.4692C41.8692 34.7728 41.669 34.968 41.4428 35.1124C40.9887 35.3995 40.5054 35.5898 39.9618 35.3929C39.8528 35.3535 39.7666 35.2535 39.6494 35.1632C40.0839 34.6579 40.8716 35.2239 41.2296 34.5825C41.0001 34.2461 40.7153 34.3495 40.4452 34.3872C40.1734 34.4266 39.9 34.4643 39.6266 34.5037C39.6071 34.4561 39.5876 34.4102 39.568 34.3626C39.7535 34.2445 39.9374 34.128 40.123 34.0099L40.1213 34.0115Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M29.7662 41.4189C29.924 41.3812 30.0819 41.3435 30.3781 41.2713C30.1698 41.5239 30.0184 41.6519 29.9436 41.8143C29.8801 41.9538 29.8411 42.172 29.9061 42.2885C30.0282 42.5001 30.2463 42.4132 30.4237 42.3131C30.741 42.1342 30.7996 41.9587 30.7459 41.3533C31.1706 41.2188 31.405 41.3943 31.348 41.8078C31.2797 42.3131 30.5246 42.9135 30.0119 42.8709C29.4521 42.8233 29.182 42.3262 29.457 41.8291C29.54 41.6782 29.6653 41.5502 29.7711 41.4124C29.7743 41.4124 29.7662 41.4189 29.7662 41.4189Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M26.5375 37.2633C26.3129 37.3617 26.1111 37.4519 25.8686 37.5586C26.0948 37.9425 26.3861 37.8703 26.6384 37.7784C26.8939 37.6849 27.1249 37.5225 27.3593 37.3929C27.4179 37.4749 27.4699 37.5175 27.4618 37.5405C27.2177 38.2476 26.2185 38.6217 25.6489 38.1935C25.5024 38.0836 25.3739 37.8342 25.3804 37.6554C25.395 37.3256 25.6424 37.109 25.9516 37.0024C26.2022 36.9154 26.4138 36.9614 26.5375 37.2633Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M27.0517 38.7021C26.915 38.9383 26.8206 39.0991 26.7278 39.2582C27.1591 39.5667 27.5952 39.4403 27.8214 38.9564C27.8947 38.8005 27.9158 38.62 27.9891 38.4642C28.0184 38.4035 28.142 38.3296 28.1892 38.3477C28.2739 38.3789 28.3569 38.4675 28.3959 38.5511C28.4268 38.62 28.4008 38.7218 28.3829 38.8071C28.2674 39.3616 27.6424 39.8964 27.0794 39.9293C26.6611 39.9539 26.2819 39.6881 26.2526 39.3518C26.2266 39.0171 26.474 38.7972 27.0517 38.7021Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M25.8964 34.8514C25.6604 35.1353 25.374 35.0631 25.1185 34.9843C24.8792 34.9105 24.6286 34.8071 24.4415 34.6464C24.2527 34.4839 24.3194 34.2428 24.4724 34.0574C24.7002 33.7801 25.0078 33.6751 25.3463 33.7489C25.7385 33.8359 26.1226 33.9671 26.2853 34.4577C25.7971 34.5233 25.4179 34.0672 24.9199 34.2739C25.1071 34.7399 25.6653 34.4971 25.8964 34.8514Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M33.6963 35.2731C33.1772 34.9942 32.8094 34.1476 32.8517 33.4422C32.8826 32.9188 33.2797 32.3347 33.8281 32.0985C33.75 32.3101 33.7224 32.4775 33.6345 32.6054C33.2602 33.1501 33.2846 33.703 33.5271 34.2887C33.6475 34.5775 33.8428 34.8662 33.6963 35.2731Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.3489 35.0041C29.6817 35.7375 28.1503 36.0837 27.5466 35.6784C27.8818 35.3126 29.5189 34.9041 30.3489 35.0041Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.8145 35.2042C37.5891 35.8079 36.4011 35.4831 35.2131 35.1566C35.2147 35.0975 35.2163 35.0385 35.2179 34.9794C35.6053 35.0007 35.9926 35.0303 36.3815 35.0401C36.7949 35.05 37.2099 35.0303 37.6232 35.0401C38.0203 35.05 38.4304 34.9696 38.8145 35.2042Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M40.1229 34.0115C39.9667 33.9656 39.8088 33.9197 39.6347 33.8672C39.7291 33.5112 40.0057 33.5358 40.2091 33.4521C40.4223 33.3651 40.6371 33.2552 40.5297 32.9812C40.4353 32.7384 40.2059 32.7007 39.9797 32.7926C39.7242 32.8959 39.4784 33.0239 39.2034 33.1535C39.3043 32.7286 39.4898 32.5415 39.9178 32.4283C40.2417 32.343 40.5672 32.3168 40.8389 32.5694C41.153 32.8598 41.1188 33.3537 40.7413 33.6588C40.5574 33.8065 40.3296 33.8967 40.1213 34.0132C40.1213 34.0115 40.1229 34.0115 40.1229 34.0115Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.0675 37.6488C37.6851 38.0885 37.3531 37.9212 37.0634 37.849C36.3588 37.6751 35.7143 37.3863 35.2847 36.6447C35.8624 36.5824 36.2107 36.9696 36.637 37.1156C37.0813 37.2682 37.5207 37.4437 38.0675 37.6488Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M37.4849 39.0893C36.9299 39.2911 36.4336 39.0154 35.9389 38.794C35.5141 38.6036 35.5141 38.5758 35.4327 38.0934C36.1488 38.3592 36.8355 38.6135 37.5223 38.8678C37.5109 38.94 37.4979 39.0154 37.4849 39.0893Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M38.004 36.817C37.3742 36.899 36.2741 36.3281 35.8168 35.7243C36.3929 35.8211 37.6672 36.4413 38.004 36.817Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M31.1919 37.6996C30.9689 38.5085 30.2675 39.0581 29.6068 39.0646C29.6068 39.022 29.5889 38.958 29.61 38.9416C30.1341 38.5249 30.663 38.1131 31.1919 37.6996Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M37.659 33.6605C37.1936 34.0838 36.2107 34.3397 35.4849 34.133C36.1911 33.9263 36.8991 33.7195 37.6053 33.5128C37.6249 33.562 37.6428 33.6113 37.659 33.6605Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.8192 36.1049C30.6434 36.6349 30.1617 37.0696 29.5254 37.278C29.5807 36.881 30.2545 36.2723 30.8192 36.1049Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M30.8208 40.8546C31.0893 40.2935 31.4051 39.9391 31.8103 39.6241C31.9291 40.1704 31.5792 40.6364 30.8208 40.8546Z\"\n      fill=\"#EE9D5B\"\n    />\n    <path\n      d=\"M35.436 39.652C35.9421 39.5109 36.2773 39.6848 36.6663 39.8193C36.3001 40.0982 36.0788 40.0687 35.436 39.652Z\"\n      fill=\"#EE9D5B\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: Tomatoes,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/pizzas-in-nyc/veggies.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Veggies', 'sticker name', 'web-stories');\n\nconst travelVeggies = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 46 50\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M22.7642 41.5806C22.9923 41.9239 23.216 42.269 23.4474 42.6075C24.1624 43.6497 24.7725 44.7535 25.3521 45.8761C25.5223 46.2074 25.7119 46.5311 25.8776 46.8642C26.205 47.5197 26.5239 48.1803 26.8459 48.8397C26.9365 49.0239 27.0256 49.2087 27.1168 49.3944C27.1447 49.4527 27.1794 49.5066 27.2043 49.5661C27.2601 49.7051 27.2861 49.8557 27.1464 49.9516C26.989 50.0595 26.851 49.9698 26.7408 49.8502C26.6629 49.7647 26.596 49.668 26.5396 49.5673C26.4021 49.32 26.2685 49.0696 26.1394 48.8173C25.7073 47.9675 25.2697 47.1215 24.8525 46.2659C24.3443 45.2209 23.7348 44.2379 23.0928 43.2727C22.4013 42.2335 21.7205 41.1866 21.0329 40.1441C20.9696 40.0477 20.892 39.9587 20.8356 39.8579C20.3991 39.0633 19.6694 38.8046 18.8493 38.8922C17.8904 38.9941 16.933 39.0159 15.972 38.9976C15.2676 38.9848 14.5957 39.153 13.9489 39.403C13.3199 39.6461 12.6836 39.7953 12.0055 39.8017C11.7195 39.8041 11.4227 39.885 11.1508 39.9857C10.6554 40.1699 10.1593 40.2333 9.64225 40.1148C9.00457 39.969 8.36747 39.8246 7.7301 39.6751C7.41217 39.6001 7.14011 39.4398 6.89198 39.2218C6.65334 39.0105 6.38017 38.8386 6.12952 38.6406C6.01055 38.5469 5.89016 38.4451 5.79728 38.3257C5.65929 38.1478 5.65803 37.9547 5.76671 37.7482C5.94877 37.3991 6.23345 37.1811 6.57874 37.0173C6.89029 36.8684 7.1945 36.705 7.49813 36.5402C7.5821 36.4954 7.65199 36.4233 7.75646 36.3429C7.66528 36.2764 7.60998 36.227 7.54566 36.1898C6.76744 35.7271 6.07396 35.1552 5.40845 34.5449C4.93362 34.1109 4.46599 33.669 3.99356 33.2324C3.6181 32.8859 3.35392 32.4633 3.12537 32.013C2.82906 31.4283 2.51632 30.85 2.22838 30.2604C2.11108 30.0208 2.0091 29.7632 1.95417 29.5029C1.85119 29.0175 2.06173 28.64 2.51676 28.4491C2.70398 28.3693 2.90613 28.3235 3.10444 28.2722C3.55864 28.1542 4.01692 28.0467 4.48104 27.8747C4.33577 27.5942 4.13366 27.4326 3.92514 27.2942C3.14996 26.7819 2.55732 26.0982 2.02502 25.3444C1.79025 25.0106 1.48728 24.7223 1.19593 24.433C0.798204 24.0382 0.480292 23.5967 0.267763 23.0728C-0.0637538 22.2564 0.402793 21.1898 1.46584 21.0906C1.80927 21.0589 2.1525 21.0135 2.49255 20.9554C2.91962 20.8825 3.32893 20.9583 3.7533 21.0904C3.76991 21.0183 3.79677 20.9681 3.78755 20.9267C3.6325 20.2767 3.48998 19.6235 3.30541 18.9815C3.16817 18.5008 3.1931 18.0659 3.50203 17.6674C3.67093 17.4479 3.8841 17.32 4.16736 17.2529C4.73629 17.1162 5.29038 17.2151 5.84668 17.2976C6.39227 17.379 6.93352 17.4847 7.47321 17.5995C7.72047 17.6519 7.95696 17.7517 8.24796 17.8459C8.21362 17.74 8.19207 17.6758 8.17201 17.611C8.07742 17.3194 7.95363 17.0323 7.89214 16.733C7.75799 16.0748 7.48731 15.4854 7.07775 14.9586C6.47387 14.1843 6.16941 13.2916 6.0336 12.3334C5.97703 11.9319 6.10562 11.569 6.2915 11.2253C6.42698 10.9773 6.66105 10.881 6.92913 10.8544C7.27704 10.821 7.60231 10.9104 7.87282 11.1197C8.43694 11.5535 9.08301 11.7739 9.74939 11.9846C10.2471 12.1418 10.7158 12.3966 11.197 12.6086C11.2863 12.6482 11.3741 12.6883 11.4857 12.7365C11.4974 12.6473 11.5165 12.5949 11.507 12.5484C11.3335 11.6654 11.1518 10.7837 10.9828 9.89888C10.9111 9.52058 10.8327 9.13802 10.8126 8.75522C10.7649 7.87327 11.194 7.40378 12.0651 7.34127C12.687 7.29628 13.2434 7.48069 13.6807 7.92409C14.1419 8.38927 14.6658 8.74189 15.2579 9.0092C15.74 9.22774 16.1651 9.54278 16.5479 9.91233C16.6386 9.99973 16.7341 10.0818 16.8725 10.2077C16.8955 10.0726 16.9304 9.98987 16.9199 9.91443C16.8548 9.45581 16.7948 8.99694 16.7056 8.54252C16.6207 8.11237 16.6339 7.69587 16.7907 7.29085C17.0502 6.6195 17.293 5.94078 17.5878 5.28506C17.9766 4.4164 18.4981 4.26357 19.3125 4.73991C19.4888 4.84412 19.6627 4.95966 19.8168 5.095C20.3964 5.60396 20.9671 6.12508 21.5419 6.63937C21.9795 7.03076 22.3067 7.5049 22.5797 8.02087C22.6247 8.10536 22.6824 8.18312 22.753 8.29391C22.8051 8.21141 22.8459 8.1748 22.8558 8.12949C23.0086 7.49787 23.4046 7.00499 23.7644 6.48989C24.0505 6.08125 24.3217 5.66109 24.5957 5.24334C24.68 5.11548 24.7604 4.98218 24.8352 4.84763C25.2489 4.09552 25.8456 3.53138 26.584 3.10572C27.0641 2.82899 27.4792 2.47381 27.8614 2.06925C28.141 1.77202 28.4538 1.49819 28.7847 1.26221C29.4676 0.773464 30.0994 0.824824 30.6873 1.42564C30.9727 1.71728 31.1972 2.06891 31.4433 2.39658C31.5185 2.49695 31.5757 2.61297 31.6571 2.74719C31.7661 2.70478 31.8707 2.68653 31.947 2.63091C32.6389 2.13001 33.4302 1.82719 34.1992 1.47601C34.8046 1.19889 35.3992 0.898347 36.0036 0.623315C36.4107 0.437217 36.8216 0.256542 37.2427 0.106469C37.9437 -0.145655 38.5402 0.0577388 38.9899 0.634578C39.4537 1.23011 39.7925 1.90194 39.8992 2.65723C40.0262 3.56189 40.1159 4.47241 40.2131 5.38003C40.2655 5.85914 40.1936 6.32788 40.0922 6.79598C39.8391 7.97821 39.6024 9.16271 39.3606 10.3475C39.3513 10.3943 39.361 10.4458 39.3628 10.5298C39.4645 10.504 39.5509 10.4964 39.6247 10.4607C40.5315 10.0265 41.5087 9.99359 42.4843 10.001C43.1492 10.0049 43.5066 10.4241 43.3524 11.0701C43.1599 11.8692 43.1531 12.6686 43.1302 13.4795C43.1062 14.3099 42.8147 15.0888 42.4716 15.8411C42.4287 15.9339 42.3836 16.0257 42.3422 16.1179C42.3385 16.1262 42.3489 16.1395 42.3616 16.1812C42.6455 16.1156 42.8995 15.9822 43.1509 15.8377C43.3727 15.7099 43.5875 15.5641 43.8204 15.4648C44.3755 15.2262 44.8183 15.3615 45.1518 15.8695C45.4902 16.3859 45.6742 16.9556 45.7125 17.575C45.738 17.9851 45.7641 18.3966 45.8129 18.8046C45.8722 19.2879 45.8246 19.7575 45.657 20.21C45.5161 20.5897 45.4555 20.9728 45.4606 21.3788C45.4677 22.0242 45.2913 22.6131 44.9177 23.1543C44.6351 23.5633 44.395 24.0059 44.1738 24.4532C43.9484 24.9074 43.6852 25.3175 43.3082 25.6647C43.0562 25.8959 42.8502 26.1835 42.6519 26.4646C41.9784 27.4233 41.2464 28.3288 40.3966 29.1348C39.8178 29.6833 39.2044 30.2004 38.4763 30.5287C37.9426 30.7693 37.3647 30.9095 36.8128 31.1122C36.261 31.3149 35.6697 31.4603 35.1784 31.7656C33.9889 32.5069 33.5355 33.6824 33.6139 35.0363C33.665 35.9049 33.8729 36.7659 34.0181 37.6289C34.3394 39.5365 34.8227 41.4052 35.4143 43.2473C35.5403 43.6373 35.7486 44.0004 35.8932 44.3849C36.0377 44.7694 36.1568 45.1638 36.2759 45.5581C36.346 45.7867 36.3243 46.0181 36.2197 46.2351C36.077 46.5309 35.8036 46.5526 35.6304 46.2709C35.5369 46.1189 35.4822 45.9431 35.4183 45.7744C35.2834 45.419 35.3738 45.4703 35.0014 45.1935C34.9276 45.3484 34.842 45.4992 34.7818 45.6626C34.7493 45.7513 34.7354 45.8657 34.7627 45.9535C34.822 46.15 34.9117 46.3363 34.9895 46.5273C35.0377 46.6468 35.097 46.7637 35.1291 46.886C35.1693 47.038 35.1178 47.1704 34.9749 47.245C34.8351 47.3185 34.6906 47.3004 34.5876 47.1815C34.497 47.0767 34.413 46.9538 34.3658 46.8236C34.2117 46.4013 34.0616 45.9758 33.9365 45.544C33.681 44.6669 33.3963 43.7942 33.2035 42.9014C32.8834 41.4168 32.6338 39.9186 32.3423 38.4281C31.9045 36.1995 31.717 33.9425 31.4905 31.687C31.4194 30.9835 31.2823 30.2868 31.169 29.5894C31.1451 29.4397 31.0905 29.295 31.0253 29.0525C30.9715 29.2013 30.9482 29.2605 30.9299 29.3195C30.922 29.3433 30.9203 29.3699 30.9201 29.3959C30.9196 31.0415 30.8482 32.6906 31.0685 34.3298C31.2449 35.6439 31.4045 36.9593 31.5904 38.2714C31.7206 39.1886 31.8996 40.099 32.0262 41.0159C32.1019 41.5637 32.1303 42.1178 32.1616 42.6708C32.2395 44.0941 32.7167 45.3862 33.4235 46.6061C33.611 46.929 33.804 47.248 33.993 47.5702C34.0447 47.659 34.1169 47.7518 34.1228 47.8463C34.1318 47.9621 34.117 48.1096 34.0503 48.1943C33.9523 48.3223 33.7882 48.2894 33.6665 48.2019C33.5644 48.1294 33.4761 48.0306 33.3959 47.9305C33.2446 47.7405 33.1035 47.5413 32.9269 47.3041C32.8549 47.5033 32.9453 47.6427 32.9449 47.7828C32.9464 48.0121 32.9629 48.2442 32.9353 48.4693C32.9182 48.6107 32.8176 48.7363 32.6424 48.7146C32.4693 48.6939 32.4245 48.5609 32.4095 48.4077C32.3356 47.657 32.1212 46.9385 31.8149 46.2574C30.8813 44.1855 30.4602 41.9953 30.2496 39.7543C30.1337 38.5204 29.9021 37.3073 29.5966 36.1074C29.351 35.1452 28.7829 34.3656 28.1774 33.6091C28.1547 33.5817 28.114 33.5698 28.0189 33.5153C28.0246 33.698 28.0099 33.8454 28.0353 33.9859C28.2087 34.9745 28.3967 35.9608 28.5701 36.9494C28.8922 38.7927 29.4709 40.5707 29.9463 42.3751C30.0604 42.8094 30.2621 43.2218 30.3732 43.6573C30.5832 44.4795 30.7497 45.3135 30.9472 46.1389C31.0853 46.7143 31.2454 47.2846 31.3899 47.8591C31.4556 48.1205 31.5203 48.384 31.5558 48.6519C31.5702 48.7638 31.5475 48.9351 31.4744 48.9947C31.3361 49.1073 31.2204 48.9691 31.1218 48.8658C31.0875 48.8307 31.0562 48.7945 30.9671 48.6978C30.9636 48.8876 30.9627 49.0089 30.9597 49.1293C30.953 49.3065 30.901 49.4598 30.7254 49.5386C30.5603 49.6132 30.4197 49.5435 30.3044 49.4328C30.1011 49.2371 29.9064 49.0329 29.7151 48.8239C29.6292 48.7312 29.5597 48.6234 29.4389 48.5425C29.4827 48.6551 29.5369 48.7636 29.5667 48.8799C29.6267 49.1089 29.5405 49.2894 29.3552 49.3563C29.1848 49.4175 29.0302 49.3515 28.9045 49.1567C28.8698 49.1028 28.8434 49.0439 28.8156 48.9856C28.3228 47.9537 27.8295 46.9202 27.3353 45.8889C27.309 45.9009 27.2827 45.9128 27.257 45.9263C27.3892 46.2084 27.5154 46.4929 27.652 46.7733C27.9446 47.375 28.2382 47.9745 28.5397 48.5727C28.6929 48.8778 28.7002 49.091 28.5416 49.2046C28.38 49.3193 28.188 49.2454 27.9599 48.9816C27.9351 48.9533 27.9112 48.9228 27.8737 48.8752C27.8531 48.9679 27.8504 49.0536 27.8159 49.1241C27.7319 49.2968 27.5536 49.342 27.3997 49.2204C27.3109 49.1513 27.2354 49.0545 27.1826 48.954C26.8362 48.2938 26.5051 47.6241 26.1543 46.9656C25.7609 46.2286 25.38 45.4798 24.9394 44.7715C24.3401 43.8104 23.6904 42.8828 23.0567 41.9438C22.9717 41.8179 22.8576 41.7102 22.7578 41.5952C22.7068 41.5304 22.6552 41.464 22.6042 41.3992C22.5802 41.3774 22.5557 41.3541 22.5317 41.3323C22.5572 41.3535 22.582 41.3732 22.606 41.395C22.6615 41.4494 22.7131 41.5158 22.7642 41.5806ZM17.2502 28.05L17.252 28.0459C17.2946 28.0846 17.3378 28.1249 17.3789 28.1642C17.4214 28.2029 17.464 28.2417 17.5066 28.2804C17.5492 28.3191 17.5917 28.3579 17.6343 28.3966C17.7282 28.4966 17.8236 28.596 17.9175 28.696C17.9607 28.7362 18.0033 28.775 18.045 28.8158C18.3357 29.1918 18.6395 29.5575 18.9126 29.9455C19.7831 31.1796 20.4673 32.5224 21.1722 33.852C21.6058 34.6702 22.0295 35.4939 22.4622 36.3141C23.0628 37.451 23.6655 38.5888 24.2706 39.7239C24.8572 40.8247 25.4133 41.9443 26.0492 43.0173C27.1646 44.9027 28.2426 46.8027 29.0619 48.8413C29.092 48.9143 29.1544 48.973 29.2024 49.039C29.2698 48.9384 29.2868 48.854 29.2615 48.7844C29.1756 48.5551 29.0809 48.3293 28.9792 48.1078C28.2299 46.4654 27.3019 44.9201 26.3754 43.3743C25.3102 41.5956 24.2963 39.7899 23.5385 37.8518C23.362 37.3985 23.1217 36.9666 22.8853 36.5401C22.1285 35.1788 21.3611 33.8251 20.596 32.4688C20.0278 31.4594 19.4467 30.4566 18.7248 29.5468C18.5192 29.288 18.2702 29.0634 18.0422 28.822C17.9997 28.7833 17.9565 28.7431 17.9139 28.7043C17.82 28.6043 17.7261 28.5043 17.6322 28.4044C17.5896 28.3656 17.547 28.3269 17.5044 28.2881C17.4619 28.2494 17.4193 28.2107 17.3767 28.1719C17.3345 28.1296 17.2928 28.0888 17.2502 28.05ZM18.8705 36.8669C18.8696 36.869 18.8696 36.869 18.8687 36.8711C18.8261 36.8323 18.7835 36.7936 18.741 36.7549C18.6984 36.7161 18.6558 36.6774 18.6132 36.6387C18.5707 36.5999 18.5281 36.5612 18.4855 36.5224C18.3916 36.4224 18.2962 36.323 18.2023 36.223C18.1606 36.1822 18.1174 36.142 18.0752 36.0997C18.0317 36.063 17.9903 36.0273 17.9468 35.9906C17.9036 35.9504 17.862 35.9096 17.8188 35.8693C17.6569 35.7405 17.4966 35.611 17.3353 35.4837C17.2496 35.4047 17.1659 35.3267 17.0802 35.2477L17.0633 35.2352L17.082 35.2435C17.1671 35.321 17.2523 35.3985 17.338 35.4774C17.4984 35.6069 17.6603 35.7357 17.8206 35.8652C17.8623 35.906 17.9055 35.9462 17.9471 35.987C17.9906 36.0237 18.032 36.0594 18.0755 36.0961C18.1187 36.1363 18.1603 36.1771 18.2041 36.2189C18.298 36.3189 18.3934 36.4183 18.4873 36.5183C18.5299 36.557 18.5725 36.5957 18.615 36.6345C18.6576 36.6732 18.7002 36.712 18.7428 36.7507C18.7859 36.7909 18.8279 36.8282 18.8705 36.8669ZM15.5691 30.9461C15.526 30.9059 15.4843 30.8651 15.4412 30.8248C15.3234 30.7341 15.2041 30.644 15.0857 30.5518C15.0425 30.5116 14.9994 30.4713 14.9583 30.432C14.8825 30.3786 14.8082 30.3245 14.7324 30.2711L14.7333 30.269C14.8085 30.3209 14.8852 30.3723 14.961 30.4258C15.0042 30.466 15.0473 30.5063 15.0884 30.5456C15.2062 30.6363 15.324 30.727 15.4439 30.8186C15.487 30.8588 15.5287 30.8996 15.5719 30.9399C15.6144 30.9786 15.657 31.0173 15.6996 31.0561C15.7422 31.0948 15.7848 31.1336 15.8258 31.1729C15.8678 31.2101 15.9104 31.2489 15.9524 31.2861L15.9506 31.2903C15.9086 31.253 15.866 31.2143 15.824 31.177C15.7814 31.1383 15.7389 31.0996 15.6963 31.0608C15.6543 31.0236 15.6117 30.9849 15.5691 30.9461ZM21.2918 39.5023C21.2818 39.4941 21.2717 39.4859 21.2607 39.4798C21.2717 39.4859 21.2827 39.492 21.2936 39.4981C21.3362 39.5369 21.3797 39.5735 21.4223 39.6123C21.6421 39.8326 21.8625 40.0545 22.0838 40.2743C22.1807 40.3731 22.277 40.4704 22.3725 40.5698C22.5252 40.7679 22.6788 40.9639 22.8315 41.162C22.8528 41.1417 22.8747 41.1228 22.896 41.1024C22.7211 40.9268 22.5441 40.7502 22.3691 40.5746C22.2765 40.4689 22.1844 40.3648 22.0917 40.2591C21.8676 40.0456 21.643 39.8306 21.419 39.617C21.3764 39.5783 21.3344 39.541 21.2918 39.5023ZM33.113 33.8244C33.1171 33.9057 33.1213 33.9871 33.1255 34.0684C33.139 34.1738 33.1525 34.2791 33.166 34.3845C33.1579 34.4343 33.1417 34.4855 33.1452 34.5343C33.2487 35.8024 33.404 37.0625 33.7727 38.2879C33.7722 38.3175 33.7732 38.3465 33.7728 38.3103C33.7791 38.3442 33.7731 38.3154 33.7685 38.2861C33.7589 38.1464 33.7593 38.0062 33.738 37.8676C33.6225 37.1469 33.5019 36.4264 33.3833 35.7068C33.3095 35.2654 33.2357 34.8241 33.1598 34.3817C33.1462 34.2764 33.1327 34.171 33.1198 34.0672C33.1157 33.9858 33.1115 33.9045 33.1073 33.8231C33.1083 33.8124 33.1093 33.8016 33.1102 33.7909C33.1108 33.8011 33.1119 33.8127 33.113 33.8244ZM19.153 37.1821C19.1397 37.17 19.1249 37.1585 19.1249 37.1585C19.1249 37.1585 19.1406 37.1679 19.1563 37.1774C19.2083 37.2401 19.2602 37.3029 19.3106 37.3662C19.3635 37.4269 19.4142 37.4867 19.467 37.5473C19.5181 37.6122 19.5706 37.6764 19.6222 37.7428C19.7363 37.8902 19.8489 38.0382 19.963 38.1857C20.0768 38.3367 20.1885 38.4868 20.3022 38.6378C20.5995 39.1012 20.8844 39.5727 21.1993 40.024C21.5059 40.4629 21.8439 40.881 22.1682 41.3079C22.1933 41.3327 22.2169 41.358 22.242 41.3828C22.2175 41.3596 22.1915 41.3368 22.167 41.3135C21.7262 40.6537 21.2909 39.9901 20.8433 39.3346C20.6787 39.0928 20.4818 38.8739 20.3016 38.645C20.1878 38.494 20.0761 38.3439 19.9623 38.1928C19.8497 38.0448 19.7356 37.8974 19.623 37.7493C19.572 37.6845 19.5195 37.6203 19.4679 37.5539C19.4151 37.4932 19.3637 37.432 19.3115 37.3728C19.2554 37.3082 19.2035 37.2455 19.153 37.1821ZM22.9527 39.1065C22.9365 39.0782 22.9197 39.0484 22.9438 39.0926C22.906 39.0572 22.9299 39.079 22.9545 39.1023C22.9751 39.1288 22.9958 39.1554 22.968 39.1195C23.003 39.1474 22.9775 39.1262 22.9527 39.1065ZM23.1486 41.5174C23.1304 41.4882 23.1106 41.4596 23.1359 41.4981C23.1037 41.464 23.1274 41.4894 23.1504 41.5132C23.1744 41.535 23.1983 41.5568 23.2223 41.5786C23.1974 41.5589 23.1725 41.5392 23.1486 41.5174ZM19.6378 35.2529C19.6148 35.229 19.5923 35.2067 19.5693 35.1828C19.5933 35.2046 19.6172 35.2264 19.6412 35.2482C19.6667 35.2918 19.6929 35.3369 19.7185 35.3806C19.7277 35.3735 19.7364 35.3649 19.7472 35.3573C19.71 35.3234 19.6736 35.2874 19.6378 35.2529ZM32.7132 36.2062C32.6997 36.1008 32.6862 35.9955 32.6727 35.8901C32.6613 35.7857 32.6504 35.6827 32.6375 35.5789C32.6219 35.4726 32.6057 35.3648 32.5916 35.2579C32.5802 35.1535 32.5693 35.0506 32.5579 34.9461C32.5571 34.8911 32.5584 34.837 32.5576 34.782C32.543 34.7843 32.5299 34.7859 32.5147 34.7866C32.5301 34.8394 32.5461 34.8937 32.5615 34.9465C32.5729 35.0509 32.5853 35.1533 32.5967 35.2577C32.6123 35.364 32.6284 35.4718 32.6425 35.5786C32.654 35.6831 32.6648 35.786 32.6763 35.8904C32.6898 35.9958 32.7033 36.1012 32.7168 36.2065C32.716 36.2397 32.7145 36.2714 32.7154 36.2295C32.7237 36.273 32.718 36.2406 32.7132 36.2062ZM30.3215 31.3331C30.3234 31.2805 30.3247 31.2264 30.3265 31.1738C30.3134 31.1755 30.2983 31.1762 30.2851 31.1778C30.299 31.2312 30.3124 31.2831 30.3277 31.3358C30.3433 31.4421 30.3595 31.5499 30.3751 31.6562C30.4137 31.9851 30.4449 32.3169 30.4937 32.6453C30.5591 33.1004 30.6382 33.5553 30.7116 34.0089C30.7293 34.1956 30.7449 34.3814 30.7626 34.5681C30.7761 34.6735 30.7896 34.7788 30.8031 34.8842C30.8085 34.9201 30.8139 34.956 30.8208 34.9914C30.8133 34.9545 30.8043 34.9183 30.7975 34.8829C30.784 34.7776 30.7704 34.6722 30.7569 34.5668C30.7393 34.3801 30.7237 34.1944 30.706 34.0077C30.7143 33.9318 30.7408 33.8541 30.7279 33.7813C30.612 33.0729 30.4904 32.3631 30.3709 31.6543C30.3533 31.5471 30.3371 31.4394 30.3215 31.3331ZM31.5565 39.8091C31.5565 39.7606 31.5551 39.7128 31.5552 39.6644C31.5471 39.6658 31.5385 39.6657 31.5304 39.6671C31.5405 39.715 31.5506 39.763 31.5627 39.8118C31.5619 39.845 31.5595 39.8787 31.5622 39.8327C31.5691 39.8767 31.5628 39.8429 31.5565 39.8091ZM24.0677 42.819C24.0433 42.7697 24.0169 42.7194 23.9926 42.6702C23.9803 42.6784 23.9701 42.6875 23.9578 42.6958C23.9959 42.7363 24.032 42.7758 24.0701 42.8163C24.1407 42.9271 24.2113 43.0379 24.2819 43.1487C24.3535 43.2574 24.425 43.3661 24.4959 43.4733C24.5656 43.5861 24.6368 43.6984 24.7066 43.8113C24.8478 44.0329 24.989 44.2544 25.1303 44.476C25.2911 44.7435 25.4514 45.0095 25.6107 45.2777C25.6544 45.3678 25.6972 45.4601 25.7409 45.5502C25.7561 45.5408 25.7705 45.5335 25.7857 45.5241C25.7268 45.4433 25.6678 45.3626 25.6089 45.2818C25.4481 45.0143 25.2878 44.7483 25.127 44.4807C24.9857 44.2592 24.8445 44.0376 24.7032 43.816C24.6335 43.7032 24.5623 43.5909 24.4926 43.478C24.4211 43.3693 24.3511 43.26 24.2795 43.1513C24.2089 43.0405 24.1383 42.9297 24.0677 42.819ZM23.507 43.2861C23.4739 43.2143 23.4408 43.1425 23.4077 43.0706C23.3954 43.0789 23.3826 43.0856 23.3703 43.0938C23.4172 43.1568 23.4635 43.2183 23.5103 43.2813C23.5809 43.3921 23.6516 43.5029 23.7222 43.6137C23.9269 43.9851 24.137 44.3527 24.3373 44.7259C24.7598 45.5155 25.1778 46.3069 25.5994 47.0986C25.2429 46.2712 24.8357 45.4722 24.4027 44.6866C24.1992 44.3181 23.9487 43.9749 23.721 43.6193C23.6483 43.5076 23.5776 43.3969 23.507 43.2861ZM24.5708 31.5889C24.6138 31.7658 24.656 31.9447 24.699 32.1215C24.7592 32.3469 24.8195 32.5724 24.8797 32.7978C24.9059 32.9224 24.9157 33.0535 24.9612 33.1705C25.413 34.3446 25.8649 35.5186 26.3346 36.6857C26.4334 36.9307 26.6038 37.1478 26.7408 37.3762C27.1243 38.2865 27.5192 39.1906 27.8893 40.106C28.573 41.7965 29.1646 43.5193 29.7212 45.2541C29.752 45.3994 29.7842 45.5441 29.815 45.6894C29.8365 45.6828 29.858 45.6761 29.8794 45.6695C29.8257 45.5314 29.7714 45.3918 29.7176 45.2537C29.6481 44.9956 29.589 44.7334 29.5069 44.4784C29.2491 43.6835 29.0127 42.8819 28.713 42.1032C28.1702 40.6863 27.5914 39.2834 27.0208 37.8791C26.9494 37.7046 26.8339 37.5491 26.7387 37.384C26.593 37.0846 26.4254 36.7955 26.3036 36.4869C25.8206 35.2593 25.3517 34.028 24.8762 32.7975C24.8159 32.572 24.7557 32.3466 24.6954 32.1212C24.6518 31.9428 24.6082 31.7645 24.5666 31.5871L24.5708 31.5889ZM30.023 46.4623C30.0031 46.3404 29.9831 46.2185 29.9632 46.0967C29.9462 46.1016 29.9286 46.1049 29.9131 46.1093C29.9521 46.2272 29.9911 46.3451 30.0307 46.4645C30.0744 46.6428 30.1165 46.8217 30.1601 47C30.2038 47.5361 30.3931 48.0225 30.6448 48.488C30.5924 48.2785 30.5088 48.0811 30.4385 47.8786C30.3389 47.5873 30.2482 47.2924 30.153 46.9994C30.1088 46.8195 30.0666 46.6406 30.023 46.4623ZM20.0055 35.7735C19.9818 35.7482 19.9567 35.7234 19.9337 35.6995C19.9582 35.7228 19.9828 35.7461 20.0088 35.7688C20.122 35.9183 20.2352 36.0678 20.3484 36.2174C20.8292 36.7683 21.3016 37.3241 21.7926 37.8659C22.0669 38.1687 22.3694 38.4468 22.6601 38.7346C22.1918 38.1011 21.7136 37.4818 21.1164 36.9676C20.8467 36.7338 20.6019 36.4713 20.3451 36.2221C20.2319 36.0726 20.1187 35.9231 20.0055 35.7735ZM30.6257 39.9345C30.6433 40.1213 30.661 40.308 30.6787 40.4947C30.7419 41.8096 30.9089 43.1083 31.3458 44.359C31.5283 44.8808 31.7472 45.3902 31.9571 45.9031C32.2501 46.6204 32.5174 47.3425 32.6048 48.1191C32.6096 48.1622 32.6405 48.202 32.6882 48.3114C32.7639 48.0244 32.7506 47.8049 32.686 47.6036C32.4689 46.931 32.2587 46.2541 31.9969 45.5989C31.5676 44.5181 31.2045 43.4219 31.0043 42.2761C30.8997 41.6807 30.7842 41.0879 30.673 40.4934C30.6554 40.3067 30.6398 40.1209 30.6221 39.9342C30.6065 39.8279 30.5903 39.7201 30.5748 39.6139C30.572 39.4611 30.5809 39.3073 30.5665 39.1556C30.383 37.2359 29.86 35.393 29.2743 33.5659C28.9676 32.6102 28.6385 31.6632 28.3163 30.7118C28.2799 30.605 28.2645 30.4814 28.1476 30.4197C28.1543 30.5294 28.1821 30.6275 28.2159 30.7232C28.5845 31.8069 28.962 32.8872 29.3201 33.975C29.7838 35.3829 30.1128 36.8242 30.3616 38.2847C30.4381 38.7285 30.5075 39.1717 30.581 39.6166C30.5939 39.7205 30.6101 39.8283 30.6257 39.9345ZM30.4857 47.2052C30.573 47.5221 30.6588 47.8395 30.746 48.1565C30.7779 48.1458 30.8084 48.1356 30.8403 48.1249C30.7205 47.8172 30.6014 47.511 30.4816 47.2033C30.4499 47.0601 30.4176 46.9154 30.3874 46.7716C30.3675 46.7776 30.346 46.7842 30.326 46.7903C30.3782 46.929 30.432 47.0671 30.4857 47.2052ZM30.9544 36.5623C30.9212 36.1899 30.8864 35.818 30.8517 35.446C30.8454 35.4122 30.8385 35.3769 30.8337 35.3424C30.842 35.3772 30.851 35.4135 30.8594 35.4482C30.8179 35.8273 30.8309 36.2008 30.9607 36.5651C30.96 36.6207 30.9584 36.6784 30.9576 36.7339C30.9737 36.7311 30.9904 36.7298 31.0065 36.727C30.9885 36.6718 30.9719 36.616 30.9544 36.5623ZM9.93895 27.4891L9.93623 27.4953C9.76033 27.2112 9.50974 27.0045 9.24176 26.815C9.32228 27.1985 9.56599 27.4095 9.93895 27.4891ZM35.2264 43.7007C35.2911 43.9728 35.3357 44.251 35.4243 44.5138C35.5565 44.9065 35.7207 45.2886 35.8936 45.7329C35.8103 44.9668 35.494 44.3397 35.2217 43.6973C35.1815 43.528 35.1429 43.3581 35.1028 43.1888C35.0798 43.196 35.0583 43.2026 35.0354 43.2099C35.0996 43.375 35.1633 43.5386 35.2264 43.7007ZM33.7475 47.7521L33.7448 47.7584C33.2712 46.8815 32.7984 46.0025 32.3562 45.1843C32.5847 45.8817 32.9572 46.5871 33.3806 47.2641C33.4883 47.4348 33.624 47.5893 33.7475 47.7521ZM25.9095 31.2355C25.8058 30.9734 25.7075 30.7075 25.5948 30.4489C25.4838 30.1948 25.4336 29.9067 25.2133 29.7072C25.2217 29.8128 25.252 29.9082 25.2951 29.9969C25.4317 30.2859 25.5688 30.5765 25.7114 30.8632C25.7735 30.9877 25.8462 31.1081 25.9128 31.2308C26.1917 31.9605 26.4846 32.6865 26.7471 33.4226C27.1522 34.5561 27.5393 35.6965 27.9345 36.8355C27.9467 36.9241 27.9463 37.0159 27.9704 37.0999C28.2337 38.0016 28.4994 38.9006 28.7657 39.8012C29.1775 41.1948 29.5923 42.5872 30.0026 43.9813C30.0572 44.1657 30.1094 44.3528 30.1419 44.5424C30.3438 45.7498 30.6935 46.9221 31.0101 48.102C31.0672 48.3149 31.109 48.5458 31.3215 48.7517C31.4064 48.4975 31.3142 48.3225 31.2497 48.1523C30.952 47.3832 30.6965 46.6029 30.5417 45.7903C30.4153 45.1343 30.2772 44.4794 30.1097 43.8325C29.9659 43.2731 29.7559 42.7292 29.6055 42.1707C29.1235 40.3671 28.5681 38.587 27.9283 36.8328C27.818 36.4125 27.7375 35.9806 27.5923 35.5722C27.1765 34.3979 26.7393 33.2304 26.2996 32.0654C26.1922 31.7806 26.0414 31.5126 25.9095 31.2355ZM19.8613 36.2376L19.8594 36.2417C19.7096 36.0201 19.5729 35.7881 19.4074 35.5794C19.1482 35.2534 18.7755 35.1789 18.3157 35.3665C18.8487 35.6672 19.355 35.9524 19.8613 36.2376ZM23.8431 40.3345C23.8182 40.2837 23.7942 40.2308 23.7692 40.18C23.757 40.1882 23.7453 40.198 23.7315 40.2068C23.7696 40.2473 23.8068 40.2898 23.8449 40.3303C23.9137 40.4539 23.9779 40.5793 24.0511 40.7012C24.7965 41.9493 25.5601 43.187 26.1688 44.5125C26.3425 44.8926 26.5252 45.2691 26.7034 45.6474C26.7107 45.5737 26.6874 45.5137 26.6646 45.4551C26.1412 44.0929 25.4724 42.8028 24.6954 41.5704C24.4277 41.1475 24.127 40.746 23.8431 40.3345ZM20.9892 36.3758C20.9972 36.3831 21.0067 36.3898 21.0153 36.3985C21.0058 36.3919 20.9969 36.3867 20.9874 36.38C20.788 36.0221 20.5613 35.6782 20.3956 35.3054C20.2345 34.9446 20.138 34.5553 20.0006 34.1404C19.7637 34.4901 19.7338 34.6383 19.8655 34.9414C20.1145 35.515 20.5142 35.9765 20.9892 36.3758ZM30.5675 30.9055C30.5773 30.8291 30.5913 30.7545 30.5975 30.6777C30.6688 29.6821 30.7402 28.6864 30.8079 27.6904C30.8102 27.6653 30.786 27.6384 30.7573 27.5735C30.2124 28.6861 30.2832 29.7907 30.5717 30.9073C30.568 30.9243 30.5637 30.9398 30.5643 30.9413C30.5652 30.9392 30.5674 30.9228 30.5675 30.9055ZM31.4821 29.2238C31.5466 28.6387 31.6521 28.0532 31.6642 27.466C31.6749 26.8932 31.6514 26.325 31.8311 25.7711C31.1667 26.868 31.1418 28.0271 31.4878 29.225C31.492 29.258 31.4983 29.2918 31.5025 29.3247C31.4953 29.293 31.489 29.2591 31.4821 29.2238ZM22.907 13.3259C22.6297 13.916 22.5745 14.5425 22.7307 15.1644C22.8932 15.8116 23.1228 16.4412 23.3288 17.0766C23.3573 17.1675 23.4139 17.2509 23.4743 17.3708C23.6553 17.169 23.7011 16.9645 23.7256 16.7493C23.7659 16.4156 23.6607 16.1143 23.5373 15.8149C23.2422 15.0967 23.0399 14.3562 22.9608 13.5832C22.9522 13.495 22.9204 13.4088 22.8987 13.3222L22.907 13.3259ZM31.6812 30.5653C31.6952 30.769 31.7017 30.9756 31.7252 31.1773C31.9678 33.3506 32.1288 35.5349 32.5243 37.6901C32.817 39.2856 33.0841 40.8858 33.4159 42.4713C33.6284 43.4896 33.9308 44.4919 34.202 45.4977C34.2991 45.8574 34.4212 46.2109 34.5442 46.5623C34.5818 46.6721 34.6588 46.7683 34.7563 46.9395C34.7817 46.8104 34.8031 46.7726 34.7935 46.7435C34.6 46.1448 34.3829 45.5517 34.2114 44.9478C33.9199 43.9206 33.6021 42.8966 33.3913 41.8517C32.7576 38.709 32.2123 35.5508 31.9553 32.3513C31.9073 31.7512 31.773 31.1588 31.6785 30.5629C31.6783 30.5094 31.6766 30.4565 31.677 30.4045C31.6639 30.4061 31.6508 30.4078 31.6377 30.4094C31.651 30.4613 31.6664 30.5141 31.6812 30.5653ZM14.5851 36.8825C14.5744 36.8815 14.5643 36.882 14.5535 36.881C14.5652 36.8799 14.5753 36.8794 14.5869 36.8784C15.3095 36.9774 16.0287 37.0898 16.7526 37.1658C16.9301 37.1849 17.1348 37.119 17.298 37.0348C17.5651 36.8997 17.8075 36.7189 18.1062 36.5283C17.8198 36.2648 17.5517 36.0131 17.2757 35.7679C16.9732 35.4984 16.6281 35.4375 16.2866 35.6551C15.9651 35.858 15.673 36.1099 15.3639 36.3357C15.1086 36.5232 14.8463 36.7014 14.5851 36.8825ZM22.4827 35.1394L22.4855 35.1332C22.5697 35.2923 22.651 35.4525 22.7362 35.6095C23.2592 36.5691 23.8011 37.5197 24.3029 38.4911C24.7862 39.4281 25.1055 40.4429 25.6534 41.3514C26.0171 41.9547 26.3489 42.5775 26.6959 43.1908C26.7066 43.0242 26.6544 42.8855 26.5982 42.7501C26.0701 41.464 25.5451 40.1767 25.0095 38.8936C24.7024 38.1575 24.3804 37.4273 24.0583 36.6971C23.7381 35.9714 23.2145 35.4475 22.4827 35.1394ZM6.29782 17.7148C6.23922 17.71 6.18062 17.7051 6.1226 17.7018C5.6918 17.5134 5.2357 17.4455 4.77364 17.4594C3.7501 17.4879 3.37545 17.9604 3.61334 18.9602C3.79494 19.7226 4.00574 20.4805 4.24848 21.2278C4.41467 21.7387 4.69611 22.2012 5.09968 22.6111C5.10147 22.3684 4.88275 22.1597 5.12893 21.9135C5.20313 22.1041 5.26123 22.2578 5.3229 22.4118C5.52102 22.912 5.89745 23.1682 6.42525 23.1598C6.71728 23.1551 7.01261 23.1058 7.29503 23.0322C7.75312 22.9109 8.19556 22.7318 8.65508 22.6186C9.08358 22.514 9.52448 22.4634 9.99386 22.3844C9.88911 22.3008 9.79714 22.219 9.69706 22.1474C9.16442 21.7636 8.63236 21.3813 8.09789 21.0016C7.91993 20.8756 7.73477 20.7575 7.54838 20.6451C7.05351 20.3451 6.53569 20.2114 5.9732 20.4441C5.91408 20.4689 5.85087 20.4831 5.78916 20.4968C5.21322 20.6155 4.69209 20.4865 4.23583 20.1179C4.03995 19.9591 3.89112 19.7577 3.93321 19.4596C4.21587 19.837 4.55979 20.1024 5.01323 20.2077C5.48776 20.3185 5.90983 20.1577 6.42287 19.9701C6.08545 19.7523 5.81339 19.592 5.55696 19.4101C5.30586 19.233 5.06352 19.0387 4.82565 18.8426C4.58246 18.6417 4.35069 18.426 4.1903 18.1376C5.18998 18.8823 6.18252 19.6264 7.36993 20.222C7.28843 19.7698 7.22921 19.4056 7.15895 19.0441C7.04103 18.4453 6.69178 18.0558 6.10127 17.8898C6.02404 17.868 5.9496 17.8313 5.87393 17.8003C5.87646 17.7803 5.87749 17.7609 5.88002 17.7409C5.96199 17.7263 6.04395 17.7116 6.1274 17.6964C6.186 17.7013 6.24402 17.7046 6.30262 17.7095C6.36811 17.7497 6.42938 17.7967 6.49849 17.8286C6.9746 18.0494 7.26596 18.4182 7.37887 18.9291C7.42581 19.1424 7.46679 19.3581 7.49764 19.5743C7.55564 19.9838 7.70299 20.3447 8.03951 20.6043C8.81138 21.201 9.58566 21.7949 10.3632 22.3841C10.434 22.4378 10.5318 22.4551 10.6178 22.4907C10.1663 21.7677 9.96755 20.9877 9.80496 20.1903C9.75152 19.9293 9.65817 19.6718 9.55074 19.4267C9.35022 18.969 8.95575 18.6973 8.54383 18.4515C7.84712 18.0347 7.10338 17.7798 6.29782 17.7148ZM11.0268 36.8589C10.9682 36.854 10.9102 36.8507 10.8516 36.8458C10.7161 36.7758 10.5758 36.7112 10.4439 36.6329C10.3387 36.5701 10.2234 36.4992 10.2826 36.3068C10.376 36.3569 10.4483 36.4013 10.5236 36.4359C10.9114 36.6152 11.2967 36.6294 11.6531 36.3748C11.8494 36.2345 12.0413 36.0785 12.2043 35.9011C12.474 35.6094 12.7257 35.3023 12.9715 34.9888C13.2759 34.6007 13.6236 34.2666 14.052 34.0204C14.121 33.9814 14.1745 33.9157 14.2721 33.831C14.1144 33.7524 14.0038 33.6935 13.8905 33.6408C13.5526 33.4836 13.1984 33.3553 12.8774 33.1709C12.287 32.8285 11.7334 32.9075 11.2305 33.302C10.729 33.696 10.27 34.146 9.78647 34.5641C9.45696 34.8479 9.13628 35.1455 8.77847 35.392C8.18043 35.8028 7.49422 35.7397 7.01581 35.2657C6.95909 35.2083 6.92364 35.1304 6.87626 35.0573C7.04998 34.9516 7.14487 35.0806 7.24897 35.1317C7.72027 35.3579 8.19453 35.3842 8.65066 35.1254C8.93761 34.9619 9.21288 34.7683 9.4627 34.5535C9.75445 34.3052 10.0132 34.0161 10.2893 33.7496C10.7071 33.3484 11.1377 32.9665 11.6981 32.7726C11.736 32.7596 11.7593 32.709 11.7992 32.6658C11.504 32.4593 11.1895 32.4019 10.8715 32.3666C10.421 32.3173 9.98686 32.2132 9.58059 32.0084C9.17698 31.806 8.76651 31.8067 8.34678 31.9338C7.82561 32.0917 7.35437 32.3425 6.9442 32.7061C6.62332 32.99 6.26304 33.208 5.85402 33.3361C5.35459 33.4925 4.91738 33.3671 4.54769 33.0046C4.46493 32.9244 4.41398 32.8112 4.34803 32.7124C4.36841 32.6941 4.38729 32.6764 4.40767 32.6581C4.50372 32.7106 4.60217 32.7604 4.69641 32.8171C5.11307 33.0662 5.54508 33.09 5.98694 32.9093C6.141 32.8459 6.29479 32.7774 6.43502 32.6917C6.8698 32.4222 7.29724 32.1383 7.73201 31.8689C7.8884 31.7717 8.05861 31.6968 8.27853 31.5818C8.12952 31.5257 8.05184 31.4851 7.96922 31.4671C7.34458 31.3283 6.7178 31.1972 6.09167 31.0589C5.71753 30.9764 5.36392 31.0172 5.00305 31.1542C4.04879 31.5153 4.0447 31.5048 3.10704 31.149C3.09757 31.1423 3.08809 31.1356 3.07803 31.1274C3.08841 31.132 3.09938 31.1381 3.10977 31.1427C3.22323 31.4166 3.31938 31.6989 3.45407 31.9611C3.70202 32.4436 3.98522 32.9107 4.44667 33.2219C4.86606 33.5046 5.22906 33.8456 5.56831 34.2182C6.45672 35.1981 7.51961 35.9286 8.75652 36.3909C9.43004 36.6421 10.1196 36.8507 10.8517 36.8372C10.9103 36.842 10.9683 36.8453 11.0269 36.8502C11.0625 36.8622 11.0987 36.8845 11.1347 36.8843C11.9925 36.8892 12.8491 36.8911 13.7081 36.8903C13.7528 36.8902 13.8346 36.8618 13.8362 36.8439C13.8506 36.6292 13.9983 36.6909 14.1176 36.7015C14.457 36.7302 14.7476 36.6067 15.0039 36.3998C15.153 36.2795 15.2885 36.1421 15.422 36.0037C15.7067 35.7062 15.9975 35.4202 16.376 35.24C16.4052 35.2269 16.4187 35.1819 16.4508 35.1366C16.4111 35.0743 16.385 34.9894 16.3278 34.9529C15.9053 34.6887 15.4895 34.4063 15.0443 34.1855C14.7445 34.0378 14.41 34.1057 14.1247 34.2824C13.9403 34.3957 13.7592 34.5267 13.6125 34.684C13.2795 35.0383 12.9625 35.4072 12.6528 35.7818C12.2197 36.3116 11.7266 36.7403 11.0268 36.8589ZM3.11996 26.0866L3.12269 26.0804C3.21388 26.1866 3.29547 26.3035 3.39957 26.3943C3.63264 26.5957 3.86687 26.8001 4.11888 26.9751C4.72214 27.3902 5.13617 27.955 5.42419 28.6155C5.84158 29.573 6.55292 30.1863 7.52309 30.5329C8.24833 30.7933 8.96086 31.0829 9.62674 31.4823C10.3963 31.9449 11.2319 32.14 12.131 32.0787C12.6599 32.0422 13.1296 31.9112 13.5303 31.5409C13.8749 31.2253 14.2869 31.0165 14.7613 30.9546C14.8071 30.9489 14.8514 30.9213 14.9171 30.8957C14.8768 30.8319 14.8584 30.7803 14.8235 30.7524C14.2937 30.345 13.778 29.9166 13.2242 29.5445C12.8474 29.2919 12.4452 29.018 11.9389 29.1875C11.9269 29.1921 11.901 29.1607 11.8592 29.1286C11.9328 29.0395 12.0055 28.9524 12.0968 28.8426C11.902 28.7351 11.7385 28.6329 11.5655 28.555C10.992 28.296 10.4071 28.0604 9.84242 27.7842C9.25488 27.4978 8.72845 27.5627 8.23373 27.9696C8.00584 28.1568 7.7871 28.3543 7.5542 28.5331C6.9504 28.9997 6.08403 28.9463 5.54741 28.4154C5.50516 28.3731 5.49288 28.3018 5.43018 28.1672C5.5947 28.2587 5.68186 28.306 5.76811 28.3554C6.05861 28.5189 6.36447 28.5762 6.69556 28.5216C7.11368 28.4522 7.46832 28.2727 7.77381 27.9757C7.96569 27.7887 8.17912 27.6261 8.3843 27.4512C8.4475 27.3972 8.51187 27.3463 8.59123 27.2808C8.52017 27.2307 8.48291 27.1968 8.43962 27.1739C7.65479 26.7603 6.85756 26.3724 6.0905 25.9294C5.57123 25.6286 5.09736 25.6298 4.61457 25.9525C4.13924 26.2724 3.64448 26.3215 3.11996 26.0866ZM37.62 22.5224C37.8879 22.4025 38.1561 22.2791 38.4278 22.1647C39.228 21.8273 40.0111 21.9581 40.778 22.2905C41.4806 22.5943 42.1783 22.563 42.8718 22.2827C43.5414 22.0117 44.0816 21.5715 44.5068 20.986C44.5832 20.882 44.6222 20.7216 44.8415 20.7244C44.8202 20.8243 44.8261 20.9188 44.7825 20.979C44.5492 21.298 44.3447 21.6558 44.0523 21.9114C43.2123 22.641 42.2459 22.9619 41.1332 22.6068C40.8392 22.5138 40.5467 22.4203 40.2558 22.3175C39.9333 22.2044 39.6059 22.1711 39.2712 22.2254C38.2461 22.391 37.367 22.8525 36.7092 23.6529C36.2392 24.2248 35.8493 24.8657 35.4269 25.476C35.4169 25.4902 35.4307 25.5212 35.4389 25.582C35.529 25.5088 35.6071 25.4491 35.682 25.3853C36.5833 24.6232 37.5957 24.3276 38.7583 24.6564C38.9436 24.7087 39.128 24.7717 39.3177 24.7999C39.6709 24.8508 40.0309 24.9233 40.3822 24.9075C41.2832 24.8645 42.0692 24.5171 42.7366 23.9047C42.8112 23.8359 42.8982 23.7813 42.9808 23.7198C43.0039 23.7436 43.0275 23.769 43.049 23.7935C42.9496 23.9929 42.7904 24.1534 42.6212 24.2971C41.6618 25.1129 40.566 25.3355 39.349 25.0349C38.9877 24.9456 38.6225 24.8596 38.2555 24.8262C37.1391 24.7266 36.1746 25.0657 35.439 25.9311C34.8355 26.6413 34.4154 27.465 34.0729 28.3294C34.0581 28.3663 34.0661 28.4134 34.0618 28.5084C34.1811 28.3997 34.2536 28.33 34.3288 28.2627C34.4049 28.1933 34.479 28.123 34.5563 28.0566C35.4836 27.2688 36.5303 26.889 37.7593 27.128C37.9602 27.1673 38.1648 27.1896 38.367 27.2233C38.9943 27.3248 39.6164 27.316 40.2366 27.1696C40.7024 27.0592 41.1344 26.8755 41.5446 26.6312C41.6505 26.5675 41.7505 26.4404 41.9794 26.5207C41.8186 26.6594 41.7073 26.7753 41.5768 26.8641C40.7865 27.4033 39.9117 27.6418 38.958 27.5671C38.5239 27.5338 38.0891 27.4853 37.6577 27.4233C36.6057 27.2728 35.6876 27.5765 34.8449 28.1932C34.1039 28.7357 33.6767 29.4706 33.4814 30.3555C33.4596 30.4539 33.4016 30.5698 33.5068 30.6723C33.6969 30.4894 33.8628 30.3108 34.0482 30.1557C34.6564 29.6475 35.3814 29.5849 36.123 29.6886C37.4114 29.8681 38.5593 29.5544 39.6037 28.8022C39.6653 28.7575 39.745 28.7368 39.8154 28.7059C39.7889 28.8321 39.7347 28.9137 39.6646 28.9807C39.1415 29.4781 38.5278 29.8 37.8206 29.9525C37.2706 30.0715 36.7233 30.0167 36.1758 29.948C35.7488 29.893 35.3305 29.9002 34.9183 30.0157C34.1971 30.2204 33.2868 30.9152 33.2903 32.0235C33.292 32.4342 33.3181 32.8458 33.3407 33.257C33.346 33.35 33.3846 33.4404 33.4083 33.5366C33.4489 33.5173 33.4656 33.516 33.4707 33.5071C33.5165 33.4305 33.5638 33.3533 33.6055 33.2749C34.2409 32.077 35.2155 31.2914 36.5144 30.9328C37.34 30.7048 38.0996 30.3469 38.8073 29.8779C40.3154 28.8778 41.4616 27.5173 42.5256 26.0782C42.7003 25.8426 42.8747 25.6019 43.0775 25.3898C43.3849 25.0714 43.6088 24.706 43.8084 24.3137C43.9932 23.9497 44.1826 23.5752 44.4365 23.2604C44.936 22.6407 45.1973 21.9652 45.1404 21.1612C45.1103 20.7218 45.1689 20.2893 45.3318 19.8733C45.3821 19.7466 45.3987 19.5949 45.3917 19.4577C45.3471 18.6367 45.3151 17.8126 45.2256 16.9954C45.1908 16.6719 45.044 16.3522 44.9013 16.0517C44.7284 15.6869 44.4935 15.6003 44.1085 15.7017C43.9979 15.731 43.8889 15.7734 43.7876 15.8266C43.1969 16.1326 42.6089 16.441 42.0217 16.756C41.5707 16.9972 41.3864 17.4509 41.5162 17.9742C42.8514 16.936 43.5011 16.5431 43.9031 16.5958C43.7783 16.6945 43.7027 16.7654 43.6157 16.82C43.2464 17.0502 42.8721 17.2719 42.5034 17.5036C42.4385 17.5444 42.3919 17.6144 42.3166 17.6903C42.6167 17.7239 42.8702 17.7791 43.1232 17.7757C43.3741 17.7713 43.6264 17.7129 43.8758 17.6694C44.1128 17.629 44.2827 17.39 44.5942 17.4088C44.363 17.7995 44.0297 17.95 43.6579 18.0014C43.3299 18.0461 42.9941 18.0489 42.6628 18.0499C42.3193 18.0505 41.9748 18.1016 41.7202 18.3217C41.2493 18.728 40.8167 19.1798 40.3512 19.6307C41.0145 19.7233 41.616 19.8246 42.2218 19.8843C42.4845 19.91 42.758 19.8709 43.022 19.8338C43.4648 19.7704 43.8408 19.5531 44.1904 19.2857C44.2832 19.215 44.3627 19.0925 44.5478 19.1794C44.4951 19.2691 44.4653 19.3516 44.4083 19.4083C44.065 19.7494 43.6588 19.9818 43.185 20.0936C42.6325 20.224 42.0922 20.1473 41.5478 20.0291C40.6328 19.8287 39.8511 20.0811 39.2023 20.7502C38.9348 21.0254 38.6557 21.2931 38.4015 21.5804C38.1304 21.8864 37.8828 22.2127 37.6244 22.5293C37.6146 22.5348 37.6015 22.5365 37.5928 22.5451C37.5865 22.551 37.5855 22.5617 37.5825 22.5715C37.5957 22.5526 37.6071 22.5378 37.62 22.5224ZM27.6378 31.2161C27.6518 31.1416 27.6738 31.0656 27.68 30.9889C27.7568 29.813 28.0179 28.6778 28.3706 27.5571C28.6565 26.649 28.8532 25.7151 28.935 24.7638C28.9944 24.0908 29.1418 23.4406 29.3875 22.8178C29.766 21.8563 29.8765 20.8817 29.6232 19.8689C29.3676 18.8501 29.4726 17.8569 29.8165 16.8727C29.9761 16.413 30.1091 15.9378 30.1948 15.4602C30.4663 13.9545 30.6989 12.4415 30.972 10.9352C31.0744 10.3682 31.2196 9.80522 31.3904 9.2548C31.5133 8.8509 31.7146 8.47179 31.869 8.07811C32.1833 7.27825 32.2965 6.4564 32.013 5.62648C31.78 4.93941 31.6321 4.24163 31.5476 3.52096C31.4734 2.8844 31.2088 2.30636 30.7776 1.82089C30.2359 1.21073 29.5432 1.13119 28.8885 1.60381C28.6712 1.76097 28.4731 1.94524 28.2635 2.11324C27.7476 2.53184 27.2505 2.98113 26.7065 3.35877C26.0504 3.81464 25.5307 4.37816 25.1111 5.05309C24.765 5.6078 24.4112 6.16034 24.0325 6.69316C23.1594 7.92489 22.8086 9.27996 23.0335 10.7808C23.1434 11.5089 23.1853 12.2393 23.1722 12.9738C23.1602 13.6629 23.2821 14.3293 23.5444 14.9722C23.7543 15.485 23.9627 15.9985 24.1393 16.5226C24.3522 17.1536 24.6918 17.673 25.2579 18.0455C25.7011 18.3362 26.0988 18.6826 26.3216 19.1888C26.3377 19.2257 26.3771 19.2519 26.4179 19.2948C26.4368 19.2373 26.4518 19.2142 26.4496 19.1908C26.3907 17.9313 26.3512 16.6728 25.981 15.448C25.7012 14.5216 25.2583 13.7191 24.4807 13.1213C23.5141 12.3775 23.214 11.3812 23.3768 10.2099C23.3869 10.1299 23.4247 10.0547 23.4511 9.97704C23.4812 9.97917 23.5112 9.9813 23.5407 9.98193C23.5484 10.112 23.5611 10.2419 23.5601 10.3719C23.5527 11.2978 23.7805 12.1303 24.4877 12.7815C24.6485 12.9298 24.7959 13.0919 24.9567 13.2402C25.3017 13.557 25.5827 13.9213 25.7993 14.3365C25.878 14.4856 25.9656 14.6312 26.0926 14.8515C26.1038 14.695 26.1138 14.6323 26.1122 14.5707C26.0821 13.5661 26.1359 12.5652 26.2436 11.5657C26.2791 11.2287 26.2473 10.8643 26.1544 10.5374C26.0288 10.0955 25.8176 9.67645 25.6374 9.2488C25.4297 8.75061 25.1916 8.26253 25.0123 7.7533C24.7925 7.12675 24.81 6.48733 25.0239 5.8579C25.062 5.74804 25.1252 5.64564 25.1772 5.54072C25.2128 5.55278 25.247 5.56542 25.2826 5.57747C25.2555 5.69344 25.2321 5.80974 25.1994 5.92444C25.0773 6.36601 25.0422 6.81872 25.1672 7.2592C25.287 7.67749 25.4391 8.09018 25.6073 8.49138C25.8149 8.98958 26.0539 9.47557 26.281 9.96621C26.305 10.0191 26.3434 10.0647 26.4002 10.1532C26.4482 10.0602 26.4852 10.0095 26.5016 9.95465C26.757 9.06536 27.0201 8.17825 27.2601 7.2846C27.4379 6.62427 27.3951 5.96684 27.2024 5.30383C27.0927 4.9248 27.0406 4.52161 27.0194 4.12714C26.9935 3.67225 27.1787 3.27353 27.4942 2.94503C27.5356 2.90126 27.608 2.88863 27.6666 2.86239C27.6572 3.00604 27.6043 3.10438 27.5462 3.19787C27.3223 3.57194 27.1675 3.97788 27.2631 4.40905C27.368 4.88158 27.5426 5.33905 27.6907 5.80339C27.6945 5.81748 27.7352 5.82063 27.8086 5.84567C27.8715 5.7071 27.9612 5.56674 27.9996 5.41354C28.095 5.02726 28.1714 4.63629 28.2493 4.24473C28.39 3.53317 28.6345 2.85896 28.978 2.22232C29.0341 2.11924 29.0643 1.97611 29.2379 1.96731C29.3185 2.1347 29.2102 2.24945 29.1543 2.36628C28.8367 3.02054 28.6426 3.70968 28.5664 4.43242C28.5549 4.5354 28.4944 4.66265 28.6293 4.73978C29.0276 4.45167 29.4276 4.17672 29.8123 3.88008C30.323 3.48773 30.6668 2.99784 30.6361 2.30976C30.6335 2.25892 30.6714 2.20615 30.723 2.07373C30.7642 2.21497 30.7909 2.27026 30.7964 2.32861C30.8474 2.83938 30.7317 3.3148 30.3955 3.69627C30.093 4.04046 29.7575 4.36635 29.3979 4.64803C28.9423 5.00514 28.5677 5.42055 28.3436 5.94854C27.8925 7.01078 27.467 8.08555 27.0373 9.15848C26.9891 9.2775 26.9316 9.41224 27.0109 9.59396C27.1126 9.48871 27.195 9.41342 27.2673 9.32995C27.6775 8.84709 28.1546 8.4436 28.6719 8.08151C29.0178 7.83972 29.3596 7.58743 29.7137 7.358C30.5622 6.80477 31.1124 6.05479 31.2833 5.0411C31.2949 4.9692 31.3504 4.90437 31.384 4.83601C31.4131 4.84022 31.4443 4.84536 31.4735 4.84957C31.4808 4.98326 31.506 5.11864 31.4934 5.24971C31.4562 5.65308 31.321 6.02546 31.1015 6.3667C30.8275 6.79311 30.4873 7.15541 30.0815 7.4551C29.7319 7.71388 29.377 7.96781 29.0254 8.22567C28.4777 8.62897 27.9472 9.04979 27.4966 9.56567C26.9664 10.173 26.6135 10.8514 26.5904 11.6796C26.5809 12.0394 26.547 12.3983 26.5289 12.7579C26.5246 12.8529 26.5412 12.9484 26.5475 13.0531C26.6043 13.031 26.632 13.0272 26.6484 13.0121C26.6847 12.9773 26.7198 12.9394 26.7496 12.8967C27.1197 12.3551 27.6233 11.9621 28.1652 11.6146C28.542 11.3729 28.9309 11.1489 29.3077 10.9072C29.9229 10.5139 30.4426 10.0299 30.7403 9.34192C30.7621 9.29195 30.8123 9.25337 30.8487 9.20984C30.8751 9.2203 30.9015 9.23076 30.9264 9.2418C30.9018 9.3551 30.8875 9.473 30.851 9.58228C30.6558 10.1802 30.2628 10.6322 29.7593 10.9855C29.3302 11.2873 28.8699 11.5442 28.4415 11.8476C28.0345 12.1356 27.6163 12.4211 27.2684 12.7725C26.7155 13.33 26.5238 14.0562 26.549 14.8276C26.5819 15.8571 26.6497 16.8833 26.7064 17.9121C26.7098 17.9782 26.7536 18.0423 26.7928 18.1429C27.1801 17.6897 27.6436 17.3969 28.1027 17.0972C28.3575 16.9307 28.611 16.7473 28.8216 16.5288C29.0504 16.2911 29.2276 16.0044 29.4286 15.7394C29.4843 15.6659 29.5155 15.5431 29.6502 15.6065C29.6574 15.6383 29.673 15.6651 29.6675 15.6862C29.6558 15.7357 29.637 15.7845 29.6149 15.8294C29.39 16.3024 29.0772 16.7041 28.6496 17.0054C28.3567 17.211 28.0552 17.4078 27.7464 17.5903C27.0952 17.9751 26.7403 18.5557 26.7203 19.2946C26.6875 20.4378 26.7141 21.5837 26.7194 22.7276C26.7197 22.8035 26.7632 22.8799 26.8042 23.0161C27.1991 22.6221 27.5479 22.2686 27.9005 21.9205C28.522 21.3052 28.9301 20.5829 29.0105 19.6943C29.0169 19.6227 29.0698 19.5554 29.1007 19.4846C29.1812 19.5812 29.2083 19.664 29.2122 19.7489C29.2392 20.4056 29.0517 20.997 28.6387 21.5035C28.4201 21.7718 28.1774 22.0183 27.944 22.2751C27.7201 22.5213 27.48 22.7565 27.273 23.0151C26.9497 23.4209 26.788 23.8797 26.8519 24.4148C26.899 24.8096 26.9038 25.2104 26.9333 25.6086C26.9397 25.7046 26.9658 25.7981 26.9855 25.9149C27.2423 25.6871 27.4558 25.4674 27.6982 25.2866C28.1044 24.9834 28.3757 24.5943 28.5308 24.1139C28.5597 24.0249 28.5985 23.9389 28.6321 23.8532C28.7707 24.2798 28.6717 24.6571 28.4149 24.9731C28.2326 25.1979 28.0037 25.3959 27.7656 25.5612C27.2902 25.8897 27.0432 26.328 27.0857 26.9009C27.1486 27.7337 27.2317 28.5655 27.328 29.3957C27.3904 29.9314 27.4892 30.4634 27.5743 30.9954C27.5868 31.0718 27.6119 31.145 27.6325 31.22C27.6282 31.2355 27.6245 31.2524 27.6245 31.2524C27.634 31.2505 27.6362 31.234 27.6378 31.2161ZM25.0934 28.5336C25.2757 28.1896 25.4185 27.9075 25.5703 27.6307C25.735 27.3298 25.802 27.003 25.798 26.6658C25.794 26.351 25.7612 26.0371 25.7408 25.6976C25.8454 25.7191 25.909 25.7324 25.9946 25.7492C25.933 25.507 25.8749 25.2825 25.8182 25.0574C25.5767 24.097 25.3567 23.1301 25.0872 22.1772C24.9173 21.5727 24.7331 20.9582 24.4494 20.4015C23.8608 19.2426 23.2293 18.1057 22.5627 16.9893C22.1564 16.3075 21.7179 15.6226 21.1799 15.0438C20.4856 14.2978 19.8095 13.5498 19.2497 12.6943C18.8049 12.0153 18.2153 11.4809 17.4957 11.1024C17.161 10.9268 16.8781 10.6947 16.6161 10.4233C16.1946 9.98934 15.7638 9.55379 15.2076 9.29496C14.5713 8.99817 14.0081 8.61073 13.5063 8.1164C13.1018 7.7173 12.588 7.56296 12.0228 7.59455C11.3483 7.63237 10.9713 8.09886 11.0804 8.76332C11.1098 8.94029 11.1588 9.1148 11.1953 9.29245C11.3363 9.98596 11.4833 10.6771 11.6142 11.3711C11.7549 12.1167 11.8544 12.8713 12.0201 13.6105C12.2261 14.5328 12.524 15.4262 13.1385 16.1705C13.851 17.0339 14.2495 18.049 14.5683 19.102C14.7813 19.8037 15.1228 20.4296 15.5731 20.9993C15.9084 21.4236 16.2563 21.8361 16.5907 22.2625C17.3085 23.1792 18.0931 24.0249 19.0414 24.7084C19.259 24.8657 19.4676 25.0438 19.6483 25.2431C20.5539 26.2318 21.518 27.1546 22.5421 28.0195C22.9462 28.36 23.2803 28.7813 23.5045 29.2644C24.0354 30.4077 24.7539 31.4191 25.569 32.374C25.8588 32.7123 26.0737 33.1143 26.3251 33.4866C26.3575 33.5345 26.3947 33.5771 26.4301 33.6238C26.3479 33.2669 26.2313 32.932 26.0893 32.607C25.8267 32.0075 25.4468 31.5038 24.9091 31.1115C24.6545 30.9254 24.4535 30.6649 24.2334 30.4308C24.1921 30.3864 24.1837 30.3119 24.1603 30.2519C24.415 30.3895 24.6056 30.5746 24.8134 30.7374C25.0143 30.896 25.2191 31.06 25.4969 31.1247C25.137 30.2485 24.7997 29.3998 24.4407 28.5612C24.2625 28.1432 23.9262 27.8973 23.4813 27.8008C23.1812 27.7362 22.8747 27.6861 22.5812 27.5946C22.0687 27.4346 21.6745 27.1196 21.4538 26.6144C21.4292 26.56 21.4428 26.489 21.4406 26.4259C21.5681 26.4973 21.6356 26.5868 21.7016 26.677C21.8893 26.934 22.1271 27.1388 22.4295 27.2268C22.8967 27.3629 23.3722 27.463 23.8452 27.5745C23.8601 27.5773 23.8823 27.5462 23.9276 27.5079C23.8814 27.3893 23.8431 27.2555 23.78 27.1332C23.3686 26.3323 22.9551 25.5305 22.5339 24.7352C22.407 24.4977 22.2725 24.2579 22.1041 24.0504C21.8197 23.6996 21.4454 23.5238 20.9816 23.6041C20.8433 23.6285 20.7047 23.6565 20.5679 23.6891C19.7183 23.8953 18.9144 23.764 18.1471 23.3557C17.8827 23.2149 17.6453 23.0377 17.499 22.768C17.4558 22.688 17.3887 22.5862 17.5341 22.4916C17.6029 22.5668 17.6657 22.6443 17.7387 22.7127C18.3038 23.255 18.9874 23.5541 19.7559 23.5281C20.3611 23.5068 20.9615 23.3492 21.5986 23.2464C21.5606 23.1488 21.5379 23.0505 21.489 22.9693C21.1897 22.4739 20.8897 21.9771 20.5781 21.49C20.4331 21.263 20.2808 21.0353 20.0968 20.8408C19.3192 20.0217 18.4086 19.5015 17.2336 19.6046C17.0558 19.6202 16.8757 19.6211 16.6954 19.617C15.655 19.5933 14.7507 18.8685 14.5092 17.8684C14.4815 17.753 14.4155 17.6231 14.5996 17.5221C14.6409 17.6149 14.6873 17.6902 14.7082 17.7702C14.9113 18.5657 15.4352 19.0376 16.2142 19.1976C16.5988 19.2761 17.0036 19.2741 17.3974 19.266C18.0854 19.254 18.7185 19.4103 19.2953 19.7925C19.374 19.8448 19.4628 19.8828 19.5452 19.9268C19.5647 19.9106 19.5856 19.8938 19.6051 19.8776C19.5454 19.7418 19.4916 19.6037 19.425 19.4724C19.3206 19.2658 19.2072 19.0628 19.0959 18.8607C18.6107 17.9675 18.1241 17.075 17.639 16.1818C17.35 15.6513 16.9164 15.3188 16.3185 15.218C15.9136 15.1491 15.5075 15.0946 15.1038 15.0201C14.6627 14.9378 14.2194 14.8631 13.7884 14.7405C13.1974 14.573 12.7414 14.2008 12.4149 13.6798C12.311 13.5145 12.2484 13.3228 12.1524 13.1113C12.2394 13.1276 12.2737 13.1229 12.2846 13.1376C12.3587 13.2263 12.4288 13.3183 12.5005 13.4097C13.0504 14.1203 13.7634 14.5878 14.6436 14.743C15.3538 14.8675 16.0746 14.9223 16.8097 15.0095C16.7467 14.9182 16.6918 14.8169 16.6195 14.7327C15.7671 13.7526 14.9102 12.7742 14.0554 11.7968C13.739 11.4343 13.3737 11.1979 12.8655 11.1814C12.2438 11.1607 11.8742 10.7497 11.6185 10.2253C11.5795 10.1471 11.588 10.0453 11.5747 9.95368C11.6001 9.9438 11.6239 9.93451 11.6493 9.92463C11.8682 10.1955 12.0519 10.5042 12.3128 10.7242C12.5823 10.9529 12.9395 11.0316 13.3721 10.9773C13.2599 10.817 13.1808 10.7199 13.1185 10.6128C12.8352 10.1233 12.5533 9.63325 12.279 9.14028C12.2349 9.06238 12.1717 8.95735 12.3129 8.86091C12.3686 8.92909 12.4367 8.98903 12.4766 9.0651C13.0065 10.0601 13.7396 10.9103 14.411 11.8053C14.4567 11.8653 14.5401 11.8985 14.6695 11.9881C14.6893 11.4429 14.7336 10.9694 14.7171 10.4987C14.6998 10.0215 14.4257 9.62179 14.2124 9.20184C14.4848 9.31012 14.6246 9.53228 14.7457 9.76857C14.979 10.2222 15.0115 10.7074 14.9382 11.1991C14.8527 11.7786 15.0131 12.2969 15.3204 12.7771C15.4593 12.9926 15.6179 13.1971 15.7774 13.3994C16.3988 14.1877 17.0225 14.9733 17.6492 15.7578C17.7002 15.8226 17.7668 15.8745 17.8256 15.9328C17.6895 15.3843 17.7 14.8462 17.6983 14.3076C17.698 14.0242 17.6912 13.7417 17.6691 13.4599C17.6385 13.0587 17.5431 12.6724 17.3344 12.3215C17.1112 11.9469 16.886 11.5714 16.6628 11.1967C16.6267 11.1348 16.5944 11.0695 16.5154 10.924C16.6485 10.9966 16.7088 11.0146 16.7478 11.053C17.269 11.5709 17.642 12.1759 17.8424 12.8895C18.0162 13.508 18.0163 14.1354 17.9908 14.7676C17.9593 15.561 18.1753 16.3014 18.5181 17.0011C18.8859 17.7516 19.2942 18.4828 19.6897 19.2207C19.803 19.4324 19.9301 19.6353 20.0997 19.9253C20.2404 19.5007 20.364 19.1691 20.4608 18.8307C20.5604 18.486 20.6668 18.1369 20.7096 17.7832C20.7537 17.4152 20.7556 17.0359 20.7176 16.6687C20.6806 16.3132 20.5879 15.9604 20.4836 15.6173C20.3828 15.2832 20.2366 14.965 20.1098 14.6393C20.1335 14.6249 20.1577 14.6121 20.1813 14.5977C20.238 14.6551 20.3055 14.7049 20.3464 14.7702C20.7185 15.3686 20.9468 16.0212 21.0479 16.7182C21.1552 17.4577 21.0967 18.177 20.8277 18.8814C20.4638 19.832 20.5571 20.7428 21.0975 21.6145C21.6743 22.5446 22.2329 23.4852 22.7999 24.4208C22.8675 24.5328 22.9474 24.6365 23.0193 24.7416C23.2077 24.2984 23.375 23.898 23.5464 23.4994C23.6375 23.2876 23.7447 23.0817 23.8338 22.869C24.0922 22.2568 24.1463 21.6187 23.9715 20.9798C23.8388 20.4974 23.6425 20.0328 23.4787 19.559C23.4329 19.4282 23.333 19.2994 23.4036 19.0835C23.7599 19.5221 23.9895 19.9617 24.1538 20.437C24.563 21.6207 24.3994 22.737 23.8006 23.817C23.3904 24.5557 23.3975 25.3203 23.7846 26.0719C24.0839 26.6554 24.408 27.2275 24.7186 27.8049C24.8394 28.0224 24.9499 28.249 25.0934 28.5336ZM39.1024 3.6259C39.1383 3.63437 39.1764 3.64377 39.2123 3.65224C39.2064 3.77382 39.2132 3.89734 39.1903 4.01514C39.0604 4.71905 38.7006 5.2739 38.1062 5.67637C37.7364 5.92745 37.3248 6.05312 36.8897 6.11875C36.4058 6.1913 35.937 6.31155 35.491 6.52142C34.9217 6.78967 34.5005 7.20426 34.2729 7.79408C34.069 8.32111 33.8838 8.85642 33.6938 9.38838C33.685 9.41428 33.7082 9.45191 33.7169 9.48309C33.7542 9.47723 33.7833 9.48145 33.8025 9.46881C33.856 9.43415 33.9063 9.39556 33.9554 9.35397C34.363 9.01037 34.8164 8.75784 35.3345 8.61843C36.0142 8.4351 36.6968 8.25929 37.3698 8.05437C38.1288 7.82292 38.7198 7.38545 38.9959 6.60219C39.0229 6.52598 39.0717 6.45689 39.1097 6.38678C39.1664 6.48396 39.1789 6.56899 39.1652 6.64864C39.0877 7.0677 38.8783 7.41712 38.5708 7.70447C38.1509 8.09606 37.6616 8.37119 37.1051 8.51346C36.758 8.6019 36.4085 8.68434 36.0548 8.74252C35.0418 8.90863 34.1935 9.35636 33.5278 10.1496C33.1485 10.6014 32.9557 11.1483 32.712 11.6701C32.6796 11.7414 32.6665 11.8226 32.6463 11.8944C32.9592 11.6914 33.2474 11.4824 33.5573 11.3117C34.0803 11.0217 34.6573 11.0028 35.2394 11.0234C36.5921 11.0724 37.6902 10.5863 38.4783 9.45848C38.5214 9.3968 38.5981 9.36001 38.6595 9.31019C38.6826 9.32539 38.7072 9.34002 38.7303 9.35522C38.6892 9.48358 38.662 9.61687 38.6064 9.73879C38.4015 10.1884 38.0501 10.4998 37.6393 10.7513C37.0454 11.1155 36.3988 11.2911 35.7061 11.3084C35.2702 11.319 34.8339 11.3108 34.4017 11.3529C33.6171 11.4301 32.9828 11.8049 32.5659 12.4736C32.3017 12.8944 32.0897 13.352 31.8976 13.8123C31.7688 14.1216 31.7163 14.4636 31.629 14.7914C31.7387 14.7729 31.7828 14.7315 31.8188 14.6829C32.5489 13.6884 33.5274 13.3058 34.7427 13.4654C35.0324 13.503 35.3336 13.5085 35.6237 13.4768C36.4042 13.389 37.0613 13.0417 37.6019 12.47C37.6799 12.3878 37.7351 12.2471 37.9326 12.3085C37.8797 12.4155 37.8475 12.5093 37.7921 12.5878C37.4817 13.0267 37.0819 13.3551 36.5871 13.5719C36.1036 13.7826 35.598 13.8083 35.0796 13.7922C34.6059 13.7761 34.1307 13.7606 33.6602 13.7882C33.215 13.8146 32.8163 13.9957 32.4828 14.3001C31.8511 14.8761 31.4945 15.6025 31.3571 16.4372C31.2686 16.9695 31.2042 17.5061 31.1306 18.0412C31.1224 18.0997 31.1256 18.1607 31.1245 18.2285C31.4244 18.0012 31.6823 17.7452 31.9918 17.5867C32.3408 17.406 32.7367 17.3193 33.1077 17.1818C33.5862 17.0025 34.0775 16.8475 34.5332 16.6183C35.162 16.3044 35.6508 15.8117 36.051 15.2325C36.1157 15.1382 36.1575 14.994 36.3697 15.0358C36.3195 15.185 36.2873 15.3185 36.2307 15.4425C36.0177 15.9109 35.6748 16.2707 35.2675 16.571C34.6591 17.017 33.9681 17.2773 33.248 17.4849C32.8185 17.6089 32.3965 17.7611 31.983 17.9307C31.6391 18.0714 31.402 18.3366 31.2518 18.6837C31.0274 19.1979 30.9128 19.7334 30.8839 20.2908C30.8797 20.3858 30.8891 20.4807 30.8931 20.6191C31.0843 20.4081 31.2244 20.2205 31.3966 20.0757C31.5805 19.9212 31.7837 19.7678 32.004 19.6803C32.3596 19.5384 32.7307 19.432 33.1048 19.3469C34.1472 19.1106 34.9957 18.5971 35.6148 17.7062C36.0138 17.1327 36.3418 16.5228 36.5898 15.8749C36.8638 15.1615 37.2312 14.5069 37.6383 13.8662C37.9337 13.4021 38.2182 12.9232 38.4345 12.419C38.9197 11.2899 39.1657 10.0897 39.2926 8.87019C39.3596 8.22536 39.488 7.60154 39.6762 6.98556C39.7292 6.81281 39.7758 6.64088 39.8211 6.46594C40.0308 5.63591 39.9336 4.8078 39.8255 3.97359C39.6825 2.8643 39.42 1.8015 38.8157 0.840639C38.5318 0.389408 38.1594 0.192127 37.6499 0.309222C37.3645 0.375345 37.0793 0.463886 36.8153 0.58913C36.3308 0.819187 35.8624 1.08619 35.3747 1.34341C35.4707 1.57224 35.3126 1.65624 35.1839 1.7582C34.6521 2.18469 34.3946 2.74638 34.4906 3.42115C34.5749 4.01748 34.7337 4.6021 34.8624 5.19325C34.8661 5.20734 34.903 5.21374 34.93 5.2257C35.3366 4.70275 35.7441 4.17772 36.1521 3.65419C36.8321 2.78284 37.4849 1.89444 37.8912 0.849639C37.9154 0.788342 37.9744 0.741184 38.0336 0.668027C38.0664 0.73475 38.1007 0.769807 38.0945 0.798132C37.8919 1.92444 37.1309 2.75124 36.5516 3.69576C36.8476 3.63065 37.1292 3.55044 37.3888 3.42694C37.6528 3.3017 37.9309 3.17273 38.138 2.9763C38.3538 2.77131 38.5282 2.4995 38.6537 2.22594C38.7693 1.97528 38.7955 1.68506 38.8612 1.41232C38.9422 1.48796 38.9718 1.55942 38.979 1.63094C39.0506 2.36701 38.6231 3.15393 37.9575 3.4752C37.6699 3.61482 37.3617 3.71058 37.0687 3.83669C36.8344 3.93656 36.5905 4.02976 36.3793 4.16725C35.5152 4.73346 35.0241 5.57795 34.6826 6.52844C34.6777 6.54243 34.7049 6.56814 34.7361 6.6217C35.2533 6.18877 35.8679 5.99276 36.5187 5.88981C36.6838 5.86357 36.8472 5.83284 37.0102 5.79702C37.7821 5.62968 38.3671 5.21186 38.7153 4.49039C38.8093 4.29478 38.885 4.08732 38.9722 3.88745C39.0118 3.79942 39.0592 3.71358 39.1024 3.6259ZM5.61697 23.1806C5.6049 23.2026 5.59341 23.2261 5.58135 23.2481C5.75095 23.4983 5.92503 23.7469 6.08775 24.0016C6.4082 24.5025 6.83851 24.8795 7.35764 25.1579C7.52723 25.2492 7.6959 25.3426 7.87061 25.425C8.635 25.786 9.29427 26.2743 9.87964 26.8951C10.2633 27.3023 10.7157 27.6655 11.1934 27.9566C12.0592 28.4856 12.9591 28.9563 13.8575 29.4276C14.393 29.7083 14.953 29.9415 15.5596 30.0165C16.251 30.1017 16.8658 30.374 17.4419 30.7547C18.4564 31.4228 19.3523 32.2322 20.2158 33.0818C20.2912 33.1561 20.3737 33.2225 20.4524 33.2922C20.1847 32.6618 19.8738 32.0707 19.5699 31.4751C19.4035 31.1493 19.1473 31.0122 18.7846 31.0428C18.5951 31.0595 18.3977 31.0689 18.2098 31.0366C17.9283 30.9889 17.6825 30.865 17.5784 30.527C17.8444 30.6275 18.0717 30.7568 18.3131 30.7941C18.5546 30.8315 18.8121 30.778 19.1233 30.7605C18.8699 30.2905 18.6134 29.9098 18.2621 29.6076C17.7282 29.15 17.139 29.0094 16.48 29.3299C16.2849 29.4248 16.0857 29.5179 15.8789 29.5828C15.4526 29.7194 15.0044 29.5879 14.7678 29.2669C14.7274 29.2118 14.728 29.1251 14.7046 29.034C14.7789 29.0483 14.8117 29.0441 14.8261 29.0592C15.206 29.4524 15.6359 29.4354 16.0999 29.241C16.6066 29.0282 17.1162 28.8229 17.6888 28.9648C17.6853 28.9074 17.6927 28.8734 17.6794 28.8613C17.1024 28.2752 16.535 27.6785 15.9382 27.1123C15.622 26.8119 15.2101 26.7164 14.7887 26.8303C14.4699 26.9164 14.1655 27.0573 13.8598 27.1815C13.4338 27.3542 13.0165 27.5582 12.582 27.7048C12.129 27.8569 11.6933 27.7707 11.3231 27.4464C11.2683 27.3986 11.2428 27.3152 11.2043 27.2472C11.3166 27.2311 11.3873 27.2537 11.4402 27.2971C11.7929 27.5937 12.1843 27.628 12.5954 27.4611C12.8787 27.3456 13.1615 27.22 13.4273 27.0681C13.942 26.7745 14.4511 26.4795 15.0747 26.5099C15.1063 26.5114 15.1381 26.4783 15.1766 26.4581C15.1653 26.4158 15.1674 26.3683 15.1441 26.3481C14.6716 25.9114 14.2022 25.4736 13.7217 25.0471C13.4937 24.8455 13.2053 24.7624 12.9085 24.7241C12.3384 24.6504 11.787 24.7129 11.245 24.9101C10.8012 25.0724 10.3527 25.2315 9.89757 25.3516C9.39684 25.4825 8.93165 25.3559 8.529 25.0235C8.46806 24.9729 8.42995 24.8927 8.3289 24.7523C8.48478 24.8039 8.5576 24.8188 8.62256 24.8488C9.216 25.1415 9.8109 25.1157 10.4112 24.8786C10.7689 24.7376 11.1227 24.5826 11.489 24.4729C11.7799 24.3856 12.0891 24.3586 12.391 24.3085C12.4699 24.295 12.5512 24.2963 12.7069 24.2858C12.134 23.8295 11.6214 23.431 11.0337 23.1308C10.1302 22.6684 9.21501 22.653 8.27814 22.9969C8.10981 23.059 7.94524 23.1351 7.77197 23.1801C7.06093 23.3756 6.34606 23.6452 5.61697 23.1806ZM12.5148 17.2395C12.4354 17.1148 12.4158 17.0689 12.3836 17.0347C11.6531 16.2751 10.9157 15.5199 10.1915 14.7543C9.86693 14.4105 9.48013 14.269 9.01956 14.2823C8.73733 14.2902 8.45536 14.3031 8.17572 14.2824C7.4335 14.2256 6.84282 13.7192 6.66655 13.0014C6.65181 12.9414 6.67523 12.8735 6.68255 12.8085C6.70643 12.7992 6.73031 12.7899 6.7542 12.7806C6.97859 13.229 7.15354 13.7227 7.68629 13.8904C8.17985 14.0457 8.68331 14.0278 9.28612 13.9781C8.4261 13.2654 7.59666 12.6445 7.01788 11.7757C7.35055 11.8709 7.48427 12.1836 7.71552 12.3891C7.94619 12.5932 8.17354 12.802 8.41472 12.9933C8.66595 13.1928 8.9349 13.3716 9.19276 13.5616C9.4438 13.7473 9.69062 13.9399 9.98423 14.1644C9.95792 13.8981 9.92688 13.7079 9.92114 13.5166C9.9029 12.8427 9.58661 12.3833 8.97856 12.0928C8.62174 11.9223 8.29367 11.6888 7.94924 11.4927C7.71567 11.3606 7.48215 11.2199 7.23223 11.1254C6.83686 10.975 6.59994 11.0949 6.4369 11.4885C6.25174 11.9356 6.2612 12.3882 6.39384 12.8482C6.61093 13.6003 6.99922 14.2667 7.42008 14.9152C7.75442 15.4298 7.99777 15.9711 8.07299 16.5883C8.12431 17.016 8.30483 17.4003 8.56569 17.7481C8.94149 18.25 9.44551 18.5603 10.0189 18.7882C10.7466 19.0771 11.4631 19.3945 12.0884 19.884C12.3755 20.1093 12.715 20.169 13.0712 20.1306C13.541 20.0791 14.0096 20.0246 14.4776 19.9686C14.4958 19.9667 14.5104 19.9334 14.5401 19.8994C14.5227 19.837 14.5092 19.7627 14.4833 19.6916C14.2802 19.1346 13.8908 18.7037 13.5283 18.2536C13.1643 17.8042 12.6952 17.5616 12.1371 17.523C11.7964 17.5 11.4502 17.5467 11.1085 17.5915C10.8177 17.6304 10.5365 17.7381 10.2449 17.7704C9.59664 17.8447 9.01597 17.5141 8.73426 16.9272C8.67915 16.8121 8.67005 16.6739 8.63972 16.5475C8.66419 16.5397 8.68866 16.5319 8.71312 16.5241C8.75226 16.5849 8.79678 16.6419 8.82755 16.7077C9.05468 17.1897 9.44201 17.4209 9.96163 17.4312C10.1521 17.4349 10.3465 17.4266 10.5346 17.3932C11.1608 17.2843 11.7813 17.1257 12.5148 17.2395ZM20.5948 9.05444C20.6258 9.05449 20.6582 9.05396 20.6892 9.05401C20.7378 8.87433 20.788 8.69407 20.8351 8.51497C21.0609 7.65105 20.9238 6.86613 20.3635 6.15085C20.0188 5.71119 19.6608 5.29917 19.1766 5.00887C18.8891 4.83557 18.612 4.83453 18.358 5.04746C18.1936 5.18579 18.032 5.34028 17.9096 5.51584C17.7478 5.74475 17.6078 5.99454 17.4884 6.24844C17.0977 7.07284 16.8432 7.92897 17.0009 8.85968C17.0568 9.18879 17.1264 9.51775 17.1692 9.8485C17.2252 10.2882 17.4678 10.6069 17.7933 10.8777C17.9814 11.0344 18.1795 11.1768 18.3686 11.3313C18.9259 11.7919 19.4554 12.2824 19.8486 12.8951C20.2605 13.5384 20.7393 14.1282 21.2863 14.655C21.6386 14.9949 22.0467 15.2751 22.4293 15.5825C22.4615 15.4576 22.4484 15.3711 22.4196 15.2924C22.169 14.6312 21.9185 13.9699 21.6636 13.3104C21.2955 12.3561 20.6175 11.7489 19.6459 11.4426C19.2818 11.3285 18.9291 11.1598 18.5929 10.9761C18.0667 10.6883 17.724 10.2185 17.4833 9.67959C17.4133 9.52188 17.4127 9.33029 17.4006 9.15351C17.3968 9.09967 17.4612 9.04002 17.5215 8.93878C17.5601 9.03785 17.5871 9.0809 17.5936 9.12849C17.7201 9.98324 18.2206 10.5317 18.9799 10.8929C19.6461 11.2092 20.4095 11.3027 21.0098 11.7984C20.9748 11.5718 20.9222 11.3658 20.8591 11.164C20.6808 10.5869 20.5161 10.0046 20.3134 9.43534C20.1072 8.85706 19.7155 8.42015 19.1789 8.1191C19.0103 8.02574 18.844 7.92972 18.6789 7.82803C18.244 7.55831 17.9575 7.17549 17.829 6.6776C17.796 6.5487 17.7476 6.41545 17.8728 6.26473C17.9161 6.37581 17.9551 6.45396 17.9765 6.5355C18.0633 6.87332 18.2446 7.15362 18.531 7.34635C19.0049 7.66313 19.4911 7.96302 20.0508 8.31903C19.8769 7.92523 19.7635 7.59428 19.5907 7.30032C19.3643 6.9131 19.0932 6.55198 18.8408 6.1818C18.7739 6.0851 18.6451 6.00564 18.755 5.82456C18.8486 5.88838 18.9436 5.9292 19.0085 5.99898C19.2084 6.21673 19.4143 6.43216 19.5834 6.67228C19.9781 7.23594 20.2402 7.86506 20.4288 8.52623C20.4748 8.7019 20.5375 8.87626 20.5948 9.05444ZM8.7342 39.2964C8.78047 39.2784 8.82382 39.2529 8.8721 39.2445C9.40404 39.1584 9.77125 38.8478 10.0519 38.4033C10.2697 38.0575 10.512 37.7264 10.7408 37.3867C10.7507 37.3725 10.7343 37.3391 10.7274 37.2951C10.655 37.268 10.5738 37.2271 10.4891 37.2082C9.86119 37.0654 9.32316 37.2506 8.86017 37.6728C8.66239 37.8535 8.49706 38.0734 8.29486 38.2471C8.10285 38.4118 7.88839 38.554 7.66957 38.6807C7.55569 38.7457 7.40903 38.7752 7.28156 38.664C7.57091 38.4581 7.86538 38.283 8.11677 38.0589C8.36964 37.8343 8.57942 37.5608 8.86512 37.2439C7.94503 37.3307 7.20072 37.7189 6.40726 37.95C6.606 37.5995 7.00264 37.5368 7.26615 37.2821C6.81901 37.2505 6.40874 37.3047 6.1298 37.714C5.99679 37.911 6.00102 38.0632 6.15809 38.2371C6.23546 38.3211 6.3356 38.3841 6.42465 38.4583C6.63324 38.6277 6.85442 38.7853 7.04803 38.9692C7.33062 39.236 7.65817 39.3799 8.03567 39.449C8.52643 39.5397 9.01563 39.6397 9.49899 39.7644C10.0014 39.8938 10.4865 39.9038 10.9623 39.6823C11.4688 39.4471 12.0054 39.3333 12.5601 39.3145C13.1198 39.2954 13.6335 39.1006 14.1643 38.9234C14.0939 38.8263 14.0353 38.742 13.9304 38.5961C14.8541 38.629 15.2612 38.0367 15.68 37.3465C15.1048 37.3215 14.583 37.2481 14.0781 37.4169C13.877 37.4831 13.6779 37.5986 13.5197 37.7397C13.3007 37.9321 13.1242 38.1719 12.9247 38.3878C12.7516 38.5745 12.5861 38.772 12.392 38.9357C12.1707 39.1221 11.8974 39.206 11.6067 39.1964C11.4638 39.1915 11.3056 39.1822 11.2268 38.9623C11.3791 38.9428 11.5033 38.9307 11.6246 38.9112C12.057 38.8431 12.4217 38.6631 12.6982 38.3049C12.9476 37.9831 13.2261 37.6829 13.4876 37.3702C13.4981 37.3575 13.4832 37.3235 13.4785 37.2804C12.7955 37.1418 12.1047 37.1774 11.4257 37.3051C11.2221 37.3429 11.0184 37.5172 10.869 37.6808C10.6826 37.8864 10.5601 38.1502 10.3947 38.3787C10.2161 38.6263 10.0433 38.8888 9.82566 39.098C9.5286 39.3813 9.16072 39.5003 8.7342 39.2964ZM24.0449 33.5099C24.0237 33.6806 24.0022 33.7754 24 33.8713C23.991 34.3294 24.1017 34.7686 24.2618 35.1885C24.467 35.7291 24.72 36.2511 24.9387 36.7865C25.6115 38.4311 26.2738 40.0797 26.9481 41.7237C27.4466 42.9384 27.9293 44.1609 28.473 45.3545C28.8663 46.2194 29.3445 47.0461 29.7994 47.8837C29.9192 48.1032 30.089 48.2964 30.236 48.5019C30.2857 48.3736 30.2817 48.275 30.2556 48.1814C29.5984 45.8394 28.9531 43.4927 28.0692 41.2217C27.4844 39.7192 26.8129 38.259 25.9751 36.8792C25.4751 36.054 24.9615 35.2376 24.4684 34.4081C24.3126 34.149 24.207 33.8599 24.0449 33.5099ZM35.8651 19.294C36.2552 19.2234 36.5394 19.1456 36.8277 19.1267C37.476 19.0835 38.0654 18.8714 38.5604 18.4696C39.4695 17.7321 40.4713 17.1399 41.4631 16.5309C41.7421 16.3601 41.9735 16.1421 42.1156 15.8448C42.5056 15.0276 42.7792 14.1762 42.8314 13.264C42.8376 13.1561 42.8187 13.0459 42.809 12.9149C42.7359 12.9434 42.6888 12.9461 42.6708 12.9704C42.2783 13.481 41.7299 13.6927 41.123 13.8114C40.7075 13.8919 40.3036 14.0111 39.9934 14.3357C39.374 14.983 38.7472 15.6245 38.1278 16.2718C38.0729 16.3295 38.0404 16.4095 37.9974 16.4799C38.3919 16.4957 38.7616 16.4918 39.1263 16.5279C40.0769 16.6211 40.8683 16.3493 41.4651 15.5778C41.5189 15.5084 41.6076 15.467 41.7049 15.3946C41.732 15.6675 41.7388 15.6717 41.6261 15.828C40.9993 16.6993 40.1703 17.1084 39.0967 16.8626C38.2968 16.6796 37.6536 16.9213 37.134 17.5159C36.832 17.8616 36.5604 18.2369 36.2877 18.6093C36.1473 18.8005 36.035 19.0153 35.8651 19.294ZM37.6743 16.2858C38.5836 15.3322 39.4575 14.4735 40.2635 13.5548C41.0773 12.6297 41.8251 11.6455 42.6001 10.6871C42.5929 10.8143 42.5495 10.928 42.4818 11.0235C41.9831 11.7379 41.479 12.4474 40.9775 13.1594C40.9047 13.2638 40.7702 13.342 40.7879 13.5598C41.2087 13.422 41.607 13.324 41.9761 13.1596C42.1885 13.0648 42.4022 12.8987 42.5331 12.7095C42.9007 12.1792 43.068 11.5714 43.0222 10.9238C42.9857 10.4194 42.7319 10.2175 42.2282 10.2614C41.6796 10.3091 41.1326 10.3698 40.5865 10.4372C40.3848 10.4621 40.1853 10.5191 39.9896 10.5727C39.5193 10.7022 39.2096 11.006 39.0799 11.4765C38.8068 12.466 38.3519 13.3638 37.797 14.221C37.6564 14.4382 37.5546 14.7198 37.5459 14.9756C37.537 15.3766 37.6206 15.7813 37.6743 16.2858ZM31.923 3.98668C31.983 3.80952 32.0188 3.7074 32.0541 3.60379C32.1497 3.31943 32.2897 3.06098 32.5325 2.87662C32.5735 2.8451 32.6584 2.86907 32.7689 2.86583C32.7037 2.98973 32.6697 3.07035 32.6222 3.14244C32.1611 3.83006 32.0748 4.56195 32.3434 5.34926C32.4305 5.60399 32.4943 5.86953 32.5293 6.13593C32.5758 6.48944 32.6833 6.80537 32.8931 7.09706C33.1962 7.51832 33.4346 7.97173 33.5132 8.49596C33.5214 8.54806 33.5615 8.59813 33.6105 8.69313C33.6685 8.57722 33.7095 8.51462 33.7344 8.44615C33.9678 7.75209 34.206 7.06136 34.429 6.36269C34.6188 5.76855 34.5786 5.17063 34.4041 4.57657C34.371 4.46501 34.3319 4.35577 34.2994 4.24571C34.0316 3.30599 34.0808 2.43469 34.8478 1.72482C34.8604 1.71301 34.8567 1.68158 34.8657 1.63835C34.4403 1.80391 34.0075 1.93263 33.6124 2.1365C33.1141 2.39271 32.6406 2.6997 32.1684 3.00103C31.8216 3.21381 31.7912 3.54194 31.923 3.98668ZM30.8488 23.7198C31.3075 23.2336 31.8365 22.9811 32.3731 22.748C32.8948 22.5208 33.3691 22.2204 33.7995 21.8558C34.1511 21.5582 34.5251 21.2605 34.7069 20.8268C34.9747 20.1902 35.1927 19.5315 35.4252 18.8793C35.4617 18.7787 35.4598 18.6636 35.4886 18.4813C35.3546 18.5697 35.2784 18.608 35.2167 18.6614C34.6065 19.1911 33.9176 19.5629 33.1263 19.7464C32.8034 19.822 32.4786 19.9104 32.1729 20.0346C31.4814 20.3158 31.0244 20.8238 30.9479 21.5812C30.8748 22.2631 30.8807 22.9539 30.8488 23.7198ZM2.51742 23.3949C2.46664 23.0569 2.40638 22.7917 2.39019 22.5249C2.36666 22.1642 2.1702 21.9641 1.85615 21.8461C1.74543 21.8045 1.63562 21.7608 1.48902 21.7021C1.92411 21.429 2.38632 21.5965 2.50903 22.031C2.58213 22.2895 2.61675 22.5595 2.65526 22.8262C2.72937 23.3522 2.94805 23.7683 3.43571 24.0365C4.14513 24.4241 4.84035 24.8414 5.54134 25.2427C5.63648 25.2972 5.74155 25.3376 5.8685 25.3988C5.8766 25.3092 5.89126 25.2586 5.88236 25.2136C5.79465 24.8381 5.72244 24.4583 5.60669 24.0903C5.52671 23.8362 5.41817 23.5795 5.26558 23.3641C5.00725 22.9962 4.70252 22.6637 4.42116 22.3117C4.24007 22.0849 4.01292 21.9694 3.72024 21.9813C3.64581 21.9844 3.5678 21.9473 3.49174 21.9285C3.48836 21.9022 3.4844 21.8743 3.48102 21.848C3.61003 21.7909 3.73903 21.7337 3.89134 21.6658C3.71376 21.4878 3.49824 21.4507 3.28648 21.4277C2.61849 21.3541 1.95533 21.3944 1.30437 21.5545C0.631352 21.7196 0.299751 22.4485 0.608273 23.0733C0.721478 23.3023 0.852853 23.5295 1.00882 23.7315C1.10553 23.8563 1.25026 23.9676 1.39629 24.0249C1.61947 24.1126 2.28107 23.9225 2.51285 23.732C2.00889 23.3336 1.44153 23.0152 1.03217 22.5021C1.56201 22.7021 1.94806 23.1464 2.51742 23.3949ZM13.5287 24.4585C13.4963 23.9163 13.4639 23.4311 13.4401 22.946C13.4051 22.2424 13.1713 21.6109 12.7226 21.0717C12.2328 20.4846 11.6389 20.014 10.9752 19.638C10.6231 19.4397 10.2473 19.2956 9.83301 19.1717C9.83737 19.2668 9.83114 19.3038 9.84042 19.3365C9.96534 19.7943 10.0882 20.2512 10.2205 20.7061C10.303 20.9885 10.3756 21.2766 10.4963 21.5425C10.9356 22.5035 11.5977 23.2639 12.5305 23.784C12.8717 23.9762 13.1842 24.2227 13.5287 24.4585ZM22.3182 13.906C22.6886 13.0825 22.8958 12.3122 22.7837 11.4813C22.7377 11.1379 22.7108 10.7906 22.6663 10.4467C22.6105 10.0208 22.461 9.62783 22.2471 9.2548C22.1251 9.04301 22.016 8.82449 21.9173 8.6019C21.8892 8.53852 21.9158 8.45214 21.9183 8.31289C22.2904 8.58459 22.3328 9.01576 22.6343 9.26484C22.7237 8.60263 21.9021 7.28215 21.1763 6.93204C21.1946 7.11158 21.2416 7.27649 21.2238 7.43381C21.1731 7.89083 21.1417 8.35763 21.0226 8.79804C20.814 9.56024 20.8786 10.287 21.099 11.0343C21.3488 11.879 21.7577 12.6515 22.0992 13.4537C22.1574 13.59 22.2275 13.7217 22.3182 13.906ZM17.686 27.9288C17.6491 27.1187 17.5196 26.4328 17.0296 25.8406C16.6953 25.4366 16.3714 25.0061 16.1364 24.5393C15.6834 23.6406 15.0754 22.9041 14.2113 22.3884C14.1013 22.3223 14.004 22.2357 13.8965 22.1669C13.8278 22.1228 13.7515 22.0903 13.6661 22.0475C13.7286 22.7335 13.7771 23.3835 13.8524 24.0318C13.9112 24.5361 14.1277 24.9599 14.5433 25.2769C14.9514 25.5882 15.3431 25.9232 15.7431 26.2445C15.8177 26.3036 15.9022 26.3485 16.0681 26.4568C15.9628 25.8375 15.8965 25.3051 15.7795 24.7837C15.657 24.2437 15.3113 23.8061 15.0046 23.3448C15.1367 23.3884 15.2395 23.4538 15.324 23.5385C15.6972 23.91 15.9305 24.3637 16.0691 24.8697C16.2056 25.3662 16.3416 25.8612 16.4751 26.3589C16.6559 27.0265 17.0972 27.4891 17.686 27.9288ZM35.1797 21.6971C35.0771 21.7249 35.0366 21.7269 35.0076 21.7451C34.8578 21.8414 34.7064 21.9383 34.5622 22.0446C33.5024 22.8322 33.1544 23.8854 33.426 25.1659C33.5836 25.9065 33.9515 26.5913 34.0075 27.3576C34.0083 27.3729 34.043 27.387 34.1063 27.435C34.3801 26.924 34.6496 26.4198 34.9212 25.9165C35.146 25.5006 35.2589 25.0488 35.2334 24.5817C35.2122 24.1872 35.1312 23.7935 35.0489 23.4056C34.9497 22.943 34.9346 22.4891 35.0707 22.0351C35.0972 21.9401 35.131 21.8457 35.1797 21.6971ZM27.6541 48.5493C27.1037 47.5104 26.6165 46.4487 26.1807 45.36C25.9899 44.8829 25.7725 44.4127 25.5404 43.9534C24.6812 42.2448 23.6303 40.6576 22.4621 39.1488C21.8459 38.3516 21.1667 37.6134 20.3367 37.0308C20.2514 36.9707 20.1562 36.9248 20.0175 36.8422C20.0878 37.6099 20.3742 38.2002 20.8618 38.6845C21.2258 39.0457 21.63 39.3689 22.0004 39.7243C22.8651 40.5596 23.5934 41.5033 24.2434 42.5155C24.9096 43.5559 25.5971 44.5847 26.1455 45.6935C26.4256 46.2585 26.6755 46.8388 26.9392 47.4102C27.1323 47.8225 27.3389 48.2208 27.6541 48.5493ZM32.9112 24.8633C32.805 24.9703 32.7496 25.0178 32.7027 25.0741C32.1401 25.7701 32.0042 26.5956 31.9857 27.4618C31.9643 28.4536 32.5785 29.2015 32.9669 30.1375C33.2016 29.3893 33.4336 28.7356 33.607 28.0683C33.7693 27.4434 33.7075 26.821 33.4348 26.222C33.2913 25.9062 33.183 25.575 33.0598 25.2497C33.0192 25.141 32.9784 25.0359 32.9112 24.8633ZM26.3875 23.1247C26.3975 22.9117 26.4058 22.7874 26.407 22.6625C26.4128 22.1607 26.3948 21.6596 26.4255 21.1602C26.5194 19.613 25.7188 18.6335 24.4067 17.9119C24.4096 18.0386 24.4009 18.1354 24.4154 18.23C24.5944 19.5378 25.0393 20.7734 25.453 22.0175C25.6024 22.4675 25.9316 22.7922 26.3875 23.1247ZM17.2275 32.9106C16.7171 32.4472 16.2433 31.9541 15.7055 31.5481C15.1455 31.1249 14.5056 31.1147 13.9089 31.5025C13.5057 31.7648 13.1355 32.0766 12.7309 32.3792C12.8721 32.6008 13.1028 32.6459 13.3173 32.7024C14.0344 32.8934 14.7546 33.0746 15.4717 33.2656C15.769 33.3451 16.0469 33.3217 16.3332 33.205C16.6022 33.0969 16.8846 33.0233 17.2275 32.9106ZM15.964 23.3326C16.1057 23.6214 16.1926 23.8624 16.3301 24.0699C16.8376 24.8264 17.3629 25.5709 17.8812 26.3197C18.0435 26.5556 18.2765 26.6775 18.5484 26.7358C18.9651 26.826 19.3608 26.9641 19.7084 27.2212C19.7306 27.2385 19.7741 27.2267 19.8306 27.2306C19.8171 27.165 19.8155 27.1121 19.7946 27.0718C19.5572 26.6163 19.3129 26.1652 19.0799 25.708C18.8622 25.2811 18.6001 24.8905 18.2382 24.5699C17.9602 24.3238 17.6888 24.0682 17.4085 23.8247C17.0175 23.4825 16.5487 23.3643 15.964 23.3326ZM22.1354 32.4763C22.1099 32.3843 22.1019 32.3373 22.084 32.2958C21.5512 31.1257 21.019 29.957 20.4823 28.7901C20.1841 28.1387 19.7145 27.6388 19.1038 27.275C18.907 27.158 18.6929 27.0806 18.4656 27.1103C18.448 27.1621 18.4299 27.1864 18.433 27.2077C18.4407 27.2583 18.4519 27.3092 18.4715 27.3552C18.8261 28.1557 19.2016 28.9394 19.7241 29.6504C20.0736 30.1245 20.4314 30.6109 20.6653 31.1456C20.9621 31.8199 21.5033 32.1416 22.1354 32.4763ZM35.6279 24.6546C35.7054 24.5622 35.7723 24.4912 35.8282 24.4141C36.1596 23.9585 36.4782 23.4922 36.8223 23.0472C37.045 22.7583 37.1637 22.4407 37.1562 22.0858C37.1399 21.3991 37.0988 20.7151 37.0658 19.9813C36.4225 20.5981 35.7649 21.1651 35.4082 21.9884C35.2844 22.2751 35.2398 22.5846 35.2953 22.8948C35.3952 23.4695 35.5104 24.0435 35.6279 24.6546ZM12.7682 17.0648C12.7951 17.0543 12.8234 17.0433 12.8503 17.0328C12.7689 16.5719 12.7396 16.108 12.5187 15.6686C12.2893 15.2117 12.1202 14.7244 11.9219 14.2502C11.7353 13.806 11.4808 13.4349 10.9582 13.3462C10.8533 13.3283 10.7178 13.3379 10.6888 13.1573C10.9864 12.955 11.2297 13.2665 11.581 13.2594C11.1255 12.6589 10.4948 12.531 9.87792 12.3546C10.1165 12.7423 10.1508 13.1662 10.1942 13.5866C10.205 13.6895 10.2174 13.7919 10.2312 13.8937C10.2846 14.2739 10.4155 14.6101 10.7103 14.8773C10.8907 15.0405 11.0437 15.235 11.2106 15.412C11.7295 15.9636 12.2493 16.5132 12.7682 17.0648ZM22.4682 31.5033C22.6746 31.1637 22.8702 30.92 22.9817 30.6415C23.2152 30.058 23.2211 29.4681 22.8847 28.9041C22.514 28.2828 21.9492 27.8562 21.3922 27.4231C21.3484 27.39 21.2803 27.3871 21.2004 27.3629C20.9144 27.9927 20.9067 28.5955 21.2163 29.1923C21.4646 29.6712 21.7296 30.1402 21.9863 30.6141C22.1344 30.8797 22.2785 31.1485 22.4682 31.5033ZM12.7241 20.4973C12.7723 20.5857 12.7957 20.6457 12.8337 20.6949C13.2102 21.1896 13.6304 21.6379 14.1563 21.9777C14.5026 22.2007 14.8507 22.4195 15.1946 22.6451C15.5459 22.8765 15.9343 23.0002 16.3447 23.0565C16.4499 23.0709 16.5587 23.0544 16.7117 23.0502C16.6614 22.9384 16.6421 22.8802 16.6116 22.8282C16.1247 22.0014 15.4409 21.3307 14.8589 20.5772C14.8442 20.5571 14.8211 20.5418 14.8034 20.5228C14.573 20.2754 14.2885 20.1891 13.9633 20.25C13.5657 20.3236 13.1671 20.4078 12.7241 20.4973ZM30.3451 27.8083C30.3716 27.8101 30.3981 27.8119 30.424 27.8122C30.8493 26.4454 31.6238 25.2693 32.4256 24.1103C32.7313 23.6681 33.039 23.2269 33.34 22.7813C33.3815 22.7202 33.3952 22.6406 33.4401 22.5177C32.8514 22.8021 32.3183 23.0442 31.7978 23.3142C31.0657 23.6942 30.6299 24.27 30.5827 25.1336C30.5442 25.8382 30.4384 26.5379 30.3678 27.2395C30.3491 27.4299 30.3522 27.6189 30.3451 27.8083ZM27.7921 35.2818C27.8201 35.2744 27.8473 35.269 27.8753 35.2615C27.6535 34.3385 27.4296 33.4145 27.2123 32.4897C26.9222 31.2631 26.619 30.0381 26.3561 28.8061C26.2286 28.2093 26.1799 27.5939 26.1104 27.0886C25.9872 27.3682 25.8431 27.7354 25.6631 28.0855C25.3931 28.6105 25.3449 29.1357 25.5814 29.6815C25.7701 30.1179 25.961 30.5552 26.1542 30.9899C26.1858 31.0623 26.2303 31.1279 26.309 31.2684C26.354 30.8585 26.3888 30.5373 26.4237 30.2161C26.4519 30.2137 26.4802 30.2114 26.5085 30.209C26.5378 30.2841 26.5893 30.3591 26.5926 30.4338C26.5983 30.6649 26.5746 30.8954 26.5839 31.1268C26.5949 31.4199 26.5682 31.731 26.6566 32.0025C27.0143 33.1025 27.4099 34.1896 27.7921 35.2818ZM2.99001 28.6538C2.92732 28.6782 2.8414 28.7047 2.76223 28.7442C2.21649 29.0067 2.07364 29.4477 2.36735 29.9816C2.44226 30.1166 2.51593 30.2573 2.62049 30.367C3.5148 31.3135 4.10516 31.3378 5.11079 30.7113C4.9695 30.6574 4.85372 30.616 4.74216 30.5679C4.16294 30.3249 3.5843 30.0835 3.00929 29.8337C2.92888 29.7993 2.81122 29.7708 2.83833 29.6064C3.33259 29.7061 3.74757 30.0216 4.29309 30.072C4.2381 29.8998 4.19591 29.7694 4.1552 29.6383C4.02608 29.2271 3.76614 28.9566 3.34313 28.8413C3.22579 28.8092 3.12312 28.7264 2.99001 28.6538ZM1.68538 24.4188C1.98478 24.7862 2.27296 25.1424 2.56263 25.4981C2.57886 25.5177 2.60658 25.5536 2.61495 25.5486C2.84545 25.452 2.91965 25.6824 3.05653 25.7691C3.39485 25.9848 3.75808 26.0526 4.12174 25.9006C4.45763 25.7613 4.7669 25.5579 5.12044 25.3667C5.0371 25.2851 4.99939 25.2324 4.94812 25.2022C4.38355 24.8689 3.81989 24.5334 3.24928 24.2111C2.97807 24.0574 2.67799 24.0636 2.38804 24.1488C2.16013 24.2167 1.9406 24.3194 1.68538 24.4188ZM8.10838 31.0829C7.88753 31.0012 7.74767 30.9553 7.61087 30.8997C6.76329 30.559 6.00804 30.089 5.49352 29.3058C5.32456 29.0483 5.1876 28.7715 5.0363 28.502C4.95873 28.3645 4.86695 28.217 4.6918 28.2351C4.26732 28.2793 3.84329 28.3424 3.44369 28.5653C4.05758 28.9503 4.14397 29.0222 4.40933 29.6465C4.60187 30.097 4.9182 30.3887 5.3784 30.5069C6.22123 30.725 7.06808 30.9226 7.91428 31.1273C7.9431 31.1351 7.97957 31.114 8.10838 31.0829ZM29.8579 29.9476C29.8532 29.7766 29.8472 29.651 29.8491 29.5276C29.8573 28.617 29.8333 27.7033 29.8838 26.7952C29.9236 26.0763 29.6196 25.4894 29.3384 24.8245C29.2881 24.9115 29.2566 24.9411 29.2567 24.9721C29.2088 25.8913 28.9845 26.772 28.6902 27.6366C28.5835 27.9495 28.6447 28.2437 28.8371 28.5128C29.1635 28.9717 29.4899 29.4306 29.8579 29.9476ZM31.2498 14.519C31.2797 14.49 31.3099 14.4748 31.313 14.4563C31.4616 13.6415 31.772 12.8846 32.1035 12.1333C32.184 11.9516 32.2218 11.7399 32.2334 11.54C32.272 10.8665 32.1128 10.2146 31.9673 9.56259C31.9523 9.49756 31.8947 9.44221 31.8214 9.32901C31.7495 9.47973 31.6848 9.57405 31.6596 9.67718C31.5348 10.1734 31.4029 10.669 31.3042 11.1706C31.1888 11.7617 31.094 12.3569 31.0098 12.9531C30.9768 13.1906 30.9612 13.4421 31.0006 13.6757C31.0491 13.9593 31.1626 14.2332 31.2498 14.519ZM38.9459 18.705C38.453 18.9971 37.9853 19.2085 37.6647 19.6168C37.5279 19.791 37.4158 20.0196 37.3868 20.2365C37.3048 20.8337 37.4037 21.4278 37.5133 22.0937C37.7621 21.8189 37.9623 21.5958 38.1666 21.3745C39.0065 20.4634 38.9723 20.4992 38.9378 19.3684C38.9312 19.1705 38.9413 18.9713 38.9459 18.705ZM27.0131 35.687C26.9842 36.4605 27.2692 37.9345 27.5496 38.5357C28.3329 40.2168 28.9116 41.9775 29.5092 43.7292C29.6948 44.2722 29.8649 44.8196 30.0646 45.4298C29.694 43.3254 27.6893 36.912 27.0131 35.687ZM19.3771 38.4379C19.2776 38.3764 19.2128 38.3204 19.1383 38.2923C18.8744 38.1928 18.6053 38.1109 18.3433 38.0072C18.1091 37.9134 17.9283 37.9699 17.7562 38.1458C17.6134 38.2913 17.4612 38.43 17.2931 38.5456C17.0828 38.6897 16.9624 38.6674 16.7544 38.4908C17.0618 38.309 17.4635 38.2373 17.5713 37.7943C17.3203 37.5999 17.0219 37.5795 16.7426 37.5067C16.2804 37.3876 15.9149 37.5437 15.6211 37.9018C15.3905 38.1834 15.1639 38.4669 14.9206 38.769C16.411 38.8405 17.8766 38.7246 19.3771 38.4379ZM41.2414 17.096C40.6486 17.4408 40.0612 17.7023 39.6325 18.1906C39.1253 18.7683 39.1481 19.4629 39.2331 20.2421C39.3917 20.1285 39.4985 20.0628 39.5913 19.9834C39.8058 19.8014 40.0035 19.5983 40.2256 19.4272C40.9638 18.8599 41.2611 18.096 41.2414 17.096ZM23.4656 30.0521C23.4198 30.1287 23.3837 30.1774 23.3601 30.2315C23.2414 30.5006 23.1509 30.7847 23.0056 31.0384C22.7583 31.4716 22.7045 31.9074 22.8961 32.3687C23.1441 32.9618 23.3981 33.5525 23.6536 34.1427C23.6858 34.2166 23.7383 34.2809 23.8295 34.4268C23.8626 33.4875 23.9088 32.6434 23.9153 31.7991C23.9175 31.456 23.854 31.1074 23.7854 30.7677C23.7378 30.5218 23.6727 30.2706 23.4656 30.0521ZM30.1679 21.2903C29.9952 21.8622 29.8389 22.388 29.6785 22.9119C29.5998 23.169 29.4964 23.42 29.4347 23.6809C29.3975 23.8371 29.3648 24.0313 29.4236 24.1691C29.5997 24.5863 29.8221 24.9854 30.0275 25.3894C30.0558 25.387 30.0841 25.3847 30.1103 25.3814C30.2062 24.9742 30.3255 24.5699 30.3887 24.1582C30.4731 23.6155 30.5343 23.0662 30.5651 22.5184C30.591 22.0728 30.3954 21.6805 30.1679 21.2903ZM32.5346 7.18298C32.4078 7.59013 32.3081 7.96082 32.1777 8.31921C32.0537 8.66302 32.0745 8.99024 32.1684 9.3374C32.298 9.80722 32.3885 10.2871 32.4975 10.7614C32.5151 10.8375 32.5423 10.9117 32.5734 11.0136C33.572 9.43752 33.3885 8.12275 32.5346 7.18298ZM16.0376 33.6157C16.5278 34.0627 16.9553 34.4632 17.3995 34.8451C17.4983 34.9311 17.6528 34.9747 17.7875 34.9897C18.1447 35.0287 18.4879 34.9435 18.8378 34.8488C18.8209 34.7879 18.8222 34.7425 18.8006 34.718C18.4643 34.3131 18.1357 33.9018 17.7844 33.5113C17.5606 33.2631 17.2501 33.1939 16.9376 33.274C16.6566 33.3471 16.3928 33.4774 16.0376 33.6157ZM31.8862 44.5462C31.7674 43.9806 31.6224 43.4182 31.5379 42.8479C31.4265 42.0979 31.383 41.3371 31.273 40.5865C30.9609 38.4732 30.6377 36.3624 30.303 34.2527C30.2256 33.7625 30.0854 33.283 29.9743 32.7991C29.9451 32.8035 29.9165 32.8095 29.8873 32.8139C29.9415 33.6156 29.9219 34.4217 30.1146 35.2127C30.4255 36.4882 30.7098 37.7707 30.8654 39.0756C30.9882 40.0976 31.0848 41.123 31.2208 42.1434C31.3322 42.9729 31.5301 43.786 31.8862 44.5462ZM20.3624 33.9131C20.8795 35.9173 22.0431 37.5247 23.471 38.9721C22.6503 37.1552 21.6339 35.4578 20.3624 33.9131ZM19.4839 34.4469C19.8077 33.9804 19.9843 33.5556 19.6837 33.0746C19.6025 32.9454 19.5106 32.8153 19.3979 32.7157C18.9777 32.3382 18.5479 31.9714 18.1167 31.6052C18.0652 31.5613 17.9879 31.5482 17.8769 31.5015C18.0651 32.7003 18.819 33.52 19.4839 34.4469ZM30.8213 14.1776C30.7927 14.1836 30.764 14.1895 30.7375 14.1964C30.7237 14.245 30.7079 14.2926 30.6977 14.3415C30.5218 15.1964 30.3396 16.0486 30.1764 16.9054C30.1445 17.0751 30.1454 17.2718 30.2008 17.4317C30.3267 17.7906 30.4965 18.1342 30.6824 18.5631C30.7193 18.4018 30.744 18.3196 30.755 18.2375C30.8499 17.5628 30.9376 16.8874 31.0351 16.2151C31.1163 15.6598 31.0355 15.1122 30.9473 14.5676C30.9242 14.4331 30.8629 14.3066 30.8213 14.1776ZM6.00753 24.5064C6.0385 25.1511 6.22831 25.6874 6.85265 25.9888C7.44109 26.2731 8.0117 26.5955 8.59288 26.8964C8.68776 26.9459 8.79173 26.9746 8.92737 27.0272C8.90428 26.6059 8.7812 26.3029 8.44476 26.1141C8.31048 26.0384 8.18133 25.9539 8.04523 25.8824C7.31699 25.5039 6.56435 25.1642 6.00753 24.5064ZM23.3474 35.2989C22.861 34.0934 22.372 32.9563 21.1771 32.3325C21.4551 33.6209 22.1222 34.6282 23.3474 35.2989ZM32.6125 32.9493C32.6319 32.9417 32.6513 32.9342 32.6722 32.926C32.7062 32.3908 32.7453 31.8554 32.7722 31.3195C32.8093 30.5583 32.6575 29.8414 32.233 29.1925C32.1483 29.063 32.0728 28.9265 31.9513 28.7249C31.8594 29.2481 31.8535 29.6877 31.9441 30.1104C32.146 31.0619 32.387 32.0035 32.6125 32.9493ZM30.4869 21.0192C30.6958 19.8559 30.5366 18.7979 30.0042 17.7658C29.5711 18.4633 29.8505 20.3336 30.4869 21.0192ZM26.7143 26.9711C26.7321 26.8535 26.7534 26.7934 26.7475 26.7386C26.6837 25.9961 26.6198 25.2535 26.5479 24.5124C26.4934 23.9529 26.2495 23.4809 25.8446 23.094C25.7869 23.0387 25.7101 23.0046 25.6419 22.962C25.6183 22.9764 25.5941 22.9893 25.5705 23.0037C25.6757 23.3844 25.758 23.7724 25.8916 24.1421C26.139 24.8219 26.3575 25.5025 26.4084 26.2294C26.4271 26.4762 26.4952 26.7262 26.7143 26.9711ZM35.9419 18.4846C36.3633 17.9248 36.7963 17.3725 37.2035 16.8027C37.4796 16.4169 37.4463 15.8059 37.134 15.3744C36.7932 16.4594 36.1375 17.38 35.9419 18.4846ZM30.5309 49.1493C30.0778 48.6741 29.7282 48.1378 29.4084 47.5813C29.2162 47.2464 29.0408 46.9016 28.8471 46.5674C28.148 45.3496 27.5181 44.0979 27.0269 42.7785C26.8381 42.2713 26.6364 41.7707 26.4401 41.2664C26.4147 41.2763 26.3893 41.2862 26.364 41.296C26.6438 42.015 26.8974 42.746 27.2101 43.4522C27.7766 44.7354 28.3589 46.0107 28.9735 47.2718C29.2139 47.7659 29.546 48.2173 29.8615 48.6701C30.0193 48.8991 30.2368 49.0823 30.5309 49.1493ZM20.6548 28.1249C20.9626 27.2775 20.9399 27.0028 20.3941 26.3822C20.1323 26.0848 19.8534 25.801 19.5775 25.516C19.5228 25.4595 19.4463 25.4219 19.3806 25.3766C19.3701 25.3894 19.3596 25.4021 19.347 25.4139C19.7706 26.2947 20.1951 27.1735 20.6548 28.1249ZM34.8469 21.3323C35.4228 21.103 36.7433 19.9166 36.8887 19.5351C36.3223 19.5326 35.8056 19.649 35.4804 20.1472C35.2537 20.4964 35.0848 20.8837 34.8469 21.3323ZM15.7746 30.4893C15.7616 30.5134 15.7472 30.5381 15.7342 30.5621C16.4597 31.1457 17.0658 31.8638 17.8825 32.4828C17.7907 32.1676 17.7361 31.9434 17.6616 31.7253C17.508 31.2734 17.2238 30.9451 16.76 30.7955C16.4324 30.6913 16.1031 30.5914 15.7746 30.4893ZM17.4768 37.3575C18.1464 37.6206 18.7813 37.8696 19.4953 38.1499C19.4285 38.0048 19.4106 37.9323 19.3664 37.8803C19.1595 37.6359 18.956 37.3867 18.7302 37.16C18.3231 36.7499 17.8562 36.8088 17.4768 37.3575ZM17.9767 27.2142C17.9436 27.2219 17.9084 27.2287 17.8753 27.2364C17.8881 27.3576 17.8884 27.4819 17.9167 27.5988C18.0307 28.0505 18.2181 28.4701 18.4986 28.8466C18.9437 29.4425 19.378 30.0461 19.8192 30.6453C19.8584 30.6974 19.9068 30.7425 19.9978 30.8436C19.9506 30.4265 19.7476 30.1788 19.5443 29.9347C19.0144 29.2975 18.5915 28.5996 18.2892 27.8271C18.2062 27.614 18.082 27.4186 17.9767 27.2142ZM34.6007 45.0296C34.1594 43.1273 33.718 41.225 33.2766 39.3227C33.3344 40.4825 34.2138 44.3092 34.6007 45.0296ZM26.6935 36.4907C26.5942 35.5821 26.6122 34.6435 26.0054 33.8617C25.9012 34.8217 26.2295 35.674 26.6935 36.4907ZM29.5472 33.0794C29.5238 32.7808 29.5085 32.4809 29.4735 32.1834C29.4355 31.8784 29.392 31.5722 29.3239 31.2737C29.2587 30.9914 29.2667 30.6807 29.0488 30.3991C28.9398 31.3731 29.1074 32.3467 29.5472 33.0794ZM13.6137 33.1505C14.4349 33.5118 15.2571 33.8711 16.1468 34.2628C15.6934 33.6321 14.631 33.159 13.6137 33.1505ZM28.9929 29.2576C29.3639 30.2107 29.7261 31.1414 30.0913 32.0795C30.0822 31.2084 29.5255 29.7295 28.9929 29.2576ZM26.5208 27.5338C26.7485 28.5427 26.9777 29.5511 27.2054 30.56C27.2838 29.9401 26.8742 28.0842 26.5208 27.5338ZM21.7127 30.7413C22.3681 32.2043 23.024 33.6688 23.6794 35.1317C23.164 33.6091 22.5114 32.1485 21.7127 30.7413ZM28.8102 33.6895C28.6998 33.0791 28.4805 32.5422 28.0081 32.1056C27.9306 32.4452 27.9477 32.5906 28.1225 32.8233C28.3435 33.1175 28.5799 33.4023 28.8102 33.6895ZM28.3543 28.9548C28.1798 29.4029 28.3219 30.077 28.6483 30.4651C28.803 30.0678 28.7308 29.6793 28.3543 28.9548ZM25.9429 45.9192C26.2744 46.6561 26.597 47.3965 26.9399 48.1273C27.0641 48.3935 27.2334 48.6387 27.3918 48.8865C27.4221 48.9334 27.4931 48.9525 27.5455 48.9856C26.9062 48.0055 26.5363 46.9051 25.9429 45.9192ZM13.9117 18.2012C13.8017 17.6183 13.4892 17.1419 13.1455 16.6829C13.1912 17.2994 13.4267 17.8161 13.9117 18.2012ZM35.086 44.7353C34.7677 43.4938 34.519 42.2321 34.0656 41.0275C34.476 42.2453 34.5751 43.5463 35.086 44.7353ZM25.5908 34.0196C25.7594 33.4285 25.5081 32.6725 25.0366 32.353C25.2273 32.927 25.3965 33.4367 25.5908 34.0196ZM19.1279 36.2344C19.0563 36.62 19.3441 37.1078 19.8113 37.403C19.6506 36.9591 19.6978 36.4447 19.1279 36.2344ZM9.00578 36.8988C8.417 36.5784 7.88648 36.6327 7.55621 37.0206C8.04755 37.1525 8.48311 36.9381 9.00578 36.8988ZM27.0645 46.4385C27.3692 47.3846 28.0565 48.7574 28.4108 48.979C27.9182 48.0489 27.4544 47.1752 27.0645 46.4385ZM24.5475 33.7412C24.8288 34.4199 25.1451 35.078 25.5878 35.6679C25.2844 35.0031 25.1462 34.2462 24.5475 33.7412ZM24.1513 18.8496C24.0711 18.383 24.0782 17.898 23.88 17.4549C23.7038 17.9694 23.8308 18.4281 24.1513 18.8496ZM24.2356 31.3858C24.1608 31.9663 24.1533 32.5344 24.628 33.0738C24.4831 32.4544 24.3594 31.9201 24.2356 31.3858ZM22.1655 15.7612C22.4125 16.175 22.6128 16.619 22.9432 16.9778C22.8048 16.4941 22.5387 16.093 22.1655 15.7612ZM18.763 36.3833C18.7871 36.0213 18.6352 35.8782 18.1054 35.7578C18.3481 35.9883 18.5422 36.1737 18.763 36.3833ZM25.3858 38.8491C25.3813 38.8508 25.3753 38.8531 25.3709 38.8549C25.5689 39.3637 25.767 39.8726 25.965 40.3814C25.9695 40.3797 25.9755 40.3774 25.9799 40.3756C25.7819 39.8668 25.5838 39.3579 25.3858 38.8491ZM26.8826 49.5962C26.9116 49.578 26.9421 49.5593 26.9717 49.5426C26.8387 49.3333 26.7051 49.1226 26.5721 48.9134C26.5569 48.9228 26.5431 48.9316 26.5273 48.9395C26.6465 49.1575 26.7648 49.3776 26.8826 49.5962ZM28.1157 31.6489C28.1336 31.642 28.1506 31.6371 28.1685 31.6301C28.1247 31.5175 28.0808 31.4049 28.0376 31.2939C28.0197 31.3008 28.0027 31.3057 27.9848 31.3127C28.028 31.4238 28.0718 31.5364 28.1157 31.6489ZM24.9174 37.6988C24.9187 37.6931 24.9214 37.6869 24.9226 37.6812C24.8595 37.5191 24.7964 37.357 24.7339 37.1964C24.7309 37.1975 24.7264 37.1993 24.7235 37.2004C24.7877 37.3655 24.8526 37.5322 24.9174 37.6988ZM20.5793 31.8652C20.5918 31.8621 20.6023 31.858 20.6148 31.8548C20.5517 31.6927 20.4892 31.5321 20.4261 31.37C20.4141 31.3747 20.4037 31.3787 20.3918 31.3834C20.4543 31.544 20.5168 31.7046 20.5793 31.8652ZM33.8291 40.2035C33.8231 40.2058 33.8172 40.2082 33.8112 40.2105C33.8515 40.314 33.8924 40.4191 33.9333 40.5242C33.9393 40.5219 33.9452 40.5195 33.9512 40.5172C33.9103 40.4121 33.87 40.3086 33.8291 40.2035ZM26.1869 48.1092C26.1757 48.098 26.1704 48.0932 26.163 48.0874C26.1667 48.1102 26.1665 48.1362 26.1747 48.1572C26.2015 48.2262 26.2299 48.2947 26.2583 48.3632C26.2618 48.3722 26.2748 48.3792 26.2994 48.4025C26.2559 48.2863 26.2202 48.1948 26.1869 48.1092ZM23.9983 35.7128C23.9896 35.7213 23.9804 35.7284 23.9717 35.737C23.9934 35.7752 24.0131 35.8125 24.0348 35.8507C24.0417 35.8463 24.0492 35.8434 24.056 35.8389C24.0361 35.7966 24.0183 35.7551 23.9983 35.7128ZM30.1512 45.8645C30.1577 45.8412 30.1661 45.8276 30.1617 45.8206C30.1479 45.7984 30.1311 45.7773 30.1142 45.7561C30.1256 45.7898 30.1364 45.8219 30.1512 45.8645ZM25.8841 47.5962C25.8901 47.5939 25.8946 47.5921 25.9005 47.5898C25.8877 47.5568 25.8748 47.5238 25.862 47.4907C25.8545 47.4936 25.8471 47.4966 25.8396 47.4995C25.8539 47.5319 25.8683 47.5643 25.8841 47.5962ZM30.2781 46.3803C30.2826 46.3785 30.2871 46.3768 30.2915 46.375C30.2787 46.342 30.2658 46.309 30.253 46.276C30.2485 46.2777 30.244 46.2795 30.2396 46.2812C30.2524 46.3142 30.2653 46.3473 30.2781 46.3803ZM24.284 36.248C24.2795 36.2497 24.2765 36.2509 24.2721 36.2527C24.2843 36.2842 24.2966 36.3157 24.3089 36.3472C24.3133 36.3455 24.3163 36.3443 24.3208 36.3426C24.3085 36.311 24.2963 36.2795 24.284 36.248ZM33.6778 39.6073C33.682 39.6489 33.6825 39.6591 33.6851 39.6702C33.6857 39.6717 33.6967 39.6691 33.7024 39.6704C33.6983 39.6599 33.6936 39.6478 33.6778 39.6073ZM34.9705 42.765C34.9663 42.7234 34.9652 42.7117 34.9632 42.7021C34.9626 42.7006 34.9516 42.7032 34.9465 42.7034C34.9506 42.7139 34.9547 42.7244 34.9705 42.765ZM33.1441 38.9249C33.1577 38.9421 33.1698 38.9599 33.1441 38.9249C33.1668 38.961 33.1562 38.9427 33.1441 38.9249ZM23.192 42.7813C23.1929 42.7705 23.1954 42.7592 23.1928 42.7481C23.1902 42.737 23.1816 42.7283 23.176 42.7183C23.1727 42.7317 23.1648 42.7469 23.1665 42.7601C23.1688 42.7661 23.1834 42.7725 23.192 42.7813ZM26.0056 26.082L26.0221 26.1067L26.0258 26.081L26.0056 26.082ZM31.619 40.2479L31.6024 40.2406L31.6117 40.2646L31.619 40.2479ZM19.1531 34.5549L19.1716 34.5805L19.1754 34.5549L19.1531 34.5549ZM31.5299 29.6511L31.5261 29.6768L31.5428 29.6755L31.5299 29.6511ZM23.7835 42.4024L23.787 42.3716L23.7659 42.3747L23.7835 42.4024ZM32.772 34.728L32.7544 34.74L32.7736 34.7585L32.772 34.728ZM30.2369 30.8198L30.2566 30.8484L30.2607 30.8192L30.2369 30.8198ZM22.9778 42.4342L22.975 42.4578L22.9902 42.4571L22.9778 42.4342ZM23.582 42.1144L23.6006 42.14L23.6044 42.1143L23.582 42.1144ZM23.4078 41.8434L23.4049 41.8757L23.4276 41.872L23.4078 41.8434ZM32.7409 34.4359L32.7232 34.4082L32.7185 34.4359L32.7409 34.4359ZM22.4384 41.6711L22.4199 41.6455L22.4161 41.6711L22.4384 41.6711ZM23.3656 39.6596C23.3731 39.6567 23.379 39.6544 23.3865 39.6515C23.383 39.6424 23.3795 39.6334 23.3745 39.625C23.3739 39.6235 23.361 39.6302 23.3551 39.6326C23.3592 39.6431 23.3627 39.6521 23.3656 39.6596ZM19.3554 34.8098L19.3377 34.8218L19.3584 34.8397L19.3554 34.8098ZM31.0239 37.0676L31.0398 37.0908L31.0427 37.0673L31.0239 37.0676ZM23.5703 39.9118L23.5506 39.8831L23.5465 39.9124L23.5703 39.9118Z\"\n      fill=\"#EE9D5B\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 46 / 50,\n  svg: travelVeggies,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/bannerWithDots.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Banner With Dots', 'sticker name', 'web-stories');\n\nfunction bannerDots({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M36.1513 38.523C36.1047 37.9912 36.0137 37.4632 35.9671 36.9314C35.9593 36.8427 35.9321 36.5325 35.9765 36.5286L35.9399 36.6211C35.7662 36.6809 35.7218 36.6848 35.5848 36.6521C35.496 36.6599 35.5365 36.6117 35.5809 36.6078C35.6253 36.6039 35.5077 36.7929 35.4633 36.7967C35.5077 36.7929 35.3379 36.897 35.3379 36.897C35.2935 36.9009 35.253 36.9491 35.2086 36.953C35.4344 36.9779 35.7008 36.9546 35.9266 36.9796C35.9748 37.02 36.0791 37.1895 35.9943 37.2416C36.4032 36.8039 36.2928 36.0544 35.8583 35.6904C35.3757 35.2859 34.7137 35.3884 34.3048 35.8261C33.3211 36.8499 33.8548 38.8576 35.3063 39.0881C36.7094 39.2782 37.9089 37.6549 37.7519 36.3735C37.5794 34.9148 35.84 33.9502 34.5784 34.8643C33.3167 35.7784 33.7789 37.4798 33.9359 38.7612C34.0562 40.1352 36.2755 39.9413 36.1513 38.523Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M30.3726 18.1438C29.871 18.5449 29.2846 18.9981 29.1653 19.6784C29.0016 20.3626 29.33 21.0485 29.8166 21.4972C30.5928 22.1886 31.9632 22.5155 32.9763 22.3377C34.3001 22.1327 35.1679 20.8064 34.6519 19.5117C34.1437 18.3056 32.725 17.9383 31.5383 18.1759C30.9651 18.2707 30.4713 18.7604 30.5257 19.3809C30.5723 19.9128 31.1149 20.4906 31.7324 20.392C31.91 20.3765 32.128 20.3128 32.3094 20.3416L32.6279 20.4031C32.543 20.4552 32.6124 20.2258 32.6124 20.2258C32.5524 20.0524 32.7938 20.2546 32.5158 20.1449C32.3305 20.0718 31.8384 20.0701 31.5604 19.9604C31.3269 19.8468 31.2669 19.6734 31.298 20.028C31.3291 20.3826 31.3984 20.1532 31.6531 19.997C32.7777 19.0502 31.5011 17.2413 30.3726 18.1438Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M17.3548 25.5677C16.0554 24.5201 16.4688 22.2266 17.453 21.5844C18.4373 20.9421 19.7013 21.0863 20.6277 21.575C22.0774 22.2969 22.1884 24.0736 21.1276 25.2381C20.1882 26.258 18.465 26.4979 17.3548 25.5677Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M10.6959 15.62C10.955 16.5352 10.9231 18.2136 10.3087 18.7062C9.69418 19.1989 9.66153 19.1042 9.33797 19.3031C9.01441 19.5021 7.3092 19.8459 7.22932 18.4238C7.06844 17.098 6.64847 14.8571 8.24802 14.226C9.33048 13.8189 10.4251 14.5718 10.6959 15.62Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.961 30.9849C18.9644 30.9669 18.9673 30.9487 18.9699 30.9303C19.1142 30.0244 18.3824 29.3291 17.4908 29.3624C17.1739 29.3901 16.8639 29.4972 16.5825 29.658C16.0335 29.5241 15.534 29.7929 15.2448 30.273C15.1455 30.4157 15.0109 30.5391 14.8764 30.6625C14.7418 30.7859 14.6073 30.9093 14.508 31.052C14.1068 31.5783 14.0242 32.1661 14.1268 32.827C14.3687 34.0564 15.313 35.135 16.6523 35.1074C16.7479 35.1064 16.8408 35.0887 16.929 35.0572C17.3463 35.3912 17.8552 35.5377 18.4589 35.3069C20.1026 34.685 19.9673 32.1443 18.961 30.9849Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M29.0892 37.0409C29.1086 37.2625 29.1569 37.303 29.1453 37.17C29.1203 37.3955 29.1242 37.4398 29.1569 37.303C29.0837 37.488 29.0875 37.5323 29.1242 37.4398C29.1203 37.3955 29.1647 37.3916 29.1608 37.3473C29.0393 37.4919 29.0432 37.5362 29.0798 37.4437L29.1203 37.3955C29.1608 37.3473 29.1608 37.3473 28.9949 37.4958C29.0393 37.4919 29.0354 37.4476 29.0798 37.4437C29.2457 37.2952 28.8656 37.5517 29.0393 37.4919C29.1686 37.436 29.1242 37.4398 28.9061 37.5035C28.9505 37.4997 28.9949 37.4958 28.9949 37.4958C28.9505 37.4997 28.8617 37.5074 28.8135 37.467C28.9061 37.5035 28.8579 37.4631 28.6764 37.4343C28.5316 37.313 28.4872 37.3168 28.5838 37.3977C28.4833 37.2725 28.4351 37.2321 28.4872 37.3168C28.5394 37.4016 28.5355 37.3573 28.4312 37.1877C28.3752 37.0587 28.3635 36.9257 28.3924 36.7445C28.3635 36.9257 28.5022 36.467 28.4251 36.6077C28.5427 36.4188 28.5832 36.3706 28.5022 36.467C28.4212 36.5634 28.4617 36.5152 28.6276 36.3667C28.5871 36.4149 28.5427 36.4188 28.5022 36.467C28.3324 36.5711 28.5022 36.467 28.591 36.4592C28.5022 36.467 28.4617 36.5152 28.4212 36.5634C28.3768 36.5672 28.3324 36.5711 28.2919 36.6193C28.1183 36.6792 28.6026 36.5922 28.3807 36.6116C27.8037 36.662 27.2694 37.1999 27.3682 37.8165C27.463 38.3888 27.9535 38.8819 28.5749 38.8276C29.1963 38.7733 29.7944 38.4531 30.2033 38.0155C30.863 37.3772 30.7737 36.3579 30.094 35.7473C29.4626 35.1772 28.5266 35.2144 27.8514 35.6753C27.1801 36.1805 26.8466 36.9689 27.0536 37.7994C27.2372 38.3639 27.9341 38.6603 28.4955 38.4326C29.0609 38.2492 29.2767 37.6498 29.0892 37.0409Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M26.4805 19.1537C26.4534 18.8434 26.4301 18.5775 26.4029 18.2673C26.3524 17.6911 25.8137 17.1576 25.1962 17.2562C24.5786 17.3548 24.1292 17.8406 24.1836 18.4611C24.2108 18.7714 24.2341 19.0373 24.2613 19.3476C24.3117 19.9237 24.8505 20.4573 25.468 20.3587C26.0855 20.26 26.5349 19.7742 26.4805 19.1537Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M39.9637 20.9233C39.8078 21.6962 40.1113 22.6075 40.9374 22.848C41.2154 22.9577 41.5338 23.0192 41.7924 22.9073C42.0509 22.7953 42.2573 22.5987 42.4155 22.3616C42.4926 22.2208 42.6102 22.0319 42.6873 21.8912C42.9553 21.3765 42.6674 20.6425 42.1558 20.4192C41.5516 20.1593 40.9901 20.387 40.6816 20.9499C40.6045 21.0906 40.4869 21.2795 40.4098 21.4203C40.8864 21.2446 41.4074 21.0652 41.884 20.8895C41.7469 20.8568 41.7391 20.7682 41.9322 20.93C41.8839 20.8895 41.8839 20.8895 41.9805 20.9704C42.077 21.0513 42.1253 21.0918 42.1369 21.2247C42.077 21.0513 42.1641 21.535 42.1447 21.3134C42.1486 21.3577 42.1564 21.4463 42.1602 21.4906C42.1564 21.4463 42.1525 21.402 42.193 21.3538C42.3239 20.8064 41.8623 20.1322 41.318 20.0458C40.6406 19.971 40.0908 20.3316 39.9637 20.9233Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M39.2324 28.4009C39.7307 28.9826 40.387 29.3272 41.1898 29.3018C41.7707 29.2957 42.3727 29.0198 42.7816 28.5821C43.2754 28.0924 43.3831 27.2791 42.9736 26.6896C42.512 26.0154 41.657 25.9561 40.8947 25.9334C40.3138 25.9395 39.7873 26.566 39.8821 27.1383C39.9848 27.7993 40.4636 28.1594 41.0889 28.1494C41.1776 28.1417 41.3629 28.2148 41.0445 28.1533C41.0889 28.1494 41.1333 28.1455 41.1815 28.186C41.2703 28.1782 41.3629 28.2148 41.4556 28.2514C41.637 28.2802 41.1776 28.1417 41.3186 28.2187C41.3186 28.2187 41.3668 28.2591 41.4112 28.2552C41.5039 28.2918 41.1699 28.053 41.2703 28.1782C41.3668 28.2591 41.0695 27.9278 41.1699 28.053C41.2703 28.1782 41.0539 27.7505 41.0656 27.8835C41.1216 28.0126 40.9901 27.5328 41.0018 27.6658C41.0134 27.7987 41.0151 27.3073 41.0267 27.4403C40.994 27.5771 41.1327 27.1184 41.1 27.2553C41.0267 27.4403 41.3025 27.0143 41.181 27.1589C41.019 27.3516 41.3913 27.0065 41.2659 27.1068C41.2215 27.1107 41.1366 27.1627 41.1405 27.2071C41.1405 27.2071 41.4434 27.0913 41.3103 27.1029C41.2659 27.1068 41.2659 27.1068 41.2254 27.155C41.181 27.1589 41.1366 27.1627 41.1405 27.2071C41.0112 27.263 41.4473 27.1356 41.3141 27.1472C41.2254 27.155 41.181 27.1589 41.0922 27.1666C40.9147 27.1821 41.3624 27.1877 41.2736 27.1954C41.2292 27.1993 41.2293 27.1993 41.1849 27.2032C41.1405 27.2071 41.0922 27.1666 41.0922 27.1666C41.3624 27.1877 41.3258 27.2802 41.2292 27.1993C41.1849 27.2032 41.181 27.1589 41.1366 27.1627C41.0439 27.1262 41.3741 27.3206 41.2331 27.2436C41.1849 27.2032 41.1849 27.2032 41.1366 27.1627C40.9918 27.0414 41.3336 27.3688 41.1887 27.2475C40.9918 27.0414 40.7948 26.8353 40.4802 26.8181C40.2062 26.7528 39.855 26.8281 39.6486 27.0248C39.0388 27.212 38.8346 27.9444 39.2324 28.4009Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M52.3018 24.9367C52.3306 24.7556 52.3267 24.7112 52.3018 24.9367C52.1803 25.0813 52.051 25.1373 51.8773 25.1971C51.6033 25.1317 51.3253 25.022 51.0512 24.9567C50.9025 24.791 50.9025 24.791 50.9547 24.8758C50.9547 24.8758 50.9586 24.9201 51.0029 24.9162C51.0551 25.001 51.0551 25.001 51.0029 24.9162C50.9508 24.8315 50.9508 24.8315 51.0029 24.9162C51.0068 24.9605 51.0629 25.0896 51.0629 25.0896C50.9624 24.9644 51.0434 24.868 51.059 25.0453C51.034 25.2708 51.0801 24.7755 51.0551 25.001C51.0629 25.0896 50.9452 25.2785 51.0956 24.9528C51.0185 25.0935 51.1766 24.8564 51.2171 24.8082C51.2576 24.76 51.3425 24.7079 51.4274 24.6558C51.2981 24.7118 51.3425 24.7079 51.5161 24.6481C51.8424 24.7982 52.1686 24.9484 52.5392 25.0946C52.4388 24.9694 52.2901 24.8038 52.1897 24.6786C51.8363 24.2182 51.1472 24.0104 50.6456 24.4115C50.1846 24.7644 49.9804 25.4968 50.3782 25.9533C50.4786 26.0785 50.6273 26.2442 50.7277 26.3694C50.9768 26.6602 51.3552 26.8952 51.7508 26.8159C52.4976 26.6614 53.0436 26.2564 53.2477 25.524C53.3865 25.0653 53.2993 24.5816 53.1679 24.1018C52.9321 23.4525 52.43 22.8265 51.6349 22.9406C50.8398 23.0547 50.2245 23.6891 50.1613 24.4985C50.0786 25.0863 50.4476 25.724 51.0362 25.8065C51.5361 25.8968 52.2191 25.5245 52.3018 24.9367Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.2208 18.4423C17.0397 19.6212 16.4824 20.7721 16.4827 20.9204C16.4829 21.0687 16.0915 22.0711 15.5145 22.1215C14.8931 22.1758 14.3621 21.7309 14.3078 21.1104C14.2012 20.4051 13.9982 19.619 14.2024 18.8866C14.3411 18.4279 14.6285 18.1348 15.0646 18.0074C15.5045 17.9243 15.9639 18.0628 16.2208 18.4423Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M9.23176 9.62937C9.2029 9.81054 9.24341 9.76234 9.23176 9.62937C9.22787 9.58505 9.26838 9.53686 9.26449 9.49253C9.30111 9.40001 9.33773 9.30749 9.26061 9.44821C9.29723 9.35569 9.33773 9.30749 9.32997 9.21885C9.40709 9.07813 9.43982 8.94129 9.51694 8.80058C9.55356 8.70806 9.55356 8.70806 9.51694 8.80058C9.55745 8.75238 9.59407 8.65986 9.67895 8.60778C9.42041 8.71969 9.16574 8.87592 8.90719 8.98782C9.04035 8.97619 9.04035 8.97619 8.86281 8.9917C8.99985 9.02439 8.95158 8.98395 8.77015 8.95514C8.53658 8.84156 8.33185 8.54682 8.30855 8.2809C8.33352 8.05541 8.32964 8.01109 8.29302 8.10361C8.36626 7.91857 8.36237 7.87425 8.32575 7.96677C8.28525 8.01497 8.16763 8.20389 8.28913 8.05929C8.41064 7.9147 8.24863 8.10749 8.20813 8.15569C8.26028 8.24045 8.21978 8.28865 8.13489 8.34073C8.09439 8.38893 8.05389 8.43713 8.01338 8.48532C7.80699 8.682 8.17928 8.33685 8.05389 8.43713C7.64109 8.83047 7.38476 9.47811 7.78645 9.97894C8.13598 10.395 8.87333 10.6432 9.33051 10.246C10.16 9.50362 11.2824 8.0211 10.0834 7.09865C9.74555 6.81555 9.29005 6.72136 8.84619 6.76014C8.22479 6.81442 7.90077 7.20001 7.63279 7.71469C7.23941 8.32964 7.03911 9.10636 7.01247 9.82325C7.01857 10.4033 7.64606 10.9291 8.2192 10.8343C8.8811 10.7319 9.24174 10.2537 9.23176 9.62937Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.2892 7.21977C16.318 7.03861 16.212 7.36049 16.1715 7.40869C16.0056 7.55716 16.2892 7.21977 16.1715 7.40869C15.9574 7.51672 16.3374 7.26021 16.1715 7.40869C16.3452 7.34886 15.9496 7.42807 16.2159 7.40481C15.9862 7.33556 16.3047 7.39705 16.2159 7.40481C16.1233 7.36824 16.4456 7.47406 16.2159 7.40481C16.1676 7.36437 16.4456 7.47406 16.2159 7.40481C16.2642 7.44525 16.2642 7.44525 16.1194 7.32392C16.0595 7.15052 16.0151 7.15439 16.0711 7.28348C16.1288 6.92116 16.1865 6.55883 16.2442 6.19651C16.4872 5.90732 16.713 5.93225 16.9466 6.04582C16.9949 6.08627 16.9949 6.08627 16.8984 6.00538C16.9949 6.08627 16.9988 6.13059 16.9427 6.0015C16.6298 5.49292 15.8597 5.38155 15.3987 5.73445C14.8932 6.09123 14.8183 6.76768 15.1312 7.27627C15.7532 8.24912 17.1602 8.48348 17.978 7.60815C18.2654 7.31508 18.3154 6.86412 18.1955 6.5173C17.4959 4.65803 14.4699 4.83306 14.1082 6.82972C13.8291 8.23857 16.0544 8.62474 16.2892 7.21977Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M25.279 7.88928C25.0515 8.35575 24.8723 8.86267 25.2296 9.36738C25.4382 9.70644 25.7722 9.94522 26.1389 10.0472C26.8685 10.2067 27.592 9.78624 27.8483 9.13861C27.9948 8.76853 28.0004 8.32144 27.7512 8.03058C27.3013 7.4893 26.7898 7.26603 26.1201 7.27987C25.7611 7.26657 25.4138 7.38623 25.0143 7.42113C24.4373 7.47154 23.903 8.00948 24.0018 8.6261C24.0966 9.1984 24.5871 9.69147 25.2085 9.63719C25.4748 9.61392 25.6928 9.55021 25.9592 9.52695C26.0035 9.52307 26.0923 9.51531 26.1367 9.51144C26.2737 9.54412 26.3142 9.49593 26.1367 9.51144C26.1811 9.50756 26.2699 9.4998 26.2737 9.54412C26.185 9.55188 26.1367 9.51144 26.0884 9.47099C26.0402 9.43055 25.9919 9.39011 25.9436 9.34966C25.9126 8.99509 25.8776 8.5962 25.8465 8.24164C25.8504 8.28596 25.806 8.28983 25.8099 8.33416C25.9237 8.10092 26.0934 7.99676 26.3193 8.0217C26.5334 7.91367 26.7148 7.94248 26.8635 8.10813C27.1049 8.31035 27.1493 8.30647 27.0488 8.18126C27.0799 8.53583 27.1149 8.93472 27.1459 9.28929C27.1825 9.19677 27.2597 9.05605 27.2963 8.96353C27.5643 8.44886 27.3207 7.71091 26.7648 7.49151C26.1972 7.13915 25.5431 7.33028 25.279 7.88928Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M33.1866 6.50352C33.2714 6.45144 33.3563 6.39937 33.4412 6.34729C33.5705 6.29134 33.5666 6.24702 33.4856 6.34341C33.2676 6.40712 33.0861 6.37831 32.8969 6.26086C32.8004 6.17997 32.7965 6.13565 32.7888 6.04701C32.7366 5.96225 32.9508 5.85422 32.7444 6.05089C32.7849 6.00269 32.8254 5.95449 32.9103 5.90241C33.0029 5.93898 32.999 5.89466 32.8659 5.90629C32.9585 5.94286 32.9585 5.94286 32.8176 5.86585C33.0029 5.93898 32.7655 5.78108 32.7172 5.74064C32.4758 5.53842 32.3233 5.32845 32.0819 5.12623C31.6436 4.71792 30.8929 4.82816 30.5284 5.26195C30.1234 5.74394 30.226 6.40487 30.6643 6.81319C31.1992 7.30238 31.6047 7.84754 32.3382 8.05142C33.2531 8.28412 34.2063 7.93288 34.669 7.08857C35.1762 6.24039 35.0386 5.18056 34.2663 4.53346C33.4901 3.84205 32.67 4.18165 31.9061 4.65033C31.3967 4.96279 31.2852 5.73176 31.6386 6.19215C31.9998 6.74118 32.6772 6.81598 33.1866 6.50352Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M40.5649 9.06462C41.1091 9.15106 41.6861 9.10065 42.1472 8.74775C42.5678 8.44304 42.8319 7.88405 42.8297 7.34832C42.7908 6.90511 42.5744 6.47741 42.2404 6.23863C41.7616 5.87851 41.1769 5.84028 40.6115 6.02365C40.0461 6.20702 39.7493 6.90286 39.9773 7.46352C40.2053 8.02418 40.8134 8.32834 41.4193 8.09677C41.593 8.03694 41.1086 8.12392 41.2861 8.10841C41.4637 8.0929 41.0159 8.08735 41.1047 8.0796C41.2861 8.10841 40.8267 7.9699 40.9677 8.04691C41.0603 8.08347 41.1125 8.16824 40.8267 7.9699C40.9233 8.05079 40.931 8.13943 40.7263 7.84469C40.7785 7.92946 40.7862 8.0181 40.6664 7.67128C40.6703 7.71561 40.6703 7.71561 40.6742 7.75993C40.6065 7.49788 40.6026 7.45356 40.6104 7.5422C40.6181 7.63084 40.6143 7.58652 40.6026 7.45356C40.6276 7.22807 40.591 7.32059 40.5987 7.40924C40.5621 7.50175 40.7491 7.08348 40.6315 7.27239C40.6315 7.27239 40.8301 6.98708 40.7086 7.13168C40.7086 7.13168 40.9594 6.93113 40.834 7.0314C40.7086 7.13168 41.133 6.87129 40.9632 6.97545C40.7935 7.0796 41.0481 6.92337 41.0964 6.96381L40.9632 6.97545C40.7857 6.99096 41.2778 6.99263 41.0076 6.97157C40.419 6.88902 39.7804 7.25743 39.6977 7.84523C39.5629 8.34828 39.9318 8.98595 40.5649 9.06462Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M49.7084 6.03974C49.7932 5.98766 49.8781 5.93559 50.0074 5.87963L50.0962 5.87188C50.2254 5.81592 50.1811 5.8198 50.0074 5.87963C49.8781 5.93559 49.7855 5.89902 49.6928 5.86246C49.6368 5.73337 49.5597 5.87409 49.6928 5.86246C49.6851 5.77381 49.8975 6.15719 49.9014 6.20151C49.8493 6.11675 49.8376 5.98379 49.9186 5.88739C49.9591 5.83919 49.9996 5.79099 50.0401 5.74279C50.1211 5.64639 49.8742 5.89127 50.0401 5.74279C49.9996 5.79099 50.2177 5.72728 49.9958 5.74667C49.9514 5.75055 49.6812 5.72949 49.8626 5.7583C49.9958 5.74667 49.6812 5.72949 49.7256 5.72561C49.5441 5.6968 49.7738 5.76606 49.6368 5.73337C49.5441 5.6968 49.4959 5.65636 49.4032 5.61979C49.5441 5.6968 49.4476 5.61592 49.3549 5.57935C49.411 5.70844 49.2584 5.49846 49.3549 5.57935C49.4032 5.61979 49.4304 5.93004 49.4592 5.74888C49.4493 5.12451 48.8295 4.68738 48.2525 4.73779C47.6311 4.79208 47.23 5.31839 47.24 5.94276C47.3182 7.85632 50.2482 8.62754 51.5309 7.44363C52.5185 6.46414 52.1318 5.11346 51.2031 4.21207C50.3264 3.39544 49.4176 3.7428 48.5244 4.26744C48.0151 4.5799 47.9479 5.34499 48.2569 5.80925C48.5216 6.2774 49.1508 6.31175 49.7084 6.03974Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M50.3933 17.9578C50.3955 18.4936 50.4904 19.0658 50.8033 19.5744C51.0119 19.9135 51.2976 20.1118 51.62 20.2177C52.1238 20.3523 52.5638 20.2692 52.9882 20.0088C53.6712 19.6365 54.1012 18.9291 54.0757 18.1274C54.0346 17.1485 53.1813 16.5978 52.2936 16.6753C51.7166 16.7257 51.1823 17.2637 51.281 17.8803C51.3759 18.4526 51.8664 18.9456 52.4878 18.8914C52.5321 18.8875 52.7097 18.872 52.5321 18.8875C52.3063 18.8625 52.6248 18.924 52.3951 18.8548C52.3024 18.8182 52.2581 18.8221 52.3024 18.8182C52.3951 18.8548 52.3468 18.8143 52.1576 18.6969C52.1576 18.6969 51.9568 18.4465 52.0572 18.5717C52.0572 18.5717 51.8969 18.2731 51.9529 18.4022C51.837 18.0997 51.9296 18.1362 51.893 18.2288C51.9008 18.3174 51.9585 17.9551 51.9218 18.0476C51.9218 18.0476 51.9296 18.1362 51.8852 18.1401C51.8852 18.1401 51.9951 17.8626 51.918 18.0033C51.9218 18.0476 51.8775 18.0515 51.8813 18.0958C51.8447 18.1883 51.999 17.9069 51.9585 17.9551C51.9141 17.9589 51.918 18.0033 51.8775 18.0515C51.8003 18.1922 52.0029 17.9512 52.0029 17.9512C52.0067 17.9955 51.9218 18.0476 51.8775 18.0515C51.7077 18.1556 51.8331 18.0553 51.8775 18.0515C51.8775 18.0515 52.1843 17.98 52.0511 17.9916C51.918 18.0033 52.2769 18.0166 52.2325 18.0204C52.4622 18.0897 52.5105 18.1301 52.4179 18.0936C52.3696 18.0531 52.4179 18.0936 52.5105 18.1301C52.6997 18.2476 52.607 18.211 52.5588 18.1706C52.4622 18.0897 52.7596 18.421 52.6592 18.2958C52.6032 18.1667 52.7635 18.4653 52.7191 18.4692L52.6592 18.2958C52.6592 18.2958 52.6071 18.211 52.6514 18.2072C52.6514 18.2072 52.723 18.5135 52.7114 18.3806C52.7036 18.2919 52.6997 18.2476 52.6919 18.159C52.6803 18.026 52.6686 17.893 52.657 17.7601C52.6509 17.18 52.0234 16.6543 51.4503 16.749C50.7845 16.8071 50.339 17.3373 50.3933 17.9578Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M45.9811 35.4929C46.6086 36.0187 47.4231 36.1262 48.1505 35.75C48.5344 35.5379 48.7253 35.1639 48.9162 34.7899C48.9972 34.6935 49.0299 34.5567 49.107 34.416C49.2574 34.0902 49.2302 33.78 49.1547 33.4293C48.7603 31.99 46.8767 31.9312 46.0744 32.9838C45.7137 33.4619 45.7315 34.1749 46.2103 34.5351C46.6891 34.8952 47.4032 34.8775 47.7638 34.3993L47.8448 34.303C47.8448 34.303 47.6345 34.4553 47.8043 34.3511C47.7599 34.355 47.5901 34.4592 47.7194 34.4032C47.675 34.4071 47.5863 34.4149 47.5419 34.4187C47.6306 34.411 47.6306 34.411 47.4975 34.4226C47.3161 34.3938 47.5457 34.4631 47.3604 34.3899C47.3122 34.3495 47.1269 34.2763 47.1712 34.2725C47.2195 34.3129 47.0708 34.1473 47.0226 34.1068C46.9704 34.0221 46.9704 34.0221 46.9743 34.0664C46.9821 34.155 46.9782 34.1107 46.9626 33.9334C46.9915 33.7523 47.0203 33.5711 47.0453 33.3456C46.9682 33.4863 46.9355 33.6232 46.8583 33.7639C46.8178 33.8121 46.7773 33.8603 46.7851 33.9489C46.7446 33.9971 46.627 34.186 46.7446 33.9971C46.9144 33.893 47.0398 33.7927 47.2095 33.6885C47.169 33.7367 47.1247 33.7406 47.0359 33.7484C47.1208 33.6963 47.2095 33.6885 47.3022 33.7251C47.1651 33.6924 47.2095 33.6885 47.3466 33.7212C47.4431 33.8021 47.4431 33.8021 47.3466 33.7212C46.9122 33.3572 46.1537 33.3788 45.7931 33.8569C45.4846 34.4198 45.4985 35.0885 45.9811 35.4929Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M7.58883 26.6099C7.4368 27.427 6.19049 28.1979 6.0341 28.2973C5.87772 28.3967 5.46716 28.4591 5.24302 28.4226C5.01889 28.386 4.31529 27.6301 4.23802 27.2593C4.16076 26.8885 3.97617 25.8957 4.24416 25.3811C4.6625 24.5406 5.5632 24.4198 6.4376 24.7007C7.26372 24.9412 7.78136 25.7445 7.58883 26.6099Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M56.7576 10.6033C53.3924 10.584 50.0565 10.3414 46.688 10.8805C41.5231 11.6885 36.272 11.5214 31.0839 11.4915C26.5969 11.4657 22.2534 12.1919 17.766 12.2219C14.6248 12.2596 11.5123 12.1859 8.37136 12.1678C6.99721 12.1599 5.6511 12.1521 4.27696 12.1442C3.63195 12.1405 1.02361 12.862 0.431457 13.4171C-0.639371 14.3046 1.36425 16.3162 1.3536 18.1592C1.34457 19.723 1.10958 21.5647 1.97442 22.3516C2.47663 22.8013 3.29184 22.4709 3.82467 22.474C4.80621 22.4796 5.78774 22.4853 6.76928 22.4909C10.3589 22.5116 14.2054 21.7518 17.7318 23.0009C19.6069 23.6819 21.7415 23.1357 23.6485 23.1466C25.892 23.1596 28.1635 23.1726 30.407 23.1856C33.8845 23.2056 37.3899 23.2258 40.8674 23.2458C42.1854 23.2534 43.5035 23.261 44.8216 23.2686C46.2518 23.2768 47.6005 22.8378 49.0033 22.7341C50.4065 22.5747 51.8406 21.9127 53.1909 21.1944C53.8942 20.8075 54.5947 20.9233 55.3238 20.9275C55.8286 20.9304 56.472 21.2133 56.8962 20.6014C57.3775 19.8223 57.2456 18.3694 57.4204 17.2534C57.7124 15.2444 57.6676 13.2894 57.6795 11.223\"\n        fill=\"#588054\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 40,\n  svg: bannerDots,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/greenLeaf.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Leaf', 'sticker name', 'web-stories');\n\nfunction GreenLeaf({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 62 58\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M8.81876 28.8347C8.59537 29.6885 8.30385 30.5547 8.23319 31.4341C8.15591 32.4239 8.16472 33.5267 8.41319 34.4792C8.68772 35.5216 8.8546 36.5859 9.29125 37.5721C9.78815 38.7027 10.3938 39.6436 11.1848 40.5896C11.6479 41.134 12.1586 41.6334 12.6068 42.2024C13.0755 42.8041 13.5046 43.4154 13.9733 44.0171C14.897 45.1987 15.7568 46.4963 16.988 47.3938C18.0445 48.158 19.1391 48.8376 20.39 49.2825C21.443 49.6541 22.5803 49.8211 23.6333 50.1927C24.2977 50.4287 24.978 50.4725 25.6056 50.7467C26.2932 51.044 27.1371 51.1065 27.8992 51.1597C28.5332 51.2022 28.9677 50.9751 29.5316 50.7123C29.7699 50.6083 30.0043 50.522 30.2426 50.4179C31.7056 49.7732 33.0574 48.7579 34.4082 47.9103C36.8919 46.3517 39.564 44.9482 41.762 43.0071C43.1666 41.7613 44.5261 40.4679 45.8023 39.0901C46.8391 37.984 47.9686 36.8805 48.7569 35.5962C49.4556 34.4594 49.8599 33.3858 50.0948 32.1149C50.2931 31.0035 50.6673 29.8577 50.7198 28.7316C50.77 27.8195 50.5612 26.9788 50.5255 26.0751C50.4731 24.9996 50.6266 23.9619 50.7419 22.8875C50.8278 22.1048 50.979 21.2812 50.9652 20.4851C50.9584 19.6999 50.8233 18.904 50.7592 18.1243C50.6699 16.9658 50.8437 15.8394 50.8293 14.6794C50.8282 14.0727 50.8707 13.4388 50.4268 12.9733C50.0526 12.5705 49.4143 12.4244 48.8703 12.3559C48.3903 12.2927 48.0601 12.1052 47.6113 11.9465C46.8201 11.6535 45.9458 11.3974 45.1194 11.2176C44.3106 11.0418 43.5979 11.1399 42.7665 11.2668C41.7199 11.4378 40.6555 11.6046 39.6033 11.7183C38.8196 11.8002 38.0344 11.8071 37.2482 11.9816C35.9305 12.2771 34.491 12.3301 33.231 12.8627C32.7147 13.0804 32.1696 13.1795 31.6369 13.3468C30.3807 13.7403 29.1534 14.2524 27.9096 14.714C26.5759 15.2018 25.2366 15.6322 23.933 16.1921C23.395 16.4235 23.0094 16.5592 22.4808 16.7087C21.5897 16.9339 20.8271 17.4124 19.9524 17.688C19.4306 17.8484 18.8718 17.9258 18.3432 18.0753C17.7246 18.2509 17.2122 18.3296 16.5782 18.2871C15.5529 18.2017 14.2266 18.29 13.3513 18.9759C12.6257 19.5375 12.0113 20.4697 11.6146 21.2652C11.2099 22.0961 10.7439 22.9503 10.5478 23.8477C10.4464 24.2909 10.1568 24.7004 9.97352 25.1342C9.75631 25.6349 9.75653 25.7563 9.64292 26.2527C9.60918 26.4409 9.55215 26.5677 9.53614 26.76C9.55965 26.9426 9.43598 27.1569 9.41313 27.3382C9.36978 27.4869 9.28457 27.8592 9.16069 27.9521C8.96655 28.3928 8.94326 28.3315 8.81876 28.8347Z\"\n        fill=\"#588054\"\n      />\n      <path\n        d=\"M16.3359 46.2802C19.4606 42.4698 22.6026 38.6258 26.217 35.2582C29.8654 31.8569 34.0747 29.2257 38.1935 26.4521C40.5411 24.8709 42.8802 23.298 45.236 21.7251C45.5496 21.5137 45.2709 20.9943 44.9488 21.2141C40.7877 24.0131 36.61 26.7954 32.4486 29.6111C28.3296 32.4015 24.708 35.6767 21.383 39.3872C19.4989 41.4871 17.7059 43.6789 15.9215 45.8622C15.674 46.1573 16.0884 46.5753 16.3359 46.2802Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M22.6187 38.6761C22.6171 37.534 22.5068 36.3503 22.1601 35.2685C21.7972 34.1364 21.1116 33.2746 20.3339 32.3879C18.6958 30.5142 17.7178 28.268 17.5581 25.7576C17.5379 25.3798 16.9417 25.3741 16.9701 25.7603C17.1084 27.9936 17.8357 30.1403 19.1727 31.9145C19.9072 32.8938 20.8706 33.7124 21.3678 34.8439C21.8895 36.034 22.0226 37.3939 22.0224 38.6705C22.0258 39.0484 22.622 39.054 22.6187 38.6761Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M27.8873 33.4533C27.6809 30.6576 27.2725 27.8964 27.0997 25.1006C26.9418 22.4558 26.9605 19.7851 27.8427 17.2363C27.9735 16.8746 27.4044 16.7261 27.2736 17.0878C26.4001 19.6113 26.3563 22.2738 26.4977 24.9018C26.6612 27.7565 27.077 30.5932 27.291 33.4476C27.3195 33.8338 27.9074 33.8311 27.8873 33.4533Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M20.3463 41.5587C21.2648 41.3277 22.1518 41.5756 23.0393 41.7899C23.8514 41.9793 24.6562 42.0932 25.4968 42.0389C27.3125 41.9298 29.0515 41.2667 30.7399 40.6207C31.0944 40.4847 30.9594 39.9058 30.5963 40.0503C28.8488 40.7218 27.0251 41.4356 25.1434 41.4611C23.4801 41.4855 21.8797 40.5691 20.2027 40.9883C19.832 41.074 19.9756 41.6444 20.3463 41.5587Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M24.8572 36.457C27.6559 36.3182 30.4461 36.1878 33.2448 36.0489C35.6233 35.9288 38.2583 36.1015 40.4809 35.0751C40.8274 34.9139 40.5402 34.4029 40.1937 34.5641C39.0698 35.0816 37.8667 35.2299 36.6395 35.3027C35.3534 35.3842 34.0677 35.4321 32.7818 35.4968C30.1428 35.6265 27.5038 35.7562 24.8565 35.8775C24.487 35.8792 24.4706 36.4756 24.8572 36.457Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M36.8878 26.752C36.33 24.4871 35.7722 22.2221 35.2059 19.9655C35.11 19.5965 34.5369 19.7503 34.6327 20.1193C35.1905 22.3843 35.7483 24.6493 36.3146 26.9058C36.4019 27.2834 36.9751 27.1296 36.8878 26.752Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M33.4489 29.5477C34.3928 29.9381 35.3734 30.0932 36.3995 29.9877C37.493 29.8651 38.6091 29.3057 39.7064 29.5274C40.0834 29.6012 40.2422 29.0294 39.8652 28.9556C38.9103 28.7584 38.0075 29.0733 37.0725 29.2707C35.9439 29.5111 34.8105 29.4743 33.7582 29.0256C33.4157 28.8844 33.0981 29.3982 33.4489 29.5477Z\"\n        fill=\"#4C664A\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 62 / 58,\n  svg: GreenLeaf,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/greenLeafShape.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Leaf Shape', 'sticker name', 'web-stories');\n\nfunction GreenLeafShape({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M3.31844 49.9977C3.20557 48.6149 2.69763 47.3169 2.38722 45.9624C1.9075 43.9306 1.82284 41.8706 1.3149 39.8671C0.919834 38.2304 0.694083 36.4808 0.581207 34.8159C0.468331 32.897 0.299018 30.9217 0.24258 29.0028C0.186142 26.9428 0.524769 24.2056 1.68175 22.4278C2.30256 21.4965 3.06447 20.6782 3.68529 19.747C4.02392 19.239 4.4472 18.9004 4.84227 18.4771C5.35021 17.9127 5.6324 17.2355 6.0839 16.6711C7.77704 14.4418 10.2321 13.2002 12.5178 11.7046C16.017 9.39062 19.9958 8.00789 23.8054 6.31476C26.7684 4.98847 29.9289 4.22656 32.8919 2.87205C34.4721 2.16657 36.1371 1.63042 37.6327 0.783847C38.3664 0.360563 39.4669 0.16303 40.3135 0.106593C41.8655 -0.00628317 44.1795 -0.232035 45.5058 0.727409C46.7192 1.6022 47.9608 2.67452 48.9485 3.80327C50.049 5.04491 50.0208 5.94791 48.9485 7.18955C47.0014 9.44706 44.5745 10.9427 42.1759 12.664C40.765 13.6799 39.8902 14.5829 39.4951 16.3325C38.7896 19.4648 37.7455 22.6817 36.2782 25.5601C35.6009 26.9146 34.8954 28.1844 34.2464 29.5672C33.8231 30.5266 33.4281 31.5143 32.9483 32.4455C32.2993 33.7436 31.8478 35.3803 30.4368 35.9164C28.2358 36.7348 26.3451 38.0046 24.0876 38.7383C23.1564 39.0487 22.4791 39.5849 21.6325 40.0646C18.3309 41.8988 14.7471 43.3098 11.5866 45.398C10.8247 45.9059 9.86524 46.0752 9.01867 46.4421C8.28498 46.7525 7.63594 47.204 6.90225 47.5144C6.05568 47.853 5.51952 48.2199 4.84227 48.8125C4.50364 49.0664 3.79817 50.0541 3.31844 49.9977Z\"\n        fill=\"#4A6747\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: GreenLeafShape,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/greenRoundBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Round Banner', 'sticker name', 'web-stories');\n\nfunction GreenRoundBanner({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M9.78162 2.67951C6.66433 3.67231 4.20211 6.38437 2.80159 9.50808C1.40106 12.6318 0.971867 16.2156 0.949278 19.7025C0.926689 24.1096 1.58177 28.5894 3.36631 32.5606C6.37067 39.2439 12.3342 43.9415 18.7043 46.8715C25.5037 49.9952 33.4098 51.3028 40.2543 48.3244C44.5915 46.4357 48.2283 42.8761 50.8035 38.6627C54.1467 33.166 55.7279 26.3858 54.7792 19.9205C53.8304 13.4551 50.171 7.37718 44.8625 4.15661C42.0163 2.43736 38.8086 1.5172 35.5784 0.936041C26.6783 -0.734781 18.3881 -0.17784 9.78162 2.67951Z\"\n        fill=\"#414C40\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 50,\n  svg: GreenRoundBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as makerYellowLeaf } from './yellowLeaf';\nimport { default as makerGreenLeafShape } from './greenLeafShape';\nimport { default as makerGreenLeaf } from './greenLeaf';\nimport { default as makerYellowDots } from './yellowDots';\nimport { default as makerBannerWithDots } from './bannerWithDots';\nimport { default as makerRoundedBannerWithDots } from './roundedBannerWithDots';\nimport { default as makerPlant } from './plant';\nimport { default as makerOffWhiteSectionSeparator } from './offWhiteSectionSeparator';\nimport { default as makerOffWhiteBanner } from './offWhiteBanner';\nimport { default as makerGreenRoundBanner } from './greenRoundBanner';\nimport { default as makerYellowRoundBanner } from './yellowRoundBanner';\nimport { default as makerSquigglyLine } from './squigglyLine';\nimport { default as makerWavyLine } from './wavyLine';\n\nexport {\n  makerYellowLeaf,\n  makerGreenLeafShape,\n  makerGreenLeaf,\n  makerYellowDots,\n  makerBannerWithDots,\n  makerPlant,\n  makerOffWhiteSectionSeparator,\n  makerOffWhiteBanner,\n  makerGreenRoundBanner,\n  makerSquigglyLine,\n  makerWavyLine,\n  makerRoundedBannerWithDots,\n  makerYellowRoundBanner,\n};\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/offWhiteBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Off-white Banner', 'sticker name', 'web-stories');\n\nfunction OffWhiteBanner({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 51 12\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M50.0394 0.524213C47.1156 0.507352 44.2173 0.29626 41.2907 0.765326C36.8034 1.46836 32.2413 1.32301 27.7338 1.29701C23.8354 1.27453 20.0617 1.90635 16.1631 1.93246C13.434 1.96532 10.7297 1.90113 8.00089 1.88539C6.80702 1.87851 5.63751 1.87176 4.44364 1.86488C3.88325 1.86165 1.61709 2.48944 1.10263 2.97242C0.172287 3.74457 1.91305 5.49486 1.9038 7.09842C1.89596 8.45902 1.69179 10.0615 2.44317 10.7461C2.8795 11.1374 3.58776 10.8499 4.05069 10.8526C4.90346 10.8575 5.75622 10.8624 6.60899 10.8673C9.72768 10.8853 13.0696 10.2243 16.1334 11.311C17.7624 11.9035 19.617 11.4283 21.2738 11.4378C23.223 11.4491 25.1965 11.4605 27.1457 11.4717C30.1669 11.4891 33.2125 11.5067 36.2337 11.5241C37.3789 11.5307 38.524 11.5373 39.6692 11.5439C40.9118 11.5511 42.0835 11.1691 43.3023 11.0789C44.5214 10.9402 45.7674 10.3642 46.9405 9.73927C47.5516 9.40264 48.1602 9.50334 48.7936 9.50699C49.2322 9.50952 49.7912 9.75571 50.1597 9.2233C50.5779 8.54539 50.4633 7.28128 50.6151 6.31026C50.8689 4.56233 50.8299 2.8613 50.8403 1.06337\"\n        fill=\"#F3E9D4\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 51 / 12,\n  svg: OffWhiteBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/offWhiteSectionSeparator.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Off-white Section Separator', 'sticker name', 'web-stories');\n\nfunction OffWhiteSectionSeparator({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 62 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M61.0541 4.68684C60.831 6.20747 60.6096 7.7164 60.3865 9.23703C60.2269 10.3249 60.1446 11.436 59.8534 12.5045C59.5621 13.573 59.0997 14.6165 58.7443 15.6637C57.8944 18.1559 57.194 20.7298 55.7723 22.9948C55.2085 23.9039 54.6046 24.9027 53.8668 25.7147C53.2566 26.39 52.5709 27.0303 51.9475 27.7037C51.2944 28.3966 50.7472 29.0094 49.7408 29.2682C49.0974 29.4368 48.589 29.6012 47.9782 29.8224C47.0537 30.1649 45.8526 29.9172 44.8794 29.8582C42.7091 29.7075 40.6007 29.4105 38.4378 29.1174C37.4881 28.9902 36.5789 28.6777 35.6309 28.5388C34.7882 28.4153 34.0944 28.469 33.2523 28.5248C31.4873 28.6366 29.6393 28.3061 27.9431 28.7744C27.6346 28.8607 27.3684 29.0248 27.0387 29.0721C26.6677 29.1252 26.2859 29.0693 25.9052 29.0971C25.1157 29.1607 24.4213 29.3099 23.6141 29.3111C21.583 29.3121 19.5347 29.1554 17.5018 29.1681C16.4919 29.1755 16.019 28.915 15.3228 28.2514C14.2367 27.22 13.1867 26.2178 12.0376 25.2489C11.3901 24.7119 10.7809 24.0969 10.1815 23.5072C9.71139 23.044 9.07247 22.7234 8.76956 22.1293C8.26796 21.1478 7.95126 20.0977 7.41989 19.1356C6.98471 18.343 6.36866 17.7748 5.71024 17.1286C5.21728 16.6382 4.65964 16.2219 4.34528 15.6143C3.54535 14.0991 2.98013 12.451 2.75095 10.8043C2.63235 9.9625 2.251 9.2614 1.97726 8.46852C1.78771 7.92696 1.45219 7.55518 1.21627 7.05462C0.98207 6.54235 0.976856 6.0278 0.948742 5.48599C0.909737 4.83505 1.27895 4.51875 1.8428 4.15927C2.85143 3.51847 4.04156 3.10738 5.22311 2.75478C7.95258 1.93599 11.0073 1.55915 13.8656 1.23718C16.0135 0.990341 18.1769 1.18787 20.3277 1.01314C24.7266 0.642096 29.0767 -0.130389 33.5203 0.0189082C35.4341 0.084271 37.3679 0.379597 39.2623 0.669135C40.9855 0.93359 42.5426 0.863048 44.2698 0.73378C45.9706 0.600653 47.6233 0.795046 49.3207 0.960135C50.8962 1.13125 52.4877 1.10159 54.0792 1.34675C54.8692 1.46252 55.6627 1.55489 56.4493 1.69405C57.1191 1.80415 57.7334 2.10924 58.3563 2.35585C58.5092 2.41409 58.6305 2.50357 58.7851 2.55012C59.132 2.6607 59.5642 2.55675 59.8894 2.72389C60.2146 2.89103 60.2261 3.17948 60.3761 3.44043C60.5914 3.80654 60.9309 4.05942 60.8772 4.51753\"\n        fill=\"#F3E9D4\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 62 / 30,\n  svg: OffWhiteSectionSeparator,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/plant.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Plant', 'sticker name', 'web-stories');\n\nfunction MakerPlant({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 32 52\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <g clipPath=\"url(#clip0)\">\n        <path\n          d=\"M17.3777 49.817C17.9123 48.4785 18.6975 47.262 19.3665 45.9748C20.0718 44.6485 20.546 43.2182 21.0973 41.8226C22.1816 39.0508 23.3082 36.3904 23.8171 33.4151C24.0799 31.8989 24.2097 30.369 24.4151 28.8362C24.6373 27.2463 24.9734 25.6707 25.2711 24.0779C25.8861 20.9102 26.1596 17.7181 26.5849 14.539C26.8201 12.7979 27.1693 11.0713 27.4234 9.32952C27.6942 7.53062 27.6997 5.72317 27.9327 3.92574C28.0046 3.33937 27.0877 3.11137 27.0165 3.71654C26.8293 5.22982 26.812 6.73651 26.6248 8.2498C26.4397 9.81947 26.1217 11.3755 25.88 12.9474C25.3762 16.0542 25.1768 19.2058 24.6533 22.2946C24.1117 25.403 23.5316 28.494 23.123 31.616C22.7311 34.6809 21.8414 37.5957 20.627 40.4289C19.985 41.9222 19.5158 43.484 18.8163 44.9607C18.0987 46.4569 17.1493 47.8303 16.5472 49.3785C16.3228 49.9332 17.1533 50.3716 17.3777 49.817Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M17.4395 49.9464C17.5402 48.1541 17.8887 46.4086 17.9706 44.617C18.0706 42.8059 18.1895 40.9941 18.1566 39.1693C18.1259 37.4009 18.0196 35.6355 18.1022 33.8627C18.184 32.0711 18.2681 30.3359 18.1611 28.5517C17.9448 24.9268 17.9175 21.2946 17.7579 17.6675C17.6908 15.9382 17.4167 14.2357 17.2929 12.5086C17.2238 11.7017 17.3051 10.8703 17.1982 10.0649C17.0884 9.18441 16.7722 8.34954 16.7379 7.46608C16.6957 6.86531 15.7512 6.90193 15.7934 7.50271C15.8473 8.40423 16.1439 9.22104 16.2537 10.1016C16.3606 10.9069 16.2982 11.7376 16.3484 12.5452C16.4722 14.2723 16.7274 15.9755 16.8134 17.7041C16.973 21.3312 17.0003 24.9634 17.2166 28.5883C17.3236 30.3726 17.2395 32.1077 17.1577 33.8993C17.0751 35.6721 17.1814 37.4376 17.2121 39.2059C17.2451 41.0307 17.1261 42.8426 17.0261 44.6537C16.9442 46.4452 16.5965 48.2095 16.495 49.983C16.4616 50.5867 17.4061 50.5501 17.4395 49.9464Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M16.8874 50.3442C16.7962 47.5052 16.5372 44.7291 15.5436 42.0379C14.5719 39.4212 14.2359 36.6105 13.3383 33.9533C12.4196 31.2404 11.9542 28.51 11.4489 25.7246C11.1843 24.2665 10.9945 22.7867 10.7676 21.3271C10.5378 19.7923 10.1765 18.2815 10.0979 16.7409C10.0745 16.1394 9.13003 16.176 9.15336 16.7775C9.23203 18.3181 9.59404 19.8477 9.8231 21.3637C10.0064 22.6744 10.1903 24.0038 10.4114 25.313C10.8985 28.1179 11.3275 30.8874 12.2273 33.601C12.6554 34.8834 13.1024 36.165 13.4186 37.4893C13.7385 38.9076 13.9087 40.3694 14.416 41.7428C14.9015 43.0417 15.1988 44.3668 15.5347 45.7092C15.9359 47.275 15.9005 48.8012 15.9625 50.3989C15.9662 50.9824 16.9107 50.9457 16.8874 50.3442Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M16.7057 50.5396C16.6432 49.9019 16.4113 49.2897 16.2362 48.6752C16.0617 48.0796 15.71 47.792 15.2958 47.3563C14.2306 46.2304 13.4552 44.7733 12.4815 43.5686C11.5078 42.3639 10.9837 41.0476 10.3246 39.6613C9.62402 38.1824 9.07602 36.7353 8.65515 35.1515C8.21393 33.5308 7.586 31.9738 7.33223 30.3082C7.07845 28.6426 6.82613 27.0146 6.55346 25.3497C6.00958 22.0576 5.36834 18.6939 5.14413 15.3517C4.88865 11.6907 4.6891 8.00863 4.54622 4.32442C4.52289 3.72292 3.5784 3.75954 3.60172 4.36105C3.66587 6.01519 3.73002 7.66932 3.79417 9.32346C3.85686 10.94 4.14551 12.529 4.17042 14.147C4.2217 17.4206 4.89781 20.7076 5.40172 23.9448C5.65549 25.6104 6.06039 27.2702 6.2575 28.938C6.43207 30.5125 6.71561 31.9699 7.20912 33.4756C7.70264 34.9813 7.99055 36.5515 8.59595 38.0152C9.15992 39.3864 9.80018 40.7735 10.4383 42.1042C11.1584 43.6011 12.3974 44.8143 13.321 46.1904C13.7221 46.7773 14.1247 47.4017 14.5992 47.9292C15.251 48.6381 15.7037 49.5807 15.7983 50.5559C15.8224 51.1762 16.7668 51.1396 16.7057 50.5396Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M25.9567 16.3894C26.7682 16.3391 27.5209 16.2346 28.2634 15.867C28.8017 15.6014 28.2974 14.7926 27.7598 15.077C27.1844 15.3629 26.5625 15.4247 25.9399 15.4676C25.3158 15.473 25.3522 16.4129 25.9567 16.3894Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M25.5431 20.3587C24.5041 20.399 23.5298 20.1544 22.5061 20.1C21.8995 20.067 21.9359 21.0069 22.5426 21.0398C23.5852 21.0935 24.5406 21.3389 25.5795 21.2986C26.184 21.2751 26.1476 20.3353 25.5431 20.3587Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M24.0466 27.1374C24.8567 27.539 25.7002 27.3368 26.5684 27.2843C27.1729 27.2609 27.1364 26.321 26.532 26.3445C25.8897 26.3694 25.1043 26.6069 24.5056 26.2913C23.9469 26.0306 23.506 26.8572 24.0466 27.1374Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M23.2526 33.4935C23.7467 34.0391 24.6635 33.7776 25.3051 33.7339C25.9088 33.6917 25.8724 32.7518 25.2686 32.794C25.0042 32.8043 24.76 32.8514 24.4956 32.8617C24.3256 32.8683 24.0248 32.9176 23.9063 32.7904C23.4922 32.3547 22.8565 33.0382 23.2526 33.4935Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M16.3246 13.3932C15.8305 13.3371 15.3706 13.1855 14.8621 13.2429C14.259 13.3039 14.2955 14.2438 14.8985 14.1827C15.3126 14.129 15.6962 14.2647 16.0951 14.3057C16.3421 14.3338 16.603 14.2296 16.6683 13.9635C16.7162 13.7357 16.5716 13.4213 16.3246 13.3932Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M17.551 19.1628C18.061 19.143 18.5522 19.1239 19.0622 19.1041C19.6667 19.0807 19.6302 18.1409 19.0258 18.1643C18.5157 18.1841 18.0246 18.2031 17.5146 18.2229C16.9101 18.2463 16.9465 19.1862 17.551 19.1628Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M17.1301 22.9441C16.3745 22.9734 15.6189 23.0027 14.8633 23.032C14.2588 23.0554 14.2953 23.9953 14.8998 23.9718C15.6554 23.9425 16.411 23.9132 17.1666 23.8839C17.771 23.8605 17.7346 22.9206 17.1301 22.9441Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M18.0248 31.3808C18.346 31.3683 18.6482 31.3566 18.9693 31.3442C19.5738 31.3207 19.5374 30.3809 18.9329 30.4043C18.6118 30.4168 18.3095 30.4285 17.9884 30.4409C17.3839 30.4644 17.4204 31.4042 18.0248 31.3808Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M9.64295 21.5965C9.27244 21.7991 8.90193 22.0018 8.53142 22.2044C8.30912 22.326 8.26484 22.6477 8.3862 22.8501C8.52717 23.0705 8.81271 23.1159 9.03502 22.9943C9.40552 22.7917 9.77603 22.5891 10.1465 22.3865C10.3688 22.2649 10.4131 21.9432 10.2918 21.7408C10.1508 21.5204 9.88414 21.4742 9.64295 21.5965Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M11.1055 27.1122C11.5995 27.1683 12.0594 27.3199 12.568 27.2625C12.8128 27.2342 13.0322 27.0375 13.022 26.7743C13.0125 26.5299 12.7953 26.2936 12.5315 26.3227C12.1174 26.3764 11.7338 26.2407 11.3349 26.1997C11.0879 26.1716 10.8271 26.2758 10.7617 26.5419C10.7138 26.7697 10.8584 27.0841 11.1055 27.1122Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M12.0448 32.3091C11.6097 32.7966 10.6942 32.6062 10.1275 32.6282C9.52304 32.6516 9.55949 33.5915 10.164 33.5681C11.0525 33.5524 12.0988 33.7001 12.7511 32.9594C13.1492 32.4922 12.4436 31.8607 12.0448 32.3091Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M3.43508 7.86905C2.82186 7.66693 2.24277 7.36936 1.58016 7.35741C0.974227 7.34326 1.01068 8.28311 1.61661 8.29726C2.16588 8.31361 2.70719 8.61264 3.20561 8.78157C3.78106 8.98515 3.99091 8.05458 3.43508 7.86905Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M4.06916 12.0236C4.4797 12.3654 5.07185 12.5119 5.4279 12.9122C5.6052 13.0936 5.9256 13.0623 6.08905 12.8866C6.27066 12.6913 6.24083 12.41 6.06354 12.2287C5.68786 11.8103 5.13495 11.6999 4.70479 11.3401C4.25429 10.9434 3.59977 11.6277 4.06916 12.0236Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M4.93759 19.2941C4.19293 19.6054 3.39517 19.5233 2.62069 19.5534C2.01621 19.5768 2.05266 20.5167 2.65714 20.4932C3.52607 20.4595 4.41827 20.5379 5.23704 20.1861C5.79571 19.9574 5.51516 19.0646 4.93759 19.2941Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M6.0358 28.0995C5.69797 28.1691 5.38268 28.3319 5.0412 28.3075C4.7949 28.2982 4.5777 28.5514 4.58718 28.7957C4.59738 29.0589 4.81246 29.2388 5.07765 29.2473C5.51358 29.2681 5.9037 29.0835 6.33525 28.9915C6.57937 28.9444 6.71809 28.619 6.63378 28.3963C6.54802 28.1361 6.29881 28.0516 6.0358 28.0995Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M9.66352 40.1765C10.2273 40.0793 10.7896 39.9445 11.3563 39.9226C11.9608 39.8991 11.9244 38.9593 11.3199 38.9827C10.7532 39.0047 10.1909 39.1394 9.62707 39.2366C9.38296 39.2837 9.16212 39.4429 9.17305 39.7248C9.1818 39.9504 9.41941 40.2236 9.66352 40.1765Z\"\n          fill=\"#588054\"\n        />\n        <path\n          d=\"M26.0196 2.88917C26.0459 3.56587 25.9065 4.36193 26.4006 4.90753C26.7378 5.30861 27.3931 5.62205 27.9068 5.69626C29.0482 5.85907 29.2834 4.60748 29.2877 3.74135C29.2847 3.17671 29.2069 2.63379 28.7753 2.23637C28.3829 1.87508 27.8118 1.78428 27.3069 1.93564C26.4097 2.21516 25.7174 3.39035 25.6958 4.2948C25.6632 5.40676 27.0081 5.93819 27.9366 5.48802C28.8091 5.05885 29.0472 3.393 28.3046 2.78174C27.522 2.11555 26.4345 2.85426 26.2413 3.72771C26.1288 4.24036 26.3381 4.75935 26.7842 5.04325C27.367 5.43481 27.9583 5.07302 28.2198 4.49812C28.4123 4.09533 28.6149 3.46624 28.0939 3.20406C27.6115 2.95922 27.1342 3.33541 26.8843 3.7216C26.4565 4.39708 26.1813 6.0832 27.4927 5.74997C28.0928 5.61374 27.7926 4.70294 27.2121 4.85723C27.5681 4.76813 27.3582 5.20925 27.4403 4.88604C27.4548 4.77252 27.4889 4.67707 27.5223 4.56282C27.5564 4.46737 27.8267 4.11804 27.8245 4.06165C27.7075 3.97206 27.6087 3.86294 27.4917 3.77335C27.475 3.83047 27.4576 3.8688 27.4409 3.92592C27.3501 4.02357 27.3988 4.30406 27.2048 4.17981C27.0304 4.07362 27.2439 3.72648 27.3347 3.62883C27.4256 3.53119 27.573 3.43134 27.69 3.52093C27.9225 3.66252 27.7526 4.15856 27.6843 4.34946C27.5834 4.67341 27.4155 4.73639 27.0733 4.69319C26.8074 4.66585 26.6352 4.61605 26.6243 4.3341C26.6075 3.90177 26.9816 3.30367 27.2925 3.02806C27.5308 2.83057 27.849 2.74293 28.1033 2.95897C28.3184 3.13888 28.3112 3.44036 28.3214 3.70352C28.3331 4.00427 28.4007 4.77349 28.004 4.78887C27.7585 4.79839 27.2164 4.48056 27.0762 4.27892C26.8364 3.94937 26.9802 3.26608 26.9648 2.87134C26.9401 2.23224 25.9956 2.26887 26.0196 2.88917Z\"\n          fill=\"white\"\n        />\n        <path\n          d=\"M2.5787 3.83602C2.52793 4.47804 3.01913 4.94845 3.64687 5.03706C4.33128 5.12347 5.00038 4.81514 5.25894 4.16505C5.50226 3.60969 5.54283 2.7045 5.31317 2.14865C5.04063 1.46268 4.21962 1.26862 3.60864 1.61234C2.47969 2.25853 1.9554 4.34965 3.50662 4.83542C4.75123 5.22013 6.14956 3.2269 5.12938 2.28755C4.65852 1.854 3.92546 1.97656 3.64436 2.53339C3.39813 3.01358 3.44253 3.67074 3.68817 4.15067C3.78991 4.33498 4.03839 4.40064 4.2251 4.33693C4.73003 4.18557 5.16224 3.62287 4.93332 3.08582C4.84974 2.88198 4.69424 2.77506 4.46684 2.76505C4.37166 2.74992 4.25832 2.75431 4.14425 2.73991C3.53759 2.70696 3.57403 3.64681 4.1807 3.67976C4.29477 3.69416 4.38922 3.6905 4.50328 3.7049C4.34779 3.59798 4.1923 3.49106 4.03681 3.38414C4.01937 3.42246 3.98232 3.44273 3.94454 3.44419C4.11747 3.51279 4.30928 3.58065 4.48148 3.63045C4.41971 3.50107 4.41096 3.2755 4.44291 3.12366C4.45742 3.01015 4.51118 2.93276 4.4734 2.93423C4.45451 2.93496 4.49593 3.02748 4.49812 3.08387C4.49089 3.38535 4.334 3.73029 4.05649 3.89166C3.61188 4.1348 3.41927 3.55869 3.5006 3.21668C3.56449 2.913 3.81364 2.508 4.11224 2.4023C4.55976 2.23434 4.4901 2.8771 4.48142 3.14099C4.47565 3.48007 4.49314 3.9312 4.12045 4.07743C3.85963 4.18167 3.51743 4.13847 3.54209 3.79866C3.57543 3.19495 2.63166 3.25038 2.5787 3.83602Z\"\n          fill=\"white\"\n        />\n        <path\n          d=\"M8.85956 14.5675C8.20644 14.7999 8.02854 15.5787 8.16593 16.1946C8.30551 16.8669 8.96381 17.2555 9.60971 17.3246C11.1297 17.4915 11.6438 15.6267 10.8648 14.5651C10.1054 13.5215 8.52452 13.7334 8.19629 15.0262C8.06486 15.5396 8.16374 16.1382 8.5198 16.5385C8.93471 16.9931 9.65909 17.1344 10.1742 16.7568C10.7996 16.2995 10.8918 15.2606 10.341 14.7172C9.5744 13.9751 8.85817 15.0194 8.92511 15.7698C8.98622 16.3698 9.93071 16.3332 9.8696 15.7332C9.8696 15.7332 9.87756 15.4505 9.89645 15.4498C9.94948 15.3536 9.89208 15.337 9.72571 15.4376C9.74606 15.4744 9.74679 15.4932 9.76714 15.5301C9.7163 15.6826 9.81731 15.8482 9.67056 15.9668C9.4875 16.1245 9.25426 15.9641 9.17141 15.7791C9.00644 15.4278 9.18944 14.7806 9.64499 14.8195C10.2713 14.8705 10.5155 15.8023 10.1537 16.2304C9.93727 16.5024 9.49843 16.4065 9.24557 16.228C9.08935 16.1023 8.95414 15.5428 9.14012 15.4603C9.70026 15.2691 9.41897 14.3576 8.85956 14.5675Z\"\n          fill=\"white\"\n        />\n        <path\n          d=\"M14.6913 7.86539C14.6406 8.50742 15.1318 8.97783 15.7595 9.06643C16.4439 9.15284 17.113 8.84451 17.3716 8.19443C17.6149 7.63906 17.6366 6.7346 17.4069 6.17875C17.1344 5.49279 16.3134 5.29872 15.7024 5.64245C14.5923 6.28791 14.068 8.37902 15.6004 8.86553C16.845 9.25024 18.2433 7.25701 17.2231 6.31766C16.7523 5.88411 16.0192 6.00667 15.7381 6.5635C15.4919 7.04368 15.5363 7.70085 15.7819 8.18078C15.8837 8.36508 16.1321 8.43075 16.3189 8.36703C16.8238 8.21567 17.256 7.65298 17.0271 7.11592C16.9435 6.91209 16.788 6.80516 16.5606 6.79516C16.4465 6.78076 16.3521 6.78442 16.238 6.77002C15.6313 6.73707 15.6678 7.67692 16.2745 7.70987C16.3885 7.72427 16.483 7.72061 16.597 7.73501C16.4415 7.62809 16.2861 7.52117 16.1306 7.41424C16.1131 7.45257 16.0761 7.47283 16.0383 7.4743C16.2112 7.54289 16.403 7.61076 16.5752 7.66055C16.4946 7.5319 16.5047 7.30561 16.5178 7.1545C16.5323 7.04098 16.586 6.9636 16.5483 6.96506C16.5294 6.9658 16.5708 7.05832 16.573 7.11471C16.5658 7.41619 16.4089 7.76113 16.1314 7.9225C15.6867 8.16564 15.4941 7.58953 15.5755 7.24752C15.6394 6.94384 15.8885 6.53884 16.1871 6.43314C16.6346 6.26518 16.565 6.90794 16.5563 7.17183C16.5505 7.51091 16.568 7.96204 16.1953 8.10827C15.9345 8.21251 15.5923 8.1693 15.617 7.82949C15.6881 7.22433 14.7436 7.26096 14.6913 7.86539Z\"\n          fill=\"white\"\n        />\n      </g>\n      <defs>\n        <clipPath id=\"clip0\">\n          <rect\n            width=\"28.2805\"\n            height=\"50\"\n            fill=\"white\"\n            transform=\"translate(0.90155 1.56665) rotate(-2.22089)\"\n          />\n        </clipPath>\n      </defs>\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 32 / 52,\n  svg: MakerPlant,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/roundedBannerWithDots.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Rounded Banner With Dots', 'sticker name', 'web-stories');\n\nfunction RoundedBannerWithDots({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M35.3985 38.5215C35.3971 37.9658 35.3459 37.4102 35.3445 36.8544C35.3443 36.7618 35.3435 36.4376 35.3934 36.4375L35.3437 36.5303C35.1442 36.5771 35.0943 36.5772 34.9444 36.5312C34.8446 36.5315 34.8944 36.485 34.9443 36.4849C34.9942 36.4848 34.8449 36.6704 34.795 36.6705C34.8449 36.6704 34.6455 36.7635 34.6455 36.7635C34.5956 36.7636 34.5457 36.8101 34.4958 36.8102C34.7455 36.8559 35.045 36.8552 35.2947 36.9009C35.3447 36.9471 35.445 37.1321 35.3453 37.1786C35.8434 36.7606 35.7916 35.9734 35.3414 35.5577C34.8411 35.0958 34.0925 35.1439 33.5943 35.562C32.3987 36.5374 32.8032 38.6668 34.4014 39.0334C35.9496 39.3538 37.4432 37.7756 37.39 36.4327C37.3364 34.9045 35.4867 33.7512 33.9913 34.5884C32.4959 35.4257 32.8496 37.231 32.9028 38.5739C32.9063 40.0096 35.4021 40.0035 35.3985 38.5215Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M30.8894 16.8761C30.2913 17.248 29.5935 17.6665 29.3955 18.3617C29.1476 19.057 29.4489 19.7972 29.9493 20.3055C30.7499 21.0908 32.2485 21.5503 33.3963 21.4549C34.8935 21.3586 35.9885 20.0592 35.5359 18.671C35.0835 17.3753 33.5349 16.8697 32.1875 17.0119C31.5387 17.0598 30.9409 17.5243 30.9425 18.1727C30.9438 18.7284 31.4944 19.3755 32.1931 19.3275C32.3928 19.327 32.6423 19.2801 32.842 19.3259L33.1917 19.4177C33.092 19.4642 33.1912 19.2324 33.1912 19.2324C33.1409 19.0473 33.391 19.2782 33.0912 19.14C32.8913 19.0479 32.3421 19.0029 32.0423 18.8647C31.7924 18.7264 31.742 18.5413 31.7429 18.9117C31.7438 19.2822 31.8431 19.0504 32.1422 18.9108C33.4878 18.0276 32.2351 16.0392 30.8894 16.8761Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M15.651 23.4323C14.3004 22.2314 14.9803 19.889 16.1401 19.3093C17.3 18.7296 18.6973 18.9903 19.6848 19.5786C21.2343 20.4547 21.1889 22.3073 19.8938 23.422C18.7481 24.3973 16.8016 24.4947 15.651 23.4323Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M9.16563 12.5292C9.36765 13.5012 9.17221 15.2393 8.43938 15.6963C7.70655 16.1532 7.67912 16.0521 7.29899 16.2301C6.91886 16.408 4.98266 16.6148 5.02898 15.1327C4.97568 13.7435 4.72037 11.3822 6.56599 10.8683C7.81308 10.5411 8.96327 11.4182 9.16563 12.5292Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.9279 29.1922C16.9334 29.1738 16.9384 29.1552 16.9431 29.1363C17.1904 28.2095 16.4397 27.424 15.4413 27.3801C15.0849 27.381 14.7288 27.4648 14.3993 27.6069C13.7993 27.4198 13.2161 27.6546 12.8475 28.1273C12.723 28.2665 12.5611 28.3827 12.3991 28.4988C12.2372 28.615 12.0752 28.7312 11.9508 28.8704C11.4529 29.3811 11.3046 29.9835 11.3562 30.678C11.5091 31.9744 12.4604 33.1762 13.9581 33.2652C14.0649 33.2725 14.1702 33.2624 14.2718 33.2375C14.7057 33.6206 15.2598 33.8172 15.9557 33.631C17.8498 33.1304 17.9407 30.4831 16.9279 29.1922Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M27.6566 36.3637C27.6572 36.5952 27.7072 36.6414 27.7069 36.5025C27.6575 36.7342 27.6576 36.7805 27.7072 36.6414C27.6078 36.8269 27.608 36.8732 27.6576 36.7805C27.6575 36.7342 27.7075 36.734 27.7073 36.6877C27.5579 36.827 27.558 36.8733 27.6077 36.7806L27.6575 36.7342C27.7073 36.6877 27.7073 36.6877 27.508 36.8272C27.5579 36.827 27.5578 36.7807 27.6077 36.7806C27.8071 36.6412 27.3584 36.8738 27.5579 36.827C27.7076 36.7804 27.6576 36.7805 27.4082 36.8274C27.4581 36.8273 27.508 36.8272 27.508 36.8272C27.4581 36.8273 27.3583 36.8275 27.3082 36.7813C27.4082 36.8274 27.3582 36.7812 27.1584 36.7354C27.0083 36.5968 26.9584 36.5969 27.0584 36.6893C26.9583 36.5506 26.9082 36.5044 26.9584 36.5969C27.0085 36.6894 27.0084 36.6431 26.9081 36.4581C26.8579 36.3193 26.8575 36.1804 26.907 35.995C26.8575 36.1804 27.0561 35.7168 26.9566 35.8559C27.1059 35.6703 27.1557 35.6239 27.0561 35.7168C26.9565 35.8096 27.0063 35.7632 27.2056 35.6238C27.1558 35.6702 27.1059 35.6703 27.0561 35.7168C26.8566 35.8099 27.0561 35.7168 27.1559 35.7165C27.0561 35.7168 27.0063 35.7632 26.9565 35.8096C26.9066 35.8098 26.8566 35.8099 26.8068 35.8563C26.6073 35.9031 27.1562 35.8555 26.9067 35.8561C26.2578 35.8576 25.6101 36.3686 25.6616 37.0169C25.713 37.6188 26.2135 38.1733 26.9123 38.1716C27.6111 38.1699 28.3092 37.8904 28.8074 37.4724C29.6046 36.8684 29.602 35.8032 28.9015 35.1102C28.251 34.4634 27.2027 34.4197 26.405 34.8384C25.6075 35.3035 25.1602 36.0919 25.3121 36.9714C25.4633 37.5731 26.2129 37.9418 26.8614 37.755C27.5099 37.6145 27.808 37.0117 27.6566 36.3637Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M26.4487 17.5815C26.4479 17.2574 26.4472 16.9795 26.4464 16.6553C26.445 16.0533 25.8945 15.4525 25.1958 15.5005C24.4971 15.5486 23.9491 16.013 23.9507 16.6614C23.9515 16.9856 23.9522 17.2634 23.9529 17.5876C23.9544 18.1897 24.5049 18.7904 25.2036 18.7424C25.9023 18.6944 26.4503 18.2299 26.4487 17.5815Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M41.3307 20.6019C41.0831 21.3898 41.335 22.3618 42.2343 22.6838C42.5341 22.822 42.8837 22.9137 43.183 22.8204C43.4823 22.727 43.7314 22.5412 43.9305 22.3091C44.03 22.17 44.1793 21.9843 44.2788 21.8452C44.6269 21.3349 44.3755 20.5482 43.8257 20.2717C43.176 19.9491 42.5276 20.1359 42.1296 20.6926C42.0301 20.8318 41.8808 21.0174 41.7813 21.1566C42.3301 21.0163 42.9287 20.8759 43.4774 20.7356C43.3276 20.6897 43.3273 20.5971 43.5275 20.7818C43.4774 20.7356 43.4774 20.7356 43.5775 20.828C43.6775 20.9204 43.7276 20.9666 43.7279 21.1055C43.6775 20.9204 43.7287 21.4297 43.7281 21.1981C43.7282 21.2445 43.7285 21.3371 43.7286 21.3834C43.7285 21.3371 43.7284 21.2908 43.7782 21.2443C43.9765 20.6881 43.5254 19.9482 42.9261 19.8107C42.177 19.6736 41.5289 19.9994 41.3307 20.6019Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M39.8021 28.2935C40.3028 28.9407 41.0027 29.3558 41.9013 29.3999C42.5503 29.4446 43.2485 29.2114 43.7467 28.7934C44.3445 28.3288 44.5421 27.4947 44.1413 26.8473C43.6902 26.1074 42.7415 25.9708 41.8927 25.8802C41.2437 25.8355 40.5963 26.4391 40.6476 27.0411C40.6992 27.7356 41.1994 28.1512 41.8983 28.1958C41.9982 28.1956 42.198 28.2877 41.8484 28.1959C41.8983 28.1958 41.9482 28.1957 41.9983 28.2419C42.0981 28.2416 42.1981 28.2877 42.298 28.3338C42.4978 28.3796 41.9982 28.1956 42.1481 28.2878C42.1481 28.2878 42.1982 28.334 42.2481 28.3339C42.348 28.38 41.9979 28.1029 42.0981 28.2416C42.1982 28.334 41.8978 27.9643 41.9979 28.1029C42.0981 28.2416 41.8973 27.779 41.8977 27.9179C41.9479 28.0568 41.8468 27.5476 41.8472 27.6865C41.8475 27.8254 41.8962 27.3159 41.8965 27.4548C41.847 27.5939 42.0455 27.1303 41.9959 27.2693C41.8965 27.4548 42.2449 27.0372 42.0955 27.1765C41.8963 27.3622 42.3448 27.0369 42.1952 27.1299C42.1453 27.13 42.0456 27.1766 42.0457 27.2229C42.0457 27.2229 42.3949 27.1294 42.2452 27.1298C42.1952 27.1299 42.1952 27.1299 42.1454 27.1763C42.0955 27.1765 42.0456 27.1766 42.0457 27.2229C41.8961 27.2696 42.395 27.1757 42.2453 27.1761C42.1454 27.1763 42.0955 27.1765 41.9957 27.1767C41.796 27.1772 42.2953 27.2223 42.1955 27.2225C42.1455 27.2227 42.1455 27.2227 42.0956 27.2228C42.0457 27.2229 41.9957 27.1767 41.9957 27.1767C42.2953 27.2223 42.2456 27.315 42.1455 27.2227C42.0956 27.2228 42.0955 27.1765 42.0456 27.1766C41.9457 27.1305 42.2956 27.3612 42.1457 27.269C42.0956 27.2228 42.0956 27.2228 42.0456 27.1766C41.8955 27.038 42.2458 27.4077 42.0957 27.2691C41.8955 27.038 41.6953 26.807 41.3458 26.7615C41.0461 26.6696 40.6469 26.7169 40.3977 26.9027C39.6992 27.0434 39.4016 27.7851 39.8021 28.2935Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M54.7208 25.8489C54.7703 25.6636 54.7702 25.6173 54.7208 25.8489C54.5714 25.9882 54.4218 26.0349 54.2222 26.0817C53.9225 25.9898 53.6227 25.8516 53.323 25.7597C53.1728 25.5748 53.1728 25.5748 53.2229 25.6673C53.2229 25.6673 53.223 25.7136 53.273 25.7135C53.3231 25.806 53.3231 25.806 53.273 25.7135C53.2228 25.621 53.2228 25.621 53.273 25.7135C53.2731 25.7598 53.3233 25.8987 53.3233 25.8987C53.2232 25.76 53.3228 25.6671 53.3232 25.8523C53.2738 26.084 53.3724 25.5743 53.3231 25.806C53.3233 25.8987 53.174 26.0843 53.3729 25.7596C53.2734 25.8988 53.4725 25.6667 53.5223 25.6203C53.5721 25.5739 53.6718 25.5273 53.7715 25.4808C53.6219 25.5274 53.6718 25.5273 53.8714 25.4805C54.2212 25.6649 54.5711 25.8493 54.9709 26.0336C54.8707 25.8949 54.7205 25.71 54.6203 25.5713C54.2697 25.0627 53.5203 24.7867 52.9222 25.1586C52.3739 25.4841 52.0762 26.2259 52.4768 26.7343C52.577 26.873 52.7271 27.0579 52.8273 27.1966C53.0777 27.5202 53.4777 27.7971 53.9268 27.7497C54.7751 27.655 55.4231 27.2829 55.7208 26.5412C55.9194 26.0776 55.8682 25.5683 55.7671 25.0591C55.5658 24.3649 55.0649 23.6714 54.1666 23.7199C53.2682 23.7684 52.521 24.3723 52.3732 25.2063C52.225 25.8087 52.5761 26.5025 53.2253 26.6399C53.7747 26.7775 54.5725 26.4514 54.7208 25.8489Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M15.064 15.942C15.8658 17.2368 15.134 18.3816 15.1202 18.5354C15.1064 18.6892 14.5739 19.6945 13.925 19.6961C13.2262 19.6978 12.6759 19.1897 12.6744 18.5413C12.6226 17.8005 12.4709 16.9672 12.7686 16.2255C12.9671 15.7619 13.3158 15.4832 13.8147 15.3893C14.3138 15.3418 14.8134 15.5258 15.064 15.942Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M8.10198 6.18699C8.05251 6.37236 8.10232 6.32592 8.10198 6.18699C8.10187 6.14068 8.15167 6.09424 8.15156 6.04793C8.20125 5.95519 8.25094 5.86244 8.15144 6.00162C8.20113 5.90888 8.25094 5.86244 8.25071 5.76982C8.3502 5.63064 8.39978 5.49159 8.49927 5.35241C8.54896 5.25966 8.54896 5.25966 8.49927 5.35241C8.54908 5.30598 8.59877 5.21323 8.69848 5.16668C8.39922 5.26003 8.10007 5.39969 7.8008 5.49304C7.95055 5.49268 7.95055 5.49268 7.75089 5.49316C7.90074 5.53911 7.85072 5.49292 7.65094 5.44709C7.40103 5.30877 7.20058 4.98507 7.19991 4.7072C7.24926 4.47552 7.24915 4.42921 7.19946 4.52195C7.29884 4.33646 7.29872 4.29015 7.24903 4.3829C7.19923 4.42933 7.04994 4.61494 7.19934 4.47564C7.34875 4.33634 7.14954 4.52207 7.09974 4.56851C7.14988 4.66101 7.10008 4.70744 7.00036 4.754C6.95056 4.80043 6.90075 4.84686 6.85095 4.8933C6.60182 5.07915 7.05027 4.75388 6.90075 4.84686C6.4025 5.21857 6.05467 5.86778 6.45534 6.42255C6.80587 6.88482 7.6053 7.20706 8.15347 6.83523C9.15008 6.13813 10.5442 4.69907 9.29375 3.63694C8.94356 3.31361 8.44407 3.17588 7.94492 3.1771C7.24611 3.17879 6.84769 3.55026 6.49952 4.06053C6.00183 4.6638 5.70425 5.45182 5.60622 6.19305C5.55777 6.79523 6.20813 7.3957 6.85691 7.34781C7.60553 7.29968 8.05364 6.83547 8.10198 6.18699Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.2094 4.30792C16.2588 4.12255 16.1099 4.4471 16.0601 4.49353C15.8607 4.63295 16.2094 4.30792 16.0601 4.49353C15.8107 4.58676 16.2594 4.35411 16.0601 4.49353C16.2596 4.44673 15.8105 4.49414 16.11 4.49341C15.8602 4.40139 16.2098 4.49317 16.11 4.49341C16.01 4.44734 16.3598 4.58542 16.11 4.49341C16.06 4.44722 16.3598 4.58542 16.11 4.49341C16.16 4.5396 16.16 4.5396 16.0099 4.40103C15.9596 4.2159 15.9096 4.21602 15.9599 4.35484C16.0588 3.9841 16.1578 3.61337 16.2567 3.24263C16.5555 2.96403 16.8052 3.00974 17.0551 3.14807C17.1051 3.19426 17.1051 3.19426 17.0051 3.10188C17.1051 3.19426 17.1052 3.24057 17.055 3.10175C16.7542 2.54674 15.9051 2.36356 15.3569 2.68907C14.7587 3.01471 14.6106 3.70975 14.9115 4.26476C15.513 5.32847 17.0613 5.6952 18.0576 4.85917C18.4063 4.58045 18.505 4.11709 18.4043 3.74684C17.8005 1.7569 14.406 1.67252 13.812 3.71169C13.3662 5.14844 15.8135 5.74455 16.2094 4.30792Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M26.1805 5.79236C25.8821 6.2562 25.6338 6.76624 25.9846 7.32113C26.1851 7.69114 26.5352 7.96816 26.9349 8.10612C27.7341 8.33574 28.5817 7.96318 28.9295 7.31397C29.1283 6.94299 29.1771 6.47976 28.9267 6.15618C28.476 5.55522 27.9263 5.27869 27.1775 5.23419C26.778 5.18885 26.3789 5.28245 25.9297 5.28354C25.2808 5.28512 24.6331 5.79612 24.6846 6.44436C24.736 7.04629 25.2365 7.60082 25.9353 7.59912C26.2348 7.59839 26.4843 7.55147 26.7838 7.55075C26.8337 7.55062 26.9335 7.55038 26.9834 7.55026C27.1333 7.59621 27.1831 7.54978 26.9834 7.55026C27.0333 7.55014 27.1332 7.5499 27.1333 7.59621C27.0334 7.59645 26.9834 7.55026 26.9334 7.50407C26.8834 7.45788 26.8333 7.41169 26.7833 7.3655C26.7824 6.99501 26.7814 6.5782 26.7805 6.20771C26.7806 6.25402 26.7307 6.25414 26.7308 6.30045C26.88 6.06853 27.0794 5.97542 27.3291 6.02113C27.5785 5.9279 27.7782 5.97372 27.9284 6.15861C28.1786 6.38956 28.2285 6.38944 28.1283 6.25075C28.1292 6.62124 28.1302 7.03804 28.1311 7.40854C28.1808 7.31579 28.2803 7.17661 28.33 7.08387C28.6782 6.57359 28.4766 5.78678 27.8769 5.51037C27.2769 5.09502 26.5286 5.23577 26.1805 5.79236Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M35.1394 5.04995C35.2391 5.0034 35.3388 4.95684 35.4385 4.91029C35.5882 4.86361 35.5881 4.8173 35.4885 4.91017C35.239 4.95708 35.0392 4.91126 34.8392 4.77281C34.7392 4.68043 34.7391 4.63412 34.7388 4.54149C34.6887 4.44899 34.938 4.35576 34.6889 4.54161C34.7387 4.49518 34.7885 4.44875 34.8882 4.40219C34.9882 4.44826 34.9881 4.40195 34.8383 4.40232C34.9383 4.44839 34.9383 4.44838 34.7883 4.35613C34.9882 4.44826 34.7382 4.26362 34.6881 4.21743C34.438 3.98648 34.2877 3.75529 34.0375 3.52434C33.5872 3.06231 32.7387 3.11069 32.2905 3.52858C31.7925 3.99291 31.8441 4.68746 32.2945 5.14949C32.8449 5.70389 33.2457 6.30497 34.045 6.5809C35.0441 6.90266 36.1415 6.62212 36.7385 5.78706C37.3853 4.95187 37.3327 3.84051 36.5323 3.10147C35.7317 2.31611 34.784 2.59628 33.8866 3.01527C33.2883 3.2946 33.0905 4.08238 33.4411 4.59096C33.792 5.19216 34.5411 5.32928 35.1394 5.04995Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M43.1315 8.35476C43.7308 8.49224 44.3797 8.49066 44.928 8.16515C45.4264 7.88607 45.7745 7.32948 45.8231 6.77362C45.8219 6.3105 45.6211 5.84787 45.2711 5.57085C44.7709 5.15526 44.1218 5.06421 43.4732 5.20472C42.8247 5.34523 42.427 6.04088 42.6282 6.64244C42.8293 7.24401 43.4791 7.61293 44.1774 7.42598C44.377 7.37918 43.828 7.42683 44.0277 7.42635C44.2273 7.42586 43.7281 7.38076 43.8279 7.38052C44.0277 7.42634 43.5281 7.24231 43.6781 7.33457C43.778 7.38064 43.8281 7.47314 43.5281 7.24231C43.6281 7.33469 43.6284 7.42732 43.4279 7.10362C43.4781 7.19612 43.4783 7.28874 43.3776 6.91849C43.3777 6.96481 43.3777 6.96481 43.3778 7.01112C43.3272 6.73337 43.3271 6.68706 43.3273 6.77968C43.3275 6.8723 43.3274 6.82599 43.3271 6.68706C43.3764 6.45538 43.3267 6.54812 43.327 6.64075C43.2773 6.73349 43.5258 6.31608 43.3765 6.50169C43.3765 6.50169 43.6254 6.22321 43.476 6.36251C43.476 6.36251 43.7751 6.17654 43.6256 6.26953C43.476 6.36251 43.9746 6.12974 43.7752 6.22285C43.5758 6.31596 43.8749 6.1763 43.9249 6.22249L43.7752 6.22285C43.5755 6.22333 44.1247 6.26831 43.8251 6.22273C43.1759 6.08537 42.4279 6.41137 42.2796 7.01379C42.0812 7.5237 42.4323 8.21752 43.1315 8.35476Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M53.6261 6.02084C53.7258 5.97428 53.8255 5.92773 53.9752 5.88105L54.075 5.88081C54.2246 5.83413 54.1747 5.83426 53.9752 5.88105C53.8255 5.92773 53.7256 5.88166 53.6256 5.83559C53.5754 5.69678 53.4759 5.83595 53.6256 5.83559C53.6254 5.74297 53.8261 6.15929 53.8262 6.2056C53.7761 6.1131 53.7757 5.97416 53.8753 5.88129C53.9251 5.83486 53.9749 5.78843 54.0247 5.742C54.1243 5.64913 53.8254 5.88142 54.0247 5.742C53.9749 5.78843 54.2244 5.74151 53.9748 5.74212C53.9249 5.74224 53.6253 5.69666 53.8251 5.74248C53.9748 5.74212 53.6253 5.69666 53.6752 5.69653C53.4754 5.65071 53.7252 5.74272 53.5754 5.69678C53.4754 5.65071 53.4254 5.60452 53.3255 5.55845C53.4754 5.65071 53.3754 5.55833 53.2754 5.51226C53.3257 5.65107 53.1754 5.41988 53.2754 5.51226C53.3255 5.55845 53.3263 5.88263 53.3757 5.69726C53.4241 5.04878 52.7739 4.54093 52.125 4.5425C51.4262 4.5442 50.9283 5.05484 50.88 5.70333C50.785 7.69497 53.9821 8.75237 55.5268 7.63713C56.7225 6.70799 56.4195 5.27306 55.4687 4.25651C54.5679 3.33246 53.5204 3.61288 52.4733 4.07854C51.875 4.35786 51.7272 5.14552 52.0279 5.65422C52.2787 6.16305 52.9778 6.25397 53.6261 6.02084Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M53.2553 18.4426C53.2068 18.9985 53.2582 19.6004 53.559 20.1554C53.7596 20.5254 54.0596 20.7563 54.4094 20.8943C54.9589 21.0783 55.4579 21.0307 55.9565 20.798C56.7543 20.4718 57.3017 19.7758 57.3496 18.9421C57.3971 17.9231 56.497 17.2769 55.4987 17.2794C54.8498 17.2809 54.2021 17.7919 54.2536 18.4402C54.305 19.0421 54.8055 19.5966 55.5043 19.5949C55.5542 19.5948 55.7539 19.5943 55.5542 19.5948C55.3046 19.5491 55.6542 19.6409 55.4044 19.5489C55.3044 19.5028 55.2545 19.5029 55.3044 19.5028C55.4044 19.5489 55.3544 19.5027 55.1544 19.3642C55.1544 19.3642 54.954 19.0869 55.0542 19.2255C55.0542 19.2255 54.9037 18.9017 54.9539 19.0405C54.8533 18.7166 54.9532 18.7627 54.9035 18.8554C54.9038 18.948 55.0027 18.5773 54.953 18.67C54.953 18.67 54.9532 18.7627 54.9033 18.7628C54.9033 18.7628 55.0524 18.4846 54.9529 18.6237C54.953 18.67 54.9031 18.6702 54.9032 18.7165C54.8535 18.8092 55.0525 18.5309 55.0027 18.5773C54.9528 18.5774 54.9529 18.6237 54.9031 18.6702C54.8036 18.8093 55.0526 18.5772 55.0526 18.5772C55.0527 18.6235 54.953 18.67 54.9031 18.6702C54.7037 18.7633 54.8532 18.6703 54.9031 18.6702C54.9031 18.6702 55.2524 18.623 55.1026 18.6234C54.9529 18.6237 55.3523 18.6691 55.3024 18.6692C55.5522 18.7612 55.6022 18.8074 55.5023 18.7613C55.4523 18.7151 55.5023 18.7613 55.6022 18.8074C55.8022 18.9459 55.7023 18.8998 55.6523 18.8536C55.5522 18.7612 55.8526 19.131 55.7524 18.9923C55.7022 18.8535 55.8527 19.1773 55.8028 19.1774L55.7524 18.9923C55.7524 18.9923 55.7023 18.8998 55.7522 18.8997C55.7522 18.8997 55.8029 19.2237 55.8026 19.0848C55.8024 18.9922 55.8022 18.9459 55.802 18.8532C55.8017 18.7143 55.8013 18.5754 55.801 18.4364C55.8495 17.8343 55.1991 17.2338 54.5503 17.2817C53.8016 17.2835 53.2538 17.7943 53.2553 18.4426Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M46.6598 36.2425C47.3101 36.843 48.2091 37.0261 49.0568 36.6998C49.5056 36.5135 49.7543 36.1424 50.003 35.7713C50.1026 35.6784 50.1521 35.5394 50.2516 35.4002C50.4505 35.0755 50.4497 34.7513 50.3989 34.381C50.0957 32.8534 47.9987 32.6269 47.0029 33.6482C46.5548 34.1124 46.5066 34.8535 47.0068 35.2691C47.507 35.6847 48.3057 35.7291 48.7538 35.2649L48.8534 35.172C48.8534 35.172 48.6042 35.3116 48.8036 35.2185C48.7537 35.2186 48.5543 35.3117 48.7039 35.265C48.654 35.2651 48.5542 35.2654 48.5043 35.2655C48.6041 35.2653 48.6041 35.2653 48.4543 35.2656C48.2546 35.2198 48.5044 35.3118 48.3045 35.2197C48.2545 35.1735 48.0546 35.0813 48.1045 35.0812C48.1545 35.1274 48.0043 34.9425 47.9543 34.8963C47.9042 34.8038 47.9042 34.8038 47.9043 34.8501C47.9045 34.9428 47.9044 34.8965 47.9039 34.7112C47.9534 34.5258 48.0029 34.3405 48.0522 34.1088C47.9527 34.248 47.9031 34.387 47.8037 34.5262C47.7538 34.5726 47.704 34.6191 47.7043 34.7117C47.6545 34.7581 47.5052 34.9437 47.6545 34.7581C47.8539 34.665 48.0034 34.572 48.2029 34.4789C48.1531 34.5254 48.1031 34.5255 48.0033 34.5257C48.103 34.4792 48.2029 34.4789 48.3028 34.525C48.1529 34.479 48.2029 34.4789 48.3527 34.5249C48.4528 34.6173 48.4528 34.6173 48.3527 34.5249C47.9025 34.1092 47.0538 34.0649 46.6057 34.5291C46.2077 35.0858 46.1595 35.7806 46.6598 36.2425Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M4.65044 23.655C4.40289 24.4892 2.93826 25.1792 2.75422 25.2686C2.57019 25.358 2.10595 25.3866 1.85924 25.329C1.61254 25.2714 0.899146 24.4255 0.848227 24.0341C0.797309 23.6427 0.685828 22.5968 1.034 22.0865C1.58104 21.2516 2.59795 21.2054 3.54724 21.5736C4.4465 21.8956 4.94779 22.7743 4.65044 23.655Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M19.8092 6.81142C17.7314 7.42931 16.0902 9.1172 15.1566 11.0613C14.2231 13.0054 13.937 15.2358 13.922 17.4059C13.9069 20.1487 14.3436 22.9368 15.5331 25.4083C17.5356 29.5677 21.5106 32.4914 25.7567 34.3149C30.2888 36.259 35.5587 37.0728 40.1209 35.2191C43.0118 34.0436 45.436 31.8283 47.1525 29.206C49.3809 25.7851 50.4348 21.5653 49.8025 17.5416C49.1701 13.5178 46.7309 9.73508 43.1925 7.73072C41.2953 6.66072 39.1573 6.08805 37.0041 5.72636C31.0717 4.6865 25.5459 5.03312 19.8092 6.81142Z\"\n        fill=\"#4A6747\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 40,\n  svg: RoundedBannerWithDots,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/squigglyLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Squiggly Line', 'sticker name', 'web-stories');\n\nfunction SquigglyLine({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 54 20\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.18923 18.3387C1.15429 18.3513 1.10478 18.3455 1.06984 18.3581C0.155435 18.4513 0.158588 19.9898 1.09436 19.9995C2.43007 20.0228 3.45891 19.2409 4.49844 18.5104C5.81264 17.5782 7.02102 16.5499 8.1459 15.3781C9.28922 14.1917 10.2937 12.9054 11.2234 11.5434C12.0755 10.2726 13.2247 9.03672 13.7622 7.5952C13.3468 7.71354 12.9148 7.82995 12.4994 7.9483C12.7625 8.12971 12.9063 8.89897 13.0257 9.1638C13.2248 9.60519 13.4403 10.0485 13.6908 10.4792C14.1356 11.2504 14.689 11.9508 15.353 12.5639C16.7103 13.827 18.546 14.5778 20.3971 14.0598C22.1084 13.5922 23.5303 12.4553 24.5979 11.0594C25.8412 9.45 26.2845 7.52926 27.2132 5.74918C26.7103 5.75694 26.191 5.76276 25.6882 5.77052C26.2855 7.66313 27.1264 9.3336 28.6632 10.6345C29.9719 11.7413 31.7931 12.758 33.5618 12.5145C35.4002 12.2458 37.0172 10.7305 38.0265 9.26087C38.5729 8.45571 39.0446 7.57488 39.322 6.63779C39.6296 5.5872 39.9857 4.40857 40.0971 3.3182C39.5448 3.32014 39.007 3.34051 38.4547 3.34245C38.7607 5.15067 40.2297 6.7445 41.7412 7.6913C43.3004 8.6604 45.1574 9.22984 47.0008 9.06202C48.8587 8.91263 50.468 7.74758 51.5763 6.28956C52.1887 5.49216 52.6827 4.56381 52.9786 3.61216C53.1397 3.09609 53.2201 2.55381 53.3482 2.03386C53.4539 1.56143 53.647 1.19959 53.6062 0.693216C53.5547 0.135423 52.9159 -0.123588 52.4597 0.0568446C52.1083 0.199445 51.8977 0.425471 51.6628 0.715523C50.964 1.5362 52.3028 2.52956 52.9851 1.70694C53.0239 1.66135 53.0792 1.61769 53.1181 1.5721C52.7414 1.36062 52.3482 1.14721 51.9715 0.93573C51.9579 0.766937 51.7697 1.51389 51.7338 1.67687C51.6485 2.11825 51.5816 2.54508 51.4467 2.98064C51.2294 3.69074 50.9004 4.35427 50.4763 4.97317C49.6281 6.21098 48.4032 7.23732 46.8627 7.39059C45.4911 7.53027 44.0184 7.10635 42.8467 6.40013C41.6749 5.69392 40.3303 4.4658 40.1097 3.06889C39.9504 2.14732 38.5613 2.1512 38.4673 3.09314C38.3664 3.95069 38.0948 4.8383 37.8804 5.66578C37.6699 6.46026 37.3623 7.22662 36.912 7.92604C36.1482 9.15706 34.8525 10.6432 33.3227 10.8479C31.9637 11.0225 30.5551 10.0544 29.5823 9.22108C28.3396 8.12198 27.7103 6.64359 27.2228 5.09826C26.9761 4.35033 25.9821 4.55113 25.6978 5.1196C24.9195 6.61642 24.5587 8.26263 23.592 9.65371C22.7234 10.9226 21.483 12.0808 19.9484 12.4689C18.3293 12.8637 16.8294 11.8179 15.8497 10.616C15.3235 9.96897 14.9409 9.2385 14.5952 8.47893C14.3039 7.82607 14.1621 7.04032 13.5427 6.61639C13.1097 6.3147 12.4758 6.44081 12.2798 6.9695C11.8209 8.16948 10.827 9.22297 10.1157 10.293C9.30433 11.5017 8.46387 12.6735 7.46809 13.7435C6.52762 14.7698 5.53084 15.706 4.42824 16.546C3.67408 17.1261 2.35798 18.3591 1.33969 18.3397C1.34172 18.8917 1.36219 19.4291 1.36422 19.9811C1.39916 19.9685 1.44867 19.9743 1.48361 19.9617C2.49703 19.8802 2.25603 18.2301 1.18923 18.3387Z\"\n        fill=\"#F9E46C\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 54 / 20,\n  svg: SquigglyLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/wavyLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Wavy Line', 'sticker name', 'web-stories');\n\nfunction WavyLine({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 52 4\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M0.912399 1.09772C4.46934 1.15747 7.14993 3.36836 10.7069 3.48787C14.3325 3.60738 17.0131 1.34868 20.5013 1.12162C24.0583 0.882602 26.8592 3.1652 30.2958 3.46397C33.8871 3.77469 36.6365 1.67135 39.97 1.19332C43.9909 0.607734 47.1354 3.44007 51.0876 3.49982C51.6375 3.51177 51.6375 2.91424 51.0876 2.90228C47.5307 2.84253 44.8501 0.631636 41.2931 0.512128C37.6675 0.39262 34.9869 2.65132 31.4987 2.87838C27.9417 3.1174 25.1408 0.834799 21.7042 0.536029C18.1129 0.225309 15.3635 2.32865 12.03 2.80668C8.0091 3.39227 4.86456 0.571882 0.912399 0.500177C0.362534 0.488226 0.362534 1.08577 0.912399 1.09772Z\"\n        fill=\"#F9E46C\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 52 / 4,\n  svg: WavyLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/yellowDots.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Dots', 'sticker name', 'web-stories');\n\nfunction YellowDots({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 62 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M37.7127 38.8071C37.7127 38.2138 37.6594 37.6205 37.6594 37.0272C37.6594 36.9284 37.6594 36.5823 37.7127 36.5823L37.6594 36.6812C37.4461 36.7306 37.3928 36.7306 37.2329 36.6812C37.1263 36.6812 37.1796 36.6317 37.2329 36.6317C37.2862 36.6317 37.1263 36.8295 37.073 36.8295C37.1263 36.8295 36.913 36.9284 36.913 36.9284C36.8597 36.9284 36.8064 36.9778 36.7531 36.9778C37.0196 37.0272 37.3395 37.0272 37.606 37.0767C37.6594 37.1261 37.766 37.3239 37.6594 37.3733C38.1925 36.9284 38.1392 36.0879 37.6594 35.6429C37.1263 35.1485 36.3266 35.1979 35.7935 35.6429C34.5141 36.6812 34.9406 38.9555 36.6465 39.351C38.2991 39.6971 39.8984 38.0161 39.8451 36.5823C39.7918 34.9507 37.8193 33.7146 36.22 34.6046C34.6207 35.4945 34.9939 37.4228 35.0472 38.8566C35.0472 40.3893 37.7127 40.3893 37.7127 38.8071Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M32.9531 15.6872C32.3134 16.0827 31.5671 16.5277 31.3538 17.2693C31.0873 18.0109 31.4071 18.802 31.9402 19.3459C32.7932 20.1864 34.3925 20.6808 35.6186 20.5819C37.2179 20.483 38.3907 19.0986 37.9109 17.6154C37.4312 16.231 35.7785 15.6872 34.3392 15.8355C33.6461 15.8849 33.0064 16.3794 33.0064 17.0715C33.0064 17.6648 33.5928 18.357 34.3392 18.3076C34.5524 18.3076 34.819 18.2581 35.0322 18.3076L35.4054 18.4065C35.2988 18.4559 35.4054 18.2087 35.4054 18.2087C35.3521 18.0109 35.6186 18.2581 35.2988 18.1098C35.0855 18.0109 34.4991 17.9615 34.1792 17.8132C33.9127 17.6648 33.8594 17.4671 33.8594 17.8626C33.8594 18.2581 33.966 18.0109 34.2859 17.8626C35.7252 16.9232 34.3925 14.7972 32.9531 15.6872Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.6614 22.6469C15.2221 21.3614 15.9543 18.8624 17.1945 18.2466C18.4348 17.6307 19.9264 17.9126 20.9795 18.5432C22.6321 19.4826 22.5788 21.4603 21.1928 22.6469C19.9666 23.6852 17.8876 23.7841 16.6614 22.6469Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M9.76331 10.9901C9.97655 12.0284 9.76331 13.8835 8.97945 14.3694C8.1956 14.8553 8.16656 14.7473 7.76012 14.9363C7.35368 15.1253 5.28527 15.341 5.33858 13.7589C5.28527 12.2756 5.01872 9.75409 6.99119 9.21023C8.32394 8.86414 9.55007 9.80353 9.76331 10.9901Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M18.0102 28.7994C18.0161 28.7798 18.0215 28.7599 18.0265 28.7398C18.2931 27.7509 17.4934 26.9104 16.4272 26.861C16.0466 26.861 15.666 26.9496 15.3138 27.1005C14.6734 26.8991 14.05 27.1483 13.655 27.6519C13.5218 27.8002 13.3485 27.9238 13.1753 28.0474C13.002 28.171 12.8287 28.2946 12.6955 28.443C12.1624 28.9868 12.0024 29.6296 12.0557 30.3712C12.2157 31.7556 13.2286 33.0411 14.8279 33.1399C14.9419 33.1481 15.0544 33.1375 15.163 33.1112C15.6254 33.5213 16.2166 33.7327 16.9603 33.5356C18.9845 33.0061 19.0885 30.1802 18.0102 28.7994Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M29.4499 36.4834C29.4499 36.7306 29.5033 36.78 29.5033 36.6317C29.4499 36.8789 29.4499 36.9283 29.5033 36.78C29.3966 36.9778 29.3966 37.0272 29.4499 36.9283C29.4499 36.8789 29.5033 36.8789 29.5033 36.8295C29.3433 36.9778 29.3433 37.0272 29.3966 36.9283L29.4499 36.8789C29.5033 36.8295 29.5033 36.8295 29.29 36.9778C29.3433 36.9778 29.3433 36.9283 29.3966 36.9283C29.6099 36.78 29.1301 37.0272 29.3433 36.9778C29.5033 36.9283 29.4499 36.9283 29.1834 36.9778C29.2367 36.9778 29.29 36.9778 29.29 36.9778C29.2367 36.9778 29.1301 36.9778 29.0768 36.9283C29.1834 36.9778 29.1301 36.9283 28.9168 36.8789C28.7569 36.7306 28.7036 36.7306 28.8102 36.8295C28.7036 36.6811 28.6503 36.6317 28.7036 36.7306C28.7569 36.8295 28.7569 36.78 28.6503 36.5823C28.597 36.4339 28.597 36.2856 28.6503 36.0878C28.597 36.2856 28.8102 35.7912 28.7036 35.9395C28.8635 35.7417 28.9168 35.6923 28.8102 35.7912C28.7036 35.8901 28.7569 35.8406 28.9702 35.6923C28.9168 35.7417 28.8635 35.7417 28.8102 35.7912C28.597 35.8901 28.8102 35.7912 28.9168 35.7912C28.8102 35.7912 28.7569 35.8406 28.7036 35.8901C28.6503 35.8901 28.597 35.8901 28.5437 35.9395C28.3304 35.989 28.9169 35.9395 28.6503 35.9395C27.9573 35.9395 27.2642 36.4834 27.3175 37.1756C27.3709 37.8183 27.904 38.4116 28.6503 38.4116C29.3966 38.4116 30.143 38.1149 30.6761 37.67C31.529 37.0272 31.529 35.8901 30.7827 35.1484C30.0897 34.4563 28.9702 34.4068 28.1172 34.8518C27.2642 35.3462 26.7845 36.1867 26.9444 37.1261C27.1043 37.7689 27.904 38.1644 28.597 37.9666C29.29 37.8183 29.6099 37.1756 29.4499 36.4834Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M28.2086 16.4288C28.2086 16.0827 28.2086 15.786 28.2086 15.4399C28.2086 14.7972 27.6222 14.1545 26.8759 14.2039C26.1295 14.2533 25.5431 14.7478 25.5431 15.4399C25.5431 15.786 25.5431 16.0827 25.5431 16.4288C25.5431 17.0715 26.1295 17.7143 26.8759 17.6648C27.6222 17.6154 28.2086 17.121 28.2086 16.4288Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M44.0949 19.6919C43.8283 20.5324 44.0949 21.5707 45.0545 21.9168C45.3743 22.0651 45.7475 22.164 46.0673 22.0651C46.3872 21.9662 46.6538 21.7684 46.867 21.5212C46.9736 21.3729 47.1335 21.1751 47.2402 21.0268C47.6133 20.4829 47.3468 19.6424 46.7604 19.3458C46.0673 18.9997 45.3743 19.1975 44.9478 19.7908C44.8412 19.9391 44.6813 20.1368 44.5747 20.2852C45.1611 20.1368 45.8008 19.9885 46.3872 19.8402C46.2273 19.7908 46.2273 19.6919 46.4405 19.8896C46.3872 19.8402 46.3872 19.8402 46.4938 19.9391C46.6004 20.038 46.6538 20.0874 46.6538 20.2357C46.6004 20.038 46.6538 20.5818 46.6538 20.3346C46.6538 20.3841 46.6538 20.4829 46.6538 20.5324C46.6538 20.4829 46.6538 20.4335 46.7071 20.3841C46.9203 19.7908 46.4405 18.9997 45.8008 18.8514C45.0011 18.703 44.3081 19.0491 44.0949 19.6919Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M42.4423 27.8993C42.9754 28.5915 43.7218 29.0365 44.6814 29.0859C45.3744 29.1354 46.1207 28.8882 46.6538 28.4432C47.2936 27.9488 47.5068 27.0588 47.0803 26.3666C46.6005 25.5756 45.5876 25.4273 44.6814 25.3284C43.9883 25.2789 43.2953 25.9217 43.3486 26.5644C43.4019 27.306 43.935 27.751 44.6814 27.8005C44.788 27.8005 45.0012 27.8993 44.628 27.8005C44.6814 27.8005 44.7347 27.8005 44.788 27.8499C44.8946 27.8499 45.0012 27.8993 45.1078 27.9488C45.3211 27.9982 44.788 27.8005 44.9479 27.8993C44.9479 27.8993 45.0012 27.9488 45.0545 27.9488C45.1612 27.9982 44.788 27.7016 44.8946 27.8499C45.0012 27.9488 44.6814 27.5532 44.788 27.7016C44.8946 27.8499 44.6814 27.3555 44.6814 27.5038C44.7347 27.6521 44.628 27.1083 44.628 27.2566C44.628 27.4049 44.6814 26.8611 44.6814 27.0094C44.628 27.1577 44.8413 26.6633 44.788 26.8116C44.6814 27.0094 45.0545 26.5644 44.8946 26.7127C44.6814 26.9105 45.1611 26.5644 45.0012 26.6633C44.9479 26.6633 44.8413 26.7127 44.8413 26.7622C44.8413 26.7622 45.2145 26.6633 45.0545 26.6633C45.0012 26.6633 45.0012 26.6633 44.9479 26.7127C44.8946 26.7127 44.8413 26.7127 44.8413 26.7622C44.6814 26.8116 45.2145 26.7127 45.0545 26.7127C44.9479 26.7127 44.8946 26.7127 44.788 26.7127C44.5747 26.7127 45.1078 26.7622 45.0012 26.7622C44.9479 26.7622 44.9479 26.7622 44.8946 26.7622C44.8413 26.7622 44.788 26.7127 44.788 26.7127C45.1078 26.7622 45.0545 26.8611 44.9479 26.7622C44.8946 26.7622 44.8946 26.7127 44.8413 26.7127C44.7347 26.6633 45.1078 26.9105 44.9479 26.8116C44.8946 26.7622 44.8946 26.7622 44.8413 26.7127C44.6814 26.5644 45.0545 26.9599 44.8946 26.8116C44.6814 26.5644 44.4681 26.3172 44.095 26.2678C43.7751 26.1689 43.3486 26.2183 43.0821 26.4161C42.3357 26.5644 42.0159 27.3555 42.4423 27.8993Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M58.382 25.3282C58.4353 25.1305 58.4353 25.081 58.382 25.3282C58.222 25.4766 58.0621 25.526 57.8489 25.5755C57.529 25.4766 57.2091 25.3282 56.8893 25.2294C56.7293 25.0316 56.7293 25.0316 56.7827 25.1305C56.7827 25.1305 56.7827 25.1799 56.836 25.1799C56.8893 25.2788 56.8893 25.2788 56.836 25.1799C56.7827 25.081 56.7827 25.081 56.836 25.1799C56.836 25.2294 56.8893 25.3777 56.8893 25.3777C56.7826 25.2294 56.8893 25.1305 56.8893 25.3282C56.836 25.5755 56.9426 25.0316 56.8893 25.2788C56.8893 25.3777 56.7293 25.5755 56.9426 25.2294C56.836 25.3777 57.0492 25.1305 57.1025 25.081C57.1558 25.0316 57.2624 24.9822 57.3691 24.9327C57.2091 24.9822 57.2624 24.9822 57.4757 24.9327C57.8489 25.1305 58.222 25.3282 58.6485 25.526C58.5419 25.3777 58.382 25.1799 58.2753 25.0316C57.9022 24.4877 57.1025 24.1911 56.4628 24.5866C55.8764 24.9327 55.5565 25.7238 55.983 26.2676C56.0896 26.416 56.2496 26.6137 56.3562 26.7621C56.6227 27.1081 57.0492 27.4048 57.529 27.3554C58.4353 27.2565 59.1283 26.8609 59.4482 26.0699C59.6614 25.5755 59.6081 25.0316 59.5015 24.4877C59.2882 23.7461 58.7551 23.0045 57.7955 23.0539C56.836 23.1034 56.0363 23.7461 55.8764 24.6361C55.7164 25.2788 56.0896 26.0204 56.7827 26.1688C57.3691 26.3171 58.222 25.971 58.382 25.3282Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.0539 14.6489C16.9069 16.0333 16.1224 17.2535 16.1072 17.4177C16.0921 17.5819 15.5208 18.6537 14.8278 18.6537C14.0814 18.6537 13.495 18.1099 13.495 17.4177C13.4417 16.6266 13.2818 15.7367 13.6017 14.9456C13.8149 14.4512 14.1881 14.1545 14.7212 14.0556C15.2543 14.0062 15.7874 14.204 16.0539 14.6489Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M8.64378 4.21656C8.59047 4.41433 8.64378 4.36489 8.64378 4.21656C8.64378 4.16712 8.69709 4.11768 8.69709 4.06824C8.7504 3.96935 8.80371 3.87047 8.69709 4.0188C8.7504 3.91991 8.80371 3.87047 8.80371 3.77159C8.91033 3.62326 8.96364 3.47494 9.07026 3.32661C9.12357 3.22773 9.12357 3.22773 9.07026 3.32661C9.12357 3.27717 9.17688 3.17829 9.2835 3.12885C8.96364 3.22773 8.64378 3.37605 8.32392 3.47494C8.48385 3.47494 8.48385 3.47494 8.27061 3.47494C8.43054 3.52438 8.37723 3.47494 8.16399 3.4255C7.89744 3.27717 7.6842 2.93108 7.6842 2.63443C7.73751 2.38722 7.73751 2.33778 7.6842 2.43666C7.79082 2.23889 7.79082 2.18945 7.73751 2.28834C7.6842 2.33778 7.52427 2.53554 7.6842 2.38722C7.84413 2.23889 7.63089 2.43666 7.57758 2.4861C7.63089 2.58499 7.57758 2.63443 7.47096 2.68387C7.41765 2.73331 7.36434 2.78275 7.31103 2.8322C7.04448 3.02996 7.52427 2.68387 7.36434 2.78275C6.83124 3.17829 6.45807 3.87047 6.88455 4.46377C7.25772 4.95819 8.11068 5.30428 8.69709 4.90875C9.76329 4.16712 11.256 2.63443 9.92322 1.49727C9.55005 1.15118 9.01695 1.00285 8.48385 1.00285C7.73751 1.00285 7.31103 1.39839 6.93786 1.94224C6.40477 2.58499 6.08491 3.4255 5.97829 4.21656C5.92498 4.85931 6.618 5.50205 7.31103 5.45261C8.11068 5.40317 8.59047 4.90875 8.64378 4.21656Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M17.3074 2.23154C17.3607 2.03377 17.2008 2.37986 17.1475 2.4293C16.9342 2.57763 17.3074 2.23154 17.1475 2.4293C16.8809 2.52819 17.3607 2.28098 17.1475 2.4293C17.3607 2.37986 16.8809 2.4293 17.2008 2.4293C16.9342 2.33042 17.3074 2.4293 17.2008 2.4293C17.0942 2.37986 17.4673 2.52819 17.2008 2.4293C17.1475 2.37986 17.4673 2.52819 17.2008 2.4293C17.2541 2.47875 17.2541 2.47875 17.0942 2.33042C17.0408 2.13265 16.9875 2.13265 17.0408 2.28098C17.1475 1.88544 17.2541 1.48991 17.3607 1.09438C17.6806 0.797727 17.9471 0.847169 18.2137 0.995494C18.267 1.04494 18.267 1.04494 18.1603 0.946052C18.267 1.04494 18.267 1.09438 18.2137 0.946052C17.8938 0.352752 16.9875 0.154985 16.4011 0.501077C15.7614 0.847169 15.6015 1.58879 15.9213 2.18209C16.5611 3.31925 18.2137 3.71479 19.2799 2.82484C19.653 2.52819 19.7596 2.03377 19.653 1.63824C19.0133 -0.487758 15.3882 -0.586641 14.7485 1.58879C14.2687 3.12149 16.8809 3.76423 17.3074 2.23154Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M27.9528 3.84217C27.6329 4.33658 27.3664 4.88044 27.7395 5.47374C27.9528 5.86928 28.3259 6.16593 28.7524 6.31425C29.6054 6.56146 30.5116 6.16593 30.8848 5.47374C31.0981 5.07821 31.1514 4.58379 30.8848 4.2377C30.405 3.59496 29.8186 3.29831 29.019 3.24886C28.5925 3.19942 28.166 3.29831 27.6862 3.29831C26.9932 3.29831 26.3002 3.84217 26.3535 4.53435C26.4068 5.17709 26.9399 5.77039 27.6862 5.77039C28.0061 5.77039 28.2726 5.72095 28.5925 5.72095C28.6458 5.72095 28.7524 5.72095 28.8057 5.72095C28.9657 5.77039 29.019 5.72095 28.8057 5.72095C28.859 5.72095 28.9657 5.72095 28.9657 5.77039C28.859 5.77039 28.8057 5.72095 28.7524 5.67151C28.6991 5.62207 28.6458 5.57263 28.5925 5.52318C28.5925 5.12765 28.5925 4.68267 28.5925 4.28714C28.5925 4.33658 28.5392 4.33658 28.5392 4.38602C28.6991 4.13882 28.9123 4.03993 29.1789 4.08937C29.4454 3.99049 29.6587 4.03993 29.8186 4.2377C30.0852 4.48491 30.1385 4.48491 30.0319 4.33658C30.0319 4.73212 30.0319 5.17709 30.0319 5.57263C30.0852 5.47374 30.1918 5.32542 30.2451 5.22653C30.6183 4.68268 30.405 3.84217 29.7653 3.54552C29.1256 3.10054 28.3259 3.24886 27.9528 3.84217Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M37.5228 3.07283C37.6295 3.02338 37.7361 2.97394 37.8427 2.9245C38.0026 2.87506 38.0026 2.82562 37.896 2.9245C37.6295 2.97394 37.4162 2.9245 37.203 2.77617C37.0964 2.67729 37.0964 2.62785 37.0964 2.52897C37.043 2.43008 37.3096 2.3312 37.043 2.52897C37.0964 2.47952 37.1497 2.43008 37.2563 2.38064C37.3629 2.43008 37.3629 2.38064 37.203 2.38064C37.3096 2.43008 37.3096 2.43008 37.1497 2.3312C37.3629 2.43008 37.0964 2.23232 37.043 2.18287C36.7765 1.93567 36.6166 1.68846 36.35 1.44125C35.8702 0.946832 34.964 0.996273 34.4842 1.44125C33.9511 1.93567 34.0044 2.67729 34.4842 3.17171C35.0706 3.76501 35.4971 4.40775 36.35 4.7044C37.4162 5.05049 38.589 4.75384 39.2288 3.86389C39.9218 2.97394 39.8685 1.78734 39.0155 0.996273C38.1626 0.155764 37.1497 0.452414 36.1901 0.89739C35.5504 1.19404 35.3371 2.03455 35.7103 2.57841C36.0835 3.22115 36.8831 3.36948 37.5228 3.07283Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M46.0499 6.62171C46.6896 6.77004 47.3826 6.77004 47.969 6.42394C48.5021 6.12729 48.8753 5.53399 48.9286 4.94069C48.9286 4.44628 48.7153 3.95186 48.3422 3.65521C47.8091 3.21023 47.116 3.11135 46.423 3.25968C45.73 3.408 45.3035 4.14963 45.5168 4.79237C45.73 5.43511 46.423 5.83065 47.1694 5.63288C47.3826 5.58344 46.7962 5.63288 47.0094 5.63288C47.2227 5.63288 46.6896 5.58344 46.7962 5.58344C47.0094 5.63288 46.4763 5.43511 46.6363 5.53399C46.7429 5.58344 46.7962 5.68232 46.4763 5.43511C46.5829 5.53399 46.5829 5.63288 46.3697 5.28679C46.423 5.38567 46.423 5.48455 46.3164 5.08902C46.3164 5.13846 46.3164 5.13846 46.3164 5.1879C46.2631 4.89125 46.2631 4.84181 46.2631 4.94069C46.2631 5.03958 46.2631 4.99014 46.2631 4.84181C46.3164 4.5946 46.2631 4.69349 46.2631 4.79237C46.2098 4.89125 46.4763 4.44628 46.3164 4.64404C46.3164 4.64404 46.5829 4.34739 46.423 4.49572C46.423 4.49572 46.7429 4.29795 46.583 4.39684C46.423 4.49572 46.9561 4.24851 46.7429 4.34739C46.5296 4.44628 46.8495 4.29795 46.9028 4.34739H46.7429C46.5296 4.34739 47.116 4.39683 46.7962 4.34739C46.1032 4.19907 45.3035 4.54516 45.1436 5.1879C44.9303 5.73176 45.3035 6.47339 46.0499 6.62171Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M57.2642 4.15728C57.3708 4.10784 57.4775 4.0584 57.6374 4.00896H57.744C57.9039 3.95952 57.8506 3.95952 57.6374 4.00896C57.4775 4.0584 57.3708 4.00896 57.2642 3.95952C57.2109 3.81119 57.1043 3.95952 57.2642 3.95952C57.2642 3.86063 57.4775 4.30561 57.4775 4.35505C57.4241 4.25617 57.4241 4.10784 57.5308 4.00896C57.5841 3.95952 57.6374 3.91007 57.6907 3.86063C57.7973 3.76175 57.4775 4.00896 57.6907 3.86063C57.6374 3.91007 57.9039 3.86063 57.6374 3.86063C57.5841 3.86063 57.2642 3.81119 57.4775 3.86063C57.6374 3.86063 57.2642 3.81119 57.3175 3.81119C57.1043 3.76175 57.3708 3.86063 57.2109 3.81119C57.1043 3.76175 57.051 3.71231 56.9444 3.66287C57.1043 3.76175 56.9977 3.66287 56.8911 3.61342C56.9444 3.76175 56.7844 3.51454 56.8911 3.61342C56.9444 3.66287 56.9444 4.00896 56.9977 3.81119C57.051 3.11901 56.3579 2.57515 55.6649 2.57515C54.9186 2.57515 54.3855 3.11901 54.3322 3.81119C54.2256 5.93719 57.6374 7.07434 59.29 5.88774C60.5694 4.89891 60.2496 3.36622 59.2367 2.2785C58.2771 1.28966 57.1576 1.58631 56.0381 2.08073C55.3984 2.37738 55.2384 3.21789 55.5583 3.76175C55.8248 4.30561 56.5712 4.40449 57.2642 4.15728Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M56.836 17.4176C56.7827 18.0109 56.836 18.6536 57.1559 19.2469C57.3691 19.6425 57.689 19.8897 58.0622 20.038C58.6486 20.2358 59.1817 20.1863 59.7148 19.9391C60.5677 19.593 61.1541 18.8514 61.2074 17.9614C61.2607 16.8737 60.3012 16.1815 59.235 16.1815C58.5419 16.1815 57.8489 16.7254 57.9022 17.4176C57.9555 18.0603 58.4886 18.6536 59.235 18.6536C59.2883 18.6536 59.5015 18.6536 59.2883 18.6536C59.0217 18.6042 59.3949 18.7031 59.1283 18.6042C59.0217 18.5547 58.9684 18.5547 59.0217 18.5547C59.1283 18.6042 59.075 18.5547 58.8618 18.4064C58.8618 18.4064 58.6486 18.1098 58.7552 18.2581C58.7552 18.2581 58.5952 17.912 58.6486 18.0603C58.5419 17.7142 58.6486 17.7637 58.5952 17.8626C58.5952 17.9614 58.7019 17.5659 58.6486 17.6648C58.6486 17.6648 58.6486 17.7637 58.5952 17.7637C58.5952 17.7637 58.7552 17.467 58.6486 17.6154C58.6486 17.6648 58.5952 17.6648 58.5952 17.7142C58.5419 17.8131 58.7552 17.5165 58.7019 17.5659C58.6486 17.5659 58.6486 17.6153 58.5952 17.6648C58.4886 17.8131 58.7552 17.5659 58.7552 17.5659C58.7552 17.6153 58.6486 17.6648 58.5952 17.6648C58.382 17.7637 58.5419 17.6648 58.5952 17.6648C58.5952 17.6648 58.9684 17.6154 58.8085 17.6154C58.6486 17.6154 59.075 17.6648 59.0217 17.6648C59.2883 17.7637 59.3416 17.8131 59.235 17.7637C59.1817 17.7142 59.235 17.7637 59.3416 17.8131C59.5548 17.9614 59.4482 17.912 59.3949 17.8626C59.2883 17.7637 59.6081 18.1592 59.5015 18.0109C59.4482 17.8626 59.6081 18.2087 59.5548 18.2087L59.5015 18.0109C59.5015 18.0109 59.4482 17.912 59.5015 17.912C59.5015 17.912 59.5548 18.2581 59.5548 18.1098C59.5548 18.0109 59.5548 17.9614 59.5548 17.8626C59.5548 17.7142 59.5548 17.5659 59.5548 17.4176C59.6081 16.7748 58.9151 16.1321 58.2221 16.1815C57.4224 16.1815 56.836 16.7254 56.836 17.4176Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M49.7457 36.4033C50.4387 37.0461 51.3983 37.2438 52.3046 36.8977C52.7844 36.7 53.0509 36.3044 53.3175 35.9089C53.4241 35.81 53.4774 35.6617 53.584 35.5134C53.7973 35.1673 53.7973 34.8212 53.744 34.4257C53.4241 32.7941 51.1851 32.5469 50.1189 33.6346C49.6391 34.129 49.5858 34.9201 50.1189 35.3651C50.652 35.81 51.5049 35.8595 51.9847 35.3651L52.0914 35.2662C52.0914 35.2662 51.8248 35.4145 52.038 35.3156C51.9847 35.3156 51.7715 35.4145 51.9314 35.3651C51.8781 35.3651 51.7715 35.3651 51.7182 35.3651C51.8248 35.3651 51.8248 35.3651 51.6649 35.3651C51.4516 35.3156 51.7182 35.4145 51.5049 35.3156C51.4516 35.2662 51.2384 35.1673 51.2917 35.1673C51.345 35.2167 51.1851 35.019 51.1318 34.9695C51.0785 34.8706 51.0785 34.8706 51.0785 34.9201C51.0785 35.019 51.0785 34.9695 51.0785 34.7718C51.1318 34.574 51.1851 34.3762 51.2384 34.129C51.1318 34.2773 51.0785 34.4257 50.9718 34.574C50.9185 34.6234 50.8652 34.6729 50.8652 34.7718C50.8119 34.8212 50.652 35.019 50.8119 34.8212C51.0252 34.7223 51.1851 34.6234 51.3983 34.5245C51.345 34.574 51.2917 34.574 51.1851 34.574C51.2917 34.5245 51.3983 34.5245 51.5049 34.574C51.345 34.5245 51.3983 34.5245 51.5583 34.574C51.6649 34.6729 51.6649 34.6729 51.5583 34.574C51.0785 34.129 50.1722 34.0796 49.6924 34.574C49.2659 35.1673 49.2126 35.9089 49.7457 36.4033Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M4.91218 22.8561C4.64563 23.7461 3.07961 24.4789 2.88283 24.5739C2.68604 24.6688 2.19016 24.6982 1.92683 24.636C1.66349 24.5739 0.903781 23.669 0.850415 23.251C0.79705 22.833 0.680703 21.7161 1.05387 21.1723C1.64028 20.2823 2.72647 20.2357 3.73936 20.6312C4.69894 20.9773 5.23204 21.9167 4.91218 22.8561Z\"\n        fill=\"#A7AA2D\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 62 / 40,\n  svg: YellowDots,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/yellowLeaf.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Leaf', 'sticker name', 'web-stories');\n\nfunction YellowLeaf({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 59 63\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M30.8112 53.684C31.6757 53.8612 32.5563 54.1059 33.4382 54.1293C34.4308 54.1534 35.5315 54.0854 36.4693 53.7862C37.4954 53.4562 38.5493 53.2325 39.5107 52.7436C40.613 52.1868 41.52 51.5316 42.4222 50.691C42.9411 50.1993 43.4123 49.6625 43.9565 49.1845C44.5322 48.6842 45.1196 48.2229 45.6953 47.7226C46.8257 46.7369 48.0753 45.8088 48.9054 44.5311C49.6119 43.4352 50.2319 42.3058 50.609 41.0328C50.9236 39.9613 51.0294 38.8168 51.344 37.7453C51.544 37.0693 51.5512 36.3876 51.7914 35.7462C52.0514 35.0437 52.0686 34.1976 52.0808 33.4337C52.0892 32.7984 51.8392 32.3767 51.5465 31.8277C51.4299 31.5953 51.3311 31.3659 51.2144 31.1334C50.4922 29.7072 49.4058 28.4118 48.487 27.1084C46.7975 24.7119 45.2527 22.1189 43.1965 20.028C41.8772 18.6923 40.5127 17.4041 39.0684 16.2036C37.9083 15.2277 36.7458 14.159 35.4212 13.4407C34.2485 12.804 33.1548 12.4578 31.8731 12.2914C30.7527 12.1529 29.5885 11.8408 28.4612 11.8487C27.5477 11.8476 26.7194 12.1011 25.8189 12.1852C24.7477 12.2952 23.7033 12.1975 22.6242 12.14C21.8381 12.0963 21.0075 11.9895 20.2133 12.0459C19.4296 12.0949 18.6421 12.2724 17.867 12.3782C16.7149 12.5296 15.5809 12.4164 14.4233 12.493C13.8176 12.5266 13.1822 12.5182 12.7413 12.9864C12.3591 13.3817 12.2475 14.0269 12.2082 14.5738C12.1708 15.0565 12.0013 15.3963 11.8669 15.8529C11.6167 16.6587 11.4079 17.5455 11.2727 18.3804C11.1406 19.1973 11.2767 19.9038 11.448 20.7272C11.6749 21.7631 11.8986 22.817 12.0685 23.8616C12.1923 24.6398 12.2413 25.4235 12.4577 26.1993C12.8234 27.4992 12.9536 28.9338 13.553 30.1634C13.798 30.6673 13.9263 31.2063 14.1219 31.7292C14.5822 32.9625 15.1593 34.1606 15.687 35.3778C16.2456 36.6835 16.7472 37.9977 17.3763 39.2694C17.6361 39.7943 17.7923 40.172 17.97 40.6919C18.2426 41.5697 18.7613 42.3054 19.0834 43.1641C19.2716 43.6765 19.3788 44.2304 19.5565 44.7503C19.765 45.3585 19.871 45.866 19.8626 46.5013C19.8323 47.5297 19.9916 48.8493 20.7235 49.6866C21.3232 50.381 22.287 50.9446 23.1026 51.298C23.954 51.6576 24.832 52.0772 25.7386 52.2248C26.1866 52.3023 26.6111 52.5696 27.0541 52.7293C27.5657 52.9193 27.6869 52.9126 28.1887 52.9995C28.3784 53.023 28.5081 53.0732 28.701 53.0789C28.8821 53.0456 29.1026 53.1576 29.285 53.1707C29.4357 53.206 29.8121 53.2711 29.9115 53.3898C30.362 53.5601 30.302 53.5866 30.8112 53.684Z\"\n        fill=\"#F9E46C\"\n      />\n      <path\n        d=\"M47.8283 45.2419C43.8559 42.326 39.8488 39.3947 36.2923 35.9661C32.7002 32.5053 29.8471 28.4432 26.8566 24.479C25.1517 22.2197 23.4557 19.9683 21.7587 17.7002C21.5308 17.3984 21.0271 17.7045 21.2639 18.0144C24.282 22.0194 27.2842 26.0419 30.3191 30.0463C33.3264 34.0098 36.7911 37.4505 40.6746 40.5717C42.8724 42.3405 45.1572 44.0133 47.4332 45.6781C47.7411 45.9094 48.1363 45.4732 47.8283 45.2419Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M39.8983 39.376C38.7578 39.4388 37.5818 39.6123 36.5201 40.0166C35.4091 40.4397 34.5853 41.1706 33.7416 41.9947C31.9585 43.7309 29.7679 44.8279 27.2697 45.1221C26.8935 45.1625 26.9198 45.7582 27.3039 45.709C29.5266 45.4512 31.6311 44.6098 33.3312 43.1796C34.2696 42.3936 35.0354 41.3877 36.1386 40.8305C37.299 40.2457 38.6499 40.0399 39.9246 39.9716C40.3018 39.948 40.2754 39.3523 39.8983 39.376Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M34.4004 34.395C31.6198 34.751 28.8845 35.3069 26.1019 35.6294C23.4694 35.9289 20.8015 36.0534 18.2092 35.3092C17.8409 35.198 17.7231 35.7743 18.0913 35.8855C20.6581 36.6224 23.319 36.5234 25.9357 36.2412C28.7775 35.9248 31.5878 35.3575 34.4267 34.9907C34.8108 34.9416 34.7766 34.3546 34.4004 34.395Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M42.8985 41.4905C42.6186 40.5856 42.8186 39.6866 42.985 38.789C43.1306 37.9678 43.2011 37.1581 43.1019 36.3216C42.8955 34.5144 42.1402 32.8135 41.4045 31.1621C41.2497 30.8154 40.6789 30.9813 40.8426 31.3361C41.6069 33.0451 42.4175 34.8279 42.5438 36.7055C42.6574 38.3651 41.8281 40.0124 42.3366 41.6645C42.4421 42.03 43.004 41.8561 42.8985 41.4905Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M37.5623 37.2596C37.2735 34.4724 36.9937 31.6932 36.705 28.906C36.4575 26.5373 36.4886 23.8969 35.3445 21.7326C35.1649 21.3952 34.6701 21.7093 34.8496 22.0467C35.4266 23.1413 35.6392 24.3346 35.7777 25.5562C35.9281 26.8361 36.0449 28.1173 36.1784 29.3979C36.4495 32.0262 36.7205 34.6544 36.9837 37.2914C37.0052 37.6604 37.6016 37.6447 37.5623 37.2596Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M27.2261 25.7669C24.9943 26.4453 22.7625 27.1237 20.5396 27.8102C20.1761 27.9258 20.3605 28.4899 20.7239 28.3743C22.9557 27.6959 25.1875 27.0175 27.4104 26.331C27.7827 26.2235 27.5984 25.6594 27.2261 25.7669Z\"\n        fill=\"#4C664A\"\n      />\n      <path\n        d=\"M30.2022 29.0508C30.5414 28.0874 30.6436 27.0998 30.4833 26.0809C30.3022 24.9956 29.6837 23.9111 29.8463 22.8034C29.8998 22.423 29.3203 22.2951 29.2668 22.6755C29.1211 23.6396 29.4839 24.5243 29.7313 25.4473C30.0318 26.5614 30.0558 27.6951 29.6642 28.77C29.5416 29.1195 30.0717 29.4091 30.2022 29.0508Z\"\n        fill=\"#4C664A\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 59 / 63,\n  svg: YellowLeaf,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/plant-based-dyes/yellowRoundBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Round Banner', 'sticker name', 'web-stories');\n\nfunction YellowRoundBanner({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M35.3985 38.5215C35.3971 37.9658 35.3459 37.4102 35.3445 36.8544C35.3443 36.7618 35.3435 36.4376 35.3934 36.4375L35.3437 36.5303C35.1442 36.5771 35.0943 36.5772 34.9444 36.5312C34.8446 36.5315 34.8944 36.485 34.9443 36.4849C34.9942 36.4848 34.8449 36.6704 34.795 36.6705C34.8449 36.6704 34.6455 36.7635 34.6455 36.7635C34.5956 36.7636 34.5457 36.8101 34.4958 36.8102C34.7455 36.8559 35.045 36.8552 35.2947 36.9009C35.3447 36.9471 35.445 37.1321 35.3453 37.1786C35.8434 36.7606 35.7916 35.9734 35.3414 35.5577C34.8411 35.0958 34.0925 35.1439 33.5943 35.562C32.3987 36.5374 32.8032 38.6668 34.4014 39.0334C35.9496 39.3538 37.4432 37.7756 37.39 36.4327C37.3364 34.9045 35.4867 33.7512 33.9913 34.5884C32.4959 35.4257 32.8496 37.231 32.9028 38.5739C32.9063 40.0096 35.4021 40.0035 35.3985 38.5215Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M30.8894 16.8761C30.2913 17.248 29.5935 17.6665 29.3955 18.3617C29.1476 19.057 29.4489 19.7972 29.9493 20.3055C30.7499 21.0908 32.2485 21.5503 33.3963 21.4549C34.8935 21.3586 35.9885 20.0592 35.5359 18.671C35.0835 17.3753 33.5349 16.8697 32.1875 17.0119C31.5387 17.0598 30.9409 17.5243 30.9425 18.1727C30.9438 18.7284 31.4944 19.3755 32.1931 19.3275C32.3928 19.327 32.6423 19.2801 32.842 19.3259L33.1917 19.4177C33.092 19.4642 33.1912 19.2324 33.1912 19.2324C33.1409 19.0473 33.391 19.2782 33.0912 19.14C32.8913 19.0479 32.3421 19.0029 32.0423 18.8647C31.7924 18.7264 31.742 18.5413 31.7429 18.9117C31.7438 19.2822 31.8431 19.0504 32.1422 18.9108C33.4878 18.0276 32.2351 16.0392 30.8894 16.8761Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M15.651 23.4323C14.3004 22.2314 14.9803 19.889 16.1401 19.3093C17.3 18.7296 18.6973 18.9903 19.6848 19.5786C21.2343 20.4547 21.1889 22.3073 19.8938 23.422C18.7481 24.3973 16.8016 24.4947 15.651 23.4323Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M9.16563 12.5292C9.36765 13.5012 9.17221 15.2393 8.43938 15.6963C7.70655 16.1532 7.67912 16.0521 7.29899 16.2301C6.91886 16.408 4.98266 16.6148 5.02898 15.1327C4.97568 13.7435 4.72037 11.3822 6.56599 10.8683C7.81308 10.5411 8.96327 11.4182 9.16563 12.5292Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.9279 29.1922C16.9334 29.1738 16.9384 29.1552 16.9431 29.1363C17.1904 28.2095 16.4397 27.424 15.4413 27.3801C15.0849 27.381 14.7288 27.4648 14.3993 27.6069C13.7993 27.4198 13.2161 27.6546 12.8475 28.1273C12.723 28.2665 12.5611 28.3827 12.3991 28.4988C12.2372 28.615 12.0752 28.7312 11.9508 28.8704C11.4529 29.3811 11.3046 29.9835 11.3562 30.678C11.5091 31.9744 12.4604 33.1762 13.9581 33.2652C14.0649 33.2725 14.1702 33.2624 14.2718 33.2375C14.7057 33.6206 15.2598 33.8172 15.9557 33.631C17.8498 33.1304 17.9407 30.4831 16.9279 29.1922Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M27.6566 36.3637C27.6572 36.5952 27.7072 36.6414 27.7069 36.5025C27.6575 36.7342 27.6576 36.7805 27.7072 36.6414C27.6078 36.8269 27.608 36.8732 27.6576 36.7805C27.6575 36.7342 27.7075 36.734 27.7073 36.6877C27.5579 36.827 27.558 36.8733 27.6077 36.7806L27.6575 36.7342C27.7073 36.6877 27.7073 36.6877 27.508 36.8272C27.5579 36.827 27.5578 36.7807 27.6077 36.7806C27.8071 36.6412 27.3584 36.8738 27.5579 36.827C27.7076 36.7804 27.6576 36.7805 27.4082 36.8274C27.4581 36.8273 27.508 36.8272 27.508 36.8272C27.4581 36.8273 27.3583 36.8275 27.3082 36.7813C27.4082 36.8274 27.3582 36.7812 27.1584 36.7354C27.0083 36.5968 26.9584 36.5969 27.0584 36.6893C26.9583 36.5506 26.9082 36.5044 26.9584 36.5969C27.0085 36.6894 27.0084 36.6431 26.9081 36.4581C26.8579 36.3193 26.8575 36.1804 26.907 35.995C26.8575 36.1804 27.0561 35.7168 26.9566 35.8559C27.1059 35.6703 27.1557 35.6239 27.0561 35.7168C26.9565 35.8096 27.0063 35.7632 27.2056 35.6238C27.1558 35.6702 27.1059 35.6703 27.0561 35.7168C26.8566 35.8099 27.0561 35.7168 27.1559 35.7165C27.0561 35.7168 27.0063 35.7632 26.9565 35.8096C26.9066 35.8098 26.8566 35.8099 26.8068 35.8563C26.6073 35.9031 27.1562 35.8555 26.9067 35.8561C26.2578 35.8576 25.6101 36.3686 25.6616 37.0169C25.713 37.6188 26.2135 38.1733 26.9123 38.1716C27.6111 38.1699 28.3092 37.8904 28.8074 37.4724C29.6046 36.8684 29.602 35.8032 28.9015 35.1102C28.251 34.4634 27.2027 34.4197 26.405 34.8384C25.6075 35.3035 25.1602 36.0919 25.3121 36.9714C25.4633 37.5731 26.2129 37.9418 26.8614 37.755C27.5099 37.6145 27.808 37.0117 27.6566 36.3637Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M26.4487 17.5815C26.4479 17.2574 26.4472 16.9795 26.4464 16.6553C26.445 16.0533 25.8945 15.4525 25.1958 15.5005C24.4971 15.5486 23.9491 16.013 23.9507 16.6614C23.9515 16.9856 23.9522 17.2634 23.9529 17.5876C23.9544 18.1897 24.5049 18.7904 25.2036 18.7424C25.9023 18.6944 26.4503 18.2299 26.4487 17.5815Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M41.3307 20.6019C41.0831 21.3898 41.335 22.3618 42.2343 22.6838C42.5341 22.822 42.8837 22.9137 43.183 22.8204C43.4823 22.727 43.7314 22.5412 43.9305 22.3091C44.03 22.17 44.1793 21.9843 44.2788 21.8452C44.6269 21.3349 44.3755 20.5482 43.8257 20.2717C43.176 19.9491 42.5276 20.1359 42.1296 20.6926C42.0301 20.8318 41.8808 21.0174 41.7813 21.1566C42.3301 21.0163 42.9287 20.8759 43.4774 20.7356C43.3276 20.6897 43.3273 20.5971 43.5275 20.7818C43.4774 20.7356 43.4774 20.7356 43.5775 20.828C43.6775 20.9204 43.7276 20.9666 43.7279 21.1055C43.6775 20.9204 43.7287 21.4297 43.7281 21.1981C43.7282 21.2445 43.7285 21.3371 43.7286 21.3834C43.7285 21.3371 43.7284 21.2908 43.7782 21.2443C43.9765 20.6881 43.5254 19.9482 42.9261 19.8107C42.177 19.6736 41.5289 19.9994 41.3307 20.6019Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M39.8021 28.2935C40.3028 28.9407 41.0027 29.3558 41.9013 29.3999C42.5503 29.4446 43.2485 29.2114 43.7467 28.7934C44.3445 28.3288 44.5421 27.4947 44.1413 26.8473C43.6902 26.1074 42.7415 25.9708 41.8927 25.8802C41.2437 25.8355 40.5963 26.4391 40.6476 27.0411C40.6992 27.7356 41.1994 28.1512 41.8983 28.1958C41.9982 28.1956 42.198 28.2877 41.8484 28.1959C41.8983 28.1958 41.9482 28.1957 41.9983 28.2419C42.0981 28.2416 42.1981 28.2877 42.298 28.3338C42.4978 28.3796 41.9982 28.1956 42.1481 28.2878C42.1481 28.2878 42.1982 28.334 42.2481 28.3339C42.348 28.38 41.9979 28.1029 42.0981 28.2416C42.1982 28.334 41.8978 27.9643 41.9979 28.1029C42.0981 28.2416 41.8973 27.779 41.8977 27.9179C41.9479 28.0568 41.8468 27.5476 41.8472 27.6865C41.8475 27.8254 41.8962 27.3159 41.8965 27.4548C41.847 27.5939 42.0455 27.1303 41.9959 27.2693C41.8965 27.4548 42.2449 27.0372 42.0955 27.1765C41.8963 27.3622 42.3448 27.0369 42.1952 27.1299C42.1453 27.13 42.0456 27.1766 42.0457 27.2229C42.0457 27.2229 42.3949 27.1294 42.2452 27.1298C42.1952 27.1299 42.1952 27.1299 42.1454 27.1763C42.0955 27.1765 42.0456 27.1766 42.0457 27.2229C41.8961 27.2696 42.395 27.1757 42.2453 27.1761C42.1454 27.1763 42.0955 27.1765 41.9957 27.1767C41.796 27.1772 42.2953 27.2223 42.1955 27.2225C42.1455 27.2227 42.1455 27.2227 42.0956 27.2228C42.0457 27.2229 41.9957 27.1767 41.9957 27.1767C42.2953 27.2223 42.2456 27.315 42.1455 27.2227C42.0956 27.2228 42.0955 27.1765 42.0456 27.1766C41.9457 27.1305 42.2956 27.3612 42.1457 27.269C42.0956 27.2228 42.0956 27.2228 42.0456 27.1766C41.8955 27.038 42.2458 27.4077 42.0957 27.2691C41.8955 27.038 41.6953 26.807 41.3458 26.7615C41.0461 26.6696 40.6469 26.7169 40.3977 26.9027C39.6992 27.0434 39.4016 27.7851 39.8021 28.2935Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M54.7208 25.8489C54.7703 25.6636 54.7702 25.6173 54.7208 25.8489C54.5714 25.9882 54.4218 26.0349 54.2222 26.0817C53.9225 25.9898 53.6227 25.8516 53.323 25.7597C53.1728 25.5748 53.1728 25.5748 53.2229 25.6673C53.2229 25.6673 53.223 25.7136 53.273 25.7135C53.3231 25.806 53.3231 25.806 53.273 25.7135C53.2228 25.621 53.2228 25.621 53.273 25.7135C53.2731 25.7598 53.3233 25.8987 53.3233 25.8987C53.2232 25.76 53.3228 25.6671 53.3232 25.8523C53.2738 26.084 53.3724 25.5743 53.3231 25.806C53.3233 25.8987 53.174 26.0843 53.3729 25.7596C53.2734 25.8988 53.4725 25.6667 53.5223 25.6203C53.5721 25.5739 53.6718 25.5273 53.7715 25.4808C53.6219 25.5274 53.6718 25.5273 53.8714 25.4805C54.2212 25.6649 54.5711 25.8493 54.9709 26.0336C54.8707 25.8949 54.7205 25.71 54.6203 25.5713C54.2697 25.0627 53.5203 24.7867 52.9222 25.1586C52.3739 25.4841 52.0762 26.2259 52.4768 26.7343C52.577 26.873 52.7271 27.0579 52.8273 27.1966C53.0777 27.5202 53.4777 27.7971 53.9268 27.7497C54.7751 27.655 55.4231 27.2829 55.7208 26.5412C55.9194 26.0776 55.8682 25.5683 55.7671 25.0591C55.5658 24.3649 55.0649 23.6714 54.1666 23.7199C53.2682 23.7684 52.521 24.3723 52.3732 25.2063C52.225 25.8087 52.5761 26.5025 53.2253 26.6399C53.7747 26.7775 54.5725 26.4514 54.7208 25.8489Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M15.064 15.942C15.8658 17.2368 15.134 18.3816 15.1202 18.5354C15.1064 18.6892 14.5739 19.6945 13.925 19.6961C13.2262 19.6978 12.6759 19.1897 12.6744 18.5413C12.6226 17.8005 12.4709 16.9672 12.7686 16.2255C12.9671 15.7619 13.3158 15.4832 13.8147 15.3893C14.3138 15.3418 14.8134 15.5258 15.064 15.942Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M8.10198 6.18699C8.05251 6.37236 8.10232 6.32592 8.10198 6.18699C8.10187 6.14068 8.15167 6.09424 8.15156 6.04793C8.20125 5.95519 8.25094 5.86244 8.15144 6.00162C8.20113 5.90888 8.25094 5.86244 8.25071 5.76982C8.3502 5.63064 8.39978 5.49159 8.49927 5.35241C8.54896 5.25966 8.54896 5.25966 8.49927 5.35241C8.54908 5.30598 8.59877 5.21323 8.69848 5.16668C8.39922 5.26003 8.10007 5.39969 7.8008 5.49304C7.95055 5.49268 7.95055 5.49268 7.75089 5.49316C7.90074 5.53911 7.85072 5.49292 7.65094 5.44709C7.40103 5.30877 7.20058 4.98507 7.19991 4.7072C7.24926 4.47552 7.24915 4.42921 7.19946 4.52195C7.29884 4.33646 7.29872 4.29015 7.24903 4.3829C7.19923 4.42933 7.04994 4.61494 7.19934 4.47564C7.34875 4.33634 7.14954 4.52207 7.09974 4.56851C7.14988 4.66101 7.10008 4.70744 7.00036 4.754C6.95056 4.80043 6.90075 4.84686 6.85095 4.8933C6.60182 5.07915 7.05027 4.75388 6.90075 4.84686C6.4025 5.21857 6.05467 5.86778 6.45534 6.42255C6.80587 6.88482 7.6053 7.20706 8.15347 6.83523C9.15008 6.13813 10.5442 4.69907 9.29375 3.63694C8.94356 3.31361 8.44407 3.17588 7.94492 3.1771C7.24611 3.17879 6.84769 3.55026 6.49952 4.06053C6.00183 4.6638 5.70425 5.45182 5.60622 6.19305C5.55777 6.79523 6.20813 7.3957 6.85691 7.34781C7.60553 7.29968 8.05364 6.83547 8.10198 6.18699Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M16.2094 4.30792C16.2588 4.12255 16.1099 4.4471 16.0601 4.49353C15.8607 4.63295 16.2094 4.30792 16.0601 4.49353C15.8107 4.58676 16.2594 4.35411 16.0601 4.49353C16.2596 4.44673 15.8105 4.49414 16.11 4.49341C15.8602 4.40139 16.2098 4.49317 16.11 4.49341C16.01 4.44734 16.3598 4.58542 16.11 4.49341C16.06 4.44722 16.3598 4.58542 16.11 4.49341C16.16 4.5396 16.16 4.5396 16.0099 4.40103C15.9596 4.2159 15.9096 4.21602 15.9599 4.35484C16.0588 3.9841 16.1578 3.61337 16.2567 3.24263C16.5555 2.96403 16.8052 3.00974 17.0551 3.14807C17.1051 3.19426 17.1051 3.19426 17.0051 3.10188C17.1051 3.19426 17.1052 3.24057 17.055 3.10175C16.7542 2.54674 15.9051 2.36356 15.3569 2.68907C14.7587 3.01471 14.6106 3.70975 14.9115 4.26476C15.513 5.32847 17.0613 5.6952 18.0576 4.85917C18.4063 4.58045 18.505 4.11709 18.4043 3.74684C17.8005 1.7569 14.406 1.67252 13.812 3.71169C13.3662 5.14844 15.8135 5.74455 16.2094 4.30792Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M26.1805 5.79236C25.8821 6.2562 25.6338 6.76624 25.9846 7.32113C26.1851 7.69114 26.5352 7.96816 26.9349 8.10612C27.7341 8.33574 28.5817 7.96318 28.9295 7.31397C29.1283 6.94299 29.1771 6.47976 28.9267 6.15618C28.476 5.55522 27.9263 5.27869 27.1775 5.23419C26.778 5.18885 26.3789 5.28245 25.9297 5.28354C25.2808 5.28512 24.6331 5.79612 24.6846 6.44436C24.736 7.04629 25.2365 7.60082 25.9353 7.59912C26.2348 7.59839 26.4843 7.55147 26.7838 7.55075C26.8337 7.55062 26.9335 7.55038 26.9834 7.55026C27.1333 7.59621 27.1831 7.54978 26.9834 7.55026C27.0333 7.55014 27.1332 7.5499 27.1333 7.59621C27.0334 7.59645 26.9834 7.55026 26.9334 7.50407C26.8834 7.45788 26.8333 7.41169 26.7833 7.3655C26.7824 6.99501 26.7814 6.5782 26.7805 6.20771C26.7806 6.25402 26.7307 6.25414 26.7308 6.30045C26.88 6.06853 27.0794 5.97542 27.3291 6.02113C27.5785 5.9279 27.7782 5.97372 27.9284 6.15861C28.1786 6.38956 28.2285 6.38944 28.1283 6.25075C28.1292 6.62124 28.1302 7.03804 28.1311 7.40854C28.1808 7.31579 28.2803 7.17661 28.33 7.08387C28.6782 6.57359 28.4766 5.78678 27.8769 5.51037C27.2769 5.09502 26.5286 5.23577 26.1805 5.79236Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M35.1394 5.04995C35.2391 5.0034 35.3388 4.95684 35.4385 4.91029C35.5882 4.86361 35.5881 4.8173 35.4885 4.91017C35.239 4.95708 35.0392 4.91126 34.8392 4.77281C34.7392 4.68043 34.7391 4.63412 34.7388 4.54149C34.6887 4.44899 34.938 4.35576 34.6889 4.54161C34.7387 4.49518 34.7885 4.44875 34.8882 4.40219C34.9882 4.44826 34.9881 4.40195 34.8383 4.40232C34.9383 4.44839 34.9383 4.44838 34.7883 4.35613C34.9882 4.44826 34.7382 4.26362 34.6881 4.21743C34.438 3.98648 34.2877 3.75529 34.0375 3.52434C33.5872 3.06231 32.7387 3.11069 32.2905 3.52858C31.7925 3.99291 31.8441 4.68746 32.2945 5.14949C32.8449 5.70389 33.2457 6.30497 34.045 6.5809C35.0441 6.90266 36.1415 6.62212 36.7385 5.78706C37.3853 4.95187 37.3327 3.84051 36.5323 3.10147C35.7317 2.31611 34.784 2.59628 33.8866 3.01527C33.2883 3.2946 33.0905 4.08238 33.4411 4.59096C33.792 5.19216 34.5411 5.32928 35.1394 5.04995Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M43.1315 8.35476C43.7308 8.49224 44.3797 8.49066 44.928 8.16515C45.4264 7.88607 45.7745 7.32948 45.8231 6.77362C45.8219 6.3105 45.6211 5.84787 45.2711 5.57085C44.7709 5.15526 44.1218 5.06421 43.4732 5.20472C42.8247 5.34523 42.427 6.04088 42.6282 6.64244C42.8293 7.24401 43.4791 7.61293 44.1774 7.42598C44.377 7.37918 43.828 7.42683 44.0277 7.42635C44.2273 7.42586 43.7281 7.38076 43.8279 7.38052C44.0277 7.42634 43.5281 7.24231 43.6781 7.33457C43.778 7.38064 43.8281 7.47314 43.5281 7.24231C43.6281 7.33469 43.6284 7.42732 43.4279 7.10362C43.4781 7.19612 43.4783 7.28874 43.3776 6.91849C43.3777 6.96481 43.3777 6.96481 43.3778 7.01112C43.3272 6.73337 43.3271 6.68706 43.3273 6.77968C43.3275 6.8723 43.3274 6.82599 43.3271 6.68706C43.3764 6.45538 43.3267 6.54812 43.327 6.64075C43.2773 6.73349 43.5258 6.31608 43.3765 6.50169C43.3765 6.50169 43.6254 6.22321 43.476 6.36251C43.476 6.36251 43.7751 6.17654 43.6256 6.26953C43.476 6.36251 43.9746 6.12974 43.7752 6.22285C43.5758 6.31596 43.8749 6.1763 43.9249 6.22249L43.7752 6.22285C43.5755 6.22333 44.1247 6.26831 43.8251 6.22273C43.1759 6.08537 42.4279 6.41137 42.2796 7.01379C42.0812 7.5237 42.4323 8.21752 43.1315 8.35476Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M53.6261 6.02084C53.7258 5.97428 53.8255 5.92773 53.9752 5.88105L54.075 5.88081C54.2246 5.83413 54.1747 5.83426 53.9752 5.88105C53.8255 5.92773 53.7256 5.88166 53.6256 5.83559C53.5754 5.69678 53.4759 5.83595 53.6256 5.83559C53.6254 5.74297 53.8261 6.15929 53.8262 6.2056C53.7761 6.1131 53.7757 5.97416 53.8753 5.88129C53.9251 5.83486 53.9749 5.78843 54.0247 5.742C54.1243 5.64913 53.8254 5.88142 54.0247 5.742C53.9749 5.78843 54.2244 5.74151 53.9748 5.74212C53.9249 5.74224 53.6253 5.69666 53.8251 5.74248C53.9748 5.74212 53.6253 5.69666 53.6752 5.69653C53.4754 5.65071 53.7252 5.74272 53.5754 5.69678C53.4754 5.65071 53.4254 5.60452 53.3255 5.55845C53.4754 5.65071 53.3754 5.55833 53.2754 5.51226C53.3257 5.65107 53.1754 5.41988 53.2754 5.51226C53.3255 5.55845 53.3263 5.88263 53.3757 5.69726C53.4241 5.04878 52.7739 4.54093 52.125 4.5425C51.4262 4.5442 50.9283 5.05484 50.88 5.70333C50.785 7.69497 53.9821 8.75237 55.5268 7.63713C56.7225 6.70799 56.4195 5.27306 55.4687 4.25651C54.5679 3.33246 53.5204 3.61288 52.4733 4.07854C51.875 4.35786 51.7272 5.14552 52.0279 5.65422C52.2787 6.16305 52.9778 6.25397 53.6261 6.02084Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M53.2553 18.4426C53.2068 18.9985 53.2582 19.6004 53.559 20.1554C53.7596 20.5254 54.0596 20.7563 54.4094 20.8943C54.9589 21.0783 55.4579 21.0307 55.9565 20.798C56.7543 20.4718 57.3017 19.7758 57.3496 18.9421C57.3971 17.9231 56.497 17.2769 55.4987 17.2794C54.8498 17.2809 54.2021 17.7919 54.2536 18.4402C54.305 19.0421 54.8055 19.5966 55.5043 19.5949C55.5542 19.5948 55.7539 19.5943 55.5542 19.5948C55.3046 19.5491 55.6542 19.6409 55.4044 19.5489C55.3044 19.5028 55.2545 19.5029 55.3044 19.5028C55.4044 19.5489 55.3544 19.5027 55.1544 19.3642C55.1544 19.3642 54.954 19.0869 55.0542 19.2255C55.0542 19.2255 54.9037 18.9017 54.9539 19.0405C54.8533 18.7166 54.9532 18.7627 54.9035 18.8554C54.9038 18.948 55.0027 18.5773 54.953 18.67C54.953 18.67 54.9532 18.7627 54.9033 18.7628C54.9033 18.7628 55.0524 18.4846 54.9529 18.6237C54.953 18.67 54.9031 18.6702 54.9032 18.7165C54.8535 18.8092 55.0525 18.5309 55.0027 18.5773C54.9528 18.5774 54.9529 18.6237 54.9031 18.6702C54.8036 18.8093 55.0526 18.5772 55.0526 18.5772C55.0527 18.6235 54.953 18.67 54.9031 18.6702C54.7037 18.7633 54.8532 18.6703 54.9031 18.6702C54.9031 18.6702 55.2524 18.623 55.1026 18.6234C54.9529 18.6237 55.3523 18.6691 55.3024 18.6692C55.5522 18.7612 55.6022 18.8074 55.5023 18.7613C55.4523 18.7151 55.5023 18.7613 55.6022 18.8074C55.8022 18.9459 55.7023 18.8998 55.6523 18.8536C55.5522 18.7612 55.8526 19.131 55.7524 18.9923C55.7022 18.8535 55.8527 19.1773 55.8028 19.1774L55.7524 18.9923C55.7524 18.9923 55.7023 18.8998 55.7522 18.8997C55.7522 18.8997 55.8029 19.2237 55.8026 19.0848C55.8024 18.9922 55.8022 18.9459 55.802 18.8532C55.8017 18.7143 55.8013 18.5754 55.801 18.4364C55.8495 17.8343 55.1991 17.2338 54.5503 17.2817C53.8016 17.2835 53.2538 17.7943 53.2553 18.4426Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M46.6598 36.2425C47.3101 36.843 48.2091 37.0261 49.0568 36.6998C49.5056 36.5135 49.7543 36.1424 50.003 35.7713C50.1026 35.6784 50.1521 35.5394 50.2516 35.4002C50.4505 35.0755 50.4497 34.7513 50.3989 34.381C50.0957 32.8534 47.9987 32.6269 47.0029 33.6482C46.5548 34.1124 46.5066 34.8535 47.0068 35.2691C47.507 35.6847 48.3057 35.7291 48.7538 35.2649L48.8534 35.172C48.8534 35.172 48.6042 35.3116 48.8036 35.2185C48.7537 35.2186 48.5543 35.3117 48.7039 35.265C48.654 35.2651 48.5542 35.2654 48.5043 35.2655C48.6041 35.2653 48.6041 35.2653 48.4543 35.2656C48.2546 35.2198 48.5044 35.3118 48.3045 35.2197C48.2545 35.1735 48.0546 35.0813 48.1045 35.0812C48.1545 35.1274 48.0043 34.9425 47.9543 34.8963C47.9042 34.8038 47.9042 34.8038 47.9043 34.8501C47.9045 34.9428 47.9044 34.8965 47.9039 34.7112C47.9534 34.5258 48.0029 34.3405 48.0522 34.1088C47.9527 34.248 47.9031 34.387 47.8037 34.5262C47.7538 34.5726 47.704 34.6191 47.7043 34.7117C47.6545 34.7581 47.5052 34.9437 47.6545 34.7581C47.8539 34.665 48.0034 34.572 48.2029 34.4789C48.1531 34.5254 48.1031 34.5255 48.0033 34.5257C48.103 34.4792 48.2029 34.4789 48.3028 34.525C48.1529 34.479 48.2029 34.4789 48.3527 34.5249C48.4528 34.6173 48.4528 34.6173 48.3527 34.5249C47.9025 34.1092 47.0538 34.0649 46.6057 34.5291C46.2077 35.0858 46.1595 35.7806 46.6598 36.2425Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M4.65044 23.655C4.40289 24.4892 2.93826 25.1792 2.75422 25.2686C2.57019 25.358 2.10595 25.3866 1.85924 25.329C1.61254 25.2714 0.899146 24.4255 0.848227 24.0341C0.797309 23.6427 0.685828 22.5968 1.034 22.0865C1.58104 21.2516 2.59795 21.2054 3.54724 21.5736C4.4465 21.8956 4.94779 22.7743 4.65044 23.655Z\"\n        fill=\"#A7AA2D\"\n      />\n      <path\n        d=\"M19.8092 6.81142C17.7314 7.42931 16.0902 9.1172 15.1566 11.0613C14.2231 13.0054 13.937 15.2358 13.922 17.4059C13.9069 20.1487 14.3436 22.9368 15.5331 25.4083C17.5356 29.5677 21.5106 32.4914 25.7567 34.3149C30.2888 36.259 35.5587 37.0728 40.1209 35.2191C43.0118 34.0436 45.436 31.8283 47.1525 29.206C49.3809 25.7851 50.4348 21.5653 49.8025 17.5416C49.1701 13.5178 46.7309 9.73508 43.1925 7.73072C41.2953 6.66072 39.1573 6.08805 37.0041 5.72636C31.0717 4.6865 25.5459 5.03312 19.8092 6.81142Z\"\n        fill=\"#F9E46C\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 40,\n  svg: YellowRoundBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/rock-music-festival/flames.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Flames', 'sticker name', 'web-stories');\n\nfunction Flames({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 60 30\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M15.8113 6.88872C14.3574 8.38987 13.6524 11.1481 13.9514 14.2886C14.1289 16.1443 14.3915 17.9724 14.5252 19.8373C14.7318 22.6969 13.9685 24.7644 12.6945 25.0315C10.9295 25.4044 10.0907 23.9401 10.2244 20.6247C10.2633 19.6577 10.4092 18.6769 10.5429 17.7652C11 14.6569 10.7933 12.6631 9.8622 10.0015C9.6045 11.8204 9.73578 13.3538 9.73821 14.8503C9.74064 16.6969 9.62395 18.4697 9.1134 20.0767C8.30625 22.6094 6.42939 22.9087 5.67086 20.6846C5.31591 19.6439 5.48123 18.5249 5.50554 17.1665C4.75674 17.9401 4.53794 19.0038 4.3945 20.1873C4.23161 21.5088 4.10032 22.858 3.85478 24.1243C3.43175 26.3024 2.4447 27.0115 1.57677 25.3676C0.0524233 22.4804 0.560538 19.386 0.740445 17.7559C1.17076 13.8787 1.74724 10.5023 0.164551 6.87836C0.164551 6.57444 0.164551 6.20912 0.164551 5.9052C1.28046 7.18533 2.19672 10.0338 1.87094 12.8795C1.65213 14.7951 1.54516 16.6646 1.32636 18.5802C1.05893 20.9424 0.747738 23.1113 1.90498 24.6355C2.62703 25.584 3.09625 25.3722 3.39528 23.7974C3.62382 22.5955 3.71377 21.3062 3.89124 20.0675C4.28509 17.3139 4.97798 15.9509 6.5704 14.8457C6.65549 15.9877 5.42531 19.9939 6.84512 21.1727C7.49181 21.7114 8.51533 20.5971 8.82652 19.1834C9.24955 17.2494 9.29574 15.2371 9.12799 13.1696C8.93349 10.7659 9.08423 8.44973 9.74551 6.16117C10.38 6.90253 11.9603 14.6615 10.8201 19.7222C10.2196 22.3791 10.966 24.0414 12.1791 24.1197C13.3461 24.198 13.7885 23.4428 13.8736 21.2233C13.9514 19.2387 13.7934 17.3047 13.5017 15.4029C12.3712 8.01688 17.287 4.29624 17.5496 4.3561C17.0585 5.6132 16.6014 6.70453 16.1905 7.86032C15.7821 9.00691 15.4952 10.2594 15.5949 11.6961C15.6873 13.0269 16.1055 13.9478 16.7521 14.3668C17.4061 14.7951 17.7903 13.8557 18.1792 13.0729C18.3908 12.6447 18.7968 11.7559 18.7968 11.7559C18.7968 11.7559 21.1355 15.1865 19.5893 20.2932C19.4702 20.6892 19.3073 21.0391 19.2028 21.4444C18.9669 22.3607 18.4904 23.3369 19.0788 24.2901C19.6209 25.1696 20.2798 25.1051 20.9046 24.5157C21.4978 23.954 21.7531 22.9455 21.8552 21.7713C22.0108 19.98 22.1372 18.1934 22.1323 16.3699C22.1275 14.5326 22.3195 12.7506 22.8204 11.1481C23.2337 9.81734 23.7904 8.81811 24.8334 8.75364C24.5027 9.98312 24.1745 10.9225 23.9873 11.954C23.54 14.4037 24.2499 15.8634 25.587 15.3477C26.9777 14.8135 27.6705 13.2709 27.7192 10.6002C27.7629 8.09977 27.2208 5.88949 26.7224 3.66078C26.5741 2.9977 26.2459 2.41289 26.3917 1.57943C28.66 2.52801 31.1836 7.63469 31.3051 10.6186C31.3659 12.1289 31.1131 13.4689 30.6755 14.6708C30.1771 16.043 29.6179 17.3415 29.0685 18.6493C28.4801 20.0537 28.0765 21.6055 28.006 23.3876C27.9501 24.7414 28.1398 26.0215 28.8715 26.6017C29.6665 27.2325 30.1649 26.2149 30.6147 25.1972C31.0717 24.1612 31.1398 22.8488 31.3295 21.6193C31.4948 20.5556 31.6552 19.8879 32.353 18.8841C32.4794 20.6063 32.2047 21.6746 32.3603 23.0284C32.4867 24.1151 32.6253 25.1466 33.3011 25.386C33.9284 25.6071 34.5337 25.4827 34.8887 24.2993C35.1537 23.4198 35.2582 22.462 35.1756 21.4582C35.0905 20.4129 35.037 19.3492 34.896 18.3315C34.4511 15.1404 35.0224 12.7137 36.4373 10.8764C36.7704 10.4436 37.1035 10.02 37.439 9.59632C38.8321 7.85111 39.3718 5.43361 39.0752 2.35764C39.0071 1.65311 38.8029 0.939371 39.0873 0C39.8775 0.888718 40.1133 2.37145 40.4682 3.66078C41.341 6.83807 41.6984 10.0338 40.5946 13.34C40.2762 14.2932 40.089 15.4213 40.1765 16.5955C40.2567 17.7007 40.512 18.6585 41.1319 18.9946C41.7762 19.3446 42.2138 18.7368 42.5469 17.7467C42.6903 17.3185 42.7389 16.7291 43.1206 16.5081C43.867 18.2579 43.9424 20.1136 43.3978 22.112C43.179 22.9133 42.8483 23.7652 43.3273 24.571C43.7527 25.2847 44.239 24.9348 44.696 24.571C46.2301 23.3461 46.7747 21.3338 46.111 18.617C45.0072 14.1136 45.1434 12.2901 47.9003 7.30775C48.0583 8.20568 47.893 8.97467 47.8031 9.71143C47.6402 11.056 47.6013 12.4098 47.6645 13.7636C47.7569 15.7621 48.4473 16.9731 49.5705 17.2218C50.6305 17.4566 51.4717 16.4344 51.7902 14.505C52.0187 13.1097 52.0601 11.6915 51.9215 10.2502C51.8388 9.39371 51.6492 8.52341 51.9482 7.44129C53.5139 11.5948 55.0407 15.5503 54.1071 20.9747C53.8591 22.4252 53.8591 23.977 54.3429 25.3492C54.6468 26.2057 55.0455 26.8319 55.6436 26.7306C56.249 26.6293 56.5991 25.8879 56.7547 24.8979C56.9637 23.5579 57.0999 22.1811 57.2968 20.6063C58.3787 22.0568 59.7426 24.5024 59.8033 26.1602C59.8836 28.3428 59.7863 28.1903 59.8033 29.5487C59.8033 29.7567 59.8033 29.6485 59.8033 29.9885C59.603 30 59.5737 30 59.3122 30C59.4435 27.2371 59.4411 23.3139 57.8001 23.2218C57.3673 23.1988 57.4427 24.2533 57.343 24.8058C56.9856 26.7767 56.3073 27.7943 55.4345 27.6884C54.5253 27.5779 53.6744 26.0169 53.5188 24.1105C53.3899 22.5173 53.565 20.9609 53.7011 19.3906C54.005 15.9094 53.7254 13.98 52.646 11.7283C52.1014 16.6508 51.4182 18.3085 49.8817 18.1796C48.8874 18.0967 47.9441 17.6132 47.4044 15.8173C46.9351 14.2609 47.2585 12.4467 47.0348 10.5219C46.162 12.2487 45.7439 13.9018 46.1547 16.0107C46.3346 16.9317 46.5218 17.848 46.7018 18.769C47.3849 22.2686 45.598 26.3761 43.6044 25.8972C42.6952 25.6807 42.3524 24.3407 42.7341 22.485C43.1814 20.3024 43.2155 20.0583 43.1741 18.1658C42.8702 18.792 42.6903 19.1512 42.5274 19.3768C41.1635 21.2417 39.6149 19.2525 39.6368 16.1995C39.6441 15.0391 39.8386 13.9708 40.0792 12.9302C41.0274 8.83653 41.0007 7.74981 39.6684 3.01612C39.8313 7.63929 38.3701 9.70223 36.7631 11.5579C35.4041 13.1236 34.9932 15.32 35.4163 18.1612C35.567 19.1742 35.6545 20.2333 35.7056 21.2786C35.832 23.9033 35.3166 25.6899 34.3198 26.2471C33.165 26.8918 31.9421 26.6477 31.8619 21.0852C31.5847 22.3699 31.1641 25.3768 30.8165 26.1827C30.2743 27.4398 29.545 28.1673 28.6746 27.5733C27.865 27.0253 27.5466 25.7038 27.4906 24.1704C27.4055 21.845 27.9598 19.9248 28.66 18.1289C29.0393 17.1527 29.4769 16.2548 29.8586 15.2786C31.1034 12.0921 31.0134 9.37529 29.5669 6.53876C28.9688 5.36454 28.3391 4.23177 27.3156 3.56408C27.7726 5.97698 28.254 8.03991 28.2273 10.3515C28.1908 13.5196 27.1551 15.6055 25.5335 16.3653C22.8933 17.604 23.5303 12.0599 23.2847 11.4935C22.7863 13.3584 22.6186 15.2464 22.621 17.208C22.621 19.2571 22.5359 21.297 22.1226 23.208C21.6437 25.4229 20.5569 26.33 19.3559 25.6393C18.3689 25.0729 18.0382 23.954 18.4248 22.1903C18.6363 21.2233 18.9475 20.3162 19.266 19.4505C19.6866 18.3131 19.7862 17.0883 19.6477 15.7805C19.4289 13.7038 18.9986 13.3952 18.0747 14.6293C17.5569 15.32 16.9977 15.8312 16.385 15.2095C15.5876 14.4037 15.1306 13.1374 15.0746 11.3922C15.0211 9.71143 15.5317 8.37145 15.8016 6.88411L15.8113 6.88872Z\"\n        fill=\"#EB6F4A\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 60 / 30,\n  svg: Flames,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/rock-music-festival/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as rockInRotterdamFlames } from './flames';\nimport { default as rockInRotterdamLightning } from './orangeLightning';\nimport { default as rockInRotterdamWhiteLightning } from './whiteLightning';\n\nexport {\n  rockInRotterdamFlames,\n  rockInRotterdamLightning,\n  rockInRotterdamWhiteLightning,\n};\n"
  },
  {
    "path": "packages/stickers/src/rock-music-festival/orangeLightning.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Orange Lightning', 'sticker name', 'web-stories');\n\nfunction OrangeLightning({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 46\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M27.4068 32.1319L55.0627 0L30.8949 19.8735L28.528 13.3109L0 46L25.6004 24.8264L27.4068 32.1319ZM1.2141 44.8176L25.6813 24.5813L27.4762 31.8407L53.9192 1.11813L30.8318 20.1032L28.478 13.577L1.2141 44.8176Z\"\n        fill=\"#F8754C\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 46,\n  svg: OrangeLightning,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/rock-music-festival/whiteLightning.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Lightning', 'sticker name', 'web-stories');\n\nfunction WhiteLightning({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 46\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M55.5 0L27.8756 32.1319L26.0713 24.8264L0.5 46L28.9955 13.3109L31.3597 19.8735L55.5 0Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 46,\n  svg: WhiteLightning,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/curvedArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Curved Arrow', 'sticker name', 'web-stories');\n\nfunction CurvedArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 81 295\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M69.8976 291.272C61.4277 289.856 53.5045 284.451 46.4298 277.049C39.5985 269.9 33.4099 261.063 27.9513 251.348C17.3979 232.562 9.47536 209.935 4.97825 185.578C0.554833 161.623 -0.476371 135.926 2.6153 111.248C5.53805 87.9031 12.0805 65.6718 21.2937 46.9804C30.4653 28.3742 42.3115 13.0597 55.9049 3.77678C57.5821 2.63071 59.2847 1.57159 61.0058 0.599249C62.2276 -0.0939282 62.7046 3.04702 61.4897 3.72958C47.8824 11.4044 35.7739 25.1694 26.1946 42.5354C16.5741 59.9652 9.50164 81.0721 5.78379 103.556C1.88031 127.168 1.96758 152.107 5.42717 175.705C8.96521 199.822 15.9229 222.566 25.5396 241.782C30.4095 251.515 35.9545 260.445 42.0958 268.084C48.6369 276.218 55.9682 283.055 64.0533 286.327C65.9931 287.119 67.9567 287.685 69.9508 288.014C71.2243 288.25 71.1847 291.487 69.8976 291.272Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M69.2679 290.966C62.1282 290.814 54.9887 290.65 47.8492 290.487C48.0328 289.488 48.2163 288.489 48.4067 287.479C50.4917 289.612 53.0512 289.718 55.4472 290.014C58.1967 290.362 60.9542 290.634 63.7128 290.831C66.4645 291.049 69.2242 291.181 71.9852 291.237C74.432 291.286 77.0753 291.588 79.351 289.831C79.3358 290.759 79.3205 291.697 79.3053 292.625C69.9497 284.843 62.2226 272.353 57.3865 257.279C56.7947 255.441 58.5528 253.843 59.1445 255.692C63.8341 270.32 71.2887 282.296 80.3671 289.856C81.0135 290.4 80.9851 292.137 80.3214 292.649C77.8832 294.532 75.2283 294.532 72.5941 294.49C69.6124 294.438 66.632 294.301 63.6531 294.077C60.6742 293.853 57.7032 293.554 54.7334 293.18C52.1842 292.848 49.5548 292.514 47.3447 290.259C46.516 289.408 46.8926 287.237 47.9021 287.251C55.0416 287.414 62.1811 287.578 69.3208 287.73C70.6109 287.762 70.5647 290.998 69.2679 290.966Z\"\n        fill=\"#9F240F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 81 / 295,\n  svg: CurvedArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as scribbledUnderline } from './scribbledUnderline';\nimport { default as scribbledUnderlineWhite } from './scribbledUnderlineWhite';\nimport { default as scribbledUnderline2 } from './scribbledUnderline2';\nimport { default as scribbledArrow } from './scribbledArrow';\nimport { default as curvedArrow } from './curvedArrow';\nimport { default as pillBox } from './pillBox';\nimport { default as openPill } from './openPill';\nimport { default as pills } from './pills';\n\nexport {\n  scribbledUnderline,\n  scribbledUnderlineWhite,\n  scribbledUnderline2,\n  scribbledArrow,\n  curvedArrow,\n  pillBox,\n  openPill,\n  pills,\n};\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/openPill.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Open pill', 'sticker name', 'web-stories');\nfunction OpenPill({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 61 40\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M15.1196 22.826C15.303 23.0095 15.5354 23.0951 15.7677 23.0951C16.0001 23.0951 16.2447 22.9973 16.4159 22.826C16.7706 22.4714 16.7706 21.8844 16.4159 21.5297L10.0076 15.1215C9.65298 14.7668 9.06596 14.7668 8.7113 15.1215C8.35665 15.4761 8.35665 16.0631 8.7113 16.4178L15.1196 22.826Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M7.28378 14.5955C7.05141 14.5955 6.81905 14.5099 6.63561 14.3265L6.10974 13.8006C5.75509 13.446 5.75509 12.8589 6.10974 12.5043C6.4644 12.1496 7.05141 12.1496 7.40607 12.5043L7.93194 13.0302C8.2866 13.3848 8.2866 13.9718 7.93194 14.3265C7.7485 14.5099 7.51614 14.5955 7.28378 14.5955Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M15.4947 29.2589C15.539 29.3032 15.5861 29.3418 15.6354 29.3748C15.6722 29.4273 15.7153 29.4784 15.7649 29.528C15.985 29.7358 16.2296 29.8214 16.4742 29.8214C16.9009 29.8214 17.3275 29.5741 17.5933 29.42C17.617 29.4062 17.6394 29.3932 17.6605 29.3812C18.1007 29.1121 18.6633 28.6841 19.3482 28.1093C20.7179 26.972 22.4422 25.3699 24.2033 23.6089C25.9643 21.8478 27.5664 20.1234 28.7037 18.7537C29.2663 18.0689 29.6943 17.4941 29.9756 17.066L29.9772 17.0636C30.2226 16.6832 30.7814 15.8172 30.1346 15.1705C30.0809 15.1168 30.0257 15.0714 29.9693 15.0334C29.9359 14.9823 29.8969 14.9339 29.8522 14.8893L18.173 3.21005C16.2652 1.29001 13.7092 0.238281 10.9943 0.238281C8.2793 0.238281 5.73556 1.29001 3.81553 3.21005C-0.146843 7.17242 -0.146843 13.6174 3.81553 17.5797L15.4947 29.2589ZM5.11185 16.2834L16.1356 27.3072C16.422 26.9004 16.7853 26.4517 17.1958 25.9569C18.3331 24.5872 19.9352 22.8629 21.6962 21.1018C23.4573 19.3408 25.1816 17.7387 26.5513 16.6013C27.0772 16.16 27.531 15.8051 27.9127 15.5424L16.8767 4.50638C15.3113 2.94101 13.22 2.07272 10.9943 2.07272C8.76849 2.07272 6.67723 2.94101 5.11185 4.50638C1.87103 7.74722 1.87103 13.0304 5.11185 16.2834Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M45.1097 22.826C45.2932 23.0095 45.5255 23.0951 45.7579 23.0951C45.9903 23.0951 46.2226 22.9973 46.4061 22.826L52.8143 16.4178C53.169 16.0631 53.169 15.4761 52.8143 15.1215C52.4597 14.7668 51.8727 14.7668 51.518 15.1215L45.1097 21.5297C44.7551 21.8844 44.7551 22.4714 45.1097 22.826Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M54.2462 14.5955C54.0138 14.5955 53.7815 14.5099 53.598 14.3265C53.2434 13.9718 53.2434 13.3848 53.598 13.0302L54.1239 12.5043C54.4785 12.1496 55.0656 12.1496 55.4202 12.5043C55.7749 12.8589 55.7749 13.446 55.4202 13.8006L54.8943 14.3265C54.7231 14.5099 54.4785 14.5955 54.2462 14.5955Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M46.0568 29.3758C46.106 29.3425 46.1521 29.3036 46.1938 29.2589L57.873 17.5797C59.793 15.6719 60.8447 13.116 60.8447 10.401C60.8447 7.68607 59.793 5.1301 57.873 3.21005C55.9652 1.29001 53.4092 0.238281 50.6942 0.238281C47.9793 0.238281 45.4233 1.29001 43.5155 3.21005L31.8363 14.8893C31.8098 14.9157 31.7853 14.9435 31.7628 14.9724C31.7121 15.0079 31.6624 15.0497 31.6138 15.0982C30.9671 15.745 31.5258 16.611 31.7712 16.9913L31.7728 16.9938C32.0419 17.4341 32.4699 17.9966 33.0447 18.6815C34.182 20.0512 35.7841 21.7755 37.5452 23.5366C39.3062 25.2976 41.0306 26.8997 42.4003 28.037C43.0851 28.5996 43.6599 29.0276 44.088 29.3089C44.3326 29.4679 44.7973 29.7614 45.2742 29.7614C45.5188 29.7614 45.7634 29.688 45.9835 29.4557C46.0098 29.4294 46.0342 29.4028 46.0568 29.3758ZM45.6179 27.2421L56.5766 16.2834C59.8175 13.0426 59.8175 7.75943 56.5766 4.50638C54.999 2.92877 52.9078 2.07272 50.6942 2.07272C48.4807 2.07272 46.3772 2.94101 44.8118 4.50638L33.8371 15.4811C34.2154 15.7484 34.6741 16.0995 35.1971 16.5291C36.5668 17.6664 38.2912 19.2685 40.0522 21.0295C41.8133 22.7906 43.4153 24.515 44.5527 25.8846C44.9656 26.3824 45.3307 26.8334 45.6179 27.2421Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M34.8438 29.2383C34.8438 30.3429 33.9483 31.2383 32.8438 31.2383C31.7392 31.2383 30.8438 30.3429 30.8438 29.2383C30.8438 28.1337 31.7392 27.2383 32.8438 27.2383C33.9483 27.2383 34.8438 28.1337 34.8438 29.2383Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M40.8438 33.2383C40.8438 34.3428 39.9483 35.2383 38.8438 35.2383C37.7392 35.2383 36.8438 34.3428 36.8438 33.2383C36.8438 32.1337 37.7392 31.2383 38.8438 31.2383C39.9483 31.2383 40.8438 32.1337 40.8438 33.2383Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M34.8438 35.2383C34.8438 36.3428 33.9483 37.2383 32.8438 37.2383C31.7392 37.2383 30.8438 36.3428 30.8438 35.2383C30.8438 34.1337 31.7392 33.2383 32.8438 33.2383C33.9483 33.2383 34.8438 34.1337 34.8438 35.2383Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M26.8438 37.2383C26.8438 38.3428 25.9483 39.2383 24.8438 39.2383C23.7392 39.2383 22.8438 38.3428 22.8438 37.2383C22.8438 36.1337 23.7392 35.2383 24.8438 35.2383C25.9483 35.2383 26.8438 36.1337 26.8438 37.2383Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M26.8438 30.2383C26.8438 31.3429 25.9483 32.2383 24.8438 32.2383C23.7392 32.2383 22.8438 31.3429 22.8438 30.2383C22.8438 29.1337 23.7392 28.2383 24.8438 28.2383C25.9483 28.2383 26.8438 29.1337 26.8438 30.2383Z\"\n        fill=\"#9F240F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 61 / 40,\n  svg: OpenPill,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/pillBox.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Pill Box', 'sticker name', 'web-stories');\n\nfunction PillBox({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 56 68\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M36 22.9427H17C15.8954 22.9427 15 23.8381 15 24.9427V41.9427C15 43.0473 15.8954 43.9427 17 43.9427H36C37.1046 43.9427 38 43.0473 38 41.9427V24.9427C38 23.8381 37.1046 22.9427 36 22.9427ZM17 20.9427C14.7909 20.9427 13 22.7336 13 24.9427V41.9427C13 44.1518 14.7909 45.9427 17 45.9427H36C38.2091 45.9427 40 44.1518 40 41.9427V24.9427C40 22.7336 38.2091 20.9427 36 20.9427H17Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M43 2.91992H2L2 9.91992H43V2.91992ZM2 0.919922C0.895431 0.919922 0 1.81535 0 2.91992V9.91992C0 11.0245 0.89543 11.9199 2 11.9199H43C44.1046 11.9199 45 11.0245 45 9.91992V2.91992C45 1.81535 44.1046 0.919922 43 0.919922H2Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M23.797 59.2558L44.9531 64.9245C47.3549 65.5681 49.8237 64.1427 50.4673 61.7409C51.1108 59.3391 49.6855 56.8704 47.2837 56.2268L26.1276 50.558C23.7258 49.9145 21.257 51.3398 20.6134 53.7416C19.9699 56.1434 21.3952 58.6122 23.797 59.2558ZM52.3991 62.2586C53.3286 58.7898 51.2701 55.2244 47.8013 54.2949L26.6452 48.6262C23.1765 47.6967 19.611 49.7552 18.6816 53.224C17.7521 56.6927 19.8107 60.2582 23.2794 61.1876L44.4355 66.8563C47.9042 67.7858 51.4697 65.7273 52.3991 62.2586Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M34.1884 64.1107L37.5542 51.5493L39.486 52.0669L36.1202 64.6283L34.1884 64.1107Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M42.6611 54.9165L45.2414 52.1288L38.6332 46.0122L32.8123 52.3009L30.6248 51.7199L37.1654 44.6536L37.164 44.6524L38.5226 43.1846L38.524 43.1859L44.3722 36.8676C46.8116 34.2322 50.9255 34.0732 53.5609 36.5126C56.1964 38.952 56.3553 43.0659 53.9159 45.7013L44.8486 55.4975L42.6611 54.9165ZM46.6 50.661L52.4482 44.3428C54.1372 42.518 54.0272 39.6694 52.2024 37.9803C50.3776 36.2913 47.529 36.4013 45.8399 38.2262L39.9917 44.5444L46.6 50.661Z\"\n        fill=\"#9F240F\"\n      />\n      <path\n        d=\"M7 13.9423C7 12.8378 7.89543 11.9423 9 11.9423H36C37.1046 11.9423 38 12.8378 38 13.9423V45.956H40V13.9423C40 11.7332 38.2091 9.94232 36 9.94232H9C6.79086 9.94232 5 11.7332 5 13.9423V51.9423C5 54.1515 6.79086 55.9423 9 55.9423H19.5547V53.9423H9C7.89543 53.9423 7 53.0469 7 51.9423V13.9423Z\"\n        fill=\"#9F240F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 56 / 68,\n  svg: PillBox,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/pills.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Pills', 'sticker name', 'web-stories');\n\nfunction Pills({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 63 64\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M15.0134 32.6401L31.4679 42.1401M56.1738 44.1335L44.9115 50.6358M41.7159 18.4844L51.7159 12.8208M14.3036 7.59499L21.3581 18.5199M22.2634 20.0827C24.8867 15.5389 30.6969 13.9821 35.2406 16.6055C39.7844 19.2288 41.3412 25.0389 38.7179 29.5827L22.7179 57.2955C20.0945 61.8393 14.2844 63.3961 9.74063 60.7728C5.19685 58.1494 3.64004 52.3393 6.26339 47.7955L22.2634 20.0827ZM60.9781 52.4548C62.7736 55.5648 61.7081 59.5415 58.5981 61.3371C55.4881 63.1326 51.5114 62.0671 49.7158 58.9571L38.7646 39.9891C36.969 36.8791 38.0346 32.9023 41.1446 31.1068C44.2546 29.3112 48.2313 30.3768 50.0269 33.4868L60.9781 52.4548ZM36.845 11.1025C35.005 8.01857 36.0134 4.02696 39.0973 2.18695C42.1812 0.346952 46.1728 1.35533 48.0128 4.43923L56.8465 19.2447C58.6865 22.3287 57.6781 26.3203 54.5942 28.1603C51.5103 30.0003 47.5187 28.9919 45.6787 25.908L36.845 11.1025ZM22.3757 2.38271C25.3925 0.434676 29.4173 1.30111 31.3653 4.31793C33.3133 7.33476 32.4469 11.3596 29.4301 13.3076L11.0303 25.1888C8.01345 27.1368 3.98864 26.2704 2.04061 23.2535C0.0925804 20.2367 0.959011 16.2119 3.97584 14.2639L22.3757 2.38271Z\"\n        stroke=\"#9F240F\"\n        strokeWidth=\"2\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 63 / 64,\n  svg: Pills,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/scribbledArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Scribbled Arrow', 'sticker name', 'web-stories');\n\nfunction scribbledArrow({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 96 27\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.66459 19.9878C13.6031 19.2564 25.5416 18.5297 37.4847 17.7984C49.4231 17.0671 61.3616 16.3403 73.3047 15.609C80.0417 15.197 86.7741 14.7851 93.5111 14.3731C94.1429 14.3361 94.521 13.4011 93.8616 13.0771C85.9533 9.21209 78.0128 5.42578 70.0307 1.72742C69.8509 2.14864 69.6757 2.57448 69.4958 2.9957C76.4081 4.77313 82.9929 7.72164 88.9322 11.6977C90.6199 12.8271 92.2477 14.0399 93.8201 15.3313C93.8662 14.9656 93.9123 14.6046 93.9584 14.2389C88.2359 17.604 82.5087 20.9691 76.7862 24.3342C76.0161 24.7832 76.7124 25.9866 77.4825 25.533C83.2096 22.1726 88.9322 18.8075 94.6547 15.4424C95.0098 15.2341 95.1435 14.6416 94.7931 14.35C89.1305 9.69348 82.7209 6.01826 75.8409 3.50486C73.8811 2.7874 71.8845 2.17178 69.8601 1.65336C69.1316 1.46358 68.592 2.57911 69.3252 2.92164C77.3119 6.62463 85.257 10.4109 93.1561 14.2759C93.2714 13.8455 93.3866 13.415 93.5065 12.9799C81.568 13.7112 69.6296 14.4379 57.6865 15.1693C45.748 15.9006 33.8095 16.6273 21.8664 17.3587C15.1294 17.7706 8.397 18.1826 1.65998 18.5945C0.783847 18.6501 0.774623 20.0387 1.66459 19.9878Z\"\n        fill=\"#FFFFFF\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M37.5458 18.7965C31.7604 19.1508 25.9776 19.5039 20.1954 19.8569C14.0389 20.2329 7.88306 20.6087 1.72573 20.9859L1.72171 20.9862C1.21392 21.0152 0.745242 20.8306 0.419215 20.4653C0.115733 20.1254 -0.00061555 19.7023 2.44762e-06 19.3294C0.00120792 18.603 0.496401 17.6663 1.59671 17.5965L1.59895 17.5964L21.8053 16.3605C21.8053 16.3605 21.8053 16.3605 21.8053 16.3605C27.5907 16.0063 33.3737 15.6532 39.156 15.3001C45.3124 14.9242 51.4681 14.5483 57.6253 14.1711C63.4101 13.8169 69.1923 13.4639 74.9739 13.1108C78.9713 12.8668 82.9685 12.6227 86.966 12.3783C81.0463 9.51861 75.1016 6.70357 69.1336 3.93509L68.1188 3.67414L68.2721 3.31517C68.1637 3.16631 68.0826 2.99859 68.0327 2.81714C67.9187 2.40191 67.989 1.99601 68.1328 1.67698C68.3326 1.23383 68.7863 0.766467 69.4016 0.65429L69.5158 0.386719L70.2218 0.713821C72.2385 1.23412 74.2291 1.8499 76.1847 2.56581C82.0047 4.69205 87.4924 7.63665 92.486 11.2934C92.9398 11.5144 93.3936 11.7356 93.8472 11.9571L94.8424 11.8962L94.6919 12.4422C94.7373 12.4832 94.78 12.5266 94.8201 12.5721L95.2051 12.3457L95.1138 13.0697C95.1147 13.0722 95.1156 13.0746 95.1164 13.0771C95.1528 13.1797 95.1772 13.2824 95.1915 13.3839C95.2705 13.4483 95.3495 13.5128 95.4282 13.5776L95.4327 13.5813C95.9419 14.005 96.0518 14.6151 95.9757 15.0868C95.9021 15.5427 95.6356 16.0262 95.1611 16.3047C94.997 16.4012 94.8329 16.4977 94.6688 16.5942L94.5856 17.254L94.1521 16.898C88.7661 20.0652 83.3794 23.2324 77.9886 26.3955C77.5512 26.6526 77.0592 26.6999 76.6127 26.545C76.1926 26.3992 75.8806 26.0996 75.6916 25.7736C75.5026 25.4474 75.3984 25.0293 75.4782 24.5943C75.5629 24.1327 75.8429 23.7272 76.2808 23.4713C79.1417 21.789 82.0037 20.1067 84.8656 18.4244C86.461 17.4866 88.0564 16.5488 89.6516 15.6111L73.3658 16.6071C73.3658 16.6071 73.3659 16.6071 73.3658 16.6071C67.5798 16.9614 61.7962 17.3146 56.0133 17.6677C49.8575 18.0436 43.7024 18.4194 37.5458 18.7965ZM1.66459 19.9878C7.82101 19.6107 13.9774 19.2347 20.1345 18.8588C25.9171 18.5057 31.7004 18.1526 37.4847 17.7984C43.6411 17.4213 49.7975 17.0454 55.9545 16.6694C61.7372 16.3163 67.5204 15.9632 73.3047 15.609L92.6889 14.4234C92.7612 14.4801 92.8334 14.537 92.9055 14.594C92.9283 14.612 92.9511 14.6301 92.9739 14.6482C93.0148 14.6807 93.0557 14.7132 93.0965 14.7457C93.0208 14.7902 92.9451 14.8348 92.8693 14.8793C92.8654 14.8816 92.8614 14.884 92.8574 14.8863C92.747 14.9512 92.6366 15.0161 92.5262 15.081C92.4082 15.1504 92.2902 15.2198 92.1722 15.2892C92.0661 15.3516 91.96 15.414 91.8539 15.4764C89.6942 16.7461 87.534 18.0159 85.3738 19.2857C82.5109 20.9685 79.648 22.6513 76.7862 24.3342C76.0161 24.7832 76.7124 25.9866 77.4825 25.533C82.7674 22.4321 88.0483 19.3272 93.329 16.222C93.7709 15.9621 94.2128 15.7022 94.6547 15.4424C94.6574 15.4408 94.6601 15.4392 94.6628 15.4376C94.7282 15.3977 94.7859 15.3448 94.8342 15.2831C94.9963 15.0761 95.0521 14.771 94.9378 14.5347C94.9355 14.53 94.9331 14.5253 94.9307 14.5207C94.8979 14.4574 94.8524 14.3994 94.7931 14.35C94.7903 14.3477 94.7875 14.3454 94.7847 14.3431C94.6181 14.2062 94.4509 14.0701 94.283 13.9348C94.2445 13.9038 94.206 13.8729 94.1675 13.842C94.2579 13.5761 94.2019 13.2756 93.9136 13.1052C93.898 13.0959 93.8816 13.087 93.8645 13.0785C93.8635 13.078 93.8626 13.0776 93.8616 13.0771C93.7416 13.0185 93.6217 12.9599 93.5017 12.9013C92.9904 12.6515 92.4789 12.4021 91.9672 12.1531C91.9333 12.1282 91.8994 12.1033 91.8655 12.0785C89.625 10.4397 87.2837 8.9465 84.8567 7.6087C82.5852 6.35654 80.2385 5.24055 77.8292 4.26879C77.171 4.00333 76.5082 3.74863 75.8409 3.50486C73.9402 2.80904 72.0049 2.20901 70.0432 1.70053C69.9822 1.68472 69.9212 1.669 69.8601 1.65336C69.8578 1.65275 69.8554 1.65215 69.8531 1.65156C69.1281 1.47079 68.5944 2.58022 69.3252 2.92164C69.3363 2.92676 69.3473 2.93187 69.3583 2.93699C69.4038 2.95807 69.4492 2.97914 69.4947 3.00022C72.0028 4.16356 74.5068 5.33511 77.0066 6.51474C79.2863 7.59051 81.5625 8.67299 83.835 9.76207C85.4481 10.5351 87.0594 11.3115 88.6688 12.0912C88.6688 12.0912 88.6688 12.0912 88.6688 12.0912C88.7805 12.1453 88.8923 12.1995 89.004 12.2536C89.6148 12.5498 90.2253 12.8464 90.8356 13.1434C90.3578 13.1727 89.88 13.2019 89.4022 13.2311C89.2026 13.2434 89.003 13.2556 88.8035 13.2678C84.214 13.5485 79.6243 13.8287 75.0344 14.109C69.2525 14.462 63.47 14.8151 57.6865 15.1693C51.5298 15.5464 45.373 15.9224 39.2157 16.2983C33.4333 16.6514 27.6504 17.0045 21.8664 17.3587L1.65998 18.5945C0.783847 18.6501 0.774623 20.0387 1.66459 19.9878Z\"\n        fill=\"#FFFFFF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 96 / 27,\n  svg: scribbledArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/scribbledUnderline.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Scribbled Underline', 'sticker name', 'web-stories');\n\nfunction ScribbledUnderline({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 182 11\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M13.8339 2.72913C35.6434 2.29508 57.4477 1.85524 79.2624 1.75685C101.062 1.65847 122.871 1.90154 144.655 2.81594C156.864 3.33102 169.063 4.06022 181.247 5.05565C181.247 4.47691 181.247 3.89818 181.247 3.31944C157.613 3.50464 133.98 3.64932 110.347 3.88081C86.987 4.10652 63.6274 4.52321 40.2936 5.88903C27.0921 6.66454 13.901 7.74677 0.746074 9.26306C-0.225305 9.37302 -0.271807 11.0398 0.746074 10.9993C20.9022 10.1833 41.0583 9.58716 61.2248 9.1994C81.2672 8.81744 101.315 8.6496 121.362 8.6959C132.647 8.71905 143.931 8.81165 155.211 8.9737C156.208 8.98527 156.208 7.24906 155.211 7.23749C135.044 6.95391 114.878 6.87867 94.7115 7.02335C74.6639 7.16804 54.6214 7.52685 34.579 8.09402C23.2996 8.41811 12.0254 8.80586 0.746074 9.26306C0.746074 9.8418 0.746074 10.4205 0.746074 10.9993C24.0953 8.30815 47.5531 6.99442 71.0161 6.31151C94.4118 5.6286 117.818 5.54758 141.219 5.36238C154.565 5.25821 167.906 5.15404 181.252 5.04986C182.26 5.04408 182.239 3.39468 181.252 3.31365C159.505 1.54272 137.716 0.622529 115.922 0.234776C94.1173 -0.152978 72.3026 -0.0140809 50.4983 0.315799C38.2733 0.506782 26.0536 0.749851 13.8339 0.99292C12.8366 1.01028 12.8315 2.74649 13.8339 2.72913Z\"\n        fill=\"#9F240F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 182 / 11,\n  svg: ScribbledUnderline,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/scribbledUnderline2.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Scribbled Underline 2', 'sticker name', 'web-stories');\n\nfunction ScribbledUnderline2({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 241 15\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M185.725 2.91649C161.781 3.2373 137.829 3.5581 113.884 3.8789C89.9391 4.19971 65.9873 4.52051 42.0425 4.84132C28.5652 5.02602 15.081 5.201 1.60371 5.38571C1.60371 4.41358 1.60371 3.44144 1.60371 2.46931C32.7201 2.75123 63.8365 2.97482 94.953 3.32479C125.776 3.67476 156.613 4.31636 187.401 6.53282C204.817 7.80632 222.226 9.5756 239.586 12.074C240.912 12.2684 240.926 15.1848 239.586 14.9904C208.769 10.5672 177.814 8.4382 146.858 7.34942C116 6.26063 85.1278 6.15369 54.2628 5.87178C36.7074 5.71623 19.1521 5.55097 1.59674 5.39543C0.249004 5.38571 0.249004 2.49848 1.59674 2.47903C25.5416 2.15823 49.4934 1.83743 73.4382 1.51662C97.3831 1.19582 121.335 0.875016 145.28 0.554212C158.764 0.359786 172.248 0.184802 185.725 9.67822e-05C187.073 -0.0193459 187.073 2.89705 185.725 2.91649Z\"\n        fill=\"#9F240F\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 241 / 15,\n  svg: ScribbledUnderline2,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sangria-artichoke/scribbledUnderlineWhite.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Scribbled Underline', 'sticker name', 'web-stories');\n\nfunction ScribbledUnderlineWhite({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 182 11\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M13.8339 2.72913C35.6434 2.29508 57.4477 1.85524 79.2624 1.75685C101.062 1.65847 122.871 1.90154 144.655 2.81594C156.864 3.33102 169.063 4.06022 181.247 5.05565C181.247 4.47691 181.247 3.89818 181.247 3.31944C157.613 3.50464 133.98 3.64932 110.347 3.88081C86.987 4.10652 63.6274 4.52321 40.2936 5.88903C27.0921 6.66454 13.901 7.74677 0.746074 9.26306C-0.225305 9.37302 -0.271807 11.0398 0.746074 10.9993C20.9022 10.1833 41.0583 9.58716 61.2248 9.1994C81.2672 8.81744 101.315 8.6496 121.362 8.6959C132.647 8.71905 143.931 8.81165 155.211 8.9737C156.208 8.98527 156.208 7.24906 155.211 7.23749C135.044 6.95391 114.878 6.87867 94.7115 7.02335C74.6639 7.16804 54.6214 7.52685 34.579 8.09402C23.2996 8.41811 12.0254 8.80586 0.746074 9.26306C0.746074 9.8418 0.746074 10.4205 0.746074 10.9993C24.0953 8.30815 47.5531 6.99442 71.0161 6.31151C94.4118 5.6286 117.818 5.54758 141.219 5.36238C154.565 5.25821 167.906 5.15404 181.252 5.04986C182.26 5.04408 182.239 3.39468 181.252 3.31365C159.505 1.54272 137.716 0.622529 115.922 0.234776C94.1173 -0.152978 72.3026 -0.0140809 50.4983 0.315799C38.2733 0.506782 26.0536 0.749851 13.8339 0.99292C12.8366 1.01028 12.8315 2.74649 13.8339 2.72913Z\"\n        fill=\"#FFF\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 182 / 11,\n  svg: ScribbledUnderlineWhite,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/combAndScissors.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Comb and Scissors', 'sticker name', 'web-stories');\n\nfunction CombAndScissors({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 32 34\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M0.0276598 14.7549C0.0276598 10.8784 0.0294814 7.00195 0.0258347 3.12547C0.0258347 2.63681 0.00213379 2.14814 0.000310417 1.65947C-0.00151295 1.42426 0.00395381 1.18722 0.0367744 0.955657C0.0896521 0.567279 0.301164 0.284656 0.682248 0.15702C0.851822 0.100496 1.02869 0.0457928 1.20738 0.0293825C1.47724 0.00203198 1.75074 -0.00708575 2.0206 0.00567783C2.39986 0.0239115 2.7773 0.0713244 3.15656 0.102322C3.33707 0.116909 3.51759 0.127846 3.6981 0.133316C5.25343 0.1789 6.81059 0.220845 8.36592 0.266429C8.49173 0.270076 8.61937 0.273713 8.74518 0.290123C9.01504 0.32659 9.20284 0.518053 9.24296 0.789735C9.24843 0.826202 9.2539 0.86084 9.2539 0.897308C9.2539 1.38597 9.2539 1.87463 9.25207 2.36512C9.25207 2.4964 9.1992 2.61127 9.12262 2.71703C9.05698 2.80819 8.96946 2.86837 8.86188 2.90119C8.70325 2.95042 8.53914 2.95407 8.37686 2.93948C7.94472 2.90119 7.51259 2.85014 7.08045 2.81549C6.43133 2.76444 5.78038 2.72068 5.13127 2.68057C4.80488 2.66051 4.48032 2.69697 4.15759 2.75167C4.12112 2.75714 4.08465 2.75897 4.05001 2.76809C3.45377 2.91578 3.38995 3.0033 3.36989 3.56672C3.3626 3.75088 3.41001 3.84204 3.6124 3.84569C3.77468 3.84934 3.93878 3.84934 4.10106 3.84934C5.3136 3.84934 6.52614 3.84934 7.74051 3.84934C7.90278 3.84934 8.06689 3.84752 8.22917 3.86211C8.48626 3.88399 8.70506 4.11373 8.71783 4.36353C8.73242 4.63886 8.52091 4.90142 8.24193 4.93242C8.08147 4.95066 7.91737 4.94884 7.75327 4.94884C6.5225 4.95066 5.29172 4.947 4.06095 4.95065C3.30243 4.95248 3.38448 4.88137 3.37901 5.66724C3.37901 5.75841 3.38448 5.84776 3.38995 5.93893C3.39542 6.02462 3.47747 6.10302 3.57229 6.10667C3.73457 6.11214 3.89867 6.11761 4.06095 6.11761C5.29172 6.11761 6.5225 6.11761 7.75327 6.11944C7.91555 6.11944 8.07965 6.11944 8.24193 6.13403C8.48079 6.15591 8.68136 6.35283 8.716 6.58804C8.75065 6.82143 8.61207 7.05665 8.37686 7.14599C8.29298 7.17699 8.20364 7.19887 8.11429 7.20434C7.97025 7.21528 7.82438 7.20981 7.68033 7.20981C6.46779 7.20981 5.25525 7.20981 4.04089 7.20981C3.87861 7.20981 3.71633 7.21528 3.55223 7.22257C3.46288 7.22622 3.38995 7.30462 3.38813 7.40126C3.38448 7.56354 3.38083 7.72765 3.38448 7.88993C3.38813 8.05221 3.45194 8.1142 3.61969 8.11967C3.78197 8.12514 3.94608 8.12514 4.10836 8.12514C5.33913 8.12514 6.56991 8.12332 7.80068 8.12697C7.96296 8.12697 8.12706 8.13426 8.28569 8.16161C8.47897 8.19443 8.60478 8.32024 8.67772 8.50076C8.79077 8.78338 8.63214 9.11158 8.33858 9.19363C8.25288 9.21734 8.1617 9.23375 8.07236 9.23922C7.92831 9.24651 7.78244 9.24469 7.6384 9.24469C6.38939 9.24469 5.14038 9.24287 3.89138 9.24652C3.37536 9.24834 3.37536 9.25198 3.37901 9.75341C3.37901 9.84275 3.38995 9.93392 3.39907 10.0233C3.40454 10.0853 3.47747 10.1509 3.54858 10.1546C3.71086 10.16 3.87314 10.1673 4.03724 10.1673C5.24978 10.1691 6.46233 10.1673 7.67669 10.1673C7.80433 10.1673 7.93013 10.1655 8.05594 10.1691C8.12888 10.171 8.20182 10.1764 8.27111 10.1892C8.49903 10.2311 8.69049 10.4445 8.71419 10.6797C8.73789 10.9149 8.52638 11.1993 8.29117 11.2395C8.22005 11.2522 8.14712 11.2577 8.07601 11.2577C7.93196 11.2613 7.78609 11.2595 7.64205 11.2595C6.42951 11.2595 5.21696 11.2595 4.0026 11.2595C3.31519 11.2595 3.37719 11.2285 3.37901 11.9269C3.37901 11.9451 3.38266 11.9633 3.38266 11.9816C3.38995 12.111 3.46106 12.1894 3.57776 12.1949C3.74004 12.2004 3.90414 12.204 4.06642 12.204C5.29719 12.204 6.52796 12.204 7.75873 12.2058C7.92101 12.2058 8.08513 12.2058 8.24741 12.2204C8.50086 12.2441 8.70872 12.4812 8.71419 12.7383C8.71966 12.9844 8.5118 13.2524 8.27111 13.2834C8.11065 13.3053 7.94654 13.3035 7.78426 13.3035C6.57172 13.3053 5.35919 13.3035 4.14482 13.3053C3.98254 13.3053 3.81844 13.3072 3.65616 13.3072C3.41183 13.3072 3.3863 13.3983 3.37719 13.608C3.37719 13.6262 3.37719 13.6445 3.37719 13.6627C3.37536 14.2352 3.34801 14.2334 3.93696 14.2334C5.2042 14.2334 6.47144 14.2334 7.73868 14.2352C7.91919 14.2352 8.09971 14.2444 8.28023 14.2626C8.38963 14.2735 8.48627 14.3246 8.5665 14.4066C8.84365 14.6911 8.71601 15.1706 8.33675 15.2782C8.15806 15.3293 7.97937 15.3238 7.79703 15.3238C6.58449 15.3238 5.37195 15.3238 4.15759 15.3238C3.99531 15.3238 3.83121 15.3238 3.66893 15.3293C3.61605 15.3311 3.55588 15.3329 3.51029 15.3548C3.46653 15.3749 3.41183 15.4186 3.40271 15.4605C3.3626 15.6757 3.36807 15.8927 3.39542 16.1078C3.40454 16.1717 3.47383 16.2391 3.54311 16.241C3.70539 16.2482 3.86767 16.2555 4.03177 16.2555C5.24432 16.2574 6.45685 16.2555 7.67122 16.2555C7.79885 16.2555 7.92467 16.2537 8.05048 16.2574C8.12341 16.2592 8.19635 16.261 8.26746 16.2738C8.59931 16.3376 8.87646 16.7424 8.61389 17.1162C8.53731 17.2256 8.43339 17.3003 8.30393 17.3167C8.14347 17.3368 7.97936 17.3423 7.81708 17.3423C6.54984 17.3441 5.28261 17.3423 4.01537 17.3441C3.85309 17.3441 3.69081 17.3532 3.5267 17.3605C3.47018 17.3623 3.3936 17.4462 3.38995 17.5082C3.38448 17.6705 3.37719 17.8328 3.37901 17.9969C3.38266 18.2248 3.43918 18.2776 3.6744 18.2849C3.81844 18.2886 3.96431 18.2886 4.10836 18.2886C5.3209 18.2886 6.53343 18.2886 7.74779 18.2886C7.91007 18.2886 8.07419 18.2886 8.23647 18.3032C8.47715 18.3251 8.67772 18.522 8.71236 18.7536C8.75065 19.0052 8.58838 19.2623 8.33675 19.3443C8.26929 19.3662 8.19634 19.3808 8.12523 19.3844C7.98119 19.3917 7.83532 19.3899 7.69127 19.3899C6.42403 19.3899 5.15679 19.3899 3.88955 19.3899C3.3626 19.3899 3.37901 19.3881 3.37719 19.8932C3.37719 20.019 3.38448 20.1466 3.38995 20.2724C3.39177 20.3253 3.47929 20.4092 3.53399 20.4146C3.6051 20.4219 3.67804 20.4292 3.75097 20.4311C3.89502 20.4347 4.04089 20.4329 4.18494 20.4329C5.37924 20.4329 6.57538 20.4311 7.76969 20.4347C7.9502 20.4347 8.13253 20.4456 8.30939 20.4712C8.51544 20.5022 8.6923 20.7137 8.716 20.9252C8.73788 21.1385 8.60661 21.3756 8.40786 21.4521C8.30758 21.4904 8.19817 21.5141 8.09241 21.5232C7.94837 21.536 7.8025 21.5305 7.65845 21.5305C6.44591 21.5305 5.23337 21.5305 4.01901 21.5324C3.85673 21.5324 3.69445 21.5433 3.53217 21.5524C3.46653 21.5561 3.39542 21.6272 3.3936 21.6946C3.38813 21.9481 3.3863 22.2015 3.38448 22.455C3.38448 22.4732 3.3936 22.4896 3.39542 22.5079C3.40454 22.5735 3.47382 22.6428 3.53946 22.6446C3.70174 22.6519 3.86403 22.6592 4.02813 22.6592C5.22244 22.661 6.41856 22.6592 7.61287 22.6592C7.7405 22.6592 7.86632 22.6592 7.99396 22.6592C8.06689 22.6592 8.138 22.661 8.21094 22.6683C8.48444 22.692 8.70142 22.8999 8.71783 23.1479C8.73606 23.4232 8.53185 23.6839 8.25287 23.7295C8.18176 23.7405 8.10882 23.7441 8.03589 23.7459C7.91008 23.7478 7.78244 23.7478 7.65663 23.7478C6.44409 23.7478 5.23155 23.7478 4.01719 23.7478C3.85491 23.7478 3.69263 23.7551 3.52852 23.7624C3.46288 23.766 3.39724 23.8353 3.39177 23.9064C3.38448 24.014 3.37536 24.1234 3.37536 24.231C3.37901 24.8892 3.32248 24.8564 3.98437 24.8564C5.23337 24.8564 6.48238 24.8564 7.73139 24.8564C7.89367 24.8564 8.05777 24.8564 8.22005 24.8728C8.36774 24.8874 8.49539 24.9566 8.5902 25.077C8.84183 25.387 8.68319 25.8556 8.29117 25.9249C8.1143 25.9559 7.93196 25.9577 7.75144 25.9595C6.61002 25.9632 5.47041 25.9613 4.32898 25.9613C4.20135 25.9613 4.07554 25.9613 3.9479 25.9613C3.3316 25.9595 3.37172 25.9522 3.37172 26.5722C3.37172 26.6615 3.38265 26.7527 3.39177 26.842C3.39906 26.9058 3.472 26.9733 3.54129 26.9751C3.70357 26.9824 3.86585 26.9897 4.02995 26.9897C5.24249 26.9915 6.45503 26.9897 7.66939 26.9897C7.79703 26.9897 7.92284 26.9879 8.04865 26.9915C8.12159 26.9934 8.1927 26.997 8.26564 27.0079C8.51179 27.0444 8.70871 27.2851 8.71054 27.5495C8.71236 27.781 8.52455 28.0126 8.29663 28.0564C8.22552 28.0691 8.15259 28.0764 8.08147 28.0783C7.93743 28.0819 7.79156 28.0801 7.64751 28.0801C6.43497 28.0801 5.22243 28.0801 4.00807 28.0801C3.84579 28.0801 3.68351 28.0874 3.51941 28.0947C3.45194 28.0983 3.38631 28.1676 3.37901 28.2351C3.37719 28.2533 3.36989 28.2715 3.36989 28.288C3.37718 28.4867 3.37719 28.6854 3.39542 28.8842C3.41548 29.0811 3.53947 29.216 3.73822 29.2543C3.89685 29.2853 4.06095 29.309 4.22323 29.3054C4.65719 29.2981 5.09298 29.2944 5.52511 29.2525C6.04842 29.2015 6.57173 29.1686 7.09686 29.1759C7.51259 29.1814 7.93014 29.1759 8.34586 29.1778C8.47168 29.1778 8.59932 29.1778 8.72513 29.1887C8.98405 29.2106 9.19555 29.4166 9.23202 29.6774C9.24296 29.7485 9.24661 29.8214 9.24661 29.8943C9.24843 30.383 9.24114 30.8717 9.24843 31.3621C9.25573 31.8253 9.00775 32.066 8.55556 32.0824C8.41151 32.0879 8.26564 32.086 8.12159 32.086C6.76318 32.086 5.40659 32.0824 4.04818 32.0878C3.39724 32.0897 2.74448 32.1061 2.09353 32.1152C1.87655 32.1188 1.65957 32.1188 1.44259 32.1207C1.22196 32.1225 1.01228 32.0769 0.802591 32.0149C0.421507 31.9019 0.191763 31.6448 0.0787139 31.2728C0.0586569 31.2035 0.0385978 31.1306 0.0367744 31.0595C0.0313043 30.6984 0.0221877 30.3356 0.0313046 29.9746C0.0367747 29.7503 0.209997 29.5607 0.421508 29.506C0.662193 29.4421 0.902875 29.5406 1.02869 29.7521C1.08703 29.8487 1.11074 29.9545 1.10709 30.0639C1.10162 30.2444 1.08886 30.4249 1.08157 30.6073C1.07427 30.8024 1.15632 30.9045 1.36054 30.9428C1.50276 30.9701 1.64681 30.9938 1.79085 30.9993C2.18835 31.0121 2.58767 31.0303 2.98516 31.0157C4.46939 30.9665 5.95361 30.9884 7.43783 30.9829C7.61834 30.9829 7.79885 30.9774 7.97937 30.9701C8.07418 30.9665 8.14894 30.8917 8.15076 30.7951C8.15441 30.6875 8.15258 30.5781 8.14894 30.4705C8.14711 30.4012 8.07235 30.3301 8.01036 30.3265C7.97389 30.3247 7.93743 30.3174 7.90279 30.3192C7.45242 30.3538 7.00022 30.3866 6.54985 30.4286C5.82779 30.4979 5.10574 30.5125 4.38004 30.4815C3.97707 30.4632 3.59234 30.3775 3.21126 30.2535C3.14197 30.2317 3.07633 30.2007 3.01069 30.1715C2.59496 29.9837 2.35428 29.6682 2.31963 29.2106C2.27952 28.669 2.23576 28.1275 2.21388 27.5841C2.14094 25.7553 2.14459 23.9265 2.17741 22.0976C2.20658 20.504 2.25034 18.9104 2.26493 17.3167C2.27587 16.1042 2.25946 14.8898 2.24123 13.6773C2.20476 11.4309 2.14824 9.18634 2.15918 6.93995C2.16282 6.10667 2.18835 5.27339 2.21752 4.44194C2.23393 3.97151 2.27587 3.5029 2.30687 3.03248C2.31234 2.95954 2.31781 2.88843 2.33057 2.81732C2.39075 2.47635 2.56214 2.21379 2.87029 2.04421C3.1912 1.86735 3.53035 1.747 3.8932 1.69777C4.52226 1.61207 5.15315 1.58107 5.78768 1.64853C6.3274 1.70688 6.86894 1.73971 7.41048 1.78165C7.55452 1.79259 7.70039 1.79806 7.84444 1.80353C7.89914 1.80535 7.95202 1.79805 8.00672 1.7944C8.06142 1.79075 8.12341 1.70871 8.12706 1.63396C8.13253 1.52091 8.0833 1.41333 8.01949 1.40421C7.96661 1.39692 7.9119 1.38962 7.8572 1.38779C7.58552 1.38232 7.31383 1.3805 7.04215 1.37685C6.22711 1.36044 5.41753 1.26927 4.60613 1.19087C3.68716 1.10152 2.76818 1.01218 1.84373 0.992126C1.64681 0.98848 1.44624 1.01218 1.24931 1.03589C1.15267 1.04683 1.09068 1.1234 1.06516 1.21457C1.04145 1.30027 1.01775 1.39144 1.01775 1.47896C1.02322 1.82358 1.02322 2.1682 1.05422 2.50917C1.08886 2.90666 1.11074 3.30415 1.11074 3.70165C1.11074 11.7445 1.11074 19.7856 1.11074 27.8285C1.11074 27.9907 1.11256 28.1548 1.10527 28.3171C1.10162 28.3882 1.08704 28.4612 1.06516 28.5286C0.986752 28.7675 0.76612 28.917 0.525436 28.9006C0.290221 28.8842 0.0841856 28.6982 0.0404247 28.4575C0.0276612 28.3864 0.0221882 28.3135 0.0203648 28.2424C0.0167181 28.0801 0.0185396 27.916 0.0185396 27.7537C0.0276565 23.4141 0.0276598 19.0836 0.0276598 14.7549Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M20.6736 14.1661C20.6645 13.94 20.7593 13.743 20.8396 13.5425C21.1422 12.7858 21.4486 12.0309 21.7513 11.276C23.0878 7.95201 24.4243 4.6262 25.7608 1.3022C25.821 1.15086 25.8775 0.997691 25.9505 0.853645C26.0927 0.57467 26.4154 0.459797 26.6908 0.602019C27.679 1.11256 28.2698 1.9039 28.381 3.0271C28.4394 3.62881 28.3646 4.21958 28.2206 4.80306C28.0856 5.34824 27.9142 5.8825 27.7118 6.4058C27.5678 6.77777 27.4219 7.14792 27.2633 7.51259C26.9059 8.32399 26.5886 9.1518 26.2896 9.9869C25.2175 12.9663 24.1399 15.9438 23.0641 18.9232C23.0331 19.0089 23.0021 19.0928 22.9711 19.1785C22.7906 19.6927 22.7833 19.6945 22.9291 20.2306C23.0987 20.8596 23.2993 21.4796 23.5619 22.0777C23.664 22.3092 23.788 22.5317 23.9138 22.7505C24.1034 23.0787 24.3824 23.3011 24.7507 23.3996C25.0825 23.4871 25.418 23.5637 25.7517 23.6421C26.0161 23.7041 26.2805 23.7624 26.5467 23.8153C27.3125 23.9667 27.9744 24.324 28.5652 24.8218C29.9491 25.9906 30.8134 27.4657 31.0522 29.2654C31.22 30.5326 30.8827 31.6722 29.9436 32.5894C29.4659 33.0561 28.8879 33.3424 28.2479 33.5175C27.6426 33.6816 27.0281 33.7016 26.4172 33.5977C24.7525 33.3114 23.4196 32.4745 22.4295 31.1033C22.0557 30.5873 21.7804 30.0166 21.5525 29.424C21.3373 28.8661 21.1714 28.2917 21.0164 27.7155C20.9326 27.4019 20.8578 27.0846 20.7721 26.7692C20.7393 26.6488 20.69 26.5321 20.6481 26.41C20.5296 26.4847 20.5132 26.5941 20.4877 26.6962C20.4056 27.0299 20.329 27.3654 20.2488 27.6991C20.1248 28.2096 19.9808 28.7147 19.8021 29.2088C19.4392 30.2099 18.9159 31.1088 18.1501 31.8582C17.4791 32.5146 16.6896 32.9796 15.818 33.3133C15.2035 33.5485 14.5654 33.667 13.9071 33.6725C13.526 33.6761 13.1486 33.6433 12.7785 33.543C11.9579 33.3242 11.307 32.8647 10.8202 32.1718C10.3151 31.4516 10.0853 30.6475 10.0853 29.7704C10.0853 28.9773 10.2713 28.2242 10.605 27.5131C11.2997 26.0271 12.35 24.8583 13.7868 24.0542C14.5891 23.6056 15.4515 23.3595 16.3741 23.3303C16.4471 23.3285 16.5182 23.3248 16.5911 23.323C16.7497 23.3212 16.8628 23.2446 16.9448 23.1097C17.1582 22.7505 17.3423 22.3785 17.5064 21.9956C17.7107 21.5124 17.9094 21.0256 18.0918 20.5351C18.2103 20.2142 18.296 19.8805 18.3981 19.5432C18.2467 19.1183 18.0972 18.6917 17.9441 18.2668C17.0743 15.8691 16.1991 13.4713 15.3312 11.0718C14.992 10.1346 14.5982 9.22108 14.2007 8.3094C13.8451 7.49618 13.5078 6.67748 13.2416 5.82961C13.0027 5.06562 12.8313 4.29069 12.8259 3.48659C12.824 3.10368 12.8623 2.72807 12.979 2.36157C13.2361 1.55565 13.774 0.99404 14.5088 0.609309C14.786 0.463439 15.1087 0.571018 15.2528 0.84817C15.3275 0.992216 15.3877 1.14356 15.4479 1.2949C16.4361 3.7455 17.4207 6.19611 18.409 8.64672C19.0782 10.3078 19.7492 11.9689 20.422 13.63C20.4968 13.8123 20.5369 14.0129 20.6901 14.1551C20.6882 14.3046 20.7447 14.4396 20.7994 14.5727C21.2243 15.6302 21.6528 16.686 22.0813 17.7417C22.1013 17.7909 22.1305 17.8383 22.167 17.8748C22.1834 17.8894 22.249 17.8876 22.2581 17.8711C22.3037 17.7946 22.3438 17.7125 22.3748 17.6286C23.1005 15.6211 23.8281 13.6154 24.5465 11.6042C24.6741 11.245 24.8163 10.8949 24.9731 10.5485C25.3779 9.66051 25.7845 8.77071 26.1456 7.86267C26.5084 6.95464 26.8312 6.03384 27.0354 5.07475C27.1521 4.52409 27.2268 3.96978 27.1885 3.40454C27.1612 3.00339 27.081 2.61501 26.8804 2.26128C26.8366 2.1847 26.7765 2.11906 26.7163 2.03883C26.6634 2.08807 26.6124 2.11723 26.5905 2.15917C26.5339 2.27222 26.4902 2.39075 26.4428 2.50927C25.6004 4.60796 24.758 6.70666 23.9156 8.80535C23.2628 10.4336 22.6101 12.0619 21.9555 13.6902C21.888 13.8579 21.8187 14.0257 21.7367 14.1861C21.6765 14.301 21.5744 14.3739 21.4467 14.4177C21.2626 14.4815 21.0875 14.4633 20.9253 14.3666C20.8341 14.3137 20.7575 14.2353 20.6736 14.1661ZM18.998 21.4632C18.8995 21.5288 18.8867 21.6419 18.8557 21.7385C18.7153 22.1889 18.5385 22.6247 18.3197 23.0422C18.1756 23.3139 18.0298 23.5856 17.8565 23.839C17.5848 24.2365 17.2147 24.4736 16.7078 24.4152C16.4708 24.3879 16.2392 24.4116 16.0095 24.4736C15.7998 24.5301 15.5846 24.5647 15.3768 24.6267C13.774 25.119 12.5596 26.0763 11.8431 27.6152C11.4474 28.4649 11.2414 29.3565 11.3216 30.3029C11.3471 30.5946 11.4128 30.8736 11.5167 31.1453C11.7446 31.736 12.1622 32.1426 12.7402 32.3852C13.2325 32.5912 13.7558 32.6641 14.2827 32.6149C14.9009 32.5584 15.488 32.3779 16.035 32.077C17.2165 31.4279 18.079 30.4779 18.6698 29.2745C18.781 29.0484 18.8612 28.8059 18.9323 28.5634C19.049 28.1641 19.111 27.752 19.1602 27.3381C19.2259 26.7819 19.2824 26.2222 19.4793 25.6898C19.6744 25.1646 19.8659 24.6377 20.061 24.1107C20.0792 24.0597 20.1066 24.0122 20.1376 23.9667C20.1996 23.8737 20.2853 23.8062 20.391 23.7716C20.721 23.6603 21.0201 23.7953 21.135 24.118C21.2444 24.4243 21.3446 24.7361 21.4303 25.0497C21.6564 25.8703 21.8679 26.6926 22.0922 27.5131C22.2782 28.1951 22.4915 28.8679 22.7888 29.5097C23.0313 30.0385 23.323 30.5363 23.7041 30.9793C24.1599 31.5118 24.7106 31.9147 25.3615 32.1736C26.0945 32.4654 26.8585 32.5857 27.6462 32.5474C27.8832 32.5365 28.113 32.4891 28.3373 32.4161C28.959 32.2174 29.4039 31.8163 29.6501 31.2091C29.7321 31.0085 29.7868 30.797 29.8105 30.58C29.8634 30.126 29.847 29.6738 29.7595 29.2271C29.5243 28.0091 28.9882 26.9351 28.1677 26.0052C27.5988 25.3597 26.9077 24.9239 26.0416 24.8036C25.8976 24.7835 25.7572 24.7434 25.6131 24.7307C25.1628 24.6905 24.7142 24.6322 24.2766 24.5119C24.1453 24.4754 24.0323 24.5118 23.9156 24.5775C23.5837 24.7635 23.3759 25.0516 23.2227 25.3871C23.1625 25.5183 23.117 25.6569 23.0477 25.7846C22.889 26.0763 22.5152 26.1401 22.2563 25.925C22.0886 25.7846 22.0266 25.6022 22.0722 25.3907C22.1506 25.0133 22.3201 24.6741 22.5481 24.3642C22.6775 24.1891 22.8289 24.0341 22.9911 23.8883C23.1315 23.7624 23.1334 23.7169 23.0604 23.5619C22.931 23.2829 22.7887 23.0094 22.6793 22.7213C22.5389 22.3493 22.4241 21.9664 22.3019 21.589C22.125 21.0383 21.9573 20.484 21.775 19.9334C21.6947 19.6927 21.5908 19.4611 21.4942 19.2277C21.4741 19.1803 21.4376 19.1384 21.3939 19.0746C21.3392 19.2423 21.3064 19.3645 21.2608 19.4812C21.1714 19.7127 21.0037 19.8714 20.7757 19.9644C20.7083 19.9917 20.6408 20.0136 20.5734 20.0409C20.484 20.0756 20.3965 20.0738 20.3108 20.0337C20.1959 19.9808 20.0756 19.9352 19.9735 19.8623C19.7401 19.6982 19.596 19.4757 19.596 19.1785C19.5979 18.4911 20.2871 18.0644 20.8997 18.3981C20.9781 18.44 21.0547 18.4838 21.135 18.5221C21.1404 18.5257 21.1751 18.4966 21.1732 18.4893C21.1313 18.3525 21.0912 18.2139 21.0383 18.0827C20.2634 16.1517 19.4866 14.2208 18.7081 12.2898C17.3952 9.03327 16.0824 5.77674 14.7696 2.52203C14.7021 2.35611 14.6255 2.192 14.5508 2.01878C14.4851 2.04066 14.4231 2.04248 14.3903 2.0753C14.1405 2.32693 13.9928 2.63325 13.9363 2.98151C13.8688 3.39906 13.9053 3.81114 13.9965 4.2214C14.115 4.75382 14.3174 5.25708 14.5198 5.76215C14.6948 6.19976 14.8717 6.63555 15.034 7.0768C16.5437 11.2067 18.048 15.3385 19.5541 19.4702C19.6033 19.6052 19.658 19.7419 19.689 19.8823C19.7747 20.2743 19.9297 20.6408 20.0592 21.0165C20.1303 21.2225 20.2069 21.4249 20.2798 21.6291C20.3035 21.6966 20.329 21.7659 20.3381 21.837C20.3582 21.9901 20.3126 22.1251 20.1941 22.2272C19.9224 22.4678 19.472 22.3949 19.3061 22.0795C19.2386 21.9518 19.1967 21.8114 19.1438 21.6783C19.111 21.5999 19.0855 21.5124 18.998 21.4632Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M25.4509 25.5857C26.1 25.5857 26.7145 25.8355 27.2761 26.222C27.9124 26.6596 28.4011 27.2358 28.7585 27.9232C28.7913 27.9871 28.8186 28.0545 28.8478 28.1202C28.9992 28.4538 28.7731 28.8586 28.3683 28.9279C28.2333 28.9516 28.1166 28.8914 28.0255 28.7985C27.9635 28.7346 27.9161 28.6544 27.8723 28.5778C27.783 28.421 27.7082 28.2551 27.6116 28.1038C27.1594 27.409 26.5321 26.9459 25.7353 26.7143C25.2029 26.5612 24.6832 26.7672 24.4024 27.1939C24.2475 27.4291 24.1928 27.6917 24.2256 27.9706C24.3204 28.8039 24.7088 29.4767 25.3469 30.0073C25.6277 30.2407 25.9432 30.414 26.2933 30.5252C26.5741 30.6145 26.8567 30.6455 27.1484 30.6018C27.5605 30.5398 27.845 30.3173 27.9817 29.9216C28.0237 29.8031 28.0437 29.6773 28.0802 29.5551C28.1896 29.1959 28.5543 29.0209 28.8989 29.1613C29.0247 29.2124 29.1031 29.3108 29.1323 29.4421C29.1469 29.5114 29.1541 29.5861 29.1487 29.6573C29.0666 30.6109 28.4084 31.4113 27.4949 31.663C27.07 31.7797 26.6361 31.7851 26.2094 31.6538C24.8893 31.2454 23.9338 30.4267 23.3978 29.1431C23.2282 28.7383 23.1152 28.3153 23.1079 27.8813C23.0896 26.8329 23.7041 26.1163 24.4079 25.7954C24.7507 25.6367 25.0169 25.5784 25.4509 25.5857Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M12.0746 29.3671C12.0509 28.8839 12.2005 28.419 12.4156 27.9759C12.9371 26.8983 13.7613 26.1507 14.9009 25.766C15.0376 25.7204 15.178 25.6803 15.3166 25.6438C16.4525 25.3521 17.7216 26.0103 18.0243 27.2885C18.1209 27.6987 18.1045 28.1163 18.017 28.5284C17.8821 29.1629 17.583 29.7154 17.171 30.2095C16.7716 30.6873 16.2957 31.072 15.7469 31.3674C15.7305 31.3765 15.7159 31.3856 15.6995 31.3929C15.3822 31.5515 15.0905 31.4658 14.9082 31.1613C14.775 30.937 14.8188 30.68 15.0285 30.5359C15.147 30.4539 15.2783 30.39 15.4023 30.3171C15.8472 30.0582 16.2119 29.7099 16.4981 29.2833C16.7242 28.9478 16.8756 28.5813 16.9558 28.1874C16.9886 28.0306 16.9923 27.8629 16.9831 27.7024C16.9594 27.2684 16.6057 26.8454 16.1645 26.7196C15.9347 26.654 15.6977 26.6649 15.4661 26.7214C15.2345 26.7761 15.0194 26.8709 14.8225 27.0022C14.1752 27.4325 13.6719 27.9905 13.3255 28.687C13.2288 28.8821 13.1577 29.0882 13.1231 29.3033C13.1048 29.4091 13.0957 29.5203 13.1048 29.626C13.1413 30.0618 13.3601 30.3736 13.7704 30.5359C13.9053 30.5888 14.0457 30.6234 14.1806 30.6745C14.4086 30.762 14.5161 30.9425 14.4961 31.185C14.476 31.4367 14.301 31.6445 14.0767 31.6919C13.9491 31.7193 13.8233 31.7065 13.7011 31.6719C13.0319 31.4859 12.5542 31.0793 12.2679 30.4447C12.1166 30.1092 12.0637 29.7537 12.0746 29.3671Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 32 / 34,\n  svg: CombAndScissors,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as skinCareFlower } from './violetLotus';\nimport { default as skinCareSleepMask } from './sleepMask';\nimport { default as skinCareFaceWashBottles } from './toiletries';\nimport { default as skinCareCombAndScissors } from './combAndScissors';\nimport { default as skinCareFaceIcon } from './towelTurban';\nimport { default as skinCarePalmIcon } from './palmIcon';\n\nexport {\n  skinCareFlower,\n  skinCareSleepMask,\n  skinCareFaceWashBottles,\n  skinCareCombAndScissors,\n  skinCareFaceIcon,\n  skinCarePalmIcon,\n};\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/palmIcon.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Palm Icon', 'sticker name', 'web-stories');\n\nfunction PalmIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 25 39\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M6.64275 23.6505C6.84748 23.5796 7.04285 23.4685 7.22081 23.3293C7.40949 23.1822 7.59281 23.0283 7.7681 22.8664C7.97416 22.6777 8.1722 22.481 8.3689 22.283C9.09282 21.5537 9.9492 21.0345 10.9046 20.6679C11.8975 20.2865 12.9278 20.1032 13.9876 20.1393C15.8369 20.2022 17.5055 20.787 18.9399 21.9739C20.2312 23.0417 21.0648 24.4052 21.4783 26.0256C21.6362 26.6452 21.7218 27.2767 21.7405 27.9177C21.7673 28.8249 21.7017 29.7241 21.4863 30.6086C21.2093 31.7473 20.7316 32.7897 19.9903 33.705C19.5086 34.2991 18.9453 34.7996 18.3016 35.209C17.3944 35.7871 16.4029 36.1577 15.3525 36.3705C14.6058 36.5217 13.8471 36.5578 13.0924 36.4508C12.1544 36.3183 11.3007 35.965 10.5447 35.3897C9.90505 34.9039 9.35776 34.3272 8.90013 33.6662C8.12403 32.5448 7.61689 31.3125 7.39744 29.9663C7.20476 28.7821 7.25561 27.6086 7.61556 26.4565C8.00762 25.204 8.71146 24.1603 9.72841 23.3334C10.5299 22.683 11.4439 22.2763 12.4675 22.1304C13.2289 22.022 13.9769 22.0996 14.7142 22.3177C15.6241 22.5867 16.4136 23.0671 17.096 23.7174C18.0554 24.6313 18.6763 25.7433 18.968 27.0359C19.2396 28.2442 19.1995 29.4391 18.7633 30.6059C18.4261 31.5078 17.8962 32.2772 17.1442 32.8861C16.8324 33.139 16.4925 33.345 16.1245 33.5043C15.4635 33.7893 14.7771 33.887 14.0599 33.7893C13.1178 33.6608 12.315 33.2514 11.6258 32.6104C10.9595 31.9922 10.4844 31.2496 10.2208 30.3758C9.87026 29.2143 9.96392 28.0876 10.5179 27.0091C11.0424 25.9868 11.8841 25.3713 13.0054 25.1318C13.4269 25.0421 13.8484 25.0328 14.2713 25.1157C15.2494 25.3097 15.964 25.8543 16.3989 26.7509C16.6758 27.3222 16.8056 27.9297 16.7789 28.5667C16.7615 28.9828 16.6705 29.3816 16.4818 29.7562C16.1433 30.4333 15.5853 30.7879 14.8453 30.8682C14.4305 30.9124 14.0505 30.7933 13.7226 30.5431C13.1245 30.0841 12.8288 29.4645 12.8234 28.7152C12.8208 28.291 12.972 27.9097 13.2409 27.5778C13.3854 27.3985 13.6343 27.3932 13.7896 27.5832C13.918 27.7411 13.9501 27.9137 13.8685 28.1037C13.8217 28.2134 13.7762 28.3245 13.7347 28.4355C13.6678 28.6122 13.6531 28.7982 13.6571 28.9855C13.6638 29.304 13.811 29.5422 14.0759 29.7121C14.3168 29.866 14.5884 29.9369 14.8667 29.9583C14.9938 29.9677 15.1343 29.9369 15.2548 29.8887C15.7258 29.6974 15.9867 29.3361 16.0643 28.837C16.1045 27.9578 15.877 27.1737 15.216 26.5622C14.7115 26.0952 14.108 25.8985 13.4189 25.9815C12.592 26.0791 11.9376 26.4739 11.4572 27.1456C10.8511 27.994 10.6785 28.9373 10.9046 29.9503C11.0103 30.4213 11.191 30.8642 11.4626 31.2643C12.1531 32.2839 13.1205 32.8031 14.3489 32.8446C15.8489 32.8031 16.997 32.1581 17.761 30.8548C18.0474 30.3664 18.2106 29.8312 18.2789 29.2745C18.4408 27.9685 18.2173 26.7295 17.5536 25.5867C16.9207 24.4975 15.9961 23.7535 14.8092 23.336C14.1227 23.0938 13.4135 23.0082 12.6896 23.0791C11.7115 23.1741 10.8364 23.5274 10.0803 24.1616C9.20789 24.8949 8.64857 25.8276 8.3475 26.9195C8.15213 27.63 8.09459 28.3566 8.13741 29.0925C8.20432 30.2527 8.51877 31.3419 9.0607 32.3669C9.45544 33.1135 9.96125 33.7759 10.5955 34.3379C10.8752 34.5855 11.1803 34.7982 11.5014 34.9869C12.0955 35.3361 12.7432 35.5248 13.4243 35.593C14.6714 35.7188 15.8583 35.486 16.9943 34.9748C17.7022 34.6564 18.3485 34.2429 18.9158 33.709C19.4149 33.2407 19.8204 32.7027 20.1362 32.0952C20.7704 30.8762 21.0675 29.5783 20.9885 28.2094C20.8855 26.3896 20.266 24.7625 19.0697 23.3708C18.5171 22.7285 17.8574 22.2214 17.1228 21.8039C16.447 21.4185 15.7231 21.1603 14.9591 21.0225C14.302 20.9034 13.6397 20.882 12.9747 20.9663C11.7182 21.1228 10.5968 21.6085 9.58658 22.3592C9.39523 22.5011 9.22797 22.675 9.05535 22.8409C8.67132 23.2089 8.29397 23.5822 7.90994 23.9502C7.72795 24.1255 7.53527 24.2901 7.31582 24.4186C7.19004 24.4922 7.05757 24.5537 6.92509 24.6153C6.81403 24.6661 6.69494 24.6755 6.57451 24.6768C6.43669 24.6782 6.31358 24.6353 6.20118 24.5577C6.07941 24.4734 5.98173 24.365 5.90011 24.2433C5.78771 24.0773 5.69805 23.8994 5.6258 23.7134C5.54417 23.5033 5.47326 23.2879 5.39565 23.0764C5.29127 22.7901 5.18957 22.5011 5.07851 22.2174C4.78012 21.4493 4.48038 20.6826 4.17663 19.9159C3.93711 19.3097 3.67618 18.7129 3.3818 18.1322C3.24264 17.8592 3.09143 17.5942 2.91882 17.3413C2.76761 17.1219 2.60035 16.9158 2.40632 16.7325C2.28991 16.6214 2.15878 16.5318 2.0156 16.4595C1.73995 16.3204 1.47501 16.3404 1.23013 16.5291C1.01336 16.695 0.859481 16.9038 0.80328 17.1794C0.76849 17.3507 0.749756 17.5206 0.748418 17.6933C0.741727 18.3904 0.835392 19.0715 1.08963 19.7245C1.29704 20.2571 1.50712 20.7883 1.7172 21.3195C2.69402 23.791 3.66815 26.2638 4.65166 28.7313C5.07985 29.8044 5.52812 30.8709 5.97103 31.9387C6.32295 32.7897 6.76854 33.5886 7.33589 34.3178C8.12136 35.3268 9.06071 36.1604 10.1874 36.7692C11.1548 37.2924 12.1852 37.627 13.2811 37.7594C14.1334 37.8625 14.9778 37.8344 15.8195 37.6791C16.5822 37.5386 17.3101 37.2911 18.0006 36.9392C19.0791 36.3879 20.0077 35.6439 20.7838 34.7139C21.497 33.8602 22.043 32.9061 22.4283 31.8611C22.6826 31.1733 22.8659 30.4668 22.9917 29.7455C23.1362 28.9199 23.2165 28.0876 23.2553 27.25C23.2994 26.2665 23.2901 25.283 23.2687 24.2995C23.2432 23.1567 23.2232 22.014 23.2085 20.8699C23.2031 20.4845 23.2165 20.0992 23.2232 19.7138C23.2432 18.6099 23.2339 17.5073 23.183 16.4047C23.1563 15.8199 23.1402 15.2352 23.1241 14.6504C23.1175 14.4109 23.1295 14.1714 23.1308 13.9332C23.1349 13.5077 23.1442 13.0822 23.1375 12.658C23.1308 12.2592 23.092 11.8618 22.9957 11.4724C22.9676 11.356 22.9355 11.2409 22.8953 11.1285C22.7455 10.711 22.4725 10.3966 22.0925 10.1718C22.059 10.1517 22.0202 10.1383 21.9827 10.1236C21.8784 10.0821 21.7579 10.1223 21.7098 10.22C21.6817 10.2788 21.6536 10.3417 21.6402 10.4046C21.6041 10.5866 21.5773 10.7713 21.5425 10.9532C21.4328 11.5286 21.386 12.1134 21.3471 12.6955C21.2829 13.6509 21.2441 14.6063 21.2521 15.5643C21.2575 16.1772 21.3017 16.786 21.3645 17.3949C21.4047 17.7923 21.4181 18.191 21.4114 18.5898C21.4074 18.8026 21.3806 19.0126 21.3324 19.2214C21.2628 19.5144 21.1197 19.766 20.919 19.9841C20.7624 20.1527 20.5777 20.2745 20.3369 20.2985C20.096 20.3226 19.89 20.2544 19.712 20.0978C19.5809 19.9828 19.4792 19.8436 19.4056 19.6844C19.3333 19.5265 19.2798 19.3619 19.2584 19.1893C19.2209 18.8855 19.1767 18.5831 19.1821 18.2753C19.1901 17.8231 19.2022 17.3721 19.2142 16.9198C19.2263 16.4542 19.253 15.9899 19.253 15.5255C19.257 12.5349 19.2557 9.54422 19.257 6.55223C19.257 6.36623 19.2637 6.18024 19.2624 5.99424C19.2597 5.63697 19.1299 5.31984 18.9386 5.02546C18.7686 4.76319 18.4475 4.7003 18.2013 4.78192C17.7169 4.94249 17.373 5.24624 17.191 5.72662C17.1107 5.93804 17.0545 6.15749 17.0211 6.38095C16.9769 6.68336 16.9421 6.98711 16.9408 7.29354C16.9394 7.59863 16.9435 7.90505 16.9381 8.21014C16.9274 8.84841 16.918 9.48535 16.8993 10.1236C16.8699 11.1205 16.8297 12.1161 16.803 13.1129C16.7923 13.4983 16.8056 13.8837 16.8123 14.2691C16.8204 14.7213 16.8337 15.1723 16.8444 15.6246C16.8578 16.1705 16.8297 16.7138 16.7762 17.257C16.7481 17.5487 16.7013 17.8364 16.621 18.1188C16.5661 18.3128 16.4765 18.4894 16.344 18.6433C16.2289 18.7771 16.0911 18.8802 15.9171 18.9203C15.6187 18.9899 15.3645 18.9069 15.1611 18.6808C15.0072 18.5095 14.9122 18.3061 14.8533 18.084C14.769 17.7602 14.7276 17.431 14.7235 17.0978C14.7195 16.7258 14.7236 16.3525 14.7463 15.9818C14.7905 15.2646 14.8212 14.5487 14.8252 13.8302C14.8346 11.716 14.8574 9.6031 14.8614 7.4889C14.864 6.14678 14.8426 4.80333 14.8333 3.46122C14.8333 3.44783 14.8319 3.43445 14.8319 3.42107C14.8614 2.87379 14.7905 2.3332 14.7035 1.79394C14.6714 1.59858 14.6245 1.40322 14.567 1.2132C14.5335 1.1008 14.4747 0.992418 14.4104 0.893399C14.282 0.692683 14.0304 0.61775 13.8163 0.707402C13.6544 0.775646 13.5086 0.862622 13.3761 0.975023C13.1218 1.19046 12.8997 1.43801 12.6896 1.69492C12.6294 1.76852 12.5906 1.85282 12.5705 1.94515C12.4916 2.32249 12.4086 2.6985 12.3364 3.07718C12.3136 3.1936 12.3176 3.31536 12.3163 3.43445C12.2815 6.81048 12.2481 10.1865 12.2119 13.5625C12.2039 14.3333 12.1838 15.104 12.1771 15.8748C12.1745 16.1397 12.1919 16.406 12.1986 16.671C12.2079 17.0028 12.2186 17.3347 12.224 17.6678C12.228 17.9087 12.1919 18.1455 12.1424 18.3797C12.0848 18.6594 11.963 18.9096 11.7409 19.0969C11.6499 19.1732 11.5482 19.2414 11.4412 19.2896C11.2873 19.3579 11.1267 19.3472 10.9849 19.2481C10.91 19.196 10.8404 19.1317 10.7802 19.0621C10.641 18.8976 10.5514 18.7049 10.4804 18.5028C10.3439 18.1121 10.265 17.7093 10.2382 17.2958C10.1312 15.65 10.1098 14.0028 10.0897 12.3542C10.0844 11.8886 10.079 11.4243 10.079 10.9586C10.0763 9.97509 10.0308 8.99159 9.97998 8.00942C9.94251 7.30692 9.88631 6.60442 9.79131 5.90459C9.73377 5.48309 9.68158 5.06158 9.59996 4.6441C9.52636 4.26541 9.42868 3.89208 9.27748 3.53615C9.19318 3.33945 9.09148 3.15345 8.93091 3.00626C8.76766 2.85639 8.57899 2.83097 8.3756 2.90992C8.26186 2.95407 8.16551 3.02366 8.08121 3.11063C7.97952 3.21634 7.8912 3.3341 7.83634 3.47058C7.78148 3.60573 7.72662 3.74088 7.68112 3.88004C7.58076 4.18379 7.52189 4.49824 7.46702 4.81136C7.34793 5.50583 7.23018 6.20031 7.16997 6.90281C7.11243 7.57855 7.06425 8.25429 7.05623 8.93271C7.04017 10.2481 7.04686 11.5648 7.09236 12.8801C7.10574 13.2789 7.11109 13.6776 7.12982 14.0764C7.17131 14.9528 7.21814 15.8279 7.26631 16.7044C7.28772 17.1018 7.31582 17.5006 7.3466 17.898C7.40815 18.6928 7.47104 19.4877 7.53928 20.2825C7.5714 20.6531 7.61689 21.0225 7.65436 21.3931C7.66774 21.5256 7.6838 21.6581 7.68112 21.7905C7.67577 22.0234 7.46703 22.1719 7.23554 22.1157C7.0656 22.0742 6.95989 21.9618 6.90904 21.7986C6.88897 21.7357 6.88361 21.6688 6.87559 21.6019C6.83544 21.2325 6.79128 20.8619 6.75917 20.4912C6.69494 19.7499 6.63071 19.0086 6.57719 18.266C6.49824 17.1928 6.43 16.1183 6.3564 15.0438C6.35373 15.0037 6.34971 14.9649 6.34837 14.9247C6.29886 13.596 6.24534 12.2686 6.24935 10.9385C6.25337 9.7155 6.29886 8.49248 6.35105 7.27213C6.3845 6.47596 6.43936 5.67979 6.57183 4.89165C6.63874 4.49824 6.7217 4.10886 6.84347 3.72884C6.96122 3.36086 7.11377 3.0076 7.33723 2.68779C7.50717 2.4456 7.71457 2.24354 7.96078 2.07762C8.09459 1.98663 8.24045 1.92374 8.39433 1.88226C8.66998 1.80866 8.92154 1.8662 9.14367 2.04149C9.26945 2.14051 9.37382 2.26094 9.46347 2.39475C9.58792 2.58476 9.69095 2.78414 9.77659 2.99422C9.93716 3.38896 10.0522 3.79842 10.1459 4.21323C10.3051 4.92777 10.4095 5.65035 10.4898 6.37694C10.6905 8.18873 10.7641 10.0072 10.8056 11.8284C10.835 13.1437 10.8578 14.4591 10.8926 15.7758C10.9059 16.2936 10.9354 16.8115 10.9662 17.3293C10.9769 17.514 11.0143 17.6986 11.0464 17.8806C11.0612 17.9595 11.1026 18.0278 11.1655 18.0826C11.2017 18.1134 11.2886 18.1067 11.3034 18.0653C11.3221 18.0157 11.3462 17.9662 11.3515 17.9154C11.3649 17.7562 11.3783 17.5969 11.377 17.4377C11.3555 15.8828 11.3997 14.3279 11.4184 12.7717C11.4479 10.22 11.48 7.66821 11.5094 5.11511C11.5161 4.5705 11.5121 4.02456 11.5188 3.47995C11.5241 3.00091 11.5763 2.52588 11.6767 2.05487C11.7235 1.83275 11.7918 1.61865 11.8787 1.40857C12.1678 0.710079 12.6843 0.271181 13.4069 0.0624375C13.5755 0.0142659 13.7454 -0.00446755 13.918 0.000884858C14.2686 0.0102516 14.5616 0.144062 14.8025 0.396963C14.9684 0.572254 15.0915 0.776984 15.1946 0.995094C15.2909 1.19982 15.3618 1.41526 15.4167 1.63471C15.5104 2.00938 15.5706 2.3894 15.5973 2.77477C15.6401 3.37156 15.6509 3.96969 15.6495 4.56783C15.6482 5.95008 15.6415 7.33234 15.6388 8.7146C15.6348 10.43 15.6268 12.1442 15.6308 13.8596C15.6335 14.6451 15.6054 15.4279 15.5465 16.2106C15.5184 16.584 15.5251 16.9546 15.5826 17.3239C15.6067 17.4805 15.6321 17.6397 15.7204 17.7762C15.7325 17.795 15.7646 17.8003 15.7887 17.807C15.794 17.8083 15.8087 17.7923 15.8128 17.7816C15.8261 17.7454 15.8435 17.708 15.8489 17.6692C15.8636 17.5635 15.8757 17.4578 15.8837 17.352C15.8917 17.2463 15.8917 17.1393 15.8957 17.0336C15.9319 15.6647 15.9626 14.2958 16.0028 12.9269C16.0483 11.3855 16.1018 9.8453 16.1553 8.3038C16.1794 7.62673 16.2062 6.94831 16.241 6.27257C16.261 5.88853 16.2864 5.50316 16.3801 5.12581C16.4323 4.91841 16.4952 4.71769 16.5929 4.52634C16.7427 4.23598 16.9515 4.00047 17.2231 3.81983C17.7196 3.48932 18.2374 3.4572 18.7713 3.72616C19.1125 3.89744 19.3721 4.1597 19.5849 4.47282C19.8525 4.86488 20.0024 5.30111 20.0559 5.77078C20.1027 6.18024 20.1268 6.59104 20.1362 7.00451C20.1696 8.3212 20.1295 9.63655 20.0933 10.9519C20.076 11.6036 20.0612 12.2539 20.0572 12.9055C20.0519 14.1419 20.0532 15.3783 20.0559 16.6148C20.0572 17.0269 20.0371 17.4377 20.0037 17.8498C19.9823 18.1148 19.9783 18.381 19.9783 18.646C19.9783 18.7504 20.0037 18.8561 20.0291 18.9578C20.0492 19.0394 20.1121 19.0902 20.1884 19.125C20.2312 19.1451 20.3034 19.1264 20.3355 19.0929C20.3931 19.034 20.4252 18.9618 20.4413 18.8828C20.4854 18.6741 20.5135 18.4627 20.5122 18.2499C20.5108 17.9702 20.5095 17.6919 20.4988 17.4123C20.4426 16.0166 20.4305 14.6223 20.5028 13.2267C20.5322 12.6687 20.5456 12.1107 20.6018 11.5554C20.6487 11.0924 20.7156 10.6321 20.8373 10.1825C20.9042 9.93763 20.9926 9.70212 21.117 9.48133C21.1959 9.34083 21.2896 9.21238 21.4074 9.10399C21.6455 8.8832 21.9306 8.79355 22.2504 8.82299C22.6264 8.85644 22.9328 9.02772 23.1696 9.3221C23.2954 9.47866 23.3918 9.65261 23.4707 9.83593C23.65 10.2561 23.7357 10.6977 23.7945 11.1473C23.8601 11.6491 23.8748 12.1535 23.8842 12.6593C23.915 14.3212 23.9498 15.9818 23.9819 17.6424C24.0193 19.5291 24.0648 21.4172 24.0889 23.3039C24.105 24.5403 24.0956 25.7767 24.0889 27.0131C24.0862 27.4775 24.0675 27.9431 24.0394 28.4074C23.9698 29.5836 23.7142 30.721 23.3048 31.825C22.8753 32.9797 22.2798 34.0435 21.5077 35.0043C20.753 35.945 19.8779 36.7532 18.8489 37.3874C17.8199 38.0204 16.7146 38.4646 15.5197 38.6573C14.5429 38.8152 13.5648 38.8205 12.5866 38.6332C11.4238 38.4124 10.3426 37.9909 9.34706 37.3526C8.62582 36.8897 8.00093 36.317 7.42822 35.6827C6.74712 34.9294 6.18646 34.0917 5.69136 33.2085C5.09725 32.1528 4.59947 31.0515 4.16058 29.9235C3.73238 28.8209 3.32158 27.713 2.91213 26.6037C2.48795 25.4569 2.04102 24.3195 1.56198 23.1942C1.21274 22.3753 0.864833 21.5564 0.565098 20.7174C0.466079 20.4417 0.369735 20.1661 0.280082 19.8877C-0.0330336 18.9042 -0.0771925 17.906 0.115494 16.8944C0.162328 16.6455 0.243953 16.406 0.351001 16.1772C0.419244 16.0327 0.499528 15.8949 0.6039 15.7731C0.907649 15.4198 1.28901 15.286 1.74664 15.3837C2.17216 15.4734 2.54147 15.6808 2.87064 15.9577C3.1677 16.2066 3.41525 16.5024 3.6347 16.8208C3.91437 17.2263 4.14585 17.6611 4.3546 18.1067C4.68912 18.8173 4.95407 19.5546 5.22436 20.2905C5.41705 20.8137 5.61911 21.3342 5.81045 21.8588C5.90546 22.121 5.98441 22.3887 6.07406 22.6523C6.13427 22.8289 6.19583 23.0042 6.26541 23.1755C6.30555 23.2731 6.36042 23.3655 6.41528 23.4565C6.4688 23.5488 6.53571 23.6144 6.64275 23.6505Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 25 / 39,\n  svg: PalmIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/sleepMask.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Sleep Mask', 'sticker name', 'web-stories');\n\nfunction SleepMask({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 55 22\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M26.5937 1.30043C24.1407 1.28867 21.6895 1.2769 19.2365 1.26514C18.1528 1.2601 17.0675 1.26346 15.9838 1.31891C14.6986 1.38611 13.4267 1.5558 12.1868 1.91198C11.4476 2.12535 10.7386 2.41433 10.0649 2.79068C8.63845 3.58872 7.57663 4.73623 6.83738 6.18615C6.30143 7.23789 5.96373 8.3518 5.84445 9.52619C5.73524 10.5981 5.82092 11.6599 6.09142 12.7033C6.68449 14.9882 7.91937 16.8363 9.84308 18.2106C11.0343 19.0624 12.3683 19.5496 13.8216 19.7277C15.0816 19.8806 16.2779 19.6538 17.4422 19.1868C18.3444 18.8239 19.1727 18.3265 19.9724 17.7771C20.7436 17.2479 21.471 16.6632 22.1952 16.0718C22.7126 15.6501 23.2284 15.2268 23.7459 14.8051C24.1609 14.4674 24.5927 14.1549 25.0715 13.9129C25.5218 13.6861 25.9905 13.5181 26.4861 13.4307C27.2405 13.298 27.9797 13.3686 28.7106 13.592C29.3053 13.7752 29.8598 14.0423 30.3873 14.3665C30.7855 14.6102 31.1786 14.8639 31.555 15.1394C32.0674 15.5124 32.563 15.9072 33.062 16.3003C33.8483 16.9203 34.6346 17.5403 35.4663 18.0981C35.9384 18.4156 36.4306 18.6945 36.9464 18.9331C38.025 19.4304 39.1591 19.6572 40.3436 19.6505C41.4776 19.6437 42.563 19.4001 43.5912 18.928C46.1315 17.7637 47.8267 15.8383 48.6449 13.1703C49.5438 10.2436 48.8617 7.23454 47.0371 4.95968C45.9265 3.57528 44.5354 2.5689 42.8839 1.92374C42.2303 1.66837 41.5583 1.47348 40.8627 1.36427C40.7317 1.34411 40.599 1.32395 40.4696 1.29371C40.2478 1.24162 40.1 1.04841 40.0949 0.819919C40.0848 0.418375 40.4326 0.057156 40.8224 0.102519C41.1198 0.137801 41.4172 0.183161 41.7112 0.247005C42.3967 0.396533 43.0637 0.604869 43.7105 0.880405C44.5925 1.25507 45.3973 1.75573 46.1382 2.35721C46.8808 2.96036 47.5277 3.65425 48.0771 4.43885C48.8029 5.47379 49.3304 6.60114 49.6496 7.82425C49.6832 7.95362 49.7202 8.0813 49.7589 8.20899C49.7807 8.28124 49.8412 8.30812 49.9101 8.31651C49.9437 8.31988 49.9773 8.32492 50.0092 8.32492C50.9097 8.32492 51.8102 8.3266 52.7108 8.3266C52.862 8.3266 53.0082 8.30643 53.1459 8.23251C53.2988 8.14851 53.4063 8.02922 53.4601 7.86121C53.5525 7.57055 53.576 7.2715 53.5727 6.97076C53.5693 6.65322 53.5576 6.33736 53.5458 6.01982C53.5424 5.9207 53.529 5.81989 53.5088 5.72244C53.4349 5.34946 53.1879 5.14449 52.8116 5.12433C52.6453 5.11425 52.4772 5.11593 52.3109 5.11593C51.4272 5.11761 50.5435 5.12097 49.658 5.12265C49.5253 5.12265 49.3909 5.12601 49.2582 5.11761C48.9608 5.09913 48.7138 4.8236 48.7054 4.50942C48.6987 4.22044 48.9171 3.94322 49.196 3.89954C49.3103 3.88274 49.4279 3.87938 49.5455 3.8777C50.2461 3.8693 50.9467 3.85586 51.6473 3.85754C52.0975 3.85922 52.5478 3.87938 52.9964 3.90122C53.1291 3.90794 53.2619 3.93146 53.3895 3.96674C53.9238 4.11123 54.2934 4.44893 54.5219 4.94792C54.6412 5.20834 54.7135 5.48219 54.7454 5.76613C54.821 6.41633 54.8126 7.06652 54.7403 7.71504C54.7084 7.9973 54.6395 8.27283 54.527 8.53661C54.2918 9.08264 53.8751 9.41026 53.2988 9.53963C52.9712 9.61355 52.6369 9.62195 52.3025 9.62195C51.7346 9.62364 51.1685 9.61523 50.6006 9.61355C50.4511 9.61355 50.2998 9.61355 50.1503 9.61859C50.0646 9.62027 50.0041 9.6942 50.0075 9.7866C50.0092 9.8202 50.0075 9.85381 50.0125 9.88741C50.0596 10.336 50.0613 10.7879 50.0478 11.2382C50.0041 12.8125 49.648 14.3128 48.9222 15.714C47.946 17.5974 46.4961 19.0036 44.5875 19.9327C43.6534 20.388 42.6789 20.7257 41.6507 20.8971C41.271 20.9593 40.8913 20.9979 40.5065 21.0013C39.5472 21.008 38.6114 20.8584 37.6974 20.5795C37.0573 20.3847 36.4491 20.1108 35.856 19.805C34.9505 19.3363 34.0987 18.7802 33.2754 18.1804C32.4253 17.5621 31.597 16.9153 30.7973 16.2315C30.4041 15.8954 30.0043 15.5678 29.5758 15.2755C29.2566 15.0588 28.9206 14.8739 28.5627 14.7328C27.642 14.3665 26.7331 14.4354 25.846 14.8504C25.4075 15.0554 24.9959 15.3124 24.6162 15.6149C24.3558 15.8232 24.0987 16.0366 23.8467 16.2533C23.556 16.5036 23.2687 16.7573 22.9814 17.0127C22.0171 17.8696 20.962 18.5987 19.8598 19.2624C19.087 19.7277 18.2772 20.1226 17.4287 20.4317C15.9721 20.9609 14.4785 21.1172 12.9479 20.8484C12.1717 20.7123 11.4274 20.467 10.7134 20.136C9.83132 19.7277 9.01143 19.217 8.27219 18.5836C7.33973 17.7839 6.55681 16.8565 5.94189 15.793C5.27321 14.6387 4.84983 13.3971 4.64318 12.0816C4.53901 11.4213 4.49197 10.756 4.52389 10.0857C4.54741 9.61187 4.54909 9.60683 4.07866 9.61187C3.47887 9.61691 2.87739 9.61187 2.2776 9.61187C2.00878 9.61187 1.74501 9.58499 1.48291 9.52283C0.908317 9.38842 0.496693 9.05072 0.258119 8.51141C0.10019 8.15691 0.0161853 7.78225 0.00778479 7.39414C-0.0022958 6.96068 -0.0022958 6.52553 0.00610469 6.09207C0.0128251 5.74093 0.0749887 5.39483 0.189235 5.06049C0.429489 4.35317 0.933519 3.96674 1.66604 3.89618C2.61362 3.80545 3.56455 3.80377 4.51549 3.86426C4.59949 3.8693 4.68182 3.87938 4.76414 3.88778C5.00944 3.90962 5.25641 4.13139 5.29841 4.40861C5.33706 4.65559 5.21609 4.9076 4.98592 5.04201C4.93047 5.07561 4.86495 5.10081 4.8011 5.10921C4.70198 5.12265 4.60117 5.12097 4.50205 5.12097C4.06858 5.11929 3.63512 5.11425 3.20165 5.11425C2.85219 5.11425 2.50105 5.11761 2.15159 5.12601C2.03566 5.12937 1.91806 5.14113 1.80549 5.16801C1.49803 5.24026 1.31154 5.43179 1.27122 5.75269C1.2561 5.86862 1.24098 5.98454 1.24098 6.10215C1.24434 6.58602 1.25442 7.06989 1.26282 7.55375C1.2645 7.61928 1.27794 7.68648 1.2897 7.75201C1.35018 8.08298 1.55516 8.27788 1.89621 8.31988C2.02894 8.33668 2.16167 8.34508 2.29608 8.34508C3.03028 8.34004 3.76448 8.33164 4.49701 8.32324C4.54741 8.32324 4.59613 8.31652 4.64654 8.3098C4.71878 8.29804 4.76582 8.25435 4.78766 8.18715C4.81791 8.09138 4.84479 7.99562 4.86999 7.89817C5.09344 7.03796 5.4261 6.22144 5.86461 5.44691C6.92811 3.5652 8.42172 2.12872 10.3471 1.1425C11.3064 0.651911 12.3179 0.334371 13.3864 0.184842C14.2298 0.067235 15.0766 -0.00165006 15.9284 3.00383e-05C16.8961 0.00171014 17.8639 0.0134716 18.8316 0.0218721C19.1979 0.0252323 19.5658 0.0269122 19.9321 0.0269122C25.6545 0.0269122 31.3752 0.0269122 37.0976 0.0269122C37.2808 0.0269122 37.4656 0.0235516 37.647 0.0369924C37.8167 0.0487531 37.9713 0.109237 38.0939 0.236924C38.2771 0.426776 38.3056 0.651908 38.225 0.887122C38.1494 1.10889 37.978 1.23658 37.7461 1.27859C37.6806 1.29035 37.6134 1.28867 37.5462 1.29035C37.3967 1.29203 37.2455 1.29203 37.0959 1.29203C33.5929 1.29203 30.0899 1.29203 26.5869 1.29203C26.5937 1.29371 26.5937 1.29707 26.5937 1.30043Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M15.3572 12.0379C15.2748 12.1858 15.2093 12.3017 15.1455 12.4176C14.8615 12.9351 14.4986 13.3853 14.0484 13.7667C13.9845 13.8205 13.9207 13.8743 13.8484 13.9163C13.5796 14.0759 13.2385 14.007 13.0437 13.755C12.879 13.5416 12.874 13.214 13.0437 13.0124C13.1176 12.9233 13.21 12.8494 13.294 12.7687C13.4973 12.5705 13.6871 12.3622 13.8333 12.1169C13.8652 12.0631 13.8249 11.969 13.7611 11.9589C13.2671 11.8783 12.7849 11.7489 12.3078 11.6028C12.2204 11.5759 12.1431 11.6095 12.0877 11.68C12.0154 11.7708 11.9466 11.8649 11.8743 11.9573C11.54 12.3773 11.1468 12.7351 10.6966 13.0292C10.5974 13.093 10.4916 13.1384 10.374 13.1535C10.1068 13.1871 9.85987 13.0628 9.74899 12.836C9.62298 12.5789 9.66666 12.2882 9.86995 12.1017C9.9674 12.0127 10.0783 11.9371 10.1841 11.8565C10.4378 11.6649 10.6714 11.4532 10.8696 11.2029C10.9939 11.0467 10.9889 10.9862 10.836 10.882C10.7402 10.8165 10.6411 10.7543 10.5454 10.6871C10.4513 10.6199 10.3538 10.5527 10.2681 10.4737C10.1959 10.4065 10.132 10.3276 10.08 10.2436C10.006 10.1243 10.001 9.98987 10.0514 9.85882C10.2278 9.40856 10.7486 9.28591 11.083 9.52784C11.1502 9.57656 11.2174 9.62529 11.2846 9.67569C11.8945 10.131 12.5749 10.4334 13.3142 10.6031C14.3021 10.8299 15.295 10.8551 16.2879 10.6367C17.217 10.4317 18.052 10.0403 18.7442 9.37495C18.8165 9.30607 18.887 9.23382 18.9677 9.17502C19.1273 9.06077 19.302 9.03389 19.4885 9.10445C19.7271 9.19518 19.8665 9.37159 19.9169 9.61689C19.9522 9.78994 19.9136 9.95459 19.7943 10.084C19.6481 10.2436 19.4868 10.3897 19.3306 10.5376C19.1626 10.6972 18.9391 10.7946 18.8014 10.9895C18.7661 11.2029 18.7392 11.4179 18.6955 11.6296C18.5628 12.2614 18.2889 12.8259 17.8891 13.3299C17.879 13.3433 17.8672 13.3551 17.8571 13.3685C17.6286 13.634 17.3464 13.6676 17.0591 13.4693C16.8188 13.3047 16.6592 12.9116 16.8894 12.5856C16.9465 12.5033 17.0137 12.4277 17.0641 12.342C17.1481 12.1992 17.2254 12.0513 17.301 11.9035C17.338 11.8329 17.3245 11.7439 17.2926 11.7187C17.2456 11.68 17.1969 11.6952 17.1515 11.7086C16.5735 11.8699 15.9855 11.9774 15.3572 12.0379Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M38.314 12.0531C38.1309 12.0245 37.9528 11.9909 37.7713 11.9708C37.3228 11.9203 36.8893 11.8011 36.4508 11.6986C36.3735 11.6801 36.3281 11.7473 36.3416 11.8212C36.3466 11.8531 36.3533 11.8884 36.3685 11.917C36.4458 12.0632 36.523 12.211 36.6087 12.3538C36.6591 12.4395 36.728 12.5151 36.7835 12.5974C37.0119 12.9368 36.8305 13.3249 36.5919 13.4744C36.5365 13.5097 36.4743 13.5366 36.4138 13.5618C36.224 13.6391 36.0543 13.592 35.9031 13.4644C35.8527 13.4224 35.809 13.3703 35.767 13.3182C35.315 12.7419 35.0177 12.1001 34.9303 11.3693C34.8765 10.9291 34.8917 10.9761 34.559 10.7124C34.3776 10.5679 34.2045 10.4099 34.0298 10.2571C33.9794 10.2134 33.934 10.1646 33.8903 10.1142C33.7374 9.93447 33.6887 9.7295 33.7727 9.50941C33.8685 9.25571 34.0567 9.10283 34.3305 9.06922C34.4498 9.0541 34.564 9.0877 34.6632 9.15323C34.7455 9.20867 34.8211 9.27587 34.8917 9.34644C35.5503 10 36.35 10.3898 37.2404 10.6065C37.9074 10.7695 38.5845 10.8384 39.2734 10.7661C39.7051 10.7208 40.1302 10.6603 40.5519 10.5494C41.2055 10.3797 41.8019 10.0941 42.3479 9.70094C42.4286 9.64214 42.5075 9.57997 42.5915 9.52453C42.9545 9.28763 43.4131 9.4254 43.5963 9.82527C43.6719 9.98824 43.6635 10.1546 43.5542 10.2974C43.4837 10.3881 43.4014 10.4738 43.3106 10.5443C43.1258 10.6872 42.9326 10.8165 42.7428 10.9526C42.7075 10.9778 42.6974 11.0517 42.7226 11.0904C42.7596 11.1458 42.7948 11.2029 42.8368 11.2534C43.0284 11.4869 43.2535 11.6851 43.4938 11.8649C43.5878 11.9355 43.6853 11.9993 43.7727 12.0766C44.0163 12.29 44.06 12.6125 43.8903 12.8898C43.7357 13.1401 43.3778 13.2359 43.0939 13.0998C43.0334 13.0712 42.978 13.0326 42.9225 12.9956C42.4739 12.6999 42.0842 12.337 41.7582 11.9103C41.4894 11.5591 41.518 11.5457 41.0627 11.6885C40.73 11.7927 40.3839 11.8515 40.0428 11.9304C39.9941 11.9422 39.9454 11.9523 39.8984 11.964C39.8379 11.9792 39.8059 12.0716 39.8396 12.127C39.979 12.3572 40.1554 12.5554 40.3469 12.7419C40.4192 12.8125 40.4965 12.8746 40.567 12.9452C40.7468 13.13 40.7955 13.3518 40.7132 13.592C40.6292 13.834 40.4377 13.965 40.189 14.002C40.0143 14.0289 39.8547 13.9667 39.7253 13.8541C39.5371 13.6912 39.349 13.5232 39.1793 13.3417C38.9054 13.0477 38.6786 12.7184 38.4921 12.3622C38.4383 12.2597 38.3762 12.1606 38.314 12.0531Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 55 / 22,\n  svg: SleepMask,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/toiletries.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Toiletries', 'sticker name', 'web-stories');\n\nfunction Toiletries({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 31 36\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.17117 20.3177C1.12473 19.4676 1.08187 18.6174 1.03186 17.7673C0.98364 16.935 0.928274 16.1028 0.87648 15.2705C0.837188 14.6329 0.797896 13.9953 0.76039 13.3577C0.706811 12.42 0.656803 11.4806 0.601437 10.543C0.549644 9.67497 0.492492 8.80876 0.440698 7.94077C0.428196 7.72824 0.413909 7.51571 0.406765 7.30317C0.372831 6.2923 0.251384 5.28858 0.144224 4.28307C0.0835005 3.71869 0.0442084 3.15253 0.00848855 2.58638C-0.0183013 2.17738 0.0209899 1.77018 0.0888576 1.36833C0.124577 1.16115 0.187087 0.953984 0.267457 0.759311C0.403192 0.428902 0.658589 0.219939 1.00329 0.119923C1.24261 0.0502694 1.48729 0.0127592 1.73554 0.00382925C2.21597 -0.0122447 2.69283 0.0252624 3.16969 0.0609823C3.46974 0.0824142 3.77157 0.10742 4.07162 0.10742C6.4827 0.110992 8.89379 0.109209 11.3049 0.110995C11.571 0.110995 11.8371 0.11278 12.1014 0.132426C12.3122 0.1485 12.5265 0.177076 12.7301 0.232441C13.2588 0.371749 13.5802 0.720012 13.6999 1.25402C13.782 1.62015 13.7999 1.98986 13.7785 2.36491C13.7053 3.62225 13.6427 4.87959 13.5659 6.13693C13.4838 7.49964 13.3873 8.86235 13.3016 10.2251C13.2516 11.0038 13.2105 11.7824 13.1659 12.5629C13.1248 13.2541 13.0855 13.9435 13.0444 14.6347C12.9944 15.4669 12.9373 16.2992 12.8908 17.1315C12.8355 18.1048 12.7873 19.08 12.7337 20.0534C12.6819 20.9749 12.6283 21.8947 12.5747 22.8163C12.5711 22.8877 12.564 22.9574 12.5604 23.0288C12.514 23.9683 12.4676 24.9059 12.4229 25.8453C12.3622 27.1384 12.2997 28.4314 12.2461 29.7263C12.2157 30.4532 12.2068 31.1801 12.18 31.907C12.1657 32.3142 12.1354 32.7214 12.1157 33.1286C12.0996 33.4501 12.0193 33.7591 11.9193 34.0627C11.7103 34.6931 11.2924 35.1236 10.6655 35.3432C10.2958 35.4736 9.91181 35.5433 9.52067 35.5718C8.83128 35.6201 8.1401 35.6379 7.44893 35.6058C6.70595 35.5701 5.9612 35.554 5.21644 35.5236C4.89853 35.5111 4.57884 35.4933 4.26093 35.4683C3.9591 35.445 3.6662 35.37 3.38222 35.2664C2.74998 35.036 2.29277 34.611 2.03737 33.9859C1.89628 33.6412 1.78376 33.2893 1.75162 32.9125C1.71768 32.5232 1.68553 32.1356 1.69089 31.7445C1.69268 31.4783 1.68732 31.2122 1.69625 30.9461C1.73197 29.8817 1.68196 28.819 1.60159 27.7563C1.54623 27.0134 1.51408 26.2686 1.47122 25.5256C1.41049 24.4808 1.3462 23.436 1.28547 22.3912C1.24439 21.7001 1.20689 21.0107 1.16938 20.3195C1.17295 20.3177 1.17117 20.3177 1.17117 20.3177ZM2.825 29.1476C2.88751 29.1387 2.95895 29.1351 3.02681 29.1208C3.34115 29.0548 3.65905 29.028 3.97875 29.0315C4.29844 29.0351 4.61813 29.0369 4.93425 29.0637C5.99513 29.153 7.05779 29.1798 8.12224 29.1673C8.75984 29.1601 9.39923 29.1637 10.0368 29.1673C10.1779 29.1673 10.3208 29.1726 10.4601 29.1923C10.6726 29.2244 10.8352 29.4191 10.8495 29.6388C10.8709 29.9424 10.6601 30.1996 10.3583 30.2246C10.1994 30.2371 10.0386 30.2335 9.87966 30.2335C7.75254 30.2335 5.62543 30.2335 3.49653 30.2335C3.33757 30.2335 3.17684 30.2335 3.01788 30.2389C2.85893 30.2442 2.78035 30.3103 2.77142 30.455C2.7357 31.1104 2.69819 31.7677 2.75534 32.4213C2.77856 32.6839 2.85357 32.9429 2.9143 33.2C2.93394 33.284 2.97859 33.3661 3.0286 33.4376C3.38758 33.9555 3.86266 34.2948 4.4949 34.4056C4.94854 34.486 5.40397 34.561 5.86297 34.5949C6.21659 34.6199 6.57022 34.6378 6.92384 34.6681C7.36677 34.7056 7.8097 34.7056 8.25262 34.6896C8.74913 34.6735 9.24206 34.6145 9.72785 34.5074C10.0154 34.4449 10.2583 34.302 10.4476 34.0805C10.6583 33.8376 10.8012 33.5519 10.9245 33.2572C10.9513 33.1929 10.953 33.1197 10.9638 33.0482C10.9709 33.0036 10.9227 32.9321 10.8816 32.9304C10.7048 32.9232 10.528 32.9125 10.3512 32.9125C8.20619 32.9107 6.06121 32.9125 3.91445 32.9107C3.73764 32.9107 3.55904 32.9125 3.38401 32.8946C3.11968 32.8679 2.94109 32.6553 2.9393 32.3838C2.93751 32.132 3.1304 31.8927 3.38222 31.8641C3.55725 31.8427 3.73585 31.8463 3.91266 31.8463C6.09336 31.8445 8.27405 31.8463 10.4547 31.8445C10.6316 31.8445 10.8084 31.8427 10.987 31.8373C11.1066 31.8338 11.1763 31.7712 11.1906 31.6391C11.212 31.4462 11.2352 31.2515 11.237 31.0568C11.2442 30.3657 11.2424 29.6727 11.2442 28.9815C11.2442 28.3082 11.2245 27.6331 11.2495 26.9598C11.2834 26.0382 11.3477 25.1184 11.4031 24.1969C11.446 23.4878 11.4924 22.7806 11.5353 22.0733C11.5371 22.0394 11.5299 22.0037 11.5281 21.968C11.5263 21.9251 11.4478 21.8769 11.4085 21.8983C11.2852 21.9679 11.162 22.0376 11.0406 22.109C9.29564 23.1056 7.43285 23.445 5.45398 23.1021C4.57348 22.9485 3.74478 22.6413 2.96073 22.2126C2.88393 22.1698 2.80892 22.1198 2.73927 22.0662C2.63389 21.9858 2.58746 21.8697 2.5821 21.7411C2.56781 21.3571 2.95359 21.075 3.309 21.2089C3.40723 21.2464 3.50367 21.2946 3.59654 21.3446C4.30737 21.7233 5.06463 21.9501 5.86118 22.0715C7.58288 22.3323 9.17241 21.9822 10.6548 21.091C10.9441 20.9178 11.2138 20.7177 11.471 20.4981C11.5871 20.3998 11.646 20.2802 11.6496 20.1284C11.6549 19.9694 11.6639 19.8087 11.6728 19.6497C11.6853 19.4015 11.6942 19.1532 11.7085 18.905C11.7621 18.037 11.8192 17.1708 11.8693 16.3028C11.955 14.8329 12.0354 13.363 12.1211 11.8932C12.1586 11.2377 12.1979 10.5823 12.2372 9.92858C12.2979 8.9195 12.3604 7.91041 12.4229 6.90132C12.4443 6.56556 12.4693 6.2298 12.489 5.89225C12.5051 5.62613 12.5158 5.36002 12.5247 5.09569C12.5283 4.96889 12.4586 4.88852 12.3425 4.88494C12.1657 4.87959 11.9889 4.8778 11.8103 4.8778C8.83128 4.8778 5.85404 4.8778 2.875 4.8778C2.71605 4.8778 2.55531 4.87602 2.39636 4.87602C2.26955 4.87602 2.15168 4.84386 2.03737 4.79028C1.8427 4.6992 1.73554 4.49024 1.76769 4.26164C1.79805 4.04553 1.97129 3.86157 2.18025 3.83299C2.26777 3.82049 2.35707 3.81692 2.44458 3.81514C2.60353 3.81157 2.76427 3.81335 2.92323 3.81335C5.93798 3.81335 8.95094 3.81335 11.9657 3.81335C12.1425 3.81335 12.3193 3.81156 12.4979 3.80799C12.614 3.80442 12.7033 3.7294 12.7194 3.61867C12.7605 3.32041 12.8105 3.02216 12.8337 2.72211C12.8533 2.47565 12.8462 2.2256 12.8408 1.97735C12.8355 1.76124 12.7712 1.55765 12.6408 1.38083C12.5533 1.26117 12.4372 1.18258 12.2854 1.17365C12.1622 1.16651 12.0371 1.1683 11.9139 1.17009C11.6835 1.17366 11.4531 1.18437 11.2227 1.18437C9.50281 1.18615 7.7829 1.18615 6.063 1.18437C5.86832 1.18437 5.67187 1.18616 5.47898 1.17009C4.84317 1.11829 4.20735 1.06471 3.57333 1.0022C3.07682 0.953981 2.5821 0.952194 2.0856 0.9897C1.91057 1.0022 1.73554 1.04685 1.56766 1.09864C1.40871 1.14865 1.29619 1.25939 1.24797 1.42727C1.18724 1.63266 1.14616 1.84161 1.14795 2.05593C1.15331 2.58816 1.14974 3.12038 1.17831 3.65082C1.21046 4.21698 1.27833 4.78135 1.32655 5.34751C1.37656 5.92974 1.42478 6.51377 1.46586 7.09779C1.50694 7.68181 1.5373 8.26583 1.57302 8.84985C1.5748 8.88557 1.58552 8.91949 1.59088 8.95343C1.59802 8.99986 1.67482 9.03916 1.71411 9.01415C1.77305 8.97665 1.83734 8.9445 1.89092 8.89985C2.67497 8.27297 3.54654 7.8104 4.50383 7.50678C5.07892 7.32461 5.66651 7.18888 6.27017 7.14423C6.99707 7.09243 7.72218 7.11565 8.44194 7.24959C9.44745 7.43534 10.3851 7.79254 11.2549 8.32655C11.4799 8.46586 11.6996 8.62124 11.9014 8.79269C12.1961 9.04273 12.1443 9.4928 11.8139 9.69998C11.7014 9.76963 11.5817 9.79642 11.462 9.72855C11.3085 9.64104 11.1584 9.54816 11.012 9.44815C10.5101 9.10881 9.98324 8.82306 9.41173 8.61588C8.23655 8.19082 7.03279 8.08008 5.80046 8.29262C4.26629 8.55516 2.95537 9.24276 1.86592 10.3554C1.73197 10.4912 1.66053 10.6341 1.68196 10.8269C1.69982 10.9859 1.69804 11.1466 1.70697 11.3056C1.75876 12.12 1.81412 12.9344 1.86413 13.7488C1.93736 14.9526 2.00701 16.1563 2.07667 17.3601C2.15168 18.6531 2.22312 19.9462 2.29813 21.2375C2.36064 22.3359 2.42672 23.4325 2.49102 24.5308C2.53924 25.3631 2.58924 26.1954 2.63389 27.0277C2.66783 27.6474 2.6964 28.2671 2.72855 28.8869C2.73212 28.9405 2.73748 28.994 2.75177 29.044C2.76784 29.0851 2.79642 29.1101 2.825 29.1476Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M30.9722 23.4416C30.9722 26.492 30.9722 29.5443 30.9704 32.5948C30.9704 32.9323 30.9633 33.2681 30.9436 33.6056C30.9347 33.7807 30.899 33.9575 30.865 34.1307C30.715 34.8808 30.2274 35.2898 29.5059 35.4523C29.2987 35.4988 29.088 35.5327 28.8754 35.5506C28.186 35.6113 27.4984 35.6684 26.8055 35.6577C26.0429 35.6452 25.282 35.6399 24.5194 35.5988C23.705 35.5559 22.8888 35.5541 22.0744 35.5309C21.8797 35.5256 21.685 35.5095 21.4939 35.4827C21.3475 35.4613 21.2332 35.372 21.1564 35.2452C20.9349 34.8755 21.2243 34.5075 21.5189 34.4718C21.6243 34.4593 21.7315 34.4504 21.8369 34.4558C22.6155 34.4968 23.396 34.5093 24.1747 34.5701C25.0588 34.6397 25.9446 34.6915 26.8305 34.6683C27.4163 34.654 28.0003 34.6219 28.5754 34.4986C28.7308 34.4647 28.8862 34.429 29.038 34.3772C29.2791 34.2968 29.4809 34.1521 29.6309 33.945C29.8202 33.6842 29.9685 33.402 29.9881 33.0716C30.0006 32.8591 30.0167 32.6465 30.0113 32.434C30.0006 32.0447 29.9917 31.6535 29.956 31.2642C29.9149 30.8213 29.906 30.3783 29.906 29.9354C29.906 25.0561 29.906 20.1786 29.906 15.2992C29.906 14.9438 29.9167 14.5902 29.9131 14.2348C29.9113 13.9687 29.9077 13.7026 29.881 13.4382C29.8363 12.9899 29.5916 12.6881 29.1666 12.5345C28.8987 12.4381 28.6218 12.3881 28.3379 12.3577C27.0644 12.2255 25.7875 12.2398 24.5123 12.272C23.3424 12.3005 22.1744 12.372 21.0028 12.3648C20.6831 12.3631 20.3652 12.3845 20.0526 12.4613C19.5954 12.5738 19.3007 12.8417 19.2132 13.315C19.1882 13.4543 19.1632 13.5936 19.1525 13.7347C19.14 13.9115 19.1418 14.0883 19.1418 14.2669C19.1418 19.4641 19.1418 24.6632 19.1436 29.8604C19.1436 30.3212 19.1204 30.782 19.0704 31.241C19.0078 31.8232 19.0025 32.409 19.0257 32.9948C19.0382 33.3002 19.115 33.5896 19.2293 33.8699C19.3329 34.1253 19.4901 34.3307 19.7597 34.4343C19.8258 34.4593 19.8883 34.495 19.9473 34.5326C20.1312 34.6486 20.2312 34.8951 20.1777 35.0844C20.1062 35.338 19.8723 35.5166 19.624 35.4952C19.5186 35.4863 19.4115 35.4631 19.3132 35.4273C18.9185 35.2773 18.6042 35.0255 18.3935 34.6576C18.297 34.4897 18.2202 34.3075 18.1613 34.1236C18.0523 33.786 17.988 33.4342 17.9863 33.0788C17.9845 32.6716 17.9988 32.2626 18.013 31.8554C18.0291 31.4124 18.0684 30.9695 18.0684 30.5266C18.0738 26.8724 18.072 23.2183 18.0702 19.5624C18.0702 18.8533 18.0488 18.1443 18.0059 17.4353C17.947 16.4619 17.938 15.485 17.9505 14.5098C17.9559 13.9937 18.0059 13.4829 18.0791 12.9739C18.0898 12.9042 18.1023 12.8346 18.1166 12.7649C18.2845 12.0166 18.7364 11.554 19.4883 11.3754C19.7669 11.3093 20.0509 11.3075 20.3313 11.2754C20.4009 11.2682 20.4563 11.2039 20.4581 11.1307C20.4581 11.095 20.4563 11.0593 20.4563 11.0253C20.4545 10.6342 20.4545 10.2449 20.4545 9.85374C20.4545 8.78929 20.4545 7.72484 20.4545 6.66039C20.4545 6.50143 20.4545 6.3407 20.4741 6.18353C20.5063 5.92099 20.7045 5.72274 20.9617 5.69416C21.1189 5.6763 21.2796 5.67809 21.4404 5.67809C22.9656 5.67631 24.4908 5.67809 26.0143 5.6763C26.1911 5.6763 26.3679 5.67095 26.5447 5.6638C26.634 5.66023 26.7001 5.58522 26.7072 5.48878C26.7126 5.39948 26.7162 5.31197 26.7162 5.22267C26.7162 4.37075 26.718 3.51882 26.7162 2.66869C26.7162 2.56332 26.7126 2.45438 26.693 2.35079C26.6858 2.30793 26.6376 2.26149 26.5965 2.24006C26.5519 2.21684 26.4929 2.21505 26.4411 2.21505C25.2713 2.21327 24.1015 2.21327 22.9299 2.21327C22.8781 2.21327 22.8245 2.22755 22.7727 2.2347C22.712 2.24184 22.6691 2.29185 22.6638 2.3365C22.6459 2.45795 22.6423 2.58297 22.6405 2.70799C22.6388 3.34737 22.6423 3.98497 22.6388 4.62435C22.6388 4.76545 22.6352 4.91012 22.603 5.04586C22.553 5.25125 22.4066 5.38161 22.2012 5.42626C21.9904 5.47091 21.8136 5.39234 21.6886 5.22267C21.6386 5.1548 21.6011 5.06549 21.5886 4.98155C21.569 4.84225 21.5707 4.69936 21.5707 4.55649C21.569 3.98854 21.5707 3.4206 21.569 2.85265C21.569 2.72942 21.5636 2.6044 21.5564 2.48117C21.5511 2.39365 21.4671 2.32757 21.3707 2.33471C21.2118 2.34721 21.0528 2.35793 20.8938 2.38115C19.9116 2.52046 18.9293 2.66155 17.947 2.80264C17.7541 2.83122 17.563 2.86516 17.3701 2.89909C17.2826 2.91517 17.2183 2.99196 17.2147 3.08662C17.2093 3.20985 17.2111 3.33487 17.2058 3.45811C17.2022 3.54562 17.1986 3.6367 17.1826 3.72243C17.1379 3.96711 16.8861 4.16358 16.6468 4.15107C16.3932 4.13857 16.161 3.93497 16.152 3.68136C16.1378 3.25629 16.1378 2.82944 16.152 2.40616C16.161 2.15433 16.3289 1.97216 16.5771 1.9293C17.0308 1.8525 17.488 1.7882 17.9434 1.72212C18.856 1.58996 19.7687 1.45958 20.6795 1.3292C20.9956 1.28455 21.31 1.23097 21.6279 1.19704C21.8922 1.16846 22.1583 1.14703 22.4227 1.14525C23.9122 1.13989 25.4017 1.14167 26.8912 1.14346C27.0323 1.14346 27.1752 1.14525 27.3163 1.16133C27.5627 1.18812 27.7467 1.36672 27.7717 1.60782C27.7896 1.76678 27.7896 1.92573 27.7896 2.08647C27.7913 3.0259 27.7896 3.96711 27.7896 4.90654C27.7896 5.04764 27.7878 5.19052 27.7913 5.33161C27.7967 5.56379 27.7931 5.68703 28.12 5.68167C28.1896 5.67988 28.2628 5.69595 28.3289 5.71738C28.5504 5.79061 28.6861 5.9442 28.7147 6.17817C28.7308 6.3014 28.729 6.42642 28.729 6.54966C28.7308 7.61411 28.7308 8.67856 28.729 9.74301C28.729 9.8841 28.7236 10.027 28.7004 10.1663C28.654 10.4217 28.4182 10.5896 28.1557 10.5699C27.9467 10.5538 27.7556 10.4002 27.7003 10.1824C27.6699 10.0645 27.6628 9.93768 27.661 9.81444C27.6556 9.44117 27.6592 9.06968 27.6592 8.69641C27.6592 8.19991 27.661 7.70341 27.6574 7.2069C27.6574 7.10153 27.6467 6.99615 27.6377 6.88899C27.6324 6.82648 27.5592 6.76219 27.4931 6.75683C27.4056 6.74968 27.3163 6.74433 27.2288 6.74255C26.9626 6.74076 26.6965 6.74255 26.4304 6.74255C25.0123 6.74255 23.5943 6.74255 22.1744 6.74255C22.0155 6.74255 21.8565 6.74968 21.6958 6.75683C21.6386 6.75861 21.5565 6.83899 21.5529 6.89435C21.5439 7.03545 21.5332 7.17654 21.5314 7.31763C21.5297 8.18741 21.5314 9.0554 21.5297 9.92517C21.5297 10.3324 21.5225 10.7414 21.5207 11.1486C21.5207 11.2236 21.5725 11.279 21.6529 11.279C21.8297 11.2825 22.0083 11.2915 22.1833 11.2825C23.0692 11.2379 23.955 11.1986 24.8391 11.1379C25.866 11.0682 26.8948 11.0575 27.9217 11.0986C28.4182 11.12 28.9094 11.1968 29.3952 11.3004C29.5327 11.329 29.672 11.3683 29.8042 11.4165C30.3185 11.6076 30.6686 11.963 30.8329 12.4881C30.8847 12.656 30.9258 12.8328 30.9418 13.0078C30.9704 13.3436 30.9883 13.6811 30.9883 14.0169C30.9901 14.7616 30.974 15.5064 30.974 16.2512C30.9704 18.6515 30.9722 21.0465 30.9722 23.4416Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M28.729 23.3414C28.729 24.5648 28.729 25.79 28.729 27.0134C28.729 27.1723 28.7326 27.3331 28.7129 27.492C28.654 27.9528 28.1735 28.0296 27.9039 27.8599C27.7949 27.7921 27.7288 27.6849 27.6949 27.5617C27.677 27.4938 27.6663 27.4224 27.6628 27.3527C27.6574 27.2295 27.6592 27.1045 27.6592 26.9794C27.6592 24.5308 27.6592 22.0823 27.6592 19.6337C27.6592 19.4747 27.661 19.314 27.6699 19.155C27.6788 19.0282 27.7253 18.9121 27.8128 18.8192C27.9592 18.6639 28.1378 18.6031 28.3432 18.6692C28.545 18.7335 28.679 18.871 28.7076 19.0854C28.729 19.2425 28.7272 19.4033 28.729 19.564C28.7308 20.8213 28.729 22.0805 28.729 23.3414Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M28.729 31.6304C28.729 31.984 28.729 32.3377 28.729 32.6931C28.729 32.7985 28.7308 32.9056 28.7254 33.011C28.7076 33.3735 28.5986 33.4825 28.2414 33.5021C28.2235 33.5039 28.2057 33.5039 28.1878 33.5039C27.8128 33.5021 27.677 33.3718 27.6574 32.9985C27.6556 32.9628 27.6556 32.9271 27.6556 32.8931C27.6556 32.0787 27.6556 31.2643 27.6556 30.4499C27.6556 30.3624 27.6556 30.2713 27.6699 30.1856C27.6967 30.0212 27.7824 29.8909 27.9235 29.7998C28.2682 29.5783 28.6629 29.8462 28.704 30.1463C28.7201 30.2677 28.7236 30.3927 28.7236 30.516C28.7308 30.8875 28.729 31.2589 28.729 31.6304Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 31 / 36,\n  svg: Toiletries,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/towelTurban.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Towel Turban', 'sticker name', 'web-stories');\n\nfunction TowelTurban({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 23 38\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M22.7514 14.3029C22.7352 15.1669 22.6778 16.028 22.5836 16.8861C22.3731 18.8261 21.9639 20.7219 21.3531 22.575C21.303 22.7281 21.2265 22.8768 21.2088 23.0328C21.1912 23.1888 21.2338 23.3507 21.2471 23.5112C21.2986 24.1544 21.2795 24.7976 21.225 25.4394C21.1264 26.5772 20.9277 27.7002 20.6348 28.8042C20.2432 30.2805 19.7031 31.6965 18.9494 33.0285C18.371 34.053 17.6777 34.9891 16.8225 35.8016C15.9629 36.62 14.9856 37.2441 13.8552 37.615C13.312 37.7931 12.7542 37.9035 12.1831 37.9477C11.2543 38.0198 10.3432 37.9256 9.45417 37.6489C8.63726 37.3942 7.89394 36.9939 7.21097 36.4802C6.50445 35.9488 5.90687 35.3115 5.36962 34.6123C4.77939 33.844 4.29954 33.0094 3.8874 32.1336C3.29864 30.8854 2.87179 29.5828 2.5671 28.2389C2.38606 27.4397 2.2477 26.6331 2.16822 25.8177C2.11523 25.2789 2.08579 24.7388 2.06371 24.1986C2.04899 23.8321 2.10787 23.4685 2.17263 23.1094C2.44052 21.6257 3.06167 20.2995 4.00516 19.1278C5.22831 17.6103 6.74291 16.4637 8.51656 15.6586C9.35555 15.2773 10.2269 14.9785 11.0909 14.665C11.5708 14.4913 12.0506 14.3132 12.5275 14.1278C13.1133 13.8996 13.6785 13.6229 14.2173 13.2976C15.0504 12.7927 15.7863 12.179 16.3721 11.393C16.9668 10.5937 17.3583 9.70616 17.5629 8.73322C17.7542 7.81917 17.7542 6.90217 17.5703 5.98959C17.4039 5.16827 17.1316 4.38227 16.693 3.6625C16.2588 2.95157 15.6965 2.36722 14.9856 1.93007C14.4322 1.58858 13.8301 1.36927 13.1928 1.25005C12.1698 1.0587 11.1557 1.12199 10.1504 1.36633C9.04644 1.63421 8.02053 2.0802 7.07115 2.70576C5.92159 3.46233 4.9722 4.42642 4.14352 5.51564C3.19855 6.7594 2.48762 8.12974 1.96068 9.59871C1.52941 10.7998 1.24386 12.0362 1.06723 13.3006C0.867054 14.7416 0.853803 16.1855 0.96714 17.6324C1.08784 19.1838 1.37339 20.7028 1.84734 22.185C1.87825 22.2821 1.90622 22.3808 1.9283 22.4808C1.96951 22.6678 1.85617 22.865 1.67366 22.9401C1.39988 23.0519 1.17174 22.9018 1.08931 22.7075C1.06134 22.6398 1.03485 22.5721 1.01277 22.5015C0.634488 21.3151 0.365133 20.1037 0.192919 18.8703C-0.00284436 17.4602 -0.0411152 16.0442 0.0398397 14.6253C0.10166 13.5287 0.270928 12.4469 0.521152 11.3753C0.861163 9.91517 1.36603 8.51685 2.05782 7.18772C2.8188 5.72612 3.75935 4.39257 4.94718 3.24301C5.71699 2.49822 6.5545 1.83881 7.47886 1.29715C8.22512 0.859991 9.00817 0.505262 9.84569 0.272701C10.7583 0.0195327 11.6841 -0.0570076 12.6247 0.0416103C13.1207 0.093127 13.5991 0.230015 14.0686 0.396341C14.3306 0.489071 14.5896 0.587689 14.8472 0.690722C16.1484 1.21031 17.3348 1.91829 18.3828 2.85001C19.3866 3.74198 20.1991 4.78704 20.8408 5.96751C21.4517 7.09205 21.8947 8.27988 22.195 9.52217C22.4423 10.5466 22.6057 11.5858 22.666 12.6397C22.6969 13.1931 22.7234 13.748 22.7514 14.3029ZM11.6326 15.4039C11.534 15.4334 11.4618 15.451 11.3941 15.476C10.5596 15.7896 9.73235 16.1207 8.9331 16.5167C7.9484 17.0054 7.0108 17.5676 6.14973 18.255C5.3917 18.8614 4.72492 19.5518 4.18032 20.3584C3.59155 21.2327 3.21033 22.1894 3.0337 23.2271C2.97777 23.5583 2.92625 23.8909 2.94244 24.2295C2.99543 25.3996 3.11465 26.561 3.35457 27.7091C3.63129 29.0308 4.02429 30.3129 4.57773 31.5434C5.04138 32.5752 5.61101 33.5408 6.33372 34.4136C6.76499 34.9347 7.24777 35.3983 7.79532 35.7957C8.66228 36.4257 9.62049 36.8246 10.6876 36.9718C11.8004 37.1249 12.8719 36.985 13.9155 36.5861C15.018 36.1652 15.932 35.4748 16.7254 34.6153C17.323 33.9676 17.8175 33.2449 18.2473 32.4766C18.8788 31.3476 19.3454 30.1524 19.6928 28.9101C20.1049 27.4397 20.3566 25.9457 20.3963 24.4164C20.4081 23.9321 20.3698 23.4523 20.2859 22.9769C20.1373 22.1335 19.862 21.3357 19.4219 20.5998C18.9774 19.855 18.4299 19.1911 17.7807 18.6127C17.1228 18.0269 16.406 17.5249 15.6406 17.0907C14.3762 16.3754 13.0338 15.844 11.6326 15.4039ZM20.7805 21.2606C20.8541 21.2003 20.8703 21.1134 20.8924 21.0281C21.2603 19.6577 21.5385 18.2712 21.699 16.8596C21.8256 15.7395 21.8888 14.6179 21.8462 13.4919C21.8005 12.3217 21.6798 11.1619 21.4222 10.0167C21.1455 8.78474 20.7319 7.6028 20.1299 6.49004C19.5559 5.42732 18.8287 4.48236 17.9412 3.66103C17.8455 3.57272 17.7395 3.49471 17.6365 3.41375C17.6277 3.40639 17.5982 3.40639 17.5982 3.40934C17.5894 3.43583 17.5761 3.4638 17.5791 3.48882C17.582 3.51679 17.6012 3.54181 17.6159 3.56683C18.162 4.55154 18.474 5.60689 18.5726 6.72996C18.6286 7.35994 18.6065 7.98697 18.5049 8.60812C18.2562 10.1242 17.5791 11.4268 16.512 12.5278C15.6376 13.4316 14.6103 14.116 13.4828 14.6591C13.39 14.7033 13.2958 14.7416 13.2061 14.7901C13.1707 14.8093 13.1486 14.852 13.1104 14.8961C13.1825 14.9329 13.2443 14.9726 13.312 14.9977C14.0774 15.2862 14.8237 15.6188 15.5479 16.0015C16.4148 16.4593 17.2406 16.9818 17.9942 17.6118C19.1423 18.5729 20.0666 19.7048 20.6539 21.0943C20.6716 21.1341 20.6907 21.1738 20.7157 21.2091C20.729 21.2341 20.7569 21.2444 20.7805 21.2606Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M11.5899 2.4836C12.239 2.4836 12.8764 2.56455 13.4916 2.76179C14.4175 3.05911 15.1946 3.58753 15.8099 4.34703C15.8467 4.39266 15.882 4.43976 15.9114 4.48981C16.0704 4.75475 15.9438 5.09918 15.6509 5.21251C15.5464 5.25226 15.4463 5.24048 15.361 5.17424C15.2918 5.12125 15.2358 5.05355 15.174 4.99025C15.0209 4.83276 14.8767 4.66791 14.7163 4.51925C14.1319 3.97906 13.4342 3.66407 12.6585 3.51099C12.1375 3.40943 11.6135 3.40207 11.088 3.44917C10.957 3.46094 10.8275 3.48155 10.695 3.48744C10.5022 3.49627 10.3594 3.40796 10.2608 3.24457C10.2137 3.16803 10.1946 3.08413 10.1887 2.99435C10.1754 2.79711 10.2755 2.64845 10.461 2.5984C10.5449 2.57633 10.6317 2.56013 10.7185 2.55278C11.0085 2.52922 11.2985 2.50715 11.5899 2.4836Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M11.3279 34.318C10.6346 34.3107 10.0032 34.1075 9.42621 33.7322C9.20689 33.5894 8.99199 33.4319 8.79328 33.2612C8.19421 32.746 7.65992 32.1632 7.09029 31.6171C6.90189 31.436 6.92396 31.1475 7.05496 30.9753C7.13002 30.8767 7.22423 30.8164 7.35081 30.8119C7.39497 30.8105 7.43913 30.809 7.48181 30.8134C7.81152 30.8443 8.11915 30.759 8.42089 30.6383C8.7609 30.5028 9.08325 30.3306 9.38499 30.1216C9.60136 29.9715 9.81626 29.8199 10.0312 29.6697C10.0915 29.6285 10.1474 29.58 10.2093 29.5432C10.3756 29.4445 10.5449 29.449 10.7038 29.5564C10.801 29.6212 10.8878 29.7007 10.9791 29.7728C11.0821 29.8537 11.1851 29.9362 11.2896 30.0156C11.3323 30.0495 11.4074 30.0466 11.453 30.0127C11.5119 29.9685 11.5693 29.9229 11.6267 29.8788C11.743 29.7904 11.8578 29.6992 11.9756 29.6138C12.1831 29.4622 12.3847 29.4004 12.6556 29.6065C12.7719 29.6948 12.8896 29.7816 13.0103 29.864C13.2399 30.0201 13.4695 30.1776 13.7021 30.3262C13.9111 30.4602 14.1378 30.5617 14.3703 30.653C14.6603 30.7663 14.9547 30.8355 15.2682 30.8164C15.3124 30.8134 15.355 30.8119 15.3992 30.8119C15.5832 30.8119 15.7039 30.9135 15.7687 31.0725C15.8526 31.2785 15.8305 31.4714 15.6612 31.6347C15.1681 32.1131 14.6794 32.5959 14.1819 33.0699C13.8316 33.404 13.4401 33.6851 13.0088 33.9088C12.4863 34.1841 11.9211 34.3121 11.3279 34.318ZM11.1734 33.3701C11.9991 33.379 12.5687 33.1729 13.0854 32.8152C13.5314 32.5061 13.9199 32.1308 14.2879 31.7334C14.3438 31.673 14.3247 31.5891 14.2423 31.5611C13.8655 31.4301 13.5358 31.2167 13.2134 30.9871C13.0118 30.8429 12.8101 30.6986 12.6041 30.5602C12.4053 30.4263 12.3317 30.4322 12.136 30.5897C12.0447 30.6633 11.9623 30.7457 11.8755 30.8237C11.7989 30.8914 11.7268 30.9636 11.6473 31.0283C11.5487 31.1078 11.4368 31.1166 11.3161 31.0784C11.2028 31.043 11.0998 30.99 11.0114 30.912C10.8569 30.7752 10.6729 30.6839 10.4992 30.5779C10.3697 30.4999 10.249 30.5205 10.1298 30.5956C10.0812 30.6265 10.0341 30.6633 9.98994 30.7001C9.74119 30.9017 9.49539 31.1093 9.21425 31.2697C9.19806 31.2785 9.18923 31.3212 9.19512 31.3448C9.201 31.3683 9.22602 31.3978 9.2481 31.4051C9.37321 31.4449 9.49833 31.4846 9.62638 31.5111C10.2181 31.6347 10.8157 31.6318 11.4133 31.5582C11.8048 31.5096 12.1934 31.4493 12.5776 31.3551C12.6615 31.3345 12.7498 31.3227 12.8366 31.3198C12.9603 31.3168 13.0633 31.3698 13.1398 31.4669C13.2134 31.5612 13.2576 31.6671 13.2635 31.7878C13.2738 31.9924 13.1604 32.1661 12.9647 32.2176C12.7674 32.2691 12.5673 32.3118 12.3671 32.3516C11.7503 32.4767 11.1277 32.5444 10.4978 32.5488C10.1754 32.5503 9.85747 32.4958 9.53954 32.459C9.49685 32.4531 9.45417 32.4428 9.41001 32.4355C9.34672 32.4252 9.29962 32.4472 9.30992 32.4796C9.31875 32.5061 9.32023 32.54 9.33936 32.5576C9.91193 33.0831 10.589 33.3495 11.1734 33.3701Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M8.1412 25.8384C8.1515 25.7736 8.16475 25.703 8.17506 25.6308C8.18095 25.594 8.13678 25.5396 8.10293 25.5411C8.0308 25.544 7.95721 25.5484 7.88509 25.5528C7.79089 25.5587 7.71729 25.6029 7.67166 25.6838C7.56568 25.8767 7.44499 26.0592 7.29485 26.2196C7.22567 26.2947 7.15355 26.3668 7.07407 26.4301C6.93423 26.5434 6.73406 26.5493 6.58098 26.4551C6.42054 26.3565 6.33664 26.1431 6.39699 25.9576C6.42349 25.8766 6.47206 25.8016 6.51622 25.7265C6.54565 25.6765 6.5854 25.6338 6.61925 25.5867C6.63986 25.5573 6.61778 25.4851 6.58393 25.4748C6.50003 25.4483 6.4176 25.4159 6.33223 25.4012C6.29543 25.3939 6.24097 25.4086 6.213 25.4336C6.13794 25.5028 6.07611 25.5837 6.00546 25.6573C5.86416 25.806 5.71697 25.9473 5.54329 26.0577C5.3328 26.1916 5.09141 26.0768 4.99426 25.9458C4.86032 25.7663 4.86768 25.4998 5.01487 25.3394C5.05461 25.2967 5.09877 25.2585 5.14145 25.2187C5.22388 25.1407 5.35782 25.0892 5.35635 24.9611C5.35488 24.8522 5.22977 24.811 5.16059 24.7374C5.00162 24.5667 4.99132 24.3665 5.13557 24.184C5.27392 24.0103 5.51532 23.9087 5.75818 24.0662C5.83178 24.1133 5.90096 24.1678 5.97455 24.2163C6.80765 24.7506 7.99107 24.8655 8.96105 24.0956C9.05231 24.0235 9.13915 23.9455 9.23483 23.8763C9.36435 23.7836 9.51155 23.7865 9.64402 23.8749C9.89424 24.0412 9.95018 24.3709 9.75736 24.6005C9.67346 24.7006 9.57631 24.7904 9.47622 24.8758C9.38202 24.9567 9.33198 25.0509 9.31579 25.1746C9.27457 25.516 9.13915 25.8207 8.94192 26.0989C8.9007 26.1578 8.85066 26.2137 8.79473 26.2594C8.68286 26.3521 8.5548 26.3624 8.42528 26.3006C8.25012 26.2167 8.1412 26.0415 8.1412 25.8384Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M17.9956 24.9612C18.0589 25.1202 18.1943 25.1894 18.2988 25.288C18.4387 25.4204 18.4887 25.5765 18.4505 25.7634C18.4225 25.9003 18.3445 26.0019 18.2223 26.0681C18.0987 26.1358 17.9691 26.1446 17.847 26.0696C17.7484 26.0092 17.6512 25.94 17.5673 25.8606C17.4407 25.7399 17.3244 25.6089 17.2067 25.4793C17.1419 25.4087 17.0698 25.3733 16.9741 25.4087C16.9064 25.4337 16.8372 25.4572 16.7695 25.4837C16.7372 25.4955 16.7224 25.5676 16.746 25.5985C16.7975 25.6692 16.8593 25.734 16.902 25.809C16.9373 25.8709 16.9624 25.9415 16.9741 26.0122C17.0036 26.1961 16.9182 26.3831 16.7695 26.4611C16.5988 26.5494 16.431 26.5317 16.2764 26.4169C16.219 26.3742 16.1616 26.3257 16.116 26.2697C15.9983 26.1225 15.8717 25.9783 15.776 25.8149C15.6082 25.5279 15.5935 25.5588 15.2903 25.5353C15.2755 25.5338 15.2594 25.5367 15.2476 25.5441C15.2255 25.5603 15.1887 25.5809 15.1902 25.5985C15.1946 25.6854 15.2167 25.7722 15.2167 25.8576C15.2196 26.0136 15.1504 26.1373 15.0312 26.2359C14.8546 26.3801 14.6309 26.3625 14.4881 26.1858C14.2732 25.9209 14.1363 25.6177 14.0627 25.2836C14.0509 25.2262 14.0465 25.1688 14.0362 25.1099C14.023 25.0363 13.9876 24.973 13.9332 24.9215C13.8272 24.8214 13.7153 24.7257 13.6182 24.6183C13.3856 24.3592 13.4533 24.0133 13.7624 23.8485C13.8758 23.7881 13.9891 23.7866 14.0951 23.8543C14.1922 23.9176 14.2805 23.9956 14.3703 24.0678C14.6691 24.3106 15.0033 24.4858 15.3786 24.5726C16.0807 24.7345 16.7386 24.6035 17.3524 24.2356C17.4393 24.184 17.5187 24.1163 17.6041 24.0604C17.8426 23.9059 18.0825 24.003 18.2223 24.184C18.3533 24.3533 18.3518 24.5417 18.2179 24.7051C18.1811 24.7493 18.134 24.7861 18.0957 24.8302C18.0619 24.8773 18.028 24.9229 17.9956 24.9612Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M15.726 20.7102C16.4251 20.7132 17.0875 20.878 17.7131 21.1842C18.2591 21.4521 18.7228 21.8259 19.0819 22.322C19.1158 22.3691 19.1496 22.4176 19.1805 22.4662C19.2644 22.6002 19.2821 22.7429 19.21 22.8828C19.1202 23.0535 18.9656 23.133 18.7787 23.1315C18.6757 23.13 18.5785 23.0874 18.5049 23.0108C18.4446 22.9475 18.3872 22.8813 18.3327 22.8121C18.0104 22.3956 17.5865 22.1144 17.1066 21.9201C16.4575 21.6567 15.7819 21.5728 15.0872 21.6817C14.7825 21.7303 14.4911 21.8215 14.2187 21.9717C14.0127 22.085 13.8257 22.2248 13.6727 22.4059C13.6064 22.4839 13.5417 22.5634 13.4651 22.6311C13.262 22.8121 12.9249 22.7635 12.7733 22.5325C12.6968 22.4147 12.685 22.2837 12.7483 22.1571C12.7866 22.0791 12.8396 22.007 12.8926 21.9393C13.2443 21.4889 13.7036 21.1871 14.2261 20.9752C14.7059 20.7809 15.2093 20.7043 15.726 20.7102Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M10.2107 22.7398C10.1033 22.7457 10.0061 22.7178 9.92517 22.6486C9.86924 22.6015 9.81773 22.55 9.7721 22.4926C9.40412 22.0363 8.91544 21.789 8.3517 21.6948C7.40821 21.5373 6.51918 21.7007 5.70227 22.21C5.4388 22.3733 5.20918 22.5735 5.02078 22.8223C4.97662 22.8811 4.93394 22.94 4.88389 22.993C4.65133 23.2462 4.2863 23.1152 4.17002 22.9076C4.10084 22.784 4.08759 22.653 4.1553 22.5294C4.22448 22.4013 4.3069 22.2791 4.39816 22.1658C4.67782 21.8228 5.01048 21.5388 5.39612 21.3209C6.40437 20.7528 7.47592 20.5658 8.61076 20.8102C9.34671 20.9691 9.97081 21.3327 10.4565 21.9156C10.5125 21.9833 10.5655 22.0539 10.6096 22.129C10.7082 22.2968 10.6552 22.5205 10.4933 22.6368C10.4109 22.7016 10.3167 22.7398 10.2107 22.7398Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 23 / 38,\n  svg: TowelTurban,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/skin-care-at-home/violetLotus.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Violet Lotus', 'sticker name', 'web-stories');\n\nfunction VioletLotus({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 48 32\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M1.87691 27.4697C1.99929 27.5473 2.11123 27.6249 2.22914 27.6921C3.53508 28.4279 4.91565 28.9801 6.3589 29.3741C7.54991 29.6995 8.75735 29.9413 9.98717 30.0666C11.42 30.2114 12.8543 30.2502 14.2945 30.1487C15.0811 30.0935 15.8632 30.0055 16.6408 29.8831C17.4855 29.7487 18.3228 29.5652 19.1467 29.3293C19.8049 29.1413 20.4586 28.9353 21.0944 28.6801C21.1899 28.6413 21.2824 28.5995 21.3735 28.5503C21.3944 28.5398 21.4018 28.498 21.4063 28.4697C21.4078 28.4607 21.3839 28.4398 21.3705 28.4368C21.2541 28.413 21.1377 28.3846 21.0183 28.3741C19.2213 28.207 17.4706 27.8174 15.7617 27.2354C14.1184 26.6757 12.5513 25.9473 11.0722 25.0339C9.41405 24.0086 7.90811 22.7937 6.58128 21.3609C4.88132 19.5266 3.54553 17.455 2.66197 15.0998C2.08288 13.5581 1.72169 11.9671 1.62617 10.3178C1.6008 9.8701 1.59035 9.42235 1.57841 8.97459C1.57542 8.85519 1.58289 8.73132 1.60677 8.6149C1.65751 8.37759 1.80079 8.20894 2.03661 8.14775C2.18437 8.11044 2.34108 8.08805 2.49182 8.08954C3.05599 8.09252 3.62165 8.09551 4.18581 8.12237C6.74247 8.24774 9.19615 8.83131 11.5498 9.83278C13.2587 10.5596 14.8647 11.476 16.3721 12.567C16.5109 12.667 16.6527 12.7641 16.7945 12.8596C16.8527 12.8984 16.9363 12.8536 16.9452 12.7805C17.0124 12.2671 17.0646 11.7521 17.1467 11.2432C17.3288 10.1164 17.6452 9.02683 18.0512 7.95969C18.481 6.82837 19.0243 5.75526 19.6675 4.7329C20.469 3.45979 21.4168 2.30609 22.4899 1.25686C22.8212 0.932987 23.1719 0.628516 23.5152 0.316583C23.5913 0.247928 23.6689 0.17778 23.7555 0.12405C24.0092 -0.0341556 24.2734 -0.0431104 24.5331 0.109125C24.6062 0.152408 24.6734 0.20763 24.7391 0.262853C26.4152 1.68819 27.8286 3.3389 28.9435 5.24334C29.8001 6.70748 30.4509 8.25968 30.8583 9.91189C31.0359 10.6313 31.1762 11.3596 31.2509 12.0984C31.2628 12.2163 31.2956 12.3342 31.321 12.4506C31.3285 12.4879 31.4165 12.5163 31.4524 12.4939C31.5523 12.4282 31.6538 12.3641 31.7509 12.2939C33.118 11.3014 34.5806 10.482 36.1388 9.83726C37.2 9.39697 38.2895 9.04026 39.4059 8.76714C40.4551 8.50893 41.5163 8.31939 42.5894 8.20596C43.6968 8.08805 44.8088 8.04178 45.9222 8.09402C46.0416 8.09999 46.1625 8.11342 46.2759 8.14625C46.5296 8.21939 46.6774 8.397 46.7236 8.65818C46.7356 8.72535 46.7371 8.79549 46.7371 8.86415C46.7326 9.26115 46.7416 9.65816 46.7177 10.0537C46.6401 11.3492 46.4311 12.6223 46.0625 13.867C45.4311 16.0073 44.4252 17.955 43.0879 19.7296C41.6447 21.643 39.9178 23.2504 37.9328 24.5787C36.5298 25.5175 35.0418 26.2906 33.4747 26.9055C32.0359 27.4697 30.5509 27.8757 29.0285 28.1413C28.439 28.2443 27.8465 28.3338 27.248 28.3771C27.1465 28.3846 27.0465 28.4115 26.9465 28.4324C26.9331 28.4353 26.9122 28.4577 26.9122 28.4682C26.9151 28.4965 26.9211 28.5383 26.9405 28.5488C27.0151 28.5906 27.0928 28.6294 27.1719 28.6577C27.5898 28.81 28.0062 28.9697 28.43 29.1055C29.4091 29.4189 30.4061 29.6667 31.4195 29.8413C32.9255 30.101 34.4448 30.2084 35.9702 30.1666C37.9985 30.1114 39.9895 29.7935 41.9267 29.1711C43.1043 28.7935 44.2341 28.3025 45.3132 27.6966C45.4162 27.6383 45.5132 27.5652 45.6073 27.4936C45.6207 27.4831 45.6177 27.4219 45.6028 27.407C45.555 27.3592 45.4998 27.316 45.4401 27.2846C45.0177 27.0563 44.6013 26.8175 44.17 26.607C42.9327 26.0055 41.6417 25.5548 40.3029 25.2414C40.1701 25.21 40.0357 25.1787 39.9029 25.1444C39.8372 25.128 39.7701 25.11 39.7074 25.0847C39.4686 24.9906 39.3268 24.7668 39.3432 24.5175C39.3596 24.2757 39.5387 24.0713 39.788 24.0086C39.9596 23.9653 40.1283 23.9832 40.2969 24.022C40.5805 24.0877 40.8641 24.1519 41.1447 24.228C42.47 24.5847 43.7565 25.0533 44.9864 25.6712C45.7222 26.0414 46.4371 26.4488 47.1192 26.9115C47.2042 26.9697 47.2893 27.0264 47.3684 27.0936C47.5177 27.219 47.5565 27.4264 47.4788 27.6115C47.4311 27.7249 47.3624 27.8234 47.2699 27.9025C47.1789 27.9801 47.0818 28.0518 46.9818 28.1174C45.7162 28.9547 44.361 29.607 42.9327 30.1099C41.6029 30.5771 40.2417 30.9099 38.8492 31.1099C37.7806 31.2636 36.7075 31.3621 35.6269 31.3577C34.7359 31.3547 33.8478 31.3338 32.9598 31.2457C31.8509 31.1353 30.7539 30.9562 29.6703 30.695C28.2688 30.3577 26.9062 29.9025 25.5928 29.3025C25.2809 29.1607 24.9764 29.0025 24.6704 28.8503C24.548 28.7891 24.4256 28.7249 24.3048 28.6607C24.2048 28.607 24.1063 28.6174 24.0092 28.6652C23.7645 28.7876 23.5212 28.9159 23.2764 29.0368C21.7168 29.8055 20.084 30.3607 18.3929 30.7517C17.49 30.9592 16.5796 31.1174 15.6617 31.2218C14.2662 31.3786 12.8647 31.4442 11.4588 31.3756C10.3976 31.3248 9.34241 31.2218 8.29467 31.0472C6.25741 30.7069 4.29924 30.1069 2.4366 29.201C1.75751 28.8697 1.10529 28.4921 0.475449 28.0742C0.362019 27.9995 0.253066 27.91 0.163516 27.81C0.0978459 27.7354 0.0485931 27.6369 0.0202355 27.5398C-0.0260321 27.3816 0.00531051 27.2294 0.132173 27.1145C0.208291 27.0458 0.291871 26.9831 0.375451 26.9249C1.09484 26.4234 1.84557 25.9772 2.62764 25.5847C3.8888 24.9518 5.20519 24.4683 6.56934 24.1235C6.88426 24.0429 7.20365 23.9787 7.52156 23.9131C7.63797 23.8892 7.75886 23.8757 7.87826 23.8772C8.17676 23.8802 8.39467 24.0489 8.49168 24.3384C8.55885 24.5369 8.48124 24.7712 8.3096 24.8877C8.19467 24.9668 8.06483 25.0071 7.9305 25.0384C7.46335 25.1459 6.9947 25.2444 6.53203 25.3697C5.03654 25.7757 3.62015 26.3742 2.2769 27.1473C2.17243 27.207 2.06944 27.2682 1.97243 27.3384C1.93362 27.3607 1.91422 27.413 1.87691 27.4697ZM30.124 14.3461C30.1255 13.1208 30.0225 11.9909 29.7972 10.8701C29.4897 9.33876 28.9688 7.88357 28.2569 6.49704C27.9897 5.97615 27.7062 5.46423 27.4211 4.95379C27.051 4.29261 26.6614 3.64337 26.1987 3.04189C25.9793 2.75683 25.739 2.48519 25.4988 2.21803C25.3256 2.0255 25.1212 1.86879 24.8958 1.73894C24.5824 1.55835 24.2585 1.51208 23.9092 1.63297C23.5958 1.74192 23.3242 1.91804 23.0734 2.12848C22.7705 2.3837 22.5018 2.67324 22.2511 2.9807C21.7824 3.55382 21.372 4.16873 20.9884 4.80305C20.0825 6.29704 19.3526 7.86865 18.8631 9.5507C18.4721 10.8984 18.2556 12.2745 18.1989 13.676C18.1586 14.6789 18.2347 15.6744 18.378 16.667C18.5541 17.8848 18.8646 19.0639 19.2959 20.2131C19.9675 21.9997 20.9048 23.6384 22.0361 25.1682C22.3332 25.5697 22.6555 25.9518 23.0331 26.2787C23.2018 26.4234 23.3794 26.5608 23.569 26.6757C23.7137 26.7637 23.8764 26.8279 24.0406 26.8742C24.266 26.9384 24.4779 26.8996 24.6674 26.7443C24.9212 26.5369 25.1525 26.3055 25.3629 26.0578C25.742 25.613 26.1167 25.1653 26.4808 24.7071C27.5241 23.3907 28.3405 21.9385 28.9584 20.3743C29.7345 18.4117 30.1375 16.3774 30.124 14.3461ZM26.5853 27.2458C26.7838 27.2294 27.0569 27.213 27.3286 27.1831C27.6181 27.1518 27.9062 27.1145 28.1942 27.0712C29.6688 26.8428 31.1165 26.4966 32.5225 25.9891C35.3463 24.9697 37.8746 23.4593 40.0522 21.3683C41.2611 20.2072 42.2984 18.9087 43.1625 17.4684C44.367 15.4595 45.1147 13.2954 45.364 10.9611C45.3893 10.7223 45.3893 10.479 45.3938 10.2387C45.3968 10.082 45.364 9.93129 45.3117 9.78204C45.2386 9.57309 45.0983 9.42981 44.8938 9.35667C44.7983 9.32235 44.6968 9.29548 44.5953 9.28653C44.3744 9.26712 44.1506 9.24474 43.9297 9.2522C43.5192 9.26713 43.1088 9.2925 42.6999 9.33429C41.7969 9.42832 40.9029 9.58055 40.0178 9.78502C38.0522 10.2417 36.197 10.976 34.4389 11.97C33.5105 12.4939 32.6299 13.0894 31.8091 13.77C31.321 14.1745 31.3941 14.0446 31.3747 14.6789C31.3494 15.5252 31.2807 16.3655 31.1404 17.1998C30.7927 19.2624 30.0897 21.1952 29.0614 23.0086C28.242 24.4533 27.245 25.7653 26.0853 26.9518C26.0495 26.9891 26.0137 27.0249 25.9779 27.0622C25.9032 27.1413 25.8734 27.2204 25.9107 27.2384C25.954 27.2593 26.0017 27.2801 26.0465 27.2787C26.2032 27.2742 26.3555 27.2607 26.5853 27.2458ZM16.8393 14.5148C16.7407 14.367 16.593 14.2745 16.4587 14.1685C15.3363 13.2864 14.1647 12.479 12.9155 11.7924C11.7259 11.1387 10.4857 10.6014 9.19615 10.179C7.80662 9.72234 6.37681 9.46563 4.92609 9.32085C4.62013 9.291 4.31118 9.2925 4.00373 9.29399C3.85149 9.29548 3.69478 9.31638 3.54702 9.35071C3.23658 9.42533 3.04106 9.62085 2.97091 9.94174C2.91718 10.1805 2.91569 10.4208 2.9336 10.6626C2.98882 11.3865 3.10375 12.0999 3.26345 12.8073C3.64254 14.4879 4.3067 16.0491 5.18877 17.5222C6.47083 19.6624 8.13647 21.4489 10.114 22.9459C11.3916 23.9131 12.7722 24.7056 14.2304 25.3608C15.8318 26.0802 17.4974 26.5951 19.2213 26.9085C19.8108 27.016 20.4048 27.0966 20.9989 27.1682C21.4406 27.2204 21.8854 27.2398 22.3287 27.2697C22.3511 27.2712 22.3899 27.2369 22.3973 27.2115C22.4063 27.1846 22.3973 27.1413 22.3794 27.119C22.3257 27.0518 22.2645 26.9906 22.2048 26.9294C21.3854 26.0921 20.6451 25.1891 19.9899 24.216C18.975 22.7071 18.1944 21.0848 17.6542 19.3445C17.2169 17.9371 16.9706 16.4983 16.8885 15.0282C16.8796 14.8565 16.89 14.6819 16.8393 14.5148Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M12.0021 1.91207C11.9065 1.9658 11.8692 2.06431 11.8245 2.15684C11.3946 3.0419 11.0543 3.95979 10.8096 4.9135C10.5558 5.90004 10.4006 6.903 10.3648 7.92388C10.3618 8.02686 10.3588 8.13133 10.3454 8.23282C10.3051 8.52088 10.0932 8.73281 9.80659 8.77759C9.64988 8.80147 9.50063 8.78356 9.35884 8.70446C9.16481 8.597 9.03944 8.44028 9.03944 8.21193C9.03944 7.95373 9.04541 7.69552 9.06482 7.43732C9.23795 5.20901 9.84092 3.10608 10.8812 1.13149C10.929 1.04045 10.9737 0.946425 11.0275 0.858367C11.1304 0.688222 11.2872 0.582253 11.4782 0.541956C11.5752 0.521061 11.6827 0.52703 11.7812 0.54494C11.8976 0.565835 12.011 0.609118 12.1244 0.647923C14.4751 1.45388 16.6408 2.60758 18.6034 4.14486C18.6974 4.21799 18.79 4.29709 18.8691 4.38664C19.0034 4.53589 19.0094 4.74335 18.9049 4.9135C18.7527 5.16424 18.3333 5.38811 17.9586 5.1717C17.8109 5.08663 17.6751 4.97917 17.5392 4.87618C16.6512 4.20008 15.7199 3.59114 14.7319 3.07175C13.9587 2.66429 13.1662 2.30012 12.3453 1.99715C12.2498 1.96133 12.1498 1.93595 12.0528 1.9076C12.0379 1.90312 12.02 1.91058 12.0021 1.91207Z\"\n        fill=\"#380E63\"\n      />\n      <path\n        d=\"M36.203 1.8957C36.1105 1.92406 36.0269 1.94346 35.9478 1.9748C34.1344 2.67628 32.4255 3.57327 30.8494 4.72399C30.6688 4.85533 30.4897 4.98667 30.3046 5.11055C29.9822 5.32696 29.4942 5.19861 29.2957 4.90458C29.1703 4.71802 29.1778 4.49862 29.336 4.33893C29.4076 4.26579 29.4897 4.20162 29.5718 4.13893C31.4509 2.73001 33.4851 1.61063 35.6896 0.807664C35.9149 0.725576 36.1403 0.646473 36.3642 0.5614C36.691 0.437523 37.0642 0.625578 37.2 0.891243C37.3328 1.15094 37.4671 1.41213 37.591 1.67779C38.1955 2.98075 38.6343 4.33743 38.9029 5.74934C39.0119 6.32545 39.088 6.90603 39.1372 7.49109C39.1492 7.6284 39.1552 7.76721 39.1477 7.90452C39.1372 8.11645 39.0149 8.25675 38.8268 8.33286C38.6477 8.4045 38.4567 8.41047 38.2731 8.35227C38.0626 8.2866 37.9179 8.14332 37.8641 7.9269C37.8343 7.81049 37.8268 7.6896 37.8164 7.5687C37.6761 5.8165 37.2433 4.14042 36.5492 2.53001C36.4806 2.37181 36.409 2.21509 36.3313 2.06137C36.3015 2.00017 36.2493 1.95391 36.203 1.8957Z\"\n        fill=\"#380E63\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 48 / 32,\n  svg: VioletLotus,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sleep/arrowDark.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\n\nconst WellbeingArrowDark = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 205 13\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M.603516 6.49949L204.27 6.49947M199.464.875l4.806 5.8336-4.806 5.8336\"\n      stroke=\"#1F2A2E\"\n      strokeWidth=\"1.09867\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 205 / 13,\n  svg: WellbeingArrowDark,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sleep/arrowLight.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Arrow', 'sticker name', 'web-stories');\nconst WellbeingArrow = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 205 13\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M.333008 6.49949L204 6.49947M199.193.875L204 6.7086l-4.807 5.8336\"\n      stroke=\"#fff\"\n      strokeWidth=\"1.09867\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 205 / 13,\n  svg: WellbeingArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sleep/cta.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Circled Dot', 'sticker name', 'web-stories');\n\nconst Cta = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 61 61\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <rect\n      opacity=\".2\"\n      x=\".496094\"\n      y=\".235352\"\n      width=\"60\"\n      height=\"59.9336\"\n      rx=\"29.9668\"\n      fill=\"#fff\"\n    />\n    <rect\n      x=\"18.4971\"\n      y=\"18.2168\"\n      width=\"24\"\n      height=\"23.9734\"\n      rx=\"11.9867\"\n      fill=\"#FDF5DC\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 61 / 61,\n  svg: Cta,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sleep/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as wellbeingArrowDark } from './arrowDark';\nimport { default as wellbeingArrowLight } from './arrowLight';\nimport { default as wellbeingCTA } from './cta';\n\nexport { wellbeingArrowDark, wellbeingArrowLight, wellbeingCTA };\n"
  },
  {
    "path": "packages/stickers/src/street-style-on-the-go/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as fashionTap } from './tap';\n\nexport { fashionTap };\n"
  },
  {
    "path": "packages/stickers/src/street-style-on-the-go/tap.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Tap', 'sticker name', 'web-stories');\n\nfunction Tap({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <circle opacity=\"0.7\" cx=\"25\" cy=\"25\" r=\"25\" fill=\"#70FFA9\" />\n      <circle cx=\"25\" cy=\"25\" r=\"11.9048\" fill=\"white\" />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: Tap,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-adventure-guide/dashedTrail.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dashed Trail', 'sticker name', 'web-stories');\n\nconst DashedTrail = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 155 164\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M63.26 163.704a.677.677 0 00.673-.591.681.681 0 00-.581-.768 7.12 7.12 0 01-3.11-1.228l-.69-.49a.68.68 0 00-.95.163.68.68 0 00.163.95l.691.491a8.445 8.445 0 003.71 1.464c.031.004.063.009.095.009zm2.71-.105c.04 0 .081-.004.122-.009l.328-.059c.204-.036.409-.082.609-.136a.68.68 0 10-.346-1.318c-.168.045-.34.081-.509.113l-.327.059a.69.69 0 00-.55.796.69.69 0 00.672.554zm3.35-1.332a.69.69 0 00.39-.122 8.273 8.273 0 002.986-3.859.68.68 0 00-1.272-.482 6.911 6.911 0 01-2.496 3.223.68.68 0 00-.163.95c.132.19.34.29.554.29zm-12.386-1.972a.678.678 0 00.395-1.236l-.74-.523a.68.68 0 00-.95.163.68.68 0 00.163.95l.74.523a.674.674 0 00.392.123zm-2.973-2.096a.68.68 0 00.395-1.236l-3.713-2.622a.678.678 0 00-.95.163.68.68 0 00.164.95l3.713 2.623a.683.683 0 00.391.122zm18.59-2.149a.67.67 0 00.682-.669v-.059c0-.286-.019-.609-.055-.927a.686.686 0 00-.754-.6.687.687 0 00-.6.755c.032.268.045.536.045.8 0 .377.305.7.682.7zM48.025 154a.68.68 0 00.395-1.237l-.74-.522a.68.68 0 00-.95.163.68.68 0 00.163.95l.741.523a.684.684 0 00.391.123zm23.69-1.441a.68.68 0 00.605-.991 8.309 8.309 0 00-2.078-2.6 7.092 7.092 0 01-.94-.95.684.684 0 00-.96-.1.684.684 0 00-.1.959 8.28 8.28 0 001.123 1.137 6.932 6.932 0 011.736 2.172.7.7 0 00.614.373zm-26.662-.659a.68.68 0 00.395-1.236l-3.713-2.623a.68.68 0 00-.95.164.68.68 0 00.163.95l3.714 2.622a.656.656 0 00.39.123zm-5.936-4.195a.68.68 0 00.395-1.237l-.74-.522a.68.68 0 00-.95.163.68.68 0 00.163.95l.74.523a.685.685 0 00.392.123zm28.348-.95a.725.725 0 00.218-.037.677.677 0 00.427-.863 8.017 8.017 0 01-.218-.8.683.683 0 00-1.336.282c.068.322.154.64.259.954.1.286.368.464.65.464zm-31.357-1.091a.68.68 0 00.322-1.282 10.033 10.033 0 00-4.481-1.182l-.187-.004a.672.672 0 00-.7.663c-.009.378.291.691.664.7l.187.005a8.666 8.666 0 013.872 1.023.694.694 0 00.323.077zm-6.954-1.782a.68.68 0 00.35-1.263 5.433 5.433 0 01-.664-.473.684.684 0 00-.959.1.684.684 0 00.1.959c.268.218.545.414.818.577.11.068.232.1.355.1zm37.997-.713a.68.68 0 00.673-.578c.027-.172.059-.341.095-.509a6.99 6.99 0 011.669-3.163.683.683 0 00-1-.927 8.325 8.325 0 00-2.118 4.395c-.055.373.2.718.572.777.041 0 .073.005.11.005zm-40.593-1.805a.677.677 0 00.545-1.086c-.781-1.059-1.517-2.341-2.176-3.818a.676.676 0 00-.9-.341c-.341.155-.496.559-.341.9.704 1.563 1.486 2.932 2.327 4.068a.67.67 0 00.545.277zm44.698-3.863a.654.654 0 00.304-.073c.245-.123.5-.232.76-.327a.681.681 0 10-.464-1.282 9.394 9.394 0 00-.91.391.68.68 0 00-.304.913.7.7 0 00.614.378zm3.468-1.059c.054 0 .109-.005.163-.018l.891-.223a5.019 5.019 0 003.209-2.518.689.689 0 00-.286-.923.689.689 0 00-.923.286 3.613 3.613 0 01-2.327 1.828l-.891.222a.682.682 0 00.163 1.346zm-51.416-1.559a.678.678 0 00.645-.9 45.366 45.366 0 01-.272-.846.683.683 0 00-1.304.396c.09.291.186.591.286.886.096.282.36.464.645.464zm55.52-3.482a.683.683 0 00.677-.786 4.924 4.924 0 00-.268-1.018.679.679 0 00-.877-.396.683.683 0 00-.396.877c.091.237.155.487.196.741a.671.671 0 00.668.582zm-56.451-.036c.04 0 .082-.005.118-.009a.678.678 0 00.55-.791c-.077-.437-.132-.85-.168-1.223-.096-1.1-.25-2.209-.464-3.291a.684.684 0 00-.8-.536.682.682 0 00-.536.8 29.1 29.1 0 01.445 3.145c.037.414.096.868.182 1.346a.69.69 0 00.673.559zm54.542-2.936c.209 0 .409-.096.545-.273a.679.679 0 00-.136-.955 3.593 3.593 0 01-1.44-2.836v-.054c0-.159.008-.319.03-.473a.68.68 0 10-1.349-.177c-.027.213-.04.436-.04.654v.082a4.938 4.938 0 001.985 3.9.696.696 0 00.405.132zm-55.82-4.214a.685.685 0 00.655-.872 22.18 22.18 0 00-.277-.887.68.68 0 10-1.295.423c.09.282.181.564.263.845.09.3.36.491.654.491zm55.306-2.204a.67.67 0 00.491-.209c.136-.141.287-.273.441-.391.06-.046.118-.087.173-.132a.685.685 0 00.118-.959.685.685 0 00-.96-.118l-.15.113a5.408 5.408 0 00-.613.541.686.686 0 00.018.964c.141.132.314.191.482.191zm-56.542-1.205a.68.68 0 00.627-.95 30.039 30.039 0 00-2.167-4.108.683.683 0 00-1.155.727 29.112 29.112 0 012.068 3.922.688.688 0 00.627.409zm59.165-1.3c.2 0 .4-.091.536-.259a11.749 11.749 0 002.14-4.281.683.683 0 10-1.318-.355 10.438 10.438 0 01-1.895 3.791.685.685 0 00.114.959.693.693 0 00.423.145zm-62.837-4.954a.68.68 0 00.54-1.095 21.526 21.526 0 00-.577-.727.683.683 0 00-.959-.1.684.684 0 00-.1.959c.187.231.373.463.55.695.141.177.341.268.546.268zm65.232-1.777c.373 0 .677-.3.682-.673v-.2c0-.254-.01-.509-.023-.763a.681.681 0 10-1.359.086c.014.223.023.45.023.673v.182a.68.68 0 00.673.69c-.005.005 0 .005.004.005zm-67.614-.968a.68.68 0 00.486-1.159 30.546 30.546 0 00-3.495-3.059.682.682 0 00-.818 1.091 29.15 29.15 0 013.336 2.922.69.69 0 00.491.205zm67.087-2.614a.676.676 0 00.65-.886 11.859 11.859 0 00-2.34-4.177.683.683 0 00-1.033.895 10.471 10.471 0 012.073 3.696.69.69 0 00.65.472zm-72.76-1.909a.682.682 0 00.36-1.263 20.041 20.041 0 00-.8-.473.683.683 0 00-.677 1.186c.259.146.513.3.763.455a.7.7 0 00.355.095zm-3.208-1.709a.69.69 0 00.623-.4.687.687 0 00-.337-.904 30.177 30.177 0 00-2.79-1.109L.9 102.639a.68.68 0 10-.44 1.287l1.522.522c.904.309 1.8.664 2.663 1.059a.62.62 0 00.282.068zm71.859-2.272a.683.683 0 00.504-1.141c-.2-.218-.39-.436-.577-.664a.68.68 0 00-.959-.086.68.68 0 00-.086.959c.2.241.404.477.618.709a.678.678 0 00.5.223zm-2.204-2.891a.679.679 0 00.573-1.045 20.454 20.454 0 01-1.946-3.936.679.679 0 00-.873-.405.679.679 0 00-.404.873 22.01 22.01 0 002.072 4.2.687.687 0 00.578.313zM71.8 93.735a.68.68 0 00.664-.832 26.127 26.127 0 01-.178-.863.684.684 0 00-.79-.55.683.683 0 00-.55.79c.054.31.118.614.186.919a.687.687 0 00.668.536zm-.5-3.6h.036a.682.682 0 00.646-.718 20.354 20.354 0 01.245-4.386.68.68 0 00-.563-.782.68.68 0 00-.782.564 22.014 22.014 0 00-.26 4.672.68.68 0 00.678.65zm.75-7.208a.677.677 0 00.668-.555l.168-.895a.681.681 0 10-1.34-.25l-.169.895a.681.681 0 00.546.796c.045.004.086.009.127.009zm.673-3.573c.322 0 .609-.227.668-.554l.49-2.618c.11-.582.264-1.16.46-1.714a.683.683 0 00-.418-.868.683.683 0 00-.869.418c-.218.623-.39 1.268-.513 1.914l-.491 2.618a.681.681 0 00.673.804zm2.154-6.89a.68.68 0 00.577-.318c.15-.241.314-.482.482-.714a.683.683 0 00-1.104-.804c-.187.259-.368.527-.537.79a.68.68 0 00.218.941.662.662 0 00.364.105zm2.345-2.754c.16 0 .319-.055.45-.169a11.524 11.524 0 011.91-1.354 11.536 11.536 0 011.767-.818.677.677 0 00.405-.873.679.679 0 00-.873-.404c-.677.25-1.34.554-1.972.913-.76.432-1.473.94-2.132 1.514a.683.683 0 00-.064.963.697.697 0 00.51.228zm17.263-1.573h.036c.319-.018.641-.046.955-.087a.682.682 0 10-.173-1.354c-.282.036-.573.06-.854.077a.682.682 0 00.036 1.364zm-2.718-.155a.686.686 0 00.673-.568.68.68 0 00-.56-.786c-.695-.118-1.386-.3-2.05-.546a13.067 13.067 0 00-2.34-.618.687.687 0 00-.786.56.684.684 0 00.559.786c.713.118 1.418.304 2.095.55.74.272 1.509.477 2.286.609a.64.64 0 00.123.013zm6.295-.45a.825.825 0 00.145-.013l4.446-.95a.677.677 0 00.522-.81.683.683 0 00-.809-.522l-4.445.95a.68.68 0 00.14 1.345zm-14.308-.772c.027 0 .059 0 .09-.005.282-.036.569-.063.855-.082a.678.678 0 00.641-.718.678.678 0 00-.718-.64c-.318.017-.64.05-.955.09a.68.68 0 00.087 1.355zm21.421-.75a.835.835 0 00.146-.014l.89-.19a.681.681 0 10-.286-1.332l-.891.19a.677.677 0 00-.522.81c.063.317.35.536.663.536zm3.555-.764a.824.824 0 00.145-.013l3.391-.728a6.67 6.67 0 001.145-.354.678.678 0 00.368-.891.684.684 0 00-.891-.368c-.295.122-.6.218-.909.281l-3.39.728a.68.68 0 00.141 1.345zm6.617-2.618a.679.679 0 00.514-.232 6.97 6.97 0 00.609-.809.679.679 0 00-.209-.94.684.684 0 00-.941.209c-.145.227-.304.44-.482.64a.68.68 0 00.064.964.656.656 0 00.445.168zm1.441-3.272c.341 0 .641-.26.677-.61.028-.236.041-.477.041-.718 0-1.454-.486-2.89-1.372-4.04a.682.682 0 00-1.082.827 5.286 5.286 0 011.059 3.782.68.68 0 00.604.75c.028.004.05.009.073.009zm-2.604-6.582a.68.68 0 00.645-.9 5.243 5.243 0 01-.2-.777.68.68 0 00-.791-.55.678.678 0 00-.55.79c.059.333.146.664.255.983a.67.67 0 00.641.454zm-.087-3.581a.684.684 0 00.655-.491 5.25 5.25 0 012.422-3.091.682.682 0 00-.681-1.182 6.61 6.61 0 00-3.05 3.89.682.682 0 00.654.873zm5.232-4.582a.676.676 0 00.277-.06c.282-.126.564-.254.841-.39a.684.684 0 00.323-.909.684.684 0 00-.909-.323c-.269.128-.537.255-.809.373-.346.154-.496.56-.346.9.114.255.364.409.623.409zm3.241-1.654a.672.672 0 00.34-.091 37.502 37.502 0 003.859-2.555.682.682 0 00-.822-1.086 35.238 35.238 0 01-3.714 2.459.683.683 0 00-.25.932c.118.218.35.34.587.34zm5.895-4.232a.66.66 0 00.45-.173c.231-.204.459-.413.686-.622a.682.682 0 00-.927-1c-.218.204-.437.404-.659.6a.683.683 0 00.45 1.195zm2.599-2.54a.674.674 0 00.5-.219 35.996 35.996 0 002.918-3.59.678.678 0 00-.159-.95.683.683 0 00-.95.159 34.68 34.68 0 01-2.813 3.454.682.682 0 00.504 1.145zm4.377-5.796c.223 0 .446-.109.573-.313l.491-.764a.678.678 0 00-.204-.94.678.678 0 00-.941.204l-.491.763a.683.683 0 00.572 1.05zm1.969-3.054c.222 0 .445-.11.572-.314l2.459-3.822a.678.678 0 00-.204-.941.678.678 0 00-.941.204l-2.459 3.823a.683.683 0 00.573 1.05zm3.936-6.118c.222 0 .445-.11.572-.314l.491-.763a.678.678 0 00-.204-.941.678.678 0 00-.941.204l-.491.764a.677.677 0 00.205.94c.113.078.24.11.368.11zM143.892 17.476a.673.673 0 01-.573.314.683.683 0 01-.572-1.05l2.459-3.822a.677.677 0 01.94-.205.678.678 0 01.205.94l-2.459 3.823zM147.828 11.358a.673.673 0 01-.573.314.646.646 0 01-.368-.109.678.678 0 01-.204-.94l.491-.764a.677.677 0 01.94-.205c.319.205.41.623.205.94l-.491.764zM149.801 7.931a.674.674 0 01-.941.205.679.679 0 01-.205-.94l2.459-3.823a.678.678 0 01.941-.205.679.679 0 01.205.941l-2.459 3.822zM153.737 1.814a.673.673 0 01-.573.313.646.646 0 01-.368-.109.679.679 0 01-.205-.94l.491-.764a.678.678 0 01.941-.205.679.679 0 01.205.941l-.491.764z\"\n      fill=\"#fff\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 155 / 164,\n  svg: DashedTrail,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-adventure-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as SummerAdventurePlus } from './plus';\nimport { default as SummerAdventureDashedTrail } from './dashedTrail';\nimport { default as SummerAdventureTerrainMap } from './terrainMap';\nimport { default as SummerAdventureShare } from './share';\n\nexport {\n  SummerAdventurePlus,\n  SummerAdventureDashedTrail,\n  SummerAdventureTerrainMap,\n  SummerAdventureShare,\n};\n"
  },
  {
    "path": "packages/stickers/src/summer-adventure-guide/plus.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Plus', 'sticker name', 'web-stories');\n\nconst Plus = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 34 34\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M8.60506 31.1897L16.2748 0.529297L25.3901 2.80951L17.7203 33.4699L8.60506 31.1897Z\"\n      fill=\"white\"\n    />\n    <path\n      d=\"M0.529663 17.7209L31.19 25.3907L33.4702 16.2754L2.80986 8.60565L0.529663 17.7209Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 34 / 34,\n  svg: Plus,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-adventure-guide/share.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Share', 'sticker name', 'web-stories');\n\nconst Share = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 37 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M30.8971 28.2353C32.5284 28.2353 33.9088 28.8157 35.0382 29.9765C36.1677 31.1373 36.7324 32.502 36.7324 34.0706C36.7324 35.702 36.152 37.098 34.9912 38.2588C33.8304 39.4196 32.4657 40 30.8971 40C29.3284 40 27.9637 39.4196 26.803 38.2588C25.6422 37.098 25.0618 35.702 25.0618 34.0706C25.0618 33.4431 25.0931 33.0039 25.1559 32.7529L10.9441 24.4706C9.75196 25.5373 8.37158 26.0706 6.80295 26.0706C5.17157 26.0706 3.75982 25.4745 2.56765 24.2824C1.37549 23.0902 0.779419 21.6784 0.779419 20.0471C0.779419 18.4157 1.37549 17.0039 2.56765 15.8118C3.75982 14.6196 5.17157 14.0235 6.80295 14.0235C8.37158 14.0235 9.75196 14.5569 10.9441 15.6235L25.0618 7.43529C24.9363 6.80784 24.8735 6.33726 24.8735 6.02353C24.8735 4.39215 25.4696 2.9804 26.6618 1.78824C27.8539 0.596072 29.2657 0 30.8971 0C32.5284 0 33.9402 0.596072 35.1324 1.78824C36.3245 2.9804 36.9206 4.39215 36.9206 6.02353C36.9206 7.65491 36.3245 9.06666 35.1324 10.2588C33.9402 11.451 32.5284 12.0471 30.8971 12.0471C29.3912 12.0471 28.0108 11.4824 26.7559 10.3529L12.6382 18.6353C12.7637 19.2628 12.8265 19.7333 12.8265 20.0471C12.8265 20.3608 12.7637 20.8314 12.6382 21.4588L26.9441 29.7412C28.0735 28.7373 29.3912 28.2353 30.8971 28.2353Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 37 / 40,\n  svg: Share,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-adventure-guide/terrainMap.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Terrain Map', 'sticker name', 'web-stories');\n\nconst TerrainMap = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 42 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M40.68 21.999c-.413 0-.807-.154-1.111-.434a1.596 1.596 0 00-.632-.357 6.794 6.794 0 00-1.843-.272 15.244 15.244 0 00-2.276.149l-.076.01a1.623 1.623 0 01-1.847-1.633c.015-.818-.07-1.638-.253-2.435l-.141-.617a19.388 19.388 0 00-.15-.61l-.074-.28a4.84 4.84 0 01.495-3.683c.185-.32.283-.685.283-1.055 0-.232.037-.461.11-.681l.203-.608c.064-.193.096-.394.096-.597a1.167 1.167 0 00-1.169-1.169h-.66a3.889 3.889 0 01-2.445-.868.534.534 0 01.19-.924c.201-.058.388-.166.538-.313a2.044 2.044 0 011.516-.579l.746.034a2.068 2.068 0 001.976-1.23 2.118 2.118 0 011.84-1.26l.883-.036a2.143 2.143 0 001.67-.926c.217-.315.513-.568.857-.733l1.27-.61.02.044-1.269.61a2.14 2.14 0 00-.837.717 2.191 2.191 0 01-1.709.947L36 2.636a2.069 2.069 0 00-1.797 1.23 2.12 2.12 0 01-2.023 1.259l-.746-.034a1.995 1.995 0 00-1.48.564c-.155.153-.35.265-.559.325a.485.485 0 00-.172.84 3.84 3.84 0 002.415.858h.66a1.215 1.215 0 011.218 1.218c0 .208-.034.414-.1.612l-.202.608a2.1 2.1 0 00-.108.666c0 .378-.1.751-.29 1.079a4.793 4.793 0 00-.49 3.646l.074.28c.053.202.104.408.15.612l.142.617c.184.801.27 1.625.254 2.447a1.573 1.573 0 001.792 1.585l.076-.011a15.396 15.396 0 012.283-.15 6.832 6.832 0 011.857.275c.24.07.466.197.65.367.295.271.678.42 1.078.42h.111V22h-.112z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.986 21.686h-.24c-.405 0-.796-.147-1.1-.413a1.64 1.64 0 00-.343-.23 4.013 4.013 0 00-1.49-.414l-.39-.03a9.544 9.544 0 00-2.648.164 1.35 1.35 0 01-1.623-1.324c0-.933-.112-1.865-.332-2.772l-.16-.658a5.665 5.665 0 01.556-4.103c.239-.43.357-.916.34-1.407-.009-.298.088-.591.272-.825.193-.244.284-.549.257-.859l-.042-.49a.529.529 0 01.057-.291.49.49 0 00-.233-.667l-.092-.041a.78.78 0 01-.329-.28.735.735 0 00-.964-.232l-.462.256a1.964 1.964 0 01-2.05-.087l-.211-.144a.403.403 0 01.062-.704.863.863 0 00.222-.143 1.727 1.727 0 011.323-.422l.8.085A2.519 2.519 0 0034.713 4.2c.29-.662.946-1.09 1.668-1.09h1a1.83 1.83 0 001.304-.54 3.254 3.254 0 011.889-.924l.31-.04.007.05-.311.038c-.701.088-1.362.411-1.861.91a1.885 1.885 0 01-1.339.554h-1c-.703 0-1.34.417-1.623 1.061a2.566 2.566 0 01-2.599 1.485l-.799-.084c-.466-.05-.934.1-1.285.41a.917.917 0 01-.235.15.356.356 0 00-.055.62l.212.143a1.91 1.91 0 001.999.086l.461-.257a.785.785 0 011.03.249.725.725 0 00.307.261l.092.042a.54.54 0 01.258.733.485.485 0 00-.052.264l.042.49c.028.323-.067.64-.267.894-.178.225-.27.507-.261.793.016.5-.104.995-.347 1.432a5.616 5.616 0 00-.551 4.068l.16.659a11.8 11.8 0 01.333 2.783 1.302 1.302 0 001.564 1.277 9.601 9.601 0 012.66-.166l.39.03a4.062 4.062 0 011.509.419c.127.063.246.143.353.237.296.258.676.401 1.069.401h.24v.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.664 21.243l-.416-.143a3.996 3.996 0 01-.738-.341 3.862 3.862 0 00-1.71-.53l-.202-.013a8.961 8.961 0 00-2.739.243 1.211 1.211 0 01-1.501-1.176c0-.943-.097-1.89-.29-2.812l-.048-.23a6.117 6.117 0 01.743-4.398c.207-.346.317-.743.317-1.147 0-.325.096-.64.278-.91a1.48 1.48 0 00.236-1.053l-.047-.313a.89.89 0 01.064-.49.746.746 0 00.03-.514l-.05-.165a2.03 2.03 0 01.258-1.732c.103-.153.183-.32.238-.497l.236-.763a1.155 1.155 0 011.255-.801 3.107 3.107 0 002.748-1.02.479.479 0 01.242-.148c1.34-.342 1.4-.342 1.419-.342l.002.146c-.056.005-.587.134-1.385.338a.338.338 0 00-.169.103 3.252 3.252 0 01-2.877 1.068 1.008 1.008 0 00-1.096.7l-.236.763c-.059.19-.145.37-.256.535a1.885 1.885 0 00-.24 1.607l.05.165a.892.892 0 01-.036.615.743.743 0 00-.053.41l.047.313c.063.406-.03.817-.259 1.157a1.477 1.477 0 00-.252.828c0 .43-.117.853-.338 1.222a5.97 5.97 0 00-.725 4.294l.048.229c.194.933.293 1.89.293 2.842a1.065 1.065 0 001.32 1.033 9.1 9.1 0 012.783-.247l.202.013a4.01 4.01 0 011.776.55c.225.133.464.244.71.329l.416.143-.048.14z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.68 20.806l-.56-.188a5.288 5.288 0 01-.5-.196 5.273 5.273 0 00-1.605-.439l-.47-.05a6.927 6.927 0 00-2.709.237.797.797 0 01-1.015-.722l-.01-.187a17.666 17.666 0 00-.379-2.853 5.619 5.619 0 01.68-4.108c.28-.465.45-.996.493-1.537.022-.272.125-.525.3-.735.232-.28.333-.645.276-1.003l-.066-.419a1.145 1.145 0 01.173-.806c.159-.242.215-.533.157-.817l-.026-.127a1.873 1.873 0 01.255-1.377c.165-.262.262-.564.28-.873l.013-.212a.472.472 0 01.582-.434l.726.17a2.023 2.023 0 002.017-.69 2.063 2.063 0 011.207-.724l.484-.094.01.048-.485.094c-.462.09-.88.34-1.178.706a2.072 2.072 0 01-2.066.706l-.726-.169a.424.424 0 00-.522.39l-.012.212a1.884 1.884 0 01-.288.896c-.254.4-.342.877-.248 1.341l.026.128c.06.296.002.6-.164.853-.15.229-.208.503-.165.772l.065.418c.06.373-.045.753-.287 1.042a1.253 1.253 0 00-.288.708 3.572 3.572 0 01-.5 1.558 5.57 5.57 0 00-.674 4.073c.204.939.332 1.901.38 2.86l.01.188a.748.748 0 00.953.678 6.976 6.976 0 012.727-.24l.47.05a5.34 5.34 0 011.62.443c.161.073.328.138.496.195l.56.188-.017.046zM31.153 6.82a.448.448 0 01-.162-.03l-.053-.02a.447.447 0 01-.211-.672.448.448 0 01.472-.185l.056.012a.452.452 0 01-.102.895zm-.055-.772a.302.302 0 00-.108.585l.053.02a.306.306 0 10.179-.585l-.056-.013a.314.314 0 00-.068-.007z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.688 19.781h-.454c-.81 0-1.628-.05-2.432-.151l-.016-.002a9.573 9.573 0 00-2.955.089.565.565 0 01-.667-.54l-.02-.925a6.94 6.94 0 00-.15-1.281 6.868 6.868 0 01.848-5.01c.144-.237.194-.517.142-.79a1.16 1.16 0 01.254-.971c.275-.326.4-.755.343-1.177L35.578 9a2.157 2.157 0 01.176-1.185c.1-.221.162-.456.183-.699l.03-.372a2.05 2.05 0 01.478-1.153 1.757 1.757 0 011.347-.626c.55 0 1.07-.267 1.39-.713l.104-.144a2.681 2.681 0 011.695-1.076l.01.048c-.674.125-1.266.5-1.666 1.056l-.103.144c-.33.46-.865.734-1.43.734-.506 0-.984.222-1.31.61a2 2 0 00-.466 1.125l-.031.372a2.152 2.152 0 01-.187.715 2.108 2.108 0 00-.172 1.158l.003.022c.058.436-.07.879-.355 1.215a1.113 1.113 0 00-.243.93c.055.284.002.577-.148.825a6.817 6.817 0 00-.843 4.974c.09.423.142.858.151 1.29l.021.925a.515.515 0 00.61.494 9.593 9.593 0 012.97-.09l.015.002c.802.1 1.618.151 2.426.151h.454v.048z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.587 19.417c-.088 0-.176-.004-.265-.012-.32-.028-.642-.07-.959-.127l-.838-.148a1.286 1.286 0 00-.448-.001 1.353 1.353 0 01-1.026-.242 1.353 1.353 0 01-.538-.907 9.676 9.676 0 00-.077-.476l-.073-.39a7.46 7.46 0 01.776-4.928c.17-.312.237-.663.197-1.016-.041-.356.095-.71.364-.948.294-.259.418-.656.325-1.037l-.038-.15a1.671 1.671 0 01.175-1.237c.126-.221.2-.472.214-.726l.012-.229a1.567 1.567 0 011.415-1.473l.294-.027a1.856 1.856 0 001.389-.853 1.88 1.88 0 011.166-.833l.33-.078.011.047-.33.078c-.473.112-.877.4-1.136.812a1.904 1.904 0 01-1.425.875l-.294.028a1.518 1.518 0 00-1.37 1.427l-.013.229c-.014.261-.09.52-.22.747-.21.366-.27.792-.17 1.202l.037.15c.098.398-.031.814-.34 1.085a1.048 1.048 0 00-.347.906c.041.362-.029.724-.203 1.044a7.413 7.413 0 00-.77 4.895l.073.39c.03.158.056.32.077.48.047.347.236.666.519.873.282.208.643.293.989.233.154-.027.31-.026.464 0l.839.15c.314.055.636.097.955.126a3.025 3.025 0 002.253-.74l.032.037a3.077 3.077 0 01-2.026.764z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.767 19.043a1.55 1.55 0 01-.222-.016l-2.29-.334a1.267 1.267 0 00-.187-.013 1.358 1.358 0 01-1.341-1.174l-.175-1.31a5.648 5.648 0 01.977-4.007l.14-.2a.736.736 0 00.11-.609.78.78 0 01.193-.74c.36-.377.511-.906.404-1.417-.09-.43-.008-.869.232-1.236l.428-.657c.056-.084.11-.172.163-.259.342-.562.871-.995 1.49-1.22.382-.138.698-.429.869-.797a1.588 1.588 0 011.126-.888l.297-.06.01.049-.297.06a1.539 1.539 0 00-1.091.86c-.177.38-.504.68-.897.822a2.86 2.86 0 00-1.465 1.2 8.573 8.573 0 01-.164.26l-.428.657a1.586 1.586 0 00-.225 1.2 1.624 1.624 0 01-.417 1.46.731.731 0 00-.181.694.785.785 0 01-.117.649l-.14.2a5.601 5.601 0 00-.969 3.973l.175 1.31a1.309 1.309 0 001.293 1.13c.065 0 .13.006.195.015l2.29.334a1.474 1.474 0 001.617-1.003l.267-.812.046.015-.266.813a1.526 1.526 0 01-1.45 1.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.673 18.617a1.5 1.5 0 01-.264-.023l-1.817-.316a.91.91 0 00-.202-.013 1.074 1.074 0 01-1.058-.698l-.177-.472a4.905 4.905 0 01.245-3.977l.197-.376c.092-.175.227-.326.393-.435.295-.194.467-.52.46-.874a1.35 1.35 0 01.216-.761l.003-.005c.218-.338.319-.744.284-1.145a1.97 1.97 0 01.146-.933l.084-.201c.13-.309.28-.611.447-.901.32-.555.829-.977 1.433-1.19.318-.112.566-.358.681-.675.145-.4.477-.698.89-.798l.258-.063.034.142-.258.063c-.364.089-.659.353-.787.706a1.26 1.26 0 01-.77.763c-.571.2-1.053.6-1.355 1.125a7.837 7.837 0 00-.438.884l-.085.201a1.83 1.83 0 00-.135.864c.038.433-.07.872-.306 1.238l-.003.004c-.13.203-.197.438-.192.68.007.403-.19.777-.527.999a1.026 1.026 0 00-.343.38l-.197.375a4.756 4.756 0 00-.238 3.858l.177.473c.142.379.51.621.914.602.078-.003.157.001.235.015l1.817.316a1.382 1.382 0 001.55-.926l.385-1.156.14.047-.386 1.155a1.53 1.53 0 01-1.452 1.047z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.36 18.012a1.5 1.5 0 01-.25-.021l-.902-.152a1.99 1.99 0 01-1.571-1.43l-.218-.8a2.354 2.354 0 01.3-1.901l.326-.498c.092-.142.207-.266.342-.37.358-.278.572-.715.572-1.168 0-.301.069-.604.2-.875l.31-.647a1.78 1.78 0 00.173-.766c0-.448.164-.878.462-1.212a5.027 5.027 0 012.435-1.508l.141-.038.013.047-.142.038a4.972 4.972 0 00-2.41 1.493 1.77 1.77 0 00-.45 1.18c0 .27-.062.543-.18.787l-.31.647a1.99 1.99 0 00-.194.854c0 .468-.22.92-.591 1.206-.13.101-.241.222-.331.36l-.326.497a2.292 2.292 0 00-.294 1.862l.218.799a1.941 1.941 0 001.532 1.395l.012.002.89.15a1.443 1.443 0 001.614-.975l.02-.058c.258-.789.47-1.602.625-2.418l.038-.195.048.01-.038.195a19.615 19.615 0 01-.628 2.423l-.019.058a1.488 1.488 0 01-1.418 1.028z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.087 17.067a1.8 1.8 0 01-.519-.076l-.047-.015a2.45 2.45 0 01-1.509-1.293 1.69 1.69 0 01.596-2.14c.38-.25.645-.633.747-1.076l.005-.021c.039-.17.059-.344.059-.518 0-.457.131-.901.38-1.285l.284-.437c.1-.153.19-.315.27-.479.127-.263.33-.477.583-.62.236-.134.41-.36.48-.62.055-.212.174-.399.342-.54l.803-.673.032.038-.804.673c-.16.134-.273.312-.327.514-.073.274-.256.51-.502.65a1.37 1.37 0 00-.564.6c-.08.167-.172.33-.273.484l-.283.437c-.244.376-.373.811-.373 1.259 0 .177-.02.355-.06.53l-.005.02a1.805 1.805 0 01-.767 1.106 1.647 1.647 0 00-.58 2.077 2.4 2.4 0 001.48 1.268l.047.015a1.763 1.763 0 002.134-1.02c.231-.563.416-1.15.548-1.744l.132-.586.048.01-.132.587a10.952 10.952 0 01-.55 1.752 1.813 1.813 0 01-1.675 1.123z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.396 16.471c-.183 0-.365-.048-.527-.142l-.54-.315a1.89 1.89 0 01-.236-.162 1.366 1.366 0 01-.447-1.474c.085-.273.261-.514.496-.677.184-.129.33-.305.422-.51l.586-1.296c.093-.205.203-.405.328-.593a3.485 3.485 0 012.204-1.495l.01.048a3.432 3.432 0 00-2.173 1.475 4.145 4.145 0 00-.324.586l-.586 1.296a1.294 1.294 0 01-.439.53 1.25 1.25 0 00-.477.651c-.161.521.008 1.08.432 1.422.071.058.149.112.228.158l.54.315a.996.996 0 001.385-.393c.173-.324.312-.668.413-1.022l.106-.376a6.439 6.439 0 01.662-1.534l.042.025a6.37 6.37 0 00-.656 1.522l-.107.376a5.208 5.208 0 01-.417 1.032 1.045 1.045 0 01-.925.553z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M38.329 15.903a.862.862 0 01-.482-.147l-.318-.216a1.01 1.01 0 01-.414-1.06c.053-.225.182-.426.365-.566.203-.156.367-.349.491-.573l.25-.454c.072-.13.134-.267.184-.407.132-.367.333-.699.598-.985.228-.245.536-.4.869-.437.49-.053.765-.08.816-.08v.049c-.049 0-.33.028-.811.08a1.34 1.34 0 00-.838.42 2.82 2.82 0 00-.589.969 2.9 2.9 0 01-.187.414l-.25.454a1.88 1.88 0 01-.503.588.958.958 0 00-.348.538.96.96 0 00.394 1.008l.318.216a.81.81 0 001.223-.418l.151-.463c.024-.074.047-.148.068-.22a5.113 5.113 0 011.355-2.243l.034.036a5.069 5.069 0 00-1.342 2.22 7.126 7.126 0 01-.068.222l-.152.463a.862.862 0 01-.814.592z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M39.155 13.122a.403.403 0 01-.267-.101.403.403 0 01-.096-.485 2.09 2.09 0 011.349-1.092l.417-.108.036.142-.416.107a1.944 1.944 0 00-1.255 1.016.256.256 0 00.061.31c.068.06.16.08.246.053a.646.646 0 00.218-.114l1.082-.87.092.115-1.082.869a.795.795 0 01-.267.14.425.425 0 01-.118.018zM38.144 15.366a.599.599 0 01-.591-.496.804.804 0 01.28-.76l.36-.297a.519.519 0 01.834.52l-.092.381a.855.855 0 01-.69.644.646.646 0 01-.101.008zm.378-1.525c-.086 0-.17.03-.237.085l-.36.298a.657.657 0 00-.229.62.452.452 0 00.523.37.71.71 0 00.572-.534l.092-.38a.372.372 0 00-.36-.46z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.789 22.506a2.648 2.648 0 01-1.463-.615l-.004-.004a2.51 2.51 0 00-1.618-.591h-.783c-.553 0-1.114.024-1.665.071l-.553.047a1.96 1.96 0 01-1.237-.313 1.944 1.944 0 01-.879-1.63c0-.888-.128-1.771-.38-2.624l-.502-1.697a4.044 4.044 0 01.394-3.19c.32-.542.509-1.16.546-1.787l.015-.263a1.636 1.636 0 00-1.32-1.7 5.135 5.135 0 01-2.163-.977l-.685-.53a.603.603 0 01-.131-.811.606.606 0 01.385-.255l.36-.069c.312-.06.583-.238.762-.501a1.232 1.232 0 011.079-.543l.872.035c.777.03 1.47-.47 1.682-1.22a1.737 1.737 0 011.775-1.251c.073.004.146.007.218.007h.184c1.18 0 2.218-.754 2.582-1.877l.047.015a2.758 2.758 0 01-2.63 1.911h-.183c-.073 0-.147-.002-.221-.007a1.688 1.688 0 00-1.725 1.217c-.22.77-.93 1.286-1.733 1.254l-.872-.035a1.19 1.19 0 00-1.036.522c-.186.273-.468.459-.793.521l-.36.07a.554.554 0 00-.438.65.55.55 0 00.204.328l.686.531a5.087 5.087 0 002.141.968 1.686 1.686 0 011.361 1.75l-.016.263a4.04 4.04 0 01-.552 1.809c-.559.948-.7 2.097-.389 3.152l.502 1.697c.254.857.382 1.745.382 2.638a1.897 1.897 0 002.063 1.895l.553-.048a19.614 19.614 0 011.67-.071h.782a2.577 2.577 0 011.65.603l.004.004c.408.344.904.553 1.436.604l-.004.047z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.788 22.877l-.17-.022a2.477 2.477 0 01-1.298-.58 2.438 2.438 0 00-1.589-.588h-.818c-.548 0-1.103.023-1.649.07l-.525.044a2.298 2.298 0 01-2.493-2.376 7.47 7.47 0 00-.34-2.527l-.589-1.87a3.968 3.968 0 01.42-3.295c.29-.467.377-1.04.238-1.57a1.994 1.994 0 00-1.34-1.405 2.775 2.775 0 01-.994-.554l-.83-.72a3.593 3.593 0 01-.975-1.367.675.675 0 01.556-.92l.335-.034c.37-.037.707-.248.903-.564a1.258 1.258 0 011.132-.592l.24.012a2.046 2.046 0 002.082-1.534 1.534 1.534 0 011.741-1.127c.055.01.112.016.167.02l.956.056A1.547 1.547 0 0037.527.298l.047.012a1.596 1.596 0 01-1.629 1.173l-.956-.056a1.563 1.563 0 01-.172-.02 1.484 1.484 0 00-1.686 1.09 2.096 2.096 0 01-2.132 1.571l-.24-.012a1.208 1.208 0 00-1.088.569 1.264 1.264 0 01-.94.587l-.335.034a.627.627 0 00-.515.853c.208.517.54.983.962 1.348l.83.72c.286.248.614.431.975.545.68.213 1.192.75 1.373 1.438a2.062 2.062 0 01-.244 1.61 3.918 3.918 0 00-.414 3.253l.588 1.871c.26.825.375 1.68.343 2.543a2.249 2.249 0 002.44 2.326l.525-.044c.548-.047 1.104-.07 1.654-.07h.818c.594 0 1.17.213 1.62.6.361.31.802.507 1.274.568l.17.022-.007.048z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.675 23.335l-.129-.022a2.404 2.404 0 01-1.174-.566 2.247 2.247 0 00-1.536-.565c-.807.014-1.622.082-2.421.2l-.173.026c-.667.099-1.335.056-1.985-.128l.014-.072-.02.07a1.892 1.892 0 01-1.378-1.816c0-1.541-.238-3.067-.708-4.534l-.28-.878a4.309 4.309 0 01.42-3.55 1.614 1.614 0 00-.737-2.32 5.429 5.429 0 01-1.902-1.386l-1.54-1.754a.643.643 0 01-.129-.618.636.636 0 01.453-.425l1.012-.255c.33-.084.625-.28.829-.554a1.643 1.643 0 011.311-.658h.344c.776 0 1.45-.499 1.677-1.241A1.909 1.909 0 0134.736.967l.942.149a1.45 1.45 0 001.59-.841l.134.058a1.598 1.598 0 01-1.747.928l-.941-.15a1.762 1.762 0 00-1.95 1.22 1.89 1.89 0 01-1.818 1.345h-.343c-.468 0-.914.224-1.194.6a1.64 1.64 0 01-.91.608l-1.013.255a.492.492 0 00-.25.805l1.54 1.753a5.27 5.27 0 001.851 1.35 1.762 1.762 0 01.803 2.529 4.163 4.163 0 00-.406 3.43l.28.877c.475 1.482.716 3.023.716 4.58 0 .776.523 1.465 1.271 1.674l.006.002c.63.178 1.277.22 1.924.124l.173-.026c.805-.119 1.625-.187 2.44-.202a2.408 2.408 0 011.635.602c.312.275.693.46 1.102.531l.13.023-.026.144z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M30.414 26.807c-.285 0-.564-.107-.777-.298l-.67-.605a.683.683 0 01.008-1.018.454.454 0 00.044-.64.5.5 0 01-.067-.561l.003-.006a2.786 2.786 0 011.088-1.134 2.739 2.739 0 001.225-1.477 4.972 4.972 0 00.276-1.68 7.458 7.458 0 00-.51-2.652l-.51-1.308a4.408 4.408 0 01.252-3.73l.16-.288c.173-.312.214-.686.114-1.027-.101-.34-.338-.633-.652-.801l-1.2-.644a5.724 5.724 0 01-1.982-1.753l-.992-1.406a.764.764 0 01.54-1.202l.675-.074a.597.597 0 00.394-.21.65.65 0 01.398-.224l.34-.053c.285-.044.543-.174.747-.378.178-.179.402-.306.648-.367A4.317 4.317 0 0032.812.958l.324-.665.043.021-.323.668A4.367 4.367 0 0129.98 3.32c-.237.059-.453.181-.625.354a1.385 1.385 0 01-.775.392l-.34.052a.6.6 0 00-.368.207.647.647 0 01-.425.228l-.674.074a.716.716 0 00-.507 1.126l.992 1.406a5.669 5.669 0 001.964 1.737l1.2.644c.326.174.572.476.675.83.105.354.062.742-.117 1.064l-.16.288a4.363 4.363 0 00-.25 3.688l.51 1.309c.334.854.506 1.751.514 2.668a5.015 5.015 0 01-.279 1.697 2.787 2.787 0 01-1.247 1.502 2.732 2.732 0 00-1.069 1.115l-.003.005a.451.451 0 00.06.507.503.503 0 01-.048.708.632.632 0 00-.007.946l.67.604a1.114 1.114 0 001.69-.244c.186-.303.215-.68.078-1.008l-.082-.197a1.146 1.146 0 011.136-1.585l.159.01c.388.027.763-.16.976-.486a.44.44 0 01.52-.17.39.39 0 00.199.02l1.397-.222a10.66 10.66 0 011.668-.132c.736 0 1.456.254 2.03.715.282.227.598.403.94.523l.315.11-.016.046-.315-.11a3.228 3.228 0 01-.955-.531 3.199 3.199 0 00-1.998-.704c-.555 0-1.113.044-1.66.131l-1.399.223a.434.434 0 01-.223-.023.39.39 0 00-.462.151 1.128 1.128 0 01-1.02.51l-.16-.011a1.098 1.098 0 00-1.087 1.518l.082.197a1.162 1.162 0 01-.982 1.602 1.261 1.261 0 01-.087.003z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M30.249 24.459a.972.972 0 01-.578-.192l-.093-.069a.646.646 0 01.068-1.086l.572-.322a.69.69 0 01.525-.061.688.688 0 01.486.751l-.02.146a.974.974 0 01-.96.833zm.304-1.708a.636.636 0 00-.31.081l-.573.322a.598.598 0 00-.064 1.005l.094.07a.925.925 0 00.549.181c.455 0 .846-.34.91-.79l.02-.146a.639.639 0 00-.627-.723z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M30.294 23.826a.299.299 0 01-.173-.543l.174-.123a.3.3 0 01.473.291.302.302 0 01-.13.205l-.178.118a.296.296 0 01-.166.052zm.175-.672a.25.25 0 00-.146.046l-.174.124a.25.25 0 00.284.411l.177-.119a.252.252 0 00-.141-.462zM30.432 26.516a.748.748 0 01-.51-.2l-.466-.433a.659.659 0 01.562-1.133l.25.043c.39.067.711.326.86.694a.751.751 0 01-.696 1.03zm-.526-1.726a.613.613 0 00-.61.58.61.61 0 00.194.478l.465.432a.697.697 0 00.681.157.703.703 0 00.447-.932c-.142-.351-.45-.6-.822-.664l-.25-.043a.63.63 0 00-.105-.008z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M30.436 27.11c-.395 0-.777-.146-1.073-.418l-.82-.751a.966.966 0 01-.2-1.166.921.921 0 00.098-.566l-.006-.04a1.628 1.628 0 01.861-1.683l.125-.065a3.32 3.32 0 001.789-2.938c0-.974-.179-1.928-.531-2.836l-.558-1.437a4.457 4.457 0 01.226-3.713l.057-.108a1.132 1.132 0 00-.478-1.54l-1.812-.938a3.2 3.2 0 00-.45-.19 3.209 3.209 0 01-2.053-2.116L25.5 6.23c-.103-.34-.103-.7-.003-1.04.19-.639.788-1.085 1.454-1.085a.593.593 0 00.534-.338.641.641 0 01.639-.363c.498.048 1-.08 1.414-.36l.228-.154c.263-.178.555-.296.868-.35a2.18 2.18 0 001.588-1.198l.544-1.127.044.02-.544 1.129a2.228 2.228 0 01-1.624 1.225 2.156 2.156 0 00-.85.342l-.227.155a2.207 2.207 0 01-1.446.368.593.593 0 00-.59.334.642.642 0 01-.579.366c-.645 0-1.224.432-1.407 1.05-.098.332-.097.682.002 1.013l.113.375a3.159 3.159 0 002.02 2.083c.158.052.311.117.458.193l1.812.938a1.181 1.181 0 01.498 1.606l-.057.108a4.412 4.412 0 00-.223 3.672l.558 1.437a7.86 7.86 0 01.534 2.854 3.362 3.362 0 01-1.815 2.981l-.125.065a1.578 1.578 0 00-.835 1.631l.006.041a.968.968 0 01-.103.596.919.919 0 00.19 1.107l.82.752c.335.308.787.45 1.24.392.448-.058.845-.33 1.06-.728.216-.398.228-.879.032-1.286a.805.805 0 01.725-1.152h.568a.8.8 0 00.655-.342.851.851 0 01.573-.354l.2-.03c.163-.023.328-.05.493-.078l.982-.169c.313-.054.633-.09.95-.108a3.868 3.868 0 012.373.659c.281.19.586.343.907.452l.542.185-.016.047-.541-.185a3.877 3.877 0 01-.919-.459 3.817 3.817 0 00-2.342-.65 8.33 8.33 0 00-.946.107l-.982.17c-.164.028-.33.054-.493.078l-.201.03a.8.8 0 00-.54.333.848.848 0 01-.695.362h-.568a.756.756 0 00-.68 1.082c.202.422.19.92-.033 1.33a1.467 1.467 0 01-1.303.769z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M30.443 27.387c-.51 0-1.001-.194-1.378-.549l-.831-.784a1.056 1.056 0 01-.215-1.242c.088-.173.125-.368.104-.56l-.035-.334a1.687 1.687 0 01.8-1.623l.075-.046a3.788 3.788 0 001.8-2.987 5.435 5.435 0 00-.485-2.604 10.691 10.691 0 01-.801-2.534l-.156-.844a2.482 2.482 0 01.02-1 2.441 2.441 0 00-.936-2.508 2.679 2.679 0 00-1.174-.486l-.464-.07a1.797 1.797 0 01-1.525-1.855l.008-.193a1.612 1.612 0 00-.124-.69 1.65 1.65 0 01-.059-1.122l.106-.346a1.941 1.941 0 011.453-1.334c.283-.06.526-.239.668-.49a1.05 1.05 0 011.151-.512l.074.016c.456.103.929-.029 1.266-.351.23-.22.53-.359.846-.392a1.47 1.47 0 001.18-.845l.407-.887.045.02-.408.888c-.222.484-.69.819-1.22.873a1.394 1.394 0 00-.817.378c-.35.334-.84.47-1.31.364l-.074-.017a1 1 0 00-1.098.488 1.056 1.056 0 01-.7.515 1.892 1.892 0 00-1.418 1.3l-.105.346c-.109.358-.088.744.057 1.089.094.223.139.47.128.712l-.008.192a1.747 1.747 0 001.483 1.804l.464.07c.431.067.845.238 1.196.496.8.586 1.174 1.59.955 2.557a2.43 2.43 0 00-.02.98l.155.845c.16.87.429 1.718.799 2.522.377.819.546 1.727.49 2.627a3.82 3.82 0 01-1.824 3.026l-.074.045a1.644 1.644 0 00-.778 1.577l.035.333c.022.203-.016.406-.108.588-.202.394-.117.88.204 1.184l.832.784c.429.405 1.01.594 1.594.52a1.8 1.8 0 001.317-.87 1.8 1.8 0 00.116-1.573.504.504 0 01.497-.692l.209.012c.393.021.781-.101 1.091-.346.201-.159.44-.27.691-.323l1.65-.344a2.878 2.878 0 012.103.366 6.087 6.087 0 002.262.832l.166.025-.007.049-.167-.026a6.122 6.122 0 01-2.28-.838 2.828 2.828 0 00-2.067-.36l-1.65.345c-.243.05-.475.159-.67.314-.32.252-.719.378-1.125.355l-.209-.012a.456.456 0 00-.447.625 1.848 1.848 0 01-.12 1.617 1.85 1.85 0 01-1.61.91z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M31.938 27.924H31.9l-.208-.006a5.362 5.362 0 01-3.733-1.678 1.484 1.484 0 01-.316-1.529c.068-.185.096-.38.084-.578l-.001-.016a2.72 2.72 0 011.212-2.428c.525-.347.92-.842 1.143-1.43.192-.51.27-1.042.234-1.585l-.01-.158a4.96 4.96 0 00-.745-2.29 4.952 4.952 0 01-.713-1.952l-.254-1.796a1.954 1.954 0 01-.016-.393 1.915 1.915 0 00-.816-1.681l-.03-.02a3.242 3.242 0 00-1.178-.51 2.094 2.094 0 01-1.659-2.047v-.475c0-.36-.058-.715-.174-1.056a3.318 3.318 0 01-.177-1.072v-.189a1.499 1.499 0 011.127-1.457l.674-.175c.33-.086.61-.292.791-.58a1.22 1.22 0 011.27-.552c.379.072.77-.045 1.046-.315l.075-.074c.245-.24.57-.372.913-.372.44 0 .853-.235 1.078-.613l.408-.684.042.025-.408.684a1.312 1.312 0 01-1.12.636c-.33 0-.643.128-.879.359l-.075.073a1.226 1.226 0 01-1.089.328 1.17 1.17 0 00-1.219.531 1.372 1.372 0 01-.82.601l-.675.175a1.45 1.45 0 00-.547.276c-.345.276-.543.69-.543 1.134v.189c0 .36.058.715.174 1.056.118.345.177.706.177 1.071v.475a2.048 2.048 0 001.62 2c.431.092.834.265 1.196.517l.03.02c.557.387.877 1.048.836 1.725-.008.128-.002.256.015.382l.255 1.796A4.91 4.91 0 0029.6 16.2c.436.695.696 1.495.752 2.313l.01.158c.038.55-.042 1.09-.237 1.605a3.006 3.006 0 01-1.162 1.454 2.659 2.659 0 00-1.19 2.385l.001.016c.012.204-.016.405-.086.598-.186.513-.07 1.08.305 1.478a5.314 5.314 0 003.7 1.662l.207.006a1.334 1.334 0 001.3-1.764l-.068-.2a.98.98 0 01.587-1.24.93.93 0 00.298-.18 2.247 2.247 0 011.055-.532l.143-.03a6.284 6.284 0 013.632.34c.232.095.472.176.714.242l1.352.369-.013.047-1.352-.37a6.347 6.347 0 01-.72-.243 6.232 6.232 0 00-3.602-.337l-.143.03c-.385.077-.741.257-1.033.519a.98.98 0 01-.314.19.932.932 0 00-.558 1.179l.068.2a1.383 1.383 0 01-1.309 1.83z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M31.658 28.412a5.104 5.104 0 01-3.847-1.75l-.267-.305a1.683 1.683 0 01-.309-1.695c.06-.16.093-.328.097-.5a3.84 3.84 0 01.892-2.362l.189-.226c.245-.293.462-.612.646-.947.41-.75.575-1.596.478-2.446a4.106 4.106 0 00-.402-1.36 8.457 8.457 0 01-.844-2.967l-.074-.784a2.902 2.902 0 00-.957-1.895 1.675 1.675 0 00-.98-.419 1.81 1.81 0 01-1.432-.907l-.25-.438a3.008 3.008 0 01-.385-1.788c.03-.319.007-.639-.068-.95l-.045-.186a4.769 4.769 0 01-.133-1.119 2.267 2.267 0 011.744-2.2l.18-.043c.355-.084.646-.321.8-.65a1.329 1.329 0 011.435-.747l.27.048c.321.057.648-.03.9-.237a1.25 1.25 0 01.638-.278l.11-.014a1.704 1.704 0 001.292-.9l.13.068c-.28.535-.805.9-1.403.977l-.11.014a1.105 1.105 0 00-.564.245 1.249 1.249 0 01-1.018.269l-.27-.049a1.182 1.182 0 00-1.278.664c-.172.371-.5.638-.899.731l-.18.043a2.116 2.116 0 00-1.631 2.058c0 .365.043.73.13 1.084l.044.186c.08.327.103.664.071.999-.057.594.07 1.183.366 1.701l.25.439c.274.479.766.79 1.316.833.394.031.773.193 1.068.457a3.048 3.048 0 011.004 1.99l.075.784a8.315 8.315 0 00.83 2.914c.22.444.36.918.416 1.41.1.88-.071 1.755-.496 2.532-.188.344-.41.67-.662.97l-.19.227a3.694 3.694 0 00-.857 2.272c-.005.187-.04.371-.105.546-.197.53-.09 1.123.282 1.548l.267.306a4.958 4.958 0 005.052 1.521l.37-.101a.837.837 0 00.595-1l-.101-.436a1.216 1.216 0 01.643-1.366 1.07 1.07 0 00.308-.231c.304-.33.716-.54 1.161-.595a5.528 5.528 0 012.49.272 8.828 8.828 0 001.735.42l.822.111-.02.145-.822-.112a8.977 8.977 0 01-1.763-.426 5.373 5.373 0 00-2.424-.264c-.41.05-.791.244-1.072.548-.1.109-.218.197-.35.263a1.07 1.07 0 00-.565 1.203l.101.436a.98.98 0 01-.699 1.173l-.37.102a5.066 5.066 0 01-1.355.184z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.688 36.583h-.724c-.594 0-1.147-.321-1.442-.837a1.57 1.57 0 01-.084-1.381 1.506 1.506 0 00-.053-1.287 6.823 6.823 0 00-1.58-2.003l-.747-.648a3.854 3.854 0 00-1.474-.796.58.58 0 01-.313-.895.525.525 0 00.08-.166l.243-.865c.052-.186.055-.383.007-.57a1.145 1.145 0 01.127-.873c.158-.265.41-.452.707-.528l.15-.038c.172-.044.342-.097.508-.16a4.884 4.884 0 012.753-.198c.205.044.414.08.622.105l1.52.186-.005.049-1.52-.186a6.848 6.848 0 01-.628-.107 4.834 4.834 0 00-2.724.197 4.97 4.97 0 01-.514.16l-.149.039a1.096 1.096 0 00-.677.505c-.151.253-.195.55-.122.836.05.195.047.401-.008.596l-.243.864a.585.585 0 01-.087.182.53.53 0 00.286.82 3.907 3.907 0 011.493.806l.747.648a6.868 6.868 0 011.591 2.017c.216.413.236.898.055 1.328a1.52 1.52 0 00.081 1.338c.286.5.823.812 1.4.812h.724v.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.906 36.329l-1.1-.118a1.043 1.043 0 01-.905-1.28 3.399 3.399 0 00-.33-2.428 5.216 5.216 0 00-1.079-1.36l-.975-.88a3.67 3.67 0 00-1.466-.805.477.477 0 01-.278-.703.412.412 0 00.037-.077l.298-.835a.861.861 0 00.038-.43.908.908 0 01.82-1.051c.15-.013.3-.059.43-.135a3.04 3.04 0 012.215-.325l2.304.538-.012.047-2.303-.537a2.99 2.99 0 00-2.18.32c-.137.08-.293.128-.45.14a.86.86 0 00-.776.996.908.908 0 01-.04.454l-.298.835a.462.462 0 01-.041.086.427.427 0 00.25.63c.549.153 1.062.435 1.485.817l.975.879c.438.395.804.856 1.088 1.372.415.752.533 1.627.335 2.463a.996.996 0 00.864 1.22l1.1.118-.006.049z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.787 35.957a1.353 1.353 0 01-1.095-1.39 3.06 3.06 0 00-.314-1.508 9.621 9.621 0 00-2.3-2.98l-.768-.67a.695.695 0 00-.135-.092.72.72 0 01-.295-.997l.12-.207a.428.428 0 00.008-.413.48.48 0 01.316-.688l.836-.19c.086-.02.173-.044.257-.072.374-.127.78-.169 1.172-.123l2.4.282-.006.048-2.4-.282a2.655 2.655 0 00-1.151.12 2.742 2.742 0 01-.262.074l-.836.19a.432.432 0 00-.294.24.432.432 0 00.01.378.475.475 0 01-.008.46l-.12.207a.672.672 0 00.275.929c.052.026.1.06.145.098l.769.67a9.67 9.67 0 012.31 2.995 3.1 3.1 0 01.32 1.532 1.304 1.304 0 001.056 1.34l-.01.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.396 35.04l-.143-.66a7.855 7.855 0 00-2.458-4.21l-.704-.625a1.58 1.58 0 01-.517-.98.765.765 0 01.71-.86l.831-.053c.415-.026.836-.04 1.251-.04h1.855v.049h-1.855c-.414 0-.834.014-1.248.04l-.831.053a.716.716 0 00-.664.805c.046.367.224.704.5.95l.704.625a7.895 7.895 0 012.474 4.236l.143.66-.048.01z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.411 33.111l-.23-.554a1.64 1.64 0 00-.458-.622 1.8 1.8 0 01-.466-.605 3.873 3.873 0 00-.815-1.14l-1.102-1.065a.435.435 0 01.357-.746c.756.093 1.524.101 2.282.025l.59-.06.014.146-.59.06a10.4 10.4 0 01-2.314-.026.29.29 0 00-.237.496l1.102 1.066c.352.34.637.739.845 1.182.1.213.248.404.428.555.217.182.39.417.498.678l.231.554-.135.056zM40.684 36.905l-.89-.047a2.04 2.04 0 01-1.564-.877 1.825 1.825 0 01-.229-1.59c.13-.4.106-.83-.069-1.213a4.408 4.408 0 00-1.276-1.623l-1.514-1.193a2.227 2.227 0 00-1.068-.455 2.348 2.348 0 01-.95-.352 3.051 3.051 0 00-1.765-.483l-2.446.09c-.21.007-.416.07-.594.181a1.35 1.35 0 01-1.106.148 4.082 4.082 0 00-1.853-.118l-.608.103c-.269.045-.54.097-.807.153l-1.462.31c-.433.092-.817.36-1.053.734a1.657 1.657 0 00-.245.72l-.142 1.49a.64.64 0 01-1.226.19l-.276-.65a3.643 3.643 0 00-1.387-1.646.657.657 0 00-.61-.054.805.805 0 01-1.088-.54 2.36 2.36 0 01-.062-.344l-.094-.896a.868.868 0 00-.356-.613 1.014 1.014 0 01-.398-1.035l.076-.352a3.323 3.323 0 00-.584-2.684l-.57-.765a1.114 1.114 0 00-1.434-.305 3.409 3.409 0 01-1.342.424l-.396.04a1.39 1.39 0 01-1.415-.825 1.249 1.249 0 00-.609-.625l-.763-.36a5.56 5.56 0 00-1.083-.38 5.67 5.67 0 01-2.119-1 8.116 8.116 0 00-1.828-1.041l-2.425-.99.055-.135 2.426.989c.663.27 1.29.628 1.86 1.06a5.535 5.535 0 002.065.974c.382.091.757.223 1.112.39l.763.36c.304.144.545.392.68.699.219.495.728.792 1.266.738l.397-.04a3.268 3.268 0 001.284-.405 1.264 1.264 0 011.623.345l.57.766a3.47 3.47 0 01.61 2.801l-.076.353a.868.868 0 00.34.885c.235.168.386.43.416.716l.095.896c.01.108.03.217.058.323a.657.657 0 00.89.442.803.803 0 01.746.066 3.79 3.79 0 011.442 1.712l.276.65a.493.493 0 00.944-.145l.143-1.49c.026-.278.12-.55.267-.785.257-.408.675-.7 1.147-.8l1.461-.31c.27-.057.543-.109.814-.154l.608-.103a4.235 4.235 0 011.92.122c.332.1.691.053.986-.131.2-.125.43-.196.666-.204l2.447-.09a3.2 3.2 0 011.849.506c.272.174.572.285.891.33.416.058.809.226 1.138.486l1.514 1.192a4.555 4.555 0 011.32 1.678c.19.415.216.883.074 1.318-.16.49-.082 1.038.21 1.463.329.479.871.782 1.45.813l.89.047-.007.145z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.905 37.363l-.783-.11a3.274 3.274 0 01-2.398-1.618 1.285 1.285 0 01-.036-1.217c.173-.347.173-.76-.001-1.107a5 5 0 00-1.338-1.653l-1.079-.861a2.63 2.63 0 00-1.315-.555 2.67 2.67 0 01-.963-.313 3.624 3.624 0 00-1.832-.45l-2.146.048a.977.977 0 00-.598.223 1.019 1.019 0 01-.956.188 5.549 5.549 0 00-2.74-.143l-2.28.458a.929.929 0 00-.734.798l-.044.376c-.025.22-.047.443-.066.662l-.234 2.861a.463.463 0 01-.825.248l-.833-1.062a2.6 2.6 0 01-.536-1.3 2.57 2.57 0 00-.123-.536l-.052-.15a1.421 1.421 0 00-1.864-.855l-.357.142a.85.85 0 01-1.15-.92c.075-.478 0-.959-.216-1.39l-.052-.104a2.746 2.746 0 01-.153-2.076 2.72 2.72 0 000-1.709 3.75 3.75 0 00-.462-.938l-.511-.752a.599.599 0 00-.84-.153 3.11 3.11 0 01-1.693.565l-.538.017a1.42 1.42 0 01-1.374-.919 1.375 1.375 0 00-.763-.785l-.334-.137a16.46 16.46 0 00-1.47-.522 6.419 6.419 0 01-2.065-1.062 6.38 6.38 0 00-1.668-.924l-1.006-.375-.157-.06-1.25-.477.018-.046 1.25.478.157.06 1.005.374a6.438 6.438 0 011.68.932 6.364 6.364 0 002.05 1.054c.498.15.994.326 1.474.523l.335.137c.363.149.652.446.79.813.207.55.74.906 1.326.887l.538-.017c.6-.02 1.176-.211 1.667-.556a.648.648 0 01.908.166l.511.752c.2.294.358.613.469.95.187.569.187 1.17 0 1.739a2.69 2.69 0 00.15 2.039l.052.103c.22.441.296.932.22 1.42a.799.799 0 001.084.867l.357-.142a1.471 1.471 0 011.927.884l.053.15c.06.177.103.361.125.547.054.466.236.907.525 1.276l.833 1.062a.414.414 0 00.738-.221l.236-2.861c.018-.22.04-.443.066-.664l.043-.377a.968.968 0 01.774-.84l2.279-.458a5.602 5.602 0 012.765.145.968.968 0 00.91-.18c.176-.145.399-.229.628-.233l2.145-.049a3.674 3.674 0 011.857.457c.294.162.612.265.946.307.49.062.953.257 1.34.565l1.078.861a5.04 5.04 0 011.352 1.669c.18.36.181.79 0 1.151-.185.373-.172.81.036 1.17a3.227 3.227 0 002.362 1.595l.783.11-.007.048z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.786 37.734l-1.003-.224a3.771 3.771 0 01-2.458-1.822 1.603 1.603 0 01-.107-1.351c.128-.343.131-.722.008-1.067a2.587 2.587 0 00-.89-1.208l-1.214-.907a1.627 1.627 0 00-.969-.322c-.285 0-.568-.074-.817-.214a5.444 5.444 0 00-2.87-.695l-1.288.047a.99.99 0 00-.584.216c-.257.204-.6.276-.917.192a6.945 6.945 0 00-3.307-.054l-.892.203a1.918 1.918 0 00-1.484 1.862v2.536c0 .328.059.65.175.957a.647.647 0 01-.36.831.652.652 0 01-.649-.088l-.03-.024a7.604 7.604 0 01-2.556-3.64l-.064-.193a1.18 1.18 0 00-1.337-.8l-.677.12a1.224 1.224 0 01-1.442-1.207v-.345c0-.459-.088-.906-.262-1.33a3.545 3.545 0 01-.265-1.35v-.715c0-.216.072-.43.204-.6a.937.937 0 00.133-.903c-.145-.379-.313-.754-.5-1.113l-.062-.119a.732.732 0 00-1.098-.244.791.791 0 01-.467.161l-.714.01c-.33.005-.665.018-.995.039l-.273.017a1.276 1.276 0 01-1.321-.968 1.226 1.226 0 00-.648-.806l-.178-.088a11.387 11.387 0 00-2.367-.859L6 21.612a2.79 2.79 0 01-1.413-.837c-.273-.3-.617-.54-.994-.694L.876 18.97l.018-.046 2.719 1.11c.383.157.733.4 1.012.707.371.408.852.692 1.388.822l.239.057.131.033a11.4 11.4 0 012.246.83l.178.089c.338.167.584.472.674.838.142.578.676.969 1.27.93l.274-.017c.33-.021.665-.034.997-.038l.714-.01a.737.737 0 00.437-.151.782.782 0 011.172.26l.061.118c.188.361.357.738.503 1.119a.987.987 0 01-.14.95.937.937 0 00-.194.57v.714c0 .459.087.906.261 1.331.176.43.266.884.266 1.35v.345a1.175 1.175 0 001.384 1.16l.678-.121a1.237 1.237 0 011.392.832l.063.194a7.55 7.55 0 00.713 1.554 7.544 7.544 0 001.827 2.062l.03.023a.602.602 0 00.934-.686 2.746 2.746 0 01-.178-.975V32.39a1.967 1.967 0 011.522-1.91l.892-.203a6.998 6.998 0 013.33.055 1 1 0 00.875-.183 1.04 1.04 0 01.612-.227l1.287-.048a5.497 5.497 0 012.897.702c.241.135.516.208.793.208.357 0 .711.118.998.331l1.213.908c.419.313.732.738.908 1.23a1.61 1.61 0 01-.009 1.1c-.16.432-.123.91.104 1.31a3.721 3.721 0 002.426 1.799l1.002.224-.01.049z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.904 38.086l-1.356-.222a3.656 3.656 0 01-2.608-1.856 2.195 2.195 0 01-.152-1.732 1.68 1.68 0 00-.735-1.977l-1.205-.718a1.937 1.937 0 00-.801-.262 1.957 1.957 0 01-.735-.22 6.189 6.189 0 00-2.84-.716l-.707-.005h-.01c-.322 0-.64.108-.895.303-.418.319-.982.4-1.473.211a5.362 5.362 0 00-3.061-.238l-.74.16c-.548.117-.989.502-1.18 1.03-.079.216-.11.443-.092.672l.033.433c.09 1.187.357 2.35.796 3.457a.34.34 0 01-.007.262.338.338 0 01-.193.178.284.284 0 00-.048.022l-.527.305a1.751 1.751 0 01-1.92-.108l-.667-.494a3.44 3.44 0 01-1.358-2.227c-.02-.12-.046-.24-.078-.357l-.098-.356a1.559 1.559 0 00-1.32-1.139.897.897 0 00-.435.056.935.935 0 01-.972-.174 2.693 2.693 0 01-.895-2.003v-.014c0-.402-.084-.792-.248-1.158-.17-.38-.257-.8-.251-1.216l.003-.252c.005-.375.044-.752.114-1.12a3.003 3.003 0 00-.1-1.51.639.639 0 00-.835-.394.687.687 0 01-.246.046h-.513c-.497 0-1 .02-1.496.058l-.337.025a1.485 1.485 0 01-1.544-1.086 1.44 1.44 0 00-.724-.894 11.003 11.003 0 00-2.361-.894l-.225-.057a3.31 3.31 0 01-1.51-.848 3.253 3.253 0 00-.995-.668L.974 19.361l.02-.045 2.383 1.026a3.3 3.3 0 011.01.679c.413.405.927.693 1.488.835l.225.056c.82.207 1.619.51 2.371.899.367.19.64.526.749.924.181.662.81 1.103 1.493 1.05l.337-.025a19.75 19.75 0 011.499-.058h.513a.633.633 0 00.23-.042.69.69 0 01.897.423c.164.494.2 1.025.102 1.536-.07.365-.108.739-.113 1.11l-.003.253c-.006.409.08.822.247 1.195.167.373.252.77.252 1.178v.014c0 .75.32 1.466.879 1.967.252.226.606.29.922.165a.948.948 0 01.458-.06c.652.08 1.187.54 1.361 1.174l.098.357c.033.118.06.24.08.362a3.393 3.393 0 001.338 2.195l.667.494a1.698 1.698 0 001.867.105l.527-.304a.326.326 0 01.056-.026.287.287 0 00.171-.377c-.44-1.11-.709-2.279-.8-3.47l-.032-.434c-.018-.236.014-.47.095-.693.197-.543.65-.94 1.216-1.061l.74-.16a5.416 5.416 0 013.09.241c.474.183 1.02.105 1.424-.204.264-.202.592-.313.925-.313h.01l.708.005a6.234 6.234 0 012.862.721c.223.118.464.19.717.214.288.028.572.12.822.27l1.205.717a1.729 1.729 0 01.756 2.035 2.147 2.147 0 00.148 1.693 3.607 3.607 0 002.573 1.831l1.357.222-.01.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.685 38.398l-1.443-.144a3.3 3.3 0 01-2.53-1.641 2.864 2.864 0 01-.235-2.317 1.537 1.537 0 00-.695-1.81l-1.012-.578a.966.966 0 00-.619-.117 1.007 1.007 0 01-.62-.105l-.11-.058a7.03 7.03 0 00-3.443-.808 1.28 1.28 0 00-.926.432c-.424.48-1.13.59-1.678.26a3.937 3.937 0 00-2.92-.468l-.76.174a1.352 1.352 0 00-1.042 1.484c.147 1.201.467 2.373.951 3.482l.026.059a.793.793 0 01-.518 1.083.747.747 0 00-.245.12l-.389.287a2.065 2.065 0 01-2.691-.2c-.116-.116-.235-.232-.355-.344l-.539-.503a3.367 3.367 0 01-1.062-2.2l-.062-.769a.525.525 0 00-.845-.368.616.616 0 01-.675.06l-1.076-.58a2.798 2.798 0 01-.651-.484 1.557 1.557 0 01-.408-1.472c.054-.214.06-.443.015-.66l-.04-.2a13.442 13.442 0 01-.228-3.63l.05-.683a.627.627 0 00-.778-.656 1.7 1.7 0 01-.321.049l-2.048.111a1.923 1.923 0 01-1.894-1.21 1.877 1.877 0 00-.855-.959 8.439 8.439 0 00-2.079-.783l-.373-.086a2.547 2.547 0 01-1.247-.702 2.491 2.491 0 00-.736-.52L1.07 19.78l.02-.045L3.6 20.9c.28.13.533.309.75.531.335.342.757.58 1.223.688l.373.087a8.49 8.49 0 012.091.787c.399.215.71.564.878.984a1.874 1.874 0 001.846 1.18l2.048-.112c.105-.006.21-.022.312-.047a.68.68 0 01.839.706l-.05.684a13.433 13.433 0 00.226 3.616l.04.2c.046.225.04.46-.015.682a1.507 1.507 0 00.394 1.425c.19.19.405.35.64.476l1.075.58c.2.107.444.086.622-.055a.572.572 0 01.925.402l.062.77a3.317 3.317 0 001.046 2.167l.539.503c.12.112.24.228.356.344a2.02 2.02 0 002.628.195l.388-.287a.788.788 0 01.262-.127.743.743 0 00.485-1.017l-.025-.059a12.527 12.527 0 01-.955-3.495 1.4 1.4 0 011.08-1.538l.76-.174a3.986 3.986 0 012.956.472 1.277 1.277 0 001.616-.249 1.33 1.33 0 01.962-.448 7.076 7.076 0 013.467.813l.11.058c.182.096.386.131.59.1.223-.032.454.011.65.123l1.012.578a1.585 1.585 0 01.717 1.868 2.816 2.816 0 00.231 2.277 3.25 3.25 0 002.493 1.616l1.443.145-.005.05z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.679 38.934l-1.342-.165a4.366 4.366 0 01-3.243-2.163 2.676 2.676 0 01-.167-2.31 1.034 1.034 0 00-.476-1.289l-.224-.12c-.301-.16-.624-.266-.96-.316A3.122 3.122 0 0133 32.085l-.485-.322a2.589 2.589 0 00-3.336.407l-.138.151a1.033 1.033 0 01-1.33.164 5.151 5.151 0 00-3.784-.776l-.044.008a.874.874 0 00-.708.957l.004.035c.15 1.272.488 2.512 1.001 3.686a.969.969 0 01-.708 1.345.827.827 0 00-.363.17 4.051 4.051 0 01-2.177.883l-.089.008a.933.933 0 01-.932-.538.778.778 0 00-.201-.267l-1.274-1.097a3.83 3.83 0 01-1.169-1.794 2.1 2.1 0 00-1.048-1.253l-1.495-.761a2.02 2.02 0 01-.671-.554 2.02 2.02 0 01-.408-1.494c.06-.457.04-.918-.056-1.369a9.115 9.115 0 01-.168-2.684l.052-.608a.781.781 0 00-.885-.838 6.018 6.018 0 01-.833.058H10.39c-.81 0-1.543-.511-1.822-1.272a1.79 1.79 0 00-.873-.982 10.711 10.711 0 00-1.745-.699l-.103-.03a9.244 9.244 0 01-2.368-1.1 9.12 9.12 0 00-1.798-.903l-.624-.232.05-.137.625.231c.64.237 1.255.546 1.827.918.722.469 1.506.833 2.33 1.082l.103.031c.607.183 1.203.422 1.769.709.44.223.774.6.944 1.062a1.8 1.8 0 001.684 1.175h1.368c.271 0 .544-.019.813-.056a.928.928 0 011.051.996l-.052.608a8.987 8.987 0 00.165 2.64c.1.468.12.945.058 1.42-.064.49.074.994.378 1.384.166.213.382.39.622.513l1.495.762a2.248 2.248 0 011.122 1.34 3.685 3.685 0 001.124 1.726l1.274 1.097a.925.925 0 01.239.317.786.786 0 00.786.454l.088-.008a3.906 3.906 0 002.099-.852.981.981 0 01.428-.199.823.823 0 00.576-.426.821.821 0 00.026-.716 13.174 13.174 0 01-1.013-3.728l-.004-.034a1.014 1.014 0 01.827-1.12l.044-.007a5.297 5.297 0 013.891.798.885.885 0 001.141-.14l.139-.151a2.736 2.736 0 013.525-.43l.485.322c.36.24.777.4 1.206.463.353.053.692.164 1.007.332l.225.12a1.18 1.18 0 01.543 1.47 2.53 2.53 0 00.158 2.185 4.22 4.22 0 003.134 2.09l1.341.166-.018.144z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.187 39.698a2.077 2.077 0 00-1.356-.701 3.815 3.815 0 01-2.858-1.773l-.191-.303a4.008 4.008 0 01-.618-2.14 1.91 1.91 0 00-1.072-1.724 9.666 9.666 0 01-.89-.5l-.739-.467a2.37 2.37 0 00-3.07.457l-.573.665a.477.477 0 00-.06.088.53.53 0 01-.8.166l-.67-.533a19.92 19.92 0 01-.358-.291l-.13-.11a2.569 2.569 0 00-2.208-.538 1.135 1.135 0 00-.89 1.24c.096.867.32 1.713.666 2.514l.498 1.157a.93.93 0 01-.729 1.285l-.027.003a2.89 2.89 0 00-1.196.446 2.914 2.914 0 01-1.674.479l-.803-.02a1.28 1.28 0 01-1.054-.6 1.256 1.256 0 00-.16-.202l-1.485-1.529a2.278 2.278 0 01-.583-1.063 2.222 2.222 0 00-.954-1.355l-1.665-1.082a2.751 2.751 0 01-1.26-2.32v-.23c0-.437-.044-.876-.132-1.304a6.546 6.546 0 01-.05-2.353l.07-.44a.673.673 0 00-.694-.783l-2.015.081c-.067.002-.134.01-.2.02a1.669 1.669 0 01-1.775-.912l-.054-.109a3.685 3.685 0 00-2.2-1.885l-.318-.1a15.025 15.025 0 01-2.621-1.109 14.927 14.927 0 00-1.879-.853l-.337-.126.017-.046.337.126c.645.24 1.28.529 1.885.856.832.45 1.711.822 2.613 1.105l.318.1a3.736 3.736 0 012.23 1.91l.053.108a1.62 1.62 0 001.725.886c.067-.012.136-.018.205-.021l2.015-.08a.725.725 0 01.744.837l-.07.44a6.494 6.494 0 00.05 2.336c.088.432.133.874.133 1.315v.229a2.705 2.705 0 001.237 2.28l1.665 1.081c.494.32.84.813.976 1.385.092.392.29.751.57 1.04l1.486 1.529c.062.064.118.135.165.21.221.352.6.567 1.014.577l.803.02a2.86 2.86 0 001.646-.47c.364-.24.785-.397 1.217-.454l.027-.004a.88.88 0 00.69-1.217l-.498-1.156a8.856 8.856 0 01-.669-2.529 1.192 1.192 0 01.928-1.293c.8-.175 1.62.025 2.25.55l.13.108c.116.097.236.194.357.29l.671.534a.482.482 0 00.726-.15.538.538 0 01.065-.097l.573-.666a2.421 2.421 0 013.134-.467l.739.468c.285.18.583.348.885.497a1.96 1.96 0 011.1 1.768c0 .75.21 1.48.61 2.114l.19.303a3.769 3.769 0 002.822 1.75c.54.056 1.032.31 1.388.718l-.038.034z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.883 39.698l-.045-.053a19.572 19.572 0 00-1.967-2.014l-.474-.42a1.79 1.79 0 01-.596-1.163 1.738 1.738 0 00-.798-1.297l-1.43-.912a3.834 3.834 0 01-1.763-3.216c0-.362-.027-.726-.081-1.084l-.119-.783a4.435 4.435 0 01.024-1.476.942.942 0 00-.152-.706.943.943 0 00-.948-.384l-1.088.212a2.067 2.067 0 01-2.306-1.25c-.11-.269-.28-.516-.492-.714a5.116 5.116 0 00-1.932-1.13l-.46-.146a7.866 7.866 0 01-1.714-.78 6.54 6.54 0 00-2.463-.891l.007-.049c.884.13 1.72.432 2.482.897a7.805 7.805 0 001.703.776l.46.146c.722.23 1.397.624 1.95 1.141.219.203.393.456.505.732a2.018 2.018 0 002.252 1.22l1.088-.212a.992.992 0 01.997.404c.15.214.207.485.16.742-.09.483-.097.975-.023 1.46l.118.783c.055.36.083.727.083 1.091a3.784 3.784 0 001.74 3.175l1.43.912c.466.297.765.783.82 1.333.045.438.251.84.58 1.131l.475.42a19.534 19.534 0 011.971 2.019l.045.053-.04.033z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.217 39.85a6.883 6.883 0 00-1.185-1.507l-.336-.322a12.83 12.83 0 00-.89-.779 1.44 1.44 0 01-.54-1.038 1.378 1.378 0 00-.586-1.052l-1.255-.882a4.698 4.698 0 01-1.992-3.622c-.022-.455-.07-.914-.144-1.364l-.213-1.304a.781.781 0 01.018-.334.729.729 0 00-.698-.922c-.21 0-.42.02-.626.062l-1.202.24a1.38 1.38 0 01-1.594-.938l-.13-.406a2.9 2.9 0 00-2.038-1.925l-1.033-.266a4.472 4.472 0 01-1.464-.677 4.462 4.462 0 00-2.014-.776l-.315-.04.006-.048.315.04c.73.09 1.434.361 2.036.784.44.31.927.535 1.448.67l1.033.266a2.947 2.947 0 012.072 1.958l.13.405a1.336 1.336 0 001.538.905l1.202-.24a3.23 3.23 0 01.636-.063.78.78 0 01.617.307.777.777 0 01.128.677.73.73 0 00-.017.313l.213 1.304c.074.452.123.913.144 1.37a4.649 4.649 0 001.972 3.584l1.254.882c.36.253.582.65.608 1.09.024.392.214.757.521 1.002.309.246.61.509.894.782l.336.322a6.92 6.92 0 011.193 1.518l-.042.024z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M18.319 39.851l-.391-.62a8.134 8.134 0 00-1.55-1.804 1.462 1.462 0 01-.492-.925 1.418 1.418 0 00-.71-1.06l-.68-.381a4.808 4.808 0 01-1.486-1.298 4.87 4.87 0 01-.981-2.921c0-.558-.053-1.118-.157-1.666l-.234-1.233a.777.777 0 00-.87-.629l-1.027.135a1.976 1.976 0 01-2.085-1.235l-.211-.54a2.667 2.667 0 00-1.925-1.635l-1.052-.224a3.327 3.327 0 01-1.341-.623 3.277 3.277 0 00-2-.685H1.08v-.049h.046c.731 0 1.452.247 2.03.696.385.3.843.512 1.321.614l1.052.223a2.717 2.717 0 011.96 1.665l.211.54A1.925 1.925 0 009.735 27.4l1.028-.133a.829.829 0 01.923.668l.234 1.233c.105.55.158 1.114.158 1.675a4.82 4.82 0 00.971 2.892c.4.528.895.96 1.472 1.284l.68.382c.403.227.677.637.734 1.096.043.347.212.665.476.894a8.187 8.187 0 011.559 1.815l.391.62-.042.026z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M17.487 39.855a3.848 3.848 0 00-1.32-2.08l-.044-.035a1.78 1.78 0 01-.6-.907 1.64 1.64 0 00-.722-.953l-.535-.33a5.377 5.377 0 01-1.495-1.361 5.378 5.378 0 01-1.071-2.955l-.032-.604a5.726 5.726 0 00-.086-.734 2.07 2.07 0 00-2.274-1.68 1.737 1.737 0 01-1.768-.97l-.771-1.599a2.64 2.64 0 00-2.012-1.465l-.804-.112a2.226 2.226 0 01-1.188-.553 2.086 2.086 0 00-1.088-.513l-.53-.08.023-.144.528.079c.435.065.838.255 1.165.55.311.28.696.459 1.11.516l.805.112A2.789 2.789 0 016.9 25.584l.771 1.6a1.589 1.589 0 001.618.888 2.217 2.217 0 012.436 1.798c.045.248.075.501.088.753l.032.604a5.239 5.239 0 002.497 4.2l.536.328c.384.236.663.604.786 1.038.093.33.284.618.55.833l.045.036a3.999 3.999 0 011.37 2.16l-.143.033z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M16.755 39.847l-.264-.653a3.825 3.825 0 00-1.023-1.46 3.889 3.889 0 01-.727-.865l-.032-.052a4.52 4.52 0 00-1.245-1.324 4.581 4.581 0 01-.993-.954 5.059 5.059 0 01-1.052-2.966l-.03-1.164a1.672 1.672 0 00-1.841-1.621 2.583 2.583 0 01-1.203-.167 2.619 2.619 0 01-1.51-1.57l-.282-.806a2.855 2.855 0 00-.623-1.024 2.703 2.703 0 00-1.77-.842 2.702 2.702 0 01-1.415-.529 2.645 2.645 0 00-.626-.346l-.968-.375.017-.046.969.376c.227.088.441.207.637.352.406.302.887.482 1.39.52a2.754 2.754 0 011.802.857c.284.3.497.65.634 1.04l.282.807a2.57 2.57 0 001.481 1.541c.373.147.781.204 1.18.164a1.72 1.72 0 011.895 1.668l.03 1.164a5.006 5.006 0 001.042 2.937c.28.362.61.68.983.944.508.358.932.809 1.259 1.338l.031.051c.197.319.439.606.718.855a3.872 3.872 0 011.036 1.478l.264.653-.046.02z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M16.11 39.688a3.977 3.977 0 00-1.16-1.946l-.072-.067a2.403 2.403 0 01-.547-.748 2.372 2.372 0 00-.648-.83l-.353-.288a4.69 4.69 0 00-.8-.525 3.028 3.028 0 01-1.628-2.416l-.057-.61a19.583 19.583 0 01-.085-1.824v-.34a.777.777 0 00-.869-.77l-.154.018a4.075 4.075 0 01-1.915-.235 2.347 2.347 0 01-1.438-1.59l-.23-.851a3.165 3.165 0 00-.89-1.486 2.142 2.142 0 00-1.47-.583c-.452 0-.886-.136-1.256-.393l-.07-.05c-.435-.302-1-.343-1.473-.106l-.022-.043a1.494 1.494 0 011.522.11l.07.049c.363.252.787.384 1.228.384a2.19 2.19 0 011.505.596c.435.41.748.932.903 1.509l.229.852a2.3 2.3 0 001.41 1.556 4.03 4.03 0 001.89.233l.155-.019a.827.827 0 01.924.82v.34c0 .605.028 1.217.084 1.82l.057.61a2.98 2.98 0 001.602 2.378c.286.148.559.326.809.53l.353.287c.28.228.509.521.661.847.13.278.31.525.536.733l.073.067a4.03 4.03 0 011.173 1.97l-.047.011z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M14.983 39.85l-.043-.024a1.373 1.373 0 00-.284-1.688 2.296 2.296 0 01-.582-.797 2.906 2.906 0 00-1.195-1.34l-.832-.488-.091-.054-.057-.032a2.877 2.877 0 01-1.442-2.423l-.067-2.376a.741.741 0 00-.744-.723h-.114c-.467 0-.931-.068-1.379-.203a3.133 3.133 0 01-2.096-2.09l-.005-.016-.35-1.128a2.27 2.27 0 00-.677-1.037 2.041 2.041 0 00-1.342-.503c-.327 0-.655-.078-.946-.227l-.132-.067a2.133 2.133 0 00-1.441-.176l-.011-.047a2.178 2.178 0 011.474.18l.132.067c.285.144.604.22.924.22.505 0 .993.184 1.374.516.324.283.563.65.69 1.06l.356 1.145a3.084 3.084 0 002.063 2.057c.443.134.902.202 1.365.202h.114a.79.79 0 01.793.77l.066 2.375c.007.233.042.464.105.688.2.718.668 1.32 1.314 1.694l.056.033.092.053.832.488c.542.317.962.788 1.215 1.363.132.3.324.562.569.78a1.42 1.42 0 01.296 1.748z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M14.398 39.85l-.043-.023.082-.165a.977.977 0 00-.351-1.265 1.03 1.03 0 01-.383-.437 4.319 4.319 0 00-1.834-1.975l-.108-.06a3.262 3.262 0 01-1.675-2.845v-1.398c0-.745-.583-1.357-1.326-1.395a1.436 1.436 0 01-.4-.078 4.735 4.735 0 01-2.954-3.04l-.173-.55a1.996 1.996 0 00-.347-.65 1.52 1.52 0 00-1.192-.573c-.257 0-.513-.064-.74-.185l-.035-.019a2.94 2.94 0 00-1.756-.324l-.006-.048a2.992 2.992 0 011.786.33l.035.018c.22.117.468.179.717.179.481 0 .93.215 1.23.591.16.2.279.423.355.667l.174.55a4.688 4.688 0 002.922 3.008c.125.043.256.069.388.075.77.038 1.372.672 1.372 1.443v1.398a3.213 3.213 0 001.65 2.803l.108.06a4.369 4.369 0 011.855 1.997c.08.171.205.315.365.416.447.284.605.855.369 1.329l-.085.165z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M13.957 39.862l-.138-.047.026-.078a1.024 1.024 0 00-.323-1.123 1.172 1.172 0 01-.354-.485 2.824 2.824 0 00-1.36-1.5 3.941 3.941 0 01-2.17-3.534v-1.38a.96.96 0 00-.96-.96c-.14 0-.278-.026-.408-.078l-1.64-.65a2.585 2.585 0 01-1.524-1.68l-.407-1.412a1.57 1.57 0 00-1.23-1.108l-.252-.045a2.008 2.008 0 01-.615-.216 1.858 1.858 0 00-1.071-.222l-.443.042-.014-.146.443-.042c.402-.038.802.045 1.156.24.178.097.37.165.57.2l.252.045a1.716 1.716 0 011.345 1.212l.406 1.412a2.438 2.438 0 001.437 1.584l1.641.65a.954.954 0 00.354.068c.61 0 1.106.496 1.106 1.106v1.38c0 1.446.801 2.75 2.091 3.404a2.968 2.968 0 011.43 1.578c.064.165.171.312.31.424.378.306.527.823.37 1.284l-.027.077z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M13.19 39.76h-.048v-.057a2.2 2.2 0 00-.324-1.148 2.272 2.272 0 01-.176-.356 2.819 2.819 0 00-1.28-1.452 4.254 4.254 0 01-2.223-3.74v-.8c0-.505-.322-.95-.802-1.108l-.022-.007-1.816-.559a2.455 2.455 0 01-1.657-1.744l-.288-1.14a3.35 3.35 0 00-.292-.755.948.948 0 00-.838-.503.998.998 0 01-.552-.166 1.697 1.697 0 00-1.694-.104l-.184.092-.022-.043.184-.092a1.746 1.746 0 011.743.107.948.948 0 00.525.159c.37 0 .707.202.881.528.13.243.23.5.297.767l.288 1.14a2.409 2.409 0 001.623 1.709l1.839.566c.5.164.836.628.836 1.154v.8c0 1.543.842 2.96 2.198 3.697a2.87 2.87 0 011.301 1.477c.047.12.105.238.173.348.216.354.33.76.33 1.174v.056z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M12.78 39.98l-.048-.005.046-.407a.792.792 0 00-.298-.716.848.848 0 01-.32-.604 1.185 1.185 0 00-.71-1.004l-.423-.185a4.128 4.128 0 01-2.483-3.598c-.007-.134.002-.27.026-.403a1.739 1.739 0 00-.965-1.876 2.265 2.265 0 00-.552-.178l-.69-.13a2.075 2.075 0 00-1.469.272 2.067 2.067 0 00-.979 1.531c-.09.766-.257 1.526-.497 2.259l-.152.464a3.724 3.724 0 01-2.274 2.334l-.016-.046a3.674 3.674 0 002.244-2.303l.152-.464c.239-.73.405-1.487.495-2.249a2.116 2.116 0 011.002-1.568c.45-.276.984-.374 1.503-.277l.69.129c.195.036.385.098.564.182a1.788 1.788 0 01.992 1.928c-.023.13-.032.262-.025.393a4.079 4.079 0 002.453 3.555l.423.185c.423.185.706.586.738 1.046a.8.8 0 00.302.569.84.84 0 01.317.76l-.046.406z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M12.226 39.771l-.37-.739a2.172 2.172 0 01-.132-.332 2.145 2.145 0 00-1.12-1.298l-.345-.165a3.705 3.705 0 01-2.11-3.513l.053-1.21a1.082 1.082 0 00-.826-1.093l-.678-.163a1.951 1.951 0 00-2.375 1.537l-.06.316a17.87 17.87 0 01-.56 2.187 4.43 4.43 0 01-2.711 2.787l-.016-.046a4.383 4.383 0 002.681-2.756c.231-.712.42-1.446.558-2.181l.06-.316a2.003 2.003 0 012.435-1.575l.678.162a1.133 1.133 0 01.863 1.144l-.052 1.21a3.657 3.657 0 002.081 3.467l.345.164c.548.263.965.746 1.145 1.328.035.11.079.22.13.325l.37.739-.044.021z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M7.497 39.86l-.025-.043 1.271-.733c.09-.051.18-.104.268-.157l.257-.153c.34-.203.708-.345 1.096-.423a.942.942 0 011.073.618l.031.08.353.78-.044.02-.353-.78a1.05 1.05 0 01-.033-.084.893.893 0 00-1.018-.586 3.405 3.405 0 00-1.08.417l-.257.153-.269.158-1.27.732z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M8.573 39.858l-.03-.04.129-.097a5.6 5.6 0 011.746-.905c.323-.1.668.07.784.387.01.027.02.052.034.077l.253.469-.043.023-.253-.47a.68.68 0 01-.037-.082.585.585 0 00-.724-.357 5.548 5.548 0 00-1.731.896l-.128.099z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M9.367 39.705l-.016-.046.755-.255a.786.786 0 01.873.263l-.038.03a.738.738 0 00-.82-.248l-.754.256zM5.855 39.86l-.02-.044c.453-.21 1.132-.527 1.217-.576.01-.013.054-.025.224-.073a9.615 9.615 0 002.304-.987.456.456 0 00-.049-.808l-.823-.363a1.503 1.503 0 01-.896-1.375v-2.741a1.232 1.232 0 00-.873-1.184l-.313-.097a1.462 1.462 0 00-1.39.288 1.464 1.464 0 00-.509.998 9.013 9.013 0 01-.59 2.559l-.014.036a5.324 5.324 0 01-3.13 3.06l-.017-.045a5.274 5.274 0 003.101-3.033l.015-.036c.319-.815.516-1.671.587-2.544a1.51 1.51 0 01.525-1.031 1.51 1.51 0 011.437-.299l.313.097a1.282 1.282 0 01.908 1.23v2.742a1.455 1.455 0 00.867 1.33l.823.364a.504.504 0 01.054.894c-.72.429-1.5.762-2.316.992-.17.048-.199.058-.204.06v-.002c-.055.04-.284.151-1.231.588z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M5.448 39.82l-.086-.12.694-.5a3.686 3.686 0 011.864-.687.634.634 0 00.197-1.216L8.1 37.29a1.372 1.372 0 01-.838-1.338l.13-2.553a.763.763 0 00-.564-.773 1.211 1.211 0 00-1.399.641c-.08.166-.137.341-.169.522l-.09.5a9.943 9.943 0 01-.613 2.076 4.456 4.456 0 01-2.044 2.224l-1.4.73-.067-.13 1.4-.73a4.325 4.325 0 001.975-2.15 9.804 9.804 0 00.605-2.046l.09-.5a2.17 2.17 0 01.181-.559 1.357 1.357 0 011.568-.72.903.903 0 01.673.923l-.13 2.554a1.233 1.233 0 00.748 1.195l.016.007a.782.782 0 01-.242 1.497 3.546 3.546 0 00-1.79.66l-.693.5z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M4.884 39.857l-.031-.038.212-.172c.338-.275.669-.566.983-.867.294-.28.658-.476 1.054-.565a.411.411 0 00.196-.698.464.464 0 01-.105-.155 4.302 4.302 0 01-.326-1.5l-.08-2.273A.404.404 0 006 33.483l-.236.759c-.126.401-.236.813-.33 1.223a5.247 5.247 0 01-2.243 3.22L1.504 39.78l-.026-.04 1.686-1.097a5.201 5.201 0 002.224-3.19c.093-.41.204-.823.33-1.226l.237-.758a.452.452 0 01.88.118l.08 2.273c.019.512.127 1.01.324 1.484a.41.41 0 00.093.138.461.461 0 01-.22.78 2.182 2.182 0 00-1.03.554c-.314.302-.646.594-.986.87l-.212.171z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M2.657 39.78l-.027-.04 1.588-1.056a3.757 3.757 0 001.542-2.122l.005-.018a.382.382 0 01.752.03c.024.172.016.346-.023.516a2.985 2.985 0 01-.838 1.486l-.116.113c-.078.076-.157.15-.237.224l-.925.866-.034-.036.926-.865c.08-.074.158-.148.235-.224l.117-.112c.412-.399.697-.904.825-1.463.037-.164.044-.332.02-.498a.333.333 0 00-.655-.026l-.005.02a3.807 3.807 0 01-1.562 2.15L2.657 39.78zM.893 37.109l-.014-.047a2.991 2.991 0 001.965-1.85l.077-.214a8.903 8.903 0 00.518-2.63c.025-.585.271-1.13.693-1.536.384-.369.547-.9.437-1.42l-.016-.067-.487-1.887a.887.887 0 00-.684-.646l-.526-.105a.9.9 0 01-.399-.191.844.844 0 00-.885-.125l-.481.212-.02-.045.482-.212a.891.891 0 01.935.132c.109.09.239.153.377.18l.527.106a.938.938 0 01.72.682l.488 1.887.016.068a1.571 1.571 0 01-.45 1.466 2.21 2.21 0 00-.68 1.502 8.937 8.937 0 01-.52 2.645l-.077.214a3.034 3.034 0 01-1.996 1.88z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M.816 36.855L.8 36.809a2.862 2.862 0 001.714-1.553c.193-.435.32-.897.379-1.37l.042-.341c.023-.192.044-.386.062-.578l.118-1.265c.033-.357.193-.69.45-.94.336-.325.495-.794.427-1.256l-.142-.96A1.946 1.946 0 001.668 26.9l-.583.077-.006-.048.583-.077c.299-.04.608-.01.894.085.717.24 1.232.853 1.343 1.602l.142.96c.07.477-.094.963-.441 1.298a1.455 1.455 0 00-.436.91l-.117 1.264c-.019.193-.04.387-.063.58l-.042.341a4.9 4.9 0 01-.383 1.384 2.917 2.917 0 01-1.743 1.579z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M.992 36.132l-.018-.045c.498-.2.905-.573 1.144-1.053.215-.43.337-.893.36-1.374l.112-2.21c.018-.354.194-.675.482-.88.29-.207.464-.543.464-.9v-1.264a.86.86 0 00-.524-.79 2.652 2.652 0 00-2.003-.033l-.193.075-.018-.045.194-.075a2.7 2.7 0 012.04.033.912.912 0 01.553.835v1.265c0 .372-.18.722-.484.938a1.097 1.097 0 00-.462.843l-.11 2.21a3.485 3.485 0 01-.367 1.393c-.245.49-.66.873-1.17 1.077z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M1.015 31.226l-.063-.133.81-.389c.098-.046.194-.093.29-.141l.132-.066a1.596 1.596 0 00.88-1.33l.004-.063a1.07 1.07 0 00-.617-1.04 1.073 1.073 0 00-1.021.057l-.233.143-.077-.124.233-.144a1.218 1.218 0 011.16-.065c.456.214.732.678.7 1.182l-.003.063a1.752 1.752 0 01-.961 1.452l-.132.067-.291.142-.81.389z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M1.164 30.599l-.01-.048.249-.047A1.365 1.365 0 002.5 29.39l.044-.256a.53.53 0 00-.817-.532l-.73.485-.027-.04.73-.486a.579.579 0 01.892.582l-.044.256a1.423 1.423 0 01-1.136 1.154l-.248.046z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M1.172 30.351l-.026-.041c.335-.212.597-.532.738-.903l.024-.064a.16.16 0 00-.258-.172l-.65.611-.034-.036.65-.611a.208.208 0 01.338.225l-.025.065c-.144.38-.413.709-.757.926zM1.215 35.825l-.111-.096c.118-.136.695-.806.803-.901.029-.061.072-.398.104-1.009l.008-.147.086-1.443a.665.665 0 00-.928-.65l-.34.146-.058-.135.34-.146a.81.81 0 011.132.794l-.085 1.443-.009.146c-.053 1.037-.118 1.085-.153 1.11-.056.044-.514.568-.79.888z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M.903 34.779l-.035-.034a3.2 3.2 0 00.798-1.498l.108-.479a.587.587 0 00-.642-.713l-.146.018-.006-.049.146-.017a.635.635 0 01.695.772l-.107.48a3.242 3.242 0 01-.81 1.52zM38.253 39.86a6.541 6.541 0 01-2.805-2.394l-.494-.755a3.025 3.025 0 01-.468-1.288 2.967 2.967 0 00-1.487-2.226l-.472-.266a2.963 2.963 0 00-1.45-.38c-.522 0-1.025.221-1.378.606a1.912 1.912 0 01-2.674.152l-.648-.562a1.803 1.803 0 00-1.18-.44 1.07 1.07 0 00-1.053 1.245c.131.778.371 1.533.715 2.243l.235.487c.297.614.565 1.252.796 1.894l.135.375a.492.492 0 01-.14.54.493.493 0 01-.55.07l-.167-.085a2.028 2.028 0 00-1.948.063l-1.086.642-.025-.042 1.086-.642a2.083 2.083 0 011.995-.065l.167.085a.444.444 0 00.496-.063.444.444 0 00.126-.486l-.135-.376c-.23-.64-.498-1.276-.794-1.889l-.235-.487a8.375 8.375 0 01-.72-2.257 1.119 1.119 0 011.103-1.301c.445 0 .875.16 1.21.452l.649.561a1.864 1.864 0 002.606-.148 1.927 1.927 0 011.414-.62c.515 0 1.025.133 1.474.385l.472.266a3.018 3.018 0 011.511 2.263c.054.45.214.888.462 1.267l.493.755a6.495 6.495 0 002.785 2.377l-.02.044z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M36.665 39.858a3.865 3.865 0 01-1.305-1.411l-.878-1.63a3.005 3.005 0 01-.34-1.075 2.971 2.971 0 00-1.522-2.254l-.366-.2a1.89 1.89 0 00-2.445.56l-.296.414a.713.713 0 00-.11.234.767.767 0 01-.928.548 2.616 2.616 0 01-1.288-.772l-.629-.686a.858.858 0 00-1.138-.12.864.864 0 00-.356.61c-.02.191.01.386.088.562l.668 1.51c.117.266.23.537.336.807l.236.605a1.992 1.992 0 01-.623 2.297l-.03-.038a1.943 1.943 0 00.607-2.241l-.235-.605a19.65 19.65 0 00-.335-.804l-.669-1.511a1.15 1.15 0 01-.091-.586.914.914 0 011.107-.792.903.903 0 01.471.273l.629.687c.34.371.777.633 1.264.757.38.097.77-.133.868-.512a.76.76 0 01.118-.25l.296-.416a1.938 1.938 0 012.509-.574l.366.2a3.022 3.022 0 011.547 2.291c.044.372.156.728.334 1.058l.878 1.63c.304.564.75 1.046 1.288 1.394l-.026.04z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M35.734 39.854a8.517 8.517 0 01-.837-1.2l-.997-1.732a2.033 2.033 0 01-.27-1.013c0-.725-.396-1.392-1.033-1.74l-.706-.385a1.278 1.278 0 00-.73-.152c-.335.03-.641.187-.86.442l-.345.402a.878.878 0 00-.194.39.933.933 0 01-1.095.719l-.435-.089a4.077 4.077 0 01-1.57-.685.43.43 0 00-.662.481l.098.306c.236.74.53 1.466.875 2.16a1.995 1.995 0 01-.191 2.094l-.04-.03a1.946 1.946 0 00.188-2.043 15.46 15.46 0 01-.878-2.166l-.098-.306a.479.479 0 01.736-.536c.468.334.99.562 1.553.676l.435.089a.884.884 0 001.038-.68.932.932 0 01.205-.413l.345-.402a1.329 1.329 0 011.65-.302l.706.386a2.03 2.03 0 011.057 1.782c0 .347.092.688.264.988l.996 1.734c.242.42.522.821.833 1.193l-.038.032z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M27.867 40l-.14-.045c.226-.7.167-1.448-.167-2.105a15.625 15.625 0 01-.616-1.372l-.154-.392a.356.356 0 01.094-.394.355.355 0 01.401-.049c.017.01.036.016.055.02l1.352.28c.67.14 1.345-.243 1.57-.89a1.32 1.32 0 01.548-.684 1.31 1.31 0 011.379-.007l.017.01a2.326 2.326 0 011.108 1.81c.025.328.125.65.29.934l1.52 2.607-.126.074-1.52-2.607a2.329 2.329 0 01-.31-.997 2.179 2.179 0 00-1.038-1.696l-.017-.01a1.165 1.165 0 00-1.226.005c-.226.141-.399.357-.487.61a1.518 1.518 0 01-1.738.984l-1.352-.28a.362.362 0 01-.094-.034.208.208 0 00-.29.259l.154.393c.18.46.386.918.61 1.359.352.692.415 1.479.177 2.217z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M28.788 39.844l-.047-.012.025-.099a2.382 2.382 0 00-.185-1.667.869.869 0 01.083-.915.868.868 0 01.86-.322c.401.083.803-.146.936-.533l.285-.83a.89.89 0 011.27-.489c.497.275.806.799.806 1.367 0 .315.08.627.233.903l1.338 2.423-.043.023-1.338-2.423a1.923 1.923 0 01-.239-.927c0-.55-.3-1.058-.781-1.324a.84.84 0 00-1.2.462l-.285.83a.865.865 0 01-.991.565.818.818 0 00-.813.304.818.818 0 00-.078.863c.267.526.334 1.13.189 1.701l-.025.1z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M29.803 39.84l-.03-.507a1.507 1.507 0 00-.239-.727.699.699 0 01-.018-.732.698.698 0 01.643-.349.654.654 0 00.658-.459l.274-.886a.577.577 0 01.553-.409c.289 0 .53.207.574.492.125.812.388 1.59.779 2.312l.636 1.174-.043.023-.636-1.173a7.156 7.156 0 01-.785-2.328.528.528 0 00-.524-.45.528.528 0 00-.508.374l-.273.886a.7.7 0 01-.707.494.652.652 0 00-.582 1.006c.145.224.23.483.247.75l.03.506-.049.002z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M32.075 39.985l-.047-.015.034-.104a2.6 2.6 0 00-.14-1.948.408.408 0 00-.398-.229.408.408 0 00-.36.283.46.46 0 01-.195.248.794.794 0 00-.366.806l.133.808-.049.008-.132-.808a.843.843 0 01.388-.855.409.409 0 00.174-.222.457.457 0 01.848-.06c.304.62.354 1.325.143 1.983l-.033.105z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M31.374 39.748a.275.275 0 01-.268-.23l-.057-.364a.274.274 0 01.272-.317c.137 0 .254.103.272.239l.05.364a.27.27 0 01-.27.308zm-.053-.862a.227.227 0 00-.223.26l.056.364a.224.224 0 00.256.187.222.222 0 00.185-.25l-.05-.364a.228.228 0 00-.224-.197zM20.103 31.413a.642.642 0 01-.465-.2.6.6 0 00-.072-.064l-.774-.587a1.577 1.577 0 00-1.038-.316.842.842 0 01-.892-.844v-.82a.784.784 0 00-.372-.665.83.83 0 01-.377-.882 3.484 3.484 0 00-.207-2.128 4.31 4.31 0 00-.63-1.032l-.213-.259a2.513 2.513 0 00-2.328-.881 1.006 1.006 0 00-.521.251c-.211.192-.495.292-.78.274a1.67 1.67 0 01-1.238-.673 2.847 2.847 0 00-1.11-.896l-.95-.431A3.669 3.669 0 007.333 21a3.682 3.682 0 01-1.439-.62l-.534-.383a15.048 15.048 0 00-2.79-1.572l-1.693-.728.02-.045 1.692.728a15.107 15.107 0 012.8 1.577l.533.381c.428.305.906.512 1.42.613a3.7 3.7 0 01.816.262l.95.43c.446.203.837.519 1.129.913.284.385.722.623 1.2.654.273.017.543-.078.744-.262.153-.14.343-.23.547-.264.89-.141 1.8.203 2.373.899l.213.259c.26.316.475.667.637 1.044.295.683.367 1.43.21 2.157a.781.781 0 00.355.83c.244.15.395.42.395.707v.82a.798.798 0 00.841.796c.384-.021.764.094 1.07.326l.775.587a.665.665 0 01.077.07.592.592 0 001.012-.288.786.786 0 01.119-.28 2.26 2.26 0 011.332-.93l2.792-.693a5.09 5.09 0 012.529.022.731.731 0 00.763-1.162l-.894-1.128a2.789 2.789 0 01-.563-2.195c.01-.063.019-.127.025-.19a5.61 5.61 0 011.137-2.875 7 7 0 00.555-.84l.335-.598a2.853 2.853 0 00-.108-2.974l-.517-.782a4.023 4.023 0 01-.635-1.734 3.676 3.676 0 00-1.561-2.592 3.751 3.751 0 01-.381-.301l-.983-.888a4.213 4.213 0 01-1.388-3.4 4.22 4.22 0 00-.045-.917l-.052-.326a2.346 2.346 0 01.757-2.122l.258-.23c.38-.336.811-.602 1.283-.788a2.079 2.079 0 001.01-.854c.35-.581 1.03-.868 1.692-.715.399.093.825.018 1.169-.206.186-.122.39-.205.61-.248L30 .931a1.04 1.04 0 00.73-.56l.045.02a1.089 1.089 0 01-.765.588l-.077.015a1.663 1.663 0 00-.592.24 1.57 1.57 0 01-1.207.214 1.51 1.51 0 00-1.639.693 2.127 2.127 0 01-1.034.874 4.255 4.255 0 00-1.268.78l-.259.23a2.295 2.295 0 00-.741 2.078l.052.325c.05.306.065.618.046.928a4.164 4.164 0 001.372 3.36l.983.888c.118.107.244.207.375.297a3.725 3.725 0 011.583 2.627c.073.609.29 1.2.627 1.712l.517.782a2.9 2.9 0 01.11 3.024l-.335.598a7.105 7.105 0 01-.559.847 5.562 5.562 0 00-1.127 2.85 2.88 2.88 0 01-.025.193c-.13.764.072 1.55.553 2.157l.894 1.128a.778.778 0 01-.037 1.013.78.78 0 01-.777.227 5.046 5.046 0 00-2.505-.022l-2.793.692a2.214 2.214 0 00-1.303.91.733.733 0 00-.11.263.641.641 0 01-.63.51z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.882 30.788a.54.54 0 01-.364-.142l-.66-.6a1.088 1.088 0 00-.531-.264c-.537-.101-.926-.57-.926-1.115v-.042c0-.304-.113-.594-.318-.818a1.19 1.19 0 01-.273-1.12 1.15 1.15 0 00-.058-.762 12.46 12.46 0 00-1.433-2.443l-.09-.12a2.54 2.54 0 00-2.233-1.01 1.6 1.6 0 00-1.005.458.84.84 0 01-1.278-.115 4.292 4.292 0 00-1.583-1.37l-.472-.237a4.284 4.284 0 00-1.006-.358 4.318 4.318 0 01-1.552-.68 8.278 8.278 0 01-1.086-.908l-.322-.32a1.648 1.648 0 00-1.056-.475 1.714 1.714 0 01-.726-.216l-1.841-1.04.024-.043 1.84 1.04c.216.122.46.195.706.21.41.027.796.2 1.087.49l.323.32c.332.33.696.633 1.08.901.464.325.98.551 1.533.673.353.078.695.2 1.018.363l.472.237c.638.321 1.191.8 1.6 1.385a.791.791 0 001.204.109 1.65 1.65 0 011.037-.473 2.588 2.588 0 012.274 1.03l.09.12c.571.76 1.055 1.584 1.44 2.452.11.25.132.532.06.796a1.14 1.14 0 00.262 1.074c.214.232.331.535.331.85v.042c0 .522.373.97.886 1.067.207.038.399.134.555.275l.66.6a.492.492 0 00.74-.089l.124-.183a3.346 3.346 0 012.728-1.482l.385-.006a4.965 4.965 0 001.401-.224c.772-.24 1.6-.29 2.395-.144l.03.006a.368.368 0 00.329-.621l-1.094-1.107a1.97 1.97 0 01-.567-1.446c.041-1.25.4-2.482 1.036-3.56l.243-.41.553-.927a3.002 3.002 0 00.018-3.036l-.773-1.333-.108-.184-.175-.295a1.65 1.65 0 00-1.223-.791 1.632 1.632 0 00-.965.186 4.309 4.309 0 01-3.372.303l-.692-.227a1.631 1.631 0 01-.335-2.94l1.286-.777a2.086 2.086 0 001.012-1.71l.072-1.768a2.528 2.528 0 00-.183-1.055 2.598 2.598 0 01.975-3.133c.422-.279.873-.521 1.339-.72l.52-.222c.42-.178.767-.5.977-.905a1.851 1.851 0 011.978-.96c.215.042.434.043.65.005.346-.061.67-.19.967-.38l.296-.191.026.04-.296.192a2.666 2.666 0 01-.985.387c-.222.04-.446.038-.667-.004a1.801 1.801 0 00-1.926.934c-.215.415-.57.744-1 .927l-.521.222a8.4 8.4 0 00-1.331.716 2.549 2.549 0 00-.958 3.074c.139.343.202.705.187 1.075l-.071 1.767a2.139 2.139 0 01-1.035 1.75l-1.288.777c-.38.23-.648.613-.734 1.05a1.582 1.582 0 001.059 1.802l.692.227c1.1.36 2.315.25 3.334-.3.305-.164.649-.23.993-.191.521.06.992.363 1.26.814l.175.296c.037.06.072.122.108.184l.773 1.333a3.048 3.048 0 01-.02 3.085l-.794 1.338a7.449 7.449 0 00-1.03 3.536 1.92 1.92 0 00.552 1.41l1.095 1.107a.416.416 0 01-.372.703l-.031-.006a4.98 4.98 0 00-2.372.144c-.458.143-.934.219-1.415.226l-.385.006a3.296 3.296 0 00-2.688 1.46l-.123.183a.532.532 0 01-.448.24z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M22.696 15.219c-.285 0-.566-.048-.836-.141l-.99-.344c-.27-.094-.501-.28-.65-.523a1.232 1.232 0 01.382-1.686l1.098-.713c.433-.28.932-.462 1.444-.526.434-.054.885.065 1.237.324.488.362.751.961.688 1.565a2.238 2.238 0 01-1.199 1.757 2.555 2.555 0 01-1.174.287zm.66-3.897c-.069 0-.138.004-.207.012a3.41 3.41 0 00-1.422.518l-1.099.713a1.183 1.183 0 00-.367 1.62c.144.234.365.413.624.503l.991.343a2.492 2.492 0 001.971-.143 2.19 2.19 0 001.172-1.718 1.68 1.68 0 00-.668-1.52 1.683 1.683 0 00-.995-.329z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M22.084 14.64c-.26 0-.516-.045-.76-.134a.931.931 0 01-.195-1.654l.78-.516c.236-.156.494-.267.769-.332a1.133 1.133 0 011.087 1.871l-.052.056c-.42.451-1.013.71-1.629.71zm.853-2.617c-.083 0-.167.01-.249.029a2.303 2.303 0 00-.752.325l-.78.516a.883.883 0 00.184 1.567 2.182 2.182 0 002.337-.562l.052-.056c.256-.275.35-.657.252-1.02a1.085 1.085 0 00-1.044-.8z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M22.122 14.28a.91.91 0 01-.407-.096.664.664 0 01-.057-1.15l.342-.216a.697.697 0 01.895 1.051l-.09.103a.911.911 0 01-.683.308zm.249-1.52a.648.648 0 00-.345.1l-.342.215a.61.61 0 00.052 1.065.865.865 0 001.032-.201l.09-.103a.651.651 0 00.06-.778.646.646 0 00-.547-.298z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.849 29.92a.754.754 0 01-.578-.27.71.71 0 00-.296-.21l-.195-.072a1.11 1.11 0 01-.718-1.108 1.06 1.06 0 00-.278-.785 1.335 1.335 0 01-.355-.908c0-.256-.061-.512-.176-.741l-.122-.242a13.515 13.515 0 00-1.448-2.275 3.416 3.416 0 00-2.7-1.31c-.398 0-.787.138-1.096.39a.662.662 0 01-.96-.13 3.634 3.634 0 00-1.401-1.18l-1.858-.886a1.656 1.656 0 00-.52-.15 1.706 1.706 0 01-.953-.435l-1.339-1.22a2.045 2.045 0 00-1.02-.502 2.097 2.097 0 01-.914-.405 8.864 8.864 0 00-1.463-.916l-.388-.193.022-.044.388.193a8.859 8.859 0 011.47.921c.261.202.57.338.894.395.39.07.752.247 1.045.515l1.339 1.22c.258.235.578.382.925.423.186.022.366.074.536.154l1.858.886c.566.27 1.056.683 1.42 1.195a.614.614 0 00.89.122c.317-.26.717-.402 1.127-.402 1.075 0 2.073.485 2.738 1.33.558.709 1.047 1.476 1.452 2.282l.122.242c.12.236.182.5.182.764 0 .325.122.636.342.875.204.22.31.52.29.82-.03.463.253.899.687 1.06l.196.072a.752.752 0 01.316.223c.14.168.352.262.57.252a.706.706 0 00.546-.301.882.882 0 01.302-.272l.688-.377a3.834 3.834 0 012.06-.466c.456.026.908-.03 1.344-.166l1.267-.397.03-.01a.499.499 0 00.198-.79l-.06-.07a3.305 3.305 0 01-.803-2.298 5.146 5.146 0 01.682-2.357l.518-.9c.59-1.021.776-2.22.527-3.372a3.26 3.26 0 00-.722-1.443.822.822 0 00-.869-.245.873.873 0 01-.906-.243l-.022-.024a.673.673 0 00-.494-.22h-.003a.673.673 0 00-.493.216.719.719 0 01-.483.23l-.436.027a4.123 4.123 0 01-1.997-.378 4.124 4.124 0 01-1.54-1.246l-.922-1.219a1.091 1.091 0 01.38-1.635l.882-.445a3.652 3.652 0 001.695-4.746l-.96-2.163a.738.738 0 01.201-.863.736.736 0 01.583-.162c.812.126 1.63 0 2.368-.362A6.612 6.612 0 0026.13.742l.283-.453.041.026-.283.453a6.66 6.66 0 01-2.707 2.448 4.004 4.004 0 01-2.398.367.686.686 0 00-.732.957l.96 2.163a3.701 3.701 0 01-1.717 4.809l-.883.445a1.04 1.04 0 00-.565.803c-.034.271.038.54.203.759l.921 1.219a4.075 4.075 0 003.496 1.604l.436-.028a.67.67 0 00.45-.214.723.723 0 01.53-.23h.003a.724.724 0 01.53.235l.022.024a.824.824 0 00.855.23.87.87 0 01.921.26c.363.417.616.924.733 1.464a4.783 4.783 0 01-.532 3.406l-.519.9a5.094 5.094 0 00-.674 2.335 3.259 3.259 0 00.79 2.264l.06.07a.545.545 0 01-.251.878l-1.267.396c-.441.139-.9.195-1.362.17a3.791 3.791 0 00-2.034.46l-.687.376a.84.84 0 00-.286.257.754.754 0 01-.617.325z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.86 29.152h-.012a.582.582 0 01-.422-.194.654.654 0 00-.156-.128 1.485 1.485 0 01-.731-1.184 2.282 2.282 0 00-.247-.893 18.071 18.071 0 00-1.569-2.53l-.842-1.135a3.609 3.609 0 00-2.64-1.442l-.056-.005a3.427 3.427 0 00-1.337.175.728.728 0 01-.852-.31.675.675 0 00-.248-.24l-.747-.417c-.25-.14-.505-.276-.76-.403l-1.016-.511a2.029 2.029 0 00-.65-.2 2.091 2.091 0 01-1.179-.57L5.291 18.09a1.967 1.967 0 00-1.021-.527 2.027 2.027 0 01-.957-.458 16.364 16.364 0 00-1.658-1.255l-.509-.336.027-.04.508.335c.579.383 1.138.806 1.663 1.26.266.229.589.383.934.446.397.072.758.26 1.047.54L6.43 19.13c.312.303.721.501 1.153.558.232.03.455.099.664.204l1.017.51c.255.129.511.265.761.405l.748.418a.72.72 0 01.265.256.68.68 0 00.794.29 3.467 3.467 0 011.357-.177l.055.003a3.661 3.661 0 012.676 1.462l.842 1.136a18.053 18.053 0 011.574 2.536c.146.285.23.592.252.912.031.476.295.904.707 1.145.063.037.12.084.168.138a.534.534 0 00.78.016.575.575 0 01.123-.096l.223-.131a5.456 5.456 0 013.055-.743c.261.013.517-.026.761-.116.344-.128.606-.401.72-.75a1.19 1.19 0 00-.137-1.029 1.254 1.254 0 01-.203-.75l.03-.554c.053-.992.34-1.973.828-2.838A6.38 6.38 0 0026.4 17.9a.923.923 0 00-.99-.785l-.112.01a.97.97 0 01-.77-.282.653.653 0 00-.805-.095.702.702 0 01-.34.103l-.142.006a5.527 5.527 0 01-3.154-.83 5.52 5.52 0 01-1.616-1.527l-.232-.331a9.43 9.43 0 00-1.222-1.418 9.54 9.54 0 01-2.298-3.422l-.16-.41a.587.587 0 01.455-.788c.2-.03.404.047.534.2l.683.812c.43.51.917.97 1.45 1.371a2.052 2.052 0 001.97.268 2.052 2.052 0 001.294-1.908 5.362 5.362 0 00-.508-2.242l-.643-1.364a2.39 2.39 0 01-.195-1.423 1.286 1.286 0 011.552-1.033l.158.037a3.68 3.68 0 004.043-1.78l.437-.778.042.024-.437.777a3.726 3.726 0 01-4.097 1.804l-.158-.036a1.237 1.237 0 00-1.492.993c-.08.476-.015.957.19 1.394l.644 1.364a5.42 5.42 0 01.512 2.262 2.1 2.1 0 01-1.324 1.954 2.102 2.102 0 01-2.018-.274 8.905 8.905 0 01-1.458-1.379l-.683-.81a.539.539 0 00-.488-.185.532.532 0 00-.417.722l.16.41a9.493 9.493 0 002.285 3.404c.455.433.868.913 1.229 1.426l.232.331a5.46 5.46 0 001.602 1.514c.94.584 2.02.868 3.126.822l.142-.005a.659.659 0 00.316-.097.701.701 0 01.866.102c.193.193.46.29.731.267l.112-.01a.971.971 0 011.043.828 6.43 6.43 0 01-.763 4.065 6.453 6.453 0 00-.822 2.816l-.03.554c-.014.253.056.51.195.721.21.319.262.71.143 1.072a1.238 1.238 0 01-.75.78c-.25.093-.513.133-.78.119a5.412 5.412 0 00-3.028.736l-.223.13a.549.549 0 00-.113.089.588.588 0 01-.419.176z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M17.154 12.079a.578.578 0 01-.448-.211l-.834-1.01a.45.45 0 01.345-.733.45.45 0 01.327.142c.019.02.039.04.06.056l.91.72a.579.579 0 01-.36 1.036zm-.937-1.905a.4.4 0 00-.307.653l.834 1.01a.53.53 0 00.876-.083.53.53 0 00-.136-.674l-.909-.72a.593.593 0 01-.066-.06.407.407 0 00-.292-.127z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M20.12 28.334a1.094 1.094 0 01-1.083-.916 2.786 2.786 0 00-.315-.9 17.977 17.977 0 00-1.823-2.67l-.838-1.015a4.32 4.32 0 00-2.9-1.557c-.2-.02-.399-.003-.592.053a1.692 1.692 0 01-1.4-.21 1.584 1.584 0 00-.16-.092l-2.756-1.38a1.649 1.649 0 00-.554-.165 1.795 1.795 0 01-1.112-.559l-.646-.691a3.778 3.778 0 00-1.364-.929 3.87 3.87 0 01-1.327-.87 5.514 5.514 0 00-1.03-.81l-1.177-.715.077-.125 1.175.715c.385.234.74.513 1.059.832.365.366.795.647 1.276.837.535.211 1.025.544 1.418.965l.646.691c.268.287.632.47 1.022.513.21.024.413.084.603.18l2.756 1.38c.06.03.118.063.174.1.378.248.845.318 1.28.192.21-.061.429-.08.648-.058a4.466 4.466 0 012.997 1.61l.838 1.015c.69.837 1.309 1.743 1.838 2.691.165.295.276.614.332.947a.955.955 0 001.444.65 4.02 4.02 0 012.494-.594l.582.053a.845.845 0 00.885-1.11 4.313 4.313 0 01-.208-1.625 7.986 7.986 0 011.04-3.459l.02-.034c.483-.841.65-1.83.47-2.783a.66.66 0 00-.584-.531.812.812 0 01-.374-.134l-.535-.361a.908.908 0 00-.82-.099c-.117.044-.24.066-.365.066h-.099a6.26 6.26 0 01-5.153-2.706l-.142-.205a7.865 7.865 0 00-1.239-1.403 8.006 8.006 0 01-2.334-3.654l-.126-.414a1.118 1.118 0 011.8-1.17l.597.517c.487.422.96.873 1.402 1.34l.15.158a1.058 1.058 0 001.795-.479c.196-.81.16-1.655-.105-2.445l-.497-1.489a3.852 3.852 0 01-.047-2.307 1.45 1.45 0 011.792-.99l.614.176a2.7 2.7 0 002.045-.225A2.71 2.71 0 0024.799 1l.338-.653.13.067-.338.653a2.85 2.85 0 01-1.175 1.198c-.664.36-1.43.445-2.155.236l-.614-.175a1.305 1.305 0 00-1.611.89 3.708 3.708 0 00.045 2.22l.498 1.488c.273.816.31 1.69.108 2.526a1.205 1.205 0 01-2.043.545l-.15-.158c-.44-.464-.908-.912-1.391-1.33l-.597-.517a.968.968 0 00-1.459.22.971.971 0 00-.106.797l.126.414a7.866 7.866 0 002.292 3.587c.476.424.9.905 1.262 1.43l.142.205a6.115 6.115 0 005.033 2.642h.099a.905.905 0 00.313-.057c.317-.117.673-.074.953.114l.535.362c.09.061.197.099.306.109.354.033.647.3.713.65.187.987.014 2.01-.486 2.883l-.02.034a7.848 7.848 0 00-1.021 3.395 4.156 4.156 0 00.201 1.57.991.991 0 01-1.038 1.302l-.582-.054a3.874 3.874 0 00-2.402.573 1.095 1.095 0 01-.585.168z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M20.28 27.6a.856.856 0 01-.78-.498 14.211 14.211 0 00-1.003-1.803l-.208-.316a19.545 19.545 0 00-1.653-2.17l-.114-.13a5.817 5.817 0 00-3.708-1.943 1.68 1.68 0 00-.446.008 1.726 1.726 0 01-1.215-.269 6.441 6.441 0 00-.807-.456l-1.957-.926a1.302 1.302 0 00-.555-.124c-.362 0-.713-.15-.965-.408l-.57-.587a5.133 5.133 0 00-1.588-1.113 5.217 5.217 0 01-1.257-.797l-.018-.016c-.414-.355-.82-.733-1.203-1.123l-.965-.98.035-.035.965.98c.382.39.786.767 1.2 1.121l.018.015c.375.323.794.588 1.245.79.604.271 1.143.65 1.604 1.124l.57.587c.242.25.581.393.93.393.197 0 .395.045.574.13l1.957.926c.28.133.555.287.814.46.348.23.768.323 1.181.26.152-.023.306-.026.458-.008a5.867 5.867 0 013.74 1.96l.113.13a19.61 19.61 0 011.658 2.175l.207.316c.378.576.717 1.185 1.007 1.81a.813.813 0 001.165.347l.36-.225a2.526 2.526 0 012.375-.172c.154.069.328.065.48-.012a.556.556 0 00.278-.67 5.098 5.098 0 01-.246-1.745c.039-1.15.361-2.287.933-3.286l.39-.683a1.917 1.917 0 00-.848-2.687 2.272 2.272 0 00-1.105-.212 5.95 5.95 0 01-3.267-.743l-.301-.168a7.28 7.28 0 01-2.385-2.142 7.203 7.203 0 00-.96-1.1l-.01-.01a9.077 9.077 0 01-2.573-4.29 1.806 1.806 0 01.152-1.322 1.804 1.804 0 011.947-.927c.515.1 1 .334 1.4.674l1.05.892a.43.43 0 00.7-.413l-.58-2.897a3.777 3.777 0 01.091-1.84 2.287 2.287 0 012.376-1.622c.201.016.4.057.59.125l.156.054A2.248 2.248 0 0024.465.898l.34-.682.044.022-.34.68a2.297 2.297 0 01-2.813 1.136l-.156-.055a2.243 2.243 0 00-.577-.122 2.239 2.239 0 00-2.325 1.588 3.728 3.728 0 00-.09 1.816l.58 2.897a.48.48 0 01-.78.46l-1.05-.893a3.022 3.022 0 00-1.377-.662 1.756 1.756 0 00-1.895.902 1.76 1.76 0 00-.147 1.286 9.028 9.028 0 002.558 4.267l.01.01c.358.334.683.707.966 1.107a7.235 7.235 0 002.37 2.129l.3.168a5.9 5.9 0 003.24.737 2.32 2.32 0 011.13.217 1.967 1.967 0 01.869 2.755l-.39.683a7.077 7.077 0 00-.926 3.263 5.05 5.05 0 00.243 1.728.605.605 0 01-.303.73.605.605 0 01-.522.013 2.474 2.474 0 00-2.33.169l-.359.224a.867.867 0 01-.455.13z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M21.503 26.465c-.287 0-.568-.112-.78-.319a.944.944 0 00-.64-.27.993.993 0 01-.764-.387l-1.08-1.398a18.48 18.48 0 00-.264-.335L16.152 21.5a2.969 2.969 0 00-1.948-1.084l-1.35-.169a6.112 6.112 0 01-1.793-.512l-2.098-.968a3.883 3.883 0 00-.857-.28 1.305 1.305 0 01-.799-.512 1.253 1.253 0 00-.312-.301l-1.089-.737-.098-.066-.744-.497a19.549 19.549 0 01-3.44-2.927l-.483-.517.036-.034.482.518a19.513 19.513 0 003.432 2.92l.744.496.099.067 1.089.737c.125.085.234.19.324.313.186.255.459.43.769.493.298.06.59.155.867.283l2.098.968a6 6 0 001.779.508l1.35.169a3.023 3.023 0 011.98 1.102l1.823 2.258c.09.11.179.224.265.335l1.08 1.399c.174.227.44.36.726.368a.993.993 0 01.674.284c.278.273.684.372 1.057.257l.676-.206a.708.708 0 01.275-.028.66.66 0 00.71-.79 4.525 4.525 0 01-.091-.761l-.002-.043a6.623 6.623 0 01.947-3.65.818.818 0 00-.15-1.022.864.864 0 01-.28-.667.863.863 0 00-.788-.888 8.553 8.553 0 01-3.476-1.076l-.187-.105a9.149 9.149 0 01-2.727-2.343 9.16 9.16 0 00-.506-.592l-.331-.356a10.656 10.656 0 01-2.442-4.34 2.293 2.293 0 01.351-1.98 2.319 2.319 0 012.053-.946l.578.047.033.003c.34.037.672-.08.914-.32.242-.241.36-.574.326-.913l-.05-.473c-.074-.73.082-1.45.454-2.082a2.967 2.967 0 013.409-1.332l.579.175c.36.109.748.088 1.094-.057.391-.165.697-.471.862-.862l.23-.546.044.02-.229.544a1.668 1.668 0 01-2.015.947l-.58-.175a2.902 2.902 0 00-.815-.125h-.027a2.919 2.919 0 00-2.51 1.435 3.344 3.344 0 00-.447 2.052l.049.474c.037.354-.087.7-.34.952-.252.25-.6.373-.953.333l-.032-.002-.578-.047a2.27 2.27 0 00-2.01.927 2.244 2.244 0 00-.343 1.936 10.613 10.613 0 002.43 4.321l.332.356c.177.19.348.39.508.596a9.09 9.09 0 002.712 2.33l.187.105a8.506 8.506 0 003.457 1.07.912.912 0 01.832.938.817.817 0 00.265.63c.304.276.37.732.159 1.084a6.577 6.577 0 00-.94 3.623l.002.042c.009.252.039.505.09.752a.711.711 0 01-.762.849.659.659 0 00-.257.026l-.676.206a1.113 1.113 0 01-.326.049z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M21.485 25.866a.636.636 0 01-.538-.296.586.586 0 00-.348-.255 2.36 2.36 0 01-1.193-.74l-1.342-1.543c-.226-.26-.461-.517-.7-.764l-.22-.227a8.91 8.91 0 00-3.926-2.363 2.123 2.123 0 00-.591-.084c-.388 0-.77-.104-1.104-.3l-1.9-1.119a3.887 3.887 0 00-.982-.41 3.93 3.93 0 01-1.189-.536l-.737-.493c-.338-.227-.69-.446-1.042-.651l-1.058-.616a6.528 6.528 0 01-2.113-1.973l-1.441-2.129.04-.027 1.442 2.129a6.478 6.478 0 002.096 1.958l1.058.615c.354.206.706.426 1.045.653l.737.494c.36.24.755.419 1.174.53.35.091.684.231.995.414l1.9 1.118c.327.193.7.295 1.08.295.204 0 .408.028.604.085a8.968 8.968 0 013.947 2.376l.22.227c.24.248.476.506.702.766l1.342 1.544c.309.355.713.605 1.168.724.157.04.29.139.378.275.162.256.49.347.761.211l.318-.16a.598.598 0 01.351-.058.551.551 0 00.627-.585l-.084-1.247a4.793 4.793 0 01.573-2.615 1.064 1.064 0 00-.085-1.147.881.881 0 01-.166-.392.834.834 0 00-.671-.687 10.362 10.362 0 01-3.35-1.24l-.41-.24a8.91 8.91 0 01-2.694-2.416 9.006 9.006 0 00-.777-.914l-.087-.09a8.377 8.377 0 01-2.165-3.991 4.127 4.127 0 01.56-3.138c.31-.48.839-.768 1.411-.768.888 0 1.605-.695 1.633-1.582.013-.406.14-.799.365-1.136l.937-1.4A2.326 2.326 0 0120.32.936l1.636.242A1.693 1.693 0 0023.692.32l.015-.027.043.024-.015.027a1.742 1.742 0 01-1.786.884L20.313.984a2.286 2.286 0 00-2.236.99l-.938 1.401c-.22.33-.344.714-.357 1.11a1.676 1.676 0 01-1.681 1.63 1.63 1.63 0 00-1.372.745 4.078 4.078 0 00-.552 3.1 8.327 8.327 0 002.153 3.97l.087.089c.28.287.542.597.78.92a8.862 8.862 0 002.681 2.402l.41.24a10.307 10.307 0 003.333 1.234c.367.067.652.36.71.728a.836.836 0 00.158.37c.261.347.296.818.089 1.2a4.741 4.741 0 00-.568 2.588l.084 1.246a.6.6 0 01-.682.637.55.55 0 00-.323.053l-.318.16a.634.634 0 01-.286.069z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M21.666 25.224a.595.595 0 01-.454-.209.542.542 0 00-.364-.19 1.946 1.946 0 01-1.288-.665l-1.868-2.152a9.183 9.183 0 00-4.434-2.822 4.47 4.47 0 00-.415-.097 4.442 4.442 0 01-1.233-.418l-2.221-1.14a2.002 2.002 0 00-.564-.19 2.072 2.072 0 01-1.206-.694l-.446-.524a1.92 1.92 0 00-.996-.62 1.964 1.964 0 01-.518-.213l-.244-.143A7.553 7.553 0 013.2 13.169a7.642 7.642 0 00-.417-.506l-1.72-1.914.037-.033 1.72 1.914c.146.163.287.334.419.51.6.797 1.342 1.458 2.202 1.965l.244.143c.157.093.328.163.505.208.4.101.753.321 1.021.636l.446.524c.302.354.72.595 1.178.677.2.036.395.102.577.195l2.22 1.14c.386.197.796.336 1.221.414.141.026.282.058.42.098a9.237 9.237 0 014.457 2.836l1.868 2.153c.321.37.767.6 1.256.647a.59.59 0 01.396.208c.165.195.45.249.675.127a.88.88 0 00.448-.924l-.125-.729a3.305 3.305 0 01.457-2.317 1.146 1.146 0 00-.777-1.742 8.08 8.08 0 01-2.916-1.113l-.825-.515a12.34 12.34 0 01-3.283-2.995l-.435-.573a10.893 10.893 0 01-1.914-4.002 4.86 4.86 0 01.534-3.653 2.355 2.355 0 011.68-1.138 1.804 1.804 0 001.507-1.474c.04-.227.12-.441.238-.638l.943-1.566a2.824 2.824 0 012.91-1.32l.768.139a1.776 1.776 0 001.398-.344l.03.039c-.407.315-.93.444-1.437.353L20.358.46a2.772 2.772 0 00-2.86 1.297l-.943 1.566c-.116.192-.194.4-.232.62a1.853 1.853 0 01-1.547 1.515 2.307 2.307 0 00-1.646 1.114 4.812 4.812 0 00-.528 3.617c.358 1.452 1 2.792 1.905 3.984l.435.573a12.257 12.257 0 003.27 2.983l.825.515a8.03 8.03 0 002.898 1.106 1.196 1.196 0 01.811 1.816 3.255 3.255 0 00-.45 2.283l.125.73a.929.929 0 01-.474.974.597.597 0 01-.281.07z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M20.645 24.024a1.01 1.01 0 01-.695-.274l-.916-.855c-.256-.24-.51-.49-.753-.742l-.647-.673a9.9 9.9 0 00-4.426-2.657 10.066 10.066 0 01-2.053-.838l-.994-.54a4.316 4.316 0 00-.727-.313 4.44 4.44 0 01-1.771-1.085l-.3-.301a6.05 6.05 0 00-1.59-1.146 6.156 6.156 0 01-1.949-1.521l-.027-.032c-.12-.14-.24-.285-.357-.429L1.102 9.72l.113-.092 2.34 2.899c.114.143.233.286.353.425l.027.032a6.018 6.018 0 001.903 1.485c.604.3 1.152.696 1.629 1.173l.3.301c.477.479 1.069.842 1.712 1.05.26.084.512.193.752.323l.993.54c.641.348 1.322.626 2.023.825a10.045 10.045 0 014.492 2.697l.647.673c.241.25.492.498.747.736l.916.855a.874.874 0 001.467-.637c0-.492.083-.976.247-1.438l.139-.392a1.106 1.106 0 00-.856-1.459 5.389 5.389 0 01-2.152-.88l-1.577-1.096c-.22-.152-.44-.312-.653-.473l-.014-.01a14.018 14.018 0 01-2.928-3.005 10.745 10.745 0 01-1.667-3.538 5.493 5.493 0 01.785-4.518 2.897 2.897 0 011.555-1.133 1.846 1.846 0 001.278-1.386c.05-.242.146-.47.28-.676l.824-1.26c.358-.549.76-1.075 1.194-1.565l.11.097c-.43.484-.828 1.005-1.182 1.548l-.823 1.26a1.835 1.835 0 00-.26.626 1.991 1.991 0 01-1.38 1.496 2.752 2.752 0 00-1.475 1.076 5.347 5.347 0 00-.764 4.398 10.606 10.606 0 001.645 3.49 13.875 13.875 0 002.897 2.973l.014.01c.212.161.43.32.647.47l1.577 1.096a5.245 5.245 0 002.095.857 1.249 1.249 0 01.968 1.652l-.139.392a4.142 4.142 0 00-.238 1.388 1.02 1.02 0 01-1.018 1.019z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M20.415 23.154a.58.58 0 01-.411-.17l-2.666-2.679a7.39 7.39 0 00-3.803-2.043 8.712 8.712 0 01-2.603-.975l-.584-.333a3.722 3.722 0 00-.785-.334 3.788 3.788 0 01-1.562-.918l-.393-.384a8.726 8.726 0 00-1.422-1.124 8.764 8.764 0 01-1.956-1.692L1.062 8.815l.038-.032 3.167 3.687a8.706 8.706 0 001.945 1.683 8.76 8.76 0 011.43 1.13l.393.384c.43.421.964.734 1.542.906.276.082.544.196.795.339l.583.333c.807.46 1.678.786 2.589.969.414.083.824.202 1.218.355.986.38 1.864.953 2.61 1.701l2.666 2.678a.528.528 0 00.648.082.53.53 0 00.26-.442l.008-.27a2.728 2.728 0 00-.194-1.092 2.73 2.73 0 00-1.014-1.258l-.718-.484c-.377-.255-.75-.526-1.108-.806l-1.267-.99a17.721 17.721 0 01-3.776-4.048 8.41 8.41 0 01-1.318-3.246 6.05 6.05 0 01.99-4.502 3.765 3.765 0 011.56-1.285 2.28 2.28 0 001.264-1.442c.076-.255.193-.494.349-.709l1.511-2.09.04.03-1.512 2.089a2.29 2.29 0 00-.34.693 2.328 2.328 0 01-1.293 1.473A3.716 3.716 0 0012.59 5.92a5.999 5.999 0 00-.982 4.466 8.366 8.366 0 001.31 3.228 17.663 17.663 0 003.766 4.035l1.268.991c.357.28.729.55 1.104.804l.718.484a2.78 2.78 0 011.032 1.28c.142.356.208.73.198 1.113l-.008.27a.578.578 0 01-.284.482.57.57 0 01-.296.082z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M19.418 21.133a.337.337 0 01-.217-.08l-.826-.707a11.838 11.838 0 00-4.607-2.439l-.344-.094a7.283 7.283 0 01-1.793-.757 7.268 7.268 0 00-1.264-.59l-.471-.167a3.156 3.156 0 01-1.524-1.149 3.104 3.104 0 00-.937-.866 13.694 13.694 0 01-1.79-1.282 19.42 19.42 0 01-1.863-1.8l-2.72-3.01.037-.033 2.72 3.01a19.322 19.322 0 001.856 1.796c.558.472 1.159.901 1.785 1.277.377.226.697.522.952.88.374.525.892.916 1.5 1.131l.47.167c.442.156.87.356 1.273.594a7.251 7.251 0 001.781.753l.344.093a11.874 11.874 0 014.626 2.449l.826.707a.286.286 0 10.358-.444l-1.397-1.061-2.006-1.516a13.757 13.757 0 01-2.962-3.063 13.674 13.674 0 01-2.27-5.37l-.126-.668a2.98 2.98 0 01.493-2.272l.677-.962c.31-.44.604-.897.876-1.36l.017-.03a1.11 1.11 0 011.06-.542c.471.045.92-.233 1.088-.676A7.461 7.461 0 0116.291.924l.468-.558.037.03-.467.56a7.401 7.401 0 00-1.243 2.114 1.111 1.111 0 01-1.139.707 1.063 1.063 0 00-1.012.518l-.018.03c-.272.464-.567.922-.877 1.363l-.678.962a2.935 2.935 0 00-.484 2.235l.126.667a13.634 13.634 0 002.262 5.352 13.7 13.7 0 002.95 3.052l2.053 1.55 1.352 1.027a.334.334 0 01-.203.6z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M12.98 17.088a.552.552 0 01-.228-.052l-2.012-.97c-.22-.105-.44-.219-.655-.335a5.67 5.67 0 01-1.703-1.416 5.732 5.732 0 00-.397-.44l-.402-.4a3.603 3.603 0 00-1.206-.797 3.68 3.68 0 01-1.487-1.1l-.53-.657a19.525 19.525 0 00-2.637-2.69l-.755-.635.031-.037.755.634c.964.81 1.854 1.717 2.644 2.697l.53.656c.387.48.894.857 1.467 1.087.46.184.871.456 1.222.806l.402.401c.14.14.275.29.4.444a5.627 5.627 0 001.689 1.403c.214.117.434.23.653.335l2.012.97a.476.476 0 00.595-.702l-.27-.38a20.586 20.586 0 01-.364-.531l-.43-.652a12.249 12.249 0 01-2.025-6.895c.004-.385.025-.776.061-1.16l.08-.847a4.517 4.517 0 00-.724-2.905 1.227 1.227 0 01-.105-1.16.782.782 0 01.51-.449.784.784 0 01.67.115c.04.028.083.053.129.073l1.604.705c.118.051.237.103.356.152l.408.17c.282.117.592.117.873 0 .277-.114.502-.34.617-.617A1.19 1.19 0 0115 1.538L16.278.21l.036.034-1.28 1.328c-.099.103-.177.223-.232.355-.119.29-.354.525-.643.645a1.18 1.18 0 01-.91 0l-.408-.17c-.12-.05-.24-.102-.357-.153l-1.604-.707a.803.803 0 01-.138-.078.735.735 0 00-1.107.314c-.156.366-.118.782.1 1.114.57.864.83 1.907.733 2.937l-.08.847c-.036.383-.057.772-.061 1.156a12.25 12.25 0 00.18 2.239c.29 1.663.908 3.22 1.837 4.629l.43.652c.118.177.24.355.363.53l.269.379a.523.523 0 01-.426.827z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M13.268 2.04a1.55 1.55 0 01-.387-.049 1.841 1.841 0 01-.524-.228L10.097.324l.027-.04 2.26 1.438c.157.101.329.175.509.222a1.485 1.485 0 001.625-.636c.06-.093.13-.18.207-.257l.767-.764.034.034-.766.764a1.49 1.49 0 00-.201.25 1.533 1.533 0 01-1.291.706z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M13.252 1.24c-.038 0-.077 0-.116-.004a1.348 1.348 0 01-.616-.211l-1.083-.7.027-.042 1.082.701a1.298 1.298 0 001.728-.293l.252-.324.038.03-.252.324c-.256.33-.646.52-1.06.52z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M13.415.64a.738.738 0 01-.544-.24l-.116-.125.108-.099.116.126a.593.593 0 00.91-.042l.116.088a.736.736 0 01-.59.292zM10.928 15.45a.649.649 0 01-.238-.046 2.415 2.415 0 01-.225-.103 6.09 6.09 0 01-1.511-1.105L7.89 13.133a3.36 3.36 0 00-1.173-.764 3.438 3.438 0 01-1.44-1.053l-.212-.265A19.5 19.5 0 001.164 7.37L.97 7.23l.028-.04.194.139a19.532 19.532 0 013.912 3.692l.213.265c.372.465.863.823 1.418 1.039.45.173.85.434 1.19.774l1.063 1.063c.441.44.945.81 1.5 1.097a2.5 2.5 0 00.22.1.596.596 0 00.736-.852.61.61 0 01-.028-.056l-.427-.933a13.24 13.24 0 01-1.129-6.8l.124-1.242a3.12 3.12 0 00-.426-1.915A3.175 3.175 0 019.312.814L9.535.22l.045.017-.222.595A3.126 3.126 0 009.6 3.536c.35.59.5 1.262.433 1.945l-.124 1.243a13.2 13.2 0 001.125 6.774l.426.934a.552.552 0 00.027.051.646.646 0 01-.07.745.652.652 0 01-.489.222z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M9.967 14.349a.654.654 0 01-.484-.215l-.819-.907a3.966 3.966 0 00-1.47-1.022 4.09 4.09 0 01-1.778-1.366 17.23 17.23 0 00-3.922-3.832l-.377-.266.085-.12.376.266a17.381 17.381 0 013.956 3.865 3.944 3.944 0 001.713 1.318c.58.23 1.108.596 1.526 1.06l.82.906a.508.508 0 00.829-.564A11.26 11.26 0 019.306 9.56a15.585 15.585 0 01.007-3.07l.03-.288a4.281 4.281 0 00-.383-2.249A4.427 4.427 0 018.712.86l.186-.654.14.04L8.853.9a4.281 4.281 0 00.24 2.992c.34.725.476 1.529.396 2.325l-.03.289a15.483 15.483 0 00-.006 3.04 11.11 11.11 0 001.1 3.862c.101.204.09.44-.03.634a.648.648 0 01-.555.308zM11.634 4.148a.728.728 0 01-.582-.292l-.875-1.178a.534.534 0 01.296-.833c.144-.037.3-.01.423.072l.684.45c.263.174.484.395.658.658a.728.728 0 01-.02.826.726.726 0 01-.581.297h-.003zm-1.03-2.27a.484.484 0 00-.388.77l.876 1.179c.127.17.33.272.542.272v.024l.003-.024a.678.678 0 00.543-.277.679.679 0 00.018-.771 2.248 2.248 0 00-.644-.643l-.684-.45a.487.487 0 00-.266-.08z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M11.381 3.413a.283.283 0 01-.182-.503.29.29 0 01.325-.026.286.286 0 01-.143.53zm0-.52a.236.236 0 00-.076.458.237.237 0 00.195-.426.235.235 0 00-.119-.032zM8.444 12.02a.506.506 0 01-.32-.114.897.897 0 00-.276-.154 4.873 4.873 0 01-2.37-1.76A13.259 13.259 0 001.823 6.55l-.95-.603.027-.041.95.603a13.319 13.319 0 013.67 3.455 4.822 4.822 0 002.345 1.742.954.954 0 01.29.162.456.456 0 00.568.008.456.456 0 00.14-.55.5.5 0 01-.044-.197l-.044-2.336c-.01-.564.004-1.136.043-1.698l.045-.665a4.24 4.24 0 00-.469-2.247A4.271 4.271 0 018.083.99L8.31.219l.047.014-.227.771a4.22 4.22 0 00.306 3.156c.364.7.528 1.487.475 2.274l-.046.664a19.438 19.438 0 00-.042 1.694l.044 2.336a.448.448 0 00.04.178.505.505 0 01-.463.714z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M7.374 10.78a.91.91 0 01-.75-.4A13.583 13.583 0 002.53 6.415l-1.46-.914.025-.042 1.461.915a13.64 13.64 0 014.11 3.98.853.853 0 001.56-.53l-.019-.305a19.575 19.575 0 01-.002-2.458l.03-.498a4.9 4.9 0 00-.417-2.3A4.925 4.925 0 017.616.759l.146-.462.047.015-.147.462a4.878 4.878 0 00.2 3.47c.325.727.47 1.53.421 2.324l-.03.497c-.051.814-.05 1.638.001 2.452l.02.304a.902.902 0 01-.9.96z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M6.962 9.209a.786.786 0 01-.666-.365l-.284-.446a7.037 7.037 0 00-3.351-2.766L1.15 5.034l.018-.045 1.511.598a7.093 7.093 0 013.374 2.785l.284.446c.121.19.319.313.543.337a.734.734 0 00.603-.212.734.734 0 00.216-.522V7.07c0-.837-.153-1.656-.455-2.437A6.841 6.841 0 017.025.391l.026-.094.047.013-.026.094a6.789 6.789 0 00.217 4.213c.305.786.46 1.61.46 2.454v1.35a.784.784 0 01-.787.788z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M6.429 7.338a.591.591 0 01-.425-.178 14.38 14.38 0 00-3.946-2.43l-.909-.375.019-.045.909.375a14.434 14.434 0 013.959 2.439l.02.017a.543.543 0 00.919-.425 11.515 11.515 0 00-.415-2.498l-.084-.298A7.916 7.916 0 016.274.525l.049.008a7.865 7.865 0 00.2 3.374l.084.298c.23.817.37 1.66.415 2.508a.59.59 0 01-.593.625z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M4.94 5.45c-.206 0-.412-.058-.593-.173a.957.957 0 00-.122-.067L1.05 3.775l.06-.133 3.175 1.435c.05.022.096.048.141.077a.95.95 0 001.45-.952l-.116-.706a13.622 13.622 0 00-.048-.282l-.003-.018A6.055 6.055 0 015.959.12l.139.049a5.906 5.906 0 00-.245 3l.003.018.049.284.115.707A1.096 1.096 0 014.94 5.45z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M4.547 4.489a.77.77 0 01-.38-.1.719.719 0 00-.125-.056L1.073 3.324l.016-.046 2.968 1.008a.728.728 0 01.134.06c.24.137.54.123.767-.033a.726.726 0 00.303-.706A10.3 10.3 0 015.225.67L5.274.3l.048.007-.048.369c-.128.972-.116 1.955.036 2.923a.775.775 0 01-.763.89z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M4.172 3.672a.371.371 0 01-.115-.018L.977 2.67l.014-.047 3.081.984a.33.33 0 00.429-.333 9.84 9.84 0 01.194-2.65l.052-.247.048.01-.052.247a9.804 9.804 0 00-.194 2.637.38.38 0 01-.101.282.383.383 0 01-.276.119z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M3.035 2.849a.806.806 0 01-.322-.067 3.735 3.735 0 00-.523-.185l-1.213-.33.012-.048 1.214.33c.18.05.358.113.53.188a.755.755 0 001.051-.771.796.796 0 01.014-.261L4.093.377l.048.01-.295 1.329a.738.738 0 00-.013.245.803.803 0 01-.798.888z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M2.46 2.042c-.103 0-.207-.016-.31-.048l-1.076-.34.014-.046 1.077.34a.963.963 0 001.253-.823L3.536 0l.048.005-.117 1.124a1.016 1.016 0 01-1.008.913z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M1.781 1.297h-.622V1.25h.622c.564 0 1.023-.46 1.023-1.024h.049c0 .592-.481 1.072-1.072 1.072zM.996.96L.971.92c.033-.02.12-.043.265-.071a.745.745 0 00.6-.626l.048.007a.795.795 0 01-.639.667c-.171.032-.23.052-.249.064zM40.982 31.483l-.476-.085a1.103 1.103 0 01-.863-.763 1.063 1.063 0 00-.269-.44l-.499-.492a.319.319 0 01.267-.544.313.313 0 00.036.003h1.73v.049h-1.73l-.042-.003a.27.27 0 00-.226.46l.499.492c.13.128.226.287.28.461.118.38.434.659.825.729l.477.085-.009.048z\"\n      fill=\"#E6E6E6\"\n    />\n    <path\n      d=\"M40.57 30.732a.54.54 0 01-.447-.838.535.535 0 01.4-.236l.162-.015.005.05-.162.013a.488.488 0 00-.425.634.49.49 0 00.52.34l.166-.017.005.048-.166.018a.45.45 0 01-.058.003z\"\n      fill=\"#E6E6E6\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 42 / 40,\n  svg: TerrainMap,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-fashion-collection/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as summerTrendHeart } from './yellowHeart';\nimport { default as summerTrendInstragramIcon } from './yellowInstagram';\nimport { default as summerTrendStar } from './yellowStar';\n\nexport { summerTrendHeart, summerTrendInstragramIcon, summerTrendStar };\n"
  },
  {
    "path": "packages/stickers/src/summer-fashion-collection/yellowHeart.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Heart', 'sticker name', 'web-stories');\n\nconst YellowHeart = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 44 41\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M3.99717 4.44036C6.22369 2.04717 9.34361 0.685474 12.6124 0.680426C15.8837 0.684212 19.0069 2.04518 21.2368 4.43883L21.9968 5.24191L22.7568 4.43883C27.1816 -0.323491 34.6294 -0.596983 39.3916 3.82784C39.6026 4.02399 39.8064 4.22771 40.0026 4.43883C44.6965 9.50177 44.6965 17.3263 40.0026 22.3893L23.1137 40.1997C22.5294 40.8165 21.5557 40.843 20.9388 40.2587C20.9186 40.2395 20.899 40.2199 20.8799 40.1997L3.99708 22.3893C-0.696457 17.3269 -0.696457 9.50276 3.99717 4.44036ZM6.22324 20.2708H6.22477L21.9968 36.9059L37.7703 20.2708C41.3562 16.4023 41.3562 10.4243 37.7703 6.55573C34.5139 3.02629 29.0128 2.80499 25.4833 6.06139C25.312 6.2195 25.1471 6.38437 24.989 6.55573L23.1137 8.53418C22.4957 9.14823 21.4979 9.14823 20.8799 8.53418L19.0045 6.55727C15.7481 3.02783 10.247 2.80653 6.71758 6.06292C6.54622 6.22103 6.38135 6.3859 6.22324 6.55727C2.60619 10.4319 2.57968 16.4208 6.22324 20.2708Z\"\n      fill=\"#FFF7CE\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 44 / 41,\n  svg: YellowHeart,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-fashion-collection/yellowInstagram.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Instagram', 'sticker name', 'web-stories');\n\nconst YellowInstagramIcon = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 40 41\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M20 4.28518C25.34 4.28518 25.9733 4.30518 28.0833 4.40184C33.5033 4.64851 36.035 7.22018 36.2817 12.6002C36.3783 14.7085 36.3967 15.3418 36.3967 20.6818C36.3967 26.0235 36.3767 26.6552 36.2817 28.7635C36.0333 34.1385 33.5083 36.7152 28.0833 36.9618C25.9733 37.0585 25.3433 37.0785 20 37.0785C14.66 37.0785 14.0267 37.0585 11.9183 36.9618C6.485 36.7135 3.96667 34.1302 3.72 28.7618C3.62333 26.6535 3.60333 26.0218 3.60333 20.6802C3.60333 15.3402 3.625 14.7085 3.72 12.5985C3.96833 7.22018 6.49333 4.64684 11.9183 4.40018C14.0283 4.30518 14.66 4.28518 20 4.28518ZM20 0.680176C14.5683 0.680176 13.8883 0.703509 11.755 0.800176C4.49167 1.13351 0.455 5.16351 0.121667 12.4335C0.0233333 14.5685 0 15.2485 0 20.6802C0 26.1118 0.0233333 26.7935 0.12 28.9268C0.453333 36.1902 4.48333 40.2268 11.7533 40.5602C13.8883 40.6568 14.5683 40.6802 20 40.6802C25.4317 40.6802 26.1133 40.6568 28.2467 40.5602C35.5033 40.2268 39.55 36.1968 39.8783 28.9268C39.9767 26.7935 40 26.1118 40 20.6802C40 15.2485 39.9767 14.5685 39.88 12.4352C39.5533 5.17851 35.5183 1.13518 28.2483 0.801842C26.1133 0.703509 25.4317 0.680176 20 0.680176ZM20 10.4102C14.3283 10.4102 9.73 15.0085 9.73 20.6802C9.73 26.3518 14.3283 30.9518 20 30.9518C25.6717 30.9518 30.27 26.3535 30.27 20.6802C30.27 15.0085 25.6717 10.4102 20 10.4102ZM20 27.3468C16.3183 27.3468 13.3333 24.3635 13.3333 20.6802C13.3333 16.9985 16.3183 14.0135 20 14.0135C23.6817 14.0135 26.6667 16.9985 26.6667 20.6802C26.6667 24.3635 23.6817 27.3468 20 27.3468ZM30.6767 7.60518C29.35 7.60518 28.275 8.68018 28.275 10.0052C28.275 11.3302 29.35 12.4052 30.6767 12.4052C32.0017 12.4052 33.075 11.3302 33.075 10.0052C33.075 8.68018 32.0017 7.60518 30.6767 7.60518Z\"\n      fill=\"#FFF7CE\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 40 / 41,\n  svg: YellowInstagramIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/summer-fashion-collection/yellowStar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Star', 'sticker name', 'web-stories');\n\nconst YellowStar = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 51 51\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M27.5583 11.9566L25.9443 2.97414L24.3304 11.9566L20.6884 3.58847L21.1894 12.701L15.7158 5.39834L18.3048 14.1497L11.2947 8.30618L15.8321 16.2246L7.66328 12.1552L13.9045 18.8138L5.01742 16.738L12.626 21.7777L3.49974 21.8074L12.0654 24.9566L3.19206 27.0902L12.2531 28.1791L4.11095 32.3015L13.1789 31.2714L6.20689 37.1604L14.7929 34.0669L9.36688 41.405L17.008 36.4149L13.4206 44.8065L19.705 38.1886L18.1494 47.1814L22.7382 39.2927L23.2985 48.4017L25.9443 39.6674L28.5902 48.4017L29.1505 39.2927L33.7393 47.1814L32.1837 38.1886L38.4681 44.8065L34.8806 36.4149L42.5218 41.405L37.0958 34.0669L45.6818 37.1604L38.7098 31.2714L47.7777 32.3015L39.6356 28.1791L48.6966 27.0902L39.8232 24.9566L48.3889 21.8074L39.2627 21.7777L46.8713 16.738L37.9842 18.8138L44.2254 12.1552L36.0566 16.2246L40.594 8.30618L33.5838 14.1497L36.1729 5.39834L30.6992 12.701L31.2003 3.58847L27.5583 11.9566ZM31.7293 1.35634L31.1778 11.3861L37.2024 3.34838L34.3528 12.9806L42.0685 6.54891L37.0744 15.2643L46.0654 10.7854L39.196 18.1141L48.9776 15.8294L40.6032 21.3764L50.6481 21.4091L41.2202 24.8753L50.9867 27.2235L41.0136 28.4221L49.9753 32.9594L39.9946 31.8257L47.6684 38.3074L38.2182 34.9025L44.1904 42.9792L35.7801 37.4868L39.7287 46.723L32.8117 39.4391L34.5239 49.337L29.4732 40.6543L28.8565 50.6802L25.9443 41.0667L23.0322 50.6802L22.4155 40.6543L17.3648 49.337L19.0769 39.4391L12.16 46.723L16.1086 37.4868L7.69832 42.9792L13.6705 34.9025L4.22026 38.3074L11.894 31.8257L1.91336 32.9594L10.8751 28.4221L0.901978 27.2235L10.6685 24.8753L1.24063 21.4091L11.2854 21.3764L2.91107 15.8294L12.6927 18.1141L5.82324 10.7854L14.8143 15.2643L9.82014 6.54891L17.5359 12.9806L14.6863 3.34838L20.7108 11.3861L20.1594 1.35634L24.1679 10.5667L25.9443 0.680176L27.7208 10.5667L31.7293 1.35634Z\"\n      fill=\"#FFE55C\"\n    />\n  </svg>\n);\nexport default {\n  aspectRatio: 51 / 51,\n  svg: YellowStar,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sustainability-tips/cloudBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Cloud Banner', 'sticker name', 'web-stories');\n\nconst CloudBanner = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 50 30\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M23.5464 25.9229C21.4359 26.7493 19.0785 27.2113 16.5915 27.2113C7.56047 27.2113 0.23938 21.1198 0.23938 13.6056C0.23938 6.09145 7.56047 0 16.5915 0C21.1119 0 25.204 1.52619 28.1639 3.99306C30.0853 3.21943 32.2185 2.78873 34.4647 2.78873C42.9124 2.78873 49.7605 8.88018 49.7605 16.3944C49.7605 23.9086 42.9124 30 34.4647 30C30.1885 30 26.3221 28.4391 23.5464 25.9229Z\"\n      fill=\"#FDF0D6\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 50 / 30,\n  svg: CloudBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/sustainability-tips/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as cloudBanner } from './cloudBanner';\n\nexport { cloudBanner };\n"
  },
  {
    "path": "packages/stickers/src/technology-advice/grayFrameCorner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Gray Frame Corner', 'sticker name', 'web-stories');\n\nconst GrayFrameCorner = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 26 26\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M25.5 25.5L25.5 0.5L0.5 0.500001L0.5 1.5L24.5 1.5L24.5 25.5H25.5Z\"\n      fill=\"#8C8C8C\"\n      fillOpacity=\"0.5\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 26 / 26,\n  svg: GrayFrameCorner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/technology-advice/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as studioWhiteFrameCorner } from './whiteFrameCorner';\nimport { default as studioGrayFrameCorner } from './grayFrameCorner';\n\nexport { studioWhiteFrameCorner, studioGrayFrameCorner };\n"
  },
  {
    "path": "packages/stickers/src/technology-advice/whiteFrameCorner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Frame Corner', 'sticker name', 'web-stories');\n\nconst WhiteFrameCorner = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 26 26\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      opacity=\"0.6\"\n      d=\"M25.5 25.5L25.5 0.5L0.5 0.500001L0.5 1.5L24.5 1.5L24.5 25.5H25.5Z\"\n      fill=\"white\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 26 / 26,\n  svg: WhiteFrameCorner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/greenFlower.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Flower', 'sticker name', 'web-stories');\n\nconst GreenFlower = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 44 42\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M20.7281 0.148751C20.1361 0.0248252 19.4925 -0.0279067 18.8989 0.192749C18.2777 0.425236 17.8132 0.951121 17.3764 1.46518C16.2566 2.76215 15.188 4.10278 14.1391 5.45138C13.6623 6.06437 13.1973 6.70512 12.9688 7.44138C12.7164 8.237 12.7836 9.09266 12.8589 9.92852C13.1502 12.7848 13.7341 15.5981 14.6067 18.3208C14.7352 18.7409 14.8791 19.2362 14.6522 19.6279C14.258 20.3203 13.236 20.0688 12.5146 19.7545C10.721 18.9153 8.86032 18.072 6.88198 17.9177C4.90365 17.7634 2.72403 18.4484 1.63416 20.1256C0.536294 21.8227 0.869125 24.2354 2.12199 25.8459C3.37486 27.4564 5.41299 28.3713 7.43024 28.6564C9.34093 28.9215 11.2814 28.7153 13.1867 28.4259C13.6976 28.1259 14.5373 28.4879 14.7756 29.0904C15.0687 29.7841 14.9111 30.572 14.8367 31.3244C14.6521 33.7124 15.6329 36.1105 17.2683 37.8525C18.9037 39.5944 21.1465 40.684 23.459 41.2033C24.4495 41.4191 25.5274 41.5321 26.4261 41.0665C27.2615 40.6443 27.8065 39.8056 28.1303 38.9468C29.1571 36.3466 28.6095 33.3868 27.6692 30.7749C27.4001 30.0218 27.0915 29.2528 27.0951 28.4488C27.0987 27.6448 27.5173 26.7782 28.2691 26.5063C28.7241 26.3448 29.2255 26.4091 29.6832 26.5249C32.0745 27.0761 34.3631 28.5064 36.7937 28.2219C37.9952 28.0856 39.1236 27.5056 40.1497 26.8382C42.1741 25.5152 44.06 23.3999 43.7943 20.9912C43.5739 19.0381 41.9929 17.5023 40.3186 16.4811C37.5728 14.8202 34.3807 14.0378 31.1859 13.8296C30.2737 13.7605 29.2784 13.7269 28.6017 13.1315C28.0075 12.6154 27.7623 11.803 27.588 11.0422C26.945 8.20505 26.7021 5.11519 24.927 2.81056C23.9059 1.47778 22.3894 0.520308 20.7281 0.148751ZM25.8825 22.2518C25.4351 23.36 24.1608 23.9041 23.0567 23.4583C21.9527 23.0126 21.4133 21.7362 21.8607 20.6281C22.3081 19.5199 23.5825 18.9758 24.6865 19.4215C25.7905 19.8673 26.3299 21.1437 25.8825 22.2518Z\"\n      fill=\"#3F4F3E\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 44 / 42,\n  svg: GreenFlower,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/greenLeafBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Green Leaf Banner', 'sticker name', 'web-stories');\n\nconst GreenLeafBanner = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 43 38\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M41.9743 28.096C43.0565 24.2879 38.1535 21.8021 34.9412 20.9069C33.0596 20.3954 31.1855 20.1253 29.349 20.1185C31.5039 19.0608 33.5762 17.8641 35.4761 16.4626C37.7583 14.7903 41.1944 11.2887 38.6674 7.94629C36.3654 4.92567 31.5569 5.77207 29.076 7.02377C27.2584 7.93511 25.8345 9.25234 24.6917 10.8146C24.9499 9.07703 25.0994 7.29931 25.0053 5.53994C24.9337 3.87568 23.2422 -0.86063 20.6675 0.20456C19.3371 0.764601 18.1906 2.52068 17.4938 3.66212C16.5459 5.20964 15.8379 6.93267 15.3661 8.71049C15.0104 10.1408 14.7821 11.5857 14.6513 13.0232C14.55 12.5953 14.4187 12.1454 14.2986 11.7431C13.9385 10.5362 12.6709 7.17138 11.0634 8.86541C9.35098 10.64 8.70707 13.7858 8.31411 16.2111C8.06709 17.6816 7.94751 19.1667 7.90664 20.67C7.43406 19.3021 6.95771 17.8136 6.12911 16.6177C4.8206 14.7563 2.63182 15.0423 1.74391 16.6337C0.634981 18.6531 0.699414 21.6488 1.0373 24.0189C1.41274 26.6524 2.44779 29.1394 4.01502 31.4653C4.09751 31.6043 4.21747 31.692 4.37489 31.7285C5.17721 32.7086 6.28682 33.5203 7.28773 34.2918C9.55945 36.0322 13.1206 38.4013 15.9202 37.658C17.6442 37.1892 17.5577 35.9859 16.894 34.7534C18.2847 35.4955 19.7316 36.1608 21.2235 36.7017C22.9027 37.301 25.193 38.0721 26.5232 36.883C28.4643 35.2364 26.8746 32.8154 24.7527 30.8701C27.2828 31.5022 29.8241 31.8672 32.3427 31.8225C35.3599 31.7887 41.128 31.3297 41.9743 28.096Z\"\n      fill=\"#3F4F3E\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 43 / 38,\n  svg: GreenLeafBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as luauYellowFlowerBanner } from './yellowFlowerBanner';\nimport { default as luauGreenLeafBanner } from './greenLeafBanner';\nimport { default as luauYellowFlower } from './yellowFlower';\nimport { default as luauGreenFlower } from './greenFlower';\nimport { default as luauYellowWavyLine } from './yellowWavyLine';\nimport { default as luauWhiteDottedArrow } from './whiteDottedArrow';\n\nexport {\n  luauYellowFlowerBanner,\n  luauGreenLeafBanner,\n  luauYellowFlower,\n  luauGreenFlower,\n  luauYellowWavyLine,\n  luauWhiteDottedArrow,\n};\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/whiteDottedArrow.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('White Dotted Arrow', 'sticker name', 'web-stories');\n\nconst WhiteDottedArrow = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 52 19\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M2.887 18.467c1.474-.298 2.943-.625 4.417-.922 2.264-.488 1.556-3.995-.708-3.507-1.474.298-2.943.625-4.417.923-2.264.487-1.556 3.994.708 3.506zM13.348 16.63c1.326-.267 2.629-.653 3.89-1.091.914-.338 1.177-1.618.804-2.402-.467-.948-1.482-1.11-2.402-.803-.972.35-1.969.582-2.971.784-2.3.465-1.591 3.971.678 3.513zM22.35 14.72c1.415-.285 2.825-.6 4.21-.88 2.264-.488 1.556-3.994-.708-3.507-1.415.286-2.824.601-4.21.881-2.24.452-1.532 3.959.708 3.506zM32.462 12.526a72.276 72.276 0 014.328-.905c2.281-.399 1.574-3.905-.708-3.506-1.45.262-2.895.554-4.328.905-2.252.546-1.544 4.053.708 3.506z\"\n      fill=\"#fff\"\n    />\n    <path\n      d=\"M34.93 3.933a2479.52 2479.52 0 0113.902 3.204l-.907-2.67a2664.914 2664.914 0 00-8.9 10.477c-1.489 1.742 1.517 3.71 2.976 1.975 2.979-3.485 5.928-6.963 8.9-10.476.694-.815.12-2.447-.907-2.669C45.362 2.716 40.73 1.658 36.092.57c-2.224-.532-3.416 2.837-1.162 3.363z\"\n      fill=\"#fff\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 52 / 19,\n  svg: WhiteDottedArrow,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/yellowFlower.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Flower', 'sticker name', 'web-stories');\n\nconst YellowFlower = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 38 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M37.5005 10.2974C37.3942 9.70212 37.2028 9.08555 36.7776 8.6178C36.3311 8.12879 35.672 7.89492 35.0342 7.68231C33.4183 7.12952 31.7812 6.64051 30.1441 6.17276C29.4 5.96015 28.6346 5.7688 27.8692 5.83258C27.04 5.89637 26.2746 6.27907 25.5304 6.66177C23.0003 8.00123 20.6191 9.59581 18.4292 11.4243C18.089 11.7007 17.685 12.0196 17.2386 11.9558C16.4519 11.8495 16.3031 10.8077 16.3243 10.021C16.4306 8.04375 16.5157 6.00267 15.9204 4.11043C15.3251 2.21818 13.8793 0.453503 11.9233 0.0708015C9.94597 -0.3119 7.84111 0.899988 6.82057 2.66467C5.80004 4.42935 5.71499 6.66177 6.204 8.63906C6.67175 10.51 7.58598 12.2322 8.56399 13.8906C9.03174 14.252 9.01048 15.1662 8.54273 15.6127C8.0112 16.1443 7.22454 16.2931 6.50166 16.5057C4.22671 17.2286 2.37699 19.0358 1.37771 21.2044C0.378435 23.3731 0.208345 25.8606 0.591046 28.1994C0.761136 29.1986 1.05879 30.2404 1.8242 30.8995C2.52581 31.5161 3.50383 31.7075 4.41806 31.6862C7.20328 31.6649 9.73336 30.0491 11.7957 28.1994C12.391 27.6678 12.9863 27.0938 13.7305 26.7961C14.4746 26.4985 15.4314 26.5622 15.9629 27.1576C16.2818 27.519 16.4094 28.008 16.4732 28.4757C16.8559 30.8995 16.3881 33.5572 17.5575 35.7046C18.1315 36.7676 19.0883 37.5968 20.0876 38.2984C22.0648 39.6804 24.7225 40.6371 26.8486 39.489C28.5708 38.5536 29.4 36.5125 29.7189 34.5777C30.2291 31.4098 29.7614 28.1568 28.7621 25.1165C28.4857 24.2448 28.1455 23.3093 28.4432 22.4588C28.6983 21.7147 29.3574 21.1832 29.9953 20.7367C32.3765 19.0783 35.1405 17.6963 36.6075 15.1875C37.458 13.7417 37.7769 11.9771 37.5005 10.2974ZM19.0032 23.3518C17.8126 23.3518 16.8346 22.3738 16.8346 21.1832C16.8346 19.9925 17.8126 19.0145 19.0032 19.0145C20.1939 19.0145 21.1719 19.9925 21.1719 21.1832C21.1719 22.3738 20.1939 23.3518 19.0032 23.3518Z\"\n      fill=\"#ECE7BD\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 38 / 40,\n  svg: YellowFlower,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/yellowFlowerBanner.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Flower Banner', 'sticker name', 'web-stories');\n\nconst YellowFlowerBanner = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 52 40\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      d=\"M16.6412 3.25188C17.5499 2.14201 19.0266 1.03214 20.489 1.14433C20.9491 1.17962 21.2316 1.61844 21.2297 2.07986L21.2068 7.83163C21.2068 8.09585 21.3106 8.36007 21.5181 8.53621C22.2185 9.1307 23.1783 8.51419 23.749 7.9197C25.6946 5.91606 27.5624 3.86838 29.3263 1.75465C29.7933 1.2042 30.2602 0.653748 30.9347 0.301459C31.6091 -0.0508293 32.543 -0.138901 33.1656 0.279441C33.9957 0.851911 33.8141 1.97483 33.5547 2.85555C32.8284 5.32157 32.102 7.7876 31.3757 10.2536C31.22 10.8041 31.0903 11.4866 31.5573 11.883C32.128 12.3674 33.0878 12.1031 33.7882 11.7729C37.2124 10.0775 39.599 6.97293 43.3345 5.82799C43.6458 5.73992 43.983 5.65185 44.2943 5.69588C45.0206 5.80597 45.4097 6.48853 45.4616 7.08302C45.5913 8.42612 44.7093 9.68115 43.8533 10.8041C42.0115 13.2261 40.1956 15.648 38.3538 18.07C36.5956 20.382 49.0443 19.7647 50.1784 19.7039C50.2392 19.7006 50.2913 19.7016 50.3512 19.7118C50.5281 19.742 50.7022 19.8067 50.8573 19.9195C51.3502 20.2718 51.1686 20.6682 50.9352 21.0204C49.7419 22.87 47.5888 24.169 45.2282 24.7855C44.0549 25.0919 42.2345 25.1699 40.7 25.1708C39.6886 25.1714 39.098 26.4283 39.7541 27.1982C41.343 29.0625 43.4951 31.7823 44.3202 33.7249C44.4759 34.0992 44.6056 34.5836 44.2683 34.8698C44.0868 35.0239 43.8273 35.09 43.5679 35.134C42.1671 35.3982 40.5847 35.6404 39.3396 34.9799C38.8467 34.7157 38.4576 34.3414 38.0944 33.945C37.1452 32.9866 36.2064 32.0282 35.2649 31.0753C34.6032 30.4057 33.4597 30.8111 33.3371 31.7444C33.0994 33.553 32.7945 35.3507 32.4133 37.1377C32.1539 38.4147 31.4276 39.978 29.897 40C29.0669 40 28.3406 39.4716 27.9515 38.8551C27.5883 38.2165 27.4845 37.512 27.4067 36.8074C27.2576 35.4995 27.1085 34.1917 26.9594 32.8781C26.8552 31.9604 25.7587 31.572 25.158 32.2736C24.3393 33.2299 23.6167 34.2439 22.9968 35.3102C22.2445 36.6312 21.4922 38.1285 19.9098 38.7009C18.576 39.1806 17.8529 38.8242 16.5903 38.8267C16.2165 38.8274 15.8295 38.6867 15.7016 38.3355C15.3382 37.3376 15.7092 35.9037 15.9927 34.1253C16.3711 32.1705 16.2238 30.4843 16.0908 28.7752C16.0331 28.0346 15.287 27.5391 14.6586 27.9352C13.1446 28.8894 12.0711 30.38 10.8045 31.6111C9.14428 33.2184 6.03136 35.134 4.68243 35.2221C3.3335 35.3102 3.02221 32.1836 3.25568 30.5983C3.38538 29.7396 4.03391 29.013 4.63055 28.3304C5.92193 26.8797 7.22722 25.4408 8.52605 23.9964C9.1287 23.3262 8.72736 22.2439 7.84552 22.0577C5.8944 21.6459 4.01156 21.0007 2.26992 20.1397C1.33605 19.6773 0.402174 19.0829 0.0908825 18.2021C-0.171362 17.413 0.179871 16.568 0.560645 15.804C0.626616 15.6716 0.719267 15.5541 0.821667 15.4474C0.936565 15.3277 1.05368 15.2091 1.23228 15.1636C1.43981 15.1196 1.64734 15.1857 1.82893 15.2517C3.87826 15.9343 6.0573 16.3086 8.23634 16.3967C8.39199 16.3967 8.52169 16.3746 8.6514 16.3306C9.0924 16.1545 9.01457 15.8022 8.91081 15.4939C8.36605 14.0187 7.19871 12.7637 6.03136 11.5747C4.73431 10.2536 3.46321 8.91052 2.16616 7.58943C1.25823 6.64266 0.324351 5.25552 1.25823 4.30874C2.16616 3.42802 3.85232 3.8904 5.07155 4.44085C7.95099 5.67386 11.1725 10.0471 12.7925 8.25943\"\n      fill=\"#ECE7BD\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 52 / 40,\n  svg: YellowFlowerBanner,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tips-for-throwing-an-outdoor-luau/yellowWavyLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Yellow Wavy Line', 'sticker name', 'web-stories');\n\nconst YellowWavyLine = ({ style }: StickerProps) => (\n  <svg\n    style={style}\n    viewBox=\"0 0 50 4\"\n    fill=\"none\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <title>{title}</title>\n    <path\n      fillRule=\"evenodd\"\n      clipRule=\"evenodd\"\n      d=\"M0.955261 1.06791C0.955261 0.478118 1.43338 0 2.02317 0C4.52148 0 5.81898 0.52048 7.02672 1.01042L7.04781 1.01898C8.1308 1.45834 9.13116 1.86419 11.2139 1.86419C13.3101 1.86419 14.3152 1.45643 15.3992 1.01665L15.4146 1.01042C16.6211 0.520964 17.9145 0 20.4046 0C22.903 0 24.2005 0.52048 25.4082 1.01042L25.4293 1.01898C26.5123 1.45834 27.5126 1.86419 29.5954 1.86419C31.6916 1.86419 32.6967 1.45643 33.7807 1.01665L33.7961 1.01042C35.0026 0.520964 36.296 0 38.7861 0C41.2759 0 42.5735 0.520752 43.7823 1.01015L43.8 1.01732C44.8866 1.45728 45.8915 1.86419 47.9769 1.86419C48.5667 1.86419 49.0448 2.34231 49.0448 2.93209C49.0448 3.52188 48.5667 4 47.9769 4C45.4871 4 44.1895 3.47925 42.9807 2.98985L42.963 2.98268C41.8764 2.54272 40.8714 2.13581 38.7861 2.13581C36.7034 2.13581 35.703 2.54166 34.62 2.98103L34.5989 2.98958C33.3912 3.47952 32.0937 4 29.5954 4C27.1053 4 25.8119 3.47904 24.6053 2.98958L24.59 2.98335C23.5059 2.54357 22.5008 2.13581 20.4046 2.13581C18.3219 2.13581 17.3215 2.54166 16.2386 2.98102L16.2175 2.98958C15.0097 3.47952 13.7122 4 11.2139 4C8.72379 4 7.43039 3.47904 6.22384 2.98958L6.20849 2.98335C5.12443 2.54357 4.11933 2.13581 2.02317 2.13581C1.43338 2.13581 0.955261 1.65769 0.955261 1.06791Z\"\n      fill=\"#ECE7BD\"\n    />\n  </svg>\n);\n\nexport default {\n  aspectRatio: 50 / 4,\n  svg: YellowWavyLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tv-show-recap/curvedDottedLine.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Curved Dotted Line', 'sticker name', 'web-stories');\n\nfunction CurvedDottedLine({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 43 51\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M42.2375 1.03526C42.2255 1.28332 42.2133 1.52441 42.2008 1.75938C42.1901 1.96124 42.345 2.1336 42.5469 2.14434C42.7488 2.15509 42.9211 2.00015 42.9319 1.79828C42.9444 1.56198 42.9567 1.31964 42.9687 1.07045C42.9784 0.868524 42.8226 0.696962 42.6207 0.687246C42.4187 0.67753 42.2472 0.83334 42.2375 1.03526ZM42.4556 3.58841C42.254 3.57301 42.0782 3.72392 42.0628 3.92549C42.0249 4.42106 41.9835 4.89678 41.9374 5.36473C41.9176 5.56591 42.0646 5.74506 42.2658 5.76489C42.4669 5.78471 42.6461 5.63769 42.6659 5.43651C42.7126 4.96288 42.7544 4.48181 42.7927 3.98127C42.8081 3.7797 42.6572 3.60382 42.4556 3.58841ZM42.0979 7.20205C41.8976 7.17517 41.7134 7.31581 41.6865 7.51617C41.6549 7.75158 41.6217 7.98975 41.5867 8.23219C41.5547 8.45403 41.5203 8.68085 41.4834 8.91238C41.4515 9.11201 41.5875 9.29965 41.7871 9.3315C41.9868 9.36335 42.1744 9.22734 42.2063 9.02771C42.2438 8.79261 42.2787 8.5622 42.3113 8.33675C42.3466 8.09204 42.3801 7.85145 42.4121 7.61349C42.4389 7.41314 42.2983 7.22893 42.0979 7.20205ZM41.5456 10.6637C41.3475 10.6237 41.1544 10.7518 41.1143 10.95C41.0255 11.389 40.9286 11.8398 40.8229 12.3008C40.7777 12.4978 40.9008 12.6942 41.0979 12.7394C41.2949 12.7845 41.4913 12.6614 41.5364 12.4644C41.6435 11.9971 41.7418 11.5402 41.8318 11.095C41.8719 10.8969 41.7437 10.7038 41.5456 10.6637ZM40.7704 14.0532C40.5752 14.0007 40.3743 14.1163 40.3218 14.3115C40.2042 14.7481 40.0791 15.1914 39.9461 15.6405C39.8887 15.8343 39.9993 16.0379 40.1931 16.0954C40.3869 16.1528 40.5906 16.0422 40.648 15.8483C40.7828 15.3933 40.9095 14.9442 41.0286 14.5018C41.0812 14.3066 40.9656 14.1058 40.7704 14.0532ZM39.7846 17.3854C39.593 17.3208 39.3853 17.4236 39.3207 17.6152C39.1753 18.046 39.0226 18.4806 38.8624 18.9181C38.7929 19.108 38.8904 19.3182 39.0802 19.3877C39.2701 19.4572 39.4803 19.3597 39.5498 19.1698C39.7122 18.7263 39.8669 18.2859 40.0143 17.8493C40.079 17.6578 39.9761 17.4501 39.7846 17.3854ZM38.5898 20.6506C38.4028 20.5737 38.1889 20.663 38.1121 20.8499C37.9387 21.2716 37.7582 21.6949 37.5702 22.1192C37.4884 22.3041 37.5718 22.5203 37.7567 22.6021C37.9415 22.684 38.1577 22.6005 38.2396 22.4157C38.4302 21.9852 38.6133 21.5559 38.7891 21.1283C38.866 20.9414 38.7768 20.7275 38.5898 20.6506ZM37.1831 23.8285C37.0018 23.739 36.7823 23.8135 36.6929 23.9947C36.4906 24.4045 36.2812 24.8144 36.0644 25.2236C35.9698 25.4023 36.0379 25.6238 36.2165 25.7184C36.3951 25.8131 36.6167 25.745 36.7113 25.5663C36.9314 25.1507 37.1441 24.7347 37.3493 24.3187C37.4388 24.1374 37.3644 23.918 37.1831 23.8285ZM35.5567 26.9002C35.3824 26.7977 35.1581 26.8559 35.0556 27.0301C34.8237 27.4243 34.5845 27.8172 34.3379 28.2082C34.2301 28.3792 34.2813 28.6052 34.4522 28.7131C34.6232 28.8209 34.8493 28.7697 34.9571 28.5987C35.2078 28.2012 35.4509 27.8019 35.6866 27.4013C35.7891 27.2271 35.7309 27.0027 35.5567 26.9002ZM33.7031 29.8405C33.5375 29.7245 33.3093 29.7648 33.1934 29.9304C33.0618 30.1183 32.9284 30.3056 32.7932 30.4921C32.6537 30.6844 32.5143 30.8745 32.3749 31.0625C32.2545 31.2249 32.2886 31.4541 32.451 31.5745C32.6133 31.695 32.8426 31.6609 32.963 31.4985C33.1039 31.3085 33.2449 31.1162 33.3858 30.9218C33.5235 30.732 33.6592 30.5414 33.793 30.3503C33.909 30.1847 33.8687 29.9564 33.7031 29.8405ZM31.6109 32.669C31.4527 32.5432 31.2224 32.5694 31.0966 32.7276C30.8014 33.0986 30.5061 33.4604 30.2108 33.8133C30.0811 33.9684 30.1016 34.1992 30.2566 34.329C30.4117 34.4587 30.6425 34.4382 30.7722 34.2832C31.0715 33.9255 31.3705 33.559 31.6694 33.1834C31.7953 33.0252 31.7691 32.7949 31.6109 32.669ZM29.3477 35.3728C29.198 35.2369 28.9666 35.2482 28.8307 35.3979C28.5126 35.7484 28.1943 36.0891 27.8756 36.4206C27.7355 36.5663 27.7401 36.798 27.8858 36.9381C28.0315 37.0782 28.2632 37.0737 28.4033 36.928C28.727 36.5914 29.0501 36.2455 29.3728 35.8898C29.5087 35.7401 29.4974 35.5087 29.3477 35.3728ZM26.9076 37.9103C26.7686 37.7636 26.5369 37.7575 26.3902 37.8966C26.0473 38.2217 25.7037 38.5369 25.3595 38.8426C25.2083 38.9768 25.1946 39.2082 25.3288 39.3593C25.463 39.5105 25.6943 39.5242 25.8455 39.39C26.1958 39.079 26.5452 38.7584 26.8939 38.4278C27.0406 38.2887 27.0467 38.057 26.9076 37.9103ZM24.2713 40.2513C24.145 40.0934 23.9147 40.0678 23.7568 40.1941C23.3896 40.4878 23.0214 40.7717 22.6519 41.0465C22.4897 41.1671 22.4559 41.3964 22.5766 41.5586C22.6972 41.7208 22.9265 41.7545 23.0887 41.6339C23.4651 41.3541 23.8402 41.0649 24.2141 40.7658C24.372 40.6395 24.3976 40.4092 24.2713 40.2513ZM21.4441 42.3542C21.3324 42.1858 21.1052 42.1397 20.9367 42.2514C20.5461 42.5105 20.1537 42.7604 19.7595 43.002C19.5872 43.1076 19.5331 43.3329 19.6387 43.5053C19.7443 43.6777 19.9696 43.7318 20.142 43.6262C20.5435 43.3801 20.9432 43.1255 21.3413 42.8616C21.5098 42.7499 21.5558 42.5227 21.4441 42.3542ZM18.4409 44.1965C18.3444 44.0189 18.1222 43.9531 17.9445 44.0496C17.5337 44.2727 17.1207 44.4881 16.7051 44.6963C16.5244 44.7869 16.4513 45.0068 16.5419 45.1875C16.6325 45.3683 16.8524 45.4414 17.0331 45.3508C17.4557 45.139 17.8759 44.92 18.294 44.6929C18.4716 44.5964 18.5374 44.3741 18.4409 44.1965ZM15.2915 45.7777C15.2093 45.593 14.9929 45.5099 14.8082 45.592C14.3823 45.7815 13.9535 45.9649 13.5216 46.1429C13.3347 46.22 13.2457 46.4339 13.3227 46.6208C13.3997 46.8077 13.6137 46.8968 13.8006 46.8198C14.2384 46.6393 14.6734 46.4533 15.1058 46.2609C15.2905 46.1787 15.3736 45.9624 15.2915 45.7777ZM12.0346 47.1234C11.9644 46.9338 11.7538 46.837 11.5642 46.9072C11.1276 47.0689 10.6876 47.2263 10.2443 47.3801C10.0533 47.4464 9.95217 47.6549 10.0184 47.8459C10.0847 48.0369 10.2932 48.138 10.4842 48.0717C10.932 47.9163 11.3767 47.7572 11.8184 47.5937C12.008 47.5235 12.1048 47.3129 12.0346 47.1234ZM8.70618 48.2814C8.64478 48.0888 8.43887 47.9824 8.24626 48.0438C7.80269 48.1852 7.35555 48.3242 6.90465 48.4614C6.71125 48.5202 6.60217 48.7247 6.661 48.9181C6.71985 49.1115 6.92432 49.2206 7.11773 49.1617C7.5714 49.0237 8.02164 48.8838 8.46861 48.7413C8.66121 48.6799 8.76758 48.474 8.70618 48.2814ZM5.33512 49.3097C5.27912 49.1155 5.07627 49.0034 4.88203 49.0594C4.43451 49.1884 3.98326 49.3166 3.52809 49.4446C3.33348 49.4994 3.22009 49.7015 3.27481 49.8961C3.32954 50.0907 3.53166 50.2041 3.72626 50.1494C4.18267 50.021 4.63547 49.8924 5.0848 49.7628C5.27904 49.7068 5.39111 49.504 5.33512 49.3097ZM1.94268 50.2659C1.889 50.071 1.68748 49.9566 1.49259 50.0103C1.26639 50.0726 1.03923 50.135 0.811072 50.1977C0.616146 50.2513 0.501538 50.4527 0.555094 50.6476C0.608649 50.8426 0.810088 50.9572 1.00501 50.9036C1.23326 50.8409 1.4606 50.7784 1.68701 50.716C1.88191 50.6623 1.99637 50.4608 1.94268 50.2659Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 43 / 51,\n  svg: CurvedDottedLine,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tv-show-recap/discPieChart.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Disc Pie Chart', 'sticker name', 'web-stories');\n\nfunction DiscPieChart({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 50\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M45.6547 25C45.6547 27.7124 45.1204 30.3983 44.0824 32.9042C43.0444 35.4101 41.523 37.6871 39.6051 39.6051C37.6871 41.523 35.4101 43.0444 32.9042 44.0824C30.3983 45.1204 27.7124 45.6547 25 45.6547C22.2876 45.6547 19.6017 45.1204 17.0958 44.0824C14.5899 43.0444 12.3129 41.523 10.3949 39.6051C8.47697 37.6871 6.95556 35.4101 5.91757 32.9042C4.87957 30.3983 4.34532 27.7124 4.34532 25C4.34532 22.2876 4.87957 19.6017 5.91757 17.0958C6.95556 14.5899 8.47697 12.3129 10.3949 10.3949C12.3129 8.47697 14.5899 6.95556 17.0958 5.91756C19.6017 4.87957 22.2876 4.34532 25 4.34532C27.7124 4.34532 30.3983 4.87957 32.9042 5.91757C35.4101 6.95556 37.6871 8.47697 39.6051 10.3949C41.523 12.3129 43.0444 14.5899 44.0824 17.0958C45.1204 19.6017 45.6547 22.2876 45.6547 25L45.6547 25Z\"\n        stroke=\"#71665C\"\n        strokeWidth=\"8.69064\"\n      />\n      <path\n        d=\"M20.5031 45.1592C15.485 44.0398 11.0647 41.0891 8.10655 36.8839C5.14836 32.6787 3.86489 27.5214 4.50707 22.4202C5.14924 17.319 7.67088 12.6407 11.579 9.2999C15.4872 5.95909 20.5008 4.19598 25.6398 4.35523\"\n        stroke=\"#FFF172\"\n        strokeWidth=\"8.69064\"\n      />\n      <path\n        d=\"M4.72045 28.9186C3.72376 23.7606 4.72999 18.4166 7.53435 13.9743C10.3387 9.53194 14.7304 6.32514 19.8157 5.00653\"\n        stroke=\"#72AAFF\"\n        strokeWidth=\"8.69064\"\n      />\n      <path\n        d=\"M18.1489 5.51465C22.0028 4.15964 26.1719 3.97786 30.129 4.99228C34.0862 6.00671 37.6537 8.17179 40.3803 11.2137C43.107 14.2557 44.8704 18.0378 45.4475 22.082C46.0246 26.1261 45.3896 30.2506 43.6226 33.9338\"\n        stroke=\"#A3978E\"\n        strokeWidth=\"8.69064\"\n      />\n      <path\n        d=\"M24.437 4.353C25.3022 4.32941 26.168 4.36022 27.0292 4.44525\"\n        stroke=\"#A3978E\"\n        strokeWidth=\"8.69064\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 50,\n  svg: DiscPieChart,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tv-show-recap/dottedDiamond.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Dotted Diamond', 'sticker name', 'web-stories');\n\nfunction DottedDiamond({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 58 58\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M1.05544 29.1443L0.911133 29L1.05467 28.8565L1.19779 28.9996L1.19737 29L1.19856 29.0012L1.05544 29.1443ZM1.62877 28.2824L1.34172 28.5694L1.48484 28.7125L1.77189 28.4255L1.62877 28.2824ZM1.91582 27.9953L2.05894 28.1384L2.34599 27.8514L2.20287 27.7083L1.91582 27.9953ZM2.48993 27.4212L2.63305 27.5643L2.9201 27.2773L2.77698 27.1342L2.48993 27.4212ZM3.06403 26.8471L3.20715 26.9902L3.4942 26.7032L3.35108 26.5601L3.06403 26.8471ZM3.63813 26.273L3.78125 26.4161L4.0683 26.1291L3.92519 25.9859L3.63813 26.273ZM4.21224 25.6989L4.35536 25.842L4.64241 25.555L4.49929 25.4118L4.21224 25.6989ZM4.78634 25.1248L4.92946 25.2679L5.21651 24.9809L5.07339 24.8377L4.78634 25.1248ZM5.36044 24.5507L5.50356 24.6938L5.79062 24.4068L5.6475 24.2636L5.36044 24.5507ZM5.93455 23.9766L6.07767 24.1197L6.36472 23.8327L6.2216 23.6895L5.93455 23.9766ZM6.50865 23.4025L6.65177 23.5456L6.93882 23.2585L6.7957 23.1154L6.50865 23.4025ZM7.08276 22.8284L7.22588 22.9715L7.51293 22.6844L7.36981 22.5413L7.08276 22.8284ZM7.65686 22.2543L7.79998 22.3974L8.08703 22.1103L7.94391 21.9672L7.65686 22.2543ZM8.23096 21.6802L8.37408 21.8233L8.66113 21.5362L8.51802 21.3931L8.23096 21.6802ZM8.80507 21.1061L8.94819 21.2492L9.23524 20.9621L9.09212 20.819L8.80507 21.1061ZM9.37917 20.532L9.52229 20.6751L9.80934 20.388L9.66622 20.2449L9.37917 20.532ZM9.95327 19.9579L10.0964 20.101L10.3834 19.8139L10.2403 19.6708L9.95327 19.9579ZM10.5274 19.3838L10.6705 19.5269L10.9575 19.2398L10.8144 19.0967L10.5274 19.3838ZM11.1015 18.8097L11.2446 18.9528L11.5317 18.6657L11.3885 18.5226L11.1015 18.8097ZM11.6756 18.2355L11.8187 18.3787L12.1058 18.0916L11.9626 17.9485L11.6756 18.2355ZM12.2497 17.6614L12.3928 17.8046L12.6799 17.5175L12.5367 17.3744L12.2497 17.6614ZM12.8238 17.0873L12.9669 17.2305L13.254 16.9434L13.1108 16.8003L12.8238 17.0873ZM13.3979 16.5132L13.541 16.6564L13.8281 16.3693L13.6849 16.2262L13.3979 16.5132ZM13.972 15.9391L14.1151 16.0823L14.4022 15.7952L14.2591 15.6521L13.972 15.9391ZM14.5461 15.365L14.6892 15.5081L14.9763 15.2211L14.8332 15.078L14.5461 15.365ZM15.1202 14.7909L15.2633 14.934L15.5504 14.647L15.4073 14.5039L15.1202 14.7909ZM15.6943 14.2168L15.8374 14.3599L16.1245 14.0729L15.9814 13.9298L15.6943 14.2168ZM16.2684 13.6427L16.4115 13.7858L16.6986 13.4988L16.5555 13.3557L16.2684 13.6427ZM16.8425 13.0686L16.9856 13.2117L17.2727 12.9247L17.1296 12.7816L16.8425 13.0686ZM17.4166 12.4945L17.5597 12.6376L17.8468 12.3506L17.7037 12.2075L17.4166 12.4945ZM17.9907 11.9204L18.1338 12.0635L18.4209 11.7765L18.2778 11.6334L17.9907 11.9204ZM18.5648 11.3463L18.7079 11.4894L18.995 11.2024L18.8519 11.0593L18.5648 11.3463ZM19.1389 10.7722L19.2821 10.9153L19.5691 10.6283L19.426 10.4851L19.1389 10.7722ZM19.713 10.1981L19.8562 10.3412L20.1432 10.0542L20.0001 9.91104L19.713 10.1981ZM20.2871 9.62399L20.4303 9.76711L20.7173 9.48006L20.5742 9.33694L20.2871 9.62399ZM20.8612 9.04989L21.0044 9.19301L21.2914 8.90596L21.1483 8.76284L20.8612 9.04989ZM21.4353 8.47578L21.5785 8.6189L21.8655 8.33185L21.7224 8.18873L21.4353 8.47578ZM22.0095 7.90168L22.1526 8.0448L22.4396 7.75775L22.2965 7.61463L22.0095 7.90168ZM22.5836 7.32758L22.7267 7.4707L23.0137 7.18365L22.8706 7.04053L22.5836 7.32758ZM23.1577 6.75347L23.3008 6.89659L23.5878 6.60954L23.4447 6.46642L23.1577 6.75347ZM23.7318 6.17937L23.8749 6.32249L24.1619 6.03544L24.0188 5.89232L23.7318 6.17937ZM24.3059 5.60527L24.449 5.74839L24.736 5.46134L24.5929 5.31822L24.3059 5.60527ZM24.88 5.03116L25.0231 5.17428L25.3101 4.88723L25.167 4.74411L24.88 5.03116ZM25.4541 4.45706L25.5972 4.60018L25.8842 4.31313L25.7411 4.17001L25.4541 4.45706ZM26.0282 3.88295L26.1713 4.02607L26.4583 3.73902L26.3152 3.5959L26.0282 3.88295ZM26.6023 3.30885L26.7454 3.45197L27.0325 3.16492L26.8893 3.0218L26.6023 3.30885ZM27.1764 2.73475L27.3195 2.87787L27.6066 2.59082L27.4634 2.4477L27.1764 2.73475ZM27.7505 2.16064L27.8936 2.30376L28.1807 2.01671L28.0375 1.87359L27.7505 2.16064ZM28.3246 1.58654L28.4677 1.72966L28.7548 1.44261L28.6116 1.29949L28.3246 1.58654ZM28.8987 1.01244L29.0418 1.15556L29.0422 1.15515L29.0434 1.15632L29.1865 1.0132L29.0422 0.868912L28.8987 1.01244ZM29.4751 1.30181L29.332 1.44493L29.6206 1.73355L29.7637 1.59043L29.4751 1.30181ZM30.0524 1.87904L29.9092 2.02216L30.1978 2.31078L30.341 2.16766L30.0524 1.87904ZM30.6296 2.45627L30.4865 2.59939L30.7751 2.88801L30.9182 2.74489L30.6296 2.45627ZM31.2068 3.0335L31.0637 3.17662L31.3523 3.46524L31.4954 3.32212L31.2068 3.0335ZM31.784 3.61074L31.6409 3.75385L31.9295 4.04247L32.0727 3.89935L31.784 3.61074ZM32.3613 4.18797L32.2182 4.33109L32.5068 4.6197L32.6499 4.47658L32.3613 4.18797ZM32.9385 4.7652L32.7954 4.90832L33.084 5.19693L33.2271 5.05381L32.9385 4.7652ZM33.5157 5.34243L33.3726 5.48555L33.6612 5.77416L33.8044 5.63104L33.5157 5.34243ZM34.093 5.91966L33.9499 6.06278L34.2385 6.35139L34.3816 6.20827L34.093 5.91966ZM34.6702 6.49689L34.5271 6.64001L34.8157 6.92863L34.9588 6.78551L34.6702 6.49689ZM35.2474 7.07412L35.1043 7.21724L35.3929 7.50585L35.536 7.36274L35.2474 7.07412ZM35.8247 7.65135L35.6815 7.79447L35.9702 8.08309L36.1133 7.93997L35.8247 7.65135ZM36.4019 8.22858L36.2588 8.3717L36.5474 8.66032L36.6905 8.5172L36.4019 8.22858ZM36.9791 8.80581L36.836 8.94893L37.1246 9.23755L37.2677 9.09443L36.9791 8.80581ZM37.5564 9.38304L37.4132 9.52616L37.7019 9.81478L37.845 9.67166L37.5564 9.38304ZM38.1336 9.96027L37.9905 10.1034L38.2791 10.392L38.4222 10.2489L38.1336 9.96027ZM38.7108 10.5375L38.5677 10.6806L38.8563 10.9692L38.9994 10.8261L38.7108 10.5375ZM39.288 11.1147L39.1449 11.2579L39.4335 11.5465L39.5767 11.4034L39.288 11.1147ZM39.8653 11.692L39.7222 11.8351L40.0108 12.1237L40.1539 11.9806L39.8653 11.692ZM40.4425 12.2692L40.2994 12.4123L40.588 12.7009L40.7311 12.5578L40.4425 12.2692ZM41.0197 12.8464L40.8766 12.9895L41.1652 13.2782L41.3084 13.135L41.0197 12.8464ZM41.597 13.4237L41.4538 13.5668L41.7425 13.8554L41.8856 13.7123L41.597 13.4237ZM42.1742 14.0009L42.0311 14.144L42.3197 14.4326L42.4628 14.2895L42.1742 14.0009ZM42.7514 14.5781L42.6083 14.7212L42.8969 15.0099L43.04 14.8667L42.7514 14.5781ZM43.3287 15.1554L43.1855 15.2985L43.4742 15.5871L43.6173 15.444L43.3287 15.1554ZM43.9059 15.7326L43.7628 15.8757L44.0514 16.1643L44.1945 16.0212L43.9059 15.7326ZM44.4831 16.3098L44.34 16.4529L44.6286 16.7415L44.7717 16.5984L44.4831 16.3098ZM45.0604 16.887L44.9172 17.0302L45.2059 17.3188L45.349 17.1757L45.0604 16.887ZM45.6376 17.4643L45.4945 17.6074L45.7831 17.896L45.9262 17.7529L45.6376 17.4643ZM46.2148 18.0415L46.0717 18.1846L46.3603 18.4732L46.5034 18.3301L46.2148 18.0415ZM46.792 18.6187L46.6489 18.7619L46.9375 19.0505L47.0807 18.9074L46.792 18.6187ZM47.3693 19.196L47.2262 19.3391L47.5148 19.6277L47.6579 19.4846L47.3693 19.196ZM47.9465 19.7732L47.8034 19.9163L48.092 20.2049L48.2351 20.0618L47.9465 19.7732ZM48.5237 20.3504L48.3806 20.4935L48.6692 20.7822L48.8124 20.639L48.5237 20.3504ZM49.101 20.9277L48.9578 21.0708L49.2465 21.3594L49.3896 21.2163L49.101 20.9277ZM49.6782 21.5049L49.5351 21.648L49.8237 21.9366L49.9668 21.7935L49.6782 21.5049ZM50.2554 22.0821L50.1123 22.2252L50.4009 22.5138L50.544 22.3707L50.2554 22.0821ZM50.8327 22.6593L50.6895 22.8025L50.9782 23.0911L51.1213 22.948L50.8327 22.6593ZM51.4099 23.2366L51.2668 23.3797L51.5554 23.6683L51.6985 23.5252L51.4099 23.2366ZM51.9871 23.8138L51.844 23.9569L52.1326 24.2455L52.2757 24.1024L51.9871 23.8138ZM52.5643 24.391L52.4212 24.5342L52.7098 24.8228L52.853 24.6797L52.5643 24.391ZM53.1416 24.9683L52.9985 25.1114L53.2871 25.4L53.4302 25.2569L53.1416 24.9683ZM53.7188 25.5455L53.5757 25.6886L53.8643 25.9772L54.0074 25.8341L53.7188 25.5455ZM54.296 26.1227L54.1529 26.2658L54.4415 26.5545L54.5846 26.4113L54.296 26.1227ZM54.8733 26.7L54.7301 26.8431L55.0188 27.1317L55.1619 26.9886L54.8733 26.7ZM55.4505 27.2772L55.3074 27.4203L55.596 27.7089L55.7391 27.5658L55.4505 27.2772ZM56.0277 27.8544L55.8846 27.9975L56.1732 28.2861L56.3163 28.143L56.0277 27.8544ZM56.605 28.4316L56.4618 28.5748L56.7504 28.8634L56.8936 28.7203L56.605 28.4316ZM57.1822 29.0089L57.0391 29.152L57.0403 29.1532L57.0398 29.1536L57.183 29.2967L57.3265 29.1532L57.1822 29.0089ZM56.8959 29.5838L56.7528 29.4406L56.4657 29.7277L56.6089 29.8708L56.8959 29.5838ZM56.3218 30.1579L56.1787 30.0148L55.8916 30.3018L56.0348 30.4449L56.3218 30.1579ZM55.7477 30.732L55.6046 30.5889L55.3175 30.8759L55.4606 31.019L55.7477 30.732ZM55.1736 31.3061L55.0305 31.163L54.7434 31.45L54.8865 31.5931L55.1736 31.3061ZM54.5995 31.8802L54.4564 31.7371L54.1693 32.0241L54.3124 32.1672L54.5995 31.8802ZM54.0254 32.4543L53.8823 32.3112L53.5952 32.5982L53.7383 32.7413L54.0254 32.4543ZM53.4513 33.0284L53.3082 32.8853L53.0211 33.1723L53.1642 33.3154L53.4513 33.0284ZM52.8772 33.6025L52.7341 33.4594L52.447 33.7464L52.5901 33.8895L52.8772 33.6025ZM52.3031 34.1766L52.16 34.0335L51.8729 34.3205L52.016 34.4637L52.3031 34.1766ZM51.729 34.7507L51.5859 34.6076L51.2988 34.8946L51.4419 35.0378L51.729 34.7507ZM51.1549 35.3248L51.0117 35.1817L50.7247 35.4687L50.8678 35.6119L51.1549 35.3248ZM50.5808 35.8989L50.4376 35.7558L50.1506 36.0428L50.2937 36.186L50.5808 35.8989ZM50.0067 36.473L49.8635 36.3299L49.5765 36.6169L49.7196 36.7601L50.0067 36.473ZM49.4326 37.0471L49.2894 36.904L49.0024 37.191L49.1455 37.3342L49.4326 37.0471ZM48.8585 37.6212L48.7153 37.4781L48.4283 37.7651L48.5714 37.9083L48.8585 37.6212ZM48.2844 38.1953L48.1412 38.0522L47.8542 38.3393L47.9973 38.4824L48.2844 38.1953ZM47.7102 38.7694L47.5671 38.6263L47.2801 38.9134L47.4232 39.0565L47.7102 38.7694ZM47.1361 39.3435L46.993 39.2004L46.706 39.4875L46.8491 39.6306L47.1361 39.3435ZM46.562 39.9176L46.4189 39.7745L46.1319 40.0616L46.275 40.2047L46.562 39.9176ZM45.9879 40.4917L45.8448 40.3486L45.5578 40.6357L45.7009 40.7788L45.9879 40.4917ZM45.4138 41.0658L45.2707 40.9227L44.9837 41.2098L45.1268 41.3529L45.4138 41.0658ZM44.8397 41.6399L44.6966 41.4968L44.4096 41.7839L44.5527 41.927L44.8397 41.6399ZM44.2656 42.2141L44.1225 42.0709L43.8355 42.358L43.9786 42.5011L44.2656 42.2141ZM43.6915 42.7882L43.5484 42.645L43.2613 42.9321L43.4045 43.0752L43.6915 42.7882ZM43.1174 43.3623L42.9743 43.2191L42.6872 43.5062L42.8304 43.6493L43.1174 43.3623ZM42.5433 43.9364L42.4002 43.7932L42.1131 44.0803L42.2563 44.2234L42.5433 43.9364ZM41.9692 44.5105L41.8261 44.3673L41.539 44.6544L41.6822 44.7975L41.9692 44.5105ZM41.3951 45.0846L41.252 44.9414L40.9649 45.2285L41.1081 45.3716L41.3951 45.0846ZM40.821 45.6587L40.6779 45.5155L40.3908 45.8026L40.534 45.9457L40.821 45.6587ZM40.2469 46.2328L40.1038 46.0897L39.8167 46.3767L39.9598 46.5198L40.2469 46.2328ZM39.6728 46.8069L39.5297 46.6638L39.2426 46.9508L39.3857 47.0939L39.6728 46.8069ZM39.0987 47.381L38.9556 47.2379L38.6685 47.5249L38.8116 47.668L39.0987 47.381ZM38.5246 47.9551L38.3815 47.812L38.0944 48.099L38.2375 48.2421L38.5246 47.9551ZM37.9505 48.5292L37.8074 48.3861L37.5203 48.6731L37.6634 48.8162L37.9505 48.5292ZM37.3764 49.1033L37.2333 48.9602L36.9462 49.2472L37.0893 49.3903L37.3764 49.1033ZM36.8023 49.6774L36.6592 49.5343L36.3721 49.8213L36.5152 49.9644L36.8023 49.6774ZM36.2282 50.2515L36.0851 50.1084L35.798 50.3954L35.9411 50.5386L36.2282 50.2515ZM35.6541 50.8256L35.5109 50.6825L35.2239 50.9695L35.367 51.1127L35.6541 50.8256ZM35.08 51.3997L34.9368 51.2566L34.6498 51.5436L34.7929 51.6868L35.08 51.3997ZM34.5059 51.9738L34.3627 51.8307L34.0757 52.1177L34.2188 52.2609L34.5059 51.9738ZM33.9318 52.5479L33.7886 52.4048L33.5016 52.6918L33.6447 52.835L33.9318 52.5479ZM33.3577 53.122L33.2145 52.9789L32.9275 53.2659L33.0706 53.4091L33.3577 53.122ZM32.7836 53.6961L32.6404 53.553L32.3534 53.8401L32.4965 53.9832L32.7836 53.6961ZM32.2094 54.2702L32.0663 54.1271L31.7793 54.4142L31.9224 54.5573L32.2094 54.2702ZM31.6353 54.8443L31.4922 54.7012L31.2052 54.9883L31.3483 55.1314L31.6353 54.8443ZM31.0612 55.4184L30.9181 55.2753L30.6311 55.5624L30.7742 55.7055L31.0612 55.4184ZM30.4871 55.9925L30.344 55.8494L30.057 56.1365L30.2001 56.2796L30.4871 55.9925ZM29.913 56.5666L29.7699 56.4235L29.4829 56.7106L29.626 56.8537L29.913 56.5666ZM29.3389 57.1407L29.1958 56.9976L29.1954 56.998L29.1942 56.9969L29.0511 57.14L29.1954 57.2843L29.3389 57.1407ZM28.7625 56.8514L28.9056 56.7082L28.617 56.4196L28.4739 56.5628L28.7625 56.8514ZM28.1853 56.2741L28.3284 56.131L28.0398 55.8424L27.8967 55.9855L28.1853 56.2741ZM27.608 55.6969L27.7512 55.5538L27.4625 55.2652L27.3194 55.4083L27.608 55.6969ZM27.0308 55.1197L27.1739 54.9766L26.8853 54.6879L26.7422 54.8311L27.0308 55.1197ZM26.4536 54.5424L26.5967 54.3993L26.3081 54.1107L26.165 54.2538L26.4536 54.5424ZM25.8763 53.9652L26.0195 53.8221L25.7309 53.5335L25.5877 53.6766L25.8763 53.9652ZM25.2991 53.388L25.4422 53.2449L25.1536 52.9562L25.0105 53.0994L25.2991 53.388ZM24.7219 52.8108L24.865 52.6676L24.5764 52.379L24.4333 52.5221L24.7219 52.8108ZM24.1447 52.2335L24.2878 52.0904L23.9992 51.8018L23.856 51.9449L24.1447 52.2335ZM23.5674 51.6563L23.7105 51.5132L23.4219 51.2246L23.2788 51.3677L23.5674 51.6563ZM22.9902 51.0791L23.1333 50.9359L22.8447 50.6473L22.7016 50.7904L22.9902 51.0791ZM22.413 50.5018L22.5561 50.3587L22.2675 50.0701L22.1243 50.2132L22.413 50.5018ZM21.8357 49.9246L21.9789 49.7815L21.6902 49.4929L21.5471 49.636L21.8357 49.9246ZM21.2585 49.3474L21.4016 49.2042L21.113 48.9156L20.9699 49.0588L21.2585 49.3474ZM20.6813 48.7701L20.8244 48.627L20.5358 48.3384L20.3927 48.4815L20.6813 48.7701ZM20.104 48.1929L20.2472 48.0498L19.9585 47.7612L19.8154 47.9043L20.104 48.1929ZM19.5268 47.6157L19.6699 47.4726L19.3813 47.1839L19.2382 47.3271L19.5268 47.6157ZM18.9496 47.0384L19.0927 46.8953L18.8041 46.6067L18.661 46.7498L18.9496 47.0384ZM18.3723 46.4612L18.5155 46.3181L18.2269 46.0295L18.0837 46.1726L18.3723 46.4612ZM17.7951 45.884L17.9382 45.7409L17.6496 45.4523L17.5065 45.5954L17.7951 45.884ZM17.2179 45.3068L17.361 45.1636L17.0724 44.875L16.9293 45.0181L17.2179 45.3068ZM16.6407 44.7295L16.7838 44.5864L16.4952 44.2978L16.352 44.4409L16.6407 44.7295ZM16.0634 44.1523L16.2065 44.0092L15.9179 43.7206L15.7748 43.8637L16.0634 44.1523ZM15.4862 43.5751L15.6293 43.4319L15.3407 43.1433L15.1976 43.2864L15.4862 43.5751ZM14.909 42.9978L15.0521 42.8547L14.7635 42.5661L14.6203 42.7092L14.909 42.9978ZM14.3317 42.4206L14.4749 42.2775L14.1862 41.9889L14.0431 42.132L14.3317 42.4206ZM13.7545 41.8434L13.8976 41.7002L13.609 41.4116L13.4659 41.5548L13.7545 41.8434ZM13.1773 41.2661L13.3204 41.123L13.0318 40.8344L12.8887 40.9775L13.1773 41.2661ZM12.6 40.6889L12.7432 40.5458L12.4545 40.2572L12.3114 40.4003L12.6 40.6889ZM12.0228 40.1117L12.1659 39.9686L11.8773 39.6799L11.7342 39.8231L12.0228 40.1117ZM11.4456 39.5344L11.5887 39.3913L11.3001 39.1027L11.157 39.2458L11.4456 39.5344ZM10.8683 38.9572L11.0115 38.8141L10.7229 38.5255L10.5797 38.6686L10.8683 38.9572ZM10.2911 38.38L10.4342 38.2369L10.1456 37.9482L10.0025 38.0914L10.2911 38.38ZM9.71389 37.8028L9.85701 37.6596L9.56839 37.371L9.42527 37.5141L9.71389 37.8028ZM9.13666 37.2255L9.27978 37.0824L8.99116 36.7938L8.84804 36.9369L9.13666 37.2255ZM8.55943 36.6483L8.70255 36.5052L8.41393 36.2166L8.27081 36.3597L8.55943 36.6483ZM7.9822 36.0711L8.12532 35.9279L7.8367 35.6393L7.69358 35.7825L7.9822 36.0711ZM7.40497 35.4938L7.54809 35.3507L7.25947 35.0621L7.11635 35.2052L7.40497 35.4938ZM6.82774 34.9166L6.97086 34.7735L6.68224 34.4849L6.53912 34.628L6.82774 34.9166ZM6.25051 34.3394L6.39363 34.1963L6.10501 33.9076L5.96189 34.0508L6.25051 34.3394ZM5.67328 33.7621L5.8164 33.619L5.52778 33.3304L5.38466 33.4735L5.67328 33.7621ZM5.09605 33.1849L5.23917 33.0418L4.95055 32.7532L4.80743 32.8963L5.09605 33.1849ZM4.51882 32.6077L4.66194 32.4646L4.37332 32.176L4.23021 32.3191L4.51882 32.6077ZM3.94159 32.0305L4.08471 31.8873L3.79609 31.5987L3.65298 31.7418L3.94159 32.0305ZM3.36436 31.4532L3.50748 31.3101L3.21886 31.0215L3.07575 31.1646L3.36436 31.4532ZM2.78713 30.876L2.93025 30.7329L2.64163 30.4443L2.49852 30.5874L2.78713 30.876ZM2.2099 30.2988L2.35302 30.1556L2.0644 29.867L1.92129 30.0102L2.2099 30.2988ZM1.63267 29.7215L1.77579 29.5784L1.48718 29.2898L1.34406 29.4329L1.63267 29.7215Z\"\n        fill=\"#E5E5E5\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 58 / 58,\n  svg: DottedDiamond,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/tv-show-recap/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as curvedDottedLine } from './curvedDottedLine';\nimport { default as dottedDiamond } from './dottedDiamond';\nimport { default as discPieChart } from './discPieChart';\n\nexport { curvedDottedLine, dottedDiamond, discPieChart };\n"
  },
  {
    "path": "packages/stickers/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { CSSProperties, FunctionComponent, SVGProps } from 'react';\n\nexport interface StickerProps extends SVGProps<SVGSVGElement> {\n  style: CSSProperties;\n}\n\nexport interface Sticker {\n  aspectRatio: number;\n  svg: FunctionComponent<{ style?: CSSProperties; className?: string }>;\n  title: string;\n}\n"
  },
  {
    "path": "packages/stickers/src/vintage-chairs-what-to-look-for/chair.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Chair', 'sticker name', 'web-stories');\n\nfunction ChairIcon({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 36 54\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M25.9143 43.0641H25.1581L22.0724 33.0725C22.5213 33.0508 22.9617 33.0237 23.3943 32.9889L25.9143 43.0641ZM19.6404 32.3591C19.1079 32.3591 18.5646 32.3513 17.9888 32.3343C17.4347 32.3513 16.8929 32.3591 16.3596 32.3591C8.29283 32.3591 3.45181 30.5736 2.23207 28.802C1.8838 28.2958 1.81182 27.792 2.01382 27.265C2.03704 27.203 2.068 27.121 2.10128 27.0243C5.62737 26.4059 11.5372 26.0375 17.9996 26.0375C24.4621 26.0375 30.3719 26.4059 33.898 27.0243C33.932 27.121 33.9622 27.203 33.9862 27.265C34.1874 27.792 34.1162 28.2958 33.7672 28.8036C32.5482 30.5736 27.7072 32.3591 19.6404 32.3591ZM10.8412 43.0645H10.0851L12.6058 32.9908C13.0377 33.0241 13.4788 33.0512 13.9262 33.0729L10.8412 43.0645ZM1.74812 53.1259H0.991976L6.29736 31.919C6.87705 32.0885 7.49698 32.2425 8.15483 32.3787L1.74812 53.1259ZM8.55312 7.41483C8.63129 7.14317 8.70636 6.87074 8.77989 6.60141C9.55847 3.76723 10.231 1.32002 14.4691 0.840947C14.8213 0.799928 16.0008 0.774388 17.4736 0.774388C19.66 0.774388 21.5283 0.828564 22.0166 0.907506C25.8214 1.51196 26.4699 3.87016 27.2206 6.60064C27.2942 6.87074 27.3692 7.14162 27.4513 7.42721C27.6641 8.08429 32.1592 21.9518 33.608 26.1907C30.0007 25.6087 24.2503 25.2643 17.9999 25.2643C11.7503 25.2643 5.9991 25.6087 2.39253 26.1907C3.84057 21.951 8.33719 8.08351 8.55312 7.41483ZM35.0096 53.1259H34.2535L27.8476 32.3787C28.5046 32.2425 29.1246 32.0885 29.7042 31.919L35.0096 53.1259ZM33.6805 53.8998H36L30.4423 31.6884C32.3462 31.0452 33.7339 30.2155 34.4049 29.2419C34.8948 28.5299 35.0001 27.7521 34.7091 26.9882C34.0257 25.1973 28.2451 7.36795 28.1909 7.2C28.1135 6.93067 28.04 6.66211 27.9665 6.39587C27.2134 3.65843 26.4348 0.827346 22.1387 0.142406C21.4816 0.0379232 19.2147 0 17.4733 0C16.2799 0 14.8419 0.0185747 14.3822 0.0712028C9.62322 0.610642 8.81522 3.55085 8.03354 6.39587C7.96079 6.66211 7.88726 6.93067 7.81296 7.18762C7.75492 7.36795 1.97433 25.1973 1.29094 26.9882C0.999936 27.7505 1.10519 28.5299 1.5951 29.2419C2.26611 30.2155 3.65379 31.0452 5.55692 31.6884L0 53.8998H2.31951L8.91738 32.5296C9.82677 32.6929 10.8035 32.8214 11.8259 32.9197L9.09384 43.8385H11.4134L14.7266 33.1047C15.2622 33.1225 15.8055 33.1333 16.3596 33.1333C16.8998 33.1333 17.4501 33.1256 17.9888 33.1085C18.5499 33.1256 19.1002 33.1333 19.6404 33.1333C20.1953 33.1333 20.7371 33.1225 21.2734 33.1047L24.5866 43.8385H26.9062L24.1749 32.9197C25.1973 32.8214 26.174 32.6929 27.0834 32.5296L33.6805 53.8998Z\"\n        fill=\"#313831\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 36 / 54,\n  svg: ChairIcon,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/vintage-chairs-what-to-look-for/chair02.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Chair 02', 'sticker name', 'web-stories');\n\nfunction ChairIcon02({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 50 55\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M49.0968 17.3675L49.0194 17.3943C46.9075 18.1225 45.085 18.7512 44.1492 22.5762L44.0673 22.917C43.8582 23.7892 43.5917 24.888 43.1001 26.0612C38.367 29.9734 32.1115 32.0417 24.9991 32.0417C17.8561 32.0417 11.1197 29.821 6.97849 26.101L6.93484 26.15C6.41872 24.9439 6.14611 23.8106 5.93093 22.917L5.84899 22.5762C4.91324 18.7505 3.0892 18.1218 0.977999 17.3935L0.901423 17.3675C0.736784 17.1324 0.762055 17.0045 0.771244 16.9594C0.865432 16.493 1.91376 15.9256 3.12825 15.2701C5.21035 14.1467 8.06127 12.6068 10.3922 9.66856C11.8403 8.22127 12.9085 6.9593 13.8496 5.84665C16.8032 2.35785 18.1502 0.765839 24.9662 0.765839C31.8075 0.765839 33.1682 2.36245 36.1478 5.85967C37.092 6.96772 38.1617 8.22357 39.5776 9.63716C41.9392 12.6068 44.7894 14.146 46.87 15.2701C48.0844 15.9256 49.1328 16.4922 49.227 16.9586C49.2362 17.0045 49.2614 17.1316 49.0968 17.3675ZM26.2819 34.5415L26.2452 34.5431C25.9572 34.5469 24.039 34.5469 23.7534 34.5431L23.7166 34.5415C13.9057 34.2245 9.70552 30.9432 7.72756 27.691C12.0365 30.9134 18.3494 32.8071 24.9993 32.8071C31.6713 32.8071 37.6113 31.0206 42.307 27.6336C40.3436 30.9049 36.1502 34.223 26.2819 34.5415ZM41.8292 54.011H41.0803L34.8975 33.9864C35.5247 33.7873 36.1097 33.5698 36.6565 33.337L41.8292 54.011ZM32.8309 44.0559H32.0835L29.3176 35.1011C29.7411 35.0567 30.1538 35.0061 30.5536 34.9502L32.8309 44.0559ZM17.9176 44.0559H17.168L19.4461 34.9502C19.8466 35.0061 20.2578 35.0575 20.682 35.1011L17.9176 44.0559ZM8.92027 54.011H8.17059L13.3433 33.337C13.8901 33.5698 14.4766 33.7873 15.103 33.9864L8.92027 54.011ZM49.9787 16.8084C49.8141 15.9891 48.788 15.4354 47.235 14.5961C45.2119 13.5034 42.4421 12.0079 40.1494 9.12708C38.7251 7.70354 37.6661 6.45995 36.7311 5.36338C33.6887 1.79188 32.1618 0 24.9667 0C17.7946 0 16.1865 1.90061 13.2659 5.35189C12.334 6.45305 11.2772 7.70201 9.82307 9.16001C7.55872 12.0079 4.7882 13.5042 2.76583 14.5961C1.21134 15.4354 0.185221 15.9891 0.021348 16.8084C-0.0521649 17.176 0.0642305 17.5543 0.369768 17.9326L0.437921 18.0175L0.72891 18.1179C2.78421 18.8262 4.26901 19.3385 5.10522 22.7584L5.18716 23.0961C5.81355 25.7081 6.90782 30.2628 12.6342 33.018L7.18962 54.7771H9.48537L15.8373 34.2042C16.7095 34.45 17.6568 34.6613 18.6875 34.8329L16.1873 44.8222H18.483L21.4618 35.1736C22.1748 35.2334 22.9114 35.2824 23.6925 35.3076L23.6933 35.2885C23.9207 35.3122 24.3112 35.3122 25.0012 35.3122C25.6636 35.3122 26.0641 35.3122 26.3068 35.2885L26.3076 35.3076C27.0871 35.2824 27.8245 35.2334 28.5382 35.1736L31.517 44.8222H33.812L31.3126 34.8329C32.3433 34.6613 33.2898 34.45 34.1627 34.2042L40.5139 54.7771H42.8097L37.3651 33.018C43.0922 30.2628 44.1857 25.7081 44.8129 23.0961L44.8941 22.7584C45.7303 19.3385 47.2143 18.8262 49.2696 18.1186L49.5614 18.0175L49.6303 17.9326C49.9351 17.5543 50.0522 17.176 49.9787 16.8084Z\"\n        fill=\"#313831\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 50 / 55,\n  svg: ChairIcon02,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/vintage-chairs-what-to-look-for/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as vintageChairsIcon01 } from './chair';\nimport { default as vintageChairsIcon02 } from './chair02';\n\nexport { vintageChairsIcon01, vintageChairsIcon02 };\n"
  },
  {
    "path": "packages/stickers/src/weekly-entertainment/entertainmentStar.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Star', 'sticker name', 'web-stories');\n\nfunction Star({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 17 15\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M8.39453 0.000610352L10.1906 5.52848L16.003 5.52848L11.3007 8.94489L13.0968 14.4728L8.39453 11.0563L3.69225 14.4728L5.48836 8.94489L0.786079 5.52848L6.59842 5.52848L8.39453 0.000610352Z\"\n        fill=\"#fff\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 17 / 15,\n  svg: Star,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/src/weekly-entertainment/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as entertainmentMusicNote } from './musicNote';\nimport { default as entertainmentStar } from './entertainmentStar';\n\nexport { entertainmentMusicNote, entertainmentStar };\n"
  },
  {
    "path": "packages/stickers/src/weekly-entertainment/musicNote.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { StickerProps, Sticker } from '../types';\n\nconst title = _x('Musical Note', 'sticker name', 'web-stories');\n\nfunction MusicNote({ style }: StickerProps) {\n  return (\n    <svg\n      style={style}\n      viewBox=\"0 0 160 156\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <title>{title}</title>\n      <path\n        d=\"M108.689 66.0306C108.101 60.5262 105.23 55.8237 100.384 52.4286C90.0206 45.1653 86.8232 37.8009 86.7945 37.7323C86.4648 36.9377 85.6295 36.4898 84.7872 36.6596C83.9484 36.8293 83.3462 37.5697 83.3462 38.4293V88.8714C83.2458 88.7812 83.149 88.6909 83.0487 88.6042C79.5716 85.6642 74.3633 84.5518 68.757 85.5486C58.9138 87.2967 51.207 94.7912 51.207 102.614C51.207 105.847 52.5871 108.794 55.0891 110.911C57.7309 113.146 61.3728 114.324 65.4341 114.324C66.7138 114.324 68.0365 114.204 69.3807 113.966C79.2239 112.218 86.9343 104.724 86.9343 96.9004V58.3194C88.7266 59.8978 91.3147 61.8626 95.0032 64.6292C101.731 69.6748 99.9965 81.2 99.9785 81.312C99.8531 82.0994 100.251 82.8723 100.961 83.2226C101.67 83.573 102.524 83.4104 103.061 82.8289C107.162 78.3792 109.32 71.943 108.689 66.0306ZM68.757 110.408C64.2656 111.207 60.0143 110.358 57.394 108.14C55.6913 106.699 54.7916 104.789 54.7916 102.611C54.7916 96.5934 61.337 90.5329 69.3807 89.1026C70.492 88.904 71.5924 88.8101 72.6534 88.8101C75.8795 88.8101 78.7723 89.7022 80.7474 91.3708C82.45 92.8119 83.3498 94.7225 83.3498 96.9004C83.3462 102.921 76.8044 108.978 68.757 110.408ZM103.689 75.3273C103.323 70.9028 101.85 65.2612 97.1432 61.7325C90.6121 56.835 87.5545 54.4259 86.9307 52.8945V44.6849C89.2284 47.6863 92.8524 51.5509 98.3332 55.3939C102.301 58.1749 104.649 61.9854 105.122 66.417C105.441 69.3787 104.911 72.5029 103.689 75.3273ZM60.4516 0L68.0365 20.858L65.9647 21.6237L48.1207 8.31071L54.5012 25.8567L52.4294 26.6224L44.8444 5.7644L46.9163 4.9987L64.7495 18.2828L58.3797 0.765697L60.4516 0ZM78.844 20.4752C73.9546 20.5944 70.3091 17.2499 70.1801 11.7527C70.0475 6.2231 73.4671 2.73773 78.4174 2.61854C83.4645 2.49574 86.6404 6.04251 86.7443 10.4597C86.7623 11.1604 86.773 11.6046 86.7228 12.2078L72.4384 12.5545C72.7251 16.6178 75.582 18.6765 78.801 18.6007C81.7331 18.5284 83.6831 16.9248 84.2567 14.588L86.5902 14.5302C85.8805 17.8241 83.167 20.3704 78.844 20.4752ZM72.3954 10.745L84.504 10.4525C84.504 6.41452 81.5539 4.45332 78.3672 4.52917C75.2487 4.60141 72.5531 6.70346 72.3954 10.745ZM93.0747 2.95805L95.186 3.7093L94.254 19.3844L103.785 6.76125L105.868 7.50167L105.37 23.3646L114.374 10.5211L116.428 11.2507L105.617 25.8134L103.534 25.073L103.843 9.74819L94.5479 21.8838L92.4366 21.1325L93.0747 2.95805ZM134.842 19.5253L136.308 21.3565L126.924 39.8993L146.89 34.5611L148.377 36.414L131.444 50.1893L130.057 48.4592L143.581 37.4578L125.185 42.377L124.174 41.1165L132.774 24.0725L119.296 35.0343L117.909 33.3042L134.842 19.5253ZM136.925 67.6667L136.258 65.5466L139.143 64.6256C136.753 64.2861 134.985 62.4513 134.215 59.9953C133.035 56.239 134.387 52.5406 139.201 51.0056L148.793 47.9464L149.449 50.0376L140.097 53.0209C136.459 54.1803 135.222 56.7772 136.172 59.8075C137.143 62.8991 139.742 64.4342 143.742 63.1592L152.675 60.3095L153.342 62.4296L136.925 67.6667ZM137.104 77.2632C137.021 73.3227 138.918 70.5164 142.068 70.1624L142.115 72.4487C140.226 72.6798 138.903 74.3593 138.964 77.191C139.014 79.6686 140.369 81.0411 142.011 81.005C146.27 80.9147 143.56 70.5453 150.026 70.4044C152.582 70.3502 154.747 72.7521 154.822 76.4072C154.901 80.1237 152.998 82.6159 149.689 82.8759L149.643 80.651C151.564 80.4813 152.983 79.0221 152.93 76.3855C152.879 74.0668 151.621 72.6293 150.105 72.6618C145.438 72.7593 148.144 82.9734 142.058 83.1973C139.28 83.2551 137.179 80.8533 137.104 77.2632ZM153.751 89.3049L153.388 91.5008L136.401 88.6475L136.763 86.4516L153.751 89.3049ZM158.654 89.6155C159.586 89.7708 160.12 90.6051 159.977 91.4828C159.83 92.3604 159.059 92.9708 158.124 92.8155C157.188 92.6566 156.625 91.8223 156.769 90.9446C156.919 90.0633 157.722 89.4566 158.654 89.6155ZM149.499 105.973C147.904 110.018 144.728 111.792 141.126 111.207L142 108.993C144.495 109.376 146.671 107.989 147.743 105.273C148.99 102.112 147.861 98.6847 143.524 96.951C139.186 95.2137 136.003 96.9185 134.756 100.079C133.684 102.798 134.308 105.269 136.43 106.768L135.555 108.982C132.652 106.966 131.429 103.434 133.025 99.3853C134.817 94.8381 139.276 92.8263 144.348 94.8526C149.42 96.8788 151.295 101.422 149.499 105.973ZM99.552 156L91.967 135.142L94.0389 134.376L111.883 147.689L105.502 130.143L107.574 129.378L115.159 150.236L113.087 151.001L95.2541 137.717L101.624 155.234L99.552 156ZM81.156 135.525C86.0453 135.406 89.6909 138.75 89.8199 144.247C89.9525 149.777 86.5329 153.262 81.5826 153.381C76.5355 153.504 73.3596 149.957 73.2556 145.54C73.2377 144.84 73.227 144.395 73.2772 143.792L87.5616 143.445C87.2749 139.382 84.418 137.323 81.199 137.399C78.2669 137.472 76.3169 139.075 75.7433 141.412L73.4098 141.47C74.1195 138.176 76.8366 135.63 81.156 135.525ZM87.6046 145.259L75.496 145.551C75.496 149.589 78.4461 151.554 81.6328 151.474C84.7549 151.399 87.4505 149.3 87.6046 145.259ZM66.9289 153.046L64.8176 152.294L65.7496 136.619L56.2182 149.242L54.1356 148.502L54.6339 132.639L45.6294 145.482L43.5755 144.753L54.3865 130.19L56.4692 130.931L56.1609 146.255L65.4521 134.12L67.5634 134.871L66.9289 153.046ZM25.1616 136.475L23.6955 134.644L33.0799 116.101L13.1139 121.439L11.6263 119.586L28.5598 105.807L29.947 107.537L16.4225 118.539L34.8184 113.619L35.8293 114.88L27.2299 131.924L40.7043 120.962L42.0915 122.692L25.1616 136.475ZM23.079 88.3369L23.7457 90.457L20.8601 91.378C23.2475 91.7175 25.0182 93.5523 25.7889 96.0083C26.9682 99.7646 25.6169 103.463 20.8028 104.998L11.2105 108.057L10.5545 105.966L19.9067 102.983C23.545 101.823 24.7817 99.2264 23.8317 96.1961C22.8603 93.1045 20.2615 91.5658 16.2612 92.8444L7.32843 95.6905L6.66171 93.5704L23.079 88.3369ZM22.8998 78.7404C22.9822 82.6809 21.086 85.4872 17.9387 85.8412L17.8885 83.5549C19.7776 83.3238 21.0967 81.6407 21.0394 78.8126C20.9856 76.335 19.6342 74.9625 17.9925 74.9986C13.734 75.0889 16.4476 85.4583 9.98101 85.5992C7.42522 85.6534 5.26014 83.2515 5.18487 79.5964C5.10601 75.8799 7.00941 73.3878 10.318 73.1277L10.3646 75.3526C8.44323 75.5223 7.02375 76.9815 7.07751 79.6181C7.1277 81.9368 8.38588 83.3743 9.90215 83.3418C14.5692 83.2407 11.8629 73.0302 17.9459 72.8063C20.7203 72.7449 22.8245 75.1467 22.8998 78.7404ZM1.3458 66.3881C0.413819 66.2328 -0.120281 65.4021 0.0231018 64.5208C0.166484 63.6396 0.940749 63.0328 1.87273 63.1881C2.8083 63.3434 3.37108 64.1813 3.2277 65.059C3.08432 65.9367 2.28137 66.5434 1.3458 66.3881ZM6.25307 66.6951L6.61511 64.4992L23.6023 67.3525L23.2403 69.5484L6.25307 66.6951ZM10.5044 50.0268C12.0995 45.9816 15.2754 44.2082 18.8779 44.7933L18.0033 47.0073C15.5084 46.6245 13.3326 48.0114 12.2608 50.7274C11.0134 53.8878 12.1425 57.3153 16.4798 59.049C20.8171 60.7863 24.0002 59.0851 25.2476 55.9248C26.3194 53.2051 25.6993 50.7347 23.5737 49.2358L24.4483 47.0218C27.3518 49.0371 28.5741 52.5695 26.979 56.6183C25.1867 61.1655 20.7275 63.1772 15.6554 61.151C10.5832 59.1248 8.70849 54.5776 10.5044 50.0268Z\"\n        fill=\"#fff\"\n      />\n    </svg>\n  );\n}\n\nexport default {\n  aspectRatio: 160 / 156,\n  svg: MusicNote,\n  title,\n} as Sticker;\n"
  },
  {
    "path": "packages/stickers/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../i18n\" }, { \"path\": \"../react\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/stories-block/README.md",
    "content": "# WordPress Stories Block\n\nWeb Stories Block for use in WordPress editor.\n"
  },
  {
    "path": "packages/stories-block/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/stories-block\",\n  \"description\": \"Web Stories block\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/stories-block/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/stories-block\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"sideEffects\": [\n    \"./src/index.js\",\n    \"*.css\"\n  ],\n  \"dependencies\": {\n    \"@googleforcreators/tracking\": \"*\",\n    \"@web-stories-wp/glider\": \"*\",\n    \"@wordpress/api-fetch\": \"^7.43.0\",\n    \"@wordpress/block-editor\": \"^15.16.0\",\n    \"@wordpress/blocks\": \"^15.16.0\",\n    \"@wordpress/components\": \"^32.5.0\",\n    \"@wordpress/compose\": \"^7.22.0\",\n    \"@wordpress/core-data\": \"^7.43.0\",\n    \"@wordpress/data\": \"^10.22.0\",\n    \"@wordpress/date\": \"^5.22.0\",\n    \"@wordpress/element\": \"^6.32.0\",\n    \"@wordpress/i18n\": \"^6.16.0\",\n    \"@wordpress/icons\": \"^12.1.0\",\n    \"@wordpress/interactivity\": \"^6.22.0\",\n    \"@wordpress/notices\": \"^5.22.0\",\n    \"@wordpress/url\": \"^4.43.0\",\n    \"@wordpress/viewport\": \"^6.43.0\",\n    \"classnames\": \"^2.5.1\",\n    \"lodash\": \"^4.18.1\",\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^16.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/latest-stories/edit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Button, Placeholder } from '@wordpress/components';\nimport { BlockIcon } from '@wordpress/block-editor';\nimport { useEntityRecords } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { BlockIcon as WebStoriesLogo } from '../../icons';\nimport StoriesInspectorControls from '../../components/storiesInspectorControls';\nimport StoriesLoading from '../../components/storiesLoading';\nimport StoriesPreview from '../../components/storiesPreview';\n\n/**\n * LatestStoriesEdit component\n *\n * @param {Object}   root0               Component props.\n * @param {Object}   root0.attributes    Block attributes.\n * @param {Function} root0.setAttributes Callable function for saving attribute values.\n * @return {*} JSX markup for the editor.\n */\nfunction LatestStoriesEdit({ attributes, setAttributes }) {\n  const { numOfStories, order, orderby, archiveLinkLabel, authors, taxQuery } =\n    attributes;\n\n  const data = useEntityRecords('postType', 'web-story', {\n    per_page: 20,\n    _embed: 'author,wp:featuredmedia',\n    orderby: orderby || 'modified',\n    order: order || 'desc',\n    author: authors || undefined,\n    ...taxQuery,\n  });\n\n  const viewAllLabel = archiveLinkLabel\n    ? archiveLinkLabel\n    : __('View All Stories', 'web-stories');\n\n  const storiesToDisplay =\n    data.records?.length > numOfStories\n      ? data.records.slice(0, numOfStories)\n      : data.records;\n\n  return (\n    <>\n      <StoriesInspectorControls\n        attributes={attributes}\n        setAttributes={setAttributes}\n      />\n      {!data.hasResolved && <StoriesLoading />}\n      {data.hasResolved && Boolean(storiesToDisplay?.length) && (\n        <StoriesPreview\n          attributes={attributes}\n          stories={storiesToDisplay}\n          viewAllLabel={viewAllLabel}\n        />\n      )}\n      {data.hasResolved && !storiesToDisplay?.length && (\n        <Placeholder\n          icon={<BlockIcon icon={<WebStoriesLogo />} showColors />}\n          label={__('Latest Stories', 'web-stories')}\n          className=\"wp-block-web-stories-embed\"\n          instructions={__('No stories found.', 'web-stories')}\n        >\n          <Button\n            href={addQueryArgs('post-new.php', { post_type: 'web-story' })}\n            isLink\n          >\n            {__('Create New Story', 'web-stories')}\n          </Button>\n        </Placeholder>\n      )}\n    </>\n  );\n}\n\nLatestStoriesEdit.propTypes = {\n  attributes: PropTypes.shape({\n    blockType: PropTypes.string,\n    align: PropTypes.string,\n    viewType: PropTypes.string,\n    numOfStories: PropTypes.number,\n    numOfColumns: PropTypes.number,\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n    archiveLinkLabel: PropTypes.string,\n    authors: PropTypes.array,\n    circleSize: PropTypes.number,\n    fieldState: PropTypes.object,\n    taxQuery: PropTypes.objectOf(PropTypes.number),\n  }),\n  setAttributes: PropTypes.func.isRequired,\n};\n\nexport default LatestStoriesEdit;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/selected-stories/edit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useEffect, useCallback } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport StoriesInspectorControls from '../../components/storiesInspectorControls';\nimport StoriesPreview from '../../components/storiesPreview';\nimport FetchSelectedStories from '../../components/storyPicker/fetchSelectedStories';\nimport EmbedPlaceholder from './embedPlaceholder';\n\nfunction SelectedStoriesEdit({\n  icon,\n  attributes,\n  setAttributes,\n  isSelected: isEditing,\n}) {\n  const { stories = [], archiveLinkLabel } = attributes;\n\n  const [selectedStoryIds, setSelectedStoryIds] = useState(stories);\n  const [selectedStories, _setSelectedStories] = useState([]);\n  const [isFetching, setIsFetching] = useState(false);\n\n  const label = __('Selected Stories', 'web-stories');\n\n  const viewAllLabel = archiveLinkLabel\n    ? archiveLinkLabel\n    : __('View All Stories', 'web-stories');\n\n  useEffect(() => {\n    if (attributes.stories.toString() !== selectedStoryIds.toString()) {\n      setAttributes({\n        stories: selectedStoryIds,\n      });\n    }\n  }, [attributes.stories, setAttributes, selectedStoryIds]);\n\n  useEffect(() => {\n    if (selectedStoryIds.length && !selectedStories.length) {\n      setIsFetching(true);\n    }\n  }, [selectedStoryIds, selectedStories, setIsFetching]);\n\n  const setSelectedStories = useCallback(\n    (newStories) => {\n      _setSelectedStories(newStories);\n      setSelectedStoryIds(newStories.map((story) => story.id));\n    },\n    [_setSelectedStories]\n  );\n\n  if (isFetching) {\n    return (\n      <FetchSelectedStories\n        icon={icon}\n        label={label}\n        selectedStoryIds={selectedStoryIds}\n        setSelectedStories={setSelectedStories}\n        setIsFetching={setIsFetching}\n      />\n    );\n  }\n\n  return (\n    <>\n      <StoriesInspectorControls\n        attributes={attributes}\n        setAttributes={setAttributes}\n        showFilters={false}\n      />\n      {Boolean(selectedStories?.length) && (\n        <StoriesPreview\n          attributes={attributes}\n          stories={selectedStories}\n          viewAllLabel={viewAllLabel}\n        />\n      )}\n      <EmbedPlaceholder\n        icon={icon}\n        label={label}\n        selectedStories={selectedStories}\n        setSelectedStories={setSelectedStories}\n        isEditing={isEditing}\n      />\n    </>\n  );\n}\n\nSelectedStoriesEdit.propTypes = {\n  icon: PropTypes.node,\n  attributes: PropTypes.shape({\n    blockType: PropTypes.string,\n    stories: PropTypes.array,\n    align: PropTypes.string,\n    viewType: PropTypes.string,\n    numOfColumns: PropTypes.number,\n    archiveLinkLabel: PropTypes.string,\n    circleSize: PropTypes.number,\n  }),\n  setAttributes: PropTypes.func.isRequired,\n  isSelected: PropTypes.bool,\n};\n\nexport default SelectedStoriesEdit;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/selected-stories/embedPlaceholder.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { Button, ToolbarButton, Placeholder } from '@wordpress/components';\nimport { BlockControls, BlockIcon } from '@wordpress/block-editor';\nimport { useCallback, useState } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport StoryPicker from '../../components/storyPicker/storyPicker';\n\nconst {\n  config: { maxNumOfStories },\n} = window.webStoriesBlockSettings;\n\nconst EmbedPlaceholder = ({\n  icon,\n  label,\n  selectedStories,\n  setSelectedStories,\n}) => {\n  const [isStoryPickerOpen, setIsStoryPickerOpen] = useState(false);\n  const [isSortingStories, setIsSortingStories] = useState(false);\n\n  const openStoryPicker = () => setIsStoryPickerOpen(true);\n  const closeStoryPicker = useCallback(() => {\n    setIsStoryPickerOpen(false);\n    setIsSortingStories(false);\n  }, []);\n\n  const openStoryRearrangeWindow = useCallback(() => {\n    setIsSortingStories(true);\n    openStoryPicker();\n  }, []);\n\n  return (\n    <>\n      {Boolean(selectedStories?.length) && (\n        <BlockControls group=\"other\">\n          <ToolbarButton\n            aria-expanded={isStoryPickerOpen}\n            aria-haspopup=\"true\"\n            onClick={openStoryPicker}\n          >\n            {__('Select', 'web-stories')}\n          </ToolbarButton>\n          <ToolbarButton\n            aria-expanded={isStoryPickerOpen}\n            aria-haspopup=\"true\"\n            onClick={openStoryRearrangeWindow}\n          >\n            {__('Rearrange', 'web-stories')}\n          </ToolbarButton>\n        </BlockControls>\n      )}\n      {selectedStories.length === 0 && (\n        <Placeholder\n          icon={<BlockIcon icon={icon} showColors />}\n          label={label}\n          className=\"wp-block-web-stories-embed\"\n          instructions={__(\n            'Select the web stories you want to display on your site.',\n            'web-stories'\n          )}\n        >\n          <Button isPrimary onClick={openStoryPicker}>\n            {__('Select Stories', 'web-stories')}\n          </Button>\n        </Placeholder>\n      )}\n      {isStoryPickerOpen && (\n        <StoryPicker\n          closeStoryPicker={closeStoryPicker}\n          selectedStories={selectedStories}\n          setSelectedStories={setSelectedStories}\n          isSortingStories={isSortingStories}\n          setIsSortingStories={setIsSortingStories}\n          maxNumOfStories={maxNumOfStories}\n        />\n      )}\n    </>\n  );\n};\n\nEmbedPlaceholder.propTypes = {\n  icon: PropTypes.node,\n  label: PropTypes.string,\n  selectedStories: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n};\n\nexport default EmbedPlaceholder;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/edit.css",
    "content": ".block-editor-block-list__block[data-type='web-stories/embed'] .wp-block {\n  height: auto;\n}\n\n/* Loading Indicator */\n.wp-block-web-stories-embed.is-loading {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  padding: 1em;\n  min-height: 200px;\n  text-align: center;\n  background: #f8f9f9;\n}\n\n.wp-block-web-stories-embed.is-loading p {\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,\n    Cantarell, 'Helvetica Neue', sans-serif;\n  font-size: 13px;\n}\n\n/* Placeholder */\n\n.wp-block-web-stories-embed .components-placeholder__learn-more {\n  margin-top: 1em;\n}\n\n/* Actual Edit Component */\n\n.wp-block-web-stories-embed\n  .components-resizable-box__container\n  amp-story-player {\n  width: inherit;\n  height: inherit;\n}\n.wp-block-web-stories-embed.alignleft .components-resizable-box__container {\n  /*!rtl:ignore*/\n  margin-right: auto;\n}\n.wp-block-web-stories-embed.alignright .components-resizable-box__container {\n  /*!rtl:ignore*/\n  margin-left: auto;\n}\n.wp-block-web-stories-embed.aligncenter .components-resizable-box__container {\n  margin: auto;\n}\n\n.wp-block-web-stories-embed\n  .components-resizable-box__container.hide-resize-handle\n  .components-resizable-box__handle {\n  display: none;\n}\n.wp-block-web-stories-embed\n  .components-resizable-box__container.show-resize-handle\n  .components-resizable-box__handle {\n  display: block;\n}\n/* Embed Preview Component */\n\n.web-stories-embed-preview {\n  position: relative;\n  width: inherit;\n  height: inherit;\n}\n\n.web-stories-embed-preview-overlay {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  opacity: 0;\n}\n\n/* Block Inspector */\n\n.web-stories-embed-poster-label {\n  display: block !important;\n}\n\n.web-stories-embed-size-control {\n  margin-bottom: 1em;\n}\n\n.web-stories-embed-size-control__row {\n  display: flex;\n  justify-content: space-between;\n}\n\n.web-stories-embed-size-control__width input,\n.web-stories-embed-size-control__height input {\n  line-height: 1.25;\n}\n\n.block-editor-block-inspector .web-stories-embed-size-control__width,\n.block-editor-block-inspector .web-stories-embed-size-control__height {\n  margin-bottom: 0 !important;\n}\n\n.block-editor-block-inspector .web-stories-embed-size-control__width {\n  margin-right: 5px;\n}\n\n.block-editor-block-inspector .web-stories-embed-size-control__height {\n  margin-left: 5px;\n}\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/edit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint complexity: [\"error\", { \"max\": 25 }] -- TODO: Refactor this. */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * WordPress dependencies\n */\nimport { useCallback, useEffect, useRef, useState } from '@wordpress/element';\nimport apiFetch from '@wordpress/api-fetch';\nimport { ResizableBox } from '@wordpress/components';\nimport { useViewportMatch } from '@wordpress/compose';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\nimport { store as blockEditorStore } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { BlockIcon } from '../../icons';\nimport FetchSelectedStories from '../../components/storyPicker/fetchSelectedStories';\nimport EmbedControls from './embedControls';\nimport EmbedLoadinng from './embedLoading';\nimport EmbedPlaceholder from './embedPlaceholder';\nimport EmbedPreview from './embedPreview';\nimport './edit.css';\nimport Singleton from './singleton';\n\nconst MIN_SIZE = 20;\n\nfunction StoryEmbedEdit({\n  attributes,\n  setAttributes,\n  className,\n  isSelected,\n  context = {},\n}) {\n  const {\n    url: outerURL = '',\n    width = 360,\n    height = 600,\n    align = 'none',\n    poster,\n    title,\n    stories = [],\n    previewOnly = false,\n  } = attributes;\n\n  const { postId, queryId } = context;\n  const isDescendentOfQueryLoop = Number.isFinite(queryId);\n\n  const [editingURL, setEditingURL] = useState(false);\n  const [localURL, setLocalURL] = useState(\n    isDescendentOfQueryLoop ? undefined : outerURL\n  );\n  const [isFetchingData, setIsFetchingData] = useState(false);\n  const [isFetching, setIsFetching] = useState(false);\n  const [storyData, setStoryData] = useState({});\n  const [cannotEmbed, setCannotEmbed] = useState(false);\n  const [selectedStoryIds, setSelectedStoryIds] = useState(\n    isDescendentOfQueryLoop ? [postId] : stories\n  );\n  const [selectedStories, _setSelectedStories] = useState([]);\n\n  const showLoadingIndicator = isFetchingData;\n  const showPlaceholder = !localURL || !outerURL || editingURL || cannotEmbed;\n\n  const isResizable = useViewportMatch('medium');\n\n  const ref = useRef();\n\n  useEffect(() => {\n    if (attributes.stories.toString() !== selectedStoryIds.toString()) {\n      setAttributes({\n        stories: selectedStoryIds,\n      });\n    }\n  }, [attributes.stories, setAttributes, selectedStoryIds]);\n\n  useEffect(() => {\n    if (selectedStoryIds.length && !selectedStories.length) {\n      setIsFetching(true);\n    }\n  }, [selectedStoryIds, selectedStories, setIsFetching]);\n\n  useEffect(() => {\n    setLocalURL(outerURL);\n    trackEvent('story_embedded');\n  }, [outerURL]);\n\n  useEffect(() => {\n    trackEvent('story_poster_changed');\n  }, [poster]);\n\n  useEffect(() => {\n    if (ref.current && window.AmpStoryPlayer) {\n      const player = new window.AmpStoryPlayer(window, ref.current);\n      try {\n        player.load();\n      } catch {\n        // Player already loaded.\n      }\n    }\n  }, [showLoadingIndicator, showPlaceholder, isResizable, previewOnly]);\n\n  const fetchStoryData = useCallback(\n    async (url) => {\n      if (!url) {\n        return;\n      }\n\n      try {\n        setIsFetchingData(true);\n        // Normalize input URL.\n        const urlToEmbed = encodeURIComponent(new URL(url).toString());\n\n        const data = await apiFetch({\n          path: `web-stories/v1/embed?url=${urlToEmbed}`,\n        });\n\n        setCannotEmbed(!(typeof data?.title === 'string'));\n        setStoryData(data);\n        setAttributes({\n          url: url,\n        });\n      } catch (err) {\n        // Only care about errors from apiFetch\n        if (!(err instanceof TypeError)) {\n          setStoryData(err);\n        }\n\n        setCannotEmbed(true);\n      } finally {\n        setIsFetchingData(false);\n      }\n    },\n    [setAttributes]\n  );\n\n  useEffect(() => {\n    if (storyData?.title || storyData?.poster) {\n      setAttributes({\n        title: storyData?.title,\n        poster: storyData?.poster,\n      });\n    }\n  }, [outerURL, setAttributes, storyData?.title, storyData?.poster]);\n\n  const setSelectedStories = useCallback(\n    (newStories) => {\n      _setSelectedStories(newStories);\n      setSelectedStoryIds(newStories.map((story) => story.id));\n      const newStory = newStories?.[0];\n      const link = newStory?.link;\n      const data = {\n        title: newStory?.title?.rendered,\n        poster: newStory?._embedded?.['wp:featuredmedia']?.[0]?.source_url,\n      };\n      setStoryData(data);\n      setLocalURL(link);\n      setEditingURL(false);\n      setCannotEmbed(false);\n      setAttributes({\n        url: link,\n      });\n    },\n    [_setSelectedStories, setAttributes]\n  );\n\n  const onSubmit = useCallback(\n    (url) => {\n      _setSelectedStories([]);\n      setSelectedStoryIds([]);\n      setEditingURL(false);\n      setCannotEmbed(false);\n      setLocalURL(url);\n\n      if (url !== outerURL) {\n        fetchStoryData(url);\n      }\n    },\n    [outerURL, fetchStoryData]\n  );\n\n  const switchBackToURLInput = useCallback(() => {\n    setEditingURL(true);\n  }, []);\n\n  const { isRTL, maxWidth } = useSelect((select) => {\n    const { getSettings } = select(blockEditorStore);\n    const settings = getSettings();\n    return {\n      isRTL: settings.isRTL,\n      maxWidth: settings.maxWidth,\n    };\n  }, []);\n\n  const { toggleSelection } = useDispatch(blockEditorStore);\n\n  if (showLoadingIndicator) {\n    return <EmbedLoadinng />;\n  }\n\n  const onResizeStart = () => toggleSelection(false);\n  const onResizeStop = () => toggleSelection(true);\n\n  const label = __('Single Story', 'web-stories');\n\n  if (showPlaceholder) {\n    if (isFetching) {\n      return (\n        <FetchSelectedStories\n          icon={<BlockIcon />}\n          label={label}\n          selectedStoryIds={selectedStoryIds}\n          setSelectedStories={setSelectedStories}\n          setIsFetching={setIsFetching}\n        />\n      );\n    }\n    return (\n      <EmbedPlaceholder\n        icon={<BlockIcon />}\n        label={label}\n        value={localURL}\n        onSubmit={onSubmit}\n        cannotEmbed={cannotEmbed}\n        errorMessage={storyData?.message}\n        selectedStories={selectedStories}\n        setSelectedStories={setSelectedStories}\n      />\n    );\n  }\n\n  const ratio = width / height;\n  const minWidth = width < height ? MIN_SIZE : MIN_SIZE * ratio;\n  const minHeight = height < width ? MIN_SIZE : MIN_SIZE / ratio;\n\n  if (!isResizable) {\n    return (\n      <>\n        <EmbedControls\n          switchBackToURLInput={switchBackToURLInput}\n          poster={poster}\n          title={title}\n          setAttributes={setAttributes}\n          width={width}\n          height={height}\n          minWidth={Math.ceil(minWidth)}\n          maxWidth={Math.floor(maxWidth)}\n          minHeight={Math.floor(minHeight)}\n          maxHeight={Math.ceil(maxWidth / ratio)}\n          previewOnly={previewOnly}\n        />\n        <div className={`${className} web-stories-embed align${align}`}>\n          {previewOnly ? (\n            <Singleton\n              title={title}\n              poster={poster}\n              width={width}\n              height={height}\n            />\n          ) : (\n            <EmbedPreview\n              url={outerURL}\n              title={title}\n              poster={poster}\n              ref={ref}\n              isSelected={isSelected}\n              width={width}\n              height={height}\n            />\n          )}\n        </div>\n      </>\n    );\n  }\n\n  const showRightHandle =\n    align === 'center' ||\n    align === 'none' ||\n    (align === 'right' && isRTL) ||\n    (align === 'left' && !isRTL);\n\n  const showLeftHandle =\n    align === 'center' ||\n    (align === 'left' && isRTL) ||\n    (align === 'right' && !isRTL);\n\n  return (\n    <>\n      <EmbedControls\n        switchBackToURLInput={switchBackToURLInput}\n        poster={poster}\n        title={title}\n        setAttributes={setAttributes}\n        width={width}\n        height={height}\n        minWidth={Math.ceil(minWidth)}\n        maxWidth={Math.floor(maxWidth)}\n        minHeight={Math.floor(minHeight)}\n        maxHeight={Math.ceil(maxWidth / ratio)}\n        previewOnly={previewOnly}\n      />\n      <div className={`${className} web-stories-embed align${align}`}>\n        <ResizableBox\n          className={isSelected ? 'show-resize-handle' : 'hide-resize-handle'}\n          size={{\n            width,\n            height,\n          }}\n          minWidth={minWidth}\n          maxWidth={maxWidth}\n          minHeight={minHeight}\n          maxHeight={maxWidth / ratio}\n          lockAspectRatio\n          enable={{\n            top: false,\n            right: showRightHandle,\n            bottom: true,\n            left: showLeftHandle,\n          }}\n          onResizeStart={onResizeStart}\n          onResizeStop={(event, direction, elt, delta) => {\n            onResizeStop();\n            setAttributes({\n              width: Number.parseInt(width + delta.width),\n              height: Number.parseInt(height + delta.height),\n            });\n          }}\n        >\n          {previewOnly ? (\n            <Singleton\n              title={title}\n              poster={poster}\n              width={width}\n              height={height}\n            />\n          ) : (\n            <EmbedPreview\n              url={outerURL}\n              title={title}\n              poster={poster}\n              ref={ref}\n              isSelected={isSelected}\n              width={width}\n              height={height}\n            />\n          )}\n        </ResizableBox>\n      </div>\n    </>\n  );\n}\n\nStoryEmbedEdit.propTypes = {\n  attributes: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    stories: PropTypes.array,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n    previewOnly: PropTypes.bool,\n  }),\n  setAttributes: PropTypes.func.isRequired,\n  className: PropTypes.string.isRequired,\n  isSelected: PropTypes.bool,\n  context: PropTypes.shape({\n    postType: PropTypes.string,\n    postId: PropTypes.number,\n  }),\n};\n\nexport default StoryEmbedEdit;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/editInLoop.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\n/**\n * WordPress dependencies\n */\nimport { useEffect, useRef } from '@wordpress/element';\nimport { Placeholder, ResizableBox } from '@wordpress/components';\nimport { useViewportMatch } from '@wordpress/compose';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\nimport { store as blockEditorStore, BlockIcon } from '@wordpress/block-editor';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport LoaderContainer from '../../components/loaderContainer';\nimport { BlockIcon as Icon } from '../../icons';\nimport EmbedLoading from './embedLoading';\nimport EmbedPreview from './embedPreview';\nimport './edit.css';\nimport Singleton from './singleton';\nimport EmbedControlsInLoop from './embedControlsInLoop';\n\nconst MIN_SIZE = 20;\n\nfunction StoryEmbedEditInLoop({\n  attributes,\n  setAttributes,\n  className,\n  isSelected,\n  context = {},\n}) {\n  const {\n    width = 360,\n    height = 600,\n    align = 'none',\n    previewOnly = false,\n  } = attributes;\n\n  const { postId } = context;\n\n  const { story, isFetching } = useSelect(\n    (select) => {\n      const { getEntityRecord, isResolving } = select(coreStore);\n\n      let story = null;\n\n      const record = getEntityRecord('postType', 'web-story', postId);\n\n      if (record) {\n        story = {\n          url: record.link,\n          title: record.title?.rendered,\n          poster: record._embedded?.['wp:featuredmedia']?.[0]?.source_url,\n        };\n      }\n\n      return {\n        story,\n        isFetching: isResolving('postType', 'web-story', postId) || false,\n      };\n    },\n    [postId]\n  );\n\n  const { isRTL, maxWidth } = useSelect((select) => {\n    const { getSettings } = select(blockEditorStore);\n    const settings = getSettings();\n    return {\n      isRTL: settings.isRTL,\n      maxWidth: settings.maxWidth,\n    };\n  }, []);\n\n  const isResizable = useViewportMatch('medium');\n\n  const ref = useRef();\n\n  useEffect(() => {\n    if (ref.current && window.AmpStoryPlayer && !previewOnly) {\n      const player = new window.AmpStoryPlayer(window, ref.current);\n      try {\n        player.load();\n      } catch {\n        // Player already loaded.\n      }\n    }\n  }, [story, isResizable, previewOnly]);\n\n  const { toggleSelection } = useDispatch(blockEditorStore);\n\n  if (isFetching) {\n    return <EmbedLoading />;\n  }\n\n  const onResizeStart = () => toggleSelection(false);\n  const onResizeStop = () => toggleSelection(true);\n\n  const label = __('Single Story', 'web-stories');\n\n  if (isFetching) {\n    return (\n      <Placeholder\n        icon={<BlockIcon icon={<Icon />} showColors />}\n        label={label}\n        className=\"wp-block-web-stories-embed\"\n        instructions={false}\n      >\n        <LoaderContainer>{__('Loading Story…', 'web-stories')}</LoaderContainer>\n      </Placeholder>\n    );\n  }\n\n  const ratio = width / height;\n  const minWidth = width < height ? MIN_SIZE : MIN_SIZE * ratio;\n  const minHeight = height < width ? MIN_SIZE : MIN_SIZE / ratio;\n\n  const previewClassName = classNames(\n    className,\n    { 'web-stories-embed': !previewOnly },\n    { 'web-stories-singleton': previewOnly },\n    `align${align || 'none'}`\n  );\n\n  if (!isResizable) {\n    return (\n      <>\n        <EmbedControlsInLoop\n          setAttributes={setAttributes}\n          width={width}\n          height={height}\n          minWidth={Math.ceil(minWidth)}\n          maxWidth={Math.floor(maxWidth)}\n          minHeight={Math.floor(minHeight)}\n          maxHeight={Math.ceil(maxWidth / ratio)}\n        />\n        <div className={previewClassName}>\n          {previewOnly ? (\n            <Singleton\n              title={story.title}\n              poster={story.poster}\n              width={width}\n              height={height}\n            />\n          ) : (\n            <EmbedPreview\n              url={story.url}\n              title={story.title}\n              poster={story.poster}\n              ref={ref}\n              isSelected={isSelected}\n              width={width}\n              height={height}\n            />\n          )}\n        </div>\n      </>\n    );\n  }\n\n  const showRightHandle =\n    align === 'center' ||\n    align === 'none' ||\n    (align === 'right' && isRTL) ||\n    (align === 'left' && !isRTL);\n\n  const showLeftHandle =\n    align === 'center' ||\n    (align === 'left' && isRTL) ||\n    (align === 'right' && !isRTL);\n\n  return (\n    <>\n      <EmbedControlsInLoop\n        setAttributes={setAttributes}\n        width={width}\n        height={height}\n        minWidth={Math.ceil(minWidth)}\n        maxWidth={Math.floor(maxWidth)}\n        minHeight={Math.floor(minHeight)}\n        maxHeight={Math.ceil(maxWidth / ratio)}\n        previewOnly={previewOnly}\n      />\n      <div className={previewClassName}>\n        <ResizableBox\n          className={isSelected ? 'show-resize-handle' : 'hide-resize-handle'}\n          size={{\n            width,\n            height,\n          }}\n          minWidth={minWidth}\n          maxWidth={maxWidth}\n          minHeight={minHeight}\n          maxHeight={maxWidth / ratio}\n          lockAspectRatio\n          enable={{\n            top: false,\n            right: showRightHandle,\n            bottom: true,\n            left: showLeftHandle,\n          }}\n          onResizeStart={onResizeStart}\n          onResizeStop={(event, direction, elt, delta) => {\n            onResizeStop();\n            setAttributes({\n              width: Number.parseInt(width + delta.width),\n              height: Number.parseInt(height + delta.height),\n            });\n          }}\n        >\n          {previewOnly ? (\n            <Singleton\n              title={story.title}\n              poster={story.poster}\n              width={width}\n              height={height}\n            />\n          ) : (\n            <EmbedPreview\n              url={story.url}\n              title={story.title}\n              poster={story.poster}\n              ref={ref}\n              isSelected={isSelected}\n              width={width}\n              height={height}\n            />\n          )}\n        </ResizableBox>\n      </div>\n    </>\n  );\n}\n\nStoryEmbedEditInLoop.propTypes = {\n  attributes: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    stories: PropTypes.array,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n    previewOnly: PropTypes.bool,\n  }),\n  setAttributes: PropTypes.func.isRequired,\n  className: PropTypes.string.isRequired,\n  isSelected: PropTypes.bool,\n  context: PropTypes.shape({\n    postType: PropTypes.string,\n    postId: PropTypes.number,\n  }),\n};\n\nexport default StoryEmbedEditInLoop;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/embedControls.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport {\n  Button,\n  BaseControl,\n  TextControl,\n  PanelBody,\n  PanelRow,\n  ToolbarGroup,\n  ToolbarButton,\n  ToggleControl,\n} from '@wordpress/components';\nimport {\n  BlockControls,\n  InspectorControls,\n  MediaUpload,\n  MediaUploadCheck,\n} from '@wordpress/block-editor';\nimport { useInstanceId } from '@wordpress/compose';\nimport { createRef, useCallback } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\n\nconst POSTER_ALLOWED_MEDIA_TYPES = ['image'];\n\nconst EmbedControls = (props) => {\n  const {\n    switchBackToURLInput,\n    width,\n    height,\n    minWidth,\n    maxWidth,\n    minHeight,\n    maxHeight,\n    poster,\n    title,\n    previewOnly,\n    setAttributes,\n  } = props;\n\n  const instanceId = useInstanceId(EmbedControls, 'web-stories-embed');\n\n  const posterDescription = `web-stories-embed-block__poster-image-description-${instanceId}`;\n  const posterImageButton = createRef();\n\n  const onSelectPoster = useCallback(\n    (image) => {\n      setAttributes({ poster: image.url });\n    },\n    [setAttributes]\n  );\n\n  const onRemovePoster = useCallback(() => {\n    setAttributes({ poster: '' });\n\n    // Move focus back to the Media Upload button.\n    posterImageButton.current.focus();\n  }, [setAttributes, posterImageButton]);\n\n  const onChangePreviewOnly = useCallback(() => {\n    setAttributes({ previewOnly: !previewOnly });\n  }, [setAttributes, previewOnly]);\n\n  const hasPoster = Boolean(poster);\n\n  return (\n    <>\n      <BlockControls>\n        <ToolbarGroup>\n          {/*\n          Using ToolbarButton if available is mandatory as other usage is deprecated\n          for accessibility reasons and causes console warnings.\n          See https://github.com/WordPress/gutenberg/pull/23316\n          See https://developer.wordpress.org/block-editor/components/toolbar-button/#inside-blockcontrols\n          */}\n          {ToolbarButton ? (\n            <ToolbarButton onClick={switchBackToURLInput}>\n              {__('Replace', 'web-stories')}\n            </ToolbarButton>\n          ) : (\n            <Button\n              className=\"components-toolbar__control\"\n              title={__('Replace', 'web-stories')}\n              onClick={switchBackToURLInput}\n            />\n          )}\n        </ToolbarGroup>\n      </BlockControls>\n      <InspectorControls>\n        <PanelBody title={__('Embed Settings', 'web-stories')}>\n          <PanelRow>\n            <BaseControl __nextHasNoMarginBottom>\n              <TextControl\n                type=\"text\"\n                className=\"web-stories-embed-title-control\"\n                label={__('Title', 'web-stories')}\n                value={title || ''}\n                onChange={(value) => setAttributes({ title: value })}\n                __nextHasNoMarginBottom\n                __next40pxDefaultSize\n              />\n            </BaseControl>\n          </PanelRow>\n          <MediaUploadCheck>\n            <PanelRow>\n              <BaseControl __nextHasNoMarginBottom>\n                <BaseControl.VisualLabel className=\"web-stories-embed-poster-label\">\n                  {__('Poster image', 'web-stories')}\n                </BaseControl.VisualLabel>\n                {hasPoster && <img src={poster} alt=\"\" />}\n                <MediaUpload\n                  title={__('Select poster image', 'web-stories')}\n                  onSelect={onSelectPoster}\n                  allowedTypes={POSTER_ALLOWED_MEDIA_TYPES}\n                  render={({ open }) => (\n                    <Button\n                      isPrimary\n                      onClick={open}\n                      ref={posterImageButton}\n                      aria-describedby={posterDescription}\n                    >\n                      {!hasPoster\n                        ? __('Select', 'web-stories')\n                        : __('Replace', 'web-stories')}\n                    </Button>\n                  )}\n                />\n                <p id={posterDescription} hidden>\n                  {hasPoster\n                    ? sprintf(\n                        /* translators: %s: poster image URL. */\n                        __('The current poster image url is %s', 'web-stories'),\n                        poster\n                      )\n                    : __(\n                        'There is no poster image currently selected',\n                        'web-stories'\n                      )}\n                </p>\n                {hasPoster && (\n                  <Button\n                    className=\"web-stories-embed-poster-remove\"\n                    onClick={onRemovePoster}\n                  >\n                    {__('Remove', 'web-stories')}\n                  </Button>\n                )}\n              </BaseControl>\n            </PanelRow>\n          </MediaUploadCheck>\n          <PanelRow>\n            <BaseControl\n              className=\"web-stories-embed-size-control\"\n              __nextHasNoMarginBottom\n            >\n              <BaseControl.VisualLabel>\n                {__('Story dimensions', 'web-stories')}\n              </BaseControl.VisualLabel>\n              <div className=\"web-stories-embed-size-control__row\">\n                <TextControl\n                  type=\"number\"\n                  className=\"web-stories-embed-size-control__width\"\n                  label={__('Width', 'web-stories')}\n                  value={width || ''}\n                  min={minWidth}\n                  max={maxWidth}\n                  onChange={(value) =>\n                    setAttributes({ width: Number.parseInt(value) })\n                  }\n                  __nextHasNoMarginBottom\n                  __next40pxDefaultSize\n                />\n                <TextControl\n                  type=\"number\"\n                  className=\"web-stories-embed-size-control__height\"\n                  label={__('Height', 'web-stories')}\n                  value={height || ''}\n                  min={minHeight}\n                  max={maxHeight}\n                  onChange={(value) =>\n                    setAttributes({\n                      height: Number.parseInt(value),\n                    })\n                  }\n                  __nextHasNoMarginBottom\n                  __next40pxDefaultSize\n                />\n              </div>\n            </BaseControl>\n          </PanelRow>\n          <PanelRow>\n            <BaseControl __nextHasNoMarginBottom>\n              <ToggleControl\n                label={__('Display as preview', 'web-stories')}\n                checked={previewOnly}\n                onChange={onChangePreviewOnly}\n                help={__(\n                  'Displays the story poster that opens the story in a lightbox on click',\n                  'web-stories'\n                )}\n                __nextHasNoMarginBottom\n              />\n            </BaseControl>\n          </PanelRow>\n        </PanelBody>\n      </InspectorControls>\n    </>\n  );\n};\n\nEmbedControls.propTypes = {\n  switchBackToURLInput: PropTypes.func,\n  width: PropTypes.number,\n  height: PropTypes.number,\n  minWidth: PropTypes.number,\n  maxWidth: PropTypes.number,\n  minHeight: PropTypes.number,\n  maxHeight: PropTypes.number,\n  poster: PropTypes.string,\n  title: PropTypes.string,\n  setAttributes: PropTypes.func,\n  previewOnly: PropTypes.bool,\n};\n\nexport default EmbedControls;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/embedControlsInLoop.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport {\n  BaseControl,\n  TextControl,\n  PanelBody,\n  PanelRow,\n  ToggleControl,\n} from '@wordpress/components';\nimport { InspectorControls } from '@wordpress/block-editor';\nimport { useCallback } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\n\nconst EmbedControlsInLoop = (props) => {\n  const {\n    width,\n    height,\n    minWidth,\n    maxWidth,\n    minHeight,\n    maxHeight,\n    previewOnly,\n    setAttributes,\n  } = props;\n\n  const onChangePreviewOnly = useCallback(() => {\n    setAttributes({ previewOnly: !previewOnly });\n  }, [setAttributes, previewOnly]);\n\n  return (\n    <InspectorControls>\n      <PanelBody title={__('Embed Settings', 'web-stories')}>\n        <PanelRow>\n          <BaseControl\n            className=\"web-stories-embed-size-control\"\n            __nextHasNoMarginBottom\n          >\n            <BaseControl.VisualLabel>\n              {__('Story dimensions', 'web-stories')}\n            </BaseControl.VisualLabel>\n            <div className=\"web-stories-embed-size-control__row\">\n              <TextControl\n                type=\"number\"\n                className=\"web-stories-embed-size-control__width\"\n                label={__('Width', 'web-stories')}\n                value={width || ''}\n                min={minWidth}\n                max={maxWidth}\n                onChange={(value) =>\n                  setAttributes({ width: Number.parseInt(value) })\n                }\n                __nextHasNoMarginBottom\n                __next40pxDefaultSize\n              />\n              <TextControl\n                type=\"number\"\n                className=\"web-stories-embed-size-control__height\"\n                label={__('Height', 'web-stories')}\n                value={height || ''}\n                min={minHeight}\n                max={maxHeight}\n                onChange={(value) =>\n                  setAttributes({\n                    height: Number.parseInt(value),\n                  })\n                }\n                __nextHasNoMarginBottom\n                __next40pxDefaultSize\n              />\n            </div>\n          </BaseControl>\n        </PanelRow>\n        <PanelRow>\n          <BaseControl __nextHasNoMarginBottom>\n            <ToggleControl\n              label={__('Display as preview', 'web-stories')}\n              checked={previewOnly}\n              onChange={onChangePreviewOnly}\n              help={__(\n                'Displays the story poster that opens the story in a lightbox on click',\n                'web-stories'\n              )}\n              __nextHasNoMarginBottom\n            />\n          </BaseControl>\n        </PanelRow>\n      </PanelBody>\n    </InspectorControls>\n  );\n};\n\nEmbedControlsInLoop.propTypes = {\n  width: PropTypes.number,\n  height: PropTypes.number,\n  minWidth: PropTypes.number,\n  maxWidth: PropTypes.number,\n  minHeight: PropTypes.number,\n  maxHeight: PropTypes.number,\n  setAttributes: PropTypes.func,\n  previewOnly: PropTypes.bool,\n};\n\nexport default EmbedControlsInLoop;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/embedLoading.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { Spinner } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\n\nconst EmbedLoading = () => (\n  <div className=\"wp-block-web-stories-embed is-loading\">\n    <Spinner />\n    <p>{__('Embedding…', 'web-stories')}</p>\n  </div>\n);\n\nexport default EmbedLoading;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/embedPlaceholder.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { useCallback, useState } from '@wordpress/element';\nimport { Button, Placeholder } from '@wordpress/components';\nimport { BlockIcon } from '@wordpress/block-editor';\nimport { __, sprintf } from '@wordpress/i18n';\n/**\n * Internal dependencies\n */\nimport StoryPicker from '../../components/storyPicker/storyPicker';\nimport InsertFromURLPopover from './insertFromURLPopover';\n\nconst EmbedPlaceholder = ({\n  icon,\n  label,\n  value,\n  onSubmit,\n  cannotEmbed = false,\n  errorMessage,\n  selectedStories = [],\n  setSelectedStories,\n}) => {\n  const [url, setUrl] = useState(value);\n  const [isURLInputVisible, setIsURLInputVisible] = useState(false);\n  const [isStoryPickerOpen, setIsStoryPickerOpen] = useState(false);\n\n  const openStoryPicker = () => setIsStoryPickerOpen(true);\n  const closeStoryPicker = useCallback(() => {\n    setIsStoryPickerOpen(false);\n  }, []);\n\n  const openURLInput = () => setIsURLInputVisible(true);\n  const closeURLInput = () => setIsURLInputVisible(false);\n\n  const onChangeUrl = (event) => {\n    setUrl(event.target.value);\n  };\n\n  const onSubmitUrl = (event) => {\n    event.preventDefault();\n\n    closeURLInput();\n    onSubmit(url);\n  };\n\n  const hasStories = selectedStories.length > 0;\n\n  return (\n    <>\n      <Placeholder\n        icon={<BlockIcon icon={icon} showColors />}\n        label={label}\n        className=\"wp-block-web-stories-embed\"\n        instructions={__(\n          'Select an existing story from your site, or add one with a URL.',\n          'web-stories'\n        )}\n      >\n        <>\n          <Button isPrimary onClick={openStoryPicker}>\n            {!hasStories\n              ? __('Select Story', 'web-stories')\n              : __('Replace Story', 'web-stories')}\n          </Button>\n          <div className=\"block-editor-media-placeholder__url-input-container\">\n            <Button\n              className=\"block-editor-media-placeholder__button\"\n              onClick={openURLInput}\n              isPressed={isURLInputVisible}\n              variant=\"tertiary\"\n            >\n              {!hasStories && value\n                ? __('Replace URL', 'web-stories')\n                : __('Insert from URL', 'web-stories')}\n            </Button>\n            {isURLInputVisible && (\n              <InsertFromURLPopover\n                url={url}\n                onChange={onChangeUrl}\n                onSubmit={onSubmitUrl}\n                onClose={closeURLInput}\n              />\n            )}\n          </div>\n        </>\n        {cannotEmbed && (\n          <div className=\"components-placeholder__error\">\n            <div className=\"components-placeholder__instructions\">\n              {__('Sorry, this content could not be embedded.', 'web-stories')}\n              {errorMessage && (\n                <>\n                  {' '}\n                  {sprintf(\n                    /* translators: %s: error message. */\n                    __('Reason: %s.', 'web-stories'),\n                    errorMessage\n                  )}\n                </>\n              )}\n            </div>\n          </div>\n        )}\n      </Placeholder>\n      {isStoryPickerOpen && (\n        <StoryPicker\n          closeStoryPicker={closeStoryPicker}\n          maxNumOfStories={1}\n          selectedStories={selectedStories}\n          setSelectedStories={setSelectedStories}\n        />\n      )}\n    </>\n  );\n};\n\nEmbedPlaceholder.propTypes = {\n  icon: PropTypes.node,\n  label: PropTypes.string,\n  value: PropTypes.string,\n  onSubmit: PropTypes.func,\n  cannotEmbed: PropTypes.bool,\n  errorMessage: PropTypes.string,\n  selectedStories: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n};\n\nexport default EmbedPlaceholder;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/embedPreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport {\n  useState,\n  useEffect,\n  useCallback,\n  forwardRef,\n} from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport StoryPlayer from './storyPlayer';\n\nfunction EmbedPreview({ url, title, poster, isSelected, width, height }, ref) {\n  const [interactive, setInteractive] = useState(false);\n\n  useEffect(() => {\n    if (!isSelected && interactive) {\n      setInteractive(false);\n    }\n  }, [isSelected, interactive, setInteractive]);\n\n  const hideOverlay = useCallback(() => setInteractive(true), [setInteractive]);\n\n  return (\n    <div\n      className=\"web-stories-embed-preview wp-block-embed__wrapper\"\n      style={{\n        '--aspect-ratio': 0 !== width ? height / width : 1,\n        '--width': `${width}px`,\n        '--height': `${height}px`,\n      }}\n    >\n      <StoryPlayer\n        url={url}\n        title={title}\n        poster={poster}\n        ref={ref}\n        onFocus={hideOverlay}\n      />\n      {!interactive && (\n        <div\n          className=\"web-stories-embed-preview-overlay\"\n          data-testid=\"embed-preview-overlay\"\n          onMouseUp={hideOverlay}\n        />\n      )}\n    </div>\n  );\n}\n\nconst EmbedPreviewWithRef = forwardRef(EmbedPreview);\n\nEmbedPreview.propTypes = {\n  url: PropTypes.string.isRequired,\n  title: PropTypes.string.isRequired,\n  poster: PropTypes.string,\n  isSelected: PropTypes.bool,\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n};\n\nexport default EmbedPreviewWithRef;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/insertFromURLPopover.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { URLPopover } from '@wordpress/block-editor';\nimport { __ } from '@wordpress/i18n';\nimport { Button } from '@wordpress/components';\nimport { keyboardReturn } from '@wordpress/icons';\n\n/**\n * Component to render url popover.\n *\n * @see https://github.com/WordPress/gutenberg/blob/adbe3eaae3d7f231953045c96ad67eb7a30369b7/packages/block-editor/src/components/media-placeholder/index.js#L31-L52\n * @param {Object} props Component props.\n * @param {string} props.url Value of form input.\n * @param {Function} props.onChange Callback from when url is changed.\n * @param {Function} props.onSubmit Callback when form is submitted.\n * @param {Function} props.onClose Callback when the dialog is closed.\n * @return {*} JSX markup for the editor.\n */\nconst InsertFromURLPopover = ({ url, onChange, onSubmit, onClose }) => (\n  <URLPopover onClose={onClose}>\n    <form\n      className=\"block-editor-media-placeholder__url-input-form\"\n      data-testid=\"embed-placeholder-form\"\n      onSubmit={onSubmit}\n    >\n      <input\n        className=\"block-editor-media-placeholder__url-input-field\"\n        type=\"url\"\n        aria-label={__('Story URL', 'web-stories')}\n        placeholder={__('Paste or type URL', 'web-stories')}\n        onChange={onChange}\n        value={url}\n      />\n      <Button\n        className=\"block-editor-media-placeholder__url-input-submit-button\"\n        icon={keyboardReturn}\n        label={__('Embed', 'web-stories')}\n        type=\"submit\"\n      />\n    </form>\n  </URLPopover>\n);\n\nInsertFromURLPopover.propTypes = {\n  url: PropTypes.string,\n  onChange: PropTypes.func,\n  onClose: PropTypes.func,\n  onSubmit: PropTypes.func,\n};\n\nexport default InsertFromURLPopover;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/singleton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { RawHTML } from '@wordpress/element';\n\nfunction Singleton({ title, poster, width, height }) {\n  return (\n    <div className=\"web-stories-singleton\">\n      <div\n        className=\"wp-block-embed__wrapper\"\n        style={{\n          '--aspect-ratio': 0 !== height ? width / height : 1,\n          '--width': `${width}px`,\n          '--height': `${height}px`,\n        }}\n      >\n        <div className=\"web-stories-singleton-poster\">\n          {poster ? (\n            <img src={poster} alt={title} />\n          ) : (\n            <div className=\"web-stories-singleton-poster-placeholder\">\n              <span>{title}</span>\n            </div>\n          )}\n        </div>\n        <div className=\"web-stories-singleton-overlay\">\n          {title && (\n            <RawHTML className=\"story-content-overlay__title\">{title}</RawHTML>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n\nSingleton.propTypes = {\n  title: PropTypes.string,\n  poster: PropTypes.string,\n  width: PropTypes.number,\n  height: PropTypes.number,\n};\n\nexport default Singleton;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/storyPlayer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { forwardRef } from '@wordpress/element';\n\nfunction StoryPlayer({ url, title, poster, width, height }, ref) {\n  return (\n    <amp-story-player\n      ref={ref}\n      style={{\n        width: width ? `${width}px` : undefined,\n        height: height ? `${height}px` : undefined,\n      }}\n      data-testid=\"amp-story-player\"\n    >\n      <a href={url}>\n        {poster ? (\n          <img\n            alt={title}\n            src={poster}\n            width={width}\n            height={height}\n            data-amp-story-player-poster-img\n          />\n        ) : (\n          title\n        )}\n      </a>\n    </amp-story-player>\n  );\n}\n\nconst StoryPlayerWithRef = forwardRef(StoryPlayer);\n\nStoryPlayer.propTypes = {\n  url: PropTypes.string.isRequired,\n  title: PropTypes.string.isRequired,\n  poster: PropTypes.string,\n  width: PropTypes.number,\n  height: PropTypes.number,\n};\n\nexport default StoryPlayerWithRef;\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/test/embedLoading.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport EmbedLoading from '../embedLoading';\n\ndescribe('EmbedLoading', () => {\n  it('should display spinner', () => {\n    render(<EmbedLoading />);\n    expect(screen.getByText('Embedding…')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/test/embedPlaceholder.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport EmbedPlaceholder from '../embedPlaceholder';\n\ndescribe('EmbedPlaceholder', () => {\n  it('should display the embed placeholder', () => {\n    const onSubmit = jest.fn();\n    render(\n      <EmbedPlaceholder\n        icon={null}\n        label=\"Embed Placeholder\"\n        value=\"\"\n        onSubmit={onSubmit}\n        cannotEmbed={false}\n      />\n    );\n    expect(screen.getByText('Embed Placeholder')).toBeInTheDocument();\n    expect(screen.getByText('Select Story')).toBeInTheDocument();\n    expect(screen.getByText('Insert from URL')).toBeInTheDocument();\n  });\n\n  it('should trigger onSubmit callback when submitting the form', () => {\n    const onSubmit = jest.fn();\n    render(\n      <EmbedPlaceholder\n        icon={null}\n        label=\"Embed Placeholder\"\n        value=\"https://example.com\"\n        onSubmit={onSubmit}\n        cannotEmbed={false}\n      />\n    );\n    fireEvent.click(screen.getByText('Replace URL'));\n    fireEvent.submit(screen.getByTestId('embed-placeholder-form'));\n    expect(onSubmit).toHaveBeenCalledOnce();\n  });\n\n  it('should display a message if embedding is not possible', () => {\n    const onSubmit = jest.fn();\n    render(\n      <EmbedPlaceholder\n        icon={null}\n        label=\"Embed Placeholder\"\n        value=\"https://example.com\"\n        onSubmit={onSubmit}\n        cannotEmbed\n      />\n    );\n    expect(\n      screen.getByText('Sorry, this content could not be embedded.')\n    ).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/test/embedPreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  render,\n  screen,\n  fireEvent,\n  waitFor,\n  act,\n} from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport EmbedPreview from '../embedPreview';\n\nconst url = 'https://wp.stories.google/stories/intro-to-web-stories-storytime';\nconst title = 'Stories in AMP';\n\njest.mock('../storyPlayer', () => {\n  return {\n    __esModule: true,\n    //eslint-disable-next-line no-shadow\n    default: function StoryPlayer({ url, title, onFocus }) {\n      return (\n        <a href={url} data-testid=\"amp-story-player\" onFocus={onFocus}>\n          {title}\n        </a>\n      );\n    },\n  };\n});\n\ndescribe('EmbedPreview', () => {\n  it('should remove overlay on mouseup', () => {\n    render(<EmbedPreview url={url} title={title} isSelected />);\n    const overlay = screen.getByTestId('embed-preview-overlay');\n    fireEvent.mouseUp(overlay);\n\n    expect(\n      screen.queryByTestId('embed-preview-overlay')\n    ).not.toBeInTheDocument();\n  });\n\n  it('should add back overlay when block gets unselected', () => {\n    const { rerender } = render(\n      <EmbedPreview url={url} title={title} isSelected />\n    );\n\n    const overlay = screen.getByTestId('embed-preview-overlay');\n    fireEvent.mouseUp(overlay);\n\n    expect(\n      screen.queryByTestId('embed-preview-overlay')\n    ).not.toBeInTheDocument();\n\n    rerender(<EmbedPreview url={url} title={title} isSelected={false} />);\n    expect(screen.getByTestId('embed-preview-overlay')).toBeInTheDocument();\n  });\n\n  it('should remove overlay on player focus', async () => {\n    render(<EmbedPreview url={url} title={title} isSelected />);\n    const player = screen.getByTestId('amp-story-player');\n    act(() => {\n      player.focus();\n    });\n    await waitFor(() =>\n      expect(screen.getByTestId('amp-story-player')).toHaveFocus()\n    );\n    expect(\n      screen.queryByTestId('embed-preview-overlay')\n    ).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/block-types/single-story/test/storyPlayer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport StoryPlayer from '../storyPlayer';\n\nconst url = 'https://wp.stories.google/stories/intro-to-web-stories-storytime';\nconst title = 'Stories in AMP';\nconst poster = 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg';\n\ndescribe('StoryPlayer', () => {\n  it('should render an <amp-story-player> element', () => {\n    const { container } = render(<StoryPlayer url={url} title={title} />);\n\n    // eslint-disable-next-line testing-library/no-node-access\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <amp-story-player\n        data-testid=\"amp-story-player\"\n      >\n        <a\n          href=\"https://wp.stories.google/stories/intro-to-web-stories-storytime\"\n        >\n          Stories in AMP\n        </a>\n      </amp-story-player>\n    `);\n  });\n\n  it('should set poster if provided', () => {\n    const { container } = render(\n      <StoryPlayer url={url} title={title} poster={poster} />\n    );\n\n    // eslint-disable-next-line testing-library/no-node-access\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <amp-story-player\n        data-testid=\"amp-story-player\"\n      >\n        <a\n          href=\"https://wp.stories.google/stories/intro-to-web-stories-storytime\"\n        >\n          <img\n            alt=\"Stories in AMP\"\n            data-amp-story-player-poster-img=\"true\"\n            src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n          />\n        </a>\n      </amp-story-player>\n    `);\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/block.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\n// eslint-disable-next-line import/no-relative-packages -- False positive because this is not another package.\nimport metadata from '../../../../blocks/embed/block.json';\n\nexport default metadata;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/authorSelection.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { useState, useCallback } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\nimport { useDebounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport Autocomplete from './autocomplete';\n\n/**\n * AuthorSelection props.\n *\n * @typedef AuthorSelectionProps\n * @property {Array<number>} authors List of author IDs.\n * @property {()=>void} setAttributes Callable function for saving attribute values.\n */\n\nconst defaultQueryProps = {\n  per_page: 100,\n};\n\n/**\n * AuthorSelection component. Used for selecting authors of stories.\n *\n * @param {AuthorSelection} props Component props.\n * @return {*} JSX markup.\n */\nconst AuthorSelection = ({ authors: authorIds, setAttributes }) => {\n  const [authorKeyword, setAuthorKeyword] = useState('');\n\n  const { authorsList } = useSelect(\n    (select) => {\n      const { getUsers } = select(coreStore);\n\n      const query = {\n        ...defaultQueryProps,\n        include: authorIds.join(','),\n      };\n      return {\n        authorsList: getUsers(query) || [],\n      };\n    },\n    [authorIds]\n  );\n\n  const { authorSuggestions } = useSelect(\n    (select) => {\n      const { getUsers } = select(coreStore);\n\n      const query = {\n        ...defaultQueryProps,\n        search: authorKeyword,\n      };\n      return {\n        authorSuggestions: getUsers(query) || [],\n      };\n    },\n    [authorKeyword]\n  );\n\n  /**\n   * Callback function called when user selects an author from the suggestions.\n   *\n   * Will process the names given by the user and valid author names will be saved.\n   *\n   * @param {Array} tokens Array of strings that were parsed from the text field.\n   * @return {void}\n   */\n  const onChange = useCallback(\n    (tokens) => {\n      if ('undefined' === typeof tokens || !Array.isArray(tokens)) {\n        return;\n      }\n      const authors = tokens\n        .map((token) =>\n          [...authorSuggestions, ...authorsList].find(\n            ({ name }) => name === token\n          )\n        )\n        .filter(Boolean)\n        .map(({ id }) => id);\n\n      setAttributes({ authors });\n    },\n    [authorSuggestions, authorsList, setAttributes]\n  );\n\n  /**\n   * Callback function used when user types in the search query in the text field.\n   *\n   * Makes an API call to fetch authors matching the search query.\n   *\n   * @param {string} search Search query to look for authors.\n   * @return {void}\n   */\n  const onInputChange = (search) => setAuthorKeyword(search);\n\n  const debouncedOnInputChange = useDebounce(onInputChange, 500);\n\n  return (\n    <Autocomplete\n      label={__('Authors', 'web-stories')}\n      value={authorsList.map(({ name }) => name)}\n      options={authorSuggestions.map(({ name }) => name)}\n      onChange={onChange}\n      onInputChange={debouncedOnInputChange}\n    />\n  );\n};\n\nAuthorSelection.propTypes = {\n  authors: PropTypes.array.isRequired,\n  setAttributes: PropTypes.func.isRequired,\n};\n\nexport default AuthorSelection;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/autocomplete.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { FormTokenField } from '@wordpress/components';\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\nconst Autocomplete = ({\n  label,\n  value,\n  onChange,\n  onInputChange,\n  placeholder,\n  options = [],\n}) => {\n  // Return the block, but only if options were passed in.\n  return (\n    Array.isArray(options) && (\n      <div className=\"components-base-control\">\n        <FormTokenField\n          value={value}\n          suggestions={options}\n          onChange={onChange}\n          onInputChange={onInputChange}\n          maxSuggestions={100}\n          label={label}\n          placeholder={placeholder}\n          __nextHasNoMarginBottom\n          __next40pxDefaultSize\n        />\n      </div>\n    )\n  );\n};\n\nAutocomplete.propTypes = {\n  label: PropTypes.string.isRequired,\n  value: PropTypes.array.isRequired,\n  onChange: PropTypes.func.isRequired,\n  onInputChange: PropTypes.func.isRequired,\n  placeholder: PropTypes.string,\n  options: PropTypes.array.isRequired,\n};\n\nexport default Autocomplete;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/blockTypeSwitcher.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { DropdownMenu, ToolbarGroup, ToolbarItem } from '@wordpress/components';\n\n/**\n * Internal dependencies\n */\nimport { BLOCK_TYPES } from '../constants';\n\nfunction BlockTypeSwitcher({ selectedBlockType, setAttributes }) {\n  return (\n    <ToolbarGroup>\n      {ToolbarItem ? (\n        <ToolbarItem>\n          {(toolbarItemHTMLProps) => (\n            <DropdownMenu\n              icon=\"update\"\n              toggleProps={toolbarItemHTMLProps}\n              label={__('Change Type', 'web-stories')}\n              controls={BLOCK_TYPES.filter(\n                (blockType) => blockType.id !== selectedBlockType\n              ).map((blockType) => {\n                return {\n                  title: blockType.label,\n                  onClick: () => setAttributes({ blockType: blockType.id }),\n                };\n              })}\n            />\n          )}\n        </ToolbarItem>\n      ) : (\n        <DropdownMenu\n          icon=\"update\"\n          label={__('Change Type', 'web-stories')}\n          controls={BLOCK_TYPES.filter(\n            (blockType) => blockType.id !== selectedBlockType\n          ).map((blockType) => {\n            return {\n              title: blockType.label,\n              onClick: () => setAttributes({ blockType: blockType.id }),\n            };\n          })}\n        />\n      )}\n    </ToolbarGroup>\n  );\n}\n\nBlockTypeSwitcher.propTypes = {\n  selectedBlockType: PropTypes.string.isRequired,\n  setAttributes: PropTypes.func.isRequired,\n};\n\nexport default BlockTypeSwitcher;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/loaderContainer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { Spinner } from '@wordpress/components';\n\nfunction LoaderContainer({ children }) {\n  return (\n    <div className=\"web-stories-block__loader-container\">\n      {children}\n      <Spinner />\n    </div>\n  );\n}\n\nLoaderContainer.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default LoaderContainer;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storiesBlockConfigurationPanel.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { Placeholder, Icon, Button } from '@wordpress/components';\nimport { BlockIcon } from '@wordpress/block-editor';\n\nfunction BlockConfigurationPanel({\n  instructions,\n  icon,\n  setAttributes,\n  selectionOptions,\n  selectionType,\n}) {\n  const label = __('Web Stories', 'web-stories');\n\n  return (\n    <Placeholder\n      icon={<BlockIcon icon={icon} showColors />}\n      label={label}\n      instructions={instructions}\n      className=\"web-stories-block-configuration-panel\"\n    >\n      <ul\n        className=\"web-stories-block-configuration-panel__options\"\n        role=\"list\"\n        aria-label={__('Block Types', 'web-stories')}\n      >\n        {selectionOptions.map((option) => (\n          <li key={option.id}>\n            <Button\n              variant=\"secondary\"\n              isSecondary\n              onClick={() => {\n                setAttributes({ [selectionType]: option.id });\n              }}\n              icon={\n                <Icon\n                  icon={option.panelIcon || option.icon}\n                  title={option.label}\n                />\n              }\n              label={option.description || option.label}\n            />\n            <span\n              className=\"web-stories-block-configuration-panel__label components-placeholder__instructions\"\n              role=\"presentation\"\n            >\n              {option.label}\n            </span>\n          </li>\n        ))}\n      </ul>\n    </Placeholder>\n  );\n}\n\nBlockConfigurationPanel.propTypes = {\n  selectionType: PropTypes.string,\n  selectionOptions: PropTypes.array,\n  instructions: PropTypes.string,\n  icon: PropTypes.node,\n  setAttributes: PropTypes.func.isRequired,\n};\n\nexport default BlockConfigurationPanel;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storiesBlockControls.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { Button, ToolbarGroup, ToolbarButton } from '@wordpress/components';\nimport { BlockControls } from '@wordpress/block-editor';\nimport { Fragment } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { BLOCK_TYPE_URL, VIEW_TYPES } from '../constants';\nimport BlockTypeSwitcher from './blockTypeSwitcher';\n\n/**\n * StoriesBlockControls props.\n *\n * @typedef StoriesBlockControlsProps\n * @property {string}    viewType     String indicator of active view type.\n * @property {Function} setAttributes Callable function for saving attribute values.\n */\n\n/**\n * LatestStoriesBlockControls component. Used for rendering block controls of the block.\n *\n * @param {StoriesBlockControlsProps} props Component props.\n * @return {*} JSX markup.\n */\nconst StoriesBlockControls = ({ blockType, viewType, setAttributes }) => {\n  return (\n    <BlockControls>\n      <ToolbarGroup>\n        {blockType && BLOCK_TYPE_URL !== blockType && (\n          <Fragment>\n            {VIEW_TYPES.map((view) => {\n              return ToolbarButton ? (\n                <ToolbarButton\n                  key={view.id}\n                  label={view.label}\n                  icon={view.icon}\n                  onClick={() => {\n                    setAttributes({ viewType: view.id });\n                  }}\n                  isPressed={view.id === viewType}\n                />\n              ) : (\n                <Button\n                  key={view.id}\n                  label={view.label}\n                  icon={view.icon}\n                  onClick={() => {\n                    setAttributes({ viewType: view.id });\n                  }}\n                  isPressed={view.id === viewType}\n                />\n              );\n            })}\n          </Fragment>\n        )}\n      </ToolbarGroup>\n      <BlockTypeSwitcher\n        selectedBlockType={blockType}\n        setAttributes={setAttributes}\n      />\n    </BlockControls>\n  );\n};\n\nStoriesBlockControls.propTypes = {\n  blockType: PropTypes.string.isRequired,\n  viewType: PropTypes.string.isRequired,\n  setAttributes: PropTypes.func.isRequired,\n};\n\nexport default StoriesBlockControls;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storiesInspectorControls.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport {\n  PanelBody,\n  RadioControl,\n  RangeControl,\n  SelectControl,\n  TextControl,\n  ToggleControl,\n} from '@wordpress/components';\nimport { InspectorControls } from '@wordpress/block-editor';\nimport { useEffect, useRef } from '@wordpress/element';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport {\n  CIRCLES_VIEW_TYPE,\n  GRID_VIEW_TYPE,\n  LIST_VIEW_TYPE,\n} from '../constants';\nimport AuthorSelection from './authorSelection';\nimport TaxonomyItem from './taxonomyItem';\n\n/**\n * StoriesInspectorControls props.\n *\n * @typedef StoriesInspectorControlsProps\n * @property {string} viewType String indicator of active view type.\n * @property {number} numOfStories Number indicator of maximum number of stories to show.\n * @property {number} numOfColumns Number indicator of number of columns in grid view type.\n * @property {string} orderby Attribute to order stories by.\n * @property {string} order Sorting order (ASC or DESC)\n * @property {boolean} isShowingTitle Whether or not to display story's title.\n * @property {boolean} isShowingDate Whether or not to display story's date.\n * @property {boolean} isShowingAuthor Whether or not to display story's author.\n * @property {boolean} isShowingViewAll Whether or not to display stories archive link.\n * @property {string} archiveLinkLabel Archive link's label.\n * @property {boolean} imageOnRight Whether or not to display images on right side in list view type.\n * @property {Array} authors An array of authors objects which are currently selected.\n * @property {Function} setAttributes Callable function for saving attribute values.\n */\n\nconst {\n  config: { fieldStates, archiveURL },\n} = window.webStoriesBlockSettings;\n\n/**\n * StoriesInspectorControls component. Used for rendering block controls of the block.\n *\n * @param {StoriesInspectorControlsProps} props Component props.\n * @return {*} JSX markup.\n */\nconst StoriesInspectorControls = (props) => {\n  const {\n    attributes: {\n      viewType,\n      numOfStories,\n      numOfColumns,\n      order,\n      orderby,\n      archiveLinkLabel,\n      authors,\n      circleSize,\n      imageAlignment,\n      fieldState,\n      taxQuery,\n    },\n    setAttributes,\n    showFilters = true,\n  } = props;\n\n  const firstUpdateRef = useRef(true);\n\n  const taxonomies = useSelect((select) => {\n    const { getTaxonomies } = select(coreStore);\n    return (\n      getTaxonomies({\n        type: 'web-story',\n        per_page: -1,\n        context: 'view',\n      }) || []\n    );\n  }, []);\n\n  useEffect(() => {\n    // Set default field state on load.\n    const defaultState = {};\n    Object.entries(fieldStates[viewType]).forEach(([field, fieldObj]) => {\n      const { show } = fieldObj;\n      // Initially the fieldState will be an empty object. Set the defaults based on current viewType.\n      if (undefined === fieldState[`show_${field}`]) {\n        defaultState[`show_${field}`] = show;\n      }\n    });\n\n    // Prevent unnecessary changes if `defaultState` is empty.\n    if (!Object.keys(defaultState).length) {\n      return;\n    }\n\n    setAttributes({\n      fieldState: {\n        ...fieldState,\n        ...defaultState,\n      },\n    });\n  }, []); // eslint-disable-line react-hooks/exhaustive-deps -- We only want to set the values once.\n\n  useEffect(() => {\n    // We want to update the fieldState for any viewType change post first render.\n    if (firstUpdateRef.current) {\n      firstUpdateRef.current = false;\n      return;\n    }\n\n    const defaultState = {};\n    Object.entries(fieldStates[viewType]).forEach(([field, fieldObj]) => {\n      const { show } = fieldObj;\n      defaultState[`show_${field}`] = show;\n    });\n\n    setAttributes({\n      fieldState: defaultState,\n    });\n  }, [viewType]); // eslint-disable-line react-hooks/exhaustive-deps -- We only want to set the values on viewType change.\n\n  const ArchiveLink = () => {\n    return archiveURL ? (\n      <a target=\"__blank\" href={archiveURL}>\n        {__('View archive page', 'web-stories')}\n      </a>\n    ) : null;\n  };\n\n  const handleToggleControl = (field) => {\n    setAttributes({\n      fieldState: {\n        ...fieldState,\n        [`show_${field}`]: !fieldState[`show_${field}`],\n      },\n    });\n  };\n\n  return (\n    <InspectorControls>\n      <PanelBody\n        className=\"web-stories-settings\"\n        title={__('Layout Options', 'web-stories')}\n      >\n        {fieldStates[viewType] &&\n          Object.entries(fieldStates[viewType]).map(([field, fieldObj]) => {\n            const { label, hidden } = fieldObj;\n\n            // @todo This shouldn't have dependency on field name, update field object appropriately.\n            if (\n              !hidden &&\n              'circle_size' !== field &&\n              'image_alignment' !== field\n            ) {\n              return (\n                <ToggleControl\n                  key={`${field}__control`}\n                  label={label}\n                  checked={fieldState[`show_${field}`] || false}\n                  onChange={() => handleToggleControl(field)}\n                  help={\n                    'archive_link' === field &&\n                    fieldState[`show_${field}`] && <ArchiveLink />\n                  }\n                  __nextHasNoMarginBottom\n                />\n              );\n            }\n\n            return false;\n          })}\n        {fieldState['show_archive_link'] && archiveURL && (\n          <TextControl\n            label={__('Archive Link Label', 'web-stories')}\n            value={archiveLinkLabel}\n            placeholder={__('View All Stories', 'web-stories')}\n            onChange={(newLabel) =>\n              setAttributes({ archiveLinkLabel: newLabel })\n            }\n            className=\"web-stories-settings-archive-link\"\n            __nextHasNoMarginBottom\n            __next40pxDefaultSize\n          />\n        )}\n      </PanelBody>\n      {[CIRCLES_VIEW_TYPE, GRID_VIEW_TYPE, LIST_VIEW_TYPE].includes(\n        viewType\n      ) && (\n        <PanelBody\n          className=\"web-stories-settings\"\n          title={__('Layout and Style Options', 'web-stories')}\n        >\n          {LIST_VIEW_TYPE === viewType && (\n            <RadioControl\n              label={__('Image Alignment', 'web-stories')}\n              selected={imageAlignment}\n              options={[\n                {\n                  value: 'left',\n                  label: __('Left', 'web-stories'),\n                },\n                {\n                  value: 'right',\n                  label: __('Right', 'web-stories'),\n                },\n              ]}\n              onChange={(value) => {\n                setAttributes({ imageAlignment: value });\n              }}\n            />\n          )}\n          {GRID_VIEW_TYPE === viewType && (\n            <RangeControl\n              label={__('Number of Columns', 'web-stories')}\n              value={numOfColumns}\n              onChange={(updatedNumOfColumns) =>\n                setAttributes({ numOfColumns: updatedNumOfColumns })\n              }\n              min={1}\n              max={4}\n              step={1}\n              __nextHasNoMarginBottom\n            />\n          )}\n          {CIRCLES_VIEW_TYPE === viewType && (\n            <RangeControl\n              label={__('Circle Size', 'web-stories')}\n              value={circleSize}\n              onChange={(updatedCircleSize) =>\n                setAttributes({ circleSize: updatedCircleSize })\n              }\n              min={80}\n              max={200}\n              step={5}\n              __nextHasNoMarginBottom\n            />\n          )}\n        </PanelBody>\n      )}\n      {showFilters && (\n        <PanelBody title={__('Sorting and Filtering', 'web-stories')}>\n          <SelectControl\n            label={__('Order By', 'web-stories')}\n            options={[\n              {\n                value: 'date',\n                label: __('Date', 'web-stories'),\n              },\n              {\n                value: 'title',\n                label: __('Title', 'web-stories'),\n              },\n            ]}\n            value={orderby || 'date'}\n            onChange={(selection) => setAttributes({ orderby: selection })}\n            __nextHasNoMarginBottom\n            __next40pxDefaultSize\n          />\n          <SelectControl\n            label={__('Order', 'web-stories')}\n            options={[\n              {\n                value: 'asc',\n                label: __('Ascending', 'web-stories'),\n              },\n              {\n                value: 'desc',\n                label: __('Descending', 'web-stories'),\n              },\n            ]}\n            value={order || 'desc'}\n            onChange={(selection) => setAttributes({ order: selection })}\n            __nextHasNoMarginBottom\n            __next40pxDefaultSize\n          />\n          {taxonomies.map((taxonomy) => {\n            const termIds = taxQuery?.[taxonomy.slug] || [];\n            const handleChange = (newTermIds) =>\n              setAttributes({\n                taxQuery: {\n                  ...taxQuery,\n                  [taxonomy.slug]: newTermIds,\n                },\n              });\n\n            return (\n              <TaxonomyItem\n                key={taxonomy.slug}\n                taxonomy={taxonomy}\n                termIds={termIds}\n                onChange={handleChange}\n              />\n            );\n          })}\n          <AuthorSelection authors={authors} setAttributes={setAttributes} />\n          <RangeControl\n            label={__('Number of Stories', 'web-stories')}\n            value={numOfStories}\n            onChange={(updatedNumOfStories) =>\n              setAttributes({ numOfStories: updatedNumOfStories })\n            }\n            min={1}\n            max={20}\n            step={1}\n            __nextHasNoMarginBottom\n          />\n        </PanelBody>\n      )}\n    </InspectorControls>\n  );\n};\n\nStoriesInspectorControls.propTypes = {\n  attributes: PropTypes.shape({\n    viewType: PropTypes.string,\n    numOfStories: PropTypes.number,\n    numOfColumns: PropTypes.number,\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n    archiveLinkLabel: PropTypes.string,\n    authors: PropTypes.array,\n    circleSize: PropTypes.number,\n    fieldState: PropTypes.object,\n    imageAlignment: PropTypes.string,\n    taxQuery: PropTypes.objectOf(PropTypes.number),\n  }),\n  setAttributes: PropTypes.func.isRequired,\n  showFilters: PropTypes.bool,\n};\n\nexport default StoriesInspectorControls;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storiesLoading.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { Spinner, Placeholder } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * StoriesLoading component. Displays a spinner when stories are being fetched.\n *\n * @return {*} JSX markup.\n */\nconst StoriesLoading = () => {\n  return (\n    <Placeholder\n      className=\"web-stories-placeholder\"\n      instructions={__('Loading Stories…', 'web-stories')}\n    >\n      <Spinner />\n    </Placeholder>\n  );\n};\n\nexport default StoriesLoading;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storiesPreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useEffect, useRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport {\n  CAROUSEL_VIEW_TYPE,\n  CIRCLES_VIEW_TYPE,\n  GRID_VIEW_TYPE,\n} from '../constants';\nimport StoryCard from './storyCard';\n\nconst {\n  config: { archiveURL },\n} = window.webStoriesBlockSettings;\n\nfunction StoriesPreview(props) {\n  const {\n    attributes: {\n      align,\n      viewType,\n      circleSize,\n      imageAlignment,\n      fieldState,\n      numOfColumns,\n    },\n    viewAllLabel,\n    stories,\n  } = props;\n\n  const carouselContainer = useRef(null);\n  const carouselNext = useRef(null);\n  const carouselPrev = useRef(null);\n\n  const blockClasses = classNames(\n    {\n      'is-style-default': !fieldState['show_sharp_corners'],\n      'is-style-squared': fieldState['show_sharp_corners'],\n      'is-carousel':\n        CIRCLES_VIEW_TYPE === viewType || CAROUSEL_VIEW_TYPE === viewType,\n      [`is-view-type-${viewType}`]: viewType,\n      [`columns-${numOfColumns}`]: GRID_VIEW_TYPE === viewType && numOfColumns,\n      [`align${align}`]: align,\n      'has-archive-link': fieldState['show_archive_link'],\n    },\n    'web-stories-list'\n  );\n\n  const StoriesLoop = () =>\n    stories.map((story) => {\n      const externalPoster = story.meta['web_stories_poster']?.url;\n      const featuredImage =\n        story._embedded?.['wp:featuredmedia']?.[0]?.source_url;\n      const posterImage = externalPoster || featuredImage;\n      return (\n        <StoryCard\n          key={story.id}\n          url={story.link}\n          title={story.title.rendered}\n          excerpt={story.excerpt.rendered ? story.excerpt.rendered : ''}\n          date={story.date_gmt}\n          author={story._embedded.author[0].name}\n          poster={posterImage}\n          imageAlignment={imageAlignment}\n          isShowingAuthor={fieldState['show_author']}\n          isShowingDate={fieldState['show_date']}\n          isShowingTitle={fieldState['show_title']}\n          isShowingExcerpt={fieldState['show_excerpt']}\n          circleSize={circleSize}\n        />\n      );\n    });\n\n  const supportsNativeCarousel = CSS.supports('scroll-marker-group: after');\n\n  useEffect(() => {\n    // Do not initialize Glider.js if browser supports CSS carousels.\n    if (supportsNativeCarousel) {\n      return;\n    }\n\n    if (!carouselContainer.current) {\n      return;\n    }\n    const storyItem = carouselContainer.current.querySelector(\n      '.web-stories-list__story'\n    );\n\n    if (!storyItem) {\n      return;\n    }\n\n    (async () => {\n      const itemStyle = window.getComputedStyle(storyItem);\n      const itemWidth =\n        Number.parseFloat(itemStyle.width) +\n        (Number.parseFloat(itemStyle.marginLeft) +\n          Number.parseFloat(itemStyle.marginRight));\n\n      const { default: Glider } = await import(\n        /* webpackChunkName: \"chunk-web-stories-glider\" */ '@web-stories-wp/glider' // @ts-expexct-error\n      );\n\n      const instance = new Glider(carouselContainer.current, {\n        slidesToShow: 'auto',\n        slidesToScroll: 'auto',\n        itemWidth,\n        duration: 0.25,\n        skipTrack: true,\n        scrollLock: true,\n        arrows: {\n          prev: carouselPrev.current,\n          next: carouselNext.current,\n        },\n      });\n\n      // Force resize to ensure Glider.js has the correct clientWidth for the carouselContainer.\n      instance.resize();\n\n      // Force correct trackWidth, especially when switching view types.\n      const trackWidth = itemWidth * stories.length;\n      instance.trackWidth = trackWidth;\n      instance.track.style.width = `${trackWidth}px`;\n    })();\n  }, [stories.length, viewType, circleSize, supportsNativeCarousel]);\n\n  return (\n    <div\n      className={blockClasses}\n      style={{\n        '--ws-circle-size':\n          'circles' === viewType && circleSize ? `${circleSize}px` : undefined,\n      }}\n    >\n      {fieldState['show_archive_link'] && archiveURL && (\n        <div className=\"web-stories-list__archive-link\">\n          <a target=\"__blank\" href={archiveURL}>\n            {viewAllLabel}\n          </a>\n        </div>\n      )}\n      <div className=\"web-stories-list__inner-wrapper\">\n        {CIRCLES_VIEW_TYPE === viewType || CAROUSEL_VIEW_TYPE === viewType ? (\n          <>\n            <div className=\"web-stories-list__carousel\" ref={carouselContainer}>\n              {supportsNativeCarousel ? (\n                <StoriesLoop />\n              ) : (\n                <div className=\"glider-track\">\n                  <StoriesLoop />\n                </div>\n              )}\n            </div>\n            <div\n              aria-label={__('Previous', 'web-stories')}\n              className=\"glider-prev\"\n              ref={carouselPrev}\n            />\n            <div\n              aria-label={__('Next', 'web-stories')}\n              className=\"glider-next\"\n              ref={carouselNext}\n            />\n          </>\n        ) : (\n          <StoriesLoop />\n        )}\n      </div>\n    </div>\n  );\n}\n\nStoriesPreview.propTypes = {\n  attributes: PropTypes.shape({\n    align: PropTypes.string,\n    viewType: PropTypes.string,\n    numOfColumns: PropTypes.number,\n    circleSize: PropTypes.number,\n    fieldState: PropTypes.object,\n    imageAlignment: PropTypes.string,\n  }),\n  stories: PropTypes.array,\n  viewAllLabel: PropTypes.string,\n};\n\nexport default StoriesPreview;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyCard.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\n/**\n * WordPress dependencies\n */\nimport { RawHTML } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { dateI18n, format, getSettings } from '@wordpress/date';\n\nfunction StoryCard({\n  title,\n  excerpt,\n  poster,\n  author,\n  date,\n  isShowingAuthor,\n  isShowingDate,\n  isShowingTitle,\n  isShowingExcerpt,\n  imageAlignment,\n}) {\n  const singleStoryClasses = classNames('web-stories-list__story', {\n    [`image-align-right`]: imageAlignment === 'right',\n  });\n  const hasContentOverlay = isShowingTitle || isShowingAuthor || isShowingDate;\n\n  const dateFormat = getSettings().formats.date;\n\n  return (\n    <div className={singleStoryClasses}>\n      <div className=\"web-stories-list__story-poster\">\n        {poster ? (\n          <img src={poster} alt={title} />\n        ) : (\n          <div className=\"web-stories-list__story-poster-placeholder\">\n            <span>{title}</span>\n          </div>\n        )}\n      </div>\n      {hasContentOverlay && (\n        <div className=\"story-content-overlay web-stories-list__story-content-overlay\">\n          {isShowingTitle && title && (\n            <RawHTML className=\"story-content-overlay__title\">{title}</RawHTML>\n          )}\n          {isShowingExcerpt && excerpt && (\n            <RawHTML className=\"story-content-overlay__excerpt\">\n              {excerpt}\n            </RawHTML>\n          )}\n          {isShowingAuthor && (\n            <div className=\"story-content-overlay__author\">\n              {sprintf(\n                /* translators: byline. %s: author name. */\n                __('By %s', 'web-stories'),\n                author\n              )}\n            </div>\n          )}\n          {isShowingDate && (\n            <time\n              dateTime={format('c', date)}\n              className=\"story-content-overlay__date\"\n            >\n              {sprintf(\n                /* translators: %s: publish date. */\n                __('On %s', 'web-stories'),\n                dateI18n(dateFormat, date)\n              )}\n            </time>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n\nStoryCard.propTypes = {\n  title: PropTypes.string,\n  excerpt: PropTypes.string,\n  poster: PropTypes.string,\n  author: PropTypes.string,\n  date: PropTypes.string,\n  isShowingAuthor: PropTypes.bool,\n  isShowingDate: PropTypes.bool,\n  isShowingTitle: PropTypes.bool,\n  isShowingExcerpt: PropTypes.bool,\n  imageAlignment: PropTypes.string,\n};\n\nexport default StoryCard;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/fetchSelectedStories.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { useEffect } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\nimport { Placeholder } from '@wordpress/components';\nimport { BlockIcon } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport LoaderContainer from '../loaderContainer';\n\nfunction FetchSelectedStories({\n  icon,\n  label,\n  selectedStoryIds = [],\n  setSelectedStories,\n  setIsFetching,\n}) {\n  const data = useSelect((select) => {\n    return select(coreStore).getEntityRecords('postType', 'web-story', {\n      _embed: 'wp:featuredmedia,author',\n      context: 'view',\n      include: selectedStoryIds,\n      orderby: selectedStoryIds.length > 0 ? 'include' : undefined,\n    });\n  });\n\n  useEffect(() => {\n    // data is null before a response\n    // has some value after the request\n    // is undefined if the entities requested does not exist\n    if (data !== null && data !== undefined) {\n      //Entities found\n      setSelectedStories(data);\n      setIsFetching(false);\n    }\n    if (data === undefined) {\n      //could not find entities\n      setSelectedStories([]);\n      setIsFetching(false);\n    }\n  }, [data, setSelectedStories, setIsFetching]);\n\n  return (\n    <Placeholder\n      icon={<BlockIcon icon={icon} showColors />}\n      label={label}\n      className=\"wp-block-web-stories-embed\"\n      instructions={false}\n    >\n      <LoaderContainer>{__('Loading Stories…', 'web-stories')}</LoaderContainer>\n    </Placeholder>\n  );\n}\n\nFetchSelectedStories.propTypes = {\n  icon: PropTypes.node,\n  label: PropTypes.string,\n  selectedStoryIds: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n  setIsFetching: PropTypes.func,\n};\n\nexport default FetchSelectedStories;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/itemOverlay.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { Icon, VisuallyHidden } from '@wordpress/components';\nimport { useCallback } from '@wordpress/element';\nimport { __ } from '@wordpress/i18n';\n\nfunction ItemOverlay({\n  isSelected,\n  story,\n  addSelectedStory,\n  removeSelectedStory,\n  isSelectable,\n}) {\n  const onClickOverlay = useCallback(\n    (event) => {\n      event.preventDefault();\n\n      if (isSelected) {\n        return;\n      }\n\n      addSelectedStory(story);\n    },\n    [addSelectedStory, story, isSelected]\n  );\n\n  const onClickIcon = useCallback(\n    (event) => {\n      event.preventDefault();\n\n      if (isSelected) {\n        removeSelectedStory(story);\n      } else {\n        addSelectedStory(story);\n      }\n    },\n    [removeSelectedStory, addSelectedStory, story, isSelected]\n  );\n\n  if (!isSelectable) {\n    return <div className=\"web-stories-story-preview-card__overlay\" />;\n  }\n\n  return (\n    <button\n      type=\"button\"\n      className={\n        isSelected\n          ? 'web-stories-story-preview-card__overlay item-selected'\n          : 'web-stories-story-preview-card__overlay'\n      }\n      onClick={onClickOverlay}\n    >\n      {isSelected && (\n        <div className=\"item-selected-icon\">\n          <Icon className=\"item-selected-icon-check\" icon=\"saved\" />\n          <Icon\n            className=\"item-selected-icon-minus\"\n            icon=\"minus\"\n            onClick={onClickIcon}\n          />\n          <VisuallyHidden>{__('Deselect', 'web-stories')}</VisuallyHidden>\n        </div>\n      )}\n    </button>\n  );\n}\n\nItemOverlay.propTypes = {\n  isSelected: PropTypes.bool,\n  story: PropTypes.object.isRequired,\n  addSelectedStory: PropTypes.func,\n  removeSelectedStory: PropTypes.func,\n  isSelectable: PropTypes.bool,\n};\n\nexport default ItemOverlay;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/selectStories.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@wordpress/element';\nimport {\n  ComboboxControl,\n  SelectControl,\n  Spinner,\n  Button,\n} from '@wordpress/components';\nimport { useSelect } from '@wordpress/data';\nimport { useDebounce } from '@wordpress/compose';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport StoryPreview from './storyPreview';\n\nconst SORT_OPTIONS = [\n  {\n    label: __('Name', 'web-stories'),\n    value: 'name',\n  },\n  {\n    label: __('Date Created', 'web-stories'),\n    value: 'date',\n  },\n  {\n    label: __('Last Modified', 'web-stories'), // default\n    value: 'modified',\n  },\n  {\n    label: __('Created By', 'web-stories'),\n    value: 'author',\n  },\n];\n\nfunction AuthorSearch({\n  label,\n  options,\n  onFilterValueChange,\n  onChange,\n  value,\n}) {\n  return (\n    <ComboboxControl\n      label={label}\n      options={options}\n      onFilterValueChange={onFilterValueChange}\n      onChange={onChange}\n      value={value}\n      className=\"web-stories-story-picker-filter__combobox\"\n      __nextHasNoMarginBottom\n      __next40pxDefaultSize\n    />\n  );\n}\n\nAuthorSearch.propTypes = {\n  label: PropTypes.string,\n  options: PropTypes.array,\n  value: PropTypes.number,\n  onFilterValueChange: PropTypes.func,\n  onChange: PropTypes.func,\n};\n\nfunction KeywordSearch({\n  label,\n  options,\n  onFilterValueChange,\n  onChange,\n  value,\n}) {\n  return (\n    <ComboboxControl\n      label={label}\n      options={options}\n      onFilterValueChange={onFilterValueChange}\n      onChange={onChange}\n      value={value}\n      className=\"web-stories-story-picker-filter__combobox\"\n      __nextHasNoMarginBottom\n      __next40pxDefaultSize\n    />\n  );\n}\n\nKeywordSearch.propTypes = {\n  label: PropTypes.string,\n  options: PropTypes.array,\n  value: PropTypes.string,\n  onFilterValueChange: PropTypes.func,\n  onChange: PropTypes.func,\n};\n\nconst STABLE_ARRAY = [];\n\nfunction SelectStories({\n  stories = STABLE_ARRAY,\n  selectedStories = STABLE_ARRAY,\n  setSelectedStories,\n  hasAllStories,\n  isLoading,\n  fetchStories,\n  maxNumOfStories,\n}) {\n  const [currentAuthor, setCurrentAuthor] = useState([]);\n  const [searchKeyword, setSearchKeyword] = useState('');\n  const [authorKeyword, setAuthorKeyword] = useState('');\n  const [order, setOrder] = useState('desc');\n  const [orderBy, setOrderBy] = useState('modified');\n  const nextPageRef = useRef(1);\n\n  const { authors } = useSelect(\n    (select) => {\n      const { getUsers, getPostType } = select(coreStore);\n\n      const capabilities = getPostType('web-story')?.capabilities['edit_posts'];\n\n      const query = {\n        search: authorKeyword,\n        capabilities,\n      };\n      return {\n        // Only load users when capability has been fetched already.\n        authors: capabilities ? getUsers(query) : STABLE_ARRAY,\n      };\n    },\n    [authorKeyword]\n  );\n\n  const fetchSelectedStories = useCallback(() => {\n    fetchStories({\n      author: currentAuthor?.id || undefined,\n      search: searchKeyword || undefined,\n      order,\n      orderby: orderBy,\n      page: nextPageRef.current,\n    });\n  }, [searchKeyword, currentAuthor, fetchStories, order, orderBy]);\n\n  useEffect(() => {\n    nextPageRef.current = 1;\n    fetchSelectedStories();\n  }, [searchKeyword, currentAuthor, order, orderBy, fetchSelectedStories]);\n\n  const onLoadMoreClick = useCallback(() => {\n    nextPageRef.current++;\n    fetchSelectedStories();\n  }, [fetchSelectedStories]);\n\n  const debouncedTypeaheadChange = useDebounce((value) => {\n    setSearchKeyword(value);\n  }, 300);\n\n  const debouncedTypeaheadAuthorChange = useDebounce((value) => {\n    setAuthorKeyword(value);\n\n    if ('' === value) {\n      setCurrentAuthor(null);\n    } else {\n      setCurrentAuthor(authors.find((author) => author.id === Number(value)));\n    }\n  }, 300);\n\n  const handleAuthorChange = useCallback(\n    (value) => {\n      // On selecting author from the dropdown, '<Search />' component sets the newOption from the\n      // suggestions array, which in our case is author ID. Check the newOption is a number.\n      if ('' === value) {\n        setCurrentAuthor(null);\n      } else {\n        setCurrentAuthor(authors.find((author) => author.id === Number(value)));\n      }\n    },\n    [authors, setCurrentAuthor]\n  );\n\n  const onSortChange = useCallback(\n    (newSort) => {\n      setOrderBy(newSort);\n      setOrder(['title', 'author'].includes(newSort) ? 'asc' : 'desc');\n    },\n    [setOrder, setOrderBy]\n  );\n\n  const authorSearchOptions = useMemo(() => {\n    return (authors ?? [])\n      .filter(({ name }) => Boolean(name?.trim().length))\n      .map(({ id, name }) => ({\n        label: name,\n        value: id,\n      }));\n  }, [authors]);\n\n  const storiesSearchOptions = useMemo(() => {\n    return stories\n      .filter(({ title }) => Boolean(title?.rendered?.trim()?.length))\n      .map(({ id, title }) => ({\n        label: title.rendered,\n        value: id,\n      }));\n  }, [stories]);\n\n  const selectedStoryIds = useMemo(\n    () => selectedStories.map((story) => story.id),\n    [selectedStories]\n  );\n\n  const addSelectedStory = useCallback(\n    (newStory) => {\n      if (selectedStoryIds.includes(newStory.id)) {\n        return;\n      }\n\n      // Special case for single story embeds to always change selection.\n      if (1 === maxNumOfStories) {\n        setSelectedStories([newStory]);\n        return;\n      }\n\n      if (selectedStories.length >= maxNumOfStories) {\n        return;\n      }\n\n      setSelectedStories([...selectedStories, newStory]);\n    },\n    [setSelectedStories, selectedStories, selectedStoryIds, maxNumOfStories]\n  );\n\n  const removeSelectedStory = useCallback(\n    (story) => {\n      setSelectedStories(\n        selectedStories.filter((_story) => _story.id !== story.id)\n      );\n    },\n    [selectedStories, setSelectedStories]\n  );\n\n  return (\n    <>\n      <div className=\"web-stories-story-picker-filter\">\n        <div className=\"web-stories-story-picker-filter__search-container\">\n          <div className=\"web-stories-story-picker-filter__search-inner\">\n            <KeywordSearch\n              label={__('Search Stories', 'web-stories')}\n              options={storiesSearchOptions}\n              onFilterValueChange={debouncedTypeaheadChange}\n              onChange={debouncedTypeaheadChange}\n              value={searchKeyword}\n            />\n          </div>\n          <AuthorSearch\n            label={__('Search by Author', 'web-stories')}\n            options={authorSearchOptions}\n            onFilterValueChange={debouncedTypeaheadAuthorChange}\n            onChange={handleAuthorChange}\n            value={currentAuthor?.id}\n          />\n          <div>\n            <SelectControl\n              label={__('Sort', 'web-stories')}\n              options={SORT_OPTIONS}\n              value={orderBy}\n              onChange={onSortChange}\n              __nextHasNoMarginBottom\n              __next40pxDefaultSize\n            />\n          </div>\n        </div>\n      </div>\n      {!stories.length && searchKeyword && (\n        <p>\n          {sprintf(\n            /* translators: %s: search term. */\n            __(\n              `Sorry, we couldn't find any results matching \"%s\"`,\n              'web-stories'\n            ),\n            searchKeyword\n          )}\n        </p>\n      )}\n      {!stories.length && !searchKeyword && (\n        <p>{__(`Sorry, we couldn't find any results`, 'web-stories')}</p>\n      )}\n      {stories.length >= 1 && (\n        <div\n          role=\"list\"\n          aria-label={__('Viewing Stories', 'web-stories')}\n          className=\"web-stories-story-picker-filter__grid\"\n        >\n          {stories.map((story) => {\n            const isSelected = selectedStoryIds.includes(story.id);\n\n            return (\n              <div\n                key={story.id}\n                role=\"listitem\"\n                className=\"web-stories-story-picker-filter__grid_item\"\n              >\n                <StoryPreview\n                  story={story}\n                  isSelected={isSelected}\n                  addSelectedStory={addSelectedStory}\n                  removeSelectedStory={removeSelectedStory}\n                />\n              </div>\n            );\n          })}\n        </div>\n      )}\n      <div className=\"web-stories-story-picker-filter__load_more\">\n        {isLoading && <Spinner />}\n        {!hasAllStories && stories.length > 0 && !isLoading && (\n          <Button\n            variant=\"primary\"\n            className=\"is-primary\"\n            onClick={onLoadMoreClick}\n          >\n            {__('Load More', 'web-stories')}\n          </Button>\n        )}\n      </div>\n    </>\n  );\n}\n\nSelectStories.propTypes = {\n  stories: PropTypes.array,\n  selectedStories: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n  hasAllStories: PropTypes.bool,\n  isLoading: PropTypes.bool,\n  fetchStories: PropTypes.func,\n  maxNumOfStories: PropTypes.number,\n};\n\nexport default SelectStories;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/sortStories.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { Draggable } from '@wordpress/components';\nimport { useCallback, useState } from '@wordpress/element';\nimport { useThrottle } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport StoryPreview from './storyPreview';\n\nfunction SortStories({ selectedStories, setSelectedStories }) {\n  const [droppingToIndex, setDroppingToIndex] = useState();\n  const [draggedElementId, setDraggedElementId] = useState();\n\n  const rearrangeStories = useCallback(\n    (oldIndex, newIndex) => {\n      const newList = selectedStories.map((story) => story.id);\n      newList.splice(newIndex, 0, newList.splice(oldIndex, 1).pop());\n      setSelectedStories(\n        newList.map((storyId) => {\n          return selectedStories.find((story) => story.id === storyId);\n        })\n      );\n    },\n    [selectedStories, setSelectedStories]\n  );\n\n  const throttledOnDragOver = useThrottle((event, currentTarget) => {\n    event.preventDefault();\n\n    currentTarget.classList.add('web-stories-story-picker-show-drag-inserter');\n\n    const targetElementRect = currentTarget.getBoundingClientRect();\n\n    const isDraggingOnRightSide =\n      Math.abs(event.clientX - targetElementRect.x) >\n      Math.abs(event.clientX - (targetElementRect.x + targetElementRect.width));\n\n    if (isDraggingOnRightSide) {\n      currentTarget.classList.add(\n        'web-stories-story-picker-show-drag-inserter-right'\n      );\n    } else {\n      currentTarget.classList.remove(\n        'web-stories-story-picker-show-drag-inserter-right'\n      );\n    }\n\n    const dropIndex = Number(currentTarget.children[0].dataset.order);\n\n    setDroppingToIndex(dropIndex);\n  });\n\n  return (\n    <div\n      role=\"list\"\n      aria-label={__('Sorting Stories', 'web-stories')}\n      className=\"web-stories-story-picker-filter__grid\"\n    >\n      {selectedStories.map((story, index) => {\n        return (\n          <div\n            key={story.id}\n            onDragOver={(event) => {\n              // `currentTarget` is only available while the event is being\n              // handled, so get it now and pass it to the throttled function.\n              // https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget\n              throttledOnDragOver(event, event.currentTarget);\n            }}\n            onDragLeave={(event) => {\n              event.preventDefault();\n              throttledOnDragOver.cancel();\n              const targetElement = event.target.closest('.droppable');\n              targetElement.classList.remove(\n                'web-stories-story-picker-show-drag-inserter',\n                'web-stories-story-picker-show-drag-inserter-right'\n              );\n            }}\n            onDrop={(event) => {\n              event.preventDefault();\n              event.stopPropagation();\n\n              throttledOnDragOver.cancel();\n\n              // Update the list after drop\n              if (draggedElementId) {\n                const oldIndex = selectedStories.findIndex(\n                  (storyItem) => storyItem.id === draggedElementId\n                );\n                rearrangeStories(oldIndex, droppingToIndex);\n              }\n\n              const targetElement = event.target.closest('.droppable');\n              targetElement.classList.remove(\n                'web-stories-story-picker-show-drag-inserter',\n                'web-stories-story-picker-show-drag-inserter-right'\n              );\n            }}\n            className=\"droppable\"\n          >\n            <div data-order={index} id={`draggable-story-${story.id}`}>\n              <Draggable elementId={`draggable-story-${story.id}`}>\n                {({ onDraggableStart, onDraggableEnd }) => {\n                  const handleOnDragStart = (event) => {\n                    setDraggedElementId(story.id);\n                    onDraggableStart(event);\n                  };\n                  const handleOnDragEnd = (event) => {\n                    onDraggableEnd(event);\n                  };\n\n                  return (\n                    <div\n                      key={story.id}\n                      role=\"listitem\"\n                      className=\"web-stories-story-picker-filter__grid_item\"\n                      onDragStart={handleOnDragStart}\n                      onDragEnd={handleOnDragEnd}\n                      data-order={index}\n                      draggable\n                    >\n                      <StoryPreview story={story} isSelectable={false} />\n                    </div>\n                  );\n                }}\n              </Draggable>\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n}\n\nSortStories.propTypes = {\n  selectedStories: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n};\n\nexport default SortStories;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/storyPicker.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __, _n, sprintf } from '@wordpress/i18n';\nimport { Button, Modal } from '@wordpress/components';\nimport { useState, useEffect, useCallback } from '@wordpress/element';\nimport apiFetch from '@wordpress/api-fetch';\nimport { useDispatch } from '@wordpress/data';\nimport { addQueryArgs } from '@wordpress/url';\nimport { store as noticesStore } from '@wordpress/notices';\n\n/**\n * Internal dependencies\n */\nimport LoaderContainer from '../loaderContainer';\nimport SelectStories from './selectStories';\nimport SortStories from './sortStories';\n\nconst {\n  config: {\n    api: { stories: storiesApi },\n  },\n} = window.webStoriesBlockSettings;\n\nfunction StoryPicker({\n  selectedStories,\n  setSelectedStories,\n  closeStoryPicker,\n  isSortingStories = false,\n  setIsSortingStories = () => {},\n  maxNumOfStories,\n}) {\n  const { createErrorNotice } = useDispatch(noticesStore);\n\n  const [localSelectedStories, setLocalSelectedStories] =\n    useState(selectedStories);\n\n  const [isFetchingForFirstTime, setIsFetchingForFirstTime] = useState(true);\n\n  const [loadingState, setLoadingState] = useState('idle');\n  const [stories, setStories] = useState([]);\n  const [hasAllStories, setHasAllStories] = useState([]);\n\n  const saveChanges = useCallback(() => {\n    closeStoryPicker();\n    setSelectedStories(localSelectedStories);\n  }, [closeStoryPicker, setSelectedStories, localSelectedStories]);\n\n  const fetchStories = useCallback(\n    async ({\n      orderby = 'modified',\n      order = 'desc',\n      search = undefined,\n      author = undefined,\n      page = 1,\n    } = {}) => {\n      const query = {\n        _embed: 'author,wp:featuredmedia',\n        context: 'edit',\n        _web_stories_envelope: true,\n        search,\n        author,\n        page,\n        per_page: 10,\n        orderby,\n        order,\n        status: 'publish',\n      };\n\n      try {\n        setLoadingState('loading');\n        const response = await apiFetch({\n          path: addQueryArgs(storiesApi, query),\n        });\n\n        const totalPages = Number(response?.headers?.['X-WP-TotalPages']);\n\n        setHasAllStories(page === totalPages);\n        setStories((existingStories) =>\n          page === 1 ? response.body : [...existingStories, ...response.body]\n        );\n      } catch {\n        setLoadingState('error');\n        createErrorNotice(__('Unable to load stories', 'web-stories'), {\n          type: 'snackbar',\n        });\n      } finally {\n        setLoadingState('idle');\n        setIsFetchingForFirstTime(false);\n      }\n    },\n    [createErrorNotice]\n  );\n\n  useEffect(() => {\n    if (isFetchingForFirstTime) {\n      fetchStories();\n    }\n  }, [isFetchingForFirstTime, fetchStories]);\n\n  const title =\n    maxNumOfStories === 1\n      ? __('Selected Story', 'web-stories')\n      : __('Selected Stories', 'web-stories');\n\n  return (\n    <Modal\n      title={title}\n      onRequestClose={closeStoryPicker}\n      shouldCloseOnClickOutside={false}\n      className=\"web-stories-story-picker-modal\"\n    >\n      <div className=\"web-stories-story-picker-modal__content\">\n        {isFetchingForFirstTime ? (\n          <LoaderContainer>\n            {__('Loading Stories…', 'web-stories')}\n          </LoaderContainer>\n        ) : isSortingStories ? (\n          <SortStories\n            selectedStories={localSelectedStories}\n            setSelectedStories={setLocalSelectedStories}\n          />\n        ) : (\n          <SelectStories\n            stories={stories}\n            selectedStories={localSelectedStories}\n            setSelectedStories={setLocalSelectedStories}\n            hasAllStories={hasAllStories}\n            fetchStories={fetchStories}\n            maxNumOfStories={maxNumOfStories}\n            isLoading={loadingState === 'loading'}\n          />\n        )}\n      </div>\n      <div className=\"web-stories-story-picker-modal__footer\">\n        <div className=\"web-stories-story-picker-modal__footer--left\">\n          {!isSortingStories &&\n            !isFetchingForFirstTime &&\n            maxNumOfStories > 1 && (\n              <p>\n                {sprintf(\n                  /* translators: %1$d: Number of selected stories, %2$d: Maximum allowed stories */\n                  _n(\n                    '%1$d of %2$d story selected',\n                    '%1$d of %2$d stories selected',\n                    maxNumOfStories,\n                    'web-stories'\n                  ),\n                  localSelectedStories.length,\n                  maxNumOfStories\n                )}\n              </p>\n            )}\n        </div>\n        <div className=\"web-stories-story-picker-modal__footer--right\">\n          {maxNumOfStories > 1 &&\n            (isSortingStories ? (\n              <Button onClick={() => setIsSortingStories(false)}>\n                {__('Select Stories', 'web-stories')}\n              </Button>\n            ) : (\n              <Button\n                onClick={() => setIsSortingStories(true)}\n                disabled={localSelectedStories.length < 2}\n              >\n                {__('Rearrange Stories', 'web-stories')}\n              </Button>\n            ))}\n          <Button\n            isPrimary\n            disabled={!localSelectedStories.length}\n            onClick={saveChanges}\n          >\n            {__('Update', 'web-stories')}\n          </Button>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n\nStoryPicker.propTypes = {\n  selectedStories: PropTypes.array,\n  setSelectedStories: PropTypes.func,\n  closeStoryPicker: PropTypes.func,\n  isSortingStories: PropTypes.bool,\n  setIsSortingStories: PropTypes.func,\n  maxNumOfStories: PropTypes.number,\n};\n\nexport default StoryPicker;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/storyPicker/storyPreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport { dateI18n, getSettings } from '@wordpress/date';\nimport { RawHTML, useMemo } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport ItemOverlay from './itemOverlay';\n\nconst noop = () => {};\n\nfunction StoryPreview({\n  story,\n  isSelected,\n  addSelectedStory = noop,\n  removeSelectedStory = noop,\n  isSelectable = true,\n}) {\n  const dateFormat = getSettings().formats.date;\n  const displayDate = dateI18n(dateFormat, story.created);\n  const displayDateText = useMemo(() => {\n    if (!displayDate) {\n      return null;\n    }\n\n    switch (story.status) {\n      case 'publish':\n        return sprintf(\n          /* translators: %s: published date */\n          __('Published %s', 'web-stories'),\n          displayDate\n        );\n\n      case 'future':\n        return sprintf(\n          /* translators: %s: future publish date */\n          __('Scheduled %s', 'web-stories'),\n          displayDate\n        );\n\n      default:\n        return sprintf(\n          /* translators: %s: last modified date */\n          __('Modified %s', 'web-stories'),\n          displayDate\n        );\n    }\n  }, [story.status, displayDate]);\n\n  const externalPoster = story.meta['web_stories_poster']?.url;\n  const featuredImage = story._embedded?.['wp:featuredmedia']?.[0]?.source_url;\n  const posterImage = externalPoster || featuredImage;\n  const storyTitle = story.title.raw || story.title.rendered;\n\n  return (\n    <div className=\"web-stories-story-preview-card\">\n      <div className=\"web-stories-story-preview-card__poster\">\n        <ItemOverlay\n          isSelected={isSelected}\n          story={story}\n          addSelectedStory={addSelectedStory}\n          removeSelectedStory={removeSelectedStory}\n          isSelectable={isSelectable}\n        />\n        {posterImage && (\n          <img src={posterImage} alt=\"\" width={640} height={853} />\n        )}\n      </div>\n      <div className=\"web-stories-story-preview-card__label\">\n        <div className=\"web-stories-story-preview-card__title\">\n          <RawHTML>\n            {storyTitle === '' ? __('Untitled', 'web-stories') : storyTitle}\n          </RawHTML>\n        </div>\n        {story._embedded?.author?.[0]?.name && (\n          <div>{story._embedded?.author?.[0]?.name}</div>\n        )}\n        <div>{displayDateText}</div>\n      </div>\n    </div>\n  );\n}\n\nStoryPreview.propTypes = {\n  story: PropTypes.object.isRequired,\n  isSelected: PropTypes.bool,\n  addSelectedStory: PropTypes.func,\n  removeSelectedStory: PropTypes.func,\n  isSelectable: PropTypes.bool,\n};\n\nexport default StoryPreview;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/taxonomyItem.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { FormTokenField } from '@wordpress/components';\nimport { useEffect, useState } from '@wordpress/element';\nimport { useDebounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\n\nconst BASE_QUERY = {\n  order: 'asc',\n  _fields: 'id,name',\n  context: 'view',\n};\n\n// Helper function to get the term id based on user input in terms `FormTokenField`.\nconst getTermIdByTermValue = (terms, termValue) => {\n  // First we check for exact match by `term.id` or case-sensitive `term.name` match.\n  const termId =\n    termValue?.id || terms?.find((term) => term.name === termValue)?.id;\n  if (termId) {\n    return termId;\n  }\n\n  /**\n   * Here we make an extra check for entered terms in a non case sensitive way,\n   * to match user expectations, due to `FormTokenField` behaviour that shows\n   * suggestions which are case insensitive.\n   *\n   * Although WP tries to discourage users to add terms with the same name (case insensitive),\n   * it's still possible if you manually change the name, as long as the terms have different slugs.\n   * In this edge case we always apply the first match from the terms list.\n   */\n  const termValueLower = termValue.toLocaleLowerCase();\n  return terms?.find((term) => term.name.toLocaleLowerCase() === termValueLower)\n    ?.id;\n};\n\n/**\n * Renders a `FormTokenField` for a given taxonomy.\n *\n * @param {Object}   props          The props for the component.\n * @param {Object}   props.taxonomy The taxonomy object.\n * @param {number[]} props.termIds  An array with the block's term ids for the given taxonomy.\n * @param {Function} props.onChange Callback `onChange` function.\n * @return {*} JSX markup.\n */\nfunction TaxonomyItem({ taxonomy, termIds, onChange }) {\n  const [search, setSearch] = useState('');\n  const [value, setValue] = useState([]);\n  const [suggestions, setSuggestions] = useState([]);\n  const debouncedSearch = useDebounce(setSearch, 250);\n  const { searchResults, searchHasResolved } = useSelect(\n    (select) => {\n      if (!search) {\n        return { searchResults: [], searchHasResolved: true };\n      }\n      const { getEntityRecords, hasFinishedResolution } = select(coreStore);\n      const selectorArgs = [\n        'taxonomy',\n        taxonomy.slug,\n        {\n          ...BASE_QUERY,\n          search,\n          orderby: 'name',\n          exclude: termIds,\n          per_page: 20,\n        },\n      ];\n      return {\n        searchResults: getEntityRecords(...selectorArgs),\n        searchHasResolved: hasFinishedResolution(\n          'getEntityRecords',\n          selectorArgs\n        ),\n      };\n    },\n    [search, termIds, taxonomy.slug]\n  );\n  // `existingTerms` are the ones fetched from the API and their type is `{ id: number; name: string }`.\n  // They are used to extract the terms' names to populate the `FormTokenField` properly\n  // and to sanitize the provided `termIds`, by setting only the ones that exist.\n  const existingTerms = useSelect(\n    (select) => {\n      if (!termIds?.length) {\n        return [];\n      }\n      const { getEntityRecords } = select(coreStore);\n      return getEntityRecords('taxonomy', taxonomy.slug, {\n        ...BASE_QUERY,\n        include: termIds,\n        per_page: termIds.length,\n      });\n    },\n    [termIds, taxonomy.slug]\n  );\n  // Update the `value` state only after the selectors are resolved\n  // to avoid emptying the input when we're changing terms.\n  useEffect(() => {\n    if (!termIds?.length) {\n      setValue([]);\n    }\n    if (!existingTerms?.length) {\n      return;\n    }\n    // Returns only the existing entity ids. This prevents the component\n    // from crashing in the editor, when non-existing ids are provided.\n    const sanitizedValue = termIds.reduce((accumulator, id) => {\n      const entity = existingTerms.find((term) => term.id === id);\n      if (entity) {\n        accumulator.push({\n          id,\n          value: entity.name,\n        });\n      }\n      return accumulator;\n    }, []);\n    setValue(sanitizedValue);\n  }, [termIds, existingTerms]);\n  // Update suggestions only when the query has resolved.\n  useEffect(() => {\n    if (!searchHasResolved) {\n      return;\n    }\n    setSuggestions(searchResults.map((result) => result.name));\n  }, [searchResults, searchHasResolved]);\n  const onTermsChange = (newTermValues) => {\n    const newTermIds = new Set();\n    for (const termValue of newTermValues) {\n      const termId = getTermIdByTermValue(searchResults, termValue);\n      if (termId) {\n        newTermIds.add(termId);\n      }\n    }\n    setSuggestions([]);\n    onChange(Array.from(newTermIds));\n  };\n  return (\n    <div className=\"block-library-query-inspector__taxonomy-control\">\n      <FormTokenField\n        label={taxonomy.name}\n        value={value}\n        onInputChange={debouncedSearch}\n        suggestions={suggestions}\n        onChange={onTermsChange}\n        __experimentalShowHowTo={false}\n        __nextHasNoMarginBottom\n      />\n    </div>\n  );\n}\n\nTaxonomyItem.propTypes = {\n  taxonomy: PropTypes.shape({\n    id: PropTypes.number,\n    slug: PropTypes.string,\n    name: PropTypes.string,\n  }).isRequired,\n  onChange: PropTypes.func.isRequired,\n  termIds: PropTypes.arrayOf(PropTypes.number),\n};\n\nexport default TaxonomyItem;\n"
  },
  {
    "path": "packages/stories-block/src/block/components/test/blockTypeSwitcher.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport BlockTypeSwitcher from '../blockTypeSwitcher';\n\ndescribe('Tests BlockTypeSwitcher', () => {\n  it('should render block type switcher without errors', () => {\n    const setAttributes = jest.fn();\n    render(\n      <BlockTypeSwitcher selectedBlockType={''} setAttributes={setAttributes} />\n    );\n\n    const switchButton = screen.getByLabelText('Change Type');\n    expect(switchButton).toBeInTheDocument();\n  });\n\n  it('should call setAttribute on block type change', async () => {\n    const setAttributes = jest.fn();\n    render(\n      <BlockTypeSwitcher selectedBlockType={''} setAttributes={setAttributes} />\n    );\n\n    const switchButton = screen.getByLabelText('Change Type');\n\n    // Opens Switcher dropdown menu.\n    fireEvent.click(switchButton);\n\n    const selectionMenu = await screen.findByRole('menu');\n\n    // Assert that the menu exists.\n    expect(selectionMenu).toBeInTheDocument();\n\n    const menuItem = screen.getByText('Latest Stories');\n\n    // Select block type.\n    fireEvent.click(menuItem);\n\n    // Confirm that the menuItem was clicked.\n    expect(setAttributes).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/components/test/loaderContainer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport LoaderContainer from '../loaderContainer';\n\ndescribe('LoaderContainer', () => {\n  it('should render provided children with spinner component', () => {\n    render(\n      <LoaderContainer>\n        <div>{__('Loading Stories…', 'web-stories')}</div>\n      </LoaderContainer>\n    );\n    expect(screen.getByText('Loading Stories…')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/components/test/storyCard.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport StoryCard from '../storyCard';\n\njest.mock('@wordpress/date', () => ({\n  /* eslint-disable no-unused-vars */\n  format: (format, dateTo) => date,\n  dateI18n: (format, dateTo) => 'November 18, 2020',\n  getSettings: () => ({\n    formats: {\n      date: 'F j, Y',\n    },\n  }),\n  /* eslint-enable no-unused-vars */\n}));\n\nconst title = 'Stories in AMP';\nconst poster = 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg';\nconst date = '2020-11-18T13:36:35';\nconst author = 'Admin';\nconst excerpt =\n  'Ullamcorper integer senectus netus dapibus consectetur orci imperdiet gravida volutpat nulla, aliquet penatibus elit sollicitudin turpis aenean suscipit vel a, at et congue nullam tincidunt semper eget auctor vehicula. Netus commodo mauris pharetra non diam fusce convallis nibh tempor nisi fringilla, lorem bibendum aenean nostra dis congue mus primis sapien vivamus tortor proin, metus leo quam arcu et augue lacinia integer suscipit ridiculus. Nulla diam viverra fringilla nostra, neque augue cubilia blandit felis, habitant leo aliquam. Fusce dictumst cursus nibh penatibus interdum duis natoque sed, lacinia ut convallis nam scelerisque lorem cubilia curabitur vel, mollis aliquam mattis commodo litora pretium suscipit.';\n\n/* eslint-disable testing-library/no-node-access */\n\ndescribe('StoryCard', () => {\n  it('should render only empty div elements when nothing is provided', () => {\n    const { container } = render(<StoryCard />);\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"web-stories-list__story\"\n      >\n        <div\n          class=\"web-stories-list__story-poster\"\n        >\n          <div\n            class=\"web-stories-list__story-poster-placeholder\"\n          >\n            <span />\n          </div>\n        </div>\n      </div>\n    `);\n  });\n\n  it('should set poster if only url and poster are provided', () => {\n    const { container } = render(<StoryCard poster={poster} />);\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"web-stories-list__story\"\n      >\n        <div\n          class=\"web-stories-list__story-poster\"\n        >\n          <img\n            src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n          />\n        </div>\n      </div>\n    `);\n  });\n\n  it('should show title, date and author if they are provided and enabled', () => {\n    const { container } = render(\n      <StoryCard\n        title={title}\n        isShowingTitle\n        date={date}\n        isShowingDate\n        author={author}\n        isShowingAuthor\n        poster={poster}\n        isShowingExcerpt\n        excerpt={excerpt}\n      />\n    );\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"web-stories-list__story\"\n      >\n        <div\n          class=\"web-stories-list__story-poster\"\n        >\n          <img\n            alt=\"Stories in AMP\"\n            src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n          />\n        </div>\n        <div\n          class=\"story-content-overlay web-stories-list__story-content-overlay\"\n        >\n          <div\n            class=\"story-content-overlay__title\"\n          >\n            Stories in AMP\n          </div>\n          <div\n            class=\"story-content-overlay__excerpt\"\n          >\n            Ullamcorper integer senectus netus dapibus consectetur orci imperdiet gravida volutpat nulla, aliquet penatibus elit sollicitudin turpis aenean suscipit vel a, at et congue nullam tincidunt semper eget auctor vehicula. Netus commodo mauris pharetra non diam fusce convallis nibh tempor nisi fringilla, lorem bibendum aenean nostra dis congue mus primis sapien vivamus tortor proin, metus leo quam arcu et augue lacinia integer suscipit ridiculus. Nulla diam viverra fringilla nostra, neque augue cubilia blandit felis, habitant leo aliquam. Fusce dictumst cursus nibh penatibus interdum duis natoque sed, lacinia ut convallis nam scelerisque lorem cubilia curabitur vel, mollis aliquam mattis commodo litora pretium suscipit.\n          </div>\n          <div\n            class=\"story-content-overlay__author\"\n          >\n            By Admin\n          </div>\n          <time\n            class=\"story-content-overlay__date\"\n            datetime=\"2020-11-18T13:36:35\"\n          >\n            On November 18, 2020\n          </time>\n        </div>\n      </div>\n    `);\n  });\n\n  it('should not show title, date and author if they are provided but disabled', () => {\n    const { container } = render(\n      <StoryCard\n        title={title}\n        isShowingTitle={false}\n        date={date}\n        isShowingDate={false}\n        author={author}\n        isShowingAuthor={false}\n        poster={poster}\n        isShowingExcerpt\n        excerpt={excerpt}\n      />\n    );\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"web-stories-list__story\"\n      >\n        <div\n          class=\"web-stories-list__story-poster\"\n        >\n          <img\n            alt=\"Stories in AMP\"\n            src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n          />\n        </div>\n      </div>\n    `);\n  });\n});\n\n/* eslint-enable testing-library/no-node-access */\n"
  },
  {
    "path": "packages/stories-block/src/block/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport {\n  EMBED_STORY_BLOCK_ICON,\n  LATEST_STORIES_BLOCK_ICON,\n  CAROUSEL_VIEW_TYPE_ICON,\n  SELECTED_STORIES_BLOCK_ICON,\n  CIRCLES_VIEW_TYPE_ICON,\n  LIST_VIEW_TYPE_ICON,\n  GRID_VIEW_TYPE_ICON,\n  BOX_CAROUSEL_CONFIG_ICON,\n  LIST_VIEW_CONFIG_ICON,\n  CIRCLE_CAROUSEL_CONFIG_ICON,\n  GRID_VIEW_CONFIG_ICON,\n} from './icons';\n\n/**\n * Block types\n */\nexport const BLOCK_TYPE_LATEST_STORIES = 'latest-stories';\nexport const BLOCK_TYPE_SELECTED_STORIES = 'selected-stories';\nexport const BLOCK_TYPE_URL = 'url';\nexport const BLOCK_TYPES = [\n  {\n    id: BLOCK_TYPE_LATEST_STORIES,\n    label: __('Latest Stories', 'web-stories'),\n    description: __('Embed latest web stories.', 'web-stories'),\n    icon: LATEST_STORIES_BLOCK_ICON,\n  },\n  {\n    id: BLOCK_TYPE_SELECTED_STORIES,\n    label: __('Selected Stories', 'web-stories'),\n    description: __('Manually select web stories.', 'web-stories'),\n    icon: SELECTED_STORIES_BLOCK_ICON,\n  },\n  {\n    id: BLOCK_TYPE_URL,\n    label: __('Single Story', 'web-stories'),\n    description: __('Embed a single story.', 'web-stories'),\n    icon: EMBED_STORY_BLOCK_ICON,\n  },\n];\n\n/**\n * Block controls icons.\n */\nexport const GRID_VIEW_TYPE = 'grid';\nexport const LIST_VIEW_TYPE = 'list';\nexport const CIRCLES_VIEW_TYPE = 'circles';\nexport const CAROUSEL_VIEW_TYPE = 'carousel';\n\nexport const VIEW_TYPES = [\n  {\n    id: CAROUSEL_VIEW_TYPE,\n    label: __('Box Carousel', 'web-stories'),\n    icon: CAROUSEL_VIEW_TYPE_ICON,\n    panelIcon: BOX_CAROUSEL_CONFIG_ICON,\n  },\n  {\n    id: CIRCLES_VIEW_TYPE,\n    label: __('Circle Carousel', 'web-stories'),\n    icon: CIRCLES_VIEW_TYPE_ICON,\n    panelIcon: CIRCLE_CAROUSEL_CONFIG_ICON,\n  },\n  {\n    id: GRID_VIEW_TYPE,\n    label: __('Grid', 'web-stories'),\n    icon: GRID_VIEW_TYPE_ICON,\n    panelIcon: GRID_VIEW_CONFIG_ICON,\n  },\n  {\n    id: LIST_VIEW_TYPE,\n    label: __('List', 'web-stories'),\n    icon: LIST_VIEW_TYPE_ICON,\n    panelIcon: LIST_VIEW_CONFIG_ICON,\n  },\n];\n"
  },
  {
    "path": "packages/stories-block/src/block/deprecated.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\nconst blockAttributes = {\n  url: {\n    type: 'string',\n  },\n  title: {\n    type: 'string',\n  },\n  poster: {\n    type: 'string',\n  },\n  width: {\n    type: 'number',\n    default: 360,\n  },\n  height: {\n    type: 'number',\n    default: 600,\n  },\n  align: {\n    type: 'string',\n    default: 'none',\n  },\n};\n\n/**\n * The block's save function (pure).\n *\n * Represents a cached copy of the block’s content to be shown in case\n * the plugin is disabled.\n *\n * The server-side 'render_callback' is used to override this on page load.\n *\n * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/\n * @param {Object} props Props.\n * @param {Object} props.attributes Block attributes.\n * @return {null|*} Rendered block.\n */\nfunction save({ attributes }) {\n  const { url, title, poster, width, height, align = 'none' } = attributes;\n\n  if (!url || !title) {\n    return null;\n  }\n\n  return (\n    <div className={`wp-block-web-stories-embed align${align}`}>\n      <amp-story-player\n        style={{\n          width: width ? `${width}px` : undefined,\n          height: height ? `${height}px` : undefined,\n        }}\n        data-testid=\"amp-story-player\"\n      >\n        <a\n          href={url}\n          style={{\n            ['--story-player-poster']: poster ? `url('${poster}')` : undefined,\n          }}\n        >\n          {title}\n        </a>\n      </amp-story-player>\n    </div>\n  );\n}\n\nsave.propTypes = {\n  attributes: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n  }).isRequired,\n};\n\n/**\n * The block's save function (pure).\n *\n * Represents a cached copy of the block’s content to be shown in case\n * the plugin is disabled.\n *\n * The server-side 'render_callback' is used to override this on page load.\n *\n * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/\n * @param {Object} props Props.\n * @param {Object} props.attributes Block attributes.\n * @return {null|*} Rendered block.\n */\nfunction saveV2({ attributes }) {\n  const { url, title, poster, width, height, align = 'none' } = attributes;\n\n  if (!url || !title) {\n    return null;\n  }\n\n  return (\n    <div className={`wp-block-web-stories-embed align${align}`}>\n      <a href={url}>\n        {poster ? (\n          <img alt={title} src={poster} width={width} height={height} />\n        ) : (\n          title\n        )}\n      </a>\n    </div>\n  );\n}\n\nsaveV2.propTypes = {\n  attributes: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n  }).isRequired,\n};\n\nconst v1 = {\n  attributes: blockAttributes,\n  save,\n};\n\nconst v2 = {\n  attributes: blockAttributes,\n  migrate(attrs) {\n    return {\n      ...attrs,\n      blockType: 'url',\n      stories: [],\n      viewType: '',\n      numOfStories: 5,\n      numOfColumns: 2,\n      circleSize: 96,\n      orderby: '',\n      order: '',\n      archiveLinkLabel: '',\n      authors: [],\n      fieldState: {},\n    };\n  },\n  save: saveV2,\n  isEligible({ url, blockType }) {\n    return Boolean(!blockType && url && url.trim().length);\n  },\n};\n\n// The deprecations in the array should be in reverse chronological order.\n// This allows the block editor to attempt to apply the most recent and likely deprecations first,\n// avoiding unnecessary and expensive processing.\nconst deprecated = [v2, v1];\n\nexport default deprecated;\n"
  },
  {
    "path": "packages/stories-block/src/block/edit.css",
    "content": "/* Load main styles on edit screen. */\n@import '../css/style.css';\n\n.web-stories-list__story {\n  cursor: default;\n}\n\n/* Carousel view styles */\n\n.web-stories-list.is-view-type-carousel .web-stories-list__story {\n  margin-right: 10px;\n  min-width: 235px;\n  flex-shrink: 0;\n}\n\n.web-stories-list .web-stories-list__story-poster img {\n  height: 100%;\n}\n\n.web-stories-list .story-content-overlay__excerpt p {\n  margin: 0;\n}\n\n.web-stories-list.is-carousel.has-archive-link {\n  margin-top: 0;\n  padding-top: calc(24px + 35px);\n}\n\n.web-stories-list.is-carousel.has-archive-link .web-stories-list__archive-link {\n  top: 0;\n}\n\n/* Block Icons */\n.is-pressed .web-stories-block__toolbar-icon.icon__circles-carousel circle {\n  stroke: black;\n}\n\n/* Block Placeholder (choose between latest / selected / single */\n\n.web-stories-block-configuration-panel .components-placeholder__instructions {\n  margin: 0;\n}\n\n.web-stories-block-configuration-panel\n  .web-stories-block-configuration-panel__options {\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-start;\n  flex-wrap: wrap;\n  align-items: center;\n  width: 100%;\n  margin: 16px 0 0;\n  padding: 0;\n  list-style: none;\n}\n\n.web-stories-block-configuration-panel\n  .web-stories-block-configuration-panel__options\n  > li {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  margin: 8px 20px 0 0;\n}\n\n.web-stories-block-configuration-panel\n  .web-stories-block-configuration-panel__options\n  .components-button {\n  height: 70px;\n  width: 70px;\n  justify-content: center;\n  margin: 0 0 12px;\n  padding: 0;\n}\n\n.web-stories-block-configuration-panel\n  .web-stories-block-configuration-panel__options\n  .components-button\n  svg {\n  fill: none;\n  /* todo: perhaps use @wordpress/postcss-themes for older WP versions */\n  color: var(--wp-admin-theme-color, #007cba);\n}\n\n/* Loading Spinners */\n\n.web-stories-block__loader-container {\n  display: flex;\n  height: 100%;\n  justify-content: center;\n  align-items: center;\n}\n\n.web-stories-block__loader-container .components-spinner {\n  margin-top: 0;\n}\n\n/* Story Picker */\n\n.web-stories-story-picker-modal {\n  width: 100%;\n  height: 100%;\n  max-height: 100%;\n  position: relative;\n  overflow: hidden;\n}\n\n@media screen and (min-width: 768px) {\n  .web-stories-story-picker-modal {\n    width: calc(100% - 16px - 16px);\n    height: calc(100% - 60px - 60px);\n  }\n}\n\n.web-stories-story-picker-modal .components-modal__header {\n  margin-bottom: 0;\n}\n\n.web-stories-story-picker-modal__content {\n  position: relative;\n  height: 100%;\n  margin: 0 0 20px 0;\n  padding: 20px 0;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n\n.web-stories-story-picker-modal__footer {\n  position: fixed;\n  bottom: 0;\n  z-index: 2;\n  width: calc(100% - 64px);\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin: 0;\n  padding: 10px 0;\n  background: #fff;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.web-stories-story-picker-modal__footer .components-button {\n  margin-left: 8px;\n}\n\n.web-stories-story-picker-modal__footer--left {\n  min-width: 1px;\n}\n\n.web-stories-story-picker-modal__footer--right {\n  display: flex;\n  flex-direction: row;\n}\n\n@media screen and (min-width: 768px) {\n  .web-stories-story-picker-modal__footer--right {\n    display: block;\n  }\n}\n\n.web-stories-story-picker-filter {\n  z-index: 2;\n  padding: 0;\n  margin-top: -12px;\n  display: flex;\n  justify-content: flex-end;\n}\n\n@media screen and (min-height: 768px) and (min-width: 768px) {\n  .web-stories-story-picker-filter {\n    position: sticky;\n    top: 0;\n    z-index: 3;\n  }\n}\n\n.web-stories-story-picker-filter__search-container {\n  display: block;\n  position: relative;\n  width: 100%;\n  background: #fff;\n}\n\n@media screen and (min-width: 768px) {\n  .web-stories-story-picker-filter__search-container {\n    display: grid;\n    grid-template-columns: 0 32% 32% 32%;\n    grid-column-gap: 1%;\n  }\n}\n\n@media screen and (min-width: 1200px) {\n  .web-stories-story-picker-filter__search-container {\n    grid-template-columns: 57% 15% 15% 10%;\n  }\n}\n\n/* SelectControl label needs some margin so all three inputs are nicely aligned. */\n.web-stories-story-picker-filter\n  .web-stories-story-picker-filter__search-container\n  .components-base-control\n  .components-input-control__label {\n  margin-bottom: 7px;\n}\n\n.web-stories-story-picker-filter\n  .web-stories-story-picker-filter__search-container\n  .components-base-control\n  .components-select-control__input {\n  height: 30px;\n}\n\n.web-stories-story-picker-filter .components-select-control {\n  gap: 0;\n  margin-top: 1px;\n}\n\n.web-stories-story-picker-filter__search-inner {\n  grid-column: 2;\n}\n\n/* Combobox popup should not push down other content */\n\n.web-stories-story-picker-filter__combobox\n  .components-combobox-control__suggestions-container {\n  position: relative;\n}\n\n.web-stories-story-picker-filter__combobox\n  .components-form-token-field__suggestions-list {\n  position: absolute;\n  top: 28px;\n  border: 1px solid #757575;\n  background: #fff;\n  z-index: 3;\n}\n\n.web-stories-story-picker-filter__combobox\n  .components-combobox-control__suggestions-container:focus-within\n  .components-form-token-field__suggestions-list {\n  border-color: var(--wp-admin-theme-color);\n  box-shadow: 0 0 0 1px var(--wp-admin-theme-color);\n}\n\n.web-stories-story-picker-filter__grid {\n  display: grid;\n  overflow: auto;\n  width: 100%;\n  padding: 30px 20px 0;\n  grid-column-gap: 24px;\n  grid-row-gap: 80px;\n  grid-auto-rows: minmax(min-content, max-content);\n  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n  scroll-margin-top: 30vh;\n}\n\n@media screen and (min-height: 768px) and (min-width: 768px) {\n  .web-stories-story-picker-filter__grid {\n    height: calc(100% - 125px);\n  }\n}\n\n@media screen and (min-width: 768px) {\n  .web-stories-story-picker-filter__grid {\n    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n  }\n}\n\n.web-stories-story-picker-filter__grid .droppable {\n  position: relative;\n}\n\n.web-stories-story-picker-filter__grid\n  .droppable.web-stories-story-picker-show-drag-inserter::before {\n  content: '';\n  position: absolute;\n  top: 0;\n  left: -14px;\n  bottom: 0;\n  width: 4px;\n  background: var(--wp-admin-theme-color, #007cba);\n}\n\n.web-stories-story-picker-filter__grid\n  .droppable.web-stories-story-picker-show-drag-inserter.web-stories-story-picker-show-drag-inserter-right::before {\n  left: auto;\n  right: -14px;\n}\n\n.web-stories-story-picker-filter__grid_item {\n  margin: 0;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n}\n\n.web-stories-story-picker-filter__load_more {\n  display: flex;\n  flex-direction: row;\n  justify-content: center;\n}\n\n/* Story Preview Cards */\n\n.web-stories-story-preview-card__poster {\n  position: relative;\n  border: 1px solid #adb1b3;\n  border-radius: 4px;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.web-stories-story-preview-card__poster img {\n  position: absolute;\n  border-radius: 4px;\n  width: 100%;\n  height: auto;\n}\n\n.web-stories-story-preview-card__poster::before {\n  content: '';\n  display: block;\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  background: linear-gradient(\n    180deg,\n    rgba(255, 255, 255, 0) 0%,\n    rgba(0, 0, 0, 0.8) 100%\n  );\n  top: 0;\n  left: 0;\n  z-index: 1;\n}\n\n.web-stories-story-preview-card__poster::after {\n  content: '';\n  display: block;\n  padding-bottom: 133.28125%;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay {\n  display: block;\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: none;\n  background: transparent;\n  box-shadow: none;\n  padding: 0;\n  margin: 0;\n  z-index: 2;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay:focus {\n  box-shadow:\n    0 0 3px 3px #5b9dd9,\n    0 0 2px 1px rgba(30, 140, 190, 0.8);\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon {\n  position: absolute;\n  top: -7px;\n  right: -7px;\n  z-index: 1;\n}\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon\n  span,\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon\n  svg {\n  background-color: #ccc;\n  box-shadow:\n    0 0 0 1px #fff,\n    0 0 0 2px rgba(0, 0, 0, 0.15);\n  cursor: pointer;\n  color: #000;\n  padding: 3px;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected:focus\n  .item-selected-icon\n  span {\n  color: #fff;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon\n  svg {\n  stroke: #000;\n  stroke-width: 2px;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected:focus\n  .item-selected-icon\n  svg {\n  background-color: #0073aa;\n  stroke: #fff;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon\n  span::before {\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon\n  .item-selected-icon-minus {\n  display: none;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon:hover\n  .item-selected-icon-minus {\n  display: block;\n}\n\n.web-stories-story-preview-card__poster\n  .web-stories-story-preview-card__overlay.item-selected\n  .item-selected-icon:hover\n  .item-selected-icon-check {\n  display: none;\n}\n\n.web-stories-story-preview-card__label > div {\n  margin-bottom: 8px;\n}\n\n.web-stories-story-preview-card__title {\n  margin-top: 8px;\n  font-weight: 700;\n  font-size: 16px;\n}\n\n/* Inspector Controls */\n\n.web-stories-settings .components-toggle-control .components-base-control__help,\n.web-stories-settings .web-stories-settings-archive-link {\n  width: 80%;\n  margin-left: auto;\n}\n"
  },
  {
    "path": "packages/stories-block/src/block/edit.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { BlockIcon } from './icons';\nimport SingleStoryEmbed from './block-types/single-story/edit';\nimport SingleStoryEmbedInLoop from './block-types/single-story/editInLoop';\nimport StoriesBlockControls from './components/storiesBlockControls';\nimport BlockConfigurationPanel from './components/storiesBlockConfigurationPanel';\nimport LatestStoriesEdit from './block-types/latest-stories/edit';\nimport SelectedStoriesEdit from './block-types/selected-stories/edit';\nimport {\n  BLOCK_TYPE_LATEST_STORIES,\n  BLOCK_TYPE_SELECTED_STORIES,\n  BLOCK_TYPE_URL,\n  BLOCK_TYPES,\n  VIEW_TYPES,\n} from './constants';\n\nfunction WebStoriesEdit({\n  attributes,\n  setAttributes,\n  className,\n  isSelected,\n  context,\n}) {\n  const { blockType, viewType } = attributes;\n  const { postType, postId, queryId } = context;\n\n  const isDescendentOfQueryLoop = Number.isFinite(queryId);\n\n  if (\n    isDescendentOfQueryLoop &&\n    postType &&\n    postId &&\n    'web-story' === postType\n  ) {\n    return (\n      <SingleStoryEmbedInLoop\n        icon={<BlockIcon />}\n        attributes={attributes}\n        setAttributes={setAttributes}\n        context={context}\n        className={className}\n        isSelected={isSelected}\n      />\n    );\n  }\n\n  if (!blockType) {\n    return (\n      <BlockConfigurationPanel\n        icon={<BlockIcon />}\n        setAttributes={setAttributes}\n        instructions={__(\n          'Embed a collection of your latest stories, select your own or enter an URL.',\n          'web-stories'\n        )}\n        selectionOptions={BLOCK_TYPES}\n        selectionType={'blockType'}\n      />\n    );\n  }\n\n  if (blockType !== BLOCK_TYPE_URL && !viewType) {\n    return (\n      <BlockConfigurationPanel\n        icon={<BlockIcon />}\n        setAttributes={setAttributes}\n        instructions={__('Select a layout style', 'web-stories')}\n        selectionOptions={VIEW_TYPES}\n        selectionType={'viewType'}\n      />\n    );\n  }\n\n  return (\n    <>\n      <StoriesBlockControls\n        blockType={blockType}\n        viewType={viewType}\n        setAttributes={setAttributes}\n      />\n\n      {blockType === BLOCK_TYPE_LATEST_STORIES && (\n        <LatestStoriesEdit\n          attributes={attributes}\n          setAttributes={setAttributes}\n        />\n      )}\n\n      {blockType === BLOCK_TYPE_SELECTED_STORIES && (\n        <SelectedStoriesEdit\n          icon={<BlockIcon />}\n          attributes={attributes}\n          setAttributes={setAttributes}\n          isSelected={isSelected}\n        />\n      )}\n\n      {blockType === BLOCK_TYPE_URL && (\n        <SingleStoryEmbed\n          icon={<BlockIcon />}\n          attributes={attributes}\n          setAttributes={setAttributes}\n          className={className}\n          isSelected={isSelected}\n        />\n      )}\n    </>\n  );\n}\n\nWebStoriesEdit.propTypes = {\n  attributes: PropTypes.shape({\n    blockType: PropTypes.string,\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n    stories: PropTypes.array,\n    viewType: PropTypes.string,\n    numOfStories: PropTypes.number,\n    numOfColumns: PropTypes.number,\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n    archiveLinkLabel: PropTypes.string,\n    authors: PropTypes.array,\n  }),\n  setAttributes: PropTypes.func.isRequired,\n  className: PropTypes.string.isRequired,\n  isSelected: PropTypes.bool,\n  context: PropTypes.shape({\n    postType: PropTypes.string,\n    postId: PropTypes.number,\n    queryId: PropTypes.number,\n  }),\n};\n\nexport default WebStoriesEdit;\n"
  },
  {
    "path": "packages/stories-block/src/block/icons.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { useInstanceId } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport CirclesCarouselViewIcon from './images/view-type/circles-carousel-view.svg';\nimport CirclesCarouselConfigIcon from './images/config-panel/circles-carousel-view-panel-icon.svg';\nimport LatestStoriesBlockIcon from './icons/block-type/latest-stories-block.svg';\nimport SelectedStoriesBlockIcon from './icons/block-type/selected-stories-block.svg';\nimport EmbedStoriesBlockIcon from './icons/block-type/embed-story-block.svg';\n\nimport GridViewIcon from './icons/view-type/grid-view.svg';\nimport ListViewIcon from './icons/view-type/list-view.svg';\nimport BoxCarouselViewIcon from './icons/view-type/box-carousel-view.svg';\n\nimport GridViewConfigIcon from './icons/config-panel/grid-view-panel-icon.svg';\nimport ListViewConfigIcon from './icons/config-panel/list-view-panel-icon.svg';\nimport BoxCarouselConfigIcon from './icons/config-panel/box-carousel-view-panel-icon.svg';\n\n// Icons for block types.\nexport const LATEST_STORIES_BLOCK_ICON = (\n  <LatestStoriesBlockIcon width={31} height={42} />\n);\n\nexport const SELECTED_STORIES_BLOCK_ICON = (\n  <SelectedStoriesBlockIcon width={32} height={32} />\n);\n\nexport const EMBED_STORY_BLOCK_ICON = (\n  <EmbedStoriesBlockIcon width={32} height={16} />\n);\n\n// Icons for view types.\nexport const CAROUSEL_VIEW_TYPE_ICON = (\n  <BoxCarouselViewIcon width={18} height={14} />\n);\n\nexport const CIRCLES_VIEW_TYPE_ICON = (\n  <CirclesCarouselViewIcon\n    className=\"web-stories-block__toolbar-icon icon__circles-carousel\"\n    width={23}\n    height={18}\n  />\n);\n\nexport const GRID_VIEW_TYPE_ICON = <GridViewIcon width={12} height={14} />;\nexport const LIST_VIEW_TYPE_ICON = <ListViewIcon width={12} height={13} />;\n\n// Configuration panel view type icons.\nexport const BOX_CAROUSEL_CONFIG_ICON = (\n  <BoxCarouselConfigIcon width={26} height={20} />\n);\n\nexport const LIST_VIEW_CONFIG_ICON = (\n  <ListViewConfigIcon width={22} height={26} />\n);\n\nexport const CIRCLE_CAROUSEL_CONFIG_ICON = (\n  <CirclesCarouselConfigIcon width={42} height={24} />\n);\n\nexport const GRID_VIEW_CONFIG_ICON = (\n  <GridViewConfigIcon width={20} height={27} />\n);\n\n// Defining the SVG like this ensures that IDs are unique\n// even if there are multiple instances of the component.\n// See https://github.com/googleforcreators/web-stories-wp/issues/8401\nexport const BlockIcon = () => {\n  const id = useInstanceId(BlockIcon);\n\n  return (\n    <svg fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\">\n      <circle\n        cx=\"32\"\n        cy=\"32\"\n        r=\"32\"\n        transform=\"rotate(-180 32 32)\"\n        fill={`url(#gradient-${id})`}\n      />\n      <g filter={`url(#filter-${id})`} fill=\"#fff\">\n        <path d=\"M41.6 19.2a3.2 3.2 0 013.2 3.2v19.2a3.2 3.2 0 01-3.2 3.2V19.2zm-24 0a3.2 3.2 0 013.2-3.2h14.4a3.2 3.2 0 013.2 3.2v25.6a3.2 3.2 0 01-3.2 3.2H20.8a3.2 3.2 0 01-3.2-3.2V19.2zM48 22.4a2.4 2.4 0 012.4 2.4v14.4a2.4 2.4 0 01-2.4 2.4V22.4z\" />\n      </g>\n      <defs>\n        <linearGradient\n          id={`gradient-${id}`}\n          x1=\"13.255\"\n          y1=\"6.599\"\n          x2=\"35.289\"\n          y2=\"62.791\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"#79B3FF\" />\n          <stop offset=\"1\" stopColor=\"#CBACFF\" />\n        </linearGradient>\n        <filter\n          id={`filter-${id}`}\n          x=\"8.96\"\n          y=\"10.24\"\n          width=\"46.08\"\n          height=\"46.08\"\n          filterUnits=\"userSpaceOnUse\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n          <feColorMatrix\n            in=\"SourceAlpha\"\n            values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n          />\n          <feOffset dy=\"1.28\" />\n          <feGaussianBlur stdDeviation=\"1.92\" />\n          <feColorMatrix values=\"0 0 0 0 0.423529 0 0 0 0 0.490196 0 0 0 0 0.733333 0 0 0 0.3 0\" />\n          <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n          <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\" />\n        </filter>\n      </defs>\n    </svg>\n  );\n};\n"
  },
  {
    "path": "packages/stories-block/src/block/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { BlockIcon } from './icons';\nimport deprecated from './deprecated';\nimport save from './save';\nimport edit from './edit';\nimport metadata from './block';\nimport { BLOCK_TYPE_LATEST_STORIES, GRID_VIEW_TYPE } from './constants';\nimport transforms from './transforms';\n\nconst { name, category, keywords, attributes, supports } = metadata;\n\nconst settings = {\n  title: __('Web Stories', 'web-stories'),\n  description: __('Embed stories using various layout options.', 'web-stories'),\n  category,\n  icon: <BlockIcon />,\n  keywords,\n  attributes,\n  example: {\n    attributes: {\n      blockType: BLOCK_TYPE_LATEST_STORIES,\n      viewType: GRID_VIEW_TYPE,\n      numberOfColumns: 2,\n    },\n  },\n  supports,\n  deprecated,\n  edit,\n  save,\n  transforms,\n};\n\nexport { metadata, name, settings };\n"
  },
  {
    "path": "packages/stories-block/src/block/save.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * The block's save function (pure).\n *\n * Represents a cached copy of the block’s content to be shown in case\n * the plugin is disabled.\n *\n * The server-side 'render_callback' is used to override this on page load.\n *\n * @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/\n * @param {Object} props Props.\n * @param {Object} props.attributes Block attributes.\n * @return {null|*} Rendered block.\n */\nfunction save({ attributes }) {\n  const { url, title, poster, width, height, align = 'none' } = attributes;\n\n  if (!url || !title) {\n    return null;\n  }\n\n  return (\n    <div className={`wp-block-web-stories-embed align${align}`}>\n      <a href={url}>\n        {poster ? (\n          <img\n            alt={title}\n            src={poster}\n            width={width}\n            height={height}\n            loading=\"lazy\"\n            decoding=\"async\"\n          />\n        ) : (\n          title\n        )}\n      </a>\n    </div>\n  );\n}\n\nsave.propTypes = {\n  attributes: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    poster: PropTypes.string,\n    width: PropTypes.number,\n    height: PropTypes.number,\n    align: PropTypes.string,\n  }).isRequired,\n};\n\nexport default save;\n"
  },
  {
    "path": "packages/stories-block/src/block/test/autocomplete.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, screen, fireEvent } from '@testing-library/react';\n\n/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport Autocomplete from '../components/autocomplete';\n\ndescribe('autocomplete', () => {\n  it('should trigger onChange callback when typing', () => {\n    const label = __('Web Stories Autocomplete', 'web-stories');\n    const value = ['admin'];\n    const options = ['admin', 'author', 'contributor'];\n    const onChangeHandler = jest.fn();\n    const onInputChangeHandler = jest.fn();\n\n    render(\n      <Autocomplete\n        label={label}\n        value={value}\n        onChange={onChangeHandler}\n        onInputChange={onInputChangeHandler}\n        options={options}\n      />\n    );\n\n    fireEvent.change(screen.getByRole('combobox'), {\n      target: { value: 'author' },\n    });\n    expect(onInputChangeHandler).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/test/block.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { registerBlockType } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { name, settings } from '..';\n\ndescribe('Block Registration', () => {\n  it('should register Web Stories block without errors', () => {\n    const block = registerBlockType(name, settings);\n    expect(block).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/test/save.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Save from '../save';\n\nconst url = 'https://wp.stories.google/stories/intro-to-web-stories-storytime';\nconst title = 'Stories in AMP';\nconst poster = 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg';\n\n/* eslint-disable testing-library/no-node-access */\n\ndescribe('save', () => {\n  it('should add alignnone class by default', () => {\n    const { container } = render(<Save attributes={{ url, title, poster }} />);\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"wp-block-web-stories-embed alignnone\"\n      >\n        <a\n          href=\"https://wp.stories.google/stories/intro-to-web-stories-storytime\"\n        >\n          <img\n            alt=\"Stories in AMP\"\n            decoding=\"async\"\n            loading=\"lazy\"\n            src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n          />\n        </a>\n      </div>\n    `);\n  });\n\n  it('should render nothing if poster is missing', () => {\n    const { container } = render(<Save attributes={{ url, title }} />);\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"wp-block-web-stories-embed alignnone\"\n      >\n        <a\n          href=\"https://wp.stories.google/stories/intro-to-web-stories-storytime\"\n        >\n          Stories in AMP\n        </a>\n      </div>\n    `);\n  });\n\n  it('should render nothing if url is missing', () => {\n    const { container } = render(<Save attributes={{ title, poster }} />);\n    expect(container.firstChild).toMatchInlineSnapshot(`null`);\n  });\n\n  it('should render nothing if title is missing', () => {\n    const { container } = render(<Save attributes={{ url, poster }} />);\n    expect(container.firstChild).toMatchInlineSnapshot(`null`);\n  });\n});\n\n/* eslint-enable testing-library/no-node-access */\n"
  },
  {
    "path": "packages/stories-block/src/block/test/storiesPlaceholder.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport StoriesLoading from '../components/storiesLoading';\n\ndescribe('StoriesLoading', () => {\n  it('should display spinner', () => {\n    render(<StoriesLoading />);\n    // Text occurs twice, once within the placeholder and once in the a11y-speak-region.\n    expect(screen.getAllByText('Loading Stories…')[0]).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/stories-block/src/block/transforms.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { createBlock } from '@wordpress/blocks';\n/**\n * Internal dependencies\n */\nimport { BLOCK_TYPE_LATEST_STORIES, BLOCK_TYPE_URL } from './constants';\nimport metadata from './block';\n\nconst { attributes } = metadata;\n\nconst transforms = {\n  from: [\n    {\n      type: 'shortcode',\n      tag: 'web_stories_embed',\n      attributes: {\n        ...attributes,\n        align: {\n          type: 'string',\n          shortcode: ({ named: { align } }) => {\n            return align;\n          },\n        },\n        height: {\n          type: 'number',\n          shortcode: ({ named: { height } }) => {\n            return height;\n          },\n        },\n        poster: {\n          type: 'string',\n          shortcode: ({ named: { poster } }) => {\n            return poster;\n          },\n        },\n        title: {\n          type: 'string',\n          shortcode: ({ named: { title } }) => {\n            return title;\n          },\n        },\n        url: {\n          type: 'string',\n          shortcode: ({ named: { url } }) => {\n            return url;\n          },\n        },\n        width: {\n          type: 'number',\n          shortcode: ({ named: { width } }) => {\n            return width;\n          },\n        },\n        blockType: {\n          type: 'string',\n          default: BLOCK_TYPE_URL,\n        },\n      },\n      priority: 9,\n    },\n    {\n      type: 'shortcode',\n      tag: 'web_stories',\n      attributes: {\n        ...attributes,\n        blockType: {\n          type: 'string',\n          default: BLOCK_TYPE_LATEST_STORIES,\n        },\n        align: {\n          type: 'string',\n          shortcode: ({ named: { align } }) => {\n            return align;\n          },\n        },\n        archiveLinkLabel: {\n          type: 'string',\n          shortcode: ({ named: { archive_link_label } }) => {\n            return archive_link_label;\n          },\n        },\n        viewType: {\n          type: 'string',\n          shortcode: ({ named: { view } }) => {\n            return view;\n          },\n        },\n        numOfStories: {\n          type: 'number',\n          shortcode: ({ named: { number } }) => {\n            return number;\n          },\n        },\n        numOfColumns: {\n          type: 'number',\n          shortcode: ({ named: { columns } }) => {\n            return columns;\n          },\n        },\n        circleSize: {\n          type: 'number',\n          shortcode: ({ named: { circle_size } }) => {\n            return circle_size;\n          },\n        },\n        fieldState: {\n          type: 'object',\n          shortcode: ({\n            named: { title, excerpt, author, date, archive_link, image_align },\n          }) => {\n            // Need this type conversion as the block is expecting following to be boolean.\n            return {\n              show_archive_link: 'true' === archive_link,\n              show_author: 'true' === author,\n              show_date: 'true' === date,\n              show_excerpt: 'true' === excerpt,\n              show_image_align: 'true' === image_align,\n              show_title: 'true' === title,\n            };\n          },\n        },\n      },\n    },\n    {\n      type: 'block',\n      blocks: ['core/legacy-widget'],\n      isMatch: ({ idBase, instance }) => {\n        if (!instance?.raw) {\n          // Can't transform if raw instance is not shown in REST API.\n          return false;\n        }\n        return idBase === 'web_stories_widget';\n      },\n      transform: ({ instance }) => {\n        const {\n          raw: {\n            archive_link_label: archiveLinkLabel,\n            circle_size: circleSize,\n            image_alignment: imageAlignment,\n            number_of_columns: numOfColumns,\n            number_of_stories: numOfStories,\n            view_type: viewType,\n            show_title,\n            show_author,\n            show_date,\n            show_excerpt,\n            show_archive_link,\n            sharp_corners: show_sharp_corners,\n            show_image_alignment,\n            title,\n            orderby = '',\n            order = '',\n          },\n        } = instance;\n\n        const transformedBlock = createBlock('web-stories/embed', {\n          blockType: 'latest-stories',\n          viewType,\n          fieldState: {\n            show_title,\n            show_author,\n            show_date,\n            show_excerpt,\n            show_archive_link,\n            show_sharp_corners,\n            show_image_alignment,\n          },\n          archiveLinkLabel,\n          circleSize,\n          numOfColumns,\n          imageAlignment,\n          numOfStories,\n          orderby: orderby.replace('post_', ''),\n          order: order.toLowerCase(),\n        });\n        if (!title) {\n          return transformedBlock;\n        }\n        return [\n          createBlock('core/heading', {\n            content: title,\n          }),\n          transformedBlock,\n        ];\n      },\n    },\n  ],\n};\n\nexport default transforms;\n"
  },
  {
    "path": "packages/stories-block/src/css/common.css",
    "content": "/* Web Stories: Common block styles */\n.web-stories-list {\n  margin-top: 24px;\n  margin-bottom: 24px;\n}\n\n.web-stories-theme-header-section .web-stories-list {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.web-stories-list.is-carousel .web-stories-list__inner-wrapper {\n  max-width: max-content;\n  margin: 0 auto;\n  position: relative;\n}\n\n.web-stories-list__story {\n  position: relative;\n  cursor: pointer;\n}\n\n.web-stories-list.is-view-type-carousel .web-stories-list__story {\n  min-width: var(--ws-story-min-width);\n}\n\n/* Curved corners by default.*/\n.web-stories-list.is-style-default.is-view-type-grid .web-stories-list__story,\n.web-stories-list.is-style-default.is-view-type-carousel\n  .web-stories-list__story {\n  border-radius: 8px;\n  overflow: hidden;\n}\n\n.web-stories-list__story-poster {\n  position: relative;\n  aspect-ratio: var(--ws-aspect-ratio);\n}\n\n.web-stories-list__story-poster a {\n  display: block;\n  margin: 0;\n  aspect-ratio: var(--ws-aspect-ratio);\n}\n\n.web-stories-list__story-poster .web-stories-list__story-poster-placeholder {\n  box-sizing: border-box;\n}\n\n/*\n  We want the placeholder to be clickable but hidden from screen readers.\n  This improves the no-js experience.\n  In the block edit component, placeholders are not links.\n*/\n.web-stories-list__story-poster .web-stories-list__story-poster-placeholder a,\n.web-stories-list__story-poster\n  .web-stories-list__story-poster-placeholder\n  span {\n  border: 0;\n  clip: rect(1px, 1px, 1px, 1px);\n  -webkit-clip-path: inset(50%);\n  clip-path: inset(50%);\n  height: 1px;\n  margin: -1px;\n  overflow: hidden;\n  padding: 0;\n  position: absolute !important;\n  width: 1px;\n  word-wrap: normal !important;\n  word-break: normal;\n}\n\n.web-stories-list__story.web-stories-list__story--amp\n  .web-stories-list__story-poster\n  a {\n  pointer-events: none;\n}\n\n.web-stories-list__story-poster img {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  box-sizing: border-box;\n}\n\n.web-stories-list__story-poster::after {\n  content: '';\n  display: block;\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  background: linear-gradient(\n    180deg,\n    rgba(255, 255, 255, 0) 0%,\n    rgba(0, 0, 0, 0.8) 100%\n  );\n  top: 0;\n  left: 0;\n  pointer-events: none;\n}\n\n.web-stories-list__story-content-overlay {\n  padding: 10px;\n  line-height: var(--ws-overlay-text-lh);\n}\n\nhtml[amp] .web-stories-list__story-content-overlay {\n  white-space: normal;\n}\n\n.web-stories-list.is-view-type-carousel\n  .web-stories-list__story-content-overlay,\n.web-stories-list.is-view-type-grid .web-stories-list__story-content-overlay {\n  position: absolute;\n  bottom: 0;\n  color: var(--ws-overlay-text-color);\n  z-index: 1;\n}\n\n.web-stories-list .story-content-overlay__title {\n  font-size: var(--ws-font-size-title);\n  font-weight: 700;\n}\n\n.web-stories-list .story-content-overlay__author,\n.web-stories-list .story-content-overlay__date {\n  font-size: var(--ws-font-size-author-date);\n}\n\n.web-stories-list .story-content-overlay__title,\n.web-stories-list .story-content-overlay__excerpt {\n  display: -webkit-box; /* stylelint-disable-line value-no-vendor-prefix */\n  -webkit-line-clamp: 2; /* Browser support: https://caniuse.com/?search=line-clamp */\n  -webkit-box-orient: vertical; /* stylelint-disable-line property-no-vendor-prefix */\n  overflow: hidden;\n}\n\n.web-stories-list .story-content-overlay__title:not(:last-child) {\n  margin-bottom: 15px;\n}\n\n.web-stories-list .story-content-overlay__excerpt {\n  -webkit-line-clamp: 3;\n  font-size: var(--ws-font-size-excerpt);\n  margin-bottom: 8px;\n}\n\n.web-stories-list.alignfull .web-stories-list__archive-link {\n  right: 10px;\n}\n\n.web-stories-list.is-view-type-grid .web-stories-list__archive-link,\n.web-stories-list.is-view-type-list .web-stories-list__archive-link {\n  display: block;\n  text-align: center;\n  margin: 32px auto 0 auto;\n  flex-basis: 100%;\n}\n\n.web-stories-list.is-view-type-grid .web-stories-list__archive-link a,\n.web-stories-list.is-view-type-list .web-stories-list__archive-link a {\n  padding: 7px 53px;\n  border: 1px solid;\n  border-radius: 100px;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentyeleven.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  max-width: 1000px;\n  margin: 0 auto;\n  border-bottom: none;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentyfifteen.css",
    "content": ".web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link\n  a {\n  text-decoration: underline;\n}\n\n@media screen and (min-width: 59.6875em) {\n  .web-stories-theme-header-section {\n    max-width: 1440px;\n    margin: 0 auto;\n  }\n\n  .web-stories-theme-header-section\n    .web-stories-list\n    .web-stories-list__inner-wrapper {\n    margin: 0 8.3333%;\n  }\n\n  .has-web-stories .site-main {\n    padding-top: 0;\n  }\n\n  .web-stories-theme-header-section .web-stories-list {\n    display: block;\n    margin-left: 29.9118%;\n    width: 68.5882%;\n    border-bottom: none;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentyfourteen.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  background: #000;\n  border-bottom: none;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__story-content-overlay {\n  color: #fff;\n}\n\n@media screen and (min-width: 783px) {\n  .has-web-stories .site-main {\n    margin-top: 0;\n  }\n}\n\n@media screen and (min-width: 1008px) {\n  .web-stories-theme-header-section .web-stories-list {\n    z-index: 1;\n    width: 100%;\n    max-width: 1260px;\n    padding-bottom: 22px;\n    padding-top: 64px;\n  }\n\n  .web-stories-theme-header-section\n    .web-stories-list.is-carousel.has-archive-link {\n    padding-top: 92px;\n  }\n}\n\n.web-stories-list.is-carousel .amp-carousel-button,\n.web-stories-list.is-carousel .glider-next,\n.web-stories-list.is-carousel .glider-prev {\n  z-index: 3; /* .site-header has 4 */\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentyseventeen.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  z-index: 1;\n  background: rgba(0, 0, 0, 0.3);\n  border-bottom: none;\n  margin-top: 0;\n  position: relative;\n}\n\n.web-stories-theme-header-section .web-stories-list.has-archive-link {\n  padding-top: 42px;\n  padding-bottom: 16px;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__story-content-overlay {\n  color: #fff;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link\n  a {\n  color: currentColor;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link {\n  color: rgba(255, 255, 255, 0.8);\n  box-shadow: inset 0 -1px 0 #fff;\n  transition:\n    color 80ms ease-in,\n    box-shadow 130ms ease-in-out;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link:hover,\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link:focus {\n  color: #fff;\n  box-shadow:\n    inset 0 0 0 rgb(0 0 0 / 0%),\n    0 3px 0 #fff;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentysixteen.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  border-bottom: none;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link,\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__story-content-overlay,\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link\n  a {\n  color: #fff;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link\n  a:hover,\n.web-stories-theme-header-section\n  .web-stories-list\n  .web-stories-list__archive-link\n  a:focus {\n  color: rgba(255, 255, 255, 0.8);\n}\n\n@media screen and (min-width: 44.375em) {\n  .web-stories-theme-header-section .web-stories-list {\n    padding-top: 33px;\n  }\n\n  .web-stories-theme-header-section\n    .web-stories-list.is-carousel.has-archive-link {\n    padding-top: 52px;\n    margin-top: 0;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentyten.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  max-width: 940px;\n  margin: 0 auto;\n  padding-right: 20px;\n  padding-left: 20px;\n  background-color: white;\n}\n\n.has-web-stories #wrapper {\n  margin-top: 0;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentytwelve.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  max-width: 68.571428571rem;\n  margin: 0 auto;\n  padding-right: 1.714285714rem;\n  padding-left: 1.714285714rem;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list.is-carousel.has-archive-link {\n  padding-top: 52px;\n  background: white;\n}\n\n@media screen and (min-width: 600px) {\n  .web-stories-theme-header-section .web-stories-list {\n    max-width: 68.571428571rem;\n    box-shadow: 0 -10px 6px rgb(100 100 100 / 30%);\n  }\n}\n\n@media screen and (min-width: 960px) {\n  .web-stories-theme-header-section .web-stories-list {\n    padding-right: 2.857142857rem;\n    padding-left: 2.857142857rem;\n  }\n\n  .has-web-stories .site {\n    margin-top: 0;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentytwenty.css",
    "content": ".web-stories-theme-header-section .web-stories-list {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/core-themes/twentytwentyone.css",
    "content": ".web-stories-theme-header-section\n  .web-stories-list.is-carousel\n  .web-stories-list__archive-link {\n  font-size: var(--primary-nav--font-size-button);\n  font-weight: var(--primary-nav--font-weight-button);\n}\n\n@media only screen and (max-width: 481px) {\n  /* To ensure that the 'view-all' link has some space from the frame. */\n  .web-stories-theme-header-section .web-stories-list__inner-wrapper {\n    max-width: var(--responsive--aligndefault-width);\n    margin-left: auto;\n    margin-right: auto;\n  }\n\n  /* Fix for menu toggle overlap. */\n  .web-stories-theme-header-section .web-stories-list {\n    margin-top: 72px;\n  }\n\n  .web-stories-theme-header-section .web-stories-list.is-view-type-circles {\n    margin-top: 72px;\n    padding-top: 0;\n  }\n\n  .web-stories-theme-header-section\n    .web-stories-list.is-carousel.has-archive-link {\n    margin-top: 24px;\n    padding-top: 72px;\n  }\n\n  /* Fix for menu toggle overlap on AMP. */\n  html[amp] .web-stories-theme-header-section .web-stories-list.is-carousel {\n    margin-top: 0;\n    padding-top: 72px; /* same as above */\n  }\n\n  html[amp]\n    .web-stories-theme-header-section\n    .web-stories-list.is-carousel.has-archive-link {\n    padding-top: calc(\n      72px + 24px\n    ); /* default margin from common.css plus above offset */\n  }\n\n  /* Carousel arrows were visible over primary navigation menu on mobile. */\n  .lock-scrolling .site {\n    z-index: 10;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/embed.css",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@import 'singleton.css';\n\n.web-stories-embed.alignnone,\n.web-stories-embed.alignleft,\n.web-stories-embed.alignright {\n  display: block;\n  width: 100%;\n}\n\n.web-stories-embed.aligncenter {\n  text-align: initial;\n}\n\n.web-stories-embed .wp-block-embed__wrapper {\n  position: relative;\n}\n\n.web-stories-embed.alignleft .wp-block-embed__wrapper {\n  margin-right: auto;\n}\n\n.web-stories-embed.alignright .wp-block-embed__wrapper {\n  margin-left: auto;\n}\n\n.web-stories-embed.alignnone .wp-block-embed__wrapper {\n  max-width: var(--width);\n}\n\n.web-stories-embed.aligncenter .wp-block-embed__wrapper {\n  margin-left: auto;\n  margin-right: auto;\n  max-width: var(--width);\n}\n\n.web-stories-embed:not(.web-stories-embed-amp) .wp-block-embed__wrapper {\n  aspect-ratio: var(--aspect-ratio);\n}\n\n.web-stories-embed:not(.web-stories-embed-amp)\n  .wp-block-embed__wrapper\n  amp-story-player {\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n\n.block-editor-block-inspector .web-stories-embed-poster-remove {\n  margin-left: 12px;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/lightbox.css",
    "content": "/* Lightbox styles */\n.web-stories-lightbox-open {\n  /* Stop page scroll when lightbox is visible. */\n  overflow-y: hidden;\n}\n\n.web-stories-list__lightbox,\n.web-stories-singleton__lightbox {\n  justify-content: center;\n  align-items: center;\n  position: fixed;\n  background: black;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  opacity: 0;\n  transform: translate(0, -100vh);\n  z-index: -999999999;\n}\n\n/* amp-lightbox needs to have z-index to render on top of other elements in the page. */\n.web-stories-list__lightbox-wrapper amp-lightbox,\n.web-stories-list__lightbox.show,\n.web-stories-singleton__lightbox.show {\n  z-index: 999999999;\n}\n\n.web-stories-list__lightbox.show,\n.web-stories-singleton__lightbox.show {\n  transform: translate(0, 0);\n  opacity: 1;\n}\n\n.web-stories-list__lightbox amp-story-player,\n.web-stories-singleton__lightbox amp-story-player {\n  width: 100%;\n  height: 100%;\n}\n\n.story-lightbox__close-button {\n  display: inline-block;\n  position: absolute;\n  left: 0;\n  top: 8px;\n  cursor: pointer;\n  height: 40px;\n  width: 40px;\n  z-index: 1;\n  border: none;\n  background: none !important;\n  border-radius: 0;\n}\n\n.story-lightbox__close-button--stick {\n  display: inline-block;\n  position: absolute;\n  left: 20px;\n  top: 15px;\n  height: 20px;\n  width: 3px;\n  background-color: #fff;\n  transform: rotateZ(45deg);\n}\n\n.story-lightbox__close-button--stick:first-child {\n  transform: rotateZ(-45deg);\n}\n\n/*\n * amp-story-player's 'shadow-root-intermediary' element shows black space on top,\n * because of the 'a' links. Making 'a' absolutely positioned removes them from normal\n * relative flow, removes the space.\n */\nhtml:not([amp]) .web-stories-singleton__lightbox amp-story-player a,\nhtml:not([amp])\n  .web-stories-list\n  .web-stories-list__lightbox\n  amp-story-player\n  a {\n  position: absolute;\n}\n\n@media all and (min-width: 676px) {\n  .admin-bar .web-stories-list__lightbox,\n  .admin-bar .web-stories-singleton__lightbox {\n    top: 46px;\n  }\n\n  .story-lightbox__close-button {\n    left: 10px;\n  }\n\n  .story-lightbox__close-button--stick {\n    left: 20px;\n    top: 5px;\n    height: 25px;\n  }\n}\n\n@media all and (min-width: 783px) {\n  .admin-bar .web-stories-list__lightbox,\n  .admin-bar .web-stories-singleton__lightbox {\n    top: 32px;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/singleton.css",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n.web-stories-singleton.alignnone,\n.web-stories-singleton.alignleft,\n.web-stories-singleton.alignright {\n  display: block;\n  width: 100%;\n}\n\n.web-stories-singleton.aligncenter {\n  text-align: initial;\n}\n\n.web-stories-singleton .wp-block-embed__wrapper {\n  position: relative;\n}\n\n.web-stories-singleton.alignleft .wp-block-embed__wrapper {\n  margin-right: auto;\n}\n\n.web-stories-singleton.alignright .wp-block-embed__wrapper {\n  margin-left: auto;\n}\n\n.web-stories-singleton.alignnone .wp-block-embed__wrapper {\n  max-width: var(--width);\n}\n\n.web-stories-singleton.aligncenter .wp-block-embed__wrapper {\n  margin-left: auto;\n  margin-right: auto;\n  max-width: var(--width);\n}\n\n/* Curved corners by default.*/\n.web-stories-singleton-poster {\n  position: relative;\n  aspect-ratio: var(--aspect-ratio);\n  border-radius: 8px;\n  overflow: hidden;\n  cursor: pointer;\n}\n\n.web-stories-singleton-poster a {\n  display: block;\n  margin: 0;\n  aspect-ratio: var(--aspect-ratio);\n}\n\n.web-stories-singleton-poster .web-stories-singleton-poster-placeholder {\n  box-sizing: border-box;\n}\n\n/*\n  We want the placeholder to be clickable but hidden from screen readers.\n  This improves the no-js experience.\n  In the block edit component, placeholders are not links.\n*/\n.web-stories-singleton-poster .web-stories-singleton-poster-placeholder a,\n.web-stories-singleton-poster .web-stories-singleton-poster-placeholder span {\n  border: 0;\n  clip: rect(1px, 1px, 1px, 1px);\n  -webkit-clip-path: inset(50%);\n  clip-path: inset(50%);\n  height: 1px;\n  margin: -1px;\n  overflow: hidden;\n  padding: 0;\n  position: absolute !important;\n  width: 1px;\n  word-wrap: normal !important;\n  word-break: normal;\n}\n\n.web-stories-singleton-poster img {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  box-sizing: border-box;\n}\n\n.web-stories-singleton-poster::after {\n  content: '';\n  display: block;\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  background: linear-gradient(\n    180deg,\n    rgba(255, 255, 255, 0) 0%,\n    rgba(0, 0, 0, 0.8) 100%\n  );\n  top: 0;\n  left: 0;\n  pointer-events: none;\n}\n\n.web-stories-singleton .web-stories-singleton-overlay {\n  padding: 10px;\n  line-height: var(--ws-overlay-text-lh);\n  position: absolute;\n  bottom: 0;\n  color: var(--ws-overlay-text-color);\n  z-index: 1;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/style.css",
    "content": "@import 'variables.css';\n@import 'common.css';\n@import 'lightbox.css';\n\n/* View Types */\n@import 'views/grid.css';\n@import 'views/circles.css';\n@import 'views/list.css';\n@import 'views/carousel.css';\n"
  },
  {
    "path": "packages/stories-block/src/css/variables.css",
    "content": ":root {\n  --ws-font-size-title: 18px;\n  --ws-font-size-circle-title: 14px;\n  --ws-font-size-excerpt: 16px;\n  --ws-font-size-author-date: 14px;\n  --ws-aspect-ratio: 4 / 6;\n  --ws-list-aspect-ratio: 4 / 6;\n  --ws-overlay-text-color: #fff;\n  --ws-overlay-text-lh: 1.3;\n  --ws-story-min-width: 160px;\n  --ws-story-max-width: 285px;\n  --ws-circle-size: 96px;\n  --ws-circle-border-color: #ccc;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/views/carousel.css",
    "content": "/* Web Stories: Carousel View */\n\n.carousel > .glider-track > .web-stories-list__story {\n  margin: 0 10px;\n}\n\n@media all and (min-width: 676px) {\n  .web-stories-list.is-view-type-carousel .web-stories-list__story {\n    margin: 0 5px;\n    max-width: var(--ws-story-max-width);\n  }\n}\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-carousel\n  .web-stories-list__story {\n  margin: 0 5px;\n  max-width: var(--ws-story-max-width);\n}\n\n.web-stories-list.is-carousel.has-archive-link {\n  margin-top: calc(\n    24px + 35px\n  ); /* default margin from common.css plus below offset */\n}\n\n.web-stories-theme-header-section\n  .web-stories-list.is-carousel.has-archive-link {\n  position: relative;\n  margin-top: 24px;\n  padding-top: calc(24px + 35px);\n}\n\n.web-stories-list.is-carousel .web-stories-list__archive-link {\n  text-align: right;\n  margin-bottom: 5px;\n}\n\n.web-stories-theme-header-section\n  .web-stories-list.is-carousel\n  .web-stories-list__archive-link {\n  margin-right: 10px;\n}\n\n.web-stories-list.is-carousel .glider-next,\n.web-stories-list.is-carousel .glider-prev {\n  padding: 10px;\n  top: 50%;\n  transform: translateY(-50%);\n}\n\n.web-stories-list.is-carousel .glider-prev {\n  transform: translateY(-50%) rotate(180deg) /*!rtl:translateY(-50%)*/;\n  left: 0;\n  right: auto;\n}\n\n.web-stories-list.is-carousel .glider-next {\n  right: 0;\n  left: auto;\n}\n\n.web-stories-list.is-carousel .glider-next,\n.web-stories-list.is-carousel .amp-carousel-button-next,\n.web-stories-list.is-carousel .glider-prev,\n.web-stories-list.is-carousel .amp-carousel-button-prev {\n  background-image: url('../../inline-icons/carousel-arrow.svg');\n}\n\n.web-stories-list.is-carousel .glider-next,\n.web-stories-list.is-carousel .amp-carousel-button-next {\n  right: 0;\n}\n\n.web-stories-list.is-carousel .glider-prev,\n.web-stories-list.is-carousel .amp-carousel-button-prev {\n  left: 0;\n}\n\n.web-stories-list.is-carousel .amp-carousel-button-prev {\n  transform: rotate(180deg) /*!rtl:none*/;\n}\n\nhtml[dir='rtl'] .web-stories-list.is-carousel .amp-carousel-button-next {\n  transform: rotate(180deg);\n}\n\n.web-stories-list.is-carousel .amp-carousel-button,\n.web-stories-list.is-carousel .glider-next,\n.web-stories-list.is-carousel .glider-prev {\n  border-radius: 50%;\n  background-color: #eaeaea;\n  background-size: 30%;\n  background-repeat: no-repeat;\n  background-position: center;\n  box-sizing: border-box;\n  height: 34px;\n  width: 34px;\n  border-style: none;\n  z-index: 10;\n  pointer-events: all;\n  cursor: pointer;\n}\n\nhtml[dir='rtl'] .web-stories-list.is-carousel .glider-next {\n  transform: translateY(-50%) rotate(180deg);\n}\n\n.web-stories-list.is-carousel\n  .web-stories-list__carousel:not(.glider)\n  ~ .glider-next,\n.web-stories-list.is-carousel\n  .web-stories-list__carousel:not(.glider)\n  ~ .glider-prev {\n  display: none;\n}\n\n.glider-next.disabled,\n.glider-prev.disabled,\n.web-stories-list.is-carousel .amp-carousel-button.amp-disabled {\n  opacity: 0;\n}\n\n/* Temporary till we have full support for the RTL carousel. */\nhtml[dir='rtl'] .glider-next.disabled,\nhtml[dir='rtl'] .glider-prev.disabled {\n  opacity: 1;\n  cursor: pointer;\n}\n\nhtml[dir='rtl'] .glider-next.disabled:hover,\nhtml[dir='rtl'] .glider-prev.disabled:hover,\n.web-stories-list.is-carousel .glider-next:not(.disabled):hover,\n.web-stories-list.is-carousel .glider-prev:not(.disabled):hover,\n.web-stories-list.is-carousel .glider-next:not(.disabled):focus,\n.web-stories-list.is-carousel .glider-prev:not(.disabled):focus,\n.web-stories-list.is-carousel .amp-carousel-button:not(.amp-disabled):hover {\n  filter: invert(1);\n}\n\n.web-stories-list.is-carousel .web-stories-list__carousel {\n  scrollbar-width: none;\n}\n\n.web-stories-list.is-carousel .glider-track::-webkit-scrollbar {\n  display: none;\n}\n\n.web-stories-list.is-carousel.is-view-type-carousel\n  .web-stories-list__carousel:not(.glider) {\n  display: flex;\n  overflow-y: scroll;\n}\n\n@supports (scroll-marker-group: after) {\n  .web-stories-list.is-carousel .web-stories-list__carousel ~ .glider-prev,\n  .web-stories-list.is-carousel .web-stories-list__carousel ~ .glider-next {\n    display: none;\n  }\n\n  .web-stories-list.is-carousel .web-stories-list__inner-wrapper {\n    max-width: none !important;\n    display: grid;\n    justify-content: center;\n  }\n\n  .web-stories-list.is-carousel .web-stories-list__carousel {\n    display: grid;\n    grid-auto-flow: column;\n    grid-auto-columns: var(--ws-circle-size);\n    gap: 0 10px;\n    position: relative;\n\n    scroll-behavior: smooth;\n    scrollbar-width: none;\n\n    overflow-x: auto;\n    overscroll-behavior-x: contain;\n\n    scroll-snap-type: x mandatory;\n  }\n\n  .web-stories-list.is-view-type-circles .web-stories-list__story {\n    margin: 0;\n    scroll-snap-align: center;\n  }\n\n  /* stylelint-disable selector-type-no-unknown, selector-pseudo-element-no-unknown */\n\n  .web-stories-list.is-carousel .web-stories-list__carousel::scroll-button(*) {\n    display: block;\n    aspect-ratio: 1;\n    border-radius: 50%;\n    background-color: #eaeaea;\n    background-size: 30%;\n    background-repeat: no-repeat;\n    background-position: center;\n    box-sizing: border-box;\n    height: 34px;\n    width: 34px;\n    border-style: none;\n    z-index: 10;\n    line-height: 1;\n    pointer-events: all;\n    cursor: pointer;\n    opacity: 1;\n    transition:\n      opacity 0.5s cubic-bezier(0.17, 0.67, 0.83, 0.67),\n      color 0.5s cubic-bezier(0.17, 0.67, 0.83, 0.67);\n    position: absolute;\n    top: 50%;\n  }\n\n  .web-stories-list.is-carousel\n    .web-stories-list__carousel::scroll-button(*):disabled {\n    opacity: 0;\n  }\n\n  .web-stories-list.is-carousel\n    .web-stories-list__carousel::scroll-button(*):hover {\n    filter: invert(1);\n  }\n\n  .web-stories-list.is-carousel\n    .web-stories-list__carousel::scroll-button(left) {\n    transform: rotate(180deg);\n    /* stylelint-disable-next-line declaration-property-value-no-unknown */\n    content: url('../../inline-icons/carousel-arrow.svg') / attr(data-prev);\n    /*!rtl:ignore*/\n    left: 0;\n  }\n\n  .web-stories-list.is-carousel\n    .web-stories-list__carousel::scroll-button(right) {\n    /* stylelint-disable-next-line declaration-property-value-no-unknown */\n    content: url('../../inline-icons/carousel-arrow.svg') / attr(data-next);\n    /*!rtl:ignore*/\n    right: 0;\n  }\n\n  /* stylelint-enable selector-type-no-unknown, selector-pseudo-element-no-unknown */\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/views/circles.css",
    "content": "/* Web Stories: Circles View */\n\n.web-stories-theme-header-section .web-stories-list.is-view-type-circles {\n  border-bottom: 1px solid #ccc;\n  padding: 12px 0;\n}\n\n.web-stories-list.is-view-type-circles .amp-carousel-slide {\n  vertical-align: top;\n}\n\n.web-stories-list.is-view-type-circles .glider-track {\n  margin: 0 auto;\n}\n\n.web-stories-list.is-view-type-circles .web-stories-list__story {\n  max-width: var(--ws-circle-size);\n  min-width: var(--ws-circle-size);\n  margin: 0 5px;\n  text-align: center;\n  display: inline-block;\n}\n\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster,\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster a {\n  aspect-ratio: 1;\n}\n\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster > img {\n  border-radius: 50%;\n}\n\n.web-stories-list.is-view-type-circles\n  .web-stories-list__story-poster\n  .web-stories-list__story-poster-placeholder,\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster > img,\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster a > img {\n  position: absolute;\n  top: 0;\n  left: 0;\n  height: var(--ws-circle-size);\n  width: var(--ws-circle-size);\n  max-width: initial;\n  border-radius: 50%;\n  background-clip: content-box;\n  border: 2px solid var(--ws-circle-border-color);\n  padding: 2px;\n}\n\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster a > img {\n  border-radius: 50%;\n}\n\n.web-stories-list.is-view-type-circles .web-stories-list__story-poster::after {\n  display: none;\n}\n\n.web-stories-list.is-view-type-circles\n  .web-stories-list__story-poster-placeholder::after {\n  content: '';\n  display: block;\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  background: linear-gradient(\n    180deg,\n    rgba(255, 255, 255, 0) 0%,\n    rgba(0, 0, 0, 0.8) 100%\n  );\n  top: 0;\n  left: 0;\n  border-radius: 50%;\n}\n\n.web-stories-list.is-view-type-circles\n  .web-stories-list__story-content-overlay {\n  padding-bottom: 0;\n}\n\n.web-stories-list.is-view-type-circles .story-content-overlay__title {\n  font-size: var(--ws-font-size-circle-title);\n}\n\n.web-stories-list.is-view-type-circles.has-title .glider-next,\n.web-stories-list.is-view-type-circles.has-title .glider-prev {\n  top: 35%;\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/views/grid.css",
    "content": "/* Web Stories: Grid View */\n.web-stories-list.is-view-type-grid .web-stories-list__inner-wrapper {\n  display: flex;\n  flex-wrap: wrap;\n}\n\n.web-stories-list.is-view-type-grid .web-stories-list__story {\n  flex-basis: calc(100% - 8px);\n  margin: 4px;\n}\n\n@media all and (min-width: 415px) {\n  .web-stories-list.is-view-type-grid.columns-1 .web-stories-list__story {\n    flex-basis: calc((100 / 1 * 1%) - 8px);\n  }\n  .web-stories-list.is-view-type-grid.columns-2 .web-stories-list__story {\n    flex-basis: calc((100 / 2 * 1%) - 8px);\n  }\n  .web-stories-list.is-view-type-grid.columns-3 .web-stories-list__story {\n    flex-basis: calc((100 / 3 * 1%) - 8px);\n  }\n  .web-stories-list.is-view-type-grid.columns-4 .web-stories-list__story {\n    flex-basis: calc((100 / 4 * 1%) - 8px);\n  }\n  .web-stories-list.is-view-type-grid.columns-5 .web-stories-list__story {\n    flex-basis: calc((100 / 5 * 1%) - 8px);\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/css/views/list.css",
    "content": "/* Web Stories: List View */\n.web-stories-list.is-view-type-list .web-stories-list__story {\n  margin-bottom: 12px;\n}\n\n.web-stories-list.is-view-type-list .web-stories-list__story-content-overlay {\n  position: absolute;\n  bottom: 0;\n  color: var(--ws-overlay-text-color);\n  z-index: 1;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .web-stories-list__story {\n  display: flex;\n  flex-wrap: nowrap;\n  align-items: center;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .web-stories-list__story-poster {\n  flex-basis: 40%;\n  aspect-ratio: var(--ws-list-aspect-ratio);\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .web-stories-list__story-poster::after {\n  display: none;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .web-stories-list__story-content-overlay {\n  flex-basis: 60%;\n  padding: 10px 15px;\n  position: relative;\n  color: inherit;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .image-align-right\n  .web-stories-list__story-poster {\n  order: 2;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list\n  .image-align-right\n  .web-stories-list__story-content-overlay {\n  order: 1;\n}\n\n.ws-legacy-widget-preview\n  .web-stories-list.is-view-type-list.is-style-default\n  .web-stories-list__story-poster {\n  border-radius: 8px;\n  overflow: hidden;\n}\n\n@media all and (min-width: 676px) {\n  .web-stories-list.is-view-type-list .web-stories-list__story {\n    display: flex;\n    flex-wrap: nowrap;\n    align-items: center;\n  }\n\n  .web-stories-list.is-view-type-list .web-stories-list__story-poster {\n    flex-basis: 40%;\n    aspect-ratio: var(--ws-list-aspect-ratio);\n  }\n\n  .web-stories-list.is-view-type-list .web-stories-list__story-poster::after {\n    display: none;\n  }\n\n  .web-stories-list.is-view-type-list .web-stories-list__story-content-overlay {\n    flex-basis: 60%;\n    padding: 10px 15px;\n    position: relative;\n    color: inherit;\n  }\n\n  .web-stories-list.is-view-type-list\n    .image-align-right\n    .web-stories-list__story-poster {\n    order: 2;\n  }\n\n  .web-stories-list.is-view-type-list\n    .image-align-right\n    .web-stories-list__story-content-overlay {\n    order: 1;\n  }\n\n  .web-stories-list.is-view-type-list.is-style-default\n    .web-stories-list__story-poster {\n    border-radius: 8px;\n    overflow: hidden;\n  }\n}\n"
  },
  {
    "path": "packages/stories-block/src/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n// The __webpack_public_path__ assignment will be done after the imports.\n// That's why the public path assignment is in its own dedicated module and imported here at the very top.\n// See https://webpack.js.org/guides/public-path/#on-the-fly\nimport './publicPath';\n\n/**\n * External dependencies\n */\nimport { initializeTracking } from '@googleforcreators/tracking';\n\n/**\n * WordPress dependencies\n */\nimport { registerBlockType } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { name, settings } from './block';\n\nregisterBlockType(name, settings);\n\ninitializeTracking('Embed Block', false);\n"
  },
  {
    "path": "packages/stories-block/src/publicPath.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n__webpack_public_path__ = window.webStoriesBlockSettings.publicPath;\n"
  },
  {
    "path": "packages/stories-block/src/view.ts",
    "content": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { store, getContext, getElement } from '@wordpress/interactivity';\n\ninterface StoryDef {\n  href: string;\n  title: string | null;\n  posterImage: string | null;\n  idx: number;\n  distance: number;\n  storyContentLoaded: boolean;\n  desktopAspectRatio: number | null;\n}\n\ninterface AmpStoryPlayerElement extends HTMLElement {\n  getStories: () => StoryDef[];\n  play: () => void;\n  pause: () => void;\n  rewind: () => void;\n  mute: () => void;\n  show: (href: string) => void;\n}\n\ninterface AmpStoryPlayerNavigationEvent extends Event {\n  detail: {\n    index: number;\n    remaining: number;\n  };\n}\n\ntype State = {\n  lightboxElement: HTMLElement | null;\n  player: null | AmpStoryPlayerElement;\n  stories: StoryDef[];\n  instanceId: string | null;\n  currentLocation: string | null;\n};\n\ntype BlockContext = {\n  instanceId: string;\n};\n\nfunction runWithViewTransition(f: () => void) {\n  if (!document.startViewTransition) {\n    f();\n  } else {\n    document.startViewTransition(() => f());\n  }\n}\n\nconst { state, actions } = store('web-stories-block', {\n  state: {\n    lightboxElement: null,\n    player: null,\n    stories: [],\n    instanceId: null,\n    currentLocation: null,\n  } as State,\n  actions: {\n    storyContentReady: (\n      storyObject: StoryDef,\n      callback: () => void,\n      maxRetries = 5\n    ) => {\n      const stateIntervalObj = setInterval(() => {\n        if (storyObject.storyContentLoaded === true) {\n          window.clearInterval(stateIntervalObj);\n          callback();\n        }\n        if (!--maxRetries) {\n          window.clearInterval(stateIntervalObj);\n        }\n      }, 250);\n    },\n    close: () => {\n      history.pushState({}, '', state.currentLocation);\n\n      const { player, lightboxElement } = state;\n      if (!player) {\n        return;\n      }\n\n      // Rewind the story and pause there upon closing the lightbox.\n      player.rewind();\n      player.pause();\n      player.mute();\n\n      lightboxElement?.classList.toggle('show');\n      document.body.classList.toggle('web-stories-lightbox-open');\n    },\n    open: (event: Event) => {\n      event.preventDefault();\n      const context = getContext<BlockContext>();\n      const lightboxElement =\n        document.querySelector(\n          `.ws-lightbox-${context.instanceId} .web-stories-list__lightbox`\n        ) ||\n        document.querySelector(\n          `.ws-lightbox-singleton-${context.instanceId} .web-stories-singleton__lightbox`\n        );\n\n      if (!lightboxElement) {\n        return;\n      }\n\n      const player = lightboxElement.querySelector(\n        'amp-story-player'\n      ) as unknown as AmpStoryPlayerElement;\n      const stories = player.getStories();\n\n      state.lightboxElement = lightboxElement as HTMLElement;\n      state.player = player;\n      state.stories = stories;\n      state.instanceId = context.instanceId;\n      state.currentLocation = location.href;\n\n      const { ref: card } = getElement();\n\n      const storyObject = stories.find(\n        (story) => story.href === card?.querySelector('a')?.href\n      );\n\n      if (storyObject) {\n        player.show(storyObject.href);\n        player.play();\n\n        actions.storyContentReady(storyObject, () => {\n          history.pushState({}, '', storyObject.href);\n        });\n      }\n\n      runWithViewTransition(() => {\n        lightboxElement.classList.toggle('show');\n        document.body.classList.toggle('web-stories-lightbox-open');\n      });\n    },\n    navigation: (event: AmpStoryPlayerNavigationEvent) => {\n      const storyObject = state.stories[event.detail.index];\n      if (storyObject && storyObject.href !== document.location.href) {\n        actions.storyContentReady(storyObject, () => {\n          history.pushState({}, '', storyObject.href);\n        });\n      }\n    },\n    onPopstate: () => {\n      const lightboxElement = state.lightboxElement;\n      const player = state.player;\n      const isLightboxOpen = lightboxElement?.classList.contains('show');\n\n      const storyObject = state.stories.find(\n        (story) => story.href === document.location.href\n      );\n\n      if (storyObject) {\n        if (!isLightboxOpen) {\n          lightboxElement?.classList.toggle('show');\n          document.body.classList.toggle('web-stories-lightbox-open');\n          player?.play();\n        }\n\n        player?.show(storyObject.href);\n      } else if (isLightboxOpen) {\n        actions.close();\n      }\n    },\n  },\n});\n"
  },
  {
    "path": "packages/stories-block/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\n    \"src/view.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/stories-carousel/README.md",
    "content": "# Carousel\n\nCarousel using a glider-js.\n"
  },
  {
    "path": "packages/stories-carousel/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/stories-carousel\",\n  \"description\": \"Web Stories embeds carousel script\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/stories-carousel/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/stories-carousel\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@web-stories-wp/glider\": \"*\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/stories-carousel/src/@types/global.d.ts",
    "content": "/*\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\ndeclare global {\n  let __webpack_public_path__: string;\n\n  interface Window {\n    webStoriesCarouselSettings: {\n      publicPath: string;\n      config: {\n        isRTL: boolean;\n      };\n    };\n  }\n}\n\nexport type {};\n"
  },
  {
    "path": "packages/stories-carousel/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n__webpack_public_path__ = window.webStoriesCarouselSettings.publicPath;\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  void (async () => {\n    // Do not initialize Glider.js if browser supports CSS carousels.\n    if (CSS.supports('scroll-marker-group: after')) {\n      return;\n    }\n\n    const carouselWrappers: NodeListOf<HTMLElement> = document.querySelectorAll(\n      '.web-stories-list__carousel'\n    );\n\n    const isRTL =\n      window.webStoriesCarouselSettings.config.isRTL ||\n      'rtl' === document.documentElement.getAttribute('dir');\n\n    if (!carouselWrappers.length) {\n      return;\n    }\n\n    const { default: Glider } = await import(\n      /* webpackChunkName: \"chunk-web-stories-glider\" */ '@web-stories-wp/glider' // @ts-expexct-error\n    );\n\n    carouselWrappers.forEach((carouselWrapper: HTMLElement) => {\n      // For multiple instance of the glider we need to link nav arrows appropriately.\n      const carouselId = carouselWrapper.dataset.id;\n\n      const navArrows = !isRTL\n        ? {\n            prev: `.${carouselId} .glider-prev`,\n            next: `.${carouselId} .glider-next`,\n          }\n        : {\n            prev: `.${carouselId} .glider-next`,\n            next: `.${carouselId} .glider-prev`,\n          };\n\n      const isCircles = carouselWrapper.classList.contains('circles');\n      const itemStyle = window.getComputedStyle(\n        carouselWrapper.querySelector(\n          '.web-stories-list__story'\n        ) as unknown as HTMLElement\n      );\n\n      const itemWidth =\n        Number.parseFloat(itemStyle.width) +\n        (Number.parseFloat(itemStyle.marginLeft) +\n          Number.parseFloat(itemStyle.marginRight));\n\n      // For circles view we would want to keep it auto.\n      if (isCircles) {\n        /* eslint-disable-next-line no-new -- we do not store the object as no further computation required with the built object. */\n        new Glider(carouselWrapper, {\n          // Set to `auto` and provide item width to adjust to viewport\n          slidesToShow: 'auto',\n          slidesToScroll: 'auto',\n          itemWidth,\n          duration: 0.25,\n          scrollLock: true,\n          arrows: navArrows,\n        });\n      } else {\n        // For Box Carousel we are showing single slide below tablets viewport.\n        /* eslint-disable-next-line no-new -- we do not store the object as no further computation required with the built object. */\n        new Glider(carouselWrapper, {\n          slidesToShow: 'auto',\n          slidesToScroll: 'auto',\n          itemWidth,\n          duration: 0.25,\n          scrollLock: true,\n          arrows: navArrows,\n        });\n      }\n    });\n  })();\n});\n"
  },
  {
    "path": "packages/stories-carousel/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/story-editor/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/story-editor/README.md",
    "content": "# Story Editor\n\nWeb stories core editor\n"
  },
  {
    "path": "packages/story-editor/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/story-editor\",\n  \"description\": \"The core Web Stories editor web application, which is platform-agnostic.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/story-editor/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/story-editor\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.js\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.js\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@ap.cx/hues\": \"^2.4.0\",\n    \"@ffmpeg/core\": \"^0.11.0\",\n    \"@ffmpeg/ffmpeg\": \"^0.11.6\",\n    \"@googleforcreators/animation\": \"*\",\n    \"@googleforcreators/date\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/dom\": \"*\",\n    \"@googleforcreators/element-library\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/fonts\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/masks\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/migration\": \"*\",\n    \"@googleforcreators/moveable\": \"*\",\n    \"@googleforcreators/output\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/rich-text\": \"*\",\n    \"@googleforcreators/stickers\": \"*\",\n    \"@googleforcreators/templates\": \"*\",\n    \"@googleforcreators/text-sets\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@googleforcreators/transform\": \"*\",\n    \"@googleforcreators/units\": \"*\",\n    \"@googleforcreators/url\": \"*\",\n    \"@hello-pangea/color-picker\": \"^3.2.2\",\n    \"@mediapipe/selfie_segmentation\": \"^0.1.1675465747\",\n    \"@pioug/colorthief\": \"^4.0.0\",\n    \"@wmik/use-media-recorder\": \"^1.6.5-beta.0\",\n    \"blurhash\": \"^2.0.5\",\n    \"classnames\": \"^2.5.1\",\n    \"flagged\": \"^2.0.10\",\n    \"history\": \"^5.3.0\",\n    \"html-to-image\": \"1.10.8\",\n    \"immer\": \"^10.1.1\",\n    \"mediainfo.js\": \"^0.1.9\",\n    \"polished\": \"^4.3.1\",\n    \"prop-types\": \"^15.8.1\",\n    \"react-blurhash\": \"^0.3.0\",\n    \"react-calendar\": \"^4.3.0\",\n    \"react-photo-album\": \"^2.3.1\",\n    \"react-transition-group\": \"^4.4.5\",\n    \"react-virtual\": \"^2.10.4\",\n    \"remove-accents\": \"^0.5.0\",\n    \"sat\": \"^0.9.0\",\n    \"styled-components\": \"^5.3.11\",\n    \"stylis-plugin-rtl\": \"^1.0.0\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@googleforcreators/karma-fixture\": \"*\",\n    \"@googleforcreators/test-utils\": \"*\",\n    \"@testing-library/dom\": \"^10.4.1\",\n    \"@testing-library/jest-dom\": \"^6.9.1\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"jest\": \"^29.6.1\",\n    \"jest-axe\": \"^9.0.0\",\n    \"jest-matcher-deep-close-to\": \"^3.0.2\",\n    \"libheif-js\": \"^1.19.8\",\n    \"mockdate\": \"^3.0.5\",\n    \"react\": \"^17.0.2\",\n    \"react-moveable\": \"^0.56.0\"\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/api/apiProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\nimport { getAllTemplates, type Template } from '@googleforcreators/templates';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\nimport Context from './context';\n\nconst filterTemplates = (templates: Template[], search: string): Template[] => {\n  if (!search) {\n    return templates;\n  }\n  const lowercaseSearchTerm: string = search.toLowerCase();\n\n  return templates.filter(({ title, vertical, tags }) => {\n    return (\n      title.toLowerCase().includes(lowercaseSearchTerm) ||\n      vertical.toLowerCase().includes(lowercaseSearchTerm) ||\n      tags.some((tag) => tag.toLowerCase().includes(lowercaseSearchTerm))\n    );\n  });\n};\n\nfunction APIProvider({ children }: PropsWithChildren<Record<string, never>>) {\n  const { apiCallbacks: actions, cdnURL } = useConfig();\n  const pageTemplatesRef = useRef<Template[]>([]);\n\n  const newActions = {\n    ...actions,\n    getPageTemplates: useCallback(\n      async (search: string) => {\n        // check if pageTemplates have been loaded yet\n        if (pageTemplatesRef.current.length === 0) {\n          pageTemplatesRef.current = filterTemplates(\n            await getAllTemplates({\n              cdnURL,\n            }),\n            search\n          );\n        }\n        return filterTemplates(pageTemplatesRef.current, search);\n      },\n      [cdnURL]\n    ),\n  };\n\n  return (\n    <Context.Provider value={{ actions: newActions }}>\n      {children}\n    </Context.Provider>\n  );\n}\n\nexport default APIProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/api/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { APIState } from '../../types';\n\nexport default createContext<APIState>({ actions: {} });\n"
  },
  {
    "path": "packages/story-editor/src/app/api/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as APIProvider } from './apiProvider';\nexport { default as APIContext } from './context';\nexport { default as useAPI } from './useAPI';\n"
  },
  {
    "path": "packages/story-editor/src/app/api/test/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst TEST_COLOR = {\n  color: { r: 1, g: 1, b: 1 },\n};\n\nexport function createStory(properties = {}) {\n  return {\n    title: { raw: 'title' },\n    excerpt: { raw: 'excerpt' },\n    permalinkTemplate: 'http://localhost:8899/web-stories/%pagename%',\n    stylePresets: { colors: [TEST_COLOR] },\n    author: { id: 1, name: 'John Doe' },\n    featuredMedia: { height: 0, id: 0, url: '', width: 0 },\n    publisherLogo: { height: 0, id: 0, url: '', width: 0 },\n    ...properties,\n  };\n}\n\nexport const GET_MEDIA_RESPONSE_HEADER = {\n  totalItems: 1,\n  totalPages: 1,\n};\nexport const GET_MEDIA_RESPONSE_BODY = [\n  {\n    id: 274,\n    type: 'image',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    output: undefined,\n    creationDate: '2020-09-01T05:33:54',\n    src: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n    width: 1080,\n    height: 2220,\n    poster: undefined,\n    posterId: undefined,\n    length: undefined,\n    lengthFormatted: undefined,\n    alt: 'IMAGE',\n    isPlaceholder: false,\n    isMuted: false,\n    isOptimized: false,\n    isExternal: false,\n    sizes: {\n      medium: {\n        file: 'IMAGE-146x300.jpg',\n        width: 146,\n        height: 300,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-146x300.jpg',\n      },\n      large: {\n        file: 'IMAGE-498x1024.jpg',\n        width: 498,\n        height: 1024,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-498x1024.jpg',\n      },\n      thumbnail: {\n        file: 'IMAGE-150x150.jpg',\n        width: 150,\n        height: 150,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x150.jpg',\n      },\n      medium_large: {\n        file: 'IMAGE-768x1579.jpg',\n        width: 768,\n        height: 1579,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-768x1579.jpg',\n      },\n      '1536x1536': {\n        file: 'IMAGE-747x1536.jpg',\n        width: 747,\n        height: 1536,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-747x1536.jpg',\n      },\n      '2048x2048': {\n        file: 'IMAGE-996x2048.jpg',\n        width: 996,\n        height: 2048,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-996x2048.jpg',\n      },\n      'web-stories-poster-portrait': {\n        file: 'IMAGE-640x853.jpg',\n        width: 640,\n        height: 853,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-640x853.jpg',\n      },\n      'web-stories-publisher-logo': {\n        file: 'IMAGE-96x96.jpg',\n        width: 96,\n        height: 96,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://wp.local/wp-content/uploads/2020/09/IMAGE-96x96.jpg',\n      },\n      'web-stories-thumbnail': {\n        file: 'IMAGE-150x308.jpg',\n        width: 150,\n        height: 308,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x308.jpg',\n      },\n      full: {\n        file: 'IMAGE.jpg',\n        width: 1080,\n        height: 2220,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n      },\n    },\n    attribution: undefined,\n  },\n];\n"
  },
  {
    "path": "packages/story-editor/src/app/api/test/apiProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\nimport { getAllTemplates } from '@googleforcreators/templates';\n\n/**\n * Internal dependencies\n */\nimport useAPI from '../useAPI';\nimport ApiProvider from '../apiProvider';\nimport { ConfigProvider } from '../../config';\n\njest.mock('@googleforcreators/templates');\n\nconst renderApiProvider = ({ configValue }) => {\n  return renderHook(() => useAPI(), {\n    wrapper: (props) => (\n      <ConfigProvider config={configValue}>\n        <ApiProvider {...props} />\n      </ConfigProvider>\n    ),\n  });\n};\n\ndescribe('APIProvider', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  it('getPageTemplates gets pageTemplates with cdnURL', async () => {\n    const pageTemplates = [{ id: 'templateid' }];\n    getAllTemplates.mockReturnValue(pageTemplates);\n\n    const cdnURL = 'https://test.url';\n    const { result } = renderApiProvider({\n      configValue: {\n        apiCallbacks: {},\n        cdnURL,\n      },\n    });\n\n    let pageTemplatesResult;\n    await act(async () => {\n      pageTemplatesResult = await result.current.actions.getPageTemplates();\n    });\n\n    expect(pageTemplatesResult).toStrictEqual(pageTemplates);\n  });\n\n  it('getPageTemplates should memoize the templates if they have already been fetched', async () => {\n    const pageTemplates = [{ id: 'templateid' }];\n    getAllTemplates.mockReturnValue(pageTemplates);\n\n    const cdnURL = 'https://test.url';\n    const { result } = renderApiProvider({\n      configValue: {\n        apiCallbacks: {},\n        cdnURL,\n      },\n    });\n\n    let pageTemplatesResult;\n    await act(async () => {\n      pageTemplatesResult = await result.current.actions.getPageTemplates();\n    });\n\n    expect(getAllTemplates).toHaveBeenCalledOnce();\n    expect(pageTemplatesResult).toStrictEqual(pageTemplates);\n\n    await act(async () => {\n      pageTemplatesResult = await result.current.actions.getPageTemplates();\n    });\n\n    expect(getAllTemplates).toHaveBeenCalledOnce();\n    expect(pageTemplatesResult).toStrictEqual(pageTemplates);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/api/useAPI.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { APIState } from '../../types';\nimport Context from './context';\n\nfunction useAPI(): APIState;\nfunction useAPI<T>(selector: (state: APIState) => T): T;\nfunction useAPI<T>(selector: (state: APIState) => T | APIState = identity) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useAPI;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/canvasProvider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { UnitsProvider } from '@googleforcreators/units';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../layout';\nimport { useStory } from '../story';\nimport type {\n  BoundingBoxes,\n  EyedropperCallback,\n  RenamableLayer,\n  VoidFuncWithNoProps,\n} from '../../types';\nimport useCanvasCopyPaste from './useCanvasCopyPaste';\nimport useEditingElement from './useEditingElement';\n\nimport Context from './context';\nimport { RECT_OBSERVATION_KEY } from './constants';\n\ninterface Local {\n  position: string;\n  isDisplayed: boolean;\n}\nfunction CanvasProvider({ children }: PropsWithChildren<unknown>) {\n  const [boundingBoxes, setBoundingBoxes] = useState<BoundingBoxes>({});\n  const [lastSelectionEvent, setLastSelectionEvent] =\n    useState<MouseEvent | null>(null);\n  const lastSelectedElementIdRef = useRef<string | null>(null);\n  const [canvasContainer, setCanvasContainer] = useState<Node | null>(null);\n  const [pageContainer, setPageContainer] = useState<Node | null>(null);\n  const [fullbleedContainer, setFullbleedContainer] = useState<Node | null>(\n    null\n  );\n  const [designSpaceGuideline, setDesignSpaceGuideline] = useState<Node | null>(\n    null\n  );\n  const [pageAttachmentContainer, setPageAttachmentContainer] =\n    useState<Node | null>(null);\n  const [displayLinkGuidelines, setDisplayLinkGuidelines] =\n    useState<boolean>(false);\n  const [eyedropperImg, setEyedropperImg] = useState<string | null>(null);\n  const [eyedropperPixelData, setEyedropperPixelData] =\n    useState<Uint8ClampedArray | null>(null);\n  const [isEyedropperActive, setIsEyedropperActive] = useState<boolean>(false);\n  const [eyedropperCallback, setEyedropperCallback] =\n    useState<EyedropperCallback | null>(null);\n  const [renamableLayer, setRenamableLayer] = useState<RenamableLayer>(null);\n  const [floatingMenuPosition, setFloatingMenuPosition] = useState(() => {\n    const local = localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX.ELEMENT_TOOLBAR_SETTINGS\n    ) as Local | null;\n    return local?.position;\n  });\n  const [displayFloatingMenu, setDisplayFloatingMenu] = useState(() => {\n    const local = localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX.ELEMENT_TOOLBAR_SETTINGS\n    ) as Local | undefined;\n    return local?.isDisplayed;\n  });\n\n  // IntersectionObserver tracks clientRects which is what we need here.\n  // different from use case of useIntersectionEffect because this is extensible\n  // to multiple nodes.\n  const clientRectObserver = useMemo(\n    () =>\n      new window.IntersectionObserver((entries) => {\n        for (const entry of entries) {\n          if (!(entry.target instanceof HTMLElement)) {\n            return;\n          }\n          if (!entry.target.dataset[RECT_OBSERVATION_KEY]) {\n            return;\n          }\n          const index = entry.target.dataset[RECT_OBSERVATION_KEY];\n          setBoundingBoxes((boxes) => ({\n            ...boxes,\n            [index]: entry.boundingClientRect,\n          }));\n        }\n      }),\n    []\n  );\n  useEffect(() => () => clientRectObserver.disconnect(), [clientRectObserver]);\n\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n\n  const {\n    nodesById,\n    editingElement,\n    editingElementState,\n    setEditingElementWithState,\n    setEditingElementWithoutState,\n    clearEditing,\n    getNodeForElement,\n    setNodeForElement,\n  } = useEditingElement();\n\n  const {\n    backgroundElementId,\n    selectedElementIds,\n    toggleElementInSelection,\n    setSelectedElementsById,\n  } = useStory(\n    ({\n      state: { currentPage, selectedElementIds },\n      actions: { toggleElementInSelection, setSelectedElementsById },\n    }) => {\n      const elements = currentPage?.elements || [];\n      return {\n        backgroundElementId: elements[0]?.id,\n        selectedElementIds,\n        toggleElementInSelection,\n        setSelectedElementsById,\n      };\n    }\n  );\n\n  const handleSelectElement = useCallback(\n    (elId: string, evt: MouseEvent) => {\n      if (editingElement && editingElement !== elId) {\n        clearEditing();\n      }\n\n      // Skip the focus that immediately follows mouse event.\n      // Use the reference to the latest element because the events come in the\n      // sequence in the same event loop.\n      if (lastSelectedElementIdRef.current === elId && evt.type === 'focus') {\n        return;\n      }\n      lastSelectedElementIdRef.current = elId;\n      if (evt.shiftKey) {\n        toggleElementInSelection({ elementId: elId, withLinked: !evt.altKey });\n      } else {\n        setSelectedElementsById({\n          elementIds: [elId],\n          withLinked: !evt.altKey,\n        });\n      }\n      if (evt.currentTarget instanceof HTMLElement) {\n        evt.currentTarget.focus({ preventScroll: true });\n      }\n      if (backgroundElementId !== elId) {\n        evt.stopPropagation();\n      }\n\n      if ('mousedown' === evt.type) {\n        setLastSelectionEvent(evt);\n\n        // Clear this selection event as soon as mouse is released\n        // `setTimeout` is currently required to not break functionality.\n        if (evt.target instanceof HTMLElement) {\n          evt.target.ownerDocument.addEventListener(\n            'mouseup',\n            () => window.setTimeout(setLastSelectionEvent, 0, null),\n            { once: true, capture: true }\n          );\n        }\n      }\n    },\n    [\n      editingElement,\n      backgroundElementId,\n      clearEditing,\n      toggleElementInSelection,\n      setSelectedElementsById,\n    ]\n  );\n\n  // Reset editing mode when selection changes.\n  useEffect(() => {\n    if (\n      editingElement &&\n      (selectedElementIds.length !== 1 ||\n        selectedElementIds[0] !== editingElement)\n    ) {\n      clearEditing();\n    }\n    if (\n      lastSelectedElementIdRef.current &&\n      !selectedElementIds.includes(lastSelectedElementIdRef.current)\n    ) {\n      lastSelectedElementIdRef.current = null;\n    }\n  }, [editingElement, selectedElementIds, clearEditing]);\n\n  useCanvasCopyPaste();\n\n  const [onMoveableMount, setMoveableMount] =\n    useState<VoidFuncWithNoProps | null>(null);\n\n  const state = useMemo(\n    () => ({\n      state: {\n        pageContainer,\n        canvasContainer,\n        fullbleedContainer,\n        nodesById,\n        editingElement,\n        editingElementState,\n        isEditing: Boolean(editingElement),\n        lastSelectionEvent,\n        displayLinkGuidelines,\n        pageAttachmentContainer,\n        designSpaceGuideline,\n        isEyedropperActive,\n        eyedropperCallback,\n        eyedropperImg,\n        eyedropperPixelData,\n        boundingBoxes,\n        clientRectObserver,\n        onMoveableMount,\n        renamableLayer,\n        floatingMenuPosition,\n        displayFloatingMenu,\n      },\n      actions: {\n        setPageContainer,\n        setFullbleedContainer,\n        getNodeForElement,\n        setNodeForElement,\n        setEditingElement: setEditingElementWithoutState,\n        setEditingElementWithState,\n        clearEditing,\n        handleSelectElement,\n        setDisplayLinkGuidelines,\n        setPageAttachmentContainer,\n        setCanvasContainer,\n        setDesignSpaceGuideline,\n        setIsEyedropperActive,\n        setEyedropperCallback,\n        setEyedropperImg,\n        setEyedropperPixelData,\n        setMoveableMount,\n        setRenamableLayer,\n        setFloatingMenuPosition,\n        setDisplayFloatingMenu,\n      },\n    }),\n    [\n      pageContainer,\n      canvasContainer,\n      fullbleedContainer,\n      nodesById,\n      editingElement,\n      editingElementState,\n      lastSelectionEvent,\n      displayLinkGuidelines,\n      pageAttachmentContainer,\n      designSpaceGuideline,\n      isEyedropperActive,\n      eyedropperCallback,\n      eyedropperImg,\n      eyedropperPixelData,\n      boundingBoxes,\n      clientRectObserver,\n      renamableLayer,\n      getNodeForElement,\n      floatingMenuPosition,\n      displayFloatingMenu,\n      setNodeForElement,\n      setEditingElementWithoutState,\n      setEditingElementWithState,\n      clearEditing,\n      handleSelectElement,\n      onMoveableMount,\n      setMoveableMount,\n      setRenamableLayer,\n    ]\n  );\n  return (\n    <Context.Provider value={state}>\n      <UnitsProvider pageSize={pageSize}>{children}</UnitsProvider>\n    </Context.Provider>\n  );\n}\n\nexport default CanvasProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const RECT_OBSERVATION_KEY = 'rectObservationKey';\n\nexport const CANVAS_BOUNDING_BOX_IDS = {\n  CANVAS_CONTAINER: 'canvasContainer',\n  PAGE_CONTAINER: 'pageContainer',\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/context.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { CanvasProviderState } from '../../types';\nimport { noop } from '../../utils/noop';\n\nexport default createContext<CanvasProviderState>({\n  state: {\n    pageContainer: null,\n    canvasContainer: null,\n    fullbleedContainer: null,\n    nodesById: {},\n    editingElement: null,\n    editingElementState: {},\n    isEditing: false,\n    lastSelectionEvent: null,\n    displayLinkGuidelines: false,\n    pageAttachmentContainer: null,\n    designSpaceGuideline: null,\n    isEyedropperActive: false,\n    eyedropperCallback: null,\n    eyedropperImg: null,\n    eyedropperPixelData: null,\n    boundingBoxes: {},\n    clientRectObserver: null,\n    onMoveableMount: null,\n    renamableLayer: null,\n    floatingMenuPosition: undefined,\n    displayFloatingMenu: undefined,\n  },\n  actions: {\n    setPageContainer: noop,\n    setFullbleedContainer: noop,\n    getNodeForElement: noop,\n    setNodeForElement: noop,\n    setEditingElement: noop,\n    setEditingElementWithState: noop,\n    clearEditing: noop,\n    handleSelectElement: noop,\n    setDisplayLinkGuidelines: noop,\n    setPageAttachmentContainer: noop,\n    setCanvasContainer: noop,\n    setDesignSpaceGuideline: noop,\n    setIsEyedropperActive: noop,\n    setEyedropperCallback: noop,\n    setEyedropperImg: noop,\n    setEyedropperPixelData: noop,\n    setMoveableMount: noop,\n    setRenamableLayer: noop,\n    setFloatingMenuPosition: noop,\n    setDisplayFloatingMenu: noop,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as CanvasProvider } from './canvasProvider';\nexport { default as useCanvas } from './useCanvas';\nexport * from './constants';\nexport * from './useCanvasBoundingBox';\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useAddPastedElements.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useBatchingCallback } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { Element, Group, Groups } from '@googleforcreators/elements';\nimport type { StoryAnimation } from '@googleforcreators/animation';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../story';\n\nfunction useAddPastedElements() {\n  const {\n    currentPage,\n    addElements,\n    addGroup,\n    updateCurrentPageProperties,\n    deleteElementById,\n    combineElements,\n    addAnimations,\n  } = useStory(\n    ({\n      state: { currentPage },\n      actions: {\n        addElements,\n        addGroup,\n        deleteSelectedElements,\n        updateCurrentPageProperties,\n        deleteElementById,\n        combineElements,\n        addAnimations,\n      },\n    }) => {\n      return {\n        currentPage,\n        addElements,\n        addGroup,\n        deleteSelectedElements,\n        updateCurrentPageProperties,\n        deleteElementById,\n        combineElements,\n        addAnimations,\n      };\n    }\n  );\n\n  const addPastedElements = useBatchingCallback<\n    Element[],\n    StoryAnimation[] | undefined,\n    Groups | undefined,\n    boolean\n  >(\n    (\n      elements: Element[],\n      animations: StoryAnimation[] = [],\n      groups: Groups = {}\n    ) => {\n      if (elements.length === 0 || !currentPage) {\n        return false;\n      }\n\n      // If a bg element is pasted, handle that first\n      const newBackgroundElement = elements\n        .filter(elementIs.backgroundable)\n        .find(({ isBackground }) => isBackground);\n      let newAnimations = animations;\n      if (newBackgroundElement) {\n        const existingBgElement = currentPage.elements[0];\n        if (elementIs.defaultBackground(newBackgroundElement)) {\n          // The user has pasted a non-media background from another page:\n          // Delete existing background (if any) and then update page\n          // with this default element background color\n          if (!elementIs.defaultBackground(existingBgElement)) {\n            deleteElementById({ elementId: existingBgElement.id });\n          }\n          updateCurrentPageProperties({\n            properties: {\n              backgroundColor: newBackgroundElement.backgroundColor,\n            },\n          });\n        } else {\n          // Since background will maintain id, we update any\n          // new animations to have the proper target\n          newAnimations = animations.map((animation) =>\n            animation.targets.includes(newBackgroundElement.id)\n              ? { ...animation, targets: [existingBgElement.id] }\n              : animation\n          );\n          // The user has pasted a media background from another page:\n          // Merge this element into the existing background element on this page\n          combineElements({\n            firstElement: newBackgroundElement,\n            secondId: existingBgElement.id,\n            shouldRetainAnimations: false,\n          });\n        }\n      }\n\n      // Then add all regular elements if any exist\n      const nonBackgroundElements = elements.filter(\n        (element) => !elementIs.backgroundable(element) || !element.isBackground\n      );\n      const groupsEntries = Object.entries(groups);\n      const newGroups: [[string, string], Group][] = groupsEntries.map(\n        ([oldGroupId, group]) => {\n          const newGroupId = uuidv4();\n          return [[oldGroupId, newGroupId], group];\n        }\n      );\n      const nonBackgroundElementsWithNewGroups = nonBackgroundElements.map(\n        (el) => {\n          if (!el.groupId) {\n            return el;\n          }\n          const newGroup = newGroups.find(\n            ([[oldGroupId]]) => oldGroupId === el.groupId\n          );\n          if (!newGroup) {\n            return el;\n          }\n          const [[, newGroupId]] = newGroup;\n          return {\n            ...el,\n            groupId: newGroupId,\n          };\n        }\n      );\n      if (nonBackgroundElementsWithNewGroups.length) {\n        addElements({ elements: nonBackgroundElementsWithNewGroups });\n      }\n\n      if (newGroups.length) {\n        for (const newGroup of newGroups) {\n          const [[, newGroupId], group] = newGroup;\n          addGroup({ groupId: newGroupId, name: group.name });\n        }\n      }\n\n      // Add any animations associated with the new elements\n      addAnimations({ animations: newAnimations });\n\n      return true;\n    },\n    [\n      addElements,\n      addGroup,\n      currentPage,\n      updateCurrentPageProperties,\n      combineElements,\n      deleteElementById,\n      addAnimations,\n    ]\n  );\n\n  return addPastedElements;\n}\n\nexport default useAddPastedElements;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useCanvas.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { CanvasProviderState } from '../../types';\nimport Context from './context';\n\nfunction useCanvas(): CanvasProviderState;\nfunction useCanvas<T>(selector: (state: CanvasProviderState) => T): T;\nfunction useCanvas<T>(\n  selector: (state: CanvasProviderState) => T | CanvasProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useCanvasBoundingBox.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useContextSelector,\n} from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { BoundingBoxes } from '../../types';\nimport Context from './context';\nimport { RECT_OBSERVATION_KEY } from './constants';\n\n/**\n * Returns a ref that when applied to an element, stores the elements\n * bounding box info. Can retrieve the relevant bounding box info like so:\n * ```js\n * const boundingBox = useCanvasBoundingBox(CANVAS_BOUNDING_BOX_IDS[<some_bounding_box_id>])\n * ```\n */\nexport function useCanvasBoundingBoxRef(boundingBoxId: string) {\n  const clientRectObserver = useContextSelector(\n    Context,\n    ({ state }) => state.clientRectObserver\n  );\n  const ref = useRef<HTMLElement | null>(null);\n  return useCallback(\n    (node: HTMLElement) => {\n      if (!clientRectObserver) {\n        return;\n      }\n      if (ref.current) {\n        clientRectObserver.unobserve?.(ref.current);\n      }\n\n      if (node) {\n        node.dataset[RECT_OBSERVATION_KEY] = boundingBoxId;\n        clientRectObserver.observe(node);\n      }\n\n      ref.current = node;\n    },\n    [clientRectObserver, boundingBoxId]\n  );\n}\n\n/**\n * Returns the bounding box associated with the relative CANVAS_BOUNDING_BOX_IDS\n */\nexport function useCanvasBoundingBox(boundingBoxId: string) {\n  return useContextSelector(\n    Context,\n    ({ state }) => state.boundingBoxes?.[boundingBoxId as keyof BoundingBoxes]\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useCanvasCopyPaste.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useBatchingCallback } from '@googleforcreators/react';\nimport { usePasteTextContent } from '@googleforcreators/rich-text';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport {\n  elementIs,\n  ElementType,\n  type TextElement,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../story';\nimport useGlobalClipboardHandlers from '../../utils/useGlobalClipboardHandlers';\nimport {\n  addElementsToClipboard,\n  processPastedElements,\n} from '../../utils/copyPaste';\nimport useUploadWithPreview from '../../components/canvas/useUploadWithPreview';\nimport useInsertElement from '../../components/canvas/useInsertElement';\nimport { DEFAULT_PRESET } from '../../components/library/panes/text/textPresets';\nimport { MAX_PRODUCTS_PER_PAGE } from '../../constants';\nimport useAddPastedElements from './useAddPastedElements';\n\nfunction useCanvasGlobalKeys() {\n  const addPastedElements = useAddPastedElements();\n\n  const {\n    currentPage,\n    selectedElements,\n    deleteSelectedElements,\n    selectedElementAnimations,\n    selectedElementsGroups,\n    currentPageProductIds,\n  } = useStory(\n    ({\n      state: { currentPage, selectedElements, selectedElementAnimations },\n      actions: { deleteSelectedElements },\n    }) => {\n      const selectedElementsGroupsIds = selectedElements\n        .map((el) => el.groupId)\n        .filter(Boolean);\n      const selectedElementsGroupsEntries = Object.entries(\n        currentPage?.groups || {}\n      ).filter(([groupId]) => selectedElementsGroupsIds.includes(groupId));\n      const selectedElementsGroups = Object.fromEntries(\n        selectedElementsGroupsEntries\n      );\n      return {\n        currentPage,\n        selectedElements,\n        deleteSelectedElements,\n        selectedElementAnimations,\n        selectedElementsGroups,\n        currentPageProductIds: currentPage?.elements\n          ?.filter(elementIs.product)\n          .map(({ product }) => product.productId),\n      };\n    }\n  );\n\n  const showSnackbar = useSnackbar(({ showSnackbar }) => showSnackbar);\n\n  const uploadWithPreview = useUploadWithPreview();\n  const insertElement = useInsertElement();\n  const pasteInserter = (content: string) =>\n    insertElement(ElementType.Text, {\n      ...DEFAULT_PRESET,\n      content,\n    } as unknown as TextElement);\n  const pasteTextContent = usePasteTextContent(pasteInserter);\n\n  const copyCutHandler = useCallback(\n    (evt: ClipboardEvent) => {\n      if (!currentPage) {\n        return;\n      }\n      const { type: eventType } = evt;\n      if (selectedElements.length === 0) {\n        return;\n      }\n\n      addElementsToClipboard(\n        currentPage,\n        selectedElements,\n        selectedElementAnimations,\n        selectedElementsGroups,\n        evt\n      );\n\n      if (eventType === 'cut') {\n        deleteSelectedElements();\n      }\n      evt.preventDefault();\n    },\n    [\n      currentPage,\n      deleteSelectedElements,\n      selectedElements,\n      selectedElementAnimations,\n      selectedElementsGroups,\n    ]\n  );\n\n  const elementPasteHandler = useBatchingCallback(\n    (content: DocumentFragment): boolean => {\n      if (!currentPage) {\n        return false;\n      }\n      const { elements, animations, groups } = processPastedElements(\n        content,\n        currentPage,\n        selectedElements\n      );\n\n      const newProductsFromElements = elements\n        .filter(elementIs.product)\n        .filter(({ product }) => product.productId)\n        .map(({ product }) => product);\n\n      if (currentPageProductIds) {\n        if (\n          currentPageProductIds.length >= MAX_PRODUCTS_PER_PAGE ||\n          newProductsFromElements.length + currentPageProductIds.length >\n            MAX_PRODUCTS_PER_PAGE\n        ) {\n          showSnackbar({\n            message: sprintf(\n              /* translators: %d: max number of products. */\n              _n(\n                'Only %d item can be added per page.',\n                'Only %d items can be added per page.',\n                MAX_PRODUCTS_PER_PAGE,\n                'web-stories'\n              ),\n              MAX_PRODUCTS_PER_PAGE\n            ),\n          });\n        } else {\n          newProductsFromElements.forEach(\n            ({ productId, productTitle, productImages }) => {\n              if (currentPageProductIds.includes(productId)) {\n                showSnackbar({\n                  message: sprintf(\n                    /* translators: %s: product title. */\n                    __(\n                      'Product \"%s\" already exists on the page.',\n                      'web-stories'\n                    ),\n                    productTitle\n                  ),\n                  thumbnail: productImages?.[0]?.url\n                    ? {\n                        src: productImages[0].url,\n                        alt: productImages[0].alt,\n                      }\n                    : undefined,\n                });\n              }\n            }\n          );\n        }\n      }\n\n      return addPastedElements(elements, animations, groups);\n    },\n    [\n      addPastedElements,\n      currentPage,\n      showSnackbar,\n      currentPageProductIds,\n      selectedElements,\n    ]\n  );\n\n  const pasteHandler = useCallback(\n    (evt: ClipboardEvent) => {\n      const { clipboardData } = evt;\n\n      try {\n        // Get the html text and plain text but only if it's not a file being copied.\n        const content =\n          !clipboardData?.files?.length &&\n          (clipboardData?.getData('text/html') ||\n            clipboardData?.getData('text/plain'));\n        if (content) {\n          const template = document.createElement('template');\n          // Remove meta tag.\n          template.innerHTML = content\n            .replace(/<meta[^>]+>/g, '')\n            .replace(/<\\/?html>/g, '')\n            .replace(/<\\/?body>/g, '');\n          // First check if it's a paste of \"real\" elements copied from this editor\n          let hasAddedElements = elementPasteHandler(template.content);\n          if (!hasAddedElements) {\n            // If not, parse as HTML and insert text with formatting\n            hasAddedElements = pasteTextContent(template.innerHTML);\n          }\n          if (hasAddedElements) {\n            evt.preventDefault();\n          }\n        }\n\n        if (!clipboardData) {\n          return;\n        }\n        const { items } = clipboardData;\n        /**\n         * Loop through all items in clipboard to check if correct type. Ignore text here.\n         */\n        const files = [];\n        for (let i = 0; i < items.length; i++) {\n          const file = items[i].getAsFile();\n          if (file) {\n            files.push(file);\n          }\n        }\n        if (files.length > 0) {\n          uploadWithPreview(files);\n        }\n      } catch {\n        // Ignore.\n      }\n    },\n    [elementPasteHandler, pasteTextContent, uploadWithPreview]\n  );\n\n  useGlobalClipboardHandlers(copyCutHandler, pasteHandler);\n\n  // @todo: return copy/cut/pasteAction that can be used in the context menus.\n}\n\nexport default useCanvasGlobalKeys;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useCanvasKeys.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  useGlobalKeyDownEffect,\n  getKeyboardMovement,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport { StoryAnimationState } from '@googleforcreators/animation';\nimport { getDefinitionForType, elementIs } from '@googleforcreators/elements';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport type { RefObject } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { states } from '../highlights';\nimport useHighlights from '../highlights/useHighlights';\nimport { useStory } from '../story';\nimport getLayerArrangementProps from './utils/getLayerArrangementProps';\nimport { useCanvas } from '.';\n\nfunction useCanvasKeys(ref: RefObject<Node>) {\n  const {\n    selectedElementIds,\n    selectedElements,\n    arrangeSelection,\n    deleteSelectedElements,\n    duplicateElementsById,\n    updateSelectedElements,\n    setSelectedElementsById,\n    currentPage,\n    currentPageNumber,\n    animationState,\n    updateAnimationState,\n    currentPageProductIds,\n    pageElements,\n  } = useStory(\n    ({\n      state: {\n        selectedElementIds,\n        selectedElements,\n        currentPage,\n        currentPageNumber,\n        animationState,\n      },\n      actions: {\n        arrangeSelection,\n        deleteSelectedElements,\n        duplicateElementsById,\n        updateSelectedElements,\n        setSelectedElementsById,\n        updateAnimationState,\n      },\n    }) => {\n      return {\n        currentPage,\n        currentPageNumber,\n        selectedElementIds,\n        selectedElements,\n        arrangeSelection,\n        deleteSelectedElements,\n        duplicateElementsById,\n        updateSelectedElements,\n        setSelectedElementsById,\n        animationState,\n        updateAnimationState,\n        currentPageProductIds: currentPage?.elements\n          ?.filter(elementIs.product)\n          .map(({ product }) => product?.productId),\n        pageElements: currentPage?.elements,\n      };\n    }\n  );\n\n  const showSnackbar = useSnackbar(({ showSnackbar }) => showSnackbar);\n\n  const { setHighlights } = useHighlights(({ setHighlights }) => ({\n    setHighlights,\n  }));\n\n  const { isEditing, getNodeForElement, setEditingElement } = useCanvas(\n    ({\n      state: { isEditing },\n      actions: { getNodeForElement, setEditingElement },\n    }) => ({\n      isEditing,\n      getNodeForElement,\n      setEditingElement,\n    })\n  );\n  const selectedElementIdsRef = useRef<string[] | null>(null);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  selectedElementIdsRef.current = selectedElementIds;\n\n  // Return focus back to the canvas when another section loses the focus.\n  useEffect(() => {\n    const container = ref.current;\n    if (!container) {\n      return undefined;\n    }\n\n    const doc = container.ownerDocument;\n    if (!doc) {\n      return undefined;\n    }\n\n    const handler = () => {\n      // Make sure that no other component is trying to get the focus\n      // at this time. We have to check all \"focusout\" events here because\n      // after DOM removal, the \"focusout\" events are all over the place.\n      setTimeout(() => {\n        if (doc.activeElement === doc.body) {\n          // For a single selection, select the frame of this element.\n          // If none or multiple selection, select the container.\n          const currentSelectedIds = selectedElementIdsRef.current;\n          const selectedFrame =\n            currentSelectedIds?.length === 1\n              ? getNodeForElement(currentSelectedIds[0])\n              : null;\n\n          // Check if the selection event happened outside the canvas area\n          // If there is any text selection, we should not add the preventScroll setting,\n          // so that the user can select the text properly.\n          const sel = window.getSelection();\n          if (sel?.toString() !== '') {\n            return;\n          }\n\n          // If there is a multi-selection happening inside the canvas\n          // container, we should prevent the first element from scrolling.\n          if (selectedFrame) {\n            (selectedFrame as HTMLElement).focus({ preventScroll: true });\n          } else {\n            (container as HTMLElement).focus({ preventScroll: true });\n          }\n        }\n      }, 300);\n    };\n    doc.addEventListener('focusout', handler, true);\n    return () => {\n      doc.removeEventListener('focusout', handler, true);\n    };\n  }, [ref, getNodeForElement]);\n\n  useGlobalKeyDownEffect('delete', () => deleteSelectedElements(), [\n    deleteSelectedElements,\n  ]);\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+a'] },\n    () => {\n      if (!currentPage) {\n        return;\n      }\n      const elementIds = currentPage.elements.map(({ id }) => id);\n      setSelectedElementsById({ elementIds });\n    },\n    [currentPage, setSelectedElementsById]\n  );\n\n  // Position (x/y) key handler.\n  useGlobalKeyDownEffect(\n    { key: ['up', 'down', 'left', 'right'], shift: true },\n    ({ key, shiftKey }: KeyboardEvent) => {\n      if (isEditing || !selectedElements?.length) {\n        return;\n      }\n      const { isLocked } = selectedElements[0];\n      const isBackground =\n        elementIs.backgroundable(selectedElements[0]) &&\n        selectedElements[0].isBackground;\n      if (isBackground || isLocked) {\n        return;\n      }\n      const { dx, dy } = getKeyboardMovement(key, shiftKey);\n      updateSelectedElements({\n        properties: ({ x, y }) => ({\n          x: x + dx,\n          y: y + dy,\n        }),\n      });\n    },\n    [updateSelectedElements, isEditing, selectedElements]\n  );\n\n  // Layer up/down.\n  useGlobalKeyDownEffect(\n    { key: ['mod+up', 'mod+down', 'mod+left', 'mod+right'], shift: true },\n    (evt: KeyboardEvent) => {\n      const { key, shiftKey } = evt;\n\n      // Cancel the default behavior of the event: it's very jarring to run\n      // into mod+left/right triggering the browser's back/forward navigation.\n      evt.preventDefault();\n\n      // The shortcut doesn't support moving multiple elements currently.\n      if (selectedElements?.length === 1 && pageElements) {\n        const { position, groupId } = getLayerArrangementProps(\n          key,\n          shiftKey,\n          selectedElements,\n          pageElements\n        );\n\n        if (position || groupId) {\n          arrangeSelection({ position, groupId });\n        }\n      }\n    },\n    [arrangeSelection, selectedElements, pageElements]\n  );\n\n  // Edit mode\n  useGlobalKeyDownEffect(\n    { key: 'enter', clickable: false },\n    () => {\n      if (selectedElements.length !== 1) {\n        return;\n      }\n\n      const { type, id, isLocked } = selectedElements[0];\n      const { hasEditMode, hasEditModeIfLocked } = getDefinitionForType(type);\n      // Only handle Enter key for editable elements\n      if (!hasEditMode || (!hasEditModeIfLocked && isLocked)) {\n        return;\n      }\n\n      setEditingElement(id);\n    },\n    [selectedElements, setEditingElement]\n  );\n\n  const cloneHandler = useCallback(() => {\n    if (selectedElements.length === 0) {\n      return;\n    }\n\n    for (const el of selectedElements) {\n      if (elementIs.product(el)) {\n        const { product } = el;\n        const { productId, productTitle, productImages } = product;\n        if (productId && currentPageProductIds?.includes(productId)) {\n          showSnackbar({\n            message: sprintf(\n              /* translators: %s: product title. */\n              __('Product \"%s\" already exists on the page.', 'web-stories'),\n              productTitle\n            ),\n            thumbnail: productImages?.[0]?.url\n              ? {\n                  src: productImages[0].url,\n                  alt: productImages[0].alt,\n                }\n              : undefined,\n          });\n        }\n      }\n    }\n\n    duplicateElementsById({\n      elementIds: selectedElements.map((element) => element.id),\n    });\n  }, [\n    duplicateElementsById,\n    selectedElements,\n    currentPageProductIds,\n    showSnackbar,\n  ]);\n\n  useGlobalKeyDownEffect('clone', () => cloneHandler(), [cloneHandler]);\n\n  const isPlaying = [\n    StoryAnimationState.Playing,\n    StoryAnimationState.PlayingSelected,\n  ].includes(animationState);\n  useGlobalKeyDownEffect(\n    { key: ['mod+enter'] },\n    (evt: KeyboardEvent) => {\n      evt.preventDefault();\n      if (currentPageNumber === 1) {\n        return;\n      }\n      updateAnimationState({\n        animationState: isPlaying\n          ? StoryAnimationState.Reset\n          : StoryAnimationState.Playing,\n      });\n\n      void trackEvent('canvas_play_animations', {\n        status: isPlaying ? 'stop' : 'play',\n      });\n    },\n    [isPlaying, updateAnimationState, currentPageNumber]\n  );\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+k'] },\n    (evt: KeyboardEvent) => {\n      evt.preventDefault();\n      if (\n        !selectedElements.length ||\n        (elementIs.backgroundable(selectedElements[0]) &&\n          selectedElements[0].isBackground)\n      ) {\n        return;\n      }\n      setHighlights({\n        elements: selectedElements,\n        highlight: states.Link,\n      });\n    },\n    [setHighlights, selectedElements]\n  );\n}\n\nexport default useCanvasKeys;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/useEditingElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useReducer,\n  useRef,\n  useCallback,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\n\ninterface State {\n  isTrimMode?: boolean;\n  showOverflow?: boolean;\n}\ninterface EditingElementReducerState {\n  editingElement: string | null;\n  editingElementState?: State;\n}\ntype NodesById = Record<string, Node>;\nfunction useEditingElement() {\n  const [state, dispatch] = useReducer(reducer, {\n    editingElement: null,\n    editingElementState: {},\n  });\n  const [nodesById, setNodesById] = useState<NodesById>({});\n\n  const clearEditing = useCallback(() => {\n    dispatch({ editingElement: null });\n  }, []);\n\n  const setEditingElementWithoutState = useCallback((id: string) => {\n    dispatch({ editingElement: id });\n  }, []);\n\n  const setEditingElementWithState = useCallback(\n    (id: string, editingState: State) => {\n      dispatch({ editingElement: id, editingElementState: editingState });\n    },\n    []\n  );\n\n  const setNodeForElement = useCallback(\n    (id: string, ref: Node) =>\n      setNodesById((oldNodes) => ({ ...oldNodes, [id]: ref })),\n    [setNodesById]\n  );\n\n  // Immutable frame lookup for imperative actions.\n  const nodesByIdRef = useRef<NodesById | null>(null);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  nodesByIdRef.current = nodesById;\n  const getNodeForElement = useCallback(\n    (id: string) => nodesByIdRef.current?.[id],\n    []\n  );\n\n  const { editingElement, editingElementState } = state;\n  return useMemo(\n    () => ({\n      nodesById,\n      editingElement,\n      editingElementState,\n      setEditingElementWithState,\n      setEditingElementWithoutState,\n      clearEditing,\n      getNodeForElement,\n      setNodeForElement,\n    }),\n    [\n      nodesById,\n      editingElement,\n      editingElementState,\n      setEditingElementWithState,\n      setEditingElementWithoutState,\n      clearEditing,\n      getNodeForElement,\n      setNodeForElement,\n    ]\n  );\n}\n\nfunction reducer(\n  state: EditingElementReducerState,\n  { editingElement, editingElementState = {} }: EditingElementReducerState\n) {\n  return {\n    ...state,\n    editingElement,\n    editingElementState,\n  };\n}\n\nexport default useEditingElement;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Element } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { LayerDirection } from '../../../constants';\n\nfunction getLayerArrangementProps(\n  key: string,\n  shift: boolean,\n  selectedElements: Element[],\n  elements: Element[]\n) {\n  // This only supports moving single layer.\n  if (!selectedElements || selectedElements.length > 1) {\n    return {};\n  }\n  let position = null;\n  if (key === 'ArrowUp') {\n    position = shift ? LayerDirection.Front : LayerDirection.Forward;\n  }\n  if (key === 'ArrowDown') {\n    position = shift ? LayerDirection.Back : LayerDirection.Backward;\n  }\n  if (!position) {\n    return {};\n  }\n\n  const { id, groupId } = selectedElements[0];\n  // Get layer index.\n  const currentPosition = elements.findIndex(({ id: elId }) => elId === id);\n\n  // If the layer is in a group, check if it's first or last of the group,\n  // in this case we should just move it out of the group.\n  if (groupId) {\n    const isLastInGroup = elements[currentPosition - 1]?.groupId !== groupId;\n    const isFirstInGroup = elements[currentPosition + 1]?.groupId !== groupId;\n    if (\n      (isLastInGroup && position === LayerDirection.Backward) ||\n      (isFirstInGroup && position === LayerDirection.Forward)\n    ) {\n      return {\n        position: currentPosition,\n        groupId: null,\n      };\n    }\n  } else {\n    // If the element has a group below, just add it to the group.\n    if (\n      elements[currentPosition - 1]?.groupId &&\n      position === LayerDirection.Backward\n    ) {\n      return {\n        position: currentPosition,\n        groupId: elements[currentPosition - 1].groupId,\n      };\n    }\n    // If the element has a group above, just add it to the group.\n    if (\n      elements[currentPosition + 1]?.groupId &&\n      position === LayerDirection.Forward\n    ) {\n      return {\n        position: currentPosition,\n        groupId: elements[currentPosition + 1].groupId,\n      };\n    }\n  }\n\n  // Otherwise let's just change the position.\n  return { position };\n}\n\nexport default getLayerArrangementProps;\n"
  },
  {
    "path": "packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getLayerArrangementProps from '../getLayerArrangementProps';\nimport { LayerDirection } from '../../../../constants';\n\ndescribe('getLayerArrangementProps', () => {\n  it('should do nothing when more or less than one element is selected', () => {\n    expect(\n      getLayerArrangementProps(null, null, [{ id: '1' }, { id: '2' }])\n    ).toStrictEqual({});\n    expect(getLayerArrangementProps(null, null, [])).toStrictEqual({});\n  });\n\n  it('should do nothing if irrelevant key is pressed', () => {\n    expect(\n      getLayerArrangementProps('ArrowLeft', null, [{ id: '1' }])\n    ).toStrictEqual({});\n  });\n\n  it('should get the layer position as expected within layers without groups', () => {\n    const elements = [\n      { id: 'a', isBackground: true },\n      { id: 'b' },\n      { id: 'c' },\n      { id: 'd' },\n    ];\n    expect(\n      getLayerArrangementProps('ArrowUp', false, [{ id: 'b' }], elements)\n    ).toStrictEqual({ position: LayerDirection.Forward });\n    expect(\n      getLayerArrangementProps('ArrowDown', false, [{ id: 'c' }], elements)\n    ).toStrictEqual({ position: LayerDirection.Backward });\n  });\n\n  it('should get the layer group and position correctly for first/last layers of the group', () => {\n    const elements = [\n      { id: 'a', isBackground: true },\n      { id: 'b' },\n      { id: 'c', groupId: 'g1' },\n      { id: 'd', groupId: 'g1' },\n      { id: 'e', groupId: 'g2' },\n    ];\n    // Position stays the same but the layer is moved out of the group.\n    expect(\n      getLayerArrangementProps(\n        'ArrowUp',\n        false,\n        [{ id: 'd', groupId: 'g1' }],\n        elements\n      )\n    ).toStrictEqual({ position: 3, groupId: null });\n    expect(\n      getLayerArrangementProps(\n        'ArrowDown',\n        false,\n        [{ id: 'c', groupId: 'g1' }],\n        elements\n      )\n    ).toStrictEqual({ position: 2, groupId: null });\n  });\n\n  it('should get the layer group and position correctly when moving an element inside a group', () => {\n    const elements = [\n      { id: 'a', isBackground: true },\n      { id: 'b' },\n      { id: 'c', groupId: 'g1' },\n      { id: 'd', groupId: 'g1' },\n      { id: 'e', groupId: 'g1' },\n      { id: 'f' },\n    ];\n    expect(\n      getLayerArrangementProps(\n        'ArrowUp',\n        false,\n        [{ id: 'd', groupId: 'g1' }],\n        elements\n      )\n    ).toStrictEqual({ position: LayerDirection.Forward });\n    expect(\n      getLayerArrangementProps(\n        'ArrowDown',\n        false,\n        [{ id: 'd', groupId: 'g1' }],\n        elements\n      )\n    ).toStrictEqual({ position: LayerDirection.Backward });\n  });\n\n  it('should get the layer group and position correctly when moving an element into a group', () => {\n    const elements = [\n      { id: 'a', isBackground: true },\n      { id: 'b' },\n      { id: 'c', groupId: 'g1' },\n      { id: 'd' },\n      { id: 'e', groupId: 'g2' },\n    ];\n    // Position stays the same but the layer is moved into either group.\n    expect(\n      getLayerArrangementProps('ArrowUp', false, [{ id: 'd' }], elements)\n    ).toStrictEqual({ position: 3, groupId: 'g2' });\n    expect(\n      getLayerArrangementProps('ArrowDown', false, [{ id: 'd' }], elements)\n    ).toStrictEqual({ position: 3, groupId: 'g1' });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/config/configProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { ConfigState } from '../../types/configProvider';\nimport Context from './context';\n\nexport interface ConfigProviderProps {\n  children: ReactNode;\n  config: ConfigState;\n}\nfunction ConfigProvider({ config, children }: ConfigProviderProps) {\n  return <Context.Provider value={config}>{children}</Context.Provider>;\n}\n\nexport default ConfigProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/config/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { ConfigState } from '../../types/configProvider';\n\nexport default createContext<ConfigState>({\n  autoSaveInterval: null,\n  localAutoSaveInterval: 15,\n  autoSaveLink: '',\n  isRTL: false,\n  allowedMimeTypes: {},\n  storyId: null,\n  dashboardLink: '',\n  dashboardSettingsLink: '',\n  generalSettingsLink: '',\n  cdnURL: '',\n  maxUpload: 0,\n  capabilities: {},\n  metadata: {},\n  canViewDefaultTemplates: false,\n  showMedia3p: false,\n  encodeMarkup: false,\n  ffmpegCoreUrl: '',\n  apiCallbacks: {},\n  styleConstants: { topOffset: 0, leftOffset: 0 },\n  version: '',\n  shoppingProvider: '',\n  mediainfoUrl: '',\n  flags: {},\n  additionalTips: {},\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/config/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ConfigProvider } from './configProvider';\nexport { default as ConfigContext } from './context';\nexport { default as useConfig } from './useConfig';\n"
  },
  {
    "path": "packages/story-editor/src/app/config/useConfig.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { ConfigState } from '../../types/configProvider';\nimport Context from './context';\n\nfunction useConfig(): ConfigState;\nfunction useConfig<T>(\n  selector: (state: ConfigState) => T | ConfigState = identity\n) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useConfig;\n"
  },
  {
    "path": "packages/story-editor/src/app/currentUser/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { CurrentUserState } from '../../types/currentUserProvider';\n\nexport default createContext<CurrentUserState>({\n  state: {\n    currentUser: null,\n  },\n  actions: {\n    updateCurrentUser: () => null,\n    toggleWebStoriesMediaOptimization: () => null,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/currentUser/currentUserProvider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../api';\nimport type { User } from '../../types';\nimport type { CurrentUserState } from '../../types/currentUserProvider';\nimport Context from './context';\n\nfunction CurrentUserProvider({ children }: PropsWithChildren<unknown>) {\n  const [currentUser, setCurrentUser] = useState<User | null>(null);\n  const {\n    actions: { getCurrentUser, updateCurrentUser: _updateCurrentUser },\n  } = useAPI();\n\n  useEffect(() => {\n    let isMounted = true;\n    if (getCurrentUser && currentUser === null) {\n      void getCurrentUser().then((user: User) => {\n        if (!isMounted) {\n          return;\n        }\n        setCurrentUser(user);\n      });\n    }\n\n    return () => {\n      isMounted = false;\n    };\n  }, [currentUser, getCurrentUser]);\n\n  const updateCurrentUser = useCallback(\n    (data: Partial<User>) =>\n      _updateCurrentUser ? _updateCurrentUser(data).then(setCurrentUser) : null,\n    [_updateCurrentUser]\n  );\n\n  const toggleWebStoriesMediaOptimization = useCallback(() => {\n    if (currentUser === null) {\n      return null;\n    }\n    return updateCurrentUser({\n      mediaOptimization: !currentUser.mediaOptimization,\n    });\n  }, [currentUser, updateCurrentUser]);\n\n  const state: CurrentUserState = {\n    state: {\n      currentUser,\n    },\n    actions: {\n      toggleWebStoriesMediaOptimization,\n      updateCurrentUser,\n    },\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nexport default CurrentUserProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/currentUser/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as CurrentUserProvider } from './currentUserProvider';\nexport { default as CurrentUserContext } from './context';\nexport { default as useCurrentUser } from './useCurrentUser';\n"
  },
  {
    "path": "packages/story-editor/src/app/currentUser/useCurrentUser.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { CurrentUserState } from '../../types/currentUserProvider';\nimport Context from './context';\n\nfunction useCurrentUser(): CurrentUserState;\nfunction useCurrentUser<T>(selector: (state: CurrentUserState) => T): T;\nfunction useCurrentUser<T>(\n  selector: (state: CurrentUserState) => T | CurrentUserState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useCurrentUser;\n"
  },
  {
    "path": "packages/story-editor/src/app/font/actions/useLoadFontFiles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { getFontCSS, getGoogleFontURL } from '@googleforcreators/fonts';\nimport {\n  ensureFontLoaded,\n  loadInlineStylesheet,\n  loadStylesheet,\n} from '@googleforcreators/dom';\nimport { type FontData, FontService } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport cleanForSlug from '../../../utils/cleanForSlug';\nimport type { FontConfig } from '../types';\n\nfunction useLoadFontFiles() {\n  const maybeLoadFont = useCallback(async (font: FontData) => {\n    const { family, service, variants } = font;\n\n    const handle = cleanForSlug(family);\n    const elementId = `web-stories-${handle}-font-css`;\n\n    const hasFontLink = () => document.getElementById(elementId);\n\n    if (hasFontLink()) {\n      return;\n    }\n\n    switch (service) {\n      case FontService.GoogleFonts:\n        await loadStylesheet(\n          getGoogleFontURL([{ family, variants }], 'auto'),\n          elementId\n        );\n        break;\n      case FontService.Custom: {\n        const fontCSS = getFontCSS(family, font.url);\n        if (!fontCSS) {\n          return;\n        }\n        loadInlineStylesheet(elementId, fontCSS);\n        break;\n      }\n      default:\n        return;\n    }\n  }, []);\n\n  /**\n   * Enqueue a list of given fonts by adding <link> or <style> elements.\n   *\n   * Allows dynamically enqueuing font styles when needed.\n   *\n   * @param {Array} fonts An array of fonts properties to create a valid FontFaceSet to inject and preload a font-face\n   * @return {Promise<boolean>} Returns fonts loaded promise\n   */\n  const maybeEnqueueFontStyle = useCallback(\n    (fonts: FontConfig[]) => {\n      return Promise.allSettled(\n        fonts.map(async ({ font, fontWeight, fontStyle, content }) => {\n          const { family, service } = font;\n          if (!family || service === FontService.System) {\n            return null;\n          }\n\n          const fontFaceSet = `\n              ${fontStyle || ''} ${fontWeight || ''} 0 '${family}'\n            `.trim();\n\n          await maybeLoadFont(font);\n\n          return ensureFontLoaded(fontFaceSet, content);\n        })\n      );\n    },\n    [maybeLoadFont]\n  );\n\n  return {\n    maybeEnqueueFontStyle,\n    maybeLoadFont,\n  };\n}\n\nexport default useLoadFontFiles;\n"
  },
  {
    "path": "packages/story-editor/src/app/font/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const GOOGLE_MENU_FONT_URL = 'https://fonts.googleapis.com/css';\n"
  },
  {
    "path": "packages/story-editor/src/app/font/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\nimport type { FontProviderState } from './types';\n\nexport default createContext<FontProviderState>({\n  state: {\n    fonts: [],\n    curatedFonts: [],\n    customFonts: [],\n    recentFonts: [],\n  },\n  actions: {\n    getFontsBySearch: () => Promise.resolve([]),\n    getFontByName: () => null,\n    maybeEnqueueFontStyle: () => Promise.resolve(),\n    getFontWeight: (name: string) => [{ name, value: 400 }],\n    getFontFallback: () => [''],\n    ensureMenuFontsLoaded: noop,\n    ensureCustomFontsLoaded: noop,\n    addRecentFont: noop,\n    loadCustomFonts: () => Promise.resolve(),\n    loadCuratedFonts: () => Promise.resolve(),\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/font/fontProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\nimport { CURATED_FONT_NAMES } from '@googleforcreators/fonts';\nimport { loadStylesheet } from '@googleforcreators/dom';\nimport type { FontData } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { FONT_WEIGHT_NAMES } from '../../constants';\nimport { useAPI } from '../api';\nimport Context from './context';\nimport useLoadFontFiles from './actions/useLoadFontFiles';\nimport { GOOGLE_MENU_FONT_URL } from './constants';\nimport type { FontWeightOption } from './types';\n\nfunction FontProvider({ children }: PropsWithChildren<unknown>) {\n  const [queriedFonts, setQueriedFonts] = useState<FontData[]>([]);\n  const [curatedFonts, setCuratedFonts] = useState<FontData[]>([]);\n  const [recentFonts, setRecentFonts] = useState<FontData[]>([]);\n  const [customFonts, setCustomFonts] = useState<FontData[] | null>(null);\n  const {\n    actions: { getFonts },\n  } = useAPI();\n\n  const fonts = queriedFonts.length > 0 ? queriedFonts : curatedFonts;\n\n  const loadCustomFonts = useCallback(async () => {\n    if (customFonts || !getFonts) {\n      return;\n    }\n\n    const _customFonts = await getFonts({\n      service: 'custom',\n    });\n\n    if (!_customFonts.length) {\n      return;\n    }\n\n    const formattedFonts = _customFonts.map((font) => ({\n      ...font,\n      // The font picker & preview expects the ID to be the font family name.\n      id: font.family,\n      name: font.family,\n      value: font.family,\n    }));\n\n    setCustomFonts(formattedFonts);\n  }, [getFonts, customFonts]);\n\n  const loadCuratedFonts = useCallback(async () => {\n    if (curatedFonts.length || !getFonts) {\n      return;\n    }\n\n    const newFonts = await getFonts({\n      include: CURATED_FONT_NAMES.join(','),\n    });\n\n    if (!newFonts.length) {\n      return;\n    }\n\n    const formattedFonts = newFonts.map((font) => ({\n      id: font.family,\n      name: font.family,\n      value: font.family,\n      ...font,\n    }));\n\n    setCuratedFonts(formattedFonts);\n  }, [getFonts, curatedFonts]);\n\n  const { maybeEnqueueFontStyle, maybeLoadFont } = useLoadFontFiles();\n\n  const getFontByName = useCallback(\n    (name: string) => {\n      const foundFont = fonts.find((font) => font.family === name);\n      return foundFont ? foundFont : null;\n    },\n    [fonts]\n  );\n\n  const getFontsBySearch = useCallback(\n    async (search: string) => {\n      if (search.length < 2) {\n        setQueriedFonts([]);\n        return [];\n      }\n\n      const newFonts = (await getFonts?.({ search })) || [];\n\n      const formattedFonts = newFonts.map((font) => ({\n        ...font,\n        id: font.family,\n        name: font.family,\n        value: font.family,\n      }));\n\n      setQueriedFonts(formattedFonts);\n      return formattedFonts;\n    },\n    [getFonts]\n  );\n\n  const getFontWeight = useCallback(\n    (name: string) => {\n      const defaultFontWeights: FontWeightOption[] = [\n        { name: FONT_WEIGHT_NAMES[400], value: 400 },\n      ];\n\n      const currentFont = getFontByName(name);\n      let fontWeights = defaultFontWeights;\n      if (currentFont) {\n        const { weights } = currentFont;\n        if (weights) {\n          fontWeights = weights.map((weight) => ({\n            name: FONT_WEIGHT_NAMES[weight],\n            value: weight,\n          }));\n        }\n      }\n      return fontWeights;\n    },\n    [getFontByName]\n  );\n\n  const getFontFallback = useCallback(\n    (name: string) => {\n      const currentFont = getFontByName(name);\n      return currentFont?.fallbacks ? currentFont.fallbacks : [];\n    },\n    [getFontByName]\n  );\n\n  const addRecentFont = useCallback(\n    (recentFont: FontData) => {\n      const newRecentFonts = [recentFont];\n      recentFonts.forEach((font) => {\n        if (recentFont.family === font.family) {\n          return;\n        }\n        newRecentFonts.push(font);\n      });\n      setRecentFonts(newRecentFonts.slice(0, 5));\n    },\n    [recentFonts]\n  );\n\n  const menuFontsRef = useRef<string[]>([]);\n  const ensureMenuFontsLoaded = useCallback((fontsToLoad: string[]) => {\n    const newMenuFonts = fontsToLoad.filter(\n      (fontName) => !menuFontsRef.current.includes(fontName)\n    );\n    if (!newMenuFonts?.length) {\n      return;\n    }\n    menuFontsRef.current = menuFontsRef.current.concat(newMenuFonts);\n\n    // Create new <link> in head with ref to new font families\n    const families = encodeURIComponent(newMenuFonts.join('|'));\n    const url = `${GOOGLE_MENU_FONT_URL}?family=${families}&subset=menu&display=swap`;\n    loadStylesheet(url, 'web-stories-google-fonts-menu-css').catch(() => {\n      // If they failed to load, remove from array again!\n      menuFontsRef.current = menuFontsRef.current.filter(\n        (font) => !newMenuFonts.includes(font)\n      );\n    });\n  }, []);\n\n  const ensureCustomFontsLoaded = useCallback(\n    (fontsToLoad) => {\n      for (const font of fontsToLoad) {\n        const fontObj = customFonts?.find(({ family }) => family === font);\n\n        if (!fontObj) {\n          continue;\n        }\n\n        void maybeLoadFont(fontObj);\n      }\n    },\n    [customFonts, maybeLoadFont]\n  );\n\n  const state = {\n    state: {\n      fonts: queriedFonts.length > 0 ? queriedFonts : curatedFonts,\n      curatedFonts,\n      customFonts,\n      recentFonts,\n    },\n    actions: {\n      getFontsBySearch,\n      getFontByName,\n      maybeEnqueueFontStyle,\n      getFontWeight,\n      getFontFallback,\n      ensureMenuFontsLoaded,\n      ensureCustomFontsLoaded,\n      addRecentFont,\n      loadCustomFonts,\n      loadCuratedFonts,\n    },\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nexport default FontProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/font/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as FontProvider } from './fontProvider';\nexport { GOOGLE_MENU_FONT_URL } from './constants';\nexport { default as useFont } from './useFont';\n"
  },
  {
    "path": "packages/story-editor/src/app/font/test/actions/useLoadFontFiles.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { FontService } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport useLoadFontFiles from '../../actions/useLoadFontFiles';\n\nconst DEFAULT_FONT = {\n  font: {\n    family: 'Font',\n    service: FontService.GoogleFonts,\n    url: 'https://fonts.example.com/font.ttf',\n  },\n  fontWeight: 400,\n  fontStyle: 'normal',\n  content: 'Fill in some text',\n} as const;\n\nconst CUSTOM_FONT = {\n  font: {\n    family: 'Bar Regular',\n    service: FontService.Custom,\n    url: 'https://fonts.example.com/bar.ttf',\n  },\n  fontWeight: 400,\n  fontStyle: 'normal',\n  content: 'Fill in some text',\n} as const;\n\ndescribe('useLoadFontFiles', () => {\n  afterEach(() => {\n    document.querySelectorAll('link,style').forEach((el) => el.remove());\n  });\n\n  it('should enqueue fonts', () => {\n    expect(document.getElementById('font-css')).toBeNull();\n\n    renderHook(async () => {\n      const { maybeEnqueueFontStyle } = useLoadFontFiles();\n\n      await maybeEnqueueFontStyle([DEFAULT_FONT, CUSTOM_FONT]);\n    });\n\n    expect(document.getElementById('font-css')).toBeDefined();\n    expect(document.getElementById('bar-regular-css')).toBeDefined();\n  });\n\n  it('waits for all promises to be settled', () => {\n    expect(document.getElementById('font-css')).toBeNull();\n\n    renderHook(async () => {\n      const { maybeEnqueueFontStyle } = useLoadFontFiles();\n\n      await maybeEnqueueFontStyle([DEFAULT_FONT]);\n    });\n\n    expect(document.querySelectorAll('link')).toHaveLength(1);\n    expect(document.getElementById('font-css')).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/font/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  FontData,\n  FontStyle,\n  FontWeight,\n} from '@googleforcreators/elements';\n\nexport interface FontWeightOption {\n  name: string;\n  value: FontWeight;\n}\n\nexport interface FontProviderState {\n  state: {\n    fonts: FontData[];\n    curatedFonts: FontData[];\n    customFonts: FontData[] | null;\n    recentFonts: FontData[];\n  };\n  actions: {\n    getFontsBySearch: (name: string) => Promise<FontData[]>;\n    getFontByName: (name: string) => FontData | null;\n    maybeEnqueueFontStyle: (fonts: FontConfig[]) => Promise<unknown>;\n    getFontWeight: (name: string) => FontWeightOption[];\n    getFontFallback: (name: string) => string[];\n    ensureMenuFontsLoaded: (fonts: string[]) => void;\n    ensureCustomFontsLoaded: (fonts: string[]) => void;\n    addRecentFont: (font: FontData) => void;\n    loadCustomFonts: () => Promise<void>;\n    loadCuratedFonts: () => Promise<void>;\n  };\n}\n\nexport interface FontConfig {\n  font: FontData;\n  fontStyle: FontStyle;\n  content: string;\n  fontWeight?: FontWeight;\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/font/useFont.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { FontProviderState } from './types';\n\nfunction useFont(): FontProviderState;\nfunction useFont<T>(selector: (state: FontProviderState) => T): T;\nfunction useFont<T>(\n  selector: (state: FontProviderState) => T | FontProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useFont;\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { FOCUSABLE_SELECTORS } from '@googleforcreators/design-system';\n\nexport const KEYS = {\n  ADD_BACKGROUND_MEDIA: 'addBackgroundMedia',\n  CROP_SELECTED_ELEMENTS: 'cropSelectedElements',\n  CROP_ELEMENTS_WITH_SHAPES: 'cropElementsWithShapes',\n  SAFE_ZONE: 'safeZone',\n  PREVIEW_STORY: 'previewStory',\n  ADD_LINKS: 'addLinks',\n  ENABLE_SWIPE: 'enableSwipe',\n  DONE: 'done',\n};\n\nexport const TIPS = {\n  [KEYS.ADD_BACKGROUND_MEDIA]: {\n    title: __('Add background media', 'web-stories'),\n    figureSrc: 'images/help-center/add_bg_module_1',\n    description: [\n      __(\n        'Double click any image or video to enter edit mode. To scale, use the slider. To change the focal point, drag the image or video.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.CROP_SELECTED_ELEMENTS]: {\n    title: __('Crop selected element', 'web-stories'),\n    figureSrc: 'images/help-center/media_edit_mode_module_2',\n    description: [\n      __(\n        'Double click any image or video element to enter edit mode. Then, use the slider to scale the element or move its focal point by dragging it.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.CROP_ELEMENTS_WITH_SHAPES]: {\n    title: __('Crop elements using shapes', 'web-stories'),\n    figureSrc: 'images/help-center/media_bg_shape_module_3',\n    description: [\n      __(\n        'Select a shape from the Shape menu to create a frame.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.SAFE_ZONE]: {\n    title: __('Stay within the safe zone', 'web-stories'),\n    figureSrc: 'images/help-center/safe_zone_module_4',\n    description: [\n      __(\n        'Elements work best when you keep them within the safe zone. Outside of the safe zone, elements like links and buttons may get cropped out or not function properly.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.PREVIEW_STORY]: {\n    title: __('Preview your Web Story', 'web-stories'),\n    figureSrc: 'images/help-center/preview_module_5',\n    description: [\n      __(\n        'Use Preview Mode to view your Story before publishing.',\n        'web-stories'\n      ),\n      __(\n        'Make sure buttons, links, logos, and text aren’t too close to the edge of your screen and that no Story element overlaps with the navigation bar.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.ADD_LINKS]: {\n    title: __('Add links to story elements', 'web-stories'),\n    figureSrc: 'images/help-center/add_link_module_6',\n    description: [\n      __(\n        'Go to the Style tab. Scroll down to <strong>Link</strong> and enter a URL. To remove a link, select the \"X\" <screenreader> (clear)</screenreader> button next to the URL box.',\n        'web-stories'\n      ),\n    ],\n  },\n  [KEYS.ENABLE_SWIPE]: {\n    title: __('Enable swipe-up option', 'web-stories'),\n    figureSrc: 'images/help-center/page_attachment_module_7',\n    description: [\n      __(\n        'Go to the Style tab. Navigate to <strong>Call to Action</strong> and enter a web address and a call to action to describe the link.',\n        'web-stories'\n      ),\n    ],\n  },\n};\n\nexport const DONE_TIP_ENTRY = [\n  KEYS.DONE,\n  {\n    title: __('Done!', 'web-stories'),\n    description: [\n      __(\n        'You’re caught up with quick tips. We’ll notify you when we add new tips, but feel free to come back whenever you need help.',\n        'web-stories'\n      ),\n    ],\n  },\n] as const;\n\nexport const GUTTER_WIDTH = 24;\n\nexport const TRANSITION_DURATION = 500;\n\nexport const Z_INDEX = {\n  MENU: 1,\n  QUICK_TIP: 2,\n};\n\nexport const POPUP_ID = 'help_center_companion';\nexport const FOCUSABLE_POPUP_CHILDREN_SELECTOR = FOCUSABLE_SELECTORS.map(\n  (selector) => `#${POPUP_ID} ${selector}`\n).join(', ');\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\nimport type { HelpCenterContext } from './types';\n\nexport default createContext<HelpCenterContext>({\n  state: {\n    isOpen: false,\n    isOpeningToTip: false,\n    navigationIndex: -1,\n    navigationFlow: [],\n    isLeftToRightTransition: false,\n    hasBottomNavigation: false,\n    isPrevDisabled: false,\n    isNextDisabled: false,\n    readTips: {},\n    readError: false,\n    unreadTipsCount: 0,\n    isHydrated: false,\n    tips: {},\n    tipKeys: [],\n  },\n  actions: {\n    goToNext: noop,\n    goToPrev: noop,\n    goToMenu: noop,\n    goToTip: noop,\n    openToUnreadTip: noop,\n    toggle: noop,\n    close: noop,\n    hydrateReadTipsSuccess: noop,\n    persistingReadTipsError: noop,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as HelpCenterProvider } from './provider';\nexport { default as useHelpCenter } from './useHelpCenter';\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/provider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useState, useMemo, useRef } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useCurrentUser } from '../currentUser';\nimport { useAPI } from '../api';\nimport Context from './context';\nimport useHelpCenterReducer from './useHelpCenterReducer';\nimport type { HelpCenterState } from './types';\n\n/**\n * Turns a boolean map into a string key\n *\n * @param map an object to stringify\n * @return a key to provide to useEffect\n */\nconst createKeyFromBooleanMap = (map: Record<string, boolean>) =>\n  Object.keys(map || {}).join(' ');\n\n/**\n * reforms the boolean map from the key returned by createKeyFromBooleanMap\n *\n * @param key a string of space-separated map keys\n * @return the map of the provided keys with with true as the value\n */\nconst createBooleanMapFromKey = (key: string) =>\n  Object.fromEntries(\n    key\n      .split(' ')\n      .sort((a, b) => a.localeCompare(b))\n      .map((keyName) => [keyName, true])\n  );\n\nfunction HelpCenterProvider({ children }: PropsWithChildren<unknown>) {\n  const {\n    actions: { updateCurrentUser: _updateCurrentUser },\n  } = useAPI();\n  const canUpdateCurrentUser = Boolean(_updateCurrentUser);\n  const { currentUser, updateCurrentUser } = useCurrentUser(\n    ({ state, actions }) => ({\n      currentUser: state.currentUser,\n      updateCurrentUser: actions.updateCurrentUser,\n    })\n  );\n  const { state, actions } = useHelpCenterReducer();\n\n  // Once app is hydrated, start persisting unreadTips\n  const { isHydrated, unreadTipsCount } = state;\n  useEffect(() => {\n    if (isHydrated) {\n      const local = localStore.getItemByKey(\n        LOCAL_STORAGE_PREFIX.HELP_CENTER\n      ) as Partial<HelpCenterState>;\n      localStore.setItemByKey(LOCAL_STORAGE_PREFIX.HELP_CENTER, {\n        ...local,\n        unreadTipsCount,\n      });\n    }\n  }, [isHydrated, unreadTipsCount]);\n\n  // Persist user updates to isOpen\n  const { isOpen } = state;\n  useEffect(() => {\n    const local = localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX.HELP_CENTER\n    ) as Partial<HelpCenterState>;\n    localStore.setItemByKey(LOCAL_STORAGE_PREFIX.HELP_CENTER, {\n      ...local,\n      isOpen,\n    });\n  }, [isOpen]);\n\n  // Hydrate unread tips once from current user endpoint.\n  useEffect(() => {\n    if (!isHydrated && currentUser?.onboarding) {\n      actions.hydrateReadTipsSuccess({\n        readTips: currentUser.onboarding,\n      });\n    }\n  }, [actions, currentUser, isHydrated]);\n\n  const persistenceKey = createKeyFromBooleanMap(state.readTips);\n  const isInitialHydrationUpdate = useRef(false);\n  useEffect(() => {\n    if ((!persistenceKey && !isHydrated) || !canUpdateCurrentUser) {\n      return;\n    }\n\n    // We don't want to persist when the update is from\n    // the initial hydrate call\n    if (!isInitialHydrationUpdate.current) {\n      isInitialHydrationUpdate.current = true;\n      return;\n    }\n    updateCurrentUser({\n      onboarding: createBooleanMapFromKey(persistenceKey),\n    })?.catch(actions.persistingReadTipsError);\n  }, [\n    actions,\n    updateCurrentUser,\n    canUpdateCurrentUser,\n    persistenceKey,\n    isHydrated,\n  ]);\n\n  // Components wrapped in a Transition no longer receive\n  // prop updates once they start exiting. To work around\n  // this, we're passing them all state they need to\n  // initialize their animations, then scheduling the\n  // state update that causes them to transition 1 render\n  // after they receive those transition initializing props.\n  const [nextRenderState, setNextRenderState] = useState(state);\n  useEffect(() => setNextRenderState(state), [state]);\n\n  // Check whether the popup is opening, if so\n  // we want to use the state on this render\n  // to avoid a tip -> menu transition when opening,\n  // otherwise, while we're in the nav, we want to\n  // see the transition so we use navigation index\n  // from the next render\n  const navigationIndex =\n    !nextRenderState.isOpen && state.isOpen\n      ? state.navigationIndex\n      : nextRenderState.navigationIndex;\n\n  useEffect(() => {\n    if (\n      navigationIndex > -1 &&\n      state.navigationFlow.length >= navigationIndex\n    ) {\n      const currentTip = state.navigationFlow[navigationIndex];\n      void trackEvent('help_center_read_tip', {\n        name: currentTip,\n        unread_count: state.unreadTipsCount,\n      });\n\n      if (state.unreadTipsCount === state.navigationFlow.length) {\n        void trackEvent('tutorial_begin');\n      }\n\n      if ('done' === currentTip) {\n        void trackEvent('tutorial_complete');\n      }\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- avoid sending duplicate tracking events.\n  }, [navigationIndex]);\n\n  const contextValue = useMemo(\n    () => ({\n      state: {\n        ...state,\n        navigationIndex,\n      },\n      actions,\n    }),\n    [actions, state, navigationIndex]\n  );\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n}\n\nexport default HelpCenterProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Tip } from '../../types/configProvider';\n\nexport interface HelpCenterState {\n  isOpen: boolean;\n  isOpeningToTip: boolean;\n  navigationIndex: number;\n  navigationFlow: string[];\n  isLeftToRightTransition: boolean;\n  hasBottomNavigation: boolean;\n  isPrevDisabled: boolean;\n  isNextDisabled: boolean;\n  readTips: Record<string, boolean>;\n  readError: boolean;\n  unreadTipsCount: number;\n  isHydrated: boolean;\n  tips: Record<string, Tip>;\n  tipKeys: string[];\n}\n\nexport type HelpCenterActionArgument =\n  | Pick<HelpCenterState, 'readTips'>\n  | string\n  | undefined;\n\nexport interface HelpCenterActions<T> {\n  goToNext: () => T;\n  goToPrev: () => T;\n  goToMenu: () => T;\n  goToTip: (key: string) => T;\n  openToUnreadTip: (key: string) => T;\n  toggle: () => T;\n  close: () => T;\n  hydrateReadTipsSuccess: (payload: Pick<HelpCenterState, 'readTips'>) => T;\n  persistingReadTipsError: () => T;\n}\n\nexport interface HelpCenterContext {\n  state: HelpCenterState;\n  actions: HelpCenterActions<void>;\n}\n\nexport interface HelpCenterReducerContext {\n  state: HelpCenterState;\n  actions: HelpCenterActions<\n    (previous: HelpCenterState) => Partial<HelpCenterState>\n  >;\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/useHelpCenter/effects.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { HelpCenterState } from '../types';\nimport { DONE_TIP_ENTRY } from '../constants';\n\ndeclare const WEB_STORIES_DISABLE_QUICK_TIPS: 'true' | 'false' | undefined;\n\nconst isMenuIndex = (_previous: HelpCenterState, next: HelpCenterState) =>\n  next.navigationIndex < 0;\n\nconst isComingFromMenu = (previous: HelpCenterState, next: HelpCenterState) =>\n  previous.navigationIndex < 0 && next.navigationIndex >= 0;\n\nconst navigationFlowTips = (\n  _previous: HelpCenterState,\n  next: HelpCenterState\n) => {\n  return (next.navigationFlow || []).filter((key) =>\n    next.tipKeys.includes(key)\n  );\n};\n\nconst isInitialHydrate = (previous: HelpCenterState, next: HelpCenterState) =>\n  !previous.isHydrated && next.isHydrated;\n\nexport const resetNavigationIndexOnOpen = (\n  previous: HelpCenterState,\n  next: HelpCenterState\n) => {\n  const isOpening = !previous.isOpen && next.isOpen;\n  const isOpeningToTip = !previous.isOpeningToTip && next.isOpeningToTip;\n  const result = {\n    navigationIndex: isOpening && !isOpeningToTip ? -1 : next.navigationIndex,\n  };\n\n  return result;\n};\n\nexport const deriveBottomNavigation = (\n  previous: HelpCenterState,\n  next: HelpCenterState\n) => ({\n  hasBottomNavigation: !isMenuIndex(previous, next),\n});\n\nexport const deriveTransitionDirection = (\n  previous: HelpCenterState,\n  next: HelpCenterState\n) => ({\n  isLeftToRightTransition:\n    !isMenuIndex(previous, next) &&\n    next.navigationIndex - previous.navigationIndex > 0,\n});\n\nexport const deriveDisabledButtons = (\n  _previous: HelpCenterState,\n  next: HelpCenterState\n) => ({\n  isPrevDisabled: next.navigationIndex <= 0,\n  isNextDisabled: next.navigationIndex >= next.navigationFlow?.length - 1,\n});\n\nexport const deriveReadTip = (\n  previous: HelpCenterState,\n  next: HelpCenterState\n) => {\n  const readTipKey =\n    !isMenuIndex(previous, next) &&\n    navigationFlowTips(previous, next)?.[next.navigationIndex];\n\n  const readTips = readTipKey\n    ? {\n        ...next.readTips,\n        [readTipKey]: true,\n      }\n    : next.readTips;\n\n  return { readTips };\n};\n\nexport const createDynamicNavigationFlow = (\n  previous: HelpCenterState,\n  next: HelpCenterState\n) => {\n  if (!isComingFromMenu(previous, next)) {\n    return {};\n  }\n  const appendedTips = next.tipKeys\n    // Tips before current index\n    .slice(0, next.navigationIndex)\n    // Filter out read tips\n    .filter((tip) => !next.readTips[tip]);\n  return {\n    navigationFlow: [...next.tipKeys, ...appendedTips, DONE_TIP_ENTRY[0]],\n  };\n};\n\nexport function deriveUnreadTipsCount(\n  _previous: HelpCenterState,\n  next: HelpCenterState\n) {\n  return {\n    unreadTipsCount:\n      next.tipKeys.filter((tip) => !next.readTips[tip])?.length || 0,\n  };\n}\n\nexport function deriveAutoOpen(\n  previous: HelpCenterState,\n  next: HelpCenterState\n) {\n  if (\n    typeof WEB_STORIES_DISABLE_QUICK_TIPS !== 'undefined' &&\n    WEB_STORIES_DISABLE_QUICK_TIPS === 'true'\n  ) {\n    return {};\n  }\n  if (isInitialHydrate(previous, next)) {\n    const hasNewTips = previous.unreadTipsCount < next.unreadTipsCount;\n    return hasNewTips ? { isOpen: true } : {};\n  }\n  return {};\n}\n\n// If there are any unread tips, we respect users last open setting.\n// If all tips are read, we want the popup closed regardless of user setting.\nexport function deriveInitialOpen(persisted: Partial<HelpCenterState>) {\n  if (\n    typeof WEB_STORIES_DISABLE_QUICK_TIPS !== 'undefined' &&\n    WEB_STORIES_DISABLE_QUICK_TIPS === 'true'\n  ) {\n    return {};\n  }\n  const hasUnreadTips = Boolean(persisted?.unreadTipsCount);\n  return hasUnreadTips && persisted?.isOpen !== undefined\n    ? {\n        isOpen: persisted?.isOpen,\n      }\n    : {};\n}\n\nexport function deriveInitialUnreadTipsCount(\n  persisted: Partial<HelpCenterState>\n) {\n  return persisted?.unreadTipsCount\n    ? {\n        unreadTipsCount: persisted?.unreadTipsCount,\n      }\n    : {};\n}\n\nexport function resetIsOpeningToTip(\n  previous: HelpCenterState,\n  next: HelpCenterState\n) {\n  return {\n    isOpeningToTip: next.isOpeningToTip && !previous.isOpeningToTip,\n  };\n}\n\ntype StateEffect<P, N> = (previous: P, next: N) => Partial<N>;\n\n/**\n * Takes an array of effects and returns a composed function\n * that given next and previous state runs through each effect\n * and computes the resulting state.\n *\n * @param effects array of effects\n * @return (previous, next) => <object in shape of next>\n */\nexport function composeEffects<P, N>(effects: StateEffect<P, N>[]) {\n  return (previous: P, next: N): N =>\n    effects.reduce(\n      (effectedNext, effect) => ({\n        ...next,\n        ...effectedNext,\n        ...effect(previous, effectedNext),\n      }),\n      next\n    );\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/useHelpCenter/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from '../context';\nimport type { HelpCenterContext } from '../types';\n\nfunction useHelpCenter(): HelpCenterContext;\nfunction useHelpCenter<T>(\n  selector: (state: HelpCenterContext) => T | HelpCenterContext = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useHelpCenter;\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/useHelpCenter/test/effects.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { getInitialState } from '../../useHelpCenterReducer';\nimport { DONE_TIP_ENTRY, TIPS } from '../../constants';\nimport {\n  composeEffects,\n  createDynamicNavigationFlow,\n  deriveBottomNavigation,\n  deriveDisabledButtons,\n  deriveInitialOpen,\n  deriveInitialUnreadTipsCount,\n  deriveReadTip,\n  deriveTransitionDirection,\n  deriveUnreadTipsCount,\n  resetNavigationIndexOnOpen,\n  resetIsOpeningToTip,\n} from '../effects';\n\nconst BASE_NAVIGATION_FLOW = Object.keys(TIPS);\nconst TIP_KEYS_MAP = Object.fromEntries(\n  Object.keys(TIPS).map((key) => [key, true])\n);\nconst initialState = getInitialState({});\n\nconst mockState = (overrides = {}) => ({\n  ...initialState,\n  ...overrides,\n});\n\ndescribe('composeEffects', () => {\n  it('retains all properties from next state', () => {\n    type DummyEffect = {\n      someDerivedState: boolean;\n      prop1: boolean;\n      prop2: Record<string, unknown>;\n      prop3: string;\n    };\n    const emptyEffect = () => ({});\n    const nonEmptyEffect = () => ({ someDerivedState: true });\n    const overwritingEffect = () => ({ prop3: 'someOtherString' });\n\n    const effects = composeEffects<Partial<DummyEffect>, Partial<DummyEffect>>([\n      emptyEffect,\n      nonEmptyEffect,\n      overwritingEffect,\n    ]);\n\n    const previous = {};\n    const next = {\n      prop1: true,\n      prop2: {},\n      prop3: 'someString',\n    };\n\n    const effectedState = effects(previous, next);\n\n    const effectedStateKeys = Object.keys(effectedState);\n    const nextKeys = Object.keys(next);\n\n    expect(nextKeys.every((key) => effectedStateKeys.includes(key))).toBeTrue();\n  });\n\n  it('calls all effects sequentially', () => {\n    const previous = {};\n    const next = {};\n\n    const mockEffects = Array.from({ length: 10 }, () => jest.fn());\n    const effects = composeEffects(mockEffects);\n\n    effects(previous, next);\n\n    mockEffects.forEach((mockEffect, i) => {\n      expect(mockEffect).toHaveBeenCalledWith(previous, next);\n      mockEffects.slice(0, i).forEach((effect) => {\n        expect(mockEffect).toHaveBeenCalledAfter(effect);\n      });\n    });\n  });\n});\n\ndescribe('deriveInitialOpen', () => {\n  it('doesnt update anything if no persisted state', () => {\n    expect(deriveInitialOpen({})).toStrictEqual({});\n  });\n\n  it('doesnt update anything if there is no persisted unreadTipsCount', () => {\n    expect(deriveInitialOpen({ isOpen: true })).toStrictEqual({});\n    expect(deriveInitialOpen({ isOpen: false })).toStrictEqual({});\n  });\n\n  it('doesnt update anything if there is no persisted isOpen', () => {\n    expect(deriveInitialOpen({ unreadTipsCount: 0 })).toStrictEqual({});\n    expect(deriveInitialOpen({ unreadTipsCount: 1 })).toStrictEqual({});\n  });\n\n  it('doesnt update anything if there are no unread tips', () => {\n    expect(\n      deriveInitialOpen({ unreadTipsCount: 0, isOpen: true })\n    ).toStrictEqual({});\n    expect(\n      deriveInitialOpen({ unreadTipsCount: 0, isOpen: false })\n    ).toStrictEqual({});\n  });\n\n  it('respects persisted isOpen if there are unread tips', () => {\n    expect(\n      deriveInitialOpen({ unreadTipsCount: 1, isOpen: true })\n    ).toStrictEqual({ isOpen: true });\n\n    expect(\n      deriveInitialOpen({ unreadTipsCount: 1, isOpen: false })\n    ).toStrictEqual({ isOpen: false });\n  });\n});\n\ndescribe('deriveInitialUnreadTipsCount', () => {\n  it('doesnt update anything if no persisted state', () => {\n    expect(deriveInitialUnreadTipsCount({})).toStrictEqual({});\n  });\n\n  it('updates unreadTipsCount if its persisted', () => {\n    expect(deriveInitialUnreadTipsCount({ unreadTipsCount: 2 })).toStrictEqual({\n      unreadTipsCount: 2,\n    });\n  });\n});\n\ndescribe('deriveUnreadTipsCount', () => {\n  it('effects proper state partial', () => {\n    const statePartial = deriveUnreadTipsCount(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual(['unreadTipsCount']);\n  });\n\n  it('counts 0 if all tips read', () => {\n    const { unreadTipsCount } = deriveUnreadTipsCount(\n      mockState(),\n      mockState({\n        readTips: TIP_KEYS_MAP,\n      })\n    );\n    expect(unreadTipsCount).toBe(0);\n  });\n\n  it('ignores non-tip keys', () => {\n    const { unreadTipsCount } = deriveUnreadTipsCount(\n      mockState(),\n      mockState({\n        readTips: {\n          notATip: true,\n        },\n      })\n    );\n    expect(unreadTipsCount).toBe(Object.keys(TIP_KEYS_MAP).length);\n  });\n\n  it('counts length of unread tip keys', () => {\n    const readTips = {\n      [BASE_NAVIGATION_FLOW[0]]: true,\n      [BASE_NAVIGATION_FLOW[1]]: true,\n      [BASE_NAVIGATION_FLOW[2]]: true,\n    };\n    const { unreadTipsCount } = deriveUnreadTipsCount(\n      mockState(),\n      mockState({\n        readTips,\n      })\n    );\n    expect(unreadTipsCount).toBe(\n      Object.keys(TIP_KEYS_MAP).length - Object.keys(readTips).length\n    );\n  });\n});\n\ndescribe('resetNavigationIndexOnOpen', () => {\n  it('effects proper state partial', () => {\n    const statePartial = resetNavigationIndexOnOpen(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual(['navigationIndex']);\n  });\n\n  it('resets the navigation index to the main menu when opening', () => {\n    const previousState = mockState({\n      isOpen: false,\n      navigationIndex: 4,\n    });\n    const nextState = mockState({\n      isOpen: true,\n      navigationIndex: 4,\n    });\n    const { navigationIndex } = resetNavigationIndexOnOpen(\n      previousState,\n      nextState\n    );\n    expect(navigationIndex).toBe(-1);\n  });\n\n  it('retains navigation index when staying open between state transitions', () => {\n    const previousState = mockState({\n      isOpen: true,\n      navigationIndex: 4,\n    });\n    const nextState = mockState({\n      isOpen: true,\n      navigationIndex: 4,\n    });\n    const { navigationIndex } = resetNavigationIndexOnOpen(\n      previousState,\n      nextState\n    );\n    expect(navigationIndex).toBe(4);\n  });\n});\n\ndescribe('deriveBottomNavigation', () => {\n  it('effects proper state partial', () => {\n    const statePartial = deriveBottomNavigation(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual(['hasBottomNavigation']);\n  });\n\n  it('sets hasBottomNavigation to true if navigationIndex is not on menu index', () => {\n    const previousState = mockState({\n      navigationIndex: -1,\n    });\n    const nextState = mockState({\n      navigationIndex: 0,\n    });\n    const { hasBottomNavigation } = deriveBottomNavigation(\n      previousState,\n      nextState\n    );\n    expect(hasBottomNavigation).toBeTrue();\n  });\n\n  it('sets hasBottomNavigation to false if navigationIndex is on menu index', () => {\n    const previousState = mockState({\n      navigationIndex: 4,\n    });\n    const nextState = mockState({\n      navigationIndex: -1,\n    });\n    const { hasBottomNavigation } = deriveBottomNavigation(\n      previousState,\n      nextState\n    );\n    expect(hasBottomNavigation).toBeFalse();\n  });\n});\n\ndescribe('deriveTransitionDirection', () => {\n  it('effects proper state partial', () => {\n    const statePartial = deriveTransitionDirection(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual([\n      'isLeftToRightTransition',\n    ]);\n  });\n\n  it('sets isLeftToRightTransition to true if navigationIndex is increasing', () => {\n    const previousState = mockState({\n      navigationIndex: 0,\n    });\n    const nextState = mockState({\n      navigationIndex: 1,\n    });\n    const { isLeftToRightTransition } = deriveTransitionDirection(\n      previousState,\n      nextState\n    );\n    expect(isLeftToRightTransition).toBeTrue();\n  });\n\n  it('sets isLeftToRightTransition to false if navigationIndex is decreasing', () => {\n    const previousState = mockState({\n      navigationIndex: 2,\n    });\n    const nextState = mockState({\n      navigationIndex: 1,\n    });\n    const { isLeftToRightTransition } = deriveTransitionDirection(\n      previousState,\n      nextState\n    );\n    expect(isLeftToRightTransition).toBeFalse();\n  });\n});\n\ndescribe('deriveDisabledButtons', () => {\n  it('effects proper state partial', () => {\n    const statePartial = deriveDisabledButtons(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual([\n      'isPrevDisabled',\n      'isNextDisabled',\n    ]);\n  });\n\n  it('sets isPrevDisabled to true if navigationIndex becomes 0', () => {\n    const previousState = mockState({ navigationIndex: 5 });\n    const nextState = mockState({ navigationIndex: 0 });\n    const { isPrevDisabled } = deriveDisabledButtons(previousState, nextState);\n    expect(isPrevDisabled).toBeTrue();\n  });\n\n  it('sets isPrevDisabled to false if navigationIndex is greater than 0', () => {\n    const previousState = mockState({ navigationIndex: 0 });\n    const nextState = mockState({ navigationIndex: 5 });\n    const { isPrevDisabled } = deriveDisabledButtons(previousState, nextState);\n    expect(isPrevDisabled).toBeFalse();\n  });\n\n  it('sets isNextDisabled to true if navigationIndex is on last index in navigation flow', () => {\n    const previousState = mockState({\n      navigationIndex: 0,\n      navigationFlow: ['tip_1', 'tip_2'],\n    });\n    const nextState = mockState({\n      navigationIndex: 1,\n      navigationFlow: ['tip_1', 'tip_2'],\n    });\n    const { isNextDisabled } = deriveDisabledButtons(previousState, nextState);\n    expect(isNextDisabled).toBeTrue();\n  });\n\n  it('sets isNextDisabled to false if navigationIndex is not on last index in navigation flow', () => {\n    const previousState = mockState({\n      navigationIndex: 2,\n      navigationFlow: ['tip_1', 'tip_2', 'tip_3'],\n    });\n    const nextState = mockState({\n      navigationIndex: 1,\n      navigationFlow: ['tip_1', 'tip_2', 'tip_3'],\n    });\n    const { isNextDisabled } = deriveDisabledButtons(previousState, nextState);\n    expect(isNextDisabled).toBeFalse();\n  });\n});\n\ndescribe('deriveReadTip', () => {\n  it('effects proper state partial', () => {\n    const statePartial = deriveReadTip(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual(['readTips']);\n  });\n\n  it('sets a tip to read if the navigation index is not on the menu or done index', () => {\n    const navigationFlow = Object.keys(TIPS);\n    const previousState = mockState({\n      navigationIndex: -1,\n      navigationFlow: navigationFlow,\n    });\n    const nextState = mockState({\n      navigationIndex: 0,\n      navigationFlow: navigationFlow,\n    });\n    const { readTips } = deriveReadTip(previousState, nextState);\n    expect(readTips[navigationFlow[0]]).toBeTrue();\n  });\n});\n\ndescribe('createDynamicNavigationFlow', () => {\n  it('effects proper state partial', () => {\n    // doesn't alter any properties if not coming from menu\n    let statePartial = createDynamicNavigationFlow(mockState(), mockState());\n    expect(Object.keys(statePartial)).toStrictEqual([]);\n\n    // alters navigationFlow if coming from menu\n    statePartial = createDynamicNavigationFlow(\n      mockState({\n        navigationIndex: -1,\n      }),\n      mockState({\n        navigationIndex: 2,\n      })\n    );\n    expect(Object.keys(statePartial)).toStrictEqual(['navigationFlow']);\n  });\n\n  it('should do nothing if not navigating from the main menu', () => {\n    // case where we stay on menu\n    const onMenuState = mockState({ navigationIndex: -1 });\n    expect(createDynamicNavigationFlow(onMenuState, onMenuState)).toStrictEqual(\n      {}\n    );\n    // case where we navigate to menu\n    const onTipState = mockState({ navigationIndex: 0 });\n    expect(createDynamicNavigationFlow(onTipState, onMenuState)).toStrictEqual(\n      {}\n    );\n    // case where we navigate between tips\n    const onAnotherTipState = mockState({ navigationIndex: 1 });\n    expect(\n      createDynamicNavigationFlow(onTipState, onAnotherTipState)\n    ).toStrictEqual({});\n  });\n\n  it('on navigate from menu, should append unread tips before navigation index to the end of the navigation flow before done tip', () => {\n    const onMenuState = mockState({ navigationIndex: -1 });\n    Object.keys(TIPS).forEach((tip) => {\n      const tipIndex = BASE_NAVIGATION_FLOW.findIndex((v) => v === tip);\n      const tipsBeforeCurrent = BASE_NAVIGATION_FLOW.slice(0, tipIndex);\n      expect(\n        createDynamicNavigationFlow(\n          onMenuState,\n          mockState({ navigationIndex: tipIndex })\n        )\n      ).toStrictEqual({\n        navigationFlow: [\n          ...BASE_NAVIGATION_FLOW,\n          ...tipsBeforeCurrent,\n          DONE_TIP_ENTRY[0],\n        ],\n      });\n    });\n  });\n});\n\ndescribe('resetIsOpeningToTip', () => {\n  it('only sets the flag to true if the state is being toggled', () => {\n    let previousState = mockState({ isOpeningToTip: false });\n    let nextState = mockState({ isOpeningToTip: true });\n    const testTrue = resetIsOpeningToTip(previousState, nextState);\n    expect(testTrue.isOpeningToTip).toBeTrue();\n\n    previousState = mockState({ isOpeningToTip: true });\n    const testBothTrue = resetIsOpeningToTip(previousState, nextState);\n    expect(testBothTrue.isOpeningToTip).toBeFalse();\n\n    previousState = mockState({ isOpeningToTip: false });\n    nextState = mockState({ isOpeningToTip: false });\n    const testBothFalse = resetIsOpeningToTip(previousState, nextState);\n    expect(testBothFalse.isOpeningToTip).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/useHelpCenter/test/useHelpCenter.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport CurrentUserProviderContext from '../../../currentUser/context';\nimport { DONE_TIP_ENTRY } from '../../constants';\nimport useHelpCenter from '..';\nimport HelpCenterProvider from '../../provider';\nimport type { User } from '../../../../types';\n\nfunction setup() {\n  const currentUser: User = {\n    id: 0,\n    mediaOptimization: false,\n    onboarding: {},\n    trackingOptin: false,\n  };\n  const currentUserPromise = jest.fn(() => Promise.resolve());\n  const contextValue = {\n    state: {\n      currentUser,\n    },\n    actions: {\n      updateCurrentUser: currentUserPromise,\n      toggleWebStoriesMediaOptimization: jest.fn(),\n    },\n  };\n\n  const wrapper = ({ children }: PropsWithChildren<undefined>) => (\n    <CurrentUserProviderContext.Provider value={contextValue}>\n      <HelpCenterProvider>{children}</HelpCenterProvider>\n    </CurrentUserProviderContext.Provider>\n  );\n\n  return renderHook(() => useHelpCenter(), { wrapper });\n}\n\ndescribe('useHelpCenter', () => {\n  it('always returns the same actions by reference', () => {\n    const { result } = setup();\n    const initialActionsReference = result.current.actions;\n    act(() => initialActionsReference.goToNext());\n    expect(result.current.actions).toBe(initialActionsReference);\n  });\n\n  describe('goToNext', () => {\n    it('doesnt increment out of navigation flow bounds', () => {\n      const { result } = setup();\n\n      for (let i = 0; i < result.current.state.navigationFlow.length + 5; i++) {\n        act(() => result.current.actions.goToNext());\n        const expected =\n          i < result.current.state.navigationFlow.length\n            ? i\n            : result.current.state.navigationFlow.length - 1;\n        expect(result.current.state.navigationIndex).toBe(expected);\n      }\n    });\n\n    it('updates the read status of the tip', () => {\n      const { result } = setup();\n      const expected: Record<string, boolean> = {};\n      for (let i = 0; i < result.current.state.navigationFlow.length; i++) {\n        act(() => result.current.actions.goToNext());\n        const expectedKey = result.current.state.navigationFlow[i];\n        if (expectedKey !== DONE_TIP_ENTRY[0]) {\n          expected[expectedKey] = true;\n        }\n        expect(result.current.state.readTips).toStrictEqual(expected);\n      }\n    });\n  });\n\n  describe('goToPrev', () => {\n    it('doesnt decrement out of navigation flow bounds', () => {\n      const { result } = setup();\n      // navigate to last tip in navigation flow\n      for (let i = 0; i < result.current.state.navigationFlow.length; ++i) {\n        act(() => result.current.actions.goToNext());\n      }\n\n      // navigate way back past first tip\n      for (let i = 0; i < result.current.state.navigationFlow.length + 5; i++) {\n        const lastIndex = result.current.state.navigationFlow.length - 1;\n        const currentIndex = lastIndex - i;\n        const expected = currentIndex > 0 ? currentIndex : 0;\n        expect(result.current.state.navigationIndex).toBe(expected);\n        act(() => result.current.actions.goToPrev());\n      }\n    });\n\n    it('updates the read status of the tip', () => {\n      const { result } = setup();\n\n      // go to the last tip\n      const lastTipIndex = result.current.state.navigationFlow.length - 1;\n      const lastTip = result.current.state.navigationFlow[lastTipIndex];\n      act(() => result.current.actions.goToTip(lastTip));\n\n      // that tip should be read\n      const expected = { [lastTip]: true };\n      expect(result.current.state.readTips).toStrictEqual(expected);\n\n      // go through the list backwards\n      for (let i = lastTipIndex; i >= 0; i--) {\n        const expectedKey = result.current.state.navigationFlow[i];\n        expected[expectedKey] = true;\n        expect(result.current.state.readTips).toStrictEqual(expected);\n        act(() => result.current.actions.goToPrev());\n      }\n    });\n  });\n\n  describe('goToMenu', () => {\n    it('always sets the navigationIndex to -1', () => {\n      const { result } = setup();\n      for (let i = 0; i < 3; i++) {\n        act(() => result.current.actions.goToNext());\n      }\n      act(() => result.current.actions.goToMenu());\n      expect(result.current.state.navigationIndex).toBe(-1);\n    });\n  });\n\n  describe('goToTip', () => {\n    it('sets navigationIndex to -1 (main menu) if key isnt in navigationFlow', () => {\n      const { result } = setup();\n      // navigate away from main menu\n      act(() =>\n        result.current.actions.goToTip(\n          String(result.current.state.navigationFlow.length - 1)\n        )\n      );\n      // navigate to unspecified key\n      act(() => result.current.actions.goToTip('this isnt a tip key'));\n      expect(result.current.state.navigationIndex).toBe(-1);\n    });\n\n    it('sets navigationIndex to index of key in navigation flow', () => {\n      const { result } = setup();\n      for (let i = 0; i < result.current.state.navigationFlow.length - 1; i++) {\n        act(() =>\n          result.current.actions.goToTip(result.current.state.navigationFlow[i])\n        );\n        expect(result.current.state.navigationIndex).toBe(i);\n      }\n    });\n  });\n\n  describe('openToUnreadTip', () => {\n    it('should only open the tip if it is not already read', () => {\n      const { result } = setup();\n      act(() => {\n        result.current.actions.goToTip('cropSelectedElements');\n        result.current.actions.goToMenu();\n        result.current.actions.close();\n      });\n\n      expect(result.current.state.navigationIndex).toBe(-1);\n      expect(result.current.state.isOpen).toBeFalse();\n\n      act(() => result.current.actions.openToUnreadTip('cropSelectedElements'));\n      expect(result.current.state.navigationIndex).toBe(-1);\n      expect(result.current.state.isOpen).toBeFalse();\n\n      act(() => result.current.actions.openToUnreadTip('addBackgroundMedia'));\n      expect(result.current.state.navigationIndex).toBe(\n        result.current.state.navigationFlow.findIndex(\n          (v) => v === 'addBackgroundMedia'\n        )\n      );\n      expect(result.current.state.isOpen).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/helpCenter/useHelpCenterReducer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReducer, useMemo } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { clamp } from '@googleforcreators/units';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\nimport type { Tip } from '../../types/configProvider';\nimport {\n  composeEffects,\n  createDynamicNavigationFlow,\n  deriveBottomNavigation,\n  deriveDisabledButtons,\n  deriveReadTip,\n  deriveTransitionDirection,\n  deriveUnreadTipsCount,\n  resetNavigationIndexOnOpen,\n  deriveAutoOpen,\n  deriveInitialOpen,\n  deriveInitialUnreadTipsCount,\n  resetIsOpeningToTip,\n} from './useHelpCenter/effects';\nimport type {\n  HelpCenterActions,\n  HelpCenterReducerContext,\n  HelpCenterState,\n} from './types';\nimport { TIPS } from './constants';\n\n/**\n * Performs any state updates that result from\n * inspection of previous or next state\n *\n * @param {*} previous - previous state\n * @param {*} next - next state\n * @return {*} partial of state\n */\nexport const deriveState = composeEffects(\n  // Order matters here as effects run\n  // sequentially and alter next state\n  // one after the other.\n  [\n    resetNavigationIndexOnOpen,\n    createDynamicNavigationFlow,\n    deriveBottomNavigation,\n    deriveTransitionDirection,\n    deriveDisabledButtons,\n    deriveReadTip,\n    deriveUnreadTipsCount,\n    deriveAutoOpen,\n    resetIsOpeningToTip,\n  ]\n);\n\nconst reducer = (\n  { state, actions }: HelpCenterReducerContext,\n  action: (state: HelpCenterState) => Partial<HelpCenterState>\n): HelpCenterReducerContext => {\n  const nextState = { ...state, ...action(state) };\n  return {\n    state: deriveState(state, nextState),\n    actions,\n  };\n};\n\nconst deriveInitialState = composeEffects<\n  Partial<HelpCenterState>,\n  HelpCenterState\n>([deriveInitialOpen, deriveInitialUnreadTipsCount]);\n\nconst persisted: Partial<HelpCenterState> = localStore.getItemByKey(\n  LOCAL_STORAGE_PREFIX.HELP_CENTER\n) as Partial<HelpCenterState>;\n\nexport const getInitialState = (\n  additionalTips?: Record<string, Tip>\n): HelpCenterState => ({\n  isOpen: false,\n  isOpeningToTip: false,\n  navigationIndex: -1,\n  navigationFlow: Object.keys({\n    ...TIPS,\n    ...additionalTips,\n  }), // Is updated using createDynamicNavigationFlow effect.\n  isLeftToRightTransition: true,\n  hasBottomNavigation: false,\n  isPrevDisabled: true,\n  isNextDisabled: false,\n  readTips: {},\n  readError: false,\n  unreadTipsCount: persisted?.unreadTipsCount ?? 0,\n  isHydrated: false,\n  tips: { ...TIPS, ...additionalTips },\n  tipKeys: Object.keys({ ...TIPS, ...additionalTips }),\n});\n\nexport const getInitial = (\n  additionalTips?: Record<string, Tip>\n): HelpCenterReducerContext => ({\n  state: deriveInitialState(persisted, getInitialState(additionalTips)),\n  // All actions are in the form: externalArgs -> state -> newStatePartial\n  //\n  // Actions should only update the part of state they directly effect.\n  // If there are state updates from deriving a value off of prevState\n  // or nextState, place them in `deriveState(previous, next)` above.\n  actions: {\n    goToNext:\n      () =>\n      ({ navigationIndex, navigationFlow }: HelpCenterState) => ({\n        navigationIndex: clamp(navigationIndex + 1, {\n          MIN: 0,\n          MAX: navigationFlow.length - 1,\n        }),\n      }),\n    goToPrev:\n      () =>\n      ({ navigationIndex, navigationFlow }: HelpCenterState) => ({\n        navigationIndex: clamp(navigationIndex - 1, {\n          MIN: 0,\n          MAX: navigationFlow.length - 1,\n        }),\n      }),\n    goToMenu: () => () => ({ navigationIndex: -1 }),\n    goToTip:\n      (key: string) =>\n      ({ navigationFlow }: HelpCenterState) => ({\n        navigationIndex: navigationFlow.findIndex((v) => v === key),\n      }),\n    openToUnreadTip:\n      (key: string) =>\n      ({ navigationFlow, readTips }: HelpCenterState) =>\n        !readTips[key]\n          ? {\n              isOpen: true,\n              isOpeningToTip: true,\n              navigationIndex: navigationFlow.findIndex((v) => v === key),\n            }\n          : {},\n    toggle:\n      () =>\n      ({ isOpen }: HelpCenterState) => {\n        void trackEvent('help_center_toggled', {\n          status: isOpen ? 'closed' : 'open',\n        });\n        return { isOpen: !isOpen };\n      },\n    close:\n      () =>\n      ({ isOpen }: HelpCenterState) => {\n        if (isOpen) {\n          void trackEvent('help_center_toggled', {\n            status: 'closed',\n          });\n        }\n        return { isOpen: false };\n      },\n    hydrateReadTipsSuccess:\n      (payload: Pick<HelpCenterState, 'readTips'>) =>\n      (state: HelpCenterState) => ({\n        readTips: {\n          ...payload?.readTips,\n          ...state.readTips,\n        },\n        isHydrated: true,\n      }),\n    persistingReadTipsError: () => () => ({\n      readError: true,\n    }),\n  },\n});\n\nfunction useHelpCenterReducer() {\n  const { additionalTips = {} } = useConfig();\n  const [store, dispatch] = useReducer(reducer, getInitial(additionalTips));\n\n  // Wrap all actions in dispatch\n  const actions: HelpCenterActions<void> = useMemo(\n    () => ({\n      goToNext: () => dispatch(store.actions.goToNext()),\n      goToPrev: () => dispatch(store.actions.goToPrev()),\n      goToMenu: () => dispatch(store.actions.goToMenu()),\n      goToTip: (payload: string) => dispatch(store.actions.goToTip(payload)),\n      openToUnreadTip: (payload: string) =>\n        dispatch(store.actions.openToUnreadTip(payload)),\n      toggle: () => dispatch(store.actions.toggle()),\n      close: () => dispatch(store.actions.close()),\n      hydrateReadTipsSuccess: (payload: Pick<HelpCenterState, 'readTips'>) =>\n        dispatch(store.actions.hydrateReadTipsSuccess(payload)),\n      persistingReadTipsError: () =>\n        dispatch(store.actions.persistingReadTipsError()),\n    }),\n    [store.actions]\n  );\n\n  return { state: store.state, actions };\n}\n\nexport default useHelpCenterReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { HighlightProviderState } from '../../types/highlightsProvider';\n\nexport default createContext<HighlightProviderState>(\n  {} as HighlightProviderState\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nexport { default as useHighlights } from './useHighlights';\nexport { default as HighlightsProvider } from './provider';\nexport { HighlightType as states } from './states';\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/provider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../story/useStory';\nimport type {\n  setHighlightProps,\n  selectElementProps,\n  HighlightState,\n  Highlight,\n  HighlightsState,\n} from '../../types/highlightsProvider';\nimport Context from './context';\nimport { type HighlightType, STATES } from './states';\n\nfunction HighlightsProvider({ children }: PropsWithChildren<unknown>) {\n  const [highlighted, setHighlighted] = useState<HighlightsState>({});\n  const {\n    actions: { setSelectedElementsById, setCurrentPage },\n  } = useStory();\n\n  const selectElement = useCallback(\n    ({ elementId, elements, pageId }: selectElementProps) => {\n      if (pageId) {\n        setCurrentPage({ pageId });\n      }\n      if (elements?.length) {\n        const elementIds = elements.map((element) => element.id);\n        setSelectedElementsById({ elementIds });\n      } else if (elementId) {\n        const elementIds = [elementId];\n        setSelectedElementsById({ elementIds });\n      }\n    },\n    [setCurrentPage, setSelectedElementsById]\n  );\n\n  const setHighlights = useCallback(\n    ({ elements, elementId, pageId, highlight }: setHighlightProps) => {\n      if (elements || elementId || pageId) {\n        selectElement({ elements, elementId, pageId });\n      }\n\n      if (highlight && STATES[highlight]) {\n        const { tab, section, ...highlightState }: Highlight =\n          STATES[highlight];\n        setHighlighted({\n          [highlight]: { ...highlightState, showEffect: true },\n          tab,\n          section,\n        });\n      }\n    },\n    [selectElement]\n  );\n\n  const onFocusOut = useCallback(() => setHighlighted({}), [setHighlighted]);\n\n  const cancelEffect = useCallback(\n    (highlight: HighlightType) =>\n      setHighlighted((state: HighlightState) => ({\n        ...state,\n        [highlight]: { ...state[highlight], showEffect: false },\n      })),\n    []\n  );\n\n  const contextValue = useMemo(\n    () => ({\n      setHighlights,\n      onFocusOut,\n      cancelEffect,\n      ...highlighted,\n    }),\n    [cancelEffect, onFocusOut, setHighlights, highlighted]\n  );\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n}\n\nexport default HighlightsProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/states.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { STYLE_PANE_IDS } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  INSERT,\n  DOCUMENT,\n  STYLE as STYLE_SIDEBAR,\n} from '../../components/sidebar/constants';\nimport { PANE_IDS } from '../../components/library/paneIds';\nimport type { HighlightState } from '../../types/highlightsProvider';\n\nexport enum HighlightType {\n  StoryTitle = 'STORY_TITLE',\n  ElementToolbarToggle = 'ELEMENT_TOOLBAR_TOGGLE',\n\n  // Sidebar tabs\n  StylePane = 'STYLE_PANE',\n\n  // STYLE\n  Animation = 'ANIMATION',\n  AssistiveText = 'ASSISTIVE_TEXT',\n  Captions = 'Captions',\n  Excerpt = 'EXCERPT',\n  Link = 'LINK',\n  PageBackground = 'PAGE_BACKGROUND',\n  Poster = 'POSTER',\n  PublisherLogo = 'PUBLISHER_LOGO',\n  VideoA11yPoster = 'VIDEO_A11Y_POSTER',\n  Style = 'STYLE',\n  Font = 'FONT',\n  TextColor = 'TEXT_COLOR',\n\n  // LIBRARY\n  Media = 'MEDIA',\n  Media3p = 'MEDIA3P',\n  TextSet = 'TEXT',\n  PageTemplates = 'PAGE_TEMPLATES',\n\n  // DOCUMENT\n  PageBackgroundAudio = 'PAGE_BACKGROUND_AUDIO',\n}\n\nexport const STATES: HighlightState = {\n  [HighlightType.StoryTitle]: {\n    focus: true,\n  },\n\n  [HighlightType.ElementToolbarToggle]: {\n    focus: true,\n  },\n\n  // Sidebar tabs\n  [HighlightType.StylePane]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n\n  [HighlightType.Poster]: {\n    focus: true,\n    tab: DOCUMENT,\n  },\n  [HighlightType.PublisherLogo]: {\n    focus: true,\n    tab: DOCUMENT,\n  },\n  [HighlightType.Excerpt]: {\n    focus: true,\n    tab: DOCUMENT,\n  },\n  [HighlightType.PageBackgroundAudio]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n  },\n  [HighlightType.Captions]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.AssistiveText]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.PageBackground]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.Animation]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Animation,\n  },\n  [HighlightType.Font]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.Link]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Link,\n  },\n  [HighlightType.VideoA11yPoster]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.Style]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n  [HighlightType.TextColor]: {\n    focus: true,\n    tab: STYLE_SIDEBAR,\n    section: STYLE_PANE_IDS.Selection,\n  },\n\n  // Library\n  [HighlightType.Media]: {\n    focus: true,\n    tab: INSERT,\n    section: PANE_IDS.Media,\n  },\n  [HighlightType.Media3p]: {\n    focus: true,\n    tab: INSERT,\n    section: PANE_IDS.Media3p,\n  },\n  [HighlightType.TextSet]: {\n    focus: true,\n    tab: INSERT,\n    section: PANE_IDS.Text,\n  },\n  [HighlightType.PageTemplates]: {\n    focus: true,\n    tab: INSERT,\n    section: PANE_IDS.PageTemplates,\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { rgba } from 'polished';\nimport { css, keyframes } from 'styled-components';\nimport {\n  theme as dsTheme,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\nconst flash = keyframes`\n  50% {\n    background-color: ${rgba(dsTheme.colors.standard.white, 0.3)};\n  }\n`;\n\nconst FLASH = css`\n  background-color: ${rgba(dsTheme.colors.standard.white, 0)};\n  animation: ${flash} 0.3s ease-in-out 2;\n`;\n\nconst OUTLINE = css`\n  ${themeHelpers.focusCSS};\n`;\n\nconst styles = {\n  OUTLINE,\n  FLASH,\n};\nexport default styles;\n"
  },
  {
    "path": "packages/story-editor/src/app/highlights/useHighlights.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { HighlightProviderState } from '../../types/highlightsProvider';\nimport Context from './context';\n\nfunction useHighlights(): HighlightProviderState;\nfunction useHighlights<T>(selector: (state: HighlightProviderState) => T): T;\nfunction useHighlights<T>(\n  selector: (\n    state: HighlightProviderState\n  ) => T | HighlightProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\nexport default useHighlights;\n"
  },
  {
    "path": "packages/story-editor/src/app/history/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\nimport type { Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { HistoryProviderState } from '../../types';\n\nexport default createContext<HistoryProviderState>({\n  state: {\n    currentEntry: {\n      selection: [],\n      capabilities: {},\n      story: {} as Story,\n      pages: [],\n      current: null,\n    },\n    hasNewChanges: false,\n    requestedState: null,\n    canUndo: false,\n    canRedo: false,\n    versionNumber: 0,\n  },\n  actions: {\n    stateToHistory: () => null,\n    clearHistory: () => null,\n    resetNewChanges: () => null,\n    undo: () => false,\n    redo: () => false,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/history/historyProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport { useGlobalKeyDownEffect } from '@googleforcreators/design-system';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport usePreventWindowUnload from '../../utils/usePreventWindowUnload';\nimport useHistoryReducer from './useHistoryReducer';\nimport Context from './context';\n\nfunction HistoryProvider({\n  children,\n  size = 50,\n}: PropsWithChildren<{ size?: number }>) {\n  const {\n    requestedState,\n    stateToHistory,\n    clearHistory,\n    currentEntry,\n    offset,\n    historyLength,\n    undo,\n    redo,\n    versionNumber,\n  } = useHistoryReducer(size);\n\n  const [hasNewChanges, setHasNewChanges] = useState(false);\n  const setPreventUnload = usePreventWindowUnload();\n  // The version number for the initially loaded (saved) state is 1.\n  const savedVersionNumberRef = useRef(1);\n\n  useEffect(() => {\n    setPreventUnload('history', hasNewChanges);\n    return () => setPreventUnload('history', false);\n  }, [setPreventUnload, hasNewChanges]);\n\n  useEffect(() => {\n    setHasNewChanges(versionNumber !== savedVersionNumberRef.current);\n  }, [versionNumber]);\n\n  const resetNewChanges = useCallback(() => {\n    // When new changes are saved, let's track which version was saved.\n    savedVersionNumberRef.current = versionNumber;\n    setHasNewChanges(false);\n  }, [versionNumber]);\n\n  const state = {\n    state: {\n      currentEntry,\n      hasNewChanges,\n      requestedState,\n      canUndo: offset < historyLength - 1,\n      canRedo: offset > 0,\n      versionNumber,\n    },\n    actions: {\n      stateToHistory,\n      clearHistory,\n      resetNewChanges,\n      undo,\n      redo,\n    },\n  };\n\n  useGlobalKeyDownEffect({ key: 'undo', dialog: true }, () => undo(), [undo]);\n  useGlobalKeyDownEffect({ key: 'redo', dialog: true }, () => redo(), [redo]);\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nexport default HistoryProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/history/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as HistoryProvider } from './historyProvider';\nexport { default as HistoryContext } from './context';\nexport { default as useHistory } from './useHistory';\n"
  },
  {
    "path": "packages/story-editor/src/app/history/karma/history.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma/fixture';\nimport { useHistory } from '..';\n\ndescribe('CUJ: Creator can View and Modify Document Settings: Navigating without changes', () => {\n  let fixture;\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should not have new history changes when switching tabs without changes', async () => {\n    // Click on the shapes tab.\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    // Click on the document tab.\n    await fixture.events.click(fixture.editor.sidebar.documentTab);\n    // Wait to ensure any processes (in case of bugs) would be finished.\n    await fixture.events.sleep(500);\n\n    const {\n      state: { hasNewChanges, canUndo, canRedo },\n    } = await fixture.renderHook(() => useHistory());\n\n    expect(hasNewChanges).toBeFalse();\n    expect(canUndo).toBeFalse();\n    expect(canRedo).toBeFalse();\n\n    await fixture.snapshot('No new history changes');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/history/reducer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type {\n  HistoryReducerState,\n  ReducerProps,\n  HistoryEntry,\n} from '../../types/historyProvider';\n\nexport enum ActionType {\n  SetCurrentState = 'set_state',\n  ClearHistory = 'clear',\n  Replay = 'replay',\n}\n\nexport const EMPTY_STATE = {\n  entries: [],\n  offset: 0,\n  requestedState: null,\n  versionNumber: 0,\n};\n\nconst reducer =\n  (size: number) =>\n  (\n    state: HistoryReducerState,\n    { type, payload }: ReducerProps\n  ): HistoryReducerState | never => {\n    const currentEntry = state.entries[state.offset];\n    switch (type) {\n      case ActionType.SetCurrentState:\n        // First check if everything in payload matches the current `requestedState`,\n        // if so, update `offset` to match the state in entries and clear `requestedState`\n        // and of course leave entries unchanged.\n        if (state.requestedState) {\n          const isReplay = Object.keys(state.requestedState).every(\n            (key) =>\n              // TS complains about this potentially being `null` despite of the check above.\n              state.requestedState &&\n              state.requestedState[key as keyof HistoryEntry] ===\n                payload[key as keyof HistoryEntry]\n          );\n\n          if (isReplay) {\n            const offset = state.entries.indexOf(state.requestedState);\n            // If a page has changed and it was not an added page, and if the page is about to change with replay,\n            // Ensure the user stays on the page where the latest change happened.\n            if (\n              currentEntry.pages !== state.requestedState.pages &&\n              currentEntry.pages.length === state.requestedState.pages.length &&\n              currentEntry.current !== state.requestedState.current\n            ) {\n              const changedPage = currentEntry.pages.filter((page, index) => {\n                return (\n                  state.requestedState &&\n                  page !== state.requestedState.pages[index]\n                );\n              });\n              // If a changed page was found.\n              if (changedPage.length === 1) {\n                // Ensure we stay on the changed page by overriding the previously saved current page.\n                const current = changedPage[0].id;\n                const requestedState = { ...state.requestedState, current };\n                return {\n                  ...state,\n                  offset,\n                  requestedState,\n                };\n              }\n            }\n            return {\n              ...state,\n              offset,\n              requestedState: null,\n            };\n          }\n        }\n\n        // If not, trim `entries` from `offset` (basically destroy all undone states),\n        // add new entry but limit entire storage to `size`\n        // and clear `offset` and `requestedState`.\n        return {\n          entries: [payload, ...state.entries.slice(state.offset)].slice(\n            0,\n            size\n          ),\n          versionNumber: state.versionNumber + 1,\n          offset: 0,\n          requestedState: null,\n        };\n\n      case ActionType.Replay:\n        return {\n          ...state,\n          versionNumber: state.versionNumber + (state.offset - payload),\n          requestedState: state.entries[payload],\n        };\n\n      case ActionType.ClearHistory:\n        return {\n          ...EMPTY_STATE,\n        };\n\n      default:\n        throw new Error(`Unknown history reducer action: ${type as string}`);\n    }\n  };\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/history/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { default as useReducer, ActionType, EMPTY_STATE } from '../reducer';\n\ndescribe('reducer', () => {\n  const size = 5;\n  const reducer = useReducer(size);\n  it('should throw error if unknown action given', () => {\n    expect(() =>\n      reducer(EMPTY_STATE, {\n        type: 'UNKNOWN_ACTION',\n        payload: {},\n      })\n    ).toThrow(/Unknown history reducer action: UNKNOWN_ACTION/i);\n  });\n\n  describe('setCurrentState', () => {\n    it('should add entry to the beginning of the history', () => {\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [{ id: 1 }],\n      };\n\n      const newEntry = { id: 2 };\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: newEntry,\n      });\n\n      expect(result.entries[0]).toStrictEqual(newEntry);\n    });\n\n    it('should clear undone states when adding a new entry', () => {\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [{ id: 1 }, { id: 2 }, { id: 3 }],\n        offset: 2,\n      };\n      const newEntry = { id: 4 };\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: newEntry,\n      });\n\n      expect(result.entries).toHaveLength(2);\n      expect(result.entries[1].id).toBe(3);\n      expect(result.entries[0].id).toBe(4);\n    });\n\n    it('should set correct state values when adding new entry', () => {\n      const initialState = {\n        ...EMPTY_STATE,\n        versionNumber: 3,\n        entries: [{ id: 1 }, { id: 2 }, { id: 3 }],\n        offset: 2,\n      };\n      const newEntry = { id: 2 };\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: newEntry,\n      });\n\n      expect(result.versionNumber).toBe(4);\n      expect(result.offset).toBe(0);\n    });\n\n    it('should respect the determined history size when adding a new entry', () => {\n      const entries = [...Array(size + 1)].map(() => {\n        return { id: 'foo' };\n      });\n      const initialState = {\n        ...EMPTY_STATE,\n        entries,\n      };\n      const newEntry = { id: 7 };\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: newEntry,\n      });\n      expect(result.entries).toHaveLength(size);\n    });\n\n    it('should set the correct values when replaying', () => {\n      const requestedState = { id: 1 };\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [{ id: 2 }, requestedState],\n        requestedState,\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: requestedState,\n      });\n\n      expect(result.offset).toBe(1);\n      expect(result.requestedState).toBeNull();\n      expect(result.entries).toHaveLength(initialState.entries.length);\n    });\n\n    it('should dynamically set the current page based on the relevant change', () => {\n      const requestedState = { current: 2, pages: [{ id: 2, foo: 'foo' }] };\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [\n          { current: 1, pages: [{ id: 1, foo: 'bar' }] },\n          requestedState,\n        ],\n        requestedState,\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: requestedState,\n      });\n\n      expect(result.requestedState.current).toBe(1);\n      expect(result.requestedState.pages[0].id).toBe(2);\n    });\n\n    it('should not dynamically set the replay if changed happened on more than one page', () => {\n      const requestedState = {\n        current: 1,\n        pages: [\n          { id: 1, foo: 'bar' },\n          { id: 2, foo: 'bar' },\n        ],\n      };\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [\n          {\n            current: 2,\n            pages: [\n              { id: 1, foo: 'foo' },\n              { id: 2, foo: 'foo' },\n            ],\n          },\n          requestedState,\n        ],\n        requestedState,\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: requestedState,\n      });\n\n      expect(result.requestedState).toBeNull();\n      expect(result.offset).toBe(1);\n    });\n\n    it('should not dynamically set the replay if a page was added', () => {\n      const requestedState = { current: 1, pages: [{ id: 1, foo: 'bar' }] };\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [\n          {\n            current: 2,\n            pages: [\n              { id: 2, foo: 'foo' },\n              { id: 1, foo: 'bar' },\n            ],\n          },\n          requestedState,\n        ],\n        requestedState,\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.SetCurrentState,\n        payload: requestedState,\n      });\n\n      expect(result.requestedState).toBeNull();\n      expect(result.offset).toBe(1);\n    });\n  });\n\n  describe('clearHistory', () => {\n    it('should set empty state when clearing history', () => {\n      const initialState = {\n        offset: 1,\n        requestedState: { id: 1 },\n        entries: [{ id: 1 }],\n        versionNumber: 1,\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.ClearHistory,\n      });\n\n      expect(result).toMatchObject(EMPTY_STATE);\n    });\n  });\n\n  describe('replay', () => {\n    it('should set the correct requestedState when replaying', () => {\n      const replay = { id: 1 };\n      const initialState = {\n        ...EMPTY_STATE,\n        entries: [{ id: 2 }, replay],\n      };\n\n      const result = reducer(initialState, {\n        type: ActionType.Replay,\n        payload: 1,\n      });\n\n      expect(result.requestedState).toStrictEqual(replay);\n    });\n\n    it('should set the correct versionNumber when replaying', () => {\n      const replay = { id: 1 };\n      const initialState = {\n        ...EMPTY_STATE,\n        versionNumber: 4,\n        offset: 3,\n        entries: [{ id: 2 }, replay],\n      };\n\n      const result1 = reducer(initialState, {\n        type: ActionType.Replay,\n        payload: 2,\n      });\n\n      expect(result1.versionNumber).toBe(5);\n\n      const result2 = reducer(initialState, {\n        type: ActionType.Replay,\n        payload: 5,\n      });\n      expect(result2.versionNumber).toBe(2);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/history/useHistory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { HistoryProviderState } from '../../types';\nimport Context from './context';\n\nfunction useHistory(): HistoryProviderState;\nfunction useHistory<T>(\n  selector: (state: HistoryProviderState) => T | HistoryProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useHistory;\n"
  },
  {
    "path": "packages/story-editor/src/app/history/useHistoryReducer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReducer, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { HistoryEntry } from '../../types';\nimport reducer, { ActionType, EMPTY_STATE } from './reducer';\n\nfunction useHistoryReducer(size: number) {\n  // State has 4 parts:\n  //\n  // `state.entries` is an array of the last changes (up to `size`) to\n  // the object with the most recent at position 0.\n  //\n  // `state.offset` is a pointer to the currently active entry. This will\n  // almost always be 0 unless the user recently did an undo without making\n  // any new changes since.\n  //\n  // `state.requestedState` is the state that the user most recently tried to\n  // undo/redo to - it will be null except for the very short timespan\n  // between the user pressing undo and the app updating to that desired\n  // state.\n  //\n  // `state.versionNumber` tracks the version number of the state.\n  // The version number is increased whenever a new entry is added.\n  // Undo and redo decrease and increase the version number respectively.\n  const [state, dispatch] = useReducer(reducer(size), { ...EMPTY_STATE });\n\n  const { entries, offset, requestedState, versionNumber } = state;\n  const historyLength = entries.length;\n\n  // @todo: make this an identity-stable function, akin to `setState` or `dispatch`.\n  // It appears the only reason for deps here is to return boolean from this\n  // method, which is otherwise appears to be unused.\n  const replay = useCallback(\n    (deltaOffset: number) => {\n      const newOffset = offset + deltaOffset;\n      if (newOffset < 0 || newOffset > historyLength - 1) {\n        return false;\n      }\n\n      dispatch({ type: ActionType.Replay, payload: newOffset });\n      return true;\n    },\n    [dispatch, offset, historyLength]\n  );\n\n  const undo = useCallback(\n    (count = 1) => {\n      return replay(typeof count === 'number' ? count : 1);\n    },\n    [replay]\n  );\n\n  const redo = useCallback(\n    (count = 1) => {\n      return replay(typeof count === 'number' ? -count : -1);\n    },\n    [replay]\n  );\n\n  const clearHistory = useCallback(() => {\n    return dispatch({ type: ActionType.ClearHistory });\n  }, [dispatch]);\n\n  const stateToHistory = useCallback(\n    (entry: HistoryEntry) => {\n      dispatch({ type: ActionType.SetCurrentState, payload: entry });\n    },\n    [dispatch]\n  );\n\n  return {\n    requestedState,\n    stateToHistory,\n    clearHistory,\n    currentEntry: entries?.[offset],\n    offset,\n    historyLength,\n    versionNumber,\n    undo,\n    redo,\n  };\n}\n\nexport default useHistoryReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport { useDropTargets } from '../components/dropTargets';\nimport { useHistory } from './history';\nimport { useAPI } from './api';\nimport { useConfig } from './config';\nimport { useFont } from './font';\nimport { useLocalMedia, useMedia } from './media';\nimport {\n  useStory,\n  useStoryTriggers,\n  useStoryTriggerListener,\n  useStoryTriggersDispatch,\n  STORY_EVENTS,\n  storyReducers,\n} from './story';\n\nimport {\n  useCanvas,\n  useCanvasBoundingBox,\n  useCanvasBoundingBoxRef,\n  CANVAS_BOUNDING_BOX_IDS,\n} from './canvas';\nimport { useLayout } from './layout';\nimport { useCurrentUser } from './currentUser';\nimport { useHelpCenter } from './helpCenter';\nimport { useUserOnboarding } from './userOnboarding';\nimport useRightClickMenu from './rightClickMenu/useRightClickMenu';\n\nexport {\n  useHistory,\n  useAPI,\n  useDropTargets,\n  useTransform,\n  useStory,\n  useStoryTriggers,\n  useStoryTriggerListener,\n  useStoryTriggersDispatch,\n  STORY_EVENTS,\n  useConfig,\n  useFont,\n  useLocalMedia,\n  useMedia,\n  useCanvas,\n  useCanvasBoundingBox,\n  useCanvasBoundingBoxRef,\n  CANVAS_BOUNDING_BOX_IDS,\n  useLayout,\n  useCurrentUser,\n  useHelpCenter,\n  useUserOnboarding,\n  useRightClickMenu,\n  storyReducers,\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { LayoutProviderState } from '../../types';\nimport { CarouselState, ZoomSetting } from '../../constants';\nimport { noop } from '../../utils/noop';\n\nexport default createContext<LayoutProviderState>({\n  actions: {\n    setZoomSetting: noop,\n    closeCarousel: noop,\n    openCarousel: noop,\n    setScrollOffset: noop,\n    setZoomLevel: noop,\n  },\n  state: {\n    pageWidth: 0,\n    pageHeight: 0,\n    hasHorizontalOverflow: false,\n    hasVerticalOverflow: false,\n    hasPageNavigation: false,\n    pagePadding: 0,\n    viewportWidth: 0,\n    viewportHeight: 0,\n    hasExtraPages: false,\n    extraPageWidth: 0,\n    extraPageCount: 0,\n    zoomSetting: ZoomSetting.Fit,\n    zoomLevel: 0,\n    workspaceWidth: 0,\n    workspaceHeight: 0,\n    scrollLeft: 0,\n    scrollTop: 0,\n    carouselState: CarouselState.Open,\n    isCarouselInTransition: false,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useLayout } from './useLayout';\nexport { default as LayoutProvider } from './layoutProvider';\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/layoutProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport useZoomSetting from './useZoomSetting';\nimport useCarouselDrawer from './useCarouselDrawer';\n\nfunction LayoutProvider({ children }: PropsWithChildren<unknown>) {\n  const zoomValue = useZoomSetting();\n  const carouselDrawer = useCarouselDrawer();\n\n  const value = {\n    state: {\n      ...zoomValue.state,\n      ...carouselDrawer.state,\n    },\n    actions: {\n      ...zoomValue.actions,\n      ...carouselDrawer.actions,\n    },\n  };\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport default LayoutProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/test/useZoomSetting.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useZoomSetting from '../useZoomSetting';\n\ndescribe('useZoomSetting', () => {\n  it('should default pageWidth and pageHeight to zero', () => {\n    const { result } = renderHook(() => useZoomSetting());\n\n    expect(result.current.state.pageWidth).toBe(0);\n    expect(result.current.state.pageHeight).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/useCarouselDrawer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useReduction } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { CAROUSEL_TRANSITION_DURATION, CarouselState } from '../../constants';\n\nconst TRANSITION_STATES = [CarouselState.Opening, CarouselState.Closing];\n\nconst carouselStateReducer = {\n  // Only open if currently closed (and mark as OPENING, not actually open yet)\n  // If in any other state, do nothing.\n  openCarousel: (state: CarouselState) =>\n    state === CarouselState.Closed ? CarouselState.Opening : state,\n\n  // Only closed if currently open (and mark as CLOSING, not actually closed yet)\n  // If in any other state, do nothing.\n  closeCarousel: (state: CarouselState) =>\n    state === CarouselState.Open ? CarouselState.Closing : state,\n\n  // Mark transition to new state as completed - must be in a transition state.\n  // If in any other state, do nothing.\n  completeTransition: (state: CarouselState) => {\n    switch (state) {\n      case CarouselState.Opening:\n        return CarouselState.Open;\n      case CarouselState.Closing:\n        return CarouselState.Closed;\n      default:\n        return state;\n    }\n  },\n};\n\nfunction useCarouselDrawer() {\n  const [carouselState, actions] = useReduction(\n    CarouselState.Open,\n    carouselStateReducer\n  );\n  const isCarouselInTransition = TRANSITION_STATES.includes(carouselState);\n\n  const { openCarousel, closeCarousel, completeTransition } = actions;\n\n  useEffect(() => {\n    if (!isCarouselInTransition) {\n      return undefined;\n    }\n    const timeout = setTimeout(\n      completeTransition,\n      CAROUSEL_TRANSITION_DURATION\n    );\n    return () => clearTimeout(timeout);\n  }, [isCarouselInTransition, completeTransition]);\n\n  return {\n    state: {\n      carouselState,\n      isCarouselInTransition,\n    },\n    actions: {\n      // Only these two methods are exposed as public API\n      openCarousel,\n      closeCarousel,\n    },\n  };\n}\n\nexport default useCarouselDrawer;\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/useLayout.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { LayoutProviderState } from '../../types';\nimport Context from './context';\n\nfunction useLayout(): LayoutProviderState;\nfunction useLayout<T>(selector: (state: LayoutProviderState) => T): T;\nfunction useLayout<T>(\n  selector: (state: LayoutProviderState) => T | LayoutProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useLayout;\n"
  },
  {
    "path": "packages/story-editor/src/app/layout/useZoomSetting.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useReduction } from '@googleforcreators/react';\nimport {\n  PAGE_WIDTH,\n  PAGE_RATIO,\n  FULLBLEED_RATIO,\n} from '@googleforcreators/units';\nimport { THEME_CONSTANTS } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  ZoomSetting,\n  PAGE_NAV_WIDTH,\n  PAGE_WIDTH_FACTOR,\n  MAX_EXTRA_PAGES,\n} from '../../constants';\n\n// Beware, that these are slightly magic numbers, that just happens to look good\nconst ZOOM_PADDING_LARGE = 72;\nconst ZOOM_PADDING_NONE = 12;\n\n// This one is only used for Zoom=FIT when width is the limiting factor\n// there must be room for the page menu with 16px gap on either side\n// - times both sides of the canvas = 2 * (40 + 2 * 16)\nconst ZOOM_PADDING_FIT = 144;\n\nconst INITIAL_STATE = {\n  zoomSetting: ZoomSetting.Fit,\n  zoomLevel: 0,\n  workspaceSize: {\n    width: 0,\n    height: 0,\n    availableHeight: 0,\n  },\n  scrollOffset: {\n    left: 0,\n    top: 0,\n  },\n};\n\ninterface WorkspaceSize {\n  width: number;\n  height: number;\n  availableHeight: number;\n}\ninterface ScrollOffset {\n  left: number;\n  top: number;\n}\ninterface ReducerState {\n  zoomSetting: ZoomSetting;\n  zoomLevel: number;\n  workspaceSize: WorkspaceSize;\n  scrollOffset: ScrollOffset;\n}\ninterface SetZoomSettingProps {\n  payload: ZoomSetting;\n}\ninterface SetZoomLevelProps {\n  payload: number;\n}\ninterface SetScrollOffsetProps {\n  payload: ScrollOffset;\n}\ninterface SetWorkspaceSizeProps {\n  payload: WorkspaceSize;\n}\nconst reducer = {\n  setZoomSetting: (\n    state: ReducerState,\n    { payload }: SetZoomSettingProps\n  ): ReducerState => ({\n    ...state,\n    zoomSetting: payload,\n    scrollOffset: {\n      left: 0,\n      top: 0,\n    },\n  }),\n  setZoomLevel: (\n    state: ReducerState,\n    { payload }: SetZoomLevelProps\n  ): ReducerState => ({\n    ...state,\n    zoomLevel: payload,\n    zoomSetting: ZoomSetting.Fixed,\n  }),\n  setScrollOffset: (\n    state: ReducerState,\n    { payload }: SetScrollOffsetProps\n  ): ReducerState => ({\n    ...state,\n    scrollOffset: payload,\n  }),\n  setWorkspaceSize: (\n    state: ReducerState,\n    { payload }: SetWorkspaceSizeProps\n  ): ReducerState => ({\n    ...state,\n    workspaceSize: payload,\n  }),\n};\n\nfunction calculateViewportProperties(\n  workspaceSize: WorkspaceSize,\n  zoomSetting: ZoomSetting,\n  zoomLevel: number\n) {\n  // Calculate page size based on zoom setting\n  let maxPageWidth = 0;\n  const workspaceRatio = workspaceSize.width / workspaceSize.availableHeight;\n  switch (zoomSetting) {\n    case ZoomSetting.Fill: {\n      // See how much we can fit inside so all space is used minus gap\n      if (workspaceRatio > FULLBLEED_RATIO) {\n        // workspace is limited in the height, so use the width minus room for scrollbar\n        maxPageWidth =\n          workspaceSize.width -\n          THEME_CONSTANTS.SCROLLBAR_WIDTH -\n          ZOOM_PADDING_LARGE;\n      } else {\n        // workspace is limited in the width, so use the height minus room for scrollbar converted\n        maxPageWidth =\n          (workspaceSize.availableHeight - THEME_CONSTANTS.SCROLLBAR_WIDTH) *\n            FULLBLEED_RATIO -\n          ZOOM_PADDING_LARGE;\n      }\n      break;\n    }\n    case ZoomSetting.Fit: {\n      // See how much we can fit inside so all is visible\n      // However, leave some extra space, as we don't want it to hug too tightly to the edges.\n      const maxWidth = workspaceSize.width - ZOOM_PADDING_FIT;\n      if (workspaceRatio > FULLBLEED_RATIO) {\n        // workspace is limited in the height, so use the (height - padding) converted\n        // However, it can never be wider than the max width calculated above\n        maxPageWidth = Math.min(\n          maxWidth,\n          (workspaceSize.availableHeight - ZOOM_PADDING_LARGE) * FULLBLEED_RATIO\n        );\n      } else {\n        // workspace is limited in the width, so use the width - padding\n        maxPageWidth = maxWidth;\n      }\n      break;\n    }\n    default:\n      // If no predefined setting was found, check for the zoom level value.\n      if (isNaN(zoomLevel)) {\n        break;\n      }\n      maxPageWidth = zoomLevel * PAGE_WIDTH;\n      break;\n  }\n\n  // Since workspaceSize.width & workspaceSize.height are initially null,\n  // maxPageWidth can end up being negative.\n  // Set it to 0 in that case.\n  maxPageWidth = Math.max(0, maxPageWidth);\n\n  // Floor page width to nearest multiple of PAGE_WIDTH_FACTOR\n  const pageWidth =\n    PAGE_WIDTH_FACTOR * Math.floor(maxPageWidth / PAGE_WIDTH_FACTOR);\n  // Update whether there's overflow and if we have room for page navigation\n  const pageHeight = pageWidth / PAGE_RATIO;\n  const fullbleedHeight = pageWidth / FULLBLEED_RATIO;\n  // Is full width of available area minus gap used (up to two zoom factors off)\n  const hasHorizontalOverflow =\n    pageWidth >=\n    workspaceSize.width - ZOOM_PADDING_LARGE - 2 * PAGE_WIDTH_FACTOR;\n  // Is full height of available area minus gap used (up to two zoom factors off)\n  const hasVerticalOverflow =\n    pageHeight >=\n    workspaceSize.availableHeight - ZOOM_PADDING_LARGE - 2 * PAGE_WIDTH_FACTOR;\n  const hasAnyOverflow = hasHorizontalOverflow || hasVerticalOverflow;\n  const hasPageNavigation =\n    !hasAnyOverflow && pageWidth < workspaceSize.width - 2 * PAGE_NAV_WIDTH;\n  // if any scroll, add a lage padding, else just a bit to allow to show hover frame\n  const pagePadding = hasAnyOverflow ? ZOOM_PADDING_LARGE : ZOOM_PADDING_NONE;\n  // If any kind of scroll, use entire available workspace\n  const viewportWidth = hasAnyOverflow\n    ? workspaceSize.width\n    : pageWidth + pagePadding;\n  const viewportHeight = hasAnyOverflow\n    ? workspaceSize.availableHeight\n    : fullbleedHeight + pagePadding;\n\n  // Calculate if extra pages can be seen before/after current page and if so how many\n  const extraSpace =\n    (workspaceSize.width - (pageWidth + 2 * PAGE_NAV_WIDTH)) / 2;\n  const extraPageWidth = Math.round(0.9 * pageWidth);\n  const hasExtraPages = !hasAnyOverflow && hasPageNavigation && extraSpace > 50;\n  const extraPageCount = hasExtraPages\n    ? Math.min(MAX_EXTRA_PAGES, Math.ceil(extraSpace / extraPageWidth))\n    : 0;\n  return {\n    pageWidth,\n    pageHeight,\n    hasHorizontalOverflow,\n    hasVerticalOverflow,\n    hasPageNavigation,\n    pagePadding,\n    viewportWidth,\n    viewportHeight,\n    hasExtraPages,\n    extraPageWidth,\n    extraPageCount,\n  };\n}\n\nfunction useZoomSetting() {\n  const [state, actions] = useReduction(INITIAL_STATE, reducer);\n  const {\n    zoomSetting,\n    zoomLevel: _zoomLevel,\n    workspaceSize,\n    scrollOffset,\n  } = state;\n\n  const viewportProperties = useMemo(\n    () => calculateViewportProperties(workspaceSize, zoomSetting, _zoomLevel),\n    [workspaceSize, zoomSetting, _zoomLevel]\n  );\n\n  const { pageWidth } = viewportProperties;\n\n  const zoomLevel = useMemo(() => {\n    const maxPageWidth = Math.ceil(\n      (pageWidth / PAGE_WIDTH_FACTOR) * PAGE_WIDTH_FACTOR\n    );\n    switch (zoomSetting) {\n      case ZoomSetting.Fill:\n      case ZoomSetting.Fit:\n        return maxPageWidth / PAGE_WIDTH;\n      default:\n        return _zoomLevel;\n    }\n  }, [_zoomLevel, pageWidth, zoomSetting]);\n\n  return {\n    state: {\n      ...viewportProperties,\n      zoomSetting,\n      zoomLevel,\n      workspaceWidth: workspaceSize.width,\n      workspaceHeight: workspaceSize.height,\n      scrollLeft: scrollOffset.left,\n      scrollTop: scrollOffset.top,\n    },\n    actions,\n  };\n}\n\nexport default useZoomSetting;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TRANSCODABLE_MIME_TYPES = [\n  'video/3gpp',\n  'video/3gpp2',\n  'video/MP2T',\n  'video/mp4',\n  'video/mpeg',\n  'video/ogg',\n  'video/quicktime',\n  'video/webm',\n  'video/x-flv',\n  'video/x-h261',\n  'video/x-h263',\n  'video/x-m4v',\n  'video/x-matroska',\n  'video/x-mjpeg',\n  'video/x-ms-asf',\n  'video/x-msvideo',\n  'video/avi',\n  'video/msvideo',\n  'video/x-nut',\n];\n"
  },
  {
    "path": "packages/story-editor/src/app/media/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * @typedef {import('./typedefs').MediaContext} MediaContext\n */\n\n/**\n * @type {MediaContext}\n */\nconst INITIAL_CONTEXT = {\n  local: { state: {}, actions: {} },\n  media3p: { state: {}, actions: {} },\n};\n\nexport default createContext(INITIAL_CONTEXT);\n"
  },
  {
    "path": "packages/story-editor/src/app/media/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as MediaProvider } from './mediaProvider';\nexport { default as useLocalMedia } from './local/useLocalMedia';\nexport { default as useMedia } from './useMedia';\nexport * from './constants';\nexport * from './types';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/actions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as common from '../pagination/actions';\nimport * as types from './types';\n\nexport const fetchMediaStart = (dispatch) => (properties) =>\n  common.fetchMediaStart(dispatch)({\n    ...properties,\n    provider: 'local',\n  });\nexport const fetchMediaSuccess = (dispatch) => (properties) =>\n  common.fetchMediaSuccess(dispatch)({\n    ...properties,\n    provider: 'local',\n  });\nexport const fetchMediaError = (dispatch) => (properties) =>\n  common.fetchMediaError(dispatch)({\n    ...properties,\n    provider: 'local',\n  });\nexport const setNextPage = (dispatch) => (properties) =>\n  common.setNextPage(dispatch)({ ...properties, provider: 'local' });\nexport const updateMediaElement =\n  (dispatch) =>\n  ({ id, data }) =>\n    common.updateMediaElement(dispatch)({\n      provider: 'local',\n      id,\n      data,\n    });\nexport const deleteMediaElement = (dispatch) => (properties) =>\n  common.deleteMediaElement(dispatch)({\n    ...properties,\n    provider: 'local',\n  });\n\nexport const resetFilters = (dispatch) => () => {\n  dispatch({ type: types.LOCAL_MEDIA_RESET_FILTERS });\n};\n\nexport const setSearchTerm =\n  (dispatch) =>\n  ({ searchTerm }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_SET_SEARCH_TERM,\n      payload: { searchTerm },\n    });\n  };\n\nexport const setMediaType =\n  (dispatch) =>\n  ({ mediaType }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_SET_MEDIA_TYPE,\n      payload: { mediaType },\n    });\n  };\n\nexport const setAudioProcessing =\n  (dispatch) =>\n  ({ id }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_ADD_AUDIO_PROCESSING,\n      payload: { id },\n    });\n  };\n\nexport const removeAudioProcessing =\n  (dispatch) =>\n  ({ id }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_REMOVE_AUDIO_PROCESSING,\n      payload: { id },\n    });\n  };\n\nexport const setPosterProcessing =\n  (dispatch) =>\n  ({ id }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_ADD_POSTER_PROCESSING,\n      payload: { id },\n    });\n  };\n\nexport const removePosterProcessing =\n  (dispatch) =>\n  ({ id }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_REMOVE_POSTER_PROCESSING,\n      payload: { id },\n    });\n  };\n\nexport const setMedia =\n  (dispatch) =>\n  ({ media }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_SET_MEDIA,\n      payload: { media },\n    });\n  };\n\nexport const prependMedia =\n  (dispatch) =>\n  ({ media }) => {\n    dispatch({\n      type: types.LOCAL_MEDIA_PREPEND_MEDIA,\n      payload: { media },\n    });\n  };\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { INITIAL_STATE as COMMON_INITIAL_STATE } from '../pagination/constants';\n\nexport const INITIAL_STATE = {\n  ...COMMON_INITIAL_STATE,\n  audioProcessing: [],\n  audioProcessed: [],\n  posterProcessing: [],\n  posterProcessed: [],\n  mediaType: '',\n  searchTerm: '',\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { FETCH_MEDIA_SUCCESS } from '../pagination/types';\nimport { INITIAL_STATE } from './constants';\nimport * as types from './types';\nimport * as reducers from './reducers';\n\n/**\n * @typedef {import('./typedefs').LocalMediaReducerState} LocalMediaReducerState\n */\n\n/**\n * The reducer for locally uploaded media.\n *\n * For pagination actions, the `payload.provider` discriminator must be\n * assigned to 'local', which is passed from the local media action dispatchers\n * at {@link ./actions}.\n *\n * @param {LocalMediaReducerState} state The state to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {LocalMediaReducerState} The new state\n */\nfunction reducer(state = INITIAL_STATE, { type, payload }) {\n  switch (type) {\n    case FETCH_MEDIA_SUCCESS: {\n      return reducers.fetchMedia(state, { type, payload });\n    }\n\n    case types.LOCAL_MEDIA_RESET_FILTERS: {\n      return reducers.resetFilters(state);\n    }\n\n    case types.LOCAL_MEDIA_SET_SEARCH_TERM: {\n      return reducers.setSearchTerm(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_SET_MEDIA_TYPE: {\n      return reducers.setMediaType(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_SET_MEDIA: {\n      return reducers.setMedia(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_PREPEND_MEDIA: {\n      return reducers.prependMedia(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_ADD_POSTER_PROCESSING: {\n      return reducers.addPosterProcessing(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_REMOVE_POSTER_PROCESSING: {\n      return reducers.removePosterProcessing(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_ADD_AUDIO_PROCESSING: {\n      return reducers.addAudioProcessing(state, payload);\n    }\n\n    case types.LOCAL_MEDIA_REMOVE_AUDIO_PROCESSING: {\n      return reducers.removeAudioProcessing(state, payload);\n    }\n\n    default:\n      return reducers.setupState(state, { type, payload });\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/addAudioProcessing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction addAudioProcessing(state, { id }) {\n  if (!id || state.audioProcessing.includes(id)) {\n    return state;\n  }\n  return {\n    ...state,\n    audioProcessing: [...state.audioProcessing, id],\n  };\n}\n\nexport default addAudioProcessing;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/addPosterProcessing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction addPosterProcessing(state, { id }) {\n  if (!id || state.posterProcessing.includes(id)) {\n    return state;\n  }\n  return {\n    ...state,\n    posterProcessing: [...state.posterProcessing, id],\n  };\n}\nexport default addPosterProcessing;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/fetchMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport commonReducer from '../../pagination/reducer';\n\nfunction fetchMedia(state, { type, payload }) {\n  const { provider, mediaType, searchTerm } = payload;\n  if (\n    provider === 'local' &&\n    mediaType === state.mediaType &&\n    searchTerm === state.searchTerm\n  ) {\n    return commonReducer(state, { type, payload });\n  }\n  return state;\n}\nexport default fetchMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as setupState } from './setupState';\nexport { default as fetchMedia } from './fetchMedia';\nexport { default as setMediaType } from './setMediaType';\nexport { default as setSearchTerm } from './setSearchTerm';\nexport { default as resetFilters } from './resetFilters';\nexport { default as setMedia } from './setMedia';\nexport { default as prependMedia } from './prependMedia';\nexport { default as addPosterProcessing } from './addPosterProcessing';\nexport { default as removePosterProcessing } from './removePosterProcessing';\nexport { default as addAudioProcessing } from './addAudioProcessing';\nexport { default as removeAudioProcessing } from './removeAudioProcessing';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/prependMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction prependMedia(state, { media }) {\n  if (!media.length) {\n    return state;\n  }\n\n  return {\n    ...state,\n    media: [\n      ...media.filter(({ id }) => !state.media.some((item) => item.id === id)),\n      ...state.media,\n    ],\n  };\n}\nexport default prependMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/removeAudioProcessing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction removeAudioProcessing(state, { id }) {\n  if (!id || !state.audioProcessing.includes(id)) {\n    return state;\n  }\n  const currentProcessing = [...state.audioProcessing];\n  const audioProcessing = currentProcessing.filter((e) => e !== id);\n\n  return {\n    ...state,\n    audioProcessing,\n    audioProcessed: [...state.audioProcessed, id],\n  };\n}\nexport default removeAudioProcessing;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/removePosterProcessing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction removePosterProcessing(state, { id }) {\n  if (!id || !state.posterProcessing.includes(id)) {\n    return state;\n  }\n  const currentProcessing = [...state.posterProcessing];\n  const posterProcessing = currentProcessing.filter((e) => e !== id);\n\n  return {\n    ...state,\n    posterProcessing,\n    posterProcessed: [...state.posterProcessed, id],\n  };\n}\nexport default removePosterProcessing;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/resetFilters.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { INITIAL_STATE } from '../constants';\n\nfunction resetFilters(state) {\n  return {\n    ...INITIAL_STATE,\n    audioProcessing: [...state.audioProcessing],\n    audioProcessed: [...state.audioProcessed],\n    posterProcessing: [...state.posterProcessing],\n    posterProcessed: [...state.posterProcessed],\n  };\n}\nexport default resetFilters;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/setMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction setMedia(state, { media }) {\n  return {\n    ...state,\n    media,\n  };\n}\nexport default setMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/setMediaType.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { LOCAL_MEDIA_TYPE_ALL } from '../types';\n\nfunction setMediaType(state, { mediaType }) {\n  if (mediaType === state.mediaType) {\n    return state;\n  }\n\n  // Filters existing media in the state by mediaType\n  // for immediate user feedback while the provider fetches items from the server.\n  // Useful when switching e.g. from All -> Videos, since there might\n  // be some videos already in state.\n  return {\n    ...state,\n    // media: [],\n    media:\n      mediaType === LOCAL_MEDIA_TYPE_ALL\n        ? []\n        : state.media.filter(({ type }) => mediaType === type),\n    pageToken: undefined,\n    mediaType,\n  };\n}\n\nexport default setMediaType;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/setSearchTerm.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { INITIAL_STATE } from '../constants';\n\nfunction setSearchTerm(state, { searchTerm }) {\n  if (searchTerm === state.searchTerm) {\n    return state;\n  }\n  return {\n    ...INITIAL_STATE,\n    audioProcessing: [...state.audioProcessing],\n    audioProcessed: [...state.audioProcessed],\n    posterProcessing: [...state.posterProcessing],\n    posterProcessed: [...state.posterProcessed],\n    mediaType: state.mediaType,\n    searchTerm,\n  };\n}\nexport default setSearchTerm;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/reducers/setupState.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport commonReducer from '../../pagination/reducer';\n\nfunction setupState(state, { type, payload }) {\n  if (payload?.provider === 'local') {\n    return commonReducer(state, { type, payload });\n  }\n  return state;\n}\nexport default setupState;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useMediaReducer from '../../useMediaReducer';\nimport reducer from '../reducer';\nimport * as localActionsToWrap from '../actions';\nimport { fetchMediaStart as commonFetchMediaStart } from '../../pagination/actions';\n\ndescribe('reducer', () => {\n  it('should not update for media action that`s not for local media', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, { ...localActionsToWrap, commonFetchMediaStart })\n    );\n\n    act(() => {\n      result.current.actions.commonFetchMediaStart({\n        provider: 'unsplash',\n        pageToken: 'page2',\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoading: false,\n        isMediaLoaded: false,\n      })\n    );\n  });\n\n  it('should assign isMediaLoading=true on fetchMediaStart', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, localActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaStart({ pageToken: 'page2' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoading: true,\n        isMediaLoaded: false,\n      })\n    );\n  });\n\n  it('should assign isMediaLoaded=true on fetchMediaSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, localActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        media: [{ id: 'id' }],\n        searchTerm: '',\n        mediaType: '',\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: true,\n        isMediaLoading: false,\n      })\n    );\n  });\n\n  it('should not update state on fetchMediaSuccess if searchTerm doesn`t match', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, localActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.setSearchTerm({ searchTerm: 'search term 1' });\n    });\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        searchTerm: 'search term 2',\n        media: [{ id: 'id' }],\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: 'search term 1',\n        media: [],\n        nextPageToken: undefined,\n      })\n    );\n  });\n\n  it('should not update state on fetchMediaSuccess if mediaType doesn`t match', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, localActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.setMediaType({ mediaType: 'image' });\n    });\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        mediaType: 'video',\n        media: [{ id: 'id' }],\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        mediaType: 'image',\n        media: [],\n        nextPageToken: undefined,\n      })\n    );\n  });\n\n  describe('prependMedia', () => {\n    it('should not add items that are already in state', () => {\n      const { result } = renderHook(() =>\n        useMediaReducer(reducer, localActionsToWrap)\n      );\n\n      act(() => {\n        result.current.actions.prependMedia({\n          media: [\n            {\n              id: 123,\n            },\n            {\n              id: 456,\n            },\n          ],\n        });\n      });\n\n      act(() => {\n        result.current.actions.prependMedia({\n          media: [\n            {\n              id: 456,\n            },\n            {\n              id: 789,\n            },\n          ],\n        });\n      });\n\n      expect(result.current.state).toStrictEqual(\n        expect.objectContaining({\n          media: [{ id: 789 }, { id: 123 }, { id: 456 }],\n        })\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/test/useContextValueProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport ApiContext from '../../../api/context';\nimport useContextValueProvider from '../useContextValueProvider';\nimport {\n  GET_MEDIA_RESPONSE_BODY,\n  GET_MEDIA_RESPONSE_HEADER,\n} from '../../../api/test/_utils';\nimport { ConfigProvider } from '../../../config';\n\njest.mock('../../useUploadMedia');\nimport useUploadMedia from '../../useUploadMedia';\n\njest.mock('../../utils/useUploadVideoFrame');\nimport useUploadVideoFrame from '../../utils/useUploadVideoFrame';\n\n// Media List representation in state based on GET_MEDIA_RESPONSE_BODY.\nconst MEDIA_LIST_FROM_GET_MEDIA = [\n  {\n    type: 'image',\n    mimeType: 'image/jpeg',\n    output: undefined,\n    creationDate: '2020-09-01T05:33:54',\n    src: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n    width: 1080,\n    height: 2220,\n    poster: undefined,\n    posterId: undefined,\n    baseColor: '#ffffff',\n    id: 274,\n    length: undefined,\n    lengthFormatted: undefined,\n    alt: 'IMAGE',\n    isPlaceholder: false,\n    isMuted: false,\n    isOptimized: false,\n    isExternal: false,\n    sizes: {\n      medium: {\n        file: 'IMAGE-146x300.jpg',\n        width: 146,\n        height: 300,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-146x300.jpg',\n      },\n      large: {\n        file: 'IMAGE-498x1024.jpg',\n        width: 498,\n        height: 1024,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-498x1024.jpg',\n      },\n      thumbnail: {\n        file: 'IMAGE-150x150.jpg',\n        width: 150,\n        height: 150,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x150.jpg',\n      },\n      medium_large: {\n        file: 'IMAGE-768x1579.jpg',\n        width: 768,\n        height: 1579,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-768x1579.jpg',\n      },\n      '1536x1536': {\n        file: 'IMAGE-747x1536.jpg',\n        width: 747,\n        height: 1536,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-747x1536.jpg',\n      },\n      '2048x2048': {\n        file: 'IMAGE-996x2048.jpg',\n        width: 996,\n        height: 2048,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-996x2048.jpg',\n      },\n      'web-stories-poster-portrait': {\n        file: 'IMAGE-640x853.jpg',\n        width: 640,\n        height: 853,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-640x853.jpg',\n      },\n      'web-stories-publisher-logo': {\n        file: 'IMAGE-96x96.jpg',\n        width: 96,\n        height: 96,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://wp.local/wp-content/uploads/2020/09/IMAGE-96x96.jpg',\n      },\n      'web-stories-thumbnail': {\n        file: 'IMAGE-150x308.jpg',\n        width: 150,\n        height: 308,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x308.jpg',\n      },\n      full: {\n        file: 'IMAGE.jpg',\n        width: 1080,\n        height: 2220,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n      },\n    },\n    attribution: undefined,\n  },\n];\n\nconst renderAllProviders = ({\n  reducerState,\n  reducerActions,\n  configState,\n  apiState,\n}) =>\n  renderHook(() => useContextValueProvider(reducerState, reducerActions), {\n    wrapper: ({ children }) => (\n      <ConfigProvider config={configState}>\n        <ApiContext.Provider value={apiState}>{children}</ApiContext.Provider>\n      </ConfigProvider>\n    ),\n  });\n\ndescribe('useContextValueProvider', () => {\n  let reducerState;\n  let reducerActions;\n  beforeEach(() => {\n    reducerState = {\n      audioProcessing: [],\n      audioProcessed: [],\n      posterProcessing: [],\n      posterProcessed: [],\n      media: [],\n      pageToken: '',\n      mediaType: '',\n      searchTerm: '',\n      totalItems: 0,\n    };\n    reducerActions = {\n      fetchMediaStart: jest.fn(),\n      fetchMediaSuccess: jest.fn(),\n      fetchMediaError: jest.fn(),\n      resetFilters: jest.fn(),\n      setMedia: jest.fn(),\n      setMediaType: jest.fn(),\n      setSearchTerm: jest.fn(),\n      setNextPage: jest.fn(),\n      setAudioProcessing: jest.fn(),\n      removeAudioProcessing: jest.fn(),\n      setPosterProcessing: jest.fn(),\n      removePosterProcessing: jest.fn(),\n      updateMediaElement: jest.fn(),\n      deleteMediaElement: jest.fn(),\n    };\n\n    const useUploadMediaResult = {\n      uploadMedia: jest.fn(),\n      isUploading: jest.fn(),\n    };\n    useUploadMedia.mockImplementation(() => useUploadMediaResult);\n\n    const useUploadVideoFrameResult = {\n      uploadVideoFrame: jest.fn(),\n    };\n    useUploadVideoFrame.mockImplementation(() => useUploadVideoFrameResult);\n  });\n\n  it('resetWithFetch calls getMedia with cacheBust:true and then fetchMediaSuccess', async () => {\n    // Set up and make initial call to useContextValueProvider (which calls\n    // getMedia and fetchMediaSuccess once). Sets an empty media state.\n    const getMedia = jest.fn(() =>\n      Promise.resolve({\n        data: [],\n        headers: GET_MEDIA_RESPONSE_HEADER,\n      })\n    );\n    const apiState = {\n      actions: {\n        getMedia,\n      },\n    };\n    const configState = {\n      allowedMimeTypes: {\n        image: [],\n        vector: [],\n        video: [],\n        caption: [],\n        audio: [],\n      },\n      capabilities: { hasUploadMediaAction: true },\n    };\n    const { result } = renderAllProviders({\n      reducerState,\n      reducerActions,\n      configState,\n      apiState,\n    });\n\n    // This promise will only complete when the \"done()\" callback is called\n    // (see reducerActions.fetchMediaSuccess mock implementation in Promise).\n    await new Promise((done) => {\n      getMedia.mockImplementation(() => {\n        return Promise.resolve({\n          data: GET_MEDIA_RESPONSE_BODY,\n          headers: GET_MEDIA_RESPONSE_HEADER,\n        });\n      });\n      reducerActions.fetchMediaSuccess.mockImplementation(() => {\n        done();\n      });\n\n      // Act:\n      result.current.actions.resetWithFetch();\n    });\n\n    // Assert after fetchMediaSuccess callback is called:\n    expect(getMedia).toHaveBeenNthCalledWith(2, {\n      mediaType: '',\n      searchTerm: '',\n      pagingNum: 1,\n    });\n\n    expect(reducerActions.fetchMediaSuccess).toHaveBeenNthCalledWith(2, {\n      media: MEDIA_LIST_FROM_GET_MEDIA,\n      mediaType: '',\n      searchTerm: '',\n      pageToken: 1,\n      nextPageToken: undefined,\n      totalPages: 1,\n      totalItems: 1,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/test/useLocalMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useLocalMedia from '../useLocalMedia';\nimport MediaContext from '../../context';\n\ndescribe('useLocalMedia', () => {\n  function renderUseLocalMedia(mediaContextValue, selector) {\n    const wrapper = ({ children }) => (\n      <MediaContext.Provider value={mediaContextValue}>\n        {children}\n      </MediaContext.Provider>\n    );\n\n    const { result } = renderHook(() => useLocalMedia(selector), { wrapper });\n    return result.current;\n  }\n\n  it('should return state for local media', () => {\n    const state = renderUseLocalMedia({\n      local: {\n        sampleLocalState1: 'value1',\n        sampleLocalState2: 'value2',\n      },\n    });\n    expect(state).toStrictEqual({\n      sampleLocalState1: 'value1',\n      sampleLocalState2: 'value2',\n    });\n  });\n\n  it('should return state for local media when using a selector', () => {\n    const state = renderUseLocalMedia(\n      {\n        local: {\n          sampleLocalState1: 'value1',\n          sampleLocalState2: 'value2',\n        },\n      },\n      ({ sampleLocalState2 }) => ({ sampleLocalState2 })\n    );\n    expect(state).toStrictEqual({\n      sampleLocalState2: 'value2',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/typedefs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {import('../typedefs').Media} Media\n */\n\n/**\n * @typedef FetchMediaSuccessPayload\n * @property {Array.<Media>} media the media that is fetched\n * @property {string} nextPageToken token representing the next page\n * @property {number} totalPages total number of pages\n * @property {string} pageToken the current page token\n */\n\n/**\n * @typedef UpdateMediaElementPayload\n * @property {string} id id of the media to update\n * @property {Object} data Updated data.\n * @property {string} data.posterId poster id\n * @property {string} data.poster poster\n * @property {number} data.height height in pixels\n * @property {number} data.width width in pixels\n * @property {string} data.alt alt string that describes the media\n */\n\n/**\n * 'local media' action typedefs from {@link ./actions}.\n *\n * @typedef {(payload: {id: string}) => undefined} DeleteMediaElementFn\n * @typedef {() => undefined} ResetFiltersFn\n * @typedef {() => undefined} ResetWithFetchFn\n * @typedef {(payload: {mediaType: string}) => undefined} SetMediaTypeFn\n * @typedef {() => undefined} SetNextPageFn\n * @typedef {(payload: {searchTerm: string}) => undefined} SetSearchTermFn\n * @typedef {(payload: UpdateMediaElementPayload) => undefined} UpdateMediaElementFn\n * @typedef {(files:[], payload: { onLocalFile, onUploadFile, onUploadFailure }) => undefined} UploadMediaFn\n * @typedef {(id: string, src: string) => undefined} UploadVideoPosterFn\n * @typedef {() => undefined} FetchMediaErrorFn\n * @typedef {(payload: {pageToken: string}) => undefined} FetchMediaStartFn\n * @typedef {(payload: FetchMediaSuccessPayload) => undefined} FetchMediaSuccessFn\n */\n\n/**\n * 'local media' actions exposed through context providers\n *\n * @typedef {Object} LocalMediaContextActions\n * @property {DeleteMediaElementFn} deleteMediaElement action to delete a media\n * @property {ResetFiltersFn} resetFilters action to reset filters\n * @property {ResetWithFetchFn} resetWithFetch resets the filter in the state,\n * and then refetches the media from the server\n * @property {SetMediaTypeFn} setMediaType action to set media type\n * @property {SetNextPageFn} setNextPage action to set next page\n * @property {SetSearchTermFn} setSearchTerm action to set search term\n * @property {UpdateMediaElementFn} updateMediaElement action update media\n * @property {UploadMediaFn} uploadMedia action to upload media\n * @property {UploadVideoPosterFn} uploadVideoPoster action upload video poster\n */\n\n/**\n * 'local media' state object exposed to the rest of application through context\n * providers.\n *\n * @typedef {Object} LocalMediaContextState\n * @property {boolean} hasMore is there more media\n * @property {boolean} isMediaLoaded is media loaded\n * @property {boolean} isMediaLoading is media loading\n * @property {boolean} isUploading is media uploading\n * @property {Array.<Media>} media array of media\n * @property {string} mediaType current media type filter selected\n * @property {string} nextPageToken the page token for the next page\n * @property {string} pageToken page token\n * @property {Array.<number>} audioProcessing Videos that have been processed for audio track detection.\n * @property {Array.<number>} audioProcessed Videos that haven't yet been processed for audio track detection.\n * @property {Array.<number>} posterProcessing Videos that have been processed for poster generation.\n * @property {Array.<number>} posterProcessed Videos that haven't yet been processed for poster generation.\n * @property {string} searchTerm search term\n * @property {number} totalPages total pages\n */\n\n/**\n * 'local media' context exposed to application through context providers containing\n * state and action.\n *\n * @typedef {Object} LocalMediaContext\n * @property {LocalMediaContextState} state state of locally uploaded media\n * @property {LocalMediaContextActions} actions actions for local media\n */\n\n/**\n * 'local media' state object used internally by the reducer.\n *\n * @typedef {Object} LocalMediaReducerState\n * @property {boolean} hasMore is there more media\n * @property {boolean} isMediaLoaded is media loaded\n * @property {boolean} isMediaLoading is media loading\n * @property {Array.<Media>} media array of media\n * @property {string} mediaType current media type filter selected\n * @property {string} nextPageToken the page token for the next page\n * @property {string} pageToken page token\n * @property {Array.<number>} audioProcessed IDs of videos that have been processed for audio track detection.\n * @property {Array.<number>} audioProcessing IDs of videos that haven't yet been processed for audio track detection.\n * @property {Array.<number>} posterProcessed IDs of videos that have been processed for poster generation.\n * @property {Array.<number>} posterProcessing IDs of videos that haven't yet been processed for poster generation.\n * @property {string} searchTerm search term\n * @property {number} totalPages total pages\n */\n\n/**\n * 'local media' actions used internally by the reducer.\n *\n * @typedef {Object} LocalMediaContextActions\n * @property {DeleteMediaElementFn} deleteMediaElement action to delete a media\n * @property {FetchMediaErrorFn} fetchMediaError action when fetching media has\n * error\n * @property {FetchMediaStartFn} fetchMediaStart action when fetching media\n * starts\n * @property {FetchMediaSuccessFn} fetchMediaSuccess action when fetching media\n * is successful\n * @property {ResetFiltersFn} resetFilters action to reset filters\n * @property {ResetWithFetchFn} resetWithFetch resets the filter in the state,\n * and then refetches the media from the server\n * @property {SetMediaTypeFn} setMediaType action to set media type\n * @property {SetNextPageFn} setNextPage action to set next page\n * @property {SetSearchTermFn} setSearchTerm action to set search term\n * @property {UpdateMediaElementFn} updateMediaElement action update media\n * @property {UploadMediaFn} uploadMedia action to upload media\n * @property {UploadVideoPosterFn} uploadVideoPoster action upload video poster\n */\n\n// This is required so that the IDE doesn't ignore this file.\n// Without it the types don't show up when you use {import('./typedefs)}.\nexport default {};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/types.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const LOCAL_MEDIA_RESET_FILTERS = 'LOCAL_MEDIA_RESET_FILTERS';\nexport const LOCAL_MEDIA_SET_SEARCH_TERM = 'LOCAL_MEDIA_SET_SEARCH_TERM';\nexport const LOCAL_MEDIA_SET_MEDIA_TYPE = 'LOCAL_MEDIA_SET_MEDIA_TYPE';\nexport const LOCAL_MEDIA_SET_MEDIA = 'LOCAL_MEDIA_SET_MEDIA';\nexport const LOCAL_MEDIA_PREPEND_MEDIA = 'LOCAL_MEDIA_PREPEND_MEDIA';\nexport const LOCAL_MEDIA_REMOVE_AUDIO_PROCESSING =\n  'LOCAL_MEDIA_REMOVE_AUDIO_PROCESSING';\nexport const LOCAL_MEDIA_ADD_AUDIO_PROCESSING =\n  'LOCAL_MEDIA_ADD_AUDIO_PROCESSING';\nexport const LOCAL_MEDIA_REMOVE_POSTER_PROCESSING =\n  'LOCAL_MEDIA_REMOVE_POSTER_PROCESSING';\nexport const LOCAL_MEDIA_ADD_POSTER_PROCESSING =\n  'LOCAL_MEDIA_ADD_POSTER_PROCESSING';\n\nexport const LOCAL_MEDIA_TYPE_ALL = 'LOCAL_MEDIA_TYPE_ALL';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/useContextValueProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useCallback, useRef } from '@googleforcreators/react';\nimport { getSmallestUrlForWidth } from '@googleforcreators/media';\nimport { getTimeTracker } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useConfig } from '../../config';\nimport useUploadVideoFrame from '../utils/useUploadVideoFrame';\nimport useProcessMedia from '../utils/useProcessMedia';\nimport useUploadMedia from '../useUploadMedia';\nimport useDetectVideoHasAudio from '../utils/useDetectVideoHasAudio';\nimport useDetectBaseColor from '../utils/useDetectBaseColor';\nimport useDetectBlurHash from '../utils/useDetectBlurhash';\nimport { LOCAL_MEDIA_TYPE_ALL } from './types';\n\n/**\n * @typedef {import('./typedefs').LocalMediaContext} LocalMediaContext\n * @typedef {import('./typedefs').LocalMediaReducerState} LocalMediaReducerState\n * @typedef {import('./typedefs').LocalMediaReducerActions} LocalMediaReducerActions\n */\n\n/**\n * Context fragment provider for local media.\n * This is called from MediaProvider to provide the media global state.\n *\n * @param {LocalMediaReducerState} reducerState The 'local' fragment of the\n * state returned from `useMediaReducer`\n * @param {LocalMediaReducerActions} reducerActions The 'local' fragment of the\n * actions returned from `useMediaReducer`\n * @return {LocalMediaContext} Context.\n */\nexport default function useContextValueProvider(reducerState, reducerActions) {\n  const { media, pageToken, mediaType, searchTerm } = reducerState;\n  const {\n    fetchMediaStart,\n    fetchMediaSuccess,\n    fetchMediaError,\n    resetFilters,\n    prependMedia,\n    setMediaType,\n    setSearchTerm,\n    setNextPage,\n    setAudioProcessing,\n    removeAudioProcessing,\n    setPosterProcessing,\n    removePosterProcessing,\n    updateMediaElement,\n    deleteMediaElement,\n  } = reducerActions;\n  const {\n    actions: { getMedia, updateMedia },\n  } = useAPI();\n\n  const isMountedRef = useRef(false);\n\n  useEffect(() => {\n    isMountedRef.current = true;\n\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  const fetchMedia = useCallback(\n    (\n      {\n        searchTerm: currentSearchTerm = '',\n        pageToken: p = 1,\n        mediaType: currentMediaType,\n      } = {},\n      callback\n    ) => {\n      if (!getMedia) {\n        return null;\n      }\n\n      fetchMediaStart({ pageToken: p });\n      const trackTiming = getTimeTracker('load_media');\n      return getMedia({\n        mediaType:\n          currentMediaType === LOCAL_MEDIA_TYPE_ALL ? '' : currentMediaType,\n        searchTerm: currentSearchTerm,\n        pagingNum: p,\n      })\n        .then(({ data, headers }) => {\n          if (!isMountedRef.current) {\n            return;\n          }\n\n          const totalPages = Number.parseInt(headers.totalPages);\n          const totalItems = Number.parseInt(headers.totalItems);\n          const hasMore = p < totalPages;\n\n          callback({\n            media: data,\n            mediaType: currentMediaType,\n            searchTerm: currentSearchTerm,\n            pageToken: p,\n            nextPageToken: hasMore ? p + 1 : undefined,\n            totalPages,\n            totalItems,\n          });\n        })\n        .catch(fetchMediaError)\n        .finally(() => {\n          trackTiming();\n        });\n    },\n    [fetchMediaError, fetchMediaStart, getMedia]\n  );\n\n  const {\n    active = [],\n    uploadMedia,\n    isUploading,\n    isTranscoding,\n    isNewResourceProcessing,\n    isCurrentResourceProcessing,\n    isNewResourceTranscoding,\n    isNewResourceMuting,\n    isElementTrimming,\n    isCurrentResourceUploading,\n    isCurrentResourceTranscoding,\n    isCurrentResourceMuting,\n    isCurrentResourceTrimming,\n    canTranscodeResource,\n    isBatchUploading,\n  } = useUploadMedia({\n    media,\n    prependMedia,\n    updateMediaElement,\n    deleteMediaElement,\n  });\n  const { uploadVideoFrame } = useUploadVideoFrame({\n    updateMediaElement,\n  });\n\n  const { updateVideoIsMuted } = useDetectVideoHasAudio({\n    updateMediaElement,\n  });\n\n  const { updateBaseColor } = useDetectBaseColor({\n    updateMediaElement,\n  });\n\n  const { updateBlurHash } = useDetectBlurHash({\n    updateMediaElement,\n  });\n\n  const {\n    allowedMimeTypes: { video: allowedVideoMimeTypes },\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const stateRef = useRef();\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  stateRef.current = reducerState;\n\n  const resetWithFetch = useCallback(() => {\n    const { mediaType: currentMediaType } = stateRef.current;\n\n    resetFilters();\n    const isFirstPage = !stateRef.current.pageToken;\n    if (!currentMediaType && !stateRef.current.searchTerm && isFirstPage) {\n      fetchMedia({ mediaType: currentMediaType }, fetchMediaSuccess);\n    }\n  }, [fetchMedia, fetchMediaSuccess, resetFilters]);\n\n  useEffect(() => {\n    fetchMedia({ searchTerm, pageToken, mediaType }, fetchMediaSuccess);\n  }, [fetchMedia, fetchMediaSuccess, mediaType, pageToken, searchTerm]);\n\n  const uploadVideoPoster = useCallback(\n    (id, src) => {\n      const { posterProcessed, posterProcessing } = stateRef.current;\n\n      (async () => {\n        // Simple way to prevent double-uploading.\n        if (posterProcessed.includes(id) || posterProcessing.includes(id)) {\n          return;\n        }\n        setPosterProcessing({ id });\n        await uploadVideoFrame(id, src);\n        removePosterProcessing({ id });\n      })();\n    },\n    [setPosterProcessing, uploadVideoFrame, removePosterProcessing]\n  );\n\n  const processVideoAudio = useCallback(\n    (id, src) => {\n      const { audioProcessed, audioProcessing } = stateRef.current;\n\n      (async () => {\n        // Simple way to prevent double-uploading.\n        if (audioProcessed.includes(id) || audioProcessing.includes(id)) {\n          return;\n        }\n        setAudioProcessing({ id });\n        await updateVideoIsMuted(id, src);\n        removeAudioProcessing({ id });\n      })();\n    },\n    [setAudioProcessing, updateVideoIsMuted, removeAudioProcessing]\n  );\n\n  const postProcessingResource = useCallback(\n    (resource) => {\n      if (!resource) {\n        return;\n      }\n\n      const {\n        type,\n        isMuted,\n        baseColor,\n        src,\n        id,\n        posterId,\n        mimeType,\n        poster,\n        blurHash,\n      } = resource;\n\n      if (!canTranscodeResource(resource)) {\n        return;\n      }\n\n      if (hasUploadMediaAction) {\n        if (\n          (allowedVideoMimeTypes.includes(mimeType) || type === 'gif') &&\n          !posterId\n        ) {\n          uploadVideoPoster(id, src);\n        }\n\n        if (allowedVideoMimeTypes.includes(mimeType) && isMuted === null) {\n          processVideoAudio(id, src);\n        }\n      }\n\n      const imageSrc =\n        type === 'image' ? getSmallestUrlForWidth(0, resource) : poster;\n      if (imageSrc && !baseColor) {\n        updateBaseColor(resource);\n      }\n      if (imageSrc && !blurHash) {\n        updateBlurHash(resource);\n      }\n    },\n    [\n      canTranscodeResource,\n      allowedVideoMimeTypes,\n      updateBaseColor,\n      updateBlurHash,\n      processVideoAudio,\n      uploadVideoPoster,\n      hasUploadMediaAction,\n    ]\n  );\n\n  const {\n    optimizeVideo,\n    optimizeGif,\n    muteExistingVideo,\n    cropExistingVideo,\n    trimExistingVideo,\n    segmentVideo,\n  } = useProcessMedia({\n    postProcessingResource,\n    uploadMedia,\n    updateMedia,\n    deleteMediaElement,\n  });\n\n  // Whenever media items in the library change,\n  // generate missing posters / has audio / base color if needed.\n  useEffect(() => {\n    media?.forEach((mediaElement) => postProcessingResource(mediaElement));\n  }, [media, mediaType, searchTerm, postProcessingResource]);\n\n  const isGeneratingPosterImages = Boolean(\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    stateRef.current?.posterProcessing?.length\n  );\n\n  let uploadingResources = active.map(({ resource }) => resource);\n\n  if (mediaType && mediaType !== LOCAL_MEDIA_TYPE_ALL) {\n    uploadingResources = uploadingResources.filter(\n      ({ type }) => mediaType === type\n    );\n  }\n\n  return {\n    state: {\n      ...reducerState,\n      uploadingMedia: uploadingResources,\n      isUploading: isUploading || isGeneratingPosterImages,\n      isTranscoding,\n      isNewResourceProcessing,\n      isCurrentResourceProcessing,\n      isNewResourceTranscoding,\n      isNewResourceMuting,\n      isElementTrimming,\n      isCurrentResourceUploading,\n      isCurrentResourceTranscoding,\n      isCurrentResourceMuting,\n      isCurrentResourceTrimming,\n      canTranscodeResource,\n      isBatchUploading,\n    },\n    actions: {\n      setNextPage,\n      setMediaType,\n      setSearchTerm,\n      resetFilters,\n      uploadMedia,\n      resetWithFetch,\n      uploadVideoPoster,\n      postProcessingResource,\n      deleteMediaElement,\n      updateMediaElement,\n      optimizeVideo,\n      optimizeGif,\n      muteExistingVideo,\n      trimExistingVideo,\n      updateBaseColor,\n      updateBlurHash,\n      cropExistingVideo,\n      segmentVideo,\n    },\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/local/useLocalMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport useMedia from '../useMedia';\n\n/**\n * @typedef {import('./typedefs').LocalMediaContext} LocalMediaContext\n */\n\n/**\n * Context value consumer to select a fragment of the locally uploaded media\n * context value that's provided from {@link ./useContextValueProvider}.\n *\n * @param {function(LocalMediaContext):Object?} selector Returns a fragment of the media\n * context value that the caller is interested in. If no selector is provided\n * then the entire context is selected.\n * @return {Object} The selected context value fragment.\n */\nfunction useLocalMedia(selector) {\n  return useMedia(({ local }) => (selector ?? identity)(local));\n}\n\nexport default useLocalMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/actions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport * from './categories/actions';\nexport * from '../pagination/actions';\nimport * as types from './types';\n\nexport const setSelectedProvider =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.MEDIA3P_SET_SELECTED_PROVIDER,\n      payload: { provider },\n    });\n  };\n\nexport const setSearchTerm =\n  (dispatch) =>\n  ({ searchTerm }) => {\n    dispatch({\n      type: types.MEDIA3P_SET_SEARCH_TERM,\n      payload: { searchTerm },\n    });\n  };\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/apiFetcher.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const API_DOMAIN = 'https://media3p.googleapis.com';\nconst API_KEY = 'AIzaSyDqgPsZ0VnxAuakmX7bjnzmNQsE7Drlvk0';\n\n/**\n * The methods exposed by the api\n *\n * @enum {string}\n */\nexport const Paths = {\n  LIST_MEDIA: '/v1/media',\n  LIST_CATEGORIES: '/v1/categories',\n  REGISTER_USAGE: '/v1/media:registerUsage',\n};\n\n/**\n * The supported order_by values for listMedia.\n *\n * @enum {string}\n */\nconst ListMediaOrderBy = {\n  RELEVANCE: 'relevance',\n  LATEST: 'latest',\n};\n\n/**\n * The supported order_by values for listCategories.\n *\n * @enum {string}\n */\nconst CategoriesOrderBy = {\n  TRENDING: 'trending',\n};\n\nfunction validateListMediaOrderBy(orderBy) {\n  validateOrderBy(ListMediaOrderBy, orderBy);\n}\n\nfunction validateCategoriesOrderBy(orderBy) {\n  validateOrderBy(CategoriesOrderBy, orderBy);\n}\n\nfunction validateOrderBy(allowedOrderByValues, orderBy) {\n  if (\n    orderBy === null ||\n    Object.values(allowedOrderByValues).indexOf(orderBy.toLowerCase()) > -1\n  ) {\n    return;\n  }\n  throw new Error('Invalid order_by: ' + orderBy);\n}\n\nfunction validatePageSize(pageSize) {\n  if (pageSize === null || pageSize > 0) {\n    return;\n  }\n  throw new Error('Invalid page_size: ' + pageSize);\n}\n\nfunction validateRegisterUsageUrl(url) {\n  if (url && url.includes(Paths.REGISTER_USAGE)) {\n    return;\n  }\n  throw new Error('Invalid url: ' + url);\n}\n\nclass ApiFetcher {\n  /**\n   * Perform a GET request to the Media3P API to list media.\n   * If the parameters are invalid or the server does not return a 200 response,\n   * an error is thrown.\n   *\n   * @param {Object} obj - An object with the options for the request.\n   * @param {?string} obj.languageCode The BCP-47 language code, such as \"en-US\"\n   * or \"sr-Latn\".\n   * @param {?string} obj.filter  Filter details for items returned.\n   * Filter fields available:\n   * > provider - The media provider to query, or a universal list/search if\n   * left blank.\n   * > type - The media type, either 'image' or 'video'.\n   * > query - A keyword search string.\n   * This may be specified without the 'query:' prefix.\n   * @param {?string} obj.orderBy The sort order for returned results.\n   * Valid sort fields are:\n   * > relevance - The default. This is 'most popular' when listing results,\n   * and 'most relevant' when applying a keyword search.\n   * > latest - Last updated time descending.\n   * @param {?number} obj.pageSize Maximum number of results to be returned by the\n   * server. If unspecified or zero, at most 20 media resources will be returned.\n   * @param {?string} obj.pageToken A page token, received from a previous\n   * `ListMedia` call. Provide this to retrieve the subsequent page.\n   * When paginating, all other parameters provided to `ListMedia` must match\n   * the call that provided the page token.\n   * @return {Promise<Object>} The response from the API.\n   */\n  async listMedia({\n    languageCode = null,\n    filter = null,\n    orderBy = null,\n    pageSize = null,\n    pageToken = null,\n  } = {}) {\n    await validateListMediaOrderBy(orderBy);\n    await validatePageSize(pageSize);\n\n    const params = new URLSearchParams(\n      [\n        ['language_code', languageCode],\n        ['filter', filter],\n        ['order_by', orderBy],\n        ['page_size', pageSize],\n        ['page_token', pageToken],\n      ].filter((entry) => Boolean(entry[1]))\n    );\n\n    return this.fetchPath({ params, path: Paths.LIST_MEDIA });\n  }\n\n  /**\n   * Perform a GET request to the Media3P API to list categories.\n   * If the parameters are invalid or the server does not return a 200 response,\n   * an error is thrown.\n   *\n   * @param {Object} obj - An object with the options for the request.\n   * @param {?string} obj.filter  Filter details for items returned.\n   * Filter fields available:\n   * > provider - The media provider to query, or a universal list/search if\n   * left blank.\n   * @param {?string} obj.orderBy The sort order for returned results.\n   * Valid sort fields are:\n   * > 'trending' - The default. This is the categories that are trending now.\n   * @param {?number} obj.pageSize Maximum number of results to be returned by the\n   * server. If unspecified or zero, at most 20 media resources will be returned.\n   * @return {Promise<Object>} The response from the API.\n   */\n  async listCategories({\n    filter = null,\n    orderBy = null,\n    pageSize = null,\n  } = {}) {\n    await validateCategoriesOrderBy(orderBy);\n    await validatePageSize(pageSize);\n\n    const params = new URLSearchParams(\n      [\n        ['filter', filter],\n        ['order_by', orderBy],\n        ['page_size', pageSize],\n      ].filter((entry) => Boolean(entry[1]))\n    );\n\n    return this.fetchPath({\n      params,\n      path: Paths.LIST_CATEGORIES,\n    });\n  }\n\n  /**\n   * Perform a POST request to the Media3P API to register a usage.\n   * If the parameters are invalid or the server does not return a 200 response,\n   * an error is thrown.\n   *\n   * @param {Object} obj - An object with the options for the request.\n   * @param {string} obj.registerUsageUrl Url to call to register media usage.\n   * @return {Promise<void>} The response from the API.\n   */\n  async registerUsage({ registerUsageUrl }) {\n    await validateRegisterUsageUrl(registerUsageUrl);\n\n    await this.fetchUrl({\n      url: new URL(registerUsageUrl),\n      method: 'POST',\n    });\n  }\n\n  /**\n   * Perform an HTTP request for the given params.\n   *\n   * @param {Object} obj - An object with the options for the request.\n   * @param {Paths} obj.path Url to be called.\n   * @param {URLSearchParams} obj.params Url to be called.\n   * @param {?string} obj.method A string to set request's method.\n   * @return {Promise<Object>} The response from the API.\n   */\n  fetchPath({ path, params, method }) {\n    const url = new URL(API_DOMAIN + path);\n    params.forEach((value, key) => {\n      url.searchParams.append(key, value);\n    });\n\n    return this.fetchUrl({ url, method });\n  }\n\n  /**\n   * Perform an HTTP request for the given params.\n   *\n   * @param {Object} obj - An object with the options for the request.\n   * @param {URL} obj.url Url to be called.\n   * @param {?string} obj.method A string to set request's method.\n   * @return {Promise<Object>} The response from the API.\n   */\n  async fetchUrl({ url, method }) {\n    url.searchParams.append('key', API_KEY);\n    const response = await window.fetch(url.href, {\n      method: method ?? 'GET',\n    });\n    if (!response.ok) {\n      throw new Error(\n        'Obtained an error from the ' +\n          url.pathname +\n          ' call, statusCode: ' +\n          response.status +\n          ', statusText: ' +\n          response.statusText\n      );\n    }\n    return response.json();\n  }\n}\n\nexport default new ApiFetcher();\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * @typedef {import('./typedefs').Media3pApiContext} Media3pApiContext\n */\n\n/**\n * @type {Media3pApiContext}\n */\nconst INITIAL_CONTEXT = { actions: {} };\n\nexport default createContext(INITIAL_CONTEXT);\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Media3pApiProvider } from './media3pApiProvider';\nexport { default as useMedia3pApi } from './useMedia3pApi';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/media3pApiProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { getResourceFromMedia3p } from '../../utils';\nimport { PROVIDERS } from '../providerConfiguration';\nimport apiFetcher from './apiFetcher';\nimport Context from './context';\n\n/** @typedef {import('react').ProviderProps} ProviderProps */\n\n/**\n * Provider for the Media3P API. Delegates fetching the data to apiFetcher,\n * but transforms the response into resources.\n *\n * @param {ProviderProps} Provider props.\n * @return {Object} Context.\n */\nfunction Media3pApiProvider({ children }) {\n  const MEDIA_PAGE_SIZE = 20;\n\n  /**\n   * Constructs the filter used for the listMedia requests.\n   *\n   * @param {Object} obj - An object with the options.\n   * @param {string} obj.provider The provider to get the media from.\n   * Currently only 'unsplash' is supported.\n   * @param {?string} obj.contentType Optional. The content type to send.\n   * @param {?string} obj.searchTerm Optional. Search term to send,\n   * eg: 'cute cats'.\n   * @param {?string} obj.categoryId Optional. Id of the selected\n   * category.\n   * @return {string} A filter string.\n   */\n  function constructFilter({ provider, contentType, searchTerm, categoryId }) {\n    if (!Object.keys(PROVIDERS).includes(provider)) {\n      throw new Error(`Unsupported provider: ${provider}`);\n    }\n\n    if (categoryId && searchTerm) {\n      throw new Error(`searchTerm and categoryId are mutually exclusive.`);\n    }\n    return [\n      `provider:${provider}`,\n      contentType && `type:${contentType}`,\n      categoryId && `category:${categoryId}`,\n      searchTerm,\n    ]\n      .filter(Boolean)\n      .join(' ');\n  }\n\n  /**\n   * Get media for the given parameters.\n   *\n   * @typedef {Object} ListMediaFilter\n   * @property {?string} contentType Optional. The content type to filter.\n   * @property {?string} searchTerm Optional. The search term to send,\n   * eg: 'cute cats'.\n   * @property {?string} categoryId Optional. Id of the selected category.\n   * @type {import('./typedefs').ListMediaFn}\n   * @param {Object} obj - An object with the options.\n   * @param {string} obj.provider The provider to get the media from.\n   * @param {?ListMediaFilter} obj.filter Optional. The filter attributes.\n   * @param {?string} obj.orderBy The desired ordering of the results.\n   * Defaults to 'relevance' in the API.\n   * @param {?string} obj.pageToken An optional page token to provide,\n   * for pagination. If unspecified, the first page of results will be returned.\n   * @return {Promise<{nextPageToken: *, media: *}>} An object with the media\n   * resources and a next page token.\n   */\n  async function listMedia({ provider, filter, orderBy, pageToken }) {\n    const { contentType, searchTerm, categoryId } = filter ?? {};\n\n    const response = await apiFetcher.listMedia({\n      filter: constructFilter({\n        provider,\n        contentType,\n        searchTerm,\n        categoryId,\n      }),\n      orderBy,\n      pageSize: MEDIA_PAGE_SIZE,\n      pageToken,\n    });\n    return {\n      media: (response.media || []).map(getResourceFromMedia3p),\n      nextPageToken: response.nextPageToken,\n    };\n  }\n\n  /**\n   * Get categories for the given parameters.\n   *\n   * @type {import('./typedefs').ListCategoriesFn}\n   * @param {Object} obj - An object with the options.\n   * @param {string} obj.provider The provider to get the media from.\n   * @param {?string} obj.orderBy The desired ordering of the results.\n   * Defaults to 'trending' in the API.\n   * @return {Promise<{categories: *}>} An object with the category\n   * resources.\n   */\n  async function listCategories({ provider, orderBy }) {\n    const filter = constructFilter({ provider });\n    const response = await apiFetcher.listCategories({\n      filter,\n      orderBy,\n    });\n    return {\n      categories: response.categories.map((m) => ({\n        id: m.name,\n        label: m.displayName,\n      })),\n    };\n  }\n\n  /**\n   * Register usage of a media for the given payload.\n   *\n   * @type {import('./typedefs').RegisterUsageFn}\n   * @param {Object} obj - An object with the options.\n   * @param {string} obj.registerUsageUrl The url to be called to register the\n   * usage.\n   * @return {Promise<undefined>} An object with the category\n   * resources.\n   */\n  async function registerUsage({ registerUsageUrl }) {\n    await apiFetcher.registerUsage({ registerUsageUrl });\n  }\n\n  /**\n   * @type {import('./typedefs').Media3pApiContext}\n   */\n  const contextValue = {\n    actions: {\n      listMedia,\n      listCategories,\n      registerUsage,\n    },\n  };\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n}\n\nMedia3pApiProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default Media3pApiProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/test/apiFetcher.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport apiFetcher, { Paths, API_DOMAIN } from '../apiFetcher';\n\nconst PHOTOS_BODY_JSON = {\n  media: [\n    {\n      name: 'photo 29044',\n      imageUrls: [\n        {\n          url: 'https://upload.wikimedia.org/wikipedia/en/2/2e/Donald_Duck_-_temper.png',\n          imageName: 'original',\n        },\n      ],\n    },\n  ],\n};\n\nconst CATEGORIES_BODY_JSON = {\n  categories: [\n    {\n      name: 'categories/unsplash:1',\n      label: 'Covid-19',\n    },\n  ],\n};\n\nconst VALID_PHOTOS_RESPONSE = {\n  ok: true,\n  status: 200,\n  json: () => PHOTOS_BODY_JSON,\n};\n\nconst VALID_CATEGORIES_RESPONSE = {\n  ok: true,\n  status: 200,\n  json: () => CATEGORIES_BODY_JSON,\n};\n\nconst VALID_REGISTER_USAGE_RESPONSE = {\n  ok: true,\n  status: 200,\n  json: () => {},\n};\n\nconst ERROR_RESPONSE = {\n  ok: false,\n  status: 400,\n  statusText: 'Error',\n};\n\nconst INVALID_REGISTER_USAGE_URL =\n  'http://some.url.com/02647749feef0d5536c92df1d9cfa38e';\nconst REGISTER_USAGE_URL =\n  API_DOMAIN +\n  Paths.REGISTER_USAGE +\n  '?payload=02647749feef0d5536c92df1d9cfa38e';\n\nfunction mockFetch(response, { requestPath, requestMethod }) {\n  jest.spyOn(window, 'fetch').mockImplementation((url, { method }) => {\n    const path = new URL(url).pathname;\n    if (path !== requestPath) {\n      throw new Error(\n        `Path ${requestPath} not found. Received ${path} instead.`\n      );\n    }\n    if ((requestMethod ?? 'GET') !== method) {\n      jest.fail(\n        `Method ${requestMethod} not found. Received ${method} instead.`\n      );\n    }\n    return Promise.resolve(response);\n  });\n}\n\ndescribe('ApiFetcher', () => {\n  afterEach(() => {\n    window.fetch?.mockClear();\n  });\n\n  describe('listMedia', () => {\n    it('should perform a GET request', async () => {\n      mockFetch(VALID_PHOTOS_RESPONSE, { requestPath: Paths.LIST_MEDIA });\n\n      const result = await apiFetcher.listMedia();\n      expect(result.media[0].name).toBe('photo 29044');\n    });\n\n    it('should throw when the API returns an error', async () => {\n      mockFetch(ERROR_RESPONSE, { requestPath: Paths.LIST_MEDIA });\n\n      expect.assertions(1);\n\n      await expect(apiFetcher.listMedia()).rejects.toThrow(/Obtained an error/);\n    });\n\n    it('should format request params correctly', async () => {\n      mockFetch(VALID_PHOTOS_RESPONSE, { requestPath: Paths.LIST_MEDIA });\n\n      const languageCode = 'es';\n      const pageSize = 15;\n      const orderBy = 'latest';\n      const pageToken = '1234';\n      const filter = 'cat';\n\n      const result = await apiFetcher.listMedia({\n        languageCode,\n        pageSize,\n        orderBy,\n        pageToken,\n        filter,\n      });\n      expect(result.media[0].name).toBe('photo 29044');\n      expect(window.fetch).toHaveBeenCalledOnce();\n      const fetchArg = fetch.mock.calls[0][0];\n      const queryString = fetchArg.substring(fetchArg.indexOf('?') + 1);\n      const queryParams = queryString.split('&');\n      expect(queryParams).toStrictEqual(\n        expect.arrayContaining([\n          'language_code=' + languageCode,\n          'page_size=' + pageSize,\n          'order_by=' + orderBy,\n          'page_token=' + pageToken,\n          'filter=' + filter,\n        ])\n      );\n      expect(queryParams).toHaveLength(6); // Also includes the key\n    });\n\n    it('should throw an error for an invalid pageSize type', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listMedia({\n          pageSize: 'big',\n        })\n      ).rejects.toThrow(/Invalid page_size/);\n    });\n\n    it('should throw an error for an invalid pageSize number', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listMedia({\n          pageSize: -30,\n        })\n      ).rejects.toThrow(/Invalid page_size/);\n    });\n\n    it('should throw an error for an invalid orderBy value', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listMedia({\n          orderBy: 'oldest',\n        })\n      ).rejects.toThrow(/Invalid order_by/);\n    });\n\n    it('should throw an error for an empty string orderBy', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listMedia({\n          orderBy: '',\n        })\n      ).rejects.toThrow(/Invalid order_by/);\n    });\n\n    it('should correctly escape a filter with spaces', async () => {\n      mockFetch(VALID_PHOTOS_RESPONSE, { requestPath: Paths.LIST_MEDIA });\n\n      const filter = 'cat and  many dogs';\n      const escapedFilter = 'cat+and++many+dogs';\n\n      await apiFetcher.listMedia({ filter });\n      const fetchArg = window.fetch.mock.calls[0][0];\n      const queryString = fetchArg.substring(fetchArg.indexOf('?') + 1);\n      const queryParams = queryString.split('&');\n      expect(queryParams).toStrictEqual(\n        expect.arrayContaining(['filter=' + escapedFilter])\n      );\n    });\n\n    it('should correctly escape a filter with &', async () => {\n      mockFetch(VALID_PHOTOS_RESPONSE, { requestPath: Paths.LIST_MEDIA });\n\n      const filter = 'Tom & Jerry';\n      const escapedFilter = 'Tom+%26+Jerry';\n\n      await apiFetcher.listMedia({ filter });\n      const fetchArg = window.fetch.mock.calls[0][0];\n      const queryString = fetchArg.substring(fetchArg.indexOf('?') + 1);\n      const queryParams = queryString.split('&');\n      expect(queryParams).toStrictEqual(\n        expect.arrayContaining(['filter=' + escapedFilter])\n      );\n    });\n  });\n\n  describe('listCategories', () => {\n    it('should perform a GET request', async () => {\n      mockFetch(VALID_CATEGORIES_RESPONSE, {\n        requestPath: Paths.LIST_CATEGORIES,\n      });\n\n      const result = await apiFetcher.listCategories();\n      expect(result.categories[0].label).toBe('Covid-19');\n    });\n\n    it('should throw when the API returns an error', async () => {\n      mockFetch(ERROR_RESPONSE, {\n        requestPath: Paths.LIST_CATEGORIES,\n      });\n\n      expect.assertions(1);\n\n      await expect(apiFetcher.listCategories()).rejects.toThrow(\n        /Obtained an error/\n      );\n    });\n\n    it('should format request params correctly', async () => {\n      mockFetch(VALID_CATEGORIES_RESPONSE, {\n        requestPath: Paths.LIST_CATEGORIES,\n      });\n\n      const pageSize = 15;\n      const orderBy = 'trending';\n      const filter = 'provider';\n\n      const result = await apiFetcher.listCategories({\n        pageSize,\n        orderBy,\n        filter,\n      });\n\n      expect(result.categories[0].label).toBe('Covid-19');\n      expect(window.fetch).toHaveBeenCalledOnce();\n      const fetchArg = fetch.mock.calls[0][0];\n      const queryString = fetchArg.substring(fetchArg.indexOf('?') + 1);\n      const queryParams = queryString.split('&');\n      expect(queryParams).toStrictEqual(\n        expect.arrayContaining([\n          'page_size=' + pageSize,\n          'order_by=' + orderBy,\n          'filter=' + filter,\n        ])\n      );\n      expect(queryParams).toHaveLength(4); // Also includes the key\n    });\n\n    it('should throw an error for an invalid pageSize type', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listCategories({\n          pageSize: 'big',\n        })\n      ).rejects.toThrow(/Invalid page_size/);\n    });\n\n    it('should throw an error for an invalid pageSize number', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listCategories({\n          pageSize: -30,\n        })\n      ).rejects.toThrow(/Invalid page_size/);\n    });\n\n    it('should throw an error for an invalid orderBy value', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listCategories({\n          orderBy: 'oldest',\n        })\n      ).rejects.toThrow(/Invalid order_by/);\n    });\n\n    it('should throw an error for an empty string orderBy', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.listCategories({\n          orderBy: '',\n        })\n      ).rejects.toThrow(/Invalid order_by/);\n    });\n  });\n\n  describe('registerUsage', () => {\n    it('should perform a POST request', async () => {\n      mockFetch(VALID_REGISTER_USAGE_RESPONSE, {\n        requestPath: Paths.REGISTER_USAGE,\n        requestMethod: 'POST',\n      });\n\n      const result = await apiFetcher.registerUsage({\n        registerUsageUrl: REGISTER_USAGE_URL,\n      });\n      expect(result).toBeUndefined();\n    });\n\n    it('should throw when the API returns an error', async () => {\n      mockFetch(ERROR_RESPONSE, {\n        requestPath: Paths.REGISTER_USAGE,\n        requestMethod: 'POST',\n      });\n\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.registerUsage({ registerUsageUrl: REGISTER_USAGE_URL })\n      ).rejects.toThrow(/Obtained an error/);\n    });\n\n    it('should throw an error for a invalid url', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.registerUsage({\n          registerUsageUrl: INVALID_REGISTER_USAGE_URL,\n        })\n      ).rejects.toThrow(/Invalid url/);\n    });\n\n    it('should throw an error for a blank url', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.registerUsage({\n          registerUsageUrl: '   ',\n        })\n      ).rejects.toThrow(/Invalid url/);\n    });\n\n    it('should throw an error for a missing url', async () => {\n      expect.assertions(1);\n\n      await expect(\n        apiFetcher.registerUsage({\n          registerUsageUrl: undefined,\n        })\n      ).rejects.toThrow(/Invalid url/);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/test/useMedia3pApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { useMedia3pApi } from '..';\nimport Media3pApiProvider from '../media3pApiProvider';\n\njest.mock('../apiFetcher');\n\nimport apiFetcherMock, { API_DOMAIN, Paths } from '../apiFetcher';\n\nconst REGISTER_USAGE_URL =\n  API_DOMAIN +\n  Paths.REGISTER_USAGE +\n  '?payload=02647749feef0d5536c92df1d9cfa38e';\n\ndescribe('useMedia3pApi', () => {\n  beforeAll(() => {\n    apiFetcherMock.listMedia.mockImplementation(() =>\n      Promise.resolve({\n        media: [\n          {\n            name: 'media/unsplash:1234',\n            provider: 'UNSPLASH',\n            author: {\n              displayName: 'Maria',\n              url: 'http://maria.com',\n            },\n            registerUsageUrl: REGISTER_USAGE_URL,\n            imageUrls: [\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=340&h=227&fit=max',\n                mimeType: 'image/jpeg',\n                width: 340,\n                height: 227,\n              },\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=1060&h=707&fit=max',\n                mimeType: 'image/jpeg',\n                width: 1060,\n                height: 707,\n              },\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=2121&h=1414&fit=max',\n                mimeType: 'image/jpeg',\n                width: 2121,\n                height: 1414,\n              },\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=3182&h=2121&fit=max',\n                mimeType: 'image/jpeg',\n                width: 3182,\n                height: 2121,\n              },\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=4243&h=2829&fit=max',\n                mimeType: 'image/jpeg',\n                width: 4243,\n                height: 2829,\n              },\n              {\n                url: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=5304&h=3536&fit=max',\n                mimeType: 'image/jpeg',\n                width: 5304,\n                height: 3536,\n              },\n            ],\n            description: 'A cat',\n            type: 'IMAGE',\n            createTime: '1234',\n            updateTime: '5678',\n          },\n        ],\n        nextPageToken: 'lala',\n      })\n    );\n    apiFetcherMock.listCategories.mockImplementation(() =>\n      Promise.resolve({\n        categories: [\n          {\n            name: 'categories/unsplash:1',\n            displayName: 'Covid-19',\n          },\n          {\n            name: 'categories/unsplash:2',\n            displayName: 'Mountains',\n          },\n        ],\n      })\n    );\n    apiFetcherMock.registerUsage.mockImplementation(() =>\n      Promise.resolve(undefined)\n    );\n  });\n\n  it('should properly call listMedia and map the results', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    const listMediaResult = await result.current.actions.listMedia({\n      provider: 'unsplash',\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:unsplash',\n      orderBy: undefined,\n      pageSize: 20,\n      pageToken: undefined,\n    });\n    expect(listMediaResult).toStrictEqual({\n      media: [\n        {\n          baseColor: undefined,\n          blurHash: undefined,\n          alt: 'A cat',\n          attribution: {\n            author: {\n              displayName: 'Maria',\n              url: 'http://maria.com',\n            },\n            registerUsageUrl: REGISTER_USAGE_URL,\n          },\n          creationDate: '1234',\n          height: 3536,\n          id: 'media/unsplash:1234',\n          isPlaceholder: false,\n          isExternal: true,\n          needsProxy: false,\n          mimeType: 'image/jpeg',\n          sizes: {\n            web_stories_thumbnail: {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=340&h=227&fit=max',\n              mimeType: 'image/jpeg',\n              width: 340,\n              height: 227,\n            },\n            '1060_707': {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=1060&h=707&fit=max',\n              mimeType: 'image/jpeg',\n              width: 1060,\n              height: 707,\n            },\n            '2121_1414': {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=2121&h=1414&fit=max',\n              mimeType: 'image/jpeg',\n              width: 2121,\n              height: 1414,\n            },\n            '3182_2121': {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=3182&h=2121&fit=max',\n              mimeType: 'image/jpeg',\n              width: 3182,\n              height: 2121,\n            },\n            large: {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=4243&h=2829&fit=max',\n              mimeType: 'image/jpeg',\n              width: 4243,\n              height: 2829,\n            },\n            full: {\n              file: 'media/unsplash:1234',\n              sourceUrl:\n                'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=5304&h=3536&fit=max',\n              mimeType: 'image/jpeg',\n              width: 5304,\n              height: 3536,\n            },\n          },\n          src: 'https://images.unsplash.com/photo-1515516089376-88db1e26e9c0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=5304&h=3536&fit=max',\n          type: 'image',\n          width: 5304,\n        },\n      ],\n      nextPageToken: 'lala',\n    });\n  });\n\n  it('should call listMedia with searchTerm', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    await result.current.actions.listMedia({\n      provider: 'unsplash',\n      filter: { searchTerm: 'cat' },\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:unsplash cat',\n      orderBy: undefined,\n      pageSize: 20,\n      pageToken: undefined,\n    });\n  });\n\n  it('should call listMedia with category', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    await result.current.actions.listMedia({\n      provider: 'unsplash',\n      filter: { categoryId: 'category/1' },\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:unsplash category:category/1',\n      orderBy: undefined,\n      pageSize: 20,\n      pageToken: undefined,\n    });\n  });\n\n  it('should call listMedia with contentType', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    await result.current.actions.listMedia({\n      provider: 'tenor',\n      filter: {\n        contentType: 'gif',\n        searchTerm: 'cat',\n      },\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:tenor type:gif cat',\n      orderBy: undefined,\n      pageSize: 20,\n      pageToken: undefined,\n    });\n  });\n\n  it('should call listMedia with pageToken', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    await result.current.actions.listMedia({\n      provider: 'unsplash',\n      pageToken: 'token',\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:unsplash',\n      orderBy: undefined,\n      pageSize: 20,\n      pageToken: 'token',\n    });\n  });\n\n  it('should call listMedia with orderBy', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    await result.current.actions.listMedia({\n      provider: 'unsplash',\n      orderBy: 'latest',\n    });\n\n    expect(apiFetcherMock.listMedia).toHaveBeenCalledWith({\n      filter: 'provider:unsplash',\n      orderBy: 'latest',\n      pageSize: 20,\n      pageToken: undefined,\n    });\n  });\n\n  it('should properly call listCategories and map the results', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    const listCategoriesResult = await result.current.actions.listCategories({\n      provider: 'unsplash',\n    });\n\n    expect(listCategoriesResult).toStrictEqual({\n      categories: [\n        {\n          id: 'categories/unsplash:1',\n          label: 'Covid-19',\n        },\n        {\n          id: 'categories/unsplash:2',\n          label: 'Mountains',\n        },\n      ],\n    });\n  });\n\n  it('should properly call registerUsage', async () => {\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n    const { result } = renderHook(() => useMedia3pApi(), { wrapper });\n\n    const registerUsageResult = await result.current.actions.registerUsage({\n      registerUsageUrl: REGISTER_USAGE_URL,\n    });\n\n    expect(registerUsageResult).toBeUndefined();\n  });\n\n  it('should properly handle an empty listMedia response', () => {\n    apiFetcherMock.listMedia.mockImplementation(() => Promise.resolve({}));\n    const wrapper = (params) => (\n      <Media3pApiProvider>{params.children}</Media3pApiProvider>\n    );\n\n    expect(async () => {\n      await renderHook(() => useMedia3pApi(), { wrapper });\n    }).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/typedefs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Functions exposed from {@link ./useMedia3pApi}.\n *\n * @typedef {(obj:{\n * provider: string,\n * contentType: ?string,\n * searchTerm: ?string,\n * categoryId: ?string,\n * orderBy: ?string,\n * pageToken: ?string\n * }) => Promise<{nextPageToken: *, media: *}>} ListMediaFn\n * @typedef {(obj:{provider: string, orderBy: ?string})\n * => Promise<{categories: *}>} ListCategoriesFn\n * @typedef {(obj:{registerUsageUrl: string})\n * => Promise<undefined>} RegisterUsageFn\n */\n\n/**\n * Media3pApi Context Value\n *\n * @typedef Media3pApiContext\n * @property {Object} actions contains all the actions used to interact with\n * media3p api\n * @property {ListMediaFn} actions.listMedia list media\n * @property {ListCategoriesFn} actions.listCategoriesFn list categories\n * @property {RegisterUsageFn} actions.registerUsage register usage\n */\n\n// This is required so that the IDE doesn't ignore this file.\n// Without it the types don't show up when you use {import('./typedefs)}.\nexport default {};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/api/useMedia3pApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\n/** @typedef {import('./typedefs').Media3pApiContext} Media3pApiContext */\n\n/**\n * Context value consumer to select a fragment of the context from\n * {@link ./media3pApiProvider}.\n *\n * @return {Media3pApiContext} The selected context value fragment.\n */\nfunction useMedia3pApi() {\n  // No selector because none of the context properties have a state because\n  // they are currently all functions without state.\n  return useContextSelector(Context, identity);\n}\n\nexport default useMedia3pApi;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/attribution.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport styled, { css } from 'styled-components';\nimport { rgba } from 'polished';\nimport {\n  Text as DefaultText,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { TenorLogoFull, UnsplashLogoFull } from '../../../icons';\nimport CoverrLogoFull from '../../../images/coverr_logo.svg';\n\nconst AttributionPill = styled.div`\n  position: absolute;\n  left: 24px;\n  bottom: 10px;\n  border-radius: 100px;\n  padding: 2px 8px;\n  height: 24px;\n  display: flex;\n  flex-wrap: nowrap;\n  background-color: ${({ theme }) => rgba(theme.colors.standard.black, 0.7)};\n  cursor: pointer;\n  align-items: center;\n  z-index: 9999;\n`;\n\nconst Text = styled(DefaultText.Span)`\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst logo = css`\n  color: ${({ theme }) => theme.colors.standard.white};\n  fill: ${({ theme }) => theme.colors.standard.white};\n  margin-left: 6px;\n  line-height: 14px;\n`;\n\nconst UnsplashLogo = styled(UnsplashLogoFull)`\n  height: 14px;\n  ${logo}\n`;\n\nconst CoverrLogo = styled(CoverrLogoFull)`\n  ${logo}\n  height: 12px;\n  margin-top: 2px;\n`;\n\nconst TenorLogo = styled(TenorLogoFull)`\n  height: 14px;\n  ${logo}\n  margin: 0 2px 2px 6px;\n`;\n\nconst unsplashUrl =\n  'https://unsplash.com?utm_source=web_stories_wordpress&utm_medium=referral';\nconst coverrUrl =\n  'https://coverr.co?utm_source=web_stories_wordpress&utm_medium=referral&utm_campaign=api_powered_by';\nconst tenorUrl =\n  'https://tenor.com?utm_source=web_stories_wordpress&utm_medium=referral';\n\nconst MEDIA_PROVIDER = {\n  coverr: 'Coverr',\n  tenor: 'Tenor',\n  unsplash: 'Unsplash',\n};\nconst getAriaLabel = (provider) =>\n  sprintf(\n    /* translators: %s: media provider name. */\n    __('Powered by %s', 'web-stories'),\n    provider\n  );\n\nexport function UnsplashAttribution() {\n  return (\n    <a\n      href={unsplashUrl}\n      target={'_blank'}\n      rel={'noreferrer'}\n      aria-label={getAriaLabel(MEDIA_PROVIDER.unsplash)}\n      tabIndex={-1}\n    >\n      <AttributionPill aria-hidden>\n        <Text size={TextSize.XSmall}>{__('Powered by', 'web-stories')}</Text>\n        <UnsplashLogo />\n      </AttributionPill>\n    </a>\n  );\n}\n\nexport function CoverrAttribution() {\n  return (\n    <a\n      href={coverrUrl}\n      target={'_blank'}\n      rel={'noreferrer'}\n      aria-label={getAriaLabel(MEDIA_PROVIDER.coverr)}\n      tabIndex={-1}\n    >\n      <AttributionPill aria-hidden>\n        <Text size={TextSize.XSmall}>{__('Powered by', 'web-stories')}</Text>\n        <CoverrLogo />\n      </AttributionPill>\n    </a>\n  );\n}\n\nexport function TenorAttribution() {\n  return (\n    <a\n      href={tenorUrl}\n      target={'_blank'}\n      rel={'noreferrer'}\n      aria-label={getAriaLabel(MEDIA_PROVIDER.tenor)}\n      tabIndex={-1}\n    >\n      <AttributionPill aria-hidden>\n        <TenorLogo />\n      </AttributionPill>\n    </a>\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/categories/actions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as types from './types';\n\nexport const fetchCategoriesStart =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_CATEGORIES_START,\n      payload: {\n        provider: provider,\n      },\n    });\n  };\n\nexport const fetchCategoriesSuccess =\n  (dispatch) =>\n  ({ provider, categories }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_CATEGORIES_SUCCESS,\n      payload: {\n        provider,\n        categories,\n      },\n    });\n  };\n\nexport const fetchCategoriesError =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_CATEGORIES_ERROR,\n      payload: { provider: provider },\n    });\n  };\n\nexport const selectCategory =\n  (dispatch) =>\n  ({ provider, categoryId }) => {\n    dispatch({\n      type: types.SELECT_CATEGORY,\n      payload: { provider, categoryId },\n    });\n  };\n\nexport const deselectCategory =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.DESELECT_CATEGORY,\n      payload: { provider },\n    });\n  };\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/categories/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as media3pTypes from '../types';\nimport * as types from './types';\n\n/**\n * @typedef {import('./typedefs').CategoriesReducerState} CategoriesReducerState\n */\n\nexport const INITIAL_STATE = {\n  isLoading: true,\n  isLoaded: false,\n  categories: [],\n  selectedCategoryId: undefined,\n};\n\n/**\n * The reducer for the state of a media list pagination.\n *\n * This is called by the reducers for the state nodes:\n * media/local, media/media3p/unsplash, media/media3p/coverr, etc.\n *\n * @param {CategoriesReducerState} state The state to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {CategoriesReducerState} The new state\n */\nfunction reducer(state = INITIAL_STATE, { type, payload }) {\n  switch (type) {\n    case types.FETCH_MEDIA_CATEGORIES_START: {\n      return {\n        ...state,\n        isLoading: true,\n        isLoaded: false,\n      };\n    }\n    case types.FETCH_MEDIA_CATEGORIES_SUCCESS: {\n      const { categories } = payload;\n      return {\n        ...state,\n        categories,\n        isLoading: false,\n        isLoaded: true,\n      };\n    }\n    case types.FETCH_MEDIA_CATEGORIES_ERROR: {\n      return {\n        ...state,\n        isLoading: false,\n        isLoaded: true,\n      };\n    }\n    case types.SELECT_CATEGORY: {\n      const { categoryId } = payload;\n      return {\n        ...state,\n        selectedCategoryId: categoryId,\n      };\n    }\n    case types.DESELECT_CATEGORY: {\n      return {\n        ...state,\n        selectedCategoryId: undefined,\n      };\n    }\n    case media3pTypes.MEDIA3P_SET_SEARCH_TERM: {\n      return {\n        ...state,\n        selectedCategoryId: undefined,\n      };\n    }\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/categories/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport reducer from '../reducer';\nimport useMediaReducer from '../../../useMediaReducer';\nimport * as commonActionsToWrap from '../actions';\n\ndescribe('reducer', () => {\n  it('should assign isLoading=true on fetchCategoriesStart', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.fetchCategoriesStart({ provider: 'unsplash' })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isLoading: true,\n        isLoaded: false,\n      })\n    );\n  });\n\n  it('should assign isLoaded=true on fetchCategoriesSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.fetchCategoriesSuccess({\n        provider: 'unsplash',\n        categories: [\n          {\n            name: 'categories/unsplash:c7USHrQ0Ljw',\n            label: 'COVID-19',\n          },\n        ],\n      })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isLoaded: true,\n        isLoading: false,\n      })\n    );\n  });\n\n  it('should update state on fetchCategoriesSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.fetchCategoriesSuccess({\n        provider: 'unsplash',\n        categories: [\n          {\n            name: 'categories/unsplash:c7USHrQ0Ljw',\n            label: 'COVID-19',\n          },\n        ],\n      })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        categories: [\n          {\n            name: 'categories/unsplash:c7USHrQ0Ljw',\n            label: 'COVID-19',\n          },\n        ],\n      })\n    );\n  });\n\n  it('should assign isLoading=false on fetchCategoriesError', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.fetchCategoriesError({ provider: 'unsplash' })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isLoaded: true,\n        isLoading: false,\n      })\n    );\n  });\n\n  it('should assign category on selectCategory', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.selectCategory({\n        provider: 'unsplash',\n        categoryId: 'categories/unsplash:1',\n      })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        selectedCategoryId: 'categories/unsplash:1',\n      })\n    );\n  });\n\n  it('should unassign category on deselectCategory', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() =>\n      result.current.actions.deselectCategory({ provider: 'unsplash' })\n    );\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        selectedCategoryId: undefined,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/categories/typedefs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Categories action typedef\n *\n * @typedef {(payload: {provider: string}) => undefined} DeselectCategoryFn\n * @typedef {(payload: {provider: string}) => undefined} FetchCategoriesStartFn\n * @typedef {(payload: {provider: string}) => undefined} FetchCategoriesErrorFn\n * @typedef {(payload: {provider: string, categories: Array.<Category>}) =>\n * undefined} FetchCategoriesSuccessFn\n * @typedef {(payload: {provider: string, categoryId: string}) => undefined} SelectCategoryFn\n */\n\n/**\n * @typedef {Object} Category\n * @property {string} id category id\n * @property {string} label the name of the category\n */\n\n/**\n * The categories state returned by the context value.\n *\n * @typedef {Object} CategoriesContextState\n * @property {Array.<Category>} categories array of category objects\n * @property {boolean} isLoading are categories loading\n * @property {boolean} isLoaded are categories loaded\n * @property {string} selectedCategoryId current selected category id\n */\n\n/**\n * The categories used internally by the reducers (i.e. reducerState).\n *\n * @typedef {Object} CategoriesReducerState\n * @property {Array.<Category>} categories array of category objects\n * @property {boolean} isLoading are categories loading\n * @property {boolean} isLoaded are categories loaded\n * @property {string} selectedCategoryId current selected category id\n */\n\n// This is required so that the IDE doesn't ignore this file.\n// Without it the types don't show up when you use {import('./typedefs)}.\nexport default {};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/categories/types.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const FETCH_MEDIA_CATEGORIES_START = 'FETCH_MEDIA_CATEGORIES_START';\nexport const FETCH_MEDIA_CATEGORIES_SUCCESS = 'FETCH_MEDIA_CATEGORIES_SUCCESS';\nexport const FETCH_MEDIA_CATEGORIES_ERROR = 'FETCH_MEDIA_CATEGORIES_ERROR';\nexport const SELECT_CATEGORY = 'SELECT_CATEGORY';\nexport const DESELECT_CATEGORY = 'DESELECT_CATEGORY';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/providerConfiguration.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { ContentType, ProviderType } from '../types';\nimport {\n  CoverrAttribution,\n  TenorAttribution,\n  UnsplashAttribution,\n} from './attribution';\n\n/** @typedef {import('react').React.Component} ReactComponent */\n\n/**\n * @typedef ProviderConfiguration\n * @property {string} displayName The display name of the provider.\n * @property {?ContentType} contentTypeFilter Optional. The content type to filter by.\n * @property {boolean} supportsCategories Whether this provider supports\n * filtering media by category.\n * @property {boolean} requiresAuthorAttribution Whether this provider\n * requires showing author\n * attribution on each media element.\n * @property {function(): ReactComponent} attributionComponent A function that\n * constructs an attribution React Component for this provider.\n * @property {string} fetchMediaErrorMessage An error message to show if\n * fetching media from this provider fails.\n * @property {?string} fetchCategoriesErrorMessage An error message to show if\n * fetching categories from this provider fails. Only needs to be specified if\n * the `supportsCategories` is true.\n */\n\n/**\n * @type {Object.<string, ProviderConfiguration>}\n */\nexport const PROVIDERS = {\n  [ProviderType.Unsplash]: {\n    provider: ProviderType.Unsplash,\n    displayName: __('Images', 'web-stories'),\n    supportsCategories: true,\n    requiresAuthorAttribution: true,\n    attributionComponent: UnsplashAttribution,\n    fetchMediaErrorMessage: sprintf(\n      /* translators: %s: media provider name. */\n      __('Error loading media from %s', 'web-stories'),\n      'Unsplash'\n    ),\n    fetchCategoriesErrorMessage: sprintf(\n      /* translators: %s: media provider name. */\n      __('Error loading categories from %s', 'web-stories'),\n      'Unsplash'\n    ),\n  },\n  [ProviderType.Coverr]: {\n    provider: ProviderType.Coverr,\n    displayName: __('Video', 'web-stories'),\n    supportsCategories: true,\n    requiresAuthorAttribution: false,\n    attributionComponent: CoverrAttribution,\n    fetchMediaErrorMessage: sprintf(\n      /* translators: %s: media provider name. */\n      __('Error loading media from %s', 'web-stories'),\n      'Coverr'\n    ),\n    defaultPreviewWidth: 640,\n  },\n  [ProviderType.Tenor]: {\n    provider: ProviderType.Tenor,\n    displayName: __('GIFs', 'web-stories'),\n    contentTypeFilter: ContentType.Gif,\n    supportsCategories: true,\n    requiresAuthorAttribution: false,\n    attributionComponent: TenorAttribution,\n    fetchMediaErrorMessage: sprintf(\n      /* translators: %s: media provider name. */\n      __('Error loading media from %s', 'web-stories'),\n      'Tenor'\n    ),\n  },\n  [ProviderType.TenorStickers]: {\n    provider: ProviderType.Tenor,\n    displayName: __('Stickers', 'web-stories'),\n    contentTypeFilter: ContentType.Sticker,\n    supportsCategories: true,\n    requiresAuthorAttribution: false,\n    attributionComponent: TenorAttribution,\n    fetchMediaErrorMessage: sprintf(\n      /* translators: %s: media provider name. */\n      __('Error loading media from %s', 'web-stories'),\n      'Tenor'\n    ),\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/providerReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { INITIAL_STATE as COMMON_INITIAL_STATE } from '../pagination/constants';\nimport paginationReducer from '../pagination/reducer';\n\nimport categoriesReducer, {\n  INITIAL_STATE as CATEGORIES_INITIAL_STATE,\n} from './categories/reducer';\nimport * as media3pTypes from './types';\nimport * as categoryTypes from './categories/types';\n\n/**\n * @typedef {import('./typedefs').Media3pProviderReducerState} Media3pProviderReducerState\n */\n\nconst INITIAL_STATE = {\n  ...COMMON_INITIAL_STATE,\n  categories: CATEGORIES_INITIAL_STATE,\n};\n\n/**\n * State reducer for a single 3p media provider.\n *\n * By the time this reducer is called, the provider discriminator will already\n * be evaluated, so the provider-specific `state` passed here will always\n * correspond to the `payload.provider` value.\n *\n * @param {Media3pProviderReducerState} state The state to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {Media3pProviderReducerState} The new state\n */\nfunction providerReducer(state = INITIAL_STATE, { type, payload }) {\n  state = {\n    ...paginationReducer(state, { type, payload }),\n    categories: categoriesReducer(state.categories, { type, payload }),\n  };\n\n  switch (type) {\n    case media3pTypes.MEDIA3P_SET_SEARCH_TERM: {\n      // This action doesn't have a provider in its payload, so effectively\n      // clears out the pageToken and nextPageToken for all providers.\n      return {\n        ...state,\n        isMediaLoaded: false,\n        pageToken: undefined,\n        nextPageToken: undefined,\n      };\n    }\n\n    case categoryTypes.SELECT_CATEGORY: {\n      // This is called only for the provider in the payload, so it clears\n      // out only that provider's pageToken and nextPageToken.\n      return {\n        ...state,\n        pageToken: undefined,\n        nextPageToken: undefined,\n      };\n    }\n\n    case categoryTypes.DESELECT_CATEGORY: {\n      // This is called only for the provider in the payload, so it clears\n      // out only that provider's pageToken and nextPageToken.\n      return {\n        ...state,\n        pageToken: undefined,\n        nextPageToken: undefined,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default providerReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { shallowEqual } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { INITIAL_STATE as INITIAL_STATE_ACTION } from '../types';\nimport * as types from './types';\nimport providerReducer from './providerReducer.js';\nimport { PROVIDERS } from './providerConfiguration';\n\n/**\n * @typedef {import('./typedefs').Media3pReducerState} Media3pReducerState\n */\n\nconst INITIAL_STATE = {\n  selectedProvider: undefined,\n  searchTerm: '',\n};\n\n/**\n * State reducer for all 3p media providers (Unsplash, Coverr etc).\n *\n * For actions that are provider specific, the `payload.provider` attribute\n * is used as the provider discriminator ('unsplash', 'coverr', etc).\n *\n * @param {Media3pReducerState} state The state to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {Media3pReducerState} The new state\n */\nfunction reduceProviderStates(state, { type, payload }) {\n  const result = { ...state };\n  for (const provider of Object.keys(PROVIDERS)) {\n    if (\n      type === INITIAL_STATE_ACTION ||\n      !payload?.provider ||\n      provider === payload?.provider\n    ) {\n      result[provider] = providerReducer(state[provider], { type, payload });\n    }\n  }\n  return !shallowEqual(result, state) ? result : state;\n}\n\n/**\n * State reducer for 3rd party media state.\n *\n * @param {import('./typedefs').Media3pReducerState} state The state to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {import('./typedefs').Media3pReducerState} The new state\n */\nfunction reducer(state = INITIAL_STATE, { type, payload }) {\n  state = reduceProviderStates(state, { type, payload });\n\n  switch (type) {\n    case types.MEDIA3P_SET_SELECTED_PROVIDER: {\n      return {\n        ...state,\n        selectedProvider: payload.provider,\n      };\n    }\n    case types.MEDIA3P_SET_SEARCH_TERM: {\n      return {\n        ...state,\n        searchTerm: payload.searchTerm,\n      };\n    }\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/test/providerReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport providerReducer from '../providerReducer';\nimport useMediaReducer from '../../useMediaReducer';\nimport * as actionsToWrap from '../actions';\nimport * as paginationActionsToWrap from '../../pagination/actions';\nimport * as categoryActionsToWrap from '../categories/actions';\n\ndescribe('providerReducer', () => {\n  it('should assign isMediaLoading=true on fetchMediaStart', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(providerReducer, actionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaStart({\n        provider: 'unsplash',\n        pageToken: 'page2',\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoading: true,\n        isMediaLoaded: false,\n      })\n    );\n  });\n\n  it('should reset {next}pageToken when the search term changes', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(providerReducer, {\n        ...actionsToWrap,\n        ...paginationActionsToWrap,\n      })\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 'page2',\n      });\n    });\n\n    act(() => {\n      result.current.actions.setNextPage({ provider: 'provider' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: true,\n        pageToken: 'page2',\n        nextPageToken: 'page2',\n      })\n    );\n\n    act(() => {\n      result.current.actions.setSearchTerm({ searchTerm: 'lala' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: false,\n        pageToken: undefined,\n        nextPageToken: undefined,\n      })\n    );\n  });\n\n  it('should reset {next}pageToken when the selected category changes', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(providerReducer, {\n        ...actionsToWrap,\n        ...paginationActionsToWrap,\n        ...categoryActionsToWrap,\n      })\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 'page2',\n      });\n    });\n\n    act(() => {\n      result.current.actions.setNextPage({ provider: 'provider' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({ pageToken: 'page2', nextPageToken: 'page2' })\n    );\n\n    act(() => {\n      result.current.actions.selectCategory({ categoryId: 'lala' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        pageToken: undefined,\n        nextPageToken: undefined,\n      })\n    );\n  });\n\n  it('should reset {next}pageToken when the category is deselected', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(providerReducer, {\n        ...actionsToWrap,\n        ...paginationActionsToWrap,\n        ...categoryActionsToWrap,\n      })\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 'page2',\n      });\n    });\n\n    act(() => {\n      result.current.actions.setNextPage({ provider: 'provider' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({ pageToken: 'page2', nextPageToken: 'page2' })\n    );\n\n    act(() => {\n      result.current.actions.deselectCategory({ categoryId: 'lala' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        pageToken: undefined,\n        nextPageToken: undefined,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport media3pReducer from '../reducer';\nimport localReducer from '../../local/reducer';\nimport useMediaReducer from '../../useMediaReducer';\nimport * as media3pActionsToWrap from '../actions';\nimport * as localMediaActionsToWrap from '../../local/actions';\nimport * as types from '../../types';\n\ndescribe('reducer', () => {\n  let initialValue;\n\n  beforeEach(() => {\n    initialValue = media3pReducer(undefined, { type: types.INITIAL_STATE });\n  });\n\n  it('should provide initial state for each provider', () => {\n    expect(initialValue).toStrictEqual(\n      expect.objectContaining({ unsplash: expect.anything() })\n    );\n  });\n\n  it('should reduce each provider state', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(media3pReducer, media3pActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'unsplash',\n        media: [{ id: 'id' }],\n      });\n    });\n\n    expect(result.current.state.unsplash).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: true,\n        isMediaLoading: false,\n      })\n    );\n  });\n\n  it('should assign selectedProvider on setSelectedProvider', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(media3pReducer, media3pActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.setSelectedProvider({ provider: 'unsplash' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        selectedProvider: 'unsplash',\n      })\n    );\n  });\n\n  it('should assign searchTerm on setSearchTerm', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(media3pReducer, media3pActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.setSearchTerm({ searchTerm: 'cats' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: 'cats',\n      })\n    );\n  });\n\n  it('setting local search term does not affect media3p search term', () => {\n    const { result: localMediaResult } = renderHook(() =>\n      useMediaReducer(localReducer, localMediaActionsToWrap)\n    );\n\n    act(() => {\n      localMediaResult.current.actions.setSearchTerm({ searchTerm: 'cats' });\n    });\n\n    const { result: media3pResult } = renderHook(() =>\n      useMediaReducer(media3pReducer, media3pActionsToWrap)\n    );\n\n    expect(localMediaResult.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: 'cats',\n      })\n    );\n    expect(media3pResult.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: '',\n      })\n    );\n  });\n\n  it('setting media3p search term does not affect local search term', () => {\n    const { result: media3pResult } = renderHook(() =>\n      useMediaReducer(media3pReducer, media3pActionsToWrap)\n    );\n\n    act(() => {\n      media3pResult.current.actions.setSearchTerm({ searchTerm: 'cats' });\n    });\n\n    const { result: localMediaResult } = renderHook(() =>\n      useMediaReducer(localReducer, localMediaActionsToWrap)\n    );\n\n    expect(media3pResult.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: 'cats',\n      })\n    );\n\n    expect(localMediaResult.current.state).toStrictEqual(\n      expect.objectContaining({\n        searchTerm: '',\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useContextValueProvider from '../useContextValueProvider';\nimport useProviderContextValueProvider from '../useProviderContextValueProvider';\n\njest.mock('../useProviderContextValueProvider');\n\ndescribe('useContextValueProvider', () => {\n  it('should provide initial state for each provider', () => {\n    useProviderContextValueProvider.mockReturnValueOnce({\n      state: { media: [] },\n    });\n\n    const { result } = renderHook(() =>\n      useContextValueProvider(\n        {\n          selectedProvider: 'unsplash',\n          searchTerm: '',\n          unsplash: {},\n        },\n        { setSelectedProvider: () => {}, setSearchTerm: () => {} }\n      )\n    );\n\n    expect(result.current).toStrictEqual(\n      expect.objectContaining({\n        state: { selectedProvider: 'unsplash', searchTerm: '' },\n        actions: {\n          setSelectedProvider: expect.any(Function),\n          setSearchTerm: expect.any(Function),\n        },\n        unsplash: {\n          state: { media: [] },\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/test/useFetchCategoriesEffect.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useFetchCategoriesEffect from '../useFetchCategoriesEffect';\n\nconst mockListCategories = jest.fn();\n\njest.mock('../api', () => ({\n  useMedia3pApi: () => ({\n    actions: {\n      listCategories: mockListCategories,\n    },\n  }),\n}));\n\nconst mockShowSnackbar = jest.fn();\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: () => ({ showSnackbar: mockShowSnackbar }),\n}));\n\ndescribe('useFetchCategoriesEffect', () => {\n  let fetchCategoriesStart;\n  let fetchCategoriesSuccess;\n  let fetchCategoriesError;\n\n  beforeEach(() => {\n    mockListCategories.mockReset();\n    fetchCategoriesStart = jest.fn();\n    fetchCategoriesSuccess = jest.fn();\n    fetchCategoriesError = jest.fn();\n    mockShowSnackbar.mockReset();\n  });\n\n  function renderUseFetchCategoriesEffect(propertyOverrides) {\n    act(() => {\n      renderHook(() => {\n        useFetchCategoriesEffect({\n          provider: 'unsplash',\n          selectedProvider: 'unsplash',\n          fetchCategoriesStart,\n          fetchCategoriesSuccess,\n          fetchCategoriesError,\n          ...propertyOverrides,\n        });\n      });\n    });\n  }\n\n  it('should fetch categories when the provider is set', async () => {\n    mockListCategories.mockImplementation(() =>\n      Promise.resolve({\n        categories: [\n          {\n            name: 'categories/unsplash:c7USHrQ0Ljw',\n            label: 'COVID-19',\n          },\n        ],\n      })\n    );\n\n    await renderUseFetchCategoriesEffect();\n\n    expect(fetchCategoriesStart.mock.calls).toHaveLength(1);\n    expect(fetchCategoriesStart.mock.calls[0][0]).toStrictEqual(\n      expect.objectContaining({ provider: 'unsplash' })\n    );\n\n    expect(fetchCategoriesSuccess.mock.calls).toHaveLength(1);\n    expect(fetchCategoriesSuccess.mock.calls[0][0]).toStrictEqual(\n      expect.objectContaining({\n        provider: 'unsplash',\n        categories: [\n          {\n            name: 'categories/unsplash:c7USHrQ0Ljw',\n            label: 'COVID-19',\n          },\n        ],\n      })\n    );\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should call fetchCategoriesError if the fetch has failed', async () => {\n    mockListCategories.mockImplementation(() => Promise.reject(new Error()));\n\n    await renderUseFetchCategoriesEffect();\n\n    expect(fetchCategoriesStart.mock.calls).toHaveLength(1);\n    expect(fetchCategoriesSuccess.mock.calls).toHaveLength(0);\n    expect(fetchCategoriesError.mock.calls).toHaveLength(1);\n    expect(mockShowSnackbar).toHaveBeenCalledOnce();\n  });\n\n  it('should not fetch media if the provider is not the same as selected provider', async () => {\n    await renderUseFetchCategoriesEffect({\n      provider: 'coverr',\n      selectedProvider: 'unsplash',\n    });\n    expect(fetchCategoriesStart).not.toHaveBeenCalledOnce();\n    expect(fetchCategoriesSuccess).not.toHaveBeenCalledOnce();\n    expect(fetchCategoriesError).not.toHaveBeenCalledOnce();\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/test/useFetchMediaEffect.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useFetchMediaEffect from '../useFetchMediaEffect';\n\nconst mockListMedia = jest.fn();\n\njest.mock('../api', () => ({\n  useMedia3pApi: () => ({\n    actions: {\n      listMedia: mockListMedia,\n    },\n  }),\n}));\n\nconst mockShowSnackbar = jest.fn();\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: () => ({ showSnackbar: mockShowSnackbar }),\n}));\n\ndescribe('useFetchMediaEffect', () => {\n  let fetchMediaStart;\n  let fetchMediaSuccess;\n  let fetchMediaError;\n  let consoleErrorFn;\n\n  beforeEach(() => {\n    consoleErrorFn = jest.spyOn(console, 'error').mockImplementation(() => {});\n    mockListMedia.mockReset();\n    fetchMediaStart = jest.fn();\n    fetchMediaSuccess = jest.fn();\n    fetchMediaError = jest.fn();\n    mockShowSnackbar.mockReset();\n  });\n\n  afterEach(() => {\n    consoleErrorFn.mockRestore();\n  });\n\n  function renderUseFetchMediaEffect(propertyOverrides) {\n    act(() => {\n      renderHook(() => {\n        useFetchMediaEffect({\n          provider: 'unsplash',\n          selectedProvider: 'unsplash',\n          pageToken: undefined,\n          isMediaLoaded: false,\n          isMediaLoading: false,\n          fetchMediaStart,\n          fetchMediaSuccess,\n          fetchMediaError,\n          ...propertyOverrides,\n        });\n      });\n    });\n  }\n\n  it('should fetch media when the provider is set and not search term', async () => {\n    mockListMedia.mockImplementation(() =>\n      Promise.resolve({ media: [{ id: 1 }], nextPageToken: 'nextPageToken' })\n    );\n\n    await renderUseFetchMediaEffect();\n\n    expect(fetchMediaStart).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      pageToken: undefined,\n    });\n    expect(mockListMedia).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      filter: { searchTerm: undefined },\n      pageToken: undefined,\n    });\n    expect(fetchMediaSuccess).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      media: [{ id: 1 }],\n      nextPageToken: 'nextPageToken',\n      pageToken: undefined,\n    });\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should fetch media when the provider is set and contentType is filtered', async () => {\n    mockListMedia.mockImplementation(() =>\n      Promise.resolve({ media: [{ id: 1 }], nextPageToken: 'nextPageToken' })\n    );\n\n    await renderUseFetchMediaEffect({\n      provider: 'tenor',\n      selectedProvider: 'tenor',\n    });\n\n    expect(fetchMediaStart).toHaveBeenCalledWith({\n      provider: 'tenor',\n      pageToken: undefined,\n    });\n    expect(mockListMedia).toHaveBeenCalledWith({\n      provider: 'tenor',\n      filter: { contentType: 'gif' },\n      pageToken: undefined,\n    });\n    expect(fetchMediaSuccess).toHaveBeenCalledWith({\n      provider: 'tenor',\n      media: [{ id: 1 }],\n      nextPageToken: 'nextPageToken',\n      pageToken: undefined,\n    });\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should fetch media when the provider is set and search term', async () => {\n    mockListMedia.mockImplementation(() =>\n      Promise.resolve({ media: [{ id: 1 }], nextPageToken: 'nextPageToken' })\n    );\n\n    await renderUseFetchMediaEffect({ searchTerm: 'cat' });\n\n    expect(fetchMediaStart).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      pageToken: undefined,\n    });\n    expect(mockListMedia).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      filter: { searchTerm: 'cat' },\n      pageToken: undefined,\n    });\n    expect(fetchMediaSuccess).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      media: [{ id: 1 }],\n      nextPageToken: 'nextPageToken',\n      pageToken: undefined,\n    });\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should fetch media when the provider is set and category id', async () => {\n    mockListMedia.mockImplementation(() =>\n      Promise.resolve({ media: [{ id: 1 }], nextPageToken: 'nextPageToken' })\n    );\n\n    await renderUseFetchMediaEffect({ selectedCategoryId: 'category/1' });\n\n    expect(fetchMediaStart).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      pageToken: undefined,\n    });\n    expect(mockListMedia).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      filter: {\n        searchTerm: null,\n        categoryId: 'category/1',\n      },\n      pageToken: undefined,\n    });\n    expect(fetchMediaSuccess).toHaveBeenCalledWith({\n      provider: 'unsplash',\n      media: [{ id: 1 }],\n      nextPageToken: 'nextPageToken',\n      pageToken: undefined,\n    });\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should call fetchMediaError if the fetch has failed', async () => {\n    mockListMedia.mockImplementation(() => Promise.reject(new Error()));\n\n    await renderUseFetchMediaEffect();\n\n    expect(fetchMediaStart).toHaveBeenCalledOnce();\n    expect(fetchMediaSuccess).not.toHaveBeenCalledWith();\n    expect(fetchMediaError).toHaveBeenCalledOnce();\n    expect(mockShowSnackbar).toHaveBeenCalledOnce();\n  });\n\n  it('should not fetch media if the provider is not the same as selected provider', async () => {\n    await renderUseFetchMediaEffect({\n      provider: 'coverr',\n      selectedProvider: 'unsplash',\n    });\n    expect(fetchMediaStart).not.toHaveBeenCalledOnce();\n    expect(fetchMediaSuccess).not.toHaveBeenCalledOnce();\n    expect(fetchMediaError).not.toHaveBeenCalledOnce();\n    expect(mockShowSnackbar).not.toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/typedefs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {import('../typedefs').Media} Media\n */\n\n/**\n * media3p/[provider] typedefs =================================================\n */\n\n/**\n * @typedef FetchMediaSuccessPayload\n * @property {string} provider media provider name\n * @property {Array.<Media>} media the media that is fetched\n * @property {string} nextPageToken token representing the next page\n * @property {number} totalPages total number of pages\n * @property {string} pageToken the current page token\n */\n\n/**\n * @typedef UpdateMediaElementPayload\n * @property {string} provider media provider name\n * @property {string} id id of the media to update\n * @property {string} posterId poster id\n * @property {string} poster poster\n * @property {number} height height in pixels\n * @property {number} width width in pixels\n * @property {string} alt alt string that describes the media\n */\n\n/**\n * 'media3p/[provider]' action typedefs not specific to any provider.\n *\n * @typedef {(payload: {provider: string, id: string}) => undefined} DeleteMediaElementFn\n * @typedef {(payload: {provider: string}) => undefined} FetchMediaErrorFn\n * @typedef {(payload: {provider: string, pageToken: string}) => undefined} FetchMediaStartFn\n * @typedef {(payload: FetchMediaSuccessPayload) => undefined} FetchMediaSuccessFn\n * @typedef {(payload: {provider: string}) => undefined} SetNextPageFn\n * @typedef {(payload: UpdateMediaElementPayload) => undefined} UpdateMediaElementFn\n */\n\n/**\n * 'media3p/[provider]' actions exposed through context providers\n *\n * @typedef {Object} Media3pProviderContextActions\n * @property {SetNextPageFn} setNextPage action to set next page\n * @property {import('./categories/typedefs').SelectCategoryFn} selectCategory\n * action to select category\n * @property {import('./categories/typedefs').DeselectCategoryFn} deselectCategory\n * action to deselect current category\n */\n\n/**\n * 'media3p/[provider]' state object used by each provider, exposed to the rest\n * of application through context providers.\n *\n * @typedef {Object} Media3pProviderContextState\n * @property {import('./categories/typedefs').CategoriesContextState} categories\n * Category state object\n * @property {boolean} hasMore has more media\n * @property {boolean} isMediaLoaded is media loaded\n * @property {boolean} isMediaLoading is media loading\n * @property {Array.<Media>} media array of media\n * @property {string} pageToken page token for current page\n * @property {string} nextPageToken the page token for the next page\n * @property {number} totalPages total pages\n */\n\n/**\n * 'media3p/[provider]' state object used by each provider internally by the\n * reducer.\n *\n * @typedef {Object} Media3pProviderReducerState\n * @property {import('./categories/typedefs').CategoriesContextState} categories\n * Category state object\n * @property {boolean} hasMore has more media\n * @property {boolean} isMediaLoaded is media loaded\n * @property {boolean} isMediaLoading is media loading\n * @property {Array.<Media>} media array of media\n * @property {string} pageToken page token for current page\n * @property {string} nextPageToken the page token for the next page\n * @property {number} totalPages total pages\n */\n\n/**\n *\n * @typedef {Object} Media3pProviderContext\n * @property {Media3pProviderContextState} state state of a single provider\n * @property {Media3pProviderContextActions} actions actions for the provider\n */\n\n/**\n * media3p/ typedefs ===========================================================\n */\n\n/**\n * 'media3p' root action typedefs.\n *\n * @typedef {(payload: {searchTerm: string}) => undefined} SetSearchTermFn\n * @typedef {(payload: {provider: string}) => undefined} SetSelectedProviderFn\n */\n\n/**\n * 'media3p' root actions in the Media3pContext object.\n *\n * @typedef {Object} Media3pContextActions\n * @property {SetSearchTermFn} setSearchTerm Sets current search term\n * @property {SetSelectedProviderFn} setSelectedProvider Sets provider\n */\n\n/**\n * 'media3p' root state in the Media3pContext object.\n *\n * @typedef {Object} Media3pContextState\n * @property {string} searchTerm search term for media3p\n * @property {string} selectedProvider current selected provider\n * @property {Media3pProviderContextState} unsplash state for Unsplash tab\n * @property {Media3pProviderContextState} coverr state for Coverr tab\n */\n\n/**\n * Context object representing all of media3p's state and actions.\n *\n * @typedef {Object} Media3pContext\n * @property {Media3pContextState} state Non-provider-specific state\n * @property {Media3pContextActions} actions Non-provider-specific actions\n * @property {Media3pProviderContext} unsplash Unsplash state and actions\n * @property {Media3pProviderContext} coverr Coverr state and actions\n */\n\n/**\n * The 'media3p' fragment of the state returned from `useMediaReducer`.\n *\n * @typedef {Object} Media3pReducerState\n * @property {string} searchTerm current search term\n * @property {string} selectedProvider selected provider\n * @property {Media3pProviderReducerState} unsplash state for Unsplash tab\n * @property {Media3pProviderReducerState} coverr state for Coverr tab\n */\n\n/**\n * The 'media3p/[provider]' fragment of the actions returned from\n * `useMediaReducer`.\n *\n * @typedef {Object} Media3pReducerActions\n * @property {DeleteMediaElementFn} deleteMediaElement Action dispatched when media element is deleted\n * @property {import('./categories/typedefs').DeselectCategoryFn} deselectCategory Action dispatched when current category is deselected\n * @property {import('./categories/typedefs').FetchCategoriesStartFn} fetchCategoriesStart Action dispatched when fetching categories starts\n * @property {import('./categories/typedefs').FetchCategoriesErrorFn} fetchCategoriesError Action dispatched when fetching categories returns an error\n * @property {import('./categories/typedefs').FetchCategoriesSuccessFn} fetchCategoriesSuccess Action dispatched when categories fetching is successful\n * @property {FetchMediaErrorFn} fetchMediaError Action dispatched when media fetching returns an error\n * @property {FetchMediaStartFn} fetchMediaStart Action dispatched when media fetching starts\n * @property {FetchMediaSuccessFn} fetchMediaSuccess Action dispatched when media successfully fetched\n * @property {import('./categories/typedefs').SelectCategoryFn} selectCategory Selects current category\n * @property {SetNextPageFn} setNextPage Sets next page token\n * @property {SetSearchTermFn} setSearchTerm Sets search term\n * @property {SetSelectedProviderFn} setSelectedProvider Sets current provider\n * @property {UpdateMediaElementFn} updateMediaElement Updates a media element\n */\n\n// This is required so that the IDE doesn't ignore this file.\n// Without it the types don't show up when you use {import('./typedefs)}.\nexport default {};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const MEDIA3P_SET_SELECTED_PROVIDER = 'MEDIA3P_SET_SELECTED_PROVIDER';\nexport const MEDIA3P_SET_SEARCH_TERM = 'MEDIA3P_SET_SEARCH_TERM';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/useContextValueProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport useProviderContextValueProvider from './useProviderContextValueProvider';\nimport { PROVIDERS } from './providerConfiguration';\n\n/**\n * @typedef {import('./typedefs').Media3pReducerState} Media3pReducerState\n * @typedef {import('./typedefs').Media3pReducerActions} Media3pReducerActions\n * @typedef {import('./typedefs').Media3pContext} Media3pContext\n */\n\nfunction useProviderSetContextValueProvider(reducerState, reducerActions) {\n  const result = {};\n\n  for (const provider of Object.keys(PROVIDERS)) {\n    // eslint-disable-next-line react-hooks/rules-of-hooks -- The 'providers' list is a constant, and so hooks are still called in the same order during a re-render as per rules-of-hooks.\n    result[provider] = useProviderContextValueProvider(\n      provider,\n      reducerState,\n      reducerActions\n    );\n  }\n  return result;\n}\n\n/**\n * Context fragment provider for 3rd party media (Unsplash, Coverr, etc).\n * This is called from MediaProvider to provide the media global state.\n *\n * @param {Media3pReducerState} reducerState The 'media3p'\n * fragment of the state returned from `useMediaReducer`\n * @param {Media3pReducerActions} reducerActions\n * The 'media3p' fragment of the actions returned from `useMediaReducer`\n * @return {Media3pContext} Object containing all context state and actions of\n * media3p.\n */\nexport default function useContextValueProvider(reducerState, reducerActions) {\n  return {\n    state: {\n      selectedProvider: reducerState.selectedProvider,\n      searchTerm: reducerState.searchTerm,\n    },\n    actions: {\n      setSelectedProvider: reducerActions.setSelectedProvider,\n      setSearchTerm: reducerActions.setSearchTerm,\n    },\n    ...useProviderSetContextValueProvider(reducerState, reducerActions),\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\nimport { useSnackbar } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useMedia3pApi } from './api';\nimport { PROVIDERS } from './providerConfiguration';\n\n/**\n * @typedef {Object} FetchCategoriesEffectParams\n * @property {string} provider provider name\n * @property {string} selectedProvider current selected provider\n * @property {Array.<import('./categories/typedefs').Category>} categories list of categories\n * @property {import('./categories/typedefs').FetchCategoriesStartFn} fetchCategoriesStart action dispatched when fetching process starts\n * @property {import('./categories/typedefs').FetchCategoriesSuccessFn} fetchCategoriesSuccess action dispatched when fetching is successful\n * @property {import('./categories/typedefs').FetchCategoriesErrorFn} fetchCategoriesError action dispatched when fetching returns an error\n */\n\n/**\n * The side effect that fetches the media categories from the backend.\n *\n * @param {FetchCategoriesEffectParams} obj required actions and parameters\n */\nexport default function useFetchCategoriesEffect({\n  provider,\n  selectedProvider,\n  categories,\n  fetchCategoriesStart,\n  fetchCategoriesSuccess,\n  fetchCategoriesError,\n}) {\n  const {\n    actions: { listCategories },\n  } = useMedia3pApi();\n\n  const { showSnackbar } = useSnackbar();\n\n  useEffect(() => {\n    async function fetch() {\n      fetchCategoriesStart({ provider });\n      try {\n        const { categories: newCategories } = await listCategories({\n          provider: PROVIDERS[provider].provider,\n        });\n        fetchCategoriesSuccess({ provider, categories: newCategories });\n      } catch {\n        fetchCategoriesError({ provider });\n        showSnackbar({\n          message: PROVIDERS[provider].fetchCategoriesErrorMessage,\n          dismissible: true,\n        });\n      }\n    }\n\n    if (\n      provider === selectedProvider &&\n      PROVIDERS[provider].supportsCategories &&\n      !categories?.length\n    ) {\n      fetch();\n    }\n  }, [\n    showSnackbar,\n    // Fetch categories is triggered by changes to these.\n    selectedProvider,\n    categories,\n    // These attributes never change.\n    provider,\n    listCategories,\n    fetchCategoriesStart,\n    fetchCategoriesSuccess,\n    fetchCategoriesError,\n  ]);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/useFetchMediaEffect.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useMedia3pApi } from './api';\nimport { PROVIDERS } from './providerConfiguration';\n\n/**\n * @typedef {Object} FetchMediaEffectParams\n * @property {string} provider provider name\n * @property {string} selectedProvider selected provider\n * @property {string} searchTerm current search term\n * @property {string} selectedCategoryId current category id\n * @property {string} pageToken current page token\n * @property {boolean} isMediaLoading is the media loading\n * @property {boolean} isMediaLoaded is media loaded\n * @property {import('./typedefs').FetchMediaStartFn} fetchMediaStart oction\n * dispatched when fetch media process starts.\n * @property {import('./typedefs').FetchMediaSuccessFn} fetchMediaSuccess action\n * dispatched when fetching media has been a success\n * @property {import('./typedefs').FetchMediaErrorFn} fetchMediaError action\n * dispatched when fetching media returns an error\n */\n\n/**\n * The side effect that fetches the media from the backend.\n *\n * @param {FetchMediaEffectParams} obj required actions and parameters\n */\nexport default function useFetchMediaEffect({\n  provider,\n  selectedProvider,\n  searchTerm,\n  selectedCategoryId,\n  pageToken,\n  isMediaLoading,\n  isMediaLoaded,\n  fetchMediaStart,\n  fetchMediaSuccess,\n  fetchMediaError,\n}) {\n  const {\n    actions: { listMedia },\n  } = useMedia3pApi();\n\n  const { showSnackbar } = useSnackbar();\n\n  const previousPropsRef = useRef();\n\n  useEffect(() => {\n    // Previous props are read from current, and stored to current after that.\n    // This allows us to get the previous values and compare for changes.\n    const previousProps = previousPropsRef.current;\n    previousPropsRef.current = {\n      pageToken,\n      searchTerm,\n      selectedCategoryId,\n      isMediaLoading,\n      isMediaLoaded,\n    };\n\n    async function fetch() {\n      fetchMediaStart({ provider, pageToken });\n      try {\n        const { media, nextPageToken } = await listMedia({\n          provider: PROVIDERS[provider].provider,\n          filter: {\n            contentType: PROVIDERS[provider].contentTypeFilter,\n            searchTerm: selectedCategoryId ? null : searchTerm,\n            categoryId: selectedCategoryId,\n          },\n          pageToken,\n        });\n        fetchMediaSuccess({\n          provider,\n          media,\n          pageToken,\n          nextPageToken,\n        });\n      } catch (e) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(e);\n        trackError('fetch_media3p', e.message);\n        fetchMediaError({ provider, pageToken });\n        showSnackbar({\n          message: PROVIDERS[provider].fetchMediaErrorMessage,\n          dismissible: true,\n        });\n      }\n    }\n\n    // If we switched provider tab, and we already had loaded a page there, we\n    // don't load media again.\n    const somethingChanged =\n      previousProps &&\n      (pageToken !== previousProps.pageToken ||\n        searchTerm !== previousProps.searchTerm ||\n        selectedCategoryId !== previousProps.selectedCategoryId);\n    const firstFetchOrSomethingChanged =\n      !previousProps ||\n      (!previousProps.isMediaLoading && !previousProps.isMediaLoaded) ||\n      somethingChanged;\n\n    if (provider === selectedProvider && firstFetchOrSomethingChanged) {\n      fetch();\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- We don't want to depend on previousProps, see https://blog.logrocket.com/how-to-get-previous-props-state-with-react-hooks/\n  }, [\n    // Fetch media is triggered by changes to these.\n    selectedProvider,\n    pageToken,\n    searchTerm,\n    selectedCategoryId,\n    // These attributes never change.\n    provider,\n    listMedia,\n    fetchMediaError,\n    fetchMediaStart,\n    fetchMediaSuccess,\n    showSnackbar,\n    previousPropsRef,\n  ]);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/media3p/useProviderContextValueProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useFetchMediaEffect from './useFetchMediaEffect';\nimport useFetchCategoriesEffect from './useFetchCategoriesEffect';\n\n/**\n * @typedef {import('./typedefs').Media3pReducerState} Media3pReducerState\n * @typedef {import('./typedefs').Media3pReducerActions} Media3pReducerActions\n * @typedef {import('./typedefs').Media3pProviderContext} Media3pProviderContext\n */\n\n/**\n * Context fragment provider for a single 3p media source (Unsplash, Coverr,\n * etc).\n *\n * @param {string} provider The 3p provider to return the context value for\n * @param {Media3pReducerState} reducerState\n * The 'media3p/[provider]' fragment of the state returned from\n * `useMediaReducer`\n * @param {Media3pReducerActions} reducerActions\n * The 'media3p/[provider]' fragment of the actions returned from\n * `useMediaReducer`\n * @return {Media3pProviderContext} Context.\n */\nexport default function useProviderContextValueProvider(\n  provider,\n  reducerState,\n  reducerActions\n) {\n  const { selectedProvider, searchTerm } = reducerState;\n  const {\n    pageToken,\n    isMediaLoading,\n    isMediaLoaded,\n    categories: { categories, selectedCategoryId },\n  } = reducerState[provider];\n  const {\n    fetchMediaStart,\n    fetchMediaSuccess,\n    fetchMediaError,\n    fetchCategoriesStart,\n    fetchCategoriesSuccess,\n    fetchCategoriesError,\n  } = reducerActions;\n\n  // Fetch or re-fetch media when the state has changed.\n  useFetchMediaEffect({\n    provider,\n    selectedProvider,\n    pageToken,\n    isMediaLoading,\n    isMediaLoaded,\n    searchTerm,\n    selectedCategoryId,\n    fetchMediaStart,\n    fetchMediaSuccess,\n    fetchMediaError,\n  });\n\n  useFetchCategoriesEffect({\n    provider,\n    selectedProvider,\n    categories,\n    fetchCategoriesStart,\n    fetchCategoriesSuccess,\n    fetchCategoriesError,\n  });\n\n  return {\n    state: reducerState[provider],\n    actions: {\n      setNextPage: useCallback(\n        () => reducerActions.setNextPage({ provider }),\n        [reducerActions, provider]\n      ),\n      selectCategory: useCallback(\n        (categoryId) => reducerActions.selectCategory({ provider, categoryId }),\n        [reducerActions, provider]\n      ),\n      deselectCategory: useCallback(\n        () => reducerActions.deselectCategory({ provider }),\n        [reducerActions, provider]\n      ),\n    },\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/mediaProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport useLocalContextValueProvider from './local/useContextValueProvider';\nimport useMedia3pContextValueProvider from './media3p/useContextValueProvider';\nimport useMediaReducer from './useMediaReducer';\nimport Context from './context';\n\nfunction MediaProvider({ children }) {\n  const { state, actions } = useMediaReducer();\n\n  const local = useLocalContextValueProvider(state.local, actions.local);\n  const media3p = useMedia3pContextValueProvider(\n    state.media3p,\n    actions.media3p\n  );\n\n  const context = { local, media3p };\n  return <Context.Provider value={context}>{children}</Context.Provider>;\n}\n\nMediaProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default MediaProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/pagination/actions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as types from './types';\n\nexport const fetchMediaStart =\n  (dispatch) =>\n  ({ provider, pageToken }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_START,\n      payload: {\n        provider,\n        pageToken,\n      },\n    });\n  };\n\nexport const fetchMediaSuccess =\n  (dispatch) =>\n  ({ provider, media, nextPageToken, totalPages, ...otherProperties }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_SUCCESS,\n      payload: {\n        provider,\n        media,\n        nextPageToken,\n        totalPages,\n        ...otherProperties,\n      },\n    });\n  };\n\nexport const fetchMediaError =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.FETCH_MEDIA_ERROR,\n      payload: { provider },\n    });\n  };\n\nexport const setNextPage =\n  (dispatch) =>\n  ({ provider }) => {\n    dispatch({\n      type: types.SET_NEXT_PAGE,\n      payload: { provider },\n    });\n  };\n\nexport const updateMediaElement =\n  (dispatch) =>\n  ({ provider, id, data }) => {\n    dispatch({\n      type: types.UPDATE_MEDIA_ELEMENT,\n      payload: {\n        provider,\n        id,\n        data,\n      },\n    });\n  };\n\nexport const deleteMediaElement =\n  (dispatch) =>\n  ({ provider, id }) => {\n    dispatch({\n      type: types.DELETE_MEDIA_ELEMENT,\n      payload: {\n        provider,\n        id,\n      },\n    });\n  };\n"
  },
  {
    "path": "packages/story-editor/src/app/media/pagination/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const INITIAL_STATE = {\n  media: [],\n  // The page token of the last loaded page, or undefined if at the first page\n  // or no pages have been loaded.\n  pageToken: undefined,\n  // The page token of the next page, or undefined if at the last page or no\n  // pages have been loaded.\n  nextPageToken: undefined,\n  hasMore: true,\n  totalPages: 1,\n  isMediaLoading: false,\n  isMediaLoaded: false,\n  totalItems: 0,\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/pagination/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as types from './types';\nimport { INITIAL_STATE } from './constants';\n\n/**\n * @typedef {import('../local/typedefs').LocalMediaReducerState} LocalMediaReducerState\n * @typedef {import('../media3p/typedefs').Media3pProviderReducerState} Media3pProviderReducerState\n */\n\n/**\n * The reducer for the state of a media list pagination.\n *\n * This is called by the reducers for the state nodes:\n * media/local, media/media3p/unsplash, media/media3p/coverr, etc.\n *\n * @param {LocalMediaReducerState|Media3pProviderReducerState} state The state\n * to reduce\n * @param {Object} obj An object with the type and payload\n * @param {string} obj.type A constant that identifies the reducer action\n * @param {Object} obj.payload The details of the action, specific to the action\n * @return {LocalMediaReducerState|Media3pProviderReducerState} The new state\n */\nfunction reducer(state = INITIAL_STATE, { type, payload }) {\n  switch (type) {\n    case types.FETCH_MEDIA_START: {\n      return {\n        ...state,\n        isMediaLoaded: false,\n        isMediaLoading: true,\n      };\n    }\n\n    case types.FETCH_MEDIA_SUCCESS: {\n      const { media, pageToken, nextPageToken, totalPages, totalItems } =\n        payload;\n      return {\n        ...state,\n        // If a pageToken is present, append the results.\n        media: pageToken ? [...state.media, ...media] : media,\n        nextPageToken,\n        totalPages,\n        hasMore: Boolean(nextPageToken),\n        isMediaLoaded: true,\n        isMediaLoading: false,\n        totalItems,\n      };\n    }\n\n    case types.FETCH_MEDIA_ERROR: {\n      return {\n        ...state,\n        isMediaLoaded: true,\n        isMediaLoading: false,\n      };\n    }\n\n    case types.SET_NEXT_PAGE: {\n      if (!state.nextPageToken) {\n        return state;\n      }\n      return {\n        ...state,\n        // Updating pageToken state will trigger the media fetch useEffect()\n        // side effect to load the next page.\n        pageToken: state.nextPageToken,\n      };\n    }\n\n    case types.UPDATE_MEDIA_ELEMENT: {\n      const { id, provider, data } = payload;\n\n      const mediaIndex = state.media.findIndex((media) => media.id === id);\n      if (mediaIndex === -1) {\n        return state;\n      }\n\n      const updatedMediaElement = {\n        ...state.media[mediaIndex],\n        provider,\n        ...data,\n      };\n\n      const newMedia = [\n        ...state.media.slice(0, mediaIndex),\n        updatedMediaElement,\n        ...state.media.slice(mediaIndex + 1),\n      ];\n\n      return {\n        ...state,\n        media: newMedia,\n      };\n    }\n\n    case types.DELETE_MEDIA_ELEMENT: {\n      const { id } = payload;\n      return {\n        ...state,\n        media: state.media.filter((media) => media.id !== id),\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/pagination/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport reducer from '../reducer';\nimport useMediaReducer from '../../useMediaReducer';\nimport * as commonActionsToWrap from '../actions';\n\ndescribe('reducer', () => {\n  it('should assign isMediaLoading=true on fetchMediaStart', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaStart({\n        provider: 'provider',\n        pageToken: 2,\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoading: true,\n        isMediaLoaded: false,\n      })\n    );\n  });\n\n  it('should assign isMediaLoaded=true on fetchMediaSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: true,\n        isMediaLoading: false,\n      })\n    );\n  });\n\n  it('should update state on fetchMediaSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 2,\n        totalPages: 10,\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        media: [{ id: 'id' }],\n        pageToken: undefined,\n        nextPageToken: 2,\n        totalPages: 10,\n        hasMore: true,\n      })\n    );\n  });\n\n  it('should append media if there is a pageToken fetchMediaSuccess', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id1' }],\n        nextPageToken: 2,\n        totalPages: 10,\n      });\n    });\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id2' }],\n        pageToken: 2,\n        nextPageToken: 3,\n        totalPages: 10,\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        media: [{ id: 'id1' }, { id: 'id2' }],\n        nextPageToken: 3,\n        totalPages: 10,\n        hasMore: true,\n      })\n    );\n  });\n\n  it(\"should replace media if there isn't a pageToken in fetchMediaSuccess\", () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        media: [{ id: 'id1' }],\n        nextPageToken: 2,\n        totalPages: 10,\n      });\n    });\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        media: [{ id: 'id2' }],\n        nextPageToken: 2,\n        totalPages: 10,\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        media: [{ id: 'id2' }],\n        nextPageToken: 2,\n        totalPages: 10,\n        hasMore: true,\n      })\n    );\n  });\n\n  it('should assign isMediaLoading=false on fetchMediaError', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaError({ provider: 'provider' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({\n        isMediaLoaded: true,\n        isMediaLoading: false,\n      })\n    );\n  });\n\n  it('should update pageToken on setNextPage', () => {\n    const { result } = renderHook(() =>\n      useMediaReducer(reducer, commonActionsToWrap)\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 2,\n      });\n    });\n\n    act(() => {\n      result.current.actions.setNextPage({ provider: 'provider' });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({ pageToken: 2, nextPageToken: 2 })\n    );\n\n    act(() => {\n      result.current.actions.fetchMediaSuccess({\n        provider: 'provider',\n        media: [{ id: 'id' }],\n        nextPageToken: 3,\n      });\n    });\n\n    expect(result.current.state).toStrictEqual(\n      expect.objectContaining({ pageToken: 2, nextPageToken: 3 })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/pagination/types.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const FETCH_MEDIA_START = 'FETCH_MEDIA_START';\nexport const FETCH_MEDIA_SUCCESS = 'FETCH_MEDIA_SUCCESS';\nexport const FETCH_MEDIA_ERROR = 'FETCH_MEDIA_ERROR';\nexport const SET_NEXT_PAGE = 'SET_NEXT_PAGE';\nexport const UPDATE_MEDIA_ELEMENT = 'UPDATE_MEDIA_ELEMENT';\nexport const DELETE_MEDIA_ELEMENT = 'DELETE_MEDIA_ELEMENT';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/test/useMediaReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useMediaReducer from '../useMediaReducer';\n\ndescribe('useMediaReducer', () => {\n  it('should return initial state', () => {\n    const { result } = renderHook(() => useMediaReducer());\n    expect(result.current.state).toStrictEqual({\n      local: expect.objectContaining({ media: [], hasMore: true }),\n      media3p: expect.objectContaining({\n        unsplash: expect.objectContaining({ media: [], hasMore: true }),\n      }),\n    });\n  });\n\n  it('should return actions', () => {\n    const { result } = renderHook(() => useMediaReducer());\n    expect(result.current.actions).toStrictEqual({\n      local: expect.objectContaining({ fetchMediaStart: expect.any(Function) }),\n      media3p: expect.objectContaining({\n        setSelectedProvider: expect.any(Function),\n        fetchMediaStart: expect.any(Function),\n      }),\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/test/useUploadMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { getResourceFromLocalFile } from '../utils';\nimport useUploadMedia from '../useUploadMedia';\n\nconst mockValidateFileForUpload = jest.fn();\n\njest.mock('../../uploader', () => ({\n  useUploader: jest.fn(() => ({\n    actions: {\n      validateFileForUpload: mockValidateFileForUpload,\n    },\n  })),\n}));\n\nconst mockAddItem = jest.fn();\nconst mockRemoveItem = jest.fn();\n\njest.mock('../uploadQueue/useMediaUploadQueue', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    actions: {\n      addItem: mockAddItem,\n      removeItem: mockRemoveItem,\n    },\n    state: {\n      isUploading: false,\n      isTranscoding: false,\n      pending: [],\n      progress: [],\n      uploaded: [],\n      failures: [],\n      finished: [],\n    },\n  })),\n}));\n\nconst mockShowSnackbar = jest.fn();\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn(() => ({\n    showSnackbar: mockShowSnackbar,\n  })),\n}));\n\njest.mock('../../config', () => ({\n  useConfig: jest.fn(() => ({\n    allowedMimeTypes: {\n      image: [],\n      vector: [],\n      video: [],\n      caption: [],\n      audio: [],\n    },\n  })),\n}));\n\njest.mock('../../../app/media/utils');\n\njest.mock('../utils/useFFmpeg', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    isTranscodingEnabled: true,\n    canTranscodeFile: jest.fn(),\n    isFileTooLarge: jest.fn(),\n    transcodeVideo: jest.fn(),\n  })),\n}));\n\nfunction setup() {\n  const media = [\n    { type: 'image/jpeg', src: 'image1.jpg' },\n    { type: 'image/jpeg', src: 'image2.jpg' },\n    { type: 'image/jpeg', src: 'image3.jpg' },\n  ];\n\n  const setMedia = jest.fn();\n\n  const { result } = renderHook(() =>\n    useUploadMedia({\n      media,\n      setMedia,\n    })\n  );\n\n  const { uploadMedia } = result.current;\n  return {\n    uploadMedia,\n    setMedia,\n    media,\n  };\n}\n\nconst supportedLocalResourceTypes = ['image', 'video'];\n\nfunction isLocalResourceSupported(resource) {\n  return supportedLocalResourceTypes.some((type) =>\n    resource.type.startsWith(type)\n  );\n}\n\ndescribe('useUploadMedia', () => {\n  beforeEach(() => {\n    mockShowSnackbar.mockReset();\n    getResourceFromLocalFile.mockReset();\n\n    // Simple implementation of getResourceFromLocalFile that will return\n    // null on unsupported resources.\n    getResourceFromLocalFile.mockImplementation((e) =>\n      isLocalResourceSupported(e) ? e : null\n    );\n  });\n\n  it('bails early if no files are passed', async () => {\n    const { uploadMedia } = setup();\n    await act(() => uploadMedia([]));\n\n    expect(mockAddItem).not.toHaveBeenCalled();\n  });\n\n  it('displays error message if file does not validate for upload', async () => {\n    mockValidateFileForUpload.mockImplementationOnce(() => {\n      throw new Error('Whoopsie');\n    });\n\n    const { uploadMedia, setMedia } = setup();\n\n    const newFiles = [{ type: 'video/mpeg', src: 'video.mpg' }];\n    await act(() => uploadMedia(newFiles));\n\n    expect(setMedia).toHaveBeenCalledTimes(0);\n    expect(mockShowSnackbar).toHaveBeenCalledOnce();\n    expect(mockShowSnackbar).toHaveBeenCalledWith({\n      message: 'Whoopsie',\n      dismissible: true,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/typedefs.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {import('./media3p/typedefs').Media3pContext} Media3pContext\n * @typedef {import('./local/typedefs').LocalMediaContext} LocalMediaContext\n */\n\n/**\n * @typedef SizeData\n * @property {string} file file name\n * @property {number} height height in pixels\n * @property {number} width width in pixels\n * @property {string} mimeType mime type of the file\n * @property {string} sourceUrl the source url\n */\n\n/**\n * How the media is represented inside the state.\n *\n * @typedef Media\n * @property {Object} attribution object describing the attribution\n * @property {string} creationDate date created\n * @property {number} height in pixels\n * @property {number} width in pixels\n * @property {string} id media id\n * @property {number} length length\n * @property {string} lengthFormatted lengthFormatted\n * @property {boolean} local whether the media is a locally uploaded media\n * @property {string} mimeType mimeType\n * @property {string} poster poster\n * @property {string} posterId poster id\n * @property {Object.<string, SizeData>} sizes dictionary representing the\n * different sizes of the media\n * @property {string} src url of media\n * @property {string} title title of media\n * @property {string} type type of media\n */\n\n/**\n * How the media is represented inside the state.\n *\n * @typedef MediaContext\n * @property {Media3pContext} media3p Context state and actions of media3p.\n * @property {LocalMediaContext} local Context state and actions of local media.\n */\n\n// This is required so that the IDE doesn't ignore this file.\n// Without it the types don't show up when you use {import('./typedefs)}.\nexport default {};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { FunctionComponent } from 'react';\nimport type {\n  Resource,\n  ResourceId,\n  TrimData,\n  VideoResource,\n} from '@googleforcreators/media';\nimport type { ElementId } from '@googleforcreators/elements';\n\nexport const INITIAL_STATE = 'INITIAL_STATE';\n\nexport enum ContentType {\n  Image = 'image',\n  Video = 'video',\n  Gif = 'gif',\n  Sticker = 'sticker',\n}\n\nexport enum ProviderType {\n  Unsplash = 'unsplash',\n  Coverr = 'coverr',\n  Tenor = 'tenor',\n  TenorStickers = 'tenor_stickers',\n}\n\nexport type Provider = {\n  provider: ProviderType;\n  displayName: string;\n  contentTypeFilter?: ContentType;\n  supportsCategories: boolean;\n  requiresAuthorAttribution: boolean;\n  attributionComponent: FunctionComponent;\n  fetchMediaErrorMessage: string;\n  fetchCategoriesErrorMessage?: string;\n  defaultPreviewWidth?: number;\n};\n\nexport type Providers = Record<string, Provider>;\n\nexport enum Media3pContentType {\n  Image = 'IMAGE',\n  Video = 'VIDEO',\n  Gif = 'GIF',\n  Sticker = 'STICKER',\n}\n\ntype AbstractMedia3pMedia = {\n  name: string;\n  provider: ProviderType;\n  type: Media3pContentType;\n  author: { displayName: string; url: string };\n  title?: string;\n  description?: string;\n  createTime: string;\n  updateTime?: string;\n  registerUsageUrl: string;\n  color?: string;\n  blurHash?: string;\n};\n\nexport type Media3pStillMedia = AbstractMedia3pMedia & {\n  type: Media3pContentType.Image;\n  imageUrls: ImageUrl[];\n};\n\nexport type Media3pSequenceMedia = AbstractMedia3pMedia & {\n  imageUrls: ImageUrl[];\n  videoUrls: VideoUrl[];\n  videoMetadata: {\n    duration: string;\n  };\n};\n\nexport type Media3pMedia = Media3pStillMedia | Media3pSequenceMedia;\n\nexport type ImageUrl = {\n  imageName?: string;\n  url: string;\n  sourceUrl: string;\n  file: string;\n  mimeType: string;\n  width: number;\n  height: number;\n};\n\nexport type VideoUrl = {\n  url: string;\n  mimeType: string;\n  width: number;\n  height: number;\n  duration: number;\n};\n\nexport type ImageSize = {\n  file: string;\n  sourceUrl: string;\n  mimeType: string;\n  width: number;\n  height: number;\n};\n\nexport type MediaUrls = ImageUrl[] | VideoUrl[];\n\nexport interface ImageSizes {\n  [keyof: string]: ImageSize;\n  web_stories_thumbnail: ImageSize;\n  large: ImageSize;\n  full: ImageSize;\n}\n\nexport type CropParams = {\n  newWidth: number;\n  newHeight: number;\n  cropElement: {\n    x: number;\n    y: number;\n  };\n  cropWidth: number;\n  cropHeight: number;\n  cropX: number;\n  cropY: number;\n};\n\nexport interface UpdateMediaProps {\n  mediaSource?: string;\n  optimizedId?: ResourceId;\n  mutedId?: ResourceId;\n}\n\ninterface UploadMediaAdditionalData {\n  originalId?: ResourceId;\n  isMuted?: boolean;\n  isGif?: boolean;\n  trimData?: TrimData;\n  mediaSource?: string;\n  cropOriginId?: ResourceId;\n  cropParams?: CropParams;\n}\n\nexport interface UploadMediaArgs {\n  onUploadStart?: (args: { resource: Resource }) => unknown;\n  onUploadSuccess?: (args: { id: number; resource: Resource }) => unknown;\n  onUploadProgress?: (args: { resource: Resource }) => unknown;\n  onUploadError?: () => unknown;\n  cropVideo?: boolean;\n  muteVideo?: boolean;\n  additionalData?: UploadMediaAdditionalData;\n  originalResourceId?: ResourceId;\n  resource?: Partial<Resource> | Partial<VideoResource>;\n  storyId?: number | null;\n  altText?: string;\n  mediaSource?: string;\n  posterFile?: File | Blob | null;\n  elementId?: ElementId;\n  trimData?: TrimData;\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/index.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useMediaUploadQueue } from './useMediaUploadQueue';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/reducer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport type {\n  AudioResource,\n  GifResource,\n  ImageResource,\n  VideoResource,\n} from '@googleforcreators/media';\nimport { resourceIs, revokeBlob } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AdditionalData,\n  QueueItem,\n  QueueState,\n  QueueItemId,\n} from './types';\nimport { ItemStatus } from './types';\n\ninterface BaseReducerProps {\n  payload: {\n    id: QueueItemId;\n  };\n}\n\ninterface ReplacePlaceholderResourceProps {\n  payload: {\n    id: QueueItemId;\n    resource: ImageResource | VideoResource | GifResource | AudioResource;\n    posterFile: File | null;\n  };\n}\n\ninterface FinishTrimmingProps {\n  payload: {\n    id: QueueItemId;\n    file: File;\n    additionalData: AdditionalData;\n  };\n}\n\ninterface FinishCroppingProps {\n  payload: {\n    id: QueueItemId;\n    file: File;\n    posterFile?: File;\n    additionalData: AdditionalData;\n  };\n}\n\ninterface FinishMutingProps {\n  payload: {\n    id: QueueItemId;\n    file: File;\n    additionalData: AdditionalData;\n  };\n}\n\ninterface FinishTranscodingProps {\n  payload: {\n    id: QueueItemId;\n    file: File;\n    additionalData?: AdditionalData;\n  };\n}\n\ninterface FinishUploadingProps {\n  payload: {\n    id: QueueItemId;\n    resource: ImageResource | VideoResource | GifResource | AudioResource;\n  };\n}\n\ninterface AddItemProps {\n  payload: QueueItem;\n}\n\ninterface CancelUploadingProps {\n  payload: {\n    id: QueueItemId;\n    error?: Error;\n  };\n}\n\n/**\n * Add an item to the upload queue.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.file File object.\n * @param action.payload.resource Resource object.\n * @param action.payload.onUploadStart Callback for when upload starts.\n * @param action.payload.onUploadProgress Callback for when upload progresses.\n * @param action.payload.onUploadError Callback for when upload errors.\n * @param action.payload.onUploadSuccess Callback for when upload succeeds.\n * @param action.payload.additionalData Additional Data object.\n * @param action.payload.posterFile File object.\n * @param action.payload.muteVideo Whether the video being uploaded should be muted.\n * @param action.payload.cropVideo Whether the video being uploaded should be cropped.\n * @param action.payload.trimData Trim data.\n * @param action.payload.originalResourceId Original resource id.\n * @param action.payload.elementId ID of element on the canvas.\n * @param action.payload.isAnimatedGif Whether the item is an animated GIF.\n * @return New state\n */\nexport function addItem(\n  state: QueueState,\n  {\n    payload: {\n      file,\n      resource,\n      onUploadStart,\n      onUploadProgress,\n      onUploadError,\n      onUploadSuccess,\n      additionalData = {},\n      posterFile,\n      muteVideo,\n      cropVideo,\n      trimData,\n      originalResourceId,\n      elementId,\n      isAnimatedGif,\n    },\n  }: AddItemProps\n) {\n  const id = uuidv4();\n\n  if (!resource.id) {\n    resource.id = uuidv4();\n  }\n\n  if (\n    resourceIs.video(resource) &&\n    resource.isMuted !== null &&\n    additionalData?.isMuted === undefined\n  ) {\n    additionalData.isMuted = resource.isMuted;\n  }\n\n  if ('baseColor' in resource && resource.baseColor) {\n    additionalData.baseColor = resource.baseColor;\n  }\n\n  // Do not copy over BlurHash for new trimmed and cropped videos\n  // since the poster (and thus the BlurHash) might be different.\n  if ('blurHash' in resource && resource.blurHash && !trimData && !cropVideo) {\n    additionalData.blurHash = resource.blurHash;\n  }\n\n  const newItem = {\n    id,\n    file,\n    state: ItemStatus.Pending,\n    resource,\n    onUploadStart,\n    onUploadProgress,\n    onUploadError,\n    onUploadSuccess,\n    additionalData,\n    posterFile,\n    muteVideo,\n    cropVideo,\n    trimData,\n    originalResourceId,\n    elementId,\n    isAnimatedGif,\n  };\n\n  return {\n    ...state,\n    queue: [...state.queue, newItem],\n  };\n}\n\n/**\n * Prepare a file for further processing.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function prepareItem(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Preparing,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Prepare a file for transcoding.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function prepareForTranscoding(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.PendingTranscoding,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Starts uploading a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function startUploading(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Uploading,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Finishes uploading a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.resource Resource object.\n * @return New state\n */\nexport function finishUploading(\n  state: QueueState,\n  { payload: { id, resource } }: FinishUploadingProps\n) {\n  const queueItem = state.queue.find((item) => item.id === id);\n  if (!queueItem) {\n    return state;\n  }\n\n  if (queueItem.resource.src && queueItem.resource.src !== resource.src) {\n    revokeBlob(queueItem.resource.src);\n  }\n\n  if (\n    resourceIs.video(resource) &&\n    resourceIs.video(queueItem.resource) &&\n    resource.poster &&\n    queueItem.resource.poster &&\n    queueItem.resource.poster !== resource.poster\n  ) {\n    revokeBlob(queueItem.resource.poster);\n  }\n\n  return {\n    ...state,\n    queue: state.queue.map((item) => {\n      if (item.id !== id) {\n        return item;\n      }\n\n      let poster;\n      if (resourceIs.video(resource) && resource.poster) {\n        poster = resource.poster;\n      } else if (resourceIs.video(item.resource) && item.resource.poster) {\n        poster = item.resource.poster;\n      }\n\n      return {\n        ...item,\n        resource: {\n          ...resource,\n          // Ensure that we don't override\n          poster,\n        },\n        previousResourceId: item.resource.id,\n        posterFile: null,\n        originalResourceId: null,\n        state: ItemStatus.Uploaded,\n      };\n    }),\n  };\n}\n\n/**\n * Cancels uploading a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function cancelUploading(\n  state: QueueState,\n  { payload: { id, error } }: CancelUploadingProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Cancelled,\n            error,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Starts transcoding a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function startTranscoding(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Transcoding,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Finishes transcoding a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.file New file object.\n * @param action.payload.additionalData Additional data.\n * @return New state\n */\nexport function finishTranscoding(\n  state: QueueState,\n  { payload: { id, file, additionalData = {} } }: FinishTranscodingProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            file,\n            state: ItemStatus.Transcoded,\n            resource: {\n              ...item.resource,\n              isOptimized: true,\n            },\n            additionalData: {\n              ...item.additionalData,\n              ...additionalData,\n            },\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Starts muting a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function startMuting(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Muting,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Finishes muting a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.file New file object.\n * @param action.payload.additionalData Additional data.\n * @return New state\n */\nexport function finishMuting(\n  state: QueueState,\n  { payload: { id, file, additionalData = {} } }: FinishMutingProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            file,\n            state: ItemStatus.Muted,\n            resource: {\n              ...item.resource,\n              isMuted: true,\n            },\n            additionalData: {\n              ...item.additionalData,\n              ...additionalData,\n            },\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Starts cropping a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function startCropping(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Cropping,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Finishes cropping a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.file New file object.\n * @param action.payload.posterFile New poster file object.\n * @param action.payload.additionalData Additional data.\n * @return New state\n */\nexport function finishCropping(\n  state: QueueState,\n  {\n    payload: { id, file, posterFile, additionalData = {} },\n  }: FinishCroppingProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            file,\n            posterFile,\n            state: ItemStatus.Cropped,\n            additionalData: {\n              ...item.additionalData,\n              ...additionalData,\n            },\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Starts trimming a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function startTrimming(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Trimming,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Finishes trimming a file.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.file New file object.\n * @param action.payload.additionalData Additional data.\n * @return New state\n */\nexport function finishTrimming(\n  state: QueueState,\n  { payload: { id, file, additionalData = {} } }: FinishTrimmingProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            file,\n            state: ItemStatus.Trimmed,\n            additionalData: {\n              ...item.additionalData,\n              ...additionalData,\n            },\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Replaces an item's placeholder resource.\n *\n * If the item's resource is not a placeholder, does nothing.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @param action.payload.posterFile Poster file.\n * @param action.payload.resource Resource object.\n * @return New state\n */\nexport function replacePlaceholderResource(\n  state: QueueState,\n  { payload: { id, resource, posterFile } }: ReplacePlaceholderResourceProps\n) {\n  const queueItem = state.queue.find((item) => item.id === id);\n  if (!queueItem || !queueItem.resource.isPlaceholder) {\n    return state;\n  }\n\n  if (queueItem.resource.src !== resource.src) {\n    revokeBlob(queueItem.resource.src);\n  }\n  if (resourceIs.video(queueItem.resource) && queueItem.resource.poster) {\n    revokeBlob(queueItem.resource.poster);\n  }\n\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            resource: {\n              ...resource,\n              // Keep the existing resource's ID (which at this point is a random uuid)\n              // instead of overriding it with another random uuid.\n              id: item.resource.id,\n              isPlaceholder: false,\n            },\n            posterFile,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Mark an item upload as fully finished.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function finishItem(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  return {\n    ...state,\n    queue: state.queue.map((item) =>\n      item.id === id\n        ? {\n            ...item,\n            state: ItemStatus.Finished,\n          }\n        : item\n    ),\n  };\n}\n\n/**\n * Removes an item from the queue.\n *\n * @param state Current state.\n * @param action Action object.\n * @param action.payload Action payload.\n * @param action.payload.id Item ID.\n * @return New state\n */\nexport function removeItem(\n  state: QueueState,\n  { payload: { id } }: BaseReducerProps\n) {\n  const newQueue = state.queue.filter((item: QueueItem) => item.id !== id);\n  return {\n    ...state,\n    queue: newQueue,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/test/reducer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { revokeBlob, ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport {\n  addItem,\n  cancelUploading,\n  finishItem,\n  finishMuting,\n  finishTranscoding,\n  finishTrimming,\n  finishUploading,\n  prepareItem,\n  prepareForTranscoding,\n  replacePlaceholderResource,\n  startMuting,\n  startTranscoding,\n  startTrimming,\n  startUploading,\n} from '../reducer';\nimport { ItemStatus } from '../types';\n\njest.mock('@googleforcreators/media', () => ({\n  ...jest.requireActual('@googleforcreators/media'),\n  revokeBlob: jest.fn(),\n}));\n\ndescribe('useMediaUploadQueue', () => {\n  afterEach(() => {\n    revokeBlob.mockReset();\n  });\n\n  describe('addItem', () => {\n    it('should add item to queue with ID and pending state', () => {\n      const initialState = { queue: [] };\n\n      const result = addItem(initialState, {\n        payload: {\n          file: {},\n          resource: {\n            id: 456,\n            foo: 'bar',\n          },\n          originalResourceId: 789,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          expect.objectContaining({\n            id: expect.any(String),\n            state: ItemStatus.Pending,\n            file: {},\n            originalResourceId: 789,\n            resource: expect.objectContaining({\n              id: 456,\n              foo: 'bar',\n            }),\n            additionalData: {},\n          }),\n        ],\n      });\n    });\n\n    it('sets additionalData.isMuted if possible', () => {\n      const initialState = { queue: [] };\n\n      const result = addItem(initialState, {\n        payload: {\n          file: {},\n          resource: {\n            id: 456,\n            type: 'video',\n            foo: 'bar',\n            isMuted: false,\n          },\n          originalResourceId: 789,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          expect.objectContaining({\n            id: expect.any(String),\n            state: ItemStatus.Pending,\n            file: {},\n            originalResourceId: 789,\n            resource: expect.objectContaining({\n              id: 456,\n              type: 'video',\n              foo: 'bar',\n              isMuted: false,\n            }),\n            additionalData: {\n              isMuted: false,\n            },\n          }),\n        ],\n      });\n    });\n\n    it('sets additionalData.muted.baseColor if possible', () => {\n      const initialState = { queue: [] };\n\n      const result = addItem(initialState, {\n        payload: {\n          file: {},\n          resource: {\n            id: 456,\n            type: 'video',\n            foo: 'bar',\n            baseColor: 'barbaz',\n          },\n          originalResourceId: 789,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          expect.objectContaining({\n            id: expect.any(String),\n            state: ItemStatus.Pending,\n            file: {},\n            originalResourceId: 789,\n            resource: expect.objectContaining({\n              id: 456,\n              type: 'video',\n              foo: 'bar',\n              baseColor: 'barbaz',\n            }),\n            additionalData: {\n              baseColor: 'barbaz',\n            },\n          }),\n        ],\n      });\n    });\n\n    it('sets additionalData.muted.blurHash if possible', () => {\n      const initialState = { queue: [] };\n\n      const result = addItem(initialState, {\n        payload: {\n          file: {},\n          resource: {\n            id: 456,\n            type: 'video',\n            foo: 'bar',\n            blurHash: 'barbaz',\n          },\n          originalResourceId: 789,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          expect.objectContaining({\n            id: expect.any(String),\n            state: ItemStatus.Pending,\n            file: {},\n            originalResourceId: 789,\n            resource: expect.objectContaining({\n              id: 456,\n              type: 'video',\n              foo: 'bar',\n              blurHash: 'barbaz',\n            }),\n            additionalData: {\n              blurHash: 'barbaz',\n            },\n          }),\n        ],\n      });\n    });\n  });\n\n  describe('startUploading', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = startUploading(initialState, {\n        payload: {\n          id: 123,\n          resource: {\n            foo: 'bar',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Uploading,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('finishUploading', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              src: 'foo',\n              poster: 'blob-url',\n            },\n            originalResourceId: 111,\n            state: ItemStatus.Uploading,\n            posterFile: {},\n          },\n        ],\n      };\n\n      const result = finishUploading(initialState, {\n        payload: {\n          id: 123,\n          resource: {\n            id: 789,\n            src: 'bar',\n            type: ResourceType.Video,\n            poster: 'new-url',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            posterFile: null,\n            originalResourceId: null,\n            resource: {\n              id: 789,\n              src: 'bar',\n              type: ResourceType.Video,\n              poster: 'new-url',\n            },\n            previousResourceId: 456,\n            state: ItemStatus.Uploaded,\n          },\n        ],\n      });\n    });\n\n    it('leaves state unchanged if item is not in queue', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Uploading,\n          },\n        ],\n      };\n\n      const result = finishUploading(initialState, {\n        payload: {\n          id: 456,\n        },\n      });\n\n      expect(result).toStrictEqual(initialState);\n    });\n\n    it('revokes previous src blob URL', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n              src: 'blob-url',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      finishUploading(initialState, {\n        payload: {\n          id: 123,\n          resource: {\n            id: 456,\n            bar: 'baz',\n            src: 'new-url',\n          },\n        },\n      });\n      expect(revokeBlob).toHaveBeenCalledWith('blob-url');\n    });\n\n    it('revokes previous poster blob URL', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n              type: ResourceType.Video,\n              poster: 'blob-url',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      finishUploading(initialState, {\n        payload: {\n          id: 123,\n          resource: {\n            id: 456,\n            bar: 'baz',\n            type: ResourceType.Video,\n            poster: 'new-url',\n          },\n        },\n      });\n      expect(revokeBlob).toHaveBeenCalledWith('blob-url');\n    });\n\n    it('keeps existing poster if no new one was provided', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n              type: ResourceType.Video,\n              poster: 'blob-url',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = finishUploading(initialState, {\n        payload: {\n          id: 123,\n          resource: {\n            id: 456,\n            bar: 'baz',\n            type: ResourceType.Video,\n          },\n        },\n      });\n      expect(revokeBlob).not.toHaveBeenCalled();\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              bar: 'baz',\n              type: ResourceType.Video,\n              poster: 'blob-url',\n            },\n            state: ItemStatus.Uploaded,\n            previousResourceId: 456,\n            posterFile: null,\n            originalResourceId: null,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('finishItem', () => {\n    it('changes state of finished item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              src: 'foo',\n            },\n            originalResourceId: 111,\n            state: ItemStatus.Uploaded,\n            posterFile: {},\n          },\n        ],\n      };\n\n      const result = finishItem(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            posterFile: {},\n            resource: {\n              id: 456,\n              src: 'foo',\n            },\n            originalResourceId: 111,\n            state: ItemStatus.Finished,\n          },\n        ],\n      });\n    });\n\n    it('leaves state unchanged if item is not in queue', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Uploaded,\n          },\n        ],\n      };\n\n      const result = finishItem(initialState, {\n        payload: {\n          id: 456,\n        },\n      });\n\n      expect(result).toStrictEqual(initialState);\n    });\n  });\n\n  describe('cancelUploading', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Uploading,\n          },\n        ],\n      };\n\n      const result = cancelUploading(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {},\n            state: ItemStatus.Cancelled,\n            error: undefined,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('startMuting', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = startMuting(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Muting,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('finishMuting', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'baz',\n            },\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            additionalData: {},\n            state: ItemStatus.Muting,\n          },\n        ],\n      };\n\n      const result = finishMuting(initialState, {\n        payload: {\n          id: 123,\n          file: {\n            bar: 'foobar',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'foobar',\n            },\n            resource: {\n              foo: 'bar',\n              id: 456,\n              isMuted: true,\n            },\n            additionalData: {},\n            state: ItemStatus.Muted,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('startTrimming', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = startTrimming(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Trimming,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('finishTrimming', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'baz',\n            },\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            additionalData: {},\n            state: ItemStatus.Trimming,\n          },\n        ],\n      };\n\n      const result = finishTrimming(initialState, {\n        payload: {\n          id: 123,\n          file: {\n            bar: 'foobar',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'foobar',\n            },\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            additionalData: {},\n            state: ItemStatus.Trimmed,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('prepareItem', () => {\n    it('changes state of pending item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = prepareItem(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Preparing,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('prepareForTranscoding', () => {\n    it('changes state of pending item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Preparing,\n          },\n        ],\n      };\n\n      const result = prepareForTranscoding(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.PendingTranscoding,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('startTranscoding', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Pending,\n          },\n        ],\n      };\n\n      const result = startTranscoding(initialState, {\n        payload: {\n          id: 123,\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Transcoding,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('finishTranscoding', () => {\n    it('changes state of uploaded item', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'baz',\n            },\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            additionalData: {},\n            state: ItemStatus.Transcoding,\n          },\n        ],\n      };\n\n      const result = finishTranscoding(initialState, {\n        payload: {\n          id: 123,\n          file: {\n            bar: 'foobar',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual({\n        queue: [\n          {\n            id: 123,\n            file: {\n              bar: 'foobar',\n            },\n            resource: {\n              id: 456,\n              foo: 'bar',\n              isOptimized: true,\n            },\n            additionalData: {},\n            state: ItemStatus.Transcoded,\n          },\n        ],\n      });\n    });\n  });\n\n  describe('replacePlaceholderResource', () => {\n    it('leaves state unchanged if item is not in queue', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n            },\n            state: ItemStatus.Uploading,\n          },\n        ],\n      };\n\n      const result = replacePlaceholderResource(initialState, {\n        payload: {\n          id: 456,\n          resource: {\n            id: 456,\n            foo: 'baz',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual(initialState);\n    });\n\n    it('leaves state unchanged if resource is not a placeholder', () => {\n      const initialState = {\n        queue: [\n          {\n            id: 123,\n            file: {},\n            resource: {\n              id: 456,\n              foo: 'bar',\n              isPlaceholder: false,\n            },\n            state: ItemStatus.Uploading,\n          },\n        ],\n      };\n\n      const result = replacePlaceholderResource(initialState, {\n        payload: {\n          id: 456,\n          resource: {\n            id: 456,\n            foo: 'baz',\n          },\n        },\n      });\n\n      expect(result).toStrictEqual(initialState);\n    });\n  });\n\n  describe('removeItem', () => {});\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/test/useMediaUploadQueue.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport { createResource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useMediaUploadQueue } from '..';\nimport useFFmpeg from '../../utils/useFFmpeg';\nimport useMediaInfo from '../../utils/useMediaInfo';\nimport { ItemStatus } from '../types';\n\nconst canTranscodeFile = (file) => {\n  return ['video/mp4'].includes(file.type);\n};\n\nconst getFileWithSleep = () => {\n  const file = new File(['foo'], 'foo.mp4', {\n    type: 'video/mp4',\n    size: 5000,\n  });\n  return new Promise((res) => setTimeout(() => res(file), 10));\n};\n\njest.mock('../../utils/useFFmpeg', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    isTranscodingEnabled: true,\n    canTranscodeFile,\n    isFileTooLarge: jest.fn(),\n    transcodeVideo: getFileWithSleep,\n    stripAudioFromVideo: getFileWithSleep,\n    trimVideo: getFileWithSleep,\n    getFirstFrameOfVideo: jest.fn(),\n    convertGifToVideo: getFileWithSleep,\n  })),\n}));\n\njest.mock('../../utils/useMediaInfo', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    isConsideredOptimized: jest.fn(() => Promise.resolve(false)),\n  })),\n}));\n\njest.mock('../../utils/heif/useConvertHeif.ts', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    convertHeif: jest.fn(),\n  })),\n}));\n\nconst mockUploadFile = jest.fn().mockImplementation((file) =>\n  Promise.resolve(\n    createResource({\n      id: 123,\n      src: 'http://example.com/file.ext',\n      mimeType: file.type,\n      elementId: 456,\n    })\n  )\n);\n\nconst videoFile = new File(['foo'], 'video.mp4', {\n  type: 'video/mp4',\n  size: 5000,\n});\n\nconst videoResource = createResource({\n  id: 111,\n  src: 'http://example.com/video.mp4',\n  mimeType: 'video/mp4',\n});\n\nconst imageFile = new File(['foo'], 'image.png', {\n  type: 'image/png',\n  size: 5000,\n});\n\nconst imageResource = createResource({\n  id: 222,\n  src: 'http://example.com/image.png',\n  mimeType: 'image/png',\n});\n\nconst gifFile = new File(['foo'], 'animated.gif', {\n  type: 'image/gif',\n  size: 5000,\n});\n\nconst gifResource = createResource({\n  id: 333,\n  src: 'http://example.com/animated.gif',\n  mimeType: 'image/gif',\n});\n\njest.mock('../../../uploader', () => ({\n  useUploader: jest.fn(() => ({\n    actions: {\n      uploadFile: mockUploadFile,\n    },\n    state: {\n      isTranscoding: false,\n    },\n  })),\n}));\n\ndescribe('useMediaUploadQueue', () => {\n  afterEach(() => {\n    useFFmpeg.mockClear();\n    useMediaInfo.mockClear();\n  });\n\n  it('sets initial state for upload queue', async () => {\n    const { result, waitFor } = renderHook(() => useMediaUploadQueue());\n\n    await waitFor(() =>\n      expect(result.current.state).toStrictEqual({\n        pending: [],\n        failures: [],\n        uploaded: [],\n        finished: [],\n        active: [],\n        progress: [],\n        isUploading: false,\n        isTranscoding: false,\n        isMuting: false,\n        isCropping: false,\n        isTrimming: false,\n        isNewResourceMuting: expect.any(Function),\n        isCurrentResourceMuting: expect.any(Function),\n        isNewResourceProcessing: expect.any(Function),\n        isCurrentResourceProcessing: expect.any(Function),\n        isNewResourceTranscoding: expect.any(Function),\n        isCurrentResourceTranscoding: expect.any(Function),\n        isElementTrimming: expect.any(Function),\n        isCurrentResourceTrimming: expect.any(Function),\n        isCurrentResourceUploading: expect.any(Function),\n        canTranscodeResource: expect.any(Function),\n        isBatchUploading: expect.any(Function),\n      })\n    );\n  });\n\n  it('should set isUploading state when adding an item to the queue', async () => {\n    const { result, waitForNextUpdate, waitFor } = renderHook(() =>\n      useMediaUploadQueue()\n    );\n\n    expect(result.current.state.isUploading).toBeFalse();\n\n    act(() =>\n      result.current.actions.addItem({\n        file: imageFile,\n        resource: imageResource,\n      })\n    );\n\n    expect(result.current.state.isUploading).toBeTrue();\n\n    const {\n      resource: { id: resourceId },\n    } = result.current.state.progress[0];\n    expect(\n      result.current.state.isCurrentResourceProcessing(resourceId)\n    ).toBeFalse();\n    expect(\n      result.current.state.isCurrentResourceUploading(resourceId)\n    ).toBeTrue();\n\n    await waitForNextUpdate();\n\n    await waitFor(() => {\n      expect(result.current.state.uploaded).toHaveLength(1);\n    });\n\n    expect(result.current.state.isUploading).toBeTrue();\n\n    const { id } = result.current.state.uploaded[0];\n\n    act(() => result.current.actions.finishItem({ id }));\n\n    expect(result.current.state.isUploading).toBeFalse();\n    expect(result.current.state.uploaded).toHaveLength(0);\n    expect(result.current.state.finished).toHaveLength(1);\n\n    act(() => result.current.actions.removeItem({ id }));\n\n    expect(result.current.state.isUploading).toBeFalse();\n    expect(result.current.state.finished).toHaveLength(0);\n  });\n\n  it('should set isUploading state when adding a gif item to the queue', async () => {\n    const { result, waitFor } = renderHook(() => useMediaUploadQueue());\n\n    expect(result.current.state.isUploading).toBeFalse();\n\n    act(() =>\n      result.current.actions.addItem({\n        file: gifFile,\n        resource: gifResource,\n        isAnimatedGif: true,\n      })\n    );\n\n    await waitFor(() => expect(result.current.state.isTranscoding).toBeTrue());\n    await waitFor(() => {\n      const {\n        resource: { id: resourceId },\n      } = result.current.state.progress[0];\n      expect(\n        result.current.state.isCurrentResourceTranscoding(resourceId)\n      ).toBeTrue();\n    });\n  });\n\n  it('should set isTrancoding state when adding an item to the queue', async () => {\n    const { result, waitFor } = renderHook(() => useMediaUploadQueue());\n\n    expect(result.current.state.isUploading).toBeFalse();\n\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: videoResource,\n      })\n    );\n\n    await waitFor(() => expect(result.current.state.isTranscoding).toBeTrue());\n\n    const {\n      resource: { id: resourceId },\n    } = result.current.state.progress[0];\n\n    expect(\n      result.current.state.isCurrentResourceProcessing(resourceId)\n    ).toBeTrue();\n    expect(\n      result.current.state.isCurrentResourceTranscoding(resourceId)\n    ).toBeTrue();\n\n    expect(result.current.state.isNewResourceProcessing(123)).toBeFalse();\n    expect(result.current.state.isNewResourceTranscoding(123)).toBeFalse();\n  });\n\n  it('should set isMuting state when adding an item to the queue', async () => {\n    const { result, waitFor } = renderHook(() => useMediaUploadQueue());\n\n    expect(result.current.state.isUploading).toBeFalse();\n\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: videoResource,\n        muteVideo: true,\n      })\n    );\n\n    await waitFor(() => expect(result.current.state.isMuting).toBeTrue());\n\n    const {\n      resource: { id: resourceId },\n    } = result.current.state.progress[0];\n\n    expect(\n      result.current.state.isCurrentResourceProcessing(resourceId)\n    ).toBeTrue();\n    expect(result.current.state.isCurrentResourceMuting(resourceId)).toBeTrue();\n\n    expect(result.current.state.isNewResourceProcessing(123)).toBeFalse();\n    expect(result.current.state.isNewResourceMuting(123)).toBeFalse();\n  });\n\n  it('should set isTrimming state when adding an item to the queue', async () => {\n    const { result, waitFor } = renderHook(() => useMediaUploadQueue());\n\n    expect(result.current.state.isUploading).toBeFalse();\n\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: videoResource,\n        trimData: { start: 100 },\n      })\n    );\n\n    await waitFor(() => expect(result.current.state.isTrimming).toBeTrue());\n\n    const {\n      resource: { id: resourceId },\n    } = result.current.state.progress[0];\n\n    expect(\n      result.current.state.isCurrentResourceProcessing(resourceId)\n    ).toBeTrue();\n    expect(\n      result.current.state.isCurrentResourceTrimming(resourceId)\n    ).toBeTrue();\n\n    expect(result.current.state.isNewResourceProcessing(123)).toBeFalse();\n    expect(result.current.state.isElementTrimming(456)).toBeFalse();\n  });\n\n  it('allows removing items from the queue', async () => {\n    const { result, waitFor, waitForNextUpdate } = renderHook(() =>\n      useMediaUploadQueue()\n    );\n\n    act(() =>\n      result.current.actions.addItem({\n        file: imageFile,\n        resource: imageResource,\n      })\n    );\n\n    await waitForNextUpdate();\n\n    expect(result.current.state.failures).toHaveLength(0);\n    expect(result.current.state.uploaded).toHaveLength(1);\n\n    act(() =>\n      result.current.actions.finishItem({\n        id: result.current.state.uploaded[0].id,\n      })\n    );\n\n    expect(result.current.state.finished).toHaveLength(1);\n\n    act(() =>\n      result.current.actions.removeItem({\n        id: result.current.state.finished[0].id,\n      })\n    );\n\n    await waitFor(() =>\n      expect(result.current.state).toStrictEqual({\n        pending: [],\n        failures: [],\n        finished: [],\n        active: [],\n        uploaded: [],\n        progress: [],\n        isUploading: false,\n        isTranscoding: false,\n        isMuting: false,\n        isCropping: false,\n        isTrimming: false,\n        isNewResourceMuting: expect.any(Function),\n        isCurrentResourceMuting: expect.any(Function),\n        isNewResourceProcessing: expect.any(Function),\n        isCurrentResourceProcessing: expect.any(Function),\n        isNewResourceTranscoding: expect.any(Function),\n        isCurrentResourceTranscoding: expect.any(Function),\n        isElementTrimming: expect.any(Function),\n        isCurrentResourceTrimming: expect.any(Function),\n        isCurrentResourceUploading: expect.any(Function),\n        canTranscodeResource: expect.any(Function),\n        isBatchUploading: expect.any(Function),\n      })\n    );\n  });\n\n  it('transcodes files sequentially', async () => {\n    const { result, waitFor, waitForNextUpdate } = renderHook(() =>\n      useMediaUploadQueue()\n    );\n\n    act(() =>\n      result.current.actions.addItem({\n        file: gifFile,\n        resource: gifResource,\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 444 },\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 555 },\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 666 },\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: imageFile,\n        resource: imageResource,\n      })\n    );\n\n    await waitForNextUpdate();\n\n    expect(\n      result.current.state.progress.filter(\n        (item) => item.state === ItemStatus.Transcoding\n      )\n    ).toHaveLength(1);\n\n    await waitForNextUpdate();\n\n    expect(\n      result.current.state.progress.filter(\n        (item) => item.state === ItemStatus.Transcoding\n      )\n    ).toHaveLength(1);\n\n    await waitForNextUpdate();\n\n    await waitFor(() => expect(result.current.state.pending).toHaveLength(0));\n    await waitFor(() => expect(result.current.state.progress).toHaveLength(0));\n    await waitFor(() => expect(result.current.state.uploaded).toHaveLength(5));\n  });\n\n  it('transcodes files sequentially with image first', async () => {\n    const { result, waitFor, waitForNextUpdate } = renderHook(() =>\n      useMediaUploadQueue()\n    );\n\n    act(() =>\n      result.current.actions.addItem({\n        file: imageFile,\n        resource: imageResource,\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: gifFile,\n        resource: gifResource,\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 444 },\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 555 },\n      })\n    );\n    act(() =>\n      result.current.actions.addItem({\n        file: videoFile,\n        resource: { ...videoResource, id: 666 },\n      })\n    );\n\n    await waitForNextUpdate();\n\n    expect(\n      result.current.state.progress.filter(\n        (item) => item.state === ItemStatus.Transcoding\n      )\n    ).toHaveLength(1);\n\n    await waitForNextUpdate();\n\n    expect(\n      result.current.state.progress.filter(\n        (item) => item.state === ItemStatus.Transcoding\n      )\n    ).toHaveLength(1);\n\n    await waitForNextUpdate();\n\n    await waitFor(() => expect(result.current.state.pending).toHaveLength(0));\n    await waitFor(() => expect(result.current.state.progress).toHaveLength(0));\n    await waitFor(() => expect(result.current.state.uploaded).toHaveLength(5));\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type {\n  ImageResource,\n  VideoResource,\n  GifResource,\n  AudioResource,\n  ResourceId,\n  Resource,\n  TrimData,\n} from '@googleforcreators/media';\nimport type { ElementId } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { CropParams } from '../types';\n\nexport enum ItemStatus {\n  Pending = 'PENDING',\n  Preparing = 'PREPARING',\n  PendingTranscoding = 'PENDING_TRANSCODING',\n  Cancelled = 'CANCELLED',\n  Uploaded = 'UPLOADED',\n  Uploading = 'UPLOADING',\n  Transcoded = 'TRANSCODED',\n  Transcoding = 'TRANSCODING',\n  Muting = 'MUTING',\n  Muted = 'MUTED',\n  Cropping = 'CROPPING',\n  Cropped = 'CROPPED',\n  Trimming = 'TRIMMING',\n  Trimmed = 'TRIMMED',\n  Finished = 'FINISHED',\n}\n\nexport type BatchId = string;\n\nexport type AdditionalData = {\n  isMuted?: boolean;\n  cropParams?: CropParams;\n  mediaSource?: string;\n  baseColor?: string;\n  blurHash?: string;\n  batchId?: BatchId;\n  mediaId?: ResourceId;\n};\n\nexport type QueueItemId = string;\n\nexport type QueueItemResource =\n  | ImageResource\n  | VideoResource\n  | GifResource\n  | AudioResource;\n\nexport type QueueItem = {\n  id: QueueItemId;\n  resource: QueueItemResource;\n  originalResourceId?: ResourceId | null;\n  previousResourceId?: ResourceId;\n  state: ItemStatus;\n\n  file: File;\n  posterFile?: File | null;\n  onUploadStart?: (args: { resource: Resource }) => void;\n  onUploadProgress?: (args: { resource: Resource; id: ResourceId }) => void;\n  onUploadError?: (args: { id: ResourceId }) => void;\n  onUploadSuccess?: (args: {\n    resource: Resource;\n    id: ResourceId;\n    batchPosition: number;\n  }) => void;\n\n  additionalData: AdditionalData;\n  elementId: ElementId;\n  trimData?: TrimData;\n  muteVideo?: boolean;\n  cropVideo?: boolean;\n  isAnimatedGif?: boolean;\n  error?: Error;\n};\n\nexport type QueueState = {\n  queue: QueueItem[];\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useReduction,\n  useRef,\n} from '@googleforcreators/react';\nimport {\n  getTimeTracker,\n  trackError,\n  trackEvent,\n} from '@googleforcreators/tracking';\nimport {\n  getExtensionFromMimeType,\n  getFileBasename,\n  blobToFile,\n  createBlob,\n  getImageDimensions,\n  ResourceType,\n  resourceIs,\n  type ResourceId,\n  type ImageResource,\n} from '@googleforcreators/media';\nimport type { ElementId } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useUploader } from '../../uploader';\nimport useUploadVideoFrame from '../utils/useUploadVideoFrame';\nimport useFFmpeg from '../utils/useFFmpeg';\nimport { useConvertHeif } from '../utils/heif';\nimport useMediaInfo from '../utils/useMediaInfo';\nimport getResourceFromLocalFile from '../utils/getResourceFromLocalFile';\nimport { useConfig } from '../../config';\nimport * as reducer from './reducer';\nimport type {\n  BatchId,\n  QueueItem,\n  QueueState,\n  QueueItemResource,\n  QueueItemId,\n} from './types';\nimport { ItemStatus } from './types';\nimport { hasStatus, hasNotStatus } from './utils';\n\nconst initialState: QueueState = {\n  queue: [],\n};\n\n/**\n * Media upload queue implementation.\n *\n * Items added to the queue will start with PENDING state\n * and end up in FINISHED state eventually.\n * Uploading is only considered to be 100% done once\n * a finished item is removed from the queue.\n *\n * A path through the queue could look like this:\n *\n * PENDING -> PREPARING -> PENDING TRANSCODING -> TRANSCODING -> TRANSCODED -> TRIMMING -> TRIMMED -> MUTING -> MUTED -> CROPPING -> CROPPED -> UPLOADING -> UPLOADED -> FINISHED\n *\n * @return Media queue state.\n */\nfunction useMediaUploadQueue() {\n  const {\n    allowedMimeTypes: { image: allowedImageMimeTypes = [] },\n  } = useConfig();\n  const {\n    actions: { uploadFile },\n  } = useUploader();\n  const {\n    isTranscodingEnabled,\n    canTranscodeFile,\n    transcodeVideo,\n    stripAudioFromVideo,\n    getFirstFrameOfVideo,\n    convertGifToVideo,\n    trimVideo,\n    cropVideo: cropResource,\n  } = useFFmpeg();\n  const { isConsideredOptimized } = useMediaInfo();\n  const { convertHeif } = useConvertHeif();\n\n  const [state, actions] = useReduction(initialState, reducer);\n\n  const { uploadVideoPoster } = useUploadVideoFrame({});\n\n  const isMountedRef = useRef(false);\n  const currentTranscodingItem = useRef<QueueItemId | null>(null);\n  const currentPosterGenerationItem = useRef<QueueItemId | null>(null);\n\n  const {\n    prepareItem,\n    prepareForTranscoding,\n    startUploading,\n    finishUploading,\n    cancelUploading,\n    startTranscoding,\n    startMuting,\n    startCropping,\n    startTrimming,\n    finishTranscoding,\n    finishMuting,\n    finishCropping,\n    finishTrimming,\n    replacePlaceholderResource,\n  } = actions;\n\n  // Try to update placeholder resources for freshly transcoded file if still missing.\n  useEffect(() => {\n    void Promise.all(\n      state.queue\n        .filter(\n          hasStatus(\n            ItemStatus.Trimmed,\n            ItemStatus.Muted,\n            ItemStatus.Cropped,\n            ItemStatus.Transcoded\n          )\n        )\n        .map(async ({ id, file, resource }) => {\n          if (\n            !resource.isPlaceholder ||\n            (resourceIs.video(resource) && resource.poster)\n          ) {\n            return;\n          }\n\n          try {\n            const { resource: newResource, posterFile } =\n              await getResourceFromLocalFile(file);\n\n            if (!isMountedRef.current) {\n              return;\n            }\n\n            replacePlaceholderResource({\n              id,\n              resource: newResource,\n              posterFile,\n            });\n          } catch {\n            // Not interested in errors here.\n          }\n        })\n    );\n  }, [state.queue, replacePlaceholderResource]);\n\n  // Try to get dimensions and poster for placeholder resources.\n  // This way we can show something more meaningful to the user before transcoding has finished.\n  // Since this uses ffmpeg, we're going to limit this to one at a time.\n  useEffect(() => {\n    void Promise.all(\n      state.queue\n        .filter(hasStatus(ItemStatus.Pending))\n        .map(async ({ id, file, resource }) => {\n          if (!resource.isPlaceholder) {\n            return;\n          }\n\n          if (!isTranscodingEnabled || !canTranscodeFile(file)) {\n            return;\n          }\n\n          const isAlreadyGeneratingPoster =\n            currentPosterGenerationItem.current !== null;\n\n          // Prevent simultaneous ffmpeg poster generation processes.\n          // See https://github.com/googleforcreators/web-stories-wp/issues/8779\n          if (isAlreadyGeneratingPoster) {\n            return;\n          }\n\n          currentPosterGenerationItem.current = id;\n\n          try {\n            const videoFrame = await getFirstFrameOfVideo(file);\n            const poster = createBlob(videoFrame);\n            const { width, height } = await getImageDimensions(poster);\n            const newResource = {\n              ...resource,\n              poster,\n              width,\n              height,\n            };\n\n            if (!isMountedRef.current) {\n              return;\n            }\n\n            replacePlaceholderResource({\n              id,\n              resource: newResource,\n              posterFile: videoFrame,\n            });\n          } catch {\n            // Not interested in errors here.\n          } finally {\n            currentPosterGenerationItem.current = null;\n          }\n        })\n    );\n  }, [\n    state.queue,\n    isTranscodingEnabled,\n    canTranscodeFile,\n    getFirstFrameOfVideo,\n    replacePlaceholderResource,\n  ]);\n\n  // Convert HEIF images to JPEG if possible.\n  const convertHeifItem = useCallback(\n    async ({ id, file }: QueueItem) => {\n      startTranscoding({ id });\n\n      const type = allowedImageMimeTypes.includes('image/webp')\n        ? 'image/webp'\n        : 'image/jpeg';\n\n      try {\n        const blob = await convertHeif(file, type);\n        const ext = getExtensionFromMimeType(blob.type) || 'jpeg';\n        const fileName = getFileBasename(file) + '.' + ext;\n        const newFile = blobToFile(blob, fileName, type);\n        finishTranscoding({ id, file: newFile });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      }\n    },\n    [\n      convertHeif,\n      startTranscoding,\n      finishTranscoding,\n      cancelUploading,\n      allowedImageMimeTypes,\n    ]\n  );\n\n  // Convert animated GIFs to videos if possible.\n  const convertGifItem = useCallback(\n    async ({ id, file, additionalData }: QueueItem) => {\n      startTranscoding({ id });\n\n      currentTranscodingItem.current = id;\n\n      try {\n        const newFile = await convertGifToVideo(file);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        additionalData.mediaSource = 'gif-conversion';\n        additionalData.isMuted = true;\n        finishTranscoding({ id, file: newFile, additionalData });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        currentTranscodingItem.current = null;\n      }\n    },\n    [startTranscoding, finishTranscoding, convertGifToVideo, cancelUploading]\n  );\n\n  const trimVideoItem = useCallback(\n    async ({ id, file, additionalData, trimData }: QueueItem) => {\n      if (!trimData) {\n        return;\n      }\n\n      startTrimming({ id });\n\n      currentTranscodingItem.current = id;\n\n      try {\n        const { start, end } = trimData;\n        const newFile = await trimVideo(file, start, end);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        finishTrimming({ id, file: newFile, additionalData });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        currentTranscodingItem.current = null;\n      }\n    },\n    [startTrimming, finishTrimming, trimVideo, cancelUploading]\n  );\n\n  const muteVideoItem = useCallback(\n    async ({ id, file, additionalData }: QueueItem) => {\n      startMuting({ id });\n\n      currentTranscodingItem.current = id;\n\n      try {\n        const newFile = await stripAudioFromVideo(file);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        additionalData.isMuted = true;\n        finishMuting({ id, file: newFile, additionalData });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        currentTranscodingItem.current = null;\n      }\n    },\n    [startMuting, finishMuting, stripAudioFromVideo, cancelUploading]\n  );\n\n  const cropVideoItem = useCallback(\n    async ({ id, file, additionalData }: QueueItem) => {\n      if (!additionalData?.cropParams) {\n        return;\n      }\n\n      startCropping({ id });\n\n      currentTranscodingItem.current = id;\n\n      try {\n        const newFile = await cropResource(file, additionalData.cropParams);\n        const posterFile = await getFirstFrameOfVideo(newFile);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        finishCropping({ id, file: newFile, posterFile, additionalData });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        currentTranscodingItem.current = null;\n      }\n    },\n    [\n      startCropping,\n      finishCropping,\n      cropResource,\n      cancelUploading,\n      getFirstFrameOfVideo,\n    ]\n  );\n\n  const optimizeVideoItem = useCallback(\n    async ({ id, file, additionalData }: QueueItem) => {\n      startTranscoding({ id });\n\n      currentTranscodingItem.current = id;\n\n      try {\n        const newFile = await transcodeVideo(file);\n\n        if (!isMountedRef.current) {\n          return;\n        }\n\n        // Do not override pre-existing mediaSource if provided,\n        // for example by media recording.\n        if (!additionalData.mediaSource) {\n          additionalData.mediaSource = 'video-optimization';\n        }\n\n        finishTranscoding({ id, file: newFile, additionalData });\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        currentTranscodingItem.current = null;\n      }\n    },\n    [startTranscoding, finishTranscoding, transcodeVideo, cancelUploading]\n  );\n\n  const uploadVideo = useCallback(\n    async (item: QueueItem) => {\n      const { id, file, resource, additionalData } = item;\n      let { posterFile } = item;\n\n      // The newly uploaded file won't have a poster yet.\n      // However, we'll likely still have one on file.\n      // Add it back so we're never without one.\n      // The final poster will be uploaded later by uploadVideoPoster().\n      let newResource: QueueItemResource = (await uploadFile(\n        file,\n        additionalData\n      )) as QueueItemResource;\n\n      if (!isMountedRef.current) {\n        return;\n      }\n\n      // If we don't have a poster yet (e.g. after converting a GIF),\n      // try to generate one now.\n      if (resourceIs.video(resource) && !resource.poster && !posterFile) {\n        try {\n          posterFile = await getFirstFrameOfVideo(file);\n        } catch {\n          // Not interested in errors here.\n        }\n      }\n      if (newResource.type === ResourceType.Video && posterFile) {\n        try {\n          const { height, width, ...posterResource } = await uploadVideoPoster(\n            newResource.id,\n            posterFile\n          );\n\n          if (!isMountedRef.current) {\n            return;\n          }\n\n          newResource = {\n            ...newResource,\n            ...posterResource,\n          };\n        } catch {\n          // Not interested in errors here.\n        }\n      }\n\n      finishUploading({\n        id,\n        resource: newResource,\n      });\n    },\n    [finishUploading, getFirstFrameOfVideo, uploadFile, uploadVideoPoster]\n  );\n\n  const uploadImage = useCallback(\n    async ({ id, file, additionalData }: QueueItem) => {\n      const resource: ImageResource = (await uploadFile(\n        file,\n        additionalData\n      )) as ImageResource;\n\n      if (!isMountedRef.current) {\n        return;\n      }\n\n      finishUploading({\n        id,\n        resource,\n      });\n    },\n    [finishUploading, uploadFile]\n  );\n\n  const uploadItem = useCallback(\n    async (item: QueueItem) => {\n      const { id, file, resource } = item;\n\n      startUploading({ id });\n\n      void trackEvent('upload_media', {\n        file_size: file?.size,\n        file_type: file?.type,\n      });\n\n      const trackTiming = getTimeTracker('load_upload_media');\n\n      try {\n        if ([ResourceType.Video, ResourceType.Gif].includes(resource.type)) {\n          await uploadVideo(item);\n        } else {\n          await uploadImage(item);\n        }\n      } catch (error) {\n        if (error instanceof Error) {\n          // Cancel uploading if there were any errors.\n          cancelUploading({ id, error });\n          void trackError('upload_media', error.message);\n        }\n      } finally {\n        trackTiming();\n      }\n    },\n    [startUploading, cancelUploading, uploadImage, uploadVideo]\n  );\n\n  // Upload files to server, optionally first transcoding them.\n  useEffect(() => {\n    state.queue.filter(hasStatus(ItemStatus.Pending)).forEach(\n      /**\n       * Uploads a single pending item.\n       */\n      (item) => {\n        void (async () => {\n          const {\n            id,\n            file,\n            resource,\n            isAnimatedGif,\n            muteVideo,\n            cropVideo,\n            trimData,\n          } = item;\n\n          // Changing item state so that an item is never processed twice\n          // in this effect.\n          prepareItem({ id });\n\n          const needsTranscoding =\n            isAnimatedGif ||\n            muteVideo ||\n            cropVideo ||\n            trimData ||\n            file.type === 'image/heic';\n\n          if (needsTranscoding) {\n            prepareForTranscoding({ id });\n            return;\n          }\n\n          const isVideo = file.type.startsWith('video/');\n\n          if (isVideo) {\n            // TODO: Consider always using getFileInfo() to have more accurate audio information.\n\n            if (\n              item.additionalData.mediaSource !== 'recording' &&\n              resourceIs.video(resource) &&\n              (await isConsideredOptimized(resource, file))\n            ) {\n              // Do not override pre-existing mediaSource if provided,\n              // for example by media recording.\n              if (!item.additionalData.mediaSource) {\n                item.additionalData.mediaSource = 'video-optimization';\n              }\n\n              void uploadItem(item);\n\n              return;\n            }\n          }\n\n          if (!isTranscodingEnabled || !canTranscodeFile(file)) {\n            void uploadItem(item);\n\n            return;\n          }\n\n          prepareForTranscoding({ id });\n        })();\n      }\n    );\n  }, [\n    state.queue,\n    prepareItem,\n    prepareForTranscoding,\n    isConsideredOptimized,\n    uploadItem,\n    isTranscodingEnabled,\n    canTranscodeFile,\n  ]);\n\n  // Transcode items sequentially.\n  useEffect(() => {\n    state.queue.filter(hasStatus(ItemStatus.PendingTranscoding)).forEach(\n      /**\n       * Uploads a single pending item.\n       */\n      (item) => {\n        const { muteVideo, cropVideo, trimData, isAnimatedGif } = item;\n\n        if (item.file.type === 'image/heic') {\n          void convertHeifItem(item);\n          return;\n        }\n\n        // Prevent simultaneous transcoding processes for videos.\n        // See https://github.com/googleforcreators/web-stories-wp/issues/8779\n        const isAlreadyTranscoding = currentTranscodingItem.current !== null;\n\n        if (isAlreadyTranscoding) {\n          return;\n        }\n\n        if (isAnimatedGif) {\n          void convertGifItem(item);\n          return;\n        }\n\n        if (trimData) {\n          void trimVideoItem(item);\n          return;\n        }\n\n        if (muteVideo) {\n          void muteVideoItem(item);\n          return;\n        }\n\n        if (cropVideo) {\n          void cropVideoItem(item);\n          return;\n        }\n\n        void optimizeVideoItem(item);\n      }\n    );\n  }, [\n    state.queue,\n    prepareItem,\n    optimizeVideoItem,\n    convertGifItem,\n    trimVideoItem,\n    muteVideoItem,\n    cropVideoItem,\n    convertHeifItem,\n  ]);\n\n  // Upload freshly transcoded files to server.\n  useEffect(() => {\n    state.queue\n      .filter(\n        hasStatus(\n          ItemStatus.Transcoded,\n          ItemStatus.Muted,\n          ItemStatus.Trimmed,\n          ItemStatus.Cropped\n        )\n      )\n      .forEach((item) => void uploadItem(item));\n  }, [state.queue, uploadItem]);\n\n  useEffect(() => {\n    isMountedRef.current = true;\n\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  return useMemo(() => {\n    /**\n     * A list of all in-progress items.\n     */\n    const progress = state.queue.filter(\n      hasNotStatus(\n        ItemStatus.Pending,\n        ItemStatus.Cancelled,\n        ItemStatus.Uploaded,\n        ItemStatus.Finished\n      )\n    );\n\n    /**\n     * A list of all pending items that still have to be uploaded.\n     */\n    const pending = state.queue.filter(hasStatus(ItemStatus.Pending));\n\n    /**\n     * A list of all items that just finished uploading.\n     */\n    const uploaded = state.queue.filter(hasStatus(ItemStatus.Uploaded));\n\n    /**\n     * A list of all items that just finished completely.\n     *\n     * Nothing further is happening.\n     */\n    const finished = state.queue.filter(hasStatus(ItemStatus.Finished));\n\n    /**\n     * A list of all items that are still in the queue and not cancelled.\n     */\n    const active = state.queue.filter(hasNotStatus(ItemStatus.Cancelled));\n\n    /**\n     * A list of all items that failed to upload.\n     */\n    const failures = state.queue.filter(hasStatus(ItemStatus.Cancelled));\n\n    /**\n     * Whether any upload is currently in progress.\n     *\n     * This includes any transcoding/trimming/muting\n     * happening before the actual file upload.\n     */\n    const isUploading = state.queue.some(\n      hasNotStatus(\n        ItemStatus.Finished,\n        ItemStatus.Cancelled,\n        ItemStatus.Pending\n      )\n    );\n\n    /**\n     * Whether any video transcoding is currently in progress.\n     */\n    const isTranscoding = state.queue.some(hasStatus(ItemStatus.Transcoding));\n\n    /**\n     * Whether any video muting is currently in progress.\n     */\n    const isMuting = state.queue.some(hasStatus(ItemStatus.Muting));\n\n    /**\n     * Whether any video cropping is currently in progress.\n     */\n    const isCropping = state.queue.some(hasStatus(ItemStatus.Cropping));\n\n    /**\n     * Whether any video trimming is currently in progress.\n     */\n    const isTrimming = state.queue.some(hasStatus(ItemStatus.Trimming));\n\n    /**\n     * Determine whether a new resource is being processed.\n     *\n     * This is the case when an existing video in a story\n     * is being optimized/muted/trimmed, which will cause\n     * a new resource to be created and uploaded.\n     */\n    const isNewResourceProcessing = (resourceId: ResourceId) =>\n      state.queue\n        .filter(\n          hasStatus(\n            ItemStatus.Transcoding,\n            ItemStatus.Trimming,\n            ItemStatus.Muting,\n            ItemStatus.Cropping\n          )\n        )\n        .some((item) => item.originalResourceId === resourceId);\n\n    /**\n     * Determine whether the current resource is being processed.\n     *\n     * This is the case when uploading a new media item that first\n     * needs to be transcoded/muted/trimmed.\n     */\n    const isCurrentResourceProcessing = (resourceId: ResourceId) =>\n      state.queue\n        .filter(\n          hasStatus(\n            ItemStatus.PendingTranscoding,\n            ItemStatus.Transcoding,\n            ItemStatus.Trimming,\n            ItemStatus.Muting,\n            ItemStatus.Cropping\n          )\n        )\n        .some((item) => item.resource.id === resourceId);\n\n    /**\n     * Determine whether the current resource is being uploaded.\n     *\n     * This is the case when uploading a new media item after any initial\n     * transcoding/muting/trimming has already happened, or when it is\n     * still pending to be processed.\n     *\n     * Checks for both `resource.id` and `previousResourceId`,\n     * since after upload to the backend, the resource's temporary uuid\n     * will be replaced by the permanent ID from the backend.\n     */\n    const isCurrentResourceUploading = (resourceId: ResourceId) =>\n      state.queue\n        .filter(\n          hasStatus(\n            ItemStatus.Pending,\n            ItemStatus.Preparing,\n            ItemStatus.Uploading,\n            ItemStatus.Uploaded,\n            ItemStatus.Finished\n          )\n        )\n        .some(\n          (item) =>\n            item.resource.id === resourceId ||\n            item.previousResourceId === resourceId\n        );\n\n    /**\n     * Determine whether the current resource is being transcoded.\n     *\n     * This is the case when uploading a new media item that first\n     * needs to be transcoded.\n     * This is also the case when optimizing an existing video (\"A\") in the story,\n     * which will cause a new resource (\"B\") to be uploaded.\n     *\n     * Example:\n     *\n     * isNewResourceTranscoding(A) -> true\n     * isCurrentResourceTranscoding(B) -> true\n     * isNewResourceTranscoding(B) -> false\n     * isCurrentResourceTranscoding(A) -> false\n     */\n    const isCurrentResourceTranscoding = (resourceId: ResourceId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Transcoding))\n        .some((item) => item.resource.id === resourceId);\n\n    /**\n     * Determine whether the current resource is being muted.\n     *\n     * This is the case when uploading a new media item that first\n     * needs to be muted.\n     * This is also the case when muting an existing video in the story,\n     * which will cause a new resource to be uploaded (the \"current\" one).\n     */\n    const isCurrentResourceMuting = (resourceId: ResourceId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Muting))\n        .some((item) => item.resource.id === resourceId);\n\n    /**\n     * Determine whether a batch of resources is being uploaded.\n     *\n     * batchId is available when uploading a new array of files\n     *\n     * @param batchId Resource batchId.\n     * @return Whether the batch of resources is uploading.\n     */\n    const isBatchUploading = (batchId: BatchId) => {\n      return state.queue.some(\n        (item) => item.additionalData?.batchId === batchId\n      );\n    };\n\n    /**\n     * Determine whether the current resource is being trimmed.\n     *\n     * This is the case when trimming an existing video in the story,\n     * which will cause a new resource to be uploaded (the \"current\" one).\n     */\n    const isCurrentResourceTrimming = (resourceId: ResourceId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Trimming))\n        .some((item) => item.resource.id === resourceId);\n\n    /**\n     * Determine whether a resource is being transcoded.\n     *\n     * When optimizing an existing video in the story,\n     * which will cause a new resource to be uploaded,\n     * this returns the state of this new resource.\n     */\n    const isNewResourceTranscoding = (resourceId: ResourceId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Transcoding))\n        .some((item) => item.originalResourceId === resourceId);\n\n    /**\n     * Determine whether a resource is being muted.\n     *\n     * When muting an existing video in the story,\n     * which will cause a new resource to be uploaded,\n     * this returns the state of this new resource.\n     */\n    const isNewResourceMuting = (resourceId: ResourceId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Muting))\n        .some((item) => item.originalResourceId === resourceId);\n\n    /**\n     * Whether a given resource can be transcoded.\n     *\n     * Checks whether the resource is not external and\n     * not already uploading.\n     */\n    const canTranscodeResource = (resource?: QueueItemResource) => {\n      if (!resource) {\n        return false;\n      }\n\n      const { isExternal, id, src = '' } = resource;\n\n      return (\n        isExternal === false &&\n        src !== '' &&\n        !state.queue.some(\n          (item) =>\n            item.resource.id === id ||\n            item.previousResourceId === id ||\n            item.originalResourceId === id\n        )\n      );\n    };\n\n    /**\n     * Is a element trimming.\n     *\n     * @param elementId Element ID.\n     * @return if element with id is found.\n     */\n    const isElementTrimming = (elementId: ElementId) =>\n      state.queue\n        .filter(hasStatus(ItemStatus.Trimming))\n        .some((item) => item.elementId === elementId);\n\n    return {\n      state: {\n        progress,\n        pending,\n        uploaded,\n        failures,\n        finished,\n        active,\n        isUploading,\n        isTranscoding,\n        isMuting,\n        isCropping,\n        isTrimming,\n        isCurrentResourceMuting,\n        isCurrentResourceProcessing,\n        isCurrentResourceUploading,\n        isCurrentResourceTranscoding,\n        isCurrentResourceTrimming,\n        isNewResourceMuting,\n        isNewResourceProcessing,\n        isNewResourceTranscoding,\n        isElementTrimming,\n        isBatchUploading,\n        canTranscodeResource,\n      },\n      actions: {\n        addItem: actions.addItem,\n        removeItem: actions.removeItem,\n        finishItem: actions.finishItem,\n      },\n    };\n  }, [state, actions]);\n}\n\nexport default useMediaUploadQueue;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/uploadQueue/utils.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport type { ItemStatus, QueueItem } from './types';\n\nexport function hasStatus(...states: ItemStatus[]) {\n  return ({ state }: QueueItem) => states.includes(state);\n}\n\nexport function hasNotStatus(...states: ItemStatus[]) {\n  return ({ state }: QueueItem) => !states.includes(state);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/useMedia.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\n/**\n * @typedef {import('./typedefs').MediaContext} MediaContext\n */\n\n/**\n * Context value consumer to select a fragment of the entire media context value\n * (local and media3p) that's provided from MediaProvider.\n *\n * @param {function(MediaContext):Object?} selector Returns a fragment of the\n * media context value that the caller is interested in. If no selector is\n * provided then the entire context is selected.\n * @return {Object} The selected context value fragment.\n */\nfunction useMedia(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/useMediaReducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReducer, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport localReducer from './local/reducer';\nimport media3pReducer from './media3p/reducer';\nimport * as localActionsToWrap from './local/actions';\nimport * as media3pActionsToWrap from './media3p/actions';\nimport * as types from './types';\n\n/**\n * @typedef {import('./media3p/typedefs').Media3pContextState} Media3pContextState\n * @typedef {import('./media3p/typedefs').Media3pContextActions} Media3pContextActions\n * @typedef {import('./local/typedefs').LocalMediaContextState} LocalMediaContextState\n * @typedef {import('./local/typedefs').LocalMediaContextActions} LocalMediaContextActions\n */\n\nfunction rootReducer(state = {}, { type, payload }) {\n  return {\n    local: localReducer(state.local, { type, payload }),\n    media3p: media3pReducer(state.media3p, { type, payload }),\n  };\n}\n\nconst wrapWithDispatch = (actionFnOrActionObject, dispatch) => {\n  if (actionFnOrActionObject instanceof Function) {\n    return actionFnOrActionObject(dispatch);\n  }\n\n  const actions = actionFnOrActionObject;\n  return Object.keys(actions).reduce(\n    (collection, action) => ({\n      ...collection,\n      [action]: wrapWithDispatch(actions[action], dispatch),\n    }),\n    {}\n  );\n};\n\n/**\n * Media reducer object used to created the MediaContext\n *\n * @typedef MediaReducer\n * @property {Object} state Reducer state of media3p and local.\n * @property {LocalMediaContextState} state.local local state\n * @property {Media3pContextState} state.media3p media3p state\n * @property {Object} actions Reducer actions of media3p and local.\n * @property {LocalMediaContextActions} actions.local local actions\n * @property {Media3pContextActions} actions.media3p media3p actions\n */\n\n/**\n * The media state reducer and action dispatcher functions.\n *\n * @param {Function} reducer The reducer, which may be overridden for unit\n * testing purposes\n * @param {Object} actionsToWrap The action dispatcher functions, that are\n * wrapped with the `dispatch` function and may be overridden for unit testing\n * purposes\n * @return {MediaReducer} Media reducer object.\n */\nfunction useMediaReducer(reducer = rootReducer, actionsToWrap) {\n  const defaultActionsToWrap = useMemo(\n    () => ({ local: localActionsToWrap, media3p: media3pActionsToWrap }),\n    []\n  );\n  const newActionsToWrap = actionsToWrap ?? defaultActionsToWrap;\n\n  const initialValue = useMemo(\n    () => reducer(undefined, { type: types.INITIAL_STATE }),\n    [reducer]\n  );\n  const [state, dispatch] = useReducer(reducer, initialValue);\n\n  const wrappedActions = useMemo(\n    () => wrapWithDispatch(newActionsToWrap, dispatch),\n    [newActionsToWrap]\n  );\n\n  return {\n    state,\n    actions: wrappedActions,\n  };\n}\n\nexport default useMediaReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/useUploadMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useSnackbar,\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\nimport { isAnimatedGif } from '@googleforcreators/media';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport usePreventWindowUnload from '../../utils/usePreventWindowUnload';\nimport { useUploader } from '../uploader';\nimport { useMediaUploadQueue } from './uploadQueue';\nimport getResourceFromLocalFile from './utils/getResourceFromLocalFile';\nimport useFFmpeg from './utils/useFFmpeg';\n\nconst storageKey = LOCAL_STORAGE_PREFIX.VIDEO_OPTIMIZATION_DIALOG_DISMISSED;\n\n/**\n * Upload media items to the app while displaying the local files in the library.\n *\n * @param {Object} props Props.\n * @param {Array<Object<*>>} props.media Media items.\n * @param {Function} props.prependMedia Action to add new media items.\n * @param {Function} props.updateMediaElement Action to update a media item.\n * @param {Function} props.deleteMediaElement Action to delete a media item.\n * @return {{uploadMedia: Function, isUploading: boolean}} Upload status, and function to upload media.\n */\nfunction useUploadMedia({\n  media,\n  prependMedia,\n  updateMediaElement,\n  deleteMediaElement,\n}) {\n  const {\n    actions: { validateFileForUpload },\n  } = useUploader();\n  const { showSnackbar, removeSnack } = useSnackbar();\n  const setPreventUnload = usePreventWindowUnload();\n  const {\n    state: {\n      isUploading,\n      isTranscoding,\n      pending,\n      progress,\n      uploaded,\n      failures,\n      finished,\n      active,\n      isNewResourceProcessing,\n      isCurrentResourceProcessing,\n      isNewResourceTranscoding,\n      isNewResourceMuting,\n      isElementTrimming,\n      isCurrentResourceUploading,\n      isCurrentResourceTranscoding,\n      isCurrentResourceMuting,\n      isCurrentResourceTrimming,\n      isBatchUploading,\n      canTranscodeResource,\n    },\n    actions: { addItem, removeItem, finishItem },\n  } = useMediaUploadQueue();\n  const { isTranscodingEnabled, canTranscodeFile, isFileTooLarge } =\n    useFFmpeg();\n\n  /**\n   * @type {import('react').MutableRefObject<Array<Object<*>>>} mediaRef Ref for current media items.\n   */\n  const mediaRef = useRef();\n  mediaRef.current = media;\n\n  // Prevent closing the window/tab while upload is in progress.\n  useEffect(() => {\n    setPreventUnload('upload', isUploading);\n  }, [isUploading, setPreventUnload]);\n\n  useEffect(() => {\n    const isDialogDismissed = Boolean(localStore.getItemByKey(storageKey));\n    if (!isDialogDismissed) {\n      return;\n    }\n\n    if (isTranscoding) {\n      showSnackbar({\n        message: __('Optimizing file…', 'web-stories'),\n        dismissible: true,\n        id: 'video-optimization',\n      });\n    } else {\n      removeSnack({\n        id: 'video-optimization',\n      });\n    }\n  }, [isTranscoding, showSnackbar, removeSnack]);\n\n  // Add *new* items to the media library and canvas.\n  useEffect(() => {\n    const newItems = pending.filter(\n      ({ resource: { id: resourceId } }) =>\n        !mediaRef.current.find(({ id }) => id === resourceId)\n    );\n\n    if (!newItems.length) {\n      return;\n    }\n\n    for (const { onUploadStart, resource } of newItems) {\n      if (onUploadStart) {\n        onUploadStart({ resource });\n      }\n    }\n  }, [pending]);\n\n  // Update *existing* items in the media library and on canvas.\n  useEffect(() => {\n    for (const { onUploadProgress, resource } of progress) {\n      const { id: resourceId } = resource;\n\n      if (!resource) {\n        continue;\n      }\n\n      updateMediaElement({\n        id: resourceId,\n        data: resource,\n      });\n\n      if (onUploadProgress) {\n        onUploadProgress({ id: resourceId, resource: resource });\n      }\n    }\n  }, [progress, updateMediaElement]);\n\n  // Handle *processed* items.\n  // Update resources in media library and on canvas.\n  // Caters for both `resource.id` as well as `previousResourceId`,\n  // since after upload to the backend, the resource's temporary uuid\n  // will have been replaced with the permanent ID from the backend.\n  useEffect(() => {\n    for (const {\n      id: itemId,\n      resource,\n      onUploadSuccess,\n      previousResourceId,\n      additionalData,\n    } of uploaded) {\n      const { id: resourceId } = resource;\n      if (!resource) {\n        continue;\n      }\n\n      updateMediaElement({ id: resourceId, data: resource });\n      if (previousResourceId) {\n        updateMediaElement({ id: previousResourceId, data: resource });\n      }\n\n      // onUploadSuccess typically calls postProcessingResource, which\n      // will cause things like base color and BlurHash generation to run\n      // twice for a given resource.\n      if (onUploadSuccess) {\n        onUploadSuccess({\n          id: resourceId,\n          resource: resource,\n          batchPosition: additionalData?.batchPosition,\n        });\n        if (previousResourceId) {\n          onUploadSuccess({\n            id: previousResourceId,\n            resource: resource,\n            batchPosition: additionalData?.batchPosition,\n          });\n        }\n      }\n\n      finishItem({ id: itemId });\n    }\n  }, [uploaded, updateMediaElement, finishItem]);\n\n  // Handle *finished* items.\n  // At this point, uploaded resources have been updated and rendered everywhere,\n  // and no further action is required.\n  // It is safe to remove them from the queue now and *properly* prepend them\n  // to the media library list.\n  useEffect(() => {\n    if (!finished.length) {\n      return;\n    }\n\n    for (const { id } of finished) {\n      removeItem({ id });\n    }\n\n    // Update state in 1 call instead of in the above loop.\n    prependMedia({ media: finished.map(({ resource }) => resource) });\n  }, [finished, removeItem, prependMedia]);\n\n  // Handle *failed* items.\n  // Remove resources from media library and canvas.\n  useEffect(() => {\n    for (const { id: itemId, onUploadError, error, resource } of failures) {\n      const { id: resourceId } = resource;\n\n      if (onUploadError) {\n        onUploadError({ id: resourceId });\n      }\n\n      deleteMediaElement({ id: resourceId });\n      removeItem({ id: itemId });\n\n      const thumbnailSrc =\n        resource && ['video', 'gif'].includes(resource.type)\n          ? resource.poster\n          : resource.src;\n\n      showSnackbar({\n        message:\n          error?.message ||\n          __(\n            'File could not be uploaded. Please try a different file.',\n            'web-stories'\n          ),\n        thumbnail: thumbnailSrc && {\n          src: thumbnailSrc,\n          alt: resource?.alt,\n        },\n        dismissible: true,\n      });\n    }\n  }, [failures, deleteMediaElement, removeItem, showSnackbar]);\n\n  const uploadMedia = useCallback(\n    /**\n     * Upload media callback.\n     *\n     * @param {Array<File>} files Files to upload.\n     * @param {Object} args Additional arguments.\n     * @param {Function} args.onUploadStart Callback for when upload starts.\n     * @param {Function} args.onUploadProgress Callback for when upload progresses.\n     * @param {Function} args.onUploadError Callback for when upload fails.\n     * @param {Function} args.onUploadSuccess Callback for when upload succeeds.\n     * @param {Object} args.additionalData Object of additionalData.\n     * @param {boolean} args.muteVideo If passing a video, should it be muted.\n     * @param {boolean} args.cropVideo If passing a video, should it be cropped.\n     * @param {import('@googleforcreators/media').TrimData} args.trimData Trim data.\n     * @param {import('@googleforcreators/media').Resource} args.resource Resource object.\n     * @param {Blob} args.posterFile Blob object of poster.\n     * @param {number} args.originalResourceId Original resource id.\n     * @param {string} args.elementId ID of element on the canvas.\n     * @return {string|null} Batch ID of the uploaded files on success, null otherwise.\n     */\n    async (\n      files,\n      {\n        onUploadStart,\n        onUploadProgress,\n        onUploadError,\n        onUploadSuccess,\n        additionalData,\n        muteVideo,\n        cropVideo,\n        trimData,\n        resource,\n        posterFile,\n        originalResourceId,\n        elementId,\n      } = {}\n    ) => {\n      // If there are no files passed, don't try to upload.\n      if (!files?.length) {\n        return null;\n      }\n\n      const batchId = uuidv4();\n\n      await Promise.all(\n        files.reverse().map(async (file, index) => {\n          // First, let's make sure the files we're trying to upload are actually valid.\n          // We don't want to display placeholders / progress bars for items that\n          // aren't supported anyway.\n          const canTranscode = isTranscodingEnabled && canTranscodeFile(file);\n          const isTooLarge = canTranscode && isFileTooLarge(file);\n          const isHeic = file.type === 'image/heic';\n\n          try {\n            validateFileForUpload({\n              file,\n              canTranscodeFile: canTranscode || isHeic,\n              isFileTooLarge: isTooLarge,\n            });\n          } catch (e) {\n            showSnackbar({\n              message: e.message,\n              dismissible: true,\n            });\n\n            return;\n          }\n\n          // getResourceFromLocalFile() will work for most files, which allows us\n          // to get the correct image/video dimensions right from the start.\n          // This is important for UX as we can then display resources without\n          // having to update the dimensions later on as the information becomes available.\n          // Downside: it takes a tad longer for the file to initially appear.\n          // Upside: file is displayed with the right dimensions from the beginning.\n          if ((!resource || !posterFile) && !cropVideo) {\n            const { resource: newResource, posterFile: newPosterFile } =\n              await getResourceFromLocalFile(file);\n            posterFile = newPosterFile;\n            resource = newResource;\n          }\n\n          const isGif =\n            resource.mimeType === 'image/gif' &&\n            isAnimatedGif(await file.arrayBuffer());\n\n          // Treat incoming video as a gif if wanted, used by media recording.\n          if (additionalData?.isGif) {\n            resource = {\n              ...resource,\n              type: 'gif',\n              mimeType: 'image/gif',\n              output: {\n                mimeType: resource.mimeType,\n                src: resource.src,\n              },\n            };\n          }\n\n          addItem({\n            file,\n            resource,\n            onUploadStart,\n            onUploadProgress,\n            onUploadError,\n            onUploadSuccess,\n            additionalData: {\n              ...additionalData,\n              batchPosition: files.length - 1 - index,\n              batchId,\n            },\n            posterFile,\n            muteVideo,\n            cropVideo,\n            trimData,\n            originalResourceId,\n            elementId,\n            isAnimatedGif: isGif,\n          });\n        })\n      );\n\n      return batchId;\n    },\n    [\n      showSnackbar,\n      validateFileForUpload,\n      addItem,\n      canTranscodeFile,\n      isTranscodingEnabled,\n      isFileTooLarge,\n    ]\n  );\n\n  return {\n    active,\n    uploadMedia,\n    isUploading,\n    isTranscoding,\n    isNewResourceProcessing,\n    isCurrentResourceProcessing,\n    isNewResourceTranscoding,\n    isNewResourceMuting,\n    isElementTrimming,\n    isCurrentResourceUploading,\n    isCurrentResourceTranscoding,\n    isCurrentResourceMuting,\n    isCurrentResourceTrimming,\n    isBatchUploading,\n    canTranscodeResource,\n  };\n}\n\nexport default useUploadMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/getPosterName.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { MEDIA_POSTER_IMAGE_FILE_TYPE } from '../../../constants';\n\nfunction getPosterName(fileName: string) {\n  return fileName + '-poster.' + MEDIA_POSTER_IMAGE_FILE_TYPE;\n}\n\nexport default getPosterName;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/getResourceFromLocalFile.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  blobToFile,\n  createBlob,\n  createFileReader,\n  createResource,\n  getFileBasename,\n  getImageDimensions,\n  getImageFromVideo,\n  getResourceSize,\n  getTypeFromMime,\n  getVideoLength,\n  hasVideoGotAudio,\n  preloadVideo,\n  seekVideo,\n  ResourceType,\n  type ResourceInput,\n  type ImageResource,\n  type VideoResource,\n} from '@googleforcreators/media';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { MEDIA_POSTER_IMAGE_MIME_TYPE } from '../../../constants';\nimport getPosterName from './getPosterName';\n\n/**\n * Generates a image resource object from a local File object.\n *\n * @param file File object.\n * @return Local image resource object.\n */\nasync function getImageResource(file: File): Promise<ImageResource | null> {\n  const reader: FileReader = await createFileReader(file);\n\n  if (!reader.result) {\n    return null;\n  }\n\n  const mimeType = file.type;\n\n  const src = createBlob(new window.Blob([reader.result], { type: mimeType }));\n  const { width, height } = await getImageDimensions(src);\n\n  const alt = getFileBasename(file);\n\n  return createResource({\n    type: ResourceType.Image,\n    mimeType,\n    src,\n    ...getResourceSize({ width, height }),\n    alt,\n  } as ResourceInput) as ImageResource;\n}\n\n/**\n * Generates a video resource object from a local File object.\n *\n * @param file File object.\n * @return Local video resource object.\n */\nasync function getVideoResource(\n  file: File\n): Promise<{ resource: VideoResource; posterFile: File | null } | null> {\n  const reader = await createFileReader(file);\n\n  if (!reader.result) {\n    return null;\n  }\n\n  const mimeType = file.type;\n\n  const src = createBlob(new Blob([reader.result], { type: mimeType }));\n\n  // Here we are potentially dealing with an unsupported file type (e.g. MOV)\n  // that cannot be *played* by the browser, but could still be used for generating a poster.\n\n  const videoEl = await preloadVideo(src);\n\n  const canPlayVideo = '' !== videoEl.canPlayType(mimeType);\n\n  const { length, lengthFormatted } = getVideoLength(videoEl);\n\n  await seekVideo(videoEl);\n  const hasAudio = videoEl && hasVideoGotAudio(videoEl);\n\n  const posterBlob = videoEl ? await getImageFromVideo(videoEl) : null;\n  const posterFile =\n    posterBlob &&\n    blobToFile(\n      posterBlob,\n      getPosterName(getFileBasename(file)),\n      MEDIA_POSTER_IMAGE_MIME_TYPE\n    );\n  const poster = posterFile ? createBlob(posterFile) : undefined;\n  const { width, height } = poster\n    ? await getImageDimensions(poster)\n    : { width: undefined, height: undefined };\n\n  const alt = getFileBasename(file);\n\n  const resource = createResource({\n    id: uuidv4(),\n    type: ResourceType.Video,\n    mimeType,\n    src: canPlayVideo ? src : '',\n    ...getResourceSize({ width, height }),\n    poster,\n    isMuted: !hasAudio,\n    length,\n    lengthFormatted,\n    alt,\n  }) as VideoResource;\n\n  return { resource, posterFile };\n}\n\nconst createPlaceholderResource = (properties: ResourceInput) => {\n  return createResource({ ...properties, isPlaceholder: true });\n};\n\nconst getPlaceholderResource = (file: File) => {\n  const alt = getFileBasename(file);\n  const type = getTypeFromMime(file.type);\n  const mimeType = type === ResourceType.Image ? 'image/png' : 'video/mp4';\n\n  // The media library requires resources with valid mimeType and dimensions.\n  return createPlaceholderResource({\n    id: uuidv4(),\n    type: type || ResourceType.Image,\n    mimeType: mimeType,\n    src: '',\n    ...getResourceSize({}),\n    alt,\n  });\n};\n\n/**\n * Generates a resource object from a local File object.\n *\n * @param file File object.\n * @return Object containing resource object and poster file.\n */\nasync function getResourceFromLocalFile(file: File) {\n  const type = getTypeFromMime(file.type);\n\n  const fallbackResource = getPlaceholderResource(file);\n  let resource;\n  let posterFile = null;\n\n  try {\n    if (ResourceType.Image === type) {\n      resource = await getImageResource(file);\n    }\n\n    if (ResourceType.Video === type) {\n      const results = await getVideoResource(file);\n      if (results) {\n        resource = results.resource;\n        posterFile = results.posterFile;\n      }\n    }\n  } catch {\n    // Not interested in the error here.\n    // We simply fall back to the placeholder resource.\n  }\n\n  resource ||= fallbackResource;\n\n  resource.id = uuidv4();\n\n  return { resource, posterFile };\n}\n\nexport default getResourceFromLocalFile;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/getResourceFromMedia3p.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createResource,\n  getVideoLengthDisplay,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { PROVIDERS } from '../media3p/providerConfiguration';\n\n/**\n * Author object.\n *\n * @typedef {Object} Author Media3p media author.\n * @property {string} url The url for the asset.\n * @property {?string} imageName A name to identify this particular image url.\n * Currently not being used.\n * @property {number} width The width of this asset.\n * @property {number} height The height of this asset.\n */\n\n/**\n * Converts the image urls in a Media3P Media object to the \"sizes\"\n * object required for a Resource.\n *\n * @param {import('../../../types').Media3pMedia} m The Media3P Media object.\n * @return {Object} The array of \"sizes\"-type objects.\n */\nfunction getImageUrls(m) {\n  // The rest of the application expects 3 named \"sizes\": \"full\", \"large\" and\n  // \"web_stories_thumbnail\". We use the biggest as \"full\", the next biggest\n  // as \"large\", and the smallest as \"web_stories_thumbnail\". The rest are\n  // named according to their size.\n  if (m.imageUrls?.length < 3) {\n    throw new Error('Invalid number of urls for asset. Need at least 3: ' + m);\n  }\n\n  const sizesFromBiggest = sortMediaBySize(m, m.imageUrls);\n\n  const namedSizes = [\n    ['full', sizesFromBiggest[0]],\n    ['large', sizesFromBiggest[1]],\n    ...sizesFromBiggest\n      .slice(2, sizesFromBiggest.length - 1)\n      .map((u) => [u.width + '_' + u.height, u]),\n    ['web_stories_thumbnail', sizesFromBiggest[sizesFromBiggest.length - 1]],\n  ];\n\n  return Object.fromEntries(new Map(namedSizes));\n}\n\n/**\n * Converts the gif urls in a Media3P Media object to the \"sizes\"\n * object required for a resource\n *\n * @param {import('../../../types').Media3pMedia} m The Media3P Media object\n * @return {Object} The array of \"sizes\"-type objects.\n */\nfunction getGifUrls(m) {\n  // The rest of the application expects 3 named \"sizes\": \"full\", \"large\" and\n  // \"web_stories_thumbnail\". We use the biggest as \"full\", the next biggest\n  // as \"large\", and the smallest as \"web_stories_thumbnail\". The rest are\n  // named according to their size.\n  if (m.imageUrls?.length < 3) {\n    throw new Error('Invalid number of urls for asset. Need at least 3: ' + m);\n  }\n\n  const previewUrl = m.imageUrls\n    .filter(({ imageName }) => imageName.endsWith('preview'))\n    .map(({ url }) => url)\n    .shift();\n\n  // Prevents the static preview image from appearing in this list\n  // which should only contain animated GIFs.\n  const imageUrls = m.imageUrls.filter(({ url }) => url !== previewUrl);\n\n  const imageSizesFromBiggest = sortMediaBySize(m, imageUrls);\n  const webmSizes = sortMediaBySize(\n    m,\n    m.videoUrls.filter(({ mimeType }) => mimeType === 'image/webm')\n  );\n  const mp4Sizes = sortMediaBySize(\n    m,\n    m.videoUrls.filter(({ mimeType }) => mimeType === 'video/mp4')\n  );\n\n  const namedSizes = [\n    ['full', imageSizesFromBiggest[0]],\n    ['large', imageSizesFromBiggest[1]],\n    ...imageSizesFromBiggest\n      .slice(2, imageSizesFromBiggest.length - 1)\n      .map((u) => [u.width + '_' + u.height, u]),\n    [\n      'web_stories_thumbnail',\n      imageSizesFromBiggest[imageSizesFromBiggest.length - 1],\n    ],\n  ];\n\n  return {\n    imageUrls: Object.fromEntries(new Map(namedSizes)),\n    videoUrls: {\n      webm: {\n        full: webmSizes[0],\n        preview: webmSizes[webmSizes.length - 1],\n      },\n      mp4: {\n        full: mp4Sizes[0],\n        preview: mp4Sizes[webmSizes.length - 1],\n      },\n    },\n    previewUrl,\n  };\n}\n\n/**\n * Converts the video urls in a Media3P Media object to the \"sizes\"\n * object required for a Resource.\n *\n * @param {import('../../../types').Media3pMedia} m The Media3P Media object.\n * @return {Object} The array of \"sizes\"-type objects.\n */\nfunction getVideoUrls(m) {\n  // The rest of the application expects 2 named \"sizes\": \"full\", and \"preview\"\n  // The highest fidelity is used (videoUrls is ordered by fidelity from the backend)\n  // as \"full\", and the lowest as \"preview\".\n  if (m.videoUrls?.length < 2) {\n    throw new Error('Invalid number of urls for asset. Need at least 2: ' + m);\n  }\n\n  const sizesFromBiggest = sortMediaBySize(m, m.videoUrls);\n\n  return {\n    full: sizesFromBiggest[0],\n    preview: sizesFromBiggest[sizesFromBiggest.length - 1],\n  };\n}\n\nfunction sortMediaBySize(m, mediaUrls) {\n  // https://github.com/GoogleForCreators/web-stories-wp/issues/12083\n  if (mediaUrls.length < 1) {\n    return [];\n  }\n\n  const sortedUrls = mediaUrls.sort((x, y) => (y.width ?? 0) - (x.width ?? 0));\n  const originalSize = getOriginalSize(sortedUrls);\n  return sortedUrls.map((u) =>\n    mediaUrlToImageSizeDescription(m, u, originalSize)\n  );\n}\n\nfunction getOriginalSize(mediaUrls) {\n  return {\n    originalWidth: mediaUrls[0].width,\n    originalHeight: mediaUrls[0].height,\n  };\n}\n\nfunction mediaUrlToImageSizeDescription(media, url, originalSize) {\n  const { originalWidth, originalHeight } = originalSize;\n  if (!originalWidth || !originalHeight) {\n    throw new Error('No original size present.');\n  }\n  const provider = PROVIDERS[media.provider.toLowerCase()];\n  if ((!url.width || !url.height) && !provider.defaultPreviewWidth) {\n    throw new Error('Missing width and height for: ' + media);\n  }\n  return {\n    file: media.name,\n    sourceUrl: url.url,\n    mimeType: url.mimeType,\n    width: url.width ?? provider.defaultPreviewWidth,\n    height:\n      url.height ??\n      (provider.defaultPreviewWidth * originalHeight) / originalWidth,\n  };\n}\n\nfunction getAttributionFromMedia3p(m) {\n  return (\n    (m.author || m.registerUsageUrl) && {\n      author: m.author && {\n        displayName: m.author.displayName,\n        url: m.author.url,\n      },\n      registerUsageUrl: m.registerUsageUrl,\n    }\n  );\n}\n\nfunction getImageResourceFromMedia3p(m) {\n  const imageUrls = getImageUrls(m);\n  return createResource({\n    id: m.name,\n    baseColor: m.color,\n    blurHash: m.blurHash,\n    type: m.type.toLowerCase(),\n    mimeType: imageUrls.full.mimeType,\n    creationDate: m.createTime,\n    src: imageUrls.full.sourceUrl,\n    width: imageUrls.full.width,\n    height: imageUrls.full.height,\n    alt: m.description || m.title || m.name,\n    isExternal: true,\n    isPlaceholder: false,\n    sizes: imageUrls,\n    attribution: getAttributionFromMedia3p(m),\n  });\n}\n\nfunction getVideoResourceFromMedia3p(m) {\n  const videoUrls = getVideoUrls(m);\n  const length = Number.parseInt(m.videoMetadata.duration.replace(/s$/, ''));\n  return createResource({\n    id: m.name,\n    baseColor: m.color,\n    posterId: m.name,\n    type: m.type.toLowerCase(),\n    mimeType: videoUrls.full.mimeType,\n    creationDate: m.createTime,\n    src: videoUrls.full.sourceUrl,\n    width: videoUrls.full.width,\n    height: videoUrls.full.height,\n    poster: m.imageUrls[0].url,\n    length,\n    lengthFormatted: getVideoLengthDisplay(length),\n    alt: m.description || m.title || m.name,\n    isExternal: true,\n    isPlaceholder: false,\n    isOptimized: true,\n    isMuted: true,\n    sizes: videoUrls,\n    attribution: getAttributionFromMedia3p(m),\n  });\n}\n\nfunction getGifResourceFromMedia3p(m) {\n  const { imageUrls, videoUrls, previewUrl } = getGifUrls(m);\n  return createResource({\n    id: m.name,\n    baseColor: m.color,\n    posterId: m.name,\n    type: m.type.toLowerCase(),\n    mimeType: imageUrls.full.mimeType,\n    creationDate: m.createTime,\n    src: imageUrls.full.sourceUrl,\n    width: imageUrls.full.width,\n    height: imageUrls.full.height,\n    poster: previewUrl,\n    alt: m.description || m.title || m.name,\n    isPlaceholder: false,\n    isOptimized: true,\n    isExternal: true,\n    sizes: imageUrls,\n    output: {\n      mimeType: videoUrls.mp4.full.mimeType,\n      src: videoUrls.mp4.full.sourceUrl,\n    },\n    attribution: getAttributionFromMedia3p(m),\n  });\n}\n\nfunction getStickerResourceFromMedia3p(m) {\n  // Animated WebP images are typically larger than GIFs, albeit with\n  // better quality.\n  // For now we prefer lower-quality GIFs, but this can be revisited again in the future.\n  const mWithGifUrlsOnly = {\n    ...m,\n    imageUrls: m.imageUrls.filter((i) => i.mimeType === 'image/gif'),\n  };\n\n  // Not using videos because of transparency.\n  const imageUrls = getImageUrls(mWithGifUrlsOnly);\n  return createResource({\n    id: m.name,\n    baseColor: m.color,\n    blurHash: m.blurHash,\n    type: 'image',\n    mimeType: imageUrls.full.mimeType,\n    creationDate: m.createTime,\n    src: imageUrls.full.sourceUrl,\n    width: imageUrls.full.width,\n    height: imageUrls.full.height,\n    alt: m.description || m.title || m.name,\n    isExternal: true,\n    isPlaceholder: false,\n    sizes: imageUrls,\n    attribution: getAttributionFromMedia3p(m),\n  });\n}\n\n/**\n * Generates a resource object from a Media3P object from the API.\n *\n * @param {import('../../../types').Media3pMedia} m A Media3P Media object.\n * @return {import('@googleforcreators/media').Resource} Resource object.\n */\nexport default function getResourceFromMedia3p(m) {\n  switch (m.type.toLowerCase()) {\n    case 'image':\n      return getImageResourceFromMedia3p(m);\n    case 'video':\n      return getVideoResourceFromMedia3p(m);\n    case 'gif':\n      return getGifResourceFromMedia3p(m);\n    case 'sticker':\n      return getStickerResourceFromMedia3p(m);\n    default:\n      throw new Error('Invalid media type.');\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/getResourceFromUrl.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createResource,\n  getImageDimensions,\n  getTypeFromMime,\n  getVideoLength,\n  hasVideoGotAudio,\n  preloadVideo,\n  type Resource,\n  ResourceType,\n  seekVideo,\n  type VideoResource,\n} from '@googleforcreators/media';\n\ntype ResourceLike = Pick<\n  Resource,\n  'id' | 'src' | 'mimeType' | 'needsProxy' | 'alt'\n> &\n  Partial<Resource> &\n  Partial<VideoResource>;\n\n/**\n * Get a resource from a URL.\n *\n * @param resourceLike Resource-like object.\n * @return Resource object.\n */\nasync function getResourceFromUrl(resourceLike: ResourceLike) {\n  const {\n    src,\n    mimeType,\n    width = 0,\n    height = 0,\n    isMuted,\n    length,\n    lengthFormatted,\n    ...rest\n  } = resourceLike;\n  const type = getTypeFromMime(mimeType);\n\n  if (![ResourceType.Image, ResourceType.Video].includes(type)) {\n    throw new Error('Invalid media type.');\n  }\n\n  const hasDimensions = Boolean(width && height);\n  const videoHasMissingMetadata =\n    !hasDimensions ||\n    isMuted === null ||\n    length === null ||\n    lengthFormatted === null;\n\n  const additionalData: Partial<VideoResource> = {};\n\n  // Only need to fetch metadata if not already provided.\n\n  if (type === ResourceType.Video && videoHasMissingMetadata) {\n    const video = await preloadVideo(src);\n    await seekVideo(video);\n\n    additionalData.width = video.videoWidth;\n    additionalData.height = video.videoHeight;\n\n    const videoLength = getVideoLength(video);\n\n    additionalData.length = videoLength.length;\n    additionalData.lengthFormatted = videoLength.lengthFormatted;\n\n    additionalData.isMuted = !hasVideoGotAudio(video);\n  }\n\n  if (type === ResourceType.Image && !hasDimensions) {\n    const dimensions = await getImageDimensions(src);\n    additionalData.width = dimensions.width;\n    additionalData.height = dimensions.height;\n  }\n\n  return createResource({\n    type,\n    width,\n    height,\n    isMuted,\n    length,\n    lengthFormatted,\n    src,\n    isExternal: true,\n    mimeType,\n    ...rest,\n    ...additionalData,\n  });\n}\n\nexport default getResourceFromUrl;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/heif/index.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useConvertHeif } from './useConvertHeif';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/heif/useConvertHeif.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { bufferToBlob, decodeImage, getDimensions, isHeif } from './utils';\n\nexport default function useConvertHeif() {\n  const convertHeif = useCallback(\n    async (\n      file: File,\n      type?: 'image/jpeg' | 'image/png' | 'image/webp',\n      quality?: number\n    ) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_heic_conversion');\n\n      try {\n        const inputBuffer = await file.arrayBuffer();\n\n        if (!isHeif(inputBuffer)) {\n          throw new TypeError('Not a valid HEIF image');\n        }\n\n        const decoder = new window.libheif.HeifDecoder();\n\n        // Image can have multiple frames, thus it's an array.\n        // For now, only decode the first frame.\n\n        const imagesArr = decoder.decode(inputBuffer);\n\n        if (!imagesArr.length) {\n          throw new TypeError('Not a valid HEIF image');\n        }\n\n        const resultBuffer = await decodeImage(imagesArr[0]);\n        const dimensions = getDimensions(imagesArr[0]);\n\n        let blob = await bufferToBlob(\n          resultBuffer,\n          dimensions.width,\n          dimensions.height,\n          type,\n          quality\n        );\n\n        // Safari does not support WebP and falls back to PNG.\n        // Use JPEG instead of PNG in that case.\n        if (blob && blob.type !== type) {\n          blob = await bufferToBlob(\n            resultBuffer,\n            dimensions.width,\n            dimensions.height,\n            'image/jpeg',\n            quality\n          );\n        }\n\n        if (!blob) {\n          throw new Error('HEIF processing error');\n        }\n\n        return blob;\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('heif_conversion', err.message);\n        }\n\n        throw err;\n      } finally {\n        trackTiming();\n      }\n    },\n    []\n  );\n\n  return { convertHeif };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/heif/utils.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DecodeResult } from 'libheif-js';\nimport { getCanvasBlob } from '@googleforcreators/media';\n\nexport function isHeif(buffer: ArrayBuffer) {\n  const fourCC = String.fromCharCode(\n    ...Array.from(new Uint8Array(buffer.slice(8, 12)))\n  );\n\n  const validFourCC = [\n    'mif1', // .heic / image/heif\n    'msf1', // .heic / image/heif-sequence\n    'heic', // .heic / image/heic\n    'heix', // .heic / image/heic\n    'hevc', // .heic / image/heic-sequence\n    'hevx', // .heic / image/heic-sequence\n  ];\n\n  return validFourCC.includes(fourCC);\n}\n\nexport function getDimensions(image: DecodeResult) {\n  const width = image.get_width();\n  const height = image.get_height();\n\n  return { width, height };\n}\n\nexport async function decodeImage(image: DecodeResult) {\n  const dimensions = getDimensions(image);\n  const { width, height } = dimensions;\n\n  return new Promise<ArrayBuffer>((resolve, reject) => {\n    image.display(\n      {\n        data: new Uint8ClampedArray(width * height * 4),\n        width,\n        height,\n        colorSpace: 'srgb',\n      },\n      (result: ImageData | null) => {\n        if (!result) {\n          reject(new Error('HEIF processing error'));\n        } else {\n          resolve(result.data.buffer);\n        }\n      }\n    );\n  });\n}\n\nexport async function bufferToBlob(\n  buffer: ArrayBuffer,\n  width: number,\n  height: number,\n  type: 'image/jpeg' | 'image/png' | 'image/webp' = 'image/webp',\n  quality = 0.82\n) {\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n\n  const ctx = canvas.getContext('2d');\n\n  if (!ctx) {\n    throw new Error('Could not get context');\n  }\n\n  const imageData = new ImageData(new Uint8ClampedArray(buffer), width, height);\n\n  ctx.putImageData(imageData, 0, 0);\n\n  return getCanvasBlob(canvas, type, quality);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as getResourceFromLocalFile } from './getResourceFromLocalFile';\nexport { default as getResourceFromMedia3p } from './getResourceFromMedia3p';\nexport { default as useUploadVideoFrame } from './useUploadVideoFrame';\nexport { default as getPosterName } from './getPosterName';\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/test/getResourceFromMedia3p.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getResourceFromMedia3p from '../getResourceFromMedia3p';\n\ndescribe('getResourceFromMedia3p', () => {\n  it('should return video resource', () => {\n    const media3pResource = {\n      color: '#00379b',\n      name: 'media/coverr:g9re0sRUYA',\n      provider: 'COVERR',\n      type: 'VIDEO',\n      description: 'NYC Postcard',\n      created_at: '',\n      createTime: '2018-09-25T20:03.07Z',\n      updateTime: '2019-05-20T22:49.08Z',\n      imageUrls: [\n        {\n          url: 'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 640,\n          height: 1138,\n        },\n        {\n          url: 'https://storage.coverr.co/p/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoMetadata: {\n        duration: '121.0000001s',\n      },\n    };\n    const expectedStoryEditorResource = {\n      baseColor: '#00379b',\n      type: 'video',\n      mimeType: 'video/mp4',\n      creationDate: '2018-09-25T20:03.07Z',\n      src: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n      width: 1080,\n      height: 1920,\n      poster:\n        'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n      posterId: 'media/coverr:g9re0sRUYA',\n      id: 'media/coverr:g9re0sRUYA',\n      length: 121,\n      lengthFormatted: '2:01',\n      alt: 'NYC Postcard',\n      isPlaceholder: false,\n      isMuted: true,\n      isOptimized: true,\n      isExternal: true,\n      needsProxy: false,\n      sizes: {\n        full: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n        preview: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n      },\n      attribution: undefined,\n      trimData: undefined,\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n\n  it('should return video resource no description', () => {\n    const media3pResource = {\n      color: '#00379b',\n      name: 'media/coverr:g9re0sRUYA',\n      provider: 'COVERR',\n      type: 'VIDEO',\n      title: 'Test title',\n      created_at: '',\n      createTime: '2018-09-25T20:03.07Z',\n      updateTime: '2019-05-20T22:49.08Z',\n      imageUrls: [\n        {\n          url: 'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 640,\n          height: 1138,\n        },\n        {\n          url: 'https://storage.coverr.co/p/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoMetadata: {\n        duration: '121.0000001s',\n      },\n    };\n    const expectedStoryEditorResource = {\n      baseColor: '#00379b',\n      type: 'video',\n      mimeType: 'video/mp4',\n      creationDate: '2018-09-25T20:03.07Z',\n      src: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n      width: 1080,\n      height: 1920,\n      poster:\n        'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n      posterId: 'media/coverr:g9re0sRUYA',\n      id: 'media/coverr:g9re0sRUYA',\n      length: 121,\n      lengthFormatted: '2:01',\n      alt: 'Test title',\n      isPlaceholder: false,\n      isMuted: true,\n      isOptimized: true,\n      isExternal: true,\n      needsProxy: false,\n      sizes: {\n        full: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n        preview: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n      },\n      attribution: undefined,\n      trimData: undefined,\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n\n  it('should return video resource no description or title', () => {\n    const media3pResource = {\n      color: '#00379b',\n      name: 'media/coverr:g9re0sRUYA',\n      provider: 'COVERR',\n      type: 'VIDEO',\n      created_at: '',\n      createTime: '2018-09-25T20:03.07Z',\n      updateTime: '2019-05-20T22:49.08Z',\n      imageUrls: [\n        {\n          url: 'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 640,\n          height: 1138,\n        },\n        {\n          url: 'https://storage.coverr.co/p/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoMetadata: {\n        duration: '121.0000001s',\n      },\n    };\n    const expectedStoryEditorResource = {\n      baseColor: '#00379b',\n      type: 'video',\n      mimeType: 'video/mp4',\n      creationDate: '2018-09-25T20:03.07Z',\n      src: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n      width: 1080,\n      height: 1920,\n      poster:\n        'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n      posterId: 'media/coverr:g9re0sRUYA',\n      id: 'media/coverr:g9re0sRUYA',\n      length: 121,\n      lengthFormatted: '2:01',\n      alt: 'media/coverr:g9re0sRUYA',\n      isPlaceholder: false,\n      isMuted: true,\n      isOptimized: true,\n      isExternal: true,\n      needsProxy: false,\n      sizes: {\n        full: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n        preview: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 360,\n          height: 640,\n        },\n      },\n      attribution: undefined,\n      trimData: undefined,\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n\n  it('should return video resource with calculated size', () => {\n    const media3pResource = {\n      color: '#00379b',\n      name: 'media/coverr:g9re0sRUYA',\n      provider: 'COVERR',\n      type: 'VIDEO',\n      description: 'NYC Postcard',\n      created_at: '',\n      createTime: '2018-09-25T20:03.07Z',\n      updateTime: '2019-05-20T22:49.08Z',\n      imageUrls: [\n        {\n          url: 'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n        },\n        {\n          url: 'https://storage.coverr.co/p/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n          mimeType: 'image/jpeg',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n        },\n        {\n          url: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n      ],\n      videoMetadata: {\n        duration: '121.0000001s',\n      },\n    };\n    const expectedStoryEditorResource = {\n      baseColor: '#00379b',\n      type: 'video',\n      mimeType: 'video/mp4',\n      creationDate: '2018-09-25T20:03.07Z',\n      src: 'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n      width: 1080,\n      height: 1920,\n      poster:\n        'https://storage.coverr.co/t/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?v=1596077699474',\n      posterId: 'media/coverr:g9re0sRUYA',\n      id: 'media/coverr:g9re0sRUYA',\n      length: 121,\n      lengthFormatted: '2:01',\n      alt: 'NYC Postcard',\n      isPlaceholder: false,\n      isMuted: true,\n      isOptimized: true,\n      isExternal: true,\n      needsProxy: false,\n      sizes: {\n        full: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 1080,\n          height: 1920,\n        },\n        preview: {\n          file: 'media/coverr:g9re0sRUYA',\n          sourceUrl:\n            'https://storage.coverr.co/videos/Y5RaHMvC502h001U003e3YbypqDJdjEMOaT/preview?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjIzQ0I1QURCMjc3QTk2RTc4MTBBIiwiaWF0IjoxNTk2MDc3Njk5fQ.hfcLRuoZqXwJiZtgv40MI-hS3cMlzhbwNIEvNKtTXNw',\n          mimeType: 'video/mp4',\n          width: 640,\n          height: 1137.7777777777778,\n        },\n      },\n      trimData: undefined,\n      attribution: undefined,\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n\n  it('should throw when unsplash has no size', () => {\n    const media3pResource = {\n      name: 'media/unsplash:dpbXgTh0Lac',\n      provider: 'UNSPLASH',\n      type: 'IMAGE',\n      author: {\n        displayName: 'XPS',\n        url: 'https://unsplash.com/@xps?utm_source=web_stories_wordpress&utm_medium=referral',\n      },\n      createTime: '2020-07-01T22:30:13Z',\n      updateTime: '2020-08-14T05:05:24Z',\n      registerUsageUrl:\n        'https://autopush-media3p.sandbox.googleapis.com/v1/media:registerUsage?payload=Af81gfyYynHd3Ao2kDkRmfXj7GcpvUB%2BodPzTbGSxvbLB1PmyrpJV4O1IbvAaUFKdHS1QhGxHlTRbkaR1/phBTcevwOmt7yMmwhUsmaNQiTRmTImxIr9NRMBWP6YyGLY/TaoLTyuRBlH5A%3D%3D',\n      imageUrls: [\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=6016&h=4016&fit=max',\n          mimeType: 'image/jpeg',\n          width: 6016,\n          height: 4016,\n        },\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=4812&h=3212&fit=max',\n          mimeType: 'image/jpeg',\n          width: 4812,\n          height: 3212,\n        },\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=3609&h=2409&fit=max',\n          mimeType: 'image/jpeg',\n          width: 3609,\n          height: 2409,\n        },\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=2406&h=1606&fit=max',\n          mimeType: 'image/jpeg',\n          width: 2406,\n          height: 1606,\n        },\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=1203&h=803&fit=max',\n          mimeType: 'image/jpeg',\n          width: 1203,\n          height: 803,\n        },\n        {\n          url: 'https://images.unsplash.com/photo-1593642532400-2682810df593?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEzNzE5M30&fm=jpg&w=340&h=227&fit=max',\n          mimeType: 'image/jpeg',\n        },\n      ],\n    };\n    expect(() => getResourceFromMedia3p(media3pResource)).toThrow(\n      'Missing width and height for: ' + media3pResource\n    );\n  });\n\n  it('should return image and video resources for tenor gifs', () => {\n    const media3pResource = {\n      color: '#00379b',\n      name: 'media/tenor:3468838096637910112',\n      provider: 'TENOR',\n      type: 'GIF',\n      author: {},\n      createTime: '2020-10-26T21:36:35Z',\n      registerUsageUrl:\n        'https://media3p.googleapis.com/v1/media:registerUsage?token=ASGVQQM7RDo11b9csHFps5CdRRojuc3hJdc5cgBr817EXo%2B4oHZyK/RIyx4%2Bko/WHVgHwgBx1wThYyUgljKneqDEakyl0A%3D%3D',\n      imageUrls: [\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAAC/happy-national-cat-day-peace.gif',\n          imageName: 'gif',\n          mimeType: 'image/gif',\n          width: 498,\n          height: 498,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAAe/happy-national-cat-day-peace.png',\n          imageName: 'gifpreview',\n          mimeType: 'image/gif',\n          width: 640,\n          height: 640,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAAM/happy-national-cat-day-peace.gif',\n          imageName: 'tinygif',\n          mimeType: 'image/gif',\n          width: 220,\n          height: 220,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAAS/happy-national-cat-day-peace.gif',\n          imageName: 'nanogif',\n          mimeType: 'image/gif',\n          width: 90,\n          height: 90,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAPs/happy-national-cat-day-peace.webm',\n          videoName: 'webm',\n          mimeType: 'image/webm',\n          width: 640,\n          height: 640,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAPo/happy-national-cat-day-peace.mp4',\n          videoName: 'mp4',\n          mimeType: 'video/mp4',\n          width: 640,\n          height: 640,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAP3/happy-national-cat-day-peace.webm',\n          videoName: 'tinywebm',\n          mimeType: 'image/webm',\n          width: 186,\n          height: 186,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAP1/happy-national-cat-day-peace.mp4',\n          videoName: 'tinymp4',\n          mimeType: 'video/mp4',\n          width: 186,\n          height: 186,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAP4/happy-national-cat-day-peace.webm',\n          videoName: 'nanowebm',\n          mimeType: 'image/webm',\n          width: 86,\n          height: 86,\n        },\n        {\n          url: 'https://c.tenor.com/MCPJ3sVx3GAAAAP2/happy-national-cat-day-peace.mp4',\n          videoName: 'nanomp4',\n          mimeType: 'video/mp4',\n          width: 86,\n          height: 86,\n        },\n      ],\n      videoMetadata: {\n        duration: '0s',\n      },\n    };\n\n    const expectedStoryEditorResource = {\n      baseColor: '#00379b',\n      id: 'media/tenor:3468838096637910112',\n      type: 'gif',\n      mimeType: 'image/gif',\n      creationDate: '2020-10-26T21:36:35Z',\n      src: 'https://c.tenor.com/MCPJ3sVx3GAAAAAC/happy-national-cat-day-peace.gif',\n      width: 498,\n      height: 498,\n      alt: 'media/tenor:3468838096637910112',\n      isPlaceholder: false,\n      isOptimized: true,\n      isExternal: true,\n      needsProxy: false,\n      poster:\n        'https://c.tenor.com/MCPJ3sVx3GAAAAAe/happy-national-cat-day-peace.png',\n      posterId: 'media/tenor:3468838096637910112',\n      sizes: {\n        full: {\n          file: 'media/tenor:3468838096637910112',\n          height: 498,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/MCPJ3sVx3GAAAAAC/happy-national-cat-day-peace.gif',\n          width: 498,\n        },\n        large: {\n          file: 'media/tenor:3468838096637910112',\n          height: 220,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/MCPJ3sVx3GAAAAAM/happy-national-cat-day-peace.gif',\n          width: 220,\n        },\n        web_stories_thumbnail: {\n          file: 'media/tenor:3468838096637910112',\n          height: 90,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/MCPJ3sVx3GAAAAAS/happy-national-cat-day-peace.gif',\n          width: 90,\n        },\n      },\n      output: {\n        mimeType: 'video/mp4',\n        src: 'https://c.tenor.com/MCPJ3sVx3GAAAAPo/happy-national-cat-day-peace.mp4',\n      },\n      attribution: {\n        author: {\n          displayName: undefined,\n          url: undefined,\n        },\n        registerUsageUrl:\n          'https://media3p.googleapis.com/v1/media:registerUsage?token=ASGVQQM7RDo11b9csHFps5CdRRojuc3hJdc5cgBr817EXo%2B4oHZyK/RIyx4%2Bko/WHVgHwgBx1wThYyUgljKneqDEakyl0A%3D%3D',\n      },\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n\n  it('should return sticker resource', () => {\n    const media3pResource = {\n      name: 'media/tenor:7259408917338674423',\n      provider: 'TENOR',\n      type: 'STICKER',\n      author: {\n        displayName: 'tenor',\n        url: 'https://tenor.com/official/tenor',\n      },\n      title: 'Tuesday Happy Tuesday Sticker',\n      createTime: '2020-09-14T18:44:39Z',\n      registerUsageUrl:\n        'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE%2Blc8Z9N5qFNkRHgYpJLI9SgPhj7JhlSjmK7Fy6OABL6uRP0NXphMGvHFqDrhfhHQaVI3CLXT3Qsz6xDyjN/dV2AA%3D%3D',\n      imageUrls: [\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAl/tuesday-happy-tuesday.webp',\n          imageName: 'webp_transparent',\n          mimeType: 'image/webp',\n          width: 498,\n          height: 303,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAt/tuesday-happy-tuesday.webp',\n          imageName: 'webppreview_transparent',\n          mimeType: 'image/webp',\n          width: 498,\n          height: 303,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAi/tuesday-happy-tuesday.gif',\n          imageName: 'gif_transparent',\n          mimeType: 'image/gif',\n          width: 498,\n          height: 286,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAq/tenor.gif',\n          imageName: 'gifpreview_transparent',\n          mimeType: 'image/gif',\n          width: 498,\n          height: 286,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAm/tuesday-happy-tuesday.webp',\n          imageName: 'tinywebp_transparent',\n          mimeType: 'image/webp',\n          width: 200,\n          height: 122,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAj/tuesday-happy-tuesday.gif',\n          imageName: 'tinygif_transparent',\n          mimeType: 'image/gif',\n          width: 200,\n          height: 115,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAn/tuesday-happy-tuesday.webp',\n          imageName: 'nanowebp_transparent',\n          mimeType: 'image/webp',\n          width: 90,\n          height: 55,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAk/tuesday-happy-tuesday.gif',\n          imageName: 'nanogif_transparent',\n          mimeType: 'image/gif',\n          width: 90,\n          height: 52,\n        },\n      ],\n      videoUrls: [\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAPs/tuesday-happy-tuesday.webm',\n          videoName: 'webm',\n          mimeType: 'image/webm',\n          width: 640,\n          height: 388,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAPo/tuesday-happy-tuesday.mp4',\n          videoName: 'mp4',\n          mimeType: 'video/mp4',\n          width: 640,\n          height: 388,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAP3/tuesday-happy-tuesday.webm',\n          videoName: 'tinywebm',\n          mimeType: 'image/webm',\n          width: 258,\n          height: 156,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAP1/tuesday-happy-tuesday.mp4',\n          videoName: 'tinymp4',\n          mimeType: 'video/mp4',\n          width: 258,\n          height: 156,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAP4/tuesday-happy-tuesday.webm',\n          videoName: 'nanowebm',\n          mimeType: 'image/webm',\n          width: 120,\n          height: 72,\n        },\n        {\n          url: 'https://c.tenor.com/ZL6Z8sVGVPcAAAP2/tuesday-happy-tuesday.mp4',\n          videoName: 'nanomp4',\n          mimeType: 'video/mp4',\n          width: 120,\n          height: 72,\n        },\n      ],\n      videoMetadata: {\n        duration: '0s',\n      },\n    };\n    const expectedStoryEditorResource = {\n      baseColor: undefined,\n      blurHash: undefined,\n      type: 'image',\n      mimeType: 'image/gif',\n      creationDate: '2020-09-14T18:44:39Z',\n      src: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAi/tuesday-happy-tuesday.gif',\n      width: 498,\n      height: 286,\n      id: 'media/tenor:7259408917338674423',\n      alt: 'Tuesday Happy Tuesday Sticker',\n      isPlaceholder: false,\n      isExternal: true,\n      needsProxy: false,\n      sizes: {\n        '200_115': {\n          file: 'media/tenor:7259408917338674423',\n          height: 115,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/ZL6Z8sVGVPcAAAAj/tuesday-happy-tuesday.gif',\n          width: 200,\n        },\n        full: {\n          file: 'media/tenor:7259408917338674423',\n          height: 286,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/ZL6Z8sVGVPcAAAAi/tuesday-happy-tuesday.gif',\n          width: 498,\n        },\n        large: {\n          file: 'media/tenor:7259408917338674423',\n          height: 286,\n          mimeType: 'image/gif',\n          sourceUrl: 'https://c.tenor.com/ZL6Z8sVGVPcAAAAq/tenor.gif',\n          width: 498,\n        },\n        web_stories_thumbnail: {\n          file: 'media/tenor:7259408917338674423',\n          height: 52,\n          mimeType: 'image/gif',\n          sourceUrl:\n            'https://c.tenor.com/ZL6Z8sVGVPcAAAAk/tuesday-happy-tuesday.gif',\n          width: 90,\n        },\n      },\n      attribution: {\n        author: {\n          displayName: 'tenor',\n          url: 'https://tenor.com/official/tenor',\n        },\n        registerUsageUrl:\n          'https://media3p.googleapis.com/v1/media:registerUsage?token=AdnbmE%2Blc8Z9N5qFNkRHgYpJLI9SgPhj7JhlSjmK7Fy6OABL6uRP0NXphMGvHFqDrhfhHQaVI3CLXT3Qsz6xDyjN/dV2AA%3D%3D',\n      },\n    };\n    expect(getResourceFromMedia3p(media3pResource)).toStrictEqual(\n      expectedStoryEditorResource\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/test/useFFmpeg.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport CurrentUserContext from '../../../currentUser/context';\nimport useFFmpeg from '../useFFmpeg';\nimport { ConfigProvider } from '../../../config';\n\njest.mock('@ffmpeg/ffmpeg', () => {\n  return {\n    createFFmpeg: jest.fn(() => ({\n      load: jest.fn(),\n      run: jest.fn(),\n      FS: jest.fn(() => ({ buffer: 'foo' })),\n    })),\n    fetchFile: jest.fn(),\n  };\n});\n\nfunction arrange({ userSettingEnabled, hasUploadMediaAction }) {\n  const currentUser = {\n    mediaOptimization: userSettingEnabled,\n  };\n  const configState = {\n    capabilities: {\n      hasUploadMediaAction,\n    },\n  };\n\n  return renderHook(() => useFFmpeg(), {\n    wrapper: ({ children }) => (\n      <ConfigProvider config={configState}>\n        <CurrentUserContext.Provider value={{ state: { currentUser } }}>\n          {children}\n        </CurrentUserContext.Provider>\n      </ConfigProvider>\n    ),\n  });\n}\n\ndescribe('useFFmpeg', () => {\n  describe('isTranscodingEnabled', () => {\n    afterEach(() => {\n      delete window.crossOriginIsolated;\n    });\n\n    it('should return false if there is no cross-origin isolation', () => {\n      const { result } = arrange({\n        userSettingEnabled: true,\n        hasUploadMediaAction: true,\n      });\n      expect(result.current.isTranscodingEnabled).toBeFalse();\n    });\n\n    it('should return true if cross-origin isolation is setup', () => {\n      window.crossOriginIsolated = true;\n      const { result } = arrange({\n        userSettingEnabled: true,\n        hasUploadMediaAction: true,\n      });\n      expect(result.current.isTranscodingEnabled).toBeTrue();\n    });\n\n    it('should return false if user has no upload permissions', () => {\n      window.crossOriginIsolated = true;\n      const { result } = arrange({\n        hasUploadMediaAction: false,\n        userSettingEnabled: true,\n      });\n      expect(result.current.isTranscodingEnabled).toBeFalse();\n    });\n  });\n\n  describe('canTranscodeFile', () => {\n    it('should return true for video files', () => {\n      const file = new File(['foo'], 'foo.mov', {\n        type: 'video/quicktime',\n      });\n\n      const { result } = arrange({});\n      expect(result.current.canTranscodeFile(file)).toBeTrue();\n    });\n\n    it('should return false if file is not a video', () => {\n      const file = new File(['foo'], 'foo.txt', {\n        type: 'text/plain',\n      });\n\n      const { result } = arrange({});\n      expect(result.current.canTranscodeFile(file)).toBeFalse();\n    });\n  });\n\n  describe('isFileTooLarge', () => {\n    it('returns true if file is over 2GB', () => {\n      const file = {\n        size: 1024 * 1024 * 1024 * 2,\n      };\n\n      const { result } = arrange({});\n      expect(result.current.isFileTooLarge(file)).toBeTrue();\n    });\n\n    it('returns false if file is less than 2GB', () => {\n      const file = {\n        size: 1024 * 1024 * 1024,\n      };\n\n      const { result } = arrange({});\n      expect(result.current.isFileTooLarge(file)).toBeFalse();\n    });\n  });\n\n  describe('transcodeVideo', () => {\n    it('should transcode a MOV file into an MP4', async () => {\n      const file = new File(['foo'], 'foo.mov', {\n        type: 'video/quicktime',\n      });\n\n      const { result } = arrange({});\n      const newFile = await result.current.transcodeVideo(file);\n      expect(newFile.type).toBe('video/mp4');\n      expect(newFile.name).toBe('foo.mp4');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/test/useMediaInfo.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport type { VideoResource } from '@googleforcreators/media';\nimport { ResourceType } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type { ConfigState } from '../../../../types';\nimport { ConfigProvider } from '../../../config';\nimport useMediaInfo from '../useMediaInfo';\n\njest.mock('@googleforcreators/tracking', () => ({\n  trackEvent: jest.fn(),\n  getTimeTracker: jest.fn(() => jest.fn()),\n}));\n\nconst mockAnalyzeData = jest.fn();\n\njest.mock('mediainfo.js', () => ({\n  __esModule: true,\n  default: jest.fn(() =>\n    Promise.resolve({\n      analyzeData: mockAnalyzeData,\n      close: jest.fn(),\n    })\n  ),\n}));\n\nfunction arrange() {\n  const configState = {\n    mediainfoUrl: 'https://example.com',\n  } as ConfigState;\n\n  return renderHook(() => useMediaInfo(), {\n    wrapper: ({ children }) => (\n      <ConfigProvider config={configState}>{children}</ConfigProvider>\n    ),\n  });\n}\n\nconst BASE_RESOURCE: VideoResource = {\n  type: ResourceType.Video,\n  mimeType: 'video/webm',\n  creationDate: '2021-05-11T21:55:24',\n  src: 'http://test.example/video.webm',\n  width: 720,\n  height: 1280,\n  poster: 'http://test.example/video-poster.jpg',\n  posterId: 92,\n  id: 91,\n  length: 6,\n  lengthFormatted: '0:06',\n  alt: 'small-video',\n  sizes: {},\n  isOptimized: false,\n  isExternal: false,\n  baseColor: '#734727',\n};\n\nconst OPTIMIZED_RESOURCE = {\n  ...BASE_RESOURCE,\n  isOptimized: true,\n};\n\nconst MOV_RESOURCE = {\n  ...BASE_RESOURCE,\n  mimeType: 'video/quicktime',\n};\n\nconst WEBM_RESOURCE = {\n  ...BASE_RESOURCE,\n  mimeType: 'video/webm',\n};\n\nconst MP4_RESOURCE = {\n  ...BASE_RESOURCE,\n  mimeType: 'video/mp4',\n};\n\nconst LARGE_RESOURCE = {\n  ...BASE_RESOURCE,\n  width: 10000,\n  height: 10000,\n};\n\nconst MEDIAINFO_RESULT_MP4 = JSON.stringify({\n  media: {\n    track: [\n      {\n        '@type': 'General',\n        VideoCount: 1,\n        Format: 'MPEG-4',\n        Format_Profile: 'Base Media',\n        CodecID: 'mp42',\n        CodecID_Compatible: 'mp41/isom',\n        FileSize: 301084,\n        Duration: 18.0,\n        OverallBitRate: 133815,\n        FrameRate: 24.0,\n        FrameCount: 360,\n        StreamSize: 2233,\n        HeaderSize: 64,\n        DataSize: 298867,\n        FooterSize: 2153,\n        IsStreamable: false,\n      },\n      {\n        '@type': 'Video',\n        Format: 'AVC',\n        CodecID: 'avc1',\n        Duration: 18.0,\n        BitRate: 132823,\n        Width: 1920,\n        Height: 1080,\n        FrameRate: 24.0,\n        ColorSpace: 'YUV',\n      },\n    ],\n  },\n});\n\nconst MEDIAINFO_RESULT_MP4_SMALL = JSON.stringify({\n  media: {\n    track: [\n      {\n        '@type': 'General',\n        VideoCount: 1,\n        Format: 'MPEG-4',\n        Format_Profile: 'Base Media',\n        CodecID: 'mp42',\n        CodecID_Compatible: 'mp41/isom',\n        FileSize: 301084,\n        Duration: 18.0,\n        OverallBitRate: 133815,\n        FrameRate: 24.0,\n        FrameCount: 360,\n        StreamSize: 2233,\n        HeaderSize: 64,\n        DataSize: 298867,\n        FooterSize: 2153,\n        IsStreamable: false,\n      },\n      {\n        '@type': 'Video',\n        Format: 'AVC',\n        CodecID: 'avc1',\n        Duration: 18.0,\n        BitRate: 132823,\n        Width: 720,\n        Height: 1080,\n        FrameRate: 24.0,\n        ColorSpace: 'YUV',\n      },\n    ],\n  },\n});\n\nconst MEDIAINFO_RESULT_WEBM = JSON.stringify({\n  media: {\n    track: [\n      {\n        '@type': 'General',\n        VideoCount: 1,\n        AudioCount: 1,\n        Format: 'WebM',\n        Format_Version: 4,\n        FileSize: 226548,\n        Duration: 5.568,\n        OverallBitRate: 325500,\n        FrameRate: 30.0,\n        FrameCount: 167,\n        IsStreamable: true,\n      },\n      {\n        '@type': 'Video',\n        StreamOrder: 0,\n        Format: 'VP9',\n        CodecID: 'V_VP9',\n        Duration: 5.567,\n        Width: 560,\n        Height: 320,\n        PixelAspectRatio: 1.0,\n        DisplayAspectRatio: 1.75,\n        FrameRate_Mode: 'CFR',\n        FrameRate: 30.0,\n        FrameCount: 167,\n        Default: true,\n        Forced: false,\n      },\n      {\n        '@type': 'Audio',\n        StreamOrder: 1,\n        Format: 'Opus',\n        CodecID: 'A_OPUS',\n        Duration: 5.568,\n        Channels: 1,\n        ChannelPositions: 'Front: C',\n        SamplingRate: 48000,\n        SamplingCount: 267264,\n      },\n    ],\n  },\n});\n\ndescribe('useMediaInfo', () => {\n  beforeAll(() => {\n    mockAnalyzeData.mockImplementation(() =>\n      Promise.resolve(\n        JSON.stringify({\n          media: {\n            track: [],\n          },\n        })\n      )\n    );\n  });\n\n  afterEach(() => {\n    mockAnalyzeData.mockClear();\n  });\n\n  describe('getFileInfo', () => {\n    it('should return file info', async () => {\n      const { result } = arrange();\n\n      const fileInfo = await result.current.getFileInfo(\n        new File(['foo'], 'foo.mov', {\n          type: 'video/quicktime',\n        })\n      );\n\n      expect(fileInfo).toMatchObject({\n        isMuted: true,\n        mimeType: 'video/quicktime',\n      });\n    });\n\n    it('should return file info for muted mp4 file', async () => {\n      const { result } = arrange();\n\n      mockAnalyzeData.mockImplementation(() =>\n        Promise.resolve(MEDIAINFO_RESULT_MP4)\n      );\n\n      const fileInfo = await result.current.getFileInfo(\n        new File(['foo'], 'foo.mp4', {\n          type: 'video/mp4',\n        })\n      );\n\n      expect(fileInfo).toMatchObject({\n        isMuted: true,\n        mimeType: 'video/mp4',\n        fileSize: 301084,\n        format: 'mp4',\n        frameRate: 24,\n        codec: 'mp42',\n        width: 1920,\n        height: 1080,\n        colorSpace: 'YUV',\n        duration: 18,\n        videoCodec: 'avc',\n      });\n    });\n\n    it('should return file info for webm file', async () => {\n      const { result } = arrange();\n\n      mockAnalyzeData.mockImplementation(() =>\n        Promise.resolve(MEDIAINFO_RESULT_WEBM)\n      );\n\n      const fileInfo = await result.current.getFileInfo(\n        new File(['foo'], 'foo.webm', {\n          type: 'video/webm',\n        })\n      );\n\n      expect(fileInfo).toMatchObject({\n        isMuted: false,\n        mimeType: 'video/webm',\n        fileSize: 226548,\n        format: 'webm',\n        frameRate: 30,\n        codec: undefined,\n        width: 560,\n        height: 320,\n        colorSpace: undefined,\n        duration: 5.567,\n        videoCodec: 'vp9',\n        audioCodec: 'opus',\n      });\n    });\n  });\n\n  describe('isConsideredOptimized', () => {\n    it('should bail early for already optimized resource', async () => {\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        OPTIMIZED_RESOURCE,\n        new File(['foo'], 'foo.mp4', {\n          type: 'video/mp4',\n        })\n      );\n      expect(actual).toBeTrue();\n    });\n\n    it('should bail early for mov resources', async () => {\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        MOV_RESOURCE,\n        new File(['foo'], 'foo.mov', {\n          type: 'video/quicktime',\n        })\n      );\n      expect(actual).toBeFalse();\n    });\n\n    it('should bail early for webm resources', async () => {\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        WEBM_RESOURCE,\n        new File(['foo'], 'foo.webm', {\n          type: 'video/webm',\n        })\n      );\n      expect(actual).toBeFalse();\n    });\n\n    it('should bail early for resources with large dimensions', async () => {\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        LARGE_RESOURCE,\n        new File(['foo'], 'foo.mp4', {\n          type: 'video/mp4',\n        })\n      );\n      expect(actual).toBeFalse();\n    });\n\n    it('should return false for large MP4 file', async () => {\n      mockAnalyzeData.mockImplementation(() =>\n        Promise.resolve(MEDIAINFO_RESULT_MP4)\n      );\n\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        MP4_RESOURCE,\n        new File(['foo'], 'foo.mp4', {\n          type: 'video/mp4',\n        })\n      );\n      expect(actual).toBeFalse();\n    });\n\n    it('should return true for small MP4 file', async () => {\n      mockAnalyzeData.mockImplementation(() =>\n        Promise.resolve(MEDIAINFO_RESULT_MP4_SMALL)\n      );\n\n      const { result } = arrange();\n\n      const actual = await result.current.isConsideredOptimized(\n        MP4_RESOURCE,\n        new File(['foo'], 'foo.mp4', {\n          type: 'video/mp4',\n        })\n      );\n      expect(actual).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/test/useProcessMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport APIContext from '../../../api/context';\nimport StoryContext from '../../../story/context';\nimport useProcessMedia from '../useProcessMedia';\nimport useMediaInfo from '../useMediaInfo';\nimport { ConfigProvider } from '../../../config';\n\nconst fetchRemoteFileMock = (url, mimeType) => {\n  if (url === 'http://www.google.com/foo.mov') {\n    return new File(['foo'], 'foo.mov', {\n      type: mimeType,\n    });\n  }\n\n  if (url === 'http://www.google.com/foo.mp4') {\n    return new File(['foo'], 'foo.mp4', {\n      type: mimeType,\n    });\n  }\n\n  if (url === 'http://www.google.com/foo.gif') {\n    return {\n      arrayBuffer: jest.fn(),\n    };\n  }\n\n  return Promise.reject(new Error('Invalid file'));\n};\n\nconst fetchRemoteBlobMock = (url) => {\n  if (url === 'http://www.google.com/foo.gif') {\n    return {};\n  }\n\n  return Promise.reject(new Error('Invalid file'));\n};\n\njest.mock('@googleforcreators/media', () => {\n  return {\n    fetchRemoteFile: fetchRemoteFileMock,\n    fetchRemoteBlob: fetchRemoteBlobMock,\n    isAnimatedGif: () => {\n      return true;\n    },\n  };\n});\n\nconst updateElementsByResourceId = jest.fn();\nconst uploadMedia = (\n  files,\n  { onUploadSuccess, onUploadStart, onUploadError }\n) => {\n  const resource = {\n    src: 'http://www.google.com/foo.gif',\n    id: 2,\n    type: 'gif',\n  };\n  if (onUploadSuccess) {\n    onUploadSuccess({ resource, id: 2 });\n  }\n  if (onUploadStart) {\n    onUploadStart({ resource });\n  }\n  if (onUploadError) {\n    onUploadError({ resource });\n  }\n};\n\nconst getOptimizedMediaById = jest.fn();\nconst getMutedMediaById = jest.fn();\n\njest.mock('../useMediaInfo', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({\n    getFileInfo: jest.fn(() => null),\n    isConsideredOptimized: jest.fn(() => false),\n  })),\n}));\n\nfunction setup() {\n  const apiContextValue = {\n    actions: {\n      getOptimizedMediaById,\n      getMutedMediaById,\n    },\n  };\n  const storyContextValue = {\n    actions: { updateElementsByResourceId },\n  };\n  const configState = {\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n  };\n  const wrapper = ({ children }) => (\n    <ConfigProvider config={configState}>\n      <APIContext.Provider value={apiContextValue}>\n        <StoryContext.Provider value={storyContextValue}>\n          {children}\n        </StoryContext.Provider>\n      </APIContext.Provider>\n    </ConfigProvider>\n  );\n\n  const uploadVideoPoster = jest.fn();\n  const updateBaseColor = jest.fn();\n  const updateMedia = jest.fn();\n  const deleteMediaElement = jest.fn();\n  const updateVideoIsMuted = jest.fn();\n\n  const postProcessingResource = (resource) => {\n    const { isExternal, type, isMuted, baseColor, src, id, posterId } =\n      resource;\n\n    if (isExternal) {\n      return;\n    }\n    if (id && src && ['video', 'gif'].includes(type) && !posterId) {\n      uploadVideoPoster(id, src);\n    }\n    if (id && src && 'video' === type && isMuted === null) {\n      updateVideoIsMuted(id, src);\n    }\n\n    if (!baseColor) {\n      updateBaseColor(resource);\n    }\n  };\n\n  const { result } = renderHook(\n    () =>\n      useProcessMedia({\n        uploadMedia,\n        postProcessingResource,\n        updateMedia,\n        deleteMediaElement,\n      }),\n    { wrapper }\n  );\n\n  const { optimizeVideo, optimizeGif, muteExistingVideo } = result.current;\n  return {\n    optimizeVideo,\n    optimizeGif,\n    muteExistingVideo,\n    uploadVideoPoster,\n    updateBaseColor,\n    updateMedia,\n    deleteMediaElement,\n  };\n}\n\ndescribe('useProcessMedia', () => {\n  afterEach(() => {\n    useMediaInfo.mockClear();\n  });\n\n  describe('optimizeVideo', () => {\n    it('should reuse already existing optimized video', async () => {\n      getOptimizedMediaById.mockImplementationOnce(() => ({\n        id: 456,\n        src: 'http://www.google.com/foo-optimized.mp4',\n      }));\n\n      const { optimizeVideo, uploadVideoPoster, updateBaseColor, updateMedia } =\n        setup();\n      act(() => {\n        optimizeVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mov',\n            id: 123,\n            mimeType: 'video/quicktime',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(getOptimizedMediaById).toHaveBeenCalledWith(123);\n      });\n\n      expect(uploadVideoPoster).not.toHaveBeenCalled();\n      expect(updateBaseColor).not.toHaveBeenCalled();\n      expect(updateMedia).not.toHaveBeenCalled();\n    });\n\n    it('should process video file', async () => {\n      const { optimizeVideo, uploadVideoPoster, updateBaseColor, updateMedia } =\n        setup();\n      act(() => {\n        optimizeVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mov',\n            id: 123,\n            mimeType: 'video/quicktime',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n\n      expect(updateBaseColor).toHaveBeenCalledWith({\n        id: 2,\n        src: 'http://www.google.com/foo.gif',\n        type: 'gif',\n      });\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mediaSource: 'source-video',\n        optimizedId: 2,\n      });\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mediaSource: 'source-video',\n        optimizedId: 2,\n      });\n    });\n\n    it('should process video file with base color', async () => {\n      const { optimizeVideo, uploadVideoPoster, updateBaseColor, updateMedia } =\n        setup();\n      act(() => {\n        optimizeVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mov',\n            id: 123,\n            mimeType: 'video/quicktime',\n            baseColor: '#000000',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n\n      expect(updateBaseColor).toHaveBeenCalledWith({\n        baseColor: undefined,\n        id: 2,\n        src: 'http://www.google.com/foo.gif',\n        type: 'gif',\n      });\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mediaSource: 'source-video',\n        optimizedId: 2,\n      });\n    });\n\n    it('should fail video processing gracefully', async () => {\n      const {\n        optimizeVideo,\n        uploadVideoPoster,\n        updateMedia,\n        updateBaseColor,\n        deleteMediaElement,\n      } = setup();\n      act(() => {\n        optimizeVideo({\n          resource: {\n            src: 'http://www.google.com/invalid.jpg',\n            id: 123,\n            mimeType: 'image/jpg',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).not.toHaveBeenCalled();\n      });\n\n      expect(updateBaseColor).not.toHaveBeenCalled();\n      expect(updateMedia).not.toHaveBeenCalled();\n      expect(deleteMediaElement).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('muteExistingVideo', () => {\n    it('should reuse already existing muted video', async () => {\n      getMutedMediaById.mockImplementationOnce(() => ({\n        id: 456,\n        src: 'http://www.google.com/foo-optimized.mp4',\n      }));\n\n      const {\n        muteExistingVideo,\n        uploadVideoPoster,\n        updateMedia,\n        updateBaseColor,\n      } = setup();\n      act(() => {\n        muteExistingVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mov',\n            id: 123,\n            mimeType: 'video/quicktime',\n          },\n        });\n      });\n      await waitFor(() => {\n        expect(getMutedMediaById).toHaveBeenCalledWith(123);\n      });\n\n      expect(uploadVideoPoster).not.toHaveBeenCalled();\n      expect(updateBaseColor).not.toHaveBeenCalled();\n      expect(updateMedia).not.toHaveBeenCalled();\n    });\n\n    it('should mute video file', async () => {\n      const {\n        muteExistingVideo,\n        uploadVideoPoster,\n        updateBaseColor,\n        updateMedia,\n      } = setup();\n      act(() => {\n        muteExistingVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mp4',\n            id: 123,\n            mimeType: 'video/mp4',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n      expect(updateBaseColor).toHaveBeenCalledWith({\n        src: 'http://www.google.com/foo.gif',\n        id: 2,\n        type: 'gif',\n      });\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mutedId: 2,\n      });\n    });\n\n    it('should mute video file with base color', async () => {\n      const { muteExistingVideo, uploadVideoPoster, updateMedia } = setup();\n      act(() => {\n        muteExistingVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mp4',\n            id: 123,\n            mimeType: 'video/mp4',\n            baseColor: '#000000',\n          },\n        });\n      });\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mutedId: 2,\n      });\n    });\n\n    it('should mute video file with empty poster', async () => {\n      const {\n        muteExistingVideo,\n        uploadVideoPoster,\n        updateMedia,\n        updateBaseColor,\n      } = setup();\n      act(() => {\n        muteExistingVideo({\n          resource: {\n            src: 'http://www.google.com/foo.mp4',\n            poster: 'http://www.google.com/foo.jpeg',\n            id: 123,\n            mimeType: 'video/mp4',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(updateBaseColor).toHaveBeenCalledWith({\n          id: 2,\n          src: 'http://www.google.com/foo.gif',\n          type: 'gif',\n        });\n      });\n\n      expect(uploadVideoPoster).toHaveBeenCalledWith(\n        2,\n        'http://www.google.com/foo.gif'\n      );\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mutedId: 2,\n      });\n    });\n\n    it('should fail video muting gracefully', async () => {\n      const {\n        muteExistingVideo,\n        uploadVideoPoster,\n        updateBaseColor,\n        updateMedia,\n        deleteMediaElement,\n      } = setup();\n      act(() => {\n        muteExistingVideo({\n          resource: {\n            src: 'http://www.google.com/invalid.jpg',\n            id: 123,\n            mimeType: 'image/jpg',\n          },\n        });\n      });\n      await waitFor(() => {\n        expect(uploadVideoPoster).not.toHaveBeenCalled();\n      });\n\n      expect(updateBaseColor).not.toHaveBeenCalled();\n      expect(updateMedia).not.toHaveBeenCalled();\n      expect(deleteMediaElement).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('optimizeGif', () => {\n    it('should process gif file', async () => {\n      const { optimizeGif, uploadVideoPoster, updateBaseColor, updateMedia } =\n        setup();\n      act(() => {\n        optimizeGif({\n          resource: {\n            src: 'http://www.google.com/foo.gif',\n            id: 123,\n            mimeType: 'image/gif',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n\n      expect(updateBaseColor).toHaveBeenCalledWith({\n        src: 'http://www.google.com/foo.gif',\n        id: 2,\n        type: 'gif',\n      });\n\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mediaSource: 'source-image',\n        optimizedId: 2,\n      });\n    });\n\n    it('should process gif file with base color', async () => {\n      const { optimizeGif, uploadVideoPoster, updateBaseColor, updateMedia } =\n        setup();\n      act(() => {\n        optimizeGif({\n          resource: {\n            src: 'http://www.google.com/foo.gif',\n            id: 123,\n            mimeType: 'image/gif',\n            baseColor: '#000000',\n          },\n        });\n      });\n      await waitFor(() => {\n        expect(uploadVideoPoster).toHaveBeenCalledWith(\n          2,\n          'http://www.google.com/foo.gif'\n        );\n      });\n\n      expect(updateBaseColor).toHaveBeenCalledWith({\n        baseColor: undefined,\n        id: 2,\n        src: 'http://www.google.com/foo.gif',\n        type: 'gif',\n      });\n\n      expect(updateMedia).toHaveBeenCalledWith(123, {\n        mediaSource: 'source-image',\n        optimizedId: 2,\n      });\n    });\n\n    it('should fail gif processing gracefully', async () => {\n      const {\n        optimizeGif,\n        uploadVideoPoster,\n        updateBaseColor,\n        updateMedia,\n        deleteMediaElement,\n      } = setup();\n      act(() => {\n        optimizeGif({\n          resource: {\n            src: 'http://www.google.com/invalid.jpg',\n            id: 123,\n            mimeType: 'image/jpg',\n          },\n        });\n      });\n\n      await waitFor(() => {\n        expect(uploadVideoPoster).not.toHaveBeenCalled();\n      });\n\n      expect(updateBaseColor).not.toHaveBeenCalled();\n      expect(updateMedia).not.toHaveBeenCalled();\n      expect(deleteMediaElement).not.toHaveBeenCalled();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useDetectBaseColor.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReduction } from '@googleforcreators/react';\nimport {\n  getSmallestUrlForWidth,\n  type Resource,\n  type ResourceId,\n  ResourceType,\n  type VideoResource,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useStory } from '../../story';\nimport { useConfig } from '../../config';\nimport getMediaBaseColor from '../../../utils/getMediaBaseColor';\nimport useCORSProxy from '../../../utils/useCORSProxy';\n\ninterface BaseColorState {\n  processed: ResourceId[];\n  processing: ResourceId[];\n}\n\nconst reducer = {\n  addProcessing: (\n    state: BaseColorState,\n    { payload }: { payload: ResourceId }\n  ) => {\n    if (!payload || state.processing.includes(payload)) {\n      return state;\n    }\n    return {\n      ...state,\n      processing: [...state.processing, payload],\n    };\n  },\n  removeProcessing: (\n    state: BaseColorState,\n    { payload }: { payload: ResourceId }\n  ) => {\n    if (!payload || !state.processing.includes(payload)) {\n      return state;\n    }\n    const currentProcessing = [...state.processing];\n    const processing = currentProcessing.filter((e) => e !== payload);\n\n    return {\n      ...state,\n      processing,\n      processed: [...state.processed, payload],\n    };\n  },\n};\n\nconst INITIAL_STATE: BaseColorState = {\n  processed: [],\n  processing: [],\n};\n\nfunction useDetectBaseColor({\n  updateMediaElement,\n}: {\n  updateMediaElement: ({\n    id,\n    data,\n  }: {\n    id: string | number;\n    data: Record<string, unknown>;\n  }) => void;\n}) {\n  const {\n    actions: { updateMedia, getPosterMediaById },\n  } = useAPI();\n  const { updateElementsByResourceId } = useStory((state) => ({\n    updateElementsByResourceId: state.actions.updateElementsByResourceId,\n  }));\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const { getProxiedUrl } = useCORSProxy();\n\n  const [state, actions] = useReduction(INITIAL_STATE, reducer);\n  const { processed, processing } = state;\n  const { addProcessing, removeProcessing } = actions;\n\n  const saveBaseColor = useCallback(\n    /**\n     *\n     * @param resource Resource object.\n     * @param baseColor Base Color.\n     */\n    async ({ id, isExternal }: Resource, baseColor: string) => {\n      try {\n        updateElementsByResourceId({\n          id,\n          properties: ({ resource }) => ({\n            resource: {\n              ...resource,\n              baseColor,\n            },\n          }),\n        });\n        if (!isExternal) {\n          updateMediaElement({\n            id,\n            data: { baseColor },\n          });\n          if (hasUploadMediaAction && updateMedia) {\n            await updateMedia(id, {\n              baseColor,\n            });\n          }\n        }\n      } catch {\n        // This might happen as an author when trying to updateMedia() that\n        // was uploaded by someone else.\n        // Do nothing with the error for now.\n      }\n    },\n    [\n      updateElementsByResourceId,\n      updateMediaElement,\n      hasUploadMediaAction,\n      updateMedia,\n    ]\n  );\n\n  const updateBaseColor = useCallback(\n    async (resource: Resource | VideoResource) => {\n      const { type, id, isExternal } = resource;\n      let imageSrc;\n\n      if ('poster' in resource) {\n        imageSrc = resource.poster;\n      }\n\n      if (type === ResourceType.Image) {\n        imageSrc = getSmallestUrlForWidth(0, resource);\n      } else if (!isExternal) {\n        try {\n          const posterResource = getPosterMediaById\n            ? await getPosterMediaById(id)\n            : null;\n          if (posterResource) {\n            imageSrc = getSmallestUrlForWidth(0, posterResource);\n          }\n        } catch {\n          // The user might not have the permission to access the video with context=edit.\n          // This might happen as an author when the video\n          // was uploaded by someone else.\n          // Do nothing with the error for now.\n        }\n      }\n\n      if (!imageSrc) {\n        return;\n      }\n      const imageSrcProxied = getProxiedUrl(resource, imageSrc);\n      if (!imageSrcProxied) {\n        return;\n      }\n      try {\n        const color = await getMediaBaseColor(imageSrcProxied);\n        await saveBaseColor(resource, color);\n      } catch {\n        // Do nothing for now.\n      }\n    },\n    [getProxiedUrl, getPosterMediaById, saveBaseColor]\n  );\n\n  const maybeUpdateBaseColor = useCallback(\n    async (resource: Resource) => {\n      const { id } = resource;\n\n      // Simple way to prevent double-uploading.\n      if (processed.includes(id) || processing.includes(id)) {\n        return;\n      }\n\n      addProcessing(id);\n      await updateBaseColor(resource);\n      removeProcessing(id);\n    },\n    [addProcessing, processed, processing, removeProcessing, updateBaseColor]\n  );\n\n  return {\n    updateBaseColor: maybeUpdateBaseColor,\n  };\n}\n\nexport default useDetectBaseColor;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useDetectBlurhash.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReduction } from '@googleforcreators/react';\nimport { getSmallestUrlForWidth } from '@googleforcreators/media';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useStory } from '../../story';\nimport { useConfig } from '../../config';\nimport useCORSProxy from '../../../utils/useCORSProxy';\nimport getBlurHashFromImage from '../../../utils/getBlurHashFromImage';\n\nconst reducer = {\n  addProcessing: (state, { payload }) => {\n    if (!payload || state.processing.includes(payload)) {\n      return state;\n    }\n    return {\n      ...state,\n      processing: [...state.processing, payload],\n    };\n  },\n  removeProcessing: (state, { payload }) => {\n    if (!payload || !state.processing.includes(payload)) {\n      return state;\n    }\n    const currentProcessing = [...state.processing];\n    const processing = currentProcessing.filter((e) => e !== payload);\n\n    return {\n      ...state,\n      processing,\n      processed: [...state.processed, payload],\n    };\n  },\n};\n\nconst INITIAL_STATE = {\n  processed: [],\n  processing: [],\n};\n\nfunction useDetectBlurHash({ updateMediaElement }) {\n  const {\n    actions: { updateMedia, getPosterMediaById },\n  } = useAPI();\n  const { updateElementsByResourceId } = useStory((state) => ({\n    updateElementsByResourceId: state.actions.updateElementsByResourceId,\n  }));\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const { getProxiedUrl } = useCORSProxy();\n\n  const [state, actions] = useReduction(INITIAL_STATE, reducer);\n  const { processed, processing } = state;\n  const { addProcessing, removeProcessing } = actions;\n\n  const saveBlurHash = useCallback(\n    /**\n     *\n     * @param {number} id Video ID.\n     * @param {string} blurHash Base Color.\n     * @return {Promise<void>}\n     */\n    async (id, blurHash) => {\n      try {\n        const properties = ({ resource }) => ({\n          resource: {\n            ...resource,\n            blurHash,\n          },\n        });\n        updateElementsByResourceId({ id, properties });\n        updateMediaElement({\n          id,\n          data: { blurHash },\n        });\n        if (hasUploadMediaAction) {\n          await updateMedia(id, {\n            blurHash,\n          });\n        }\n      } catch {\n        // This might happen as an author when trying to updateMedia() that\n        // was uploaded by someone else.\n        // Do nothing with the error for now.\n      }\n    },\n    [\n      updateElementsByResourceId,\n      updateMediaElement,\n      hasUploadMediaAction,\n      updateMedia,\n    ]\n  );\n\n  const updateBlurHash = useCallback(\n    async (resource) => {\n      const { type, poster, id, isExternal } = resource;\n      let imageSrc = poster;\n\n      if (type === 'image') {\n        imageSrc = getSmallestUrlForWidth(300, resource);\n      } else if (!isExternal) {\n        try {\n          const posterResource = getPosterMediaById\n            ? await getPosterMediaById(id)\n            : null;\n          if (posterResource) {\n            imageSrc = getSmallestUrlForWidth(300, posterResource);\n          }\n        } catch {\n          // The user might not have the permission to access the video with context=edit.\n          // This might happen as an author when the video\n          // was uploaded by someone else.\n          // Do nothing with the error for now.\n        }\n      }\n\n      if (!imageSrc) {\n        return;\n      }\n      const imageSrcProxied = getProxiedUrl(resource, imageSrc);\n      try {\n        const blurHash = await getBlurHashFromImage(imageSrcProxied);\n        await saveBlurHash(resource.id, blurHash);\n      } catch (error) {\n        trackError('blurhash_generation', error?.message);\n      }\n    },\n    [getProxiedUrl, getPosterMediaById, saveBlurHash]\n  );\n\n  const maybeUpdateBlurHash = useCallback(\n    async (resource) => {\n      const { id } = resource;\n\n      // Simple way to prevent double-uploading.\n      if (processed.includes(id) || processing.includes(id)) {\n        return;\n      }\n\n      addProcessing(id);\n      await updateBlurHash(resource);\n      removeProcessing(id);\n    },\n    [addProcessing, processed, processing, removeProcessing, updateBlurHash]\n  );\n\n  return {\n    updateBlurHash: maybeUpdateBlurHash,\n  };\n}\n\nexport default useDetectBlurHash;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useDetectVideoHasAudio.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  hasVideoGotAudio,\n  preloadVideo,\n  type ResourceId,\n  seekVideo,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useStory } from '../../story';\nimport { useConfig } from '../../config';\n\nfunction useDetectVideoHasAudio({\n  updateMediaElement,\n}: {\n  updateMediaElement: ({\n    id,\n    data,\n  }: {\n    id: string | number;\n    data: Record<string, unknown>;\n  }) => void;\n}) {\n  const {\n    actions: { updateMedia },\n  } = useAPI();\n  const { updateElementsByResourceId } = useStory((state) => ({\n    updateElementsByResourceId: state.actions.updateElementsByResourceId,\n  }));\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const updateVideoIsMuted = useCallback(\n    /**\n     *\n     * @param id Video ID.\n     * @param src Video URL.\n     */\n    async (id: ResourceId, src: string) => {\n      try {\n        const video = await preloadVideo(src);\n        await seekVideo(video);\n        const hasAudio = hasVideoGotAudio(video);\n\n        updateElementsByResourceId({\n          id,\n          properties: ({ resource }) => ({\n            resource: {\n              ...resource,\n              isMuted: !hasAudio,\n            },\n          }),\n        });\n        updateMediaElement({\n          id,\n          data: {\n            isMuted: !hasAudio,\n          },\n        });\n\n        if (hasUploadMediaAction && updateMedia) {\n          await updateMedia(id, {\n            isMuted: !hasAudio,\n          });\n        }\n      } catch {\n        // Do nothing for now.\n      }\n    },\n    [\n      hasUploadMediaAction,\n      updateElementsByResourceId,\n      updateMediaElement,\n      updateMedia,\n    ]\n  );\n\n  return {\n    updateVideoIsMuted,\n  };\n}\n\nexport default useDetectVideoHasAudio;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useFFmpeg.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\nimport {\n  getExtensionFromMimeType,\n  getFileBasename,\n  blobToFile,\n  readFile,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport type { FFmpeg } from '@ffmpeg/ffmpeg';\nimport { useConfig } from '../../config';\nimport { useCurrentUser } from '../../currentUser';\nimport {\n  MEDIA_TRANSCODING_MAX_FILE_SIZE,\n  MEDIA_VIDEO_DIMENSIONS_THRESHOLD,\n  MEDIA_TRANSCODED_MIME_TYPE,\n  MEDIA_TRANSCODED_FILE_TYPE,\n  MEDIA_POSTER_IMAGE_MIME_TYPE,\n  MEDIA_POSTER_IMAGE_FILE_TYPE,\n} from '../../../constants';\nimport { TRANSCODABLE_MIME_TYPES } from '../constants';\nimport type { CropParams } from '../types';\nimport getPosterName from './getPosterName';\n\nconst isDevelopment =\n  typeof WEB_STORIES_ENV !== 'undefined' && WEB_STORIES_ENV === 'development';\n\n/**\n * Checks whether the file size is too large for transcoding.\n *\n * @see https://github.com/ffmpegwasm/ffmpeg.wasm/tree/9b56b7f05b552c404aa0f62f46bed2592d9daf06#what-is-the-maximum-size-of-input-file\n * @param file File object.\n * @return Whether the file is too  large.\n */\nconst isFileTooLarge = ({ size }: File) =>\n  size >= MEDIA_TRANSCODING_MAX_FILE_SIZE;\n\nconst FFMPEG_CONFIG = {\n  CODEC: [\n    // Use H.264 video codec.\n    '-vcodec',\n    'libx264',\n  ],\n  SCALE: [\n    // Scale down to 720p as recommended by Storytime.\n    // See https://trac.ffmpeg.org/wiki/Scaling\n    // Adds 1px pad to width/height if they're not divisible by 2, which FFmpeg will complain about.\n    '-vf',\n    `scale='min(${MEDIA_VIDEO_DIMENSIONS_THRESHOLD.WIDTH},iw)':'min(${MEDIA_VIDEO_DIMENSIONS_THRESHOLD.HEIGHT},ih)':'force_original_aspect_ratio=decrease',pad='width=ceil(iw/2)*2:height=ceil(ih/2)*2'`,\n  ],\n  FPS: [\n    // Reduce to 24fps as recommended by Storytime.\n    // See https://trac.ffmpeg.org/wiki/ChangingFrameRate\n    '-r',\n    '24',\n  ],\n  FASTSTART: [\n    // move some information to the beginning of your file.\n    '-movflags',\n    '+faststart',\n  ],\n  COLOR_PROFILE: [\n    // Simpler color profile\n    '-pix_fmt',\n    'yuv420p',\n  ],\n  PRESET: [\n    // As the name says...\n    '-preset',\n    'fast', // 'veryfast' seems to cause crashes.\n  ],\n  SEEK_TO_START: [\n    // Desired position.\n    // Using as an input option (before -i) saves us some time by seeking to position.\n    '-ss',\n    '00:00:01.000',\n  ],\n  SINGLE_FRAME: [\n    // Stop writing to the stream after 1 frame.\n    '-frames:v',\n    '1',\n  ],\n};\n\nconst FFMPEG_SHARED_CONFIG = [\n  ...FFMPEG_CONFIG.CODEC,\n  ...FFMPEG_CONFIG.SCALE,\n  ...FFMPEG_CONFIG.FPS,\n  ...FFMPEG_CONFIG.FASTSTART,\n  ...FFMPEG_CONFIG.COLOR_PROFILE,\n  ...FFMPEG_CONFIG.PRESET,\n];\n\n/**\n * @typedef FFmpegData\n * @property {boolean} isTranscodingEnabled Whether transcoding is enabled.\n * @property {(file: File) => boolean} canTranscodeFile Whether a given file can be transcoded.\n * @property {(file: File) => boolean} isFileTooLarge Whether a given file is too large.\n * @property {(file: File) => Promise<File>} transcodeVideo Transcode a given video.\n * @property {(file: File) => Promise<File>} stripAudioFromVideo Strip audio from given video.\n * @property {(file: File) => Promise<File>} getFirstFrameOfVideo Get the first frame of a video.\n * @property {(file: File) => Promise<File>} convertGifToVideo Convert GIF to MP4.\n */\n\n/**\n * Custom hook to interact with FFmpeg.\n *\n * @see https://ffmpeg.org/ffmpeg.html\n * @return Functions and vars related to FFmpeg usage.\n */\nfunction useFFmpeg() {\n  const {\n    ffmpegCoreUrl,\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const { currentUser } = useCurrentUser(({ state }) => ({\n    currentUser: state.currentUser,\n  }));\n\n  /**\n   * Whether the video optimization feature is enabled.\n   *\n   * @type {boolean} Whether the feature flag is enabled.\n   */\n  const isCrossOriginIsolationEnabled = Boolean(window?.crossOriginIsolated);\n\n  const getFFmpegInstance = useCallback(\n    async (file: File) => {\n      const { createFFmpeg } = await import(\n        /* webpackChunkName: \"chunk-ffmpeg\" */\n        '@ffmpeg/ffmpeg'\n      );\n\n      const ffmpeg = createFFmpeg({\n        corePath: ffmpegCoreUrl,\n        log: isDevelopment,\n      });\n      await ffmpeg.load();\n\n      ffmpeg.FS('writeFile', file.name, await readFile(file));\n\n      return ffmpeg;\n    },\n    [ffmpegCoreUrl]\n  );\n\n  /**\n   * Extract a video's first frame using FFmpeg.\n   *\n   * Exact seeking is not possible in most formats, so ffmpeg will seek to the closest seek point before position.\n   *\n   * @param {File} file Original video file object.\n   * @return {Promise<File>} File object for the video frame.\n   */\n  const getFirstFrameOfVideo = useCallback(\n    async (file: File) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_video_poster_ffmpeg');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const tempFileName = uuidv4() + '.' + MEDIA_POSTER_IMAGE_FILE_TYPE;\n        const originalFileName = getFileBasename(file);\n        const outputFileName = getPosterName(originalFileName);\n\n        await ffmpeg.run(\n          ...FFMPEG_CONFIG.SEEK_TO_START,\n          // Input filename.\n          '-i',\n          file.name,\n          ...FFMPEG_CONFIG.SINGLE_FRAME,\n          ...FFMPEG_CONFIG.SCALE,\n          ...FFMPEG_CONFIG.COLOR_PROFILE,\n          ...FFMPEG_CONFIG.PRESET,\n          // Output filename. MUST be different from input filename.\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], {\n            type: MEDIA_POSTER_IMAGE_MIME_TYPE,\n          }),\n          outputFileName,\n          MEDIA_POSTER_IMAGE_MIME_TYPE\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('video_poster_generation_ffmpeg', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Transcode a video using FFmpeg.\n   *\n   * @param {File} file Original video file object.\n   * @return {Promise<File>} Transcoded video file object.\n   */\n  const transcodeVideo = useCallback(\n    async (file: File) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_video_transcoding');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const tempFileName = uuidv4() + '.' + MEDIA_TRANSCODED_FILE_TYPE;\n        const outputFileName =\n          getFileBasename(file) + '.' + MEDIA_TRANSCODED_FILE_TYPE;\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          ...FFMPEG_SHARED_CONFIG,\n          // Output filename. MUST be different from input filename.\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], {\n            type: MEDIA_TRANSCODED_MIME_TYPE,\n          }),\n          outputFileName,\n          MEDIA_TRANSCODED_MIME_TYPE\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('video_transcoding', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Segment a video using FFmpeg.\n   *\n   * @param {File} file Original video file object.\n   * @param {string} segmentTime number of secs to split the video into.\n   * @return {Promise<File[]>} Segmented video files .\n   */\n  const segmentVideo = useCallback(\n    async (file: File, segmentTime: number, fileLength: number) => {\n      // eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('segment_video');\n\n      let ffmpeg: FFmpeg | undefined;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n        const type = file?.type || MEDIA_TRANSCODED_MIME_TYPE;\n        const ext = getExtensionFromMimeType(type);\n\n        if (!ext) {\n          throw new Error('Invalid file extension');\n        }\n\n        const outputFileName = getFileBasename(file) + '_%03d.' + ext;\n        const keyframes = [];\n        for (let i = segmentTime; i < fileLength; i += segmentTime) {\n          keyframes.push(i);\n        }\n        const segmentTimes = keyframes.join(',');\n\n        await ffmpeg.run(\n          '-i',\n          file.name,\n          '-c',\n          'copy',\n          '-map',\n          '0',\n          '-force_key_frames',\n          `${segmentTimes}`,\n          '-f',\n          'segment',\n          '-segment_times',\n          `${segmentTimes}`,\n          '-segment_time_delta', //account for possible roundings operated when setting key frame times.\n          `${(1 / (2 * Number(FFMPEG_CONFIG.FPS[1]))).toFixed(2)}`,\n          '-reset_timestamps',\n          '1',\n          outputFileName\n        );\n\n        return ffmpeg\n          .FS('readdir', '/')\n          .filter(\n            (outputFile) =>\n              outputFile !== file.name && outputFile.endsWith(`.${ext}`)\n          )\n          .map((outputFile) => {\n            const data = (ffmpeg as FFmpeg).FS('readFile', outputFile);\n            return blobToFile(\n              new Blob([data.buffer as BlobPart], { type }),\n              outputFile,\n              type\n            );\n          })\n          .sort((a, b) => a.name.localeCompare(b.name));\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('segment_video', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Trim Video using FFmpeg.\n   *\n   * @param {File} file Original video file object.\n   * @param {string} start Time stamp of start time of new video. Example '00:01:02.345'.\n   * @param {string} end Time stamp of end time of new video. Example '00:02:00'.\n   * @return {Promise<File>} Transcoded video file object.\n   */\n  const trimVideo = useCallback(\n    async (file: File, start: string, end: string) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_trim_video_transcoding');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const type = file?.type || MEDIA_TRANSCODED_MIME_TYPE;\n        const ext = getExtensionFromMimeType(type);\n\n        if (!ext) {\n          throw new Error('Invalid file extension');\n        }\n\n        const tempFileName = uuidv4() + '.' + ext;\n        const outputFileName = getFileBasename(file) + '-trimmed.' + ext;\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          '-ss',\n          start,\n          '-to',\n          end,\n          tempFileName\n        );\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], { type }),\n          outputFileName,\n          type\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.log(err);\n\n        if (err instanceof Error) {\n          void trackError('trim_video_transcoding', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Crop Video to remove portions of the video using FFmpeg.\n   */\n  const cropVideo = useCallback(\n    async (file: File, cropParams: CropParams) => {\n      let ffmpeg;\n\n      const { cropWidth, cropHeight, cropX, cropY } = cropParams;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const type = file?.type || MEDIA_TRANSCODED_MIME_TYPE;\n        const ext = getExtensionFromMimeType(type);\n\n        if (!ext) {\n          throw new Error('Invalid file extension');\n        }\n\n        const tempFileName = uuidv4() + '.' + ext;\n        const outputFileName = getFileBasename(file) + '-cropped.' + ext;\n        const crop = `crop=${cropWidth}:${cropHeight}:${cropX}:${cropY}`;\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          '-vf',\n          crop,\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], { type }),\n          outputFileName,\n          type\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.log(err);\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Strip audio from video using FFmpeg.\n   *\n   * @param {File} file Original video file object.\n   * @return {Promise<File>} Transcoded video file object.\n   */\n  const stripAudioFromVideo = useCallback(\n    async (file: File) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_mute_video_transcoding');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const type = file?.type || MEDIA_TRANSCODED_MIME_TYPE;\n        const ext = getExtensionFromMimeType(type);\n\n        if (!ext) {\n          throw new Error('Invalid file extension');\n        }\n\n        const tempFileName = uuidv4() + '.' + ext;\n        const outputFileName = getFileBasename(file) + '-muted.' + ext;\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          '-vcodec',\n          'copy',\n          // Mute audio from video.\n          '-an',\n          // Output filename. MUST be different from input filename.\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], { type }),\n          outputFileName,\n          type\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.log(err);\n\n        if (err instanceof Error) {\n          void trackError('mute_video_transcoding', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n        } catch {\n          // Not interested in errors here.\n        }\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Converts an animated GIF to a video using FFmpeg.\n   *\n   * @param {File} file Original GIF file object.\n   * @return {Promise<File>} Converted video file object.\n   */\n  const convertGifToVideo = useCallback(\n    async (file: File) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_gif_conversion');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const tempFileName = uuidv4() + '.' + MEDIA_TRANSCODED_FILE_TYPE;\n        const outputFileName =\n          getFileBasename(file) + '.' + MEDIA_TRANSCODED_FILE_TYPE;\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          ...FFMPEG_SHARED_CONFIG,\n          // Output filename. MUST be different from input filename.\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], {\n            type: MEDIA_TRANSCODED_MIME_TYPE,\n          }),\n          outputFileName,\n          MEDIA_TRANSCODED_MIME_TYPE\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('gif_conversion', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n          // eslint-disable-next-line no-empty -- no-op\n        } catch {}\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Converts any audio file format to MP3 using FFmpeg.\n   *\n   * @param {File} file Original audio file object.\n   * @return {Promise<File>} Converted video file object.\n   */\n  const convertToMp3 = useCallback(\n    async (file: File) => {\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_mp3_conversion');\n\n      let ffmpeg;\n\n      try {\n        ffmpeg = await getFFmpegInstance(file);\n\n        const tempFileName = uuidv4() + '.mp3';\n        const outputFileName = getFileBasename(file) + '.mp3';\n\n        await ffmpeg.run(\n          // Input filename.\n          '-i',\n          file.name,\n          // Output filename. MUST be different from input filename.\n          tempFileName\n        );\n\n        const data = ffmpeg.FS('readFile', tempFileName);\n\n        return blobToFile(\n          new Blob([data.buffer as BlobPart], { type: 'audio/mpeg' }),\n          outputFileName,\n          'audio/mpeg'\n        );\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('mp3_conversion', err.message);\n        }\n\n        throw err;\n      } finally {\n        try {\n          ffmpeg?.exit();\n          // eslint-disable-next-line no-empty -- no-op\n        } catch {}\n\n        trackTiming();\n      }\n    },\n    [getFFmpegInstance]\n  );\n\n  /**\n   * Determines whether the given file can be transcoded.\n   */\n  const canTranscodeFile = useCallback(\n    (file: File) => TRANSCODABLE_MIME_TYPES.includes(file.type),\n    []\n  );\n\n  /**\n   * Whether user opted in to video optimization.\n   */\n  const isUserSettingEnabled = Boolean(currentUser?.mediaOptimization);\n\n  /**\n   * Whether transcoding as a whole is supported.\n   *\n   * Considers user opt-in, cross-site isolation, and upload permissions.\n   */\n  const isTranscodingEnabled = Boolean(\n    hasUploadMediaAction &&\n    isUserSettingEnabled &&\n    isCrossOriginIsolationEnabled\n  );\n\n  return useMemo(\n    () => ({\n      isTranscodingEnabled,\n      canTranscodeFile,\n      isFileTooLarge,\n      transcodeVideo,\n      stripAudioFromVideo,\n      getFirstFrameOfVideo,\n      convertGifToVideo,\n      convertToMp3,\n      trimVideo,\n      cropVideo,\n      segmentVideo,\n    }),\n    [\n      isTranscodingEnabled,\n      canTranscodeFile,\n      transcodeVideo,\n      stripAudioFromVideo,\n      getFirstFrameOfVideo,\n      convertGifToVideo,\n      convertToMp3,\n      trimVideo,\n      cropVideo,\n      segmentVideo,\n    ]\n  );\n}\n\nexport default useFFmpeg;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useMediaInfo.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport {\n  getTimeTracker,\n  trackError,\n  trackEvent,\n} from '@googleforcreators/tracking';\nimport type { VideoResource } from '@googleforcreators/media';\nimport type { ReadChunkFunc } from 'mediainfo.js';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../config';\nimport {\n  MEDIA_VIDEO_DIMENSIONS_THRESHOLD,\n  MEDIA_VIDEO_FILE_SIZE_THRESHOLD,\n  MEDIA_MIME_TYPES_OPTIMIZED_VIDEOS,\n  MEDIA_RECOMMENDED_MAX_VIDEO_DURATION,\n  MEDIA_RECOMMENDED_MIN_VIDEO_FPS,\n} from '../../../constants';\n\n// More specific types than the ones from mediainfo.js\n// See also https://github.com/MediaArea/MediaInfoLib/tree/master/Source/Resource/Text/Stream\n\ninterface GeneralTrack {\n  '@type': 'General';\n  FileSize: string;\n  Format: string;\n  FrameRate: string;\n  CodecID?: string;\n}\n\ninterface ImageTrack {\n  '@type': 'Image';\n  Width: string;\n  Height: string;\n  ColorSpace: string;\n}\ninterface VideoTrack {\n  '@type': 'Video';\n  Width: string;\n  Height: string;\n  ColorSpace: string;\n  Duration: string;\n  Format: string;\n}\n\ninterface AudioTrack {\n  '@type': 'Audio';\n  Format: string;\n}\n\ntype Track = GeneralTrack | ImageTrack | VideoTrack | AudioTrack;\n\ninterface ResultObject {\n  '@ref': string;\n  media: {\n    track: Track[];\n  };\n}\n\ninterface MediaInfoResult {\n  mimeType: string;\n  fileSize: number;\n  format?: string;\n  codec?: string;\n  frameRate?: number;\n  height: number;\n  width: number;\n  colorSpace?: string;\n  duration: number;\n  videoCodec?: string;\n  audioCodec?: string;\n  isMuted?: boolean;\n}\n\n/**\n * Determines whether the resource/file has small enough dimensions.\n *\n * @param obj Dimensions object.\n * @param obj.width Width.\n * @param obj.height Height.\n * @return Whether the resource/file has small enough dimensions.\n */\nconst hasSmallDimensions = ({\n  width,\n  height,\n}: {\n  width: number;\n  height: number;\n}) =>\n  width * height <=\n  MEDIA_VIDEO_DIMENSIONS_THRESHOLD.WIDTH *\n    MEDIA_VIDEO_DIMENSIONS_THRESHOLD.HEIGHT;\n\n/**\n * Whether the file has a reasonable file size / duration ratio.\n *\n * The recommendation for videos in stories is to be < 15s in duration\n * and < 4 MB in size. If uploading a longer video,\n * it is only natural that it will exceed the size limit.\n * Thus, we're instead checking for the average size per second.\n * Example: 4MB for a 15s video, 12MB for a 45s long video.\n *\n * @todo Revisit to avoid fallacy that we're OK with such large file sizes.\n * @param fileSize File size.\n * @param duration Duration.\n * @return Whether the file has a good file size / duration ratio.\n */\nconst hasSmallFileSize = (fileSize: number, duration: number) =>\n  fileSize <=\n  (MEDIA_VIDEO_FILE_SIZE_THRESHOLD / MEDIA_RECOMMENDED_MAX_VIDEO_DURATION) *\n    duration;\n\n/**\n * Custom hook to interact with mediainfo.js.\n *\n * @see https://mediainfo.js.org/\n * @return Functions and vars related to mediainfo.js usage.\n */\nfunction useMediaInfo() {\n  const { mediainfoUrl } = useConfig();\n\n  const getFileInfo = useCallback(\n    /**\n     * Returns information about a given media file.\n     *\n     * @param file File object.\n     * @return File info or null on error.\n     */\n    async (file: File) => {\n      const getSize = () => file.size;\n\n      // TODO: Look into using createFileReader from media package.\n      const readChunk: ReadChunkFunc = (chunkSize, offset) =>\n        new Promise((resolve, reject) => {\n          const reader = new FileReader();\n          reader.onerror = reject;\n          reader.onload = (event) => {\n            if (event.target?.error) {\n              reject(event.target.error);\n            }\n            resolve(new Uint8Array(event.target?.result as ArrayBuffer));\n          };\n          reader.readAsArrayBuffer(file.slice(offset, offset + chunkSize));\n        });\n\n      //eslint-disable-next-line @wordpress/no-unused-vars-before-return -- False positive because of the finally().\n      const trackTiming = getTimeTracker('load_mediainfo');\n\n      try {\n        const { default: MediaInfoFactory } = await import(\n          /* webpackChunkName: \"chunk-mediainfo\" */\n          'mediainfo.js'\n        );\n\n        const mediaInfo = await MediaInfoFactory({\n          format: 'JSON',\n          locateFile: () => mediainfoUrl,\n        });\n\n        const result: ResultObject = JSON.parse(\n          (await mediaInfo.analyzeData(getSize, readChunk)) as unknown as string\n        ) as ResultObject;\n\n        const normalizedResult: MediaInfoResult = result.media.track.reduce(\n          (acc: MediaInfoResult, track) => {\n            if (track['@type'] === 'General') {\n              acc.fileSize = Number(track.FileSize);\n              acc.format = track.Format.toLowerCase().replace('mpeg-4', 'mp4');\n              acc.frameRate = Number(Number(track.FrameRate).toFixed(0));\n              acc.codec = track.CodecID?.trim();\n            }\n\n            if (track['@type'] === 'Image' || track['@type'] === 'Video') {\n              acc.width = Number(track.Width);\n              acc.height = Number(track.Height);\n              acc.colorSpace = track.ColorSpace; // Maybe useful in the future.\n            }\n\n            if (track['@type'] === 'Video') {\n              acc.duration = Number(track.Duration);\n              acc.videoCodec = track.Format.toLowerCase();\n            }\n\n            if (track['@type'] === 'Audio') {\n              acc.audioCodec = track.Format.toLowerCase();\n            }\n\n            return acc;\n          },\n          {\n            mimeType: file.type,\n          } as MediaInfoResult\n        );\n\n        normalizedResult.isMuted = !normalizedResult.audioCodec;\n\n        mediaInfo.close();\n\n        return normalizedResult;\n      } catch (err) {\n        // eslint-disable-next-line no-console -- We want to surface this error.\n        console.error(err);\n\n        if (err instanceof Error) {\n          void trackError('mediainfo', err.message);\n        }\n\n        return null;\n      } finally {\n        trackTiming();\n      }\n    },\n    [mediainfoUrl]\n  );\n\n  const isConsideredOptimized = useCallback(\n    /**\n     * Determines whether a video file is to be considered optimized.\n     *\n     * Checks things like dimensions, file size, mime type, and codecs.\n     *\n     * @todo Allow WebM with VP9 once Safari catches up.\n     * @param resource Resource object.\n     * @param file File object.\n     * @return Whether the file meets optimization criteria.\n     */\n    async (resource: VideoResource, file: File) => {\n      // This should never happen, but just in case.\n      if (resource.isOptimized) {\n        return true;\n      }\n\n      // Short-circuit for non-matching mime types.\n      if (!MEDIA_MIME_TYPES_OPTIMIZED_VIDEOS.includes(resource.mimeType)) {\n        return false;\n      }\n\n      // Placeholders are the size of the canvas, so account for that when\n      // checking the dimensions.\n      if (!resource.isPlaceholder && !hasSmallDimensions(resource)) {\n        return false;\n      }\n\n      if (\n        file.size &&\n        resource.length &&\n        !hasSmallFileSize(file.size, resource.length)\n      ) {\n        return false;\n      }\n\n      const fileInfo = await getFileInfo(file);\n\n      if (!fileInfo) {\n        return false;\n      }\n\n      // AVC is H.264.\n      const isSupportedMp4 =\n        fileInfo.mimeType === 'video/mp4' && fileInfo.videoCodec === 'avc';\n\n      const hasHighFps =\n        !fileInfo.frameRate ||\n        fileInfo.frameRate >= MEDIA_RECOMMENDED_MIN_VIDEO_FPS;\n\n      // Video is small enough and uses a widely supported codec.\n      const result =\n        hasSmallFileSize(fileInfo.fileSize, fileInfo.duration) &&\n        hasSmallDimensions(fileInfo) &&\n        isSupportedMp4 &&\n        hasHighFps;\n\n      void trackEvent('mediainfo_is_optimized', {\n        result,\n        file_size: fileInfo.fileSize,\n        file_type: fileInfo.mimeType,\n        width: fileInfo.width,\n        height: fileInfo.height,\n        duration: fileInfo.duration,\n      });\n\n      return result;\n    },\n    [getFileInfo]\n  );\n\n  return useMemo(\n    () => ({\n      getFileInfo,\n      isConsideredOptimized,\n    }),\n    [getFileInfo, isConsideredOptimized]\n  );\n}\n\nexport default useMediaInfo;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useProcessMedia.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  fetchRemoteBlob,\n  fetchRemoteFile,\n  isAnimatedGif,\n  type Resource,\n  type ResourceId,\n  type VideoResource,\n} from '@googleforcreators/media';\nimport { DANGER_ZONE_HEIGHT } from '@googleforcreators/units';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ElementId,\n  ElementType,\n  MediaElement,\n} from '@googleforcreators/elements';\nimport useAPI from '../../api/useAPI';\nimport useStory from '../../story/useStory';\nimport type { CropParams, UpdateMediaProps, UploadMediaArgs } from '../types';\nimport useFFmpeg from './useFFmpeg';\nimport useMediaInfo from './useMediaInfo';\n\ninterface UseProcessMediaProps {\n  uploadMedia: (files: File[], args: UploadMediaArgs) => Promise<string | null>;\n  postProcessingResource: (resource: Resource) => void;\n  updateMedia: (id: ResourceId, data: UpdateMediaProps) => void;\n  deleteMediaElement: (args: { id: ResourceId }) => void;\n}\n\nfunction useProcessMedia({\n  uploadMedia,\n  postProcessingResource,\n  updateMedia,\n  deleteMediaElement,\n}: UseProcessMediaProps) {\n  const {\n    actions: { getOptimizedMediaById, getMutedMediaById },\n  } = useAPI();\n\n  const { segmentVideo: ffSegmentVideo } = useFFmpeg();\n\n  const { updateElementsByResourceId, updateElementById } = useStory(\n    (state) => ({\n      updateElementsByResourceId: state.actions.updateElementsByResourceId,\n      updateElementById: state.actions.updateElementById,\n    })\n  );\n  const { isConsideredOptimized } = useMediaInfo();\n\n  const copyResourceData = useCallback(\n    ({\n      oldResource,\n      resource,\n    }: {\n      oldResource: Resource;\n      resource: Resource;\n    }) => {\n      const { id, alt } = oldResource;\n\n      updateElementsByResourceId({\n        id,\n        properties: () => {\n          return {\n            type: resource.type as unknown as ElementType,\n            resource: {\n              ...resource,\n              alt,\n            },\n          };\n        },\n      });\n    },\n    [updateElementsByResourceId]\n  );\n\n  const copyResourceDataByElementId = useCallback(\n    ({\n      elementId,\n      oldResource,\n      resource,\n    }: {\n      elementId: ElementId;\n      oldResource: Pick<Resource, 'id' | 'alt'>;\n      resource: Resource;\n    }) => {\n      const { alt } = oldResource;\n\n      updateElementById<MediaElement>({\n        elementId,\n        properties: () => {\n          return {\n            type: resource.type as unknown as ElementType,\n            resource: {\n              ...resource,\n              alt,\n            },\n          };\n        },\n      });\n    },\n    [updateElementById]\n  );\n\n  const updateExistingElementById = useCallback(\n    <T extends Resource = Resource>(\n      elementId: ElementId,\n      resource: Partial<T>\n    ) => {\n      updateElementById<MediaElement>({\n        elementId,\n        properties: (element) => {\n          return {\n            resource: {\n              ...element.resource,\n              ...resource,\n            },\n          };\n        },\n      });\n    },\n    [updateElementById]\n  );\n\n  const updateExistingElementsByResourceId = useCallback(\n    <T extends Resource = Resource>(\n      resourceId: ResourceId,\n      resource: Partial<T>\n    ) => {\n      updateElementsByResourceId({\n        id: resourceId,\n        properties: (element) => {\n          return {\n            resource: {\n              ...element.resource,\n              ...resource,\n            },\n          };\n        },\n      });\n    },\n    [updateElementsByResourceId]\n  );\n\n  const updateOldTranscodedObject = useCallback(\n    (oldId: ResourceId, newId: ResourceId, mediaSource: string) => {\n      updateMedia(oldId, {\n        mediaSource,\n        optimizedId: newId,\n      });\n    },\n    [updateMedia]\n  );\n\n  const updateOldMutedObject = useCallback(\n    (oldId: ResourceId, newId: ResourceId) => {\n      updateMedia(oldId, {\n        mutedId: newId,\n      });\n    },\n    [updateMedia]\n  );\n\n  /**\n   * Optimize video existing video using FFmpeg.\n   *\n   * @param resource Resource object.\n   */\n  const optimizeVideo = useCallback(\n    ({ resource: oldResource }: { resource: VideoResource }) => {\n      const { id: resourceId, src: url, mimeType } = oldResource;\n\n      const onUploadError = () =>\n        updateExistingElementsByResourceId(resourceId, {\n          isOptimized: false,\n        });\n\n      const onUploadSuccess = ({\n        id,\n        resource,\n      }: {\n        id: ResourceId;\n        resource: Resource;\n      }) => {\n        copyResourceData({ oldResource, resource });\n        updateOldTranscodedObject(resourceId, resource.id, 'source-video');\n        deleteMediaElement({ id: resourceId });\n\n        // onUploadSuccess is also called with previousResourceId,\n        // for which we don't need to run this.\n        if (id === resource.id) {\n          postProcessingResource(resource);\n        }\n      };\n\n      // TODO: Confirm which properties exactly need to be updated.\n      const onUploadProgress = ({ resource }: { resource: Resource }) => {\n        const oldResourceWithId = { ...resource, id: oldResource.id };\n        updateExistingElementsByResourceId(resourceId, {\n          ...oldResourceWithId,\n        });\n      };\n\n      void (async () => {\n        if (getOptimizedMediaById) {\n          const optimizedResource = await getOptimizedMediaById(resourceId);\n\n          // This video was optimized before, no need to optimize it again.\n          if (optimizedResource) {\n            updateExistingElementsByResourceId(resourceId, optimizedResource);\n            return;\n          }\n        }\n\n        let file = null;\n        try {\n          file = await fetchRemoteFile(url, mimeType);\n        } catch {\n          // Ignore for now.\n          return;\n        }\n\n        // Video meets criteria to be considered optimized,\n        // just mark it as such and call it a day.\n        if (await isConsideredOptimized(oldResource, file)) {\n          updateExistingElementsByResourceId(resourceId, { isOptimized: true });\n          updateMedia(resourceId, {\n            mediaSource: 'video-optimization',\n          });\n          return;\n        }\n\n        await uploadMedia([file], {\n          onUploadSuccess,\n          onUploadError,\n          onUploadProgress,\n          additionalData: {\n            originalId: oldResource.id,\n            isMuted: oldResource.isMuted,\n          },\n          originalResourceId: oldResource.id,\n        });\n      })();\n    },\n    [\n      updateExistingElementsByResourceId,\n      copyResourceData,\n      updateOldTranscodedObject,\n      deleteMediaElement,\n      postProcessingResource,\n      getOptimizedMediaById,\n      uploadMedia,\n      isConsideredOptimized,\n      updateMedia,\n    ]\n  );\n\n  /**\n   * Trim existing video using FFmpeg.\n   *\n   * @param resource Resource object.\n   * @param {string} start Time stamp of start time of new video. Example '00:01:02.345'.\n   * @param {string} end Time stamp of end time of new video. Example '00:02:00'.\n   */\n  const trimExistingVideo = useCallback(\n    ({\n      resource: oldResource,\n      canvasResourceId,\n      elementId,\n      start,\n      end,\n    }: {\n      resource: VideoResource;\n      canvasResourceId: ResourceId;\n      elementId: ElementId;\n      start: string;\n      end: string;\n    }) => {\n      const { id: resourceId, ...oldResourceWithoutId } = oldResource;\n      const { src: url, mimeType, poster, isMuted, isOptimized } = oldResource;\n\n      const trimData = {\n        original: resourceId,\n        start,\n        end,\n      };\n\n      const onUploadStart = () =>\n        updateExistingElementById<VideoResource>(elementId, {\n          trimData,\n        });\n\n      const onUploadError = () =>\n        updateExistingElementById<VideoResource>(elementId, {\n          trimData: oldResource.trimData || undefined,\n        });\n\n      const onUploadSuccess = ({\n        id,\n        resource,\n      }: {\n        id: ResourceId;\n        resource: Resource;\n      }) => {\n        const oldCanvasResource: Pick<Resource, 'id' | 'alt'> = {\n          alt: oldResource.alt,\n          id: canvasResourceId,\n        };\n        copyResourceDataByElementId({\n          elementId,\n          oldResource: oldCanvasResource,\n          resource,\n        });\n\n        // onUploadSuccess is also called with previousResourceId,\n        // for which we don't need to run this.\n        if (id === resource.id) {\n          postProcessingResource(resource);\n        }\n      };\n\n      const onUploadProgress = ({ resource }: { resource: Resource }) => {\n        const newResourceWithCanvasId = { ...resource, id: canvasResourceId };\n        updateExistingElementById(elementId, {\n          ...newResourceWithCanvasId,\n        });\n      };\n\n      const process = async () => {\n        let file = null;\n        let posterFile = null;\n        try {\n          file = await fetchRemoteFile(url, mimeType);\n        } catch {\n          // Ignore for now.\n          return;\n        }\n        if (poster) {\n          try {\n            posterFile = await fetchRemoteBlob(poster);\n          } catch {\n            // Ignore for now.\n          }\n        }\n\n        await uploadMedia([file], {\n          onUploadSuccess,\n          onUploadStart,\n          onUploadError,\n          onUploadProgress,\n          additionalData: {\n            originalId: resourceId,\n            isMuted,\n            trimData,\n            mediaSource: isOptimized ? 'video-optimization' : 'editor',\n          },\n          elementId,\n          trimData,\n          resource: {\n            ...oldResourceWithoutId,\n            trimData,\n          },\n          originalResourceId: canvasResourceId,\n          posterFile,\n        });\n      };\n      return process();\n    },\n    [\n      updateExistingElementById,\n      copyResourceDataByElementId,\n      postProcessingResource,\n      uploadMedia,\n    ]\n  );\n\n  /**\n   * Mute existing video using FFmpeg.\n   *\n   * @param resource Resource object.\n   */\n  const muteExistingVideo = useCallback(\n    ({ resource: oldResource }: { resource: VideoResource }) => {\n      const { id: resourceId, ...oldResourceWithoutId } = oldResource;\n      const { src: url, mimeType, poster, isOptimized } = oldResource;\n\n      const onUploadError = () => {\n        updateExistingElementsByResourceId<VideoResource>(resourceId, {\n          isMuted: false,\n        });\n      };\n\n      const onUploadSuccess = ({\n        id,\n        resource,\n      }: {\n        id: ResourceId;\n        resource: Resource;\n      }) => {\n        copyResourceData({ oldResource, resource });\n        updateOldMutedObject(oldResource.id, resource.id);\n\n        // onUploadSuccess is also called with previousResourceId,\n        // for which we don't need to run this.\n        if (id === resource.id) {\n          postProcessingResource(resource);\n        }\n      };\n\n      // TODO: Confirm which properties exactly need to be updated.\n      const onUploadProgress = ({ resource }: { resource: Resource }) => {\n        const oldResourceWithId = { ...resource, id: oldResource.id };\n        updateExistingElementsByResourceId(resourceId, {\n          ...oldResourceWithId,\n        });\n      };\n\n      void (async () => {\n        if (getMutedMediaById) {\n          const mutedResource = await getMutedMediaById(resourceId);\n\n          // This video was muted before, no need to mute it again.\n          if (mutedResource) {\n            updateExistingElementsByResourceId(resourceId, mutedResource);\n            return;\n          }\n        }\n\n        let file = null;\n        let posterFile = null;\n        try {\n          file = await fetchRemoteFile(url, mimeType);\n        } catch {\n          // Ignore for now.\n          return;\n        }\n        if (poster) {\n          try {\n            posterFile = await fetchRemoteBlob(poster);\n          } catch {\n            // Ignore for now.\n          }\n        }\n\n        await uploadMedia([file], {\n          onUploadSuccess,\n          onUploadError,\n          onUploadProgress,\n          additionalData: {\n            originalId: resourceId,\n            mediaSource: isOptimized ? 'video-optimization' : 'editor',\n          },\n          muteVideo: true,\n          resource: {\n            ...oldResourceWithoutId,\n            isMuted: true,\n          },\n          originalResourceId: resourceId,\n          posterFile,\n        });\n      })();\n    },\n    [\n      updateExistingElementsByResourceId,\n      copyResourceData,\n      updateOldMutedObject,\n      postProcessingResource,\n      getMutedMediaById,\n      uploadMedia,\n    ]\n  );\n\n  /**\n   * Convert existing gif to a video using FFmpeg.\n   *\n   * @param resource Resource object.\n   */\n  const optimizeGif = useCallback(\n    ({ resource: oldResource }: { resource: Resource }) => {\n      const { id: resourceId, src: url, mimeType } = oldResource;\n\n      const onUploadSuccess = ({\n        id,\n        resource,\n      }: {\n        id: ResourceId;\n        resource: Resource;\n      }) => {\n        copyResourceData({ oldResource, resource });\n        updateOldTranscodedObject(oldResource.id, resource.id, 'source-image');\n        deleteMediaElement({ id: oldResource.id });\n\n        // onUploadSuccess is also called with previousResourceId,\n        // for which we don't need to run this.\n        if (id === resource.id) {\n          postProcessingResource(resource);\n        }\n      };\n\n      // TODO: Confirm which properties exactly need to be updated.\n      const onUploadProgress = ({ resource }: { resource: Resource }) => {\n        const oldResourceWithId = { ...resource, id: oldResource.id };\n        updateExistingElementsByResourceId(resourceId, {\n          ...oldResourceWithId,\n        });\n      };\n\n      const process = async () => {\n        let file = null;\n        try {\n          file = await fetchRemoteFile(url, mimeType);\n        } catch {\n          // Ignore for now.\n          return;\n        }\n\n        const buffer = await file.arrayBuffer();\n        if (!isAnimatedGif(buffer)) {\n          return;\n        }\n\n        await uploadMedia([file], {\n          onUploadSuccess,\n          onUploadProgress,\n          additionalData: {\n            originalId: resourceId,\n          },\n          originalResourceId: resourceId,\n        });\n      };\n      return process();\n    },\n    [\n      copyResourceData,\n      updateOldTranscodedObject,\n      deleteMediaElement,\n      postProcessingResource,\n      updateExistingElementsByResourceId,\n      uploadMedia,\n    ]\n  );\n\n  /**\n   * Crop video using FFmpeg.\n   *\n   * @param resource Resource object.\n   * @param Crop params.\n   */\n  const cropExistingVideo = useCallback(\n    (\n      {\n        id: elementId,\n        resource: oldResource,\n      }: { id: ElementId; resource: Resource },\n      cropParams: CropParams\n    ) => {\n      const { id: resourceId, ...oldResourceWithoutId } = oldResource;\n      const { src: url, mimeType, isOptimized } = oldResource;\n      const { newWidth, newHeight, cropElement } = cropParams;\n\n      const onUploadError = () => {\n        updateExistingElementsByResourceId(resourceId, {\n          height: oldResource.height,\n          width: oldResource.width,\n        });\n      };\n\n      // TODO: Confirm which properties exactly need to be updated.\n      const onUploadProgress = ({ resource }: { resource: Resource }) => {\n        const oldResourceWithId = { ...resource, id: oldResource.id };\n        updateExistingElementsByResourceId(resourceId, {\n          ...oldResourceWithId,\n        });\n      };\n\n      const onUploadSuccess = ({\n        id,\n        resource,\n      }: {\n        id: ResourceId;\n        resource: Resource;\n      }) => {\n        copyResourceData({ oldResource, resource });\n        updateElementById<MediaElement>({\n          elementId,\n          properties: {\n            x: cropElement.x < 0 ? 0 : cropElement.x,\n            y:\n              cropElement.y < DANGER_ZONE_HEIGHT\n                ? -DANGER_ZONE_HEIGHT\n                : cropElement.y,\n            width: newWidth,\n            height: newHeight,\n            resource,\n          },\n        });\n\n        // onUploadSuccess is also called with previousResourceId,\n        // for which we don't need to run this.\n        if (id === resource.id) {\n          postProcessingResource(resource);\n        }\n      };\n\n      const process = async () => {\n        let file = null;\n        try {\n          file = await fetchRemoteFile(url, mimeType);\n          await uploadMedia([file], {\n            onUploadSuccess,\n            onUploadProgress,\n            onUploadError,\n            cropVideo: true,\n            additionalData: {\n              originalId: resourceId,\n              cropOriginId: resourceId,\n              cropParams,\n              mediaSource: isOptimized ? 'video-optimization' : 'editor',\n            },\n            originalResourceId: resourceId,\n            resource: {\n              ...oldResourceWithoutId,\n              width: newWidth,\n              height: newHeight,\n            },\n          });\n        } catch (e) {\n          if (e instanceof Error) {\n            void trackError('crop_existing_video', e.message);\n          }\n          return;\n        }\n      };\n      return process();\n    },\n    [\n      updateElementById,\n      copyResourceData,\n      postProcessingResource,\n      uploadMedia,\n      updateExistingElementsByResourceId,\n    ]\n  );\n\n  /**\n   * Segment video using FFmpeg.\n   *\n   * @param resource Resource object.\n   * @param {Function} onUploadSuccess Callback for when upload finishes.\n   * @return {string|null} Batch ID of the uploaded files on success, null otherwise.\n   */\n  const segmentVideo = useCallback(\n    async (\n      {\n        resource,\n        segmentTime,\n      }: { resource: VideoResource; segmentTime: number },\n      onUploadSuccess: (args: { id: ResourceId; resource: Resource }) => void\n    ) => {\n      try {\n        const { src: url, mimeType } = resource;\n        const segmentedFiles = await ffSegmentVideo(\n          await fetchRemoteFile(url, mimeType),\n          segmentTime,\n          resource.length\n        );\n\n        return await uploadMedia(segmentedFiles, {\n          onUploadSuccess: onUploadSuccess,\n        });\n      } catch (err) {\n        if (err instanceof Error) {\n          // eslint-disable-next-line no-console -- surface this error\n          console.log(err.message);\n          void trackError('segment_video', err.message);\n        }\n        return null;\n      }\n    },\n    [uploadMedia, ffSegmentVideo]\n  );\n\n  return {\n    optimizeVideo,\n    optimizeGif,\n    muteExistingVideo,\n    trimExistingVideo,\n    cropExistingVideo,\n    segmentVideo,\n  };\n}\n\nexport default useProcessMedia;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useUpdateElementDimensions.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport type { Resource } from '@googleforcreators/media';\nimport type { ElementId, ElementType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../story/useStory';\nimport getInsertedElementSize from '../../../utils/getInsertedElementSize';\n\nfunction useUpdateElementDimensions() {\n  const { updateElementsByResourceId } = useStory((state) => ({\n    updateElementsByResourceId: state.actions.updateElementsByResourceId,\n  }));\n\n  const updateElementDimensions = useCallback(\n    ({ id, resource }: { id: ElementId; resource: Resource }) => {\n      updateElementsByResourceId({\n        id,\n        properties: (el) => {\n          const hasChangedDimensions =\n            el.resource.width !== resource.width ||\n            el.resource.height !== resource.height;\n\n          if (!hasChangedDimensions) {\n            return {\n              type: resource.type as unknown as ElementType,\n              resource,\n            };\n          }\n\n          const { width, height } = getInsertedElementSize(\n            el.type,\n            undefined,\n            undefined,\n            {},\n            resource.width / resource.height,\n            resource\n          );\n\n          return {\n            resource,\n            type: resource.type as unknown as ElementType,\n            width,\n            height,\n          };\n        },\n      });\n    },\n    [updateElementsByResourceId]\n  );\n\n  return {\n    updateElementDimensions,\n  };\n}\n\nexport default useUpdateElementDimensions;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useUploadVideoFrame.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\nimport {\n  preloadImage,\n  getFirstFrameOfVideo,\n  getFileNameFromUrl,\n  getFileBasename,\n  blobToFile,\n} from '@googleforcreators/media';\nimport type { ResourceId } from '@googleforcreators/media';\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useStory } from '../../story';\nimport { useConfig } from '../../config';\nimport { useUploader } from '../../uploader';\nimport { MEDIA_POSTER_IMAGE_MIME_TYPE } from '../../../constants';\nimport getPosterName from './getPosterName';\n\ntype VideoPosterType = {\n  posterId?: ResourceId;\n  poster?: string;\n  width?: number;\n  height?: number;\n};\n\ninterface UseUploadVideoFrameProps {\n  updateMediaElement?: (props: { id: number; data: VideoPosterType }) => void;\n}\n\nfunction useUploadVideoFrame({ updateMediaElement }: UseUploadVideoFrameProps) {\n  const {\n    actions: { updateMedia },\n  } = useAPI();\n  const {\n    actions: { uploadFile },\n  } = useUploader();\n  const { storyId } = useConfig();\n  const { updateElementsByResourceId } = useStory((state) => ({\n    updateElementsByResourceId: state.actions.updateElementsByResourceId,\n  }));\n\n  /**\n   * Uploads a poster file.\n   *\n   * If the poster is for a local video, ensures the two are properly connected on the backend.\n   */\n  const uploadVideoPoster = useCallback(\n    /**\n     *\n     * @param id Video ID.\n     * @param posterFile File object.\n     * @return Poster information.\n     */\n    async (\n      id: ResourceId,\n      posterFile: File | null\n    ): Promise<VideoPosterType> => {\n      // TODO: Make param mandatory; don't allow calling without.\n      if (!posterFile) {\n        return {};\n      }\n\n      const resource = await uploadFile(posterFile, {\n        mediaId: id,\n        mediaSource: 'poster-generation',\n      });\n      const { id: posterId, src: poster, width, height } = resource;\n\n      // If video ID is not set, skip relating media.\n      if (id && updateMedia) {\n        await updateMedia(id, {\n          posterId,\n          storyId,\n        });\n      }\n\n      // Preload the full image in the browser to stop jumping around.\n      try {\n        await preloadImage({ src: poster });\n      } catch {\n        // Ignore\n      }\n\n      return { posterId, poster, width, height };\n    },\n    [storyId, updateMedia, uploadFile]\n  );\n\n  /**\n   * Uploads the video's first frame as its poster image.\n   *\n   * Updates the resource both in the media library and on the canvas\n   * to include the new poster image reference.\n   */\n  const uploadVideoFrame = useCallback(\n    /**\n     *\n     * @param id Video ID.\n     * @param src Video URL.\n     */\n    async (id: number, src: string) => {\n      const trackTiming = getTimeTracker('load_video_poster');\n      try {\n        const originalFileName = getFileNameFromUrl(src);\n        const fileName = getPosterName(\n          getFileBasename({ name: originalFileName })\n        );\n        const blob = await getFirstFrameOfVideo(src);\n        const posterFile = blob\n          ? blobToFile(blob, fileName, MEDIA_POSTER_IMAGE_MIME_TYPE)\n          : null;\n        const newPoster = await uploadVideoPoster(id, posterFile);\n\n        if (updateElementsByResourceId) {\n          updateElementsByResourceId({\n            id,\n            properties: ({ resource }) => ({\n              resource: {\n                ...resource,\n                ...newPoster,\n              },\n            }),\n          });\n        }\n        if (updateMediaElement) {\n          updateMediaElement({\n            id,\n            data: newPoster,\n          });\n        }\n      } catch (err) {\n        if (err instanceof Error) {\n          // TODO: Potentially display error message to user.\n          void trackError('video_poster_generation', err.message);\n        }\n      } finally {\n        trackTiming();\n      }\n    },\n    [uploadVideoPoster, updateElementsByResourceId, updateMediaElement]\n  );\n\n  return {\n    uploadVideoFrame,\n    uploadVideoPoster,\n  };\n}\n\nexport default useUploadVideoFrame;\n"
  },
  {
    "path": "packages/story-editor/src/app/media/utils/useVideoElementTranscoding.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useVideoTrim from '../../../components/videoTrim/useVideoTrim';\nimport { useLocalMedia } from '../..';\nimport useFFmpeg from './useFFmpeg';\n\nfunction useVideoElementTranscoding({\n  resource,\n  elementId,\n  isSingleElement = true,\n}) {\n  const { isTranscodingEnabled } = useFFmpeg();\n  const {\n    muteExistingVideo,\n    isElementTrimming,\n    isNewResourceMuting,\n    canTranscodeResource,\n  } = useLocalMedia(\n    ({\n      state: { canTranscodeResource, isNewResourceMuting, isElementTrimming },\n      actions: { muteExistingVideo },\n    }) => ({\n      canTranscodeResource,\n      isNewResourceMuting,\n      isElementTrimming,\n      muteExistingVideo,\n    })\n  );\n  const { isMuted, id: resourceId = 0 } = resource;\n  const isTrimming = isSingleElement ? isElementTrimming(elementId) : false;\n  const isMuting = isNewResourceMuting(resourceId);\n\n  const handleMute = useCallback(() => {\n    muteExistingVideo({ resource });\n  }, [resource, muteExistingVideo]);\n\n  const shouldDisableVideoActions = !canTranscodeResource(resource);\n\n  const canMute =\n    isTranscodingEnabled &&\n    isSingleElement &&\n    ((!isMuted && canTranscodeResource(resource)) || isMuting);\n\n  const { hasTrimMode, toggleTrimMode } = useVideoTrim(\n    ({ state: { hasTrimMode }, actions: { toggleTrimMode } }) => ({\n      hasTrimMode,\n      toggleTrimMode,\n    })\n  );\n\n  return {\n    state: {\n      canTrim: hasTrimMode,\n      canMute,\n      isTrimming,\n      isMuting,\n      isDisabled: shouldDisableVideoActions,\n    },\n    actions: {\n      handleMute,\n      handleTrim: toggleTrimMode,\n    },\n  };\n}\n\nexport default useVideoElementTranscoding;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/context.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { PageCanvasProviderState } from '../../types';\nimport { noop } from '../../utils/noop';\n\nexport default createContext<PageCanvasProviderState>({\n  actions: {\n    calculateAccessibleTextColors: async () => {\n      return Promise.resolve({});\n    },\n    generateDeferredPageCanvas: () => noop,\n    generateDeferredCurrentPageCanvas: noop,\n  },\n  state: {\n    pageCanvasMap: {},\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/getPageWithoutSelection.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { ElementId, Page } from '@googleforcreators/elements';\n\nfunction pageWithoutSelection(page: Page, selection: ElementId[]): Page {\n  return {\n    ...page,\n    elements: page.elements.filter(({ id }) => !selection.includes(id)),\n  };\n}\n\nexport default pageWithoutSelection;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/getPixelDataFromCanvas.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { FULLBLEED_RATIO, getBox, PAGE_RATIO } from '@googleforcreators/units';\nimport { calculateTextHeight } from '@googleforcreators/element-library';\nimport type { TextElement } from '@googleforcreators/elements';\n\nfunction getPixelDataFromCanvas(\n  canvas: HTMLCanvasElement,\n  attrs: TextElement\n): Uint8ClampedArray {\n  const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;\n\n  // The canvas does not consider danger zone as y = 0, so we need to adjust that.\n  const safeZoneDiff =\n    (canvas.width / FULLBLEED_RATIO - canvas.width / PAGE_RATIO) / 2;\n  const box = getBox(\n    {\n      ...attrs,\n      height: attrs.height\n        ? attrs.height\n        : calculateTextHeight(attrs, attrs.width),\n    },\n    canvas.width,\n    canvas.height - 2 * safeZoneDiff\n  );\n  const { x, y: origY, width, height } = box;\n  const y = origY + safeZoneDiff;\n  const pixelData = ctx.getImageData(x, y, width, height).data;\n  return pixelData;\n}\n\nexport default getPixelDataFromCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as PageCanvasProvider } from './pageCanvasProvider';\nexport { default as useCalculateAccessibleTextColors } from './useCalculateAccessibleTextColors';\nexport { default as usePageCanvas } from './usePageCanvas';\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/pageCanvasCacheValidator.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, memo } from '@googleforcreators/react';\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport objectWithout from '../../utils/objectWithout';\nimport { useStory } from '../story';\n\ninterface PageCanvasCacheValidatorProps {\n  pageId: string;\n  clearPageCanvasCache: (props: {\n    pageId: string;\n    canvas?: HTMLCanvasElement;\n  }) => void;\n}\nfunction PageCanvasCacheValidator({\n  pageId,\n  clearPageCanvasCache,\n}: PageCanvasCacheValidatorProps) {\n  const page = useStory(({ state }) =>\n    objectWithout(state.pages.find(({ id }) => id === pageId) as Page, [\n      'animations',\n    ])\n  );\n\n  // clear pageCanvas whenever a page is updated.\n  useEffect(() => {\n    clearPageCanvasCache({ pageId: page.id as string });\n  }, [page, clearPageCanvasCache]);\n\n  // clear pageCanvas if the page gets deleted\n  useEffect(() => {\n    return () => clearPageCanvasCache({ pageId });\n  }, [clearPageCanvasCache, pageId]);\n\n  return null;\n}\n\nexport default memo(PageCanvasCacheValidator);\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/pageCanvasProvider.tsx",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\nimport type { Page, TextElement } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { getAccessibleTextColorsFromPixels } from '../../utils/contrastUtils';\nimport useIdleQueue from '../../utils/useIdleTaskQueue';\nimport { useStory } from '../story';\nimport { STABLE_ARRAY } from '../../constants';\nimport storyPageToCanvas from './utils/storyPageToCanvas';\nimport Context from './context';\nimport getPixelDataFromCanvas from './getPixelDataFromCanvas';\nimport usePageCanvasMap from './usePageCanvasMap';\nimport usePageSnapshot from './usePageSnapshot';\nimport PageCanvasCacheValidator from './pageCanvasCacheValidator';\nimport getPageWithoutSelection from './getPageWithoutSelection';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\nfunction PageCanvasProvider({ children }: PropsWithChildren<unknown>) {\n  const queueIdleTask = useIdleQueue();\n  // This is our cache to hold generated canvases for\n  // full story pages within the story we're viewing\n  const [pageCanvasMap, actions] = usePageCanvasMap();\n  // This is our cache to hold 1 generated canvas\n  // for a partial page\n  const { getSnapshotCanvas, setSnapshot } = usePageSnapshot();\n  const pageIds = useStory(({ state }) => state.pages.map(({ id }) => id));\n  const { currentPage, singleElementSelection } = useStory(({ state }) => ({\n    singleElementSelection:\n      state.selectedElementIds?.length === 1\n        ? state.selectedElementIds\n        : STABLE_ARRAY,\n    currentPage: state.currentPage,\n  }));\n\n  // sync values to a ref so callbacks don't cause re-renders\n  // on consuming components\n  const values = {\n    currentPageValue: currentPage as Page,\n    pageCanvasMapValue: pageCanvasMap,\n    singleElementSelectionValue: singleElementSelection,\n  };\n  const valuesRef = useRef(values);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  valuesRef.current = values;\n\n  /**\n   * makes a request to the idleCallback queue to generate a canvas\n   * for a given story page.\n   *\n   * @param {[string, Page]} PageTuple - a tuple containing a uid for the requested generation task & the page to generate a canvas from\n   * @return {Function} a cleanup function to clear the requested canvas generation\n   */\n  const generateDeferredPageCanvas = useCallback(\n    ([taskId, page]: [string, Page]) => {\n      const cancelIdleTask = queueIdleTask({\n        taskId,\n        task: async () => {\n          try {\n            const canvas = await storyPageToCanvas(page, {});\n            actions.setPageCanvas({ pageId: page.id, canvas });\n          } catch {\n            actions.setPageCanvas({ pageId: page.id, canvas: null });\n          }\n        },\n      });\n      return cancelIdleTask;\n    },\n    [queueIdleTask, actions]\n  );\n\n  /**\n   * Small wrapper around `generateDeferredPageCanvas()` that just passes in the\n   * current page.\n   *\n   * @return {void}\n   */\n  const generateDeferredCurrentPageCanvas = useCallback(() => {\n    const { currentPageValue, pageCanvasMapValue } = valuesRef.current;\n    const canvas = pageCanvasMapValue[currentPageValue.id];\n    if (typeof canvas === 'undefined') {\n      generateDeferredPageCanvas([currentPageValue.id, currentPageValue]);\n    }\n  }, [generateDeferredPageCanvas]);\n\n  /**\n   * Gets or creates a canvas from the page and excludes\n   * the current selection from the generated canvas.\n   *\n   * @return {HTMLCanvasElement} generated canvas\n   */\n  const getSelectionExclusionCanvas = useCallback(\n    async (page: Page, selection: string[]) => {\n      const pageWithoutSelection = getPageWithoutSelection(page, selection);\n      let canvas = getSnapshotCanvas(pageWithoutSelection);\n      if (!canvas) {\n        // Generate the page canvas with the excluded elements if we don't already\n        // have a valid canvas in the cache.\n        canvas = await storyPageToCanvas(pageWithoutSelection, {});\n        setSnapshot({\n          page: pageWithoutSelection,\n          canvas,\n        });\n      }\n      return canvas;\n    },\n    [setSnapshot, getSnapshotCanvas]\n  );\n\n  /**\n   * Gets or creates a generated canvas from the current story page.\n   *\n   * @return {HTMLCanvasElement} generated canvas\n   */\n  const getCanvas = useCallback(\n    async (page: Page) => {\n      const { pageCanvasMapValue } = valuesRef.current;\n\n      let canvas = pageCanvasMapValue[page.id];\n      if (!canvas) {\n        canvas = await storyPageToCanvas(page, {});\n        actions.setPageCanvas({ pageId: page.id, canvas });\n      }\n      return canvas;\n    },\n    [actions]\n  );\n\n  /**\n   * Given an element, returns accessible text colors relative\n   * to the current page\n   *\n   * @param {} story element\n   * @return {Object} Returns object consisting of color and backgroundColor in case relevant.\n   */\n  const calculateAccessibleTextColors = useCallback(\n    async (element: TextElement) => {\n      const { currentPageValue, singleElementSelectionValue } =\n        valuesRef.current;\n\n      let canvas: HTMLCanvasElement;\n      if (singleElementSelectionValue.includes(element.id)) {\n        canvas = await getSelectionExclusionCanvas(\n          currentPageValue,\n          singleElementSelectionValue\n        );\n      } else {\n        canvas = await getCanvas(currentPageValue);\n      }\n\n      const { fontSize } = element;\n      const pixelData = getPixelDataFromCanvas(canvas, element);\n      const accessibleTextColors = getAccessibleTextColorsFromPixels(\n        pixelData,\n        fontSize\n      );\n\n      return accessibleTextColors;\n    },\n    [getSelectionExclusionCanvas, getCanvas]\n  );\n\n  return (\n    <Context.Provider\n      value={{\n        state: {\n          pageCanvasMap,\n        },\n        actions: {\n          calculateAccessibleTextColors,\n          generateDeferredPageCanvas,\n          generateDeferredCurrentPageCanvas,\n        },\n      }}\n    >\n      {pageIds.map((pageId) => (\n        <PageCanvasCacheValidator\n          key={pageId}\n          pageId={pageId}\n          clearPageCanvasCache={actions.clearPageCanvas}\n        />\n      ))}\n      {children}\n    </Context.Provider>\n  );\n}\n\nexport default PageCanvasProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/test/usePageCanvas.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { PageCanvasProvider, usePageCanvas } from '..';\nimport storyPageToCanvas from '../utils/storyPageToCanvas';\nimport useStory from '../../story/useStory';\nimport createMockPage from '../testUtils/createMockPage';\nimport { MockStoryProvider, useStoryMock } from '../testUtils/useStoryMock';\n\njest.mock('../../story/useStory');\njest.mock('../utils/storyPageToCanvas');\n\njest.mock('../../../utils/contrastUtils', () => {\n  return {\n    __esModule: true,\n    getAccessibleTextColorsFromPixels: () => {},\n  };\n});\njest.mock('../getPixelDataFromCanvas', () => {\n  return {\n    __esModule: true,\n    default: () => {},\n  };\n});\n\nfunction renderUsePageCanvas(_mockStoryContext) {\n  return renderHook(() => [usePageCanvas(), useStoryMock()], {\n    wrapper: ({ children }) => (\n      <MockStoryProvider mockContextValue={_mockStoryContext}>\n        <PageCanvasProvider>{children}</PageCanvasProvider>\n      </MockStoryProvider>\n    ),\n  });\n}\n\ndescribe('usePageCanvas', () => {\n  let mockStoryContext;\n  let currentPage;\n\n  beforeEach(() => {\n    storyPageToCanvas.mockImplementation(\n      () =>\n        'lets pretend this is a canvas. I wont tell the computer if you dont 🤫'\n    );\n\n    currentPage = createMockPage();\n    mockStoryContext = {\n      actions: {},\n      state: {\n        pages: [currentPage],\n        currentPage,\n        selectedElementIds: [],\n      },\n    };\n\n    useStory.mockImplementation(useStoryMock);\n  });\n\n  afterEach(() => {\n    jest.resetAllMocks();\n  });\n\n  describe('calculateAccessibleTextColors', () => {\n    describe('page canvas cache', () => {\n      it('generates a page canvas when called and canvas cache is not populated', async () => {\n        const { result } = renderUsePageCanvas(mockStoryContext);\n        const element = { id: 'a' };\n\n        // see that no canvas has been generated at this point\n        expect(storyPageToCanvas).toHaveBeenCalledTimes(0);\n\n        // cache populates with generated canvas for currentPage\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            element\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n      });\n\n      it('does not generate a page canvas when called and canvas cache is populated', async () => {\n        const { result } = renderUsePageCanvas(mockStoryContext);\n        const element1 = { id: 'a' };\n        const element2 = { id: 'b' };\n\n        // cache populates with generated canvas for currentPage\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            element1\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n\n        // cache already populated with generated canvas for currentPage\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            element2\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n      });\n\n      it('generates a page canvas when called and canvas cache is stale', async () => {\n        const { result } = renderUsePageCanvas(mockStoryContext);\n        const [, useStoryMockCurrent] = result.current;\n        const { actions: storyActions } = useStoryMockCurrent;\n\n        const element1 = { id: 'a' };\n        const element2 = { id: 'b' };\n\n        // cache populates with generated canvas for currentPage\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            element1\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n\n        // make currentPage stale by making an update to it\n        act(() => storyActions.duplicateLastElement());\n        expect(result.current[0].state.pageCanvasMap).toStrictEqual({});\n\n        // cache populates with generated canvas for updated currentPage\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            element2\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledTimes(2);\n      });\n    });\n\n    describe('partial page snapshot cache', () => {\n      it('generates a partial page canvas when called and partial page snapshot cache is not populated', async () => {\n        // set up story to have single selected element\n        const lastElementIndex = currentPage.elements.length - 1;\n        const selectedElement = currentPage.elements[lastElementIndex];\n        mockStoryContext.state.selectedElementIds = [selectedElement.id];\n\n        // render hook\n        const { result } = renderUsePageCanvas(mockStoryContext);\n\n        // since we're testing an existing element against the currentPage\n        // calculateAccessibleTextColors knows to exclude the element we're testing\n        // from the generated canvas. It holds this canvas generated from a partial\n        // of the page in the snapshot cache.\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            selectedElement\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n\n        // See that we're calling the story generation on a page partial and\n        // not the full page.\n        const generatedStory = storyPageToCanvas.mock.calls[0][0];\n        for (const element of generatedStory.elements) {\n          expect(element.id).not.toBe(selectedElement.id);\n        }\n      });\n\n      it('does not generate a new partial page canvas when called and snapshot cache stays valid', async () => {\n        // set up story to have single selected element\n        const lastElementIndex = currentPage.elements.length - 1;\n        const selectedElement = currentPage.elements[lastElementIndex];\n        mockStoryContext.state.selectedElementIds = [selectedElement.id];\n\n        // render hook\n        const { result } = renderUsePageCanvas(mockStoryContext);\n        const [, useStoryMockCurrent] = result.current;\n        const { actions: storyActions } = useStoryMockCurrent;\n\n        // since we're testing an existing element against the currentPage\n        // calculateAccessibleTextColors knows to exclude the element we're testing\n        // from the generated canvas. It holds this canvas generated from a partial\n        // of the page in the snapshot cache.\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            selectedElement\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n\n        // update the selected element\n        act(() =>\n          storyActions.updateSelectedElement({ properties: { opacity: 50 } })\n        );\n\n        // change selection\n        const anotherElementId = currentPage.elements[0].id;\n        act(() =>\n          storyActions.setSelectedElement({ elementId: anotherElementId })\n        );\n\n        // revert selection back to originally selected element\n        act(() =>\n          storyActions.setSelectedElement({ elementId: selectedElement.id })\n        );\n\n        // since we haven't called calculateAccessibleTextColors since the\n        // last story partial page changed, and with the current selection\n        // the canvas generated for the partial page is the same since the\n        // last time we called calculateAccessibleTextColors, the snapshot\n        // cache should still be valid and shouldn't have been updated.\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            selectedElement\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n      });\n\n      it('generates a new partial page canvas when called and snapshot cache is not valid', async () => {\n        // set up story to have single selected element\n        const lastElementIndex = currentPage.elements.length - 1;\n        const selectedElement = currentPage.elements[lastElementIndex];\n        mockStoryContext.state.selectedElementIds = [selectedElement.id];\n\n        // render hook\n        const { result } = renderUsePageCanvas(mockStoryContext);\n        const [, useStoryMockCurrent] = result.current;\n        const { actions: storyActions } = useStoryMockCurrent;\n\n        // since we're testing an existing element against the currentPage\n        // calculateAccessibleTextColors knows to exclude the element we're testing\n        // from the generated canvas. It holds this canvas generated from a partial\n        // of the page in the snapshot cache.\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            selectedElement\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledOnce();\n\n        // add a new element\n        act(() => storyActions.duplicateLastElement());\n\n        // in this scenario, the snapshot cache is no longer valid\n        // because we've added a new element to the currentPage.\n        // We should be generating a new canvas based on the updated\n        // page partial in this scenario.\n        await act(async () => {\n          const [usePageCanvasCurrent] = result.current;\n          await usePageCanvasCurrent.actions.calculateAccessibleTextColors(\n            selectedElement\n          );\n        });\n        expect(storyPageToCanvas).toHaveBeenCalledTimes(2);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/testUtils/createMockPage.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction createMockPage() {\n  return {\n    elements: [\n      {\n        x: 1,\n        y: 1,\n        width: 1,\n        height: 1,\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        mask: {\n          type: 'rectangle',\n        },\n        isBackground: true,\n        type: 'shape',\n        id: '21e59f86-f8e8-44d4-bf33-6fb25259fdf3',\n        isDefaultBackground: true,\n      },\n      {\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        backgroundColor: {\n          color: {\n            r: 201,\n            g: 24,\n            b: 74,\n          },\n        },\n        type: 'shape',\n        x: 112.5,\n        y: 281.5,\n        width: 55,\n        height: 55,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        mask: {\n          type: 'rectangle',\n        },\n        id: 'a90d42b7-b1ac-4616-9979-76ed3b70115b',\n      },\n      {\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        backgroundColor: {\n          color: {\n            r: 201,\n            g: 24,\n            b: 74,\n          },\n        },\n        type: 'shape',\n        x: 236,\n        y: 281.5,\n        width: 55,\n        height: 55,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        mask: {\n          type: 'rectangle',\n        },\n        id: 'ebfbdd1c-cc6f-4a16-a630-0d8f055e792d',\n      },\n      {\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        backgroundColor: {\n          color: {\n            r: 201,\n            g: 24,\n            b: 74,\n          },\n        },\n        type: 'shape',\n        x: 175,\n        y: 281.5,\n        width: 55,\n        height: 55,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        mask: {\n          type: 'rectangle',\n        },\n        id: '686bd91e-0c1a-4344-ae67-f6e9fe2eb6da',\n      },\n    ],\n    animations: [\n      {\n        id: '80f03ac8-415a-453d-8981-8c91355e866b',\n        type: 'effect-fly-in',\n        targets: ['ebfbdd1c-cc6f-4a16-a630-0d8f055e792d'],\n        flyInDir: 'rightToLeft',\n        duration: 600,\n        delay: 0,\n      },\n    ],\n    type: 'page',\n    id: 'a41fe2ac-88ec-4693-83ec-46a21fda4850',\n    backgroundColor: {\n      color: {\n        r: 233,\n        g: 213,\n        b: 197,\n      },\n    },\n    pageTemplateType: 'quote',\n    defaultBackgroundElement: {\n      x: 1,\n      y: 1,\n      width: 1,\n      height: 1,\n      opacity: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      mask: {\n        type: 'rectangle',\n      },\n      isBackground: true,\n      type: 'shape',\n      id: '61df41e7-b2dc-4ed0-8c5e-91cd08261d1e',\n      isDefaultBackground: true,\n    },\n    image: {\n      id: 769,\n      height: 1200,\n      width: 800,\n      url: 'http://localhost:8899/wp-content/uploads/2022/03/web-stories-page-template-768.jpg',\n    },\n  };\n}\n\nexport default createMockPage;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/testUtils/useStoryMock.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createContext,\n  identity,\n  useContextSelector,\n  useReduction,\n} from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\n\nconst Context = createContext(null);\n\nconst reducer = {\n  setSelectedElement: ({ state }, { payload }) => ({\n    state: {\n      ...state,\n      selectedElementIds: [payload.elementId],\n    },\n  }),\n  updateSelectedElement: ({ state }, { payload }) => {\n    const newCurrentPage = {\n      ...state.currentPage,\n      elements: state.currentPage.elements.reduce((els, el) => {\n        if (state.selectedElementIds.includes(el.id)) {\n          els.push({ ...el, ...payload.properties });\n        } else {\n          els.push(el);\n        }\n        return els;\n      }, []),\n    };\n    return {\n      state: {\n        ...state,\n        pages: [newCurrentPage],\n        currentPage: newCurrentPage,\n      },\n    };\n  },\n  duplicateLastElement: ({ state }) => {\n    const newCurrentPage = {\n      ...state.currentPage,\n      elements: [\n        ...state.currentPage.elements,\n        {\n          ...state.currentPage.elements[state.currentPage.elements.length - 1],\n          id: uuidv4(),\n        },\n      ],\n    };\n    return {\n      state: {\n        ...state,\n        pages: [newCurrentPage],\n        currentPage: newCurrentPage,\n      },\n    };\n  },\n};\n\nexport function MockStoryProvider({ children, mockContextValue }) {\n  const [state, actions] = useReduction(mockContextValue, reducer);\n  return (\n    <Context.Provider\n      value={{\n        ...state,\n        actions,\n      }}\n    >\n      {children}\n    </Context.Provider>\n  );\n}\n\nexport function useStoryMock(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/useCalculateAccessibleTextColors.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useCalculateAccessibleTextColors() {\n  return useContextSelector(\n    Context,\n    ({ actions }) => actions.calculateAccessibleTextColors\n  );\n}\n\nexport default useCalculateAccessibleTextColors;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/usePageCanvas.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { PageCanvasProviderState } from '../../types';\nimport Context from './context';\n\nexport function usePageCanvas(): PageCanvasProviderState;\nexport function usePageCanvas<T>(\n  selector: (state: PageCanvasProviderState) => T\n): T;\nexport function usePageCanvas<T>(\n  selector: (\n    state: PageCanvasProviderState\n  ) => T | PageCanvasProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default usePageCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/usePageCanvasMap.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useReduction } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport objectWithout from '../../utils/objectWithout';\nimport type { PageCanvasMap } from '../../types';\n\nconst INITIAL_STATE: PageCanvasMap = {};\n\ninterface Action {\n  payload: {\n    pageId: string;\n    canvas?: HTMLCanvasElement | null;\n  };\n}\nconst reducer = {\n  setPageCanvas: (map: PageCanvasMap, action: Action): PageCanvasMap => {\n    const { pageId, canvas } = action.payload;\n    return {\n      ...map,\n      [pageId]: canvas,\n    } as PageCanvasMap;\n  },\n  clearPageCanvas: (map: PageCanvasMap, action: Action): PageCanvasMap => {\n    const { pageId } = action.payload;\n    return objectWithout(map, [pageId]) as PageCanvasMap;\n  },\n};\n\n/**\n * Cache for holding generated page canvases.\n *\n * Small state abstraction to hold a map of pageIds to a generated canvas\n * for the relevant page.\n */\nfunction usePageCanvasMap() {\n  return useReduction(INITIAL_STATE, reducer);\n}\n\nexport default usePageCanvasMap;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/usePageSnapshot.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useRef,\n  shallowEqual,\n} from '@googleforcreators/react';\nimport type { Element, Page } from '@googleforcreators/elements';\nimport type { Pattern } from '@googleforcreators/patterns';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\ninterface SnapShot {\n  elements: Element[];\n  backgroundColor: Pattern;\n  canvas: HTMLCanvasElement;\n}\n/**\n * Cache that holds 1 generated canvas for a page partial.\n */\nfunction usePageSnapshot() {\n  // limit exclusion canvas cache to 1 entry so that our memory doesn't\n  // explode from all possible element exclusion combinations\n  const [snapShot, _setSnapshot] = useState<SnapShot | null>(null);\n  const snapshotRef = useRef(snapShot);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  snapshotRef.current = snapShot;\n\n  /**\n   * Takes a story page and returns a canvas from the cache if\n   * the requested page matches the cache, returns null if there's\n   * a mismatch with the existing cache.\n   *\n   * This function maintains a stable reference throughout the life of this hook.\n   *\n   * @param {Page} page - requested page\n   * @return {HTMLCanvasElement | null}\n   */\n  const getSnapshotCanvas = useCallback((page: Page) => {\n    if (\n      page.backgroundColor === snapshotRef.current?.backgroundColor &&\n      shallowEqual(page.elements, snapshotRef.current?.elements)\n    ) {\n      return snapshotRef.current.canvas;\n    }\n\n    return null;\n  }, []);\n\n  /**\n   * Sets the snapshots canvas relative to the supplied page.\n   *\n   * This function maintains a stable reference throughout the life of this hook.\n   *\n   * @param {Object} args\n   * @param {Page} args.page - story page\n   * @param {HTMLCanvasElement} args.canvas - generated canvas from the story page\n   * @return {void}\n   */\n  const setSnapshot = useCallback(\n    ({ page, canvas }: { page: Page; canvas: HTMLCanvasElement }) => {\n      _setSnapshot({\n        elements: page.elements,\n        backgroundColor: page.backgroundColor,\n        canvas,\n      });\n    },\n    []\n  );\n\n  return {\n    setSnapshot,\n    getSnapshotCanvas,\n  };\n}\n\nexport default usePageSnapshot;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/utils/storyPageToCanvas.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport storyPageToNode from './storyPageToNode';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\n/**\n * Async method to generate a dataUrl from a story page.\n */\nasync function storyPageToCanvas(page: Page, { width = 400, ...options }) {\n  const htmlToImage = await import(\n    /* webpackChunkName: \"chunk-html-to-image\" */ 'html-to-image'\n  );\n\n  const [node, cleanup] = await storyPageToNode(page, width, {\n    renderFullHeightThumb: true,\n  });\n\n  const canvas = await htmlToImage.toCanvas(node, {\n    ...options,\n  });\n\n  cleanup();\n\n  return canvas;\n}\n\nexport default storyPageToCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/utils/storyPageToDataUrl.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { PAGE_RATIO } from '@googleforcreators/units';\nimport type { Page } from '@googleforcreators/elements';\nimport type { Options } from 'html-to-image/lib/types';\n\n/**\n * Internal dependencies\n */\nimport storyPageToNode from './storyPageToNode';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\ninterface StoryPageToCanvasOptions extends Options {\n  width?: number;\n}\n/**\n * Async method to generate a dataUrl from a story page.\n */\nasync function storyPageToDataUrl(\n  page: Page,\n  { width = 400, ...options }: StoryPageToCanvasOptions\n) {\n  const htmlToImage = await import(\n    /* webpackChunkName: \"chunk-html-to-image\" */ 'html-to-image'\n  );\n\n  const [node, cleanup] = await storyPageToNode(page, width);\n\n  const dataUrl = await htmlToImage.toJpeg(node, {\n    ...options,\n    width,\n    height: width * (1 / PAGE_RATIO),\n    canvasHeight: width * (1 / PAGE_RATIO),\n    canvasWidth: width,\n  });\n\n  cleanup();\n\n  return dataUrl;\n}\n\nexport default storyPageToDataUrl;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageCanvas/utils/storyPageToNode.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { theme as ds_theme } from '@googleforcreators/design-system';\nimport {\n  forwardRef,\n  render,\n  unmountComponentAtNode,\n} from '@googleforcreators/react';\nimport {\n  PAGE_RATIO,\n  FULLBLEED_RATIO,\n  UnitsProvider,\n} from '@googleforcreators/units';\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  generatePatternStyles,\n  type Pattern,\n} from '@googleforcreators/patterns';\nimport { TransformProvider } from '@googleforcreators/transform';\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { FontProvider } from '../../font';\nimport DisplayElement from '../../../components/canvas/displayElement';\n\nconst StoryPage = styled.div<{ height: number; width: number }>`\n  display: block;\n  position: relative;\n  padding: 0;\n  border: 0;\n  background-color: transparent;\n  height: ${({ height }) => height}px;\n  width: ${({ width }) => width}px;\n  flex: none;\n  outline: 0;\n`;\n\nconst PreviewWrapper = styled.div<{ background: Pattern }>`\n  height: 100%;\n  position: relative;\n  overflow: hidden;\n  background-color: ${({ theme }) =>\n    (theme as typeof ds_theme).colors.standard.white};\n  border-radius: 4px;\n  ${({ background }) => generatePatternStyles(background)}\n`;\n\nconst FullHeight = styled.div<{ yOffset: number }>`\n  position: absolute;\n  top: ${({ yOffset }) => yOffset}px;\n  bottom: ${({ yOffset }) => yOffset}px;\n  right: 0;\n  left: 0;\n`;\n\ninterface PageWithDepsProps {\n  page: Page;\n  width: number;\n  height: number;\n  renderFullHeightThumb?: boolean;\n  containerHeight: number;\n}\nconst PageWithDependencies = forwardRef<HTMLDivElement, PageWithDepsProps>(\n  function PageWithDependencies(\n    {\n      page,\n      width,\n      height,\n      renderFullHeightThumb = false,\n      containerHeight,\n    }: PageWithDepsProps,\n    ref\n  ) {\n    return (\n      <ThemeProvider theme={ds_theme}>\n        <FontProvider>\n          <TransformProvider>\n            <UnitsProvider\n              pageSize={{\n                width,\n                height,\n              }}\n            >\n              <StoryPage\n                ref={ref}\n                height={renderFullHeightThumb ? containerHeight : height}\n                width={width}\n              >\n                <PreviewWrapper background={page.backgroundColor}>\n                  <FullHeight\n                    yOffset={\n                      renderFullHeightThumb ? (containerHeight - height) / 2 : 0\n                    }\n                  >\n                    {page.elements.map((element) => (\n                      <DisplayElement\n                        key={element.id}\n                        previewMode\n                        element={element}\n                      />\n                    ))}\n                  </FullHeight>\n                </PreviewWrapper>\n              </StoryPage>\n            </UnitsProvider>\n          </TransformProvider>\n        </FontProvider>\n      </ThemeProvider>\n    );\n  }\n);\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\ninterface Options {\n  renderFullHeightThumb?: boolean;\n}\n/**\n * Takes a story page and generates a DOM node containing the rendered\n * page. Returns a tuple containing the page DOM node and a cleanup\n * method to remove the returned DOM node.\n *\n * **IMPORTANT:** Not calling the returned `cleanup()` method after use of\n * page DOM node will result in memory leak.\n */\nasync function storyPageToNode(\n  page: Page,\n  width: number,\n  opts: Options = {}\n): Promise<[HTMLElement, () => void]> {\n  const { renderFullHeightThumb = false } = opts;\n  const height = width * (1 / PAGE_RATIO);\n  const containerHeight = width * (1 / FULLBLEED_RATIO);\n\n  const bufferRoot = document.createElement('div');\n  bufferRoot.style.cssText = `\n     contain: strict;\n     position: absolute;\n     top: 0;\n     left: 0;\n     width: ${width}px;\n     height: ${containerHeight}px;\n     opacity: 0;\n     transform: translate(-100%, -100%);\n     pointer-events: none;\n   `;\n\n  const node: HTMLElement = await new Promise((resolve) => {\n    const resolverRef = (htmlNode: HTMLDivElement) => {\n      if (!htmlNode) {\n        return;\n      }\n      resolve(htmlNode);\n    };\n\n    render(\n      <PageWithDependencies\n        ref={resolverRef}\n        page={page}\n        width={width}\n        height={height}\n        containerHeight={containerHeight}\n        renderFullHeightThumb={renderFullHeightThumb}\n      />,\n      bufferRoot\n    );\n  });\n\n  document.body.appendChild(bufferRoot);\n  const cleanup = () => {\n    unmountComponentAtNode(bufferRoot);\n    document.body.removeChild(bufferRoot);\n  };\n\n  return [node, cleanup];\n}\nexport default storyPageToNode;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageDataUrls/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { PageDataUrlsContext } from '../../types';\nimport { noop } from '../../utils/noop';\n\nexport default createContext<PageDataUrlsContext>({\n  state: {\n    dataUrls: {},\n  },\n  actions: {\n    queuePageImageGeneration: noop,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/pageDataUrls/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as usePageDataUrls } from './usePageDataUrls';\nexport { default as PageDataUrlProvider } from './pageDataUrlsProvider';\n"
  },
  {
    "path": "packages/story-editor/src/app/pageDataUrls/pageDataUrlsProvider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\nimport { useMemo, useCallback, useState } from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport useIdleTaskQueue from '../../utils/useIdleTaskQueue';\nimport storyPageToDataUrl from '../pageCanvas/utils/storyPageToDataUrl';\nimport type { PageDataUrls, QueuePageImageGeneration } from '../../types';\nimport Context from './context';\n\nfunction PageDataUrlProvider({ children }: PropsWithChildren<unknown>) {\n  const [dataUrls, setDataUrls] = useState<PageDataUrls>({});\n  const queueIdleTask = useIdleTaskQueue();\n\n  /**\n   * Add page image generation task to a idle task\n   * queue.\n   */\n  const queuePageImageGeneration: QueuePageImageGeneration = useCallback(\n    (storyPage: Page) => {\n      const idleTaskUid: string = storyPage.id;\n      const idleTask: () => Promise<void> = async () => {\n        try {\n          const dataUrl = await storyPageToDataUrl(storyPage, {});\n          setDataUrls((state) => ({\n            ...state,\n            [storyPage?.id]: dataUrl,\n          }));\n        } catch {\n          // Do nothing for now.\n        }\n      };\n\n      const clearQueueOfPageTask = queueIdleTask({\n        taskId: idleTaskUid,\n        task: idleTask,\n      });\n      return () => {\n        clearQueueOfPageTask();\n      };\n    },\n    [queueIdleTask]\n  );\n\n  const value = useMemo(\n    () => ({\n      state: {\n        dataUrls,\n      },\n      actions: {\n        queuePageImageGeneration,\n      },\n    }),\n    [queuePageImageGeneration, dataUrls]\n  );\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport default PageDataUrlProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/pageDataUrls/test/usePageDataUrls.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { usePageDataUrls, PageDataUrlProvider } from '..';\nimport {\n  requestIdleCallback,\n  cancelIdleCallback,\n} from '../../../utils/idleCallback';\n\nconst mockDataUrlFromPage = (page) => `${page.id}-dataUrl`;\n\njest.mock('../../../utils/idleCallback', () => {\n  return {\n    __esModule: true,\n    requestIdleCallback: jest.fn(),\n    cancelIdleCallback: jest.fn(),\n  };\n});\n\njest.mock('../../pageCanvas/utils/storyPageToDataUrl', () => {\n  return {\n    __esModule: true,\n    // make dataUrl generation predictable\n    default: jest.fn((page) => Promise.resolve(mockDataUrlFromPage(page))),\n  };\n});\n\nfunction setup() {\n  const wrapper = ({ children }) => (\n    <PageDataUrlProvider>{children}</PageDataUrlProvider>\n  );\n\n  return renderHook(() => usePageDataUrls(), { wrapper });\n}\n\ndescribe('usePageDataUrls', () => {\n  let mockIdleCallbacks, runIdleCallbacks;\n\n  beforeEach(() => {\n    mockIdleCallbacks = [];\n    runIdleCallbacks = () => {\n      while (mockIdleCallbacks.length > 0) {\n        const { task } = mockIdleCallbacks.shift();\n        task();\n      }\n    };\n\n    requestIdleCallback.mockImplementation((callback) => {\n      const idleCallbackId = Symbol();\n      mockIdleCallbacks.push({ taskId: idleCallbackId, task: callback });\n      return idleCallbackId;\n    });\n    cancelIdleCallback.mockImplementation((idleCallbackId) => {\n      mockIdleCallbacks = mockIdleCallbacks.filter(\n        ({ taskId }) => taskId !== idleCallbackId\n      );\n    });\n  });\n\n  describe('queuePageImageGeneration', () => {\n    it('generates page data Urls sequentially', async () => {\n      const runAllIdleCallbacks = async () => {\n        runIdleCallbacks();\n        await act(async () => {\n          await Promise.resolve();\n        });\n      };\n\n      const { result } = setup();\n      const pageA = { id: 'a' };\n      const pageB = { id: 'b' };\n      const pageC = { id: 'b' };\n\n      // queue dataUrl generation tasks\n      result.current.actions.queuePageImageGeneration(pageA);\n      result.current.actions.queuePageImageGeneration(pageB);\n      result.current.actions.queuePageImageGeneration(pageC);\n\n      // see that no dataUrls have been generated\n      expect(result.current.state.dataUrls).toStrictEqual({});\n\n      // run idleCallback tasks and see that page dataUrl only gets\n      // generated when idle callback tasks are run. Also see that\n      // dataUrl generation functions in a first in first out (FIFO)\n      // manner\n      await runAllIdleCallbacks();\n      expect(result.current.state.dataUrls).toStrictEqual({\n        [pageA.id]: mockDataUrlFromPage(pageA),\n      });\n\n      await runAllIdleCallbacks();\n      expect(result.current.state.dataUrls).toStrictEqual({\n        [pageA.id]: mockDataUrlFromPage(pageA),\n        [pageB.id]: mockDataUrlFromPage(pageB),\n      });\n\n      await runAllIdleCallbacks();\n      expect(result.current.state.dataUrls).toStrictEqual({\n        [pageA.id]: mockDataUrlFromPage(pageA),\n        [pageB.id]: mockDataUrlFromPage(pageB),\n        [pageC.id]: mockDataUrlFromPage(pageC),\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/pageDataUrls/usePageDataUrls.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { PageDataUrlsContext } from '../../types';\nimport Context from './context';\n\nfunction usePageDataUrls(): PageDataUrlsContext;\nfunction usePageDataUrls<T>(selector: (state: PageDataUrlsContext) => T): T;\nfunction usePageDataUrls<T>(\n  selector: (state: PageDataUrlsContext) => T | PageDataUrlsContext = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default usePageDataUrls;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const ACTIONS = {\n  ADD_ANIMATION: {\n    trackingEventName: 'add_animation',\n    text: __('Add animation', 'web-stories'),\n  },\n  ADD_LINK: {\n    trackingEventName: 'add_link',\n    text: __('Add link', 'web-stories'),\n  },\n  ADD_CAPTIONS: {\n    trackingEventName: 'add_captions',\n    text: __('Add captions', 'web-stories'),\n  },\n  AUTO_STYLE_TEXT: {\n    trackingEventName: 'auto_style_text',\n    text: __('Adaptive text colors', 'web-stories'),\n  },\n  CHANGE_BACKGROUND_COLOR: {\n    trackingEventName: 'change_background_color',\n    text: __('Change background color', 'web-stories'),\n  },\n  CHANGE_TEXT_COLOR: {\n    trackingEventName: 'change_text_color',\n    text: __('Change color', 'web-stories'),\n  },\n  CHANGE_COLOR: {\n    trackingEventName: 'change_color',\n    text: __('Change color', 'web-stories'),\n  },\n  RESET_ELEMENT: {\n    trackingEventName: 'reset_element',\n    text: __('Reset element', 'web-stories'),\n  },\n  CHANGE_FONT: {\n    trackingEventName: 'change_font',\n    text: __('Edit text', 'web-stories'),\n  },\n  INSERT_BACKGROUND_MEDIA: {\n    trackingEventName: 'insert_background_media',\n    text: __('Insert background media', 'web-stories'),\n  },\n  INSERT_TEXT: {\n    trackingEventName: 'insert_text',\n    text: __('Insert text', 'web-stories'),\n  },\n  REPLACE_BACKGROUND_MEDIA: {\n    trackingEventName: 'replace_background_media',\n    text: __('Replace background', 'web-stories'),\n  },\n  REPLACE_MEDIA: {\n    trackingEventName: 'replace_media',\n    text: __('Replace media', 'web-stories'),\n  },\n  TRIM_VIDEO: {\n    trackingEventName: 'trim_video',\n    text: __('Trim video', 'web-stories'),\n  },\n  INSERT_AUDIO_STICKER: {\n    trackingEventName: 'insert_audio_sticker',\n    text: __('Insert audio sticker', 'web-stories'),\n  },\n};\n\nexport const RESET_PROPERTIES = {\n  ANIMATION: 'animation',\n  OVERLAY: 'overlay',\n  STYLES: 'styles',\n};\n\nexport const RESET_DEFAULTS = {\n  TEXT_BORDER_RADIUS: {\n    locked: true,\n    topLeft: 2,\n    topRight: 2,\n    bottomLeft: 2,\n    bottomRight: 2,\n  },\n  STANDARD_BORDER_RADIUS: 0,\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as useQuickActions } from './useQuickActions';\nexport { default as MediaPicker } from './mediaPicker';\nexport * from './constants';\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/mediaPicker.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport {\n  getExtensionsFromMimeType,\n  resourceList,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../config';\nimport { useStory } from '../story';\nimport { TRANSCODABLE_MIME_TYPES, useLocalMedia } from '../media';\nimport useFFmpeg from '../media/utils/useFFmpeg';\n\nconst MediaPicker = ({ render, ...props }) => {\n  const {\n    allowedMimeTypes: {\n      image: allowedImageMimeTypes,\n      vector: allowedVectorMimeTypes,\n      video: allowedVideoMimeTypes,\n    },\n    MediaUpload,\n  } = useConfig();\n\n  const { selectedElements, updateElementsById } = useStory(\n    ({ state: { selectedElements }, actions: { updateElementsById } }) => ({\n      selectedElements,\n      updateElementsById,\n    })\n  );\n  const {\n    resetWithFetch,\n    postProcessingResource,\n    optimizeVideo,\n    optimizeGif,\n    canTranscodeResource,\n  } = useLocalMedia(\n    ({\n      state: { canTranscodeResource },\n      actions: {\n        resetWithFetch,\n        postProcessingResource,\n        optimizeVideo,\n        optimizeGif,\n      },\n    }) => ({\n      canTranscodeResource,\n      resetWithFetch,\n      postProcessingResource,\n      optimizeVideo,\n      optimizeGif,\n    })\n  );\n\n  const { isTranscodingEnabled } = useFFmpeg();\n  const { showSnackbar } = useSnackbar();\n\n  // Media Upload Props\n  let allowedMimeTypes = useMemo(\n    () => [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ],\n    [allowedImageMimeTypes, allowedVectorMimeTypes, allowedVideoMimeTypes]\n  );\n  const allowedFileTypes = useMemo(\n    () => allowedMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedMimeTypes]\n  );\n  if (isTranscodingEnabled) {\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    allowedMimeTypes = allowedMimeTypes.concat(TRANSCODABLE_MIME_TYPES);\n  }\n\n  const transcodableMimeTypes = TRANSCODABLE_MIME_TYPES.filter(\n    (x) => !allowedVideoMimeTypes.includes(x)\n  );\n\n  let onSelectErrorMessage = __(\n    'No file types are currently supported.',\n    'web-stories'\n  );\n  if (allowedFileTypes.length) {\n    onSelectErrorMessage = sprintf(\n      /* translators: %s: list of allowed file types. */\n      __('Please choose only %s to insert into page.', 'web-stories'),\n      translateToExclusiveList(allowedFileTypes)\n    );\n  }\n\n  /**\n   * Insert element such image, video and audio into the editor.\n   *\n   * @param {Object} resource Resource object\n   * @param {string} thumbnailURL The thumbnail's url\n   * @return {null|*} Return onInsert or null.\n   */\n  const insertMediaElement = useCallback(\n    (resource, thumbnailURL) => {\n      resourceList.set(resource.id, {\n        url: thumbnailURL,\n        type: 'cached',\n      });\n      updateElementsById({\n        elementIds: [selectedElements?.[0]?.id],\n        properties: { type: resource.type, resource },\n      });\n    },\n    [selectedElements, updateElementsById]\n  );\n\n  const handleMediaSelect = useCallback(\n    (resource) => {\n      try {\n        if (isTranscodingEnabled && canTranscodeResource(resource)) {\n          if (transcodableMimeTypes.includes(resource.mimeType)) {\n            optimizeVideo({ resource });\n          }\n\n          if (resource.mimeType === 'image/gif') {\n            optimizeGif({ resource });\n          }\n        }\n        // WordPress media picker event, sizes.medium.sourceUrl is the smallest image\n        insertMediaElement(\n          resource,\n          resource.sizes?.medium?.sourceUrl || resource.src\n        );\n\n        postProcessingResource(resource);\n      } catch (e) {\n        showSnackbar({\n          message: e.message,\n          dismissable: true,\n        });\n      }\n    },\n    [\n      isTranscodingEnabled,\n      canTranscodeResource,\n      insertMediaElement,\n      postProcessingResource,\n      transcodableMimeTypes,\n      optimizeVideo,\n      optimizeGif,\n      showSnackbar,\n    ]\n  );\n  return (\n    <MediaUpload\n      title={__('Replace media', 'web-stories')}\n      buttonInsertText={__('Replace media', 'web-stories')}\n      onSelect={handleMediaSelect}\n      onClose={resetWithFetch}\n      type={allowedMimeTypes}\n      onSelectErrorMessage={onSelectErrorMessage}\n      // Only way to access the open function is to dive\n      // into the MediaUpload component in the render prop.\n      render={(open) => render({ onClick: open })}\n      {...props}\n    />\n  );\n};\nMediaPicker.propTypes = {\n  buttonInsertText: PropTypes.string,\n  cropParams: PropTypes.bool,\n  multiple: PropTypes.bool,\n  onClose: PropTypes.func,\n  onPermissionError: PropTypes.func,\n  onSelect: PropTypes.func,\n  onSelectErrorMessage: PropTypes.string,\n  render: PropTypes.func.isRequired,\n  title: PropTypes.string,\n  type: PropTypes.oneOfType([\n    PropTypes.string,\n    PropTypes.arrayOf(PropTypes.string),\n  ]),\n};\n\nexport default MediaPicker;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/test/useQuickActions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { fireEvent, render, screen } from '@testing-library/react';\nimport { Icons, useSnackbar } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useQuickActions } from '..';\nimport { states } from '../../highlights';\nimport useHighlights from '../../highlights/useHighlights';\nimport { STORY_EVENTS } from '../../story/storyTriggers/storyEvents';\nimport { useStory, useStoryTriggersDispatch } from '../../story';\nimport { ACTIONS } from '../constants';\nimport useApplyTextAutoStyle from '../../../utils/useApplyTextAutoStyle';\nimport { useConfig, useLocalMedia } from '../..';\nimport useFFmpeg from '../../media/utils/useFFmpeg';\nimport MediaPicker from '../mediaPicker';\nimport { noop } from '../../../utils/noop';\nimport useInsertElement from '../../../components/canvas/useInsertElement';\n\nconst {\n  Bucket,\n  Captions,\n  CircleSpeed,\n  ColorBucket,\n  Eraser,\n  LetterTPlus,\n  Link,\n  Media,\n  PictureSwap,\n} = Icons;\n\njest.mock('../../story', () => ({\n  useStory: jest.fn(),\n  useStoryTriggersDispatch: jest.fn(),\n  // Was getting a circular deps error or something\n  // trying to requireActual here so just manually\n  // set STORY_EVENTS and ELEMENT_TYPES for now:\n  // __esModule: true,\n  // ...jest.requireActual('../../../story'),\n  STORY_EVENTS: {\n    onReplaceBackgroundMedia: 'onReplaceBackgroundMedia',\n    onReplaceForegroundMedia: 'onReplaceForegroundMedia',\n  },\n  ELEMENT_TYPES: {\n    IMAGE: 'image',\n    SHAPE: 'shape',\n    TEXT: 'text',\n    VIDEO: 'video',\n    GIF: 'gif',\n    PRODUCT: 'product',\n  },\n}));\n\njest.mock('../../highlights/useHighlights', () => ({\n  ...jest.requireActual('../../highlights/useHighlights'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\njest.mock('../../../utils/useApplyTextAutoStyle');\n\njest.mock('../../../components/canvas/useInsertElement');\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn((selector = (v) => v) =>\n    selector({ showSnackbar: jest.fn() })\n  ),\n}));\n\njest.mock('@googleforcreators/tracking');\n\njest.mock('@googleforcreators/media', () => ({\n  ...jest.requireActual('@googleforcreators/media'),\n  resourceList: {\n    set: jest.fn(),\n  },\n}));\n\njest.mock('../../media', () => ({\n  ...jest.requireActual('../../media'),\n  useLocalMedia: jest.fn(),\n}));\n\njest.mock('../../config');\njest.mock('../../media/utils/useFFmpeg');\n\nconst mockClickEvent = {\n  preventDefault: jest.fn(),\n};\n\nconst BACKGROUND_ELEMENT = {\n  id: 'background-element-id',\n  isBackground: true,\n  type: 'shape',\n};\nconst BACKGROUND_IMAGE_ELEMENT = {\n  id: 'background-image-element-id',\n  isBackground: true,\n  type: 'image',\n  resource: {\n    resource: {\n      id: 'mysite/1234',\n    },\n  },\n};\n\nconst BACKGROUND_IMAGE_MEDIA3P_ELEMENT = {\n  id: 'background-image-media3p-element-id',\n  isBackground: true,\n  type: 'image',\n  resource: {\n    id: 'media/unsplash:wsomemedia-123',\n    isExternal: true,\n  },\n};\n\nconst BACKGROUND_VIDEO_ELEMENT = {\n  id: 'background-video-element-id',\n  isBackground: true,\n  type: 'video',\n  resource: {\n    id: 'mysite/1234',\n  },\n};\n\nconst IMAGE_ELEMENT = {\n  id: 'image-element-id',\n  type: 'image',\n};\n\nconst SHAPE_ELEMENT = {\n  id: 'shape-element-id',\n  type: 'shape',\n};\n\nconst TEXT_ELEMENT = {\n  id: 'text-element-id',\n  type: 'text',\n};\n\nconst VIDEO_ELEMENT = {\n  id: 'video-element-id',\n  type: 'video',\n};\n\nconst STICKER_ELEMENT = {\n  id: 'sticker-element-id',\n  type: 'sticker',\n};\n\nconst resetElementAction = expect.objectContaining({\n  label: ACTIONS.RESET_ELEMENT.text,\n  onClick: expect.any(Function),\n  Icon: Eraser,\n});\n\nconst defaultQuickActions = [\n  expect.objectContaining({\n    label: ACTIONS.CHANGE_BACKGROUND_COLOR.text,\n    onClick: expect.any(Function),\n    Icon: Bucket,\n  }),\n  expect.objectContaining({\n    label: ACTIONS.INSERT_BACKGROUND_MEDIA.text,\n    onClick: expect.any(Function),\n    Icon: Media,\n  }),\n  expect.objectContaining({\n    label: ACTIONS.INSERT_TEXT.text,\n    onClick: expect.any(Function),\n    Icon: LetterTPlus,\n  }),\n];\n\nconst foregroundCommonActions = [\n  expect.objectContaining({\n    label: ACTIONS.ADD_LINK.text,\n    onClick: expect.any(Function),\n    Icon: Link,\n  }),\n];\n\nconst foregroundImageQuickActions = [\n  expect.objectContaining({\n    label: ACTIONS.REPLACE_MEDIA.text,\n    onClick: expect.any(Function),\n    Icon: PictureSwap,\n  }),\n  ...foregroundCommonActions,\n];\n\nconst foregroundImageQuickActionsWithClear = [\n  ...foregroundImageQuickActions,\n  resetElementAction,\n];\n\nconst shapeQuickActions = foregroundCommonActions;\n\nconst shapeQuickActionsWithClear = [...shapeQuickActions, resetElementAction];\n\nconst textQuickActions = [\n  expect.objectContaining({\n    label: ACTIONS.AUTO_STYLE_TEXT.text,\n    onClick: expect.any(Function),\n    Icon: ColorBucket,\n  }),\n  ...foregroundCommonActions,\n];\nconst textQuickActionsWithClear = [...textQuickActions, resetElementAction];\n\nconst backgroundMediaQuickActions = [\n  expect.objectContaining({\n    label: ACTIONS.REPLACE_BACKGROUND_MEDIA.text,\n    onClick: expect.any(Function),\n    Icon: PictureSwap,\n  }),\n  expect.objectContaining({\n    label: ACTIONS.ADD_ANIMATION.text,\n    onClick: expect.any(Function),\n    Icon: CircleSpeed,\n  }),\n];\nconst backgroundMediaQuickActionsWithClear = [\n  ...backgroundMediaQuickActions,\n  resetElementAction,\n];\n\nconst videoQuickActions = [\n  ...foregroundImageQuickActions,\n  expect.objectContaining({\n    label: ACTIONS.ADD_CAPTIONS.text,\n    onClick: expect.any(Function),\n    Icon: Captions,\n  }),\n];\n\nconst videoQuickActionsWithClear = [...videoQuickActions, resetElementAction];\n\nconst stickerQuickActions = [...foregroundCommonActions];\n\nconst stickerQuickActionsWithClear = [\n  ...stickerQuickActions,\n  resetElementAction,\n];\n\nconst videoResource = {\n  id: 'video',\n  type: 'video',\n  mimeType: 'video/mp4',\n  src: 'video',\n};\nconst imageResource = {\n  id: 'image',\n  type: 'image',\n  mimeType: 'image',\n  src: 'image',\n};\nconst gifResource = {\n  id: 'gif',\n  type: 'gif',\n  mimeType: 'image/gif',\n  src: 'gif',\n};\n\nlet highlight;\nconst mockUseHighlights = useHighlights;\nconst mockUseStory = useStory;\nconst mockDispatchStoryEvent = jest.fn();\nconst mockUpdateElementsById = jest.fn();\nconst mockUseApplyTextAutoStyle = useApplyTextAutoStyle;\nconst mockUseInsertElement = useInsertElement;\nconst mockInsertElement = jest.fn();\nconst mockUseConfig = useConfig;\nconst mockUseLocalMedia = useLocalMedia;\nconst mockResetWithFetch = jest.fn();\nconst mockPostProcessingResource = jest.fn();\nconst mockOptimizeVideo = jest.fn();\nconst mockOptimizeGif = jest.fn();\nconst mockUseFFmpeg = useFFmpeg;\nconst mockUseSnackbar = useSnackbar;\nconst mockShowSnackbar = jest.fn();\n\nconst MockMediaPicker = ({ onSelect, onClose }) => (\n  <>\n    <button onClick={() => onSelect(imageResource)}>{'onSelect image'}</button>\n    <button onClick={() => onSelect(gifResource)}>{'onSelect gif'}</button>\n    <button onClick={() => onSelect(videoResource)}>{'onSelect video'}</button>\n    <button\n      onClick={() =>\n        onSelect({\n          ...videoResource,\n          isMuted: null,\n        })\n      }\n    >\n      {'onSelect muted video'}\n    </button>\n    <button onClick={onClose}>{'onClose'}</button>\n  </>\n);\n\ndescribe('useQuickActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    highlight = undefined;\n    mockUseHighlights.mockImplementation(() => ({\n      setHighlights: (value) => {\n        highlight = value;\n      },\n    }));\n\n    mockUseApplyTextAutoStyle.mockImplementation(() => ({\n      applyTextAutoStyle: jest.fn(),\n    }));\n\n    mockUseStory.mockReturnValue({\n      currentPage: {\n        elements: [BACKGROUND_ELEMENT],\n      },\n      selectedElementAnimations: [],\n      selectedElements: [],\n      updateElementsById: mockUpdateElementsById,\n    });\n\n    useStoryTriggersDispatch.mockReturnValue(mockDispatchStoryEvent);\n\n    mockUseConfig.mockReturnValue({\n      allowedMimeTypes: {\n        image: [],\n        vector: [],\n        video: [],\n        caption: [],\n        audio: [],\n      },\n      capabilities: { hasUploadMediaAction: true },\n      isRTL: true,\n      MediaPicker: MockMediaPicker,\n    });\n\n    mockUseLocalMedia.mockReturnValue({\n      resetWithFetch: noop,\n      postProcessingResource: noop,\n      optimizeVideo: noop,\n      optimizeGif: noop,\n      canTranscodeResource: noop,\n    });\n  });\n\n  describe('multiple elements selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((s) =>\n        s({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_ELEMENT, IMAGE_ELEMENT, VIDEO_ELEMENT],\n            },\n            selectedElementAnimations: [],\n            selectedElements: [IMAGE_ELEMENT, VIDEO_ELEMENT],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n    });\n\n    it('should return no quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual([]);\n    });\n  });\n\n  describe('no element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((s) =>\n        s({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_ELEMENT],\n            },\n            selectedElementAnimations: [],\n            selectedElements: [],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n      mockUseInsertElement.mockReturnValue(mockInsertElement);\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(defaultQuickActions);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_ELEMENT.id,\n        highlight: states.PageBackground,\n      });\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: undefined,\n        highlight: states.Media,\n      });\n\n      result.current[2].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        highlight: states.StylePane,\n      });\n    });\n  });\n\n  describe('empty background element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((selector) =>\n        selector({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_ELEMENT],\n            },\n            selectedElementAnimations: [],\n            selectedElements: [BACKGROUND_ELEMENT],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(defaultQuickActions);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_ELEMENT.id,\n        highlight: states.PageBackground,\n      });\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_ELEMENT.id,\n        highlight: states.Media,\n      });\n\n      result.current[2].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        highlight: states.StylePane,\n      });\n    });\n  });\n\n  describe('background image element is selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((selector) =>\n        selector({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_IMAGE_ELEMENT],\n            },\n            selectedElementAnimations: [],\n            selectedElements: [BACKGROUND_IMAGE_ELEMENT],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(backgroundMediaQuickActions);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_IMAGE_ELEMENT.id,\n        highlight: states.Animation,\n      });\n    });\n\n    it(`should trigger ${STORY_EVENTS.onReplaceBackgroundMedia} when replace media clicked`, () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(mockDispatchStoryEvent).toHaveBeenCalledOnce();\n      expect(mockDispatchStoryEvent).toHaveBeenCalledWith(\n        STORY_EVENTS.onReplaceBackgroundMedia\n      );\n    });\n  });\n\n  describe('background third party image element is selected with animation', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((selector) =>\n        selector({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_IMAGE_MEDIA3P_ELEMENT],\n            },\n            selectedElementAnimations: [],\n            selectedElements: [BACKGROUND_IMAGE_MEDIA3P_ELEMENT],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(backgroundMediaQuickActions);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_IMAGE_MEDIA3P_ELEMENT.id,\n        highlight: states.Animation,\n      });\n    });\n  });\n\n  describe('background video element is selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockImplementation((selector) =>\n        selector({\n          state: {\n            currentPage: {\n              elements: [BACKGROUND_VIDEO_ELEMENT],\n            },\n            selectedElementAnimations: [\n              {\n                target: [BACKGROUND_VIDEO_ELEMENT.id],\n              },\n            ],\n            selectedElements: [BACKGROUND_VIDEO_ELEMENT],\n          },\n          actions: {\n            updateElementsById: mockUpdateElementsById,\n          },\n        })\n      );\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(\n        backgroundMediaQuickActionsWithClear\n      );\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: BACKGROUND_VIDEO_ELEMENT.id,\n        highlight: states.Animation,\n      });\n    });\n\n    it('clicking `clear filters and animations` should update the element', () => {\n      const { result } = renderHook(() => useQuickActions());\n      result.current[2].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [BACKGROUND_VIDEO_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n  });\n\n  describe('foreground image element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, IMAGE_ELEMENT],\n        },\n        selectedElementAnimations: [\n          {\n            target: [IMAGE_ELEMENT.id],\n          },\n        ],\n        selectedElements: [IMAGE_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(\n        foregroundImageQuickActionsWithClear\n      );\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: IMAGE_ELEMENT.id,\n        highlight: states.Link,\n      });\n    });\n\n    it(`\\`${ACTIONS.RESET_ELEMENT.text}\\` action should not be present if element has no animations`, () => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, IMAGE_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [IMAGE_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current[2]).toBeUndefined();\n    });\n\n    it('clicking `reset element` should update the element', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[2].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [IMAGE_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n\n    it(`should trigger ${STORY_EVENTS.onReplaceForegroundMedia} when replace media clicked`, () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(mockDispatchStoryEvent).toHaveBeenCalledOnce();\n      expect(mockDispatchStoryEvent).toHaveBeenCalledWith(\n        STORY_EVENTS.onReplaceForegroundMedia\n      );\n    });\n  });\n\n  describe('shape element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, SHAPE_ELEMENT],\n        },\n        selectedElementAnimations: [\n          {\n            target: [SHAPE_ELEMENT.id],\n          },\n        ],\n        selectedElements: [SHAPE_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n      expect(result.current).toStrictEqual(shapeQuickActionsWithClear);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: SHAPE_ELEMENT.id,\n        highlight: states.Link,\n      });\n    });\n\n    it(`\\`${ACTIONS.RESET_ELEMENT.text}\\` action should not be present if element has no animations`, () => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, SHAPE_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [SHAPE_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current[1]).toBeUndefined();\n    });\n\n    it('clicking `clear animations` should call `updateElementsById`', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [SHAPE_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n  });\n\n  describe('text selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, TEXT_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [TEXT_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n    });\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(textQuickActions);\n    });\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: TEXT_ELEMENT.id,\n        highlight: states.Link,\n      });\n    });\n\n    it(`\\`${ACTIONS.RESET_ELEMENT.text}\\` action should not be present if element has no animations`, () => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, TEXT_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [TEXT_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current[2]).toBeUndefined();\n    });\n\n    it('clicking `reset element` should update the element', () => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, TEXT_ELEMENT],\n        },\n        selectedElementAnimations: [\n          {\n            target: [TEXT_ELEMENT.id],\n          },\n        ],\n        selectedElements: [TEXT_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n      expect(result.current).toStrictEqual(textQuickActionsWithClear);\n\n      result.current[2].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [TEXT_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n  });\n\n  describe('video element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, VIDEO_ELEMENT],\n        },\n        selectedElementAnimations: [\n          {\n            id: VIDEO_ELEMENT.id,\n          },\n        ],\n        selectedElements: [VIDEO_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n      expect(result.current).toStrictEqual(videoQuickActionsWithClear);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: VIDEO_ELEMENT.id,\n        highlight: states.Link,\n      });\n\n      result.current[2].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: VIDEO_ELEMENT.id,\n        highlight: states.Captions,\n      });\n    });\n\n    it(`should not show \\`${ACTIONS.RESET_ELEMENT.text}\\` action if element has no animations`, () => {\n      mockUseStory.mockReturnValueOnce({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, VIDEO_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [VIDEO_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current[4]).toBeUndefined();\n    });\n\n    it(`should click \\`${ACTIONS.RESET_ELEMENT.text} and update the element`, () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[3].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [VIDEO_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n  });\n\n  describe('sticker element selected', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, STICKER_ELEMENT],\n        },\n        selectedElementAnimations: [\n          {\n            target: [STICKER_ELEMENT.id],\n          },\n        ],\n        selectedElements: [STICKER_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n    });\n\n    it('should return the quick actions', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current).toStrictEqual(stickerQuickActionsWithClear);\n    });\n\n    it('should set the correct highlight', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[0].onClick(mockClickEvent);\n      expect(highlight).toStrictEqual({\n        elementId: STICKER_ELEMENT.id,\n        highlight: states.Link,\n      });\n    });\n\n    it(`\\`${ACTIONS.RESET_ELEMENT.text}\\` action should not be present if element has no animations`, () => {\n      mockUseStory.mockReturnValue({\n        currentPage: {\n          elements: [BACKGROUND_ELEMENT, STICKER_ELEMENT],\n        },\n        selectedElementAnimations: [],\n        selectedElements: [STICKER_ELEMENT],\n        updateElementsById: mockUpdateElementsById,\n      });\n\n      const { result } = renderHook(() => useQuickActions());\n\n      expect(result.current[3]).toBeUndefined();\n    });\n\n    it('clicking `reset element` should update the element', () => {\n      const { result } = renderHook(() => useQuickActions());\n\n      result.current[1].onClick(mockClickEvent);\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [STICKER_ELEMENT.id],\n        properties: expect.any(Function),\n      });\n    });\n  });\n});\n\ndescribe('MediaPicker', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockReturnValue({\n      selectedElements: [IMAGE_ELEMENT],\n      updateElementsById: mockUpdateElementsById,\n    });\n\n    mockUseConfig.mockReturnValue({\n      allowedMimeTypes: {\n        image: ['image/gif'],\n        vector: [],\n        video: ['muted'],\n        caption: [],\n        audio: [],\n      },\n      capabilities: { hasUploadMediaAction: true },\n      isRTL: true,\n      MediaUpload: MockMediaPicker,\n    });\n\n    mockUseLocalMedia.mockReturnValue({\n      resetWithFetch: mockResetWithFetch,\n      postProcessingResource: mockPostProcessingResource,\n      optimizeVideo: mockOptimizeVideo,\n      optimizeGif: mockOptimizeGif,\n      canTranscodeResource: () => true,\n    });\n\n    mockUseFFmpeg.mockReturnValue({ isTranscodingEnabled: true });\n    mockUseSnackbar.mockReturnValue({ showSnackbar: mockShowSnackbar });\n  });\n\n  it('should insert an image', () => {\n    render(<MediaPicker render={noop} />);\n\n    fireEvent.click(screen.getByText('onSelect image'));\n\n    expect(mockOptimizeGif).toHaveBeenCalledTimes(0);\n    expect(mockOptimizeVideo).toHaveBeenCalledTimes(0);\n    expect(mockUpdateElementsById).toHaveBeenCalledWith({\n      elementIds: [IMAGE_ELEMENT.id],\n      properties: { type: imageResource.id, resource: imageResource },\n    });\n  });\n\n  it('should insert an optimized gif', () => {\n    render(<MediaPicker render={noop} />);\n\n    fireEvent.click(screen.getByText('onSelect gif'));\n\n    expect(mockOptimizeGif).toHaveBeenCalledOnce();\n    expect(mockOptimizeVideo).toHaveBeenCalledTimes(0);\n    expect(mockUpdateElementsById).toHaveBeenCalledWith({\n      elementIds: [IMAGE_ELEMENT.id],\n      properties: { type: gifResource.id, resource: gifResource },\n    });\n  });\n\n  it('should insert an optimized video', () => {\n    render(<MediaPicker render={noop} />);\n\n    fireEvent.click(screen.getByText('onSelect video'));\n\n    expect(mockOptimizeGif).toHaveBeenCalledTimes(0);\n    expect(mockOptimizeVideo).toHaveBeenCalledOnce();\n    expect(mockUpdateElementsById).toHaveBeenCalledWith({\n      elementIds: [IMAGE_ELEMENT.id],\n      properties: { type: videoResource.id, resource: videoResource },\n    });\n  });\n\n  it('should call postProcessingResource for a video that is muted', () => {\n    render(<MediaPicker render={noop} />);\n\n    fireEvent.click(screen.getByText('onSelect muted video'));\n\n    expect(mockPostProcessingResource).toHaveBeenCalledWith({\n      ...videoResource,\n      mimeType: 'video/mp4',\n      isMuted: null,\n    });\n    expect(mockUpdateElementsById).toHaveBeenCalledWith({\n      elementIds: [IMAGE_ELEMENT.id],\n      properties: {\n        type: videoResource.id,\n        resource: {\n          ...videoResource,\n          isMuted: null,\n        },\n      },\n    });\n  });\n\n  it('should show a snackbar if something fails during upload', () => {\n    mockOptimizeVideo.mockImplementation(() => {\n      throw new Error('throwing it down');\n    });\n\n    render(<MediaPicker render={noop} />);\n\n    fireEvent.click(screen.getByText('onSelect video'));\n\n    expect(mockUpdateElementsById).not.toHaveBeenCalled();\n    expect(mockShowSnackbar).toHaveBeenCalledWith({\n      message: 'throwing it down',\n      dismissable: true,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/useElementReset.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useSnackbar,\n  prettifyShortcut,\n} from '@googleforcreators/design-system';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { ElementType } from '@googleforcreators/elements';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useHistory } from '../history';\nimport { useStory } from '../story';\nimport updateProperties from '../../components/style/updateProperties';\nimport { ACTIONS, RESET_DEFAULTS, RESET_PROPERTIES } from './constants';\n\nfunction useElementReset() {\n  const showSnackbar = useSnackbar(({ showSnackbar }) => showSnackbar);\n  const { selectedElementAnimations, updateElementsById } = useStory(\n    ({\n      state: { selectedElementAnimations },\n      actions: { updateElementsById },\n    }) => ({\n      selectedElementAnimations,\n      updateElementsById,\n    })\n  );\n  const { undo } = useHistory(({ actions: { undo } }) => ({\n    undo,\n  }));\n  const undoRef = useRef(undo);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  undoRef.current = undo;\n  /**\n   * Reset properties on an element. Shows a snackbar once the properties\n   * have been reset.\n   *\n   * @param {string} elementId the id of the element\n   * @param {Array.<string>} properties The properties of the element to update\n   * @return {void}\n   */\n  const handleResetProperties = useCallback(\n    (elementType, elementId, properties) => {\n      const newProperties = {};\n      // Choose properties to clear\n      if (properties.includes(RESET_PROPERTIES.OVERLAY)) {\n        newProperties.overlay = null;\n      }\n\n      if (properties.includes(RESET_PROPERTIES.ANIMATION)) {\n        // this is the only place where we're updating both animations and other\n        // properties on an element. updateElementsById only accepts if you update\n        // one or the other, so we're updating animations if needed here separately\n        updateElementsById({\n          elementIds: [elementId],\n          properties: (currentProperties) =>\n            updateProperties(\n              currentProperties,\n              {\n                animation: { ...selectedElementAnimations?.[0], delete: true },\n              },\n              /* commitValues */ true\n            ),\n        });\n      }\n\n      if (properties.includes(RESET_PROPERTIES.STYLES)) {\n        newProperties.opacity = 100;\n        newProperties.border = null;\n        newProperties.borderRadius = null;\n      }\n\n      if (elementType === ElementType.Text) {\n        newProperties.borderRadius = RESET_DEFAULTS.TEXT_BORDER_RADIUS;\n      }\n\n      updateElementsById({\n        elementIds: [elementId],\n        properties: (currentProperties) =>\n          updateProperties(\n            currentProperties,\n            newProperties,\n            /* commitValues */ true\n          ),\n      });\n    },\n    [selectedElementAnimations, updateElementsById]\n  );\n\n  /**\n   * Reset element styles and show a confirmation snackbar. Clicking\n   * the action in the snackbar adds the animations back to the element.\n   *\n   * @param {string} elementId the id of the element\n   * @param {Array} resetProperties the properties that are to be reset ('animations', 'overlay')\n   * @param {string} elementType the type of element being adjusted\n   * @return {void}\n   */\n  const handleElementReset = useCallback(\n    ({ elementId, resetProperties, elementType }) => {\n      handleResetProperties(elementType, elementId, resetProperties);\n\n      showSnackbar({\n        actionLabel: __('Undo', 'web-stories'),\n        dismissible: false,\n        message: __('Element properties have been reset', 'web-stories'),\n        // Don't pass a stale version of `undo`\n        onAction: () => {\n          undoRef.current();\n\n          trackEvent('quick_action', {\n            name: `undo_${ACTIONS.RESET_ELEMENT.trackingEventName}`,\n            element: elementType,\n            isBackground: true,\n          });\n        },\n        actionHelpText: sprintf(\n          /* translators: %s: Ctrl/Cmd + Z keyboard shortcut */\n          __('Press %s to undo the last change', 'web-stories'),\n          prettifyShortcut('mod+z')\n        ),\n      });\n    },\n    [handleResetProperties, showSnackbar]\n  );\n\n  return handleElementReset;\n}\n\nexport default useElementReset;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/useForegroundActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { useMemo } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { states } from '../highlights';\nimport { useStory } from '../story';\nimport { ACTIONS } from './constants';\nimport useElementReset from './useElementReset';\n\nfunction useForegroundActions({\n  actionProps,\n  selectedElement,\n  handleFocusPanel,\n  resetProperties,\n}) {\n  const { currentPageNumber } = useStory(\n    ({ state: { currentPageNumber } }) => ({\n      currentPageNumber,\n    })\n  );\n  const handleElementReset = useElementReset();\n\n  const showClearAction = resetProperties.length > 0;\n  const foregroundCommonActions = useMemo(() => {\n    const handleFocusAnimationPanel = handleFocusPanel(states.Animation);\n    const handleFocusLinkPanel = handleFocusPanel(states.Link);\n    const commonActions = [];\n\n    // Don't show the 'Add animation' button on the first page\n    if (currentPageNumber > 1) {\n      // 'Add animation' button\n      commonActions.push({\n        Icon: Icons.CircleSpeed,\n        label: ACTIONS.ADD_ANIMATION.text,\n        onClick: (evt) => {\n          handleFocusAnimationPanel()(evt);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.ADD_ANIMATION.trackingEventName,\n            element: selectedElement?.type,\n          });\n        },\n        ...actionProps,\n      });\n    }\n\n    // 'Add link' button is always rendered\n    commonActions.push({\n      Icon: Icons.Link,\n      label: ACTIONS.ADD_LINK.text,\n      onClick: (evt) => {\n        handleFocusLinkPanel()(evt);\n\n        trackEvent('quick_action', {\n          name: ACTIONS.ADD_LINK.trackingEventName,\n          element: selectedElement?.type,\n        });\n      },\n      ...actionProps,\n    });\n\n    // Only show 'Reset element' button for modified elements\n    if (showClearAction) {\n      // 'Reset element' button\n      commonActions.push({\n        Icon: Icons.Eraser,\n        label: ACTIONS.RESET_ELEMENT.text,\n        onClick: () => {\n          handleElementReset({\n            elementId: selectedElement?.id,\n            resetProperties,\n            elementType: selectedElement?.type,\n          });\n\n          trackEvent('quick_action', {\n            name: ACTIONS.RESET_ELEMENT.trackingEventName,\n            element: selectedElement?.type,\n          });\n        },\n        separator: 'top',\n        ...actionProps,\n      });\n    }\n\n    return commonActions;\n  }, [\n    handleFocusPanel,\n    currentPageNumber,\n    actionProps,\n    showClearAction,\n    selectedElement?.type,\n    selectedElement?.id,\n    resetProperties,\n    handleElementReset,\n  ]);\n\n  return foregroundCommonActions;\n}\n\nexport default useForegroundActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/useMediaActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { Icons } from '@googleforcreators/design-system';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { states } from '../highlights';\nimport {\n  BACKGROUND_BLUR_PX,\n  VIDEO_EFFECTS,\n} from '../../components/mediaRecording/constants';\nimport { useMediaRecording } from '../../components/mediaRecording';\nimport { STORY_EVENTS, useStoryTriggersDispatch } from '../story';\nimport { useConfig } from '../config';\nimport { ACTIONS } from './constants';\nimport useElementReset from './useElementReset';\n\nconst quickActionIconAttrs = {\n  width: 24,\n  height: 24,\n};\nconst StyledSettings = styled(Icons.Settings).attrs(quickActionIconAttrs)``;\nconst Mic = styled(Icons.Mic).attrs(quickActionIconAttrs)``;\nconst MicOff = styled(Icons.MicOff).attrs(quickActionIconAttrs)``;\nconst Video = styled(Icons.Camera).attrs(quickActionIconAttrs)``;\nconst VideoOff = styled(Icons.CameraOff).attrs(quickActionIconAttrs)``;\nconst BackgroundBlur = styled(Icons.BackgroundBlur).attrs(\n  quickActionIconAttrs\n)``;\nconst BackgroundBlurOff = styled(Icons.BackgroundBlurOff).attrs(\n  quickActionIconAttrs\n)``;\n\nfunction useMediaActions({\n  actionProps,\n  selectedElement,\n  handleFocusPanel,\n  resetProperties,\n  commonActions,\n}) {\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const dispatchStoryEvent = useStoryTriggersDispatch();\n  const {\n    toggleRecordingMode,\n    toggleVideo,\n    toggleAudio,\n    hasVideo,\n    hasAudio,\n    videoEffect,\n    setVideoEffect,\n    toggleSettings,\n    audioInput,\n    videoInput,\n    isReady,\n    isProcessing,\n    isAdjustingTrim,\n    isProcessingTrim,\n    startTrim,\n  } = useMediaRecording(({ state, actions }) => ({\n    hasAudio: state.hasAudio,\n    hasVideo: state.hasVideo,\n    videoEffect: state.videoEffect,\n    audioInput: state.audioInput,\n    videoInput: state.videoInput,\n    isReady:\n      state.inputStatus === 'ready' &&\n      !state.file?.type?.startsWith('image') &&\n      !state.isCountingDown &&\n      (state.status === 'ready' || state.status === 'idle'),\n    isProcessing: state.isProcessing,\n    isAdjustingTrim: state.isAdjustingTrim,\n    isProcessingTrim: state.isProcessingTrim,\n    toggleRecordingMode: actions.toggleRecordingMode,\n    toggleVideo: actions.toggleVideo,\n    toggleAudio: actions.toggleAudio,\n    toggleSettings: actions.toggleSettings,\n    muteAudio: actions.muteAudio,\n    unMuteAudio: actions.unMuteAudio,\n    startTrim: actions.startTrim,\n    setVideoEffect: actions.setVideoEffect,\n  }));\n  const showClearAction = resetProperties.length > 0;\n\n  const foregroundImageActions = useMemo(() => {\n    const actions = [];\n\n    if (hasUploadMediaAction) {\n      actions.push({\n        Icon: Icons.PictureSwap,\n        label: ACTIONS.REPLACE_MEDIA.text,\n        onClick: () => {\n          dispatchStoryEvent(STORY_EVENTS.onReplaceForegroundMedia);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.REPLACE_MEDIA.trackingEventName,\n            element: selectedElement?.type,\n          });\n        },\n        wrapWithMediaPicker: true,\n        ...actionProps,\n      });\n    }\n\n    return [...actions, ...commonActions];\n  }, [\n    hasUploadMediaAction,\n    commonActions,\n    actionProps,\n    dispatchStoryEvent,\n    selectedElement?.type,\n  ]);\n\n  const { handleFocusAnimationPanel, handleFocusCaptionsPanel } = useMemo(\n    () => ({\n      handleFocusAnimationPanel: handleFocusPanel(states.Animation),\n      handleFocusCaptionsPanel: handleFocusPanel(states.Captions),\n    }),\n    [handleFocusPanel]\n  );\n  const videoActions = useMemo(() => {\n    const [baseActions, clearActions] = showClearAction\n      ? [\n          foregroundImageActions.slice(0, foregroundImageActions.length - 1),\n          foregroundImageActions.slice(-1),\n        ]\n      : [foregroundImageActions, []];\n\n    return [\n      ...baseActions,\n      {\n        Icon: Icons.Captions,\n        label: ACTIONS.ADD_CAPTIONS.text,\n        onClick: (evt) => {\n          handleFocusCaptionsPanel()(evt);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.ADD_CAPTIONS.trackingEventName,\n            element: selectedElement?.type,\n          });\n        },\n        ...actionProps,\n      },\n      ...clearActions,\n    ];\n  }, [\n    actionProps,\n    foregroundImageActions,\n    handleFocusCaptionsPanel,\n    selectedElement?.type,\n    showClearAction,\n  ]);\n\n  const handleElementReset = useElementReset();\n  const backgroundElementMediaActions = useMemo(() => {\n    const baseActions = [\n      {\n        Icon: Icons.CircleSpeed,\n        label: ACTIONS.ADD_ANIMATION.text,\n        onClick: (evt) => {\n          handleFocusAnimationPanel()(evt);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.ADD_ANIMATION.trackingEventName,\n            element: selectedElement?.type,\n            isBackground: true,\n          });\n        },\n        ...actionProps,\n      },\n    ];\n\n    if (hasUploadMediaAction) {\n      baseActions.unshift({\n        Icon: Icons.PictureSwap,\n        label: ACTIONS.REPLACE_BACKGROUND_MEDIA.text,\n        onClick: () => {\n          dispatchStoryEvent(STORY_EVENTS.onReplaceBackgroundMedia);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.REPLACE_BACKGROUND_MEDIA.trackingEventName,\n            element: selectedElement?.type,\n            isBackground: true,\n          });\n        },\n        wrapWithMediaPicker: true,\n        ...actionProps,\n      });\n    }\n\n    const clearAction = {\n      Icon: Icons.Eraser,\n      label: ACTIONS.RESET_ELEMENT.text,\n      onClick: () => {\n        handleElementReset({\n          elementId: selectedElement?.id,\n          resetProperties,\n          elementType: ELEMENT_TYPES.IMAGE,\n        });\n\n        trackEvent('quick_action', {\n          name: ACTIONS.RESET_ELEMENT.trackingEventName,\n          element: selectedElement?.type,\n          isBackground: true,\n        });\n      },\n      separator: 'top',\n      ...actionProps,\n    };\n\n    return showClearAction ? [...baseActions, clearAction] : baseActions;\n  }, [\n    actionProps,\n    dispatchStoryEvent,\n    handleElementReset,\n    handleFocusAnimationPanel,\n    hasUploadMediaAction,\n    resetProperties,\n    selectedElement?.id,\n    selectedElement?.type,\n    showClearAction,\n  ]);\n\n  const mediaRecordingActions = useMemo(() => {\n    return [\n      {\n        Icon: Icons.Cross,\n        label: __('Close', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_mode_toggled', {\n            status: 'closed',\n          });\n          toggleRecordingMode();\n        },\n        ...actionProps,\n      },\n      {\n        Icon: StyledSettings,\n        label: __('Options', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_open_settings');\n          toggleSettings();\n        },\n        disabled: !isReady,\n        separator: 'top',\n        ...actionProps,\n      },\n      audioInput && {\n        Icon: hasAudio ? Mic : MicOff,\n        label: hasAudio\n          ? __('Disable Audio', 'web-stories')\n          : __('Enable Audio', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_audio_toggled', {\n            status: hasAudio ? 'muted' : 'unmuted',\n          });\n          toggleAudio();\n        },\n        disabled: !isReady || !hasVideo,\n        ...actionProps,\n      },\n      videoInput && {\n        Icon: hasVideo ? Video : VideoOff,\n        label: hasVideo\n          ? __('Disable Video', 'web-stories')\n          : __('Enable Video', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_video_toggled', {\n            status: hasVideo ? 'off' : 'on',\n          });\n          toggleVideo();\n        },\n        disabled: !isReady || !hasAudio,\n        ...actionProps,\n      },\n      videoInput && {\n        Icon:\n          videoEffect === VIDEO_EFFECTS.BLUR\n            ? BackgroundBlur\n            : BackgroundBlurOff,\n        label:\n          videoEffect === VIDEO_EFFECTS.BLUR\n            ? __('Disable Background Blur', 'web-stories')\n            : __('Enable Background Blur', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_background_blur_px', {\n            value: videoEffect === VIDEO_EFFECTS.BLUR ? 0 : BACKGROUND_BLUR_PX,\n          });\n          const newVideoEffect =\n            videoEffect === VIDEO_EFFECTS.BLUR\n              ? VIDEO_EFFECTS.NONE\n              : VIDEO_EFFECTS.BLUR;\n          setVideoEffect(newVideoEffect);\n        },\n        disabled: !isReady || !hasVideo,\n        ...actionProps,\n      },\n      {\n        Icon: Icons.Scissors,\n        label: __('Trim Video', 'web-stories'),\n        onClick: () => {\n          trackEvent('media_recording_trim_start');\n          startTrim();\n        },\n        disabled:\n          !isProcessing || isAdjustingTrim || !hasVideo || isProcessingTrim,\n        ...actionProps,\n      },\n    ].filter(Boolean);\n  }, [\n    actionProps,\n    isReady,\n    audioInput,\n    hasAudio,\n    hasVideo,\n    videoInput,\n    videoEffect,\n    isProcessing,\n    isAdjustingTrim,\n    isProcessingTrim,\n    toggleRecordingMode,\n    toggleSettings,\n    toggleAudio,\n    toggleVideo,\n    setVideoEffect,\n    startTrim,\n  ]);\n\n  return {\n    backgroundElementMediaActions,\n    foregroundImageActions,\n    mediaRecordingActions,\n    videoActions,\n  };\n}\n\nexport default useMediaActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/useQuickActions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useRef } from '@googleforcreators/react';\nimport { Icons, Placement } from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { ElementType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { states, useHighlights } from '../highlights';\nimport { useHistory } from '../history';\nimport { useStory } from '../story';\nimport useInsertElement from '../../components/canvas/useInsertElement';\nimport { DEFAULT_PRESET } from '../../components/library/panes/text/textPresets';\nimport { useMediaRecording } from '../../components/mediaRecording';\nimport { AUDIO_STICKER_DEFAULT_PRESET } from '../../constants';\nimport { getResetProperties } from './utils';\nimport { ACTIONS } from './constants';\nimport useTextActions from './useTextActions';\nimport useMediaActions from './useMediaActions';\nimport useForegroundActions from './useForegroundActions';\n\nconst { Bucket, LetterTPlus, Media, AudioSticker } = Icons;\n\n/**\n * Determines the quick actions to display in the quick\n * actions menu from the selected element.\n *\n * Quick actions should follow the `quickActionPropType` definition.\n *\n * @return {Array.<{ Icon: Node, label: string, onClick: Function, separator: string, tooltipPlacement: string, wrapWithMediaPicker: boolean }>} an array of quick action objects\n */\nconst useQuickActions = () => {\n  const {\n    backgroundElement,\n    selectedElementAnimations,\n    selectedElements,\n    updateElementsById,\n  } = useStory(\n    ({\n      state: {\n        currentPage,\n        currentPageNumber,\n        selectedElementAnimations,\n        selectedElements,\n      },\n      actions: { updateElementsById },\n    }) => ({\n      backgroundElement: currentPage?.elements.find(\n        (element) => element.isBackground\n      ),\n      currentPageNumber,\n      selectedElementAnimations,\n      selectedElements,\n      updateElementsById,\n    })\n  );\n  const { undo } = useHistory(({ actions: { undo } }) => ({\n    undo,\n  }));\n  const { setHighlights } = useHighlights(({ setHighlights }) => ({\n    setHighlights,\n  }));\n\n  const { isInRecordingMode } = useMediaRecording(({ state }) => ({\n    isInRecordingMode: state.isInRecordingMode,\n  }));\n\n  const undoRef = useRef(undo);\n  undoRef.current = undo;\n\n  const selectedElement = selectedElements?.[0];\n\n  /**\n   * Prevent quick actions menu from removing focus from the canvas.\n   */\n  const handleMouseDown = useCallback((ev) => {\n    ev.stopPropagation();\n  }, []);\n\n  /**\n   * Highlights a panel in the editor. Triggers a tracking event\n   * using the selected element's type.\n   *\n   * The selected element and selected element type may be overridden\n   * using the `elementParams` arguments.\n   *\n   * @param {string} highlight The panel to highlight\n   * @param {Object} elementParams\n   * @param {string} elementParams.elementId The element id that is or will be selected in the canvas.\n   * @param {string} elementParams.elementType The type of the element that is or will be selected in the canvas.\n   * @param {Event} ev The triggering event.\n   */\n  const handleFocusPanel = useCallback(\n    (highlight) => (elementId) => (ev) => {\n      ev.preventDefault();\n      setHighlights({\n        elementId: elementId || selectedElement?.id,\n        highlight,\n      });\n    },\n    [setHighlights, selectedElement]\n  );\n\n  const resetProperties = useMemo(\n    () => getResetProperties(selectedElement, selectedElementAnimations),\n    [selectedElement, selectedElementAnimations]\n  );\n\n  const handleFocusMediaPanel = useMemo(() => {\n    const resourceId = selectedElements?.[0]?.resource?.id?.toString() || '';\n    const is3PMedia = resourceId.startsWith('media/');\n    const panelToFocus = is3PMedia ? states.Media3p : states.Media;\n\n    return handleFocusPanel(panelToFocus);\n  }, [handleFocusPanel, selectedElements]);\n\n  const { handleFocusPageBackground } = useMemo(\n    () => ({\n      handleFocusPageBackground: handleFocusPanel(states.PageBackground),\n    }),\n    [handleFocusPanel]\n  );\n\n  const insertElement = useInsertElement();\n\n  const actionMenuProps = useMemo(\n    () => ({\n      // The <BaseTooltip> component will handle proper placement for RTL layout\n      tooltipPlacement: Placement.Right,\n      onMouseDown: handleMouseDown,\n    }),\n    [handleMouseDown]\n  );\n\n  const hasAudioAnywhere = useStory(\n    ({ state }) =>\n      state.story?.backgroundAudio ||\n      state.pages?.some((page) => {\n        return (\n          page.backgroundAudio ||\n          page.elements\n            .filter((element) => element.type === ElementType.Video)\n            .some((element) => !element.resource.isMuted)\n        );\n      })\n  );\n\n  const noElementSelectedActions = useMemo(() => {\n    const actions = [\n      {\n        Icon: Bucket,\n        label: ACTIONS.CHANGE_BACKGROUND_COLOR.text,\n        onClick: (evt) => {\n          handleFocusPageBackground(backgroundElement?.id)(evt);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.CHANGE_BACKGROUND_COLOR.trackingEventName,\n            element: 'none',\n          });\n        },\n        ...actionMenuProps,\n      },\n      {\n        Icon: Media,\n        label: ACTIONS.INSERT_BACKGROUND_MEDIA.text,\n        onClick: (evt) => {\n          handleFocusMediaPanel()(evt);\n\n          trackEvent('quick_action', {\n            name: ACTIONS.INSERT_BACKGROUND_MEDIA.trackingEventName,\n            element: 'none',\n          });\n        },\n        separator: 'top',\n        ...actionMenuProps,\n      },\n      {\n        Icon: LetterTPlus,\n        label: ACTIONS.INSERT_TEXT.text,\n        onClick: () => {\n          setHighlights({\n            highlight: states.StylePane,\n          });\n          insertElement('text', DEFAULT_PRESET);\n          trackEvent('quick_action', {\n            name: ACTIONS.INSERT_TEXT.trackingEventName,\n            element: 'none',\n          });\n        },\n        ...actionMenuProps,\n      },\n    ];\n\n    if (hasAudioAnywhere) {\n      actions.push({\n        Icon: AudioSticker,\n        label: ACTIONS.INSERT_AUDIO_STICKER.text,\n        onClick: () => {\n          insertElement('audioSticker', AUDIO_STICKER_DEFAULT_PRESET);\n        },\n        ...actionMenuProps,\n      });\n    }\n\n    return actions;\n  }, [\n    actionMenuProps,\n    backgroundElement,\n    handleFocusMediaPanel,\n    handleFocusPageBackground,\n    setHighlights,\n    insertElement,\n    hasAudioAnywhere,\n  ]);\n\n  const foregroundCommonActions = useForegroundActions({\n    actionProps: actionMenuProps,\n    selectedElement,\n    handleFocusPanel,\n    resetProperties,\n  });\n\n  const textActions = useTextActions({\n    selectedElement,\n    updater: updateElementsById,\n    commonActions: foregroundCommonActions,\n    actionProps: actionMenuProps,\n  });\n  const {\n    backgroundElementMediaActions,\n    foregroundImageActions,\n    mediaRecordingActions,\n    videoActions,\n  } = useMediaActions({\n    selectedElement,\n    handleFocusPanel,\n    resetProperties,\n    commonActions: foregroundCommonActions,\n  });\n\n  // Return special actions for media recording mode.\n  if (isInRecordingMode) {\n    return mediaRecordingActions;\n  }\n\n  // Hide menu if there are multiple elements selected\n  if (selectedElements.length > 1) {\n    return [];\n  }\n\n  const isBackgroundElementMedia = Boolean(\n    backgroundElement && backgroundElement?.resource\n  );\n\n  const noElementsSelected = selectedElements.length === 0;\n  const isBackgroundSelected = selectedElements?.[0]?.isBackground;\n\n  // Return the base state if:\n  //  1. no element is selected\n  //  2. or, the selected element is the background element and it's not media\n  if (\n    noElementsSelected ||\n    (isBackgroundSelected && !isBackgroundElementMedia)\n  ) {\n    return noElementSelectedActions;\n  }\n\n  // return background media actions if:\n  // 1. the background is selected\n  // 2. and, the background is media\n  if (isBackgroundSelected && isBackgroundElementMedia) {\n    return backgroundElementMediaActions;\n  }\n\n  // switch quick actions based on non-background element type\n  switch (selectedElements?.[0]?.type) {\n    case ElementType.Image:\n    case ElementType.Gif:\n      return foregroundImageActions;\n    case ElementType.Shape:\n    case ElementType.Sticker:\n      return foregroundCommonActions;\n    case ElementType.Text:\n      return textActions;\n    case ElementType.Video:\n      return videoActions;\n    default:\n      return [];\n  }\n};\n\nexport default useQuickActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/useTextActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useApplyTextAutoStyle from '../../utils/useApplyTextAutoStyle';\nimport { ACTIONS } from './constants';\n\nfunction useTextActions({\n  selectedElement,\n  updater,\n  commonActions,\n  actionProps,\n}) {\n  const applyTextAutoStyle = useApplyTextAutoStyle(\n    selectedElement,\n    (properties) =>\n      updater({\n        elementIds: [selectedElement?.id],\n        properties,\n      })\n  );\n  const textActions = useMemo(\n    () => [\n      {\n        Icon: Icons.ColorBucket,\n        label: ACTIONS.AUTO_STYLE_TEXT.text,\n        onClick: () => {\n          applyTextAutoStyle();\n          trackEvent('quick_action', {\n            name: ACTIONS.AUTO_STYLE_TEXT.trackingEventName,\n            element: 'text',\n          });\n        },\n        ...actionProps,\n      },\n      ...commonActions,\n    ],\n    [actionProps, applyTextAutoStyle, commonActions]\n  );\n  return textActions;\n}\n\nexport default useTextActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/utils/getResetProperties.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { RESET_PROPERTIES, RESET_DEFAULTS } from '../constants';\n\nfunction isBorderRadiusDefault(element) {\n  // text element presets have a different default border radius\n  if (element?.type === ELEMENT_TYPES.TEXT && element?.borderRadius) {\n    return (\n      element.borderRadius.locked &&\n      element.borderRadius.topLeft === RESET_DEFAULTS.TEXT_BORDER_RADIUS.topLeft\n    );\n  }\n  // Otherwise if borderRadius is not present or radius is 0 return false to show reset\n  return (\n    !element?.borderRadius ||\n    element.borderRadius === RESET_DEFAULTS.STANDARD_BORDER_RADIUS\n  );\n}\n/**\n * Determines which properties on an element are to be reset when\n * the \"clear\" action is selected from a quick action menu\n *\n * @param {Object} selectedElement element currently selected\n * @param {Array.<Object>} selectedElementAnimations array of animations currently applied to the selected element\n * @return {Array.<string>} array of properties to reset on element\n */\nconst getResetProperties = (\n  selectedElement,\n  selectedElementAnimations = []\n) => {\n  if (!selectedElement) {\n    return [];\n  }\n\n  const resetProperties = [];\n\n  if (selectedElement?.overlay) {\n    resetProperties.push(RESET_PROPERTIES.OVERLAY);\n  }\n  if (selectedElementAnimations?.length) {\n    resetProperties.push(RESET_PROPERTIES.ANIMATION);\n  }\n\n  if (\n    selectedElement?.opacity < 100 ||\n    !isBorderRadiusDefault(selectedElement) ||\n    selectedElement?.border\n  ) {\n    resetProperties.push(RESET_PROPERTIES.STYLES);\n  }\n  return resetProperties;\n};\n\nexport default getResetProperties;\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as getResetProperties } from './getResetProperties';\n"
  },
  {
    "path": "packages/story-editor/src/app/quickActions/utils/test/getResetProperties.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { RESET_PROPERTIES } from '../../constants';\nimport getResetProperties from '../getResetProperties';\n\ndescribe('getResetProperties', () => {\n  it.each`\n    selectedElement                                             | selectedElementAnimations       | result\n    ${{ overlay: '', id: '1234' }}                              | ${[]}                           | ${[]}\n    ${{ overlay: { type: 'linear' }, id: '1234' }}              | ${[]}                           | ${[RESET_PROPERTIES.OVERLAY]}\n    ${{ overlay: { type: 'linear' }, id: '1234' }}              | ${[{ type: 'effect-fade-in' }]} | ${[RESET_PROPERTIES.OVERLAY, RESET_PROPERTIES.ANIMATION]}\n    ${{ overlay: '', id: '1234' }}                              | ${[{ type: 'effect-fade-in' }]} | ${[RESET_PROPERTIES.ANIMATION]}\n    ${{ overlay: { type: 'linear' }, id: '1234', opacity: 60 }} | ${[{ type: 'effect-fade-in' }]} | ${[RESET_PROPERTIES.OVERLAY, RESET_PROPERTIES.ANIMATION, RESET_PROPERTIES.STYLES]}\n    ${{ opacity: 60 }}                                          | ${[]}                           | ${[RESET_PROPERTIES.STYLES]}\n  `(\n    'should return array with reset properties',\n    ({ selectedElement, selectedElementAnimations, result }) => {\n      const resetPropertiesArray = getResetProperties(\n        selectedElement,\n        selectedElementAnimations\n      );\n\n      expect(resetPropertiesArray).toStrictEqual(result);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  createShortcutAriaLabel,\n  Shortcut,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { __, _n } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\n\nexport const RIGHT_CLICK_MENU_LABELS = {\n  ADD_NEW_PAGE_AFTER: __('Add New Page After', 'web-stories'),\n  ADD_NEW_PAGE_BEFORE: __('Add New Page Before', 'web-stories'),\n  ADD_TO_COLOR_PRESETS: __('Add Color to “Saved Colors”', 'web-stories'),\n  ADD_TO_TEXT_PRESETS: __('Add Style to “Saved Styles”', 'web-stories'),\n  BRING_FORWARD: __('Bring Forward', 'web-stories'),\n  BRING_TO_FRONT: __('Bring to Front', 'web-stories'),\n  BROWSE_STOCK_IMAGES_AND_VIDEO: __(\n    'Browse Stock Images and Video',\n    'web-stories'\n  ),\n  BROWSE_PAGE_TEMPLATES: __('Browse Page Templates', 'web-stories'),\n  CLEAR_IMAGE_STYLES: __('Clear Image Styles', 'web-stories'),\n  CLEAR_SHAPE_STYLES: __('Clear Shape Styles', 'web-stories'),\n  CLEAR_VIDEO_STYLES: __('Clear Video Styles', 'web-stories'),\n  CHOOSE_IMAGE_OR_VIDEO: __('Choose Image or Video', 'web-stories'),\n  COPY_IMAGE_STYLES: __('Copy Image Styles', 'web-stories'),\n  COPY_SHAPE_STYLES: __('Copy Shape Styles', 'web-stories'),\n  COPY_VIDEO_STYLES: __('Copy Video Styles', 'web-stories'),\n  COPY_STYLES: __('Copy Style', 'web-stories'),\n  DELETE_PAGE: __('Delete Page', 'web-stories'),\n  DETACH_IMAGE_FROM_BACKGROUND: __(\n    'Detach Image From Background',\n    'web-stories'\n  ),\n  DETACH_VIDEO_FROM_BACKGROUND: __(\n    'Detach Video From Background',\n    'web-stories'\n  ),\n  DUPLICATE_PAGE: __('Duplicate Page', 'web-stories'),\n  DUPLICATE_ELEMENTS: (numElements = 1) =>\n    _n('Duplicate Element', 'Duplicate Elements', numElements, 'web-stories'),\n  GROUP_LAYERS: __('Group Layers', 'web-stories'),\n  UNGROUP_LAYERS: __('Ungroup Layers', 'web-stories'),\n  UNGROUP_LAYER: __('Remove from Group', 'web-stories'),\n  LOCK_UNLOCK: __('Lock/Unlock', 'web-stories'),\n  HIDE_SHOW: __('Hide/Show', 'web-stories'),\n  RENAME_LAYER: __('Rename Layer', 'web-stories'),\n  PASTE_IMAGE_STYLES: __('Paste Image Styles', 'web-stories'),\n  PASTE_SHAPE_STYLES: __('Paste Shape Styles', 'web-stories'),\n  PASTE_VIDEO_STYLES: __('Paste Video Styles', 'web-stories'),\n  PASTE_STYLES: __('Paste Style', 'web-stories'),\n  SCALE_AND_CROP_BACKGROUND_IMAGE: __(\n    'Scale & Crop Background Image',\n    'web-stories'\n  ),\n  SCALE_AND_CROP_BACKGROUND_VIDEO: __(\n    'Scale & Crop Background Video',\n    'web-stories'\n  ),\n  SCALE_AND_CROP_IMAGE: __('Scale & Crop Image', 'web-stories'),\n  SCALE_AND_CROP_VIDEO: __('Scale & Crop Video', 'web-stories'),\n  CROP_OFF_SCREEN_VIDEO: __('Crop Off-Screen Video', 'web-stories'),\n  SEND_BACKWARD: __('Send Backward', 'web-stories'),\n  SEND_TO_BACK: __('Send to Back', 'web-stories'),\n  SET_AS_PAGE_BACKGROUND: __('Set as Page Background', 'web-stories'),\n  TRIM_VIDEO: __('Trim Video', 'web-stories'),\n  UPLOAD_IMAGE_OR_VIDEO: __('Upload Image or Video', 'web-stories'),\n  USE_SHAPE_AS_MASK: __('Use Shape as a Mask', 'web-stories'),\n  REMOVE_MASK: __('Unmask', 'web-stories'),\n  RECORD_VIDEO: __('Record Video', 'web-stories'),\n  HEADING_LEVEL: __('Heading Level', 'web-stories'),\n};\n\nconst StyledKbd = styled(Text.Kbd).attrs({\n  size: TextSize.Small,\n})`\n  color: inherit;\n\n  :not(:last-child) {\n    margin-right: 4px;\n  }\n`;\n\nexport const RIGHT_CLICK_MENU_SHORTCUTS = {\n  SEND_BACKWARD: {\n    display: <Shortcut shortcut=\"mod down\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('mod down'),\n  },\n  SEND_TO_BACK: {\n    display: <Shortcut shortcut=\"mod shift down\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('mod shift down'),\n  },\n  BRING_FORWARD: {\n    display: <Shortcut shortcut=\"mod up\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('mod up'),\n  },\n  BRING_TO_FRONT: {\n    display: <Shortcut shortcut=\"mod shift up\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('mod shift up'),\n  },\n  DELETE: {\n    display: <Shortcut shortcut=\"delete\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('delete'),\n  },\n  COPY_STYLES: {\n    display: <Shortcut shortcut=\"alt mod O\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('alt mod O'),\n  },\n  PASTE_STYLES: {\n    display: <Shortcut shortcut=\"alt mod P\" component={StyledKbd} />,\n    title: createShortcutAriaLabel('alt mod P'),\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/context.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { prettifyShortcut } from '@googleforcreators/design-system';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\nexport const UNDO_HELP_TEXT = sprintf(\n  /* translators: %s: Ctrl/Cmd + Z keyboard shortcut */\n  __('Press %s to undo the last change', 'web-stories'),\n  prettifyShortcut('mod+z')\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useCopyPasteActions } from './useCopyPasteActions';\nexport { default as useElementActions } from './useElementActions';\nexport { default as useLayerActions } from './useLayerActions';\nexport { default as usePageActions } from './usePageActions';\nexport { default as usePresetActions } from './usePresetActions';\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/testUtils.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ELEMENT = {\n  opacity: 100,\n  flip: {\n    vertical: false,\n    horizontal: false,\n  },\n  rotationAngle: 0,\n  lockAspectRatio: true,\n  scale: 100,\n  focalX: 50,\n  focalY: 50,\n  resource: {\n    baseColor: '#304844',\n    blurHash: 'UIG9W]0K59wH.Ttl9Fj]0NxaMc%g-qIoV?xu',\n    type: 'image',\n    mimeType: 'image/jpeg',\n    creationDate: '2022-01-20T20:39:12',\n    src: 'http://localhost:8899/wp-content/uploads/2022/01/example-2-6.jpg',\n    width: 1920,\n    height: 1280,\n    id: 1244,\n    alt: '',\n    sizes: {\n      medium: {\n        file: 'example-2-6-300x200.jpg',\n        width: 300,\n        height: 200,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-300x200.jpg',\n      },\n      large: {\n        file: 'example-2-6-1024x683.jpg',\n        width: 1024,\n        height: 683,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-1024x683.jpg',\n      },\n      thumbnail: {\n        file: 'example-2-6-150x150.jpg',\n        width: 150,\n        height: 150,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-150x150.jpg',\n      },\n      medium_large: {\n        file: 'example-2-6-768x512.jpg',\n        width: 768,\n        height: 512,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-768x512.jpg',\n      },\n      '1536x1536': {\n        file: 'example-2-6-1536x1024.jpg',\n        width: 1536,\n        height: 1024,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-1536x1024.jpg',\n      },\n      'post-thumbnail': {\n        file: 'example-2-6-1200x800.jpg',\n        width: 1200,\n        height: 800,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-1200x800.jpg',\n      },\n      'web-stories-poster-portrait': {\n        file: 'example-2-6-640x853.jpg',\n        width: 640,\n        height: 853,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-640x853.jpg',\n      },\n      'web-stories-publisher-logo': {\n        file: 'example-2-6-96x96.jpg',\n        width: 96,\n        height: 96,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-96x96.jpg',\n      },\n      'web-stories-thumbnail': {\n        file: 'example-2-6-150x100.jpg',\n        width: 150,\n        height: 100,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6-150x100.jpg',\n      },\n      full: {\n        file: 'example-2-6.jpg',\n        width: 1920,\n        height: 1280,\n        mimeType: 'image/jpeg',\n        sourceUrl:\n          'http://localhost:8899/wp-content/uploads/2022/01/example-2-6.jpg',\n      },\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n    needsProxy: false,\n  },\n  type: 'image',\n  x: 61,\n  y: 96,\n  width: 330,\n  height: 220,\n  mask: {\n    type: 'rectangle',\n    showInLibrary: true,\n    name: 'Rectangle',\n    path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n    ratio: 1,\n    supportsBorder: true,\n  },\n  id: 'selected-element-id',\n  overlay: {\n    type: 'linear',\n    rotation: 0,\n    stops: [\n      {\n        color: {\n          r: 0,\n          g: 0,\n          b: 0,\n          a: 0,\n        },\n        position: 0,\n      },\n      {\n        color: {\n          r: 0,\n          g: 0,\n          b: 0,\n          a: 1,\n        },\n        position: 1,\n      },\n    ],\n    alpha: 0.7,\n  },\n  border: {\n    left: 20,\n    right: 20,\n    top: 20,\n    bottom: 20,\n    lockedWidth: true,\n    color: {\n      color: {\n        r: 199,\n        g: 125,\n        b: 255,\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/useCopyPasteActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport { useCopyPasteActions } from '..';\nimport objectPick from '../../../../utils/objectPick';\nimport { useStory } from '../../..';\nimport { ATTRIBUTES_TO_COPY } from '../../../story/useStoryReducer/reducers/copySelectedElement';\nimport { ELEMENT } from './testUtils';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn(),\n}));\njest.mock('@googleforcreators/tracking'); // should be mocked in the testing env.\njest.mock('../../../story/useStory');\n\nconst mockUseStory = useStory;\nconst mockUseSnackbar = useSnackbar;\n\nconst mockCopySelectedElement = jest.fn();\nconst mockShowSnackbar = jest.fn();\nconst mockAddAnimations = jest.fn();\nconst mockUpdateSelectedElements = jest.fn();\n\nconst ANIMATION = {\n  targets: [ELEMENT.id],\n  id: 'element-animation',\n  type: 'effect-pulse',\n  scale: 0.5,\n  iterations: 1,\n  duration: 1450,\n  delay: 0,\n};\n\nconst defaultStoryActions = {\n  addAnimations: mockAddAnimations,\n  copySelectedElement: mockCopySelectedElement,\n  updateSelectedElements: mockUpdateSelectedElements,\n};\n\nconst defaultStoryState = {\n  selectedElement: ELEMENT,\n  selectedElementAnimations: [ANIMATION],\n  // needed for `useRichTextFormatting`\n  selectedElements: [ELEMENT],\n};\n\ndescribe('useCopyPasteActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockImplementation((selector = (v) => v) =>\n      selector({ state: defaultStoryState, actions: defaultStoryActions })\n    );\n    mockUseSnackbar.mockReturnValue(mockShowSnackbar);\n  });\n\n  it('should copy styles and show a confirmation snackbar', () => {\n    const { result } = renderHook(() => useCopyPasteActions());\n\n    expect(result.current.copiedElementType).toBeUndefined();\n\n    result.current.handleCopyStyles();\n\n    expect(mockCopySelectedElement).toHaveBeenCalledWith();\n\n    expect(mockShowSnackbar).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'Copied style.',\n        actionLabel: 'Undo',\n      })\n    );\n  });\n\n  it('should paste styles and show a confirmation snackbar', () => {\n    const styles = objectPick(ELEMENT, ATTRIBUTES_TO_COPY);\n    // Set copied element in state\n    mockUseStory.mockImplementation((selector) =>\n      selector({\n        actions: defaultStoryActions,\n        state: {\n          ...defaultStoryState,\n          copiedElementState: {\n            type: ELEMENT.type,\n            animations: [ANIMATION],\n            styles,\n          },\n          selectedElement: { id: 'new-element', type: 'image' },\n          selectedElementAnimations: [\n            { id: 'other-animation', targets: ['new-element'] },\n          ],\n          // needed for `useRichTextFormatting`\n          selectedElements: [{ id: 'new-element', type: 'image' }],\n        },\n      })\n    );\n\n    const { result } = renderHook(() => useCopyPasteActions());\n\n    // paste element\n    result.current.handlePasteStyles();\n\n    // Pasting styles is a multiple step process\n    // 1. Update styles on element in story\n    // 2. Delete existing animation on target element\n    // 3. Add new animations\n\n    expect(mockUpdateSelectedElements).toHaveBeenCalledWith({\n      properties: expect.any(Function),\n    });\n\n    // Need to call updater fn that is passed to `updateElementById`\n    // to see what is being updated.\n    const updatedStyles =\n      mockUpdateSelectedElements.mock.calls[0][0].properties();\n\n    // verify old animation deleted\n    // verify styles copied\n    expect(updatedStyles).toStrictEqual({\n      ...styles,\n      animation: {\n        id: 'other-animation',\n        targets: ['new-element'],\n        delete: true,\n      },\n    });\n\n    // verify new animation added\n    expect(mockAddAnimations).toHaveBeenCalledWith({\n      animations: [\n        {\n          ...ANIMATION,\n          id: expect.any(String),\n          targets: ['new-element'],\n        },\n      ],\n    });\n\n    // verify snackbar showing\n    expect(mockShowSnackbar).toHaveBeenCalledWith(\n      expect.objectContaining({\n        message: 'Pasted style.',\n        actionLabel: 'Undo',\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/useElementActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport { useElementActions } from '..';\nimport { useCanvas, useStory } from '../../..';\nimport { ELEMENT } from './testUtils';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn(),\n}));\njest.mock('@googleforcreators/tracking'); // should be mocked in the testing env.\njest.mock('../../../story/useStory');\njest.mock('../../../canvas/useCanvas');\n\nconst mockUseCanvas = useCanvas;\nconst mockUseStory = useStory;\nconst mockUseSnackbar = useSnackbar;\n\nconst mockShowSnackbar = jest.fn();\nconst mockClearBackgroundElement = jest.fn();\nconst mockDuplicateElementsById = jest.fn();\nconst mockSetBackgroundElement = jest.fn();\nconst mockUpdateElementsById = jest.fn();\nconst mockSetEditingElement = jest.fn();\n\nconst defaultStoryContext = {\n  selectedElements: [ELEMENT],\n  clearBackgroundElement: mockClearBackgroundElement,\n  duplicateElementsById: mockDuplicateElementsById,\n  setBackgroundElement: mockSetBackgroundElement,\n  updateElementsById: mockUpdateElementsById,\n};\n\ndescribe('useElementActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockReturnValue(defaultStoryContext);\n    mockUseCanvas.mockReturnValue(mockSetEditingElement);\n    mockUseSnackbar.mockReturnValue(mockShowSnackbar);\n  });\n\n  describe('element duplication', () => {\n    it('should not duplicate anything if no elements are selected', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleDuplicateSelectedElements();\n\n      expect(mockDuplicateElementsById).not.toHaveBeenCalled();\n    });\n    it('should duplicate the selected element', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleDuplicateSelectedElements();\n\n      expect(mockDuplicateElementsById).toHaveBeenCalledWith({\n        elementIds: [ELEMENT.id],\n      });\n    });\n\n    it('should duplicate the selected elements', () => {\n      // need multiple selected elements\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [{ id: '1' }, { id: 'potato' }, { id: '3' }],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleDuplicateSelectedElements();\n\n      expect(mockDuplicateElementsById).toHaveBeenCalledWith({\n        elementIds: ['1', 'potato', '3'],\n      });\n    });\n\n    it('should show a snackbar', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleDuplicateSelectedElements();\n\n      expect(mockShowSnackbar).toHaveBeenCalledWith(\n        expect.objectContaining({\n          actionLabel: 'Undo',\n          message: 'Duplicated elements.',\n        })\n      );\n    });\n  });\n\n  describe('scale and crop', () => {\n    it('should not set the editing element if there is no selected element', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleOpenScaleAndCrop();\n\n      expect(mockSetEditingElement).not.toHaveBeenCalled();\n    });\n\n    it('should set the editing element', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleOpenScaleAndCrop({ type: 'event' });\n\n      expect(mockSetEditingElement).toHaveBeenCalledWith(ELEMENT.id, {\n        type: 'event',\n      });\n    });\n  });\n\n  describe('set page background', () => {\n    it('should not set the page background if no element is selected', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleSetPageBackground();\n\n      expect(mockSetBackgroundElement).not.toHaveBeenCalled();\n    });\n\n    it('should not set the page background if background element is selected', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [{ isBackground: true }],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleSetPageBackground();\n\n      expect(mockSetBackgroundElement).not.toHaveBeenCalled();\n    });\n\n    it('should set the page background', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleSetPageBackground();\n\n      expect(mockSetBackgroundElement).toHaveBeenCalledWith({\n        elementId: ELEMENT.id,\n      });\n    });\n\n    it('should show a snackbar', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleSetPageBackground();\n\n      expect(mockShowSnackbar).toHaveBeenCalledWith(\n        expect.objectContaining({\n          actionLabel: 'Undo',\n          message: 'Set page background.',\n        })\n      );\n    });\n  });\n\n  describe('remove page background', () => {\n    beforeEach(() => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [{ ...ELEMENT, isBackground: true }],\n      });\n    });\n\n    it('should not remove the page background if no element is selected', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleRemovePageBackground();\n\n      expect(mockClearBackgroundElement).not.toHaveBeenCalled();\n    });\n\n    it('should not set the page background if non-background element is selected', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        selectedElements: [{ isBackground: false }],\n      });\n\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleRemovePageBackground();\n\n      expect(mockClearBackgroundElement).not.toHaveBeenCalled();\n    });\n\n    it('should set the page background', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleRemovePageBackground();\n\n      expect(mockUpdateElementsById).toHaveBeenCalledWith({\n        elementIds: [ELEMENT.id],\n        properties: expect.any(Function),\n      });\n\n      // Removing the background removes background-specific styles (overlay)\n      // also resets the opacity\n\n      // Need to call updater fn that is passed to `updateElementById`\n      // to see what is being updated.\n      const updatedStyles =\n        mockUpdateElementsById.mock.calls[0][0].properties();\n      expect(updatedStyles).toStrictEqual({\n        overlay: null,\n        opacity: 100,\n        isBackground: false,\n      });\n\n      expect(mockClearBackgroundElement).toHaveBeenCalledOnce();\n    });\n\n    it('should show a snackbar', () => {\n      const { result } = renderHook(() => useElementActions());\n\n      result.current.handleRemovePageBackground();\n\n      expect(mockShowSnackbar).toHaveBeenCalledWith(\n        expect.objectContaining({\n          actionLabel: 'Undo',\n          message: 'Removed page background.',\n        })\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/useLayerActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport { useLayerActions } from '..';\nimport { useStory } from '../../..';\nimport { ELEMENT } from './testUtils';\n\njest.mock('@googleforcreators/tracking'); // should be mocked in the testing env.\njest.mock('../../../story/useStory');\n\nconst mockUseStory = useStory;\n\nconst mockArrangeElement = jest.fn();\n\nconst defaultStoryContext = {\n  arrangeElement: mockArrangeElement,\n  elements: [\n    { id: 'background-layer', isBackground: true },\n    { id: 'bottom-layer' },\n    { id: 'middle-bottom-layer' },\n    ELEMENT,\n    { id: 'middle-top-layer' },\n    { id: 'top-layer' },\n  ],\n  selectedElement: ELEMENT,\n};\n\ndescribe('useLayerActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockReturnValue(defaultStoryContext);\n  });\n\n  it('should not move the background layer', () => {\n    mockUseStory.mockReturnValue({\n      ...defaultStoryContext,\n      selectedElement: { id: 'background-layer', isBackground: true },\n    });\n    const { result } = renderHook(() => useLayerActions());\n\n    expect(result.current.canElementMoveForwards).toBeFalse();\n    expect(result.current.canElementMoveBackwards).toBeFalse();\n\n    result.current.handleSendBackward();\n    result.current.handleSendToBack();\n    result.current.handleBringForward();\n    result.current.handleBringToFront();\n\n    expect(mockArrangeElement).not.toHaveBeenCalled();\n  });\n\n  it('should not be movable if the selected element is the only layer', () => {\n    mockUseStory.mockReturnValue({\n      ...defaultStoryContext,\n      elements: [{ id: 'background-layer', isBackground: true }, ELEMENT],\n    });\n\n    const { result } = renderHook(() => useLayerActions());\n\n    result.current.handleSendBackward();\n\n    expect(result.current.canElementMoveBackwards).toBeFalse();\n    expect(result.current.canElementMoveForwards).toBeFalse();\n  });\n\n  describe('moving backwards', () => {\n    it('should move the selected layer backwards', () => {\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleSendBackward();\n\n      expect(mockArrangeElement).toHaveBeenCalledWith({\n        elementId: ELEMENT.id,\n        position: 2,\n      });\n    });\n\n    it('should move the selected layer all the way back', () => {\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleSendToBack();\n\n      expect(mockArrangeElement).toHaveBeenCalledWith({\n        elementId: ELEMENT.id,\n        position: 1, // can't move past background\n      });\n    });\n\n    it('`canElementMoveBackwards` should be false it the selected element is all the way back', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        elements: [\n          { id: 'background-layer', isBackground: true },\n          ELEMENT,\n          { id: 'bottom-layer' },\n          { id: 'middle-bottom-layer' },\n          { id: 'middle-top-layer' },\n          { id: 'top-layer' },\n        ],\n      });\n\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleSendBackward();\n\n      expect(result.current.canElementMoveBackwards).toBeFalse();\n    });\n  });\n\n  describe('moving forwards', () => {\n    it('should move the selected layer forwards', () => {\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleBringForward();\n\n      expect(mockArrangeElement).toHaveBeenCalledWith({\n        elementId: ELEMENT.id,\n        position: 4,\n      });\n    });\n\n    it('should move the selected layer all the way forward', () => {\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleBringToFront();\n\n      expect(mockArrangeElement).toHaveBeenCalledWith({\n        elementId: ELEMENT.id,\n        position: 5,\n      });\n    });\n\n    it('`canElementMoveForwards` should be false it the selected element is all the way forward', () => {\n      mockUseStory.mockReturnValue({\n        ...defaultStoryContext,\n        elements: [\n          { id: 'background-layer', isBackground: true },\n          { id: 'bottom-layer' },\n          { id: 'middle-bottom-layer' },\n          { id: 'middle-top-layer' },\n          { id: 'top-layer' },\n          ELEMENT,\n        ],\n      });\n\n      const { result } = renderHook(() => useLayerActions());\n\n      result.current.handleSendBackward();\n\n      expect(result.current.canElementMoveForwards).toBeFalse();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/usePageActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { createPage, duplicatePage } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { usePageActions } from '..';\nimport { useStory } from '../../..';\nimport { ELEMENT } from './testUtils';\n\njest.mock('@googleforcreators/tracking'); // should be mocked in the testing env.\njest.mock('@googleforcreators/elements');\njest.mock('../../../story/useStory');\n\nconst mockUseStory = useStory;\n\nconst mockAddPageAt = jest.fn();\nconst mockDeleteCurrentPage = jest.fn();\nconst mockCreatePage = createPage;\nconst mockDuplicatePage = duplicatePage;\n\nconst defaultStoryContext = {\n  addPageAt: mockAddPageAt,\n  currentPage: {\n    id: 'current-page',\n    elements: [ELEMENT],\n  },\n  deleteCurrentPage: mockDeleteCurrentPage,\n  isSelectedElementBackground: false,\n  pageLength: 10,\n  selectedElementType: ELEMENT.type,\n};\n\ndescribe('usePageActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockReturnValue(defaultStoryContext);\n    mockCreatePage.mockReturnValue({ id: 'new-page', elements: [] });\n    mockDuplicatePage.mockImplementation((page) => ({\n      ...page,\n      id: 'duplicated-page',\n    }));\n  });\n\n  describe('add page at position', () => {\n    it('should add a page at a specific position', () => {\n      const { result } = renderHook(() => usePageActions());\n\n      result.current.handleAddPageAtPosition(4);\n\n      expect(mockAddPageAt).toHaveBeenCalledWith({\n        page: { id: 'new-page', elements: [] },\n        position: 4,\n      });\n    });\n\n    it('should add a position at the end if there are less pages than specified', () => {\n      const { result } = renderHook(() => usePageActions());\n\n      result.current.handleAddPageAtPosition(10000);\n\n      expect(mockAddPageAt).toHaveBeenCalledWith({\n        page: { id: 'new-page', elements: [] },\n        position: 9,\n      });\n    });\n\n    it('should add a position at the start if a negative number is specified', () => {\n      const { result } = renderHook(() => usePageActions());\n\n      result.current.handleAddPageAtPosition(-1);\n\n      expect(mockAddPageAt).toHaveBeenCalledWith({\n        page: expect.any(Object),\n        position: 0,\n      });\n    });\n  });\n\n  describe('duplicate page', () => {\n    it('should duplicate the current page and put it at the end of all existing pages', () => {\n      const { result } = renderHook(() => usePageActions());\n\n      result.current.handleDuplicatePage();\n\n      expect(mockDuplicatePage).toHaveBeenCalledWith({\n        id: 'current-page',\n        elements: [ELEMENT],\n      });\n      expect(mockAddPageAt).toHaveBeenCalledWith({\n        page: { id: 'duplicated-page', elements: [ELEMENT] },\n        position: null,\n      });\n    });\n  });\n\n  describe('delete page', () => {\n    it('should delete the current page', () => {\n      const { result } = renderHook(() => usePageActions());\n\n      result.current.handleDeletePage();\n\n      expect(mockDeleteCurrentPage).toHaveBeenCalledOnce();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/test/usePresetActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useAddPreset from '../../../../utils/useAddPreset';\nimport { useStory } from '../../..';\nimport { usePresetActions } from '..';\nimport { ELEMENT } from './testUtils';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn(),\n}));\njest.mock('@googleforcreators/tracking'); // should be mocked in the testing env.\njest.mock('../../../../utils/useAddPreset');\njest.mock('../../../../components/colorPicker/useDeleteColor', () => ({\n  __esModule: true,\n  default: jest.fn(() => ({ deleteGlobalPreset: jest.fn() })),\n}));\njest.mock('../../../../components/styleManager/useDeleteStyle');\njest.mock('../../../story/useStory');\n\nconst mockUseAddPreset = useAddPreset;\nconst mockUseStory = useStory;\nconst mockUseSnackbar = useSnackbar;\n\nconst mockAddGlobalPreset = jest.fn();\nconst mockShowSnackbar = jest.fn();\n\ndescribe('usePresetActions', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    mockUseStory.mockReturnValue(ELEMENT);\n    mockUseAddPreset.mockReturnValue({ addGlobalPreset: mockAddGlobalPreset });\n    mockUseSnackbar.mockReturnValue(mockShowSnackbar);\n  });\n\n  it('should add a text preset and show a confirmation snackbar', () => {\n    const { result } = renderHook(() => usePresetActions());\n\n    result.current.handleAddTextPreset();\n\n    expect(mockAddGlobalPreset).toHaveBeenCalledOnce();\n\n    expect(mockShowSnackbar).toHaveBeenCalledWith(\n      expect.objectContaining({\n        actionLabel: 'Undo',\n        message: 'Saved style to \"Saved Styles\".',\n      })\n    );\n  });\n\n  it('should add a color preset and show a confirmation snackbar', () => {\n    const { result } = renderHook(() => usePresetActions());\n\n    result.current.handleAddColorPreset(4);\n\n    expect(mockAddGlobalPreset).toHaveBeenCalledOnce();\n\n    expect(mockShowSnackbar).toHaveBeenCalledWith(\n      expect.objectContaining({\n        actionLabel: 'Undo',\n        message: 'Added color to \"Saved Colors\".',\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/useCopyPasteActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport { PRESET_TYPES } from '../../../constants';\nimport updateProperties from '../../../components/style/updateProperties';\nimport useApplyStyle from '../../../components/styleManager/useApplyStyle';\nimport getUpdatedSizeAndPosition from '../../../utils/getUpdatedSizeAndPosition';\nimport { getTextPresets } from '../../../utils/presetUtils';\nimport { useHistory, useStory } from '../..';\nimport { UNDO_HELP_TEXT } from './constants';\n\nfunction getTextElementStyles(element, animation) {\n  const { textStyles } = getTextPresets(\n    [element.styles],\n    {\n      textStyles: [],\n      colors: [],\n    },\n    PRESET_TYPES.STYLE\n  );\n  const { colors } = getTextPresets(\n    [element.styles],\n    {\n      textStyles: [],\n      colors: [],\n    },\n    PRESET_TYPES.COLOR\n  );\n  const { content, ...copiedElementStyles } = element.styles;\n  return {\n    ...copiedElementStyles,\n    ...textStyles[0],\n    ...colors[0].color,\n    animation,\n    border: copiedElementStyles.border || null,\n  };\n}\n\n/**\n * Creates the right click menu copy/paste actions.\n *\n * @return {Object} Right click menu copy/paste actions\n */\nconst useCopyPasteActions = () => {\n  const undo = useHistory(({ actions }) => actions.undo);\n  const {\n    addAnimations,\n    copySelectedElement,\n    copiedElementState,\n    selectedElement,\n    selectedElementType,\n    selectedElementAnimations,\n    updateSelectedElements,\n    isSelectedElementBackground,\n  } = useStory(({ state, actions }) => ({\n    addAnimations: actions.addAnimations,\n    copiedElementState: state.copiedElementState,\n    copySelectedElement: actions.copySelectedElement,\n    selectedElement: state.selectedElements?.[0],\n    selectedElementType: state.selectedElements?.[0]?.type,\n    isSelectedElementBackground: state.selectedElements?.[0]?.isBackground,\n    selectedElementAnimations: state.selectedElementAnimations,\n    updateSelectedElements: actions.updateSelectedElements,\n  }));\n\n  const showSnackbar = useSnackbar((value) => value.showSnackbar);\n\n  // Needed to not pass stale refs of `undo` to snackbar\n  const undoRef = useRef(undo);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  undoRef.current = undo;\n\n  /**\n   * Copy the styles and animations of the selected element.\n   */\n  const handleCopyStyles = useCallback(() => {\n    copySelectedElement();\n\n    showSnackbar({\n      actionLabel: __('Undo', 'web-stories'),\n      dismissible: false,\n      message: __('Copied style.', 'web-stories'),\n      onAction: () => {\n        undoRef.current();\n\n        trackEvent('context_menu_action', {\n          name: 'undo_copy_styles',\n          element: selectedElementType,\n          isBackground: isSelectedElementBackground,\n        });\n      },\n      actionHelpText: UNDO_HELP_TEXT,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'copy_styles',\n      element: selectedElementType,\n      isBackground: isSelectedElementBackground,\n    });\n  }, [\n    copySelectedElement,\n    showSnackbar,\n    selectedElementType,\n    isSelectedElementBackground,\n  ]);\n\n  const pushUpdate = useCallback(\n    (update, commitValues) => {\n      updateSelectedElements({\n        properties: (element) => {\n          const updates = updateProperties(element, update, commitValues);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...element,\n            ...updates,\n          });\n          return {\n            ...updates,\n            ...sizeUpdates,\n          };\n        },\n      });\n    },\n    [updateSelectedElements]\n  );\n\n  const handleApplyStyle = useApplyStyle({ pushUpdate });\n\n  /**\n   * Update the selected element's styles and animations.\n   *\n   * Pasting is not allowed if the copied element styles are from a\n   * different element type.\n   */\n  const handlePasteStyles = useCallback(() => {\n    const id = selectedElement?.id;\n\n    if (!id || selectedElementType !== copiedElementState.type) {\n      return;\n    }\n\n    // Delete old animation if one exists\n    const oldAnimationToDelete = selectedElementAnimations.length\n      ? { ...selectedElementAnimations[0], delete: true }\n      : undefined;\n\n    // Create new animations\n    const newAnimations = copiedElementState.animations.map((animation) => ({\n      ...animation,\n      id: uuidv4(),\n      targets: [selectedElement.id],\n    }));\n\n    addAnimations({ animations: newAnimations });\n\n    // Text elements need the text styles extracted from content before\n    // applying to the other text\n    if (\n      copiedElementState.type === 'text' &&\n      copiedElementState.styles.content\n    ) {\n      const updatedElementStyles = getTextElementStyles(\n        copiedElementState,\n        oldAnimationToDelete\n      );\n      handleApplyStyle(updatedElementStyles);\n    } else {\n      // Add styles and animations to element\n      updateSelectedElements({\n        properties: (currentProperties) =>\n          updateProperties(\n            currentProperties,\n            {\n              ...copiedElementState.styles,\n              animation: oldAnimationToDelete,\n            },\n            /* commitValues */ true\n          ),\n      });\n    }\n\n    showSnackbar({\n      actionLabel: __('Undo', 'web-stories'),\n      dismissible: false,\n      message: __('Pasted style.', 'web-stories'),\n      // don't pass a stale reference for undo\n      // need history updates to run so `undo` works correctly.\n      onAction: () => {\n        undoRef.current();\n\n        trackEvent('context_menu_action', {\n          name: 'undo_paste_styles',\n          element: selectedElementType,\n          isBackground: isSelectedElementBackground,\n        });\n      },\n      actionHelpText: UNDO_HELP_TEXT,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'paste_styles',\n      element: selectedElementType,\n      isBackground: isSelectedElementBackground,\n    });\n  }, [\n    addAnimations,\n    copiedElementState,\n    handleApplyStyle,\n    selectedElement,\n    selectedElementAnimations,\n    showSnackbar,\n    updateSelectedElements,\n    selectedElementType,\n    isSelectedElementBackground,\n  ]);\n\n  return {\n    copiedElementType: copiedElementState?.type,\n    handleCopyStyles,\n    handlePasteStyles,\n  };\n};\n\nexport default useCopyPasteActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/useElementActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useHistory, useStory } from '../..';\nimport updateProperties from '../../../components/style/updateProperties';\nimport generateGroupName from '../../../utils/generateGroupName';\nimport { UNDO_HELP_TEXT } from './constants';\n\n/**\n * Creates the right click menu element actions.\n *\n * @return {Object} Right click menu element actions\n */\nconst useElementActions = () => {\n  const {\n    clearBackgroundElement,\n    duplicateElementsById,\n    selectedElements,\n    setBackgroundElement,\n    updateElementsById,\n    deleteGroupById,\n    addGroup,\n    groups,\n    elements,\n    arrangeElement,\n  } = useStory(({ state, actions }) => ({\n    clearBackgroundElement: actions.clearBackgroundElement,\n    duplicateElementsById: actions.duplicateElementsById,\n    selectedElements: state.selectedElements,\n    setBackgroundElement: actions.setBackgroundElement,\n    updateElementsById: actions.updateElementsById,\n    addGroup: actions.addGroup,\n    deleteGroupById: actions.deleteGroupById,\n    groups: state.currentPage.groups,\n    elements: state.currentPage?.elements || [],\n    arrangeElement: actions.arrangeElement,\n  }));\n  const showSnackbar = useSnackbar((value) => value.showSnackbar);\n  const setEditingElement = useCanvas(\n    ({ actions }) => actions.setEditingElement\n  );\n  const undo = useHistory(({ actions }) => actions.undo);\n\n  // Needed to not pass stale refs of `undo` to snackbar\n  const undoRef = useRef(undo);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  undoRef.current = undo;\n\n  /**\n   * Duplicate all selected elements.\n   */\n  const handleDuplicateSelectedElements = useCallback(() => {\n    if (!selectedElements.length) {\n      return;\n    }\n\n    duplicateElementsById({\n      elementIds: selectedElements.map(({ id }) => id),\n    });\n\n    showSnackbar({\n      actionLabel: __('Undo', 'web-stories'),\n      dismissible: false,\n      message: __('Duplicated elements.', 'web-stories'),\n      // don't pass a stale reference for undo\n      // need history updates to run so `undo` works correctly.\n      onAction: () => {\n        undoRef.current();\n\n        trackEvent('context_menu_action', {\n          name: 'undo_duplicate_elements',\n          elements: selectedElements.map((element) => element.type),\n        });\n      },\n      actionHelpText: UNDO_HELP_TEXT,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'duplicate_elements',\n      elements: selectedElements.map((element) => element.type),\n    });\n  }, [duplicateElementsById, selectedElements, showSnackbar]);\n\n  const handleGroupSelectedElements = useCallback(() => {\n    if (!selectedElements.length) {\n      return;\n    }\n\n    const groupId = uuidv4();\n    const name = generateGroupName(groups);\n    addGroup({ groupId, name });\n    updateElementsById({\n      elementIds: selectedElements.map(({ id }) => id),\n      properties: (currentProperties) =>\n        updateProperties(\n          currentProperties,\n          {\n            groupId,\n          },\n          /* commitValues */ true\n        ),\n    });\n    // Fix the order\n    const elementFromGroupWithHighestPosition = Math.max(\n      ...selectedElements.map((el) =>\n        elements.findIndex(({ id }) => id === el?.id)\n      )\n    );\n    for (const [index, element] of selectedElements.reverse().entries()) {\n      const position = elements.findIndex(({ id }) => id === element?.id);\n      if (position !== elementFromGroupWithHighestPosition) {\n        const newPosition = elementFromGroupWithHighestPosition - index;\n        arrangeElement({\n          elementId: element.id,\n          position: newPosition,\n        });\n      }\n    }\n  }, [\n    selectedElements,\n    updateElementsById,\n    addGroup,\n    groups,\n    arrangeElement,\n    elements,\n  ]);\n\n  const handleUngroupSelectedElements = useCallback(() => {\n    if (!selectedElements.length) {\n      return;\n    }\n\n    // this will remove the group but keep the elements\n    deleteGroupById({ groupId: selectedElements[0]?.groupId });\n\n    updateElementsById({\n      elementIds: selectedElements.map(({ id }) => id),\n      properties: (currentProperties) =>\n        updateProperties(\n          currentProperties,\n          {\n            groupId: null,\n          },\n          /* commitValues */ true\n        ),\n    });\n  }, [selectedElements, updateElementsById, deleteGroupById]);\n\n  /**\n   * Set element as the element being 'edited'.\n   *\n   * @param {Event} evt The triggering event\n   */\n  const handleOpenScaleAndCrop = useCallback(\n    (evt) => {\n      const selectedElement = selectedElements?.[0];\n\n      if (selectedElement) {\n        setEditingElement(selectedElement.id, evt);\n\n        trackEvent('context_menu_action', {\n          name: 'open_scale_and_crop',\n          element: selectedElement.type,\n          isBackground: selectedElement.isBackground,\n        });\n      }\n    },\n    [selectedElements, setEditingElement]\n  );\n\n  /**\n   * Set currently selected element as the page's background.\n   */\n  const handleSetPageBackground = useCallback(() => {\n    const selectedElement = selectedElements?.[0];\n\n    if (selectedElement && !selectedElement.isBackground) {\n      setBackgroundElement({ elementId: selectedElement.id });\n\n      showSnackbar({\n        actionLabel: __('Undo', 'web-stories'),\n        dismissible: false,\n        message: __('Set page background.', 'web-stories'),\n        // don't pass a stale reference for undo\n        // need history updates to run so `undo` works correctly.\n        onAction: () => {\n          undoRef.current();\n\n          trackEvent('context_menu_action', {\n            name: 'undo_set_page_background',\n            element: selectedElement.type,\n            isBackground: selectedElement.isBackground,\n          });\n        },\n        actionHelpText: UNDO_HELP_TEXT,\n      });\n\n      trackEvent('context_menu_action', {\n        name: 'set_as_page_background',\n        element: selectedElement.type,\n        isBackground: selectedElement.isBackground,\n      });\n    }\n  }, [selectedElements, setBackgroundElement, showSnackbar]);\n\n  /**\n   * Remove media from background and clear opacity and overlay.\n   */\n  const handleRemovePageBackground = useCallback(() => {\n    const selectedElement = selectedElements?.[0];\n\n    if (selectedElement && selectedElement.isBackground) {\n      updateElementsById({\n        elementIds: [selectedElement.id],\n        properties: (currentProperties) =>\n          updateProperties(\n            currentProperties,\n            {\n              isBackground: false,\n              opacity: 100,\n              overlay: null,\n            },\n            /* commitValues */ true\n          ),\n      });\n\n      clearBackgroundElement();\n\n      showSnackbar({\n        actionLabel: __('Undo', 'web-stories'),\n        dismissible: false,\n        message: __('Removed page background.', 'web-stories'),\n        // don't pass a stale reference for undo\n        // need history updates to run so `undo` works correctly.\n        onAction: () => {\n          undoRef.current();\n\n          trackEvent('context_menu_action', {\n            name: 'undo_remove_page_background',\n            elements: selectedElement.type,\n            isBackground: selectedElement.isBackground,\n          });\n        },\n        actionHelpText: UNDO_HELP_TEXT,\n      });\n\n      trackEvent('context_menu_action', {\n        name: 'remove_media_from_background',\n        element: selectedElement.type,\n        isBackground: selectedElement.isBackground,\n      });\n    }\n  }, [\n    clearBackgroundElement,\n    selectedElements,\n    showSnackbar,\n    updateElementsById,\n  ]);\n\n  return {\n    handleDuplicateSelectedElements,\n    handleGroupSelectedElements,\n    handleUngroupSelectedElements,\n    handleOpenScaleAndCrop,\n    handleSetPageBackground,\n    handleRemovePageBackground,\n  };\n};\n\nexport default useElementActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/useHeadingSelect.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, useMemo, useState } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport { getTextElementTagNames } from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../story/useStory';\nimport { useConfig } from '../../config';\nimport { getCommonValue } from '../../../components/panels/shared';\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { HEADING_LEVELS } from '../../../constants';\n\nconst ReversedIcon = styled(Icons.ChevronRightSmall)`\n  transform: rotate(180deg);\n`;\n\nfunction useHeadingSelect({ menuItemProps, isMenuOpen }) {\n  const { isRTL } = useConfig();\n  const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n  const { textElements } = useStory(({ state }) => ({\n    textElements: state.currentPage?.elements?.filter(\n      ({ type }) => 'text' === type\n    ),\n  }));\n\n  const tagNamesMap = getTextElementTagNames(textElements);\n\n  const { selectedElements, updateSelectedElements } = useStory(\n    ({ state: { selectedElements }, actions: { updateSelectedElements } }) => ({\n      selectedElements,\n      updateSelectedElements,\n    })\n  );\n\n  const selectedElementsWithTagNames = selectedElements.map((element) => ({\n    ...element,\n    tagName: tagNamesMap.get(element.id),\n    defaultTagName: element.tagName || 'auto',\n  }));\n\n  const selectedTagName = getCommonValue(\n    selectedElementsWithTagNames,\n    'defaultTagName',\n    'auto'\n  );\n\n  const uniqueTagNames = [\n    ...new Set(\n      selectedElementsWithTagNames.map(({ tagName }) => tagName || 'auto')\n    ),\n  ];\n\n  const computedTagName = uniqueTagNames?.length ? uniqueTagNames[0] : 'auto';\n  const selectedValue = 'auto' === selectedTagName ? 'auto' : computedTagName;\n\n  useEffect(() => {\n    // Close submenu if the menu itself also closes.\n    if (!isMenuOpen) {\n      setIsSubMenuOpen(false);\n    }\n  }, [isMenuOpen]);\n\n  const subMenuItems = useMemo(() => {\n    if (!isMenuOpen || selectedElements.length === 0) {\n      return [];\n    }\n\n    const options = [\n      {\n        value: 'auto',\n        label:\n          'auto' === selectedValue && HEADING_LEVELS[computedTagName]\n            ? sprintf(\n                /* translators: %s: heading level. */\n                __('Automatic (%s)', 'web-stories'),\n                HEADING_LEVELS[computedTagName]\n              )\n            : __('Automatic', 'web-stories'),\n      },\n      { value: 'h1', label: HEADING_LEVELS.h1 },\n      { value: 'h2', label: HEADING_LEVELS.h2 },\n      { value: 'h3', label: HEADING_LEVELS.h3 },\n      { value: 'p', label: HEADING_LEVELS.p },\n    ];\n\n    return options.map((element) => {\n      const { value } = element;\n      return {\n        key: value,\n        supportsIcon: true,\n        icon: selectedValue === value ? <Icons.CheckmarkSmall /> : null,\n        label: <span>{element.label}</span>,\n        onClick: () => {\n          updateSelectedElements({\n            properties: (oldElement) => ({\n              ...oldElement,\n              tagName: value,\n            }),\n          });\n        },\n        ...menuItemProps,\n      };\n    });\n  }, [\n    isMenuOpen,\n    menuItemProps,\n    updateSelectedElements,\n    selectedValue,\n    selectedElements,\n    computedTagName,\n  ]);\n\n  // Only display if submenu has any items.\n  return subMenuItems.length > 0\n    ? {\n        label: RIGHT_CLICK_MENU_LABELS.HEADING_LEVEL,\n        openSubMenu: () => setIsSubMenuOpen(true),\n        closeSubMenu: () => setIsSubMenuOpen(false),\n        isHeadingSubMenuOpen: isSubMenuOpen,\n        headingSubMenuItems: isSubMenuOpen ? subMenuItems : [],\n        SuffixIcon: isRTL ? ReversedIcon : Icons.ChevronRightSmall,\n        ...menuItemProps,\n      }\n    : null;\n}\n\nexport default useHeadingSelect;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/useLayerActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../..';\nimport { useLocalMedia } from '../../media';\nimport { getCropParams } from '../../../utils/getCropParams';\n\n/**\n * Creates the right click menu layer actions.\n *\n * Exposes two booleans:\n * - `canElementMoveBackwards`\n * - `canElementMoveForwards`\n *\n * These define the ability of the element to move in the layers.\n *\n * @return {Object} Right click menu layer actions\n */\nconst useLayerActions = () => {\n  const { cropExistingVideo } = useLocalMedia(\n    ({ actions: { cropExistingVideo } }) => ({\n      cropExistingVideo,\n    })\n  );\n\n  const { arrangeElement, elements, selectedElement } = useStory(\n    ({ state, actions }) => ({\n      arrangeElement: actions.arrangeElement,\n      elements: state.currentPage?.elements || [],\n      selectedElement: state.selectedElements?.[0],\n    })\n  );\n\n  const elementPosition = elements.findIndex(\n    ({ id }) => id === selectedElement?.id\n  );\n\n  // Non background elements may change layers.\n  const canElementMoveBackwards =\n    selectedElement && !selectedElement.isBackground && elementPosition > 1;\n  const canElementMoveForwards =\n    selectedElement &&\n    !selectedElement.isBackground &&\n    elementPosition < elements.length - 1;\n\n  /**\n   * Send element one layer backwards, if possible.\n   */\n  const handleSendBackward = useCallback(() => {\n    if (!canElementMoveBackwards) {\n      return;\n    }\n\n    const backwardPositionSkipGroups = elements.findLastIndex(\n      (el, position) => position < elementPosition && !el.groupId\n    );\n    const newPosition =\n      elementPosition === 1 ? elementPosition : backwardPositionSkipGroups;\n\n    arrangeElement({\n      elementId: selectedElement.id,\n      position: newPosition,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'send_backward',\n      element: selectedElement.type,\n      isBackground: selectedElement.isBackground,\n    });\n  }, [\n    arrangeElement,\n    canElementMoveBackwards,\n    elementPosition,\n    selectedElement,\n    elements,\n  ]);\n\n  /**\n   * Send element all the way back, if possible.\n   */\n  const handleSendToBack = useCallback(() => {\n    if (!canElementMoveBackwards) {\n      return;\n    }\n\n    arrangeElement({\n      elementId: selectedElement.id,\n      position: 1,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'send_to_back',\n      element: selectedElement.type,\n    });\n  }, [arrangeElement, canElementMoveBackwards, selectedElement]);\n\n  /**\n   * Bring element one layer forwards, if possible.\n   */\n  const handleBringForward = useCallback(() => {\n    if (!canElementMoveForwards) {\n      return;\n    }\n\n    const forwardPositionSkipGroups = elements.findIndex(\n      (el, position) =>\n        (position > elementPosition && !el.groupId) ||\n        position === elements.length - 1\n    );\n    const newPosition =\n      elementPosition >= elements.length - 1\n        ? elementPosition\n        : forwardPositionSkipGroups;\n\n    arrangeElement({\n      elementId: selectedElement.id,\n      position: newPosition,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'bring_forward',\n      element: selectedElement.type,\n    });\n  }, [\n    arrangeElement,\n    canElementMoveForwards,\n    elementPosition,\n    elements,\n    selectedElement,\n  ]);\n\n  /**\n   * Send element all the way to the front, if possible.\n   */\n  const handleBringToFront = useCallback(() => {\n    if (!canElementMoveForwards) {\n      return;\n    }\n\n    arrangeElement({\n      elementId: selectedElement.id,\n      position: elements.length - 1,\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'bring_to_front',\n      element: selectedElement.type,\n    });\n  }, [arrangeElement, canElementMoveForwards, elements, selectedElement]);\n\n  /**\n   * Crop Video to remove off-canvas portion of the video.\n   */\n  const handleCropOffScreenVideo = useCallback(() => {\n    cropExistingVideo(selectedElement, getCropParams(selectedElement));\n  }, [selectedElement, cropExistingVideo]);\n\n  return {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleBringForward,\n    handleBringToFront,\n    handleSendBackward,\n    handleSendToBack,\n    handleCropOffScreenVideo,\n  };\n};\n\nexport default useLayerActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/usePageActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useCallback } from '@googleforcreators/react';\nimport { createPage, duplicatePage } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../..';\n\n/**\n * Creates the right click menu page actions.\n *\n * @return {Object} Right click menu page actions\n */\nconst usePageActions = () => {\n  const {\n    addPageAt,\n    currentPage,\n    deleteCurrentPage,\n    isSelectedElementBackground,\n    pageLength,\n    selectedElementType,\n  } = useStory(({ state, actions }) => ({\n    addPageAt: actions.addPageAt,\n    currentPage: state.currentPage,\n    deleteCurrentPage: actions.deleteCurrentPage,\n    isSelectedElementBackground:\n      state.selectedElements?.[0]?.background || false,\n    pageLength: state.pages?.length || 1,\n    selectedElementType: state.selectedElements?.[0]?.type || null,\n  }));\n\n  /**\n   * Adds a new page at the designated index.\n   *\n   * Defaults to adding the new page after all of the existing pages.\n   *\n   * @param {number} index The index\n   */\n  const handleAddPageAtPosition = useCallback(\n    (index) => {\n      let position = Boolean(index) || index === 0 ? index : pageLength - 1;\n      position = position > pageLength ? pageLength - 1 : position;\n      position = position < 0 ? 0 : position;\n\n      addPageAt({ page: createPage(), position });\n\n      trackEvent('context_menu_action', {\n        name: 'page_added',\n        element: selectedElementType,\n        isBackground: isSelectedElementBackground,\n      });\n    },\n    [addPageAt, isSelectedElementBackground, pageLength, selectedElementType]\n  );\n\n  /**\n   * Duplicate the current page.\n   */\n  const handleDuplicatePage = useCallback(() => {\n    addPageAt({ page: duplicatePage(currentPage), position: null });\n  }, [addPageAt, currentPage]);\n\n  /**\n   * Delete the current page.\n   */\n  const handleDeletePage = useCallback(() => {\n    deleteCurrentPage();\n\n    trackEvent('context_menu_action', {\n      name: 'page_deleted',\n      element: selectedElementType,\n      isBackground: isSelectedElementBackground,\n    });\n  }, [deleteCurrentPage, isSelectedElementBackground, selectedElementType]);\n\n  return {\n    handleAddPageAtPosition,\n    handleDuplicatePage,\n    handleDeletePage,\n  };\n};\n\nexport default usePageActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/hooks/usePresetActions.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { PRESET_TYPES } from '../../../constants';\nimport useDeleteColor from '../../../components/colorPicker/useDeleteColor';\nimport useDeleteStyle from '../../../components/styleManager/useDeleteStyle';\nimport useAddPreset from '../../../utils/useAddPreset';\nimport { noop } from '../../../utils/noop';\nimport { useStory } from '../..';\nimport { UNDO_HELP_TEXT } from './constants';\n\n/**\n * Creates the right click menu preset actions.\n *\n * @return {Object} Right click menu preset actions\n */\nconst usePresetActions = () => {\n  const { addGlobalPreset: addGlobalTextPreset } = useAddPreset({\n    presetType: PRESET_TYPES.STYLE,\n  });\n  const { addGlobalPreset: addGlobalColorPreset } = useAddPreset({\n    presetType: PRESET_TYPES.COLOR,\n  });\n  const deleteGlobalTextPreset = useDeleteStyle({\n    onEmpty: noop,\n  });\n  const { deleteGlobalColor: deleteGlobalColorPreset } = useDeleteColor({\n    onEmpty: noop,\n  });\n  const selectedElement = useStory(({ state }) => state.selectedElements?.[0]);\n\n  const showSnackbar = useSnackbar((value) => value.showSnackbar);\n\n  /**\n   * Add text styles to global presets.\n   *\n   * @param {Event} evt The triggering event\n   */\n  const handleAddTextPreset = useCallback(\n    (evt) => {\n      const preset = addGlobalTextPreset(evt);\n\n      showSnackbar({\n        actionLabel: __('Undo', 'web-stories'),\n        dismissible: false,\n        message: __('Saved style to \"Saved Styles\".', 'web-stories'),\n        onAction: () => {\n          deleteGlobalTextPreset(preset);\n\n          trackEvent('context_menu_action', {\n            name: 'remove_text_preset',\n            element: selectedElement?.type,\n          });\n        },\n        actionHelpText: UNDO_HELP_TEXT,\n      });\n\n      trackEvent('context_menu_action', {\n        name: 'add_text_preset',\n        element: selectedElement?.type,\n      });\n    },\n    [\n      addGlobalTextPreset,\n      deleteGlobalTextPreset,\n      selectedElement?.type,\n      showSnackbar,\n    ]\n  );\n\n  /**\n   * Add color to global presets.\n   *\n   * @param {Event} evt The triggering event\n   */\n  const handleAddColorPreset = useCallback(\n    (evt) => {\n      const preset = addGlobalColorPreset(evt);\n\n      showSnackbar({\n        actionLabel: __('Undo', 'web-stories'),\n        dismissible: false,\n        message: __('Added color to \"Saved Colors\".', 'web-stories'),\n        onAction: () => {\n          deleteGlobalColorPreset(preset);\n\n          trackEvent('context_menu_action', {\n            name: 'remove_color_preset',\n            element: selectedElement?.type,\n          });\n        },\n        actionHelpText: UNDO_HELP_TEXT,\n      });\n\n      trackEvent('context_menu_action', {\n        name: 'add_color_preset',\n        element: selectedElement?.type,\n      });\n    },\n    [\n      addGlobalColorPreset,\n      deleteGlobalColorPreset,\n      selectedElement?.type,\n      showSnackbar,\n    ]\n  );\n\n  return {\n    handleAddTextPreset,\n    handleAddColorPreset,\n  };\n};\n\nexport default usePresetActions;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useRightClickMenu } from './useRightClickMenu';\nexport { default as RightClickMenuProvider } from './provider';\nexport * from './menus';\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/items/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as LayerHide } from './layerHide';\nexport { default as LayerLock } from './layerLock';\nexport { default as LayerName } from './layerName';\nexport { default as LayerUngroup } from './layerUngroup';\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/items/layerHide.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useStory } from '../..';\n\nfunction LayerHide() {\n  const updateSelectedElements = useStory(\n    (ctx) => ctx.actions.updateSelectedElements\n  );\n  const toggleLayerHide = useCallback(\n    () =>\n      updateSelectedElements({\n        properties: (oldElement) => ({\n          ...oldElement,\n          isHidden: !oldElement.isHidden,\n        }),\n      }),\n    [updateSelectedElements]\n  );\n\n  return (\n    <ContextMenuComponents.MenuButton onClick={toggleLayerHide}>\n      {RIGHT_CLICK_MENU_LABELS.HIDE_SHOW}\n    </ContextMenuComponents.MenuButton>\n  );\n}\n\nexport default LayerHide;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/items/layerLock.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useStory } from '../..';\n\nfunction LayerLock() {\n  const updateSelectedElements = useStory(\n    (ctx) => ctx.actions.updateSelectedElements\n  );\n  const toggleLayerLock = useCallback(\n    () =>\n      updateSelectedElements({\n        properties: (oldElement) => ({\n          ...oldElement,\n          isLocked: !oldElement.isLocked,\n        }),\n      }),\n    [updateSelectedElements]\n  );\n\n  return (\n    <ContextMenuComponents.MenuButton onClick={toggleLayerLock}>\n      {RIGHT_CLICK_MENU_LABELS.LOCK_UNLOCK}\n    </ContextMenuComponents.MenuButton>\n  );\n}\n\nexport default LayerLock;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/items/layerName.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useCanvas, useStory } from '../..';\n\nfunction LayerName() {\n  const { selectedElementIds } = useStory(({ state }) => ({\n    selectedElementIds: state.selectedElementIds,\n  }));\n  const { setRenamableLayer } = useCanvas(({ state, actions }) => ({\n    setRenamableLayer: actions.setRenamableLayer,\n    renamableLayer: state.renamableLayer,\n  }));\n  const enableLayerNaming = useCallback(() => {\n    setRenamableLayer({\n      elementId: selectedElementIds[0],\n    });\n  }, [setRenamableLayer, selectedElementIds]);\n\n  return (\n    <>\n      <ContextMenuComponents.MenuSeparator />\n      <ContextMenuComponents.MenuButton onClick={enableLayerNaming}>\n        {RIGHT_CLICK_MENU_LABELS.RENAME_LAYER}\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\n\nexport default LayerName;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/items/layerUngroup.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useStory } from '../..';\n\nfunction LayerUngroup() {\n  const { selectedElements, removeElementFromGroup } = useStory(\n    ({ state, actions }) => ({\n      selectedElements: state.selectedElements,\n      removeElementFromGroup: actions.removeElementFromGroup,\n    })\n  );\n  const handleLayerUngroup = useCallback(() => {\n    removeElementFromGroup({\n      elementId: selectedElements[0].id,\n      groupId: selectedElements[0].groupId,\n    });\n  }, [selectedElements, removeElementFromGroup]);\n\n  const isLayerInGroup = selectedElements.some((el) => el.groupId);\n\n  if (!isLayerInGroup) {\n    return null;\n  }\n\n  return (\n    <ContextMenuComponents.MenuButton onClick={handleLayerUngroup}>\n      {RIGHT_CLICK_MENU_LABELS.UNGROUP_LAYER}\n    </ContextMenuComponents.MenuButton>\n  );\n}\n\nexport default LayerUngroup;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/emptyStateMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { states, useHighlights } from '../../highlights';\nimport { MediaUploadButton } from '../../../components/form';\nimport useOnMediaSelect from '../../../components/library/panes/media/local/useOnMediaSelect';\nimport LibraryProvider from '../../../components/library/libraryProvider';\nimport { useMediaRecording } from '../../../components/mediaRecording';\nimport useFFmpeg from '../../media/utils/useFFmpeg';\nimport { MenuPropType } from './shared';\n\nconst MediaButton = () => {\n  const { onSelect } = useOnMediaSelect();\n\n  return (\n    <MediaUploadButton\n      renderButton={(open) => (\n        <ContextMenuComponents.MenuButton onClick={open}>\n          {RIGHT_CLICK_MENU_LABELS.UPLOAD_IMAGE_OR_VIDEO}\n        </ContextMenuComponents.MenuButton>\n      )}\n      onInsert={onSelect}\n    />\n  );\n};\n\nfunction EmptyStateMenu() {\n  const { setHighlights } = useHighlights(({ setHighlights }) => ({\n    setHighlights,\n  }));\n  const { toggleRecordingMode } = useMediaRecording(({ actions }) => ({\n    toggleRecordingMode: actions.toggleRecordingMode,\n  }));\n  const { isTranscodingEnabled } = useFFmpeg();\n\n  return (\n    <>\n      <ContextMenuComponents.MenuButton\n        onClick={() => {\n          setHighlights({\n            highlight: states.Media,\n          });\n        }}\n      >\n        {RIGHT_CLICK_MENU_LABELS.CHOOSE_IMAGE_OR_VIDEO}\n      </ContextMenuComponents.MenuButton>\n      <LibraryProvider>\n        <MediaButton />\n      </LibraryProvider>\n      {/* `isTranscodingEnabled` already checks for `hasUploadMediaAction` */}\n      {isTranscodingEnabled && (\n        <ContextMenuComponents.MenuButton onClick={toggleRecordingMode}>\n          {RIGHT_CLICK_MENU_LABELS.RECORD_VIDEO}\n        </ContextMenuComponents.MenuButton>\n      )}\n      <ContextMenuComponents.MenuButton\n        onClick={() => {\n          setHighlights({\n            highlight: states.PageTemplates,\n          });\n        }}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BROWSE_PAGE_TEMPLATES}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        onClick={() => {\n          setHighlights({\n            highlight: states.Media3p,\n          });\n        }}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BROWSE_STOCK_IMAGES_AND_VIDEO}\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\nEmptyStateMenu.propTypes = MenuPropType;\n\nexport default EmptyStateMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/foregroundMediaMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef, useMemo } from '@googleforcreators/react';\nimport { useFeature } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport {\n  RIGHT_CLICK_MENU_LABELS,\n  RIGHT_CLICK_MENU_SHORTCUTS,\n} from '../constants';\nimport {\n  useCopyPasteActions,\n  useElementActions,\n  useLayerActions,\n} from '../hooks';\nimport useShapeMask from '../../../utils/useShapeMask';\nimport { useStory, useLocalMedia } from '../..';\nimport useVideoTrim from '../../../components/videoTrim/useVideoTrim';\nimport useRightClickMenu from '../useRightClickMenu';\nimport useLayerSelect from '../useLayerSelect';\nimport { LayerHide, LayerLock, LayerName, LayerUngroup } from '../items';\nimport { isOffCanvas } from '../../../utils/isOffCanvas';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction ForegroundMediaMenu({ parentMenuRef }) {\n  const { copiedElementType, selectedElement } = useStory(({ state }) => ({\n    copiedElementType: state.copiedElementState.type,\n    selectedElement: state.selectedElements?.[0],\n  }));\n  const { handleCopyStyles, handlePasteStyles } = useCopyPasteActions();\n  const {\n    handleDuplicateSelectedElements,\n    handleOpenScaleAndCrop,\n    handleSetPageBackground,\n  } = useElementActions();\n  const {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleSendBackward,\n    handleSendToBack,\n    handleBringForward,\n    handleBringToFront,\n    handleCropOffScreenVideo,\n  } = useLayerActions();\n\n  const { hasShapeMask, removeShapeMask } = useShapeMask(selectedElement);\n  // @todo #12203 -- handle elements that have been rotated\n  const { offCanvas } = useMemo(\n    () => isOffCanvas(selectedElement),\n    [selectedElement]\n  );\n\n  const offScreenVideoCropping = useFeature('offScreenVideoCropping');\n\n  const canTranscodeResource = useLocalMedia(\n    (value) => value.state.canTranscodeResource\n  );\n  const { hasTrimMode, toggleTrimMode } = useVideoTrim(\n    ({ state, actions }) => ({\n      hasTrimMode: state.hasTrimMode,\n      toggleTrimMode: actions.toggleTrimMode,\n    })\n  );\n\n  const subMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  const isVideo = selectedElement?.type === 'video';\n  const scaleLabel = isVideo\n    ? RIGHT_CLICK_MENU_LABELS.SCALE_AND_CROP_VIDEO\n    : RIGHT_CLICK_MENU_LABELS.SCALE_AND_CROP_IMAGE;\n  const copyLabel = isVideo\n    ? RIGHT_CLICK_MENU_LABELS.COPY_VIDEO_STYLES\n    : RIGHT_CLICK_MENU_LABELS.COPY_IMAGE_STYLES;\n  const pasteLabel = isVideo\n    ? RIGHT_CLICK_MENU_LABELS.PASTE_VIDEO_STYLES\n    : RIGHT_CLICK_MENU_LABELS.PASTE_IMAGE_STYLES;\n\n  const showToggleTrimMode = isVideo && hasTrimMode;\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(1)}\n      </ContextMenuComponents.MenuButton>\n\n      {hasShapeMask && (\n        <ContextMenuComponents.MenuButton onClick={removeShapeMask}>\n          {RIGHT_CLICK_MENU_LABELS.REMOVE_MASK}\n        </ContextMenuComponents.MenuButton>\n      )}\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendBackward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_BACKWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_BACKWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendToBack}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_TO_BACK}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_TO_BACK.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringForward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_FORWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_FORWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringToFront}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_TO_FRONT}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_TO_FRONT.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n\n      <LayerName />\n      <LayerLock />\n      <LayerHide />\n      <LayerUngroup />\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton onClick={handleSetPageBackground}>\n        {RIGHT_CLICK_MENU_LABELS.SET_AS_PAGE_BACKGROUND}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton onClick={handleOpenScaleAndCrop}>\n        {scaleLabel}\n      </ContextMenuComponents.MenuButton>\n\n      {offScreenVideoCropping && isVideo && offCanvas && (\n        <ContextMenuComponents.MenuButton onClick={handleCropOffScreenVideo}>\n          {RIGHT_CLICK_MENU_LABELS.CROP_OFF_SCREEN_VIDEO}\n        </ContextMenuComponents.MenuButton>\n      )}\n\n      {showToggleTrimMode && (\n        <ContextMenuComponents.MenuButton\n          disabled={!canTranscodeResource(selectedElement?.resource)}\n          onClick={toggleTrimMode}\n        >\n          {RIGHT_CLICK_MENU_LABELS.TRIM_VIDEO}\n        </ContextMenuComponents.MenuButton>\n      )}\n\n      <ContextMenuComponents.MenuButton onClick={handleCopyStyles}>\n        {copyLabel}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.COPY_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={copiedElementType !== selectedElement?.type}\n        onClick={handlePasteStyles}\n      >\n        {pasteLabel}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.PASTE_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\nForegroundMediaMenu.propTypes = MenuPropType;\n\nexport default ForegroundMediaMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/groupMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useElementActions } from '../hooks';\nimport { useStory } from '../..';\n\nfunction GroupMenu() {\n  const {\n    handleDuplicateSelectedElements,\n    //handleGroupSelectedElements,\n    handleUngroupSelectedElements,\n  } = useElementActions();\n  const { selectedElements } = useStory(({ state }) => ({\n    selectedElements: state.selectedElements,\n  }));\n  const isGroupSelected = selectedElements.some((el) => el.groupId);\n  // const isOnlyGroupSelected = selectedElements.every(\n  //   (el) => el.groupId && el.groupId === selectedElements[0].groupId\n  // );\n\n  return (\n    <>\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(2)}\n      </ContextMenuComponents.MenuButton>\n      {isGroupSelected && (\n        <ContextMenuComponents.MenuButton\n          onClick={handleUngroupSelectedElements}\n        >\n          {RIGHT_CLICK_MENU_LABELS.UNGROUP_LAYERS}\n        </ContextMenuComponents.MenuButton>\n      )}\n    </>\n  );\n}\n\nexport default GroupMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ForegroundMediaMenu } from './foregroundMediaMenu';\nexport { default as MultipleElementsMenu } from './multipleElementsMenu';\nexport { default as PageMenu } from './pageMenu';\nexport { default as ShapeMenu } from './shapeMenu';\nexport { default as StickerMenu } from './stickerMenu';\nexport { default as TextMenu } from './textMenu';\nexport { default as GroupMenu } from './groupMenu';\nexport { default as ProductMenu } from './productMenu';\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/multipleElementsMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useElementActions } from '../hooks';\nimport useShapeMaskElements from '../../../utils/useShapeMaskElements';\nimport { useStory } from '../..';\n\nfunction MultipleElementsMenu() {\n  const {\n    handleDuplicateSelectedElements,\n    handleGroupSelectedElements,\n    handleUngroupSelectedElements,\n  } = useElementActions();\n  const { canMergeIntoMask, mergeIntoMask } = useShapeMaskElements();\n  const { selectedElements } = useStory(({ state }) => ({\n    selectedElements: state.selectedElements,\n  }));\n  const isGroupSelected = selectedElements.some((el) => el.groupId);\n  const isOnlyGroupSelected = selectedElements.every(\n    (el) => el.groupId && el.groupId === selectedElements[0].groupId\n  );\n\n  return (\n    <>\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(2)}\n      </ContextMenuComponents.MenuButton>\n      {/* only show if 1 shape and 1 media element is selected */}\n      {canMergeIntoMask && (\n        <ContextMenuComponents.MenuButton onClick={mergeIntoMask}>\n          {RIGHT_CLICK_MENU_LABELS.USE_SHAPE_AS_MASK}\n        </ContextMenuComponents.MenuButton>\n      )}\n      {!isOnlyGroupSelected && (\n        <ContextMenuComponents.MenuButton onClick={handleGroupSelectedElements}>\n          {RIGHT_CLICK_MENU_LABELS.GROUP_LAYERS}\n        </ContextMenuComponents.MenuButton>\n      )}\n      {isGroupSelected && (\n        <ContextMenuComponents.MenuButton\n          onClick={handleUngroupSelectedElements}\n        >\n          {RIGHT_CLICK_MENU_LABELS.UNGROUP_LAYERS}\n        </ContextMenuComponents.MenuButton>\n      )}\n    </>\n  );\n}\n\nexport default MultipleElementsMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/pageMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useVideoTrim from '../../../components/videoTrim/useVideoTrim';\nimport { RIGHT_CLICK_MENU_LABELS } from '../constants';\nimport { useElementActions, usePageActions } from '../hooks';\nimport { useStory, useLocalMedia } from '../..';\nimport useRightClickMenu from '../useRightClickMenu';\nimport useLayerSelect from '../useLayerSelect';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction PageMenu({ parentMenuRef }) {\n  const { currentPageIndex, canDeletePage, selectedElement } = useStory(\n    ({ state }) => ({\n      currentPageIndex: state.currentPageIndex,\n      canDeletePage: state.pages.length > 1,\n      selectedElement: state.selectedElements?.[0],\n    })\n  );\n  const { handleOpenScaleAndCrop, handleRemovePageBackground } =\n    useElementActions();\n  const { handleAddPageAtPosition, handleDeletePage, handleDuplicatePage } =\n    usePageActions();\n\n  const canTranscodeResource = useLocalMedia(\n    (value) => value.state.canTranscodeResource\n  );\n  const { hasTrimMode, toggleTrimMode } = useVideoTrim(\n    ({ state, actions }) => ({\n      hasTrimMode: state.hasTrimMode,\n      toggleTrimMode: actions.toggleTrimMode,\n    })\n  );\n\n  const subMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  const disableBackgroundMediaActions = selectedElement?.isDefaultBackground;\n  const isVideo = selectedElement?.type === 'video';\n  const detachLabel = isVideo\n    ? RIGHT_CLICK_MENU_LABELS.DETACH_VIDEO_FROM_BACKGROUND\n    : RIGHT_CLICK_MENU_LABELS.DETACH_IMAGE_FROM_BACKGROUND;\n  const scaleLabel = isVideo\n    ? RIGHT_CLICK_MENU_LABELS.SCALE_AND_CROP_BACKGROUND_VIDEO\n    : RIGHT_CLICK_MENU_LABELS.SCALE_AND_CROP_BACKGROUND_IMAGE;\n\n  const showTrimModeAction = isVideo && hasTrimMode;\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                // eslint-disable-next-line react-hooks/refs -- FIXME\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        disabled={disableBackgroundMediaActions}\n        onClick={handleRemovePageBackground}\n      >\n        {detachLabel}\n      </ContextMenuComponents.MenuButton>\n\n      <ContextMenuComponents.MenuButton\n        disabled={disableBackgroundMediaActions}\n        onClick={handleOpenScaleAndCrop}\n      >\n        {scaleLabel}\n      </ContextMenuComponents.MenuButton>\n\n      <ContextMenuComponents.MenuSeparator />\n\n      {showTrimModeAction && (\n        <>\n          <ContextMenuComponents.MenuButton\n            disabled={!canTranscodeResource(selectedElement?.resource)}\n            onClick={toggleTrimMode}\n          >\n            {detachLabel}\n          </ContextMenuComponents.MenuButton>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        onClick={() => handleAddPageAtPosition(currentPageIndex + 1)}\n      >\n        {RIGHT_CLICK_MENU_LABELS.ADD_NEW_PAGE_AFTER}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        onClick={() => handleAddPageAtPosition(currentPageIndex)}\n      >\n        {RIGHT_CLICK_MENU_LABELS.ADD_NEW_PAGE_BEFORE}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton onClick={handleDuplicatePage}>\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_PAGE}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canDeletePage}\n        onClick={handleDeletePage}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DELETE_PAGE}\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\nPageMenu.propTypes = MenuPropType;\n\nexport default PageMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/productMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport {\n  RIGHT_CLICK_MENU_LABELS,\n  RIGHT_CLICK_MENU_SHORTCUTS,\n} from '../constants';\nimport { useLayerActions } from '../hooks';\nimport useLayerSelect from '../useLayerSelect';\nimport { LayerHide, LayerLock, LayerName, LayerUngroup } from '../items';\nimport useRightClickMenu from '../useRightClickMenu';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction ProductMenu({ parentMenuRef }) {\n  const {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleSendBackward,\n    handleSendToBack,\n    handleBringForward,\n    handleBringToFront,\n  } = useLayerActions();\n\n  const subMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                // eslint-disable-next-line react-hooks/refs -- FIXME\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendBackward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_BACKWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_BACKWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendToBack}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_TO_BACK}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_TO_BACK.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringForward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_FORWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_FORWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringToFront}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_TO_FRONT}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_TO_FRONT.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n\n      <LayerName />\n      <LayerLock />\n      <LayerHide />\n      <LayerUngroup />\n    </>\n  );\n}\nProductMenu.propTypes = MenuPropType;\n\nexport default ProductMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/shapeMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  RIGHT_CLICK_MENU_LABELS,\n  RIGHT_CLICK_MENU_SHORTCUTS,\n} from '../constants';\nimport {\n  useCopyPasteActions,\n  useElementActions,\n  useLayerActions,\n  usePresetActions,\n} from '../hooks';\nimport useLayerSelect from '../useLayerSelect';\nimport { LayerHide, LayerLock, LayerName, LayerUngroup } from '../items';\nimport { useStory } from '../..';\nimport useRightClickMenu from '../useRightClickMenu';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction ShapeMenu({ parentMenuRef }) {\n  const { copiedElementType, selectedElementType } = useStory(({ state }) => ({\n    copiedElementType: state.copiedElementState.type,\n    selectedElementType: state.selectedElements?.[0].type,\n  }));\n  const { handleCopyStyles, handlePasteStyles } = useCopyPasteActions();\n  const { handleDuplicateSelectedElements } = useElementActions();\n  const {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleSendBackward,\n    handleSendToBack,\n    handleBringForward,\n    handleBringToFront,\n  } = useLayerActions();\n  const { handleAddColorPreset } = usePresetActions();\n\n  const subMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(1)}\n      </ContextMenuComponents.MenuButton>\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendBackward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_BACKWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_BACKWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendToBack}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_TO_BACK}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_TO_BACK.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringForward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_FORWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_FORWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringToFront}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_TO_FRONT}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_TO_FRONT.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n\n      <LayerName />\n      <LayerLock />\n      <LayerHide />\n      <LayerUngroup />\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton onClick={handleCopyStyles}>\n        {RIGHT_CLICK_MENU_LABELS.COPY_SHAPE_STYLES}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.COPY_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={copiedElementType !== selectedElementType}\n        onClick={handlePasteStyles}\n      >\n        {RIGHT_CLICK_MENU_LABELS.PASTE_SHAPE_STYLES}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.PASTE_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton onClick={handleAddColorPreset}>\n        {RIGHT_CLICK_MENU_LABELS.ADD_TO_COLOR_PRESETS}\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\nShapeMenu.propTypes = MenuPropType;\n\nexport default ShapeMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/shared.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\nexport const SubMenuContainer = styled.div`\n  position: absolute;\n  top: ${({ position }) => position?.y ?? 0}px;\n  left: ${({ position }) => position?.x ?? 0}px;\n  z-index: 9999;\n`;\nSubMenuContainer.propTypes = {\n  position: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),\n};\n\nexport const DEFAULT_DISPLACEMENT = 210;\n\nexport const SUB_MENU_ARIA_LABEL = __('Select a layer', 'web-stories');\n\nexport const MenuPropType = {\n  parentMenuRef: PropTypes.oneOfType([\n    PropTypes.func,\n    PropTypes.shape({ current: PropTypes.instanceOf(Element) }),\n  ]).isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/stickerMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport {\n  RIGHT_CLICK_MENU_LABELS,\n  RIGHT_CLICK_MENU_SHORTCUTS,\n} from '../constants';\nimport { useElementActions, useLayerActions } from '../hooks';\nimport useLayerSelect from '../useLayerSelect';\nimport { LayerHide, LayerLock, LayerName, LayerUngroup } from '../items';\nimport useRightClickMenu from '../useRightClickMenu';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction StickerMenu({ parentMenuRef }) {\n  const { handleDuplicateSelectedElements } = useElementActions();\n  const {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleSendBackward,\n    handleSendToBack,\n    handleBringForward,\n    handleBringToFront,\n  } = useLayerActions();\n\n  const subMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(1)}\n      </ContextMenuComponents.MenuButton>\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendBackward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_BACKWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_BACKWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendToBack}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_TO_BACK}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_TO_BACK.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringForward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_FORWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_FORWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringToFront}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_TO_FRONT}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_TO_FRONT.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n\n      <LayerName />\n      <LayerLock />\n      <LayerHide />\n      <LayerUngroup />\n    </>\n  );\n}\nStickerMenu.propTypes = MenuPropType;\n\nexport default StickerMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/menus/textMenu.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  RIGHT_CLICK_MENU_LABELS,\n  RIGHT_CLICK_MENU_SHORTCUTS,\n} from '../constants';\nimport {\n  useCopyPasteActions,\n  useElementActions,\n  useLayerActions,\n  usePresetActions,\n} from '../hooks';\nimport useLayerSelect from '../useLayerSelect';\nimport useHeadingSelect from '../hooks/useHeadingSelect';\nimport { LayerLock, LayerHide, LayerName, LayerUngroup } from '../items';\nimport { useStory } from '../..';\nimport useRightClickMenu from '../useRightClickMenu';\nimport {\n  DEFAULT_DISPLACEMENT,\n  MenuPropType,\n  SubMenuContainer,\n  SUB_MENU_ARIA_LABEL,\n} from './shared';\n\nfunction TextMenu({ parentMenuRef }) {\n  const { copiedElementType, selectedElementType } = useStory(({ state }) => ({\n    copiedElementType: state.copiedElementState.type,\n    selectedElementType: state.selectedElements?.[0].type,\n  }));\n  const { handleCopyStyles, handlePasteStyles } = useCopyPasteActions();\n  const { handleDuplicateSelectedElements } = useElementActions();\n  const {\n    canElementMoveBackwards,\n    canElementMoveForwards,\n    handleSendBackward,\n    handleSendToBack,\n    handleBringForward,\n    handleBringToFront,\n  } = useLayerActions();\n  const { handleAddColorPreset, handleAddTextPreset } = usePresetActions();\n\n  const subMenuRef = useRef();\n  const headingSubMenuRef = useRef();\n  const { menuPosition, onCloseMenu } = useRightClickMenu();\n  const layerSelectProps = useLayerSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const { closeSubMenu, isSubMenuOpen, subMenuItems, ...subMenuTriggerProps } =\n    layerSelectProps || {};\n\n  const headingSelectProps = useHeadingSelect({\n    menuPosition,\n    isMenuOpen: true,\n  });\n\n  const {\n    closeHeadingSubMenu,\n    isHeadingSubMenuOpen,\n    headingSubMenuItems,\n    ...headingSubMenuTriggerProps\n  } = headingSelectProps || {};\n\n  return (\n    <>\n      {layerSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={subMenuRef}\n            isSubMenuOpen={isSubMenuOpen}\n            {...subMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={subMenuRef}\n            position={{\n              x:\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 0,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isSubMenuOpen}\n              onCloseSubMenu={closeSubMenu}\n              aria-label={SUB_MENU_ARIA_LABEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {subMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      {headingSelectProps && (\n        <>\n          <ContextMenuComponents.SubMenuTrigger\n            closeSubMenu={closeHeadingSubMenu}\n            parentMenuRef={parentMenuRef}\n            subMenuRef={headingSubMenuRef}\n            isSubMenuOpen={isHeadingSubMenuOpen}\n            {...headingSubMenuTriggerProps}\n          />\n          <SubMenuContainer\n            ref={headingSubMenuRef}\n            position={{\n              x:\n                (parentMenuRef.current.firstChild?.offsetWidth ||\n                  DEFAULT_DISPLACEMENT) + 2,\n              y: 40,\n            }}\n          >\n            <ContextMenu\n              onDismiss={onCloseMenu}\n              isOpen={isHeadingSubMenuOpen}\n              onCloseSubMenu={closeHeadingSubMenu}\n              aria-label={RIGHT_CLICK_MENU_LABELS.HEADING_LEVEL}\n              isSubMenu\n              parentMenuRef={parentMenuRef}\n            >\n              {headingSubMenuItems.map(({ key, ...menuItemProps }) => (\n                <ContextMenuComponents.MenuItem key={key} {...menuItemProps} />\n              ))}\n            </ContextMenu>\n          </SubMenuContainer>\n          <ContextMenuComponents.MenuSeparator />\n        </>\n      )}\n\n      <ContextMenuComponents.MenuButton\n        onClick={handleDuplicateSelectedElements}\n      >\n        {RIGHT_CLICK_MENU_LABELS.DUPLICATE_ELEMENTS(1)}\n      </ContextMenuComponents.MenuButton>\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendBackward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_BACKWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_BACKWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveBackwards}\n        onClick={handleSendToBack}\n      >\n        {RIGHT_CLICK_MENU_LABELS.SEND_TO_BACK}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.SEND_TO_BACK.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringForward}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_FORWARD}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_FORWARD.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={!canElementMoveForwards}\n        onClick={handleBringToFront}\n      >\n        {RIGHT_CLICK_MENU_LABELS.BRING_TO_FRONT}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.BRING_TO_FRONT.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n\n      <LayerName />\n      <LayerLock />\n      <LayerHide />\n      <LayerUngroup />\n\n      <ContextMenuComponents.MenuSeparator />\n\n      <ContextMenuComponents.MenuButton onClick={handleCopyStyles}>\n        {RIGHT_CLICK_MENU_LABELS.COPY_STYLES}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.COPY_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton\n        disabled={copiedElementType !== selectedElementType}\n        onClick={handlePasteStyles}\n      >\n        {RIGHT_CLICK_MENU_LABELS.PASTE_STYLES}\n        <ContextMenuComponents.MenuShortcut>\n          {RIGHT_CLICK_MENU_SHORTCUTS.PASTE_STYLES.display}\n        </ContextMenuComponents.MenuShortcut>\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton onClick={handleAddTextPreset}>\n        {RIGHT_CLICK_MENU_LABELS.ADD_TO_TEXT_PRESETS}\n      </ContextMenuComponents.MenuButton>\n      <ContextMenuComponents.MenuButton onClick={handleAddColorPreset}>\n        {RIGHT_CLICK_MENU_LABELS.ADD_TO_COLOR_PRESETS}\n      </ContextMenuComponents.MenuButton>\n    </>\n  );\n}\nTextMenu.propTypes = MenuPropType;\n\nexport default TextMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useGlobalKeyDownEffect } from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo, useReducer } from '@googleforcreators/react';\n\n/** @typedef {import('react')} Node */\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport rightClickMenuReducer, {\n  ACTION_TYPES,\n  DEFAULT_RIGHT_CLICK_MENU_STATE,\n} from './reducer';\nimport { useCopyPasteActions } from './hooks';\n\n/**\n * Determines the items displayed in the right click menu\n * based off of the right-clicked element.\n *\n * Right click menu items should have the same shape as items\n * in the design system's context menu.\n *\n * @param {Object} root0 props for the provider\n * @param {Node} root0.children the children to be rendered\n * @return {Node} React node\n */\nfunction RightClickMenuProvider({ children }) {\n  const [{ isMenuOpen, menuPosition }, dispatch] = useReducer(\n    rightClickMenuReducer,\n    DEFAULT_RIGHT_CLICK_MENU_STATE\n  );\n\n  const { handleCopyStyles, handlePasteStyles } = useCopyPasteActions();\n\n  /**\n   * Open the menu at the position from the click event.\n   *\n   * @param {Event} evt The triggering event\n   */\n  const handleOpenMenu = useCallback((evt) => {\n    evt.preventDefault();\n    evt.stopPropagation();\n\n    let x = evt?.clientX;\n    let y = evt?.clientY;\n\n    // Context menus opened through a shortcut will not have clientX and clientY\n    // Instead determine the position of the menu off of the element\n    if (!x && !y) {\n      const dims = evt.target.getBoundingClientRect();\n      x = dims.x;\n      y = dims.y;\n    }\n\n    dispatch({\n      type: ACTION_TYPES.OPEN_MENU,\n      payload: { x, y },\n    });\n\n    trackEvent('context_menu_action', {\n      name: 'context_menu_opened',\n    });\n  }, []);\n\n  /**\n   * Close the menu and reset the tracked position.\n   */\n  const handleCloseMenu = useCallback(() => {\n    if (isMenuOpen) {\n      dispatch({ type: ACTION_TYPES.CLOSE_MENU });\n    }\n  }, [isMenuOpen]);\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+alt+o'] },\n    (evt) => {\n      evt.preventDefault();\n      handleCopyStyles();\n    },\n    [handleCopyStyles]\n  );\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+alt+p'] },\n    (evt) => {\n      evt.preventDefault();\n      handlePasteStyles();\n    },\n    [handlePasteStyles]\n  );\n\n  const value = useMemo(\n    () => ({\n      isMenuOpen,\n      menuPosition,\n      onCloseMenu: handleCloseMenu,\n      onOpenMenu: handleOpenMenu,\n    }),\n    [handleCloseMenu, handleOpenMenu, isMenuOpen, menuPosition]\n  );\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nRightClickMenuProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default RightClickMenuProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/reducer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ACTION_TYPES = {\n  OPEN_MENU: 'OPEN_MENU',\n  CLOSE_MENU: 'CLOSE_MENU',\n  RESET: 'RESET',\n};\n\nexport const DEFAULT_RIGHT_CLICK_MENU_STATE = {\n  isMenuOpen: false,\n  menuPosition: {\n    x: 0,\n    y: 0,\n  },\n};\n\n// TODO: check if we need to add tracking events when we come back to right click menu.\nfunction rightClickMenuReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.CLOSE_MENU:\n      return {\n        ...state,\n        isMenuOpen: false,\n        menuPosition: DEFAULT_RIGHT_CLICK_MENU_STATE.menuPosition,\n      };\n    case ACTION_TYPES.OPEN_MENU:\n      return {\n        ...state,\n        isMenuOpen: true,\n        menuPosition: action.payload,\n      };\n    case ACTION_TYPES.RESET:\n      return {\n        ...DEFAULT_RIGHT_CLICK_MENU_STATE,\n      };\n    default:\n      return state;\n  }\n}\n\nexport default rightClickMenuReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/useLayerSelect.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\nimport SAT from 'sat';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport { getLayerName } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../story/useStory';\nimport { useCanvas } from '../canvas';\nimport { useConfig } from '../config';\nimport useElementPolygon from '../../utils/useElementPolygon';\n\nconst ReversedIcon = styled(Icons.ChevronRightSmall)`\n  transform: rotate(180deg);\n`;\n\nfunction useLayerSelect({ menuItemProps, menuPosition, isMenuOpen }) {\n  const { isRTL } = useConfig();\n  const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\n  const nodesById = useCanvas(({ state: { nodesById } }) => nodesById);\n  const { currentPage, selectedElements, setSelectedElementsById } = useStory(\n    ({\n      state: { currentPage, selectedElements },\n      actions: { setSelectedElementsById },\n    }) => ({\n      currentPage,\n      selectedElements,\n      setSelectedElementsById,\n    })\n  );\n\n  const getElementPolygon = useElementPolygon();\n\n  useEffect(() => {\n    // Close submenu if the menu itself also closes.\n    if (!isMenuOpen) {\n      setIsSubMenuOpen(false);\n    }\n  }, [isMenuOpen]);\n\n  const { x, y } = menuPosition;\n  const getIntersectingElements = useCallback(() => {\n    if (!currentPage?.elements?.length || !Object.keys(nodesById)?.length) {\n      return [];\n    }\n    const clickedPoint = new SAT.Vector(x, y);\n    const elementsWithPolygons = currentPage.elements.map((element) => {\n      const polygon = getElementPolygon(element);\n      return { element, polygon };\n    });\n    const intersectingElements = elementsWithPolygons\n      .map(({ element, polygon }) =>\n        SAT.pointInPolygon(clickedPoint, polygon) ? element : null\n      )\n      .filter(Boolean);\n    intersectingElements.reverse();\n    return intersectingElements;\n  }, [currentPage, x, y, nodesById, getElementPolygon]);\n\n  const subMenuItems = useMemo(() => {\n    if (!isMenuOpen || selectedElements.length === 0) {\n      return [];\n    }\n    const intersectingElements = getIntersectingElements();\n    // If the only intersecting element is the selected element, don't display the menu.\n    if (\n      intersectingElements.length === 1 &&\n      intersectingElements[0].id === selectedElements[0].id\n    ) {\n      return [];\n    }\n    return intersectingElements.map((element) => {\n      const { id, isBackground, type } = element;\n      return {\n        key: id,\n        supportsIcon: true,\n        icon: selectedElements[0].id === id ? <Icons.CheckmarkSmall /> : null,\n        label: <span>{getLayerName(element)}</span>,\n        onClick: () => {\n          setSelectedElementsById({ elementIds: [id] });\n          trackEvent('context_menu_action', {\n            name: 'layer_selected',\n            element: type,\n            isBackground: isBackground,\n          });\n        },\n        ...menuItemProps,\n      };\n    });\n  }, [\n    getIntersectingElements,\n    isMenuOpen,\n    menuItemProps,\n    setSelectedElementsById,\n    selectedElements,\n  ]);\n\n  // Only display if submenu has any items.\n  return subMenuItems.length > 0\n    ? {\n        label: __('Select Layer', 'web-stories'),\n        openSubMenu: () => setIsSubMenuOpen(true),\n        closeSubMenu: () => setIsSubMenuOpen(false),\n        isSubMenuOpen,\n        subMenuItems: isSubMenuOpen ? subMenuItems : [],\n        SuffixIcon: isRTL ? ReversedIcon : Icons.ChevronRightSmall,\n        ...menuItemProps,\n      }\n    : null;\n}\n\nexport default useLayerSelect;\n"
  },
  {
    "path": "packages/story-editor/src/app/rightClickMenu/useRightClickMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useRightClickMenu(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useRightClickMenu;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/actions/test/useAutoSave.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport { getStoryMarkup } from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport APIContext from '../../../api/context';\nimport ConfigContext from '../../../config/context';\nimport useAutoSave from '../useAutoSave';\n\njest.mock('@googleforcreators/output', () => ({\n  getStoryMarkup: jest.fn(),\n}));\n\nfunction setup(args) {\n  const configValue = {\n    metadata: 'meta',\n  };\n  const autoSaveById = jest.fn();\n  const apiContextValue = {\n    actions: { autoSaveById },\n  };\n  const wrapper = ({ children }) => (\n    <ConfigContext.Provider value={configValue}>\n      <APIContext.Provider value={apiContextValue}>\n        {children}\n      </APIContext.Provider>\n    </ConfigContext.Provider>\n  );\n  const { result } = renderHook(() => useAutoSave(args), { wrapper });\n  return {\n    autoSave: result.current.autoSave,\n    autoSaveById,\n  };\n}\n\ndescribe('useAutoSave', () => {\n  it('should properly call autoSaveById when using autoSave', () => {\n    getStoryMarkup.mockImplementation(() => {\n      return 'Hello World!';\n    });\n    const story = {\n      storyId: 1,\n      title: 'Story!',\n      author: { id: 1, name: 'John Doe' },\n      slug: 'story',\n      publisherLogo: {\n        id: 1,\n        url: 'https://example.com/logo.png',\n        height: 0,\n        width: 0,\n      },\n      defaultPageDuration: 7,\n      status: 'publish',\n      date: '2020-04-10T07:06:26',\n      modified: '',\n      excerpt: '',\n      featuredMedia: {\n        id: 0,\n        url: 'https://example.com/image.png',\n        isExternal: false,\n        height: 100,\n        width: 100,\n      },\n      fonts: {},\n      password: '',\n      globalStoryStyles: '',\n      taxonomies: [],\n    };\n    const pages = [\n      {\n        type: 'page',\n        id: '2',\n        elements: [\n          {\n            id: '2',\n            type: 'text',\n            x: 0,\n            y: 0,\n          },\n        ],\n      },\n    ];\n    const { autoSave, autoSaveById } = setup({\n      storyId: 1,\n      story,\n      pages,\n    });\n\n    autoSaveById.mockImplementation(() => ({\n      finally(callback) {\n        callback();\n      },\n    }));\n\n    act(() => {\n      autoSave();\n    });\n    expect(autoSaveById).toHaveBeenCalledOnce();\n\n    const expected = {\n      ...story,\n      pages,\n      content: 'Hello World!',\n      products: [],\n    };\n    delete expected.taxonomies;\n\n    expect(autoSaveById).toHaveBeenCalledWith(expected);\n  });\n\n  it('should properly call autoSaveById when using autoSave with custom poster', () => {\n    getStoryMarkup.mockImplementation(() => {\n      return 'Hello World!';\n    });\n    const story = {\n      storyId: 1,\n      title: 'Story!',\n      author: { id: 1, name: 'John Doe' },\n      slug: 'story',\n      publisherLogo: {\n        id: 1,\n        url: 'https://example.com/logo.png',\n        height: 0,\n        width: 0,\n      },\n      defaultPageDuration: 7,\n      status: 'publish',\n      date: '2020-04-10T07:06:26',\n      modified: '',\n      excerpt: '',\n      featuredMedia: {\n        id: 0,\n        url: 'https://example.com/image.png',\n        isExternal: true,\n        needsProxy: false,\n        height: 100,\n        width: 100,\n      },\n      fonts: {},\n      password: '',\n      globalStoryStyles: '',\n      taxonomies: [],\n    };\n    const pages = [\n      {\n        type: 'page',\n        id: '2',\n        elements: [\n          {\n            id: '2',\n            type: 'text',\n            x: 0,\n            y: 0,\n          },\n        ],\n      },\n    ];\n    const { autoSave, autoSaveById } = setup({\n      storyId: 1,\n      story,\n      pages,\n    });\n\n    autoSaveById.mockImplementation(() => ({\n      finally(callback) {\n        callback();\n      },\n    }));\n\n    act(() => {\n      autoSave();\n    });\n    expect(autoSaveById).toHaveBeenCalledOnce();\n\n    const expected = {\n      ...story,\n      pages,\n      content: 'Hello World!',\n      products: [],\n    };\n    delete expected.taxonomies;\n\n    expect(autoSaveById).toHaveBeenCalledWith(expected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/actions/useAutoSave.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport type { Page, Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useConfig } from '../../config';\nimport getStoryPropsToSave from '../utils/getStoryPropsToSave';\nimport type { StorySaveData } from '../../../types';\n\ninterface AutoSaveProps {\n  storyId: number;\n  pages: Page[];\n  story: Story;\n}\n/**\n * Custom hook to auto-save a story.\n */\nfunction useAutoSave({ storyId, pages, story }: AutoSaveProps) {\n  const {\n    actions: { autoSaveById },\n  } = useAPI();\n  const { metadata, flags } = useConfig();\n  const [isAutoSaving, setIsAutoSaving] = useState(false);\n\n  const autoSave = useCallback(\n    (props: Partial<StorySaveData>) => {\n      setIsAutoSaving(true);\n      return autoSaveById?.({\n        storyId,\n        ...getStoryPropsToSave({\n          story,\n          pages,\n          metadata,\n          flags,\n        }),\n        ...props,\n      }).finally(() => setIsAutoSaving(false));\n    },\n    [story, pages, metadata, autoSaveById, storyId, flags]\n  );\n\n  return { autoSave, isAutoSaving };\n}\n\nexport default useAutoSave;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/actions/useLocalAutoSave.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { sessionStore } from '@googleforcreators/design-system';\nimport type { Page, Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport getSessionStorageKey from '../../../utils/getSessionStorageKey';\nimport type { ReducerState, Capabilities, Restore } from '../../../types';\n\ninterface UseLocalAutoSaveProps {\n  restore: Restore;\n  storyId: number;\n  pages: Page[];\n  capabilities: Capabilities;\n  isNew: boolean;\n}\nfunction useLocalAutoSave({\n  restore,\n  storyId,\n  pages,\n  capabilities,\n  isNew,\n}: UseLocalAutoSaveProps) {\n  const restoreLocalAutoSave = useCallback(() => {\n    const existingAutoSave = sessionStore.getItemByKey(\n      getSessionStorageKey(storyId, isNew)\n    ) as { story?: Story; pages?: Page[] };\n    // If either of the values is missing, nothing to do.\n    if (!existingAutoSave?.story || !existingAutoSave?.pages) {\n      return;\n    }\n\n    restore({\n      current: pages[0].id,\n      selection: [],\n      capabilities,\n      ...existingAutoSave,\n    } as Partial<ReducerState>);\n  }, [restore, storyId, pages, capabilities, isNew]);\n\n  return {\n    restoreLocalAutoSave,\n  };\n}\n\nexport default useLocalAutoSave;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/actions/useSaveStory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x, sprintf } from '@googleforcreators/i18n';\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { stripHTML } from '@googleforcreators/dom';\nimport type { Page, Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useConfig } from '../../config';\nimport useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL';\nimport getStoryPropsToSave from '../utils/getStoryPropsToSave';\nimport { useHistory } from '../../history';\nimport type {\n  RESTError,\n  StorySaveData,\n  UpdateStoryProps,\n  ReducerState,\n} from '../../../types';\n\nconst HTTP_STATUS_DESCRIPTIONS = {\n  400: _x('Bad Request', 'HTTP status description', 'web-stories'),\n  401: _x('Unauthorized', 'HTTP status description', 'web-stories'),\n  403: _x('Forbidden', 'HTTP status description', 'web-stories'),\n  500: _x('Internal Server Error', 'HTTP status description', 'web-stories'),\n};\n\ninterface UseSaveStoryProps {\n  storyId: number;\n  pages: Page[];\n  story: Story;\n  updateStory: (props: UpdateStoryProps) => ReducerState;\n}\n\n/**\n * Custom hook to save story.\n */\nfunction useSaveStory({\n  storyId,\n  pages,\n  story,\n  updateStory,\n}: UseSaveStoryProps) {\n  const {\n    actions: { saveStoryById },\n  } = useAPI();\n  const {\n    actions: { resetNewChanges },\n  } = useHistory();\n  const { metadata, flags } = useConfig();\n  const { showSnackbar } = useSnackbar();\n  const [isSaving, setIsSaving] = useState(false);\n  const [isFreshlyPublished, setIsFreshlyPublished] = useState(false);\n  const [isFreshlyPending, setIsFreshlyPending] = useState(false);\n\n  const { editLink } = story;\n  const refreshPostEditURL = useRefreshPostEditURL(storyId, editLink);\n\n  const saveStory = useCallback(\n    (props: Partial<StorySaveData>) => {\n      setIsSaving(true);\n\n      const isStoryAlreadyPublished = ['publish', 'future', 'private'].includes(\n        story.status\n      );\n      const isStoryAlreadyPending = 'pending' === story.status;\n      const trackTiming = getTimeTracker('load_save_story');\n\n      // Wrapping everything in a Promise so we can catch\n      // errors caused by getStoryPropsToSave() / getStoryMarkup().\n      return Promise.resolve()\n        .then(() =>\n          saveStoryById?.({\n            storyId,\n            ...getStoryPropsToSave({\n              story,\n              pages,\n              metadata,\n              flags,\n            }),\n            // Saving an auto-draft should create a draft by default.\n            status: 'auto-draft' === story.status ? 'draft' : story.status,\n            ...props,\n          })\n        )\n        .then((data) => {\n          if (!data) {\n            return;\n          }\n          const {\n            status,\n            slug,\n            link,\n            previewLink,\n            revisions,\n            editLink: newEditLink,\n            embedPostLink,\n            featuredMedia,\n            date: origDate,\n            modified,\n          } = data;\n\n          const date =\n            ['draft', 'auto-draft', 'pending'].includes(status) &&\n            (origDate === modified || !origDate)\n              ? null\n              : origDate;\n\n          const properties: Partial<Story> = {\n            status,\n            slug,\n            link,\n            previewLink,\n            editLink: newEditLink,\n            embedPostLink,\n            featuredMedia,\n            revisions,\n            date,\n            origDate,\n            modified,\n          };\n          updateStory({ properties });\n\n          refreshPostEditURL();\n\n          const isStoryPublished = ['publish', 'future', 'private'].includes(\n            data.status\n          );\n          const isStoryPending = 'pending' === data.status;\n          setIsFreshlyPublished(!isStoryAlreadyPublished && isStoryPublished);\n          setIsFreshlyPending(!isStoryAlreadyPending && isStoryPending);\n        })\n        .catch((err: RESTError) => {\n          const description = err.message ? stripHTML(err.message) : null;\n          let message: string = __('Failed to save the story', 'web-stories');\n\n          if (description) {\n            message = sprintf(\n              /* translators: %s: error message */\n              __('Failed to save the story: %s', 'web-stories'),\n              description\n            );\n          }\n\n          if (\n            err?.data?.status &&\n            Object.prototype.hasOwnProperty.call(\n              HTTP_STATUS_DESCRIPTIONS,\n              err?.data?.status\n            )\n          ) {\n            if (description) {\n              message = sprintf(\n                /* translators: 1: error message. 2: status code */\n                __('Failed to save the story: %1$s (%2$s)', 'web-stories'),\n                description,\n                HTTP_STATUS_DESCRIPTIONS[err.data.status]\n              );\n            } else {\n              message = sprintf(\n                /* translators: %s: error message */\n                __('Failed to save the story: %s', 'web-stories'),\n                HTTP_STATUS_DESCRIPTIONS[err.data.status]\n              );\n            }\n          }\n\n          // eslint-disable-next-line no-console -- We want to surface this error.\n          console.log(__('Failed to save the story', 'web-stories'), err);\n          void trackError('save_story', description || '');\n\n          showSnackbar({\n            message,\n            dismissible: true,\n          });\n        })\n        .finally(() => {\n          setIsSaving(false);\n          resetNewChanges();\n          trackTiming();\n        });\n    },\n    [\n      story,\n      pages,\n      metadata,\n      saveStoryById,\n      storyId,\n      updateStory,\n      refreshPostEditURL,\n      showSnackbar,\n      resetNewChanges,\n      flags,\n    ]\n  );\n\n  return { saveStory, isSaving, isFreshlyPublished, isFreshlyPending };\n}\n\nexport default useSaveStory;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/constants.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { Story } from '@googleforcreators/elements';\nimport { StoryAnimationState } from '@googleforcreators/animation';\n\nexport const INITIAL_STATE = {\n  pages: [],\n  capabilities: {},\n  current: null,\n  selection: [],\n  story: { fonts: {} } as Story,\n  animationState: StoryAnimationState.Reset,\n  copiedElementState: {},\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/story/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\nimport type { Element, Page, Story } from '@googleforcreators/elements';\nimport type {\n  StoryAnimation,\n  StoryAnimationState,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport type { StoryProviderState } from '../../types';\nimport { INITIAL_STATE } from './constants';\n\nexport default createContext<StoryProviderState>({\n  state: {\n    story: {} as Story,\n    pages: [] as Page[],\n    animationState: '' as StoryAnimationState,\n    capabilities: {},\n    currentPage: null,\n    currentPageId: null,\n    currentPageIndex: null,\n    currentPageNumber: null,\n    selectedElementIds: [],\n    selectedElements: [] as Element[],\n    selectedElementAnimations: [] as StoryAnimation[],\n    hasSelection: false,\n    meta: {\n      isSaving: false,\n      isSavingStory: false,\n      isAutoSavingStory: false,\n      isFreshlyPublished: false,\n      isFreshlyPending: false,\n    },\n  },\n  actions: {\n    addPage: () => INITIAL_STATE,\n    addPageAt: () => INITIAL_STATE,\n    copySelectedElement: () => INITIAL_STATE,\n    deletePage: () => INITIAL_STATE,\n    deleteCurrentPage: () => INITIAL_STATE,\n    updatePageProperties: () => INITIAL_STATE,\n    updateCurrentPageProperties: () => INITIAL_STATE,\n    arrangePage: () => INITIAL_STATE,\n    setCurrentPage: () => INITIAL_STATE,\n    addElements: () => INITIAL_STATE,\n    addElement: () => INITIAL_STATE,\n    deleteElementsById: () => INITIAL_STATE,\n    deleteElementById: () => INITIAL_STATE,\n    deleteSelectedElements: () => INITIAL_STATE,\n    updateElementsById: () => INITIAL_STATE,\n    updateElementsByResourceId: () => INITIAL_STATE,\n    deleteElementsByResourceId: () => INITIAL_STATE,\n    updateElementById: () => INITIAL_STATE,\n    duplicateElementsById: () => INITIAL_STATE,\n    updateSelectedElements: () => INITIAL_STATE,\n    combineElements: () => INITIAL_STATE,\n    setBackgroundElement: () => INITIAL_STATE,\n    clearBackgroundElement: () => INITIAL_STATE,\n    arrangeElement: () => INITIAL_STATE,\n    arrangeGroup: () => INITIAL_STATE,\n    arrangeSelection: () => INITIAL_STATE,\n    setSelectedElementsById: () => INITIAL_STATE,\n    clearSelection: () => INITIAL_STATE,\n    addElementToSelection: () => INITIAL_STATE,\n    removeElementFromSelection: () => INITIAL_STATE,\n    toggleElementInSelection: () => INITIAL_STATE,\n    updateAnimationState: () => INITIAL_STATE,\n    addAnimations: () => INITIAL_STATE,\n    updateStory: () => INITIAL_STATE,\n    toggleLayer: () => INITIAL_STATE,\n    updateElementsByFontFamily: () => INITIAL_STATE,\n    addGroup: () => INITIAL_STATE,\n    updateGroupById: () => INITIAL_STATE,\n    deleteGroupById: () => INITIAL_STATE,\n    deleteGroupAndElementsById: () => INITIAL_STATE,\n    duplicateGroupById: () => INITIAL_STATE,\n    removeElementFromGroup: () => INITIAL_STATE,\n    addElementsAcrossPages: () => INITIAL_STATE,\n    autoSave: () => null,\n    saveStory: () => null,\n    restoreLocalAutoSave: () => null,\n  },\n  internal: {\n    reducerState: INITIAL_STATE,\n    restore: () => INITIAL_STATE,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/test/useHashState.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useHashState, { hashToParams } from '../useHashState';\n\nconst hashKeyVal = (key) =>\n  JSON.parse(decodeURI(hashToParams(window.location.hash).get(key)));\n\ndescribe('useHashState', () => {\n  afterEach(() => {\n    window.location.hash = '';\n  });\n\n  it('initializes with fallback if no value found under hash key', () => {\n    const fallback = 4;\n    const { result } = renderHook(() => useHashState('test', fallback));\n    expect(result.current[0]).toBe(fallback);\n  });\n\n  it('updates hash key value on every update', () => {\n    const key = 'test';\n    const { result } = renderHook(() => useHashState(key, 5));\n    expect(hashKeyVal(key)).toBe(5);\n\n    act(() => result.current[1](10));\n    expect(hashKeyVal(key)).toBe(10);\n\n    act(() => result.current[1](15));\n    expect(hashKeyVal(key)).toBe(15);\n  });\n\n  it('initializes with hash key value if it exists', () => {\n    const key = 'test';\n    const persisted = 86;\n    window.location.hash = `${key}=${persisted}`;\n    const { result } = renderHook(() => useHashState(key, 0));\n    expect(result.current[0]).toBe(persisted);\n  });\n\n  it('can handle objects', () => {\n    const key = 'test';\n    const fallback = {\n      one: 'thing',\n      two: {\n        three: 4,\n      },\n    };\n    const addFive = (obj) => ({ ...obj, five: true });\n\n    const { result: result1 } = renderHook(() => useHashState(key, fallback));\n    act(() => result1.current[1](addFive));\n\n    const { result: result2 } = renderHook(() => useHashState(key, null));\n    expect(result2.current[0]).toStrictEqual(addFive(fallback));\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/test/useLoadStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport PropTypes from 'prop-types';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { createStory } from '../../../api/test/_utils';\nimport useLoadStory from '../useLoadStory';\nimport APIContext from '../../../api/context';\nimport HistoryContext from '../../../history/context';\nimport ConfigContext from '../../../config/context';\n\nconst getStoryById = jest.fn();\nconst clearHistory = jest.fn();\n\nconst apiContextValue = { actions: { getStoryById } };\nconst historyContextValue = { actions: { clearHistory } };\n\nfunction ContextWrapper({ children }) {\n  const configValue = {\n    globalAutoAdvance: true,\n    globalPageDuration: 20,\n  };\n  return (\n    <ConfigContext.Provider value={configValue}>\n      <APIContext.Provider value={apiContextValue}>\n        <HistoryContext.Provider value={historyContextValue}>\n          {children}\n        </HistoryContext.Provider>\n      </APIContext.Provider>\n    </ConfigContext.Provider>\n  );\n}\n\nContextWrapper.propTypes = {\n  children: PropTypes.any.isRequired,\n};\n\ndescribe('useLoadStory', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  beforeEach(() => {\n    getStoryById.mockReset();\n    clearHistory.mockReset();\n  });\n\n  it('should load draft story with identical date and modified as having no publish date', async () => {\n    getStoryById.mockReturnValue(\n      Promise.resolve(\n        createStory({\n          date: '2020-01-01T19:20:20',\n          dateGmt: '2020-01-01T20:20:20',\n          modified: '2020-01-01T19:20:20',\n          status: 'draft',\n        })\n      )\n    );\n\n    const restore = jest.fn();\n    await renderHook(\n      () =>\n        useLoadStory({\n          storyId: 11,\n          shouldLoad: true,\n          restore,\n        }),\n      { wrapper: ContextWrapper }\n    );\n\n    expect(restore.mock.calls[0][0].story).toStrictEqual(\n      expect.objectContaining({\n        storyId: 11,\n        title: 'title',\n        date: null,\n        modified: '2020-01-01T19:20:20',\n        author: { id: 1, name: 'John Doe' },\n        excerpt: 'excerpt',\n        featuredMedia: { id: 0, height: 0, width: 0, url: '' },\n        permalinkConfig: {\n          prefix: 'http://localhost:8899/web-stories/',\n          suffix: '',\n        },\n      })\n    );\n  });\n\n  it('should load draft story with specific publish date set to that date', async () => {\n    getStoryById.mockReturnValue(\n      Promise.resolve(\n        createStory({\n          date: '2020-01-01T19:20:20',\n          dateGmt: '2020-01-01T20:20:20',\n          modified: '2019-01-01T19:20:20',\n          status: 'draft',\n        })\n      )\n    );\n\n    const restore = jest.fn();\n    await renderHook(\n      () =>\n        useLoadStory({\n          storyId: 12,\n          shouldLoad: true,\n          restore,\n        }),\n      { wrapper: ContextWrapper }\n    );\n\n    expect(restore.mock.calls[0][0].story).toStrictEqual(\n      expect.objectContaining({\n        storyId: 12,\n        title: 'title',\n        date: '2020-01-01T19:20:20',\n        modified: '2019-01-01T19:20:20',\n        author: { id: 1, name: 'John Doe' },\n        excerpt: 'excerpt',\n        featuredMedia: { id: 0, height: 0, width: 0, url: '' },\n        permalinkConfig: {\n          prefix: 'http://localhost:8899/web-stories/',\n          suffix: '',\n        },\n      })\n    );\n  });\n\n  it('should load published story with identical date and modified with actual publish date', async () => {\n    getStoryById.mockReturnValue(\n      Promise.resolve(\n        createStory({\n          date: '2020-01-01T19:20:20',\n          dateGmt: '2020-01-01T20:20:20',\n          modified: '2020-01-01T19:20:20',\n          status: 'published',\n        })\n      )\n    );\n\n    const restore = jest.fn();\n    await renderHook(\n      () =>\n        useLoadStory({\n          storyId: 13,\n          shouldLoad: true,\n          restore,\n        }),\n      { wrapper: ContextWrapper }\n    );\n\n    expect(restore.mock.calls[0][0].story).toStrictEqual(\n      expect.objectContaining({\n        storyId: 13,\n        title: 'title',\n        date: '2020-01-01T19:20:20',\n        modified: '2020-01-01T19:20:20',\n        author: { id: 1, name: 'John Doe' },\n        excerpt: 'excerpt',\n        featuredMedia: { id: 0, height: 0, width: 0, url: '' },\n        permalinkConfig: {\n          prefix: 'http://localhost:8899/web-stories/',\n          suffix: '',\n        },\n      })\n    );\n  });\n\n  it('should load story with global page advancement settings if undefined in story', async () => {\n    getStoryById.mockReturnValue(Promise.resolve(createStory()));\n\n    const restore = jest.fn();\n    await renderHook(\n      () =>\n        useLoadStory({\n          storyId: 11,\n          shouldLoad: true,\n          restore,\n        }),\n      { wrapper: ContextWrapper }\n    );\n\n    expect(restore.mock.calls[0][0].story).toStrictEqual(\n      expect.objectContaining({\n        storyId: 11,\n        title: 'title',\n        author: { id: 1, name: 'John Doe' },\n        excerpt: 'excerpt',\n        featuredMedia: { id: 0, height: 0, width: 0, url: '' },\n        permalinkConfig: {\n          prefix: 'http://localhost:8899/web-stories/',\n          suffix: '',\n        },\n        autoAdvance: true,\n        defaultPageDuration: 20,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/useHashState.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, useState } from '@googleforcreators/react';\nimport type { Dispatch, SetStateAction } from 'react';\n\nexport function hashToParams(hash: string) {\n  return new URLSearchParams(hash.startsWith('#') ? hash.substr(1) : hash);\n}\n\n/**\n * Functions like a normal `useState()` but reads initial value of of url\n * hash key and uses `fallback` if no value found. Also updates hash key on\n * every state update so is persistent between mounts.\n *\n * Values held in here must be serializable.\n *\n * Can be used as many times as needed, but may exceed url char limit\n * if over used.\n */\nfunction useHashState(\n  key: string,\n  fallback: string | null\n): [string | null, Dispatch<SetStateAction<string | null>>] {\n  const [value, setValue] = useState<string | null>(() => {\n    const params = hashToParams(window.location.hash);\n    let _value = fallback;\n    try {\n      if (params.has(key)) {\n        const paramValue = params.get(key);\n        if (null === paramValue) {\n          return paramValue;\n        }\n        _value = JSON.parse(decodeURI(paramValue)) as string;\n      }\n    } catch {\n      /* empty */\n    }\n    return _value;\n  });\n\n  // update url param when value updates\n  useEffect(() => {\n    const params = hashToParams(window.location.hash);\n    if (!value) {\n      params.delete(key);\n    } else {\n      params.set(key, encodeURI(JSON.stringify(value)));\n    }\n\n    if (!window.location.hash && !params.toString()) {\n      return;\n    }\n\n    history.replaceState(history.state, '', `#${params.toString()}`);\n  }, [key, value]);\n\n  return [value, setValue];\n}\n\nexport default useHashState;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/useHistoryEntry.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useHistory } from '../../history';\nimport deleteNestedKeys from '../utils/deleteNestedKeys';\nimport pageContainsBlobUrl from '../utils/pageContainsBlobUrl';\nimport type { HistoryEntry } from '../../../types';\n\n// Changes to these properties of elements do not create a new history entry\n// if only one (or multiple) of these properties change but nothing else changes.\n// These are still saved as part of changes involving other properties.\nconst ELEMENT_PROPS_TO_IGNORE = [\n  'resource.baseColor',\n  'resource.blurHash',\n  'resource.id',\n  'resource.isMuted',\n  'resource.posterId',\n  'resource.poster',\n  'resource.font.metrics',\n  'resource.font.weights',\n  'resource.font.variants',\n  'resource.font.fallbacks',\n  'resource.font.styles',\n  'resource.isOptimized',\n  'resource.length',\n  'resource.lengthFormatted',\n  'resource.trimData.original',\n  'resource.trimData.start',\n  'resource.trimData.end',\n  'resource.creationDate',\n];\n\n// Record any change to core variables in history (history will know if it's a replay)\nfunction useHistoryEntry({\n  story,\n  current,\n  pages,\n  selection,\n  capabilities,\n}: HistoryEntry) {\n  const {\n    state: { currentEntry },\n    actions: { stateToHistory },\n  } = useHistory();\n\n  const currentHistoryEntryRef = useRef<HistoryEntry | null>(null);\n  useEffect(() => {\n    if (currentEntry) {\n      currentHistoryEntryRef.current = structuredClone(currentEntry);\n    }\n  }, [currentEntry]);\n\n  const currentPageIdRef = useRef<string | null>(null);\n  const selectedElementIdsRef = useRef<string[]>([]);\n  useEffect(() => {\n    currentPageIdRef.current = current;\n    selectedElementIdsRef.current = selection;\n  }, [current, selection]);\n\n  const deleteKeysFromPages = (list: Page[]) => {\n    // Create a copy of the list not to influence the original.\n    return structuredClone(list).map((page) => {\n      page.elements.forEach((element) =>\n        deleteNestedKeys(ELEMENT_PROPS_TO_IGNORE)({ ...element })\n      );\n      return page;\n    });\n  };\n\n  useEffect(() => {\n    // There are some element properties that should not influence history.\n    // Before adding a new history entry, let's check if the only properties that changed\n    // should not influence history. Then we skip adding an entry.\n    let skipAddingEntry = false;\n    if (\n      ELEMENT_PROPS_TO_IGNORE.length &&\n      currentHistoryEntryRef.current &&\n      pages?.length\n    ) {\n      // If story / capabilities change, we should always add a new entry.\n      const withoutPages = {\n        story,\n        capabilities,\n      };\n      const onlyPagesChanged = Object.entries(withoutPages).every(\n        ([key, value]) =>\n          JSON.stringify(value) ===\n          JSON.stringify(\n            currentHistoryEntryRef.current?.[key as keyof HistoryEntry]\n          )\n      );\n      // If only pages have changed, check if relevant properties have changed.\n      if (onlyPagesChanged) {\n        const adjustedPages = deleteKeysFromPages(pages);\n        const adjustedEntryPages = deleteKeysFromPages(\n          currentHistoryEntryRef.current.pages\n        );\n        // Check if after removing properties that shouldn't influence history, nothing changed.\n        // Is so, let's skip adding a history entry.\n        skipAddingEntry =\n          JSON.stringify(adjustedPages) === JSON.stringify(adjustedEntryPages);\n      }\n\n      if (pageContainsBlobUrl(pages)) {\n        skipAddingEntry = true;\n      }\n    }\n\n    if (!skipAddingEntry) {\n      stateToHistory({\n        story,\n        current: currentPageIdRef.current,\n        selection: selectedElementIdsRef.current,\n        pages,\n        capabilities,\n      });\n    }\n  }, [story, pages, stateToHistory, capabilities]);\n}\n\nexport default useHistoryEntry;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/useHistoryReplay.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useHistory } from '../../history';\nimport type { Restore } from '../../../types';\n\nfunction useHistoryReplay({ restore }: { restore: Restore }) {\n  const {\n    state: { requestedState },\n  } = useHistory();\n  useEffect(() => {\n    if (!requestedState) {\n      return;\n    }\n    const { current, pages, selection, story, capabilities } = requestedState;\n    restore({\n      pages,\n      current,\n      story,\n      selection,\n      capabilities,\n    });\n  }, [restore, requestedState]);\n}\n\nexport default useHistoryReplay;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/effects/useLoadStory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\nimport { migrate } from '@googleforcreators/migration';\nimport { createPage, type TextElement } from '@googleforcreators/elements';\nimport { populateElementFontData } from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useHistory } from '../../history';\nimport getUniquePresets from '../../../utils/getUniquePresets';\nimport { useConfig } from '../../config';\nimport type { RawStory, Restore } from '../../../types';\n\nfunction loadStory(\n  storyId: number,\n  post: RawStory,\n  restore: Restore,\n  clearHistory: () => void,\n  globalConfig: {\n    globalAutoAdvance?: boolean;\n    globalPageDuration?: number;\n  }\n) {\n  const {\n    title: { raw: title = '' } = {},\n    status,\n    slug,\n    date: origDate,\n    modified,\n    excerpt: { raw: excerpt = '' } = {},\n    link,\n    storyData: storyDataRaw,\n    permalinkTemplate,\n    stylePresets: globalStoryStyles = {},\n    password,\n    previewLink,\n    editLink,\n    embedPostLink,\n    author,\n    capabilities = {\n      publish: false,\n      'assign-author': false,\n    },\n    extras = {},\n    featuredMedia,\n    publisherLogo,\n    taxonomies,\n    terms,\n    revisions,\n  }: RawStory = post;\n\n  const date =\n    ['draft', 'auto-draft', 'pending'].includes(status) &&\n    (origDate === modified || !origDate)\n      ? null\n      : origDate;\n\n  const [prefix, suffix] = permalinkTemplate\n    ? permalinkTemplate.split(/%(?:postname|pagename)%/)\n    : [];\n  // If either of these is undefined, the placeholder was not found in settings.\n  const foundSettings = prefix !== undefined && suffix !== undefined;\n  const permalinkConfig = foundSettings\n    ? {\n        prefix,\n        suffix,\n      }\n    : null;\n\n  // First clear history completely.\n  clearHistory();\n\n  // If there are no pages, create empty page.\n  const storyData =\n    storyDataRaw && migrate(storyDataRaw, storyDataRaw.version || 0);\n  let pages =\n    storyData?.pages && storyData.pages.length > 0\n      ? storyData.pages\n      : [createPage()];\n\n  if (storyData?.fonts && Object.keys(storyData?.fonts).length >= 1) {\n    // fonts are stored in storyData,\n    // so we need to populate the font data back to the elements\n    pages = populateElementFontData(pages, storyData.fonts);\n  }\n\n  // Initialize color/style presets, if missing.\n  // Otherwise ensure the saved presets are unique.\n  const newGlobalStoryStyles = {\n    colors: globalStoryStyles.colors\n      ? getUniquePresets(globalStoryStyles.colors)\n      : [],\n    textStyles: globalStoryStyles.textStyles\n      ? getUniquePresets<Partial<TextElement>>(globalStoryStyles.textStyles)\n      : [],\n  };\n\n  // Set story-global variables.\n  const story = {\n    storyId: storyId,\n    title,\n    fonts: storyData?.fonts || {},\n    status,\n    author,\n    date,\n    origDate,\n    modified,\n    excerpt,\n    slug,\n    link,\n    extras,\n    featuredMedia,\n    permalinkConfig,\n    publisherLogo,\n    password,\n    previewLink,\n    editLink,\n    embedPostLink,\n    revisions,\n    currentStoryStyles: {\n      colors: storyData?.currentStoryStyles?.colors\n        ? getUniquePresets(storyData.currentStoryStyles.colors)\n        : [],\n    },\n    globalStoryStyles: newGlobalStoryStyles,\n    autoAdvance:\n      storyData?.autoAdvance === undefined\n        ? globalConfig.globalAutoAdvance\n        : storyData?.autoAdvance,\n    defaultPageDuration:\n      storyData?.defaultPageDuration === undefined\n        ? globalConfig.globalPageDuration\n        : storyData?.defaultPageDuration,\n    backgroundAudio: storyData?.backgroundAudio,\n    taxonomies,\n    terms,\n  };\n\n  // TODO read current page and selection from deeplink?\n  restore({\n    pages,\n    story,\n    selection: [],\n    current: null, // will be set to first page by `restore`\n    capabilities,\n  });\n}\n\ninterface LoadStoryProps {\n  storyId: number;\n  story?: RawStory;\n  shouldLoad: boolean;\n  restore: Restore;\n}\n// When ID is set, load story from API.\nfunction useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) {\n  const {\n    actions: { getStoryById },\n  } = useAPI();\n  const {\n    actions: { clearHistory },\n  } = useHistory();\n  const { globalAutoAdvance, globalPageDuration } = useConfig();\n\n  useEffect(() => {\n    const globalConfig = { globalAutoAdvance, globalPageDuration };\n    if (storyId && shouldLoad) {\n      if (story) {\n        loadStory(storyId, story, restore, clearHistory, globalConfig);\n      } else {\n        void getStoryById?.(storyId).then((post: RawStory) => {\n          loadStory(storyId, post, restore, clearHistory, globalConfig);\n        });\n      }\n    }\n  }, [\n    storyId,\n    story,\n    shouldLoad,\n    restore,\n    getStoryById,\n    clearHistory,\n    globalAutoAdvance,\n    globalPageDuration,\n  ]);\n}\n\nexport default useLoadStory;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport * as storyReducers from './useStoryReducer/reducers';\nexport { default as StoryProvider } from './storyProvider';\nexport { default as StoryContext } from './context';\nexport { default as useStory } from './useStory';\nexport {\n  useStoryTriggers,\n  useStoryTriggerListener,\n  useStoryTriggersDispatch,\n  STORY_EVENTS,\n} from './storyTriggers';\n\nexport { storyReducers };\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\nimport { useMemo, useEffect } from '@googleforcreators/react';\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { STABLE_ARRAY } from '../../constants';\nimport type { RawStory } from '../../types';\nimport Context from './context';\n\nimport useLoadStory from './effects/useLoadStory';\nimport useSaveStory from './actions/useSaveStory';\nimport useHashState from './effects/useHashState';\nimport useHistoryEntry from './effects/useHistoryEntry';\nimport useHistoryReplay from './effects/useHistoryReplay';\nimport useStoryReducer from './useStoryReducer';\nimport useAutoSave from './actions/useAutoSave';\nimport { StoryTriggersProvider } from './storyTriggers';\nimport useLocalAutoSave from './actions/useLocalAutoSave';\n\ninterface ProviderProps {\n  storyId: number;\n  initialEdits?: {\n    story?: RawStory;\n  };\n}\nfunction StoryProvider({\n  storyId,\n  initialEdits,\n  children,\n}: PropsWithChildren<ProviderProps>) {\n  const [hashPageId, setHashPageId] = useHashState('page', null);\n  const {\n    state: reducerState,\n    api,\n    internal: { restore },\n  } = useStoryReducer({\n    current: hashPageId,\n  });\n  const {\n    pages,\n    current,\n    selection,\n    story,\n    animationState,\n    capabilities,\n    copiedElementState,\n  } = reducerState;\n\n  useEffect(() => setHashPageId(current), [current, setHashPageId]);\n\n  // Generate current page info.\n  let currentPageId: string | null = null;\n  let currentPageIndex: number | null = null;\n  let currentPageNumber: number | null = null;\n  let currentPage: Page | null = null;\n  if (current) {\n    currentPageId = current;\n    currentPageIndex = pages.findIndex(({ id }) => id === current);\n    currentPageNumber = currentPageIndex + 1;\n    currentPage = pages[currentPageIndex];\n  }\n\n  // Generate selection info\n  const selectedElementIds = useMemo(\n    () => (selection && selection.length > 0 ? selection : STABLE_ARRAY),\n    [selection]\n  );\n  const isCurrentPageEmpty = !currentPage;\n\n  const currentPageElements = currentPage?.elements;\n  const selectedElements = useMemo(() => {\n    if (isCurrentPageEmpty) {\n      return STABLE_ARRAY;\n    }\n    const els = currentPageElements?.filter(\n      ({ id }) => selection && selection.includes(id)\n    );\n    return els && els.length > 0 ? els : STABLE_ARRAY;\n  }, [isCurrentPageEmpty, currentPageElements, selection]);\n\n  const currentPageAnimations = currentPage?.animations;\n  const selectedElementAnimations = useMemo(() => {\n    if (isCurrentPageEmpty || selection.length === 0) {\n      return STABLE_ARRAY;\n    }\n    const animations = (currentPageAnimations || []).filter(({ targets }) =>\n      targets.some((id) => selection && selection.includes(id))\n    );\n    return animations.length > 0 ? animations : STABLE_ARRAY;\n  }, [isCurrentPageEmpty, selection, currentPageAnimations]);\n  const hasSelection = selectedElements.length > 0;\n\n  // This effect loads and initialises the story on first load (when there's no pages).\n  const shouldLoad = pages.length === 0;\n  useLoadStory({ restore, shouldLoad, storyId, story: initialEdits?.story });\n\n  // These effects send updates to and restores state from history.\n  useHistoryEntry({ pages, current, selection, story, capabilities });\n  useHistoryReplay({ restore });\n\n  // This action allows the user to save the story\n  // (and it will have side-effects because saving can update url and status,\n  //  thus the need for `updateStory`)\n  const { updateStory } = api;\n  const { saveStory, isSaving, isFreshlyPublished, isFreshlyPending } =\n    useSaveStory({\n      storyId,\n      pages,\n      story,\n      updateStory,\n    });\n\n  const { autoSave, isAutoSaving } = useAutoSave({\n    storyId,\n    pages,\n    story,\n  });\n\n  const { restoreLocalAutoSave } = useLocalAutoSave({\n    pages,\n    capabilities,\n    restore,\n    storyId,\n    isNew: story.status === 'auto-draft',\n  });\n\n  const fullStory = useMemo(\n    () => ({\n      pages,\n      currentPage,\n      currentPageId,\n      currentPageIndex,\n      currentPageNumber,\n      selectedElementIds,\n      selectedElements,\n      selectedElementAnimations,\n      hasSelection,\n      story,\n      animationState,\n      capabilities,\n      meta: {\n        isSaving: isSaving || isAutoSaving,\n        isSavingStory: isSaving,\n        isAutoSavingStory: isAutoSaving,\n        isFreshlyPublished,\n        isFreshlyPending,\n      },\n      copiedElementState,\n    }),\n    [\n      pages,\n      currentPage,\n      currentPageId,\n      currentPageIndex,\n      currentPageNumber,\n      selectedElementIds,\n      selectedElements,\n      selectedElementAnimations,\n      hasSelection,\n      story,\n      animationState,\n      capabilities,\n      isSaving,\n      isAutoSaving,\n      isFreshlyPublished,\n      isFreshlyPending,\n      copiedElementState,\n    ]\n  );\n\n  const state = {\n    state: fullStory,\n    actions: {\n      ...api,\n      autoSave,\n      saveStory,\n      restoreLocalAutoSave,\n    },\n    internal: { reducerState, restore },\n  };\n\n  return (\n    <Context.Provider value={state}>\n      <StoryTriggersProvider story={fullStory}>\n        {children}\n      </StoryTriggersProvider>\n    </Context.Provider>\n  );\n}\n\nexport default StoryProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport {\n  useStoryTriggers,\n  useStoryTriggerListener,\n  useStoryTriggersDispatch,\n} from './useStoryTriggers';\nexport { StoryTriggersProvider } from './storyTriggersProvider';\nexport { STORY_EVENTS } from './storyEvents';\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { OnInitialElementAddedRegister } from './onInitialElementAddedRegister';\nimport { OnPageAddedRegister } from './onPageAddedRegister';\nexport { STORY_EVENTS } from './types';\n\n// Add all story event registers here. All registers\n// should take registerPropTypes from `/storyEvents/propTypes`.\nexport const StoryEventRegisters = [\n  OnInitialElementAddedRegister,\n  OnPageAddedRegister,\n];\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useRef, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { OnActionProps, State } from '../../../../types';\nimport { STORY_EVENTS } from './types';\n\nexport function isNewStory(story: State | null) {\n  return (\n    story?.pages?.length === 0 ||\n    (story?.pages?.length === 1 && story?.pages[0]?.elements?.length <= 1)\n  );\n}\n\nfunction OnInitialElementAddedRegister({\n  currentStory,\n  dispatchStoryEvent,\n}: OnActionProps) {\n  const hasFiredOnceRef = useRef(false);\n\n  // Dispatch `onInitialElementAdded` story event once, the first time\n  // we notice a story has any content.\n  useEffect(() => {\n    if (!hasFiredOnceRef.current && !isNewStory(currentStory)) {\n      dispatchStoryEvent(STORY_EVENTS.onInitialElementAdded);\n      hasFiredOnceRef.current = true;\n    }\n  }, [dispatchStoryEvent, currentStory]);\n\n  return null;\n}\n\nexport { OnInitialElementAddedRegister };\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useRef, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { OnActionProps } from '../../../../types';\nimport { STORY_EVENTS } from './types';\n\nfunction OnPageAddedRegister({\n  currentStory,\n  dispatchStoryEvent,\n}: OnActionProps) {\n  const hasFiredOnceRef = useRef({\n    [STORY_EVENTS.onSecondPageAdded]: false,\n    [STORY_EVENTS.onFifthPageAdded]: false,\n  });\n\n  // Dispatch `onSecondPageAdded` story event once, the first time\n  // the story grows to 2 or more pages.\n  useEffect(() => {\n    if (\n      !hasFiredOnceRef.current[STORY_EVENTS.onSecondPageAdded] &&\n      currentStory?.pages?.length >= 2\n    ) {\n      dispatchStoryEvent(STORY_EVENTS.onSecondPageAdded);\n      hasFiredOnceRef.current[STORY_EVENTS.onSecondPageAdded] = true;\n    }\n  }, [dispatchStoryEvent, currentStory?.pages]);\n\n  // Dispatch `onFifthPageAdded` story event once, the first time\n  // the story grows to 5 or more pages.\n  useEffect(() => {\n    if (\n      !hasFiredOnceRef.current[STORY_EVENTS.onFifthPageAdded] &&\n      currentStory?.pages?.length >= 5\n    ) {\n      dispatchStoryEvent(STORY_EVENTS.onFifthPageAdded);\n      hasFiredOnceRef.current[STORY_EVENTS.onFifthPageAdded] = true;\n    }\n  }, [dispatchStoryEvent, currentStory?.pages]);\n\n  return null;\n}\n\nexport { OnPageAddedRegister };\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/test/onInitialElementAddedRegister.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport {\n  OnInitialElementAddedRegister,\n  isNewStory,\n} from '../onInitialElementAddedRegister';\nimport { STORY_EVENTS } from '../types';\n\ndescribe('OnInitialElementAddedRegister', () => {\n  it('fires onInitialElementAdded once when story is not empty', () => {\n    const dispatchMock = jest.fn();\n    const currentStoryMock = {\n      pages: [{ elements: [{}, {}] }],\n    };\n\n    const { rerender } = render(\n      <OnInitialElementAddedRegister\n        currentStory={currentStoryMock}\n        dispatchStoryEvent={dispatchMock}\n      />\n    );\n\n    // Should fire onInitialElementAdded event once when story starts empty\n    expect(dispatchMock).toHaveBeenCalledOnce();\n    expect(dispatchMock).toHaveBeenCalledWith(\n      STORY_EVENTS.onInitialElementAdded\n    );\n\n    // Should not fire onInitialElementAdded again when updated current story\n    // is also not empty, but onInitialElementAdded has already fired once.\n    rerender(\n      <OnInitialElementAddedRegister\n        currentStory={{ ...currentStoryMock }}\n        dispatchStoryEvent={dispatchMock}\n      />\n    );\n    expect(dispatchMock).toHaveBeenCalledOnce();\n  });\n\n  it('fires onInitialElementAdded once when story first becomes non-empty', () => {\n    const dispatchMock = jest.fn();\n    const emptyStoryMock = {\n      pages: [{ elements: [{ isBackground: true }] }],\n    };\n    const nonEmptyStoryMock = {\n      pages: [{ elements: [{ isBackground: true }, {}] }],\n    };\n\n    const { rerender } = render(\n      <OnInitialElementAddedRegister\n        currentStory={emptyStoryMock}\n        dispatchStoryEvent={dispatchMock}\n      />\n    );\n\n    // Should fire onInitialElementAdded event once when story starts empty\n    expect(dispatchMock).toHaveBeenCalledTimes(0);\n\n    // Should not fire onInitialElementAdded again when updated current story\n    // is also not empty, but onInitialElementAdded has already fired once.\n    rerender(\n      <OnInitialElementAddedRegister\n        currentStory={nonEmptyStoryMock}\n        dispatchStoryEvent={dispatchMock}\n      />\n    );\n    expect(dispatchMock).toHaveBeenCalledOnce();\n    expect(dispatchMock).toHaveBeenCalledWith(\n      STORY_EVENTS.onInitialElementAdded\n    );\n  });\n});\n\ndescribe('isNewStory', () => {\n  it('returns true if there are no pages in story', () => {\n    expect(isNewStory({ pages: [] })).toBeTrue();\n  });\n  it('returns true if there is only one page in the story that only has a background element', () => {\n    expect(\n      isNewStory({ pages: [{ elements: [{ isBackground: true }] }] })\n    ).toBeTrue();\n  });\n  it('returns false if there is more than page', () => {\n    expect(\n      isNewStory({\n        pages: [\n          { elements: [{ isBackground: true }] },\n          { elements: [{ isBackground: true }] },\n        ],\n      })\n    ).toBeFalse();\n  });\n  it('returns false if there is only one page and it has more than just the bg element', () => {\n    expect(\n      isNewStory({\n        pages: [{ elements: [{ isBackground: true }, { id: 'otherElement' }] }],\n      })\n    ).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/test/onPageAddedRegister.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { OnPageAddedRegister } from '../onPageAddedRegister';\nimport { STORY_EVENTS } from '../types';\n\ndescribe('OnPageAddedRegister', () => {\n  describe(`Story event: ${STORY_EVENTS.onSecondPageAdded}`, () => {\n    it('fires onSecondPageAdded if the story starts with more than 1 page', () => {\n      const dispatchMock = jest.fn();\n      const currentStoryMock = {\n        pages: [{ elements: [] }, { elements: [] }, { elements: [] }],\n      };\n\n      render(\n        <OnPageAddedRegister\n          currentStory={currentStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should fire onSecondPageAdded event if story has more than one page\n      expect(dispatchMock).toHaveBeenCalledOnce();\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onSecondPageAdded);\n    });\n\n    it('fires onSecondPageAdded once a story goes from 1 to 2 pages', () => {\n      const dispatchMock = jest.fn();\n      const onePageStoryMock = {\n        pages: [{ elements: [] }],\n      };\n      const twoPageStoryMock = {\n        pages: [{ elements: [] }, { elements: [] }],\n      };\n\n      const { rerender } = render(\n        <OnPageAddedRegister\n          currentStory={onePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should not fire when story is first created with less than 2 pages.\n      expect(dispatchMock).toHaveBeenCalledTimes(0);\n\n      // Should fire onSecondPageAdded when story goes from 1 to 2 pages\n      rerender(\n        <OnPageAddedRegister\n          currentStory={twoPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).toHaveBeenCalledOnce();\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onSecondPageAdded);\n    });\n\n    it('should not fire onSecondPageAdded more than once', () => {\n      const dispatchMock = jest.fn();\n      const onePageStoryMock = {\n        pages: [{ elements: [] }],\n      };\n      const twoPageStoryMock = {\n        pages: [{ elements: [] }, { elements: [] }],\n      };\n\n      const { rerender } = render(\n        <OnPageAddedRegister\n          currentStory={onePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should not fire when story is first created with less than 2 pages.\n      expect(dispatchMock).toHaveBeenCalledTimes(0);\n\n      // Should fire onSecondPageAdded when story goes from 1 to 2 pages\n      rerender(\n        <OnPageAddedRegister\n          currentStory={twoPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).toHaveBeenCalledOnce();\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onSecondPageAdded);\n\n      // going from 1 to 2 pages again will not re-trigger the event\n      rerender(\n        <OnPageAddedRegister\n          currentStory={onePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      rerender(\n        <OnPageAddedRegister\n          currentStory={twoPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).toHaveBeenCalledOnce();\n    });\n  });\n\n  describe(`Story event: ${STORY_EVENTS.onFifthPageAdded}`, () => {\n    it('fires onFifthPageAdded if the story starts with more than 1 page', () => {\n      const dispatchMock = jest.fn();\n      const currentStoryMock = {\n        pages: [\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n        ],\n      };\n\n      render(\n        <OnPageAddedRegister\n          currentStory={currentStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should fire onFifthPageAdded event if story has more than 4 pages\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onFifthPageAdded);\n    });\n\n    it('fires onFifthPageAdded once a story goes from 4 to 5 pages', () => {\n      const dispatchMock = jest.fn();\n      const fourPageStoryMock = {\n        pages: [\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n        ],\n      };\n      const fivePageStoryMock = {\n        pages: [\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n        ],\n      };\n\n      const { rerender } = render(\n        <OnPageAddedRegister\n          currentStory={fourPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should not fire when story is first created with less than 5 pages.\n      expect(dispatchMock).not.toHaveBeenCalledWith(\n        STORY_EVENTS.onFifthPageAdded\n      );\n\n      // Should fire onFifthPageAdded when story goes from 4 to 5 pages\n      rerender(\n        <OnPageAddedRegister\n          currentStory={fivePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onFifthPageAdded);\n    });\n\n    it('should not fire onFifthPageAdded more than once', () => {\n      const dispatchMock = jest.fn();\n      const fourPageStoryMock = {\n        pages: [\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n        ],\n      };\n      const fivePageStoryMock = {\n        pages: [\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n          { elements: [] },\n        ],\n      };\n\n      const { rerender } = render(\n        <OnPageAddedRegister\n          currentStory={fourPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n\n      // Should not fire when story is first created with less than 5 pages.\n      expect(dispatchMock).not.toHaveBeenCalledWith(\n        STORY_EVENTS.onFifthPageAdded\n      );\n\n      // Should fire onFifthPageAdded when story goes from 4 to 5 pages\n      rerender(\n        <OnPageAddedRegister\n          currentStory={fivePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).toHaveBeenCalledWith(STORY_EVENTS.onFifthPageAdded);\n\n      dispatchMock.mockClear();\n\n      // going from 4 to 5 pages again will not re-trigger the event\n      rerender(\n        <OnPageAddedRegister\n          currentStory={fourPageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      rerender(\n        <OnPageAddedRegister\n          currentStory={fivePageStoryMock}\n          dispatchStoryEvent={dispatchMock}\n        />\n      );\n      expect(dispatchMock).not.toHaveBeenCalled();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyEvents/types.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const STORY_EVENTS = {\n  onInitialElementAdded: 'onInitialElementAdded',\n  onSecondPageAdded: 'onSecondPageAdded',\n  onFifthPageAdded: 'onFifthPageAdded',\n  onReplaceBackgroundMedia: 'onReplaceBackgroundMedia',\n  onReplaceForegroundMedia: 'onReplaceForegroundMedia',\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useReducer,\n  useEffect,\n  useMemo,\n  useCallback,\n  createContext,\n} from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { State, StoryTriggersState } from '../../../types';\nimport { STORY_EVENTS, StoryEventRegisters } from './storyEvents';\n\nexport const Context = createContext<StoryTriggersState>([]);\n\ntype Listener = (story?: State) => void;\nfunction createSubscriptionMap(): Record<string, Map<symbol, Listener>> {\n  return Object.values(STORY_EVENTS).reduce(\n    (accum, evenType) => ({\n      ...accum,\n      [evenType]: new Map(),\n    }),\n    {}\n  );\n}\n\ntype StoryTuple = [State, State | null];\nfunction reducer([currentStory]: StoryTuple, updatedStory: State): StoryTuple {\n  return [updatedStory, currentStory];\n}\n\nexport function StoryTriggersProvider({\n  children,\n  story,\n}: PropsWithChildren<{ story: State }>) {\n  // store prev & next versions of story to help compute internally fired events.\n  // Not sure if this is necessarily needed but was used a lot in FTUE. Lets keep\n  // an eye on this as we create more internal event registers, and we can always\n  // remove if we end up not using it.\n  const [[currentStory, previousStory], updateStory] = useReducer(reducer, [\n    story,\n    null,\n  ] as StoryTuple);\n  const subscriptionMap = useMemo(createSubscriptionMap, []);\n\n  // Update story to derive events\n  useEffect(() => updateStory(story), [story]);\n\n  // Method provided to listen to story events\n  // return self cleanup method\n  const addEventListener = useCallback(\n    (eventType: string, listener: Listener) => {\n      const key = Symbol();\n      subscriptionMap[eventType].set(key, listener);\n      return () => subscriptionMap[eventType].delete(key);\n    },\n    [subscriptionMap]\n  );\n\n  // Method to push events into the queue\n  const dispatchStoryEvent = useCallback(\n    (eventType: string) => {\n      subscriptionMap[eventType]?.forEach((listener) => listener(currentStory));\n    },\n    [subscriptionMap, currentStory]\n  );\n\n  // Memoizing provider values\n  const value = useMemo(\n    () => [addEventListener, dispatchStoryEvent],\n    [addEventListener, dispatchStoryEvent]\n  );\n\n  return (\n    <Context.Provider value={value}>\n      <>\n        {\n          // Story event registers used to manage and fire\n          // story events internally. These should only dispatch\n          // events based on current & previous story and internal\n          // react state. Similar to DOM EventTarget API\n          //\n          // If we find ourselves passing more in here\n          // we should probably just be pulling the `dispatchStoryEvent`\n          // method from the provider to dispatch events.\n          StoryEventRegisters.map((StoryEventRegister) => (\n            <StoryEventRegister\n              key={StoryEventRegister.name}\n              currentStory={currentStory}\n              previousStory={previousStory}\n              dispatchStoryEvent={dispatchStoryEvent}\n            />\n          ))\n        }\n        {children}\n      </>\n    </Context.Provider>\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/test/useStoryTriggers.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { useStoryTriggers, StoryTriggersProvider, STORY_EVENTS } from '..';\n\nfunction createProviderWithStory(story) {\n  function ProviderWithStory({ children }) {\n    return (\n      <StoryTriggersProvider story={story}>{children}</StoryTriggersProvider>\n    );\n  }\n  ProviderWithStory.propTypes = {\n    children: PropTypes.node,\n  };\n  return ProviderWithStory;\n}\n\ndescribe('useStoryTriggers', () => {\n  it('provides working dispatch and listener methods for story events', () => {\n    const story = {};\n    const listenerMock = jest.fn();\n    const { result } = renderHook(() => useStoryTriggers(), {\n      wrapper: createProviderWithStory(story),\n    });\n\n    const [addEventListener] = result.current;\n\n    // Should return cleanup method\n    let cleanup;\n    act(() => {\n      cleanup = addEventListener(\n        STORY_EVENTS.onInitialElementAdded,\n        listenerMock\n      );\n    });\n    expect(typeof cleanup).toBe('function');\n\n    // dispatching subscribed event calls all listeners\n    // with current story passed to the provider\n    let [, dispatchStoryEvent] = result.current;\n    dispatchStoryEvent(STORY_EVENTS.onInitialElementAdded);\n    expect(listenerMock).toHaveBeenCalledOnce();\n    expect(listenerMock).toHaveBeenCalledWith(story);\n\n    // dispatching a different story event doesn't call\n    // the listener of another story event\n    dispatchStoryEvent('This is not a supported story event');\n    expect(listenerMock).toHaveBeenCalledOnce();\n\n    // Dispatching an event after a listener\n    // has cleaned up should not call that listener\n    act(() => {\n      cleanup();\n    });\n    dispatchStoryEvent = result.current[1];\n    dispatchStoryEvent(STORY_EVENTS.onInitialElementAdded);\n    expect(listenerMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  identity,\n  useContextSelector,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { Listener, StoryTriggersState } from '../../../types';\nimport { Context } from './storyTriggersProvider';\n\nexport function useStoryTriggers(): StoryTriggersState;\nexport function useStoryTriggers<T>(\n  selector: (state: StoryTriggersState) => T | StoryTriggersState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nfunction getAddEventListener(v: StoryTriggersState) {\n  return v[0];\n}\n\nfunction getDispatch(v: StoryTriggersState) {\n  return v[1];\n}\n\n/**\n * Example usage:\n * ```js\n *  useStoryTriggerListener(\n      STORY_EVENTS.onInitialElementAdded,\n      useCallback((story) => {\n        // do something with new story data\n        // on this event\n      }, [])\n    )\n */\nexport function useStoryTriggerListener(eventType: string, listener: Listener) {\n  const addEventListener = useContextSelector(Context, getAddEventListener);\n  useEffect(\n    () => addEventListener(eventType, listener),\n    [eventType, listener, addEventListener]\n  );\n}\n\n/**\n * Example usage:\n * ```js\n *  const dispatchStoryEvent = useStoryTriggersDispatch();\n *   // later in some effect or action\n *  dispatchStoryEvent(STORY_EVENTS.onInitialElementAdded);\n * ```\n */\nexport function useStoryTriggersDispatch() {\n  return useContextSelector(Context, getDispatch);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { StoryProviderState } from '../../types';\nimport Context from './context';\n\nexport function useStory(): StoryProviderState;\nexport function useStory<T>(selector: (state: StoryProviderState) => T): T;\nexport function useStory<T>(\n  selector: (state: StoryProviderState) => T | StoryProviderState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useStory;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/actions.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Dispatch } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AddAnimationsProps,\n  AddElementsAcrossPagesProps,\n  AddElementProps,\n  AddElementsProps,\n  AddGroupProps,\n  AddPageProps,\n  ArrangeElementProps,\n  ArrangeGroupProps,\n  ArrangePageProps,\n  CombineElementsProps,\n  DeleteElementsByResourceIdProps,\n  DeleteElementsProps,\n  DeleteGroupProps,\n  DeletePageProps,\n  DuplicateElementsByIdProps,\n  DuplicateGroupProps,\n  ReducerActionProps,\n  RemoveElementFromGroupProps,\n  RestoreProps,\n  SelectElementProps,\n  SetBackgroundElementProps,\n  SetCurrentPageProps,\n  SetSelectedElementsProps,\n  ToggleElementInSelectionProps,\n  ToggleLayerProps,\n  UnselectElementProps,\n  UpdateAnimationStateProps,\n  UpdateElementsByFontFamilyProps,\n  UpdateElementsByResourceIdProps,\n  UpdateElementsProps,\n  UpdateGroupProps,\n  UpdatePageProps,\n  UpdateStoryProps,\n} from '../../../types';\nimport { ActionTypes } from './types';\n\nexport type DispatchType = Dispatch<ReducerActionProps>;\n// Exposed actions\nconst addPage =\n  (dispatch: DispatchType) =>\n  ({ page, position, updateSelection }: AddPageProps) =>\n    dispatch({\n      type: ActionTypes.AddPage,\n      payload: { page, position, updateSelection },\n    });\n\nconst addPageAt =\n  (dispatch: DispatchType) =>\n  ({ page, position, updateSelection }: AddPageProps) =>\n    dispatch({\n      type: ActionTypes.AddPage,\n      payload: { page, position, updateSelection },\n    });\n\nconst deletePage =\n  (dispatch: DispatchType) =>\n  ({ pageId }: DeletePageProps) =>\n    dispatch({ type: ActionTypes.DeletePage, payload: { pageId } });\n\nconst deleteCurrentPage = (dispatch: DispatchType) => () =>\n  dispatch({ type: ActionTypes.DeletePage, payload: { pageId: null } });\n\nconst updatePageProperties =\n  (dispatch: DispatchType) =>\n  ({ pageId, properties }: UpdatePageProps) =>\n    dispatch({ type: ActionTypes.UpdatePage, payload: { pageId, properties } });\n\nconst updateCurrentPageProperties =\n  (dispatch: DispatchType) =>\n  ({ properties }: UpdatePageProps) =>\n    dispatch({\n      type: ActionTypes.UpdatePage,\n      payload: { pageId: null, properties },\n    });\n\nconst arrangePage =\n  (dispatch: DispatchType) =>\n  ({ pageId, position }: ArrangePageProps) =>\n    dispatch({ type: ActionTypes.ArrangePage, payload: { pageId, position } });\n\nconst setCurrentPage =\n  (dispatch: DispatchType) =>\n  ({ pageId }: SetCurrentPageProps) =>\n    dispatch({ type: ActionTypes.SetCurrentPage, payload: { pageId } });\n\nconst addElements =\n  (dispatch: DispatchType) =>\n  ({ elements, pageId, updateSelection }: AddElementsProps) =>\n    dispatch({\n      type: ActionTypes.AddElements,\n      payload: { elements, pageId, updateSelection },\n    });\n\nconst addElement =\n  (dispatch: DispatchType) =>\n  ({ element, pageId, updateSelection }: AddElementProps) =>\n    dispatch({\n      type: ActionTypes.AddElements,\n      payload: { elements: [element], pageId, updateSelection },\n    });\n\nconst deleteElementsById =\n  (dispatch: DispatchType) =>\n  ({ elementIds }: DeleteElementsProps) =>\n    dispatch({ type: ActionTypes.DeleteElements, payload: { elementIds } });\n\nconst deleteSelectedElements = (dispatch: DispatchType) => () =>\n  dispatch({ type: ActionTypes.DeleteElements, payload: { elementIds: null } });\n\ninterface DeleteElementProps extends Omit<DeleteElementsProps, 'elementIds'> {\n  elementId: string;\n}\nconst deleteElementById =\n  (dispatch: DispatchType) =>\n  ({ elementId }: DeleteElementProps) =>\n    dispatch({\n      type: ActionTypes.DeleteElements,\n      payload: { elementIds: [elementId] },\n    });\n\nconst updateElementsById =\n  (dispatch: DispatchType) =>\n  ({ elementIds, properties }: UpdateElementsProps) =>\n    dispatch({\n      type: ActionTypes.UpdateElements,\n      payload: { elementIds, properties },\n    });\n\nconst updateElementsByResourceId =\n  (dispatch: DispatchType) =>\n  ({ id, properties }: UpdateElementsByResourceIdProps) =>\n    dispatch({\n      type: ActionTypes.UpdateElementsByResourceId,\n      payload: { id, properties },\n    });\n\nconst deleteElementsByResourceId =\n  (dispatch: DispatchType) =>\n  ({ id }: DeleteElementsByResourceIdProps) =>\n    dispatch({\n      type: ActionTypes.DeleteElementsByResourceId,\n      payload: { id },\n    });\n\ninterface UpdateElementByIdProps extends Omit<\n  UpdateElementsProps,\n  'elementIds'\n> {\n  elementId: string;\n}\nconst updateElementById =\n  (dispatch: DispatchType) =>\n  ({ elementId, properties }: UpdateElementByIdProps) =>\n    dispatch({\n      type: ActionTypes.UpdateElements,\n      payload: { elementIds: [elementId], properties },\n    });\n\nconst duplicateElementsById =\n  (dispatch: DispatchType) =>\n  ({ elementIds }: DuplicateElementsByIdProps) =>\n    dispatch({\n      type: ActionTypes.DuplicateElementsById,\n      payload: { elementIds },\n    });\n\nconst updateSelectedElements =\n  (dispatch: DispatchType) =>\n  ({ properties }: UpdateElementsProps) =>\n    dispatch({\n      type: ActionTypes.UpdateElements,\n      payload: { elementIds: null, properties },\n    });\n\nconst combineElements =\n  (dispatch: DispatchType) =>\n  ({ firstElement, secondId, shouldRetainAnimations }: CombineElementsProps) =>\n    dispatch({\n      type: ActionTypes.CombineElements,\n      payload: { firstElement, secondId, shouldRetainAnimations },\n    });\n\nconst setBackgroundElement =\n  (dispatch: DispatchType) =>\n  ({ elementId }: SetBackgroundElementProps) =>\n    dispatch({\n      type: ActionTypes.SetBackgroundElement,\n      payload: { elementId },\n    });\n\nconst clearBackgroundElement = (dispatch: DispatchType) => () =>\n  dispatch({\n    type: ActionTypes.SetBackgroundElement,\n    payload: { elementId: null },\n  });\n\nconst arrangeElement =\n  (dispatch: DispatchType) =>\n  ({ elementId, position, groupId }: ArrangeElementProps) =>\n    dispatch({\n      type: ActionTypes.ArrangeElement,\n      payload: { elementId, position, groupId },\n    });\n\nconst arrangeGroup =\n  (dispatch: DispatchType) =>\n  ({ groupId, position }: ArrangeGroupProps) =>\n    dispatch({\n      type: ActionTypes.ArrangeGroup,\n      payload: { groupId, position },\n    });\n\nconst arrangeSelection =\n  (dispatch: DispatchType) =>\n  ({ position, groupId }: ArrangeElementProps) =>\n    dispatch({\n      type: ActionTypes.ArrangeElement,\n      payload: { elementId: null, position, groupId },\n    });\n\nconst setSelectedElementsById =\n  (dispatch: DispatchType) =>\n  ({ elementIds, withLinked }: SetSelectedElementsProps) =>\n    dispatch({\n      type: ActionTypes.SetSelectedElements,\n      payload: { elementIds, withLinked },\n    });\n\nconst clearSelection = (dispatch: DispatchType) => () =>\n  dispatch({\n    type: ActionTypes.SetSelectedElements,\n    payload: { elementIds: [] },\n  });\n\nconst addElementToSelection =\n  (dispatch: DispatchType) =>\n  ({ elementId }: SelectElementProps) =>\n    dispatch({ type: ActionTypes.SelectElement, payload: { elementId } });\n\nconst removeElementFromSelection =\n  (dispatch: DispatchType) =>\n  ({ elementId }: UnselectElementProps) =>\n    dispatch({ type: ActionTypes.UnselectElement, payload: { elementId } });\n\nconst toggleElementInSelection =\n  (dispatch: DispatchType) =>\n  ({ elementId, withLinked }: ToggleElementInSelectionProps) =>\n    dispatch({\n      type: ActionTypes.ToggleElementInSelection,\n      payload: { elementId, withLinked },\n    });\n\nconst updateStory =\n  (dispatch: DispatchType) =>\n  ({ properties }: UpdateStoryProps) =>\n    dispatch({ type: ActionTypes.UpdateStory, payload: { properties } });\n\nconst updateAnimationState =\n  (dispatch: DispatchType) =>\n  ({ animationState }: UpdateAnimationStateProps) =>\n    dispatch({\n      type: ActionTypes.UpdateAnimationState,\n      payload: { animationState },\n    });\n\nconst addAnimations =\n  (dispatch: DispatchType) =>\n  ({ animations }: AddAnimationsProps) =>\n    dispatch({ type: ActionTypes.AddAnimations, payload: { animations } });\n\nconst toggleLayer =\n  (dispatch: DispatchType) =>\n  ({ metaKey, shiftKey, elementId, withLinked }: ToggleLayerProps) =>\n    dispatch({\n      type: ActionTypes.ToggleLayer,\n      payload: { metaKey, shiftKey, elementId, withLinked },\n    });\n\nconst copySelectedElement = (dispatch: DispatchType) => () =>\n  dispatch({\n    type: ActionTypes.CopySelectedElement,\n    payload: null,\n  });\n\nconst updateElementsByFontFamily =\n  (dispatch: DispatchType) =>\n  ({ family, properties }: UpdateElementsByFontFamilyProps) =>\n    dispatch({\n      type: ActionTypes.UpdateElementsByFontFamily,\n      payload: { family, properties },\n    });\n\nconst addGroup =\n  (dispatch: DispatchType) =>\n  ({ groupId, name, isLocked }: AddGroupProps) =>\n    dispatch({\n      type: ActionTypes.AddGroup,\n      payload: { groupId, name, isLocked },\n    });\n\nconst updateGroupById =\n  (dispatch: DispatchType) =>\n  ({ groupId, properties }: UpdateGroupProps) =>\n    dispatch({\n      type: ActionTypes.UpdateGroup,\n      payload: { groupId, properties },\n    });\n\nconst deleteGroupById =\n  (dispatch: DispatchType) =>\n  ({ groupId }: DeleteGroupProps) =>\n    dispatch({\n      type: ActionTypes.DeleteGroup,\n      payload: { groupId },\n    });\n\nconst deleteGroupAndElementsById =\n  (dispatch: DispatchType) =>\n  ({ groupId }: DeleteGroupProps) =>\n    dispatch({\n      type: ActionTypes.DeleteGroup,\n      payload: { groupId, includeElements: true },\n    });\n\nconst duplicateGroupById =\n  (dispatch: DispatchType) =>\n  ({ groupId, name, oldGroupId, isLocked }: DuplicateGroupProps) =>\n    dispatch({\n      type: ActionTypes.DuplicateGroup,\n      payload: { groupId, name, oldGroupId, isLocked },\n    });\n\nconst removeElementFromGroup =\n  (dispatch: DispatchType) =>\n  ({ elementId, groupId }: RemoveElementFromGroupProps) =>\n    dispatch({\n      type: ActionTypes.RemoveElementFromGroup,\n      payload: { elementId, groupId },\n    });\n\nconst addElementsAcrossPages =\n  (dispatch: DispatchType) =>\n  ({ elements, page, position }: AddElementsAcrossPagesProps) =>\n    dispatch({\n      type: ActionTypes.AddElementsAcrossPages,\n      payload: { elements, page, position },\n    });\n\nexport const exposedActions = {\n  addPage,\n  addPageAt,\n  copySelectedElement,\n  deletePage,\n  deleteCurrentPage,\n  updatePageProperties,\n  updateCurrentPageProperties,\n  arrangePage,\n  setCurrentPage,\n  addElements,\n  addElement,\n  deleteElementsById,\n  deleteElementById,\n  deleteSelectedElements,\n  updateElementsById,\n  updateElementsByResourceId,\n  deleteElementsByResourceId,\n  updateElementById,\n  duplicateElementsById,\n  updateSelectedElements,\n  combineElements,\n  setBackgroundElement,\n  clearBackgroundElement,\n  arrangeElement,\n  arrangeGroup,\n  arrangeSelection,\n  setSelectedElementsById,\n  clearSelection,\n  addElementToSelection,\n  removeElementFromSelection,\n  toggleElementInSelection,\n  updateAnimationState,\n  addAnimations,\n  updateStory,\n  toggleLayer,\n  updateElementsByFontFamily,\n  addGroup,\n  updateGroupById,\n  deleteGroupById,\n  deleteGroupAndElementsById,\n  duplicateGroupById,\n  removeElementFromGroup,\n  addElementsAcrossPages,\n};\n\n// Internal actions\nconst restore =\n  (dispatch: DispatchType) =>\n  ({ pages, selection, current, story, capabilities }: RestoreProps) =>\n    dispatch({\n      type: ActionTypes.Restore,\n      payload: { pages, selection, current, story, capabilities },\n    });\n\nexport const internalActions = {\n  restore,\n};\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './useStoryReducer';\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { ReducerActionProps, ReducerState } from '../../../types';\nimport { ActionTypes } from './types';\nimport * as reducers from './reducers';\n\n// eslint-disable-next-line complexity -- reducer function, negligible.\nfunction reducer(\n  state: ReducerState,\n  { type, payload }: ReducerActionProps\n): ReducerState {\n  switch (type) {\n    case ActionTypes.AddPage: {\n      return reducers.addPage(state, payload);\n    }\n\n    case ActionTypes.DeletePage: {\n      return reducers.deletePage(state, payload);\n    }\n\n    case ActionTypes.UpdatePage: {\n      return reducers.updatePage(state, payload);\n    }\n\n    case ActionTypes.ArrangePage: {\n      return reducers.arrangePage(state, payload);\n    }\n\n    case ActionTypes.SetCurrentPage: {\n      return reducers.setCurrentPage(state, payload);\n    }\n\n    case ActionTypes.AddElements: {\n      return reducers.addElements(state, payload);\n    }\n\n    case ActionTypes.DeleteElements: {\n      return reducers.deleteElements(state, payload);\n    }\n\n    case ActionTypes.UpdateElements: {\n      return reducers.updateElements(state, payload);\n    }\n\n    case ActionTypes.UpdateElementsByResourceId: {\n      return reducers.updateElementsByResourceId(state, payload);\n    }\n\n    case ActionTypes.DeleteElementsByResourceId: {\n      return reducers.deleteElementsByResourceId(state, payload);\n    }\n\n    case ActionTypes.CombineElements: {\n      return reducers.combineElements(state, payload);\n    }\n\n    case ActionTypes.SetBackgroundElement: {\n      return reducers.setBackgroundElement(state, payload);\n    }\n\n    case ActionTypes.ArrangeElement: {\n      return reducers.arrangeElement(state, payload);\n    }\n\n    case ActionTypes.ArrangeGroup: {\n      return reducers.arrangeGroup(state, payload);\n    }\n\n    case ActionTypes.SetSelectedElements: {\n      return reducers.setSelectedElements(state, payload);\n    }\n\n    case ActionTypes.SelectElement: {\n      return reducers.selectElement(state, payload);\n    }\n\n    case ActionTypes.UnselectElement: {\n      return reducers.unselectElement(state, payload);\n    }\n\n    case ActionTypes.ToggleElementInSelection: {\n      return reducers.toggleElement(state, payload);\n    }\n\n    case ActionTypes.ToggleLayer: {\n      return reducers.toggleLayer(state, payload);\n    }\n\n    case ActionTypes.DuplicateElementsById: {\n      return reducers.duplicateElementsById(state, payload);\n    }\n\n    case ActionTypes.UpdateStory: {\n      return reducers.updateStory(state, payload);\n    }\n\n    case ActionTypes.UpdateAnimationState: {\n      return reducers.updateAnimationState(state, payload);\n    }\n\n    case ActionTypes.AddAnimations: {\n      return reducers.addAnimations(state, payload);\n    }\n\n    case ActionTypes.CopySelectedElement: {\n      return reducers.copySelectedElement(state);\n    }\n\n    case ActionTypes.Restore: {\n      return reducers.restore(state, payload);\n    }\n\n    case ActionTypes.UpdateElementsByFontFamily: {\n      return reducers.updateElementsByFontFamily(state, payload);\n    }\n\n    case ActionTypes.AddGroup: {\n      return reducers.addGroup(state, payload);\n    }\n\n    case ActionTypes.UpdateGroup: {\n      return reducers.updateGroup(state, payload);\n    }\n\n    case ActionTypes.DeleteGroup: {\n      return reducers.deleteGroup(state, payload);\n    }\n\n    case ActionTypes.DuplicateGroup: {\n      return reducers.duplicateGroup(state, payload);\n    }\n\n    case ActionTypes.RemoveElementFromGroup: {\n      return reducers.removeElementFromGroup(state, payload);\n    }\n\n    case ActionTypes.AddElementsAcrossPages: {\n      return reducers.addElementsAcrossPages(state, payload);\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AddAnimationsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { exclusion } from './utils';\n\n/**\n * Add animations to current page.\n *\n * Animations are expected to a be list of element objects with at least an id property.\n * If any animation id already exists on the page, animation is skipped (not even updated).\n * If multiple animations in the new list have the same id, only the latter is used.\n *\n * If animations aren't a list or an empty list (after duplicates have been filtered), nothing happens.\n *\n * Animations will be added to the end of the list of animations on the current page.\n */\nexport const addAnimations = (\n  draft: ReducerStateDraft,\n  { animations }: AddAnimationsProps\n) => {\n  const page = draft.pages.find(({ id }) => id === draft.current);\n\n  if (!page) {\n    return;\n  }\n\n  if (!page.animations) {\n    page.animations = [];\n  }\n  page.animations = page.animations.concat(\n    exclusion(page.animations, animations)\n  );\n};\n\nexport default produce<ReducerState, [AddAnimationsProps]>(addAnimations);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { type Element, elementIs } from '@googleforcreators/elements';\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport { MAX_PRODUCTS_PER_PAGE } from '../../../../constants';\nimport type {\n  AddElementsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { exclusion } from './utils';\n\nconst isNotProduct = (e: Element) => !elementIs.product(e);\n\n/**\n * Add elements to current page.\n *\n * Elements are expected to a be list of element objects with at least an id property.\n * If any element id already exists on the page, element is skipped (not even updated).\n * If multiple elements in the new list have the same id, only the latter is used.\n *\n * If elements aren't a list or an empty list (after duplicates have been filtered), nothing happens.\n *\n * Elements will be added to the front (end) of the list of elements on the current page.\n *\n * Selection is set to be exactly the new elements by default.\n */\nexport const addElements = (\n  draft: ReducerStateDraft,\n  { elements, pageId, updateSelection = true }: AddElementsProps\n) => {\n  const page = draft.pages.find(({ id }) =>\n    pageId ? id === pageId : id === draft.current\n  );\n  if (!page) {\n    return;\n  }\n\n  const newElements = exclusion<Element>(page.elements, elements);\n\n  if (newElements.length === 0) {\n    return;\n  }\n\n  // If an element is added, the id is added to this array\n  const addedIds = [];\n\n  // Always add non-products if any\n  const nonProducts = newElements.filter(isNotProduct);\n  if (nonProducts.length) {\n    page.elements = page.elements.concat(nonProducts);\n    addedIds.push(...nonProducts.map(({ id }) => id));\n  }\n\n  // For products, first filter out products that already exist on the page\n  const newProducts = newElements.filter(elementIs.product);\n  if (newProducts.length) {\n    const currentProducts = page.elements\n      .filter(elementIs.product)\n      .map((e) => e.product.productId);\n\n    const uniqueProducts = newProducts.filter(\n      (e) => !currentProducts.includes(e.product.productId)\n    );\n\n    // Then, if the number of products after adding these would still be within\n    // the limit, add them all, otherwise add none\n    if (\n      currentProducts.length + uniqueProducts.length <=\n      MAX_PRODUCTS_PER_PAGE\n    ) {\n      page.elements = page.elements.concat(uniqueProducts);\n      addedIds.push(...uniqueProducts.map(({ id }) => id));\n    }\n  }\n\n  // If any elements were added, update selection to match the ids of those\n  // but only if inserting on the current page and not opted out.\n  if (addedIds.length > 0 && updateSelection) {\n    draft.selection = addedIds;\n  }\n};\n\nexport default produce<ReducerState, [AddElementsProps]>(addElements);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AddElementsAcrossPagesProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { addPage } from './addPage';\nimport { addElements } from './addElements';\n\n/**\n * Add multiple elements across individual pages.\n *\n * Adds N elements to N pages in the given order.\n *\n * Selection is unchanged afterwards.\n */\nconst addElementsAcrossPages = (\n  draft: ReducerStateDraft,\n  { page, position, elements }: AddElementsAcrossPagesProps\n) => {\n  elements.forEach((element, index) => {\n    // Ensure every newly added page has a unique ID.\n    const pageId = uuidv4();\n    const uniquePage = {\n      ...page,\n      elements: page.elements.map((el) => ({ ...el, id: uuidv4() })),\n      id: pageId,\n    };\n\n    addPage(draft, {\n      page: uniquePage,\n      position: position + index + 1,\n      updateSelection: false,\n    });\n\n    addElements(draft, { elements: [element], pageId, updateSelection: false });\n  });\n};\n\nexport default produce<ReducerState, [AddElementsAcrossPagesProps]>(\n  addElementsAcrossPages\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AddGroupProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Add a group to the current page groups list (id, name).\n */\nexport const addGroup = (\n  draft: ReducerStateDraft,\n  { groupId, name, isLocked = false }: AddGroupProps\n) => {\n  if (!groupId || !name) {\n    return;\n  }\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n\n  if (!page.groups) {\n    page.groups = {};\n  }\n  page.groups[groupId] = { name, isLocked };\n};\n\nexport default produce<ReducerState, [AddGroupProps]>(addGroup);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  AddPageProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { isInsideRange } from './utils';\n\n/**\n * Insert page at the given position.\n *\n * If position is outside bounds or no position given, new page will be inserted after current page.\n *\n * Current page will be updated to point to the newly inserted page.\n *\n * New page must have at least one element, the default background element.\n *\n * Selection is cleared by default.\n */\nexport const addPage = (\n  draft: ReducerStateDraft,\n  { page, position, updateSelection = true }: AddPageProps\n) => {\n  // Ensure new page has at least one element\n  if (!page.elements?.length) {\n    return;\n  }\n\n  const isWithinBounds =\n    position !== null && isInsideRange(position, 0, draft.pages.length);\n  const currentPageIndex = draft.pages.findIndex(\n    ({ id }) => id === draft.current\n  );\n\n  const insertionPoint = isWithinBounds ? position : currentPageIndex + 1;\n\n  draft.pages.splice(insertionPoint, 0, page);\n  if (updateSelection) {\n    draft.current = page.id;\n    draft.selection = [page.elements[0].id];\n  }\n};\n\nexport default produce<ReducerState, [AddPageProps]>(addPage);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ArrangeElementProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { getAbsolutePosition, moveArrayElement } from './utils';\n\n/**\n * Move element in element order on the current page (optionally handle group id when moved in the Layers Panel).\n *\n * If no element is given, check if selection only has one element, and if so, use that.\n * If no element is given and selection is empty or has multiple elements, state is unchanged.\n *\n * If the element does not exist on the current page, state is unchanged.\n *\n * If the element is background element, state is unchanged (you can't reorder the background).\n *\n * Element is given by id and must be moved to the given position.\n * The position can either be a number from 0 to the number of elements, or a string\n * equal to one of the constants: FRONT, BACK, FORWARD, BACKWARD.\n *\n * FRONT is the same as moving to the highest possible number. BACK is the same as moving to 0.\n *\n * FORWARD and BACKWARD is changing the elements relative position by plus or minus 1 respectively.\n *\n * If there is a current background element, both BACK and position 0 is treated as position 1.\n *\n * If element is already at the desired position, state is unchanged.\n *\n * If group is set to a specific id, that id is enforced and will be copied to group.\n * If group is set to null or undefined, group is required to not be present and will be removed.\n * If group is unset or set to false, group will be ignored whether set or not and will not be changed or removed.\n *\n * Selection and current page is unchanged.\n *\n * TODO: Handle multi-element re-order when UX and priority is finalized.\n */\nexport const arrangeElement = (\n  draft: ReducerStateDraft,\n  { elementId, position, groupId = false }: ArrangeElementProps\n) => {\n  if (elementId === null && draft.selection.length !== 1) {\n    return;\n  }\n\n  const idToArrange = elementId !== null ? elementId : draft.selection[0];\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n\n  // Abort if there's less than three elements (nothing to rearrange as first is bg)\n  if (!page || page.elements.length < 3) {\n    return;\n  }\n\n  const currentPosition = page.elements.findIndex(\n    ({ id }) => id === idToArrange\n  );\n\n  if (currentPosition === -1 || page.elements[0].id === idToArrange) {\n    return;\n  }\n\n  const minPosition = 1;\n  const maxPosition = page.elements.length - 1;\n  const newPosition = getAbsolutePosition({\n    currentPosition,\n    minPosition,\n    maxPosition,\n    desiredPosition: position,\n  });\n\n  const currentGroupId = page.elements[currentPosition].groupId;\n\n  // If it's already there, do nothing.\n  if (currentPosition === newPosition && currentGroupId === groupId) {\n    return;\n  }\n\n  // Update group id on current element\n  if (groupId) {\n    // Can only change groups to a group that exists\n    if (!page.groups?.[groupId]) {\n      return;\n    }\n    page.elements[currentPosition].groupId = groupId;\n  } else if (groupId === undefined || groupId === null) {\n    delete page.elements[currentPosition].groupId;\n  }\n\n  // If there are no elements left in the group, remove the group as well.\n  if (currentGroupId) {\n    const groupHasElements = page.elements.some(\n      (e) => e.groupId === currentGroupId\n    );\n    if (!groupHasElements && page.groups) {\n      delete page.groups[currentGroupId];\n    }\n  }\n\n  // Then reorder if relevant\n  page.elements = moveArrayElement(page.elements, currentPosition, newPosition);\n};\n\nexport default produce<ReducerState, [ArrangeElementProps]>(arrangeElement);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport type { Element } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ArrangeGroupProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { getAbsolutePosition } from './utils';\n\n/**\n * Move group to a new position\n */\nexport const arrangeGroup = (\n  draft: ReducerStateDraft,\n  { groupId, position }: ArrangeGroupProps\n) => {\n  if (!groupId) {\n    return;\n  }\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const { elements, groups } = page;\n  const isInGroup = (el: Element) => el.groupId === groupId;\n\n  // If group doesn't exist or doesn't have any elements, abort\n  if (!groups?.[groupId] || !elements.some(isInGroup)) {\n    return;\n  }\n\n  // Find group position in elements array\n  const groupStartIndex = elements.findIndex(isInGroup);\n  const groupEndIndex = elements.findLastIndex(isInGroup);\n  const groupSize = groupEndIndex - groupStartIndex + 1;\n\n  // Splice out the entire group and replace with dummy entry\n  const groupSlice = elements.splice(\n    groupStartIndex,\n    groupSize,\n    'dummy' as unknown as Element\n  );\n\n  // Dummy entry is needed to calculate the new position as if the group is one entry\n  const minPosition = 1;\n  const maxPosition = elements.length - 1;\n  const newPosition = getAbsolutePosition({\n    currentPosition: groupStartIndex,\n    minPosition,\n    maxPosition,\n    desiredPosition: position,\n  });\n\n  // remove the dummy entry\n  elements.splice(elements.indexOf('dummy' as unknown as Element), 1);\n\n  // Insert the new elements at position\n  elements.splice(newPosition, 0, ...groupSlice);\n};\n\nexport default produce<ReducerState, [ArrangeGroupProps]>(arrangeGroup);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ArrangePageProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { isInsideRange, moveArrayElement } from './utils';\n\n/**\n * Move page in page order with the given id to the given position.\n *\n * If new position is outside bounds, nothing happens.\n * If page is already at the new position, nothing happens.\n *\n * Current page remains unchanged (but might have moved in the page order).\n *\n * Current selection is unchanged.\n *\n * TODO: Handle multi-page re-order when UX and priority is finalized.\n */\nexport const arrangePage = (\n  draft: ReducerStateDraft,\n  { pageId, position }: ArrangePageProps\n) => {\n  // Abort if there's less than two elements (nothing to rearrange)\n  if (draft.pages.length < 2) {\n    return;\n  }\n\n  const pageIndex = draft.pages.findIndex(({ id }) => id === pageId);\n  const isTargetWithinBounds = isInsideRange(\n    position,\n    0,\n    draft.pages.length - 1\n  );\n  const isSimilar = pageIndex === position;\n  if (pageIndex === -1 || !isTargetWithinBounds || isSimilar) {\n    return;\n  }\n\n  draft.pages = moveArrayElement(draft.pages, pageIndex, position);\n};\n\nexport default produce<ReducerState, [ArrangePageProps]>(arrangePage);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\nimport { DEFAULT_ATTRIBUTES_FOR_MEDIA } from '@googleforcreators/element-library';\nimport { produce } from 'immer';\nimport type { Element } from '@googleforcreators/elements';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport objectPick from '../../../../utils/objectPick';\nimport objectWithout from '../../../../utils/objectWithout';\nimport type {\n  CombineElementsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { removeAnimationsWithElementIds } from './utils';\n\n/**\n * Combine elements by taking properties from a first item and\n * adding them to the given second item, then remove first item.\n *\n *\n * First item must either to be the id of an existing element with\n * a resource (some media element, or be given as the properties of\n * an element (with a resource) that doesn't exist but whose properties\n * should be merged into the target element.\n *\n * If second item is background element, copy some extra properties not\n * relevant while background, but relevant if unsetting as background.\n *\n * If the second item is the default background element,\n * save a copy of the old element as appropriate and remove flag.\n *\n * Updates selection to only include the second item after merge.\n */\nexport const combineElements = (\n  draft: ReducerStateDraft,\n  {\n    firstElement,\n    secondId,\n    shouldRetainAnimations = true,\n  }: CombineElementsProps\n) => {\n  if (!firstElement || !secondId) {\n    return;\n  }\n  const firstId = firstElement.id;\n  const element = firstElement;\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n\n  const secondElementPosition = page.elements.findIndex(\n    ({ id }) => id === secondId\n  );\n  const secondElement = page.elements[secondElementPosition];\n\n  if (!elementIs.media(element) || !secondElement) {\n    return;\n  }\n\n  if (\n    elementIs.defaultBackground(secondElement) &&\n    secondElement.isDefaultBackground\n  ) {\n    page.defaultBackgroundElement = {\n      ...secondElement,\n      // But generate a new ID for this temp background element\n      id: uuidv4(),\n    };\n  }\n\n  const propsFromFirst = [\n    'alt',\n    'type',\n    'resource',\n    'scale',\n    'focalX',\n    'focalY',\n    'tracks',\n    'poster',\n  ];\n\n  // If the element we're dropping into is not background, maintain link and border.\n  if (elementIs.backgroundable(secondElement) && secondElement.isBackground) {\n    // If we're dropping into background, maintain the flip and overlay, too.\n    // Only copy position properties for backgrounds, as they're ignored while being background\n    // For non-backgrounds, elements should keep original positions from secondElement\n    propsFromFirst.push('flip', 'overlay', 'width', 'height', 'x', 'y');\n  } else {\n    propsFromFirst.push('link');\n    propsFromFirst.push('border');\n    if (canSupportMultiBorder(secondElement)) {\n      propsFromFirst.push('borderRadius');\n    }\n  }\n\n  const newElement = {\n    // First copy everything from existing element except if it was default background\n    ...objectWithout<Element>(secondElement, ['isDefaultBackground']),\n    // Then set sensible default attributes\n    ...(DEFAULT_ATTRIBUTES_FOR_MEDIA as Partial<Element>),\n    // Then copy all relevant attributes from new element\n    ...objectPick(element, propsFromFirst),\n  } as Element;\n\n  // Elements are now\n  page.elements = page.elements\n    // Remove first element if combining from existing id\n    .filter(({ id }) => id !== firstId)\n    // Update reference to second element\n    .map((el) => (el.id === secondId ? newElement : el));\n\n  // First element should always be the image getting applied to\n  // new element. We want to remove any animations it has. Second\n  // element should be an element with or without animations that\n  // we want to retain.\n  //\n  // We want different behavior for copy and paste where we\n  // replace the element's animation with any coming from the\n  // newly pasted element.\n  page.animations = removeAnimationsWithElementIds(\n    page.animations,\n    shouldRetainAnimations ? [firstId] : [firstId, secondId]\n  );\n\n  // Selection is always just second id\n  draft.selection = [secondId];\n};\n\nexport default produce<ReducerState, [CombineElementsProps]>(combineElements);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport objectPick from '../../../../utils/objectPick';\nimport type { ReducerState, ReducerStateDraft } from '../../../../types';\n\nexport const ATTRIBUTES_TO_COPY = [\n  'background',\n  'backgroundColor',\n  'backgroundTextMode',\n  'border',\n  'borderRadius',\n  'content',\n  'flip',\n  'font',\n  'fontSize',\n  'lineHeight',\n  'lockAspectRatio',\n  'opacity',\n  'overlay',\n  'padding',\n  'rotationAngle',\n  'textAlign',\n];\n\n/**\n * Copies the styles and animations of the selected element\n * on the current page.\n */\nexport const copySelectedElement = (draft: ReducerStateDraft) => {\n  // we can only copy one element and it has to exist\n  if (draft.selection?.length !== 1 || !draft.selection[0]) {\n    return;\n  }\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const element = page.elements.find(({ id }) => id === draft.selection[0]);\n  if (!element) {\n    return;\n  }\n\n  // find related animations\n  const elementAnimations = (page.animations || []).filter(({ targets }) =>\n    targets.includes(element.id)\n  );\n\n  // omit properties that must not be copied\n  const copiedStyles = objectPick(\n    element,\n    ATTRIBUTES_TO_COPY\n  ) as Partial<Element>;\n\n  draft.copiedElementState = {\n    animations: elementAnimations,\n    styles: copiedStyles,\n    type: element.type,\n  };\n};\n\nexport default produce<ReducerState, []>(copySelectedElement);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DeleteElementsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { intersect } from './utils';\n\n/**\n * Delete elements by the given list of ids.\n * If given list of ids is `null`, delete all currently selected elements.\n *\n * Elements will be deleted on the current page only.\n *\n * If an element id does not correspond do an element on the current page, id is ignored.\n *\n * If an empty list or a list of only unknown ids is given, state is unchanged.\n *\n * If any id to delete is the current background element, background element will be unset for the page,\n * and default background element will be restored. Default background element cannot be removed.\n *\n * If any id to delete is in current selection, deleted ids are removed from selection.\n * Otherwise selection is unchanged.\n *\n * Current page is unchanged.\n */\nexport const deleteElements = (\n  draft: ReducerStateDraft,\n  { elementIds }: DeleteElementsProps\n) => {\n  const idsToDelete = elementIds === null ? draft.selection : elementIds;\n\n  if (idsToDelete.length === 0) {\n    return;\n  }\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const pageElementIds = page.elements.map(({ id }) => id);\n  const backgroundElement = page.elements[0];\n\n  const isDeletingBackground = idsToDelete.some(\n    (id) => id === backgroundElement.id\n  );\n  const backgroundIsDefault =\n    elementIs.defaultBackground(backgroundElement) &&\n    backgroundElement.isDefaultBackground;\n\n  const validDeletionIds =\n    isDeletingBackground && backgroundIsDefault\n      ? idsToDelete.filter((id) => id !== backgroundElement.id)\n      : idsToDelete;\n\n  // Nothing to delete?\n  const hasAnythingToDelete =\n    intersect(pageElementIds, validDeletionIds).length > 0;\n  if (!hasAnythingToDelete) {\n    return;\n  }\n\n  page.elements = page.elements.filter(\n    (element) => !validDeletionIds.includes(element.id)\n  );\n\n  // Restore default background if non-default bg has been deleted.\n  if (\n    isDeletingBackground &&\n    !backgroundIsDefault &&\n    page.defaultBackgroundElement\n  ) {\n    page.elements.unshift(page.defaultBackgroundElement);\n  }\n\n  // Remove animations associated with elements\n  if (page.animations) {\n    page.animations = page.animations.filter((anim) =>\n      anim.targets.some((elementId) => !validDeletionIds.includes(elementId))\n    );\n  }\n\n  draft.selection = draft.selection.filter(\n    (id) => !validDeletionIds.includes(id)\n  );\n};\n\nexport default produce<ReducerState, [DeleteElementsProps]>(deleteElements);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DeleteElementsByResourceIdProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Delete elements by the given resource id.\n *\n * Contrary to deleteElements this works across all pages, not just the current one.\n *\n * If an empty id or a no matches with id, state is unchanged.\n *\n * If no element with the given resource id is found, state is changed.\n */\nexport const deleteElementsByResourceId = (\n  draft: ReducerStateDraft,\n  { id }: DeleteElementsByResourceIdProps\n) => {\n  if (id === null) {\n    return;\n  }\n\n  const hasElementWithResourceId = draft.pages.some((page) =>\n    page.elements\n      .filter(elementIs.media)\n      .some((element) => element.resource.id === id)\n  );\n\n  if (!hasElementWithResourceId) {\n    return;\n  }\n\n  const deletedElementIds: string[] = [];\n\n  draft.pages.forEach((page) => {\n    const { elements, animations } = page;\n\n    const isDeletingBackground =\n      elementIs.media(elements[0]) && elements[0].resource?.id === id;\n\n    page.elements = elements.filter(elementIs.media).filter((element) => {\n      if (element.resource.id === id) {\n        deletedElementIds.push(element.id);\n        return false;\n      }\n      return true;\n    });\n\n    if (isDeletingBackground && page.defaultBackgroundElement) {\n      page.elements.unshift(page.defaultBackgroundElement);\n    }\n\n    // Remove animations associated with elements\n    if (animations) {\n      page.animations = animations.filter((anim) =>\n        anim.targets.some((elementId) => !deletedElementIds.includes(elementId))\n      );\n    }\n  });\n\n  draft.selection = draft.selection.filter(\n    (selectedId) => !deletedElementIds.includes(selectedId)\n  );\n};\n\nexport default produce<ReducerState, [DeleteElementsByResourceIdProps]>(\n  deleteElementsByResourceId\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DeleteGroupProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { deleteElements } from './deleteElements';\n\n/**\n * Delete group by id.\n */\nconst deleteGroup = produce<ReducerState, [DeleteGroupProps]>(\n  (\n    draft: ReducerStateDraft,\n    { groupId, includeElements = false }: DeleteGroupProps\n  ) => {\n    const page = draft.pages.find(({ id }) => id === draft.current);\n    if (!page) {\n      return;\n    }\n    const { elements, groups } = page;\n    if (!groupId || !groups?.[groupId]) {\n      return;\n    }\n\n    // Delete the group object completely\n    delete groups[groupId];\n\n    // If includeElements is true, remove elements as well\n    // Otherwise just unset groupId on elements\n    const groupElements = elements.filter((el) => el.groupId === groupId);\n    if (includeElements) {\n      const elementIds = groupElements.map(({ id }) => id);\n      deleteElements(draft, { elementIds });\n    } else {\n      groupElements.forEach((el) => {\n        delete el.groupId;\n      });\n    }\n  }\n);\n\nexport default deleteGroup;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DeletePageProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Delete page by id or delete current page if no id given.\n *\n * If another page than current page is deleted, it will remain current page.\n *\n * If the current page is deleted, the next page will become current.\n * If no next page, previous page will become current.\n *\n * If state only has one or zero pages, nothing happens.\n *\n * If a page is deleted, selection is cleared.\n */\nexport const deletePage = (\n  draft: ReducerStateDraft,\n  { pageId }: DeletePageProps\n) => {\n  if (draft.pages.length <= 1) {\n    return;\n  }\n\n  const idToDelete = pageId === null ? draft.current : pageId;\n\n  const pageIndex = draft.pages.findIndex(({ id }) => id === idToDelete);\n  if (pageIndex === -1) {\n    return;\n  }\n\n  draft.pages.splice(pageIndex, 1);\n\n  if (idToDelete === draft.current) {\n    // New current page is at the same index unless it's off the end of the array\n    const newCurrentIndex = Math.min(draft.pages.length - 1, pageIndex);\n    draft.current = draft.pages[newCurrentIndex].id;\n  }\n\n  draft.selection = [];\n};\n\nexport default produce<ReducerState, [DeletePageProps]>(deletePage);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  duplicateElement,\n  elementIs,\n  ElementType,\n} from '@googleforcreators/elements';\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DuplicateElementsByIdProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Duplicate all elements specified by `elementIds` on the current page.\n * Set selected elements to be the newly created elements.\n *\n * If given `elementIds` are not a list, do nothing.\n */\nexport const duplicateElementsById = (\n  draft: ReducerStateDraft,\n  { elementIds }: DuplicateElementsByIdProps\n) => {\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  let hasDeletedSomething = false;\n\n  elementIds.forEach((elementId) => {\n    const elementIndex = page.elements.findIndex(({ id }) => id === elementId);\n\n    if (elementIndex < 0) {\n      return;\n    }\n\n    const elementToDuplicate = page.elements[elementIndex];\n\n    if (\n      elementIs.backgroundable(elementToDuplicate) &&\n      elementToDuplicate.isBackground\n    ) {\n      return;\n    }\n\n    if (elementToDuplicate.type === ElementType.Product) {\n      return;\n    }\n    const { element, elementAnimations } = duplicateElement({\n      element: elementToDuplicate,\n      animations: page.animations,\n      currentElements: page?.elements,\n    });\n\n    if (!hasDeletedSomething) {\n      hasDeletedSomething = true;\n      draft.selection = [];\n    }\n\n    draft.selection.push(element.id);\n\n    if (page.animations) {\n      page.animations = page.animations.concat(elementAnimations);\n    }\n    page.elements.splice(elementIndex + 1, 0, element);\n  });\n};\n\nexport default produce<ReducerState, [DuplicateElementsByIdProps]>(\n  duplicateElementsById\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { duplicateElement, elementIs } from '@googleforcreators/elements';\nimport type { Element } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  DuplicateGroupProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { addGroup } from './addGroup';\n\n/**\n * Duplicate group with all elements on the current page.\n * Set selected elements to be the newly created group.\n */\nexport const duplicateGroup = (\n  draft: ReducerStateDraft,\n  { oldGroupId, groupId, name, isLocked }: DuplicateGroupProps\n) => {\n  if (!oldGroupId || !groupId || !name) {\n    return;\n  }\n\n  // Check that old group exists\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page?.groups?.[oldGroupId]) {\n    return;\n  }\n\n  // Check that old group has members\n  const isInGroup = (el: Element) => el.groupId === oldGroupId;\n  const members = page.elements.filter(isInGroup);\n  if (!members.length) {\n    return;\n  }\n\n  // Check that old group doesn't include background\n  if (\n    members\n      .filter(elementIs.backgroundable)\n      .some((element) => element.isBackground)\n  ) {\n    return;\n  }\n\n  // Add group\n  addGroup(draft, { groupId, name, isLocked });\n\n  // Create a list of the new elements to insert\n  const newElements = members.map((oldElement) => {\n    const { element, elementAnimations } = duplicateElement({\n      element: oldElement,\n      animations: page.animations,\n    });\n\n    element.groupId = groupId;\n\n    if (elementAnimations.length && page.animations) {\n      page.animations.push(...elementAnimations);\n    }\n\n    return element;\n  });\n\n  // Insert the new elements at the right position\n  const lastIndexOfOldGroup = page.elements.findLastIndex(isInGroup);\n  page.elements.splice(lastIndexOfOldGroup + 1, 0, ...newElements);\n\n  draft.selection = newElements.map(({ id }) => id);\n};\n\nexport default produce<ReducerState, [DuplicateGroupProps]>(duplicateGroup);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Manipulate pages.\nexport { default as addPage } from './addPage';\nexport { default as deletePage } from './deletePage';\nexport { default as updatePage } from './updatePage';\nexport { default as arrangePage } from './arrangePage';\n\n// Manipulate elements on a page.\nexport { default as addElements } from './addElements';\nexport { default as deleteElements } from './deleteElements';\nexport { default as updateElements } from './updateElements';\nexport { default as updateElementsByResourceId } from './updateElementsByResourceId';\nexport { default as deleteElementsByResourceId } from './deleteElementsByResourceId';\nexport { default as setBackgroundElement } from './setBackgroundElement';\nexport { default as arrangeElement } from './arrangeElement';\nexport { default as arrangeGroup } from './arrangeGroup';\nexport { default as combineElements } from './combineElements';\nexport { default as duplicateElementsById } from './duplicateElementsById';\nexport { default as copySelectedElement } from './copySelectedElement';\nexport { default as updateElementsByFontFamily } from './updateElementsByFontFamily';\n\n// Manipulate current page.\nexport { default as setCurrentPage } from './setCurrentPage';\n\n// Manipulate list of selected elements.\nexport { default as setSelectedElements } from './setSelectedElements';\nexport { default as selectElement } from './selectElement';\nexport { default as unselectElement } from './unselectElement';\nexport { default as toggleElement } from './toggleElement';\nexport { default as toggleLayer } from './toggleLayer';\n\n// Manipulate animation state\nexport { default as updateAnimationState } from './updateAnimationState';\nexport { default as addAnimations } from './addAnimations';\n\n// Manipulate entire internal state.\nexport { default as restore } from './restore';\n\n// Manipulate story-global properties.\nexport { default as updateStory } from './updateStory';\n\n// Layer groups.\nexport { default as addGroup } from './addGroup';\nexport { default as updateGroup } from './updateGroup';\nexport { default as deleteGroup } from './deleteGroup';\nexport { default as duplicateGroup } from './duplicateGroup';\nexport { default as removeElementFromGroup } from './removeElementFromGroup';\n\n// Video segmentation.\nexport { default as addElementsAcrossPages } from './addElementsAcrossPages';\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  RemoveElementFromGroupProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { arrangeElement } from './arrangeElement';\nimport { getLastIndexOfGroup } from './utils';\n\n/**\n * Remove element from group.\n */\nexport const removeElementFromGroup = (\n  draft: ReducerStateDraft,\n  { elementId, groupId }: RemoveElementFromGroupProps\n) => {\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const { elements } = page;\n  const element = elements.find(({ id }) => id === elementId);\n  if (!element || element.groupId !== groupId) {\n    return;\n  }\n\n  // Find out where to move the element to\n  const position = getLastIndexOfGroup({ elements, groupId });\n\n  // Only then delete the group id property\n  delete element.groupId;\n\n  // If already at last index of group, nothing left to do\n  if (elements[position] === element) {\n    return;\n  }\n\n  // Otherwise move\n  arrangeElement(draft, { elementId, position });\n};\n\nexport default produce<ReducerState, [RemoveElementFromGroupProps]>(\n  removeElementFromGroup\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport type { Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  RestoreProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Restore internal state completely from given state.\n *\n * Some validation is performed:\n *\n * - `pages` must be an array (if not, nothing happens).\n * - `current` must point to a legal page, if at least one page exists.\n * - `selection` is an array.\n * - `story` is an object.\n */\nexport const restore = (\n  draft: ReducerStateDraft,\n  { pages, current, selection, story, capabilities }: RestoreProps\n): ReducerState | undefined => {\n  if (!Array.isArray(pages) || pages.length === 0) {\n    return undefined;\n  }\n\n  const newStory = typeof story === 'object' ? story : ({} as Story);\n  const newCapabilities = typeof capabilities === 'object' ? capabilities : {};\n  const oldCurrent = current ?? draft.current;\n  const newCurrent = pages.some(({ id }) => id === oldCurrent)\n    ? oldCurrent\n    : pages[0].id;\n  const newSelection = Array.isArray(selection) ? selection : [];\n\n  return {\n    pages,\n    current: newCurrent,\n    selection: newSelection,\n    story: newStory,\n    animationState: draft.animationState,\n    capabilities: newCapabilities,\n    copiedElementState: {},\n  };\n};\n\nexport default produce<ReducerState, [RestoreProps]>(restore);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  SelectElementProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Add the given id to the current selection.\n *\n * If no id is given or id is already in the current selection, nothing happens.\n */\nexport const selectElement = (\n  draft: ReducerStateDraft,\n  { elementId }: SelectElementProps\n) => {\n  if (draft.selection.includes(elementId)) {\n    return;\n  }\n\n  const currentPage = draft.pages.find(({ id }) => id === draft.current);\n  if (!currentPage) {\n    return;\n  }\n  const byId = (i: string) => currentPage.elements.find(({ id }) => id === i);\n  const isBackgroundElement = currentPage.elements[0].id === elementId;\n  const element = byId(elementId);\n  const isVideoPlaceholder =\n    element && elementIs.media(element) && element.resource?.isPlaceholder;\n  const hasExistingSelection = draft.selection.length > 0;\n\n  // The bg element can't be added to non-empty selection.\n  // Same goes for video elements with placeholder resources.\n  if ((isBackgroundElement || isVideoPlaceholder) && hasExistingSelection) {\n    return;\n  }\n\n  // If background element or locked element was already the (only) selection,\n  // or the new element is locked, set selection to new element only\n  const isLockedElement = element?.isLocked;\n  const wasBackground = draft.selection.includes(currentPage.elements[0].id);\n  const wasLockedElement = draft.selection.some((id) => byId(id)?.isLocked);\n  if (wasBackground || isLockedElement || wasLockedElement) {\n    draft.selection = [elementId];\n  } else {\n    draft.selection.push(elementId);\n  }\n};\n\nexport default produce<ReducerState, [SelectElementProps]>(selectElement);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs, type Element } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  SetBackgroundElementProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { moveArrayElement, removeAnimationsWithElementIds } from './utils';\n\n/**\n * Set background element on the current page to element matching the given id.\n *\n * If element id is null, default background element is restored.\n *\n * If page had a background element before, that element is removed!\n * If that element was the default background element, it will be remembered as such.\n * If the removed background element was in selection, selection is cleared.\n *\n * Default background element can never be \"set to nothing\" - only replaced by another\n * element.\n */\nexport const setBackgroundElement = (\n  draft: ReducerStateDraft,\n  { elementId }: SetBackgroundElementProps\n) => {\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const currentBackgroundElement = page.elements[0];\n\n  // If new id is null, clear background attribute and proceed\n  if (elementId === null) {\n    if (\n      elementIs.defaultBackground(currentBackgroundElement) &&\n      currentBackgroundElement.isDefaultBackground\n    ) {\n      // Nothing to do here, we can't unset default background\n      return;\n    }\n\n    // Unset isBackground for the element, too.\n    page.elements.filter(elementIs.backgroundable).forEach((element) => {\n      delete element.isBackground;\n    });\n    if (page.defaultBackgroundElement) {\n      page.elements.unshift(page.defaultBackgroundElement);\n      draft.selection = [page.defaultBackgroundElement.id];\n    }\n  } else {\n    // Does the element even exist or is it already background\n    const elementPosition = page.elements.findIndex(\n      ({ id }) => id === elementId\n    );\n    const isBackground = elementPosition === 0;\n    const exists = elementPosition !== -1;\n    if (!exists || isBackground) {\n      return;\n    }\n\n    // If current bg is default, save it as such\n    const wasDefault =\n      elementIs.defaultBackground(currentBackgroundElement) &&\n      currentBackgroundElement.isDefaultBackground;\n    if (wasDefault) {\n      page.defaultBackgroundElement = currentBackgroundElement;\n    }\n\n    // Slice first element out and update position\n    page.elements.splice(0, 1);\n    const currentPosition = elementPosition - 1;\n\n    // Also remove old element from selection\n    if (draft.selection.includes(currentBackgroundElement.id)) {\n      draft.selection = draft.selection.filter(\n        (id) => id !== currentBackgroundElement.id\n      );\n    }\n\n    // Reorder elements and set element opacity to 100% because backgrounds\n    // cannot be transparent.\n    page.elements = moveArrayElement(\n      page.elements,\n      currentPosition,\n      0\n    ) as unknown as Element[];\n    page.elements.forEach((element) => {\n      // Set isBackground for the element.\n      if (element.id === elementId && elementIs.backgroundable(element)) {\n        element.isBackground = true;\n        if (Object.prototype.hasOwnProperty.call(element, 'opacity')) {\n          element.opacity = 100;\n        }\n\n        // See https://github.com/GoogleForCreators/web-stories-wp/issues/12778.\n        element.isHidden = false;\n      }\n    });\n\n    //  remove new element from selection if there's more than one element there\n    if (draft.selection.includes(elementId) && draft.selection.length > 1) {\n      draft.selection = draft.selection.filter((id) => id !== elementId);\n    }\n  }\n\n  // Remove any applied background animations\n  // or existing element animations.\n  const backgroundElement = page.elements.find(\n    (element) => elementIs.backgroundable(element) && element.isBackground\n  );\n  if (backgroundElement) {\n    page.animations = removeAnimationsWithElementIds(page.animations, [\n      elementId as string,\n      backgroundElement.id,\n    ]);\n  }\n};\n\nexport default produce<ReducerState, [SetBackgroundElementProps]>(\n  setBackgroundElement\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  SetCurrentPageProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Set current page to the given id.\n *\n * If id doesn't match an existing page, nothing happens.\n *\n * If page is changed, selection is cleared\n */\nexport const setCurrentPage = (\n  draft: ReducerStateDraft,\n  { pageId }: SetCurrentPageProps\n) => {\n  const pageExists = draft.pages.some(({ id }) => id === pageId);\n  const pageIsAlreadyCurrent = draft.current === pageId;\n  if (!pageExists || pageIsAlreadyCurrent) {\n    return;\n  }\n\n  draft.current = pageId;\n  draft.selection = [];\n};\n\nexport default produce<ReducerState, [SetCurrentPageProps]>(setCurrentPage);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\nimport { elementIs } from '@googleforcreators/elements';\nimport { produce, current } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  SetSelectedElementsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { intersect } from './utils';\n\n/**\n * Set selected elements to the given list of ids.\n *\n * If given `elementIds` is not a list, do nothing.\n *\n * If given list matches (ignoring permutations) the current selection,\n * nothing happens.\n *\n * Duplicates will be removed from the given list of element ids.\n *\n * Locked elements can never be part of a multi-selection, so remove those if so.\n *\n * Current page and pages are unchanged.\n */\nexport const setSelectedElements = (\n  draft: ReducerStateDraft,\n  { elementIds, withLinked = false }: SetSelectedElementsProps\n) => {\n  const newElementIds =\n    typeof elementIds === 'function'\n      ? elementIds(current(draft.selection))\n      : elementIds;\n\n  if (!Array.isArray(newElementIds)) {\n    return;\n  }\n\n  const currentPage = draft.pages.find(({ id }) => id === draft.current);\n  if (!currentPage) {\n    return;\n  }\n  let allIds = newElementIds;\n\n  if (withLinked) {\n    const elements = currentPage.elements.filter(({ id }) =>\n      newElementIds.includes(id)\n    );\n    const groupIds = elements.map(({ groupId }) => groupId).filter(Boolean);\n    const elementsFromGroups = currentPage.elements.filter(({ groupId }) =>\n      groupIds.includes(groupId)\n    );\n    const elementsIdsFromGroups = elementsFromGroups.map(({ id }) => id);\n    allIds = allIds.concat(elementsIdsFromGroups);\n  }\n\n  const uniqueElementIds = [...new Set(allIds)];\n\n  // They can only be similar if they have the same length\n  if (draft.selection.length === uniqueElementIds.length) {\n    // If intersection of the two lists has the same length as the old list,\n    // nothing will change.\n    // NB: this assumes selection is always without duplicates.\n    const commonElements = intersect(draft.selection, uniqueElementIds);\n    if (commonElements.length === draft.selection.length) {\n      return;\n    }\n  }\n\n  // If it's a non-group multi-selection, filter out the background element,\n  // locked elements, and video placeholders.\n  const byId = (id: string) =>\n    currentPage.elements.find(({ id: i }) => i === id);\n  const isMultiSelection = uniqueElementIds.length > 1;\n  const isGroupSelection = withLinked;\n  const isNotBackgroundElement = (id: string) =>\n    currentPage.elements[0].id !== id;\n  const isLockedElement = (id: string) => byId(id)?.isLocked;\n  const isVideoPlaceholder = (id: string) => {\n    const e = byId(id);\n    return e && elementIs.media(e) && e.resource?.isPlaceholder;\n  };\n  const newSelection =\n    isMultiSelection && !isGroupSelection\n      ? uniqueElementIds.filter(\n          (id) =>\n            isNotBackgroundElement(id) &&\n            !isVideoPlaceholder(id) &&\n            !isLockedElement(id)\n        )\n      : uniqueElementIds;\n\n  draft.animationState = StoryAnimationState.Reset;\n  draft.selection = newSelection;\n};\n\nexport default produce<ReducerState, [SetSelectedElementsProps]>(\n  setSelectedElements\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/test/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  intersect,\n  isInsideRange,\n  moveArrayElement,\n  getAbsolutePosition,\n  removeAnimationsWithElementIds,\n  updateAnimations,\n  removeDuplicates,\n  exclusion,\n  getLastIndexOfGroup,\n} from '../utils';\nimport { LayerDirection } from '../../../../../constants';\n\nconst ABC = ['A', 'B', 'C'];\nconst BCD = ['B', 'C', 'D'];\nconst ABCD = ['A', 'B', 'C', 'D'];\nconst D = ['D'];\n\ndescribe('intersect', () => {\n  it('should return first element if only one given', () => {\n    const result = intersect(ABC);\n\n    expect(result).toStrictEqual(ABC);\n  });\n\n  it('should return intersection set if multiple elements given', () => {\n    const shouldBeBC = intersect(ABC, BCD);\n    expect(shouldBeBC).toStrictEqual(['B', 'C']);\n\n    const shouldBeD = intersect(ABCD, BCD, D);\n    expect(shouldBeD).toStrictEqual(['D']);\n\n    const shouldBeEmpty = intersect(ABC, BCD, D);\n    expect(shouldBeEmpty).toStrictEqual([]);\n  });\n});\n\ndescribe('isInsideRange', () => {\n  it('should function as expected', () => {\n    const isSingleDigit = (number) => isInsideRange(number, 0, 9);\n\n    expect(isSingleDigit(0)).toBeTrue();\n    expect(isSingleDigit(3.2)).toBeTrue();\n    expect(isSingleDigit(9)).toBeTrue();\n\n    expect(isSingleDigit(-0.1)).toBeFalse();\n    expect(isSingleDigit(10)).toBeFalse();\n\n    expect(isSingleDigit(Number.POSITIVE_INFINITY)).toBeFalse();\n    expect(isSingleDigit(Number.NEGATIVE_INFINITY)).toBeFalse();\n    expect(isSingleDigit(Number.NaN)).toBeFalse();\n  });\n});\n\ndescribe('moveArrayElement', () => {\n  it('should move element forwards', () => {\n    // Move B from being 2nd in the array (position 1) to being 3rd (position 2)\n    const result = moveArrayElement(ABCD, 1, 2);\n    expect(result).toStrictEqual(['A', 'C', 'B', 'D']);\n  });\n\n  it('should move element backwards', () => {\n    // Move C from being 3rd (position 2) to being 2nd (position 1)\n    const result = moveArrayElement(ABCD, 2, 1);\n    expect(result).toStrictEqual(['A', 'C', 'B', 'D']);\n  });\n\n  it('should not allow to move element outside of range', () => {\n    // Move C from being 3rd (position 2) to being last (position 3+)\n    const firstResult = moveArrayElement(ABCD, 2, 100);\n    expect(firstResult).toStrictEqual(['A', 'B', 'D', 'C']);\n\n    // Move C from being 3rd (position 2) to being first (position 0-)\n    const secondResult = moveArrayElement(ABCD, 2, -100);\n    expect(secondResult).toStrictEqual(['C', 'A', 'B', 'D']);\n  });\n});\n\ndescribe('getAbsolutePosition', () => {\n  it('should return clamped number', () => {\n    const resultWithinLimits = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: 11,\n    });\n    expect(resultWithinLimits).toBe(11);\n\n    const resultBelowLimit = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: -3,\n    });\n    expect(resultBelowLimit).toBe(0);\n\n    const resultAboveLimit = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: 33,\n    });\n    expect(resultAboveLimit).toBe(20);\n  });\n\n  it('should return top and bottom limit', () => {\n    const resultToBack = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Back,\n    });\n    expect(resultToBack).toBe(0);\n\n    const resultToFront = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Front,\n    });\n    expect(resultToFront).toBe(20);\n  });\n\n  it('should return relative position', () => {\n    const resultGoingBackward = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Backward,\n    });\n    expect(resultGoingBackward).toBe(9);\n\n    const resultGoingBelow = getAbsolutePosition({\n      currentPosition: 0,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Backward,\n    });\n    expect(resultGoingBelow).toBe(0);\n\n    const resultGoingForward = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Forward,\n    });\n    expect(resultGoingForward).toBe(11);\n\n    const resultGoingAbove = getAbsolutePosition({\n      currentPosition: 20,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: LayerDirection.Forward,\n    });\n    expect(resultGoingAbove).toBe(20);\n  });\n\n  it('should ignore invalid input', () => {\n    const resultGoingBackward = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: 'OFF_THE_CHARTS',\n    });\n    expect(resultGoingBackward).toBe(10);\n\n    const resultGoingForward = getAbsolutePosition({\n      currentPosition: 10,\n      minPosition: 0,\n      maxPosition: 20,\n      desiredPosition: [15],\n    });\n    expect(resultGoingForward).toBe(10);\n  });\n});\n\ndescribe('removeAnimationsWithElementIds', () => {\n  it('should return an empty array if no animations passed in', () => {\n    expect(removeAnimationsWithElementIds()).toStrictEqual([]);\n  });\n\n  it('should return all animations if no ids passed in', () => {\n    const animations = [{ id: 'a', targets: ['e1'] }];\n    expect(removeAnimationsWithElementIds(animations)).toStrictEqual(\n      animations\n    );\n  });\n\n  it('should filter out animations with matching ids', () => {\n    const animations = [\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n    ];\n    expect(removeAnimationsWithElementIds(animations, ['e1'])).toStrictEqual([\n      { id: 'b', targets: ['e2'] },\n    ]);\n  });\n});\n\ndescribe('updateAnimations', () => {\n  it('should return original if no updates requested', () => {\n    const animations = [\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n    ];\n    const updates = {};\n    expect(updateAnimations(animations, updates)).toStrictEqual(animations);\n  });\n  it('should delete animations if requested', () => {\n    const animations = [\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n    ];\n    const updates = { b: { delete: true } };\n    expect(updateAnimations(animations, updates)).toStrictEqual([\n      { id: 'a', targets: ['e1'] },\n      { id: 'c', targets: ['e1'] },\n    ]);\n  });\n  it('should modify animations if requested', () => {\n    const animations = [\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n    ];\n    const updates = { b: { id: 'b', targets: ['e2'], newProp: 'x' } };\n    expect(updateAnimations(animations, updates)).toStrictEqual([\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'], newProp: 'x' },\n      { id: 'c', targets: ['e1'] },\n    ]);\n  });\n  it('should add animations if requested', () => {\n    const animations = [\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n    ];\n    const updates = { d: { id: 'd', targets: ['e3'] } };\n    expect(updateAnimations(animations, updates)).toStrictEqual([\n      { id: 'a', targets: ['e1'] },\n      { id: 'b', targets: ['e2'] },\n      { id: 'c', targets: ['e1'] },\n      { id: 'd', targets: ['e3'] },\n    ]);\n  });\n});\n\ndescribe('removeDuplicates', () => {\n  it('should return an empty array if nothing passed in', () => {\n    expect(removeDuplicates()).toStrictEqual([]);\n  });\n});\n\ndescribe('exclusion', () => {\n  it('should return entries from right not present in left', () => {\n    const left = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];\n    const right = [{ id: 'a' }, { id: 'd' }, { id: 'e' }];\n    expect(exclusion(left, right)).toStrictEqual([{ id: 'd' }, { id: 'e' }]);\n  });\n\n  it('should return only last instance of entries with duplicate keys', () => {\n    const left = [];\n    const right = [\n      { id: 'a', prop: 1 },\n      { id: 'a', prop: 2 },\n      { id: 'a', prop: 3 },\n    ];\n    expect(exclusion(left, right)).toStrictEqual([{ id: 'a', prop: 3 }]);\n  });\n\n  it('should return an empty array if no new entries present', () => {\n    const left = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];\n    const right = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];\n    expect(exclusion(left, right)).toStrictEqual([]);\n  });\n\n  it('should return an empty array if nothing passed in', () => {\n    expect(exclusion()).toStrictEqual([]);\n  });\n});\n\ndescribe('getLastIndexOfGroup', () => {\n  it('should calculate the last position of a group', () => {\n    const elements = [\n      { id: 'e1', isBackground: true },\n      { id: 'e2' },\n      { id: 'e3', groupId: 'g1' },\n      { id: 'e4', groupId: 'g1' },\n      { id: 'e5', groupId: 'g1' },\n      { id: 'e6', groupId: 'g1' },\n      { id: 'e7', groupId: 'g1' }, // <-- 6th index\n      { id: 'e8' },\n      { id: 'e9', groupId: 'g2' },\n      { id: 'e10', groupId: 'g2' }, // <-- 9th index\n    ];\n\n    expect(getLastIndexOfGroup({ elements, groupId: 'g1' })).toBe(6);\n    expect(getLastIndexOfGroup({ elements, groupId: 'g2' })).toBe(9);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ToggleElementInSelectionProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Toggle element id in selection.\n *\n * If the given id is currently selected, remove it from selection.\n *\n * Otherwise add the given id to the current selection.\n *\n * If old selection was a single element, that is locked, and/or if new\n * element is locked, create new selection of only the new element.\n *\n * If no id is given, do nothing.\n */\nexport const toggleElement = (\n  draft: ReducerStateDraft,\n  { elementId, withLinked = false }: ToggleElementInSelectionProps\n) => {\n  if (!elementId) {\n    return;\n  }\n\n  const currentPage = draft.pages.find(({ id }) => id === draft.current);\n  if (!currentPage) {\n    return;\n  }\n  const backgroundElementId = currentPage.elements[0].id;\n  const isBackgroundElement = backgroundElementId === elementId;\n  const hasExistingSelection = draft.selection.length > 0;\n\n  const elementGroupId = currentPage.elements.find(\n    ({ id }) => id === elementId\n  )?.groupId;\n  let allIds = [elementId];\n\n  if (elementGroupId && withLinked) {\n    const elementsFromGroups = currentPage.elements.filter(\n      ({ groupId }) => elementGroupId === groupId\n    );\n    const elementsIdsFromGroups = elementsFromGroups.map(({ id }) => id);\n    const selectionWithGroups = draft.selection.concat(elementsIdsFromGroups);\n    allIds = allIds.concat(selectionWithGroups);\n  }\n\n  // If it wasn't selected, we're adding the element(s) to the selection.\n  const wasSelected = draft.selection.includes(elementId);\n  if (!wasSelected) {\n    // The bg element can't be added to non-empty selection\n    if (isBackgroundElement && hasExistingSelection) {\n      return;\n    }\n\n    // The resulting selection will be only the new element under three circumstances:\n    // * if old selection was just the background element\n    // * if old selection was just a locked element\n    // * if new selection is a locked element\n    const selectionWasOnlyBackground =\n      draft.selection.includes(backgroundElementId);\n    const getElementById = (byId: string) =>\n      currentPage.elements.find(({ id }) => id === byId);\n    const oldElementIsLocked =\n      draft.selection.length > 0\n        ? getElementById(draft.selection[0])?.isLocked\n        : false;\n    const newElement = getElementById(elementId);\n    const resultIsOnlyNewElement =\n      selectionWasOnlyBackground || oldElementIsLocked || newElement?.isLocked;\n\n    // If either of those, return a selection with only the new element(s)\n    if (resultIsOnlyNewElement) {\n      draft.selection = allIds;\n      return;\n    }\n\n    // Otherwise add the new element(s) to the existing selection and make unique\n    draft.selection = [...new Set(draft.selection.concat(allIds))];\n    return;\n  }\n\n  // Otherwise we're removing from selection, so just filter out from current selection\n  draft.selection = draft.selection.filter((id) => !allIds.includes(id));\n};\n\nexport default produce<ReducerState, [ToggleElementInSelectionProps]>(\n  toggleElement\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ToggleLayerProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { toggleElement } from './toggleElement';\nimport { setSelectedElements } from './setSelectedElements';\n\nexport const toggleLayer = (\n  draft: ReducerStateDraft,\n  { elementId, metaKey, shiftKey, withLinked = false }: ToggleLayerProps\n) => {\n  // Meta pressed. Toggle this layer in the selection.\n  if (metaKey) {\n    toggleElement(draft, { elementId, withLinked });\n    return;\n  }\n\n  // No special key pressed - just selected this layer and nothing else.\n  if (draft.selection.length <= 0 || !shiftKey) {\n    setSelectedElements(draft, {\n      elementIds: [elementId],\n      withLinked,\n    });\n    return;\n  }\n\n  // Shift key pressed with any element selected:\n  // select everything between this layer and the first selected layer\n  const firstId = draft.selection[0];\n  const currentPage = draft.pages.find(({ id }) => id === draft.current);\n  if (!currentPage) {\n    return;\n  }\n  const pageElementIds = currentPage.elements.map((el) => el.id);\n  const firstIndex = pageElementIds.findIndex((id) => id === firstId);\n  const clickedIndex = pageElementIds.findIndex((id) => id === elementId);\n  const lowerIndex = Math.min(firstIndex, clickedIndex);\n  const higherIndex = Math.max(firstIndex, clickedIndex);\n  const elementIds = pageElementIds.slice(lowerIndex, higherIndex + 1);\n  // reverse selection if firstId isn't first anymore\n  if (firstId !== elementIds[0]) {\n    elementIds.reverse();\n  }\n\n  setSelectedElements(draft, {\n    elementIds,\n    withLinked,\n  });\n};\n\nexport default produce<ReducerState, [ToggleLayerProps]>(toggleLayer);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  UnselectElementProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Remove the given id from the current selection.\n *\n * If no id is given or id is not in the current selection, nothing happens.\n */\nexport const unselectElement = (\n  draft: ReducerStateDraft,\n  { elementId }: UnselectElementProps\n) => {\n  const index = draft.selection.indexOf(elementId);\n  if (index === -1) {\n    return;\n  }\n  draft.selection.splice(index, 1);\n};\n\nexport default produce<ReducerState, [UnselectElementProps]>(unselectElement);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ReducerState,\n  ReducerStateDraft,\n  UpdateAnimationStateProps,\n} from '../../../../types';\n\n/**\n * Update the story animation state to play, pause, scrub or reset\n * active pages animations.\n */\nexport const updateAnimationState = (\n  draft: ReducerStateDraft,\n  { animationState }: UpdateAnimationStateProps\n) => {\n  draft.animationState = animationState;\n};\n\nexport default produce<ReducerState, [UpdateAnimationStateProps]>(\n  updateAnimationState\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  StoryAnimationState,\n  type StoryAnimation,\n} from '@googleforcreators/animation';\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  UpdateElementsProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { updateElementWithUpdater, updateAnimations } from './utils';\n\n/**\n * Update elements by the given list of ids with the given properties.\n * If given list of ids is `null`, update all currently selected elements.\n *\n * Elements will be updated only on the current page.\n *\n * If an element id does not correspond do an element on the current page, id is ignored.\n *\n * If an empty list or a list of only unknown ids is given, state is unchanged.\n *\n * If given set of properties is empty, state is unchanged.\n *\n * Current selection and page is unchanged.\n */\nexport const updateElements = (\n  draft: ReducerStateDraft,\n  { elementIds, properties: propertiesOrUpdater }: UpdateElementsProps\n) => {\n  if (\n    [\n      StoryAnimationState.Playing,\n      StoryAnimationState.PlayingSelected,\n      StoryAnimationState.Scrubbing,\n    ].includes(draft.animationState)\n  ) {\n    return;\n  }\n\n  const idsToUpdate = elementIds === null ? draft.selection : elementIds;\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page || !idsToUpdate) {\n    return;\n  }\n  const animationLookup: Record<string, StoryAnimation> = {};\n  page.elements\n    .filter(({ id }) => idsToUpdate.includes(id))\n    .forEach((element) => {\n      // Update function will update the element inline unless there's an animation update.\n      // If so, the element will remain unchanged, and the animation will be returned instead.\n      const animation = updateElementWithUpdater(element, propertiesOrUpdater);\n      if (animation) {\n        animationLookup[animation.id] = {\n          ...animation,\n          targets: [element.id],\n        };\n      }\n    });\n\n  const isAnimationUpdate = Object.keys(animationLookup).length > 0;\n\n  if (isAnimationUpdate) {\n    page.animations = updateAnimations(page.animations || [], animationLookup);\n  }\n};\n\nexport default produce<ReducerState, [UpdateElementsProps]>(updateElements);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ReducerState,\n  ReducerStateDraft,\n  UpdateElementsByFontFamilyProps,\n} from '../../../../types';\nimport { updateElementWithUpdater } from './utils';\n\n/**\n * Update elements by the given font 'family' with the given properties.\n *\n * Elements will be updated through all pages with correct font 'family'.\n *\n * If an empty family or a no matches with family, state is unchanged.\n *\n * If no element with the given family is found, state is unchanged.\n *\n * If given set of properties is empty, state is unchanged.\n *\n * Current selection and page is unchanged.\n */\nexport const updateElementsByFontFamily = (\n  draft: ReducerStateDraft,\n  { family, properties: propertiesOrUpdater }: UpdateElementsByFontFamilyProps\n) => {\n  if (!family) {\n    return;\n  }\n\n  draft.pages.forEach((page) => {\n    page.elements\n      .filter(elementIs.text)\n      .filter((element) => element.font.family === family)\n      .forEach((element) =>\n        updateElementWithUpdater(element, propertiesOrUpdater)\n      );\n  });\n};\n\nexport default produce<ReducerState, [UpdateElementsByFontFamilyProps]>(\n  updateElementsByFontFamily\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  UpdateElementsByResourceIdProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { updateElementWithUpdater } from './utils';\n\n/**\n * Update elements by the given Resource id with the given properties.\n *\n * Elements will be updated through all pages with correct id.\n *\n * If an empty id or a no matches with id, state is unchanged.\n *\n * If given set of properties is empty, state is unchanged.\n *\n * Current selection and page is unchanged.\n */\nexport const updateElementsByResourceId = (\n  draft: ReducerStateDraft,\n  { id, properties: propertiesOrUpdater }: UpdateElementsByResourceIdProps\n) => {\n  if (!id) {\n    return;\n  }\n\n  draft.pages.forEach((page) => {\n    page.elements\n      .filter(elementIs.media)\n      .filter((element) => element.resource.id === id)\n      .forEach((element) =>\n        updateElementWithUpdater(element, propertiesOrUpdater)\n      );\n  });\n};\n\nexport default produce<ReducerState, [UpdateElementsByResourceIdProps]>(\n  updateElementsByResourceId\n);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ReducerState,\n  ReducerStateDraft,\n  UpdateGroupProps,\n} from '../../../../types';\n\n/**\n * Update group by id.\n */\nexport const updateGroup = (\n  draft: ReducerStateDraft,\n  { groupId, properties }: UpdateGroupProps\n) => {\n  if (!groupId) {\n    return;\n  }\n\n  const page = draft.pages.find(({ id }) => id === draft.current);\n  if (!page) {\n    return;\n  }\n  const { groups } = page;\n\n  // Should only update existing groups\n  if (!groups?.[groupId]) {\n    return;\n  }\n\n  Object.assign(groups[groupId], properties);\n};\n\nexport default produce<ReducerState, [UpdateGroupProps]>(updateGroup);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport { PAGE_RESERVED_PROPERTIES } from '../types';\nimport type {\n  UpdatePageProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\nimport { objectWithout } from './utils';\n\n/**\n * Update page by id or current page if no id given.\n *\n * If id doesn't exist, nothing happens.\n *\n * Current page and selection is unchanged.\n */\nexport const updatePage = (\n  draft: ReducerStateDraft,\n  { pageId, properties }: UpdatePageProps\n) => {\n  const idToUpdate = pageId === null ? (draft.current as string) : pageId;\n  const page = draft.pages.find(({ id }) => id === idToUpdate);\n  if (!page) {\n    return;\n  }\n  const allowedProperties = objectWithout(properties, PAGE_RESERVED_PROPERTIES);\n  Object.assign(page, allowedProperties);\n};\n\nexport default produce<ReducerState, [UpdatePageProps]>(updatePage);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { produce, current } from 'immer';\nimport type { Draft } from 'immer';\nimport type { Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type {\n  UpdateStoryProps,\n  ReducerState,\n  ReducerStateDraft,\n} from '../../../../types';\n\n/**\n * Update story properties.\n *\n * No validation is performed and existing values are overwritten.\n */\nexport const updateStory = (\n  draft: ReducerStateDraft,\n  { properties }: UpdateStoryProps\n) => {\n  // If properties is a callback, replace story with callback response\n  if (typeof properties === 'function') {\n    draft.story = properties<Draft<Story>>(current(draft.story));\n    return;\n  }\n  // Otherwise copy all the properties into the existing story object\n  Object.assign(draft.story, properties);\n};\n\nexport default produce<ReducerState, [UpdateStoryProps]>(updateStory);\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Element } from '@googleforcreators/elements';\nimport type { StoryAnimation } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { LayerDirection } from '../../../../constants';\nimport { ELEMENT_RESERVED_PROPERTIES } from '../types';\nimport objectWithout from '../../../../utils/objectWithout';\nimport type { ElementUpdater } from '../../../../types';\nexport { objectWithout };\n\nexport function intersect<T>(first: T[], ...rest: T[][]) {\n  if (!first || !rest?.length) {\n    return first;\n  }\n\n  return rest.reduce(\n    (intersection, list) =>\n      intersection.filter((value) => list.includes(value)),\n    first\n  );\n}\n\nexport function isInsideRange(index: number, start: number, end: number) {\n  return index >= start && index <= end;\n}\n\nexport function moveArrayElement<T>(\n  array: T[],\n  oldPosition: number,\n  newPosition: number\n) {\n  // First remove from list.\n  const element = array[oldPosition];\n  const arrayWithoutElement = [\n    ...array.slice(0, oldPosition),\n    ...array.slice(oldPosition + 1),\n  ];\n\n  // Then re-insert at the right point\n  return [\n    ...arrayWithoutElement.slice(0, newPosition),\n    element,\n    ...arrayWithoutElement.slice(newPosition),\n  ];\n}\n\ninterface PositionProps {\n  currentPosition: number;\n  minPosition: number;\n  maxPosition: number;\n  desiredPosition: LayerDirection | number;\n}\nexport function getAbsolutePosition({\n  currentPosition,\n  minPosition,\n  maxPosition,\n  desiredPosition,\n}: PositionProps) {\n  if (typeof desiredPosition === 'number') {\n    return Math.min(maxPosition, Math.max(minPosition, desiredPosition));\n  }\n\n  switch (desiredPosition) {\n    case LayerDirection.Front:\n      return maxPosition;\n    case LayerDirection.Back:\n      return minPosition;\n    case LayerDirection.Forward:\n      return Math.min(maxPosition, currentPosition + 1);\n    case LayerDirection.Backward:\n      return Math.max(minPosition, currentPosition - 1);\n    default:\n      return currentPosition;\n  }\n}\n\ninterface AllowedProperties extends Partial<Element> {\n  animation: StoryAnimation;\n}\nfunction isWithAnimation(\n  props: Partial<Element> | Element\n): props is AllowedProperties {\n  return 'animation' in props;\n}\nexport function updateElementWithUpdater<T extends Element = Element>(\n  element: T,\n  properties: Partial<T> | ElementUpdater<T>\n): null | void | StoryAnimation {\n  const updater =\n    typeof properties === 'function' ? properties(element) : properties;\n  const allowedProperties: Partial<Element> | Element = objectWithout(\n    updater,\n    ELEMENT_RESERVED_PROPERTIES\n  );\n  if (Object.keys(allowedProperties).length === 0) {\n    return null;\n  }\n  if (isWithAnimation(allowedProperties) && allowedProperties.animation) {\n    return allowedProperties.animation;\n  }\n  Object.assign(element, allowedProperties);\n  return null;\n}\n\nexport function removeAnimationsWithElementIds(\n  animations: StoryAnimation[] = [],\n  ids: string[] = []\n) {\n  return animations.filter(\n    ({ targets }) => !ids.some((id) => targets?.includes(id))\n  );\n}\n\ntype AnimationToDelete = StoryAnimation & {\n  delete?: boolean;\n};\nexport function updateAnimations(\n  oldAnimations: StoryAnimation[],\n  animationUpdates: Record<string, StoryAnimation>\n) {\n  const newAnimations = oldAnimations.reduce(\n    (animations: StoryAnimation[], animation) => {\n      const updatedAnimation = animationUpdates[animation.id];\n\n      // remove animation from lookup\n      delete animationUpdates[animation.id];\n\n      if ((updatedAnimation as AnimationToDelete)?.delete) {\n        // delete animation\n        return animations;\n      } else if (updatedAnimation) {\n        // update animation\n        return [...animations, updatedAnimation];\n      } else {\n        // No updates\n        return [...animations, animation];\n      }\n    },\n    []\n  );\n\n  // add animations\n  Object.values(animationUpdates).forEach((a) => newAnimations.push(a));\n\n  return newAnimations;\n}\n\n/**\n * Entry must have {id: string, ...} prop on it. WIP\n * on enforcing this with jsdocs.\n *\n * @typedef {Object.<string, any>} Entry\n */\n\ninterface Entry {\n  id: string;\n}\n/**\n * Remove duplicate entries. Uses last instance if\n * multiple entries share the same id.\n *\n * @param entries - set of entries with possible duplicate Ids\n * @return New set of entries with only unique Ids\n */\nexport function removeDuplicates<T extends Entry>(entries: T[] = []) {\n  // Use only last of multiple elements with same id by turning into an object and getting the values.\n  return Object.values(\n    Object.fromEntries(entries.map((entry) => [entry.id, entry]))\n  );\n}\n\n/**\n * Takes to sets of entries and returns unique entries\n * (keying on id) of right set not present in left set.\n *\n * @param left - base set of entries\n * @param right - new entries\n * @return - right exclusion of sets set\n */\nexport function exclusion<T extends Entry>(left: T[] = [], right: T[] = []) {\n  const rightSet = removeDuplicates(right);\n  const leftJoinKeys = left.map(({ id }) => id);\n  return rightSet.filter(({ id }) => !leftJoinKeys.includes(id));\n}\n\n/**\n * Calculate the last index of a group.\n *\n * @param props Props\n * @param props.elements Elements array\n * @param props.groupId Group id\n * @return Last index of group\n */\nexport function getLastIndexOfGroup({\n  elements,\n  groupId,\n}: {\n  elements: Element[];\n  groupId: string;\n}) {\n  const isMember = (e: Element) => e.groupId === groupId;\n  const firstGroupElementIndex = elements.findIndex(isMember);\n  const groupSize = elements.filter(isMember).length;\n  return firstGroupElementIndex + groupSize - 1;\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useStoryReducer from '../useStoryReducer';\n\nexport function setupReducer(partial) {\n  const { result } = renderHook(() => useStoryReducer(partial));\n\n  // convert each method to be wrapped in act and return the new state\n  const wrapWithAct = (methods) =>\n    Object.keys(methods).reduce((obj, methodName) => {\n      const method = methods[methodName];\n      const wrapped = (parms) => {\n        act(() => method(parms));\n        return result.current.state;\n      };\n      return {\n        ...obj,\n        [methodName]: wrapped,\n      };\n    }, {});\n\n  return wrapWithAct({\n    ...result.current.api,\n    ...result.current.internal,\n  });\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addAnimations.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addAnimations', () => {\n  it('should ignore an empty list', () => {\n    const { restore, addAnimations } = setupReducer();\n\n    // Set an initial state with a current page and other animations.\n    const initialState = restore({\n      pages: [{ id: '111', animations: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addAnimations({ animations: [] });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should add all new animations to the current page', () => {\n    const { restore, addAnimations } = setupReducer();\n\n    // Set an initial state with a current page and other animations\n    restore({\n      pages: [{ id: '111', animations: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addAnimations({\n      animations: [{ id: '123' }, { id: '234' }],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      animations: [{ id: '000' }, { id: '123' }, { id: '234' }],\n    });\n  });\n\n  it('should add animations even if page has no animation array', () => {\n    const { restore, addAnimations } = setupReducer();\n\n    // Set an initial state with a current page and no animations\n    restore({\n      pages: [{ id: '111' }],\n      current: '111',\n    });\n\n    const result = addAnimations({\n      animations: [{ id: '123' }, { id: '234' }],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      animations: [{ id: '123' }, { id: '234' }],\n    });\n  });\n\n  it('should skip animations matching existing ids', () => {\n    const { restore, addAnimations } = setupReducer();\n\n    // Set an initial state with a current page and other animations\n    restore({\n      pages: [{ id: '111', animations: [{ id: '000', a: 1 }] }],\n      current: '111',\n    });\n\n    const result = addAnimations({\n      animations: [{ id: '123' }, { id: '000', a: 2 }],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      animations: [{ id: '000', a: 1 }, { id: '123' }],\n    });\n  });\n\n  it('should only add animations with unique ids (using the latter)', () => {\n    const { restore, addAnimations } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [{ id: '111', animations: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addAnimations({\n      animations: [\n        { id: '123', a: 1 },\n        { id: '123', a: 2 },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      animations: [{ id: '000' }, { id: '123', a: 2 }],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addElement', () => {\n  it('should add an element to the current page and select it', () => {\n    const { restore, addElement } = setupReducer();\n\n    // Set an initial state with a current page and no elements.\n    restore({\n      pages: [{ id: '111', elements: [] }],\n      current: '111',\n    });\n\n    const result = addElement({ element: { id: '123' } });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '123' }],\n    });\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should add an element to the end of the list on the current page and replace selection', () => {\n    const { restore, addElement } = setupReducer();\n\n    // Set an initial state with a current page and one element.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '321' }] }],\n      current: '111',\n      selection: ['321'],\n    });\n\n    const result = addElement({ element: { id: '123' } });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '321' }, { id: '123' }],\n    });\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should not add an element with an id that already exists', () => {\n    const { restore, addElement } = setupReducer();\n\n    // Set an initial state with a current page and one element.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '321' }] }],\n      current: '111',\n      selection: ['321'],\n    });\n\n    const result = addElement({ element: { id: '321' } });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '321' }],\n    });\n    expect(result.selection).toStrictEqual(['321']);\n  });\n\n  it('should add an element with a unique product id', () => {\n    const { restore, addElement } = setupReducer();\n\n    // Set an initial state with a current page and one element.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '321',\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'abc' },\n            },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['321'],\n    });\n\n    const result = addElement({\n      element: {\n        id: '234',\n        type: ELEMENT_TYPES.PRODUCT,\n        product: { productId: 'bcd' },\n      },\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        {\n          id: '321',\n          type: ELEMENT_TYPES.PRODUCT,\n          product: { productId: 'abc' },\n        },\n        {\n          id: '234',\n          type: ELEMENT_TYPES.PRODUCT,\n          product: { productId: 'bcd' },\n        },\n      ],\n    });\n    expect(result.selection).toStrictEqual(['234']);\n  });\n\n  it('should not add an element with a duplicate product id', () => {\n    const { restore, addElement } = setupReducer();\n\n    // Set an initial state with a current page and one element.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '321',\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'abc' },\n            },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['321'],\n    });\n\n    const result = addElement({\n      element: {\n        id: '234',\n        type: ELEMENT_TYPES.PRODUCT,\n        product: { productId: 'abc' },\n      },\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        {\n          id: '321',\n          type: ELEMENT_TYPES.PRODUCT,\n          product: { productId: 'abc' },\n        },\n      ],\n    });\n    expect(result.selection).toStrictEqual(['321']);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addElementToSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addElementToSelection', () => {\n  it('should add element to selection (if not already there)', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    expect(initialState.selection).not.toContain('e1');\n\n    // Add element e1\n    const firstResult = addElementToSelection({ elementId: 'e1' });\n    expect(firstResult.selection).toContain('e1');\n\n    // Add element e1 again - nothing happens\n    const secondResult = addElementToSelection({ elementId: 'e1' });\n    expect(secondResult).toStrictEqual(firstResult);\n  });\n\n  it('should not allow adding video placeholder to non-empty selection', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', resource: { isPlaceholder: true } },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e3'],\n    });\n\n    // Toggle no element\n    const failedAttempt = addElementToSelection({ elementId: 'e1' });\n    expect(failedAttempt.selection).toStrictEqual(initialState.selection);\n  });\n\n  it('should not allow adding background element to non-empty selection', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e3'],\n    });\n\n    // Toggle no element\n    const failedAttempt = addElementToSelection({ elementId: 'e1' });\n    expect(failedAttempt.selection).toStrictEqual(initialState.selection);\n  });\n\n  it('should remove background element from selection if adding a new one', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state with bg element selected\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e1'],\n    });\n\n    // Add a new element to selection - should expunge bg element from selection\n    const { selection } = addElementToSelection({ elementId: 'e2' });\n    expect(selection).not.toContain('e1');\n    expect(selection).toContain('e2');\n  });\n\n  it('should replace selection if adding locked element to non-empty selection', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n            { id: 'e4', isLocked: true },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e3'],\n    });\n\n    const replacedSelection = addElementToSelection({ elementId: 'e4' });\n    expect(replacedSelection.selection).toStrictEqual(['e4']);\n  });\n\n  it('should remove locked element from selection if adding a new one', () => {\n    const { restore, addElementToSelection } = setupReducer();\n\n    // Set an initial state with bg element selected\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', isLocked: true },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2'],\n    });\n\n    // Add a new element to selection - should expunge locked element from selection\n    const { selection } = addElementToSelection({ elementId: 'e3' });\n    expect(selection).toStrictEqual(['e3']);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addElements', () => {\n  it('should ignore an empty list', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    const initialState = restore({\n      pages: [{ id: '111', elements: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addElements({ elements: [] });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should add all elements to the current page and select them', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addElements({ elements: [{ id: '123' }, { id: '234' }] });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '000' }, { id: '123' }, { id: '234' }],\n    });\n    expect(result.selection).toStrictEqual(['123', '234']);\n  });\n\n  it('should skip elements matching existing ids', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '000', a: 1 }] }],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [{ id: '123' }, { id: '000', a: 2 }],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '000', a: 1 }, { id: '123' }],\n    });\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should only add elements with unique ids (using the latter)', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '000' }] }],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '123', a: 1 },\n        { id: '123', a: 2 },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [{ id: '000' }, { id: '123', a: 2 }],\n    });\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should only add a product once', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000' },\n            { id: '123', product: { productId: 1 }, type: 'product' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '000' },\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n      ],\n    });\n    expect(result.selection).toStrictEqual(['124']);\n  });\n\n  it('should allow adding 6 products', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000' },\n            { id: '122', product: { productId: 0 }, type: 'product' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n        { id: '125', product: { productId: 3 }, type: 'product' },\n        { id: '126', product: { productId: 4 }, type: 'product' },\n        { id: '127', product: { productId: 5 }, type: 'product' },\n        { id: '130', type: 'image' },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '000' },\n        { id: '122', product: { productId: 0 }, type: 'product' },\n        { id: '130', type: 'image' },\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n        { id: '125', product: { productId: 3 }, type: 'product' },\n        { id: '126', product: { productId: 4 }, type: 'product' },\n        { id: '127', product: { productId: 5 }, type: 'product' },\n      ],\n    });\n    expect(result.selection).toStrictEqual([\n      '130',\n      '123',\n      '124',\n      '125',\n      '126',\n      '127',\n    ]);\n  });\n\n  it('should not allow adding more than 6 products', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000' },\n            { id: '122', product: { productId: 0 }, type: 'product' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n        { id: '125', product: { productId: 3 }, type: 'product' },\n        { id: '126', product: { productId: 4 }, type: 'product' },\n        { id: '127', product: { productId: 5 }, type: 'product' },\n        { id: '128', product: { productId: 6 }, type: 'product' },\n        { id: '129', product: { productId: 7 }, type: 'product' },\n        { id: '130', type: 'image' },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '000' },\n        { id: '122', product: { productId: 0 }, type: 'product' },\n        { id: '130', type: 'image' },\n      ],\n    });\n    expect(result.selection).toStrictEqual(['130']);\n  });\n\n  it('should only allow 6 products with duplicates', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000' },\n            { id: '123', product: { productId: 1 }, type: 'product' },\n            { id: '124', product: { productId: 2 }, type: 'product' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n        { id: '125', product: { productId: 3 }, type: 'product' },\n        { id: '126', product: { productId: 4 }, type: 'product' },\n        { id: '127', product: { productId: 5 }, type: 'product' },\n        { id: '128', product: { productId: 6 }, type: 'product' },\n        { id: '130', type: 'image' },\n      ],\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '000' },\n        { id: '123', product: { productId: 1 }, type: 'product' },\n        { id: '124', product: { productId: 2 }, type: 'product' },\n        { id: '130', type: 'image' },\n        { id: '125', product: { productId: 3 }, type: 'product' },\n        { id: '126', product: { productId: 4 }, type: 'product' },\n        { id: '127', product: { productId: 5 }, type: 'product' },\n        { id: '128', product: { productId: 6 }, type: 'product' },\n      ],\n    });\n    expect(result.selection).toStrictEqual(['130', '125', '126', '127', '128']);\n  });\n\n  it('should add elements to a specific page', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '000' }],\n        },\n        { id: '222', elements: [{ id: '123', type: 'text' }] },\n      ],\n      current: '111',\n      selection: ['123'],\n    });\n\n    const result = addElements({\n      elements: [\n        { id: '124', type: 'video' },\n        { id: '125', type: 'video' },\n      ],\n      pageId: '222',\n      updateSelection: false,\n    });\n\n    expect(result.pages[1].elements).toHaveLength(3);\n    expect(result.pages[1].elements).toStrictEqual([\n      { id: '123', type: 'text' },\n      { id: '124', type: 'video' },\n      { id: '125', type: 'video' },\n    ]);\n\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should add elements to a specific page and select element', () => {\n    const { restore, addElements } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [{ id: '222', elements: [{ id: '123', type: 'text' }] }],\n      current: '111',\n      selection: ['123'],\n    });\n\n    const result = addElements({\n      elements: [{ id: '124', type: 'video' }],\n      pageId: '222',\n      updateSelection: true,\n    });\n\n    expect(result.pages[0].elements).toHaveLength(2);\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', type: 'text' },\n      { id: '124', type: 'video' },\n    ]);\n\n    expect(result.selection).toStrictEqual(['124']);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addElementsAcrossPages.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addElementsAcrossPages', () => {\n  it('should add elements on individual pages and not change selection', () => {\n    const { restore, addElementsAcrossPages } = setupReducer();\n\n    // Set an initial state with a current page and other elements.\n    restore({\n      pages: [\n        { id: '111', elements: [{ id: '000' }] },\n        { id: '222', elements: [{ id: '333' }] },\n      ],\n      current: '111',\n      selection: ['000'],\n      story: { fonts: {} },\n    });\n\n    const result = addElementsAcrossPages({\n      elements: [\n        { id: '123', type: 'video' },\n        { id: '124', type: 'video' },\n        { id: '125', type: 'video' },\n        { id: '126', type: 'video' },\n        { id: '127', type: 'video' },\n        { id: '128', type: 'video' },\n        { id: '129', type: 'video' },\n        { id: '130', type: 'video' },\n      ],\n      page: {\n        id: '444',\n        elements: [{ id: '555' }],\n      },\n      position: 0,\n    });\n\n    expect(result).toStrictEqual({\n      pages: [\n        { id: '111', elements: [{ id: '000' }] },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '123', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '124', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '125', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '126', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '127', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '128', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '129', type: 'video' }],\n        },\n        {\n          id: expect.any(String),\n          elements: [{ id: expect.any(String) }, { id: '130', type: 'video' }],\n        },\n        { id: '222', elements: [{ id: '333' }] },\n      ],\n      current: '111',\n      selection: ['000'],\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      story: { fonts: {} },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addGroup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addGroup', () => {\n  it('should do nothing if nothing supplied', () => {\n    const { restore, addGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addGroup({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no name supplied', () => {\n    const { restore, addGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addGroup({ groupId: 'g1' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should add group with default lock status', () => {\n    const { restore, addGroup } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addGroup({ groupId: 'g1', name: 'Group 1' });\n\n    expect(result.pages[0].groups).toStrictEqual({\n      g1: { name: 'Group 1', isLocked: false },\n    });\n  });\n\n  it('should add group even if `groups` is not set', () => {\n    const { restore, addGroup } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addGroup({ groupId: 'g1', name: 'Group 1' });\n\n    expect(result.pages[0].groups).toStrictEqual({\n      g1: { name: 'Group 1', isLocked: false },\n    });\n  });\n\n  it('should add group with specified lock status', () => {\n    const { restore, addGroup } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = addGroup({ groupId: 'g1', name: 'Group 1', isLocked: true });\n\n    expect(result.pages[0].groups).toStrictEqual({\n      g1: { name: 'Group 1', isLocked: true },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addPage', () => {\n  it('should add a page', () => {\n    const { addPage } = setupReducer();\n\n    const result = addPage({\n      page: {\n        id: '123',\n        elements: [{ id: '456' }],\n      },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '123',\n        elements: [{ id: '456' }],\n      },\n    ]);\n  });\n  it('should reject adding a page without an element', () => {\n    const { restore, addPage } = setupReducer();\n\n    const initial = restore({\n      pages: [{ id: '111' }],\n    });\n\n    const result = addPage({ page: { id: '222' } });\n\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should make the new page current', () => {\n    const { restore, addPage } = setupReducer();\n\n    // Set an initial state with a different current page.\n    restore({\n      pages: [{ id: '111' }],\n      current: '111',\n    });\n\n    const result = addPage({ page: { id: '123', elements: [{ id: '456' }] } });\n\n    expect(result.current).toBe('123');\n  });\n\n  it('should insert the new page just after current one', () => {\n    const { restore, addPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '111',\n    });\n\n    const result = addPage({ page: { id: '123', elements: [{ id: '456' }] } });\n\n    const pageIds = result.pages.map(({ id }) => id);\n\n    expect(pageIds).toStrictEqual(['111', '123', '222']);\n  });\n\n  it('should add pages at position and not move to it', () => {\n    const { restore, addPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '221' }],\n      current: '221',\n    });\n\n    addPage({\n      page: { id: '331', elements: [{ id: '123' }] },\n      position: 2,\n      updateSelection: false,\n    });\n    addPage({\n      page: { id: '441', elements: [{ id: '456' }] },\n      position: 3,\n      updateSelection: false,\n    });\n    const result = addPage({\n      page: { id: '551', elements: [{ id: '789' }] },\n      position: 4,\n      updateSelection: false,\n    });\n\n    const pageIds = result.pages.map(({ id }) => id);\n    expect(pageIds).toStrictEqual(['111', '221', '331', '441', '551']);\n    expect(result.current).toBe('221');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/addPageAt.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('addPageAt', () => {\n  it('should add a page at the given position', () => {\n    const { restore, addPageAt } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '222',\n    });\n\n    const result = addPageAt({\n      page: { id: '123', elements: [{ id: '456' }] },\n      position: 1,\n    });\n    expect(getPageIds(result)).toStrictEqual(['111', '123', '222']);\n  });\n\n  it('should treat illegal positions as \"add after current\"', () => {\n    const { restore, addPageAt } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '222',\n    });\n\n    const firstResult = addPageAt({\n      page: { id: '123', elements: [{ id: '456' }] },\n      position: -50,\n    });\n    expect(getPageIds(firstResult)).toStrictEqual(['111', '222', '123']);\n\n    const secondResult = addPageAt({\n      page: { id: '321', elements: [{ id: '456' }] },\n      position: 50,\n    });\n    expect(getPageIds(secondResult)).toStrictEqual([\n      '111',\n      '222',\n      '123',\n      '321',\n    ]);\n  });\n});\n\nfunction getPageIds({ pages }) {\n  return pages.map(({ id }) => id);\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { LayerDirection } from '../../../../constants';\nimport { setupReducer } from './_utils';\n\ndescribe('arrangeElement', () => {\n  it('should do nothing if there are only two elements on page', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({ elementId: '234', position: 0 });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if already in the right place and no groups are used', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234' },\n            { id: '345' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({ elementId: '234', position: 1 });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should do nothing if already in the right place and in the right group', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: '234',\n      position: 1,\n      groupId: 'g1',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should set group if already in the right place, but changing group', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', groupId: 'g1' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g2' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: 'e3',\n      position: 2,\n      groupId: 'g2',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: 'e1', isBackground: true },\n      { id: 'e2', groupId: 'g1' },\n      { id: 'e3', groupId: 'g2' },\n      { id: 'e4', groupId: 'g2' },\n    ]);\n  });\n\n  it('should remove group if changing group and the old group is empty', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', groupId: 'g1' },\n            { id: 'e3', groupId: 'g2' },\n            { id: 'e4', groupId: 'g2' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: 'e2',\n      position: 1,\n      groupId: 'g2',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: 'e1', isBackground: true },\n      { id: 'e2', groupId: 'g2' },\n      { id: 'e3', groupId: 'g2' },\n      { id: 'e4', groupId: 'g2' },\n    ]);\n\n    expect(result.pages[0].groups).toStrictEqual({\n      g2: { name: 'Group 2' },\n    });\n  });\n\n  it('should not be able to change group to a group that does not exist', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', groupId: 'g1' },\n            { id: 'e3', groupId: 'g1' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: 'e2',\n      position: 1,\n      groupId: 'g2',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should remove group if already in the right place, but explicitly without group', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345', groupId: 'g1' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: '234',\n      position: 1,\n      groupId: null,\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', isBackground: true },\n      { id: '234' },\n      { id: '345', groupId: 'g1' },\n    ]);\n  });\n\n  it('should delete the group if no elements left into the group', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345' },\n          ],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({\n      elementId: '234',\n      position: 1,\n      groupId: null,\n    });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '123', isBackground: true },\n        { id: '234' },\n        { id: '345' },\n      ],\n      groups: {},\n    });\n  });\n\n  it('should move but not alter group if group is unset', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeElement({ elementId: '234', position: 2 });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', isBackground: true },\n      { id: '345' },\n      { id: '234', groupId: 'g1' },\n    ]);\n  });\n\n  it('should move element to specified position', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    const result = arrangeElement({ elementId: '234', position: 2 });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345',\n      '234',\n      '456',\n    ]);\n  });\n\n  it('should move element to front', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    const result = arrangeElement({\n      elementId: '234',\n      position: LayerDirection.Front,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345',\n      '456',\n      '234',\n    ]);\n  });\n\n  it('should move element to back', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    const result = arrangeElement({\n      elementId: '456',\n      position: LayerDirection.Back,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '456',\n      '234',\n      '345',\n    ]);\n  });\n\n  it('should move element forward', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    const result = arrangeElement({\n      elementId: '234',\n      position: LayerDirection.Forward,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345',\n      '234',\n      '456',\n    ]);\n  });\n\n  it('should move element backward', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    const result = arrangeElement({\n      elementId: '345',\n      position: LayerDirection.Backward,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345',\n      '234',\n      '456',\n    ]);\n  });\n\n  it('should only allow element in positions inside the bounds', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    // Try to move element from 2nd position before the start.\n    const firstResult = arrangeElement({ elementId: '456', position: -100 });\n    expect(getElementIdsFromCurrentPage(firstResult)).toStrictEqual([\n      '123',\n      '456',\n      '234',\n      '345',\n    ]);\n\n    // Try to move element from 2nd position after the end.\n    const secondResult = arrangeElement({ elementId: '234', position: 100 });\n    expect(getElementIdsFromCurrentPage(secondResult)).toStrictEqual([\n      '123',\n      '456',\n      '345',\n      '234',\n    ]);\n  });\n\n  it('should not be able to move background element at all', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    // Try to move bg element anywhere\n    const result = arrangeElement({ elementId: '123', position: 2 });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '234',\n      '345',\n      '456',\n    ]);\n  });\n\n  it('should not be able to move element below background using position', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    // Try to move any non-bg element to position 0\n    const result = arrangeElement({ elementId: '345', position: 0 });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345', // Note that it *does* move, but not below background\n      '234',\n      '456',\n    ]);\n  });\n\n  it('should not be able to move element below background using \"send backwards\"', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    // Try to move the element just above the background further backwards.\n    const result = arrangeElement({\n      elementId: '234',\n      position: LayerDirection.Backward,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '234',\n      '345',\n      '456',\n    ]);\n  });\n\n  it('should not be able to move element below background using \"send to back\"', () => {\n    const { restore, arrangeElement } = setupReducer();\n\n    restore(getInitialState());\n\n    // Try to move any non-bg element to position BACK\n    const result = arrangeElement({\n      elementId: '345',\n      position: LayerDirection.Back,\n    });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345', // Note that it *does* move, but not below background\n      '234',\n      '456',\n    ]);\n  });\n});\n\nfunction getElementIdsFromCurrentPage({ pages, current }) {\n  return pages.find(({ id }) => id === current).elements.map(({ id }) => id);\n}\n\nfunction getInitialState() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          { id: '123', isBackground: true },\n          { id: '234' },\n          { id: '345' },\n          { id: '456' },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/arrangeGroup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('arrangeGroup', () => {\n  it('should do nothing if nothing supplied', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group does not exist', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({ groupId: 'g1', position: 1 });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group has no elements', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({ groupId: 'g1', position: 1 });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group elements are already in position', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n          ],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({ groupId: 'g1', position: 1 });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should move all elements of group to new position', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345', groupId: 'g1' },\n            { id: '456' },\n          ],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({ groupId: 'g1', position: 3 });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', isBackground: true },\n      { id: '456' },\n      { id: '234', groupId: 'g1' },\n      { id: '345', groupId: 'g1' },\n    ]);\n  });\n\n  it('should move all elements of group to new position even if backwards', () => {\n    const { restore, arrangeGroup } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345', groupId: 'g1' },\n            { id: '456' },\n            { id: '567', groupId: 'g2' },\n            { id: '678', groupId: 'g2' },\n          ],\n          groups: { g1: { name: 'Group 1' }, g2: { name: 'Group 2' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = arrangeGroup({ groupId: 'g2', position: 3 });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', isBackground: true },\n      { id: '234', groupId: 'g1' },\n      { id: '345', groupId: 'g1' },\n      { id: '567', groupId: 'g2' },\n      { id: '678', groupId: 'g2' },\n      { id: '456' },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/arrangePage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('arrangePage', () => {\n  it('should do nothing if there is only one page', () => {\n    const { restore, arrangePage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({\n      pages: [{ id: '111' }],\n    });\n\n    const result = arrangePage({ pageId: '111', position: 3 });\n    expect(result).toBe(initialState);\n  });\n\n  it('should reorder a page to the specified position', () => {\n    const { restore, arrangePage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }, { id: '333' }, { id: '444' }],\n    });\n\n    // Reorder page 111 from 1st place (position 0) to 2nd place (position 1)\n    const result = arrangePage({ pageId: '111', position: 1 });\n    const pageIds = result.pages.map(({ id }) => id);\n    expect(pageIds).toStrictEqual(['222', '111', '333', '444']);\n  });\n\n  it('should do nothing if illegal reordering', () => {\n    const { restore, arrangePage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({\n      pages: [{ id: '111' }, { id: '222' }, { id: '333' }, { id: '444' }],\n    });\n\n    // Reorder page 555 - doesn't exist\n    const firstFailedAttempt = arrangePage({ pageId: '555', position: 2 });\n    expect(firstFailedAttempt).toBe(initialState);\n\n    // Reorder page 333 to position 2 - it's already there\n    const secondFailedAttempt = arrangePage({ pageId: '333', position: 2 });\n    expect(secondFailedAttempt).toBe(initialState);\n\n    // Reorder page 333 to position 20 - outside bounds\n    const thirdFailedAttempt = arrangePage({ pageId: '333', position: 20 });\n    expect(thirdFailedAttempt).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/arrangeSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('arrangeSelection', () => {\n  it('should arrange a single selected element to the desired position', () => {\n    const { restore, arrangeSelection } = setupReducer();\n\n    restore(getInitialState(['234']));\n\n    const result = arrangeSelection({ position: 3 });\n\n    expect(getElementIdsFromCurrentPage(result)).toStrictEqual([\n      '123',\n      '345',\n      '456',\n      '234',\n    ]);\n  });\n\n  it('should do nothing if selection is background element', () => {\n    const { restore, arrangeSelection } = setupReducer();\n\n    const initialState = restore(getInitialState(['123']));\n\n    const result = arrangeSelection({ position: 2 });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if there is no selection', () => {\n    const { restore, arrangeSelection } = setupReducer();\n\n    const initialState = restore(getInitialState([]));\n\n    const result = arrangeSelection({ position: 2 });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if there is multi-selection', () => {\n    const { restore, arrangeSelection } = setupReducer();\n\n    const initialState = restore(getInitialState(['234', '456']));\n\n    const result = arrangeSelection({ position: 2 });\n\n    expect(result).toBe(initialState);\n  });\n});\n\nfunction getElementIdsFromCurrentPage({ pages, current }) {\n  return pages.find(({ id }) => id === current).elements.map(({ id }) => id);\n}\n\nfunction getInitialState(selection) {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          { id: '123', isBackground: true },\n          { id: '234' },\n          { id: '345' },\n          { id: '456' },\n        ],\n      },\n    ],\n    current: '111',\n    selection,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/clearBackgroundElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('clearBackgroundElement', () => {\n  it('should clear the background element', () => {\n    const { restore, clearBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page, some elements and a default background element\n    restore({\n      pages: [\n        {\n          id: '111',\n          defaultBackgroundElement: {\n            id: '123',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          elements: [{ id: '456', isBackground: true }, { id: '789' }],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = clearBackgroundElement();\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        isDefaultBackground: true,\n        isBackground: true,\n      },\n      { id: '456' },\n      { id: '789' },\n    ]);\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should do nothing if background is default', () => {\n    const { restore, clearBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and some elements.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isDefaultBackground: true, isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = clearBackgroundElement();\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should keep overlay if present', () => {\n    const { restore, clearBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page, some elements and a default background element\n    restore({\n      pages: [\n        {\n          id: '111',\n          defaultBackgroundElement: {\n            id: '123',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          elements: [\n            { id: '456', isBackground: true, overlay: { type: 'linear' } },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = clearBackgroundElement();\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        isDefaultBackground: true,\n        isBackground: true,\n      },\n      { id: '456', overlay: { type: 'linear' } },\n      { id: '789' },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/clearSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('clearSelection', () => {\n  it('should clear selection if there is one', () => {\n    const { restore, clearSelection } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        { id: '111', elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }] },\n      ],\n      current: '111',\n      selection: ['e2', 'e1'],\n    });\n\n    // Clear selection\n    const result = clearSelection();\n\n    expect(result.selection).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/combineElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { MaskTypes } from '@googleforcreators/masks';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('combineElements', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should do nothing if first element is missing', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const initial = restore(getDefaultState1());\n\n    // Combine nothing into 789\n    const result = combineElements({ secondId: '789' });\n\n    expect(result).toBe(initial);\n  });\n\n  it('should do nothing if second element is missing', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    const initial = restore(state);\n\n    // Combine 456 into nothing\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n    });\n\n    expect(result).toBe(initial);\n  });\n\n  it('should do nothing if second element does not exist', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    const initial = restore(state);\n\n    // Combine 456 into non-existing element abc\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: 'abc',\n    });\n\n    expect(result).toBe(initial);\n  });\n\n  it('should do nothing if first element does not have a resource', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    const initial = restore(state);\n\n    // Combine element 789 into 456 (789 does not have a resource)\n    const result = combineElements({\n      firstElement: state.pages[0].elements[2],\n      secondId: '456',\n    });\n\n    expect(result).toBe(initial);\n  });\n\n  it('should combine elements when the origin does not exist as an element', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    restore(state);\n\n    // Combine non-existing element into 789\n    const result = combineElements({\n      firstElement: {\n        id: 'abc',\n        type: 'video',\n        focalX: 20,\n        resource: { type: 'video', src: '1' },\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n      },\n      secondId: '789',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        type: 'shape',\n        isBackground: true,\n        isDefaultBackground: true,\n        x: 1,\n        y: 1,\n        width: 1,\n        height: 1,\n      },\n      {\n        id: '456',\n        type: 'video',\n        focalX: 20,\n        resource: { type: 'video', src: '1' },\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n        tracks: ['track-1'],\n      },\n      {\n        id: '789',\n        resource: { type: 'video', src: '1' },\n        type: 'video',\n        // Note that focalX is copied and focalY is reset to 50\n        focalX: 20,\n        focalY: 50,\n        scale: 100,\n        x: 20,\n        y: 20,\n        width: 20,\n        height: 20,\n        flip: {\n          vertical: false,\n          horizontal: true,\n        },\n        overlay: { r: 1, g: 1, b: 1 },\n      },\n    ]);\n  });\n\n  it('should add the relevant properties from first to second', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    restore(state);\n\n    // Combine element 456 into 789\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '789',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        type: 'shape',\n        isBackground: true,\n        isDefaultBackground: true,\n        x: 1,\n        y: 1,\n        width: 1,\n        height: 1,\n      },\n      {\n        id: '789',\n        resource: { type: 'video', src: '1' },\n        type: 'video',\n        // Note that focalX is copied and focalY is reset to 50\n        focalX: 20,\n        focalY: 50,\n        scale: 100,\n        x: 20,\n        y: 20,\n        width: 20,\n        height: 20,\n        tracks: ['track-1'],\n        flip: {\n          vertical: false,\n          horizontal: true,\n        },\n        overlay: { r: 1, g: 1, b: 1 },\n      },\n    ]);\n  });\n\n  it('should preserve selection if first element was selected and second was background', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    restore(state);\n\n    // Combine element 456 into 123\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '123',\n    });\n\n    expect(result.selection).toStrictEqual(['123']);\n  });\n\n  it('should preserve selection if first element was selected and second was not background', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    restore(state);\n\n    // Combine element 456 into 789\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '789',\n    });\n\n    expect(result.selection).toStrictEqual(['789']);\n  });\n\n  it('should keep the poster of the first video', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState4();\n    restore(getDefaultState4());\n\n    // Combine element 789 into 007\n    const result = combineElements({\n      firstElement: state.pages[0].elements[2],\n      secondId: '007',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        type: 'image',\n        overlay: { color: { r: 0, g: 0, b: 0 } },\n        isBackground: true,\n        x: 1,\n        y: 1,\n        width: 1,\n        height: 1,\n      },\n      {\n        id: '456',\n        type: 'image',\n        resource: { type: 'image', src: '1' },\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n        link: {\n          url: 'https://link456.example/',\n          icon: 'https://link456.example/image.png',\n          desc: 'Lorem ipsum dolor',\n        },\n      },\n      {\n        id: '007',\n        type: 'video',\n        resource: { type: 'video', src: '2' },\n        focalX: 50,\n        focalY: 50,\n        scale: 100,\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n        link: {\n          url: 'https://link789.example/',\n          icon: 'https://link789.example/image.png',\n          desc: 'Lorem ipsum dolor',\n        },\n        poster: 'img.jpg',\n      },\n    ]);\n  });\n\n  it('should not remove background overlay if present on second element', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState3();\n    restore(getDefaultState3());\n\n    // Combine element 456 into 123\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '123',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        resource: { type: 'image', src: '1' },\n        type: 'image',\n        focalX: 50,\n        focalY: 50,\n        scale: 100,\n        overlay: { color: { r: 0, g: 0, b: 0 } },\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n        isBackground: true,\n      },\n    ]);\n  });\n\n  it('should copy dimensions too if combining with background element', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState2();\n    restore(state);\n\n    // Combine element 456 into 123\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '123',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        resource: { type: 'image', src: '1' },\n        alt: 'Hello',\n        type: 'image',\n        focalX: 50,\n        focalY: 50,\n        scale: 100,\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n        isBackground: true,\n      },\n    ]);\n  });\n\n  it('should be able to copy properties from given element rather than existing', () => {\n    const { restore, combineElements } = setupReducer();\n\n    restore(getDefaultState2());\n\n    // Combine new element into 123\n    const result = combineElements({\n      firstElement: {\n        type: 'image',\n        resource: { type: 'image', src: '2' },\n        width: 30,\n        height: 30,\n        x: 30,\n        y: 30,\n      },\n      secondId: '123',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        resource: { type: 'image', src: '2' },\n        type: 'image',\n        focalX: 50,\n        focalY: 50,\n        scale: 100,\n        x: 30,\n        y: 30,\n        width: 30,\n        height: 30,\n        isBackground: true,\n      },\n      {\n        id: '456',\n        type: 'image',\n        resource: { type: 'image', src: '1' },\n        alt: 'Hello',\n        x: 10,\n        y: 10,\n        width: 10,\n        height: 10,\n      },\n    ]);\n  });\n\n  it('should create default background element when combining into that', () => {\n    const { restore, combineElements } = setupReducer();\n\n    const state = getDefaultState1();\n    restore(state);\n\n    // Combine element 456 into 123\n    const result = combineElements({\n      firstElement: state.pages[0].elements[1],\n      secondId: '123',\n    });\n\n    expect(result.pages[0].defaultBackgroundElement).toStrictEqual({\n      // Note that id is regenerated. It doesn't matter what it is, just\n      // has to be unique and different from current\n      id: expect.not.stringMatching('/^123$/'),\n      type: 'shape',\n      isBackground: true,\n      isDefaultBackground: true,\n      x: 1,\n      y: 1,\n      width: 1,\n      height: 1,\n    });\n  });\n\n  describe('combine elements with links', () => {\n    it('should not preserve link if combining with background element', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState4();\n      restore(state);\n\n      // Combine element 456 into 123\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '123',\n      });\n\n      expect(result.pages[0].elements[0]).toStrictEqual({\n        id: '123',\n        isBackground: true,\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        overlay: { color: { r: 0, g: 0, b: 0 } },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n      });\n    });\n\n    it('should preserve the origin element link if combining with another', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState4();\n      restore(state);\n\n      // Combine element 456 into 789\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '789',\n      });\n\n      expect(result.pages[0].elements[1]).toStrictEqual({\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        id: '789',\n        link: {\n          url: 'https://link456.example/',\n          icon: 'https://link456.example/image.png',\n          desc: 'Lorem ipsum dolor',\n        },\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n        poster: 'img.jpg',\n      });\n    });\n\n    it('should preserve the target element link if the origin is without link', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState4();\n      restore(state);\n\n      // Combine element 456 into 789\n      const result = combineElements({\n        firstElement: state.pages[0].elements[3],\n        secondId: '789',\n      });\n\n      expect(result.pages[0].elements[2]).toStrictEqual({\n        height: 10,\n        id: '789',\n        link: {\n          url: 'https://link789.example/',\n          icon: 'https://link789.example/image.png',\n          desc: 'Lorem ipsum dolor',\n        },\n        resource: {\n          src: '3',\n          type: 'video',\n        },\n        poster: 'img.jpg',\n        scale: 100,\n        type: 'video',\n        width: 10,\n        x: 10,\n        y: 10,\n        focalX: 50,\n        focalY: 50,\n      });\n    });\n  });\n\n  describe('combine elements with borders', () => {\n    it('should not preserve border if combining with background element', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState5();\n      restore(state);\n\n      // Combine element 456 into 123\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '123',\n      });\n\n      expect(result.pages[0].elements[0]).toStrictEqual({\n        id: '123',\n        isBackground: true,\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        overlay: { color: { r: 0, g: 0, b: 0 } },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n      });\n    });\n\n    it('should preserve the origin element border if combining into rectangle', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState5();\n      restore(state);\n\n      // Combine element 456 into 101\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '101',\n      });\n\n      expect(result.pages[0].elements[2]).toStrictEqual({\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        id: '101',\n        mask: {\n          type: MaskTypes.RECTANGLE,\n        },\n        border: {\n          top: 10,\n          left: 10,\n          right: 10,\n          bottom: 10,\n        },\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n      });\n    });\n\n    it('should preserve the border of origin element even when combining with non-rectangular', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState5();\n      restore(state);\n\n      // Combine element 456 into 789\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '789',\n      });\n\n      expect(result.pages[0].elements[1]).toStrictEqual({\n        height: 10,\n        id: '789',\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        mask: {\n          type: 'circle',\n        },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n        focalX: 50,\n        focalY: 50,\n        border: {\n          bottom: 10,\n          left: 10,\n          right: 10,\n          top: 10,\n        },\n      });\n    });\n  });\n\n  describe('combine elements with border radius', () => {\n    it('should not preserve border if combining with background element', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState6();\n      restore(state);\n\n      // Combine element 456 into 123\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '123',\n      });\n\n      expect(result.pages[0].elements[0]).toStrictEqual({\n        id: '123',\n        isBackground: true,\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        overlay: { color: { r: 0, g: 0, b: 0 } },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n      });\n    });\n\n    it('should preserve the origin element border if combining into rectangle', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState6();\n      restore(state);\n\n      // Combine element 456 into 101\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '101',\n      });\n\n      expect(result.pages[0].elements[2]).toStrictEqual({\n        focalX: 50,\n        focalY: 50,\n        height: 10,\n        id: '101',\n        mask: {\n          type: MaskTypes.RECTANGLE,\n        },\n        borderRadius: {\n          topLeft: 10,\n          topRight: 10,\n          bottomRight: 10,\n          bottomLeft: 10,\n        },\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n      });\n    });\n\n    it('should not preserve the border radius of origin element when combining with non-rectangular', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState6();\n      restore(state);\n\n      // Combine element 456 into 789\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '789',\n      });\n\n      expect(result.pages[0].elements[1]).toStrictEqual({\n        height: 10,\n        id: '789',\n        resource: {\n          src: '1',\n          type: 'image',\n        },\n        mask: {\n          type: 'circle',\n        },\n        scale: 100,\n        type: 'image',\n        width: 10,\n        x: 10,\n        y: 10,\n        focalX: 50,\n        focalY: 50,\n      });\n    });\n  });\n\n  describe('combine elements with animations', () => {\n    it('should by default remove animations only from the original element', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState7();\n      restore(state);\n\n      // Combine element 456 into 789\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '789',\n      });\n\n      expect(result.pages[0].animations).toStrictEqual([\n        { id: 'b', targets: ['789'] },\n      ]);\n    });\n\n    it('should remove animations from both elements if instructed', () => {\n      const { restore, combineElements } = setupReducer();\n\n      const state = getDefaultState7();\n      restore(state);\n\n      // Combine element 456 into 789 with retain elements flag set to false\n      const result = combineElements({\n        firstElement: state.pages[0].elements[1],\n        secondId: '789',\n        shouldRetainAnimations: false,\n      });\n\n      expect(result.pages[0].animations).toStrictEqual([]);\n    });\n  });\n});\n\nfunction getDefaultState1() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'shape',\n            isBackground: true,\n            isDefaultBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'video',\n            focalX: 20,\n            resource: { type: 'video', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            tracks: ['track-1'],\n          },\n          {\n            id: '789',\n            type: 'shape',\n            focalX: 10,\n            focalY: 100,\n            x: 20,\n            y: 20,\n            width: 20,\n            height: 20,\n            flip: {\n              vertical: false,\n              horizontal: true,\n            },\n            overlay: { r: 1, g: 1, b: 1 },\n          },\n        ],\n      },\n    ],\n    current: '111',\n    selection: ['456'],\n  };\n}\n\nfunction getDefaultState2() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'shape',\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            alt: 'Hello',\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n\nfunction getDefaultState3() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'image',\n            overlay: { color: { r: 0, g: 0, b: 0 } },\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n\n// State with background element, 2 elements with links, 1 without.\nfunction getDefaultState4() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'image',\n            overlay: { color: { r: 0, g: 0, b: 0 } },\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            link: {\n              url: 'https://link456.example/',\n              icon: 'https://link456.example/image.png',\n              desc: 'Lorem ipsum dolor',\n            },\n          },\n          {\n            id: '789',\n            type: 'video',\n            resource: { type: 'video', src: '2' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            link: {\n              url: 'https://link789.example/',\n              icon: 'https://link789.example/image.png',\n              desc: 'Lorem ipsum dolor',\n            },\n            poster: 'img.jpg',\n          },\n          {\n            id: '007',\n            type: 'video',\n            resource: { type: 'video', src: '3' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n\n// Page with rectangular element with border, circular without border, rectangle without border.\nfunction getDefaultState5() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'image',\n            overlay: { color: { r: 0, g: 0, b: 0 } },\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            border: {\n              top: 10,\n              left: 10,\n              right: 10,\n              bottom: 10,\n            },\n          },\n          {\n            id: '789',\n            type: 'shape',\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            mask: {\n              type: MaskTypes.CIRCLE,\n            },\n          },\n          {\n            id: '101',\n            type: 'shape',\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            mask: {\n              type: MaskTypes.RECTANGLE,\n            },\n            border: {\n              top: 2,\n              left: 2,\n              right: 2,\n              bottom: 2,\n            },\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n\n// Page with rectangular element with border radius, circular without, rectangle without.\nfunction getDefaultState6() {\n  return {\n    pages: [\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'image',\n            overlay: { color: { r: 0, g: 0, b: 0 } },\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            borderRadius: {\n              topLeft: 10,\n              topRight: 10,\n              bottomRight: 10,\n              bottomLeft: 10,\n            },\n          },\n          {\n            id: '789',\n            type: 'shape',\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            mask: {\n              type: MaskTypes.CIRCLE,\n            },\n          },\n          {\n            id: '101',\n            type: 'shape',\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n            mask: {\n              type: MaskTypes.RECTANGLE,\n            },\n            borderRadius: {\n              topLeft: 1,\n              topRight: 1,\n              bottomRight: 1,\n              bottomLeft: 1,\n            },\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n\n// State with background element, 1 media element, 1 shape, and animations on both latter elements\nfunction getDefaultState7() {\n  return {\n    pages: [\n      {\n        id: '111',\n        animations: [\n          { id: 'a', targets: ['456'] },\n          { id: 'b', targets: ['789'] },\n        ],\n        elements: [\n          {\n            id: '123',\n            type: 'image',\n            overlay: { color: { r: 0, g: 0, b: 0 } },\n            isBackground: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n          },\n          {\n            id: '456',\n            type: 'image',\n            resource: { type: 'image', src: '1' },\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n          },\n          {\n            id: '789',\n            type: 'shape',\n            x: 10,\n            y: 10,\n            width: 10,\n            height: 10,\n          },\n        ],\n      },\n    ],\n    current: '111',\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/copySelectedElement.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('copySelectedElement', () => {\n  it('should do nothing if no selection', () => {\n    const { restore, copySelectedElement } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = copySelectedElement();\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('copies the styles of an element and animations', () => {\n    const { restore, copySelectedElement } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [{ id: '1234', targets: ['456'], effect: 'bounce' }],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            {\n              id: '456',\n              x: 0,\n              y: 0,\n              type: 'shape',\n              background: 'blue',\n              backgroundColor: 'red',\n              backgroundTextMode: null,\n              textAlign: 'middle',\n            },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['456'],\n    });\n\n    const result = copySelectedElement();\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      copiedElementState: {\n        animations: [\n          {\n            effect: 'bounce',\n            id: '1234',\n            targets: ['456'],\n          },\n        ],\n        styles: {\n          background: 'blue',\n          backgroundColor: 'red',\n          backgroundTextMode: null,\n          textAlign: 'middle',\n        },\n        type: 'shape',\n      },\n    });\n  });\n\n  it('copies the styles of an element if no animations', () => {\n    const { restore, copySelectedElement } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            {\n              id: '456',\n              x: 0,\n              y: 0,\n              type: 'shape',\n              background: 'blue',\n              backgroundColor: 'red',\n              backgroundTextMode: null,\n              textAlign: 'middle',\n            },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['456'],\n    });\n\n    const result = copySelectedElement();\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      copiedElementState: {\n        animations: [],\n        styles: {\n          background: 'blue',\n          backgroundColor: 'red',\n          backgroundTextMode: null,\n          textAlign: 'middle',\n        },\n        type: 'shape',\n      },\n    });\n  });\n\n  it('should not update state if multiple elements selected', () => {\n    const { restore, copySelectedElement } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = copySelectedElement();\n\n    expect(result).toStrictEqual(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteCurrentPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteCurrentPage', () => {\n  it('should update the current page to the next one if possible, otherwise previous', () => {\n    const { restore, deleteCurrentPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }, { id: '333' }, { id: '444' }],\n      current: '333',\n    });\n\n    // Delete page 333 (not last) and 444 becomes current\n    const firstResult = deleteCurrentPage();\n    const firstSetOfPageIds = firstResult.pages.map(({ id }) => id);\n    expect(firstSetOfPageIds).toStrictEqual(['111', '222', '444']);\n    expect(firstResult.current).toBe('444');\n\n    // Now delete page 444 (last) and 222 becomes current\n    const secondResult = deleteCurrentPage();\n    const secondSetOfPageIds = secondResult.pages.map(({ id }) => id);\n    expect(secondSetOfPageIds).toStrictEqual(['111', '222']);\n    expect(secondResult.current).toBe('222');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteElementById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteElementById', () => {\n  it('should delete the given element', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with a current page with two elements.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementById({ elementId: '456' });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123' }] },\n    ]);\n  });\n\n  it('should ignore an unknown element (on the current page)', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with multiple pages with elements.\n    restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }] },\n        { id: '222', elements: [{ id: '456' }] },\n      ],\n      current: '111',\n    });\n\n    // 456 does not exist on current page, so nothing happens\n    const result = deleteElementById({ elementId: '456' });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123' }] },\n      { id: '222', elements: [{ id: '456' }] },\n    ]);\n  });\n\n  it('should remove the deleted element from selection if exists', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with a current page and a selected element.\n    const initialState = restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n      selection: ['123', '456'],\n    });\n\n    const result = deleteElementById({ elementId: '456' });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [{ id: '111', elements: [{ id: '123' }] }],\n      selection: ['123'],\n    });\n  });\n\n  it('should not allow deleting default background element', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with a current page and a selected element.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isDefaultBackground: true },\n            { id: '456' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['456'],\n    });\n\n    const result = deleteElementById({ elementId: '123' });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should restore default background element if non-default background element is deleted', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with a current page and a selected element.\n    restore({\n      pages: [\n        {\n          id: '111',\n          defaultBackgroundElement: {\n            id: '000',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          elements: [{ id: '123', isBackground: true }, { id: '456' }],\n        },\n      ],\n    });\n\n    const result = deleteElementById({ elementId: '123' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '000',\n        isDefaultBackground: true,\n        isBackground: true,\n      },\n      { id: '456' },\n    ]);\n  });\n\n  it('should delete the given element and any animations belonging to it', () => {\n    const { restore, deleteElementById } = setupReducer();\n\n    // Set an initial state with a current page with two elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: 'a', targets: ['456'] },\n            { id: 'b', targets: ['123'] },\n          ],\n          elements: [{ id: '123' }, { id: '456' }],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementById({ elementId: '456' });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        animations: [{ id: 'b', targets: ['123'] }],\n        elements: [{ id: '123' }],\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteElementsById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteElementsById', () => {\n  it('should remove the deleted elements', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementsById({ elementIds: ['789', '456'] });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [{ id: '111', elements: [{ id: '123', isBackground: true }] }],\n    });\n  });\n\n  it('should skip unknown elements', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementsById({ elementIds: ['456', '000'] });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '789' }],\n        },\n      ],\n    });\n  });\n\n  it('should do nothing if no elements', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementsById({ elementIds: [] });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if only unknown elements', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteElementsById({ elementIds: ['000', '999'] });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should remove any deleted elements from selection too', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234' },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['234', '789'],\n    });\n\n    // 789 is selected, 456 is not\n    const result = deleteElementsById({ elementIds: ['789', '456'] });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n        },\n      ],\n      selection: ['234'],\n    });\n  });\n\n  it('should skip default background element if included', () => {\n    const { restore, deleteElementsById } = setupReducer();\n\n    // Set an initial state with a current page and some elements\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isDefaultBackground: true },\n            { id: '234' },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 123 is the default background element\n    const result = deleteElementsById({ elementIds: ['123', '789', '456'] });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isDefaultBackground: true },\n            { id: '234' },\n          ],\n        },\n      ],\n      selection: [],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteElementsByResourceId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteElementsByResourceId', () => {\n  it('should remove the deleted elements', () => {\n    const { restore, deleteElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          defaultBackgroundElement: {\n            id: '1',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          elements: [\n            {\n              id: '789',\n              isBackground: true,\n              resource: { type: 'image', id: '11' },\n            },\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'video', id: '10' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            {\n              id: '456',\n              isBackground: true,\n              resource: { type: 'image', id: '11' },\n            },\n            { id: '123', resource: { type: 'video', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['456', '789'],\n    });\n\n    const result = deleteElementsByResourceId({\n      id: '10',\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        defaultBackgroundElement: {\n          id: '1',\n          isBackground: true,\n          isDefaultBackground: true,\n        },\n        elements: [\n          {\n            id: '789',\n            isBackground: true,\n            resource: { type: 'image', id: '11' },\n          },\n        ],\n      },\n      {\n        id: '222',\n        elements: [\n          {\n            id: '456',\n            isBackground: true,\n            resource: { type: 'image', id: '11' },\n          },\n        ],\n      },\n    ]);\n    expect(result.selection).toStrictEqual(['789']);\n  });\n\n  it('should insert default page background if deleting current background', () => {\n    const { restore, deleteElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          defaultBackgroundElement: { id: 'e0', type: 'shape' },\n          elements: [\n            {\n              id: '123',\n              isBackground: true,\n              resource: { type: 'image', id: '11' },\n            },\n            { id: '456', resource: { type: 'video', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['123'],\n    });\n\n    const result = deleteElementsByResourceId({\n      id: '11',\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        defaultBackgroundElement: { id: 'e0', type: 'shape' },\n        elements: [\n          { id: 'e0', type: 'shape' },\n          { id: '456', resource: { type: 'video', id: '10' } },\n        ],\n      },\n    ]);\n    expect(result.selection).toStrictEqual([]);\n  });\n\n  it('should remove any animations belonging to the deleted elements', () => {\n    const { restore, deleteElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: 'a', targets: ['123'] },\n            { id: 'b', targets: ['456'] },\n            { id: 'c', targets: ['789'] },\n          ],\n          defaultBackgroundElement: {\n            id: '1',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'video', id: '10' } },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          defaultBackgroundElement: {\n            id: '2',\n            isDefaultBackground: true,\n            isBackground: true,\n          },\n          animations: [{ id: 'd', targets: ['123'] }],\n          elements: [\n            {\n              id: '123',\n              resource: { type: 'video', id: '10' },\n              isBackground: true,\n            },\n            {\n              id: '456',\n              resource: { type: 'image', id: '11' },\n            },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteElementsByResourceId({\n      id: '10',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '1', isDefaultBackground: true, isBackground: true },\n      { id: '789', resource: { type: 'image', id: '11' } },\n    ]);\n    expect(result.pages[0].animations).toStrictEqual([\n      { id: 'c', targets: ['789'] },\n    ]);\n    expect(result.pages[1].elements).toStrictEqual([\n      { id: '2', isBackground: true, isDefaultBackground: true },\n      { id: '456', resource: { type: 'image', id: '11' } },\n    ]);\n    expect(result.pages[1].animations).toStrictEqual([]);\n  });\n\n  it('should do nothing if id not given', () => {\n    const { restore, deleteElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteElementsByResourceId({\n      id: null,\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no elements with given id', () => {\n    const { restore, deleteElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video' } },\n            { id: '456' },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteElementsByResourceId({\n      id: '12',\n    });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteGroupAndElementsById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteGroupAndElementsById', () => {\n  it('should do nothing if nothing supplied', () => {\n    const { restore, deleteGroupAndElementsById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupAndElementsById({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group does not exist', () => {\n    const { restore, deleteGroupAndElementsById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupAndElementsById({ groupId: 'g1' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should delete only the specified group and all members', () => {\n    const { restore, deleteGroupAndElementsById } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345', groupId: 'g1' },\n            { id: '456', groupId: 'g2' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupAndElementsById({ groupId: 'g1' });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '123', isBackground: true },\n        { id: '456', groupId: 'g2' },\n      ],\n      groups: {\n        g2: { name: 'Group 2' },\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteGroupById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteGroupById', () => {\n  it('should do nothing if nothing supplied', () => {\n    const { restore, deleteGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupById({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group does not exist', () => {\n    const { restore, deleteGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupById({ groupId: 'g1' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should delete only the specified group and unset group on members', () => {\n    const { restore, deleteGroupById } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', groupId: 'g1' },\n            { id: '345', groupId: 'g1' },\n            { id: '456', groupId: 'g2' },\n          ],\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = deleteGroupById({ groupId: 'g1' });\n\n    expect(result.pages[0]).toStrictEqual({\n      id: '111',\n      elements: [\n        { id: '123', isBackground: true },\n        { id: '234' },\n        { id: '345' },\n        { id: '456', groupId: 'g2' },\n      ],\n      groups: {\n        g2: { name: 'Group 2' },\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deletePage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deletePage', () => {\n  it('should delete the specified page', () => {\n    const { restore, deletePage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({ pages: [{ id: '111' }, { id: '222' }] });\n\n    const result = deletePage({ pageId: '222' });\n\n    expect(result.pages).toStrictEqual([{ id: '111' }]);\n  });\n\n  it(\"should not delete the page if it's the only page\", () => {\n    const { restore, deletePage } = setupReducer();\n\n    // Set an initial state with only one page.\n    const initialState = restore({ pages: [{ id: '111' }] });\n\n    const result = deletePage({ pageId: '111' });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('should ignore unknown page ids', () => {\n    const { restore, deletePage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({ pages: [{ id: '111' }, { id: '222' }] });\n\n    const result = deletePage({ pageId: '333' });\n\n    expect(result).toStrictEqual(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/deleteSelectedElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('deleteSelectedElements', () => {\n  it('should remove the selected elements and clear selection', () => {\n    const { restore, deleteSelectedElements } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = deleteSelectedElements();\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [{ id: '111', elements: [{ id: '123', isBackground: true }] }],\n      selection: [],\n    });\n  });\n\n  it('should do nothing if no elements selected', () => {\n    const { restore, deleteSelectedElements } = setupReducer();\n\n    // Set an initial state with a current page and some elements, none selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = deleteSelectedElements();\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/duplicateElementsById.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('duplicateElementsById', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('duplicates an element at index after specified element', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['456'] });\n    const newElementId = result.pages[0].elements.find(\n      (el) => !initialState.pages[0].elements.includes(el)\n    ).id;\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: [newElementId],\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            expect.objectContaining({\n              id: '123',\n              isBackground: true,\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '456', x: 0, y: 0, type: 'shape' }),\n            expect.objectContaining({\n              id: expect.any(String),\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '789', x: 0, y: 0, type: 'shape' }),\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should not update state if non-existent element ids are passed in', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['not-an-id'] });\n\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it(\"doesn't duplicate background elements\", () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['123'] });\n    expect(result).toStrictEqual(initialState);\n  });\n\n  it('duplicates an elements animations', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n          ],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['456'] });\n    const newElement = result.pages[0].elements.find(\n      (el) => !initialState.pages[0].elements.includes(el)\n    );\n    expect(result.selection).toHaveLength(1);\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: [newElement.id],\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n            {\n              id: expect.any(String),\n              targets: [newElement.id],\n              type: 'wild_wacky_animation',\n            },\n          ],\n          elements: [\n            expect.objectContaining({\n              id: '123',\n              isBackground: true,\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '456', x: 0, y: 0, type: 'shape' }),\n            expect.objectContaining({\n              id: expect.any(String),\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '789', x: 0, y: 0, type: 'shape' }),\n          ],\n        },\n      ],\n    });\n  });\n\n  it('places duplicated element in a new location', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['456'] });\n    const initialElement = initialState.pages[0].elements.find(\n      (el) => el.id === '456'\n    );\n    const newElement = result.pages[0].elements.find(\n      (el) => !initialState.pages[0].elements.includes(el)\n    );\n    expect(result.pages[0].elements).toHaveLength(4);\n    expect(initialElement.x).not.toBe(newElement.x);\n    expect(initialElement.y).not.toBe(newElement.y);\n  });\n\n  it('should duplicate multiple non-background elements', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n          ],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'image' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['123', '456', '789'] });\n    const newElementIds = result.pages[0].elements\n      .filter((el) => !initialState.pages[0].elements.includes(el))\n      .map((el) => el.id);\n\n    expect(newElementIds).toHaveLength(2);\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: expect.arrayContaining(newElementIds),\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n            {\n              id: expect.any(String),\n              targets: expect.not.arrayContaining(['456']),\n              type: 'wild_wacky_animation',\n            },\n          ],\n          elements: [\n            expect.objectContaining({\n              id: '123',\n              isBackground: true,\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '456', x: 0, y: 0, type: 'shape' }),\n            expect.objectContaining({\n              id: expect.any(String),\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '789', x: 0, y: 0, type: 'image' }),\n            expect.objectContaining({\n              id: expect.any(String),\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'image',\n            }),\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should only duplicate existing elements', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n          ],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'shape' },\n            { id: '789', x: 0, y: 0, type: 'image' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({\n      elementIds: ['456', 'not-an-existing-element'],\n    });\n    const newElementId = result.pages[0].elements.find(\n      (el) => !initialState.pages[0].elements.includes(el)\n    ).id;\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: [newElementId],\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: '1', targets: ['456'], type: 'wild_wacky_animation' },\n            {\n              id: expect.any(String),\n              targets: expect.not.arrayContaining(['456']),\n              type: 'wild_wacky_animation',\n            },\n          ],\n          elements: [\n            expect.objectContaining({\n              id: '123',\n              isBackground: true,\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '456', x: 0, y: 0, type: 'shape' }),\n            expect.objectContaining({\n              id: expect.any(String),\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '789', x: 0, y: 0, type: 'image' }),\n          ],\n        },\n      ],\n    });\n  });\n\n  it('should skip product elements', () => {\n    const { restore, duplicateElementsById } = setupReducer();\n\n    // Set an initial state with a current page.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            { id: '123', isBackground: true, type: 'shape' },\n            { id: '456', x: 0, y: 0, type: 'product' },\n            { id: '789', x: 0, y: 0, type: 'shape' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['789', '456'],\n    });\n\n    const result = duplicateElementsById({ elementIds: ['456', '789'] });\n\n    const newElementId = result.pages[0].elements.find(\n      (el) => !initialState.pages[0].elements.includes(el)\n    ).id;\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: [newElementId],\n      pages: [\n        {\n          id: '111',\n          animations: [],\n          elements: [\n            expect.objectContaining({\n              id: '123',\n              isBackground: true,\n              type: 'shape',\n            }),\n            expect.objectContaining({ id: '456', x: 0, y: 0, type: 'product' }),\n            expect.objectContaining({ id: '789', x: 0, y: 0, type: 'shape' }),\n            expect.objectContaining({\n              id: newElementId,\n              x: expect.any(Number),\n              y: expect.any(Number),\n              type: 'shape',\n            }),\n          ],\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/duplicateGroupById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('duplicateGroupById', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should do nothing if nothing supplied', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no new group id supplied', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({ oldGroupId: 'g1' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no new group name supplied', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({ oldGroupId: 'g1', groupId: 'g2' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no old group does not exist', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({\n      oldGroupId: 'g1',\n      groupId: 'g2',\n      name: 'Group 1 Copy',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no old group has no members', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({\n      oldGroupId: 'g1',\n      groupId: 'g2',\n      name: 'Group 1 Copy',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if group contains background', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', type: 'shape', isBackground: true, groupId: 'g1' },\n            { id: '234' },\n          ],\n          groups: { g1: { name: 'Group 1' } },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({\n      oldGroupId: 'g1',\n      groupId: 'g2',\n      name: 'Group 1 Copy',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should make a duplicate with all elements', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', type: 'shape', border: { width: 1 }, groupId: 'g1' },\n            { id: '345', type: 'shape', border: { width: 3 }, groupId: 'g1' },\n            { id: '456', groupId: 'g2' },\n            { id: '567' },\n          ],\n          groups: {\n            g1: { name: 'Group 1', isLocked: false },\n            g2: { name: 'Group 2', isLocked: false },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({\n      oldGroupId: 'g1',\n      groupId: 'g3',\n      name: 'Group 1 Copy',\n    });\n\n    expect(result.pages[0]).toStrictEqual(\n      expect.objectContaining({\n        elements: [\n          { id: '123', isBackground: true },\n          { id: '234', type: 'shape', border: { width: 1 }, groupId: 'g1' },\n          { id: '345', type: 'shape', border: { width: 3 }, groupId: 'g1' },\n          expect.objectContaining({\n            id: expect.any(String),\n            type: 'shape',\n            border: { width: 1 },\n            groupId: 'g3',\n          }),\n          expect.objectContaining({\n            id: expect.any(String),\n            type: 'shape',\n            border: { width: 3 },\n            groupId: 'g3',\n          }),\n          {\n            id: '456',\n            groupId: 'g2',\n          },\n          {\n            id: '567',\n          },\n        ],\n        groups: {\n          g1: { name: 'Group 1', isLocked: false },\n          g2: { name: 'Group 2', isLocked: false },\n          g3: { name: 'Group 1 Copy', isLocked: false },\n        },\n      })\n    );\n  });\n\n  it('should append new animations to existing', () => {\n    const { restore, duplicateGroupById } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          animations: [\n            { id: 'a1', targets: ['234'], x: 1 },\n            { id: 'a2', targets: ['234'], x: 2 },\n            { id: 'a3', targets: ['456'], x: 3 },\n          ],\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '234', type: 'shape', border: { width: 1 }, groupId: 'g1' },\n            { id: '345', type: 'shape', border: { width: 3 }, groupId: 'g1' },\n            { id: '456', groupId: 'g2' },\n            { id: '567' },\n          ],\n          groups: {\n            g1: { name: 'Group 1', isLocked: false },\n            g2: { name: 'Group 2', isLocked: false },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = duplicateGroupById({\n      oldGroupId: 'g1',\n      groupId: 'g3',\n      name: 'Group 1 Copy',\n    });\n\n    expect(result.pages[0]).toStrictEqual(\n      expect.objectContaining({\n        animations: [\n          { id: 'a1', targets: ['234'], x: 1 },\n          { id: 'a2', targets: ['234'], x: 2 },\n          { id: 'a3', targets: ['456'], x: 3 },\n          { id: expect.any(String), targets: [expect.any(String)], x: 1 },\n          { id: expect.any(String), targets: [expect.any(String)], x: 2 },\n        ],\n        elements: [\n          { id: '123', isBackground: true },\n          { id: '234', type: 'shape', border: { width: 1 }, groupId: 'g1' },\n          { id: '345', type: 'shape', border: { width: 3 }, groupId: 'g1' },\n          expect.objectContaining({\n            id: expect.any(String),\n            type: 'shape',\n            border: { width: 1 },\n            groupId: 'g3',\n          }),\n          expect.objectContaining({\n            id: expect.any(String),\n            type: 'shape',\n            border: { width: 3 },\n            groupId: 'g3',\n          }),\n          {\n            id: '456',\n            groupId: 'g2',\n          },\n          {\n            id: '567',\n          },\n        ],\n        groups: {\n          g1: { name: 'Group 1', isLocked: false },\n          g2: { name: 'Group 2', isLocked: false },\n          g3: { name: 'Group 1 Copy', isLocked: false },\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/reducer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport reducer from '../reducer';\n\ndescribe('reducer', () => {\n  it('should do nothing if unknown action given', () => {\n    const initialState = { pages: [] };\n\n    const result = reducer(initialState, {\n      type: 'UNKNOWN_ACTION',\n      payload: {},\n    });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/removeElementFromGroup.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('removeElementFromGroup', () => {\n  it('should do nothing if element is not in group', () => {\n    const { restore, removeElementFromGroup } = setupReducer();\n    const initialState = restore({\n      current: 'p1',\n      selection: ['e2'],\n      pages: [\n        {\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g1' },\n            { id: 'e5', groupId: 'g2' },\n          ],\n          id: 'p1',\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n    });\n\n    const result = removeElementFromGroup({\n      elementId: 'e2',\n      groupId: 'g1',\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should move element out of group', () => {\n    const { restore, removeElementFromGroup } = setupReducer();\n    restore({\n      current: 'p1',\n      selection: ['e2'],\n      pages: [\n        {\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g1' },\n            { id: 'e5', groupId: 'g2' },\n          ],\n          id: 'p1',\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n    });\n\n    const result = removeElementFromGroup({\n      elementId: 'e3',\n      groupId: 'g1',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: 'e1', isBackground: true },\n      { id: 'e2' },\n      { id: 'e4', groupId: 'g1' },\n      { id: 'e3' },\n      { id: 'e5', groupId: 'g2' },\n    ]);\n  });\n\n  it('should remove element from group but not reorder if already last element', () => {\n    const { restore, removeElementFromGroup } = setupReducer();\n    restore({\n      current: 'p1',\n      selection: ['e2'],\n      pages: [\n        {\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g1' },\n            { id: 'e5', groupId: 'g2' },\n          ],\n          id: 'p1',\n          groups: {\n            g1: { name: 'Group 1' },\n            g2: { name: 'Group 2' },\n          },\n        },\n      ],\n    });\n\n    const result = removeElementFromGroup({\n      elementId: 'e4',\n      groupId: 'g1',\n    });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: 'e1', isBackground: true },\n      { id: 'e2' },\n      { id: 'e3', groupId: 'g1' },\n      { id: 'e4' },\n      { id: 'e5', groupId: 'g2' },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/removeElementFromSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('removeElementFromSelection', () => {\n  it('should remove element from selection (if even there)', () => {\n    const { restore, removeElementFromSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }] },\n      ],\n      current: '111',\n      selection: ['e1', 'e2'],\n    });\n\n    expect(initialState.selection).toContain('e1');\n\n    // Remove element e1\n    const firstResult = removeElementFromSelection({ elementId: 'e1' });\n    expect(firstResult.selection).not.toContain('e1');\n\n    // Remove element e1 again - nothing happens\n    const secondResult = removeElementFromSelection({ elementId: 'e1' });\n    expect(secondResult).toStrictEqual(firstResult);\n  });\n\n  it('should ignore missing element id', () => {\n    const { restore, removeElementFromSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }] },\n      ],\n      current: '111',\n      selection: ['e1', 'e2'],\n    });\n\n    // Remove no element\n    const failedAttempt = removeElementFromSelection({ elementId: null });\n    expect(failedAttempt).toStrictEqual(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/restore.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('restore', () => {\n  it('should restore pages while defaulting selection and current', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    // Restore only pages variable, leave the other as defaults.\n    const pages = [{ id: '123' }];\n    const result = restore({ pages });\n\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      pages,\n      selection: [],\n      current: '123',\n      story: {},\n    });\n  });\n\n  it('should restore pages, current, capabilities, and selection', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    const result = restore({\n      pages: [{ id: '111' }, { id: '222', elements: [{ id: '333' }] }],\n      current: '222',\n      capabilities: { canDo: true },\n      selection: ['333'],\n    });\n\n    expect(result.pages).toHaveLength(2);\n    expect(result.current).toBe('222');\n    expect(result.capabilities).toStrictEqual({ canDo: true });\n    expect(result.selection).toHaveLength(1);\n  });\n\n  it('should restore story if set', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    const result = restore({\n      pages: [{ id: '111' }],\n      story: { a: 1, b: [2] },\n    });\n\n    expect(result.story).toStrictEqual({ a: 1, b: [2] });\n  });\n\n  it('should force current to be a valid page id', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    const result = restore({\n      pages: [{ id: '111' }],\n      current: '222',\n    });\n\n    expect(result.current).toBe('111');\n  });\n\n  it('should restore to an empty state if no pages', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    const result = restore({\n      pages: [],\n      current: '111',\n      selection: ['222'],\n      story: { a: 1 },\n    });\n\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      pages: [],\n      selection: [],\n      current: null,\n      story: { fonts: {} },\n    });\n  });\n\n  it('should restore to an empty state if empty', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    const result = restore({});\n\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      pages: [],\n      selection: [],\n      current: null,\n      story: { fonts: {} },\n    });\n  });\n\n  it('should override existing content', () => {\n    const reducer = setupReducer();\n\n    const { restore } = reducer;\n\n    // First restore to some non-initial state.\n    const stateWithContent = restore({\n      pages: [{ id: '111' }, { id: '222', elements: [{ id: '333' }] }],\n      current: '222',\n      selection: ['333'],\n      story: { a: 1 },\n    });\n\n    // And validate that it is non-initial.\n    expect(stateWithContent.pages).not.toHaveLength(0);\n    expect(stateWithContent.current).not.toBeNull();\n    expect(stateWithContent.selection).not.toHaveLength(0);\n    expect(Object.keys(stateWithContent.story)).not.toHaveLength(0);\n\n    // Then override by restoring to a new state.\n    const pages = [{ id: '123' }];\n    const result = restore({ pages });\n\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      pages,\n      selection: [],\n      current: '123',\n      story: {},\n    });\n  });\n\n  it('should restore with existing current page (if it exists in restore story) if no current page supplied', () => {\n    // Initialize state with a current story page.\n    const currentPage = { current: '222' };\n    const reducer = setupReducer(currentPage);\n    const { restore } = reducer;\n\n    // Restore state to hold story\n    const storyWithNoCurrentPage = {\n      pages: [{ id: '111' }, { id: '222', elements: [{ id: '333' }] }],\n      selection: ['333'],\n      story: { a: 1 },\n    };\n    const result = restore(storyWithNoCurrentPage);\n\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      ...storyWithNoCurrentPage,\n      ...currentPage,\n    });\n  });\n\n  it('should restore with first page as current if initialized with faulty current pageId', () => {\n    // Initialize state with a story page that does not exist\n    const currentPage = { current: 'DOES NOT EXIST' };\n    const reducer = setupReducer(currentPage);\n    const { restore } = reducer;\n\n    // Restore state to hold story\n    const storyWithNoCurrentPage = {\n      pages: [{ id: '111' }, { id: '222', elements: [{ id: '333' }] }],\n      selection: ['333'],\n      story: { a: 1 },\n    };\n    const result = restore(storyWithNoCurrentPage);\n\n    // Should set first story as current\n    expect(result).toStrictEqual({\n      animationState: StoryAnimationState.Reset,\n      capabilities: {},\n      copiedElementState: {},\n      ...storyWithNoCurrentPage,\n      current: '111',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/setBackgroundElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('setBackgroundElement', () => {\n  it('should set the given background opacity to 100', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000', isBackground: true },\n            { id: '123', opacity: 20, resource: {} },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = setBackgroundElement({ elementId: '123' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      {\n        id: '123',\n        isBackground: true,\n        isHidden: false,\n        opacity: 100,\n        resource: {},\n      },\n    ]);\n  });\n  it('should not set opacity for new background elements if none was present', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '000', isBackground: true },\n            { id: '123', resource: {} },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = setBackgroundElement({ elementId: '123' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '123', isBackground: true, isHidden: false, resource: {} },\n    ]);\n  });\n\n  it('should set the given background element and move it back', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and some elements.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456', resource: {} },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 456 is to be bg - move it back and set it as background\n    const result = setBackgroundElement({ elementId: '456' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '456', isBackground: true, isHidden: false, resource: {} },\n      { id: '789' },\n    ]);\n  });\n\n  it('should remove the new background element from selection if there is more than it there', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456', resource: {} },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['456', '789'],\n    });\n\n    // 456 is to be bg\n    const result = setBackgroundElement({ elementId: '456' });\n\n    expect(result.selection).toStrictEqual(['789']);\n  });\n\n  it('should do nothing if already background', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and some elements.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isHidden: false, opacity: 100 },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 123 is already bg\n    const result = setBackgroundElement({ elementId: '123' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if given unknown element', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and some elements.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isHidden: false, opacity: 100 },\n            { id: '456' },\n            { id: '789' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 000 doesn't exist - nothing happens\n    const result = setBackgroundElement({ elementId: '000' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should save default background element for later', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and no selection.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isDefaultBackground: true },\n            { id: '456' },\n            { id: '789', resource: {} },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 789 becomes background, 123 is deleted\n    const result = setBackgroundElement({ elementId: '789' });\n\n    expect(result.pages[0]).toStrictEqual(\n      expect.objectContaining({\n        defaultBackgroundElement: {\n          id: '123',\n          isBackground: true,\n          isDefaultBackground: true,\n        },\n        elements: [\n          { id: '789', isBackground: true, isHidden: false, resource: {} },\n          { id: '456' },\n        ],\n      })\n    );\n  });\n\n  it('should delete existing background element if not default', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and no selection.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789', resource: {} },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // 789 becomes background, 123 is deleted\n    const result = setBackgroundElement({ elementId: '789' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '789', isBackground: true, isHidden: false, resource: {} },\n      { id: '456' },\n    ]);\n  });\n\n  it('should also delete non-default background element from selection', () => {\n    const { restore, setBackgroundElement } = setupReducer();\n\n    // Set an initial state with a current page and background element selected.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true },\n            { id: '456' },\n            { id: '789', resource: {} },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['123'],\n    });\n\n    // 789 becomes background, 123 is deleted (also from selection)\n    const result = setBackgroundElement({ elementId: '789' });\n\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: '789', isBackground: true, isHidden: false, resource: {} },\n      { id: '456' },\n    ]);\n    expect(result.selection).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/setCurrentPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('setCurrentPage', () => {\n  it('should set current page if it exists', () => {\n    const { restore, setCurrentPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '111',\n    });\n\n    // Update current page to 222\n    const result = setCurrentPage({ pageId: '222' });\n\n    expect(result.current).toBe('222');\n  });\n\n  it('should ignore unknown pages', () => {\n    const { restore, setCurrentPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '111',\n    });\n\n    // Unknown page 333, do nothing\n    const result = setCurrentPage({ pageId: '333' });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if page is already selected', () => {\n    const { restore, setCurrentPage } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({\n      pages: [{ id: '111' }, { id: '222' }],\n      current: '111',\n    });\n\n    // Unknown page 333, do nothing\n    const result = setCurrentPage({ pageId: '111' });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/setSelectedElementsById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('setSelectedElementsById', () => {\n  it('should update selection', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n            { id: 'e4' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e4'],\n    });\n\n    // Select element 2 and 3\n    const result = setSelectedElementsById({ elementIds: ['e2', 'e3'] });\n\n    expect(result.selection).toStrictEqual(['e2', 'e3']);\n  });\n\n  it('should be able to get element ids from callback', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n            { id: 'e4' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e4'],\n    });\n\n    // Select element 3 in a callback\n    const elementIds = jest.fn().mockImplementation(() => ['e3']);\n    const result = setSelectedElementsById({ elementIds });\n\n    expect(result.selection).toStrictEqual(['e3']);\n    expect(elementIds).toHaveBeenCalledWith(['e2', 'e4']);\n  });\n\n  it('should update selection to include all elements in the same group', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', groupId: 'g1' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g2' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e4'],\n    });\n\n    // Select element 2 (which is in the same group as 3)\n    const result = setSelectedElementsById({\n      elementIds: ['e2'],\n      withLinked: true,\n    });\n\n    expect(result.selection).toStrictEqual(['e2', 'e3']);\n  });\n\n  it('should remove duplicates', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // Select element 2 and 3 (and 2 again for weird reasons)\n    const result = setSelectedElementsById({ elementIds: ['e2', 'e3', 'e2'] });\n\n    expect(result.selection).toStrictEqual(['e2', 'e3']);\n  });\n\n  it('should not update selection if nothing has changed', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e3', 'e2'],\n    });\n\n    // Update to e2+e3, which is the same as e3+e2.\n    const result = setSelectedElementsById({ elementIds: ['e2', 'e3'] });\n\n    expect(result.selection).toStrictEqual(['e3', 'e2']);\n  });\n\n  it('should remove background if included among other elements', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // Try setting all elements as selected\n    const result = setSelectedElementsById({ elementIds: ['e2', 'e1', 'e3'] });\n\n    expect(result.selection).toStrictEqual(['e2', 'e3']);\n  });\n\n  it('should remove video placeholder if included among other elements', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', resource: { isPlaceholder: true } },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // Try setting all elements as selected\n    const result = setSelectedElementsById({ elementIds: ['e2', 'e1', 'e3'] });\n\n    expect(result.selection).toStrictEqual(['e2', 'e3']);\n  });\n\n  it('should remove locked elements if included among other elements', () => {\n    const { restore, setSelectedElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3', isLocked: true },\n            { id: 'e4', isLocked: true },\n            { id: 'e5' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    // Try setting all but first element as selected\n    const result = setSelectedElementsById({\n      elementIds: ['e2', 'e5', 'e3', 'e4'],\n    });\n\n    expect(result.selection).toStrictEqual(['e2', 'e5']);\n  });\n\n  it('should not update animationState if nothing has changed', () => {\n    const { restore, setSelectedElementsById, updateAnimationState } =\n      setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e3'],\n    });\n\n    updateAnimationState({ animationState: StoryAnimationState.Playing });\n    const result = setSelectedElementsById({ elementIds: ['e3'] });\n\n    expect(result.animationState).toStrictEqual(StoryAnimationState.Playing);\n  });\n\n  it('should reset animationState if selection has changed', () => {\n    const { restore, setSelectedElementsById, updateAnimationState } =\n      setupReducer();\n\n    // Set an initial state.\n    restore({\n      animationState: StoryAnimationState.Playing,\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2'],\n    });\n\n    updateAnimationState({ animationState: StoryAnimationState.Playing });\n    const result = setSelectedElementsById({ elementIds: ['e3'] });\n\n    expect(result.animationState).toStrictEqual(StoryAnimationState.Reset);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/toggleElementInSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('toggleElementInSelection', () => {\n  it('should add/remove element in selection', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e3', 'e2'],\n    });\n\n    expect(initialState.selection).toContain('e3');\n\n    // Toggle element e3 - which would remove it from selection\n    const firstResult = toggleElementInSelection({ elementId: 'e3' });\n    expect(firstResult.selection).not.toContain('e3');\n\n    // Toggle element e3 again - which would add it to selection\n    const secondResult = toggleElementInSelection({ elementId: 'e3' });\n    expect(secondResult.selection).toContain('e3');\n  });\n\n  it('should add/remove all elements from same group in selection', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2', groupId: 'g1' },\n            { id: 'e3', groupId: 'g1' },\n            { id: 'e4', groupId: 'g2' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e4'],\n    });\n\n    expect(initialState.selection).toContain('e2');\n\n    // Toggle element e2 with linked - which would remove it from selection\n    const firstResult = toggleElementInSelection({\n      elementId: 'e2',\n      withLinked: true,\n    });\n    expect(firstResult.selection).not.toContain('e2');\n\n    // Toggle element e2 with linked again - which would add it\n    // *and* group member e3 to selection\n    const secondResult = toggleElementInSelection({\n      elementId: 'e2',\n      withLinked: true,\n    });\n    expect(secondResult.selection).toContain('e2');\n    expect(secondResult.selection).toContain('e3');\n  });\n\n  it('should ignore missing element id', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e1', 'e2'],\n    });\n\n    // Toggle no element\n    const failedAttempt = toggleElementInSelection({ elementId: null });\n    expect(failedAttempt).toStrictEqual(initialState);\n  });\n\n  it('should not allow adding background element to non-empty selection', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e3'],\n    });\n\n    // Toggle no element\n    const failedAttempt = toggleElementInSelection({ elementId: 'e1' });\n    expect(failedAttempt.selection).toStrictEqual(initialState.selection);\n  });\n\n  it('should remove background element from selection if adding a new one', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state with bg element selected\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e1'],\n    });\n\n    // Add a new element to selection - should expunge bg element from selection\n    const { selection } = toggleElementInSelection({ elementId: 'e2' });\n    expect(selection).not.toContain('e1');\n    expect(selection).toContain('e2');\n  });\n\n  it('should set selection to only new element if trying to add locked element to non-empty selection', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n            { id: 'e4', isLocked: true },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e2', 'e3'],\n    });\n\n    // Toggle e4\n    const onlyNewElement = toggleElementInSelection({ elementId: 'e4' });\n    expect(onlyNewElement.selection).toStrictEqual(['e4']);\n  });\n\n  it('should set selection to only new element if trying to add any element to selection of locked element', () => {\n    const { restore, toggleElementInSelection } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: 'e1', isBackground: true },\n            { id: 'e2' },\n            { id: 'e3' },\n            { id: 'e4', isLocked: true },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['e4'],\n    });\n\n    // Toggle e2\n    const onlyNewElement = toggleElementInSelection({ elementId: 'e2' });\n    expect(onlyNewElement.selection).toStrictEqual(['e2']);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/toggleLayer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('toggleLayer', () => {\n  it('adds an element to selection if meta key is pressed', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3' },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['2', '5', '4', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '3', metaKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['2', '5', '4', '6', '3'],\n    });\n  });\n\n  it('removes an element from selection if meta key is pressed', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3' },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['2', '5', '4', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '4', metaKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['2', '5', '6'],\n    });\n  });\n\n  it('replaces selection if meta key is pressed but new layer is locked', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3', isLocked: true },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['2', '5', '4', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '3', metaKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['3'],\n    });\n  });\n\n  it('replaces selection if meta key is pressed but old selection is locked', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3', isLocked: true },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['3'],\n    });\n\n    const result = toggleLayer({ elementId: '4', metaKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['4'],\n    });\n  });\n\n  it('selects a single element if no special keys are pressed', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3' },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['2', '5', '4', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '3' });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['3'],\n    });\n  });\n\n  it('selects everything between the element and the first element in the current selection', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3' },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['3', '5'],\n    });\n\n    const result = toggleLayer({ elementId: '6', shiftKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['3', '4', '5', '6'],\n    });\n  });\n\n  it('filters out locked elements when selecting a list of elements', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3', isLocked: true },\n            { id: '4' },\n            { id: '5', isLocked: true },\n            { id: '6' },\n            { id: '7' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['2', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '7', shiftKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['2', '4', '6', '7'],\n    });\n  });\n\n  it('reverses selection if the new element is before the first one', () => {\n    const { restore, toggleLayer } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '1', isBackground: true },\n            { id: '2' },\n            { id: '3' },\n            { id: '4' },\n            { id: '5' },\n            { id: '6' },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['4', '6'],\n    });\n\n    const result = toggleLayer({ elementId: '2', shiftKey: true });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      selection: ['4', '3', '2'],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateAnimationState.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateAnimationState', () => {\n  it('should update animation state', () => {\n    const { restore, updateAnimationState } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }, { id: '456' }, { id: '789' }] },\n      ],\n      current: '111',\n      selection: ['123', '456'],\n      animationState: StoryAnimationState.Reset,\n    });\n\n    const result = updateAnimationState({\n      animationState: StoryAnimationState.Playing,\n    });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      animationState: StoryAnimationState.Playing,\n    });\n  });\n\n  it('should do nothing if state is the same', () => {\n    const { restore, updateAnimationState } = setupReducer();\n\n    // Set an initial state with a current page and some elements, none selected.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }, { id: '456' }, { id: '789' }] },\n      ],\n      current: '111',\n      selection: [],\n      animationState: StoryAnimationState.Reset,\n    });\n\n    const result = updateAnimationState({\n      animationState: StoryAnimationState.Reset,\n    });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      animationState: StoryAnimationState.Reset,\n    });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateCurrentPageProperties.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateCurrentPageProperties', () => {\n  it('should update properties of the current page', () => {\n    const { restore, updateCurrentPageProperties } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({ pages: [{ id: '111' }, { id: '222' }], current: '222' });\n\n    // Add x=1 to page 222\n    const result = updateCurrentPageProperties({ properties: { x: 1 } });\n\n    expect(result.pages).toStrictEqual([{ id: '111' }, { id: '222', x: 1 }]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateElementById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateElementById', () => {\n  it('should update the given element', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with a current page with an element.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementById({\n      elementId: '123',\n      properties: { a: 1 },\n    });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123', a: 1 }, { id: '456' }] },\n    ]);\n  });\n\n  it('should update the given element via an update function', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with a current page with an element.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementById({\n      elementId: '123',\n      properties: () => ({ a: 1 }),\n    });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123', a: 1 }, { id: '456' }] },\n    ]);\n  });\n\n  it('should skip reserved properties when updating by function', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with a current page with an element.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementById({\n      elementId: '123',\n      properties: () => ({ a: 1, id: '321' }),\n    });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123', a: 1 }, { id: '456' }] },\n    ]);\n  });\n\n  it('should do nothing if update by function only attempts reserved attributes', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with a current page with an element.\n    const initial = restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementById({\n      elementId: '123',\n      properties: () => ({ id: '321' }),\n    });\n\n    // TODO: Use .toBe() and ensure that the test still passes.\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should not allow updating reserved properties', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with a current page with an element.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', isBackground: true, isDefaultBackground: true, x: 1 },\n            { id: '456' },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    // only x=2 is allowed to be changed here\n    const result = updateElementById({\n      elementId: '123',\n      properties: {\n        x: 2,\n        id: '000',\n        isBackground: false,\n        isDefaultBackground: false,\n      },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          { id: '123', isBackground: true, isDefaultBackground: true, x: 2 },\n          { id: '456' },\n        ],\n      },\n    ]);\n  });\n\n  it('should ignore an unknown element (on the current page)', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with multiple pages with elements.\n    restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }] },\n        { id: '222', elements: [{ id: '456' }] },\n      ],\n      current: '111',\n    });\n\n    // 456 does not exist on current page, so nothing happens\n    const result = updateElementById({\n      elementId: '456',\n      properties: { a: 1 },\n    });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123' }] },\n      { id: '222', elements: [{ id: '456' }] },\n    ]);\n  });\n\n  it('should update animations correctly', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with one page with elements and animations\n    restore({\n      pages: [\n        {\n          id: 'p1',\n          animations: [\n            { id: 'a1', targets: ['e3'] },\n            { id: 'a2', targets: ['e3'] },\n            { id: 'a3', targets: ['e2'] },\n          ],\n          elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }],\n        },\n      ],\n      current: 'p1',\n    });\n\n    // update animation a2:\n    const result = updateElementById({\n      elementId: 'e3',\n      properties: {\n        animation: { id: 'a2', newProp: 'x' },\n      },\n    });\n\n    expect(result.pages[0].animations).toStrictEqual([\n      { id: 'a1', targets: ['e3'] },\n      { id: 'a2', targets: ['e3'], newProp: 'x' },\n      { id: 'a3', targets: ['e2'] },\n    ]);\n  });\n\n  it('should add animations correctly', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with one page with elements and no animations\n    restore({\n      pages: [\n        {\n          id: 'p1',\n          elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }],\n        },\n      ],\n      current: 'p1',\n    });\n\n    // add animation a4:\n    const result = updateElementById({\n      elementId: 'e3',\n      properties: {\n        animation: { id: 'a4' },\n      },\n    });\n\n    expect(result.pages[0].animations).toStrictEqual([\n      { id: 'a4', targets: ['e3'] },\n    ]);\n  });\n\n  it('should delete animations correctly', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with one page with elements and animations\n    restore({\n      pages: [\n        {\n          id: 'p1',\n          animations: [\n            { id: 'a1', targets: ['e3'] },\n            { id: 'a2', targets: ['e3'] },\n            { id: 'a3', targets: ['e2'] },\n          ],\n          elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3' }],\n        },\n      ],\n      current: 'p1',\n    });\n\n    // delete animation a1:\n    const result = updateElementById({\n      elementId: 'e3',\n      properties: {\n        animation: { id: 'a1', delete: true },\n      },\n    });\n\n    expect(result.pages[0].animations).toStrictEqual([\n      { id: 'a2', targets: ['e3'] },\n      { id: 'a3', targets: ['e2'] },\n    ]);\n  });\n\n  it('if updating both animation and regular element property, only animation gets updated', () => {\n    const { restore, updateElementById } = setupReducer();\n\n    // Set an initial state with one page with elements and animations\n    restore({\n      pages: [\n        {\n          id: 'p1',\n          animations: [\n            { id: 'a1', targets: ['e3'] },\n            { id: 'a2', targets: ['e3'] },\n            { id: 'a3', targets: ['e2'] },\n          ],\n          elements: [{ id: 'e1' }, { id: 'e2' }, { id: 'e3', a: 11 }],\n        },\n      ],\n      current: 'p1',\n    });\n\n    // update animation a2 and change property 'a'\n    const result = updateElementById({\n      elementId: 'e3',\n      properties: {\n        a: 22,\n        animation: { id: 'a2', newProp: 'x' },\n      },\n    });\n\n    expect(result.pages[0].animations).toStrictEqual([\n      { id: 'a1', targets: ['e3'] },\n      { id: 'a2', targets: ['e3'], newProp: 'x' },\n      { id: 'a3', targets: ['e2'] },\n    ]);\n    // Note that property 'a' was not changed\n    expect(result.pages[0].elements).toStrictEqual([\n      { id: 'e1' },\n      { id: 'e2' },\n      { id: 'e3', a: 11 },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateElementsByFontFamily.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateElementsByFontFamily', () => {\n  it('should update all the elements with given font family through all pages', () => {\n    const { restore, updateElementsByFontFamily } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '123',\n              type: 'text',\n              font: {\n                name: 'font 1',\n                value: 'font 1',\n                family: 'font 1',\n                service: 'custom',\n              },\n            },\n            {\n              id: '456',\n              type: 'text',\n              font: {\n                name: 'font 2',\n                value: 'font 2',\n                family: 'font 2',\n                service: 'custom',\n              },\n            },\n            { id: '789', resource: { type: 'image', id: '3' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            {\n              id: '987',\n              type: 'text',\n              font: {\n                name: 'font 1',\n                value: 'font 1',\n                family: 'font 1',\n                service: 'custom',\n              },\n            },\n          ],\n        },\n      ],\n    });\n\n    const result = updateElementsByFontFamily({\n      family: 'font 1',\n      properties: {\n        font: {\n          name: 'replaced font',\n          value: 'replaced font',\n          family: 'replaced font',\n          service: 'custom',\n        },\n      },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'text',\n            font: {\n              name: 'replaced font',\n              value: 'replaced font',\n              family: 'replaced font',\n              service: 'custom',\n            },\n          },\n          {\n            id: '456',\n            type: 'text',\n            font: {\n              name: 'font 2',\n              value: 'font 2',\n              family: 'font 2',\n              service: 'custom',\n            },\n          },\n          { id: '789', resource: { type: 'image', id: '3' } },\n        ],\n      },\n      {\n        id: '222',\n        elements: [\n          {\n            id: '987',\n            type: 'text',\n            font: {\n              name: 'replaced font',\n              value: 'replaced font',\n              family: 'replaced font',\n              service: 'custom',\n            },\n          },\n        ],\n      },\n    ]);\n  });\n\n  it('should do nothing if family not given', () => {\n    const { restore, updateElementsByFontFamily } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '123',\n              type: 'text',\n              font: {\n                name: 'font 1',\n                value: 'font 1',\n                family: 'font 1',\n                service: 'custom',\n              },\n            },\n          ],\n        },\n      ],\n    });\n\n    const result = updateElementsByFontFamily({\n      family: undefined,\n      properties: {\n        font: {\n          name: 'replaced font',\n          value: 'replaced font',\n          family: 'replaced font',\n          service: 'custom',\n        },\n      },\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no elements with given family', () => {\n    const { restore, updateElementsByFontFamily } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '123',\n              type: 'text',\n              font: {\n                name: 'font 1',\n                value: 'font 1',\n                family: 'font 1',\n                service: 'custom',\n              },\n            },\n          ],\n        },\n      ],\n    });\n\n    const result = updateElementsByFontFamily({\n      family: 'font 2',\n      properties: {\n        font: {\n          name: 'replaced font',\n          value: 'replaced font',\n          family: 'replaced font',\n          service: 'custom',\n        },\n      },\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  //\n  it('should update all font properties with given font family', () => {\n    const { restore, updateElementsByFontFamily } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            {\n              id: '123',\n              type: 'text',\n              font: {\n                name: 'font 1',\n                value: 'font 1',\n                family: 'font 1',\n                service: 'custom',\n                weights: [100, 300, 400, 500, 700, 900, 1000],\n                fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n                metrics: {\n                  upm: 2048,\n                  asc: 1900,\n                  des: -500,\n                  tAsc: 1536,\n                  tDes: -512,\n                  tLGap: 102,\n                  wAsc: 1946,\n                  wDes: 512,\n                  xH: 1082,\n                  capH: 1456,\n                  yMin: -555,\n                  yMax: 2163,\n                  hAsc: 1900,\n                  hDes: -500,\n                  lGap: 0,\n                },\n              },\n            },\n          ],\n        },\n      ],\n    });\n\n    const result = updateElementsByFontFamily({\n      family: 'font 1',\n      properties: {\n        font: {\n          name: 'replaced font',\n          value: 'replaced font',\n          family: 'replaced font',\n          service: 'custom',\n          fallbacks: ['Helvetica', 'sans-serif'], // <- remove Helvetica Neue + change obj position\n          weights: [100, 300, 400, 500, 700, 900], // <- remove weight 1000\n          metrics: {\n            upm: 2048,\n            asc: 1920, // <- update metric\n            des: -500,\n            tAsc: 1536,\n            tDes: -512,\n            tLGap: 102,\n            wAsc: 1946,\n            wDes: 512,\n            xH: 1082,\n            capH: 1456,\n            yMin: -555,\n            yMax: 2163,\n            hAsc: 1900,\n            hDes: -500,\n            lGap: 0,\n          },\n        },\n      },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            type: 'text',\n            font: {\n              name: 'replaced font',\n              value: 'replaced font',\n              family: 'replaced font',\n              service: 'custom',\n              fallbacks: ['Helvetica', 'sans-serif'],\n              weights: [100, 300, 400, 500, 700, 900],\n              metrics: {\n                upm: 2048,\n                asc: 1920,\n                des: -500,\n                tAsc: 1536,\n                tDes: -512,\n                tLGap: 102,\n                wAsc: 1946,\n                wDes: 512,\n                xH: 1082,\n                capH: 1456,\n                yMin: -555,\n                yMax: 2163,\n                hAsc: 1900,\n                hDes: -500,\n                lGap: 0,\n              },\n            },\n          },\n        ],\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateElementsById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateElementsById', () => {\n  it('should update the given elements', () => {\n    const { restore, updateElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementsById({\n      elementIds: ['123', '456'],\n      properties: { a: 1 },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          { id: '123', a: 1 },\n          { id: '456', a: 1 },\n        ],\n      },\n    ]);\n  });\n\n  it('should skip unknown elements', () => {\n    const { restore, updateElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementsById({\n      elementIds: ['123', '789'],\n      properties: { a: 1 },\n    });\n\n    expect(result.pages).toStrictEqual([\n      { id: '111', elements: [{ id: '123', a: 1 }, { id: '456' }] },\n    ]);\n  });\n\n  it('should update the given elements with a function', () => {\n    const { restore, updateElementsById } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', a: 1 },\n            { id: '456', a: 2 },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateElementsById({\n      elementIds: ['123', '456'],\n      properties: ({ a, ...rest }) => ({ a: a + 1, ...rest }),\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          { id: '123', a: 2 },\n          { id: '456', a: 3 },\n        ],\n      },\n    ]);\n  });\n\n  it('should do nothing if no elements given', () => {\n    const { restore, updateElementsById } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementsById({ elementIds: [], properties: { a: 1 } });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if only unknown elements given', () => {\n    const { restore, updateElementsById } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [{ id: '111', elements: [{ id: '123' }, { id: '456' }] }],\n      current: '111',\n    });\n\n    const result = updateElementsById({\n      elementIds: ['789'],\n      properties: { a: 1 },\n    });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateElementsByResourceId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateElementsByResourceId', () => {\n  it('should update all the elements with given id of element resource through all pages with a function', () => {\n    const { restore, updateElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'video', id: '10' } },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '11' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateElementsByResourceId({\n      id: '10',\n      properties: ({ resource, ...rest }) => ({\n        ...rest,\n        resource: { ...resource, posterId: '1', poster: '2' },\n      }),\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            resource: {\n              type: 'video',\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          {\n            id: '456',\n            resource: {\n              type: 'video',\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          { id: '789', resource: { type: 'image', id: '11' } },\n        ],\n      },\n      {\n        id: '222',\n        elements: [\n          {\n            id: '123',\n            resource: {\n              type: 'video',\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          {\n            id: '456',\n            resource: {\n              type: 'image',\n              id: '11',\n            },\n          },\n        ],\n      },\n    ]);\n  });\n\n  it('should update all the elements with given id of element resource through all pages', () => {\n    const { restore, updateElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'video', id: '10' } },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '11' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateElementsByResourceId({\n      id: '10',\n      properties: {\n        resource: { id: '10', posterId: '1', poster: '2' },\n      },\n    });\n\n    expect(result.pages).toStrictEqual([\n      {\n        id: '111',\n        elements: [\n          {\n            id: '123',\n            resource: {\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          {\n            id: '456',\n            resource: {\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          { id: '789', resource: { type: 'image', id: '11' } },\n        ],\n      },\n      {\n        id: '222',\n        elements: [\n          {\n            id: '123',\n            resource: {\n              id: '10',\n              posterId: '1',\n              poster: '2',\n            },\n          },\n          {\n            id: '456',\n            resource: {\n              id: '11',\n              type: 'image',\n            },\n          },\n        ],\n      },\n    ]);\n  });\n\n  it('should do nothing if id not given', () => {\n    const { restore, updateElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateElementsByResourceId({\n      id: undefined,\n      properties: ({ resource, ...rest }) => ({\n        ...rest,\n        resource: { ...resource, posterId: '1', poster: '2' },\n      }),\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if no elements with given id', () => {\n    const { restore, updateElementsByResourceId } = setupReducer();\n\n    // Set an initial state.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', resource: { type: 'video' } },\n            { id: '456' },\n            { id: '789', resource: { type: 'image', id: '11' } },\n          ],\n        },\n        {\n          id: '222',\n          elements: [\n            { id: '123', resource: { type: 'video', id: '10' } },\n            { id: '456', resource: { type: 'image', id: '10' } },\n          ],\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateElementsByResourceId({\n      id: '12',\n      properties: ({ resource, ...rest }) => ({\n        ...rest,\n        resource: { ...resource, posterId: '1', poster: '2' },\n      }),\n    });\n\n    expect(result).toBe(initialState);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateGroupById.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateGroupById', () => {\n  it('should do nothing if nothing supplied', () => {\n    const { restore, updateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateGroupById({});\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should not add group if it does not exist', () => {\n    const { restore, updateGroupById } = setupReducer();\n\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {},\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateGroupById({ groupId: 'g1', properties: { a: 1 } });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should update and overwrite properties in specified group', () => {\n    const { restore, updateGroupById } = setupReducer();\n\n    restore({\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', isBackground: true }, { id: '234' }],\n          groups: {\n            g1: { a: 1, b: 2 },\n            g2: { c: 3, d: 4 },\n          },\n        },\n      ],\n      current: '111',\n    });\n\n    const result = updateGroupById({\n      groupId: 'g1',\n      properties: { a: 3, c: 4 },\n    });\n\n    expect(result.pages[0].groups).toStrictEqual({\n      g1: { b: 2, a: 3, c: 4 },\n      g2: { c: 3, d: 4 },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updatePageProperties.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updatePageProperties', () => {\n  it('should do nothing if page not found', () => {\n    const { restore, updatePageProperties } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    const initialState = restore({ pages: [{ id: '111' }, { id: '222' }] });\n\n    // There's no page 333\n    const result = updatePageProperties({\n      pageId: '333',\n      properties: { x: 1 },\n    });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should update properties of the given page', () => {\n    const { restore, updatePageProperties } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({ pages: [{ id: '111' }, { id: '222' }] });\n\n    // Add x=1 to page 111\n    const result = updatePageProperties({\n      pageId: '111',\n      properties: { x: 1 },\n    });\n\n    expect(result.pages).toStrictEqual([{ id: '111', x: 1 }, { id: '222' }]);\n  });\n\n  it('should disallow updating reserve properties', () => {\n    const { restore, updatePageProperties } = setupReducer();\n\n    // Set an initial state with multiple pages.\n    restore({ pages: [{ id: '111' }, { id: '222' }] });\n\n    // Try modifying illegal props besides x=2\n    const result = updatePageProperties({\n      pageId: '111',\n      properties: {\n        x: 2,\n        id: '333',\n        elements: ['many'],\n      },\n    });\n\n    expect(result.pages).toStrictEqual([{ id: '111', x: 2 }, { id: '222' }]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateSelectedElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateSelectedElements', () => {\n  it('should update the selected elements', () => {\n    const { restore, updateSelectedElements } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }, { id: '456' }, { id: '789' }] },\n      ],\n      current: '111',\n      selection: ['123', '456'],\n    });\n\n    const result = updateSelectedElements({ properties: { a: 1 } });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [\n        {\n          id: '111',\n          elements: [{ id: '123', a: 1 }, { id: '456', a: 1 }, { id: '789' }],\n        },\n      ],\n      selection: ['123', '456'],\n    });\n  });\n\n  it('should do nothing if no elements selected', () => {\n    const { restore, updateSelectedElements } = setupReducer();\n\n    // Set an initial state with a current page and some elements, none selected.\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }, { id: '456' }, { id: '789' }] },\n      ],\n      current: '111',\n      selection: [],\n    });\n\n    const result = updateSelectedElements({ properties: { a: 1 } });\n\n    expect(result).toBe(initialState);\n  });\n\n  it('should do nothing if elements selected and animation playing or scrubbing', () => {\n    const { restore, updateSelectedElements, updateAnimationState } =\n      setupReducer();\n\n    const initialState = restore({\n      pages: [\n        { id: '111', elements: [{ id: '123' }, { id: '456' }, { id: '789' }] },\n      ],\n      current: '111',\n      selection: ['123', '456'],\n    });\n\n    updateAnimationState({ animationState: StoryAnimationState.Playing });\n    const playingResult = updateSelectedElements({ properties: { a: 1 } });\n\n    updateAnimationState({ animationState: StoryAnimationState.Scrubbing });\n    const scrubbingResult = updateSelectedElements({ properties: { a: 1 } });\n\n    expect(playingResult).toStrictEqual({\n      ...initialState,\n      animationState: StoryAnimationState.Playing,\n    });\n    expect(scrubbingResult).toStrictEqual({\n      ...initialState,\n      animationState: StoryAnimationState.Scrubbing,\n    });\n  });\n\n  it('should update the selected elements with a function', () => {\n    const { restore, updateSelectedElements } = setupReducer();\n\n    // Set an initial state with a current page and some elements selected.\n    const initialState = restore({\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', a: 1 },\n            { id: '456', a: 2 },\n            { id: '789', a: 0 },\n          ],\n        },\n      ],\n      current: '111',\n      selection: ['123', '456'],\n    });\n\n    const result = updateSelectedElements({\n      properties: ({ a, ...rest }) => ({ a: a + 1, ...rest }),\n    });\n\n    expect(result).toStrictEqual({\n      ...initialState,\n      pages: [\n        {\n          id: '111',\n          elements: [\n            { id: '123', a: 2 },\n            { id: '456', a: 3 },\n            { id: '789', a: 0 },\n          ],\n        },\n      ],\n      selection: ['123', '456'],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/test/updateStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { setupReducer } from './_utils';\n\ndescribe('updateStory', () => {\n  it('should update story with given properties', () => {\n    const { updateStory } = setupReducer();\n\n    const result = updateStory({ properties: { a: 1, b: 2 } });\n\n    expect(result.story).toStrictEqual({ a: 1, b: 2, fonts: {} });\n  });\n\n  it('should update story with property updater function which will overwrite existing values', () => {\n    const { updateStory } = setupReducer();\n\n    const firstResult = updateStory({ properties: { a: 1, b: 2 } });\n    expect(firstResult.story).toStrictEqual({ a: 1, b: 2, fonts: {} });\n\n    const secondResult = updateStory({\n      properties: (old) => ({ b: old.b + 2 }),\n    });\n    // Note how 'a' has been deleted, because only 'b' was returned in the updater\n    expect(secondResult.story).toStrictEqual({ b: 4 });\n  });\n\n  it('should overwrite existing properties but not delete old ones', () => {\n    const { updateStory } = setupReducer();\n\n    const firstResult = updateStory({ properties: { a: 1, b: 2 } });\n    expect(firstResult.story).toStrictEqual({ a: 1, b: 2, fonts: {} });\n\n    const secondResult = updateStory({ properties: { b: 3, c: 4 } });\n    expect(secondResult.story).toStrictEqual({ a: 1, b: 3, c: 4, fonts: {} });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/types.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum ActionTypes {\n  // Manipulate pages.\n  AddPage = 'ADD_PAGE',\n  UpdatePage = 'UPDATE_PAGE',\n  DeletePage = 'DELETE_PAGE',\n  ArrangePage = 'ARRANGE_PAGE',\n\n  // Manipulate elements on a page.\n  DeleteElements = 'DELETE_ELEMENTS',\n  AddElements = 'ADD_ELEMENTS',\n  UpdateElements = 'UPDATE_ELEMENTS',\n  UpdateElementsByResourceId = 'UPDATE_ELEMENTS_BY_RESOURCE_ID',\n  DeleteElementsByResourceId = 'DELETE_ELEMENTS_BY_RESOURCE_ID',\n  SetBackgroundElement = 'SET_BACKGROUND_ELEMENT',\n  ArrangeElement = 'ARRANGE_ELEMENT',\n  ArrangeGroup = 'ARRANGE_GROUP',\n  CombineElements = 'COMBINE_ELEMENTS',\n  DuplicateElementsById = 'DUPLICATE_ELEMENTS_BY_ID',\n  CopySelectedElement = 'COPY_SELECTED_ELEMENT',\n  UpdateElementsByFontFamily = 'UPDATE_ELEMENTS_BY_FONT_FAMILY',\n\n  // Manipulate current page.\n  SetCurrentPage = 'SET_CURRENT_PAGE',\n\n  // Manipulate list of selected elements.\n  SetSelectedElements = 'SET_SELECTED_ELEMENTS',\n  SelectElement = 'SELECT_ELEMENT',\n  UnselectElement = 'UNSELECT_ELEMENT',\n  ToggleElementInSelection = 'TOGGLE_ELEMENT_IN_SELECTION',\n  ToggleLayer = 'TOGGLE_LAYER',\n\n  // Manipulate story-global state.\n  UpdateStory = 'UPDATE_STORY',\n\n  // Manipulate animation state.\n  UpdateAnimationState = 'UPDATE_ANIMATION_STATE',\n  AddAnimations = 'ADD_ANIMATIONS',\n\n  // Manipulate entire internal state.\n  Restore = 'RESTORE',\n\n  // Layer groups\n  AddGroup = 'ADD_GROUP',\n  UpdateGroup = 'UPDATE_GROUP',\n  DeleteGroup = 'DELETE_GROUP',\n  DuplicateGroup = 'DUPLICATE_GROUP',\n  RemoveElementFromGroup = 'REMOVE_ELEMENT_FROM_GROUP',\n\n  // Video segmentation.\n  AddElementsAcrossPages = 'ADD_ELEMENTS_ACROSS_PAGES',\n}\n\n// Reserved property names for pages, elements and groups.\nexport const PAGE_RESERVED_PROPERTIES = ['id', 'elements', 'groups'];\nexport const ELEMENT_RESERVED_PROPERTIES = [\n  'id',\n  'isBackground',\n  'isDefaultBackground',\n];\n"
  },
  {
    "path": "packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReducer, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type {\n  ExternalActions,\n  InternalActions,\n  ReducerState,\n  ReducerProviderState,\n} from '../../../types';\nimport { INITIAL_STATE } from '../constants';\nimport { type DispatchType, exposedActions, internalActions } from './actions';\nimport reducer from './reducer';\n\n/**\n * More description to follow - especially about return value.\n *\n * Invariants kept by the system:\n * - Pages is always an array.\n * - All pages have a elements array.\n * - If there's at least one page, current page points to a valid page.\n * - Selection is always a unique array (and never null, never has duplicates).\n * - Pages always have a background element which is the bottom-most element\n * - Pages are created with a default background element, which will be remembered even as other elements become background\n * - If a page is ever set to not have a background element, the default one will be inserted instead\n * - A page can only have non-duplicated element ids, however two different pages can have the same element id.\n * - If selection has multiple elements, it can never include the bottom-most (background) element.\n *\n * Invariants *not* kept by the system:\n * - New pages and objects aren't checked for id's and id's aren't validated for type.\n * - Selection isn't guaranteed to refer to objects on the current page.\n * - New pages aren't validated for type of elements property when added.\n * - No validation of keys or values in the story object.\n */\ntype Actions = InternalActions | ExternalActions;\nfunction useStoryReducer(partial: Partial<ReducerState>): ReducerProviderState {\n  const [state, dispatch] = useReducer(reducer, {\n    ...INITIAL_STATE,\n    ...partial,\n  } as ReducerState);\n  const { internal, api } = useMemo(() => {\n    const wrapWithDispatch = <\n      T extends Record<string, (props: DispatchType) => unknown>,\n    >(\n      actions: T\n    ) =>\n      Object.keys(actions).reduce(\n        (collection: Actions, action) => ({\n          ...collection,\n          [action]: actions[action as keyof typeof actions](dispatch),\n        }),\n        {} as Actions\n      );\n\n    return {\n      internal: wrapWithDispatch<typeof internalActions>(\n        internalActions\n      ) as InternalActions,\n      api: wrapWithDispatch(exposedActions) as ExternalActions,\n    };\n  }, [dispatch]);\n\n  return {\n    state,\n    internal,\n    api,\n  };\n}\n\nexport default useStoryReducer;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/cleanElementFontProperties.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\nimport { elementIs } from '@googleforcreators/elements';\n\nfunction reduceElementFontProperties({ elements, ...rest }: Page): Page {\n  return {\n    elements: elements.map((element) => {\n      if (elementIs.text(element) && Boolean(element.font?.family)) {\n        return { ...element, font: { family: element.font.family } };\n      }\n      return element;\n    }),\n    ...rest,\n  };\n}\n\nexport function cleanElementFontProperties(data: Page[]) {\n  return data.map((page) => reduceElementFontProperties(page));\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/deleteNestedKeys.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Dynamically deletes nested keys from an object by the defined paths.\n * Each path has to be in the format of nested keys separated by a dot, e.g. `foo.bar.a`\n *\n * Note that this function mutates the original object.\n */\nfunction deleteNestedKeys<T extends Record<string, unknown>>(paths: string[]) {\n  return (object: T) => {\n    paths.forEach((path) => {\n      const keys = path.split('.');\n      if (!keys.length) {\n        return;\n      }\n      if (keys.length === 1) {\n        delete object[keys[0]];\n        return;\n      }\n      const lastKey = keys.pop();\n      const nextLastKey = keys.pop();\n      const nextLastObj = keys.reduce<Partial<T>>(\n        (a, key) => a?.[key] || a,\n        object\n      );\n\n      if (!nextLastObj || !nextLastKey || !lastKey) {\n        return;\n      }\n      // Make sure we're not trying to get a property out of `undefined` or `null`.\n      if (\n        Object.prototype.hasOwnProperty.call(nextLastObj, nextLastKey) &&\n        'object' === typeof nextLastObj[nextLastKey] &&\n        nextLastObj[nextLastKey]\n      ) {\n        delete (nextLastObj[nextLastKey] as Record<string, unknown>)[lastKey];\n      }\n    });\n  };\n}\n\nexport default deleteNestedKeys;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/getAllProducts.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  type Element,\n  ElementType,\n  type Page,\n  type ProductData,\n  type ProductElement,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\n\nfunction isProduct(e: Element): e is ProductElement {\n  return 'product' in e;\n}\nfunction getAllProducts(pages: Page[]): ProductData[] {\n  const products: ProductData[] = [];\n  const productIds: string[] = [];\n  pages.forEach(({ elements }) =>\n    elements.forEach((element) => {\n      if (!isProduct(element)) {\n        return;\n      }\n      const { product, type } = element;\n      if (\n        type === ElementType.Product &&\n        product &&\n        !productIds.includes(product.productId)\n      ) {\n        products.push(product);\n        productIds.push(product.productId);\n      }\n    })\n  );\n\n  return products;\n}\n\nexport default getAllProducts;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/getStoryFontsFromPages.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { FontData, Page } from '@googleforcreators/elements';\nimport { elementIs } from '@googleforcreators/elements';\n\nexport function getStoryFontsFromPages(pages: Page[]) {\n  const fonts: Record<string, FontData> = {};\n  pages.forEach(({ elements = [] }) =>\n    elements.forEach((element) => {\n      if (elementIs.text(element) && Boolean(element.font?.family)) {\n        fonts[element.font.family] = element.font;\n      }\n    })\n  );\n  return fonts;\n}\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { getStoryMarkup } from '@googleforcreators/output';\nimport type { Page, Story, TaxonomySlug } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport objectPick from '../../../utils/objectPick';\nimport type { StorySaveData, MetaData, Flags } from '../../../types';\nimport getAllProducts from './getAllProducts';\nimport { cleanElementFontProperties } from './cleanElementFontProperties';\nimport { getStoryFontsFromPages } from './getStoryFontsFromPages';\n\ninterface StoryPropsToSave {\n  story: Story;\n  pages: Page[];\n  metadata: MetaData;\n  flags: Flags;\n}\nfunction getStoryPropsToSave({\n  story,\n  pages,\n  metadata,\n  flags,\n}: StoryPropsToSave): StorySaveData {\n  const { terms, fonts, ...propsFromStory } = objectPick(story, [\n    'title',\n    'fonts',\n    'status',\n    'author',\n    'date',\n    'modified',\n    'slug',\n    'excerpt',\n    'featuredMedia',\n    'publisherLogo',\n    'password',\n    'currentStoryStyles',\n    'globalStoryStyles',\n    'autoAdvance',\n    'defaultPageDuration',\n    'backgroundAudio',\n    'terms',\n  ]);\n\n  // clean up fonts to store at the story level\n  // this avoids storing the same font (properties) multiple times\n  // see: https://github.com/GoogleForCreators/web-stories-wp/issues/12261\n  const cleanedFonts = getStoryFontsFromPages(pages);\n  // clean up text elements to remove font properties from individual elements\n  const cleanedPages = cleanElementFontProperties(pages);\n\n  const products = getAllProducts(cleanedPages);\n  const content = getStoryMarkup(\n    { ...story, fonts: cleanedFonts },\n    cleanedPages,\n    metadata,\n    flags\n  );\n\n  const termData: Record<TaxonomySlug, number[]> = {};\n  if (terms) {\n    terms.forEach(({ taxonomy, id }) => {\n      const termIds = Array.isArray(termData[taxonomy])\n        ? termData[taxonomy]\n        : [];\n      termIds.push(id);\n      termData[taxonomy] = termIds;\n    });\n  }\n  return {\n    content,\n    pages: cleanedPages,\n    ...propsFromStory,\n    fonts: cleanedFonts,\n    ...termData,\n    products,\n  } as StorySaveData;\n}\n\nexport default getStoryPropsToSave;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/isEmptyStory.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { shallowEqual } from '@googleforcreators/react';\nimport {\n  DEFAULT_PAGE_BACKGROUND_COLOR,\n  type DefaultBackgroundElement,\n  type Page,\n} from '@googleforcreators/elements';\n\nconst isEmptyStory = (pages: Page[]) => {\n  const hasOnlyOnePage = pages.length === 1;\n  if (!hasOnlyOnePage) {\n    return false;\n  }\n\n  const hasNoExtraElements = pages[0].elements?.length === 1;\n  if (!hasNoExtraElements) {\n    return false;\n  }\n\n  const hasNoBackgroundMedia = (\n    pages[0].elements[0] as DefaultBackgroundElement\n  ).isDefaultBackground;\n  if (!hasNoBackgroundMedia) {\n    return false;\n  }\n\n  const hasPageAttachment = pages[0].pageAttachment?.url;\n  if (hasPageAttachment) {\n    return false;\n  }\n\n  const hasDefaultBackgroundColor =\n    'color' in pages[0].backgroundColor &&\n    shallowEqual(\n      DEFAULT_PAGE_BACKGROUND_COLOR.color,\n      pages[0].backgroundColor.color\n    );\n  if (!hasDefaultBackgroundColor) {\n    return false;\n  }\n\n  return true;\n};\n\nexport default isEmptyStory;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { isBlobURL } from '@googleforcreators/media';\nimport type { Page } from '@googleforcreators/elements';\nimport { elementIs } from '@googleforcreators/elements';\n\nfunction pageContainsBlobUrl(pages: Page[]) {\n  // skip entries that have a blob url\n  // https://github.com/GoogleForCreators/web-stories-wp/issues/10289\n  return pages.some((page) =>\n    page.elements.some((element) => {\n      if (!elementIs.media(element) || !element.resource) {\n        return false;\n      }\n      if (isBlobURL(element.resource.src)) {\n        return true;\n      }\n      return (\n        elementIs.sequenceMedia(element) && isBlobURL(element.resource.poster)\n      );\n    })\n  );\n}\n\nexport default pageContainsBlobUrl;\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/cleanElementFontPropties.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { cleanElementFontProperties } from '../cleanElementFontProperties';\n\ndescribe('cleanElementFontProperties', () => {\n  it('cleans font properties from elements', () => {\n    const fonts = {\n      Oswald: {\n        family: 'Oswald',\n        service: 'fonts.google.com',\n        metrics: { upm: 1000, asc: 1050, des: -350 },\n      },\n      Roboto: {\n        family: 'Roboto',\n        service: 'fonts.google.com',\n        metrics: { upm: 1000, asc: 1048, des: -271 },\n      },\n    };\n\n    const pages = [\n      {\n        elements: [{ type: 'shape' }, { type: 'text', font: fonts['Oswald'] }],\n      },\n      {\n        elements: [{ type: 'shape' }, { type: 'text', font: fonts['Roboto'] }],\n      },\n    ];\n\n    const newPages = cleanElementFontProperties(pages);\n    expect(newPages[0].elements[1]).toStrictEqual({\n      type: 'text',\n      font: { family: 'Oswald' },\n    });\n\n    expect(newPages[1].elements[1]).toStrictEqual({\n      type: 'text',\n      font: { family: 'Roboto' },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/deleteNestedKeys.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport deleteNestedKeys from '../deleteNestedKeys';\n\ndescribe('deleteNestedKeys', () => {\n  it('should correctly delete nested keys', () => {\n    const object = {\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n        },\n      },\n    };\n    deleteNestedKeys(['foo.bar.a'])(object);\n    expect(object).toStrictEqual({\n      foo: {\n        bar: {\n          b: 'World',\n        },\n      },\n    });\n  });\n\n  it('should correctly delete not nested keys', () => {\n    const object = {\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n        },\n      },\n    };\n    deleteNestedKeys(['foo'])(object);\n    expect(object).toStrictEqual({\n      bar: 'Hello World',\n    });\n  });\n\n  it('should not do anything in case of non-existent key', () => {\n    const object = {\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n        },\n      },\n    };\n    deleteNestedKeys(['foo.bar.c'])(object);\n    expect(object).toStrictEqual({\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n        },\n      },\n    });\n  });\n\n  it('should delete properties with `null` and `undefined` as values', () => {\n    const object = {\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          a: null,\n          b: undefined,\n          c: 'Hello',\n        },\n      },\n    };\n    deleteNestedKeys(['foo.bar.a', 'foo.bar.b'])(object);\n    expect(object).toStrictEqual({\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          c: 'Hello',\n        },\n      },\n    });\n  });\n\n  it('should not change anything in properties with `null` and `undefined` as parent values', () => {\n    const obj1 = {\n      bar: undefined,\n      foo: null,\n    };\n    deleteNestedKeys(['bar.a', 'foo.a'])(obj1);\n    expect(obj1).toStrictEqual({\n      bar: undefined,\n      foo: null,\n    });\n\n    const obj2 = {\n      bar: 'Hello World',\n      foo: {\n        bar: null,\n      },\n    };\n\n    deleteNestedKeys(['foo.bar.a', 'foo.bar.b'])(obj2);\n    expect(obj2).toStrictEqual({\n      bar: 'Hello World',\n      foo: {\n        bar: null,\n      },\n    });\n  });\n\n  it('should delete multiple properties', () => {\n    const object = {\n      bar: 'Hello World',\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n          c: '!',\n        },\n      },\n    };\n    deleteNestedKeys(['bar', 'foo.bar.c'])(object);\n    expect(object).toStrictEqual({\n      foo: {\n        bar: {\n          a: 'Hello',\n          b: 'World',\n        },\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/getAllProduct.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n/**\n * Internal dependencies\n */\nimport getAllProducts from '../getAllProducts';\n\ndescribe('getAllProducts', () => {\n  it('should return empty array', () => {\n    expect(getAllProducts([])).toStrictEqual([]);\n  });\n\n  it('should return empty array as type not product', () => {\n    expect(\n      getAllProducts([\n        {\n          elements: [\n            {\n              type: ELEMENT_TYPES.TEXT,\n              content: '<span style=\"font-style: italic\">Hello</span>',\n            },\n          ],\n        },\n      ])\n    ).toStrictEqual([]);\n  });\n\n  it('should return a product', () => {\n    expect(\n      getAllProducts([\n        {\n          elements: [\n            {\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'b' },\n            },\n            {\n              type: ELEMENT_TYPES.TEXT,\n              content: '<span style=\"font-style: italic\">Hello</span>',\n            },\n          ],\n        },\n      ])\n    ).toStrictEqual([{ productId: 'b' }]);\n  });\n\n  it('should return unique products', () => {\n    expect(\n      getAllProducts([\n        {\n          elements: [\n            {\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'a' },\n            },\n            {\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'b' },\n            },\n            {\n              type: ELEMENT_TYPES.TEXT,\n              content: '<span style=\"font-style: italic\">Hello</span>',\n            },\n          ],\n        },\n        {\n          elements: [\n            {\n              type: ELEMENT_TYPES.PRODUCT,\n              product: { productId: 'b' },\n            },\n          ],\n        },\n      ])\n    ).toStrictEqual([{ productId: 'a' }, { productId: 'b' }]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/getStoryFontsFromPages.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { getStoryFontsFromPages } from '../getStoryFontsFromPages';\n\ndescribe('getStoryFontsFromPages', () => {\n  it('clean font properties from elements', () => {\n    const elementfonts = {\n      Oswald: {\n        family: 'Oswald',\n        service: 'fonts.google.com',\n        metrics: { upm: 1000, asc: 1050, des: -350 },\n      },\n      Roboto: {\n        family: 'Roboto',\n        service: 'fonts.google.com',\n        metrics: { upm: 1000, asc: 1048, des: -271 },\n      },\n    };\n\n    const pages = [\n      {\n        elements: [\n          { type: 'shape' },\n          { type: 'text', font: elementfonts['Oswald'] },\n        ],\n      },\n      {\n        elements: [\n          { type: 'shape' },\n          { type: 'text', font: elementfonts['Roboto'] },\n        ],\n      },\n    ];\n\n    const fonts = getStoryFontsFromPages(pages);\n    expect(fonts).toStrictEqual(elementfonts);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/getStoryPropsToSave.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { getStoryMarkup } from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport getStoryPropsToSave from '../getStoryPropsToSave';\n\njest.mock('@googleforcreators/output', () => ({\n  getStoryMarkup: jest.fn(),\n}));\n\ndescribe('getStoryPropsToSave', () => {\n  it('should return correct story properties', () => {\n    const neededProps = {\n      title: 'Story!',\n      author: { id: 1, name: 'John Doe' },\n      slug: 'story',\n      publisherLogo: {\n        id: 1,\n        url: 'https://example.com/logo.png',\n        height: 0,\n        width: 0,\n      },\n      status: 'publish',\n      date: '2020-04-10T07:06:26',\n      modified: '',\n      excerpt: '',\n      featuredMedia: {\n        id: 0,\n        url: 'https://example.com/image.png',\n        isExternal: false,\n        height: 100,\n        width: 100,\n      },\n      fonts: {},\n      password: '',\n      globalStoryStyles: '',\n      autoAdvance: 'manual',\n      defaultPageDuration: 7,\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n      },\n      taxonomies: [],\n    };\n    const extraProps = {\n      storyId: 1,\n      foo: 'bar',\n    };\n    const story = {\n      ...neededProps,\n      ...extraProps,\n    };\n    const pages = [\n      { id: '1', elements: [] },\n      { id: '2', elements: [] },\n    ];\n    const metadata = {};\n    getStoryMarkup.mockImplementation(() => {\n      return 'Hello World!';\n    });\n    const props = getStoryPropsToSave({ story, pages, metadata });\n\n    const expected = {\n      content: 'Hello World!',\n      pages,\n      ...neededProps,\n      products: [],\n    };\n    delete expected.taxonomies;\n\n    expect(props).toStrictEqual(expected);\n  });\n\n  it('should return correct story properties with external poster', () => {\n    const neededProps = {\n      title: 'Story!',\n      author: { id: 1, name: 'John Doe' },\n      slug: 'story',\n      publisherLogo: {\n        id: 1,\n        url: 'https://example.com/logo.png',\n        height: 0,\n        width: 0,\n      },\n      status: 'publish',\n      date: '2020-04-10T07:06:26',\n      modified: '',\n      excerpt: '',\n      featuredMedia: {\n        id: 0,\n        url: 'https://example.com/image.png',\n        isExternal: true,\n        needsProxy: false,\n        height: 100,\n        width: 100,\n      },\n      fonts: {},\n      password: '',\n      globalStoryStyles: '',\n      autoAdvance: 'manual',\n      defaultPageDuration: 7,\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n      },\n      taxonomies: [],\n    };\n    const extraProps = {\n      storyId: 1,\n      foo: 'bar',\n    };\n    const story = {\n      ...neededProps,\n      ...extraProps,\n    };\n    const pages = [\n      { id: '1', elements: [] },\n      { id: '2', elements: [] },\n    ];\n    const metadata = {};\n    getStoryMarkup.mockImplementation(() => {\n      return 'Hello World!';\n    });\n    const props = getStoryPropsToSave({ story, pages, metadata });\n\n    const expected = {\n      content: 'Hello World!',\n      pages,\n      ...neededProps,\n      products: [],\n    };\n\n    delete expected.taxonomies;\n\n    expect(props).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/isEmptyStory.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { createPage, registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport isEmptyStory from '../isEmptyStory';\n\ndescribe('isEmptyStory', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should count newly created story as empty', () => {\n    const newlyCreatedStoryPages = [createPage()];\n    expect(isEmptyStory(newlyCreatedStoryPages)).toBeTrue();\n  });\n\n  it('should not count story with changed background color as empty', () => {\n    const storyWithChangedBackgroundColor = [createPage()];\n    storyWithChangedBackgroundColor[0].backgroundColor =\n      createSolidFromString('#ff0000');\n    expect(isEmptyStory(storyWithChangedBackgroundColor)).toBeFalse();\n  });\n\n  it('should not count story with changed background media as empty', () => {\n    const storyWithBackgroundMedia = [createPage()];\n    storyWithBackgroundMedia[0].elements[0].isDefaultBackground = false;\n    expect(isEmptyStory(storyWithBackgroundMedia)).toBeFalse();\n  });\n\n  it('should not count story with 2 pages as empty', () => {\n    const storyWith2Pages = [createPage(), createPage()];\n    expect(isEmptyStory(storyWith2Pages)).toBeFalse();\n  });\n\n  it('should not count story with extra elements as empty', () => {\n    const storyWithExtraElements = [createPage()];\n    storyWithExtraElements[0].elements.push({});\n    expect(isEmptyStory(storyWithExtraElements)).toBeFalse();\n  });\n\n  it('should not count story with an attachment as empty', () => {\n    const storyWithAttachment = [createPage()];\n    const testUrl = 'https://testurl.com';\n    const pageAttachmentObject = { url: testUrl };\n\n    storyWithAttachment[0].pageAttachment = pageAttachmentObject;\n    expect(isEmptyStory(storyWithAttachment)).toBeFalse();\n  });\n\n  it('should count story without the pageAttachment property as empty', () => {\n    const storyWithoutAttachment = [createPage()];\n\n    expect(isEmptyStory(storyWithoutAttachment)).toBeTrue();\n  });\n\n  it('should count story without the pageAttachment property set to null as empty', () => {\n    const storyWithoutAttachment = [createPage()];\n    const pageAttachmentObject = null;\n\n    storyWithoutAttachment[0].pageAttachment = pageAttachmentObject;\n    expect(isEmptyStory(storyWithoutAttachment)).toBeTrue();\n  });\n\n  it('should count story that has the pageAttachment property with an empty url string as empty', () => {\n    const storyWithoutAttachment = [createPage()];\n    const testUrl = '';\n    const pageAttachmentObject = { url: testUrl };\n\n    storyWithoutAttachment[0].pageAttachment = pageAttachmentObject;\n    expect(isEmptyStory(storyWithoutAttachment)).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/story/utils/test/pageContainsBlobUrl.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport pageContainsBlobUrl from '../pageContainsBlobUrl';\n\ndescribe('pageContainsBlobUrl', () => {\n  it('should find resource entry with blob url', () => {\n    const pages = [\n      {\n        elements: [\n          {\n            resource: {\n              src: 'https://example.com/bcee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n          {\n            resource: {\n              src: 'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n        ],\n      },\n    ];\n    expect(pageContainsBlobUrl(pages)).toBeTrue();\n  });\n\n  it('should find resource poster entry with blob url', () => {\n    const pages = [\n      {\n        elements: [\n          {\n            type: 'text',\n            font: {\n              family: 'Arial',\n              service: 'system',\n            },\n          },\n        ],\n      },\n      {\n        elements: [\n          {\n            resource: {\n              poster:\n                'https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n          {\n            resource: {\n              poster:\n                'blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n        ],\n      },\n    ];\n    expect(pageContainsBlobUrl(pages)).toBeTrue();\n  });\n\n  it('should allow page entries without blob urls', () => {\n    const pages = [\n      {\n        elements: [\n          {\n            type: 'text',\n            font: {\n              family: 'Arial',\n              service: 'system',\n            },\n          },\n          {\n            resource: {\n              src: 'https://example.com/bcee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n          {\n            resource: {\n              src: 'https://example.com/ccee4374-8f8a-4210-8f2d-9c5f8d6a6c5a',\n            },\n          },\n        ],\n      },\n    ];\n\n    expect(pageContainsBlobUrl(pages)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/taxonomy/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport type { TaxonomyState } from '../../types';\n\nexport default createContext<TaxonomyState>({\n  state: {\n    taxonomies: [],\n    termCache: [],\n    terms: [],\n  },\n  actions: {\n    createTerm: () => Promise.resolve(undefined),\n    addSearchResultsToCache: () => Promise.resolve(undefined),\n    addTerms: () => undefined,\n    removeTerms: () => undefined,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/taxonomy/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as TaxonomyProvider } from './taxonomyProvider';\nexport { default as useTaxonomy } from './useTaxonomy';\n"
  },
  {
    "path": "packages/story-editor/src/app/taxonomy/taxonomyProvider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type {\n  Story,\n  Term,\n  Taxonomy,\n  TermSlug,\n} from '@googleforcreators/elements';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type {\n  createTermProps,\n  TaxonomyRestError,\n  addSearchResultsToCacheProps,\n  UpdateStoryProps,\n} from '../../types';\nimport cleanForSlug from '../../utils/cleanForSlug';\nimport { useAPI } from '../api';\nimport { useStory } from '../story';\nimport removeDupsFromArray from '../../utils/removeDupsFromArray';\nimport Context from './context';\n\nfunction TaxonomyProvider(props: PropsWithChildren<unknown>) {\n  // Should grab categories on mount\n  const [shouldRefetchCategories, setShouldRefetchCategories] = useState(true);\n  const { updateStory, terms } = useStory(\n    ({ state: { pages, story }, actions: { updateStory } }) => ({\n      updateStory,\n      isStoryLoaded: pages.length > 0,\n      terms: story.terms || [],\n    })\n  );\n  const [hasTaxonomies, setHasTaxonomies] = useState(false);\n  const [taxonomies, setTaxonomies] = useState<Taxonomy[]>([]);\n  const [termCache, setTermCache] = useState<Term[]>([]);\n\n  const {\n    actions: { getTaxonomyTerm, createTaxonomyTerm, getTaxonomies },\n  } = useAPI();\n\n  // Get all registered `web-story` taxonomies.\n  useEffect(() => {\n    if (hasTaxonomies || !getTaxonomies) {\n      return;\n    }\n\n    void (async () => {\n      try {\n        const result = await getTaxonomies();\n        setTaxonomies(result);\n      } catch (e) {\n        if (e instanceof Error) {\n          // eslint-disable-next-line no-console -- Log error\n          console.error(e.message);\n        }\n      } finally {\n        setHasTaxonomies(true);\n      }\n    })();\n  }, [hasTaxonomies, getTaxonomies]);\n\n  const addTerms = useCallback(\n    (newTerms: Term[]) => {\n      if (updateStory) {\n        const properties = (story: Story) => {\n          const currentTerms = story?.terms || [];\n          return {\n            ...story,\n            terms: removeDupsFromArray([...currentTerms, ...newTerms], 'id'),\n          };\n        };\n        updateStory({ properties } as UpdateStoryProps);\n        setTermCache(\n          (cache: Term[]) =>\n            removeDupsFromArray([...cache, ...newTerms], 'id') as Term[]\n        );\n      }\n    },\n    [updateStory]\n  );\n\n  const removeTerms = useCallback(\n    (deleteTerms: Term[]) => {\n      if (updateStory) {\n        const removeTermsID = deleteTerms.map(({ id }) => id);\n        const properties = (story: Story) => {\n          const currentTerms = story?.terms || [];\n          const newAssignedTerms = currentTerms.filter(\n            ({ id }) => !removeTermsID.includes(id)\n          );\n          return {\n            ...story,\n            terms: newAssignedTerms,\n          };\n        };\n        updateStory({ properties } as UpdateStoryProps);\n      }\n    },\n    [updateStory]\n  );\n\n  const addSearchResultsToCache = useCallback(\n    async ({\n      taxonomy,\n      args,\n      addNameToSelection = false,\n    }: addSearchResultsToCacheProps) => {\n      let termResults: Term[] = [];\n      const termsEndpoint = taxonomy?.restPath;\n      if (!termsEndpoint || !getTaxonomyTerm) {\n        return [];\n      }\n      try {\n        termResults = await getTaxonomyTerm(termsEndpoint, args);\n      } catch (e) {\n        // Log error\n        if (e instanceof Error) {\n          // eslint-disable-next-line no-console -- We want to surface this error.\n          console.error(e.message);\n        }\n      }\n\n      // Avoid update if we're not actually adding any terms here\n      if (termResults.length < 1) {\n        return termResults;\n      }\n\n      setTermCache((cache: Term[]) => {\n        return cache\n          ? (removeDupsFromArray([...cache, ...termResults], 'id') as Term[])\n          : termResults;\n      });\n\n      if (addNameToSelection && args.search) {\n        const selectedTermSlug: TermSlug = cleanForSlug(args.search);\n        const selectedTerm = termResults.find(\n          (term: Term) => term.slug === selectedTermSlug\n        );\n\n        if (selectedTerm) {\n          addTerms([selectedTerm]);\n        }\n      }\n\n      return termResults;\n    },\n    [getTaxonomyTerm, addTerms]\n  );\n\n  const createTerm = useCallback(\n    async ({\n      taxonomy,\n      termName,\n      parent,\n      addToSelection = false,\n    }: createTermProps) => {\n      const data: Term = {\n        name: termName,\n      } as Term;\n      if (parent?.id) {\n        data.parent = parent.id;\n        data.slug = `${parent.slug}-${cleanForSlug(data.name)}`;\n      }\n\n      // make sure the term doesn't already exist locally\n      const preEmptiveSlug = data?.slug || cleanForSlug(termName) || '';\n      const cachedTerm: Term | undefined = termCache.find(\n        (term: Term) =>\n          term.slug === preEmptiveSlug && term.taxonomy === taxonomy.slug\n      );\n      if (cachedTerm) {\n        if (addToSelection) {\n          addTerms([cachedTerm]);\n        }\n\n        return;\n      }\n\n      const termsEndpoint = taxonomy?.restPath;\n      if (!termsEndpoint || !createTaxonomyTerm) {\n        return;\n      }\n\n      // create term and add to cache\n      try {\n        const newTerm: Term = await createTaxonomyTerm(termsEndpoint, data);\n\n        if (addToSelection) {\n          addTerms([newTerm]);\n        }\n      } catch (e) {\n        // If the backend says the term already exists\n        // we fetch for it as well as related terms to\n        // help more thoroughly populate our cache.\n        //\n        // We could pull down only the exact term, but\n        // we're modeling after Gutenberg.\n        if ((e as TaxonomyRestError).code === 'term_exists') {\n          void addSearchResultsToCache({\n            taxonomy,\n            args: { search: termName },\n            addNameToSelection: addToSelection,\n          });\n        }\n      }\n    },\n    [createTaxonomyTerm, termCache, addSearchResultsToCache, addTerms]\n  );\n\n  // Fetch hierarchical taxonomies on mount\n  useEffect(() => {\n    // only fetch when `shouldRefetchCategories` is true\n    if (shouldRefetchCategories && taxonomies?.length) {\n      const hierarchicalTaxonomies = taxonomies.filter(\n        (taxonomy: Taxonomy) => taxonomy.hierarchical\n      );\n      hierarchicalTaxonomies.forEach(\n        (taxonomy: Taxonomy) =>\n          void addSearchResultsToCache({ taxonomy, args: { per_page: -1 } })\n      );\n\n      setShouldRefetchCategories(false);\n    }\n  }, [addSearchResultsToCache, shouldRefetchCategories, taxonomies]);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        taxonomies,\n        termCache,\n        terms,\n      },\n      actions: {\n        createTerm,\n        addSearchResultsToCache,\n        addTerms,\n        removeTerms,\n      },\n    }),\n    [\n      termCache,\n      terms,\n      taxonomies,\n      createTerm,\n      addSearchResultsToCache,\n      addTerms,\n      removeTerms,\n    ]\n  );\n\n  return <Context.Provider {...props} value={value} />;\n}\n\nexport default TaxonomyProvider;\n"
  },
  {
    "path": "packages/story-editor/src/app/taxonomy/test/useTaxonomy.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../api';\nimport { useStory } from '../../story';\nimport cleanForSlug from '../../../utils/cleanForSlug';\nimport { TaxonomyProvider, useTaxonomy } from '..';\n\nfunction mockResponse(...args) {\n  return new Promise((r) => r(...args));\n}\n\nasync function receiveQueuedMockedResponses() {\n  // flush promise queue and resulting react updates\n  await act(async () => {\n    await new Promise((r) => r());\n  });\n}\n\njest.mock('../../story', () => ({\n  __esModule: true,\n  useStory: jest.fn(),\n}));\njest.mock('../../api', () => ({\n  __esModule: true,\n  useAPI: jest.fn(),\n}));\njest.mock('../../history', () => ({\n  __esModule: true,\n  useHistory: () => ({\n    actions: { clearHistory: () => {} },\n  }),\n}));\n\nfunction createTaxonomy(slug, overrides) {\n  return {\n    slug,\n    restBase: `${slug}s`,\n    restPath: 'someUrl',\n    ...overrides,\n  };\n}\n\nlet autoIncrementId;\n\nfunction createTermFromName(taxonomy, name, overrides) {\n  return {\n    id: autoIncrementId++,\n    name,\n    slug: cleanForSlug(name),\n    taxonomy: taxonomy.slug,\n    ...overrides,\n  };\n}\n\nasync function setup({ useStoryPartial = {}, useAPIPartial = {} }) {\n  useAPI.mockImplementation(() => ({\n    actions: {\n      getTaxonomyTerm: () => mockResponse([]),\n      createTaxonomyTerm: (_taxonomyEndpoint, { name, parent }) =>\n        mockResponse(\n          createTermFromName(createTaxonomy('fake restpoint response'), name, {\n            parent,\n          })\n        ),\n      getTaxonomies: () => mockResponse({}),\n      ...useAPIPartial,\n    },\n  }));\n  useStory.mockImplementation(() => ({\n    updateStory: () => {},\n    isStoryLoaded: true,\n    terms: [],\n    ...useStoryPartial,\n  }));\n\n  const render = renderHook(() => useTaxonomy(), { wrapper: TaxonomyProvider });\n  await receiveQueuedMockedResponses();\n  return render;\n}\n\ndescribe('TaxonomyProvider', () => {\n  beforeAll(() => {\n    autoIncrementId = 0;\n  });\n\n  it('should fetch taxonomies on mount if taxonomies present on story', async () => {\n    const sampleTaxonomy = createTaxonomy('sample');\n    const getTaxonomiesMock = jest.fn(() => mockResponse([sampleTaxonomy]));\n\n    const { result } = await setup({\n      useAPIPartial: { getTaxonomies: getTaxonomiesMock },\n    });\n\n    expect(getTaxonomiesMock).toHaveBeenCalledOnce();\n    expect(result.current.state.taxonomies).toStrictEqual([sampleTaxonomy]);\n  });\n\n  it('populates the terms cache when addSearchResultsToCache(..args) called', async () => {\n    const sampleTaxonomy = createTaxonomy('sample');\n    const taxonomiesResponse = { sampleTaxonomy };\n    const term1 = createTermFromName(sampleTaxonomy, 'term1');\n    const term2 = createTermFromName(sampleTaxonomy, 'term2');\n    const getTaxonomyTermMock = jest.fn(() => mockResponse([term1, term2]));\n\n    const { result } = await setup({\n      useAPIPartial: {\n        getTaxonomies: () => mockResponse(taxonomiesResponse),\n        getTaxonomyTerm: getTaxonomyTermMock,\n      },\n    });\n\n    act(() => {\n      result.current.actions.addSearchResultsToCache({\n        taxonomy: sampleTaxonomy,\n        args: {\n          search: 'term',\n          per_page: 20,\n        },\n      });\n    });\n\n    expect(getTaxonomyTermMock).toHaveBeenCalledWith('someUrl', {\n      search: 'term',\n      per_page: 20,\n    });\n\n    await receiveQueuedMockedResponses();\n\n    expect(result.current.state.termCache).toStrictEqual([term1, term2]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/taxonomy/useTaxonomy.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { TaxonomyState } from '../../types';\nimport Context from './context';\n\nfunction useTaxonomy(): TaxonomyState;\nfunction useTaxonomy<T>(selector: (state: TaxonomyState) => T): T;\nfunction useTaxonomy<T>(\n  selector: (state: TaxonomyState) => T | TaxonomyState = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useTaxonomy;\n"
  },
  {
    "path": "packages/story-editor/src/app/uploader/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useUploader } from './useUploader';\n"
  },
  {
    "path": "packages/story-editor/src/app/uploader/test/useUploader.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport ConfigContext from '../../config/context';\nimport APIContext from '../../api/context';\nimport useUploader from '../useUploader';\n\nconst mockShowSnackbar = jest.fn();\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: () => ({ showSnackbar: mockShowSnackbar }),\n}));\n\nfunction setup(args) {\n  const configValue = {\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    maxUpload: 104857600,\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    ...args,\n  };\n\n  const apiValue = {\n    actions: {\n      uploadMedia: jest.fn(() => 'Upload successful!'),\n    },\n  };\n\n  const wrapper = ({ children }) => (\n    <ConfigContext.Provider value={configValue}>\n      <APIContext.Provider value={apiValue}>{children}</APIContext.Provider>\n    </ConfigContext.Provider>\n  );\n  const { result } = renderHook(() => useUploader(), { wrapper });\n\n  return {\n    actions: result.current.actions,\n  };\n}\n\ndescribe('useUploader', () => {\n  beforeEach(() => {\n    mockShowSnackbar.mockReset();\n  });\n\n  describe('validateFileForUpload', () => {\n    it('throws an error if user does not have upload capabilities', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({\n        capabilities: {\n          hasUploadMediaAction: false,\n        },\n      });\n\n      await expect(() => validateFileForUpload({ file: {} })).toThrow(\n        'Sorry, you are not allowed to upload files.'\n      );\n    });\n\n    it('throws an error if file is too large', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({\n        maxUpload: 2000000,\n      });\n\n      await expect(() =>\n        validateFileForUpload({ file: { size: 3000000 } })\n      ).toThrow(\n        'Your file is 3MB and the upload limit is 2MB. Please resize and try again!'\n      );\n    });\n\n    it('throws an error if file type is not supported and cannot be transcoded', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 20000, type: 'video/quicktime' },\n        })\n      ).toThrow(\n        'Please choose only png, jpg, jpeg, gif, webp, mp4, or webm to upload.'\n      );\n    });\n\n    it('throws an error if file type is not supported and in list of mime types', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 20000, type: 'video/quicktime' },\n          overrideAllowedMimeTypes: ['video/mp4'],\n        })\n      ).toThrow('Please choose only mp4 to upload.');\n    });\n\n    it('throws an error if file too large to transcode', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 1024 * 1024 * 1024 * 2, type: 'video/mp4' },\n          canTranscodeFile: true,\n          isFileTooLarge: true,\n        })\n      ).toThrow(\n        'Your file is too large (2048 MB) and cannot be processed. Please try again with a file that is smaller than 2048 MB.'\n      );\n    });\n\n    it('throws an error if file is too large for transcoding', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({\n        maxUpload: 1024 * 1024 * 1024 * 10,\n      });\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 1024 * 1024 * 1024 * 3, type: 'video/quicktime' },\n          canTranscodeFile: true,\n          isFileTooLarge: true,\n        })\n      ).toThrow(\n        'Your file is too large (3072 MB) and cannot be processed. Please try again with a file that is smaller than 2048 MB.'\n      );\n    });\n\n    it('does not throw an error if file is too large to upload but can be transcoded', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 1024 * 1024 * 150, type: 'video/mp4' },\n          canTranscodeFile: true,\n          isFileTooLarge: false,\n        })\n      ).not.toThrow();\n    });\n\n    it('throws an error if file is too large to transcode or upload', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 1024 * 1024 * 1024 * 2, type: 'video/mp4' },\n          canTranscodeFile: false,\n          isFileTooLarge: true,\n        })\n      ).toThrow(\n        'Your file is 2048MB and the upload limit is 100MB. Please resize and try again!'\n      );\n    });\n\n    it('does not throw an error if file is not too large to upload', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({});\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 1024 * 1024 * 50, type: 'video/mp4' },\n          canTranscodeFile: false,\n          isFileTooLarge: false,\n        })\n      ).not.toThrow();\n    });\n\n    it('formats the error message correctly if there is only one file type supported', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({\n        allowedMimeTypes: { image: [], video: ['video/mp4'], vector: [] },\n      });\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 20000, type: 'video/quicktime' },\n        })\n      ).toThrow('Please choose only mp4 to upload.');\n    });\n\n    it('formats the error message correctly if no file types are supported', async () => {\n      const {\n        actions: { validateFileForUpload },\n      } = setup({ allowedMimeTypes: { image: [], video: [], vector: [] } });\n\n      await expect(() =>\n        validateFileForUpload({\n          file: { size: 20000, type: 'video/quicktime' },\n        })\n      ).toThrow('No file types are currently supported.');\n    });\n  });\n\n  describe('uploadFile', () => {\n    it('uploads image', async () => {\n      const {\n        actions: { uploadFile },\n      } = setup({});\n\n      const file = {\n        size: 20000,\n        type: 'image/png',\n      };\n\n      const result = await uploadFile(file);\n      expect(result).toBe('Upload successful!');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/uploader/useUploader.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport {\n  getFileBasename,\n  getExtensionsFromMimeType,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../api';\nimport { useConfig } from '../config';\nimport createError from '../../utils/createError';\nimport type { AdditionalData } from '../media/uploadQueue/types';\nimport { MEDIA_TRANSCODING_MAX_FILE_SIZE } from '../../constants';\n\ninterface ValidateFileForUploadProps {\n  file: File;\n  canTranscodeFile?: boolean;\n  isFileTooLarge?: boolean;\n  overrideAllowedMimeTypes: string[];\n}\n\nconst bytesToMB = (bytes: number) => String(Math.round(bytes / 1_048_576)); // 2^20\n\nfunction useUploader() {\n  const {\n    actions: { uploadMedia },\n  } = useAPI();\n  const {\n    storyId,\n    maxUpload = 0,\n    allowedMimeTypes: {\n      image: allowedImageMimeTypes = [],\n      vector: allowedVectorMimeTypes = [],\n      video: allowedVideoMimeTypes = [],\n    },\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const allowedMimeTypes = useMemo(\n    () => [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ],\n    [allowedImageMimeTypes, allowedVectorMimeTypes, allowedVideoMimeTypes]\n  );\n\n  const isFileSizeWithinLimits = useCallback(\n    ({ size }) => {\n      return size <= maxUpload;\n    },\n    [maxUpload]\n  );\n\n  /**\n   * Validates a file for upload.\n   *\n   * @throws Throws an error if file doesn't meet requirements.\n   * @param {Object} args\n   * @param {Object} args.file File object.\n   * @param {boolean} args.canTranscodeFile Whether file can be transcoded by consumer.\n   * @param {boolean} args.isFileTooLarge Whether file is too large for consumer.\n   * @param {Array} args.overrideAllowedMimeTypes Array of override allowed mime types.\n   */\n  const validateFileForUpload = useCallback(\n    ({\n      file,\n      canTranscodeFile,\n      isFileTooLarge,\n      overrideAllowedMimeTypes = allowedMimeTypes,\n    }: ValidateFileForUploadProps) => {\n      // Bail early if user doesn't have upload capabilities.\n      if (!hasUploadMediaAction) {\n        const message = __(\n          'Sorry, you are not allowed to upload files.',\n          'web-stories'\n        );\n        throw createError('PermissionError', file.name, message);\n      }\n\n      if (!canTranscodeFile) {\n        // The file is too large for the site anyway, abort.\n        if (!isFileSizeWithinLimits(file)) {\n          const message = sprintf(\n            /* translators: 1: the file size in MB. 2: is the upload file limit in MB */\n            __(\n              'Your file is %1$sMB and the upload limit is %2$sMB. Please resize and try again!',\n              'web-stories'\n            ),\n            bytesToMB(file.size),\n            bytesToMB(maxUpload)\n          );\n          throw createError('SizeError', file.name, message);\n        }\n\n        const isValidType = (currentFile: File) =>\n          overrideAllowedMimeTypes.includes(currentFile.type);\n        // TODO: Move this check to useUploadMedia?\n        if (!isValidType(file)) {\n          let message: string = __(\n            'No file types are currently supported.',\n            'web-stories'\n          );\n\n          const allowedFileTypes = overrideAllowedMimeTypes.flatMap((type) =>\n            getExtensionsFromMimeType(type)\n          );\n\n          if (allowedFileTypes.length) {\n            /* translators: %s is a list of allowed file extensions. */\n            message = sprintf(\n              /* translators: %s: list of allowed file types. */\n              __('Please choose only %s to upload.', 'web-stories'),\n              translateToExclusiveList(allowedFileTypes)\n            );\n          }\n\n          throw createError('ValidError', file.name, message);\n        }\n        // TODO: Move this check to useUploadMedia?\n      } else if (isFileTooLarge) {\n        const message = sprintf(\n          /* translators: 1: File size in MB. 2: Maximum allowed file size in MB. */\n          __(\n            'Your file is too large (%1$s MB) and cannot be processed. Please try again with a file that is smaller than %2$s MB.',\n            'web-stories'\n          ),\n          bytesToMB(file.size),\n          bytesToMB(MEDIA_TRANSCODING_MAX_FILE_SIZE)\n        );\n        throw createError('SizeError', file.name, message);\n      }\n    },\n    [allowedMimeTypes, hasUploadMediaAction, isFileSizeWithinLimits, maxUpload]\n  );\n\n  /**\n   * Uploads a file.\n   *\n   * @param {Object} file File object.\n   * @param {Object} additionalData Additional Data object.\n   * @param {Array} overrideAllowedMimeTypes Array of override allowed mime types.\n   */\n  const uploadFile = useCallback(\n    (\n      file: File,\n      additionalData: AdditionalData = {},\n      overrideAllowedMimeTypes: string[] = allowedMimeTypes\n    ) => {\n      // This will throw if the file cannot be uploaded.\n      validateFileForUpload({ file, overrideAllowedMimeTypes });\n\n      if (!uploadMedia) {\n        throw createError('UploadError', file.name, '');\n      }\n      const _additionalData = {\n        storyId,\n        altText: getFileBasename(file),\n        mediaSource: 'editor',\n        ...additionalData,\n      };\n\n      return uploadMedia(file, _additionalData);\n    },\n    [allowedMimeTypes, validateFileForUpload, storyId, uploadMedia]\n  );\n\n  return useMemo(() => {\n    return {\n      actions: {\n        uploadFile,\n        validateFileForUpload,\n      },\n    };\n  }, [validateFileForUpload, uploadFile]);\n}\n\nexport default useUploader;\n"
  },
  {
    "path": "packages/story-editor/src/app/userOnboarding/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { useUserOnboarding } from './useUserOnboarding';\n"
  },
  {
    "path": "packages/story-editor/src/app/userOnboarding/test/useUserOnboarding.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n/**\n * Internal dependencies\n */\nimport { useUserOnboarding } from '../..';\nimport { KEYS } from '../../helpCenter/constants';\nimport { useHelpCenter } from '../../helpCenter';\njest.mock('../../helpCenter');\n\ndescribe('useUserOnboarding', () => {\n  jest.useFakeTimers();\n  beforeEach(jest.clearAllMocks);\n\n  it('should open the help center to the Safe Zone tip if it is triggered', async () => {\n    const openToUnreadTip = jest.fn();\n    useHelpCenter.mockImplementationOnce(() => ({ openToUnreadTip }));\n\n    const { result: trigger } = renderHook(() =>\n      useUserOnboarding(({ SAFE_ZONE }) => SAFE_ZONE)\n    );\n\n    await act(async () => {\n      await trigger.current();\n    });\n\n    jest.runOnlyPendingTimers();\n    expect(openToUnreadTip).toHaveBeenCalledWith(KEYS.SAFE_ZONE);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/app/userOnboarding/useUserOnboarding.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useDebouncedCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { KEYS } from '../helpCenter/constants';\nimport { useHelpCenter } from '../helpCenter';\nimport { noop } from '../../utils/noop';\n\nconst TRIGGER_CONTEXTS = {\n  SAFE_ZONE: 'safeZone',\n};\n\nexport function useUserOnboarding(selector) {\n  const triggerType = selector(TRIGGER_CONTEXTS);\n\n  const { openToUnreadTip = noop } = useHelpCenter(({ actions }) => ({\n    openToUnreadTip: actions.openToUnreadTip,\n  }));\n\n  const openToUnreadTipDebounced = useDebouncedCallback(openToUnreadTip, 300);\n\n  const trigger = useCallback(() => {\n    switch (triggerType) {\n      case TRIGGER_CONTEXTS.SAFE_ZONE:\n        openToUnreadTipDebounced(KEYS.SAFE_ZONE);\n        break;\n      default:\n        return;\n    }\n  }, [triggerType, openToUnreadTipDebounced]);\n\n  return trigger;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/autoSaveCheck/autoSaveDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Text,\n  TextSize,\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonAsLink,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\n\nexport const AutoSaveDialog = ({ onClose, isOpen, autoSaveLink }) => {\n  return (\n    <Dialog\n      isOpen={isOpen}\n      title={__('Autosave', 'web-stories')}\n      contentLabel={__('Autosave Available', 'web-stories')}\n      secondaryText={__('Dismiss', 'web-stories')}\n      onClose={onClose}\n      actions={\n        <>\n          <Button\n            type={ButtonType.Tertiary}\n            size={ButtonSize.Small}\n            onClick={onClose}\n          >\n            {__('Dismiss', 'web-stories')}\n          </Button>\n          <ButtonAsLink\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            href={autoSaveLink}\n          >\n            {__('View the autosave', 'web-stories')}\n          </ButtonAsLink>\n        </>\n      }\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'There is an autosave of this story that is more recent than the version you are editing.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Dialog>\n  );\n};\n\nAutoSaveDialog.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  onClose: PropTypes.func.isRequired,\n  autoSaveLink: PropTypes.string.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/autoSaveCheck/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app/config';\nimport { AutoSaveDialog } from './autoSaveDialog';\n\nexport const AutoSaveCheck = () => {\n  const { autoSaveLink } = useConfig();\n  const [showDialog, setShowDialog] = useState(Boolean(autoSaveLink));\n  const onClose = () => setShowDialog(false);\n\n  return (\n    <AutoSaveDialog\n      isOpen={showDialog}\n      onClose={onClose}\n      autoSaveLink={autoSaveLink}\n    />\n  );\n};\n\nexport default AutoSaveCheck;\n"
  },
  {
    "path": "packages/story-editor/src/components/autoSaveCheck/stories/autoSaveDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { AutoSaveDialog } from '../autoSaveDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Autosave link dialog',\n  component: AutoSaveDialog,\n  args: {\n    isOpen: true,\n    autoSaveLink: 'http://example.com',\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <AutoSaveDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/autoSaveHandler/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useConfig, useHistory, useStory } from '../../app';\nimport useIsUploadingToStory from '../../utils/useIsUploadingToStory';\n\nfunction AutoSaveHandler() {\n  const { autoSaveInterval } = useConfig();\n  const {\n    state: { hasNewChanges },\n  } = useHistory();\n  const { autoSave, isSaving } = useStory(({ actions, state }) => ({\n    isSaving: state.meta.isSaving,\n    autoSave: actions.autoSave,\n  }));\n  const isUploading = useIsUploadingToStory();\n\n  // Cache it to make it stable in terms of the below timeout\n  const cachedSaveStoryRef = useRef(autoSave);\n  useEffect(() => {\n    cachedSaveStoryRef.current = autoSave;\n  }, [autoSave]);\n\n  useEffect(() => {\n    if (!hasNewChanges || !autoSaveInterval || isUploading || isSaving) {\n      return undefined;\n    }\n    // This is only a timeout (and not an interval), as `hasNewChanges` will come\n    // back false after the save.\n    // This timeout will thus be re-started when some new change occurs after an autosave.\n    const timeout = setTimeout(\n      () => cachedSaveStoryRef.current(),\n      autoSaveInterval * 1000\n    );\n\n    return () => clearTimeout(timeout);\n  }, [autoSaveInterval, hasNewChanges, isUploading, isSaving]);\n\n  return null;\n}\n\nexport default AutoSaveHandler;\n"
  },
  {
    "path": "packages/story-editor/src/components/autoSaveHandler/test/autoSaveHandler.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport HistoryContext from '../../../app/history/context';\nimport StoryContext from '../../../app/story/context';\nimport ConfigContext from '../../../app/config/context';\nimport AutoSaveHandler from '..';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\n\njest.mock('../../../utils/useIsUploadingToStory');\n\nfunction setup({\n  hasNewChanges = true,\n  status = 'draft',\n  autoSaveInterval = 0.1,\n  isUploading = false,\n}) {\n  const autoSave = jest.fn();\n  const historyContextValue = { state: { hasNewChanges } };\n  const configValue = {\n    autoSaveInterval,\n  };\n  const storyContextValue = {\n    state: {\n      story: { status },\n      meta: { isSaving: false },\n    },\n    actions: { autoSave },\n  };\n\n  useIsUploadingToStory.mockImplementation(() => isUploading);\n\n  const { rerender } = render(\n    <ConfigContext.Provider value={configValue}>\n      <HistoryContext.Provider value={historyContextValue}>\n        <StoryContext.Provider value={storyContextValue}>\n          <AutoSaveHandler />\n        </StoryContext.Provider>\n      </HistoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n  const secondaryautoSave = jest.fn();\n  const secondaryStoryContextValue = {\n    state: {\n      story: { status },\n    },\n    actions: { autoSave: secondaryautoSave },\n  };\n  const renderAgain = () => {\n    rerender(\n      <ConfigContext.Provider value={configValue}>\n        <HistoryContext.Provider value={historyContextValue}>\n          <StoryContext.Provider value={secondaryStoryContextValue}>\n            <AutoSaveHandler />\n          </StoryContext.Provider>\n        </HistoryContext.Provider>\n      </ConfigContext.Provider>\n    );\n    return secondaryautoSave;\n  };\n  return {\n    autoSave,\n    renderAgain,\n  };\n}\n\ndescribe('AutoSaveHandler', () => {\n  beforeEach(() => {\n    jest.useFakeTimers();\n  });\n\n  it('should trigger saving in case of a draft', () => {\n    const { autoSave } = setup({});\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledOnce();\n  });\n\n  it('should not trigger saving in case of not having new changes', () => {\n    const { autoSave } = setup({ hasNewChanges: false });\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledTimes(0);\n  });\n\n  it('should also trigger saving for a non-draft post', () => {\n    const { autoSave } = setup({ hasNewChanges: true, status: 'publish' });\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledOnce();\n  });\n\n  it('should not trigger saving when interval is 0', () => {\n    const { autoSave } = setup({\n      autoSaveInterval: 0,\n    });\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledTimes(0);\n  });\n\n  it('should not trigger saving when media is uploading', () => {\n    const { autoSave } = setup({\n      isUploading: true,\n    });\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledTimes(0);\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- It needs overhaul for the current version.\n  it.skip('should only setup one timeout even if autoSave updates', () => {\n    jest.spyOn(window, 'setTimeout');\n\n    const { renderAgain, autoSave } = setup({});\n    // The number of invocations of setTimeout might vary due to other components\n    // so the only thing we can check for sure is, that the number doesn't go up by\n    // changing the props in the story handler.\n    const timeoutCallsBefore = setTimeout.mock.calls.length;\n    const secondaryautoSave = renderAgain();\n    const timeoutCallsAfter = setTimeout.mock.calls.length;\n    expect(timeoutCallsAfter).toBe(timeoutCallsBefore);\n\n    expect(secondaryautoSave).not.toBe(autoSave);\n\n    jest.runAllTimers();\n    expect(autoSave).toHaveBeenCalledTimes(0);\n    expect(secondaryautoSave).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/canvas.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport CanvasLayout from './canvasLayout';\n\nfunction Canvas({ header, footer }) {\n  return <CanvasLayout header={header} footer={footer} />;\n}\n\nCanvas.propTypes = {\n  header: PropTypes.node,\n  footer: PropTypes.object,\n};\n\nexport default Canvas;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/canvasElementDropzone.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { useUnits } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useDropTargets } from '../dropTargets';\nimport { isDragType } from '../../utils/dragEvent';\nimport { useCanvas } from '../../app';\nimport useInsertElement from './useInsertElement';\n\nconst Container = styled.div`\n  width: 100%;\n  height: 100%;\n`;\n\nfunction CanvasElementDropzone({ children }) {\n  const insertElement = useInsertElement();\n\n  const { activeDropTargetId } = useDropTargets((state) => ({\n    activeDropTargetId: state.state.activeDropTargetId,\n  }));\n  const { pageContainer } = useCanvas((state) => ({\n    pageContainer: state.state.pageContainer,\n  }));\n  const { editorToDataX, editorToDataY } = useUnits((state) => ({\n    editorToDataX: state.actions.editorToDataX,\n    editorToDataY: state.actions.editorToDataY,\n  }));\n\n  const onDropHandler = useCallback(\n    (e) => {\n      // Handles onDrop for shapes.\n      if (isDragType(e, 'resource/media') && !activeDropTargetId) {\n        const {\n          resource,\n          offset: { x: offsetX, y: offsetY, w: offsetWidth, h: offsetHeight },\n        } = JSON.parse(e.dataTransfer.getData('resource/media'));\n        const { x, y } = pageContainer.getBoundingClientRect();\n\n        insertElement(resource.type, {\n          resource,\n          x: editorToDataX(e.clientX - x - offsetX),\n          y: editorToDataY(e.clientY - y - offsetY),\n          width: editorToDataX(offsetWidth),\n          height: editorToDataY(offsetHeight),\n        });\n        e.stopPropagation();\n        e.preventDefault();\n      }\n    },\n    [\n      activeDropTargetId,\n      pageContainer,\n      insertElement,\n      editorToDataX,\n      editorToDataY,\n    ]\n  );\n  const onDragOverHandler = useCallback(\n    (e) => {\n      if (!isDragType(e, 'resource/media') || activeDropTargetId) {\n        return;\n      }\n      e.stopPropagation();\n      e.preventDefault();\n    },\n    [activeDropTargetId]\n  );\n\n  return (\n    <Container onDrop={onDropHandler} onDragOver={onDragOverHandler}>\n      {children}\n    </Container>\n  );\n}\n\nCanvasElementDropzone.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default CanvasElementDropzone;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/canvasLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { StyleSheetManager } from 'styled-components';\nimport { memo, useRef, useCombinedRefs } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport {\n  CANVAS_BOUNDING_BOX_IDS,\n  useCanvas,\n  useCanvasBoundingBoxRef,\n  useLayout,\n} from '../../app';\nimport { FloatingMenuLayer } from '../floatingMenu';\nimport { useMediaRecording } from '../mediaRecording';\nimport EditLayer from './editLayer';\nimport DisplayLayer from './displayLayer';\nimport FramesLayer from './framesLayer';\nimport NavLayer from './navLayer';\nimport SelectionCanvas from './selectionCanvas';\nimport { useLayoutParams, useLayoutParamsCssVars } from './layout';\nimport CanvasUploadDropTarget from './canvasUploadDropTarget';\nimport CanvasElementDropzone from './canvasElementDropzone';\nimport EyedropperLayer from './eyedropperLayer';\nimport EmptyStateLayer from './emptyStateLayer';\nimport EditLayerFocusManager from './editLayerFocusManager';\nimport MediaRecordingLayer from './mediaRecordingLayer';\n\n// data-fix-caret is for allowing caretRangeFromPoint to work in Safari.\n// See https://github.com/googleforcreators/web-stories-wp/issues/7745.\nconst Background = styled.section.attrs({\n  'aria-label': __('Canvas', 'web-stories'),\n  'data-fix-caret': true,\n})`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  width: 100%;\n  height: 100%;\n  position: relative;\n  user-select: none;\n`;\n\nfunction CanvasLayout({ header, footer }) {\n  const boundingBoxTrackingRef = useCanvasBoundingBoxRef(\n    CANVAS_BOUNDING_BOX_IDS.CANVAS_CONTAINER\n  );\n  const setCanvasContainer = useCanvas(\n    (state) => state.actions.setCanvasContainer\n  );\n\n  const backgroundRef = useRef(null);\n\n  const setBackgroundRef = useCombinedRefs(\n    backgroundRef,\n    setCanvasContainer,\n    boundingBoxTrackingRef\n  );\n\n  useLayoutParams(backgroundRef);\n  const layoutParamsCss = useLayoutParamsCssVars();\n\n  const { pageWidth, pageHeight } = useLayout(\n    ({ state: { pageWidth, pageHeight } }) => ({\n      pageWidth,\n      pageHeight,\n    })\n  );\n\n  const { isInRecordingMode } = useMediaRecording(\n    ({ state: { isInRecordingMode } }) => ({ isInRecordingMode })\n  );\n\n  // If we don't have proper canvas dimensions yet, don't bother rendering element layers.\n  const hasDimensions = pageWidth !== 0 && pageHeight !== 0;\n\n  // Elsewhere we use stylisRTLPlugin in case of RTL, however, since we're\n  // forcing the canvas to always be LTR due to problems that otherwise come up\n  // with Moveable and left-right direction, for this subtree, we are not using any plugin.\n  // See also https://styled-components.com/docs/api#stylesheetmanager for general usage.\n  return (\n    <StyleSheetManager stylisPlugins={[]}>\n      <EditLayerFocusManager>\n        <Background ref={setBackgroundRef} style={layoutParamsCss}>\n          <CanvasUploadDropTarget>\n            <CanvasElementDropzone>\n              <SelectionCanvas>\n                {hasDimensions && !isInRecordingMode && <DisplayLayer />}\n                {hasDimensions && !isInRecordingMode && <FramesLayer />}\n                <NavLayer header={header} footer={footer} />\n              </SelectionCanvas>\n              <EditLayer />\n              {!isInRecordingMode && (\n                <>\n                  <EyedropperLayer />\n                  <EmptyStateLayer />\n                  <FloatingMenuLayer />\n                </>\n              )}\n              {isInRecordingMode && <MediaRecordingLayer />}\n            </CanvasElementDropzone>\n          </CanvasUploadDropTarget>\n        </Background>\n      </EditLayerFocusManager>\n    </StyleSheetManager>\n  );\n}\n\nCanvasLayout.propTypes = {\n  header: PropTypes.node,\n  footer: PropTypes.object,\n};\n\nexport default memo(CanvasLayout);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/canvasUploadDropTarget.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport {\n  UploadDropTarget,\n  UploadDropTargetMessage,\n  UploadDropTargetOverlay,\n} from '../uploadDropTarget';\n\nimport { Layer as CanvasLayer, PageArea } from './layout';\nimport useUploadWithPreview from './useUploadWithPreview';\n\nconst MESSAGE_ID = 'edit-story-canvas-upload-message';\n\nfunction CanvasUploadDropTarget({ children }) {\n  const uploadWithPreview = useUploadWithPreview();\n  const onDropHandler = useCallback(\n    (files) => {\n      if (files && files.length > 0) {\n        uploadWithPreview(files);\n      }\n    },\n    [uploadWithPreview]\n  );\n  return (\n    <UploadDropTarget onDrop={onDropHandler} labelledBy={MESSAGE_ID}>\n      {children}\n      <UploadDropTargetOverlay>\n        <CanvasLayer>\n          <PageArea\n            overlay={\n              <UploadDropTargetMessage\n                id={MESSAGE_ID}\n                message={__(\n                  'Upload to media library and add to the page.',\n                  'web-stories'\n                )}\n              />\n            }\n          />\n        </CanvasLayer>\n      </UploadDropTargetOverlay>\n    </UploadDropTarget>\n  );\n}\n\nCanvasUploadDropTarget.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default CanvasUploadDropTarget;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/displayElement.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Element } from '@googleforcreators/elements';\n\nexport interface DisplayElementProps {\n  element: Element;\n  previewMode?: boolean;\n  isAnimatable?: boolean;\n  siblingCount?: number;\n}\ndeclare function DisplayElement(props: DisplayElementProps): JSX.Element;\nexport default DisplayElement;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/displayElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { memo, useRef, useState } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { calcRotatedResizeOffset, useUnits } from '@googleforcreators/units';\nimport { WAAPIWrapper } from '@googleforcreators/animation';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport {\n  getDefinitionForType,\n  ELEMENT_TYPES,\n} from '@googleforcreators/elements';\nimport {\n  elementWithPosition,\n  elementWithRotation,\n  elementWithSize,\n  useColorTransformHandler,\n} from '@googleforcreators/element-library';\nimport {\n  canSupportMultiBorder,\n  DisplayWithMask as WithMask,\n  getResponsiveBorder,\n} from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../propTypes';\nimport useCORSProxy from '../../utils/useCORSProxy';\nimport { useLocalMedia, useFont, useConfig } from '../../app';\nimport renderResourcePlaceholder from './renderResourcePlaceholder';\n\n// Using attributes to avoid creation of hundreds of classes by styled components for previewMode.\nconst Wrapper = styled.div.attrs(\n  ({ previewMode, x, y, width, height, rotationAngle }) => {\n    const style = {\n      position: 'absolute',\n      zIndex: 1,\n      left: `${x}px`,\n      top: `${y}px`,\n      width: `${width}px`,\n      height: `${height}px`,\n      transform: `rotate(${rotationAngle}deg)`,\n    };\n    return previewMode ? { style } : {};\n  }\n)`\n  ${({ previewMode }) => !previewMode && elementWithPosition}\n  ${({ previewMode }) => !previewMode && elementWithSize}\n  ${({ previewMode }) => !previewMode && elementWithRotation}\n  contain: layout;\n  transition: opacity 0.15s cubic-bezier(0, 0, 0.54, 1);\n  ${({ isBackground, theme }) =>\n    isBackground &&\n    css`\n      border-radius: ${theme.borders.radius.small};\n      overflow: hidden;\n    `}\n`;\n\nconst BackgroundOverlay = styled.div`\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n`;\n\nconst ReplacementContainer = styled.div`\n  transition: opacity 0.25s cubic-bezier(0, 0, 0.54, 1);\n  pointer-events: none;\n  opacity: ${({ hasReplacement }) => (hasReplacement ? 1 : 0)};\n  height: 100%;\n`;\n\nfunction AnimationWrapper({ children, id, isAnimatable }) {\n  return isAnimatable ? (\n    <WAAPIWrapper target={id}>{children}</WAAPIWrapper>\n  ) : (\n    children\n  );\n}\nAnimationWrapper.propTypes = {\n  isAnimatable: PropTypes.bool.isRequired,\n  children: PropTypes.arrayOf(PropTypes.node),\n  id: PropTypes.string,\n};\n\nfunction DisplayElement({\n  element,\n  previewMode,\n  isAnimatable = false,\n  siblingCount = 0,\n}) {\n  const { getBox, getBoxWithBorder, dataToEditorX } = useUnits((state) => ({\n    getBox: state.actions.getBox,\n    getBoxWithBorder: state.actions.getBoxWithBorder,\n    dataToEditorX: state.actions.dataToEditorX,\n  }));\n  const { getProxiedUrl } = useCORSProxy();\n  const { cdnURL } = useConfig();\n  const {\n    actions: { maybeEnqueueFontStyle },\n  } = useFont();\n\n  const [replacement, setReplacement] = useState(null);\n\n  const hasReplacement = Boolean(replacement);\n\n  const {\n    id,\n    opacity,\n    type,\n    isBackground,\n    overlay,\n    border,\n    flip,\n    rotationAngle,\n  } = element;\n\n  const { isCurrentResourceProcessing, isCurrentResourceUploading } =\n    useLocalMedia(({ state }) => {\n      return ELEMENT_TYPES.IMAGE === type\n        ? {\n            isCurrentResourceProcessing: state.isCurrentResourceProcessing,\n            isCurrentResourceUploading: state.isCurrentResourceUploading,\n          }\n        : {};\n    });\n\n  const replacementElement = hasReplacement\n    ? {\n        ...element,\n        type: replacement.resource.type,\n        resource: replacement.resource,\n        scale: replacement.scale,\n        focalX: replacement.focalX,\n        focalY: replacement.focalY,\n        // Okay, this is a bit weird, but... the flip and overlay properties are taken from the dragged image\n        // if the drop-target is the background element, but from the original drop-target image\n        // itself if the drop-target is a regular element.\n        //\n        // @see compare with similar logic in `combineElements`\n        flip: isBackground ? replacement.flip : flip,\n        overlay: isBackground ? replacement.overlay : overlay,\n      }\n    : null;\n\n  let Replacement;\n  if (replacement?.resource.type) {\n    const definition = getDefinitionForType(replacement.resource.type);\n    Replacement = definition.Display;\n  }\n\n  const wrapperRef = useRef(null);\n\n  const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n  useTransformHandler(id, (transform) => {\n    const target = wrapperRef.current;\n    if (transform === null) {\n      target.style.transform = '';\n      target.style.width = '';\n      target.style.height = '';\n    } else {\n      const { translate = [0, 0], rotate, resize, dropTargets } = transform;\n\n      let dx = 0;\n      let dy = 0;\n      if (resize && resize[0] !== 0 && resize[1] !== 0) {\n        target.style.width = `${resize[0]}px`;\n        target.style.height = `${resize[1]}px`;\n\n        // If we have border, we have to adjust the transformation since the border was considered by Moveable when\n        // creating the transformation values but the border is not considered in the width and height of the element.\n        // So we calculate a transformation assuming that the element was resized by the border and then deduct it from the\n        // applied transformation.\n        // We add canSupportMultiBorder check to ignore non-rectangular shapes since the border works differently for those.\n        if (canSupportMultiBorder(element)) {\n          const [_dx, _dy] = calcRotatedResizeOffset(\n            rotationAngle,\n            0,\n            left + right,\n            0,\n            top + bottom\n          );\n          dx = _dx;\n          dy = _dy;\n        }\n      }\n      target.style.transform = `translate(${translate[0] - dx}px, ${\n        translate[1] - dy\n      }px) rotate(${rotate}deg)`;\n      if (dropTargets?.hover !== undefined) {\n        target.style.opacity = dropTargets.hover ? 0 : 1;\n      }\n      if (dropTargets?.replacement !== undefined) {\n        setReplacement(dropTargets.replacement || null);\n      }\n    }\n  });\n\n  const bgOverlayRef = useRef(null);\n  useColorTransformHandler({\n    id,\n    targetRef: bgOverlayRef,\n    resetOnNullTransform: false,\n  });\n\n  if (element.isHidden) {\n    return null;\n  }\n\n  const { Display } = getDefinitionForType(type);\n\n  // The element content will use box without border, the wrapper will use box with border.\n  const box = getBox(element);\n  const boxWithBorder = getBoxWithBorder(element);\n\n  const responsiveBorder = getResponsiveBorder(\n    border,\n    previewMode,\n    dataToEditorX\n  );\n\n  return (\n    <Wrapper\n      ref={wrapperRef}\n      data-element-id={id}\n      isBackground={element.isBackground}\n      previewMode={previewMode}\n      {...(previewMode ? box : boxWithBorder)}\n    >\n      <AnimationWrapper id={id} isAnimatable={isAnimatable}>\n        <WithMask\n          element={element}\n          fill\n          style={{\n            opacity: typeof opacity !== 'undefined' ? opacity / 100 : null,\n          }}\n          previewMode={previewMode}\n          responsiveBorder={responsiveBorder}\n        >\n          <Display\n            element={element}\n            previewMode={previewMode}\n            box={box}\n            getProxiedUrl={getProxiedUrl}\n            isCurrentResourceProcessing={isCurrentResourceProcessing}\n            isCurrentResourceUploading={isCurrentResourceUploading}\n            maybeEnqueueFontStyle={maybeEnqueueFontStyle}\n            siblingCount={siblingCount}\n            renderResourcePlaceholder={renderResourcePlaceholder}\n            cdnUrl={cdnURL}\n          />\n        </WithMask>\n        {!previewMode && (\n          <ReplacementContainer hasReplacement={hasReplacement}>\n            {replacementElement && (\n              <WithMask\n                element={replacementElement}\n                fill\n                style={{\n                  opacity: opacity ? opacity / 100 : null,\n                }}\n                previewMode={previewMode}\n              >\n                <Replacement\n                  element={replacementElement}\n                  box={box}\n                  getProxiedUrl={getProxiedUrl}\n                  isCurrentResourceProcessing={isCurrentResourceProcessing}\n                  isCurrentResourceUploading={isCurrentResourceUploading}\n                  maybeEnqueueFontStyle={maybeEnqueueFontStyle}\n                />\n              </WithMask>\n            )}\n          </ReplacementContainer>\n        )}\n        {isBackground && overlay && !hasReplacement && (\n          <BackgroundOverlay\n            ref={bgOverlayRef}\n            style={generatePatternStyles(overlay)}\n          />\n        )}\n      </AnimationWrapper>\n    </Wrapper>\n  );\n}\n\nDisplayElement.propTypes = {\n  previewMode: PropTypes.bool,\n  element: StoryPropTypes.element.isRequired,\n  siblingCount: PropTypes.number,\n  isAnimatable: PropTypes.bool,\n};\n\n// Don't rerender the display element needlessly (e.g. element selection change)\n// if the element or other props haven't changed.\nexport default memo(DisplayElement);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/displayLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  memo,\n  useCallback,\n  useEffect,\n  useMemo,\n  useCombinedRefs,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { _x, __ } from '@googleforcreators/i18n';\nimport {\n  AnimationProvider,\n  StoryAnimationState,\n  useStoryAnimationContext,\n} from '@googleforcreators/animation';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport {\n  useStory,\n  useCanvas,\n  useCanvasBoundingBoxRef,\n  CANVAS_BOUNDING_BOX_IDS,\n} from '../../app';\nimport { STABLE_ARRAY } from '../../constants';\nimport { StoryPropTypes } from '../../propTypes';\nimport DisplayElement from './displayElement';\nimport { Layer, PageArea } from './layout';\nimport PageAttachment from './pageAttachment';\nimport ShoppingPageAttachment from './shoppingPageAttachment';\nimport { MediaCaptionsLayer } from './mediaCaptions';\n\nconst DisplayPageArea = styled(PageArea)`\n  position: absolute;\n`;\n\nfunction DisplayPage({ pageElements, editingElement }) {\n  return pageElements\n    ? pageElements.map((element) => {\n        if (editingElement === element.id) {\n          return null;\n        }\n        if (element.isHidden) {\n          return null;\n        }\n\n        const siblingCount =\n          pageElements.filter(({ type }) => type === element.type).length - 1;\n\n        return (\n          <DisplayElement\n            key={element.id}\n            element={element}\n            isAnimatable\n            siblingCount={siblingCount}\n          />\n        );\n      })\n    : null;\n}\n\nDisplayPage.propTypes = {\n  pageElements: PropTypes.arrayOf(StoryPropTypes.element),\n  editingElement: PropTypes.string,\n};\n\nfunction DisplayPageAnimationController({ resetAnimationState }) {\n  const { animationState, pageId } = useStory(({ state }) => ({\n    animationState: state.animationState,\n    pageId: state.currentPage?.id,\n  }));\n\n  const WAAPIAnimationMethods = useStoryAnimationContext(\n    ({ actions }) => actions.WAAPIAnimationMethods\n  );\n\n  useEffect(() => {\n    switch (animationState) {\n      case StoryAnimationState.PlayingSelected:\n      case StoryAnimationState.Playing:\n        WAAPIAnimationMethods.play();\n        return;\n\n      case StoryAnimationState.Reset:\n        WAAPIAnimationMethods.reset();\n        return;\n\n      case StoryAnimationState.Scrubbing:\n      case StoryAnimationState.Paused:\n        WAAPIAnimationMethods.pause();\n        return;\n      default:\n        return;\n    }\n  }, [animationState, WAAPIAnimationMethods]);\n\n  /*\n   * Reset animation state if user changes page\n   */\n  useEffect(() => resetAnimationState, [resetAnimationState, pageId]);\n\n  return null;\n}\n\nDisplayPageAnimationController.propTypes = {\n  resetAnimationState: PropTypes.func,\n};\n\nfunction StoryAnimations({ children }) {\n  const {\n    isAnimationPlaying,\n    currentPageAnimations,\n    currentPageElements,\n    selectedElements,\n    updateAnimationState,\n  } = useStory(({ state, actions }) => {\n    return {\n      isAnimationPlaying:\n        state.animationState === StoryAnimationState.PlayingSelected,\n      currentPageAnimations: state.currentPage?.animations || STABLE_ARRAY,\n      currentPageElements: state.currentPage?.elements || STABLE_ARRAY,\n      selectedElements: state.selectedElements,\n      updateAnimationState: actions.updateAnimationState,\n    };\n  });\n\n  const resetAnimationState = useCallback(() => {\n    updateAnimationState({ animationState: StoryAnimationState.Reset });\n  }, [updateAnimationState]);\n\n  const animatedElements = useMemo(\n    () => selectedElements.map((el) => el.id),\n    [selectedElements]\n  );\n\n  return (\n    <AnimationProvider\n      animations={currentPageAnimations}\n      elements={currentPageElements}\n      onWAAPIFinish={resetAnimationState}\n      selectedElementIds={isAnimationPlaying ? animatedElements : STABLE_ARRAY}\n    >\n      <DisplayPageAnimationController\n        resetAnimationState={resetAnimationState}\n      />\n      {children}\n    </AnimationProvider>\n  );\n}\n\nStoryAnimations.propTypes = {\n  children: PropTypes.node,\n};\n\nfunction DisplayLayer() {\n  const {\n    backgroundColor,\n    isBackgroundSelected,\n    pageAttachment,\n    shoppingAttachment,\n    hasProducts,\n  } = useStory(({ state }) => {\n    return {\n      hasCurrentPage: Boolean(state.currentPage),\n      backgroundColor: state.currentPage?.backgroundColor,\n      isBackgroundSelected: state.selectedElements?.[0]?.isBackground,\n      pageAttachment: state.currentPage?.pageAttachment || {},\n      shoppingAttachment: state.currentPage?.shoppingAttachment || {},\n      hasProducts: state.currentPage?.elements?.some(\n        ({ type, product }) =>\n          type === ELEMENT_TYPES.PRODUCT && product?.productId\n      ),\n    };\n  });\n\n  // Have page elements shallowly equaled for scenarios like animation\n  // updates where elements don't change, but we get a new page elements\n  // array\n  const currentPageElements = useStory(\n    ({ state }) => state.currentPage?.elements || STABLE_ARRAY\n  );\n\n  const boundingBoxTrackingRef = useCanvasBoundingBoxRef(\n    CANVAS_BOUNDING_BOX_IDS.PAGE_CONTAINER\n  );\n  const { editingElement, setPageContainer, setFullbleedContainer } = useCanvas(\n    ({\n      state: { editingElement },\n      actions: { setPageContainer, setFullbleedContainer },\n    }) => ({ editingElement, setPageContainer, setFullbleedContainer })\n  );\n\n  const Overlay = useMemo(() => {\n    if (hasProducts) {\n      return <ShoppingPageAttachment {...shoppingAttachment} />;\n    }\n\n    // Always render <PageAttachment> because the pageAttachmentContainer ref\n    // is needed in the page attachment panel and the useElementsWithLinks hook.\n    return <PageAttachment pageAttachment={pageAttachment} />;\n  }, [hasProducts, pageAttachment, shoppingAttachment]);\n\n  return (\n    <StoryAnimations>\n      <Layer\n        data-testid=\"DisplayLayer\"\n        pointerEvents=\"none\"\n        aria-label={_x('Display layer', 'compound noun', 'web-stories')}\n      >\n        <DisplayPageArea\n          ref={useCombinedRefs(setPageContainer, boundingBoxTrackingRef)}\n          fullbleedRef={setFullbleedContainer}\n          background={backgroundColor}\n          isBackgroundSelected={isBackgroundSelected}\n          fullBleedContainerLabel={__(\n            'Fullbleed area (Display layer)',\n            'web-stories'\n          )}\n          overlay={Overlay}\n          isControlled\n        >\n          <DisplayPage\n            pageElements={currentPageElements}\n            editingElement={editingElement}\n          />\n        </DisplayPageArea>\n        <MediaCaptionsLayer />\n      </Layer>\n    </StoryAnimations>\n  );\n}\n\nexport default memo(DisplayLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo, useState, forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useUnits } from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport { BG_MIN_SCALE, BG_MAX_SCALE } from '@googleforcreators/animation';\nimport {\n  elementWithPosition,\n  elementWithSize,\n  elementWithRotation,\n} from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport useCORSProxy from '../../utils/useCORSProxy';\nimport { useConfig, useStory, useFont } from '../../app';\nimport useVideoTrim from '../videoTrim/useVideoTrim';\n\nconst Z_INDEX_CANVAS = {\n  FLOAT_PANEL: 11,\n};\n\nconst Wrapper = styled.div`\n  ${elementWithPosition}\n  ${elementWithSize}\n  ${elementWithRotation}\n  pointer-events: initial;\n`;\n\nconst EditElement = memo(\n  forwardRef(function EditElement({ element, editWrapper, onResize }, ref) {\n    const { id, type } = element;\n    const { getBox, getBoxWithBorder } = useUnits((state) => ({\n      getBox: state.actions.getBox,\n      getBoxWithBorder: state.actions.getBoxWithBorder,\n    }));\n    const { getProxiedUrl } = useCORSProxy();\n    const { isRTL, styleConstants: { topOffset } = {} } = useConfig();\n    const {\n      actions: { maybeEnqueueFontStyle },\n    } = useFont();\n\n    // Update the true global properties of the current element\n    // This now only happens on unmount\n    const { updateElementById, deleteSelectedElements } = useStory((state) => ({\n      updateElementById: state.actions.updateElementById,\n      deleteSelectedElements: state.actions.deleteSelectedElements,\n    }));\n    const { isTrimMode, resource, setVideoNode } = useVideoTrim(\n      ({ state: { isTrimMode, videoData }, actions: { setVideoNode } }) => ({\n        isTrimMode,\n        setVideoNode,\n        resource: videoData?.resource,\n      })\n    );\n\n    // Needed for elements that can scale in edit mode.\n    const [localProperties, setLocalProperties] = useState(null);\n\n    const { Edit } = getDefinitionForType(type);\n    const elementWithLocal = localProperties\n      ? { ...element, ...localProperties }\n      : element;\n    // In case of text edit mode, we include the border to the selection, so get the box with border.\n    const isText = 'text' === type;\n    const editBox = isText\n      ? getBoxWithBorder(elementWithLocal)\n      : getBox(elementWithLocal);\n\n    return (\n      <Wrapper aria-labelledby={`layer-${id}`} {...editBox} ref={ref}>\n        <Edit\n          element={elementWithLocal}\n          box={editBox}\n          editWrapper={editWrapper}\n          onResize={onResize}\n          setLocalProperties={setLocalProperties}\n          getProxiedUrl={getProxiedUrl}\n          isRTL={isRTL}\n          topOffset={topOffset}\n          isTrimMode={isTrimMode}\n          resource={resource}\n          setVideoNode={setVideoNode}\n          updateElementById={updateElementById}\n          deleteSelectedElements={deleteSelectedElements}\n          maybeEnqueueFontStyle={maybeEnqueueFontStyle}\n          zIndexCanvas={Z_INDEX_CANVAS}\n          scaleMin={BG_MIN_SCALE}\n          scaleMax={BG_MAX_SCALE}\n        />\n      </Wrapper>\n    );\n  })\n);\n\nEditElement.propTypes = {\n  element: PropTypes.object.isRequired,\n  editWrapper: PropTypes.object,\n  onResize: PropTypes.func,\n};\n\nexport default EditElement;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  memo,\n  useEffect,\n  useRef,\n  useCallback,\n  useState,\n} from '@googleforcreators/react';\nimport { _x, __ } from '@googleforcreators/i18n';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\nimport { withOverlay } from '@googleforcreators/moveable';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../propTypes';\nimport { useStory, useCanvas } from '../../app';\nimport { Z_INDEX_EDIT_LAYER } from '../../constants/zIndex';\nimport useVideoTrim from '../videoTrim/useVideoTrim';\nimport VideoTrimmer from '../videoTrim/videoTrimmer';\nimport EditElement from './editElement';\nimport { Layer, PageArea, FooterArea } from './layout';\nimport useFocusCanvas from './useFocusCanvas';\nimport SingleSelectionMoveable from './singleSelectionMoveable';\n\nconst LayerWithGrayout = withOverlay(styled(Layer)`\n  background-color: ${({ grayout, theme }) =>\n    grayout ? theme.colors.opacity.overlayDark : 'transparent'};\n`);\n\nconst EditPageArea = withOverlay(PageArea);\n\nfunction EditLayer() {\n  const { currentPage } = useStory((state) => ({\n    currentPage: state.state.currentPage,\n  }));\n\n  const { editingElement: editingElementId, showOverflow = true } = useCanvas(\n    ({\n      state: { editingElement, editingElementState: { showOverflow } = {} },\n    }) => ({\n      editingElement,\n      showOverflow,\n    })\n  );\n\n  const editingElement =\n    editingElementId &&\n    currentPage &&\n    currentPage.elements.find((element) => element.id === editingElementId);\n\n  if (!editingElement) {\n    return null;\n  }\n\n  return (\n    <EditLayerForElement element={editingElement} showOverflow={showOverflow} />\n  );\n}\n\nfunction EditLayerForElement({ element, showOverflow }) {\n  const ref = useRef(null);\n  const pageAreaRef = useRef(null);\n  const { editModeGrayout } = getDefinitionForType(element.type);\n  const { isTrimMode } = useVideoTrim(({ state: { isTrimMode } }) => ({\n    isTrimMode,\n  }));\n\n  const { clearEditing, onMoveableMount } = useCanvas((state) => ({\n    clearEditing: state.actions.clearEditing,\n    onMoveableMount: state.state.onMoveableMount,\n  }));\n\n  const focusCanvas = useFocusCanvas();\n\n  const [editWrapper, setEditWrapper] = useState(null);\n\n  useKeyDownEffect(ref, { key: 'esc', editable: true }, () => clearEditing(), [\n    clearEditing,\n  ]);\n\n  // Unmount effect to restore focus, but do not force it, in case the\n  // design panel is active.\n  useEffect(() => {\n    return () => focusCanvas(/* force */ false);\n  }, [focusCanvas]);\n\n  const moveableRef = useRef(null);\n  const setRef = useCallback(\n    (newMoveable) => {\n      moveableRef.current = newMoveable;\n      onMoveableMount?.(newMoveable);\n    },\n    [onMoveableMount]\n  );\n\n  const onResize = useCallback(() => {\n    // Update moveable when resizing.\n    if (moveableRef.current) {\n      moveableRef.current.updateRect();\n    }\n  }, []);\n\n  const { hasEditModeMoveable } = getDefinitionForType(element.type);\n\n  return (\n    <LayerWithGrayout\n      ref={ref}\n      aria-label={_x('Edit layer', 'compound noun', 'web-stories')}\n      data-testid=\"editLayer\"\n      grayout={editModeGrayout}\n      zIndex={Z_INDEX_EDIT_LAYER}\n      onPointerDown={(evt) => {\n        if (evt.target === ref.current || evt.target === pageAreaRef.current) {\n          clearEditing();\n        }\n      }}\n    >\n      <EditPageArea\n        ref={pageAreaRef}\n        fullBleedContainerLabel={__(\n          'Fullbleed area (Edit layer)',\n          'web-stories'\n        )}\n        isControlled\n        showOverflow={showOverflow}\n        overflow={showOverflow ? 'visible' : 'hidden'}\n      >\n        <EditElement\n          editWrapper={hasEditModeMoveable && editWrapper}\n          onResize={onResize}\n          element={element}\n          ref={setEditWrapper}\n        />\n      </EditPageArea>\n      {hasEditModeMoveable && editWrapper && (\n        <SingleSelectionMoveable\n          selectedElement={element}\n          targetEl={editWrapper}\n          isEditMode\n          ref={setRef}\n        />\n      )}\n      {isTrimMode && (\n        <FooterArea showOverflow>\n          <VideoTrimmer />\n        </FooterArea>\n      )}\n    </LayerWithGrayout>\n  );\n}\n\nEditLayerForElement.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n  showOverflow: PropTypes.bool.isRequired,\n};\n\nexport default memo(EditLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst FOCUS_GROUPS = {\n  EDIT_ELEMENT: 'EDIT_ELEMENT',\n  ELEMENT_SELECTION: 'ELEMENT_SELECTION',\n};\n\nexport default FOCUS_GROUPS;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/context.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext(null);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport Provider from './provider';\nimport useFocusGroupRef from './useFocusGroupRef';\nimport useEditLayerFocusManager from './useEditLayerFocusManager';\nimport FOCUS_GROUPS from './constants';\n\nexport {\n  Provider as default,\n  useFocusGroupRef,\n  FOCUS_GROUPS,\n  useEditLayerFocusManager,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/keyBindings.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\nfunction wrapIndex(i, length) {\n  return ((i % length) + length) % length;\n}\n\nfunction createNavigateFocusGroup(uuid, focusGroup) {\n  function navigateFocusGroup(step) {\n    if (!focusGroup) {\n      return;\n    }\n\n    const currentIndex = focusGroup.findIndex(\n      (nodeTuple) => nodeTuple[0] === uuid\n    );\n    if (currentIndex === -1) {\n      return;\n    }\n\n    const nextIndex = wrapIndex(currentIndex + step, focusGroup.length);\n    const [, node] = focusGroup[nextIndex];\n    node?.focus();\n  }\n\n  return navigateFocusGroup;\n}\n\nfunction KeyBindings({ uuid, node, focusGroup, exitFocusGroup }) {\n  const traverseFocusGroup = useCallback(\n    (e) => {\n      e.preventDefault();\n\n      const navigateFocusGroup = createNavigateFocusGroup(uuid, focusGroup);\n\n      if (e.shiftKey) {\n        navigateFocusGroup(-1);\n        return;\n      }\n\n      navigateFocusGroup(1);\n    },\n    [focusGroup, uuid]\n  );\n\n  const handleEsc = useCallback(\n    (e) => {\n      e.preventDefault();\n      exitFocusGroup?.();\n    },\n    [exitFocusGroup]\n  );\n\n  useKeyDownEffect(\n    node,\n    { key: ['tab'], allowDefault: true, editable: true, shift: true },\n    traverseFocusGroup,\n    [traverseFocusGroup]\n  );\n\n  useKeyDownEffect(\n    node,\n    { key: ['esc'], allowDefault: true, editable: true },\n    handleEsc,\n    [handleEsc]\n  );\n\n  return null;\n}\n\nKeyBindings.propTypes = {\n  uuid: PropTypes.string.isRequired,\n  node:\n    typeof Element !== 'undefined'\n      ? PropTypes.instanceOf(Element).isRequired\n      : PropTypes.any.isRequired,\n  focusGroup: PropTypes.array.isRequired,\n  exitFocusGroup: PropTypes.func,\n};\n\nexport default KeyBindings;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/provider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReduction, useCallback, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport reduction, { INITIAL_STATE } from './reduction';\nimport KeyBindings from './keyBindings';\n\nfunction EditLayerFocusManager({ children }) {\n  const [state, actions] = useReduction(INITIAL_STATE, reduction);\n\n  const stateRef = useRef(state);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  stateRef.current = state;\n\n  const enterFocusGroup = useCallback(\n    ({ groupId }) => {\n      // grab the first node in the focus group & focus it\n      const nodeTuple = stateRef.current.focusGroups?.[groupId]?.[0];\n      if (nodeTuple) {\n        const [, node] = nodeTuple;\n        node.focus();\n      }\n    },\n    [stateRef]\n  );\n\n  const focusGroups = Object.entries(state.focusGroups);\n  const focusGroupCleanupCallbacks = state.cleanupCallbacks;\n\n  return (\n    <Context.Provider\n      value={{\n        enterFocusGroup,\n        setFocusGroupCleanup: actions.setFocusGroupCleanup,\n        actions,\n      }}\n    >\n      {focusGroups.map(([groupId, focusGroup]) =>\n        focusGroup.map(\n          ([uuid, node]) =>\n            node && (\n              <KeyBindings\n                key={uuid}\n                uuid={uuid}\n                node={node}\n                focusGroup={focusGroup}\n                exitFocusGroup={focusGroupCleanupCallbacks[groupId]}\n              />\n            )\n        )\n      )}\n      {children}\n    </Context.Provider>\n  );\n}\n\nEditLayerFocusManager.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n\nexport default EditLayerFocusManager;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/reduction.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst INITIAL_STATE = {\n  cleanup: null,\n  focusGroups: {},\n  cleanupCallbacks: {},\n};\n\nconst reduction = {\n  addNodeToGroup: (state, action) => {\n    // parse payload\n    const { groupId, nodeTuple } = action.payload;\n\n    // add or update node in the nodeGroup\n    const nodeGroup = state.focusGroups[groupId] || [];\n    let newNodeGroup = [];\n    const index = nodeGroup.findIndex(\n      (_nodeTuple) => _nodeTuple[0] === nodeTuple[0]\n    );\n    if (index === -1) {\n      newNodeGroup = [...nodeGroup, nodeTuple];\n    } else {\n      newNodeGroup = [\n        ...nodeGroup.slice(0, index),\n        nodeTuple,\n        ...nodeGroup.slice(0, index + 1),\n      ];\n    }\n\n    // update state\n    return {\n      ...state,\n      focusGroups: {\n        ...state.focusGroups,\n        [groupId]: newNodeGroup,\n      },\n    };\n  },\n\n  removeNodeFromGroup: (state, action) => {\n    // parse payload\n    const { groupId, nodeTuple } = action.payload;\n\n    // remove nodeTuple from group if it exists\n    const nodeGroup = state.focusGroups[groupId] || [];\n    const newNodeGroup = nodeGroup.filter(\n      (_nodeTuple) => _nodeTuple[0] !== nodeTuple[0]\n    );\n\n    // update state\n    return {\n      ...state,\n      focusGroups: {\n        ...state.focusGroups,\n        [groupId]: newNodeGroup,\n      },\n    };\n  },\n\n  setFocusGroupCleanup: (state, action) => {\n    const { groupId, cleanup } = action.payload;\n    return {\n      ...state,\n      activeGroupKey: groupId,\n      cleanupCallbacks: {\n        ...state.cleanupCallbacks,\n        [groupId]: cleanup,\n      },\n    };\n  },\n};\n\nexport { reduction as default, INITIAL_STATE };\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/test/EditLayerFocusManager.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\nimport { render, fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport EditLayerFocusManager, {\n  useFocusGroupRef,\n  useEditLayerFocusManager,\n} from '..';\n\ndescribe('EditLayerFocusManager', () => {\n  const FOCUS_GROUP_ID = 'test-group';\n\n  const KEYS = {\n    esc: {\n      key: 'Escape',\n      which: 27,\n    },\n    tab: {\n      key: 'Tab',\n      which: 9,\n    },\n    shitTab: {\n      key: 'Tab',\n      which: 9,\n      shiftKey: true,\n    },\n  };\n\n  function MockFocusGroupButton({ mockFocus, ...props }) {\n    const focusGroupRef = useFocusGroupRef(FOCUS_GROUP_ID);\n    return <button ref={focusGroupRef} onClick={() => {}} {...props} />;\n  }\n\n  function EnterFocusGroupTrigger({ cleanup = () => {}, ...props }) {\n    const { enterFocusGroup, setFocusGroupCleanup } =\n      useEditLayerFocusManager();\n\n    useEffect(() => {\n      setFocusGroupCleanup({\n        groupId: FOCUS_GROUP_ID,\n        cleanup,\n      });\n    }, [cleanup, setFocusGroupCleanup]);\n\n    return (\n      <button\n        onClick={() => {\n          enterFocusGroup({\n            groupId: FOCUS_GROUP_ID,\n          });\n        }}\n        {...props}\n      />\n    );\n  }\n\n  function pressKey(key) {\n    // eslint-disable-next-line testing-library/no-node-access\n    fireEvent.keyDown(document.activeElement, key);\n  }\n\n  function blurActiveElement() {\n    // eslint-disable-next-line testing-library/no-node-access\n    document.activeElement.blur();\n  }\n\n  let focusGroupProps, TestFocusGroup, focusGroupTrigger;\n\n  beforeEach(() => {\n    focusGroupTrigger = {\n      text: 'trigger',\n      cleanup: jest.fn(blurActiveElement),\n    };\n\n    focusGroupProps = Array.from({ length: 3 }, (_, i) => ({\n      text: `button--${i}`,\n      focus: jest.fn(),\n    }));\n\n    function FocusGroup() {\n      return (\n        <EditLayerFocusManager>\n          {focusGroupProps.map((focusElProps, i) => (\n            <div key={focusElProps.text}>\n              <button>{`non focus group button ${i}`}</button>\n              <MockFocusGroupButton tabIndex={-1} onFocus={focusElProps.focus}>\n                {focusElProps.text}\n              </MockFocusGroupButton>\n            </div>\n          ))}\n          <EnterFocusGroupTrigger cleanup={focusGroupTrigger.cleanup}>\n            {focusGroupTrigger.text}\n          </EnterFocusGroupTrigger>\n        </EditLayerFocusManager>\n      );\n    }\n\n    TestFocusGroup = FocusGroup;\n  });\n\n  it('focuses first element in focus group with enterFocusGroup', () => {\n    const { unmount } = render(<TestFocusGroup />);\n\n    // enter focus group\n    fireEvent.click(screen.getByText(focusGroupTrigger.text));\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    unmount();\n  });\n\n  it('[tab] focuses elements cyclicly', () => {\n    const { unmount } = render(<TestFocusGroup />);\n\n    // enter focus group\n    fireEvent.click(screen.getByText(focusGroupTrigger.text));\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    // [tab] to next in group\n    pressKey(KEYS.tab);\n    expect(screen.getByText(focusGroupProps[1].text)).toHaveFocus();\n\n    // [tab] to next in group\n    pressKey(KEYS.tab);\n    expect(screen.getByText(focusGroupProps[2].text)).toHaveFocus();\n\n    // [tab] to next in group should wrap\n    pressKey(KEYS.tab);\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    unmount();\n  });\n\n  it('[tab+shift] focuses elements cyclicly', () => {\n    const { unmount } = render(<TestFocusGroup />);\n\n    // enter focus group\n    fireEvent.click(screen.getByText(focusGroupTrigger.text));\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    // [tab+shift] should wrap to last element\n    pressKey(KEYS.shitTab);\n    expect(screen.getByText(focusGroupProps[2].text)).toHaveFocus();\n\n    // [tab+shift] to prev in group\n    pressKey(KEYS.shitTab);\n    expect(screen.getByText(focusGroupProps[1].text)).toHaveFocus();\n\n    // [tab+shift] to original element in group\n    pressKey(KEYS.shitTab);\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    unmount();\n  });\n\n  it('[esc] exits focus group & calls cleanup', () => {\n    const { unmount } = render(<TestFocusGroup />);\n\n    // enter focus group\n    fireEvent.click(screen.getByText(focusGroupTrigger.text));\n    expect(screen.getByText(focusGroupProps[0].text)).toHaveFocus();\n\n    // [esc] should exit focus group\n    pressKey(KEYS.esc);\n    expect(focusGroupTrigger.cleanup).toHaveBeenCalledOnce();\n    focusGroupProps.forEach((focusGroupEl) => {\n      const node = screen.getByText(focusGroupEl.text);\n      expect(node).not.toHaveFocus();\n    });\n\n    // focus group elements should not be in tab flow\n    for (let i = 0; i < 10; i++) {\n      pressKey(KEYS.tab);\n      focusGroupProps.forEach((focusGroupEl) => {\n        const node = screen.getByText(focusGroupEl.text);\n        expect(node).not.toHaveFocus();\n      });\n    }\n\n    unmount();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/useEditLayerFocusManager.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useEditLayerFocusManager(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useEditLayerFocusManager;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/editLayerFocusManager/useFocusGroupRef.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useInitializedValue,\n  useContextSelector,\n} from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\n/**\n * Takes a group identifier and returns a callback ref which puts the node in the specified group.\n * The returned callback ref should only be applied to one jsx element at a time.\n *\n * **Sample Usage**\n * ```js\n * function SomeComponentWithButtonInFocusGroup(){\n *   const ref = useFocusGroupRef('focus-group-1');\n *   return (\n *     <div>\n *       <p>some component</p>\n *       <button ref={ref}>Click Me!</button>\n *      </div>\n *   );\n * }\n * ```\n *\n * @param {string} groupId - identifier to indicate group by which to associate node.\n * @return {Function} callback ref that places node in specified focus group.\n */\nfunction useFocusGroupRef(groupId) {\n  const actions = useContextSelector(Context, (value) => value.actions);\n  const uuid = useInitializedValue(uuidv4);\n  return useCallback(\n    (node) => {\n      // When the component unmounts, remove it from the\n      // focus group.\n      if (node === null) {\n        actions.removeNodeFromGroup({\n          groupId,\n          nodeTuple: [uuid, node],\n        });\n        return;\n      }\n      // Add or update node in the focus group.\n      actions.addNodeToGroup({\n        groupId,\n        nodeTuple: [uuid, node],\n      });\n    },\n    [actions, groupId, uuid]\n  );\n}\n\nexport default useFocusGroupRef;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/emptyStateLayer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  ButtonType,\n  ButtonVariant,\n  Button,\n  Icons,\n  Text,\n  TextSize,\n  theme,\n  lightMode,\n  CONTEXT_MENU_MIN_WIDTH,\n} from '@googleforcreators/design-system';\nimport { useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useConfig, useRightClickMenu } from '../../app';\nimport useStory from '../../app/story/useStory';\nimport isEmptyStory from '../../app/story/utils/isEmptyStory';\nimport { Layer, PageArea } from './layout';\n\nconst DisplayPageArea = styled(PageArea)`\n  position: absolute;\n  z-index: 1;\n`;\n\nconst EmptyStateMessage = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  padding: 20px;\n  text-align: center;\n  svg {\n    pointer-events: none;\n  }\n  p {\n    margin-top: 14px;\n  }\n`;\n\nconst StyledButton = styled(Button)`\n  pointer-events: initial;\n`;\n\nfunction EmptyStateLayer() {\n  const { isRTL } = useConfig();\n  const { isMenuOpen, onOpenMenu } = useRightClickMenu(\n    ({ isMenuOpen, onOpenMenu }) => ({\n      isMenuOpen,\n      onOpenMenu,\n    })\n  );\n  const { pages } = useStory(({ state: { pages } }) => ({\n    pages,\n  }));\n  const { isAnythingTransforming } = useTransform((state) => ({\n    isAnythingTransforming: state.state.isAnythingTransforming,\n  }));\n\n  if (!isEmptyStory(pages) || isAnythingTransforming) {\n    return null;\n  }\n\n  const onButtonClick = (e) => {\n    const bb = e.target.getBoundingClientRect();\n    e.clientX =\n      bb.left - ((isRTL ? -1 : 1) * CONTEXT_MENU_MIN_WIDTH) / 2 + bb.width / 2;\n    // Hardcoded because it's not trivial to get the menu height here.\n    const EMPTY_STATE_CONTEXT_MENU_HEIGHT = 132;\n    e.clientY = bb.top - EMPTY_STATE_CONTEXT_MENU_HEIGHT + bb.height;\n    onOpenMenu(e);\n  };\n\n  return (\n    <Layer\n      onContextMenu={onOpenMenu}\n      pointerEvents=\"none\"\n      aria-label={__('Empty state layer', 'web-stories')}\n    >\n      <DisplayPageArea withSafezone={false}>\n        <EmptyStateMessage>\n          <StyledButton\n            type={ButtonType.Secondary}\n            variant={ButtonVariant.Circle}\n            onClick={onButtonClick}\n            aria-haspopup=\"true\"\n            aria-label={__('Add content', 'web-stories')}\n            aria-describedby=\"emptystate-message\"\n            aria-expanded={isMenuOpen}\n          >\n            <Icons.Media />\n          </StyledButton>\n          <ThemeProvider theme={{ ...theme, colors: lightMode }}>\n            <Text.Paragraph id=\"emptystate-message\" size={TextSize.Small}>\n              {__(\n                'Add an image, video or template to get started',\n                'web-stories'\n              )}\n            </Text.Paragraph>\n          </ThemeProvider>\n        </EmptyStateMessage>\n      </DisplayPageArea>\n    </Layer>\n  );\n}\n\nexport default EmptyStateLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/extraPages.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { memo } from '@googleforcreators/react';\nimport { PAGE_RATIO } from '@googleforcreators/units';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useLayout } from '../../app';\nimport PagePreview from '../footer/pagepreview';\n\nconst GAP = 32;\n\nconst ExtraPageWrapper = styled.div`\n  display: flex;\n  overflow: hidden;\n  justify-content: ${({ isPrevious }) =>\n    isPrevious ? 'flex-end' : 'flex-start'};\n  align-items: center;\n  height: 100%;\n`;\nconst ExtraPageList = styled.ol`\n  display: flex;\n  flex-direction: ${({ isPrevious }) => (isPrevious ? 'row-reverse' : 'row')};\n  width: ${({ listWidth }) => listWidth}px;\n  margin: 0;\n  padding: 0 ${GAP}px;\n  gap: ${GAP}px;\n`;\nconst ExtraPage = styled.li`\n  display: block;\n  width: ${({ extraPageWidth }) => extraPageWidth - GAP}px;\n  height: 100%;\n  border-radius: 4px;\n  background-color: white;\n\n  /* First extra page is at 60% opacity, then 45, 30, and 15 */\n  opacity: ${({ $distance }) => 0.6 - $distance * 0.15};\n  transition: opacity 0.2s ease;\n  &:hover {\n    opacity: 1;\n  }\n\n  ${({ $inert }) => $inert && 'pointer-events: none;'}\n`;\nconst ExtraPagePreview = styled(PagePreview)`\n  cursor: pointer;\n`;\n\nfunction range(from, to) {\n  return from < to ? Array.from(Array(to - from)).map((k, v) => v + from) : [];\n}\n\nfunction getPagesToShow({\n  isPrevious,\n  hasExtraPages,\n  currentPageIndex,\n  extraPageCount,\n  pageCount,\n}) {\n  if (!hasExtraPages) {\n    return [];\n  }\n  // Showing pages before the current one\n  if (isPrevious) {\n    const from = Math.max(0, currentPageIndex - extraPageCount);\n    const to = currentPageIndex;\n    return range(from, to).reverse();\n  }\n  // Showing pages after the current one\n  const from = currentPageIndex + 1;\n  const to = Math.min(pageCount, currentPageIndex + extraPageCount + 2);\n  return range(from, to);\n}\n\nfunction ExtraPages({ isPrevious = false }) {\n  const { currentPageIndex, pages, setCurrentPage } = useStory(\n    ({ state: { pages, currentPageIndex }, actions: { setCurrentPage } }) => ({\n      currentPageIndex,\n      pages,\n      setCurrentPage,\n    })\n  );\n  const { hasExtraPages, extraPageWidth, extraPageCount } = useLayout(\n    ({ state: { hasExtraPages, extraPageWidth, extraPageCount } }) => ({\n      hasExtraPages,\n      extraPageWidth,\n      extraPageCount,\n    })\n  );\n  const isAnythingTransforming = useTransform(\n    ({ state: { isAnythingTransforming } }) => isAnythingTransforming\n  );\n\n  const pageCount = pages?.length;\n  if (!pageCount) {\n    return null;\n  }\n  const pagesToShow = getPagesToShow({\n    isPrevious,\n    hasExtraPages,\n    currentPageIndex,\n    extraPageCount,\n    pageCount,\n  });\n  if (pagesToShow.length === 0) {\n    return null;\n  }\n  const listWidth = pagesToShow.length * extraPageWidth;\n  const extraPageHeight = (extraPageWidth - GAP) / PAGE_RATIO;\n\n  const clickPage = (pageId) => () => setCurrentPage({ pageId });\n\n  return (\n    <ExtraPageWrapper isPrevious={isPrevious}>\n      <ExtraPageList\n        isPrevious={isPrevious}\n        listWidth={listWidth}\n        extraPageHeight={extraPageHeight}\n      >\n        {pagesToShow.map((pageNum, index) => (\n          <ExtraPage\n            key={pageNum}\n            extraPageWidth={extraPageWidth}\n            $inert={isAnythingTransforming}\n            $distance={index}\n          >\n            <ExtraPagePreview\n              page={pages[pageNum]}\n              onClick={clickPage(pages[pageNum].id)}\n              aria-label={sprintf(\n                /* translators: %s: page number. */\n                __('Go to page %s', 'web-stories'),\n                pageNum + 1\n              )}\n              width={extraPageWidth - GAP}\n            />\n          </ExtraPage>\n        ))}\n      </ExtraPageList>\n    </ExtraPageWrapper>\n  );\n}\n\nExtraPages.propTypes = {\n  isPrevious: PropTypes.bool,\n};\n\nexport default memo(ExtraPages);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/eyedropperLayer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useFocusOut } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { rgba, readableColor } from 'polished';\nimport { FULLBLEED_RATIO } from '@googleforcreators/units';\nimport {\n  useGlobalKeyDownEffect,\n  CircularProgress,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useLayout } from '../../app';\nimport useEyeDropperApi from '../eyedropper/useEyeDropperApi';\nimport { Layer, PageArea } from './layout';\nimport getColorFromPixelData from './utils/getColorFromPixelData';\n\nconst MAGNIFIER_SIZE = 200;\nconst MAGNIFIER_PIXELS = 7;\nconst MAGNIFIER_RECT_SIZE = MAGNIFIER_SIZE / MAGNIFIER_PIXELS;\n\nconst EyedropperBackground = styled(Layer)`\n  background: ${({ theme }) => theme.colors.opacity.black64};\n  cursor: not-allowed;\n  z-index: 2;\n`;\n\nconst DisplayPageArea = styled(PageArea)`\n  position: absolute;\n`;\n\nconst EyedropperCanvas = styled.div`\n  background: transparent;\n  border-radius: 5px;\n  position: absolute;\n  z-index: 2;\n  transform: translateZ(0);\n  top: 0;\n  left: 0;\n  bottom: 0;\n  right: 0;\n  cursor: default;\n`;\n\nconst ColorInfo = styled.div`\n  text-transform: uppercase;\n  margin-top: 30px;\n  padding: 9px;\n  min-width: 102px;\n  text-align: center;\n`;\n\nconst Circle = styled.div`\n  transform: translateY(20px);\n  background: ${({ theme }) => theme.colors.bg.primary};\n  border: 2px solid black;\n  border-radius: 50%;\n  overflow: hidden;\n  width: ${MAGNIFIER_SIZE - 2}px;\n  height: ${MAGNIFIER_SIZE}px;\n`;\n\n// Initially hide the magnifier.\nconst Magnifier = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  transform: translateY(-2000px);\n  pointer-events: none;\n`;\n\nconst Center = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  z-index: 3;\n  background: ${({ theme }) => theme.colors.opacity.black64};\n  cursor: not-allowed;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst CanvasImage = styled.img`\n  width: 100%;\n`;\n\nfunction EyedropperLayer() {\n  const {\n    fullbleedContainer,\n    isEyedropperActive,\n    eyedropperCallback,\n    eyedropperImg,\n    eyedropperPixelData,\n    setIsEyedropperActive,\n    setEyedropperImg,\n    setEyedropperPixelData,\n  } = useCanvas(\n    ({\n      state: {\n        fullbleedContainer,\n        isEyedropperActive,\n        eyedropperCallback,\n        eyedropperImg,\n        eyedropperPixelData,\n      },\n      actions: {\n        setIsEyedropperActive,\n        setEyedropperImg,\n        setEyedropperPixelData,\n      },\n    }) => ({\n      fullbleedContainer,\n      isEyedropperActive,\n      eyedropperCallback,\n      eyedropperImg,\n      eyedropperPixelData,\n      setIsEyedropperActive,\n      setEyedropperImg,\n      setEyedropperPixelData,\n    })\n  );\n\n  const { isEyeDropperApiSupported } = useEyeDropperApi({});\n\n  const { pageWidth } = useLayout(({ state: { pageWidth } }) => ({\n    pageWidth,\n  }));\n\n  const fullHeight = pageWidth / FULLBLEED_RATIO;\n  const img = eyedropperImg;\n  const imgRef = useRef();\n  const magnifierRef = useRef();\n  const magnifierInfoRef = useRef();\n  const magnifierColorRef = useRef();\n  const eyedropperCanvasRef = useRef();\n\n  const closeEyedropper = () => {\n    setIsEyedropperActive(false);\n    setEyedropperImg(null);\n    setEyedropperPixelData(null);\n  };\n\n  useFocusOut(eyedropperCanvasRef, closeEyedropper, [isEyedropperActive, img]);\n\n  useGlobalKeyDownEffect('esc', closeEyedropper);\n\n  if (isEyeDropperApiSupported) {\n    return null;\n  }\n\n  if (isEyedropperActive && !img) {\n    return (\n      <>\n        {/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions -- No keyboard navigation for Eyedropper. */}\n        <Center onClick={closeEyedropper}>\n          <CircularProgress />\n        </Center>\n      </>\n    );\n  }\n  if (!isEyedropperActive || !img) {\n    return null;\n  }\n\n  const magnify = (x, y) => {\n    const canvas = magnifierRef.current;\n    if (canvas) {\n      const ctx = canvas.getContext('2d');\n\n      ctx.imageSmoothingEnabled = false;\n      ctx.mozImageSmoothingEnabled = false;\n      ctx.webkitImageSmoothingEnabled = false;\n      ctx.msImageSmoothingEnabled = false;\n\n      // Draw enlarged cropped image.\n      ctx.clearRect(0, 0, MAGNIFIER_SIZE, MAGNIFIER_SIZE);\n      ctx.drawImage(\n        imgRef.current,\n        Math.round(x - MAGNIFIER_PIXELS / 2),\n        Math.round(y - MAGNIFIER_PIXELS / 2),\n        MAGNIFIER_PIXELS,\n        MAGNIFIER_PIXELS,\n        0,\n        0,\n        MAGNIFIER_SIZE,\n        MAGNIFIER_SIZE\n      );\n\n      // Draw center square for better aiming.\n      ctx.beginPath();\n      ctx.rect(\n        Math.round(MAGNIFIER_SIZE / 2) - MAGNIFIER_RECT_SIZE / 2,\n        Math.round(MAGNIFIER_SIZE / 2) - MAGNIFIER_RECT_SIZE / 2,\n        MAGNIFIER_RECT_SIZE,\n        MAGNIFIER_RECT_SIZE\n      );\n      ctx.stroke();\n    }\n  };\n\n  const onMouseMove = (e) => {\n    const { left, top, width, height } =\n      fullbleedContainer.getBoundingClientRect();\n    const x = (e.clientX - left) * (pageWidth / width);\n    const y = (e.clientY - top) * (fullHeight / height);\n\n    if (x < 0 || y < 0 || x > width || y > height) {\n      magnifierInfoRef.current.style.display = 'none';\n      return;\n    } else {\n      magnifierInfoRef.current.style.display = 'block';\n    }\n\n    // Move magnifier canvas.\n    magnifierInfoRef.current.style.transform = `translate(${\n      x - MAGNIFIER_SIZE / 2\n    }px, ${y}px)`;\n\n    // Redraw magnifier canvas.\n    magnify(x, y);\n\n    // Get and print pixel color.\n    const rgbaObject = getColorFromPixelData(eyedropperPixelData, x, y, width);\n    const { r, g, b, a } = rgbaObject;\n    const hex = rgba(r, g, b, a);\n    magnifierColorRef.current.style.background = `rgba(${r},${g},${b},${a})`;\n    magnifierColorRef.current.style.color = readableColor(\n      hex,\n      '#333',\n      '#EDEDED',\n      false\n    );\n    magnifierColorRef.current.innerText = hex;\n  };\n\n  const onClick = (e) => {\n    const { left, top, width, height } =\n      fullbleedContainer.getBoundingClientRect();\n    const x = (e.clientX - left) * (pageWidth / width);\n    const y = (e.clientY - top) * (fullHeight / height);\n\n    const rgbaObject = getColorFromPixelData(\n      eyedropperPixelData,\n      x,\n      y,\n      pageWidth\n    );\n    eyedropperCallback(rgbaObject);\n  };\n\n  return (\n    <EyedropperBackground\n      data-testid=\"eyedropperLayer\"\n      onMouseMove={onMouseMove}\n    >\n      {/* Remove the safe zone so we don't have to move the canvas image up (we have fullbleed image). */}\n      <DisplayPageArea withSafezone={false} showOverflow>\n        {/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions -- No pixel-by-pixel keyboard navigation. */}\n        <EyedropperCanvas ref={eyedropperCanvasRef} onClick={onClick}>\n          <CanvasImage ref={imgRef} src={img} alt=\"\" />\n          <Magnifier ref={magnifierInfoRef}>\n            <Circle>\n              <canvas\n                ref={magnifierRef}\n                width={MAGNIFIER_SIZE}\n                height={MAGNIFIER_SIZE}\n              />\n            </Circle>\n            <ColorInfo ref={magnifierColorRef} />\n          </Magnifier>\n        </EyedropperCanvas>\n      </DisplayPageArea>\n    </EyedropperBackground>\n  );\n}\n\nexport default EyedropperLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/frameElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useLayoutEffect,\n  useRef,\n  useState,\n  memo,\n  useCombinedRefs,\n  useEffect,\n} from '@googleforcreators/react';\nimport { useUnits } from '@googleforcreators/units';\nimport { useTransformHandler } from '@googleforcreators/transform';\nimport PropTypes from 'prop-types';\nimport {\n  getDefinitionForType,\n  getLayerName,\n} from '@googleforcreators/elements';\nimport {\n  elementWithPosition,\n  elementWithSize,\n  elementWithRotation,\n} from '@googleforcreators/element-library';\nimport { FrameWithMask as WithMask } from '@googleforcreators/masks';\nimport {\n  useKeyDownEffect,\n  useLiveRegion,\n  prettifyShortcut,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  useStory,\n  useTransform,\n  useCanvas,\n  useConfig,\n  useDropTargets,\n} from '../../app';\nimport WithLink from '../elementLink/frame';\nimport WithProductPill from '../shopping/frame';\nimport useDoubleClick from '../../utils/useDoubleClick';\nimport usePerformanceTracking from '../../utils/usePerformanceTracking';\nimport { TRACKING_EVENTS } from '../../constants';\nimport { noop } from '../../utils/noop';\nimport {\n  FOCUS_GROUPS,\n  useFocusGroupRef,\n  useEditLayerFocusManager,\n} from './editLayerFocusManager';\n\n// @todo: should the frame borders follow clip lines?\n\n// Pointer events are disabled in the display mode to ensure that selection\n// can be limited to the mask.\nconst Wrapper = styled.div`\n  ${elementWithPosition}\n  ${elementWithSize}\n  ${elementWithRotation}\n  outline: 1px solid transparent;\n  transition: outline-color 0.5s;\n  &:focus,\n  &:active {\n    outline-color: ${({ theme, hasMask }) =>\n      hasMask ? 'transparent' : theme.colors.border.selection};\n  }\n  ${({ isLocked, hasMask, theme }) =>\n    !isLocked &&\n    !hasMask &&\n    `\n    &:hover {\n      outline-color: ${theme.colors.border.selection};\n    }\n  `}\n  ${({ isClickable }) => !isClickable && `pointer-events: none;`}\n`;\n\nconst EmptyFrame = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  pointer-events: none;\n`;\n\nconst FRAME_ELEMENT_MESSAGE = sprintf(\n  /* translators: %s: Ctrl+Alt+P keyboard shortcut. */\n  __(\n    'To exit the canvas area, press Escape. Press Tab to move to the next group or element. To enter floating menu, press %s.',\n    'web-stories'\n  ),\n  prettifyShortcut('ctrl+alt+p')\n);\n\nfunction FrameElement({ id }) {\n  const speak = useLiveRegion();\n  const { enterFocusGroup, setFocusGroupCleanup } = useEditLayerFocusManager(\n    ({ enterFocusGroup, setFocusGroupCleanup }) => ({\n      enterFocusGroup,\n      setFocusGroupCleanup,\n    })\n  );\n  const [isTransforming, setIsTransforming] = useState(false);\n  const focusGroupRef = useFocusGroupRef(FOCUS_GROUPS.ELEMENT_SELECTION);\n\n  const {\n    setNodeForElement,\n    handleSelectElement,\n    isEditing,\n    setEditingElement,\n    setEditingElementWithState,\n  } = useCanvas(({ state, actions }) => ({\n    setNodeForElement: actions.setNodeForElement,\n    handleSelectElement: actions.handleSelectElement,\n    isEditing: state.isEditing,\n    setEditingElement: actions.setEditingElement,\n    setEditingElementWithState: actions.setEditingElementWithState,\n  }));\n  const { isSelected, isOnlySelectedElement, isActive, isBackground, element } =\n    useStory(({ state }) => {\n      const isSelected = state.selectedElementIds.includes(id);\n      const isOnlySelectedElement =\n        isSelected && state.selectedElementIds.length === 1;\n      const isActive = isOnlySelectedElement && !isTransforming && !isEditing;\n\n      return {\n        isSelected,\n        isBackground: state.currentPage?.elements[0].id === id,\n        element: state.currentPage?.elements.find((el) => el.id === id),\n        isOnlySelectedElement,\n        isActive,\n      };\n    });\n  const { type, flip, isLocked, isHidden } = element;\n\n  // Unlocked elements are always clickable,\n  // locked elements are only clickable if selected,\n  // hidden elements are never clickable.\n  const isClickable = (!isLocked || isSelected) && !isHidden;\n\n  const { Frame, isMaskable, Controls } = getDefinitionForType(type);\n  const elementRef = useRef();\n  const combinedFocusGroupRef = useCombinedRefs(elementRef, focusGroupRef); // Only attach focus group ref to one element.\n  const [hovering, setHovering] = useState(false);\n  const { isRTL, styleConstants: { topOffset } = {} } = useConfig();\n\n  const {\n    draggingResource,\n    activeDropTargetId,\n    isDropSource,\n    registerDropTarget,\n    unregisterDropTarget,\n  } = useDropTargets(\n    ({\n      state: { draggingResource, activeDropTargetId },\n      actions: { isDropSource, registerDropTarget, unregisterDropTarget },\n    }) => ({\n      draggingResource,\n      activeDropTargetId,\n      isDropSource,\n      registerDropTarget,\n      unregisterDropTarget,\n    })\n  );\n\n  const onPointerEnter = () => setHovering(true);\n  const onPointerLeave = () => setHovering(false);\n\n  const isAnythingTransforming = useTransform(\n    ({ state }) => !isSelected && hovering && !state.isAnythingTransforming\n  );\n  const isLinkActive = isAnythingTransforming && !isLocked;\n\n  const getBoxWithBorder = useUnits(({ actions }) => actions.getBoxWithBorder);\n\n  useLayoutEffect(() => {\n    setNodeForElement(id, elementRef.current);\n  }, [id, setNodeForElement]);\n  const boxWithBorder = getBoxWithBorder(element);\n\n  useTransformHandler(id, (transform) => {\n    const target = elementRef.current;\n    if (transform?.dropTargets?.hover !== undefined) {\n      target.style.opacity = transform.dropTargets.hover ? 0 : 1;\n    }\n    setIsTransforming(transform !== null);\n  });\n\n  // Media needs separate handler for double click.\n  const { isMedia } = getDefinitionForType(type);\n  const handleMediaDoubleClick = useCallback(\n    (evt) => {\n      if (!isSelected) {\n        handleSelectElement(id, evt);\n      }\n      setEditingElement(id);\n    },\n    [id, setEditingElement, handleSelectElement, isSelected]\n  );\n  const handleMediaClick = useDoubleClick(noop, handleMediaDoubleClick);\n\n  /**\n   * Announce keyboard options on element.\n   *\n   * Using a live region because an `aria-label` would remove\n   * any labels/content that would be read from children.\n   */\n  const handleFocus = useCallback(\n    (evt) => {\n      if (!isSelected) {\n        handleSelectElement(id, evt);\n      }\n\n      // no floating menu on background, so no need to announce\n      // possible floating menu keyboard navigation commands\n      if (isBackground) {\n        return;\n      }\n      speak(FRAME_ELEMENT_MESSAGE);\n    },\n    [handleSelectElement, id, isBackground, isSelected, speak]\n  );\n\n  const { clearTransforms } = useTransform((state) => ({\n    clearTransforms: state.actions.clearTransforms,\n  }));\n\n  const handleMouseDown = useCallback(\n    (evt) => {\n      if (!isSelected) {\n        handleSelectElement(id, evt);\n        clearTransforms();\n      }\n\n      elementRef.current.focus({ preventScroll: true });\n\n      if (!isBackground) {\n        evt.stopPropagation();\n      }\n    },\n    [handleSelectElement, id, isBackground, isSelected, clearTransforms]\n  );\n\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: elementRef.current,\n    eventData: {\n      ...TRACKING_EVENTS.SELECT_ELEMENT,\n      label: element.type,\n    },\n    eventType: 'pointerdown',\n  });\n\n  useKeyDownEffect(\n    elementRef,\n    { key: ['ctrl+alt+p'] },\n    () => {\n      enterFocusGroup({\n        groupId: FOCUS_GROUPS.EDIT_ELEMENT,\n      });\n    },\n    [enterFocusGroup]\n  );\n\n  useEffect(() => {\n    if (isSelected) {\n      setFocusGroupCleanup({\n        groupId: FOCUS_GROUPS.EDIT_ELEMENT,\n        cleanup: () => elementRef.current?.focus(),\n      });\n    }\n  }, [setFocusGroupCleanup, isSelected]);\n\n  const layerName = getLayerName(element);\n  const elementLabel = element.isLocked\n    ? sprintf(\n        // translators: %s: Name of element\n        __('Locked element: %s', 'web-stories'),\n        layerName\n      )\n    : sprintf(\n        // translators: %s: Name of element\n        __('Element: %s', 'web-stories'),\n        layerName\n      );\n\n  return (\n    <WithProductPill\n      element={element}\n      active={isLinkActive}\n      anchorRef={elementRef}\n    >\n      <WithLink element={element} active={isLinkActive} anchorRef={elementRef}>\n        {Controls && (\n          <Controls\n            isTransforming={isTransforming}\n            box={boxWithBorder}\n            elementRef={elementRef}\n            element={element}\n            isRTL={isRTL}\n            topOffset={topOffset}\n            isActive={isActive}\n          />\n        )}\n        {/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events -- False positive */}\n        <Wrapper\n          ref={combinedFocusGroupRef}\n          data-element-id={id}\n          {...boxWithBorder}\n          tabIndex={-1}\n          role=\"button\"\n          aria-label={elementLabel}\n          hasMask={isMaskable}\n          isClickable={isClickable}\n          data-testid=\"frameElement\"\n          onMouseDown={handleMouseDown}\n          onFocus={handleFocus}\n          onPointerEnter={onPointerEnter}\n          onPointerLeave={onPointerLeave}\n          onClick={isMedia ? handleMediaClick(id) : null}\n        >\n          <WithMask\n            element={element}\n            fill\n            flip={flip}\n            draggingResource={draggingResource}\n            activeDropTargetId={activeDropTargetId}\n            isDropSource={isDropSource}\n            registerDropTarget={registerDropTarget}\n            unregisterDropTarget={unregisterDropTarget}\n            isSelected={isSelected}\n          >\n            {Frame ? (\n              <Frame\n                wrapperRef={elementRef}\n                element={element}\n                box={boxWithBorder}\n                isOnlySelectedElement={isOnlySelectedElement}\n                setEditingElementWithState={setEditingElementWithState}\n              />\n            ) : (\n              <EmptyFrame />\n            )}\n          </WithMask>\n        </Wrapper>\n      </WithLink>\n    </WithProductPill>\n  );\n}\n\nFrameElement.propTypes = {\n  id: PropTypes.string.isRequired,\n};\n\nexport default memo(FrameElement);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/framesLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { memo, useRef, useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { PAGE_WIDTH } from '@googleforcreators/units';\nimport { StoryAnimationState } from '@googleforcreators/animation';\nimport {\n  themeHelpers,\n  useKeyDownEffect,\n  useGlobalKeyDownEffect,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useEffect } from 'react';\nimport { DESIGN_SPACE_MARGIN, STABLE_ARRAY } from '../../constants';\nimport {\n  useStory,\n  useCanvas,\n  useLayout,\n  useTransform,\n  useRightClickMenu,\n} from '../../app';\nimport useCanvasKeys from '../../app/canvas/useCanvasKeys';\nimport {\n  Layer,\n  NavNextArea,\n  NavPrevArea,\n  PageArea,\n  PageBeforeArea,\n  PageAfterArea,\n} from './layout';\nimport ExtraPages from './extraPages';\nimport FrameElement from './frameElement';\nimport Selection from './selection';\nimport PageNav from './pagenav';\nimport {\n  FOCUS_GROUPS,\n  useEditLayerFocusManager,\n} from './editLayerFocusManager';\n\nconst FramesPageArea = styled(PageArea)`\n  pointer-events: initial;\n`;\nconst marginRatio = 100 * (DESIGN_SPACE_MARGIN / PAGE_WIDTH);\n\nconst FocusContainer = styled.div`\n  /* begin under header row */\n  grid-row: 2 / -1;\n  grid-column: 1 / -1;\n  /* show focus border by adding margin */\n  margin: 5px;\n\n  ${themeHelpers.focusableOutlineCSS};\n`;\n\nconst FOCUS_CONTAINER_MESSAGE = __(\n  'Canvas Area. To navigate into the page, press Enter.',\n  'web-stories'\n);\n\nconst FRAME_ELEMENT_MESSAGE = __(\n  'To exit the canvas area, press Escape. Press Tab to move to the next group or element.',\n  'web-stories'\n);\n\nconst DesignSpaceGuidelineBorder = styled.div`\n  border: 1px solid ${({ theme }) => theme.colors.border.negativePress};\n  left: ${marginRatio}%;\n  right: ${marginRatio}%;\n  top: 0;\n  bottom: 0;\n  position: absolute;\n  pointer-events: none;\n  z-index: 1;\n  visibility: ${({ isVisible }) => (isVisible ? 'visible' : 'hidden')};\n`;\n\nfunction DesignSpaceGuideline() {\n  const setDesignSpaceGuideline = useCanvas(\n    ({ actions }) => actions.setDesignSpaceGuideline\n  );\n  const { isAnythingTransforming } = useTransform(({ state }) => ({\n    isAnythingTransforming: state.isAnythingTransforming,\n  }));\n\n  return (\n    <DesignSpaceGuidelineBorder\n      ref={setDesignSpaceGuideline}\n      isVisible={isAnythingTransforming}\n    />\n  );\n}\n\nfunction FramesNavAndSelection({ children }) {\n  const framesLayerRef = useRef(null);\n\n  const onOpenMenu = useRightClickMenu((state) => state.onOpenMenu);\n\n  useKeyDownEffect(framesLayerRef, 'mod+alt+shift+m', (evt) => {\n    // used to shift focus outline correctly\n    document.dispatchEvent(new KeyboardEvent('keydown', { key: 'tab' }));\n    onOpenMenu(evt);\n  });\n\n  return (\n    <Layer\n      ref={framesLayerRef}\n      data-testid=\"FramesLayer\"\n      pointerEvents=\"initial\"\n      // Use `-1` to ensure that there's a default target to focus if\n      // there's no selection, but it's not reachable by keyboard\n      // otherwise.\n      tabIndex=\"-1\"\n      aria-label={__('Frames layer', 'web-stories')}\n    >\n      {children}\n      <PageBeforeArea>\n        <ExtraPages isPrevious />\n      </PageBeforeArea>\n      <PageAfterArea>\n        <ExtraPages />\n      </PageAfterArea>\n      <NavPrevArea>\n        <PageNav isNext={false} />\n      </NavPrevArea>\n      <NavNextArea>\n        <PageNav />\n      </NavNextArea>\n      <Selection onContextMenu={onOpenMenu} />\n    </Layer>\n  );\n}\n\nFramesNavAndSelection.propTypes = {\n  children: PropTypes.node,\n};\n\nfunction FrameElements() {\n  // We are returning this directly because we want the elementIds array to be shallowly\n  // compared between re-renders. This allows element properties to update without re-rendering\n  // this top level component.\n  const elementIds = useStory(\n    ({ state }) =>\n      state.currentPage?.elements?.map((el) => el.id) || STABLE_ARRAY\n  );\n  const isAnimating = useStory(({ state }) =>\n    [StoryAnimationState.Playing, StoryAnimationState.Scrubbing].includes(\n      state.animationState\n    )\n  );\n\n  const onOpenMenu = useRightClickMenu((state) => state.onOpenMenu);\n\n  const { setScrollOffset } = useLayout(({ actions: { setScrollOffset } }) => ({\n    setScrollOffset,\n  }));\n  const onScroll = useCallback(\n    (evt) =>\n      setScrollOffset({\n        left: evt.target.scrollLeft,\n        top: evt.target.scrollTop,\n      }),\n    [setScrollOffset]\n  );\n\n  return (\n    !isAnimating && (\n      <FramesPageArea\n        fullBleedContainerLabel={__(\n          'Fullbleed area (Frames layer)',\n          'web-stories'\n        )}\n        onContextMenu={onOpenMenu}\n        onScroll={onScroll}\n      >\n        {elementIds.map((id) => {\n          return <FrameElement key={id} id={id} />;\n        })}\n        <DesignSpaceGuideline />\n      </FramesPageArea>\n    )\n  );\n}\n\nfunction FramesLayer() {\n  const canvasRef = useRef();\n  const speak = useLiveRegion();\n\n  const { enterFocusGroup, setFocusGroupCleanup } = useEditLayerFocusManager(\n    ({ enterFocusGroup, setFocusGroupCleanup }) => ({\n      enterFocusGroup,\n      setFocusGroupCleanup,\n    })\n  );\n\n  useGlobalKeyDownEffect(\n    { key: 'mod+option+2', editable: true },\n    () => {\n      enterFocusGroup({\n        groupId: FOCUS_GROUPS.ELEMENT_SELECTION,\n      });\n    },\n    [enterFocusGroup]\n  );\n\n  // TODO: https://github.com/google/web-stories-wp/issues/10266\n  // refactor `useCanvasKeys`. This is the last hook causing extraneous re-renders in this component.\n  // - pulls most of state from useStory and only creates actions and attaches them to hot keys\n  // - extraneous re-renders in this component contribute only ~1ms to total re-render time,\n  //   so this is a high hanging fruit with little reward.\n  useCanvasKeys(canvasRef);\n\n  useKeyDownEffect(\n    canvasRef,\n    { key: ['enter'] },\n    () => {\n      enterFocusGroup({\n        groupId: FOCUS_GROUPS.ELEMENT_SELECTION,\n      });\n      speak(FRAME_ELEMENT_MESSAGE);\n    },\n    [enterFocusGroup, speak]\n  );\n\n  useEffect(() => {\n    setFocusGroupCleanup({\n      groupId: FOCUS_GROUPS.ELEMENT_SELECTION,\n      cleanup: () => canvasRef.current?.focus(),\n    });\n  }, [setFocusGroupCleanup]);\n\n  return (\n    <FramesNavAndSelection>\n      <FocusContainer\n        role=\"region\"\n        data-testid=\"canvas-focus-container\"\n        ref={canvasRef}\n        aria-label={FOCUS_CONTAINER_MESSAGE}\n        // eslint-disable-next-line styled-components-a11y/no-noninteractive-tabindex -- Container used to separate elements from normal tab order.\n        tabIndex={0}\n      />\n      <FrameElements />\n    </FramesNavAndSelection>\n  );\n}\n\nexport default memo(FramesLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './canvas';\nexport { default as useInsertElement } from './useInsertElement';\nexport { default as useInsertTextSet } from './useInsertTextSet';\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/backgroundCopyPaste.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Background Copy Paste integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    await addNewPage();\n\n    await waitFor(() => {\n      if (fixture.editor.footer.carousel.pages.length === 0) {\n        throw new Error('Carousel pages not loaded yet');\n      }\n    });\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should correctly copy pattern background to page with pattern background', async () => {\n    // Arrange the backgrounds\n    await gotoPage(1);\n    await setBackgroundColor('FF0000');\n    await gotoPage(2);\n    await setBackgroundColor('00FF00');\n\n    // Verify setup - 1 element on each page in the right color\n    await gotoPage(1);\n    await waitFor(() => {\n      const pageArea = getPageArea();\n      if (!pageArea) {\n        throw new Error('node not ready!');\n      }\n      expect(getPageArea()).toHaveStyle('background-color', 'rgb(255, 0, 0)');\n    });\n    expect(await getNumElements()).toBe(1);\n    await gotoPage(2);\n    await waitFor(() => {\n      const pageArea = getPageArea();\n      if (!pageArea) {\n        throw new Error('node not ready!');\n      }\n      expect(getPageArea()).toHaveStyle('background-color', 'rgb(0, 255, 0)');\n    });\n    expect(await getNumElements()).toBe(1);\n\n    // Act: Copy background from page 1 to page 2\n    await gotoPage(1);\n    await clickBackgroundElement();\n    await fixture.events.clipboard.copy();\n    await gotoPage(2);\n    await fixture.events.clipboard.paste();\n\n    // Assert - validate that page 2 now has the correct background color and only 1 element\n    await gotoPage(2);\n    await waitFor(() => {\n      const pageArea = getPageArea();\n      if (!pageArea) {\n        throw new Error('node not ready!');\n      }\n      expect(getPageArea()).toHaveStyle('background-color', 'rgb(255, 0, 0)');\n    });\n    expect(await getNumElements()).toBe(1);\n  });\n\n  it('should correctly copy pattern background to page with image', async () => {\n    // Arrange the backgrounds\n    await gotoPage(1);\n    await setBackgroundColor('FF0000');\n    await gotoPage(2);\n    await setBackgroundColor('00FF00');\n    await addBackgroundImage(0);\n\n    // Verify setup - 1 element on each page\n    await gotoPage(1);\n    expect(await getPageArea()).toHaveStyle(\n      'background-color',\n      'rgb(255, 0, 0)'\n    );\n    expect(await getNumElements()).toBe(1);\n    await gotoPage(2);\n    expect(await getCanvasBackgroundElement()).not.toBeEmpty();\n    expect(await getCanvasBackgroundImage()).toHaveProperty(\n      'src',\n      /blue-marble/\n    );\n    expect(await getNumElements()).toBe(1);\n\n    // Act: Copy background from page 1 to page 2\n    await gotoPage(1);\n    await clickBackgroundElement();\n    await fixture.events.clipboard.copy();\n    await gotoPage(2);\n    await fixture.events.clipboard.paste();\n\n    // Assert - validate that page 2 now has the correct background color, no image and only 1 element\n    await gotoPage(2);\n    expect(await getPageArea()).toHaveStyle(\n      'background-color',\n      'rgb(255, 0, 0)'\n    );\n    expect(await getCanvasBackgroundElement()).toBeEmpty();\n    expect(await getNumElements()).toBe(1);\n  });\n\n  it('should correctly copy image to page without image', async () => {\n    // Arrange the backgrounds\n    await gotoPage(1);\n    await setBackgroundColor('FF0000');\n    await addBackgroundImage(0);\n    await gotoPage(2);\n    await setBackgroundColor('00FF00');\n\n    // Verify setup - 1 element on each page\n    await gotoPage(1);\n    expect(await getCanvasBackgroundElement()).not.toBeEmpty();\n    expect(await getCanvasBackgroundImage()).toHaveProperty(\n      'src',\n      /blue-marble/\n    );\n    expect(await getNumElements()).toBe(1);\n    await gotoPage(2);\n    expect(await getPageArea()).toHaveStyle(\n      'background-color',\n      'rgb(0, 255, 0)'\n    );\n    expect(await getNumElements()).toBe(1);\n\n    // Act: Copy background from page 1 to page 2\n    await gotoPage(1);\n    await clickBackgroundElement();\n    await fixture.events.clipboard.copy();\n    await gotoPage(2);\n    await fixture.events.clipboard.paste();\n\n    // Assert - validate that page 2 now has the correct image and only 1 element\n    await gotoPage(2);\n    expect(await getCanvasBackgroundElement()).not.toBeEmpty();\n    expect(await getNumElements()).toBe(1);\n\n    // Now delete background image and verify that underlying color is still correct\n    await clickBackgroundElement();\n    await fixture.events.keyboard.press('del');\n    expect(await getPageArea()).toHaveStyle(\n      'background-color',\n      'rgb(0, 255, 0)'\n    );\n    expect(await getCanvasBackgroundElement()).toBeEmpty();\n  });\n\n  it('should correctly copy image to page with existing image', async () => {\n    // Arrange the backgrounds\n    await gotoPage(1);\n    await setBackgroundColor('FF0000');\n    await addBackgroundImage(0);\n    await fixture.events.sleep(100);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.filters.linear\n    );\n    await gotoPage(2);\n    await setBackgroundColor('00FF00');\n    await addBackgroundImage(1);\n    await fixture.events.sleep(100);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.filters.radial\n    );\n\n    // Verify setup - 1 image on each page with correct overlay\n    await gotoPage(1);\n    expect(await getCanvasBackgroundImage()).toHaveProperty(\n      'src',\n      /blue-marble/\n    );\n    expect(await getCanvasBackgroundOverlay()).toHaveStyle(\n      'background-image',\n      'linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%)'\n    );\n    expect(await getNumElements()).toBe(1);\n    await gotoPage(2);\n    expect(await getCanvasBackgroundImage()).toHaveProperty('src', /curiosity/);\n    expect(await getCanvasBackgroundOverlay()).toHaveStyle(\n      'background-image',\n      'radial-gradient(67% 67%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%)'\n    );\n    expect(await getNumElements()).toBe(1);\n\n    // Act: Copy background from page 1 to page 2\n    await gotoPage(1);\n    await clickBackgroundElement();\n    await fixture.events.clipboard.copy();\n    await gotoPage(2);\n    await fixture.events.clipboard.paste();\n\n    // Assert - validate that page 2 now has the correct image and overlay and only 1 element\n    await gotoPage(2);\n    expect(await getCanvasBackgroundImage()).toHaveProperty(\n      'src',\n      /blue-marble/\n    );\n    expect(await getCanvasBackgroundOverlay()).toHaveStyle(\n      'background-image',\n      'linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%)'\n    );\n    await fixture.events.sleep(10000);\n    expect(await getNumElements()).toBe(1);\n\n    // Now delete background image and verify that underlying color is still correct\n    await clickBackgroundElement();\n    await fixture.events.keyboard.press('del');\n    expect(await getPageArea()).toHaveStyle(\n      'background-color',\n      'rgb(0, 255, 0)'\n    );\n    expect(await getCanvasBackgroundElement()).toBeEmpty();\n  });\n\n  // High-level helpers\n  async function addNewPage() {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n  }\n  async function gotoPage(index /* 1-indexed */) {\n    const pageAtIndex = fixture.editor.footer.carousel.pages[index - 1].node;\n    await fixture.events.click(pageAtIndex);\n  }\n  async function setBackgroundColor(hex) {\n    await clickBackgroundElement();\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const hexInput = getInputByAriaLabel('Background color');\n    // First click the input field to focus it\n    await fixture.events.click(hexInput);\n    // Select all the text\n    hexInput.select();\n    // Then type hex combo\n    await fixture.events.keyboard.type(hex);\n    await fixture.events.keyboard.press('tab');\n  }\n  async function addBackgroundImage(index) {\n    // Add image and click \"set as background\"\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.events.click(fixture.editor.library.mediaTab);\n    const image = fixture.editor.library.media.item(index);\n    await fixture.events.mouse.clickOn(image, 20, 20);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.sizePosition.setAsBackground\n    );\n  }\n  async function getNumElements() {\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return elements.length;\n  }\n  async function getCanvasBackgroundElement() {\n    const wrapper = await getCanvasBackgroundElementWrapper();\n    // TODO fix this selector\n    return wrapper.querySelector('[class^=\"display__Element-\"]');\n  }\n  async function getCanvasBackgroundOverlay() {\n    const wrapper = await getCanvasBackgroundElementWrapper();\n    // TODO fix this selector\n    return wrapper.querySelector(\n      '[class^=\"displayElement__BackgroundOverlay-\"]'\n    );\n  }\n  async function getCanvasBackgroundImage() {\n    const wrapper = await getCanvasBackgroundElementWrapper();\n    // TODO fix this selector\n    return wrapper.querySelector('img');\n  }\n  async function clickBackgroundElement() {\n    const bg = await getCanvasBackgroundElementFrame();\n    await fixture.events.click(bg);\n  }\n\n  // Low-level helpers\n  function getElementByQueryAndMatcher(tagName, matcher) {\n    return Array.from(fixture.querySelectorAll(tagName)).find(matcher);\n  }\n\n  function getByAttribute(attr, value) {\n    return (el) =>\n      typeof value === 'string'\n        ? el.getAttribute(attr) === value\n        : value.test(el.getAttribute(attr));\n  }\n\n  function getInputByAriaLabel(ariaLabel) {\n    return getElementByQueryAndMatcher(\n      'input',\n      getByAttribute('aria-label', ariaLabel)\n    );\n  }\n\n  function getCanvasElementWrapperById(id) {\n    return fixture.querySelector(\n      `[data-testid=\"safezone\"] [data-element-id=\"${id}\"]`\n    );\n  }\n\n  function getCanvasElementFrameById(id) {\n    return fixture.querySelector(\n      `[data-testid=\"FramesLayer\"] [data-element-id=\"${id}\"]`\n    );\n  }\n\n  async function getBackgroundElementId() {\n    const {\n      state: {\n        currentPage: {\n          elements: [{ id }],\n        },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return id;\n  }\n\n  async function getCanvasBackgroundElementWrapper() {\n    const id = await getBackgroundElementId();\n    return getCanvasElementWrapperById(id);\n  }\n\n  async function getCanvasBackgroundElementFrame() {\n    const id = await getBackgroundElementId();\n    return getCanvasElementFrameById(id);\n  }\n\n  function getPageArea() {\n    return fixture.querySelector('[data-testid=\"fullbleed\"]');\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/canvasKeyboardNavigation.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport STICKERS from '@googleforcreators/stickers';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\nconst stickerTestType = Object.keys(STICKERS)[0];\n\ndescribe('Canvas - keyboard navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function tabToCanvasFocusContainer() {\n    // start focused on media pane searchbar\n    await fixture.editor.library.mediaTab.click();\n    await fixture.events.focus(fixture.editor.library.media.searchBar);\n\n    // tab until focus reaches the canvas container\n    let count = 0;\n    while (count < 15) {\n      // eslint-disable-next-line no-await-in-loop -- need to await key press\n      await fixture.events.keyboard.press('tab');\n\n      if (document.activeElement === focusContainer) {\n        break;\n      }\n\n      count++;\n    }\n\n    if (count >= 15) {\n      throw new Error('Could not find focus container.');\n    }\n  }\n\n  function getActiveElementId() {\n    return document.activeElement.getAttribute('data-element-id');\n  }\n\n  async function addElementsToCanvas() {\n    // add one of each element\n    // add text to canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    // add shape to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    // add sticker to canvas\n    await fixture.events.click(\n      fixture.editor.library.shapes.sticker(stickerTestType)\n    );\n    // add image to canvas\n    await fixture.editor.library.mediaTab.click();\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n  }\n\n  it('should focus the canvas with global keyboard shortcut mod+alt+2 (mod+option+2)', async () => {\n    // add some elements\n    // add text to canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    // add shape to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    // add image to canvas\n    await fixture.editor.library.mediaTab.click();\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    await fixture.events.keyboard.shortcut('mod+alt+2');\n\n    const selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n    // see that background element is selected & focused\n    expect(document.activeElement.getAttribute('data-element-id')).toBe(\n      selectedElements[0].id\n    );\n  });\n\n  it('should not focus the canvas while tabbing through the editor', async () => {\n    await tabToCanvasFocusContainer();\n\n    // tab once more\n    await fixture.events.keyboard.press('tab');\n\n    // verify that prev page button is focused\n    expect(document.activeElement).toBe(\n      fixture.editor.canvas.framesLayer.prevPage\n    );\n  });\n\n  it('should focus the canvas and elements in the canvas after entering into the canvas space', async () => {\n    // add some elements\n    // add text to canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    // add shape to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    // add image to canvas\n    await fixture.editor.library.mediaTab.click();\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    await tabToCanvasFocusContainer();\n\n    // enter into the canvas\n    await fixture.events.keyboard.press('Enter');\n\n    const selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n    // see that background element is selected & focused\n    expect(document.activeElement.getAttribute('data-element-id')).toBe(\n      selectedElements[0].id\n    );\n\n    // exit canvas\n    await fixture.events.keyboard.press('Escape');\n\n    // verify exit\n    expect(document.activeElement).toBe(focusContainer);\n  });\n\n  it('should change element selection on focus and wrap around at the last element when only keyboard is used', async () => {\n    await addElementsToCanvas();\n\n    await tabToCanvasFocusContainer();\n\n    // enter into the canvas\n    await fixture.events.keyboard.press('Enter');\n\n    let selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n\n    // tab to the text element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('text');\n\n    // tab to the shape element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // shape should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('shape');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // tab to the sticker element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // sticker should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('sticker');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // tab to the image element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // image should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('image');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // verify cyclicality: wrap around to background element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n  });\n\n  it('should change element selection on focus and wrap around at the last element when mix of cursor and keyboard are used', async () => {\n    await addElementsToCanvas();\n\n    await fixture.events.click(\n      fixture.editor.canvas.framesLayer.frames[1].node\n    );\n\n    let selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('text');\n\n    // tab to the shape element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // shape should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('shape');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // tab to the sticker element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // sticker should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('sticker');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // tab to the image element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    // image should be selected and receive focus\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('image');\n    expect(getActiveElementId()).toBe(selectedElements[0].id);\n\n    // verify cyclicality: wrap around to background element\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/canvasKeys.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Canvas Keyboard Shortcuts', () => {\n  let fixture;\n  let elementIds;\n\n  async function insertMediaByIndex(index) {\n    const mediaItem = fixture.editor.library.media.item(index);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    // Let's insert three images\n    await insertMediaByIndex(0);\n    await insertMediaByIndex(1);\n    await insertMediaByIndex(2);\n\n    // And let's get the ID's of those three elements for easy access later\n    const storyContext = await fixture.renderHook(() => useStory());\n    elementIds = storyContext.state.currentPage.elements\n      .slice(1)\n      .map(({ id }) => id);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds;\n  }\n\n  it('should have the last element selected by default', async () => {\n    expect(await getSelection()).toEqual([elementIds[2]]);\n  });\n\n  it('should select all elements when pressing mod+a shortcut', async () => {\n    await fixture.events.focus(fixture.editor.canvas.framesLayer.fullbleed);\n    await fixture.events.keyboard.shortcut('mod+a');\n    expect(await getSelection()).toEqual([...elementIds]);\n  });\n\n  it('should focus on the design panel link input when pressing mod+k shortcut', async () => {\n    const TEST_URL = 'https://test.com';\n\n    // select any or all elements on the page\n    await fixture.events.focus(fixture.editor.canvas.framesLayer.fullbleed);\n    await fixture.events.keyboard.shortcut('mod+a');\n\n    // press mod+k\n    await fixture.events.keyboard.shortcut('mod+k');\n\n    // expect to focus on design panel link input\n    expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n    expect(document.activeElement).toEqual(\n      fixture.editor.sidebar.designPanel.link.address\n    );\n\n    // add url to the selectedElements\n    await fixture.events.keyboard.type(TEST_URL);\n    await fixture.events.keyboard.press('Enter');\n\n    // check that all the elements selected have the url\n    const { selectedElements: elements } = await fixture.renderHook(() =>\n      useStory(({ state: selectedElements }) => selectedElements)\n    );\n\n    for (const element of elements) {\n      expect(element.link.url).toBe(TEST_URL);\n    }\n  });\n\n  it('should play pause animation when pressing mod+enter shortcut', async () => {\n    // add a second page to allow for animations\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n\n    // insert element\n    await insertMediaByIndex(0);\n\n    // add a long animation to the element\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const effectChooser =\n      fixture.editor.sidebar.designPanel.animation.effectChooser;\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n\n    // Synthetic delay to make the dropdown behave correctly\n    await fixture.events.sleep(400);\n    // click to close\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n    const duration = fixture.screen.getByLabelText('Duration');\n    await fixture.events.click(duration);\n    const durationMs = 1000;\n    await fixture.events.keyboard.type(durationMs.toString());\n    await fixture.events.keyboard.press('Enter');\n\n    // wait for initial animation\n    await fixture.events.sleep(durationMs);\n\n    // select the canvas\n    await fixture.events.click(\n      fixture.editor.canvas.framesLayer.frames[0].node\n    );\n\n    // check that 'Play Animation' toggle button is there\n    let toggle = fixture.screen.getByLabelText('Play Page Animations');\n    expect(toggle).toBeDefined();\n\n    // press mod+enter\n    await fixture.events.keyboard.shortcut('mod+enter');\n\n    // check that 'Stop Animation' toggle button is there\n    toggle = fixture.screen.getByLabelText('Stop Page Animations');\n    expect(toggle).toBeDefined();\n\n    // press mod+enter\n    await fixture.events.keyboard.shortcut('mod+enter');\n\n    // check that 'Play Animation' toggle button is there\n    await fixture.events.sleep(durationMs);\n    toggle = fixture.screen.getByLabelText('Play Page Animations');\n    expect(toggle).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/carousel.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '..';\n\ndescribe('Carousel integration', () => {\n  let fixture;\n  let element1;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    fixture.setPages([\n      { id: 'page1', backgroundColor: createSolid(255, 255, 255) },\n      { id: 'page2', backgroundColor: createSolid(255, 0, 0) },\n      { id: 'page3', backgroundColor: createSolid(0, 255, 0) },\n      { id: 'page4', backgroundColor: createSolid(0, 0, 255) },\n    ]);\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    element1 = await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: `Page 1`,\n        x: 40,\n        y: 40,\n        width: 250,\n      })\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getCurrentPageId() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPageId;\n  }\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds;\n  }\n\n  async function getPageIds() {\n    const {\n      state: { pages },\n    } = await fixture.renderHook(() => useStory());\n    return pages.map(({ id }) => id);\n  }\n\n  async function clickOnThumbnail(index) {\n    await fixture.events.sleep(100);\n    await fixture.editor.footer.carousel.waitReady();\n\n    let thumb;\n    await waitFor(() => {\n      thumb = fixture.editor.footer.carousel.pages[index];\n\n      if (!thumb) {\n        throw new Error('cant access carousel before rendered');\n      }\n    });\n\n    thumb.node.scrollIntoView();\n    await fixture.events.mouse.clickOn(thumb.node, 5, 5);\n  }\n\n  it('should have no aXe violations', async () => {\n    await expectAsync(fixture.editor.footer.carousel.node).toHaveNoViolations();\n  });\n\n  it('should select the current page', async () => {\n    expect(await getCurrentPageId()).toEqual('page1');\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  // Since we're already on the first page, selection and current page id remains unchanged.\n  it('should click into carousel on the first page', async () => {\n    await clickOnThumbnail(0);\n    expect(await getCurrentPageId()).toEqual('page1');\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  it('should exit the carousel on Esc', async () => {\n    // Enter.\n    await clickOnThumbnail(0);\n    await fixture.editor.footer.carousel.waitFocusedWithin();\n\n    // Exit.\n    await fixture.events.keyboard.press('Esc');\n    await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n  });\n\n  it('should click into carousel on the second page', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getSelection()).toEqual([]);\n  });\n\n  it('should navigate the page with keys', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Go left.\n    await fixture.events.keyboard.press('left');\n    expect(await getCurrentPageId()).toEqual('page1');\n\n    // Go left again: end of the line.\n    await fixture.events.keyboard.press('left');\n    expect(await getCurrentPageId()).toEqual('page1');\n\n    // Go right.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Go right again.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page3');\n\n    // Go right again.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page4');\n\n    // Go right again: end of the line.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page4');\n  });\n\n  it('should reorder the page with keys', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Order left.\n    await fixture.events.keyboard.shortcut('mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order left again: end of the line.\n    await fixture.events.keyboard.shortcut('mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order right.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page2', 'page3', 'page4']);\n\n    // Order right again.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page2', 'page4']);\n\n    // Order right again.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n\n    // Order right again: end of the line.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n\n    // Order to first.\n    await fixture.events.keyboard.shortcut('shift+mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order to last.\n    await fixture.events.keyboard.shortcut('shift+mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n  });\n\n  it('should delete the first page', async () => {\n    await clickOnThumbnail(0);\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n    expect(await getPageIds()).toEqual(['page2', 'page3', 'page4']);\n    expect(await getCurrentPageId()).toEqual('page2');\n  });\n\n  it('should delete the second page', async () => {\n    await clickOnThumbnail(1);\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4']);\n    expect(await getCurrentPageId()).toEqual('page3');\n  });\n\n  it('should duplicate the first page', async () => {\n    await clickOnThumbnail(0);\n    await fixture.events.keyboard.shortcut('mod+D');\n    const newPageId = await getCurrentPageId();\n    expect(await getPageIds()).toEqual([\n      'page1',\n      newPageId,\n      'page2',\n      'page3',\n      'page4',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/cloneSelection.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Clone element integration', () => {\n  let fixture;\n  let bg, bgRect;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    bg = await getElementByIndex(1);\n    bgRect = (await getCanvasElementWrapperById(bg.id)).getBoundingClientRect();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should correctly do nothing if no selection', async () => {\n    // Switch to shapes tab and add a triangle\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    // Clear selection by pressing above background element\n    await clickAboveElement(bg.id);\n\n    // Press clone shortcut\n    await fixture.events.keyboard.shortcut('mod+d');\n\n    // Expect nothing to have changed\n    expect(await getNumElements()).toBe(2);\n  });\n\n  it('should correctly do nothing if background is selected', async () => {\n    // Switch to shapes tab and add a triangle\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    // Select background\n    await clickElement(bg.id);\n\n    // Press clone shortcut\n    await fixture.events.keyboard.shortcut('mod+d');\n\n    // Expect nothing to have changed\n    expect(await getNumElements()).toBe(2);\n  });\n\n  it('should correctly clone 1 element', async () => {\n    // Switch to shapes tab and add a triangle\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    // Select background to clear element selection.\n    await clickElement(bg.id);\n\n    // Select the added shape.\n    const shape = await getElementByIndex(2);\n    await clickElement(shape.id);\n\n    // Press clone shortcut\n    await fixture.events.keyboard.shortcut('mod+d');\n    // Expect a new image to have been added\n    expect(await getNumElements()).toBe(3);\n\n    // Verify new element is in fact a clone and in correct position\n    const clonedShape = await getElementByIndex(3);\n    expect(clonedShape).toEqual(\n      jasmine.objectContaining({\n        mask: {\n          type: 'rectangle',\n        },\n        x: shape.x + 30,\n        y: shape.y + 30,\n      })\n    );\n  });\n\n  it('should correctly clone 2 elements', async () => {\n    // Add first image to page\n    let mediaItem = await getMediaElement(/blue-marble/);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n    let img1 = await getElementByIndex(2);\n    // Drag it to (50,50)\n    const rect1 = (\n      await getCanvasElementWrapperById(img1.id)\n    ).getBoundingClientRect();\n    await fixture.events.mouse.seq(({ move, down, up }) => [\n      move(rect1.left + 10, rect1.top + 10),\n      down(),\n      move(bgRect.left + 50, bgRect.top + 50, { steps: 2 }),\n      up(),\n    ]);\n\n    // Save final objects\n    img1 = await getElementByIndex(2);\n    // Add second image to page\n    mediaItem = await getMediaElement(/saturn/);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n    let img2 = await getElementByIndex(3);\n\n    // Drag it to (100,100)\n    const rect2 = (\n      await getCanvasElementWrapperById(img2.id)\n    ).getBoundingClientRect();\n    await fixture.events.mouse.seq(({ move, down, up }) => [\n      move(rect2.left + 10, rect2.top + 10),\n      down(),\n      move(bgRect.left + 100, bgRect.top + 100, { steps: 2 }),\n      up(),\n    ]);\n    img2 = await getElementByIndex(3);\n\n    // Select img1 and img2.\n    await clickElement(img1.id);\n    await clickElement(img2.id, /* isMultiSelect */ true);\n\n    // Press clone shortcut\n    await fixture.events.keyboard.shortcut('mod+d');\n\n    // Expect two new images to have been added\n    expect(await getNumElements()).toBe(5);\n\n    // Verify new elements are in fact clones and in correct positions\n    const clonedImg1 = await getElementByIndex(3);\n    expect(clonedImg1).toEqual(\n      jasmine.objectContaining({\n        resource: jasmine.objectContaining({\n          src: img1.resource.src,\n        }),\n        x: img1.x + 30,\n        y: img1.y + 30,\n      })\n    );\n    const clonedImg2 = await getElementByIndex(5);\n    expect(clonedImg2).toEqual(\n      jasmine.objectContaining({\n        resource: jasmine.objectContaining({\n          src: img2.resource.src,\n        }),\n        x: img2.x + 30,\n        y: img2.y + 30,\n      })\n    );\n  });\n\n  // High-level helpers\n  async function getNumElements() {\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return elements.length;\n  }\n  async function getElementByIndex(index) {\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return elements[index - 1];\n  }\n  async function clickElement(elementId, isMultiSelect = false) {\n    const wrapper = await getCanvasElementWrapperById(elementId);\n    const rect = wrapper.getBoundingClientRect();\n    if (isMultiSelect) {\n      // hold shift\n      await fixture.events.keyboard.down('shift');\n    }\n    await fixture.events.mouse.click(rect.left + 10, rect.top + 10);\n    if (isMultiSelect) {\n      // release shift\n      await fixture.events.keyboard.up('shift');\n    }\n  }\n  async function clickAboveElement(elementId) {\n    const wrapper = await getCanvasElementWrapperById(elementId);\n    const rect = wrapper.getBoundingClientRect();\n    await fixture.events.mouse.click(rect.left, rect.top - 10);\n  }\n\n  // Low-level helpers\n  function getElementByQueryAndMatcher(tagName, matcher) {\n    return Array.from(fixture.querySelectorAll(tagName)).find(matcher);\n  }\n\n  function getByAttribute(attr, value) {\n    return (el) =>\n      typeof value === 'string'\n        ? el.getAttribute(attr) === value\n        : value.test(el.getAttribute(attr));\n  }\n\n  function getMediaElement(imageAlt) {\n    return getElementByQueryAndMatcher(\n      '[data-testid^=\"mediaElement\"] img',\n      getByAttribute('alt', imageAlt)\n    );\n  }\n\n  function getCanvasElementWrapperById(id) {\n    return fixture.querySelector(\n      `[data-testid=\"safezone\"] [data-element-id=\"${id}\"]`\n    );\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/elementKeyboardNavigation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Canvas Element - keyboard navigation', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  function getCanvasElementWrapperById(id) {\n    return fixture.querySelector(\n      `[data-testid=\"frameElement\"][data-element-id=\"${id}\"]`\n    );\n  }\n\n  it('should be able to navigate in and out of the floating menu with ctrl+alt+p & esc', async () => {\n    // Insert an element\n    const shapeTab = fixture.editor.library.shapesTab;\n    await fixture.events.click(shapeTab);\n    const rectangleShape = fixture.editor.library.shapes.shape('Rectangle');\n    await fixture.events.click(rectangleShape);\n\n    // Get the element wrapper and see that it has focus\n    let wrapperEl;\n    await waitFor(async () => {\n      const elementId = await fixture.renderHook(() =>\n        useStory(({ state }) => state.currentPage.elements[1].id)\n      );\n      wrapperEl = getCanvasElementWrapperById(elementId);\n\n      if (!wrapperEl) {\n        throw new Error('element has not rendered to screen');\n      }\n\n      // There's some sort of debaounced timeout that we need to wait for before\n      // frame elements receive focus after adding the element through the library\n      if (document.activeElement !== wrapperEl) {\n        throw new Error(\n          'frame element wrapper has not received focus since adding new element'\n        );\n      }\n    });\n    expect(document.activeElement).toBe(wrapperEl);\n\n    // Use Keyboard to navigate into the floating menu\n    const designMenu = fixture.editor.canvas.designMenu;\n    await fixture.events.keyboard.shortcut('control+alt+p');\n    expect(designMenu._node.contains(document.activeElement)).toBe(true);\n\n    // Use keyboard to navigate out of design menu\n    await fixture.events.keyboard.press('Esc');\n    expect(document.activeElement).toBe(wrapperEl);\n\n    // verify cyclicality: wrap around to background element\n    await fixture.events.keyboard.press('Tab');\n\n    const selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].isBackground).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/fullbleedMediaAsBackground.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '..';\n\ndescribe('Fullbleed Media as Background', () => {\n  let fixture;\n  let image;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    image = await fixture.act(() =>\n      insertElement('image', {\n        x: 0,\n        y: 0,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          id: 10,\n          type: 'image',\n          mimeType: 'image/jpg',\n          src: 'http://localhost:9876/__static__/earth.jpg',\n          alt: 'earth',\n          width: 640,\n          height: 529,\n          baseColor: '#734727',\n        },\n      })\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should set image as background when resized to match the canvas', async () => {\n    const imageFrame = fixture.editor.canvas.framesLayer.frame(image.id);\n    const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(imageFrame.node, 0, 0),\n      down(),\n      moveRel(canvas, 0, 0),\n      up(),\n    ]);\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(imageFrame.node, '100%', '100%'),\n      down(),\n      moveRel(canvas, '100%', '100%'),\n      up(),\n    ]);\n    const elements = await getElements(fixture);\n    expect(elements.length).toBe(1);\n    expect(elements[0].isDefaultBackground).not.toBeDefined();\n    expect(elements[0].resource).toEqual(image.resource);\n  });\n\n  it('should not set image as background when media background is already set', async () => {\n    const tempImage = fixture.editor.library.media.item(1);\n    await fixture.events.mouse.clickOn(tempImage, 20, 20);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.sizePosition.setAsBackground\n    );\n\n    const imageFrame = fixture.editor.canvas.framesLayer.frame(image.id);\n    const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n    await fixture.events.mouse.clickOn(imageFrame.node, 10, 10);\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(imageFrame.node, 0, 0),\n      down(),\n      moveRel(canvas, 0, 0),\n      up(),\n    ]);\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(imageFrame.node, '100%', '100%'),\n      down(),\n      moveRel(canvas, '100%', '100%'),\n      up(),\n    ]);\n    const elements = await getElements(fixture);\n    expect(elements.length).toBe(2);\n    expect(elements[0].isDefaultBackground).not.toBeDefined();\n    expect(elements[0].resource).not.toEqual(image.resource);\n  });\n});\n\nasync function getElements(fixture) {\n  const {\n    state: {\n      currentPage: { elements },\n    },\n  } = await fixture.renderHook(() => useStory());\n  return elements;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/keys.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '..';\n\ndescribe('Canvas keys integration', () => {\n  let fixture;\n  let element1;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    element1 = await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: `Page 1`,\n        x: 40,\n        y: 40,\n        width: 250,\n      })\n    );\n\n    await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds;\n  }\n\n  async function getLatestElement(elementId) {\n    const storyContext = await fixture.renderHook(() => useStory());\n    const elements = storyContext.state.currentPage.elements;\n    return elements.find(({ id }) => id === elementId);\n  }\n\n  async function getNonBackgroundElementIds() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    const elements = storyContext.state.currentPage.elements;\n    const nonBackgroundElements = elements.filter(\n      ({ isBackground }) => !isBackground\n    );\n    return nonBackgroundElements.map(({ id }) => id);\n  }\n\n  it('should select the inserted element by default', async () => {\n    expect(await getNonBackgroundElementIds()).toEqual([element1.id]);\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  it('should delete the selected element', async () => {\n    await fixture.events.keyboard.press('Del');\n    expect(await getNonBackgroundElementIds()).toEqual([]);\n    expect(await getSelection()).toEqual([]);\n  });\n\n  it('should delete element from the design panel', async () => {\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const bold = fixture.editor.sidebar.designPanel.textStyle.bold.button;\n    await fixture.events.focus(bold);\n    expect(await getSelection()).toEqual([element1.id]);\n\n    await fixture.events.keyboard.press('Del');\n    expect(await getNonBackgroundElementIds()).toEqual([]);\n    expect(await getSelection()).toEqual([]);\n  });\n\n  it('should delete element from the tabs', async () => {\n    const textTab = fixture.querySelector('#library-tab-text');\n    await fixture.events.focus(textTab);\n    expect(await getSelection()).toEqual([element1.id]);\n\n    await fixture.events.keyboard.press('Del');\n    expect(await getNonBackgroundElementIds()).toEqual([]);\n    expect(await getSelection()).toEqual([]);\n  });\n\n  it('should not be able to delete element from a dialog', async () => {\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const colorButton = fixture.querySelector(\n      'button[aria-label=\"Text color\"]'\n    );\n    await fixture.events.click(colorButton);\n    expect(await getSelection()).toEqual([element1.id]);\n    const dialogs = await fixture.screen.findAllByRole('dialog');\n    expect(dialogs.length).toBe(1);\n\n    await fixture.snapshot('color picker open');\n\n    await fixture.events.keyboard.press('Del');\n    expect(await getNonBackgroundElementIds()).toEqual([element1.id]);\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  it('should move selection with arrow keys', async () => {\n    await fixture.events.keyboard.press('left');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x - 10);\n\n    await fixture.events.keyboard.press('right');\n    await fixture.events.keyboard.press('right');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x + 10);\n\n    await fixture.events.keyboard.press('up');\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y - 10);\n\n    await fixture.events.keyboard.press('down');\n    await fixture.events.keyboard.press('down');\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y + 10);\n  });\n\n  it('should move selection with arrow keys and fine step', async () => {\n    await fixture.events.keyboard.shortcut('shift+left');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x - 1);\n\n    await fixture.events.keyboard.shortcut('shift+right');\n    await fixture.events.keyboard.shortcut('shift+right');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x + 1);\n\n    await fixture.events.keyboard.shortcut('shift+up');\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y - 1);\n\n    await fixture.events.keyboard.shortcut('shift+down');\n    await fixture.events.keyboard.shortcut('shift+down');\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y + 1);\n  });\n\n  it('should not bubble up arrow keys from library tabs', async () => {\n    const textTab = fixture.querySelector('#library-tab-text');\n    await fixture.events.focus(textTab);\n\n    await fixture.events.keyboard.press('right');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x);\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y);\n\n    await fixture.events.keyboard.press('left');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x);\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y);\n\n    await fixture.events.keyboard.press('up');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x);\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y);\n\n    await fixture.events.keyboard.press('down');\n    expect((await getLatestElement(element1.id)).x).toEqual(element1.x);\n    expect((await getLatestElement(element1.id)).y).toEqual(element1.y);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/lasso.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '..';\n\ndescribe('Lasso integration', () => {\n  let fixture;\n  let element1, element2, element3;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    element1 = await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: 'hello world!',\n        x: 40,\n        y: -40,\n        width: 250,\n      })\n    );\n    element2 = await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: 'hello world!',\n        x: 40,\n        y: 80,\n        width: 250,\n      })\n    );\n    element3 = await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: 'hello world!',\n        isLocked: true,\n        x: 300,\n        y: 500,\n        width: 250,\n      })\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds;\n  }\n\n  it('should have the last element selected by default', async () => {\n    expect(await getSelection()).toEqual([element3.id]);\n  });\n\n  it('should select right on the top-left corner', async () => {\n    const frame1 = fixture.editor.canvas.framesLayer.frame(element1.id);\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(frame1.node, -20, -20),\n      down(),\n      moveBy(22, 22, { steps: 5 }),\n      up(),\n    ]);\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  it('should select right on the bottom-right corner', async () => {\n    const frame1 = fixture.editor.canvas.framesLayer.frame(element1.id);\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(frame1.node, '100%', '100%'),\n      moveBy(20, 20),\n      down(),\n      moveBy(-22, -22, { steps: 5 }),\n      up(),\n    ]);\n    expect(await getSelection()).toEqual([element1.id]);\n  });\n\n  it('should select two elements', async () => {\n    const frame1 = fixture.editor.canvas.framesLayer.frame(element1.id);\n    const frame2 = fixture.editor.canvas.framesLayer.frame(element2.id);\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(frame1.node, '100%', '100%'),\n      moveBy(2, -2),\n      down(),\n      moveRel(frame2.node, '100%', 0, { steps: 5 }),\n      moveBy(-2, 2),\n      up(),\n    ]);\n    expect(await getSelection()).toEqual([element1.id, element2.id]);\n  });\n\n  it('should select only unlocked elements', async () => {\n    const frame1 = fixture.editor.canvas.framesLayer.frame(element1.id);\n    const frame3 = fixture.editor.canvas.framesLayer.frame(element3.id);\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(frame1.node, -2, -2),\n      down(),\n      moveRel(frame3.node, '50%', '50%', { steps: 5 }),\n      up(),\n    ]);\n    // Note no element 3 in the resulting selection\n    expect(await getSelection()).toEqual([element1.id, element2.id]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/multiSelectionMovable.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport useInsertElement from '../useInsertElement';\n\ndescribe('Multi-selection Moveable integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function clickOnTarget(target, key = false) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    if (key) {\n      await fixture.events.keyboard.down(key);\n    }\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n    if (key) {\n      await fixture.events.keyboard.up(key);\n    }\n  }\n\n  describe('multi-selection', () => {\n    let element1;\n    let element2;\n    let element3;\n    let frame1;\n    let frame2;\n    let frame3;\n\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      element1 = await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: createSolidFromString('#ff00ff'),\n          mask: { type: 'rectangle' },\n          x: 10,\n          y: 10,\n          width: 50,\n          height: 50,\n        })\n      );\n\n      element2 = await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: createSolidFromString('#00ff00'),\n          mask: { type: 'rectangle' },\n          x: 100,\n          y: 100,\n          width: 50,\n          height: 50,\n        })\n      );\n\n      element3 = await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: createSolidFromString('#0000ff'),\n          mask: { type: 'rectangle' },\n          x: element1.x + element1.width + 1,\n          y: element1.y + element1.height + 1,\n          width: 20,\n          height: 20,\n        })\n      );\n\n      frame1 = fixture.editor.canvas.framesLayer.frame(element1.id).node;\n      frame2 = fixture.editor.canvas.framesLayer.frame(element2.id).node;\n      frame3 = fixture.editor.canvas.framesLayer.frame(element3.id).node;\n    });\n\n    it('should render initial content', async () => {\n      await fixture.snapshot();\n    });\n\n    async function getSelection() {\n      const storyContext = await fixture.renderHook(() => useStory());\n      return storyContext.state.selectedElementIds;\n    }\n\n    describe('deleting element', () => {\n      beforeEach(async () => {\n        await clickOnTarget(frame1);\n        await clickOnTarget(frame2, 'Shift');\n      });\n\n      it('should delete element that gets dragged out of the canvas to left while in multi-selection', async () => {\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(frame1, 10, 10),\n          down(),\n          moveBy(-65, 0, { steps: 6 }),\n          up(),\n        ]);\n        expect(await getSelection()).toEqual([element2.id]);\n      });\n\n      it('should delete element that gets dragged out of the canvas to right while in multi-selection', async () => {\n        const safezone = fixture.querySelector('[data-testid=\"safezone\"]');\n        const safezoneWidth = safezone.getBoundingClientRect().width;\n        const frameWidth = frame2.getBoundingClientRect().width;\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(frame2, 10, 10),\n          down(),\n          moveBy(safezoneWidth - frameWidth, 0, { steps: 10 }),\n          up(),\n        ]);\n        expect(await getSelection()).toEqual([element1.id]);\n      });\n    });\n\n    describe('click interaction', () => {\n      let safezone;\n      beforeEach(async () => {\n        await clickOnTarget(frame1);\n        await clickOnTarget(frame2, 'Shift');\n\n        safezone = fixture.querySelector('[data-testid=\"safezone\"]');\n      });\n\n      it('should have multiple elements selected', async () => {\n        expect(await getSelection()).toEqual([element1.id, element2.id]);\n      });\n\n      it('should select one element when clicking in multi-selection', async () => {\n        await fixture.events.mouse.clickOn(frame1, 10, 10);\n        expect(await getSelection()).toEqual([element1.id]);\n      });\n\n      it('should select bg element when clicking out of the multi-selection', async () => {\n        const { x, y } = safezone.getBoundingClientRect();\n        await fixture.events.mouse.click(x + 100, y + 200);\n        const storyContext = await fixture.renderHook(() => useStory());\n\n        // Let's assure we have the background element (the first element) in the selection now.\n        const background = storyContext.state.currentPage.elements[0];\n        expect(storyContext.state.selectedElementIds).toEqual([background.id]);\n      });\n\n      it('should de-select all elements when clicking out of the page', async () => {\n        const { x, y } = safezone.getBoundingClientRect();\n        await fixture.events.mouse.click(x - 10, y - 10);\n        expect(await getSelection()).toEqual([]);\n      });\n\n      it('should allow adding an element to selection in the middle of multi-selection', async () => {\n        await clickOnTarget(frame3, 'Shift');\n        expect(await getSelection()).toEqual([\n          element1.id,\n          element2.id,\n          element3.id,\n        ]);\n      });\n\n      it('should allow removing an element from multi-selection', async () => {\n        // Remove element2 from multi-selection.\n        await clickOnTarget(frame2, 'Shift');\n\n        expect(await getSelection()).toEqual([element1.id]);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/pageMenuActions.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '..';\n\ndescribe('PageMenu integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('add a text', () => {\n    let element;\n\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      element = await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'hello world!',\n          x: 40,\n          y: 40,\n          width: 250,\n        })\n      );\n      await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n    });\n\n    function getFrame() {\n      return fixture.editor.canvas.framesLayer.frame(element.id);\n    }\n\n    async function getSelection() {\n      const storyContext = await fixture.renderHook(() => useStory());\n      return storyContext.state.selectedElementIds;\n    }\n\n    it('should render initial content and make it selected', async () => {\n      expect(getFrame().node.textContent).toEqual('hello world!');\n      expect(await getSelection()).toEqual([element.id]);\n    });\n\n    describe('delete the element, restore, and delete again', () => {\n      it('using shortcuts', async () => {\n        // Delete.\n        await fixture.events.keyboard.shortcut('del');\n        expect(getFrame()).toBeNull();\n        expect(await getSelection()).toEqual([]);\n\n        // Restore.\n        await fixture.events.keyboard.shortcut('mod+z');\n        expect(getFrame()).toBeTruthy();\n        expect(await getSelection()).toEqual([element.id]);\n\n        // Delete again.\n        await fixture.events.keyboard.shortcut('del');\n        expect(getFrame()).toBeNull();\n        expect(await getSelection()).toEqual([]);\n      });\n\n      it('using page menu', async () => {\n        // Delete.\n        await fixture.events.keyboard.shortcut('del');\n        expect(getFrame()).toBeNull();\n        expect(await getSelection()).toEqual([]);\n\n        // Restore.\n        // @todo: Use either `workspace.pageMenu.undoButton` or\n        // `byRole('button', {name: 'Undo Changes'})` APIs.\n        const undoButton = fixture.querySelector(\n          'button[aria-label=\"Undo Changes\"]'\n        );\n        await fixture.events.click(undoButton);\n        expect(getFrame()).toBeTruthy();\n        expect(await getSelection()).toEqual([element.id]);\n\n        // Delete again.\n        await fixture.events.keyboard.shortcut('del');\n        expect(getFrame()).toBeNull();\n        expect(await getSelection()).toEqual([]);\n      });\n    });\n  });\n\n  it('should render selection frame handles below page menu but allow click-through', async () => {\n    // Add image\n    const mediaItem = fixture.editor.library.media.item(0);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n\n    // Press right-arrow 10 times to move it into correct location\n    await Array.from(Array(10)).reduce(\n      (p) => p.then(() => fixture.events.keyboard.press('right')),\n      Promise.resolve()\n    );\n\n    // Snapshot it\n    await fixture.snapshot();\n\n    // Now click the image link button to confirm that a quick-action\n    // button can receive pointer events\n    await fixture.events.click(\n      fixture.editor.canvas.quickActionMenu.addLinkButton\n    );\n    // Confirm by expecting link panel input to be focused\n    expect(fixture.editor.sidebar.designPanel.link.address).toBe(\n      document.activeElement\n    );\n\n    // Then drag right-handle of image to the left to confirm it\n    // can also receive pointer events\n    const image = fixture.editor.canvas.framesLayer.frames[1];\n    const widthBefore = image.node.getBoundingClientRect().width;\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(image.node, '100%', '50%'),\n      down(),\n      moveBy(-100, 0, { steps: 10 }),\n      up(),\n    ]);\n    const widthAfter = image.node.getBoundingClientRect().width;\n    // Confirm by expecting frame width to have decreased\n    expect(widthAfter).toBeLessThan(widthBefore);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/pageSideMenuActions.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('PageMenu integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should render side menu with the animation play button disabled on the first page', async () => {\n    // add a new page and a text component\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // add animation\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n\n    const panel = fixture.editor.sidebar.designPanel.animation;\n    const effectChooser = panel.effectChooser;\n\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n\n    // the play button should be visible once an animation is added\n    // and be enabled if on any page other than the first page\n    let button = fixture.screen.getByLabelText('Play Page Animations');\n    expect(button.disabled).toBeFalsy();\n\n    // switch to the first page delete it\n    const pageAtIndex = fixture.editor.footer.carousel.pages[0].node;\n    await fixture.events.click(pageAtIndex);\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n\n    // the second page should now be the first page\n    // make sure the play button is visible and is disabled\n    button = fixture.screen.getByLabelText('Page Animations Disabled');\n    expect(button.disabled).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/quickActions.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { ACTIONS } from '../../../app/quickActions';\nimport { Fixture } from '../../../karma';\nimport useInsertElement from '../useInsertElement';\n\ndescribe('Quick Actions integration', () => {\n  let fixture;\n\n  async function clickOnTarget(target) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    // #11321 adding/editing animations on the first page is disabled\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('menu visibility', () => {\n    it('quick menu should not be visible if the canvas is overflowing', async () => {\n      const { zoomSelector } = fixture.editor.footer;\n\n      await fixture.events.click(zoomSelector.select);\n      await fixture.events.sleep(300);\n      await fixture.events.click(await zoomSelector.option('Fill'));\n      await fixture.events.sleep(300);\n\n      expect(fixture.screen.queryByTestId('quick-actions-menu')).toBeNull();\n    });\n\n    it('quick menu should not be visible if no quick actions are present', async () => {\n      // when two different elements types are selected, there may not be any quick actions to show\n      // in that case, we shouldn't be rendering the context menu at all\n      // add shape to canvas\n      await fixture.editor.library.shapesTab.click();\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n\n      // add text to canvas\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n\n      expect(\n        fixture.screen.queryByTestId('Element quick actions')\n      ).not.toBeNull();\n\n      // select both text and shape elements\n      await fixture.events.keyboard.down('Shift');\n      const triangle = fixture.editor.canvas.framesLayer.frames[1].node;\n      await clickOnTarget(triangle);\n      await fixture.events.keyboard.up('Shift');\n\n      expect(fixture.screen.queryByTestId('Element quick actions')).toBeNull();\n    });\n  });\n\n  describe('quick action menu should have no aXe accessibility violations', () => {\n    it('should have no aXe violations with the default menu', async () => {\n      await expectAsync(\n        fixture.editor.canvas.quickActionMenu.node\n      ).toHaveNoViolations();\n    });\n  });\n\n  describe('no element selected', () => {\n    it(`clicking the \\`${ACTIONS.CHANGE_BACKGROUND_COLOR.text}\\` button should select the background and open the design panel`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.pageBackground).not.toBeNull();\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.pageBackground.backgroundColorInput\n      );\n    });\n\n    it(`clicking the \\`${ACTIONS.INSERT_BACKGROUND_MEDIA.text}\\` button should select the background and open the media tab in the library`, async () => {\n      // change the library pane so media isn't visible\n      await fixture.events.click(fixture.editor.library.shapesTab);\n\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.insertBackgroundMediaButton\n      );\n\n      expect(fixture.editor.library.media).not.toBeNull();\n      expect(document.activeElement).toEqual(fixture.editor.library.mediaTab);\n    });\n\n    it(`clicking the \\`${ACTIONS.INSERT_TEXT.text}\\` button should select the background, open the text tab in the library and insert the default text`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.insertTextButton\n      );\n      await fixture.events.sleep(100);\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n      expect(\n        fixture.editor.sidebar.designPanel.selectionSection\n      ).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.canvas.framesLayer.frames[1].node\n      );\n    });\n\n    it('should allow clicking multiple actions', async () => {\n      expect(fixture.editor.library.media).not.toBeNull();\n\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.pageBackground).not.toBeNull();\n\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.insertTextButton\n      );\n\n      expect(\n        fixture.editor.sidebar.designPanel.selectionSection\n      ).not.toBeNull();\n    });\n  });\n\n  describe('foreground image selected', () => {\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const foregroundImage = await fixture.act(() =>\n        insertElement('image', {\n          x: 0,\n          y: 0,\n          width: 640 / 2,\n          height: 529 / 2,\n          resource: {\n            id: 10,\n            type: 'image',\n            mimeType: 'image/jpg',\n            src: 'http://localhost:9876/__static__/earth.jpg',\n            alt: 'earth',\n            width: 640,\n            height: 529,\n            baseColor: '#734727',\n          },\n        })\n      );\n\n      await clickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(foregroundImage.id).node\n      );\n    });\n\n    it(`should replace the media using the \\`${ACTIONS.REPLACE_MEDIA.text}\\` quick action`, async () => {\n      // track initial media\n      const { initialCurrentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          initialCurrentPage: state.currentPage,\n        }))\n      );\n\n      const { resource: initialResource, ...initialElement } =\n        initialCurrentPage.elements.find((element) => !element.isBackground);\n\n      // click replace media button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.replaceMediaButton\n      );\n\n      // fixture replaces media automatically\n      // verify that media was replaced\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      const { resource: finalResource, ...finalElement } =\n        currentPage.elements.find((element) => !element.isBackground);\n\n      // everything should be the same except the resource\n      expect(initialElement).toEqual(finalElement);\n      expect(initialResource).not.toEqual(finalResource);\n      expect(finalElement.type).toEqual(finalResource.type);\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_ANIMATION.text}\\` button should select the animation panel and focus the dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_LINK.text}\\` button should select the link panel and focus the input`, async () => {\n      // click quick menu button\n\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addLinkButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.link.address\n      );\n    });\n\n    it(`should add animations and filters to the foreground image, click the \\`${ACTIONS.RESET_ELEMENT.text}\\` button, clear the animations and filters, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to image\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Pulse\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(\n        async () => {\n          await fixture.events.click(\n            fixture.screen.getByRole('button', { name: 'Stop Page Animations' })\n          );\n        },\n        { timeout: 4000 }\n      );\n\n      // apply filter\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.selectionSection\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.filters.linear\n      );\n\n      // verify the animations and styles were added\n      let originalAnimations = [];\n      let originalSelectedElement = null;\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n            selectedElement: state.selectedElements[0],\n          }))\n        );\n        ({\n          animations: originalAnimations,\n          selectedElement: originalSelectedElement,\n        } = story);\n\n        if (!originalSelectedElement) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalSelectedElement.overlay.type).toBe('linear');\n        expect(originalAnimations.length).toEqual(1);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations or styles\n      const { animations, selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(selectedElement.overlay).toBeNull();\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n        timeout: 4000,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations and styles match original animation\n      const {\n        animations: revertedAnimations,\n        selectedElement: revertedSelectedElement,\n      } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(revertedSelectedElement.overlay.type).toEqual(\n        originalSelectedElement.overlay.type\n      );\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n\n  describe('shape selected', () => {\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const shapeElement = await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: {\n            color: {\n              r: 203,\n              g: 103,\n              b: 103,\n            },\n          },\n          type: 'shape',\n          x: 48,\n          y: 0,\n          width: 148,\n          height: 137,\n          scale: 100,\n          focalX: 50,\n          focalY: 50,\n          mask: {\n            type: 'heart',\n          },\n          id: 'cb89750a-3ffd-4876-8ed9-d715c553e05b',\n          link: null,\n        })\n      );\n\n      await clickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(shapeElement.id).node\n      );\n    });\n\n    it(`should select the \\`${ACTIONS.ADD_ANIMATION.text}\\` button and select the animation panel and focus the dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`should click the \\`${ACTIONS.ADD_LINK.text}\\` button and select the link panel and focus the input`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addLinkButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.link.address\n      );\n    });\n\n    it(`should add animations and filters to the shape, click the \\`${ACTIONS.RESET_ELEMENT.text}\\` button, clear the animations and filters, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to shape\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Pulse\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(async () => {\n        await fixture.events.click(\n          await fixture.screen.findByRole('button', {\n            name: 'Stop Page Animations',\n          })\n        );\n      });\n\n      // add styles to the shape\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.selectionSection\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.sizePosition.opacity\n      );\n      await fixture.events.keyboard.type('99');\n      await fixture.events.keyboard.press('Enter');\n\n      // verify the animations and styles were added\n      let originalAnimations = [];\n      let originalSelectedElement = null;\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n            selectedElement: state.selectedElements[0],\n          }))\n        );\n        ({\n          animations: originalAnimations,\n          selectedElement: originalSelectedElement,\n        } = story);\n\n        if (!originalSelectedElement) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalAnimations.length).toEqual(1);\n        expect(originalSelectedElement.opacity).toEqual(99);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations or styles\n      const { animations, selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(selectedElement.opacity).toEqual(100);\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n        timeout: 4000,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations match original animation\n      const {\n        animations: revertedAnimations,\n        selectedElement: revertedSelectedElement,\n      } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(revertedSelectedElement.opacity).toEqual(\n        originalSelectedElement.opacity\n      );\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n\n  describe('background image selected', () => {\n    beforeEach(async () => {\n      await addBackgroundImage(0);\n\n      const {\n        state: {\n          currentPage: {\n            elements: [{ id }],\n          },\n        },\n      } = await fixture.renderHook(() => useStory());\n\n      const canvasElementWrapperId = fixture.querySelector(\n        `[data-testid=\"safezone\"] [data-element-id=\"${id}\"]`\n      );\n\n      await fixture.events.click(canvasElementWrapperId);\n    });\n\n    it(`should replace the background media when clicking the \\`${ACTIONS.REPLACE_BACKGROUND_MEDIA.text}\\` action`, async () => {\n      // track initial media\n      const { initialCurrentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          initialCurrentPage: state.currentPage,\n        }))\n      );\n\n      const { resource: initialResource, ...initialElement } =\n        initialCurrentPage.elements.find((element) => element.isBackground);\n\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.replaceBackgroundMediaButton\n      );\n\n      // verify that media was replaced\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      const { resource: finalResource, ...finalElement } =\n        currentPage.elements.find((element) => element.isBackground);\n\n      // everything should be the same except the resource\n      expect(initialElement).toEqual(finalElement);\n      expect(initialResource).not.toEqual(finalResource);\n      expect(finalElement.type).toEqual(finalResource.type);\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_ANIMATION.text}\\` button should select the animation panel and focus the dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`should add animations and filters to the background image, click the \\`${ACTIONS.RESET_ELEMENT.text}\\` button, clear the animations and filters, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to background image\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Pan and Zoom\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(async () => {\n        await fixture.events.click(\n          await fixture.screen.findByRole('button', {\n            name: 'Stop Page Animations',\n          })\n        );\n      });\n\n      // apply filter\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.selectionSection\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.filters.linear\n      );\n\n      // verify the styles were added\n      let originalAnimations = [];\n      let originalSelectedElement = null;\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n            selectedElement: state.selectedElements[0],\n          }))\n        );\n        ({\n          animations: originalAnimations,\n          selectedElement: originalSelectedElement,\n        } = story);\n\n        if (!originalSelectedElement) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalSelectedElement.overlay.type).toBe('linear');\n        expect(originalAnimations.length).toEqual(1);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations or styles\n      const { animations, selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(selectedElement.overlay).toBeNull();\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations match original animation\n      const {\n        animations: revertedAnimations,\n        selectedElement: revertedSelectedElement,\n      } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(revertedSelectedElement.overlay.type).toEqual(\n        originalSelectedElement.overlay.type\n      );\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n\n  async function addBackgroundImage(index) {\n    // Drag image to canvas corner to set as background\n    const image = fixture.editor.library.media.item(index);\n    const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n\n    await fixture.events.mouse.seq(({ down, moveRel, up }) => [\n      moveRel(image, 20, 20),\n      down(),\n      moveRel(canvas, 10, 10),\n      up(),\n    ]);\n  }\n\n  describe('text element selected', () => {\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'Hello world!',\n          x: 10,\n          y: 20,\n          width: 400,\n        })\n      );\n\n      await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_ANIMATION.text}\\` button should select the animation panel and focus the dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_LINK.text}\\` button should select the link panel and focus the input`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addLinkButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.link.address\n      );\n    });\n\n    it(`should add animations to the text, click the \\`${ACTIONS.RESET_ELEMENT.text}\\` button, clear the animations, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to text\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Drop\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(async () => {\n        await fixture.events.click(\n          await fixture.screen.findByRole('button', {\n            name: 'Stop Page Animations',\n          })\n        );\n      });\n\n      // verify animations were added\n      let originalAnimations = [];\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n          }))\n        );\n        ({ animations: originalAnimations } = story);\n\n        if (originalAnimations.length === 0) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalAnimations.length).toEqual(1);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations\n      const { animations } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations match original animation\n      const { animations: revertedAnimations } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n\n  describe('video selected', () => {\n    beforeEach(async () => {\n      const videoElement = {\n        resource: {\n          type: 'video',\n          mimeType: 'video/webm',\n          creationDate: '2021-05-21T00:09:18',\n          src: 'http://localhost:8899/wp-content/uploads/2021/05/small-video-10.webm',\n          width: 560,\n          height: 320,\n          poster:\n            'http://localhost:8899/wp-content/uploads/2021/05/small-video-poster-10.jpg',\n          posterId: 11,\n          id: 10,\n          length: 6,\n          lengthFormatted: '0:06',\n          alt: 'small-video',\n          sizes: {},\n          isOptimized: false,\n          baseColor: '#734727',\n        },\n        controls: false,\n        loop: false,\n        autoPlay: true,\n        tracks: [],\n        type: 'video',\n        x: 66,\n        y: 229,\n        width: 280,\n        height: 160,\n        id: '6e7f5de8-7793-4aef-8835-c1d32477b4e0',\n      };\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const foregroundVideo = await fixture.act(() =>\n        insertElement('video', videoElement)\n      );\n\n      await clickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(foregroundVideo.id).node\n      );\n    });\n\n    it(`should replace the media using the \\`${ACTIONS.REPLACE_MEDIA.text}\\` quick action`, async () => {\n      // track initial media\n      const { initialCurrentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          initialCurrentPage: state.currentPage,\n        }))\n      );\n\n      const {\n        resource: initialResource,\n        type: initialType,\n        ...initialElement\n      } = initialCurrentPage.elements.find((element) => !element.isBackground);\n\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.replaceMediaButton\n      );\n\n      // verify that media was replaced\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      const {\n        resource: finalResource,\n        type: finalType,\n        ...finalElement\n      } = currentPage.elements.find((element) => !element.isBackground);\n\n      // everything should be the same except the resource\n      expect(initialElement).toEqual(finalElement);\n      expect(initialResource).not.toEqual(finalResource);\n\n      // MediaUpload fixture injects an image. New media should not have the same type\n      expect(initialType).not.toEqual(finalType);\n      expect(finalType).toEqual(finalResource.type);\n    });\n\n    it(`should click the \\`${ACTIONS.ADD_ANIMATION.text}\\` button and open the animation panel and focus the animation dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`should click the \\`${ACTIONS.ADD_LINK.text}\\` button and select the link panel and focus the input`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addLinkButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.link.address\n      );\n    });\n\n    it(`should click the \\`${ACTIONS.ADD_CAPTIONS.text}\\` button and open the captions panel and focus the add captions input`, async () => {\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addCaptionsButton\n      );\n      expect(\n        fixture.editor.sidebar.designPanel.captions.addCaptionsButton\n      ).not.toBeNull();\n    });\n\n    it(`should add animations and filters to the video, click the \\`${ACTIONS.RESET_ELEMENT.text}\\` button, clear the animations and filters, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to video\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Drop\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(async () => {\n        await fixture.events.click(\n          await fixture.screen.findByRole('button', {\n            name: 'Stop Page Animations',\n          })\n        );\n      });\n\n      // apply filter\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.selectionSection\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.filters.linear\n      );\n\n      // verify the animations and styles were added\n      let originalAnimations = [];\n      let originalSelectedElement = null;\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n            selectedElement: state.selectedElements[0],\n          }))\n        );\n        ({\n          animations: originalAnimations,\n          selectedElement: originalSelectedElement,\n        } = story);\n\n        if (!originalSelectedElement) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalSelectedElement.overlay.type).toBe('linear');\n        expect(originalAnimations.length).toEqual(1);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations or styles\n      const { animations, selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(selectedElement.overlay).toBeNull();\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations and styles match original animation\n      const {\n        animations: revertedAnimations,\n        selectedElement: revertedSelectedElement,\n      } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(revertedSelectedElement.overlay.type).toEqual(\n        originalSelectedElement.overlay.type\n      );\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n\n  describe('sticker selected', () => {\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const sticker = await fixture.act(() =>\n        insertElement('sticker', {\n          border: null,\n          borderRadius: null,\n          flip: { vertical: false, horizontal: false },\n          focalX: 50,\n          focalY: 50,\n          height: 137,\n          id: '41262f75-7671-4ff2-92ef-5bbafc7b616a',\n          lockAspectRatio: true,\n          opacity: 100,\n          rotationAngle: 0,\n          scale: 100,\n          sticker: { type: 'diyInstagramIcon' },\n          type: 'sticker',\n          width: 137,\n          x: 227,\n          y: 0,\n        })\n      );\n\n      await clickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(sticker.id).node\n      );\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_ANIMATION.text}\\` button should select the animation panel and focus the dropdown`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addAnimationButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.animation).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.animation.effectChooser\n      );\n    });\n\n    it(`clicking the \\`${ACTIONS.ADD_LINK.text}\\` button should select the link panel and focus the input`, async () => {\n      // click quick menu button\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.addLinkButton\n      );\n\n      expect(fixture.editor.sidebar.designPanel.link).not.toBeNull();\n\n      expect(document.activeElement).toEqual(\n        fixture.editor.sidebar.designPanel.link.address\n      );\n    });\n\n    it(`Clicking the \\`${ACTIONS.RESET_ELEMENT.text}\\` button should clear the animations and filters, then click Undo and reapply the animations and filters.`, async () => {\n      // quick action should not be present if there are no animations yet\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // add animation to image\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // animation\n      const animation = fixture.screen.getByRole('option', {\n        name: '\"Pulse\" Effect',\n      });\n\n      // apply animation to element\n      await fixture.events.click(animation, { clickCount: 1 });\n\n      // the bot clicks the clear button too fast\n      // the animation does not get removed if it is clicked before it stops playing\n      // click \"stop playing\" and test the animations have been applied\n      await waitFor(async () => {\n        await fixture.events.click(\n          await fixture.screen.findByRole('button', {\n            name: 'Stop Page Animations',\n          })\n        );\n      });\n\n      // apply opacity\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.selectionSection\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.sizePosition.opacity\n      );\n      await fixture.events.keyboard.type('40');\n      await fixture.events.keyboard.press('Enter');\n\n      // verify the animations and styles were added\n      let originalAnimations = [];\n      let originalSelectedElement = null;\n      await waitFor(async () => {\n        const story = await fixture.renderHook(() =>\n          useStory(({ state }) => ({\n            animations: state.pages[1].animations,\n            selectedElement: state.selectedElements[0],\n          }))\n        );\n        ({\n          animations: originalAnimations,\n          selectedElement: originalSelectedElement,\n        } = story);\n\n        if (!originalSelectedElement) {\n          throw new Error('story not ready');\n        }\n\n        expect(originalSelectedElement.opacity).toBe(40);\n        expect(originalAnimations.length).toEqual(1);\n      });\n\n      // reset the element\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      );\n\n      // verify that element has no animations or styles\n      const { animations, selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(animations.length).toBe(0);\n      expect(selectedElement.opacity).toBe(100);\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeNull();\n\n      // wait for the undo button to appear\n      await fixture.screen.findByRole('button', {\n        name: /^Undo$/,\n        hidden: true,\n      });\n      // click `undo` button on snackbar\n      await fixture.events.click(\n        await fixture.screen.findByRole('button', {\n          name: /^Undo$/,\n          hidden: true,\n        })\n      );\n\n      // Verify that new animations and styles match original animation\n      const {\n        animations: revertedAnimations,\n        selectedElement: revertedSelectedElement,\n      } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[1].animations,\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n      expect(revertedAnimations.length).toBe(1);\n      expect(revertedAnimations[0]).toEqual(originalAnimations[0]);\n      expect(revertedSelectedElement.opacity).toEqual(\n        originalSelectedElement.opacity\n      );\n      expect(\n        fixture.editor.canvas.quickActionMenu.resetElementButton\n      ).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/rightClickMenu.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { ATTRIBUTES_TO_COPY } from '../../../app/story/useStoryReducer/reducers/copySelectedElement';\nimport { Fixture } from '../../../karma';\nimport objectPick from '../../../utils/objectPick';\nimport useInsertElement from '../useInsertElement';\n\ndescribe('Right Click Menu integration', () => {\n  let fixture;\n  let insertElement;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.events.click(fixture.editor.footer.layerPanel.togglePanel);\n\n    insertElement = await fixture.renderHook(() => useInsertElement());\n\n    // Remove empty state message by changing the background\n    await fixture.events.click(\n      fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n    );\n    await fixture.events.keyboard.type('ef');\n    await fixture.events.keyboard.press('Tab');\n  });\n\n  afterEach(async () => {\n    await closeRightClickMenu();\n    fixture.restore();\n  });\n\n  function rightClickMenu() {\n    return within(\n      fixture.screen.getByRole('dialog', {\n        name: 'Context Menu for the selected element',\n      })\n    ).getByRole('menu');\n  }\n\n  function sendBackward() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Send Backward/i,\n    });\n  }\n\n  function sendToBack() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Send to Back/i,\n    });\n  }\n\n  function bringForward() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Bring Forward/i,\n    });\n  }\n\n  function bringToFront() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Bring to Front/i,\n    });\n  }\n\n  function selectLayerButton() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Select Layer/i,\n    });\n  }\n\n  function selectHeadingLevel() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Heading Level/i,\n    });\n  }\n\n  function setAsPageBackground() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Set as page Background/i,\n    });\n  }\n\n  function scaleAndCropImage() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Scale & Crop Image/i,\n    });\n  }\n\n  function scaleAndCropBackgroundImage() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Scale & Crop Background Image/i,\n    });\n  }\n\n  function scaleAndCropVideo() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Scale & Crop Video/i,\n    });\n  }\n\n  function scaleAndCropBackgroundVideo() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Scale & Crop Background Video/i,\n    });\n  }\n\n  function duplicatePage() {\n    const menu = rightClickMenu();\n\n    return within(menu).queryByRole('menuitem', {\n      name: /^Duplicate Page/i,\n    });\n  }\n\n  function deletePage() {\n    const menu = rightClickMenu();\n\n    return within(menu).queryByRole('menuitem', {\n      name: /^Delete Page/i,\n    });\n  }\n\n  function copyImageStyles() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Copy Image Styles/i,\n    });\n  }\n\n  function pasteImageStyles() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Paste Image Styles/i,\n    });\n  }\n\n  function detachImageFromBackground() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Detach Image From Background/i,\n    });\n  }\n\n  function copyStyles() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Copy Style/i,\n    });\n  }\n\n  function pasteStyles() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Paste Style/i,\n    });\n  }\n\n  function addToSavedStyles() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Add Style to/i,\n    });\n  }\n\n  function addToSavedColors() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Add Color to/i,\n    });\n  }\n\n  function useShapeAsMask() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Use Shape as a Mask/i,\n    });\n  }\n\n  function removeShapeMask() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Unmask/i,\n    });\n  }\n\n  function duplicateElements() {\n    return fixture.screen.getByRole('menuitem', {\n      name: /^Duplicate Element/i,\n    });\n  }\n\n  function getMenuItemByName(name) {\n    return fixture.screen.getByRole('menuitem', {\n      name,\n    });\n  }\n\n  /**\n   * Closes the browser right click menu by left clicking\n   */\n  async function closeRightClickMenu() {\n    const framesLayer = fixture.screen.getByTestId('FramesLayer');\n    // close browser default (only shows in puppeteer tests)\n    const rect = framesLayer.getBoundingClientRect();\n    await fixture.events.mouse.click(rect.left + 1, rect.top + 1);\n    // close right click menu\n    await fixture.events.mouse.click(rect.left + 1, rect.top + 1);\n  }\n\n  /**\n   * Right click on the target in the fixture.\n   *\n   * @param {Object} target The element to be clicked.\n   */\n  async function rightClickOnTarget(target) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2, {\n      button: 'right',\n    });\n  }\n\n  /**\n   * Click on the target in the fixture.\n   *\n   * @param {Object} target The element to be clicked.\n   * @param {string} key The key to be held down while clicking\n   */\n  async function clickOnTarget(target, key = false) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    if (key) {\n      await fixture.events.keyboard.down(key);\n    }\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n    if (key) {\n      await fixture.events.keyboard.up(key);\n    }\n  }\n\n  /**\n   * Add text to canvas\n   *\n   * @param {Object} textPartial text element partial\n   * @return {Object} the text element\n   */\n  function addText(textPartial = {}) {\n    return fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: 'Hello world!',\n        x: 10,\n        y: 20,\n        width: 400,\n        ...textPartial,\n      })\n    );\n  }\n\n  /**\n   * Add earth image to canvas\n   *\n   * @return {Object} the image element\n   */\n  function addEarthImage() {\n    return fixture.act(() =>\n      insertElement('image', {\n        x: 200,\n        y: 0,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          id: 10,\n          type: 'image',\n          mimeType: 'image/jpg',\n          src: 'http://localhost:9876/__static__/earth.jpg',\n          alt: 'Earth',\n          width: 640,\n          height: 529,\n          baseColor: '#734727',\n        },\n      })\n    );\n  }\n\n  /**\n   * Add ranger image to canvas\n   *\n   * @return {Object} the image element\n   */\n  function addRangerImage() {\n    return fixture.act(() =>\n      insertElement('image', {\n        x: 50,\n        y: 200,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          id: 6,\n          type: 'image',\n          mimeType: 'image/jpg',\n          src: 'http://localhost:9876/__static__/ranger9.png',\n          alt: 'Ranger',\n          width: 640,\n          height: 480,\n        },\n      })\n    );\n  }\n\n  /**\n   * Add video to canvas\n   *\n   * @return {Object} the video element\n   */\n  function addVideo() {\n    return fixture.act(() =>\n      insertElement('video', {\n        x: 0,\n        y: 0,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          width: 640,\n          height: 529,\n          type: 'video',\n          mimeType: 'video/mp4',\n          src: 'http://localhost:9876/__static__/beach.mp4',\n          alt: 'beach',\n        },\n      })\n    );\n  }\n\n  const getSelection = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  };\n\n  /**\n   * Add shape to canvas\n   *\n   * @param {Object} shapePartial Object with shape properties to override defaults.\n   * @return {Object} the shape element\n   */\n  function addShape(shapePartial = {}) {\n    return fixture.act(() =>\n      insertElement('shape', {\n        type: 'shape',\n        x: 48,\n        y: 0,\n        width: 148,\n        height: 137,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        mask: {\n          type: 'heart',\n        },\n        link: null,\n        ...shapePartial,\n      })\n    );\n  }\n\n  /**\n   * Add product to canvas\n   *\n   * @param {Object} productPartial Object with product properties to override defaults.\n   * @return {Object} the product element\n   */\n  function addProduct(productPartial = {}) {\n    return fixture.act(() =>\n      insertElement('product', {\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 50,\n        product: {\n          productId: 'kt-38',\n          productTitle: 'Logo Collection',\n        },\n        ...productPartial,\n      })\n    );\n  }\n\n  const verifyPageDuplicated = (pages = []) => {\n    expect(pages[0].backgroundColor).toEqual(pages[1].backgroundColor);\n    pages[0].elements.forEach((elem, index) => {\n      // ids won't match\n      const { id, ...originalElement } = elem;\n      const { id: newId, ...newElement } = pages[1].elements[index];\n\n      expect(originalElement).toEqual(newElement);\n    });\n  };\n\n  /**\n   * Verifies that one element is a duplicate of the other\n   *\n   * @param {Object} element1 The original element\n   * @param {Object} element2 The duplicate element\n   */\n  function verifyElementDuplicated(element1, element2) {\n    for (const property in element1) {\n      if (!['x', 'y', 'id'].includes(property)) {\n        expect(element1[property]).toEqual(element2[property]);\n      } else {\n        expect(element1[property]).not.toEqual(element2[property]);\n      }\n    }\n  }\n\n  describe('menu visibility', () => {\n    it('right clicking on the canvas should open the custom right click menu', async () => {\n      await fixture.events.click(fixture.editor.canvas.framesLayer.container, {\n        button: 'right',\n      });\n\n      expect(rightClickMenu()).not.toBeNull();\n    });\n\n    // NOTE: this opens the real right click menu, which can't be closed\n    // after it is opened :grimacing:.\n    it('right clicking away from the canvas should not open the custom right click menu', async () => {\n      // right click outside canvas\n      await fixture.events.click(\n        fixture.editor.canvas.pageActions.duplicatePage,\n        {\n          button: 'right',\n        }\n      );\n      expect(\n        fixture.screen.queryByRole('menu', {\n          name: 'Context Menu for the selected element',\n        })\n      ).toBeNull();\n    });\n\n    it('right clicking a layer in the layer panel should open the custom right click menu', async () => {\n      await addEarthImage();\n\n      await fixture.events.click(fixture.editor.footer.layerPanel.layers[0], {\n        button: 'right',\n      });\n\n      expect(rightClickMenu()).not.toBeNull();\n    });\n\n    it('should open and close the context menu using keyboard shortcuts', async () => {\n      // add an element to the page\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        const node = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!node) {\n          throw new Error('node not ready');\n        }\n        expect(node).toBeTruthy();\n      });\n      const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n\n      // only possible if element in canvas is focused\n      await fixture.events.focus(frame1);\n\n      // open right click menu\n      await fixture.events.keyboard.shortcut('mod+alt+shift+m');\n\n      expect(\n        fixture.screen.queryByRole('dialog', {\n          name: 'Context Menu for the selected element',\n        })\n      ).not.toBeNull();\n\n      // close right click menu\n      await fixture.events.keyboard.press('esc');\n      expect(\n        fixture.screen.queryByRole('dialog', {\n          name: 'Context Menu for the selected element',\n        })\n      ).toBeNull();\n    });\n  });\n\n  describe('Right click menu: Select Layer', () => {\n    it('should allow selecting a layer from the point where the menu was opened from', async () => {\n      // Add a Triangle and an image to the same place.\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.events.sleep(100);\n      const mediaItem = fixture.editor.library.media.item(0);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n      // Add a Text a different place.\n      await addText({ x: 200 });\n\n      // Right-click on the top-left corner of the triangle.\n      const triangle = fixture.editor.canvas.framesLayer.frames[2].node;\n      const { x, y } = triangle.getBoundingClientRect();\n      await fixture.events.mouse.click(x + 10, y + 10, {\n        button: 'right',\n      });\n\n      // Open the Select Layer submenu.\n      await fixture.events.click(selectLayerButton());\n      // Verify if displays Background, Triangle, Image as options but not the text.\n      expect(getMenuItemByName('Background')).not.toBeNull();\n      expect(getMenuItemByName('Triangle')).not.toBeNull();\n      expect(getMenuItemByName('blue-marble')).not.toBeNull();\n      expect(() =>\n        getMenuItemByName(\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'\n        )\n      ).toThrow();\n\n      // Verify that clicking on the background button selects background.\n      await fixture.events.click(getMenuItemByName('Background'));\n      const [element] = await getSelection();\n      expect(element.isDefaultBackground).toBeTrue();\n    });\n\n    it('should not display the option to select layer when opening from the layer panel', async () => {\n      await addEarthImage();\n\n      await fixture.events.click(fixture.editor.footer.layerPanel.layers[0], {\n        button: 'right',\n      });\n\n      expect(() => selectLayerButton()).toThrow();\n    });\n  });\n\n  describe('right click menu: shared foreground and background media actions', () => {\n    it('should set an image as the background and detach an image from the background', async () => {\n      const earthImage = await addEarthImage();\n\n      // right click image\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // set image as page background\n      await fixture.events.click(setAsPageBackground());\n\n      // verify the image has been set as the background\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      expect(currentPage.elements.length).toBe(1);\n      expect(currentPage.elements[0].isBackground).toBeTrue();\n\n      // right click background image\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // remove from image background\n      await fixture.events.click(detachImageFromBackground());\n\n      // verify the image has been removed from the background\n      const { currentPage: newCurrentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      expect(newCurrentPage.elements.length).toBe(2);\n      expect(\n        newCurrentPage.elements.find((element) => element.id === earthImage.id)\n          .isBackground\n      ).toBe(undefined);\n    });\n\n    it('should let a user scale and crop image', async () => {\n      const earthImage = await addEarthImage();\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // foreground: click 'scale and crop image' button\n      await fixture.events.click(scaleAndCropImage());\n\n      // Verify element is being edited\n      expect(fixture.screen.getByTestId('edit-panel-slider')).toBeDefined();\n\n      // escape edit mode\n      await fixture.events.keyboard.press('Esc');\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // set video as page background\n      await fixture.events.click(setAsPageBackground());\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // background: click 'scale and crop image' button\n      await fixture.events.click(scaleAndCropBackgroundImage());\n\n      // Verify element is being edited\n      expect(fixture.screen.getByTestId('edit-panel-slider')).toBeDefined();\n    });\n\n    it('should let a user scale and crop video', async () => {\n      const video = await addVideo();\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(video.id).node\n      );\n\n      // foreground: click 'scale and crop video' button\n      await fixture.events.click(scaleAndCropVideo());\n\n      // Verify element is being edited\n      expect(fixture.screen.getByTestId('edit-panel-slider')).toBeDefined();\n\n      // escape edit mode\n      await fixture.events.keyboard.press('Esc');\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(video.id).node\n      );\n\n      // set video as page background\n      await fixture.events.click(setAsPageBackground());\n\n      // right click video\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(video.id).node\n      );\n\n      // background: click 'scale and crop video' button\n      await fixture.events.click(scaleAndCropBackgroundVideo());\n\n      // Verify element is being edited\n      expect(fixture.screen.getByTestId('edit-panel-slider')).toBeDefined();\n    });\n  });\n\n  describe('right click menu: page/background with no media', () => {\n    it(\"should duplicate the current page when clicking 'Duplicate page'\", async () => {\n      await addEarthImage();\n      await addText();\n\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n      const backgroundElement = currentPage.elements.find(\n        (element) => element.isBackground\n      );\n\n      // duplicate page\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(backgroundElement.id).node\n      );\n      await fixture.events.click(duplicatePage());\n\n      // verify duplication of all content\n      const { pages } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          pages: state.pages,\n        }))\n      );\n\n      verifyPageDuplicated(pages);\n    });\n\n    it('should delete the current page when clicking the \"Delete Page\" button', async () => {\n      // duplicate page\n      await fixture.events.click(fixture.editor.canvas.framesLayer.container, {\n        button: 'right',\n      });\n      await fixture.events.click(duplicatePage());\n\n      // insert elements on new page\n      await addEarthImage();\n      await addText();\n\n      // delete page\n      await fixture.events.click(fixture.editor.canvas.framesLayer.container, {\n        button: 'right',\n      });\n      await fixture.events.click(deletePage());\n\n      // verify the correct page was deleted\n      const { pages } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          pages: state.pages,\n        }))\n      );\n\n      expect(pages.length).toBe(1);\n      expect(pages[0].elements.length).toBe(1);\n      expect(pages[0].elements[0].isBackground).toBe(true);\n    });\n  });\n\n  describe('right click menu: foreground media', () => {\n    it('should duplicate the element', async () => {\n      const image = await addEarthImage();\n\n      const imageFrame = fixture.editor.canvas.framesLayer.frame(image.id).node;\n\n      // multiple elements should be selected\n      const { initialElements, selectedElements } = await fixture.renderHook(\n        () =>\n          useStory(({ state }) => ({\n            selectedElements: state.selectedElements,\n            initialElements: state.currentPage.elements,\n          }))\n      );\n\n      expect(selectedElements.length).toBe(1);\n      expect(initialElements.length).toBe(2);\n\n      // open right click menu\n      await rightClickOnTarget(imageFrame);\n\n      // duplicate elements\n      await fixture.events.click(duplicateElements());\n\n      // verify elements were duplicated\n      const { finalElements } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          finalElements: state.currentPage.elements,\n        }))\n      );\n\n      expect(finalElements.length).toBe(\n        initialElements.length + selectedElements.length\n      );\n\n      // verify image duplication\n      const imageElements = finalElements.filter(\n        (element) => element.type === 'image'\n      );\n      expect(imageElements.length).toBe(2);\n      verifyElementDuplicated(imageElements[0], imageElements[1]);\n    });\n\n    it('should be able to move media forwards and backwards when possible', async () => {\n      const earthImage = await addEarthImage();\n\n      // right click image\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n      );\n\n      // movement buttons should be disabled\n      expect(sendBackward().disabled).toBeTrue();\n      expect(sendToBack().disabled).toBeTrue();\n      expect(bringForward().disabled).toBeTrue();\n      expect(bringToFront().disabled).toBeTrue();\n\n      await closeRightClickMenu();\n\n      // add more elements to enable movement buttons\n      await addVideo();\n      const rangerImage = await addRangerImage();\n\n      // right click image\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n      );\n\n      // verify multiple layers\n      expect(fixture.editor.footer.layerPanel.layers.length).toBe(4);\n      expect(fixture.editor.footer.layerPanel.layers[2].textContent).toContain(\n        'Earth'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[1].textContent).toContain(\n        'beach'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[0].textContent).toContain(\n        'Ranger'\n      );\n\n      // More than one layer so some movement buttons will be enabled\n      expect(sendBackward().disabled).toBeFalse();\n      expect(sendToBack().disabled).toBeFalse();\n      expect(bringForward().disabled).toBeTrue();\n      expect(bringToFront().disabled).toBeTrue();\n\n      // Move image with 'Send backward'\n      await fixture.events.click(sendBackward());\n\n      // verify new layer order\n      expect(fixture.editor.footer.layerPanel.layers[2].textContent).toContain(\n        'Earth'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[1].textContent).toContain(\n        'Ranger'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[0].textContent).toContain(\n        'beach'\n      );\n\n      // right click image\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n      );\n\n      // verify all buttons are enabled now that there\n      // are layers above and below\n      expect(sendBackward().disabled).toBeFalse();\n      expect(sendToBack().disabled).toBeFalse();\n      expect(bringForward().disabled).toBeFalse();\n      expect(bringToFront().disabled).toBeFalse();\n\n      // Move image with 'Bring forward' button\n      await fixture.events.click(bringForward());\n\n      expect(fixture.editor.footer.layerPanel.layers[2].textContent).toContain(\n        'Earth'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[1].textContent).toContain(\n        'beach'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[0].textContent).toContain(\n        'Ranger'\n      );\n\n      // Move image all the way to back\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n      );\n      await fixture.events.click(sendToBack());\n\n      // verify positioning\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n      );\n      expect(fixture.editor.footer.layerPanel.layers[2].textContent).toContain(\n        'Ranger'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[1].textContent).toContain(\n        'Earth'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[0].textContent).toContain(\n        'beach'\n      );\n\n      // verify 'back' buttons are disabled since ranger image is under everything\n      // except the background\n      expect(sendBackward().disabled).toBeTrue();\n      expect(sendToBack().disabled).toBeTrue();\n      expect(bringForward().disabled).toBeFalse();\n      expect(bringToFront().disabled).toBeFalse();\n\n      // Move image all the way to the front\n      await fixture.events.click(bringToFront());\n\n      // verify positioning\n      expect(fixture.editor.footer.layerPanel.layers[2].textContent).toContain(\n        'Earth'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[1].textContent).toContain(\n        'beach'\n      );\n      expect(fixture.editor.footer.layerPanel.layers[0].textContent).toContain(\n        'Ranger'\n      );\n\n      // verify 'forward' buttons are disabled since ranger image is under everything\n      // except the background\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n      );\n      expect(sendBackward().disabled).toBeFalse();\n      expect(sendToBack().disabled).toBeFalse();\n      expect(bringForward().disabled).toBeTrue();\n      expect(bringToFront().disabled).toBeTrue();\n    });\n\n    describe('right click menu: copying and pasting styles', () => {\n      it('should copy and paste styles', async () => {\n        // #11321 adding/editing animations on the first page is disabled\n        await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n        const earthImage = await addEarthImage();\n        const rangerImage = await addRangerImage();\n\n        // select earth image\n        await fixture.events.click(\n          fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n        );\n\n        // add animation\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.animationSection\n        );\n        const effectChooserToggle =\n          fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n        await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n        // animation\n        const animation = fixture.screen.getByRole('option', {\n          name: '\"Pulse\" Effect',\n        });\n\n        // apply animation to element\n        await fixture.events.click(animation, { clickCount: 1 });\n\n        // the bot clicks the clear button too fast\n        // the animation does not get removed if it is clicked before it stops playing\n        // click \"stop playing\" and test the animations have been applied\n        await waitFor(\n          async () => {\n            await fixture.events.click(\n              fixture.screen.getByRole('button', {\n                name: 'Stop Page Animations',\n              })\n            );\n          },\n          { timeout: 4000 }\n        );\n\n        // add border\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.selectionSection\n        );\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.border.width()\n        );\n        await fixture.events.keyboard.type('20');\n\n        // add border radius\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.sizePosition.radius()\n        );\n        await fixture.events.keyboard.type('50');\n\n        // add filter\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.filters.solid\n        );\n\n        // add opacity\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.sizePosition.opacity\n        );\n        await fixture.events.keyboard.type('40');\n\n        // track initial animation\n        const { initialAnimations, initialElements } = await fixture.renderHook(\n          () =>\n            useStory(({ state }) => ({\n              initialAnimations: state.currentPage.animations,\n              initialElements: state.currentPage.elements,\n            }))\n        );\n\n        expect(initialAnimations.length).toBe(1);\n        expect(initialElements[1].id).toBe(initialAnimations[0].targets[0]);\n\n        // copy earth image styles\n        await rightClickOnTarget(\n          fixture.editor.canvas.framesLayer.frame(earthImage.id).node\n        );\n        await fixture.events.click(copyImageStyles());\n\n        // paste styles onto ranger image\n        await rightClickOnTarget(\n          fixture.editor.canvas.framesLayer.frame(rangerImage.id).node\n        );\n        await fixture.events.click(pasteImageStyles());\n\n        // verify that the styles and animations were copied and pasted\n        const { finalAnimations, finalElements } = await fixture.renderHook(\n          () =>\n            useStory(({ state }) => ({\n              finalAnimations: state.currentPage.animations,\n              finalElements: state.currentPage.elements,\n            }))\n        );\n\n        // validate copied styles\n        const images = finalElements.filter((element) => !element.isBackground);\n\n        const copiedProperties = objectPick(images[0], ATTRIBUTES_TO_COPY);\n        const pastedProperties = objectPick(images[1], ATTRIBUTES_TO_COPY);\n\n        expect(copiedProperties).toEqual(pastedProperties);\n\n        // validate copied animations\n        expect(finalAnimations.length).toEqual(2);\n        const { id: id1, targets: targets1, ...anim1 } = finalAnimations[0];\n        const { id: id2, targets: targets2, ...anim2 } = finalAnimations[1];\n\n        expect(anim1).toEqual(anim2);\n        expect(targets1).toEqual([images[0].id]);\n        expect(targets2).toEqual([images[1].id]);\n      });\n    });\n  });\n\n  describe('right click menu: text', () => {\n    it('should duplicate the element', async () => {\n      const text = await addText({\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n        fontSize: 60,\n        content: '<span style=\"color: #00ff00\">Another Text Element</span>',\n      });\n\n      const textFrame = fixture.editor.canvas.framesLayer.frame(text.id).node;\n\n      // multiple elements should be selected\n      const { initialElements, selectedElements } = await fixture.renderHook(\n        () =>\n          useStory(({ state }) => ({\n            selectedElements: state.selectedElements,\n            initialElements: state.currentPage.elements,\n          }))\n      );\n\n      expect(selectedElements.length).toBe(1);\n      expect(initialElements.length).toBe(2);\n\n      // open right click menu\n      await rightClickOnTarget(textFrame);\n\n      // duplicate elements\n      await fixture.events.click(duplicateElements());\n\n      // verify elements were duplicated\n      const { finalElements } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          finalElements: state.currentPage.elements,\n        }))\n      );\n\n      expect(finalElements.length).toBe(\n        initialElements.length + selectedElements.length\n      );\n\n      // verify text duplication\n      const textElements = finalElements.filter(\n        (element) => element.type === 'text'\n      );\n      expect(textElements.length).toBe(2);\n      verifyElementDuplicated(textElements[0], textElements[1]);\n    });\n\n    it('should not copy and paste content directly with styles', async () => {\n      const textA = await addText({\n        fontSize: 60,\n        content: '<span style=\"color: #ff0110\">Some Text Element</span>',\n        backgroundColor: { r: 10, g: 0, b: 200 },\n        lineHeight: 1.4,\n        textAlign: 'center',\n        border: {\n          left: 1,\n          right: 1,\n          top: 1,\n          bottom: 1,\n          lockedWidth: true,\n          color: {\n            color: {\n              r: 0,\n              g: 0,\n              b: 0,\n            },\n          },\n        },\n        padding: {\n          vertical: 0,\n          horizontal: 20,\n          locked: true,\n        },\n      });\n      const textB = await addText({\n        y: 300,\n        fontSize: 40,\n        content: '<span style=\"color: #10ff01\">Another Text Element</span>',\n      });\n\n      // copy text element A styles\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(textA.id).node\n      );\n      await fixture.events.click(copyStyles());\n\n      // paste text element A styles onto text element B\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(textB.id).node\n      );\n      await fixture.events.click(pasteStyles());\n\n      // verify that the styles were copied and pasted\n      const { currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          currentPage: state.currentPage,\n        }))\n      );\n\n      const textElements = currentPage.elements.filter(\n        (element) => !element.isBackground\n      );\n\n      const { content: _copiedContent, ...copiedProperties } = objectPick(\n        textElements[0],\n        ATTRIBUTES_TO_COPY\n      );\n      const { content, ...pastedProperties } = objectPick(textElements[1], [\n        ...ATTRIBUTES_TO_COPY,\n        'content',\n      ]);\n      expect(content).toBe(\n        '<span style=\"color: #ff0110\">Another Text Element</span>'\n      );\n      expect(copiedProperties).toEqual(pastedProperties);\n\n      // should update bounding box size when updating fontSize\n      expect(textB.height).not.toBe(textElements[1].height);\n    });\n\n    it('should add color to \"Saved Colors\"', async () => {\n      const text = await addText({\n        fontSize: 60,\n        content: '<span style=\"color: #00ff00\">Another Text Element</span>',\n      });\n\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(text.id).node\n      );\n      await fixture.events.click(addToSavedColors());\n\n      // verify that the global color was added\n      const { colors } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          colors: state.story.globalStoryStyles.colors,\n        }))\n      );\n      expect(colors.map(({ color }) => color)).toContain({\n        r: 0,\n        g: 255,\n        b: 0,\n      });\n    });\n\n    it('should add style to \"Saved Styles\"', async () => {\n      const text = await addText({\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n        fontSize: 60,\n        content: '<span style=\"color: #00ff00\">Another Text Element</span>',\n      });\n\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(text.id).node\n      );\n      await fixture.events.click(addToSavedStyles());\n\n      // verify that the global color was added\n      const { textStyles } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          textStyles: state.story.globalStoryStyles.textStyles,\n        }))\n      );\n      expect(textStyles).toContain({\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n        backgroundTextMode: 'NONE',\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        fontSize: 60,\n        lineHeight: 1.3,\n        padding: {\n          vertical: 0,\n          horizontal: 0,\n          locked: true,\n        },\n        textAlign: 'initial',\n        color: {\n          color: {\n            r: 0,\n            g: 255,\n            b: 0,\n          },\n        },\n        fontWeight: 400,\n        isItalic: false,\n        isUnderline: false,\n        letterSpacing: 0,\n      });\n    });\n  });\n\n  describe('right click menu: shapes', () => {\n    it('should duplicate the element', async () => {\n      const shape = await addShape({\n        backgroundColor: {\n          color: {\n            r: 203,\n            g: 103,\n            b: 103,\n          },\n        },\n      });\n      const shapeFrame = fixture.editor.canvas.framesLayer.frame(shape.id).node;\n\n      // multiple elements should be selected\n      const { initialElements, selectedElements } = await fixture.renderHook(\n        () =>\n          useStory(({ state }) => ({\n            selectedElements: state.selectedElements,\n            initialElements: state.currentPage.elements,\n          }))\n      );\n\n      expect(selectedElements.length).toBe(1);\n      expect(initialElements.length).toBe(2);\n\n      // open right click menu\n      await rightClickOnTarget(shapeFrame);\n\n      // duplicate elements\n      await fixture.events.click(duplicateElements());\n\n      // verify elements were duplicated\n      const { finalElements } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          finalElements: state.currentPage.elements,\n        }))\n      );\n\n      expect(finalElements.length).toBe(\n        initialElements.length + selectedElements.length\n      );\n\n      // verify shape duplication\n      const shapeElements = finalElements.filter(\n        (element) => element.type === 'shape' && !element.isBackground\n      );\n      expect(shapeElements.length).toBe(2);\n      verifyElementDuplicated(shapeElements[0], shapeElements[1]);\n    });\n\n    it('should add style to \"Saved Colors\"', async () => {\n      const shape = await addShape({\n        backgroundColor: {\n          color: {\n            r: 203,\n            g: 103,\n            b: 103,\n          },\n        },\n      });\n\n      // Save color to saved colors\n      await rightClickOnTarget(\n        fixture.editor.canvas.framesLayer.frame(shape.id).node\n      );\n      await fixture.events.click(addToSavedColors());\n\n      // verify that the global color was added\n      const { colors } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          colors: state.story.globalStoryStyles.colors,\n        }))\n      );\n      expect(colors).toContain({\n        color: {\n          r: 203,\n          g: 103,\n          b: 103,\n        },\n      });\n    });\n  });\n\n  describe('right click menu: multiple elements selected', () => {\n    it('should duplicate all selected elements', async () => {\n      await addText({\n        y: 300,\n        fontSize: 40,\n        content: '<span style=\"color: #10ff01\">Another Text Element</span>',\n      });\n      const image = await addEarthImage();\n      const shape = await addShape({\n        backgroundColor: {\n          color: {\n            r: 203,\n            g: 103,\n            b: 103,\n          },\n        },\n      });\n\n      const imageFrame = fixture.editor.canvas.framesLayer.frame(image.id).node;\n      const shapeFrame = fixture.editor.canvas.framesLayer.frame(shape.id).node;\n\n      // select multiple targets\n      await clickOnTarget(imageFrame);\n      await clickOnTarget(shapeFrame, 'Shift');\n\n      // multiple elements should be selected\n      const { initialElements, selectedElements } = await fixture.renderHook(\n        () =>\n          useStory(({ state }) => ({\n            selectedElements: state.selectedElements,\n            initialElements: state.currentPage.elements,\n          }))\n      );\n\n      expect(selectedElements.length).toBe(2);\n      expect(initialElements.length).toBe(4);\n\n      // open right click menu\n      await rightClickOnTarget(imageFrame);\n\n      // duplicate elements\n      await fixture.events.click(duplicateElements());\n\n      // verify elements were duplicated\n      const { finalElements } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          finalElements: state.currentPage.elements,\n        }))\n      );\n\n      expect(finalElements.length).toBe(\n        initialElements.length + selectedElements.length\n      );\n\n      // verify text element was not duplicated\n      expect(\n        finalElements.filter((element) => element.type === 'text').length\n      ).toBe(1);\n\n      // verify image duplication\n      const imageElements = finalElements.filter(\n        (element) => element.type === 'image'\n      );\n      expect(imageElements.length).toBe(2);\n      verifyElementDuplicated(imageElements[0], imageElements[1]);\n\n      // verify shape duplication\n      const shapeElements = finalElements.filter(\n        (element) => element.type === 'shape' && !element.isBackground\n      );\n      expect(shapeElements.length).toBe(2);\n      verifyElementDuplicated(shapeElements[0], shapeElements[1]);\n    });\n  });\n\n  describe('right click menu: use shape mask', () => {\n    it('adds and removes mask from image element', async () => {\n      const image = await addEarthImage();\n      const shape = await addShape({\n        backgroundColor: {\n          color: {\n            r: 203,\n            g: 103,\n            b: 103,\n          },\n        },\n      });\n\n      const imageFrame = fixture.editor.canvas.framesLayer.frame(image.id).node;\n      const shapeFrame = fixture.editor.canvas.framesLayer.frame(shape.id).node;\n\n      // select shape and image targets\n      await clickOnTarget(imageFrame);\n      await clickOnTarget(shapeFrame, 'Shift');\n\n      // multiple elements should be selected\n      const selectedElements = await fixture.renderHook(() =>\n        useStory(({ state }) => state.selectedElements)\n      );\n      expect(selectedElements.length).toBe(2);\n\n      // add shape mask\n      await rightClickOnTarget(imageFrame);\n      await fixture.events.click(useShapeAsMask());\n      await clickOnTarget(imageFrame);\n\n      const { selectedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          selectedElement: state.selectedElements[0],\n        }))\n      );\n\n      expect(selectedElement.mask.type).toEqual('heart');\n\n      // remove the mask\n      const maskedFrame = fixture.editor.canvas.framesLayer.frame(\n        selectedElement.id\n      ).node;\n      await rightClickOnTarget(maskedFrame);\n      await fixture.events.click(removeShapeMask());\n\n      // click on the now \"detached\" mask\n      await clickOnTarget(imageFrame);\n\n      // delete the \"detached\" mask\n      await fixture.events.keyboard.press('del');\n\n      const { unmaskedElement } = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          unmaskedElement: state.currentPage.elements[1],\n        }))\n      );\n\n      expect(unmaskedElement.mask.type).toEqual('rectangle');\n    });\n  });\n\n  describe('right click menu: product', () => {\n    it('product has right click menu', async () => {\n      const product = await addProduct({});\n      const productElement = fixture.editor.canvas.framesLayer.frame(\n        product.id\n      ).node;\n      await rightClickOnTarget(productElement);\n      await fixture.events.click(selectLayerButton());\n\n      const productItem = fixture.screen.getByRole('menuitem', {\n        name: /^Logo Collection$/,\n      });\n\n      expect(productItem).toBeDefined();\n      expect(sendBackward().disabled).toBeTrue();\n      expect(sendToBack().disabled).toBeTrue();\n      expect(bringForward().disabled).toBeTrue();\n      expect(bringToFront().disabled).toBeTrue();\n    });\n  });\n\n  describe('right click menu: heading level', () => {\n    it('text has heading right click menu', async () => {\n      const text = await addText({\n        y: 300,\n        fontSize: 40,\n        content: '<span style=\"color: #000\">Web Stories</span>',\n        tagName: 'h2',\n      });\n\n      const textElement = fixture.editor.canvas.framesLayer.frame(text.id).node;\n\n      await rightClickOnTarget(textElement);\n      await fixture.events.click(selectHeadingLevel());\n\n      const textItemH2 = fixture.screen.getByRole('menuitem', {\n        name: /^Heading 2$/,\n      });\n\n      expect(textItemH2).toBeDefined();\n\n      // check if h2 has the \"checked\" icon\n      expect(textItemH2.firstChild.tagName).toEqual('svg');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/rtl.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('RTL support', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    fixture.setConfig({ isRTL: true });\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should display the editor in RTL mode', async () => {\n    await fixture.snapshot('Direction: RTL');\n  });\n\n  async function getSelectedElements() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  }\n\n  describe('CUJ: Creator can Select an Element: Transforming element', () => {\n    it('should allow dragging element in RTL mode', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        const node = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!node) {\n          throw new Error('node not ready');\n        }\n        expect(node).toBeTruthy();\n      });\n      const frame = fixture.editor.canvas.framesLayer.frames[1].node;\n      const elements = await getSelectedElements();\n      const originX = elements[0].x;\n      const box = frame.getBoundingClientRect();\n      await fixture.events.mouse.seq(({ move, moveBy, down, up }) => [\n        move(box.left + 10, box.top + 10),\n        down(),\n        moveBy(100, 0),\n        up(),\n      ]);\n\n      const changedElements = await getSelectedElements();\n      // We moved it to the right so the X should be more than before if it works as expected.\n      expect(changedElements[0].width).toBeGreaterThan(originX);\n      await fixture.snapshot(\n        'Direction: RTL. Default Text element moved to the right.'\n      );\n    });\n\n    it('should allow resizing element in RTL mode', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        const node = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!node) {\n          throw new Error('node not ready');\n        }\n        expect(node).toBeTruthy();\n      });\n      const elements = await getSelectedElements();\n      const originWidth = elements[0].width;\n      const resizeW = fixture\n        .querySelector('.moveable-e')\n        .getBoundingClientRect();\n      await fixture.events.mouse.seq(({ move, moveBy, down, up }) => [\n        move(resizeW.left + 1, resizeW.top + 1),\n        down(),\n        moveBy(200, 0),\n        up(),\n      ]);\n\n      const changedElements = await getSelectedElements();\n      // We resized it from the right handle so the width should be higher than before.\n      expect(changedElements[0].width).toBeGreaterThan(originWidth);\n      await fixture.snapshot(\n        'Direction: RTL. Default Text element resized wider.'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/selection.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('CUJ: Creator can Transform an Element: Selection integration', () => {\n  let fixture;\n  let fullbleed;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    fullbleed = fixture.container.querySelector('[data-testid=\"fullbleed\"]');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function clickOnTarget(target) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n  }\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds;\n  }\n\n  async function getElements() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  }\n\n  async function setFontSize(size) {\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const fontSize = fixture.editor.sidebar.designPanel.textStyle.fontSize;\n    await fixture.events.click(fontSize, { clickCount: 3 });\n    await fixture.events.keyboard.type(size);\n    await fixture.events.keyboard.press('tab');\n    // Give time for the font size to be applied.\n    await fixture.events.sleep(100);\n  }\n\n  it('should have the last element selected by default', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n    expect(await getSelection()).toEqual([frame1.dataset.elementId]);\n  });\n\n  it('should not allow background selection through the empty area of a triangle', async () => {\n    // Switch to shapes tab and click the triangle\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n    expect(await getSelection()).toEqual([frame1.dataset.elementId]);\n\n    // Click on the upper left corner of the triangle -- that's empty area.\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(frame1, 7, 7),\n      down(),\n      up(),\n    ]);\n    expect(await getSelection()).toEqual([frame1.dataset.elementId]);\n  });\n\n  it('should click \"through\" a locked element', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    const elements = await getElements();\n\n    // Click on the background and confirm it is selected\n    const background = fixture.editor.canvas.framesLayer.frames[0].node;\n    await fixture.events.mouse.clickOn(background, 20, 20);\n    expect(await getSelection()).toEqual([elements[0].id]);\n\n    // Hover layer and enable lock\n    const layerPanel = fixture.editor.footer.layerPanel;\n    await fixture.events.click(layerPanel.togglePanel);\n    const paragraphLayer = layerPanel.getLayerByInnerText('Fill in some text');\n    await fixture.events.hover(paragraphLayer);\n    const lockButton = within(paragraphLayer).getByLabelText(/Lock/);\n    await fixture.events.click(lockButton);\n\n    // Try to click on the text element\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n    await fixture.events.mouse.clickOn(frame1, 20, 20);\n    expect(await getSelection()).toEqual([elements[0].id]);\n  });\n\n  it('should show the selection lines when an element is being selected', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n    // De-select element by clicking somewhere else.\n    const { x, y } = fullbleed.getBoundingClientRect();\n    await fixture.events.mouse.click(x - 50, y);\n    expect(await getSelection()).toEqual([]);\n    // Select the element again.\n    await clickOnTarget(frame1);\n    expect(\n      fixture.querySelector('.moveable-line.moveable-direction.moveable-n')\n    ).toBeDefined();\n    await fixture.snapshot('text element is selected');\n  });\n\n  it('should show the selection lines when out of page area', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    await setFontSize('30');\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n    const resizeW = fixture\n      .querySelector('.moveable-w')\n      .getBoundingClientRect();\n    await fixture.events.mouse.seq(({ move, moveBy, down, up }) => [\n      move(resizeW.left + 1, resizeW.top + 1),\n      down(),\n      moveBy(-200, 0),\n      up(),\n    ]);\n\n    expect(await getSelection()).toEqual([frame1.dataset.elementId]);\n    await fixture.snapshot();\n  });\n\n  it('should show the selection on top of page navigation arrows', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    await setFontSize('30');\n\n    const frame1 = fixture.editor.canvas.framesLayer.frames[1].node;\n\n    const prevPage =\n      fixture.editor.canvas.framesLayer.prevPage.getBoundingClientRect();\n    const resizeW = fixture\n      .querySelector('.moveable-w')\n      .getBoundingClientRect();\n    await fixture.events.mouse.seq(({ move, down, up }) => [\n      move(resizeW.left + 1, resizeW.top + 1),\n      down(),\n      move(prevPage.left - prevPage.width / 2, 0),\n      up(),\n    ]);\n    expect(await getSelection()).toEqual([frame1.dataset.elementId]);\n    await fixture.snapshot('selection on top of the page nav');\n  });\n\n  it('should return focus to selection when pressing mod+alt+2', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      const node = fixture.editor.canvas.framesLayer.frames[1].node;\n      if (!node) {\n        throw new Error('node not ready');\n      }\n      expect(node).toBeTruthy();\n    });\n    // NB: We can't actually validate that the frame has focus, as that's a bit flaky,\n    // But as long as the focus moves in the shortcut press, it's fair to assume that it has\n    // Move to the canvas selection.\n\n    // Click elsewhere\n    await fixture.events.click(fixture.editor.canvas.header.title);\n    expect(fixture.editor.canvas.header.title).toHaveFocus();\n\n    // Return focus with shortcut\n    await fixture.events.keyboard.shortcut('mod+alt+2');\n    expect(fixture.editor.canvas.header.title).not.toHaveFocus();\n    await fixture.snapshot('selected element has focus');\n  });\n\n  it('should allow selecting element by clicking on its border', async () => {\n    // Add a shape.\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    const node = fixture.editor.canvas.framesLayer.frames[1].node;\n    // Get the initial coordinates.\n    const { x, y } = node.getBoundingClientRect();\n\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n\n    const panel = fixture.editor.sidebar.designPanel.border;\n    await fixture.events.click(panel.width(), { clickCount: 3 });\n    await fixture.events.keyboard.type('10');\n    await fixture.events.keyboard.press('tab');\n\n    // Select page by clicking on the background element\n    await fixture.events.mouse.clickOn(\n      fixture.editor.canvas.framesLayer.frames[0].node,\n      10,\n      10\n    );\n\n    // Now select the shape by clicking on the border.\n    await fixture.events.mouse.click(x - 5, y - 5);\n    const storyContext = await fixture.renderHook(() => useStory());\n    const [element] = storyContext.state.selectedElements;\n    // Verify the shape was selected.\n    expect(element.border).toEqual({\n      left: 10,\n      right: 10,\n      top: 10,\n      bottom: 10,\n      lockedWidth: true,\n      color: { color: { r: 0, g: 0, b: 0 } },\n    });\n\n    await fixture.snapshot('Border included in selection frame');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/karma/snapping.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Snapping integration', () => {\n  let element1;\n  let frame1;\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    const mediaItem = fixture.editor.library.media.item(0);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    element1 = elements[1].id;\n\n    frame1 = fixture.editor.canvas.framesLayer.frame(element1).node;\n  });\n\n  describe('CUJ: Creator can transform an element: Snap to place', () => {\n    it('should show design space guideline when moving align design space left edge', async () => {\n      await fixture.events.mouse.seq(({ moveRel, moveBy, down }) => [\n        moveRel(frame1, 10, 10),\n        down(),\n        moveBy(0, 20, { steps: 6 }),\n      ]);\n\n      await fixture.snapshot('Design space guideline visible');\n\n      await fixture.events.mouse.up();\n\n      await fixture.snapshot('Design space guideline hidden');\n    });\n\n    it('should show canvas center guidelines when moved to the center', async () => {\n      await fixture.events.mouse.seq(({ moveRel, moveBy, down }) => [\n        moveRel(frame1, 10, 10),\n        down(),\n        moveBy(10, 150, { steps: 6 }),\n      ]);\n\n      await fixture.snapshot('Canvas center guidelines visible');\n\n      await fixture.events.mouse.up();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/layout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  forwardRef,\n  createRef,\n  useRef,\n  useEffect,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { FULLBLEED_RATIO } from '@googleforcreators/units';\nimport { THEME_CONSTANTS } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { HEADER_HEIGHT, HEADER_GAP } from '../../constants';\nimport { useLayout } from '../../app';\nimport useFooterHeight from '../footer/useFooterHeight';\nimport { FOOTER_BOTTOM_MARGIN } from '../footer/constants';\nimport usePinchToZoom from './usePinchToZoom';\n\n/**\n * @file See https://user-images.githubusercontent.com/726049/72654503-bfffe780-3944-11ea-912c-fc54d68b6100.png\n * for the layering details.\n */\n\n// 8px extra is for the focus outline to display.\nconst PAGE_NAV_WIDTH = THEME_CONSTANTS.LARGE_BUTTON_SIZE + 8;\nconst PAGE_NAV_GAP = 20;\n\nconst LayerGrid = styled.section`\n  pointer-events: ${({ pointerEvents }) => pointerEvents};\n\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n\n  ${({ zIndex }) => (typeof zIndex === 'number' ? `z-index: ${zIndex};` : '')}\n\n  display: grid;\n  /*\n    . = empty space\n    h = header\n    p = previous page\n    n = next page\n    b = back navigation\n    f = forward navigation\n    c = canvas page\n    m = page action menu\n    w = workspace footer\n    t = canvas page title\n\n    Also note that we need to specify all the widths and heights\n    even though some of the elements could just use the size that\n    the element takes up. This is because we reuse this grid in 3\n    different layers on top of each other and some elements are\n    missing in some layers, but we still need them to align perfectly.\n  */\n  grid:\n    'h h h h h h h' ${HEADER_HEIGHT}px\n    '. . . t . . .' minmax(${HEADER_GAP}px, 1fr)\n    'p b . c . f n' var(--viewport-height-px)\n    '. . . . . . .' 1fr\n    'w w w w w w w' ${({ footerHeight }) => footerHeight}px\n    '. . . . . . .' ${FOOTER_BOTTOM_MARGIN}px\n    /\n    1fr\n    var(--page-nav-width)\n    var(--page-nav-gap)\n    var(--viewport-width-px)\n    var(--page-nav-gap)\n    var(--page-nav-width)\n    1fr;\n  height: 100%;\n`;\n\nconst Area = styled.div`\n  pointer-events: ${({ pointerEvents }) => pointerEvents};\n\n  grid-area: ${({ area }) => area};\n  overflow: ${({ showOverflow }) => (showOverflow ? 'visible' : 'hidden')};\n  position: relative;\n  width: 100%;\n  height: 100%;\n  ${({ zIndex }) => (zIndex !== undefined ? `z-index: ${zIndex}` : null)};\n`;\n\n// Page area is not `overflow:hidden` by default to allow different clipping\n// mechanisms.\nconst PageAreaContainer = styled(Area).attrs({\n  area: 'c',\n})`\n  position: relative;\n  display: flex;\n  justify-content: ${({ hasHorizontalOverflow }) =>\n    hasHorizontalOverflow ? 'flex-start' : 'center'};\n  align-items: ${({ hasVerticalOverflow }) =>\n    hasVerticalOverflow ? 'flex-start' : 'center'};\n  overflow: ${({ showOverflow }) =>\n    showOverflow ? 'visible' : 'var(--overflow-x) var(--overflow-y)'};\n  ${({\n    isControlled,\n    hasVerticalOverflow,\n    hasHorizontalOverflow,\n    showOverflow,\n  }) =>\n    isControlled &&\n    `\n      overflow: ${showOverflow ? 'visible' : 'hidden'};\n      width: calc(\n        100% - ${hasVerticalOverflow ? THEME_CONSTANTS.SCROLLBAR_WIDTH : 0}px\n      );\n      height: calc(\n        100% - ${hasHorizontalOverflow ? THEME_CONSTANTS.SCROLLBAR_WIDTH : 0}px\n      );\n    `}\n`;\n\nconst PageTitleContainer = styled(Area).attrs({\n  area: 't',\n})`\n  position: relative;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst Layer = forwardRef(function Layer({ children, ...rest }, ref) {\n  const footerHeight = useFooterHeight();\n  return (\n    <LayerGrid ref={ref} footerHeight={footerHeight} {...rest}>\n      {children}\n    </LayerGrid>\n  );\n});\n\nLayer.propTypes = {\n  children: PropTypes.node,\n};\n\nconst PaddedPage = styled.div`\n  padding: calc(0.5 * var(--page-padding-px));\n`;\n\n// This layers is needed to clip the frames at the desired page padding\n// if the layer is scrollable\nconst PageClip = styled.div`\n  ${({ hasHorizontalOverflow, hasVerticalOverflow }) =>\n    (hasHorizontalOverflow || hasVerticalOverflow) &&\n    `\n      overflow: hidden;\n      width: ${\n        hasHorizontalOverflow\n          ? 'calc(var(--page-width-px) + var(--page-padding-px))'\n          : `calc(var(--viewport-width-px) - ${THEME_CONSTANTS.SCROLLBAR_WIDTH}px)`\n      };\n      flex-basis: ${\n        hasHorizontalOverflow\n          ? 'calc(var(--page-width-px) + var(--page-padding-px))'\n          : `calc(var(--viewport-width-px) - ${THEME_CONSTANTS.SCROLLBAR_WIDTH}px)`\n      };\n      height: ${\n        hasVerticalOverflow\n          ? 'calc(var(--fullbleed-height-px) + var(--page-padding-px))'\n          : `calc(var(--viewport-height-px) - ${THEME_CONSTANTS.SCROLLBAR_WIDTH}px)`\n      };\n      flex-shrink: 0;\n      flex-grow: 0;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n    `}\n`;\n\nconst FullbleedContainer = styled.div`\n  ${({ background }) => generatePatternStyles(background)}\n  overflow: visible;\n  position: relative;\n  width: var(--page-width-px);\n  height: var(--fullbleed-height-px);\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  border-radius: 5px;\n\n  ${({ isControlled }) =>\n    isControlled &&\n    `\n      left: var(--scroll-left-px);\n      top: var(--scroll-top-px);\n    `};\n\n  ${({ isBackgroundSelected, theme }) =>\n    isBackgroundSelected &&\n    `\n      &:before {\n        content: '';\n        position: absolute;\n        top: -4px;\n        left: -4px;\n        right: -4px;\n        bottom: -4px;\n        border: ${theme.colors.border.selection} 1px solid;\n        border-radius: ${theme.borders.radius.medium};\n      }\n    `}\n`;\n\n// Overflow is only hidden for display layer, not edit nor frames\nconst PageAreaWithoutOverflow = styled.div`\n  overflow: ${({ showOverflow }) => (showOverflow ? 'initial' : 'hidden')};\n  position: relative;\n  width: var(--page-width-px);\n  height: var(--fullbleed-height-px);\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst PageAreaSafeZone = styled.div`\n  width: var(--page-width-px);\n  height: var(--page-height-px);\n  overflow: visible;\n  position: relative;\n`;\n\nconst HeadArea = styled(Area).attrs({ area: 'h' })``;\n\nconst MenuArea = styled(Area).attrs({ area: 'm' })``;\n\nconst NavArea = styled(Area)`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\nconst NavPrevArea = styled(NavArea).attrs({ area: 'b' })``;\n\nconst NavNextArea = styled(NavArea).attrs({ area: 'f' })``;\n\nconst PageBeforeArea = styled(Area).attrs({ area: 'p' })``;\n\nconst PageAfterArea = styled(Area).attrs({ area: 'n' })``;\n\nconst PageMenuArea = styled.div`\n  grid-area: c;\n  position: absolute;\n  right: calc(-24px + var(--page-padding-px));\n  top: calc(0.5 * var(--page-padding-px));\n  min-height: calc(100% - var(--page-padding-px));\n`;\n\nconst FooterArea = styled(Area).attrs({\n  area: 'w',\n  showOverflow: true,\n})``;\n\n/**\n * @param {!{current: ?Element}} containerRef Container reference.\n */\nfunction useLayoutParams(containerRef) {\n  const { setWorkspaceSize } = useLayout(\n    ({ actions: { setWorkspaceSize } }) => ({\n      setWorkspaceSize,\n    })\n  );\n\n  const footerHeight = useFooterHeight();\n\n  useResizeEffect(\n    containerRef,\n    ({ width, height }) => {\n      // See Layer's `grid` CSS above. Per the layout, the maximum available\n      // space for the page is:\n      const availableHeight =\n        height -\n        HEADER_HEIGHT -\n        HEADER_GAP -\n        footerHeight -\n        FOOTER_BOTTOM_MARGIN;\n\n      setWorkspaceSize({ width, height, availableHeight });\n    },\n    [setWorkspaceSize, footerHeight]\n  );\n}\n\nfunction useLayoutParamsCssVars() {\n  const {\n    pageWidth,\n    pageHeight,\n    pagePadding,\n    viewportWidth,\n    viewportHeight,\n    hasPageNavigation,\n    hasVerticalOverflow,\n    hasHorizontalOverflow,\n    scrollLeft,\n    scrollTop,\n  } = useLayout(\n    ({\n      state: {\n        pageWidth,\n        pageHeight,\n        pagePadding,\n        viewportWidth,\n        viewportHeight,\n        hasPageNavigation,\n        hasVerticalOverflow,\n        hasHorizontalOverflow,\n        scrollLeft,\n        scrollTop,\n      },\n    }) => ({\n      pageWidth,\n      pageHeight,\n      pagePadding,\n      viewportWidth,\n      viewportHeight,\n      hasPageNavigation,\n      hasVerticalOverflow,\n      hasHorizontalOverflow,\n      scrollLeft,\n      scrollTop,\n    })\n  );\n  const fullHeight = pageWidth / FULLBLEED_RATIO;\n  return {\n    '--page-nav-width': `${hasPageNavigation ? PAGE_NAV_WIDTH : 0}px`,\n    '--page-nav-gap': `${hasPageNavigation ? PAGE_NAV_GAP : 0}px`,\n    '--page-width-px': `${pageWidth}px`,\n    '--page-height-px': `${pageHeight}px`,\n    '--page-padding-px': `${pagePadding}px`,\n    '--fullbleed-height-px': `${fullHeight}px`,\n    '--viewport-width-px': `${viewportWidth}px`,\n    '--viewport-height-px': `${viewportHeight}px`,\n    '--overflow-x': hasHorizontalOverflow ? 'scroll' : 'visible',\n    '--overflow-y': hasVerticalOverflow ? 'scroll' : 'auto',\n    '--scroll-left-px': `${-scrollLeft}px`,\n    '--scroll-top-px': `${-scrollTop}px`,\n  };\n}\n\nconst PageArea = forwardRef(function PageArea(\n  {\n    children,\n    fullbleedRef: _fullbleedRef = null,\n    fullBleedContainerLabel = __('Fullbleed area', 'web-stories'),\n    overlay = [],\n    background,\n    isControlled = false,\n    className = '',\n    showOverflow = false,\n    isBackgroundSelected = false,\n    pageAreaRef = createRef(),\n    withSafezone = true,\n    ...rest\n  },\n  ref\n) {\n  const internalFullblledRef = useRef();\n  const fullbleedRef = _fullbleedRef || internalFullblledRef;\n  const {\n    hasVerticalOverflow,\n    hasHorizontalOverflow,\n    zoomSetting,\n    scrollLeft,\n    scrollTop,\n  } = useLayout(\n    ({\n      state: {\n        hasVerticalOverflow,\n        hasHorizontalOverflow,\n        zoomSetting,\n        scrollLeft,\n        scrollTop,\n      },\n    }) => ({\n      hasVerticalOverflow,\n      hasHorizontalOverflow,\n      zoomSetting,\n      scrollLeft,\n      scrollTop,\n    })\n  );\n\n  // We need to ref scroll, because scroll changes should not update a non-controlled layer\n  const scrollRef = useRef();\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  scrollRef.current = { top: scrollTop, left: scrollLeft };\n  // If zoom setting changes for a non-controlled layer, make sure to reset actual scroll inside container\n  useEffect(() => {\n    if (!isControlled) {\n      fullbleedRef.current.scrollTop = scrollRef.current.top;\n      fullbleedRef.current.scrollLeft = scrollRef.current.left;\n    }\n  }, [isControlled, zoomSetting, fullbleedRef]);\n\n  const paddedRef = useRef(null);\n  usePinchToZoom({ containerRef: paddedRef });\n\n  return (\n    <PageAreaContainer\n      showOverflow={showOverflow}\n      isControlled={isControlled}\n      hasHorizontalOverflow={hasHorizontalOverflow}\n      hasVerticalOverflow={hasVerticalOverflow}\n      className={className}\n      data-scroll-container\n      {...rest}\n    >\n      <PageClip\n        hasHorizontalOverflow={hasHorizontalOverflow}\n        hasVerticalOverflow={hasVerticalOverflow}\n      >\n        <PaddedPage ref={paddedRef}>\n          <FullbleedContainer\n            aria-label={fullBleedContainerLabel}\n            role=\"region\"\n            ref={fullbleedRef}\n            data-testid=\"fullbleed\"\n            background={background}\n            isControlled={isControlled}\n            isBackgroundSelected={isBackgroundSelected}\n          >\n            <PageAreaWithoutOverflow\n              ref={pageAreaRef}\n              showOverflow={showOverflow}\n            >\n              {withSafezone ? (\n                <PageAreaSafeZone ref={ref} data-testid=\"safezone\">\n                  {children}\n                </PageAreaSafeZone>\n              ) : (\n                children\n              )}\n              {overlay}\n            </PageAreaWithoutOverflow>\n          </FullbleedContainer>\n        </PaddedPage>\n      </PageClip>\n    </PageAreaContainer>\n  );\n});\n\nPageArea.propTypes = {\n  children: PropTypes.node,\n  fullbleedRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),\n  overlay: PropTypes.node,\n  background: PropTypes.object,\n  isControlled: PropTypes.bool,\n  className: PropTypes.string,\n  showOverflow: PropTypes.bool,\n  isBackgroundSelected: PropTypes.bool,\n  fullBleedContainerLabel: PropTypes.string,\n  pageAreaRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),\n  withSafezone: PropTypes.bool,\n};\n\nexport {\n  Layer,\n  PageArea,\n  PageBeforeArea,\n  PageAfterArea,\n  PageTitleContainer as PageTitleArea,\n  HeadArea,\n  MenuArea,\n  NavPrevArea,\n  NavNextArea,\n  PageMenuArea,\n  FooterArea,\n  useLayoutParams,\n  useLayoutParamsCssVars,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/cue.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport parseTimestamp from './parseTimestamp';\n\nconst CueWrapper = styled.span`\n  text-align: center;\n  height: ${({ $height }) => `${$height}px`};\n`;\nconst CueEl = styled.span`\n  color: ${({ $isFutureCue, theme }) =>\n    $isFutureCue ? theme.colors.fg.black : theme.colors.fg.white};\n`;\n// TODO: Adjust font size and styling based on canvas size.\nconst Section = styled.span`\n  margin: 0 10px 10px;\n  padding: 6px 12px;\n  vertical-align: middle;\n  border-radius: 15px;\n  background: rgba(11, 11, 11, 0.6);\n  color: rgba(255, 255, 255, 1);\n  display: inline-block;\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,\n    Cantarell, 'Helvetica Neue', sans-serif;\n  line-height: 1.4;\n  word-break: normal;\n  word-wrap: break-word;\n  overflow-wrap: break-word;\n`;\n\n/** @typedef {import(\"react\").ReactNode} ReactNode */\n\nfunction Cue({ cue, videoTime, height }) {\n  const html = cue.getCueAsHTML();\n\n  /* eslint-disable react/jsx-key -- Order should never change */\n  return (\n    <CueWrapper $height={height}>\n      <Section>\n        {html.childNodes.map((node) => {\n          if (node.target === 'timestamp') {\n            return null;\n          } else {\n            let timestamp = null;\n            if (node.previousSibling?.target === 'timestamp') {\n              timestamp = parseTimestamp(node.previousSibling.data);\n            }\n            const isFutureCue = timestamp > videoTime;\n\n            const isText = node.nodeType === Node.TEXT_NODE;\n\n            if (isText) {\n              return timestamp !== null ? (\n                <span>\n                  <CueEl $isFutureCue={isFutureCue}>{node.textContent}</CueEl>\n                </span>\n              ) : (\n                <CueEl>{node.textContent}</CueEl>\n              );\n            }\n\n            return timestamp !== null ? (\n              <span>\n                <CueEl\n                  $isFutureCue={isFutureCue}\n                  dangerouslySetInnerHTML={{ __html: node.innerHTML }}\n                />\n              </span>\n            ) : (\n              <CueEl dangerouslySetInnerHTML={{ __html: node.innerHTML }} />\n            );\n          }\n        })}\n      </Section>\n    </CueWrapper>\n  );\n  /* eslint-enable react/jsx-key -- Order should never change */\n}\n\nCue.propTypes = {\n  cue: PropTypes.shape({\n    getCueAsHTML: PropTypes.func,\n  }).isRequired,\n  videoTime: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n};\n\nexport default Cue;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as MediaCaptionsLayer } from './mediaCaptionsLayer';\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/mediaCaptionsLayer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../../app';\nimport { Layer, PageArea } from '../layout';\nimport TrackRenderer from './trackRenderer';\n\nconst CaptionsLayer = styled(Layer)``;\n\nconst CaptionsPageArea = styled(PageArea)`\n  position: absolute;\n  pointer-events: none;\n`;\n\nconst CaptionsCanvas = styled.div`\n  background: transparent;\n  border-radius: 5px;\n  position: absolute;\n  z-index: 2;\n  transform: translateZ(0);\n  top: 0;\n  left: 0;\n  bottom: 0;\n  right: 0;\n  cursor: default;\n`;\n\nfunction MediaCaptionsLayer() {\n  const { isEditing } = useCanvas(({ state: { isEditing } }) => ({\n    isEditing,\n  }));\n\n  const { currentPageId, backgroundAudio, videoElement } = useStory(\n    ({ state }) => {\n      const { selectedElements, currentPage } = state;\n\n      let backgroundAudio = null;\n      let videoElement = null;\n\n      if (selectedElements.length === 1 && currentPage) {\n        const selectedElement = selectedElements[0];\n        const { isBackground, type, tracks } = selectedElement;\n        const { backgroundAudio: currentPageBackgroundAudio } = currentPage;\n        if (\n          isBackground &&\n          currentPageBackgroundAudio &&\n          currentPageBackgroundAudio?.tracks?.length > 0\n        ) {\n          backgroundAudio = currentPageBackgroundAudio;\n        }\n        if (type === 'video' && tracks?.length > 0) {\n          videoElement = selectedElement;\n        }\n      }\n\n      return {\n        currentPageId: currentPage?.id,\n        backgroundAudio,\n        videoElement,\n      };\n    }\n  );\n\n  const [mediaTrackCount, setMediaTrackCount] = useState(0);\n  const [mediaElementId, setMediaElementId] = useState('');\n\n  useEffect(() => {\n    setMediaTrackCount(0);\n    setMediaElementId('');\n\n    if (backgroundAudio) {\n      setMediaElementId(`page-${currentPageId}-background-audio`);\n      setMediaTrackCount(backgroundAudio?.tracks?.length);\n      return;\n    }\n\n    if (isEditing || !videoElement) {\n      return;\n    }\n    setMediaElementId(`video-${videoElement.id}`);\n    setMediaTrackCount(videoElement.tracks.length);\n  }, [videoElement, backgroundAudio, currentPageId, isEditing]);\n\n  if (!mediaTrackCount) {\n    return null;\n  }\n\n  return (\n    <CaptionsLayer>\n      <CaptionsPageArea withSafezone={false} showOverflow>\n        <CaptionsCanvas>\n          {Array.from({ length: mediaTrackCount }).map((_, index) => (\n            <TrackRenderer\n              key={\n                // eslint-disable-next-line react/no-array-index-key -- Order should never change.\n                index\n              }\n              elementId={mediaElementId}\n              trackIndex={index}\n            />\n          ))}\n        </CaptionsCanvas>\n      </CaptionsPageArea>\n    </CaptionsLayer>\n  );\n}\n\nexport default MediaCaptionsLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/parseTimestamp.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Parses a WebVTT timestamp and returns the time in seconds from video start.\n *\n * As implemented in <amp-story-captions>.\n *\n * @see https://www.w3.org/TR/webvtt1/#webvtt-timestamp\n * @see https://github.com/ampproject/amphtml/blob/78fed1a5551cae5486717acbd45878a1e36343a0/extensions/amp-story-captions/0.1/track-renderer.js#L10-L26\n * @param {string} timestamp Timestamp string.\n * @return {?number} Time in seconds.\n */\nfunction parseTimestamp(timestamp) {\n  const match = /^(?:(\\d{2,}):)?(\\d{2}):(\\d{2})\\.(\\d{3})$/.exec(timestamp);\n  if (!match) {\n    return null;\n  }\n  const hours = match[1] ? Number.parseInt(match[1]) : 0;\n  const minutes = Number.parseInt(match[2]);\n  const seconds = Number.parseInt(match[3]);\n  const milliseconds = Number.parseInt(match[4]);\n  return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000;\n}\n\nexport default parseTimestamp;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/test/parseTimestamp.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport parseTimestamp from '../parseTimestamp';\n\ndescribe('parseTimestamp', () => {\n  it.each([\n    ['00:00:14.330', 14.33],\n    ['00:10:53.220', 653.22],\n  ])(\n    'should parse valid timestamp %s and return %d',\n    (timeStampString, expected) => {\n      expect(parseTimestamp(timeStampString)).toBeCloseTo(expected, 2);\n    }\n  );\n\n  it('should reject invalid timestamp', () => {\n    expect(parseTimestamp('')).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaCaptions/trackRenderer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../../app';\nimport Cue from './cue';\n\nconst Track = styled.div`\n  width: 100%;\n  height: 100%;\n  display: grid;\n  align-content: end;\n  font-size: ${({ $fontSize }) => `${$fontSize}px`};\n`;\n\n/** @typedef {import('react').ReactNode} ReactNode */\n\n/**\n * Track renderer component.\n *\n * @param {Object} props Component props.\n * @param {string} props.elementId Media element id.\n * @param {number} props.trackIndex Video track index in the tracklist.\n * @return {*} Track component.\n */\nfunction TrackRenderer({ elementId, trackIndex }) {\n  const { pageWidth, pageHeight } = useLayout(\n    ({ state: { pageWidth, pageHeight } }) => ({\n      pageWidth,\n      pageHeight,\n    })\n  );\n\n  // To mimic the responsive `amp-story-captions span` styling on the frontend.\n  const fontSize = pageWidth * 0.04;\n  const height = pageHeight * 0.3;\n\n  const [track, setTrack] = useState(null);\n  const [videoTime, setVideoTime] = useState(0);\n  const [cues, setCues] = useState([]);\n\n  const updateCues = useCallback(() => {\n    const activeCues = track?.activeCues ? [...track.activeCues] : [];\n    setCues(activeCues);\n  }, [track]);\n\n  useEffect(() => {\n    updateCues();\n    setVideoTime(0);\n\n    /**\n     * @type {HTMLVideoElement}\n     */\n    const mediaEl = document.getElementById(elementId);\n\n    if (!mediaEl) {\n      return undefined;\n    }\n\n    const mediaTrack = mediaEl.textTracks?.[trackIndex];\n\n    if (!mediaTrack) {\n      return undefined;\n    }\n\n    mediaTrack.mode = 'hidden';\n\n    updateCues();\n\n    setTrack(mediaTrack);\n\n    mediaEl.addEventListener('timeupdate', () => {\n      setVideoTime(mediaEl.currentTime);\n    });\n\n    // TODO: Figure out why this doesn't work after moving the video on the canvas.\n    mediaTrack.addEventListener('cuechange', updateCues);\n\n    return () => {\n      mediaTrack.removeEventListener('cuechange', updateCues);\n    };\n  }, [trackIndex, updateCues, elementId, pageWidth, pageHeight]);\n\n  if (!cues || !track) {\n    return null;\n  }\n\n  return (\n    <Track $fontSize={fontSize}>\n      {cues.map((cue, index) => (\n        <Cue\n          key={\n            // eslint-disable-next-line react/no-array-index-key -- Order should never change.\n            index\n          }\n          cue={cue}\n          videoTime={videoTime}\n          height={height}\n        />\n      ))}\n    </Track>\n  );\n}\n\nTrackRenderer.propTypes = {\n  elementId: PropTypes.string.isRequired,\n  trackIndex: PropTypes.number.isRequired,\n};\n\nexport default TrackRenderer;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/mediaRecordingLayer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { StyleSheetManager } from 'styled-components';\nimport stylisRTLPlugin from 'stylis-plugin-rtl';\nObject.defineProperty(stylisRTLPlugin, 'name', { value: 'stylisRTLPlugin' });\nimport { __ } from '@googleforcreators/i18n';\nimport { useEffect, useMemo } from '@googleforcreators/react';\nimport { withOverlay } from '@googleforcreators/moveable';\nimport { FULLBLEED_RATIO } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport useConfig from '../../app/config/useConfig';\nimport { Z_INDEX_RECORDING_MODE } from '../../constants/zIndex';\nimport {\n  useMediaRecording,\n  SettingsModal,\n  MediaRecording,\n  DurationIndicator,\n  Footer,\n} from '../mediaRecording';\nimport VideoRecordingTrimProvider from '../videoTrim/recordingProvider';\nimport VideoTrimmer from '../videoTrim/videoTrimmer';\nimport { PageTitleArea, Layer, PageArea, FooterArea } from './layout';\n\nconst DisplayPageArea = styled(PageArea)`\n  position: absolute;\n`;\n\nconst LayerWithGrayout = withOverlay(styled(Layer)`\n  background-color: ${({ theme }) => theme.colors.opacity.overlayExtraDark};\n  z-index: ${Z_INDEX_RECORDING_MODE};\n`);\n\nconst StyledFooter = styled(FooterArea)`\n  display: flex;\n  align-items: start;\n  flex-direction: row;\n  justify-content: center;\n  z-index: ${Z_INDEX_RECORDING_MODE};\n`;\n\nfunction MediaRecordingLayer() {\n  const { isRTL } = useConfig();\n\n  const {\n    status,\n    inputStatus,\n    audioInput,\n    videoInput,\n    hasVideo,\n    isAdjustingTrim,\n    trimData,\n    originalMediaBlobUrl,\n    duration,\n    updateMediaDevices,\n    getMediaStream,\n    resetStream,\n    onTrim,\n    videoEffect,\n  } = useMediaRecording(({ state, actions }) => ({\n    status: state.status,\n    inputStatus: state.inputStatus,\n    audioInput: state.audioInput,\n    videoInput: state.videoInput,\n    hasVideo: state.hasVideo,\n    isAdjustingTrim: state.isAdjustingTrim,\n    trimData: state.trimData,\n    originalMediaBlobUrl: state.originalMediaBlobUrl,\n    duration: state.duration,\n    videoEffect: state.videoEffect,\n    updateMediaDevices: actions.updateMediaDevices,\n    getMediaStream: actions.getMediaStream,\n    resetStream: actions.resetStream,\n    onTrim: actions.onTrim,\n  }));\n  const isReady = 'ready' === inputStatus || 'ready' === status;\n\n  useEffect(() => {\n    async function run() {\n      resetStream();\n      await getMediaStream();\n    }\n    run();\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Only want to act on actual input changes.\n  }, [audioInput, videoInput, hasVideo, videoEffect]);\n\n  useEffect(() => {\n    if (isReady) {\n      updateMediaDevices();\n    }\n  }, [isReady, updateMediaDevices]);\n\n  // Video data was designed for a different purpose, so we need to fake the api a bit here\n  const videoData = useMemo(() => {\n    return isAdjustingTrim\n      ? {\n          element: {\n            width: FULLBLEED_RATIO * 480,\n            height: 480,\n            scale: 1,\n            focalX: 50,\n            focalY: 50,\n            flip: {},\n          },\n          resource: {\n            src: originalMediaBlobUrl,\n            length: duration,\n          },\n          ...trimData,\n        }\n      : null;\n  }, [isAdjustingTrim, trimData, originalMediaBlobUrl, duration]);\n\n  return (\n    // CanvasLayout disables stylisRTLPlugin, but for this subtree we want it again\n    // to make RTL work automatically.\n    <StyleSheetManager stylisPlugins={isRTL ? [stylisRTLPlugin] : []}>\n      <VideoRecordingTrimProvider onTrim={onTrim} videoData={videoData}>\n        <LayerWithGrayout\n          aria-label={__('Media Recording layer', 'web-stories')}\n        >\n          <PageTitleArea>\n            <DurationIndicator />\n          </PageTitleArea>\n          <DisplayPageArea withSafezone={false} showOverflow>\n            <MediaRecording />\n          </DisplayPageArea>\n          <StyledFooter showOverflow>\n            {isAdjustingTrim ? <VideoTrimmer /> : <Footer />}\n          </StyledFooter>\n        </LayerWithGrayout>\n        <SettingsModal />\n      </VideoRecordingTrimProvider>\n    </StyleSheetManager>\n  );\n}\n\nexport default MediaRecordingLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/multiSelectionMoveable/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  forwardRef,\n  useCombinedRefs,\n  useEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { useUnits } from '@googleforcreators/units';\nimport { useTransform } from '@googleforcreators/transform';\nimport { Moveable } from '@googleforcreators/moveable';\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport classnames from 'classnames';\nimport { useCanvas, useLayout, useStory } from '../../../app';\nimport objectWithout from '../../../utils/objectWithout';\nimport isTargetOutOfContainer from '../../../utils/isTargetOutOfContainer';\nimport useSnapping from '../utils/useSnapping';\nimport useUpdateSelectionRectangle from '../utils/useUpdateSelectionRectangle';\nimport useWindowResizeHandler from '../useWindowResizeHandler';\nimport useDrag from './useDrag';\nimport useResize from './useResize';\nimport useRotate from './useRotate';\n\nconst CORNER_HANDLES = ['nw', 'ne', 'sw', 'se'];\n\nconst MultiSelectionMoveable = forwardRef(function MultiSelectionMoveable(\n  { selectedElements, ...props },\n  ref\n) {\n  const moveable = useRef();\n  const [isDragging, setIsDragging] = useState(false);\n  const isAnyLayerLocked = selectedElements.some((el) => el.isLocked);\n  const actionsEnabled = !isAnyLayerLocked;\n\n  const { updateElementsById, deleteElementsById, backgroundElement } =\n    useStory((state) => ({\n      updateElementsById: state.actions.updateElementsById,\n      deleteElementsById: state.actions.deleteElementsById,\n      backgroundElement: state.state.currentPage.elements[0] ?? {},\n    }));\n  const { nodesById, fullbleedContainer } = useCanvas(\n    ({ state: { nodesById, fullbleedContainer } }) => ({\n      fullbleedContainer,\n      nodesById,\n    })\n  );\n  const { editorToDataX, editorToDataY } = useUnits((state) => ({\n    editorToDataX: state.actions.editorToDataX,\n    editorToDataY: state.actions.editorToDataY,\n  }));\n  const { zoomSetting, scrollLeft, scrollTop } = useLayout(\n    ({ state: { zoomSetting, scrollLeft, scrollTop } }) => ({\n      zoomSetting,\n      scrollLeft,\n      scrollTop,\n    })\n  );\n\n  const {\n    actions: { pushTransform },\n  } = useTransform();\n\n  useWindowResizeHandler(moveable);\n\n  // Update moveable with whatever properties could be updated outside moveable\n  // itself.\n  useEffect(() => {\n    if (moveable.current) {\n      moveable.current.updateRect();\n    }\n  }, [selectedElements, moveable, nodesById, scrollLeft, scrollTop]);\n\n  // If zoom ever updates, update selection rect\n  useUpdateSelectionRectangle(moveable, [zoomSetting]);\n\n  // Create targets list including nodes and also necessary attributes.\n  const targetList = selectedElements.map((element) => ({\n    element,\n    node: nodesById[element.id],\n    updateForResizeEvent: getDefinitionForType(element.type)\n      .updateForResizeEvent,\n  }));\n\n  /**\n   * Set style to the element.\n   *\n   * @param {Object} element Target element's id.\n   * @param {Object} target Target element node to update.\n   * @param {Object} frame Properties from the frame for that specific element.\n   */\n  const setTransformStyle = (element, target, frame) => {\n    const { id, border } = element;\n    target.style.transform = `translate(${frame.translate[0]}px, ${frame.translate[1]}px) rotate(${frame.rotate}deg)`;\n    // If the element has a border, we have to take it out of the resizing values\n    // since the border is in pixels and thus not stored within width/height.\n    // We add canSupportMultiBorder check to ignore non-rectangular shapes since the border works differently for those.\n    const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n    let frameForEl = { ...frame };\n    if (\n      (frame.resize[0] || frame.resize[1]) &&\n      canSupportMultiBorder(element)\n    ) {\n      const elWidth = frame.resize[0] - (left + right);\n      const elHeight = frame.resize[1] - (top + bottom);\n      frameForEl = {\n        ...frame,\n        resize: [elWidth, elHeight],\n      };\n    }\n    pushTransform(id, frameForEl);\n  };\n\n  const frames = targetList\n    ? targetList.map(({ element }) => ({\n        translate: [0, 0],\n        rotate: element.rotationAngle,\n        direction: [0, 0],\n        resize: [0, 0],\n        updates: null,\n      }))\n    : [];\n\n  /**\n   * Resets Moveable once the action is done, sets the initial values.\n   */\n  const resetMoveable = () => {\n    targetList.forEach(({ element, node }, i) => {\n      frames[i].direction = [0, 0];\n      frames[i].translate = [0, 0];\n      frames[i].resize = [0, 0];\n      frames[i].updates = null;\n      node.style.transform = '';\n      node.style.width = '';\n      node.style.height = '';\n      pushTransform(element.id, null);\n    });\n    if (moveable.current) {\n      moveable.current.updateRect();\n    }\n  };\n\n  const onGroupEventStart = ({ events, isDrag, isRotate }) => {\n    events.forEach((ev, i) => {\n      const sFrame = frames[i];\n      if (isDrag) {\n        ev.set(sFrame.translate);\n      } else if (isRotate) {\n        ev.set(sFrame.rotate);\n      }\n    });\n  };\n\n  // Update elements once the event has ended.\n  const onGroupEventEnd = ({ targets, isRotate, isResize }) => {\n    const updates = {};\n    const toRemove = [];\n    targets.forEach((target, i) => {\n      const { element, updateForResizeEvent } = targetList[i];\n      if (isTargetOutOfContainer(target, fullbleedContainer)) {\n        toRemove.push(element.id);\n        return;\n      }\n      // Update position in all cases.\n      const frame = frames[i];\n      const { direction } = frame;\n\n      const roundToZero = (num) => (Math.abs(num) <= 1 ? 0 : num);\n      const properties = {\n        x: roundToZero(element.x + editorToDataX(frame.translate[0])),\n        y: roundToZero(element.y + editorToDataY(frame.translate[1])),\n      };\n      if (isRotate) {\n        properties.rotationAngle = frame.rotate;\n      }\n      const [editorWidth, editorHeight] = frame.resize;\n      const didResize = editorWidth !== 0 && editorHeight !== 0;\n      if (isResize && didResize) {\n        // We remove the border from the width/height before updating the element since border is not included in those.\n        const { border } = element;\n        const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n        const newWidth = editorToDataX(editorWidth - (left + right));\n        const newHeight = editorToDataY(editorHeight - (top + bottom));\n        properties.width = newWidth;\n        properties.height = newHeight;\n        if (updateForResizeEvent) {\n          Object.assign(\n            properties,\n            updateForResizeEvent(element, direction, newWidth, newHeight)\n          );\n        }\n      }\n      updates[element.id] = properties;\n    });\n    updateElementsById({\n      elementIds: Object.keys(updates),\n      properties: (currentProperties) => updates[currentProperties.id],\n    });\n    if (toRemove.length > 0) {\n      deleteElementsById({ elementIds: toRemove });\n    }\n    resetMoveable();\n  };\n\n  // Get a list of all the other non-bg nodes\n  const otherNodes = Object.values(\n    objectWithout(nodesById, [\n      ...selectedElements.map((element) => element.id),\n      backgroundElement.id,\n    ])\n  );\n\n  const snapProps = useSnapping({\n    canSnap: true,\n    otherNodes,\n  });\n  const dragProps = useDrag({\n    targetList,\n    frames,\n    setTransformStyle,\n    onGroupEventStart,\n    onGroupEventEnd,\n    isDragging,\n    setIsDragging,\n  });\n  const resizeProps = useResize({\n    onGroupEventEnd,\n    targetList,\n    setTransformStyle,\n    frames,\n  });\n  const rotateProps = useRotate({\n    onGroupEventStart,\n    setTransformStyle,\n    onGroupEventEnd,\n    targetList,\n    frames,\n  });\n\n  const combinedRef = useCombinedRefs(moveable, ref);\n\n  // Not all targets have been defined yet.\n  if (targetList.some(({ node }) => node === undefined)) {\n    return null;\n  }\n\n  const classNames = classnames('default-moveable', {\n    'hide-handles': isDragging,\n    immoveable: isAnyLayerLocked,\n  });\n\n  return (\n    <Moveable\n      {...props}\n      className={classNames}\n      ref={combinedRef}\n      zIndex={0}\n      target={targetList.map(({ node }) => node)}\n      renderDirections={CORNER_HANDLES}\n      {...dragProps}\n      draggable={actionsEnabled}\n      resizable={actionsEnabled}\n      rotatable={actionsEnabled}\n      {...rotateProps}\n      {...resizeProps}\n      {...snapProps}\n    />\n  );\n});\n\nMultiSelectionMoveable.propTypes = {\n  selectedElements: PropTypes.arrayOf(PropTypes.object).isRequired,\n};\n\nexport default MultiSelectionMoveable;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/multiSelectionMoveable/useDrag.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport { areEventsDragging } from '@googleforcreators/moveable';\n\n/**\n * Internal dependencies\n */\nimport { useDropTargets } from '../../dropTargets';\nimport { useCanvas } from '../../../app';\n\nfunction useMultiSelectionDrag({\n  targetList,\n  frames,\n  setTransformStyle,\n  onGroupEventStart,\n  onGroupEventEnd,\n  isDragging,\n  setIsDragging,\n}) {\n  const { draggingResource } = useDropTargets(\n    ({ state: { draggingResource } }) => ({\n      draggingResource,\n    })\n  );\n  const { nodesById, handleSelectElement } = useCanvas(\n    ({ state: { nodesById }, actions: { handleSelectElement } }) => ({\n      nodesById,\n      handleSelectElement,\n    })\n  );\n\n  const eventTrackerRef = useRef({});\n\n  // Let's check if we consider this a drag or a click, In case of a click handle click instead.\n  // We are doing this here in Moveable selection since it takes over the mouseup event\n  // and it can be captured here and not in the frame element.\n  // @todo Add integration test for this!\n  const clickHandled = (inputEvent) => {\n    if (areEventsDragging(eventTrackerRef.current, inputEvent)) {\n      // No click was found/handled.\n      return false;\n    }\n\n    const clickedElement = Object.keys(nodesById).find((id) =>\n      nodesById[id].contains(inputEvent.target)\n    );\n    if (clickedElement) {\n      setTimeout(() => {\n        handleSelectElement(clickedElement, inputEvent);\n      }, 0);\n    }\n    // Click was handled.\n    return true;\n  };\n\n  const startEventTracking = (evt) => {\n    const { timeStamp, clientX, clientY } = evt;\n    eventTrackerRef.current = {\n      timeStamp,\n      clientX,\n      clientY,\n    };\n  };\n\n  const hideHandles = isDragging || Boolean(draggingResource);\n\n  const onDragGroup = ({ events }) => {\n    events.forEach(({ target, beforeTranslate }, i) => {\n      const sFrame = frames[i];\n      const { element } = targetList[i];\n      sFrame.translate = beforeTranslate;\n      setTransformStyle(element, target, sFrame);\n    });\n  };\n  const onDragGroupStart = ({ events, inputEvent }) => {\n    startEventTracking(inputEvent);\n    if (!isDragging) {\n      setIsDragging(true);\n    }\n    onGroupEventStart({ events, isDrag: true });\n  };\n  const onDragGroupEnd = ({ targets, inputEvent }) => {\n    setIsDragging(false);\n    if (!clickHandled(inputEvent)) {\n      onGroupEventEnd({ targets });\n    }\n  };\n\n  // When dragging, let's disable resizing, rotating and handles.\n  return {\n    onDragGroup,\n    onDragGroupEnd,\n    onDragGroupStart,\n    className: `default-moveable ${hideHandles ? 'hide-handles' : ''}`,\n    resizable: !hideHandles,\n    rotatable: !hideHandles,\n  };\n}\n\nexport default useMultiSelectionDrag;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/multiSelectionMoveable/useResize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useUnits } from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\nfunction useResize({ onGroupEventEnd, targetList, setTransformStyle, frames }) {\n  const { editorToDataX, editorToDataY, dataToEditorY, dataToEditorX } =\n    useUnits((state) => ({\n      editorToDataX: state.actions.editorToDataX,\n      editorToDataY: state.actions.editorToDataY,\n      dataToEditorY: state.actions.dataToEditorY,\n      dataToEditorX: state.actions.dataToEditorX,\n    }));\n\n  const onResizeGroupStart = ({ events }) => {\n    events.forEach((ev, i) => {\n      const frame = frames[i];\n      ev.setOrigin(['%', '%']);\n      if (ev.dragStart) {\n        ev.dragStart.set(frame.translate);\n      }\n    });\n  };\n\n  const onResizeGroup = ({ events }) => {\n    events.forEach(({ target, direction, width, height, drag }, i) => {\n      const sFrame = frames[i];\n      const { element, updateForResizeEvent } = targetList[i];\n      const { border, type } = element;\n      const { resizeRules } = getDefinitionForType(type);\n      const minWidth = dataToEditorX(resizeRules.minWidth);\n      const minHeight = dataToEditorY(resizeRules.minHeight);\n\n      const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n      // We remove the border in pixels since that's not saved to the width/height directly.\n      let newWidth = width - (left + right);\n      let newHeight = height - (top + bottom);\n\n      const aspectRatio = element.width / element.height;\n      if (newWidth < minWidth) {\n        newWidth = minWidth;\n        newHeight = newWidth / aspectRatio;\n      }\n      if (newHeight < minHeight) {\n        newHeight = minHeight;\n        newWidth = minHeight * aspectRatio;\n      }\n      let updates = null;\n      if (updateForResizeEvent) {\n        updates = updateForResizeEvent(\n          element,\n          direction,\n          editorToDataX(newWidth),\n          editorToDataY(newHeight)\n        );\n      }\n      if (updates && updates.height) {\n        newHeight = dataToEditorY(updates.height);\n      }\n\n      // We add the border size back for the target display.\n      const frameWidth = newWidth + left + right;\n      const frameHeight = newHeight + top + bottom;\n      target.style.width = `${frameWidth}px`;\n      target.style.height = `${frameHeight}px`;\n      sFrame.direction = direction;\n      sFrame.resize = [frameWidth, frameHeight];\n      sFrame.translate = drag.beforeTranslate;\n      sFrame.updates = updates;\n      setTransformStyle(element, target, sFrame);\n    });\n  };\n  const onResizeGroupEnd = ({ targets }) => {\n    onGroupEventEnd({ targets, isResize: true });\n  };\n  return {\n    onResizeGroup,\n    onResizeGroupStart,\n    onResizeGroupEnd,\n  };\n}\n\nexport default useResize;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/multiSelectionMoveable/useRotate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useGlobalIsKeyPressed } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport normalizeRotationDegrees from '../utils/normalizeRotationDegrees';\n\nfunction useRotate({\n  onGroupEventStart,\n  setTransformStyle,\n  onGroupEventEnd,\n  targetList,\n  frames,\n}) {\n  // ⇧ key rotates the element 30 degrees at a time\n  const throttleRotation = useGlobalIsKeyPressed('shift');\n\n  const onRotateGroupStart = ({ events }) => {\n    onGroupEventStart({ events, isRotate: true });\n  };\n  const onRotateGroup = ({ events }) => {\n    events.forEach(({ target, beforeRotate, drag }, i) => {\n      const sFrame = frames[i];\n      const { element } = targetList[i];\n      sFrame.rotate = normalizeRotationDegrees(beforeRotate);\n      sFrame.translate = drag.beforeTranslate;\n      setTransformStyle(element, target, sFrame);\n    });\n  };\n  const onRotateGroupEnd = ({ targets }) => {\n    onGroupEventEnd({ targets, isRotate: true });\n  };\n  return {\n    onRotateGroup,\n    onRotateGroupEnd,\n    onRotateGroupStart,\n    throttleRotate: throttleRotation ? 30 : 0,\n  };\n}\n\nexport default useRotate;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/navLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\nimport Proptypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_NAV_LAYER } from '../../constants/zIndex';\nimport { ChecklistCountProvider } from '../checklist';\nimport Footer from '../footer';\nimport DirectionAware from '../directionAware';\nimport PageSideMenu from './pageSideMenu';\nimport { FooterArea, HeadArea, Layer, PageMenuArea } from './layout';\n\nfunction NavLayer({ header, footer }) {\n  return (\n    <ChecklistCountProvider\n      hasChecklist={Boolean(footer?.secondaryMenu?.checklist)}\n    >\n      <Layer pointerEvents=\"none\" onMouseDown={(evt) => evt.stopPropagation()}>\n        <HeadArea pointerEvents=\"initial\" zIndex={Z_INDEX_NAV_LAYER}>\n          {header}\n        </HeadArea>\n        <DirectionAware>\n          <PageMenuArea>\n            <PageSideMenu />\n          </PageMenuArea>\n        </DirectionAware>\n        <FooterArea pointerEvents=\"initial\">\n          <Footer footer={footer} zIndex={Z_INDEX_NAV_LAYER} />\n        </FooterArea>\n      </Layer>\n    </ChecklistCountProvider>\n  );\n}\n\nNavLayer.propTypes = {\n  header: Proptypes.node,\n  footer: Proptypes.object,\n};\n\nexport default memo(NavLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pageAttachment/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { Placement, Popup } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useUnits } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas } from '../../../app';\nimport useElementsWithLinks from '../../../utils/useElementsWithLinks';\nimport { OUTLINK_THEME } from '../../../constants';\nimport DefaultIcon from './icons/defaultIcon.svg';\nimport ArrowIcon from './icons/arrowBar.svg';\n\nconst Wrapper = styled.div`\n  position: absolute;\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n  flex-direction: column;\n  bottom: 0;\n  height: 20%;\n  width: 100%;\n  color: ${({ theme }) => theme.colors.standard.white};\n  z-index: 3;\n`;\n\nconst Guideline = styled.div`\n  mix-blend-mode: difference;\n  position: absolute;\n  height: 1px;\n  bottom: 20%;\n  width: 100%;\n  background-image: ${({ theme }) =>\n    `linear-gradient(to right, ${theme.colors.standard.black} 50%, ${theme.colors.standard.white} 0%)`};\n  background-position: top;\n  background-size: 16px 0.5px;\n  background-repeat: repeat-x;\n  z-index: 3;\n`;\n\n// The CSS here is based on how it's displayed in the front-end, including static\n// font-size, line-height, etc. independent of the viewport size -- it's not responsive.\nconst ArrowBar = styled(ArrowIcon)`\n  display: block;\n  cursor: pointer;\n  margin-bottom: 10px;\n  filter: drop-shadow(0px 2px 6px rgba(0, 0, 0, 0.3));\n  width: 20px;\n  height: 8px;\n`;\n\nconst OutlinkChip = styled.div`\n  height: ${({ $factor }) => $factor(36)}px;\n  display: flex;\n  position: relative;\n  padding: ${({ $factor }) => $factor(10)}px ${({ $factor }) => $factor(6)}px;\n  margin: 0 0 20px;\n  max-width: calc(100% - 64px);\n  border-radius: 30px;\n  place-items: center;\n  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.15);\n  background: ${({ bgColor }) => bgColor};\n`;\n\nconst TextWrapper = styled.span`\n  font-family: Roboto, sans-serif;\n  font-size: ${({ $factor }) => $factor(16)}px;\n  line-height: 18px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  position: relative;\n  padding-inline-start: 6px;\n  padding-inline-end: 8px;\n  height: 16px;\n  letter-spacing: 0.3px;\n  font-weight: 700;\n  max-width: 210px;\n  color: ${({ fgColor }) => fgColor};\n`;\n\nconst Tooltip = styled.div`\n  background-color: ${({ theme }) => theme.colors.standard.black};\n  color: ${({ theme }) => theme.colors.standard.white};\n  width: 200px;\n  padding: 8px;\n  font-size: 14px;\n  border-radius: 4px;\n  text-align: center;\n`;\n\nconst LinkImage = styled.img`\n  height: 24px;\n  width: 24px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 0 none;\n  object-fit: contain;\n`;\n\nconst spacing = { x: 8 };\n\nconst LIGHT_COLOR = '#FFFFFF';\nconst DARK_COLOR = '#000000';\n\nfunction PageAttachment({ pageAttachment = {} }) {\n  const {\n    displayLinkGuidelines,\n    pageAttachmentContainer,\n    setPageAttachmentContainer,\n  } = useCanvas((state) => ({\n    displayLinkGuidelines: state.state.displayLinkGuidelines,\n    pageAttachmentContainer: state.state.pageAttachmentContainer,\n    setPageAttachmentContainer: state.actions.setPageAttachmentContainer,\n  }));\n\n  const { dataToEditorY } = useUnits(({ actions: { dataToEditorY } }) => ({\n    dataToEditorY,\n  }));\n\n  const { hasInvalidLinkSelected } = useElementsWithLinks();\n\n  const { ctaText, url, icon, theme } = pageAttachment;\n  const bgColor = theme === OUTLINK_THEME.DARK ? DARK_COLOR : LIGHT_COLOR;\n  const fgColor = theme === OUTLINK_THEME.DARK ? LIGHT_COLOR : DARK_COLOR;\n  return (\n    <>\n      {(displayLinkGuidelines || hasInvalidLinkSelected) && <Guideline />}\n      <Wrapper role=\"presentation\" ref={setPageAttachmentContainer}>\n        {url?.length > 0 && (\n          <>\n            <ArrowBar fill={bgColor} />\n            <OutlinkChip bgColor={bgColor} $factor={dataToEditorY}>\n              {icon ? (\n                <LinkImage\n                  src={icon}\n                  alt={__('Site Icon', 'web-stories')}\n                  decoding=\"async\"\n                  crossOrigin=\"anonymous\"\n                />\n              ) : (\n                <DefaultIcon\n                  fill={fgColor}\n                  width={dataToEditorY(24)}\n                  height={dataToEditorY(24)}\n                />\n              )}\n              <TextWrapper fgColor={fgColor} $factor={dataToEditorY}>\n                {ctaText || __('Learn more', 'web-stories')}\n              </TextWrapper>\n            </OutlinkChip>\n            {pageAttachmentContainer && hasInvalidLinkSelected && (\n              <Popup\n                anchor={{ current: pageAttachmentContainer }}\n                isOpen\n                placement={Placement.Left}\n                spacing={spacing}\n              >\n                <Tooltip>\n                  {__(\n                    'Links can not reside below the dashed line when a page attachment is present. Your viewers will not be able to click on the link.',\n                    'web-stories'\n                  )}\n                </Tooltip>\n              </Popup>\n            )}\n          </>\n        )}\n      </Wrapper>\n    </>\n  );\n}\n\nPageAttachment.propTypes = {\n  pageAttachment: PropTypes.shape({\n    url: PropTypes.string,\n    ctaText: PropTypes.string,\n    icon: PropTypes.string,\n    theme: PropTypes.string,\n    rel: PropTypes.arrayOf(PropTypes.string),\n  }),\n};\n\nexport default PageAttachment;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pageAttachment/karma/pageAttachment.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\nimport { screen, waitFor } from '@testing-library/react';\nimport useInsertElement from '../../useInsertElement';\nimport { useStory } from '../../../../app/story';\nimport { Fixture } from '../../../../karma';\n\ndescribe('Page Attachment', () => {\n  let fixture;\n  let frame;\n  let safezone;\n\n  const clickOnTarget = async (target) => {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n  };\n\n  const selectPage = async () => {\n    // Select page by clicking on the background element\n    await fixture.events.mouse.clickOn(\n      fixture.editor.canvas.framesLayer.frames[0].node,\n      10,\n      10\n    );\n  };\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    // Select Page by default.\n    await selectPage();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const moveElementToBottom = async () => {\n    safezone = fixture.querySelector('[data-testid=\"safezone\"]');\n    const safezoneHeight = safezone.getBoundingClientRect().height;\n    const frameHeight = frame.getBoundingClientRect().height;\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(frame, 10, 10),\n      down(),\n      moveBy(0, safezoneHeight - frameHeight, { steps: 10 }),\n      up(),\n    ]);\n  };\n\n  const addElement = async (withLink = true) => {\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    const element = await fixture.act(() =>\n      insertElement('shape', {\n        backgroundColor: createSolidFromString('#ff00ff'),\n        mask: { type: 'rectangle' },\n        x: 10,\n        y: 10,\n        width: 50,\n        height: 50,\n        link: withLink\n          ? {\n              url: 'https://example.com',\n            }\n          : null,\n      })\n    );\n    frame = fixture.editor.canvas.framesLayer.frame(element.id).node;\n  };\n\n  const setPageAttachmentLink = async (link) => {\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const input = fixture.screen.getByLabelText(\n      'Type an address to add a page attachment link'\n    );\n    await fixture.events.click(input, { clickCount: 3 });\n    if ('' === link) {\n      await fixture.events.keyboard.press('Del');\n    } else {\n      await fixture.events.keyboard.type(link);\n    }\n    await fixture.events.keyboard.press('tab');\n  };\n\n  const setCtaText = async (text) => {\n    const input = fixture.screen.getByLabelText('Call to Action text');\n    await fixture.events.click(input, { clickCount: 3 });\n    await fixture.events.keyboard.type(text);\n    await fixture.events.keyboard.press('tab');\n  };\n\n  describe('CUJ: Creator can Add a Page Attachment: Add Page Attachment', () => {\n    it('it should allow adding Page Attachment with custom CTA Text', async () => {\n      await setPageAttachmentLink('http://example.com');\n      await setCtaText('Click me!');\n      const ctaText = fixture.screen.getByText('Click me!');\n      expect(ctaText).toBeDefined();\n    });\n\n    it('it should allow using dark theme for Page Attachment', async () => {\n      await setPageAttachmentLink('http://example.test');\n      const input = fixture.screen.getByLabelText('Use dark theme');\n      await fixture.events.click(input);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.currentPage.pageAttachment.theme).toEqual(\n        'dark'\n      );\n    });\n\n    it('it should allow adding Page Attachment with custom CTA Text and icon', async () => {\n      await setPageAttachmentLink('http://example.com');\n      const editIcon = fixture.screen.getByRole('button', {\n        name: 'Edit link icon',\n      });\n      await fixture.events.click(editIcon);\n      const uploadButton = fixture.screen.getByRole('menuitem', {\n        name: 'Upload a file',\n      });\n      expect(uploadButton).toBeDefined();\n      await fixture.events.click(uploadButton);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n\n      expect(storyContext.state.currentPage.pageAttachment.icon).toEqual(\n        'http://localhost:9876/__static__/saturn.jpg'\n      );\n    });\n\n    it('it should allow adding Page Attachment with custom hotlink icon', async () => {\n      await setPageAttachmentLink('http://example.com');\n      const editIcon = fixture.screen.getByRole('button', {\n        name: 'Edit link icon',\n      });\n      await fixture.events.click(editIcon);\n      const fileButton = fixture.screen.getByRole('menuitem', {\n        name: 'Link to a file',\n      });\n      expect(fileButton).toBeDefined();\n      await fixture.events.click(fileButton);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as link icon',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type(\n        'http://localhost:9876/__static__/icon.png'\n      );\n\n      await fixture.events.click(insertBtn);\n      await waitFor(\n        async () => {\n          const storyContext = await fixture.renderHook(() => useStory());\n          // Check if the background audio source is set\n          if (!storyContext.state.currentPage?.pageAttachment?.icon) {\n            throw new Error('icon not ready');\n          }\n          expect(storyContext.state.currentPage.pageAttachment.icon).toEqual(\n            'http://localhost:9876/__static__/icon.png'\n          );\n        },\n        {\n          timeout: 1500,\n        }\n      );\n    });\n\n    it('it should allow adding Page Attachment with custom invalid icon', async () => {\n      await setPageAttachmentLink('http://example.com');\n      const editIcon = fixture.screen.getByRole('button', {\n        name: 'Edit link icon',\n      });\n      await fixture.events.click(editIcon);\n      const fileButton = fixture.screen.getByRole('menuitem', {\n        name: 'Link to a file',\n      });\n      expect(fileButton).toBeDefined();\n      await fixture.events.click(fileButton);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as link icon',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type(\n        'http://localhost:9876/__static__/saturn.jpg'\n      );\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        const dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        if (\n          -1 ===\n          dialog.textContent.indexOf('do not match required image dimensions')\n        ) {\n          throw new Error('dimensions not available');\n        }\n        expect(dialog.textContent).toContain(\n          'do not match required image dimensions'\n        );\n      });\n    });\n\n    it('it should allow adding Page Attachment with custom CTA Text and invalid icon url', async () => {\n      await setPageAttachmentLink('http://example.com');\n      const editIcon = fixture.screen.getByRole('button', {\n        name: 'Edit link icon',\n      });\n      await fixture.events.click(editIcon);\n      const fileButton = fixture.screen.getByRole('menuitem', {\n        name: 'Link to a file',\n      });\n      expect(fileButton).toBeDefined();\n      await fixture.events.click(fileButton);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as link icon',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type('invalid');\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        const dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        expect(dialog.textContent).toContain('Invalid link');\n      });\n    });\n\n    it('it should display warning for a link in the Page Attachment Area', async () => {\n      await addElement();\n      await moveElementToBottom();\n      await clickOnTarget(safezone);\n      await setPageAttachmentLink('');\n      const warning = fixture.screen.getByText(\n        'Links cannot reside below the dashed line when a page attachment is present. If you add a page attachment, your viewers will not be able to click on the link.'\n      );\n      expect(warning).toBeDefined();\n    });\n  });\n\n  describe('CUJ: Creator can Add a Page Attachment: Remove Page Attachment', () => {\n    it('it should allow removing a Page Attachment', async () => {\n      await setPageAttachmentLink('http://example.com');\n      await setCtaText('Click me!');\n      const ctaText = fixture.screen.getByText('Click me!');\n      expect(ctaText).toBeDefined();\n\n      await setPageAttachmentLink('');\n      expect(fixture.screen.queryByText('Click me!')).toBeNull();\n    });\n  });\n\n  describe('CUJ: Creator can Add a Page Attachment: Adding link to element in Attachment area', () => {\n    it('it should not allow adding link to Attachment area', async () => {\n      await setPageAttachmentLink('http://example.com');\n      await addElement(false);\n      await moveElementToBottom();\n\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      const input = fixture.screen.getByLabelText('Element link');\n      await fixture.events.click(input);\n\n      // Verify that the warning is displayed.\n      const warning = fixture.screen.getByText(\n        'Link can not reside below the dashed line when a page attachment is present'\n      );\n      expect(warning).toBeDefined();\n\n      await fixture.events.keyboard.type('example.com');\n      await fixture.events.keyboard.press('tab');\n\n      // Verify the link is still null after typing.\n      const {\n        state: {\n          currentPage: {\n            elements: [{ link }],\n          },\n        },\n      } = await fixture.renderHook(() => useStory());\n      expect(link).toBeUndefined();\n    });\n  });\n\n  describe('CUJ: Creator can Add a Page Attachment: Shopping Attachment', () => {\n    it('it should allow changing the CTA text', async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      await fixture.act(() =>\n        insertElement('product', {\n          x: 10,\n          y: 10,\n          width: 50,\n          height: 50,\n          product: {\n            productId: 'foobar',\n          },\n        })\n      );\n\n      await selectPage();\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await setCtaText('Click me!');\n      const ctaText = fixture.screen.getByText('Click me!');\n      expect(ctaText).toBeDefined();\n    });\n\n    it('it should allow using dark theme for the shopping ttachment', async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      await fixture.act(() =>\n        insertElement('product', {\n          x: 10,\n          y: 10,\n          width: 50,\n          height: 50,\n          product: {\n            productId: 'foobar',\n          },\n        })\n      );\n\n      await selectPage();\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      const input = fixture.screen.getByLabelText('Use dark theme');\n      await fixture.events.click(input);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.currentPage.shoppingAttachment.theme).toEqual(\n        'dark'\n      );\n    });\n\n    it('it should not allow adding a page attachment if there are products', async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      await fixture.act(() =>\n        insertElement('product', {\n          x: 10,\n          y: 10,\n          width: 50,\n          height: 50,\n          product: {\n            productId: 'foobar',\n          },\n        })\n      );\n\n      await selectPage();\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      expect(\n        fixture.screen.queryByLabelText(\n          'Type an address to add a page attachment link'\n        )\n      ).toBeNull();\n    });\n\n    it('it should not use page attachment CTA text for shopping attachment', async () => {\n      await setPageAttachmentLink('http://example.com');\n      await setCtaText('Click me!');\n\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      await fixture.act(() =>\n        insertElement('product', {\n          x: 10,\n          y: 10,\n          width: 50,\n          height: 50,\n          product: {\n            productId: 'foobar',\n          },\n        })\n      );\n\n      await selectPage();\n\n      await setCtaText('Shop me!');\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      expect(fixture.screen.queryByText('Click me!')).toBeNull();\n\n      const ctaText = fixture.screen.getByText('Shop me!');\n      expect(ctaText).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pageAttachment/test/pageAttachment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\nimport {\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n  UnitsProvider,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport PageAttachment from '..';\nimport CanvasContext from '../../../../app/canvas/context';\nimport StoryContext from '../../../../app/story/context';\nimport { ConfigProvider } from '../../../../app/config';\nimport getDefaultConfig from '../../../../getDefaultConfig';\n\nfunction setup(props = {}) {\n  const { pageAttachment = {}, canvasProps = null } = props;\n  const canvasContext = {\n    state: {\n      pageSize: {},\n      displayLinkGuidelines: false,\n      pageAttachmentContainer: null,\n      currentPage: {\n        elements: [],\n      },\n      ...canvasProps,\n    },\n    actions: { setPageAttachmentContainer: jest.fn() },\n  };\n  const storyContext = {\n    state: {\n      currentPage: {\n        elements: [],\n      },\n    },\n  };\n  return renderWithTheme(\n    <ConfigProvider config={getDefaultConfig()}>\n      <StoryContext.Provider value={storyContext}>\n        <CanvasContext.Provider value={canvasContext}>\n          <UnitsProvider\n            pageSize={{\n              height: PAGE_HEIGHT,\n              width: PAGE_WIDTH,\n            }}\n            dataToEditorY={jest.fn()}\n          >\n            <PageAttachment pageAttachment={pageAttachment} />\n          </UnitsProvider>\n        </CanvasContext.Provider>\n      </StoryContext.Provider>\n    </ConfigProvider>\n  );\n}\n\ndescribe('PageAttachment', () => {\n  it('should display only wrapper in case of empty Page Attachment', () => {\n    setup();\n    const pageAttachment = screen.getByRole('presentation');\n    expect(pageAttachment).toBeInTheDocument();\n    expect(pageAttachment).toBeEmptyDOMElement();\n  });\n\n  it('should display the configured Page Attachment', () => {\n    setup({\n      pageAttachment: { url: 'http://example.test', ctaText: 'Click me!' },\n    });\n    const ctaText = screen.getByText('Click me!');\n    expect(ctaText).toBeInTheDocument();\n  });\n\n  it('should display default CTA Text if none set', () => {\n    setup({\n      pageAttachment: { url: 'http://example.test' },\n    });\n    const ctaText = screen.getByText('Learn more');\n    expect(ctaText).toBeInTheDocument();\n  });\n\n  it('should display dotted line if link found in the area', () => {\n    setup({\n      canvasProps: {\n        displayLinkGuidelines: true,\n      },\n    });\n    const pageAttachment = screen.getByRole('presentation');\n    // The guiding line is always displayed right before the page attachment, on the same level.\n    // eslint-disable-next-line testing-library/no-node-access\n    const guideline = pageAttachment.previousSibling;\n    expect(guideline).toBeInTheDocument();\n    const style = window.getComputedStyle(guideline);\n    // Verify the background was added for displaying dashed line.\n    expect(style.backgroundSize).toBe('16px 0.5px');\n    expect(style.backgroundPosition).toBe('top');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pageSideMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n  noop,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport { Fragment } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../app';\nimport { MediaPicker, useQuickActions } from '../../app/quickActions';\nimport { ZoomSetting } from '../../constants';\nimport {\n  Z_INDEX_CANVAS_SIDE_MENU,\n  Z_INDEX_CANVAS_SIDE_MENU_RECORDING_MODE,\n} from '../../constants/zIndex';\nimport Tooltip from '../tooltip';\nimport { useMediaRecording } from '../mediaRecording';\nimport PageMenu from './pagemenu/pageMenu';\n\nconst MenusWrapper = styled.section`\n  position: absolute;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: space-between;\n  z-index: ${({ $zIndex }) => $zIndex};\n  pointer-events: none;\n  min-height: 100%;\n  ${({ isZoomed, theme }) =>\n    isZoomed &&\n    `\n    min-height: initial;\n    background-color: ${rgba(theme.colors.standard.black, 0.45)};\n    border-radius: ${theme.borders.radius.small};\n    padding: 8px;\n    margin-left: -24px;\n  `}\n`;\n\nconst Divider = styled.div`\n  width: 20px;\n  height: 1px;\n  margin: 13px auto 1px;\n  background-color: ${({ theme }) => theme.colors.divider.primary};\n`;\n\nconst StyledContextMenu = styled(ContextMenu)`\n  pointer-events: all;\n`;\n\nfunction PageSideMenu() {\n  const { zoomSetting } = useLayout(({ state: { zoomSetting } }) => ({\n    zoomSetting,\n  }));\n  const quickActions = useQuickActions();\n\n  const { isInRecordingMode } = useMediaRecording(\n    ({ state: { isInRecordingMode } }) => ({ isInRecordingMode })\n  );\n\n  const isZoomed = zoomSetting !== ZoomSetting.Fit;\n\n  return (\n    <MenusWrapper\n      aria-label={__('Page side menu', 'web-stories')}\n      isZoomed={isZoomed}\n      $zIndex={\n        isInRecordingMode\n          ? Z_INDEX_CANVAS_SIDE_MENU_RECORDING_MODE\n          : Z_INDEX_CANVAS_SIDE_MENU\n      }\n    >\n      {\n        // Dont render a menu wrapper if there are no quick actions\n        quickActions.length ? (\n          <StyledContextMenu\n            isInline\n            isAlwaysVisible\n            isIconMenu\n            disableControlledTabNavigation\n            data-testid=\"Element quick actions\"\n            aria-label={__(\n              'Group of available options for selected element',\n              'web-stories'\n            )}\n            onMouseDown={(e) => {\n              // Stop the event from bubbling if the user clicks in between buttons.\n              // This prevents the selected element in the canvas from losing focus.\n              e.stopPropagation();\n            }}\n          >\n            {quickActions.map(\n              ({\n                Icon,\n                label,\n                onClick,\n                separator,\n                tooltipPlacement,\n                wrapWithMediaPicker,\n                ...quickAction\n              }) => {\n                const action = (externalOnClick = noop) => (\n                  <Fragment key={label}>\n                    {separator === 'top' && (\n                      <ContextMenuComponents.MenuSeparator />\n                    )}\n                    <Tooltip placement={tooltipPlacement} title={label}>\n                      <ContextMenuComponents.MenuButton\n                        aria-label={label}\n                        onClick={(evt) => {\n                          onClick(evt);\n\n                          externalOnClick(evt);\n                        }}\n                        {...quickAction}\n                      >\n                        <ContextMenuComponents.MenuIcon title={label}>\n                          <Icon />\n                        </ContextMenuComponents.MenuIcon>\n                      </ContextMenuComponents.MenuButton>\n                    </Tooltip>\n                    {separator === 'bottom' && (\n                      <ContextMenuComponents.MenuSeparator />\n                    )}\n                  </Fragment>\n                );\n\n                if (wrapWithMediaPicker) {\n                  return (\n                    <MediaPicker\n                      key={label}\n                      render={({ onClick: openMediaPicker }) =>\n                        action(openMediaPicker)\n                      }\n                    />\n                  );\n                }\n\n                return action();\n              }\n            )}\n          </StyledContextMenu>\n        ) : null\n      }\n      {!isInRecordingMode && (\n        <>\n          {isZoomed && <Divider />}\n          <PageMenu />\n        </>\n      )}\n    </MenusWrapper>\n  );\n}\n\nexport default PageSideMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pagemenu/animationToggle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { Icons } from '@googleforcreators/design-system';\nimport { StoryAnimationState } from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport PageMenuButton from './pageMenuButton';\n\nfunction AnimationToggle() {\n  const { animationState, updateAnimationState, isFirstPage } = useStory(\n    ({\n      state: { animationState, currentPageNumber },\n      actions: { updateAnimationState },\n    }) => {\n      const _isFirstPage = currentPageNumber === 1;\n      return {\n        animationState,\n        updateAnimationState,\n        isFirstPage: _isFirstPage,\n      };\n    }\n  );\n  const isPlaying = [\n    StoryAnimationState.Playing,\n    StoryAnimationState.PlayingSelected,\n  ].includes(animationState);\n\n  const tooltip = isFirstPage\n    ? __('Animations Disabled', 'web-stories')\n    : isPlaying\n      ? __('Stop', 'web-stories')\n      : __('Play', 'web-stories');\n  const label = isFirstPage\n    ? __('Page Animations Disabled', 'web-stories')\n    : isPlaying\n      ? __('Stop Page Animations', 'web-stories')\n      : __('Play Page Animations', 'web-stories');\n  const shortcut = isFirstPage ? null : 'mod+enter';\n  const Icon = isPlaying ? Icons.StopOutline : Icons.PlayOutline;\n\n  const toggleAnimationState = useCallback(() => {\n    updateAnimationState({\n      animationState: isPlaying\n        ? StoryAnimationState.Reset\n        : StoryAnimationState.Playing,\n    });\n\n    trackEvent('canvas_play_animations', {\n      status: isPlaying ? 'stop' : 'play',\n    });\n  }, [isPlaying, updateAnimationState]);\n\n  return (\n    <PageMenuButton\n      title={tooltip}\n      shortcut={shortcut}\n      onClick={toggleAnimationState}\n      aria-label={label}\n      disabled={isFirstPage}\n    >\n      <Icon />\n    </PageMenuButton>\n  );\n}\n\nexport default AnimationToggle;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pagemenu/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './pageMenu';\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pagemenu/pageMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { memo, useCallback, useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport { createPage, duplicatePage } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport usePerformanceTracking from '../../../utils/usePerformanceTracking';\nimport { TRACKING_EVENTS } from '../../../constants';\nimport PageMenuButton from './pageMenuButton';\nimport AnimationToggle from './animationToggle';\n\nconst Wrapper = styled.div`\n  margin-top: auto;\n  padding: 0 4px;\n  pointer-events: all;\n`;\n\nfunction PageMenu() {\n  const {\n    currentPage,\n    numberOfPages,\n    deleteCurrentPage,\n    addPage,\n    hasVisibleAnimations,\n  } = useStory(\n    ({\n      state: { currentPage, pages },\n      actions: { deleteCurrentPage, addPage },\n    }) => {\n      return {\n        currentPage,\n        numberOfPages: pages.length,\n        deleteCurrentPage,\n        addPage,\n        hasVisibleAnimations: currentPage?.animations?.some((animation) =>\n          animation.targets.some(\n            (id) =>\n              !currentPage.elements.find((element) => element.id === id)\n                ?.isHidden\n          )\n        ),\n      };\n    }\n  );\n\n  const addPageButtonRef = useRef(null);\n  const deletePageButtonRef = useRef(null);\n\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: addPageButtonRef.current,\n    eventData: TRACKING_EVENTS.PAGE_ADD,\n  });\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: deletePageButtonRef.current,\n    eventData: TRACKING_EVENTS.PAGE_DELETE,\n  });\n\n  const handleDeletePage = useCallback(\n    () => deleteCurrentPage(),\n    [deleteCurrentPage]\n  );\n\n  const handleAddPage = useCallback(\n    () => addPage({ page: createPage() }),\n    [addPage]\n  );\n\n  const handleDuplicatePage = useCallback(\n    () => addPage({ page: duplicatePage(currentPage) }),\n    [addPage, currentPage]\n  );\n\n  const disableDeleteButton = numberOfPages <= 1;\n\n  if (!currentPage) {\n    return null;\n  }\n\n  return (\n    <Wrapper role=\"group\" aria-label={__('Page actions', 'web-stories')}>\n      {hasVisibleAnimations && <AnimationToggle />}\n      <PageMenuButton\n        ref={addPageButtonRef}\n        title={__('New Page', 'web-stories')}\n        onClick={handleAddPage}\n        aria-label={__('Add New Page', 'web-stories')}\n      >\n        <Icons.PlusOutline />\n      </PageMenuButton>\n      <PageMenuButton\n        title={__('Duplicate Page', 'web-stories')}\n        onClick={handleDuplicatePage}\n        aria-label={__('Duplicate Page', 'web-stories')}\n      >\n        <Icons.PagePlus />\n      </PageMenuButton>\n      <PageMenuButton\n        ref={deletePageButtonRef}\n        title={__('Delete Page', 'web-stories')}\n        disabled={disableDeleteButton}\n        onClick={handleDeletePage}\n        aria-label={__('Delete Page', 'web-stories')}\n      >\n        <Icons.Trash />\n      </PageMenuButton>\n    </Wrapper>\n  );\n}\n\n// Don't rerender the page menu needlessly e.g. on element selection change.\nexport default memo(PageMenu);\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pagemenu/pageMenuButton.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonVariant,\n  ButtonType,\n  ButtonSize,\n  Placement,\n} from '@googleforcreators/design-system';\nimport { forwardRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../tooltip';\n\nconst StyledButton = styled(Button)`\n  margin-top: 12px;\n`;\n\nfunction PageMenuButtonWithRef(\n  { children, title, shortcut, ...rest },\n  forwardedRef\n) {\n  return (\n    <Tooltip\n      title={title}\n      shortcut={shortcut}\n      placement={Placement.Right}\n      hasTail\n    >\n      <StyledButton\n        variant={ButtonVariant.Square}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        ref={forwardedRef}\n        {...rest}\n      >\n        {children}\n      </StyledButton>\n    </Tooltip>\n  );\n}\n\nconst PageMenuButton = forwardRef(PageMenuButtonWithRef);\n\nPageMenuButton.propTypes = {\n  children: PropTypes.node,\n  title: PropTypes.string,\n  shortcut: PropTypes.string,\n};\n\nPageMenuButtonWithRef.propTypes = PageMenuButton.propTypes;\n\nexport default PageMenuButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/pagenav/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  Icons,\n  ButtonVariant,\n  ButtonType,\n  ButtonSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig, useStory, useLayout } from '../../../app';\nimport usePerformanceTracking from '../../../utils/usePerformanceTracking';\nimport { TRACKING_EVENTS } from '../../../constants';\n\nconst Wrapper = styled.div`\n  display: flex;\n  align-items: center;\n  color: ${({ theme }) => theme.colors.fg.white};\n\n  & > * {\n    pointer-events: initial;\n  }\n`;\n\nconst FlippableArrow = styled(Icons.ArrowLeftLarge)`\n  transform: rotate(${({ $isLeft }) => ($isLeft ? 0 : 0.5)}turn);\n`;\n\nfunction PageNav({ isNext = true }) {\n  const { pages, currentPageIndex, setCurrentPage } = useStory(\n    ({ state: { pages, currentPageIndex }, actions: { setCurrentPage } }) => ({\n      pages,\n      currentPageIndex,\n      setCurrentPage,\n    })\n  );\n  const { isRTL } = useConfig();\n  const buttonRef = useRef(null);\n\n  // Cancel lasso on mouse down\n  const cancelMouseDown = useCallback((evt) => evt.stopPropagation(), []);\n  const handleClick = useCallback(() => {\n    const newPage = isNext\n      ? pages[currentPageIndex + 1]\n      : pages[currentPageIndex - 1];\n    if (newPage) {\n      setCurrentPage({ pageId: newPage.id });\n    }\n  }, [setCurrentPage, currentPageIndex, isNext, pages]);\n\n  const { hasPageNavigation } = useLayout(\n    ({ state: { hasPageNavigation } }) => ({\n      hasPageNavigation,\n    })\n  );\n\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: buttonRef.current,\n    eventData: TRACKING_EVENTS.PAGE_NAVIGATION,\n  });\n\n  // Buttons are completely missing if there's no room for them\n  if (!hasPageNavigation) {\n    return false;\n  }\n\n  // If there's room, but it's inactive, just disable\n  const displayNav =\n    (isNext && currentPageIndex < pages.length - 1) ||\n    (!isNext && currentPageIndex > 0);\n\n  // If reading direction is RTL and this is next button, it's pointing left.\n  // If reading direction is !RTL and this is !next button, it's pointing left.\n  // Otherwise it's a right.\n  // Thus, if the two bools are equal, it's a left button.\n  const isLeft = isRTL === isNext;\n\n  return (\n    <Wrapper>\n      <Button\n        ref={buttonRef}\n        variant={ButtonVariant.Square}\n        type={ButtonType.Tertiary}\n        size={ButtonSize.Medium}\n        aria-disabled={!displayNav}\n        aria-label={\n          isNext\n            ? __('Next Page', 'web-stories')\n            : __('Previous Page', 'web-stories')\n        }\n        onClick={handleClick}\n        onMouseDown={cancelMouseDown}\n      >\n        <FlippableArrow $isLeft={isLeft} />\n      </Button>\n    </Wrapper>\n  );\n}\n\nPageNav.propTypes = {\n  isNext: PropTypes.bool,\n};\n\nexport default PageNav;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/renderResourcePlaceholder.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { Blurhash } from 'react-blurhash';\n\n/**\n * Internal dependencies\n */\nimport { HideOnError } from '../hideOnError';\n\nconst placeholderStyles = css`\n  position: absolute !important;\n  top: 0;\n  left: 0;\n  height: 100%;\n  width: 100%;\n`;\n\nconst BlurhashContainer = styled(Blurhash)`\n  ${placeholderStyles}\n`;\n\nconst BaseColorContainer = styled.div`\n  ${placeholderStyles}\n  background-color: ${({ $baseColor }) => $baseColor};\n`;\n\nfunction renderResourcePlaceholder({ blurHash, baseColor }) {\n  if (blurHash) {\n    return (\n      <HideOnError>\n        <BlurhashContainer\n          hash={blurHash}\n          punch={1}\n          height=\"100%\"\n          width=\"100%\"\n        />\n      </HideOnError>\n    );\n  }\n\n  if (baseColor) {\n    return <BaseColorContainer $baseColor={baseColor} />;\n  }\n\n  return null;\n}\nexport default renderResourcePlaceholder;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/rightClickMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { StyleSheetManager } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { ContextMenu } from '@googleforcreators/design-system';\nimport {\n  createPortal,\n  useEffect,\n  useMemo,\n  useRef,\n} from '@googleforcreators/react';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useRightClickMenu, useConfig } from '../../app';\nimport DirectionAware from '../directionAware';\nimport { useStory } from '../../app/story';\nimport {\n  ForegroundMediaMenu,\n  MultipleElementsMenu,\n  PageMenu,\n  ShapeMenu,\n  StickerMenu,\n  TextMenu,\n  ProductMenu,\n} from '../../app/rightClickMenu';\nimport isEmptyStory from '../../app/story/utils/isEmptyStory';\nimport EmptyStateMenu from '../../app/rightClickMenu/menus/emptyStateMenu';\n\nconst RightClickMenuContainer = styled.div`\n  position: absolute;\n  top: ${({ position }) => position?.y ?? 0}px;\n  left: ${({ position }) => position?.x ?? 0}px;\n  z-index: 9999;\n`;\n\nconst RightClickMenu = () => {\n  const { isRTL } = useConfig();\n  const { selectedElements, isThisEmptyStory } = useStory((value) => ({\n    selectedElements: value.state.selectedElements,\n    isThisEmptyStory: isEmptyStory(value.state.pages),\n  }));\n  const { isMenuOpen, menuPosition, onCloseMenu, maskRef } =\n    useRightClickMenu();\n  const ref = useRef();\n\n  /**\n   * Prevent browser's context menu when right clicking on custom ContextMenu\n   *\n   * @param {Object} evt Triggering event\n   */\n  const preventAdditionalContext = (evt) => {\n    evt.preventDefault();\n    evt.stopPropagation();\n  };\n\n  const Menu = useMemo(() => {\n    if (isThisEmptyStory) {\n      return EmptyStateMenu;\n    }\n\n    // TODO: First fix the right click with multi-elements in the Layers Panel\n    // const isOnlyGroupSelected = selectedElements.every(\n    //   (el) => el.groupId && el.groupId === selectedElements[0].groupId\n    // );\n    // if (isOnlyGroupSelected) {\n    //   return GroupMenu;\n    // }\n\n    if (selectedElements.length > 1) {\n      return MultipleElementsMenu;\n    }\n\n    const selectedElement = selectedElements?.[0];\n\n    if (selectedElement?.isDefaultBackground) {\n      return PageMenu;\n    }\n\n    switch (selectedElement?.type) {\n      case ELEMENT_TYPES.IMAGE:\n      case ELEMENT_TYPES.VIDEO:\n      case ELEMENT_TYPES.GIF:\n        return selectedElement?.isBackground ? PageMenu : ForegroundMediaMenu;\n      case ELEMENT_TYPES.SHAPE:\n        return ShapeMenu;\n      case ELEMENT_TYPES.TEXT:\n        return TextMenu;\n      case ELEMENT_TYPES.STICKER:\n        return StickerMenu;\n      case ELEMENT_TYPES.PRODUCT:\n        return ProductMenu;\n      case ELEMENT_TYPES.AUDIO_STICKER:\n        // NOTE: Using same options for this case as Products.\n        return ProductMenu;\n      default:\n        return PageMenu;\n    }\n  }, [selectedElements, isThisEmptyStory]);\n\n  useEffect(() => {\n    const node = ref.current;\n\n    node.addEventListener('contextmenu', preventAdditionalContext);\n    return () => {\n      node.removeEventListener('contextmenu', preventAdditionalContext);\n    };\n  }, [ref]);\n\n  return createPortal(\n    <StyleSheetManager stylisPlugins={[]}>\n      <RightClickMenuContainer position={menuPosition} ref={ref}>\n        <DirectionAware>\n          <ContextMenu\n            data-testid=\"right-click-context-menu\"\n            isOpen={isMenuOpen}\n            onDismiss={onCloseMenu}\n            aria-label={__(\n              'Context Menu for the selected element',\n              'web-stories'\n            )}\n            maskRef={maskRef}\n            onMouseDown={(evt) => evt.stopPropagation()}\n            isRTL={isRTL}\n          >\n            {/* eslint-disable-next-line react-hooks/static-components -- FIXME */}\n            <Menu parentMenuRef={ref} />\n          </ContextMenu>\n        </DirectionAware>\n      </RightClickMenuContainer>\n    </StyleSheetManager>,\n    document.body\n  );\n};\n\nexport default RightClickMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/selection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../app';\nimport SingleSelectionMoveable from './singleSelectionMoveable';\nimport MultiSelectionMoveable from './multiSelectionMoveable';\n\nfunction Selection(props) {\n  const isBackground = useStory(({ state }) => {\n    return (\n      state.selectedElements[0]?.id === state.currentPage?.elements?.[0]?.id\n    );\n  });\n  const { selectedElements, isAnimating } = useStory((state) => ({\n    selectedElements: state.state.selectedElements,\n    isAnimating: [\n      StoryAnimationState.Playing,\n      StoryAnimationState.PlayingSelected,\n      StoryAnimationState.Scrubbing,\n    ].includes(state.state.animationState),\n  }));\n  const { editingElement, lastSelectionEvent, nodesById, onMoveableMount } =\n    useCanvas(\n      ({\n        state: {\n          editingElement,\n          lastSelectionEvent,\n          nodesById,\n          onMoveableMount,\n        },\n      }) => ({\n        editingElement,\n        lastSelectionEvent,\n        nodesById,\n        onMoveableMount,\n      })\n    );\n\n  // No selection.\n  if (selectedElements.length === 0) {\n    return null;\n  }\n\n  // No need for displaying non-functional frame for selected background.\n  if (isBackground) {\n    return null;\n  }\n\n  // No need for displaying non-functional frame for video placeholders.\n  const isVideoPlaceholder = selectedElements[0]?.resource?.isPlaceholder;\n  if (isVideoPlaceholder) {\n    return null;\n  }\n\n  // Do not show selection for in editing mode.\n  if (editingElement || isAnimating) {\n    return null;\n  }\n\n  // Single selection.\n  if (selectedElements.length === 1) {\n    const selectedElement = selectedElements[0];\n    const target = nodesById[selectedElement.id];\n    if (!target) {\n      // Target not ready yet.\n      return null;\n    }\n    return (\n      <SingleSelectionMoveable\n        selectedElement={selectedElement}\n        targetEl={target}\n        pushEvent={lastSelectionEvent}\n        {...props}\n        {...(onMoveableMount && { ref: onMoveableMount })}\n      />\n    );\n  }\n\n  // Multi-selection.\n  return (\n    <MultiSelectionMoveable\n      selectedElements={selectedElements}\n      {...props}\n      {...(onMoveableMount && { ref: onMoveableMount })}\n    />\n  );\n}\n\nexport default Selection;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/selectionCanvas.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useEffect, useRef, useCallback } from '@googleforcreators/react';\nimport { withOverlay, InOverlay } from '@googleforcreators/moveable';\nimport SAT from 'sat';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../app';\nimport { STABLE_ARRAY } from '../../constants';\nimport useElementPolygon from '../../utils/useElementPolygon';\n\nconst LASSO_ACTIVE_THRESHOLD = 10;\n\nconst LassoMode = {\n  OFF: 0,\n  ON: 1,\n  MAYBE: 2,\n};\n\nconst Container = withOverlay(styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  width: 100%;\n  height: 100%;\n  user-select: none;\n`);\n\nconst Lasso = styled.div`\n  display: none;\n  position: absolute;\n  border: 1px dotted ${({ theme }) => theme.colors.border.selection};\n  z-index: 1;\n`;\n\nfunction SelectionCanvas({ children }) {\n  // Have page elements shallowly equaled for scenarios like animation\n  // updates where elements don't change, but we get a new page elements\n  // array\n  const currentPageElements = useStory(\n    ({ state }) => state.currentPage?.elements || STABLE_ARRAY\n  );\n  const { selectedElements, clearSelection, setSelectedElementsById } =\n    useStory(\n      ({\n        state: { selectedElements },\n        actions: { clearSelection, setSelectedElementsById },\n      }) => ({\n        selectedElements,\n        clearSelection,\n        setSelectedElementsById,\n      })\n    );\n\n  const { isEditing, nodesById, clearEditing } = useCanvas(\n    ({ state: { isEditing, nodesById }, actions: { clearEditing } }) => {\n      return {\n        isEditing,\n        nodesById,\n        clearEditing,\n      };\n    }\n  );\n\n  const overlayRef = useRef(null);\n  const lassoRef = useRef(null);\n  const startRef = useRef([0, 0]);\n  const endRef = useRef([0, 0]);\n  const lassoModeRef = useRef(LassoMode.OFF);\n\n  const getLassoBox = useCallback(() => {\n    const [x1, y1] = startRef.current;\n    const [x2, y2] = endRef.current;\n    const x = Math.min(x1, x2);\n    const y = Math.min(y1, y2);\n    const w = Math.abs(x1 - x2);\n    const h = Math.abs(y1 - y2);\n    return [x, y, w, h];\n  }, []);\n\n  const updateLasso = useCallback(() => {\n    const lasso = lassoRef.current;\n    if (!lasso) {\n      return;\n    }\n    const lassoMode = lassoModeRef.current;\n    const [x, y, w, h] = getLassoBox();\n\n    const overlay = overlayRef.current;\n    let offsetX = 0,\n      offsetY = 0;\n    for (\n      let offsetNode = overlay;\n      offsetNode;\n      offsetNode = offsetNode.offsetParent\n    ) {\n      offsetX += offsetNode.offsetLeft;\n      offsetY += offsetNode.offsetTop;\n    }\n    const relativeX = x - offsetX;\n    const relativeY = y - offsetY;\n\n    lasso.style.left = `${relativeX}px`;\n    lasso.style.top = `${relativeY}px`;\n    lasso.style.width = `${w}px`;\n    lasso.style.height = `${h}px`;\n    lasso.style.display = lassoMode === LassoMode.ON ? 'block' : 'none';\n  }, [getLassoBox]);\n\n  const onMouseDown = useCallback(\n    (evt) => {\n      // Selecting the background element should be handled at the frameElement level\n      if (!nodesById[currentPageElements[0]?.id]?.contains(evt.target)) {\n        if (selectedElements.length) {\n          clearSelection();\n        }\n        if (isEditing) {\n          clearEditing();\n        }\n      }\n      startRef.current = [evt.pageX, evt.pageY];\n      endRef.current = [evt.pageX, evt.pageY];\n      lassoModeRef.current = LassoMode.MAYBE;\n      updateLasso();\n    },\n    [\n      clearEditing,\n      clearSelection,\n      currentPageElements,\n      isEditing,\n      nodesById,\n      selectedElements.length,\n      updateLasso,\n    ]\n  );\n\n  const onMouseMove = useCallback(\n    (evt) => {\n      if (lassoModeRef.current === LassoMode.OFF) {\n        return;\n      }\n      const [x1, y1] = startRef.current;\n      const x2 = evt.pageX;\n      const y2 = evt.pageY;\n      endRef.current[0] = x2;\n      endRef.current[1] = y2;\n      updateLasso();\n      // Ignore clicks and unintentional selections\n      if (Math.abs(x1 - x2) + Math.abs(y1 - y2) > LASSO_ACTIVE_THRESHOLD) {\n        lassoModeRef.current = LassoMode.ON;\n      }\n    },\n    [updateLasso]\n  );\n\n  const getElementPolygon = useElementPolygon();\n  const selectIntersection = useCallback(\n    ({ x: lx, y: ly, width: lw, height: lh }) => {\n      const lassoP = new SAT.Box(new SAT.Vector(lx, ly), lw, lh).toPolygon();\n      const newSelectedElementIds = currentPageElements\n        // Skip background, hidden and locked elements\n        .filter(\n          ({ isBackground, isLocked, isHidden }) =>\n            !isBackground && !isLocked && !isHidden\n        )\n        .map(({ id, ...rest }) => {\n          const elementP = getElementPolygon({ id, ...rest });\n          return SAT.testPolygonPolygon(lassoP, elementP) ? id : null;\n        })\n        .filter((id) => id);\n      setSelectedElementsById({\n        elementIds: newSelectedElementIds,\n        withLinked: true,\n      });\n    },\n    [currentPageElements, setSelectedElementsById, getElementPolygon]\n  );\n\n  const onMouseUp = useCallback(() => {\n    if (lassoModeRef.current === LassoMode.ON) {\n      const [lx, ly, lwidth, lheight] = getLassoBox();\n      clearSelection();\n      clearEditing();\n      selectIntersection({ x: lx, y: ly, width: lwidth, height: lheight });\n    }\n    lassoModeRef.current = LassoMode.OFF;\n    updateLasso();\n  }, [\n    clearEditing,\n    clearSelection,\n    getLassoBox,\n    selectIntersection,\n    updateLasso,\n  ]);\n\n  useEffect(() => {\n    document.addEventListener('mouseup', onMouseUp);\n    return () => {\n      document.removeEventListener('mouseup', onMouseUp);\n    };\n  }, [onMouseUp]);\n\n  useEffect(updateLasso);\n\n  // data-fix-caret is for allowing caretRangeFromPoint to work in Safari.\n  // See https://github.com/googleforcreators/web-stories-wp/issues/7745.\n  return (\n    <Container\n      onMouseDown={onMouseDown}\n      onMouseMove={onMouseMove}\n      data-fix-caret\n    >\n      {children}\n      <InOverlay ref={overlayRef}>\n        <Lasso ref={lassoRef} />\n      </InOverlay>\n    </Container>\n  );\n}\n\nSelectionCanvas.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default SelectionCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/shoppingPageAttachment/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { useUnits } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { OUTLINK_THEME } from '../../../constants';\nimport ArrowIcon from './icons/arrowBar.svg';\n\nconst Wrapper = styled.div`\n  position: absolute;\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n  flex-direction: column;\n  bottom: 0;\n  height: 20%;\n  width: 100%;\n  color: ${({ theme }) => theme.colors.standard.white};\n  z-index: 3;\n`;\n\nconst InnerWrap = styled.div`\n  position: relative;\n  width: 100%;\n  height: 100%;\n`;\n\nconst Inner = styled.div`\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  ${({ $hasGradient }) =>\n    $hasGradient &&\n    `background: linear-gradient(0, rgba(0, 0, 0, 0.15), transparent) !important`};\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n`;\n\nconst ArrowWrap = styled.div`\n  width: ${({ $factor }) => $factor(32)}px;\n  min-height: ${({ $factor }) => $factor(32)}px;\n  border-radius: 50%;\n  background: ${({ bgColor }) => bgColor};\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\n// The CSS here is based on how it's displayed in the front-end, including static\n// font-size, line-height, etc. independent of the viewport size -- it's not responsive.\nconst ArrowBar = styled(ArrowIcon)`\n  display: block;\n  cursor: pointer;\n  filter: drop-shadow(0px 2px 6px rgba(0, 0, 0, 0.3));\n  width: ${({ $factor }) => $factor(20)}px;\n  height: ${({ $factor }) => $factor(8)}px;\n`;\n\nconst OutlinkChip = styled.div`\n  height: ${({ $factor }) => $factor(36)}px;\n  display: flex;\n  position: relative;\n  padding: ${({ $factor }) => $factor(10)}px ${({ $factor }) => $factor(6)}px;\n  margin: 0 0 ${({ $factor }) => $factor(20)}px;\n  max-width: calc(100% - 64px);\n  border-radius: 30px;\n  place-items: center;\n  background: ${({ bgColor }) => bgColor};\n`;\n\nconst TextWrapper = styled.span`\n  font-family: Roboto, sans-serif;\n  font-size: ${({ $factor }) => $factor(16)}px;\n  line-height: 18px;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  position: relative;\n  padding-inline-start: 6px;\n  padding-inline-end: 8px;\n  height: ${({ $factor }) => $factor(16)}px;\n  letter-spacing: 0.3px;\n  font-weight: 700;\n  max-width: 210px;\n  color: ${({ fgColor }) => fgColor};\n`;\n\nconst LIGHT_COLOR = '#FFFFFF';\nconst DARK_COLOR = '#000000';\n\nfunction PageAttachment({ ctaText, theme }) {\n  const arrowColor = theme === OUTLINK_THEME.DARK ? LIGHT_COLOR : DARK_COLOR;\n  const fgColor = theme === OUTLINK_THEME.DARK ? DARK_COLOR : LIGHT_COLOR;\n\n  const { dataToEditorY } = useUnits(({ actions: { dataToEditorY } }) => ({\n    dataToEditorY,\n  }));\n\n  return (\n    <Wrapper role=\"presentation\" tabIndex={-1}>\n      <InnerWrap>\n        <Inner $hasGradient={theme !== OUTLINK_THEME.DARK}>\n          <ArrowWrap bgColor={fgColor} $factor={dataToEditorY}>\n            <ArrowBar fill={arrowColor} $factor={dataToEditorY} />\n          </ArrowWrap>\n          <OutlinkChip $factor={dataToEditorY}>\n            <TextWrapper fgColor={fgColor} $factor={dataToEditorY}>\n              {ctaText || __('Shop Now', 'web-stories')}\n            </TextWrapper>\n          </OutlinkChip>\n        </Inner>\n      </InnerWrap>\n    </Wrapper>\n  );\n}\n\nPageAttachment.propTypes = {\n  ctaText: PropTypes.string,\n  theme: PropTypes.string,\n};\n\nexport default PageAttachment;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/singleSelectionMoveable/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  forwardRef,\n  useRef,\n  useEffect,\n  useState,\n  useMemo,\n  useBatchingCallback,\n  useCombinedRefs,\n} from '@googleforcreators/react';\nimport classnames from 'classnames';\nimport { useUnits } from '@googleforcreators/units';\nimport { useGlobalIsKeyPressed } from '@googleforcreators/design-system';\nimport { useTransform } from '@googleforcreators/transform';\nimport { Moveable } from '@googleforcreators/moveable';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas, useLayout } from '../../../app';\nimport objectWithout from '../../../utils/objectWithout';\nimport useSnapping from '../utils/useSnapping';\nimport useUpdateSelectionRectangle from '../utils/useUpdateSelectionRectangle';\nimport useWindowResizeHandler from '../useWindowResizeHandler';\nimport useDrag from './useDrag';\nimport useResize from './useResize';\nimport useRotate from './useRotate';\n\nconst SingleSelectionMoveable = forwardRef(function SingleSelectionMoveable(\n  { selectedElement, targetEl, pushEvent, isEditMode, ...props },\n  ref\n) {\n  const moveable = useRef(null);\n  const [isDragging, setIsDragging] = useState(false);\n\n  const nodesById = useCanvas(({ state }) => state.nodesById);\n  const getBox = useUnits(({ actions }) => actions.getBox);\n  const pushTransform = useTransform(({ actions }) => actions.pushTransform);\n  const { zoomSetting, scrollLeft, scrollTop } = useLayout(({ state }) => ({\n    zoomSetting: state.zoomSetting,\n    scrollLeft: state.scrollLeft,\n    scrollTop: state.scrollTop,\n  }));\n\n  const { isBackground, isLocked, isHidden } = selectedElement;\n  const actionsEnabled = !isBackground && !isLocked && !isHidden;\n\n  const latestEventRef = useRef();\n\n  const backgroundElementId = useStory(\n    ({ state }) => state.currentPage?.elements[0]?.id\n  );\n\n  // ⇧ key throttles rotating 30 degrees at a time / forces locking ratio when resizing.\n  const isShiftPressed = useGlobalIsKeyPressed('shift');\n\n  useWindowResizeHandler(moveable);\n\n  useEffect(() => {\n    latestEventRef.current = pushEvent;\n  }, [pushEvent]);\n\n  // If scroll ever updates, update rect now\n  useEffect(() => {\n    if (!moveable.current) {\n      return;\n    }\n    moveable.current.updateRect();\n  }, [scrollLeft, scrollTop]);\n\n  // If zoom ever updates, update selection rect\n  useUpdateSelectionRectangle(moveable, [zoomSetting]);\n\n  useEffect(() => {\n    if (!moveable.current) {\n      return;\n    }\n    // If we have persistent event then let's use that, ensuring the targets match.\n    if (\n      latestEventRef.current &&\n      targetEl.contains(latestEventRef.current.target) &&\n      actionsEnabled\n    ) {\n      moveable.current.moveable.dragStart(latestEventRef.current);\n    }\n    moveable.current.updateRect();\n  }, [targetEl, moveable, actionsEnabled]);\n\n  // Update moveable with whatever properties could be updated outside moveable\n  // itself.\n  useEffect(() => {\n    if (!moveable.current) {\n      return;\n    }\n    moveable.current.updateRect();\n  });\n\n  const box = getBox(selectedElement);\n  const frame = useMemo(\n    () => ({\n      translate: [0, 0],\n      rotate: box.rotationAngle,\n      resize: [0, 0],\n      updates: null,\n    }),\n    [box.rotationAngle]\n  );\n\n  const { border } = selectedElement;\n  const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n  const setTransformStyle = (target, newFrame = frame) => {\n    // Get the changes coming from each action type.\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    frame.translate = newFrame.translate;\n    frame.direction = newFrame.direction;\n    frame.resize = newFrame.resize;\n    frame.updates = newFrame.updates;\n    frame.rotate = newFrame.rotate;\n    target.style.transform = `translate(${frame.translate[0]}px, ${frame.translate[1]}px) rotate(${frame.rotate}deg)`;\n    if (frame.resize[0]) {\n      target.style.width = `${frame.resize[0]}px`;\n    }\n    if (frame.resize[1]) {\n      target.style.height = `${frame.resize[1]}px`;\n    }\n\n    // If the element has a border, we have to take it out of the resizing values\n    // since the border is in pixels and thus not stored within width/height.\n    // We add canSupportMultiBorder check to ignore non-rectangular shapes since the border works differently for those.\n    let frameForEl = { ...frame };\n    if (\n      (frame.resize[0] || frame.resize[1]) &&\n      canSupportMultiBorder(selectedElement)\n    ) {\n      const elWidth = frame.resize[0] - (left + right);\n      const elHeight = frame.resize[1] - (top + bottom);\n      frameForEl = {\n        ...frame,\n        resize: [elWidth, elHeight],\n      };\n    }\n    pushTransform(selectedElement.id, frameForEl);\n  };\n\n  /**\n   * Resets Moveable once the action is done, sets the initial values.\n   *\n   * @param {Object} target Target element.\n   */\n  const resetMoveable = useBatchingCallback(\n    (target) => {\n      if (!moveable.current) {\n        return;\n      }\n\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      frame.direction = [0, 0];\n      frame.translate = [0, 0];\n      frame.resize = [0, 0];\n      frame.updates = null;\n      pushTransform(selectedElement.id, null);\n      // Inline start resetting has to be done very carefully here to avoid\n      // conflicts with stylesheets. See #3951.\n      target.style.transform = '';\n      target.style.width = '';\n      target.style.height = '';\n      moveable.current.updateRect();\n    },\n    [frame, pushTransform, selectedElement.id]\n  );\n\n  const canSnap = !isEditMode;\n  const hideHandles = isDragging;\n\n  const classNames = classnames('default-moveable', {\n    'hide-handles': hideHandles,\n    'type-text': selectedElement.type === 'text',\n    immoveable: isLocked || isHidden,\n  });\n  const _dragProps = useDrag({\n    setIsDragging,\n    resetMoveable,\n    selectedElement,\n    setTransformStyle,\n    frame,\n  });\n  // No dragging in edit mode.\n  const dragProps = isEditMode\n    ? {\n        onDrag: () => false,\n        onDragEnd: () => false,\n        onDragStart: () => false,\n      }\n    : _dragProps;\n\n  const resizeProps = useResize({\n    resetMoveable,\n    selectedElement,\n    setTransformStyle,\n    frame,\n    isEditMode,\n    pushTransform,\n    classNames,\n    forceLockRatio: isShiftPressed,\n  });\n\n  const rotateProps = useRotate({\n    selectedElement,\n    isEditMode,\n    pushTransform,\n    frame,\n    setTransformStyle,\n    resetMoveable,\n    throttleRotation: isShiftPressed,\n  });\n\n  // Get a list of all the other non-bg nodes\n  const otherNodes = Object.values(\n    objectWithout(nodesById, [selectedElement.id, backgroundElementId])\n  );\n\n  const snapProps = useSnapping({\n    otherNodes,\n    canSnap: canSnap && actionsEnabled,\n    isDragging,\n  });\n\n  const isResizable =\n    actionsEnabled && !hideHandles && true !== selectedElement.lockDimensions;\n  const isRotatable =\n    actionsEnabled &&\n    !hideHandles &&\n    false !== selectedElement.supportsRotation;\n\n  return (\n    <Moveable\n      {...props}\n      className={classNames}\n      zIndex={0}\n      ref={useCombinedRefs(moveable, ref)}\n      target={targetEl}\n      edge\n      draggable={actionsEnabled}\n      resizable={isResizable}\n      rotatable={isRotatable}\n      {...dragProps}\n      {...resizeProps}\n      {...rotateProps}\n      {...snapProps}\n      origin={false}\n      pinchable\n    />\n  );\n});\n\nSingleSelectionMoveable.propTypes = {\n  selectedElement: PropTypes.object.isRequired,\n  targetEl: PropTypes.object.isRequired,\n  pushEvent: PropTypes.object,\n  isEditMode: PropTypes.bool,\n  editMoveableRef: PropTypes.object,\n};\n\nexport default SingleSelectionMoveable;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/singleSelectionMoveable/useDrag.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useUnits } from '@googleforcreators/units';\nimport { useBatchingCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useDropTargets } from '../../dropTargets';\nimport { useStory } from '../../../app';\nimport useElementOutOfCanvas from '../utils/useElementOutOfCanvas';\nimport useFullbleedMediaAsBackground from '../utils/useFullbleedMediaAsBackground';\n\nfunction useSingleSelectionDrag({\n  setIsDragging,\n  resetMoveable,\n  selectedElement,\n  setTransformStyle,\n  frame,\n}) {\n  const { isDropSource, handleDrag, handleDrop, setDraggingResource } =\n    useDropTargets(\n      ({\n        actions: { handleDrag, handleDrop, isDropSource, setDraggingResource },\n      }) => ({\n        handleDrag,\n        handleDrop,\n        setDraggingResource,\n        isDropSource,\n      })\n    );\n\n  const { handleElementOutOfCanvas } = useElementOutOfCanvas();\n  const { handleFullbleedMediaAsBackground } = useFullbleedMediaAsBackground();\n\n  const { updateSelectedElements } = useStory((state) => ({\n    updateSelectedElements: state.actions.updateSelectedElements,\n  }));\n\n  const { editorToDataX, editorToDataY } = useUnits(\n    ({ actions: { editorToDataX, editorToDataY } }) => ({\n      editorToDataX,\n      editorToDataY,\n    })\n  );\n\n  const resetDragging = useBatchingCallback(\n    (target) => {\n      setIsDragging(false);\n      setDraggingResource(null);\n      resetMoveable(target);\n    },\n    [setIsDragging, setDraggingResource, resetMoveable]\n  );\n\n  const onDrag = ({ target, beforeTranslate, clientX, clientY }) => {\n    setIsDragging(true);\n    if (isDropSource(selectedElement.type)) {\n      setDraggingResource(selectedElement.resource);\n    }\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    frame.translate = beforeTranslate;\n    setTransformStyle(target, frame);\n    if (isDropSource(selectedElement.type)) {\n      handleDrag(\n        selectedElement.resource,\n        clientX,\n        clientY,\n        selectedElement.id\n      );\n    }\n    return undefined;\n  };\n\n  const onDragStart = ({ set }) => {\n    // Note: we can't set isDragging true here since a \"click\" is also considered dragStart.\n    set(frame.translate);\n    return undefined;\n  };\n\n  const onDragEnd = ({ target, isDrag }) => {\n    if (!isDrag) {\n      return false;\n    }\n    if (handleElementOutOfCanvas(target)) {\n      setIsDragging(false);\n      setDraggingResource(null);\n      return undefined;\n    }\n\n    const roundToZero = (num) => (Math.abs(num) <= 1 ? 0 : num);\n\n    // When dragging finishes, set the new properties based on the original + what moved meanwhile.\n    const [deltaX, deltaY] = frame.translate;\n    let properties = {};\n    if (deltaX !== 0 || deltaY !== 0) {\n      properties = {\n        x: roundToZero(selectedElement.x + editorToDataX(deltaX)),\n        y: roundToZero(selectedElement.y + editorToDataY(deltaY)),\n      };\n      updateSelectedElements({ properties });\n      if (isDropSource(selectedElement.type)) {\n        handleDrop(selectedElement.resource, selectedElement.id);\n      }\n    }\n    resetDragging(target);\n    handleFullbleedMediaAsBackground({ ...selectedElement, ...properties });\n    return undefined;\n  };\n\n  return {\n    onDrag,\n    throttleDrag: 0,\n    onDragStart,\n    onDragEnd,\n  };\n}\n\nexport default useSingleSelectionDrag;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/singleSelectionMoveable/useResize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport classnames from 'classnames';\nimport { useUnits } from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport { useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport useElementOutOfCanvas from '../utils/useElementOutOfCanvas';\nimport useFullbleedMediaAsBackground from '../utils/useFullbleedMediaAsBackground';\n\nconst EMPTY_HANDLES = [];\nconst VERTICAL_HANDLES = ['n', 's'];\nconst HORIZONTAL_HANDLES = ['e', 'w'];\nconst DIAGONAL_HANDLES = ['nw', 'ne', 'sw', 'se'];\n\nfunction getRenderDirections({ vertical, horizontal, diagonal }) {\n  return [\n    ...(vertical ? VERTICAL_HANDLES : EMPTY_HANDLES),\n    ...(horizontal ? HORIZONTAL_HANDLES : EMPTY_HANDLES),\n    ...(diagonal ? DIAGONAL_HANDLES : EMPTY_HANDLES),\n  ];\n}\n\nfunction useSingleSelectionResize({\n  resetMoveable,\n  selectedElement,\n  setTransformStyle,\n  frame,\n  isEditMode,\n  pushTransform,\n  classNames,\n  forceLockRatio,\n}) {\n  const { updateSelectedElements } = useStory((state) => ({\n    updateSelectedElements: state.actions.updateSelectedElements,\n  }));\n\n  const { handleElementOutOfCanvas } = useElementOutOfCanvas();\n  const { handleFullbleedMediaAsBackground } = useFullbleedMediaAsBackground();\n\n  const { editorToDataX, editorToDataY, dataToEditorY, dataToEditorX } =\n    useUnits(\n      ({\n        actions: { editorToDataX, editorToDataY, dataToEditorY, dataToEditorX },\n      }) => ({\n        editorToDataX,\n        editorToDataY,\n        dataToEditorY,\n        dataToEditorX,\n      })\n    );\n\n  const { lockAspectRatio: elementLockRatio, type, border } = selectedElement;\n  const isText = type === 'text';\n  const [isResizingFromCorner, setIsResizingFromCorner] = useState(true);\n  // Text element lock aspect ratio doesn't influence resizing.\n  // See https://github.com/GoogleForCreators/web-stories-wp/issues/10466\n  // We always lock the aspect ratio for text element when resizing from corners and never when resizing from edges.\n  const lockAspectRatio =\n    (!isText && (forceLockRatio || elementLockRatio)) ||\n    (isText && isResizingFromCorner);\n  const { resizeRules, updateForResizeEvent } = getDefinitionForType(type);\n\n  const minWidth = dataToEditorX(resizeRules.minWidth);\n  const minHeight = dataToEditorY(resizeRules.minHeight);\n  const aspectRatio = selectedElement.width / selectedElement.height;\n\n  const { left = 0, right = 0, top = 0, bottom = 0 } = border || {};\n  const onResize = ({ target, direction, width, height, drag }) => {\n    // We remove the border in pixels since that's not saved to the width/height directly.\n    let newWidth = width - (left + right);\n    let newHeight = height - (top + bottom);\n    let updates = null;\n\n    if (lockAspectRatio) {\n      if (newWidth < minWidth) {\n        newWidth = minWidth;\n        newHeight = newWidth / aspectRatio;\n      }\n      if (newHeight < minHeight) {\n        newHeight = minHeight;\n        newWidth = minHeight * aspectRatio;\n      }\n    } else {\n      newHeight = Math.max(newHeight, minHeight);\n      newWidth = Math.max(newWidth, minWidth);\n    }\n\n    if (updateForResizeEvent) {\n      updates = updateForResizeEvent(\n        selectedElement,\n        direction,\n        editorToDataX(newWidth, false),\n        editorToDataY(newHeight, false)\n      );\n    }\n    if (updates && updates.height) {\n      newHeight = dataToEditorY(updates.height);\n    }\n    if (updates && updates.marginOffset) {\n      target.querySelector('.syncMargin').style.margin = `${\n        -dataToEditorY(updates.marginOffset) / 2\n      }px 0`;\n    }\n\n    // We add the border size back for the target display.\n    const frameWidth = newWidth + left + right;\n    const frameHeight = newHeight + top + bottom;\n    target.style.width = `${frameWidth}px`;\n    target.style.height = `${frameHeight}px`;\n    /* eslint-disable react-hooks/immutability -- FIXME */\n    frame.direction = direction;\n    frame.resize = [frameWidth, frameHeight];\n    frame.translate = drag.beforeTranslate;\n    frame.updates = updates;\n    /* eslint-enable react-hooks/immutability -- FIXME */\n    setTransformStyle(target, frame);\n  };\n\n  const onResizeStart = ({ setOrigin, dragStart, direction }) => {\n    setOrigin(['%', '%']);\n    if (dragStart) {\n      dragStart.set(frame.translate);\n    }\n    // Both `direction[]` values for diagonals are either 1 or -1. Non-diagonal\n    // directions have 0s.\n    const newResizingMode = direction[0] !== 0 && direction[1] !== 0;\n    if (isResizingFromCorner !== newResizingMode && isText) {\n      setIsResizingFromCorner(newResizingMode);\n    }\n    if (isEditMode) {\n      // In edit mode, we need to signal right away that the action started.\n      pushTransform(selectedElement.id, frame);\n    }\n  };\n\n  const onResizeEnd = ({ target }) => {\n    if (handleElementOutOfCanvas(target)) {\n      return;\n    }\n    const [editorWidth, editorHeight] = frame.resize;\n    let properties = {};\n    if (editorWidth !== 0 && editorHeight !== 0) {\n      const { direction } = frame;\n      const [deltaX, deltaY] = frame.translate;\n      // Border is not saved into element's width/height (since it's in pixels) so remove it before updating.\n      const newWidth = editorToDataX(editorWidth - (left + right));\n      const newHeight = editorToDataY(editorHeight - (top + bottom));\n      properties = {\n        width: newWidth,\n        height: newHeight,\n        x: selectedElement.x + editorToDataX(deltaX),\n        y: selectedElement.y + editorToDataY(deltaY),\n      };\n      if (updateForResizeEvent) {\n        Object.assign(\n          properties,\n          updateForResizeEvent(selectedElement, direction, newWidth, newHeight)\n        );\n      }\n      updateSelectedElements({ properties });\n    }\n    setIsResizingFromCorner(true);\n    resetMoveable(target);\n    handleFullbleedMediaAsBackground({ ...selectedElement, ...properties });\n  };\n\n  const visuallyHideHandles =\n    selectedElement.width <= resizeRules.minWidth ||\n    selectedElement.height <= resizeRules.minHeight;\n\n  return {\n    onResize,\n    onResizeStart,\n    onResizeEnd,\n    keepRatio: lockAspectRatio,\n    renderDirections: getRenderDirections(resizeRules),\n    className: classnames(classNames, {\n      'visually-hide-handles': visuallyHideHandles,\n    }),\n  };\n}\n\nexport default useSingleSelectionResize;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/singleSelectionMoveable/useRotate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport useElementOutOfCanvas from '../utils/useElementOutOfCanvas';\nimport normalizeRotationDegrees from '../utils/normalizeRotationDegrees';\n\nfunction useSingleSelectionRotate({\n  selectedElement,\n  isEditMode,\n  pushTransform,\n  frame,\n  setTransformStyle,\n  resetMoveable,\n  throttleRotation,\n}) {\n  const { updateSelectedElements } = useStory((state) => ({\n    updateSelectedElements: state.actions.updateSelectedElements,\n  }));\n\n  const { handleElementOutOfCanvas } = useElementOutOfCanvas();\n\n  const onRotateStart = ({ set }) => {\n    if (isEditMode) {\n      // In edit mode, we need to signal right away that the action started.\n      pushTransform(selectedElement.id, frame);\n    }\n    set(frame.rotate);\n  };\n  const onRotate = ({ target, beforeRotate }) => {\n    // eslint-disable-next-line react-hooks/immutability -- FIXME\n    frame.rotate = normalizeRotationDegrees(beforeRotate);\n    setTransformStyle(target, frame);\n  };\n  const onRotateEnd = ({ target }) => {\n    if (handleElementOutOfCanvas(target)) {\n      return;\n    }\n    const properties = { rotationAngle: Math.round(frame.rotate) };\n    updateSelectedElements({ properties });\n    resetMoveable(target);\n  };\n\n  return {\n    throttleRotate: throttleRotation ? 30 : 0,\n    onRotate,\n    onRotateEnd,\n    onRotateStart,\n  };\n}\n\nexport default useSingleSelectionRotate;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/__snapshots__/mediaDisplay.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`MediaDisplay should apply and reset transformations: empty style after 1`] = `{}`;\n\nexports[`MediaDisplay should apply and reset transformations: empty style before 1`] = `{}`;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ThemeProvider } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { PAGE_WIDTH, PAGE_RATIO } from '@googleforcreators/units';\nimport { TransformProvider, useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport FrameElement from '../frameElement';\nimport DisplayElement from '../displayElement';\nimport { CanvasProvider } from '../../../app/canvas';\nimport LayoutContext from '../../../app/layout/context';\nimport ConfigProvider from '../../../app/config/configProvider';\nimport StoryContext from '../../../app/story/context';\nimport theme from '../../../theme';\nimport useEditingElement from '../../../app/canvas/useEditingElement';\nimport { DropTargetsProvider } from '../../dropTargets';\nimport { MediaProvider } from '../../../app/media';\nimport EditLayerFocusManager from '../editLayerFocusManager';\n\njest.mock('../../../app/canvas/useEditingElement');\n\nconst LAYOUT_CONTEXT = {\n  state: {\n    pageWidth: PAGE_WIDTH,\n    pageHeight: PAGE_WIDTH / PAGE_RATIO,\n  },\n  actions: {},\n};\n\nexport function TestFrameElement({\n  element,\n  refs,\n  configContext: inputConfigContext,\n  storyContext: inputStoryContext,\n  editingElementContext: inputEditingElementContext,\n}) {\n  const configContext = {\n    ...inputConfigContext,\n    allowedMimeTypes: {\n      audio: [],\n      image: [],\n      caption: [],\n      vector: [],\n      video: [],\n      ...(inputConfigContext && inputConfigContext.allowedMimeTypes),\n    },\n    locale: {\n      locale: 'en-US',\n    },\n  };\n  const storyContext = {\n    ...inputStoryContext,\n    state: {\n      selectedElements: [],\n      selectedElementIds: [],\n      ...(inputStoryContext && inputStoryContext.state),\n      currentPage: {\n        ...inputStoryContext.state?.currentPage,\n        elements: [\n          element,\n          ...(inputStoryContext.state?.currentPage?.elements || []),\n        ],\n      },\n    },\n    actions: {\n      toggleElementInSelection: () => {},\n      setSelectedElementsById: () => {},\n      ...(inputStoryContext && inputStoryContext.actions),\n    },\n  };\n  const editingElementContext = {\n    nodesById: {},\n    setNodeForElement: () => {},\n    setEditingElementWithState: () => {},\n    ...inputEditingElementContext,\n  };\n  useEditingElement.mockImplementation(() => editingElementContext);\n  return (\n    <ThemeProvider theme={theme}>\n      <ConfigProvider config={configContext}>\n        <StoryContext.Provider value={storyContext}>\n          <LayoutContext.Provider value={LAYOUT_CONTEXT}>\n            <CanvasProvider>\n              <TransformProvider>\n                <DropTargetsProvider>\n                  <WithRefs refs={refs}>\n                    <EditLayerFocusManager>\n                      <FrameElement id={element.id} />\n                    </EditLayerFocusManager>\n                  </WithRefs>\n                </DropTargetsProvider>\n              </TransformProvider>\n            </CanvasProvider>\n          </LayoutContext.Provider>\n        </StoryContext.Provider>\n      </ConfigProvider>\n    </ThemeProvider>\n  );\n}\n\nTestFrameElement.propTypes = {\n  element: PropTypes.object.isRequired,\n  refs: PropTypes.object,\n  configContext: PropTypes.object,\n  storyContext: PropTypes.object,\n  editingElementContext: PropTypes.object,\n};\n\nexport function TestDisplayElement({\n  element,\n  refs,\n  configContext: inputConfigContext,\n  storyContext: inputStoryContext,\n}) {\n  const configContext = {\n    ...inputConfigContext,\n    allowedMimeTypes: {\n      audio: [],\n      image: [],\n      caption: [],\n      vector: [],\n      video: [],\n      ...(inputConfigContext && inputConfigContext.allowedMimeTypes),\n    },\n    capabilities: { hasUploadMediaAction: true },\n  };\n  const storyContext = {\n    ...inputStoryContext,\n    state: {\n      selectedElements: [],\n      selectedElementIds: [],\n      ...(inputStoryContext && inputStoryContext.state),\n    },\n    actions: {\n      toggleElementInSelection: () => {},\n      setSelectedElementsById: () => {},\n      ...(inputStoryContext && inputStoryContext.actions),\n    },\n  };\n  const editingElementContext = {\n    nodesById: {},\n    setNodeForElement: () => {},\n    setEditingElementWithState: () => {},\n  };\n  useEditingElement.mockImplementation(() => editingElementContext);\n  return (\n    <ThemeProvider theme={theme}>\n      <ConfigProvider config={configContext}>\n        <StoryContext.Provider value={storyContext}>\n          <LayoutContext.Provider value={LAYOUT_CONTEXT}>\n            <CanvasProvider>\n              <MediaProvider>\n                <TransformProvider>\n                  <WithRefs refs={refs}>\n                    <DisplayElement element={element} page={null} />\n                  </WithRefs>\n                </TransformProvider>\n              </MediaProvider>\n            </CanvasProvider>\n          </LayoutContext.Provider>\n        </StoryContext.Provider>\n      </ConfigProvider>\n    </ThemeProvider>\n  );\n}\n\nTestDisplayElement.propTypes = {\n  element: PropTypes.object.isRequired,\n  refs: PropTypes.object,\n  configContext: PropTypes.object,\n  storyContext: PropTypes.object,\n};\n\nfunction WithRefs({ refs, children }) {\n  const transformContext = useTransform();\n  if (refs) {\n    Object.assign(refs, {\n      transformContext,\n    });\n  }\n  return children;\n}\n\nWithRefs.propTypes = {\n  refs: PropTypes.object,\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/frame.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, fireEvent, act, screen } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { TestFrameElement } from './_utils';\n\njest.useFakeTimers();\n\ndescribe('TextFrame: enter edit mode', () => {\n  let element;\n  let storyContext;\n  let setEditingElementWithState;\n  let editingElementContext;\n\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  beforeEach(() => {\n    element = {\n      id: '1',\n      type: 'text',\n      x: 0,\n      y: 0,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 20,\n      content: 'hello world',\n      color: createSolid(255, 255, 255),\n    };\n\n    storyContext = {};\n    setEditingElementWithState = jest.fn();\n    editingElementContext = { setEditingElementWithState };\n  });\n\n  function setSelected() {\n    storyContext = {\n      ...storyContext,\n      state: {\n        selectedElements: [element],\n        selectedElementIds: [element.id],\n      },\n    };\n  }\n\n  it('should go to edit mode on a single click when selected', () => {\n    setSelected();\n    render(\n      <TestFrameElement\n        storyContext={storyContext}\n        editingElementContext={editingElementContext}\n        element={element}\n      />\n    );\n\n    const frame = screen.queryByText(element.content);\n\n    act(() => jest.runOnlyPendingTimers());\n\n    fireEvent.mouseDown(frame);\n    fireEvent.mouseUp(frame);\n\n    expect(\n      editingElementContext.setEditingElementWithState\n    ).toHaveBeenCalledWith('1', { offset: 0 });\n  });\n\n  it('should go to edit mode on enter key', () => {\n    setSelected();\n    render(\n      <TestFrameElement\n        storyContext={storyContext}\n        editingElementContext={editingElementContext}\n        element={element}\n      />\n    );\n\n    // Find the focusable target.\n    const target = screen.getByTestId('frameElement');\n\n    act(() => jest.runOnlyPendingTimers());\n\n    // Fire \"Enter\" keydown.\n    fireEvent.keyDown(target, { key: 'Enter' });\n\n    expect(\n      editingElementContext.setEditingElementWithState\n    ).toHaveBeenCalledWith('1', { selectAll: true });\n  });\n\n  it('should go to edit mode on a character key', () => {\n    setSelected();\n    render(\n      <TestFrameElement\n        storyContext={storyContext}\n        editingElementContext={editingElementContext}\n        element={element}\n      />\n    );\n\n    // Find the focusable target.\n    const target = screen.getByTestId('frameElement');\n\n    act(() => jest.runOnlyPendingTimers());\n\n    // Fire \"d\" keydown.\n    fireEvent.keyDown(target, { key: 'd' });\n\n    expect(\n      editingElementContext.setEditingElementWithState\n    ).toHaveBeenCalledWith('1', { selectAll: true });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/frameElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, fireEvent } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { TestFrameElement } from './_utils';\n\n/* eslint-disable testing-library/no-node-access, testing-library/no-container */\n\ndescribe('FrameElement selection', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  let setSelectedElementsById;\n  let toggleElementInSelection;\n  let storyContext;\n\n  beforeEach(() => {\n    setSelectedElementsById = jest.fn();\n    toggleElementInSelection = jest.fn();\n    storyContext = {\n      actions: {\n        setSelectedElementsById,\n        toggleElementInSelection,\n      },\n    };\n  });\n\n  it('should select unselected element on mousedown', () => {\n    const element = {\n      id: '1',\n      type: 'text',\n      x: 0,\n      y: 0,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 20,\n      content: 'hello world',\n      color: createSolid(255, 255, 255),\n    };\n    const { container } = render(\n      <TestFrameElement storyContext={storyContext} element={element} />\n    );\n\n    // Fire a mousedown event.\n    const wrapper = container.querySelector('[data-element-id=\"1\"]');\n    fireEvent.mouseDown(wrapper);\n    expect(setSelectedElementsById).toHaveBeenCalledWith({\n      elementIds: ['1'],\n      withLinked: true,\n    });\n  });\n\n  it('should select unselected element on focus', () => {\n    const element = {\n      id: '1',\n      type: 'text',\n      x: 0,\n      y: 0,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 20,\n      content: 'hello world',\n      color: createSolid(255, 255, 255),\n    };\n    const { container } = render(\n      <TestFrameElement storyContext={storyContext} element={element} />\n    );\n\n    // Fire a mousedown event.\n    const wrapper = container.querySelector('[data-element-id=\"1\"]');\n    fireEvent.focus(wrapper);\n    expect(setSelectedElementsById).toHaveBeenCalledWith({\n      elementIds: ['1'],\n      withLinked: true,\n    });\n  });\n\n  it('should not select on mousedown if already selected', () => {\n    const element = {\n      id: '1',\n      type: 'text',\n      x: 0,\n      y: 0,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 20,\n      content: 'hello world',\n      color: createSolid(255, 255, 255),\n    };\n    storyContext = {\n      ...storyContext,\n      state: {\n        selectedElementIds: [element.id],\n      },\n    };\n    const { container } = render(\n      <TestFrameElement storyContext={storyContext} element={element} />\n    );\n\n    // Fire a mousedown event.\n    const wrapper = container.querySelector('[data-element-id=\"1\"]');\n    fireEvent.mouseDown(wrapper);\n    expect(setSelectedElementsById).not.toHaveBeenCalled();\n  });\n\n  it('should toggle selection on mousedown with shift', () => {\n    const element = {\n      id: '1',\n      type: 'text',\n      x: 0,\n      y: 0,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      font: {\n        family: 'Roboto',\n      },\n      fontSize: 20,\n      content: 'hello world',\n      color: createSolid(255, 255, 255),\n    };\n    const { container } = render(\n      <TestFrameElement storyContext={storyContext} element={element} />\n    );\n\n    // Fire a mousedown event with shift.\n    const wrapper = container.querySelector('[data-element-id=\"1\"]');\n    fireEvent.mouseDown(wrapper, { shiftKey: true });\n    expect(toggleElementInSelection).toHaveBeenCalledWith({\n      elementId: '1',\n      withLinked: true,\n    });\n  });\n});\n\n/* eslint-enable testing-library/no-node-access, testing-library/no-container */\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/mediaDisplay.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, act } from '@testing-library/react';\nimport { resourceList } from '@googleforcreators/media';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { TestDisplayElement } from './_utils';\n\n/* eslint-disable testing-library/no-node-access, testing-library/no-container */\n\ndescribe('MediaDisplay', () => {\n  let imageElement;\n  let videoElement;\n  let storyContext;\n  let refs;\n\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  beforeEach(() => {\n    imageElement = {\n      id: 'foo',\n      type: 'image',\n      mimeType: 'image/png',\n      x: 0,\n      y: 0,\n      width: 80,\n      height: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      scale: 100,\n      focalX: 50,\n      focalY: 50,\n      isBackground: false,\n      resource: {\n        id: 123,\n        type: 'image',\n        mimeType: 'image/png',\n        src: 'https://example.com/image1.png',\n        width: 1000,\n        height: 800,\n        alt: '',\n        sizes: {\n          medium: {\n            sourceUrl: 'https://example.com/image1-mid.png',\n            width: 500,\n            height: 400,\n            mimeType: 'image/png',\n          },\n          full: {\n            sourceUrl: 'https://example.com/image1.png',\n            width: 1000,\n            height: 800,\n            mimeType: 'image/png',\n          },\n        },\n      },\n    };\n    videoElement = {\n      id: 'baz',\n      type: 'video',\n      mimeType: 'video/mp4',\n      scale: 1,\n      origRatio: 9 / 16,\n      x: 0,\n      y: 0,\n      height: 1920,\n      width: 1080,\n      rotationAngle: 0,\n      cale: 100,\n      focalX: 50,\n      focalY: 50,\n      isBackground: false,\n      loop: true,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      resource: {\n        type: 'video',\n        mimeType: 'video/mp4',\n        id: 123,\n        src: 'https://example.com/video.mp4',\n        poster: 'https://example.com/poster.png',\n        height: 1920,\n        width: 1080,\n        length: 99,\n        alt: '',\n      },\n    };\n\n    storyContext = {};\n    refs = {};\n  });\n\n  it('should render img with srcset, when fullsize resource is loaded', () => {\n    resourceList.set(imageElement.resource.id, { type: 'fullsize' });\n    const { container } = render(\n      <TestDisplayElement storyContext={storyContext} element={imageElement} />\n    );\n\n    const img = container.querySelector('img');\n\n    expect(img.srcset).toBe(\n      'https://example.com/image1.png 1000w,https://example.com/image1-mid.png 500w'\n    );\n    // Take optimized image loading into account, fullsize uses original image\n    expect(img.src).toBe(imageElement.resource.src);\n  });\n\n  it('should render img with scale and focal point', () => {\n    const { container } = render(\n      <TestDisplayElement storyContext={storyContext} element={imageElement} />\n    );\n\n    const img = container.querySelector('img');\n    // The offset is setup to fit 1000:800 image inside 80:100 box.\n    expect(window.getComputedStyle(img)).toMatchObject({\n      width: '125px',\n      height: '100px',\n      left: '-22.5px',\n      top: '0px',\n    });\n  });\n\n  it('should apply and reset transformations', () => {\n    const { container } = render(\n      <TestDisplayElement\n        refs={refs}\n        storyContext={storyContext}\n        element={imageElement}\n      />\n    );\n\n    const {\n      actions: { pushTransform },\n    } = refs.transformContext;\n\n    const img = container.querySelector('img');\n\n    // Start with empty style.\n    expect(img.style).toMatchSnapshot('empty style before');\n\n    // Resize to 100:80 (or 1:1 with the original size).\n    act(() => {\n      pushTransform(imageElement.id, { resize: [100, 80] });\n    });\n    expect(img).toHaveStyle({\n      width: '100px',\n      height: '80px',\n      left: '0px',\n      top: '0px',\n    });\n\n    // Reset.\n    act(() => {\n      pushTransform(imageElement.id, null);\n    });\n    expect(img.style).toMatchSnapshot('empty style after');\n  });\n\n  it('should render flipped background video', () => {\n    const flipCases = [\n      {\n        flip: { vertical: true, horizontal: false },\n        transform: 'scale3d(1, -1, 1)',\n      },\n      {\n        flip: { vertical: false, horizontal: true },\n        transform: 'scale3d(-1, 1, 1)',\n      },\n      {\n        flip: { vertical: true, horizontal: true },\n        transform: 'scale3d(-1, -1, 1)',\n      },\n    ];\n\n    flipCases.forEach(({ flip, transform }) => {\n      const flippedBackgroundVideo = {\n        ...videoElement,\n        isBackground: true,\n        flip,\n      };\n      const { container } = render(\n        <TestDisplayElement\n          storyContext={{\n            ...storyContext,\n            page: {},\n          }}\n          element={flippedBackgroundVideo}\n        />\n      );\n\n      const element = container.querySelector(\n        '[data-element-id=\"baz\"]'\n      ).firstChild;\n      expect(window.getComputedStyle(element)).toMatchObject({\n        transform,\n      });\n    });\n  });\n});\n\n/* eslint-enable testing-library/no-node-access, testing-library/no-container */\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/multiSelectionMoveable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, act, waitFor } from '@testing-library/react';\nimport { withOverlay } from '@googleforcreators/moveable';\nimport { MockMoveable } from 'react-moveable'; // eslint-disable-line import/named -- This is a custom Jest mock\nimport PropTypes from 'prop-types';\nimport { forwardRef } from '@googleforcreators/react';\nimport { UnitsProvider } from '@googleforcreators/units';\nimport { TransformProvider } from '@googleforcreators/transform';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport CanvasContext from '../../../app/canvas/context';\nimport Selection from '../selection';\nimport StoryContext from '../../../app/story/context';\n\nconst pageSize = { width: 100, height: 100 };\n\nconst element1 = { id: '1', type: 'text', x: 0, y: 0 };\nconst element2 = { id: '2', type: 'text', x: 10, y: 10 };\n\nconst WrapperWithRef = ({ children }, ref) => (\n  <div ref={ref}>\n    <TransformProvider>\n      <UnitsProvider pageSize={pageSize}>{children}</UnitsProvider>\n    </TransformProvider>\n  </div>\n);\nconst Wrapper = withOverlay(forwardRef(WrapperWithRef));\n\nWrapperWithRef.propTypes = {\n  children: PropTypes.node,\n};\n\ndescribe('multiSelectionMoveable', () => {\n  let updateElementsById;\n  let updateSelectedElements;\n  let target1;\n  let target2;\n  let storyContext;\n  let canvasContext;\n\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  beforeEach(() => {\n    updateElementsById = jest.fn();\n    updateSelectedElements = jest.fn();\n    target1 = document.createElement('div');\n    target2 = document.createElement('div');\n\n    storyContext = {\n      state: {\n        selectedElements: [element1, element2],\n        currentPage: {\n          elements: [],\n        },\n      },\n      actions: { updateElementsById, updateSelectedElements },\n    };\n    canvasContext = {\n      state: {\n        pageSize,\n        nodesById: {\n          1: target1,\n          2: target2,\n        },\n        fullbleedContainer: document.body,\n      },\n      actions: { handleSelectElement: jest.fn() },\n    };\n  });\n\n  function arrange() {\n    return render(\n      <StoryContext.Provider value={storyContext}>\n        <CanvasContext.Provider value={canvasContext}>\n          <Selection />\n        </CanvasContext.Provider>\n      </StoryContext.Provider>,\n      { wrapper: Wrapper }\n    );\n  }\n\n  function performRotation(rotateTo) {\n    const moveable =\n      MockMoveable.mock.calls[MockMoveable.mock.calls.length - 1][0];\n    moveable?.onRotateGroupStart({ events: [{ set: () => {} }] });\n    moveable?.onRotateGroup({\n      events: [\n        {\n          target: target1,\n          beforeRotate: rotateTo,\n          drag: { beforeTranslate: [0, 0] },\n        },\n        {\n          target: target2,\n          beforeRotate: rotateTo,\n          drag: { beforeTranslate: [0, 0] },\n        },\n      ],\n    });\n    moveable?.onRotateGroupEnd({ targets: [target1, target2] });\n  }\n\n  const rotateCases = [\n    ['normally', { rotateTo: 45, expectedRotationAngle: 45 }],\n    ['through 360 degrees', { rotateTo: 370, expectedRotationAngle: 10 }],\n    ['through negative', { rotateTo: -370, expectedRotationAngle: 350 }],\n  ];\n\n  it.each(rotateCases)(\n    'should rotate %p',\n    async (_, { rotateTo, expectedRotationAngle }) => {\n      arrange();\n      // Wait until the component has loaded.\n      await waitFor(\n        () => MockMoveable.mock.calls[MockMoveable.mock.calls.length - 1][0]\n      );\n      act(() => {\n        performRotation(rotateTo);\n      });\n\n      const func = updateElementsById.mock.calls[0][0].properties;\n      expect(func(element1)).toStrictEqual({\n        x: 0,\n        y: 0,\n        rotationAngle: expectedRotationAngle,\n      });\n      expect(func(element2)).toStrictEqual({\n        x: 10,\n        y: 10,\n        rotationAngle: expectedRotationAngle,\n      });\n      expect(updateElementsById).toHaveBeenCalledOnce();\n    }\n  );\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/singleSelectionMoveable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, act, waitFor } from '@testing-library/react';\nimport { withOverlay } from '@googleforcreators/moveable';\nimport { MockMoveable } from 'react-moveable'; // eslint-disable-line import/named -- This is a custom Jest mock\nimport PropTypes from 'prop-types';\nimport { forwardRef } from '@googleforcreators/react';\nimport { UnitsProvider } from '@googleforcreators/units';\nimport { TransformProvider } from '@googleforcreators/transform';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport CanvasContext from '../../../app/canvas/context';\nimport Selection from '../selection';\nimport StoryContext from '../../../app/story/context';\n\nconst pageSize = { width: 100, height: 100 };\n\nconst element = {\n  id: '1',\n  type: 'text',\n};\n\nconst WrapperWithRef = ({ children }, ref) => (\n  <div ref={ref}>\n    <TransformProvider>\n      <UnitsProvider pageSize={pageSize}>{children}</UnitsProvider>\n    </TransformProvider>\n  </div>\n);\nconst Wrapper = withOverlay(forwardRef(WrapperWithRef));\n\nWrapperWithRef.propTypes = {\n  children: PropTypes.node,\n};\n\ndescribe('singleSelectionMoveable', () => {\n  let updateSelectedElements;\n  let target;\n  let storyContext;\n  let canvasContext;\n\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  beforeEach(() => {\n    updateSelectedElements = jest.fn();\n    target = document.createElement('div');\n\n    storyContext = {\n      state: {\n        selectedElements: [element],\n        currentPage: {\n          elements: [{ isBackground: true, id: 2 }],\n        },\n      },\n      actions: { updateSelectedElements },\n    };\n    canvasContext = {\n      state: {\n        pageSize,\n        nodesById: { 1: target, 2: document.body },\n        fullbleedContainer: document.body,\n      },\n      actions: {\n        setDisplayLinkGuidelines: jest.fn(),\n      },\n    };\n  });\n\n  function arrange() {\n    return render(\n      <StoryContext.Provider value={storyContext}>\n        <CanvasContext.Provider value={canvasContext}>\n          <Selection />\n        </CanvasContext.Provider>\n      </StoryContext.Provider>,\n      { wrapper: Wrapper }\n    );\n  }\n\n  function performRotation(rotateTo) {\n    const moveable =\n      MockMoveable.mock.calls[MockMoveable.mock.calls.length - 1][0];\n    moveable?.onRotateStart({ set: () => {} });\n    moveable?.onRotate({\n      target,\n      beforeRotate: rotateTo,\n    });\n    moveable?.onRotateEnd({ target });\n  }\n\n  const rotateCases = [\n    ['normally', { rotateTo: 45, expectedRotationAngle: 45 }],\n    ['through 360 degrees', { rotateTo: 370, expectedRotationAngle: 10 }],\n    ['through negative', { rotateTo: -370, expectedRotationAngle: 350 }],\n  ];\n\n  it.each(rotateCases)(\n    'should rotate %p',\n    async (_, { rotateTo, expectedRotationAngle }) => {\n      arrange();\n      // Wait until the component has loaded.\n      await waitFor(\n        () => MockMoveable.mock.calls[MockMoveable.mock.calls.length - 1][0]\n      );\n      act(() => {\n        performRotation(rotateTo);\n      });\n\n      expect(updateSelectedElements).toHaveBeenLastCalledWith({\n        properties: { rotationAngle: expectedRotationAngle },\n      });\n    }\n  );\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/useCanvasKeys.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, fireEvent } from '@testing-library/react';\nimport { useRef } from '@googleforcreators/react';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport useHighlights from '../../../app/highlights/useHighlights';\nimport useCanvasKeys from '../../../app/canvas/useCanvasKeys';\nimport StoryContext from '../../../app/story/context';\nimport CanvasContext from '../../../app/canvas/context';\n\njest.mock('../../../app/highlights/useHighlights', () => ({\n  ...jest.requireActual('../../../app/highlights/useHighlights'),\n  __esModule: true,\n  default: jest.fn(),\n}));\n\nconst Canvas = () => {\n  const ref = useRef(null);\n  useCanvasKeys(ref);\n  return <div ref={ref} />;\n};\n\nconst mockUseHighlights = useHighlights;\nconst setHighlights = jest.fn();\n\ndescribe('useCanvasKeys', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n    mockUseHighlights.mockImplementation(() => ({\n      setHighlights,\n    }));\n  });\n\n  it('should select all elements and collect their IDs when mod+a is pressed.', () => {\n    const setSelectedElementsById = jest.fn();\n\n    const { container } = render(\n      <StoryContext.Provider\n        value={{\n          actions: { setSelectedElementsById },\n          state: {\n            currentPage: { elements: [{ id: '123' }, { id: '456' }] },\n          },\n        }}\n      >\n        <Canvas />\n      </StoryContext.Provider>\n    );\n\n    fireEvent.keyDown(container, {\n      key: 'a',\n      which: 65,\n      ctrlKey: true,\n    });\n\n    expect(setSelectedElementsById).toHaveBeenCalledWith({\n      elementIds: ['123', '456'],\n    });\n  });\n\n  it('should enter edit mode when the element can when the \"Enter\" key is pressed.', () => {\n    const setEditingElement = jest.fn();\n\n    const { container } = render(\n      <StoryContext.Provider\n        value={{\n          actions: { addElements: () => {} },\n          state: {\n            selectedElements: [{ id: 'abc123', type: 'text' }],\n          },\n        }}\n      >\n        <CanvasContext.Provider\n          value={{\n            state: { isEditing: false },\n            actions: { setEditingElement },\n          }}\n        >\n          <Canvas />\n        </CanvasContext.Provider>\n      </StoryContext.Provider>\n    );\n\n    fireEvent.keyDown(container, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    expect(setEditingElement).toHaveBeenCalledWith('abc123');\n  });\n\n  it('should delete selected elements when the \"Delete\" key is pressed.', () => {\n    const deleteSelectedElements = jest.fn();\n\n    const { container } = render(\n      <StoryContext.Provider\n        value={{\n          state: {\n            currentPage: { elements: [{ id: '123' }] },\n            selectedElements: [{ id: '123' }],\n          },\n          actions: { deleteSelectedElements },\n        }}\n      >\n        <Canvas />\n      </StoryContext.Provider>\n    );\n\n    fireEvent.keyDown(container, {\n      key: 'Backspace',\n      which: 8,\n    });\n\n    expect(deleteSelectedElements).toHaveBeenCalledWith();\n  });\n\n  it('should open and focus the design panel link input when mod+k is pressed.', () => {\n    const { container } = render(\n      <StoryContext.Provider\n        value={{\n          actions: {},\n          state: {\n            selectedElements: [{ id: '123' }, { id: '456' }],\n          },\n        }}\n      >\n        <Canvas />\n      </StoryContext.Provider>\n    );\n\n    fireEvent.keyDown(container, {\n      key: 'k',\n      which: 75,\n      ctrlKey: true,\n    });\n\n    expect(setHighlights).toHaveBeenCalledWith({\n      elements: [{ id: '123' }, { id: '456' }],\n      highlight: 'LINK',\n    });\n  });\n\n  it('should should play/pause animation when mod+enter is pressed.', () => {\n    const updateAnimationState = jest.fn();\n\n    const { container } = render(\n      <StoryContext.Provider\n        value={{\n          state: {\n            currentPageNumber: 2,\n            currentPage: { elements: [{ id: '123' }] },\n          },\n          actions: { updateAnimationState },\n        }}\n      >\n        <Canvas />\n      </StoryContext.Provider>\n    );\n\n    fireEvent.keyDown(container, {\n      key: 'Enter',\n      which: 13,\n      ctrlKey: true,\n    });\n\n    expect(updateAnimationState).toHaveBeenCalledWith({\n      animationState: 'playing',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/test/useInsertElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport useInsertElement from '../useInsertElement';\nimport { ZoomSetting } from '../../../constants';\nimport { useStory } from '../../../app/story';\nimport { useLocalMedia } from '../../../app/media';\nimport { useLayout } from '../../../app/layout';\n\njest.mock('../../../app/story');\njest.mock('../../../app/media');\njest.mock('../../../app/layout');\n\nconst IMAGE_TYPE = 'image';\n\nconst PROPS_LOCAL = {\n  resource: {\n    type: 'image',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    creationDate: '2020-08-10T03:42:08',\n    src: 'http://local_url/wp-content/uploads/2020/08/local_image.jpg',\n    width: 1920,\n    height: 1080,\n    posterId: 0,\n    id: 211,\n    alt: 'local_image',\n    sizes: {\n      full: {\n        file: 'local_image.jpg',\n        width: 1920,\n        height: 1080,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://wp.local/wp-content/uploads/2020/08/local_image.jpg',\n      },\n    },\n  },\n  x: 126,\n  y: 512,\n  width: 354,\n  height: 199,\n};\n\ndescribe('useInsertElement', () => {\n  const setZoomSetting = jest.fn();\n\n  beforeAll(() => {\n    useStory.mockReturnValue({\n      addElement: jest.fn(),\n    });\n\n    useLocalMedia.mockReturnValue({\n      postProcessingResource: jest.fn(),\n      isCurrentResourceUploading: jest.fn(),\n    });\n\n    useLayout.mockReturnValue({\n      setZoomSetting,\n    });\n\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should always invoke setZoomSetting with FIT', () => {\n    const { result } = renderHook(() => useInsertElement());\n    act(() => {\n      result.current(IMAGE_TYPE, PROPS_LOCAL);\n    });\n\n    expect(setZoomSetting).toHaveBeenCalledWith(ZoomSetting.Fit);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useFocusCanvas.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\nfunction useFocusCanvas() {\n  /**\n   * @param {boolean} force When true, the focus will always be\n   * transferred to the canvas. Otherwise, the focus will only be transferred\n   * when no other editor input is holding it.\n   */\n  const focusCanvas = useCallback((force = true) => {\n    setTimeout(() => {\n      const doc = window.document;\n      if (\n        force &&\n        doc.activeElement instanceof HTMLElement &&\n        doc.activeElement !== doc.body\n      ) {\n        doc.activeElement.blur();\n      }\n      const evt = new window.FocusEvent('focusout');\n      doc.dispatchEvent(evt);\n    });\n  }, []);\n\n  return focusCanvas;\n}\n\nexport default useFocusCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useInsertElement.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  createNewElement,\n  elementIs,\n  type ElementType,\n  type Element,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\nimport { useLayout } from '../../app/layout';\nimport { ZoomSetting } from '../../constants';\nimport { noop } from '../../utils/noop';\nimport useFocusCanvas from './useFocusCanvas';\nimport getElementProperties from './utils/getElementProperties';\n\nfunction createElementForCanvas(type: ElementType, props: Element) {\n  return createNewElement(type, getElementProperties(type, props));\n}\n\ninterface ElementWithPageId extends Element {\n  pageId?: string;\n}\nfunction useInsertElement() {\n  const { addElement, combineElements, backgroundElementId } = useStory(\n    ({ state, actions }) => ({\n      addElement: actions.addElement,\n      combineElements: actions.combineElements,\n      backgroundElementId: state.currentPage?.elements?.[0]?.id,\n    })\n  );\n\n  const { setZoomSetting } = useLayout(({ actions: { setZoomSetting } }) => ({\n    setZoomSetting,\n  }));\n\n  const focusCanvas = useFocusCanvas();\n\n  /**\n   * @param {string} type The element's type.\n   * @param {Object} props The element's initial properties.\n   * @param {boolean} insertAsBackground Whether to insert the element as a background element.\n   */\n  const insertElement = useCallback(\n    (\n      type: ElementType,\n      props: ElementWithPageId,\n      insertAsBackground = false\n    ) => {\n      setZoomSetting(ZoomSetting.Fit);\n      const element = createElementForCanvas(type, props);\n      const { id } = element;\n      addElement({ element });\n\n      if (insertAsBackground && backgroundElementId) {\n        combineElements({\n          firstElement: element,\n          secondId: backgroundElementId,\n        });\n      }\n\n      const elementId = insertAsBackground ? backgroundElementId : id;\n\n      // Auto-play on insert.\n      if (\n        elementId &&\n        elementIs.video(element) &&\n        element.resource.src &&\n        !element.resource.isPlaceholder\n      ) {\n        setTimeout(() => {\n          const videoEl = document.getElementById(\n            `video-${elementId}`\n          ) as HTMLVideoElement | null;\n          if (videoEl) {\n            videoEl.play().catch(noop);\n          }\n        });\n      }\n\n      focusCanvas();\n\n      return element;\n    },\n    [\n      addElement,\n      backgroundElementId,\n      combineElements,\n      focusCanvas,\n      setZoomSetting,\n    ]\n  );\n\n  return insertElement;\n}\n\nexport default useInsertElement;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useInsertTextSet.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useBatchingCallback } from '@googleforcreators/react';\nimport {\n  DANGER_ZONE_HEIGHT,\n  FULLBLEED_HEIGHT,\n  PAGE_WIDTH,\n} from '@googleforcreators/units';\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport objectWithout from '../../utils/objectWithout';\nimport { useStory } from '../../app/story';\nimport { useCalculateAccessibleTextColors } from '../../app/pageCanvas';\nimport useInsertElement from './useInsertElement';\n\nconst SCRIM_PADDING = 24;\n\nfunction useInsertTextSet(shouldUseSmartColor = false) {\n  const insertElement = useInsertElement();\n  const calculateAccessibleTextColors = useCalculateAccessibleTextColors();\n\n  const { setSelectedElementsById } = useStory(\n    ({ actions: { setSelectedElementsById } }) => {\n      return {\n        setSelectedElementsById,\n      };\n    }\n  );\n\n  const insertTextSet = useBatchingCallback(\n    async (toAdd, applySmartColor = shouldUseSmartColor) => {\n      const htmlFormatters = getHTMLFormatters();\n      const { setColor } = htmlFormatters;\n      const addedElements = [];\n\n      const hasPredefinedColor = toAdd.some((element) =>\n        element.content?.includes('color:')\n      );\n\n      let textElementsContrasts = [];\n      let firstValidColor = null;\n\n      const white = {\n        r: 255,\n        g: 255,\n        b: 255,\n      };\n      const black = {\n        r: 0,\n        g: 0,\n        b: 0,\n      };\n      const whiteScrim = {\n        ...white,\n        a: 0.3,\n      };\n      const blackScrim = {\n        ...black,\n        a: 0.3,\n      };\n      let preferredScrimColor, scrimsCount, useScrim;\n\n      // Insert scrim as a first element if needed.\n      if (applySmartColor && !hasPredefinedColor) {\n        textElementsContrasts = await Promise.all(\n          toAdd.map((element) =>\n            element.type === 'text'\n              ? calculateAccessibleTextColors(element)\n              : null\n          )\n        );\n        firstValidColor = textElementsContrasts.find((c) => c);\n        const allColorsEqual = textElementsContrasts.every(\n          (contrast) =>\n            contrast === null ||\n            (contrast.color?.r === firstValidColor.color?.r &&\n              contrast.color?.g === firstValidColor.color?.g &&\n              contrast.color?.b === firstValidColor.color?.b &&\n              contrast.color?.a === firstValidColor.color?.a)\n        );\n        scrimsCount = textElementsContrasts.reduce(\n          (acc, contrast) => (contrast?.backgroundColor ? acc + 1 : acc),\n          0\n        );\n        const blackScrims = textElementsContrasts.reduce(\n          (acc, contrast) =>\n            contrast?.backgroundColor?.r === 0 &&\n            contrast?.backgroundColor?.g === 0 &&\n            contrast?.backgroundColor?.b === 0\n              ? acc + 1\n              : acc,\n          0\n        );\n        preferredScrimColor =\n          scrimsCount - blackScrims > 0 ? blackScrim : whiteScrim;\n\n        useScrim = scrimsCount > 0 || allColorsEqual === false;\n\n        if (useScrim) {\n          const { textSetHeight, textSetWidth } = toAdd[0];\n          const getMinDim = (dim) =>\n            Math.min.apply(\n              null,\n              toAdd.map((e) => e[dim])\n            );\n          const x = getMinDim('x');\n          const y = getMinDim('y');\n          const scrim = {\n            x: x - SCRIM_PADDING,\n            y: y - SCRIM_PADDING,\n            width: textSetWidth + SCRIM_PADDING * 2,\n            height: textSetHeight + SCRIM_PADDING * 2,\n            backgroundColor: {\n              color: preferredScrimColor,\n            },\n            type: 'shape',\n          };\n          addedElements.push(insertElement(ELEMENT_TYPES.SHAPE, scrim));\n        }\n      }\n\n      toAdd.forEach((element, index) => {\n        const toInsert = objectWithout(element, [\n          'id',\n          'normalizedOffsetX',\n          'normalizedOffsetY',\n          'textSetWidth',\n          'textSetHeight',\n        ]);\n        if (applySmartColor && !hasPredefinedColor) {\n          // If scrim is used - adjust the colors, otherwise use defaults.\n          const scrimContrastingTextColor =\n            preferredScrimColor.r === 0 ? white : black;\n          const autoColor = useScrim\n            ? { color: scrimContrastingTextColor }\n            : textElementsContrasts[index];\n\n          // Only apply the colors if a better color was detected.\n          if (element.type === 'text' && autoColor.color) {\n            toInsert.content = setColor(toInsert.content, autoColor);\n          }\n          if (element.type === 'shape' && firstValidColor.color) {\n            // So far we only use borders (no fill) or shapes with fill (no borders).\n            if (element.border) {\n              toInsert.border.color = firstValidColor;\n            } else {\n              toInsert.backgroundColor = firstValidColor;\n            }\n          }\n        }\n        addedElements.push(insertElement(element.type, toInsert));\n      });\n      // Select all added elements.\n      setSelectedElementsById({\n        elementIds: addedElements.map(({ id }) => id),\n      });\n    },\n    [\n      calculateAccessibleTextColors,\n      shouldUseSmartColor,\n      insertElement,\n      setSelectedElementsById,\n    ]\n  );\n\n  const insertTextSetByOffset = useCallback(\n    (elements, { offsetX, offsetY }) => {\n      if (!elements.length) {\n        return;\n      }\n\n      const positionedTextSet = elements\n        .map((element) => {\n          // Skip adding any elements that are outside of page.\n          const x = element.normalizedOffsetX + offsetX;\n          const y = element.normalizedOffsetY + offsetY;\n          const { width, height } = element;\n          if (\n            x > PAGE_WIDTH ||\n            x + width < 0 ||\n            y > FULLBLEED_HEIGHT ||\n            y + height < -DANGER_ZONE_HEIGHT\n          ) {\n            return null;\n          }\n          return {\n            ...element,\n            x,\n            y,\n          };\n        })\n        .filter((el) => el);\n\n      insertTextSet(positionedTextSet, false /* Skips using smart color */);\n    },\n    [insertTextSet]\n  );\n\n  return { insertTextSet, insertTextSetByOffset };\n}\n\nexport default useInsertTextSet;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/usePinchToZoom.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useLayoutEffect,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../app/layout';\n\nconst MIN_LEVEL = 0.25;\nconst MAX_LEVEL = 3;\n\nfunction usePinchToZoom({ containerRef }) {\n  const { zoomLevel, setZoomLevel } = useLayout(\n    ({ state: { zoomLevel }, actions: { setZoomLevel } }) => ({\n      zoomLevel,\n      setZoomLevel,\n    })\n  );\n\n  const handleZoom = useDebouncedCallback((level) => setZoomLevel(level), 25);\n\n  useLayoutEffect(() => {\n    if (!containerRef.current) {\n      return undefined;\n    }\n\n    // Clamp zoom ensuring it's between the min-max value and ensure it only moves by steps of 25%.\n    const clampZoomLevel = (value) => {\n      return Math.min(MAX_LEVEL, Math.max(MIN_LEVEL, value - (value % 0.25)));\n    };\n\n    const onWheel = (e) => {\n      const { ctrlKey, deltaY } = e;\n      const node = containerRef.current.childNodes[0];\n      if (ctrlKey && node.contains(e.target) && deltaY) {\n        // Zoom by 25% steps. This is due to performance reasons and could be followed up later.\n        // Ideally we'd use transform: scale locally and update only when the event finishes, however,\n        // there are too many other pieces that would need adjustment as well.\n        const newStepZoom = deltaY > 0 ? zoomLevel - 0.25 : zoomLevel + 0.25;\n        handleZoom(clampZoomLevel(newStepZoom));\n        e.preventDefault();\n      }\n    };\n\n    const preventDefault = (e) => {\n      const node = containerRef.current.childNodes[0];\n      if (node.contains(e.target)) {\n        e.preventDefault();\n      }\n    };\n\n    const handleGestureChange = (e) => {\n      const node = containerRef.current.childNodes[0];\n      const { scale } = e;\n      if (node.contains(e.target) && scale) {\n        const newStepZoom = scale < 1 ? zoomLevel - 0.25 : zoomLevel + 0.25;\n        handleZoom(clampZoomLevel(newStepZoom));\n        e.preventDefault();\n      }\n    };\n\n    document.addEventListener('wheel', onWheel, { passive: false });\n    // Safari.\n    document.addEventListener('gesturestart', preventDefault);\n    document.addEventListener('gestureend', preventDefault);\n    document.addEventListener('gesturechange', handleGestureChange);\n    return () => {\n      document.removeEventListener('wheel', onWheel, { passive: false });\n      // Safari\n      document.removeEventListener('gesturestart', preventDefault);\n      document.removeEventListener('gestureend', preventDefault);\n      document.removeEventListener('gesturechange', handleGestureChange);\n    };\n  }, [containerRef, handleZoom, zoomLevel]);\n}\n\nexport default usePinchToZoom;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useUploadWithPreview.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\ndeclare function useUploadWithPreview(): (\n  files: File[],\n  insertAsBackground?: boolean,\n  args?: object\n) => void;\n\nexport default useUploadWithPreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useUploadWithPreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../app/story/useStory';\nimport { useLocalMedia } from '../../app/media';\nimport useUpdateElementDimensions from '../../app/media/utils/useUpdateElementDimensions';\nimport useInsertElement from './useInsertElement';\n\nfunction useUploadWithPreview() {\n  const { uploadMedia, postProcessingResource } = useLocalMedia(\n    ({ actions: { uploadMedia, postProcessingResource } }) => ({\n      uploadMedia,\n      postProcessingResource,\n    })\n  );\n  const insertElement = useInsertElement();\n  const { updateElementDimensions } = useUpdateElementDimensions();\n  const { deleteElementsByResourceId } = useStory((state) => ({\n    deleteElementsByResourceId: state.actions.deleteElementsByResourceId,\n  }));\n\n  const onUploadProgress = useCallback(\n    ({ id, resource }) => {\n      updateElementDimensions({ id, resource });\n    },\n    [updateElementDimensions]\n  );\n\n  const onUploadSuccess = useCallback(\n    ({ id, resource }) => {\n      updateElementDimensions({ id, resource });\n\n      // onUploadSuccess is also called with previousResourceId,\n      // for which we don't need to run this.\n      if (id === resource.id) {\n        postProcessingResource(resource);\n      }\n    },\n    [updateElementDimensions, postProcessingResource]\n  );\n\n  const onUploadError = useCallback(\n    ({ id }) => {\n      deleteElementsByResourceId({ id });\n    },\n    [deleteElementsByResourceId]\n  );\n\n  const uploadWithPreview = useCallback(\n    (files, insertAsBackground = false, args = {}) => {\n      const onUploadStart = ({ resource }) => {\n        insertElement(resource.type, { resource }, insertAsBackground);\n      };\n\n      uploadMedia(files, {\n        onUploadStart,\n        onUploadProgress,\n        onUploadError,\n        onUploadSuccess,\n        ...args,\n      });\n    },\n    [\n      uploadMedia,\n      onUploadProgress,\n      onUploadError,\n      onUploadSuccess,\n      insertElement,\n    ]\n  );\n\n  return uploadWithPreview;\n}\n\nexport default useUploadWithPreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/useWindowResizeHandler.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\n\nfunction useWindowResizeHandler(ref) {\n  useEffect(() => {\n    const handleUpdateMoveable = () => ref.current?.updateRect();\n    window.addEventListener('resize', handleUpdateMoveable);\n    return () => {\n      window.removeEventListener('resize', handleUpdateMoveable);\n    };\n  }, [ref]);\n}\n\nexport default useWindowResizeHandler;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/getColorFromPixelData.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst getColorIndicesForCoord = (x, y, width) => {\n  const red = (Math.floor(y) * width + Math.floor(x)) * 4;\n  return [red, red + 1, red + 2, red + 3];\n};\nfunction getColorFromPixelData(pixelData, x, y, width) {\n  const colorIndices = getColorIndicesForCoord(x, y, width);\n  const [redIndex, greenIndex, blueIndex, alphaIndex] = colorIndices;\n  const r = pixelData[redIndex];\n  const g = pixelData[greenIndex];\n  const b = pixelData[blueIndex];\n  const a = pixelData[alphaIndex] / 255;\n  return { r, g, b, a };\n}\n\nexport default getColorFromPixelData;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/getElementProperties.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport STICKERS from '@googleforcreators/stickers';\nimport { dataPixels } from '@googleforcreators/units';\nimport {\n  elementIs,\n  type ElementType,\n  type Element,\n  getDefinitionForType,\n} from '@googleforcreators/elements';\nimport { DEFAULT_MASK } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport getInsertedElementSize from '../../../utils/getInsertedElementSize';\n\nfunction isNum(value: number | undefined) {\n  return typeof value === 'number';\n}\n\nfunction getElementProperties(type: ElementType, element: Element) {\n  let { x, y, width, height } = element;\n  const { mask, rotationAngle = 0, ...rest } = element;\n  const { isMaskable, isMedia } = getDefinitionForType(type);\n\n  const attrs = { ...rest, type };\n  let ratio = 1;\n  let resource, scale, focalX, focalY, sticker;\n  if (elementIs.sticker(element)) {\n    sticker = element.sticker;\n    ratio = STICKERS?.[sticker.type]?.aspectRatio;\n  } else if (elementIs.media(element)) {\n    resource = element.resource;\n    ratio =\n      isNum(resource.width) && isNum(resource.height)\n        ? resource.width / resource.height\n        : 1;\n    scale = element.scale || 100;\n    focalX = element.focalX || 50;\n    focalY = element.focalY || 50;\n  }\n\n  // Width and height defaults. Width takes precedence.\n  const size = getInsertedElementSize(\n    type,\n    width,\n    height,\n    attrs,\n    ratio,\n    resource\n  );\n  width = size.width;\n  height = size.height;\n\n  // X and y defaults: in the top corner of the page.\n  if (!isNum(x)) {\n    x = 48;\n  }\n  if (!isNum(y)) {\n    y = 0;\n  }\n\n  x = dataPixels(x);\n  y = dataPixels(y);\n\n  const mediaProps = {\n    focalX,\n    focalY,\n    resource,\n    scale,\n  };\n\n  return {\n    ...attrs,\n    x,\n    y,\n    width,\n    height,\n    rotationAngle,\n    ...(isMedia ? { ...mediaProps } : {}),\n    ...(isMaskable\n      ? {\n          mask: mask || DEFAULT_MASK,\n        }\n      : {}),\n    ...(sticker ? { sticker } : {}),\n  };\n}\n\nexport default getElementProperties;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/normalizeRotationDegrees.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Converts degrees above 360 or below 0 to an equivalent between 0 and 360.\n * Note that using just degrees % 360 would leave in negative degrees.\n *\n * @param {number} degrees Initial rotation angle.\n * @return {number} Degrees between 0 and 360.\n */\nfunction normalizeRotationDegrees(degrees) {\n  return ((degrees % 360) + 360) % 360;\n}\n\nexport default normalizeRotationDegrees;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/test/getElementProperties.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport getElementProperties from '../getElementProperties';\n\nconst COMMON_PROPERTIES = {\n  opacity: 100,\n  flip: {\n    vertical: false,\n    horizontal: false,\n  },\n  rotationAngle: 0,\n  lockAspectRatio: true,\n  backgroundColor: {\n    color: {\n      r: 196,\n      g: 196,\n      b: 196,\n    },\n  },\n  x: 94,\n  y: 77,\n  width: 137,\n  height: 137,\n  scale: 100,\n  focalX: 50,\n  focalY: 50,\n};\n\nconst BASIC_SHAPE = {\n  ...COMMON_PROPERTIES,\n  id: 'fake-shape-id',\n  backgroundColor: {\n    color: {\n      r: 196,\n      g: 196,\n      b: 196,\n    },\n  },\n  type: 'shape',\n  mask: {\n    type: 'triangle',\n  },\n};\n\nconst VIDEO_RESOURCE = {\n  type: 'video',\n  mimeType: 'video/webm',\n  creationDate: '2021-05-11T21:55:24',\n  src: 'http://test.example/video.mp4',\n  width: 720,\n  height: 1280,\n  poster: 'http://test.example/video-poster.jpg',\n  posterId: 92,\n  id: 91,\n  length: 6,\n  lengthFormatted: '0:06',\n  alt: 'small-video',\n  sizes: {},\n  isOptimized: false,\n  baseColor: '#734727',\n};\n\ndescribe('getElementProperties', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should default x/y to (48, 0) if not provided', () => {\n    const properties = getElementProperties('shape', {\n      ...BASIC_SHAPE,\n      x: undefined,\n      y: undefined,\n    });\n\n    expect(properties.x).toBe(48);\n    expect(properties.y).toBe(0);\n  });\n\n  it('should keep x/y unmodified', () => {\n    const properties = getElementProperties('shape', {\n      ...BASIC_SHAPE,\n      x: 50,\n      y: 25,\n    });\n\n    expect(properties.x).toBe(50);\n    expect(properties.y).toBe(25);\n  });\n\n  it('should keep resource unmodified', () => {\n    const properties = getElementProperties('video', {\n      ...COMMON_PROPERTIES,\n      resource: VIDEO_RESOURCE,\n    });\n\n    expect(properties.resource).toStrictEqual(VIDEO_RESOURCE);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/useElementOutOfCanvas.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport isTargetOutOfContainer from '../../../utils/isTargetOutOfContainer';\nimport { useStory, useCanvas, useTransform } from '../../../app';\n\nfunction useElementOutOfCanvas() {\n  const { deleteSelectedElements } = useStory((state) => ({\n    deleteSelectedElements: state.actions.deleteSelectedElements,\n  }));\n  const { clearTransforms } = useTransform((state) => ({\n    clearTransforms: state.actions.clearTransforms,\n  }));\n  const { fullbleedContainer } = useCanvas(\n    ({ state: { fullbleedContainer } }) => ({\n      fullbleedContainer,\n    })\n  );\n\n  // Deletes elements that are out of canvas.\n  const handleElementOutOfCanvas = (target) => {\n    if (isTargetOutOfContainer(target, fullbleedContainer)) {\n      deleteSelectedElements();\n      clearTransforms();\n      return true;\n    }\n    return false;\n  };\n\n  return {\n    handleElementOutOfCanvas,\n  };\n}\n\nexport default useElementOutOfCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/useFullbleedMediaAsBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport {\n  useSnackbar,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { MEDIA_ELEMENT_TYPES } from '@googleforcreators/elements';\nimport SAT from 'sat';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas, useTransform } from '../../../app';\nimport useElementPolygon from '../../../utils/useElementPolygon';\n\nfunction useFullbleedMediaAsBackground() {\n  const [\n    isBackgroundSnackbarMessageDismissed,\n    setIsBackgroundSnackbarMessageDismissed,\n  ] = useState(\n    localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX.BACKGROUND_IS_SET_DIALOG_DISMISSED\n    )\n  );\n  const { setBackgroundElement, isDefaultBackground } = useStory((state) => ({\n    setBackgroundElement: state.actions.setBackgroundElement,\n    isDefaultBackground:\n      state.state.currentPage?.elements[0]?.isDefaultBackground,\n  }));\n  const { fullbleedContainer } = useCanvas(\n    ({ state: { fullbleedContainer } }) => ({\n      fullbleedContainer,\n    })\n  );\n  const { clearTransforms } = useTransform((state) => ({\n    clearTransforms: state.actions.clearTransforms,\n  }));\n  const { showSnackbar } = useSnackbar();\n  const getElementPolygon = useElementPolygon();\n\n  const buffer = 2;\n\n  const handleFullbleedMediaAsBackground = (selectedElement) => {\n    if (\n      isDefaultBackground &&\n      MEDIA_ELEMENT_TYPES.includes(selectedElement.type)\n    ) {\n      const elPolygon = getElementPolygon(selectedElement);\n      const fullbleedBox = fullbleedContainer.getBoundingClientRect();\n      // We use 2 pixel buffer from each edge for setting the background media.\n      const bgPolygon = new SAT.Box(\n        new SAT.Vector(fullbleedBox.x + buffer, fullbleedBox.y + buffer),\n        fullbleedBox.width - buffer * 2,\n        fullbleedBox.height - buffer * 2\n      ).toPolygon();\n      const response = new SAT.Response();\n      SAT.testPolygonPolygon(elPolygon, bgPolygon, response);\n      if (response.bInA) {\n        setBackgroundElement({ elementId: selectedElement.id });\n      }\n\n      if (!isBackgroundSnackbarMessageDismissed) {\n        showSnackbar({\n          message: __(\n            'Full bleed images and videos are automatically set as background. Double click to scale and position at any time.',\n            'web-stories'\n          ),\n          dismissible: true,\n        });\n        localStore.setItemByKey(\n          LOCAL_STORAGE_PREFIX.BACKGROUND_IS_SET_DIALOG_DISMISSED,\n          true\n        );\n        setIsBackgroundSnackbarMessageDismissed(true);\n      }\n      clearTransforms();\n    }\n  };\n\n  return {\n    handleFullbleedMediaAsBackground,\n  };\n}\n\nexport default useFullbleedMediaAsBackground;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/useSnapping.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { FULLBLEED_RATIO } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useDropTargets } from '../../dropTargets';\nimport {\n  useCanvas,\n  useLayout,\n  useUserOnboarding,\n  CANVAS_BOUNDING_BOX_IDS,\n  useCanvasBoundingBox,\n} from '../../../app';\n\nfunction useSnapping({\n  canSnap,\n  otherNodes,\n  snappingOffsetX = null,\n  isDragging,\n}) {\n  const canvasRect = useCanvasBoundingBox(\n    CANVAS_BOUNDING_BOX_IDS.CANVAS_CONTAINER\n  );\n  const pageRect = useCanvasBoundingBox(CANVAS_BOUNDING_BOX_IDS.PAGE_CONTAINER);\n  const designSpaceGuideline = useCanvas(\n    ({ state }) => state.designSpaceGuideline\n  );\n  const { pageWidth, pageHeight } = useLayout(\n    ({ state: { pageWidth, pageHeight } }) => ({\n      pageWidth,\n      pageHeight,\n    })\n  );\n  const { activeDropTargetId, isDropTargetingDisabled } = useDropTargets(\n    ({ state }) => ({\n      activeDropTargetId: state.activeDropTargetId,\n      isDropTargetingDisabled: state.isDropTargetingDisabled,\n    })\n  );\n\n  const triggerOnboarding = useUserOnboarding(({ SAFE_ZONE }) => SAFE_ZONE);\n\n  // Drop-targeting is disabled with ⌘ key, we also disable snapping in this case.\n  canSnap = canSnap && !isDropTargetingDisabled && !activeDropTargetId;\n\n  const handleSnap = useCallback(\n    ({ elements }) => {\n      const isSnappingDesignSpace = elements\n        .flat()\n        .some(\n          ({ center, element }) => element === designSpaceGuideline && !center\n        );\n      if (isDragging && isSnappingDesignSpace) {\n        triggerOnboarding();\n      }\n    },\n    [isDragging, designSpaceGuideline, triggerOnboarding]\n  );\n\n  if (!canvasRect || !pageRect) {\n    return {};\n  }\n\n  const canvasOffsetX = snappingOffsetX ? snappingOffsetX : canvasRect.x;\n\n  const offsetX = Math.ceil(pageRect.x - canvasOffsetX);\n  const offsetY = Math.floor(pageRect.y - canvasRect.y);\n\n  const verticalGuidelines = canSnap\n    ? [offsetX, offsetX + pageWidth / 2, offsetX + pageWidth]\n    : [];\n\n  const fullBleedOffset = (pageWidth / FULLBLEED_RATIO - pageHeight) / 2;\n\n  const horizontalGuidelines = canSnap\n    ? [\n        offsetY - fullBleedOffset,\n        offsetY,\n        offsetY + pageHeight / 2,\n        offsetY + pageHeight,\n        offsetY + pageHeight + fullBleedOffset,\n      ]\n    : [];\n\n  const elementGuidelines = canSnap\n    ? [...otherNodes, designSpaceGuideline]\n    : [];\n\n  const snapDirections = {\n    left: true,\n    top: true,\n    right: true,\n    bottom: true,\n    center: true,\n    middle: true,\n  };\n\n  return {\n    snappable: canSnap,\n    snapGap: canSnap,\n    snapDirections,\n    elementSnapDirections: snapDirections,\n    isDisplaySnapDigit: false,\n    onSnap: handleSnap,\n    horizontalGuidelines,\n    verticalGuidelines,\n    elementGuidelines,\n  };\n}\n\nexport default useSnapping;\n"
  },
  {
    "path": "packages/story-editor/src/components/canvas/utils/useUpdateSelectionRectangle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\n\nfunction useUpdateSelectionRectangle(moveableRef, dependencies = []) {\n  // If deps ever update, update rect now AND in a frame's time\n  useEffect(() => {\n    let mounted = true;\n\n    const update = () => {\n      if (!mounted) {\n        return;\n      }\n      moveableRef.current?.updateRect?.();\n    };\n\n    update();\n\n    const timeout = setTimeout(update);\n\n    return () => {\n      mounted = false;\n      clearTimeout(timeout);\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- ref is stable, deps are the only thing that matters\n  }, dependencies);\n}\n\nexport default useUpdateSelectionRectangle;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklist.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport {\n  useEffect,\n  useRef,\n  useCallback,\n  forwardRef,\n} from '@googleforcreators/react';\nimport { FOCUSABLE_SELECTORS } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_FOOTER } from '../../constants/zIndex';\nimport DirectionAware from '../directionAware';\nimport Popup, { NavigationWrapper, TopNavigation } from '../secondaryPopup';\nimport { Tablist } from '../tablist';\nimport { Toggle } from './toggle';\nimport {\n  CATEGORY_LABELS,\n  CHECKLIST_TITLE,\n  ISSUE_TYPES,\n  POPUP_ID,\n  PANEL_EXPANSION_BY_CHECKPOINT,\n  PANEL_VISIBILITY_BY_STATE,\n} from './constants';\nimport {\n  AccessibilityChecks,\n  DesignChecks,\n  EmptyContentCheck,\n  PriorityChecks,\n} from './checklistContent';\n\nimport { useCategoryCount } from './countContext';\nimport { useChecklist } from './checklistContext';\nimport { useCheckpoint } from './checkpointContext';\nimport { getTabPanelMaxHeight } from './styles';\n\nconst Wrapper = styled.div`\n  z-index: ${Z_INDEX_FOOTER};\n`;\n\n// TODO make this responsive so that title bar is never covered by popup.\nconst StyledNavigationWrapper = styled(NavigationWrapper)``;\n\nconst ThroughputPopup = forwardRef(function ThroughputPopup(\n  { isOpen, children, close },\n  ref\n) {\n  const closeButtonRef = useRef();\n  const {\n    checklistFocused,\n    isChecklistMounted,\n    resetChecklistFocused,\n    setIsChecklistMounted,\n  } = useChecklist(\n    ({\n      state: { isChecklistMounted, checklistFocused },\n      actions: { setIsChecklistMounted, resetChecklistFocused },\n    }) => ({\n      checklistFocused,\n      isChecklistMounted,\n      resetChecklistFocused,\n      setIsChecklistMounted,\n    })\n  );\n\n  // focus checklist\n  useEffect(() => {\n    if (checklistFocused && closeButtonRef.current) {\n      closeButtonRef.current.focus();\n    }\n\n    resetChecklistFocused();\n  }, [checklistFocused, resetChecklistFocused]);\n\n  return (\n    <Popup\n      popupId={POPUP_ID}\n      isOpen={isOpen}\n      ariaLabel={CHECKLIST_TITLE}\n      shouldKeepMounted\n      onEnter={() => setIsChecklistMounted(true)}\n      onExited={() => setIsChecklistMounted(false)}\n    >\n      {isChecklistMounted ? (\n        <StyledNavigationWrapper ref={ref} isOpen={isOpen}>\n          <TopNavigation\n            ref={closeButtonRef}\n            onClose={close}\n            label={CHECKLIST_TITLE}\n            popupId={POPUP_ID}\n          />\n          <Tablist\n            id=\"pre-publish-checklist\"\n            data-isexpanded={isOpen}\n            aria-label={__('Potential Story issues by category', 'web-stories')}\n          >\n            {children}\n          </Tablist>\n          <EmptyContentCheck />\n        </StyledNavigationWrapper>\n      ) : (\n        children\n      )}\n    </Popup>\n  );\n});\nThroughputPopup.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  close: PropTypes.func.isRequired,\n  children: PropTypes.arrayOf(PropTypes.node).isRequired,\n};\n\nexport function Checklist({ items = {} }) {\n  const { close, openPanel, toggle, isOpen, isChecklistMounted, setOpenPanel } =\n    useChecklist(\n      ({\n        actions: { close, toggle, setOpenPanel },\n        state: { isOpen, isChecklistMounted, openPanel },\n      }) => ({\n        close,\n        toggle,\n        isOpen,\n        isChecklistMounted,\n        openPanel,\n        setOpenPanel,\n      })\n    );\n\n  const priorityCount = useCategoryCount(ISSUE_TYPES.PRIORITY);\n  const designCount = useCategoryCount(ISSUE_TYPES.DESIGN);\n  const accessibilityCount = useCategoryCount(ISSUE_TYPES.ACCESSIBILITY);\n\n  const { checkpoint } = useCheckpoint(({ state: { checkpoint } }) => ({\n    checkpoint,\n  }));\n\n  const navRef = useRef();\n\n  const handleOpenPanel = useCallback(\n    (panelName) => () =>\n      setOpenPanel((currentOpenPanel) =>\n        currentOpenPanel === panelName ? null : panelName\n      ),\n    [setOpenPanel]\n  );\n  // Set Focus within the popup on open\n  useEffect(() => {\n    if (isChecklistMounted) {\n      const firstFocusableChild = navRef.current?.querySelector(\n        FOCUSABLE_SELECTORS.join(', ')\n      );\n      firstFocusableChild?.focus();\n    }\n  }, [isChecklistMounted]);\n\n  useEffect(() => {\n    if (checkpoint) {\n      setOpenPanel(PANEL_EXPANSION_BY_CHECKPOINT[checkpoint]);\n    }\n  }, [checkpoint, setOpenPanel]);\n\n  const visiblePanels = PANEL_VISIBILITY_BY_STATE[checkpoint];\n  const priorityBadgeCount = visiblePanels.includes(ISSUE_TYPES.PRIORITY)\n    ? priorityCount\n    : 0;\n  const designBadgeCount = visiblePanels.includes(ISSUE_TYPES.DESIGN)\n    ? designCount\n    : 0;\n  const accessibilityBadgeCount = visiblePanels.includes(\n    ISSUE_TYPES.ACCESSIBILITY\n  )\n    ? accessibilityCount\n    : 0;\n\n  const maxPanelHeight = getTabPanelMaxHeight(\n    [priorityBadgeCount, designBadgeCount, accessibilityBadgeCount].filter(\n      (num) => Boolean(num)\n    ).length\n  );\n\n  const { Priority, Design, Accessibility } = items;\n\n  return (\n    <DirectionAware>\n      <Wrapper role=\"region\" aria-label={CHECKLIST_TITLE}>\n        <ThroughputPopup ref={navRef} close={close} isOpen={isOpen}>\n          {Priority && (\n            <PriorityChecks\n              badgeCount={priorityBadgeCount}\n              isOpen={isOpen && openPanel === ISSUE_TYPES.PRIORITY}\n              onClick={handleOpenPanel(ISSUE_TYPES.PRIORITY)}\n              maxHeight={maxPanelHeight}\n              title={CATEGORY_LABELS[ISSUE_TYPES.PRIORITY]}\n            >\n              <Priority />\n            </PriorityChecks>\n          )}\n          {Design && (\n            <DesignChecks\n              badgeCount={designBadgeCount}\n              isOpen={isOpen && openPanel === ISSUE_TYPES.DESIGN}\n              onClick={handleOpenPanel(ISSUE_TYPES.DESIGN)}\n              maxHeight={maxPanelHeight}\n              title={CATEGORY_LABELS[ISSUE_TYPES.DESIGN]}\n            >\n              <Design />\n            </DesignChecks>\n          )}\n          {Accessibility && (\n            <AccessibilityChecks\n              badgeCount={accessibilityBadgeCount}\n              isOpen={isOpen && openPanel === ISSUE_TYPES.ACCESSIBILITY}\n              onClick={handleOpenPanel(ISSUE_TYPES.ACCESSIBILITY)}\n              maxHeight={maxPanelHeight}\n              title={CATEGORY_LABELS[ISSUE_TYPES.ACCESSIBILITY]}\n            >\n              <Accessibility />\n            </AccessibilityChecks>\n          )}\n        </ThroughputPopup>\n        <Toggle isOpen={isOpen} onClick={toggle} popupId={POPUP_ID} />\n      </Wrapper>\n    </DirectionAware>\n  );\n}\n\nChecklist.propTypes = {\n  items: PropTypes.shape({\n    Priority: PropTypes.elementType,\n    Design: PropTypes.elementType,\n    Accessibility: PropTypes.elementType,\n  }),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContent/accessibilityChecks.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { ISSUE_TYPES } from '../constants';\nimport { ChecklistCategoryProvider } from '../countContext';\nimport { PanelText, StyledTablistPanel } from '../styles';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nfunction AccessibilityPanel({\n  children,\n  badgeCount,\n  isOpen,\n  onClick,\n  maxHeight,\n  title,\n}) {\n  const isChecklistMounted = useIsChecklistMounted();\n  return isChecklistMounted ? (\n    <StyledTablistPanel\n      badgeCount={badgeCount}\n      isExpanded={Boolean(badgeCount) && isOpen}\n      onClick={onClick}\n      maxHeight={maxHeight}\n      title={title}\n    >\n      <PanelText>\n        {__('Make your Web Story accessible.', 'web-stories')}\n      </PanelText>\n      {children}\n    </StyledTablistPanel>\n  ) : (\n    children\n  );\n}\n\nAccessibilityPanel.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.node,\n    PropTypes.arrayOf(PropTypes.node),\n  ]),\n};\n\nexport function AccessibilityChecks(props) {\n  return (\n    <ChecklistCategoryProvider category={ISSUE_TYPES.ACCESSIBILITY}>\n      <AccessibilityPanel {...props}>{props.children}</AccessibilityPanel>\n    </ChecklistCategoryProvider>\n  );\n}\nAccessibilityChecks.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContent/designChecks.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { ISSUE_TYPES } from '../constants';\nimport { ChecklistCategoryProvider } from '../countContext';\nimport { PanelText, StyledTablistPanel } from '../styles';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nfunction DesignPanel({\n  badgeCount = 0,\n  isOpen,\n  maxHeight,\n  onClick,\n  title,\n  children,\n}) {\n  const isChecklistMounted = useIsChecklistMounted();\n  return isChecklistMounted ? (\n    <StyledTablistPanel\n      badgeCount={badgeCount}\n      isExpanded={Boolean(badgeCount) && isOpen}\n      onClick={onClick}\n      maxHeight={maxHeight}\n      title={title}\n    >\n      <PanelText>\n        {__('Follow best practices for Web Stories.', 'web-stories')}\n      </PanelText>\n      {children}\n    </StyledTablistPanel>\n  ) : (\n    children\n  );\n}\nDesignPanel.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.node,\n    PropTypes.arrayOf(PropTypes.node),\n  ]),\n};\n\nexport function DesignChecks(props) {\n  return (\n    <ChecklistCategoryProvider category={ISSUE_TYPES.DESIGN}>\n      <DesignPanel {...props}>{props.children}</DesignPanel>\n    </ChecklistCategoryProvider>\n  );\n}\nDesignChecks.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContent/emptyContent.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { Icons, Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useCategoryCount } from '../countContext';\nimport { ISSUE_TYPES, PPC_CHECKPOINT_STATE } from '../constants';\nimport { useCheckpoint } from '../checkpointContext';\n\nconst Wrapper = styled.div`\n  display: grid;\n  grid-template-rows: 113px 64px;\n  width: 308px;\n  margin: 0 auto 32px;\n\n  & > * {\n    display: flex;\n    align-self: center;\n    justify-self: center;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n\n  p {\n    width: 226px;\n    text-align: center;\n  }\n`;\n\nconst IconContainer = styled.div`\n  height: 50px;\n  width: 50px;\n`;\n\nexport const EmptyContent = () => {\n  return (\n    <Wrapper>\n      <IconContainer>\n        <Icons.CheckmarkCircle />\n      </IconContainer>\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'You are all set for now. Return to this checklist as you build your Web Story for tips on how to improve it.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Wrapper>\n  );\n};\n\nconst EmptyContentCheck = () => {\n  const accessibilityCount = useCategoryCount(ISSUE_TYPES.ACCESSIBILITY);\n  const designCount = useCategoryCount(ISSUE_TYPES.DESIGN);\n  const priorityCount = useCategoryCount(ISSUE_TYPES.PRIORITY);\n  const { checkpoint } = useCheckpoint(({ state: { checkpoint } }) => ({\n    checkpoint,\n  }));\n\n  const isEmptyView =\n    accessibilityCount + designCount + priorityCount === 0 ||\n    checkpoint === PPC_CHECKPOINT_STATE.UNAVAILABLE;\n\n  return isEmptyView ? <EmptyContent /> : null;\n};\n\nexport default EmptyContentCheck;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContent/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { DesignChecks } from './designChecks';\nexport { AccessibilityChecks } from './accessibilityChecks';\nexport { PriorityChecks } from './priorityChecks';\nexport { default as EmptyContentCheck, EmptyContent } from './emptyContent';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContent/priorityChecks.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { PANEL_STATES } from '../../tablist';\nimport { ISSUE_TYPES } from '../constants';\nimport { ChecklistCategoryProvider, useCategoryCount } from '../countContext';\nimport { PanelText, StyledTablistPanel } from '../styles';\nimport { useCheckpoint } from '../checkpointContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nfunction PriorityPanel({\n  children,\n  badgeCount = 0,\n  isOpen,\n  onClick,\n  maxHeight,\n  title,\n}) {\n  const isChecklistMounted = useIsChecklistMounted();\n  return isChecklistMounted ? (\n    <StyledTablistPanel\n      badgeCount={badgeCount}\n      isExpanded={Boolean(badgeCount) && isOpen}\n      onClick={onClick}\n      maxHeight={maxHeight}\n      status={PANEL_STATES.DANGER}\n      title={title}\n    >\n      <PanelText>\n        {__('Make this Web Story easier to discover.', 'web-stories')}\n      </PanelText>\n      {children}\n    </StyledTablistPanel>\n  ) : (\n    children\n  );\n}\n\nPriorityPanel.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.node,\n    PropTypes.arrayOf(PropTypes.node),\n  ]),\n};\n\nexport function PriorityChecks(props) {\n  const count = useCategoryCount(ISSUE_TYPES.PRIORITY);\n  const { updateHighPriorityCount } = useCheckpoint(\n    ({ actions: { updateHighPriorityCount } }) => ({\n      updateHighPriorityCount,\n    })\n  );\n\n  useEffect(() => {\n    updateHighPriorityCount(count);\n  }, [updateHighPriorityCount, count]);\n\n  return (\n    <ChecklistCategoryProvider category={ISSUE_TYPES.PRIORITY}>\n      <PriorityPanel {...props}>{props.children}</PriorityPanel>\n    </ChecklistCategoryProvider>\n  );\n}\n\nPriorityChecks.propTypes = {\n  badgeCount: PropTypes.number,\n  isOpen: PropTypes.bool,\n  maxHeight: PropTypes.string,\n  onClick: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContext/context.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContext/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ChecklistProvider } from './provider';\nexport { useChecklist } from './useChecklist';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContext/provider.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useState, useMemo, useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nconst ChecklistProvider = ({ children }) => {\n  const [isOpen, setIsOpen] = useState(false);\n  const [checklistFocused, setChecklistFocused] = useState(false);\n  const [openPanel, _setOpenPanel] = useState();\n  const [isChecklistMounted, setIsChecklistMounted] = useState(false);\n\n  const setOpenPanel = useCallback(\n    (newOpenPanel) => {\n      _setOpenPanel(newOpenPanel);\n    },\n    [_setOpenPanel]\n  );\n\n  const toggle = useCallback(() => {\n    trackEvent('checklist_toggled', {\n      status: isOpen ? 'closed' : 'open',\n    });\n    setIsOpen((prevVal) => !prevVal);\n  }, [isOpen]);\n\n  const close = useCallback(() => {\n    trackEvent('checklist_toggled', {\n      status: 'closed',\n    });\n    setIsOpen(false);\n  }, []);\n\n  const open = useCallback(() => {\n    trackEvent('checklist_toggled', {\n      status: 'open',\n    });\n    setIsOpen(true);\n    // focus checklist even if checklist is already open\n    setChecklistFocused(true);\n  }, []);\n\n  const resetChecklistFocused = useCallback(\n    () => setChecklistFocused(false),\n    []\n  );\n\n  const contextValue = useMemo(\n    () => ({\n      state: {\n        checklistFocused,\n        isOpen,\n        isChecklistMounted,\n        openPanel,\n      },\n      actions: {\n        toggle,\n        close,\n        open,\n        resetChecklistFocused,\n        setIsChecklistMounted,\n        setOpenPanel,\n      },\n    }),\n    [\n      checklistFocused,\n      close,\n      openPanel,\n      isOpen,\n      open,\n      resetChecklistFocused,\n      toggle,\n      setOpenPanel,\n      setIsChecklistMounted,\n      isChecklistMounted,\n    ]\n  );\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n};\n\nChecklistProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\nexport default ChecklistProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContext/test/useChecklist.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { ChecklistProvider, useChecklist } from '..';\n\nfunction setup() {\n  const wrapper = ({ children }) => (\n    <ChecklistProvider>{children}</ChecklistProvider>\n  );\n\n  return renderHook(() => useChecklist(), { wrapper });\n}\n\ndescribe('useChecklist', () => {\n  it('returns isOpen as false by default', () => {\n    const { result } = setup();\n\n    expect(result.current.state.isOpen).toBeFalse();\n  });\n\n  it('updates `isOpen` to false when close fires', () => {\n    const { result } = setup();\n\n    act(() => result.current.actions.toggle());\n    expect(result.current.state.isOpen).toBeTrue();\n\n    act(() => result.current.actions.close());\n    expect(result.current.state.isOpen).toBeFalse();\n  });\n\n  it('updates the `openPanel` value when `setOpenPanel` is called', () => {\n    const { result } = setup();\n\n    act(() => result.current.actions.setOpenPanel());\n    expect(result.current.state.openPanel).toBeUndefined();\n\n    act(() => result.current.actions.setOpenPanel('design'));\n    expect(result.current.state.openPanel).toBe('design');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistContext/useChecklist.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nexport function useChecklist(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checklistIcon.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Icons } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { PPC_CHECKPOINT_STATE } from './constants';\n\nconst ChecklistIcon = ({ checkpoint, ...rest }) => {\n  if (checkpoint === PPC_CHECKPOINT_STATE.ALL) {\n    return <Icons.ExclamationOutline {...rest} />;\n  }\n  return null;\n};\nChecklistIcon.propTypes = {\n  checkpoint: PropTypes.oneOf(Object.values(PPC_CHECKPOINT_STATE)),\n};\n\nexport default ChecklistIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checkpointContext/checkpointContext.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useCallback,\n  useReducer,\n  useMemo,\n  createContext,\n  useContextSelector,\n  identity,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { STORY_EVENTS, useStory, useStoryTriggerListener } from '../../../app';\nimport { PPC_CHECKPOINT_STATE } from '../constants';\n\nexport const PPC_CHECKPOINT_ACTION = {\n  ON_INITIAL_ELEMENT_ADDED: 'story is no longer empty',\n  ON_PUBLISH_CLICKED: 'publish button is pressed',\n  ON_STORY_HAS_2_PAGES: \"story 'recommended' section enabled\",\n  ON_STORY_HAS_5_PAGES: \"story 'high priority' section enabled\",\n  ON_STORY_IS_PUBLISHED: 'story is published, regardless of recommendations',\n};\n\nconst machine = {\n  [PPC_CHECKPOINT_STATE.UNAVAILABLE]: {\n    [PPC_CHECKPOINT_ACTION.ON_INITIAL_ELEMENT_ADDED]:\n      PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED,\n    [PPC_CHECKPOINT_ACTION.ON_PUBLISH_CLICKED]: PPC_CHECKPOINT_STATE.ALL,\n    [PPC_CHECKPOINT_ACTION.ON_STORY_IS_PUBLISHED]: PPC_CHECKPOINT_STATE.ALL,\n    [PPC_CHECKPOINT_ACTION.ON_STORY_HAS_2_PAGES]:\n      PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED,\n  },\n  [PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED]: {\n    [PPC_CHECKPOINT_ACTION.ON_STORY_HAS_5_PAGES]: PPC_CHECKPOINT_STATE.ALL,\n    [PPC_CHECKPOINT_ACTION.ON_PUBLISH_CLICKED]: PPC_CHECKPOINT_STATE.ALL,\n    [PPC_CHECKPOINT_ACTION.ON_STORY_IS_PUBLISHED]: PPC_CHECKPOINT_STATE.ALL,\n  },\n  [PPC_CHECKPOINT_STATE.ALL]: {},\n};\n\nconst checkpointReducer = (state, action) => {\n  return machine[state][action] || state;\n};\n\nexport const CheckpointContext = createContext({ state: {}, actions: {} });\n\nfunction ChecklistCheckpointProvider({ children }) {\n  const [checkpointState, dispatch] = useReducer(\n    checkpointReducer,\n    PPC_CHECKPOINT_STATE.UNAVAILABLE\n  );\n\n  const [highPriorityCount, setHighPriorityCount] = useState();\n  const [reviewChecklistRequested, setReviewChecklistRequested] = useState();\n\n  const hasHighPriorityIssues = highPriorityCount > 0;\n\n  const storyStatus = useStory(({ state: { story } }) => story.status);\n\n  useEffect(() => {\n    if (storyStatus === 'publish') {\n      dispatch(PPC_CHECKPOINT_ACTION.ON_STORY_IS_PUBLISHED);\n    }\n  }, [storyStatus]);\n\n  useStoryTriggerListener(\n    STORY_EVENTS.onSecondPageAdded,\n    useCallback(() => {\n      dispatch(PPC_CHECKPOINT_ACTION.ON_STORY_HAS_2_PAGES);\n    }, [])\n  );\n\n  useStoryTriggerListener(\n    STORY_EVENTS.onFifthPageAdded,\n    useCallback(() => {\n      dispatch(PPC_CHECKPOINT_ACTION.ON_STORY_HAS_5_PAGES);\n    }, [])\n  );\n\n  useStoryTriggerListener(\n    STORY_EVENTS.onInitialElementAdded,\n    useCallback(() => {\n      dispatch(PPC_CHECKPOINT_ACTION.ON_INITIAL_ELEMENT_ADDED);\n    }, [])\n  );\n\n  const updateHighPriorityCount = useCallback((count) => {\n    setHighPriorityCount(count);\n  }, []);\n\n  const showPriorityIssues = useCallback(\n    () => dispatch(PPC_CHECKPOINT_ACTION.ON_PUBLISH_CLICKED),\n    []\n  );\n\n  const handleReviewChecklist = useCallback(() => {\n    setReviewChecklistRequested(true);\n  }, []);\n\n  const handleResetReviewChecklist = useCallback(() => {\n    setReviewChecklistRequested(false);\n  }, []);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        checkpoint: checkpointState,\n        hasHighPriorityIssues,\n        reviewChecklistRequested,\n      },\n      actions: {\n        updateHighPriorityCount,\n        handleResetReviewChecklist,\n        handleReviewChecklist,\n        showPriorityIssues,\n      },\n    }),\n    [\n      checkpointState,\n      handleReviewChecklist,\n      showPriorityIssues,\n      handleResetReviewChecklist,\n      reviewChecklistRequested,\n      hasHighPriorityIssues,\n      updateHighPriorityCount,\n    ]\n  );\n\n  return (\n    <CheckpointContext.Provider value={value}>\n      {children}\n    </CheckpointContext.Provider>\n  );\n}\nChecklistCheckpointProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport function useCheckpoint(selector) {\n  return useContextSelector(CheckpointContext, selector ?? identity);\n}\n\nexport { ChecklistCheckpointProvider };\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checkpointContext/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport {\n  ChecklistCheckpointProvider,\n  useCheckpoint,\n  CheckpointContext,\n} from './checkpointContext';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/elementLinkTappableRegionTooBig.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useLayout, useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nconst MAX_LINK_SCREEN_PERCENT = 80;\n\nexport function isElementLinkTappableRegionTooBig(element, pageSize) {\n  if (\n    !['text', 'image', 'shape', 'gif', 'video'].includes(element.type) ||\n    !element.link?.url?.length\n  ) {\n    return false;\n  }\n\n  const elementArea = element.width * element.height;\n  const canvasArea = pageSize.width * pageSize.height;\n  return (elementArea / canvasArea) * 100 > MAX_LINK_SCREEN_PERCENT;\n}\n\nconst ElementLinkTappableRegionTooBig = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n\n  const elements = useMemo(\n    () =>\n      pageSize.height > 0 &&\n      filterStoryElements(pages, (element) =>\n        isElementLinkTappableRegionTooBig(element, pageSize)\n      ),\n    [pages, pageSize]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        elementId,\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('ElementLinkTappableRegionTooBig', isRendered);\n\n  const { title, footer } = ACCESSIBILITY_COPY.linkTappableRegionTooBig;\n\n  const thumbnails = (elements || []).map((element) => (\n    <Thumbnail\n      key={element.id}\n      onClick={() => handleClick(element.id, element.pageId)}\n      type={THUMBNAIL_TYPES.TEXT}\n      displayBackground={<LayerThumbnail page={element} />}\n      aria-label={__('Go to offending link', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          elements.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default ElementLinkTappableRegionTooBig;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/elementLinkTappableRegionTooSmall.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nconst LINK_TAPPABLE_REGION_MIN_WIDTH = 48;\nconst LINK_TAPPABLE_REGION_MIN_HEIGHT = 48;\n\nexport function elementLinkTappableRegionTooSmall(element) {\n  if (\n    !['text', 'image', 'shape', 'gif', 'video'].includes(element.type) ||\n    !element.link?.url?.length\n  ) {\n    return false;\n  }\n\n  return (\n    element.width < LINK_TAPPABLE_REGION_MIN_WIDTH ||\n    element.height < LINK_TAPPABLE_REGION_MIN_HEIGHT\n  );\n}\n\nconst ElementLinkTappableRegionTooSmall = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, elementLinkTappableRegionTooSmall),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        elementId,\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const thumbnails = elements.map((element) => (\n    <Thumbnail\n      key={element.id}\n      onClick={() => handleClick(element.id, element.pageId)}\n      type={THUMBNAIL_TYPES.TEXT}\n      displayBackground={<LayerThumbnail page={element} />}\n      aria-label={__('Go to offending link', 'web-stories')}\n    />\n  ));\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('ElementLinkTappableRegionTooSmall', isRendered);\n\n  const { title, footer } = ACCESSIBILITY_COPY.linkTappableRegionTooSmall;\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          elements.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default ElementLinkTappableRegionTooSmall;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/firstPageAnimation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { Link, TextSize } from '@googleforcreators/design-system';\nimport { trackClick } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport {\n  ChecklistCard,\n  DefaultFooterText,\n  DefaultCtaButton,\n} from '../../checklistCard';\nimport { DESIGN_COPY } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function firstPageAnimation(animations) {\n  return Boolean(animations?.length);\n}\n\nconst FirstPageAnimation = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n\n  const { updatePageProperties, pageId, pageAnimations } = useStory(\n    ({ actions: { updatePageProperties }, state: { pages } }) => {\n      const page = pages?.at(0);\n      return {\n        updatePageProperties,\n        pageId: page?.id,\n        pageAnimations: page?.animations,\n      };\n    }\n  );\n\n  const removeAnimations = useCallback(() => {\n    updatePageProperties({\n      pageId,\n      properties: { animations: [] },\n    });\n  }, [updatePageProperties, pageId]);\n\n  const isRendered = firstPageAnimation(pageAnimations);\n\n  const onClick = useCallback((evt) => {\n    trackClick(evt, 'click_checklist_cover_animations');\n  }, []);\n\n  const { title, footer } = DESIGN_COPY.firstPageAnimation;\n  useRegisterCheck('FirstPageAnimation', isRendered);\n\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      cta={\n        <DefaultCtaButton\n          aria-label={__('Remove Animations', 'web-stories')}\n          onClick={removeAnimations}\n        >\n          {__('Remove Animations', 'web-stories')}\n        </DefaultCtaButton>\n      }\n      footer={\n        <>\n          <DefaultFooterText>{footer}</DefaultFooterText>\n          <DefaultFooterText as=\"span\">\n            <Link\n              target=\"_blank\"\n              rel=\"noreferrer\"\n              onClick={onClick}\n              href=\"https://wp.stories.google/docs/how-to/animations/\"\n              size={TextSize.XSmall}\n            >\n              {__('Learn more', 'web-stories')}\n            </Link>\n          </DefaultFooterText>\n        </>\n      }\n    />\n  ) : null;\n};\n\nexport default FirstPageAnimation;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/imageElementMissingAlt.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function imageElementMissingAlt(element) {\n  return (\n    ['gif', 'image'].includes(element.type) &&\n    !element.alt?.length &&\n    !element.resource?.alt?.length\n  );\n}\n\nconst ImageElementMissingAlt = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, imageElementMissingAlt),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        pageId,\n        elementId,\n        highlight: states.AssistiveText,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = ACCESSIBILITY_COPY.imagesMissingAltText;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('ImageElementMissingAlt', isRendered);\n\n  const thumbnails = elements.map((element) => (\n    <Thumbnail\n      key={element.id}\n      onClick={() => handleClick(element.id, element.pageId)}\n      type={THUMBNAIL_TYPES.IMAGE}\n      displayBackground={<LayerThumbnail page={element} />}\n      aria-label={__('Go to offending video', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          elements.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default ImageElementMissingAlt;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/imageElementResolution.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  ChecklistCardStyles,\n} from '../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function imageElementResolution(element) {\n  if (!['image', 'gif'].includes(element.type)) {\n    return false;\n  }\n\n  const scale = (element.scale || 100) / 100;\n  const imageResolutionLow =\n    element.resource?.height < 2 * (element.height * scale) ||\n    element.resource?.width < 2 * (element.width * scale);\n\n  return imageResolutionLow;\n}\n\nconst ImageElementResolution = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const failingElements = useMemo(\n    () => filterStoryElements(pages, imageElementResolution),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        pageId,\n        elementId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.imageResolutionTooLow;\n  const isRendered = failingElements.length > 0;\n  useRegisterCheck('ImageElementResolution', isRendered);\n\n  const thumbnails = failingElements.map((element) => (\n    <Thumbnail\n      key={element.id}\n      onClick={() => handleClick(element.id, element.pageId)}\n      type={THUMBNAIL_TYPES.IMAGE}\n      displayBackground={<LayerThumbnail page={element} />}\n      aria-label={__('Go to offending image', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          failingElements.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={\n          <ChecklistCardStyles.CardListWrapper>\n            <List size={TextSize.XSmall}>{footer}</List>\n          </ChecklistCardStyles.CardListWrapper>\n        }\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default ImageElementResolution;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ElementLinkTappableRegionTooBig } from './elementLinkTappableRegionTooBig';\nexport { default as ElementLinkTappableRegionTooSmall } from './elementLinkTappableRegionTooSmall';\nexport { default as FirstPageAnimation } from './firstPageAnimation';\nexport { default as ImageElementMissingAlt } from './imageElementMissingAlt';\nexport { default as ImageElementResolution } from './imageElementResolution';\nexport {\n  PageBackgroundTextLowContrast,\n  getPagesWithFailedContrast,\n} from './pageBackgroundLowTextContrast';\nexport { default as PageTooLittleText } from './pageTooLittleText';\nexport { default as PageTooManyLinks } from './pageTooManyLinks';\nexport { default as PageTooMuchText } from './pageTooMuchText';\nexport { default as PublisherLogoMissing } from './publisherLogoMissing';\nexport { default as PublisherLogoSize } from './publisherLogoSize';\nexport { default as StoryAmpValidationErrors } from './storyAmpValidationErrors';\nexport { default as StoryMissingExcerpt } from './storyMissingExcerpt';\nexport { default as StoryMissingTitle } from './storyMissingTitle';\nexport { default as StoryPagesCount } from './storyPagesCount';\nexport { StoryPosterAttached } from './storyPosterAttached';\nexport { default as StoryPosterSize } from './storyPosterSize';\nexport { default as StoryTitleLength } from './storyTitleLength';\nexport { default as TextElementFontSizeTooSmall } from './textElementFontSizeTooSmall';\nexport { default as VideoElementLength } from './videoElementLength';\nexport { default as VideoElementMissingCaptions } from './videoElementMissingCaptions';\nexport { default as VideoElementMissingDescription } from './videoElementMissingDescription';\nexport { default as VideoElementMissingPoster } from './videoElementMissingPoster';\nexport { default as VideoElementResolution } from './videoElementResolution';\nexport { default as VideoOptimization } from './videoOptimization';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageBackgroundLowTextContrast/check.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  PAGE_RATIO,\n  FULLBLEED_RATIO,\n  getBox,\n  getBoundRect,\n} from '@googleforcreators/units';\nimport {\n  getMediaSizePositionProps,\n  preloadImage,\n} from '@googleforcreators/media';\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { getTextColors } from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport {\n  calculateLuminanceFromRGB,\n  calculateLuminanceFromStyleColor,\n  checkContrastFromLuminances,\n} from '../../../../utils/contrastUtils';\nimport getMediaBaseColor from '../../../../utils/getMediaBaseColor';\nimport { noop } from '../../../../utils/noop';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n * @typedef {import('@googleforcreators/elements').Element} Element\n * @typedef RGB The shape of color objects used for calculating color use against accessibility standards\n * @property {number} r red value\n * @property {number} g green value\n * @property {number} b blue value\n */\n\n/**\n *\n * @param {Element} a An element with a position and size\n * @param {Element} b An element with a position and size\n * @return {number} The total area of the elements' overlapping rectangles\n */\nfunction getOverlappingArea(a, b) {\n  const dx = Math.min(a.endX, b.endX) - Math.max(a.startX, b.startX);\n  const dy = Math.min(a.endY, b.endY) - Math.max(a.startY, b.startY);\n  if (dx >= 0 && dy >= 0) {\n    return dx * dy;\n  }\n  return 0;\n}\n\nconst OVERLAP_RATIO = 1 / 3;\n/**\n *\n * @param {number} overlapArea The amount of area that the text element overlaps with the element\n * @param {number} textBoxArea The amount of area of the text element\n * @return {boolean} True if the amount of overlap is visually significant\n */\nfunction isOverlapSignificant(overlapArea, textBoxArea) {\n  return overlapArea >= OVERLAP_RATIO * textBoxArea;\n}\n\n/**\n * Returns the provided background elements filtered for elements which overlap significantly\n * with the text element and are not occluded by the other elements\n *\n * @param {Element} textElement The text element which is in front of the potential background elements\n * @param {Element[]} potentialBackgroundElements All the elements behind the text element\n * @param {Page} page The page with all the elements\n * @return {Element[]} The visually significant background elements\n */\nfunction getBackgroundsForElement(\n  textElement,\n  potentialBackgroundElements,\n  page\n) {\n  const { pageSize } = page;\n  const textPos = getBox(textElement, pageSize?.width, pageSize?.height);\n  const textBox = getBoundRect([textPos]);\n  const textBoxArea = textBox.width * textBox.height;\n\n  const elementOverlaps = [...potentialBackgroundElements]\n    .map((element, index) => {\n      const bgPos = getBox(element, pageSize?.width, pageSize?.height);\n      const bgBox = getBoundRect([bgPos]);\n      const overlappingArea = getOverlappingArea(textBox, bgBox);\n      return {\n        element:\n          // if the element is the background element use the page's background color\n          // image backgrounds will ignore this property\n          element.isBackground || element.isDefaultBackground\n            ? { ...element, backgroundColor: page?.backgroundColor }\n            : element,\n        area: overlappingArea,\n        index,\n      };\n    })\n    // elements are ordered from lowest to highest\n    // so the first elements in the reversed array are occluding the text box area behind it;\n    .reverse();\n\n  let unoccludedArea = textBoxArea;\n  const significantElements = [];\n  for (const overlap of elementOverlaps) {\n    if (!isOverlapSignificant(unoccludedArea, textBoxArea)) {\n      break;\n    }\n    if (isOverlapSignificant(overlap.area, textBoxArea)) {\n      significantElements.push(overlap.element);\n    }\n    unoccludedArea -= overlap.area;\n  }\n  return significantElements;\n}\n\n/**\n * @param {Object} arguments The arguments\n * @param {Element} arguments.background The image-type background element\n * @param {Element} arguments.text The text-type element\n * @param {Page} arguments.page The page with both elements\n * @return {Promise<RGB>} Resolves to the dominant color of the section of the image behind the text element\n */\nfunction getTextImageBackgroundColor({ background, text, page }) {\n  const { pageSize } = page;\n  const safeZoneDiff =\n    (pageSize?.width / FULLBLEED_RATIO - pageSize?.width / PAGE_RATIO) / 2;\n\n  const textPos = getBox(text, pageSize?.width, pageSize?.height);\n  const textBox = getBoundRect([textPos]);\n\n  const { resource, scale, focalX, focalY } = background;\n  const bgBox = getBox(background, pageSize?.width, pageSize?.height);\n  const { width, height } = bgBox;\n\n  const bgMediaBox = getMediaSizePositionProps(\n    resource,\n    width,\n    height,\n    scale,\n    focalX,\n    focalY\n  );\n\n  const bgImage = {\n    offsetX: bgMediaBox.offsetX,\n    offsetY: bgMediaBox.offsetY,\n    src: background.resource.src,\n    width: bgMediaBox.width,\n    height: bgMediaBox.height,\n    rotationAngle: background.isBackground\n      ? undefined\n      : background.rotationAngle,\n    flip: background.flip,\n  };\n\n  const overlapBox = {\n    x: background.isBackground\n      ? bgMediaBox.offsetX + Math.abs(textBox.startX)\n      : bgMediaBox.offsetX + Math.abs(textBox.startX) - bgBox.x,\n    y: background.isBackground\n      ? bgMediaBox.offsetY + Math.abs(textBox.startY + safeZoneDiff)\n      : bgMediaBox.offsetY +\n        Math.abs(textBox.startY + safeZoneDiff) -\n        (bgBox.y + safeZoneDiff),\n    width: textBox.width,\n    height: textBox.height,\n  };\n\n  return getOverlapBgColor({\n    bgImage,\n    bgBox,\n    overlapBox,\n  }).catch(() => {\n    // ignore errors\n  });\n}\n\nconst TO_RADIANS = Math.PI / 180;\n\n/**\n * @param {Object} arguments The arguments\n * @param {Element} arguments.bgImage The background element\n * @param {{ width: number, height: number }} arguments.bgBox The containing box of the background image - needed for calculating canvas translations for rotated elements\n * @param {{ x: number, y: number, width: number, height: number }} arguments.overlapBox The position and size of the text element relative to the scaled and rotated background image\n * @return {Promise<Object>} Resolves to the dominant color of the background image in the overlap box area\n */\nasync function getOverlapBgColor({ bgImage, bgBox, overlapBox }) {\n  function getImageData(imageNode) {\n    return new Promise((resolve, reject) => {\n      try {\n        const canvas = document.createElement('canvas');\n\n        canvas.width = bgImage.width;\n        canvas.height = bgImage.height;\n\n        const ctx = canvas.getContext('2d');\n\n        if (bgImage.rotationAngle) {\n          const translationOffsetX = bgImage.offsetX + bgBox.width / 2;\n          const translationOffsetY = bgImage.offsetY + bgBox.height / 2;\n          ctx.translate(translationOffsetX, translationOffsetY);\n          ctx.rotate(bgImage.rotationAngle * TO_RADIANS);\n          ctx.translate(-translationOffsetX, -translationOffsetY);\n        }\n\n        let xPos = 0,\n          yPos = 0;\n\n        const { flip } = bgImage;\n        if (flip.vertical || flip.horizontal) {\n          xPos = flip.horizontal ? bgImage.width * -1 : 0;\n          yPos = flip.vertical ? bgImage.height * -1 : 0;\n          ctx.scale(flip.horizontal ? -1 : 1, flip.vertical ? -1 : 1);\n        }\n\n        ctx.drawImage(imageNode, xPos, yPos, bgImage.width, bgImage.height);\n\n        const imageData = ctx.getImageData(\n          overlapBox.x,\n          overlapBox.y,\n          overlapBox.width,\n          overlapBox.height\n        );\n\n        resolve(imageData);\n      } catch (e) {\n        reject(e);\n      }\n    });\n  }\n\n  const image = await preloadImage({\n    src: bgImage.src,\n    width: bgImage.width,\n    height: bgImage.height,\n  });\n  const imgData = await getImageData(image);\n\n  const cropCanvas = document.createElement('canvas');\n  cropCanvas.width = overlapBox.width; // size of the new image / text container\n  cropCanvas.height = overlapBox.height;\n  const cropCtx = cropCanvas.getContext('2d');\n  cropCtx.putImageData(imgData, 0, 0);\n\n  const hexColor = await getMediaBaseColor(\n    cropCanvas.toDataURL(),\n    cropCanvas.width,\n    cropCanvas.height\n  );\n\n  const {\n    color: { r, g, b },\n  } = createSolidFromString(hexColor);\n\n  return { r, g, b };\n}\n\n/**\n *\n * @param {Element} element The text element to get font colors from\n * @return {Array} the style colors from the span tags in text element content\n */\nfunction getTextStyleColors(element) {\n  return getTextColors(element.content);\n}\n\nfunction getTextShapeBackgroundColor({ background }) {\n  return background?.backgroundColor?.color;\n}\n\n/**\n * Returns guidance if the contrast between any of the text style colors and the background color is too low\n *\n * @param {Object} arguments The arguments\n * @param {RGB} arguments.backgroundColor The r, g, b object representing a background color to compare to the text colors\n * @param {Array} arguments.textStyleColors The array of style colors of the text being checked\n * @param {number} arguments.fontSize The font size (in pixels) of the text being checked\n * @return {boolean} If true, there is a contrast issue with some text\n */\nfunction textBackgroundHasLowContrast({\n  backgroundColor,\n  textStyleColors,\n  fontSize,\n} = {}) {\n  const noColorsToCompare = !textStyleColors || !backgroundColor;\n  if (noColorsToCompare) {\n    return false;\n  }\n\n  return textStyleColors.some((styleColor) => {\n    if (!styleColor) {\n      return false;\n    }\n    const textLuminance = calculateLuminanceFromStyleColor(styleColor);\n    const backgroundLuminance = calculateLuminanceFromRGB(backgroundColor);\n    const contrastCheck = checkContrastFromLuminances(\n      textLuminance,\n      backgroundLuminance,\n      fontSize\n    );\n    return !contrastCheck.WCAG_AA;\n  });\n}\n\nfunction getBackgroundColorByType(element) {\n  switch (element.type) {\n    case 'image':\n      return getTextImageBackgroundColor;\n    case 'shape':\n      return getTextShapeBackgroundColor;\n    default:\n      return noop;\n  }\n}\n/**\n * Returns all failing pages as well as the offending elements' id(s).\n *\n * @param {Array<Page>}  storyPages The story's page(s) to check for contrast failures\n * @param {Object} pageSize pageWidth and pageHeight from useLayout state\n * @return {Array<Object>} Each object contains the page that failed and the results\n * from `pageBackgroundTextLowContrast`. In `results` you will find the offending\n * elements' id(s).\n */\nexport async function getPagesWithFailedContrast(storyPages, pageSize) {\n  const promises = [];\n  (storyPages || []).forEach((page) => {\n    const maybeTextContrastResult = pageBackgroundTextLowContrast({\n      ...page,\n      pageSize,\n    });\n    if (maybeTextContrastResult instanceof Promise) {\n      promises.push(\n        maybeTextContrastResult.then((result) => ({ result, page }))\n      );\n    } else {\n      promises.push(maybeTextContrastResult);\n    }\n  });\n  const awaitedPageResult = await Promise.all(promises);\n  // if any element fails, return the page\n  return awaitedPageResult\n    .filter((results) => results.result.some(({ id }) => id))\n    .map((page) => page);\n}\n\nexport async function pageBackgroundTextLowContrast(page) {\n  // getting the background color can be async, prepare to resolve them with Promise.all\n  const backgroundColorPromises = [];\n\n  // for every element on the page, collect the text elements and check their background colors\n  page.elements.forEach((element, index) => {\n    // we don't need to check non-text elements and text that have a background mode\n    if (element.type === 'text' && element.backgroundTextMode === 'NONE') {\n      // get all the colors on the text spans\n      const textStyleColors = getTextStyleColors(element);\n      // all the elements \"behind\" the text element are potential background elements\n      const potentialBackgroundElements = page.elements.slice(0, index);\n      // get the background elements which overlap significantly with the text element\n      const textBackgrounds = getBackgroundsForElement(\n        element,\n        potentialBackgroundElements,\n        page\n      );\n\n      // loop through the background elements which overlap significantly with the text element\n      for (const backgroundElement of textBackgrounds) {\n        // elements with different types have different methods for comparing colors\n        const getBackgroundColor = getBackgroundColorByType(backgroundElement)(\n          // call that method to get the promise of a background color, or the background color itself\n          {\n            background: backgroundElement,\n            text: element,\n            page,\n          }\n        );\n\n        // prepare background color promises for the textBackgroundHasLowContrast parameter\n        const prepare = (getBackgroundColorResult) => {\n          return (\n            getBackgroundColorResult && {\n              backgroundColor: getBackgroundColorResult,\n              textStyleColors,\n              fontSize: element.fontSize,\n              id: element.id,\n              isBackgroundElement: backgroundElement.isBackground,\n            }\n          );\n        };\n\n        const bgColorCompare =\n          getBackgroundColor instanceof Promise\n            ? getBackgroundColor.then(prepare)\n            : prepare(getBackgroundColor);\n\n        backgroundColorPromises.push(bgColorCompare);\n      }\n    }\n  });\n\n  // resolve promises\n  const bgColorComparisons = await Promise.all(backgroundColorPromises);\n  const results = bgColorComparisons.map((compareObj) => {\n    // add the offending elementId and isBackground to result\n    // isBackground tells us whether the actual background element is part of the contrast issue\n    return (\n      textBackgroundHasLowContrast(compareObj) && {\n        id: compareObj.id,\n        isBackground: compareObj.isBackgroundElement,\n      }\n    );\n  });\n  return results.filter(({ id }) => id);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageBackgroundLowTextContrast/component.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useLayout, useStory } from '../../../../app';\nimport { useHighlights } from '../../../../app/highlights';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../../checklistCard';\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../../thumbnail';\nimport { ThumbnailPagePreview } from '../../utils';\nimport { ACCESSIBILITY_COPY } from '../../constants';\nimport { useRegisterCheck } from '../../countContext';\nimport { useIsChecklistMounted } from '../../popupMountedContext';\nimport { getPagesWithFailedContrast } from './check';\n\nconst PageBackgroundTextLowContrast = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const [failingPages, setFailingPages] = useState([]);\n  const storyPages = useStory(({ state }) => state?.pages);\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n\n  useEffect(() => {\n    let isStale = false;\n\n    getPagesWithFailedContrast(storyPages, pageSize)\n      .then((failures) => {\n        if (isStale) {\n          return;\n        }\n        const failedPages = failures.map(({ page }) => page);\n        setFailingPages(failedPages);\n      })\n      .catch(() => {\n        // TODO: Add some error handling\n      });\n\n    return () => {\n      isStale = true;\n    };\n  }, [storyPages, pageSize]);\n\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (pageId) =>\n      setHighlights({\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = failingPages.length > 0;\n  useRegisterCheck('PageBackgroundTextLowContrast', isRendered);\n\n  const { title, footer } = ACCESSIBILITY_COPY.lowContrast;\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      cardType={\n        failingPages.length > 1\n          ? CARD_TYPE.MULTIPLE_ISSUE\n          : CARD_TYPE.SINGLE_ISSUE\n      }\n      footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n      thumbnails={failingPages.map((page) => (\n        <Thumbnail\n          key={page.id}\n          onClick={() => handleClick(page.id)}\n          type={THUMBNAIL_TYPES.PAGE}\n          displayBackground={<ThumbnailPagePreview page={page} />}\n          aria-label={__('Go to offending page', 'web-stories')}\n        />\n      ))}\n    />\n  ) : null;\n};\n\nexport default PageBackgroundTextLowContrast;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageBackgroundLowTextContrast/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as PageBackgroundTextLowContrast } from './component';\nexport {\n  pageBackgroundTextLowContrast,\n  getPagesWithFailedContrast,\n} from './check';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageTooLittleText.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useMemo } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY, MIN_STORY_CHARACTER_COUNT } from '../constants';\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport {\n  ChecklistCard,\n  CARD_TYPE,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport {\n  characterCountForPage,\n  filterStoryPages,\n  ThumbnailPagePreview,\n} from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function pageTooLittleText(page) {\n  return characterCountForPage(page) < MIN_STORY_CHARACTER_COUNT;\n}\n\nconst PageTooLittleText = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const failingPages = useMemo(\n    () => filterStoryPages(pages, pageTooLittleText),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (pageId) =>\n      setHighlights({\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.tooLittlePageText;\n  const isRendered = failingPages.length > 0;\n  useRegisterCheck('PageTooLittleText', isRendered);\n\n  const thumbnails = failingPages.map((page) => (\n    <Thumbnail\n      key={page.id}\n      onClick={() => handleClick(page.id)}\n      type={THUMBNAIL_TYPES.PAGE}\n      displayBackground={<ThumbnailPagePreview page={page} />}\n      aria-label={__('Go to offending page', 'web-stories')}\n    />\n  ));\n\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      cardType={\n        failingPages.length > 1\n          ? CARD_TYPE.MULTIPLE_ISSUE\n          : CARD_TYPE.SINGLE_ISSUE\n      }\n      footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n      thumbnails={thumbnails}\n    />\n  ) : null;\n};\n\nexport default PageTooLittleText;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageTooManyLinks.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY, MAX_LINKS_PER_PAGE } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryPages, ThumbnailPagePreview } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function pageTooManyLinks(page) {\n  const elementsWithLinks = page.elements.filter((element) => {\n    return Boolean(element.link?.url?.length);\n  });\n\n  return elementsWithLinks.length > MAX_LINKS_PER_PAGE;\n}\n\nconst PageTooManyLinks = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const failingPages = useMemo(\n    () => filterStoryPages(pages, pageTooManyLinks),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (pageId) =>\n      setHighlights({\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.tooManyLinksOnPage;\n\n  const isRendered = failingPages.length > 0;\n  useRegisterCheck('PageTooManyLinks', isRendered);\n\n  const thumbnails = failingPages.map((page) => (\n    <Thumbnail\n      key={page.id}\n      onClick={() => handleClick(page.id)}\n      type={THUMBNAIL_TYPES.PAGE}\n      displayBackground={<ThumbnailPagePreview page={page} />}\n      aria-label={__('Go to offending page', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          failingPages.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default PageTooManyLinks;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/pageTooMuchText.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { List, TextSize } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY, MAX_PAGE_CHARACTER_COUNT } from '../constants';\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport {\n  ChecklistCard,\n  CARD_TYPE,\n  ChecklistCardStyles,\n} from '../../checklistCard';\nimport {\n  characterCountForPage,\n  filterStoryPages,\n  ThumbnailPagePreview,\n} from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\n/**\n * Check page for too much text\n *\n * @param {Page} page The page being checked for guidelines\n * @return {boolean} returns true if page has more text than MAX_PAGE_CHARACTER_COUNT\n */\nexport function pageTooMuchText(page) {\n  return characterCountForPage(page) > MAX_PAGE_CHARACTER_COUNT;\n}\n\nconst PageTooMuchText = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const failingPages = useMemo(\n    () => filterStoryPages(pages, pageTooMuchText),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    ({ pageId, elements }) =>\n      setHighlights({\n        pageId,\n        elements,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.tooMuchPageText;\n\n  const isRendered = failingPages.length > 0;\n  useRegisterCheck('PageTooMuchText', isRendered);\n\n  const thumbnails = failingPages.map((page) => (\n    <Thumbnail\n      key={page.id}\n      onClick={() =>\n        handleClick({\n          pageId: page.id,\n          elements: page.elements.filter(({ type }) => type === 'text'),\n        })\n      }\n      type={THUMBNAIL_TYPES.PAGE}\n      displayBackground={<ThumbnailPagePreview page={page} />}\n      aria-label={__('Go to offending page', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          failingPages.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={\n          <ChecklistCardStyles.CardListWrapper>\n            <List size={TextSize.XSmall}>{footer}</List>\n          </ChecklistCardStyles.CardListWrapper>\n        }\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default PageTooMuchText;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/publisherLogoMissing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ChecklistCard, ChecklistCardStyles } from '../../checklistCard';\nimport { PRIORITY_COPY } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function publisherLogoMissing(publisherLogo) {\n  return !publisherLogo?.id;\n}\n\nconst PublisherLogoMissing = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const publisherLogo = useStory(({ state }) => state?.story?.publisherLogo);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.PublisherLogo,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = publisherLogoMissing(publisherLogo);\n  useRegisterCheck('PublisherLogoMissing', isRendered);\n\n  const { footer, title } = PRIORITY_COPY.noPublisherLogo;\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        titleProps={{\n          onClick: handleClick,\n        }}\n        footer={\n          <ChecklistCardStyles.CardListWrapper>\n            <List size={TextSize.XSmall}>{footer}</List>\n          </ChecklistCardStyles.CardListWrapper>\n        }\n      />\n    )\n  );\n};\n\nexport default PublisherLogoMissing;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/publisherLogoSize.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ChecklistCard, ChecklistCardStyles } from '../../checklistCard';\nimport { PRIORITY_COPY, PUBLISHER_LOGO_DIMENSION } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function publisherLogoSize(publisherLogo) {\n  return (\n    Boolean(publisherLogo?.id) &&\n    (publisherLogo?.height < PUBLISHER_LOGO_DIMENSION ||\n      publisherLogo?.width < PUBLISHER_LOGO_DIMENSION)\n  );\n}\n\nconst PublisherLogoSize = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const publisherLogo = useStory(({ state }) => state?.story?.publisherLogo);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.PublisherLogo,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = publisherLogoSize(publisherLogo);\n  useRegisterCheck('PublisherLogoSize', isRendered);\n\n  const { footer, title } = PRIORITY_COPY.logoTooSmall;\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        titleProps={{\n          onClick: handleClick,\n        }}\n        footer={\n          <ChecklistCardStyles.CardListWrapper>\n            <List size={TextSize.XSmall}>{footer}</List>\n          </ChecklistCardStyles.CardListWrapper>\n        }\n      />\n    )\n  );\n};\n\nexport default PublisherLogoSize;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/shared/test/thumbnailWrapper.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { theme as dsTheme } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport ThumbnailWrapper from '../thumbnailWrapper';\nimport { MAX_THUMBNAILS_DISPLAYED } from '../../../../checklistCard';\n\nconst Wrapper = ({ children }) => (\n  <ThemeProvider theme={dsTheme}>{children}</ThemeProvider>\n);\n\ndescribe('ThumbnailWrapper', () => {\n  it('should not show the `expand` when there are zero children', () => {\n    render(<ThumbnailWrapper />, { wrapper: Wrapper });\n\n    expect(screen.queryByRole('button')).not.toBeInTheDocument();\n  });\n\n  it('should not show the `expand` when there is one child', () => {\n    render(\n      <ThumbnailWrapper>\n        <div />\n      </ThumbnailWrapper>,\n      { wrapper: Wrapper }\n    );\n\n    expect(screen.queryByRole('button')).not.toBeInTheDocument();\n  });\n\n  it(`should not show the 'expand' button when there are less than ${MAX_THUMBNAILS_DISPLAYED} children`, () => {\n    render(\n      <ThumbnailWrapper>{[<div key={1} />, <div key={2} />]}</ThumbnailWrapper>,\n      { wrapper: Wrapper }\n    );\n\n    expect(screen.queryByRole('button')).not.toBeInTheDocument();\n  });\n\n  it(`should not show the 'expand' button when there are less than ${\n    MAX_THUMBNAILS_DISPLAYED + 2\n  } children`, () => {\n    const children = [...Array(MAX_THUMBNAILS_DISPLAYED + 2).keys()].map(\n      (_, index) => <div key={index} /> // eslint-disable-line react/no-array-index-key\n    );\n\n    render(<ThumbnailWrapper>{children}</ThumbnailWrapper>, {\n      wrapper: Wrapper,\n    });\n\n    expect(screen.getByRole('button')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/shared/thumbnailWrapper.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Disclosure,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { getVisibleThumbnails } from '../../utils';\nimport { StyledOverflowThumbnail } from '../../../checklistCard/styles';\nimport { MAX_THUMBNAILS_DISPLAYED } from '../../../checklistCard/constants';\n\nconst Wrapper = styled.div`\n  grid-area: thumbnail;\n  transition: height ease-in-out 300ms;\n\n  ${({ $isMultiple }) =>\n    $isMultiple &&\n    css`\n      display: grid;\n      grid-gap: 8px;\n      grid-template-columns: repeat(4, 52px);\n      grid-template-rows: auto;\n    `}\n`;\n\nconst StyledButton = styled(Button).attrs({\n  variant: ButtonVariant.Rectangle,\n  size: ButtonSize.Small,\n  type: ButtonType.Tertiary,\n})`\n  grid-column: span 4;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  height: 32px;\n  width: 100%;\n  margin: 4px 0;\n  padding: 0 64px;\n\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.tertiary\n    )};\n`;\n\nconst disclosureStyle = css`\n  margin-right: 0;\n`;\n\nconst ToggleButton = ({ children, isExpanded, ...props }) => (\n  <StyledButton aria-pressed={isExpanded} {...props}>\n    {children || isExpanded\n      ? __('Collapse', 'web-stories')\n      : __('Expand', 'web-stories')}\n    <Disclosure css={disclosureStyle} duration=\"100ms\" $isOpen={isExpanded} />\n  </StyledButton>\n);\nToggleButton.propTypes = {\n  children: PropTypes.node,\n  isExpanded: PropTypes.bool,\n};\n\nconst ThumbnailWrapper = ({ children, ...props }) => {\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  const thumbnailCount = Array.isArray(children) ? children.length : 1;\n\n  // Find out if there is overflow of thumbnails.\n  // When there is overflow we are subtracting 1 thumbnail from the available grid space.\n  const hasOverflowThumbnail =\n    thumbnailCount > 0 && thumbnailCount > MAX_THUMBNAILS_DISPLAYED + 1;\n\n  const visibleThumbnails =\n    isExpanded || thumbnailCount <= 1\n      ? children\n      : getVisibleThumbnails(children);\n\n  const handleExpand = () => setIsExpanded((current) => !current);\n\n  return (\n    <Wrapper $isMultiple={thumbnailCount > 1} {...props}>\n      {visibleThumbnails}\n      {hasOverflowThumbnail && (\n        <>\n          {!isExpanded && (\n            <StyledOverflowThumbnail\n              overflowCount={thumbnailCount - MAX_THUMBNAILS_DISPLAYED}\n              onClick={handleExpand}\n            />\n          )}\n          <ToggleButton isExpanded={isExpanded} onClick={handleExpand} />\n        </>\n      )}\n    </Wrapper>\n  );\n};\nThumbnailWrapper.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.node,\n    PropTypes.arrayOf(PropTypes.node),\n  ]),\n  overflowLabel: PropTypes.string,\n  showOverflowThumbnail: PropTypes.bool,\n};\n\nexport default ThumbnailWrapper;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/shared/videoChecklistCard.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport * as PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../../thumbnail';\n\nfunction VideoChecklistCard({ elements, footer, onThumbnailClick, ...props }) {\n  return (\n    <ChecklistCard\n      {...props}\n      cardType={\n        elements.length > 1 ? CARD_TYPE.MULTIPLE_ISSUE : CARD_TYPE.SINGLE_ISSUE\n      }\n      footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n      thumbnails={elements.map((element) => (\n        <Thumbnail\n          key={element.id}\n          onClick={() => onThumbnailClick(element.id, element.pageId)}\n          type={THUMBNAIL_TYPES.VIDEO}\n          displayBackground={<LayerThumbnail page={element} />}\n          aria-label={__('Go to offending video', 'web-stories')}\n        />\n      ))}\n    />\n  );\n}\n\nVideoChecklistCard.propTypes = {\n  title: PropTypes.string.isRequired,\n  elements: PropTypes.arrayOf(PropTypes.object).isRequired,\n  footer: PropTypes.string.isRequired,\n  onThumbnailClick: PropTypes.func.isRequired,\n};\n\nexport default VideoChecklistCard;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyAmpValidationErrors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useEffect, useRef, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { ChecklistCard, DefaultFooterText } from '../../checklistCard';\nimport { PRIORITY_COPY } from '../constants';\nimport { useRegisterCheck } from '../countContext';\n\n/** @typedef {import('amphtml-validator').ValidationResult} ValidationResult */\n\nexport async function getStoryAmpValidationErrors(link) {\n  try {\n    const response = await fetch(link);\n    const storyMarkup = await response.text();\n\n    await window.amp.validator.init();\n\n    /**\n     * @type {ValidationResult}\n     */\n    const validationResult = window.amp.validator.validateString(storyMarkup);\n    const { status: markupStatus, errors } = validationResult;\n\n    if ('FAIL' !== markupStatus) {\n      return false;\n    }\n    // Error codes can be found here: // https://github.com/ampproject/amphtml/blob/cfb102aafc1543788b77f3ef9bd138c753e13097/validator/validator.proto#L853\n    const filteredErrors = errors\n      .filter(({ severity }) => severity === 'ERROR')\n      .filter(({ code, params }) => {\n        // Filter out errors that are covered in other checks\n        // Already covered by metadata checks.\n\n        // Missing story poster\n        if ('MISSING_URL' === code && params?.[0].startsWith('poster')) {\n          return false;\n        }\n\n        // Missing publisher logo\n        if (\n          'MISSING_URL' === code &&\n          params?.[0].startsWith('publisher-logo')\n        ) {\n          return false;\n        }\n\n        // Missing video posters\n        if ('INVALID_URL_PROTOCOL' === code && params?.[0].startsWith('src')) {\n          return false;\n        }\n\n        return true;\n      });\n    return filteredErrors.length > 0;\n  } catch {\n    return false;\n  }\n}\n\nconst StoryAmpValidationErrors = () => {\n  // ampValidationErrorRef is making sure that tracking is only fired once per session.\n  const ampValidationErrorsRef = useRef();\n  const { isSaving, link, isPublic } = useStory(({ state }) => ({\n    isSaving: state.meta.isSaving,\n    link: state.story.link,\n    isPublic:\n      ['publish', 'future'].includes(state.story.status) &&\n      state.story.link &&\n      !state.story.password?.length,\n  }));\n\n  // isRendered is getting set asynchronously based on the returned value of `getStoryAmpValidationErrors`,\n  // setting this statefully allows the value to be a boolean not a promise which is crucial to updating tracking accurately.\n  const [isRendered, setIsRendered] = useState(false);\n\n  // using `isSaving` as an indicator of when to check for validation errors so that this check doesn't run on all story updates.\n  // Allows us to just track status and link, puts the story in line with what the outcome would be if the user was testing their\n  // story link in the recommended test/amp site.\n  useEffect(() => {\n    let isMounted = true;\n    if (!isSaving) {\n      if (!isPublic) {\n        return () => {\n          isMounted = false;\n        };\n      }\n\n      getStoryAmpValidationErrors(link).then((hasErrors) => {\n        if (isMounted) {\n          setIsRendered(hasErrors);\n          if (hasErrors && !ampValidationErrorsRef?.current) {\n            ampValidationErrorsRef.current = true;\n          }\n        }\n      });\n    }\n    return () => {\n      isMounted = false;\n    };\n  }, [link, isPublic, isSaving]);\n\n  useEffect(() => {\n    if (isRendered && ampValidationErrorsRef?.current) {\n      trackEvent('amp_validation_errors_found');\n    }\n  }, [isRendered]);\n\n  useRegisterCheck('StoryHasAmpErrors', isRendered);\n  const { footer, title } = PRIORITY_COPY.ampValidation;\n\n  return (\n    isRendered && (\n      <ChecklistCard\n        title={title}\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n      />\n    )\n  );\n};\n\nexport default StoryAmpValidationErrors;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyMissingExcerpt.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { states, useHighlights } from '../../../app/highlights';\nimport { useStory } from '../../../app';\nimport { ChecklistCard, DefaultFooterText } from '../../checklistCard';\nimport { PRIORITY_COPY } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyMissingExcerpt(excerpt) {\n  return !excerpt?.length;\n}\n\nconst StoryMissingExcerpt = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const excerpt = useStory(({ state }) => state?.story?.excerpt);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.Excerpt,\n      }),\n    [setHighlights]\n  );\n\n  const { title, footer } = PRIORITY_COPY.storyMissingDescription;\n\n  const isRendered = storyMissingExcerpt(excerpt);\n  useRegisterCheck('StoryMissingExcerpt', isRendered);\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      titleProps={{\n        onClick: handleClick,\n      }}\n      footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n    />\n  ) : null;\n};\n\nexport default StoryMissingExcerpt;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyMissingTitle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ChecklistCard, ChecklistCardStyles } from '../../checklistCard';\nimport { PRIORITY_COPY } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyMissingTitle(title) {\n  return typeof title !== 'string' || title?.trim() === '';\n}\n\nconst StoryMissingTitle = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const storyTitle = useStory(({ state }) => state?.story?.title);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.StoryTitle,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = storyMissingTitle(storyTitle);\n  useRegisterCheck('StoryMissingTitle', isRendered);\n\n  const { footer, title } = PRIORITY_COPY.storyMissingTitle;\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      titleProps={{\n        onClick: handleClick,\n      }}\n      footer={\n        <ChecklistCardStyles.CardListWrapper>\n          <List size={TextSize.XSmall}>{footer}</List>\n        </ChecklistCardStyles.CardListWrapper>\n      }\n    />\n  ) : null;\n};\n\nexport default StoryMissingTitle;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyPagesCount.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\n\nimport { ChecklistCard, DefaultFooterText } from '../../checklistCard';\nimport { useRegisterCheck } from '../countContext';\nimport { DESIGN_COPY, MAX_STORY_PAGES, MIN_STORY_PAGES } from '../constants';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyPagesCount(numPages) {\n  const hasTooFewPages = numPages < MIN_STORY_PAGES;\n  const hasTooManyPages = numPages > MAX_STORY_PAGES;\n\n  return { hasTooFewPages, hasTooManyPages };\n}\n\nconst StoryPagesCount = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const numPages = useStory(({ state }) => state?.pages?.length);\n\n  const { hasTooFewPages, hasTooManyPages } = useMemo(\n    () => storyPagesCount(numPages),\n    [numPages]\n  );\n\n  const { storyTooShort, storyTooLong } = DESIGN_COPY;\n  const copySource =\n    (hasTooFewPages && storyTooShort) ||\n    (hasTooManyPages && storyTooLong) ||\n    {};\n\n  const isRendered = hasTooFewPages || hasTooManyPages;\n  useRegisterCheck('StoryPagesCount', isRendered);\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={copySource.title}\n        footer={<DefaultFooterText>{copySource.title}</DefaultFooterText>}\n      />\n    )\n  );\n};\n\nexport default StoryPagesCount;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyPosterAttached.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { states, useHighlights } from '../../../app/highlights';\nimport { useStory } from '../../../app';\nimport { ChecklistCard, ChecklistCardStyles } from '../../checklistCard';\nimport { PRIORITY_COPY } from '../constants';\nimport { hasNoFeaturedMedia } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyHasNoPosterAttached(featuredMedia) {\n  return (\n    typeof featuredMedia?.url !== 'string' ||\n    hasNoFeaturedMedia({ featuredMedia })\n  );\n}\n\nexport function StoryPosterAttached() {\n  const isChecklistMounted = useIsChecklistMounted();\n  const featuredMedia = useStory(({ state }) => state?.story?.featuredMedia);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.Poster,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = useMemo(\n    () => storyHasNoPosterAttached(featuredMedia),\n    [featuredMedia]\n  );\n  useRegisterCheck('StoryPosterAttached', isRendered);\n\n  const { title, footer } = PRIORITY_COPY.storyMissingPoster;\n  return isRendered && isChecklistMounted ? (\n    <ChecklistCard\n      title={title}\n      titleProps={{\n        onClick: handleClick,\n      }}\n      footer={\n        <ChecklistCardStyles.CardListWrapper>\n          <List size={TextSize.XSmall}>{footer}</List>\n        </ChecklistCardStyles.CardListWrapper>\n      }\n    />\n  ) : null;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyPosterSize.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { List, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport {\n  PRIORITY_COPY,\n  ASPECT_RATIO_LEFT,\n  ASPECT_RATIO_RIGHT,\n  FEATURED_MEDIA_RESOURCE_MIN_HEIGHT,\n  FEATURED_MEDIA_RESOURCE_MIN_WIDTH,\n} from '../constants';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ChecklistCard, ChecklistCardStyles } from '../../checklistCard';\nimport { hasNoFeaturedMedia } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyPosterSize(featuredMedia) {\n  if (hasNoFeaturedMedia({ featuredMedia })) {\n    return false;\n  }\n  if (\n    featuredMedia?.height < FEATURED_MEDIA_RESOURCE_MIN_HEIGHT ||\n    featuredMedia?.width < FEATURED_MEDIA_RESOURCE_MIN_WIDTH\n  ) {\n    return true;\n  }\n  const hasCorrectAspectRatio =\n    Math.abs(\n      featuredMedia.width / featuredMedia.height -\n        ASPECT_RATIO_LEFT / ASPECT_RATIO_RIGHT\n    ) <= 0.001;\n\n  return !hasCorrectAspectRatio;\n}\n\nconst StoryPosterSize = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const featuredMedia = useStory(({ state }) => state?.story?.featuredMedia);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.Poster,\n      }),\n    [setHighlights]\n  );\n  const { footer, title } = PRIORITY_COPY.storyPosterSize;\n\n  const isRendered = useMemo(\n    () => storyPosterSize(featuredMedia),\n    [featuredMedia]\n  );\n  useRegisterCheck('StoryPosterSize', isRendered);\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        titleProps={{\n          onClick: handleClick,\n        }}\n        footer={\n          <ChecklistCardStyles.CardListWrapper>\n            <List size={TextSize.XSmall}>{footer}</List>\n          </ChecklistCardStyles.CardListWrapper>\n        }\n      />\n    )\n  );\n};\n\nexport default StoryPosterSize;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/storyTitleLength.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport { useHighlights, states } from '../../../app/highlights';\nimport { ChecklistCard, DefaultFooterText } from '../../checklistCard';\nimport { PRIORITY_COPY, MAX_STORY_TITLE_LENGTH_CHARS } from '../constants';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function storyTitleLength(title) {\n  return title?.length > MAX_STORY_TITLE_LENGTH_CHARS;\n}\n\nconst StoryTitleLength = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const storyTitle = useStory(({ state }) => state?.story?.title);\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    () =>\n      setHighlights({\n        highlight: states.StoryTitle,\n      }),\n    [setHighlights]\n  );\n\n  const isRendered = storyTitleLength(storyTitle);\n  useRegisterCheck('StoryTitleLength', isRendered);\n\n  const { title, footer } = PRIORITY_COPY.storyTitleTooLong;\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        titleProps={{\n          onClick: handleClick,\n        }}\n      />\n    )\n  );\n};\n\nexport default StoryTitleLength;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/elementLinkTappableRegionTooBig.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { isElementLinkTappableRegionTooBig } from '../elementLinkTappableRegionTooBig';\n\ndescribe('isElementLinkTappableRegionTooBig', () => {\n  it('should return true if element tappable region is too big', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 300,\n      height: 500,\n    };\n    const pageSize = {\n      width: 336,\n      height: 504,\n    };\n    expect(isElementLinkTappableRegionTooBig(element, pageSize)).toBeTrue();\n  });\n\n  it('should return false if element has large enough tappable region', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 150,\n      height: 100,\n    };\n    const pageSize = {\n      width: 336,\n      height: 504,\n    };\n    expect(isElementLinkTappableRegionTooBig(element, pageSize)).toBeFalse();\n  });\n\n  it('should return false if not an element with link', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      content: 'G',\n      width: 40,\n      height: 40,\n    };\n    const pageSize = {\n      width: 336,\n      height: 504,\n    };\n    expect(isElementLinkTappableRegionTooBig(element, pageSize)).toBeFalse();\n  });\n\n  it('should return false for an element of an unknown type', () => {\n    const element = {\n      id: 'elementid',\n      type: 'unknown',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 40,\n      height: 40,\n    };\n    const pageSize = {\n      width: 336,\n      height: 504,\n    };\n    expect(isElementLinkTappableRegionTooBig(element, pageSize)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/elementLinkTappableRegionTooSmall.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { elementLinkTappableRegionTooSmall } from '../elementLinkTappableRegionTooSmall';\n\ndescribe('elementLinkTappableRegionTooSmall', () => {\n  it('should return true if element tappable region is too small', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 40,\n      height: 40,\n    };\n    expect(elementLinkTappableRegionTooSmall(element)).toBeTrue();\n  });\n\n  it('should return false if element has large enough tappable region', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 48,\n      height: 48,\n    };\n    expect(elementLinkTappableRegionTooSmall(element)).toBeFalse();\n  });\n\n  it('should return false if not an element with link', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      content: 'G',\n      width: 40,\n      height: 40,\n    };\n    expect(elementLinkTappableRegionTooSmall(element)).toBeFalse();\n  });\n\n  it('should return false for an element of an unknown type', () => {\n    const element = {\n      id: 'elementid',\n      type: 'unknown',\n      link: {\n        url: 'https://google.com',\n      },\n      content: 'G',\n      width: 40,\n      height: 40,\n    };\n    expect(elementLinkTappableRegionTooSmall(element)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/firstPageAnimation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { firstPageAnimation } from '../firstPageAnimation';\n\ndescribe('firstPageAnimation', () => {\n  it('should return false if animations is empty', () => {\n    const animations = [];\n    const test = firstPageAnimation(animations);\n    expect(test).toBeFalse();\n  });\n\n  it('should return true if animations is not empty', () => {\n    const animations = [\n      {\n        delay: 0,\n        duration: 1600,\n        id: '530d9a8d-d5d9-45d6-807d-2dab3fe6dd1d',\n        targets: ['cea32b1d-7539-4b0c-86b8-7b731c692f7b'],\n        type: 'effect-drop',\n      },\n    ];\n    const test = firstPageAnimation(animations);\n\n    expect(test).toBeTrue();\n  });\n\n  it('should return false if animations is undefined', () => {\n    const animations = undefined;\n    const test = firstPageAnimation(animations);\n    expect(test).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/imageElementMissingAlt.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { imageElementMissingAlt } from '../imageElementMissingAlt';\n\ndescribe('imageElementMissingAlt', () => {\n  it('should return true if image element missing alt', () => {\n    const element = {\n      id: 'elementid',\n      type: 'image',\n      resource: {},\n    };\n    const test = imageElementMissingAlt(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return true if image element has empty alt', () => {\n    const element = {\n      id: 'elementid',\n      type: 'image',\n      alt: '',\n      resource: {\n        alt: '',\n      },\n    };\n    const test = imageElementMissingAlt(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return false if image element has alt', () => {\n    const element = {\n      id: 'elementid',\n      type: 'image',\n      alt: 'Image is about things',\n      resource: {},\n    };\n    expect(imageElementMissingAlt(element)).toBeFalse();\n  });\n\n  it('should return false if image element has a resource alt', () => {\n    const element = {\n      id: 'elementid',\n      type: 'image',\n      resource: { alt: 'Image is about things' },\n    };\n    expect(imageElementMissingAlt(element)).toBeFalse();\n  });\n\n  it(`should return false if it's not an image element`, () => {\n    const element = {\n      type: 'video',\n      id: 'elementid',\n      resource: { alt: '' },\n    };\n    expect(imageElementMissingAlt(element)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/imageElementResolution.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { imageElementResolution } from '../imageElementResolution';\n\ndescribe('imageElementResolution', () => {\n  it(\"should return true if an image element's resolution is too low (<2x pixel density)\", () => {\n    const tooLowResolutionImageElement = {\n      id: 910,\n      type: 'image',\n      height: 1000,\n      width: 1000,\n      resource: {\n        height: 1000,\n        width: 1000,\n      },\n    };\n\n    const result = imageElementResolution(tooLowResolutionImageElement);\n    expect(result).toBeTrue();\n  });\n\n  it(\"should return true if a gif element's resolution is too low (<2x pixel density)\", () => {\n    const tooLowResolutionImageElement = {\n      id: 911,\n      type: 'gif',\n      height: 1000,\n      width: 1000,\n      resource: {\n        height: 1000,\n        width: 1000,\n      },\n    };\n\n    const result = imageElementResolution(tooLowResolutionImageElement);\n    expect(result).toBeTrue();\n  });\n\n  it(\"should return true if an image element's resolution is too low (<2x pixel density) accounting for scale\", () => {\n    const tooLowResolutionImageElement = {\n      id: 910,\n      type: 'image',\n      height: 200,\n      width: 200,\n      scale: 400,\n      resource: {\n        height: 700,\n        width: 700,\n      },\n    };\n\n    const result = imageElementResolution(tooLowResolutionImageElement);\n    expect(result).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/pageBackgroundLowTextContrast.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PAGE_HEIGHT, PAGE_WIDTH } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { pageBackgroundTextLowContrast } from '../pageBackgroundLowTextContrast';\n\ndescribe('pageBackgroundTextLowContrast', () => {\n  const bgEl = {\n    id: 'bgEl-id',\n    x: 1,\n    y: 1,\n    type: 'shape',\n    isBackground: true,\n    height: PAGE_HEIGHT,\n    width: PAGE_WIDTH,\n    backgroundColor: {\n      color: {\n        r: 255,\n        g: 255,\n        b: 255,\n      },\n    },\n  };\n  const textEl = {\n    id: 'textEl -id',\n    type: 'text',\n    backgroundTextMode: 'NONE',\n    content: 'Fill with text',\n    x: 1,\n    y: 1,\n    width: 175,\n    height: 36,\n    fontSize: 12,\n  };\n  const page = {\n    id: 123,\n    pageSize: {\n      height: PAGE_HEIGHT,\n      width: PAGE_WIDTH,\n    },\n    elements: [bgEl, textEl],\n    backgroundColor: {\n      color: {\n        r: 2,\n        g: 12,\n        b: 1,\n      },\n    },\n  };\n\n  it('should return an array of ids if the default font (no spans, no colors added) does not have high enough contrast with the page', async () => {\n    const check = await pageBackgroundTextLowContrast(page);\n    await expect(check[0].id).toBe(textEl.id);\n  });\n  it('should return an array containing isBackground if the default font does not have high enough contrast with the background element', async () => {\n    const check = await pageBackgroundTextLowContrast(page);\n    await expect(check[0].isBackground).toBeTrue();\n  });\n  it('should return an array containing isBackground = false if the contrast issue is cause by an overlapped element', async () => {\n    const overlappedElement = {\n      ...bgEl,\n      isBackground: false,\n    };\n\n    const smallGreyTextEl = {\n      ...textEl,\n      content: '<span style=\"color:#777777\">I woke up like this</span>',\n    };\n\n    const check = await pageBackgroundTextLowContrast({\n      ...page,\n      elements: [overlappedElement, smallGreyTextEl],\n    });\n    await expect(check[0].isBackground).toBeFalse();\n  });\n  it('should return an empty array if the text size is large enough', async () => {\n    const largeGreyTextEl = {\n      ...textEl,\n      content: '<span style=\"color:#777777\">I woke up like this</span>',\n      fontSize: 84,\n    };\n    const smallGreyTextEl = {\n      ...textEl,\n      content: '<span style=\"color:#777777\">I woke up like this</span>',\n    };\n\n    const whiteBgPage = {\n      ...page,\n      backgroundColor: {\n        color: {\n          r: 255,\n          g: 255,\n          b: 255,\n        },\n      },\n    };\n    const pass = await pageBackgroundTextLowContrast({\n      ...whiteBgPage,\n      elements: [bgEl, largeGreyTextEl],\n    });\n    expect(pass).toHaveLength(0);\n    const fail = await pageBackgroundTextLowContrast({\n      ...whiteBgPage,\n      elements: [bgEl, smallGreyTextEl],\n    });\n    expect(fail[0].id).toContain(textEl.id);\n  });\n\n  it('should return an empty array if the contrast is great enough', async () => {\n    const whiteBackgroundColor = { color: { r: 255, g: 255, b: 255 } };\n    const check = await pageBackgroundTextLowContrast({\n      ...page,\n      backgroundColor: whiteBackgroundColor,\n    });\n    expect(check).toHaveLength(0);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/pageTooLittleText.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { pageTooLittleText } from '../pageTooLittleText';\n\ndescribe('pageTooLittleText', () => {\n  it('should return true if too little text', () => {\n    const page = {\n      id: 'd886c844-5b5c-4b27-a9c3-332df2aeaaaa',\n      elements: [\n        {\n          id: '25b6f99b-3f69-4351-9e18-31b8ef1d1a61',\n          type: 'text',\n          content:\n            '<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">FRESH</span>',\n        },\n      ],\n    };\n    const test = pageTooLittleText(page);\n    expect(test).toBeTrue();\n  });\n\n  it('should return false if there is enough text', () => {\n    const page = {\n      id: 'd886c844-5b5c-4b27-a9c3-332df2aeaaaa',\n      elements: [\n        {\n          id: '25b6f99b-3f69-4351-9e18-31b8ef1d1a61',\n          type: 'text',\n          content:\n            '<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">FRESH</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">&amp;&nbsp;</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">BRIGHT</span>',\n        },\n        {\n          id: '85b6f99b-3f69-4351-9e18-31b8ef1d1a61',\n          type: 'text',\n          content:\n            '<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">\"I wish it need not have happened in my time,\" said Frodo.\\n\"So do I,\" said Gandalf\\n\"and so do all who live to see such times. But that is not for them to decide. All we have to decide is what to do with the time that is given us.</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">&amp;&nbsp;</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">The Fellowship of the Ring</span>',\n        },\n      ],\n    };\n    expect(pageTooLittleText(page)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/pageTooManyLinks.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { pageTooManyLinks } from '../pageTooManyLinks';\n\ndescribe('pageTooManyLinks', () => {\n  it('should return true if page has too many links', () => {\n    const linkElements = [\n      {\n        type: 'text',\n        link: {\n          url: 'https://google.com',\n        },\n      },\n      {\n        type: 'image',\n        link: {\n          url: 'https://google.com',\n        },\n      },\n      {\n        type: 'text',\n        link: {\n          url: 'https://google.com',\n        },\n      },\n      {\n        type: 'text',\n        link: {\n          url: 'https://google.com',\n        },\n      },\n    ];\n\n    const page = {\n      id: 'pageid',\n      elements: [\n        { type: 'text' },\n        { type: 'video' },\n        {\n          type: 'text',\n          link: {\n            url: '',\n          },\n        },\n        ...linkElements,\n      ],\n    };\n    expect(pageTooManyLinks(page)).toBeTrue();\n  });\n\n  it('should return undefined if page has a reasonable number of links', () => {\n    const page = {\n      elements: [\n        { type: 'text' },\n        { type: 'video' },\n        {\n          type: 'text',\n          link: {\n            url: 'https://google.com',\n          },\n        },\n        {\n          type: 'image',\n          link: {\n            url: 'https://google.com',\n          },\n        },\n        {\n          type: 'text',\n          link: {\n            url: '',\n          },\n        },\n        {\n          type: 'text',\n          link: {\n            url: 'https://google.com',\n          },\n        },\n      ],\n    };\n    expect(pageTooManyLinks(page)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/pageTooMuchText.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { pageTooMuchText } from '../pageTooMuchText';\n\ndescribe('pageTooMuchText', () => {\n  it('should return true if too much text', () => {\n    const testElements = [\n      {\n        id: '25b6f99b-3f69-4351-9e18-31b8ef1d1a61',\n        type: 'text',\n        content:\n          '<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">FRESH</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">&amp;&nbsp;</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">BRIGHT</span>',\n      },\n      {\n        id: 'd886c844-5b5c-4b27-a9c3-332df2aed3f3',\n        type: 'text',\n        content:\n          \"<span style=\\\"color: #28292b\\\">this is a lot of text that should</span>&nbsp;not pass the test because it's too much text. not pass the test because it's too much text. not pass the test because it's too much text. a little more.\",\n      },\n    ];\n    const page = {\n      id: 'd886c844-5b5c-4b27-a9c3-332df2aeaaaa',\n      elements: testElements,\n    };\n    expect(pageTooMuchText(page)).toBeTrue();\n  });\n\n  it('should return false if under the text limit', () => {\n    const page = {\n      id: 'd886c844-5b5c-4b27-a9c3-332df2aeaaaa',\n      elements: [\n        {\n          id: '25b6f99b-3f69-4351-9e18-31b8ef1d1a61',\n          type: 'text',\n          content:\n            '<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">FRESH</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">&amp;&nbsp;</span>\\n<span style=\"font-weight: 400; color: #fff; letter-spacing: 0.09em\">BRIGHT</span>',\n        },\n        {\n          id: 'd886c844-5b5c-4b27-a9c3-332df2aed3f3',\n          type: 'text',\n          content:\n            '<span style=\"color: #28292b\">this is not a lot of text</span>',\n        },\n      ],\n    };\n    expect(pageTooMuchText(page)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/publisherLogoMissing.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { publisherLogoMissing } from '../publisherLogoMissing';\n\ndescribe('publisherLogoMissing', () => {\n  it(\"should return true if the story's publisher logo does not exist\", () => {\n    const noPublisherLogo = {\n      height: 0,\n      id: 0,\n      url: '',\n      width: 0,\n    };\n\n    const publisherLogo = {\n      height: 100,\n      id: 1,\n      url: 'test',\n      width: 200,\n    };\n\n    expect(publisherLogoMissing(noPublisherLogo)).toBeTrue();\n    expect(publisherLogoMissing(publisherLogo)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/publisherLogoSize.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { publisherLogoSize } from '../publisherLogoSize';\n\ndescribe('publisherLogoSize', () => {\n  it(\"should return true if the story's publisher logo is too small\", () => {\n    const testNoPublisherLogo = {\n      id: 0,\n    };\n    const testHeightPublisherLogo = {\n      id: 1,\n      height: 1,\n      width: 96,\n    };\n    const testWidthPublisherLogo = {\n      id: 1,\n      width: 1,\n      height: 96,\n    };\n    const testPublisherLogo = { id: 1, height: 1, width: 1 };\n    const testHappy = publisherLogoSize({\n      id: 1,\n      height: 96,\n      width: 96,\n    });\n    const testNoLogo = publisherLogoSize(testNoPublisherLogo);\n    const testHeight = publisherLogoSize(testHeightPublisherLogo);\n    const testWidth = publisherLogoSize(testWidthPublisherLogo);\n    const test = publisherLogoSize(testPublisherLogo);\n    expect(testHappy).toBeFalse();\n    expect(testNoLogo).toBeFalse();\n    expect(testHeight).toBeTrue();\n    expect(testWidth).toBeTrue();\n    expect(test).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyAmpValidationErrors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getStoryAmpValidationErrors } from '../storyAmpValidationErrors';\n\ndescribe('getStoryAmpValidationErrors', () => {\n  const fetchSpy = jest.spyOn(window, 'fetch');\n\n  beforeAll(() => {\n    fetchSpy.mockResolvedValue({\n      text: () => ({\n        status: 200,\n      }),\n    });\n\n    delete window.amp;\n  });\n\n  afterAll(() => {\n    fetchSpy.mockClear();\n    delete window.amp;\n  });\n\n  it('should return false if no link', async () => {\n    await expect(\n      getStoryAmpValidationErrors({ link: null, status: 'draft' })\n    ).resolves.toBeFalse();\n  });\n\n  it('should return false if there are no violations', async () => {\n    window.amp = {\n      validator: {\n        validateString: () => ({\n          status: 'PASS',\n          errors: [],\n        }),\n      },\n    };\n\n    await expect(\n      getStoryAmpValidationErrors({\n        link: 'http://test/web-stories/123',\n        status: 'publish',\n      })\n    ).resolves.toBeFalse();\n  });\n\n  it('should return true if there are AMP violations', async () => {\n    window.amp = {\n      validator: {\n        init: () => {},\n        validateString: () => ({\n          status: 'FAIL',\n          errors: [\n            { code: 'INVALID_URL_PROTOCOL', severity: 'ERROR' },\n            { code: 'TAG_REQUIRED_BY_MISSING', severity: 'ERROR' },\n            {\n              code: 'MISSING_URL',\n              severity: 'ERROR',\n              params: ['poster-portrait-src'],\n            },\n          ],\n        }),\n      },\n    };\n\n    await expect(\n      getStoryAmpValidationErrors({\n        link: 'http://test/web-stories/123',\n        status: 'publish',\n      })\n    ).resolves.toBeTrue();\n  });\n\n  it('should return false if there are no ERROR severity errors', async () => {\n    window.amp = {\n      validator: {\n        validateString: () => ({\n          status: 'FAIL',\n          errors: [\n            { severity: 'WARNING' },\n            { code: 'LOREM IPSUM', severity: 'WARNING' },\n          ],\n        }),\n      },\n    };\n\n    await expect(\n      getStoryAmpValidationErrors({\n        link: 'http://test/web-stories/123',\n        status: 'publish',\n      })\n    ).resolves.toBeFalse();\n  });\n\n  it('should return false if MISSING URL is the only AMP Violation', async () => {\n    window.amp = {\n      validator: {\n        validateString: () => ({\n          status: 'FAIL',\n          errors: [\n            {\n              code: 'MISSING_URL',\n              severity: 'ERROR',\n              params: ['poster-portrait-src'],\n            },\n          ],\n        }),\n      },\n    };\n\n    await expect(\n      getStoryAmpValidationErrors({\n        link: 'http://test/web-stories/123',\n        status: 'publish',\n      })\n    ).resolves.toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyMissingExcerpt.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { storyMissingExcerpt } from '../storyMissingExcerpt';\n\ndescribe('storyMissingExcerpt', () => {\n  it('should return true if story is missing excerpt', () => {\n    const excerpt = undefined;\n    const test = storyMissingExcerpt(excerpt);\n    expect(test).toBeTrue();\n  });\n\n  it('should return true if story has empty excerpt', () => {\n    const excerpt = '';\n    const test = storyMissingExcerpt(excerpt);\n\n    expect(test).toBeTrue();\n  });\n\n  it('should return true if story has excerpt', () => {\n    const excerpt = 'This is an excerpt';\n    const test = storyMissingExcerpt(excerpt);\n    expect(test).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyMissingTitle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { storyMissingTitle } from '../storyMissingTitle';\n\ndescribe('storyMissingTitle', () => {\n  it('should return true if the story is missing its title', () => {\n    const testEmptyStringTitle = '';\n    const testUndefinedTitleStory = undefined;\n    const testUndefined = storyMissingTitle(testUndefinedTitleStory);\n    const testEmptyString = storyMissingTitle(testEmptyStringTitle);\n    const testHappy = storyMissingTitle('The Allegory of the Cave');\n    expect(testHappy).toBeFalse();\n    expect(testEmptyString).toBeTrue();\n    expect(testUndefined).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyPagesCount.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { storyPagesCount } from '../storyPagesCount';\n\ndescribe('storyPagesCount', () => {\n  it('should return true if story has less than 4 pages or more than 30 pages', () => {\n    const { hasTooFewPages } = storyPagesCount(3);\n    const { hasTooManyPages } = storyPagesCount(31);\n    const result = storyPagesCount(20);\n\n    expect(hasTooFewPages).toBeTrue();\n\n    expect(hasTooManyPages).toBeTrue();\n\n    expect(result.hasTooFewPages).toBeFalse();\n    expect(result.hasTooManyPages).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyPosterAttached.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { storyHasNoPosterAttached } from '../storyPosterAttached';\n\ndescribe('storyHasNoPosterAttached', () => {\n  it('should return true if the story is missing its poster image', () => {\n    const testStory = {\n      id: 890,\n      title: 'Work work work work work',\n      featuredMedia: undefined,\n    };\n    expect(storyHasNoPosterAttached(testStory)).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyPosterSize.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { storyPosterSize } from '../storyPosterSize';\n\ndescribe('storyPosterSize', () => {\n  it(\"should return true if the story's poster image has the wrong ratio\", () => {\n    const testFeaturedMedia = {\n      height: 960,\n      width: 960,\n      url: 'featured-media.com/img',\n    };\n    const testHappy = storyPosterSize({\n      url: 'featured-media.com/img',\n      height: 960,\n      width: 720,\n    });\n    const test = storyPosterSize(testFeaturedMedia);\n    expect(testHappy).toBeFalse();\n    expect(test).toBeTrue();\n  });\n  it('should return false for a story with the correct poster image size.', () => {\n    const testFeaturedMedia = {\n      height: 853,\n      width: 640,\n      url: 'featured-media.com/img',\n    };\n\n    const test = storyPosterSize(testFeaturedMedia);\n    expect(test).toBeFalse();\n  });\n  it(\"should return true if the story's poster image is too small\", () => {\n    const testHeightFeaturedMedia = {\n      url: 'featured-media.com/img',\n      height: 1,\n      width: 640,\n    };\n    const testWidthFeaturedMedia = {\n      url: 'featured-media.com/img',\n      width: 1,\n      height: 853,\n    };\n    const testFeaturedMedia = {\n      height: 1,\n      width: 1,\n      url: 'featured-media.com/img',\n    };\n    const testHappy = storyPosterSize({\n      url: 'featured-media.com/img',\n      height: 853,\n      width: 640,\n    });\n    const testHeight = storyPosterSize(testHeightFeaturedMedia);\n    const testWidth = storyPosterSize(testWidthFeaturedMedia);\n    const test = storyPosterSize(testFeaturedMedia);\n    expect(testHappy).toBeFalse();\n    expect(testHeight).toBeTrue();\n    expect(testWidth).toBeTrue();\n    expect(test).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/storyTitleLength.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { storyTitleLength } from '../storyTitleLength';\n\ndescribe('storyTitleLength', () => {\n  it('should return true if the story title is longer than 40 characters', () => {\n    const testTitle =\n      'If you want to make an apple pie from scratch, you must first create the universe.';\n    const testFalse = storyTitleLength(\n      'Once, there was a man from Nantucket...'\n    );\n    const test = storyTitleLength(testTitle);\n    expect(test).toBeTrue();\n    expect(testFalse).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/textElementFontSizeTooSmall.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { textElementFontSizeTooSmall } from '../textElementFontSizeTooSmall';\n\ndescribe('textElementFontSizeTooSmall', () => {\n  it('should return true if text element font size is too small', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      fontSize: 11,\n    };\n    expect(textElementFontSizeTooSmall(element)).toBeTrue();\n  });\n\n  it('should return false if text element font size is large enough', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      fontSize: 12,\n    };\n    expect(textElementFontSizeTooSmall(element)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoElementLength.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { videoElementLength } from '../videoElementLength';\n\ndescribe('videoElementLength', () => {\n  it('should return true if the video element is longer than 1 minute', () => {\n    const tooLongVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        length: 75,\n        sizes: {\n          full: {\n            height: 2160,\n            width: 3840,\n          },\n        },\n      },\n    };\n\n    const result = videoElementLength(tooLongVideo);\n    expect(result).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoElementMissingCaptions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { videoElementMissingCaptions } from '../videoElementMissingCaptions';\n\ndescribe('videoElementMissingCaptions', () => {\n  it('should return a warning if video element missing captions', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n    };\n\n    const test = videoElementMissingCaptions(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return a warning if video element has empty captions', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n      tracks: [],\n    };\n    const test = videoElementMissingCaptions(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return undefined if video element has captions', () => {\n    const element = {\n      id: 'elementid',\n      type: 'text',\n      tracks: [{ id: 'trackid' }],\n    };\n    expect(videoElementMissingCaptions(element)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoElementMissingDescription.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { videoElementMissingDescription } from '../videoElementMissingDescription';\n\ndescribe('videoElementMissingDescription', () => {\n  it('should return a warning if video element missing title', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n      resource: {},\n    };\n    const test = videoElementMissingDescription(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return a warning if video element has empty description', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n      alt: '',\n      resource: {\n        alt: '',\n      },\n    };\n    const test = videoElementMissingDescription(element);\n    expect(test).toBeTrue();\n  });\n\n  it('should return undefined if video element has title', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n      alt: 'Video description',\n      resource: {},\n    };\n    expect(videoElementMissingDescription(element)).toBeFalse();\n  });\n\n  it('should return undefined if video resource has title', () => {\n    const element = {\n      id: 'elementid',\n      type: 'video',\n      resource: {\n        alt: 'Video description',\n      },\n    };\n    expect(videoElementMissingDescription(element)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoElementMissingPoster.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { videoElementMissingPoster } from '../videoElementMissingPoster';\n\ndescribe('videoElementMissingPoster', () => {\n  it(\"should return true if the video element and resource don't have a poster image\", () => {\n    const posterlessVideo = {\n      id: 303,\n      type: 'video',\n      resource: {\n        height: 800,\n        width: 500,\n      },\n    };\n\n    const result = videoElementMissingPoster(posterlessVideo);\n    expect(result).toBeTrue();\n  });\n\n  it('should not return true if the video resource has a poster image', () => {\n    const posterlessVideo = {\n      id: 303,\n      type: 'video',\n      resource: {\n        height: 800,\n        width: 500,\n        poster: 'http://mydomain.com/test/poster',\n      },\n    };\n\n    const result = videoElementMissingPoster(posterlessVideo);\n    expect(result).toBeFalse();\n  });\n\n  it('should not return true if the video element has a poster image', () => {\n    const posterlessVideo = {\n      id: 303,\n      type: 'video',\n      resource: {\n        height: 800,\n        width: 500,\n      },\n      poster: 'http://mydomain.com/test/poster',\n    };\n\n    const result = videoElementMissingPoster(posterlessVideo);\n    expect(result).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoElementResolution.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { videoElementResolution } from '../videoElementResolution';\n\ndescribe('videoElementResolution', () => {\n  it('should return a message if a video element is less than 480p', () => {\n    const tooLowResolutionVideoElement = {\n      id: 789,\n      type: 'video',\n      resource: {\n        height: 480,\n        width: 852,\n      },\n    };\n\n    const result = videoElementResolution(tooLowResolutionVideoElement);\n    expect(result).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/test/videoOptimization.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { videoElementsNotOptimized } from '../videoOptimization';\n\ndescribe('videoOptimization (pre-publish checklist card)', () => {\n  it('should return true if the video element is currently being transcoded', () => {\n    const largeUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 2160,\n        width: 3840,\n      },\n    };\n\n    const result = videoElementsNotOptimized(largeUnoptimizedVideo);\n    expect(result).toBeTrue();\n  });\n\n  it('should return true if the video element is larger than 1080x1920 and not optimized', () => {\n    const largeUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 2160,\n        width: 3840,\n      },\n    };\n\n    const result = videoElementsNotOptimized(largeUnoptimizedVideo);\n    expect(result).toBeTrue();\n  });\n\n  it('should return false if the video element is larger than 1080x1920 and is optimizing', () => {\n    const largeUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 2160,\n        width: 3840,\n      },\n    };\n\n    const result = videoElementsNotOptimized(largeUnoptimizedVideo);\n    expect(result).toBeTrue();\n  });\n\n  it('should return false if the video element is larger than 1080x1920 and Optimized', () => {\n    const largeUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: true,\n        height: 2160,\n        width: 3840,\n      },\n    };\n\n    const result = videoElementsNotOptimized(largeUnoptimizedVideo);\n    expect(result).toBeFalse();\n  });\n\n  it('should return false if the video element is larger than 1080x1920 and isExternal', () => {\n    const largeUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isExternal: true,\n        isOptimized: true,\n        height: 2160,\n        width: 3840,\n      },\n    };\n\n    const result = videoElementsNotOptimized(largeUnoptimizedVideo);\n    expect(result).toBeFalse();\n  });\n\n  it('should return false if the video element is smaller than 1080x1920', () => {\n    const smallUnoptimizedVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 300,\n        width: 400,\n      },\n    };\n    const smallOptimizedVideo = {\n      id: 203,\n      type: 'video',\n      resource: {\n        isOptimized: true,\n        height: 300,\n        width: 400,\n      },\n    };\n\n    expect(videoElementsNotOptimized(smallUnoptimizedVideo)).toBeFalse();\n    expect(videoElementsNotOptimized(smallOptimizedVideo)).toBeFalse();\n  });\n\n  it('should return false if the video element is exactly 1280x720', () => {\n    const landscapeVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 720,\n        width: 1280,\n      },\n    };\n    const portraitVideo = {\n      id: 202,\n      type: 'video',\n      resource: {\n        isOptimized: false,\n        height: 1280,\n        width: 720,\n      },\n    };\n\n    expect(videoElementsNotOptimized(landscapeVideo)).toBeFalse();\n    expect(videoElementsNotOptimized(portraitVideo)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/textElementFontSizeTooSmall.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY, MIN_FONT_SIZE } from '../constants';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\n\nexport function textElementFontSizeTooSmall(element) {\n  return (\n    element.type === 'text' &&\n    element.fontSize &&\n    element.fontSize < MIN_FONT_SIZE\n  );\n}\n\nconst TextElementFontSizeTooSmall = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, textElementFontSizeTooSmall),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        elementId,\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = ACCESSIBILITY_COPY.fontSizeTooSmall;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('TextElementFontSizeTooSmall', isRendered);\n\n  const thumbnails = elements.map((element) => (\n    <Thumbnail\n      key={element.id}\n      onClick={() => handleClick(element.id, element.pageId)}\n      type={THUMBNAIL_TYPES.TEXT}\n      displayBackground={<LayerThumbnail page={element} />}\n      aria-label={__('Go to offending text element', 'web-stories')}\n    />\n  ));\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        cardType={\n          elements.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={thumbnails}\n      />\n    )\n  );\n};\n\nexport default TextElementFontSizeTooSmall;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoElementLength.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY, MAX_VIDEO_LENGTH_SECONDS } from '../constants';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport VideoChecklistCard from './shared/videoChecklistCard';\n\nexport function videoElementLength(element) {\n  return (\n    element.type === 'video' &&\n    element.resource?.length > MAX_VIDEO_LENGTH_SECONDS\n  );\n}\n\nconst VideoElementLength = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, videoElementLength),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        elementId,\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.videoTooLong;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('VideoElementLength', isRendered);\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <VideoChecklistCard\n        title={title}\n        elements={elements}\n        footer={footer}\n        onThumbnailClick={handleClick}\n      />\n    )\n  );\n};\nexport default VideoElementLength;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoElementMissingCaptions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights, states } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY } from '../constants';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport VideoChecklistCard from './shared/videoChecklistCard';\n\nexport function videoElementMissingCaptions(element) {\n  return (\n    element.type === 'video' &&\n    !element?.resource?.isMuted &&\n    !element.tracks?.length\n  );\n}\n\nconst VideoElementMissingCaptions = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, videoElementMissingCaptions),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        pageId,\n        elementId,\n        highlight: states.Captions,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = ACCESSIBILITY_COPY.videoMissingCaptions;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('VideoElementMissingCaptions', isRendered);\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <VideoChecklistCard\n        title={title}\n        elements={elements}\n        footer={footer}\n        onThumbnailClick={handleClick}\n      />\n    )\n  );\n};\nexport default VideoElementMissingCaptions;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoElementMissingDescription.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { ACCESSIBILITY_COPY } from '../constants';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport VideoChecklistCard from './shared/videoChecklistCard';\n\nexport function videoElementMissingDescription(element) {\n  return (\n    element.type === 'video' &&\n    !element.alt?.length &&\n    !element.resource?.alt?.length\n  );\n}\n\nconst VideoElementMissingDescription = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, videoElementMissingDescription),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        pageId,\n        elementId,\n        highlight: states.AssistiveText,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = ACCESSIBILITY_COPY.videoMissingTitle;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('VideoElementMissingDescription', isRendered);\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <VideoChecklistCard\n        title={title}\n        elements={elements}\n        footer={footer}\n        onThumbnailClick={handleClick}\n      />\n    )\n  );\n};\nexport default VideoElementMissingDescription;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoElementMissingPoster.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { PRIORITY_COPY } from '../constants';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport VideoChecklistCard from './shared/videoChecklistCard';\n\nexport function videoElementMissingPoster(element) {\n  return (\n    element.type === 'video' && !element.resource?.poster && !element.poster\n  );\n}\n\nconst VideoElementMissingPoster = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n\n  const elements = useMemo(\n    () => filterStoryElements(pages, videoElementMissingPoster),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        pageId,\n        elementId,\n        highlight: states.VideoA11yPoster,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = PRIORITY_COPY.videoMissingPoster;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('VideoElementMissingPoster', isRendered);\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <VideoChecklistCard\n        title={title}\n        elements={elements}\n        footer={footer}\n        onThumbnailClick={handleClick}\n      />\n    )\n  );\n};\n\nexport default VideoElementMissingPoster;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoElementResolution.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { useHighlights } from '../../../app/highlights';\nimport { DESIGN_COPY, MIN_VIDEO_HEIGHT, MIN_VIDEO_WIDTH } from '../constants';\nimport { filterStoryElements } from '../utils';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport VideoChecklistCard from './shared/videoChecklistCard';\n\nexport function videoElementResolution(element) {\n  if (element.type !== 'video') {\n    return false;\n  }\n\n  const videoResolutionLow =\n    element.resource?.height <= MIN_VIDEO_HEIGHT &&\n    element.resource?.width <= MIN_VIDEO_WIDTH;\n\n  return videoResolutionLow;\n}\n\nconst VideoElementResolution = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const pages = useStory(({ state }) => state?.pages);\n  const elements = useMemo(\n    () => filterStoryElements(pages, videoElementResolution),\n    [pages]\n  );\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const handleClick = useCallback(\n    (elementId, pageId) =>\n      setHighlights({\n        elementId,\n        pageId,\n      }),\n    [setHighlights]\n  );\n\n  const { footer, title } = DESIGN_COPY.videoResolutionTooLow;\n\n  const isRendered = elements.length > 0;\n  useRegisterCheck('VideoElementResolution', isRendered);\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <VideoChecklistCard\n        title={title}\n        elements={elements}\n        footer={footer}\n        onThumbnailClick={handleClick}\n      />\n    )\n  );\n};\n\nexport default VideoElementResolution;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/checks/videoOptimization.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, _n, __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { useCallback, useMemo, useReducer } from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport { useLocalMedia } from '../../../app/media';\nimport { MEDIA_VIDEO_DIMENSIONS_THRESHOLD } from '../../../constants';\nimport { PRIORITY_COPY } from '../constants';\nimport { LayerThumbnail, Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport {\n  CARD_TYPE,\n  ChecklistCard,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { filterStoryElements } from '../utils/filterStoryElements';\nimport { useHighlights } from '../../../app/highlights';\nimport { StyledVideoOptimizationIcon } from '../../checklistCard/styles';\nimport { useRegisterCheck } from '../countContext';\nimport { useIsChecklistMounted } from '../popupMountedContext';\nimport useFFmpeg from '../../../app/media/utils/useFFmpeg';\nimport Tooltip from '../../tooltip';\n\nconst OptimizeButton = styled(Button)`\n  margin-top: 4px;\n`;\n\nexport function videoElementsNotOptimized(element = {}) {\n  const { resource } = element;\n  if (!resource) {\n    return false;\n  }\n\n  const { isOptimized, height = 0, width = 0 } = resource;\n  if (element.type !== 'video' || isOptimized) {\n    return false;\n  }\n\n  const videoArea = height * width;\n  const isLargeVideo =\n    videoArea >\n    MEDIA_VIDEO_DIMENSIONS_THRESHOLD.WIDTH *\n      MEDIA_VIDEO_DIMENSIONS_THRESHOLD.HEIGHT;\n\n  return isLargeVideo;\n}\n\nconst initialState = {};\nconst actionTypes = {\n  cancelled: 'cancelled',\n  uploaded: 'uploaded',\n  uploading: 'uploading',\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case actionTypes.cancelled:\n      return {\n        ...state,\n        [action.element.resource.id]: actionTypes.cancelled,\n      };\n    case actionTypes.uploaded:\n      return {\n        ...state,\n        [action.element.resource.id]: actionTypes.uploaded,\n      };\n    case actionTypes.uploading:\n      return {\n        ...state,\n        [action.element.resource.id]: actionTypes.uploading,\n      };\n    default:\n      throw new Error();\n  }\n}\n\nconst BulkVideoOptimization = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const [state, dispatch] = useReducer(reducer, initialState);\n  const pages = useStory(({ state: storyState }) => storyState?.pages);\n\n  const {\n    optimizeVideo,\n    isNewResourceTranscoding,\n    isCurrentResourceTranscoding,\n    canTranscodeResource,\n  } = useLocalMedia(\n    ({\n      actions: { optimizeVideo },\n      state: {\n        isNewResourceTranscoding,\n        canTranscodeResource,\n        isCurrentResourceTranscoding,\n      },\n    }) => ({\n      optimizeVideo,\n      isNewResourceTranscoding,\n      canTranscodeResource,\n      isCurrentResourceTranscoding,\n    })\n  );\n\n  const unoptimizedElements = useMemo(\n    () => filterStoryElements(pages, videoElementsNotOptimized),\n    [pages]\n  );\n  const unoptimizedVideos = unoptimizedElements.filter(\n    (element, index, array) =>\n      array.findIndex(\n        (innerElement) => innerElement.resource.id === element.resource.id\n      ) === index\n  );\n\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n\n  const processVideoElement = useCallback(\n    async (element) => {\n      if (\n        canTranscodeResource(element.resource) &&\n        state[element.resource.id] !== actionTypes.uploading\n      ) {\n        dispatch({ type: actionTypes.uploading, element });\n        try {\n          await optimizeVideo({ resource: element.resource });\n        } catch (e) {\n          dispatch({ type: actionTypes.cancelled, element });\n          return;\n        }\n        dispatch({ type: actionTypes.uploaded, element });\n      }\n    },\n    [canTranscodeResource, optimizeVideo, state]\n  );\n\n  const sequencedVideoOptimization = useCallback(() => {\n    // only attempt to optimize videos that are not currently being transcoded\n    const optimizingResources = unoptimizedVideos.filter(\n      ({ resource }) =>\n        !isNewResourceTranscoding(resource?.id) &&\n        !isCurrentResourceTranscoding(resource?.id)\n    );\n    return new Promise((resolve) => {\n      optimizingResources\n        .map((element) => async () => {\n          await processVideoElement(element);\n        })\n        .reduce((p, fn) => p.then(fn), Promise.resolve())\n        .then(resolve);\n    });\n  }, [\n    isNewResourceTranscoding,\n    isCurrentResourceTranscoding,\n    processVideoElement,\n    unoptimizedVideos,\n  ]);\n\n  const handleUpdateVideos = useCallback(async () => {\n    await sequencedVideoOptimization();\n  }, [sequencedVideoOptimization]);\n\n  const handleClickThumbnail = useCallback(\n    (element) => async () => {\n      setHighlights({\n        pageId: element.pageId,\n        elementId: element.id,\n      });\n      await processVideoElement(element);\n    },\n    [processVideoElement, setHighlights]\n  );\n\n  const { footer, title } = PRIORITY_COPY.videoNotOptimized;\n\n  const currentlyUploading = useMemo(\n    () =>\n      Object.values(state).filter((value) => value === actionTypes.uploading),\n    [state]\n  );\n  const isTranscoding = useMemo(\n    () =>\n      currentlyUploading.length > 0 ||\n      unoptimizedVideos.some(\n        (video) =>\n          isNewResourceTranscoding(video.resource.id) ||\n          isCurrentResourceTranscoding(video.resource.id)\n      ),\n    [\n      currentlyUploading,\n      unoptimizedVideos,\n      isNewResourceTranscoding,\n      isCurrentResourceTranscoding,\n    ]\n  );\n\n  const isRendered = unoptimizedVideos.length > 0;\n  useRegisterCheck('VideoOptimization', isRendered);\n\n  let optimizeButtonCopy =\n    unoptimizedVideos.length === 1\n      ? __('Optimize video', 'web-stories')\n      : __('Optimize all videos', 'web-stories');\n\n  if (isTranscoding) {\n    const numTranscoding =\n      currentlyUploading.length +\n      unoptimizedVideos.filter(\n        (video) =>\n          isNewResourceTranscoding(video.resource.id) ||\n          isCurrentResourceTranscoding(video.resource.id)\n      ).length;\n    optimizeButtonCopy = sprintf(\n      /* translators: 1: number of videos currently transcoding. 2: total number of videos in list. */\n      _n(\n        'Optimizing %1$d of %2$d',\n        'Optimizing %1$d of %2$d',\n        numTranscoding,\n        'web-stories'\n      ),\n      numTranscoding,\n      unoptimizedVideos.length\n    );\n  }\n\n  return (\n    isRendered &&\n    isChecklistMounted && (\n      <ChecklistCard\n        cta={\n          <OptimizeButton\n            type={ButtonType.Secondary}\n            size={ButtonSize.Small}\n            onClick={handleUpdateVideos}\n            disabled={isTranscoding}\n          >\n            {optimizeButtonCopy}\n          </OptimizeButton>\n        }\n        title={title}\n        cardType={\n          unoptimizedVideos.length > 1\n            ? CARD_TYPE.MULTIPLE_ISSUE\n            : CARD_TYPE.SINGLE_ISSUE\n        }\n        footer={<DefaultFooterText>{footer}</DefaultFooterText>}\n        thumbnails={unoptimizedVideos.map((element) => (\n          <Thumbnail\n            key={element.resource.id}\n            onClick={handleClickThumbnail(element)}\n            isLoading={\n              isNewResourceTranscoding(element.resource.id) ||\n              isCurrentResourceTranscoding(element.resource.id)\n            }\n            type={THUMBNAIL_TYPES.VIDEO}\n            displayBackground={<LayerThumbnail page={element} />}\n            aria-label={__('Go to offending video', 'web-stories')}\n            isError={state[element.resource.id] === actionTypes.cancelled}\n          >\n            {\n              <Tooltip\n                title={\n                  state[element.resource.id] === actionTypes.uploading ||\n                  isNewResourceTranscoding(element.resource.id) ||\n                  isCurrentResourceTranscoding(element.resource.id)\n                    ? __('Video optimization in progress', 'web-stories')\n                    : __('Optimize', 'web-stories')\n                }\n              >\n                <StyledVideoOptimizationIcon />\n              </Tooltip>\n            }\n          </Thumbnail>\n        ))}\n      />\n    )\n  );\n};\n\nconst VideoOptimization = () => {\n  // `isTranscodingEnabled` already checks for `hasUploadMediaAction`.\n  const { isTranscodingEnabled } = useFFmpeg();\n\n  return isTranscodingEnabled ? <BulkVideoOptimization /> : null;\n};\n\nexport default VideoOptimization;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf, _n, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { Link, TextSize } from '@googleforcreators/design-system';\n\nexport const THUMBNAIL_MAX = 4;\nexport const THUMBNAIL_COUNT_FOR_OVERFLOW = 3;\n\nexport const ASPECT_RATIO_LEFT = 3;\nexport const ASPECT_RATIO_RIGHT = 4;\nconst IMAGE_SIZE_WIDTH = 828;\nconst IMAGE_SIZE_HEIGHT = 1792;\nconst MAX_CHARACTER_PERCENTAGE = 10;\nexport const MIN_FONT_SIZE = 12;\nexport const MIN_STORY_CHARACTER_COUNT = 100;\nexport const MAX_PAGE_CHARACTER_COUNT = 200;\nexport const MIN_STORY_PAGES = 4;\nexport const MAX_STORY_PAGES = 30;\nexport const MAX_STORY_TITLE_LENGTH_WORDS = 10;\nexport const MAX_STORY_TITLE_LENGTH_CHARS = 70;\nexport const MAX_VIDEO_LENGTH_SECONDS = 60;\nconst MAX_VIDEO_LENGTH_MINUTES = Math.floor(MAX_VIDEO_LENGTH_SECONDS / 60);\nconst MIN_TAP_REGION_WIDTH = 48;\nexport const MAX_LINKS_PER_PAGE = 3;\nconst MAX_VIDEO_RESOLUTION = 720;\nconst MIN_VIDEO_RESOLUTION = 480;\nexport const MIN_VIDEO_HEIGHT = 480;\nexport const MIN_VIDEO_WIDTH = 852;\nconst MIN_VIDEO_FPS = 24;\nexport const FEATURED_MEDIA_RESOURCE_MIN_WIDTH = 640;\nexport const FEATURED_MEDIA_RESOURCE_MIN_HEIGHT = 853;\nexport const PUBLISHER_LOGO_DIMENSION = 96;\nconst PUBLISHER_LOGO_RATIO = 1;\n\nexport const POPUP_ID = 'checklist_companion';\n\nexport const CHECKLIST_TITLE = __('Checklist', 'web-stories');\n\nexport const ISSUE_TYPES = {\n  ACCESSIBILITY: 'accessibility',\n  DESIGN: 'design',\n  PRIORITY: 'priority',\n};\n\nexport const CATEGORY_LABELS = {\n  [ISSUE_TYPES.ACCESSIBILITY]: __('Accessibility', 'web-stories'),\n  [ISSUE_TYPES.DESIGN]: __('Design', 'web-stories'),\n  [ISSUE_TYPES.PRIORITY]: __('Priority', 'web-stories'),\n};\n\nconst DOCS_URL = 'https://wp.stories.google/docs/faq/';\n\n// Event Tracking\nconst onAmpErrorClick = (evt) => trackClick(evt, 'click_checklist_amp_test');\n\n// Checklist Copy\nexport const ACCESSIBILITY_COPY = {\n  fontSizeTooSmall: {\n    title: sprintf(\n      /* translators: %d: minimum font size. */\n      __('Increase font size to %d or above', 'web-stories'),\n      MIN_FONT_SIZE\n    ),\n    footer: sprintf(\n      /* translators: %d: minimum font size. */\n      __(\n        'Ensure legibility by selecting text size %d or greater',\n        'web-stories'\n      ),\n      MIN_FONT_SIZE\n    ),\n  },\n  imagesMissingAltText: {\n    title: __('Add assistive text to images', 'web-stories'),\n    footer: __(\n      'Optimize accessibility and indexability with meaningful text to better assist users.',\n      'web-stories'\n    ),\n  },\n  linkTappableRegionTooBig: {\n    title: __('Reduce link size', 'web-stories'),\n    footer: __(\n      'Elements with links must not cover most of the page. Decrease the size of elements with links.',\n      'web-stories'\n    ),\n  },\n  linkTappableRegionTooSmall: {\n    title: sprintf(\n      /* translators: %s: minimum tappable region size width x minimum tappable region size height. */\n      __('Increase tap area size to at least %s', 'web-stories'),\n      `${MIN_TAP_REGION_WIDTH}x${MIN_TAP_REGION_WIDTH}px`\n    ),\n    footer: __(\n      'Optimize accessibility and indexability with meaningful text to better assist users',\n      'web-stories'\n    ),\n  },\n  lowContrast: {\n    title: __(\n      'Increase contrast between text and background color',\n      'web-stories'\n    ),\n    footer: __(\n      'Ensure legibility of text and ease of reading by increasing color contrast',\n      'web-stories'\n    ),\n    textPanel: __(\n      'This color or font size combination may be hard for some people to read.',\n      'web-stories'\n    ),\n    backgroundPanel: __(\n      'This background color may make some text hard to read.',\n      'web-stories'\n    ),\n    warningIcon: __('Low Warning', 'web-stories'),\n  },\n  videoMissingCaptions: {\n    title: __('Add video captions', 'web-stories'),\n    footer: __(\n      \"Keep the audience engaged even when they can't listen to the audio\",\n      'web-stories'\n    ),\n  },\n  videoMissingTitle: {\n    title: __('Add video description', 'web-stories'),\n    footer: __(\n      'Improves indexability and accessibility (for videos without captions)',\n      'web-stories'\n    ),\n  },\n};\n\nexport const DESIGN_COPY = {\n  storyTooShort: {\n    title: sprintf(\n      /* translators: %d: maximum number of pages. */\n      _n(\n        'Make Web Story at least %d page',\n        'Make Web Story at least %d pages',\n        MIN_STORY_PAGES,\n        'web-stories'\n      ),\n      MIN_STORY_PAGES\n    ),\n    footer: sprintf(\n      /* translators: 1: minimum number of pages. 2: maximum number of pages. */\n      __(\n        'It is recommended to have between %1$d and %2$d pages in your story',\n        'web-stories'\n      ),\n      MIN_STORY_PAGES,\n      MAX_STORY_PAGES\n    ),\n  },\n  storyTooLong: {\n    title: sprintf(\n      /* translators: %d: minimum number of pages. */\n      _n(\n        'Make Web Story fewer than %d page',\n        'Make Web Story fewer than %d pages',\n        MAX_STORY_PAGES,\n        'web-stories'\n      ),\n      MAX_STORY_PAGES\n    ),\n    footer: sprintf(\n      /* translators: 1: minimum number of pages. 2: maximum number of pages. */\n      __(\n        'It is recommended to have between %1$d and %2$d pages in your story',\n        'web-stories'\n      ),\n      MIN_STORY_PAGES,\n      MAX_STORY_PAGES\n    ),\n  },\n  tooLittlePageText: {\n    title: __('Add more text to page', 'web-stories'),\n    footer: sprintf(\n      /* translators: %d: minimum number of story characters. */\n      _n(\n        'Include at least %d character',\n        'Include at least %d characters',\n        MIN_STORY_CHARACTER_COUNT,\n        'web-stories'\n      ),\n      MIN_STORY_CHARACTER_COUNT\n    ),\n  },\n  tooMuchPageText: {\n    title: __('Reduce text amount on page', 'web-stories'),\n    footer: (\n      <>\n        <li>\n          {sprintf(\n            /* translators: %d: maximum number of story characters. */\n            _n(\n              'Include no more than %d character',\n              'Include no more than %d characters',\n              MAX_PAGE_CHARACTER_COUNT,\n              'web-stories'\n            ),\n            MAX_PAGE_CHARACTER_COUNT\n          )}\n        </li>\n        <li>\n          {__(\n            'Use a page attachment breaking up the text into multiple screens; or',\n            'web-stories'\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: maximum percentage of characters, depending on number of pages. */\n            __(\n              'Keep the total number of text-heavy pages under %s of total number of story pages',\n              'web-stories'\n            ),\n            MAX_CHARACTER_PERCENTAGE + '%'\n          )}\n        </li>\n      </>\n    ),\n  },\n  tooManyLinksOnPage: {\n    title: sprintf(\n      /* translators: %s: maximum number of links per page. */\n      __('Avoid including more than %s links per page', 'web-stories'),\n      MAX_LINKS_PER_PAGE\n    ),\n    footer: sprintf(\n      /* translators: %s: maximum number of links per page. */\n      __('Avoid having more than %s links on one page', 'web-stories'),\n      MAX_LINKS_PER_PAGE\n    ),\n  },\n  imageResolutionTooLow: {\n    title: __('Increase image resolution', 'web-stories'),\n    footer: (\n      <>\n        <li>\n          {__(\n            'Use larger resolution (2x or 3x) images for best appearance on screens with high pixel density',\n            'web-stories'\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: minimum image size width x minimum image size height. */\n            __(\n              'For full-screen images, use a resolution of at least %s',\n              'web-stories'\n            ),\n            `${IMAGE_SIZE_WIDTH}x${IMAGE_SIZE_HEIGHT}px`\n          )}\n        </li>\n      </>\n    ),\n  },\n  videoFrameRateTooLow: {\n    title: sprintf(\n      /* translators: %d: minimum number of frames per second for video. */\n      __('Increase video frame rate to at least %d fps', 'web-stories'),\n      MIN_VIDEO_FPS\n    ),\n    footer: sprintf(\n      /* translators: %d: minimum number of frames per second for video. */\n      _n(\n        'Ensure your video has a minimum of %d frame per second',\n        'Ensure your video has a minimum of %d frames per second',\n        MIN_VIDEO_FPS,\n        'web-stories'\n      ),\n      MIN_VIDEO_FPS\n    ),\n  },\n  videoResolutionTooLow: {\n    title: __('Increase video resolution', 'web-stories'),\n    footer: sprintf(\n      /* translators: 1: minimum video resolution. 2: minimum video width x minimum video height in pixels. */\n      __(\n        'Consider using a minimum resolution of %1$s (%2$s) to represent portrait videos',\n        'web-stories'\n      ),\n      `${MIN_VIDEO_RESOLUTION}p`,\n      `${MIN_VIDEO_WIDTH}x${MIN_VIDEO_HEIGHT}px`\n    ),\n  },\n  videoTooLong: {\n    title: sprintf(\n      /* translators: %d: maximum video length in minutes. */\n      _n(\n        'Split videos into segments of %d minute or less',\n        'Split videos into segments of %d minutes or less',\n        MAX_VIDEO_LENGTH_MINUTES,\n        'web-stories'\n      ),\n      MAX_VIDEO_LENGTH_MINUTES\n    ),\n    footer: __('Shorter videos help readers navigate stories', 'web-stories'),\n  },\n  firstPageAnimation: {\n    title: __('First Page Animations', 'web-stories'),\n    footer: __(\n      'Animations on the first page of a story are not supported for user experience and performance reasons.',\n      'web-stories'\n    ),\n    animationPanel: __(\n      'Animations on the first page of a story are not supported for user experience and performance reasons.',\n      'web-stories'\n    ),\n  },\n};\n\nexport const PRIORITY_COPY = {\n  storyMissingDescription: {\n    title: __('Add Web Story description', 'web-stories'),\n    footer: __(\n      'Incorporate a brief description for better user experience',\n      'web-stories'\n    ),\n  },\n  storyMissingTitle: {\n    title: __('Add Web Story title', 'web-stories'),\n    footer: (\n      <>\n        <li>\n          {sprintf(\n            /* translators: %d: maximum story title length in words. */\n            _n(\n              'Keep under %d word',\n              'Keep under %d words',\n              MAX_STORY_TITLE_LENGTH_WORDS,\n              'web-stories'\n            ),\n            MAX_STORY_TITLE_LENGTH_WORDS\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %d: maximum story title length in characters. */\n            _n(\n              \"Don't exceed %d character\",\n              \"Don't exceed %d characters\",\n              MAX_STORY_TITLE_LENGTH_CHARS,\n              'web-stories'\n            ),\n            MAX_STORY_TITLE_LENGTH_CHARS\n          )}\n        </li>\n      </>\n    ),\n  },\n  storyMissingPoster: {\n    title: __('Add poster image', 'web-stories'),\n    footer: (\n      <>\n        <li>{__('Use as a representation of the story', 'web-stories')}</li>\n        <li>{__('Avoid images with embedded text', 'web-stories')}</li>\n        <li>\n          {sprintf(\n            /* translators: %s: image dimensions.  */\n            __(\"Use an image that's at least %s\", 'web-stories'),\n            `${FEATURED_MEDIA_RESOURCE_MIN_WIDTH}x${FEATURED_MEDIA_RESOURCE_MIN_HEIGHT}px`\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: aspect ratio.  */\n            __('Maintain a %s aspect ratio', 'web-stories'),\n            `${ASPECT_RATIO_LEFT}:${ASPECT_RATIO_RIGHT}`\n          )}\n        </li>\n      </>\n    ),\n  },\n  videoMissingPoster: {\n    title: __('Add poster image to every video', 'web-stories'),\n    footer: __(\n      'Ensure a better experience by displaying a poster while users wait for the video to load',\n      'web-stories'\n    ),\n  },\n  storyTitleTooLong: {\n    title: sprintf(\n      /* translators: %d: maximum number of story characters. */\n      _n(\n        'Shorten title to fewer than %d character',\n        'Shorten title to fewer than %d characters',\n        MAX_STORY_TITLE_LENGTH_CHARS,\n        'web-stories'\n      ),\n      MAX_STORY_TITLE_LENGTH_CHARS\n    ),\n    footer: sprintf(\n      /* translators: %d: maximum number of story characters. */\n      _n(\n        'Limit story title to %d character or less',\n        'Limit story title to %d characters or less',\n        MAX_STORY_TITLE_LENGTH_CHARS,\n        'web-stories'\n      ),\n      MAX_STORY_TITLE_LENGTH_CHARS\n    ),\n  },\n  logoTooSmall: {\n    title: sprintf(\n      /* translators: %s: image dimensions. */\n      __('Increase size of publisher logo to at least %s', 'web-stories'),\n      `${PUBLISHER_LOGO_DIMENSION}x${PUBLISHER_LOGO_DIMENSION}px`\n    ),\n    footer: (\n      <>\n        <li>\n          {sprintf(\n            /* translators: %s: image dimensions. */\n            __(\"Use an image that's at least %s\", 'web-stories'),\n            `${PUBLISHER_LOGO_DIMENSION}x${PUBLISHER_LOGO_DIMENSION}px`\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: aspect ratio.  */\n            __('Maintain a %s aspect ratio', 'web-stories'),\n            `${PUBLISHER_LOGO_RATIO}x${PUBLISHER_LOGO_RATIO}px`\n          )}\n        </li>\n      </>\n    ),\n  },\n  noPublisherLogo: {\n    title: __('Add a publisher logo to your story', 'web-stories'),\n    footer: (\n      <>\n        <li>\n          {sprintf(\n            /* translators: %s: image dimensions. */\n            __(\"Use an image that's at least %s\", 'web-stories'),\n            `${PUBLISHER_LOGO_DIMENSION}x${PUBLISHER_LOGO_DIMENSION}px`\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: aspect ratio.  */\n            __('Maintain a %s aspect ratio', 'web-stories'),\n            `${PUBLISHER_LOGO_RATIO}x${PUBLISHER_LOGO_RATIO}px`\n          )}\n        </li>\n      </>\n    ),\n  },\n  storyPosterSize: {\n    title: sprintf(\n      /* translators: %s: image dimensions.  */\n      __('Correct poster image aspect ratio to %s', 'web-stories'),\n      `${FEATURED_MEDIA_RESOURCE_MIN_WIDTH}x${FEATURED_MEDIA_RESOURCE_MIN_HEIGHT}px`\n    ),\n    footer: (\n      <>\n        <li>\n          {sprintf(\n            /* translators: %s: image dimensions.  */\n            __(\"Use an image that's at least %s\", 'web-stories'),\n            `${FEATURED_MEDIA_RESOURCE_MIN_WIDTH}x${FEATURED_MEDIA_RESOURCE_MIN_HEIGHT}px`\n          )}\n        </li>\n        <li>\n          {sprintf(\n            /* translators: %s: aspect ratio.  */\n            __('Maintain a %s aspect ratio', 'web-stories'),\n            `${ASPECT_RATIO_LEFT}:${ASPECT_RATIO_RIGHT}`\n          )}\n        </li>\n      </>\n    ),\n  },\n  videoNotOptimized: {\n    title: __('Optimize videos', 'web-stories'),\n    footer: sprintf(\n      /* translators: %s: video resolution (720p) */\n      __(\n        'Videos larger than %s can cause slower loading and higher bandwidth costs.',\n        'web-stories'\n      ),\n      `${MAX_VIDEO_RESOLUTION}p`\n    ),\n  },\n  storyMissingPublisherName: {\n    title: __('Add Site Title', 'web-stories'),\n  },\n  ampValidation: {\n    title: __('Compatibility', 'web-stories'),\n    footer: (\n      <TranslateWithMarkup\n        mapping={{\n          a: (\n            <Link\n              href={DOCS_URL}\n              rel=\"noreferrer\"\n              target=\"_blank\"\n              onClick={onAmpErrorClick}\n              size={TextSize.XSmall}\n            />\n          ),\n        }}\n      >\n        {__(\n          'Your story contains errors that can affect eligibility to appear on Google. Please see <a>our FAQ</a> for more information.',\n          'web-stories'\n        )}\n      </TranslateWithMarkup>\n    ),\n  },\n};\n\nexport const PPC_CHECKPOINT_STATE = {\n  UNAVAILABLE: 'unavailable',\n  ONLY_RECOMMENDED: 'recommended',\n  ALL: 'all',\n};\n\nexport const PANEL_VISIBILITY_BY_STATE = {\n  [PPC_CHECKPOINT_STATE.UNAVAILABLE]: [],\n  [PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED]: [\n    ISSUE_TYPES.ACCESSIBILITY,\n    ISSUE_TYPES.DESIGN,\n  ],\n  [PPC_CHECKPOINT_STATE.ALL]: Object.values(ISSUE_TYPES),\n};\n\nexport const PANEL_EXPANSION_BY_CHECKPOINT = {\n  [PPC_CHECKPOINT_STATE.UNAVAILABLE]: null,\n  [PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED]: ISSUE_TYPES.DESIGN,\n  [PPC_CHECKPOINT_STATE.ALL]: ISSUE_TYPES.PRIORITY,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/countContext/checkCountContext.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useCallback,\n  createContext,\n  useContext,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { ISSUE_TYPES } from '../constants';\n\nexport const CountContext = createContext(null);\nexport const CategoryContext = createContext(null);\n\nconst INITIAL_STATE = {\n  [ISSUE_TYPES.PRIORITY]: {},\n  [ISSUE_TYPES.DESIGN]: {},\n  [ISSUE_TYPES.ACCESSIBILITY]: {},\n};\nfunction ChecklistCountProvider({ hasChecklist, children }) {\n  const value = useState({ ...INITIAL_STATE, hasChecklist });\n  return (\n    <CountContext.Provider value={value}>{children}</CountContext.Provider>\n  );\n}\nChecklistCountProvider.propTypes = {\n  children: PropTypes.node,\n  hasChecklist: PropTypes.bool,\n};\n\nfunction ChecklistCategoryProvider({ children, category }) {\n  const setCategories = useContext(CountContext)?.[1];\n  if (!setCategories) {\n    throw new Error(\n      'Cannot use `ChecklistCategoryProvider` outside of `ChecklistCountProvider`'\n    );\n  }\n\n  const addEntry = useCallback(\n    (entry) =>\n      setCategories((categories) => ({\n        ...categories,\n        [category]: {\n          ...categories[category],\n          ...entry,\n        },\n      })),\n    [category, setCategories]\n  );\n\n  return (\n    <CategoryContext.Provider value={addEntry}>\n      {children}\n    </CategoryContext.Provider>\n  );\n}\nChecklistCategoryProvider.propTypes = {\n  children: PropTypes.node,\n  category: PropTypes.oneOf(Object.values(ISSUE_TYPES)).isRequired,\n};\n\nfunction useRegisterCheck(id, isRendered) {\n  const addEntry = useContext(CategoryContext);\n  if (!addEntry) {\n    throw new Error(\n      'Cannot use `useRegisterCheck` outside of `ChecklistCategoryProvider`'\n    );\n  }\n  useEffect(() => addEntry({ [id]: isRendered }), [id, addEntry, isRendered]);\n}\n\nfunction useIsChecklistEmpty() {\n  const categories = useContext(CountContext)?.[0];\n  if (!categories) {\n    throw new Error(\n      'Cannot use `useIsChecklistEmpty` outside of `ChecklistCountProvider`'\n    );\n  }\n  return (\n    Object.values(categories)\n      .map((category) => Object.values(category))\n      .flatMap((v) => v)\n      .filter((isRendered) => isRendered).length > 0\n  );\n}\n\nfunction useCategoryCount(category) {\n  const categories = useContext(CountContext)?.[0];\n  if (!categories) {\n    throw new Error(\n      'Cannot use `useCategoryCount` outside of `ChecklistCountProvider`'\n    );\n  }\n  return Object.values(categories[category] || {}).filter(\n    (isRendered) => isRendered\n  ).length;\n}\n\nfunction useHasChecklist() {\n  const countContext = useContext(CountContext)?.[0];\n  if (!countContext) {\n    throw new Error(\n      'Cannot use `useHasChecklist` outside of `ChecklistCountProvider`'\n    );\n  }\n  const { hasChecklist } = countContext;\n  return hasChecklist;\n}\n\nexport {\n  ChecklistCountProvider,\n  ChecklistCategoryProvider,\n  useRegisterCheck,\n  useIsChecklistEmpty,\n  useCategoryCount,\n  useHasChecklist,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/countContext/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport {\n  ChecklistCountProvider,\n  ChecklistCategoryProvider,\n  useRegisterCheck,\n  useIsChecklistEmpty,\n  useCategoryCount,\n  useHasChecklist,\n} from './checkCountContext';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/countContext/test/checkCountContext.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContext } from '@googleforcreators/react';\nimport { render } from '@testing-library/react';\nimport { act, renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { ISSUE_TYPES } from '../../constants';\nimport {\n  ChecklistCountProvider,\n  ChecklistCategoryProvider,\n  CategoryContext,\n  CountContext,\n  useRegisterCheck,\n} from '../checkCountContext';\n\nlet consoleErrorFn;\n\ndescribe('ChecklistCategoryProvider', () => {\n  beforeEach(() => {\n    consoleErrorFn = jest.spyOn(console, 'error').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    consoleErrorFn.mockRestore();\n  });\n\n  it('throws an error if used outside of ChecklistCountProvider', () => {\n    expect(() =>\n      render(<ChecklistCategoryProvider category={ISSUE_TYPES.DESIGN} />)\n    ).toThrow(\n      'Cannot use `ChecklistCategoryProvider` outside of `ChecklistCountProvider`'\n    );\n  });\n\n  it('provides a method to add entries', () => {\n    const ChecklistWrapper = ({ children }) => (\n      <ChecklistCountProvider hasChecklist>\n        <ChecklistCategoryProvider category={ISSUE_TYPES.PRIORITY}>\n          {children}\n        </ChecklistCategoryProvider>\n      </ChecklistCountProvider>\n    );\n    const useContextValues = () => ({\n      categoryContextValue: useContext(CategoryContext),\n      countContextValue: useContext(CountContext),\n    });\n    const { result } = renderHook(() => useContextValues(), {\n      wrapper: ChecklistWrapper,\n    });\n    act(() => {\n      result.current.categoryContextValue({ testEntry: true });\n    });\n    const [categories] = result.current.countContextValue;\n    expect(categories).toStrictEqual({\n      [ISSUE_TYPES.PRIORITY]: {\n        testEntry: true,\n      },\n      [ISSUE_TYPES.DESIGN]: {},\n      [ISSUE_TYPES.ACCESSIBILITY]: {},\n      hasChecklist: true,\n    });\n  });\n});\n\ndescribe('useRegisterCheck', () => {\n  it('registers a check under a key', () => {\n    const testKey = 'testKey';\n\n    const ChecklistWrapper = ({ children }) => (\n      <ChecklistCountProvider hasChecklist>\n        <ChecklistCategoryProvider category={ISSUE_TYPES.PRIORITY}>\n          {children}\n        </ChecklistCategoryProvider>\n      </ChecklistCountProvider>\n    );\n    const useCountContextAndRegisterHook = (isEntryRendered) => ({\n      registerCheck: useRegisterCheck(testKey, isEntryRendered),\n      countContextValue: useContext(CountContext),\n    });\n    const { result, rerender } = renderHook(\n      (isEntryRendered) => useCountContextAndRegisterHook(isEntryRendered),\n      {\n        wrapper: ChecklistWrapper,\n        initialProps: true,\n      }\n    );\n\n    expect(result.current.countContextValue[0]).toStrictEqual({\n      [ISSUE_TYPES.PRIORITY]: {\n        [testKey]: true,\n      },\n      [ISSUE_TYPES.DESIGN]: {},\n      [ISSUE_TYPES.ACCESSIBILITY]: {},\n      hasChecklist: true,\n    });\n\n    rerender(false);\n    expect(result.current.countContextValue[0]).toStrictEqual({\n      [ISSUE_TYPES.PRIORITY]: {\n        [testKey]: false,\n      },\n      [ISSUE_TYPES.DESIGN]: {},\n      [ISSUE_TYPES.ACCESSIBILITY]: {},\n      hasChecklist: true,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { ChecklistProvider, useChecklist } from './checklistContext';\nexport {\n  ChecklistCheckpointProvider,\n  useCheckpoint,\n  CheckpointContext,\n} from './checkpointContext';\nexport {\n  ChecklistCountProvider,\n  ChecklistCategoryProvider,\n  useRegisterCheck,\n  useIsChecklistEmpty,\n  useCategoryCount,\n  useHasChecklist,\n} from './countContext';\n\nexport { Checklist } from './checklist';\nexport * from './checks';\nexport { default as ChecklistIcon } from './checklistIcon';\nexport {\n  PPC_CHECKPOINT_STATE,\n  PRIORITY_COPY as CHECKLIST_PRIORITY_COPY,\n  ACCESSIBILITY_COPY,\n  DESIGN_COPY,\n} from './constants';\nexport { useIsChecklistMounted } from './popupMountedContext';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/karma/checklist.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport { DATA_VERSION } from '@googleforcreators/migration';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useInsertElement } from '../../canvas';\nimport { ACCESSIBILITY_COPY, DESIGN_COPY, PRIORITY_COPY } from '../constants';\n\ndescribe('Checklist integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const emptyContent = () => {\n    return fixture.screen.queryByText(\n      /You are all set for now. Return to this checklist as you build your Web Story for tips on how to improve it./\n    );\n  };\n\n  const addPages = async (count) => {\n    let clickCount = 1;\n    while (clickCount <= count) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n      // eslint-disable-next-line no-await-in-loop, no-loop-func\n      await waitFor(() => {\n        if (!fixture.editor.footer.carousel.pages.length) {\n          throw new Error('page not yet added');\n        }\n        expect(fixture.editor.footer.carousel.pages.length).toBe(\n          clickCount + 1\n        );\n      });\n      clickCount++;\n    }\n  };\n\n  const openChecklist = async () => {\n    const { toggleButton } = fixture.editor.checklist;\n    await fixture.events.click(toggleButton);\n    // wait for animation\n    await fixture.events.sleep(500);\n  };\n\n  /**\n   * Inserts an image without assistive text. This will trigger\n   * an a11y issue in the checklist.\n   */\n  const addAccessibilityIssue = async () => {\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    await fixture.act(() =>\n      insertElement('image', {\n        x: 0,\n        y: 0,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          type: 'image',\n          mimeType: 'image/jpg',\n          src: 'http://localhost:9876/__static__/earth.jpg',\n          alt: '',\n          width: 640,\n          height: 529,\n          baseColor: '#734727',\n        },\n      })\n    );\n  };\n\n  const openChecklistWithKeyboard = async () => {\n    const { toggleButton } = fixture.editor.checklist;\n    await fixture.events.focus(toggleButton);\n    await fixture.events.keyboard.press('Enter');\n    // wait for animation\n    await fixture.events.sleep(500);\n  };\n\n  describe('initial state', () => {\n    it('should begin with empty message on a new story', async () => {\n      await openChecklist();\n\n      const emptyMessage = fixture.screen.getByText(\n        'You are all set for now. Return to this checklist as you build your Web Story for tips on how to improve it.'\n      );\n\n      expect(emptyMessage).toBeTruthy();\n    });\n  });\n\n  describe('open and close', () => {\n    it('should toggle the checklist', async () => {\n      const { toggleButton } = fixture.editor.checklist;\n\n      await fixture.events.click(toggleButton);\n      // wait for animation\n      await fixture.events.sleep(500);\n      expect(\n        fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n      ).toBe('true');\n\n      await fixture.events.click(toggleButton);\n      // wait for animation\n      await fixture.events.sleep(500);\n    });\n\n    it('should close the checklist when the \"close\" button is clicked', async () => {\n      await openChecklist();\n\n      await fixture.events.click(fixture.editor.checklist.closeButton);\n      await fixture.events.sleep(500);\n    });\n  });\n\n  describe('Checklist aXe tests', () => {\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should have no aXe violations with empty message on a new story', async () => {\n      await openChecklist();\n      await expectAsync(fixture.editor.checklist.node).toHaveNoViolations();\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should have no aXe violations with checks present', async () => {\n      await addPages(4);\n      await addAccessibilityIssue();\n      await openChecklist();\n      await expectAsync(fixture.editor.checklist.node).toHaveNoViolations();\n    });\n  });\n\n  describe('Checklist cursor interaction', () => {\n    it('should open the high priority section by default when 4 pages are added to the story', async () => {\n      // need to add some pages, the add page button is under the checklist so do this before expanding\n      await addPages(4);\n      await openChecklist();\n      expect(fixture.editor.checklist.priorityPanel).toBeDefined();\n    });\n\n    it('should open the design section when clicked', async () => {\n      // need to add some pages, the add page button is under the checklist so do this before expanding\n      await addPages(4);\n      await openChecklist();\n      await fixture.events.click(fixture.editor.checklist.designTab);\n      expect(fixture.editor.checklist.designPanel).toBeDefined();\n    });\n\n    it('should open the design section by default when 2 pages are added to the story', async () => {\n      // need to add some pages, the add page button is under the checklist so do this before expanding\n      await addPages(2);\n      await openChecklist();\n\n      expect(fixture.editor.checklist.designPanel).toBeDefined();\n    });\n\n    it('should open the accessibility section', async () => {\n      // need to add some pages, the add page button is under the checklist so do this before expanding\n      await addPages(2);\n      await addAccessibilityIssue();\n      await openChecklist();\n\n      await fixture.events.click(fixture.editor.checklist.accessibilityTab);\n      expect(fixture.editor.checklist.accessibilityPanel).toBeDefined();\n    });\n  });\n\n  describe('Checklist keyboard interaction', () => {\n    it('should toggle the Checklist with keyboard', async () => {\n      await fixture.events.focus(fixture.editor.checklist.toggleButton);\n      await fixture.events.keyboard.press('Enter');\n      // wait for animation\n      await fixture.events.sleep(500);\n      expect(\n        fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n      ).toBe('true');\n\n      await fixture.events.keyboard.press('Enter');\n      // wait for animation\n      await fixture.events.sleep(500);\n    });\n\n    it('should close the Checklist when pressing enter on the \"close\" button', async () => {\n      await openChecklistWithKeyboard();\n\n      // will already be focused on the close button\n      expect(\n        fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n      ).toBe('true');\n      expect(fixture.editor.checklist.closeButton).toEqual(\n        document.activeElement\n      );\n\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.sleep(500);\n    });\n\n    it('should open the tab panels with tab and enter', async () => {\n      // need to add some pages, the add page button is under the checklist so do this before expanding\n      await addPages(4);\n\n      await openChecklistWithKeyboard();\n\n      // tab to priority section\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.keyboard.press('Enter');\n      expect(fixture.editor.checklist.priorityPanel).toBeDefined();\n      expect(fixture.editor.checklist.designPanel).toBeNull();\n      expect(fixture.editor.checklist.accessibilityPanel).toBeNull();\n\n      // tab to design section\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.keyboard.press('Enter');\n      expect(fixture.editor.checklist.priorityPanel).toBeNull();\n      expect(fixture.editor.checklist.designPanel).toBeDefined();\n      expect(fixture.editor.checklist.accessibilityPanel).toBeNull();\n\n      // add accessibility section\n      await addAccessibilityIssue();\n      // tab to accessibility section\n      let tabCount = 1;\n      while (\n        tabCount < 4 &&\n        fixture.editor.checklist.accessibilityTab !== document.activeElement\n      ) {\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.keyboard.press('tab');\n        tabCount++;\n      }\n\n      await fixture.events.keyboard.press('Enter');\n      expect(fixture.editor.checklist.priorityPanel).toBeNull();\n      expect(fixture.editor.checklist.designPanel).toBeNull();\n      expect(fixture.editor.checklist.accessibilityPanel).toBeDefined();\n    });\n  });\n\n  describe('Checkpoints', () => {\n    it('empty story should begin in the empty state', async () => {\n      await openChecklist();\n\n      const { priorityPanel, designPanel, accessibilityPanel } =\n        fixture.editor.checklist;\n\n      expect(await emptyContent()).toBeDefined();\n      expect(priorityPanel).toBeNull();\n      expect(designPanel).toBeNull();\n      expect(accessibilityPanel).toBeNull();\n    });\n\n    it('should expand the design panel after adding 2 pages', async () => {\n      await addPages(1);\n      await openChecklist();\n\n      const {\n        expandedDesignTab,\n        priorityPanel,\n        designPanel,\n        accessibilityPanel,\n      } = fixture.editor.checklist;\n\n      expect(await emptyContent()).toBeNull();\n      expect(priorityPanel).toBeNull();\n      expect(designPanel).toBeDefined();\n      expect(accessibilityPanel).toBeNull();\n\n      expect(expandedDesignTab).toBeDefined();\n    });\n\n    it('should add the accessibility panel after adding 2 pages if there is an a11y problem. This will not open the panel.', async () => {\n      await addPages(1);\n      await openChecklist();\n\n      await addAccessibilityIssue();\n\n      const {\n        priorityPanel,\n        designPanel,\n        accessibilityPanel,\n        expandedDesignTab,\n      } = fixture.editor.checklist;\n\n      expect(await emptyContent()).toBeNull();\n      expect(priorityPanel).toBeNull();\n      expect(designPanel).toBeDefined();\n      expect(accessibilityPanel).toBeDefined();\n\n      expect(expandedDesignTab).toBeDefined();\n    });\n\n    it('should expand the priority panel after adding 5 pages', async () => {\n      await addPages(4);\n      await openChecklist();\n\n      const {\n        expandedPriorityTab,\n        priorityPanel,\n        designPanel,\n        accessibilityPanel,\n      } = fixture.editor.checklist;\n\n      expect(await emptyContent()).toBeNull();\n      expect(priorityPanel).toBeDefined();\n      expect(designPanel).toBeDefined();\n      expect(accessibilityPanel).toBeNull();\n\n      expect(expandedPriorityTab).toBeDefined();\n    });\n  });\n\n  describe('checklist should have no aXe accessibility violations', () => {\n    it('should have no aXe violations with with a closed checklist', async () => {\n      await expectAsync(fixture.editor.checklist.node).toHaveNoViolations();\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should have no aXe violations with an open empty checklist', async () => {\n      await openChecklist();\n\n      await expectAsync(fixture.editor.checklist.node).toHaveNoViolations();\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should have no aXe violations with a open non-empty checklist', async () => {\n      await addPages(4);\n\n      await openChecklist();\n\n      await expectAsync(fixture.editor.checklist.node).toHaveNoViolations();\n    });\n  });\n\n  it('should open the checklist after following \"checklist\" button in dialog on publishing story', async () => {\n    await fixture.events.click(fixture.editor.titleBar.publish);\n\n    const reviewButton = fixture.screen.getByRole('button', {\n      name: /^Checklist$/,\n    });\n    await fixture.events.click(reviewButton);\n\n    await waitFor(\n      () => {\n        if (!fixture.editor.checklist.issues) {\n          throw new Error('Checklist not visible yet');\n        }\n      },\n      { timeout: 2000 }\n    );\n\n    expect(\n      fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n    ).toBe('true');\n    expect(fixture.editor.checklist.priorityPanel).toBeDefined();\n  });\n});\n\ndescribe('Checklist integration - Card visibility', () => {\n  let fixture;\n\n  const priorityIssuesRequiringMediaUploadPermissions = [\n    PRIORITY_COPY.storyMissingPoster.title,\n    PRIORITY_COPY.videoMissingPoster.title,\n  ];\n\n  // issues that show if there is a poster image\n  const posterIssuesRequiringMediaUploadPermissions = [\n    PRIORITY_COPY.storyPosterSize.title,\n  ];\n\n  const designIssuesRequiringMediaUploadPermissions = [\n    DESIGN_COPY.videoResolutionTooLow.title,\n    DESIGN_COPY.imageResolutionTooLow.title,\n  ];\n\n  const accessibilityIssuesRequiringMediaUploadPermissions = [\n    ACCESSIBILITY_COPY.videoMissingCaptions.title,\n  ];\n\n  const addPages = async (count) => {\n    let clickCount = 1;\n    while (clickCount <= count) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n      // eslint-disable-next-line no-await-in-loop, no-loop-func\n      await waitFor(() => {\n        if (!fixture.editor.footer.carousel.pages.length) {\n          throw new Error('page not yet added');\n        }\n        expect(fixture.editor.footer.carousel.pages.length).toBe(\n          clickCount + 1\n        );\n      });\n      clickCount++;\n    }\n  };\n\n  const openChecklist = async () => {\n    const { toggleButton } = fixture.editor.checklist;\n    await fixture.events.click(toggleButton);\n    // wait for animation\n    await fixture.events.sleep(500);\n  };\n\n  /**\n   * Inserts an image that has\n   * - width less than the minimum allowed image width (2 times element width)\n   * - height less than the minimum allowed image height (2 times element height)\n   *\n   * This will trigger an a11y issue in the checklist.\n   */\n  const addImageWithIssues = async () => {\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    await fixture.act(() =>\n      insertElement('image', {\n        x: 0,\n        y: 0,\n        width: 640 / 2,\n        height: 529 / 2,\n        resource: {\n          id: 10,\n          type: 'image',\n          mimeType: 'image/jpg',\n          src: 'http://localhost:9876/__static__/earth.jpg',\n          alt: 'earth',\n          width: 640,\n          height: 529,\n          baseColor: '#734727',\n        },\n      })\n    );\n  };\n\n  /**\n   * Inserts a video that has\n   * - no poster image\n   * - width less than the minimum allowed video width\n   * - height less than the minimum allowed video height\n   *\n   * This will trigger an a11y issue in the checklist.\n   */\n  const addVideoWithIssues = async () => {\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    await fixture.act(() =>\n      insertElement('video', {\n        resource: {\n          type: 'video',\n          mimeType: 'video/webm',\n          creationDate: '2021-05-21T00:09:18',\n          src: 'http://localhost:8899/wp-content/uploads/2021/05/small-video-10.webm',\n          // resolution too low\n          height: 220,\n          width: 320,\n          // no poster image\n          poster: null,\n          posterId: null,\n          id: 10,\n          length: 6,\n          lengthFormatted: '0:06',\n          title: 'small-video',\n          alt: 'small-video',\n          isOptimized: false,\n          baseColor: '#734727',\n        },\n        controls: false,\n        loop: false,\n        autoPlay: true,\n        tracks: [],\n        type: 'video',\n        x: 66,\n        y: 229,\n        width: 280,\n        height: 160,\n        id: '6e7f5de8-7793-4aef-8835-c1d32477b4e0',\n      })\n    );\n  };\n\n  describe('hasUploadMediaAction=false', () => {\n    beforeEach(async () => {\n      fixture = new Fixture({\n        mocks: {\n          getStoryById: () =>\n            Promise.resolve({\n              title: { raw: '' },\n              status: 'draft',\n              author: 1,\n              slug: '',\n              date: '2020-05-06T22:32:37',\n              dateGmt: '2020-05-06T22:32:37',\n              modified: '2020-05-06T22:32:37',\n              excerpt: { raw: '' },\n              link: 'http://stories.local/?post_type=web-story&p=1',\n              previewLink: 'http://stories.local/?post_type=web-story&p=1',\n              storyData: {\n                version: DATA_VERSION,\n                pages: [],\n              },\n              featuredMedia: 2,\n              permalinkTemplate: 'http://stories3.local/stories/%pagename%/',\n              stylePresets: { textStyles: [], colors: [] },\n              password: '',\n            }),\n        },\n      });\n\n      fixture.setConfig({ capabilities: { hasUploadMediaAction: false } });\n      await fixture.render();\n    });\n\n    afterEach(() => {\n      fixture.restore();\n    });\n\n    /**\n     * Check if a card is not visible in the application.\n     *\n     * @param {string} title Title of the card\n     */\n    const checkIfCardDoesNotExist = (title) => {\n      const card = fixture.screen.queryByText(title);\n\n      expect(card).toBeNull();\n    };\n\n    it(`should not show cards that require the \\`hasUploadMediaAction\\` permission`, async () => {\n      // add issues to checklist that need to be resolved by uploading media\n      await addImageWithIssues();\n      await addVideoWithIssues();\n\n      // show all checkpoints\n      await addPages(4);\n      await openChecklist();\n\n      priorityIssuesRequiringMediaUploadPermissions.forEach(\n        checkIfCardDoesNotExist\n      );\n\n      posterIssuesRequiringMediaUploadPermissions.forEach(\n        checkIfCardDoesNotExist\n      );\n\n      // open design tab\n      await fixture.events.click(fixture.editor.checklist.designTab);\n\n      designIssuesRequiringMediaUploadPermissions.forEach(\n        checkIfCardDoesNotExist\n      );\n\n      accessibilityIssuesRequiringMediaUploadPermissions.forEach(\n        checkIfCardDoesNotExist\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/karma/firstPageAnimation.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { DESIGN_COPY } from '../constants';\nimport { useStory } from '../../../app/story';\n\ndescribe('firstPageAnimation', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    // adding animations to the first page\n    await addNewPage();\n    await addElementWithAnimation();\n    await removeFirstPage();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function addNewPage() {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.editor.library.textTab.click();\n  }\n\n  async function addElementWithAnimation() {\n    // add element\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // add animation\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.editor.sidebar.designPanel.animation;\n    const effectChooser = panel.effectChooser;\n\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n  }\n\n  async function removeFirstPage() {\n    // switch to the first page\n    const pageAtIndex = fixture.editor.footer.carousel.pages[0].node;\n    await fixture.events.click(pageAtIndex);\n\n    // delete the first page making the second page move to the first page\n    const deleteBtn = fixture.screen.getByRole('button', {\n      name: /^Delete Page$/,\n    });\n    await fixture.events.click(deleteBtn);\n  }\n\n  async function openCheckList() {\n    // now the checklist should have the FirstPageAnimation checklist item\n    // open the checklist\n    await fixture.events.click(fixture.editor.checklist.toggleButton);\n    // wait for animation\n    await fixture.events.sleep(500);\n  }\n\n  async function getCurrentPage() {\n    const page = await fixture.renderHook(() =>\n      useStory(({ state: { currentPage } }) => currentPage)\n    );\n    return page;\n  }\n\n  it('should see First Page Animation text in checklist design panel', async () => {\n    await openCheckList();\n    // open the Design tab\n    await fixture.events.click(fixture.editor.checklist.designTab);\n    // check for firstPageAnimation footer\n    const seeFirstPageAnimationText = fixture.screen.getByText(\n      new RegExp(`^${DESIGN_COPY.firstPageAnimation.footer}`)\n    );\n\n    expect(seeFirstPageAnimationText).toBeDefined();\n  });\n\n  it('should remove all first page animations when \"Remove Animations\" button is clicked', async () => {\n    // check for first page animations\n    let page = await getCurrentPage();\n    expect(page.animations.length).toBe(1);\n    await openCheckList();\n\n    // check for remove animations button\n    const seeRemoveAnimations = fixture.screen.getByText(/^Remove Animations/);\n    expect(seeRemoveAnimations).toBeDefined();\n\n    const removeAnimationsBtn = fixture.screen.getByRole('button', {\n      name: /^Remove Animations$/,\n    });\n\n    await fixture.events.click(removeAnimationsBtn);\n    page = await getCurrentPage();\n    // check that the first page animations are removed\n    expect(Boolean(page.animations?.length)).toBeFalsy();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/karma/prepublishSelect.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app';\nimport { useInsertElement } from '../../canvas';\nimport { ACCESSIBILITY_COPY, DESIGN_COPY, PRIORITY_COPY } from '../constants';\n\ndescribe('Pre-publish checklist select offending elements onClick', () => {\n  let fixture;\n  let insertElement;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    insertElement = await fixture.renderHook(() => useInsertElement());\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const openChecklist = async () => {\n    const { toggleButton } = fixture.editor.checklist;\n    await fixture.events.click(toggleButton);\n    // wait for animation\n    await fixture.events.sleep(500);\n  };\n\n  const addPages = async (count) => {\n    let clickCount = 1;\n    while (clickCount <= count) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n      // eslint-disable-next-line no-await-in-loop, no-loop-func\n      await waitFor(() => {\n        if (!fixture.editor.footer.carousel.pages.length) {\n          throw new Error('page not yet added');\n        }\n        expect(fixture.editor.footer.carousel.pages.length).toBe(\n          clickCount + 1\n        );\n      });\n      clickCount++;\n    }\n  };\n\n  async function clickOnCanvas() {\n    const canvas = fixture.querySelector('[data-testid=\"fullbleed\"]');\n    await fixture.events.click(canvas);\n  }\n\n  describe('Checklist interactions', () => {\n    it('should select the offending text elements', async () => {\n      await addPages(1);\n      // four paragraphs will cause the \"too much text on page\" error\n      const doInsert = () =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          fontSize: 14,\n          content:\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',\n          x: 40,\n          y: 40,\n          width: 250,\n        });\n\n      const element1 = await fixture.act(doInsert);\n      const element2 = await fixture.act(doInsert);\n      const element3 = await fixture.act(doInsert);\n      const element4 = await fixture.act(doInsert);\n      await openChecklist();\n\n      expect(fixture.editor.checklist.designPanel).toBeDefined();\n\n      let storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(1);\n\n      const tooMuchTextOnTitle = fixture.screen.getByText(\n        DESIGN_COPY.tooMuchPageText.title\n      );\n      // Use title to get to thumbnail in card\n      const { getByRole } = within(\n        tooMuchTextOnTitle.parentElement.parentElement\n      );\n      const thumbnail = getByRole('button');\n      expect(thumbnail).toBeDefined();\n      await fixture.events.click(thumbnail);\n      await fixture.events.sleep(500);\n      storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(4);\n      expect(\n        [element1, element2, element3, element4].map(({ id }) => id)\n      ).toEqual(storyContext.state.selectedElementIds);\n    });\n\n    it('should select the element when the font size is too small', async () => {\n      await addPages(1);\n\n      const insertSmallFont = () =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          fontSize: 9,\n          content: 'Lorem ipsum.',\n          x: 40,\n          y: 40,\n          width: 250,\n        });\n\n      const insertNormalFont = () =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          fontSize: 20,\n          content: 'Lorem ipsum.',\n          x: 100,\n          y: 40,\n          width: 250,\n        });\n\n      const smallFontElement = await fixture.act(insertSmallFont);\n      const normalFontElement = await fixture.act(insertNormalFont);\n\n      await openChecklist();\n\n      await fixture.events.click(fixture.editor.checklist.accessibilityTab);\n\n      let storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(1);\n      expect(storyContext.state.selectedElementIds[0]).toEqual(\n        normalFontElement.id\n      );\n      const fontTooSmallTitle = fixture.screen.getByText(\n        ACCESSIBILITY_COPY.fontSizeTooSmall.title\n      );\n      // Use title to get to thumbnail in card\n      const { getByRole } = within(\n        fontTooSmallTitle.parentElement.parentElement\n      );\n      const thumbnail = getByRole('button');\n      expect(thumbnail).toBeDefined();\n      await fixture.events.click(thumbnail);\n      await fixture.events.click(fontTooSmallTitle);\n      await fixture.events.sleep(500);\n      storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds[0]).toEqual(\n        smallFontElement.id\n      );\n    });\n\n    it('should select link elements when they are too small to tap', async () => {\n      const tooSmallLinkElement = await fixture.act(() =>\n        insertElement('text', {\n          id: 'elementid',\n          type: 'text',\n          link: {\n            url: 'https://google.com',\n          },\n          content: 'G',\n          width: 40,\n          height: 40,\n        })\n      );\n      await clickOnCanvas();\n      let storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(1);\n      expect(storyContext.state.selectedElementIds[0]).not.toEqual(\n        tooSmallLinkElement.id\n      );\n\n      await openChecklist();\n      await fixture.events.click(fixture.editor.checklist.accessibilityTab);\n\n      const linkTooSmallTitle = fixture.screen.getByText(\n        ACCESSIBILITY_COPY.linkTappableRegionTooSmall.title\n      );\n      // Use title to get to thumbnail in card\n      const { getByRole } = within(\n        linkTooSmallTitle.parentElement.parentElement\n      );\n      const thumbnail = getByRole('button');\n      expect(thumbnail).toBeDefined();\n      await fixture.events.click(thumbnail);\n      await fixture.events.sleep(500);\n      storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds[0]).toEqual(\n        tooSmallLinkElement.id\n      );\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should select the element with the keyboard', async () => {\n      await addPages(4);\n      const tooSmallLinkElement = await fixture.act(() =>\n        insertElement('text', {\n          id: 'elementid',\n          type: 'text',\n          link: {\n            url: 'https://google.com',\n          },\n          content: 'S',\n          width: 40,\n          height: 40,\n        })\n      );\n\n      await clickOnCanvas();\n\n      let storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(1);\n      expect(storyContext.state.selectedElementIds[0]).not.toEqual(\n        tooSmallLinkElement.id\n      );\n\n      await openChecklist();\n\n      await fixture.events.keyboard.press('tab');\n      // Collapse priority panel which is expanded by default\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('tab');\n      // Navigate to accessibility panel\n      await fixture.events.keyboard.press('tab');\n      // Expand panel\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.keyboard.press('Enter');\n\n      storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds.length).toEqual(1);\n      expect(storyContext.state.selectedElementIds[0]).toEqual(\n        tooSmallLinkElement.id\n      );\n    });\n\n    it('should open the style pane and focus the text input', async () => {\n      await fixture.act(() => {\n        insertElement('image', {\n          x: 0,\n          y: 0,\n          width: 640 / 2,\n          height: 529 / 2,\n          resource: {\n            id: 10,\n            type: 'image',\n            mimeType: 'image/jpg',\n            src: 'http://localhost:9876/__static__/earth.jpg',\n            alt: '',\n            width: 640,\n            height: 529,\n            baseColor: '#734727',\n          },\n        });\n      });\n\n      await addPages(2);\n      await openChecklist();\n      await fixture.events.click(fixture.editor.checklist.accessibilityTab);\n      const imageMissingAltTextTitle = fixture.screen.getByText(\n        ACCESSIBILITY_COPY.imagesMissingAltText.title\n      );\n      // Use title to get to thumbnail in card\n      const { getByRole } = within(\n        imageMissingAltTextTitle.parentElement.parentElement\n      );\n      const thumbnail = getByRole('button');\n      expect(thumbnail).toBeDefined();\n      await fixture.events.click(thumbnail);\n      await fixture.events.sleep(500);\n      expect(\n        fixture.editor.sidebar.designPanel.node.contains(document.activeElement)\n      ).toBeTrue();\n      await fixture.snapshot(\n        'design tab opened and focused by checklist panel'\n      );\n    });\n\n    it('should open the design panel accessibility section and focus the video poster button when using mouse', async () => {\n      await fixture.act(() => {\n        insertElement('video', {\n          x: 0,\n          y: 0,\n          width: 640 / 2,\n          height: 529 / 2,\n          resource: {\n            width: 640,\n            height: 529,\n            type: 'video',\n            mimeType: 'video/mp4',\n            src: 'http://localhost:9876/__static__/beach.mp4',\n            alt: 'Beach',\n          },\n        });\n      });\n\n      await addPages(5);\n      await openChecklist();\n      // high priority should auto expand\n      const videoMissingPosterTitle = fixture.screen.getByText(\n        PRIORITY_COPY.videoMissingPoster.title\n      );\n\n      expect(videoMissingPosterTitle).toBeDefined();\n      // Use title to get to thumbnail in card\n      const { getByRole } = within(\n        videoMissingPosterTitle.parentElement.parentElement\n      );\n      const thumbnail = getByRole('button');\n      expect(thumbnail).toBeDefined();\n      await fixture.events.click(thumbnail);\n      await fixture.events.sleep(500);\n\n      const mediaButton =\n        await fixture.editor.sidebar.designPanel.videoAccessibility\n          .posterMenuButton;\n      expect(mediaButton.contains(document.activeElement)).toBeTrue();\n\n      await fixture.snapshot(\n        'design tab opened accessibility and focused on video poster button by checklist panel'\n      );\n    });\n\n    it('should open the design panel accessibility section and focus the video poster button when using keyboard', async () => {\n      await fixture.act(() => {\n        insertElement('video', {\n          x: 0,\n          y: 0,\n          width: 640 / 2,\n          height: 529 / 2,\n          resource: {\n            width: 640,\n            height: 529,\n            type: 'video',\n            mimeType: 'video/mp4',\n            src: 'http://localhost:9876/__static__/beach.mp4',\n            alt: 'Beach',\n          },\n        });\n      });\n\n      await addPages(4);\n      await openChecklist();\n      // high priority should auto expand\n      // tab to card\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n\n      // press enter on video preview in card\n      await fixture.events.keyboard.press('Enter');\n\n      const mediaButton =\n        await fixture.editor.sidebar.designPanel.videoAccessibility\n          .posterMenuButton;\n      expect(mediaButton.contains(document.activeElement)).toBeTrue();\n\n      await fixture.snapshot(\n        'design tab opened accessibility and focused on video poster button by checklist panel'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/popupMountedContext.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useChecklist } from './checklistContext';\n\nexport function useIsChecklistMounted() {\n  return useChecklist(({ state }) => state.isChecklistMounted);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { Checklist } from '..';\nimport { noop } from '../../../utils/noop';\nimport Popup, { NavigationWrapper, TopNavigation } from '../../secondaryPopup';\nimport { EmptyContent } from '../checklistContent';\n\nexport default {\n  title: 'Stories Editor/Components/Checklist',\n  component: Checklist,\n};\n\nconst Page = styled.div`\n  position: relative;\n  display: flex;\n  align-items: flex-end;\n  height: 300px;\n  width: 900px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Container = styled.div`\n  position: relative;\n  margin-left: 20px;\n  margin-bottom: 10px;\n`;\n\nexport const EmptyState = () => {\n  return (\n    <Page>\n      <Container>\n        <Popup\n          popupId={'1234'}\n          isOpen\n          ariaLabel={__('Checklist', 'web-stories')}\n        >\n          <NavigationWrapper>\n            <TopNavigation\n              onClose={noop}\n              label={__('Checklist', 'web-stories')}\n              popupId={'1234'}\n            />\n            <EmptyContent />\n          </NavigationWrapper>\n        </Popup>\n      </Container>\n    </Page>\n  );\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { TablistPanel } from '../tablist';\nimport {\n  DISTANCE_FROM_TOP,\n  DISTANCE_FROM_BOTTOM,\n  NAVIGATION_HEIGHT,\n} from '../secondaryPopup';\n\nconst BUTTON_HEIGHT = 60;\nexport const getTabPanelMaxHeight = (buttonCount) => {\n  if (!buttonCount) {\n    return undefined;\n  }\n\n  return `100vh - ${\n    NAVIGATION_HEIGHT +\n    buttonCount * BUTTON_HEIGHT +\n    DISTANCE_FROM_TOP +\n    DISTANCE_FROM_BOTTOM\n  }px`;\n};\n\nexport const StyledTablistPanel = styled(TablistPanel)`\n  height: ${({ badgeCount }) => (badgeCount === 0 ? 0 : 'auto')};\n  visibility: ${({ badgeCount }) => (badgeCount === 0 ? 'hidden' : 'visible')};\n\n  button {\n    display: ${({ badgeCount }) => (badgeCount === 0 ? 'none' : 'auto')};\n  }\n`;\n\nexport const PanelText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/toggle/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ToggleButton } from '../../toggleButton';\nimport { useCategoryCount } from '../countContext';\nimport { useCheckpoint } from '../checkpointContext';\nimport { ISSUE_TYPES, PPC_CHECKPOINT_STATE } from '../constants';\nimport { noop } from '../../../utils/noop';\n\nfunction Toggle({ isOpen = false, popupId = '', onClick = noop }) {\n  const priorityCount = useCategoryCount(ISSUE_TYPES.PRIORITY);\n\n  const { checkpoint } = useCheckpoint(({ state: { checkpoint } }) => ({\n    checkpoint,\n  }));\n\n  const notificationCount = useMemo(\n    () => (checkpoint === PPC_CHECKPOINT_STATE.ALL ? priorityCount : 0),\n    [checkpoint, priorityCount]\n  );\n\n  return (\n    <ToggleButton\n      aria-owns={popupId}\n      onClick={onClick}\n      isOpen={isOpen}\n      MainIcon={Icons.Checkbox}\n      label={__('Checklist', 'web-stories')}\n      aria-label={\n        notificationCount > 0\n          ? sprintf(\n              /* translators: %s:  number of unaddressed issues. */\n              _n(\n                'Checklist: %s unaddressed issue',\n                'Checklist: %s unaddressed issues',\n                notificationCount,\n                'web-stories'\n              ),\n              notificationCount\n            )\n          : __('Checklist', 'web-stories')\n      }\n      notificationCount={notificationCount}\n    />\n  );\n}\n\nToggle.propTypes = {\n  isOpen: PropTypes.bool,\n  popupId: PropTypes.string,\n  onClick: PropTypes.func,\n};\n\nexport { Toggle };\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/characterCountForPage.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { stripHTML } from '@googleforcreators/dom';\n\nexport function characterCountForPage(page) {\n  let characterCount = 0;\n  page.elements.forEach((element) => {\n    if (element.type === 'text') {\n      characterCount += stripHTML(element.content).length;\n    }\n  });\n  return characterCount;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/filterStoryElements.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\n/**\n * Filters through story elements with array.filter\n *\n * @param {Array<Page>} pages The story pages to filter\n * @param {Function} filter The page being checked for guidelines\n * @return {Array<any>} An array of elements that contain a pageId property\n */\nexport function filterStoryElements(pages, filter) {\n  return (pages || [])\n    .flatMap((page) =>\n      (page?.elements || []).map((element) => ({ ...element, pageId: page.id }))\n    )\n    .filter(filter);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/filterStoryPages.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {import('@googleforcreators/elements').Page} Page\n */\n\n/**\n * Filters through story pages with array.filter\n *\n * @param {Array<Page>} pages The story to filter\n * @param {Function} filter The page being checked for guidelines\n * @return {Array<Page>} An array of pages that\n */\nexport function filterStoryPages(pages, filter) {\n  return (pages || []).filter(filter);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/getVisibleThumbnails.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { THUMBNAIL_COUNT_FOR_OVERFLOW, THUMBNAIL_MAX } from '../constants';\n\nexport function getVisibleThumbnails(items) {\n  if (items.length > THUMBNAIL_MAX) {\n    return items.slice(0, THUMBNAIL_COUNT_FOR_OVERFLOW);\n  }\n  return items;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/hasNoFeaturedMedia.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport function hasNoFeaturedMedia(story) {\n  return (story.featuredMedia?.url?.trim() || '') === '';\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { hasNoFeaturedMedia } from './hasNoFeaturedMedia';\nexport { characterCountForPage } from './characterCountForPage';\nexport { filterStoryPages } from './filterStoryPages';\nexport { filterStoryElements } from './filterStoryElements';\nexport { getVisibleThumbnails } from './getVisibleThumbnails';\nexport { ThumbnailPagePreview } from './thumbnailPagePreview';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/test/filterStoryElements.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { filterStoryElements } from '..';\n\ndescribe('filterStoryElements', () => {\n  it('returns array of passing elements with pageId property appended', () => {\n    expect(\n      filterStoryElements(\n        [\n          { id: 1, elements: [{ id: 'a' }, { id: 'b' }, { id: 'c' }] },\n          { id: 2, elements: [{ id: 'd' }, { id: 'e' }] },\n        ],\n\n        (element) => ['b', 'c', 'd'].includes(element.id)\n      )\n    ).toStrictEqual([\n      { id: 'b', pageId: 1 },\n      { id: 'c', pageId: 1 },\n      { id: 'd', pageId: 2 },\n    ]);\n  });\n\n  it('returns an empty array if story has no elements', () => {\n    expect(\n      filterStoryElements([{ id: 1 }, { id: 2 }], () => true)\n    ).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/test/filterStoryPages.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { filterStoryPages } from '..';\n\ndescribe('filterStoryPages', () => {\n  it('returns array of passing pages', () => {\n    expect(\n      filterStoryPages(\n        [\n          { id: 1, elements: [{ id: 'a' }, { id: 'b' }, { id: 'c' }] },\n          { id: 2, elements: [{ id: 'd' }, { id: 'e' }] },\n        ],\n        (page) => page.id > 1\n      )\n    ).toStrictEqual([{ id: 2, elements: [{ id: 'd' }, { id: 'e' }] }]);\n  });\n\n  it('returns an empty array if story has no pages', () => {\n    expect(filterStoryPages([], () => true)).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/checklist/utils/thumbnailPagePreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../../propTypes';\nimport PagePreview from '../../footer/pagepreview';\nimport { THUMBNAIL_DIMENSIONS } from '../../thumbnail';\n\nexport const ThumbnailPagePreview = ({ page }) => (\n  <PagePreview\n    page={page}\n    width={THUMBNAIL_DIMENSIONS.WIDTH}\n    height={THUMBNAIL_DIMENSIONS.HEIGHT}\n    as=\"div\"\n    help=\"checklist\"\n    isActive\n    className=\"pagePreviewOverrides\"\n  />\n);\nThumbnailPagePreview.propTypes = {\n  page: StoryPropTypes.page.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/checkboxCta.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Checkbox } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { CheckboxCtaContainer, CheckboxCtaLabel } from './styles';\n\nexport const CheckboxCta = ({ id, children, ...rest }) => (\n  <CheckboxCtaContainer>\n    <Checkbox id={id} {...rest} />\n    <CheckboxCtaLabel htmlFor={id}>{children}</CheckboxCtaLabel>\n  </CheckboxCtaContainer>\n);\nCheckboxCta.propTypes = {\n  id: PropTypes.string.isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n    PropTypes.string,\n  ]),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/checklistCard.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Headline, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport ThumbnailWrapper from '../checklist/checks/shared/thumbnailWrapper';\nimport { getGridVariant } from './helpers';\nimport { CARD_TYPE } from './constants';\nimport { Wrapper, Container, Title, Cta, Footer } from './styles';\n\n/**\n *\n * @param {Object} props Component props.\n * @param {string} props.cardType the type of card  getting rendered. Selected from constants > CARD_TYPE, defaults to SINGLE_ISSUE.\n * @param {string} props.className the className to be passed to the outermost element.\n * @param {string}  props.title text to display as title of card.\n * @param {Object}  props.titleProps if an object is passed in it should have an onClick, these are so that issues can have buttons as titles.\n * @param {Node} props.footer will  be rendered in the footer section of a card.\n * @param {Node} props.cta will be rendered as the cta section of a card.\n * @param {Node}  props.thumbnails array of thumbnails to be rendered in the thumbnail section of the card\n * @return {Node} card to display.\n */\nconst ChecklistCard = ({\n  cardType = CARD_TYPE.SINGLE_ISSUE,\n  className,\n  title,\n  titleProps,\n  footer,\n  cta,\n  thumbnails,\n}) => {\n  let thumbnailCount = 0;\n  if (thumbnails) {\n    thumbnailCount = Array.isArray(thumbnails) ? thumbnails.length : 1;\n  }\n\n  const gridVariant = getGridVariant({\n    cardType,\n    thumbnailCount,\n    hasCta: Boolean(cta),\n  });\n\n  return (\n    <Wrapper className={className}>\n      <Container gridVariant={gridVariant}>\n        <Title as={titleProps?.onClick ? 'button' : 'div'} {...titleProps}>\n          <Headline size={TextSize.XXXSmall} as=\"h2\">\n            {title}\n          </Headline>\n        </Title>\n        <ThumbnailWrapper>{thumbnails}</ThumbnailWrapper>\n        <Cta>{cta}</Cta>\n        <Footer>{footer}</Footer>\n      </Container>\n    </Wrapper>\n  );\n};\n\nChecklistCard.propTypes = {\n  cardType: PropTypes.oneOf(Object.values(CARD_TYPE)),\n  className: PropTypes.string,\n  cta: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n    PropTypes.bool,\n  ]),\n  footer: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n    PropTypes.bool,\n  ]),\n  thumbnails: PropTypes.oneOfType([\n    PropTypes.node,\n    PropTypes.arrayOf(PropTypes.node),\n  ]),\n  title: PropTypes.string.isRequired,\n  titleProps: PropTypes.shape({ onClick: PropTypes.func }),\n};\n\nexport default ChecklistCard;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const CARD_TYPE = {\n  SINGLE_ISSUE: 'single_issue',\n  MULTIPLE_ISSUE: 'multiple_issue',\n};\nexport const GRID_VARIANT = {\n  SINGLE_WITH_THUMBNAIL: 'single_with_thumbnail',\n  SINGLE: 'single',\n  DEFAULT: 'single',\n  MULTIPLE_WITH_THUMBNAIL: 'multiple_with_thumbnail',\n  MULTIPLE_WITH_THUMBNAIL_WITH_CTA: 'multiple_with_thumbnail_with_cta',\n  MULTIPLE_WITH_THUMBNAIL_OVERFLOW: ' multiple_with_thumbnail_overflow',\n};\n\nexport const GRID_TEMPLATE_AREA = {\n  [GRID_VARIANT.SINGLE]:\n    \"'title title title title' 'cta cta cta thumbnail' 'footer footer footer footer'\",\n  [GRID_VARIANT.SINGLE_WITH_THUMBNAIL]:\n    \"'title title title thumbnail' 'cta cta cta thumbnail' 'footer footer footer footer'\",\n  [GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL]:\n    \"'title title title title' 'thumbnail thumbnail thumbnail thumbnail' 'footer footer footer footer'\",\n  [GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_WITH_CTA]:\n    \"'title title title title' 'thumbnail thumbnail thumbnail thumbnail' 'cta cta cta cta' 'footer footer footer footer'\",\n  [GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_WITH_CTA_OVERFLOW]:\n    \"'title title title title' 'thumbnail thumbnail thumbnail thumbnail' 'cta cta cta cta' 'footer footer footer footer'\",\n  [GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_OVERFLOW]:\n    \"'title title title title' 'thumbnail thumbnail thumbnail thumbnail' 'footer footer footer footer'\",\n};\n\nexport const MAX_THUMBNAILS_DISPLAYED = 3;\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/defaultCtaButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n} from '@googleforcreators/design-system';\n\nexport const DefaultCtaButton = ({ children, ...rest }) => (\n  <Button size={ButtonSize.Small} type={ButtonType.Secondary} {...rest}>\n    {children}\n  </Button>\n);\n\nDefaultCtaButton.propTypes = {\n  children: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/defaultFooterText.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nexport const DefaultFooterText = ({ children, ...rest }) => (\n  <Text.Paragraph size={TextSize.XSmall} {...rest}>\n    {children}\n  </Text.Paragraph>\n);\n\nDefaultFooterText.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/helpers/getGridVariant.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { CARD_TYPE, GRID_VARIANT } from '../constants';\n\n/**\n *\n * @param {Object} props props passed to function\n * @param {string} props.cardType type of card getting rendered.\n * @param {number} props.thumbnailCount how many thumbnails are getting rendered inside the card, defaults to 0.\n * @param {boolean} props.hasCta whether or not a card has a cta.\n * @return {string} type of card.\n */\nexport const getGridVariant = ({ cardType, thumbnailCount, hasCta }) => {\n  if (cardType === CARD_TYPE.SINGLE_ISSUE) {\n    return thumbnailCount > 0\n      ? GRID_VARIANT.SINGLE_WITH_THUMBNAIL\n      : GRID_VARIANT.SINGLE;\n  }\n\n  if (cardType === CARD_TYPE.MULTIPLE_ISSUE) {\n    if (!thumbnailCount) {\n      return GRID_VARIANT.DEFAULT;\n    }\n    if (hasCta) {\n      return thumbnailCount <= 4\n        ? GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_WITH_CTA\n        : GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_WITH_CTA_OVERFLOW;\n    }\n    return thumbnailCount <= 4\n      ? GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL\n      : GRID_VARIANT.MULTIPLE_WITH_THUMBNAIL_OVERFLOW;\n  }\n  return GRID_VARIANT.DEFAULT;\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/helpers/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { getGridVariant } from './getGridVariant';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as ChecklistCardStyles from './styles';\n\nexport { default as ChecklistCard } from './checklistCard';\nexport * from './constants';\nexport { ChecklistCardStyles };\nexport { DefaultCtaButton } from './defaultCtaButton';\nexport { DefaultFooterText } from './defaultFooterText';\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  TextSize,\n  Text,\n  Link,\n  List,\n  Tooltip as BaseTooltip,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { THUMBNAIL_BG } from '../../thumbnail/stories/demoThumbnails';\nimport { CARD_TYPE } from '../constants';\nimport { CardListWrapper, StyledVideoOptimizationIcon } from '../styles';\nimport { DefaultCtaButton } from '../defaultCtaButton';\nimport { DefaultFooterText } from '../defaultFooterText';\nimport { ChecklistCard } from '..';\nimport { CheckboxCta } from '../checkboxCta';\n\nexport default {\n  title: 'Stories Editor/Components/ChecklistCard',\n  component: ChecklistCard,\n  parameters: {\n    controls: { hideNoControlsWarning: true },\n  },\n};\n\nconst Container = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  display: flex;\n  flex-wrap: wrap;\n  padding: 16px;\n  width: 900px;\n\n  & > div {\n    margin: 0 8px 16px;\n  }\n`;\n\nexport const _default = {\n  render: function Render() {\n    const getThumbnails = (numOfThumbnails) => {\n      const thumbnails = [];\n      let index = 0;\n      while (numOfThumbnails > index) {\n        thumbnails.push(\n          <Thumbnail\n            key={index}\n            type={THUMBNAIL_TYPES.IMAGE}\n            displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n            aria-label=\"my helper text describing this thumbnail image\"\n          >\n            <BaseTooltip title=\"Optimize\">\n              <StyledVideoOptimizationIcon />\n            </BaseTooltip>\n          </Thumbnail>\n        );\n        index++;\n      }\n      return thumbnails;\n    };\n\n    return (\n      <Container>\n        <div>\n          <Text.Paragraph>{'Single Issue'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Add video captions\"\n            footer={\n              <DefaultFooterText>\n                {\n                  'Keep the audience engaged even when they can’t listen to the audio. '\n                }\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n            thumbnailCount={1}\n            thumbnails={getThumbnails(1)}\n          />\n        </div>\n        <div>\n          <Text.Paragraph>{'Single Issue - No CTA'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Add video captions\"\n            footer={\n              <DefaultFooterText>\n                {\n                  'Keep the audience engaged even when they can’t listen to the audio. '\n                }\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            thumbnailCount={1}\n            thumbnails={getThumbnails(1)}\n          />\n        </div>\n        <div>\n          <Text.Paragraph>{'Single Issue - No Thumbnail'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Increase size of publisher logo to at least 96x96px\"\n            footer={\n              <DefaultFooterText>\n                {'Maintain a 1:1 aspect ratio. '}\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n          />\n        </div>\n        <div>\n          <Text.Paragraph>\n            {'Single Issue - No Thumbnail or CTA'}\n          </Text.Paragraph>\n          <ChecklistCard\n            title=\"Add Web Story title\"\n            footer={\n              <DefaultFooterText>\n                {'Keep title under 40 characters. '}\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n          />\n        </div>\n        <div>\n          <Text.Paragraph>\n            {'Single Issue - No Thumbnail with a list'}\n          </Text.Paragraph>\n          <ChecklistCard\n            title=\"Add Web Story poster image\"\n            footer={\n              <CardListWrapper>\n                <List>\n                  <li>{'Use as a representation of the story.'}</li>\n                  <li>{'Avoid images with embedded text.'}</li>\n                  <li>{\"Use an image that's at least 640x853px.\"}</li>\n                  <li>{'Maintain a 3:4 aspect ratio.'}</li>\n                </List>\n\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </CardListWrapper>\n            }\n            cta={<DefaultCtaButton>{'Upload'}</DefaultCtaButton>}\n          />\n        </div>\n        <div>\n          <Text.Paragraph>{'Multiple Issues - No CTA'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Add video captions\"\n            footer={\n              <DefaultFooterText>\n                {\n                  'Keep the audience engaged even when they can’t listen to the audio. '\n                }\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cardType={CARD_TYPE.MULTIPLE_ISSUE}\n            thumbnailCount={3}\n            thumbnails={getThumbnails(3)}\n          />\n        </div>\n        <div>\n          <Text.Paragraph>{'Multiple Issues'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Add video captions\"\n            cta={<DefaultCtaButton>{'Fix everything'}</DefaultCtaButton>}\n            footer={\n              <DefaultFooterText>\n                {\n                  'Keep the audience engaged even when they can’t listen to the audio. '\n                }\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cardType={CARD_TYPE.MULTIPLE_ISSUE}\n            thumbnailCount={3}\n            thumbnails={getThumbnails(3)}\n          />\n        </div>\n\n        <div>\n          <Text.Paragraph>{'Multiple Issues - 4'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Videos not optimized\"\n            cta={\n              <>\n                <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                  {'Optimize all videos'}\n                </DefaultCtaButton>\n                <CheckboxCta\n                  id=\"demo-optimize\"\n                  aria-label=\"check this box to optimize videos by default\"\n                >\n                  {'Enable auto optimization'}\n                </CheckboxCta>\n              </>\n            }\n            footer={\n              <DefaultFooterText>\n                {'Unoptimized video may cause playback issues. '}\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cardType={CARD_TYPE.MULTIPLE_ISSUE}\n            thumbnailCount={4}\n            thumbnails={getThumbnails(4)}\n          />\n        </div>\n\n        <div>\n          <Text.Paragraph>{'Video Optimization - more than 4'}</Text.Paragraph>\n          <ChecklistCard\n            title=\"Videos not optimized\"\n            cta={\n              <>\n                <DefaultCtaButton>{'Optimize all videos'}</DefaultCtaButton>\n                <CheckboxCta\n                  id=\"demo-optimize\"\n                  aria-label=\"check this box to optimize videos by default\"\n                >\n                  {'Enable auto optimization'}\n                </CheckboxCta>\n              </>\n            }\n            footer={\n              <DefaultFooterText>\n                {'Unoptimized video may cause playback issues. '}\n                <Link href=\"/demo\" size={TextSize.XSmall}>\n                  {'Learn more'}\n                </Link>\n              </DefaultFooterText>\n            }\n            cardType={CARD_TYPE.MULTIPLE_ISSUE}\n            thumbnailCount={6}\n            thumbnails={getThumbnails(6)}\n          />\n        </div>\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/checklistCard/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  Icons,\n  TextSize,\n  Text,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { CARD_WIDTH } from '../secondaryPopup';\nimport { OverflowThumbnail } from '../thumbnail';\nimport { GRID_TEMPLATE_AREA, GRID_VARIANT } from './constants';\n\nconst { focusableOutlineCSS } = themeHelpers;\n\nexport const Wrapper = styled.div`\n  width: ${CARD_WIDTH}px;\n  display: flex;\n  border-radius: 4px;\n  background: ${({ theme }) => theme.colors.bg.secondary};\n  margin: 8px 0;\n`;\n\nexport const Container = styled.div`\n  width: 240px;\n  display: grid;\n  margin: 16px;\n  grid-gap: 8px;\n  grid-template-columns: 52px 52px 52px 52px;\n  ${({ gridVariant }) => css`\n    grid-template-areas: ${GRID_TEMPLATE_AREA[gridVariant]};\n  `}\n`;\nContainer.propTypes = {\n  gridVariant: PropTypes.oneOf(Object.values(GRID_VARIANT)),\n};\n\n// Titles can be divs or buttons. Buttons are for if there is an action for the user to take (like highlighting)\nexport const Title = styled.div`\n  grid-area: title;\n\n  &:is(button) {\n    display: flex;\n    outline: none;\n    margin: 0;\n    padding: 0;\n    background-color: transparent;\n    border: none;\n    text-align: left;\n    cursor: pointer;\n    border-radius: ${({ theme }) => theme.borders.radius.small};\n    ${({ theme }) =>\n      focusableOutlineCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nexport const Cta = styled.div`\n  grid-area: cta;\n  margin: 0;\n`;\n\nexport const CheckboxCtaLabel = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.linkNormal};\n`;\n\nexport const CheckboxCtaContainer = styled.div`\n  display: flex;\n  align-items: center;\n  margin: 14px 0 6px;\n  label {\n    margin: 0 8px;\n  }\n`;\n\nexport const StyledOverflowThumbnail = styled(OverflowThumbnail)`\n  width: 52px;\n  cursor: pointer;\n`;\n\nexport const Footer = styled.div`\n  grid-area: footer;\n  padding-top: 8px;\n  border-top: 1px solid ${({ theme }) => theme.colors.divider.primary};\n\n  & > * {\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\n\n// For use with lists\nexport const CardListWrapper = styled.div`\n  margin-left: 16px;\n  li {\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\n\nexport const StyledVideoOptimizationIcon = styled(Icons.GearWithGauge)`\n  rect {\n    color: ${({ theme }) => theme.colors.opacity.black64};\n  }\n\n  path {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/addCustomColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { PatternPropType } from '@googleforcreators/patterns';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../app/story/useStory';\nimport getUniquePresets from '../../utils/getUniquePresets';\n\nconst StyledButton = styled(Button)`\n  flex: 0 0 32px;\n  margin: 0 16px 16px;\n`;\n\nfunction AddCustomColor({ color, onSave }) {\n  const { updateStory, globalStoryStyles } = useStory(\n    ({\n      state: {\n        story: { globalStoryStyles },\n      },\n      actions: { updateStory },\n    }) => ({\n      globalStoryStyles,\n      updateStory,\n    })\n  );\n\n  const handleAddSavedColor = useCallback(() => {\n    updateStory({\n      properties: {\n        globalStoryStyles: {\n          ...globalStoryStyles,\n          colors: getUniquePresets(\n            [...globalStoryStyles.colors, color].filter(Boolean)\n          ),\n        },\n      },\n    });\n    onSave();\n  }, [onSave, color, globalStoryStyles, updateStory]);\n\n  return (\n    <StyledButton\n      onClick={handleAddSavedColor}\n      type={ButtonType.Secondary}\n      size={ButtonSize.Small}\n      variant={ButtonVariant.Rectangle}\n    >\n      {__('Add to Saved Colors', 'web-stories')}\n    </StyledButton>\n  );\n}\n\nAddCustomColor.propTypes = {\n  onSave: PropTypes.func,\n  color: PatternPropType,\n};\n\nexport default AddCustomColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/basicColorList.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  PatternPropType,\n  generatePatternStyles,\n  hasOpacity,\n  hasGradient,\n} from '@googleforcreators/patterns';\nimport { Icons, Swatch, themeHelpers } from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport useRovingTabIndex from '../../utils/useRovingTabIndex';\nimport Tooltip from '../tooltip';\nimport ColorAdd from './colorAdd';\n\nconst focusStyle = css`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst SwatchList = styled.div.attrs({ role: 'listbox' })`\n  display: flex;\n  max-width: 100%;\n  flex-wrap: wrap;\n  gap: 6px;\n`;\n\nconst StyledSwatch = styled(Swatch).attrs(({ isSelected }) => ({\n  role: 'option',\n  'aria-selected': isSelected,\n}))`\n  ${focusStyle};\n\n  ${({ isSelected, theme }) =>\n    isSelected &&\n    css`\n      border: 2px solid ${theme.colors.border.defaultActive};\n    `}\n`;\n\nfunction getPatternAsString(pattern) {\n  if (!pattern) {\n    return '';\n  }\n  const styles = generatePatternStyles(pattern);\n  return styles.backgroundColor || styles.backgroundImage;\n}\n\nfunction ConditionalTooltip({ tooltip, children }) {\n  if (!tooltip) {\n    return children;\n  }\n  return <Tooltip title={tooltip}>{children}</Tooltip>;\n}\n\nConditionalTooltip.propTypes = {\n  tooltip: PropTypes.string,\n  children: PropTypes.node.isRequired,\n};\n\nfunction BasicColorList({\n  color,\n  colors,\n  handleClick,\n  allowsOpacity,\n  allowsGradient,\n  isLocal = false,\n  isGlobal = false,\n  isEditMode,\n  changedStyle,\n  ...rest\n}) {\n  const colorAsBackground = getPatternAsString(color);\n  const listRef = useRef(null);\n\n  useRovingTabIndex({ ref: listRef });\n\n  const selectedSwatchIndex = colors\n    .map(getPatternAsString)\n    .findIndex((c) => colorAsBackground === c);\n\n  let firstIndex = 0;\n  const colorType = isLocal\n    ? __('local', 'web-stories')\n    : __('global', 'web-stories');\n\n  const isBackground = changedStyle === 'background';\n\n  return (\n    <>\n      {colors.length > 0 && (\n        <SwatchList ref={listRef} {...rest}>\n          {colors.map((pattern, i) => {\n            const isTransparentAndInvalid =\n              !allowsOpacity && hasOpacity(pattern);\n            const isGradientAndInvalid =\n              !allowsGradient && hasGradient(pattern);\n            const isDisabled =\n              (isTransparentAndInvalid || isGradientAndInvalid) && !isEditMode;\n            let tooltip = null;\n            if (isDisabled && !isEditMode) {\n              tooltip = isTransparentAndInvalid\n                ? __(\n                    'Page background colors cannot have an opacity.',\n                    'web-stories'\n                  )\n                : __('Gradient not allowed for Text', 'web-stories');\n            }\n\n            const patternAsBackground = getPatternAsString(pattern);\n            const title = !isEditMode\n              ? patternAsBackground\n              : sprintf(\n                  /* translators: 1: the color type. 2: the color as a string */\n                  __('Delete %1$s color: %2$s', 'web-stories'),\n                  colorType,\n                  patternAsBackground\n                );\n            const isSelected = colorAsBackground === patternAsBackground;\n            // By default, the first swatch can be tabbed into, unless there's a selected one.\n            let tabIndex = i === firstIndex ? 0 : -1;\n            if (selectedSwatchIndex >= 0) {\n              tabIndex = isSelected ? 0 : -1;\n            } else if (isDisabled && i === firstIndex) {\n              firstIndex++;\n              tabIndex = -1;\n            }\n            return (\n              <ConditionalTooltip key={patternAsBackground} tooltip={tooltip}>\n                <StyledSwatch\n                  onClick={() => handleClick(pattern, isLocal)}\n                  pattern={pattern}\n                  isSelected={isSelected}\n                  isDisabled={isDisabled}\n                  tabIndex={tabIndex}\n                  title={title}\n                >\n                  {isEditMode && <Icons.Cross />}\n                </StyledSwatch>\n              </ConditionalTooltip>\n            );\n          })}\n          {(isLocal || isGlobal) && (\n            <ColorAdd\n              isLocal={isLocal}\n              isGlobal={isGlobal}\n              isBackground={isBackground}\n            />\n          )}\n        </SwatchList>\n      )}\n      {/* The `ColorAdd` button can only live in the listbox if there is at least one element with `role=\"option\"` */}\n      {!colors.length && (isLocal || isGlobal) && (\n        <ColorAdd\n          isLocal={isLocal}\n          isGlobal={isGlobal}\n          isBackground={isBackground}\n        />\n      )}\n    </>\n  );\n}\n\nBasicColorList.propTypes = {\n  handleClick: PropTypes.func.isRequired,\n  allowsOpacity: PropTypes.bool,\n  allowsGradient: PropTypes.bool,\n  color: PatternPropType,\n  colors: PropTypes.arrayOf(PatternPropType),\n  isLocal: PropTypes.bool,\n  isGlobal: PropTypes.bool,\n  isEditMode: PropTypes.bool.isRequired,\n  changedStyle: PropTypes.string,\n};\n\nexport default BasicColorList;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/basicColorPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { PatternPropType } from '@googleforcreators/patterns';\nimport {\n  TextSize,\n  Button,\n  Icons,\n  Text,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useState, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../app/story/useStory';\nimport useEyedropper from '../eyedropper';\nimport { BASIC_COLORS, CONFIRMATION_DIALOG_STORAGE_KEY } from './constants';\nimport Header from './header';\nimport BasicColorList from './basicColorList';\nimport ConfirmationDialog from './confirmationDialog';\nimport useDeleteColor from './useDeleteColor';\n\nconst Body = styled.div`\n  display: flex;\n  flex-direction: column;\n  padding: 8px 16px 0;\n  overflow: auto;\n  ${themeHelpers.scrollbarCSS};\n`;\n\nconst Footer = styled.div`\n  padding: 8px 16px 16px;\n  display: flex;\n  flex-direction: column;\n`;\n\nconst SavedColors = styled.div`\n  border-bottom: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  padding-bottom: 16px;\n`;\n\nconst DefaultColors = styled.div``;\n\nconst Label = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin: 12px 0 10px;\n`;\n\nconst DefaultText = styled(Label)`\n  margin: 0 0 0 8px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\nconst StyledButton = styled(Button)`\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  gap: 4px;\n  flex-basis: 100%;\n`;\n\nconst StyledText = styled(Text.Paragraph)`\n  padding: 5px 10px;\n`;\n\nconst StyledPlus = styled(Icons.PlusOutline)`\n  width: 32px;\n  margin: -8px 0;\n`;\n\nconst EyedropperWrapper = styled.div`\n  display: flex;\n`;\n\nfunction BasicColorPicker({\n  color,\n  handleColorChange,\n  allowsOpacity,\n  allowsGradient,\n  allowsSavedColors,\n  showCustomPicker,\n  handleClose,\n  showDialog,\n  setShowDialog,\n  changedStyle,\n  hasEyedropper,\n  allowsSavedColorDeletion,\n  shouldCloseOnSelection,\n}) {\n  const { savedColors, storyColors } = useStory((state) => ({\n    savedColors: state.state.story?.globalStoryStyles?.colors || [],\n    storyColors: state.state.story?.currentStoryStyles?.colors || [],\n  }));\n\n  const [isEditMode, setIsEditMode] = useState(false);\n  const [toDelete, setToDelete] = useState(null);\n  const hasPresets = storyColors.length > 0 || savedColors.length > 0;\n\n  const { initEyedropper } = useEyedropper({\n    onChange: useCallback(\n      (newColor) => handleColorChange({ color: newColor }),\n      [handleColorChange]\n    ),\n  });\n\n  const { deleteLocalColor, deleteGlobalColor } = useDeleteColor({\n    onEmpty: () => setIsEditMode(false),\n  });\n\n  const handleSelect = (pattern) => {\n    handleColorChange(pattern);\n    // if closing on select, go ahead and close\n    if (shouldCloseOnSelection) {\n      handleClose();\n    }\n  };\n\n  const handleClick = (preset, isLocal = false) => {\n    // If not in edit mode, apply the color.\n    if (!isEditMode) {\n      handleSelect(preset);\n      return;\n    }\n    // If deleting a local color, delete without confirmation.\n    if (isLocal) {\n      deleteLocalColor(preset);\n      return;\n    }\n\n    // If the user has dismissed the confirmation dialogue previously.\n    const isDialogDismissed = localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX[CONFIRMATION_DIALOG_STORAGE_KEY]\n    );\n    if (isDialogDismissed) {\n      deleteGlobalColor(preset);\n      return;\n    }\n\n    // Ask confirmation for a global color.\n    setShowDialog(true);\n    setToDelete(preset);\n  };\n\n  const hasHeader = !shouldCloseOnSelection || allowsSavedColorDeletion;\n\n  return (\n    <>\n      {hasHeader && (\n        <Header\n          handleClose={handleClose}\n          isEditMode={isEditMode}\n          setIsEditMode={setIsEditMode}\n          hasPresets={hasPresets && allowsSavedColors}\n        >\n          <DefaultText>{__('Color', 'web-stories')}</DefaultText>\n        </Header>\n      )}\n      <Body>\n        {hasEyedropper && (\n          <EyedropperWrapper>\n            <Button\n              variant={ButtonVariant.Square}\n              type={ButtonType.Quaternary}\n              size={ButtonSize.Small}\n              aria-label={__('Pick a color from canvas', 'web-stories')}\n              onClick={initEyedropper()}\n              onPointerEnter={initEyedropper(false)}\n            >\n              <Icons.Pipette />\n            </Button>\n            <StyledText size={TextSize.Small}>\n              {__('Sample color', 'web-stories')}\n            </StyledText>\n          </EyedropperWrapper>\n        )}\n        {allowsSavedColors && (\n          <SavedColors>\n            <Label id=\"colorpicker-story-colors-title\">\n              {__('Current story', 'web-stories')}\n            </Label>\n            <BasicColorList\n              color={color}\n              colors={storyColors}\n              handleClick={handleClick}\n              isLocal\n              allowsOpacity={allowsOpacity}\n              allowsGradient={allowsGradient}\n              aria-labelledby=\"colorpicker-story-colors-title\"\n              isEditMode={isEditMode}\n              data-testid=\"saved-story-colors\"\n              changedStyle={changedStyle}\n            />\n            <Label id=\"colorpicker-saved-colors-title\">\n              {__('Saved colors', 'web-stories')}\n            </Label>\n            <BasicColorList\n              color={color}\n              colors={savedColors}\n              isGlobal\n              handleClick={handleClick}\n              allowsOpacity={allowsOpacity}\n              allowsGradient={allowsGradient}\n              aria-labelledby=\"colorpicker-saved-colors-title\"\n              isEditMode={isEditMode}\n              changedStyle={changedStyle}\n            />\n          </SavedColors>\n        )}\n\n        <DefaultColors>\n          <Label id=\"colorpicker-default-colors-title\">\n            {__('Default', 'web-stories')}\n          </Label>\n          <BasicColorList\n            color={color}\n            colors={BASIC_COLORS}\n            handleClick={(pattern) => {\n              handleSelect(pattern);\n              setIsEditMode(false);\n            }}\n            allowsOpacity={allowsOpacity}\n            allowsGradient={allowsGradient}\n            aria-labelledby=\"colorpicker-default-colors-title\"\n            isEditMode={false}\n          />\n        </DefaultColors>\n      </Body>\n      <Footer>\n        <StyledButton\n          onClick={showCustomPicker}\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Rectangle}\n        >\n          {__('Custom', 'web-stories')}\n          <StyledPlus />\n        </StyledButton>\n      </Footer>\n      {showDialog && (\n        <ConfirmationDialog\n          onClose={() => setShowDialog(false)}\n          onPrimary={() => {\n            deleteGlobalColor(toDelete);\n            setToDelete(null);\n            setShowDialog(false);\n          }}\n        />\n      )}\n    </>\n  );\n}\n\nBasicColorPicker.propTypes = {\n  handleColorChange: PropTypes.func.isRequired,\n  showCustomPicker: PropTypes.func.isRequired,\n  handleClose: PropTypes.func,\n  allowsOpacity: PropTypes.bool,\n  allowsGradient: PropTypes.bool,\n  allowsSavedColors: PropTypes.bool,\n  color: PatternPropType,\n  showDialog: PropTypes.bool,\n  setShowDialog: PropTypes.func,\n  changedStyle: PropTypes.string,\n  hasEyedropper: PropTypes.bool,\n  allowsSavedColorDeletion: PropTypes.bool,\n  shouldCloseOnSelection: PropTypes.bool,\n};\n\nexport default BasicColorPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/colorAdd.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\nimport useAddPreset from '../../utils/useAddPreset';\nimport { PRESET_TYPES } from '../../constants';\n\nconst COLOR_SIZE = 24;\nconst AddColorAction = styled.button`\n  cursor: pointer;\n  background-color: transparent;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  border-color: ${({ theme }) => theme.colors.border.defaultNormal};\n  border-width: 1px;\n  border-style: dashed;\n  border-radius: 50%;\n  height: ${COLOR_SIZE}px;\n  width: ${COLOR_SIZE}px;\n  padding: 0;\n  svg {\n    height: 100%;\n    width: 100%;\n  }\n  :hover {\n    border-color: ${({ theme }) => theme.colors.border.defaultHover};\n  }\n  ${focusStyle};\n`;\n\nfunction ColorAdd({\n  isLocal = false,\n  isGlobal = false,\n  isBackground = false,\n  ...props\n}) {\n  const { addGlobalPreset, addLocalPreset } = useAddPreset({\n    presetType: PRESET_TYPES.COLOR,\n    isBackgroundColor: isBackground,\n  });\n  if (!isLocal && !isGlobal) {\n    return null;\n  }\n\n  const label = isLocal\n    ? __('Add local color', 'web-stories')\n    : __('Add global color', 'web-stories');\n\n  return (\n    <AddColorAction\n      tabIndex=\"0\"\n      onClick={isLocal ? addLocalPreset : addGlobalPreset}\n      aria-label={label}\n      {...props}\n    >\n      <Icons.Plus />\n    </AddColorAction>\n  );\n}\n\nColorAdd.propTypes = {\n  isLocal: PropTypes.bool,\n  isGlobal: PropTypes.bool,\n  isBackground: PropTypes.bool,\n};\n\nexport default ColorAdd;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/colorPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { CSSTransition } from 'react-transition-group';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useDebouncedCallback,\n  useFocusOut,\n  useRef,\n  useState,\n  useCallback,\n  useEffect,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { PatternPropType, hasGradient } from '@googleforcreators/patterns';\nimport {\n  useKeyDownEffect,\n  THEME_CONSTANTS,\n} from '@googleforcreators/design-system';\nimport { useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport useFocusTrapping from '../../utils/useFocusTrapping';\nimport useStory from '../../app/story/useStory';\nimport { noop } from '../../utils/noop';\nimport CustomColorPicker from './customColorPicker';\nimport BasicColorPicker from './basicColorPicker';\n\nconst PICKER_WIDTH = 208;\n\nconst Container = styled.div`\n  border-radius: 8px;\n  background: ${({ theme }) => theme.colors.bg.secondary};\n  user-select: none;\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n  align-items: stretch;\n  ${({ maxHeight }) =>\n    maxHeight\n      ? `\n          height: ${maxHeight}px;\n          width: ${PICKER_WIDTH + THEME_CONSTANTS.SCROLLBAR_WIDTH}px;\n        `\n      : `\n          width: ${PICKER_WIDTH}px;\n        `};\n  overflow: hidden;\n\n  &.picker-appear {\n    opacity: 0.01;\n    margin-top: -10px;\n\n    &.picker-appear-active {\n      opacity: 1;\n      margin-top: 0;\n      transition: 300ms ease-out;\n      transition-property: opacity, margin-top;\n    }\n  }\n`;\n\nfunction ColorPicker({\n  onChange,\n  isEyedropperActive = false,\n  color = null,\n  allowsGradient = false,\n  allowsOpacity = true,\n  allowsSavedColors = false,\n  hasEyedropper = true,\n  maxHeight = null,\n  onClose = noop,\n  changedStyle = 'background',\n  onDimensionChange = noop,\n  allowsSavedColorDeletion = true,\n  shouldCloseOnSelection = false,\n}) {\n  const [showDialog, setShowDialog] = useState(false);\n  // If initial color is a gradient, start by showing a custom color picker.\n  // Note that no such switch happens if the color later changes to a gradient,\n  // only if it was a gradient at the moment the color picker mounted.\n  const [isCustomPicker, setCustomPicker] = useState(hasGradient(color));\n  const showCustomPicker = useCallback(() => {\n    setCustomPicker(true);\n    onDimensionChange();\n  }, [onDimensionChange]);\n  const hideCustomPicker = useCallback(() => {\n    setCustomPicker(false);\n    onDimensionChange();\n  }, [onDimensionChange]);\n\n  const {\n    actions: { pushTransform },\n  } = useTransform();\n\n  const { selectedElementIds = [] } = useStory(\n    ({ state: { selectedElementIds } }) => ({ selectedElementIds })\n  );\n\n  const onDebouncedChange = useDebouncedCallback(onChange, 100, {\n    leading: true,\n  });\n\n  // Floating menu color picker doesn't stay mounted\n  // So, if the eyedropper is used from inside a floating menu color picker\n  // the debounced onChange can never be seen.\n  // this gives us a way to process that change when no longer mounted\n  const isMountedRef = useRef(true);\n  useEffect(() => {\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  const handleColorChange = useCallback(\n    (newColor) => {\n      if (isMountedRef.current) {\n        onDebouncedChange(newColor);\n      } else {\n        onChange(newColor);\n      }\n\n      selectedElementIds.forEach((id) => {\n        pushTransform(id, {\n          color: newColor,\n          style: changedStyle,\n          staticTransformation: true,\n        });\n      });\n    },\n    [\n      onChange,\n      onDebouncedChange,\n      selectedElementIds,\n      changedStyle,\n      pushTransform,\n    ]\n  );\n\n  const maybeClose = () => {\n    // Usually we close the color picker when focusing anywhere outside of it.\n    // There's an exception for when the eyedropper is in use or when a confirmation dialog is open\n    // since both cause focusing outside of the color picker for interacting by the user, but the picker needs to stay open.\n    if (!isEyedropperActive && !showDialog) {\n      onClose();\n    }\n  };\n\n  // Detect focus out of color picker (clicks or focuses outside)\n  const containerRef = useRef();\n  useFocusOut(containerRef, maybeClose, [isEyedropperActive, showDialog]);\n\n  // Re-establish focus when actively exiting by button or key press\n  const previousFocus = useRef(document.activeElement);\n  const handleCloseAndRefocus = useCallback(\n    (evt) => {\n      // Ignore reason: In Jest, focus is always on document.body if not on any specific\n      // element, so it can never be falsy, as it can be in a real browser.\n\n      // istanbul ignore else\n      if (previousFocus.current) {\n        previousFocus.current.focus();\n      }\n      onClose(evt);\n    },\n    [onClose]\n  );\n\n  useKeyDownEffect(containerRef, 'esc', handleCloseAndRefocus);\n  useFocusTrapping({ ref: containerRef });\n\n  const ActualColorPicker = isCustomPicker\n    ? CustomColorPicker\n    : BasicColorPicker;\n\n  return (\n    <CSSTransition\n      nodeRef={containerRef}\n      in\n      appear\n      classNames=\"picker\"\n      timeout={300}\n    >\n      <Container\n        role=\"dialog\"\n        aria-label={__('Color and gradient picker', 'web-stories')}\n        ref={containerRef}\n        maxHeight={maxHeight}\n      >\n        <ActualColorPicker\n          color={color}\n          allowsGradient={allowsGradient}\n          allowsOpacity={allowsOpacity}\n          handleColorChange={handleColorChange}\n          showCustomPicker={showCustomPicker}\n          hideCustomPicker={hideCustomPicker}\n          handleClose={handleCloseAndRefocus}\n          hasEyedropper={hasEyedropper}\n          allowsSavedColors={allowsSavedColors}\n          showDialog={showDialog}\n          setShowDialog={setShowDialog}\n          changedStyle={changedStyle}\n          allowsSavedColorDeletion={allowsSavedColorDeletion}\n          shouldCloseOnSelection={shouldCloseOnSelection}\n        />\n      </Container>\n    </CSSTransition>\n  );\n}\n\nColorPicker.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  onClose: PropTypes.func,\n  allowsGradient: PropTypes.bool,\n  allowsOpacity: PropTypes.bool,\n  allowsSavedColors: PropTypes.bool,\n  isEyedropperActive: PropTypes.bool,\n  maxHeight: PropTypes.number,\n  color: PatternPropType,\n  changedStyle: PropTypes.string,\n  onDimensionChange: PropTypes.func,\n  hasEyedropper: PropTypes.bool,\n  allowsSavedColorDeletion: PropTypes.bool,\n  shouldCloseOnSelection: PropTypes.bool,\n};\n\nexport default ColorPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/confirmationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport {\n  Text,\n  Checkbox,\n  TextSize,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\nimport { CONFIRMATION_DIALOG_STORAGE_KEY } from './constants';\n\nconst Label = styled.label`\n  margin-left: 12px;\n`;\n\nconst CheckboxWrapper = styled.footer`\n  display: flex;\n  margin-top: 12px;\n  padding: 14px 0 0 9px;\n  border-top: 1px solid ${({ theme }) => theme.colors.divider.primary};\n`;\n\nfunction ConfirmationDialog({ onClose, onPrimary }) {\n  const [isDialogDismissed, setIsDialogDismissed] = useState(\n    localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX[CONFIRMATION_DIALOG_STORAGE_KEY]\n    )\n  );\n\n  const cbId = `cb-${uuidv4()}`;\n  return (\n    <Dialog\n      isOpen\n      onClose={onClose}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={onPrimary}\n      primaryText={__('Delete', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'This is a global color. Deleting this color will remove it from the Saved Colors across all stories and the color will no longer be available to any other users on the site.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n      <CheckboxWrapper>\n        <Checkbox\n          id={cbId}\n          checked={isDialogDismissed}\n          onChange={() => {\n            localStore.setItemByKey(\n              LOCAL_STORAGE_PREFIX[CONFIRMATION_DIALOG_STORAGE_KEY],\n              !isDialogDismissed\n            );\n            setIsDialogDismissed(!isDialogDismissed);\n          }}\n        />\n        <Label htmlFor={cbId}>\n          <Text.Span size={TextSize.Small}>\n            {__(\"Don't ask for confirmation again.\", 'web-stories')}\n          </Text.Span>\n        </Label>\n      </CheckboxWrapper>\n    </Dialog>\n  );\n}\n\nConfirmationDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onPrimary: PropTypes.func.isRequired,\n};\n\nexport default ConfirmationDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolidFromString } from '@googleforcreators/patterns';\n\nexport const LINE_LENGTH = 112;\nexport const LINE_WIDTH = 12;\n\nexport const GRADIENT_STOP_SIZE = 14;\n\nexport const TYPE_SOLID = 'solid';\nexport const TYPE_LINEAR = 'linear';\nexport const TYPE_RADIAL = 'radial';\n\nexport const CONFIRMATION_DIALOG_STORAGE_KEY =\n  'DELETE_COLOR_PRESET_DIALOG_DISMISSED';\n\nconst c = (hex) => createSolidFromString(`#${hex}`);\n\nexport const BASIC_COLORS = [\n  // Grays\n  c('00000000'),\n  c('000000'),\n  c('454545'),\n  c('B6B6B6'),\n  c('EEEEEE'),\n  c('FFFFFF'),\n  // Blues\n  c('003BAD'),\n  c('0044C9'),\n  c('0354F2'),\n  c('1263FF'),\n  c('347EFF'),\n  c('6D9FFF'),\n  // Purples\n  c('4B1283'),\n  c('5A189A'),\n  c('7B2CBF'),\n  c('9D4EDD'),\n  c('C77DFF'),\n  c('E0AAFF'),\n  // Pinks\n  c('E03568'),\n  c('FF477E'),\n  c('FF5C8A'),\n  c('FF7096'),\n  c('FF85A1'),\n  c('FF99AC'),\n  // Reds\n  c('590D22'),\n  c('800F2F'),\n  c('A4133C'),\n  c('C9184A'),\n  c('FF4D6D'),\n  c('FF758F'),\n  // Yellows\n  c('DBCA09'),\n  c('FFD900'),\n  c('FFE747'),\n  c('FFEE70'),\n  c('FFF599'),\n  c('FFFFB7'),\n  // Oranges\n  c('E06E04'),\n  c('EA7D00'),\n  c('FF9500'),\n  c('FFA811'),\n  c('FFBC35'),\n  c('FFCC4A'),\n  // Greens\n  c('607047'),\n  c('79895D'),\n  c('839568'),\n  c('A5B98B'),\n  c('C1D3AA'),\n  c('D4E4C0'),\n  // Browns\n  c('603809'),\n  c('603808'),\n  c('6F4518'),\n  c('8B5E34'),\n  c('A47148'),\n  c('BC8A5F'),\n];\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/currentColorPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n  lazy,\n  Suspense,\n  createContext,\n  useContext,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Icons,\n  Button,\n  ButtonSize,\n  ButtonVariant,\n  ButtonType,\n  CircularProgress,\n} from '@googleforcreators/design-system';\n\nconst Saturation = lazy(() =>\n  import(\n    /* webpackChunkName: \"chunk-react-color\" */\n    /* webpackExports: \"Saturation\" */\n    '@hello-pangea/color-picker'\n  ).then((module) => ({ default: module.Saturation }))\n);\nconst Hue = lazy(() =>\n  import(\n    /* webpackChunkName: \"chunk-react-color\" */\n    /* webpackExports: \"Hue\" */\n    '@hello-pangea/color-picker'\n  ).then((module) => ({ default: module.Hue }))\n);\nconst Alpha = lazy(() =>\n  import(\n    /* webpackChunkName: \"chunk-react-color\" */\n    /* webpackExports: \"Alpha\" */\n    '@hello-pangea/color-picker'\n  ).then((module) => ({ default: module.Alpha }))\n);\n\n/**\n * Internal dependencies\n */\nimport useEyedropper from '../eyedropper';\nimport Pointer from './pointer';\nimport EditablePreview from './editablePreview';\n\nconst CONTAINER_PADDING = 16;\nconst HEADER_FOOTER_HEIGHT = 36;\nconst BODY_HEIGHT = 116;\nconst CONTROLS_HEIGHT = 20;\nconst CONTROLS_BORDER_RADIUS = 50;\nconst OPACITY_WIDTH = 52;\nconst HEX_WIDTH = 74;\n\nconst BodyFallback = styled.div`\n  height: ${BODY_HEIGHT + 3 * CONTROLS_HEIGHT + 4 * CONTAINER_PADDING}px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\nconst SaturationWrapper = styled.div`\n  position: relative;\n  margin: 0 16px;\n  flex: 0 1 ${BODY_HEIGHT}px;\n`;\n\nconst wrapperCSS = css`\n  margin: 0 16px;\n  border: 1px solid ${({ theme }) => theme.colors.shadow.active};\n  flex: 0 0 ${CONTROLS_HEIGHT}px;\n  position: relative;\n  border-radius: ${CONTROLS_BORDER_RADIUS}px;\n  background-clip: padding-box;\n`;\n\nconst HueWrapper = styled.div`\n  ${wrapperCSS}\n`;\n\nconst AlphaWrapper = styled.div`\n  ${wrapperCSS}\n  div:first-child div:first-child div:first-child {\n    background-image: conic-gradient(\n      ${({ theme }) => theme.colors.fg.tertiary} 0.25turn,\n      transparent 0turn 0.5turn,\n      ${({ theme }) => theme.colors.fg.tertiary} 0turn 0.75turn,\n      transparent 0turn 1turn\n    ) !important;\n    background-size: 8px 8px !important;\n  }\n`;\n\nconst Footer = styled.div`\n  height: ${HEADER_FOOTER_HEIGHT}px;\n  line-height: 19px;\n  position: relative;\n  margin: 0 16px;\n  display: flex;\n  justify-content: space-between;\n`;\n\nconst HexValue = styled.div`\n  width: ${HEX_WIDTH}px;\n`;\n\nconst Opacity = styled.div`\n  width: ${OPACITY_WIDTH}px;\n`;\n\nfunction CurrentColorPicker({ rgb, hsl, hsv, hex, onChange }) {\n  const [showOpacity, hasEyedropper] = useContext(CurrentColorPickerContext);\n  const alphaPercentage = String(Math.round(rgb.a * 100));\n  const hexValue = hex[0] === '#' ? hex.substr(1) : hex;\n\n  const handleFormatHex = useCallback((v) => {\n    if ('transparent' === v) {\n      v = '000000';\n    }\n    return `#${v}`;\n  }, []);\n  const handleFormatPercentage = useCallback((v) => `${v}%`, []);\n\n  const handleHexInputChange = useCallback(\n    (value) => onChange({ hex: value }),\n    [onChange]\n  );\n\n  const handleOpacityInputChange = useCallback(\n    (value) =>\n      onChange({ ...rgb, a: isNaN(value) ? 1 : Number.parseInt(value) / 100 }),\n    [rgb, onChange]\n  );\n\n  const { initEyedropper } = useEyedropper({ onChange });\n\n  // Note: pointer prop is handled differently for Saturation vs. Hue. See:\n  // https://github.com/hello-pangea/color-picker/blob/026c725c7d45f9690f71ca55c8d82a721356fdcc/packages/color-picker/src/components/common/Saturation.tsx#L128\n  // https://github.com/hello-pangea/color-picker/blob/026c725c7d45f9690f71ca55c8d82a721356fdcc/packages/color-picker/src/components/common/Hue.jsx#L101\n\n  return (\n    <>\n      <Suspense fallback={null}>\n        <SaturationWrapper>\n          <Saturation\n            radius=\"8px\"\n            pointer={<Pointer offsetX={-8} offsetY={-8} currentColor={rgb} />}\n            hsl={hsl}\n            hsv={hsv}\n            onChange={onChange}\n          />\n        </SaturationWrapper>\n        <HueWrapper>\n          <Hue\n            direction=\"horizontal\"\n            height={`${CONTROLS_HEIGHT}px`}\n            radius={`${CONTROLS_BORDER_RADIUS}px`}\n            pointer={() => (\n              <Pointer offsetX={-8} offsetY={1} currentColor={rgb} />\n            )}\n            hsl={hsl}\n            onChange={onChange}\n          />\n        </HueWrapper>\n        {showOpacity && (\n          <AlphaWrapper>\n            <Alpha\n              direction=\"horizontal\"\n              height={`${CONTROLS_HEIGHT}px`}\n              radius={`${CONTROLS_BORDER_RADIUS}px`}\n              pointer={() => (\n                <Pointer\n                  offsetX={-8}\n                  offsetY={1}\n                  currentColor={rgb}\n                  withAlpha\n                />\n              )}\n              rgb={rgb}\n              hsl={hsl}\n              onChange={onChange}\n            />\n          </AlphaWrapper>\n        )}\n      </Suspense>\n      <Footer>\n        {hasEyedropper && (\n          <Button\n            variant={ButtonVariant.Square}\n            type={ButtonType.Quaternary}\n            size={ButtonSize.Small}\n            aria-label={__('Pick a color from canvas', 'web-stories')}\n            onClick={initEyedropper()}\n            onPointerEnter={initEyedropper(false)}\n          >\n            <Icons.Pipette />\n          </Button>\n        )}\n        <HexValue>\n          <EditablePreview\n            label={__('Edit hex value', 'web-stories')}\n            value={hexValue}\n            onChange={handleHexInputChange}\n            width={80}\n            format={handleFormatHex}\n          />\n        </HexValue>\n        {showOpacity && (\n          <Opacity>\n            {/* @todo This needs % as suffix */}\n            <EditablePreview\n              label={__('Edit opacity', 'web-stories')}\n              value={alphaPercentage}\n              width={OPACITY_WIDTH}\n              format={handleFormatPercentage}\n              onChange={handleOpacityInputChange}\n            />\n          </Opacity>\n        )}\n      </Footer>\n    </>\n  );\n}\n\nCurrentColorPicker.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  rgb: PropTypes.object,\n  hex: PropTypes.string,\n  hsl: PropTypes.object,\n  hsv: PropTypes.object,\n};\n\nconst CurrentColorPickerContext = createContext([false, false]);\n\nconst DynamicImportWrapper = () => {\n  return (...args) => {\n    function DynamicFetcher({ showOpacity, hasEyedropper, ...props }) {\n      const isMountedRef = useRef(false);\n      const [Picker, setPicker] = useState(null);\n\n      useEffect(() => {\n        isMountedRef.current = true;\n        import(\n          /* webpackChunkName: \"chunk-react-color\" */\n          /* webpackExports: \"CustomPicker\" */\n          '@hello-pangea/color-picker'\n        ).then(({ CustomPicker }) => {\n          if (isMountedRef.current) {\n            setPicker({ component: CustomPicker(...args) });\n          }\n        });\n\n        return () => {\n          isMountedRef.current = false;\n        };\n      }, []);\n\n      return Picker ? (\n        <CurrentColorPickerContext.Provider\n          value={[showOpacity, hasEyedropper]}\n        >\n          <Picker.component {...props} />\n        </CurrentColorPickerContext.Provider>\n      ) : (\n        <BodyFallback>\n          <CircularProgress />\n        </BodyFallback>\n      );\n    }\n    DynamicFetcher.propTypes = {\n      showOpacity: PropTypes.bool.isRequired,\n      hasEyedropper: PropTypes.bool.isRequired,\n    };\n    return DynamicFetcher;\n  };\n};\n\nconst DynamicHOC = DynamicImportWrapper();\nexport default DynamicHOC(CurrentColorPicker);\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/customColorPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { createSolid, PatternPropType } from '@googleforcreators/patterns';\nimport {\n  Button,\n  Icons,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport CurrentColorPicker from './currentColorPicker';\nimport GradientPicker from './gradientPicker';\nimport Header from './header';\nimport PatternTypePicker from './patternTypePicker';\nimport useColor from './useColor';\nimport AddCustomColor from './addCustomColor';\n\nfunction CustomColorPicker({\n  color,\n  allowsGradient,\n  allowsOpacity,\n  handleColorChange,\n  handleClose,\n  hideCustomPicker,\n  allowsSavedColors,\n  hasEyedropper,\n}) {\n  const {\n    state: { type, stops, currentStopIndex, currentColor, generatedColor },\n    actions: {\n      load,\n      updateCurrentColor,\n      reverseStops,\n      selectStop,\n      addStopAt,\n      removeCurrentStop,\n      rotateClockwise,\n      moveCurrentStopBy,\n      setToSolid,\n      setToGradient,\n    },\n  } = useColor();\n\n  const isMountedRef = useRef(true);\n  useEffect(() => {\n    return () => {\n      isMountedRef.current = false;\n    };\n  }, []);\n\n  // If color picker isn't mounted while using eyedropper, generatedColor won't update.\n  useEffect(() => {\n    if (generatedColor) {\n      handleColorChange(generatedColor);\n    }\n  }, [handleColorChange, generatedColor]);\n\n  useEffect(() => {\n    if (color) {\n      load(color);\n    } else {\n      // If no color given, load solid black\n      load(createSolid(0, 0, 0));\n    }\n  }, [color, load]);\n\n  const handleColorPickerChange = useCallback(\n    (e) => {\n      updateCurrentColor(e);\n      // If using the eyedropper in floating menu, the popup unmounts\n      // so the generatedColor won't ever be updated\n      // check for unmount and if so, we know this change event\n      // is from the eyedropper so we can just grab the rgb and\n      // trigger the rest of the change for the element.\n      if (!isMountedRef.current && e?.rgb) {\n        handleColorChange({ color: e.rgb });\n      }\n    },\n    [updateCurrentColor, handleColorChange]\n  );\n\n  return (\n    <>\n      <Header handleClose={handleClose}>\n        <Button\n          aria-label={__('Go back', 'web-stories')}\n          onClick={hideCustomPicker}\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n        >\n          <Icons.ArrowLeft />\n        </Button>\n      </Header>\n      {allowsGradient && (\n        <PatternTypePicker\n          type={type}\n          setToGradient={setToGradient}\n          setToSolid={setToSolid}\n        />\n      )}\n      {type !== 'solid' && (\n        <GradientPicker\n          stops={stops}\n          currentStopIndex={currentStopIndex}\n          onSelect={selectStop}\n          onReverse={reverseStops}\n          onAdd={addStopAt}\n          onDelete={removeCurrentStop}\n          onRotate={rotateClockwise}\n          onMove={moveCurrentStopBy}\n          type={type}\n        />\n      )}\n      <CurrentColorPicker\n        color={currentColor}\n        onChange={handleColorPickerChange}\n        showOpacity={allowsOpacity}\n        hasEyedropper={hasEyedropper}\n      />\n      {allowsSavedColors && (\n        <AddCustomColor\n          color={generatedColor || color}\n          onSave={hideCustomPicker}\n        />\n      )}\n    </>\n  );\n}\n\nCustomColorPicker.propTypes = {\n  handleColorChange: PropTypes.func.isRequired,\n  handleClose: PropTypes.func,\n  hideCustomPicker: PropTypes.func.isRequired,\n  allowsGradient: PropTypes.bool,\n  allowsOpacity: PropTypes.bool,\n  allowsSavedColors: PropTypes.bool,\n  color: PatternPropType,\n  hasEyedropper: PropTypes.bool,\n};\n\nexport default CustomColorPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/editablePreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useMemo,\n  useRef,\n  useLayoutEffect,\n  useState,\n  lazy,\n  Suspense,\n} from '@googleforcreators/react';\nimport {\n  Text,\n  TextSize,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\n\nconst EditableInput = lazy(() =>\n  import(\n    /* webpackChunkName: \"chunk-react-color\" */\n    /* webpackExports: \"EditableInput\" */\n    '@hello-pangea/color-picker'\n  ).then((module) => ({ default: module.EditableInput }))\n);\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\n\nconst Preview = styled.button`\n  margin: 0;\n  padding: 5px 7px;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  border-radius: 4px;\n  background: transparent;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  width: 100%;\n\n  ${focusStyle};\n`;\n\nconst Wrapper = styled.div`\n  input {\n    ${focusStyle};\n  }\n`;\n\nfunction EditablePreview({ label = '', value = '', width, format, onChange }) {\n  const [isEditing, setIsEditing] = useState(false);\n  const enableEditing = useCallback(() => setIsEditing(true), []);\n  const disableEditing = useCallback(() => setIsEditing(false), []);\n  const wrapperRef = useRef(null);\n  const editableRef = useRef();\n  const inputStyles = useMemo(\n    () => ({\n      input: {\n        textAlign: 'center',\n        textTransform: 'lowercase',\n        width: '100%',\n        padding: '6px 12px',\n        border: '1px solid #5E6668',\n        color: '#E4E5E6',\n        borderRadius: '4px',\n        background: 'transparent',\n        lineHeight: '18px',\n      },\n      wrap: {\n        lineHeight: 0,\n        maxWidth: `${width}px`,\n      },\n    }),\n    [width]\n  );\n\n  // Handle ESC keypress to toggle input field.\n  //eslint-disable-next-line react-hooks/exhaustive-deps -- False positive.\n  useKeyDownEffect(wrapperRef, { key: 'esc', editable: true }, disableEditing, [\n    isEditing,\n  ]);\n\n  const handleOnBlur = (evt) => {\n    // Ignore reason: There's no practical way to simulate the else occurring\n    // istanbul ignore else\n    if (!evt.currentTarget.contains(evt.relatedTarget)) {\n      disableEditing();\n    }\n  };\n\n  useLayoutEffect(() => {\n    // Wait one tick to ensure the input has been loaded.\n    const timeout = setTimeout(() => {\n      if (isEditing && editableRef.current) {\n        editableRef.current.input.focus();\n        editableRef.current.input.select();\n        editableRef.current.input.setAttribute('aria-label', label);\n      }\n    });\n\n    return () => clearTimeout(timeout);\n  }, [isEditing, label]);\n\n  if (!isEditing) {\n    return (\n      <Preview\n        aria-label={label}\n        onClick={enableEditing}\n        onFocus={enableEditing}\n      >\n        <Text.Paragraph size={TextSize.Small}>{format(value)}</Text.Paragraph>\n      </Preview>\n    );\n  }\n\n  // The value is set to 'transparent' by the library if it's black with 0 opacity.\n  // We want to always display hex though.\n  const editValue = value === 'transparent' ? '000000' : value;\n  return (\n    <Wrapper ref={wrapperRef} tabIndex={-1} onBlur={handleOnBlur}>\n      <Suspense fallback={null}>\n        <EditableInput\n          value={editValue}\n          ref={editableRef}\n          onChange={onChange}\n          onChangeComplete={disableEditing}\n          style={inputStyles}\n        />\n      </Suspense>\n    </Wrapper>\n  );\n}\n\nEditablePreview.propTypes = {\n  label: PropTypes.string,\n  value: PropTypes.string,\n  width: PropTypes.number.isRequired,\n  onChange: PropTypes.func.isRequired,\n  format: PropTypes.func.isRequired,\n};\n\nexport default EditablePreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/gradientLine.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  ColorStopPropType,\n  generatePatternStyles,\n} from '@googleforcreators/patterns';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Pointer from './pointer';\nimport GradientStop from './gradientStop';\nimport useKeyMoveStop from './useKeyMoveStop';\nimport useKeyAddStop from './useKeyAddStop';\nimport useKeyDeleteStop from './useKeyDeleteStop';\nimport useKeyFocus from './useKeyFocus';\nimport usePointerAddStop from './usePointerAddStop';\nimport usePointerMoveStop from './usePointerMoveStop';\nimport { LINE_LENGTH, LINE_WIDTH } from './constants';\n\nconst Line = styled.div`\n  ${themeHelpers.transparentBg}\n  width: ${LINE_LENGTH}px;\n  height: ${LINE_WIDTH}px;\n  border-radius: 2px;\n  position: relative;\n\n  &:focus {\n    /* The line will only have temporary focus while deleting stops */\n    outline: none;\n  }\n`;\n\nconst Background = styled.div.attrs(({ stops }) => ({\n  style: generatePatternStyles({\n    type: 'linear',\n    stops,\n    // And fix rotation to .25 to make it go right-to-left\n    rotation: 0.25,\n  }),\n}))`\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  pointer-events: none;\n`;\n\nconst TempPointer = styled(Pointer).attrs(({ x }) => ({\n  style: {\n    left: `${x}px`,\n  },\n  offsetX: -LINE_WIDTH / 2,\n}))`\n  height: ${LINE_WIDTH - 2}px;\n  width: ${LINE_WIDTH - 2}px;\n  opacity: 0.6;\n  top: 1px;\n  pointer-events: none;\n`;\n\nfunction GradientLine({\n  stops,\n  currentStopIndex,\n\n  onSelect,\n  onAdd,\n  onDelete,\n  onMove,\n}) {\n  const line = useRef();\n\n  useKeyMoveStop(line, onMove);\n  useKeyAddStop(line, onAdd, stops, currentStopIndex);\n  useKeyDeleteStop(line, onDelete);\n  const stopsRef = useKeyFocus(line, stops, currentStopIndex);\n\n  usePointerMoveStop(line, onMove);\n  const tempPointerPosition = usePointerAddStop(line, onAdd);\n  return (\n    <Line\n      ref={line}\n      aria-label={__('Gradient line', 'web-stories')}\n      tabIndex=\"-1\"\n    >\n      <Background stops={stops} />\n      {stops.map(({ position, color }, index) => (\n        <GradientStop\n          ref={(ref) => (stopsRef[index].current = ref)}\n          key={\n            // eslint-disable-next-line react/no-array-index-key -- Should be OK here.\n            index\n          }\n          index={index}\n          isSelected={index === currentStopIndex}\n          position={position}\n          onSelect={onSelect}\n          color={{ color }}\n        >\n          <Pointer offsetX={-LINE_WIDTH / 2} />\n        </GradientStop>\n      ))}\n      {tempPointerPosition && (\n        <TempPointer\n          aria-label={sprintf(\n            /* translators: %d: stop percentage */\n            __('Temporary gradient stop at %d%%', 'web-stories'),\n            Math.round(100 * (tempPointerPosition / LINE_LENGTH))\n          )}\n          x={tempPointerPosition}\n        />\n      )}\n    </Line>\n  );\n}\n\nGradientLine.propTypes = {\n  stops: PropTypes.arrayOf(ColorStopPropType),\n  currentStopIndex: PropTypes.number.isRequired,\n\n  onSelect: PropTypes.func.isRequired,\n  onAdd: PropTypes.func.isRequired,\n  onDelete: PropTypes.func.isRequired,\n  onMove: PropTypes.func.isRequired,\n};\n\nexport default GradientLine;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/gradientPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { ColorStopPropType } from '@googleforcreators/patterns';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../tooltip';\nimport GradientLine from './gradientLine';\n\nconst Wrapper = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 16px 16px 0;\n  height: 60px;\n`;\n\nconst Buttons = styled.div`\n  display: flex;\n  gap: 8px;\n`;\n\nconst SmallButton = styled(Button)`\n  width: 24px;\n  height: 24px;\n  padding: 0;\n  svg {\n    width: 24px;\n    height: 24px;\n  }\n`;\n\nfunction GradientPicker({\n  stops,\n  currentStopIndex,\n  type,\n\n  onSelect,\n  onAdd,\n  onDelete,\n  onMove,\n\n  onRotate,\n  onReverse,\n}) {\n  const reverseLabel = __('Reverse gradient stops', 'web-stories');\n  const rotateLabel = __('Rotate gradient', 'web-stories');\n  const canRotate = type !== 'radial';\n  return (\n    <Wrapper>\n      <GradientLine\n        stops={stops}\n        currentStopIndex={currentStopIndex}\n        onSelect={onSelect}\n        onAdd={onAdd}\n        onDelete={onDelete}\n        onMove={onMove}\n      />\n      <Buttons>\n        <Tooltip hasTail title={reverseLabel}>\n          <SmallButton\n            aria-label={reverseLabel}\n            onClick={onReverse}\n            type={ButtonType.Quaternary}\n            size={ButtonSize.Small}\n            variant={ButtonVariant.Square}\n          >\n            <Icons.ArrowsLeftRight />\n          </SmallButton>\n        </Tooltip>\n        {canRotate && (\n          <Tooltip hasTail title={rotateLabel}>\n            <SmallButton\n              onClick={onRotate}\n              aria-label={rotateLabel}\n              type={ButtonType.Quaternary}\n              size={ButtonSize.Small}\n              variant={ButtonVariant.Square}\n            >\n              <Icons.ArrowRightCurved id=\"gradient-rotator\" />\n            </SmallButton>\n          </Tooltip>\n        )}\n      </Buttons>\n    </Wrapper>\n  );\n}\n\nGradientPicker.propTypes = {\n  stops: PropTypes.arrayOf(ColorStopPropType),\n  currentStopIndex: PropTypes.number.isRequired,\n  type: PropTypes.string.isRequired,\n\n  onSelect: PropTypes.func.isRequired,\n  onAdd: PropTypes.func.isRequired,\n  onDelete: PropTypes.func.isRequired,\n  onMove: PropTypes.func.isRequired,\n\n  onReverse: PropTypes.func.isRequired,\n  onRotate: PropTypes.func.isRequired,\n};\n\nexport default GradientPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/gradientStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { Icons, themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { LINE_LENGTH, LINE_WIDTH, GRADIENT_STOP_SIZE } from './constants';\n\nconst POINTER_MARGIN = 10;\nconst OFFSET = 1;\nconst Stop = styled.button.attrs(({ position }) => ({\n  style: {\n    right: `${position * LINE_LENGTH - LINE_WIDTH / 2}px`,\n  },\n}))`\n  position: absolute;\n  top: -${POINTER_MARGIN + GRADIENT_STOP_SIZE}px;\n  background: transparent;\n  border: 0;\n  padding: 0;\n\n  &:focus {\n    /* We auto-select stops on focus, so no extra focus display is necessary */\n    outline: none;\n  }\n`;\n\nconst fillCss = css`\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n`;\n\nconst Background = styled.div`\n  ${fillCss}\n  ${({ color }) => generatePatternStyles(color)}\n`;\n\nconst Transparent = styled.div`\n  ${themeHelpers.transparentBg}\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  top: 0;\n`;\n\nconst StopPointer = styled.div`\n  transform: translate(${({ offset }) => `${offset}px`}, 0);\n  width: ${GRADIENT_STOP_SIZE}px;\n  height: ${GRADIENT_STOP_SIZE}px;\n  border-radius: 2px;\n  overflow: hidden;\n`;\n\nconst IconWrapper = styled.div`\n  position: absolute;\n  left: -${9 + OFFSET}px;\n  top: -8px;\n  color: ${({ theme, isSelected }) =>\n    isSelected ? theme.colors.fg.primary : theme.colors.fg.tertiary};\n  svg {\n    width: 32px;\n    height: 32px;\n  }\n`;\n\nfunction GradientStopWithRef(\n  { position, index, isSelected, color, onSelect },\n  ref\n) {\n  return (\n    <Stop\n      ref={ref}\n      key={index}\n      isSelected={isSelected}\n      position={position}\n      onFocus={() => onSelect(index)}\n      onClick={() => onSelect(index)}\n      aria-label={sprintf(\n        /* translators: %d: stop percentage */\n        __('Gradient stop at %d%%', 'web-stories'),\n        Math.round(100 - position * 100)\n      )}\n    >\n      <IconWrapper isSelected={isSelected}>\n        <Icons.TailedRectangle />\n      </IconWrapper>\n      <StopPointer offset={-OFFSET}>\n        <Transparent />\n        <Background color={color} />\n      </StopPointer>\n    </Stop>\n  );\n}\n\nconst GradientStop = forwardRef(GradientStopWithRef);\n\nGradientStop.propTypes = {\n  position: PropTypes.number.isRequired,\n  index: PropTypes.number.isRequired,\n  isSelected: PropTypes.bool.isRequired,\n  color: PropTypes.object.isRequired,\n  onSelect: PropTypes.func.isRequired,\n};\n\nGradientStopWithRef.propTypes = GradientStop.propTypes;\n\nexport default GradientStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  Icons,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\nimport { noop } from '../../utils/noop';\n\nconst HEADER_HEIGHT = 44;\n\nconst Wrapper = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  height: ${HEADER_HEIGHT}px;\n  padding: 4px 8px 4px 8px;\n  position: relative;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n`;\n\nconst Actions = styled.div`\n  display: flex;\n  margin-left: auto;\n`;\n\nconst StyledButton = styled(Button)`\n  margin-left: 8px;\n  ${focusStyle};\n`;\n\nfunction Header({\n  children,\n  handleClose,\n  isEditMode = false,\n  setIsEditMode = noop,\n  hasPresets = false,\n}) {\n  const ref = useRef();\n  useEffect(() => {\n    ref.current?.focus();\n  }, []);\n\n  const buttonProps = {\n    type: ButtonType.Tertiary,\n    size: ButtonSize.Small,\n    variant: ButtonVariant.Square,\n    onClick: (evt) => {\n      evt.stopPropagation();\n      setIsEditMode(!isEditMode);\n    },\n    isEditMode,\n  };\n\n  return (\n    <Wrapper>\n      {children}\n      <Actions>\n        {hasPresets ? (\n          isEditMode ? (\n            <StyledButton\n              {...buttonProps}\n              variant={ButtonVariant.Rectangle}\n              aria-label={__('Exit edit mode', 'web-stories')}\n            >\n              {__('Done', 'web-stories')}\n            </StyledButton>\n          ) : (\n            <StyledButton\n              {...buttonProps}\n              variant={ButtonVariant.Square}\n              aria-label={__('Edit colors', 'web-stories')}\n            >\n              <Icons.Pencil />\n            </StyledButton>\n          )\n        ) : null}\n        <StyledButton\n          aria-label={__('Close', 'web-stories')}\n          onClick={handleClose}\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          ref={ref}\n        >\n          <Icons.Cross />\n        </StyledButton>\n      </Actions>\n    </Wrapper>\n  );\n}\n\nHeader.propTypes = {\n  children: PropTypes.node,\n  handleClose: PropTypes.func.isRequired,\n  isEditMode: PropTypes.bool,\n  setIsEditMode: PropTypes.func,\n  hasPresets: PropTypes.bool,\n};\n\nexport default Header;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default } from './colorPicker';\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/insertStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction insertStop(stops, newPosition) {\n  // We're going to find the stop index and the color for the new stop\n\n  // Find index of first stop bigger than new position\n  const followingIndex = stops.findIndex(\n    ({ position }) => position > newPosition\n  );\n  // If it's -1, it's easy-peasy\n  if (followingIndex === -1) {\n    // Insert at end with same color as previously last stop\n    return {\n      index: stops.length,\n      color: stops[stops.length - 1].color,\n    };\n  }\n\n  // If it's 0, it's also easy\n  if (followingIndex === 0) {\n    // Insert at start with same color as previously start stop\n    return {\n      index: 0,\n      color: stops[0].color,\n    };\n  }\n\n  // Find the two stops surrounding the new stop\n  const preceding = stops[followingIndex - 1];\n  const following = stops[followingIndex];\n\n  // Find the ratio the new stop is from the preceding stop\n  const diffNewToPreceding = newPosition - preceding.position;\n  const diffFollowingToPreceding = following.position - preceding.position;\n  const ratio = diffNewToPreceding / diffFollowingToPreceding;\n\n  // Mix the two colors by that amount:\n  const {\n    color: { r: pr, g: pg, b: pb, a: pa = 1 },\n  } = preceding;\n  const {\n    color: { r: fr, g: fg, b: fb, a: fa = 1 },\n  } = following;\n  const mix = (p, f) => p + (f - p) * ratio;\n  const fullColor = {\n    r: Math.round(mix(pr, fr)),\n    g: Math.round(mix(pg, fg)),\n    b: Math.round(mix(pb, fb)),\n    a: mix(pa, fa),\n  };\n\n  const newColor =\n    fullColor.a === 1\n      ? { r: fullColor.r, g: fullColor.g, b: fullColor.b }\n      : fullColor;\n\n  return {\n    index: followingIndex,\n    color: newColor,\n  };\n}\n\nexport default insertStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/karma/colorPicker.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app';\n\ndescribe('ColorPicker', () => {\n  ['LTR', 'RTL'].forEach((direction) => {\n    describe(`when document is in ${direction} mode`, () => {\n      let fixture;\n\n      beforeEach(async () => {\n        fixture = new Fixture();\n        fixture.setConfig({ isRTL: direction === 'RTL' });\n        await fixture.render();\n        await fixture.collapseHelpCenter();\n      });\n\n      afterEach(() => {\n        fixture.restore();\n      });\n\n      it('should display correctly', async () => {\n        // Click the background element\n        await fixture.events.mouse.clickOn(\n          fixture.editor.canvas.framesLayer.frames[0].node,\n          10,\n          10\n        );\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        const bgPanel = fixture.editor.sidebar.designPanel.pageBackground;\n\n        // Click the background page panel color preview\n        await fixture.events.click(bgPanel.backgroundColor.button);\n\n        await waitFor(() => {\n          if (!bgPanel.backgroundColor.picker) {\n            throw new Error('picker not ready');\n          }\n          expect(bgPanel.backgroundColor.picker).toBeDefined();\n        });\n\n        // Verify there are no aXe violations within the color picker.\n        await expectAsync(\n          bgPanel.backgroundColor.picker.node\n        ).toHaveNoViolations();\n\n        // Snapshot it\n        await fixture.snapshot('Basic color picker');\n\n        // Go to the custom color picker as well and snapshot that too\n        await fixture.events.click(bgPanel.backgroundColor.picker.custom);\n        await fixture.snapshot('Custom color picker');\n      });\n    });\n  });\n\n  describe('Color Picker: Saved colors', () => {\n    let fixture;\n\n    beforeEach(async () => {\n      fixture = new Fixture();\n      await fixture.render();\n      await fixture.collapseHelpCenter();\n      localStorage.setItem(\n        'web_stories_ui_panel_settings:shapeStyle',\n        JSON.stringify({ isCollapsed: false })\n      );\n    });\n\n    afterEach(() => {\n      fixture.restore();\n      localStorage.clear();\n    });\n\n    const getSelection = async () => {\n      const storyContext = await fixture.renderHook(() => useStory());\n      return storyContext.state.selectedElements;\n    };\n\n    describe('CUJ: Creator can Apply or Save a Color from/to Their Preset Library: Add Colors', () => {\n      it('should allow adding local colors', async () => {\n        // Switch to shapes tab and click the triangle\n        await fixture.events.click(fixture.editor.library.shapesTab);\n        await fixture.events.click(\n          fixture.editor.library.shapes.shape('Triangle')\n        );\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.button\n        );\n\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.addSavedColor(\n            'global'\n          )\n        );\n        expect(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.applySavedColor(\n            '#c4c4c4'\n          )\n        ).toBeTruthy();\n      });\n\n      it('should allow adding global colors', async () => {\n        // Switch to shapes tab and click the triangle\n        await fixture.events.click(fixture.editor.library.shapesTab);\n        await fixture.events.click(\n          fixture.editor.library.shapes.shape('Triangle')\n        );\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.button\n        );\n\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.addSavedColor(\n            'local'\n          )\n        );\n        expect(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.applySavedColor(\n            '#c4c4c4'\n          )\n        ).toBeTruthy();\n      });\n\n      it('should allow applying global colors', async () => {\n        // Add shape and save its color.\n        await fixture.events.click(fixture.editor.library.shapesTab);\n        await fixture.events.click(\n          fixture.editor.library.shapes.shape('Triangle')\n        );\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.button\n        );\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.addSavedColor(\n            'global'\n          )\n        );\n\n        // Add text and apply the previously saved color.\n        await fixture.events.click(fixture.editor.sidebar.insertTab);\n        await fixture.editor.library.textTab.click();\n        await fixture.events.click(\n          fixture.editor.library.text.preset('Paragraph')\n        );\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n          expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n        });\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.button\n        );\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.picker.applySavedColor(\n            '#c4c4c4'\n          )\n        );\n        const [text] = await getSelection();\n        expect(text.content).toEqual(\n          '<span style=\"color: #c4c4c4\">Fill in some text</span>'\n        );\n      });\n\n      it('should allow applying local colors', async () => {\n        await fixture.events.click(fixture.editor.library.shapesTab);\n        await fixture.events.click(\n          fixture.editor.library.shapes.shape('Triangle')\n        );\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.button\n        );\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.shapeStyle.backgroundColor.picker.addSavedColor(\n            'local'\n          )\n        );\n\n        // Add text and apply the previously saved color.\n        await fixture.events.click(fixture.editor.sidebar.insertTab);\n        await fixture.editor.library.textTab.click();\n        await fixture.events.click(\n          fixture.editor.library.text.preset('Paragraph')\n        );\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n          expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n        });\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.button\n        );\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.picker.applySavedColor(\n            '#c4c4c4'\n          )\n        );\n        const [text] = await getSelection();\n        expect(text.content).toEqual(\n          '<span style=\"color: #c4c4c4\">Fill in some text</span>'\n        );\n      });\n\n      it('should allow saving text background color', async () => {\n        // Add text element\n        await fixture.editor.library.textTab.click();\n        await fixture.events.click(\n          fixture.editor.library.text.preset('Paragraph')\n        );\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n          expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n        });\n        // add fill\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fill\n        );\n\n        // save default text fill to local palette\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.backgroundColor.button\n        );\n        const picker =\n          fixture.editor.sidebar.designPanel.textStyle.backgroundColor.picker;\n        await fixture.events.click(picker.addSavedColor('local'));\n\n        // check if default text fill is saved\n        expect(picker.applySavedColor('#c4c4c4')).toBeTruthy();\n      });\n    });\n\n    describe('CUJ: Creator can Apply or Save a Color from/to Their Preset Library: Manage Color Presets', () => {\n      it('should allow deleting local and global color presets', async () => {\n        // Add text element and a color preset.\n        await fixture.editor.library.textTab.click();\n        await fixture.events.click(\n          fixture.editor.library.text.preset('Paragraph')\n        );\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n          expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n        });\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.button\n        );\n        const picker =\n          fixture.editor.sidebar.designPanel.textStyle.fontColor.picker;\n        await fixture.events.click(picker.addSavedColor('global'));\n        await fixture.events.click(picker.addSavedColor('local'));\n\n        await fixture.events.click(picker.editButton);\n\n        await fixture.snapshot('Color presets in edit mode');\n\n        // Verify being in edit mode.\n\n        expect(picker.exitEditButton).toBeTruthy();\n        expect(picker.deleteGlobalColor).toBeTruthy();\n        // Verify edit mode has no aXe violations.\n        await expectAsync(picker.exitEditButton).toHaveNoViolations();\n        await expectAsync(picker.deleteGlobalColor).toHaveNoViolations();\n\n        // Delete global preset.\n        await fixture.events.click(picker.deleteGlobalColor);\n\n        // Confirm both the color picker and the confirmation dialog are open since it's a global color.\n        await waitFor(() => {\n          if (fixture.screen.getAllByRole('dialog').length !== 2) {\n            throw new Error('dialog not ready');\n          }\n          expect(fixture.screen.getAllByRole('dialog').length).toBe(2);\n        });\n        await fixture.events.click(\n          fixture.screen.getByRole('button', { name: 'Delete' })\n        );\n\n        // Delete local preset.\n        await fixture.events.click(picker.deleteStoryColor);\n\n        // Verify the edit mode was exited (due to removing all elements).\n        expect(() => picker.exitEditButton).toThrow();\n\n        // Verify there is no edit button either (since we have no presets left).\n        expect(() => picker.editButton).toThrow();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/karma/eyedropper.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app';\n\ndescribe('Eyedropper', () => {\n  let fixture;\n  let eyeDropper;\n\n  beforeAll(() => {\n    eyeDropper = window.EyeDropper;\n\n    // removed to run test against htmlToImage EyeDropper vs API\n    // see issue testing with native API here\n    // https://github.com/GoogleForCreators/web-stories-wp/pull/11739#issuecomment-1162367409\n    delete window.EyeDropper;\n  });\n\n  afterAll(() => {\n    window.EyeDropper = eyeDropper;\n  });\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    // removed to run test against htmlToImage EyeDropper vs API\n    // see issue testing with native API here\n    // https://github.com/GoogleForCreators/web-stories-wp/pull/11739#issuecomment-1162367409\n    delete window.EyeDropper;\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getElements = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n\n    return storyContext.state.currentPage.elements;\n  };\n\n  function getCanvasElementWrapperById(id) {\n    return fixture.querySelector(\n      `[data-testid=\"safezone\"] [data-element-id=\"${id}\"]`\n    );\n  }\n\n  it('should get color from the image to page background', async () => {\n    // Insert image that will be the color source\n    const image = fixture.editor.library.media.item(1);\n    const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n    await fixture.events.mouse.seq(({ down, moveRel, up }) => [\n      moveRel(image, 1, 1),\n      down(),\n      moveRel(canvas, 30, 30),\n      up(),\n    ]);\n\n    await fixture.collapseHelpCenter();\n\n    // Click the background element\n    await fixture.events.mouse.clickOn(\n      fixture.editor.canvas.framesLayer.frames[0].node,\n      10,\n      10\n    );\n\n    // Use eyedropper to select the color\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const bgPanel = fixture.editor.sidebar.designPanel.pageBackground;\n    await fixture.events.click(bgPanel.backgroundColor.button);\n    await waitFor(() => {\n      if (!bgPanel.backgroundColor.picker) {\n        throw new Error('picker not ready');\n      }\n      expect(bgPanel.backgroundColor.picker).toBeDefined();\n    });\n    // Go to the custom color view\n    await fixture.events.click(bgPanel.backgroundColor.picker.custom);\n    // Contents of the color picker are lazy loaded\n    await waitFor(() => {\n      if (!bgPanel.backgroundColor.picker.eyedropper) {\n        throw new Error('eyedropper not ready');\n      }\n      expect(bgPanel.backgroundColor.picker.eyedropper).toBeDefined();\n    });\n    // Click the eyedropper icon in the custom view\n    await fixture.events.click(bgPanel.backgroundColor.picker.eyedropper);\n    // The bots are a little too fast, wait for eyedropper\n    await fixture.events.sleep(500);\n    const eyeDropperLayer =\n      await fixture.screen.findByTestId('eyedropperLayer');\n    expect(eyeDropperLayer).toBeTruthy();\n\n    const imageOnCanvas = (await getElements(fixture))[1];\n    const imageOnCanvasRect = (\n      await getCanvasElementWrapperById(imageOnCanvas.id)\n    ).getBoundingClientRect();\n    await fixture.events.mouse.click(\n      imageOnCanvasRect.right - 2,\n      imageOnCanvasRect.top + 8\n    );\n    await fixture.snapshot('BG color from image');\n\n    await waitFor(() => {\n      if (bgPanel.backgroundColor.hex.value !== 'DBB198') {\n        throw new Error('bg color not updated yet');\n      }\n      expect(\n        fixture.editor.sidebar.designPanel.pageBackground.backgroundColor.hex\n          .value\n      ).toBe('DBB198');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/patternTypePicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  ToggleButton,\n  Icons,\n  ButtonSize,\n  ButtonVariant,\n  ButtonType,\n} from '@googleforcreators/design-system';\n\nconst HEADER_FOOTER_HEIGHT = 52;\n\nconst Wrapper = styled.div`\n  display: flex;\n  justify-content: flex-start;\n  align-items: center;\n  height: ${HEADER_FOOTER_HEIGHT}px;\n  padding: 0 16px;\n  position: relative;\n  gap: 8px;\n`;\n\nfunction PatternTypePicker({ type, setToGradient, setToSolid }) {\n  const setToLinear = useCallback(\n    () => setToGradient('linear'),\n    [setToGradient]\n  );\n  const setToRadial = useCallback(\n    () => setToGradient('radial'),\n    [setToGradient]\n  );\n\n  return (\n    <Wrapper>\n      <ToggleButton\n        aria-label={__('Solid pattern type', 'web-stories')}\n        onClick={setToSolid}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        isToggled={type === 'solid'}\n      >\n        <Icons.PatternSolid />\n      </ToggleButton>\n      <ToggleButton\n        aria-label={__('Linear gradient pattern type', 'web-stories')}\n        onClick={setToLinear}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        isToggled={type === 'linear'}\n      >\n        <Icons.PatternLinear />\n      </ToggleButton>\n      <ToggleButton\n        aria-label={__('Radial gradient pattern type', 'web-stories')}\n        onClick={setToRadial}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        isToggled={type === 'radial'}\n      >\n        <Icons.PatternRadial />\n      </ToggleButton>\n    </Wrapper>\n  );\n}\n\nPatternTypePicker.propTypes = {\n  type: PropTypes.string.isRequired,\n  setToGradient: PropTypes.func.isRequired,\n  setToSolid: PropTypes.func.isRequired,\n};\n\nexport default PatternTypePicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/pointer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app';\n\nconst rgb = ({ r = 0, g = 0, b = 0 } = {}) => {\n  return `rgb(${r},${g},${b})`;\n};\n\nconst rgba = ({ r, g, b, a }) => {\n  const al = (color) => (1 - a) * 255 + a * color;\n  return `rgb(${al(r)}, ${al(g)}, ${al(b)})`;\n};\n\nconst POINTER_SIZE = 16;\nconst BORDER_WIDTH = 2;\n\n// The attrs method is more performant for frequently changed styles.\nconst PointerElement = styled.div.attrs(({ currentColor = {}, withAlpha }) => {\n  return {\n    style: {\n      background: withAlpha ? rgba(currentColor) : rgb(currentColor),\n    },\n  };\n})`\n  width: ${POINTER_SIZE}px;\n  height: ${POINTER_SIZE}px;\n  transform: translate(\n    ${({ offsetX = 0, offsetY = 0, isRTL }) =>\n      `${(isRTL ? -1 : 1) * offsetX}px, ${offsetY}px`}\n  );\n  background: transparent;\n  border: ${BORDER_WIDTH}px solid ${({ theme }) => theme.colors.fg.primary};\n  border-radius: 100%;\n  position: relative;\n\n  &:before {\n    content: '';\n    display: block;\n    width: ${2 * POINTER_SIZE}px;\n    height: ${2 * POINTER_SIZE}px;\n    position: absolute;\n    top: -${POINTER_SIZE / 2 + BORDER_WIDTH}px;\n    left: -${POINTER_SIZE / 2 + BORDER_WIDTH}px;\n  }\n`;\n\nfunction Pointer(props) {\n  const { isRTL } = useConfig();\n  return <PointerElement {...props} isRTL={isRTL} />;\n}\n\nexport default Pointer;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/regenerateColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\nimport { TYPE_SOLID, TYPE_LINEAR, TYPE_RADIAL } from './constants';\n\nfunction regenerateSolid({ currentColor: { r, g, b, a } }) {\n  return createSolid(r, g, b, a);\n}\n\nfunction regenerateStops(stops) {\n  return stops.map(({ color: { r, g, b, a }, position }) => ({\n    color: createSolid(r, g, b, a).color,\n    position,\n  }));\n}\n\nfunction regenerateLinear({ stops, rotation, alpha }) {\n  const minimal = {\n    type: TYPE_LINEAR,\n    stops: regenerateStops(stops),\n  };\n  if (rotation !== 0) {\n    minimal.rotation = rotation;\n  }\n  if (alpha !== 1 && alpha !== undefined) {\n    minimal.alpha = alpha;\n  }\n  return minimal;\n}\n\nfunction regenerateRadial({ stops, center, size, alpha }) {\n  const minimal = {\n    type: TYPE_RADIAL,\n    stops: regenerateStops(stops),\n  };\n  if (center && (center.x !== 0.5 || center.y !== 0.5)) {\n    minimal.center = center;\n  }\n  if (size && (size.w !== 1 || size.h !== 1)) {\n    minimal.size = size;\n  }\n  if (alpha !== 1 && alpha !== undefined) {\n    minimal.alpha = alpha;\n  }\n  return minimal;\n}\n\nfunction regenerateColor(pattern) {\n  const { regenerate, type } = pattern;\n  if (!regenerate) {\n    return null;\n  }\n\n  switch (type) {\n    case TYPE_SOLID:\n      return regenerateSolid(pattern);\n    case TYPE_LINEAR:\n      return regenerateLinear(pattern);\n    case TYPE_RADIAL:\n      return regenerateRadial(pattern);\n\n    // Ignore reason: only required for eslint, won't actually happen\n    // istanbul ignore next\n    default:\n      return null;\n  }\n}\n\nexport default regenerateColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen, within } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport theme from '../../../../theme';\nimport ColorPicker from '../..';\n\nfunction arrange(customProps = {}) {\n  const onChange = jest.fn();\n  const onClose = jest.fn();\n  const props = {\n    onChange,\n    onClose,\n    ...customProps,\n  };\n  const view = renderWithTheme(<ColorPicker {...props} />);\n  const { rerender } = view;\n  const getDialog = () => screen.getByRole('dialog');\n  const getSolidButton = () => screen.queryByLabelText(/solid pattern/i);\n  const getLinearButton = () =>\n    screen.queryByLabelText(/linear gradient pattern/i);\n  const getRadialButton = () =>\n    screen.queryByLabelText(/radial gradient pattern/i);\n  const getCloseButton = () => screen.queryByLabelText(/close/i);\n  const getEditableHexElement = () => screen.getByLabelText(/edit hex/i);\n  const getEditableAlphaElement = () =>\n    screen.queryByLabelText(/edit opacity/i);\n  const getGradientLine = () => screen.queryByLabelText(/gradient line/i);\n  const getGradientStops = () =>\n    screen.queryAllByLabelText(/^gradient stop at/i);\n  // The gradient line is reversed, so we deduct the value from 100.\n  const getGradientStopAt = (pct) =>\n    screen.queryByLabelText(new RegExp(`gradient stop at ${100 - pct}%`, 'i'));\n  const getTempGradientStop = () =>\n    screen.queryByLabelText(/temporary gradient stop/i);\n  const getGradientReverse = () =>\n    screen.queryByLabelText(/reverse gradient stops/i);\n  const getGradientRotate = () => screen.queryByLabelText(/rotate gradient/i);\n  const getSwatchList = (name) => screen.queryByRole('listbox', { name });\n  const getSwatches = (list) =>\n    within(getSwatchList(list)).getAllByRole('option');\n  const getEnabledSwatches = (list) =>\n    within(getSwatchList(list))\n      .getAllByRole('option')\n      .filter(\n        (e) => !e.hasAttribute('disabled') && !e.hasAttribute('aria-disabled')\n      );\n  const getSwatchByLabel = (list, name) =>\n    within(getSwatchList(list)).getByRole('option', { name });\n  const getSelectedSwatch = (list) =>\n    within(getSwatchList(list)).queryByRole('option', {\n      selected: true,\n    });\n  const getCustomButton = () => screen.getByRole('button', { name: 'Custom' });\n  const getAddCustomButton = () =>\n    screen.getByRole('button', { name: 'Add to Saved Colors' });\n  const getBackButton = () => screen.getByRole('button', { name: 'Go back' });\n  const wrapperRerender = (moreCustomProps) =>\n    rerender(\n      <ThemeProvider theme={theme}>\n        <ColorPicker {...props} {...moreCustomProps} />\n      </ThemeProvider>\n    );\n  return {\n    ...view,\n    getDialog,\n    getSolidButton,\n    getLinearButton,\n    getRadialButton,\n    getCloseButton,\n    getEditableHexElement,\n    getEditableAlphaElement,\n    getGradientLine,\n    getGradientStops,\n    getGradientStopAt,\n    getTempGradientStop,\n    getGradientReverse,\n    getGradientRotate,\n    getSwatchList,\n    getEnabledSwatches,\n    getSwatches,\n    getSwatchByLabel,\n    getSelectedSwatch,\n    getCustomButton,\n    getAddCustomButton,\n    getBackButton,\n    onChange,\n    onClose,\n    rerender: wrapperRerender,\n  };\n}\n\nexport { arrange };\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/addStopByPointer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport { firePointerEvent } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { LINE_LENGTH } from '../../constants';\nimport { arrange } from './_utils';\n\n// There's a slight offset, so +1\nconst OFFSET20 = LINE_LENGTH * 0.2 + 1;\n\ndescribe('<ColorPicker /> when adding a stop with a pointer device', () => {\n  it('should show temp stop when hovering and add a stop when clicking', async () => {\n    const { getGradientLine, getGradientStops, getTempGradientStop, onChange } =\n      arrange({\n        color: {\n          type: 'linear',\n          stops: [\n            { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n            { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n          ],\n        },\n        allowsGradient: true,\n      });\n\n    // Initially 2 stops should be visible\n    await waitFor(() => expect(getGradientStops()).toHaveLength(2));\n\n    // No temp stop visible initially\n    expect(getTempGradientStop()).not.toBeInTheDocument();\n\n    // Hover gradient line at 20% mark\n    firePointerEvent.pointerMove(getGradientLine(), {\n      clientX: OFFSET20,\n    });\n\n    // Expect a temp stop be added at 20%\n    expect(getTempGradientStop()).toBeInTheDocument();\n    expect(getTempGradientStop()).toHaveAttribute(\n      'aria-label',\n      // Due to rounding, the stop might be reported as being at 21%\n      expect.stringMatching(/temporary gradient stop at 2[01]%/i)\n    );\n\n    // Click gradient line at 20% mark\n    firePointerEvent.pointerDown(getGradientLine(), {\n      clientX: OFFSET20,\n    });\n\n    // Temp stop should be removed now\n    expect(getTempGradientStop()).not.toBeInTheDocument();\n\n    // 3 stops should be visible\n    expect(getGradientStops()).toHaveLength(3);\n\n    // And gradient should now have an extra stop\n    // Note that actual color is not tested here - see tests of insertStop and useColor for that\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n        {\n          color: {\n            r: expect.any(Number),\n            g: expect.any(Number),\n            b: expect.any(Number),\n            a: expect.any(Number),\n          },\n          position: expect.closeTo(0.8, 1),\n        },\n        { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should remove temp stop when pointer leaves the gradient line', async () => {\n    const { getGradientLine, getTempGradientStop } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n          { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // No temp stop visible initially\n    await waitFor(() => expect(getTempGradientStop()).not.toBeInTheDocument());\n\n    // Hover gradient line at 20% mark\n    firePointerEvent.pointerMove(getGradientLine(), {\n      clientX: OFFSET20,\n    });\n\n    // Expect temp stop to be visible\n    expect(getTempGradientStop()).toBeInTheDocument();\n\n    // Move pointer out\n    firePointerEvent.pointerLeave(getGradientLine());\n\n    // Temp stop should be removed now\n    expect(getTempGradientStop()).not.toBeInTheDocument();\n  });\n\n  it('should not add temp stop when hovering existing stop', async () => {\n    const { getGradientStopAt, getTempGradientStop } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n          { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // No temp stop visible initially\n    await waitFor(() => expect(getTempGradientStop()).not.toBeInTheDocument());\n\n    // Hover first stop (and give a fake offset)\n    firePointerEvent.pointerMove(getGradientStopAt(0), {\n      clientX: OFFSET20,\n    });\n\n    // Temp stop should still not be in the document\n    expect(getTempGradientStop()).not.toBeInTheDocument();\n  });\n\n  it('should not add a new stop when clicking existing stop', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n          { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Click first stop (and give a fake offset)\n    firePointerEvent.pointerDown(getGradientStopAt(0), {\n      clientX: OFFSET20,\n    });\n\n    await waitFor(() => expect(onChange).not.toHaveBeenCalled());\n  });\n\n  it('should not remove temp stop when pointer leaves existing gradient stop', async () => {\n    const { getGradientLine, getTempGradientStop, getGradientStopAt } = arrange(\n      {\n        color: {\n          type: 'linear',\n          stops: [\n            { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n            { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n          ],\n        },\n        allowsGradient: true,\n      }\n    );\n\n    // No temp stop visible initially\n    await waitFor(() => expect(getTempGradientStop()).not.toBeInTheDocument());\n\n    // Hover gradient line at 20% mark\n    firePointerEvent.pointerMove(getGradientLine(), {\n      clientX: OFFSET20,\n    });\n\n    // Expect temp stop to be visible\n    expect(getTempGradientStop()).toBeInTheDocument();\n\n    // Move pointer out from stop at 0%\n    firePointerEvent.pointerLeave(getGradientStopAt(0));\n\n    // Temp stop should still be in the document\n    expect(getTempGradientStop()).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/colorInteraction.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport {\n  TEXT_ELEMENT_DEFAULT_FONT,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport ColorPicker from '../../colorPicker';\nimport { StoryContext } from '../../../../app/story';\nimport {\n  getShapePresets,\n  getTextPresets,\n  getPagePreset,\n  areAllType,\n} from '../../../../utils/presetUtils';\n\njest.mock('../../../../utils/presetUtils');\n\nfunction arrange(extraStylePresets, extraStateProps, extraStoryPresets) {\n  const updateStory = jest.fn();\n  const updateElementsById = jest.fn();\n  const updateCurrentPageProperties = jest.fn();\n  const pushUpdate = jest.fn();\n\n  const textElement = {\n    id: '1',\n    type: 'text',\n  };\n  const storyContextValue = {\n    state: {\n      currentPage: {\n        elements: [\n          {\n            id: 'bg',\n            type: 'shape',\n          },\n          textElement,\n        ],\n      },\n      selectedElementIds: ['1'],\n      selectedElements: [textElement],\n      ...extraStateProps,\n      story: {\n        globalStoryStyles: {\n          colors: [],\n          textStyles: [],\n          ...extraStylePresets,\n        },\n        currentStoryStyles: {\n          colors: [],\n          ...extraStoryPresets,\n        },\n      },\n    },\n    actions: { updateStory, updateElementsById, updateCurrentPageProperties },\n  };\n\n  const {\n    getAllByRole,\n    getByRole,\n    getByText,\n    queryByLabelText,\n    getByLabelText,\n    queryByText,\n    queryAllByLabelText,\n    container,\n  } = renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <ColorPicker allowsSavedColors onChange={() => jest.fn()} />\n    </StoryContext.Provider>\n  );\n  setAppElement(container);\n  return {\n    getAllByRole,\n    getByRole,\n    getByText,\n    queryByText,\n    getByLabelText,\n    pushUpdate,\n    queryByLabelText,\n    queryAllByLabelText,\n    updateStory,\n    updateElementsById,\n    updateCurrentPageProperties,\n  };\n}\n\nconst EDIT_BUTTON_LABEL = 'Edit colors';\nconst ADD_LOCAL_LABEL = 'Add local color';\nconst ADD_GLOBAL_LABEL = 'Add global color';\nconst TEST_COLOR = {\n  color: {\n    r: 1,\n    g: 1,\n    b: 1,\n  },\n};\nconst TEST_COLOR_2 = {\n  color: {\n    r: 2,\n    g: 2,\n    b: 2,\n  },\n};\n\nconst BACKGROUND_PROPS = {\n  backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n  backgroundColor: TEST_COLOR,\n};\n\ndescribe('colorPicker/colorsInteraction', () => {\n  beforeAll(() => {\n    areAllType.mockImplementation((elType, els) => {\n      return els.length > 0 && els.every(({ type }) => elType === type);\n    });\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  describe('colorPicker/Header', () => {\n    it('should not display edit button if no presets exist', () => {\n      arrange();\n\n      const editButton = screen.queryByLabelText(EDIT_BUTTON_LABEL);\n      expect(editButton).not.toBeInTheDocument();\n    });\n\n    it('should display buttons for adding local/global color if no presets exist', () => {\n      arrange();\n      const addLocal = screen.queryByLabelText(ADD_LOCAL_LABEL);\n      expect(addLocal).toBeInTheDocument();\n\n      const addGlobal = screen.queryByLabelText(ADD_GLOBAL_LABEL);\n      expect(addGlobal).toBeInTheDocument();\n    });\n\n    it('should have functional Edit button if relevant presets exist', () => {\n      const extraStylePresets = {\n        colors: [TEST_COLOR],\n      };\n      arrange(extraStylePresets);\n      const editButton = screen.getByLabelText(EDIT_BUTTON_LABEL);\n      expect(editButton).toBeInTheDocument();\n\n      fireEvent.click(editButton);\n      const exitEditModeButton = screen.getByLabelText('Exit edit mode');\n      expect(exitEditModeButton).toBeInTheDocument();\n      expect(\n        screen.queryByLabelText(EDIT_BUTTON_LABEL)\n      ).not.toBeInTheDocument();\n\n      fireEvent.click(exitEditModeButton);\n      const newEditButton = screen.getByLabelText(EDIT_BUTTON_LABEL);\n      expect(newEditButton).toBeInTheDocument();\n    });\n\n    it('should add a text color preset', () => {\n      const extraStateProps = {\n        selectedElements: [\n          {\n            id: '1',\n            type: 'text',\n            content: '<span style=\"color: rgb(2, 2, 2)\">Content</span>',\n            backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n            font: TEXT_ELEMENT_DEFAULT_FONT,\n          },\n        ],\n      };\n      const { updateStory } = arrange(null, extraStateProps);\n\n      getTextPresets.mockImplementation(() => {\n        return {\n          colors: [TEST_COLOR_2],\n          textStyles: [],\n        };\n      });\n\n      // Global color for the current story.\n      const addButton = screen.queryByLabelText(ADD_GLOBAL_LABEL);\n      fireEvent.click(addButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [TEST_COLOR_2],\n            textStyles: [],\n          },\n        },\n      });\n\n      updateStory.mockReset();\n\n      // Local color for all stories.\n      const addLocal = screen.queryByLabelText(ADD_LOCAL_LABEL);\n      fireEvent.click(addLocal);\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          currentStoryStyles: {\n            colors: [TEST_COLOR_2],\n          },\n        },\n      });\n    });\n\n    it('should add color preset from a Text with correct values when multiple styles have changed', () => {\n      const extraStateProps = {\n        selectedElements: [\n          {\n            id: '1',\n            type: 'text',\n            content: '<span style=\"color: rgba(2, 2, 2, 1)\">Content</span>',\n            ...BACKGROUND_PROPS,\n          },\n        ],\n      };\n      const { updateStory } = arrange(null, extraStateProps);\n\n      getTextPresets.mockImplementation(() => {\n        return {\n          colors: [TEST_COLOR_2],\n        };\n      });\n\n      // Global color.\n      const addButton = screen.queryByLabelText(ADD_GLOBAL_LABEL);\n      fireEvent.click(addButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [TEST_COLOR_2],\n            textStyles: [],\n          },\n        },\n      });\n\n      updateStory.mockReset();\n      // Color for current story.\n      const addLocal = screen.queryByLabelText(ADD_LOCAL_LABEL);\n      fireEvent.click(addLocal);\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          currentStoryStyles: {\n            colors: [TEST_COLOR_2],\n          },\n        },\n      });\n    });\n\n    it('should allow adding presets from shapes', () => {\n      const extraStateProps = {\n        selectedElements: [\n          {\n            id: '1',\n            type: 'shape',\n            backgroundColor: [TEST_COLOR_2],\n          },\n        ],\n      };\n      const { updateStory } = arrange(null, extraStateProps);\n\n      getShapePresets.mockImplementation(() => {\n        return {\n          colors: [TEST_COLOR_2],\n        };\n      });\n\n      const addButton = screen.queryByLabelText(ADD_GLOBAL_LABEL);\n      fireEvent.click(addButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [TEST_COLOR_2],\n            textStyles: [],\n          },\n        },\n      });\n\n      updateStory.mockReset();\n      // Color for current story.\n      const addLocal = screen.queryByLabelText(ADD_LOCAL_LABEL);\n      fireEvent.click(addLocal);\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          currentStoryStyles: {\n            colors: [TEST_COLOR_2],\n          },\n        },\n      });\n    });\n\n    it('should allow adding preset from the background', () => {\n      const extraStateProps = {\n        selectedElements: [\n          {\n            id: 'bg',\n          },\n        ],\n      };\n      const { updateStory } = arrange(null, extraStateProps);\n\n      getPagePreset.mockImplementation(() => {\n        return {\n          colors: [TEST_COLOR_2],\n        };\n      });\n\n      const addButton = screen.queryByLabelText(ADD_GLOBAL_LABEL);\n      fireEvent.click(addButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [TEST_COLOR_2],\n            textStyles: [],\n          },\n        },\n      });\n\n      updateStory.mockReset();\n      // Color for current story.\n      const addLocal = screen.queryByLabelText(ADD_LOCAL_LABEL);\n      fireEvent.click(addLocal);\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          currentStoryStyles: {\n            colors: [TEST_COLOR_2],\n          },\n        },\n      });\n    });\n  });\n\n  describe('colorPicker/colorInteraction', () => {\n    it('should allow deleting the relevant color preset', () => {\n      const extraStylePresets = {\n        colors: [TEST_COLOR, TEST_COLOR_2],\n      };\n      const extraStoryPresets = {\n        colors: [TEST_COLOR, TEST_COLOR_2],\n      };\n      const { updateStory } = arrange(\n        extraStylePresets,\n        null,\n        extraStoryPresets\n      );\n      const editButton = screen.getByLabelText(EDIT_BUTTON_LABEL);\n      fireEvent.click(editButton);\n\n      const deletePresets = screen.queryAllByTitle(/Delete global color/);\n\n      expect(deletePresets[0]).toBeDefined();\n\n      fireEvent.click(deletePresets[0]);\n      const confirmationButton = screen.getByRole('button', { name: 'Delete' });\n      fireEvent.click(confirmationButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [TEST_COLOR_2],\n            textStyles: [],\n          },\n        },\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/footerInteraction.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, fireEvent, act } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\n\nimport { arrange } from './_utils';\n\njest.mock(\n  '../../../../app/story/useStory',\n  () => (cb) =>\n    cb({\n      state: {\n        story: {\n          globalStoryStyles: {\n            colors: [],\n          },\n          selectedElements: [],\n        },\n      },\n      actions: {\n        updateStory: jest.fn(),\n      },\n    })\n);\n\ndescribe('<ColorPicker /> as the footer is interacted with', () => {\n  it('should set hex when edited and invoke onChange', async () => {\n    const { getCustomButton, getEditableHexElement, onChange } = arrange({\n      color: createSolid(0, 0, 255),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n\n    await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n\n    // At first it's a button\n    const initialButton = getEditableHexElement();\n    expect(initialButton).toHaveTextContent(/#0000ff/i);\n    fireEvent.click(initialButton);\n\n    // When clicked, it's an input\n    await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n    const input = getEditableHexElement();\n    expect(input).toHaveValue('0000FF'); // toHaveValue doesn't support regex\n    await waitFor(() => expect(input).toHaveFocus());\n    fireEvent.change(input, { target: { value: 'ff00ff' } });\n\n    // Press esc to abort editing\n    fireEvent.keyDown(input, { key: 'Escape', which: 27 });\n\n    // It's the button again\n    await waitFor(() =>\n      expect(getEditableHexElement()).toHaveTextContent(/#ff00ff/i)\n    );\n\n    expect(onChange).toHaveBeenCalledWith(createSolid(255, 0, 255));\n  });\n\n  it('should set opacity when edited and invoke onChange', async () => {\n    const {\n      getCustomButton,\n      getEditableAlphaElement,\n      getSolidButton,\n      onChange,\n    } = arrange({\n      color: createSolid(0, 0, 255, 0.4),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n\n    // At first it's a button\n    const initialButton = getEditableAlphaElement();\n    expect(initialButton).toHaveTextContent(/40%/i);\n    fireEvent.click(initialButton);\n\n    // When clicked, it's an input\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n    const input = getEditableAlphaElement();\n    expect(input).toHaveValue('40');\n    await waitFor(() => expect(input).toHaveFocus());\n    fireEvent.change(input, { target: { value: '70' } });\n\n    // focus solid button in order to blur and thus abort editin\n    // NB: has to be done with `act` rather than `fireEvent.focus` due to\n    // https://github.com/testing-library/react-testing-library/issues/376\n    act(() => getSolidButton().focus());\n\n    // It's the button again\n    await waitFor(() =>\n      expect(getEditableAlphaElement()).toHaveTextContent(/70%/i)\n    );\n\n    expect(onChange).toHaveBeenCalledWith(createSolid(0, 0, 255, 0.7));\n  });\n\n  it('should set opacity to default when edited with illegal value and invoke onChange', async () => {\n    const {\n      getCustomButton,\n      getEditableAlphaElement,\n      getSolidButton,\n      onChange,\n    } = arrange({\n      color: createSolid(0, 0, 255, 0.4),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n\n    // At first it's a button\n    const initialButton = getEditableAlphaElement();\n    fireEvent.click(initialButton);\n\n    // When clicked, it's an input\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n    const input = getEditableAlphaElement();\n    await waitFor(() => expect(input).toHaveFocus());\n    fireEvent.change(input, { target: { value: 'ten' } });\n\n    // focus solid button in order to blur and thus abort editing\n    // NB: has to be done with `act` rather than `fireEvent.focus` due to\n    // https://github.com/testing-library/react-testing-library/issues/376\n    act(() => getSolidButton().focus());\n\n    // It's the button again\n    await waitFor(() =>\n      expect(getEditableAlphaElement()).toHaveTextContent(/100%/i)\n    );\n\n    expect(onChange).toHaveBeenCalledWith(createSolid(0, 0, 255, 1));\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/headerInteraction.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\njest.mock(\n  '../../../../app/story/useStory',\n  () => (cb) =>\n    cb({\n      state: {\n        story: {\n          globalStoryStyles: {\n            colors: [],\n          },\n          selectedElements: [],\n        },\n      },\n      actions: {\n        updateStory: jest.fn(),\n      },\n    })\n);\n\ndescribe('<ColorPicker /> as the header is interacted with', () => {\n  it('should invoke onchange with new correct pattern when switching to linear', async () => {\n    const { getCustomButton, getLinearButton, onChange } = arrange({\n      color: createSolid(0, 0, 255),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n    fireEvent.click(getLinearButton());\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        rotation: 0.5,\n        stops: [\n          { color: { r: 0, g: 0, b: 255 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n        type: 'linear',\n      })\n    );\n  });\n\n  it('should invoke onchange with new correct pattern when switching to radial', async () => {\n    const { getCustomButton, getRadialButton, onChange } = arrange({\n      color: createSolid(0, 0, 255),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n    fireEvent.click(getRadialButton());\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        stops: [\n          { color: { r: 0, g: 0, b: 255 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n        type: 'radial',\n      })\n    );\n  });\n\n  it('should display gradient line only if switching to non-solid pattern', async () => {\n    const {\n      getCustomButton,\n      getGradientLine,\n      getSolidButton,\n      getLinearButton,\n    } = arrange({\n      color: createSolid(0, 0, 0),\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getCustomButton());\n\n    await waitFor(() => expect(getGradientLine()).not.toBeInTheDocument());\n    fireEvent.click(getLinearButton());\n    expect(getGradientLine()).toBeInTheDocument();\n    fireEvent.click(getSolidButton());\n    expect(getGradientLine()).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/manipulateGradient.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\ndescribe('<ColorPicker /> when manipulating a gradient', () => {\n  it('should have stops reversed when reverse button is clicked', async () => {\n    const { getGradientReverse, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.4 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getGradientReverse());\n\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 0, g: 0, b: 255 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0 }, position: 0.6 },\n        { color: { r: 255, g: 0, b: 0 }, position: 1 },\n      ],\n    });\n\n    fireEvent.click(getGradientReverse());\n\n    // Wait for callback to have been called a second time after debounce\n    await waitFor(() => expect(onChange).toHaveBeenCalledTimes(2));\n\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should have rotation changed by .25 turn when rotate button is clicked', async () => {\n    const { getGradientRotate, onChange } = arrange({\n      color: {\n        type: 'linear',\n        rotation: 0.25,\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    fireEvent.click(getGradientRotate());\n\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      rotation: 0.5,\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n\n    fireEvent.click(getGradientRotate());\n    fireEvent.click(getGradientRotate());\n\n    // Wait for callback to have been called a second time after debounce\n    await waitFor(() => expect(onChange).toHaveBeenCalledTimes(2));\n\n    // Because rotation is now at 0, it's not included\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/manipulateStopByKeyboard.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\ndescribe('<ColorPicker /> when manipulating stops using keyboard', () => {\n  it('should delete stop when pressing delete when gradient line is focused', async () => {\n    const { getGradientLine, getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.5 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Send key to gradient line itself, not a stop\n    fireEvent.keyDown(getGradientLine(), { key: 'Delete', which: 46 });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0 }, position: 0.5 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n\n    // Expect next stop to have focus now, so that any\n    // future key presses will still be correctly handled\n    await waitFor(() => expect(getGradientStopAt(50)).toHaveFocus());\n  });\n\n  it('should delete stop when pressing backspace when gradient stop is focused', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.5 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Select middle stop\n    fireEvent.click(getGradientStopAt(50));\n    fireEvent.keyDown(getGradientStopAt(50), { key: 'Backspace', which: 8 });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n\n    // Expect last stop to have focus now, so that any\n    // future key presses will still be correctly handled\n    await waitFor(() => expect(getGradientStopAt(100)).toHaveFocus());\n  });\n\n  it('should move stop when pressing arrow keys', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.5 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const firstStop = getGradientStopAt(100);\n    fireEvent.click(firstStop);\n\n    // Move first stop left (does nothing)\n    fireEvent.keyDown(firstStop, { key: 'ArrowLeft', which: 37 });\n\n    await waitFor(() => expect(onChange).not.toHaveBeenCalled());\n\n    // Move first stop right 10 times\n    Array(10)\n      .fill(0)\n      .forEach(() =>\n        fireEvent.keyDown(firstStop, {\n          key: 'ArrowRight',\n          which: 39,\n        })\n      );\n\n    // Wait for callback to have been called a second time after debounce\n    await waitFor(() => expect(onChange).toHaveBeenCalledTimes(2));\n\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0 }, position: 0.5 },\n        { color: { r: 0, g: 0, b: 255 }, position: 0.9 },\n      ],\n    });\n  });\n\n  it('should reorder stops when moving with arrow keys past another stop', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.995 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const firstStop = getGradientStopAt(100);\n    fireEvent.click(firstStop);\n    fireEvent.keyDown(firstStop, {\n      key: 'ArrowRight',\n      which: 39,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 0.99 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.995 },\n        ],\n      })\n    );\n  });\n\n  it('should add a stop before first stop if selected and not at 0 when pressing enter', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0.2 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const firstStop = getGradientStopAt(20);\n    fireEvent.click(firstStop);\n    fireEvent.keyDown(firstStop, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 255, g: 0, b: 0 }, position: 0.2 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n  });\n\n  it('should add a stop after last stop if selected and not at 100 when pressing enter', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 0.8 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const lastStop = getGradientStopAt(80);\n    fireEvent.click(lastStop);\n    fireEvent.keyDown(lastStop, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 255 }, position: 0.8 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n  });\n\n  it('should add a stop half-way after the current stop if not last when pressing enter', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.2 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const someStop = getGradientStopAt(20);\n    fireEvent.click(someStop);\n    fireEvent.keyDown(someStop, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.2 },\n          {\n            color: { r: 0, g: expect.any(Number), b: expect.any(Number) },\n            position: 0.6,\n          },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n  });\n\n  it('should add a stop half-way before the current stop if last at 100 when pressing enter', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.2 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    const lastStop = getGradientStopAt(100);\n    fireEvent.click(lastStop);\n    fireEvent.keyDown(lastStop, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.2 },\n          {\n            color: { r: 0, g: expect.any(Number), b: expect.any(Number) },\n            position: 0.6,\n          },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/moveStopByPointer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor } from '@testing-library/react';\nimport { firePointerEvent } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { LINE_LENGTH } from '../../constants';\nimport { arrange } from './_utils';\n\ndescribe('<ColorPicker /> when moving a stop with a pointer device', () => {\n  it('should move stop when dragging a stop', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n          { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Get first gradient stop\n    const stop = getGradientStopAt(100);\n\n    // Click it to make sure it's selected\n    fireEvent.click(stop);\n\n    // Click at position 0\n    firePointerEvent.pointerDown(stop, {\n      clientX: 0,\n    });\n\n    // Move to the 30% mark\n    firePointerEvent.pointerMove(stop, {\n      clientX: 0.3 * LINE_LENGTH,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n          {\n            color: { r: 255, g: 0, b: 255, a: 0.8 },\n            position: expect.closeTo(0.7, 1),\n          },\n        ],\n      })\n    );\n    onChange.mockReset();\n\n    // Move to the 40% mark\n    firePointerEvent.pointerMove(stop, {\n      clientX: 0.4 * LINE_LENGTH,\n    });\n\n    // Wait for callback to have been called after debounce\n    await waitFor(() => expect(onChange).toHaveBeenCalledOnce());\n\n    expect(onChange).toHaveBeenCalledWith({\n      type: 'linear',\n      stops: [\n        { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n        {\n          color: { r: 255, g: 0, b: 255, a: 0.8 },\n          position: expect.closeTo(0.6, 1),\n        },\n      ],\n    });\n    onChange.mockReset();\n\n    // And release pointer\n    firePointerEvent.pointerUp(stop);\n\n    // Move back to the 20% mark\n    firePointerEvent.pointerMove(stop, {\n      clientX: 0.2 * LINE_LENGTH,\n    });\n\n    // Verify no new updated position\n    // TODO: Wait for debounce, but it shouldn't be called, so debounce won't invoke anyway?\n    expect(onChange).not.toHaveBeenCalled();\n  });\n\n  it('should reorder stops when dragging past an existing stop', async () => {\n    const { getGradientStopAt, onChange } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.4 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Get first gradient stop\n    const stop = getGradientStopAt(100);\n\n    // Click it to make sure it's selected\n    fireEvent.click(stop);\n\n    // Click at position 0\n    firePointerEvent.pointerDown(stop, {\n      clientX: 0,\n    });\n\n    // Move to the 60% mark past the stop at 40%\n    firePointerEvent.pointerMove(stop, {\n      clientX: 0.4 * LINE_LENGTH,\n    });\n\n    await waitFor(() =>\n      expect(onChange).toHaveBeenCalledWith({\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          {\n            color: { r: 0, g: 255, b: 0 },\n            position: expect.closeTo(0.4, 1),\n          },\n          {\n            color: { r: 0, g: 0, b: 255 },\n            position: expect.closeTo(0.6, 1),\n          },\n        ],\n      })\n    );\n    onChange.mockReset();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/onclose.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\njest.mock(\n  '../../../../app/story/useStory',\n  () => (cb) =>\n    cb({\n      state: {\n        story: {\n          globalStoryStyles: {\n            colors: [],\n          },\n          selectedElements: [],\n        },\n      },\n      actions: {\n        updateStory: jest.fn(),\n      },\n    })\n);\n\ndescribe('<ColorPicker /> as it closes', () => {\n  it('should invoke onclose and restore focus when pressing \"escape\"', async () => {\n    // Body has focus before the test runs. Make sure body is re-focusable\n    document.body.tabIndex = 0;\n    expect(document.body).toHaveFocus();\n\n    const { getDialog, onClose } = arrange();\n    expect(document.body).not.toHaveFocus();\n    const dialog = getDialog();\n\n    fireEvent.keyDown(dialog, { key: 'Escape', which: 27 });\n\n    await waitFor(() => {\n      expect(onClose).toHaveBeenCalledWith(expect.anything());\n    });\n\n    await waitFor(() => expect(document.body).toHaveFocus());\n  });\n\n  it('should invoke onclose and restore focus when clicking close button', async () => {\n    // Body has focus before the test runs. Make sure body is re-focusable\n    document.body.tabIndex = 0;\n    expect(document.body).toHaveFocus();\n\n    const { getCloseButton, onClose } = arrange();\n    expect(document.body).not.toHaveFocus();\n    const closeButton = getCloseButton();\n\n    fireEvent.click(closeButton);\n\n    await waitFor(() => {\n      expect(onClose).toHaveBeenCalledWith(expect.anything());\n    });\n\n    await waitFor(() => expect(document.body).toHaveFocus());\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/onload.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { waitFor, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\njest.mock(\n  '../../../../app/story/useStory',\n  () => (cb) =>\n    cb({\n      state: {\n        story: {\n          globalStoryStyles: {\n            colors: [],\n          },\n          selectedElements: [],\n        },\n      },\n      actions: {\n        updateStory: jest.fn(),\n      },\n    })\n);\n\ndescribe('<ColorPicker /> as it loads', () => {\n  describe('when opening the basic color picker', () => {\n    it('should render with initial focus forced to the close button', async () => {\n      const { getCloseButton } = arrange();\n\n      const closeButton = getCloseButton();\n      await waitFor(() => expect(closeButton).toBeInTheDocument());\n      await waitFor(() => expect(closeButton).toHaveFocus());\n    });\n\n    it('should highlight the current color if in list', () => {\n      const { getSelectedSwatch } = arrange({\n        color: createSolid(238, 238, 238),\n      });\n\n      const swatch = getSelectedSwatch('Default');\n      expect(swatch).toBeInTheDocument();\n      expect(swatch).toHaveAccessibleName(/#eee/);\n    });\n\n    it('should not highlight any color if not in list', () => {\n      const { getSelectedSwatch } = arrange({\n        color: createSolid(237, 238, 238),\n      });\n\n      const swatch = getSelectedSwatch('Default');\n      expect(swatch).toBeNull();\n    });\n  });\n\n  describe('when opening the custom color picker', () => {\n    it('should render with initial focus forced to the close button', async () => {\n      const { getCloseButton } = arrange();\n\n      const closeButton = getCloseButton();\n      await waitFor(() => expect(closeButton).toBeInTheDocument());\n      await waitFor(() => expect(closeButton).toHaveFocus());\n    });\n\n    it('should automatically do so if invoked on a gradient', async () => {\n      const { getEditableHexElement } = arrange({\n        color: {\n          type: 'linear',\n          stops: [\n            { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n            { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 0 },\n          ],\n        },\n        allowsGradient: true,\n      });\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n      expect(getEditableHexElement()).toBeInTheDocument();\n    });\n    it('should do so if invoked on a color and clicking custom button', async () => {\n      const { getCustomButton, getEditableHexElement } = arrange({\n        color: createSolid(255, 0, 0),\n      });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n      expect(getEditableHexElement()).toBeInTheDocument();\n    });\n\n    it('should correctly set color based on given prop', async () => {\n      const { getCustomButton, getEditableHexElement, rerender } = arrange({\n        color: createSolid(255, 0, 0),\n      });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n      expect(getEditableHexElement()).toHaveTextContent(/#ff0000/i);\n\n      rerender({ color: createSolid(0, 0, 255) });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n      expect(getEditableHexElement()).toHaveTextContent(/#0000ff/i);\n    });\n\n    it('should correctly set opacity based on given prop', async () => {\n      const { getCustomButton, getEditableAlphaElement, rerender } = arrange({\n        color: createSolid(255, 0, 0, 0.7),\n      });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() =>\n        expect(getEditableAlphaElement()).toBeInTheDocument()\n      );\n      expect(getEditableAlphaElement()).toHaveTextContent(/70%/i);\n\n      rerender({ color: createSolid(0, 0, 255) });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() =>\n        expect(getEditableAlphaElement()).toBeInTheDocument()\n      );\n      expect(getEditableAlphaElement()).toHaveTextContent(/100%/i);\n    });\n\n    it('should correctly set color and opacity based on first stop for a gradient', async () => {\n      const { getEditableHexElement, getEditableAlphaElement } = arrange({\n        color: {\n          type: 'linear',\n          stops: [\n            { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n            { color: { r: 255, g: 0, b: 255, a: 0.8 }, position: 0 },\n          ],\n        },\n        allowsGradient: true,\n      });\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n\n      expect(getEditableHexElement()).toHaveTextContent(/#00ff00/i);\n      expect(getEditableAlphaElement()).toHaveTextContent(/40%/i);\n    });\n\n    it('should have pattern type buttons only if enabled', async () => {\n      const {\n        getCustomButton,\n        getSolidButton,\n        getLinearButton,\n        getRadialButton,\n        getEditableHexElement,\n        rerender,\n      } = arrange();\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n\n      expect(getSolidButton()).not.toBeInTheDocument();\n      expect(getLinearButton()).not.toBeInTheDocument();\n      expect(getRadialButton()).not.toBeInTheDocument();\n\n      rerender({ allowsGradient: true });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getEditableHexElement()).toBeInTheDocument());\n\n      expect(getSolidButton()).toBeInTheDocument();\n      expect(getLinearButton()).toBeInTheDocument();\n      expect(getRadialButton()).toBeInTheDocument();\n    });\n\n    it('should have gradient line only if pattern is non-solid', async () => {\n      const { getCustomButton, getGradientLine, rerender } = arrange({\n        color: createSolid(0, 0, 0),\n        allowsGradient: true,\n      });\n\n      fireEvent.click(getCustomButton());\n\n      await waitFor(() => expect(getGradientLine()).not.toBeInTheDocument());\n\n      rerender({\n        color: {\n          stops: [\n            { color: { r: 0, g: 0, b: 255 }, position: 0 },\n            { color: { r: 0, g: 0, b: 255 }, position: 1 },\n          ],\n          type: 'linear',\n        },\n        allowsGradient: true,\n      });\n\n      await waitFor(() => expect(getGradientLine()).toBeInTheDocument());\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/savedColors.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { waitFor, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { areAllType } from '../../../../utils/presetUtils';\nimport { arrange } from './_utils';\n\nconst mockSavedColors = jest\n  .fn()\n  .mockImplementation(() => [\n    TEAL_COLOR,\n    PINK_COLOR,\n    SEMIPINK_COLOR,\n    OPAQUEGRAD_COLOR,\n    SEMIGRAD_COLOR,\n  ]);\nconst mockUpdateStory = jest.fn();\n\njest.mock(\n  '../../../../app/story/useStory',\n  () => (cb) =>\n    cb({\n      state: {\n        story: {\n          globalStoryStyles: {\n            colors: mockSavedColors(),\n          },\n          selectedElements: [],\n        },\n      },\n      actions: {\n        updateStory: mockUpdateStory,\n      },\n    })\n);\n\njest.mock('../../../../utils/presetUtils');\n\nconst TEAL_COLOR = createSolid(0, 255, 255);\nconst PINK_COLOR = createSolid(255, 0, 255);\nconst PINK_LABEL = '#f0f';\nconst SEMIPINK_COLOR = createSolid(255, 0, 255, 0.3);\nconst SEMIPINK_LABEL = 'rgba(255,0,255,0.3)';\nconst OPAQUEGRAD_COLOR = {\n  type: 'linear',\n  stops: [\n    { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0 },\n    { color: { r: 255, g: 0, b: 255, a: 1 }, position: 1 },\n  ],\n};\nconst OPAQUEGRAD_LABEL = 'linear-gradient(0.5turn, #0f0 0%, #f0f 100%)';\nconst SEMIGRAD_COLOR = {\n  type: 'linear',\n  stops: [\n    { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0 },\n    { color: { r: 255, g: 0, b: 255, a: 1 }, position: 1 },\n  ],\n  alpha: 0.3,\n};\nconst SEMIGRAD_LABEL =\n  'linear-gradient(0.5turn, rgba(0,255,0,0.3) 0%, rgba(255,0,255,0.3) 100%)';\n\ndescribe('<ColorPicker /> and saved colors', () => {\n  beforeEach(() => {\n    areAllType.mockImplementation(() => true);\n  });\n\n  it('should not display saved colors on load if not enabled', () => {\n    const { getSwatchList } = arrange({\n      color: PINK_COLOR,\n    });\n\n    expect(getSwatchList('Saved colors')).not.toBeInTheDocument();\n  });\n\n  it('should display saved colors on load if enabled and highlight the current one', () => {\n    const { getSwatchList, getSwatches, getSelectedSwatch } = arrange({\n      allowsSavedColors: true,\n      color: PINK_COLOR,\n    });\n\n    expect(getSwatchList('Saved colors')).toBeInTheDocument();\n    expect(getSwatches('Saved colors')).toHaveLength(5);\n    expect(getSelectedSwatch('Saved colors')).toHaveAccessibleName(PINK_LABEL);\n  });\n\n  it('should disable semitransparents and gradients unless allowed', () => {\n    const { rerender, getEnabledSwatches, getSwatchByLabel } = arrange({\n      allowsSavedColors: true,\n      allowsGradient: false,\n      allowsOpacity: false,\n    });\n\n    // Both the semitransparent and the gradients are disabled\n    expect(getEnabledSwatches('Saved colors')).toHaveLength(2);\n    expect(getSwatchByLabel('Saved colors', SEMIPINK_LABEL)).toBeDisabled();\n    expect(getSwatchByLabel('Saved colors', OPAQUEGRAD_LABEL)).toBeDisabled();\n    expect(getSwatchByLabel('Saved colors', SEMIGRAD_LABEL)).toBeDisabled();\n\n    // If enabling only transparency, both gradients are still disabled\n    rerender({ allowsOpacity: true });\n    expect(getEnabledSwatches('Saved colors')).toHaveLength(3);\n    expect(getSwatchByLabel('Saved colors', SEMIPINK_LABEL)).toBeEnabled();\n    expect(getSwatchByLabel('Saved colors', OPAQUEGRAD_LABEL)).toBeDisabled();\n    expect(getSwatchByLabel('Saved colors', SEMIGRAD_LABEL)).toBeDisabled();\n\n    // If enabling only gradients, both the semitransparents are disabled\n    rerender({ allowsGradient: true });\n    expect(getEnabledSwatches('Saved colors')).toHaveLength(3);\n    expect(getSwatchByLabel('Saved colors', SEMIPINK_LABEL)).toBeDisabled();\n    expect(getSwatchByLabel('Saved colors', OPAQUEGRAD_LABEL)).toBeEnabled();\n    expect(getSwatchByLabel('Saved colors', SEMIGRAD_LABEL)).toBeDisabled();\n\n    // If enabling both, none are disabled\n    rerender({ allowsOpacity: true, allowsGradient: true });\n    expect(getEnabledSwatches('Saved colors')).toHaveLength(5);\n    expect(getSwatchByLabel('Saved colors', SEMIPINK_LABEL)).toBeEnabled();\n    expect(getSwatchByLabel('Saved colors', OPAQUEGRAD_LABEL)).toBeEnabled();\n    expect(getSwatchByLabel('Saved colors', SEMIGRAD_LABEL)).toBeEnabled();\n  });\n\n  it('should not add the same custom color twice', async () => {\n    const { getCustomButton, getAddCustomButton, getEditableAlphaElement } =\n      arrange({\n        allowsSavedColors: true,\n        allowsOpacity: true,\n        color: TEAL_COLOR,\n      });\n\n    fireEvent.click(getCustomButton());\n\n    // Wait for the lazy-loaded module\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n\n    // Click to save the color that already exists.\n    fireEvent.click(getAddCustomButton());\n\n    // Verify the TEAL color that was already saved wasn't added a second time.\n    expect(mockUpdateStory).toHaveBeenCalledWith({\n      properties: {\n        globalStoryStyles: {\n          colors: [\n            TEAL_COLOR,\n            PINK_COLOR,\n            SEMIPINK_COLOR,\n            OPAQUEGRAD_COLOR,\n            SEMIGRAD_COLOR,\n          ],\n        },\n      },\n    });\n  });\n\n  it('should invoke updateStory with the added color when adding one', async () => {\n    const { getCustomButton, getAddCustomButton, getEditableAlphaElement } =\n      arrange({\n        allowsSavedColors: true,\n        allowsOpacity: true,\n        color: TEAL_COLOR,\n      });\n\n    fireEvent.click(getCustomButton());\n\n    // Wait for the lazy-loaded module\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n    // Click to enable and focus input\n    fireEvent.click(getEditableAlphaElement());\n    // Wait for input to be present\n    await waitFor(() => expect(getEditableAlphaElement()).toBeInTheDocument());\n    // Adjust the opacity to 50%\n    fireEvent.change(getEditableAlphaElement(), { target: { value: '50' } });\n\n    // Click to save\n    fireEvent.click(getAddCustomButton());\n\n    expect(mockUpdateStory).toHaveBeenCalledWith({\n      properties: {\n        globalStoryStyles: {\n          colors: expect.arrayContaining([\n            {\n              // This matches TEAL at 50% opacity\n              color: { r: 0, g: 255, b: 255, a: 0.5 },\n            },\n          ]),\n        },\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/colorPicker/selectStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { arrange } from './_utils';\n\ndescribe('<ColorPicker /> when selecting a stop', () => {\n  it('should have stop highlighted when focused', async () => {\n    const { getGradientStopAt } = arrange({\n      color: {\n        type: 'linear',\n        stops: [\n          { color: { r: 255, g: 0, b: 0 }, position: 0 },\n          { color: { r: 0, g: 255, b: 0 }, position: 0.4 },\n          { color: { r: 0, g: 0, b: 255 }, position: 1 },\n        ],\n      },\n      allowsGradient: true,\n    });\n\n    // Unfortunately JSDOM does not support tab semantics, so we'll manually\n    // focus elements and see that they're highlighted\n\n    // Focus and selection to have moved to first stop\n    const firstStop = getGradientStopAt(0);\n    act(() => firstStop.focus());\n    await waitFor(() => expect(firstStop).toHaveFocus());\n\n    // Now focus second stop and verify this is now highlighted\n    const secondStop = getGradientStopAt(40);\n    act(() => secondStop.focus());\n    expect(secondStop).toHaveFocus();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/insertStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { toBeDeepCloseTo } from 'jest-matcher-deep-close-to';\n\n/**\n * Internal dependencies\n */\nimport insertStop from '../insertStop';\n\nconst WHITE = { r: 255, g: 255, b: 255 };\nconst BLACK = { r: 0, g: 0, b: 0 };\nconst ABLACK = { r: 0, g: 0, b: 0, a: 0 };\nconst GRAY80 = { r: 51, g: 51, b: 51 };\nconst MGRAY80 = { r: 51, g: 51, b: 51, a: 0.2 };\n\nexpect.extend({ toBeDeepCloseTo });\n\ndescribe('insertStop', () => {\n  it('should correctly find position at start of list', () => {\n    const stops = [\n      { color: WHITE, position: 0.5 },\n      { color: BLACK, position: 0.7 },\n    ];\n    const newPosition = 0;\n\n    const result = insertStop(stops, newPosition);\n\n    expect(result).toStrictEqual({\n      index: 0,\n      color: WHITE,\n    });\n  });\n\n  it('should correctly find position at end of list', () => {\n    const stops = [\n      { color: WHITE, position: 0.5 },\n      { color: BLACK, position: 0.7 },\n    ];\n    const newPosition = 0.8;\n\n    const result = insertStop(stops, newPosition);\n\n    expect(result).toStrictEqual({\n      index: 2,\n      color: BLACK,\n    });\n  });\n\n  it('should find position and color between existing stops', () => {\n    const stops = [\n      { color: WHITE, position: 0 },\n      { color: BLACK, position: 1 },\n    ];\n    const newPosition = 0.8;\n\n    const result = insertStop(stops, newPosition);\n\n    expect(result).toStrictEqual({\n      index: 1,\n      color: GRAY80,\n    });\n  });\n\n  it('should find average opacity too', () => {\n    const stops = [\n      { color: WHITE, position: 0 },\n      { color: ABLACK, position: 1 },\n    ];\n    const newPosition = 0.8;\n\n    const result = insertStop(stops, newPosition);\n\n    // Due to floating-point rounding errors, the .2 might be .199999999\n    expect(result).toBeDeepCloseTo(\n      {\n        index: 1,\n        color: MGRAY80,\n      },\n      2 // must match within two decimals\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/regenerateColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport regenerateColor from '../regenerateColor';\n\ndescribe('regenerateColor', () => {\n  it('should return null if regenerate is not true', () => {\n    const state = {\n      regenerate: false,\n      type: 'solid',\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toBeNull();\n  });\n  it('should correctly generate color for solid state with full opacity', () => {\n    const state = {\n      regenerate: true,\n      type: 'solid',\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      alpha: 0.8,\n      center: { x: 1, y: 0 },\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      color: { r: 255, g: 0, b: 0 },\n    });\n  });\n\n  it('should correctly generate color for solid state with less than full opacity', () => {\n    const state = {\n      regenerate: true,\n      type: 'solid',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      rotation: 0.6,\n      size: { w: 0.5, h: 0.5 },\n      stops: [],\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      color: { r: 0, g: 255, b: 0, a: 0.1 },\n    });\n  });\n\n  it('should correctly generate color for linear gradient with default alpha and rotation', () => {\n    const state = {\n      regenerate: true,\n      type: 'linear',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0,\n      alpha: 1,\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should correctly generate color for linear gradient with non-default alpha and rotation', () => {\n    const state = {\n      regenerate: true,\n      type: 'linear',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n      alpha: 0.1,\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      type: 'linear',\n      rotation: 0.5,\n      alpha: 0.1,\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should correctly generate color for radial gradient with default properties', () => {\n    const state = {\n      regenerate: true,\n      type: 'radial',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n      alpha: 1,\n      center: { x: 0.5, y: 0.5 },\n      size: { w: 1, h: 1 },\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should correctly generate color for radial gradient with non-default center only', () => {\n    const state = {\n      regenerate: true,\n      type: 'radial',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n      alpha: undefined,\n      center: { x: 1, y: 0 },\n      size: { w: 1, h: 1 },\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n      center: { x: 1, y: 0 },\n    });\n  });\n\n  it('should correctly generate color for radial gradient with non-default alpha and size', () => {\n    const state = {\n      regenerate: true,\n      type: 'radial',\n      currentColor: { r: 0, g: 255, b: 0, a: 0.1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n      alpha: 0.5,\n      center: { x: 0.5, y: 0.5 },\n      size: { w: 0, h: 1 },\n    };\n\n    const result = regenerateColor(state);\n\n    expect(result).toStrictEqual({\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255 }, position: 1 },\n      ],\n      alpha: 0.5,\n      size: { w: 0, h: 1 },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useColor from '../../useColor';\n\nfunction arrangeUseColor() {\n  const { result } = renderHook(() => useColor());\n\n  // convert each method to be wrapped in act and return the new state\n  const wrapWithAct = (methods) =>\n    Object.keys(methods).reduce((obj, methodName) => {\n      const method = methods[methodName];\n      const wrapped = (parms) => {\n        act(() => method(parms));\n        return result.current.state;\n      };\n      return {\n        ...obj,\n        [methodName]: wrapped,\n      };\n    }, {});\n\n  return wrapWithAct(result.current.actions);\n}\n\nexport default arrangeUseColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/addStopAt.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport insertStop from '../../insertStop';\nimport arrangeUseColor from './_utils';\n\njest.mock('../../insertStop', () => jest.fn());\n\ndescribe('useColor({ action:\"addStopAt\" })', () => {\n  it('should correctly ignore stop already present', () => {\n    const { load, addStopAt } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    const initial = load(pattern);\n    const result = addStopAt(0);\n\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should insert stop using helper function and select it', () => {\n    const { load, addStopAt } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    insertStop.mockImplementation(() => ({\n      color: { r: 0, g: 255, b: 0, a: 1 },\n      index: 1,\n    }));\n    const result = addStopAt(0.2);\n\n    expect(result).toMatchObject({\n      currentStopIndex: 1,\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.2 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    });\n\n    expect(insertStop).toHaveBeenCalledWith(\n      [\n        { color: { a: 1, b: 0, g: 0, r: 255 }, position: 0 },\n        { color: { a: 1, b: 255, g: 0, r: 0 }, position: 1 },\n      ],\n      0.2\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/load.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"load\" })', () => {\n  it('should correctly load a default solid pattern', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      color: { r: 0, g: 0, b: 0 },\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 1,\n      center: { x: 0.5, y: 0.5 },\n      currentColor: { b: 0, g: 0, r: 0 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0.5,\n      size: { h: 1, w: 1 },\n      stops: [],\n      type: 'solid',\n    });\n  });\n\n  it('should correctly load an explicit solid pattern', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      type: 'solid',\n      color: { r: 0, g: 0, b: 0, a: 0 },\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 1,\n      center: { x: 0.5, y: 0.5 },\n      currentColor: { b: 0, g: 0, r: 0, a: 0 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0.5,\n      size: { h: 1, w: 1 },\n      stops: [],\n      type: 'solid',\n    });\n  });\n\n  it('should correctly load a linear gradient with default properties', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 1,\n      center: { x: 0.5, y: 0.5 },\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0,\n      size: { h: 1, w: 1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      type: 'linear',\n    });\n  });\n\n  it('should correctly load a linear gradient with explicit properties', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      type: 'linear',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      alpha: 0.7,\n      rotation: 0.25,\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 0.7,\n      center: { x: 0.5, y: 0.5 },\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0.25,\n      size: { h: 1, w: 1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      type: 'linear',\n    });\n  });\n\n  it('should correctly load a radial gradient with default properties', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 1,\n      center: { x: 0.5, y: 0.5 },\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0.5,\n      size: { h: 1, w: 1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      type: 'radial',\n    });\n  });\n\n  it('should correctly load a radial gradien with explicit properties', () => {\n    const { load } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      alpha: 0.2,\n      size: { h: 0.5, w: 0.5 },\n      center: { x: 0, y: 0 },\n    };\n\n    const result = load(pattern);\n\n    expect(result).toStrictEqual({\n      alpha: 0.2,\n      center: { x: 0, y: 0 },\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      currentStopIndex: 0,\n      generatedColor: null,\n      regenerate: false,\n      rotation: 0.5,\n      size: { h: 0.5, w: 0.5 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      type: 'radial',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/moveCurrentStopBy.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"moveCurrentStopBy\" })', () => {\n  it('should not be able to move lower than position 0', () => {\n    const { load, selectStop, moveCurrentStopBy } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    const initial = selectStop(0);\n    const result = moveCurrentStopBy(-0.1);\n\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should not be able to move higher than position 1', () => {\n    const { load, selectStop, moveCurrentStopBy } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    const initial = selectStop(1);\n    const result = moveCurrentStopBy(0.1);\n\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should move and potentially reorder stops', () => {\n    const { load, selectStop, moveCurrentStopBy } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    selectStop(2);\n    const result = moveCurrentStopBy(-0.7);\n\n    expect(result).toMatchObject({\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 0.3 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/removeCurrentStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"removeCurrentStop\" })', () => {\n  it('should not be able to have less than 2 stops', () => {\n    const { load, selectStop, removeCurrentStop } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    const initial = selectStop(0);\n    const result = removeCurrentStop();\n\n    expect(result).toStrictEqual(initial);\n  });\n\n  it('should delete a stop and select the next one as current', () => {\n    const { load, selectStop, removeCurrentStop } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    selectStop(1);\n    const result = removeCurrentStop();\n\n    expect(result).toMatchObject({\n      currentStopIndex: 1,\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    });\n  });\n\n  it('should delete the last stop and penultimate', () => {\n    const { load, selectStop, removeCurrentStop } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    selectStop(2);\n    const result = removeCurrentStop();\n\n    expect(result).toMatchObject({\n      currentStopIndex: 1,\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/reverseStops.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"reverseStops\" })', () => {\n  it('should reverse stop list while keeping selection', () => {\n    const { load, selectStop, reverseStops } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n    };\n\n    load(pattern);\n    selectStop(2);\n\n    const result = reverseStops();\n    expect(result).toMatchObject({\n      currentStopIndex: 0,\n      stops: [\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.6 },\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 1 },\n      ],\n      currentColor: { r: 0, g: 0, b: 255, a: 1 },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/rotateClockwise.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"rotateClockwise\" })', () => {\n  it('should add .25 to the rotation mod 1', () => {\n    const { load, rotateClockwise } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n    };\n\n    load(pattern);\n    const firstResult = rotateClockwise();\n\n    expect(firstResult).toMatchObject({\n      regenerate: true,\n      rotation: 0.75,\n    });\n\n    rotateClockwise();\n    const secondResult = rotateClockwise();\n\n    expect(secondResult).toMatchObject({\n      regenerate: true,\n      rotation: 0.25,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/selectStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"selectStop\" })', () => {\n  it('should be able to select stops inside the list and update the current color', () => {\n    const { load, selectStop } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      rotation: 0.5,\n    };\n\n    load(pattern);\n\n    const firstStopSelected = selectStop(0);\n    expect(firstStopSelected).toMatchObject({\n      currentStopIndex: 0,\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n    });\n\n    const firstFailedAttempt = selectStop(-1);\n    expect(firstFailedAttempt).toStrictEqual(firstStopSelected);\n\n    const lastStopSelected = selectStop(2);\n    expect(lastStopSelected).toMatchObject({\n      currentStopIndex: 2,\n      currentColor: { r: 0, g: 0, b: 255, a: 1 },\n    });\n\n    const secondFailedAttempt = selectStop(3);\n    expect(secondFailedAttempt).toStrictEqual(lastStopSelected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/setToGradient.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"setToGradient\" })', () => {\n  it('should correctly set to gradient when initialized as solid', () => {\n    const { load, setToGradient } = arrangeUseColor();\n\n    const pattern = { color: { r: 255, g: 0, b: 0, a: 1 } };\n\n    // Initially load as radial gradient\n    load(pattern);\n\n    const result = setToGradient('radial');\n\n    expect(result).toMatchObject({\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 1 },\n      ],\n      type: 'radial',\n    });\n  });\n\n  it('should correctly set to new gradient when initialized as another gradient', () => {\n    const { load, setToGradient, selectStop } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    // Initially load as linear gradient as select stop 1\n    load(pattern);\n    selectStop(1);\n\n    const result = setToGradient('linear');\n\n    expect(result).toMatchObject({\n      currentColor: { r: 0, g: 0, b: 255, a: 1 },\n      currentStopIndex: 1,\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n      type: 'linear',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/setToSolid.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"setToSolid\" })', () => {\n  it('should correctly set to solid when initialized as non-solid', () => {\n    const { load, setToSolid } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    // Initially load as radial gradient\n    load(pattern);\n\n    const result = setToSolid();\n\n    expect(result).toMatchObject({\n      currentColor: { r: 255, g: 0, b: 0, a: 1 },\n      type: 'solid',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/test/useColor/updateCurrentColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport arrangeUseColor from './_utils';\n\ndescribe('useColor({ action:\"removeCurrentStop\" })', () => {\n  it('should update the current color of a solid', () => {\n    const { load, updateCurrentColor } = arrangeUseColor();\n\n    const pattern = { color: { r: 255, g: 0, b: 0, a: 1 } };\n\n    load(pattern);\n    const result = updateCurrentColor({ rgb: { r: 0, g: 255, b: 0, a: 0 } });\n\n    expect(result).toMatchObject({\n      regenerate: true,\n      currentColor: { r: 0, g: 255, b: 0, a: 0 },\n    });\n  });\n\n  it('should also update the current stop of a gradient', () => {\n    const { load, selectStop, updateCurrentColor } = arrangeUseColor();\n\n    const pattern = {\n      type: 'radial',\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 1 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    };\n\n    load(pattern);\n    selectStop(1);\n    const result = updateCurrentColor({ rgb: { r: 0, g: 255, b: 0, a: 0 } });\n\n    expect(result).toMatchObject({\n      regenerate: true,\n      currentColor: { r: 0, g: 255, b: 0, a: 0 },\n      stops: [\n        { color: { r: 255, g: 0, b: 0, a: 1 }, position: 0 },\n        { color: { r: 0, g: 255, b: 0, a: 0 }, position: 0.4 },\n        { color: { r: 0, g: 0, b: 255, a: 1 }, position: 1 },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useReduction } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport insertStop from './insertStop';\nimport regenerateColor from './regenerateColor';\nimport { TYPE_SOLID, TYPE_LINEAR, TYPE_RADIAL } from './constants';\n\nconst initialState = {\n  type: TYPE_SOLID,\n  regenerate: false,\n  stops: [],\n  currentColor: {\n    r: 0,\n    g: 0,\n    b: 0,\n    a: 0,\n  },\n  currentStopIndex: 0,\n  rotation: 0.5,\n  alpha: 1,\n  center: { x: 0.5, y: 0.5 },\n  size: { w: 1, h: 1 },\n};\n\nconst reducer = {\n  load: (state, { payload }) => {\n    const { type, color, stops, rotation, center, size, alpha } = payload;\n    const shouldReset =\n      type &&\n      type !== TYPE_SOLID &&\n      (state.type !== type || stops?.length !== state.stops?.length);\n    const maybeReset = shouldReset\n      ? { currentColor: stops[0].color, currentStopIndex: 0 }\n      : {};\n    switch (type) {\n      case TYPE_LINEAR:\n        return {\n          ...state,\n          ...maybeReset,\n          type,\n          regenerate: false,\n          stops,\n          alpha: isNaN(alpha) ? state.alpha : alpha,\n          rotation: isNaN(rotation) ? 0 : rotation, // explicitly default to 0 here!\n        };\n\n      case TYPE_RADIAL:\n        return {\n          ...state,\n          ...maybeReset,\n          type,\n          regenerate: false,\n          stops,\n          center: typeof center !== 'undefined' ? center : state.center,\n          size: typeof size !== 'undefined' ? size : state.size,\n          alpha: isNaN(alpha) ? state.alpha : alpha,\n        };\n\n      case TYPE_SOLID:\n      default:\n        return {\n          ...state,\n          type: TYPE_SOLID,\n          regenerate: false,\n          currentColor: color,\n        };\n    }\n  },\n  setToSolid: (state) => ({\n    ...state,\n    type: TYPE_SOLID,\n    regenerate: true,\n  }),\n  setToGradient: (state, { payload }) => {\n    const stops =\n      state.stops && state.stops.length >= 2\n        ? state.stops\n        : [\n            { color: state.currentColor, position: 0 },\n            { color: state.currentColor, position: 1 },\n          ];\n    return {\n      ...state,\n      regenerate: true,\n      type: payload,\n      stops,\n    };\n  },\n  addStopAt: (state, { payload: newPosition }) => {\n    newPosition = Number(newPosition.toFixed(2));\n    // If there's already a stop at this position, do nothing:\n    if (state.stops.some(({ position }) => position === newPosition)) {\n      return state;\n    }\n\n    const { index, color } = insertStop(state.stops, newPosition);\n\n    const stops = [\n      ...state.stops.slice(0, index),\n      { color, position: newPosition },\n      ...state.stops.slice(index),\n    ];\n    return {\n      ...state,\n      regenerate: true,\n      currentColor: color,\n      currentStopIndex: index,\n      stops,\n    };\n  },\n  moveCurrentStopBy: (state, { payload: deltaPosition }) => {\n    const index = state.currentStopIndex;\n    const currentPosition = state.stops[index].position;\n    // Clamp by 0 and 1, round to 2 decimals\n    const desiredPosition = Math.max(\n      0,\n      Math.min(1, Number((currentPosition + deltaPosition).toFixed(2)))\n    );\n    if (desiredPosition === currentPosition) {\n      return state;\n    }\n    const stops = [\n      ...state.stops.slice(0, index),\n      {\n        ...state.stops[index],\n        position: desiredPosition,\n      },\n      ...state.stops.slice(index + 1),\n    ];\n\n    // Sort by position\n    stops.sort((a, b) => a.position - b.position);\n\n    const currentStopIndex = stops.findIndex(\n      ({ position }) => position === desiredPosition\n    );\n\n    return {\n      ...state,\n      regenerate: true,\n      stops,\n      currentStopIndex,\n    };\n  },\n  removeCurrentStop: (state) => {\n    // Can't have less than two stops\n    if (state.stops.length === 2) {\n      return state;\n    }\n    const index = state.currentStopIndex;\n    const stops = [...state.stops];\n    stops.splice(index, 1);\n    const currentStopIndex = index === stops.length ? index - 1 : index;\n\n    return {\n      ...state,\n      regenerate: true,\n      stops,\n      currentColor: stops[currentStopIndex].color,\n      currentStopIndex,\n    };\n  },\n  updateCurrentColor: (state, { payload: { rgb } }) => {\n    const currentColor = { ...rgb };\n    const newState = {\n      ...state,\n      regenerate: true,\n      currentColor,\n    };\n\n    if (state.type !== TYPE_SOLID) {\n      // Also update color for current stop\n      newState.stops = [\n        ...state.stops.slice(0, state.currentStopIndex),\n        {\n          ...state.stops[state.currentStopIndex],\n          color: currentColor,\n        },\n        ...state.stops.slice(state.currentStopIndex + 1),\n      ];\n    }\n\n    return newState;\n  },\n  rotateClockwise: (state) => ({\n    ...state,\n    rotation: (state.rotation + 0.25) % 1,\n    regenerate: true,\n  }),\n  selectStop: (state, { payload: newIndex }) => {\n    const currentStopIndex = Math.max(\n      0,\n      Math.min(state.stops.length - 1, newIndex)\n    );\n    const currentColor = state.stops[currentStopIndex].color;\n    return {\n      ...state,\n      currentStopIndex,\n      currentColor,\n    };\n  },\n  reverseStops: (state) => {\n    const stops = state.stops\n      .map(({ color, position }) => ({ color, position: 1 - position }))\n      .reverse();\n\n    const currentStopIndex = stops.length - state.currentStopIndex - 1;\n\n    return {\n      ...state,\n      stops,\n      currentStopIndex,\n      regenerate: true,\n    };\n  },\n};\n\nfunction useColor() {\n  const [state, actions] = useReduction(initialState, reducer);\n\n  const generatedColor = regenerateColor(state);\n\n  return {\n    state: {\n      ...state,\n      generatedColor,\n    },\n    actions,\n  };\n}\n\nexport default useColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useDeleteColor.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app';\nimport { noop } from '../../utils/noop';\n\nfunction useDeleteColor({ onEmpty = noop }) {\n  const { currentStoryStyles, globalStoryStyles, updateStory } = useStory(\n    ({\n      state: {\n        story: { globalStoryStyles, currentStoryStyles },\n      },\n      actions: { updateStory },\n    }) => {\n      return {\n        currentStoryStyles,\n        globalStoryStyles,\n        updateStory,\n      };\n    }\n  );\n\n  const { colors: globalColors } = globalStoryStyles || {};\n  const { colors: localColors } = currentStoryStyles || {};\n  const hasLocalPresets = localColors?.length > 0;\n\n  const deleteGlobalColor = useCallback(\n    (toDelete) => {\n      const updatedColors = globalColors.filter((color) => color !== toDelete);\n      updateStory({\n        properties: {\n          globalStoryStyles: {\n            ...globalStoryStyles,\n            colors: updatedColors,\n          },\n        },\n      });\n      // If no colors left, exit edit mode.\n      if (updatedColors.length === 0 && !hasLocalPresets) {\n        onEmpty();\n      }\n    },\n    [globalColors, updateStory, hasLocalPresets, globalStoryStyles, onEmpty]\n  );\n\n  const deleteLocalColor = useCallback(\n    (toDelete) => {\n      const updatedColors = localColors.filter((color) => color !== toDelete);\n      updateStory({\n        properties: {\n          currentStoryStyles: { colors: updatedColors },\n        },\n      });\n      // If no colors are left, exit edit mode.\n      if (updatedColors.length === 0 && globalColors.length === 0) {\n        onEmpty();\n      }\n    },\n    [globalColors, localColors, updateStory, onEmpty]\n  );\n\n  return {\n    deleteLocalColor,\n    deleteGlobalColor,\n  };\n}\n\nexport default useDeleteColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useKeyAddStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\nfunction truncate(val, pos) {\n  return Number(val.toFixed(pos));\n}\n\nfunction getNewStopPosition(stops, currentStopIndex) {\n  const numStops = stops.length;\n  const isLastStopFocussed = currentStopIndex === numStops - 1;\n  if (isLastStopFocussed && stops[currentStopIndex].position < 1) {\n    // If last stop is focussed, and the last stop is not at the end\n    // insert new stop at the very end!\n    return 1;\n  }\n  if (currentStopIndex === 0 && stops[0].position > 0) {\n    // If first stop is focussed, and the first stop is not at the start\n    // insert new stop at the very start!\n    return 0;\n  }\n\n  // Other insert new stop half-way between current and next\n  // (or current and previous if last).\n  const preStop = isLastStopFocussed\n    ? stops[currentStopIndex - 1]\n    : stops[currentStopIndex];\n  const postStop = isLastStopFocussed\n    ? stops[currentStopIndex]\n    : stops[currentStopIndex + 1];\n  return preStop.position + (postStop.position - preStop.position) / 2;\n}\n\nfunction useKeyAddStop(ref, onAdd, stops, currentStopIndex) {\n  useKeyDownEffect(\n    ref,\n    'enter',\n    () => onAdd(truncate(getNewStopPosition(stops, currentStopIndex), 4)),\n    [onAdd, stops, currentStopIndex]\n  );\n}\n\nexport default useKeyAddStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useKeyDeleteStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\nfunction useKeyDeleteStop(ref, onDelete) {\n  useKeyDownEffect(\n    ref,\n    'delete',\n    () => {\n      ref.current.focus();\n      onDelete();\n    },\n    [onDelete, ref]\n  );\n}\n\nexport default useKeyDeleteStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useKeyFocus.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useLayoutEffect, createRef, useMemo } from '@googleforcreators/react';\n\nfunction useKeyFocus(ref, stops, currentStopIndex) {\n  const numStops = stops.length;\n  // Make sure proper stop is focused if any is focused\n  const stopRefs = useMemo(\n    () => Array.from({ length: numStops }).map(createRef),\n    [numStops]\n  );\n  useLayoutEffect(() => {\n    if (ref.current.contains(document.activeElement)) {\n      stopRefs[currentStopIndex].current.focus();\n    }\n  }, [currentStopIndex, stopRefs, numStops, ref]);\n\n  return stopRefs;\n}\n\nexport default useKeyFocus;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/useKeyMoveStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\nfunction useKeyMoveStop(ref, onMove) {\n  // Reversed since the gradient line is reversed in terms of colors.\n  useKeyDownEffect(ref, 'left', () => onMove(0.01), [onMove]);\n  useKeyDownEffect(ref, 'right', () => onMove(-0.01), [onMove]);\n}\n\nexport default useKeyMoveStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/usePointerAddStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useLayoutEffect, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { LINE_LENGTH, GRADIENT_STOP_SIZE } from './constants';\nimport { getPageX } from './utils';\n\nfunction usePointerAddStop(ref, onAdd) {\n  const [tempPointerPosition, setTempPointerPosition] = useState(null);\n  useLayoutEffect(() => {\n    const node = ref.current;\n\n    const nodeLeftEdge = node.getBoundingClientRect().left;\n\n    const onPointerDown = (evt) => {\n      if (evt.target !== node) {\n        return;\n      }\n\n      // We're considering the pointer size as extra to the normal line length\n      // in calculations since the pointers can be 7px \"over the edge\" from both sides.\n      const relativePosition =\n        (getPageX(evt) - nodeLeftEdge + GRADIENT_STOP_SIZE / 2) / LINE_LENGTH;\n      onAdd(\n        (LINE_LENGTH + GRADIENT_STOP_SIZE / 2) / LINE_LENGTH - relativePosition\n      );\n      setTempPointerPosition(null);\n    };\n\n    const onPointerMove = (evt) => {\n      if (evt.target !== node) {\n        setTempPointerPosition(null);\n        return;\n      }\n\n      setTempPointerPosition(getPageX(evt) - nodeLeftEdge);\n    };\n\n    const onPointerLeave = (evt) => {\n      if (evt.target === node) {\n        setTempPointerPosition(null);\n      }\n    };\n\n    node.addEventListener('pointermove', onPointerMove);\n    node.addEventListener('pointerleave', onPointerLeave);\n    node.addEventListener('pointerdown', onPointerDown);\n    return () => {\n      node.removeEventListener('pointermove', onPointerMove);\n      node.removeEventListener('pointerleave', onPointerLeave);\n      node.removeEventListener('pointerdown', onPointerDown);\n    };\n  }, [ref, onAdd]);\n\n  return tempPointerPosition;\n}\n\nexport default usePointerAddStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/usePointerMoveStop.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useLayoutEffect, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { LINE_LENGTH } from './constants';\nimport { getPageX, setPointerCapture, releasePointerCapture } from './utils';\n\nfunction usePointerMoveStop(ref, onMove) {\n  const lastPageXRef = useRef(null);\n  useLayoutEffect(() => {\n    const node = ref.current;\n    const onPointerMove = (evt) => {\n      const relativeDeltaX = getPageX(evt) - lastPageXRef.current;\n      lastPageXRef.current = getPageX(evt);\n      onMove(-relativeDeltaX / LINE_LENGTH);\n    };\n\n    const onPointerUp = (evt) => {\n      lastPageXRef.current = null;\n      releasePointerCapture(evt);\n      evt.target.removeEventListener('pointermove', onPointerMove);\n      evt.target.removeEventListener('pointerup', onPointerUp);\n    };\n\n    const onPointerDown = (evt) => {\n      if (evt.target === node) {\n        return;\n      }\n      lastPageXRef.current = getPageX(evt);\n      setPointerCapture(evt);\n      evt.target.addEventListener('pointermove', onPointerMove);\n      evt.target.addEventListener('pointerup', onPointerUp);\n    };\n\n    node.addEventListener('pointerdown', onPointerDown);\n    return () => node.removeEventListener('pointerdown', onPointerDown);\n  }, [ref, onMove]);\n}\n\nexport default usePointerMoveStop;\n"
  },
  {
    "path": "packages/story-editor/src/components/colorPicker/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// These functions are used as wrapper to allow test library to simulate events\n// correctly even though pointer events are not supported by jsdom library\n\nexport function getPageX(evt) {\n  return evt.pageX || evt.clientX;\n}\n\nexport function getPageY(evt) {\n  return evt.pageY || evt.clientY;\n}\n\nexport function setPointerCapture(evt) {\n  // Ignore reason: PointerEvents don't work in JSDOM\n  // istanbul ignore if\n  if (evt.target.setPointerCapture) {\n    evt.target.setPointerCapture(evt.pointerId);\n  }\n}\n\nexport function releasePointerCapture(evt) {\n  // Ignore reason: PointerEvents don't work in JSDOM\n  // istanbul ignore if\n  if (evt.target.releasePointerCapture) {\n    evt.target.releasePointerCapture(evt.pointerId);\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/devTools/devTools.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useState, useEffect } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { DATA_VERSION } from '@googleforcreators/migration';\nimport {\n  useGlobalKeyDownEffect,\n  useSnackbar,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\nimport { dummyImage, dummyVideo } from './dummyData';\n\nconst Container = styled.div`\n  position: fixed;\n  z-index: 2147483646;\n  bottom: 0;\n  left: 0;\n  display: flex;\n  flex-direction: column;\n  width: 35%;\n  height: 50%;\n  border: 6px solid ${({ theme }) => theme.colors.bg.secondary};\n  background: ${({ theme }) => theme.colors.bg.primary};\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst Textarea = styled.textarea`\n  flex: 1;\n  border: 0;\n  background: ${({ theme }) => theme.colors.bg.primary};\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  white-space: nowrap;\n  overflow: auto;\n`;\n\nconst Options = styled.div`\n  display: flex;\n  justify-content: space-between;\n  padding: 6px;\n`;\n\nconst Label = styled.label`\n  margin-right: 6px;\n`;\n\nconst Button = styled.button`\n  margin-left: 6px;\n`;\n\nconst replaceResourcesWithDummy = (state) => {\n  const videosToReload = [];\n  const newState = {\n    ...state,\n    pages: state.pages.map((page) => ({\n      ...page,\n      elements: page.elements.map((element) => {\n        const newElement = { ...element };\n        if ('resource' in element) {\n          newElement.resource = { ...element.resource };\n          if (element.type === 'video') {\n            newElement.resource.mimeType = 'video/mp4';\n            newElement.resource.src = dummyVideo;\n            newElement.resource.poster = dummyImage;\n            videosToReload.push(newElement.id);\n          }\n          if (element.type === 'image') {\n            newElement.resource.mimeType = 'image/png';\n            newElement.resource.src = dummyImage;\n          }\n        }\n        return newElement;\n      }),\n    })),\n  };\n\n  return [newState, videosToReload];\n};\n\nconst templateResourcePlaceholder =\n  '__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/%%templateName%%/';\n\nconst getResourceFileName = (src) => {\n  // If empty source return empty.\n  if (!src.length) {\n    return src;\n  }\n\n  const matchedPaths = src.match(/\\/([^/?#]+)[^/]*$/);\n\n  // If file path found, return it with the placeholder for easy replacements.\n  if (matchedPaths.length > 1) {\n    return `${templateResourcePlaceholder}${matchedPaths[1]}`;\n  }\n\n  // If file path not found return original URL.\n  return src;\n};\n\n/**\n * Prepare story JSON to export as template by resetting few properties\n * which are not used and adding handy placeholder strings for easy replacement\n * of template names.\n *\n * Resource ids and posterIds are reset to 0 and replaces the resource URL with\n * replaceable path.\n *\n * @see https://github.com/googleforcreators/web-stories-wp/issues/7227\n * @param {*} state Current story.\n * @return {*} Updated state for Template.\n */\nconst prepareTemplate = (state) => {\n  const newState = {\n    ...state,\n    pages: state.pages.map((page) => ({\n      ...page,\n      elements: page.elements.map((element) => {\n        const newElement = { ...element };\n        if ('resource' in element) {\n          newElement.resource = { ...element.resource };\n          if (element.type === 'video') {\n            newElement.resource.id = 0;\n            newElement.resource.posterId = 0;\n            newElement.resource.src = getResourceFileName(\n              newElement.resource.src\n            );\n            newElement.resource.poster = getResourceFileName(\n              newElement.resource.poster\n            );\n          }\n          if (element.type === 'image') {\n            newElement.resource.id = 0;\n            newElement.resource.sizes = [];\n            newElement.resource.src = getResourceFileName(\n              newElement.resource.src\n            );\n          }\n        }\n        return newElement;\n      }),\n      pageTemplateType: page?.pageTemplateType ?? '',\n    })),\n  };\n\n  return newState;\n};\n\nfunction DevTools() {\n  const [isVisible, setIsVisible] = useState(false);\n  const [isBase64, setIsBase64] = useState(false);\n  const [isDummyResources, setIsDummyResources] = useState(false);\n  const [isTemplate, setIsTemplate] = useState(false);\n  const { showSnackbar } = useSnackbar();\n  const textareaRef = useRef();\n  const { reducerState, restore } = useStory(({ internal }) => ({\n    reducerState: internal.reducerState,\n    restore: internal.restore,\n  }));\n\n  const {\n    pages,\n    current,\n    selection,\n    story: { globalStoryStyles },\n  } = reducerState;\n  const reducerStateSlice = {\n    current,\n    selection,\n    story: { globalStoryStyles },\n    version: DATA_VERSION,\n    pages,\n  };\n  const storyData = isDummyResources\n    ? replaceResourcesWithDummy(reducerStateSlice)[0]\n    : isTemplate\n      ? prepareTemplate(reducerStateSlice)\n      : reducerStateSlice;\n\n  const toggleDummyResources = () => setIsDummyResources((v) => !v);\n  const toggleTemplate = () => setIsTemplate((v) => !v);\n  const toggleBase64 = () => setIsBase64((v) => !v);\n  const toggleVisible = () => setIsVisible((v) => !v);\n  const copyToClipboard = () => {\n    textareaRef.current.select();\n    document.execCommand('copy');\n    textareaRef.current.setSelectionRange(0, 0);\n    showSnackbar({ message: 'Copied to clipboard', timeout: 1200 });\n  };\n  const loadFromInput = () => {\n    let input = output;\n    try {\n      input = window.atob(input);\n    } catch (e) {\n      // Do nothing.\n    }\n    const inputState = JSON.parse(input);\n    const stateToRestore = {\n      ...inputState,\n      story: { ...reducerState.story, ...inputState.story },\n      capabilities: reducerState.capabilities,\n    };\n    const [stateWithDummyResources, videosToReload] = isDummyResources\n      ? replaceResourcesWithDummy(stateToRestore)\n      : [stateToRestore, []];\n    restore(stateWithDummyResources);\n    if (videosToReload.length > 0) {\n      videosToReload.forEach((videoId) => {\n        const videoEl = document.getElementById(`video-${videoId}`);\n        if (videoEl) {\n          videoEl.load();\n        }\n      });\n    }\n    showSnackbar({ message: 'Story restored from input', timeout: 1200 });\n  };\n\n  useGlobalKeyDownEffect(\n    { key: 'mod+shift+alt+j', editable: true },\n    toggleVisible\n  );\n\n  const jsonStr = JSON.stringify(storyData, null, 2);\n  const defaultOutput = isBase64 ? window.btoa(jsonStr) : jsonStr;\n  const [output, setOutput] = useState(defaultOutput);\n  useEffect(() => setOutput(defaultOutput), [defaultOutput]);\n  const changeTextarea = (evt) => setOutput(evt.target.value);\n\n  return isVisible ? (\n    <Container>\n      <Options>\n        <div>\n          <Label title=\"For easier sharing thru various channels\">\n            <input type=\"checkbox\" checked={isBase64} onChange={toggleBase64} />\n            {'Base64'}\n          </Label>\n          <Label title=\"Replace resources with dummy resources\">\n            <input\n              type=\"checkbox\"\n              checked={isDummyResources}\n              onChange={toggleDummyResources}\n            />\n            {'Dummy resources'}\n          </Label>\n          <Label title=\"Export as Template\">\n            <input\n              type=\"checkbox\"\n              checked={isTemplate}\n              onChange={toggleTemplate}\n            />\n            {'Template'}\n          </Label>\n        </div>\n        <div>\n          <Button aria-label=\"Load data from input\" onClick={loadFromInput}>\n            {'Load'}\n          </Button>\n          <Button aria-label=\"Copy data to clipboard\" onClick={copyToClipboard}>\n            {'Copy'}\n          </Button>\n          <Button aria-label=\"Close DevTools\" onClick={toggleVisible}>\n            {'X'}\n          </Button>\n        </div>\n      </Options>\n      <Textarea\n        ref={textareaRef}\n        className=\"mousetrap\"\n        value={output}\n        onChange={changeTextarea}\n      />\n    </Container>\n  ) : null;\n}\n\nexport default DevTools;\n"
  },
  {
    "path": "packages/story-editor/src/components/devTools/dummyData.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const dummyVideo =\n  'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAPEbW9vdgAAAGxtdmhkAAAAANrF/AXaxfwFAAAD6AAAB9AAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAABhpb2RzAAAAABCAgIAHAE///////wAAAzh0cmFrAAAAXHRraGQAAAAB2sX8BdrF/AUAAAABAAAAAAAAB9AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAABQAAAAUAAAAAAKwbWRpYQAAACBtZGhkAAAAANrF/AXaxfwFAAAD6AAAB9BVxAAAAAAAIWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAAAAAAACZ21pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAq3N0c2QAAAAAAAAAAQAAAJthdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAABQAFABIAAAASAAAAAAAAAABDkpWVC9BVkMgQ29kaW5nAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAAM2F2Y0MBTUAK/+EAG2dNQArsxLzzzUBAQZAAAAMAEAAAAwFI8SJZoAEABWjpeyyAAAAAEmNvbHJuY2xjAAEAAQAGAAAAGHN0dHMAAAAAAAAAAQAAABQAAABkAAAAZHN0c3oAAAAAAAAAAAAAABQAAAC1AAAADAAAAAwAAAAMAAAADAAAAGcAAAAOAAAADQAAAAwAAADEAAAADwAAAA4AAAAMAAAAmgAAAA8AAAAMAAAADAAAABEAAAAOAAAADAAAABxzdHNjAAAAAAAAAAEAAAABAAAACgAAAAEAAAAgY282NAAAAAAAAAACAAAAAAAAA/QAAAAAAAAGKwAAAKhjdHRzAAAAAAAAABMAAAABAAAAyAAAAAEAAAH0AAAAAQAAAMgAAAABAAAAAAAAAAEAAABkAAAAAQAAAfQAAAABAAAAyAAAAAEAAAAAAAAAAQAAAGQAAAABAAAB9AAAAAEAAADIAAAAAQAAAAAAAAABAAAAZAAAAAEAAAH0AAAAAQAAAMgAAAABAAAAAAAAAAEAAABkAAAAAQAAAZAAAAACAAAAZAAAABRzdHNzAAAAAAAAAAEAAAABAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAAH0AAAAMgAAQAAAAAAAW1kYXQAAAAAAAADXAAAALFliIQAIf8tERhKDUPN//6tPIlfMgqs2j4bf1chdW+++2VwQdh75gd9Y8UGeNAnhlaisT01Zs49a/0nV0aO/GLhqiGwvWR/s1K9W3zBx2od2cS1bT/kb2rz7FeHrWTqTLX6Gx65Y6i33pdJ/uLJd1nt76ybxnGFuPrIHacdB39MBmZsd4t/m7wPBzhrJIjUCiCUcSaxJPxvEH+6DID5TqxsXtv0RS9+hTuYECGa+YWdx4EAAAAIQZokbEMfi4AAAAAIQZ5COIc/0YEAAAAIAZ5hNEEH1YAAAAAIAZ5jakEH1YEAAABjQZpoSahBaJlMCM/eVhjnGE9A+AdJ7SwN5vlKUC/otPa/5jefanvcx5sQZ4c8/3tiMqvDgQF8rydFoFe3gcpkTP4xG9DP5oXTv1DTSsVi1O/u9fkq6BMYR61X6/n148wbBk3hAAAACkGehi5RMJfxO6sAAAAJAZ6lKRDn87czAAAACAGep25Cn8WAAAAAwEGarDUILakymAT/lvijvmpe6mLGpu6rJNoev4/97f/3/AViMdt7WMTLeGSxGKwsecwmz+Z5NTf4Lgky4aLbYBjw9pUtNg4bov9E4yT+OadpewkQxiWZZozDDf98P4PN72xr+rkQJcODW8z2LOkQVijjHcWSmTAvF7/ANFm8TO5l9vC/tz7FvEis+ba+dTueI87l9hdLXQfWqKN+J9j1fj5cguj08byzEmWnKbLlqG1uTZmu0LDedc3Ugo76bySHIAAAAAtBnspklERc3+sNqQAAAAoBnukpEZ/3fsMPAAAACAGe625N/6+AAAAAlkGa8DUILakymARfBGYe5snAbMic1iEEu9W/yugK09WdqQ1/7ftt/lUz4i6orQg+4cIz2nHYVKTXCJJbyOrz/tGL+TWtNtUBVK2kbTsfCYF8ddhk+qL5Jr82IUEUALXNsKpx1hhGIJnvqqlGTOyyOpmwbHhNUa2TaBkzzVzuaVnuHnaL3sjfLR0XEc/T6ntUXHacPLf94QAAAAtBnw5klERd//FEowAAAAgBny1pFf+ngQAAAAgBny9uf+yhJAAAAA1BmzM1CC2pMpgE/xwwAAAACkGfUWSURFz/kYEAAAAIAZ9ybkv/mIA=';\nexport const dummyImage =\n  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGElEQVQYV2NkYGD4////fwZGEMnIyMgAAEvqB/6wfXLSAAAAAElFTkSuQmCC';\n"
  },
  {
    "path": "packages/story-editor/src/components/devTools/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default } from './devTools';\n"
  },
  {
    "path": "packages/story-editor/src/components/dialog/dialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { ThemeProvider } from 'styled-components';\nimport {\n  Dialog as StyledDialog,\n  Button,\n  ButtonSize,\n  ButtonType,\n  theme,\n  lightMode,\n} from '@googleforcreators/design-system';\n\n/**\n * Dialog is wrapped in a ThemeProvider so that colors can be inverted.\n *\n * @param {boolean} isOpen When true, dialog will be visible\n * @param {Function} onClose Action taken on 'x'/clicking outside of dialog. Default secondary action.\n * @param {Function} onSecondary Action taken on secondary button click when specified.\n * @param {Function} onPrimary Action taken on primary button click.\n * @param {string} primaryText When present, primary button will render.\n * @param {string} secondaryText When present, secondary button will render.\n * @param {Object} primaryRest Unique props needed on primary button, spread on button.\n * @param {Object} secondaryRest Unique props needed on secondary button, spread on button.\n * @param {Object} actions Custom actions object for when the API restrictions of primary and secondary structure are too much.\n * @param {Node} children Contents of dialog\n */\n\nconst Dialog = ({\n  onClose,\n  onSecondary,\n  onPrimary,\n  primaryText,\n  PrimaryComponent = Button,\n  secondaryText,\n  primaryRest,\n  secondaryRest,\n  actions,\n  children,\n  ...rest\n}) => {\n  const _PrimaryButton = useMemo(\n    () =>\n      primaryText && (\n        <PrimaryComponent\n          type={ButtonType.Primary}\n          size={ButtonSize.Small}\n          onClick={(evt) => onPrimary?.(evt)}\n          {...primaryRest}\n        >\n          {primaryText}\n        </PrimaryComponent>\n      ),\n    [primaryText, primaryRest, onPrimary]\n  );\n\n  const _SecondaryButton = useMemo(\n    () =>\n      secondaryText && (\n        <Button\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          onClick={() => onSecondary?.() || onClose()}\n          {...secondaryRest}\n        >\n          {secondaryText}\n        </Button>\n      ),\n    [secondaryText, secondaryRest, onSecondary, onClose]\n  );\n\n  return (\n    <ThemeProvider theme={{ ...theme, colors: lightMode }}>\n      <StyledDialog\n        onClose={onClose}\n        {...rest}\n        actions={\n          actions || (\n            <>\n              {_SecondaryButton}\n              {_PrimaryButton}\n            </>\n          )\n        }\n      >\n        {children}\n      </StyledDialog>\n    </ThemeProvider>\n  );\n};\n\nDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onPrimary: PropTypes.func,\n  onSecondary: PropTypes.func,\n  primaryText: PropTypes.string,\n  PrimaryComponent: PropTypes.object,\n  primaryRest: PropTypes.object,\n  secondaryText: PropTypes.string,\n  secondaryRest: PropTypes.object,\n  actions: PropTypes.object,\n  children: PropTypes.node,\n};\n\nexport default Dialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/dialog/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './dialog';\n"
  },
  {
    "path": "packages/story-editor/src/components/dialog/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Base',\n  component: Dialog,\n  args: {\n    primaryText: 'confirm action',\n    secondaryText: 'cancel action',\n    title: 'my dialog title',\n    isOpen: true,\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n    onPrimary: { action: 'primary clicked' },\n    onSecondary: { action: 'secondary clicked' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['actions', 'children'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Dialog {...args}>\n        <Text.Paragraph size={TextSize.Small}>\n          {\n            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'\n          }\n        </Text.Paragraph>\n      </Dialog>\n    );\n  },\n};\n\nexport const WithCustomAction = {\n  render: _default,\n\n  args: {\n    primaryRest: {\n      href: 'https://example.com',\n    },\n    primaryText: 'primary button',\n    secondaryText: 'secondary button',\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/directionAware/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { StyleSheetManager } from 'styled-components';\nimport stylisRTLPlugin from 'stylis-plugin-rtl';\nObject.defineProperty(stylisRTLPlugin, 'name', { value: 'stylisRTLPlugin' });\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app';\n\nconst withRTLPlugins = [stylisRTLPlugin];\nconst withoutRTLPlugins = [];\n\nfunction DirectionAware({ children }) {\n  const { isRTL } = useConfig();\n  return (\n    <StyleSheetManager\n      stylisPlugins={isRTL ? withRTLPlugins : withoutRTLPlugins}\n    >\n      {children}\n    </StyleSheetManager>\n  );\n}\n\nDirectionAware.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default DirectionAware;\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as DropTargetsProvider } from './provider';\nexport { default as useDropTargets } from './useDropTargets';\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/karma/dropTarget.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { useLocalMedia } from '../../../app/media';\n\ndescribe('Drop-Target integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getElements = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  };\n\n  describe('when there is nothing on the canvas', () => {\n    it('should by default have transparent background', async () => {\n      const backgroundId = (await getElements(fixture))[0].id;\n      const bgElement =\n        fixture.editor.canvas.displayLayer.display(backgroundId).element;\n\n      // Verify that it's empty\n      expect(bgElement).toBeEmpty();\n\n      // And that background color is transparent:\n      expect(bgElement).toHaveStyle('backgroundColor', 'rgba(0, 0, 0, 0)');\n    });\n\n    it('should correctly handle image dragged from library straight to edge', async () => {\n      const backgroundId = (await getElements(fixture))[0].id;\n\n      // Verify that bg replacement is empty\n      let rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n      expect(rep1).toBeEmpty();\n\n      // Get library element reference\n      const libraryElement = fixture.editor.library.media.item(0);\n\n      // Drag the element to the background\n      await dragToDropTarget(fixture, libraryElement, backgroundId);\n\n      // Update to DOM mutations\n      rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n\n      // Verify that bg replacement is no longer empty\n      expect(rep1).not.toBeEmpty();\n\n      // Verify that replacement img has correct source\n      const replaceImg = rep1.querySelector('img');\n      const libraryImage = libraryElement.querySelector('img');\n      expect(replaceImg).toHaveProperty('src', libraryImage.src);\n\n      // Now drop the element\n      await fixture.events.mouse.up();\n\n      // And then wait a frame before invoking story hook\n      await fixture.events.sleep(100);\n\n      // Verify new background element has the correct image\n      const bgElement = (await getElements(fixture))[0];\n      expect(bgElement.type).toBe('image');\n      const bg = fixture.editor.canvas.displayLayer.display(\n        bgElement.id\n      ).element;\n      const bgImg = bg.querySelector('img');\n      expect(bgImg).toHaveProperty('src', libraryImage.src);\n\n      // And verify that we no longer have a replacement element\n      const rep2 = fixture.editor.canvas.displayLayer.display(\n        bgElement.id\n      ).replacement;\n      expect(rep2).toBeEmpty();\n\n      // Verify the background base color is handled as expected.\n      expect(bgElement.resource.baseColor).toEqual('#734727');\n    });\n\n    it('should correctly handle image dragged from library straight to edge (no cached base color)', async () => {\n      const backgroundId = (await getElements(fixture))[0].id;\n\n      // Verify that bg replacement is empty\n      let rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n      expect(rep1).toBeEmpty();\n\n      // Get library element reference\n      const mediaIndex = 4;\n      const { mediaResource } = await fixture.renderHook(() =>\n        useLocalMedia(({ state }) => ({\n          mediaResource: state.media[mediaIndex],\n        }))\n      );\n      const libraryElement = fixture.editor.library.media.item(mediaIndex);\n\n      // Drag the element to the background\n      await dragToDropTarget(fixture, libraryElement, backgroundId);\n\n      // Update to DOM mutations\n      rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n\n      // Verify that bg replacement is no longer empty\n      expect(rep1).not.toBeEmpty();\n\n      // Verify that replacement img has correct source\n      const replaceImg = rep1.querySelector('img');\n      const libraryImage = libraryElement.querySelector('img');\n      expect(replaceImg).toHaveProperty('src', libraryImage.src);\n\n      // Now drop the element\n      await fixture.events.mouse.up();\n\n      // And then wait a frame before invoking story hook\n      await fixture.events.sleep(100);\n\n      // Verify new background element has the correct image\n      const bgElement = (await getElements(fixture))[0];\n      expect(bgElement.type).toBe('image');\n      const bg = fixture.editor.canvas.displayLayer.display(\n        bgElement.id\n      ).element;\n      const bgImg = bg.querySelector('img');\n      expect(bgImg).toHaveProperty('src', libraryImage.src);\n\n      // And verify that we no longer have a replacement element\n      const rep2 = fixture.editor.canvas.displayLayer.display(\n        bgElement.id\n      ).replacement;\n      expect(rep2).toBeEmpty();\n\n      // Verify the background base color is handled as expected.\n      await waitFor(() => {\n        if (bgElement.resource.baseColor === mediaResource.baseColor) {\n          return;\n        }\n        throw new Error('Background element image loading');\n      });\n      expect(bgElement.resource.baseColor).toEqual(mediaResource.baseColor);\n    });\n  });\n\n  describe('when there is an image on the canvas', () => {\n    let imageData;\n\n    beforeEach(async () => {\n      await insertMediaByIndex(fixture, 0);\n      imageData = (await getElements(fixture))[1];\n    });\n\n    it('should correctly handle image dropped on edge', async () => {\n      const backgroundId = (await getElements(fixture))[0].id;\n\n      // Verify that bg replacement is empty\n      let rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n      expect(rep1).toBeEmpty();\n\n      // Drag the image element to the background\n      await dragCanvasElementToDropTarget(fixture, imageData.id, backgroundId);\n\n      // Update to DOM mutations\n      rep1 =\n        fixture.editor.canvas.displayLayer.display(backgroundId).replacement;\n\n      // Verify that bg replacement is no longer empty\n      expect(rep1).not.toBeEmpty();\n\n      // Verify that replacement img has correct source\n      const replaceImg = rep1.querySelector('img');\n      expect(replaceImg).toHaveProperty('src', imageData.resource.src);\n\n      // Now drop the element\n      await fixture.events.mouse.up();\n\n      // Verify new background element has the correct image\n      const newBackgroundId = (await getElements(fixture))[0].id;\n      const bg =\n        fixture.editor.canvas.displayLayer.display(newBackgroundId).element;\n      const bgImg = bg.querySelector('img');\n      expect(bgImg).toHaveProperty('src', imageData.resource.src);\n\n      // And verify that we no longer have a replacement element\n      const rep2 =\n        fixture.editor.canvas.displayLayer.display(newBackgroundId).replacement;\n      expect(rep2).toBeEmpty();\n    });\n  });\n\n  describe('when there is a background image and nothing else', () => {\n    let bgImageData;\n\n    beforeEach(async () => {\n      const libraryElement = fixture.editor.library.media.item(0);\n      const backgroundId = (await getElements(fixture))[0].id;\n      await dragToDropTarget(fixture, libraryElement, backgroundId);\n      await fixture.events.mouse.up();\n      await fixture.events.sleep(100);\n\n      bgImageData = (await getElements(fixture))[0];\n    });\n\n    it('should correctly handle image dragged from library straight to edge replacing old image', async () => {\n      // Verify that background element has the correct image before doing anything\n      const bg1 = fixture.editor.canvas.displayLayer.display(\n        bgImageData.id\n      ).element;\n      const bgImg1 = bg1.querySelector('img');\n      expect(bgImg1).toHaveProperty('src', bgImageData.resource.src);\n\n      // Verify that bg replacement is empty\n      let rep1 = fixture.editor.canvas.displayLayer.display(\n        bgImageData.id\n      ).replacement;\n      expect(rep1).toBeEmpty();\n\n      // Get library element reference\n      const libraryElement = fixture.editor.library.media.item(1);\n      const libraryImage = libraryElement.querySelector('img');\n\n      // Drag the element to the background\n      await dragToDropTarget(fixture, libraryElement, bgImageData.id);\n\n      // make sure rep1 is up to date with latest DOM updates.\n      rep1 = fixture.editor.canvas.displayLayer.display(\n        bgImageData.id\n      ).replacement;\n\n      // Verify that bg replacement is no longer empty\n      expect(rep1).not.toBeEmpty();\n\n      // Verify that replacement img has correct source\n      const replaceImg = rep1.querySelector('img');\n      expect(replaceImg).toHaveProperty('src', libraryImage.src);\n\n      // Now drop the element\n      await fixture.events.mouse.up();\n\n      // Verify new background element has the correct image\n      const newBackgroundId = (await getElements(fixture))[0].id;\n      const bg2 =\n        fixture.editor.canvas.displayLayer.display(newBackgroundId).element;\n      const bgImg2 = bg2.querySelector('img');\n      expect(bgImg2).toHaveProperty('src', libraryImage.src);\n\n      // And verify that we no longer have a replacement element\n      const rep2 =\n        fixture.editor.canvas.displayLayer.display(newBackgroundId).replacement;\n      expect(rep2).toBeEmpty();\n    });\n\n    describe('when there is second image on canvas', () => {\n      let imageData;\n\n      beforeEach(async () => {\n        await insertMediaByIndex(fixture, 1);\n        imageData = (await getElements(fixture))[1];\n      });\n\n      it('should correctly handle image dropped on edge replacing old image', async () => {\n        // Verify that background element has the correct image before doing anything\n        const bg1 = fixture.editor.canvas.displayLayer.display(\n          bgImageData.id\n        ).element;\n        const bgImg1 = bg1.querySelector('img');\n        expect(bgImg1).toHaveProperty('src', bgImageData.resource.src);\n\n        // Verify that bg replacement is empty\n        let rep1 = fixture.editor.canvas.displayLayer.display(\n          bgImageData.id\n        ).replacement;\n        expect(rep1).toBeEmpty();\n\n        // Drag the image element to the background\n        await dragCanvasElementToDropTarget(\n          fixture,\n          imageData.id,\n          bgImageData.id\n        );\n\n        // Update to DOM mutations\n        rep1 = fixture.editor.canvas.displayLayer.display(\n          bgImageData.id\n        ).replacement;\n\n        // Verify that bg replacement is no longer empty\n        expect(rep1).not.toBeEmpty();\n\n        // Verify that replacement img has correct source\n        const replaceImg = rep1.querySelector('img');\n        expect(replaceImg).toHaveProperty('src', imageData.resource.src);\n\n        // Now drop the element\n        await fixture.events.mouse.up();\n\n        // Verify new background element has the correct image\n        const newBackgroundId = (await getElements(fixture))[0].id;\n        const bg2 =\n          fixture.editor.canvas.displayLayer.display(newBackgroundId).element;\n        const bgImg2 = bg2.querySelector('img');\n        expect(bgImg2).toHaveProperty('src', imageData.resource.src);\n\n        // And verify that we no longer have a replacement element\n        const rep2 =\n          fixture.editor.canvas.displayLayer.display(\n            newBackgroundId\n          ).replacement;\n        expect(rep2).toBeEmpty();\n      });\n\n      describe('when the background is flipped', () => {\n        beforeEach(async () => {\n          // Click the bg in the top left corner\n          const bgElement = fixture.editor.canvas.framesLayer.frame(\n            bgImageData.id\n          ).node;\n          await fixture.events.mouse.clickOn(bgElement, 5, 5);\n\n          // And flip it\n          await fixture.events.click(fixture.editor.sidebar.designTab);\n          await fixture.events.click(\n            fixture.editor.sidebar.designPanel.pageBackground.flipHorizontal\n          );\n        });\n\n        it('should correctly handle image dropped on edge without flip', async () => {\n          // Verify that background element has the correct transform (flip) before doing anything\n          const bg1 = fixture.editor.canvas.displayLayer.display(\n            bgImageData.id\n          ).node;\n          const rep = fixture.editor.canvas.displayLayer.display(\n            bgImageData.id\n          ).replacement;\n          const bgImg1 = bg1.querySelector('img');\n          const combinedBgTransform1 = getAllTransformsBetween(bgImg1, bg1);\n          expect(combinedBgTransform1).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n\n          // Drag the image element to the background\n          await dragCanvasElementToDropTarget(\n            fixture,\n            imageData.id,\n            bgImageData.id\n          );\n\n          // Verify that replacement img has correct transform\n          const replaceImg = rep.querySelector('img');\n          const combinedRepTransform = getAllTransformsBetween(replaceImg, bg1);\n          expect(combinedRepTransform).toBe('');\n\n          // Now drop the element\n          await fixture.events.mouse.up();\n\n          // Verify that new background is not flipped\n          const newBackgroundId = (await getElements(fixture))[0].id;\n          const bg2 =\n            fixture.editor.canvas.displayLayer.display(newBackgroundId).node;\n          const bgImg2 = bg2.querySelector('img');\n          const combinedBgTransform2 = getAllTransformsBetween(bgImg2, bg2);\n          expect(combinedBgTransform2).toBe('');\n        });\n      });\n\n      describe('when the canvas element is flipped', () => {\n        beforeEach(async () => {\n          // Click the corner of the on-canvas element\n          const element = fixture.editor.canvas.framesLayer.frame(\n            imageData.id\n          ).node;\n          await fixture.events.mouse.clickOn(element, 1, 1);\n\n          // And flip it\n          await fixture.events.click(fixture.editor.sidebar.designTab);\n          await fixture.events.click(\n            fixture.editor.sidebar.designPanel.sizePosition.flipHorizontal\n          );\n        });\n\n        it('should correctly handle image dropped on edge with flip', async () => {\n          // Verify that background element has the correct transform (flip) before doing anything\n          let bg1 = fixture.editor.canvas.displayLayer.display(\n            bgImageData.id\n          ).node;\n          let rep = fixture.editor.canvas.displayLayer.display(\n            bgImageData.id\n          ).replacement;\n          const bgImg1 = bg1.querySelector('img');\n          const combinedBgTransform1 = getAllTransformsBetween(bgImg1, bg1);\n          expect(combinedBgTransform1).toBe('');\n\n          // Drag the image element to the background\n          await dragCanvasElementToDropTarget(\n            fixture,\n            imageData.id,\n            bgImageData.id\n          );\n\n          // Make sure rep is up to date with DOM mutations\n          bg1 = fixture.editor.canvas.displayLayer.display(bgImageData.id).node;\n          rep = fixture.editor.canvas.displayLayer.display(\n            bgImageData.id\n          ).replacement;\n\n          // Verify that replacement img has correct transform\n          const replaceImg = rep.querySelector('img');\n          const combinedRepTransform = getAllTransformsBetween(replaceImg, bg1);\n          expect(combinedRepTransform).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n\n          // Now drop the element\n          await fixture.events.mouse.up();\n\n          // Verify that new background is flipped\n          const newBackgroundId = (await getElements(fixture))[0].id;\n          const bg2 =\n            fixture.editor.canvas.displayLayer.display(newBackgroundId).node;\n          const bgImg2 = bg2.querySelector('img');\n          const combinedBgTransform2 = getAllTransformsBetween(bgImg2, bg2);\n          expect(combinedBgTransform2).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n        });\n      });\n\n      describe('when there is a third flipped image on the canvas', () => {\n        let flippedImageData;\n\n        beforeEach(async () => {\n          await insertMediaByIndex(fixture, 2);\n          flippedImageData = (await getElements(fixture))[2];\n\n          await fixture.events.click(fixture.editor.sidebar.designTab);\n          await fixture.events.click(\n            fixture.editor.sidebar.designPanel.sizePosition.flipHorizontal\n          );\n\n          const element = fixture.editor.canvas.displayLayer.display(\n            flippedImageData.id\n          ).node;\n\n          await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n            moveRel(element, '50%', '50%'),\n            down(),\n            moveRel(element, '50%', '200%'),\n            up(),\n          ]);\n        });\n\n        it('should correctly handle flipped image dropped into non-flipped image', async () => {\n          // Verify that non-flipped element has the correct transform (flip) before doing anything\n          let target = fixture.editor.canvas.displayLayer.display(\n            imageData.id\n          ).node;\n          let rep = fixture.editor.canvas.displayLayer.display(\n            imageData.id\n          ).replacement;\n          const targetImg = target.querySelector('img');\n          const transformBefore = getAllTransformsBetween(targetImg, target);\n          expect(transformBefore).toBe('');\n\n          // Drag the flipped image element to the non-flipped target\n          await dragCanvasElementToDropTarget(\n            fixture,\n            flippedImageData.id,\n            imageData.id\n          );\n\n          // Make sure rep is up to date with DOM mutations\n          target = fixture.editor.canvas.displayLayer.display(\n            imageData.id\n          ).node;\n          rep = fixture.editor.canvas.displayLayer.display(\n            imageData.id\n          ).replacement;\n\n          // Verify that replacement img has correct transform\n          const replaceImg = rep.querySelector('img');\n          const replTransform = getAllTransformsBetween(replaceImg, target);\n          expect(replTransform).toBe('');\n\n          // Now drop the element\n          await fixture.events.mouse.up();\n\n          // Verify that new combined element is still not flipped\n          const newElementId = (await getElements(fixture))[1].id;\n          const newTarget =\n            fixture.editor.canvas.displayLayer.display(newElementId).node;\n          const newTargetImg = newTarget.querySelector('img');\n          const transformAfter = getAllTransformsBetween(\n            newTargetImg,\n            newTarget\n          );\n          expect(transformAfter).toBe('');\n        });\n\n        it('should correctly handle non-flipped image dropped into flipped image', async () => {\n          // Verify that non-flipped element has the correct transform (flip) before doing anything\n          let target = fixture.editor.canvas.displayLayer.display(\n            flippedImageData.id\n          ).node;\n          let rep = fixture.editor.canvas.displayLayer.display(\n            flippedImageData.id\n          ).replacement;\n          const targetImg = target.querySelector('img');\n          const transformBefore = getAllTransformsBetween(targetImg, target);\n          expect(transformBefore).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n\n          // Drag the image element to the background\n          await dragCanvasElementToDropTarget(\n            fixture,\n            imageData.id,\n            flippedImageData.id\n          );\n\n          // Make sure rep is up to date with DOM mutations\n          target = fixture.editor.canvas.displayLayer.display(\n            flippedImageData.id\n          ).node;\n          rep = fixture.editor.canvas.displayLayer.display(\n            flippedImageData.id\n          ).replacement;\n\n          // Verify that replacement img has correct transform\n          const replaceImg = rep.querySelector('img');\n          const replTransform = getAllTransformsBetween(replaceImg, target);\n          expect(replTransform).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n\n          // Now drop the element\n          await fixture.events.mouse.up();\n\n          // Verify that new combined element is still flipped\n          const newElementId = (await getElements(fixture))[1].id;\n          const newTarget =\n            fixture.editor.canvas.displayLayer.display(newElementId).node;\n          const newTargetImg = newTarget.querySelector('img');\n          const transformAfter = getAllTransformsBetween(\n            newTargetImg,\n            newTarget\n          );\n          expect(transformAfter).toBe('matrix(-1, 0, 0, 1, 0, 0)');\n        });\n      });\n    });\n  });\n});\n\nfunction dragCanvasElementToDropTarget(fixture, fromId, toId) {\n  const from = fixture.editor.canvas.framesLayer.frame(fromId).node;\n  return dragToDropTarget(fixture, from, toId);\n}\n\nasync function insertMediaByIndex(fixture, index) {\n  const mediaItem = fixture.editor.library.media.item(index);\n  await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n}\n\nasync function dragToDropTarget(fixture, from, toId) {\n  const to = fixture.editor.canvas.framesLayer.frame(toId).node;\n\n  // Schedule a sequence of events by dragging from center of image\n  // to corner of target\n  await fixture.events.mouse.seq(({ moveRel, down }) => [\n    moveRel(from, '20%', '20%'),\n    down(),\n    moveRel(to, 5, 5, { steps: 5 }),\n  ]);\n}\n\nfunction getAllTransformsBetween(startElement, endElement) {\n  let e = startElement;\n  const transforms = [];\n  while (e && e !== endElement) {\n    transforms.unshift(getComputedStyle(e).transform);\n    e = e.parentNode;\n  }\n\n  return transforms.filter((t) => t !== 'none').join(' ');\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/karma/order.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Drop-Target order', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function insertMediaByIndex(index) {\n    const mediaItem = fixture.editor.library.media.item(index);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n  }\n\n  it('should replace top image when bg image is set and another one is on top', async () => {\n    // Drag first media element straight to canvas edge to set as background\n    const bgMedia = fixture.editor.library.media.item(0);\n    const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n\n    await fixture.events.mouse.seq(({ down, moveRel, up }) => [\n      moveRel(bgMedia, 20, 20),\n      down(),\n      moveRel(canvas, 10, 10),\n      up(),\n    ]);\n\n    // Add one more element\n    await insertMediaByIndex(1);\n\n    // Get the elements\n    const [bgImage, topImage] = await getElements(fixture);\n\n    // Drag the top element to align with the edge without dropping in there\n    const bgFrame = fixture.editor.canvas.framesLayer.frame(bgImage.id).node;\n    const topFrame = fixture.editor.canvas.framesLayer.frame(topImage.id).node;\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(topFrame, 25, 25),\n      down(),\n      moveRel(bgFrame, 25, 25),\n      up(),\n    ]);\n\n    // Now add one more element\n    await insertMediaByIndex(2);\n\n    // Get the new element\n    const otherImage = (await getElements(fixture))[2];\n\n    const otherFrame = fixture.editor.canvas.framesLayer.frame(\n      otherImage.id\n    ).node;\n\n    // Drag image by edge to position of top image edge\n    // (which should collide with bg image edge)\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(otherFrame, 5, 5),\n      down(),\n      moveRel(topFrame, 5, 5),\n      up(),\n    ]);\n\n    // Expect old element to have been removed\n    expect(fixture.editor.canvas.framesLayer.frame(otherImage.id)).toBeFalsy();\n\n    const backgroundId = (await getElements(fixture))[0].id;\n    // TODO: refactor after #2386?\n    const topImageImg = fixture.editor.canvas.displayLayer\n      .display(topImage.id)\n      .node.querySelector('img');\n    const backgroundImg = fixture.editor.canvas.displayLayer\n      .display(backgroundId)\n      .node.querySelector('img');\n\n    await waitFor(() => {\n      if (!topImageImg || !backgroundImg) {\n        throw new Error('image not ready');\n      }\n      expect(topImageImg.src).toBe(otherImage.resource.src);\n      expect(backgroundImg.src).toBe(bgImage.resource.src);\n    });\n  });\n\n  it('should replace the top image when two images are in the same place on canvas', async () => {\n    // Add three images - will be added on top of each other\n    await insertMediaByIndex(0);\n    await insertMediaByIndex(1);\n    await insertMediaByIndex(2);\n\n    // Get the elements\n    const elements = await getElements(fixture);\n    // Slice out the irrelevant bg element and get the next three\n    const [bottomImage, topImage, otherImage] = elements.slice(1);\n\n    const otherImageFrame = fixture.editor.canvas.framesLayer.frame(\n      otherImage.id\n    ).node;\n\n    // Drag image to other image edge - they're all aligned with the\n    // same top left corner.\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(otherImageFrame, 5, 5),\n      down(),\n      moveBy(0, 10),\n      up(),\n    ]);\n\n    // Expect old element to have been removed\n    expect(fixture.editor.canvas.framesLayer.frame(otherImage.id)).toBeFalsy();\n\n    const topImageImg = fixture.editor.canvas.displayLayer\n      .display(topImage.id)\n      .node.querySelector('img');\n    const bottomImageImg = fixture.editor.canvas.displayLayer\n      .display(bottomImage.id)\n      .node.querySelector('img');\n    expect(topImageImg.src).toBe(otherImage.resource.src);\n    expect(bottomImageImg.src).toBe(bottomImage.resource.src);\n  });\n});\n\nasync function getElements(fixture) {\n  const {\n    state: {\n      currentPage: { elements },\n    },\n  } = await fixture.renderHook(() => useStory());\n  return elements;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useState, useMemo, useCallback } from '@googleforcreators/react';\nimport { useGlobalIsKeyPressed } from '@googleforcreators/design-system';\nimport { useTransform } from '@googleforcreators/transform';\nimport {\n  getDefinitionForType,\n  ELEMENT_TYPES,\n  MEDIA_ELEMENT_TYPES,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\nimport getElementProperties from '../canvas/utils/getElementProperties';\nimport { noop } from '../../utils/noop';\nimport Context from './context';\n\nconst DROP_SOURCE_ALLOWED_TYPES = MEDIA_ELEMENT_TYPES;\nconst DROP_TARGET_ALLOWED_TYPES = MEDIA_ELEMENT_TYPES.concat(\n  ELEMENT_TYPES.SHAPE\n);\n\nconst isDropSource = (type) => DROP_SOURCE_ALLOWED_TYPES.includes(type);\nconst isDropTarget = (type) => DROP_TARGET_ALLOWED_TYPES.includes(type);\n\nfunction DropTargetsProvider({ children }) {\n  const [draggingResource, setDraggingResource] = useState(null);\n  const [dropTargets, setDropTargets] = useState({});\n  const [activeDropTargetId, setActiveDropTargetId] = useState(null);\n  const {\n    actions: { pushTransform },\n  } = useTransform();\n  const { currentPage, combineElements } = useStory(\n    ({ state: { currentPage }, actions: { combineElements } }) => ({\n      currentPage,\n      combineElements,\n    })\n  );\n\n  const elements = useMemo(\n    () => currentPage?.elements || [],\n    [currentPage?.elements]\n  );\n\n  const sortedDropTargetIds = useMemo(\n    () =>\n      elements\n        .filter(({ id }) => id in dropTargets)\n        .map(({ id }) => id)\n        .reverse(), // Sort by z-index\n    [dropTargets, elements]\n  );\n\n  const getDropTargetFromCursor = useCallback(\n    (x, y, ignoreId = null) => {\n      const underCursor = document.elementsFromPoint(x, y);\n      return (\n        sortedDropTargetIds.find(\n          (id) => underCursor.includes(dropTargets[id]) && id !== ignoreId\n        ) || null\n      );\n    },\n    [sortedDropTargetIds, dropTargets]\n  );\n\n  /**\n   * Registering drop targets\n   */\n\n  const registerDropTarget = useCallback((id, ref) => {\n    setDropTargets((prev) => ({ ...prev, [id]: ref }));\n  }, []);\n\n  const unregisterDropTarget = useCallback((id) => {\n    setDropTargets((prev) => {\n      const { [id]: _, ...without } = prev;\n      return without;\n    });\n  }, []);\n\n  /**\n   * Dragging elements\n   */\n  const handleDrag = useCallback(\n    (resource, x, y, selfId = null) => {\n      if (!isDropSource(resource?.type)) {\n        return;\n      }\n\n      const newElement = getElementProperties(resource.type, {\n        resource,\n      });\n\n      const existingElement = elements.find(({ id }) => id === selfId);\n\n      // Get these attributes from the existing element (if exists and is non-null)\n      // or get defaults from a new element of the same type\n      const scale = existingElement?.scale ?? newElement.scale;\n      const focalX = existingElement?.focalX ?? newElement.focalX;\n      const focalY = existingElement?.focalY ?? newElement.focalY;\n      const flip = existingElement?.flip ?? newElement.flip;\n\n      const dropTargetId = getDropTargetFromCursor(x, y, selfId);\n\n      if (dropTargetId && dropTargetId !== activeDropTargetId) {\n        pushTransform(dropTargetId, {\n          dropTargets: {\n            active: true,\n            replacement: { resource, scale, focalX, focalY, flip },\n          },\n        });\n        if (selfId) {\n          pushTransform(selfId, {\n            dropTargets: { hover: true },\n          });\n        }\n      } else if (!dropTargetId) {\n        if (selfId) {\n          pushTransform(selfId, {\n            dropTargets: { hover: false },\n          });\n        }\n      }\n      setActiveDropTargetId(dropTargetId);\n      elements\n        .filter(({ id }) => id !== dropTargetId)\n        .forEach((el) =>\n          pushTransform(el.id, {\n            dropTargets: { active: false, replacement: null },\n          })\n        );\n    },\n    [activeDropTargetId, elements, getDropTargetFromCursor, pushTransform]\n  );\n\n  /**\n   * Dropping and merging elements\n   */\n  const handleDrop = useCallback(\n    (resource, selfId = null) => {\n      if (!isDropSource(resource?.type)) {\n        return;\n      }\n\n      if (!activeDropTargetId || activeDropTargetId === selfId) {\n        Object.keys(dropTargets)\n          .filter((id) => id !== selfId)\n          .map((id) => pushTransform(id, null));\n        return;\n      }\n\n      const combineArgs = {\n        secondId: activeDropTargetId,\n      };\n\n      const firstElement = elements.find(({ id }) => id === selfId);\n      if (firstElement) {\n        combineArgs.firstElement = firstElement;\n      } else {\n        // Create properties as you'd create them for a new element to be added\n        // Then merge these into the existing element using the same logic as\n        // for merging existing elements.\n        combineArgs.firstElement = getElementProperties(resource.type, {\n          resource,\n        });\n      }\n\n      combineElements(combineArgs);\n\n      // Reset styles on visible elements\n      elements\n        .filter(({ id }) => dropTargets[id] && id !== selfId)\n        .forEach((el) => {\n          pushTransform(el.id, {\n            dropTargets: {\n              active: false,\n              replacement: null,\n            },\n          });\n          pushTransform(el.id, null);\n        });\n\n      setActiveDropTargetId(null);\n\n      const { onDropHandler } = getDefinitionForType(resource.type);\n      // onDropHandler will play the video, but we don't want that for videos\n      // that don't have a src because they are still uploading.\n      if (onDropHandler && resource.src && !resource.isPlaceholder) {\n        onDropHandler(activeDropTargetId);\n      }\n    },\n    [activeDropTargetId, combineElements, elements, dropTargets, pushTransform]\n  );\n\n  // mod key (⌘ on macOS, Ctrl on Windows) disables drop-targeting.\n  const isDropTargetingDisabled = useGlobalIsKeyPressed('mod');\n\n  const state = {\n    state: {\n      dropTargets,\n      activeDropTargetId,\n      draggingResource,\n      isDropTargetingDisabled,\n    },\n    // If drop-targeting is disabled, all the related actions are ignored.\n    actions: {\n      registerDropTarget: isDropTargetingDisabled ? noop : registerDropTarget,\n      unregisterDropTarget,\n      isDropSource: isDropTargetingDisabled ? () => false : isDropSource,\n      isDropTarget: isDropTargetingDisabled ? () => false : isDropTarget,\n      handleDrag: isDropTargetingDisabled ? noop : handleDrag,\n      handleDrop: isDropTargetingDisabled ? noop : handleDrop,\n      setDraggingResource: isDropTargetingDisabled ? noop : setDraggingResource,\n    },\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nDropTargetsProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default DropTargetsProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/dropTargets/useDropTargets.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useDropTargets(selector, equalityFn) {\n  return useContextSelector(Context, selector ?? identity, equalityFn);\n}\n\nexport default useDropTargets;\n"
  },
  {
    "path": "packages/story-editor/src/components/elementLink/frame.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { withoutProtocol } from '@googleforcreators/url';\nimport { Placement, Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../propTypes';\nimport Tooltip from '../tooltip';\nimport { getLinkFromElement } from '.';\n\nconst StyledTooltip = styled(Tooltip)`\n  box-shadow: 0px 6px 10px\n    ${({ theme }) => rgba(theme.colors.standard.black, 0.1)};\n  align-items: center;\n  p {\n    display: flex;\n    max-width: 100%;\n  }\n`;\n\nconst IconWrapper = styled.span`\n  background-color: ${({ theme }) => theme.colors.fg.secondary};\n  width: 24px;\n  height: 24px;\n  border-radius: 50%;\n  overflow: hidden;\n  margin-right: 8px;\n  display: inline-block;\n`;\n\nconst BrandIcon = styled.img`\n  width: 100%;\n  height: 100%;\n  border: none;\n`;\n\nconst LinkDesc = styled.span`\n  padding-top: 2px;\n  flex: 1;\n  max-width: 100%;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n`;\n\nconst ExternalLink = styled(Icons.ExternalLink)`\n  width: 24px;\n`;\n\nfunction WithLink({ element, active, children, anchorRef }) {\n  const link = getLinkFromElement(element);\n\n  const tooltipContent =\n    link?.url && active ? (\n      <>\n        {link?.icon && (\n          <IconWrapper>\n            <BrandIcon\n              src={link.icon}\n              alt={__('Site Icon', 'web-stories')}\n              decoding=\"async\"\n              crossOrigin=\"anonymous\"\n            />\n          </IconWrapper>\n        )}\n        <LinkDesc>{link.desc || withoutProtocol(link.url)}</LinkDesc>\n        <ExternalLink />\n      </>\n    ) : null;\n\n  return (\n    <StyledTooltip\n      forceAnchorRef={anchorRef}\n      placement={Placement.Top}\n      title={tooltipContent}\n    >\n      {children}\n    </StyledTooltip>\n  );\n}\n\nWithLink.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n  anchorRef: PropTypes.object,\n  active: PropTypes.bool.isRequired,\n  children: PropTypes.node.isRequired,\n};\n\nexport default WithLink;\n"
  },
  {
    "path": "packages/story-editor/src/components/elementLink/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { LinkType } from '@googleforcreators/elements';\n\nexport function getLinkFromElement(element) {\n  return element.link || null;\n}\n\nexport function createLink({\n  url = '',\n  needsProxy = false,\n  rel = [],\n  type = LinkType.Regular,\n  pageId = null,\n  ...rest\n} = {}) {\n  return {\n    needsProxy,\n    url,\n    rel,\n    type,\n    pageId,\n    ...rest,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/emptyContentMessage.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { DesertBw } from '@googleforcreators/design-system';\n\nconst Message = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  max-width: 400px;\n  margin: 8vh auto;\n  text-align: center;\n\n  * {\n    text-align: center;\n    margin: 0 auto;\n  }\n`;\n\nconst EmptyImage = styled(DesertBw)`\n  margin-bottom: 48px;\n`;\n\nfunction EmptyContentMessage({ children, ...props }) {\n  return (\n    <Message {...props}>\n      <EmptyImage aria-hidden width={274} height={118} />\n      {children}\n    </Message>\n  );\n}\n\nEmptyContentMessage.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default EmptyContentMessage;\n"
  },
  {
    "path": "packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\n\nfunction CopyStoryDataToClipboard() {\n  const { pages, current, selection, story } = useStory(({ internal }) => ({\n    pages: internal.reducerState.pages,\n    current: internal.reducerState.current,\n    selection: internal.reducerState.selection,\n    story: internal.reducerState.story,\n  }));\n\n  const copyToClipboard = useCallback(async () => {\n    const jsonStr = JSON.stringify(\n      { pages, current, selection, story },\n      null,\n      2\n    );\n    try {\n      await navigator.clipboard.writeText(jsonStr);\n      alert(__('Copied to clipboard', 'web-stories'));\n    } catch {\n      alert(__('Failed to copy story data', 'web-stories'));\n    }\n  }, [pages, current, selection, story]);\n\n  if (!pages || !current || !selection || !story) {\n    return null;\n  }\n\n  return (\n    <Button\n      onClick={copyToClipboard}\n      variant={ButtonVariant.Rectangle}\n      type={ButtonType.Quaternary}\n      size={ButtonSize.Small}\n    >\n      {__('Copy story data', 'web-stories')}\n    </Button>\n  );\n}\n\nexport default CopyStoryDataToClipboard;\n"
  },
  {
    "path": "packages/story-editor/src/components/errorBoundary/errorActions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport CopyStoryDataToClipboard from './copyStoryDataToClipboard';\n\nconst Message = styled.div`\n  color: #fff;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 1.6;\n  padding: 20px;\n  button {\n    margin-right: 6px;\n  }\n`;\n\nconst TextArea = styled.textarea`\n  width: 100%;\n  min-height: 200px;\n`;\n\nconst P = styled.p`\n  margin: 0 0 8px 0;\n`;\n\nconst Wrapper = styled.div`\n  display: flex;\n`;\n\nfunction ErrorActions({ error, errorInfo }) {\n  const textAreaContent = `${error}\\n${errorInfo.componentStack}`;\n  const reportUrl =\n    'https://wordpress.org/support/plugin/web-stories/#new-topic-0';\n\n  const reload = () => {\n    window.location.reload(true);\n  };\n\n  return (\n    <Message>\n      <P>{__('Something went wrong!', 'web-stories')}</P>\n      <P>\n        {__(\n          'The editor has crashed. Please try reloading the page and report the error using the button below.',\n          'web-stories'\n        )}\n      </P>\n      <P>{__('Apologies for the inconvenience.', 'web-stories')}</P>\n      <P>\n        <TextArea\n          readOnly\n          value={textAreaContent}\n          onFocus={(e) => e.target.setSelectionRange(0, textAreaContent.length)}\n        />\n      </P>\n      <Wrapper>\n        <Button\n          variant={ButtonVariant.Rectangle}\n          type={ButtonType.Quaternary}\n          size={ButtonSize.Small}\n          onClick={reload}\n        >\n          {__('Reload', 'web-stories')}\n        </Button>\n        <CopyStoryDataToClipboard />\n        <ButtonAsLink\n          variant={ButtonVariant.Rectangle}\n          type={ButtonType.Primary}\n          size={ButtonSize.Small}\n          href={reportUrl}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n        >\n          {__('Report Error', 'web-stories')}\n        </ButtonAsLink>\n      </Wrapper>\n    </Message>\n  );\n}\n\nErrorActions.propTypes = {\n  error: PropTypes.instanceOf(Error),\n  errorInfo: PropTypes.object,\n};\n\nexport default ErrorActions;\n"
  },
  {
    "path": "packages/story-editor/src/components/errorBoundary/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Component } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { trackError } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport ErrorActions from './errorActions';\n\nclass ErrorBoundary extends Component {\n  static propTypes = {\n    children: PropTypes.node.isRequired,\n  };\n\n  state = {\n    error: null,\n    errorInfo: null,\n  };\n\n  componentDidCatch(error, errorInfo) {\n    this.setState({ error, errorInfo });\n    const msg = errorInfo\n      ? `${error.message}\\n\\n${errorInfo.componentName}\\n${errorInfo.componentStack}`\n      : error.message;\n    trackError('editor_error_boundary', msg, true);\n  }\n\n  render() {\n    const { error, errorInfo } = this.state;\n    if (error) {\n      return <ErrorActions error={error} errorInfo={errorInfo} />;\n    }\n    return this.props.children;\n  }\n}\n\nconst shouldDisableErrorBoundaries =\n  typeof WEB_STORIES_DISABLE_ERROR_BOUNDARIES !== 'undefined' &&\n  WEB_STORIES_DISABLE_ERROR_BOUNDARIES === 'true';\nexport default shouldDisableErrorBoundaries\n  ? ({ children }) => children\n  : ErrorBoundary;\n"
  },
  {
    "path": "packages/story-editor/src/components/eyedropper/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useLayout } from '../../app';\nimport { ZoomSetting } from '../../constants';\nimport useEyeDropperApi from './useEyeDropperApi';\n\nexport default ({ onChange }) => {\n  const {\n    fullbleedContainer,\n    eyedropperPixelData,\n    setEyedropperCallback,\n    setIsEyedropperActive,\n    setEyedropperImg,\n    setEyedropperPixelData,\n  } = useCanvas(\n    ({\n      state: { fullbleedContainer, eyedropperPixelData },\n      actions: {\n        setEyedropperCallback,\n        setIsEyedropperActive,\n        setEyedropperImg,\n        setEyedropperPixelData,\n      },\n    }) => ({\n      fullbleedContainer,\n      setEyedropperCallback,\n      eyedropperPixelData,\n      setIsEyedropperActive,\n      setEyedropperImg,\n      setEyedropperPixelData,\n    })\n  );\n\n  const { isEyeDropperApiSupported, openEyeDropper } = useEyeDropperApi({\n    onChange,\n    handleClose: useCallback(() => {\n      setIsEyedropperActive(false);\n    }, [setIsEyedropperActive]),\n  });\n\n  const { zoomSetting, setZoomSetting } = useLayout(\n    ({ state: { zoomSetting }, actions: { setZoomSetting } }) => ({\n      zoomSetting,\n      setZoomSetting,\n    })\n  );\n\n  const initEyedropper = useCallback(\n    (resetZoom = true) =>\n      async () => {\n        if (isEyeDropperApiSupported) {\n          if (resetZoom) {\n            setIsEyedropperActive(true);\n            openEyeDropper();\n          }\n\n          // pointer event just return\n          return;\n        }\n\n        if (!resetZoom && zoomSetting !== ZoomSetting.Fit) {\n          return;\n        }\n        if (resetZoom) {\n          setIsEyedropperActive(true);\n        }\n        const prepareEyedropper = () =>\n          new Promise((resolve) => {\n            // Wait one tick for the zoom to settle in.\n            setTimeout(() => {\n              import(\n                /* webpackChunkName: \"chunk-html-to-image\" */ 'html-to-image'\n              ).then((htmlToImage) => {\n                htmlToImage\n                  .toCanvas(fullbleedContainer, {\n                    pixelRatio: 1,\n                  })\n                  .then((canvas) => {\n                    const ctx = canvas.getContext('2d');\n                    const pixelData = ctx.getImageData(\n                      0,\n                      0,\n                      canvas.width,\n                      canvas.height\n                    ).data;\n                    setEyedropperPixelData(pixelData);\n                    setEyedropperImg(canvas.toDataURL());\n                    resolve();\n                  })\n                  .catch(() => {\n                    resolve();\n                  });\n              });\n            });\n          });\n\n        if (!eyedropperPixelData || !resetZoom) {\n          if (resetZoom) {\n            setZoomSetting(ZoomSetting.Fit);\n          }\n          await prepareEyedropper();\n        }\n\n        setEyedropperCallback(() => (rgbObject) => {\n          onChange(rgbObject);\n          setIsEyedropperActive(false);\n          setEyedropperImg(null);\n          setEyedropperPixelData(null);\n        });\n      },\n    [\n      fullbleedContainer,\n      onChange,\n      eyedropperPixelData,\n      zoomSetting,\n      setIsEyedropperActive,\n      setEyedropperCallback,\n      setEyedropperImg,\n      setEyedropperPixelData,\n      setZoomSetting,\n      isEyeDropperApiSupported,\n      openEyeDropper,\n    ]\n  );\n\n  return { initEyedropper };\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/eyedropper/useEyeDropperApi.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, useCallback, useRef } from 'react';\nimport { getSolidFromHex } from '@googleforcreators/patterns';\nimport { noop } from '@googleforcreators/design-system';\nimport { rgbToColorString, parseToRgb } from 'polished';\n\nfunction useEyeDropperApi({ onChange = noop, handleClose = noop }) {\n  const isEyeDropperApiSupported =\n    typeof window !== 'undefined' && 'EyeDropper' in window;\n  const eyeDropper = useRef(null);\n\n  useEffect(() => {\n    if (isEyeDropperApiSupported && !eyeDropper.current) {\n      eyeDropper.current = new window.EyeDropper();\n    }\n  }, [isEyeDropperApiSupported]);\n\n  const openEyeDropper = useCallback(async () => {\n    if (!eyeDropper.current || !isEyeDropperApiSupported) {\n      return;\n    }\n\n    try {\n      const { sRGBHex } = await eyeDropper.current.open();\n      // Per documentation, `sRGBHex` should always be a hex color but is not.\n      const hexColor =\n        typeof sRGBHex === 'string' && sRGBHex[0] === '#'\n          ? sRGBHex\n          : rgbToColorString(parseToRgb(sRGBHex));\n      onChange(getSolidFromHex(hexColor.substring(1)).color);\n    } catch (e) {\n      //eslint-disable-next-line no-console -- Surface error for debugging.\n      console.log(e.message);\n    } finally {\n      handleClose();\n    }\n  }, [eyeDropper, isEyeDropperApiSupported, onChange, handleClose]);\n\n  return { isEyeDropperApiSupported, openEyeDropper };\n}\n\nexport default useEyeDropperApi;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ELEMENT_TYPES,\n  getDefinitionForType,\n} from '@googleforcreators/elements';\n\nexport const SELECTED_ELEMENT_TYPES = {\n  ...ELEMENT_TYPES,\n  MULTIPLE: 'multiple',\n  NONE: 'none',\n};\n\nexport const TOOLBAR_POSITIONS = {\n  ELEMENT: 'FIXED_TO_ELEMENT',\n  TOP: 'FIXED_TO_TOP',\n};\n\nexport function hasDesignMenu(type) {\n  switch (type) {\n    case SELECTED_ELEMENT_TYPES.MULTIPLE:\n      return true;\n    case SELECTED_ELEMENT_TYPES.NONE:\n      return false;\n    default:\n      return getDefinitionForType(type)?.hasDesignMenu;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/context/context.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nconst FloatingMenuContext = createContext({ state: {}, actions: {} });\n\nexport default FloatingMenuContext;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/context/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useFloatingMenu } from './use';\nexport { default as FloatingMenuProvider } from './provider';\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/context/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction FloatingMenuProvider({ handleDismiss, children }) {\n  const value = {\n    state: {},\n    actions: { handleDismiss },\n  };\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nFloatingMenuProvider.propTypes = {\n  children: PropTypes.node,\n  handleDismiss: PropTypes.func.isRequired,\n};\n\nexport default FloatingMenuProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/context/use.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useFloatingMenu(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useFloatingMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/borderRadius.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { DEFAULT_BORDER_RADIUS } from '../../panels/design/sizePosition/radius';\nimport {\n  Input,\n  Separator,\n  useProperties,\n  FocusTrapButton,\n  handleReturnTrappedFocus,\n} from './shared';\n\nconst CORNER_LABEL = __('Corner Radius', 'web-stories');\nfunction BorderRadius() {\n  const inputRef = useRef();\n  const buttonRef = useRef();\n  // Note that \"mask\" never updates on an element,\n  // so selecting it cannot cause re-renders\n  // We need it to determine if radii are supported.\n  const {\n    borderRadius = DEFAULT_BORDER_RADIUS,\n    mask,\n    type,\n  } = useProperties(['borderRadius', 'mask', 'type']);\n\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  // Only multi-border elements support border radius\n  const canHaveBorderRadius = canSupportMultiBorder({ mask });\n\n  // We only allow editing the current border radii, if all corners are identical\n  const hasUniformBorder =\n    borderRadius.topLeft === borderRadius.topRight &&\n    borderRadius.topLeft === borderRadius.bottomLeft &&\n    borderRadius.topLeft === borderRadius.bottomRight;\n\n  // Render nothing if radii not supported or not locked\n  if (!canHaveBorderRadius || (!borderRadius.locked && !hasUniformBorder)) {\n    return null;\n  }\n\n  const onChange = (value) => {\n    void trackEvent('floating_menu', {\n      name: 'set_border_radius',\n      element: type,\n    });\n\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: {\n        borderRadius: {\n          locked: true,\n          topLeft: value,\n          topRight: value,\n          bottomRight: value,\n          bottomLeft: value,\n        },\n      },\n    });\n  };\n\n  return (\n    <FocusTrapButton\n      ref={buttonRef}\n      inputRef={inputRef}\n      inputLabel={CORNER_LABEL}\n    >\n      <Input\n        tabIndex={-1}\n        ref={inputRef}\n        suffix={<Icons.Corner />}\n        value={borderRadius.topLeft}\n        aria-label={CORNER_LABEL}\n        onChange={(_, value) => onChange(value)}\n        onKeyDown={(e) => {\n          handleReturnTrappedFocus(e, buttonRef);\n        }}\n      />\n      <Separator />\n    </FocusTrapButton>\n  );\n}\n\nexport default BorderRadius;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/borderWidthAndColor.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { DEFAULT_BORDER } from '../../panels/design/border/shared';\nimport {\n  Input,\n  Color,\n  useProperties,\n  FocusTrapButton,\n  handleReturnTrappedFocus,\n} from './shared';\n\nconst Container = styled.div`\n  display: flex;\n  align-items: center;\n`;\n\nconst Dash = styled.div`\n  width: 8px;\n  height: 1px;\n  background-color: ${({ theme }) => theme.colors.border.defaultNormal};\n`;\n\nfunction getHasBorderWidth(border) {\n  if (!border) {\n    return false;\n  }\n  const { left, right, top, bottom } = border;\n  return Boolean(left || right || top || bottom);\n}\n\nconst BLACK = { color: { r: 0, g: 0, b: 0 } };\n\nconst WIDTH_LABEL = __('Border width', 'web-stories');\nconst COLOR_LABEL = __('Border color', 'web-stories');\n\nfunction BorderWidthAndColor() {\n  const inputRef = useRef();\n  const buttonRef = useRef();\n  // Note that \"mask\" never updates on an element,\n  // so selecting it cannot cause re-renders\n  // We need it to determine if border opacity is allowed.\n  const {\n    border = DEFAULT_BORDER,\n    mask,\n    type,\n  } = useProperties(['border', 'mask', 'type']);\n\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  // We only allow editing the current border width, if all borders are identical\n  const hasUniformBorder =\n    border?.left === border?.right &&\n    border?.left === border?.top &&\n    border?.left === border?.bottom;\n\n  // Border width and color inputs should only be rendered if all sides of the border are the same.\n  // Both checks are needed since not all shaped have lockedWidth eg. circles.\n  if (!border?.lockedWidth && !hasUniformBorder) {\n    return null;\n  }\n\n  // Only multi-border elements support border opacity\n  const canHaveBorderOpacity = canSupportMultiBorder({ mask });\n\n  // We only allow editing border color, if at least one border has a non-zero width\n  const hasBorderWidth = getHasBorderWidth(border);\n\n  const handleWidthChange = (value) => {\n    void trackEvent('floating_menu', {\n      name: 'set_border_width',\n      element: type,\n    });\n\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: ({ border: oldBorder }) => ({\n        border: {\n          locked: true,\n          color: border?.color,\n          ...oldBorder,\n          left: value,\n          right: value,\n          top: value,\n          bottom: value,\n        },\n      }),\n    });\n  };\n\n  const handleColorChange = (value) => {\n    void trackEvent('floating_menu', {\n      name: 'set_border_color',\n      element: type,\n    });\n\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: ({ border: oldBorder }) => ({\n        border: {\n          ...oldBorder,\n          color: value,\n        },\n      }),\n    });\n  };\n\n  return (\n    <Container>\n      <FocusTrapButton\n        ref={buttonRef}\n        inputRef={inputRef}\n        inputLabel={WIDTH_LABEL}\n      >\n        <Input\n          tabIndex={-1}\n          ref={inputRef}\n          suffix={<Icons.BorderBox />}\n          value={border?.left || 0}\n          aria-label={WIDTH_LABEL}\n          onChange={(_, value) => handleWidthChange(value)}\n          onKeyDown={(e) => {\n            handleReturnTrappedFocus(e, buttonRef);\n          }}\n        />\n      </FocusTrapButton>\n      {hasBorderWidth && (\n        <>\n          <Dash />\n          <Color\n            tabIndex={-1}\n            label={COLOR_LABEL}\n            value={border?.color || BLACK}\n            onChange={handleColorChange}\n            hasInputs={false}\n            hasEyedropper={false}\n            allowsOpacity={canHaveBorderOpacity}\n            allowsGradient={false}\n            allowsSavedColors={false}\n          />\n        </>\n      )}\n    </Container>\n  );\n}\n\nexport default BorderWidthAndColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/dismiss.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useFloatingMenu } from '../context';\nimport { IconButton, useProperties } from './shared';\n\nfunction Dismiss({ isMultiple }) {\n  const { type } = useProperties(['type']);\n  const { handleDismiss } = useFloatingMenu(\n    ({ actions: { handleDismiss } }) => ({\n      handleDismiss,\n    })\n  );\n\n  const handleClick = () => {\n    trackEvent('floating_menu', {\n      name: 'dismiss_menu',\n      element: isMultiple ? 'multiple' : type,\n    });\n    handleDismiss();\n  };\n\n  return (\n    <IconButton\n      Icon={Icons.Cross}\n      title={__('Dismiss menu', 'web-stories')}\n      onClick={handleClick}\n    />\n  );\n}\n\nexport default Dismiss;\n\nDismiss.propTypes = {\n  isMultiple: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/elementAlignment.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport useAlignment from '../../panels/design/alignment/useAlignment';\nimport { IconButton, Separator } from './shared';\n\nfunction ElementAlignment() {\n  const { selectedElements, selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElements: state.selectedElements,\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const updateElements = (callback) => {\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: callback,\n    });\n  };\n\n  const {\n    isDistributionEnabled,\n    handleAlignLeft,\n    handleAlignCenter,\n    handleAlignRight,\n    handleAlignTop,\n    handleAlignMiddle,\n    handleAlignBottom,\n    handleHorizontalDistribution,\n    handleVerticalDistribution,\n  } = useAlignment({ selectedElements, updateElements, isFloatingMenu: true });\n  return (\n    <>\n      {isDistributionEnabled && (\n        <>\n          <IconButton\n            Icon={Icons.DistributeHorizontal}\n            title={__('Distribute horizontally', 'web-stories')}\n            onClick={handleHorizontalDistribution}\n          />\n          <IconButton\n            Icon={Icons.DistributeVertical}\n            title={__('Distribute vertically', 'web-stories')}\n            onClick={handleVerticalDistribution}\n          />\n          <Separator />\n        </>\n      )}\n      <IconButton\n        Icon={Icons.AlignLeft}\n        title={__('Align left', 'web-stories')}\n        onClick={handleAlignLeft}\n      />\n      <IconButton\n        Icon={Icons.AlignCenter}\n        title={__('Align center', 'web-stories')}\n        onClick={handleAlignCenter}\n      />\n      <IconButton\n        Icon={Icons.AlignRight}\n        title={__('Align right', 'web-stories')}\n        onClick={handleAlignRight}\n      />\n      <IconButton\n        Icon={Icons.AlignTop}\n        title={__('Align top', 'web-stories')}\n        onClick={handleAlignTop}\n      />\n      <IconButton\n        Icon={Icons.AlignMiddle}\n        title={__('Align vertical center', 'web-stories')}\n        onClick={handleAlignMiddle}\n      />\n      <IconButton\n        Icon={Icons.AlignBottom}\n        title={__('Align bottom', 'web-stories')}\n        onClick={handleAlignBottom}\n      />\n    </>\n  );\n}\n\nexport default ElementAlignment;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/flipHorizontal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { IconButton } from './shared';\nimport useFlip from './shared/useFlip';\n\nfunction FlipHorizontal() {\n  const { horizontal, toggle } = useFlip('horizontal');\n  return (\n    <IconButton\n      Icon={Icons.MirrorLeftRight}\n      title={__('Flip horizontally', 'web-stories')}\n      onClick={toggle}\n      isToggled={horizontal}\n    />\n  );\n}\n\nexport default FlipHorizontal;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/flipVertical.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { IconButton } from './shared';\nimport useFlip from './shared/useFlip';\n\nfunction FlipVertical() {\n  const { vertical, toggle } = useFlip('vertical');\n  return (\n    <IconButton\n      Icon={Icons.MirrorUpDown}\n      title={__('Flip vertically', 'web-stories')}\n      onClick={toggle}\n      isToggled={vertical}\n    />\n  );\n}\n\nexport default FlipVertical;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/fontFamily.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport StoryFontPicker from '../../storyFontPicker';\n\nconst StyledFontPicker = styled(StoryFontPicker)`\n  width: 164px;\n`;\n\nconst listStyleOverrides = css`\n  max-height: 200px;\n`;\nconst containerStyleOverrides = css`\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n`;\nfunction FontFamily() {\n  const { selectedElements } = useStory(({ state }) => ({\n    selectedElements: state.selectedElements,\n  }));\n\n  return (\n    <StyledFontPicker\n      tabIndex={-1}\n      listStyleOverrides={listStyleOverrides}\n      containerStyleOverrides={containerStyleOverrides}\n      selectedElements={selectedElements}\n    />\n  );\n}\n\nexport default FontFamily;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/fontSize.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  NumericInput,\n  CONTEXT_MENU_SKIP_ELEMENT,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport getUpdatedSizeAndPosition from '../../../utils/getUpdatedSizeAndPosition';\nimport updateProperties from '../../style/updateProperties';\nimport {\n  focusStyle,\n  inputContainerStyleOverride,\n} from '../../panels/shared/styles';\nimport { MIN_MAX } from '../../panels/design/textStyle/font';\nimport { FocusTrapButton, handleReturnTrappedFocus } from './shared';\n\nconst Input = styled(NumericInput).attrs({\n  inputClassName: CONTEXT_MENU_SKIP_ELEMENT,\n})`\n  width: 50px;\n  flex: 0 0 50px;\n`;\n\nconst FONT_SIZE_LABEL = __('Font size', 'web-stories');\n\nfunction FontSize() {\n  const inputRef = useRef();\n  const buttonRef = useRef();\n  const { fontSize, selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      fontSize: state.selectedElements[0].fontSize,\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const onChange = useCallback(\n    (update) => {\n      void trackEvent('floating_menu', {\n        name: 'set_font_size',\n      });\n\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: (element) => {\n          const updates = updateProperties(element, update, true);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...element,\n            ...updates,\n          });\n          return {\n            ...updates,\n            ...sizeUpdates,\n          };\n        },\n      });\n    },\n    [selectedElementIds, updateElementsById]\n  );\n\n  return (\n    <FocusTrapButton\n      ref={buttonRef}\n      inputRef={inputRef}\n      inputLabel={FONT_SIZE_LABEL}\n    >\n      <Input\n        tabIndex={-1}\n        ref={inputRef}\n        aria-label={FONT_SIZE_LABEL}\n        isFloat\n        value={fontSize}\n        onChange={(evt, value) => onChange({ fontSize: value })}\n        min={MIN_MAX.FONT_SIZE.MIN}\n        max={MIN_MAX.FONT_SIZE.MAX}\n        placeholder={fontSize}\n        containerStyleOverride={inputContainerStyleOverride}\n        selectButtonStylesOverride={focusStyle}\n        onKeyDown={(e) => {\n          handleReturnTrappedFocus(e, buttonRef);\n        }}\n      />\n    </FocusTrapButton>\n  );\n}\n\nexport default FontSize;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as BorderWidthAndColor } from './borderWidthAndColor';\nexport { default as BorderRadius } from './borderRadius';\nexport { default as Dismiss } from './dismiss';\nexport { default as ElementAlignment } from './elementAlignment';\nexport { default as FlipHorizontal } from './flipHorizontal';\nexport { default as FlipVertical } from './flipVertical';\nexport { default as FontFamily } from './fontFamily';\nexport { default as FontSize } from './fontSize';\nexport { default as LayerOpacity } from './layerOpacity';\nexport { default as Loop } from './loop';\nexport { default as More } from './more';\nexport { default as Mute } from './mute';\nexport { default as ShapeColor } from './shapeColor';\nexport { default as Settings } from './settings';\nexport { default as TextAlign } from './textAlign';\nexport { default as TextColor } from './textColor';\nexport { default as ToggleBold } from './toggleBold';\nexport { default as ToggleItalics } from './toggleItalics';\nexport { default as ToggleUnderline } from './toggleUnderline';\nexport { default as Trim } from './trim';\nexport { Separator } from './shared';\nexport { default as Trash } from './trash';\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/border.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Design Menu: Border width & color', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    try {\n      await fixture.render();\n    } catch {\n      // ignore\n    }\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  describe('For a rectangular shape', () => {\n    beforeEach(async () => {\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await waitFor(() => fixture.editor.library.shapes);\n\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Rectangle')\n      );\n    });\n\n    it('should render color once width is non-zero', async () => {\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).toBeNull();\n\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).not.toBeNull();\n    });\n\n    it('should render border width and color if widths are unlocked but equal', async () => {\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.click(panel.lockBorderWidth);\n\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).not.toBeNull();\n    });\n\n    it('should render border width and color if widths are locked', async () => {\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.click(panel.lockBorderWidth);\n\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).not.toBeNull();\n    });\n\n    it('should not render border width or color if widths are uneven', async () => {\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.click(panel.lockBorderWidth);\n\n      await fixture.events.click(panel.width('Right'), { clickCount: 3 });\n      await fixture.events.keyboard.type('20');\n      await fixture.events.keyboard.press('tab');\n\n      expect(fixture.editor.canvas.designMenu.borderWidth).toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).toBeNull();\n    });\n\n    it('should actually set the border width and color when updated', async () => {\n      await fixture.events.click(fixture.editor.canvas.designMenu.borderWidth, {\n        clickCount: 3,\n      });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.borderColor.button\n      );\n\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.borderColor.picker.defaultColor(\n          '#800f2f'\n        )\n      );\n\n      const { border } = await getSelectedElement();\n      expect(border).toEqual(\n        jasmine.objectContaining({\n          left: 10,\n          right: 10,\n          top: 10,\n          bottom: 10,\n          color: { color: { r: 128, g: 15, b: 47 } },\n        })\n      );\n    });\n  });\n\n  describe('For a non-rectangular shape', () => {\n    beforeEach(async () => {\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await waitFor(() => fixture.editor.library.shapes);\n\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n    });\n\n    it('should render border width but only color once width is non-zero', async () => {\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).toBeNull();\n\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      expect(fixture.editor.canvas.designMenu.borderWidth).not.toBeNull();\n      expect(fixture.editor.canvas.designMenu.borderColor).not.toBeNull();\n    });\n\n    it('should not allow opacity in color picker', async () => {\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.borderColor.button\n      );\n\n      const transparentButton =\n        fixture.editor.canvas.designMenu.borderColor.picker.defaultColor(\n          'rgba(0,0,0,0)'\n        );\n\n      expect(transparentButton.hasAttribute('disabled')).toBe(true);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/borderRadius.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Design Menu: Border radius', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  it('should not render for non-shapes', async () => {\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    expect(fixture.editor.canvas.designMenu.borderRadius).toBeNull();\n  });\n\n  it('should not render for non-rectangular shapes', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n\n    expect(fixture.editor.canvas.designMenu.borderRadius).toBeNull();\n  });\n\n  it('should render for rectangular shape but only while radii are equal', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    expect(fixture.editor.canvas.designMenu.borderRadius).not.toBeNull();\n\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n\n    const panel = fixture.editor.sidebar.designPanel.sizePosition;\n    await fixture.events.click(panel.lockBorderRadius);\n\n    await fixture.events.click(panel.radius('Top left'), { clickCount: 3 });\n    await fixture.events.keyboard.type('10');\n    await fixture.events.keyboard.press('tab');\n\n    expect(fixture.editor.canvas.designMenu.borderRadius).toBeNull();\n  });\n\n  it('should display the same radius as entered in the design panel', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n\n    const panel = fixture.editor.sidebar.designPanel.sizePosition;\n    await fixture.events.click(panel.radius(), { clickCount: 3 });\n    await fixture.events.keyboard.type('10');\n    await fixture.events.keyboard.press('tab');\n\n    expect(fixture.editor.canvas.designMenu.borderRadius.value).toBe('10');\n  });\n\n  it('should update the border-radius on the selected element when typing', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    await fixture.events.click(fixture.editor.canvas.designMenu.borderRadius, {\n      clickCount: 3,\n    });\n    await fixture.events.keyboard.type('10');\n    await fixture.events.keyboard.press('tab');\n\n    const element = await getSelectedElement();\n    expect(element.borderRadius.topLeft).toBe(10);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/flip.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Design Menu: Flip toggles', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    // Add an image to stage\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  it('should render the buttons as untoggled if current selection is not flipped', async () => {\n    // Check that actual element properties have flips set to false\n    const { flip: { vertical = false, horizontal = false } = {} } =\n      await getSelectedElement();\n    expect(vertical).toBe(false);\n    expect(horizontal).toBe(false);\n\n    // Check that the design menu buttons are untoggled\n    expect(fixture.editor.canvas.designMenu.flipVertical.checked).toBe(false);\n    expect(fixture.editor.canvas.designMenu.flipHorizontal.checked).toBe(false);\n  });\n\n  it('should render the buttons as toggled if current selection is flipped both ways', async () => {\n    // Toggle the flips using the design panel\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.sizePosition.flipHorizontal\n    );\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.sizePosition.flipVertical\n    );\n\n    // Check that actual element properties have flips set to true\n    const { flip: { vertical = false, horizontal = false } = {} } =\n      await getSelectedElement();\n    expect(vertical).toBe(true);\n    expect(horizontal).toBe(true);\n\n    // Check that the design menu buttons are toggled\n    expect(fixture.editor.canvas.designMenu.flipVertical.checked).toBe(true);\n    expect(fixture.editor.canvas.designMenu.flipHorizontal.checked).toBe(true);\n  });\n\n  it('should correctly flip the element if the vertical flip button is clicked', async () => {\n    // Check that actual element property have vertical flip set to false\n    const { flip: { vertical = false } = {} } = await getSelectedElement();\n    expect(vertical).toBe(false);\n\n    // Check that the design menu button is untoggled\n    expect(fixture.editor.canvas.designMenu.flipVertical.checked).toBe(false);\n\n    // Click the toggle\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.flipVertical.node\n    );\n\n    // Check that actual element property have vertical flip set to true\n    const { flip: { vertical: verticalAfter = false } = {} } =\n      await getSelectedElement();\n    expect(verticalAfter).toBe(true);\n\n    // Check that the design menu button is toggled\n    expect(fixture.editor.canvas.designMenu.flipVertical.checked).toBe(true);\n  });\n\n  it('should correctly flip the element if the horizontal flip button is clicked', async () => {\n    // Check that actual element property have horizontal flip set to false\n    const { flip: { horizontal = false } = {} } = await getSelectedElement();\n    expect(horizontal).toBe(false);\n\n    // Check that the design menu button is untoggled\n    expect(fixture.editor.canvas.designMenu.flipHorizontal.checked).toBe(false);\n\n    // Click the toggle\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.flipHorizontal.node\n    );\n\n    // Check that actual element property have horizontal flip set to true\n    const { flip: { horizontal: horizontalAfter = false } = {} } =\n      await getSelectedElement();\n    expect(horizontalAfter).toBe(true);\n\n    // Check that the design menu button is toggled\n    expect(fixture.editor.canvas.designMenu.flipHorizontal.checked).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/loop.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Design Menu: Video loop toggle', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    try {\n      await fixture.render();\n    } catch {\n      // ignore\n    }\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    // Add a video to stage\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(5),\n      20,\n      20\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElementLoop = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0].loop || false;\n  };\n\n  it('should render the checkbox as unchecked if the video is not set to loop', async () => {\n    expect(await getSelectedElementLoop()).toBe(false);\n\n    expect(fixture.editor.canvas.designMenu.loop.checked).toBe(false);\n  });\n\n  it('should render the checkbox as checked if the video is set to loop', async () => {\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n\n    // Toggle the loop property using the design panel\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.videoOptions.loop\n    );\n\n    expect(await getSelectedElementLoop()).toBe(true);\n\n    expect(fixture.editor.canvas.designMenu.loop.checked).toBe(true);\n  });\n\n  it('should toggle the element loop flag when pressed', async () => {\n    expect(await getSelectedElementLoop()).toBe(false);\n    expect(fixture.editor.canvas.designMenu.loop.checked).toBe(false);\n\n    await fixture.events.click(fixture.editor.canvas.designMenu.loop);\n\n    expect(await getSelectedElementLoop()).toBe(true);\n    expect(fixture.editor.canvas.designMenu.loop.checked).toBe(true);\n\n    await fixture.events.click(fixture.editor.canvas.designMenu.loop);\n\n    expect(await getSelectedElementLoop()).toBe(false);\n    expect(fixture.editor.canvas.designMenu.loop.checked).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/more.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport STICKERS from '@googleforcreators/stickers';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\n\nconst stickerTestType = Object.keys(STICKERS)[0];\n\ndescribe('More button', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('media element: should focus the size and position panel when the more button is clicked', async () => {\n    // add image to canvas\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    // click more button\n    await fixture.events.click(fixture.editor.canvas.designMenu.more);\n\n    // verify that first input in size and position panel is focused\n    expect(document.activeElement).toBe(fixture.editor.sidebar.designTab);\n  });\n\n  it('text element: should focus the size and position panel when the more button is clicked', async () => {\n    // add text to canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n\n    // click more button\n    await fixture.events.click(fixture.editor.canvas.designMenu.more);\n\n    // verify that first input in size and position panel is focused\n    expect(document.activeElement).toBe(fixture.editor.sidebar.designTab);\n  });\n\n  it('shape element: should focus the size and position panel when the more button is clicked', async () => {\n    // add shape to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n\n    // click more button\n    await fixture.events.click(fixture.editor.canvas.designMenu.more);\n\n    // verify that first input in size and position panel is focused\n    expect(document.activeElement).toBe(fixture.editor.sidebar.designTab);\n  });\n\n  it('sticker element: should focus the size and position panel when the more button is clicked', async () => {\n    // add sticker to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(\n      fixture.editor.library.shapes.sticker(stickerTestType)\n    );\n\n    // click more button\n    await fixture.events.click(fixture.editor.canvas.designMenu.more);\n\n    // verify that first input in size and position panel is focused\n    expect(document.activeElement).toBe(fixture.editor.sidebar.designTab);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/opacity.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app';\nimport { Fixture } from '../../../../karma';\n\ndescribe('Design Menu: Opacity Input', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    // add image to canvas\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should update the opacity', async () => {\n    // check initial opacity\n    const initialOpacity = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1].opacity)\n    );\n\n    expect(initialOpacity).toBe(100);\n\n    // click opacity input\n    await fixture.events.click(fixture.editor.canvas.designMenu.opacity);\n\n    // update opacity\n    await fixture.events.keyboard.type('50');\n    await fixture.events.keyboard.press('tab');\n\n    // verify updated opacity\n    const finalOpacity = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1].opacity)\n    );\n\n    expect(finalOpacity).toBe(50);\n  });\n\n  it('should not update the opacity to a number greater than 100', async () => {\n    // check initial opacity\n    const initialOpacity = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1].opacity)\n    );\n\n    expect(initialOpacity).toBe(100);\n\n    // click opacity input\n    await fixture.events.click(fixture.editor.canvas.designMenu.opacity);\n\n    // update opacity\n    await fixture.events.keyboard.type('200');\n    await fixture.events.keyboard.press('tab');\n\n    // Verify the opacity didn't change\n    const finalOpacity = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1].opacity)\n    );\n\n    // With PR#13339, For value > max will be automatically updated to be in valid range.\n    // For example: Value 20 is valid but 234 will be reverted to 34 (leading number will be discarded).\n    expect(finalOpacity).toBe(0);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/shopping.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\nimport { tabToCanvasFocusContainer } from '../../karma/utils';\n\ndescribe('Shopping integration', () => {\n  let fixture;\n\n  async function focusProductSearchInput() {\n    await fixture.editor.library.shoppingTab.click();\n    await fixture.events.keyboard.press('tab');\n    const searchInput = fixture.querySelector('[aria-label=\"Product search\"]');\n    await fixture.events.focus(searchInput);\n    await fixture.events.click(searchInput);\n  }\n\n  async function insertProduct(product) {\n    await focusProductSearchInput();\n    await fixture.events.keyboard.type(product);\n    // allow some time for the debounced search to catch up\n    await fixture.events.sleep(400);\n    const productButton = fixture.querySelector(\n      `[aria-label=\"Add ${product}\"]`\n    );\n    await fixture.events.click(productButton);\n    await waitFor(() =>\n      fixture.querySelector('[aria-label=\"Design menu\"] [aria-label=\"Product\"]')\n    );\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  describe('Product floating menu', () => {\n    it('should render products menu', async () => {\n      const productTitle = 'Album';\n      await insertProduct(productTitle);\n      const selectedElement = await getSelectedElement();\n      await expect(selectedElement?.product?.productTitle).toBe(productTitle);\n    });\n\n    it('should update selected product via floating menu', async () => {\n      const productTitle = 'Beanie with Logo';\n      const newProductTitle = 'Single';\n      await insertProduct(productTitle);\n      await getSelectedElement();\n      const productSelector = fixture.querySelector(\n        '[aria-label=\"Design menu\"] [aria-label=\"Product\"]'\n      );\n      await fixture.events.mouse.clickOn(productSelector, 1, 1);\n      await fixture.events.keyboard.type(newProductTitle);\n      await fixture.events.keyboard.press('ArrowDown');\n      await fixture.events.keyboard.press('Enter');\n      const selectedElement = await getSelectedElement();\n      await expect(selectedElement?.product?.productTitle).toBe(\n        newProductTitle\n      );\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Follow-up fix in #12650\n    xit('should show floating menu when product is selected on canvas', async () => {\n      const productTitle = 'Single';\n      await insertProduct(productTitle);\n      const focusContainer = fixture.screen.getByTestId(\n        'canvas-focus-container'\n      );\n\n      // deselect the product\n      await fixture.events.click(focusContainer);\n      const canvasElement = await getSelectedElement();\n      await expect(canvasElement.isBackground).toBe(true);\n\n      // reselect the product\n      await tabToCanvasFocusContainer(focusContainer, fixture);\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('Tab');\n      const selectedElement = await getSelectedElement();\n      await expect(selectedElement?.product?.productTitle).toBe(productTitle);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/text.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\nimport { initHelpers } from '../../../../karma/richText/_utils';\n\ndescribe('Design Menu: Text Styles', () => {\n  let fixture;\n  const data = {};\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    data.fixture = fixture;\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  const setLinearGradient = async () => {\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.button\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker.custom\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker\n        .linearGradientPickerButton\n    );\n  };\n\n  const setRadialGradient = async () => {\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.button\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker.custom\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker\n        .radialGradientPickerButton\n    );\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker\n        .radialGradientPickerButton\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker.gradientStopEndButton\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker.hexInput\n    );\n    await fixture.events.keyboard.type('b05151');\n    await new Promise((r) => setTimeout(r, 100));\n  };\n\n  const addText = async () => {\n    // Enter edit-mode\n    await fixture.events.keyboard.press('Enter');\n    await fixture.screen.findByTestId('textEditor');\n\n    // Increase the font size for making sure setting selection works as expected.\n    await fixture.events.click(fixture.editor.canvas.designMenu.fontSize, {\n      clickCount: 3,\n    });\n    await fixture.events.keyboard.type('30');\n    await fixture.events.keyboard.press('tab');\n  };\n\n  const closeColorPicker = async () => {\n    const colorPicker = fixture.screen.queryByRole('dialog', {\n      name: /Color and gradient picker/,\n    });\n    const dismissPicker = within(colorPicker).queryByRole('button', {\n      name: 'Close',\n    });\n    await fixture.events.click(dismissPicker);\n  };\n\n  const setSolidColor = async () => {\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.button\n    );\n\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.fontColor.picker.defaultColor('#ff7096')\n    );\n  };\n\n  const exitEditMode = async () => {\n    // Click on background to exit edit mode.\n    await fixture.events.mouse.clickOn(\n      fixture.editor.canvas.framesLayer.frames[0].node,\n      '10%',\n      '10%'\n    );\n  };\n\n  it('should allow whole number font sizes', async () => {\n    const fontSize = fixture.editor.canvas.designMenu.fontSize;\n\n    const size = 42;\n\n    await fixture.events.focus(fontSize);\n    await fixture.events.keyboard.type(`${size}`);\n    await fixture.events.keyboard.press('tab');\n\n    const element = await getSelectedElement();\n    expect(element.fontSize).toBe(size);\n  });\n\n  it('should allow fractional font sizes', async () => {\n    const fontSize = fixture.editor.canvas.designMenu.fontSize;\n\n    const size = 15.25;\n\n    await fixture.events.focus(fontSize);\n    await fixture.events.keyboard.type(`${size}`);\n    await fixture.events.keyboard.press('tab');\n\n    const element = await getSelectedElement();\n    expect(element.fontSize).toBe(size);\n  });\n\n  describe('Text Color', () => {\n    const { setSelection } = initHelpers(data);\n    it('should allow changing text color from the design menu', async () => {\n      await setSolidColor();\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"color: #ff7096\">Fill in some text</span>'\n      );\n    });\n\n    it('should allow changing linear gradient text color from the design menu', async () => {\n      await setLinearGradient();\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">Fill in some text</span>'\n      );\n    });\n\n    it('should allow changing radial gradient text color from the design menu', async () => {\n      await setRadialGradient();\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: radial-gradient(#b05151 0%, #010101 100%); background-clip: text\">Fill in some text</span>'\n      );\n    });\n\n    it('should allow changing text color for a selection from the design menu', async () => {\n      await addText();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setSolidColor();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        'Fill <span style=\"color: #ff7096\">in</span> some text'\n      );\n\n      await fixture.snapshot('Mixed color value in the floating menu');\n    });\n\n    it('should allow changing linear gradient color for a selection from the design menu', async () => {\n      await addText();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setLinearGradient();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        'Fill <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">in</span> some text'\n      );\n    });\n\n    it('should allow changing radial gradient color for a selection from the design menu', async () => {\n      await addText();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setRadialGradient();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        'Fill <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: radial-gradient(#b05151 0%, #010101 100%); background-clip: text\">in</span> some text'\n      );\n    });\n\n    it('should allow adding solid and linear gradient color for a selection from the design menu', async () => {\n      await addText();\n\n      await setSelection(0, 4);\n      await setSolidColor();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setLinearGradient();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"color: #ff7096\">Fill</span> <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">in</span> some text'\n      );\n    });\n\n    it('should allow adding solid and radial gradient color for a selection from the design menu', async () => {\n      await addText();\n      await setSelection(0, 4);\n      await setSolidColor();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setRadialGradient();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"color: #ff7096\">Fill</span> <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: radial-gradient(#b05151 0%, #010101 100%); background-clip: text\">in</span> some text'\n      );\n    });\n\n    it('should allow adding linear and radial gradient color for a selection from the design menu', async () => {\n      await addText();\n      await setSelection(0, 4);\n      await setLinearGradient();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setRadialGradient();\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">Fill</span> <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: radial-gradient(#b05151 0%, #010101 100%); background-clip: text\">in</span> some text'\n      );\n    });\n\n    it('should allow adding solid, linear and radial gradient color for a selection from the design menu', async () => {\n      await addText();\n      await setSelection(0, 4);\n      await setLinearGradient();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n      await setRadialGradient();\n\n      await setSelection(8, 12);\n      await setSolidColor();\n\n      await closeColorPicker();\n      await exitEditMode();\n\n      const element = await getSelectedElement();\n      expect(element.content).toBe(\n        '<span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">Fill</span> <span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: radial-gradient(#b05151 0%, #010101 100%); background-clip: text\">in</span> <span style=\"color: #ff7096\">some</span> text'\n      );\n    });\n  });\n\n  describe('Text Formatting', () => {\n    const { setSelection } = initHelpers(data);\n\n    it('should allow toggling bold, italic, underline from the design menu', async () => {\n      await fixture.events.click(fixture.editor.canvas.designMenu.bold.node);\n      await fixture.events.click(fixture.editor.canvas.designMenu.italic.node);\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.underline.node\n      );\n\n      expect(fixture.editor.canvas.designMenu.bold.checked).toBeTrue();\n      expect(fixture.editor.canvas.designMenu.italic.checked).toBeTrue();\n      expect(fixture.editor.canvas.designMenu.underline.checked).toBeTrue();\n\n      const formattedText = await getSelectedElement();\n      expect(formattedText.content).toBe(\n        '<span style=\"font-weight: 700; font-style: italic; text-decoration: underline\">Fill in some text</span>'\n      );\n\n      // Uncheck all again.\n      await fixture.events.click(fixture.editor.canvas.designMenu.bold.node);\n      await fixture.events.click(fixture.editor.canvas.designMenu.italic.node);\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.underline.node\n      );\n\n      expect(fixture.editor.canvas.designMenu.bold.checked).toBeFalse();\n      expect(fixture.editor.canvas.designMenu.italic.checked).toBeFalse();\n      expect(fixture.editor.canvas.designMenu.underline.checked).toBeFalse();\n\n      const text = await getSelectedElement();\n      expect(text.content).toBe('Fill in some text');\n    });\n\n    it('should allow format a selection of a text from the design menu', async () => {\n      await addText();\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n\n      await fixture.events.click(fixture.editor.canvas.designMenu.bold.node);\n      await fixture.events.click(fixture.editor.canvas.designMenu.italic.node);\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.underline.node\n      );\n\n      expect(fixture.editor.canvas.designMenu.bold.checked).toBeTrue();\n      expect(fixture.editor.canvas.designMenu.italic.checked).toBeTrue();\n      expect(fixture.editor.canvas.designMenu.underline.checked).toBeTrue();\n\n      await exitEditMode();\n\n      const formattedText = await getSelectedElement();\n      expect(formattedText.content).toBe(\n        'Fill <span style=\"font-weight: 700; font-style: italic; text-decoration: underline\">in</span> some text'\n      );\n\n      // Verify all toggles show false now since we have mixed values inside the text.\n      expect(fixture.editor.canvas.designMenu.bold.checked).toBeFalse();\n      expect(fixture.editor.canvas.designMenu.italic.checked).toBeFalse();\n      expect(fixture.editor.canvas.designMenu.underline.checked).toBeFalse();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/karma/textAlign.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Design Menu: Text alignment', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n\n    // Open style pane\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getTextAlignForSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0].textAlign || 'left';\n  };\n\n  const alignments = [\n    {\n      value: 'left',\n      label: 'Align text left',\n      otherLabel: 'Align text center',\n    },\n    {\n      value: 'center',\n      label: 'Align text center',\n      otherLabel: 'Align text left',\n    },\n    {\n      value: 'right',\n      label: 'Align text right',\n      otherLabel: 'Align text left',\n    },\n    {\n      value: 'justify',\n      label: 'Align text justified',\n      otherLabel: 'Align text left',\n    },\n  ];\n\n  alignments.forEach(({ value, label, otherLabel }) => {\n    it(`should display the correct control when the alignment is \"${value}\"`, async () => {\n      // Select the relevant alignment in the text style panel\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.align(label)\n      );\n\n      // Check that the value on the element matches\n      expect(await getTextAlignForSelectedElement()).toBe(value);\n\n      // Check that the icon in the  matches\n      const icon = fixture.editor.canvas.designMenu.textAlignIcon(label);\n      expect(icon).toBeTruthy();\n\n      // Click the input and check the icon in the sub menu\n      await fixture.events.click(fixture.editor.canvas.designMenu.textAlign);\n      const alignOption =\n        fixture.editor.canvas.designMenu.textAlignOption(label);\n      expect(alignOption.getAttribute('aria-pressed')).toBe('true');\n    });\n\n    it(`should set the alignment to \"${value}\" when selected`, async () => {\n      // Select another alignment in the text style panel\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.align(otherLabel)\n      );\n\n      // Check that the value on the element is not a match\n      expect(await getTextAlignForSelectedElement()).not.toBe(value);\n\n      // Click the input and click the correct option in the sub menu\n      await fixture.events.click(fixture.editor.canvas.designMenu.textAlign);\n      await fixture.events.click(\n        fixture.editor.canvas.designMenu.textAlignOption(label)\n      );\n\n      // Check that the value on the element now is a match\n      expect(await getTextAlignForSelectedElement()).toBe(value);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/layerOpacity.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __, _x } from '@googleforcreators/i18n';\nimport {\n  Icons,\n  NumericInput,\n  CONTEXT_MENU_SKIP_ELEMENT,\n} from '@googleforcreators/design-system';\nimport { useRef } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { MIN_MAX } from '../../panels/design/sizePosition/opacity';\nimport {\n  FocusTrapButton,\n  handleReturnTrappedFocus,\n  useProperties,\n} from './shared';\n\nconst Input = styled(NumericInput)`\n  width: 82px;\n  flex: 0 0 82px;\n`;\n\nconst OPACITY_LABEL = __('Opacity in percent', 'web-stories');\n\nfunction LayerOpacity() {\n  const inputRef = useRef();\n  const buttonRef = useRef();\n  const { opacity, type } = useProperties(['opacity', 'type']);\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const handleOpacityChange = (_, value) => {\n    void trackEvent('floating_menu', {\n      name: 'set_opacity',\n      element: type,\n    });\n\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: () => ({\n        opacity: value ?? 100,\n      }),\n    });\n  };\n\n  return (\n    <FocusTrapButton\n      ref={buttonRef}\n      inputRef={inputRef}\n      inputLabel={OPACITY_LABEL}\n    >\n      <Input\n        ref={inputRef}\n        tabIndex={-1}\n        suffix={<Icons.ColorDrop />}\n        unit={_x('%', 'Percentage', 'web-stories')}\n        value={opacity || 0}\n        aria-label={OPACITY_LABEL}\n        onChange={handleOpacityChange}\n        inputClassName={CONTEXT_MENU_SKIP_ELEMENT}\n        onKeyDown={(e) => {\n          handleReturnTrappedFocus(e, buttonRef);\n        }}\n        min={MIN_MAX.OPACITY.MIN}\n        max={MIN_MAX.OPACITY.MAX}\n      />\n    </FocusTrapButton>\n  );\n}\n\nexport default LayerOpacity;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/loop.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport LoopPanelContent from '../../panels/shared/media/loopPanelContent';\nimport { useProperties } from './shared';\n\nconst StyledLoopContent = styled(LoopPanelContent)`\n  gap: 8px;\n`;\n\nfunction Loop() {\n  const { loop } = useProperties(['loop']);\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const handleChange = () => {\n    void trackEvent('floating_menu', {\n      name: 'set_loop',\n    });\n\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: ({ loop: oldLoop }) => ({ loop: !oldLoop }),\n    });\n  };\n\n  return (\n    <StyledLoopContent tabIndex={-1} loop={loop} onChange={handleChange} />\n  );\n}\n\nexport default Loop;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/more.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { TextButton } from './shared';\n\nfunction More() {\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n  const selectedElementType = useStory(\n    ({ state }) => state.selectedElements[0].type\n  );\n\n  const handleHighlightDesignPanel = () => {\n    setHighlights({\n      highlight: states.StylePane,\n    });\n\n    trackEvent('floating_menu', {\n      name: 'click_more_button',\n      element: selectedElementType,\n    });\n  };\n\n  return (\n    <TextButton\n      text={_x(\n        'More',\n        'Link to more options in design panel for selected element',\n        'web-stories'\n      )}\n      onClick={handleHighlightDesignPanel}\n    />\n  );\n}\n\nexport default More;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/mute.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport useVideoElementTranscoding from '../../../app/media/utils/useVideoElementTranscoding';\nimport { IconButton, useProperties } from './shared';\n\nfunction Mute() {\n  const { id: elementId, resource } = useProperties(['id', 'resource']);\n  const {\n    state: { canMute, isMuting, isDisabled },\n    actions: { handleMute },\n  } = useVideoElementTranscoding({\n    elementId,\n    resource,\n  });\n\n  if (!canMute) {\n    return null;\n  }\n\n  const title = isMuting\n    ? __('Removing audio', 'web-stories')\n    : __('Remove audio', 'web-stories');\n\n  const handleChange = (e) => {\n    trackEvent('floating_menu', {\n      name: 'set_mute',\n    });\n    handleMute(e);\n  };\n  return (\n    <IconButton\n      Icon={Icons.Muted}\n      title={title}\n      disabled={isDisabled || isMuting}\n      onClick={handleChange}\n    />\n  );\n}\n\nexport default Mute;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/settings.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n  Icons,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { TOOLBAR_POSITIONS } from '../constants';\nimport { useCanvas } from '../../../app';\nimport { states, useHighlights } from '../../../app/highlights';\nimport { IconButton } from './shared';\n\nconst MenuItem = styled(ContextMenuComponents.MenuItem)`\n  span {\n    font-size: 14px;\n    font-weight: 400;\n  }\n`;\n\nconst StyledIconButton = styled(IconButton)`\n  svg {\n    width: 24px;\n    height: 24px;\n  }\n`;\n\nconst OFFSET_X = -8;\nconst OFFSET_Y = 3;\n\nconst SubMenuContainer = styled.div`\n  position: absolute;\n  top: calc(var(--height) + ${OFFSET_Y}px);\n  z-index: 9999;\n`;\nconst LOCAL_STORAGE_KEY = LOCAL_STORAGE_PREFIX.ELEMENT_TOOLBAR_SETTINGS;\n\nfunction Settings() {\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n  const {\n    setFloatingMenuPosition,\n    setDisplayFloatingMenu,\n    floatingMenuPosition,\n  } = useCanvas(({ actions, state }) => ({\n    setFloatingMenuPosition: actions.setFloatingMenuPosition,\n    setDisplayFloatingMenu: actions.setDisplayFloatingMenu,\n    floatingMenuPosition: state.floatingMenuPosition,\n  }));\n  const setHighlights = useHighlights(({ setHighlights }) => setHighlights);\n\n  const buttonRef = useRef();\n  const subMenuRef = useRef();\n\n  const [offsetLeft, setOffsetLeft] = useState(0);\n\n  // Record left position of this button in the parent design menu\n  useEffect(\n    () => setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X),\n    []\n  );\n\n  const handleCloseMenu = () => setIsMenuOpen(false);\n\n  const local = useMemo(\n    () => localStore.getItemByKey(LOCAL_STORAGE_KEY) || {},\n    []\n  );\n  const handleToolbarPosition = (position) => {\n    setFloatingMenuPosition(position);\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, {\n      ...local,\n      position,\n    });\n    trackEvent('floating_menu', {\n      name: 'reposition_menu',\n      position,\n    });\n  };\n\n  const hideFloatingMenu = useCallback(() => {\n    setDisplayFloatingMenu(false);\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, {\n      ...local,\n      isDisplayed: false,\n    });\n    setHighlights({\n      highlight: states.ElementToolbarToggle,\n    });\n    trackEvent('floating_menu', {\n      name: 'persistent_menu_hide',\n    });\n  }, [local, setDisplayFloatingMenu, setHighlights]);\n\n  const subMenuItems = [\n    {\n      key: TOOLBAR_POSITIONS.ELEMENT,\n      label: <span>{__('Fix to element', 'web-stories')}</span>,\n      onClick: () => handleToolbarPosition(TOOLBAR_POSITIONS.ELEMENT),\n      supportsIcon: true,\n      icon:\n        !floatingMenuPosition ||\n        floatingMenuPosition === TOOLBAR_POSITIONS.ELEMENT ? (\n          <Icons.CheckmarkSmall />\n        ) : null,\n    },\n    {\n      key: TOOLBAR_POSITIONS.TOP,\n      label: <span>{__('Fix to top', 'web-stories')}</span>,\n      onClick: () => handleToolbarPosition(TOOLBAR_POSITIONS.TOP),\n      supportsIcon: true,\n      icon:\n        floatingMenuPosition === TOOLBAR_POSITIONS.TOP ? (\n          <Icons.CheckmarkSmall />\n        ) : null,\n    },\n    {\n      key: 'hide',\n      label: <span>{__('Always hide', 'web-stories')}</span>,\n      // Note: this doesn't really support icon but this way there's the same amount of padding as the other items have.\n      supportsIcon: true,\n      onClick: () => hideFloatingMenu(),\n    },\n  ];\n\n  return (\n    <>\n      <StyledIconButton\n        ref={buttonRef}\n        Icon={Icons.Settings}\n        title={__('Menu settings', 'web-stories')}\n        onClick={() => setIsMenuOpen((value) => !value)}\n        aria-haspopup=\"menu\"\n        aria-expanded={isMenuOpen}\n        // Hide tooltip if menu is open to avoid overlapping overlays\n        hasTooltip={!isMenuOpen}\n      />\n      <SubMenuContainer ref={subMenuRef} style={{ left: `${offsetLeft}px` }}>\n        <ContextMenu\n          onDismiss={handleCloseMenu}\n          isOpen={isMenuOpen}\n          onCloseSubMenu={handleCloseMenu}\n          aria-label={__('Toolbar position options', 'web-stories')}\n          isSubMenu\n          isSecondary\n          parentMenuRef={buttonRef}\n        >\n          {subMenuItems.map(({ key, ...menuItemProps }) => (\n            <MenuItem key={key} {...menuItemProps} />\n          ))}\n        </ContextMenu>\n      </SubMenuContainer>\n    </>\n  );\n}\n\nexport default Settings;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shapeColor.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { Color } from './shared';\n\nfunction ShapeColor() {\n  const { backgroundColor, selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      backgroundColor: state.selectedElements[0].backgroundColor,\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const onChange = useCallback(\n    (value) => {\n      void trackEvent('floating_menu', {\n        name: 'set_shape_color',\n        element: 'shape',\n      });\n\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: () => ({\n          backgroundColor: value,\n        }),\n      });\n    },\n    [selectedElementIds, updateElementsById]\n  );\n\n  return (\n    <Color\n      tabIndex={-1}\n      label={__('Shape color', 'web-stories')}\n      value={backgroundColor}\n      allowsSavedColors\n      onChange={onChange}\n      hasInputs\n      hasEyedropper\n      allowsOpacity\n      allowsGradient\n      opacityFocusTrap\n      colorFocusTrap\n    />\n  );\n}\n\nexport default ShapeColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/color.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Placement } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Color from '../../../form/color';\n\nconst EYEDROPPER_WIDTH = 38; // icon width + spacing\nconst WIDTH_INCLUDING_INPUTS = 184;\nconst WIDTH_EXCLUDING_INPUTS = 60;\n\nconst PICKER_MAX_HEIGHT = 362;\n\nfunction getWidth(hasInputs, hasEyedropper) {\n  return (\n    (hasInputs ? WIDTH_INCLUDING_INPUTS : WIDTH_EXCLUDING_INPUTS) +\n    (hasEyedropper ? EYEDROPPER_WIDTH : 0)\n  );\n}\n\nfunction FloatingColor(props) {\n  const { hasInputs, hasEyedropper, allowsGradient = true } = props;\n  const width = getWidth(hasInputs, hasEyedropper);\n  return (\n    <Color\n      width={width}\n      maxHeight={PICKER_MAX_HEIGHT}\n      pickerPlacement={Placement.TopStart}\n      isInDesignMenu\n      allowsGradient={allowsGradient}\n      allowsSavedColors\n      allowsSavedColorDeletion={false}\n      pickerHasEyedropper={!hasEyedropper}\n      containerLabelBase={__('Color input (floating menu)', 'web-stories')}\n      {...props}\n    />\n  );\n}\n\nFloatingColor.propTypes = {\n  hasInputs: PropTypes.bool,\n  hasEyedropper: PropTypes.bool,\n  allowsGradient: PropTypes.bool,\n};\n\nexport default FloatingColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/focusTrapButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { Button, ButtonType } from '@googleforcreators/design-system';\nimport { forwardRef } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\n\nconst _FocusTrapButton = styled(Button).attrs({ type: ButtonType.Primary })`\n  background-color: transparent;\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  outline: none;\n  margin: 0;\n  padding: 0;\n  min-width: inherit;\n\n  :hover,\n  :focus {\n    background-color: transparent;\n  }\n\n  ${({ styleOverride }) => css`\n    ${styleOverride}\n  `}\n`;\n_FocusTrapButton.propTypes = {\n  styleOverride: PropTypes.array,\n};\n\nexport const handleReturnTrappedFocus = (e, buttonRef) => {\n  // only bubble up for moving focus\n  if (e.key === 'Tab') {\n    e.preventDefault();\n    buttonRef.current.focus();\n  } else {\n    e.stopPropagation();\n  }\n};\n\n/**\n * Intended as a last resort effort to wrangle nested inputs within a <ContextMenu>. Freeform inputs should be avoided within menus if at all possible. Because this is a last resort, it is a shared element in the floating menu not the design-system.\n * When it's necessary, wrap the freeform input in the <FocusTrapButton> and pass the associated handleReturnTrappedFocus as onKeyDown of the designated input.\n * You will also need to give the input the imported CONTEXT_MENU_SKIP_ELEMENT class from design system. This tells the context menu to ignore the input in its focusableChildren so it relies on the FocusTrapButton as the focusable element for that input. This allows the freeform inputs to be typed into and arrowed around and then tab to get back into the menu.\n *\n * **Sample Usage**\n * ```js\n *\n * function SomeComponent() {\n * const buttonRef = useRef();\n * const inputRef = useRef();\n *\n * <FocusTrapButton ref={buttonRef} inputRef={inputRef} inputLabel='Font size'>\n * <input ref={inputRef} aria-label=\"Font size\" onKeyDown={(e) => handleReturnTrappedFocus(e, buttonRef)} inputClassName={CONTEXT_MENU_SKIP_ELEMENT} />\n * </FocusTrapButton>\n * }\n * ```\n *\n * @param {Object} props Props.\n * @param {Object} props.inputRef ref associated with input element\n * @param {string} props.inputLabel label of the associated input, will be used to create \"Press Enter to edit [inputLabel]\"\n * @param {Array} props.styleOverride css to override button styles. Useful when an input has a specific style that adjusts the width, like color opacity.\n * @param {Node} props.children children within wrapper\n */\n\nconst FocusTrapButton = forwardRef(function FocusTrapButton(\n  { inputRef, inputLabel, children, styleOverride },\n  ref\n) {\n  return (\n    <_FocusTrapButton\n      id={uuidv4()}\n      tabIndex={-1}\n      ref={ref}\n      onClick={(e) => {\n        e.stopPropagation();\n        inputRef.current.focus();\n      }}\n      onBlur={(e) => {\n        e.preventDefault();\n        e.stopPropagation();\n      }}\n      onKeyDown={(e) => {\n        e.preventDefault();\n\n        if (e.key === 'Enter') {\n          inputRef.current.focus();\n        }\n      }}\n      aria-label={sprintf(\n        /* translators: %s: input label that is accessible by pressing Enter */\n        __('Press Enter to edit %s', 'web-stories'),\n        inputLabel\n      )}\n      styleOverride={styleOverride}\n    >\n      {children}\n    </_FocusTrapButton>\n  );\n});\n\nexport default FocusTrapButton;\n\nFocusTrapButton.propTypes = {\n  inputRef: PropTypes.object.isRequired,\n  inputLabel: PropTypes.string.isRequired,\n  children: PropTypes.node.isRequired,\n  styleOverride: PropTypes.array,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/icon.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { memo, forwardRef } from '@googleforcreators/react';\nimport {\n  ContextMenuComponents,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../../tooltip';\nimport ToggleButton from './toggleButton';\n\nconst IconButton = memo(\n  forwardRef(function IconButton(\n    { Icon, title, hasTooltip = true, ...rest },\n    ref\n  ) {\n    return (\n      <Tooltip\n        placement={Placement.Bottom}\n        title={hasTooltip ? title : undefined}\n      >\n        <ToggleButton aria-label={title} ref={ref} tabIndex={-1} {...rest}>\n          <ContextMenuComponents.MenuIcon title={title}>\n            <Icon />\n          </ContextMenuComponents.MenuIcon>\n        </ToggleButton>\n      </Tooltip>\n    );\n  })\n);\n\nIconButton.propTypes = {\n  Icon: PropTypes.object.isRequired,\n  onClick: PropTypes.func.isRequired,\n  hasTooltip: PropTypes.bool,\n  title: PropTypes.string,\n};\n\nexport default IconButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Color } from './color';\nexport {\n  default as FocusTrapButton,\n  handleReturnTrappedFocus,\n} from './focusTrapButton';\nexport { default as IconButton } from './icon';\nexport { default as Input } from './input';\nexport { default as Separator } from './separator';\nexport { default as TextButton } from './text';\nexport { default as useProperties } from './useProperties';\nexport { default as useTextToggle } from './useTextToggle';\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/input.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  NumericInput,\n  CONTEXT_MENU_SKIP_ELEMENT,\n} from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\nconst Input = styled(NumericInput).attrs({\n  inputClassName: CONTEXT_MENU_SKIP_ELEMENT,\n})`\n  width: 70px;\n  flex: 0 0 70px;\n`;\n\nexport default Input;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/separator.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\n\nexport default ContextMenuComponents.MenuSeparator;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/text.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { memo } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { ContextMenuComponents } from '@googleforcreators/design-system';\n\nconst Button = styled(ContextMenuComponents.MenuButton)`\n  font-size: 14px;\n  padding: 0 12px;\n  font-weight: normal;\n  letter-spacing: normal;\n`;\n\nconst TextButton = memo(function TextButton({ text, ...rest }) {\n  return (\n    <Button forcePadding {...rest} tabIndex={-1}>\n      {text}\n    </Button>\n  );\n});\n\nTextButton.propTypes = {\n  text: PropTypes.string.isRequired,\n  onClick: PropTypes.func.isRequired,\n};\n\nexport default TextButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/toggleButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { forwardRef } from '@googleforcreators/react';\nimport {\n  ContextMenuComponents,\n  ButtonType,\n} from '@googleforcreators/design-system';\n\nconst ToggleButton = forwardRef(function ToggleButton(\n  { isToggled, children, ...rest },\n  ref\n) {\n  // Add extra properties to indicate this is a pushbutton, only if isToggled is a boolean\n  const toggleProps =\n    typeof isToggled === 'boolean'\n      ? {\n          type: isToggled ? ButtonType.Secondary : ButtonType.Tertiary,\n          'aria-pressed': isToggled,\n          role: 'button',\n        }\n      : {};\n\n  return (\n    <ContextMenuComponents.MenuButton ref={ref} {...toggleProps} {...rest}>\n      {children}\n    </ContextMenuComponents.MenuButton>\n  );\n});\n\nToggleButton.propTypes = {\n  isToggled: PropTypes.bool,\n  children: PropTypes.node,\n};\n\nexport default ToggleButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/useFlip.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { trackEvent } from '@googleforcreators/tracking';\nimport type { Flip } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport useProperties from './useProperties';\n\nfunction useFlip(property: keyof Flip) {\n  const { flip, type } = useProperties(['flip', 'type']);\n\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const toggle = () => {\n    void trackEvent('floating_menu', {\n      name: `set_flip_${property}`,\n      element: type as unknown as string,\n    });\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: (oldElement) => ({\n        flip: {\n          ...oldElement.flip,\n          [property]: Boolean(!oldElement.flip?.[property] || false),\n        } as Flip,\n      }),\n    });\n  };\n\n  return {\n    [property]: flip?.[property] || false,\n    toggle,\n  };\n}\n\nexport default useFlip;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/useProperties.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Element } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport objectPick from '../../../../utils/objectPick';\n\nfunction useProperties(propertyList: (keyof Element)[]) {\n  return useStory(({ state: { selectedElements } }) =>\n    objectPick(selectedElements[0], propertyList)\n  );\n}\n\nexport default useProperties;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/shared/useTextToggle.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useRichTextFormatting from '../../../panels/design/textStyle/useRichTextFormatting';\nimport updateProperties from '../../../style/updateProperties';\nimport { useStory } from '../../../../app';\nimport getUpdatedSizeAndPosition from '../../../../utils/getUpdatedSizeAndPosition';\nimport useProperties from './useProperties';\n\nfunction useTextToggle({ currentValue, handler, eventName }) {\n  const { content } = useProperties(['content']);\n\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const pushUpdate = useCallback(\n    (update) => {\n      void trackEvent('floating_menu', {\n        name: eventName,\n        element: 'text',\n      });\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: (element) => {\n          const updates = updateProperties(element, update, true);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...element,\n            ...updates,\n          });\n          return {\n            ...updates,\n            ...sizeUpdates,\n          };\n        },\n      });\n    },\n    [updateElementsById, selectedElementIds, eventName]\n  );\n  const { textInfo, handlers } = useRichTextFormatting(\n    [{ content, type: 'text' }],\n    pushUpdate\n  );\n\n  const toggle = () => {\n    const fn = handlers[handler];\n    fn(!textInfo[currentValue]);\n  };\n\n  return {\n    isToggled: textInfo[currentValue],\n    toggle,\n  };\n}\n\nexport default useTextToggle;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/test/mute.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport Mute from '../mute';\nimport mockUseVideoElementTranscoding from '../../../../app/media/utils/useVideoElementTranscoding';\n\njest.mock('../../../../app/media/utils/useVideoElementTranscoding', () =>\n  jest.fn()\n);\njest.mock('../shared/useProperties', () =>\n  jest.fn().mockImplementation(() => ({}))\n);\njest.mock('../shared/icon', () =>\n  jest.fn().mockImplementation(function MockButton({ title, Icon, ...rest }) {\n    return (\n      <button role=\"menuitem\" {...rest}>\n        {title}\n      </button>\n    );\n  })\n);\n\ndescribe('Design Menu: Mute video', () => {\n  it('should not render if mute is not possible', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canMute: false },\n      actions: {},\n    }));\n    renderWithTheme(<Mute />);\n    const mute = screen.queryByRole('menuitem', { name: 'Remove audio' });\n    expect(mute).not.toBeInTheDocument();\n  });\n\n  it('should render if mute is possible', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canMute: true },\n      actions: {},\n    }));\n    renderWithTheme(<Mute />);\n    const mute = screen.getByRole('menuitem', { name: 'Remove audio' });\n    expect(mute).toBeInTheDocument();\n  });\n\n  it('should render as disabled with alternate title if mute is ongoing', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canMute: true, isMuting: true },\n      actions: {},\n    }));\n    renderWithTheme(<Mute />);\n    const mute = screen.getByRole('menuitem', { name: 'Removing audio' });\n    expect(mute).toBeInTheDocument();\n    expect(mute).toBeDisabled();\n  });\n\n  it('should render as disabled if other transcoding is ongoing', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canMute: true, isDisabled: true },\n      actions: {},\n    }));\n    renderWithTheme(<Mute />);\n    const mute = screen.getByRole('menuitem', { name: 'Remove audio' });\n    expect(mute).toBeInTheDocument();\n    expect(mute).toBeDisabled();\n  });\n\n  it('should invoke mute function when clicked', () => {\n    const handleMute = jest.fn();\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canMute: true },\n      actions: { handleMute },\n    }));\n    renderWithTheme(<Mute />);\n    const mute = screen.getByRole('menuitem', { name: 'Remove audio' });\n    fireEvent.click(mute);\n    expect(handleMute).toHaveBeenCalledWith(\n      expect.objectContaining({ type: 'click' })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/test/trim.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport Trim from '../trim';\nimport mockUseVideoElementTranscoding from '../../../../app/media/utils/useVideoElementTranscoding';\n\njest.mock('../../../../app/media/utils/useVideoElementTranscoding', () =>\n  jest.fn()\n);\njest.mock('../shared/useProperties', () =>\n  jest.fn().mockImplementation(() => ({}))\n);\njest.mock('../shared/icon', () =>\n  jest.fn().mockImplementation(function MockButton({ title, Icon, ...rest }) {\n    return (\n      <button role=\"menuitem\" {...rest}>\n        {title}\n      </button>\n    );\n  })\n);\n\ndescribe('Design Menu: Trim video', () => {\n  it('should not render if trim is not possible', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canTrim: false },\n      actions: {},\n    }));\n    renderWithTheme(<Trim />);\n    const trim = screen.queryByRole('menuitem', { name: 'Trim video' });\n    expect(trim).not.toBeInTheDocument();\n  });\n\n  it('should render if trim is possible', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canTrim: true },\n      actions: {},\n    }));\n    renderWithTheme(<Trim />);\n    const trim = screen.getByRole('menuitem', { name: 'Trim video' });\n    expect(trim).toBeInTheDocument();\n  });\n\n  it('should render as disabled with alternate title if trim is ongoing', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canTrim: true, isTrimming: true },\n      actions: {},\n    }));\n    renderWithTheme(<Trim />);\n    const trim = screen.getByRole('menuitem', { name: 'Trimming video' });\n    expect(trim).toBeInTheDocument();\n    expect(trim).toBeDisabled();\n  });\n\n  it('should render as disabled if other transcoding is ongoing', () => {\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canTrim: true, isDisabled: true },\n      actions: {},\n    }));\n    renderWithTheme(<Trim />);\n    const trim = screen.getByRole('menuitem', { name: 'Trim video' });\n    expect(trim).toBeInTheDocument();\n    expect(trim).toBeDisabled();\n  });\n\n  it('should invoke trim function when clicked', () => {\n    const handleTrim = jest.fn();\n    mockUseVideoElementTranscoding.mockImplementationOnce(() => ({\n      state: { canTrim: true },\n      actions: { handleTrim },\n    }));\n    renderWithTheme(<Trim />);\n    const trim = screen.getByRole('menuitem', { name: 'Trim video' });\n    fireEvent.click(trim);\n    expect(handleTrim).toHaveBeenCalledWith(\n      expect.objectContaining({ type: 'click' })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/textAlign.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useRef, useEffect } from '@googleforcreators/react';\nimport {\n  Icons,\n  ContextMenu,\n  ContextMenuComponents,\n  Disclosure,\n  Placement,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport Tooltip from '../../tooltip';\nimport { IconButton, useProperties } from './shared';\n\nconst OFFSET_X = -8;\nconst OFFSET_Y = 3;\n\nconst SubMenuContainer = styled.div`\n  position: absolute;\n  top: calc(var(--height) + ${OFFSET_Y}px);\n  z-index: 9999;\n`;\n\nconst StyledMenuButton = styled(ContextMenuComponents.MenuButton)`\n  flex: 0 0 60px;\n  height: 36px;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  padding: 2px 0;\n  border-radius: 4px;\n`;\n\nconst StyledMenuIcon = styled(ContextMenuComponents.MenuIcon)`\n  width: auto;\n  display: flex;\n  overflow: hidden;\n\n  svg {\n    width: 32px;\n  }\n\n  svg:last-child {\n    margin-left: -8px;\n  }\n`;\n\nconst ALIGNMENTS = [\n  {\n    value: 'left',\n    icon: Icons.AlignTextLeft,\n    label: __('Align text left', 'web-stories'),\n  },\n  {\n    value: 'center',\n    icon: Icons.AlignTextCenter,\n    label: __('Align text center', 'web-stories'),\n  },\n  {\n    value: 'right',\n    icon: Icons.AlignTextRight,\n    label: __('Align text right', 'web-stories'),\n  },\n  {\n    value: 'justify',\n    icon: Icons.AlignTextJustified,\n    label: __('Align text justified', 'web-stories'),\n  },\n];\n\nfunction TextAlign() {\n  const { textAlign = 'left' } = useProperties(['textAlign']);\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const [isMenuOpen, setMenuOpen] = useState(false);\n  const subMenuRef = useRef();\n  const buttonRef = useRef();\n  const [offsetLeft, setOffsetLeft] = useState(0);\n\n  // Record left position of this button in the parent design menu\n  useEffect(() => {\n    if (buttonRef.current) {\n      setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X);\n    } else {\n      setOffsetLeft(OFFSET_X);\n    }\n  }, []);\n\n  // When menu has just opened, focus the current button in submenu\n  const currentIconMounted = (node) => {\n    if (node) {\n      /* eslint-disable-next-line @wordpress/react-no-unsafe-timeout\n         --------\n         We have to wait a frame for the parent to have rendered\n      */\n      setTimeout(() => node.focus());\n    }\n  };\n\n  const { icon: CurrentIcon, label: currentLabel } =\n    ALIGNMENTS.find(({ value }) => value === textAlign) || ALIGNMENTS[0];\n\n  const handleTextAlign = (value) => () => {\n    trackEvent('floating_menu', {\n      name: `set_text_alignment_${value}`,\n      element: 'text',\n    });\n    updateElementsById({\n      elementIds: selectedElementIds,\n      properties: { textAlign: value },\n    });\n  };\n\n  const handleCloseMenu = () => {\n    setMenuOpen(false);\n    buttonRef.current.focus();\n  };\n\n  // Only display tooltip while menu is not open, but always apply as label for a11y\n  const buttonLabel = __('Change text alignment', 'web-stories');\n  const tooltip = isMenuOpen ? '' : buttonLabel;\n\n  useKeyDownEffect(buttonRef, 'down', () => setMenuOpen(true), []);\n\n  return (\n    <>\n      <Tooltip placement={Placement.Bottom} title={tooltip}>\n        <StyledMenuButton\n          tabIndex={-1}\n          ref={buttonRef}\n          onClick={() => setMenuOpen((value) => !value)}\n          aria-haspopup=\"menu\"\n          aria-expanded={isMenuOpen}\n          aria-label={buttonLabel}\n        >\n          <StyledMenuIcon title={tooltip}>\n            <CurrentIcon role=\"img\" aria-label={currentLabel} />\n            <Disclosure\n              style={{ marginLeft: -8, marginRight: 0 }}\n              $isOpen={isMenuOpen}\n            />\n          </StyledMenuIcon>\n        </StyledMenuButton>\n      </Tooltip>\n      <SubMenuContainer ref={subMenuRef} style={{ left: `${offsetLeft}px` }}>\n        <ContextMenu\n          onDismiss={handleCloseMenu}\n          isOpen={isMenuOpen}\n          onCloseSubMenu={handleCloseMenu}\n          aria-label={__('Text alignment options', 'web-stories')}\n          isSubMenu\n          isSecondary\n          parentMenuRef={buttonRef}\n          isHorizontal\n        >\n          {ALIGNMENTS.map(({ value, icon, label }) => (\n            <IconButton\n              isToggled={value === textAlign}\n              ref={value === textAlign ? currentIconMounted : null}\n              key={value}\n              Icon={icon}\n              title={label}\n              onClick={handleTextAlign(value)}\n            />\n          ))}\n        </ContextMenu>\n      </SubMenuContainer>\n    </>\n  );\n}\n\nexport default TextAlign;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/textColor.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  hasGradient,\n  createSolid,\n  DEFAULT_GRADIENT,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport useRichTextFormatting from '../../panels/design/textStyle/useRichTextFormatting';\nimport updateProperties from '../../style/updateProperties';\nimport { useStory } from '../../../app';\nimport { MULTIPLE_VALUE } from '../../../constants';\nimport { Color, useProperties } from './shared';\n\nfunction TextColor() {\n  const { content } = useProperties(['content']);\n  const { selectedElementIds, updateElementsById } = useStory(\n    ({ state, actions }) => ({\n      selectedElementIds: state.selectedElementIds,\n      updateElementsById: actions.updateElementsById,\n    })\n  );\n\n  const pushUpdate = useCallback(\n    (update) => {\n      trackEvent('floating_menu', {\n        name: 'set_text_color',\n        element: 'text',\n      });\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: (element) => updateProperties(element, update, true),\n      });\n    },\n    [updateElementsById, selectedElementIds]\n  );\n\n  const onColorChange = (color) => {\n    if (hasGradient(color)) {\n      handleSetColor(createSolid(0, 0, 0));\n      handleSetGradientColor(color);\n    } else {\n      handleSetGradientColor(DEFAULT_GRADIENT);\n      handleSetColor(color);\n    }\n  };\n\n  const {\n    textInfo: { color, gradientColor },\n    handlers: { handleSetColor, handleSetGradientColor },\n  } = useRichTextFormatting([{ content, type: 'text' }], pushUpdate);\n\n  const colorInputValue =\n    gradientColor === MULTIPLE_VALUE\n      ? MULTIPLE_VALUE\n      : hasGradient(gradientColor)\n        ? gradientColor\n        : color;\n\n  return (\n    <Color\n      tabIndex={-1}\n      label={__('Text color', 'web-stories')}\n      allowsSavedColors\n      value={colorInputValue}\n      onChange={onColorChange}\n      hasInputs={false}\n      hasEyedropper\n      allowsOpacity\n      allowsGradient\n    />\n  );\n}\n\nexport default TextColor;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/toggleBold.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { IconButton, useTextToggle } from './shared';\n\nfunction ToggleBold() {\n  const { isToggled, toggle } = useTextToggle({\n    currentValue: 'isBold',\n    handler: 'handleClickBold',\n    eventName: 'set_bold',\n  });\n\n  return (\n    <IconButton\n      isToggled={isToggled}\n      Icon={Icons.LetterBBold}\n      title={__('Toggle bold', 'web-stories')}\n      onClick={toggle}\n      tabIndex={-1}\n    />\n  );\n}\n\nexport default ToggleBold;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/toggleItalics.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { IconButton, useTextToggle } from './shared';\n\nfunction ToggleItalics() {\n  const { isToggled, toggle } = useTextToggle({\n    currentValue: 'isItalic',\n    handler: 'handleClickItalic',\n    eventName: 'set_italic',\n  });\n\n  return (\n    <IconButton\n      isToggled={isToggled}\n      Icon={Icons.LetterIItalic}\n      title={__('Toggle italic', 'web-stories')}\n      onClick={toggle}\n      tabIndex={-1}\n    />\n  );\n}\n\nexport default ToggleItalics;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/toggleUnderline.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { IconButton, useTextToggle } from './shared';\n\nfunction ToggleUnderline() {\n  const { isToggled, toggle } = useTextToggle({\n    currentValue: 'isUnderline',\n    handler: 'handleClickUnderline',\n    eventName: 'set_underline',\n  });\n\n  return (\n    <IconButton\n      isToggled={isToggled}\n      Icon={Icons.LetterUUnderline}\n      title={__('Toggle underline', 'web-stories')}\n      onClick={toggle}\n      tabIndex={-1}\n    />\n  );\n}\n\nexport default ToggleUnderline;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/trash.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { IconButton } from './shared';\n\nfunction Trash({ title, handleRemove }) {\n  return <IconButton Icon={Icons.Trash} title={title} onClick={handleRemove} />;\n}\n\nexport default Trash;\nTrash.propTypes = {\n  title: PropTypes.string,\n  handleRemove: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/elements/trim.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport useVideoElementTranscoding from '../../../app/media/utils/useVideoElementTranscoding';\nimport { IconButton, useProperties } from './shared';\n\nfunction Trim() {\n  const { id: elementId, resource } = useProperties(['id', 'resource']);\n  const {\n    state: { canTrim, isTrimming, isDisabled },\n    actions: { handleTrim },\n  } = useVideoElementTranscoding({\n    elementId,\n    resource,\n  });\n\n  if (!canTrim) {\n    return null;\n  }\n\n  const title = isTrimming\n    ? __('Trimming video', 'web-stories')\n    : __('Trim video', 'web-stories');\n\n  const handleClick = (e) => {\n    trackEvent('floating_menu', {\n      name: 'set_trim',\n    });\n    handleTrim(e);\n  };\n  return (\n    <IconButton\n      Icon={Icons.Scissors}\n      title={title}\n      disabled={isDisabled || isTrimming}\n      onClick={handleClick}\n    />\n  );\n}\n\nexport default Trim;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as FloatingMenuLayer } from './layer';\nexport { default as FloatingMenu } from './menu';\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/floatingMenu.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport { Fixture } from '../../../karma';\nimport { focusFloatingMenu, tabToCanvasFocusContainer } from './utils';\n\ndescribe('Design Menu: Keyboard Navigation', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function addElementsToCanvas() {\n    /**\n     * Element order:\n     * 0: backgroundAudio\n     * 1: image\n     * 2: text\n     * 3: shape\n     */\n    // add an image to the canvas first since that element is open in side panel by default\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n    // next let's add a text element\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n\n    // add now let's add a shape to the canvas - this is the floating menu that will be visible.\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n  }\n\n  it('should never pass focus to floating menu when using keyboard from outside of canvas', async () => {\n    // add a shape to the canvas so that a floating menu is visible\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    // Now let's focus the footer and tab a few times. We should never run into the floating menu or its focusable content.\n\n    const { checklistToggle } = fixture.editor.footer;\n\n    await fixture.events.click(checklistToggle);\n    await fixture.events.sleep(300); // allow transition to play out\n    // close the checklist again, we're using it as a focus anchor\n    await fixture.events.click(checklistToggle);\n    // Floating menus are after the footer popups in the tab order, so if it was going to be selected it would happen after the footer content.\n    let count = 0;\n    while (count < 15) {\n      // eslint-disable-next-line no-await-in-loop -- need to await key press\n      await fixture.events.keyboard.press('tab');\n\n      expect(fixture.editor.canvas.designMenu).not.toContain(\n        document.activeElement\n      );\n\n      count++;\n    }\n  });\n\n  it('should return focus to element & maintain selection on esc when only keyboard is used', async () => {\n    const focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n\n    await addElementsToCanvas();\n\n    // let's make sure it's the shape menu we're interacting with, which is the 3rd element\n    await tabToCanvasFocusContainer(focusContainer, fixture);\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n    await fixture.events.keyboard.press('Tab');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    // Eyedropper is first to focus in the menu\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Pick a color from canvas'\n    );\n\n    // arrow right once to the shape color input\n    await fixture.events.keyboard.press('ArrowRight');\n    // arrow right again to color picker\n    await fixture.events.keyboard.press('ArrowRight');\n\n    // arrow right again to opacity\n    await fixture.events.keyboard.press('ArrowRight');\n    // arrow right to border radius\n    await fixture.events.keyboard.press('ArrowRight');\n    // arrow right again to flip\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n\n    // now go back to the element to move it around\n    await fixture.events.keyboard.press('esc');\n\n    let selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('shape');\n    expect(selectedElements[0].x).toBe(48);\n\n    // scoot the element to the right\n    await fixture.events.keyboard.press('ArrowRight');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].x).toBe(58);\n\n    // now let's make sure that the canvas is still the active focus group\n    // and we can tab through layers without exiting the canvas ever.\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].isBackground).toBe(true);\n\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].type).toBe('image');\n  });\n\n  it('should return focus to element & maintain selection on esc when mix of cursor and keyboard are used', async () => {\n    await addElementsToCanvas();\n\n    // click on a flip so we know that the floating menu is focused via cursor\n    await fixture.events.click(\n      fixture.editor.canvas.designMenu.flipHorizontal.node\n    );\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n\n    // now escape the floating menu via keyboard\n    await fixture.events.keyboard.press('esc');\n\n    let selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements.length).toBe(1);\n    expect(selectedElements[0].type).toBe('shape');\n    expect(selectedElements[0].x).toBe(48);\n\n    // scoot the element to the right\n    await fixture.events.keyboard.press('ArrowRight');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].x).toBe(58);\n\n    // now let's make sure that the canvas is still the active focus group\n    // and we can tab through layers without exiting the canvas ever.\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].isBackground).toBe(true);\n\n    await fixture.events.keyboard.press('Tab');\n\n    selectedElements = await fixture.renderHook(() =>\n      useStory(({ state }) => state.selectedElements)\n    );\n    expect(selectedElements[0].type).toBe('image');\n  });\n\n  it('should allow hiding and displaying menu', async () => {\n    // Add a shape to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    const settingsButton = fixture.screen.getByRole('menuitem', {\n      name: 'Menu settings',\n    });\n    await fixture.events.click(settingsButton);\n\n    await fixture.events.click(\n      fixture.screen.getByRole('menuitem', { name: 'Always hide' })\n    );\n\n    const showMenuButton = fixture.screen.getByRole('button', {\n      name: 'Show element toolbar',\n    });\n    expect(showMenuButton).toBeTruthy();\n\n    // Menu is not visible anymore.\n    expect(() =>\n      fixture.screen.getByRole('menuitem', {\n        name: 'Menu settings',\n      })\n    ).toThrow();\n\n    // Click the display button.\n    await fixture.events.click(showMenuButton);\n\n    // Menu is visible again.\n    expect(\n      fixture.screen.getByRole('menuitem', {\n        name: 'Menu settings',\n      })\n    ).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/image.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { focusFloatingMenu, tabToCanvasFocusContainer } from './utils';\n\ndescribe('Image Design Menu: Keyboard Navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should navigate into and out of floating menu by keyboard', async () => {\n    const elementUpdates = {\n      opacity: {\n        keyboard: '60',\n        result: 60,\n      },\n      borderWidth: {\n        keyboard: '6',\n        result: 6,\n      },\n    };\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    await tabToCanvasFocusContainer(focusContainer, fixture);\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    await fixture.events.keyboard.press('Enter');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Opacity in percent'\n    );\n    await fixture.events.keyboard.type(elementUpdates.opacity.keyboard);\n\n    // Tab out of input back to menu navigation\n    await fixture.events.keyboard.press('tab');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip vertically'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Border width'\n    );\n    // Give border a width\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.borderWidth.keyboard);\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Give border a color\n    // Expand color popup\n    await fixture.events.keyboard.press('Enter');\n    // Tab from dismiss to color picker\n    await fixture.events.keyboard.press('tab');\n    // Tab from color picker into swatches\n    await fixture.events.keyboard.press('tab');\n    // Navigate down one row and to the right once\n    await fixture.events.keyboard.press('ArrowDown');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Pick this swatch\n    await fixture.events.keyboard.press('Enter');\n    // Back to the color input now\n    await fixture.events.keyboard.press('Esc');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Arrow right to more button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement).toHaveTextContent('More');\n\n    // Arrow right to Menu settings\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Menu settings'\n    );\n\n    // Arrow right to Dismiss menu button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Dismiss menu'\n    );\n\n    // Arrow right again and end up back on the opacity\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    // Check that element actually updated\n    const selectedElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n    expect(selectedElement.opacity).toBe(elementUpdates.opacity.result);\n    expect(selectedElement.flip.vertical).toBe(true);\n    expect(selectedElement.border.left).toBe(elementUpdates.borderWidth.result);\n    // we just want to know that the keyboard nav picked a non default color value;\n    expect(selectedElement.border.color.color).not.toBe({ r: 0, g: 0, b: 0 });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/shape.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { focusFloatingMenu, tabToCanvasFocusContainer } from './utils';\n\ndescribe('Shape Design Menu: Keyboard Navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should navigate into and out of floating menu by keyboard', async () => {\n    const elementUpdates = {\n      backgroundColor: {\n        keyboard: '787800',\n        result: {\n          r: 120,\n          g: 120,\n          b: 0,\n        },\n      },\n      backgroundOpacity: {\n        keyboard: '60',\n        result: { a: 0.6 },\n      },\n      borderRadius: {\n        keyboard: '4',\n        result: 4,\n      },\n      borderWidth: {\n        keyboard: '6',\n        result: 6,\n      },\n    };\n\n    // Add a shape to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await waitFor(() => fixture.editor.library.shapes);\n\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    await tabToCanvasFocusContainer(focusContainer, fixture);\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    // Eyedropper is first to focus in the menu\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Pick a color from canvas'\n    );\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Shape color'\n    );\n    // Press enter and update color hex\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.backgroundColor.keyboard);\n    await fixture.events.keyboard.press('Tab');\n    // The square is green now, let's just make sure the color picker is navigable and then carry on.\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Shape color'\n    );\n    await fixture.events.keyboard.press('Enter');\n    // Tab from dismiss to color picker\n    await fixture.events.keyboard.press('tab');\n    // Tab from color picker into swatches\n    await fixture.events.keyboard.press('tab');\n    // Navigate down one row and to the right once\n    await fixture.events.keyboard.press('ArrowDown');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Back to the color input now\n    await fixture.events.keyboard.press('Esc');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Shape color'\n    );\n    await fixture.events.keyboard.press('ArrowRight');\n\n    // Tab to opacity\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity'\n    );\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(\n      elementUpdates.backgroundOpacity.keyboard\n    );\n\n    // Tab out of focus trap and resume traversing menu\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Corner Radius'\n    );\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.borderRadius.keyboard);\n    await fixture.events.keyboard.press('tab');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip vertically'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Border width'\n    );\n    // Give border a width\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.borderWidth.keyboard);\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Give border a color\n    // Expand color popup\n    await fixture.events.keyboard.press('Enter');\n    // Tab from dismiss to color picker\n    await fixture.events.keyboard.press('tab');\n    // Tab from color picker into swatches\n    await fixture.events.keyboard.press('tab');\n    // Navigate down one row and to the right once\n    await fixture.events.keyboard.press('ArrowDown');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Pick this swatch\n    await fixture.events.keyboard.press('Enter');\n    // Back to the color input now\n    await fixture.events.keyboard.press('Esc');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Arrow right to more button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement).toHaveTextContent('More');\n\n    // Arrow right to Menu settings\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Menu settings'\n    );\n\n    // Arrow right to Dismiss menu button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Dismiss menu'\n    );\n\n    // Arrow right twice and end up back on the color input\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Pick a color from canvas'\n    );\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Shape color'\n    );\n\n    // Check that element actually updated\n    const selectedElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n\n    expect(selectedElement.backgroundColor.color).toEqual({\n      ...elementUpdates.backgroundColor.result,\n      ...elementUpdates.backgroundOpacity.result,\n    });\n    expect(selectedElement.flip.vertical).toBe(true);\n    expect(selectedElement.borderRadius.topLeft).toBe(\n      elementUpdates.borderRadius.result\n    );\n    expect(selectedElement.border.left).toBe(elementUpdates.borderWidth.result);\n    // we just want to know that the keyboard nav picked a non default color value;\n    expect(selectedElement.border.color.color).not.toBe({ r: 0, g: 0, b: 0 });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/sticker.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport STICKERS from '@googleforcreators/stickers';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { focusFloatingMenu, tabToCanvasFocusContainer } from './utils';\n\nconst stickerTestType = Object.keys(STICKERS)[0];\n\ndescribe('Sticker Design Menu: Keyboard Navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should navigate into and out of floating menu by keyboard', async () => {\n    const elementUpdates = {\n      opacity: {\n        keyboard: '60',\n        result: 60,\n      },\n    };\n\n    // add sticker to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(\n      fixture.editor.library.shapes.sticker(stickerTestType)\n    );\n\n    await tabToCanvasFocusContainer(focusContainer, fixture);\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    await fixture.events.keyboard.press('Enter');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Opacity in percent'\n    );\n    await fixture.events.keyboard.type(elementUpdates.opacity.keyboard);\n\n    // Tab out of input back to menu navigation\n    await fixture.events.keyboard.press('tab');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip vertically'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement).toHaveTextContent('More');\n\n    // Arrow right to Menu settings\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Menu settings'\n    );\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Dismiss menu'\n    );\n\n    // Arrow right again and end up back on the opacity\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    // Check that element actually updated\n    const selectedElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n    expect(selectedElement.opacity).toBe(elementUpdates.opacity.result);\n    expect(selectedElement.flip.vertical).toBe(true);\n    expect(selectedElement.flip.horizontal).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/text.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { focusFloatingMenu, tabToCanvasFocusContainer } from './utils';\n\ndescribe('Text Design Menu: Keyboard Navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n\n    focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should navigate into and out of floating menu by keyboard', async () => {\n    const elementUpdates = {\n      fontSize: {\n        keyboard: '30',\n        result: 30,\n      },\n      textAlign: {\n        result: 'center',\n      },\n    };\n\n    // Add text to the canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n\n    await tabToCanvasFocusContainer(focusContainer, fixture);\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Font family'\n    );\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Font size'\n    );\n\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.fontSize.keyboard);\n    await fixture.events.keyboard.press('Tab');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Change text alignment'\n    );\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Update alignment to be centered\n    await fixture.events.keyboard.press('Enter');\n    // return focus to the dropdown group\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Change text alignment'\n    );\n    // Proceed to text style toggles\n    await fixture.events.keyboard.press('ArrowRight');\n    // Make it bold\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Toggle bold'\n    );\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Make it italic\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Toggle italic'\n    );\n    await fixture.events.keyboard.press('Space');\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Toggle underline'\n    );\n    // Proceed to color\n    await fixture.events.keyboard.press('ArrowRight');\n    // eyedropper\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Pick a color from canvas'\n    );\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Text color'\n    );\n    await fixture.events.keyboard.press('Enter');\n    // Tab from dismiss to color picker\n    await fixture.events.keyboard.press('tab');\n    // Tab from color picker into swatches, go past saved colors\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('tab');\n    // Navigate down one row and to the right once\n    await fixture.events.keyboard.press('ArrowDown');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Select this color\n    await fixture.events.keyboard.press('Enter');\n    // Back to the color input now\n    await fixture.events.keyboard.press('Esc');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Text color'\n    );\n\n    // Proceed to more\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement).toHaveTextContent('More');\n\n    // Arrow right to Menu settings\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Menu settings'\n    );\n\n    // Arrow right to Dismiss menu button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Dismiss menu'\n    );\n\n    // Arrow right again and end up back on the font family\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Font family'\n    );\n\n    // Check that element actually updated\n    const selectedElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n    expect(selectedElement.fontSize).toBe(elementUpdates.fontSize.result);\n    expect(selectedElement.textAlign).toBe(elementUpdates.textAlign.result);\n    // bold and italic are inline with content\n    expect(selectedElement.content).toContain('font-weight: 700');\n    expect(selectedElement.content).toContain('font-style: italic');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/utils.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport async function tabToCanvasFocusContainer(focusContainer, fixture) {\n  // start focused on media pane searchbar\n  await fixture.editor.library.mediaTab.click();\n  await fixture.events.focus(fixture.editor.library.media.searchBar);\n\n  // tab until focus reaches the canvas container\n  let count = 0;\n  while (count < 25) {\n    // eslint-disable-next-line no-await-in-loop -- need to await key press\n    await fixture.events.keyboard.press('tab');\n\n    if (document.activeElement === focusContainer) {\n      break;\n    }\n\n    count++;\n  }\n\n  if (count >= 25) {\n    throw new Error('Could not find focus container.');\n  }\n}\n\nexport async function focusFloatingMenu(fixture) {\n  await fixture.events.keyboard.shortcut('control+alt+p');\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/karma/video.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\nimport { focusFloatingMenu } from './utils';\n\ndescribe('Video Design Menu: Keyboard Navigation', () => {\n  let fixture;\n  let focusContainer;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n    await waitFor(() => {\n      focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n      if (!focusContainer) {\n        throw new Error('Canvas container not ready');\n      }\n    });\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n  xit('should navigate into and out of floating menu by keyboard', async () => {\n    const elementUpdates = {\n      opacity: {\n        keyboard: '60',\n        result: 60,\n      },\n      borderWidth: {\n        keyboard: '6',\n        result: 6,\n      },\n    };\n    // Add a video to canvas\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(5),\n      20,\n      20\n    );\n\n    // Escape out of the canvas elements focus trap\n    await fixture.events.keyboard.press('esc');\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.press('Tab');\n\n    await focusFloatingMenu(fixture);\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    await fixture.events.keyboard.press('Enter');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Opacity in percent'\n    );\n    await fixture.events.keyboard.type(elementUpdates.opacity.keyboard);\n\n    // Tab out of input back to menu navigation\n    await fixture.events.keyboard.press('tab');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    // Proceed to flips\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip horizontally'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Flip vertically'\n    );\n    await fixture.events.keyboard.press('Space');\n\n    await fixture.events.keyboard.press('ArrowRight');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Border width'\n    );\n    // Give border a width\n    await fixture.events.keyboard.press('Enter');\n    await fixture.events.keyboard.type(elementUpdates.borderWidth.keyboard);\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Give border a color\n    // Expand color popup\n    await fixture.events.keyboard.press('Enter');\n    // Tab from dismiss to color picker\n    await fixture.events.keyboard.press('tab');\n    // Tab from color picker into swatches\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('tab');\n    // Navigate down one row and to the right once\n    await fixture.events.keyboard.press('ArrowDown');\n    await fixture.events.keyboard.press('ArrowRight');\n    // Pick this swatch\n    await fixture.events.keyboard.press('Enter');\n    // Back to the color input now\n    await fixture.events.keyboard.press('Esc');\n\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Border color'\n    );\n    // Arrow right to loop\n    await fixture.events.keyboard.press('ArrowRight');\n\n    // checkbox focuses, it gets labelled by its label but that's not getting picked up on in the active element.\n    expect(document.activeElement.getAttribute('type')).toBe('checkbox');\n    // Loop the video\n    await fixture.events.keyboard.press('Space');\n\n    // Arrow right to more button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement).toHaveTextContent('More');\n\n    // Arrow right to Menu settings\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Menu settings'\n    );\n\n    // Arrow right to Dismiss menu button\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Dismiss menu'\n    );\n    // Arrow right again and end up back on the opacity\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.getAttribute('aria-label')).toBe(\n      'Press Enter to edit Opacity in percent'\n    );\n\n    // Check that element actually updated\n    const selectedElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n\n    expect(selectedElement.opacity).toBe(elementUpdates.opacity.result);\n    expect(selectedElement.flip.horizontal).toBe(true);\n    expect(selectedElement.loop).toBe(true);\n    expect(selectedElement.border.left).toBe(elementUpdates.borderWidth.result);\n    // we just want to know that the keyboard nav picked a non default color value;\n    expect(selectedElement.border.color.color).not.toBe({ r: 0, g: 0, b: 0 });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/layer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useRef,\n  useState,\n  useCallback,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useLayout, useStory, useTransform } from '../../app';\nimport { FLOATING_MENU_DISTANCE, HEADER_HEIGHT } from '../../constants';\nimport DirectionAware from '../directionAware';\nimport {\n  SELECTED_ELEMENT_TYPES,\n  hasDesignMenu,\n  TOOLBAR_POSITIONS,\n} from './constants';\nimport FloatingMenu from './menu';\n\nfunction FloatingMenuLayer() {\n  const {\n    setMoveableMount,\n    isEyedropperActive,\n    floatingMenuPosition,\n    displayFloatingMenu,\n  } = useCanvas(({ actions, state }) => ({\n    setMoveableMount: actions.setMoveableMount,\n    isEyedropperActive: state.isEyedropperActive,\n    floatingMenuPosition: state.floatingMenuPosition,\n    displayFloatingMenu: state.displayFloatingMenu,\n  }));\n\n  const { workspaceWidth, workspaceHeight } = useLayout(\n    ({ state: { workspaceWidth, workspaceHeight } }) => ({\n      workspaceWidth,\n      workspaceHeight,\n    })\n  );\n  // We need to know if what is currently selected as well as a unique identifier\n  // for the combined selection (in order to undismiss in case of change of selection)\n  const { selectedElementType, selectionIdentifier } = useStory(\n    ({ state: { selectedElements } }) => ({\n      selectedElementType:\n        selectedElements.length === 1 && !selectedElements[0].isBackground\n          ? selectedElements[0]?.type\n          : selectedElements.length > 1\n            ? SELECTED_ELEMENT_TYPES.MULTIPLE\n            : SELECTED_ELEMENT_TYPES.NONE,\n      selectionIdentifier: selectedElements.map(({ id }) => id).join(''),\n    })\n  );\n\n  const isAnythingTransforming = useTransform(\n    ({ state }) => state.isAnythingTransforming\n  );\n\n  const [moveable, setMoveable] = useState(null);\n  const menuRef = useRef();\n  const workspaceSizeRef = useRef();\n\n  const [isDismissed, setDismissed] = useState(false);\n  const handleDismiss = useCallback(() => setDismissed(true), []);\n  useEffect(() => setDismissed(false), [selectionIdentifier]);\n\n  // Whenever the selection frame (un)mounts, update the reference to moveable\n  // This happens when selection changes between the three possible states: None,\n  // single, multiple. If the selection merely changes inside one of those (so\n  // from single to another single), this function is not invoked.\n  useEffect(() => {\n    setMoveableMount(() => setMoveable);\n    return () => setMoveableMount(null);\n  }, [setMoveableMount]);\n\n  // When eyedropper is active, always hide the floating menu, too.\n  useEffect(() => {\n    if (isEyedropperActive) {\n      setDismissed(true);\n    } else {\n      setDismissed(false);\n    }\n  }, [isEyedropperActive]);\n\n  // Whenever the workspace resizes, update size\n  useEffect(() => {\n    workspaceSizeRef.current = {\n      width: workspaceWidth,\n      height: workspaceHeight,\n    };\n    // Note that we don't have to manually update our position, because the selection\n    // frame will already be updating because of the resize, so a DOM mutation is incoming.\n  }, [workspaceWidth, workspaceHeight]);\n\n  const selectedElementHasDesignMenu = hasDesignMenu(selectedElementType);\n  const isMenuPermanentlyDismissed = false === displayFloatingMenu;\n  const hasMenu =\n    selectedElementHasDesignMenu &&\n    !isDismissed &&\n    moveable &&\n    !isMenuPermanentlyDismissed;\n\n  // Whenever moveable is set (because selection count changed between none, single, or multiple)\n  useEffect(() => {\n    const menu = menuRef.current;\n    if (!menu || !moveable) {\n      return undefined;\n    }\n\n    // If the toolbar is positioned to the top, we keep it in a fixed position.\n    const updatePosition = () => {\n      const frameRect = moveable.getRect();\n      const { width, height } = workspaceSizeRef.current;\n      if (floatingMenuPosition === TOOLBAR_POSITIONS.TOP) {\n        menu.style.left = `clamp(0px, ${\n          width / 2\n        }px - (var(--width) / 2), ${width}px - var(--width))`;\n        menu.style.top = `clamp(0px, ${HEADER_HEIGHT}px, ${height}px - var(--height))`;\n      } else {\n        const centerX = frameRect.left + frameRect.width / 2;\n        menu.style.left = `clamp(0px, ${centerX}px - (var(--width) / 2), ${width}px - var(--width))`;\n        const bottomX =\n          frameRect.top + frameRect.height + FLOATING_MENU_DISTANCE;\n        menu.style.top = `clamp(0px, ${bottomX}px, ${height}px - var(--height))`;\n      }\n    };\n\n    // Update now\n    updatePosition();\n\n    // And update when any element's properties inside the moveable box changes\n    const observer = new MutationObserver(updatePosition);\n    const node = document.querySelector('.moveable-control-box');\n    observer.observe(node, {\n      attributes: true,\n      subtree: true,\n      attributeFilter: ['style'],\n    });\n\n    return () => observer.disconnect();\n  }, [moveable, hasMenu, floatingMenuPosition]);\n\n  if (!hasMenu) {\n    return false;\n  }\n\n  return (\n    <DirectionAware>\n      <FloatingMenu\n        ref={menuRef}\n        handleDismiss={handleDismiss}\n        selectedElementType={selectedElementType}\n        selectionIdentifier={selectionIdentifier}\n        visuallyHidden={isAnythingTransforming}\n      />\n    </DirectionAware>\n  );\n}\n\nexport default FloatingMenuLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  forwardRef,\n  useLayoutEffect,\n  useCallback,\n  memo,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { ContextMenu, useLiveRegion } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_FLOATING_MENU } from '../../constants/zIndex';\nimport {\n  useFocusGroupRef,\n  FOCUS_GROUPS,\n} from '../canvas/editLayerFocusManager';\nimport { FloatingMenuProvider } from './context';\nimport MenuSelector from './menus';\n\nconst FLOATING_MENU_MESSAGE = __(\n  'To exit the floating menu, press Escape.',\n  'web-stories'\n);\n\nconst MenuWrapper = styled.section`\n  display: flex;\n  position: absolute;\n  z-index: ${Z_INDEX_FLOATING_MENU};\n  visibility: ${({ visuallyHidden }) =>\n    visuallyHidden ? 'hidden' : 'visible'};\n  transition: 140ms opacity;\n`;\n\nconst FloatingMenu = memo(\n  forwardRef(function FloatingMenu(\n    { selectionIdentifier, selectedElementType, handleDismiss, visuallyHidden },\n    ref\n  ) {\n    const focusGroupRef = useFocusGroupRef(FOCUS_GROUPS.EDIT_ELEMENT);\n    const speak = useLiveRegion();\n\n    const announceKeyboardControls = useCallback(() => {\n      speak(FLOATING_MENU_MESSAGE);\n    }, [speak]);\n\n    useLayoutEffect(() => {\n      const node = ref.current;\n      const updateSize = () => {\n        node.style.width = '';\n        const bounds = node.getBoundingClientRect();\n        node.style.setProperty('--width', `${bounds.width.toFixed(2)}px`);\n        node.style.setProperty('--height', `${bounds.height.toFixed(2)}px`);\n        node.style.width = 'var(--width)';\n      };\n      updateSize();\n      // If the menu children list changes, update the size again\n      const observer = new MutationObserver(updateSize);\n      const menu = node.querySelector('[role=menu]');\n      observer.observe(menu, { childList: true });\n      return () => observer.disconnect();\n    }, [ref, selectionIdentifier]);\n\n    return (\n      <MenuWrapper\n        ref={ref}\n        aria-label={__('Design menu', 'web-stories')}\n        visuallyHidden={visuallyHidden}\n      >\n        <FloatingMenuProvider handleDismiss={handleDismiss}>\n          <ContextMenu\n            isInline\n            isHorizontal\n            isSecondary\n            isAlwaysVisible\n            tabIndex={-1}\n            ref={focusGroupRef}\n            dismissOnEscape={false}\n            onFocus={announceKeyboardControls}\n            aria-label={__(\n              'Design options for selected element',\n              'web-stories'\n            )}\n            onMouseDown={(e) => {\n              // Stop the event from bubbling if the user clicks in between buttons.\n              // This prevents the selected element in the canvas from losing focus.\n              e.stopPropagation();\n            }}\n            popoverZIndex={Z_INDEX_FLOATING_MENU}\n          >\n            <MenuSelector selectedElementType={selectedElementType} />\n          </ContextMenu>\n        </FloatingMenuProvider>\n      </MenuWrapper>\n    );\n  })\n);\n\nFloatingMenu.propTypes = {\n  handleDismiss: PropTypes.func.isRequired,\n  selectedElementType: PropTypes.string.isRequired,\n  selectionIdentifier: PropTypes.string.isRequired,\n  visuallyHidden: PropTypes.bool,\n};\n\nexport default FloatingMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/audioSticker.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  LayerOpacity,\n  FlipHorizontal,\n  FlipVertical,\n  More,\n  Separator,\n  Dismiss,\n  Settings,\n} from '../elements';\n\nconst FloatingAudioStickerMenu = memo(function FloatingAudioStickerMenu() {\n  return (\n    <>\n      <LayerOpacity />\n\n      <Separator />\n\n      <FlipHorizontal />\n      <FlipVertical />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingAudioStickerMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/image.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  LayerOpacity,\n  FlipHorizontal,\n  FlipVertical,\n  BorderWidthAndColor,\n  More,\n  Separator,\n  Settings,\n  Dismiss,\n} from '../elements';\n\nconst FloatingImageMenu = memo(function FloatingImageMenu() {\n  return (\n    <>\n      <LayerOpacity />\n\n      <Separator />\n      <FlipHorizontal />\n      <FlipVertical />\n\n      <Separator />\n\n      <BorderWidthAndColor />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingImageMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './selector';\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/multiple.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { ElementAlignment, Dismiss, Separator, Settings } from '../elements';\n\nconst FloatingMultipleMenu = memo(function FloatingMultipleMenu() {\n  return (\n    <>\n      <ElementAlignment />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss isMultiple />\n    </>\n  );\n});\n\nexport default FloatingMultipleMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/product.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { memo, useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Separator, Dismiss, Trash, Settings } from '../elements';\nimport { useStory } from '../../../app/story';\nimport { useConfig } from '../../../app/config';\nimport ProductDropdown from '../../library/panes/shopping/productDropdown';\n\nconst StyledDropDown = styled(ProductDropdown)`\n  width: 240px;\n`;\n\nconst FloatingProductMenu = memo(function FloatingProductMenu() {\n  const { selectedElement, updateSelectedElements, deleteSelectedElements } =\n    useStory(({ actions, state }) => ({\n      updateSelectedElements: actions.updateSelectedElements,\n      selectedElement: state.selectedElements[0],\n      deleteSelectedElements: actions.deleteSelectedElements,\n    }));\n\n  const { shoppingProvider } = useConfig();\n  const isShoppingEnabled = 'none' !== shoppingProvider;\n\n  const setProduct = useCallback(\n    (product) => updateSelectedElements({ properties: { product } }),\n    [updateSelectedElements]\n  );\n\n  return (\n    <>\n      {isShoppingEnabled && (\n        <>\n          <StyledDropDown\n            product={selectedElement?.product}\n            setProduct={setProduct}\n          />\n          <Separator />\n        </>\n      )}\n      <Trash\n        title={__('Remove product', 'web-stories')}\n        handleRemove={deleteSelectedElements}\n      />\n      <Settings />\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingProductMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/selector.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { SELECTED_ELEMENT_TYPES } from '../constants';\nimport Image from './image';\nimport Multiple from './multiple';\nimport Shape from './shape';\nimport Sticker from './sticker';\nimport Text from './text';\nimport Video from './video';\nimport Product from './product';\nimport AudioSticker from './audioSticker';\n\nconst FloatingMenuSelector = memo(function FloatingMenuSelector({\n  selectedElementType,\n}) {\n  switch (selectedElementType) {\n    case SELECTED_ELEMENT_TYPES.MULTIPLE:\n      return <Multiple />;\n    case SELECTED_ELEMENT_TYPES.GIF:\n    case SELECTED_ELEMENT_TYPES.IMAGE:\n      return <Image />;\n    case SELECTED_ELEMENT_TYPES.SHAPE:\n      return <Shape />;\n    case SELECTED_ELEMENT_TYPES.STICKER:\n      return <Sticker />;\n    case SELECTED_ELEMENT_TYPES.TEXT:\n      return <Text />;\n    case SELECTED_ELEMENT_TYPES.VIDEO:\n      // eslint-disable-next-line jsx-a11y/media-has-caption -- False positive\n      return <Video />;\n    case SELECTED_ELEMENT_TYPES.PRODUCT:\n      return <Product />;\n    case SELECTED_ELEMENT_TYPES.AUDIO_STICKER:\n      return <AudioSticker />;\n    default:\n      return null;\n  }\n});\n\nFloatingMenuSelector.propTypes = {\n  selectedElementType: PropTypes.string.isRequired,\n};\n\nexport default FloatingMenuSelector;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/shape.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  ShapeColor,\n  BorderRadius,\n  FlipHorizontal,\n  FlipVertical,\n  BorderWidthAndColor,\n  More,\n  Separator,\n  Dismiss,\n  Settings,\n} from '../elements';\n\nconst FloatingShapeMenu = memo(function FloatingShapeMenu() {\n  return (\n    <>\n      <ShapeColor />\n\n      <Separator />\n\n      <BorderRadius />\n      <FlipHorizontal />\n      <FlipVertical />\n\n      <Separator />\n\n      <BorderWidthAndColor />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingShapeMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/sticker.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  LayerOpacity,\n  FlipHorizontal,\n  FlipVertical,\n  More,\n  Separator,\n  Dismiss,\n  Settings,\n} from '../elements';\n\nconst FloatingStickerMenu = memo(function FloatingStickerMenu() {\n  return (\n    <>\n      <LayerOpacity />\n\n      <Separator />\n\n      <FlipHorizontal />\n      <FlipVertical />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingStickerMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/text.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  FontFamily,\n  FontSize,\n  TextAlign,\n  ToggleBold,\n  ToggleItalics,\n  ToggleUnderline,\n  TextColor,\n  More,\n  Separator,\n  Dismiss,\n  Settings,\n} from '../elements';\n\nconst FloatingTextMenu = memo(function FloatingTextMenu() {\n  return (\n    <>\n      <FontFamily />\n      <FontSize />\n      <TextAlign />\n      <ToggleBold />\n      <ToggleItalics />\n      <ToggleUnderline />\n\n      <Separator />\n\n      <TextColor />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingTextMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/menus/video.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  LayerOpacity,\n  FlipHorizontal,\n  FlipVertical,\n  BorderWidthAndColor,\n  Loop,\n  Trim,\n  Mute,\n  More,\n  Separator,\n  Dismiss,\n  Settings,\n} from '../elements';\n\nconst FloatingVideoMenu = memo(function FloatingVideoMenu() {\n  return (\n    <>\n      <LayerOpacity />\n\n      <Separator />\n\n      <FlipHorizontal />\n      <FlipVertical />\n\n      <Separator />\n\n      <BorderWidthAndColor />\n\n      <Separator />\n\n      <Loop />\n      <Trim />\n      <Mute />\n\n      <Separator />\n\n      <More />\n\n      <Separator />\n\n      <Settings />\n\n      <Dismiss />\n    </>\n  );\n});\n\nexport default FloatingVideoMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/floatingMenu/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { ConfigContext } from '../../../app/config';\nimport { StoryContext } from '../../../app/story';\nimport EditLayerFocusManager from '../../canvas/editLayerFocusManager';\nimport FloatingMenu from '../menu';\n\nexport default {\n  title: 'Stories Editor/Components/FloatingMenu',\n  component: FloatingMenu,\n  args: {\n    selectedElementType: 'image',\n    selectionIdentifier: 'a1d51657-6c26-43b6-9571-a5f1de0dcbd9',\n    visuallyHidden: false,\n    ref: { current: {} }, // current just needs to be truthy for menu to render in storybook\n  },\n  argTypes: {\n    handleDismiss: { action: 'dismissed' },\n    selectedElementType: {\n      options: ['image', 'shape', 'sticker'],\n      control: { type: 'select' },\n    },\n  },\n  parameters: {\n    controls: {\n      exclude: [\n        'selectionIdentifier',\n        'visuallyHidden',\n        'ref',\n        'handleDismiss',\n      ],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <ConfigContext.Provider\n        value={{\n          capabilities: {\n            hasUploadMediaAction: true,\n          },\n        }}\n      >\n        <StoryContext.Provider\n          value={{\n            state: {\n              story: {},\n              selectedElements: [\n                {\n                  type: args.selectedElementType,\n                  flip: 'horizontal',\n                  resource: {},\n                  id: 'some-element-id',\n                },\n              ],\n            },\n            actions: { updateSelectedElements: () => {} },\n          }}\n        >\n          <EditLayerFocusManager>\n            <FloatingMenu {...args} />\n          </EditLayerFocusManager>\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/fontPicker/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  forwardRef,\n  useCallback,\n  useMemo,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  DatalistDropdown,\n  DatalistOption,\n  DatalistSelected,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useFont } from '../../app';\nimport { MULTIPLE_DISPLAY_VALUE, MULTIPLE_VALUE } from '../../constants';\n\nconst FontPicker = forwardRef(function FontPicker(\n  {\n    zIndex,\n    onChange,\n    currentValue,\n    highlightStylesOverride,\n    showDropdownLabel,\n    listStyleOverrides,\n    containerStyleOverrides,\n    className,\n    tabIndex,\n  },\n  ref\n) {\n  const {\n    fonts = [],\n    recentFonts = [],\n    curatedFonts = [],\n    customFonts = [],\n    ensureMenuFontsLoaded,\n    ensureCustomFontsLoaded,\n    getFontsBySearch,\n    loadCustomFonts,\n    loadCuratedFonts,\n  } = useFont(({ actions, state }) => ({\n    getFontsBySearch: actions.getFontsBySearch,\n    ensureMenuFontsLoaded: actions.ensureMenuFontsLoaded,\n    ensureCustomFontsLoaded: actions.ensureCustomFontsLoaded,\n    loadCuratedFonts: actions.loadCuratedFonts,\n    loadCustomFonts: actions.loadCustomFonts,\n    recentFonts: state.recentFonts,\n    curatedFonts: state.curatedFonts,\n    fonts: state.fonts,\n    customFonts: state.customFonts,\n  }));\n\n  useEffect(() => {\n    loadCustomFonts();\n    loadCuratedFonts();\n  }, [loadCustomFonts, loadCuratedFonts]);\n\n  const fontMap = useMemo(() => {\n    const map = new Map();\n    // curatedFonts and recentFonts are subsets of fonts.\n    fonts.forEach((f) => {\n      map.set(f.id, f);\n    });\n\n    customFonts?.forEach((f) => {\n      map.set(f.id, f);\n    });\n\n    return map;\n  }, [fonts, customFonts]);\n\n  const onObserve = useCallback(\n    (observedFonts) => {\n      if (!observedFonts.length) {\n        return;\n      }\n      ensureMenuFontsLoaded(\n        observedFonts.filter(\n          (fontName) => fontMap.get(fontName)?.service === 'fonts.google.com'\n        )\n      );\n      ensureCustomFontsLoaded(\n        observedFonts.filter(\n          (fontName) => fontMap.get(fontName)?.service === 'custom'\n        )\n      );\n    },\n    [fontMap, ensureCustomFontsLoaded, ensureMenuFontsLoaded]\n  );\n\n  const renderer = useCallback(\n    ({ option, ...rest }, _ref) => {\n      return (\n        <DatalistOption\n          ref={_ref}\n          {...rest}\n          fontFamily={\n            option.service === 'fonts.google.com'\n              ? `'${option.name}::MENU'`\n              : option.name\n          }\n        >\n          {currentValue === option.id && (\n            <DatalistSelected aria-label={__('Selected', 'web-stories')} />\n          )}\n          {option.name}\n        </DatalistOption>\n      );\n    },\n    [currentValue]\n  );\n\n  // These option groups will always be shown before others.\n  const priorityOptionGroups = useMemo(() => {\n    return [\n      ...(customFonts?.length\n        ? [\n            {\n              label: __('Your fonts', 'web-stories'),\n              options: customFonts,\n            },\n          ]\n        : []),\n      ...(recentFonts?.length\n        ? [\n            {\n              label: __('Recently used', 'web-stories'),\n              options: recentFonts,\n            },\n          ]\n        : []),\n    ];\n  }, [customFonts, recentFonts]);\n\n  //console.error('What is datalist?', DatalistDropdown, DatalistOption);\n  //return null;\n\n  return (\n    <DatalistDropdown\n      ref={ref}\n      zIndex={zIndex}\n      tabIndex={tabIndex}\n      highlightStylesOverride={highlightStylesOverride}\n      data-testid=\"font\"\n      title={__('Available font families', 'web-stories')}\n      dropdownButtonLabel={__('Font family', 'web-stories')}\n      options={fonts}\n      primaryOptions={curatedFonts}\n      primaryLabel={__('Recommended', 'web-stories')}\n      priorityOptionGroups={priorityOptionGroups}\n      searchResultsLabel={__('Search results', 'web-stories')}\n      selectedId={MULTIPLE_VALUE === currentValue ? '' : currentValue}\n      placeholder={\n        MULTIPLE_VALUE === currentValue ? MULTIPLE_DISPLAY_VALUE : currentValue\n      }\n      hasSearch\n      getOptionsByQuery={getFontsBySearch}\n      onChange={onChange}\n      onObserve={onObserve}\n      renderer={forwardRef(renderer)}\n      disabled={!fonts?.length}\n      dropDownLabel={showDropdownLabel ? __('Font', 'web-stories') : null}\n      listStyleOverrides={listStyleOverrides}\n      containerStyleOverrides={containerStyleOverrides}\n      className={className}\n    />\n  );\n});\n\nFontPicker.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  currentValue: PropTypes.string.isRequired,\n  highlightStylesOverride: PropTypes.array,\n  showDropdownLabel: PropTypes.bool,\n  listStyleOverrides: PropTypes.array,\n  containerStyleOverrides: PropTypes.array,\n  zIndex: PropTypes.number,\n  tabIndex: PropTypes.number,\n};\n\nexport default FontPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContainer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  memo,\n  useRef,\n  useState,\n  useResizeEffect,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport CarouselLayout from './carouselLayout';\nimport { CarouselProvider } from './carouselContext';\n\nconst Wrapper = styled.div`\n  height: auto;\n  width: 100%;\n  align-self: flex-end;\n`;\n\nfunction CarouselContainer() {\n  const ref = useRef();\n  const [carouselWidth, setCarouselWidth] = useState(0);\n\n  useResizeEffect(ref, ({ width }) => setCarouselWidth(width), []);\n\n  return (\n    <CarouselProvider availableSpace={carouselWidth}>\n      <Wrapper ref={ref}>\n        <CarouselLayout />\n      </Wrapper>\n    </CarouselProvider>\n  );\n}\n\n// Don't rerender the carousel container needlessly e.g. on element selection change.\nexport default memo(CarouselContainer);\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useMemo,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { ElementId, Page } from '@googleforcreators/elements';\nimport { useStory } from '../../../../app/story';\nimport {\n  requestIdleCallback,\n  cancelIdleCallback,\n} from '../../../../utils/idleCallback';\nimport Context from './context';\nimport useCarouselSizing from './useCarouselSizing';\nimport useCarouselScroll from './useCarouselScroll';\nimport useCarouselKeys from './useCarouselKeys';\n\nfunction CarouselProvider({\n  availableSpace,\n  children,\n}: PropsWithChildren<{ availableSpace: number }>) {\n  const { pages, currentPageId, setCurrentPage, arrangePage } = useStory(\n    ({\n      state: { pages, currentPageId },\n      actions: { setCurrentPage, arrangePage },\n    }) => ({ pages, currentPageId, setCurrentPage, arrangePage })\n  );\n\n  const [listElement, setListElement] = useState<HTMLElement | null>(null);\n  const pagesRef = useRef<Record<ElementId, HTMLElement>>({});\n\n  const numPages = pages.length;\n\n  const pageIds = useMemo(() => pages.map(({ id }) => id), [pages]);\n\n  const [showSkeleton, setShowSkeleton] = useState(true);\n\n  useEffect(() => {\n    const id = requestIdleCallback(() => setShowSkeleton(false), {\n      timeout: 5000,\n    });\n    return () => cancelIdleCallback(id);\n  }, []);\n\n  const {\n    pageThumbWidth,\n    pageThumbHeight,\n    pageThumbMargin,\n    carouselWidth,\n    hasOverflow,\n    showablePages,\n  } = useCarouselSizing({ availableSpace, numPages });\n\n  const { canScrollBack, canScrollForward, scrollBack, scrollForward } =\n    useCarouselScroll({\n      listElement,\n      carouselWidth,\n      hasOverflow,\n      showablePages,\n      pageThumbWidth,\n      pageThumbMargin,\n    });\n\n  useCarouselKeys({ listElement, pageRefs: pagesRef });\n\n  const setPageRef = useCallback((page: Page, el: HTMLElement) => {\n    pagesRef.current[page.id] = el;\n  }, []);\n\n  const clickPage = useCallback(\n    (page: Page) => setCurrentPage({ pageId: page.id }),\n    [setCurrentPage]\n  );\n\n  interface Position {\n    position: number;\n  }\n\n  const rearrangePages = useCallback(\n    ({ position: oldPos }: Position, { position: newPos }: Position) => {\n      const pageId = pageIds[oldPos];\n      arrangePage({ pageId, position: newPos });\n      setCurrentPage({ pageId });\n    },\n    [pageIds, arrangePage, setCurrentPage]\n  );\n\n  const value = {\n    state: {\n      pageThumbWidth,\n      pageThumbHeight,\n      pageThumbMargin,\n      carouselWidth,\n      hasOverflow,\n      pages,\n      pageIds,\n      numPages,\n      currentPageId,\n      canScrollBack,\n      canScrollForward,\n      showSkeleton,\n    },\n    actions: {\n      scrollBack,\n      scrollForward,\n      clickPage,\n      rearrangePages,\n      setListRef: setListElement,\n      setPageRef,\n    },\n  };\n\n  return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport default CarouselProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../../utils/noop';\nimport type { CarouselContext } from './types';\n\nconst Context = createContext<CarouselContext>({\n  state: {\n    pageThumbWidth: 0,\n    pageThumbHeight: 0,\n    pageThumbMargin: 0,\n    carouselWidth: 0,\n    hasOverflow: false,\n    pages: [],\n    pageIds: [],\n    numPages: 0,\n    currentPageId: null,\n    canScrollBack: false,\n    canScrollForward: false,\n    showSkeleton: false,\n  },\n  actions: {\n    scrollBack: noop,\n    scrollForward: noop,\n    clickPage: noop,\n    rearrangePages: noop,\n    setListRef: noop,\n    setPageRef: noop,\n  },\n});\n\nexport default Context;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/index.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useCarousel } from './useCarousel';\nexport { default as CarouselProvider } from './carouselProvider';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/types.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page, ElementId } from '@googleforcreators/elements';\n\nexport interface CarouselContext {\n  state: {\n    pageThumbWidth: number;\n    pageThumbHeight: number;\n    pageThumbMargin: number;\n    carouselWidth: number;\n    hasOverflow: boolean;\n    pages: Page[];\n    pageIds: ElementId[];\n    numPages: number;\n    currentPageId: ElementId | null;\n    canScrollBack: boolean;\n    canScrollForward: boolean;\n    showSkeleton: boolean;\n  };\n  actions: {\n    scrollBack: () => void;\n    scrollForward: () => void;\n    clickPage: (page: Page) => void;\n    rearrangePages: unknown;\n    setListRef: unknown;\n    setPageRef: unknown;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/useCarousel.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { CarouselContext } from './types';\n\nfunction useCarousel(): CarouselContext;\nfunction useCarousel<T>(selector: (state: CarouselContext) => T): T;\nfunction useCarousel<T>(\n  selector: (state: CarouselContext) => T | CarouselContext = identity\n) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useCarousel;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/useCarouselKeys.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport {\n  useEscapeToBlurEffect,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport { duplicatePage, type ElementId } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { RefObject } from 'react';\nimport { useStory } from '../../../../app/story';\nimport { useConfig } from '../../../../app/config';\n\nfunction useCarouselKeys({\n  listElement,\n  pageRefs,\n}: {\n  listElement: HTMLElement | null;\n  pageRefs: RefObject<Record<ElementId, HTMLElement>>;\n}) {\n  const { isRTL } = useConfig();\n  const {\n    addPageAt,\n    arrangePage,\n    currentPage,\n    currentPageId,\n    deletePage,\n    pages,\n    setCurrentPage,\n  } = useStory(\n    ({\n      state: { pages, currentPage, currentPageId },\n      actions: { addPageAt, arrangePage, deletePage, setCurrentPage },\n    }) => ({\n      addPageAt,\n      arrangePage,\n      currentPage,\n      currentPageId,\n      deletePage,\n      pages,\n      setCurrentPage,\n    })\n  );\n\n  const pageIds = useMemo(() => pages.map(({ id }) => id), [pages]);\n\n  useEscapeToBlurEffect(listElement, [listElement]);\n\n  // Navigate left and right.\n  useKeyDownEffect(\n    listElement,\n    { key: ['up', 'down', 'left', 'right'] },\n    ({ key }: KeyboardEvent) => {\n      // Intercept all keys, but only handle left and right.\n      const dir = getArrowDir(key, 'ArrowRight', 'ArrowLeft', isRTL);\n      if (dir === 0) {\n        return;\n      }\n\n      if (!currentPageId) {\n        return;\n      }\n\n      const index = pageIds.indexOf(currentPageId);\n      const nextIndex = index + dir;\n      if (nextIndex >= 0 && nextIndex < pageIds.length) {\n        const pageId = pageIds[nextIndex];\n        setCurrentPage({ pageId });\n\n        const thumbnail = pageRefs.current && pageRefs.current[pageId];\n        // @todo: provide a cleaner `focusFirst()` API and takes into account\n        // `tabIndex`, `disabled`, links, buttons, inputs, etc.\n        const button = thumbnail?.querySelector('button');\n        if (button) {\n          button.focus();\n        }\n      }\n    },\n    [currentPageId, isRTL, pageIds, setCurrentPage, pageRefs, listElement]\n  );\n\n  // Rearrange pages.\n  useKeyDownEffect(\n    listElement,\n    { key: ['mod+up', 'mod+down', 'mod+left', 'mod+right'], shift: true },\n    (evt: KeyboardEvent) => {\n      const { key, shiftKey } = evt;\n\n      // Cancel the default behavior of the event: it's very jarring to run\n      // into mod+left/right triggering the browser's back/forward navigation.\n      evt.preventDefault();\n\n      // Intercept all keys, but only handle left and right.\n      const dir = getArrowDir(key, 'ArrowRight', 'ArrowLeft', isRTL);\n      if (dir === 0) {\n        return;\n      }\n\n      if (!currentPageId) {\n        return;\n      }\n\n      const index = pageIds.indexOf(currentPageId);\n      let newPos = index + dir;\n      if (shiftKey) {\n        newPos = dir < 0 ? 0 : pageIds.length - 1;\n      }\n      if (newPos !== index && newPos >= 0 && newPos < pageIds.length) {\n        arrangePage({ pageId: currentPageId, position: newPos });\n      }\n    },\n    [arrangePage, currentPageId, isRTL, pageIds, setCurrentPage]\n  );\n\n  // Delete the current page.\n  useKeyDownEffect(\n    listElement,\n    'delete',\n    () => {\n      deletePage({ pageId: currentPageId });\n\n      // Wait for active page to change, then set new active page as focus\n      const currentElement = document.activeElement;\n      const setFocusWhenActiveElementChanges = () => {\n        if (document.activeElement !== currentElement && listElement) {\n          // Find the new active element (an option with tabindex=0)\n          const focusableOption: HTMLElement | null = listElement.querySelector(\n            '[role=\"option\"][tabindex=\"0\"]'\n          );\n\n          // If exists, set focus\n          if (focusableOption) {\n            focusableOption.focus();\n            return;\n          }\n        }\n        // Otherwise, try again in 100ms\n        setTimeout(setFocusWhenActiveElementChanges, 100);\n      };\n      setFocusWhenActiveElementChanges();\n    },\n    [currentPageId, deletePage, listElement]\n  );\n\n  // Clone the current page.\n  useKeyDownEffect(\n    listElement,\n    'clone',\n    () => {\n      if (!currentPage) {\n        return;\n      }\n\n      const index = pageIds.indexOf(currentPage.id);\n      addPageAt({ page: duplicatePage(currentPage), position: index + 1 });\n    },\n    [addPageAt, currentPage, pageIds]\n  );\n}\n\nfunction getArrowDir(key: string, pos: string, neg: string, isRTL: boolean) {\n  const rtlDir = isRTL ? -1 : 1;\n  if (key === pos) {\n    return rtlDir;\n  }\n  if (key === neg) {\n    return -rtlDir;\n  }\n  return 0;\n}\n\nexport default useCarouselKeys;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/useCarouselScroll.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useEffect,\n  useLayoutEffect,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\nimport { useStory } from '../../../../app/story';\nimport { useLayout } from '../../../../app/layout';\nimport { CarouselState } from '../../../../constants';\n\ninterface UseCarouselScrollProps {\n  listElement: HTMLElement | null;\n  carouselWidth: number;\n  hasOverflow: boolean;\n  showablePages: number;\n  pageThumbWidth: number;\n  pageThumbMargin: number;\n}\n\nfunction useCarouselScroll({\n  listElement,\n  carouselWidth,\n  hasOverflow,\n  showablePages,\n  pageThumbWidth,\n  pageThumbMargin,\n}: UseCarouselScrollProps) {\n  const [ratio, setRatio] = useState(0);\n  const { isRTL } = useConfig();\n  const { carouselState } = useLayout(({ state: { carouselState } }) => ({\n    carouselState,\n  }));\n  const { currentPageIndex } = useStory(\n    ({ state: { currentPageId, pages } }) => ({\n      currentPageIndex: pages.findIndex(({ id }) => id === currentPageId),\n    })\n  );\n\n  const scroll = useCallback(\n    (offset: number) => {\n      if (!listElement) {\n        return;\n      }\n\n      if (isRTL) {\n        offset *= -1;\n      }\n\n      listElement.scrollBy({\n        left: offset,\n        behavior: 'smooth',\n      });\n    },\n    [listElement, isRTL]\n  );\n\n  const scrollByPx = carouselWidth;\n  const isAtStart = isRTL ? 0 === ratio : 0 === ratio;\n  const isAtEnd = isRTL ? -1 === ratio : 1 === ratio;\n\n  const canScrollBack = hasOverflow && !isAtStart;\n  const canScrollForward = hasOverflow && !isAtEnd;\n\n  const scrollForward = useCallback(\n    () => scroll(scrollByPx),\n    [scroll, scrollByPx]\n  );\n  const scrollBack = useCallback(\n    () => scroll(-scrollByPx),\n    [scroll, scrollByPx]\n  );\n\n  // This effects handles setting the scroll ratio, which is need to\n  // enable and disable the scroll arrows correctly.\n  useLayoutEffect(() => {\n    if (!hasOverflow || !listElement) {\n      return undefined;\n    }\n\n    const handleScroll = () => {\n      const { offsetWidth, scrollLeft, scrollWidth } = listElement;\n      const max = scrollWidth - offsetWidth;\n      setRatio(scrollLeft / max);\n    };\n\n    listElement.addEventListener('scroll', handleScroll, { passive: true });\n    return () => listElement.removeEventListener('scroll', handleScroll);\n  }, [listElement, hasOverflow]);\n\n  const getOffsetFromIndex = useCallback(\n    (index) => (pageThumbWidth + pageThumbMargin) * index,\n    [pageThumbWidth, pageThumbMargin]\n  );\n\n  // Is this the first scroll (which will be instant rather than animated)?\n  const firstScrollRef = useRef(true);\n\n  // If the carousel drawer is collapsed, reset first scroll to true\n  useEffect(() => {\n    if (carouselState === CarouselState.Closed) {\n      firstScrollRef.current = true;\n    }\n  }, [carouselState]);\n\n  // This effect makes sure, that whenever the current page changes, it'll be in focus\n  // Note that it doesn't run just because the current page is updated (some element\n  // added or removed to page). Only when the actual index for the current page is updated\n  // (because a page is added or deleted or user navigate to another page), this runs.\n  useLayoutEffect(() => {\n    if (!hasOverflow || !listElement) {\n      return undefined;\n    }\n\n    const { scrollLeft } = listElement;\n\n    // If scrolled to the start, what is the min index of the first visible page\n    // in order for the current page to be at the very end of the current scroll\n    const minVisiblePageIndex = Math.max(\n      0,\n      currentPageIndex - showablePages + 1\n    );\n    // If scrolled to the very end, the current page must be the first visible page\n    const maxVisiblePageIndex = currentPageIndex;\n    // Convert these to scroll numbers\n    const minOffset = getOffsetFromIndex(minVisiblePageIndex);\n    const maxOffset = getOffsetFromIndex(maxVisiblePageIndex);\n\n    if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {\n      // Page is already visible\n      return undefined;\n    }\n\n    // Scroll so that current page is visible with least amount of delta needed\n    const targetLeft = scrollLeft < minOffset ? minOffset : maxOffset;\n    const doScroll = () => {\n      // However, if at the end of container, new page might not have been added yet.\n      const maxScroll = listElement.scrollWidth - listElement.offsetWidth;\n      // If so, wait a bit\n      if (maxScroll < targetLeft) {\n        return;\n      }\n\n      // If this is the first scroll, jump instantly to the target offset\n      const scrollBehavior = firstScrollRef.current ? 'auto' : 'smooth';\n      firstScrollRef.current = false;\n\n      // Otherwise, do scroll and cancel interval\n      listElement.scrollTo({\n        left: targetLeft,\n        top: 0,\n        behavior: scrollBehavior,\n      });\n      clearInterval(retry);\n    };\n    const retry = setInterval(doScroll, 100);\n    return () => clearInterval(retry);\n  }, [\n    listElement,\n    hasOverflow,\n    currentPageIndex,\n    showablePages,\n    getOffsetFromIndex,\n  ]);\n\n  return {\n    canScrollBack,\n    canScrollForward,\n    scrollForward,\n    scrollBack,\n  };\n}\nexport default useCarouselScroll;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselContext/useCarouselSizing.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport {\n  NAVIGATION_BUTTON_GUTTER,\n  WIDE_CAROUSEL_LIMIT,\n  WIDE_THUMBNAIL_WIDTH,\n  WIDE_THUMBNAIL_HEIGHT,\n  NARROW_THUMBNAIL_WIDTH,\n  NARROW_THUMBNAIL_HEIGHT,\n  THUMBNAIL_MARGIN,\n} from '../constants';\n\nfunction useCarouselSizing({\n  availableSpace,\n  numPages,\n}: {\n  availableSpace: number;\n  numPages: number;\n}) {\n  return useMemo(() => {\n    const isWideCarousel = availableSpace >= WIDE_CAROUSEL_LIMIT;\n    const spaceForCarousel = availableSpace - 2 * NAVIGATION_BUTTON_GUTTER;\n    const pageThumbWidth = isWideCarousel\n      ? WIDE_THUMBNAIL_WIDTH\n      : NARROW_THUMBNAIL_WIDTH;\n    const pageThumbHeight = isWideCarousel\n      ? WIDE_THUMBNAIL_HEIGHT\n      : NARROW_THUMBNAIL_HEIGHT;\n    const pageThumbMargin = THUMBNAIL_MARGIN;\n    const pageAndMargin = pageThumbWidth + pageThumbMargin;\n    const showablePages = Math.floor(\n      (spaceForCarousel - pageThumbMargin) / pageAndMargin\n    );\n    const hasOverflow = showablePages < numPages;\n    const carouselWidth =\n      Math.min(showablePages, numPages) * (pageThumbWidth + pageThumbMargin) +\n      pageThumbMargin;\n    return {\n      pageThumbWidth,\n      pageThumbHeight,\n      pageThumbMargin,\n      carouselWidth,\n      showablePages,\n      hasOverflow,\n    };\n  }, [availableSpace, numPages]);\n}\n\nexport default useCarouselSizing;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselDrawer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonVariant,\n  ButtonType,\n  ButtonSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useLayout } from '../../../app';\nimport { CarouselState } from '../../../constants';\nimport CarouselDrawerIcon from './carouselDrawerIcon';\n\nconst Wrapper = styled.div`\n  display: flex;\n  justify-content: center;\n`;\n\nconst StyledButton = styled(Button)`\n  white-space: nowrap;\n  gap: 8px;\n`;\n\nfunction CarouselDrawer() {\n  const { carouselState, openCarousel, closeCarousel } = useLayout(\n    ({\n      state: { carouselState },\n      actions: { openCarousel, closeCarousel },\n    }) => ({ carouselState, openCarousel, closeCarousel })\n  );\n\n  const { currentPageNumber, pageCount } = useStory(\n    ({ state: { currentPageNumber, pages } }) => ({\n      currentPageNumber,\n      pageCount: pages.length,\n    })\n  );\n\n  const onClick = useCallback(() => {\n    // Note that we only trigger a change of state if the carousel is in one of these\n    // stable states, and not if it's in any of the transitioning states.\n    if (carouselState === CarouselState.Open) {\n      closeCarousel();\n    } else if (carouselState === CarouselState.Closed) {\n      openCarousel();\n    }\n  }, [carouselState, openCarousel, closeCarousel]);\n\n  return (\n    <Wrapper>\n      <StyledButton\n        aria-label={__('Toggle page carousel', 'web-stories')}\n        onClick={onClick}\n        variant={ButtonVariant.Rectangle}\n        size={ButtonSize.Small}\n        type={ButtonType.Tertiary}\n      >\n        {sprintf(\n          /* translators: 1: current page number. 2: total page count. */\n          _n(\n            '%1$d of %2$d page',\n            '%1$d of %2$d pages',\n            pageCount,\n            'web-stories'\n          ),\n          currentPageNumber,\n          pageCount\n        )}\n        <CarouselDrawerIcon state={carouselState} />\n      </StyledButton>\n    </Wrapper>\n  );\n}\n\nexport default CarouselDrawer;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselDrawerIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { CarouselState } from '../../../constants';\n\nconst iconCss = css`\n  width: 32px;\n  margin: -8px;\n`;\n\nconst IconDown = styled(Icons.ChevronDownSmall)`\n  ${iconCss}\n`;\n\nconst IconUp = styled(Icons.ChevronUpSmall)`\n  ${iconCss}\n`;\n\nfunction CarouselDrawerIcon({ state }) {\n  // If open or going from open to closed, show down arrow\n  if ([CarouselState.Open, CarouselState.Closing].includes(state)) {\n    return <IconDown />;\n  }\n  // Otherwise if closed or going from closed to open, show up arrow\n  return <IconUp />;\n}\n\nCarouselDrawerIcon.propTypes = {\n  state: PropTypes.string.isRequired,\n};\n\nexport default CarouselDrawerIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { CSSTransition } from 'react-transition-group';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../../app';\nimport {\n  CarouselState,\n  CAROUSEL_TRANSITION_DURATION,\n} from '../../../constants';\nimport { Z_INDEX_FOOTER } from '../../../constants/zIndex';\nimport { CarouselScrollForward, CarouselScrollBack } from './carouselScroll';\nimport CarouselList from './carouselList';\nimport CarouselDrawer from './carouselDrawer';\nimport { useCarousel } from './carouselContext';\nimport {\n  NAVIGATION_BUTTON_WIDTH,\n  NAVIGATION_BUTTON_GAP,\n  DRAWER_BUTTON_GAP_EXPANDED,\n  DRAWER_BUTTON_GAP_COLLAPSED,\n} from './constants';\n\nconst DRAWER_BUTTON_GAP_DIFF =\n  DRAWER_BUTTON_GAP_EXPANDED - DRAWER_BUTTON_GAP_COLLAPSED;\n\nconst Wrapper = styled.section`\n  position: relative;\n  display: grid;\n  grid:\n    /* Note the two empty 1fr areas on either side of the buttons - that's on purpose\n     *\n     * d = drawer button\n     * p = previous arrow\n     * c = carousel page list\n     * n = next arrow\n     */\n    '. d d d d d .' 32px\n    '. . . . . . .' ${({ isCollapsed }) =>\n      isCollapsed ? DRAWER_BUTTON_GAP_COLLAPSED : DRAWER_BUTTON_GAP_EXPANDED}px\n    '. p . c . n .' auto /\n    1fr\n    ${NAVIGATION_BUTTON_WIDTH}px\n    ${NAVIGATION_BUTTON_GAP}px\n    auto\n    ${NAVIGATION_BUTTON_GAP}px\n    ${NAVIGATION_BUTTON_WIDTH}px\n    1fr;\n  width: 100%;\n  height: auto;\n  z-index: ${Z_INDEX_FOOTER};\n\n  &.carousel-enter {\n    top: ${({ thumbHeight }) => thumbHeight + DRAWER_BUTTON_GAP_DIFF}px;\n\n    &.carousel-enter-active {\n      top: 0;\n      transition: ${CAROUSEL_TRANSITION_DURATION}ms ease-out;\n      transition-property: top;\n    }\n  }\n\n  &.carousel-exit {\n    top: 0;\n\n    &.carousel-exit-active {\n      top: ${({ thumbHeight }) => thumbHeight + DRAWER_BUTTON_GAP_DIFF}px;\n      transition: ${CAROUSEL_TRANSITION_DURATION}ms ease-out;\n      transition-property: top;\n    }\n  }\n`;\n\nconst Area = styled.div`\n  grid-area: ${({ area }) => area};\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-direction: column;\n`;\n\nfunction CarouselLayout() {\n  const { carouselState } = useLayout(({ state: { carouselState } }) => ({\n    carouselState,\n  }));\n\n  const { numPages, pageThumbHeight } = useCarousel(\n    ({ state: { numPages, pageThumbHeight } }) => ({\n      numPages,\n      pageThumbHeight,\n    })\n  );\n  const nodeRef = useRef();\n  if (numPages <= 0) {\n    return null;\n  }\n\n  const isCollapsed = carouselState === CarouselState.Closed;\n\n  const isOpenOrOpening = [CarouselState.Open, CarouselState.Opening].includes(\n    carouselState\n  );\n\n  return (\n    <CSSTransition\n      in={isOpenOrOpening}\n      classNames=\"carousel\"\n      containerRef\n      nodeRef={nodeRef}\n      timeout={CAROUSEL_TRANSITION_DURATION}\n    >\n      <Wrapper\n        ref={nodeRef}\n        aria-label={__('Page Carousel', 'web-stories')}\n        isCollapsed={isCollapsed}\n        thumbHeight={pageThumbHeight}\n      >\n        <Area area=\"d\">\n          <CarouselDrawer />\n        </Area>\n        {!isCollapsed && (\n          <>\n            <Area area=\"p\">\n              <CarouselScrollBack />\n            </Area>\n            <Area area=\"c\">\n              <CarouselList />\n            </Area>\n            <Area area=\"n\">\n              <CarouselScrollForward />\n            </Area>\n          </>\n        )}\n      </Wrapper>\n    </CSSTransition>\n  );\n}\n\nexport default CarouselLayout;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselList.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Reorderable } from '../../reorderable';\nimport CarouselPage from './carouselPage';\nimport SkeletonPage from './skeletonPage';\nimport { useCarousel } from './carouselContext';\n\nconst PageList = styled(Reorderable).attrs({\n  role: 'listbox',\n  'aria-orientation': 'horizontal',\n  mode: 'horizontal',\n})`\n  grid-area: carousel;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  overflow-x: hidden;\n  overflow-y: hidden;\n  width: ${({ $width }) => $width}px;\n  list-style: none;\n  padding: 4px 0;\n  margin: -4px 0;\n\n  ${({ hasOverflow }) =>\n    hasOverflow &&\n    css`\n      overflow-x: visible;\n      justify-content: flex-start;\n    `};\n\n  ::-webkit-scrollbar-thumb {\n    border: 6px solid transparent !important;\n  }\n`;\n\nfunction CarouselList() {\n  const {\n    pageThumbWidth,\n    carouselWidth,\n    hasOverflow,\n    pageIds,\n    rearrangePages,\n    setListRef,\n    showSkeleton,\n  } = useCarousel(\n    ({\n      state: {\n        pageThumbWidth,\n        carouselWidth,\n        hasOverflow,\n        pageIds,\n        showSkeleton,\n      },\n      actions: { rearrangePages, setListRef },\n    }) => ({\n      pageThumbWidth,\n      carouselWidth,\n      hasOverflow,\n      pageIds,\n      rearrangePages,\n      setListRef,\n      showSkeleton,\n    })\n  );\n\n  const Page = showSkeleton ? SkeletonPage : CarouselPage;\n\n  return (\n    <PageList\n      mode=\"horizontal\"\n      $width={carouselWidth}\n      ref={setListRef}\n      hasOverflow={hasOverflow}\n      aria-label={__('Pages List', 'web-stories')}\n      onPositionChange={rearrangePages}\n      getItemSize={() => pageThumbWidth}\n    >\n      {pageIds.map((pageId, index) => (\n        <Page key={pageId} pageId={pageId} index={index} />\n      ))}\n    </PageList>\n  );\n}\n\nexport default CarouselList;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { ReorderableSeparator, ReorderableItem } from '../../reorderable';\nimport PagePreview from '../pagepreview';\nimport { useCarousel } from './carouselContext';\nimport { THUMBNAIL_LINE_WIDTH } from './constants';\n\nconst Line = styled.div`\n  background: ${({ theme }) => theme.colors.border.selection};\n  height: ${({ $height }) => $height}px;\n  width: ${THUMBNAIL_LINE_WIDTH}px;\n  margin: 0px;\n`;\n\nconst ItemContainer = styled.li.attrs({ role: 'presentation' })`\n  display: flex;\n  position: relative;\n  margin: 0;\n  padding: 0;\n`;\n\nconst PageSeparator = styled(ReorderableSeparator)`\n  position: absolute;\n  bottom: 0;\n  left: ${({ $width }) => $width / 2}px;\n  width: ${({ $width, margin }) => $width + margin}px;\n  height: ${({ $height }) => $height}px;\n  display: flex;\n  justify-content: center;\n\n  ${ItemContainer}:first-of-type &:first-of-type,\n  ${ItemContainer}:last-of-type &:last-of-type {\n    width: ${({ $width, margin }) =>\n      ($width + margin + THUMBNAIL_LINE_WIDTH) / 2}px;\n  }\n\n  ${ItemContainer}:first-of-type &:first-of-type {\n    left: ${({ margin }) => (margin - THUMBNAIL_LINE_WIDTH) / 2}px;\n    justify-content: flex-start;\n  }\n\n  ${ItemContainer}:first-of-type &:last-of-type {\n    left: ${({ $width, margin }) => margin + $width / 2}px;\n  }\n\n  /* stylelint-disable-next-line no-duplicate-selectors */\n  ${ItemContainer}:last-of-type &:last-of-type {\n    justify-content: flex-end;\n  }\n`;\n\nconst ReorderablePage = styled(ReorderableItem)`\n  display: flex;\n  z-index: 1;\n  margin-right: ${({ margin }) => margin}px;\n  margin-left: ${({ margin, position }) => (position === 0 ? margin : 0)}px;\n`;\n\nfunction CarouselPage({ pageId, index }) {\n  const {\n    pageThumbWidth,\n    pageThumbHeight,\n    pageThumbMargin,\n    clickPage,\n    setPageRef,\n    page,\n    isCurrentPage,\n    hasMultiplePages,\n  } = useCarousel(\n    ({\n      state: {\n        pageThumbWidth,\n        pageThumbHeight,\n        pageThumbMargin,\n        numPages,\n        pages,\n        currentPageId,\n      },\n      actions: { clickPage, setPageRef },\n    }) => ({\n      pageThumbWidth,\n      pageThumbHeight,\n      pageThumbMargin,\n      clickPage,\n      setPageRef,\n      page: pages.find(({ id }) => id === pageId),\n      isCurrentPage: pageId === currentPageId,\n      hasMultiplePages: numPages > 1,\n    })\n  );\n\n  if (!page || !page.id) {\n    return null;\n  }\n\n  return (\n    <ItemContainer\n      ref={(el) => setPageRef(page, el)}\n      data-testid={`carousel-page-preview-${pageId}`}\n    >\n      {index === 0 && (\n        <PageSeparator\n          position={0}\n          $width={pageThumbWidth}\n          $height={pageThumbHeight}\n          margin={pageThumbMargin}\n        >\n          <Line $height={pageThumbHeight} />\n        </PageSeparator>\n      )}\n      <ReorderablePage position={index} margin={pageThumbMargin}>\n        <PagePreview\n          tabIndex={isCurrentPage && hasMultiplePages ? 0 : -1}\n          onClick={() => clickPage(page)}\n          role=\"option\"\n          data-page-id={page.id}\n          label={\n            isCurrentPage\n              ? sprintf(\n                  /* translators: %s: page number. */\n                  __('Page %s (current page)', 'web-stories'),\n                  index + 1\n                )\n              : sprintf(\n                  /* translators: %s: page number. */\n                  __('Go to page %s', 'web-stories'),\n                  index + 1\n                )\n          }\n          isActive={isCurrentPage}\n          page={page}\n          width={pageThumbWidth}\n          height={pageThumbHeight}\n          isInteractive={hasMultiplePages}\n        />\n      </ReorderablePage>\n      <PageSeparator\n        position={index + 1}\n        $width={pageThumbWidth}\n        $height={pageThumbHeight}\n        margin={pageThumbMargin}\n      >\n        <Line $height={pageThumbHeight} />\n      </PageSeparator>\n    </ItemContainer>\n  );\n}\n\nCarouselPage.propTypes = {\n  pageId: PropTypes.string.isRequired,\n  index: PropTypes.number.isRequired,\n};\n\nexport default CarouselPage;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/carouselScroll.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Button,\n  Icons,\n  ButtonVariant,\n  ButtonType,\n  ButtonSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../app';\nimport { useCarousel } from './carouselContext';\n\nconst FlippableArrow = styled(Icons.ArrowLeft)`\n  transform: rotate(${({ $isLeft }) => ($isLeft ? 0 : 0.5)}turn);\n`;\n\nfunction CarouselScrollButton({ isNext = false }) {\n  const {\n    hasOverflow,\n    canScrollBack,\n    canScrollForward,\n    scrollBack,\n    scrollForward,\n  } = useCarousel(\n    ({\n      state: { hasOverflow, canScrollBack, canScrollForward },\n      actions: { scrollBack, scrollForward },\n    }) => ({\n      hasOverflow,\n      canScrollBack,\n      canScrollForward,\n      scrollBack,\n      scrollForward,\n    })\n  );\n  const { isRTL } = useConfig();\n\n  if (!hasOverflow) {\n    // If no overflow, just abort quickly\n    return null;\n  }\n\n  const canScroll = isNext ? canScrollForward : canScrollBack;\n  const onClick = isNext ? scrollForward : scrollBack;\n  const label = isNext\n    ? __('Scroll Forward', 'web-stories')\n    : __('Scroll Back', 'web-stories');\n\n  // If reading direction is RTL and this is next button, it's pointing left.\n  // If reading direction is !RTL and this is !next button, it's pointing left.\n  // Otherwise it's a right.\n  // Thus, if the two bools are equal, it's a left button.\n  const isLeft = isRTL === isNext;\n\n  return (\n    <Button\n      variant={ButtonVariant.Square}\n      type={ButtonType.Plain}\n      size={ButtonSize.Small}\n      disabled={!canScroll}\n      onClick={onClick}\n      aria-label={label}\n    >\n      <FlippableArrow $isLeft={isLeft} />\n    </Button>\n  );\n}\n\nCarouselScrollButton.propTypes = {\n  isNext: PropTypes.bool,\n};\n\nfunction CarouselScrollForward() {\n  return <CarouselScrollButton isNext />;\n}\n\nfunction CarouselScrollBack() {\n  return <CarouselScrollButton />;\n}\n\nexport { CarouselScrollForward, CarouselScrollBack };\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { THEME_CONSTANTS } from '@googleforcreators/design-system';\n\n// The navigation buttons and menu gutters\nexport const NAVIGATION_BUTTON_WIDTH = THEME_CONSTANTS.ICON_SIZE;\nexport const NAVIGATION_BUTTON_GAP = 8;\nexport const NAVIGATION_BUTTON_GUTTER =\n  NAVIGATION_BUTTON_WIDTH + NAVIGATION_BUTTON_GAP;\n\n// Drawer button\nexport const DRAWER_BUTTON_HEIGHT = 32;\nexport const DRAWER_BUTTON_GAP_EXPANDED = 8;\nexport const DRAWER_BUTTON_GAP_COLLAPSED = 2;\n\n// Thumbnail size varies with available carousel size - over or under this limit\nexport const WIDE_CAROUSEL_LIMIT = 400;\nexport const WIDE_THUMBNAIL_WIDTH = 45;\nexport const WIDE_THUMBNAIL_HEIGHT = 80;\nexport const NARROW_THUMBNAIL_WIDTH = 36;\nexport const NARROW_THUMBNAIL_HEIGHT = 64;\nexport const THUMBNAIL_MARGIN = 16;\nexport const THUMBNAIL_LINE_WIDTH = 4;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './carouselContainer';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/karma/carouselDrawer.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\n\nconst TOGGLE_DURATION = 400;\n\ndescribe('Carousel Drawer', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    // We add some content to the first page to make the thumbnail more interesting\n    const mediaItem = fixture.editor.library.media.item(0);\n    await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n\n    await waitFor(() => {\n      if (fixture.editor.footer.carousel.pages.length === 0) {\n        throw new Error('Carousel pages not loaded yet');\n      }\n    });\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('with a single-page story', () => {\n    it('should show correctly', async () => {\n      // 1 page\n      expect(fixture.editor.footer.carousel.pages.length).toBe(1);\n\n      // Toggle button exists\n      expect(fixture.editor.footer.carousel.toggle).toBeTruthy();\n\n      // No scroll buttons\n      expect(fixture.editor.footer.carousel.next).toBeFalsy();\n      expect(fixture.editor.footer.carousel.previous).toBeFalsy();\n\n      await fixture.snapshot();\n    });\n\n    it('should collapse and expand', async () => {\n      await fixture.events.click(fixture.editor.footer.carousel.toggle);\n      await fixture.events.sleep(TOGGLE_DURATION);\n\n      expect(fixture.editor.footer.carousel.pages.length).toBe(0);\n      await fixture.snapshot('Collapsed');\n\n      await fixture.events.click(fixture.editor.footer.carousel.toggle);\n      await fixture.events.sleep(TOGGLE_DURATION);\n\n      expect(fixture.editor.footer.carousel.pages.length).toBe(1);\n      await fixture.snapshot('Re-expanded');\n    });\n  });\n\n  describe('with a multi-page story', () => {\n    const EXTRA_PAGES = 19;\n\n    beforeEach(() => {\n      // Let's add some extra pages\n      let pagesToAdd = EXTRA_PAGES;\n\n      const addPage = async () => {\n        if (pagesToAdd <= 0) {\n          return undefined;\n        }\n\n        // Add a page\n        await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n\n        // Add some media to it\n        await fixture.events.click(\n          fixture.editor.library.media.item(pagesToAdd % 8)\n        );\n\n        // Keep going\n        pagesToAdd -= 1;\n        return addPage();\n      };\n\n      return addPage();\n    });\n\n    it('should show correctly', async () => {\n      // 20 pages\n      expect(fixture.editor.footer.carousel.pages.length).toBe(1 + EXTRA_PAGES);\n\n      // Toggle button exists\n      expect(fixture.editor.footer.carousel.toggle).toBeTruthy();\n\n      // Both scroll buttons exist\n      expect(fixture.editor.footer.carousel.next).toBeTruthy();\n      expect(fixture.editor.footer.carousel.previous).toBeTruthy();\n\n      await fixture.snapshot();\n    });\n\n    it('should collapse and expand', async () => {\n      await fixture.events.click(fixture.editor.footer.carousel.toggle);\n      await fixture.events.sleep(TOGGLE_DURATION);\n\n      expect(fixture.editor.footer.carousel.pages.length).toBe(0);\n      await fixture.snapshot('Collapsed');\n\n      await fixture.events.click(fixture.editor.footer.carousel.toggle);\n      await fixture.events.sleep(TOGGLE_DURATION);\n\n      expect(fixture.editor.footer.carousel.pages.length).toBe(1 + EXTRA_PAGES);\n      await fixture.snapshot('Re-expanded');\n    });\n\n    it('should have no aXe violations while carousel is expanded', async () => {\n      await expectAsync(\n        fixture.editor.footer.carousel.node\n      ).toHaveNoViolations();\n    });\n\n    it('should have no aXe violations while carousel is collapsed', async () => {\n      await fixture.events.click(fixture.editor.footer.carousel.toggle);\n      await fixture.events.sleep(TOGGLE_DURATION);\n      await expectAsync(\n        fixture.editor.footer.carousel.node\n      ).toHaveNoViolations();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/karma/carouselNavigation.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Carousel Navigation', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    fixture.setPages([\n      { id: 'page1', backgroundColor: createSolid(255, 255, 255) },\n      { id: 'page2', backgroundColor: createSolid(255, 0, 0) },\n      { id: 'page3', backgroundColor: createSolid(0, 255, 0) },\n      { id: 'page4', backgroundColor: createSolid(0, 0, 255) },\n    ]);\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getCurrentPageId() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPageId;\n  }\n\n  async function getSelectionLength() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElementIds.length;\n  }\n\n  async function getPageIds() {\n    const {\n      state: { pages },\n    } = await fixture.renderHook(() => useStory());\n    return pages.map(({ id }) => id);\n  }\n\n  async function clickOnThumbnail(index) {\n    await fixture.editor.footer.carousel.waitReady();\n    await waitFor(() => {\n      if (fixture.editor.footer.carousel.pages.length === 0) {\n        throw new Error('Carousel pages not loaded yet');\n      }\n    });\n    const thumb = fixture.editor.footer.carousel.pages[index];\n    thumb.node.scrollIntoView();\n    await fixture.events.mouse.clickOn(thumb.node, 5, 5);\n  }\n\n  it('should select the current page', async () => {\n    expect(await getCurrentPageId()).toEqual('page1');\n    expect(await getSelectionLength()).toBe(1);\n  });\n\n  // Since we're already on the first page, selection and current page id remains unchanged.\n  it('should click into carousel on the first page', async () => {\n    await clickOnThumbnail(0);\n    expect(await getCurrentPageId()).toEqual('page1');\n    expect(await getSelectionLength()).toBe(1);\n  });\n\n  it('should exit the carousel on Esc', async () => {\n    // Enter.\n    await clickOnThumbnail(0);\n    await fixture.editor.footer.carousel.waitFocusedWithin();\n\n    // Exit.\n    await fixture.events.keyboard.press('Esc');\n    await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n  });\n\n  it('should click into carousel on the second page', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getSelectionLength()).toBe(0);\n  });\n\n  it('should navigate the page with keys', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Go left.\n    await fixture.events.keyboard.press('left');\n    expect(await getCurrentPageId()).toEqual('page1');\n\n    // Go left again: end of the line.\n    await fixture.events.keyboard.press('left');\n    expect(await getCurrentPageId()).toEqual('page1');\n\n    // Go right.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Go right again.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page3');\n\n    // Go right again.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page4');\n\n    // Go right again: end of the line.\n    await fixture.events.keyboard.press('right');\n    expect(await getCurrentPageId()).toEqual('page4');\n  });\n\n  it('should reorder the page with keys', async () => {\n    await clickOnThumbnail(1);\n    expect(await getCurrentPageId()).toEqual('page2');\n\n    // Order left.\n    await fixture.events.keyboard.shortcut('mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order left again: end of the line.\n    await fixture.events.keyboard.shortcut('mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order right.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page2', 'page3', 'page4']);\n\n    // Order right again.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page2', 'page4']);\n\n    // Order right again.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n\n    // Order right again: end of the line.\n    await fixture.events.keyboard.shortcut('mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n\n    // Order to first.\n    await fixture.events.keyboard.shortcut('shift+mod+left');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page2', 'page1', 'page3', 'page4']);\n\n    // Order to last.\n    await fixture.events.keyboard.shortcut('shift+mod+right');\n    expect(await getCurrentPageId()).toEqual('page2');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4', 'page2']);\n  });\n\n  it('should delete the first page', async () => {\n    await clickOnThumbnail(0);\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n    expect(await getPageIds()).toEqual(['page2', 'page3', 'page4']);\n    expect(await getCurrentPageId()).toEqual('page2');\n  });\n\n  it('should delete the second page', async () => {\n    await clickOnThumbnail(1);\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n    expect(await getPageIds()).toEqual(['page1', 'page3', 'page4']);\n    expect(await getCurrentPageId()).toEqual('page3');\n  });\n\n  it('should duplicate the first page', async () => {\n    await clickOnThumbnail(0);\n    await fixture.events.keyboard.shortcut('mod+D');\n    const newPageId = await getCurrentPageId();\n    expect(await getPageIds()).toEqual([\n      'page1',\n      newPageId,\n      'page2',\n      'page3',\n      'page4',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/carousel/skeletonPage.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  generatePatternStyles,\n  getSolidFromHex,\n  isHexColorString,\n} from '@googleforcreators/patterns';\nimport { type ElementId, elementIs } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useCarousel } from './carouselContext';\n\nconst EmptyPage = styled.li.attrs({ role: 'presentation' })`\n  display: block;\n  position: relative;\n  flex: 0 0;\n  margin: 0;\n  padding: 0;\n  border-radius: 4px;\n`;\n\nfunction SkeletonPage({ pageId, index }: { pageId: ElementId; index: number }) {\n  const { pageThumbWidth, pageThumbHeight, pageThumbMargin, hasPage, bgColor } =\n    useCarousel(\n      ({\n        state: { pageThumbWidth, pageThumbHeight, pageThumbMargin, pages },\n      }) => {\n        let bgColor = null;\n\n        const page = pages.find(({ id }) => id === pageId);\n\n        if (page) {\n          bgColor = page.backgroundColor;\n          const bgElement = page.elements[0];\n\n          // Using isHexColorString for extra hardening.\n          // See https://github.com/googleforcreators/web-stories-wp/issues/9888.\n          if (\n            bgElement &&\n            elementIs.media(bgElement) &&\n            bgElement.resource.baseColor &&\n            isHexColorString(bgElement.resource.baseColor)\n          ) {\n            bgColor = getSolidFromHex(\n              bgElement.resource.baseColor.replace('#', '')\n            );\n          }\n        }\n\n        return {\n          pageThumbWidth,\n          pageThumbHeight,\n          pageThumbMargin,\n          hasPage: Boolean(page && page.id),\n          bgColor,\n        };\n      }\n    );\n\n  if (!hasPage) {\n    return null;\n  }\n\n  return (\n    <EmptyPage\n      style={{\n        flexBasis: `${pageThumbWidth}px`,\n        height: `${pageThumbHeight}px`,\n        marginLeft: `${index === 0 ? pageThumbMargin : 0}px`,\n        marginRight: `${pageThumbMargin}px`,\n        ...generatePatternStyles(bgColor),\n      }}\n      data-testid={`carousel-page-preview-skeleton-${pageId}`}\n    />\n  );\n}\n\nexport default SkeletonPage;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { THEME_CONSTANTS } from '@googleforcreators/design-system';\n\n// If the workspace is wider than this limit, this margin will be applied to the right\nexport const VERY_WIDE_WORKSPACE_LIMIT = 1000;\nexport const VERY_WIDE_MARGIN = 8;\n\nexport const FOOTER_MARGIN = 16;\nexport const FOOTER_TOP_MARGIN = FOOTER_MARGIN;\nexport const FOOTER_BOTTOM_MARGIN = FOOTER_MARGIN;\n\nexport const FOOTER_MENU_GAP = 8;\n\nexport const KEYBOARD_SHORTCUTS_PADDING = 3;\n\nconst BORDER_WIDTH = 1;\nconst KEYBOARD_SHORTCUTS_WIDTH =\n  THEME_CONSTANTS.ICON_SIZE + 2 * KEYBOARD_SHORTCUTS_PADDING + 2 * BORDER_WIDTH;\nconst LARGE_BUTTON_WIDTH = THEME_CONSTANTS.LARGE_BUTTON_SIZE + 2 * BORDER_WIDTH;\n\n// What's the max space required for either menu? The widest possible menu is\n// the secondary one with two large buttons + shortcuts button + 2 gaps + right margin:\nexport const MAX_MENU_WIDTH =\n  2 * LARGE_BUTTON_WIDTH +\n  2 * KEYBOARD_SHORTCUTS_WIDTH +\n  2 * FOOTER_MENU_GAP +\n  FOOTER_MARGIN;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/footer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  memo,\n  useMemo,\n  useRef,\n  useState,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { ChecklistProvider } from '../checklist';\nimport { KeyboardShortcutsMenuProvider } from '../keyboardShortcutsMenu/keyboardShortcutsMenuContext';\nimport FooterLayout from './footerLayout';\nimport { VERY_WIDE_WORKSPACE_LIMIT, VERY_WIDE_MARGIN } from './constants';\n\nconst Outer = styled.section`\n  height: 100%;\n`;\nconst Inner = styled(Outer)`\n  margin-right: ${({ marginRight }) => marginRight}px;\n`;\n\nfunction Footer({ footer, zIndex }) {\n  const ref = useRef();\n  const [workspaceWidth, setWorkspaceWidth] = useState(0);\n\n  useResizeEffect(ref, ({ width }) => setWorkspaceWidth(width), []);\n  const margin = useMemo(\n    () => (workspaceWidth >= VERY_WIDE_WORKSPACE_LIMIT ? VERY_WIDE_MARGIN : 0),\n    [workspaceWidth]\n  );\n\n  return (\n    <ChecklistProvider>\n      <KeyboardShortcutsMenuProvider>\n        <Outer ref={ref}>\n          <Inner marginRight={margin}>\n            <FooterLayout footer={footer} zIndex={zIndex} />\n          </Inner>\n        </Outer>\n      </KeyboardShortcutsMenuProvider>\n    </ChecklistProvider>\n  );\n}\n\nFooter.propTypes = {\n  footer: PropTypes.object,\n  zIndex: PropTypes.number,\n};\n\n// Don't rerender the workspace footer needlessly e.g. on element selection change.\nexport default memo(Footer);\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/footerLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport DirectionAware from '../directionAware';\nimport Carousel from './carousel';\nimport PrimaryMenu from './primaryMenu';\nimport SecondaryMenu from './secondaryMenu';\nimport { MAX_MENU_WIDTH } from './constants';\n\nconst Wrapper = styled.section`\n  position: relative;\n  display: grid;\n  grid:\n    /* Note the two empty 1fr areas each side of the buttons - that's on purpose */\n    'secondary carousel primary' auto /\n    1fr\n    minmax(auto, calc(100% - ${3 * MAX_MENU_WIDTH}px))\n    1fr;\n  width: 100%;\n  max-width: 100%;\n  height: 100%;\n`;\n\nconst Area = styled.div`\n  grid-area: ${({ area }) => area};\n  display: flex;\n  align-items: flex-end;\n  justify-content: center;\n  z-index: ${({ zIndex = 'auto' }) => zIndex};\n`;\n\nfunction FooterLayout({ footer, zIndex }) {\n  return (\n    <DirectionAware>\n      <Wrapper aria-label={__('Workspace Footer', 'web-stories')}>\n        <Area area=\"carousel\">\n          <Carousel />\n        </Area>\n        <Area area=\"primary\" zIndex={zIndex}>\n          <PrimaryMenu />\n        </Area>\n        <Area area=\"secondary\" zIndex={zIndex}>\n          <SecondaryMenu menu={footer?.secondaryMenu} />\n        </Area>\n      </Wrapper>\n    </DirectionAware>\n  );\n}\n\nFooterLayout.propTypes = {\n  footer: PropTypes.object,\n  zIndex: PropTypes.number,\n};\n\nexport default FooterLayout;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/gridview/gridView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useState,\n  useRef,\n  useCallback,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { FULLBLEED_RATIO } from '@googleforcreators/units';\nimport {\n  Slider,\n  Button,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n  Icons,\n  useGridViewKeys,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig, useStory } from '../../../app';\nimport {\n  Reorderable,\n  ReorderableSeparator,\n  ReorderableItem,\n} from '../../reorderable';\nimport PagePreview from '../pagepreview';\nimport { Z_INDEX_GRID_VIEW_SLIDER } from '../../../constants/zIndex';\n\nconst MIN_GRID_GAP = 20;\nconst LINE_HEIGHT = 64;\n\nconst Container = styled.section`\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  width: 100%;\n  padding: 32px;\n`;\n\nconst TopRow = styled.header`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  margin-bottom: 36px;\n  @media ${({ theme }) => theme.breakpoint.desktop} {\n    margin-bottom: 72px;\n  }\n  @media ${({ theme }) => theme.breakpoint.wide} {\n    margin-bottom: 112px;\n  }\n`;\n\nconst Wrapper = styled(Reorderable)`\n  position: relative;\n  overflow-y: auto;\n  overflow-x: hidden;\n  flex-grow: 1;\n  display: flex;\n  flex-direction: column;\n  pointer-events: all;\n  padding: 4px;\n`;\n\nconst Grid = styled.div`\n  position: relative;\n  display: grid;\n  grid-template-columns: ${({ pageWidth }) =>\n    `repeat(auto-fit, minmax(${pageWidth}px, max-content))`};\n  grid-template-rows: repeat(auto-fill, ${({ pageHeight }) => pageHeight}px);\n  grid-gap: ${({ gapWidth }) => gapWidth}px;\n  justify-content: center;\n  align-items: flex-start;\n  flex-grow: 1;\n`;\n\nconst NoButton = styled.div`\n  flex: 0 0 56px;\n`;\n\nconst ClickableButton = styled(Button)`\n  pointer-events: all;\n`;\n\nconst ClickableSlider = styled(Slider)`\n  pointer-events: all;\n  width: 366px;\n`;\n\nconst PageSeparator = styled(ReorderableSeparator)`\n  position: absolute;\n  bottom: 0;\n  left: ${({ width }) => width / 2}px;\n  width: ${({ width, margin }) => width + margin}px;\n  height: ${({ height }) => height}px;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n\n  ${({ before, width, margin }) =>\n    before &&\n    `\n      left: -${(width + 2 * margin) / 2}px;\n    `}\n`;\n\nconst Line = styled.div`\n  background: ${({ theme }) => theme.colors.border.selection};\n  height: ${({ height }) => height}px;\n  width: 2px;\n  margin: 0px;\n`;\n\nconst ItemContainer = styled.div`\n  display: flex;\n  flex-direction: row;\n  position: relative;\n`;\n\nfunction GridView({ onClose }) {\n  const {\n    pages,\n    currentPageId,\n    currentPageIndex,\n    setCurrentPage,\n    arrangePage,\n  } = useStory(\n    ({\n      state: { pages, currentPageIndex, currentPageId },\n      actions: { setCurrentPage, arrangePage },\n    }) => ({\n      pages,\n      currentPageIndex,\n      currentPageId,\n      setCurrentPage,\n      arrangePage,\n    })\n  );\n\n  const { isRTL } = useConfig();\n  const [pagesPerRow, setPagesPerRow] = useState(4);\n  const [availableWidth, setAvailableWidth] = useState(null);\n  const wrapperRef = useRef();\n\n  // Get updated size of wrapper\n  useResizeEffect(wrapperRef, ({ width }) => setAvailableWidth(width), []);\n\n  // Calculate max page width that can fit on the page\n  const minGaps = MIN_GRID_GAP * (pagesPerRow - 1);\n  const rawPageWidth = (availableWidth - minGaps) / pagesPerRow;\n\n  const pageWidth = Math.floor(rawPageWidth / 12) * 12;\n  const actualPageWidths = pageWidth * pagesPerRow;\n  const pageGridGap = Math.floor(\n    (availableWidth - actualPageWidths) / (pagesPerRow - 1)\n  );\n  const pageHeight = pageWidth / FULLBLEED_RATIO;\n\n  const handleClickPage = (page) => () => setCurrentPage({ pageId: page.id });\n\n  const gridRef = useRef();\n  const pagesRef = useRef({});\n\n  const arrangeItem = useCallback(\n    (focusedPageId, nextIndex) => {\n      arrangePage({ pageId: focusedPageId, position: nextIndex });\n    },\n    [arrangePage]\n  );\n\n  useGridViewKeys({\n    containerRef: wrapperRef,\n    gridRef,\n    itemRefs: pagesRef,\n    isRTL,\n    currentItemId: currentPageId,\n    items: pages,\n    arrangeItem,\n  });\n\n  // actual divider height should be smaller than page height, but no more than LINE_HEIGHT\n  const dividerLineHeight = Math.min(pageHeight - 24, LINE_HEIGHT);\n\n  return (\n    <Container aria-label={__('Grid View', 'web-stories')}>\n      <TopRow>\n        <ClickableButton\n          variant={ButtonVariant.Square}\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Medium}\n          onClick={onClose}\n          aria-label={__('Close', 'web-stories')}\n        >\n          <Icons.Cross />\n        </ClickableButton>\n        <ClickableSlider\n          min={4}\n          max={12}\n          majorStep={1}\n          minorStep={1}\n          value={pagesPerRow}\n          handleChange={(newValue) => setPagesPerRow(newValue)}\n          aria-label={__('Pages per row', 'web-stories')}\n          popupZIndexOverride={Z_INDEX_GRID_VIEW_SLIDER}\n        />\n        <NoButton />\n      </TopRow>\n      <Wrapper\n        aria-label={__('Grid View Pages List', 'web-stories')}\n        ref={wrapperRef}\n        onPositionChange={({ position: oldPos }, { position: newPos }) => {\n          const pageId = pages[oldPos].id;\n          arrangePage({ pageId, position: newPos });\n          setCurrentPage({ pageId });\n        }}\n        mode={'grid'}\n        getItemSize={() => pageHeight}\n        scrollSize={64}\n      >\n        <Grid\n          pageWidth={pageWidth}\n          pageHeight={pageHeight}\n          gapWidth={pageGridGap}\n          ref={gridRef}\n        >\n          {pages.map((page, index) => {\n            const isCurrentPage = index === currentPageIndex;\n            const isInteractive = pages.length > 1;\n\n            return (\n              <ItemContainer\n                key={page.id}\n                ref={(el) => {\n                  pagesRef.current[page.id] = el;\n                }}\n              >\n                <PageSeparator\n                  position={index}\n                  width={pageWidth}\n                  height={pageHeight}\n                  margin={pageGridGap}\n                  before\n                >\n                  <Line height={dividerLineHeight} />\n                </PageSeparator>\n                <ReorderableItem position={index}>\n                  <PagePreview\n                    label={\n                      isCurrentPage\n                        ? sprintf(\n                            /* translators: %s: page number. */\n                            __('Page %s (current page)', 'web-stories'),\n                            index + 1\n                          )\n                        : sprintf(\n                            /* translators: %s: page number. */\n                            __('Page %s', 'web-stories'),\n                            index + 1\n                          )\n                    }\n                    tabIndex={isCurrentPage && isInteractive ? 0 : -1}\n                    isActive={isCurrentPage && isInteractive}\n                    page={page}\n                    width={pageWidth}\n                    height={pageHeight}\n                    onClick={handleClickPage(page)}\n                    isInteractive={isInteractive}\n                    gridRef={gridRef}\n                    role=\"option\"\n                  />\n                </ReorderableItem>\n                <PageSeparator\n                  position={index + 1}\n                  width={pageWidth}\n                  height={pageHeight}\n                  margin={pageGridGap}\n                >\n                  <Line height={dividerLineHeight} />\n                </PageSeparator>\n              </ItemContainer>\n            );\n          })}\n        </Grid>\n      </Wrapper>\n    </Container>\n  );\n}\n\nGridView.propTypes = {\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default GridView;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/gridview/gridViewButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons, Modal, Placement } from '@googleforcreators/design-system';\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../tooltip';\nimport { ToggleButton } from '../../toggleButton';\nimport GridView from './gridView';\n\nconst Box = styled.div`\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nfunction GridViewButton() {\n  const [isGridViewOpen, setIsGridViewOpen] = useState(false);\n\n  const toggleModal = useCallback(() => {\n    setIsGridViewOpen((prevIsOpen) => {\n      const newIsOpen = !prevIsOpen;\n\n      trackEvent('grid_view_toggled', {\n        status: newIsOpen ? 'open' : 'closed',\n      });\n\n      return newIsOpen;\n    });\n  }, [setIsGridViewOpen]);\n\n  return (\n    <>\n      <Box>\n        <Tooltip\n          title={__('Grid View', 'web-stories')}\n          placement={Placement.Top}\n          hasTail\n        >\n          <ToggleButton\n            isOpen={isGridViewOpen}\n            onClick={toggleModal}\n            aria-owns=\"gridview_modal\"\n            MainIcon={Icons.Box4}\n            aria-label={__('Grid View', 'web-stories')}\n            label={__('Grid View', 'web-stories')}\n          />\n        </Tooltip>\n      </Box>\n      <Modal\n        isOpen={isGridViewOpen}\n        onClose={toggleModal}\n        contentLabel={__('Grid View', 'web-stories')}\n        popupId=\"gridview_modal\"\n        overlayStyles={{\n          alignItems: 'stretch',\n          backgroundColor: '#131516', // theme.colors.brand.gray[90]\n        }}\n        contentStyles={{\n          pointerEvents: 'none',\n          flex: 1,\n        }}\n      >\n        <GridView onClose={toggleModal} />\n      </Modal>\n    </>\n  );\n}\n\nexport default GridViewButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/gridview/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as GridViewButton } from './gridViewButton';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/gridview/karma/gridView.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitForElementToBeRemoved } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useStory } from '../../../../app';\n\ndescribe('GridView integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    fixture.setPages([\n      { id: 'page1', backgroundColor: createSolid(255, 255, 255) },\n      { id: 'page2', backgroundColor: createSolid(255, 0, 0) },\n      { id: 'page3', backgroundColor: createSolid(0, 255, 0) },\n      { id: 'page4', backgroundColor: createSolid(0, 0, 255) },\n    ]);\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    await fixture.events.click(fixture.editor.footer.gridViewToggle);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getPageIds() {\n    const {\n      state: { pages },\n    } = await fixture.renderHook(() => useStory());\n    return pages.map(({ id }) => id);\n  }\n\n  async function getCurrentPageId() {\n    const {\n      state: { currentPageId },\n    } = await fixture.renderHook(() => useStory());\n\n    return currentPageId;\n  }\n\n  it('should open grid view', () => {\n    expect(fixture.editor.gridView.node).toBeTruthy();\n  });\n\n  it('should have no aXe violations', async () => {\n    await expectAsync(fixture.editor.gridView.node).toHaveNoViolations();\n  });\n\n  it('should use tab to jump between the \"Back\" button, Preview Size control, and page list', async () => {\n    // Tab cycle: Back -> Page Size range -> Active/previously focused Page in Page List\n\n    // Back Button\n    await fixture.events.keyboard.press('tab');\n    expect(fixture.editor.gridView.close).toHaveFocus();\n\n    // Page Size range\n    await fixture.events.keyboard.press('tab');\n    expect(fixture.editor.gridView.size).toHaveFocus();\n\n    // Active/previously fcoused page in Page List\n    await fixture.events.keyboard.press('tab');\n    expect(fixture.editor.gridView.currentPage).toHaveFocus();\n  });\n\n  // @todo test wrapping + up down\n  it('should use the up, down, left, right keys to navigate focus with wrapping', async () => {\n    // Tab thrice to focus the current page in the page list\n    await fixture.events.keyboard.seq(({ press }) => [\n      press('tab'),\n      press('tab'),\n      press('tab'),\n    ]);\n\n    // The initial focus should be on the first (and active) page.\n    expect(fixture.editor.gridView.page('Page 1')).toHaveFocus();\n    expect(fixture.editor.gridView.currentPage).toHaveFocus();\n\n    // go right by 1\n    await fixture.events.keyboard.press('right');\n    expect(fixture.editor.gridView.page('Page 2')).toHaveFocus();\n\n    // go left 1\n    await fixture.events.keyboard.press('left');\n    expect(fixture.editor.gridView.page('Page 1')).toHaveFocus();\n\n    // go left 1 (focus should remain on page 1)\n    await fixture.events.keyboard.press('left');\n    expect(fixture.editor.gridView.page('Page 1')).toHaveFocus();\n\n    // go right 3 (the end of the list)\n    await fixture.events.keyboard.seq(({ press }) => [\n      press('right'),\n      press('right'),\n      press('right'),\n    ]);\n    expect(fixture.editor.gridView.page('Page 4')).toHaveFocus();\n\n    // go right 1 (focus should remain on page 4)\n    await fixture.events.keyboard.press('right');\n    expect(fixture.editor.gridView.page('Page 4')).toHaveFocus();\n  });\n\n  // @todo test wrapping + up down\n  it('should reorder the pages using mod+left/right, mod+up/down and use shift+mod+dir to reorder to first/last', async () => {\n    const initialPageIds = await getPageIds();\n    let pageIds = [...initialPageIds];\n\n    // Tab thrice to focus the current page in the page list\n    await fixture.events.keyboard.seq(({ press }) => [\n      press('tab'),\n      press('tab'),\n      press('tab'),\n    ]);\n\n    // The initial focus should be on the first (and active) page.\n    expect(fixture.editor.gridView.page('Page 1')).toHaveFocus();\n\n    // move the first page to the right\n    await fixture.events.keyboard.shortcut('mod+right');\n    pageIds = await getPageIds();\n    expect(pageIds[1]).toEqual(initialPageIds[0]);\n\n    // move the first page back to the start\n    await fixture.events.keyboard.shortcut('mod+left');\n    pageIds = await getPageIds();\n    expect(pageIds).toEqual(initialPageIds);\n\n    // move the first page to the end\n    await fixture.events.keyboard.shortcut('shift+mod+right');\n    pageIds = await getPageIds();\n    expect(pageIds[pageIds.length - 1]).toEqual(initialPageIds[0]);\n\n    // focus on the penultimate page\n    await fixture.events.keyboard.press('left');\n    expect(fixture.editor.gridView.page('Page 3')).toHaveFocus();\n\n    // move page 4 to the start\n    await fixture.events.keyboard.shortcut('shift+mod+left');\n    pageIds = await getPageIds();\n    expect(pageIds[0]).toEqual(initialPageIds[3]);\n  });\n\n  it('should select the focused page when \"Enter\" is pressed', async () => {\n    // Tab thrice to focus the current page in the page list\n    await fixture.events.keyboard.seq(({ press }) => [\n      press('tab'),\n      press('tab'),\n      press('tab'),\n    ]);\n\n    const initialPageIds = await getPageIds();\n    const page2Id = initialPageIds[1];\n\n    // Focus on page 2\n    await fixture.events.keyboard.press('right');\n\n    // Press enter and make page 2 the active/selected page\n    await fixture.events.keyboard.press('Enter');\n\n    const currentPage = await getCurrentPageId();\n\n    expect(currentPage).toEqual(page2Id);\n  });\n\n  it('should trap focus', async () => {\n    // Tab cycle: Back -> Page Size range -> Active/previously focused Page in Page List\n\n    // Full cycle forwards\n    await fixture.events.keyboard.seq(({ press }) => [\n      press('tab'),\n      press('tab'),\n      press('tab'),\n      press('tab'),\n    ]);\n\n    expect(fixture.editor.gridView.close).toHaveFocus();\n  });\n\n  // TODO: https://github.com/googleforcreators/web-stories-wp/issues/10146\n  // eslint-disable-next-line jasmine/no-disabled-tests\n  xit('should use \"Esc\" to exit the dialog', async () => {\n    const { gridView } = fixture.editor;\n    expect(gridView.node).toBeTruthy();\n    await fixture.events.keyboard.press('Esc');\n    await waitForElementToBeRemoved(gridView.node);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/gridview/test/gridview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent } from '@testing-library/react';\nimport {\n  queryByAriaLabel,\n  renderWithTheme,\n} from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport GridView from '../gridView';\nimport { noop } from '../../../../utils/noop';\n\njest.mock('../../../../app/pageCanvas', () => {\n  const usePageCanvasMock = (selector) => {\n    return selector({\n      state: {\n        pageCanvasMap: {},\n      },\n      actions: {\n        generateDeferredPageCanvas: () => {},\n      },\n    });\n  };\n  return {\n    default: ({ children }) => children,\n    usePageCanvas: usePageCanvasMock,\n  };\n});\n\nfunction setupGridView() {\n  const setCurrentPage = jest.fn();\n  const arrangePage = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      currentPageIndex: 0,\n      pages: [\n        {\n          id: 'foo',\n          elements: [],\n        },\n        {\n          id: 'bar',\n          elements: [],\n        },\n      ],\n    },\n    actions: { setCurrentPage, arrangePage },\n  };\n  const { container } = renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <GridView onClose={noop} />\n    </StoryContext.Provider>\n  );\n  return {\n    container,\n    setCurrentPage,\n    arrangePage,\n  };\n}\n\ndescribe('Grid View', () => {\n  it('should change the current page upon selection', () => {\n    const { container, setCurrentPage } = setupGridView();\n    const secondPage = queryByAriaLabel(container, 'Page 2');\n\n    fireEvent.click(secondPage);\n    expect(setCurrentPage).toHaveBeenCalledWith({ pageId: 'bar' });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './footer';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/karma/footerMenu.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('Footer menu', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should have no aXe violations', async () => {\n    await expectAsync(fixture.editor.footer.node).toHaveNoViolations();\n  });\n\n  it('should show correct tooltip on hover', async () => {\n    const { gridViewToggle } = fixture.editor.footer;\n    await fixture.events.mouse.moveRel(gridViewToggle, '50%', '50%', {\n      steps: 2,\n    });\n\n    await fixture.snapshot('Grid view tooltip visible');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/karma/popups.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('Popup Menus - Help Center, KeyboardShortcuts, and Checklist', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should start with help center open', () => {\n    const { helpCenterToggle, checklistToggle, keyboardShortcutsToggle } =\n      fixture.editor.footer;\n\n    expect(helpCenterToggle).toBeDefined();\n    expect(checklistToggle).toBeDefined();\n    expect(keyboardShortcutsToggle).toBeDefined();\n    expect(fixture.editor.helpCenter.quickTips).toBeDefined();\n  });\n\n  it('should collapse help center and keyboard shortcuts when checklist is expanded', async () => {\n    const { checklistToggle } = fixture.editor.footer;\n\n    await fixture.events.click(checklistToggle);\n    await fixture.events.sleep(300); // allow transition to play out\n\n    expect(\n      fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n    ).toBe('true');\n    expect(fixture.editor.helpCenter.quickTips).toBeNull();\n    expect(fixture.editor.keyboardShortcuts.keyboardShortcutsMenu).toBeNull();\n  });\n\n  it('should collapse checklist when helpCenter is expanded', async () => {\n    const { helpCenterToggle, checklistToggle } = fixture.editor.footer;\n\n    await fixture.events.click(checklistToggle);\n    await fixture.events.sleep(300);\n    expect(\n      fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n    ).toBe('true');\n    expect(fixture.editor.helpCenter.quickTips).toBeNull();\n\n    await fixture.events.click(helpCenterToggle);\n\n    const { quickTips } = await fixture.editor.helpCenter;\n\n    await fixture.events.sleep(300);\n\n    expect(quickTips).toBeDefined();\n  });\n\n  it('should collapse checklist and help center when keyboard shortcuts menu is expanded', async () => {\n    const { checklistToggle, keyboardShortcutsToggle } = fixture.editor.footer;\n\n    await fixture.events.click(checklistToggle);\n    await fixture.events.sleep(300);\n\n    expect(\n      fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n    ).toBe('true');\n    expect(fixture.editor.helpCenter.quickTips).toBeNull();\n\n    await fixture.events.click(keyboardShortcutsToggle);\n\n    await fixture.events.sleep(300);\n\n    const { keyboardShortcutsMenu } = await fixture.editor.keyboardShortcuts;\n\n    expect(keyboardShortcutsMenu).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/karma/zoomSelector.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('Zoom selector', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    // Add an image to the canvas to make it more visual when things move\n    await fixture.events.mouse.clickOn(\n      fixture.editor.library.media.item(0),\n      20,\n      20\n    );\n\n    // Add some matchers not generally useful, but applicable in this file\n    jasmine.addMatchers({\n      toBeVerticallyScrollable: () => ({\n        compare: (actual) => {\n          const { scrollHeight, clientHeight } = actual;\n          const pass = scrollHeight > clientHeight;\n          return {\n            pass,\n            message: pass\n              ? `Expected element to not be vertically scrollable, but overflows ${\n                  clientHeight - scrollHeight\n                } pixels`\n              : `Expected element to be vertically scrollable`,\n          };\n        },\n      }),\n      toBeHorizontallyScrollable: () => ({\n        compare: (actual) => {\n          const { scrollWidth, clientWidth } = actual;\n          const pass = scrollWidth > clientWidth;\n          return {\n            pass,\n            message: pass\n              ? `Expected element to not be horizontally scrollable, but overflows ${\n                  clientWidth - scrollWidth\n                } pixels`\n              : `Expected element to be horizontally scrollable`,\n          };\n        },\n      }),\n      toHaveSize: () => ({\n        compare: (actual, width, height) => {\n          const { clientWidth, clientHeight } = actual;\n          // 1px differences due to rounding are OK.\n          const pass =\n            Math.abs(clientWidth - width) <= 1 &&\n            Math.abs(clientHeight - height) <= 1;\n          return {\n            pass,\n            message: pass\n              ? `Expected element to not be ${width}x${height} pixels`\n              : `Expected element to be ${width}x${height} pixels, but found it to be ${clientWidth}x${clientHeight} pixels`,\n          };\n        },\n      }),\n    });\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should always show zoom selector in primary menu', () => {\n    const { zoomSelector } = fixture.editor.footer;\n    expect(zoomSelector).not.toBeNull();\n  });\n\n  it('should default set zoom to FIT and have no scroll', async () => {\n    const { zoomSelector } = fixture.editor.footer;\n    expect(zoomSelector.node).toHaveTextContent('Fit');\n\n    const { scrollContainer } = fixture.editor.canvas.framesLayer;\n    expect(scrollContainer).not.toBeVerticallyScrollable();\n    expect(scrollContainer).not.toBeHorizontallyScrollable();\n\n    await fixture.snapshot();\n  });\n\n  it('should allow setting zoom to 100% and work correctly', async () => {\n    const { zoomSelector } = fixture.editor.footer;\n\n    await fixture.events.click(zoomSelector.select);\n    await fixture.events.sleep(300);\n    await fixture.events.click(await zoomSelector.option('100%'));\n    await fixture.events.sleep(300);\n\n    const { scrollContainer, fullbleed } = fixture.editor.canvas.framesLayer;\n    // 100% is actually smaller than FIT because we are using such a large browser window\n    expect(scrollContainer).not.toBeVerticallyScrollable();\n    expect(scrollContainer).not.toBeHorizontallyScrollable();\n\n    expect(fullbleed).toHaveSize(408, 725);\n\n    await fixture.snapshot();\n  });\n\n  it('should allow setting zoom to FILL and work correctly', async () => {\n    const { zoomSelector } = fixture.editor.footer;\n\n    await fixture.events.click(zoomSelector.select);\n    await fixture.events.sleep(300);\n    await fixture.events.click(await zoomSelector.option('Fill'));\n    await fixture.events.sleep(300);\n\n    const { scrollContainer } = fixture.editor.canvas.framesLayer;\n    expect(scrollContainer).toBeVerticallyScrollable();\n    expect(scrollContainer).not.toBeHorizontallyScrollable();\n\n    await fixture.snapshot();\n  });\n\n  it('should allow setting zoom to 200% and work correctly', async () => {\n    const { zoomSelector } = fixture.editor.footer;\n\n    await fixture.events.click(zoomSelector.select);\n    await fixture.events.sleep(300);\n    await fixture.events.click(await zoomSelector.option('200%'));\n    await fixture.events.sleep(300);\n\n    const { scrollContainer, fullbleed } = fixture.editor.canvas.framesLayer;\n    // 200% still isn't big enough to force a horizontal scrollbar\n    expect(scrollContainer).toBeVerticallyScrollable();\n    expect(scrollContainer).not.toBeHorizontallyScrollable();\n\n    expect(fullbleed).toHaveSize(816, 1451);\n\n    await fixture.snapshot();\n\n    // Scroll down by 100px in the frame scroll container and validate, that the display\n    // scroll container is offset the same amount\n    const { fullbleed: displayFullbleed } = fixture.editor.canvas.displayLayer;\n    scrollContainer.scrollBy(0, 100);\n    expect(scrollContainer.scrollTop).toBe(100);\n\n    // Wait for scroll event to be handled\n    await fixture.events.sleep(100);\n    expect(displayFullbleed).toHaveStyle('top', '-100px');\n\n    await fixture.snapshot('Scrolled 100px down');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/layers/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './layers';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/layers/layers.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useState, useRef, useEffect } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { Placement } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_FOOTER } from '../../../constants/zIndex';\nimport { LayerPanel } from '../../panels/layer';\nimport Popup, { NavigationWrapper } from '../../secondaryPopup';\nimport { ToggleButton } from '../../toggleButton';\nimport { useCanvas, useStory } from '../../../app';\n\nconst Container = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  overflow: auto;\n  z-index: ${Z_INDEX_FOOTER};\n`;\n\nconst StyledNavigationWrapper = styled(NavigationWrapper)`\n  width: 260px;\n`;\n\nfunction Layers() {\n  const numElements = useStory(\n    ({ state }) => state.currentPage?.elements?.length\n  );\n  const [isOpen, setIsOpen] = useState(false);\n  const ref = useRef();\n  const { renamableLayer } = useCanvas(({ state }) => ({\n    renamableLayer: state.renamableLayer,\n  }));\n\n  useEffect(() => {\n    if (renamableLayer) {\n      setIsOpen(true);\n    }\n  }, [renamableLayer]);\n\n  return (\n    <>\n      <Popup\n        isOpen={isOpen}\n        placement={Placement.Right}\n        ariaLabel={__('Layers Panel', 'web-stories')}\n      >\n        <StyledNavigationWrapper alignRight ref={ref} isOpen={isOpen}>\n          <Container>\n            <LayerPanel />\n          </Container>\n        </StyledNavigationWrapper>\n      </Popup>\n      <ToggleButton\n        hasMenuList\n        isOpen={isOpen}\n        notificationCount={numElements}\n        copy={__('Layers', 'web-stories')}\n        onClick={() => setIsOpen((state) => !state)}\n        aria-label={sprintf(\n          /* translators: %d: number of layers */\n          __('Layers (%d)', 'web-stories'),\n          numElements\n        )}\n      />\n    </>\n  );\n}\n\nexport default Layers;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/pagepreview/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { rgba } from 'polished';\nimport PropTypes from 'prop-types';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport {\n  PAGE_RATIO,\n  FULLBLEED_RATIO,\n  UnitsProvider,\n} from '@googleforcreators/units';\nimport {\n  useState,\n  useEffect,\n  useCallback,\n  useMemo,\n} from '@googleforcreators/react';\nimport { TransformProvider } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../../propTypes';\nimport { usePageCanvas } from '../../../app/pageCanvas';\nimport DisplayElement from '../../canvas/displayElement';\nimport usePerformanceTracking from '../../../utils/usePerformanceTracking';\nimport { TRACKING_EVENTS } from '../../../constants';\n\nconst Page = styled.button`\n  display: block;\n  position: relative;\n  cursor: ${({ isInteractive }) => (isInteractive ? 'pointer' : 'default')};\n  padding: 0;\n  border: 0;\n  background-color: transparent;\n  height: ${({ height }) => height}px;\n  width: ${({ width }) => width}px;\n  flex: none;\n  outline: 0;\n\n  &::after {\n    content: '';\n    display: block;\n    position: absolute;\n    left: -4px;\n    right: -4px;\n    top: -4px;\n    bottom: -4px;\n    pointer-events: none;\n    border-style: solid;\n    border-width: 1px;\n    border-radius: 8px;\n    border-color: ${({ isActive, isInteractive, theme }) =>\n      isInteractive && isActive\n        ? theme.colors.border.defaultActive\n        : 'transparent'};\n  }\n\n  ${({ isInteractive, isActive, theme }) =>\n    isInteractive &&\n    css`\n      &:focus::after {\n        border-color: ${rgba(\n          theme.colors.border.selection,\n          isActive ? 1 : 0.7\n        )};\n      }\n    `}\n`;\n\nconst PageOffset = styled.div`\n  position: relative;\n  top: ${({ $top }) => $top}px;\n`;\n\nconst PreviewWrapper = styled.div`\n  height: 100%;\n  position: relative;\n  overflow: hidden;\n  background-color: white;\n  border-radius: 4px;\n  ${({ background }) => generatePatternStyles(background)}\n`;\n\nconst Image = styled.img`\n  position: absolute;\n  width: 100%;\n  left: 0;\n\n  /*\n   image will always be vertically centered\n   so we don't need to alter height of image\n   when it's in the fullbleed ratio and the\n   thumbnail is in the smaller ratio\n  */\n  top: 50%;\n  transform: translateY(-50%);\n`;\n\nfunction PagePreview({ page, label, ...props }) {\n  const { backgroundColor } = page;\n  const { width, isActive } = props;\n\n  const height = Math.round(width / PAGE_RATIO);\n  const fullHeight = Math.round(width / FULLBLEED_RATIO);\n  const pageYOffset = (fullHeight - height) / 2;\n\n  const { pageCanvas, generateDeferredPageCanvas } = usePageCanvas(\n    ({ state, actions }) => ({\n      pageCanvas: state.pageCanvasMap[page.id],\n      generateDeferredPageCanvas: actions.generateDeferredPageCanvas,\n    })\n  );\n  const [pageNode, setPageNode] = useState();\n  const setPageRef = useCallback((node) => node && setPageNode(node), []);\n\n  // Generate a canvas if we don't have one\n  useEffect(() => {\n    // Avoid frequent generation of active pages as well\n    // due to rapid cache invalidation from frequent updates\n    // to page.\n    if (isActive || pageCanvas) {\n      return;\n    }\n\n    generateDeferredPageCanvas([page.id, page]);\n  }, [page, pageCanvas, isActive, generateDeferredPageCanvas]);\n\n  // Grab image off of canvas if we got a canvas\n  // from the cache\n  const pageImage = useMemo(\n    () => pageCanvas?.toDataURL('image/png'),\n    [pageCanvas]\n  );\n\n  usePerformanceTracking({\n    node: pageNode,\n    eventData: TRACKING_EVENTS.PAGE_PREVIEW_CLICK,\n  });\n\n  return (\n    <UnitsProvider pageSize={{ width, height }}>\n      <TransformProvider>\n        <Page\n          ref={setPageRef}\n          aria-label={label}\n          height={fullHeight}\n          {...props}\n        >\n          <PreviewWrapper background={backgroundColor}>\n            {pageImage ? (\n              <Image\n                draggable=\"false\"\n                src={pageImage}\n                alt={label}\n                decoding=\"async\"\n              />\n            ) : (\n              <PageOffset $top={pageYOffset}>\n                {page.elements.map((element) => (\n                  <DisplayElement\n                    key={element.id}\n                    previewMode\n                    element={element}\n                  />\n                ))}\n              </PageOffset>\n            )}\n          </PreviewWrapper>\n        </Page>\n      </TransformProvider>\n    </UnitsProvider>\n  );\n}\n\nPagePreview.propTypes = {\n  page: StoryPropTypes.page.isRequired,\n  label: PropTypes.string,\n  width: PropTypes.number.isRequired,\n  isInteractive: PropTypes.bool,\n  isActive: PropTypes.bool,\n  tabIndex: PropTypes.number,\n};\n\nexport default PagePreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/primaryMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_FOOTER } from '../../constants/zIndex';\nimport ZoomSelector from './zoomSelector';\nimport { GridViewButton } from './gridview';\nimport Layers from './layers';\nimport { FOOTER_MENU_GAP, FOOTER_MARGIN } from './constants';\nimport ToolbarToggle from './toolbarToggle';\n\nconst Wrapper = styled.div`\n  display: flex;\n  align-items: flex-end;\n  justify-content: flex-end;\n  width: 100%;\n  height: 100%;\n  z-index: ${Z_INDEX_FOOTER};\n`;\n\nconst MenuItems = styled.div`\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  margin-right: ${FOOTER_MARGIN}px;\n  gap: ${FOOTER_MENU_GAP}px;\n`;\n\nfunction PrimaryMenu() {\n  return (\n    <Wrapper>\n      {/* This ID is used for portal rendering of additional menu items, e.g. for custom meta boxes */}\n      <MenuItems id=\"primary-menu-items\">\n        <ToolbarToggle />\n        <ZoomSelector />\n        <GridViewButton />\n        <Layers />\n      </MenuItems>\n    </Wrapper>\n  );\n}\n\nexport default PrimaryMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/secondaryMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useCallback, useEffect, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport KeyboardShortcutsMenu from '../keyboardShortcutsMenu';\nimport { HelpCenter } from '../helpCenter';\nimport { useCanvas, useHelpCenter } from '../../app';\nimport { Checklist, useChecklist, useCheckpoint } from '../checklist';\nimport { useKeyboardShortcutsMenu } from '../keyboardShortcutsMenu/keyboardShortcutsMenuContext';\nimport { FOOTER_MENU_GAP, FOOTER_MARGIN } from './constants';\n\nconst Wrapper = styled.div`\n  display: flex;\n  align-items: flex-end;\n  justify-content: flex-start;\n  width: 100%;\n  height: 100%;\n`;\n\nconst MenuItems = styled.div`\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  margin-left: ${FOOTER_MARGIN}px;\n  gap: ${FOOTER_MENU_GAP}px;\n`;\n\nconst POPUPS = {\n  HELP_CENTER: 'help_center',\n  CHECKLIST: 'checklist',\n  KEYBOARD_SHORTCUTS: 'keyboard_shortcuts',\n};\n\nfunction SecondaryMenu({ menu }) {\n  const expandedPopupRef = useRef('');\n\n  const { close: closeHelpCenter, isHelpCenterOpen } = useHelpCenter(\n    ({ actions: { close }, state: { isOpen: isHelpCenterOpen } }) => ({\n      close,\n      isHelpCenterOpen,\n    })\n  );\n\n  const {\n    close: closeChecklist,\n    open: openChecklist,\n    isChecklistOpen,\n  } = useChecklist(\n    ({ actions: { close, open }, state: { isOpen: isChecklistOpen } }) => ({\n      close,\n      open,\n      isChecklistOpen,\n    })\n  );\n\n  const { close: closeKeyboardShortcutsMenu, isKeyboardShortcutsMenuOpen } =\n    useKeyboardShortcutsMenu(\n      ({\n        actions: { close },\n        state: { isOpen: isKeyboardShortcutsMenuOpen },\n      }) => ({\n        close,\n        isKeyboardShortcutsMenuOpen,\n      })\n    );\n\n  const { handleResetReviewChecklist, reviewChecklistRequested } =\n    useCheckpoint(\n      ({\n        actions: { handleResetReviewChecklist },\n        state: { reviewChecklistRequested },\n      }) => ({\n        reviewChecklistRequested,\n        handleResetReviewChecklist,\n      })\n    );\n\n  const isActiveTrimOrEdit = useCanvas(\n    ({\n      state: {\n        editingElementState: { isTrimMode },\n        isEditing,\n      },\n    }) => isTrimMode || isEditing\n  );\n\n  const setPopupRef = useCallback((newPopup = '') => {\n    expandedPopupRef.current = newPopup;\n  }, []);\n\n  // Only one popup is open at a time\n  // we want to close an open popup if a new one is opened.\n  useEffect(() => {\n    if (isChecklistOpen && expandedPopupRef.current !== POPUPS.CHECKLIST) {\n      closeHelpCenter();\n      closeKeyboardShortcutsMenu();\n      setPopupRef(POPUPS.CHECKLIST);\n    }\n  }, [\n    closeHelpCenter,\n    closeKeyboardShortcutsMenu,\n    isChecklistOpen,\n    setPopupRef,\n  ]);\n\n  useEffect(() => {\n    if (isHelpCenterOpen && expandedPopupRef.current !== POPUPS.HELP_CENTER) {\n      closeChecklist();\n      closeKeyboardShortcutsMenu();\n      setPopupRef(POPUPS.HELP_CENTER);\n    }\n  }, [\n    closeChecklist,\n    closeKeyboardShortcutsMenu,\n    isHelpCenterOpen,\n    setPopupRef,\n  ]);\n\n  useEffect(() => {\n    if (\n      isKeyboardShortcutsMenuOpen &&\n      expandedPopupRef.current !== POPUPS.KEYBOARD_SHORTCUTS\n    ) {\n      closeChecklist();\n      closeHelpCenter();\n      setPopupRef(POPUPS.KEYBOARD_SHORTCUTS);\n    }\n  }, [\n    closeChecklist,\n    closeHelpCenter,\n    isKeyboardShortcutsMenuOpen,\n    setPopupRef,\n  ]);\n\n  useEffect(() => {\n    if (reviewChecklistRequested) {\n      setPopupRef();\n      handleResetReviewChecklist();\n      openChecklist();\n    }\n  }, [\n    reviewChecklistRequested,\n    handleResetReviewChecklist,\n    openChecklist,\n    setPopupRef,\n  ]);\n\n  // The checklist and help center will stay open as user interacts with canvas\n  // we want to collapse either of these if expanded when the trim or cropping mode is selected.\n  useEffect(() => {\n    if (isActiveTrimOrEdit && expandedPopupRef.current) {\n      setPopupRef();\n      closeChecklist();\n      closeHelpCenter();\n    }\n  }, [closeChecklist, closeHelpCenter, isActiveTrimOrEdit, setPopupRef]);\n\n  return (\n    <Wrapper>\n      <MenuItems>\n        <HelpCenter components={menu?.helpCenter} />\n        {menu?.checklist && <Checklist items={menu.checklist} />}\n        <KeyboardShortcutsMenu />\n      </MenuItems>\n    </Wrapper>\n  );\n}\n\nSecondaryMenu.propTypes = {\n  menu: PropTypes.shape({\n    checklist: PropTypes.object,\n    helpCenter: PropTypes.object,\n  }),\n};\n\nexport default SecondaryMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/toolbarToggle.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Icons,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n  Placement,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../tooltip';\nimport { useCanvas } from '../../app';\nimport { states, useHighlights } from '../../app/highlights';\nimport styles from '../../app/highlights/styles';\nimport { ToggleButton } from '../toggleButton';\n\nconst StyledButton = styled(ToggleButton)`\n  ${({ isHighlighted }) =>\n    isHighlighted &&\n    css`\n      ${styles.OUTLINE}\n      ${styles.FLASH}\n    `}\n`;\n\nconst LOCAL_STORAGE_KEY = LOCAL_STORAGE_PREFIX.ELEMENT_TOOLBAR_SETTINGS;\n\nfunction ToolbarToggle() {\n  const { displayFloatingMenu, setDisplayFloatingMenu } = useCanvas(\n    ({ state, actions }) => ({\n      displayFloatingMenu: state.displayFloatingMenu,\n      setDisplayFloatingMenu: actions.setDisplayFloatingMenu,\n    })\n  );\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.ElementToolbarToggle],\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const handleToolbarVisibility = () => {\n    const local = localStore.getItemByKey(LOCAL_STORAGE_KEY) || {};\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, {\n      ...local,\n      isDisplayed: true,\n    });\n    setDisplayFloatingMenu(true);\n  };\n\n  // We only display the button for showing the toolbar.\n  if (displayFloatingMenu) {\n    return null;\n  }\n  return (\n    <Tooltip\n      title={__('Show element toolbar', 'web-stories')}\n      placement={Placement.Top}\n      hasTail\n    >\n      <StyledButton\n        ref={(node) => {\n          if (node && highlight?.focus && highlight?.showEffect) {\n            node.focus();\n          }\n        }}\n        onClick={handleToolbarVisibility}\n        aria-label={__('Show element toolbar', 'web-stories')}\n        label={__('Show element toolbar', 'web-stories')}\n        isOpen={false}\n        isHighlighted={highlight?.showEffect}\n        onAnimationEnd={() => resetHighlight()}\n        MainIcon={Icons.BoxWithDots}\n      />\n    </Tooltip>\n  );\n}\n\nexport default ToolbarToggle;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/useFooterHeight.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../app';\nimport { CarouselState } from '../../constants';\nimport {\n  DRAWER_BUTTON_HEIGHT,\n  DRAWER_BUTTON_GAP_EXPANDED,\n  DRAWER_BUTTON_GAP_COLLAPSED,\n  WIDE_THUMBNAIL_HEIGHT,\n} from './carousel/constants';\nimport { FOOTER_TOP_MARGIN } from './constants';\n\nfunction useFooterHeight() {\n  // Footer height is exclusively determined by the carousel height + some fixed top margin\n  const { carouselState } = useLayout(({ state: { carouselState } }) => ({\n    carouselState,\n  }));\n\n  if (carouselState === CarouselState.Closed) {\n    // Collapsed - height is only carousel button height + collapsed gap both top and bottom\n    return (\n      FOOTER_TOP_MARGIN + DRAWER_BUTTON_HEIGHT + DRAWER_BUTTON_GAP_COLLAPSED * 2\n    );\n  }\n  // Expanded or collapsed/expanding - height is button + wide gap + max thumbnail height\n  return (\n    FOOTER_TOP_MARGIN +\n    DRAWER_BUTTON_HEIGHT +\n    DRAWER_BUTTON_GAP_EXPANDED +\n    WIDE_THUMBNAIL_HEIGHT\n  );\n}\n\nexport default useFooterHeight;\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/zoomSelector/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './zoomSelector';\n"
  },
  {
    "path": "packages/story-editor/src/components/footer/zoomSelector/zoomSelector.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { css } from 'styled-components';\nimport { __, _x, sprintf } from '@googleforcreators/i18n';\nimport {\n  BUTTON_TRANSITION_TIMING,\n  DropDown,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ZoomSetting } from '../../../constants';\nimport { useLayout } from '../../../app/layout';\n\n// Styles updated so the Zoom selector matches the other footer buttons\nconst selectButtonCSS = css`\n  width: 80px;\n  height: 36px;\n  padding: 0 10px;\n  border-width: 1px;\n  border-style: solid;\n  border-color: ${({ theme }) => theme.colors.border.defaultNormal};\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  transition: background-color ${BUTTON_TRANSITION_TIMING};\n\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: ${({ theme }) => theme.colors.bg.secondary};\n    background-color: ${({ theme }) => theme.colors.bg.tertiary};\n  }\n\n  span {\n    height: 100%;\n    padding: 0;\n    display: flex;\n    align-items: center;\n  }\n\n  svg {\n    margin: 0 -10px;\n  }\n`;\n\nconst ZOOM_OPTIONS = [\n  {\n    label: _x('100%', 'zoom level', 'web-stories'),\n    value: 1,\n  },\n  {\n    label: _x('200%', 'zoom level', 'web-stories'),\n    value: 2,\n  },\n  { label: _x('Fill', 'zoom level', 'web-stories'), value: ZoomSetting.Fill },\n  { label: _x('Fit', 'zoom level', 'web-stories'), value: ZoomSetting.Fit },\n];\n\nfunction ZoomSelector() {\n  const { zoomSetting, zoomLevel, setZoomSetting, setZoomLevel } = useLayout(\n    ({\n      state: { zoomSetting, zoomLevel },\n      actions: { setZoomSetting, setZoomLevel },\n    }) => ({\n      zoomSetting,\n      zoomLevel,\n      setZoomSetting,\n      setZoomLevel,\n    })\n  );\n\n  const placeholder = useMemo(() => {\n    const option = ZOOM_OPTIONS.find(({ value }) => {\n      if (zoomSetting === ZoomSetting.Fixed) {\n        return value === zoomLevel;\n      }\n      return value === zoomSetting;\n    });\n    if (option) {\n      return option.label;\n    }\n\n    return sprintf(\n      /* translators: %d: zoom level percentage value. */\n      _x('%d%%', 'zoom level', 'web-stories'),\n      Math.round(zoomLevel * 100)\n    );\n  }, [zoomSetting, zoomLevel]);\n\n  const handleSetZoom = useCallback(\n    (_event, value) => {\n      if (Object.values(ZoomSetting).includes(value)) {\n        setZoomSetting(value);\n      } else {\n        setZoomLevel(value);\n      }\n    },\n    [setZoomSetting, setZoomLevel]\n  );\n\n  return (\n    <DropDown\n      ariaLabel={__('Zoom Level', 'web-stories')}\n      placeholder={placeholder}\n      options={ZOOM_OPTIONS}\n      placement={Placement.TopStart}\n      onMenuItemClick={handleSetZoom}\n      selectedValue={zoomSetting}\n      popupFillWidth={false}\n      selectButtonStylesOverride={selectButtonCSS}\n      className=\"zoom-selector-dropdown\"\n    />\n  );\n}\n\nexport default ZoomSelector;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/activeOpacity.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { PatternPropType } from '@googleforcreators/patterns';\nimport { __ } from '@googleforcreators/i18n';\nimport { CONTEXT_MENU_SKIP_ELEMENT } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport {\n  default as FocusTrapButton,\n  handleReturnTrappedFocus,\n} from '../../floatingMenu/elements/shared/focusTrapButton';\nimport OpacityInput from './opacityInput';\n\nconst OpacityWrapper = styled.div`\n  width: ${({ isInDesignMenu }) =>\n    isInDesignMenu ? 'calc(39% - 10px)' : 'calc(47% - 10px)'};\n`;\n\nconst ActiveOpacity = ({\n  handleOpacityChange,\n  isInDesignMenu,\n  opacityFocusTrap,\n  tabIndex,\n  value,\n}) => {\n  const opacityFocusTrapButtonRef = useRef();\n  const opacityFocusTrapRef = useRef();\n\n  return opacityFocusTrap ? (\n    <FocusTrapButton\n      ref={opacityFocusTrapButtonRef}\n      inputRef={opacityFocusTrapRef}\n      inputLabel={__('Opacity', 'web-stories')}\n      styleOverride={css`\n        width: ${isInDesignMenu ? 'calc(35%)' : 'calc(45%)'};\n      `}\n    >\n      <OpacityWrapper isInDesignMenu={isInDesignMenu}>\n        <OpacityInput\n          ref={opacityFocusTrapRef}\n          tabIndex={tabIndex}\n          inputClassName={CONTEXT_MENU_SKIP_ELEMENT}\n          value={value}\n          onChange={handleOpacityChange}\n          isInDesignMenu={isInDesignMenu}\n          onKeyDown={(e) =>\n            handleReturnTrappedFocus(e, opacityFocusTrapButtonRef)\n          }\n        />\n      </OpacityWrapper>\n    </FocusTrapButton>\n  ) : (\n    <OpacityWrapper isInDesignMenu={isInDesignMenu}>\n      <OpacityInput\n        tabIndex={tabIndex}\n        value={value}\n        onChange={handleOpacityChange}\n        isInDesignMenu={isInDesignMenu}\n      />\n    </OpacityWrapper>\n  );\n};\n\nActiveOpacity.propTypes = {\n  handleOpacityChange: PropTypes.func,\n  isInDesignMenu: PropTypes.bool,\n  opacityFocusTrap: PropTypes.bool,\n  tabIndex: PropTypes.number,\n  value: PropTypes.oneOfType([PatternPropType, PropTypes.string]),\n};\n\nexport default ActiveOpacity;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/applyOpacityChange.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction applyOpacityChange(pattern, newOpacity) {\n  if (!pattern) {\n    return null;\n  }\n\n  const { type } = pattern;\n\n  // Return the same color, just with opacity applied\n  if (!type || type === 'solid') {\n    const {\n      color: { r, g, b },\n    } = pattern;\n    return { color: { r, g, b, a: newOpacity } };\n  }\n\n  // Return gradient with opacity applied\n  return {\n    ...pattern,\n    alpha: newOpacity,\n  };\n}\n\nexport default applyOpacityChange;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/color.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef, useCallback } from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { getPreviewText, PatternPropType } from '@googleforcreators/patterns';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  Placement,\n} from '@googleforcreators/design-system';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../../constants';\nimport useEyedropper from '../../eyedropper';\nimport Tooltip from '../../tooltip';\nimport { focusStyle } from '../../panels/shared/styles';\n\nimport applyOpacityChange from './applyOpacityChange';\nimport ColorInput from './colorInput';\nimport ActiveOpacity from './activeOpacity';\nimport { SPACING } from './constants';\n\nconst containerCss = css`\n  display: flex;\n  align-items: center;\n`;\n\nconst Container = styled.section`\n  ${containerCss}\n  gap: ${({ isInDesignMenu }) => (isInDesignMenu ? 6 : 8)}px;\n  width: ${({ width }) => (width ? `${width}px` : 'inherit')};\n`;\nContainer.propTypes = {\n  isInDesignMenu: PropTypes.bool,\n  width: PropTypes.number,\n};\n\nconst ColorInputsWrapper = styled.div`\n  ${containerCss}\n  gap: ${({ isInDesignMenu }) => (isInDesignMenu ? 0 : 6)}px;\n`;\n\nconst Space = styled.div`\n  width: 8px;\n  height: 1px;\n  background-color: ${({ theme }) => theme.colors.divider.primary};\n`;\n\n// 10px comes from divider / 2\nconst InputWrapper = styled.div`\n  ${({ hasInputs }) => hasInputs && `width: calc(53% - 10px);`}\n`;\n\nconst EyeDropperButton = styled(Button).attrs({\n  variant: ButtonVariant.Square,\n  type: ButtonType.Tertiary,\n  size: ButtonSize.Small,\n})`\n  ${focusStyle};\n`;\n\nconst DEFAULT_CONTAINER_LABEL_BASE = __('Color input', 'web-stories');\n\nconst Color = forwardRef(function Color(\n  {\n    onChange,\n    allowsGradient = false,\n    allowsOpacity = true,\n    allowsSavedColors = false,\n    value = null,\n    label = null,\n    containerLabelBase = DEFAULT_CONTAINER_LABEL_BASE,\n    changedStyle = null,\n    hasEyedropper = false,\n    pickerHasEyedropper = true,\n    maxHeight = null,\n    shouldCloseOnSelection = false,\n    allowsSavedColorDeletion = true,\n    pickerPlacement = Placement.RightStart,\n    isInDesignMenu = false,\n    hasInputs = true,\n    width,\n    tabIndex,\n    opacityFocusTrap,\n    colorFocusTrap,\n  },\n  ref\n) {\n  const handleOpacityChange = useCallback(\n    (newOpacity) => onChange(applyOpacityChange(value, newOpacity)),\n    [value, onChange]\n  );\n\n  const containerLabel = sprintf(\n    /* translators: 1: the input section in the editor. 2: color input label name. */\n    __('%1$s: %2$s', 'web-stories'),\n    containerLabelBase,\n    label\n  );\n\n  const displayOpacity =\n    value !== MULTIPLE_VALUE && Boolean(getPreviewText(value)) && hasInputs;\n\n  const { initEyedropper } = useEyedropper({\n    onChange: useCallback((color) => onChange({ color }), [onChange]),\n  });\n\n  const tooltip = __('Pick a color from canvas', 'web-stories');\n\n  const tooltipPlacement =\n    isInDesignMenu || hasEyedropper ? Placement.Bottom : Placement.BottomStart;\n\n  // Sometimes there's more than 1 color to an element.\n  // When there's multiple colors the input displays \"Mixed\" (in english) and takes up a different amount of space.\n  // By checking here to ignore that value based on mixed colors we prevent visual spill over of content.\n  const ignoreSetWidth = width && value === MULTIPLE_VALUE;\n\n  return (\n    <Container\n      aria-label={containerLabel}\n      isInDesignMenu={isInDesignMenu}\n      width={!ignoreSetWidth && width ? width : null}\n    >\n      {hasEyedropper && (\n        <Tooltip\n          title={tooltip}\n          hasTail\n          placement={isInDesignMenu ? Placement.Bottom : Placement.BottomStart}\n        >\n          <EyeDropperButton\n            id={uuidv4()}\n            tabIndex={tabIndex}\n            aria-label={tooltip}\n            onClick={initEyedropper()}\n            onPointerEnter={initEyedropper(false)}\n          >\n            <Icons.Pipette />\n          </EyeDropperButton>\n        </Tooltip>\n      )}\n\n      <ColorInputsWrapper isInDesignMenu={isInDesignMenu}>\n        <InputWrapper hasInputs={hasInputs}>\n          <ColorInput\n            ref={ref}\n            tabIndex={tabIndex}\n            onChange={onChange}\n            value={value}\n            label={label}\n            changedStyle={changedStyle}\n            pickerPlacement={pickerPlacement}\n            hasInputs={hasInputs}\n            isInDesignMenu={isInDesignMenu}\n            spacing={\n              isInDesignMenu ? SPACING.FLOATING_MENU : SPACING.DEFAULT_SIDEBAR\n            }\n            tooltipPlacement={tooltipPlacement}\n            colorFocusTrap={colorFocusTrap}\n            pickerProps={{\n              allowsGradient,\n              allowsOpacity,\n              allowsSavedColors,\n              hasEyedropper: pickerHasEyedropper,\n              allowsSavedColorDeletion,\n              maxHeight,\n              shouldCloseOnSelection,\n            }}\n          />\n        </InputWrapper>\n        {allowsOpacity && displayOpacity && (\n          <>\n            <Space />\n            <ActiveOpacity\n              handleOpacityChange={handleOpacityChange}\n              isInDesignMenu={isInDesignMenu}\n              opacityFocusTrap={opacityFocusTrap}\n              tabIndex={tabIndex}\n              value={value}\n            />\n          </>\n        )}\n      </ColorInputsWrapper>\n    </Container>\n  );\n});\n\nColor.propTypes = {\n  value: PropTypes.oneOfType([PatternPropType, PropTypes.string]),\n  allowsGradient: PropTypes.bool,\n  allowsOpacity: PropTypes.bool,\n  allowsSavedColors: PropTypes.bool,\n  containerLabelBase: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n  label: PropTypes.string.isRequired,\n  changedStyle: PropTypes.string,\n  hasEyedropper: PropTypes.bool,\n  pickerHasEyedropper: PropTypes.bool,\n  maxHeight: PropTypes.number,\n  shouldCloseOnSelection: PropTypes.bool,\n  allowsSavedColorDeletion: PropTypes.bool,\n  pickerPlacement: PropTypes.string,\n  isInDesignMenu: PropTypes.bool,\n  hasInputs: PropTypes.bool,\n};\n\nexport default Color;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/colorInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  forwardRef,\n  useCallback,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  getPreviewText,\n  getOpaquePattern,\n  PatternPropType,\n} from '@googleforcreators/patterns';\nimport {\n  HexInput,\n  Text,\n  TextSize,\n  Swatch,\n  Popup,\n  Disclosure,\n  Placement,\n  CONTEXT_MENU_SKIP_ELEMENT,\n} from '@googleforcreators/design-system';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport {\n  default as FocusTrapButton,\n  handleReturnTrappedFocus,\n} from '../../floatingMenu/elements/shared/focusTrapButton';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../constants';\nimport ColorPicker from '../../colorPicker';\nimport useSidebar from '../../sidebar/useSidebar';\nimport DefaultTooltip from '../../tooltip';\nimport {\n  focusStyle,\n  inputContainerStyleOverride,\n} from '../../panels/shared/styles';\nimport { useCanvas, useConfig } from '../../../app';\n\nconst Preview = styled.div`\n  height: 36px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  cursor: pointer;\n  position: relative;\n  width: 100%;\n  padding: 0;\n`;\n\nconst Input = styled(HexInput)`\n  min-width: 100px;\n  div {\n    background-color: transparent;\n  }\n  input {\n    padding-left: 26px;\n  }\n`;\n\nconst Tooltip = styled(DefaultTooltip)`\n  width: 100%;\n  height: 100%;\n`;\n\nconst buttonAttrs = {\n  as: 'button',\n  type: 'button', // avoid submitting forms\n};\n\nconst minimalInputContainerStyleOverride = css`\n  ${inputContainerStyleOverride};\n  padding-right: 6px;\n`;\n\nconst ColorButton = styled(Preview).attrs(buttonAttrs)`\n  display: flex;\n  overflow: hidden;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  border-radius: 4px;\n  outline: none;\n  background: transparent;\n\n  &:focus {\n    box-shadow:\n      0 0 0 2px ${({ theme }) => theme.colors.bg.primary},\n      0 0 0 4px ${({ theme }) => theme.colors.border.focus};\n    border-color: ${({ theme }) => theme.colors.border.defaultHover};\n  }\n`;\n\nconst ColorPreview = styled.div`\n  position: absolute;\n  top: 6px;\n  left: 6px;\n  padding: 0;\n  width: 24px;\n  height: 24px;\n  background: transparent;\n  border-radius: 50px;\n  cursor: pointer;\n`;\n\nconst TextualPreview = styled.div`\n  padding: 6px 12px 6px 38px;\n  text-align: left;\n  flex-grow: 1;\n  height: 32px;\n`;\n\nconst MixedLabel = styled(TextualPreview)`\n  align-self: center;\n  padding: 6px 6px 6px 38px;\n`;\n\nconst StyledSwatch = styled(Swatch)`\n  ${focusStyle};\n`;\n\nconst DisclosureContainer = styled.div`\n  width: ${({ isSmall }) => (isSmall ? '28px' : '58px')};\n  padding-right: 8px;\n  display: flex;\n  justify-content: ${({ isSmall }) => (isSmall ? 'center' : 'flex-end')};\n  align-items: center;\n  align-self: center;\n`;\n\nconst loadReactColor = () =>\n  import(\n    /* webpackChunkName: \"chunk-react-color\" */\n    /* webpackExports: [\"Hue\", \"Saturation\", \"Alpha\", \"CustomPicker\", \"EditableInput\"] */\n    '@hello-pangea/color-picker'\n  );\n\nconst ColorInput = forwardRef(function ColorInput(\n  {\n    onChange,\n    value = null,\n    label = null,\n    changedStyle,\n    pickerPlacement = Placement.RightStart,\n    isInDesignMenu = false,\n    hasInputs = true,\n    pickerProps,\n    spacing,\n    tooltipPlacement,\n    colorFocusTrap = false,\n    ...props\n  },\n  ref\n) {\n  /**\n   * isolate the ref used for color input that\n   * is nested in a focus trap(when colorFocusTrap is true).\n   * This preserves existing color input functionality outside\n   * of floating menu while letting floating menu use\n   * the logic for the color input and do its own thing with focus.\n   */\n  const focusTrapInputRef = useRef();\n\n  const colorFocusTrapButtonRef = useRef();\n  const isMixed = value === MULTIPLE_VALUE;\n  value = isMixed ? '' : value;\n\n  const previewPattern = !value\n    ? { color: { r: 0, g: 0, b: 0, a: 0 } }\n    : getOpaquePattern(value);\n  const previewText = getPreviewText(value);\n\n  const [pickerOpen, setPickerOpen] = useState(false);\n  const previewRef = useRef(null);\n\n  const { isEyedropperActive } = useCanvas(\n    ({ state: { isEyedropperActive } }) => ({\n      isEyedropperActive,\n    })\n  );\n  const [dynamicPlacement, setDynamicPlacement] = useState(pickerPlacement);\n\n  const {\n    refs: { sidebar },\n  } = useSidebar();\n\n  const { styleConstants: { topOffset } = {} } = useConfig();\n\n  const positionPlacement = useCallback(\n    (popupRef) => {\n      // if the popup was assigned as top as in the case of floating menus, we want to check that it will fit\n      if (pickerPlacement?.startsWith('top')) {\n        // check to see if there's an overlap with the window edge\n        const { top } = popupRef.current?.getBoundingClientRect() || {};\n        if (top <= topOffset) {\n          setDynamicPlacement(pickerPlacement.replace('top', 'bottom'));\n        }\n      }\n    },\n    [pickerPlacement, topOffset]\n  );\n\n  const colorType = value?.type;\n  // Allow editing always in case of solid color of if color type is missing (mixed)\n  const isEditable = (!colorType || colorType === 'solid') && hasInputs;\n\n  const buttonProps = {\n    onClick: () => setPickerOpen(true),\n    'aria-label': label,\n    onPointerEnter: () => loadReactColor(),\n    onFocus: () => loadReactColor(),\n    tabIndex: props.tabIndex,\n  };\n\n  const onClose = useCallback(() => setPickerOpen(false), []);\n\n  const tooltip = __('Open color picker', 'web-stories');\n\n  const containerStyle = isInDesignMenu\n    ? minimalInputContainerStyleOverride\n    : inputContainerStyleOverride;\n\n  return (\n    <>\n      {isEditable ? (\n        // If editable, only the visual preview component is a button\n        // And the text is an input field\n        <Preview ref={previewRef}>\n          {colorFocusTrap ? (\n            <FocusTrapButton\n              ref={colorFocusTrapButtonRef}\n              inputRef={focusTrapInputRef}\n              inputLabel={label}\n            >\n              <Input\n                ref={focusTrapInputRef}\n                aria-label={label}\n                value={isMixed ? null : value}\n                onChange={onChange}\n                isIndeterminate={isMixed}\n                placeholder={isMixed ? MULTIPLE_DISPLAY_VALUE : ''}\n                containerStyleOverride={containerStyle}\n                id={uuidv4()}\n                onKeyDown={(e) =>\n                  handleReturnTrappedFocus(e, colorFocusTrapButtonRef)\n                }\n                inputClassName={CONTEXT_MENU_SKIP_ELEMENT}\n                {...props}\n              />\n            </FocusTrapButton>\n          ) : (\n            <Input\n              ref={ref}\n              aria-label={label}\n              value={isMixed ? null : value}\n              onChange={onChange}\n              isIndeterminate={isMixed}\n              placeholder={isMixed ? MULTIPLE_DISPLAY_VALUE : ''}\n              containerStyleOverride={containerStyle}\n              id={uuidv4()}\n              {...props}\n            />\n          )}\n          <ColorPreview>\n            <Tooltip title={tooltip} hasTail placement={tooltipPlacement}>\n              <StyledSwatch\n                isSmall\n                pattern={previewPattern}\n                id={uuidv4()}\n                {...buttonProps}\n              />\n            </Tooltip>\n          </ColorPreview>\n        </Preview>\n      ) : (\n        // If not editable, the whole component is a button\n        <Tooltip title={tooltip} hasTail placement={tooltipPlacement}>\n          <ColorButton ref={previewRef} id={uuidv4()} {...buttonProps}>\n            <ColorPreview>\n              <Swatch\n                isPreview\n                role=\"status\"\n                tabIndex=\"-1\"\n                pattern={previewPattern}\n                isIndeterminate={isMixed}\n              />\n            </ColorPreview>\n            {hasInputs ? (\n              <TextualPreview>\n                <Text.Paragraph size={TextSize.Small}>\n                  {previewText}\n                </Text.Paragraph>\n              </TextualPreview>\n            ) : (\n              <>\n                {/* We display Mixed value even without inputs */}\n                {isMixed && (\n                  <MixedLabel>\n                    <Text.Span size={TextSize.Small}>\n                      {MULTIPLE_DISPLAY_VALUE}\n                    </Text.Span>\n                  </MixedLabel>\n                )}\n                <DisclosureContainer isSmall={isMixed}>\n                  <Disclosure $isOpen={pickerOpen} />\n                </DisclosureContainer>\n              </>\n            )}\n          </ColorButton>\n        </Tooltip>\n      )}\n      <Popup\n        anchor={previewRef}\n        dock={isInDesignMenu ? null : sidebar}\n        isOpen={pickerOpen && !isEyedropperActive}\n        placement={dynamicPlacement}\n        spacing={spacing}\n        refCallback={positionPlacement}\n        renderContents={({ propagateDimensionChange }) => (\n          <ColorPicker\n            color={isMixed ? null : value}\n            isEyedropperActive={isEyedropperActive}\n            onChange={onChange}\n            onClose={onClose}\n            changedStyle={changedStyle}\n            onDimensionChange={propagateDimensionChange}\n            {...pickerProps}\n          />\n        )}\n      />\n    </>\n  );\n});\n\nColorInput.propTypes = {\n  value: PropTypes.oneOfType([PatternPropType, PropTypes.string]),\n  pickerProps: PropTypes.object,\n  onChange: PropTypes.func.isRequired,\n  label: PropTypes.string,\n  changedStyle: PropTypes.string,\n  pickerPlacement: PropTypes.string,\n  isInDesignMenu: PropTypes.bool,\n  hasInputs: PropTypes.bool,\n  spacing: PropTypes.object,\n  tooltipPlacement: PropTypes.string,\n};\n\nexport default ColorInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const SPACING = {\n  FLOATING_MENU: { x: 0, y: 12 },\n  DEFAULT_SIDEBAR: { x: 12, y: 0 },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/getPreviewOpacity.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../../constants';\n\nfunction getPreviewOpacity(pattern) {\n  if (!pattern || pattern === MULTIPLE_VALUE) {\n    return null;\n  }\n  const isSolidPattern = pattern.type === 'solid' || !pattern.type;\n  if (!isSolidPattern) {\n    const { alpha = 1 } = pattern;\n    return Math.round(alpha * 100);\n  }\n  const {\n    color: { a = 1 },\n  } = pattern;\n  return Math.round(a * 100);\n}\n\nexport default getPreviewOpacity;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/getPreviewStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createSolid,\n  generatePatternStyles,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../../constants';\n\nfunction getPreviewStyle(pattern) {\n  if (!pattern || pattern === MULTIPLE_VALUE) {\n    return {};\n  }\n  const isSolidPattern = pattern.type === 'solid' || !pattern.type;\n  if (!isSolidPattern) {\n    // Should filter out alpha component\n    const opaquePattern = { ...pattern, alpha: undefined };\n    return generatePatternStyles(opaquePattern);\n  }\n  const {\n    color: { r, g, b },\n  } = pattern;\n  return generatePatternStyles(createSolid(r, g, b));\n}\n\nexport default getPreviewStyle;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './color';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/opacityInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useEffect,\n  forwardRef,\n} from '@googleforcreators/react';\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { _x, __ } from '@googleforcreators/i18n';\nimport { PatternPropType } from '@googleforcreators/patterns';\nimport { NumericInput, Icons } from '@googleforcreators/design-system';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { inputContainerStyleOverride } from '../../panels/shared/styles';\nimport getPreviewOpacity from './getPreviewOpacity';\n\nconst Input = styled(NumericInput)`\n  min-width: 100px;\n  div {\n    background-color: transparent;\n  }\n`;\n\nconst minimalInputContainerStyleOverride = css`\n  ${inputContainerStyleOverride};\n  width: 76px;\n  padding-right: 6px;\n`;\n\nconst OpacityInput = forwardRef(function OpacityInput(\n  { value, onChange, isInDesignMenu, ...props },\n  ref\n) {\n  const [inputValue, setInputValue] = useState('');\n\n  // Allow any input, but only persist non-NaN values up-chain\n  const handleChange = useCallback(\n    (evt, val) => {\n      setInputValue(val);\n      if (!isNaN(val)) {\n        onChange(val / 100);\n      }\n    },\n    [onChange]\n  );\n\n  const updateFromValue = useCallback(\n    () => setInputValue(getPreviewOpacity(value)),\n    [value]\n  );\n\n  useEffect(() => updateFromValue(), [updateFromValue, value]);\n\n  const containerStyle = isInDesignMenu\n    ? minimalInputContainerStyleOverride\n    : inputContainerStyleOverride;\n\n  return (\n    <Input\n      ref={ref}\n      aria-label={__('Opacity', 'web-stories')}\n      onChange={handleChange}\n      value={inputValue}\n      unit={_x('%', 'Percentage', 'web-stories')}\n      suffix={<Icons.ColorDrop />}\n      min={0}\n      max={100}\n      allowEmpty={false}\n      isFloat={false}\n      containerStyleOverride={containerStyle}\n      id={uuidv4()}\n      {...props}\n    />\n  );\n});\n\nOpacityInput.propTypes = {\n  value: PropTypes.oneOfType([PatternPropType, PropTypes.string]),\n  onChange: PropTypes.func.isRequired,\n  isInDesignMenu: PropTypes.bool,\n};\n\nexport default OpacityInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { createGlobalStyle } from 'styled-components';\nimport { useState } from '@googleforcreators/react';\nimport {\n  ContextMenu,\n  ContextMenuComponents,\n  Icons,\n  Headline,\n  Text,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport Row from '../../row';\nimport Color from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Form/Color',\n  component: Color,\n};\n\nconst GlobalStyle = createGlobalStyle`\n  *, *::before, *::after {\n    box-sizing: border-box;\n  }\n`;\n\nconst Background = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  width: 100%;\n  height: 100vh;\n  position: relative;\n  z-index: 0;\n`;\n\nconst DesignPanelWrapper = styled.div`\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  width: 312px;\n  padding: 16px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n`;\n\nconst DesignMenuWrapper = styled.div`\n  padding: 50px;\n  display: flex;\n  height: 100%;\n  flex-direction: column;\n  align-items: center;\n  justify-content: flex-end;\n`;\n\nconst DesignMenuSingle = styled.div`\n  width: 600px;\n`;\n\nconst ContextMenuWrapper = styled.div`\n  display: flex;\n`;\n\nconst ColorInputWrapper = styled.div`\n  width: ${({ $width }) => $width}px;\n  flex: 0 0 ${({ $width }) => $width}px;\n`;\n\nfunction ColorInput({ initialColor, ...rest }) {\n  const [color, setColor] = useState(initialColor);\n\n  return <Color onChange={setColor} label=\"Color\" value={color} {...rest} />;\n}\n\nconst RED = { type: 'solid', color: { r: 255, g: 0, b: 0 } };\nconst BLUE = { type: 'solid', color: { r: 0, g: 0, b: 255 } };\nconst GREEN = { type: 'solid', color: { r: 0, g: 255, b: 0 } };\nconst YELLOW = { type: 'solid', color: { r: 255, g: 255, b: 0 } };\nconst MAGENTA = { type: 'solid', color: { r: 255, g: 0, b: 255 } };\nconst CYAN = { type: 'solid', color: { r: 0, g: 255, b: 255 } };\nconst RED_GREEN = {\n  type: 'linear',\n  stops: [\n    { color: { r: 255, g: 0, b: 0 }, position: 0 },\n    { color: { r: 0, g: 255, b: 0 }, position: 1 },\n  ],\n  rotation: 0.375,\n};\n\nfunction Wrapper({ children }) {\n  const [globalColors, setGlobalColors] = useState([RED, GREEN, BLUE]);\n  const [storyColors, setStoryColors] = useState([CYAN, MAGENTA, YELLOW]);\n  const updateStory = ({\n    properties: { globalStoryStyles, currentStoryStyles },\n  }) => {\n    if (globalStoryStyles) {\n      setGlobalColors(globalStoryStyles.colors);\n    }\n    if (currentStoryStyles) {\n      setStoryColors(currentStoryStyles.colors);\n    }\n  };\n  const storyContext = {\n    state: {\n      currentPage: {\n        background: RED,\n      },\n      selectedElements: [],\n      story: {\n        globalStoryStyles: {\n          colors: globalColors,\n        },\n        currentStoryStyles: {\n          colors: storyColors,\n        },\n      },\n    },\n    actions: {\n      updateStory,\n    },\n  };\n  return (\n    <StoryContext.Provider value={storyContext}>\n      <Background>\n        <GlobalStyle />\n        {children}\n      </Background>\n    </StoryContext.Provider>\n  );\n}\n\nfunction DesignPanelColorInput({ label, ...props }) {\n  return (\n    <>\n      <Text.Paragraph>{label}</Text.Paragraph>\n      <Row>\n        <ColorInput {...props} />\n      </Row>\n    </>\n  );\n}\n\nfunction DummyButton({ children }) {\n  return (\n    <ContextMenuComponents.MenuButton onClick={() => {}}>\n      <ContextMenuComponents.MenuIcon>\n        {children}\n      </ContextMenuComponents.MenuIcon>\n    </ContextMenuComponents.MenuButton>\n  );\n}\n\nfunction DesignMenuColorInput({ label, width, atStart = false, ...props }) {\n  return (\n    <DesignMenuSingle>\n      <Headline style={{ margin: '40px 0 10px' }}>{label}</Headline>\n      <ContextMenuWrapper>\n        <ContextMenu\n          isInline\n          isHorizontal\n          isSecondary\n          isAlwaysVisible\n          disableControlledTabNavigation\n          aria-label={label}\n        >\n          {atStart && (\n            <>\n              <ColorInputWrapper $width={width}>\n                <ColorInput {...props} />\n              </ColorInputWrapper>\n              <ContextMenuComponents.MenuSeparator />\n            </>\n          )}\n          <DummyButton>\n            <Icons.PictureSwap />\n          </DummyButton>\n          <ContextMenuComponents.MenuSeparator />\n          <DummyButton>\n            <Icons.Trash />\n          </DummyButton>\n          <DummyButton>\n            <Icons.ColorBucket />\n          </DummyButton>\n          <DummyButton>\n            <Icons.MirrorLeftRight />\n          </DummyButton>\n          <DummyButton>\n            <Icons.MirrorUpDown />\n          </DummyButton>\n          {!atStart && (\n            <>\n              <ContextMenuComponents.MenuSeparator />\n              <ColorInputWrapper $width={width}>\n                <ColorInput {...props} />\n              </ColorInputWrapper>\n            </>\n          )}\n          <ContextMenuComponents.MenuSeparator />\n          <DummyButton>\n            <Icons.Cross />\n          </DummyButton>\n        </ContextMenu>\n      </ContextMenuWrapper>\n    </DesignMenuSingle>\n  );\n}\n\nfunction DesignPanel({ style, pickerPlacement }) {\n  return (\n    <Wrapper>\n      <DesignPanelWrapper style={style}>\n        <DesignPanelColorInput\n          label=\"Without saved colors\"\n          initialColor={MAGENTA}\n          pickerPlacement={pickerPlacement}\n        />\n        <DesignPanelColorInput\n          label=\"With saved colors\"\n          initialColor={YELLOW}\n          allowsSavedColors\n          pickerPlacement={pickerPlacement}\n        />\n        <DesignPanelColorInput\n          label=\"With dropper\"\n          initialColor={BLUE}\n          hasEyedropper\n          pickerPlacement={pickerPlacement}\n        />\n        <DesignPanelColorInput\n          label=\"Without opacity\"\n          initialColor={CYAN}\n          allowsOpacity={false}\n          pickerPlacement={pickerPlacement}\n        />\n        <DesignPanelColorInput\n          label=\"With gradient\"\n          initialColor={RED_GREEN}\n          allowsGradient\n          pickerPlacement={pickerPlacement}\n        />\n      </DesignPanelWrapper>\n    </Wrapper>\n  );\n}\n\nexport function DesignPanelLeft() {\n  return (\n    <DesignPanel style={{ left: 0 }} pickerPlacement={Placement.RightStart} />\n  );\n}\n\nexport function DesignPanelRight() {\n  return <DesignPanel style={{ right: 0 }} />;\n}\n\nexport function DesignMenu() {\n  return (\n    <Wrapper>\n      <DesignMenuWrapper>\n        <DesignMenuColorInput\n          width={216}\n          atStart\n          label=\"All options\"\n          initialColor={RED}\n          // Params below are to the color input component\n          maxHeight={362}\n          pickerPlacement={Placement.TopStart}\n          isInDesignMenu\n          shouldCloseOnSelection\n          allowsSavedColors\n          allowsSavedColorDeletion={false}\n          hasEyedropper\n          pickerHasEyedropper={false}\n        />\n        <DesignMenuColorInput\n          width={98}\n          atStart\n          label=\"No inputs, with eyedropper\"\n          initialColor={BLUE}\n          // Params below are to the color input component\n          maxHeight={362}\n          pickerPlacement={Placement.TopStart}\n          isInDesignMenu\n          shouldCloseOnSelection\n          allowsSavedColors\n          allowsSavedColorDeletion={false}\n          hasInputs={false}\n          hasEyedropper\n          pickerHasEyedropper={false}\n        />\n        <DesignMenuColorInput\n          width={60}\n          atStart\n          label=\"No inputs, without eyedropper\"\n          initialColor={CYAN}\n          // Params below are to the color input component\n          maxHeight={362}\n          pickerPlacement={Placement.TopStart}\n          hasInputs={false}\n          isInDesignMenu\n          shouldCloseOnSelection\n          allowsSavedColors\n          allowsSavedColorDeletion={false}\n        />\n        <DesignMenuColorInput\n          width={60}\n          atStart\n          label=\"No inputs, allows gradient\"\n          initialColor={RED_GREEN}\n          // Params below are to the color input component\n          maxHeight={362}\n          pickerPlacement={Placement.TopStart}\n          hasInputs={false}\n          isInDesignMenu\n          shouldCloseOnSelection\n          allowsGradient\n          allowsSavedColors\n          allowsSavedColorDeletion={false}\n        />\n        <DesignMenuColorInput\n          width={60}\n          label=\"No inputs, to the right\"\n          initialColor={YELLOW}\n          // Params below are to the color input component\n          maxHeight={362}\n          pickerPlacement={Placement.TopStart}\n          hasInputs={false}\n          isInDesignMenu\n          shouldCloseOnSelection\n          allowsSavedColors\n          allowsSavedColorDeletion={false}\n        />\n      </DesignMenuWrapper>\n    </Wrapper>\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/applyOpacityChange.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\nimport applyOpacityChange from '../applyOpacityChange';\n\ndescribe('applyOpacityChange', () => {\n  it('should return null for no pattern', () => {\n    const pattern = null;\n    const opacity = 0.3;\n    const result = applyOpacityChange(pattern, opacity);\n    const expected = null;\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('should return solid with opacity applied', () => {\n    const pattern = createSolid(255, 0, 0);\n    const opacity = 0.3;\n    const result = applyOpacityChange(pattern, opacity);\n    const expected = createSolid(255, 0, 0, 0.3);\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('should return non-solid with alpha applied', () => {\n    const pattern = { type: 'linear', stops: [] };\n    const opacity = 0.3;\n    const result = applyOpacityChange(pattern, opacity);\n    const expected = { type: 'linear', stops: [], alpha: 0.3 };\n    expect(result).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/color.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { ConfigProvider } from '../../../../app/config';\nimport getDefaultConfig from '../../../../getDefaultConfig';\nimport { MULTIPLE_VALUE } from '../../../../constants';\nimport Color from '../color';\nimport applyOpacityChange from '../applyOpacityChange';\n\njest.mock('../applyOpacityChange', () => jest.fn());\n\nfunction arrange(props = {}) {\n  const onChange = jest.fn();\n  renderWithTheme(\n    <ConfigProvider config={getDefaultConfig()}>\n      <Color label=\"Color\" onChange={onChange} {...props} />\n    </ConfigProvider>\n  );\n  const colorPreview = screen.getByRole('button', { name: 'Color' });\n  const colorSection = screen.getByRole('region', {\n    name: 'Color input: Color',\n  });\n  const opacityInput = screen.queryByLabelText(/Opacity/);\n  return {\n    colorPreview,\n    colorSection,\n    opacityInput,\n    onChange,\n  };\n}\n\ndescribe('<Color />', () => {\n  it('should render both color preview and opacity input', () => {\n    const { colorPreview, opacityInput } = arrange({\n      value: createSolid(255, 0, 0),\n    });\n\n    expect(colorPreview).toBeInTheDocument();\n    expect(opacityInput).toBeInTheDocument();\n  });\n\n  it('should update via `applyOpacityChange` when opacity changes', () => {\n    const { opacityInput, onChange } = arrange({\n      value: createSolid(255, 0, 0),\n    });\n\n    applyOpacityChange.mockImplementationOnce(() =>\n      createSolid(255, 0, 0, 0.3)\n    );\n\n    fireEvent.change(opacityInput, { target: { value: '30' } });\n    fireEvent.blur(opacityInput);\n\n    expect(applyOpacityChange).toHaveBeenCalledWith(\n      createSolid(255, 0, 0),\n      0.3\n    );\n\n    expect(onChange).toHaveBeenCalledWith(createSolid(255, 0, 0, 0.3));\n  });\n\n  it(\"should pass 300 as width prop to the color's section when width is specified and current value is not mixed\", () => {\n    const { colorSection } = arrange({\n      value: createSolid(255, 0, 0),\n      width: 300,\n    });\n    expect(colorSection).toHaveAttribute('width', '300');\n  });\n\n  it(\"should pass false as width prop to the color's section when width is specified and current value is mixed\", () => {\n    const { colorSection } = arrange({\n      value: MULTIPLE_VALUE,\n      width: 300,\n    });\n    expect(colorSection).not.toHaveAttribute('width');\n  });\n\n  it(\"should pass null as width prop to the color's section when width is not specified and current value is mixed\", () => {\n    const { colorSection } = arrange({\n      value: MULTIPLE_VALUE,\n    });\n    expect(colorSection).not.toHaveAttribute('width');\n  });\n\n  it(\"should pass null as width prop to the color's section when width is not specified and current value is not mixed\", () => {\n    const { colorSection } = arrange({\n      value: createSolid(255, 0, 0),\n    });\n    expect(colorSection).not.toHaveAttribute('width');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/colorInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, waitFor } from '@testing-library/react';\nimport {\n  createSolid,\n  getPreviewText as getPreviewTextMock,\n} from '@googleforcreators/patterns';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport ColorInput from '../colorInput';\nimport getPreviewStyleMock from '../getPreviewStyle';\nimport { StoryContext } from '../../../../app/story';\nimport { ConfigContext } from '../../../../app/config';\nimport getDefaultConfig from '../../../../getDefaultConfig';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\n\njest.mock('../getPreviewStyle', () => jest.fn());\njest.mock('@googleforcreators/patterns', () => {\n  return {\n    ...jest.requireActual('@googleforcreators/patterns'),\n    getPreviewText: jest.fn(),\n  };\n});\n\nfunction arrange(children = null) {\n  const storyContextValue = {\n    state: {\n      story: {\n        globalStoryStyles: {\n          colors: [],\n          textStyles: [],\n        },\n        currentStoryStyles: {\n          colors: [],\n        },\n      },\n    },\n    actions: {\n      updateStory: jest.fn(),\n    },\n  };\n\n  renderWithTheme(\n    <ConfigContext.Provider value={getDefaultConfig()}>\n      <StoryContext.Provider value={storyContextValue}>\n        {children}\n      </StoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n  const button = screen.getByRole('button', { name: 'Color' });\n  const input = screen.queryByLabelText('Color', { selector: 'input' });\n  return {\n    button,\n    input,\n  };\n}\n\ndescribe('<ColorInput />', () => {\n  beforeEach(() => {\n    getPreviewStyleMock.mockReset();\n    getPreviewTextMock.mockReset();\n\n    getPreviewStyleMock.mockImplementation(() => {\n      return { backgroundColor: 'red' };\n    });\n  });\n\n  it('should render correct style and text', async () => {\n    getPreviewTextMock.mockImplementation(() => {\n      return 'FF0000';\n    });\n    const { button, input } = arrange(\n      <ColorInput\n        onChange={() => {}}\n        value={createSolid(255, 0, 0)}\n        label=\"Color\"\n      />\n    );\n\n    await waitFor(() => expect(button).toBeDefined());\n    expect(button).toHaveAttribute('aria-label', 'Color');\n\n    expect(input).toHaveValue('FF0000');\n  });\n\n  it('should render one big button if gradient', async () => {\n    getPreviewTextMock.mockImplementation(() => {\n      return 'Radial';\n    });\n\n    const { button, input } = arrange(\n      <ColorInput\n        onChange={() => {}}\n        value={{\n          type: 'radial',\n          stops: [\n            {\n              ...createSolid(255, 0, 0),\n              position: 0,\n            },\n            {\n              ...createSolid(0, 255, 0),\n              position: 100,\n            },\n          ],\n        }}\n        label=\"Color\"\n      />\n    );\n\n    await waitFor(() => expect(button).toBeDefined());\n    expect(button).toHaveAttribute('aria-label', 'Color');\n    expect(button).toHaveTextContent('Radial');\n\n    expect(input).toBeNull();\n  });\n\n  it('should render multiple if applicable', async () => {\n    getPreviewTextMock.mockImplementationOnce(() => {\n      return null;\n    });\n\n    const { input } = arrange(\n      <ColorInput onChange={() => {}} value={MULTIPLE_VALUE} label=\"Color\" />\n    );\n    await waitFor(() => expect(input.placeholder).toBe(MULTIPLE_DISPLAY_VALUE));\n    expect(input).toHaveValue('');\n  });\n\n  it('should open the color picker when clicked', async () => {\n    const onChange = jest.fn();\n    const onClose = jest.fn();\n    const value = { color: { r: 0, g: 0, b: 0, a: 1 } };\n    const { button } = arrange(\n      <ColorInput\n        onChange={onChange}\n        value={value}\n        hasGradient\n        hasOpacity={false}\n        onClose={onClose}\n        label=\"Color\"\n      />\n    );\n\n    fireEvent.click(button);\n\n    const pickerDialog = await screen.findByLabelText(\n      /color and gradient picker/i\n    );\n    await waitFor(() => expect(pickerDialog).toBeInTheDocument());\n  });\n\n  it('should open the color picker when clicked if multiple', async () => {\n    const onChange = jest.fn();\n    const onClose = jest.fn();\n    const { button } = arrange(\n      <ColorInput\n        onChange={onChange}\n        value={MULTIPLE_VALUE}\n        hasGradient\n        onClose={onClose}\n        label=\"Color\"\n      />\n    );\n\n    fireEvent.click(button);\n\n    const pickerDialog = await screen.findByLabelText(\n      /color and gradient picker/i\n    );\n    await waitFor(() => expect(pickerDialog).toBeInTheDocument());\n  });\n\n  it('should invoke onChange when inputting valid hex', async () => {\n    getPreviewTextMock.mockImplementation(() => {\n      return 'FF0000';\n    });\n    const onChange = jest.fn();\n    const value = createSolid(255, 0, 0);\n    const { input } = arrange(\n      <ColorInput onChange={onChange} value={value} label=\"Color\" />\n    );\n\n    // Only 5 digits can't be valid\n    fireEvent.change(input, { target: { value: '0FF00' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    // Since saved value didn't change shouldn't trigger onChange\n    await waitFor(() => expect(onChange).not.toHaveBeenCalled());\n    // Input should revert to saved value\n    expect(input).toHaveValue('FF0000');\n\n    // Non-hex can't be valid\n    fireEvent.change(input, { target: { value: 'COFFEE' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    // Since saved value didn't change shouldn't trigger onChange\n    expect(onChange).not.toHaveBeenCalled();\n    // Input should revert to saved value\n    expect(input).toHaveValue('FF0000');\n\n    // Exactly 6 hex digits is good\n    fireEvent.change(input, { target: { value: '00FF00' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledWith(createSolid(0, 255, 0));\n    expect(input).toHaveValue('00FF00');\n\n    // Allow shorthand 1 digits\n    fireEvent.change(input, { target: { value: '0' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledWith(createSolid(0, 0, 0));\n    expect(input).toHaveValue('000000');\n\n    // Allow shorthand 2 digits\n    fireEvent.change(input, { target: { value: 'AF' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledWith(createSolid(175, 175, 175));\n    expect(input).toHaveValue('AFAFAF');\n\n    // Allow shorthand 3 digit hex\n    fireEvent.change(input, { target: { value: 'F60' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledWith(createSolid(255, 102, 0));\n    expect(input).toHaveValue('FF6600');\n\n    // Allow shorthand 4 digits\n    fireEvent.change(input, { target: { value: 'AAFF' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledWith(createSolid(255, 102, 0));\n    expect(input).toHaveValue('AAAAFF');\n\n    // Also validate that it'll ignore the first #\n    fireEvent.change(input, { target: { value: '#0000FF' } });\n    fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n    expect(onChange).toHaveBeenCalledTimes(6);\n    expect(onChange).toHaveBeenCalledWith(createSolid(0, 0, 255));\n    expect(input).toHaveValue('0000FF');\n  });\n\n  it('should revert to last known value when blurring invalid input', async () => {\n    getPreviewTextMock.mockImplementation(() => {\n      return 'FF0000';\n    });\n    const onChange = jest.fn();\n    const value = createSolid(255, 0, 0);\n    const { input } = arrange(\n      <ColorInput onChange={onChange} value={value} label=\"Color\" />\n    );\n\n    // Only 5 digits can't be valid\n    fireEvent.change(input, { target: { value: '0FF00' } });\n    fireEvent.blur(input);\n\n    // Reverting to already saved value, shouldn't trigger onChange\n    await waitFor(() => expect(onChange).toHaveBeenCalledTimes(0));\n    expect(input).toHaveValue('FF0000');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/getPreviewOpacity.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\nimport getPreviewOpacity from '../getPreviewOpacity';\n\ndescribe('getPreviewOpacity', () => {\n  it('should return null for no pattern', () => {\n    const pattern = null;\n    const result = getPreviewOpacity(pattern);\n    const expected = null;\n    expect(result).toBe(expected);\n  });\n\n  it('should return default alpha for non-solid pattern', () => {\n    const pattern = { type: 'linear' };\n    const result = getPreviewOpacity(pattern);\n    const expected = 100;\n    expect(result).toBe(expected);\n  });\n\n  it('should return non-default alpha for non-solid pattern', () => {\n    const pattern = { type: 'linear', alpha: 0.7 };\n    const result = getPreviewOpacity(pattern);\n    const expected = 70;\n    expect(result).toBe(expected);\n  });\n\n  it('should return 100% for solid pattern without alpha component', () => {\n    const pattern = createSolid(255, 0, 0);\n    const result = getPreviewOpacity(pattern);\n    const expected = 100;\n    expect(result).toBe(expected);\n  });\n\n  it('should return alpha as percent for solid pattern with alpha component', () => {\n    const pattern = createSolid(255, 0, 0, 0.2);\n    const result = getPreviewOpacity(pattern);\n    const expected = 20;\n    expect(result).toBe(expected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/getPreviewStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createSolid,\n  generatePatternStyles as generatePatternStylesMock,\n} from '@googleforcreators/patterns';\n/**\n * Internal dependencies\n */\nimport getPreviewStyle from '../getPreviewStyle';\n\njest.mock('@googleforcreators/patterns', () => ({\n  ...jest.requireActual('@googleforcreators/patterns'),\n  generatePatternStyles: jest.fn(),\n}));\n\ndescribe('getPreviewStyle', () => {\n  beforeEach(() => {\n    generatePatternStylesMock.mockReset();\n    generatePatternStylesMock.mockImplementation(() => ({\n      backgroundColor: 'red',\n    }));\n  });\n\n  it('should return transparent for no pattern', () => {\n    const pattern = null;\n    const result = getPreviewStyle(pattern);\n    expect(result).toStrictEqual({});\n    expect(generatePatternStylesMock).not.toHaveBeenCalled();\n  });\n\n  it('should return generated pattern for non-solid', () => {\n    const pattern = { type: 'linear' };\n    const result = getPreviewStyle(pattern);\n    expect(result).toStrictEqual({ backgroundColor: 'red' });\n    expect(generatePatternStylesMock).toHaveBeenCalledWith(pattern);\n  });\n\n  it('should ignore alpha for non-solid', () => {\n    const pattern = { type: 'linear', alpha: 0.7 };\n    const result = getPreviewStyle(pattern);\n    expect(result).toStrictEqual({ backgroundColor: 'red' });\n    // Note the absence of alpha below\n    expect(generatePatternStylesMock).toHaveBeenCalledWith({ type: 'linear' });\n  });\n\n  it('should return transparent for transparent solid', () => {\n    const pattern = createSolid(255, 0, 255, 0);\n    const result = getPreviewStyle(pattern);\n    expect(result).toStrictEqual({ backgroundColor: 'red' });\n    expect(generatePatternStylesMock).toHaveBeenCalledWith(\n      createSolid(255, 0, 255)\n    );\n  });\n\n  it('should return fully opaque style for non-transparent solid', () => {\n    const pattern = createSolid(255, 0, 255, 0.1);\n    const result = getPreviewStyle(pattern);\n    expect(result).toStrictEqual({ backgroundColor: 'red' });\n    expect(generatePatternStylesMock).toHaveBeenCalledWith(\n      createSolid(255, 0, 255)\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/color/test/opacityInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, act, fireEvent, screen } from '@testing-library/react';\nimport {\n  createSolid,\n  getPreviewText as getPreviewTextMock,\n} from '@googleforcreators/patterns';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport OpacityInput from '../opacityInput';\nimport getPreviewOpacityMock from '../getPreviewOpacity';\n\njest.mock('../getPreviewOpacity', () => jest.fn());\njest.mock('@googleforcreators/patterns', () => ({\n  ...jest.requireActual('@googleforcreators/patterns'),\n  getPreviewText: jest.fn(),\n}));\n\nfunction arrange(customProps = {}) {\n  const onChange = jest.fn();\n  const props = {\n    onChange,\n    value: createSolid(0, 0, 0),\n    ...customProps,\n  };\n  const { rerender } = renderWithTheme(<OpacityInput {...props} />);\n  const element = screen.queryByLabelText('Opacity');\n  const wrappedRerender = (extraProps) =>\n    rerender(<OpacityInput {...props} {...extraProps} />);\n  return { element, onChange, rerender: wrappedRerender };\n}\n\ndescribe('<OpacityInput />', () => {\n  beforeEach(() => {\n    getPreviewOpacityMock.mockReset();\n    getPreviewTextMock.mockReset();\n\n    getPreviewOpacityMock.mockImplementation(() => 100);\n    getPreviewTextMock.mockImplementation(() => 'FF0000');\n  });\n\n  it('should render (and rerender) correct opacity when there is a text', () => {\n    const { element, rerender } = arrange({ value: createSolid(255, 0, 0) });\n\n    expect(getPreviewOpacityMock).toHaveBeenCalledWith(createSolid(255, 0, 0));\n\n    expect(element).toBeDefined();\n    expect(element).toHaveValue('100%');\n\n    // Try again with a different value\n    getPreviewOpacityMock.mockReset();\n    getPreviewOpacityMock.mockImplementation(() => 20);\n    rerender({ value: createSolid(255, 0, 0, 0.2) });\n    expect(getPreviewOpacityMock).toHaveBeenCalledWith(\n      createSolid(255, 0, 0, 0.2)\n    );\n    expect(element).toBeDefined();\n    expect(element).toHaveValue('20%');\n  });\n\n  it('should remove postfix when there is focus but add again when blurred', async () => {\n    const { element } = arrange();\n\n    act(() => element.focus());\n\n    await waitFor(() => expect(element).toHaveFocus());\n    expect(element).toHaveValue('100');\n\n    document.body.tabIndex = 0; // Allow body to be focused\n    act(() => document.body.focus());\n\n    await waitFor(() => expect(element).not.toHaveFocus());\n    expect(element).toHaveValue('100%');\n  });\n\n  it('should invoke callback with valid input only', () => {\n    const { element, onChange } = arrange();\n\n    fireEvent.change(element, { target: { value: '50' } });\n    fireEvent.blur(element);\n    expect(onChange).toHaveBeenCalledWith(0.5);\n\n    onChange.mockReset();\n    fireEvent.change(element, { target: { value: 'ten' } });\n    fireEvent.blur(element);\n    expect(onChange).not.toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\n\nexport default createContext({\n  isMultiple: false,\n  registerPresubmitHandler: noop,\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/calendarWrapper.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { themeHelpers, TextSize } from '@googleforcreators/design-system';\n\n// Modified from react-calendar/dist/Calendar.css\nconst CalendarWrapper = styled.div`\n  min-height: 236px;\n\n  .react-calendar {\n    width: 350px;\n    max-width: 100%;\n    background-color: ${({ theme }) => theme.colors.bg.primary};\n    ${({ theme }) =>\n      themeHelpers.expandPresetStyles({\n        preset: theme.typography.presets.label[TextSize.Small],\n        theme,\n      })}\n    color: ${({ theme }) => theme.colors.fg.primary};\n\n    button {\n      margin: 0;\n      border: 0;\n      outline: none;\n      ${({ theme }) =>\n        themeHelpers.expandPresetStyles({\n          preset: theme.typography.presets.label[TextSize.Small],\n          theme,\n        })}\n      color: ${({ theme }) => theme.colors.fg.primary};\n\n      &:enabled:hover {\n        cursor: pointer;\n      }\n    }\n  }\n\n  .react-calendar,\n  .react-calendar *,\n  .react-calendar *:before,\n  .react-calendar *:after {\n    box-sizing: border-box;\n  }\n\n  .react-calendar .react-calendar__navigation {\n    display: flex;\n    height: 44px;\n    margin-bottom: 1em;\n\n    /* stylelint-disable-next-line no-descending-specificity */\n    button {\n      min-width: 44px;\n      background: none;\n      color: ${({ theme }) => theme.colors.fg.secondary};\n\n      &:disabled {\n        background-color: transparent;\n      }\n\n      &:enabled:hover,\n      &:enabled:focus {\n        background-color: ${({ theme }) => theme.colors.bg.secondary};\n        color: ${({ theme }) => theme.colors.fg.primary};\n      }\n    }\n  }\n\n  .react-calendar__month-view__weekdays {\n    text-align: center;\n    text-transform: uppercase;\n    font-weight: bold;\n    font-size: 10px;\n  }\n\n  .react-calendar__month-view__weekdays__weekday {\n    padding: 0.5em;\n  }\n\n  .react-calendar .react-calendar__month-view__days__day--weekend {\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n\n  .react-calendar .react-calendar__month-view__days__day--neighboringMonth {\n    color: ${({ theme }) => theme.colors.fg.tertiary};\n  }\n\n  .react-calendar__tile {\n    max-width: 100%;\n    padding: 10px 6.6667px;\n    background: none;\n    text-align: center;\n    line-height: 16px;\n\n    &:disabled {\n      background-color: ${({ theme }) => theme.colors.bg.tertiary};\n    }\n\n    &:enabled:hover,\n    &:enabled:focus {\n      background-color: ${({ theme }) =>\n        theme.colors.interactiveBg.tertiaryHover};\n      color: ${({ theme }) => theme.colors.interactiveFg.active};\n    }\n  }\n\n  /* stylelint-disable no-descending-specificity */\n  .react-calendar__year-view .react-calendar__tile,\n  .react-calendar__decade-view .react-calendar__tile,\n  .react-calendar__century-view .react-calendar__tile {\n    padding: 1.2em 0.5em;\n  }\n\n  .react-calendar button.react-calendar__tile--now {\n    background: ${({ theme }) => theme.colors.bg.tertiary};\n    color: ${({ theme }) => theme.colors.fg.primary};\n\n    &:enabled:hover,\n    &:enabled:focus {\n      background-color: ${({ theme }) =>\n        theme.colors.interactiveBg.secondaryHover};\n      color: ${({ theme }) => theme.colors.interactiveFg.active};\n    }\n  }\n\n  .react-calendar button.react-calendar__tile--active,\n  .react-calendar button.react-calendar__tile--hasActive {\n    background: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n    color: ${({ theme }) => theme.colors.interactiveFg.brandNormal};\n\n    &:enabled:hover,\n    &:enabled:focus {\n      background-color: ${({ theme }) => theme.colors.interactiveBg.brandHover};\n      color: ${({ theme }) => theme.colors.interactiveFg.brandHover};\n    }\n  }\n`;\n\nexport default CalendarWrapper;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/datePicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useRef,\n  useCallback,\n  useMemo,\n  useEffect,\n  lazy,\n  Suspense,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { _x } from '@googleforcreators/i18n';\nimport { getOptions, format, formatDate } from '@googleforcreators/date';\nimport { CircularProgress } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport CalendarWrapper from './calendarWrapper';\nimport { getCalendarType } from './utils';\n\nconst Calendar = lazy(\n  () => import(/* webpackChunkName: \"chunk-react-calendar\" */ 'react-calendar')\n);\n\nconst FallbackCalendar = styled.div`\n  height: 256px;\n  width: 350px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\nfunction DatePicker({ currentDate, onChange, onViewChange }) {\n  const nodeRef = useRef();\n  const value = useMemo(\n    () => (currentDate ? new Date(currentDate) : new Date()),\n    [currentDate]\n  );\n  const handleOnChange = useCallback(\n    (newDate) => {\n      newDate.setHours(value.getHours());\n      newDate.setMinutes(value.getMinutes());\n      onChange(newDate.toISOString(), /* Close calendar */ true);\n    },\n    [value, onChange]\n  );\n\n  const updateTabIndexes = useCallback(\n    (setFocus = false) => {\n      // Set tabIndex to -1 for every except for the first button.\n      if (nodeRef.current) {\n        // Allow tabbing to sections inside the calendar.\n        const navButtons = [\n          ...nodeRef.current.querySelectorAll(\n            '.react-calendar__navigation button'\n          ),\n        ];\n        navButtons[0].tabIndex = '0';\n        navButtons.shift();\n        for (const btn of navButtons) {\n          btn.tabIndex = '-1';\n        }\n\n        // Dates / days.\n        const buttons = [\n          ...nodeRef.current.querySelectorAll(\n            '.react-calendar__viewContainer button'\n          ),\n        ];\n\n        let foundActive = false;\n        for (const btn of buttons) {\n          if (!btn.classList.contains('react-calendar__tile--now')) {\n            btn.tabIndex = '-1';\n          } else {\n            btn.tabIndex = '0';\n            if (setFocus) {\n              // When changing view we need to explicitly set focus again,\n              // It seems to not be happening by default.\n              btn.focus();\n            }\n            foundActive = true;\n          }\n        }\n        if (!foundActive) {\n          // Assume first as active.\n          buttons[0].tabIndex = '0';\n          buttons[0].focus();\n        }\n      }\n    },\n    [nodeRef]\n  );\n\n  useEffect(() => {\n    // Wait one tick for the calendar to be available.\n    const timeout = setTimeout(() => {\n      updateTabIndexes();\n    });\n    return () => {\n      clearTimeout(timeout);\n    };\n  }, [updateTabIndexes]);\n  const { weekStartsOn } = getOptions();\n  const calendarType = getCalendarType(weekStartsOn);\n  return (\n    <Suspense\n      fallback={\n        <FallbackCalendar>\n          <CircularProgress />\n        </FallbackCalendar>\n      }\n    >\n      <CalendarWrapper ref={nodeRef}>\n        <Calendar\n          value={value}\n          calendarType={calendarType}\n          onChange={handleOnChange}\n          onViewChange={onViewChange}\n          onActiveStartDateChange={() => updateTabIndexes(true /* Set focus */)}\n          nextAriaLabel={_x(\n            'Next',\n            'This label can apply to next month, year and/or decade',\n            'web-stories'\n          )}\n          prevAriaLabel={_x(\n            'Previous',\n            'This label can apply to previous month, year and/or decade',\n            'web-stories'\n          )}\n          next2AriaLabel={_x(\n            'Jump forward',\n            'This label can apply to month, year and/or decade',\n            'web-stories'\n          )}\n          prev2AriaLabel={_x(\n            'Jump backwards',\n            'This label can apply to month, year and/or decade',\n            'web-stories'\n          )}\n          formatDay={(locale, date) => format(date, 'j')}\n          formatWeekday={(locale, date) => format(date, 'l')}\n          formatLongDate={(locale, date) => formatDate(date)}\n          formatMonth={(locale, date) => format(date, 'F')}\n          formatMonthYear={(locale, date) => format(date, 'F Y')}\n          formatShortWeekday={(locale, date) => format(date, 'D')}\n          formatYear={(locale, date) => format(date, 'Y')}\n        />\n      </CalendarWrapper>\n    </Suspense>\n  );\n}\n\nDatePicker.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  onViewChange: PropTypes.func,\n  currentDate: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n};\n\nexport default DatePicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/dateTime.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useFocusTrapping from '../../../utils/useFocusTrapping';\nimport useRovingTabIndex from '../../../utils/useRovingTabIndex';\nimport TimePicker from './timePicker';\nimport DatePicker from './datePicker';\n\nconst DateTimeWrapper = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  border: 1px solid ${({ theme }) => theme.colors.divider.primary};\n  width: 100%;\n  padding: 4px;\n`;\n\nconst StyledButton = styled(Button)`\n  margin: 5px 0;\n  color: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n\n  &:hover {\n    color: ${({ theme }) => theme.colors.interactiveBg.brandHover};\n  }\n`;\n\nfunction DateTime({\n  value,\n  onChange,\n  onViewChange,\n  is12Hour = true,\n  hasLeadingZeros,\n  forwardedRef,\n  onClose,\n  canReset = false,\n}) {\n  const selectedTime = value ? new Date(value) : new Date();\n  const initialHours = selectedTime.getHours();\n  const [localeData, setLocaleData] = useState({\n    minutes: selectedTime.getMinutes(),\n    am: initialHours < 12 ? 'AM' : 'PM',\n    hours: is12Hour ? initialHours % 12 || 12 : initialHours,\n    date: selectedTime,\n  });\n\n  const previousFocus = useRef(document.activeElement);\n  const handleClose = useCallback(\n    (evt) => {\n      if (previousFocus.current) {\n        previousFocus.current.focus();\n      }\n      onClose(evt);\n    },\n    [onClose]\n  );\n\n  useKeyDownEffect(forwardedRef, { key: ['esc'], editable: true }, handleClose);\n  useRovingTabIndex({ ref: forwardedRef });\n  useFocusTrapping({ ref: forwardedRef });\n\n  return (\n    <DateTimeWrapper ref={forwardedRef}>\n      <TimePicker\n        localeData={localeData}\n        setLocaleData={setLocaleData}\n        onChange={onChange}\n        is12Hour={is12Hour}\n        hasLeadingZeros={hasLeadingZeros}\n      />\n      <DatePicker\n        currentDate={value}\n        onChange={onChange}\n        onViewChange={onViewChange}\n      />\n      {canReset && (\n        <StyledButton\n          size={ButtonSize.Small}\n          onClick={() => {\n            onChange(null);\n            onClose();\n          }}\n          aria-label={__('Reset publish time', 'web-stories')}\n        >\n          {__('Reset', 'web-stories')}\n        </StyledButton>\n      )}\n    </DateTimeWrapper>\n  );\n}\n\nDateTime.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  onViewChange: PropTypes.func,\n  onClose: PropTypes.func,\n  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n  is12Hour: PropTypes.bool,\n  hasLeadingZeros: PropTypes.bool,\n  forwardedRef: PropTypes.object,\n  canReset: PropTypes.bool,\n};\n\nexport default DateTime;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './dateTime';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/timePicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport { NumericInput } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Switch from '../switch';\nimport TimeZone from './timeZone';\n\nconst TimeWrapper = styled.div`\n  margin-bottom: 1em;\n  padding: 0 20px;\n`;\n\nconst Fieldset = styled.fieldset`\n  margin-top: 0.5em;\n  position: relative;\n`;\n\nconst Legend = styled.legend`\n  position: absolute;\n  top: -999em;\n  left: -999em;\n`;\n\nconst InputRow = styled.div`\n  display: flex;\n`;\n\nconst NumberInput = styled(NumericInput)`\n  background-color: ${({ theme }) => theme.colors.bg.tertiary};\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n\n  margin-right: 4px;\n  width: 50%;\n  max-width: 50px;\n\n  div {\n    height: 32px;\n  }\n\n  input {\n    text-align: center;\n  }\n`;\n\nconst TimeSeparator = styled.span`\n  padding: 0 3px 0 0;\n  color: #555d66;\n`;\n\nconst InputGroup = styled.div`\n  flex-basis: 100%;\n`;\n\nconst StyledSwitch = styled(Switch)`\n  width: 100px;\n`;\n\nfunction TimePicker({\n  onChange,\n  is12Hour,\n  hasLeadingZeros,\n  localeData,\n  setLocaleData,\n}) {\n  const onChangeEvent = (prop) => (_, value) => {\n    let filteredValue =\n      value !== undefined && value !== null\n        ? Number.parseInt(value)\n        : localeData[prop];\n    filteredValue = isNaN(filteredValue) ? '' : filteredValue;\n    filteredValue = filteredValue === '' && value === '-' ? '-' : filteredValue;\n    setLocaleData({\n      ...localeData,\n      [prop]: filteredValue,\n    });\n  };\n\n  const getMaxHours = () => {\n    return is12Hour ? 12 : 23;\n  };\n\n  const getMinHours = () => {\n    return is12Hour ? 1 : 0;\n  };\n\n  const getHours = (value) => {\n    const { am } = localeData;\n    if (!is12Hour) {\n      return value;\n    }\n    return am === 'AM' ? value % 12 : ((value % 12) + 12) % 24;\n  };\n\n  const changeDate = (newDate, props = {}) => {\n    setLocaleData({ ...localeData, ...props, date: newDate });\n    onChange(newDate.toISOString());\n  };\n\n  const updateMinutes = () => {\n    const { minutes, date } = localeData;\n    const value = Number.parseInt(minutes);\n    if (isNaN(value) || value < 0 || value > 59) {\n      return;\n    }\n    if (date.getMinutes() !== minutes) {\n      const newDate = date;\n      newDate.setMinutes(minutes);\n      changeDate(newDate);\n    }\n  };\n\n  const updateHours = () => {\n    const { hours, date } = localeData;\n    const value = Number.parseInt(hours);\n    if (isNaN(value) || value < getMinHours() || value > getMaxHours()) {\n      return;\n    }\n\n    if (date.getHours() !== getHours(hours)) {\n      const newDate = date;\n      newDate.setHours(getHours(hours));\n      changeDate(newDate);\n    }\n  };\n\n  const updateAmPm = (_evt, useAM) => {\n    const { am, date, hours } = localeData;\n\n    if (am === 'AM' && useAM) {\n      return;\n    }\n    const newDate = date;\n\n    if (useAM) {\n      newDate.setHours(hours % 12);\n    } else {\n      newDate.setHours(((hours % 12) + 12) % 24);\n    }\n\n    changeDate(newDate, { am: useAM ? 'AM' : 'PM' });\n  };\n\n  const hours = useRef();\n  useEffect(() => {\n    hours.current.focus();\n  }, []);\n\n  const isAM = localeData.am === 'AM';\n\n  return (\n    <TimeWrapper>\n      <Fieldset>\n        <Legend>{__('Time', 'web-stories')}</Legend>\n        <InputRow>\n          <InputGroup>\n            <NumberInput\n              ref={hours}\n              aria-label={__('Hours', 'web-stories')}\n              step={1}\n              min={getMinHours()}\n              max={getMaxHours()}\n              value={localeData.hours}\n              onChange={onChangeEvent('hours')}\n              updateOnChange\n              onBlur={updateHours}\n              padZero={hasLeadingZeros}\n            />\n            <TimeSeparator>{':'}</TimeSeparator>\n            <NumberInput\n              aria-label={__('Minutes', 'web-stories')}\n              min={0}\n              max={59}\n              value={localeData.minutes}\n              onChange={onChangeEvent('minutes')}\n              updateOnChange\n              onBlur={updateMinutes}\n              padZero\n            />\n          </InputGroup>\n          {is12Hour && (\n            <InputGroup>\n              <StyledSwitch\n                groupLabel={__('AM or PM', 'web-stories')}\n                name=\"time-picker-am-pm-switch\"\n                value={isAM}\n                onLabel={__('AM', 'web-stories')}\n                offLabel={__('PM', 'web-stories')}\n                onChange={updateAmPm}\n              />\n            </InputGroup>\n          )}\n          <TimeZone />\n        </InputRow>\n      </Fieldset>\n    </TimeWrapper>\n  );\n}\n\nTimePicker.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  is12Hour: PropTypes.bool,\n  hasLeadingZeros: PropTypes.bool,\n  localeData: PropTypes.shape({\n    am: PropTypes.string.isRequired,\n    hours: PropTypes.number.isRequired,\n    minutes: PropTypes.number.isRequired,\n    date: PropTypes.instanceOf(Date).isRequired,\n  }).isRequired,\n  setLocaleData: PropTypes.func.isRequired,\n};\n\nexport default TimePicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/timeZone.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getSettings } from '@googleforcreators/date';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Placement, Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../tooltip';\nimport { Z_INDEX_TIME_PICKER_TOOLTIP } from '../../../constants/zIndex';\n\nconst Wrapper = styled.div`\n  white-space: nowrap;\n`;\n\nconst StyledText = styled(Text.Span)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  line-height: 30px;\n`;\n\nfunction TimeZone() {\n  const { timezone, gmtOffset, timezoneAbbr } = getSettings();\n\n  // Convert timezone offset to hours.\n  const userTimezoneOffset = -1 * (new Date().getTimezoneOffset() / 60);\n\n  // System timezone and user timezone match, nothing needed.\n  // Compare as numbers because it comes over as string.\n  if (Number(gmtOffset) === userTimezoneOffset) {\n    return null;\n  }\n\n  const offsetSymbol = Number(gmtOffset) >= 0 ? '+' : '';\n  const zoneAbbr =\n    '' !== timezoneAbbr && Number.isNaN(Number(timezoneAbbr))\n      ? timezoneAbbr\n      : `UTC${offsetSymbol}${gmtOffset}`;\n\n  const tooltip =\n    'UTC' === timezone\n      ? __('Coordinated Universal Time', 'web-stories')\n      : `(${zoneAbbr}) ${timezone.replace('_', ' ')}`;\n\n  return (\n    <Wrapper>\n      <Tooltip\n        hasTail\n        title={tooltip}\n        placement={Placement.Top}\n        popupZIndexOverride={Z_INDEX_TIME_PICKER_TOOLTIP}\n      >\n        <StyledText size={TextSize.XSmall}>{zoneAbbr}</StyledText>\n      </Tooltip>\n    </Wrapper>\n  );\n}\n\nexport default TimeZone;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/dateTime/utils.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport function getCalendarType(weekStartsOn) {\n  const calendarTypes = {\n    0: 'US',\n    1: 'ISO 8601',\n    5: 'Hebrew',\n    6: 'Arabic',\n  };\n  return calendarTypes[weekStartsOn] || 'ISO 8601';\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/form/filterToggle/filterToggle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  generatePatternStyles,\n  PatternPropType,\n} from '@googleforcreators/patterns';\nimport {\n  TextSize,\n  BUTTON_TRANSITION_TIMING,\n  Text,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../panels/shared/styles';\n\nconst fillCss = css`\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  top: 0;\n  left: 0;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n`;\n\nconst Overlay = styled.div`\n  ${fillCss};\n`;\n\nconst Filter = styled.div`\n  ${fillCss};\n  ${({ filter }) => generatePatternStyles(filter)};\n`;\n\nconst Button = styled.button(\n  ({ theme }) => css`\n    border-radius: ${theme.borders.radius.small};\n    width: 100%;\n    height: 48px;\n    position: relative;\n    display: flex;\n    align-items: center;\n    justify-content: space-around;\n    box-sizing: border-box;\n    padding: 0;\n    margin: 0;\n    background: transparent;\n    border: none;\n    cursor: pointer;\n    ${focusStyle};\n\n    img {\n      width: 100%;\n      height: 100%;\n      border-radius: ${theme.borders.radius.small};\n    }\n\n    ${Overlay} {\n      ${({ isToggled }) =>\n        isToggled &&\n        `\n        box-shadow:\n          0px 0px 0 2px ${theme.colors.bg.secondary},\n          0px 0px 0 3px ${theme.colors.fg.primary}`};\n    }\n\n    &:active > ${Overlay} {\n      box-shadow:\n        0px 0px 0 2px ${theme.colors.bg.secondary},\n        0px 0px 0 3px ${theme.colors.fg.primary};\n    }\n\n    &:disabled {\n      pointer-events: none;\n      ${Overlay} {\n        background-color: ${theme.colors.opacity.black64};\n      }\n    }\n\n    transition:\n      background-color ${BUTTON_TRANSITION_TIMING},\n      color ${BUTTON_TRANSITION_TIMING};\n  `\n);\n\nconst Wrapper = styled.div`\n  width: 60px;\n`;\n\nconst StyledText = styled(Text.Span).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.border.defaultActive};\n  margin-top: 8px;\n  text-align: center;\n  width: 100%;\n  display: block;\n`;\n\nfunction FilterToggle({ isToggled, filter = null, children, label, ...rest }) {\n  return (\n    <Wrapper>\n      <Button {...rest} isToggled={isToggled} aria-pressed={isToggled}>\n        {children}\n        <Filter filter={filter} />\n        <Overlay />\n      </Button>\n      {label && <StyledText>{label}</StyledText>}\n    </Wrapper>\n  );\n}\n\nFilterToggle.propTypes = {\n  isToggled: PropTypes.bool.isRequired,\n  filter: PatternPropType,\n  children: PropTypes.node.isRequired,\n  label: PropTypes.string,\n};\n\nexport default FilterToggle;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/filterToggle/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './filterToggle';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/filterToggle/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { __, _x } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport FilterToggle from '../filterToggle';\nimport Row from '../../row';\nimport { dummyImage } from '../../../devTools/dummyData';\n\nconst StyledRow = styled(Row)`\n  width: 300px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  padding: 20px;\n  button {\n    margin-right: 10px;\n  }\n`;\n\nexport default {\n  title: 'Stories Editor/Components/Form/FilterToggle',\n  component: FilterToggle,\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render() {\n    const filters = [\n      {\n        value: 'a',\n        filter: {\n          type: 'radial',\n          size: { w: 0.8, h: 0.5 },\n          stops: [\n            { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 0, a: 0.7 }, position: 1 },\n          ],\n          alpha: 0.6,\n        },\n        label: __('Radial', 'web-stories'),\n        helper: __('This is the best option', 'web-stories'),\n        isToggled: true,\n      },\n      {\n        value: 'b',\n        filter: {\n          type: 'linear',\n          rotation: 0,\n          stops: [\n            { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 0, a: 0.7 }, position: 1 },\n          ],\n          alpha: 0.9,\n        },\n        label: __('Linear', 'web-stories'),\n        helper: __('Also a good option', 'web-stories'),\n      },\n      {\n        value: 'c',\n        filter: null,\n        label: _x('None', 'filter', 'web-stories'),\n      },\n    ];\n    const [value, setValue] = useState('a');\n\n    return (\n      <StyledRow>\n        {filters.map(({ value: toggleValue, ...rest }) => {\n          return (\n            <FilterToggle\n              key={toggleValue}\n              {...rest}\n              isToggled={toggleValue === value}\n              onClick={() => setValue(toggleValue)}\n            >\n              <img src={dummyImage} alt={rest.label} />\n            </FilterToggle>\n          );\n        })}\n      </StyledRow>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/hierarchical/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Checkbox,\n  Input,\n  KEYS,\n  Text,\n  themeHelpers,\n  TextSize,\n  useKeyDownEffect,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\nimport { _n, sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useDebouncedCallback,\n  useEffect,\n  usePrevious,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport DirectionAware from '../../directionAware';\nimport { makeFlatOptionTree } from './utils';\n\nexport { makeFlatOptionTree };\n\nconst Container = styled.div`\n  margin-bottom: 8px;\n  display: block;\n`;\n\nconst Label = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  margin: 0 12px;\n`;\n\nconst Border = styled.div`\n  padding-top: 4px;\n  margin-top: -4px; /* Run side borders into the search border  */\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  border-top: none;\n  border-radius: ${({ theme }) =>\n    `0 0 ${theme.borders.radius.small} ${theme.borders.radius.small}`};\n`;\n\nconst CheckboxArea = styled.ul`\n  max-height: 175px;\n  padding: 12px 12px 0 12px;\n  overflow-y: scroll;\n  margin-top: 4px;\n  margin-bottom: 0;\n\n  ${themeHelpers.scrollbarCSS};\n\n  :focus-within {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst CheckboxContainer = styled.li`\n  display: flex;\n  align-items: center;\n  margin-bottom: 8px;\n  margin-left: ${({ $level }) => 20 * $level}px;\n`;\n\nconst NoResultsText = styled(Text.Paragraph)`\n  margin-bottom: 12px;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst buildOptionId = (id) => `hierarchical_term_option_${id}`;\nconst buildOptionName = (name) => `hierarchical_term_${name}`;\n\n/**\n * Renders a checkbox and all children of the checkbox.\n *\n * @param {Object} option The option to render.\n * @param {string} option.id the option id\n * @param {string} option.label The label of the checkbox\n * @param {Function} option.onChange Change event handler\n * @param {boolean} option.checked The value of the checkbox\n * @param {Object} option.optionRef Ref used to store refs to checkboxes.\n * @param {number} option.$level The indentation level.\n * @return {Node} The rendered option and children.\n */\nconst Option = ({ optionRef = { current: {} }, $level = 0, ...option }) => {\n  const { id, label, onBlur, onChange, onFocus, checked, value } = option;\n\n  const optionId = buildOptionId(option.id);\n  const optionName = buildOptionName(option.label);\n\n  return (\n    <CheckboxContainer aria-selected={checked} role=\"treeitem\" $level={$level}>\n      <Checkbox\n        id={optionId}\n        ref={(node) => {\n          optionRef.current[id] = node;\n        }}\n        value={value}\n        checked={checked}\n        name={optionName}\n        onChange={(evt) => onChange(evt, option)}\n        onBlur={onBlur}\n        onFocus={onFocus}\n        tabIndex={-1}\n      />\n      <Label htmlFor={optionId}>{label}</Label>\n    </CheckboxContainer>\n  );\n};\nconst OptionPropType = {\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n  checked: PropTypes.bool,\n  label: PropTypes.string.isRequired,\n  $level: PropTypes.number,\n  optionRef: PropTypes.shape({\n    current: PropTypes.shape({\n      [PropTypes.string.isRequired]: PropTypes.node,\n    }),\n  }),\n};\nOption.propTypes = OptionPropType;\n\n/**\n * Hierarchical input\n *\n * @param {Object} props props\n * @param {string} props.className Class name to add to outer container\n * @param {string} props.inputValue The value of the input\n * @param {Function} props.onInputChange The change event handler of the input\n * @param {string} props.label Input label\n * @param {string} props.noOptionsText Text to display no options are found\n * @param {Array} props.options Array of options\n * @param {Function} props.onChange Change event handler. Passed to checkboxes.\n * @return {Node} The input\n */\nconst HierarchicalInput = ({\n  className,\n  inputValue,\n  onInputChange,\n  label,\n  noOptionsText,\n  options,\n  onChange,\n  ...inputProps\n}) => {\n  const speak = useLiveRegion('assertive');\n  const debouncedSpeak = useDebouncedCallback(speak, 500);\n  const checkboxListRef = useRef(null);\n  const inputRef = useRef(null);\n\n  // Focus handling\n  const [focusedCheckboxId, setFocusedCheckboxId] = useState(-1);\n  const optionRef = useRef({});\n\n  /**\n   * Handles listbox and checkbox focus.\n   *\n   * When listbox receives focus:\n   * - If none of the options are selected before the listbox receives focus, focus is set on the first option.\n   * - If one or more options are selected before the listbox receives focus, focus is set on the first option in the list that is selected.\n   */\n  const handleListboxFocus = useCallback(\n    (evt) => {\n      if (document.activeElement === checkboxListRef.current) {\n        if (!options.length) {\n          return;\n        }\n\n        // If the focus came from inside the list, focus input\n        // only happens when tabbing backwards\n        if (checkboxListRef.current.contains(evt.relatedTarget)) {\n          inputRef.current?.focus();\n          return;\n        }\n\n        // if there wasn't an option focused, find first selected\n        if (focusedCheckboxId === -1) {\n          const firstCheckedOption = options.find(\n            (option) => option.checked\n          )?.id;\n\n          setFocusedCheckboxId(firstCheckedOption ? firstCheckedOption : 0);\n        } else {\n          // else focus the previously focused option\n          optionRef.current[focusedCheckboxId]?.focus();\n        }\n      }\n    },\n    [focusedCheckboxId, options]\n  );\n\n  /**\n   * Handle keyboard interactions.\n   */\n  const handleKeyDown = useCallback(\n    (evt) => {\n      const currentSelectedIndex = options.findIndex(\n        (option) => option.id === focusedCheckboxId\n      );\n\n      switch (evt.key) {\n        case KEYS.UP:\n          if (currentSelectedIndex > 0) {\n            setFocusedCheckboxId(options[currentSelectedIndex - 1].id);\n          }\n          break;\n        case KEYS.DOWN:\n          if (currentSelectedIndex < options.length - 1) {\n            setFocusedCheckboxId(options[currentSelectedIndex + 1].id);\n          }\n          break;\n        default:\n          break;\n      }\n    },\n    [options, focusedCheckboxId]\n  );\n\n  /**\n   * Sets the value that filters the displayed items.\n   */\n  const handleInputChange = useCallback(\n    (evt) => {\n      onInputChange(evt.target.value);\n    },\n    [onInputChange]\n  );\n\n  /**\n   * Callback that is called when a checkbox is clicked.\n   */\n  const handleCheckboxChange = useCallback(\n    (evt, option) => {\n      onChange(evt, { id: option.id, checked: !option.checked });\n    },\n    [onChange]\n  );\n\n  /* Announce count of results found */\n  const previousInput = usePrevious(inputValue);\n  useEffect(() => {\n    // only run effect when input changes. Ignore when options change.\n    if (previousInput !== inputValue) {\n      const count = options.length;\n\n      const message = sprintf(\n        /* translators: %d: number of results. */\n        _n('%d result found.', '%d results found.', count, 'web-stories'),\n        count\n      );\n\n      debouncedSpeak(message);\n    }\n  }, [debouncedSpeak, options, inputValue, previousInput]);\n\n  useKeyDownEffect(\n    checkboxListRef,\n    { key: ['up', 'down', 'shift+up', 'shift+down'] },\n    handleKeyDown,\n    [handleKeyDown]\n  );\n\n  /**\n   * Focus checkbox when 'focusedCheckboxId' changes\n   */\n  useEffect(() => {\n    // only focus checkbox if focus is in the list\n    if (checkboxListRef.current?.contains(document.activeElement)) {\n      optionRef.current[focusedCheckboxId]?.focus();\n    }\n  }, [focusedCheckboxId]);\n\n  const showOptionArea = Boolean(options.length) || Boolean(inputValue.length);\n\n  return (\n    <Container className={className}>\n      <Input\n        ref={inputRef}\n        value={inputValue}\n        onChange={handleInputChange}\n        label={label}\n        type=\"search\"\n        placeholder={__('Search', 'web-stories')}\n        {...inputProps}\n      />\n      {showOptionArea && (\n        <Border>\n          <DirectionAware>\n            <CheckboxArea\n              id=\"checkbox_list\"\n              ref={checkboxListRef}\n              tabIndex={0}\n              onFocus={handleListboxFocus}\n              role=\"tree\"\n              aria-activedescendant={\n                focusedCheckboxId !== -1\n                  ? buildOptionId(focusedCheckboxId)\n                  : undefined\n              }\n              aria-multiselectable\n            >\n              {options.length ? (\n                options.map((option) => (\n                  <Option\n                    key={option.id}\n                    {...option}\n                    onChange={handleCheckboxChange}\n                    optionRef={optionRef}\n                  />\n                ))\n              ) : (\n                <NoResultsText role=\"treeitem\" size={TextSize.Small}>\n                  {noOptionsText}\n                </NoResultsText>\n              )}\n            </CheckboxArea>\n          </DirectionAware>\n        </Border>\n      )}\n    </Container>\n  );\n};\nHierarchicalInput.propTypes = {\n  className: PropTypes.string,\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n  inputValue: PropTypes.string.isRequired,\n  onInputChange: PropTypes.func.isRequired,\n  label: PropTypes.string.isRequired,\n  noOptionsText: PropTypes.string.isRequired,\n  options: PropTypes.arrayOf(PropTypes.shape(OptionPropType)).isRequired,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport default HierarchicalInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/hierarchical/stories/hierarchical.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Hierarchical from '..';\nimport { makeFlatOptionTree } from '../utils';\n\nexport default {\n  title: 'Stories Editor/Components/Form/Hierarchical',\n  component: Hierarchical,\n};\n\nconst Wrapper = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  padding: 50px 200px;\n`;\n\nconst OPTIONS = [\n  { id: 1, label: 'apple', checked: false },\n  { id: 'fitty', label: 'corgi', checked: true, parent: 1 },\n  { id: 'sixty', label: 'morgi', checked: true, parent: 1 },\n  { id: 'gritty', label: 'borky', checked: true, parent: 'sixty' },\n  { id: 2, label: 'banana', checked: false },\n  { id: 3, label: 'cantaloupe', checked: true },\n  { id: 4, label: 'papaya', checked: false },\n  { id: '100', label: 'trees', checked: true, parent: 4 },\n  { id: '1001', label: 'porgi', checked: true, parent: '100' },\n  { id: '10011', label: 'hal', checked: true, parent: '100' },\n  { id: 5, label: 'zebra fish', checked: true },\n];\n\nexport const _default = {\n  render: function Render() {\n    const [options, setOptions] = useState(OPTIONS);\n    const [searchText, setSearchText] = useState('');\n\n    const filteredOptions = useMemo(\n      () => makeFlatOptionTree(options, searchText),\n      [options, searchText]\n    );\n\n    const handleInputChange = useCallback((val) => setSearchText(val), []);\n\n    const handleChange = useCallback((evt, { id, checked }) => {\n      setOptions((currentOptions) => {\n        const index = currentOptions.findIndex((option) => option.id === id);\n\n        return [\n          ...currentOptions.slice(0, index),\n          { ...currentOptions[index], checked },\n          ...currentOptions.slice(index + 1),\n        ];\n      });\n    }, []);\n\n    return (\n      <Wrapper>\n        <Hierarchical\n          inputValue={searchText}\n          onInputChange={handleInputChange}\n          label=\"Categories\"\n          placeholder=\"Start Typing\"\n          noOptionsText=\"No results found\"\n          options={filteredOptions}\n          onChange={handleChange}\n        />\n      </Wrapper>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/hierarchical/test/hierarchical.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n// eslint-disable-next-line import/no-internal-modules -- Importing testUtils is OK.\nimport { renderWithProviders } from '@googleforcreators/design-system/src/testUtils';\n\n/**\n * Internal dependencies\n */\nimport Hierarchical, { makeFlatOptionTree } from '..';\nimport { noop } from '../../../../utils/noop';\n\nconst OPTIONS = [\n  { id: 1, label: 'apple', checked: false },\n  { id: 'fitty', label: 'corgi', checked: true, parent: 1 },\n  { id: 'sixty', label: 'morgi', checked: true, parent: 1 },\n  { id: 'gritty', label: 'borky', checked: true, parent: 'sixty' },\n  { id: 2, label: 'banana', checked: false },\n  { id: 3, label: 'cantaloupe', checked: true },\n  { id: 4, label: 'papaya', checked: false },\n  { id: '100', label: 'trees', checked: true, parent: 4 },\n  { id: '1001', label: 'porgi', checked: true, parent: '100' },\n  { id: '10011', label: 'hal', checked: true, parent: '100' },\n  { id: 5, label: 'zebra fish', checked: true },\n];\n\ndescribe('Hierarchical', () => {\n  it('clicking a checkbox should call onChange with the path and new value', () => {\n    const onChange = jest.fn();\n\n    renderWithProviders(\n      <Hierarchical\n        inputValue=\"\"\n        onInputChange={noop}\n        label=\"Categories\"\n        options={makeFlatOptionTree(OPTIONS)}\n        onChange={onChange}\n        noOptionsText=\"no options found\"\n      />\n    );\n\n    const initialCheckboxLength = screen.getAllByRole('checkbox').length;\n\n    const appleCheckbox = screen.getByRole('checkbox', { name: 'apple' });\n    const morgiCheckbox = screen.getByRole('checkbox', { name: 'morgi' });\n    const treesCheckbox = screen.getByRole('checkbox', { name: 'trees' });\n    const zebraFishCheckbox = screen.getByRole('checkbox', {\n      name: 'zebra fish',\n    });\n\n    fireEvent.click(appleCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: 1,\n      checked: true,\n    });\n\n    fireEvent.click(morgiCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: 'sixty',\n      checked: false,\n    });\n\n    fireEvent.click(treesCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: '100',\n      checked: false,\n    });\n\n    fireEvent.click(zebraFishCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: 5,\n      checked: false,\n    });\n\n    expect(screen.getAllByRole('checkbox')).toHaveLength(initialCheckboxLength);\n  });\n\n  it('should check the correct box when items are filtered', () => {\n    const onChange = jest.fn();\n\n    renderWithProviders(\n      <Hierarchical\n        inputValue=\"orgi\"\n        onInputChange={noop}\n        label=\"Categories\"\n        options={makeFlatOptionTree(OPTIONS, 'orgi')}\n        onChange={onChange}\n        noOptionsText=\"no options found\"\n      />\n    );\n\n    const initialCheckboxLength = screen.getAllByRole('checkbox').length;\n\n    const appleCheckbox = screen.getByRole('checkbox', { name: 'apple' });\n    const morgiCheckbox = screen.getByRole('checkbox', { name: 'morgi' });\n\n    fireEvent.click(appleCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: 1,\n      checked: true,\n    });\n\n    fireEvent.click(morgiCheckbox);\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), {\n      id: 'sixty',\n      checked: false,\n    });\n\n    expect(screen.getAllByRole('checkbox')).toHaveLength(initialCheckboxLength);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/hierarchical/test/utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { filterOptionsByLabelText, makeFlatOptionTree } from '../utils';\n\nconst OPTIONS = [\n  {\n    id: 1,\n    label: 'apple',\n    checked: false,\n    options: [\n      { id: 'fitty', label: 'corgi', checked: true, options: [] },\n      {\n        id: 'sixty',\n        label: 'morgi',\n        checked: true,\n        options: [{ id: 'gritty', label: 'borky', checked: true, options: [] }],\n      },\n    ],\n  },\n  { id: 2, label: 'banana', checked: false, options: [] },\n  { id: 3, label: 'cantaloupe', checked: true, options: [] },\n  {\n    id: 4,\n    label: 'papaya',\n    checked: false,\n    options: [\n      {\n        id: '100',\n        label: 'trees',\n        checked: true,\n        options: [\n          { id: '1001', label: 'porgi', checked: true, options: [] },\n          { id: '10011', label: 'hal', checked: true, options: [] },\n        ],\n      },\n    ],\n  },\n  { id: 5, label: 'zebra fish', checked: true, options: [] },\n];\n\ndescribe('filterOptionsByLabelText', () => {\n  it('should do no filtering with no text', () => {\n    expect(filterOptionsByLabelText(OPTIONS, '')).toStrictEqual(OPTIONS);\n    expect(filterOptionsByLabelText(OPTIONS, '     ')).toStrictEqual(OPTIONS);\n    expect(filterOptionsByLabelText(OPTIONS)).toStrictEqual(OPTIONS);\n  });\n\n  it('should filter a list of options', () => {\n    expect(\n      filterOptionsByLabelText(OPTIONS, 'this will not match anything')\n    ).toStrictEqual([]);\n    expect(filterOptionsByLabelText(OPTIONS, '   apple    ')).toStrictEqual([\n      {\n        checked: false,\n        id: 1,\n        label: 'apple',\n        options: [],\n      },\n    ]);\n    expect(filterOptionsByLabelText(OPTIONS, 'org')).toStrictEqual([\n      {\n        checked: false,\n        id: 1,\n        label: 'apple',\n        options: [\n          { checked: true, id: 'fitty', label: 'corgi', options: [] },\n          {\n            checked: true,\n            id: 'sixty',\n            label: 'morgi',\n            options: [],\n          },\n        ],\n      },\n      {\n        checked: false,\n        id: 4,\n        label: 'papaya',\n        options: [\n          {\n            checked: true,\n            id: '100',\n            label: 'trees',\n            options: [\n              { checked: true, id: '1001', label: 'porgi', options: [] },\n            ],\n          },\n        ],\n      },\n    ]);\n  });\n});\n\ndescribe('makeFlatOptionTree', () => {\n  it('appends $level prop if tree is flat', () => {\n    const flatOptionTree = makeFlatOptionTree([\n      {\n        id: 'something',\n        label: 'something',\n        parent: 0,\n      },\n      {\n        id: 'something-else',\n        label: 'something-else',\n        parent: 0,\n      },\n    ]);\n\n    expect(flatOptionTree).toStrictEqual([\n      {\n        id: 'something',\n        label: 'something',\n        parent: 0,\n        $level: 0,\n      },\n      {\n        id: 'something-else',\n        label: 'something-else',\n        parent: 0,\n        $level: 0,\n      },\n    ]);\n  });\n\n  it('adds proper $level to children options', () => {\n    const flatOptionTree = makeFlatOptionTree([\n      {\n        id: 'a',\n        label: 'a',\n        parent: 0,\n      },\n      {\n        id: 'b',\n        label: 'b',\n        parent: 0,\n      },\n      {\n        id: 'aa',\n        label: 'aa',\n        parent: 'a',\n      },\n      {\n        id: 'bb',\n        label: 'bb',\n        parent: 'b',\n      },\n      {\n        id: 'ab',\n        label: 'ab',\n        parent: 'a',\n      },\n      {\n        id: 'bbb',\n        label: 'bbb',\n        parent: 'bb',\n      },\n    ]);\n\n    expect(flatOptionTree).toStrictEqual([\n      {\n        id: 'a',\n        label: 'a',\n        parent: 0,\n        $level: 0,\n      },\n      {\n        id: 'aa',\n        label: 'aa',\n        parent: 'a',\n        $level: 1,\n      },\n      {\n        id: 'ab',\n        label: 'ab',\n        parent: 'a',\n        $level: 1,\n      },\n      {\n        id: 'b',\n        label: 'b',\n        parent: 0,\n        $level: 0,\n      },\n      {\n        id: 'bb',\n        label: 'bb',\n        parent: 'b',\n        $level: 1,\n      },\n      {\n        id: 'bbb',\n        label: 'bbb',\n        parent: 'bb',\n        $level: 2,\n      },\n    ]);\n  });\n\n  it('orders children beneath root entries', () => {\n    const findOpt = (id) => (opt) => opt.id === id;\n\n    const flatOptionTree = makeFlatOptionTree([\n      {\n        id: 'a',\n        label: 'a',\n        parent: 0,\n      },\n      {\n        id: 'b',\n        label: 'b',\n        parent: 0,\n      },\n      {\n        id: 'aa',\n        label: 'aa',\n        parent: 'a',\n      },\n      {\n        id: 'bb',\n        label: 'bb',\n        parent: 'b',\n      },\n      {\n        id: 'ab',\n        label: 'ab',\n        parent: 'a',\n      },\n      {\n        id: 'bbb',\n        label: 'bbb',\n        parent: 'bb',\n      },\n    ]);\n\n    const getIndex = (id) => flatOptionTree.findIndex(findOpt(id));\n    const isInOrder = (...args) =>\n      args.every(\n        //eslint-disable-next-line jest/no-conditional-in-test\n        (el, i, _args) => i === 0 || getIndex(_args[i - 1]) < getIndex(el)\n      );\n\n    // sibling order doesn't matter, so that's why we dont\n    // test aa vs ab\n    expect(isInOrder('a', 'aa', 'b', 'bb', 'bbb')).toBeTrue();\n    expect(isInOrder('a', 'ab', 'b', 'bb', 'bbb')).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/hierarchical/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Creates an object composed of keys generated from the\n * values of the `key` in each object.\n *\n * @param {Array.<Object>} arr The array to iterate over\n * @param {string|number|undefined|null|boolean} key The key used to group the array items.\n * @return {Object} The composed object\n */\nconst groupBy = (arr, key) =>\n  arr.reduce((prev, arrItem) => {\n    if (prev[arrItem[key]]) {\n      prev[arrItem[key]].push(arrItem);\n    } else {\n      prev[arrItem[key]] = [arrItem];\n    }\n    return prev;\n  }, {});\n\n/**\n * Composes a tree from an array of options that are related.\n * Can be parents or children as defined by the `parent` key.\n *\n * @param {Object} groupedOptionsByParent A object of options grouped by parent key.\n * @param {Array.<Object>} options A flat array of options.\n * @return {Array.<Object>} A tree of options\n */\nconst fillTree = (groupedOptionsByParent, options = []) => {\n  return options.map((option) => {\n    const children = groupedOptionsByParent[option.id];\n\n    return {\n      ...option,\n      options:\n        children && children.length\n          ? fillTree(groupedOptionsByParent, children)\n          : [],\n    };\n  });\n};\n\n/**\n * Returns options in a tree form.\n *\n * Works similarly to Gutenberg Editor:\n * https://github.com/WordPress/gutenberg/blob/3f9968e2815cfb56684c1acc9a2700d8e4a02726/packages/editor/src/utils/terms.js#L13-L40\n *\n * @param {Array} flatOptions Array of terms in flat format.\n * @return {Array} Array of terms in tree format.\n */\nexport const buildOptionsTree = (flatOptions) => {\n  const formattedOptions = flatOptions.map((option) => ({\n    options: [],\n    // Categories with no parent will have a parent id of 0\n    parent: 0,\n    ...option,\n  }));\n\n  const groupedOptionsByParent = groupBy(formattedOptions, 'parent');\n\n  return fillTree(groupedOptionsByParent, groupedOptionsByParent[0]);\n};\n\n/**\n * Filters an option and its children based on the label text. Only returns an option iff:\n * 1. The option's label includes the `labelText`\n * 2. The label of a child of the option includes the `labelText`\n *\n * Returns a list with a new option. This option's children (and all nested children) will\n * also match the label text. If there are no children that match the label text then\n * no children will be returned.\n *\n * @param {Object} option The option to check\n * @param {string} labelText The text to match\n * @return {Array.<Object>} A filtered list of options\n */\nexport const filterOption = (option, labelText = '') => {\n  const { options, ...rest } = option;\n  let newChildren = [];\n\n  // Find if any children match\n  if (options) {\n    for (let i = 0; i < options.length; i++) {\n      newChildren = newChildren.concat(filterOption(options[i], labelText));\n    }\n  }\n\n  // Find if current option matches\n  const matchesCurrentOption = option.label\n    .toLowerCase()\n    .includes(labelText.trim().toLowerCase());\n\n  // create new option with new children\n  const newOption = { ...rest, options: newChildren };\n\n  // Return the filtered option if the current option matches or\n  // if option has children that match the label text\n  return matchesCurrentOption || newChildren.length ? [newOption] : [];\n};\n\n/**\n * Filters a list of options based on the label text. Only returns an option iff:\n * 1. The option's label includes the `labelText`\n * 2. The label of a child of the option includes the `labelText`\n *\n * @param {Array.<Object>} options The option to filter\n * @param {string} labelText The text to match\n * @return {Array.<Object>} A filtered list of options\n */\nexport const filterOptionsByLabelText = (options, labelText) =>\n  options.reduce(\n    (all, option) => all.concat(filterOption(option, labelText)),\n    []\n  );\n\n/**\n * Flattens a tree of options. Order is preserved ->\n * all children will follow each parent option.\n *\n * @param {Array.<Object>} optionTree Array of nested options\n * @param {number} level The nesting level\n * @return {Array.<Object>} Flat array of options, ordered by parent\n */\nfunction flattenOptionTree(optionTree = [], level = 0) {\n  return optionTree.flatMap(({ options, ...option }) => [\n    {\n      ...option,\n      $level: level,\n    },\n    ...flattenOptionTree(options, level + 1),\n  ]);\n}\n\n/**\n * Create a filtered and flattened, ordered list of options.\n *\n * @param {Array.<Object>} categories Unordered of categories\n * @param {string} labelText The text to filter by\n * @return {Array.<Object>} The flattened and filtered list of options\n */\nexport function makeFlatOptionTree(categories, labelText = '') {\n  const optionTree = buildOptionsTree(categories);\n  const filteredOptionTree = filterOptionsByLabelText(optionTree, labelText);\n  return flattenOptionTree(filteredOptionTree);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/form/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Color } from './color';\nexport { default as FilterToggle } from './filterToggle';\nexport { default as LinkIcon } from './linkIcon';\nexport { default as LinkInput } from './link';\nexport { default as Media } from './media';\nexport { default as MediaUploadButton } from './mediaUploadButton';\nexport { default as Row } from './row';\nexport { default as Switch } from './switch';\nexport { default as TextArea } from './textArea';\nexport { default as usePresubmitHandler } from './usePresubmitHandler';\nexport { default as DateTime } from './dateTime';\nexport { default as Required } from './required';\nexport { default as RadioGroup } from './radioGroup';\nexport { default as Select } from './select';\nexport {\n  default as HierarchicalInput,\n  makeFlatOptionTree,\n} from './hierarchical';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/link.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { forwardRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Input } from '@googleforcreators/design-system';\nimport { isValidUrl, withProtocol } from '@googleforcreators/url';\n\n/**\n * Internal dependencies\n */\nimport { inputContainerStyleOverride } from '../panels/shared/styles';\nimport Row from './row';\n\nconst MIN_MAX = {\n  URL: {\n    MIN: 2,\n    MAX: 2048, // Based on sitemaps url limits (safe side)\n  },\n};\n\nconst LinkInput = forwardRef(function LinkInput(\n  { onChange, onBlur, onFocus, value = '', hint, hasError, ...rest },\n  ref\n) {\n  const trimmedValue = (value || '').trim();\n  const isValid = isValidUrl(withProtocol(trimmedValue));\n  const isNotValid = trimmedValue.length > 0 && !isValid;\n  return (\n    <Row>\n      <Input\n        ref={ref}\n        placeholder={__('Web address', 'web-stories')}\n        onChange={(evt) => onChange(evt.target.value)}\n        onBlur={() => {\n          if (trimmedValue?.length) {\n            const urlWithProtocol = withProtocol(trimmedValue);\n            if (urlWithProtocol !== trimmedValue) {\n              onChange(urlWithProtocol);\n            }\n          }\n          if (onBlur) {\n            onBlur();\n          }\n        }}\n        onFocus={onFocus}\n        value={value || ''}\n        minLength={MIN_MAX.URL.MIN}\n        maxLength={MIN_MAX.URL.MAX}\n        hasError={isNotValid || hasError}\n        hint={isNotValid ? __('Invalid web address.', 'web-stories') : hint}\n        containerStyleOverride={inputContainerStyleOverride}\n        type=\"url\"\n        {...rest}\n      />\n    </Row>\n  );\n});\n\nLinkInput.propTypes = {\n  value: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n  onFocus: PropTypes.func,\n  onBlur: PropTypes.func,\n  hint: PropTypes.string,\n  hasError: PropTypes.bool,\n};\n\nexport default LinkInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/linkIcon.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useMemo } from '@googleforcreators/react';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport { MediaVariant } from '@googleforcreators/design-system';\nimport { useConfig } from '../../app';\nimport Media from './media';\n\nconst StyledMedia = styled(Media)`\n  width: 54px;\n  height: 54px;\n`;\n\nfunction LinkIcon({ handleChange, icon, isLoading = false, ...rest }) {\n  const {\n    allowedMimeTypes: { image: allowedImageMimeTypes },\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const allowedImageFileTypes = useMemo(\n    () =>\n      allowedImageMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedImageMimeTypes]\n  );\n\n  const iconErrorMessage = useMemo(() => {\n    let message = __(\n      'No image file types are currently supported.',\n      'web-stories'\n    );\n\n    if (allowedImageFileTypes.length) {\n      message = sprintf(\n        /* translators: %s: list of allowed file types. */\n        __('Please choose only %s as an icon.', 'web-stories'),\n        translateToExclusiveList(allowedImageFileTypes)\n      );\n    }\n\n    return message;\n  }, [allowedImageFileTypes]);\n\n  const options = [\n    hasUploadMediaAction && 'upload',\n    'hotlink',\n    icon && 'remove',\n  ].filter(Boolean);\n\n  return (\n    <StyledMedia\n      value={icon || ''}\n      cropParams={{\n        width: 96,\n        height: 96,\n      }}\n      onChange={handleChange}\n      onChangeErrorText={iconErrorMessage}\n      title={__('Select as link icon', 'web-stories')}\n      ariaLabel={__('Edit link icon', 'web-stories')}\n      buttonInsertText={__('Select as link icon', 'web-stories')}\n      hotlinkTitle={__('Use external image as link icon', 'web-stories')}\n      hotlinkInsertText={__('Use image as link icon', 'web-stories')}\n      hotlinkInsertingText={__('Using image as link icon', 'web-stories')}\n      type={allowedImageMimeTypes}\n      isLoading={isLoading}\n      variant={MediaVariant.Circle}\n      canUpload={options.length !== 0}\n      menuOptions={options}\n      {...rest}\n    />\n  );\n}\n\nLinkIcon.propTypes = {\n  icon: PropTypes.string,\n  isLoading: PropTypes.bool,\n  disabled: PropTypes.bool,\n  handleChange: PropTypes.func.isRequired,\n};\n\nexport default LinkIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/media.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, forwardRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  MediaInput as Input,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app';\nimport { MULTIPLE_VALUE } from '../../constants';\nimport HotlinkModal from '../hotlinkModal';\nimport useHotlink from './useHotlink';\n\nconst StyledInput = styled(Input)`\n  button:focus {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )}\n  }\n`;\n\nconst MediaInputField = ({\n  open,\n  openHotlink,\n  dropdownOptions,\n  onChange,\n  forwardedRef,\n  value,\n  ...rest\n}) => {\n  const onMenuOption = useCallback(\n    (evt, opt) => {\n      switch (opt) {\n        case 'upload':\n          open(evt);\n          break;\n        case 'hotlink':\n          openHotlink(evt);\n          break;\n        case 'remove':\n        case 'reset':\n          onChange(null);\n          break;\n        default:\n          break;\n      }\n    },\n    [onChange, open, openHotlink]\n  );\n\n  return (\n    <StyledInput\n      onMenuOption={onMenuOption}\n      menuOptions={dropdownOptions}\n      openMediaPicker={open}\n      ref={forwardedRef}\n      value={value === MULTIPLE_VALUE ? null : value}\n      {...rest}\n    />\n  );\n};\n\nfunction MediaInput(\n  {\n    buttonInsertText = __('Choose an image', 'web-stories'),\n    hotlinkTitle = __('Use external image', 'web-stories'),\n    hotlinkInsertText = __('Use image', 'web-stories'),\n    hotlinkInsertingText = __('Using image', 'web-stories'),\n    menuOptions = [],\n    onChange,\n    onChangeErrorText = __(\n      'Unable to use this file type, please select a valid image type.',\n      'web-stories'\n    ),\n    title = __('Choose an image', 'web-stories'),\n    type = 'image',\n    value,\n    cropParams,\n    canUseProxy = false,\n    ...rest\n  },\n  forwardedRef\n) {\n  const { MediaUpload } = useConfig();\n  const {\n    actions: { onSelect, openHotlink, onCloseHotlink },\n    state: { allowedFileTypes, isOpen },\n  } = useHotlink({ onChange, type, canUseProxy });\n\n  const renderMediaIcon = useCallback(\n    (open) => {\n      // Options available for the media input menu.\n      const availableMenuOptions = [\n        { label: __('Upload a file', 'web-stories'), value: 'upload' },\n        { label: __('Link to a file', 'web-stories'), value: 'hotlink' },\n        { label: __('Remove', 'web-stories'), value: 'remove' },\n        { label: __('Reset', 'web-stories'), value: 'reset' },\n      ];\n\n      // No menu for mixed value.\n      // Match the options from props, if none are matched, menu is not displayed.\n      const dropdownOptions =\n        value === MULTIPLE_VALUE\n          ? []\n          : availableMenuOptions.filter(({ value: option }) =>\n              menuOptions.includes(option)\n            );\n      return (\n        <MediaInputField\n          open={open}\n          openHotlink={openHotlink}\n          onChange={onChange}\n          dropdownOptions={dropdownOptions}\n          forwardedRef={forwardedRef}\n          value={value}\n          {...rest}\n        />\n      );\n    },\n    [value, openHotlink, onChange, forwardedRef, rest, menuOptions]\n  );\n\n  return (\n    <>\n      <HotlinkModal\n        isOpen={isOpen}\n        title={hotlinkTitle}\n        onSelect={onSelect}\n        onClose={onCloseHotlink}\n        insertText={hotlinkInsertText}\n        insertingText={hotlinkInsertingText}\n        allowedFileTypes={allowedFileTypes}\n        canUseProxy={canUseProxy}\n        requiredImgDimensions={cropParams}\n      />\n      <MediaUpload\n        title={title}\n        buttonInsertText={buttonInsertText}\n        onSelect={onChange}\n        onSelectErrorMessage={onChangeErrorText}\n        type={type}\n        cropParams={cropParams}\n        render={renderMediaIcon}\n      />\n    </>\n  );\n}\n\nconst MediaInputWithRef = forwardRef(MediaInput);\n\nMediaInputField.propTypes = {\n  open: PropTypes.func,\n  openHotlink: PropTypes.func,\n  dropdownOptions: PropTypes.array,\n  onChange: PropTypes.func,\n  forwardedRef: PropTypes.oneOfType([\n    PropTypes.func,\n    PropTypes.shape({ current: PropTypes.elementType }),\n  ]),\n  value: PropTypes.string,\n};\n\nMediaInput.propTypes = {\n  className: PropTypes.string,\n  buttonInsertText: PropTypes.string,\n  hotlinkTitle: PropTypes.string,\n  hotlinkInsertText: PropTypes.string,\n  hotlinkInsertingText: PropTypes.string,\n  menuOptions: PropTypes.array,\n  onChange: PropTypes.func.isRequired,\n  onChangeErrorText: PropTypes.string,\n  type: PropTypes.oneOfType([\n    PropTypes.string,\n    PropTypes.arrayOf(PropTypes.string),\n  ]),\n  cropParams: PropTypes.object,\n  canUseProxy: PropTypes.bool,\n  title: PropTypes.string,\n  value: PropTypes.string,\n};\n\nexport default MediaInputWithRef;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/mediaUploadButton.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useConfig, useLocalMedia } from '../../app';\nimport useFFmpeg from '../../app/media/utils/useFFmpeg';\nimport { TRANSCODABLE_MIME_TYPES } from '../../app/media';\n\nfunction MediaUploadButton({ onInsert, renderButton, buttonInsertText }) {\n  const {\n    allowedMimeTypes: {\n      image: allowedImageMimeTypes,\n      vector: allowedVectorMimeTypes,\n      video: allowedVideoMimeTypes,\n    },\n    MediaUpload,\n  } = useConfig();\n\n  const allowedUploadMimeTypes = useMemo(\n    () => [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ],\n    [allowedImageMimeTypes, allowedVectorMimeTypes, allowedVideoMimeTypes]\n  );\n  const allowedFileTypes = useMemo(\n    () =>\n      allowedUploadMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedUploadMimeTypes]\n  );\n\n  const {\n    canTranscodeResource,\n    resetWithFetch,\n    postProcessingResource,\n    optimizeVideo,\n    optimizeGif,\n  } = useLocalMedia(\n    ({\n      state: { canTranscodeResource },\n      actions: {\n        resetWithFetch,\n        postProcessingResource,\n        optimizeVideo,\n        optimizeGif,\n      },\n    }) => {\n      return {\n        canTranscodeResource,\n        resetWithFetch,\n        postProcessingResource,\n        optimizeVideo,\n        optimizeGif,\n      };\n    }\n  );\n  const { isTranscodingEnabled } = useFFmpeg();\n  const { showSnackbar } = useSnackbar();\n\n  const allowedMimeTypes = useMemo(() => {\n    if (isTranscodingEnabled) {\n      return [\n        ...TRANSCODABLE_MIME_TYPES,\n        ...allowedImageMimeTypes,\n        ...allowedVectorMimeTypes,\n        ...allowedVideoMimeTypes,\n      ];\n    }\n    return [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ];\n  }, [\n    allowedImageMimeTypes,\n    allowedVectorMimeTypes,\n    allowedVideoMimeTypes,\n    isTranscodingEnabled,\n  ]);\n\n  let onSelectErrorMessage = __(\n    'No file types are currently supported.',\n    'web-stories'\n  );\n  if (allowedFileTypes.length) {\n    onSelectErrorMessage = sprintf(\n      /* translators: %s: list of allowed file types. */\n      __('Please choose only %s to insert into page.', 'web-stories'),\n      translateToExclusiveList(allowedFileTypes)\n    );\n  }\n\n  const onSelect = useCallback(\n    (resource) => {\n      try {\n        if (isTranscodingEnabled && canTranscodeResource(resource)) {\n          if (\n            !resource.isOptimized &&\n            TRANSCODABLE_MIME_TYPES.includes(resource.mimeType)\n          ) {\n            optimizeVideo({ resource });\n          }\n\n          if (resource.mimeType === 'image/gif') {\n            optimizeGif({ resource });\n          }\n        }\n        onInsert(resource);\n\n        postProcessingResource(resource);\n      } catch (e) {\n        showSnackbar({\n          message: e.message,\n          dismissible: true,\n        });\n      }\n    },\n    [\n      isTranscodingEnabled,\n      canTranscodeResource,\n      onInsert,\n      optimizeGif,\n      optimizeVideo,\n      postProcessingResource,\n      showSnackbar,\n    ]\n  );\n\n  return (\n    <MediaUpload\n      onSelect={onSelect}\n      onSelectErrorMessage={onSelectErrorMessage}\n      onClose={resetWithFetch}\n      type={allowedMimeTypes}\n      render={renderButton}\n      buttonInsertText={buttonInsertText}\n    />\n  );\n}\n\nMediaUploadButton.propTypes = {\n  onInsert: PropTypes.func.isRequired,\n  renderButton: PropTypes.func.isRequired,\n  buttonInsertText: PropTypes.string,\n};\n\nexport default MediaUploadButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/radioGroup/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo, useRef } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { Radio, themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useRadioNavigation from '../shared/useRadioNavigation';\n\nconst VisuallyHiddenLabel = styled.h3`\n  ${themeHelpers.visuallyHidden};\n`;\n\nconst StyledRadio = styled(Radio)`\n  input:focus + span,\n  input:focus-visible + span {\n    ${({ theme }) =>\n      `box-shadow: 0px 0px 0 2px ${theme.colors.bg.secondary}, 0px 0px 0 4px ${theme.colors.border.focus} !important;`};\n  }\n`;\n\nfunction RadioGroup({\n  className,\n  groupLabel,\n  id,\n  name,\n  options,\n  value: selectedValue,\n  ...radioButtonProps\n}) {\n  const groupId = useMemo(() => id || uuidv4(), [id]);\n  const groupRef = useRef(null);\n  useRadioNavigation(groupRef);\n\n  return (\n    <div\n      className={className}\n      ref={groupRef}\n      role=\"radiogroup\"\n      aria-labelledby={groupId}\n    >\n      <VisuallyHiddenLabel id={groupId}>{groupLabel}</VisuallyHiddenLabel>\n      {options.map(({ helper = '', label, value, disabled }) => (\n        <StyledRadio\n          key={value}\n          name={name}\n          value={value}\n          checked={value === selectedValue}\n          label={label}\n          hint={helper}\n          disabled={disabled}\n          {...radioButtonProps}\n        />\n      ))}\n    </div>\n  );\n}\nRadioGroup.propTypes = {\n  className: PropTypes.string,\n  groupLabel: PropTypes.string.isRequired,\n  id: PropTypes.string,\n  name: PropTypes.string.isRequired,\n  onChange: PropTypes.func.isRequired,\n  options: PropTypes.arrayOf(\n    PropTypes.shape({\n      helper: PropTypes.string,\n      label: PropTypes.string.isRequired,\n      value: PropTypes.string.isRequired,\n    })\n  ).isRequired,\n  value: PropTypes.string.isRequired,\n};\n\nexport default RadioGroup;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/required.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { _x } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nconst RequiredWrapper = styled.div`\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-start;\n  align-items: center;\n`;\n\nconst StyledText = styled(Text.Paragraph).attrs({\n  as: 'span',\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  font-size: 12px;\n`;\n\nfunction Required() {\n  return (\n    <RequiredWrapper>\n      <StyledText>\n        {_x('Required', 'Required form input', 'web-stories')}\n      </StyledText>\n    </RequiredWrapper>\n  );\n}\n\nexport default Required;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/row.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\nconst Row = styled.div`\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-start;\n  align-items: center;\n  margin-bottom: 16px;\n\n  ${({ spaceBetween = true }) =>\n    spaceBetween && `justify-content: space-between;`}\n  ${({ expand = true }) => expand && `flex: 1;`}\n`;\n\nexport default Row;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/select/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './select';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/select/select.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { DropDown } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../panels/shared/styles';\n\nconst Container = styled.div`\n  position: relative;\n  width: 100%;\n`;\n\nconst StyledDropDown = styled(DropDown)`\n  background-color: transparent;\n  border: 0;\n  width: auto;\n`;\n\nconst menuStylesOverride = css`\n  top: -14px;\n  right: unset;\n  width: auto;\n`;\n\nconst selectButtonStylesOverride = css`\n  border: none;\n  width: auto;\n  margin-right: auto;\n  padding-left: 0;\n\n  ${focusStyle};\n`;\n\nconst selectValueStylesOverride = css`\n  margin-right: 0;\n`;\n\nfunction Select(props) {\n  return (\n    <Container>\n      <StyledDropDown\n        isInline\n        hasSearch={false}\n        menuStylesOverride={menuStylesOverride}\n        selectButtonStylesOverride={selectButtonStylesOverride}\n        selectValueStylesOverride={selectValueStylesOverride}\n        {...props}\n      />\n    </Container>\n  );\n}\n\nexport default Select;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/shared/useRadioNavigation.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\nfunction useRadioNavigation(ref) {\n  const changeCurrent = useCallback(\n    (direction) => {\n      const radioGroup = ref.current;\n      if (!radioGroup) {\n        return;\n      }\n      const list = Array.from(\n        radioGroup.querySelectorAll('input[type=\"radio\"]')\n      );\n\n      // Find index of currently focused input\n      const currentIndex = list.indexOf(document.activeElement);\n      if (currentIndex === -1) {\n        return;\n      }\n\n      // Find new index, if outside range = ignore it\n      const newIndex = currentIndex + direction;\n      if (newIndex < 0 || newIndex >= list.length) {\n        return;\n      }\n\n      // Now select this one\n      list[newIndex].focus();\n      list[newIndex].click();\n    },\n    [ref]\n  );\n  const handlePrevious = useCallback(() => changeCurrent(-1), [changeCurrent]);\n  useKeyDownEffect(ref, ['up', 'left'], handlePrevious, [handlePrevious]);\n  const handleNext = useCallback(() => changeCurrent(1), [changeCurrent]);\n  useKeyDownEffect(ref, ['down', 'right'], handleNext, [handleNext]);\n}\n\nexport default useRadioNavigation;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stackable/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as StackableGroup } from './stackableGroup';\nexport { default as StackableInput } from './stackableInput';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stackable/stackableGroup.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport StackableInput from './stackableInput';\n\n/**\n * Internal dependencies\n */\n\nconst StackableContainer = styled.div`\n  display: flex;\n  max-width: ${({ locked }) => (locked ? '106px' : 'none')};\n\n  & > ${StackableInput} {\n    border-radius: 0;\n\n    &:first-of-type > div {\n      border-top-left-radius: 4px;\n      border-bottom-left-radius: 4px;\n      margin-left: 0;\n    }\n\n    &:last-of-type > div {\n      border-top-right-radius: 4px;\n      border-bottom-right-radius: 4px;\n    }\n  }\n\n  ${({ $stackableGroupStyleOverride }) => $stackableGroupStyleOverride}\n`;\n\nfunction StackableGroup({\n  children,\n  locked,\n  className,\n  stackableGroupStyleOverride,\n}) {\n  return (\n    <StackableContainer\n      $stackableGroupStyleOverride={stackableGroupStyleOverride}\n      locked={locked}\n      className={className}\n    >\n      {children}\n    </StackableContainer>\n  );\n}\n\nStackableGroup.propTypes = {\n  children: PropTypes.node,\n  locked: PropTypes.bool,\n  className: PropTypes.string,\n  stackableGroupStyleOverride: PropTypes.array,\n};\n\nexport default StackableGroup;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stackable/stackableInput.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport styled, { css } from 'styled-components';\nimport { NumericInput, themeHelpers } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\n\nconst inputContainerStyleOverride = css`\n  position: relative;\n  :focus-within {\n    z-index: 1;\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst iconCss = css`\n  width: 29px;\n  height: 29px;\n`;\n\nconst StackableInput = styled(NumericInput)`\n  svg {\n    ${iconCss}\n  }\n  & > div {\n    border-radius: 0;\n    margin-left: -1px;\n    padding: 2px 7px 2px 12px;\n    ${inputContainerStyleOverride};\n  }\n`;\n\nexport default StackableInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stories/link.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport LinkInput from '../link';\n\nexport default {\n  title: 'Stories Editor/Components/Form/Link',\n  component: LinkInput,\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nconst Container = styled.div`\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nexport const _default = {\n  render: function Render() {\n    const [value, setValue] = useState('https://test.com');\n    const onChange = (newValue) => {\n      setValue(newValue);\n    };\n    return (\n      <Container>\n        <LinkInput\n          hint={__('Type an address to add a link', 'web-stories')}\n          onChange={onChange}\n          onFocus={() => {}}\n          value={value}\n          clear\n          aria-label={__('Test URL', 'web-stories')}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stories/radioGroup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport RadioGroup from '../radioGroup';\n\nexport default {\n  title: 'Stories Editor/Components/Form/RadioGroup',\n  component: RadioGroup,\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render() {\n    const options = [\n      {\n        value: 'a',\n        label: __('Option A', 'web-stories'),\n        helper: __('This is the best option', 'web-stories'),\n      },\n      {\n        value: 'b',\n        label: __('Option B', 'web-stories'),\n        helper: __('Also a good option', 'web-stories'),\n      },\n      {\n        value: 'c',\n        label: __('Option C without description', 'web-stories'),\n      },\n    ];\n    const [value, setValue] = useState('a');\n\n    return (\n      <RadioGroup\n        name=\"test-group\"\n        options={options}\n        onChange={(evt) => setValue(evt.target.value)}\n        value={value}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stories/switch.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Switch from '../switch';\n\nexport default {\n  title: 'Stories Editor/Components/Form/Switch',\n  component: Switch,\n  args: {\n    onLabel: 'Fit to Device',\n    offLabel: 'Do not format',\n    disabled: false,\n  },\n  argTypes: {\n    handleChange: { action: 'Switching' },\n  },\n};\n\nconst Container = styled.div`\n  padding: 20px 50px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.standard.black};\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const [value, setValue] = useState(true);\n\n    const handleChange = (evt, newValue) => {\n      args.handleChange(`${newValue ? 'On' : 'Off'}`, evt);\n      setValue(newValue);\n    };\n\n    return (\n      <Container>\n        <Switch\n          groupLabel=\"Switch\"\n          name=\"test-switch\"\n          value={value}\n          onChange={handleChange}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/stories/tags.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport Tags from '../tags';\n\nconst Bg = styled.div`\n  height: calc(100vh - 32px);\n  background: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Wrapper = styled.div`\n  position: relative;\n  width: 250px;\n  inset: 15vh 0 0 0;\n  margin: auto;\n`;\n\nexport default {\n  title: 'Stories Editor/Components/Form/Tags',\n  component: Tags,\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <Bg>\n        <Wrapper>\n          <Tags.Label htmlFor=\"tags-input\">{'Add New Tag'}</Tags.Label>\n          <Tags.Input\n            id=\"tags-input\"\n            aria-describedby=\"tags-description\"\n            name=\"web_story_tag\"\n            suggestedTerms={[\n              { name: 'banana', id: 1 },\n              { name: 'anna', id: 2 },\n              { name: 'nana', id: 3 },\n            ]}\n          />\n          <Tags.Description id=\"tags-description\">\n            {'Separate with commas or the Enter key.'}\n          </Tags.Description>\n        </Wrapper>\n      </Bg>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/form/switch.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport {\n  Switch as BaseSwitch,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\nconst StyledSwitch = styled(BaseSwitch)`\n  label:focus-within ~ span {\n    ${({ theme }) =>\n      `box-shadow: 0px 0px 0 2px ${theme.colors.bg.secondary}, 0px 0px 0 4px ${theme.colors.border.focus} !important;`};\n  }\n`;\n\nfunction Switch({\n  offLabel = __('Off', 'web-stories'),\n  onChange,\n  onLabel = __('On', 'web-stories'),\n  value,\n  ...props\n}) {\n  const switchRef = useRef(null);\n\n  const handleToggleValue = useCallback(\n    (evt) => {\n      onChange(evt, !value);\n    },\n    [onChange, value]\n  );\n\n  useKeyDownEffect(\n    switchRef,\n    ['space', 'enter', 'left', 'right', 'up', 'down'],\n    handleToggleValue,\n    [handleToggleValue, value]\n  );\n\n  return (\n    <StyledSwitch\n      ref={switchRef}\n      offLabel={offLabel}\n      onChange={onChange}\n      onLabel={onLabel}\n      value={value}\n      {...props}\n    />\n  );\n}\nSwitch.propTypes = {\n  className: PropTypes.string,\n  disabled: PropTypes.bool,\n  groupLabel: PropTypes.string.isRequired,\n  id: PropTypes.string,\n  name: PropTypes.string.isRequired,\n  offLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,\n  onChange: PropTypes.func.isRequired,\n  onLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,\n  value: PropTypes.bool,\n  darkTheme: PropTypes.bool,\n};\n\nexport default Switch;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/description.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nexport default styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { default as Input } from './input';\nimport { default as Description } from './description';\nimport { default as Label } from './label';\n\nconst Tags = {\n  Input,\n  Description,\n  Label,\n};\n\nexport default Tags;\nexport { deepEquals } from './reducer';\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/input.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  themeHelpers,\n  BaseInput,\n  List,\n  noop,\n} from '@googleforcreators/design-system';\nimport {\n  useEffect,\n  useMemo,\n  useReducer,\n  useRef,\n  useState,\n  useCallback,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport reducer, { ACTIONS } from './reducer';\nimport Tag from './tag';\n\nconst INPUT_KEY = uuidv4();\n\nconst Border = styled.div`\n  ${({ theme, isInputFocused }) => css`\n    color: ${theme.colors.fg.primary};\n    border: 1px solid ${theme.colors.border.defaultNormal};\n    border-radius: ${theme.borders.radius.small};\n    ${isInputFocused && themeHelpers.focusCSS};\n  `}\n  display: flex;\n  flex-direction: column;\n  margin-bottom: 6px;\n`;\n\nconst InputWrapper = styled.div`\n  display: flex;\n  flex-wrap: wrap;\n  padding: 0;\n`;\n\nconst TextInput = styled(BaseInput).attrs({ type: 'text' })`\n  width: auto;\n  flex-grow: 1;\n  height: 32px;\n  margin: 2px 0;\n  padding-left: 4px;\n`;\n\nconst SuggestionList = styled(List)`\n  max-height: 120px;\n  overflow-y: scroll;\n  border-top: ${({ theme }) =>\n    `1px solid ${theme.colors.border.defaultNormal}`};\n  display: block;\n  list-style-type: none;\n  width: 100%;\n  padding: 6px 4px 4px;\n  margin-top: 6px;\n  li {\n    cursor: pointer;\n    padding: 4px;\n    width: 100%;\n    ${themeHelpers.focusableOutlineCSS()}\n    border-radius: ${({ theme }) => theme.borders.radius.small};\n\n    &:hover {\n      background-color: ${({ theme }) => theme.colors.bg.tertiary};\n    }\n  }\n`;\nfunction Input({\n  suggestedTerms = [],\n  onTagsChange,\n  onInputChange,\n  suggestedTermsLabel,\n  tagDisplayTransformer,\n  tokens = [],\n  onUndo = noop,\n  ...props\n}) {\n  const [{ value, tags, offset, tagBuffer }, dispatch] = useReducer(reducer, {\n    value: '',\n    tags: [...tokens],\n    tagBuffer: null,\n    offset: 0,\n  });\n\n  // isInputFocused is used to update the styled state of the input area.\n  const [isInputFocused, setIsInputFocused] = useState(false);\n  const [isSuggestionsOpen, setIsSuggestionsOpen] = useState(false);\n\n  // inputRef is used to return focus to input after keydown actions to avoid focused state being hijacked.\n  const inputRef = useRef();\n  const menuRef = useRef();\n  const containerRef = useRef();\n\n  useEffect(() => {\n    dispatch({ type: ACTIONS.UPDATE_TAGS, payload: tokens });\n  }, [tokens]);\n\n  const suggestionListId = uuidv4();\n  const totalSuggestions = suggestedTerms.length;\n  // suggestedTerms is returned from a debounced callback,\n  // we want to update isSuggestionsOpen via a useEffect to prevent sluggish closing.\n  useEffect(() => {\n    setIsSuggestionsOpen(totalSuggestions > 0);\n  }, [totalSuggestions]);\n\n  // Allow parents to pass onTagsChange callback\n  // that updates as tags does.\n  const onTagChangeRef = useRef(onTagsChange);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  onTagChangeRef.current = onTagsChange;\n  useEffect(() => {\n    if (!tagBuffer) {\n      return;\n    }\n    onTagChangeRef.current?.(tagBuffer);\n  }, [tagBuffer]);\n\n  // Allow parents to pass onInputChange callback\n  // that updates as value does.\n  const onInputChangeRef = useRef(onInputChange);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  onInputChangeRef.current = onInputChange;\n  useEffect(() => {\n    onInputChangeRef.current?.(value);\n  }, [value]);\n\n  // Prepare and memoize event handlers to be as self\n  // contained and descriptive as possible\n  const { handleFocus, handleBlur, handleKeyDown, handleChange, removeTag } =\n    useMemo(\n      () => ({\n        // Key interactions are modeled after WordPress Tag input UX\n        // and are only available when focused on the text input\n        handleKeyDown: (e) => {\n          if (e.target.value === '') {\n            if (e.key === 'ArrowLeft') {\n              dispatch({ type: ACTIONS.INCREMENT_OFFSET });\n            }\n            if (e.key === 'ArrowRight') {\n              dispatch({ type: ACTIONS.DECREMENT_OFFSET });\n            }\n            if (e.key === 'Backspace') {\n              dispatch({ type: ACTIONS.REMOVE_TAG });\n            }\n            if (e.key === 'z' && e.metaKey) {\n              onUndo(e);\n            }\n          }\n          if (e.key === 'ArrowDown' && suggestedTerms.length > 0) {\n            menuRef?.current?.firstChild?.focus();\n          }\n          if (['Comma', ',', 'Enter'].includes(e.key)) {\n            dispatch({ type: ACTIONS.SUBMIT_VALUE });\n          }\n        },\n        handleChange: (e) => {\n          dispatch({ type: ACTIONS.UPDATE_VALUE, payload: e.target.value });\n        },\n        removeTag: (tag) => () => {\n          dispatch({ type: ACTIONS.REMOVE_TAG, payload: tag });\n          inputRef?.current.focus();\n        },\n        handleFocus: () => {\n          setIsInputFocused(true);\n        },\n        handleBlur: () => {\n          dispatch({ type: ACTIONS.RESET_OFFSET });\n          setIsInputFocused(false);\n        },\n      }),\n      [onUndo, suggestedTerms]\n    );\n\n  const renderedTags = tagBuffer || tags;\n\n  const handleTagSelectedFromSuggestions = useCallback((e, selectedValue) => {\n    e.preventDefault();\n    setIsSuggestionsOpen(false);\n    dispatch({ type: ACTIONS.SUBMIT_VALUE, payload: selectedValue });\n    inputRef?.current.focus();\n  }, []);\n\n  const handleSuggestionKeyDown = useCallback(\n    (e, index, name) => {\n      const nextChild = index + 1;\n      const previousChild = index - 1;\n      if (e.key === 'ArrowDown') {\n        if (nextChild < totalSuggestions) {\n          menuRef?.current?.children?.[nextChild]?.focus();\n        }\n      }\n      if (e.key === 'ArrowUp') {\n        if (previousChild < 0) {\n          inputRef?.current.focus();\n        } else {\n          menuRef?.current?.children?.[previousChild]?.focus();\n        }\n      }\n      if (e.key === 'Enter') {\n        handleTagSelectedFromSuggestions(e, name);\n      }\n    },\n    [handleTagSelectedFromSuggestions, totalSuggestions]\n  );\n  return (\n    <Border ref={containerRef} isInputFocused={isInputFocused}>\n      <InputWrapper>\n        {\n          // Text input should move, relative to end, with offset\n          // this helps with natural tab order and visuals\n          // as you ArrowLeft or ArrowRight through tags\n          [\n            ...renderedTags.slice(0, renderedTags.length - offset),\n            INPUT_KEY,\n            ...renderedTags.slice(renderedTags.length - offset),\n          ].map((tag) =>\n            tag === INPUT_KEY ? (\n              <TextInput\n                key={INPUT_KEY}\n                {...props}\n                value={value}\n                onKeyDown={handleKeyDown}\n                onChange={handleChange}\n                onFocus={handleFocus}\n                onBlur={handleBlur}\n                size=\"4\"\n                ref={inputRef}\n                autoComplete={isSuggestionsOpen ? 'off' : 'on'}\n                aria-expanded={isSuggestionsOpen}\n                aria-autocomplete=\"list\"\n                aria-owns={isSuggestionsOpen ? suggestionListId : null}\n                role=\"combobox\"\n              />\n            ) : (\n              <Tag key={tag} onDismiss={removeTag(tag)}>\n                {tagDisplayTransformer(tag) || tag}\n              </Tag>\n            )\n          )\n        }\n      </InputWrapper>\n      {isSuggestionsOpen && (\n        <SuggestionList\n          aria-label={suggestedTermsLabel}\n          role=\"listbox\"\n          ref={menuRef}\n          id={suggestionListId}\n          data-testid=\"suggested_terms_list\"\n        >\n          {suggestedTerms.map(({ name, id }, index) => (\n            <li\n              key={id}\n              aria-selected={value === name}\n              role=\"option\"\n              tabIndex={0}\n              onClick={(e) => handleTagSelectedFromSuggestions(e, name)}\n              onKeyDown={(e) => handleSuggestionKeyDown(e, index, name)}\n            >\n              {name}\n            </li>\n          ))}\n        </SuggestionList>\n      )}\n    </Border>\n  );\n}\nInput.propTypes = {\n  initialTags: PropTypes.arrayOf(PropTypes.string),\n  name: PropTypes.string.isRequired,\n  onInputChange: PropTypes.func,\n  onTagsChange: PropTypes.func,\n  onUndo: PropTypes.func,\n  suggestedTerms: PropTypes.arrayOf(\n    PropTypes.shape({ id: PropTypes.number, name: PropTypes.string })\n  ),\n  suggestedTermsLabel: PropTypes.string,\n  tagDisplayTransformer: PropTypes.func,\n  tokens: PropTypes.arrayOf(PropTypes.string),\n};\nexport default Input;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/label.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nexport default styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  display: inline-block;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin-bottom: 8px;\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/reducer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { clamp } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport cleanForSlug from '../../../utils/cleanForSlug';\n\nfunction formatTag(tag) {\n  return tag.replace(/( +)/g, ' ').trim();\n}\n\nfunction uniquesOnly(arr) {\n  const slugMap = new Map();\n  arr.forEach((item) => {\n    slugMap.set(cleanForSlug(item), item);\n  });\n  return [...slugMap.values()];\n}\n\nfunction subsetAOfB(a = [], b = []) {\n  return a.forEach((v) => b.includes(v));\n}\n\nexport function deepEquals(a = [], b = []) {\n  return a.length === b.length && a.every((item) => b.includes(item));\n}\n\nexport const ACTIONS = {\n  UPDATE_VALUE: 'updateValue',\n  SUBMIT_VALUE: 'submitValue',\n  REMOVE_TAG: 'removeTag',\n  RESET_OFFSET: 'resetOffset',\n  RESET_VALUE: 'resetValue',\n  INCREMENT_OFFSET: 'incrementOffset',\n  DECREMENT_OFFSET: 'decrementOffset',\n  UPDATE_TAGS: 'updateTags',\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case ACTIONS.UPDATE_VALUE: {\n      const values = action.payload.split(',');\n\n      // if we're not adding any tags,\n      // we don't want to update the tagBuffer\n      if (values.length <= 1) {\n        return {\n          ...state,\n          value: action.payload,\n        };\n      }\n\n      const newTags = values\n        .slice(0, -1)\n        .map(formatTag)\n        .filter((tag) => tag.length);\n      const value = values[values.length - 1];\n\n      // if we're not adding any tags,\n      // we don't want to update the tagBuffer\n      if (subsetAOfB(newTags, state.tags)) {\n        return { ...state, value };\n      }\n\n      return {\n        ...state,\n        value,\n        tagBuffer: uniquesOnly([\n          ...state.tags.slice(0, state.tags.length - state.offset),\n          ...newTags,\n          ...state.tags.slice(state.tags.length - state.offset),\n        ]),\n      };\n    }\n\n    case ACTIONS.SUBMIT_VALUE: {\n      const newTag = formatTag(action?.payload || state.value);\n\n      // don't update tagBuffer if we're not\n      // adding any tags\n      if (newTag === '' || state.tags.includes(newTag)) {\n        return { ...state, value: '' };\n      }\n\n      return {\n        ...state,\n        value: '',\n        tagBuffer: uniquesOnly([\n          ...state.tags.slice(0, state.tags.length - state.offset),\n          newTag,\n          ...state.tags.slice(state.tags.length - state.offset),\n        ]),\n      };\n    }\n\n    case ACTIONS.REMOVE_TAG: {\n      const removedTagIndex =\n        typeof action.payload === 'string'\n          ? // if there's a specified tag, remove that tag\n            state.tags.findIndex((tag) => tag === action.payload)\n          : // otherwise remove at the current offset\n            state.tags.length - 1 - state.offset;\n      return removedTagIndex < 0\n        ? state\n        : {\n            ...state,\n            tagBuffer: [\n              ...state.tags.slice(0, removedTagIndex),\n              ...state.tags.slice(removedTagIndex + 1, state.tags.length),\n            ],\n          };\n    }\n\n    case ACTIONS.INCREMENT_OFFSET: {\n      return {\n        ...state,\n        offset: clamp(state.offset + 1, { MIN: 0, MAX: state.tags.length }),\n      };\n    }\n\n    case ACTIONS.DECREMENT_OFFSET: {\n      return {\n        ...state,\n        offset: clamp(state.offset - 1, { MIN: 0, MAX: state.tags.length }),\n      };\n    }\n\n    case ACTIONS.RESET_OFFSET: {\n      return {\n        ...state,\n        offset: 0,\n      };\n    }\n\n    case ACTIONS.RESET_VALUE: {\n      return {\n        ...state,\n        value: '',\n      };\n    }\n\n    // Retain order as much as possible\n    // and append new tags to the end\n    case ACTIONS.UPDATE_TAGS: {\n      const stateTagsWithSlugs = state.tags.map((name) => [\n        cleanForSlug(name),\n        name,\n      ]);\n      const payloadTagsWithSlugs = action.payload.map((name) => [\n        cleanForSlug(name),\n        name,\n      ]);\n      // if the payload is the same as the existing tags\n      // we don't want to cause an update.\n      if (\n        deepEquals(\n          stateTagsWithSlugs.map(([slug]) => slug),\n          payloadTagsWithSlugs.map(([slug]) => slug)\n        )\n      ) {\n        return state;\n      }\n\n      const tagsToPersist = stateTagsWithSlugs\n        .filter(([tagSlug]) =>\n          payloadTagsWithSlugs.map(([slug]) => slug).includes(tagSlug)\n        )\n        .map(([, name]) => name);\n\n      const tagsToAdd = payloadTagsWithSlugs\n        .filter(\n          ([tagSlug]) =>\n            !stateTagsWithSlugs.map(([slug]) => slug).includes(tagSlug)\n        )\n        .map(([, name]) => name);\n\n      return {\n        ...state,\n        tags: [...tagsToPersist, ...tagsToAdd],\n        tagBuffer: null,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/tag.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  Icons,\n  Text,\n  themeHelpers,\n  TextSize,\n  Placement,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useMemo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_STORY_DETAILS } from '../../../constants/zIndex';\nimport Tooltip from '../../tooltip';\n\nconst Dismiss = styled.button`\n  all: unset;\n  cursor: pointer;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${themeHelpers.focusableOutlineCSS};\n  width: 22px;\n  min-width: 22px;\n  height: 22px;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n\n  svg {\n    height: 20px;\n    width: 20px;\n    margin: auto;\n  }\n`;\n\nconst Token = styled.span`\n  ${({ theme }) => css`\n    color: ${theme.colors.fg.primary};\n    border: 1px solid ${theme.colors.border.defaultNormal};\n    border-radius: ${theme.borders.radius.small};\n  `}\n  position: relative;\n  display: flex;\n  align-items: center;\n  padding: 2px;\n  margin: 2px;\n  max-width: calc(100% - 4px);\n  height: 32px;\n`;\n\nconst TokenText = styled(Text.Span).attrs({\n  size: TextSize.Small,\n})`\n  padding-left: 10px;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n`;\n\nfunction Tag({ children, onDismiss }) {\n  const id = useMemo(() => uuidv4(), []);\n  return (\n    <Token data-testid=\"flat-term-token\">\n      <TokenText id={id}>{children}</TokenText>\n      <Tooltip\n        title={__('Remove Tag', 'web-stories')}\n        placement={Placement.Bottom}\n        hasTail\n        popupZIndexOverride={Z_INDEX_STORY_DETAILS}\n      >\n        <Dismiss\n          onClick={onDismiss}\n          aria-label={__('Remove Tag', 'web-stories')}\n          aria-describedby={id}\n        >\n          <Icons.Cross />\n        </Dismiss>\n      </Tooltip>\n    </Token>\n  );\n}\n\nTag.propTypes = {\n  children: PropTypes.node.isRequired,\n  onDismiss: PropTypes.func.isRequired,\n};\n\nexport default Tag;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/test/input.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n// eslint-disable-next-line import/no-internal-modules -- Importing testUtils is OK.\nimport { renderWithProviders } from '@googleforcreators/design-system/src/testUtils';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../../utils/noop';\nimport Input from '../input';\n\nconst baseProps = {\n  suggestedTerms: [\n    { id: 1, name: 'adventure' },\n    { id: 2, name: 'ace ventura' },\n    { id: 3, name: 'advent' },\n  ],\n  onTagsChange: noop,\n  onInputChange: noop,\n  suggestedTermsLabel: 'Taxonomy - Terms - Label',\n  tagDisplayTransformer: noop,\n  tokens: [],\n  name: 'input name',\n  onUndo: noop,\n};\n\ndescribe('Input', () => {\n  it('should call `onUndo` when meta+z is pressed', () => {\n    const mockUndo = jest.fn();\n\n    renderWithProviders(<Input {...baseProps} onUndo={mockUndo} />);\n\n    const input = screen.getByRole('combobox');\n\n    fireEvent.focus(input);\n    fireEvent.keyDown(input, { key: 'z', metaKey: true });\n\n    expect(mockUndo).toHaveBeenCalledOnce();\n  });\n\n  it('should show suggestion list when suggestedTerms length is greater than 0', () => {\n    renderWithProviders(<Input {...baseProps} />);\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n  });\n\n  it('should not render suggestion list when list is empty', () => {\n    renderWithProviders(<Input {...baseProps} suggestedTerms={[]} />);\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n    expect(screen.queryByRole('listbox')).not.toBeInTheDocument();\n  });\n\n  it('should move focus through list with down and up arrows', () => {\n    renderWithProviders(<Input {...baseProps} />);\n    const input = screen.getByRole('combobox');\n    expect(input).toBeInTheDocument();\n    const menu = screen.getByRole('listbox');\n    expect(menu).toBeInTheDocument();\n\n    fireEvent.focus(input);\n    fireEvent.keyDown(input, { key: 'ArrowDown', keyCode: 40 });\n    const listItems = screen.queryAllByRole('option');\n    expect(listItems[0]).toHaveFocus();\n    fireEvent.keyDown(listItems[0], { key: 'ArrowDown', keyCode: 40 });\n    expect(listItems[1]).toHaveFocus();\n    fireEvent.keyDown(listItems[1], { key: 'ArrowUp', keyCode: 38 });\n    expect(listItems[0]).toHaveFocus();\n  });\n\n  it('should return focus to input from suggestion list', () => {\n    renderWithProviders(<Input {...baseProps} />);\n    const input = screen.getByRole('combobox');\n    const listItems = screen.queryAllByRole('option');\n    fireEvent.focus(input);\n    fireEvent.keyDown(input, { key: 'ArrowDown', keyCode: 40 });\n    expect(listItems[0]).toHaveFocus();\n    fireEvent.keyDown(listItems[0], { key: 'ArrowUp', keyCode: 38 });\n    expect(input).toHaveFocus();\n  });\n\n  it('should call handler when \"enter\" key is hit while focused on a suggestion', () => {\n    const handleTagsChange = jest.fn();\n    renderWithProviders(\n      <Input {...baseProps} onTagsChange={handleTagsChange} />\n    );\n    const input = screen.getByRole('combobox');\n    const listItems = screen.queryAllByRole('option');\n    fireEvent.focus(input);\n    fireEvent.keyDown(input, { key: 'ArrowDown', keyCode: 40 });\n    fireEvent.keyDown(listItems[0], { key: 'Enter', keyCode: 13 });\n    expect(handleTagsChange).toHaveBeenCalledWith([\n      baseProps.suggestedTerms[0].name,\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/tags/test/reducer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport reducer, { ACTIONS } from '../reducer';\n\ndescribe('<Tags.Input /> Reducer', () => {\n  describe('ACTIONS.UPDATE_VALUE', () => {\n    it('should update the value', () => {\n      const oldState = {\n        offset: 0,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.UPDATE_VALUE, payload: 'potato' };\n      const expectedState = {\n        offset: 0,\n        value: 'potato',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('should add tags when theres postfixed commas in the value', () => {\n      const oldState = {\n        offset: 0,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      const action = {\n        type: ACTIONS.UPDATE_VALUE,\n        payload: 'potato, tomato, pizza pie',\n      };\n      const expectedState = {\n        offset: 0,\n        value: ' pizza pie',\n        tags: ['tag1'],\n        tagBuffer: ['tag1', 'potato', 'tomato'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('should strip extraneous spaces once added as a tag', () => {\n      const oldState = {\n        offset: 0,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      const action = {\n        type: ACTIONS.UPDATE_VALUE,\n        payload: 'potato, tomato     , pizza   pie',\n      };\n      const expectedState = {\n        offset: 0,\n        value: ' pizza   pie',\n        tags: ['tag1'],\n        tagBuffer: ['tag1', 'potato', 'tomato'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('should respect the offset when adding new tags', () => {\n      const oldState = {\n        offset: 1,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      const action = {\n        type: ACTIONS.UPDATE_VALUE,\n        payload: 'potato, tomato, pizza pie',\n      };\n      const expectedState = {\n        offset: 1,\n        value: ' pizza pie',\n        tags: ['tag1'],\n        tagBuffer: ['potato', 'tomato', 'tag1'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.SUBMIT_VALUE', () => {\n    it('adds the value as a tag on submit and clears the value', () => {\n      const oldState = {\n        offset: 0,\n        value: 'tag2',\n        tags: ['tag1'],\n      };\n      const action = { type: ACTIONS.SUBMIT_VALUE };\n      const expectedState = {\n        offset: 0,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: ['tag1', 'tag2'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('formats the new value on submit', () => {\n      const oldState = {\n        offset: 0,\n        value: '   tag   two    ',\n        tags: ['tag1'],\n      };\n      const action = { type: ACTIONS.SUBMIT_VALUE };\n      const expectedState = {\n        offset: 0,\n        value: '',\n        tags: ['tag1'],\n        tagBuffer: ['tag1', 'tag two'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('returns the original state with the value reset if the value is empty', () => {\n      const oldState = {\n        offset: 0,\n        value: '    ',\n        tags: ['tag1'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.SUBMIT_VALUE };\n      expect(reducer(oldState, action)).toStrictEqual({\n        ...oldState,\n        value: '',\n      });\n    });\n\n    it('respects the offset when adding tags', () => {\n      const oldState = {\n        offset: 1,\n        value: 'tag2',\n        tags: ['tag1', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.SUBMIT_VALUE };\n      const expectedState = {\n        offset: 1,\n        value: '',\n        tags: ['tag1', 'tag3'],\n        tagBuffer: ['tag1', 'tag2', 'tag3'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.REMOVE_TAG', () => {\n    it('removes the tag specified in the payload', () => {\n      const oldState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.REMOVE_TAG, payload: 'tag2' };\n      const expectedState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: ['tag1', 'tag3'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n    it('returns original state when tag not found', () => {\n      const oldState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.REMOVE_TAG, payload: 'tag8' };\n      const expectedState = oldState;\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('removes tag from index dictated by offset when no payload present', () => {\n      let oldState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      let action = { type: ACTIONS.REMOVE_TAG };\n      let expectedState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n\n      oldState = {\n        offset: 2,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      action = { type: ACTIONS.REMOVE_TAG };\n      expectedState = {\n        offset: 2,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: ['tag2', 'tag3'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n\n      oldState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      action = { type: ACTIONS.REMOVE_TAG };\n      expectedState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: ['tag1', 'tag3'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n\n      oldState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      action = { type: ACTIONS.REMOVE_TAG };\n      expectedState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: ['tag1', 'tag2'],\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.INCREMENT_OFFSET', () => {\n    it('should increase offset by 1', () => {\n      const oldState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.INCREMENT_OFFSET };\n      const expectedState = {\n        offset: 1,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('should not let offset exceed tag length', () => {\n      const oldState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.INCREMENT_OFFSET };\n      const expectedState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.DECREMENT_OFFSET', () => {\n    it('should decrease offset by 1', () => {\n      const oldState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.DECREMENT_OFFSET };\n      const expectedState = {\n        offset: 2,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n\n    it('should not let offset go below 0', () => {\n      const oldState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.DECREMENT_OFFSET };\n      const expectedState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.RESET_OFFSET', () => {\n    it('should reset offset to 0', () => {\n      const oldState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.RESET_OFFSET };\n      const expectedState = {\n        offset: 0,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n\n  describe('ACTIONS.RESET_VALUE', () => {\n    it('should reset value to empty string', () => {\n      const oldState = {\n        offset: 3,\n        value: 'tag4',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      const action = { type: ACTIONS.RESET_VALUE };\n      const expectedState = {\n        offset: 3,\n        value: '',\n        tags: ['tag1', 'tag2', 'tag3'],\n        tagBuffer: null,\n      };\n      expect(reducer(oldState, action)).toStrictEqual(expectedState);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/test/radioGroup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport RadioGroup from '../radioGroup';\n\ndescribe('RadioGroup', () => {\n  const options = [\n    {\n      value: 'a',\n      label: __('Option A', 'web-stories'),\n      helper: __('This is the best option', 'web-stories'),\n    },\n    {\n      value: 'b',\n      label: __('Option B', 'web-stories'),\n      helper: __('Also a good option', 'web-stories'),\n    },\n  ];\n\n  it('should render with correct options', () => {\n    renderWithTheme(\n      <RadioGroup\n        name=\"test\"\n        groupLabel=\"test\"\n        onChange={() => null}\n        options={options}\n        value={options[0].value}\n      />\n    );\n\n    const optionA = screen.getByRole('radio', { name: 'Option A' });\n    const optionB = screen.getByRole('radio', { name: 'Option B' });\n\n    expect(optionA).toBeInTheDocument();\n    expect(optionA).toBeChecked();\n    expect(optionB).toBeInTheDocument();\n  });\n\n  it('should change the value when clicking', () => {\n    const onChange = jest.fn();\n\n    renderWithTheme(\n      <RadioGroup\n        name=\"test\"\n        groupLabel=\"test\"\n        onChange={onChange}\n        options={options}\n        value={options[0].value}\n      />\n    );\n    const optionB = screen.getByRole('radio', { name: 'Option B' });\n    fireEvent.click(optionB);\n    expect(onChange).toHaveBeenCalledOnce();\n\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object));\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/test/switch.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport Switch from '../switch';\n\ndescribe('Switch', () => {\n  it('should render with passed default value', () => {\n    const onLabel = 'On';\n    const offLabel = 'Off';\n    const onChange = jest.fn();\n\n    renderWithTheme(\n      <Switch\n        groupLabel=\"Switch\"\n        name=\"test-switch\"\n        onChange={onChange}\n        onLabel={onLabel}\n        offLabel={offLabel}\n        value\n      />\n    );\n\n    const onLabelEl = screen.getByText(onLabel);\n    const onLabelRadio = screen.getByRole('radio', { name: onLabel });\n    const offLabelEl = screen.getByText(offLabel);\n    const offLabelRadio = screen.getByRole('radio', { name: offLabel });\n\n    expect(onLabelRadio).toBeChecked();\n    expect(offLabelRadio).not.toBeChecked();\n\n    fireEvent.click(onLabelEl);\n\n    expect(onChange).toHaveBeenCalledTimes(0);\n\n    fireEvent.click(offLabelEl);\n\n    expect(onChange).toHaveBeenCalledOnce();\n    expect(onChange).toHaveBeenCalledWith(expect.any(Object), false);\n  });\n\n  it('should render as disabled', () => {\n    const onLabel = 'On';\n    const offLabel = 'Off';\n    const onChange = jest.fn();\n\n    renderWithTheme(\n      <Switch\n        groupLabel=\"Switch\"\n        name=\"test-switch\"\n        onChange={onChange}\n        onLabel={onLabel}\n        offLabel={offLabel}\n        disabled\n      />\n    );\n\n    fireEvent.click(screen.getByText(onLabel));\n    fireEvent.click(screen.getByText(offLabel));\n\n    expect(onChange).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/form/textArea.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  forwardRef,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { TextArea as StyledTextArea } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { inputContainerStyleOverride } from '../panels/shared/styles';\n\nconst TextArea = forwardRef(\n  (\n    {\n      className,\n      placeholder,\n      value,\n      disabled,\n      rows = 2,\n      onChange,\n      onBlur,\n      ...rest\n    },\n    ref\n  ) => {\n    const [currentValue, setCurrentValue] = useState(value);\n    // Change happens only once blurring to avoid repeated onChange calls for each letter change.\n    const handleChange = useCallback(\n      (evt) => {\n        if (currentValue !== value) {\n          onChange(evt);\n        }\n      },\n      [currentValue, onChange, value]\n    );\n\n    // If new value comes from the outer world, update the local, too.\n    useEffect(() => {\n      setCurrentValue(value);\n    }, [value]);\n\n    const handleBlur = useCallback(\n      (e) => {\n        handleChange(e);\n        if (onBlur) {\n          onBlur(e);\n        }\n      },\n      [onBlur, handleChange]\n    );\n\n    return (\n      <StyledTextArea\n        placeholder={placeholder}\n        value={currentValue}\n        {...rest}\n        rows={rows}\n        containerStyleOverride={inputContainerStyleOverride}\n        onChange={(evt) => setCurrentValue(evt.target.value)}\n        onBlur={handleBlur}\n        ref={ref}\n      />\n    );\n  }\n);\n\nTextArea.displayName = 'TextArea';\n\nTextArea.propTypes = {\n  className: PropTypes.string,\n  placeholder: PropTypes.string,\n  value: PropTypes.string.isRequired,\n  disabled: PropTypes.bool,\n  rows: PropTypes.number,\n  onChange: PropTypes.func.isRequired,\n  onBlur: PropTypes.func,\n};\n\nexport default TextArea;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/useFormContext.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useFormContext(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useFormContext;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/useHotlink.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport getResourceFromUrl from '../../app/media/utils/getResourceFromUrl';\nimport useCORSProxy from '../../utils/useCORSProxy';\n\nfunction useHotlink({ onChange, type, canUseProxy }) {\n  const [isOpen, setIsOpen] = useState(false);\n\n  const openHotlink = () => setIsOpen(true);\n  const onCloseHotlink = () => setIsOpen(false);\n  const allowedFileTypes = useMemo(\n    () =>\n      Array.isArray(type)\n        ? type.flatMap((_type) => getExtensionsFromMimeType(_type))\n        : [],\n    [type]\n  );\n\n  const { getProxiedUrl } = useCORSProxy();\n\n  const onSelect = useCallback(\n    async ({ link, hotlinkInfo, needsProxy }) => {\n      const { mimeType, fileName: originalFileName } = hotlinkInfo;\n\n      const proxiedUrl =\n        needsProxy && canUseProxy ? getProxiedUrl({ needsProxy }, link) : link;\n\n      const resourceLike = {\n        id: uuidv4(),\n        src: proxiedUrl,\n        mimeType,\n        needsProxy,\n        alt: originalFileName,\n        height: hotlinkInfo?.height,\n        width: hotlinkInfo?.width,\n      };\n\n      const resource = await getResourceFromUrl(resourceLike);\n      resource.src = link;\n      onChange(resource);\n\n      setIsOpen(false);\n    },\n    [canUseProxy, getProxiedUrl, onChange]\n  );\n\n  return {\n    actions: {\n      onSelect,\n      openHotlink,\n      onCloseHotlink,\n    },\n    state: {\n      allowedFileTypes,\n      isOpen,\n    },\n  };\n}\n\nexport default useHotlink;\n"
  },
  {
    "path": "packages/story-editor/src/components/form/usePresubmitHandler.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useFormContext from './useFormContext';\n\n/**\n * @param {Function} handler The handler function with three arguments: the new\n * element state, the element's updated properties, and the old element state.\n * @param {Array|undefined} deps The handler dependencies. See `useCallback`.\n */\nfunction usePresubmitHandler(handler, deps = undefined) {\n  const registerPresubmitHandler = useFormContext(\n    (value) => value.registerPresubmitHandler\n  );\n  useEffect(\n    () => registerPresubmitHandler(handler),\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Pass through provided deps.\n    [registerPresubmitHandler].concat(deps || [])\n  );\n}\n\nexport default usePresubmitHandler;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/buttonWithChecklistWarning.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Button as DefaultButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Placement,\n} from '@googleforcreators/design-system';\nimport { forwardRef, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { Z_INDEX_STORY_DETAILS } from '../../../constants/zIndex';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\nimport {\n  useCheckpoint,\n  PPC_CHECKPOINT_STATE,\n  ChecklistIcon,\n} from '../../checklist';\nimport Tooltip from '../../tooltip';\n\nconst Button = styled(DefaultButton)`\n  padding: 4px 6px;\n  height: 32px;\n  svg {\n    width: 24px;\n    height: auto;\n  }\n`;\n\nconst InnerButton = forwardRef(function InnerButton(\n  { text, checkpoint, hasHighPriorityIssues = false, onClick, ...buttonProps },\n  ref\n) {\n  const handleClick = (evt) => {\n    // https://github.com/reactjs/react-modal/issues/680#issuecomment-413422345\n    // React Modal restores input on last focused element on close.\n    // Blur button so that it doesn't steal focus back when opening the checklist.\n    evt.currentTarget.blur();\n\n    onClick?.(evt);\n  };\n\n  return (\n    <Button\n      ref={ref}\n      variant={ButtonVariant.Rectangle}\n      type={ButtonType.Primary}\n      size={ButtonSize.Small}\n      onClick={handleClick}\n      {...buttonProps}\n    >\n      {text}\n      {hasHighPriorityIssues && <ChecklistIcon checkpoint={checkpoint} />}\n    </Button>\n  );\n});\n\nInnerButton.propTypes = {\n  checkpoint: PropTypes.oneOf(Object.values(PPC_CHECKPOINT_STATE)),\n  hasHighPriorityIssues: PropTypes.bool,\n  onClick: PropTypes.func,\n  text: PropTypes.node.isRequired,\n};\n\nconst ButtonWithChecklistWarning = forwardRef(\n  function ButtonWithChecklistWarning(\n    { disabled, hasFutureDate, ...buttonProps },\n    ref\n  ) {\n    const isUploading = useIsUploadingToStory();\n    const { isSaving, canPublish, status } = useStory(({ state }) => ({\n      isSaving: state.meta?.isSaving,\n      status: state.story.status,\n      canPublish: Boolean(state?.capabilities?.publish),\n    }));\n\n    const { checkpoint, hasHighPriorityIssues } = useCheckpoint(\n      ({ state: { checkpoint, hasHighPriorityIssues } }) => ({\n        checkpoint,\n        hasHighPriorityIssues,\n      })\n    );\n    const TOOLTIP_TEXT = {\n      [PPC_CHECKPOINT_STATE.ALL]: hasHighPriorityIssues\n        ? __(\n            'Make updates before publishing to improve discoverability and performance on search engines',\n            'web-stories'\n          )\n        : '',\n      [PPC_CHECKPOINT_STATE.ONLY_RECOMMENDED]: __(\n        'Review checklist to improve performance before publishing',\n        'web-stories'\n      ),\n      [PPC_CHECKPOINT_STATE.UNAVAILABLE]: '',\n    };\n\n    const TOOLTIP_TEXT_UPLOADING = __(\n      'Saving is disabled due to media currently being uploaded.',\n      'web-stories'\n    );\n\n    const TOOLTIP_TEXT_REVIEW = __(\n      'Submit your work for review, and an Editor will be able to approve it for you.',\n      'web-stories'\n    );\n\n    let toolTip = isUploading\n      ? TOOLTIP_TEXT_UPLOADING\n      : TOOLTIP_TEXT[checkpoint];\n\n    if (!canPublish) {\n      toolTip = TOOLTIP_TEXT_REVIEW;\n    }\n\n    const publishText = useMemo(\n      () =>\n        hasFutureDate && status !== 'private'\n          ? __('Schedule', 'web-stories')\n          : __('Publish', 'web-stories'),\n      [hasFutureDate, status]\n    );\n\n    const text = canPublish\n      ? publishText\n      : __('Submit for review', 'web-stories');\n    return (\n      <Tooltip\n        title={toolTip}\n        popupZIndexOverride={Z_INDEX_STORY_DETAILS}\n        hasTail\n        placement={Placement.BottomEnd}\n      >\n        <InnerButton\n          ref={ref}\n          text={text}\n          disabled={disabled || isSaving || isUploading}\n          checkpoint={checkpoint}\n          hasHighPriorityIssues={hasHighPriorityIssues}\n          {...buttonProps}\n        />\n      </Tooltip>\n    );\n  }\n);\n\nexport default ButtonWithChecklistWarning;\n\nButtonWithChecklistWarning.propTypes = {\n  disabled: PropTypes.bool,\n  hasFutureDate: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/historyButtons.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../tooltip';\nimport { useConfig, useHistory } from '../../../app';\n\nfunction HistoryButton({ title, shortcut, children, ...rest }) {\n  return (\n    <Tooltip title={title} shortcut={shortcut} hasTail>\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        {...rest}\n      >\n        {children}\n      </Button>\n    </Tooltip>\n  );\n}\n\nHistoryButton.propTypes = {\n  title: PropTypes.string.isRequired,\n  shortcut: PropTypes.string.isRequired,\n  children: PropTypes.node.isRequired,\n};\n\nfunction Redo() {\n  const {\n    state: { canRedo },\n    actions: { redo },\n  } = useHistory();\n  const { isRTL } = useConfig();\n\n  const handleRedo = useCallback(() => redo(), [redo]);\n\n  return (\n    <HistoryButton\n      title={__('Redo', 'web-stories')}\n      shortcut=\"shift+mod+z\"\n      disabled={!canRedo}\n      onClick={handleRedo}\n      aria-label={__('Redo Changes', 'web-stories')}\n    >\n      {isRTL ? <Icons.ArrowDownLeftCurved /> : <Icons.ArrowDownRightCurved />}\n    </HistoryButton>\n  );\n}\n\nfunction Undo() {\n  const {\n    state: { canUndo },\n    actions: { undo },\n  } = useHistory();\n  const { isRTL } = useConfig();\n\n  const handleUndo = useCallback(() => undo(), [undo]);\n\n  return (\n    <HistoryButton\n      title={__('Undo', 'web-stories')}\n      shortcut=\"mod+z\"\n      disabled={!canUndo}\n      onClick={handleUndo}\n      aria-label={__('Undo Changes', 'web-stories')}\n    >\n      {isRTL ? <Icons.ArrowDownRightCurved /> : <Icons.ArrowDownLeftCurved />}\n    </HistoryButton>\n  );\n}\n\nexport { Redo, Undo };\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { Redo as RedoButton, Undo as UndoButton } from './historyButtons';\nexport { default as PreviewButton } from './preview';\nexport { default as PublishButton } from './publish';\nexport { default as SwitchToDraftButton } from './switchToDraft';\nexport { default as UpdateButton } from './update';\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/preview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport { escapeHTML } from '@googleforcreators/dom';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport PreviewErrorDialog from '../previewErrorDialog';\nimport Tooltip from '../../tooltip';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\n\nconst PREVIEW_TARGET = 'story-preview';\n\nfunction PreviewButton({ forceIsSaving = false }) {\n  const { isSaving, previewLink, status, autoSave, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n        story: { status, previewLink },\n      },\n      actions: { autoSave, saveStory },\n    }) => ({ isSaving, status, previewLink, autoSave, saveStory })\n  );\n  const isUploading = useIsUploadingToStory();\n\n  const [previewLinkToOpenViaDialog, setPreviewLinkToOpenViaDialog] =\n    useState(null);\n  const isDraft = ['draft', 'auto-draft'].includes(status) || !status;\n\n  /**\n   * Applies any local transforms (e.g. AMP development mode) to the stored preview link.\n   *\n   * @param {string} urlString The original preview link.\n   * @return {string} The decorated preview link.\n   */\n  const decoratePreviewLink = (urlString) => {\n    const url = new URL(urlString);\n    // #development=1 triggers amp-story's multi-aspect preview mode.\n    url.hash = '#development=1';\n    return url.toString();\n  };\n\n  /**\n   * Open a preview of the story in current window.\n   */\n  const openPreviewLink = useCallback(async () => {\n    trackEvent('preview_story');\n\n    // Start a about:blank popup with waiting message until we complete\n    // the saving operation. That way we will not bust the popup timeout.\n    let popup;\n    try {\n      popup = window.open('about:blank', PREVIEW_TARGET);\n      if (popup) {\n        popup.document.write('<!DOCTYPE html><html><head>');\n        popup.document.write('<title>');\n        popup.document.write(\n          escapeHTML(__('Generating the preview…', 'web-stories'))\n        );\n        popup.document.write('</title>');\n        popup.document.write('</head><body>');\n        // Output \"waiting\" message.\n        popup.document.write(\n          escapeHTML(__('Please wait. Generating the preview…', 'web-stories'))\n        );\n        const decoratedPreviewLink = decoratePreviewLink(previewLink);\n        // Force redirect to the preview URL after 5 seconds. The saving tab\n        // might get frozen by the browser.\n        popup.document.write(\n          `<script>\n            setTimeout(function() {\n              location.replace(${JSON.stringify(decoratedPreviewLink)});\n            }, 5000);\n          </script>`\n        );\n      }\n    } catch {\n      // Ignore errors. Anything can happen with a popup. The errors\n      // will be resolved after the story is saved.\n    }\n\n    // Save story directly if draft, otherwise, use auto-save.\n    const updateFunc = isDraft ? saveStory : autoSave;\n    try {\n      const update = await updateFunc();\n      if (popup && !popup.closed) {\n        if (popup.location.href) {\n          // Auto-save sends an updated preview link, use that instead if available.\n          const updatedPreviewLink = decoratePreviewLink(\n            update?.previewLink ?? previewLink\n          );\n          popup.location.replace(updatedPreviewLink);\n        }\n      }\n    } catch {\n      setPreviewLinkToOpenViaDialog(previewLink);\n    }\n  }, [autoSave, isDraft, previewLink, saveStory]);\n\n  const openPreviewLinkSync = useCallback(\n    (evt) => {\n      setPreviewLinkToOpenViaDialog(null);\n      // Ensure that this method is as safe as possible and pass the random\n      // target in case the normal target is not openable.\n      const decoratedPreviewLink = decoratePreviewLink(\n        previewLinkToOpenViaDialog\n      );\n      window.open(decoratedPreviewLink, PREVIEW_TARGET + Math.random());\n      evt.preventDefault();\n    },\n    [previewLinkToOpenViaDialog]\n  );\n\n  const onDialogClose = useCallback(\n    () => setPreviewLinkToOpenViaDialog(null),\n    []\n  );\n\n  const label = __('Preview', 'web-stories');\n  return (\n    <>\n      <Tooltip title={label} hasTail>\n        <Button\n          variant={ButtonVariant.Square}\n          type={ButtonType.Quaternary}\n          size={ButtonSize.Small}\n          onClick={openPreviewLink}\n          disabled={isSaving || forceIsSaving || isUploading}\n          aria-label={label}\n        >\n          <Icons.Eye />\n        </Button>\n      </Tooltip>\n      <PreviewErrorDialog\n        isOpen={Boolean(previewLinkToOpenViaDialog)}\n        onClose={onDialogClose}\n        onRetry={openPreviewLinkSync}\n      />\n    </>\n  );\n}\n\nPreviewButton.propTypes = {\n  forceIsSaving: PropTypes.bool,\n};\n\nexport default PreviewButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/publish.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\nimport {\n  toDate,\n  isAfter,\n  subMinutes,\n  getOptions,\n} from '@googleforcreators/date';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL';\nimport { useCheckpoint } from '../../checklist';\nimport { PublishModal } from '../../publishModal';\nimport ButtonWithChecklistWarning from './buttonWithChecklistWarning';\n\nfunction PublishButton({ forceIsSaving }) {\n  const { date, storyId, saveStory, titleLength, editLink, canPublish } =\n    useStory(\n      ({\n        state: {\n          story: { date, storyId, title, editLink },\n          capabilities,\n        },\n        actions: { saveStory },\n      }) => ({\n        date,\n        storyId,\n        saveStory,\n        titleLength: title?.length || 0,\n        editLink,\n        canPublish: Boolean(capabilities?.publish),\n      })\n    );\n\n  const showPriorityIssues = useCheckpoint(\n    ({ actions: { showPriorityIssues } }) => showPriorityIssues\n  );\n\n  const [showDialog, setShowDialog] = useState(false);\n  const publishButtonRef = useRef();\n\n  const refreshPostEditURL = useRefreshPostEditURL(storyId, editLink);\n  // Offset the date by one minute to accommodate for network latency.\n  const hasFutureDate = isAfter(\n    subMinutes(toDate(date, getOptions()), 1),\n    toDate(new Date(), getOptions())\n  );\n\n  const publish = useCallback(() => {\n    let newStatus = 'pending';\n\n    if (canPublish) {\n      if (hasFutureDate) {\n        newStatus = 'future';\n      } else {\n        newStatus = 'publish';\n      }\n    }\n\n    trackEvent('publish_story', {\n      status: newStatus,\n      title_length: titleLength,\n    });\n\n    setShowDialog(false);\n    saveStory({ status: newStatus });\n    refreshPostEditURL();\n  }, [refreshPostEditURL, saveStory, hasFutureDate, titleLength, canPublish]);\n\n  const handlePublish = useCallback(() => {\n    showPriorityIssues();\n    setShowDialog(true);\n  }, [showPriorityIssues]);\n\n  const closeDialog = useCallback(({ focusPublishButton = true } = {}) => {\n    setShowDialog(false);\n\n    if (focusPublishButton) {\n      publishButtonRef.current?.focus();\n    }\n  }, []);\n\n  return (\n    <>\n      <ButtonWithChecklistWarning\n        ref={publishButtonRef}\n        onClick={handlePublish}\n        disabled={forceIsSaving}\n        hasFutureDate={hasFutureDate}\n      />\n      <PublishModal\n        isOpen={showDialog}\n        onPublish={publish}\n        onClose={closeDialog}\n        hasFutureDate={hasFutureDate}\n        publishButtonDisabled={forceIsSaving}\n      />\n    </>\n  );\n}\n\nPublishButton.propTypes = {\n  forceIsSaving: PropTypes.bool,\n};\n\nexport default PublishButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/switchToDraft.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport Tooltip from '../../tooltip';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\n\nfunction SwitchToDraftButton({ forceIsSaving = false }) {\n  const { isSaving, saveStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n      },\n      actions: { saveStory },\n    }) => ({ isSaving, saveStory })\n  );\n  const isUploading = useIsUploadingToStory();\n\n  const handleUnPublish = useCallback(() => {\n    saveStory({ status: 'draft' });\n  }, [saveStory]);\n\n  const label = __('Switch to Draft', 'web-stories');\n  return (\n    <Tooltip title={label} hasTail>\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        onClick={handleUnPublish}\n        disabled={isSaving || forceIsSaving || isUploading}\n        aria-label={label}\n      >\n        <Icons.PageSwap />\n      </Button>\n    </Tooltip>\n  );\n}\n\nSwitchToDraftButton.propTypes = {\n  forceIsSaving: PropTypes.bool,\n};\n\nexport default SwitchToDraftButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/test/preview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, waitFor } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport MediaContext from '../../../../app/media/context';\nimport PreviewButton from '../preview';\n\nfunction arrange({\n  props: extraButtonProps,\n  story: extraStoryProps,\n  storyState: extraStoryStateProps,\n  meta: extraMetaProps,\n  media: extraMediaProps,\n} = {}) {\n  const saveStory = jest.fn();\n  const autoSave = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        publish: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n        ...extraStoryProps,\n      },\n      ...extraStoryStateProps,\n    },\n    actions: { saveStory, autoSave },\n  };\n  const mediaContextValue = {\n    local: {\n      state: { ...extraMediaProps },\n    },\n  };\n\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <MediaContext.Provider value={mediaContextValue}>\n        <PreviewButton {...extraButtonProps} />\n      </MediaContext.Provider>\n    </StoryContext.Provider>\n  );\n  return {\n    saveStory,\n    autoSave,\n  };\n}\n\ndescribe('PreviewButton', () => {\n  let previewPopup;\n\n  beforeEach(() => {\n    previewPopup = {\n      document: {\n        write: jest.fn(),\n      },\n      location: {\n        href: 'about:blank',\n        replace: jest.fn(),\n      },\n    };\n  });\n\n  it('should open draft preview when clicking on Preview via about:blank', async () => {\n    const { saveStory } = arrange({\n      story: {\n        previewLink: 'http://localhost/?preview=true',\n      },\n    });\n    const previewButton = screen.getByRole('button', { name: 'Preview' });\n\n    expect(previewButton).toBeInTheDocument();\n\n    saveStory.mockImplementation(() => Promise.resolve());\n\n    const mockedOpen = jest.fn(() => previewPopup);\n    const windowSpy = jest.spyOn(window, 'open').mockImplementation(mockedOpen);\n\n    fireEvent.click(previewButton);\n\n    await waitFor(() => {\n      expect(saveStory).toHaveBeenCalledWith();\n    });\n\n    expect(mockedOpen).toHaveBeenCalledWith('about:blank', 'story-preview');\n    expect(previewPopup.location.replace).toHaveBeenCalledWith(\n      'http://localhost/?preview=true#development=1'\n    );\n\n    windowSpy.mockRestore();\n  });\n\n  it('should open preview for a published story when clicking on Preview via about:blank', async () => {\n    const { autoSave } = arrange({\n      story: {\n        link: 'http://localhost',\n        status: 'publish',\n      },\n    });\n    const previewButton = screen.getByRole('button', { name: 'Preview' });\n    autoSave.mockImplementation(() => Promise.resolve());\n\n    const mockedOpen = jest.fn(() => previewPopup);\n    const windowSpy = jest.spyOn(window, 'open').mockImplementation(mockedOpen);\n\n    fireEvent.click(previewButton);\n\n    await waitFor(() => {\n      expect(autoSave).toHaveBeenCalledWith();\n    });\n\n    expect(previewPopup.location.replace).toHaveBeenCalledWith(\n      'http://localhost/?preview_id=1679&preview_nonce=b5ea827939&preview=true#development=1'\n    );\n\n    windowSpy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/test/publish.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, within } from '@testing-library/react';\nimport MockDate from 'mockdate';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport useIsUploadingToStory from '../../../../utils/useIsUploadingToStory';\nimport ConfigContext from '../../../../app/config/context';\nimport {\n  CheckpointContext,\n  ChecklistCountProvider,\n  PPC_CHECKPOINT_STATE,\n} from '../../../checklist';\nimport PublishButton from '../publish';\n\njest.mock('../../../../utils/useIsUploadingToStory');\n\nconst newPoster = {\n  id: 'new-poster',\n  src: 'new-poster-url',\n  height: '36px',\n  width: '100000px',\n};\n\nfunction arrange({\n  props: extraButtonProps,\n  story: extraStoryProps,\n  storyState: extraStoryStateProps,\n  meta: extraMetaProps,\n  media: extraMediaProps,\n  config: extraConfigProps,\n  checklist: extraChecklistProps,\n} = {}) {\n  const saveStory = jest.fn();\n  const handleReviewChecklist = jest.fn();\n  const showPriorityIssues = jest.fn();\n\n  useIsUploadingToStory.mockImplementation(() => extraMediaProps?.isUploading);\n\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        publish: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        title: 'Example Story',\n        excerpt: '',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n        ...extraStoryProps,\n      },\n      ...extraStoryStateProps,\n    },\n    actions: { saveStory },\n  };\n  const configValue = {\n    allowedMimeTypes: {},\n    capabilities: {},\n    metadata: {\n      publisher: 'publisher title',\n    },\n    MediaUpload: ({ onSelect }) => (\n      <button\n        data-testid=\"media-upload-button\"\n        onClick={() => onSelect(newPoster)}\n      >\n        {'Media Upload Button!'}\n      </button>\n    ),\n    ...extraConfigProps,\n  };\n  const prepublishChecklistContextValue = {\n    state: {\n      checkpoint: PPC_CHECKPOINT_STATE.UNAVAILABLE,\n      ...extraChecklistProps,\n    },\n    actions: {\n      showPriorityIssues,\n      handleReviewChecklist,\n    },\n  };\n  renderWithTheme(\n    <ConfigContext.Provider value={configValue}>\n      <StoryContext.Provider value={storyContextValue}>\n        <ChecklistCountProvider hasChecklist>\n          <CheckpointContext.Provider value={prepublishChecklistContextValue}>\n            <PublishButton {...extraButtonProps} />\n          </CheckpointContext.Provider>\n        </ChecklistCountProvider>\n      </StoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n  return {\n    saveStory,\n    showPriorityIssues,\n  };\n}\n\ndescribe('PublishButton', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n    MockDate.set('2020-07-15T12:00:00+00:00');\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n    MockDate.reset();\n    jest.clearAllMocks();\n  });\n\n  it('should be able to publish', () => {\n    const { saveStory, showPriorityIssues } = arrange();\n\n    const publishButton = screen.getByRole('button', { name: 'Publish' });\n    expect(publishButton).toBeEnabled();\n    fireEvent.click(publishButton);\n\n    expect(showPriorityIssues).toHaveBeenCalledOnce();\n\n    const publishModal = screen.getByRole('dialog');\n\n    const publishModalButton = within(publishModal).getByRole('button', {\n      name: 'Publish',\n    });\n    fireEvent.click(publishModalButton);\n\n    expect(saveStory).toHaveBeenCalledWith({\n      status: 'publish',\n    });\n  });\n\n  it('should be able to submit for review if lacking capabilities', () => {\n    const { saveStory } = arrange({\n      storyState: {\n        capabilities: {\n          publish: false,\n        },\n      },\n    });\n\n    const publishButton = screen.getByRole('button', {\n      name: 'Submit for review',\n    });\n    expect(publishButton).toBeEnabled();\n    fireEvent.click(publishButton);\n\n    const publishModal = screen.getByRole('dialog');\n\n    const publishModalButton = within(publishModal).getByRole('button', {\n      name: 'Submit for review',\n    });\n    fireEvent.click(publishModalButton);\n\n    expect(saveStory).toHaveBeenCalledWith({\n      status: 'pending',\n    });\n  });\n\n  it('should disable button while upload is in progress', () => {\n    arrange({ media: { isUploading: true } });\n    expect(screen.getByRole('button', { name: 'Publish' })).toBeDisabled();\n  });\n\n  it('should allow forcing isSaving state', () => {\n    arrange({\n      props: { forceIsSaving: true },\n    });\n\n    const publishButton = screen.getByRole('button', { name: 'Publish' });\n    expect(publishButton).toBeDisabled();\n  });\n\n  it('should update window location when publishing', () => {\n    const { saveStory } = arrange({\n      story: { title: 'Some title' },\n    });\n    const publishButton = screen.getByRole('button', { name: 'Publish' });\n\n    fireEvent.click(publishButton);\n    const publishModal = screen.getByRole('dialog');\n\n    const publishModalButton = within(publishModal).getByRole('button', {\n      name: 'Publish',\n    });\n    fireEvent.click(publishModalButton);\n\n    expect(saveStory).toHaveBeenCalledOnce();\n    expect(window.location.href).toContain('post=123&action=edit');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/test/switchToDraft.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport useIsUploadingToStory from '../../../../utils/useIsUploadingToStory';\nimport { CheckpointContext } from '../../../checklist';\nimport SwitchToDraftButton from '../switchToDraft';\n\njest.mock('../../../../utils/useIsUploadingToStory');\n\nfunction arrange({\n  props: extraButtonProps,\n  story: extraStoryProps,\n  storyState: extraStoryStateProps,\n  meta: extraMetaProps,\n  media: extraMediaProps,\n  checklist: extraChecklistProps,\n} = {}) {\n  const saveStory = jest.fn();\n\n  useIsUploadingToStory.mockImplementation(() => extraMediaProps?.isUploading);\n\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        publish: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n        ...extraStoryProps,\n      },\n      ...extraStoryStateProps,\n    },\n    actions: { saveStory },\n  };\n\n  const prepublishChecklistContextValue = {\n    state: {\n      hasHighPriorityIssues: false,\n      ...extraChecklistProps,\n    },\n  };\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <CheckpointContext.Provider value={prepublishChecklistContextValue}>\n        <SwitchToDraftButton {...extraButtonProps} />\n      </CheckpointContext.Provider>\n    </StoryContext.Provider>\n  );\n  return {\n    saveStory,\n  };\n}\n\ndescribe('SwitchToDraftButton', () => {\n  it('should allow switching state to draft', () => {\n    const { saveStory } = arrange();\n\n    const updateButton = screen.getByRole('button', {\n      name: 'Switch to Draft',\n    });\n    expect(updateButton).toBeEnabled();\n    fireEvent.click(updateButton);\n\n    expect(saveStory).toHaveBeenCalledWith({\n      status: 'draft',\n    });\n  });\n\n  it('should allow forcing isSaving state', () => {\n    arrange({\n      props: { forceIsSaving: true },\n    });\n\n    const updateButton = screen.getByRole('button', {\n      name: 'Switch to Draft',\n    });\n    expect(updateButton).toBeDisabled();\n  });\n\n  it('should disable button while upload is in progress', () => {\n    arrange({ media: { isUploading: true } });\n    expect(\n      screen.getByRole('button', { name: 'Switch to Draft' })\n    ).toBeDisabled();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/test/update.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport MockDate from 'mockdate';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../app/story/context';\nimport MediaContext from '../../../../app/media/context';\nimport HistoryContext from '../../../../app/history/context';\nimport UpdateButton from '../update';\n\nfunction arrange({\n  props: extraButtonProps,\n  story: extraStoryProps,\n  storyState: extraStoryStateProps,\n  meta: extraMetaProps,\n  media: extraMediaProps,\n  history: extraHistoryProps,\n} = {}) {\n  const saveStory = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        publish: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n        ...extraStoryProps,\n      },\n      ...extraStoryStateProps,\n    },\n    actions: { saveStory },\n  };\n  const mediaContextValue = {\n    local: {\n      state: { ...extraMediaProps },\n    },\n  };\n  const historyContextValue = {\n    state: { ...extraHistoryProps },\n  };\n\n  renderWithTheme(\n    <HistoryContext.Provider value={historyContextValue}>\n      <StoryContext.Provider value={storyContextValue}>\n        <MediaContext.Provider value={mediaContextValue}>\n          <UpdateButton {...extraButtonProps} />\n        </MediaContext.Provider>\n      </StoryContext.Provider>\n    </HistoryContext.Provider>\n  );\n  return {\n    saveStory,\n  };\n}\n\ndescribe('UpdateButton', () => {\n  const FUTURE_DATE = '2022-01-01T20:20:20Z';\n\n  beforeAll(() => {\n    MockDate.set('2020-07-15T12:00:00+00:00');\n  });\n\n  afterAll(() => {\n    MockDate.reset();\n  });\n\n  it('should display Save button if status is not yet available', () => {\n    arrange({\n      story: { status: undefined },\n    });\n\n    expect(\n      screen.getByRole('button', { name: 'Save draft' })\n    ).toBeInTheDocument();\n  });\n\n  it('should not be able to save draft if there are no changes', () => {\n    const { saveStory } = arrange();\n\n    const updateButton = screen.getByRole('button', { name: 'Save draft' });\n    expect(updateButton).toBeDisabled();\n    fireEvent.click(updateButton);\n\n    expect(saveStory).not.toHaveBeenCalled();\n  });\n\n  it('should be able to save draft if there are changes', () => {\n    const { saveStory } = arrange({\n      history: { hasNewChanges: true },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Save draft' });\n    expect(updateButton).toBeEnabled();\n    fireEvent.click(updateButton);\n\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should be able to save a published story if there are changes', () => {\n    const { saveStory } = arrange({\n      history: { hasNewChanges: true },\n      story: { status: 'publish' },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Update' });\n    expect(updateButton).toBeEnabled();\n    fireEvent.click(updateButton);\n\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should not be able to save if there are no new changes', () => {\n    arrange({\n      history: { hasNewChanges: false },\n      story: { status: 'publish' },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Update' });\n    expect(updateButton).toBeDisabled();\n  });\n\n  it('should allow forcing isSaving state', () => {\n    arrange({\n      history: { hasNewChanges: true },\n      props: { forceIsSaving: true },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Save draft' });\n    expect(updateButton).toBeDisabled();\n  });\n\n  it('should allow forcing having updates', () => {\n    arrange({\n      history: { hasNewChanges: false },\n      props: { hasUpdates: true },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Save draft' });\n    expect(updateButton).toBeEnabled();\n  });\n\n  it('should save pending story', () => {\n    const { saveStory } = arrange({\n      history: { hasNewChanges: true },\n      story: { status: 'pending' },\n    });\n\n    const updateButton = screen.getByRole('button', {\n      name: 'Save as pending',\n    });\n    expect(updateButton).toBeEnabled();\n\n    fireEvent.click(updateButton);\n\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should be able to save a post if has changes and already published', () => {\n    const { saveStory } = arrange({\n      history: { hasNewChanges: true },\n      story: { status: 'publish' },\n    });\n\n    const updateButton = screen.getByRole('button', { name: 'Update' });\n    expect(updateButton).toBeEnabled();\n    fireEvent.click(updateButton);\n\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should disable button while upload is in progress', () => {\n    arrange({ media: { isUploading: true } });\n    expect(screen.getByRole('button', { name: 'Save draft' })).toBeDisabled();\n  });\n\n  it('should change label for published stories with future date', () => {\n    const { saveStory } = arrange({\n      story: {\n        title: 'Some title',\n        status: 'publish',\n        date: FUTURE_DATE,\n      },\n      history: {\n        hasNewChanges: true,\n      },\n    });\n    const scheduleButton = screen.getByRole('button', { name: 'Schedule' });\n\n    expect(scheduleButton).toBeInTheDocument();\n    fireEvent.click(scheduleButton);\n    expect(scheduleButton).toBeEnabled();\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should not change label for private stories with future date', () => {\n    const { saveStory } = arrange({\n      story: {\n        title: 'Some title',\n        status: 'private',\n        date: FUTURE_DATE,\n      },\n      history: {\n        hasNewChanges: true,\n      },\n    });\n    const updateButton = screen.getByRole('button', { name: 'Update' });\n    const scheduleButton = screen.queryByRole('button', { name: 'Schedule' });\n\n    expect(scheduleButton).not.toBeInTheDocument();\n    expect(updateButton).toBeInTheDocument();\n    fireEvent.click(updateButton);\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should save post via shortcut', () => {\n    const { saveStory } = arrange({\n      story: { title: 'Some title' },\n    });\n\n    fireEvent.keyDown(document.body, {\n      key: 'S',\n      which: 83,\n      ctrlKey: true,\n    });\n\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should not save post via shortcut if already saving', () => {\n    const { saveStory } = arrange({\n      story: { title: 'Some title' },\n      meta: { isSaving: true },\n    });\n\n    fireEvent.keyDown(document.body, {\n      key: 'S',\n      which: 83,\n      ctrlKey: true,\n    });\n\n    expect(saveStory).not.toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/header/buttons/update.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  useGlobalKeyDownEffect,\n  Icons,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\nimport {\n  getOptions,\n  isAfter,\n  subMinutes,\n  toDate,\n} from '@googleforcreators/date';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useHistory } from '../../../app';\nimport Tooltip from '../../tooltip';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\nimport ButtonWithChecklistWarning from './buttonWithChecklistWarning';\n\nfunction PlainButton({ text, onClick, disabled }) {\n  return (\n    <Tooltip title={text} hasTail>\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Quaternary}\n        size={ButtonSize.Small}\n        onClick={onClick}\n        disabled={disabled}\n        aria-label={text}\n      >\n        <Icons.FloppyDisk />\n      </Button>\n    </Tooltip>\n  );\n}\n\nPlainButton.propTypes = {\n  text: PropTypes.string,\n  onClick: PropTypes.func,\n  disabled: PropTypes.bool,\n};\n\nfunction UpdateButton({ hasUpdates = false, forceIsSaving = false }) {\n  const {\n    isSaving: _isSaving,\n    status,\n    date,\n    saveStory,\n    canPublish,\n  } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n        story: { status, date },\n        capabilities,\n      },\n      actions: { saveStory },\n    }) => ({\n      isSaving,\n      status,\n      date,\n      saveStory,\n      canPublish: Boolean(capabilities?.publish),\n    })\n  );\n\n  const isSaving = _isSaving || forceIsSaving;\n\n  const isUploading = useIsUploadingToStory();\n  const {\n    state: { hasNewChanges },\n  } = useHistory();\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+s'] },\n    (event) => {\n      event.preventDefault();\n      if (isSaving || isUploading) {\n        return;\n      }\n      saveStory();\n    },\n    [saveStory, isSaving, isUploading]\n  );\n\n  // The button is enabled only if we're not already saving nor uploading. And\n  // then only if there are new changes or the story has meta-boxes – as these\n  // can update without us knowing it.\n  const isEnabled = !isSaving && !isUploading && (hasNewChanges || hasUpdates);\n\n  const isPending = 'pending' === status;\n  const isDraft = ['draft', 'auto-draft'].includes(status) || !status;\n\n  if (isPending) {\n    return (\n      <PlainButton\n        text={__('Save as pending', 'web-stories')}\n        disabled={!isEnabled}\n        onClick={() => saveStory()}\n      />\n    );\n  }\n\n  if (isDraft) {\n    return (\n      <PlainButton\n        text={__('Save draft', 'web-stories')}\n        disabled={!isEnabled}\n        onClick={() => saveStory()}\n      />\n    );\n  }\n\n  // Offset the date by one minute to accommodate for network latency.\n  const hasFutureDate = isAfter(\n    subMinutes(toDate(date, getOptions()), 1),\n    toDate(new Date(), getOptions())\n  );\n\n  const text =\n    hasFutureDate && status !== 'private'\n      ? __('Schedule', 'web-stories')\n      : __('Update', 'web-stories');\n\n  return (\n    <ButtonWithChecklistWarning\n      text={text}\n      onClick={() => saveStory()}\n      disabled={!isEnabled}\n      isUploading={isUploading}\n      canPublish={canPublish}\n    />\n  );\n}\n\nUpdateButton.propTypes = {\n  hasUpdates: PropTypes.bool,\n  forceIsSaving: PropTypes.bool,\n};\n\nexport default UpdateButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './buttons';\nexport { default as HeaderTitle } from './title';\n"
  },
  {
    "path": "packages/story-editor/src/components/header/previewErrorDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\n\nfunction PreviewErrorDialog({ isOpen, onClose, onRetry }) {\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      title={__('Open preview', 'web-stories')}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={onRetry}\n      primaryText={__('Try again', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__('The preview window failed to open.', 'web-stories')}\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nPreviewErrorDialog.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  onClose: PropTypes.func.isRequired,\n  onRetry: PropTypes.func.isRequired,\n};\n\nexport default PreviewErrorDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/header/stories/previewErrorDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PreviewErrorDialog from '../previewErrorDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Preview Error',\n  component: PreviewErrorDialog,\n  args: {\n    isOpen: true,\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n    onRetry: { action: 'retried' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <PreviewErrorDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/header/title.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\nimport { updateSlug } from '../../utils/storyUpdates';\nimport { states, useHighlights } from '../../app/highlights';\nimport styles from '../../app/highlights/styles';\n\nconst Input = styled.input`\n  color: ${({ theme }) => `${theme.colors.fg.primary} !important`};\n  margin: 0;\n  ${themeHelpers.expandTextPreset(\n    ({ paragraph }, { Medium }) => paragraph[Medium]\n  )}\n  background: ${({ isHighlighted }) => !isHighlighted && 'none !important'};\n  border: none !important;\n  text-align: start;\n  min-width: 60%;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n\n  ${themeHelpers.focusableOutlineCSS};\n\n  ${({ isHighlighted }) =>\n    isHighlighted &&\n    css`\n      ${styles.OUTLINE}\n      ${styles.FLASH}\n    `}\n`;\n\nfunction HeaderTitle() {\n  const { title, slug, updateStory } = useStory(\n    ({\n      state: {\n        story: { title, slug },\n      },\n      actions: { updateStory },\n    }) => ({ title, slug, updateStory })\n  );\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.StoryTitle],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  const handleChange = useCallback(\n    (evt) => updateStory({ properties: { title: evt.target.value } }),\n    [updateStory]\n  );\n\n  const handleBlur = useCallback(() => {\n    updateSlug({\n      currentSlug: slug,\n      currentTitle: title,\n      updateStory,\n    });\n  }, [slug, title, updateStory]);\n\n  if (typeof title !== 'string') {\n    return null;\n  }\n\n  return (\n    <Input\n      ref={(node) => {\n        if (node && highlight?.focus && highlight?.showEffect) {\n          node.addEventListener('keydown', cancelHighlight, { once: true });\n          node.focus();\n        }\n      }}\n      value={title}\n      type=\"text\"\n      onBlur={handleBlur}\n      onChange={handleChange}\n      placeholder={__('Add title', 'web-stories')}\n      aria-label={__('Story title', 'web-stories')}\n      isHighlighted={highlight?.showEffect}\n      onAnimationEnd={() => resetHighlight()}\n    />\n  );\n}\n\nexport default HeaderTitle;\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/companion/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { TransitionGroup } from 'react-transition-group';\nimport PropTypes from 'prop-types';\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { Menu } from '../menu';\nimport { QuickTip } from '../quickTip';\nimport { DONE_TIP_ENTRY } from '../../../app/helpCenter/constants';\nimport { useHelpCenter } from '../../../app';\n\nfunction Companion({\n  tipKey,\n  onTipSelect,\n  isLeftToRightTransition,\n  readTips,\n  components,\n}) {\n  const {\n    state: { tips },\n  } = useHelpCenter();\n  const TIP_MAP = { ...tips, [DONE_TIP_ENTRY[0]]: DONE_TIP_ENTRY[1] };\n  const tip = tipKey && TIP_MAP[tipKey];\n\n  return (\n    <TransitionGroup>\n      {tip ? (\n        <QuickTip\n          key={tipKey}\n          isDone={tipKey === DONE_TIP_ENTRY[0]}\n          transitionKey={tipKey}\n          isLeftToRightTransition={isLeftToRightTransition}\n          {...tip}\n        />\n      ) : (\n        <Menu\n          key=\"menu\"\n          readTips={readTips}\n          onTipSelect={onTipSelect}\n          components={components}\n        />\n      )}\n    </TransitionGroup>\n  );\n}\n\nCompanion.propTypes = {\n  readTips: PropTypes.object,\n  tipKey: PropTypes.string,\n  onTipSelect: PropTypes.func.isRequired,\n  isLeftToRightTransition: PropTypes.bool.isRequired,\n  components: PropTypes.object,\n};\n\nexport default memo(Companion);\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useRef, useEffect, useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { ThemeGlobals } from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useStoryTriggerListener, STORY_EVENTS } from '../../app/story';\nimport { Z_INDEX_FOOTER } from '../../constants/zIndex';\nimport DirectionAware from '../directionAware';\nimport { useHelpCenter } from '../../app/helpCenter';\nimport { POPUP_ID, KEYS } from '../../app/helpCenter/constants';\nimport Popup from '../secondaryPopup';\nimport Navigator from './navigator';\nimport Companion from './companion';\nimport { Toggle } from './toggle';\nimport { forceFocusCompanion } from './utils';\n\nconst Wrapper = styled.div`\n  z-index: ${Z_INDEX_FOOTER};\n`;\n\nexport const HelpCenter = ({ components }) => {\n  const ref = useRef(null);\n  const { state, actions } = useHelpCenter();\n\n  // Set Focus on the expanded companion\n  // whenever it opens\n  useEffect(() => {\n    if (state.isOpen) {\n      forceFocusCompanion();\n    }\n  }, [state.isOpen]);\n\n  useStoryTriggerListener(\n    STORY_EVENTS.onReplaceBackgroundMedia,\n    useCallback(() => {\n      actions.openToUnreadTip(KEYS.ADD_BACKGROUND_MEDIA);\n    }, [actions])\n  );\n\n  useStoryTriggerListener(\n    STORY_EVENTS.onReplaceForegroundMedia,\n    useCallback(() => {\n      actions.openToUnreadTip(KEYS.CROP_SELECTED_ELEMENTS);\n    }, [actions])\n  );\n\n  return (\n    <DirectionAware>\n      <>\n        <ThemeGlobals.Styles />\n        <Wrapper ref={ref}>\n          <Popup\n            popupId={POPUP_ID}\n            isOpen={state.isOpen}\n            ariaLabel={__('Help Center', 'web-stories')}\n          >\n            <Navigator\n              isOpen={state.isOpen}\n              onNext={actions.goToNext}\n              onPrev={actions.goToPrev}\n              onAllTips={actions.goToMenu}\n              onClose={actions.close}\n              hasBottomNavigation={state.hasBottomNavigation}\n              isNextDisabled={state.isNextDisabled}\n              isPrevDisabled={state.isPrevDisabled}\n            >\n              <Companion\n                readTips={state.readTips}\n                tipKey={state.navigationFlow[state.navigationIndex]}\n                onTipSelect={actions.goToTip}\n                isLeftToRightTransition={state.isLeftToRightTransition}\n                components={components}\n              />\n            </Navigator>\n          </Popup>\n          <Toggle\n            isOpen={state.isOpen}\n            onClick={actions.toggle}\n            notificationCount={state.unreadTipsCount}\n            popupId={POPUP_ID}\n          />\n        </Wrapper>\n      </>\n    </DirectionAware>\n  );\n};\n\nHelpCenter.propTypes = {\n  components: PropTypes.object,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/karma/helpCenter.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { DONE_TIP_ENTRY, KEYS, TIPS } from '../../../app/helpCenter/constants';\n\ndescribe('Help Center integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('Help Center aXe tests', () => {\n    it('should have no aXe violations from default view', async () => {\n      await expectAsync(\n        fixture.editor.helpCenter.quickTips\n      ).toHaveNoViolations();\n    });\n\n    it('should have no aXe violations from tip view', async () => {\n      const { quickTips } = await fixture.editor.helpCenter;\n      const { getByRole } = within(quickTips);\n\n      const cropTip = getByRole('button', { name: 'Crop selected element' });\n\n      await fixture.events.click(cropTip);\n      await expectAsync(\n        await fixture.editor.helpCenter.quickTips\n      ).toHaveNoViolations();\n    });\n  });\n\n  describe('Help Center default navigation', () => {\n    it('should show Help Center by default for a new user with 7 unread tips', async () => {\n      const { quickTips, toggleButton } = await fixture.editor.helpCenter;\n      expect(quickTips).toBeDefined();\n\n      expect(toggleButton).toHaveTextContent('7');\n    });\n\n    it('should navigate to the second tip on click and update unread count to 6', async () => {\n      const { quickTips, toggleButton } = await fixture.editor.helpCenter;\n      const { getByRole, getByText } = within(quickTips);\n\n      const cropTip = getByRole('button', { name: 'Crop selected element' });\n\n      await fixture.events.click(cropTip);\n\n      const exposedCropTip = getByText(\n        TIPS[KEYS.CROP_SELECTED_ELEMENTS].description\n      );\n      expect(exposedCropTip).toBeDefined();\n\n      expect(toggleButton).toHaveTextContent('6');\n    });\n  });\n\n  describe('Help Center cursor interaction', () => {\n    it('should toggle the Help Center closed and open again with cursor', async () => {\n      const { quickTips, toggleButton } = fixture.editor.helpCenter;\n      expect(quickTips).toBeDefined();\n\n      await fixture.events.click(toggleButton);\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeNull();\n\n      await fixture.events.click(toggleButton);\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeDefined();\n    });\n\n    it('should close the Help Center when the \"close\" button is clicked', async () => {\n      const { getByRole } = within(fixture.editor.helpCenter.quickTips);\n\n      const closeButton = getByRole('button', { name: /Close/ });\n      expect(closeButton).toBeTruthy();\n      await fixture.events.click(closeButton);\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeNull();\n    });\n\n    it('should update remaining unread tips as they are clicked through', async () => {\n      const { quickTips, toggleButton } = fixture.editor.helpCenter;\n      expect(toggleButton).toHaveTextContent('7');\n\n      const { getByTestId } = within(quickTips);\n\n      const mainMenu = getByTestId('help_center_container');\n      expect(mainMenu).toBeTruthy();\n\n      const { queryAllByRole } = within(mainMenu);\n\n      const tips = queryAllByRole('button');\n      // go to the first tip\n      await fixture.events.click(tips[0]);\n\n      const nextButton = fixture.screen.getByRole('button', { name: /^Next$/ });\n      expect(nextButton).toBeTruthy();\n\n      let clickCount = 1;\n      const totalTipCount = Object.keys(TIPS).length;\n      while (clickCount <= totalTipCount) {\n        expect(toggleButton).toHaveTextContent(\n          `${7 - clickCount <= 0 ? '' : 7 - clickCount}`\n        );\n\n        // eslint-disable-next-line no-await-in-loop\n        await fixture.events.click(nextButton);\n        clickCount++;\n      }\n\n      // disabled is null before this, we're just seeing it's present.\n      expect(nextButton.getAttribute('disabled')).toBe('');\n\n      // now that we have gone through all the tips we should see a \"done\" screen\n      expect(\n        fixture.screen.getByText(DONE_TIP_ENTRY[1].description)\n      ).toBeDefined();\n    });\n  });\n\n  describe('Help Center keyboard interaction', () => {\n    it('should toggle the Help Center closed and open again with keyboard', async () => {\n      const { quickTips, toggleButton } = fixture.editor.helpCenter;\n      expect(quickTips).toBeDefined();\n\n      await fixture.events.focus(toggleButton);\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeNull();\n\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeDefined();\n    });\n\n    it('should close the Help Center when pressing enter on the \"close\" button', async () => {\n      const { getByRole } = within(fixture.editor.helpCenter.quickTips);\n\n      const closeButton = getByRole('button', { name: /Close/ });\n      expect(closeButton).toBeTruthy();\n      await fixture.events.focus(closeButton);\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.sleep(500);\n      expect(fixture.editor.helpCenter.quickTips).toBeNull();\n    });\n\n    it('should navigate quick tips with tab and enter', async () => {\n      const { quickTips, toggleButton } = fixture.editor.helpCenter;\n      expect(quickTips).toBeDefined();\n      const { getByTestId, getByText } = within(quickTips);\n\n      const mainMenu = getByTestId('help_center_container');\n      expect(mainMenu).toBeTruthy();\n\n      const { queryAllByRole } = within(mainMenu);\n\n      const tips = queryAllByRole('button');\n      // confirm that there are 7 buttons present in this section\n      expect(tips.length).toBe(7);\n\n      await fixture.events.focus(tips[0]);\n      // confirm our starting spot is accurate\n      expect(document.activeElement).toBe(tips[0]);\n      // tab to the third item\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('tab');\n      expect(document.activeElement).toBe(tips[2]);\n\n      await fixture.events.keyboard.press('Enter');\n\n      const exposedCropTip = getByText(\n        TIPS[KEYS.CROP_ELEMENTS_WITH_SHAPES].description\n      );\n      expect(exposedCropTip).toBeDefined();\n      expect(toggleButton).toHaveTextContent('6');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/menu/header.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { themeHelpers, Text, TextSize } from '@googleforcreators/design-system';\n\nconst Panel = styled.div`\n  padding: 24px 0 16px 0;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.bg.tertiary};\n`;\n\nconst Heading = styled.h1`\n  ${themeHelpers.expandTextPreset(({ label }, { Medium }) => label[Medium])}\n  color: ${({ theme }) => theme.colors.fg.primary};\n  line-height: 32px;\n  margin: 0 0 8px 0;\n`;\n\nexport function Header() {\n  return (\n    <Panel>\n      <Heading as=\"h2\">{__('Web Stories Help Center', 'web-stories')}</Heading>\n      <Text.Paragraph size={TextSize.XSmall}>\n        {__(\n          'Discover tips & resources to help you get the most out of your Web Stories.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Panel>\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/menu/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../utils/noop';\nimport { GUTTER_WIDTH } from '../../../app/helpCenter/constants';\nimport { Header } from './header';\nimport { Tips } from './tips';\nimport { Transitioner } from './transitioner';\n\nconst Container = styled.div`\n  padding: 0 ${GUTTER_WIDTH}px;\n  max-height: 60vh;\n  overflow-y: scroll;\n\n  * {\n    user-select: text;\n  }\n`;\n\nexport function Menu({\n  onTipSelect = noop,\n  readTips,\n  components,\n  ...transitionProps\n}) {\n  const Footer = components?.Footer;\n  return (\n    <Transitioner {...transitionProps}>\n      <Container data-testid=\"help_center_container\">\n        <Header />\n        <Tips readTips={readTips} onTipSelect={onTipSelect} />\n        {Footer && <Footer />}\n      </Container>\n    </Transitioner>\n  );\n}\nMenu.propTypes = {\n  readTips: PropTypes.object,\n  onTipSelect: PropTypes.func.isRequired,\n  components: PropTypes.shape({\n    Footer: PropTypes.elementType,\n  }),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/menu/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { ThemeProvider } from 'styled-components';\nimport { useState } from '@googleforcreators/react';\nimport { TransitionGroup } from 'react-transition-group';\nimport {\n  theme as dsTheme,\n  ThemeGlobals,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Menu as HelpCenterMenu } from '..';\nimport { HelpCenterProvider } from '../../../../app/helpCenter';\n\nexport default {\n  title: 'Stories Editor/Components/Help Center/Menu',\n};\n\nconst Bg = styled.div`\n  position: relative;\n  top: 0;\n  left: 0;\n  height: 602px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  padding: 0 50px;\n`;\n\nconst Container = styled.div`\n  position: relative;\n  width: 340px;\n  height: 100%;\n`;\n\nexport const Menu = () => {\n  const [mounted, setMounted] = useState(true);\n  return (\n    <ThemeProvider theme={dsTheme}>\n      <ThemeGlobals.Styles />\n      <HelpCenterProvider>\n        <button onClick={() => setMounted((v) => !v)}>\n          {mounted ? 'unmount' : 'mount'}\n        </button>\n        <Bg>\n          <Container>\n            <TransitionGroup component={null}>\n              {mounted && <HelpCenterMenu key=\"someKey\" readTips={{}} />}\n            </TransitionGroup>\n          </Container>\n        </Bg>\n      </HelpCenterProvider>\n    </ThemeProvider>\n  );\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/menu/tips.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  Button,\n  ButtonSize,\n  Icons,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../app/config';\nimport { forceFocusCompanion } from '../utils';\nimport { useHelpCenter } from '../../../app';\nimport { noop } from '../../../utils/noop';\n\nconst Panel = styled.div`\n  padding: 24px 0;\n`;\n\nconst StyledButton = styled(Button)`\n  ${themeHelpers.expandTextPreset(({ label }, { Small }) => label[Small])}\n  display: flex;\n  justify-content: space-between;\n  width: 100%;\n  padding: 6px 0;\n`;\n\nconst ButtonText = styled.span`\n  vertical-align: middle;\n  text-align: left;\n\n  ${({ unread, theme }) =>\n    unread &&\n    css`\n      &::before {\n        content: ' ';\n        display: inline-block;\n        height: 10px;\n        width: 10px;\n        margin-right: 16px;\n        border-radius: ${theme.borders.radius.round};\n        background-color: ${theme.colors.accent.primary};\n      }\n    `}\n`;\n\nconst ArrowWrap = styled.div`\n  width: 32px;\n  margin: -9px;\n  transform-origin: 50% 50%;\n  transform: ${({ $isRTL }) => ($isRTL ? 'none' : 'rotate(180deg)')};\n`;\n\nconst StyledArrow = styled(Icons.ArrowLeft)`\n  width: 100%;\n`;\n\nfunction Tip({ children, onClick, unread = true }) {\n  const { isRTL } = useConfig();\n  return (\n    <StyledButton size={ButtonSize.Small} onClick={onClick}>\n      <ButtonText unread={unread}>{children}</ButtonText>\n      <ArrowWrap $isRTL={isRTL}>\n        <StyledArrow />\n      </ArrowWrap>\n    </StyledButton>\n  );\n}\nTip.propTypes = {\n  children: PropTypes.node,\n  onClick: PropTypes.func,\n  unread: PropTypes.bool,\n};\n\nexport function Tips({ onTipSelect = noop, readTips }) {\n  const {\n    state: { tips },\n  } = useHelpCenter();\n  const tipsIterable = Object.entries(tips);\n\n  return (\n    <Panel>\n      {tipsIterable.map(([key, tip]) => (\n        <Tip\n          unread={!readTips[key]}\n          key={key}\n          onClick={() => {\n            forceFocusCompanion();\n            onTipSelect(key);\n          }}\n        >\n          {tip.title}\n        </Tip>\n      ))}\n    </Panel>\n  );\n}\nTips.propTypes = {\n  readTips: PropTypes.object,\n  onTipSelect: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/menu/transitioner.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { BEZIER } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { ScheduledTransition } from '../../transition/scheduledTransition';\nimport {\n  TRANSITION_DURATION,\n  Z_INDEX,\n} from '../../../app/helpCenter/constants';\n\nconst DURATION = 1.2 * TRANSITION_DURATION;\n\nconst enterStyles = css`\n  opacity: 1;\n  transform: none;\n`;\nconst exitStyles = css`\n  position: absolute;\n  bottom: 0;\n  opacity: 0.6;\n  transform: scale(0.96);\n`;\n\nconst transitionStyles = {\n  entering: enterStyles,\n  entered: enterStyles,\n  exiting: exitStyles,\n  exited: exitStyles,\n};\n\nconst Manager = styled.div`\n  position: relative;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  opacity: 0.6;\n  transform-origin: 50% 50%;\n  transform: scale(0.96);\n  transition:\n    transform ${DURATION}ms ${BEZIER.default},\n    opacity ${DURATION}ms ${BEZIER.default};\n  z-index: ${Z_INDEX.MENU};\n\n  ${({ state }) => transitionStyles[state]};\n`;\n\nexport function Transitioner({ children, ...props }) {\n  return (\n    <ScheduledTransition\n      {...props}\n      timeout={DURATION}\n      mountOnEnter\n      unmountOnExit\n    >\n      {(state) => <Manager state={state}>{children}</Manager>}\n    </ScheduledTransition>\n  );\n}\n\nTransitioner.propTypes = {\n  children: PropTypes.node,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/navigator/bottomNavigation.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useEffect, useState, useRef } from '@googleforcreators/react';\nimport {\n  ButtonSize,\n  ButtonType,\n  Icons,\n  BEZIER,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../app/config';\nimport { TRANSITION_DURATION } from '../../../app/helpCenter/constants';\nimport { forceFocusCompanion } from '../utils';\nimport { NavBar, NavButton } from '../../secondaryPopup';\n\nconst secondaryTextStyle = css`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst AllTips = styled.span`\n  ${secondaryTextStyle}\n`;\n\nconst BottomNavBar = styled(NavBar)`\n  position: absolute;\n  bottom: 0;\n  transition: transform ${TRANSITION_DURATION}ms ${BEZIER.default};\n  z-index: 2;\n  ${({ isHidden }) =>\n    isHidden &&\n    css`\n      transform: translateY(100%);\n    `}\n`;\n\nconst BottomNavButtons = styled.div`\n  display: flex;\n  padding: 0 16px;\n  white-space: nowrap;\n`;\n\nconst ArrowWrap = styled.div`\n  ${secondaryTextStyle}\n  margin: -5px -16px;\n  ${({ $isRTL }) =>\n    $isRTL &&\n    css`\n      transform: rotate(180deg);\n    `}\n  svg {\n    display: block;\n  }\n`;\n\nconst onCondition = (condition) => (fn) => {\n  if (condition) {\n    fn();\n  }\n};\n\nexport function BottomNavigation({\n  onAllTips,\n  onPrev,\n  onNext,\n  hasBottomNavigation,\n  isNextDisabled,\n  isPrevDisabled,\n}) {\n  const { isRTL } = useConfig();\n  // If either the prev or next has focus and become disabled,\n  // we want to force focus to the companion instead of losing\n  // it to the canvas.\n  const prevButtonRef = useRef(null);\n  const nextButtonRef = useRef(null);\n  const [local, setLocal] = useState({\n    isPrevDisabled,\n    isNextDisabled,\n  });\n  // We want to force focus one render before we disable the actual\n  // DOM elements so we can see if they're currently focused.\n  useEffect(() => {\n    [\n      isPrevDisabled && document.activeElement === prevButtonRef.current,\n      isNextDisabled && document.activeElement === nextButtonRef.current,\n    ].forEach((condition) => onCondition(condition)(forceFocusCompanion));\n    setLocal({ isPrevDisabled, isNextDisabled });\n  }, [isPrevDisabled, isNextDisabled]);\n\n  return (\n    <BottomNavBar\n      aria-hidden={!hasBottomNavigation}\n      isHidden={!hasBottomNavigation}\n    >\n      <BottomNavButtons>\n        <NavButton\n          onClick={() => {\n            forceFocusCompanion();\n            onAllTips();\n          }}\n          type={ButtonType.Plain}\n          size={ButtonSize.Small}\n          disabled={!hasBottomNavigation}\n        >\n          <ArrowWrap $isRTL={isRTL}>\n            <Icons.ArrowLeft />\n          </ArrowWrap>\n          <AllTips>{__('All Tips', 'web-stories')}</AllTips>\n        </NavButton>\n      </BottomNavButtons>\n      <BottomNavButtons>\n        <NavButton\n          ref={prevButtonRef}\n          onClick={onPrev}\n          type={ButtonType.Plain}\n          size={ButtonSize.Small}\n          disabled={!hasBottomNavigation || local.isPrevDisabled}\n        >\n          {__('Previous', 'web-stories')}\n        </NavButton>\n        <NavButton\n          ref={nextButtonRef}\n          onClick={onNext}\n          type={ButtonType.Plain}\n          size={ButtonSize.Small}\n          disabled={!hasBottomNavigation || local.isNextDisabled}\n        >\n          {__('Next', 'web-stories')}\n        </NavButton>\n      </BottomNavButtons>\n    </BottomNavBar>\n  );\n}\n\nBottomNavigation.propTypes = {\n  onNext: PropTypes.func.isRequired,\n  onPrev: PropTypes.func.isRequired,\n  onAllTips: PropTypes.func.isRequired,\n  hasBottomNavigation: PropTypes.bool,\n  isNextDisabled: PropTypes.bool,\n  isPrevDisabled: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/navigator/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport {\n  memo,\n  useEffect,\n  useRef,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { POPUP_ID } from '../../../app/helpCenter/constants';\nimport { NavigationWrapper, TopNavigation } from '../../secondaryPopup';\nimport { BottomNavigation } from './bottomNavigation';\nimport { removeInnerElementFromLayoutFlow } from './utils';\n\nconst Layout = styled.div`\n  ${themeHelpers.fullSizeRelative}\n  contain: content;\n`;\n\nconst Content = styled.div``;\nconst ContentInner = styled.div`\n  position: relative;\n`;\n\nfunction Navigator({\n  children,\n  isOpen,\n  onClose,\n  onNext,\n  onPrev,\n  onAllTips,\n  hasBottomNavigation,\n  isNextDisabled,\n  isPrevDisabled,\n}) {\n  const innerRef = useRef(null);\n  const layoutRef = useRef(null);\n\n  // After first mount, make layout height independent\n  // of inner content height without disrupting layout.\n  useEffect(\n    () => removeInnerElementFromLayoutFlow(innerRef.current, layoutRef.current),\n    []\n  );\n\n  // Listen to changes in inner content height and apply\n  // them to the layout container to animate to those updates.\n  useResizeEffect(\n    innerRef,\n    ({ height }) => {\n      if (layoutRef.current) {\n        layoutRef.current.style.height = `${height}px`;\n      }\n    },\n    []\n  );\n\n  return (\n    <NavigationWrapper isOpen={isOpen}>\n      <TopNavigation\n        onClose={onClose}\n        label={__('Quick Tips', 'web-stories')}\n        popupId={POPUP_ID}\n      />\n      <Layout ref={layoutRef}>\n        <Content ref={innerRef}>\n          <ContentInner>{children}</ContentInner>\n        </Content>\n      </Layout>\n      <BottomNavigation\n        onNext={onNext}\n        onPrev={onPrev}\n        onAllTips={onAllTips}\n        hasBottomNavigation={hasBottomNavigation}\n        isNextDisabled={isNextDisabled}\n        isPrevDisabled={isPrevDisabled}\n      />\n    </NavigationWrapper>\n  );\n}\n\nNavigator.propTypes = {\n  isOpen: PropTypes.bool,\n  children: PropTypes.node.isRequired,\n  onClose: PropTypes.func.isRequired,\n  onNext: PropTypes.func.isRequired,\n  onPrev: PropTypes.func.isRequired,\n  onAllTips: PropTypes.func.isRequired,\n  hasBottomNavigation: PropTypes.bool,\n  isNextDisabled: PropTypes.bool,\n  isPrevDisabled: PropTypes.bool,\n};\n\nexport default memo(Navigator);\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/navigator/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  theme as dsTheme,\n  ThemeGlobals,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport HelpCenterNavigator from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Help Center/Navigator',\n};\n\nconst Bg = styled.div`\n  position: relative;\n  top: 0;\n  left: 0;\n  height: 100vh;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  padding: 50px;\n`;\n\nconst Wrapper = styled.div`\n  position: absolute;\n  bottom: 50px;\n  left: 50px;\n`;\n\nexport const Navigator = () => {\n  const [visible, setVisible] = useState(false);\n  return (\n    <ThemeProvider theme={dsTheme}>\n      <ThemeGlobals.Styles />\n      <Bg>\n        <Wrapper>\n          <HelpCenterNavigator\n            onNext={() => {}}\n            onPrev={() => {}}\n            hasBottomNavigation={visible}\n          >\n            {visible ? (\n              <div>\n                <div>\n                  <h1>{'Hello'}</h1>\n                </div>\n                <div>\n                  <h1>{'Hello'}</h1>\n                </div>\n                <div>\n                  <h1>{'Hello'}</h1>\n                </div>\n              </div>\n            ) : (\n              <div>\n                <div>\n                  <h1>{'WORLD'}</h1>\n                </div>\n                <div>\n                  <h1>{'WORLD'}</h1>\n                </div>\n              </div>\n            )}\n          </HelpCenterNavigator>\n        </Wrapper>\n        <button onClick={() => setVisible((b) => !b)}>\n          {'Toggle Children'}\n        </button>\n      </Bg>\n    </ThemeProvider>\n  );\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/navigator/utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { BEZIER } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { TRANSITION_DURATION } from '../../../app/helpCenter/constants';\nimport { noop } from '../../../utils/noop';\n\n/**\n * Removes inner Element from the layout flow without disrupting\n * visual layout. Adds transition for height of outer Element\n * So it animates if it changes.\n *\n * @param {HTMLElement} innerEl - element we're removing from layout flow\n * @param {HTMLElement} outerEl - element we're applying height to\n * @return {Function} cleanup method\n */\nexport function removeInnerElementFromLayoutFlow(innerEl, outerEl) {\n  if (!innerEl || !outerEl) {\n    return noop;\n  }\n\n  // Explicitly set height of outer container to not\n  // disrupt current visual layout.\n  const { height } = innerEl.getBoundingClientRect();\n  outerEl.style.height = `${height}px`;\n\n  // Remove inner element from layout flow\n  innerEl.style.position = 'absolute';\n  innerEl.style.bottom = 0;\n  innerEl.style.content = 'contain';\n\n  // Applying transition on separate frame as a\n  // change to the animated property. This prevents any\n  // content flash.\n  //\n  // Only way to guarantee the frame after styles\n  // get applied is to do 2 frames from now.\n  let id = requestAnimationFrame(() => {\n    id = requestAnimationFrame(() => {\n      outerEl.style.transition = `height ${TRANSITION_DURATION}ms ${BEZIER.default}`;\n    });\n  });\n  return () => cancelAnimationFrame(id);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/quickTip/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { TranslateWithMarkup } from '@googleforcreators/i18n';\nimport {\n  Link,\n  themeHelpers,\n  Text,\n  TextSize,\n  VisuallyHidden,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { NAVIGATION_HEIGHT } from '../../secondaryPopup';\nimport { GUTTER_WIDTH } from '../../../app/helpCenter/constants';\nimport { useConfig } from '../../../app';\nimport { Transitioner } from './transitioner';\nimport DoneCheckmark from './icons/doneCheckmark.svg';\n\nconst Panel = styled.div`\n  width: 100%;\n  padding-bottom: ${NAVIGATION_HEIGHT}px;\n\n  * {\n    user-select: text;\n  }\n`;\n\nconst Overflow = styled.div`\n  position: relative;\n  width: 100%;\n  max-height: 70vh;\n  padding: ${GUTTER_WIDTH}px;\n\n  strong {\n    font-weight: 700;\n  }\n`;\n\nconst Video = styled.video`\n  height: 180px;\n  margin-bottom: ${GUTTER_WIDTH}px;\n  max-width: 100%;\n`;\n\nconst Title = styled.h1`\n  ${themeHelpers.expandTextPreset(({ label }, { Medium }) => label[Medium])}\n  color: ${({ theme }) => theme.colors.fg.primary};\n  line-height: 32px;\n  margin: 0 0 8px 0;\n`;\n\nconst Paragraph = styled(Text.Paragraph)`\n  & + & {\n    margin-top: 8px;\n  }\n`;\n\nconst DoneContainer = styled.div`\n  ${themeHelpers.centerContent}\n  height: 180px;\n  margin-bottom: ${GUTTER_WIDTH}px;\n  color: #f4f2ef;\n\n  svg {\n    display: block;\n\n    path {\n      color: #4285f4;\n    }\n  }\n`;\n\nexport function QuickTip({\n  title,\n  description,\n  isLeftToRightTransition = true,\n  figureSrc,\n  figureSrcImg,\n  figureAlt,\n  href,\n  isDone = false,\n  ...transitionProps\n}) {\n  const { cdnURL } = useConfig();\n  return (\n    <Transitioner\n      {...transitionProps}\n      isLeftToRightTransition={isLeftToRightTransition}\n    >\n      <Panel>\n        <Overflow>\n          {Boolean(figureSrc) && (\n            <Video\n              controls={false}\n              autoPlay\n              loop\n              muted\n              noControls\n              preload=\"true\"\n              crossOrigin=\"anonymous\"\n            >\n              <source src={`${cdnURL}${figureSrc}.webm`} type=\"video/webm\" />\n              <source src={`${cdnURL}${figureSrc}.mp4`} type=\"video/mp4\" />\n            </Video>\n          )}\n          {/* `figureSrcImg` is temporary until we get an animation for the embed quick tip.\n          Once we have the animation then the .png image won't be necessary */}\n          {figureSrcImg && (\n            //eslint-disable-next-line jsx-a11y/media-has-caption -- False positive because it's actually an image.\n            <Video\n              as=\"img\"\n              alt={figureAlt}\n              src={`${cdnURL}${figureSrcImg}.png`}\n              crossOrigin=\"anonymous\"\n            />\n          )}\n          {isDone && (\n            <DoneContainer>\n              <DoneCheckmark height={135} width={135} />\n            </DoneContainer>\n          )}\n          <Title>{title}</Title>\n          {description.map((paragraph, i) => (\n            <Paragraph\n              // eslint-disable-next-line react/no-array-index-key -- Should be OK due to also using the title.\n              key={`${title}-${i}`}\n              size={TextSize.Small}\n            >\n              <TranslateWithMarkup\n                mapping={{\n                  a: (\n                    <Link\n                      size={TextSize.Small}\n                      rel=\"noreferrer\"\n                      target=\"_blank\"\n                      href={href}\n                    />\n                  ),\n                  screenreader: <VisuallyHidden />,\n                }}\n              >\n                {paragraph}\n              </TranslateWithMarkup>\n            </Paragraph>\n          ))}\n        </Overflow>\n      </Panel>\n    </Transitioner>\n  );\n}\n\nQuickTip.propTypes = {\n  /* Temporary props: `figureAlt`, `figureSrc`.\n  See packages/story-editor/src/app/helpCenter/constants.js. */\n  figureAlt: PropTypes.string,\n  figureSrc: PropTypes.string,\n  figureSrcImg: PropTypes.string,\n  href: PropTypes.string,\n  isDone: PropTypes.bool,\n  title: PropTypes.string.isRequired,\n  description: PropTypes.arrayOf(PropTypes.string).isRequired,\n  isLeftToRightTransition: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/quickTip/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { TransitionGroup } from 'react-transition-group';\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  theme as dsTheme,\n  ThemeGlobals,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { TIPS } from '../../../../app/helpCenter/constants';\nimport { QuickTip as HelpCenterQuickTip } from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Help Center/Quick Tip',\n  args: {\n    isLeftToRightTransition: true,\n  },\n};\n\nconst Bg = styled.div`\n  position: relative;\n  top: 0;\n  left: 0;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  padding: 0 50px;\n`;\n\nconst Container = styled.div`\n  position: relative;\n  width: 340px;\n  height: 100%;\n  height: 400px;\n  overflow: hidden;\n`;\n\nconst [tip] = Object.values(TIPS);\nexport const QuickTip = {\n  render: function Render(args) {\n    const [toggled, setToggled] = useState(true);\n    return (\n      <ThemeProvider theme={dsTheme}>\n        <ThemeGlobals.Styles />\n        <button onClick={() => setToggled((v) => !v)}>{'toggleTips'}</button>\n        <Bg>\n          <Container>\n            <TransitionGroup component={null}>\n              <HelpCenterQuickTip\n                key={toggled ? 'key1' : 'key2'}\n                title={tip.title}\n                description={tip.description}\n                {...args}\n              />\n            </TransitionGroup>\n          </Container>\n        </Bg>\n      </ThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/quickTip/transitioner.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { BEZIER } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { ScheduledTransition } from '../../transition/scheduledTransition';\nimport {\n  TRANSITION_DURATION,\n  Z_INDEX,\n} from '../../../app/helpCenter/constants';\n\nconst DELAY = 80;\nconst DURATION = TRANSITION_DURATION - DELAY;\n\nconst Opacity = styled.div``;\n\nconst enterStyles = () => css`\n  transition-delay: ${DELAY}ms;\n  transform: none;\n  ${Opacity} {\n    opacity: 1;\n  }\n`;\n\nconst exitStyles = ({ isLeftToRightTransition }) => css`\n  position: absolute;\n  bottom: 0;\n\n  ${Opacity} {\n    opacity: 0;\n  }\n\n  ${isLeftToRightTransition\n    ? css`\n        transform: translateX(-100%);\n      `\n    : css`\n        transform: translateX(100%);\n      `}\n`;\n\nconst transitionStyles = {\n  entering: enterStyles,\n  entered: enterStyles,\n  exiting: exitStyles,\n  exited: exitStyles,\n};\n\nconst Manager = styled.div`\n  position: relative;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  transition: transform ${DURATION}ms ${BEZIER.default};\n  transform-origin: 50% 50%;\n  z-index: ${Z_INDEX.QUICK_TIP};\n  ${({ isLeftToRightTransition }) =>\n    isLeftToRightTransition\n      ? css`\n          transform: translateX(100%);\n        `\n      : css`\n          transform: translateX(-100%);\n        `}\n\n  ${Opacity} {\n    opacity: 0.6;\n    transition: opacity ${DURATION}ms ${BEZIER.default};\n  }\n\n  ${({ state, ...props }) => transitionStyles[state]?.(props)};\n`;\n\nexport function Transitioner({ children, isLeftToRightTransition, ...props }) {\n  return (\n    <ScheduledTransition\n      {...props}\n      timeout={{\n        enter: DURATION + DELAY,\n        exit: DURATION,\n      }}\n      mountOnEnter\n      unmountOnExit\n    >\n      {(state) => (\n        <Manager\n          state={state}\n          isLeftToRightTransition={isLeftToRightTransition}\n        >\n          <Opacity>{children}</Opacity>\n        </Manager>\n      )}\n    </ScheduledTransition>\n  );\n}\n\nTransitioner.propTypes = {\n  children: PropTypes.node,\n  isLeftToRightTransition: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/toggle/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ToggleButton } from '../../toggleButton';\nimport { noop } from '../../../utils/noop';\n\nfunction Toggle({\n  isOpen = false,\n  popupId = '',\n  onClick = noop,\n  notificationCount = 0,\n}) {\n  return (\n    <ToggleButton\n      aria-owns={popupId}\n      aria-label={\n        notificationCount > 0\n          ? sprintf(\n              /* translators: %s:  number of unread notifications. */\n              _n(\n                'Help Center: %s unread notification',\n                'Help Center: %s unread notifications',\n                notificationCount,\n                'web-stories'\n              ),\n              notificationCount\n            )\n          : __('Help Center', 'web-stories')\n      }\n      onClick={onClick}\n      isOpen={isOpen}\n      label={__('Help', 'web-stories')}\n      MainIcon={Icons.QuestionMarkOutline}\n      notificationCount={notificationCount}\n    />\n  );\n}\n\nToggle.propTypes = {\n  isOpen: PropTypes.bool,\n  popupId: PropTypes.string,\n  onClick: PropTypes.func,\n  notificationCount: PropTypes.number,\n};\n\nexport { Toggle };\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/toggle/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  theme as dsTheme,\n  ThemeGlobals,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Toggle as HelpCenterToggle } from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Help Center',\n  args: {\n    notificationCount: 6,\n  },\n};\n\nconst Bg = styled.div`\n  position: relative;\n  top: 0;\n  left: 0;\n  height: 100vh;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  padding: 50px;\n`;\n\nexport const Toggle = {\n  render: function Render(args) {\n    const [isOpen, setIsOpen] = useState(false);\n    return (\n      <ThemeProvider theme={dsTheme}>\n        <ThemeGlobals.Styles />\n        <Bg>\n          <HelpCenterToggle\n            isOpen={isOpen}\n            onClick={() => setIsOpen((v) => !v)}\n            {...args}\n          />\n        </Bg>\n      </ThemeProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/toggle/test/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n// eslint-disable-next-line import/no-internal-modules -- Importing testUtils is OK.\nimport { renderWithProviders } from '@googleforcreators/design-system/src/testUtils';\n\n/**\n * Internal dependencies\n */\nimport { Toggle } from '..';\n\ndescribe('help center toggle <Toggle />', () => {\n  it('should render', () => {\n    renderWithProviders(<Toggle />);\n\n    const toggle = screen.getByRole('button');\n    expect(toggle).toBeInTheDocument();\n  });\n\n  it('should have proper aria attributes when closed', () => {\n    renderWithProviders(<Toggle />);\n\n    const toggle = screen.getByRole('button');\n    expect(toggle).toHaveAttribute('aria-haspopup');\n  });\n\n  it('should have proper aria attributes when open', () => {\n    const popupId = 'id-for-popup';\n    renderWithProviders(<Toggle isOpen popupId={popupId} />);\n\n    const toggle = screen.getByRole('button');\n    expect(toggle).toHaveAttribute('aria-expanded');\n    expect(toggle).toHaveAttribute('aria-pressed');\n    expect(toggle).toHaveAttribute('aria-owns', popupId);\n  });\n\n  it('should fire onClick event when clicked', () => {\n    const onClickMock = jest.fn();\n    renderWithProviders(<Toggle onClick={onClickMock} />);\n\n    const toggle = screen.getByRole('button');\n    fireEvent.click(toggle);\n    expect(onClickMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/helpCenter/utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { FOCUSABLE_POPUP_CHILDREN_SELECTOR } from '../../app/helpCenter/constants';\n\nexport function forceFocusCompanion() {\n  document.querySelector(FOCUSABLE_POPUP_CHILDREN_SELECTOR)?.focus();\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/hideOnError.tsx",
    "content": "/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { PropsWithChildren } from 'react';\nimport { Component } from '@googleforcreators/react';\n\ninterface HideOnErrorState {\n  error: Error | null;\n}\n\nexport class HideOnError extends Component<PropsWithChildren<unknown>> {\n  state: HideOnErrorState;\n\n  constructor(props: PropsWithChildren<unknown>) {\n    super(props);\n\n    this.state = {\n      error: null,\n    };\n  }\n\n  static getDerivedStateFromError(error: Error) {\n    return { error };\n  }\n\n  render() {\n    const { error } = this.state;\n    if (!error) {\n      return this.props.children;\n    }\n\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/hotlinkModal.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Input } from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useRef, useLayoutEffect } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\nimport useHotlinkModal from './useHotlinkModal';\n\nconst InputWrapper = styled.form`\n  margin: 16px 4px;\n  width: 470px;\n  height: 100px;\n`;\n\nfunction HotlinkModal({\n  isOpen,\n  onClose,\n  onSelect,\n  onError,\n  allowedFileTypes = [],\n  insertText = __('Insert', 'web-stories'),\n  insertingText = __('Inserting…', 'web-stories'),\n  title,\n  canUseProxy = true,\n  requiredImgDimensions = {},\n}) {\n  const inputRef = useRef(null);\n\n  const {\n    action: { onSubmit, onBlur, onChange, onCloseDialog, onInsert },\n    state: { errorMsg, isInserting, link, description, isDisabled },\n  } = useHotlinkModal({\n    allowedFileTypes,\n    onClose,\n    onError,\n    onSelect,\n    canUseProxy,\n    requiredImgDimensions,\n  });\n\n  const primaryText = isInserting ? insertingText : insertText;\n\n  useLayoutEffect(() => {\n    // Wait one tick to ensure the input has been loaded.\n    const timeout = setTimeout(() => {\n      if (isOpen && inputRef.current) {\n        inputRef.current.focus();\n      }\n    });\n    return () => clearTimeout(timeout);\n  }, [isOpen, inputRef]);\n\n  return (\n    <Dialog\n      onClose={onCloseDialog}\n      isOpen={isOpen}\n      title={title}\n      onPrimary={onInsert}\n      primaryText={primaryText}\n      secondaryText={__('Cancel', 'web-stories')}\n      primaryRest={{ disabled: isDisabled }}\n    >\n      <InputWrapper onSubmit={onSubmit}>\n        <Input\n          ref={inputRef}\n          onChange={onChange}\n          value={link}\n          hint={errorMsg || description}\n          hasError={Boolean(errorMsg)}\n          onBlur={onBlur}\n          label={__('URL', 'web-stories')}\n          type=\"url\"\n          required\n        />\n      </InputWrapper>\n    </Dialog>\n  );\n}\n\nHotlinkModal.propTypes = {\n  allowedFileTypes: PropTypes.array,\n  insertText: PropTypes.string,\n  insertingText: PropTypes.string,\n  isOpen: PropTypes.bool.isRequired,\n  onClose: PropTypes.func.isRequired,\n  onError: PropTypes.func,\n  onSelect: PropTypes.func.isRequired,\n  title: PropTypes.string.isRequired,\n  canUseProxy: PropTypes.bool,\n  requiredImgDimensions: PropTypes.shape({\n    width: PropTypes.number,\n    height: PropTypes.number,\n  }),\n};\n\nexport default HotlinkModal;\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './hotlinkModal';\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/stories/hotlinkDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport HotlinkModal from '../hotlinkModal';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Insert Media By Link',\n  component: HotlinkModal,\n  args: {\n    isOpen: true,\n    allowedFileTypes: ['mp3', 'm3a', 'aac', 'wav', 'oga', 'ogg'],\n    title: 'Insert external audio',\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n    onSelect: { action: 'select' },\n    onError: { action: 'error' },\n  },\n};\n\nexport const _default = {\n  render: ({ insertElement, ...args }) => {\n    return <HotlinkModal {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/test/isValidUrlForHotlinking.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { isValidUrlForHotlinking } from '../utils';\n\ndescribe('isValidUrlForHotlinking', () => {\n  it('should accept proper-looking media URL', () => {\n    expect(isValidUrlForHotlinking('https://foo/image.jpeg')).toBeTrue();\n  });\n\n  it('should reject URL without protocol', () => {\n    expect(isValidUrlForHotlinking('foo/image.jpeg')).toBeFalse();\n  });\n\n  it('should reject URL without pathname', () => {\n    expect(isValidUrlForHotlinking('https://foo/')).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/useHotlinkModal.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { withProtocol } from '@googleforcreators/url';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { getImageDimensions } from '@googleforcreators/media';\nimport useCORSProxy from '../../utils/useCORSProxy';\nimport useAPI from '../../app/api/useAPI';\nimport {\n  getHotlinkDescription,\n  isValidUrlForHotlinking,\n  getErrorMessage,\n  CORSMessage,\n  checkImageDimensions,\n} from './utils';\n\nfunction useHotlinkModal({\n  onSelect,\n  onClose,\n  onError,\n  allowedFileTypes,\n  canUseProxy,\n  requiredImgDimensions,\n}) {\n  const [isInserting, setIsInserting] = useState(false);\n  const [link, setLink] = useState('');\n  const [errorMsg, setErrorMsg] = useState(null);\n\n  const {\n    actions: { getHotlinkInfo },\n  } = useAPI();\n\n  const { checkResourceAccess, getProxiedUrl } = useCORSProxy();\n\n  const isDisabled = errorMsg || !link || isInserting;\n  const description = getHotlinkDescription(allowedFileTypes);\n\n  const onBlur = useCallback(() => {\n    if (link?.length > 0) {\n      const newLink = withProtocol(link.trim());\n      setLink(newLink);\n      if (!isValidUrlForHotlinking(newLink)) {\n        setErrorMsg(__('Invalid link.', 'web-stories'));\n      }\n    }\n  }, [link, setErrorMsg, setLink]);\n\n  const onChange = useCallback(\n    ({ target: { value } }) => {\n      // Always set the error to false when changing.\n      if (errorMsg) {\n        setErrorMsg(null);\n      }\n      setLink(value);\n    },\n    [errorMsg, setLink, setErrorMsg]\n  );\n\n  const onCloseDialog = useCallback(() => {\n    onClose();\n    setLink('');\n    setErrorMsg(null);\n    setIsInserting(false);\n  }, [onClose]);\n\n  const onInsert = useCallback(async () => {\n    if (!link) {\n      return;\n    }\n\n    if (!isValidUrlForHotlinking(link)) {\n      setErrorMsg(__('Invalid link.', 'web-stories'));\n      return;\n    }\n\n    setIsInserting(true);\n\n    try {\n      const hotlinkInfo = await getHotlinkInfo(link);\n      if (!allowedFileTypes.includes(hotlinkInfo?.ext)) {\n        setErrorMsg(__('Invalid link.', 'web-stories'));\n        return;\n      }\n\n      const needsProxy = await checkResourceAccess(link);\n\n      if (needsProxy && !canUseProxy) {\n        setErrorMsg(<CORSMessage />);\n        return;\n      }\n\n      if ('image' === hotlinkInfo?.type && requiredImgDimensions) {\n        const proxiedUrl = needsProxy\n          ? getProxiedUrl({ needsProxy }, link)\n          : link;\n\n        const dimensions = await getImageDimensions(proxiedUrl);\n        const errorMessage = checkImageDimensions(\n          dimensions.width,\n          dimensions.height,\n          requiredImgDimensions?.width,\n          requiredImgDimensions?.height\n        );\n        if (errorMessage) {\n          setErrorMsg(errorMessage);\n          return;\n        }\n\n        hotlinkInfo.width = dimensions.width;\n        hotlinkInfo.height = dimensions.height;\n      }\n\n      await onSelect({ link, hotlinkInfo, needsProxy });\n      setLink('');\n      setErrorMsg(null);\n    } catch (err) {\n      if (onError) {\n        onError(err);\n      }\n      setErrorMsg(getErrorMessage(err.code, description));\n    } finally {\n      setIsInserting(false);\n    }\n  }, [\n    link,\n    getHotlinkInfo,\n    allowedFileTypes,\n    checkResourceAccess,\n    canUseProxy,\n    requiredImgDimensions,\n    onSelect,\n    getProxiedUrl,\n    onError,\n    description,\n  ]);\n\n  const onSubmit = useCallback(\n    (evt) => {\n      evt.preventDefault();\n\n      if (!isDisabled) {\n        onInsert();\n      }\n    },\n    [isDisabled, onInsert]\n  );\n\n  return {\n    action: {\n      onChange,\n      onSubmit,\n      onBlur,\n      onCloseDialog,\n      onInsert,\n    },\n    state: {\n      description,\n      isInserting,\n      link,\n      errorMsg,\n      isDisabled,\n    },\n  };\n}\nexport default useHotlinkModal;\n"
  },
  {
    "path": "packages/story-editor/src/components/hotlinkModal/utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  __,\n  sprintf,\n  translateToExclusiveList,\n  TranslateWithMarkup,\n} from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { Link, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Determine whether a URL is valid and acceptable for hotlinking.\n *\n * Validates that a URL has a valid path segment.\n *\n * @param {string} url URL to validate.\n * @return {boolean} Whether the URL is valid for hotlinking.\n */\nexport function isValidUrlForHotlinking(url) {\n  try {\n    const urlObj = new URL(url);\n    return urlObj.pathname !== '/';\n  } catch {\n    return false;\n  }\n}\n\nexport function getErrorMessage(code, description) {\n  switch (code) {\n    case 'rest_invalid_param':\n    case 'rest_invalid_url':\n      return __('Invalid link.', 'web-stories');\n    case 'rest_invalid_ext':\n      return sprintf(\n        /* translators: %s is the description with allowed file extensions. */\n        __('Invalid link. %s', 'web-stories'),\n        description\n      );\n    default:\n      return __(\n        'Media failed to load. Please ensure the link is valid and the site allows linking from external sites.',\n        'web-stories'\n      );\n  }\n}\n\nexport function getHotlinkDescription(allowedFileTypes) {\n  let description = __('No file types are currently supported.', 'web-stories');\n  if (allowedFileTypes.length) {\n    description = sprintf(\n      /* translators: %s is a list of allowed file extensions. */\n      __('You can insert %s.', 'web-stories'),\n      translateToExclusiveList(allowedFileTypes)\n    );\n  }\n\n  return description;\n}\n\nexport function CORSMessage() {\n  const onDocsClick = (evt) => trackClick(evt, 'click_cors_check_docs');\n  const DOCS_URL =\n    'https://wp.stories.google/docs/troubleshooting/common-issues/';\n\n  return (\n    <TranslateWithMarkup\n      mapping={{\n        a: (\n          <Link\n            size={TextSize.Medium}\n            href={DOCS_URL}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            onClick={onDocsClick}\n          />\n        ),\n      }}\n    >\n      {__(\n        'Unable to load media. Make sure CORS is set up correctly for the file. <a>Learn more</a>.',\n        'web-stories'\n      )}\n    </TranslateWithMarkup>\n  );\n}\n\nexport function checkImageDimensions(\n  suppliedWidth,\n  suppliedHeight,\n  requiredWidth,\n  requiredHeight\n) {\n  if (\n    requiredHeight &&\n    requiredHeight !== suppliedHeight &&\n    requiredWidth &&\n    requiredWidth !== suppliedWidth\n  ) {\n    return sprintf(\n      /* translators: 1: image dimensions. 2: required dimensions. */\n      __(\n        'Image dimensions (%1$s) do not match required image dimensions (%2$s).',\n        'web-stories'\n      ),\n      `${suppliedWidth}x${suppliedHeight}px`,\n      `${requiredWidth}x${requiredHeight}px`\n    );\n  }\n  if (requiredHeight && requiredHeight !== suppliedHeight) {\n    return sprintf(\n      /* translators: 1: supplied height. 2: required height. */\n      __(\n        'Image height (%1$s) does not match required image height (%2$s).',\n        'web-stories'\n      ),\n      `${suppliedHeight}px`,\n      `${requiredHeight}px`\n    );\n  }\n  if (requiredWidth && requiredWidth !== suppliedWidth) {\n    return sprintf(\n      /* translators: 1: supplied width. 2: required width. */\n      __(\n        'Image width (%1$s) does not match required image width (%2$s).',\n        'web-stories'\n      ),\n      `${suppliedWidth}px`,\n      `${requiredWidth}px`\n    );\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TOP_MARGIN = 16;\n\nexport const TOGGLE_SHORTCUTS_MENU = 'mod+/';\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/headerShortcut.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Headline, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { header } from './keyboardShortcutList';\nimport ShortcutLabel from './shortcutLabel';\n\nconst List = styled.dl`\n  margin: 24px;\n  display: flex;\n  flex-shrink: 0;\n`;\n\nconst Item = styled.dt`\n  margin: 0 12px 0 0;\n`;\n\nfunction HeaderShortcut(props) {\n  const { label, shortcut } = header;\n\n  return (\n    <List>\n      <Item>\n        <Headline as=\"h2\" size={TextSize.XSmall} {...props}>\n          {label}\n        </Headline>\n      </Item>\n      <ShortcutLabel keys={shortcut} />\n    </List>\n  );\n}\n\nexport default HeaderShortcut;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Icons,\n  useGlobalKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport { useEffect, useFocusOut, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_FOOTER } from '../../constants/zIndex';\nimport { isKeyboardUser } from '../../utils/keyboardOnlyOutline';\nimport Popup from '../secondaryPopup';\nimport { ToggleButton } from '../toggleButton';\nimport DirectionAware from '../directionAware';\nimport ShortcutMenu from './shortcutMenu';\nimport { TOGGLE_SHORTCUTS_MENU } from './constants';\nimport { useKeyboardShortcutsMenu } from './keyboardShortcutsMenuContext';\n\nconst Wrapper = styled.div`\n  z-index: ${Z_INDEX_FOOTER};\n`;\n\nfunction KeyboardShortcutsMenu() {\n  const anchorRef = useRef();\n  const wrapperRef = useRef();\n  const { close, toggle, isOpen } = useKeyboardShortcutsMenu(\n    ({ actions: { close, toggle }, state: { isOpen } }) => ({\n      close,\n      toggle,\n      isOpen,\n    })\n  );\n\n  useEffect(() => {\n    if (isKeyboardUser() && !isOpen) {\n      // When menu closes, return focus to toggle menu button\n      anchorRef?.current?.focus?.();\n    }\n  }, [isOpen]);\n\n  useGlobalKeyDownEffect(TOGGLE_SHORTCUTS_MENU, toggle, [toggle]);\n  useFocusOut(wrapperRef, close, [close]);\n\n  return (\n    <DirectionAware>\n      <Wrapper ref={wrapperRef}>\n        <Popup\n          popupId=\"keyboard_shortcut_menu\"\n          isOpen={isOpen}\n          ariaLabel={__('Keyboard Shortcuts', 'web-stories')}\n        >\n          <ShortcutMenu toggleMenu={toggle} />\n        </Popup>\n\n        <ToggleButton\n          ref={anchorRef}\n          isOpen={isOpen}\n          aria-owns=\"keyboard_shortcut_menu\"\n          onClick={toggle}\n          aria-label={__('Keyboard Shortcuts', 'web-stories')}\n          label={__('Keyboard Shortcuts', 'web-stories')}\n          MainIcon={Icons.Keyboard}\n          shortcut=\"mod+/\"\n        />\n      </Wrapper>\n    </DirectionAware>\n  );\n}\n\nexport default KeyboardShortcutsMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/karma/keyboardShortcuts.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('Keyboard Shortcuts Menu', () => {\n  let fixture;\n  // Delay 100 ms when opening, but 300ms when closing. Even though animations\n  // are disabled, we apparently still need quite a bit of time to makes sure\n  // the dialog is actually gone.\n  const openDelay = 100;\n  const closeDelay = 300;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('CUJ: User can interact with menu using mouse: Click toggle button to open, click close button to close menu', () => {\n    it('should be able to open menu by clicking on keyboard shortcut button', async () => {\n      const { keyboardShortcutsToggle } = fixture.editor.footer;\n\n      // Menu should be closed\n      await expect(\n        fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n      ).toBeNull();\n\n      await fixture.events.click(keyboardShortcutsToggle);\n      await fixture.events.sleep(openDelay);\n\n      await expect(\n        fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n      ).toBeTruthy();\n\n      await fixture.snapshot('shortcuts dialog open');\n    });\n\n    describe('when menu is open', () => {\n      beforeEach(async () => {\n        const { keyboardShortcutsToggle } = fixture.editor.footer;\n\n        await fixture.events.click(keyboardShortcutsToggle);\n      });\n\n      it('should be able to close menu by clicking on close button', async () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        const menu = within(keyboardShortcutsMenu);\n        const closeButton = menu.getByRole('button', {\n          name: /^Close Menu$/,\n        });\n        await fixture.events.click(closeButton);\n        // Give time for menu to close\n        await fixture.events.sleep(closeDelay);\n\n        expect(\n          fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n        ).toBeNull();\n      });\n\n      it('should be able to close menu by clicking outside the menu', async () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        // Click outside menu\n        await fixture.events.mouse.clickOn(keyboardShortcutsMenu, -10, -10);\n        // Give time for menu to close\n        await fixture.events.sleep(closeDelay);\n\n        expect(\n          fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n        ).toBeNull();\n      });\n\n      it('should not close menu when clicking inside the menu', async () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        const menu = within(keyboardShortcutsMenu);\n        const scrollableMenuArea = menu.queryByRole('presentation');\n        // Click inside menu\n        await fixture.events.click(scrollableMenuArea);\n        // Give time for menu to process clicks\n        await fixture.events.sleep(closeDelay);\n\n        // Menu should still be open\n        expect(\n          fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n        ).toBeTruthy();\n      });\n    });\n  });\n\n  describe('CUJ: User can interact with menu using keyboard: Tab to menu, enter to open, esc to close', () => {\n    it('should be able to toggle menu open with Enter key', async () => {\n      const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n\n      // Menu should be closed\n      expect(keyboardShortcutsMenu).toBeNull();\n\n      const { keyboardShortcutsToggle } = fixture.editor.footer;\n\n      await fixture.events.focus(keyboardShortcutsToggle);\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.sleep(openDelay);\n\n      expect(\n        fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n      ).toBeTruthy();\n    });\n\n    describe('when menu is open', () => {\n      beforeEach(async () => {\n        const { keyboardShortcutsToggle } = fixture.editor.footer;\n\n        await fixture.events.focus(keyboardShortcutsToggle);\n        // Tab back and forth to trigger app to think we're a keyboard user\n        await fixture.events.keyboard.press('tab');\n        await fixture.events.keyboard.shortcut('shift+tab');\n        await fixture.events.keyboard.press('Enter');\n        await fixture.events.sleep(openDelay);\n      });\n\n      it('should be able to close open menu using Esc key', async () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        await fixture.events.keyboard.press('Escape');\n        // Give time for menu to close\n        await fixture.events.sleep(closeDelay);\n\n        expect(\n          fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n        ).toBeNull();\n      });\n\n      it('should place focus on close button when menu opens', () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        const menu = within(keyboardShortcutsMenu);\n        const closeButton = menu.getByRole('button', {\n          name: /^Close Menu$/,\n        });\n\n        expect(document.activeElement).toEqual(closeButton);\n      });\n\n      it('should be able to close menu with close button', async () => {\n        const { keyboardShortcutsMenu } = fixture.editor.keyboardShortcuts;\n        expect(keyboardShortcutsMenu).toBeTruthy();\n\n        const menu = within(keyboardShortcutsMenu);\n        const closeButton = menu.getByRole('button', {\n          name: /^Close Menu$/,\n        });\n\n        await fixture.events.focus(closeButton);\n        await fixture.events.keyboard.press('Enter');\n        // Give time for menu to close\n        await fixture.events.sleep(closeDelay);\n\n        expect(\n          fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n        ).toBeNull();\n      });\n    });\n  });\n\n  describe('Keyboard Shortcuts Menu should have no aXe accessibility violations', () => {\n    it('should have no aXe violations with an open menu', async () => {\n      const { keyboardShortcutsToggle } = fixture.editor.footer;\n\n      await fixture.events.click(keyboardShortcutsToggle);\n      await fixture.events.sleep(openDelay);\n\n      await expectAsync(\n        fixture.editor.keyboardShortcuts.keyboardShortcutsMenu\n      ).toHaveNoViolations();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutList.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, TranslateWithMarkup, sprintf } from '@googleforcreators/i18n';\nimport {\n  isPlatformMacOS,\n  prettifyShortcut,\n  Shortcut,\n} from '@googleforcreators/design-system';\n\nconst isMacOS = isPlatformMacOS();\n\nconst LargeKey = (props) => <kbd className=\"large-key\" {...props} />;\n\nconst ShiftKeyWrapper = (props) => {\n  return isMacOS ? <kbd {...props} /> : <LargeKey {...props} />;\n};\n\nconst shortcuts = {\n  header: {\n    label: __('Keyboard Shortcuts', 'web-stories'),\n    shortcut: (\n      <kbd>\n        <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n        <kbd>{'/'}</kbd>\n      </kbd>\n    ),\n  },\n  landmarks: [\n    {\n      label: __('Element', 'web-stories'),\n      shortcut: (\n        <kbd>\n          <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n          <kbd>{prettifyShortcut('alt')}</kbd>\n          <kbd>{'1'}</kbd>\n        </kbd>\n      ),\n    },\n    {\n      label: __('Workspace', 'web-stories'),\n      shortcut: (\n        <kbd>\n          <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n          <kbd>{prettifyShortcut('alt')}</kbd>\n          <kbd>{'2'}</kbd>\n        </kbd>\n      ),\n    },\n    {\n      label: __('Design panels', 'web-stories'),\n      shortcut: (\n        <kbd>\n          <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n          <kbd>{prettifyShortcut('alt')}</kbd>\n          <kbd>{'3'}</kbd>\n        </kbd>\n      ),\n    },\n  ],\n  sections: [\n    {\n      title: __('Basics', 'web-stories'),\n      commands: [\n        {\n          label: __('Undo', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'Z'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Redo', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <ShiftKeyWrapper>{prettifyShortcut('shift')}</ShiftKeyWrapper>\n              <kbd>{'Z'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Save', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'S'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Play / Stop', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{prettifyShortcut('enter')}</kbd>\n            </kbd>\n          ),\n        },\n      ],\n    },\n    {\n      title: __('Text', 'web-stories'),\n      commands: [\n        {\n          label: __('Insert/edit link', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'K'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Bold', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'B'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Italic', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'I'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Underline', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'U'}</kbd>\n            </kbd>\n          ),\n        },\n      ],\n    },\n    {\n      title: __('Element', 'web-stories'),\n      commands: [\n        {\n          label: __('Copy', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'C'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Cut', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'X'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Duplicate', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'D'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Paste', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'V'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Copy Styles', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{prettifyShortcut('alt')}</kbd>\n              <kbd>{'O'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Paste Styles', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{prettifyShortcut('alt')}</kbd>\n              <kbd>{'P'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Select all', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'A'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Select multiple', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  lkbd: <LargeKey />,\n                  shortcut: <Shortcut shortcut=\"shift\" />,\n                }}\n              >\n                {sprintf(\n                  /* translators: %s: Shift key. */\n                  __('<lkbd>%s</lkbd> <span>+ click</span>', 'web-stories'),\n                  prettifyShortcut('shift')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Move forward or back', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  kbd: <kbd />,\n                  lkbd: <LargeKey />,\n                }}\n              >\n                {sprintf(\n                  /* translators: 1: Cmd/Ctrl key. 2: Up key. 3: Down key. */\n                  __(\n                    '<lkbd>%1$s</lkbd> <kbd>%2$s</kbd> <span>or</span> <kbd>%3$s</kbd>',\n                    'web-stories'\n                  ),\n                  prettifyShortcut('mod'),\n                  prettifyShortcut('up'),\n                  prettifyShortcut('down')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Move to front or back', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  kbd: <kbd />,\n                  lkbd: <LargeKey />,\n                }}\n              >\n                {sprintf(\n                  /* translators: 1: Cmd/Ctrl key. 2: Shift key. 3: Up key. 4: Down key. */\n                  __(\n                    '<lkbd>%1$s</lkbd> <lkbd>%2$s</lkbd> <kbd>%3$s</kbd> <span>or</span> <kbd>%4$s</kbd>',\n                    'web-stories'\n                  ),\n                  prettifyShortcut('mod'),\n                  prettifyShortcut('shift'),\n                  prettifyShortcut('up'),\n                  prettifyShortcut('down')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Enter crop/edit mode', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  kbd: <kbd />,\n                }}\n              >\n                {sprintf(\n                  /* translators: %s: Enter key. */\n                  __(\n                    '<kbd>%s</kbd> <span>or double-click</span>',\n                    'web-stories'\n                  ),\n                  prettifyShortcut('enter')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Delete', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('delete')}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          // Not yet implemented\n          disabled: true,\n          label: __('Insert/edit link', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd>{'A'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Disable snapping and drop targeting', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  lkbd: <LargeKey />,\n                }}\n              >\n                {sprintf(\n                  /* translators: %s: Cmd/Ctrl key. */\n                  __('<span>Hold</span> <lkbd>%s</lkbd>', 'web-stories'),\n                  prettifyShortcut('mod')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Access floating toolbar', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('ctrl')}</kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('alt')}</kbd>\n              <kbd>{'P'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Open context menu', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('mod')}</kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('alt')}</kbd>\n              <kbd className=\"large-key\">{prettifyShortcut('shift')}</kbd>\n              <kbd>{'M'}</kbd>\n            </kbd>\n          ),\n        },\n        {\n          label: __('Move element 1px', 'web-stories'),\n          shortcut: (\n            <kbd>\n              <TranslateWithMarkup\n                mapping={{\n                  lkbd: <LargeKey />,\n                  shortcut: <Shortcut shortcut=\"shift\" />,\n                }}\n              >\n                {sprintf(\n                  /* translators: %s: Shift key. */\n                  __(\n                    '<lkbd>%s</lkbd> <span>+ arrow keys</span>',\n                    'web-stories'\n                  ),\n                  prettifyShortcut('shift')\n                )}\n              </TranslateWithMarkup>\n            </kbd>\n          ),\n        },\n      ],\n    },\n  ],\n};\n\nexport const header = shortcuts.header;\nexport const landmarks = shortcuts.landmarks.filter((o) => !o.disabled);\nexport const sections = shortcuts.sections.map((section) => ({\n  ...section,\n  commands: section.commands.filter((o) => !o.disabled),\n}));\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext/context.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../../utils/noop';\nimport type { KeyboardShortcutsMenuContext } from './types';\n\nexport default createContext<KeyboardShortcutsMenuContext>({\n  state: {\n    isOpen: false,\n  },\n  actions: {\n    toggle: noop,\n    close: noop,\n  },\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as KeyboardShortcutsMenuProvider } from './provider';\nexport { useKeyboardShortcutsMenu } from './useKeyboardShortcutsMenu';\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext/provider.tsx",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useMemo, useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport type { PropsWithChildren } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction KeyboardShortcutsMenuProvider({\n  children,\n}: PropsWithChildren<unknown>) {\n  const [isOpen, setIsOpen] = useState(false);\n\n  const toggle = useCallback(\n    (e: KeyboardEvent) => {\n      e.preventDefault();\n      void trackEvent('shortcuts_menu_toggled', {\n        status: isOpen ? 'closed' : 'open',\n      });\n\n      setIsOpen((prevIsOpen) => !prevIsOpen);\n    },\n    [isOpen]\n  );\n\n  const close = useCallback(() => {\n    if (isOpen) {\n      void trackEvent('shortcuts_menu_toggled', {\n        status: 'closed',\n      });\n      setIsOpen(false);\n    }\n  }, [isOpen]);\n\n  const contextValue = useMemo(\n    () => ({\n      state: {\n        isOpen,\n      },\n      actions: {\n        toggle,\n        close,\n      },\n    }),\n    [close, isOpen, toggle]\n  );\n\n  return <Context.Provider value={contextValue}>{children}</Context.Provider>;\n}\n\nexport default KeyboardShortcutsMenuProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext/types.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface KeyboardShortcutsMenuContext {\n  state: {\n    isOpen: boolean;\n  };\n  actions: {\n    toggle: (evt: KeyboardEvent) => void;\n    close: () => void;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext/useKeyboardShortcutsMenu.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useContextSelector, identity } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { KeyboardShortcutsMenuContext } from './types';\n\nexport function useKeyboardShortcutsMenu(): KeyboardShortcutsMenuContext;\nexport function useKeyboardShortcutsMenu<T>(\n  selector: (state: KeyboardShortcutsMenuContext) => T\n): T;\nexport function useKeyboardShortcutsMenu<T>(\n  selector: (\n    state: KeyboardShortcutsMenuContext\n  ) => T | KeyboardShortcutsMenuContext = identity\n) {\n  return useContextSelector(Context, selector);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/landmarkShortcuts.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { landmarks } from './keyboardShortcutList';\nimport ShortcutLabel from './shortcutLabel';\n\nconst LandmarksWrapper = styled.dl`\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  margin: 0;\n  padding: 16px 24px;\n  display: flex;\n  justify-content: space-between;\n  user-select: text;\n`;\n\nconst Landmark = styled.div`\n  display: flex;\n  flex-direction: column;\n`;\n\nconst Label = styled(Text.Span).attrs({\n  size: TextSize.XSmall,\n})`\n  text-align: center;\n  margin-top: 8px;\n  white-space: nowrap;\n  display: inline-block;\n`;\n\nfunction LandmarkShortcuts() {\n  return (\n    <LandmarksWrapper>\n      {landmarks.map(({ label, shortcut }) => (\n        <Landmark key={label}>\n          <ShortcutLabel keys={shortcut} />\n          <dt>\n            <Label>{label}</Label>\n          </dt>\n        </Landmark>\n      ))}\n    </LandmarksWrapper>\n  );\n}\n\nexport default LandmarkShortcuts;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/regularShortcuts.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { sections } from './keyboardShortcutList';\nimport ShortcutMenuSection from './shortcutMenuSection';\n\nconst ContentWrapper = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin: 0 24px 24px;\n\n  * {\n    user-select: text;\n  }\n`;\n\nfunction RegularShortcuts() {\n  return (\n    <ContentWrapper>\n      {sections.map(({ title, commands }) => (\n        <ShortcutMenuSection key={title} title={title} commands={commands} />\n      ))}\n    </ContentWrapper>\n  );\n}\n\nexport default RegularShortcuts;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/shortcutLabel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\nconst Wrapper = styled.dd`\n  display: block;\n  margin: 0;\n\n  kbd {\n    ${themeHelpers.expandTextPreset(\n      ({ paragraph }, { XSmall }) => paragraph[XSmall]\n    )}\n\n    display: flex;\n    justify-content: ${({ alignment }) => alignment};\n    align-items: center;\n    margin: 0;\n    padding: 0;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n    background-color: transparent;\n\n    & > kbd {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      padding: 0 5px;\n      height: 24px;\n      width: 24px;\n      border-radius: ${({ theme }) => theme.borders.radius.medium};\n      border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n      color: ${({ theme }) => theme.colors.fg.primary};\n    }\n\n    & > kbd.large-key {\n      width: auto;\n    }\n\n    kbd + kbd {\n      margin-left: 2px;\n    }\n\n    kbd + span {\n      margin-left: 4px;\n    }\n\n    span + kbd {\n      margin-left: 4px;\n    }\n  }\n`;\n\nfunction ShortCutLabel({ keys, alignment = 'center', ...rest }) {\n  return (\n    <Wrapper alignment={alignment} {...rest}>\n      {keys}\n    </Wrapper>\n  );\n}\n\nShortCutLabel.propTypes = {\n  keys: PropTypes.PropTypes.element,\n  alignment: PropTypes.oneOf(['left', 'center', 'right']),\n};\n\nexport default ShortCutLabel;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/shortcutMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  useEffect,\n  useRef,\n  useLayoutEffect,\n  useState,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  themeHelpers,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ADMIN_TOOLBAR_HEIGHT, HEADER_HEIGHT } from '../../constants';\nimport HeaderShortcut from './headerShortcut';\nimport LandmarkShortcuts from './landmarkShortcuts';\nimport RegularShortcuts from './regularShortcuts';\nimport { TOGGLE_SHORTCUTS_MENU, TOP_MARGIN } from './constants';\nimport { useKeyboardShortcutsMenu } from './keyboardShortcutsMenuContext';\n\nconst BORDER_WIDTH = 1;\nconst Container = styled.div`\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 352px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: ${BORDER_WIDTH}px solid\n    ${({ theme }) => theme.colors.border.defaultNormal};\n`;\n\n// How much less space than the full browser height can the popup occupy?\nconst EXTRA_SPACE =\n  ADMIN_TOOLBAR_HEIGHT + HEADER_HEIGHT + TOP_MARGIN - 2 * BORDER_WIDTH;\nconst FlexContent = styled.div`\n  display: flex;\n  flex-direction: column;\n  max-height: calc(\n    100vh - ${EXTRA_SPACE}px - ${({ bottomOffset }) => bottomOffset}px\n  );\n`;\n\nconst CloseContainer = styled.div`\n  position: absolute;\n  right: 4px;\n  top: 4px;\n`;\n\nconst ScrollableContent = styled.div`\n  overflow: auto;\n  flex-shrink: 1;\n\n  ${themeHelpers.focusableOutlineCSS};\n`;\n\nconst HEADER_ID = `kb-header-${uuidv4()}`;\n\nfunction ShortcutMenu() {\n  const anchorRef = useRef();\n  const containerRef = useRef();\n\n  const { close, toggle, isOpen } = useKeyboardShortcutsMenu(\n    ({ actions, state }) => ({\n      toggle: actions.toggle,\n      close: actions.close,\n      isOpen: state.isOpen,\n    })\n  );\n\n  const [bottomOffset, setBottomOffset] = useState(0);\n  useLayoutEffect(() => {\n    const node = containerRef.current;\n    if (!node) {\n      return undefined;\n    }\n    const calc = () => {\n      // Find node bottom offset from bottom of browser window\n      const nodeRect = node.getBoundingClientRect();\n      const docRect =\n        node.ownerDocument.documentElement.getBoundingClientRect();\n      setBottomOffset(docRect.height - nodeRect.y - nodeRect.height);\n    };\n    // Call it now\n    calc();\n    // Call it in a frame\n    // eslint-disable-next-line @wordpress/react-no-unsafe-timeout -- No need to cancel this one\n    setTimeout(calc);\n    // And call it every time the window resizes\n    window.addEventListener('resize', calc);\n    return () => window.removeEventListener('resize', calc);\n  }, []);\n\n  useEffect(() => {\n    if (isOpen && anchorRef.current) {\n      anchorRef.current.focus();\n    }\n  }, [isOpen]);\n\n  useKeyDownEffect(containerRef, TOGGLE_SHORTCUTS_MENU, toggle, [toggle]);\n\n  useKeyDownEffect(containerRef, 'esc', close);\n\n  return (\n    <Container ref={containerRef}>\n      <CloseContainer>\n        <Button\n          ref={anchorRef}\n          type={ButtonType.Plain}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Circle}\n          onClick={close}\n          aria-label={__('Close Menu', 'web-stories')}\n        >\n          <Icons.Cross />\n        </Button>\n      </CloseContainer>\n\n      <FlexContent bottomOffset={bottomOffset}>\n        <HeaderShortcut id={HEADER_ID} />\n        {/*eslint-disable-next-line styled-components-a11y/no-noninteractive-tabindex -- scrollable content must be scrollable with keyboard */}\n        <ScrollableContent role=\"presentation\" tabIndex={0}>\n          <LandmarkShortcuts />\n          <RegularShortcuts />\n        </ScrollableContent>\n      </FlexContent>\n    </Container>\n  );\n}\n\nexport default ShortcutMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/shortcutMenuSection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { Headline, Text, TextSize } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport ShortcutLabel from './shortcutLabel';\n\nconst Header = styled(Headline).attrs({\n  as: 'h3',\n  size: TextSize.XXSmall,\n})`\n  margin-top: 24px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst List = styled.dl`\n  display: grid;\n  grid-template-columns: 1fr;\n  row-gap: 12px;\n  align-items: center;\n  margin: 12px 0 0;\n`;\n\nconst ListRow = styled.div`\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  grid-template-rows: auto;\n  column-gap: 5px;\n  align-items: center;\n\n  dd {\n    grid-column: 1;\n    grid-row: 1;\n  }\n  dt {\n    grid-column: 2;\n    grid-row: 1;\n  }\n`;\n\nconst Label = styled(Text.Span).attrs({\n  size: TextSize.Small,\n})`\n  display: inline-block;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nfunction ShortcutMenuSection({ title, commands }) {\n  const headerId = `header-${uuidv4()}`;\n  return (\n    <>\n      <Header id={headerId}>{title}</Header>\n      <List title={title}>\n        {commands.map(({ label, shortcut }) => (\n          <ListRow key={label}>\n            <ShortcutLabel keys={shortcut} alignment={'left'} />\n            <dt>\n              <Label>{label}</Label>\n            </dt>\n          </ListRow>\n        ))}\n      </List>\n    </>\n  );\n}\n\nShortcutMenuSection.propTypes = {\n  title: PropTypes.string.isRequired,\n  commands: PropTypes.array.isRequired,\n};\n\nexport default ShortcutMenuSection;\n"
  },
  {
    "path": "packages/story-editor/src/components/keyboardShortcutsMenu/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport ShortcutMenu from '../shortcutMenu';\n\nexport default {\n  title: 'Stories Editor/Components/Keyboard Shortcuts Menu',\n  component: ShortcutMenu,\n};\n\n// Make the menu a little easier to see in isolation on storyBook.\nconst Container = styled.div`\n  width: 800px;\n  height: 100vh;\n  margin: -50px 10px 0;\n`;\nexport const _default = {\n  render: function Render() {\n    return (\n      <Container>\n        <ShortcutMenu />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/layout/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  SnackbarContainer,\n  useSnackbar,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { withOverlay } from '@googleforcreators/moveable';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport Workspace from '../workspace';\nimport { CANVAS_MIN_WIDTH, SIDEBAR_WIDTH } from '../../constants';\nimport { CanvasProvider } from '../../app/canvas';\nimport { HighlightsProvider } from '../../app/highlights';\nimport LayoutProvider from '../../app/layout/layoutProvider';\nimport { ChecklistCheckpointProvider } from '../checklist';\nimport { RightClickMenuProvider } from '../../app/rightClickMenu';\nimport RightClickMenu from '../canvas/rightClickMenu';\nimport SidebarProvider from '../sidebar/sidebarProvider';\nimport { MediaRecordingProvider } from '../mediaRecording';\n\nconst Editor = withOverlay(styled.section.attrs({\n  'aria-label': __('Web Stories Editor', 'web-stories'),\n})`\n  ${themeHelpers.expandTextPreset(\n    ({ paragraph }, { Medium }) => paragraph[Medium]\n  )}\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n\n  position: relative;\n  max-height: 100vh;\n  height: 100%;\n  width: 100%;\n  display: grid;\n  grid:\n    'sidebar   canv          ' 1fr\n    'sidebar   supplementary ' auto /\n    ${SIDEBAR_WIDTH}px\n    minmax(${CANVAS_MIN_WIDTH}px, 1fr);\n`);\n\nfunction Layout({ header, footer = {}, sidebarTabs, children }) {\n  const snackbarState = useSnackbar(\n    ({ removeSnack, currentSnacks, placement }) => ({\n      onRemove: removeSnack,\n      notifications: currentSnacks,\n      placement,\n    })\n  );\n\n  return (\n    <>\n      <LayoutProvider>\n        <ChecklistCheckpointProvider>\n          <HighlightsProvider>\n            <SidebarProvider sidebarTabs={sidebarTabs}>\n              <Editor zIndex={3}>\n                <CanvasProvider>\n                  <RightClickMenuProvider>\n                    <MediaRecordingProvider>\n                      <Workspace header={header} footer={footer} />\n                      <RightClickMenu />\n                    </MediaRecordingProvider>\n                  </RightClickMenuProvider>\n                </CanvasProvider>\n                {children}\n              </Editor>\n            </SidebarProvider>\n          </HighlightsProvider>\n        </ChecklistCheckpointProvider>\n      </LayoutProvider>\n      <SnackbarContainer {...snackbarState} />\n    </>\n  );\n}\n\nLayout.propTypes = {\n  children: PropTypes.node,\n  header: PropTypes.node,\n  footer: PropTypes.object,\n  sidebarTabs: PropTypes.object,\n};\n\nexport default Layout;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/common/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Exports\n */\nexport { default as SearchInput } from './searchInput';\nexport { default as Section } from './section';\n\nexport const Title = styled.h3`\n  color: ${({ theme }) => theme.colors.fg.primary};\n  margin: 0;\n  font-size: 19px;\n  line-height: 1.4;\n  flex: 3 0 0;\n  display: flex;\n  align-items: center;\n  padding: 2px 0;\n`;\n\nexport const Header = styled.div`\n  display: flex;\n  margin: 0 0 25px;\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/common/searchInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useState, useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { SearchInput } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../panels/shared/styles';\n\nconst StyledSearchInput = styled(SearchInput)`\n  input {\n    ${focusStyle};\n  }\n`;\n\n/**\n * A Search Input component.\n *\n * @param {Object} obj The options for the component.\n * @param {string} obj.initialValue The initial value to populate the input with.\n * @param {string} obj.placeholder A placeholder text to show when it's empty.\n * @param {Function} obj.onSearch Callback to call when a search is triggered.\n * @param {boolean} obj.disabled Whether the input should be shown as disabled.\n * @return {SearchInput} The component.\n * @class\n */\nfunction WrappedSearchInput({\n  initialValue,\n  placeholder,\n  onSearch,\n  disabled = false,\n}) {\n  // Local state so that we can debounce triggering searches.\n  const [localValue, setLocalValue] = useState(initialValue);\n\n  const onChange = useCallback(\n    (evt) => {\n      const newValue = evt.target.value;\n      setLocalValue(newValue);\n      if (newValue === '') {\n        onSearch(newValue);\n      }\n    },\n    [onSearch]\n  );\n\n  const onClear = useCallback(() => {\n    setLocalValue('');\n    onSearch('');\n  }, [onSearch]);\n\n  const onSubmit = useCallback(\n    (evt) => {\n      evt.preventDefault();\n      onSearch(localValue);\n    },\n    [localValue, onSearch]\n  );\n\n  const hasContent = localValue.length > 0;\n\n  return (\n    <form onSubmit={onSubmit}>\n      <StyledSearchInput\n        inputValue={localValue}\n        placeholder={placeholder}\n        onChange={onChange}\n        handleClearInput={onClear}\n        disabled={disabled}\n        ariaClearLabel={__('Clear Search', 'web-stories')}\n        isOpen={hasContent}\n        aria-label={__('Search', 'web-stories')}\n      />\n    </form>\n  );\n}\n\nWrappedSearchInput.propTypes = {\n  initialValue: PropTypes.string.isRequired,\n  placeholder: PropTypes.string.isRequired,\n  onSearch: PropTypes.func.isRequired,\n  disabled: PropTypes.bool,\n};\n\nexport default WrappedSearchInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/common/section.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { Headline, TextSize } from '@googleforcreators/design-system';\n\nexport const Container = styled.div`\n  position: relative;\n  margin-top: 28px;\n  margin-bottom: 28px;\n\n  &:first-child {\n    margin-top: 0px;\n  }\n`;\n\nexport const Title = styled(Headline).attrs({\n  as: 'h2',\n  size: TextSize.XXXSmall,\n})`\n  flex: 1 1 auto;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  margin-bottom: 28px;\n`;\n\nexport default function Section({ title, children, ...rest }) {\n  return (\n    <Container {...rest}>\n      <Title>{title}</Title>\n      {children}\n    </Container>\n  );\n}\n\nSection.propTypes = {\n  title: PropTypes.string.isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/common/test/searchInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { SearchInput } from '..';\n\njest.useFakeTimers();\n\ndescribe('SearchInput', () => {\n  const pressEnter = (node) => fireEvent.submit(node.form);\n  const triggerOnChange = (node) => fireEvent.change(node);\n\n  const setInputValue = (input, value) => {\n    const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n      window.HTMLInputElement.prototype,\n      'value'\n    ).set;\n    nativeInputValueSetter.call(input, value);\n  };\n\n  it('should render <SearchInput /> form', () => {\n    renderWithTheme(\n      <SearchInput\n        initialValue={'dog'}\n        placeholder={'Hello'}\n        onSearch={() => {}}\n      />\n    );\n\n    expect(screen.getByRole('searchbox')).toBeInTheDocument();\n  });\n\n  it('should trigger onSearch when enter is pressed', () => {\n    const onSearchMock = jest.fn();\n\n    renderWithTheme(\n      <SearchInput\n        initialValue={'dog'}\n        placeholder={'Hello'}\n        onSearch={onSearchMock}\n      />\n    );\n\n    const input = screen.getByRole('searchbox');\n    setInputValue(input, 'cat');\n    triggerOnChange(input);\n\n    expect(onSearchMock).not.toHaveBeenCalled();\n\n    pressEnter(input);\n\n    expect(onSearchMock).toHaveBeenCalledOnce();\n  });\n\n  it('should trigger onSearch when text is emptied', () => {\n    const onSearchMock = jest.fn();\n\n    renderWithTheme(\n      <SearchInput\n        initialValue={'d'}\n        placeholder={'Hello'}\n        onSearch={onSearchMock}\n      />\n    );\n\n    const input = screen.getByRole('searchbox');\n    setInputValue(input, '');\n    triggerOnChange(input);\n\n    expect(onSearchMock).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Placement } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { MediaPane, MediaIcon } from './panes/media/local';\nimport { Media3pPane, Media3pIcon } from './panes/media/media3p';\nimport { ShapesPane, ShapesIcon } from './panes/shapes';\nimport { TextPane, TextIcon } from './panes/text';\nimport { PageTemplatesPane, PageTemplatesIcon } from './panes/pageTemplates';\nimport { ShoppingIcon, ShoppingPane } from './panes/shopping';\nimport { PANE_IDS } from './paneIds';\n\nexport const MEDIA = {\n  icon: MediaIcon,\n  tooltip: __('Media', 'web-stories'),\n  placement: Placement.BottomStart,\n  Pane: MediaPane,\n  id: PANE_IDS.Media,\n};\nexport const MEDIA3P = {\n  icon: Media3pIcon,\n  tooltip: __('Third-party media', 'web-stories'),\n  Pane: Media3pPane,\n  id: PANE_IDS.Media3p,\n};\nexport const TEXT = {\n  icon: TextIcon,\n  tooltip: __('Text', 'web-stories'),\n  Pane: TextPane,\n  id: PANE_IDS.Text,\n};\nexport const SHAPES = {\n  icon: ShapesIcon,\n  tooltip: __('Shapes & Stickers', 'web-stories'),\n  Pane: ShapesPane,\n  id: PANE_IDS.Shapes,\n};\nexport const PAGE_TEMPLATES = {\n  icon: PageTemplatesIcon,\n  tooltip: __('Page Templates', 'web-stories'),\n  Pane: PageTemplatesPane,\n  id: PANE_IDS.PageTemplates,\n};\nexport const SHOPPING = {\n  icon: ShoppingIcon,\n  tooltip: __('Shopping', 'web-stories'),\n  Pane: ShoppingPane,\n  id: PANE_IDS.Shopping,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ tabs: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/library/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './library';\nexport * from './constants';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/karma/libraryTabs.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('LibraryTabs integration', () => {\n  let fixture;\n  let libraryLayout;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    libraryLayout = fixture.container.querySelector(\n      '[data-testid=\"libraryLayout\"]'\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('library Tabs should have no aXe accessibility violations', () => {\n    /* eslint-disable-next-line jasmine/no-disabled-tests --\n     * aXe violations\n     * TODO: https://github.com/googleforcreators/web-stories-wp/issues/9954\n     */\n    xit('Local Media Panel should have no aXe violations', async () => {\n      const { mediaTab } = fixture.editor.library;\n      expect(mediaTab).toBeDefined();\n      await fixture.events.click(mediaTab);\n      await expectAsync(mediaTab).toHaveNoViolations();\n      await expectAsync(fixture.editor.library.media).toHaveNoViolations();\n    });\n\n    it('Media 3p Panel should have no aXe violations', async () => {\n      // Set local storage to have accepted third party media terms to avoid interruption with dialog\n      localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P, true);\n      const { media3pTab } = fixture.editor.library;\n      expect(media3pTab).toBeDefined();\n      // navigate to third party media panel\n      await fixture.events.click(media3pTab);\n      // check tab for violations\n      await expectAsync(media3pTab).toHaveNoViolations();\n      // check panel node for violations\n      await expectAsync(\n        fixture.editor.library.media3p.node\n      ).toHaveNoViolations();\n    });\n\n    it('Text Panel should have no aXe violations', async () => {\n      const { textTab } = fixture.editor.library;\n      expect(textTab).toBeDefined();\n      // navigate to text panel\n      await fixture.events.click(textTab);\n      await expectAsync(textTab).toHaveNoViolations();\n\n      // check panel for violations\n      await expectAsync(fixture.editor.library.text.node).toHaveNoViolations();\n    });\n\n    it('Shapes Panel should have no aXe violations', async () => {\n      const { shapesTab } = fixture.editor.library;\n      expect(shapesTab).toBeDefined();\n      // navigate to shapes panel\n      await fixture.events.click(shapesTab);\n      // check tab for violations\n      await expectAsync(shapesTab).toHaveNoViolations();\n      // Just grab the shapes library in the shapes pane\n      // there's some issues with clip path id repetition that\n      // are giving false positives to aXe tests in stickers.\n      const shapesLibrary = fixture.container.querySelector(\n        '[data-testid=\"shapes-library-pane\"]'\n      );\n      expect(shapesLibrary).toBeDefined();\n      await expectAsync(shapesLibrary).toHaveNoViolations();\n    });\n\n    it('Page Templates Panel should have no aXe violations', async () => {\n      const { pageTemplatesTab } = fixture.editor.library;\n      expect(pageTemplatesTab).toBeDefined();\n      // navigate to pageTemplates panel\n      await fixture.events.click(pageTemplatesTab);\n      // check tab for violations\n      await expectAsync(pageTemplatesTab).toHaveNoViolations();\n\n      // check pane for violations\n      await expectAsync(\n        fixture.editor.library.pageTemplatesPane.node\n      ).toHaveNoViolations();\n    });\n  });\n\n  describe('keyboard navigation', () => {\n    beforeEach(async () => {\n      localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P, true);\n      const textTab = fixture.container.querySelector('#library-tab-media');\n      await fixture.events.focus(textTab);\n    });\n\n    async function expectActivePaneToBe(paneId) {\n      const expandedPane = libraryLayout.querySelector(\n        '[aria-expanded=\"true\"]'\n      );\n      const expectedPane = fixture.container.querySelector(\n        `#library-pane-${paneId}`\n      );\n      expect(expandedPane).toEqual(expectedPane);\n      await fixture.waitOnScreen(expectedPane);\n    }\n\n    function expectFocusedTabToBe(tabId) {\n      const focusedTab = libraryLayout.querySelector('[role=\"tab\"]:focus');\n      const expectedTab = fixture.container.querySelector(\n        `#library-tab-${tabId}`\n      );\n      expect(focusedTab).toEqual(expectedTab);\n    }\n\n    it('should be on the media tab', async () => {\n      await expectActivePaneToBe('media');\n    });\n\n    it('should focus tabs on navigation keys and change tabs with space/enter', async () => {\n      // When pressing right key from media, expect media3p to have focus but pane unchanged\n      await fixture.events.keyboard.press('ArrowRight');\n      expectFocusedTabToBe('media3p');\n      await expectActivePaneToBe('media');\n\n      // Then press \"enter\" and expect media3p to be active pane\n      await fixture.events.keyboard.press('Enter');\n      await expectActivePaneToBe('media3p');\n\n      // Press \"end\" to move focus to the last tab, \"templates\"\n      await fixture.events.keyboard.press('End');\n      expectFocusedTabToBe('pageTemplates');\n      await expectActivePaneToBe('media3p');\n\n      // Then press \"space\" to make templates active\n      await fixture.events.keyboard.press('Space');\n      await expectActivePaneToBe('pageTemplates');\n\n      // Then press \"left\" to focus shopping tab\n      await fixture.events.keyboard.press('ArrowLeft');\n      expectFocusedTabToBe('shopping');\n      await expectActivePaneToBe('pageTemplates');\n\n      // Then press \"home\" to focus media tab\n      await fixture.events.keyboard.press('Home');\n      expectFocusedTabToBe('media');\n      await expectActivePaneToBe('pageTemplates');\n\n      // Then press \"enter\" and expect media to be active pane\n      await fixture.events.keyboard.press('Enter');\n      await expectActivePaneToBe('media');\n    });\n\n    it('should return focus to current tab when pressing mod+alt+1', async () => {\n      const { textTab } = fixture.editor.library;\n\n      // Click tab\n      await fixture.events.mouse.clickOn(textTab, 5, 5);\n      await waitFor(() => {\n        if (!fixture.editor.library.text) {\n          throw new Error('text tab not ready');\n        }\n        expect(fixture.editor.library.text).toBeTruthy();\n      });\n      expect(textTab).toHaveFocus();\n\n      // Click elsewhere\n      await fixture.events.click(fixture.editor.canvas.header.title);\n      expect(textTab).not.toHaveFocus();\n\n      // Return focus with shortcut\n      await fixture.events.keyboard.shortcut('mod+alt+1');\n      expect(textTab).toHaveFocus();\n      await fixture.snapshot('text tab has focus');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/karma/mediaTab.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app';\n\ndescribe('Library Media Tab', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('CUJ: Creator Can Add Image/Video to Page: Can add media', () => {\n    it('should not add media when dragged out of Page from the library', async () => {\n      const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n      const mediaItem = fixture.editor.library.media.item(0);\n\n      const { width } = mediaItem.getBoundingClientRect();\n\n      await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n        moveRel(mediaItem, 20, 20),\n        down(),\n        moveRel(bgFrame, -width, 0, { steps: 30 }),\n        up(),\n      ]);\n\n      // Only background, no media added.\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n    });\n  });\n\n  describe('CUJ: Creator Can Add Image/Video to Page: Can manage media', () => {\n    it('should open the dropdown menu', async () => {\n      const mediaIndex = 0;\n      const mediaItem = fixture.editor.library.media.item(mediaIndex);\n      // Hover the media\n      await fixture.events.mouse.moveRel(mediaItem, 20, 20, { steps: 2 });\n      const menuButtons = await fixture.screen.findAllByRole('button', {\n        name: 'More',\n      });\n      const moreButton = menuButtons[mediaIndex];\n      await fixture.events.click(moreButton);\n      expect(\n        fixture.screen.getByRole('menuitem', { name: 'Edit meta data' })\n      ).toBeDefined();\n      expect(\n        fixture.screen.getByRole('menuitem', { name: 'Delete from library' })\n      ).toBeDefined();\n    });\n\n    it('should allow setting media as background from the insertion menu', async () => {\n      const mediaIndex = 0;\n      const mediaItem = fixture.editor.library.media.item(mediaIndex);\n      // Hover the media\n      await fixture.events.mouse.moveRel(mediaItem, 20, 20, { steps: 2 });\n      const menuButtons = await fixture.screen.findAllByRole('button', {\n        name: 'Open insertion menu',\n      });\n      const insertionButton = menuButtons[mediaIndex];\n      await fixture.events.click(insertionButton);\n\n      await fixture.events.click(\n        fixture.screen.getByRole('menuitem', { name: 'Add as background' })\n      );\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      const [background] = storyContext.state.selectedElements;\n      expect(background.type).toBe('image');\n      expect(background.resource.src).toMatch(/^http.+\\/blue-marble.jpg$/);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/karma/shapes/shapes.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport STICKERS from '@googleforcreators/stickers';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma/fixture';\n\nconst testStickerType = Object.keys(STICKERS)[0];\n\ndescribe('Shape library integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('add shape via clicking on shape preview', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to shapes tab and click the triangle\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n\n    // Now background + 1 extra element\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n  });\n\n  it('add shape via dragging from shape preview', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to the shapes tab and drag the triangle to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    const triangle = fixture.editor.library.shapes.shape('Triangle');\n    const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(triangle, 10, 10),\n      down(),\n      /* The steps give time for Moveable to react and display a clone to drag */\n      moveRel(bgFrame, 50, 50, { steps: 20 }),\n      up(),\n    ]);\n\n    // Now background + 1 extra element\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n  });\n\n  it('should not add shape dragged out of the page area', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to the shapes tab and drag the triangle to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    const triangle = fixture.editor.library.shapes.shape('Triangle');\n    const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n\n    // Shape is 1/3 of the page's width by default.\n    const { width: pageWidth } = bgFrame.getBoundingClientRect();\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(triangle, 10, 10),\n      down(),\n      /* The steps give time for Moveable to react and display a clone to drag */\n      moveRel(bgFrame, -(pageWidth / 3 + 20), 50, { steps: 20 }),\n      up(),\n    ]);\n\n    // Still only background.\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n  });\n});\n\ndescribe('Sticker library integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('add sticker via clicking on sticker preview', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to shapes tab and click the first sticker\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(\n      fixture.editor.library.shapes.sticker(testStickerType)\n    );\n\n    // Now background + 1 extra element\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n  });\n\n  it('add sticker via keyboard naviation to sticker preview', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to shapes tab and click the first sticker\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    let limit = 0;\n    const stickersTab = fixture.editor.library.shapes.getByTestId(\n      'stickers-library-pane'\n    );\n    while (!stickersTab.contains(document.activeElement) && limit < 10) {\n      // eslint-disable-next-line no-await-in-loop\n      await fixture.events.keyboard.press('tab');\n      limit++;\n    }\n    await fixture.events.keyboard.press('Enter');\n\n    // Now background + 1 extra element\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n  });\n\n  it('add sticker via dragging from sticker preview', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to the shapes tab and drag the first sticker to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    const stickerButton =\n      fixture.editor.library.shapes.sticker(testStickerType);\n    const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(stickerButton, 10, 10),\n      down(),\n      /* The steps give time for Moveable to react and display a clone to drag */\n      moveRel(bgFrame, 50, 50, { steps: 20 }),\n      up(),\n    ]);\n\n    // Now background + 1 extra element\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n  });\n\n  it('should not add sticker dragged out of the page area', async () => {\n    // Only background initially\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n    // Switch to the shapes tab and drag the first sticker to the canvas\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    const stickerButton =\n      fixture.editor.library.shapes.sticker(testStickerType);\n    const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n\n    // Shape is 1/3 of the page's width by default.\n    const { width: pageWidth } = bgFrame.getBoundingClientRect();\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(stickerButton, 10, 10),\n      down(),\n      /* The steps give time for Moveable to react and display a clone to drag */\n      moveRel(bgFrame, -(pageWidth / 3 + 20), 50, { steps: 20 }),\n      up(),\n    ]);\n\n    // Still only background.\n    expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/library.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport LibraryProvider from './libraryProvider';\nimport LibraryLayout from './libraryLayout';\nimport LibraryUploadDropTarget from './libraryUploadDropTarget';\n\nfunction Library() {\n  return (\n    <LibraryProvider>\n      <LibraryUploadDropTarget>\n        <LibraryLayout />\n      </LibraryUploadDropTarget>\n    </LibraryProvider>\n  );\n}\n\nexport default Library;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/libraryLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport TabView from '../tabview';\nimport { states, useHighlights } from '../../app/highlights';\nimport LibraryPanes from './libraryPanes';\nimport useLibrary from './useLibrary';\nimport { getTabId, getPaneId } from './panes/shared';\nimport { MEDIA, MEDIA3P, TEXT, PAGE_TEMPLATES } from './constants';\n\nconst Layout = styled.section.attrs({\n  'aria-label': __('Library', 'web-stories'),\n  'data-testid': 'libraryLayout',\n})`\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  color: ${({ theme }) => theme.colors.fg.primary};\n  max-height: 100%;\n`;\n\n// @todo Verify that L10N works with the translation happening here.\nconst TabsArea = styled.nav.attrs({\n  'aria-label': __('Library tabs', 'web-stories'),\n})``;\n\nconst LibraryPaneContainer = styled.div`\n  height: 100%;\n  min-height: 0;\n`;\n\nfunction LibraryLayout() {\n  const { setTab, tab, tabRefs, tabs } = useLibrary((state) => ({\n    tab: state.state.tab,\n    tabRefs: state.state.tabRefs,\n    setTab: state.actions.setTab,\n    tabs: state.data.tabs,\n  }));\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: {\n      // Note that the distinct key sets e.g. MEDIA.id !== states.MEDIA.\n      [MEDIA.id]: state[states.Media],\n      [MEDIA3P.id]: state[states.Media3p],\n      [TEXT.id]: state[states.TextSet],\n      [PAGE_TEMPLATES.id]: state[states.PageTemplates],\n    },\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onTabChange = useCallback(\n    (id) => {\n      setTab(id);\n      resetHighlight();\n      trackEvent('library_tab_change', {\n        name: id,\n      });\n    },\n    [setTab, resetHighlight]\n  );\n\n  return (\n    <Layout>\n      <TabsArea>\n        <TabView\n          label={__('Element Library Selection', 'web-stories')}\n          tabs={tabs}\n          tabRefs={tabRefs}\n          tab={tab}\n          onTabChange={onTabChange}\n          onTabRefUpdated={(node, tabId) => {\n            const h = highlight[tabId];\n            if (node && h?.focus && h?.showEffect) {\n              node.focus();\n            }\n          }}\n          getTabId={getTabId}\n          getAriaControlsId={getPaneId}\n          shortcut=\"mod+option+1\"\n        />\n      </TabsArea>\n      <LibraryPaneContainer>\n        <LibraryPanes />\n      </LibraryPaneContainer>\n    </Layout>\n  );\n}\n\nexport default LibraryLayout;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/libraryPanes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useHighlights } from '../../app/highlights';\nimport styles from '../../app/highlights/styles';\nimport { useAPI } from '../../app';\nimport useLibrary from './useLibrary';\nimport { Pane, getTabId } from './panes/shared';\nimport {\n  MEDIA,\n  MEDIA3P,\n  SHAPES,\n  TEXT,\n  PAGE_TEMPLATES,\n  SHOPPING,\n} from './constants';\nimport { MediaPane } from './panes/media/local';\nimport { Media3pPane } from './panes/media/media3p';\nimport { ShapesPane } from './panes/shapes';\nimport { TextPane } from './panes/text';\nimport { PageTemplatesPane } from './panes/pageTemplates';\nimport { ShoppingPane } from './panes/shopping';\n\nfunction LibraryPanes() {\n  const { tab, tabs } = useLibrary((state) => ({\n    tab: state.state.tab,\n    tabs: state.data.tabs,\n  }));\n  const {\n    actions: { getMedia },\n  } = useAPI();\n  const showMediaPane = Boolean(getMedia);\n\n  const highlighted = useHighlights(({ ...highlighted }) => highlighted);\n\n  const mediaHighlights = highlighted[MEDIA.id];\n  const media3pHighlights = highlighted[MEDIA3P.id];\n  const textHighlights = highlighted[TEXT.id];\n\n  return tabs.map(({ id }) => {\n    const isActive = id === tab;\n    const paneProps = {\n      key: id,\n      isActive,\n      'aria-labelledby': getTabId(id),\n    };\n\n    if (!isActive) {\n      return <Pane key={id} {...paneProps} />;\n    }\n\n    switch (id) {\n      case MEDIA.id:\n        return showMediaPane ? (\n          <MediaPane\n            key={id}\n            css={mediaHighlights?.showEffect && styles.FLASH}\n            {...paneProps}\n          />\n        ) : null;\n      case MEDIA3P.id:\n        return (\n          <Media3pPane\n            key={id}\n            {...paneProps}\n            css={media3pHighlights?.showEffect && styles.FLASH}\n          />\n        );\n      case SHAPES.id:\n        return <ShapesPane key={id} {...paneProps} />;\n      case TEXT.id:\n        return (\n          <TextPane\n            key={id}\n            css={textHighlights?.showEffect && styles.FLASH}\n            {...paneProps}\n          />\n        );\n      case PAGE_TEMPLATES.id:\n        return <PageTemplatesPane key={id} {...paneProps} />;\n      case SHOPPING.id:\n        return <ShoppingPane key={id} {...paneProps} />;\n      default:\n        return null;\n    }\n  });\n}\n\nexport default LibraryPanes;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/libraryProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useEffect,\n  useRef,\n  useMemo,\n  useState,\n  useCallback,\n} from '@googleforcreators/react';\nimport { getTimeTracker, trackEvent } from '@googleforcreators/tracking';\nimport { loadTextSets } from '@googleforcreators/text-sets';\nimport { uniqueEntriesByKey } from '@googleforcreators/design-system';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useInsertElement, useInsertTextSet } from '../canvas';\nimport { useHighlights } from '../../app/highlights';\nimport { useConfig, useAPI, useStory } from '../../app';\nimport Context from './context';\nimport {\n  MEDIA,\n  MEDIA3P,\n  PAGE_TEMPLATES,\n  SHAPES,\n  TEXT,\n  SHOPPING,\n} from './constants';\n\nconst LIBRARY_TAB_IDS = new Set(\n  [MEDIA, MEDIA3P, PAGE_TEMPLATES, SHAPES, TEXT, SHOPPING].map((tab) => tab.id)\n);\n\nfunction LibraryProvider({ children }) {\n  const { showMedia3p, shoppingProvider, canViewDefaultTemplates } =\n    useConfig();\n  const {\n    actions: { getMedia, getCustomPageTemplates },\n  } = useAPI();\n\n  const { hasProducts } = useStory(({ state: { currentPage } }) => ({\n    hasProducts: currentPage?.elements?.some(\n      ({ type }) => type === ELEMENT_TYPES.PRODUCT\n    ),\n  }));\n\n  const isShoppingEnabled =\n    (shoppingProvider && 'none' !== shoppingProvider) || hasProducts;\n\n  const supportsCustomTemplates = Boolean(getCustomPageTemplates);\n  const showPageTemplates = canViewDefaultTemplates || supportsCustomTemplates;\n\n  const showMedia = Boolean(getMedia); // Do not show media tab if getMedia api callback is not provided.\n  const [textSets, setTextSets] = useState({});\n  const [areTextSetsLoading, setAreTextSetsLoading] = useState({});\n  const [savedTemplates, _setSavedTemplates] = useState(null);\n\n  // The first page of templates to fetch is 1.\n  const [nextTemplatesToFetch, setNextTemplatesToFetch] = useState(1);\n  // If to use smart colors with text and text sets.\n  const [shouldUseSmartColor, setShouldUseSmartColor] = useState(false);\n\n  const setSavedTemplates = useCallback(\n    (t) =>\n      _setSavedTemplates((_savedTemplates) =>\n        uniqueEntriesByKey(\n          typeof t === 'function' ? t(_savedTemplates) : t,\n          'templateId'\n        )\n      ),\n    []\n  );\n\n  const updateSavedTemplate = useCallback((template) => {\n    _setSavedTemplates((_savedTemplates) => {\n      return _savedTemplates.map((t) => {\n        if (t.templateId === template.templateId) {\n          return {\n            ...t,\n            ...template,\n          };\n        }\n        return t;\n      });\n    });\n  }, []);\n\n  const tabs = useMemo(\n    // Order here is important, as it denotes the actual visual order of elements.\n    () =>\n      [\n        showMedia && MEDIA,\n        showMedia3p && MEDIA3P,\n        TEXT,\n        SHAPES,\n        isShoppingEnabled && SHOPPING,\n        showPageTemplates && PAGE_TEMPLATES,\n      ].filter(Boolean),\n    [showMedia3p, showMedia, showPageTemplates, isShoppingEnabled]\n  );\n\n  const [tab, setTab] = useState(tabs[0].id);\n\n  const insertElement = useInsertElement();\n  const { insertTextSet, insertTextSetByOffset } =\n    useInsertTextSet(shouldUseSmartColor);\n\n  const { highlightedTab } = useHighlights(({ section: highlightedTab }) => ({\n    highlightedTab,\n  }));\n\n  useEffect(() => {\n    if (LIBRARY_TAB_IDS.has(highlightedTab)) {\n      setTab(highlightedTab);\n      trackEvent('quick_action_tab_change', {\n        name: highlightedTab,\n      });\n    }\n  }, [highlightedTab]);\n\n  const mediaTabRef = useRef(null);\n  const media3pTabRef = useRef(null);\n  const textTabRef = useRef(null);\n  const shapesTabRef = useRef(null);\n  const pageTemplatesTabRef = useRef(null);\n  const shoppingRef = useRef(null);\n\n  const tabRefs = useMemo(\n    () => ({\n      [MEDIA.id]: mediaTabRef,\n      [MEDIA3P.id]: media3pTabRef,\n      [TEXT.id]: textTabRef,\n      [SHAPES.id]: shapesTabRef,\n      [PAGE_TEMPLATES.id]: pageTemplatesTabRef,\n      [SHOPPING.id]: shoppingRef,\n    }),\n    []\n  );\n\n  const state = useMemo(\n    () => ({\n      state: {\n        areTextSetsLoading,\n        tab,\n        tabRefs,\n        textSets,\n        savedTemplates,\n        nextTemplatesToFetch,\n        shouldUseSmartColor,\n      },\n      actions: {\n        setTab,\n        insertElement,\n        insertTextSet,\n        insertTextSetByOffset,\n        setSavedTemplates,\n        updateSavedTemplate,\n        setNextTemplatesToFetch,\n        setShouldUseSmartColor,\n      },\n      data: {\n        tabs,\n      },\n    }),\n    [\n      areTextSetsLoading,\n      tab,\n      tabRefs,\n      textSets,\n      savedTemplates,\n      insertElement,\n      insertTextSet,\n      insertTextSetByOffset,\n      tabs,\n      nextTemplatesToFetch,\n      setNextTemplatesToFetch,\n      shouldUseSmartColor,\n      setSavedTemplates,\n      updateSavedTemplate,\n    ]\n  );\n  useEffect(() => {\n    let mounted = true;\n\n    async function getTextSets() {\n      const trackTiming = getTimeTracker('load_text_sets');\n      setAreTextSetsLoading(true);\n      const newTextSets = await loadTextSets();\n      trackTiming();\n\n      if (!mounted) {\n        return;\n      }\n\n      setTextSets(newTextSets);\n      setAreTextSetsLoading(false);\n    }\n\n    // if text sets have not been loaded but are needed fetch dynamically imported text sets\n    if (tab === TEXT.id && !Object.keys(textSets).length) {\n      getTextSets();\n    }\n\n    return () => {\n      mounted = false;\n    };\n  }, [tab, textSets]);\n\n  useEffect(() => {\n    // Set tab back to first tab if on shopping and shopping is disabled.\n    if (tab === SHOPPING.id && !isShoppingEnabled) {\n      setTab(tabs[0].id);\n    }\n  }, [isShoppingEnabled, tab, tabs]);\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nLibraryProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default LibraryProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/libraryUploadDropTarget.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { UploadDropTarget, UploadDropTargetMessage } from '../uploadDropTarget';\nimport { useLocalMedia } from '../../app/media';\n\nconst MESSAGE_ID = 'edit-story-library-upload-message';\n\nfunction LibraryUploadDropTarget({ children }) {\n  const { uploadMedia } = useLocalMedia(({ actions: { uploadMedia } }) => ({\n    uploadMedia,\n  }));\n  const onDropHandler = useCallback(\n    (files) => {\n      uploadMedia(files);\n    },\n    [uploadMedia]\n  );\n  return (\n    <UploadDropTarget onDrop={onDropHandler} labelledBy={MESSAGE_ID}>\n      {children}\n      <UploadDropTargetMessage\n        id={MESSAGE_ID}\n        message={__('Upload to media library', 'web-stories')}\n      />\n    </UploadDropTarget>\n  );\n}\n\nLibraryUploadDropTarget.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default LibraryUploadDropTarget;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/paneIds.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum PANE_IDS {\n  Media = 'media',\n  Media3p = 'media3p',\n  Text = 'text',\n  Shapes = 'shapes',\n  Elements = 'elements',\n  PageTemplates = 'pageTemplates',\n  Shopping = 'shopping',\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/common/styles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { PANE_PADDING } from '../shared';\n\n/* Undo the -1.5em set by the Pane */\nexport const FullWidthWrapper = styled.div`\n  margin-left: -${PANE_PADDING};\n  margin-right: -${PANE_PADDING};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/attribution.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { rgba } from 'polished';\nimport { useState } from '@googleforcreators/react';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nconst StyledText = styled(Text.Span)`\n  color: ${({ theme, active }) =>\n    rgba(theme.colors.standard.white, active ? 1.0 : 0.6)};\n`;\n\nconst Link = styled.a`\n  display: block;\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 100%;\n  padding: 8px;\n  background-color: ${({ theme, active }) =>\n    rgba(theme.colors.bg.primary, active ? 0.8 : 0.6)};\n  text-overflow: ellipsis;\n  overflow: hidden;\n  white-space: nowrap;\n  text-decoration: none;\n`;\n\nconst Attribution = ({ author, url }) => {\n  const [active, setActive] = useState(false);\n  const makeActive = () => setActive(true);\n  const makeInactive = () => setActive(false);\n\n  return (\n    <Link\n      title={author}\n      active={active}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n      href={url}\n      target=\"_blank\"\n      rel=\"noreferrer\"\n    >\n      <StyledText size={TextSize.XSmall}>{author}</StyledText>\n    </Link>\n  );\n};\n\nAttribution.propTypes = {\n  author: PropTypes.string.isRequired,\n  url: PropTypes.string.isRequired,\n};\n\nexport default Attribution;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/innerElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { useEffect, useRef, memo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport {\n  getSmallestUrlForWidth,\n  resourceList,\n  ResourcePropTypes,\n} from '@googleforcreators/media';\nimport { Icons, Text, TextSize, noop } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport LibraryMoveable from '../../shared/libraryMoveable';\nimport { useDropTargets } from '../../../../dropTargets';\nimport { ContentType } from '../../../../../app/media';\nimport InsertionOverlay from '../../shared/insertionOverlay';\n\nconst styledTiles = css`\n  width: 100%;\n  cursor: pointer;\n  transition:\n    0.2s transform,\n    0.15s opacity;\n  border-radius: 4px;\n  opacity: 0;\n  object-fit: cover;\n`;\n\nconst Image = styled.img`\n  ${styledTiles}\n`;\n\n// Display the newly uploaded videos without a delay: showWithoutDelay\nconst Video = styled.video`\n  ${styledTiles}\n  ${({ showWithoutDelay }) => (showWithoutDelay ? 'opacity: 1;' : '')}\n`;\n\nconst DurationWrapper = styled.div`\n  position: absolute;\n  bottom: 8px;\n  left: 8px;\n  background: ${({ theme }) => theme.colors.opacity.black64};\n  border-radius: 100px;\n  height: 18px;\n  padding: 0 6px;\n`;\nconst MuteWrapper = styled.div`\n  position: absolute;\n  bottom: 8px;\n  right: 8px;\n  height: 24px;\n  width: 24px;\n  background: ${({ theme }) => theme.colors.opacity.black64};\n  color: ${({ theme }) => theme.colors.fg.primary};\n  border-radius: 100px;\n`;\nconst Duration = styled(Text.Span).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.primary};\n  display: block;\n`;\n\nconst CloneImg = styled.img`\n  opacity: 0;\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n  position: absolute;\n`;\n\nfunction InnerElement({\n  type,\n  src,\n  resource,\n  alt,\n  width,\n  height,\n  onClick,\n  onLoad = noop,\n  showVideoDetail,\n  mediaElementRef,\n  active,\n  isMuted,\n}) {\n  const newVideoPosterRef = useRef(null);\n  // Track if we have already set the dragging resource.\n  const hasSetResourceRef = useRef(null);\n\n  // Note: This `useDropTargets` is purposefully separated from the one below since it\n  // uses a custom function for checking for equality and is meant for `handleDrag` and `handleDrop` only.\n  const { handleDrag, handleDrop } = useDropTargets(\n    ({ state, actions }) => ({\n      handleDrag: actions.handleDrag,\n      handleDrop: actions.handleDrop,\n      dropTargets: state.dropTargets,\n      activeDropTargetId: state.activeDropTargetId,\n    }),\n    (prev, curr) => {\n      // If we're dragging this element, always update the actions.\n      if (hasSetResourceRef.current) {\n        return false;\n        // If we're rendering the first time, init `handleDrag` and `handleDrop`.\n      } else if (hasSetResourceRef.current === null) {\n        hasSetResourceRef.current = false;\n        return false;\n      }\n      // If the drop targets updated meanwhile, also update the actions, otherwise `handleDrag` won't consider those.\n      if (prev?.dropTargets && curr?.dropTargets) {\n        const prevIds = Object.keys(prev.dropTargets);\n        const currentIds = Object.keys(curr.dropTargets);\n        if (prevIds.join() !== currentIds.join()) {\n          return false;\n        }\n      }\n\n      if (prev?.activeDropTargetId !== curr?.activeDropTargetId) {\n        return false;\n      }\n\n      // Otherwise ignore the changes in the actions.\n      return true;\n    }\n  );\n\n  const { setDraggingResource } = useDropTargets(\n    ({ actions: { setDraggingResource } }) => ({\n      setDraggingResource,\n    })\n  );\n\n  useEffect(() => {\n    // assign display poster for videos\n    if (resource.poster) {\n      newVideoPosterRef.current = resource.poster;\n    }\n  }, [resource.poster]);\n\n  const makeMediaVisible = () => {\n    if (mediaElementRef.current) {\n      mediaElementRef.current.style.opacity = 1;\n    }\n    onLoad();\n  };\n\n  let media;\n  const { lengthFormatted, poster, mimeType } = resource;\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  const displayPoster = poster ?? newVideoPosterRef.current;\n  const thumbnailURL = displayPoster\n    ? displayPoster\n    : getSmallestUrlForWidth(width, resource);\n\n  const commonProps = {\n    width,\n    height,\n    alt,\n    crossOrigin: 'anonymous',\n  };\n\n  const commonImageProps = {\n    ...commonProps,\n    onLoad: makeMediaVisible,\n    loading: 'lazy',\n    decoding: 'async',\n    draggable: false,\n  };\n\n  const cloneProps = {\n    ...commonImageProps,\n    onLoad: undefined,\n  };\n\n  const imageProps = {\n    ...commonImageProps,\n    src: thumbnailURL,\n  };\n  const videoProps = {\n    ...commonProps,\n    title: alt,\n    alt: null,\n    loop: type === ContentType.Gif,\n    muted: true,\n    preload: 'metadata',\n    poster: displayPoster,\n    showWithoutDelay: active,\n  };\n\n  if (type === ContentType.Image || type === ContentType.Sticker) {\n    // eslint-disable-next-line styled-components-a11y/alt-text -- False positive.\n    media = <Image key={src} {...imageProps} ref={mediaElementRef} />;\n    cloneProps.src = thumbnailURL;\n  } else if ([ContentType.Video, ContentType.Gif].includes(type)) {\n    media = (\n      <>\n        {poster && !active ? (\n          /* eslint-disable-next-line styled-components-a11y/alt-text -- False positive. */\n          <Image key={src} {...imageProps} ref={mediaElementRef} />\n        ) : (\n          // eslint-disable-next-line jsx-a11y/media-has-caption,styled-components-a11y/media-has-caption -- No captions/tracks because video is muted.\n          <Video key={src} {...videoProps} ref={mediaElementRef}>\n            {type === ContentType.Gif ? (\n              resource.output.src && (\n                <source\n                  src={resource.output.src}\n                  type={resource.output.mimeType}\n                />\n              )\n            ) : (\n              <source\n                src={getSmallestUrlForWidth(width, resource)}\n                type={mimeType}\n              />\n            )}\n          </Video>\n        )}\n        {type === ContentType.Video && showVideoDetail && lengthFormatted && (\n          <DurationWrapper>\n            <Duration>{lengthFormatted}</Duration>\n          </DurationWrapper>\n        )}\n        {type === ContentType.Video && showVideoDetail && isMuted && (\n          <MuteWrapper>\n            <Icons.Muted />\n          </MuteWrapper>\n        )}\n      </>\n    );\n    cloneProps.src = poster;\n  }\n\n  if (!media) {\n    throw new Error('Invalid media element type.');\n  }\n\n  const dragHandler = (event) => {\n    if (!hasSetResourceRef.current) {\n      // Drop-targets handling.\n      resourceList.set(resource.id, {\n        url: thumbnailURL,\n        type: 'cached',\n      });\n      setDraggingResource(resource);\n      hasSetResourceRef.current = true;\n    }\n    handleDrag(resource, event.clientX, event.clientY);\n  };\n\n  const imageURL = type === ContentType.Image ? thumbnailURL : poster;\n\n  return (\n    <>\n      {media}\n      {active && <InsertionOverlay showIcon={false} />}\n      <LibraryMoveable\n        active={active}\n        handleDrag={dragHandler}\n        handleDragEnd={() => {\n          handleDrop(resource);\n          hasSetResourceRef.current = false;\n        }}\n        type={resource.type}\n        elementProps={{ resource }}\n        onClick={onClick(imageURL)}\n        cloneElement={CloneImg}\n        cloneProps={cloneProps}\n      />\n    </>\n  );\n}\n\nInnerElement.propTypes = {\n  type: PropTypes.string.isRequired,\n  src: PropTypes.string.isRequired,\n  resource: ResourcePropTypes.imageResource,\n  alt: PropTypes.string,\n  width: PropTypes.number,\n  height: PropTypes.number,\n  isMuted: PropTypes.bool,\n  onClick: PropTypes.func.isRequired,\n  onLoad: PropTypes.func,\n  showVideoDetail: PropTypes.bool,\n  mediaElementRef: PropTypes.object,\n  active: PropTypes.bool.isRequired,\n};\n\nexport default memo(InnerElement);\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/insertionMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useRef,\n  useMemo,\n  useCallback,\n  useState,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  Icons,\n  Menu,\n  Placement,\n  Popup,\n  useKeyDownEffect,\n  noop,\n} from '@googleforcreators/design-system';\nimport {\n  getSmallestUrlForWidth,\n  ResourcePropTypes,\n} from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport getElementProperties from '../../../../canvas/utils/getElementProperties';\nimport useStory from '../../../../../app/story/useStory';\nimport { ActionButton } from '../../shared';\nimport useRovingTabIndex from '../../../../../utils/useRovingTabIndex';\nimport useFocusCanvas from '../../../../canvas/useFocusCanvas';\n\nconst DropDownContainer = styled.div`\n  margin-top: 10px;\n  min-width: 160px;\n`;\n\nconst MenuContainer = styled.div`\n  z-index: 1;\n`;\n\nconst menuStylesOverride = css`\n  min-width: 160px;\n  margin-top: 0;\n  li {\n    display: block;\n  }\n`;\n\n// This is used for nested roving tab index to detect parent siblings.\nconst BUTTON_NESTING_DEPTH = 3;\nconst MENU_OPTIONS = {\n  INSERT: 'insert',\n  ADD_BACKGROUND: 'addBackground',\n};\n\n/**\n * Get a More icon that displays a dropdown menu on click.\n *\n * @param {Object} props Component props.\n * @param {Object} props.resource Selected media element's resource object.\n * @param {boolean} props.display Whether the more icon should be displayed.\n * @param {Function} props.onInsert Callback for inserting media.\n * @param {number} props.width Media width.\n * @param {number} props.index Element index in the gallery.\n * @param {boolean} props.isLocal If the menu is for local or 3p media.\n * @param {Function} props.setParentActive Sets the parent element active.\n * @param {Function} props.setParentInactive Sets the parent element inactive.\n * @return {null|*} Element or null if should not display the More icon.\n */\nfunction InsertionMenu({\n  resource,\n  display,\n  onInsert,\n  width,\n  index,\n  isLocal = false,\n  setParentActive = noop,\n  setParentInactive = noop,\n}) {\n  const insertButtonRef = useRef();\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n  const onMenuOpen = useCallback((e) => {\n    e.stopPropagation();\n    setIsMenuOpen(true);\n  }, []);\n  const onMenuCancelled = useCallback(() => {\n    // When menu gets closed, we want to focus back on the original button.\n    setIsMenuOpen(false);\n    insertButtonRef.current?.focus();\n    // However, activeness of the parent is also lost then due to blurring, we need to set it active \"manually\".\n    setParentActive();\n  }, [setParentActive]);\n\n  const { currentBackgroundId, combineElements } = useStory((state) => ({\n    currentBackgroundId: state.state.currentPage?.elements?.[0]?.id,\n    combineElements: state.actions.combineElements,\n  }));\n\n  const { type, poster } = resource;\n  const insertLabel = ['image', 'gif'].includes(type)\n    ? __('Insert image', 'web-stories')\n    : __('Insert video', 'web-stories');\n  const groups = [\n    {\n      options: [\n        { label: insertLabel, value: MENU_OPTIONS.INSERT },\n        {\n          label: __('Add as background', 'web-stories'),\n          value: MENU_OPTIONS.ADD_BACKGROUND,\n        },\n      ],\n    },\n  ];\n\n  const handleCurrentValue = (evt, value) => {\n    const thumbnailUrl = poster || getSmallestUrlForWidth(width, resource);\n    const newElement = getElementProperties(resource.type, {\n      resource,\n    });\n    setIsMenuOpen(false);\n    switch (value) {\n      case MENU_OPTIONS.INSERT:\n        onInsert(resource, thumbnailUrl);\n        break;\n      case MENU_OPTIONS.ADD_BACKGROUND:\n        combineElements({\n          firstElement: newElement,\n          secondId: currentBackgroundId,\n        });\n        break;\n      default:\n        break;\n    }\n    // Since the parent is set active when closing a menu, we need to set it inactive here \"manually\".\n    setParentInactive();\n  };\n\n  useRovingTabIndex({ ref: insertButtonRef }, [], BUTTON_NESTING_DEPTH);\n  // In case of 3p media, we tab out of the panel since it's the only button there.\n  const focusCanvas = useFocusCanvas();\n  useKeyDownEffect(isLocal ? null : insertButtonRef, 'tab', focusCanvas, [\n    focusCanvas,\n  ]);\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const buttonId = useMemo(() => `button-${uuidv4()}`, []);\n\n  // Keep icon and menu displayed if menu is open (even if user's mouse leaves the area).\n  return (\n    <MenuContainer>\n      <ActionButton\n        ref={insertButtonRef}\n        onClick={onMenuOpen}\n        aria-label={__('Open insertion menu', 'web-stories')}\n        aria-pressed={isMenuOpen}\n        aria-haspopup\n        aria-expanded={isMenuOpen}\n        aria-owns={isMenuOpen ? listId : null}\n        id={buttonId}\n        $display={display}\n        tabIndex={index === 0 ? 0 : -1}\n      >\n        <Icons.PlusFilledSmall />\n      </ActionButton>\n      {isMenuOpen && (\n        <Popup\n          anchor={insertButtonRef}\n          placement={Placement.BottomStart}\n          isOpen={isMenuOpen}\n        >\n          <DropDownContainer>\n            <Menu\n              parentId={buttonId}\n              listId={listId}\n              handleMenuItemSelect={handleCurrentValue}\n              groups={groups}\n              onDismissMenu={onMenuCancelled}\n              hasMenuRole\n              menuStylesOverride={menuStylesOverride}\n            />\n          </DropDownContainer>\n        </Popup>\n      )}\n    </MenuContainer>\n  );\n}\n\nInsertionMenu.propTypes = {\n  resource: ResourcePropTypes.resource.isRequired,\n  display: PropTypes.bool.isRequired,\n  onInsert: PropTypes.func.isRequired,\n  width: PropTypes.number.isRequired,\n  index: PropTypes.number.isRequired,\n  isLocal: PropTypes.bool,\n  setParentActive: PropTypes.func,\n  setParentInactive: PropTypes.func,\n};\n\nexport default InsertionMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/mediaElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useEffect,\n  useCallback,\n  memo,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport { rgba } from 'polished';\nimport { __ } from '@googleforcreators/i18n';\nimport { LoadingBar } from '@googleforcreators/design-system';\nimport { Blurhash } from 'react-blurhash';\n\n/**\n * Internal dependencies\n */\nimport DropDownMenu from '../local/dropDownMenu';\nimport { ContentType, useLocalMedia } from '../../../../../app/media';\nimport Tooltip from '../../../../tooltip';\nimport { noop } from '../../../../../utils/noop';\nimport { HideOnError } from '../../../../hideOnError';\nimport Attribution from './attribution';\nimport InnerElement from './innerElement';\nimport InsertionMenu from './insertionMenu';\n\nconst AUTOPLAY_PREVIEW_VIDEO_DELAY_MS = 600;\n\nconst Container = styled.div.attrs((props) => ({\n  style: {\n    width: props.width + 'px',\n    height: props.height + 'px',\n    margin: props.margin,\n    backgroundColor: 'transparent',\n    color: 'inherit',\n    border: 'none',\n    padding: 0,\n  },\n}))``;\n\nconst InnerContainer = styled.div`\n  position: relative;\n  display: flex;\n  margin-bottom: 10px;\n  background-color: ${({ theme, $baseColor }) =>\n    $baseColor ? $baseColor : rgba(theme.colors.standard.black, 0.3)};\n`;\n\nconst BlurhashContainer = styled(Blurhash)`\n  position: absolute !important;\n  top: 0;\n  left: 0;\n`;\n\nfunction Element({\n  index,\n  resource,\n  width: requestedWidth,\n  height: requestedHeight,\n  margin,\n  onInsert,\n  providerType,\n  canEditMedia,\n}) {\n  const {\n    id: resourceId,\n    src,\n    type,\n    width: originalWidth,\n    height: originalHeight,\n    alt,\n    isMuted,\n    baseColor,\n    blurHash,\n  } = resource;\n\n  const { isCurrentResourceProcessing, isCurrentResourceUploading } =\n    useLocalMedia(({ state }) => ({\n      isCurrentResourceProcessing: state.isCurrentResourceProcessing,\n      isCurrentResourceUploading: state.isCurrentResourceUploading,\n    }));\n\n  const oRatio =\n    originalWidth && originalHeight ? originalWidth / originalHeight : 1;\n  const width = requestedWidth || requestedHeight / oRatio;\n  const height = requestedHeight || width / oRatio;\n\n  const mediaElementRef = useRef();\n  const [showVideoDetail, setShowVideoDetail] = useState(true);\n  const [active, setActive] = useState(false);\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n  const [isLoaded, setLoaded] = useState(false);\n\n  const makeActive = useCallback(() => setActive(true), []);\n  const makeInactive = useCallback(() => setActive(false), []);\n  const onMenuOpen = useCallback(() => setIsMenuOpen(true), []);\n  const onMenuCancelled = useCallback(() => setIsMenuOpen(false), []);\n  const onMenuSelected = useCallback(() => {\n    setIsMenuOpen(false);\n    setActive(false);\n  }, []);\n\n  const [hoverTimer, setHoverTimer] = useState(null);\n  const activeRef = useRef(active);\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  activeRef.current = active;\n\n  useEffect(() => {\n    if (![ContentType.Video, ContentType.Gif].includes(type)) {\n      return undefined;\n    }\n    const resetHoverTime = () => {\n      if (hoverTimer !== null) {\n        clearTimeout(hoverTimer);\n        setHoverTimer(null);\n      }\n    };\n    if (!isMenuOpen) {\n      if (active) {\n        setShowVideoDetail(false);\n        if (mediaElementRef.current && hoverTimer === null) {\n          const timer = setTimeout(() => {\n            if (activeRef.current && src) {\n              mediaElementRef.current.play().catch(noop);\n            }\n          }, AUTOPLAY_PREVIEW_VIDEO_DELAY_MS);\n          setHoverTimer(timer);\n          // Pointer still in the media element, continue the video.\n        }\n      } else {\n        setShowVideoDetail(true);\n        resetHoverTime();\n        if (mediaElementRef.current && mediaElementRef.current?.pause && src) {\n          // Stop video and reset position.\n          mediaElementRef.current.pause();\n          mediaElementRef.current.currentTime = 0;\n        }\n      }\n    }\n    return resetHoverTime;\n  }, [isMenuOpen, active, type, src, hoverTimer, setHoverTimer, activeRef]);\n\n  const onClick = useCallback(\n    (thumbnailUrl) => () => {\n      onInsert(resource, thumbnailUrl);\n    },\n    [onInsert, resource]\n  );\n\n  const attribution = active &&\n    resource.attribution?.author?.displayName &&\n    resource.attribution?.author?.url && (\n      <Attribution\n        author={resource.attribution.author.displayName}\n        url={resource.attribution.author.url}\n      />\n    );\n\n  const ref = useRef();\n\n  const onLoad = useCallback(() => setLoaded(true), []);\n\n  const isPlaceholder = !isLoaded && !active;\n\n  return (\n    <Container\n      ref={ref}\n      data-testid={`mediaElement-${type}`}\n      data-id={resourceId}\n      className={'mediaElement'}\n      width={width}\n      height={height}\n      margin={margin}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n      tabIndex=\"-1\"\n    >\n      <InnerContainer $baseColor={isPlaceholder && baseColor}>\n        <InnerElement\n          type={type}\n          src={src}\n          mediaElementRef={mediaElementRef}\n          resource={resource}\n          alt={alt}\n          isMuted={isMuted}\n          width={width}\n          height={height}\n          onClick={onClick}\n          onLoad={onLoad}\n          showVideoDetail={showVideoDetail}\n          active={active}\n        />\n        {attribution}\n        {isPlaceholder && blurHash && (\n          <HideOnError>\n            <BlurhashContainer\n              hash={blurHash}\n              width={width}\n              height={height}\n              punch={1}\n            />\n          </HideOnError>\n        )}\n        {(!src ||\n          isCurrentResourceProcessing(resourceId) ||\n          isCurrentResourceUploading(resourceId)) && (\n          <LoadingBar loadingMessage={__('Uploading media…', 'web-stories')} />\n        )}\n        <InsertionMenu\n          resource={resource}\n          display={active}\n          onInsert={onInsert}\n          width={width}\n          index={index}\n          isLocal={providerType === 'local'}\n          setParentActive={makeActive}\n          setParentInactive={makeInactive}\n        />\n        {providerType === 'local' && canEditMedia && (\n          <DropDownMenu\n            resource={resource}\n            display={active}\n            isMenuOpen={isMenuOpen}\n            onMenuOpen={onMenuOpen}\n            onMenuCancelled={onMenuCancelled}\n            onMenuSelected={onMenuSelected}\n            setParentActive={makeActive}\n          />\n        )}\n      </InnerContainer>\n    </Container>\n  );\n}\n\nElement.propTypes = {\n  index: PropTypes.number.isRequired,\n  resource: PropTypes.object,\n  width: PropTypes.number,\n  height: PropTypes.number,\n  margin: PropTypes.string,\n  onInsert: PropTypes.func,\n  providerType: PropTypes.string,\n  canEditMedia: PropTypes.bool,\n};\n\n/**\n * Get a formatted element for different media types.\n *\n * @param {Object} props Component props.\n * @param {number} props.index Index of the media element in the gallery.\n * @param {Object} props.resource Resource object\n * @param {number} props.width Width that element is inserted into editor.\n * @param {number} props.height Height that element is inserted into editor.\n * @param {string?} props.margin The margin in around the element\n * @param {Function} props.onInsert Insertion callback.\n * @param {string} props.providerType Which provider the element is from.\n * @param {boolean} props.canEditMedia Current user can upload media.\n * @return {null|*} Element or null if does not map to video/image.\n */\nfunction MediaElement({\n  providerType = 'local',\n  canEditMedia = false,\n  ...props\n}) {\n  const { isCurrentResourceProcessing, isCurrentResourceUploading } =\n    useLocalMedia(({ state }) => ({\n      isCurrentResourceProcessing: state.isCurrentResourceProcessing,\n      isCurrentResourceUploading: state.isCurrentResourceUploading,\n    }));\n\n  const { id: resourceId } = props.resource;\n\n  if (\n    isCurrentResourceProcessing(resourceId) ||\n    isCurrentResourceUploading(resourceId)\n  ) {\n    return (\n      <Tooltip title={__('Uploading media…', 'web-stories')}>\n        <Element\n          {...props}\n          providerType={providerType}\n          canEditMedia={canEditMedia}\n        />\n      </Tooltip>\n    );\n  }\n\n  return (\n    <Element\n      {...props}\n      providerType={providerType}\n      canEditMedia={canEditMedia}\n    />\n  );\n}\n\nMediaElement.propTypes = {\n  index: PropTypes.number.isRequired,\n  resource: PropTypes.object,\n  width: PropTypes.number,\n  height: PropTypes.number,\n  margin: PropTypes.string,\n  onInsert: PropTypes.func,\n  providerType: PropTypes.string,\n  canEditMedia: PropTypes.bool,\n};\n\nexport default memo(MediaElement);\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/mediaGallery.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport Gallery from 'react-photo-album';\n\n/**\n * Internal dependencies\n */\nimport { SIDEBAR_WIDTH } from '../../../../../constants';\nimport MediaElement from './mediaElement';\nimport { GalleryContainer } from './styles';\n\nconst PHOTO_SPACING = 8;\nconst TARGET_ROW_HEIGHT = 110;\nconst ROW_CONSTRAINTS = { maxPhotos: 2 };\n\n// eslint-disable-next-line react/prop-types -- Negligible here.\nconst ContainerRenderer = ({ children, containerRef }) => {\n  return <GalleryContainer ref={containerRef}>{children}</GalleryContainer>;\n};\n\nconst RowRenderer = ({ children }) => children;\n\n/**\n * @callback InsertionCallback\n * @param {Object} element Inserted element.\n */\n\n/**\n * Displays a gallery of media elements arranged in a row-based format.\n *\n * @param {Object} props Component props.\n * @param {Array.<Object>} props.resources List of resources to display.\n * @param {Array.<Object>} props.uploadingResources List of uploading resources to display.\n * @param {InsertionCallback} props.onInsert Called when element is selected.\n * @param {string} props.providerType Provider of gallery's elements.\n * @param {boolean} props.canEditMedia Current user can upload media.\n * @return {*} The gallery element.\n */\nfunction MediaGallery({\n  resources,\n  uploadingResources = [],\n  onInsert,\n  providerType,\n  canEditMedia = false,\n}) {\n  // Use different key for uploading vs. uploaded items to avoid confusions.\n  const photos = [\n    ...uploadingResources.map((resource) => ({\n      key: `uploading-${resource.id}`,\n      src: resource.src,\n      width: resource.width,\n      height: resource.height,\n      resource,\n    })),\n    ...resources.map((resource) => ({\n      key: resource.id,\n      src: resource.src,\n      width: resource.width,\n      height: resource.height,\n      resource,\n    })),\n  ].map((photo, index) => ({\n    ...photo,\n    index,\n  }));\n\n  const imageRenderer = useCallback(\n    ({ photo, layout }) => {\n      return (\n        <MediaElement\n          key={photo.key}\n          index={photo.index}\n          margin={`0px 0px ${PHOTO_SPACING}px 0px`}\n          resource={photo.resource}\n          width={layout.width}\n          height={layout.height}\n          onInsert={onInsert}\n          providerType={providerType}\n          canEditMedia={canEditMedia}\n        />\n      );\n    },\n    [providerType, onInsert, canEditMedia]\n  );\n\n  return (\n    <div>\n      <Gallery\n        layout=\"rows\"\n        photos={photos}\n        renderPhoto={imageRenderer}\n        renderRowContainer={RowRenderer}\n        renderContainer={ContainerRenderer}\n        targetRowHeight={TARGET_ROW_HEIGHT}\n        rowConstraints={ROW_CONSTRAINTS}\n        spacing={PHOTO_SPACING}\n        // Used for tests / SSR.\n        defaultContainerWidth={SIDEBAR_WIDTH}\n      />\n    </div>\n  );\n}\n\nMediaGallery.propTypes = {\n  resources: PropTypes.arrayOf(PropTypes.object).isRequired,\n  uploadingResources: PropTypes.arrayOf(PropTypes.object),\n  onInsert: PropTypes.func.isRequired,\n  providerType: PropTypes.string.isRequired,\n  canEditMedia: PropTypes.bool,\n};\nexport default MediaGallery;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useState,\n  useDebouncedCallback,\n  Suspense,\n  lazy,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { PROVIDERS } from '../../../../../app/media/media3p/providerConfiguration';\nimport { noop } from '../../../../../utils/noop';\nimport {\n  MediaGalleryContainer,\n  MediaGalleryInnerContainer,\n  MediaGalleryLoadingPill,\n  MediaGalleryMessage,\n} from './styles';\n\nconst ROOT_MARGIN = 300;\n\nconst SHOW_LOADING_PILL_DELAY_MS = 1000;\n\nconst StyledText = styled(Text.Span)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst MediaGallery = lazy(\n  () => import(/* webpackChunkName: \"chunk-media-gallery\" */ './mediaGallery')\n);\n\nfunction LazyMediaGallery({\n  providerType,\n  canEditMedia,\n  resources,\n  uploadingResources,\n  onInsert,\n}) {\n  return (\n    <Suspense\n      fallback={\n        <MediaGalleryLoadingPill>\n          <StyledText size={TextSize.Small}>\n            {__('Loading…', 'web-stories')}\n          </StyledText>\n        </MediaGalleryLoadingPill>\n      }\n    >\n      <MediaGallery\n        providerType={providerType}\n        canEditMedia={canEditMedia}\n        resources={resources}\n        uploadingResources={uploadingResources}\n        onInsert={onInsert}\n      />\n    </Suspense>\n  );\n}\n\nLazyMediaGallery.propTypes = {\n  providerType: PropTypes.string.isRequired,\n  canEditMedia: PropTypes.bool,\n  resources: PropTypes.arrayOf(PropTypes.object).isRequired,\n  uploadingResources: PropTypes.arrayOf(PropTypes.object),\n  onInsert: PropTypes.func.isRequired,\n};\n\nfunction PaginatedMediaGallery({\n  providerType,\n  resources,\n  uploadingResources = [],\n  searchTerm,\n  selectedCategoryId,\n  isMediaLoading,\n  isMediaLoaded,\n  hasMore,\n  onInsert,\n  setNextPage,\n  canEditMedia = false,\n}) {\n  // State and callback ref necessary to load on scroll.\n  const refContainer = useRef();\n\n  const isNextPageNeeded = useCallback(() => {\n    // Load the next page if the container still isn't full, i.e. scrollbar is not visible.\n    if (\n      refContainer.current?.clientHeight === refContainer.current?.scrollHeight\n    ) {\n      return setNextPage();\n    }\n    return noop;\n  }, [setNextPage]);\n\n  const debouncedSetNextPage = useDebouncedCallback(isNextPageNeeded, 500);\n\n  const loadNextPageIfNeeded = useCallback(() => {\n    const node = refContainer.current;\n    if (\n      !resources.length ||\n      !node ||\n      // This condition happens when the component is hidden, and causes the\n      // calculation below to load a new page in error.\n      node.clientHeight === 0 ||\n      !hasMore ||\n      !isMediaLoaded ||\n      isMediaLoading\n    ) {\n      return;\n    }\n\n    // When the node.scrollHeight is first calculated it may not be accurate\n    // depending on if the elements have fully render on the page. If the container\n    // height and scroll height are the same, debounce the call to allow time\n    // for the elements to paint before making an additional setNextPage call.\n    if (node.clientHeight === node.scrollHeight) {\n      debouncedSetNextPage();\n      return;\n    }\n\n    // Load the next page if we are \"close\" (by a length of ROOT_MARGIN) to the\n    // bottom of the container.\n    const bottom =\n      node.scrollHeight - node.scrollTop <= node.clientHeight + ROOT_MARGIN;\n    if (bottom) {\n      setNextPage();\n    }\n  }, [\n    resources.length,\n    hasMore,\n    isMediaLoaded,\n    isMediaLoading,\n    debouncedSetNextPage,\n    setNextPage,\n  ]);\n\n  // Scroll to the top when the searchTerm or selected category changes.\n  useEffect(() => {\n    refContainer.current?.scrollTo?.(0, 0);\n  }, [searchTerm, selectedCategoryId]);\n\n  // After scroll or resize, see if we need the load the next page.\n  const handleScrollOrResize = useDebouncedCallback(loadNextPageIfNeeded, 500);\n\n  // After loading a next page, see if we need to load another,\n  // i.e. when the page of results isn't full.\n  useLayoutEffect(() => {\n    async function loadNextPageIfNeededAfterGalleryRendering() {\n      // Wait for <Gallery> to finish its render layout cycles first.\n      await sleep(200);\n\n      loadNextPageIfNeeded();\n    }\n    loadNextPageIfNeededAfterGalleryRendering();\n  }, [loadNextPageIfNeeded]);\n\n  useEffect(() => {\n    const node = refContainer.current;\n    if (!node) {\n      return undefined;\n    }\n\n    // When the user scrolls or resizes (debounced).\n    node.addEventListener('scroll', handleScrollOrResize);\n    window.addEventListener('resize', handleScrollOrResize);\n    return () => {\n      node.removeEventListener('scroll', handleScrollOrResize);\n      window.removeEventListener('resize', handleScrollOrResize);\n    };\n  }, [handleScrollOrResize]);\n\n  const [showLoadingPill, setShowLoadingPill] = useState(false);\n\n  useEffect(() => {\n    if (isMediaLoading && hasMore) {\n      const showLoadingTimeout = setTimeout(() => {\n        setShowLoadingPill(isMediaLoading);\n      }, SHOW_LOADING_PILL_DELAY_MS);\n      return () => clearTimeout(showLoadingTimeout);\n    }\n    setShowLoadingPill(false);\n    return undefined;\n  }, [isMediaLoading, hasMore]);\n\n  const Attribution =\n    (providerType !== 'local' &&\n      PROVIDERS[providerType].attributionComponent) ||\n    null;\n\n  return (\n    <>\n      <MediaGalleryContainer\n        data-testid=\"media-gallery-container\"\n        ref={refContainer}\n      >\n        <MediaGalleryInnerContainer>\n          {isMediaLoaded && !resources.length && !uploadingResources.length ? (\n            <MediaGalleryMessage>\n              {__('No media found.', 'web-stories')}\n            </MediaGalleryMessage>\n          ) : (\n            <div style={{ marginBottom: 15 }}>\n              <LazyMediaGallery\n                providerType={providerType}\n                canEditMedia={canEditMedia}\n                resources={resources}\n                uploadingResources={uploadingResources}\n                onInsert={onInsert}\n              />\n            </div>\n          )}\n        </MediaGalleryInnerContainer>\n      </MediaGalleryContainer>\n      {showLoadingPill && (\n        <MediaGalleryLoadingPill data-testid={'loading-pill'}>\n          <StyledText size={TextSize.Small}>\n            {__('Loading…', 'web-stories')}\n          </StyledText>\n        </MediaGalleryLoadingPill>\n      )}\n      {!showLoadingPill && Attribution && <Attribution />}\n    </>\n  );\n}\n\nPaginatedMediaGallery.propTypes = {\n  providerType: PropTypes.string.isRequired,\n  resources: PropTypes.arrayOf(PropTypes.object).isRequired,\n  uploadingResources: PropTypes.arrayOf(PropTypes.object),\n  isMediaLoading: PropTypes.bool.isRequired,\n  isMediaLoaded: PropTypes.bool.isRequired,\n  hasMore: PropTypes.bool.isRequired,\n  onInsert: PropTypes.func.isRequired,\n  setNextPage: PropTypes.func.isRequired,\n  searchTerm: PropTypes.string,\n  selectedCategoryId: PropTypes.string,\n  canEditMedia: PropTypes.bool,\n};\n\nexport default PaginatedMediaGallery;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/stories/mediaElement.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { SnackbarContext } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport MediaElement from '../mediaElement';\nimport { CanvasProvider } from '../../../../../../app/canvas';\nimport ApiContext from '../../../../../../app/api/context';\nimport MediaContext from '../../../../../../app/media/context';\nimport testImage from '../../local/stories/test-image.jpg';\nimport testPoster from './test-poster.png';\nimport testVideo from './test-video.mp4';\n\nconst Column = styled.div`\n  width: 150px;\n`;\n\nexport default {\n  title: 'Stories Editor/Components/Media Element',\n  component: MediaElement,\n  args: {\n    resource: {\n      id: 123,\n      type: 'image',\n      mimeType: 'image/png',\n      creationDate: '2019-11-13T18:15:52Z',\n      src: testImage,\n      width: 910,\n      height: 675,\n      alt: 'my image',\n      sizes: {},\n    },\n  },\n  argTypes: {\n    onInsert: { action: 'insert into canvas' },\n    showSnackbar: { action: 'show snackbar' },\n    deleteMediaElement: { action: 'delete from state' },\n    updateMediaElement: { action: 'update  state' },\n    deleteMedia: { action: 'delete from server' },\n    updateMedia: { action: 'update  server' },\n    isCurrentResourceProcessing: { action: 'false' },\n    isCurrentResourceUploading: { action: 'false' },\n  },\n  parameters: {\n    controls: {\n      exclude: [\n        'providerType',\n        'canEditMedia',\n        'index',\n        'width',\n        'height',\n        'margin',\n      ],\n    },\n  },\n};\n\nexport const _Image = {\n  render: function Render(args) {\n    const resource = args.resource;\n    const snackbarValue = { showSnackbar: args.showSnackbar };\n    const mediaValue = {\n      local: {\n        actions: {\n          deleteMediaElement: args.deleteMediaElement,\n          updateMediaElement: args.updateMediaElement,\n        },\n        state: {\n          isCurrentResourceProcessing: args.isCurrentResourceProcessing,\n          isCurrentResourceUploading: args.isCurrentResourceUploading,\n        },\n      },\n    };\n    const apiValue = {\n      actions: {\n        deleteMedia: args.deleteMedia,\n        updateMedia: args.updateMedia,\n      },\n    };\n\n    return (\n      <SnackbarContext.Provider value={snackbarValue}>\n        <MediaContext.Provider value={mediaValue}>\n          <ApiContext.Provider value={apiValue}>\n            <CanvasProvider>\n              <Column>\n                <MediaElement\n                  index={0}\n                  resource={resource}\n                  width={150}\n                  onInsert={args.onInsert}\n                />\n              </Column>\n            </CanvasProvider>\n          </ApiContext.Provider>\n        </MediaContext.Provider>\n      </SnackbarContext.Provider>\n    );\n  },\n};\n\nexport const _Image_With_Attribution = {\n  render: _Image,\n\n  args: {\n    resource: {\n      id: 123,\n      type: 'image',\n      mimeType: 'image/png',\n      creationDate: '2019-11-13T18:15:52Z',\n      src: testImage,\n      width: 910,\n      height: 675,\n      alt: 'my image',\n      sizes: {},\n      attribution: {\n        author: {\n          displayName: 'Some Author',\n          url: 'http://www.google.com',\n        },\n      },\n    },\n  },\n};\n\nexport const _Video = {\n  render: _Image,\n\n  args: {\n    resource: {\n      id: 456,\n      type: 'video',\n      mimeType: 'video/mp4',\n      title: 'My Video :)',\n      creationDate: '2019-11-13T18:15:52Z',\n      src: testVideo,\n      width: 640,\n      height: 480,\n      poster: testPoster,\n      lengthFormatted: '0:26',\n      alt: 'my video',\n      sizes: {},\n    },\n  },\n};\n\nexport const _Video_With_Attribution = {\n  render: _Image,\n\n  args: {\n    resource: {\n      id: 456,\n      type: 'video',\n      mimeType: 'video/mp4',\n      title: 'My Video :)',\n      creationDate: '2019-11-13T18:15:52Z',\n      src: testVideo,\n      width: 640,\n      height: 480,\n      poster: testPoster,\n      lengthFormatted: '0:26',\n      alt: 'my video',\n      sizes: {},\n      attribution: {\n        author: {\n          displayName: 'Some Author',\n          url: 'http://www.google.com',\n        },\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/stories/mediaGallery.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport MediaGallery from '../mediaGallery';\nimport { CanvasProvider } from '../../../../../../app/canvas';\nimport { LayoutProvider } from '../../../../../../app/layout';\nimport { noop } from '../../../../../../utils/noop';\n\nimport MediaContext from '../../../../../../app/media/context';\n\nexport default {\n  title: 'Stories Editor/Components/Media Gallery',\n  component: MediaGallery,\n  argTypes: {\n    onInsert: { action: 'selected' },\n  },\n};\n\nconst resources = [\n  {\n    id: 1,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 18,\n    height: 12,\n    src: 'https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/slideshows/how_to_brush_dogs_teeth_slideshow/1800x1200_how_to_brush_dogs_teeth_slideshow.jpg',\n  },\n  {\n    id: 2,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 128,\n    height: 72,\n    src: 'https://www.sciencemag.org/sites/default/files/styles/article_main_large/public/dogs_1280p_0.jpg?itok=cnRk0HYq',\n  },\n  {\n    id: 3,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 110,\n    height: 62,\n    src: 'https://post.medicalnewstoday.com/wp-content/uploads/sites/3/2020/02/322868_1100-1100x628.jpg',\n  },\n  {\n    id: 4,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 79,\n    height: 59,\n    src: 'https://www.abc.net.au/cm/rimage/11779952-4x3-xlarge.jpg?v=3',\n  },\n  {\n    id: 5,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 18,\n    height: 12,\n    src: 'https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/slideshows/how_to_brush_dogs_teeth_slideshow/1800x1200_how_to_brush_dogs_teeth_slideshow.jpg',\n  },\n  {\n    id: 6,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 218,\n    height: 278,\n    src: 'https://i0.wp.com/rollinsps.vic.edu.au/wp-content/uploads/2018/11/IMG_0451.jpg',\n  },\n  {\n    id: 7,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 1100,\n    height: 825,\n    src: 'https://i.insider.com/5d2e0e30a17d6c5cfd30be94?width=1100&format=jpeg&auto=webp',\n  },\n  {\n    id: 8,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 591,\n    height: 555,\n    src: 'https://www.dogsnsw.org.au/media/1007/breeding-dogs.jpg',\n  },\n  {\n    id: 9,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 640,\n    height: 635,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/golden-retriever-royalty-free-image-506756303-1560962726.jpg?crop=0.672xw:1.00xh;0.166xw,0&resize=640:*',\n  },\n  {\n    id: 10,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 1100,\n    height: 825,\n    src: 'https://i.insider.com/5d2e0e30a17d6c5cfd30be94?width=1100&format=jpeg&auto=webp',\n  },\n  {\n    id: 11,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 18,\n    height: 12,\n    src: 'https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/slideshows/how_to_brush_dogs_teeth_slideshow/1800x1200_how_to_brush_dogs_teeth_slideshow.jpg',\n  },\n  {\n    id: 12,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 320,\n    height: 400,\n    src: 'https://upload.wikimedia.org/wikipedia/commons/9/9a/Declassified_image_of_Conan%2C_the_dog_who_chased_al-Baghdadi.jpg',\n  },\n  {\n    id: 13,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 1100,\n    height: 825,\n    src: 'https://i.insider.com/5d2e0e30a17d6c5cfd30be94?width=1100&format=jpeg&auto=webp',\n  },\n  {\n    id: 14,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 480,\n    height: 720,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/bernese-mountain-dog-royalty-free-image-1581013857.jpg?crop=0.87845xw:1xh;center,top&resize=480:*',\n  },\n  {\n    id: 15,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 640,\n    height: 640,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/smartest-dog-breeds-lead-1587757081.jpg?crop=1.00xw:1.00xh;0,0&resize=640:*',\n  },\n  {\n    id: 16,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 320,\n    height: 400,\n    src: 'https://upload.wikimedia.org/wikipedia/commons/9/9a/Declassified_image_of_Conan%2C_the_dog_who_chased_al-Baghdadi.jpg',\n  },\n  {\n    id: 17,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 591,\n    height: 555,\n    src: 'https://www.dogsnsw.org.au/media/1007/breeding-dogs.jpg',\n  },\n  {\n    id: 18,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 640,\n    height: 635,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/golden-retriever-royalty-free-image-506756303-1560962726.jpg?crop=0.672xw:1.00xh;0.166xw,0&resize=640:*',\n  },\n  {\n    id: 19,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 1100,\n    height: 825,\n    src: 'https://i.insider.com/5d2e0e30a17d6c5cfd30be94?width=1100&format=jpeg&auto=webp',\n  },\n  {\n    id: 20,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 18,\n    height: 12,\n    src: 'https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/slideshows/how_to_brush_dogs_teeth_slideshow/1800x1200_how_to_brush_dogs_teeth_slideshow.jpg',\n  },\n  {\n    id: 21,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 320,\n    height: 400,\n    src: 'https://upload.wikimedia.org/wikipedia/commons/9/9a/Declassified_image_of_Conan%2C_the_dog_who_chased_al-Baghdadi.jpg',\n  },\n  {\n    id: 22,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 1100,\n    height: 825,\n    src: 'https://i.insider.com/5d2e0e30a17d6c5cfd30be94?width=1100&format=jpeg&auto=webp',\n  },\n  {\n    id: 23,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 480,\n    height: 720,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/bernese-mountain-dog-royalty-free-image-1581013857.jpg?crop=0.87845xw:1xh;center,top&resize=480:*',\n  },\n  {\n    id: 24,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 640,\n    height: 640,\n    src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/smartest-dog-breeds-lead-1587757081.jpg?crop=1.00xw:1.00xh;0,0&resize=640:*',\n  },\n  {\n    id: 25,\n    type: 'image',\n    alt: 'image alt',\n    mimeType: 'image/jpeg',\n    baseColor: '#ffffff',\n    width: 320,\n    height: 400,\n    src: 'https://upload.wikimedia.org/wikipedia/commons/9/9a/Declassified_image_of_Conan%2C_the_dog_who_chased_al-Baghdadi.jpg',\n  },\n];\n\nconst Container = styled.div`\n  width: 300px;\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const mediaValue = {\n      local: {\n        state: {\n          isCurrentResourceProcessing: () => false,\n          isCurrentResourceUploading: () => false,\n        },\n        actions: {\n          uploadMedia: noop,\n        },\n      },\n    };\n\n    return (\n      <Container>\n        <MediaContext.Provider value={mediaValue}>\n          <LayoutProvider>\n            <CanvasProvider>\n              <MediaGallery\n                resources={resources}\n                providerType={'unsplash'}\n                {...args}\n              />\n            </CanvasProvider>\n          </LayoutProvider>\n        </MediaContext.Provider>\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/styles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Pane, PANE_PADDING } from '../../shared';\n\nexport const PaneInner = styled.div`\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n`;\nexport const PaneHeader = styled.div`\n  padding-top: 24px;\n  flex: 0 1 auto;\n`;\n\nexport const GalleryContainer = styled.div`\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  justify-content: space-between;\n`;\n\nexport const MediaGalleryContainer = styled.div`\n  overflow-y: scroll;\n  overflow-x: hidden;\n  padding: 0 ${PANE_PADDING};\n  margin-top: 1em;\n  position: relative;\n  width: 100%;\n  flex: 1 1 auto;\n  min-height: 100px;\n`;\n\n// Exceeding the parent's width here so the media items\n// better align with the upload buttons and scroll bar.\nexport const MediaGalleryInnerContainer = styled.div`\n  width: calc(100% + ${TextSize.SCROLLBAR_WIDTH}px);\n`;\n\nexport const MediaGalleryLoadingPill = styled.div`\n  display: block;\n  position: absolute;\n  bottom: 20px;\n  left: 60px;\n  right: 60px;\n  width: 240px;\n  text-align: center;\n  padding: 8px 80px;\n  background-color: ${({ theme }) => rgba(theme.colors.standard.black, 0.4)};\n  border-radius: 100px;\n`;\n\nexport const MediaGalleryMessage = styled(Text.Paragraph).attrs({\n  size: TextSize.Medium,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  padding: 1em;\n  text-align: center;\n`;\n\nexport const StyledPane = styled(Pane)`\n  height: 100%;\n  padding: 0;\n  overflow: hidden;\n`;\n\nexport const SearchInputContainer = styled.div`\n  padding: 0 ${PANE_PADDING};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/test/accessibility.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useCanvasBoundingBox } from '../../../../../../app';\nimport Attribution from '../attribution';\nimport MediaElement from '../mediaElement';\nimport { useLocalMedia } from '../../../../../../app/media';\n\njest.mock('../../../../../../app/media');\n\njest.mock('../../../../../../app/canvas', () => ({\n  ...jest.requireActual('../../../../../../app/canvas'),\n  useCanvas: jest.fn(),\n  useCanvasBoundingBox: jest.fn(),\n}));\n\nconst RESOURCE = {\n  alt: 'image of maria',\n  attribution: {\n    author: {\n      displayName: 'Maria',\n      url: 'http://maria.com',\n    },\n    registerUsageUrl: '',\n  },\n  creationDate: '1234',\n  height: 353,\n  id: undefined,\n  length: null,\n  lengthFormatted: null,\n  mimeType: 'image/jpeg',\n  poster: null,\n  posterId: null,\n  sizes: {\n    full: {\n      file: 'media/unsplash:1234',\n      sourceUrl: 'http://lala.com',\n      mimeType: 'image/jpeg',\n      width: 530,\n      height: 353,\n    },\n  },\n  src: 'http://lala.com',\n  type: 'image',\n  width: 530,\n};\n\nconst mockCanvasContext = {\n  fullbleedContainer: {},\n  nodesById: {},\n  pageContainer: { getBoundingClientRect: () => ({ x: 0, y: 0 }) },\n};\n\ndescribe('automated accessibility tests', () => {\n  const mockUseCanvas = useCanvas;\n  const mockUseCanvasBoundingBox = useCanvasBoundingBox;\n\n  beforeEach(() => {\n    mockUseCanvas.mockReturnValue(mockCanvasContext);\n    mockUseCanvasBoundingBox.mockReturnValue({ x: 0, y: 0 });\n    useLocalMedia.mockReturnValue({\n      isCurrentResourceTrimming: jest.fn(),\n      isCurrentResourceMuting: jest.fn(),\n      isCurrentResourceTranscoding: jest.fn(),\n      isCurrentResourceProcessing: jest.fn(),\n      isCurrentResourceUploading: jest.fn(),\n      isNewResourceProcessing: jest.fn(),\n    });\n  });\n\n  it('should render MediaElement without accessibility violations', async () => {\n    const { container } = renderWithTheme(\n      <MediaElement\n        index={0}\n        resource={RESOURCE}\n        width={RESOURCE.width}\n        height={RESOURCE.height}\n        onInsert={() => {}}\n      />\n    );\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should render transcoding MediaElement without accessibility violations', async () => {\n    useLocalMedia.mockReturnValue({\n      isCurrentResourceTrimming: jest.fn(),\n      isCurrentResourceMuting: jest.fn(),\n      isCurrentResourceTranscoding: () => true,\n      isCurrentResourceProcessing: jest.fn(),\n      isNewResourceProcessing: jest.fn(),\n      isCurrentResourceUploading: jest.fn(),\n    });\n    // transcoding\n    const { container: container2 } = renderWithTheme(\n      <MediaElement\n        index={0}\n        resource={RESOURCE}\n        width={RESOURCE.width}\n        height={RESOURCE.height}\n        onInsert={() => {}}\n      />\n    );\n\n    const transcodingResults = await axe(container2);\n    expect(transcodingResults).toHaveNoViolations();\n  });\n\n  it('should render Attribution without accessibility violations', async () => {\n    const { container } = renderWithTheme(\n      <Attribution author=\"Juan of Ark\" url=\"https://www.juanofark.com\" />\n    );\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/common/test/paginatedMediaGallery.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  useCanvas,\n  useCanvasBoundingBox,\n  useLocalMedia,\n} from '../../../../../../app';\nimport PaginatedMediaGallery from '../paginatedMediaGallery';\n\njest.mock('../../../../../../app/media');\n\njest.mock('../../../../../../app/canvas', () => ({\n  ...jest.requireActual('../../../../../../app/canvas'),\n  useCanvas: jest.fn(),\n  useCanvasBoundingBox: jest.fn(),\n}));\n\nconst mockCanvasContext = {\n  fullbleedContainer: {},\n  nodesById: {},\n  pageContainer: { getBoundingClientRect: () => ({ x: 0, y: 0 }) },\n};\n\ndescribe('paginatedMediaGallery', () => {\n  const providerType = 'unsplash';\n  const resources = [\n    {\n      alt: null,\n      attribution: {\n        author: {\n          displayName: 'Maria',\n          url: 'http://maria.com',\n        },\n        registerUsageUrl: '',\n      },\n      creationDate: '1234',\n      height: 353,\n      id: undefined,\n      length: null,\n      lengthFormatted: null,\n      mimeType: 'image/jpeg',\n      poster: null,\n      posterId: null,\n      sizes: {\n        full: {\n          file: 'media/unsplash:1234',\n          sourceUrl: 'http://lala.com',\n          mimeType: 'image/jpeg',\n          width: 530,\n          height: 353,\n        },\n      },\n      src: 'http://lala.com',\n      type: 'image',\n      width: 530,\n    },\n  ];\n  const mockUseCanvas = useCanvas;\n  const mockUseCanvasBoundingBox = useCanvasBoundingBox;\n\n  beforeAll(() => {\n    // https://stackoverflow.com/questions/53271193/typeerror-scrollintoview-is-not-a-function\n    window.HTMLElement.prototype.scrollTo = () => {};\n  });\n\n  beforeEach(() => {\n    mockUseCanvas.mockReturnValue(mockCanvasContext);\n    mockUseCanvasBoundingBox.mockReturnValue({ x: 0, y: 0 });\n    useLocalMedia.mockReturnValue({\n      isCurrentResourceTrimming: jest.fn(),\n      isCurrentResourceMuting: jest.fn(),\n      isCurrentResourceTranscoding: jest.fn(),\n      isCurrentResourceProcessing: jest.fn(),\n      isCurrentResourceUploading: jest.fn(),\n      isNewResourceProcessing: jest.fn(),\n    });\n  });\n\n  it('should render attribution when media is present', () => {\n    renderWithTheme(\n      <PaginatedMediaGallery\n        providerType={providerType}\n        resources={resources}\n        isMediaLoading={false}\n        isMediaLoaded\n        hasMore={false}\n        onInsert={() => {}}\n        setNextPage={() => {}}\n      />\n    );\n\n    expect(screen.getByText(/Powered by/)).toBeInTheDocument();\n    expect(screen.queryByTestId('loading-pill')).not.toBeInTheDocument();\n  });\n\n  it('should render the loading pill when media is loading', async () => {\n    renderWithTheme(\n      <PaginatedMediaGallery\n        providerType={providerType}\n        resources={resources}\n        isMediaLoading\n        isMediaLoaded={false}\n        hasMore\n        onInsert={() => {}}\n        setNextPage={() => {}}\n      />\n    );\n\n    expect(screen.getByText(/Powered by/)).toBeInTheDocument();\n    expect(screen.queryByTestId('loading-pill')).not.toBeInTheDocument();\n\n    // The loading indicator only appears (and thus the attribution disappears)\n    // if loading takes too long.\n    await waitFor(\n      () => {\n        expect(screen.queryByText(/Powered by/)).not.toBeInTheDocument();\n      },\n      {\n        timeout: 1000,\n      }\n    );\n\n    expect(screen.queryByText(/Powered by/)).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/deleteDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackError } from '@googleforcreators/tracking';\nimport { Text, TextSize, useSnackbar } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../../app/api';\nimport { useLocalMedia } from '../../../../../app/media';\nimport { useStory } from '../../../../../app/story';\nimport Dialog from '../../../../dialog';\n\n/**\n * Display a confirmation dialog for when a user wants to delete a media element.\n *\n * @param {Object} props Component props.\n * @param {number} props.mediaId Selected media element's ID.\n * @param {string} props.type Selected media element's type.\n * @param {Function} props.onClose Callback to toggle dialog display on close.\n * @return {null|*} The dialog element.\n */\nfunction DeleteDialog({ mediaId, type, onClose }) {\n  const {\n    actions: { deleteMedia },\n  } = useAPI();\n  const { showSnackbar } = useSnackbar();\n  const { deleteMediaElement } = useLocalMedia(\n    ({ actions: { deleteMediaElement } }) => ({\n      deleteMediaElement,\n    })\n  );\n  const { deleteElementsByResourceId } = useStory((state) => ({\n    deleteElementsByResourceId: state.actions.deleteElementsByResourceId,\n  }));\n\n  const onDelete = useCallback(async () => {\n    onClose();\n    try {\n      await deleteMedia(mediaId);\n      deleteMediaElement({ id: mediaId });\n      deleteElementsByResourceId({ id: mediaId });\n    } catch (err) {\n      trackError('local_media_deletion', err.message);\n      showSnackbar({\n        message: __('Failed to delete media item.', 'web-stories'),\n        dismissible: true,\n      });\n    }\n  }, [\n    deleteMedia,\n    deleteMediaElement,\n    deleteElementsByResourceId,\n    mediaId,\n    onClose,\n    showSnackbar,\n  ]);\n\n  const imageDialogTitle = __('Delete Image?', 'web-stories');\n  const videoDialogTitle = __('Delete Video?', 'web-stories');\n  const imageDialogDescription = __(\n    'You are about to permanently delete this image from your site. The image will appear broken in any content that uses it.',\n    'web-stories'\n  );\n  const videoDialogDescription = __(\n    'You are about to permanently delete this video from your site. The video will appear broken in any content that uses it.',\n    'web-stories'\n  );\n\n  // Keep icon and menu displayed if menu is open (even if user's mouse leaves the area).\n  return (\n    <Dialog\n      isOpen\n      onClose={onClose}\n      title={type === 'image' ? imageDialogTitle : videoDialogTitle}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={onDelete}\n      primaryText={__('Delete', 'web-stories')}\n      maxWidth={512}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {type === 'image' ? imageDialogDescription : videoDialogDescription}\n      </Text.Paragraph>\n      <Text.Paragraph size={TextSize.Small} isBold>\n        {__('This action can not be undone.', 'web-stories')}\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nDeleteDialog.propTypes = {\n  mediaId: PropTypes.number.isRequired,\n  type: PropTypes.string.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default DeleteDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/dropDownMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useMemo,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  Icons,\n  Menu,\n  Placement,\n  Popup,\n  noop,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useLocalMedia } from '../../../../../app';\nimport { ActionButton } from '../../shared';\nimport DropDownKeyEvents from '../../../../panels/utils/dropDownKeyEvents';\nimport DeleteDialog from './deleteDialog';\nimport MediaEditDialog from './mediaEditDialog';\n\nconst MoreButton = styled(ActionButton)`\n  top: 4px;\n  right: 4px;\n`;\n\nconst DropDownContainer = styled.div`\n  margin-top: 10px;\n`;\n\nconst MenuContainer = styled.div`\n  z-index: 1;\n`;\n\nconst menuStylesOverride = css`\n  min-width: 160px;\n  margin-top: 0;\n  li {\n    display: block;\n  }\n`;\n\nconst MENU_OPTIONS = {\n  EDIT: 'edit',\n  DELETE: 'delete',\n};\n\n/**\n * Get a More icon that displays a dropdown menu on click.\n *\n * @param {Object} props Component props.\n * @param {Object} props.resource Selected media element's resource object.\n * @param {boolean} props.display Whether the more icon should be displayed.\n * @param {boolean} props.isMenuOpen If the dropdown menu is open.\n * @param {Function} props.onMenuOpen Callback for when menu is opened.\n * @param {Function} props.onMenuCancelled Callback for when menu is closed without any selections.\n * @param {Function} props.onMenuSelected Callback for when menu is closed and an option selected.\n * @param {Function} props.setParentActive Sets the parent element active.\n * @return {null|*} Element or null if should not display the More icon.\n */\nfunction DropDownMenu({\n  resource,\n  display,\n  isMenuOpen,\n  onMenuOpen,\n  onMenuCancelled,\n  onMenuSelected,\n  setParentActive = noop,\n}) {\n  const groups = [\n    {\n      options: [\n        {\n          label: __('Edit meta data', 'web-stories'),\n          value: MENU_OPTIONS.EDIT,\n        },\n        {\n          label: __('Delete from library', 'web-stories'),\n          value: MENU_OPTIONS.DELETE,\n        },\n      ],\n    },\n  ];\n\n  const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n  const [showEditDialog, setShowEditDialog] = useState(false);\n  const moreButtonRef = useRef();\n\n  const onClose = useCallback(() => {\n    onMenuCancelled();\n    moreButtonRef.current?.focus();\n    // Activeness of the parent is lost then due to blurring, we need to set it active \"manually\"\n    // to focus back on the original button.\n    setParentActive();\n  }, [onMenuCancelled, setParentActive]);\n\n  const { canTranscodeResource } = useLocalMedia(\n    ({ state: { canTranscodeResource } }) => ({\n      canTranscodeResource,\n    })\n  );\n\n  const handleCurrentValue = (evt, value) => {\n    onMenuSelected();\n    switch (value) {\n      case MENU_OPTIONS.EDIT:\n        setShowEditDialog(true);\n        break;\n      case MENU_OPTIONS.DELETE:\n        setShowDeleteDialog(true);\n        break;\n      default:\n        break;\n    }\n  };\n\n  // On Delete dialog closing.\n  const onDeleteDialogClose = useCallback(() => {\n    setShowDeleteDialog(false);\n    onClose();\n  }, [setShowDeleteDialog, onClose]);\n\n  // On Edit dialog closing.\n  const onEditDialogClose = useCallback(() => {\n    setShowEditDialog(false);\n    onClose();\n  }, [setShowEditDialog, onClose]);\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const buttonId = useMemo(() => `button-${uuidv4()}`, []);\n\n  // Keep icon and menu displayed if menu is open (even if user's mouse leaves the area).\n  return (\n    canTranscodeResource(resource) && ( // Don't show menu if resource is being processed.\n      <MenuContainer>\n        {/* eslint-disable react-hooks/refs -- FIXME */}\n        {moreButtonRef.current && (\n          <DropDownKeyEvents target={moreButtonRef.current} />\n        )}\n        {/* eslint-enable react-hooks/refs -- FIXME */}\n        <MoreButton\n          ref={moreButtonRef}\n          onClick={onMenuOpen}\n          aria-label={__('More', 'web-stories')}\n          aria-pressed={isMenuOpen}\n          aria-haspopup\n          aria-expanded={isMenuOpen}\n          aria-owns={isMenuOpen ? listId : null}\n          id={buttonId}\n          $display={display}\n          tabIndex={display || isMenuOpen ? 0 : -1}\n        >\n          <Icons.DotsFillSmall />\n        </MoreButton>\n        {(display || isMenuOpen) && (\n          <Popup\n            anchor={moreButtonRef}\n            placement={Placement.BottomStart}\n            isOpen={isMenuOpen}\n          >\n            <DropDownContainer>\n              <Menu\n                parentId={buttonId}\n                listId={listId}\n                handleMenuItemSelect={handleCurrentValue}\n                groups={groups}\n                onDismissMenu={onClose}\n                hasMenuRole\n                menuStylesOverride={menuStylesOverride}\n              />\n            </DropDownContainer>\n          </Popup>\n        )}\n        {showDeleteDialog && (\n          <DeleteDialog\n            mediaId={resource.id}\n            type={resource.type}\n            onClose={onDeleteDialogClose}\n          />\n        )}\n        {showEditDialog && (\n          <MediaEditDialog resource={resource} onClose={onEditDialogClose} />\n        )}\n      </MenuContainer>\n    )\n  );\n}\n\nDropDownMenu.propTypes = {\n  resource: PropTypes.object.isRequired,\n  display: PropTypes.bool.isRequired,\n  isMenuOpen: PropTypes.bool.isRequired,\n  onMenuOpen: PropTypes.func.isRequired,\n  onMenuCancelled: PropTypes.func.isRequired,\n  onMenuSelected: PropTypes.func.isRequired,\n  setParentActive: PropTypes.func,\n};\n\nexport default DropDownMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/hotlink/hotlink.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button as DefaultButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../../../../panels/shared/styles';\nimport Tooltip from '../../../../../tooltip';\nimport HotlinkModal from '../../../../../hotlinkModal';\nimport useInsert from './useInsert';\n\nconst Button = styled(DefaultButton)`\n  ${focusStyle};\n  margin: 0 10px 0 0;\n`;\n\nfunction Hotlink() {\n  const label = __('Insert by link', 'web-stories');\n  const {\n    action: { onSelect, onError, onClose, onClick },\n    state: { allowedFileTypes, isOpen },\n  } = useInsert();\n  return (\n    <>\n      <Tooltip title={label}>\n        <Button\n          variant={ButtonVariant.Square}\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          onClick={onClick}\n          aria-label={label}\n        >\n          <Icons.Link />\n        </Button>\n      </Tooltip>\n      <HotlinkModal\n        onClose={onClose}\n        isOpen={isOpen}\n        onError={onError}\n        onSelect={onSelect}\n        allowedFileTypes={allowedFileTypes}\n        title={__('Insert external image or video', 'web-stories')}\n      />\n    </>\n  );\n}\n\nexport default Hotlink;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/hotlink/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './hotlink';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/hotlink/useInsert.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport {\n  getImageFromVideo,\n  seekVideo,\n  getVideoLength,\n  preloadVideo,\n  hasVideoGotAudio,\n  getExtensionsFromMimeType,\n  blobToFile,\n} from '@googleforcreators/media';\nimport { v4 as uuidv4 } from 'uuid';\nimport { trackError, trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport useLibrary from '../../../../useLibrary';\nimport useLocalMedia from '../../../../../../app/media/local/useLocalMedia';\nimport getResourceFromUrl from '../../../../../../app/media/utils/getResourceFromUrl';\nimport {\n  getPosterName,\n  useUploadVideoFrame,\n} from '../../../../../../app/media/utils';\nimport { useConfig } from '../../../../../../app/config';\nimport useCORSProxy from '../../../../../../utils/useCORSProxy';\nimport { MEDIA_POSTER_IMAGE_MIME_TYPE } from '../../../../../../constants';\n\nconst eventName = 'hotlink_media';\n\nfunction useInsert() {\n  const [isOpen, setIsOpen] = useState(false);\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n  const {\n    capabilities: { hasUploadMediaAction },\n    allowedMimeTypes: {\n      image: allowedImageMimeTypes,\n      vector: allowedVectorMimeTypes,\n      video: allowedVideoMimeTypes,\n    },\n  } = useConfig();\n  const { updateBaseColor } = useLocalMedia(\n    ({ actions: { updateBaseColor } }) => ({\n      updateBaseColor,\n    })\n  );\n\n  const allowedMimeTypes = useMemo(\n    () => [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ],\n    [allowedImageMimeTypes, allowedVectorMimeTypes, allowedVideoMimeTypes]\n  );\n  const allowedFileTypes = useMemo(\n    () => allowedMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedMimeTypes]\n  );\n\n  const { uploadVideoPoster } = useUploadVideoFrame({});\n  const { getProxiedUrl } = useCORSProxy();\n\n  const onClick = () => setIsOpen(true);\n  const onClose = () => setIsOpen(false);\n  const onSelect = useCallback(\n    async ({ link, hotlinkInfo, needsProxy }) => {\n      const { ext, type, mimeType, fileName: originalFileName } = hotlinkInfo;\n\n      const isVideo = type === 'video';\n\n      try {\n        const proxiedUrl = needsProxy\n          ? getProxiedUrl({ needsProxy }, link)\n          : link;\n\n        const resourceLike = {\n          id: uuidv4(),\n          src: proxiedUrl,\n          mimeType,\n          needsProxy,\n          alt: originalFileName,\n        };\n\n        // We need to gather some metadata for videos, but efficiently.\n        // Thus only loading it once to speed up insertion.\n        if (isVideo) {\n          // preloadVideoMetadata would suffice, except for audio detection\n          // which requires loading more than just metadata.\n          const video = await preloadVideo(proxiedUrl);\n          await seekVideo(video);\n\n          resourceLike.width = video.videoWidth;\n          resourceLike.height = video.videoHeight;\n\n          const videoLength = getVideoLength(video);\n\n          resourceLike.length = videoLength.length;\n          resourceLike.lengthFormatted = videoLength.lengthFormatted;\n\n          resourceLike.isMuted = !hasVideoGotAudio(video);\n\n          // We want to auto-generate and *upload* posters for hotlinked videos.\n          // While this could be done _after_ insertion, at this point we have\n          // already preloaded the video, so this will be quick.\n          // Also, this avoids adding a history entry for adding the poster,\n          // which would also cause the autoplayed video to be paused again.\n          // However, upload might fail, thus adding this nested try ... catch.\n          if (hasUploadMediaAction) {\n            try {\n              const fileName = getPosterName(\n                originalFileName.replace(`.${ext}`, '')\n              );\n\n              const blob = await getImageFromVideo(video);\n              const posterFile = blobToFile(\n                blob,\n                fileName,\n                MEDIA_POSTER_IMAGE_MIME_TYPE\n              );\n              const posterData = await uploadVideoPoster(0, posterFile);\n\n              resourceLike.poster = posterData.poster;\n              resourceLike.posterId = posterData.posterId;\n            } catch {\n              // No need to catch poster generation errors.\n            }\n          }\n        }\n\n        // Passing the potentially proxied URL here just so that\n        // metadata retrieval works as expected (if still needed after the above).\n        // Afterwards, overriding `src` again to ensure we store the original URL.\n        const resource = await getResourceFromUrl(resourceLike);\n        resource.src = link;\n\n        insertElement(type, {\n          resource,\n        });\n\n        updateBaseColor(resource);\n\n        // After getting link metadata and before actual insertion\n        // is a great opportunity to measure usage in a reasonably accurate way.\n        trackEvent(eventName, {\n          event_label: link,\n          file_size: hotlinkInfo.fileSize,\n          file_type: hotlinkInfo.mimeType,\n          needs_proxy: needsProxy,\n        });\n        setIsOpen(false);\n      } catch {\n        // Do nothing for now\n      }\n    },\n    [\n      getProxiedUrl,\n      insertElement,\n      updateBaseColor,\n      hasUploadMediaAction,\n      uploadVideoPoster,\n    ]\n  );\n\n  const onError = useCallback((err) => trackError(eventName, err?.message), []);\n\n  return {\n    action: {\n      onSelect,\n      onError,\n      onClick,\n      onClose,\n    },\n    state: {\n      allowedFileTypes,\n      isOpen,\n    },\n  };\n}\n\nexport default useInsert;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as MediaPane } from './mediaPane';\nexport { default as MediaIcon } from './mediaIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/karma/hotlink.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\n\nimport { Fixture } from '../../../../../../karma/fixture';\nimport { useStory } from '../../../../../../app/story';\n\ndescribe('Embedding hotlinked media', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getElements() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  }\n\n  it('should not allow embedding media from an invalid link', async () => {\n    const button = fixture.screen.getByRole('button', {\n      name: 'Insert by link',\n    });\n    await fixture.events.click(button);\n    const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n    const insertBtn = fixture.screen.getByRole('button', {\n      name: 'Insert',\n    });\n\n    // Try inserting from a string that's not a link at all.\n    await fixture.events.click(input);\n    await fixture.events.keyboard.type('d');\n    await fixture.events.click(insertBtn);\n    let dialog;\n    await waitFor(() => {\n      dialog = screen.getByRole('dialog');\n      if (!dialog) {\n        throw new Error('dialog not ready');\n      }\n      expect(dialog.textContent).toContain('Invalid link');\n    });\n\n    // Delete the value, verify now the informative message show instead again.\n    await fixture.events.click(input, { clickCount: 3 });\n    await fixture.events.keyboard.press('Del');\n    await waitFor(() => {\n      dialog = screen.getByRole('dialog');\n      if (!dialog) {\n        throw new Error('dialog not ready');\n      }\n      expect(dialog.textContent).toContain('You can insert');\n    });\n\n    await fixture.events.click(input);\n    await fixture.events.keyboard.type('https://example.jpgef');\n    await fixture.events.click(insertBtn);\n\n    await waitFor(\n      () => {\n        dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        expect(dialog.textContent).toContain('Invalid link');\n      },\n      {\n        timeout: 1500,\n      }\n    );\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- TODO: Investigate & fix failing test.\n  xit('should insert a new media element from valid url', async () => {\n    spyOn(window, 'fetch').and.callFake(() => {\n      return true;\n    });\n\n    // Get URL from existing library.\n    const libraryElement = fixture.editor.library.media.item(0);\n    const img = libraryElement.getElementsByTagName('img')[0];\n\n    const button = fixture.screen.getByRole('button', {\n      name: 'Insert by link',\n    });\n    await fixture.events.click(button);\n    const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n    const insertBtn = fixture.screen.getByRole('button', {\n      name: 'Insert',\n    });\n    await fixture.events.click(input);\n    await fixture.events.keyboard.type(img.src);\n    await fixture.events.click(insertBtn);\n\n    const elements = await getElements();\n    expect(elements[1].resource.src).toBe(img.src);\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- TODO: Investigate & fix failing test.\n  xit('should insert a new media element from valid url using proxy', async () => {\n    // Let's throw an error when checking for HEAD, forcing to use the CORS proxy.\n    spyOn(window, 'fetch').and.callFake(() => {\n      throw new Error();\n    });\n\n    const button = fixture.screen.getByRole('button', {\n      name: 'Insert by link',\n    });\n    await fixture.events.click(button);\n    const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n    const insertBtn = fixture.screen.getByRole('button', {\n      name: 'Insert',\n    });\n    await fixture.events.click(input);\n    await fixture.events.keyboard.type(\n      'http://localhost:9876/__static__/saturn.jpg'\n    );\n    await fixture.events.click(insertBtn);\n\n    const elements = await getElements();\n    expect(elements[1].resource.src).toBe(\n      'http://localhost:9876/__static__/saturn.jpg'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/karma/mediaFetching.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\n\nimport { Fixture, LOCAL_MEDIA_PER_PAGE } from '../../../../../../karma/fixture';\nimport { ROOT_MARGIN } from '../mediaPane';\n\ndescribe('MediaPane fetching', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should fetch additional pages', async () => {\n    const localPane = await waitFor(() =>\n      fixture.querySelector('#library-pane-media')\n    );\n    const mediaGallery = await within(localPane).findByTestId(\n      'media-gallery-container'\n    );\n\n    const initialElementsLength =\n      fixture.screen.queryAllByTestId(/^mediaElement-/).length;\n\n    // ensure fixture.screen has loaded before calling expect to prevent immediate failure\n    // Wait for the debounce\n    await fixture.events.sleep(1000);\n    await waitFor(() => {\n      if (initialElementsLength !== LOCAL_MEDIA_PER_PAGE) {\n        throw new Error(\n          `wait for initial fetch ${initialElementsLength} != ${LOCAL_MEDIA_PER_PAGE}`\n        );\n      }\n      expect(initialElementsLength).toEqual(LOCAL_MEDIA_PER_PAGE);\n    });\n\n    // Scroll all the way down.\n    await mediaGallery.scrollTo(\n      0,\n      mediaGallery.scrollHeight - mediaGallery.clientHeight - ROOT_MARGIN / 2\n    );\n\n    // ensure fixture.screen has loaded before calling expect to prevent immediate failure\n    await waitFor(() => {\n      if (\n        fixture.screen.queryAllByTestId(/^mediaElement-/).length <\n        initialElementsLength + LOCAL_MEDIA_PER_PAGE\n      ) {\n        throw new Error('Not loaded yet');\n      }\n\n      expect(\n        fixture.screen.queryAllByTestId(/^mediaElement-/).length\n      ).toBeGreaterThanOrEqual(initialElementsLength + LOCAL_MEDIA_PER_PAGE);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/mediaEditDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { formatDate, toDate, isValid } from '@googleforcreators/date';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { trackError } from '@googleforcreators/tracking';\nimport {\n  getSmallestUrlForWidth,\n  ResourcePropTypes,\n} from '@googleforcreators/media';\nimport {\n  Text,\n  TextArea,\n  TextSize,\n  useSnackbar,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../../app/api';\nimport { useLocalMedia } from '../../../../../app/media';\nimport Dialog from '../../../../dialog';\n\nconst THUMBNAIL_WIDTH = 152;\n\nconst styledMediaThumbnail = css`\n  display: flex;\n  width: ${THUMBNAIL_WIDTH}px;\n  margin-right: 28px;\n`;\n\nconst Image = styled.img`\n  ${styledMediaThumbnail}\n`;\n\nconst Video = styled.video`\n  ${styledMediaThumbnail}\n`;\n\nconst DialogBody = styled.div`\n  display: flex;\n  justify-content: left;\n  align-items: flex-start;\n`;\n\nconst MetadataTextContainer = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin: 0 4px;\n`;\n\nconst DateText = styled(Text.Span)`\n  margin-bottom: 8px;\n`;\n\nconst AssistiveTextArea = styled(TextArea)`\n  margin: 20px 0 4px;\n`;\n\nconst imageDialogTitle = __('Edit Image', 'web-stories');\nconst videoDialogTitle = __('Edit Video', 'web-stories');\nconst imageInputTitle = __('Assistive text', 'web-stories');\nconst videoInputTitle = __('Video description', 'web-stories');\nconst imageDialogDescription = __(\n  'Describe the appearance and function of the image. Leave empty if the image is purely decorative.',\n  'web-stories'\n);\nconst videoDialogDescription = __(\n  'For indexability and accessibility. Include any burned-in text inside the video.',\n  'web-stories'\n);\n\n/**\n * Displays a dialog where the user can edit the selected media element.\n *\n * @param {Object} props Component props.\n * @param {Object} props.resource Selected media element's resource object.\n * @param {Object} props.onClose Callback to toggle dialog display.\n * @return {null|*} The dialog element.\n */\nfunction MediaEditDialog({ resource, onClose }) {\n  const { id, src, creationDate, width, height, type, alt, poster, mimeType } =\n    resource;\n  const {\n    actions: { updateMedia },\n  } = useAPI();\n  const { updateMediaElement } = useLocalMedia(\n    ({ actions: { updateMediaElement } }) => ({\n      updateMediaElement,\n    })\n  );\n  const { showSnackbar } = useSnackbar();\n  const [altText, setAltText] = useState(alt);\n  const parsedDate = toDate(creationDate);\n\n  const handleAltTextChange = useCallback((evt) => {\n    setAltText(evt.target.value);\n  }, []);\n\n  const updateMediaItem = useCallback(async () => {\n    try {\n      // Update server.\n      await updateMedia(id, { altText });\n      // Update internal state.\n      updateMediaElement({ id, data: { alt: altText } });\n      onClose();\n    } catch (err) {\n      trackError('local_media_edit', err.message);\n      showSnackbar({\n        message: __('Failed to update, please try again.', 'web-stories'),\n        dismissible: true,\n      });\n    }\n  }, [altText, id, onClose, showSnackbar, updateMedia, updateMediaElement]);\n\n  const isImage = type === 'image';\n\n  return (\n    <Dialog\n      isOpen\n      onClose={onClose}\n      title={isImage ? imageDialogTitle : videoDialogTitle}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={updateMediaItem}\n      primaryText={__('Save', 'web-stories')}\n    >\n      <DialogBody>\n        {type === 'image' ? (\n          <Image\n            src={getSmallestUrlForWidth(THUMBNAIL_WIDTH, resource)}\n            alt={alt}\n            loading={'lazy'}\n            crossOrigin=\"anonymous\"\n            decoding=\"async\"\n          />\n        ) : (\n          <Video\n            key={src}\n            crossOrigin=\"anonymous\"\n            poster={poster}\n            preload=\"metadata\"\n            muted\n          >\n            <source src={src} type={mimeType} />\n          </Video>\n        )}\n        <MetadataTextContainer>\n          {isValid(parsedDate) && (\n            <DateText size={TextSize.XSmall}>\n              {sprintf(\n                /* translators: %s: upload date of media item. */\n                __('Uploaded: %s', 'web-stories'),\n                formatDate(creationDate)\n              )}\n            </DateText>\n          )}\n          <Text.Span size={TextSize.Small}>\n            {sprintf(\n              /* translators: 1: image width. 2: image height. */\n              __('%1$d x %2$d pixels', 'web-stories'),\n              width,\n              height\n            )}\n          </Text.Span>\n          <AssistiveTextArea\n            value={altText}\n            aria-label={isImage ? imageInputTitle : videoInputTitle}\n            type=\"text\"\n            placeholder={isImage ? imageInputTitle : videoInputTitle}\n            onChange={handleAltTextChange}\n          />\n          <Text.Paragraph size={TextSize.Small}>\n            {isImage ? imageDialogDescription : videoDialogDescription}\n          </Text.Paragraph>\n        </MetadataTextContainer>\n      </DialogBody>\n    </Dialog>\n  );\n}\n\nMediaEditDialog.propTypes = {\n  resource: ResourcePropTypes.resource.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default MediaEditDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/mediaIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction MediaIcon() {\n  return <Icons.ArrowCloud title={__('Media Gallery', 'web-stories')} />;\n}\n\nexport default MediaIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/mediaPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  Button as DefaultButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Text,\n  TextSize,\n  Icons,\n  Placement,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../../app/config';\nimport { useLocalMedia } from '../../../../../app/media';\nimport { SearchInput } from '../../../common';\nimport { MediaUploadButton, Select } from '../../../../form';\nimport {\n  MediaGalleryMessage,\n  PaneHeader,\n  PaneInner,\n  SearchInputContainer,\n  StyledPane,\n} from '../common/styles';\nimport PaginatedMediaGallery from '../common/paginatedMediaGallery';\nimport { PANE_PADDING } from '../../shared';\nimport { LOCAL_MEDIA_TYPE_ALL } from '../../../../../app/media/local/types';\nimport { focusStyle } from '../../../../panels/shared/styles';\nimport Tooltip from '../../../../tooltip';\nimport useOnMediaSelect from './useOnMediaSelect';\nimport paneId from './paneId';\nimport VideoOptimizationDialog from './videoOptimizationDialog';\nimport LinkInsertion from './hotlink';\nimport MediaRecording from './mediaRecording';\n\nexport const ROOT_MARGIN = 300;\n\nconst Button = styled(DefaultButton)`\n  ${focusStyle};\n`;\n\nconst FilterArea = styled.div`\n  display: flex;\n  justify-content: space-between;\n  margin-top: 24px;\n  padding: 0 ${PANE_PADDING} 0 ${PANE_PADDING};\n`;\n\nconst SearchCount = styled(Text.Paragraph).attrs({\n  size: TextSize.Medium,\n})`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-shrink: 0;\n`;\n\nconst ButtonsWrapper = styled.div`\n  display: flex;\n  flex: 1;\n  justify-content: flex-end;\n`;\n\nconst FILTER_NONE = LOCAL_MEDIA_TYPE_ALL;\nconst FILTERS = [\n  { value: FILTER_NONE, label: __('All Types', 'web-stories') },\n  { value: 'image', label: __('Images', 'web-stories') },\n  { value: 'video', label: __('Video', 'web-stories') },\n];\n\nfunction MediaPane(props) {\n  const {\n    hasMore,\n    media,\n    uploadingMedia,\n    isMediaLoading,\n    isMediaLoaded,\n    mediaType,\n    searchTerm,\n    setNextPage,\n    setMediaType,\n    setSearchTerm,\n    totalItems,\n  } = useLocalMedia(\n    ({\n      state: {\n        hasMore,\n        media,\n        uploadingMedia,\n        isMediaLoading,\n        isMediaLoaded,\n        mediaType,\n        searchTerm,\n        totalItems,\n      },\n      actions: { setNextPage, setMediaType, setSearchTerm },\n    }) => {\n      return {\n        hasMore,\n        media,\n        // If the media library is empty and we're still loading new items,\n        // do not display uploading items either for better UX.\n        uploadingMedia: !media.length && isMediaLoading ? [] : uploadingMedia,\n        isMediaLoading,\n        isMediaLoaded,\n        mediaType,\n        searchTerm,\n        totalItems,\n        setNextPage,\n        setMediaType,\n        setSearchTerm,\n      };\n    }\n  );\n\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const isSearching = searchTerm.length > 0;\n\n  /**\n   * Filter REST API calls and re-request API.\n   *\n   * @param {string} value that is passed to rest api to filter.\n   */\n  const onFilter = useCallback(\n    (evt, filter) => {\n      setMediaType({ mediaType: filter });\n    },\n    [setMediaType]\n  );\n\n  const { onSelect, insertMediaElement } = useOnMediaSelect();\n\n  const onSearch = (value) => {\n    const trimText = value.trim();\n    if (trimText !== searchTerm) {\n      setSearchTerm({ searchTerm: trimText });\n    }\n  };\n\n  useEffect(() => {\n    if (searchTerm.length > 0) {\n      trackEvent('search', {\n        search_type: 'media',\n        search_term: searchTerm,\n        search_filter: mediaType,\n      });\n    }\n  }, [searchTerm, mediaType]);\n\n  const renderUploadButtonIcon = useCallback(\n    (open) => (\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        onClick={open}\n        aria-label={__('Upload', 'web-stories')}\n      >\n        <Icons.ArrowCloud />\n      </Button>\n    ),\n    []\n  );\n\n  return (\n    <StyledPane id={paneId} {...props}>\n      <PaneInner>\n        <PaneHeader>\n          <SearchInputContainer>\n            <SearchInput\n              initialValue={searchTerm}\n              placeholder={__('Search', 'web-stories')}\n              onSearch={onSearch}\n            />\n          </SearchInputContainer>\n          <FilterArea>\n            <Select\n              selectedValue={mediaType?.toString() || FILTER_NONE}\n              onMenuItemClick={onFilter}\n              options={FILTERS}\n              placement={Placement.BottomStart}\n            />\n            {isSearching && media.length > 0 && (\n              <SearchCount>\n                {sprintf(\n                  /* translators: %s: number of results. */\n                  _n(\n                    '%s result found.',\n                    '%s results found.',\n                    totalItems,\n                    'web-stories'\n                  ),\n                  totalItems\n                )}\n              </SearchCount>\n            )}\n            {!isSearching && (\n              <ButtonsWrapper>\n                {/* MediaRecording already checks for permissions */}\n                <MediaRecording />\n                <LinkInsertion />\n                {hasUploadMediaAction && (\n                  <Tooltip title={__('Upload', 'web-stories')}>\n                    <MediaUploadButton\n                      renderButton={renderUploadButtonIcon}\n                      onInsert={onSelect}\n                    />\n                  </Tooltip>\n                )}\n              </ButtonsWrapper>\n            )}\n          </FilterArea>\n        </PaneHeader>\n\n        {isMediaLoaded && !media.length && !uploadingMedia.length ? (\n          <MediaGalleryMessage>\n            {isSearching\n              ? __('No results found.', 'web-stories')\n              : __('No media found.', 'web-stories')}\n          </MediaGalleryMessage>\n        ) : (\n          <PaginatedMediaGallery\n            providerType=\"local\"\n            canEditMedia={hasUploadMediaAction}\n            resources={media}\n            uploadingResources={uploadingMedia}\n            isMediaLoading={isMediaLoading}\n            isMediaLoaded={isMediaLoaded}\n            hasMore={hasMore}\n            onInsert={insertMediaElement}\n            setNextPage={setNextPage}\n            searchTerm={searchTerm}\n          />\n        )}\n        <VideoOptimizationDialog />\n      </PaneInner>\n    </StyledPane>\n  );\n}\n\nexport default MediaPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/mediaRecording/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './mediaRecording';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/mediaRecording/mediaRecording.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button as DefaultButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../../../../panels/shared/styles';\nimport Tooltip from '../../../../../tooltip';\nimport useMediaRecording from '../../../../../mediaRecording/useMediaRecording';\nimport useFFmpeg from '../../../../../../app/media/utils/useFFmpeg';\n\nconst Button = styled(DefaultButton)`\n  ${focusStyle};\n  margin: 0 10px 0 0;\n`;\n\nconst Camera = styled(Icons.Camera)`\n  width: 24px !important;\n  height: 24px !important;\n`;\n\nfunction MediaRecording() {\n  const { isInRecordingMode, toggleRecordingMode } = useMediaRecording(\n    ({ state: { isInRecordingMode }, actions: { toggleRecordingMode } }) => ({\n      isInRecordingMode,\n      toggleRecordingMode,\n    })\n  );\n\n  const { isTranscodingEnabled } = useFFmpeg();\n\n  const onClick = useCallback(() => {\n    trackEvent('media_recording_toggled', {\n      status: isInRecordingMode ? 'closed' : 'open',\n    });\n    toggleRecordingMode();\n  }, [isInRecordingMode, toggleRecordingMode]);\n\n  // Media recording requires video optimization to be enabled,\n  // since it's the only reliable way to ensure the recorded video\n  // can be played in all browsers.\n  // `isTranscodingEnabled` already checks for `hasUploadMediaAction`\n  if (!isTranscodingEnabled) {\n    return null;\n  }\n\n  const label = __('Record Video/Audio', 'web-stories');\n  return (\n    <Tooltip title={label}>\n      <Button\n        variant={ButtonVariant.Square}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        onClick={onClick}\n        aria-label={label}\n        aria-pressed={isInRecordingMode}\n        isToggled={isInRecordingMode}\n      >\n        <Camera />\n      </Button>\n    </Tooltip>\n  );\n}\n\nexport default MediaRecording;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../../shared';\n\nexport default getPaneId('media');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/stories/deleteDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { SnackbarContext } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport DeleteDialog from '../deleteDialog';\nimport ApiContext from '../../../../../../app/api/context';\nimport MediaContext from '../../../../../../app/media/context';\nimport StoryContext from '../../../../../../app/story/context';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Delete Media',\n  component: DeleteDialog,\n  argTypes: {\n    deleteMedia: { action: 'delete from server' },\n    deleteMediaElement: { action: 'delete from state' },\n    deleteElementsByResourceId: { action: 'delete element by resource ID' },\n    showSnackbar: { action: 'show snackbar' },\n    onClose: { action: 'on close' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['mediaId', 'type'],\n      hideNoControlsWarning: true,\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const apiValue = {\n      actions: {\n        deleteMedia: args.deleteMedia,\n      },\n    };\n    const mediaValue = {\n      local: {\n        actions: { deleteMediaElement: args.deleteMediaElement },\n      },\n    };\n    const storyContext = {\n      actions: {\n        deleteElementsByResourceId: args.deleteElementsByResourceId,\n      },\n    };\n    const snackbarValue = { showSnackbar: args.showSnackbar };\n\n    return (\n      <SnackbarContext.Provider value={snackbarValue}>\n        <MediaContext.Provider value={mediaValue}>\n          <ApiContext.Provider value={apiValue}>\n            <StoryContext.Provider value={storyContext}>\n              <DeleteDialog\n                mediaId={123}\n                type={'image'}\n                onClose={args.onClose}\n              />\n            </StoryContext.Provider>\n          </ApiContext.Provider>\n        </MediaContext.Provider>\n      </SnackbarContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/stories/mediaEditDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { SnackbarContext } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport MediaEditDialog from '../mediaEditDialog';\nimport ApiContext from '../../../../../../app/api/context';\nimport MediaContext from '../../../../../../app/media/context';\nimport testImage from './test-image.jpg';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Edit Media',\n  component: MediaEditDialog,\n  args: {\n    resource: {\n      id: 123,\n      type: 'image',\n      mimeType: 'image/png',\n      creationDate: '2019-11-13T18:15:52Z',\n      src: testImage,\n      width: 910,\n      height: 675,\n      alt: 'my image',\n      sizes: {},\n    },\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n    updateMedia: { action: 'update server' },\n    updateMediaElement: { action: 'update state' },\n    showSnackbar: { action: 'show snackbar' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const apiValue = {\n      actions: args.updateMedia,\n    };\n    const mediaValue = {\n      local: {\n        actions: args.updateMediaElement,\n      },\n    };\n    const snackbarValue = { showSnackbar: args.showSnackbar };\n\n    return (\n      <SnackbarContext.Provider value={snackbarValue}>\n        <MediaContext.Provider value={mediaValue}>\n          <ApiContext.Provider value={apiValue}>\n            <MediaEditDialog resource={args.resource} onClose={args.onClose} />\n          </ApiContext.Provider>\n        </MediaContext.Provider>\n      </SnackbarContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/stories/videoOptimizationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport VideoOptimizationDialog from '../videoOptimizationDialog';\nimport MediaContext from '../../../../../../app/media/context';\nimport CurrentUserContext from '../../../../../../app/currentUser/context';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Video Optimization',\n  component: VideoOptimizationDialog,\n  argTypes: {\n    updateCurrentUser: { action: 'close dialog' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    // Reset local storage for improved testablity.\n    const storageKey = LOCAL_STORAGE_PREFIX.VIDEO_OPTIMIZATION_DIALOG_DISMISSED;\n    localStore.setItemByKey(storageKey, false);\n\n    const mediaValue = {\n      local: {\n        state: { isTranscoding: true },\n      },\n    };\n\n    const userValue = {\n      actions: { updateCurrentUser: args.updateCurrentUser },\n    };\n\n    return (\n      <CurrentUserContext.Provider value={userValue}>\n        <MediaContext.Provider value={mediaValue}>\n          <VideoOptimizationDialog />\n        </MediaContext.Provider>\n      </CurrentUserContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/test/videoOptimizationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n  setAppElement,\n} from '@googleforcreators/design-system';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport CurrentUserContext from '../../../../../../app/currentUser/context';\nimport MediaContext from '../../../../../../app/media/context';\nimport VideoOptimizationDialog from '../videoOptimizationDialog';\n\nconst updateCurrentUser = jest.fn();\nconst storageKey = LOCAL_STORAGE_PREFIX.VIDEO_OPTIMIZATION_DIALOG_DISMISSED;\n\nfunction setup() {\n  updateCurrentUser.mockReset();\n  const mediaValue = {\n    local: {\n      state: { isTranscoding: true },\n    },\n  };\n\n  const userValue = {\n    actions: { updateCurrentUser },\n  };\n\n  localStore.setItemByKey(storageKey, false);\n\n  return renderWithTheme(\n    <CurrentUserContext.Provider value={userValue}>\n      <MediaContext.Provider value={mediaValue}>\n        <VideoOptimizationDialog />\n      </MediaContext.Provider>\n    </CurrentUserContext.Provider>\n  );\n}\n\ndescribe('videoOptimizationDialog', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  it('should render', () => {\n    setup();\n\n    expect(\n      screen.getByText('Video optimization in progress')\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', { name: /Disable/i })\n    ).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: /Sounds/i })).toBeInTheDocument();\n  });\n\n  it('should trigger API request to update user when disabling', async () => {\n    setup();\n\n    fireEvent.click(screen.getByRole('button', { name: /Disable/i }));\n\n    await waitFor(() => expect(updateCurrentUser).toHaveBeenCalledOnce());\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/useOnMediaSelect.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { resourceList } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport useLibrary from '../../../useLibrary';\n\nfunction useOnMediaSelect() {\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n\n  /**\n   * Insert element such image, video and audio into the editor.\n   *\n   * @param {Object} resource Resource object\n   * @param {string} thumbnailURL The thumbnail's url\n   * @return {null|*} Return onInsert or null.\n   */\n  const insertMediaElement = useCallback(\n    (resource, thumbnailURL) => {\n      resourceList.set(resource.id, {\n        url: thumbnailURL,\n        type: 'cached',\n      });\n      insertElement(resource.type, { resource });\n    },\n    [insertElement]\n  );\n\n  /**\n   * Callback of select in media picker to insert media element.\n   *\n   * @param {Object} resource Object coming from backbone media picker.\n   */\n  const onSelect = useCallback(\n    (resource) => {\n      // WordPress media picker event, sizes.medium.source_url is the smallest image\n      insertMediaElement(\n        resource,\n        resource.sizes?.medium?.source_url || resource.src\n      );\n    },\n    [insertMediaElement]\n  );\n\n  return { insertMediaElement, onSelect };\n}\n\nexport default useOnMediaSelect;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/local/videoOptimizationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Text,\n  TextSize,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useCurrentUser } from '../../../../../app/currentUser';\nimport { useLocalMedia } from '../../../../../app/media';\nimport Dialog from '../../../../dialog';\n\nconst storageKey = LOCAL_STORAGE_PREFIX.VIDEO_OPTIMIZATION_DIALOG_DISMISSED;\n\nfunction VideoOptimizationDialog() {\n  const { isTranscoding } = useLocalMedia(({ state: { isTranscoding } }) => ({\n    isTranscoding,\n  }));\n\n  const [isDialogDismissed, setIsDialogDismissed] = useState(\n    Boolean(localStore.getItemByKey(storageKey))\n  );\n\n  const { updateCurrentUser } = useCurrentUser(({ actions }) => ({\n    updateCurrentUser: actions.updateCurrentUser,\n  }));\n\n  const setIsDialogDismissedValue = useCallback((value) => {\n    setIsDialogDismissed(value);\n    localStore.setItemByKey(storageKey, value);\n  }, []);\n\n  const onDisable = useCallback(() => {\n    updateCurrentUser({\n      mediaOptimization: false,\n    });\n    setIsDialogDismissedValue(true);\n  }, [updateCurrentUser, setIsDialogDismissedValue]);\n\n  const onClose = useCallback(() => {\n    setIsDialogDismissedValue(true);\n  }, [setIsDialogDismissedValue]);\n\n  const dialogTitle = __('Video optimization in progress', 'web-stories');\n  const dialogDescription = __(\n    'This process can’t be stopped once it begins. Optimization is automatically enabled for all videos to ensure smooth playback. You can disable optimization any time in Settings.',\n    'web-stories'\n  );\n\n  return (\n    <Dialog\n      isOpen={isTranscoding && !isDialogDismissed}\n      onClose={onClose}\n      title={dialogTitle}\n      onSecondary={onDisable}\n      secondaryText={__('Disable optimization', 'web-stories')}\n      onPrimary={onClose}\n      primaryText={__('Sounds good', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>{dialogDescription}</Text.Paragraph>\n    </Dialog>\n  );\n}\n\nexport default VideoOptimizationDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as Media3pPane } from './media3pPane';\nexport { default as Media3pIcon } from './media3pIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/karma/mediaFetching.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport apiFetcher from '../../../../../../app/media/media3p/api/apiFetcher';\nimport { Fixture, MEDIA_PER_PAGE } from '../../../../../../karma/fixture';\nimport { ROOT_MARGIN } from '../../local/mediaPane';\n\nconst RESOURCE_BUILDERS = {\n  unsplash: (name) => ({\n    name,\n    provider: 'UNSPLASH',\n    imageUrls: [\n      {\n        imageName: 'full',\n        url: 'http://localhost:9876/__static__/blue-marble.jpg',\n        width: 600,\n        height: 600,\n        mimeType: 'image/png',\n      },\n      {\n        imageName: 'large',\n        url: 'http://localhost:9876/__static__/blue-marble.jpg',\n        width: 300,\n        height: 300,\n        mimeType: 'image/png',\n      },\n      {\n        imageName: 'web_stories_thumbnail',\n        url: 'http://localhost:9876/__static__/blue-marble.jpg',\n        width: 200,\n        height: 200,\n        mimeType: 'image/png',\n      },\n    ],\n    description: 'A cat',\n    type: 'IMAGE',\n    createTime: '1234',\n    updateTime: '5678',\n    blurHash: 'L4CD_PIU00%MD%M{j[xu00%M~qM{',\n  }),\n  coverr: (name) => ({\n    name,\n    provider: 'COVERR',\n    videoUrls: [\n      {\n        url: 'http://localhost:9876/__static__/beach.mp4',\n        width: 1920,\n        height: 1080,\n        mimeType: 'video/mp4',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.mp4',\n        width: 640,\n        height: 360,\n        mimeType: 'video/mp4',\n      },\n    ],\n    imageUrls: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        width: 1920,\n        height: 1080,\n        mimeType: 'image/jpg',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        width: 640,\n        height: 360,\n        mimeType: 'image/jpg',\n      },\n    ],\n    description: 'A beach',\n    type: 'VIDEO',\n    videoMetadata: {\n      duration: '12.34s',\n    },\n    createTime: '1234',\n    updateTime: '5678',\n    blurHash: 'D3DM_PIU00%MD%M{j[xu00%M~qM{',\n  }),\n};\n\n// page is index 0.\nconst mediaPage = (page, provider) =>\n  Array.from({ length: MEDIA_PER_PAGE }).map((n) => {\n    const mediaName = `media/${provider}:${n + page * MEDIA_PER_PAGE + 1}`;\n    return RESOURCE_BUILDERS[provider](mediaName);\n  });\n\nconst categories = [\n  {\n    name: 'categories/unsplash:KHXRtL69hcY',\n    displayName: 'Sustainability',\n  },\n  {\n    name: 'categories/unsplash:bo8jQKTaE0Y',\n    displayName: 'Wallpapers',\n  },\n  {\n    name: 'categories/unsplash:c7USHrQ0Ljw',\n    displayName: 'COVID-19',\n  },\n  {\n    name: 'categories/unsplash:Fzo3zuOHN6w',\n    displayName: 'Travel',\n  },\n  {\n    name: 'categories/unsplash:6sMVjTLSkeQ',\n    displayName: 'Nature',\n  },\n  {\n    name: 'categories/unsplash:iUIsnVtjB0Y',\n    displayName: 'Textures & Patterns',\n  },\n  {\n    name: 'categories/unsplash:BJJMtteDJA4',\n    displayName: 'Current Events',\n  },\n  {\n    name: 'categories/unsplash:towJZFskpGg',\n    displayName: 'People',\n  },\n  {\n    name: 'categories/unsplash:aeu6rL-j6ew',\n    displayName: 'Business & Work',\n  },\n  {\n    name: 'categories/unsplash:J9yrPaHXRQY',\n    displayName: 'Technology',\n  },\n  {\n    name: 'categories/unsplash:Jpg6Kidl-Hk',\n    displayName: 'Animals',\n  },\n  {\n    name: 'categories/unsplash:R_Fyn-Gwtlw',\n    displayName: 'Interiors',\n  },\n  {\n    name: 'categories/unsplash:rnSKDHwwYUk',\n    displayName: 'Architecture',\n  },\n  {\n    name: 'categories/unsplash:xjPR4hlkBGA',\n    displayName: 'Food & Drink',\n  },\n  {\n    name: 'categories/unsplash:Bn-DjrcBrwo',\n    displayName: 'Athletics',\n  },\n  {\n    name: 'categories/unsplash:_8zFHuhRhyo',\n    displayName: 'Spirituality',\n  },\n  {\n    name: 'categories/unsplash:_hb-dl4Q-4U',\n    displayName: 'Health & Wellness',\n  },\n  {\n    name: 'categories/unsplash:hmenvQhUmxM',\n    displayName: 'Film',\n  },\n  {\n    name: 'categories/unsplash:S4MKLAsBB74',\n    displayName: 'Fashion',\n  },\n  {\n    name: 'categories/unsplash:qPYsDzvJOYc',\n    displayName: 'Experimental',\n  },\n];\n\ndescribe('Media3pPane fetching', () => {\n  let fixture;\n  let listMediaSpy;\n  let listCategoriesSpy;\n\n  beforeEach(async () => {\n    localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P, true);\n\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    listMediaSpy = spyOn(apiFetcher, 'listMedia');\n    listCategoriesSpy = spyOn(apiFetcher, 'listCategories');\n\n    mockListMedia();\n    mockListCategories();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  function mockListMedia() {\n    listMediaSpy.and.callFake(({ pageToken, filter }) => {\n      let provider;\n      if (filter.includes('unsplash')) {\n        provider = 'unsplash';\n      } else if (filter.includes('coverr')) {\n        provider = 'coverr';\n      } else {\n        throw Error('Invalid provider in filter: ' + filter);\n      }\n      switch (pageToken) {\n        case undefined:\n          return { media: mediaPage(0, provider), nextPageToken: 'page2' };\n        case 'page2':\n          return { media: mediaPage(1, provider), nextPageToken: undefined };\n        default:\n          throw new Error(`Unexpected pageToken: ${pageToken}`);\n      }\n    });\n  }\n\n  function mockListCategories() {\n    listCategoriesSpy.and.callFake(() => {\n      return {\n        categories,\n      };\n    });\n  }\n\n  async function expectMediaElements(section, expectedCount) {\n    let mediaElements;\n    await waitFor(\n      () => {\n        mediaElements = within(section).queryAllByTestId(/^mediaElement/);\n\n        // Continue waiting if number of elements does not match the expectedCount\n        if (!mediaElements || mediaElements.length !== expectedCount) {\n          throw new Error(\n            `Not ready: ${mediaElements?.length} != ${expectedCount}`\n          );\n        }\n      },\n      { timeout: 5000 }\n    );\n    expect(mediaElements?.length).toBe(expectedCount);\n  }\n\n  async function waitForInitialMediaLoad() {\n    const mediaElements = await within(\n      fixture.editor.library.media3p.unsplashSection\n    ).findAllByTestId(/^mediaElement/, { timeout: 5000 });\n    expect(mediaElements).toBeTruthy();\n  }\n\n  it('should render no results message', async () => {\n    listMediaSpy.and.callFake(() => ({ media: [] }));\n    await fixture.events.click(fixture.editor.library.media3pTab);\n\n    await expect(fixture.screen.findByText(/^No media found.$/)).toBeTruthy();\n\n    await fixture.snapshot();\n  });\n\n  it('should render categories and media resources', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n\n    expectMediaElements(\n      fixture.editor.library.media3p.unsplashSection,\n      MEDIA_PER_PAGE\n    );\n    await fixture.snapshot();\n  });\n\n  it('should arrow navigate between category pills', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n    await fixture.events.focus(fixture.editor.library.media3p.filters[0]);\n    expect(document.activeElement.textContent).toBe('Sustainability');\n\n    await fixture.events.keyboard.press('ArrowRight');\n    expect(document.activeElement.textContent).toBe('Wallpapers');\n\n    await fixture.events.keyboard.press('tab');\n    expect(document.activeElement).toBe(\n      fixture.editor.library.media3p.expandFiltersButton\n    );\n  });\n\n  it('should expand category section on arrow down', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('tab');\n    await fixture.events.keyboard.press('tab');\n    expect(document.activeElement.textContent).toBe('Sustainability');\n\n    await fixture.events.keyboard.press('ArrowDown');\n    expect(\n      fixture.editor.library.media3p.expandFiltersButton.getAttribute(\n        'aria-expanded'\n      )\n    ).toBe('true');\n  });\n\n  it('should fetch 2nd page', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n\n    const mediaGallery = fixture.editor.library.media3p.mediaGallery;\n    await expectMediaElements(\n      fixture.editor.library.media3p.unsplashSection,\n      MEDIA_PER_PAGE\n    );\n\n    mediaGallery.scrollTo(\n      0,\n      mediaGallery.scrollHeight - mediaGallery.clientHeight - ROOT_MARGIN / 2\n    );\n    // Wait for debounce\n    await expectMediaElements(\n      fixture.editor.library.media3p.unsplashSection,\n      MEDIA_PER_PAGE * 2\n    );\n  });\n\n  it('should render the second media provider', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n    await fixture.events.click(fixture.editor.library.media3p.coverrTab);\n\n    const mediaGallery = fixture.editor.library.media3p.mediaGallery;\n    mediaGallery.scrollTo(\n      0,\n      mediaGallery.scrollHeight - mediaGallery.clientHeight - ROOT_MARGIN / 2\n    );\n\n    // Wait for the debounce\n    await expectMediaElements(\n      fixture.editor.library.media3p.coverrSection,\n      // In 1600:1000 the coverr section will fetch again due to screen height\n      // This may fail locally if the viewport is a different size.\n      MEDIA_PER_PAGE * 2\n    );\n  });\n\n  it('should scroll to the top when a category is selected', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n    const mediaGallery = fixture.editor.library.media3p.mediaGallery;\n    await expectMediaElements(\n      fixture.editor.library.media3p.unsplashSection,\n      MEDIA_PER_PAGE\n    );\n\n    mediaGallery.scrollTo(\n      0,\n      mediaGallery.scrollHeight - mediaGallery.clientHeight - ROOT_MARGIN / 2\n    );\n\n    await expectMediaElements(\n      fixture.editor.library.media3p.unsplashSection,\n      MEDIA_PER_PAGE * 2\n    );\n\n    await fixture.events.click(fixture.editor.library.media3p.mediaElements[0]);\n\n    await waitFor(() => {\n      if (mediaGallery.scrollTop !== 0) {\n        throw new Error('still scrolling');\n      }\n      expect(mediaGallery.scrollTop).toBe(0);\n    });\n  });\n  // TODO: https://github.com/googleforcreators/web-stories-wp/issues/10144\n  // eslint-disable-next-line jasmine/no-disabled-tests\n  xit('should have a delay before autoplaying videos', async () => {\n    await fixture.events.click(fixture.editor.library.media3pTab);\n    // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n    await waitForInitialMediaLoad();\n    await fixture.events.click(fixture.editor.library.media3p.coverrTab);\n    //  Wait for the debounce\n    await expectMediaElements(\n      fixture.editor.library.media3p.coverrSection,\n      // In 1600:1000 the coverr section will fetch again due to screen height\n      // This may fail locally if the viewport is a different size.\n      MEDIA_PER_PAGE * 2\n    );\n\n    const firstMediaElement = waitFor(\n      () => fixture.editor.library.media3p.mediaElements[0]\n    );\n\n    expect(firstMediaElement.querySelector('video').paused).toBe(true);\n\n    await fixture.events.focus(firstMediaElement);\n\n    // shouldn't play yet\n    expect(firstMediaElement.querySelector('video').paused).toBe(true);\n\n    // wait for a little and check again\n    await waitFor(() => {\n      if (firstMediaElement.querySelector('video').paused) {\n        throw new Error('wait');\n      }\n\n      expect(firstMediaElement.querySelector('video').paused).toBe(false);\n    });\n  });\n\n  describe('Gallery navigation', () => {\n    it('should handle pressing right and left when focused', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n\n      await fixture.events.keyboard.press('ArrowRight');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(1)\n      );\n\n      await fixture.events.keyboard.press('ArrowLeft');\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n    });\n\n    it('should handle pressing right when at the end of a row', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(1)\n      );\n\n      await fixture.events.keyboard.press('ArrowRight');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(2)\n      );\n    });\n\n    it('should handle pressing right when the last element is focused', async () => {\n      // Only mock 1 page.\n      listMediaSpy.and.callFake(({ pageToken }) => {\n        if (!pageToken) {\n          return { media: mediaPage(1, 'unsplash'), nextPageToken: undefined };\n        }\n        throw new Error(`Unexpected pageToken: ${pageToken}`);\n      });\n\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { mediaElements, unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(\n          mediaElements.length - 1\n        )\n      );\n\n      await fixture.events.keyboard.press('ArrowRight');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(\n          mediaElements.length - 1\n        )\n      );\n    });\n\n    it('should handle pressing left at the beginning of a row', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(2)\n      );\n\n      await fixture.events.keyboard.press('ArrowLeft');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(1)\n      );\n    });\n\n    it('should handle pressing left when the first element is focused', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n\n      await fixture.events.keyboard.press('ArrowLeft');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n    });\n\n    it('should handle pressing down', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(1)\n      );\n\n      await fixture.events.keyboard.press('ArrowDown');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(3)\n      );\n    });\n\n    it('should handle pressing up', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(3)\n      );\n\n      await fixture.events.keyboard.press('ArrowUp');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(1)\n      );\n    });\n\n    it('should handle pressing End and Home', async () => {\n      mockListMedia();\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { unsplashSection } = fixture.editor.library.media3p;\n\n      await expectMediaElements(unsplashSection, MEDIA_PER_PAGE);\n\n      await fixture.events.focus(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n\n      await fixture.events.keyboard.press('End');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex([MEDIA_PER_PAGE - 1])\n      );\n\n      await fixture.events.keyboard.press('Home');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.insertionBtnByIndex(0)\n      );\n    });\n  });\n\n  describe('Provider navigation', () => {\n    it('should handle pressing Right', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      expect(fixture.editor.library.media3p.tabs.length).toBe(4);\n\n      // unsplash section should be visible\n      expect(\n        () => fixture.editor.library.media3p.unsplashSection\n      ).not.toThrow();\n\n      await fixture.events.focus(fixture.editor.library.media3p.tabs[0]);\n\n      await fixture.events.keyboard.press('ArrowRight');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.coverrTab\n      );\n\n      // unsplash section should still be showing\n      expect(\n        () => fixture.editor.library.media3p.unsplashSection\n      ).not.toThrow();\n      expect(() => fixture.editor.library.media3p.coverrSection).toThrow();\n    });\n\n    it('should handle pressing Right when no more providers', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { tabs } = fixture.editor.library.media3p;\n      expect(tabs.length).toBe(4);\n\n      // unsplash section should be visible\n      expect(\n        () => fixture.editor.library.media3p.unsplashSection\n      ).not.toThrow();\n\n      await fixture.events.focus(tabs[tabs.length - 1]);\n\n      await fixture.events.keyboard.press('ArrowRight');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.unsplashTab\n      );\n    });\n\n    it('should handle pressing Left', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { tabs } = fixture.editor.library.media3p;\n      expect(tabs.length).toBe(4);\n\n      // unsplash section should be visible\n      expect(\n        () => fixture.editor.library.media3p.unsplashSection\n      ).not.toThrow();\n\n      await fixture.events.focus(tabs[tabs.length - 1]);\n\n      await fixture.events.keyboard.press('ArrowLeft');\n\n      expect(document.activeElement).toBe(tabs[tabs.length - 2]);\n    });\n\n    it('should handle pressing Left when at the beginning', async () => {\n      await fixture.events.click(fixture.editor.library.media3pTab);\n      // 3p media fetching can take extra time to load, waiting to prevent flakey tests\n      await waitForInitialMediaLoad();\n      const { tabs } = fixture.editor.library.media3p;\n      expect(tabs.length).toBe(4);\n\n      // unsplash section should be visible\n      expect(\n        () => fixture.editor.library.media3p.unsplashSection\n      ).not.toThrow();\n\n      await fixture.events.focus(tabs[0]);\n\n      await fixture.events.keyboard.press('ArrowLeft');\n\n      expect(document.activeElement).toBe(\n        fixture.editor.library.media3p.stickersTab\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/media3pIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction Media3pIcon() {\n  return <Icons.Picture title={__('Explore Media', 'web-stories')} />;\n}\n\nexport default Media3pIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/media3pPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useMemo,\n} from '@googleforcreators/react';\nimport { useFeatures } from 'flagged';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport useMedia from '../../../../../app/media/useMedia';\nimport {\n  PaneHeader,\n  PaneInner,\n  SearchInputContainer,\n  StyledPane,\n} from '../common/styles';\nimport { SearchInput } from '../../../common';\nimport { PROVIDERS } from '../../../../../app/media/media3p/providerConfiguration';\nimport TermsDialog from './termsDialog';\n\nimport paneId from './paneId';\nimport ProviderTabList from './providerTabList';\nimport ProviderPanel from './providerPanel';\n\nconst PaneBottom = styled.div`\n  position: relative;\n  height: 100%;\n  flex: 1 1 auto;\n  min-height: 0;\n`;\n\n/**\n * Pane that contains the media 3P integrations.\n *\n * @param {Object} props Component props\n * @return {*} The media pane element for 3P integrations.\n */\nfunction Media3pPane(props) {\n  const { isActive } = props;\n\n  const {\n    searchTerm,\n    selectedProvider,\n    setSelectedProvider,\n    setSearchTerm,\n    media3p,\n  } = useMedia(\n    ({\n      media3p: {\n        state: { selectedProvider, searchTerm },\n        actions: { setSelectedProvider, setSearchTerm },\n      },\n      media3p,\n    }) => ({\n      searchTerm,\n      selectedProvider,\n      setSelectedProvider,\n      setSearchTerm,\n      media3p,\n    })\n  );\n\n  useEffect(() => {\n    if (isActive && !selectedProvider) {\n      setSelectedProvider({ provider: Object.keys(PROVIDERS)[0] });\n    }\n  }, [isActive, selectedProvider, setSelectedProvider]);\n\n  const selectedCategoryId =\n    media3p[selectedProvider]?.state?.categories?.selectedCategoryId;\n\n  useEffect(() => {\n    if (searchTerm.length) {\n      trackEvent('search', {\n        search_type: 'media3p',\n        search_term: searchTerm,\n        search_filter: selectedProvider,\n        search_category: selectedCategoryId,\n      });\n    }\n  }, [selectedProvider, searchTerm, selectedCategoryId]);\n\n  const onSearch = useCallback(\n    (value) => {\n      const trimText = value.trim();\n      if (trimText !== searchTerm) {\n        setSearchTerm({ searchTerm: trimText });\n      }\n    },\n    [searchTerm, setSearchTerm]\n  );\n\n  const paneBottomRef = useRef();\n\n  const features = useFeatures();\n  const providers = useMemo(\n    () =>\n      Object.keys(PROVIDERS).filter(\n        (p) => !PROVIDERS[p].featureName || features[PROVIDERS[p].featureName]\n      ),\n    [features]\n  );\n\n  // TODO(#2368): handle pagination / infinite scrolling\n  return (\n    <>\n      {isActive && <TermsDialog />}\n      <StyledPane id={paneId} {...props}>\n        <PaneInner>\n          <PaneHeader>\n            <SearchInputContainer>\n              <SearchInput\n                initialValue={searchTerm}\n                placeholder={__('Search', 'web-stories')}\n                onSearch={onSearch}\n                disabled={Boolean(\n                  selectedProvider &&\n                  PROVIDERS[selectedProvider].supportsCategories &&\n                  media3p[selectedProvider]?.state.categories.selectedCategoryId\n                )}\n              />\n            </SearchInputContainer>\n            <ProviderTabList providers={providers} />\n          </PaneHeader>\n          <PaneBottom ref={paneBottomRef}>\n            {providers.map((providerType) => (\n              <ProviderPanel\n                key={providerType}\n                providerType={providerType}\n                isActive={providerType === selectedProvider}\n                searchTerm={searchTerm}\n                role=\"tabpanel\"\n                aria-labelledby={`provider-tab-${providerType}`}\n                id={`provider-tabpanel-${providerType}`}\n              />\n            ))}\n          </PaneBottom>\n        </PaneInner>\n      </StyledPane>\n    </>\n  );\n}\n\nMedia3pPane.propTypes = {\n  isActive: PropTypes.bool,\n};\n\nexport default Media3pPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../../shared';\n\nexport default getPaneId('media3p');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/providerPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { resourceList } from '@googleforcreators/media';\nimport { Headline, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport PaginatedMediaGallery from '../common/paginatedMediaGallery';\nimport useMedia from '../../../../../app/media/useMedia';\nimport { PROVIDERS } from '../../../../../app/media/media3p/providerConfiguration';\nimport useMedia3pApi from '../../../../../app/media/media3p/api/useMedia3pApi';\nimport useLibrary from '../../../useLibrary';\nimport { ChipGroup } from '../../shared';\nimport useLocalMedia from '../../../../../app/media/local/useLocalMedia';\n\nconst MediaSubheading = styled(Headline).attrs(() => ({\n  as: 'h2',\n  size: TextSize.XXSmall,\n}))`\n  margin-top: 24px;\n  padding: 0 24px;\n  ${(props) => props.shouldDisplay || 'display: none;'}\n`;\n\nconst ProviderWrapper = styled.div`\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  min-height: 100px;\n  max-width: 100%;\n  top: 0;\n  left: 0;\n  ${({ hidden }) =>\n    hidden &&\n    css`\n      position: absolute;\n      visibility: hidden;\n    `}\n`;\n\nfunction ProviderPanel({ providerType, isActive, searchTerm, ...rest }) {\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n\n  const {\n    actions: { registerUsage },\n  } = useMedia3pApi();\n\n  const { updateBaseColor } = useLocalMedia(\n    ({ actions: { updateBaseColor } }) => ({\n      updateBaseColor,\n    })\n  );\n\n  /**\n   * If the resource has a register usage url then the fact that it's been\n   * inserted needs to be registered as per API provider policies.\n   *\n   * @param {Object} resource The resource to attempt to register usage.\n   */\n  const handleRegisterUsage = useCallback(\n    (resource) => {\n      if (resource?.attribution?.registerUsageUrl) {\n        registerUsage({\n          registerUsageUrl: resource.attribution.registerUsageUrl,\n        });\n      }\n    },\n    [registerUsage]\n  );\n\n  /**\n   * Insert element such image, video and audio into the editor.\n   *\n   * @param {Object} resource Resource object\n   * @return {null|*} Return onInsert or null.\n   */\n  const insertMediaElement = useCallback(\n    (resource, thumbnailURL) => {\n      resourceList.set(resource.id, {\n        url: thumbnailURL,\n        type: 'cached',\n      });\n      insertElement(resource.type, { resource });\n      handleRegisterUsage(resource);\n\n      if (!resource.baseColor) {\n        updateBaseColor(resource);\n      }\n    },\n    [insertElement, handleRegisterUsage, updateBaseColor]\n  );\n\n  const { media3p } = useMedia(({ media3p }) => ({ media3p }));\n\n  if (!isActive) {\n    return <ProviderWrapper {...rest} hidden />;\n  }\n\n  const state = media3p[providerType].state;\n  const actions = media3p[providerType].actions;\n  const displayName = state.categories.selectedCategoryId\n    ? state.categories.categories.find(\n        (e) => e.id === state.categories.selectedCategoryId\n      ).label\n    : __('Trending', 'web-stories');\n\n  // We display the media name if there's media to display or a category has\n  // been selected.\n  const shouldDisplayMediaSubheading = Boolean(\n    state.media?.length || state.categories.selectedCategoryId\n  );\n  // When displaying search results, subHeading should be updated to reflect so\n  const searchResultsLabel = __('Search Results', 'web-stories');\n\n  return (\n    <ProviderWrapper {...rest}>\n      {PROVIDERS[providerType].supportsCategories && (\n        <ChipGroup\n          items={state.categories.categories}\n          selectedItemId={state.categories.selectedCategoryId}\n          selectItem={actions.selectCategory}\n          deselectItem={actions.deselectCategory}\n        />\n      )}\n      <MediaSubheading\n        data-testid={'media-subheading'}\n        shouldDisplay={shouldDisplayMediaSubheading}\n      >\n        {searchTerm.length && !state.categories.selectedCategoryId\n          ? searchResultsLabel\n          : displayName}\n      </MediaSubheading>\n      <PaginatedMediaGallery\n        providerType={providerType}\n        resources={state.media}\n        isMediaLoading={state.isMediaLoading}\n        isMediaLoaded={state.isMediaLoaded}\n        hasMore={state.hasMore}\n        setNextPage={actions.setNextPage}\n        onInsert={insertMediaElement}\n        searchTerm={searchTerm}\n        selectedCategoryId={state.categories.selectedCategoryId}\n      />\n    </ProviderWrapper>\n  );\n}\n\nProviderPanel.propTypes = {\n  providerType: PropTypes.string.isRequired,\n  isActive: PropTypes.bool.isRequired,\n  searchTerm: PropTypes.string,\n};\n\nexport default ProviderPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/providerTab.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../../../panels/shared/styles';\n\nconst StyledText = styled(Text.Span)`\n  color: inherit;\n`;\n\nconst Tab = styled.button`\n  padding: 6px 16px;\n  background: none;\n  border: none;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  position: relative;\n  cursor: pointer;\n\n  :hover {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n\n  border-radius: ${({ theme }) => theme.borders.radius.x_large};\n  ${focusStyle};\n\n  ${({ $isActive, theme }) =>\n    $isActive &&\n    css`\n      ::after {\n        content: '';\n        position: absolute;\n        background-color: ${theme.colors.border.selection};\n        height: 2px;\n        border-radius: 1px;\n        bottom: -17px;\n        left: 16px;\n        right: 16px;\n      }\n    `}\n`;\n\nfunction ProviderTab({ name, isActive, ...rest }) {\n  return (\n    <Tab $isActive={isActive} {...rest}>\n      <StyledText size={TextSize.Small}>{name}</StyledText>\n    </Tab>\n  );\n}\n\nProviderTab.propTypes = {\n  name: PropTypes.string.isRequired,\n  isActive: PropTypes.bool,\n};\n\nexport default ProviderTab;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/providerTabList.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useMedia from '../../../../../app/media/useMedia';\nimport { useConfig } from '../../../../../app/config';\nimport { PROVIDERS } from '../../../../../app/media/media3p/providerConfiguration';\nimport ProviderTab from './providerTab';\n\nconst Section = styled.div.attrs({ role: 'tablist' })`\n  display: flex;\n  flex-wrap: wrap;\n  margin-top: 16px;\n  margin-bottom: 16px;\n  padding: 0 1em;\n`;\n\nfunction ProviderTabList({ providers }) {\n  const { isRTL } = useConfig();\n  const ref = useRef();\n\n  const { selectedProvider, setSelectedProvider } = useMedia(\n    ({\n      media3p: {\n        state: { selectedProvider },\n        actions: { setSelectedProvider },\n      },\n    }) => ({\n      selectedProvider,\n      setSelectedProvider,\n    })\n  );\n\n  const [focusedIndex, setFocusedIndex] = useState(0);\n\n  const providerCount = providers.length;\n\n  // Whenever selected provider changes, update focused index to that\n  useEffect(\n    () => setFocusedIndex(providers.indexOf(selectedProvider)),\n    [providers, selectedProvider]\n  );\n\n  const focusByIndex = useCallback((newIndex) => {\n    if (!ref.current) {\n      return;\n    }\n    const container = ref.current;\n    const newFocusedTab = container.children[newIndex];\n    newFocusedTab.focus();\n  }, []);\n\n  const selectFocused = useCallback(\n    () => setSelectedProvider({ provider: providers[focusedIndex] }),\n    [focusedIndex, setSelectedProvider, providers]\n  );\n\n  const dir = isRTL ? -1 : 1;\n\n  useKeyDownEffect(\n    ref,\n    'left',\n    () => focusByIndex((focusedIndex - dir + providerCount) % providerCount),\n    [focusByIndex, focusedIndex, dir, providerCount]\n  );\n\n  useKeyDownEffect(\n    ref,\n    'right',\n    () => focusByIndex((focusedIndex + dir + providerCount) % providerCount),\n    [focusByIndex, focusedIndex, dir, providerCount]\n  );\n\n  useKeyDownEffect(ref, 'home', () => focusByIndex(0), [focusByIndex]);\n\n  useKeyDownEffect(ref, 'end', () => focusByIndex(providerCount - 1), [\n    focusByIndex,\n    providerCount,\n  ]);\n\n  useKeyDownEffect(ref, ['enter', 'space'], selectFocused, [selectFocused]);\n\n  return (\n    <Section ref={ref}>\n      {providers.map((providerType, index) => (\n        <ProviderTab\n          key={providerType}\n          index={index}\n          name={PROVIDERS[providerType].displayName}\n          isActive={selectedProvider === providerType}\n          onClick={() => setSelectedProvider({ provider: providerType })}\n          onFocus={() => setFocusedIndex(index)}\n          tabIndex={selectedProvider === providerType ? 0 : -1}\n          role=\"tab\"\n          id={`provider-tab-${providerType}`}\n          aria-controls={`provider-tabpanel-${providerType}`}\n        />\n      ))}\n    </Section>\n  );\n}\n\nProviderTabList.propTypes = {\n  providers: PropTypes.arrayOf(PropTypes.string).isRequired,\n};\n\nexport default ProviderTabList;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/stories/termsDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport TermsDialog from '../termsDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Media Use Terms Notice',\n  component: TermsDialog,\n};\n\nexport const _default = {\n  render: function Render() {\n    return <TermsDialog />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/termsDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState, useCallback } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\nimport {\n  Text,\n  Link,\n  TextSize,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../../../../dialog';\n\nconst TERMS_URL = 'https://wp.stories.google/docs/terms/';\n\nfunction TermsDialog() {\n  const hasAcknowledgedTerms3p = localStore.getItemByKey(\n    LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P\n  );\n\n  const [dialogOpen, setDialogOpen] = useState(!hasAcknowledgedTerms3p);\n\n  const acknowledgeTerms = useCallback(() => {\n    setDialogOpen(false);\n    localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P, true);\n    trackEvent('media3p_terms_acknowledged');\n    setDialogOpen(false);\n  }, []);\n\n  const onTermsClick = useCallback((evt) => {\n    trackClick(evt, 'click_terms_of_service');\n  }, []);\n\n  if (hasAcknowledgedTerms3p) {\n    return null;\n  }\n\n  return (\n    <Dialog\n      isOpen={dialogOpen}\n      contentLabel={__('Third party stock content terms', 'web-stories')}\n      onClose={acknowledgeTerms}\n      ariaHideApp={false}\n      onPrimary={acknowledgeTerms}\n      primaryText={__('Dismiss', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                size={TextSize.Small}\n                href={TERMS_URL}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                aria-label={__(\n                  'Learn more by visiting Web Stories for WordPress',\n                  'web-stories'\n                )}\n                onClick={onTermsClick}\n              />\n            ),\n          }}\n        >\n          {__(\n            'Your use of stock content is subject to third party terms. <a>Learn more.</a>',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nexport default TermsDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/test/accessibility.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport Media3pIcon from '../media3pIcon';\nimport ProviderTab from '../providerTab';\nimport PaginatedMediaGallery from '../../common/paginatedMediaGallery';\nimport { noop } from '../../../../../../utils/noop';\nimport {\n  useCanvas,\n  useCanvasBoundingBox,\n  useLocalMedia,\n} from '../../../../../../app';\n\njest.mock('../../../../../../app/media');\n\njest.mock('../../../../../../app/canvas', () => ({\n  ...jest.requireActual('../../../../../../app/canvas'),\n  useCanvas: jest.fn(),\n  useCanvasBoundingBox: jest.fn(),\n}));\n\nconst mockCanvasContext = {\n  fullbleedContainer: {},\n  nodesById: {},\n  pageContainer: { getBoundingClientRect: () => ({ x: 0, y: 0 }) },\n};\n\nconst RESOURCES = [\n  {\n    alt: 'alt text',\n    attribution: {\n      author: {\n        displayName: 'Maria',\n        url: 'http://maria.com',\n      },\n      registerUsageUrl: '',\n    },\n    creationDate: '1234',\n    height: 353,\n    id: undefined,\n    length: null,\n    lengthFormatted: null,\n    mimeType: 'image/jpeg',\n    poster: null,\n    posterId: null,\n    sizes: {\n      full: {\n        file: 'media/unsplash:1234',\n        sourceUrl: 'http://lala.com',\n        mimeType: 'image/jpeg',\n        width: 530,\n        height: 353,\n      },\n    },\n    src: 'http://lala.com',\n    type: 'image',\n    width: 530,\n  },\n];\n\ndescribe('automated accessibility tests', () => {\n  const mockUseCanvas = useCanvas;\n  const mockUseCanvasBoundingBox = useCanvasBoundingBox;\n\n  beforeEach(() => {\n    mockUseCanvas.mockReturnValue(mockCanvasContext);\n    mockUseCanvasBoundingBox.mockReturnValue({ x: 0, y: 0 });\n    useLocalMedia.mockReturnValue({\n      isCurrentResourceTrimming: jest.fn(),\n      isCurrentResourceMuting: jest.fn(),\n      isCurrentResourceTranscoding: jest.fn(),\n      isCurrentResourceProcessing: jest.fn(),\n      isCurrentResourceUploading: jest.fn(),\n      isNewResourceProcessing: jest.fn(),\n    });\n  });\n  it('should render Media3pIcon without accessibility violations', async () => {\n    const { container } = renderWithTheme(<Media3pIcon />);\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should render ProviderTab without accessibility violations', async () => {\n    const { container } = renderWithTheme(\n      <ProviderTab name=\"jane of ark\" isActive />\n    );\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should render PaginatedMediaGallery without accessibility violations', async () => {\n    const { container } = renderWithTheme(\n      <PaginatedMediaGallery\n        providerType=\"local\"\n        resources={RESOURCES}\n        isMediaLoading={false}\n        isMediaLoaded\n        hasMore\n        onInsert={noop}\n        setNextPage={noop}\n      />\n    );\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/media/media3p/test/media3pPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { fireEvent, screen } from '@testing-library/react';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { createResource } from '@googleforcreators/media';\nimport useLibrary from '../../../../useLibrary';\nimport useConfig from '../../../../../../app/config/useConfig';\nimport useMedia from '../../../../../../app/media/useMedia';\nimport useLocalMedia from '../../../../../../app/media/local/useLocalMedia';\nimport useMedia3pApi from '../../../../../../app/media/media3p/api/useMedia3pApi';\nimport Media3pPane from '../media3pPane';\n\nfunction ProviderAttribution({ index }) {\n  return <span>{`Provider ${index}`}</span>;\n}\n\nProviderAttribution.propTypes = {\n  index: PropTypes.number,\n};\n\njest.mock('../../../../useLibrary');\njest.mock('../../../../../../app/config/useConfig');\njest.mock('../../../../../../app/media/useMedia');\njest.mock('../../../../../../app/media/local/useLocalMedia');\njest.mock('../../../../../../app/media/media3p/api/useMedia3pApi');\njest.mock('../../../shared/libraryMoveable', () => ({\n  __esModule: true,\n  default: jest.fn(() => null),\n}));\n\njest.mock('../../../../../../app/media/media3p/providerConfiguration', () => ({\n  PROVIDERS: {\n    PROVIDER_1: {\n      displayName: 'Provider 1',\n      supportsCategories: true,\n      requiresAuthorAttribution: true,\n      fetchMediaErrorMessage: 'Error loading media from Provider 1',\n      fetchCategoriesErrorMessage: 'Error loading categories from Provider 1',\n    },\n  },\n}));\n\nconst createMediaResource = (id, name, provider) =>\n  createResource({\n    id,\n    name,\n    isExternal: true,\n    baseColor: '#734727',\n    alt: `${name} + ${id}`,\n    provider,\n    src: `http://www.img.com/${id}_1`,\n    width: 480,\n    height: 640,\n    sizes: {\n      full: {\n        sourceUrl: `http://www.img.com/${id}_full`,\n        width: 480,\n        height: 640,\n        mimeType: 'image/png',\n      },\n      large: {\n        sourceUrl: `http://www.img.com/${id}_large`,\n        width: 300,\n        height: 200,\n        mimeType: 'image/png',\n      },\n      thumbnail: {\n        sourceUrl: `http://www.img.com/${id}_thumbnail`,\n        width: 200,\n        height: 100,\n        mimeType: 'image/png',\n      },\n    },\n    type: 'image',\n    mimeType: 'image/png',\n    creationDate: '1234',\n    attribution: {\n      author: {\n        displayName: 'Photographer Name',\n        url: 'https://author.url',\n      },\n      registerUsageUrl: 'https://registerUsageUrl.com/register',\n    },\n  });\n\nconst DEFAULT_PROVIDER_STATE = (index) => ({\n  state: {\n    isMediaLoaded: false,\n    isMediaLoading: false,\n    hasMore: false,\n    media: [],\n    categories: {\n      selectedCategoryId: undefined,\n      categories: [\n        {\n          id: `provider${index}/1`,\n          label: `${index} Dogs`,\n        },\n        {\n          id: `provider${index}/2`,\n          label: `${index} Cats`,\n        },\n      ],\n    },\n  },\n  actions: {\n    selectCategory: jest.fn(),\n    deselectCategory: jest.fn(),\n    setNextPage: jest.fn(),\n  },\n});\n\nconst DEFAULT_USE_MEDIA_RESULT = {\n  searchTerm: '',\n  selectedProvider: 'PROVIDER_1',\n  setSelectedProvider: jest.fn(),\n  setSearchTerm: jest.fn(),\n  media3p: {\n    PROVIDER_1: DEFAULT_PROVIDER_STATE(1),\n  },\n};\n\nconst MEDIA = [];\nfor (let i = 0; i < 10; i++) {\n  MEDIA.push(createMediaResource(i, 'img', 'PROVIDER_1'));\n}\n\n/* eslint-disable testing-library/no-node-access, testing-library/no-container */\n\ndescribe('Media3pPane', () => {\n  const insertElement = jest.fn();\n  const registerUsage = jest.fn();\n  let useMediaResult;\n\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n\n    useConfig.mockImplementation(() => ({\n      capabilities: {\n        hasUploadMediaAction: true,\n      },\n    }));\n    useLibrary.mockImplementation((selector) =>\n      selector({\n        actions: {\n          insertElement: insertElement,\n        },\n      })\n    );\n    useMedia.mockImplementation(() => useMediaResult);\n    useLocalMedia.mockImplementation(() => ({\n      isCurrentResourceMuting: jest.fn(() => false),\n      isCurrentResourceTrimming: jest.fn(() => false),\n      isCurrentResourceTranscoding: jest.fn(() => false),\n      isCurrentResourceProcessing: jest.fn(() => false),\n      isCurrentResourceUploading: jest.fn(() => false),\n    }));\n    useMedia3pApi.mockImplementation(() => ({\n      actions: {\n        registerUsage,\n      },\n    }));\n\n    // https://stackoverflow.com/questions/53271193/typeerror-scrollintoview-is-not-a-function\n    window.HTMLElement.prototype.scrollTo = () => {};\n  });\n\n  beforeEach(() => {\n    useMediaResult = DEFAULT_USE_MEDIA_RESULT;\n  });\n\n  it('should display terms dialog', () => {\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(\n      screen.getByText(\n        /Your use of stock content is subject to third party terms/\n      )\n    ).toBeInTheDocument();\n\n    fireEvent.click(screen.getByRole('button', { name: 'Dismiss' }));\n\n    expect(\n      screen.queryByText(\n        'Your use of stock content is subject to third party terms.'\n      )\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render <Media3pPane /> with no media', () => {\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(screen.queryByText('No media found.')).not.toBeInTheDocument();\n    expect(getComputedStyle(screen.queryByText('Trending')).display).toBe(\n      'none'\n    );\n  });\n\n  it('should render \"No media found\" text once loading is completed', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoading = false;\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(screen.getByText('No media found.')).toBeInTheDocument();\n    expect(getComputedStyle(screen.queryByText('Trending')).display).toBe(\n      'none'\n    );\n  });\n\n  it('should render <Media3pPane /> with no \"Trending\" text while media is being loaded', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = false;\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoading = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = [];\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(getComputedStyle(screen.queryByText('Trending')).display).toBe(\n      'none'\n    );\n  });\n\n  it('should render <Media3pPane /> with the \"Trending\" text while a new page is being loaded', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = false;\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoading = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(getComputedStyle(screen.queryByText('Trending')).display).not.toBe(\n      'none'\n    );\n  });\n\n  it('should render <Media3pPane /> with the \"Trending\" text', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    renderWithTheme(<Media3pPane isActive />);\n\n    expect(getComputedStyle(screen.queryByText('Trending')).display).not.toBe(\n      'none'\n    );\n  });\n\n  it('should render <Media3pPane /> with enabled search when a category is not selected', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    const { container } = renderWithTheme(<Media3pPane isActive />);\n\n    expect(container.querySelector('input')).toBeEnabled();\n  });\n\n  it('should render <Media3pPane /> with the \"Search Results\" text', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    useMediaResult.searchTerm = 'cats';\n    renderWithTheme(<Media3pPane isActive />);\n\n    const subHeading = screen.getByTestId('media-subheading');\n\n    expect(getComputedStyle(subHeading).display).not.toBe('none');\n    expect(subHeading).toHaveTextContent('Search Results');\n  });\n\n  it('should render <Media3pPane /> with disabled search when a category is selected', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    useMediaResult.selectedProvider = 'PROVIDER_1';\n    useMediaResult.media3p.PROVIDER_1.state.categories.selectedCategoryId =\n      'provider1/1';\n    const { container } = renderWithTheme(<Media3pPane isActive />);\n\n    expect(container.querySelector('input')).toBeDisabled();\n  });\n\n  it('should render <Media3pPane /> with the category display name when selected', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    useMediaResult.searchTerm = '';\n    renderWithTheme(<Media3pPane isActive />);\n\n    const subHeading = screen.getByTestId('media-subheading');\n\n    expect(getComputedStyle(subHeading).display).not.toBe('none');\n    expect(subHeading).toHaveTextContent('1 Dogs');\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- TODO: Ensure react-photo-album gallery renders with Jest.\n  it.skip('should register usage when inserting media3p resource', () => {\n    useMediaResult.media3p.PROVIDER_1.state.isMediaLoaded = true;\n    useMediaResult.media3p.PROVIDER_1.state.media = MEDIA;\n    useMediaResult.searchTerm = '';\n    renderWithTheme(<Media3pPane isActive />);\n\n    fireEvent.click(\n      screen.queryAllByRole('button', { name: 'Open insertion menu' })[0]\n    );\n\n    fireEvent.click(screen.getByText(/Insert image/));\n\n    expect(registerUsage).toHaveBeenCalledWith({\n      registerUsageUrl: 'https://registerUsageUrl.com/register',\n    });\n  });\n});\n\n/* eslint-enable testing-library/no-node-access, testing-library/no-container */\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const PAGE_TEMPLATE_TYPES = {\n  cover: { name: __('Cover', 'web-stories') },\n  section: { name: __('Section', 'web-stories') },\n  quote: { name: __('Quote', 'web-stories') },\n  editorial: { name: __('Editorial', 'web-stories') },\n  list: { name: __('List', 'web-stories') },\n  table: { name: __('Table', 'web-stories') },\n  steps: { name: __('Steps', 'web-stories') },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/defaultPageTemplate.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { forwardRef, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { _x, sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonType,\n  TextSize,\n  Text,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport InsertionOverlay from '../shared/insertionOverlay';\nimport { PageTemplateTitleContainer } from '../shared';\nimport { PAGE_TEMPLATE_TYPES } from './constants';\n\nconst PageTemplateWrapper = styled.div``;\n\nconst PageTemplateButton = styled(Button).attrs({ type: ButtonType.Plain })`\n  position: relative;\n  display: block;\n  padding: 0;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  overflow: hidden;\n\n  &:focus-visible {\n    box-shadow: none;\n  }\n\n  &:focus-visible [role='presentation'] {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst TemplateTitleContainer = styled(PageTemplateTitleContainer)`\n  ${PageTemplateButton}:hover &,\n  ${PageTemplateButton}:focus & {\n    opacity: 1;\n  }\n`;\n\nconst PosterImg = styled.img`\n  display: block;\n  width: 100%;\n`;\n\nconst DefaultPageTemplate = forwardRef(\n  ({ page, columnWidth, isActive, onFocus, ...rest }, ref) => {\n    const templateTitle = sprintf(\n      /* translators: 1: template name. 2: page template name. */\n      _x('%1$s %2$s', 'page template title', 'web-stories'),\n      page.title,\n      PAGE_TEMPLATE_TYPES[page.type].name\n    );\n    const [isFocused, setIsFocused] = useState(false);\n\n    return (\n      <PageTemplateWrapper ref={ref} role=\"listitem\">\n        <PageTemplateButton\n          columnWidth={columnWidth}\n          tabIndex={isActive ? 0 : -1}\n          aria-label={templateTitle}\n          onPointerEnter={() => setIsFocused(true)}\n          onPointerLeave={() => setIsFocused(false)}\n          onFocus={() => {\n            setIsFocused(true);\n            onFocus?.();\n          }}\n          onBlur={() => setIsFocused(false)}\n          {...rest}\n        >\n          {page.png && (\n            <PosterImg\n              src={page.png}\n              alt={sprintf(\n                /* translators: 1: page title */\n                __('Snapshot of page template for %1$s', 'web-stories'),\n                page.title\n              )}\n              crossOrigin=\"anonymous\"\n              decoding=\"async\"\n              draggable={false}\n            />\n          )}\n          {isFocused && <InsertionOverlay />}\n          {page.title && (\n            <TemplateTitleContainer>\n              <Text.Span size={TextSize.Small}>{templateTitle}</Text.Span>\n            </TemplateTitleContainer>\n          )}\n        </PageTemplateButton>\n      </PageTemplateWrapper>\n    );\n  }\n);\n\nDefaultPageTemplate.propTypes = {\n  isActive: PropTypes.bool,\n  page: PropTypes.object.isRequired,\n  columnWidth: PropTypes.number.isRequired,\n};\n\nDefaultPageTemplate.displayName = 'DefaultPageTemplate';\n\nexport default DefaultPageTemplate;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/defaultTemplates.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useMemo,\n  useCallback,\n  useRef,\n} from '@googleforcreators/react';\nimport { _x, __ } from '@googleforcreators/i18n';\nimport { getTimeTracker, trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  Text,\n  Headline,\n  LoadingSpinner,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../app/api';\nimport { ChipGroup, LoadingContainer, PANE_PADDING } from '../shared';\nimport { SearchInput } from '../../common';\nimport { virtualPaneContainer } from '../shared/virtualizedPanelGrid';\nimport { PAGE_TEMPLATE_TYPES } from './constants';\nimport TemplateList from './templateList';\n\nconst ActionRow = styled.div`\n  display: flex;\n  justify-content: space-between;\n  margin: 0px 16px 22px 16px;\n`;\n\nconst PageTemplatesParentContainer = styled.div`\n  ${virtualPaneContainer};\n  margin-top: 26px;\n  overflow-x: hidden;\n  overflow-y: scroll;\n`;\n\nconst SearchInputContainer = styled.div`\n  padding: 0 ${PANE_PADDING};\n  margin-bottom: 26px;\n`;\n\nconst Message = styled(Text.Paragraph).attrs({\n  size: TextSize.Medium,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  padding: 1em;\n  text-align: center;\n`;\n\nfunction DefaultTemplates({ pageSize }) {\n  const {\n    actions: { getPageTemplates },\n  } = useAPI();\n  const [pageTemplates, setPageTemplates] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [searchTerm, setSearchTerm] = useState('');\n\n  // load and process pageTemplates\n  useEffect(() => {\n    async function loadPageTemplates() {\n      setIsLoading(true);\n      const trackTiming = getTimeTracker('load_page_templates');\n      setPageTemplates(await getPageTemplates(searchTerm));\n      setIsLoading(false);\n      trackTiming();\n    }\n\n    loadPageTemplates();\n  }, [getPageTemplates, setPageTemplates, searchTerm]);\n\n  const pageTemplatesParentRef = useRef();\n  const [selectedPageTemplateType, setSelectedPageTemplateType] =\n    useState(null);\n\n  const pills = useMemo(\n    () => [\n      { id: null, label: _x('All', 'page templates', 'web-stories') },\n      ...Object.entries(PAGE_TEMPLATE_TYPES).map(([key, { name }]) => ({\n        id: key,\n        label: name,\n      })),\n    ],\n    []\n  );\n\n  const filteredPages = useMemo(\n    () =>\n      pageTemplates.reduce((pages, template) => {\n        const templatePosters = Object.values(template.postersByPage).map(\n          (poster, index) => {\n            return {\n              id: `${template.slug}_${index}`,\n              title: template.title,\n              story: template.pages[index],\n              ...poster,\n            };\n          }\n        );\n\n        const templatePages = templatePosters.reduce((acc, posterByPage) => {\n          // skip unselected page template types if not matching\n          if (\n            !posterByPage.type ||\n            (selectedPageTemplateType &&\n              posterByPage.type !== selectedPageTemplateType)\n          ) {\n            return acc;\n          }\n\n          return [...acc, posterByPage];\n        }, []);\n\n        return [...pages, ...templatePages];\n      }, []),\n    [pageTemplates, selectedPageTemplateType]\n  );\n\n  const handleSelectPageTemplateType = useCallback((key) => {\n    setSelectedPageTemplateType(key);\n    trackEvent('search', {\n      search_type: 'page_templates',\n      search_term: '',\n      search_category: key,\n    });\n  }, []);\n\n  return (\n    <>\n      <SearchInputContainer>\n        <SearchInput\n          initialValue={searchTerm}\n          placeholder={__('Search', 'web-stories')}\n          onSearch={setSearchTerm}\n          disabled={false}\n        />\n      </SearchInputContainer>\n      <ChipGroup\n        items={pills}\n        selectedItemId={selectedPageTemplateType}\n        selectItem={handleSelectPageTemplateType}\n        deselectItem={() => handleSelectPageTemplateType(null)}\n      />\n      {/* tabIndex is required for FireFox bug when using keyboard to navigate from Chips to Template */}\n      <PageTemplatesParentContainer ref={pageTemplatesParentRef} tabIndex={-1}>\n        <ActionRow>\n          <Headline as=\"h2\" size={TextSize.XXXSmall}>\n            {__('Templates', 'web-stories')}\n          </Headline>\n        </ActionRow>\n\n        {/* eslint-disable-next-line react-hooks/refs -- FIXME */}\n        {isLoading || !pageTemplatesParentRef.current ? (\n          <LoadingContainer>\n            <LoadingSpinner animationSize={64} numCircles={8} />\n          </LoadingContainer>\n        ) : pageTemplates.length === 0 ? (\n          <Message>{__('No page templates found.', 'web-stories')}</Message>\n        ) : (\n          <TemplateList\n            pageSize={pageSize}\n            parentRef={pageTemplatesParentRef}\n            pages={filteredPages}\n          />\n        )}\n      </PageTemplatesParentContainer>\n    </>\n  );\n}\n\nDefaultTemplates.propTypes = {\n  pageSize: PropTypes.object.isRequired,\n};\n\nexport default DefaultTemplates;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/deleteDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../../../dialog';\n\n/**\n * Display a confirmation dialog for when a user wants to delete a template.\n *\n * @param {Object} props Component props.\n * @param {Function} props.onClose Callback to toggle dialog display on close.\n * @param {Function} props.onDelete Callback to delete template.\n * @return {null|*} The dialog element.\n */\nfunction DeleteDialog({ onClose, onDelete }) {\n  return (\n    <Dialog\n      isOpen\n      onClose={onClose}\n      title={__('Delete Page Template', 'web-stories')}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={onDelete}\n      primaryText={__('Delete', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'Are you sure you want to delete this template? This action cannot be undone.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nDeleteDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onDelete: PropTypes.func.isRequired,\n};\n\nexport default DeleteDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/dropDownMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useMemo,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  Icons,\n  Menu,\n  Placement,\n  Popup,\n  noop,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ActionButton } from '../shared';\nimport DropDownKeyEvents from '../../../panels/utils/dropDownKeyEvents';\nimport DeleteDialog from './deleteDialog';\nimport NameDialog from './nameDialog';\n\nconst MoreButton = styled(ActionButton)`\n  top: 4px;\n  right: 4px;\n`;\n\nconst DropDownContainer = styled.div`\n  margin-top: 10px;\n`;\n\nconst MenuContainer = styled.div`\n  z-index: 1;\n`;\n\nconst menuStylesOverride = css`\n  min-width: 160px;\n  margin-top: 0;\n  li {\n    display: block;\n  }\n`;\n\nconst MENU_OPTIONS = {\n  RENAME: 'rename',\n  DELETE: 'delete',\n};\n\n/**\n * Get a More icon that displays a dropdown menu on click.\n *\n * @param {Object} props Component props.\n * @param {boolean} props.display Whether the more icon should be displayed.\n * @param {boolean} props.isMenuOpen If the dropdown menu is open.\n * @param {Function} props.onMenuOpen Callback for when menu is opened.\n * @param {Function} props.onMenuCancelled Callback for when menu is closed without any selections.\n * @param {Function} props.onMenuSelected Callback for when menu is closed and an option selected.\n * @param {Function} props.setParentActive Sets the parent element active.\n * @param {Function} props.onDelete Deletes template.\n * @param {Function} props.onUpdateName updates template name.\n * @param {string} props.previousName Previous name of the template.\n * @return {null|*} Element or null if should not display the More icon.\n */\nfunction DropDownMenu({\n  display,\n  isMenuOpen,\n  onMenuOpen,\n  onMenuCancelled,\n  onMenuSelected,\n  setParentActive = noop,\n  onDelete,\n  onUpdateName,\n  previousName,\n}) {\n  const groups = [\n    {\n      options: [\n        {\n          label: __('Rename Template', 'web-stories'),\n          value: MENU_OPTIONS.RENAME,\n        },\n        {\n          label: __('Delete Template', 'web-stories'),\n          value: MENU_OPTIONS.DELETE,\n        },\n      ],\n    },\n  ];\n\n  const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n  const [showRenameDialog, setShowRenameDialog] = useState(false);\n  const moreButtonRef = useRef();\n\n  const onClose = useCallback(() => {\n    onMenuCancelled();\n    moreButtonRef.current?.focus();\n    // Activeness of the parent is lost then due to blurring, we need to set it active \"manually\"\n    // to focus back on the original button.\n    setParentActive();\n  }, [onMenuCancelled, setParentActive]);\n\n  const handleCurrentValue = (evt, value) => {\n    evt.stopPropagation();\n    onMenuSelected();\n    switch (value) {\n      case MENU_OPTIONS.RENAME:\n        setShowRenameDialog(true);\n        break;\n      case MENU_OPTIONS.DELETE:\n        setShowDeleteDialog(true);\n        break;\n      default:\n        break;\n    }\n  };\n\n  // On Delete dialog closing.\n  const onDeleteDialogClose = useCallback(() => {\n    setShowDeleteDialog(false);\n    onClose();\n  }, [setShowDeleteDialog, onClose]);\n\n  // On Rename dialog closing.\n  const onRenameDialogClose = useCallback(() => {\n    setShowRenameDialog(false);\n    onClose();\n  }, [setShowRenameDialog, onClose]);\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const buttonId = useMemo(() => `button-${uuidv4()}`, []);\n\n  // Keep icon and menu displayed if menu is open (even if user's mouse leaves the area).\n  return (\n    <MenuContainer>\n      {/* eslint-disable react-hooks/refs -- FIXME */}\n      {moreButtonRef.current && (\n        <DropDownKeyEvents target={moreButtonRef.current} />\n      )}\n      {/* eslint-enable react-hooks/refs -- FIXME */}\n      <MoreButton\n        ref={moreButtonRef}\n        onClick={onMenuOpen}\n        aria-label={__('More', 'web-stories')}\n        aria-pressed={isMenuOpen}\n        aria-haspopup\n        aria-expanded={isMenuOpen}\n        aria-owns={isMenuOpen ? listId : null}\n        id={buttonId}\n        $display={display}\n        tabIndex={display || isMenuOpen ? 0 : -1}\n      >\n        <Icons.DotsFillSmall />\n      </MoreButton>\n      {(display || isMenuOpen) && (\n        <Popup\n          anchor={moreButtonRef}\n          placement={Placement.BottomStart}\n          isOpen={isMenuOpen}\n        >\n          <DropDownContainer>\n            <Menu\n              parentId={buttonId}\n              listId={listId}\n              handleMenuItemSelect={handleCurrentValue}\n              groups={groups}\n              onDismissMenu={onClose}\n              hasMenuRole\n              menuStylesOverride={menuStylesOverride}\n            />\n          </DropDownContainer>\n        </Popup>\n      )}\n      {showDeleteDialog && (\n        <DeleteDialog onClose={onDeleteDialogClose} onDelete={onDelete} />\n      )}\n      {showRenameDialog && (\n        <NameDialog\n          onClose={onRenameDialogClose}\n          onSave={(name) => {\n            onUpdateName(name);\n            onRenameDialogClose();\n          }}\n          title={__('Rename Page Template', 'web-stories')}\n          placeholder={previousName || __('Untitled', 'web-stories')}\n          previousInput={previousName || ''}\n        />\n      )}\n    </MenuContainer>\n  );\n}\n\nDropDownMenu.propTypes = {\n  display: PropTypes.bool.isRequired,\n  isMenuOpen: PropTypes.bool.isRequired,\n  onMenuOpen: PropTypes.func.isRequired,\n  onMenuCancelled: PropTypes.func.isRequired,\n  onMenuSelected: PropTypes.func.isRequired,\n  onDelete: PropTypes.func.isRequired,\n  onUpdateName: PropTypes.func.isRequired,\n  setParentActive: PropTypes.func,\n  previousName: PropTypes.string,\n};\n\nexport default DropDownMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as PageTemplatesPane } from './pageTemplatesPane';\nexport { default as PageTemplatesIcon } from './pageTemplatesIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/karma/defaultPageTemplates.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma/fixture';\nimport { useStory } from '../../../../../app/story';\nimport formattedTemplatesArray from '../../../../../dataUtils/formattedTemplatesArray';\n\nfunction getComparableElement(fullElement) {\n  const { id, ...partialElement } = fullElement;\n  if (partialElement.isDefaultBackground) {\n    const { backgroundColor, ...defaultBackgroundElement } = partialElement;\n    return defaultBackgroundElement;\n  }\n  return partialElement;\n}\n\nconst expectPageTemplateEqual = (currentPage, template) => {\n  expect(currentPage.id).not.toEqual(template.id);\n  expect(currentPage.elements.length).toEqual(template.elements.length);\n  template.elements.forEach((element, index) => {\n    expect(getComparableElement(currentPage.elements[index])).toEqual(\n      getComparableElement(element)\n    );\n  });\n};\n\ndescribe('CUJ: Page Templates: Creator can Apply a Default Page Template', () => {\n  let fixture;\n  let originalTimeout;\n\n  beforeEach(async () => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;\n    fixture.restore();\n  });\n\n  const expectAllTemplatesLoaded = () => {\n    expect(fixture.screen.getAllByRole('listitem').length).toBe(\n      fixture.editor.library.pageTemplatesPane.pageTemplateButtons.length\n    );\n  };\n\n  describe('Filtering chips', () => {\n    it('should show all filtering chips', async () => {\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n      await waitFor(() => expectAllTemplatesLoaded);\n\n      const filteringList = fixture.screen.getByRole('listbox', {\n        name: 'List of filtering options',\n      });\n\n      const filterOptions = within(filteringList).getAllByRole('option');\n\n      const expectedFilterOptions = [\n        'All',\n        'Cover',\n        'Section',\n        'Quote',\n        'Editorial',\n        'List',\n        'Table',\n        'Steps',\n      ];\n\n      filterOptions.map((option, index) =>\n        expect(option).toHaveTextContent(expectedFilterOptions[index])\n      );\n    });\n\n    it('should filter templates by type', async () => {\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n\n      await waitFor(() => expectAllTemplatesLoaded);\n\n      const filteringList = fixture.screen.getByRole('listbox', {\n        name: 'List of filtering options',\n      });\n\n      const editorialChip = within(filteringList).getByRole('option', {\n        name: 'Editorial',\n      });\n\n      // filter by editorial\n      await fixture.events.click(editorialChip);\n\n      const editorialTemplates = formattedTemplatesArray.flatMap((template) => {\n        return template.pages.filter((page) => {\n          return page.pageTemplateType === 'editorial';\n        });\n      });\n\n      await waitFor(() => {\n        expect(fixture.screen.getAllByRole('listitem').length).toBe(\n          editorialTemplates.length\n        );\n      });\n      // filter back to all by clicking 'editorial' again\n      await fixture.events.click(editorialChip);\n\n      await waitFor(() => expectAllTemplatesLoaded);\n    });\n  });\n\n  describe('Creator can apply a template', () => {\n    it('should add a new page when applying a template', async () => {\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n\n      await waitFor(() => expectAllTemplatesLoaded);\n\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.pageTemplateButton(\n          'Cooking Cover'\n        )\n      );\n\n      // check that all elements have been applied\n      const { pages, currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => {\n          return {\n            currentPage: state.currentPage,\n            pages: state.pages,\n          };\n        })\n      );\n\n      expect(pages.length).toEqual(2);\n      const cookingTemplate = formattedTemplatesArray.find(\n        (t) => t.title === 'Cooking'\n      );\n      const coverPage = cookingTemplate.pages.find(\n        (p) => p.pageTemplateType === 'cover'\n      );\n      expectPageTemplateEqual(currentPage, coverPage);\n\n      await fixture.snapshot('applied page template');\n    });\n\n    it('should apply page template to an empty page using keyboard', async () => {\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n\n      await waitFor(() => expectAllTemplatesLoaded);\n\n      const { pageTemplateButtons } = fixture.editor.library.pageTemplatesPane;\n\n      await fixture.events.focus(pageTemplateButtons[0]);\n\n      await fixture.events.keyboard.press('right');\n\n      await fixture.events.keyboard.press('right');\n\n      const activeTextSetId =\n        pageTemplateButtons[2].getAttribute('data-testid');\n      const documentTestId = document.activeElement.getAttribute('data-testid');\n      expect(activeTextSetId).toBe(documentTestId);\n      await fixture.events.keyboard.press('Enter');\n\n      // check that all elements have been applied\n      const currentPage = await fixture.renderHook(() =>\n        useStory(({ state }) => state.currentPage)\n      );\n      const cookingTemplate = formattedTemplatesArray.find(\n        (t) => t.title === 'Cooking'\n      );\n      const coverPage = cookingTemplate.pages.find(\n        (p) => p.pageTemplateType === 'cover'\n      );\n      expectPageTemplateEqual(currentPage, coverPage);\n    });\n  });\n\n  describe('Keyboard Navigation', () => {\n    it('should navigate templates via keyboard', async () => {\n      // Click templates layout icon\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n\n      await waitFor(() => expectAllTemplatesLoaded);\n\n      // tab to \"Save current page as template\" button\n      await fixture.events.keyboard.press('tab');\n      expect(fixture.editor.library.pageTemplatesPane.saveTemplateBtn).toBe(\n        document.activeElement\n      );\n\n      // tab to default templates dropdown button\n      await fixture.events.keyboard.press('tab');\n      expect(fixture.editor.library.pageTemplatesPane.dropDown).toBe(\n        document.activeElement\n      );\n\n      // tab to search field\n      await fixture.events.keyboard.press('tab');\n\n      // tab to filtering buttons\n      await fixture.events.keyboard.press('tab');\n      // filter templates by \"section\"\n      await fixture.events.keyboard.press('right');\n      await fixture.events.keyboard.press('right');\n      await fixture.events.keyboard.press('Enter');\n\n      await waitFor(\n        () => {\n          // allow filtered templates to be removed from DOM\n          if (fixture.screen.getAllByText(/cover/i).length !== 1) {\n            throw new Error('templates still not filtered');\n          }\n          // expect templates titles to not contain \"cover\", there will still be one filter button containing \"cover\"\n          expect(fixture.screen.getAllByText(/cover/i).length).toBe(1);\n        },\n        { timeout: 5000 }\n      );\n      // navigate to and add \"Fresh & Bright\" template\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('Enter');\n\n      // check that all elements have been applied\n      const { pages, currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => {\n          return {\n            currentPage: state.currentPage,\n            pages: state.pages,\n          };\n        })\n      );\n\n      expect(pages.length).toEqual(2);\n      const cookingTemplate = formattedTemplatesArray.find(\n        (t) => t.title === 'Cooking'\n      );\n      const sectionPage = cookingTemplate.pages.find(\n        (p) => p.pageTemplateType === 'section'\n      );\n\n      expectPageTemplateEqual(currentPage, sectionPage);\n\n      // make next template \"Entertainment Section\" active before leaving template list\n      await fixture.events.keyboard.press('right');\n      await fixture.events.keyboard.press('tab');\n      // expect focus to leave templates\n      expect(\n        fixture.editor.library.pageTemplatesPane.pageTemplates[1]\n      ).not.toBe(document.activeElement);\n\n      // return to template list\n      await fixture.events.keyboard.shortcut('shift+tab');\n      // expect focus to be on last focused element\n      expect(\n        fixture.screen.getByRole('button', { name: 'Entertainment Section' })\n      ).toBe(document.activeElement);\n\n      // return to filters\n      await fixture.events.keyboard.shortcut('shift+tab');\n      await fixture.events.keyboard.shortcut('shift+tab');\n\n      // filter by all\n      await fixture.events.keyboard.press('left');\n      await fixture.events.keyboard.press('left');\n      await fixture.events.keyboard.press('Enter');\n\n      await waitFor(\n        () => {\n          // allow time for previous filtered templates to remount\n          if (fixture.screen.getAllByText(/cover/i).length <= 1) {\n            throw new Error('templates filters still not reset');\n          }\n          // expect template titles to contain \"cover\"\n          expect(\n            fixture.screen.getAllByText(/cover/i).length\n          ).toBeGreaterThanOrEqual(1);\n        },\n        { timeout: 1000 }\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/karma/savedPageTemplates.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma/fixture';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('CUJ: Page Templates: Custom Saved Templates', () => {\n  let fixture;\n  let originalTimeout;\n\n  beforeEach(async () => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;\n    fixture.restore();\n  });\n\n  describe('Saved page templates', () => {\n    const openSavedTemplates = async () => {\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.dropDown\n      );\n      await fixture.events.sleep(500);\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.dropDownOption(\n          'Saved templates'\n        )\n      );\n    };\n\n    it('should allow saving a non-empty page as template', async () => {\n      await openSavedTemplates();\n      // Verify a template is not added for an empty page.\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.saveTemplateBtn\n      );\n\n      expect(\n        () => fixture.editor.library.pageTemplatesPane.pageTemplates.length\n      ).toThrow();\n\n      // Add an element and verify the template is added now.\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      await openSavedTemplates();\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.saveTemplateBtn\n      );\n      await fixture.events.sleep(200);\n\n      await fixture.events.click(\n        fixture.screen.getByPlaceholderText('Untitled')\n      );\n\n      await fixture.events.keyboard.type('Template name');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n\n      const message = fixture.screen.getByRole('alert', { hidden: true });\n      expect(message.textContent).toBe('Page Template saved.');\n\n      expect(\n        fixture.editor.library.pageTemplatesPane.pageTemplates.length\n      ).toBe(1);\n    });\n\n    it('should allow deleting a saved template', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      await openSavedTemplates();\n\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.saveTemplateBtn\n      );\n      await fixture.events.sleep(200);\n\n      await fixture.events.click(\n        fixture.screen.getByPlaceholderText('Untitled')\n      );\n\n      await fixture.events.keyboard.type('Template name');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n\n      expect(\n        fixture.editor.library.pageTemplatesPane.pageTemplates.length\n      ).toBe(1);\n\n      // Hover the added template to reveal the button.\n      await fixture.events.hover(\n        fixture.editor.library.pageTemplatesPane.pageTemplates[0]\n      );\n      await fixture.events.sleep(200);\n      // Expand more dropdown of the first item.\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.moreBtnByIndex(0)\n      );\n\n      await fixture.events.click(\n        fixture.screen.getByRole('menuitem', { name: 'Delete Template' })\n      );\n\n      const dialog = await fixture.screen.findByRole('dialog', {\n        name: 'Delete Page Template',\n        timeout: 9000,\n      });\n\n      const deleteButton = await within(dialog).findByRole('button', {\n        name: 'Delete',\n      });\n\n      await fixture.events.click(deleteButton);\n\n      await fixture.events.sleep(200);\n      const list = fixture.editor.getByRole('list', {\n        name: 'Page Template Options',\n      });\n      expect(list.children.length).toBe(0);\n    });\n\n    it('should allow applying a template', async () => {\n      // Add an element and verify the template is added now.\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      await openSavedTemplates();\n      await fixture.events.click(\n        fixture.editor.library.pageTemplatesPane.saveTemplateBtn\n      );\n      await fixture.events.sleep(200);\n\n      await fixture.events.click(\n        fixture.screen.getByPlaceholderText('Untitled')\n      );\n\n      await fixture.events.keyboard.type('Template name');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n      expect(\n        fixture.editor.library.pageTemplatesPane.pageTemplates.length\n      ).toBe(1);\n\n      const template =\n        fixture.editor.library.pageTemplatesPane.pageTemplates[0];\n      await fixture.events.click(template);\n      await fixture.events.sleep(200);\n      const { pages, currentPage } = await fixture.renderHook(() =>\n        useStory(({ state }) => {\n          return {\n            currentPage: state.currentPage,\n            pages: state.pages,\n          };\n        })\n      );\n\n      expect(pages.length).toEqual(2);\n      // The dummy template has text as the first element.\n      expect(currentPage.elements[1].type).toBe('text');\n    });\n\n    it('should allow manipulating custom templates using keyboard', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n      await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n      // navigate to Save current page a template button and save\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n\n      await fixture.events.click(\n        fixture.screen.getByPlaceholderText('Untitled')\n      );\n\n      await fixture.events.keyboard.type('Template name');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n      const message = fixture.screen.getByRole('alert', { hidden: true });\n      expect(message.textContent).toBe('Page Template saved.');\n\n      // Wait until the page templates list has rendered.\n      await fixture.events.sleep(800);\n\n      expect(\n        fixture.editor.library.pageTemplatesPane.pageTemplates.length\n      ).toBe(1);\n      // navigate to newly saved template and open delete dialog\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('down');\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.sleep(200);\n\n      await waitFor(() => {\n        expect(fixture.screen.getByRole('dialog')).toBeTruthy();\n      });\n      // navigate to delete button, and delete newly created template\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Enter');\n\n      // add time buffer for templates to be removed\n      await fixture.events.sleep(500);\n      // there should no longer be any saved templates\n      await waitFor(() => {\n        expect(\n          () => fixture.editor.library.pageTemplatesPane.pageTemplates\n        ).toThrow();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/nameDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Input } from '@googleforcreators/design-system';\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../../../dialog';\n\nconst InputWrapper = styled.form`\n  margin: 16px 4px;\n  width: 470px;\n  height: 100px;\n`;\n\n/**\n * Display a dialog for when a user wants to rename a template.\n *\n * @param {Object} props Component props.\n * @param {Function} props.onClose Callback to toggle dialog display on close.\n * @param {Function} props.onSave Callback to save template. Template name will be the argument\n * @param {string} props.title Previous name of the template\n * @param {string} props.placeholder Placeholder input text.\n * @param {string} props.previousInput Prefill input text.\n * @return {null|*} The dialog element.\n */\nfunction NameDialog({ onClose, onSave, title, placeholder, previousInput }) {\n  const [templateName, setTemplateName] = useState(previousInput);\n  return (\n    <Dialog\n      isOpen\n      title={title}\n      primaryText={__('Save', 'web-stories')}\n      onPrimary={() => {\n        onSave(templateName);\n      }}\n      secondaryText={__('Cancel', 'web-stories')}\n      onSecondary={onClose}\n      onClose={onClose}\n    >\n      <InputWrapper\n        onSubmit={(e) => {\n          e.preventDefault();\n          onSave(templateName);\n        }}\n      >\n        <Input\n          onChange={(e) => {\n            setTemplateName(e.target.value);\n          }}\n          value={templateName}\n          label={__('Template name', 'web-stories')}\n          placeholder={placeholder}\n          type=\"text\"\n        />\n      </InputWrapper>\n    </Dialog>\n  );\n}\n\nNameDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onSave: PropTypes.func.isRequired,\n  title: PropTypes.string,\n  placeholder: PropTypes.string,\n  previousInput: PropTypes.string,\n};\n\nexport default NameDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/pageTemplatesIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction PageTemplatesIcon() {\n  return (\n    <Icons.Box4Alternate title={__('Page templates library', 'web-stories')} />\n  );\n}\n\nexport default PageTemplatesIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/pageTemplatesPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useMemo,\n  useCallback,\n  useEffect,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { FULLBLEED_RATIO, PAGE_RATIO } from '@googleforcreators/units';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\nimport { DATA_VERSION, migrate } from '@googleforcreators/migration';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { Pane, PANE_PADDING } from '../shared';\nimport { Select } from '../../../form';\nimport { useAPI } from '../../../../app/api';\nimport useLibrary from '../../useLibrary';\nimport { useConfig } from '../../../../app/config';\nimport { SearchInput } from '../../common';\nimport paneId from './paneId';\nimport DefaultTemplates from './defaultTemplates';\nimport SavedTemplates from './savedTemplates';\nimport TemplateSave from './templateSave';\n\nconst SearchInputContainer = styled.div`\n  padding: 0 ${PANE_PADDING};\n  margin-bottom: 26px;\n`;\n\nexport const StyledPane = styled(Pane)`\n  height: 100%;\n  padding: 0;\n  overflow: hidden;\n`;\n\nexport const PaneInner = styled.div`\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n`;\n\nconst DropDownWrapper = styled.div`\n  text-align: left;\n  margin: 28px 16px 17px;\n`;\n\nconst ButtonWrapper = styled.div`\n  padding: 0 1em;\n  margin-top: 24px;\n`;\n\nconst DEFAULT = 'default';\nconst SAVED = 'saved';\nconst PAGE_TEMPLATE_PANE_WIDTH = 158;\nconst LOCAL_STORAGE_KEY =\n  LOCAL_STORAGE_PREFIX.DEFAULT_VIEW_PAGE_TEMPLATE_LAYOUT;\nconst DEFAULT_TEMPLATE_VIEW = localStore.getItemByKey(LOCAL_STORAGE_KEY);\n\nfunction PageTemplatesPane(props) {\n  const {\n    actions: { getCustomPageTemplates },\n  } = useAPI();\n\n  const { canViewDefaultTemplates } = useConfig();\n  const supportsCustomTemplates = Boolean(getCustomPageTemplates);\n\n  const {\n    savedTemplates,\n    setSavedTemplates,\n    nextTemplatesToFetch,\n    setNextTemplatesToFetch,\n  } = useLibrary((state) => ({\n    savedTemplates: state.state.savedTemplates,\n    nextTemplatesToFetch: state.state.nextTemplatesToFetch,\n    setSavedTemplates: state.actions.setSavedTemplates,\n    setNextTemplatesToFetch: state.actions.setNextTemplatesToFetch,\n  }));\n\n  const [showDefaultTemplates, setShowDefaultTemplates] = useState(\n    DEFAULT_TEMPLATE_VIEW === null\n      ? canViewDefaultTemplates\n      : canViewDefaultTemplates && DEFAULT_TEMPLATE_VIEW\n  );\n\n  const [highlightedTemplate, setHighlightedTemplate] = useState(null);\n  const [searchTerm, setSearchTerm] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n\n  const updateTemplatesList = useCallback(\n    (page) => {\n      setSavedTemplates((_savedTemplates) => {\n        return [page, ...(_savedTemplates || [])];\n      });\n      setHighlightedTemplate(page.id);\n      localStore.setItemByKey(LOCAL_STORAGE_KEY, false);\n    },\n    [setSavedTemplates]\n  );\n\n  const loadTemplates = useCallback(async () => {\n    // if nextTemplatesToFetch is false, we must not perform an API call\n    // with page=false.\n    if (!nextTemplatesToFetch) {\n      return;\n    }\n\n    setIsLoading(true);\n    try {\n      const { templates, hasMore } = await getCustomPageTemplates(\n        nextTemplatesToFetch,\n        searchTerm\n      );\n      const updatedTemplates = templates.map(\n        ({ version, templateId, ...page }) => {\n          const template = {\n            pages: [page],\n          };\n\n          // Older page templates unfortunately don't have a version.\n          // This is just a reasonable fallback, as 25 was the data version\n          // when custom page templates were first introduced.\n          const migratedTemplate = migrate(template, version || 25);\n          return {\n            templateId,\n            version: DATA_VERSION,\n            ...migratedTemplate.pages[0],\n          };\n        }\n      );\n      setSavedTemplates((_savedTemplates) => [\n        ...(_savedTemplates || []),\n        ...updatedTemplates,\n      ]);\n\n      if (!hasMore) {\n        setNextTemplatesToFetch(false);\n      } else {\n        setNextTemplatesToFetch(nextTemplatesToFetch + 1);\n      }\n    } catch (err) {\n      trackError('saved_templates', err.message);\n      setNextTemplatesToFetch(false);\n      setSavedTemplates((_savedTemplates) => _savedTemplates ?? []);\n    } finally {\n      setIsLoading(false);\n    }\n  }, [\n    searchTerm,\n    getCustomPageTemplates,\n    nextTemplatesToFetch,\n    setSavedTemplates,\n    setNextTemplatesToFetch,\n  ]);\n\n  const handleSelect = (_, menuItem) => {\n    const value = menuItem === DEFAULT;\n    const shouldSetShowDefaultTemplates = showDefaultTemplates !== value;\n\n    if (shouldSetShowDefaultTemplates) {\n      setShowDefaultTemplates(DEFAULT === menuItem);\n      localStore.setItemByKey(LOCAL_STORAGE_KEY, value);\n    }\n  };\n\n  useEffect(() => {\n    if (!savedTemplates && !showDefaultTemplates) {\n      loadTemplates();\n    }\n  }, [loadTemplates, showDefaultTemplates, savedTemplates]);\n\n  useEffect(() => {\n    let timeout = null;\n    if (highlightedTemplate) {\n      timeout = setTimeout(() => {\n        setHighlightedTemplate(null);\n      }, 1000);\n    }\n    return () => clearTimeout(timeout);\n  }, [highlightedTemplate]);\n\n  const options = [];\n\n  if (canViewDefaultTemplates) {\n    options.push({\n      value: DEFAULT,\n      label: __('Default templates', 'web-stories'),\n    });\n  }\n\n  if (supportsCustomTemplates) {\n    options.push({\n      value: SAVED,\n      label: __('Saved templates', 'web-stories'),\n    });\n  }\n\n  const pageSize = useMemo(() => {\n    const width = PAGE_TEMPLATE_PANE_WIDTH;\n    const height = Math.round(width / PAGE_RATIO);\n    const containerHeight = Math.round(width / FULLBLEED_RATIO);\n    return { width, height, containerHeight };\n  }, []);\n\n  return (\n    <StyledPane id={paneId} {...props}>\n      <PaneInner>\n        <>\n          {supportsCustomTemplates && (\n            <ButtonWrapper>\n              <TemplateSave\n                setShowDefaultTemplates={setShowDefaultTemplates}\n                updateList={updateTemplatesList}\n              />\n            </ButtonWrapper>\n          )}\n          <DropDownWrapper>\n            {options.length > 1 && (\n              <Select\n                options={options}\n                selectedValue={showDefaultTemplates ? DEFAULT : SAVED}\n                onMenuItemClick={handleSelect}\n                aria-label={__('Select templates type', 'web-stories')}\n              />\n            )}\n          </DropDownWrapper>\n        </>\n        {showDefaultTemplates ? (\n          <DefaultTemplates pageSize={pageSize} />\n        ) : (\n          <>\n            <SearchInputContainer>\n              <SearchInput\n                initialValue={searchTerm}\n                placeholder={__('Search', 'web-stories')}\n                onSearch={(str) => {\n                  setSavedTemplates([]);\n                  setNextTemplatesToFetch(1);\n                  setSearchTerm(str);\n                }}\n                disabled={false}\n              />\n            </SearchInputContainer>\n\n            <SavedTemplates\n              pageSize={pageSize}\n              highlightedTemplate={highlightedTemplate}\n              loadTemplates={loadTemplates}\n              isLoading={isLoading}\n            />\n          </>\n        )}\n      </PaneInner>\n    </StyledPane>\n  );\n}\n\nexport default PageTemplatesPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../shared';\n\nexport default getPaneId('pageTemplates');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/savedPageTemplate.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Icons,\n  themeHelpers,\n  Text,\n  TextSize,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  forwardRef,\n  useCallback,\n  useEffect,\n  useFocusOut,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { fetchRemoteBlob, blobToFile } from '@googleforcreators/media';\nimport { trackError } from '@googleforcreators/tracking';\nimport { UnitsProvider } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../app/api';\nimport { useConfig } from '../../../../app/config';\nimport { usePageDataUrls } from '../../../../app/pageDataUrls';\nimport { useUploader } from '../../../../app/uploader';\nimport { PageSizePropType } from '../../../../propTypes';\nimport { focusStyle } from '../../../panels/shared/styles';\nimport DisplayElement from '../../../canvas/displayElement';\nimport InsertionOverlay from '../shared/insertionOverlay';\nimport { ActionButton, PageTemplateTitleContainer } from '../shared';\nimport useRovingTabIndex from '../../../../utils/useRovingTabIndex';\nimport useLibrary from '../../useLibrary';\nimport DropDownMenu from './dropDownMenu';\n\nconst TemplateImage = styled.img`\n  width: 100%;\n  height: auto;\n`;\n\nconst PageTemplateWrapper = styled.div`\n  position: relative;\n  height: ${({ pageSize }) => pageSize.height}px;\n  width: ${({ pageSize }) => pageSize.width}px;\n  cursor: pointer;\n\n  ${({ isHighlighted }) => isHighlighted && themeHelpers.focusCSS};\n  ${focusStyle};\n`;\n\nPageTemplateWrapper.propTypes = {\n  pageSize: PageSizePropType.isRequired,\n};\n\nconst PreviewPageWrapper = styled.button`\n  position: relative;\n  padding: 0;\n  border: 0;\n  height: 100%;\n  width: 100%;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.secondary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  overflow: hidden;\n  ${({ background }) => generatePatternStyles(background)}\n`;\nPreviewPageWrapper.propTypes = {\n  pageSize: PageSizePropType.isRequired,\n};\n\nconst ElementsWrapper = styled.div`\n  z-index: 10;\n`;\n\nconst TemplateInsertionOverlay = styled(InsertionOverlay)`\n  z-index: 11;\n`;\n\nconst TemplateTitleContainer = styled(PageTemplateTitleContainer)`\n  opacity: ${({ isActive }) => (isActive ? 1 : 0)};\n`;\n\n// This is used for nested roving tab index to detect parent siblings.\nconst BUTTON_NESTING_DEPTH = 2;\n\nfunction SavedPageTemplate(\n  { page, pageSize, handleDelete, index, title, highlightedTemplate, onClick },\n  ref\n) {\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const {\n    actions: { updatePageTemplate },\n  } = useAPI();\n  const {\n    actions: { uploadFile },\n  } = useUploader();\n\n  const { showSnackbar } = useSnackbar();\n\n  const { updateSavedTemplate } = useLibrary((state) => ({\n    updateSavedTemplate: state.actions.updateSavedTemplate,\n  }));\n  const queuePageImageGeneration = usePageDataUrls(\n    ({ actions }) => actions.queuePageImageGeneration\n  );\n  const pageDataUrl =\n    usePageDataUrls(({ state: { dataUrls } }) => dataUrls[page.id]) ||\n    page.pregeneratedPageDataUrl;\n  const [isActive, setIsActive] = useState(false);\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n  const onMenuOpen = useCallback((e) => {\n    e.stopPropagation();\n    setIsMenuOpen(true);\n    setIsActive(false);\n  }, []);\n\n  const onMenuCancelled = useCallback(() => {\n    setIsMenuOpen(false);\n    setIsActive(false);\n  }, []);\n\n  const onMenuSelected = useCallback(() => {\n    setIsMenuOpen(false);\n    setIsActive(false);\n  }, []);\n\n  useFocusOut(ref, () => setIsActive(false), []);\n\n  const makeActive = useCallback(() => setIsActive(true), []);\n\n  const makeInactive = useCallback(() => {\n    setIsActive(false);\n  }, []);\n\n  const updateTemplateName = useCallback(\n    async (newName) => {\n      try {\n        const res = await updatePageTemplate(page.templateId, {\n          title: newName,\n        });\n\n        updateSavedTemplate({\n          templateId: page.templateId,\n          title: res.title,\n        });\n        setIsMenuOpen(false);\n        setIsActive(false);\n        showSnackbar({\n          message: __('Page Template renamed.', 'web-stories'),\n          dismissible: true,\n        });\n      } catch {\n        showSnackbar({\n          message: __(\n            'Unable to rename the template. Please try again.',\n            'web-stories'\n          ),\n          dismissible: true,\n        });\n      }\n    },\n    [updatePageTemplate, updateSavedTemplate, page.templateId, showSnackbar]\n  );\n\n  const imageUrl = page.image?.url || pageDataUrl;\n  const shouldPostBlob =\n    hasUploadMediaAction && pageDataUrl && !page.image?.url;\n  useEffect(() => {\n    if (!shouldPostBlob) {\n      return;\n    }\n\n    (async () => {\n      try {\n        const blob = await fetchRemoteBlob(pageDataUrl);\n        const file = blobToFile(\n          blob,\n          `web-stories-page-template-${page.templateId}.jpg`,\n          'image/jpeg'\n        );\n        const resource = await uploadFile(file, {\n          templateId: page.templateId,\n          mediaSource: 'page-template',\n        });\n\n        await updatePageTemplate(page.templateId, {\n          featured_media: resource.id,\n        });\n        updateSavedTemplate({\n          templateId: page.templateId,\n          image: {\n            id: resource.id,\n            height: resource.height,\n            width: resource.width,\n            url: resource.src,\n          },\n        });\n      } catch (err) {\n        // Catch upload errors, e.g. if the file is too large,\n        // so that the page template can still be added, albeit without an image.\n        trackError('upload_generated_page_template_image', err?.message);\n      }\n    })();\n  }, [\n    pageDataUrl,\n    uploadFile,\n    updatePageTemplate,\n    page.templateId,\n    shouldPostBlob,\n    updateSavedTemplate,\n  ]);\n\n  useEffect(() => {\n    // We don't want to go through the work of generating a blob if the user\n    // can't upload it because their machine will have to regenerate it everytime\n    // the page refreshes.\n    if (imageUrl || !hasUploadMediaAction) {\n      return;\n    }\n    queuePageImageGeneration(page);\n  }, [imageUrl, queuePageImageGeneration, page, hasUploadMediaAction]);\n\n  const insertButtonRef = useRef();\n  useRovingTabIndex({ ref: insertButtonRef }, [], BUTTON_NESTING_DEPTH);\n\n  return (\n    <PageTemplateWrapper\n      pageSize={pageSize}\n      role=\"listitem\"\n      ref={ref}\n      onPointerEnter={makeActive}\n      onPointerLeave={makeInactive}\n      aria-label={title}\n      isHighlighted={page.id === highlightedTemplate}\n      onFocus={makeActive}\n      onBlur={makeInactive}\n    >\n      <PreviewPageWrapper\n        pageSize={pageSize}\n        background={page.backgroundColor}\n        onClick={onClick}\n      >\n        {imageUrl ? (\n          <TemplateImage\n            alt={page.image?.alt || __('Saved Page Template', 'web-stories')}\n            src={imageUrl}\n            crossOrigin=\"anonymous\"\n            height={page.image?.height}\n            width={page.image?.height}\n            draggable={false}\n          />\n        ) : (\n          <ElementsWrapper>\n            <UnitsProvider\n              pageSize={{\n                height: pageSize.height,\n                width: pageSize.width,\n              }}\n            >\n              {page.elements.map((element) => (\n                <DisplayElement\n                  key={element.id}\n                  previewMode\n                  element={element}\n                />\n              ))}\n            </UnitsProvider>\n          </ElementsWrapper>\n        )}\n        {isActive && <TemplateInsertionOverlay showIcon={false} />}\n        <TemplateTitleContainer isActive={isActive}>\n          <Text.Span size={TextSize.Small}>\n            {title || __('Untitled', 'web-stories')}\n          </Text.Span>\n        </TemplateTitleContainer>\n      </PreviewPageWrapper>\n      <ActionButton\n        ref={insertButtonRef}\n        onClick={(e) => {\n          e.stopPropagation();\n          onClick(e);\n        }}\n        aria-label={__('Use template', 'web-stories')}\n        $display={isActive}\n        tabIndex={index === 0 ? 0 : -1}\n      >\n        <Icons.PlusFilledSmall />\n      </ActionButton>\n      <DropDownMenu\n        display={isActive}\n        isMenuOpen={isMenuOpen}\n        onMenuOpen={onMenuOpen}\n        onMenuCancelled={onMenuCancelled}\n        onMenuSelected={onMenuSelected}\n        onDelete={() => {\n          handleDelete(page.templateId);\n        }}\n        previousName={title}\n        onUpdateName={updateTemplateName}\n      />\n    </PageTemplateWrapper>\n  );\n}\n\nconst PageTemplateWithRef = forwardRef(SavedPageTemplate);\n\nSavedPageTemplate.propTypes = {\n  page: PropTypes.object.isRequired,\n  pageSize: PageSizePropType.isRequired,\n  handleDelete: PropTypes.func.isRequired,\n  index: PropTypes.number,\n  title: PropTypes.string,\n  highlightedTemplate: PropTypes.object,\n  onClick: PropTypes.func,\n};\n\nSavedPageTemplate.displayName = 'SavedPageTemplate';\n\nexport default PageTemplateWithRef;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/savedTemplates.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { LoadingSpinner, useSnackbar } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useLayoutEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../app/api';\nimport useLibrary from '../../useLibrary';\nimport { LoadingContainer } from '../shared';\nimport TemplateList from './templateList';\n\nconst Wrapper = styled.div`\n  height: 100%;\n  padding-top: 5px;\n  overflow-y: scroll;\n  overflow-x: hidden;\n  min-height: 96px;\n`;\n\nfunction SavedTemplates({\n  searchTerm,\n  setSearchTerm,\n  pageSize,\n  loadTemplates,\n  isLoading,\n  ...rest\n}) {\n  'use no memo';\n\n  const {\n    actions: { deletePageTemplate },\n  } = useAPI();\n\n  const { savedTemplates, setSavedTemplates, nextTemplatesToFetch } =\n    useLibrary((state) => ({\n      savedTemplates: state.state.savedTemplates,\n      nextTemplatesToFetch: state.state.nextTemplatesToFetch,\n      setSavedTemplates: state.actions.setSavedTemplates,\n    }));\n\n  const { showSnackbar } = useSnackbar();\n  const ref = useRef();\n\n  // This is a workaround to force re-rendering for the virtual list to work and the parentRef being assigned correctly.\n  // @todo Look into why does the ref not work as expected otherwise.\n  const [, update] = useState(null);\n  useLayoutEffect(() => {\n    update(false);\n  }, []);\n\n  const fetchTemplates = useCallback(() => {\n    if (!nextTemplatesToFetch) {\n      return;\n    }\n\n    loadTemplates();\n  }, [nextTemplatesToFetch, loadTemplates]);\n\n  const handleDelete = useCallback(\n    async (id) => {\n      try {\n        await deletePageTemplate(id);\n        setSavedTemplates(\n          savedTemplates.filter(({ templateId }) => templateId !== id)\n        );\n        showSnackbar({\n          message: __('Page Template deleted.', 'web-stories'),\n          dismissable: true,\n        });\n      } catch {\n        showSnackbar({\n          message: __(\n            'Unable to delete the template. Please try again.',\n            'web-stories'\n          ),\n          dismissible: true,\n        });\n      }\n    },\n    [deletePageTemplate, savedTemplates, showSnackbar, setSavedTemplates]\n  );\n\n  return (\n    // tabIndex is required for FireFox bug when using keyboard to navigate from Saved / Default Templates dropdown to Template\n    <Wrapper ref={ref} tabIndex={-1}>\n      {/* eslint-disable-next-line react-hooks/refs -- FIXME */}\n      {!isLoading && ref.current ? (\n        <TemplateList\n          parentRef={ref}\n          pageSize={pageSize}\n          pages={savedTemplates}\n          handleDelete={handleDelete}\n          fetchTemplates={fetchTemplates}\n          {...rest}\n        />\n      ) : (\n        <LoadingContainer>\n          <LoadingSpinner animationSize={64} numCircles={8} />\n        </LoadingContainer>\n      )}\n    </Wrapper>\n  );\n}\n\nSavedTemplates.propTypes = {\n  searchTerm: PropTypes.string,\n  setSearchTerm: PropTypes.func,\n  pageSize: PropTypes.object.isRequired,\n  loadTemplates: PropTypes.func.isRequired,\n  isLoading: PropTypes.bool,\n};\n\nexport default SavedTemplates;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/templateList.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useGridViewKeys, useSnackbar } from '@googleforcreators/design-system';\nimport { duplicatePage } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { PANE_PADDING } from '../shared';\nimport { useStory } from '../../../../app/story';\nimport { useConfig } from '../../../../app/config';\n\nimport DefaultPageTemplate from './defaultPageTemplate';\nimport SavedPageTemplate from './savedPageTemplate';\n\nconst WrapperGrid = styled.div`\n  display: grid;\n  width: 100%;\n  margin-left: ${PANE_PADDING};\n  margin-bottom: 12px;\n  gap: 12px;\n  grid-template-columns: ${({ columnWidth }) =>\n    `repeat(auto-fit, ${columnWidth}px)`};\n  grid-template-rows: ${({ rowHeight }) =>\n    `repeat(minmax(${rowHeight}px, 1fr))`};\n`;\n\nfunction TemplateList({\n  pages,\n  parentRef,\n  pageSize,\n  handleDelete,\n  fetchTemplates,\n  ...rest\n}) {\n  const { addPage } = useStory(({ actions }) => ({\n    addPage: actions.addPage,\n  }));\n  const { isRTL } = useConfig();\n  const { showSnackbar } = useSnackbar();\n  const [currentPageId, setCurrentPageId] = useState();\n  const containerRef = useRef();\n  const pagesRef = useRef({});\n\n  const handlePageClick = useCallback(\n    ({ templateId, version, title, ...page }) => {\n      // Just using destructuring above so we don't pass unnecessary props to addPage().\n      const duplicatedPage = duplicatePage(page);\n      addPage({ page: duplicatedPage });\n      trackEvent('insert_page_template', {\n        name: title || 'custom', // Custom page templates don't have titles (yet).\n      });\n      showSnackbar({\n        message: __('Page Template added.', 'web-stories'),\n        dismissible: true,\n      });\n    },\n    [addPage, showSnackbar]\n  );\n\n  const handleFocus = useCallback((id) => {\n    setCurrentPageId(id);\n  }, []);\n\n  const isSavedTemplates = handleDelete || fetchTemplates;\n\n  useEffect(() => {\n    if (pages.length > 0) {\n      // Set `currentPageId` to first item during initial load, or if we have filtered pages by type\n      // since the previous `currentPageId` may no longer be present.\n      if (!currentPageId || !pages.some((page) => page.id === currentPageId)) {\n        setCurrentPageId(pages[0].id);\n      }\n    }\n  }, [currentPageId, pages]);\n\n  useEffect(() => {\n    fetchTemplates?.();\n  }, [fetchTemplates]);\n\n  useGridViewKeys({\n    containerRef: parentRef,\n    gridRef: containerRef,\n    itemRefs: pagesRef,\n    items: pages,\n    currentItemId: currentPageId,\n    isRTL,\n  });\n\n  return (\n    <WrapperGrid\n      ref={containerRef}\n      columnWidth={pageSize.width}\n      rowHeight={pageSize.containerHeight}\n      role=\"list\"\n      aria-label={__('Page Template Options', 'web-stories')}\n    >\n      {isSavedTemplates\n        ? pages.map((page, index) => (\n            <SavedPageTemplate\n              key={page.id}\n              data-testid={`page_template_${page.id}`}\n              ref={(el) => (pagesRef.current[page.id] = el)}\n              page={page}\n              pageSize={pageSize}\n              onClick={() => handlePageClick(page)}\n              handleDelete={handleDelete}\n              onFocus={() => handleFocus(page.id)}\n              index={index}\n              title={page?.title?.raw}\n              {...rest}\n            />\n          ))\n        : pages.map((page) => (\n            <DefaultPageTemplate\n              ref={(el) => (pagesRef.current[page.id] = el)}\n              key={page.id}\n              data-testid={`page_template_${page.id}`}\n              page={page}\n              pageSize={pageSize}\n              onFocus={() => handleFocus(page.id)}\n              isActive={currentPageId === page.id}\n              onClick={() => handlePageClick(page.story)}\n              columnWidth={pageSize.width}\n              {...rest}\n            />\n          ))}\n    </WrapperGrid>\n  );\n}\n\nTemplateList.propTypes = {\n  parentRef: PropTypes.object.isRequired,\n  pages: PropTypes.arrayOf(\n    PropTypes.shape({\n      id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,\n    })\n  ),\n  pageSize: PropTypes.object.isRequired,\n  handleDelete: PropTypes.func,\n  fetchTemplates: PropTypes.func,\n};\n\nexport default TemplateList;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/pageTemplates/templateSave.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport {\n  BUTTON_TRANSITION_TIMING,\n  TextSize,\n  Text,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport { v4 as uuidv4 } from 'uuid';\nimport { DATA_VERSION } from '@googleforcreators/migration';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../../../app/api';\nimport { usePageCanvas } from '../../../../app/pageCanvas';\nimport { useStory } from '../../../../app/story';\nimport { focusStyle } from '../../../panels/shared/styles';\nimport isDefaultPage from '../../../../utils/isDefaultPage';\nimport createThumbnailCanvasFromFullbleedCanvas from '../../../../utils/createThumbnailCanvasFromFullbleedCanvas';\nimport Icon from './images/illustration.svg';\nimport NameDialog from './nameDialog';\n\nconst StyledText = styled(Text.Span)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst IconWrapper = styled.div`\n  width: 32px;\n  height: 42px;\n  margin-right: 29px;\n`;\n\nconst SaveButton = styled.button`\n  border: 0;\n  background: none;\n  height: 56px;\n  width: 100%;\n  padding: 7px;\n  background-color: ${({ theme }) =>\n    theme.colors.interactiveBg.secondaryNormal};\n  transition: background-color ${BUTTON_TRANSITION_TIMING};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  cursor: pointer;\n\n  &:hover {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.secondaryHover};\n  }\n\n  ${({ $isDisabled, theme }) =>\n    $isDisabled &&\n    `\n      cursor: default;\n      background-color: ${theme.colors.interactiveBg.disable};\n      &:hover {\n        background-color: ${theme.colors.interactiveBg.disable};\n      }\n\n      ${IconWrapper} svg {\n        path:nth-child(1): ${theme.colors.fg.disable};\n        path:nth-child(2) {\n          fill: ${theme.colors.fg.tertiary};\n        }\n        path:nth-child(3) {\n          fill: ${theme.colors.fg.secondary};\n        }\n      }\n\n      ${StyledText} {\n        color: ${theme.colors.fg.disable};\n      }\n  `}\n\n  ${focusStyle};\n`;\nfunction TemplateSave({ setShowDefaultTemplates, updateList }) {\n  const {\n    actions: { addPageTemplate },\n  } = useAPI();\n  const { showSnackbar } = useSnackbar();\n\n  const { currentPage } = useStory(({ state: { currentPage } }) => ({\n    currentPage,\n  }));\n  const pageCanvasMap = usePageCanvas(({ state }) => state.pageCanvasMap);\n\n  const isDisabled = useMemo(\n    () => currentPage && isDefaultPage(currentPage),\n    [currentPage]\n  );\n\n  const [isDialogOpen, setIsDialogOpen] = useState(false);\n\n  const handleSaveTemplate = useCallback(\n    async (templateName) => {\n      if (isDisabled) {\n        return;\n      }\n\n      let tmpPageDataUrl;\n      const currentPageCanvas = pageCanvasMap[currentPage.id];\n      if (currentPageCanvas) {\n        const thumbnailCanvas =\n          createThumbnailCanvasFromFullbleedCanvas(currentPageCanvas);\n        tmpPageDataUrl = thumbnailCanvas.toDataURL('image/jpeg');\n      }\n\n      try {\n        const { templateId, ...page } = currentPage;\n        const addedTemplate = await addPageTemplate({\n          story_data: {\n            ...page,\n            id: uuidv4(),\n            version: DATA_VERSION,\n          },\n          featured_media: undefined,\n          title:\n            templateName !== '' ? templateName : __('Untitled', 'web-stories'),\n        });\n\n        // If we already have a data url for the page template, we'll\n        // pass it here and the <SavedPageTemplate /> component can be responsible\n        // for creating a resource from it on the WP backend and associating\n        // that resource with the template post\n        if (tmpPageDataUrl) {\n          addedTemplate.pregeneratedPageDataUrl = tmpPageDataUrl;\n        }\n\n        updateList?.(addedTemplate);\n        showSnackbar({\n          message: __('Page Template saved.', 'web-stories'),\n          dismissable: true,\n        });\n      } catch {\n        showSnackbar({\n          message: __(\n            'Unable to save the template. Please try again.',\n            'web-stories'\n          ),\n          dismissable: true,\n        });\n      }\n\n      setShowDefaultTemplates(false);\n      setIsDialogOpen(false);\n    },\n    [\n      isDisabled,\n      addPageTemplate,\n      currentPage,\n      setShowDefaultTemplates,\n      showSnackbar,\n      updateList,\n      pageCanvasMap,\n    ]\n  );\n\n  return (\n    <>\n      <SaveButton\n        aria-disabled={isDisabled}\n        onClick={() => {\n          if (!isDisabled) {\n            setIsDialogOpen(true);\n          }\n        }}\n        $isDisabled={isDisabled}\n      >\n        <IconWrapper>\n          <Icon aria-hidden />\n        </IconWrapper>\n        <StyledText size={TextSize.Small}>\n          {__('Save current page as template', 'web-stories')}\n        </StyledText>\n      </SaveButton>\n      {isDialogOpen && (\n        <NameDialog\n          onClose={() => {\n            setIsDialogOpen(false);\n          }}\n          onSave={async (templateName) => {\n            await handleSaveTemplate(templateName);\n            setIsDialogOpen(false);\n          }}\n          title={__('Save Page Template', 'web-stories')}\n          placeholder={__('Untitled', 'web-stories')}\n          previousInput={''}\n        />\n      )}\n    </>\n  );\n}\n\nTemplateSave.propTypes = {\n  setShowDefaultTemplates: PropTypes.func.isRequired,\n  updateList: PropTypes.func,\n};\n\nexport default TemplateSave;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as ShapesPane } from './shapesPane';\nexport { default as ShapesIcon } from './shapesIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../shared';\n\nexport default getPaneId('shapes');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/shapePreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  createRef,\n  useCallback,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { PAGE_WIDTH, useUnits } from '@googleforcreators/units';\nimport { themeHelpers } from '@googleforcreators/design-system';\nimport { MaskTypes } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport useLibrary from '../../useLibrary';\nimport LibraryMoveable from '../shared/libraryMoveable';\nimport InsertionOverlay from '../shared/insertionOverlay';\n\n// By default, the element should be 33% of the page.\nexport const DEFAULT_ELEMENT_WIDTH = PAGE_WIDTH / 3;\nconst PREVIEW_SIZE = 36;\n\nconst Aspect = styled.button`\n  background: transparent;\n  outline: none;\n  border: 0;\n  padding: 0;\n  position: relative;\n\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  background-color: ${({ theme }) => theme.colors.interactiveBg.previewOverlay};\n\n  &:focus-visible [role='presentation'] {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst AspectInner = styled.div`\n  position: relative;\n  padding-bottom: 95.5%;\n`;\n\nconst ShapePreviewContainer = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  height: 100%;\n  width: 100%;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  display: flex;\n  justify-content: center;\n  align-items: center;\n\n  svg {\n    display: inline-block;\n    width: 36px;\n    height: 36px;\n  }\n`;\n\nconst ShapeClone = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0;\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n  svg {\n    display: inline-block;\n    width: 100%;\n    height: 100%;\n    path {\n      fill: #c4c4c4;\n    }\n  }\n`;\n\nconst ShapePreviewSizer = styled.div`\n  padding-top: 100%;\n`;\n\nconst Path = styled.path`\n  fill: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nfunction ShapePreview({ mask, isPreview, index }) {\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n  const { dataToEditorX, dataToEditorY } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n    dataToEditorY: state.actions.dataToEditorY,\n  }));\n\n  const [active, setActive] = useState(false);\n  const makeActive = () => setActive(true);\n  const makeInactive = () => setActive(false);\n\n  const ref = useRef();\n  // Creating a ref to the Path so that it can be used as a drag icon.\n  // This avoids the drag image that follows the cursor from being the whole\n  // component with large paddings, and only drags the svg part of it.\n  const pathRef = createRef();\n\n  // Contains the data to be passed in for insertElement() calls in order\n  // to insert the correct shape.\n  const shapeData = useMemo(\n    () => ({\n      backgroundColor: createSolidFromString('#c4c4c4'),\n      width: DEFAULT_ELEMENT_WIDTH * mask.ratio,\n      height: DEFAULT_ELEMENT_WIDTH,\n      mask: {\n        type: mask.type,\n      },\n      // Rectangles have unlocked aspect ratio by default.\n      lockAspectRatio: MaskTypes.RECTANGLE !== mask.type,\n    }),\n    [mask.ratio, mask.type]\n  );\n\n  const onClick = useCallback(() => {\n    // Shapes inserted with a specific size.\n    insertElement('shape', shapeData);\n    trackEvent('insert_shape', { name: mask.type });\n  }, [insertElement, shapeData, mask.type]);\n\n  const getSVG = (displayLabel = true) => {\n    return (\n      <svg\n        viewBox={`0 0 1 ${\n          1 / (isPreview && mask.iconRatio ? mask.iconRatio : mask.ratio)\n        }`}\n        width={\n          PREVIEW_SIZE *\n          (isPreview && mask.iconRatio ? mask.iconRatio : mask.ratio)\n        }\n        height={PREVIEW_SIZE}\n      >\n        {displayLabel && <title>{mask.name}</title>}\n        <Path\n          d={isPreview && mask.iconPath ? mask.iconPath : mask.path}\n          ref={pathRef}\n        />\n      </svg>\n    );\n  };\n\n  // We use rovingTabIndex for navigating so only the first item will have 0 as tabIndex.\n  // onClick on Aspect is for the keyboard only.\n  return (\n    <Aspect\n      ref={ref}\n      onClick={onClick}\n      tabIndex={index === 0 ? 0 : -1}\n      aria-label={mask.name}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n    >\n      <AspectInner>\n        <ShapePreviewContainer key={mask.type}>\n          <ShapePreviewSizer />\n          {getSVG()}\n        </ShapePreviewContainer>\n        {active && <InsertionOverlay />}\n      </AspectInner>\n      <LibraryMoveable\n        type={'shape'}\n        elementProps={shapeData}\n        cloneElement={ShapeClone}\n        onClick={onClick}\n        cloneProps={{\n          width: dataToEditorX(DEFAULT_ELEMENT_WIDTH * mask.ratio),\n          height: dataToEditorY(DEFAULT_ELEMENT_WIDTH),\n          children: getSVG(false),\n        }}\n      />\n    </Aspect>\n  );\n}\nShapePreview.propTypes = {\n  mask: PropTypes.object.isRequired,\n  isPreview: PropTypes.bool,\n  index: PropTypes.number,\n};\n\nexport default ShapePreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/shapesIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction ShapesIcon() {\n  return <Icons.Shapes title={__('Shapes library', 'web-stories')} />;\n}\n\nexport default ShapesIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/shapesPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useRef } from '@googleforcreators/react';\nimport STICKERS from '@googleforcreators/stickers';\nimport { MASKS } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { Section } from '../../common';\nimport { Pane } from '../shared';\nimport useRovingTabIndex from '../../../../utils/useRovingTabIndex';\nimport ShapePreview from './shapePreview';\nimport StickerPreview from './stickerPreview';\nimport paneId from './paneId';\n\nconst SectionContent = styled.div`\n  position: relative;\n\n  display: grid;\n  grid-column-gap: 12px;\n  grid-row-gap: 24px;\n  @media screen and (min-width: 1220px) {\n    grid-template-columns: repeat(4, 1fr);\n  }\n  @media screen and (min-width: 1100px) and (max-width: 1220px) {\n    grid-template-columns: repeat(3, 1fr);\n  }\n  @media screen and (max-width: 1100px) {\n    grid-template-columns: repeat(2, 1fr);\n  }\n`;\n\nconst STICKER_TYPES = Object.keys(STICKERS);\n\nfunction ShapesPane(props) {\n  const sectionRef = useRef();\n  useRovingTabIndex({ ref: sectionRef });\n\n  const stickersRef = useRef(null);\n  useRovingTabIndex({ ref: stickersRef });\n\n  return (\n    <Pane id={paneId} {...props} isOverflowScrollable>\n      <Section\n        data-testid=\"shapes-library-pane\"\n        title={__('Shapes', 'web-stories')}\n      >\n        <SectionContent ref={sectionRef}>\n          {MASKS.filter((mask) => mask.showInLibrary).map((mask, i) => (\n            <ShapePreview mask={mask} key={mask.type} index={i} isPreview />\n          ))}\n        </SectionContent>\n      </Section>\n      <Section\n        data-testid=\"stickers-library-pane\"\n        title={__('Stickers', 'web-stories')}\n      >\n        <SectionContent ref={stickersRef}>\n          {STICKER_TYPES.map((stickerType, i) => (\n            <StickerPreview\n              key={stickerType}\n              index={i}\n              stickerType={stickerType}\n            />\n          ))}\n        </SectionContent>\n      </Section>\n    </Pane>\n  );\n}\n\nexport default ShapesPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shapes/stickerPreview.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport STICKERS from '@googleforcreators/stickers';\nimport {\n  Button,\n  ButtonSize,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { useUnits } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport useLibrary from '../../useLibrary';\nimport LibraryMoveable from '../shared/libraryMoveable';\nimport InsertionOverlay from '../shared/insertionOverlay';\nimport { DEFAULT_ELEMENT_WIDTH } from './shapePreview';\n\nconst StickerButton = styled(Button).attrs({\n  size: ButtonSize.Small,\n})`\n  position: relative;\n  padding: 0 0 95.5% 0;\n  margin: 0;\n  height: 60px;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.previewOverlay};\n\n  &:focus-visible {\n    box-shadow: none;\n  }\n\n  &:focus-visible [role='presentation'] {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst StickerInner = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  height: 100%;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\nconst StickerClone = styled.div`\n  position: absolute;\n  top: 0;\n  left: 0;\n  opacity: 0;\n  width: ${({ width }) => `${width}px`};\n  height: ${({ height }) => `${height}px`};\n`;\n\nfunction StickerPreview({ stickerType, index }) {\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n\n  const { dataToEditorX, dataToEditorY } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n    dataToEditorY: state.actions.dataToEditorY,\n  }));\n\n  const sticker = STICKERS[stickerType];\n  const aspectRatio = sticker.aspectRatio;\n  const stickerData = useMemo(\n    () => ({\n      width: DEFAULT_ELEMENT_WIDTH * aspectRatio,\n      height: DEFAULT_ELEMENT_WIDTH,\n      sticker: {\n        type: stickerType,\n      },\n    }),\n    [aspectRatio, stickerType]\n  );\n\n  const [isActive, setIsActive] = useState(false);\n  const makeActive = () => setIsActive(true);\n  const makeInactive = () => setIsActive(false);\n\n  const onClick = () =>\n    insertElement('sticker', {\n      width: DEFAULT_ELEMENT_WIDTH,\n      sticker: { type: stickerType },\n    });\n\n  const Svg = sticker.svg;\n  return (\n    <StickerButton\n      data-testid={`library-sticker-${stickerType}`}\n      onClick={onClick}\n      tabIndex={index === 0 ? 0 : -1}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n    >\n      <StickerInner>\n        <Svg\n          style={{\n            height: aspectRatio < 0.955 ? '60%' : 'auto',\n            width: aspectRatio < 0.955 ? 'auto' : '60%',\n          }}\n        />\n        {isActive && <InsertionOverlay />}\n        <LibraryMoveable\n          type={'sticker'}\n          elementProps={stickerData}\n          cloneElement={StickerClone}\n          onClick={onClick}\n          cloneProps={{\n            width: dataToEditorX(\n              DEFAULT_ELEMENT_WIDTH * (aspectRatio < 1 ? aspectRatio : 1)\n            ),\n            height: dataToEditorY(\n              DEFAULT_ELEMENT_WIDTH / (aspectRatio < 1 ? 1 : aspectRatio)\n            ),\n            children: (\n              <Svg\n                style={{\n                  height: 'auto',\n                  width: '100%',\n                }}\n              />\n            ),\n          }}\n        />\n      </StickerInner>\n    </StickerButton>\n  );\n}\n\nStickerPreview.propTypes = {\n  stickerType: PropTypes.oneOf(Object.keys(STICKERS)).isRequired,\n  index: PropTypes.number,\n};\n\nexport default StickerPreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/chipGroup/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const FOCUS_BORDER_SPACING = 4;\nexport const CHIP_HEIGHT = 36 + FOCUS_BORDER_SPACING * 2; // Chip height + focus box-shadow spacing\nexport const CHIP_TOP_MARGIN = 16;\nexport const CHIP_BOTTOM_MARGIN = 20;\nexport const CHIP_COLLAPSED_FULL_HEIGHT =\n  CHIP_HEIGHT + CHIP_TOP_MARGIN + CHIP_BOTTOM_MARGIN;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/chipGroup/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Chip,\n  Icons,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useRovingTabIndex from '../../../../../utils/useRovingTabIndex';\nimport { useExpandAnimation, useHandleRowVisibility } from '../hooks';\nimport {\n  CHIP_COLLAPSED_FULL_HEIGHT,\n  CHIP_BOTTOM_MARGIN,\n  CHIP_TOP_MARGIN,\n  FOCUS_BORDER_SPACING,\n} from './constants';\n\nconst Section = styled.div`\n  height: ${CHIP_COLLAPSED_FULL_HEIGHT}px;\n  min-height: ${CHIP_COLLAPSED_FULL_HEIGHT}px;\n  background-color: ${({ theme }) => theme.colors.divider.tertiary};\n  display: flex;\n  flex-direction: column;\n  align-items: flex-start;\n  flex: 0 1 auto;\n  position: relative;\n  transition:\n    height 0.2s,\n    min-height 0.2s;\n`;\n\n// This hides the pills unless expanded\nconst Container = styled.div`\n  overflow: hidden;\n  margin: ${CHIP_TOP_MARGIN}px 12px ${CHIP_BOTTOM_MARGIN}px 24px;\n`;\n\nconst InnerContainer = styled.div`\n  display: flex;\n  justify-content: center;\n  flex-wrap: wrap;\n  position: relative;\n  padding: 4px 0;\n  transition: transform 0.2s;\n  column-gap: 8px;\n  row-gap: 14px;\n`;\n\n// Flips the button upside down when expanded;\n// Important: the visibility is 'inherit' when props.visible because otherwise\n// it gets shown even when the provider is not the selectedProvider!\nconst ExpandButton = styled(Button).attrs({\n  type: ButtonType.Tertiary,\n  size: ButtonSize.Small,\n  variant: ButtonVariant.Circle,\n})`\n  display: flex;\n  position: absolute;\n  bottom: -24px;\n  background: ${({ theme }) => theme.colors.bg.tertiary};\n  max-height: none;\n  width: 32px;\n  height: 32px;\n  ${({ isExpanded }) => isExpanded && 'transform: scaleY(-1);'}\n  visibility: inherit;\n  align-self: center;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst ChipGroup = ({\n  items,\n  selectedItemId,\n  selectItem,\n  deselectItem,\n  ariaLabel,\n}) => {\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  const sectionRef = useRef();\n  const innerContainerRef = useRef();\n\n  const itemsRef = useRef([]);\n\n  const [focusedRowOffset, setFocusedRowOffset] = useState(0);\n\n  const handleClick = useCallback(\n    (selected, id) => {\n      if (selected && id !== null) {\n        deselectItem();\n      } else {\n        setIsExpanded(false);\n        selectItem(id);\n      }\n    },\n    [deselectItem, selectItem]\n  );\n\n  const handleExpandClick = useCallback(\n    () => setIsExpanded((currentExpanded) => !currentExpanded),\n    []\n  );\n\n  useExpandAnimation({\n    sectionRef,\n    innerContainerRef,\n    isExpanded,\n    setFocusedRowOffset,\n    collapsedHeight: CHIP_COLLAPSED_FULL_HEIGHT,\n    bottomMargin: CHIP_BOTTOM_MARGIN,\n    topMargin: CHIP_TOP_MARGIN,\n  });\n\n  useHandleRowVisibility({\n    isExpanded,\n    innerContainerRef,\n    selectedItemId,\n    setFocusedRowOffset,\n    itemRefs: itemsRef,\n    offsetSpacing: FOCUS_BORDER_SPACING,\n  });\n\n  const hasItems = items.length > 0;\n  useRovingTabIndex({ ref: sectionRef }, [isExpanded]);\n  useKeyDownEffect(\n    sectionRef,\n    !isExpanded ? 'down' : '',\n    () => hasItems && setIsExpanded(true),\n    [isExpanded, hasItems]\n  );\n\n  const containerId = useMemo(() => `pill-group-${uuidv4()}`, []);\n  return (\n    <Section ref={sectionRef}>\n      {hasItems && (\n        <>\n          <Container\n            id={containerId}\n            isExpanded={isExpanded}\n            role=\"listbox\"\n            aria-label={\n              ariaLabel || __('List of filtering options', 'web-stories')\n            }\n          >\n            <InnerContainer\n              role=\"presentation\"\n              ref={innerContainerRef}\n              style={{ transform: `translateY(-${focusedRowOffset}px` }}\n            >\n              {items.map((item, index) => {\n                const { id, label } = item;\n                const selected = id === selectedItemId;\n                const tabIndex =\n                  selected || (!selected && index === 0) ? 0 : -1;\n\n                return (\n                  <Chip\n                    key={id}\n                    role=\"option\"\n                    ref={(el) => {\n                      itemsRef.current[id] = el;\n                    }}\n                    active={selected}\n                    aria-selected={selected}\n                    onClick={() => handleClick(selected, id)}\n                    tabIndex={tabIndex}\n                  >\n                    {label}\n                  </Chip>\n                );\n              })}\n            </InnerContainer>\n          </Container>\n          <ExpandButton\n            onClick={handleExpandClick}\n            isExpanded={isExpanded}\n            aria-controls={containerId}\n            aria-expanded={isExpanded}\n            aria-label={__('Expand', 'web-stories')}\n          >\n            <Icons.ChevronUp />\n          </ExpandButton>\n        </>\n      )}\n    </Section>\n  );\n};\n\nChipGroup.propTypes = {\n  items: PropTypes.array.isRequired,\n  selectedItemId: PropTypes.string,\n  selectItem: PropTypes.func,\n  deselectItem: PropTypes.func,\n  ariaLabel: PropTypes.string,\n};\n\nexport default ChipGroup;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/chipGroup/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport ChipGroup from '..';\n\nexport default {\n  title: 'Stories Editor/Components/ChipGroup',\n  component: ChipGroup,\n};\n\nconst Container = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  max-width: 350px;\n`;\n\nconst categories = [\n  {\n    id: 'categories/unsplash:KHXRtL69hcY',\n    label: 'Sustainability',\n  },\n  {\n    id: 'categories/unsplash:bo8jQKTaE0Y',\n    label: 'Wallpapers',\n  },\n  {\n    id: 'categories/unsplash:c7USHrQ0Ljw',\n    label: 'COVID-19',\n  },\n  {\n    id: 'categories/unsplash:Fzo3zuOHN6w',\n    label: 'Travel',\n  },\n  {\n    id: 'categories/unsplash:6sMVjTLSkeQ',\n    label: 'Nature',\n  },\n  {\n    id: 'categories/unsplash:iUIsnVtjB0Y',\n    label: 'Textures & Patterns',\n  },\n  {\n    id: 'categories/unsplash:BJJMtteDJA4',\n    label: 'Current Events',\n  },\n  {\n    id: 'categories/unsplash:towJZFskpGg',\n    label: 'People',\n  },\n  {\n    id: 'categories/unsplash:aeu6rL-j6ew',\n    label: 'Business & Work',\n  },\n  {\n    id: 'categories/unsplash:J9yrPaHXRQY',\n    label: 'Technology',\n  },\n  {\n    id: 'categories/unsplash:Jpg6Kidl-Hk',\n    label: 'Animals',\n  },\n  {\n    id: 'categories/unsplash:R_Fyn-Gwtlw',\n    label: 'Interiors',\n  },\n  {\n    id: 'categories/unsplash:rnSKDHwwYUk',\n    label: 'Architecture',\n  },\n  {\n    id: 'categories/unsplash:xjPR4hlkBGA',\n    label: 'Food & Drink',\n  },\n  {\n    id: 'categories/unsplash:Bn-DjrcBrwo',\n    label: 'Athletics',\n  },\n  {\n    id: 'categories/unsplash:_8zFHuhRhyo',\n    label: 'Spirituality',\n  },\n  {\n    id: 'categories/unsplash:_hb-dl4Q-4U',\n    label: 'Health & Wellness',\n  },\n  {\n    id: 'categories/unsplash:hmenvQhUmxM',\n    label: 'Film',\n  },\n  {\n    id: 'categories/unsplash:S4MKLAsBB74',\n    label: 'Fashion',\n  },\n  {\n    id: 'categories/unsplash:qPYsDzvJOYc',\n    label: 'Experimental',\n  },\n];\n\nexport const empty = () => {\n  return (\n    <Container>\n      <ChipGroup items={[]} />\n    </Container>\n  );\n};\n\nexport const unselected = () => {\n  return (\n    <Container>\n      <ChipGroup items={categories} />\n    </Container>\n  );\n};\n\nexport const selected = () => {\n  return (\n    <Container>\n      <ChipGroup items={categories} selectedItemId={categories[1].id} />\n    </Container>\n  );\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/hooks/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as useExpandAnimation } from './useExpandAnimation';\nexport { default as useHandleRowVisibility } from './useHandleRowVisibility';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/hooks/useExpandAnimation.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useLayoutEffect } from '@googleforcreators/react';\n\nfunction useExpandAnimation({\n  sectionRef,\n  innerContainerRef,\n  isExpanded,\n  setFocusedRowOffset,\n  collapsedHeight,\n  bottomMargin,\n  topMargin,\n}) {\n  // Handles expand and contract animation.\n  // We calculate the actual height of the categories list, and set its explicit\n  // height if it's expanded, in order to have a CSS height transition.\n  useLayoutEffect(() => {\n    if (!sectionRef.current || !innerContainerRef.current) {\n      return;\n    }\n    let height;\n    if (!isExpanded) {\n      height = `${collapsedHeight}px`;\n    } else {\n      height = `${\n        innerContainerRef.current.offsetHeight + topMargin + bottomMargin\n      }px`;\n    }\n    // Safari has some strange issues with flex-shrink that require setting\n    // min-height as well.\n    sectionRef.current.style.height = height;\n    sectionRef.current.style.minHeight = height;\n\n    setFocusedRowOffset(0);\n  }, [\n    bottomMargin,\n    collapsedHeight,\n    innerContainerRef,\n    isExpanded,\n    sectionRef,\n    setFocusedRowOffset,\n    topMargin,\n  ]);\n}\n\nexport default useExpandAnimation;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/hooks/useHandleRowVisibility.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useLayoutEffect } from '@googleforcreators/react';\n\nfunction useHandleRowVisibility({\n  innerContainerRef,\n  isExpanded,\n  setFocusedRowOffset,\n  selectedItemId,\n  itemRefs,\n  offsetSpacing = 0,\n}) {\n  // Handles setting which row will be seen, by manipulating translateY.\n  useLayoutEffect(() => {\n    if (!innerContainerRef.current) {\n      return;\n    }\n    const selectedItem = itemRefs.current?.[selectedItemId]\n      ? itemRefs.current[selectedItemId]\n      : null;\n    const selectedItemOffsetTop = selectedItem?.offsetTop - offsetSpacing || 0;\n\n    if (!isExpanded && selectedItem) {\n      setFocusedRowOffset(selectedItemOffsetTop);\n    }\n  }, [\n    innerContainerRef,\n    isExpanded,\n    itemRefs,\n    offsetSpacing,\n    selectedItemId,\n    setFocusedRowOffset,\n  ]);\n\n  // Handles fading rows in and out depending on the selected item.\n  useLayoutEffect(() => {\n    if (!innerContainerRef.current) {\n      return;\n    }\n    const selectedItem = itemRefs.current?.[selectedItemId]\n      ? itemRefs.current[selectedItemId]\n      : null;\n    const selectedItemOffsetTop = selectedItem?.offsetTop || 0;\n\n    for (const pill of itemRefs.current) {\n      // Ensure the node still exists.\n      if (!pill) {\n        continue;\n      }\n      const isSameRow =\n        selectedItem && pill.offsetTop === selectedItemOffsetTop;\n      if (selectedItem && !isSameRow && !isExpanded) {\n        pill.classList.add('invisible');\n      } else {\n        pill.classList.remove('invisible');\n      }\n    }\n  }, [innerContainerRef, isExpanded, selectedItemId, itemRefs]);\n}\n\nexport default useHandleRowVisibility;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { Button, ButtonVariant } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_LIBRARY_ACTION_BUTTON } from '../../../../constants/zIndex';\n\nexport const PANE_PADDING = '1em';\n\nconst Pane = styled.section.attrs(({ isActive }) => ({\n  role: 'tabpanel',\n  'aria-expanded': isActive,\n  hidden: !isActive,\n}))`\n  padding: 1.5em ${PANE_PADDING};\n  ${({ isOverflowScrollable = false }) =>\n    isOverflowScrollable &&\n    css`\n      overflow-y: scroll;\n      height: 100%;\n    `}\n`;\n\nfunction getPaneId(tab) {\n  return `library-pane-${tab}`;\n}\n\nfunction getTabId(tab) {\n  return `library-tab-${tab}`;\n}\n\nconst LoadingContainer = styled.div`\n  display: flex;\n  justify-content: center;\n  margin-top: 18px;\n`;\n\nconst ACTION_BUTTON_SIZE = 16;\nconst ActionButton = styled(Button).attrs({ variant: ButtonVariant.Icon })`\n  display: flex;\n  align-items: center;\n  position: absolute;\n  top: calc(50% - ${ACTION_BUTTON_SIZE / 2}px);\n  right: calc(50% - ${ACTION_BUTTON_SIZE / 2}px);\n  color: ${({ theme }) => theme.colors.fg.primary};\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n  width: ${ACTION_BUTTON_SIZE}px;\n  height: ${ACTION_BUTTON_SIZE}px;\n  opacity: ${({ $display }) => ($display ? '1' : '0')};\n  z-index: ${Z_INDEX_LIBRARY_ACTION_BUTTON};\n`;\n\nconst PageTemplateTitleContainer = styled.div`\n  position: absolute;\n  bottom: 0;\n  width: 100%;\n  padding: 8px;\n  background-color: ${({ theme }) => theme.colors.opacity.black64};\n  opacity: ${({ isActive }) => (isActive ? 1 : 0)};\n`;\n\nexport {\n  ActionButton,\n  Pane,\n  getPaneId,\n  getTabId,\n  LoadingContainer,\n  PageTemplateTitleContainer,\n};\n\nexport { default as ChipGroup } from './chipGroup';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/insertionOverlay.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\nimport { rgba } from 'polished';\nimport PropTypes from 'prop-types';\n\nconst ICON_SIZE = 16;\nconst IconContainer = styled.div`\n  height: ${ICON_SIZE}px;\n  width: ${ICON_SIZE}px;\n  position: absolute;\n  top: calc(50% - ${ICON_SIZE / 2}px);\n  left: calc(50% - ${ICON_SIZE / 2}px);\n  color: ${({ theme }) => theme.colors.fg.primary};\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n  pointer-events: none;\n  svg {\n    position: absolute;\n    top: 0;\n    left: 0;\n  }\n`;\n\nconst Scrim = styled.div`\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  background-color: ${({ theme }) => rgba(theme.colors.standard.black, 0.5)};\n  pointer-events: none;\n`;\n\nfunction InsertionOverlay({ showIcon = true, className = '' }) {\n  // The icon looks like a button but is just representational.\n  // The real interactive element is the containing element.\n  // If the showIcon is `false`, we still display the scrim for shade.\n  return (\n    <Scrim className={className}>\n      {showIcon && (\n        <IconContainer role=\"presentation\">\n          <Icons.PlusFilledSmall />\n        </IconContainer>\n      )}\n    </Scrim>\n  );\n}\n\nInsertionOverlay.propTypes = {\n  showIcon: PropTypes.bool,\n  className: PropTypes.string,\n};\n\nexport default InsertionOverlay;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/libraryMoveable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { editorToDataX, editorToDataY } from '@googleforcreators/units';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\nimport {\n  Moveable,\n  InOverlay,\n  areEventsDragging,\n} from '@googleforcreators/moveable';\nimport { useTransform } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport { ZoomSetting, TRACKING_EVENTS } from '../../../../constants';\nimport { useDropTargets } from '../../../dropTargets';\nimport { useLayout } from '../../../../app/layout';\nimport useInsertElement from '../../../canvas/useInsertElement';\nimport { useInsertTextSet } from '../../../canvas';\nimport isTargetOutOfContainer from '../../../../utils/isTargetOutOfContainer';\nimport useSnapping from '../../../canvas/utils/useSnapping';\nimport { useStory, useCanvas } from '../../../../app';\nimport objectWithout from '../../../../utils/objectWithout';\nimport { noop } from '../../../../utils/noop';\nimport usePerformanceTracking from '../../../../utils/usePerformanceTracking';\nimport { PRODUCT_WIDTH, PRODUCT_HEIGHT } from '../shopping/constants';\n\nconst TargetBox = styled.div`\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  z-index: 1;\n  cursor: pointer;\n`;\n\nfunction LibraryMoveable({\n  type,\n  elementProps = {},\n  handleDrag,\n  handleDragEnd,\n  onClick = noop,\n  cloneElement,\n  cloneProps,\n  elements = [],\n  active = false,\n}) {\n  const CloneElement = cloneElement;\n\n  const [isDragging, setIsDragging] = useState(false);\n  const [didManuallyReset, setDidManuallyReset] = useState(false);\n  const [hover, setHover] = useState(false);\n  const cloneRef = useRef(null);\n  const targetBoxRef = useRef(null);\n  const targetBoxSizeRef = useRef(null);\n  const overlayRef = useRef(null);\n  const moveable = useRef(null);\n\n  // These useLayout's are specifically kept as separate entries\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n  // This is a stable function, so it will ever only run once\n  const { setZoomSetting } = useLayout(({ actions: { setZoomSetting } }) => ({\n    setZoomSetting,\n  }));\n\n  const insertElement = useInsertElement();\n  const { backgroundElement } = useStory((state) => ({\n    backgroundElement: state.state.currentPage?.elements?.[0] ?? {},\n  }));\n  const { fullbleedContainer, nodesById, pageContainer } = useCanvas(\n    (state) => ({\n      fullbleedContainer: state.state.fullbleedContainer,\n      pageContainer: state.state.pageContainer,\n      nodesById: state.state.nodesById,\n    })\n  );\n\n  const { activeDropTargetId, setDraggingResource } = useDropTargets(\n    ({ state: { activeDropTargetId }, actions: { setDraggingResource } }) => ({\n      activeDropTargetId,\n      setDraggingResource,\n    })\n  );\n\n  const { clearTransforms, pushTransform } = useTransform((state) => ({\n    clearTransforms: state.actions.clearTransforms,\n    pushTransform: state.actions.pushTransform,\n  }));\n\n  const frame = {\n    translate: [0, 0],\n  };\n\n  const { insertTextSetByOffset } = useInsertTextSet();\n\n  const eventTrackerRef = useRef({});\n  const startEventTracking = (evt) => {\n    const { timeStamp, clientX, clientY } = evt;\n    eventTrackerRef.current = {\n      timeStamp,\n      clientX,\n      clientY,\n    };\n  };\n\n  const resetMoveable = useCallback(() => {\n    if (!targetBoxRef.current || !cloneRef.current) {\n      return;\n    }\n\n    targetBoxRef.current.style.transform = null;\n    cloneRef.current.style.transform = null;\n    // Hide the clone, too.\n    cloneRef.current.style.opacity = 0;\n    setIsDragging(false);\n    clearTransforms();\n    setDraggingResource(null);\n  }, [setDraggingResource, clearTransforms]);\n\n  // We only need to use this effect while dragging since the active element is document.body\n  // and using just that interferes with other handlers.\n  useKeyDownEffect(\n    isDragging ? document.body : { current: null },\n    'esc',\n    () => {\n      setDidManuallyReset(true);\n      resetMoveable();\n    },\n    [isDragging, resetMoveable]\n  );\n\n  const onDrag = ({ beforeTranslate, inputEvent }) => {\n    pushTransform(null, { drag: beforeTranslate });\n    // This is needed if the user clicks \"Esc\" but continues dragging.\n    if (didManuallyReset) {\n      return false;\n    }\n    frame.translate = beforeTranslate;\n    // Don't display the clone unless we're sure it's a drag gesture\n    if (\n      cloneRef.current &&\n      areEventsDragging(eventTrackerRef.current, inputEvent)\n    ) {\n      if (cloneRef.current.style.opacity !== 1 && !activeDropTargetId) {\n        // We're not doing it in `onDragStart` since otherwise on clicking it would appear, too.\n        cloneRef.current.style.opacity = 1;\n      } else if (activeDropTargetId) {\n        // If there's an active drop target, let's hide the clone.\n        cloneRef.current.style.opacity = 0;\n      }\n      cloneRef.current.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`;\n      // We also have to move the original target ref for snapping to work.\n      targetBoxRef.current.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`;\n    }\n    handleDrag?.(inputEvent);\n    return undefined;\n  };\n\n  const getTargetOffset = useCallback(() => {\n    const overlay = overlayRef.current;\n    let offsetX = 0,\n      offsetY = 0;\n    for (\n      let offsetNode = overlay;\n      offsetNode;\n      offsetNode = offsetNode.offsetParent\n    ) {\n      offsetX += offsetNode.offsetLeft;\n      offsetY += offsetNode.offsetTop;\n    }\n    return {\n      offsetX,\n      offsetY,\n    };\n  }, [overlayRef]);\n\n  const onDragStart = ({ set, inputEvent }) => {\n    inputEvent.stopPropagation();\n    setDidManuallyReset(false);\n    // Note: we can't set isDragging true here since a \"click\" is also considered dragStart.\n    set(frame.translate);\n    setIsDragging(true);\n    startEventTracking(inputEvent);\n    setZoomSetting(ZoomSetting.Fit);\n\n    // Position the clone that's being dragged.\n    const { offsetX, offsetY } = getTargetOffset();\n    const targetBox = targetBoxRef.current.getBoundingClientRect();\n    // Let's save the original targetbox size.\n    targetBoxSizeRef.current = {\n      width: targetBox.width,\n      height: targetBox.height,\n    };\n    // Assign new size to targetbox so that it would match the clone, for snapping.\n    targetBoxRef.current.style.width = `${cloneProps.width}px`;\n    targetBoxRef.current.style.height = `${cloneProps.height}px`;\n    const x1 = targetBox.left - offsetX;\n    const y1 = targetBox.top - offsetY;\n    cloneRef.current.style.left = `${x1}px`;\n    cloneRef.current.style.top = `${y1}px`;\n    // Update moveable to take the new size of the target for snapping.\n    if (moveable.current) {\n      moveable.current.updateRect();\n    }\n  };\n\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: targetBoxRef.current,\n    eventData: {\n      ...TRACKING_EVENTS.INSERT_ELEMENT,\n      label: type,\n    },\n    eventType: 'pointerdown',\n  });\n\n  const onDragEnd = ({ inputEvent }) => {\n    if (didManuallyReset) {\n      return false;\n    }\n    // Restore the original size of the target.\n    targetBoxRef.current.style.width = `${targetBoxSizeRef.current.width}px`;\n    targetBoxRef.current.style.height = `${targetBoxSizeRef.current.height}px`;\n    if (!areEventsDragging(eventTrackerRef.current, inputEvent)) {\n      resetMoveable();\n      onClick();\n      return false;\n    }\n    // We only skip Moveable onDragEnd handling if there's an active drop target ID.\n    if (activeDropTargetId && handleDragEnd) {\n      handleDragEnd();\n      // Only continue if the clone is at least partially on the page.\n    } else if (!isTargetOutOfContainer(cloneRef.current, fullbleedContainer)) {\n      const {\n        x,\n        y,\n        width: w,\n        height: h,\n      } = cloneRef.current.getBoundingClientRect();\n      const { x: pageX, y: pageY } = pageContainer.getBoundingClientRect();\n\n      if (type === 'textSet') {\n        insertTextSetByOffset(elements, {\n          offsetX: editorToDataX(x - pageX, pageSize.width),\n          offsetY: editorToDataY(y - pageY, pageSize.height),\n        });\n      } else if (type === 'product') {\n        insertElement(type, {\n          ...elementProps,\n          width: PRODUCT_WIDTH,\n          height: PRODUCT_HEIGHT,\n          x: editorToDataX(x - pageX, pageSize.width),\n          y: editorToDataY(y - pageY, pageSize.height),\n        });\n      } else {\n        insertElement(type, {\n          ...elementProps,\n          x: editorToDataX(x - pageX, pageSize.width),\n          y: editorToDataY(y - pageY, pageSize.height),\n          width: editorToDataX(w, pageSize.width),\n          height: editorToDataY(h, pageSize.height),\n        });\n      }\n    }\n    resetMoveable();\n    return undefined;\n  };\n\n  const { offsetX: snappingOffsetX } = getTargetOffset();\n  const snapProps = useSnapping({\n    isDragging: true,\n    canSnap: true,\n    otherNodes: Object.values(objectWithout(nodesById, [backgroundElement.id])),\n    snappingOffsetX,\n  });\n\n  return (\n    <>\n      <TargetBox\n        ref={targetBoxRef}\n        onPointerOver={() => setHover(true)}\n        onPointerOut={() => setHover(false)}\n      />\n      {(isDragging || active || hover) && (\n        <>\n          <InOverlay\n            ref={overlayRef}\n            zIndex={1}\n            pointerEvents=\"none\"\n            render={() => {\n              return <CloneElement ref={cloneRef} {...cloneProps} />;\n            }}\n          />\n          <Moveable\n            ref={moveable}\n            className=\"default-moveable hide-handles\"\n            // eslint-disable-next-line react-hooks/refs -- FIXME\n            target={targetBoxRef.current}\n            edge\n            draggable\n            origin={false}\n            pinchable\n            onDragStart={onDragStart}\n            onDrag={onDrag}\n            onDragEnd={onDragEnd}\n            {...snapProps}\n          />\n        </>\n      )}\n    </>\n  );\n}\n\nLibraryMoveable.propTypes = {\n  type: PropTypes.string.isRequired,\n  handleDrag: PropTypes.func,\n  handleDragEnd: PropTypes.func,\n  elementProps: PropTypes.object,\n  onClick: PropTypes.func,\n  cloneElement: PropTypes.object.isRequired,\n  cloneProps: PropTypes.object.isRequired,\n  active: PropTypes.bool,\n  elements: PropTypes.array,\n};\n\nexport default LibraryMoveable;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\n\nexport const PANEL_GRID_ROW_GAP = 12;\n\n// padding-top is to help outlines on text sets\nexport const virtualPaneContainer = css`\n  margin-top: 38px;\n  padding-top: 2px;\n  width: 100%;\n  height: 100%;\n`;\n\n// Contains mapped over useVirtual rows\nexport const VirtualizedWrapper = styled.div`\n  height: ${({ height }) => `${height}px`};\n  width: 100%;\n  position: relative;\n`;\nVirtualizedWrapper.propTypes = {\n  height: PropTypes.number.isRequired,\n};\n\n// VirtualizedContainer is the last accessible parent before virtualizedRows and columns are in play.\nexport const VirtualizedContainer = styled.div`\n  position: absolute;\n  top: 0;\n  left: ${({ paneLeft = 0 }) => paneLeft};\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  grid-template-columns: ${({ columnWidth }) => `\n    repeat(auto-fill, ${columnWidth}px)`};\n  grid-template-rows: ${({ rowHeight }) => `minmax(${rowHeight}px, auto)`};\n  gap: ${({ rowGap = 12 }) => rowGap}px;\n  width: calc(100% - ${({ paneLeft = 0 }) => paneLeft});\n  height: 100%;\n  margin-top: 4px;\n`;\n\nVirtualizedContainer.propTypes = {\n  columnWidth: PropTypes.number.isRequired,\n  rowHeight: PropTypes.number.isRequired,\n  rowGap: PropTypes.number,\n  paneLeft: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/getVirtualizedItemIndex.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @param {Object} props             All props.\n * @param {number} props.rowIndex    Identifies the virtualized row index.\n * @param {number} props.columnIndex Identifies the virtualized column index.\n * @return {number} itemIndex        Returns the true index of an item in a virtualized grid\n */\nexport const getVirtualizedItemIndex = ({ columnIndex, rowIndex }) =>\n  columnIndex === 0 ? rowIndex * 2 : rowIndex * 2 + 1;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './components';\nexport { getVirtualizedItemIndex } from './getVirtualizedItemIndex';\nexport { default as useVirtualizedGridNavigation } from './useVirtualizedGridNavigation';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/test/getVirtualizedItemIndex.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getVirtualizedItemIndex } from '../getVirtualizedItemIndex';\n\ndescribe('getVirtualizedItemIndex', () => {\n  it.each`\n    rowIndex | columnIndex | returnedGridIndex\n    ${0}     | ${0}        | ${0}\n    ${0}     | ${1}        | ${1}\n    ${1}     | ${0}        | ${2}\n    ${1}     | ${1}        | ${3}\n    ${2}     | ${0}        | ${4}\n    ${2}     | ${1}        | ${5}\n    ${3}     | ${0}        | ${6}\n    ${10}    | ${0}        | ${20}\n    ${10}    | ${1}        | ${21}\n    ${49}    | ${1}        | ${99}\n    ${101}   | ${0}        | ${202}\n  `(\n    'should return `$returnedGridIndex` when columnIndex is `$columnIndex` and rowIndex is `$rowIndex`',\n    ({ rowIndex, columnIndex, returnedGridIndex }) => {\n      expect(getVirtualizedItemIndex({ rowIndex, columnIndex })).toStrictEqual(\n        returnedGridIndex\n      );\n    }\n  );\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/test/useVirtualizedGridNavigation.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\nimport { createRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useVirtualizedGridNavigation from '../useVirtualizedGridNavigation';\n\ndescribe('useVirtualizedGridNavigation()', () => {\n  it('should initially return focus booleans as false', () => {\n    const { result } = renderHook(\n      () =>\n        useVirtualizedGridNavigation({\n          containerRef: createRef(),\n          gridItemRefs: { current: [] },\n          gritItemIds: [],\n          rowVirtualizer: { virtualItems: [] },\n        }),\n      {}\n    );\n\n    expect(result.current.activeGridItemId).toBeUndefined();\n    expect(result.current.isGridFocused).toBeFalse();\n  });\n\n  it('should update isGridFocused to true and set activeGridItemId to first index when handleGridFocus is called', () => {\n    const { result } = renderHook(\n      () =>\n        useVirtualizedGridNavigation({\n          containerRef: createRef(),\n          gridItemRefs: { current: [] },\n          gridItemIds: ['one', 'two', 'three'],\n          rowVirtualizer: { virtualItems: [] },\n        }),\n      {}\n    );\n\n    act(() => {\n      result.current.handleGridFocus();\n    });\n\n    expect(result.current.activeGridItemId).toBe('one');\n    expect(result.current.isGridFocused).toBeTrue();\n  });\n\n  it('should update activeGridItemId when handleGridItemFocus is called', () => {\n    const { result } = renderHook(\n      () =>\n        useVirtualizedGridNavigation({\n          containerRef: createRef(),\n          gridItemRefs: { current: [] },\n          gridItemIds: ['one', 'two', 'three'],\n          rowVirtualizer: { virtualItems: [] },\n        }),\n      {}\n    );\n    expect(result.current.activeGridItemId).toBeUndefined();\n\n    act(() => {\n      result.current.handleGridItemFocus('two');\n    });\n\n    expect(result.current.activeGridItemId).toBe('two');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shared/virtualizedPanelGrid/useVirtualizedGridNavigation.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useRovingTabIndex from '../../../../../utils/useRovingTabIndex';\nimport useFocusCanvas from '../../../../canvas/useFocusCanvas';\n\n/**\n * This is a shared custom hook to enable keyboard arrow navigation on panels\n * that use `useVirtual` to virtualize the contents. It takes over control of\n * focus when keyboard is in play.\n * Use the returned `handleGridFocus` as `onFocus` of the element that `containerRef` belongs.\n * Use the returned `activeGridItemId` as a check in your map of gridItems against the id of\n * each grid item to identify which grid item should get focus styles/behavior.\n * Use the returned `handleGridItemFocus` as the gridItem `onFocus`, pass it the grid item's id as a param.\n * Use the returned `isGridFocused` as a boolean to show focus styles or not.\n *\n * @param {Object} props                All props.\n * @param {Object} props.containerRef   ref of virtualized grid's container (nearest parent in DOM).\n * @param {Object} props.gridItemRefs   ref containing array as .current holding each virtualized item DOM.\n * @param {Array} props.gridItemIds     array of available grid item ids. it's important that ids don't update when the DOM does.\n * @param {Object} props.rowVirtualizer instance of outermost `useVirtual` for this grid.\n * @return {Object}                     memoized keys { handleGridFocus, handleGridItemFocus, activeGridItemId, isGridFocused }\n */\nexport default function useVirtualizedGridNavigation({\n  containerRef,\n  gridItemRefs,\n  gridItemIds,\n  rowVirtualizer,\n}) {\n  const [activeGridItemId, setActiveGridItemId] = useState();\n\n  const [isGridFocused, setIsGridFocused] = useState(false);\n  const currentAvailableRows = useMemo(\n    () => rowVirtualizer.virtualItems,\n    [rowVirtualizer]\n  );\n  const currentAvailableRowsRef = useRef();\n\n  /**\n   * useVirtual and useRovingTabIndex do not play well together but we need both!\n   * The below useEffect is key to maintaining the proper focus for keyboard users.\n   * What happens is on \"scroll\" of the virtualized container useVirtual is grabbing more rows\n   * and these rows are fed through the rendered map to create grid that is visible to users.\n   * While it doesn't look like the DOM is updating, it is in fact updating.\n   * So the old refs get lost and the list gets new ones! By manually forcing focus and maintaining an object\n   * of gridItemRefs that are organized by gridItem id (those don't update) we can make sure the focus stays where it's supposed to be.\n   * Checking for a difference in currentAvailableRows and assigning the matching ref to any change is just so that the effect hook will run when the virtualized list\n   * updates and reattach focus to the new instance of an already selected layout.\n   */\n  useEffect(() => {\n    if (currentAvailableRows !== currentAvailableRowsRef?.current) {\n      currentAvailableRowsRef.current = currentAvailableRows;\n    }\n\n    if (activeGridItemId && isGridFocused) {\n      gridItemRefs.current?.[activeGridItemId]?.focus();\n    }\n  }, [activeGridItemId, currentAvailableRows, isGridFocused, gridItemRefs]);\n\n  useRovingTabIndex({ ref: containerRef });\n\n  const handleGridFocus = useCallback(() => {\n    if (!isGridFocused) {\n      const newGridItemId = gridItemRefs.current?.[activeGridItemId]\n        ? activeGridItemId\n        : gridItemIds?.[0];\n\n      setActiveGridItemId(newGridItemId);\n      setIsGridFocused(true);\n      gridItemRefs.current?.[newGridItemId]?.focus();\n    }\n  }, [activeGridItemId, isGridFocused, gridItemIds, gridItemRefs]);\n\n  const handleGridItemFocus = useCallback(\n    (itemId) => {\n      if (activeGridItemId !== itemId) {\n        setActiveGridItemId(itemId);\n      }\n    },\n    [activeGridItemId]\n  );\n\n  // Exit grid\n  const focusCanvas = useFocusCanvas();\n\n  const onTabKeyDown = useCallback(() => {\n    focusCanvas();\n    setIsGridFocused(false);\n  }, [focusCanvas]);\n\n  useKeyDownEffect(containerRef, 'tab', onTabKeyDown, [onTabKeyDown]);\n\n  useFocusOut(containerRef, () => {\n    setIsGridFocused(false);\n  }, []);\n\n  return useMemo(\n    () => ({\n      handleGridFocus,\n      handleGridItemFocus,\n      activeGridItemId,\n      isGridFocused,\n    }),\n    [activeGridItemId, isGridFocused, handleGridFocus, handleGridItemFocus]\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const PRODUCT_WIDTH = 25;\nexport const PRODUCT_HEIGHT = 25;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as ShoppingPane } from './shoppingPane';\nexport { default as ShoppingIcon } from './shoppingIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/karma/shopping.karma.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\nfunction isStoryEmpty() {\n  return Boolean(document.getElementById('emptystate-message'));\n}\n\nconst dropDownSelector = '[aria-label=\"Design menu\"] [aria-label=\"Product\"]';\n\ndescribe('Shopping integration', () => {\n  let fixture;\n\n  async function focusProductSearchInput() {\n    await fixture.editor.library.shoppingTab.click();\n    await fixture.events.keyboard.press('tab');\n    const searchInput = fixture.querySelector('[aria-label=\"Product search\"]');\n    await fixture.events.focus(searchInput);\n    await fixture.events.click(searchInput);\n  }\n\n  async function insertProduct(productTitle) {\n    await searchProduct(productTitle);\n\n    const productButton = fixture.querySelector(\n      `[aria-label=\"Add ${productTitle}\"]`\n    );\n    await fixture.events.click(productButton);\n    await waitFor(() => fixture.querySelector(dropDownSelector));\n\n    await clearSearch();\n  }\n\n  async function searchProduct(productTitle) {\n    await focusProductSearchInput();\n    await fixture.events.keyboard.type(productTitle);\n    // delay for search to catch-up\n    await fixture.events.sleep(400);\n  }\n\n  async function clearSearch() {\n    await focusProductSearchInput();\n    const clearSearchButton = fixture.querySelector(\n      `[aria-label=\"Clear product search\"]`\n    );\n    await fixture.events.click(clearSearchButton);\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  describe('Shopping tab', () => {\n    it('should handle product search add and remove', async () => {\n      expect(isStoryEmpty()).toEqual(true);\n      const productTitle = 'Hoodie';\n      await insertProduct(productTitle);\n\n      // add a small delay for debounce search to catchup\n      await fixture.events.sleep(500);\n\n      // check story `state`\n      const selectedElement = await getSelectedElement();\n      expect(isStoryEmpty()).toEqual(false);\n      await expect(selectedElement?.product?.productTitle).toBe(productTitle);\n      await focusProductSearchInput();\n\n      // select the product add / remove button\n      const product = fixture.querySelector(\n        `[aria-label=\"Remove ${productTitle}\"]`\n      );\n\n      // check add / remove icons\n      const checkIcon = fixture.querySelector(\n        `[aria-label=\"Remove ${productTitle}\"] svg[class^=\"productButton__Checkmark-\"]`\n      );\n\n      const removeIcon = fixture.querySelector(\n        `[aria-label=\"Remove ${productTitle}\"] svg[class^=\"productButton__Cross-\"]`\n      );\n\n      expect(window.getComputedStyle(checkIcon).display).toBe('block');\n      expect(window.getComputedStyle(removeIcon).display).toBe('none');\n      await fixture.events.hover(product);\n      expect(window.getComputedStyle(checkIcon).display).toBe('none');\n      expect(window.getComputedStyle(removeIcon).display).toBe('block');\n\n      // remove the product\n      await fixture.events.mouse.clickOn(product, 1, 1);\n      expect(isStoryEmpty()).toEqual(true);\n    });\n\n    it('should hide product lacking product image in dropdown', async () => {\n      expect(isStoryEmpty()).toEqual(true);\n      const productTitle = 'Hoodie';\n      await insertProduct(productTitle);\n\n      // check story `state`\n      const selectedElement = await getSelectedElement();\n      expect(isStoryEmpty()).toEqual(false);\n      await expect(selectedElement?.product?.productTitle).toBe(productTitle);\n      const dropDown = fixture.querySelector(dropDownSelector);\n      await fixture.events.click(dropDown);\n      await fixture.events.keyboard.type('WordPress');\n      expect(fixture.screen.getByText('No matches found')).toBeDefined();\n    });\n\n    it('should hide product lacking duplicate products in dropdown', async () => {\n      expect(isStoryEmpty()).toEqual(true);\n      await insertProduct('Album');\n\n      const product2Title = 'Hoodie';\n      await insertProduct(product2Title);\n\n      // check story `state`\n      const selectedElement = await getSelectedElement();\n      expect(isStoryEmpty()).toEqual(false);\n      await expect(selectedElement?.product?.productTitle).toBe(product2Title);\n      const dropDown = fixture.querySelector(dropDownSelector);\n      await fixture.events.click(dropDown);\n      await fixture.events.keyboard.type('album');\n      expect(fixture.screen.getByText('No matches found')).toBeDefined();\n    });\n\n    it('should disable button if product lacks product image', async () => {\n      await searchProduct('WordPress');\n\n      const productButton = fixture.querySelector(\n        '[aria-label=\"Products without images cannot be added.\"]'\n      );\n\n      await expect(productButton.getAttribute('aria-disabled')).toBe('true');\n    });\n\n    it('should disable button if there are more than 6 products on the page', async () => {\n      await insertProduct('Hoodie');\n      await insertProduct('Big Logo Collection');\n      await insertProduct('Logo Collection');\n      await insertProduct('Beanie with Logo');\n      await insertProduct('Album');\n      await insertProduct('Single');\n\n      await searchProduct('Massive Logo Collection');\n\n      const disabledButton = fixture.querySelector(\n        '[aria-label=\"Only 6 items can be added per page.\"]'\n      );\n      expect(disabledButton).toBeDefined();\n    });\n\n    it('should sort searched products', async () => {\n      await fixture.editor.library.shoppingTab.click();\n      await fixture.events.keyboard.press('tab');\n\n      const sortDropdown = fixture.querySelector(\n        '[aria-label=\"Product sort options\"]'\n      );\n      await fixture.events.mouse.clickOn(sortDropdown, 1, 1);\n\n      const option = fixture.screen.getByRole('menuitem', {\n        name: /^Alphabetical: Z-A/,\n      });\n\n      await fixture.events.mouse.clickOn(option, 1, 1);\n\n      // delay for search to catch-up\n      await fixture.events.sleep(400);\n\n      const firstOption = fixture.querySelector(\n        '[aria-label=\"Products list\"] [role=\"listitem\"]'\n      );\n\n      expect(firstOption.textContent).toContain('WordPress Pennant');\n    });\n\n    it('should display product pill tooltip when adding product on canvas', async () => {\n      await insertProduct('Big Logo Collection');\n\n      const container = fixture.container;\n      // Unselect element.\n      const fullbleedElements = await within(container).findAllByTestId(\n        'fullbleed',\n        {\n          timeout: 2000,\n        }\n      );\n      // There are three fullbleed elements; [0](Display layer), [1](Frames layer), and [2](Edit layer),\n      const { left, top } = fullbleedElements[1].getBoundingClientRect();\n      await fixture.events.mouse.click(left - 5, top - 5);\n\n      // Move mouse to hover over the element.\n      const frame = await waitFor(() => {\n        const frameNode = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!frameNode) {\n          throw new Error('node not ready');\n        }\n        expect(frameNode).toBeTruthy();\n        return frameNode;\n      });\n\n      const tooltipText = '$28.00';\n\n      await fixture.events.mouse.moveRel(frame, 10, 10);\n\n      const tooltip = await fixture.screen.findByText(tooltipText);\n      expect(tooltip).toHaveTextContent(tooltipText);\n      await fixture.snapshot('Product pill tooltip on hover');\n    });\n\n    it('add product via dragging', async () => {\n      expect(isStoryEmpty()).toEqual(true);\n      await searchProduct('hoodie');\n\n      // Only background initially\n      const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n\n      const product = fixture.querySelector(\n        '[aria-label=\"Products list\"] [role=\"listitem\"] img'\n      );\n\n      await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n        moveRel(product, 10, 10),\n        down(),\n        /* The steps give time for Moveable to react and display a clone to drag */\n        moveRel(bgFrame, 50, 50, { steps: 20 }),\n        up(),\n      ]);\n\n      // Now background + 1 extra element\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../shared';\n\nexport default getPaneId('shopping');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/product.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { Text, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport ProductImage from './productImage';\nimport ProductButton from './productButton';\nimport ProductPrice from './productPrice';\n\nconst StyledDescription = styled.div`\n  padding-left: 12px;\n`;\n\nconst StyledTitle = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\nfunction Product({ product, onClick, onFocus, isOnPage, canAddMore }) {\n  return (\n    <>\n      <ProductButton\n        product={product}\n        isOnPage={isOnPage}\n        canAddMore={canAddMore}\n        onClick={onClick}\n        onFocus={onFocus}\n      />\n      <ProductImage product={product} draggable={!isOnPage && canAddMore} />\n      <StyledDescription>\n        <StyledTitle isBold>{product?.productTitle}</StyledTitle>\n        <ProductPrice\n          price={product?.productPrice}\n          currency={product?.productPriceCurrency}\n        />\n      </StyledDescription>\n    </>\n  );\n}\n\nProduct.propTypes = {\n  product: PropTypes.object.isRequired,\n  onClick: PropTypes.func.isRequired,\n  onFocus: PropTypes.func,\n  isOnPage: PropTypes.bool,\n  canAddMore: PropTypes.bool,\n};\n\nexport default Product;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productButton.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  Icons,\n  Button,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../../tooltip';\nimport { noop } from '../../../../utils/noop';\nimport { MAX_PRODUCTS_PER_PAGE } from '../../../../constants';\n\nconst Checkmark = styled(Icons.Checkmark)`\n  width: 16px !important;\n  height: 16px !important;\n  border-radius: 100%;\n  color: ${({ theme }) => theme.colors.interactiveBg.disable};\n  background-color: ${({ theme }) => theme.colors.fg.positive};\n`;\n\nconst Cross = styled(Icons.Cross)`\n  width: 16px !important;\n  height: 16px !important;\n  border-radius: 100%;\n  color: ${({ theme }) => theme.colors.interactiveBg.disable};\n  background-color: ${({ theme }) => theme.colors.fg.negative};\n`;\n\nconst StyledButton = styled(Button)`\n  ${Cross} {\n    display: none;\n  }\n\n  &:hover ${Checkmark}, &:focus-within ${Checkmark}, &:active ${Checkmark} {\n    display: none;\n  }\n\n  &:hover ${Cross}, &:focus-within ${Cross}, &:active ${Cross} {\n    display: block;\n  }\n`;\n\nconst StyledActionsContainer = styled.div`\n  margin-right: 10px;\n`;\n\nconst DISABLED_PRODUCT_TEXT = sprintf(\n  /* translators: %d: max number of products. */\n  _n(\n    'Only %d item can be added per page.',\n    'Only %d items can be added per page.',\n    MAX_PRODUCTS_PER_PAGE,\n    'web-stories'\n  ),\n  MAX_PRODUCTS_PER_PAGE\n);\n\nconst DISABLED_PRODUCT_IMAGE_TEXT = __(\n  'Products without images cannot be added.',\n  'web-stories'\n);\n\nconst TooltipWrapper = ({ hasImage, disabled, children }) => {\n  if (!hasImage) {\n    return (\n      <Tooltip hasTail title={DISABLED_PRODUCT_IMAGE_TEXT}>\n        {children}\n      </Tooltip>\n    );\n  } else if (disabled) {\n    return (\n      <Tooltip hasTail title={DISABLED_PRODUCT_TEXT}>\n        {children}\n      </Tooltip>\n    );\n  } else {\n    return children;\n  }\n};\n\nTooltipWrapper.propTypes = {\n  disabled: PropTypes.bool,\n  hasImage: PropTypes.bool,\n  children: PropTypes.node,\n};\n\nfunction ProductButton({ product, onClick, onFocus, isOnPage, canAddMore }) {\n  const ADD_PRODUCT_TEXT = sprintf(\n    /* translators: %s: product title. */\n    __('Add %s', 'web-stories'),\n    product?.productTitle\n  );\n\n  const hasImage = Boolean(product?.productImages?.length);\n  const REMOVE_PRODUCT_TEXT = sprintf(\n    /* translators: %s: product title. */\n    __('Remove %s', 'web-stories'),\n    product?.productTitle\n  );\n\n  const disabled = !isOnPage && !canAddMore;\n\n  let ariaLabel = '';\n  if (!hasImage) {\n    ariaLabel = DISABLED_PRODUCT_IMAGE_TEXT;\n  } else if (isOnPage) {\n    ariaLabel = REMOVE_PRODUCT_TEXT;\n  } else if (disabled) {\n    ariaLabel = DISABLED_PRODUCT_TEXT;\n  } else {\n    ariaLabel = ADD_PRODUCT_TEXT;\n  }\n\n  return (\n    <TooltipWrapper hasImage={hasImage} disabled={disabled}>\n      <StyledActionsContainer>\n        <StyledButton\n          aria-label={ariaLabel}\n          aria-disabled={!hasImage || disabled}\n          // Note for below:\n          // In order to support focus for accessibility\n          // we have to utilize `noop` for the onClick\n          // as `disabled` will disable the ability to focus\n          // and tab order does not accomplish the same\n          onClick={\n            hasImage && !disabled\n              ? () => {\n                  onClick(product, isOnPage);\n                }\n              : noop\n          }\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          onFocus={onFocus}\n        >\n          {isOnPage ? (\n            <>\n              <Checkmark />\n              <Cross />\n            </>\n          ) : (\n            <Icons.PlusFilled />\n          )}\n        </StyledButton>\n      </StyledActionsContainer>\n    </TooltipWrapper>\n  );\n}\n\nProductButton.propTypes = {\n  product: PropTypes.object.isRequired,\n  onClick: PropTypes.func,\n  onFocus: PropTypes.func,\n  isOnPage: PropTypes.bool,\n  canAddMore: PropTypes.bool,\n};\n\nexport default ProductButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productDropdown.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useEffect,\n  useState,\n  useMemo,\n} from '@googleforcreators/react';\nimport { DatalistDropdown } from '@googleforcreators/design-system';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useAPI } from '../../../../app';\n\nfunction ProductDropdown({ product, setProduct, ...rest }) {\n  const initialProducts = useMemo(\n    () => [{ id: product?.productId, name: product?.productTitle, product }],\n    [product]\n  );\n  const [isLoading, setIsLoading] = useState(false);\n  const [initialOptions, setInitialOptions] = useState(initialProducts);\n\n  const {\n    actions: { getProducts },\n  } = useAPI();\n  const { isSaving, currentPageProductIds } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n        currentPage,\n      },\n    }) => ({\n      isSaving,\n      currentPageProductIds: currentPage?.elements\n        ?.filter(({ type }) => type === ELEMENT_TYPES.PRODUCT)\n        .filter(({ product: p }) => p.productId !== product.productId)\n        .map(({ product: p }) => p?.productId),\n    })\n  );\n\n  const onChange = ({ product: newProduct }) => setProduct(newProduct);\n\n  const getProductsByQuery = useCallback(\n    async (value = '') => {\n      const { products } = await getProducts(value);\n      return products\n        .filter(\n          (p) =>\n            p.productImages.length &&\n            !currentPageProductIds.includes(p.productId)\n        )\n        .map((p) => ({\n          name: p.productTitle,\n          id: p.productId,\n          product: p,\n        }));\n    },\n    [currentPageProductIds, getProducts]\n  );\n\n  useEffect(() => {\n    (async () => {\n      try {\n        setIsLoading(true);\n        const products = await getProductsByQuery();\n        setInitialOptions(products);\n      } catch {\n        setInitialOptions(initialProducts);\n      } finally {\n        setIsLoading(false);\n      }\n    })();\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Stop getProductsByQuery from re-render.\n  }, [initialProducts]);\n\n  const dropDownParams = {\n    hasSearch: true,\n    lightMode: true,\n    onChange,\n    getOptionsByQuery: getProductsByQuery,\n    selectedId: product?.productId,\n    dropDownLabel: __('Product', 'web-stories'),\n    disabled: isSaving,\n    primaryOptions: isLoading ? initialProducts : initialOptions,\n    zIndex: 10,\n  };\n\n  return (\n    <DatalistDropdown\n      options={initialOptions}\n      searchResultsLabel={__('Search results', 'web-stories')}\n      aria-label={__('Product', 'web-stories')}\n      {...dropDownParams}\n      {...rest}\n    />\n  );\n}\n\nProductDropdown.propTypes = {\n  product: PropTypes.object,\n  setProduct: PropTypes.func,\n};\n\nexport default ProductDropdown;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productImage.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport LibraryMoveable from '../shared/libraryMoveable';\nimport { PRODUCT_WIDTH, PRODUCT_HEIGHT } from './constants';\n\nconst imgPlaceholder = css`\n  display: block;\n  margin-right: 10px;\n  border-radius: 4px;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.disable};\n  width: 41px;\n  height: 41px;\n`;\n\nconst StyledImgPlaceHolder = styled.div`\n  ${imgPlaceholder}\n`;\n\nconst ProductImageWrap = styled.div`\n  position: relative;\n`;\n\nconst StyledImage = styled.img`\n  ${imgPlaceholder}\n  object-fit: cover;\n`;\n\nconst StyledImageClone = styled.img`\n  opacity: 0;\n  position: absolute;\n  object-fit: cover;\n  border-radius: 4px;\n  width: ${PRODUCT_WIDTH}px;\n  height: ${PRODUCT_HEIGHT}px;\n`;\n\nfunction ProductImage({ product }) {\n  const imageSrc = product?.productImages[0]?.url || '';\n  return imageSrc ? (\n    <StyledImage\n      alt={product?.productImages[0]?.alt}\n      src={imageSrc}\n      loading=\"lazy\"\n      decoding=\"async\"\n      draggable={false} // dragging is handled by `DraggableProductImage`\n      crossOrigin=\"anonymous\"\n    />\n  ) : (\n    <StyledImgPlaceHolder />\n  );\n}\n\nProductImage.propTypes = {\n  product: PropTypes.object.isRequired,\n};\n\nfunction DraggableProductImage({ product, draggable }) {\n  const src = product?.productImages[0]?.url || '';\n  return (\n    <ProductImageWrap>\n      <ProductImage product={product} />\n      {draggable && src && (\n        <LibraryMoveable\n          type=\"product\"\n          elementProps={{ product }}\n          cloneElement={StyledImageClone}\n          cloneProps={{\n            loading: 'lazy',\n            decoding: 'async',\n            crossOrigin: 'anonymous',\n            src,\n          }}\n        />\n      )}\n    </ProductImageWrap>\n  );\n}\n\nDraggableProductImage.propTypes = {\n  product: PropTypes.object.isRequired,\n  draggable: PropTypes.bool,\n};\n\nexport default DraggableProductImage;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productList.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { MAX_PRODUCTS_PER_PAGE } from '../../../../constants';\nimport useProductNavigation from './useProductNavigation';\nimport Product from './product';\n\nconst StyledListItem = styled.div`\n  display: flex;\n  width: 100%;\n  padding: 5px 0;\n  align-items: center;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n  transition: background-color ease-in-out 300ms;\n`;\n\nfunction ProductList({\n  products = [],\n  onPageProducts = [],\n  onClick,\n  isMenuFocused = true,\n}) {\n  const { handleListNav, currentRowsRef, setCurrentFocusIndex } =\n    useProductNavigation({ isMenuFocused, products });\n\n  useEffect(() => {\n    if (!isMenuFocused) {\n      setCurrentFocusIndex(0);\n    }\n  }, [isMenuFocused, setCurrentFocusIndex]);\n\n  const onFocus = (evt, index) => {\n    if (currentRowsRef.current[`row-${index}`] && evt.type === 'focus') {\n      setCurrentFocusIndex(index);\n    }\n  };\n\n  const canAddMore = onPageProducts.length < MAX_PRODUCTS_PER_PAGE;\n  return (\n    // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- list handles arrow up and arrow down\n    <div\n      aria-label={__('Products list', 'web-stories')}\n      role=\"list\"\n      onKeyDown={handleListNav}\n    >\n      {products.map((product, index) => {\n        return (\n          <StyledListItem\n            role=\"listitem\"\n            key={product?.productId}\n            tabIndex={-1}\n            ref={\n              (el) => (currentRowsRef.current[`row-${index}`] = el) // track the active row\n            }\n          >\n            <Product\n              product={product}\n              canAddMore={canAddMore}\n              isOnPage={onPageProducts.some(\n                (item) => item.product.productId === product?.productId\n              )}\n              onClick={onClick}\n              onFocus={(evt) => {\n                onFocus(evt, index);\n              }}\n            />\n          </StyledListItem>\n        );\n      })}\n    </div>\n  );\n}\n\nProductList.propTypes = {\n  products: PropTypes.arrayOf(PropTypes.object),\n  onPageProducts: PropTypes.arrayOf(PropTypes.object),\n  onClick: PropTypes.func.isRequired,\n  isMenuFocused: PropTypes.bool,\n};\n\nexport default ProductList;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productPrice.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\n\nconst StyledPrice = styled(Text.Paragraph).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nfunction ProductPrice({ price, currency }) {\n  const {\n    locale: { locale },\n  } = useConfig();\n\n  if (price && currency && locale) {\n    return (\n      <StyledPrice>\n        {new Intl.NumberFormat(locale, {\n          style: 'currency',\n          currency: currency,\n        }).format(price)}\n      </StyledPrice>\n    );\n  }\n\n  return null;\n}\n\nProductPrice.propTypes = {\n  price: PropTypes.number,\n  currency: PropTypes.string,\n};\n\nexport default ProductPrice;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/productSort.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport { useCallback, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../../tooltip';\nimport DropDownMenu from '../../../panels/shared/media/dropDownMenu';\n\nconst StyledDropDownMenu = styled(DropDownMenu)`\n  margin-left: 12px;\n`;\n\nconst StyledIcon = styled(Icons.Sort)`\n  width: 28px !important;\n  height: 28px !important;\n`;\n\nconst menuStylesOverride = css`\n  min-width: 180px;\n  margin-top: 0;\n`;\n\nconst options = [\n  {\n    value: 'date-desc',\n    orderby: 'date',\n    order: 'desc',\n    label: __('Recently Added', 'web-stories'),\n  },\n  {\n    value: 'title-asc',\n    orderby: 'title',\n    order: 'asc',\n    label: __('Alphabetical: A-Z', 'web-stories'),\n  },\n  {\n    value: 'title-desc',\n    orderby: 'title',\n    order: 'desc',\n    label: __('Alphabetical: Z-A', 'web-stories'),\n  },\n  {\n    value: 'price-asc',\n    orderby: 'price',\n    order: 'asc',\n    label: __('Lowest Price', 'web-stories'),\n  },\n  {\n    value: 'price-desc',\n    orderby: 'price',\n    order: 'desc',\n    label: __('Highest Price', 'web-stories'),\n  },\n];\n\nfunction ProductSort({ onChange, value = 'date-desc' }) {\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n  const onMenuOpen = () => setIsMenuOpen(true);\n  const onMenuClose = () => setIsMenuOpen(false);\n  const onMenuSelected = useCallback(\n    (newValue) => {\n      setIsMenuOpen(false);\n      onChange(options.find((option) => option.value === newValue));\n    },\n    [onChange]\n  );\n\n  const optionsWithGroup = [{ options }];\n\n  return (\n    <StyledDropDownMenu\n      onMenuOpen={onMenuOpen}\n      isMenuOpen={isMenuOpen}\n      onMenuSelected={onMenuSelected}\n      display\n      onMenuClose={onMenuClose}\n      groups={optionsWithGroup}\n      ariaLabel={__('Product sort options', 'web-stories')}\n      activeValue={value}\n      dropDownHeight={340}\n      menuStylesOverride={menuStylesOverride}\n    >\n      <Tooltip title={__('Sort', 'web-stories')}>\n        <StyledIcon />\n      </Tooltip>\n    </StyledDropDownMenu>\n  );\n}\n\nProductSort.propTypes = {\n  value: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport default ProductSort;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/shoppingIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction ShoppingIcon() {\n  return <Icons.Shopping title={__('Shopping library', 'web-stories')} />;\n}\n\nexport default ShoppingIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/shoppingPane.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useState,\n  useEffect,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  Text,\n  TextSize,\n  SearchInput,\n  useLiveRegion,\n  useSnackbar,\n  InfiniteScroller,\n  LoadingSpinner,\n} from '@googleforcreators/design-system';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\nimport { trackError, trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { Section } from '../../common';\nimport { useAPI, useConfig } from '../../../../app';\nimport { Row } from '../../../form';\nimport { Pane } from '../shared';\nimport { useStory } from '../../../../app/story';\nimport useLibrary from '../../useLibrary';\nimport paneId from './paneId';\nimport ProductList from './productList';\nimport ProductSort from './productSort';\nimport { PRODUCT_WIDTH, PRODUCT_HEIGHT } from './constants';\n\nconst LoadingContainer = styled.div`\n  display: flex;\n  justify-content: center;\n`;\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst loadingSpinnerProps = { animationSize: 25, circleSize: 3 };\n\nfunction ShoppingPane(props) {\n  const { showSnackbar } = useSnackbar();\n  const { shoppingProvider } = useConfig();\n  const speak = useLiveRegion('assertive');\n  const {\n    actions: { getProducts },\n  } = useAPI();\n\n  const { currentPageProducts, deleteElementById, currentPageNumber } =\n    useStory(({ actions, state: { currentPage, currentPageNumber } }) => ({\n      currentPageProducts: currentPage?.elements\n        ?.filter(({ type }) => type === ELEMENT_TYPES.PRODUCT)\n        .map(({ id, product }) => ({\n          elementId: id,\n          product,\n        })),\n      deleteElementById: actions.deleteElementById,\n      currentPageNumber,\n    }));\n\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n\n  const [loaded, setLoaded] = useState(false);\n  const [isLoading, setIsLoading] = useState(false);\n  const [canLoadMore, setCanLoadMore] = useState(false);\n  const [searchTerm, setSearchTerm] = useState('');\n  const [page, setPage] = useState(1);\n  const [orderby, setOrderby] = useState('date');\n  const [order, setOrder] = useState('desc');\n  const [isMenuFocused, setIsMenuFocused] = useState(false);\n  const [products, setProducts] = useState([]);\n\n  const searchProducts = useCallback(\n    async (value = '', _page = 1, sortBy, sortOrder) => {\n      setIsLoading(true);\n      setPage(_page);\n      if (_page === 1) {\n        setLoaded(false);\n      }\n      try {\n        const { products: _products, hasNextPage } = await getProducts(\n          value,\n          _page,\n          sortBy,\n          sortOrder\n        );\n        const newProducts =\n          _page === 1 ? _products : [...products, ..._products];\n        setProducts(newProducts);\n        setCanLoadMore(hasNextPage);\n      } catch (err) {\n        trackError('search_products', err?.message);\n        showSnackbar({ message: err.message });\n        if (_page === 1) {\n          setProducts([]);\n          setPage(1);\n        }\n        setCanLoadMore(false);\n      } finally {\n        setIsLoading(false);\n        setLoaded(true);\n      }\n    },\n    [getProducts, products, showSnackbar]\n  );\n\n  const searchProductsWithTelemetry = useCallback(\n    (value = '', _page, sortBy, sortOrder) => {\n      searchProducts(value, _page, sortBy, sortOrder);\n      trackEvent('search', {\n        search_type: 'products',\n        search_term: value,\n        search_order: sortOrder,\n        search_orderby: sortBy,\n        search_provider: shoppingProvider,\n      });\n    },\n    [searchProducts, shoppingProvider]\n  );\n\n  const debouncedProductsQuery = useDebouncedCallback(\n    searchProductsWithTelemetry,\n    300\n  );\n\n  const onSearch = useCallback(\n    (evt) => {\n      const value = evt.target.value;\n      if (value !== searchTerm) {\n        setSearchTerm(value);\n        debouncedProductsQuery(value, 1, orderby, order);\n      }\n    },\n    [debouncedProductsQuery, order, orderby, searchTerm]\n  );\n\n  const isShoppingEnabled = 'none' !== shoppingProvider;\n\n  useEffect(() => {\n    if (isShoppingEnabled) {\n      searchProducts(searchTerm, page, orderby, order);\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Only run once on mount.\n  }, [isShoppingEnabled]);\n\n  const numProducts = products.length;\n\n  useEffect(() => {\n    if (!isShoppingEnabled && numProducts === 0) {\n      setProducts(currentPageProducts?.map(({ product }) => product));\n      setIsLoading(false);\n      setLoaded(true);\n    }\n  }, [currentPageProducts, isShoppingEnabled, numProducts]);\n\n  const handleFocus = () => setIsMenuFocused(false);\n\n  const onSortBy = useCallback(\n    (option) => {\n      setOrderby(option.orderby);\n      setOrder(option.order);\n      debouncedProductsQuery(searchTerm, 1, option.orderby, option.order);\n    },\n    [debouncedProductsQuery, searchTerm]\n  );\n\n  const handleInputKeyPress = useCallback((event) => {\n    const { key } = event;\n    if (key === 'ArrowDown' || key === 'Tab') {\n      setIsMenuFocused(true);\n    }\n  }, []);\n\n  const insertProduct = useCallback(\n    (product) => {\n      insertElement(ELEMENT_TYPES.PRODUCT, {\n        width: PRODUCT_WIDTH,\n        height: PRODUCT_HEIGHT,\n        product,\n      });\n\n      trackEvent('insert_product', {\n        page: currentPageNumber,\n        provider: shoppingProvider,\n      });\n\n      const PRODUCT_ADDED_TEXT = sprintf(\n        /* translators: %s: product title. */\n        __('%s added to page', 'web-stories'),\n        product.productTitle\n      );\n\n      speak(PRODUCT_ADDED_TEXT);\n    },\n    [insertElement, speak, currentPageNumber, shoppingProvider]\n  );\n\n  const deleteProduct = useCallback(\n    (product) => {\n      const element = currentPageProducts.find(\n        (item) => item.product.productId === product.productId\n      );\n      if (element) {\n        deleteElementById({ elementId: element.elementId });\n\n        const PRODUCT_REMOVED_TEXT = sprintf(\n          /* translators: %s: product title. */\n          __('%s removed', 'web-stories'),\n          product?.productTitle\n        );\n\n        speak(PRODUCT_REMOVED_TEXT);\n      }\n    },\n    [deleteElementById, currentPageProducts, speak]\n  );\n\n  const onClick = useCallback(\n    (product, onPage) =>\n      onPage ? deleteProduct(product) : insertProduct(product),\n    [deleteProduct, insertProduct]\n  );\n\n  const handleClearInput = useCallback(() => {\n    setSearchTerm('');\n    debouncedProductsQuery('', 1, orderby, order);\n  }, [debouncedProductsQuery, order, orderby]);\n\n  const onLoadMore = useCallback(() => {\n    if (canLoadMore) {\n      searchProducts(searchTerm, page + 1, orderby, order);\n    }\n  }, [canLoadMore, searchProducts, order, orderby, page, searchTerm]);\n\n  const allDataLoadedMessage =\n    page > 1 ? __('No more products', 'web-stories') : '';\n\n  return (\n    <Pane id={paneId} {...props}>\n      <Section\n        data-testid=\"products-library-pane\"\n        title={__('Products', 'web-stories')}\n      >\n        <Row>\n          <HelperText>\n            {__(\n              'This will add products as a tappable dot on your story.',\n              'web-stories'\n            )}\n          </HelperText>\n        </Row>\n        {isShoppingEnabled && (\n          <Row>\n            <SearchInput\n              aria-label={__('Product search', 'web-stories')}\n              inputValue={searchTerm}\n              onChange={onSearch}\n              placeholder={__('Search', 'web-stories')}\n              onKeyDown={handleInputKeyPress}\n              onFocus={handleFocus}\n              isOpen\n              ariaClearLabel={__('Clear product search', 'web-stories')}\n              clearId=\"clear-product-search\"\n              handleClearInput={handleClearInput}\n            />\n            <ProductSort onChange={onSortBy} value={`${orderby}-${order}`} />\n          </Row>\n        )}\n        {!loaded && isLoading && (\n          <LoadingContainer>\n            <LoadingSpinner {...loadingSpinnerProps} />\n          </LoadingContainer>\n        )}\n        {loaded && products?.length > 0 && (\n          <>\n            <ProductList\n              isMenuFocused={isMenuFocused}\n              onClick={onClick}\n              products={products}\n              onPageProducts={currentPageProducts}\n            />\n            <InfiniteScroller\n              allDataLoadedMessage={allDataLoadedMessage}\n              allDataLoadedAriaMessage={__(\n                'Products are loaded',\n                'web-stories'\n              )}\n              onLoadMore={onLoadMore}\n              canLoadMore={canLoadMore}\n              isLoading={isLoading}\n              loadingSpinnerProps={loadingSpinnerProps}\n              loadingAriaMessage={__('Loading more products', 'web-stories')}\n            />\n          </>\n        )}\n        {loaded && !isLoading && products?.length === 0 && (\n          <HelperText>{__('No products found.', 'web-stories')}</HelperText>\n        )}\n      </Section>\n    </Pane>\n  );\n}\n\nexport default ShoppingPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport ProductList from '../productList';\nimport { ConfigContext } from '../../../../../app/config';\n\nconst Container = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  max-width: 350px;\n`;\n\nconst products = [\n  {\n    productId: 'sb-36',\n    productTitle: 'Hoodie with Pocket',\n    productBrand: '',\n    productPrice: 35,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-pocket/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-pocket/',\n  },\n  {\n    productId: 'sb-37',\n    productTitle: 'Hoodie with Zipper',\n    productBrand: '',\n    productPrice: 45,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-zipper/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-zipper/',\n  },\n  {\n    productId: 'sb-38',\n    productTitle: 'Hoodie',\n    productBrand: '',\n    productPrice: 42,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'https://wp.stories.google/static/main/images/templates/fresh-and-bright/page1_bg-alt.png',\n        alt: '',\n      },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie/',\n    },\n    productDetails: 'This is a variable product.',\n    productUrl: 'http://localhost:10004/product/hoodie/',\n  },\n  {\n    productId: 'sb-39',\n    productTitle: 'Hoodie with Logo',\n    productBrand: '',\n    productPrice: 45,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-logo/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-logo/',\n  },\n];\n\nconst configValue = {\n  locale: 'en-US',\n};\n\nexport default {\n  title: 'Stories Editor/Components/ProductList',\n  component: ProductList,\n  args: {\n    products,\n    isMenuFocused: true,\n    onPageProducts: [],\n  },\n  argTypes: {\n    onClick: { action: 'button clicked' },\n  },\n};\n\nexport const PageWithProducts = {\n  render: function Render(args) {\n    return (\n      <ConfigContext.Provider value={configValue}>\n        <Container>\n          <ProductList\n            {...args}\n            onPageProducts={[\n              { elementId: '123', product: { productId: 'sb-38' } },\n            ]}\n          />\n        </Container>\n      </ConfigContext.Provider>\n    );\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <ConfigContext.Provider value={configValue}>\n        <Container>\n          <ProductList {...args} />\n        </Container>\n      </ConfigContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/shopping/useProductNavigation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useState,\n  useEffect,\n  useRef,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nfunction useProductNavigation({ isMenuFocused, products = [] }) {\n  const currentRowsRef = useRef([]);\n  const [currentFocusIndex, setCurrentFocusIndex] = useState(0);\n  useEffect(() => {\n    const el = currentRowsRef.current[`row-${currentFocusIndex}`];\n    if (!el) {\n      return;\n    }\n    if (!isMenuFocused || el.contains(document.activeElement)) {\n      return;\n    }\n    el.focus();\n  }, [currentFocusIndex, isMenuFocused]);\n\n  // Handles managing the which `row` index has focus\n  // Arrows move the index up or down by 1\n  // unless we're at the start or the end\n  // after we update the index using setCurrentFocusIndex\n  // the element will get focus via the useEffect above el.focus();\n  const handleListNav = useCallback(\n    (evt) => {\n      const { key } = evt;\n      if (key === 'ArrowUp') {\n        evt.preventDefault();\n        setCurrentFocusIndex((index) => Math.max(0, index - 1));\n      } else if (key === 'ArrowDown') {\n        evt.preventDefault();\n        setCurrentFocusIndex((index) =>\n          Math.min(products.length - 1, index + 1)\n        );\n      }\n    },\n    [products]\n  );\n\n  return { handleListNav, currentRowsRef, setCurrentFocusIndex };\n}\n\nuseProductNavigation.propTypes = {\n  isMenuFocused: PropTypes.bool,\n  products: PropTypes.arrayOf(PropTypes.object),\n};\n\nexport default useProductNavigation;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/fontPreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useEffect,\n  useCallback,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport {\n  Text,\n  useKeyDownEffect,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useUnits } from '@googleforcreators/units';\nimport { stripHTML } from '@googleforcreators/dom';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport { useFont, useStory } from '../../../../app';\nimport { useCalculateAccessibleTextColors } from '../../../../app/pageCanvas';\nimport { StoryPropTypes } from '../../../../propTypes';\nimport useLibrary from '../../useLibrary';\nimport LibraryMoveable from '../shared/libraryMoveable';\nimport InsertionOverlay from '../shared/insertionOverlay';\nimport useRovingTabIndex from '../../../../utils/useRovingTabIndex';\nimport { areAllType, getTextInlineStyles } from '../../../../utils/presetUtils';\nimport objectWithout from '../../../../utils/objectWithout';\nimport getUpdatedSizeAndPosition from '../../../../utils/getUpdatedSizeAndPosition';\nimport { focusStyle } from '../../../panels/shared/styles';\n\n// If text is selected, there's no `+` icon displayed and we display the focus style on the button directly.\nconst Preview = styled.button`\n  position: relative;\n  display: flex;\n  align-items: center;\n  background-color: ${({ theme }) =>\n    theme.colors.interactiveBg.secondaryNormal};\n  padding: 8px 0px;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  width: 100%;\n  border: none;\n  cursor: pointer;\n  text-align: left;\n\n  ${({ isTextSelected }) => (isTextSelected ? focusStyle : 'outline: none;')}\n\n  &:focus-visible [role='presentation'] {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst PreviewText = styled(Text.Span)`\n  color: ${({ theme, isClone }) =>\n    isClone ? theme.colors.standard.black : theme.colors.fg.primary};\n  font-size: ${({ fontSize }) => fontSize}px;\n  font-weight: ${({ fontWeight }) => fontWeight};\n  font-family: ${({ fontFamily }) => fontFamily};\n  line-height: normal;\n  margin: ${({ isClone }) => (isClone ? 0 : '0px 16px')};\n`;\n\nconst DragContainer = styled.div`\n  position: absolute;\n  opacity: 0;\n  background-color: ${({ theme }) => theme.colors.opacity.white24};\n  width: ${({ width }) => width}px;\n  line-height: ${({ lineHeight }) => lineHeight}px;\n`;\n\nfunction FontPreview({ title, element, insertPreset, getPosition, index }) {\n  const htmlFormatters = getHTMLFormatters();\n  const { font, fontSize, content } = element;\n  const { fontWeight } = getTextInlineStyles(content);\n  const {\n    actions: { maybeEnqueueFontStyle },\n  } = useFont();\n\n  const { dataToEditorX, dataToEditorY } = useUnits((state) => ({\n    dataToEditorX: state.actions.dataToEditorX,\n    dataToEditorY: state.actions.dataToEditorY,\n  }));\n\n  const { shouldUseSmartColor } = useLibrary((state) => ({\n    shouldUseSmartColor: state.state.shouldUseSmartColor,\n  }));\n\n  const calculateAccessibleTextColors = useCalculateAccessibleTextColors();\n\n  const { isTextSelected, updateSelectedElements } = useStory(\n    ({ state, actions }) => ({\n      isTextSelected: areAllType('text', state.selectedElements),\n      updateSelectedElements: actions.updateSelectedElements,\n    })\n  );\n\n  const buttonRef = useRef(null);\n\n  useEffect(() => {\n    maybeEnqueueFontStyle([\n      {\n        font,\n        fontWeight,\n        content: stripHTML(content),\n      },\n    ]);\n  }, [font, fontWeight, content, maybeEnqueueFontStyle]);\n\n  const applyStyleOnContent = useCallback(\n    (\n      { fontWeight: newFontWeight, isItalic, isUnderline, letterSpacing },\n      elContent\n    ) => {\n      elContent = htmlFormatters.setFontWeight(elContent, newFontWeight);\n      elContent = htmlFormatters.toggleItalic(elContent, isItalic);\n      elContent = htmlFormatters.toggleUnderline(elContent, isUnderline);\n      elContent = htmlFormatters.setLetterSpacing(elContent, letterSpacing);\n      return elContent;\n    },\n    [htmlFormatters]\n  );\n\n  const onClick = useCallback(async () => {\n    // If we have only text(s) selected, we apply the preset instead of inserting.\n    if (isTextSelected) {\n      updateSelectedElements({\n        properties: (oldElement) => {\n          const newContent = applyStyleOnContent(\n            getTextInlineStyles(element.content),\n            oldElement.content\n          );\n          const presetAtts = objectWithout(element, [\n            'x',\n            'y',\n            'content',\n            'width',\n          ]);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...oldElement,\n            ...presetAtts,\n          });\n          return {\n            ...oldElement,\n            ...presetAtts,\n            ...sizeUpdates,\n            content: newContent,\n          };\n        },\n      });\n      return;\n    }\n\n    let newElement = element;\n    const insertOpts = {\n      isPositioned: false,\n    };\n    if (shouldUseSmartColor) {\n      const position = getPosition(element);\n      insertOpts.isPositioned = true;\n      newElement = {\n        ...element,\n        ...position,\n      };\n      insertOpts.accessibleColors =\n        await calculateAccessibleTextColors(newElement);\n    }\n    insertPreset(newElement, insertOpts);\n    trackEvent('insert_text_preset', { name: title });\n  }, [\n    isTextSelected,\n    getPosition,\n    element,\n    shouldUseSmartColor,\n    insertPreset,\n    title,\n    updateSelectedElements,\n    applyStyleOnContent,\n    calculateAccessibleTextColors,\n  ]);\n\n  const getTextDisplay = (textProps = {}) => {\n    const { isClone } = textProps;\n    return (\n      <PreviewText\n        font={font}\n        fontSize={fontSize}\n        fontWeight={fontWeight}\n        {...textProps}\n      >\n        {isClone ? stripHTML(content) : title}\n      </PreviewText>\n    );\n  };\n\n  useKeyDownEffect(\n    buttonRef,\n    {\n      key: ['enter', 'space'],\n    },\n    onClick,\n    [onClick]\n  );\n\n  useRovingTabIndex({ ref: buttonRef });\n\n  const [active, setActive] = useState(false);\n  const makeActive = () => setActive(true);\n  const makeInactive = () => setActive(false);\n\n  return (\n    <Preview\n      ref={buttonRef}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n      tabIndex={index === 0 ? 0 : -1}\n      isTextSelected={isTextSelected}\n      aria-label={\n        isTextSelected\n          ? sprintf(\n              /* translators: %s: preset name */\n              __('Apply preset: %s', 'web-stories'),\n              title\n            )\n          : null\n      }\n    >\n      {getTextDisplay()}\n      {active && !isTextSelected && <InsertionOverlay />}\n      <LibraryMoveable\n        cloneElement={DragContainer}\n        cloneProps={{\n          children: getTextDisplay({\n            fontSize: dataToEditorY(fontSize),\n            isClone: true,\n          }),\n          width: dataToEditorX(element.width),\n          lineHeight: Math.ceil(dataToEditorY(fontSize)),\n        }}\n        elementProps={element}\n        type={'text'}\n        onClick={onClick}\n      />\n    </Preview>\n  );\n}\n\nFontPreview.propTypes = {\n  title: PropTypes.string.isRequired,\n  element: StoryPropTypes.textContent.isRequired,\n  insertPreset: PropTypes.func.isRequired,\n  getPosition: PropTypes.func.isRequired,\n  index: PropTypes.number.isRequired,\n};\n\nexport default FontPreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as TextPane } from './textPane';\nexport { default as TextIcon } from './textIcon';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/karma/savedStyles.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Library: Saved Styles', () => {\n  let fixture;\n\n  const getSelection = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  };\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n    localStorage.clear();\n  });\n\n  describe('User can apply style and create new styled texts from Saved Styles panel in Library', () => {\n    it('should allow adding new styled text element and applying style from the same button', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      // Click to add a style and verify it was added.\n      await fixture.events.click(fixture.editor.library.text.addStyleButton);\n      expect(fixture.editor.library.text.applyStyleButtons.length).toBe(1);\n\n      // Add a shape element to select a different type of element.\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n      await fixture.editor.library.textTab.click();\n\n      const addTextButton =\n        fixture.editor.library.text.addTextWithStyleButtons[0];\n      await fixture.events.click(addTextButton);\n\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[3].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[3].node).toBeTruthy();\n      });\n\n      // Verify the new paragraph was added with the same style as the saved style from Title 1.\n      const [lastAdded] = await getSelection();\n      expect(lastAdded.type).toBe('text');\n      expect(lastAdded.fontSize).toBe(36);\n      expect(lastAdded.content).toBe(\n        '<span style=\"font-weight: 700\">Fill in some text</span>'\n      );\n\n      // Select background for being able to insert another text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      // Add a Label and click the same button again with selected text element now.\n      await fixture.events.click(fixture.editor.library.text.preset('LABEL'));\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[4].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[4].node).toBeTruthy();\n      });\n      // Verify original size.\n      const [originalLabel] = await getSelection();\n      expect(originalLabel.fontSize).toBe(12);\n\n      // Apply style.\n      const applyStyleButton = fixture.editor.library.text.applyStyleButtons[0];\n      await fixture.events.click(applyStyleButton);\n\n      // Verify the style was applied here, too.\n      const [label] = await getSelection();\n      expect(label.fontSize).toBe(36);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/karma/textPane.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\nimport { dataFontEm, dataPixels } from '@googleforcreators/units';\nimport { stripHTML } from '@googleforcreators/dom';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\nimport { PRESETS } from '../textPresets';\n\nconst TIMEOUT_INTERVAL = 300000;\n\ndescribe('CUJ: Creator can Add and Write Text: Consecutive text presets', () => {\n  let fixture;\n  let originalTimeout;\n\n  beforeEach(async () => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = TIMEOUT_INTERVAL;\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;\n    fixture.restore();\n  });\n\n  async function addPreset(name) {\n    // Select background for being able to insert a text.\n    await fixture.events.mouse.clickOn(\n      fixture.editor.canvas.framesLayer.frames[0].node,\n      '2%',\n      '2%'\n    );\n    // Imitate the movement of real use to trigger the background processes while the user is moving the mouse.\n    await fixture.events.mouse.moveRel(\n      fixture.editor.library.text.preset(name),\n      10,\n      10,\n      { steps: 2 }\n    );\n    await fixture.events.click(fixture.editor.library.text.preset(name));\n  }\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  }\n\n  describe('Adding text presets', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      // Give some time for everything to be ready for the tests.\n      await fixture.events.sleep(800);\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[0].node) {\n          throw new Error('node not ready');\n        }\n      });\n    });\n\n    it('should add text preset via dragging from the preview', async () => {\n      // Only background initially\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n      const title = fixture.editor.library.text.preset('Title 1');\n      const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n      await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n        moveRel(title, 10, 10),\n        down(),\n        /* The steps give time for Moveable to react and display a clone to drag */\n        moveRel(bgFrame, 50, 50, { steps: 20 }),\n        up(),\n      ]);\n      // Now background + 1 extra element\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(2);\n    });\n  });\n\n  describe('Applying text presets', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      // Give some time for everything to be ready for the tests.\n      await fixture.events.sleep(800);\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[0].node) {\n          throw new Error('node not ready');\n        }\n      });\n    });\n\n    it('should apply Title preset to a label', async () => {\n      // Only background initially\n      expect(fixture.editor.canvas.framesLayer.frames.length).toBe(1);\n\n      // Add label.\n      await fixture.events.click(fixture.editor.library.text.preset('LABEL'));\n      const [label] = await getSelection();\n      expect(label.fontSize).toBe(12);\n\n      // Apply Title 1.\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Apply preset: Title 1')\n      );\n      // Verify the font size and font weight were applied.\n      const [styledLabel] = await getSelection();\n      expect(styledLabel.fontSize).toBe(36);\n      expect(styledLabel.content).toBe(\n        '<span style=\"font-weight: 700\">LABEL</span>'\n      );\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- TODO: Fix flakey test.\n    xit('should overwrite most of the styles but not text color when applying a preset', async () => {\n      // Add label.\n      await fixture.events.click(fixture.editor.library.text.preset('LABEL'));\n\n      // Open style pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.alignment.right\n      );\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.fill\n      );\n\n      const { italic, underline, letterSpacing, fontColor } =\n        fixture.editor.sidebar.designPanel.textStyle;\n\n      // First enter edit mode, select something, style it with all styles and exit edit mode\n      await fixture.events.click(letterSpacing, { clickCount: 3 });\n      await fixture.events.keyboard.type('50');\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('Escape');\n      await fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await fixture.events.keyboard.type('FFFFFF');\n      await fixture.events.keyboard.press('Tab');\n      await fixture.events.keyboard.press('Escape');\n      await fixture.events.click(italic.button);\n      await fixture.events.click(underline.button);\n\n      const [label] = await getSelection();\n      expect(label.content).toBe(\n        '<span style=\"font-style: italic; text-decoration: underline; color: #fff; letter-spacing: 0.5em\">LABEL</span>'\n      );\n\n      // Go to text tab in insert panel\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n\n      // Apply Title 1.\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Apply preset: Title 1')\n      );\n      // Verify the style except for color was overwritten.\n      const [styledLabel] = await getSelection();\n      expect(styledLabel.fontSize).toBe(36);\n      expect(styledLabel.content).toBe(\n        '<span style=\"font-weight: 700; color: #fff\">LABEL</span>'\n      );\n    });\n  });\n\n  describe('Adding texts consecutively', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      // Give some time for everything to be ready for the tests.\n      await fixture.events.sleep(800);\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[0].node) {\n          throw new Error('node not ready');\n        }\n      });\n    });\n\n    it('should add text presets below each other if added consecutively', async () => {\n      await fixture.events.mouse.moveRel(\n        fixture.editor.library.text.preset('Title 1'),\n        10,\n        10\n      );\n\n      await waitFor(\n        () => {\n          if (!fixture.editor.library.text.textSets.length) {\n            throw new Error('Text set not ready');\n          }\n          expect(fixture.editor.library.text.textSets.length).toBeGreaterThan(\n            0\n          );\n        },\n        { timeout: TIMEOUT_INTERVAL / 3 }\n      );\n\n      await addPreset('Title 1');\n      await addPreset('Title 3');\n      await addPreset('Paragraph');\n\n      await fixture.snapshot('consecutively added different text presets');\n    });\n\n    it('should ensure staggered presets fit on the page', async () => {\n      const POSITION_MARGIN = dataFontEm(1);\n      const PARAGRAPH_TEXT = 'Fill in some text';\n      let lastY;\n      let lastHeight;\n      let nextY;\n      let nextHeight;\n      let storyContext;\n      let nodeIndex = 1;\n\n      const verifyDefaultPosition = async (name, content) => {\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[nodeIndex].node) {\n            throw new Error('node not ready');\n          }\n          expect(\n            fixture.editor.canvas.framesLayer.frames[nodeIndex].node\n          ).toBeTruthy();\n        });\n        nodeIndex++;\n        storyContext = await fixture.renderHook(() => useStory());\n        let element = null;\n        await waitFor(() => {\n          element = storyContext.state.selectedElements[0];\n          if (!element) {\n            throw new Error('story not ready');\n          }\n          expect(stripHTML(element.content)).toEqual(content);\n          const preset = PRESETS.find(({ title }) => name === title);\n          expect(element.y).toEqual(dataPixels(preset.element.y));\n        });\n        nextY = element.y;\n        nextHeight = element.height;\n      };\n\n      const verifyStaggeredPosition = async (content) => {\n        await waitFor(() => {\n          if (!fixture.editor.canvas.framesLayer.frames[nodeIndex].node) {\n            throw new Error('node not ready');\n          }\n          expect(\n            fixture.editor.canvas.framesLayer.frames[nodeIndex].node\n          ).toBeTruthy();\n        });\n        nodeIndex++;\n        // Store both last and next value to ensure incorrect value isn't used within waitFor.\n        lastY = nextY;\n        lastHeight = nextHeight;\n        storyContext = await fixture.renderHook(() => useStory());\n        let element = null;\n        await waitFor(() => {\n          element = storyContext.state.selectedElements[0];\n          if (!element) {\n            throw new Error('story not ready');\n          }\n          expect(stripHTML(element.content)).toEqual(content);\n          expect(element.y).toEqual(\n            dataPixels(lastY + lastHeight + POSITION_MARGIN)\n          );\n        });\n        nextY = element.y;\n        nextHeight = element.height;\n      };\n      await fixture.events.mouse.moveRel(\n        fixture.editor.library.text.preset('Title 1'),\n        10,\n        10\n      );\n\n      await waitFor(\n        () => {\n          if (!fixture.editor.library.text.textSets.length) {\n            throw new Error('text set not ready');\n          }\n          expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n        },\n        {\n          timeout: TIMEOUT_INTERVAL / 3,\n        }\n      );\n\n      // Stagger all different text presets.\n      await addPreset('Title 1');\n      await verifyDefaultPosition('Title 1', 'Title 1');\n\n      await addPreset('Paragraph');\n      await verifyStaggeredPosition(PARAGRAPH_TEXT);\n\n      await addPreset('Title 2');\n      await verifyStaggeredPosition('Title 2');\n\n      await addPreset('Paragraph');\n      await verifyStaggeredPosition(PARAGRAPH_TEXT);\n\n      await addPreset('Title 3');\n      await verifyStaggeredPosition('Title 3');\n\n      await addPreset('Paragraph');\n      await verifyStaggeredPosition(PARAGRAPH_TEXT);\n\n      await addPreset('Caption');\n      await verifyStaggeredPosition('Caption');\n\n      await addPreset('Paragraph');\n      await verifyStaggeredPosition(PARAGRAPH_TEXT);\n\n      await addPreset('Paragraph');\n      await verifyDefaultPosition('Paragraph', PARAGRAPH_TEXT);\n\n      await addPreset('LABEL');\n      await verifyStaggeredPosition('LABEL');\n\n      await fixture.snapshot('staggered all text presets');\n    });\n  });\n\n  describe('Easier/smarter text color', () => {\n    it('should add text color based on background', async () => {\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n      );\n      await fixture.events.keyboard.type('000');\n      await fixture.events.keyboard.press('Tab');\n\n      // Enable the smart colors first.\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      fixture.editor.library.text.smartColorToggle.click();\n\n      // Should be added with white style on black background.\n      await fixture.events.mouse.moveRel(\n        fixture.editor.library.text.preset('Paragraph'),\n        10,\n        10\n      );\n      await fixture.events.sleep(800);\n      // Select background for being able to insert another text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(\n        () => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n        },\n        { timeout: 3000 }\n      );\n\n      const [text1] = await getSelection();\n      expect(text1.content).toEqual(\n        '<span style=\"color: #fff\">Fill in some text</span>'\n      );\n\n      // Select background for being able to insert another text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      await fixture.events.mouse.moveRel(\n        fixture.editor.library.text.preset('Title 1'),\n        10,\n        10\n      );\n      await fixture.events.sleep(800);\n      // Should be added with white style on black background.\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[2].node) {\n          throw new Error('node not ready');\n        }\n      });\n      const [title] = await getSelection();\n      expect(title.content).toEqual(\n        '<span style=\"font-weight: 700; color: #fff\">Title 1</span>'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/karma/textSets.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('CUJ: Text Sets (Text and Shape Combinations): Using Text Sets', () => {\n  let fixture;\n  let originalTimeout;\n\n  beforeEach(async () => {\n    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.editor.library.textTab.click();\n  });\n\n  afterEach(() => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;\n    fixture.restore();\n  });\n\n  it('should display text sets', async () => {\n    await waitFor(\n      () => {\n        if (fixture.editor.library.text.textSets.length === 0) {\n          throw new Error('text sets not ready');\n        }\n        expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n      },\n      { timeout: 2000 }\n    );\n  });\n\n  it('should allow inserting text sets', async () => {\n    await waitFor(\n      () => {\n        if (fixture.editor.library.text.textSets.length === 0) {\n          throw new Error('text sets not ready');\n        }\n        expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n      },\n      { timeout: 2000 }\n    );\n    const textSets = fixture.editor.library.text.textSets;\n    await fixture.events.click(textSets[1]);\n\n    // Wait for text set to be inserted\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[2].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // Text sets contain at least 2 elements.\n    expect((await getSelection()).length).toBeGreaterThan(1);\n  });\n\n  it('should allow inserting text set by keyboard', async () => {\n    await waitFor(\n      () => {\n        if (fixture.editor.library.text.textSets.length === 0) {\n          throw new Error('text sets not ready');\n        }\n        expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n      },\n      { timeout: 2000 }\n    );\n    const textSets = fixture.editor.library.text.textSets;\n\n    await fixture.events.focus(textSets[0]);\n\n    await fixture.events.keyboard.press('down');\n\n    const activeTextSetId = textSets[2].getAttribute('data-testid');\n    const documentTestId = document.activeElement.getAttribute('data-testid');\n\n    expect(activeTextSetId).toBe(documentTestId);\n    await fixture.events.keyboard.press('Enter');\n\n    // Wait for text set to be inserted\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[2].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // Text sets contain at least 2 elements.\n    expect((await getSelection()).length).toBeGreaterThan(1);\n  });\n\n  it('should allow user to drag and drop text set onto page', async () => {\n    await waitFor(\n      () => {\n        if (fixture.editor.library.text.textSets.length === 0) {\n          throw new Error('text sets not ready');\n        }\n        expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n      },\n      { timeout: 2000 }\n    );\n\n    const textSet = fixture.editor.library.text.textSets[1];\n    const page = fixture.editor.canvas.framesLayer.fullbleed;\n\n    textSet.scrollIntoView();\n    await fixture.events.mouse.moveRel(textSet, 25, 25);\n    await fixture.events.mouse.down();\n    await fixture.events.mouse.moveRel(page, 50, 100, { steps: 20 });\n    await fixture.snapshot('Text set dragged');\n    await fixture.events.mouse.up();\n\n    await fixture.renderHook(() => useStory());\n\n    // After text set has been added, there should some text elements\n    await fixture.snapshot('Text set added');\n    expect((await getSelection()).length).toBeGreaterThan(1);\n  });\n\n  it('should allow filtering text sets by category', async () => {\n    await waitFor(() => {\n      if (!fixture.editor.library.text.textSetFilter('Editorial')) {\n        throw new Error('filtering not ready');\n      }\n      expect(\n        fixture.editor.library.text.textSetFilter('Editorial')\n      ).toBeTruthy();\n    });\n    await fixture.events.click(\n      fixture.editor.library.text.textSetFilter('Editorial')\n    );\n    expect(fixture.editor.library.text.textSets.length).toBe(15);\n  });\n\n  it('should position the text sets as expected by category', async () => {\n    await waitFor(\n      () => {\n        if (fixture.editor.library.text.textSets.length === 0) {\n          throw new Error('text sets not ready');\n        }\n        expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n      },\n      { timeout: 2000 }\n    );\n\n    await fixture.events.click(\n      fixture.editor.library.text.textSetFilter('Editorial')\n    );\n    const editorialTextSets = await waitFor(() => {\n      if (!fixture.editor.library.text.textSets) {\n        throw new Error('editorialTextSets not ready');\n      }\n      return fixture.editor.library.text.textSets;\n    });\n    await fixture.events.click(editorialTextSets[0]);\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.snapshot('Editorial text set positioning');\n\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.events.click(\n      fixture.editor.library.text.textSetFilter('Header')\n    );\n    const headerTextSets = await waitFor(() => {\n      if (!fixture.editor.library.text.textSets) {\n        throw new Error('headerTextSets set not ready');\n      }\n      return fixture.editor.library.text.textSets;\n    });\n\n    await fixture.events.click(headerTextSets[0]);\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.snapshot('List text set positioning');\n\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.events.click(\n      fixture.editor.library.text.textSetFilter('Steps')\n    );\n    const stepsTextSets = await waitFor(() => {\n      if (!fixture.editor.library.text.textSets) {\n        throw new Error('stepsTextSets not ready');\n      }\n      return fixture.editor.library.text.textSets;\n    });\n    await fixture.events.click(stepsTextSets[0]);\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    await fixture.snapshot('Steps text set positioning');\n  });\n\n  describe('Easier/smarter text set color', () => {\n    it('should add text color based on background', async () => {\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n      );\n      await fixture.events.keyboard.type('000');\n      await fixture.events.keyboard.press('Tab');\n\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      await fixture.editor.library.text.smartColorToggle.click();\n\n      const textSets = await waitFor(\n        () => {\n          if (!fixture.editor.library.text.textSets.length) {\n            throw new Error('text set not ready');\n          }\n          expect(fixture.editor.library.text.textSets.length).toBeTruthy();\n\n          return fixture.editor.library.text.textSets;\n        },\n        { timeout: 2000 }\n      );\n      // First hover text set to trigger image generation\n      await fixture.events.mouse.moveRel(textSets[1], 10, 10);\n\n      await fixture.events.sleep(800);\n      // Then click the text set\n      await fixture.events.click(textSets[1]);\n\n      await waitFor(\n        () => {\n          if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n            throw new Error('node not ready');\n          }\n          expect(\n            fixture.editor.canvas.framesLayer.frames[1].node\n          ).toBeDefined();\n        },\n        { timeout: 5000 }\n      );\n      const selection = await getSelection();\n      // Text color should be changed to white, since it's placed on a dark background.\n      expect(selection[0].content).toEqual(\n        '<span style=\"font-weight: 600; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\">Category</span>'\n      );\n    });\n  });\n\n  async function getSelection() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/paneId.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getPaneId } from '../shared';\n\nexport default getPaneId('text');\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/stylePresets/stylePresets.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Headline,\n  TextSize,\n  Text,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n  Icons,\n  Button,\n  Placement,\n  Popup,\n  Disclosure,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { useCallback, useRef, useState, memo } from '@googleforcreators/react';\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../../app';\nimport { PRESET_TYPES } from '../../../../../constants';\nimport useAddPreset from '../../../../../utils/useAddPreset';\nimport { DEFAULT_PRESET } from '../textPresets';\nimport StyleGroup from '../../../../styleManager/styleGroup';\nimport StyleManager, {\n  NoStylesWrapper,\n  MoreButton,\n} from '../../../../styleManager';\nimport useLibrary from '../../../useLibrary';\nimport { areAllType } from '../../../../../utils/presetUtils';\nimport useApplyStyle from '../../../../styleManager/useApplyStyle';\nimport updateProperties from '../../../../style/updateProperties';\nimport getUpdatedSizeAndPosition from '../../../../../utils/getUpdatedSizeAndPosition';\nimport InsertionOverlay from '../../shared/insertionOverlay';\nimport { Container } from '../../../common/section';\n\nconst SectionContainer = styled(Container)`\n  padding: 16px 0;\n  margin-bottom: -24px;\n  border-top: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n`;\n\nconst TitleBar = styled.div`\n  display: flex;\n  padding-bottom: 16px;\n  justify-content: space-between;\n  align-items: center;\n`;\n\nconst StylesWrapper = styled.div``;\n\nconst StyledButton = styled(Button)`\n  margin-left: auto;\n`;\n\nconst NoStylesText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst SPACING = { x: 40 };\nconst TYPE = 'text';\nconst STYLE_BUTTON_WIDTH = 150;\n\nfunction PresetPanel() {\n  const { textStyles, isText, updateSelectedElements } = useStory(\n    ({ state, actions }) => ({\n      isText: Boolean(\n        state.selectedElements && areAllType(TYPE, state.selectedElements)\n      ),\n      textStyles: state.story?.globalStoryStyles?.textStyles || [],\n      updateSelectedElements: actions.updateSelectedElements,\n    })\n  );\n\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n\n  const {\n    setColor,\n    setFontWeight,\n    setLetterSpacing,\n    toggleItalic,\n    toggleUnderline,\n  } = getHTMLFormatters();\n\n  const buttonRef = useRef(null);\n  const stylesRef = useRef(null);\n  const [isPopupOpen, setIsPopupOpen] = useState(false);\n  const hasPresets = textStyles.length > 0;\n\n  const pushUpdate = useCallback(\n    (update) => {\n      updateSelectedElements({\n        properties: (element) => {\n          const updates = updateProperties(element, update, true);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...element,\n            ...updates,\n          });\n          return {\n            ...updates,\n            ...sizeUpdates,\n          };\n        },\n      });\n    },\n    [updateSelectedElements]\n  );\n\n  const handleApplyStyle = useApplyStyle({ pushUpdate });\n  const { addGlobalPreset } = useAddPreset({ presetType: PRESET_TYPES.STYLE });\n\n  const addStyledText = (preset) => {\n    // Get all the inline styles that saved styles support.\n    const { color, fontWeight, isItalic, isUnderline, letterSpacing } = preset;\n    let content = DEFAULT_PRESET.content;\n    content = setColor(content, color);\n    content = setFontWeight(content, fontWeight);\n    content = toggleItalic(content, isItalic);\n    content = toggleUnderline(content, isUnderline);\n    content = setLetterSpacing(content, letterSpacing);\n\n    insertElement(TYPE, {\n      ...DEFAULT_PRESET,\n      ...preset,\n      content,\n    });\n  };\n\n  const handlePresetClick = (preset) => {\n    if (isText) {\n      handleApplyStyle(preset);\n    } else {\n      addStyledText(preset);\n      setIsPopupOpen(false);\n    }\n  };\n\n  // If it's not text, we're displaying insertion overlay and label for adding a new text.\n  const styleItemProps = isText\n    ? {}\n    : {\n        activeItemOverlay: <InsertionOverlay />,\n        applyLabel: __('Add new text', 'web-stories'),\n      };\n\n  return (\n    <SectionContainer>\n      <TitleBar>\n        <Headline as=\"h2\" size={TextSize.XXXSmall}>\n          {__('Saved Styles', 'web-stories')}\n        </Headline>\n        <StyledButton\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          onClick={addGlobalPreset}\n          aria-label={__('Add style', 'web-stories')}\n          disabled={!isText}\n        >\n          <Icons.Plus />\n        </StyledButton>\n      </TitleBar>\n      {hasPresets && (\n        <>\n          <StylesWrapper ref={stylesRef}>\n            {/* We only show the insertion overlay if we're inserting -> this means selected elements are not texts */}\n            <StyleGroup\n              styles={[...textStyles].reverse().slice(0, 2)}\n              handleClick={handlePresetClick}\n              buttonWidth={STYLE_BUTTON_WIDTH}\n              {...styleItemProps}\n            />\n          </StylesWrapper>\n          <MoreButton\n            ref={buttonRef}\n            onClick={() => setIsPopupOpen(true)}\n            aria-haspopup=\"dialog\"\n            aria-expanded={isPopupOpen}\n          >\n            {__('More styles', 'web-stories')}\n            <Disclosure $isOpen={isPopupOpen} />\n          </MoreButton>\n          <Popup\n            anchor={buttonRef}\n            isOpen={isPopupOpen}\n            placement={Placement.RightStart}\n            spacing={SPACING}\n            renderContents={() => (\n              <StyleManager\n                styles={textStyles}\n                applyStyle={handlePresetClick}\n                onClose={() => setIsPopupOpen(false)}\n                {...styleItemProps}\n              />\n            )}\n          />\n        </>\n      )}\n      {!hasPresets && (\n        <NoStylesWrapper>\n          <NoStylesText size={TextSize.Small}>\n            {__('No Styles Saved', 'web-stories')}\n          </NoStylesText>\n        </NoStylesWrapper>\n      )}\n    </SectionContainer>\n  );\n}\n\nexport default memo(PresetPanel);\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction TextIcon() {\n  return <Icons.LetterT title={__('Text library', 'web-stories')} />;\n}\n\nexport default TextIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useRef,\n  useState,\n  useResizeEffect,\n  useMemo,\n  useCallback,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport { Text, TextSize, Toggle } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { usePageCanvas } from '../../../../app/pageCanvas';\nimport { Container as SectionContainer } from '../../common/section';\nimport { Pane as SharedPane } from '../shared';\nimport useLibrary from '../../useLibrary';\nimport Tooltip from '../../../tooltip';\nimport FontPreview from './fontPreview';\nimport paneId from './paneId';\nimport { PRESETS } from './textPresets';\nimport useInsertPreset from './useInsertPreset';\nimport TextSetsPane from './textSets/textSetsPane';\nimport PresetPanel from './stylePresets/stylePresets';\n\n// Relative position needed for Moveable to update its position properly.\nconst Pane = styled(SharedPane)`\n  overflow-y: scroll;\n  max-height: 100%;\n  position: relative;\n`;\n\nconst GridContainer = styled.div`\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 12px;\n`;\n\nconst SmartColorToggle = styled.div`\n  display: flex;\n\n  label {\n    cursor: pointer;\n    margin: auto 12px;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\n\nfunction TextPane(props) {\n  const paneRef = useRef();\n  const [, forceUpdate] = useState();\n\n  const { shouldUseSmartColor, setShouldUseSmartColor } = useLibrary(\n    (state) => ({\n      shouldUseSmartColor: state.state.shouldUseSmartColor,\n      setShouldUseSmartColor: state.actions.setShouldUseSmartColor,\n    })\n  );\n\n  const { getPosition, insertPreset } = useInsertPreset({\n    shouldUseSmartColor,\n  });\n  const generateDeferredCurrentPageCanvas = usePageCanvas(\n    ({ actions }) => actions.generateDeferredCurrentPageCanvas\n  );\n\n  useResizeEffect(paneRef, () => {\n    forceUpdate(Date.now());\n  }, []);\n\n  const handleToggleClick = useCallback(\n    () => setShouldUseSmartColor((currentValue) => !currentValue),\n    [setShouldUseSmartColor]\n  );\n\n  const toggleId = useMemo(() => `toggle_auto_color_${uuidv4()}`, []);\n  return (\n    <Pane id={paneId} {...props} ref={paneRef}>\n      <SmartColorToggle>\n        <Text.Label htmlFor={toggleId} size={TextSize.Small}>\n          {__('Adaptive text colors', 'web-stories')}\n        </Text.Label>\n        <Tooltip\n          title={__(\n            'May impact performance when inserting text',\n            'web-stories'\n          )}\n        >\n          <Toggle\n            id={toggleId}\n            checked={shouldUseSmartColor}\n            onChange={handleToggleClick}\n          />\n        </Tooltip>\n      </SmartColorToggle>\n      <SectionContainer\n        onPointerOver={() =>\n          shouldUseSmartColor && generateDeferredCurrentPageCanvas()\n        }\n      >\n        <GridContainer>\n          {PRESETS.map(({ title, element }, index) => (\n            <FontPreview\n              key={title}\n              title={title}\n              element={element}\n              insertPreset={insertPreset}\n              getPosition={getPosition}\n              index={index}\n            />\n          ))}\n        </GridContainer>\n      </SectionContainer>\n      <PresetPanel />\n      <TextSetsPane paneRef={paneRef} />\n    </Pane>\n  );\n}\n\nexport default TextPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textPresets.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\nimport { dataFontEm, PAGE_HEIGHT } from '@googleforcreators/units';\nimport {\n  TEXT_ELEMENT_DEFAULT_FONT,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { FONT_WEIGHT } from '../../../../constants';\n\n// Measured in editor. As small as you can make\n// width with preset font before line wraps\nconst DEFAULT_WIDTH = {\n  DEFAULT: 165,\n  HEADING_1: 186,\n  HEADING_2: 145,\n  HEADING_3: 120,\n  PARAGRAPH: 200,\n  CAPTION: 70,\n  LABEL: 56,\n};\n\n// @todo Once none of the elements are placed randomly, default x can be moved to text/index.js\nconst DEFAULT_LEFT_MARGIN = 48;\n\nconst DEFAULT_TEXT_BORDER_RADIUS = {\n  locked: true,\n  topLeft: 2,\n  topRight: 2,\n  bottomRight: 2,\n  bottomLeft: 2,\n};\n\nconst DEFAULT_TEXT_PADDING = {\n  locked: true,\n  hasHiddenPadding: false,\n  horizontal: 0,\n  vertical: 0,\n};\n\nconst DEFAULT_TEXT_ALIGN = 'left';\n\nconst DEFAULT_PRESET = {\n  content: _x('Fill in some text', 'text preset content', 'web-stories'),\n  fontSize: dataFontEm(1.33),\n  lineHeight: 1.2,\n  x: DEFAULT_LEFT_MARGIN,\n  y: (PAGE_HEIGHT - dataFontEm(1.33)) / 2,\n  font: TEXT_ELEMENT_DEFAULT_FONT,\n  width: DEFAULT_WIDTH.PARAGRAPH,\n  borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n  backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n  padding: DEFAULT_TEXT_PADDING,\n  textAlign: DEFAULT_TEXT_ALIGN,\n};\n\nconst PRESETS = [\n  {\n    title: _x('Title 1', 'text preset title', 'web-stories'),\n    element: {\n      content: `<span style=\"font-weight: ${FONT_WEIGHT.BOLD}\">${_x(\n        'Title 1',\n        'text preset content',\n        'web-stories'\n      )}</span>`,\n      fontSize: dataFontEm(2.667),\n      lineHeight: 1.19,\n      x: DEFAULT_LEFT_MARGIN,\n      y: (PAGE_HEIGHT - dataFontEm(2.667)) / 2,\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n      width: DEFAULT_WIDTH.HEADING_1,\n      borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n      padding: DEFAULT_TEXT_PADDING,\n      textAlign: DEFAULT_TEXT_ALIGN,\n    },\n  },\n  {\n    title: _x('Title 2', 'text preset title', 'web-stories'),\n    element: {\n      content: `<span style=\"font-weight: ${FONT_WEIGHT.BOLD}\">${_x(\n        'Title 2',\n        'text preset content',\n        'web-stories'\n      )}</span>`,\n      fontSize: dataFontEm(2),\n      lineHeight: 1.2,\n      x: DEFAULT_LEFT_MARGIN,\n      y: (PAGE_HEIGHT - dataFontEm(2)) / 2,\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n      width: DEFAULT_WIDTH.HEADING_2,\n      borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n      padding: DEFAULT_TEXT_PADDING,\n      textAlign: DEFAULT_TEXT_ALIGN,\n    },\n  },\n  {\n    title: _x('Title 3', 'text preset title', 'web-stories'),\n    element: {\n      content: `<span style=\"font-weight: ${FONT_WEIGHT.BOLD}\">${_x(\n        'Title 3',\n        'text preset content',\n        'web-stories'\n      )}</span>`,\n      fontSize: dataFontEm(1.6),\n      lineHeight: 1.2,\n      x: DEFAULT_LEFT_MARGIN,\n      y: (PAGE_HEIGHT - dataFontEm(1.6)) / 2,\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n      width: DEFAULT_WIDTH.HEADING_3,\n      borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n      padding: DEFAULT_TEXT_PADDING,\n      textAlign: DEFAULT_TEXT_ALIGN,\n    },\n  },\n  {\n    title: _x('Paragraph', 'text preset title', 'web-stories'),\n    element: DEFAULT_PRESET,\n  },\n  {\n    title: _x('Caption', 'text preset title', 'web-stories'),\n    element: {\n      content: `<span style=\"font-weight: ${FONT_WEIGHT.NORMAL}\">${_x(\n        'Caption',\n        'text preset content',\n        'web-stories'\n      )}</span>`,\n      fontSize: dataFontEm(1),\n      lineHeight: 1.2,\n      x: DEFAULT_LEFT_MARGIN,\n      y: (PAGE_HEIGHT - dataFontEm(1)) / 2,\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n      width: DEFAULT_WIDTH.CAPTION,\n      borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n      padding: DEFAULT_TEXT_PADDING,\n      textAlign: DEFAULT_TEXT_ALIGN,\n    },\n  },\n  {\n    title: _x('Label', 'text preset title', 'web-stories').toUpperCase(),\n    element: {\n      content: _x('Label', 'text preset content', 'web-stories').toUpperCase(),\n      fontSize: dataFontEm(0.888),\n      lineHeight: 1.2,\n      x: DEFAULT_LEFT_MARGIN,\n      y: (PAGE_HEIGHT - dataFontEm(0.888)) / 2,\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n      width: DEFAULT_WIDTH.LABEL,\n      borderRadius: DEFAULT_TEXT_BORDER_RADIUS,\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n      padding: DEFAULT_TEXT_PADDING,\n      textAlign: DEFAULT_TEXT_ALIGN,\n    },\n  },\n];\n\nexport { DEFAULT_PRESET, PRESETS };\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\nimport { PAGE_RATIO } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { TEXT_SET_SIZE } from '../../../../../constants';\n\nexport const CATEGORIES = {\n  contact: _x('Contact', 'text set category', 'web-stories'),\n  editorial: _x('Editorial', 'text set category', 'web-stories'),\n  list: _x('List', 'text set category', 'web-stories'),\n  cover: _x('Cover', 'text set category', 'web-stories'),\n  section_header: _x('Header', 'text set category', 'web-stories'),\n  step: _x('Steps', 'text set category', 'web-stories'),\n  table: _x('Table', 'text set category', 'web-stories'),\n  quote: _x('Quote', 'text set category', 'web-stories'),\n};\n\nexport const PANE_TEXT = {\n  TITLE: __('Text Sets', 'web-stories'),\n  SWITCH_LABEL: __('Match fonts from story', 'web-stories'),\n};\n\nexport const TEXT_SET_PAGE_SIZE = {\n  width: TEXT_SET_SIZE,\n  height: TEXT_SET_SIZE / PAGE_RATIO,\n};\n\nexport { TEXT_SET_SIZE };\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './textSets';\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/stories/textSet.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { UnitsProvider, getBox, PAGE_RATIO } from '@googleforcreators/units';\nimport { TransformContext } from '@googleforcreators/transform';\n\n/**\n * Internal dependencies\n */\nimport TextSet from '../textSet';\nimport { TEXT_SET_SIZE } from '../../../../../../constants';\nimport LibraryContext from '../../../../context';\nimport FontContext from '../../../../../../app/font/context';\nimport APIContext from '../../../../../../app/api/context';\nimport ConfigContext from '../../../../../../app/config/context';\nimport StoryContext from '../../../../../../app/story/context';\nimport { LayoutProvider } from '../../../../../../app/layout';\nimport CanvasContext from '../../../../../../app/canvas/context';\n\nexport default {\n  title: 'Stories Editor/Components/Library/Panes/Text/TextSet',\n  component: TextSet,\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render() {\n    const textSet1 = [\n      {\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        backgroundTextMode: 'NONE',\n        font: {\n          family: 'Alegreya',\n          service: 'fonts.google.com',\n          fallbacks: ['serif'],\n          weights: [400, 500, 700, 800, 900],\n          styles: ['regular', 'italic'],\n          variants: [\n            [0, 400],\n            [1, 400],\n            [0, 500],\n            [1, 500],\n            [0, 700],\n            [1, 700],\n            [0, 800],\n            [1, 800],\n            [0, 900],\n            [1, 900],\n          ],\n          metrics: {\n            upm: 1000,\n            asc: 1016,\n            des: -345,\n            tAsc: 1016,\n            tDes: -345,\n            tLGap: 0,\n            wAsc: 1123,\n            wDes: 345,\n            xH: 452,\n            capH: 636,\n            yMin: -293,\n            yMax: 962,\n            hAsc: 1016,\n            hDes: -345,\n            lGap: 0,\n          },\n        },\n        fontSize: 36,\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n        lineHeight: 1.1,\n        textAlign: 'center',\n        padding: {\n          locked: true,\n          horizontal: 0,\n          vertical: 0,\n        },\n        type: 'text',\n        content:\n          '<span style=\"font-weight: 400\">Good design is aesthetic</span>',\n        x: 0,\n        y: 15,\n        width: 328,\n        height: 78,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        id: '755f1d9e-aeb4-4c4d-ba7f-fac834434243',\n        previewOffsetX: 0,\n        previewOffsetY: 0,\n        textSetWidth: 333,\n        textSetHeight: 304,\n        normalizedOffsetX: 0,\n        normalizedOffsetY: 0,\n      },\n      {\n        opacity: 100,\n        flip: {\n          vertical: false,\n          horizontal: false,\n        },\n        rotationAngle: 0,\n        lockAspectRatio: true,\n        backgroundTextMode: 'NONE',\n        font: {\n          family: 'Roboto',\n          weights: [100, 300, 400, 500, 700, 900],\n          styles: ['italic', 'regular'],\n          variants: [\n            [0, 100],\n            [1, 100],\n            [0, 300],\n            [1, 300],\n            [0, 400],\n            [1, 400],\n            [0, 500],\n            [1, 500],\n            [0, 700],\n            [1, 700],\n            [0, 900],\n            [1, 900],\n          ],\n          fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n          service: 'fonts.google.com',\n          metrics: {\n            upm: 2048,\n            asc: 1900,\n            des: -500,\n            tAsc: 1536,\n            tDes: -512,\n            tLGap: 102,\n            wAsc: 1946,\n            wDes: 512,\n            xH: 1082,\n            capH: 1456,\n            yMin: -555,\n            yMax: 2163,\n            hAsc: 1900,\n            hDes: -500,\n            lGap: 0,\n          },\n        },\n        fontSize: 18,\n        backgroundColor: {\n          color: {\n            r: 196,\n            g: 196,\n            b: 196,\n          },\n        },\n        lineHeight: 1.5,\n        textAlign: 'justify',\n        padding: {\n          locked: true,\n          horizontal: 0,\n          vertical: 0,\n        },\n        type: 'text',\n        content:\n          'The possibilities for innovation are not, by any means, exhausted. Technological development is always offering new opportunities for innovative design. But innovative design always develops in tandem with innovative technology, and can never be an end in itself.',\n        x: 0,\n        y: 110,\n        width: 333,\n        height: 181,\n        scale: 100,\n        focalX: 50,\n        focalY: 50,\n        id: '755f1d9e-aeb4-4c4d-ba7f-fac834434243',\n        previewOffsetX: 30,\n        previewOffsetY: 30,\n        textSetWidth: 333,\n        textSetHeight: 304,\n        normalizedOffsetX: 0,\n        normalizedOffsetY: 0,\n      },\n    ];\n\n    const libraryValue = {\n      actions: {\n        insertTextSet: () => {},\n      },\n    };\n    const transformValue = {\n      actions: {\n        registerTransformHandler: () => {},\n      },\n    };\n    const configValue = {\n      cdnURL: 'https://wp.stories.google/static/main/',\n    };\n    const fontsValue = {\n      actions: {\n        maybeEnqueueFontStyle: () => {},\n        loadCustomFonts: () => {},\n        loadCuratedFonts: () => {},\n      },\n    };\n    const apiValue = {\n      actions: {\n        getAllFonts: () => [],\n      },\n    };\n\n    const storyValue = {\n      actions: {\n        setSelectedElementsById: () => {},\n      },\n      state: {\n        currentPage: {},\n      },\n    };\n\n    const canvasValue = {\n      state: {\n        nodesById: {},\n        pageSize: {},\n        pageContainer: document.body,\n        canvasContainer: document.body,\n        designSpaceGuideline: {},\n      },\n      actions: {},\n    };\n\n    return (\n      <TransformContext.Provider value={transformValue}>\n        <ConfigContext.Provider value={configValue}>\n          <APIContext.Provider value={apiValue}>\n            <StoryContext.Provider value={storyValue}>\n              <CanvasContext.Provider value={canvasValue}>\n                <FontContext.Provider value={fontsValue}>\n                  <LayoutProvider>\n                    <LibraryContext.Provider value={libraryValue}>\n                      <UnitsProvider\n                        pageSize={{\n                          width: TEXT_SET_SIZE,\n                          height: TEXT_SET_SIZE / PAGE_RATIO,\n                        }}\n                        getBox={getBox}\n                      >\n                        <TextSet\n                          id={'755f1d9e-aeb4-4c4d-ba7f-fac834434243'}\n                          elements={textSet1}\n                          index={0}\n                        />\n                      </UnitsProvider>\n                    </LibraryContext.Provider>\n                  </LayoutProvider>\n                </FontContext.Provider>\n              </CanvasContext.Provider>\n            </StoryContext.Provider>\n          </APIContext.Provider>\n        </ConfigContext.Provider>\n      </TransformContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/test/textSet.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { UnitsProvider, getBox, PAGE_RATIO } from '@googleforcreators/units';\nimport { TransformContext } from '@googleforcreators/transform';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport LibraryContext from '../../../../context';\nimport FontContext from '../../../../../../app/font/context';\nimport APIContext from '../../../../../../app/api/context';\nimport TextSet from '../textSet';\nimport { TEXT_SET_SIZE } from '../../../../../../constants';\nimport StoryContext from '../../../../../../app/story/context';\nimport { LayoutProvider } from '../../../../../../app/layout';\nimport CanvasContext from '../../../../../../app/canvas/context';\n\nconst SET = [\n  {\n    opacity: 100,\n    flip: {\n      vertical: false,\n      horizontal: false,\n    },\n    rotationAngle: 0,\n    lockAspectRatio: true,\n    backgroundTextMode: 'NONE',\n    font: {\n      family: 'Alegreya',\n      service: 'fonts.google.com',\n      fallbacks: ['serif'],\n      weights: [400, 500, 700, 800, 900],\n      styles: ['regular', 'italic'],\n      variants: [\n        [0, 400],\n        [1, 400],\n        [0, 500],\n        [1, 500],\n        [0, 700],\n        [1, 700],\n        [0, 800],\n        [1, 800],\n        [0, 900],\n        [1, 900],\n      ],\n    },\n    fontSize: 36,\n    backgroundColor: {\n      color: {\n        r: 196,\n        g: 196,\n        b: 196,\n      },\n    },\n    lineHeight: 1.1,\n    textAlign: 'center',\n    padding: {\n      locked: true,\n      horizontal: 0,\n      vertical: 0,\n    },\n    type: 'text',\n    content: '<span style=\"font-weight: 400\">Good design is aesthetic</span>',\n    x: 40,\n    y: 291,\n    width: 328,\n    height: 78,\n    scale: 100,\n    focalX: 50,\n    focalY: 50,\n    id: '1',\n    previewOffsetX: 0,\n    previewOffsetY: 0,\n    textSetWidth: 333,\n    textSetHeight: 304,\n    normalizedOffsetX: 0,\n    normalizedOffsetY: 0,\n  },\n  {\n    opacity: 100,\n    flip: {\n      vertical: false,\n      horizontal: false,\n    },\n    rotationAngle: 0,\n    lockAspectRatio: true,\n    backgroundTextMode: 'NONE',\n    font: {\n      family: 'Roboto',\n      weights: [100, 300, 400, 500, 700, 900],\n      styles: ['italic', 'regular'],\n      variants: [\n        [0, 100],\n        [1, 100],\n        [0, 300],\n        [1, 300],\n        [0, 400],\n        [1, 400],\n        [0, 500],\n        [1, 500],\n        [0, 700],\n        [1, 700],\n        [0, 900],\n        [1, 900],\n      ],\n      fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n      service: 'fonts.google.com',\n      metrics: {\n        upm: 2048,\n        asc: 1900,\n        des: -500,\n        tAsc: 1536,\n        tDes: -512,\n        tLGap: 102,\n        wAsc: 1946,\n        wDes: 512,\n        xH: 1082,\n        capH: 1456,\n        yMin: -555,\n        yMax: 2163,\n        hAsc: 1900,\n        hDes: -500,\n        lGap: 0,\n      },\n    },\n    fontSize: 18,\n    backgroundColor: {\n      color: {\n        r: 196,\n        g: 196,\n        b: 196,\n      },\n    },\n    lineHeight: 1.5,\n    textAlign: 'justify',\n    padding: {\n      locked: true,\n      horizontal: 0,\n      vertical: 0,\n    },\n    type: 'text',\n    content:\n      'The possibilities for innovation are not, by any means, exhausted. Technological development is always offering new opportunities for innovative design. But innovative design always develops in tandem with innovative technology, and can never be an end in itself.',\n    x: 40,\n    y: 411,\n    width: 333,\n    height: 181,\n    scale: 100,\n    focalX: 50,\n    focalY: 50,\n    id: '2',\n    previewOffsetX: 30,\n    previewOffsetY: 30,\n    textSetWidth: 333,\n    textSetHeight: 304,\n    normalizedOffsetX: 0,\n    normalizedOffsetY: 0,\n  },\n];\n\nconst insertTextSet = jest.fn();\n\nfunction setup(elements, id) {\n  const libraryValue = {\n    actions: {\n      insertTextSet,\n    },\n  };\n  const transformValue = {\n    actions: {\n      registerTransformHandler: () => {},\n    },\n  };\n  const fontsValue = {\n    actions: {\n      maybeEnqueueFontStyle: () => {},\n      loadCustomFonts: jest.fn(),\n      loadCuratedFonts: jest.fn(),\n    },\n  };\n  const apiValue = {\n    actions: {\n      getAllFonts: () => [],\n    },\n  };\n\n  const storyValue = {\n    actions: {\n      setSelectedElementsById: jest.fn(),\n    },\n    state: {\n      currentPage: {},\n    },\n  };\n\n  const canvasValue = {\n    state: {\n      nodesById: {},\n      pageSize: {},\n      pageContainer: document.body,\n      canvasContainer: document.body,\n      designSpaceGuideline: {},\n    },\n    actions: {},\n  };\n\n  return renderWithTheme(\n    <TransformContext.Provider value={transformValue}>\n      <APIContext.Provider value={apiValue}>\n        <StoryContext.Provider value={storyValue}>\n          <CanvasContext.Provider value={canvasValue}>\n            <FontContext.Provider value={fontsValue}>\n              <LayoutProvider>\n                <LibraryContext.Provider value={libraryValue}>\n                  <UnitsProvider\n                    pageSize={{\n                      width: TEXT_SET_SIZE,\n                      height: TEXT_SET_SIZE / PAGE_RATIO,\n                    }}\n                    getBox={getBox}\n                  >\n                    <TextSet\n                      ref={{ current: null }}\n                      id={id}\n                      elements={elements}\n                      index={0}\n                    />\n                  </UnitsProvider>\n                </LibraryContext.Provider>\n              </LayoutProvider>\n            </FontContext.Provider>\n          </CanvasContext.Provider>\n        </StoryContext.Provider>\n      </APIContext.Provider>\n    </TransformContext.Provider>\n  );\n}\n\n/* eslint-disable testing-library/no-container */\n\ndescribe('TextSets', () => {\n  beforeEach(() => {\n    insertTextSet.mockReset();\n  });\n\n  const SET_ID = '123';\n\n  it('should render the correct images for the text sets x', () => {\n    const { container } = setup(SET, SET_ID);\n    const textSetImg = container.querySelector(`img[src$=\"${SET_ID}.png\"]`);\n    expect(textSetImg).toBeTruthy();\n  });\n});\n\n/* eslint-enable testing-library/no-container */\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/test/textSetsPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef } from '@googleforcreators/react';\nimport { screen } from '@testing-library/react';\nimport { TransformContext } from '@googleforcreators/transform';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport LibraryContext from '../../../../context';\nimport FontContext from '../../../../../../app/font/context';\nimport APIContext from '../../../../../../app/api/context';\nimport StoryContext from '../../../../../../app/story/context';\nimport TextSetsPane from '../textSetsPane';\n\nfunction setup() {\n  const libraryValue = {\n    state: {\n      textSets: [],\n    },\n    actions: {\n      insertElement: jest.fn(),\n    },\n  };\n  const transformValue = {\n    actions: {\n      registerTransformHandler: jest.fn(),\n    },\n  };\n  const fontsValue = {\n    actions: {\n      maybeEnqueueFontStyle: jest.fn(),\n      loadCustomFonts: jest.fn(),\n      loadCuratedFonts: jest.fn(),\n    },\n  };\n  const apiValue = {\n    actions: {\n      getAllFonts: jest.fn(),\n    },\n  };\n\n  const storyValue = {\n    state: {\n      pages: [],\n    },\n    actions: {\n      setSelectedElementsById: jest.fn(),\n    },\n  };\n\n  return renderWithTheme(\n    <TransformContext.Provider value={transformValue}>\n      <APIContext.Provider value={apiValue}>\n        <StoryContext.Provider value={storyValue}>\n          <FontContext.Provider value={fontsValue}>\n            <LibraryContext.Provider value={libraryValue}>\n              <MockPane>\n                {(paneRef) => <TextSetsPane paneRef={paneRef} />}\n              </MockPane>\n            </LibraryContext.Provider>\n          </FontContext.Provider>\n        </StoryContext.Provider>\n      </APIContext.Provider>\n    </TransformContext.Provider>\n  );\n}\n\nfunction MockPane({ children }) {\n  const ref = useRef();\n  return <div ref={ref}>{children(ref)}</div>;\n}\n\ndescribe('TextSets Panel', () => {\n  it('should render the Panel', () => {\n    setup();\n    const h1 = screen.getByText('Text Sets');\n    expect(h1).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/textSet.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useCallback, forwardRef, useState } from '@googleforcreators/react';\nimport { dataToEditorX, dataToEditorY } from '@googleforcreators/units';\nimport {\n  BUTTON_TRANSITION_TIMING,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useLayout } from '../../../../../app/layout';\nimport { TEXT_SET_SIZE } from '../../../../../constants';\nimport useLibrary from '../../../useLibrary';\nimport LibraryMoveable from '../../shared/libraryMoveable';\nimport { useConfig } from '../../../../../app';\nimport InsertionOverlay from '../../shared/insertionOverlay';\nimport useRovingTabIndex from '../../../../../utils/useRovingTabIndex';\nimport TextSetElements from './textSetElements';\n\nconst TextSetItem = styled.button`\n  border: 0;\n  background: none;\n  position: absolute;\n  top: 0;\n  height: ${TEXT_SET_SIZE}px;\n  width: ${TEXT_SET_SIZE}px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  flex-direction: column;\n  transform: ${({ translateX, translateY }) =>\n    `translateX(${translateX}px) translateY(${translateY}px)`};\n\n  background-color: ${({ theme }) =>\n    theme.colors.interactiveBg.secondaryNormal};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  cursor: pointer;\n  transition: background-color ${BUTTON_TRANSITION_TIMING};\n  outline: none;\n\n  &:focus-visible [role='presentation'] {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n\nconst TextSetImg = styled.img`\n  width: ${TEXT_SET_SIZE}px;\n  height: ${TEXT_SET_SIZE}px;\n`;\n\nconst DragContainer = styled.div`\n  position: absolute;\n  opacity: 0;\n  width: ${({ width }) => width}px;\n  height: ${({ height }) => height}px;\n  background-color: ${({ theme }) => theme.colors.opacity.white24};\n`;\n\nfunction TextSet(\n  { id, elements, translateY, translateX, isActive, index, ...rest },\n  ref\n) {\n  const { insertTextSet } = useLibrary((state) => ({\n    insertTextSet: state.actions.insertTextSet,\n  }));\n\n  const { cdnURL } = useConfig();\n\n  const { pageWidth, pageHeight } = useLayout(\n    ({ state: { pageWidth, pageHeight } }) => ({\n      pageWidth,\n      pageHeight,\n    })\n  );\n\n  const onClick = useCallback(() => {\n    insertTextSet(elements);\n    trackEvent('insert_textset');\n  }, [elements, insertTextSet]);\n\n  const handleKeyboardPageClick = useCallback(\n    ({ code }) => {\n      if (code === 'Enter' || code === 'Space') {\n        onClick();\n      }\n    },\n    [onClick]\n  );\n\n  const renderImages =\n    typeof WEB_STORIES_DISABLE_OPTIMIZED_RENDERING === 'undefined' ||\n    WEB_STORIES_DISABLE_OPTIMIZED_RENDERING !== 'true';\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  useRovingTabIndex({ ref: ref.current });\n  const [isHovering, setIsHovering] = useState(false);\n  const setHovering = () => setIsHovering(true);\n  const unsetHovering = () => setIsHovering(false);\n\n  const { textSetHeight, textSetWidth } = elements[0];\n  const dragWidth = dataToEditorX(textSetWidth, pageWidth);\n  const dragHeight = dataToEditorY(textSetHeight, pageHeight);\n  return (\n    <TextSetItem\n      translateX={translateX}\n      translateY={translateY}\n      ref={ref}\n      onKeyUp={handleKeyboardPageClick}\n      onPointerEnter={setHovering}\n      onPointerLeave={unsetHovering}\n      tabIndex={index === 0 ? 0 : -1}\n      {...rest}\n    >\n      {renderImages ? (\n        <TextSetImg\n          src={`${cdnURL}images/text-sets/${id}.png`}\n          alt=\"\"\n          crossOrigin=\"anonymous\"\n          decoding=\"async\"\n        />\n      ) : (\n        <TextSetElements isForDisplay elements={elements} />\n      )}\n      {(isActive || isHovering) && <InsertionOverlay />}\n      <LibraryMoveable\n        type={'textSet'}\n        elements={elements}\n        elementProps={{}}\n        onClick={onClick}\n        cloneElement={DragContainer}\n        cloneProps={{\n          width: dragWidth,\n          height: dragHeight,\n          children: (\n            <TextSetElements\n              elements={elements}\n              pageSize={{\n                width: pageWidth,\n                height: pageHeight,\n              }}\n            />\n          ),\n        }}\n      />\n    </TextSetItem>\n  );\n}\n\nconst TextSetWithRef = forwardRef(TextSet);\n\nTextSet.propTypes = {\n  id: PropTypes.string.isRequired,\n  elements: PropTypes.array.isRequired,\n  translateY: PropTypes.number.isRequired,\n  translateX: PropTypes.number.isRequired,\n  isActive: PropTypes.bool,\n  index: PropTypes.number,\n};\n\nTextSet.displayName = 'TextSet';\n\nexport default TextSetWithRef;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/textSetElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { UnitsProvider, PAGE_WIDTH } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\n\nimport { StoryPropTypes } from '../../../../../propTypes';\nimport DisplayElement from '../../../../canvas/displayElement';\n\nfunction getElementContent(content, isForDisplay) {\n  if (!content) {\n    return {};\n  }\n\n  return {\n    content: isForDisplay\n      ? `<span style=\"color: #fff\">${content}<span>`\n      : content,\n  };\n}\n\nfunction TextSetContainer({ pageSize, children }) {\n  return pageSize ? (\n    <UnitsProvider pageSize={pageSize}>{children}</UnitsProvider>\n  ) : (\n    children\n  );\n}\n\nTextSetContainer.propTypes = {\n  pageSize: StoryPropTypes.size,\n  children: PropTypes.node.isRequired,\n};\n\nfunction TextSetElements({ elements, isForDisplay, pageSize }) {\n  const { textSetHeight, textSetWidth } = elements[0];\n\n  const xOffset = isForDisplay ? (PAGE_WIDTH - textSetWidth) / 2 : 0;\n  const yOffset = isForDisplay ? (PAGE_WIDTH - textSetHeight) / 2 : 0;\n\n  return (\n    <TextSetContainer pageSize={pageSize}>\n      {elements.map(\n        ({ id, content, normalizedOffsetX, normalizedOffsetY, ...rest }) => (\n          <DisplayElement\n            previewMode\n            key={id}\n            element={{\n              id,\n              ...getElementContent(content, isForDisplay),\n              ...rest,\n              x: normalizedOffsetX + xOffset,\n              y: normalizedOffsetY + yOffset,\n            }}\n          />\n        )\n      )}\n    </TextSetContainer>\n  );\n}\n\nTextSetElements.propTypes = {\n  elements: PropTypes.array.isRequired,\n  pageSize: StoryPropTypes.size,\n  isForDisplay: PropTypes.bool,\n};\n\nexport default TextSetElements;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/textSets.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useCallback, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { useVirtual } from 'react-virtual';\nimport { __ } from '@googleforcreators/i18n';\nimport { UnitsProvider } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport {\n  getVirtualizedItemIndex,\n  useVirtualizedGridNavigation,\n  VirtualizedContainer,\n  PANEL_GRID_ROW_GAP,\n  VirtualizedWrapper,\n} from '../../shared/virtualizedPanelGrid';\nimport TextSet from './textSet';\nimport { TEXT_SET_PAGE_SIZE, TEXT_SET_SIZE } from './constants';\n\nfunction TextSets({ paneRef, filteredTextSets }) {\n  const containerRef = useRef();\n  const textSetsRef = useRef({});\n\n  const textSetIds = useMemo(\n    () => filteredTextSets.map((textSet) => textSet.id),\n    [filteredTextSets]\n  );\n\n  const rowVirtualizer = useVirtual({\n    size: Math.ceil((filteredTextSets || []).length / 2),\n    parentRef: paneRef,\n    estimateSize: useCallback(() => TEXT_SET_SIZE + PANEL_GRID_ROW_GAP, []),\n    overscan: 4,\n  });\n\n  const columnVirtualizer = useVirtual({\n    horizontal: true,\n    size: 2,\n    parentRef: paneRef,\n    estimateSize: useCallback(() => TEXT_SET_SIZE + PANEL_GRID_ROW_GAP, []),\n    overscan: 0,\n  });\n\n  const {\n    activeGridItemId,\n    handleGridFocus,\n    handleGridItemFocus,\n    isGridFocused,\n  } = useVirtualizedGridNavigation({\n    rowVirtualizer,\n    containerRef,\n    gridItemRefs: textSetsRef,\n    gridItemIds: textSetIds,\n  });\n\n  return (\n    <UnitsProvider pageSize={TEXT_SET_PAGE_SIZE}>\n      <VirtualizedWrapper height={rowVirtualizer.totalSize}>\n        <VirtualizedContainer\n          height={rowVirtualizer.totalSize}\n          ref={containerRef}\n          columnWidth={TEXT_SET_SIZE}\n          rowHeight={TEXT_SET_SIZE}\n          onFocus={handleGridFocus}\n          role=\"group\"\n          aria-label={__('Text Set Options', 'web-stories')}\n        >\n          {rowVirtualizer.virtualItems.map((virtualRow) =>\n            columnVirtualizer.virtualItems.map((virtualColumn) => {\n              const gridIndex = getVirtualizedItemIndex({\n                columnIndex: virtualColumn.index,\n                rowIndex: virtualRow.index,\n              });\n\n              const textSet = filteredTextSets[gridIndex];\n\n              if (!textSet?.elements) {\n                return null;\n              }\n\n              const isActive = activeGridItemId === textSet.id && isGridFocused;\n\n              return (\n                <TextSet\n                  key={gridIndex}\n                  id={textSet.id}\n                  data-testid={`text_set_${textSet.id}`}\n                  ref={(el) => (textSetsRef.current[textSet.id] = el)}\n                  translateY={virtualRow.start}\n                  translateX={virtualColumn.start}\n                  aria-label={textSet.title}\n                  isActive={isActive}\n                  onFocus={() => handleGridItemFocus(textSet.id)}\n                  elements={textSet.elements}\n                  index={gridIndex}\n                />\n              );\n            })\n          )}\n        </VirtualizedContainer>\n      </VirtualizedWrapper>\n    </UnitsProvider>\n  );\n}\n\nTextSets.propTypes = {\n  paneRef: PropTypes.object,\n  filteredTextSets: PropTypes.arrayOf(\n    PropTypes.shape({\n      id: PropTypes.string,\n      elements: PropTypes.array,\n      title: PropTypes.string,\n    })\n  ),\n};\n\nexport default TextSets;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/textSets/textSetsPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useMemo,\n  useCallback,\n  useEffect,\n  useRef,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  _n,\n  sprintf,\n  __,\n  _x,\n  translateToInclusiveList,\n} from '@googleforcreators/i18n';\nimport {\n  TextSize,\n  LOCAL_STORAGE_PREFIX,\n  Text,\n  Toggle,\n  Headline,\n  useLiveRegion,\n  localStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { FullWidthWrapper } from '../../common/styles';\nimport { ChipGroup } from '../../shared';\nimport useLibrary from '../../../useLibrary';\nimport useStory from '../../../../../app/story/useStory';\nimport {\n  getInUseFontsForPages,\n  getTextSetsForFonts,\n} from '../../../../../utils/getInUseFonts';\nimport { Container as SectionContainer } from '../../../common/section';\nimport { virtualPaneContainer } from '../../shared/virtualizedPanelGrid';\nimport EmptyContentMessage from '../../../../emptyContentMessage';\nimport TextSets from './textSets';\nimport { CATEGORIES, PANE_TEXT } from './constants';\n\nconst TitleBar = styled.div`\n  display: flex;\n  justify-content: space-between;\n  padding: 20px 0;\n`;\n\nconst TextSetsToggle = styled.div`\n  display: flex;\n\n  label {\n    cursor: pointer;\n    margin: auto 12px;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\n\nconst TextSetsWrapper = styled.div`\n  ${virtualPaneContainer};\n`;\n\nfunction TextSetsPane({ paneRef }) {\n  const { areTextSetsLoading, textSets } = useLibrary(\n    ({ state: { areTextSetsLoading, textSets } }) => ({\n      areTextSetsLoading,\n      textSets,\n    })\n  );\n  const [showInUse, setShowInUse] = useState(false);\n  const trackChangeRef = useRef(false);\n\n  const allTextSets = useMemo(() => Object.values(textSets).flat(), [textSets]);\n  const storyPages = useStory(({ state: { pages } }) => pages);\n\n  const [selectedCat, setSelectedCat] = useState(\n    localStore.getItemByKey(LOCAL_STORAGE_PREFIX.TEXT_SET_SETTINGS)\n      ?.selectedCategory\n  );\n\n  const getTextSetsForInUseFonts = useCallback(\n    () =>\n      getTextSetsForFonts({\n        fonts: getInUseFontsForPages(storyPages),\n        textSets: selectedCat ? textSets[selectedCat] : allTextSets,\n      }),\n    [allTextSets, storyPages, selectedCat, textSets]\n  );\n\n  const addIdToTextSets = useCallback(\n    (textSetsArray = []) =>\n      textSetsArray.map(\n        ({ textSetFonts = [], textSetCategory, elements, id }) => {\n          return {\n            id,\n            title: sprintf(\n              /* translators: 1: text set category. 2: list of fonts. */\n              _n(\n                'Text set %1$s with %2$s font',\n                'Text set %1$s with %2$s fonts',\n                textSetFonts.length,\n                'web-stories'\n              ),\n              CATEGORIES[textSetCategory],\n              translateToInclusiveList(textSetFonts)\n            ),\n            elements,\n          };\n        }\n      ),\n    []\n  );\n  const filteredTextSets = useMemo(() => {\n    if (showInUse) {\n      return addIdToTextSets(getTextSetsForInUseFonts());\n    }\n    return addIdToTextSets(selectedCat ? textSets?.[selectedCat] : allTextSets);\n  }, [\n    selectedCat,\n    textSets,\n    allTextSets,\n    addIdToTextSets,\n    getTextSetsForInUseFonts,\n    showInUse,\n  ]);\n\n  const categories = useMemo(\n    () => [\n      { id: null, label: _x('All', 'text sets', 'web-stories') },\n      ...Object.keys(textSets).map((category) => ({\n        id: category,\n        label: CATEGORIES[category] ?? category,\n      })),\n    ],\n    [textSets]\n  );\n\n  const speak = useLiveRegion();\n\n  const handleSelectedCategory = useCallback(\n    (selectedCategory) => {\n      setSelectedCat(selectedCategory);\n      speak(\n        selectedCategory === null\n          ? __('Show all text sets', 'web-stories')\n          : sprintf(\n              /* translators: %s: filter category name */\n              __('Selected text set filter %s', 'web-stories'),\n              CATEGORIES[selectedCategory]\n            )\n      );\n      localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TEXT_SET_SETTINGS, {\n        selectedCategory,\n      });\n      trackChangeRef.current = true;\n    },\n    [speak]\n  );\n\n  const onChangeShowInUse = useCallback(() => {\n    requestAnimationFrame(() => setShowInUse((prevVal) => !prevVal));\n    trackChangeRef.current = true;\n  }, [setShowInUse]);\n\n  useEffect(() => {\n    if (trackChangeRef.current) {\n      trackEvent('search', {\n        search_type: 'textsets',\n        search_term: '',\n        search_category: selectedCat,\n        search_filter: showInUse ? 'show_in_use' : undefined,\n      });\n    }\n  }, [selectedCat, showInUse]);\n\n  const sectionId = useMemo(() => `section-${uuidv4()}`, []);\n  const toggleId = useMemo(() => `toggle_text_sets_${uuidv4()}`, []);\n\n  const emptyContentMessage = useMemo(\n    () =>\n      showInUse\n        ? __(\n            'No matching Text Sets available. Try adding text to your story.',\n            'web-stories'\n          )\n        : __('No Text Sets available.', 'web-stories'),\n    [showInUse]\n  );\n\n  return (\n    <SectionContainer id={sectionId}>\n      <TitleBar>\n        <Headline as=\"h2\" size={TextSize.XXXSmall}>\n          {PANE_TEXT.TITLE}\n        </Headline>\n        <TextSetsToggle>\n          <Text.Label htmlFor={toggleId} size={TextSize.Small}>\n            {PANE_TEXT.SWITCH_LABEL}\n          </Text.Label>\n          <Toggle\n            id={toggleId}\n            aria-label={PANE_TEXT.SWITCH_LABEL}\n            name={toggleId}\n            checked={showInUse}\n            onChange={onChangeShowInUse}\n          />\n        </TextSetsToggle>\n      </TitleBar>\n      <FullWidthWrapper>\n        <ChipGroup\n          items={categories}\n          selectedItemId={selectedCat}\n          selectItem={handleSelectedCategory}\n          deselectItem={() => handleSelectedCategory(null)}\n          ariaLabel={__('Select filter for text sets list', 'web-stories')}\n        />\n      </FullWidthWrapper>\n      <TextSetsWrapper>\n        {!filteredTextSets?.length && !areTextSetsLoading ? (\n          <EmptyContentMessage>{emptyContentMessage}</EmptyContentMessage>\n        ) : (\n          <TextSets paneRef={paneRef} filteredTextSets={filteredTextSets} />\n        )}\n      </TextSetsWrapper>\n    </SectionContainer>\n  );\n}\n\nTextSetsPane.propTypes = {\n  paneRef: PropTypes.object,\n};\n\nexport default TextSetsPane;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/panes/text/useInsertPreset.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { dataFontEm, PAGE_HEIGHT } from '@googleforcreators/units';\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\nimport { calculateTextHeight } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport getInsertedElementSize from '../../../../utils/getInsertedElementSize';\nimport useLibrary from '../../useLibrary';\nimport { useHistory } from '../../../../app';\nimport { useCalculateAccessibleTextColors } from '../../../../app/pageCanvas';\nimport { applyHiddenPadding } from '../../../panels/design/textStyle/utils';\n\nconst POSITION_MARGIN = dataFontEm(1);\nconst TYPE = 'text';\n\nfunction useInsertPreset({ shouldUseSmartColor }) {\n  const { insertElement } = useLibrary((state) => ({\n    insertElement: state.actions.insertElement,\n  }));\n  const {\n    state: { versionNumber },\n  } = useHistory();\n\n  const htmlFormatters = getHTMLFormatters();\n  const { setColor } = htmlFormatters;\n\n  const [autoColor, setAutoColor] = useState(null);\n  const [presetAtts, setPresetAtts] = useState(null);\n\n  const lastPresetRef = useRef(null);\n  const calculateAccessibleTextColors = useCalculateAccessibleTextColors();\n\n  useEffect(() => {\n    // Version number change is happening due to adding a preset.\n    // If we have set the last element but not the history version number yet,\n    // Set the version number that was the result of adding the preset.\n    if (\n      lastPresetRef.current?.element &&\n      !lastPresetRef.current.versionNumber\n    ) {\n      lastPresetRef.current.versionNumber = versionNumber;\n    } else if (lastPresetRef.current?.versionNumber) {\n      // If the version number changes meanwhile and we already have it set\n      // something else changed meanwhile so clear the lastPreset, too.\n      lastPresetRef.current = null;\n    }\n  }, [versionNumber]);\n\n  const getPosition = useCallback((element) => {\n    const { y } = element;\n    if (!lastPresetRef.current) {\n      return y;\n    }\n    const {\n      element: { height: lastHeight, y: lastY },\n    } = lastPresetRef.current;\n    let positionedY = lastY + lastHeight + POSITION_MARGIN;\n    // Let's get the width/height of the element about to be inserted.\n    const { width, height } = getInsertedElementSize(\n      TYPE,\n      element.width,\n      element.height,\n      {\n        ...element,\n        y: positionedY,\n      }\n    );\n    // If the element is going out of page, use the default position.\n    if (positionedY + height >= PAGE_HEIGHT) {\n      positionedY = y;\n    }\n    return {\n      width,\n      height,\n      y: positionedY,\n    };\n  }, []);\n\n  // Once the colors have been detected, we'll insert the element.\n  useEffect(() => {\n    if (autoColor && presetAtts) {\n      // Add all the necessary props in case of color / highlight.\n      const { content } = presetAtts;\n      const { color, backgroundColor } = autoColor;\n      const highlightProps = backgroundColor\n        ? {\n            backgroundColor: { color: backgroundColor },\n            backgroundTextMode: BACKGROUND_TEXT_MODE.HIGHLIGHT,\n            padding: applyHiddenPadding(presetAtts),\n          }\n        : null;\n      const elementProps = {\n        ...presetAtts,\n        content: color ? setColor(content, { color }) : content,\n        ...highlightProps,\n      };\n      const addedElement = insertElement(TYPE, {\n        ...elementProps,\n        height: calculateTextHeight(elementProps, elementProps.width),\n      });\n      lastPresetRef.current = {\n        versionNumber: null,\n        element: addedElement,\n      };\n      setAutoColor(null);\n      setPresetAtts(null);\n    }\n  }, [autoColor, presetAtts, insertElement, setColor]);\n\n  const insertPreset = useCallback(\n    async (element, presetProps = {}) => {\n      const { isPositioned, accessibleColors } = presetProps;\n      // If it's already positioned, skip calculating that.\n      const atts = isPositioned ? {} : getPosition(element);\n      if (shouldUseSmartColor) {\n        setPresetAtts({\n          ...element,\n          ...atts,\n        });\n        // If we already have the color, skip calculation.\n        if (accessibleColors) {\n          setAutoColor(accessibleColors);\n          return;\n        }\n        setAutoColor(\n          await calculateAccessibleTextColors({ ...element, ...atts })\n        );\n      } else {\n        const addedElement = insertElement(TYPE, {\n          ...element,\n          ...atts,\n        });\n        lastPresetRef.current = {\n          versionNumber: null,\n          element: addedElement,\n        };\n      }\n    },\n    [\n      getPosition,\n      calculateAccessibleTextColors,\n      shouldUseSmartColor,\n      insertElement,\n    ]\n  );\n  return {\n    getPosition,\n    insertPreset,\n  };\n}\n\nexport default useInsertPreset;\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/_utils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport Library from '../..';\nimport { MediaProvider } from '../../../../app/media';\nimport { ConfigProvider } from '../../../../app/config';\nimport { FontProvider } from '../../../../app/font';\nimport APIContext from '../../../../app/api/context';\n\nexport async function arrange({ mediaResponse = [] }) {\n  const config = {\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n  };\n  const getMediaPromise = Promise.resolve({\n    data: mediaResponse,\n    headers: { totalPages: 1 },\n  });\n  const getAllFontsPromise = Promise.resolve([]);\n  const allPromises = [getMediaPromise, getAllFontsPromise];\n  const apiContextValue = {\n    actions: {\n      getMedia: () => getMediaPromise,\n      getAllFonts: () => getAllFontsPromise,\n    },\n  };\n\n  const view = renderWithTheme(\n    <ConfigProvider config={config}>\n      <APIContext.Provider value={apiContextValue}>\n        <FontProvider>\n          <MediaProvider>\n            <Library />\n          </MediaProvider>\n        </FontProvider>\n      </APIContext.Provider>\n    </ConfigProvider>\n  );\n\n  // Another option without allPromises:\n  // const flushPromises = () => new Promise(window.setImmediate);\n  // await act(flushPromises);\n\n  await act(() => Promise.all(allPromises));\n\n  return view;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/deleteDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, fireEvent, screen } from '@testing-library/react';\nimport {\n  setAppElement,\n  SnackbarContext,\n} from '@googleforcreators/design-system';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport DeleteDialog from '../panes/media/local/deleteDialog';\nimport ApiContext from '../../../app/api/context';\nimport MediaContext from '../../../app/media/context';\n\nconst deleteMedia = jest.fn();\nconst deleteMediaElement = jest.fn();\nconst showSnackbar = jest.fn();\n\nfunction setup() {\n  deleteMedia.mockReset();\n  deleteMediaElement.mockReset();\n  showSnackbar.mockReset();\n\n  const apiValue = {\n    actions: {\n      deleteMedia,\n    },\n  };\n\n  const mediaValue = {\n    local: {\n      actions: {\n        deleteMediaElement,\n      },\n    },\n  };\n\n  const snackbarValue = { showSnackbar };\n\n  return renderWithTheme(\n    <SnackbarContext.Provider value={snackbarValue}>\n      <MediaContext.Provider value={mediaValue}>\n        <ApiContext.Provider value={apiValue}>\n          <DeleteDialog mediaId={123} type={'image'} onClose={() => {}} />\n        </ApiContext.Provider>\n      </MediaContext.Provider>\n    </SnackbarContext.Provider>\n  );\n}\n\ndescribe('DeleteDialog', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  it('should render', () => {\n    const { container } = setup();\n    setAppElement(container);\n\n    expect(screen.getByText('Delete Image?')).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: /delete/i })).toBeInTheDocument();\n  });\n\n  it('should update server and internal state on delete', async () => {\n    const { container } = setup();\n    setAppElement(container);\n\n    // Mock out `deleteMedia`.\n    let serverDeleted = false;\n    deleteMedia.mockImplementation(() => {\n      serverDeleted = true;\n    });\n\n    // Mock out `deleteMediaElement`.\n    let stateDeleted = false;\n    deleteMediaElement.mockImplementation(() => {\n      stateDeleted = true;\n    });\n\n    fireEvent.click(screen.getByRole('button', { name: /delete/i }));\n\n    await waitFor(() => expect(deleteMedia).toHaveBeenCalledOnce());\n    expect(deleteMediaElement).toHaveBeenCalledOnce();\n\n    expect(serverDeleted).toBeTrue();\n    expect(stateDeleted).toBeTrue();\n  });\n\n  it('should show snackbar if error on delete from server', async () => {\n    const { container } = setup();\n    setAppElement(container);\n\n    // Mock out `deleteMedia`.\n    deleteMedia.mockImplementation(() => {\n      throw Error;\n    });\n\n    fireEvent.click(screen.getByRole('button', { name: /delete/i }));\n\n    await waitFor(() => expect(deleteMedia).toHaveBeenCalledOnce());\n    expect(deleteMediaElement).toHaveBeenCalledTimes(0);\n    expect(showSnackbar).toHaveBeenCalledOnce();\n  });\n\n  it('should show snackbar if error on delete from state', async () => {\n    const { container } = setup();\n    setAppElement(container);\n\n    // Mock out `deleteMediaElement`.\n    deleteMediaElement.mockImplementation(() => {\n      throw Error;\n    });\n\n    fireEvent.click(screen.getByRole('button', { name: /delete/i }));\n\n    await waitFor(() => expect(deleteMedia).toHaveBeenCalledOnce());\n    expect(deleteMediaElement).toHaveBeenCalledOnce();\n    expect(showSnackbar).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/mediaEditDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, fireEvent, screen } from '@testing-library/react';\nimport {\n  SnackbarContext,\n  setAppElement,\n} from '@googleforcreators/design-system';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport MediaEditDialog from '../panes/media/local/mediaEditDialog';\nimport ApiContext from '../../../app/api/context';\nimport MediaContext from '../../../app/media/context';\n\nconst updateMedia = jest.fn();\nconst updateMediaElement = jest.fn();\nconst showSnackbar = jest.fn();\n\nconst resource = {\n  type: 'image',\n  mimeType: 'image/png',\n  src: 'image-url',\n  width: 910,\n  height: 675,\n  alt: 'my image alt text',\n  sizes: {},\n};\n\nfunction setup() {\n  updateMedia.mockReset();\n  updateMediaElement.mockReset();\n  showSnackbar.mockReset();\n\n  const apiValue = {\n    actions: {\n      updateMedia,\n    },\n  };\n\n  const mediaValue = {\n    local: {\n      actions: {\n        updateMediaElement,\n      },\n    },\n  };\n\n  const snackbarValue = { showSnackbar };\n\n  return renderWithTheme(\n    <SnackbarContext.Provider value={snackbarValue}>\n      <MediaContext.Provider value={mediaValue}>\n        <ApiContext.Provider value={apiValue}>\n          <MediaEditDialog resource={resource} onClose={() => {}} />\n        </ApiContext.Provider>\n      </MediaContext.Provider>\n    </SnackbarContext.Provider>\n  );\n}\n\ndescribe('MediaEditDialog', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n  });\n\n  it('should render', () => {\n    setup();\n\n    expect(screen.getByText('Edit Image')).toBeInTheDocument();\n    expect(screen.getByText('910 x 675 pixels')).toBeInTheDocument();\n    expect(screen.getByLabelText('Assistive text').value).toContain(\n      'my image alt text'\n    );\n    expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument();\n  });\n\n  it('should update server and internal state with new alt text on save', async () => {\n    setup();\n\n    // Mock out `updateMedia`.\n    let serverAltText = resource.alt;\n    updateMedia.mockImplementation((_id, update) => {\n      serverAltText = update.altText;\n    });\n\n    // Mock out `updateMediaElement`.\n    let stateAltText = resource.alt;\n    updateMediaElement.mockImplementation((update) => {\n      stateAltText = update.data.alt;\n    });\n\n    const input = screen.getByLabelText('Assistive text');\n    fireEvent.change(input, { target: { value: 'new alt text' } });\n    fireEvent.click(screen.getByRole('button', { name: /save/i }));\n\n    await waitFor(() => expect(updateMedia).toHaveBeenCalledOnce());\n    expect(updateMediaElement).toHaveBeenCalledOnce();\n\n    expect(serverAltText).toBe('new alt text');\n    expect(stateAltText).toBe('new alt text');\n  });\n\n  it('should show snackbar if error on save to server', async () => {\n    setup();\n\n    // Mock out `updateMedia`.\n    const serverAltText = resource.alt;\n    updateMedia.mockImplementation(() => {\n      throw Error;\n    });\n\n    const input = screen.getByLabelText('Assistive text');\n    fireEvent.change(input, { target: { value: 'new alt text' } });\n    fireEvent.click(screen.getByRole('button', { name: /save/i }));\n\n    await waitFor(() => expect(updateMedia).toHaveBeenCalledOnce());\n    expect(updateMediaElement).toHaveBeenCalledTimes(0);\n    expect(showSnackbar).toHaveBeenCalledOnce();\n    expect(serverAltText).toBe('my image alt text');\n  });\n\n  it('should show snackbar if error on save to state', async () => {\n    setup();\n\n    // Mock out `updateMediaElement`.\n    updateMediaElement.mockImplementation(() => {\n      throw Error;\n    });\n\n    const input = screen.getByLabelText('Assistive text');\n    fireEvent.change(input, { target: { value: 'new alt text' } });\n    fireEvent.click(screen.getByRole('button', { name: /save/i }));\n\n    await waitFor(() => expect(updateMedia).toHaveBeenCalledOnce());\n    expect(updateMediaElement).toHaveBeenCalledOnce();\n    expect(showSnackbar).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/mediaElement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport MediaElement from '../panes/media/common/mediaElement';\nimport CanvasContext from '../../../app/canvas/context';\nimport StoryContext from '../../../app/story/context';\nimport { useLocalMedia } from '../../../app/media';\njest.mock('../../../app/media');\n\nconst IMAGE_RESOURCE = {\n  id: 789,\n  src: 'http://image-url.com',\n  type: 'image',\n  mimeType: 'image/png',\n  width: 100,\n  height: 100,\n  alt: 'image :)',\n};\n\nconst VIDEO_RESOURCE = {\n  id: 456,\n  src: 'http://video-url.com',\n  type: 'video',\n  mimeType: 'video/mp4',\n  width: 100,\n  height: 100,\n  alt: 'video :)',\n};\n\nconst GIF_RESOURCE = {\n  id: 789,\n  src: 'http://gif-url.com',\n  type: 'gif',\n  mimeType: 'image/gif',\n  width: 100,\n  height: 100,\n  alt: 'gif :)',\n  output: {\n    src: 'http://gif-url.com',\n  },\n};\n\nconst renderMediaElement = (resource, providerType, canEditMedia = true) => {\n  const canvasContext = {\n    state: {\n      pageSize: {\n        width: 200,\n        height: 200,\n      },\n      designSpaceGuideline: document.body,\n      canvasContainer: document.body,\n      pageContainer: document.body,\n      nodesById: [],\n    },\n    actions: {},\n  };\n  const storyContext = {\n    state: {\n      currentPage: {\n        elements: [],\n      },\n    },\n    actions: {\n      addElement: jest.fn(),\n      combineElements: jest.fn(),\n    },\n  };\n  return renderWithTheme(\n    <StoryContext.Provider value={storyContext}>\n      <CanvasContext.Provider value={canvasContext}>\n        <MediaElement\n          index={0}\n          resource={resource}\n          onInsert={() => {}}\n          providerType={providerType}\n          width={150}\n          height={150}\n          canEditMedia={canEditMedia}\n        />\n      </CanvasContext.Provider>\n    </StoryContext.Provider>\n  );\n};\n\nconst mockedReturnValue = {\n  isCurrentResourceTrimming: jest.fn(),\n  isCurrentResourceMuting: jest.fn(),\n  isCurrentResourceTranscoding: jest.fn(),\n  isNewResourceProcessing: jest.fn(),\n  canTranscodeResource: jest.fn(),\n  isCurrentResourceProcessing: jest.fn(),\n  isCurrentResourceUploading: jest.fn(),\n};\n\ndescribe('MediaElement', () => {\n  beforeEach(() => {\n    useLocalMedia.mockReturnValue(mockedReturnValue);\n  });\n\n  it('should render MediaElement for a resource of type=`image` without accessibility violations', async () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { container } = renderMediaElement(IMAGE_RESOURCE, 'local');\n\n    const results = await axe(container, { preload: false });\n    expect(results).toHaveNoViolations();\n  }, 30000);\n\n  it('should render MediaElement for a resource of type=`gif` without accessibility violations', async () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { container } = renderMediaElement(GIF_RESOURCE, 'local');\n\n    const results = await axe(container, { preload: false });\n    expect(results).toHaveNoViolations();\n  }, 30000);\n\n  it('should render MediaElement for a resource of type=`video` without accessibility violations', async () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { container } = renderMediaElement(VIDEO_RESOURCE, 'local');\n\n    const results = await axe(container, { preload: false });\n    expect(results).toHaveNoViolations();\n  }, 30000);\n\n  it(\"should render dropdown menu's more icon for uploaded image\", () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { getByAriaLabel } = renderMediaElement(\n      {\n        ...IMAGE_RESOURCE,\n      },\n      'local'\n    );\n    expect(getByAriaLabel('More')).toBeInTheDocument();\n  });\n\n  it(\"should render dropdown menu's more icon for uploaded video\", () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { getByAriaLabel } = renderMediaElement(\n      {\n        ...VIDEO_RESOURCE,\n      },\n      'local'\n    );\n    expect(getByAriaLabel('More')).toBeInTheDocument();\n  });\n\n  it(\"should render dropdown menu's more icon for uploaded gif\", () => {\n    useLocalMedia.mockReturnValue({\n      ...mockedReturnValue,\n      canTranscodeResource: () => true,\n    });\n    const { getByAriaLabel } = renderMediaElement(\n      {\n        ...GIF_RESOURCE,\n      },\n      'local'\n    );\n    expect(getByAriaLabel('More')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/shapes/shapePreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { UnitsProvider, PAGE_RATIO } from '@googleforcreators/units';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport ShapePreview from '../../panes/shapes/shapePreview';\nimport useLibrary from '../../useLibrary';\nimport { TEXT_SET_SIZE } from '../../../../constants';\nimport CanvasContext from '../../../../app/canvas/context';\n\njest.mock('../../useLibrary');\n\ndescribe('ShapePreview', () => {\n  const insertElement = jest.fn();\n\n  const rectangleMask = {\n    type: 'rectangle',\n    name: 'Rectangle',\n    path: 'M 0,0 1,0 1,1 0,1 0,0 Z',\n    ratio: 1,\n  };\n\n  beforeAll(() => {\n    useLibrary.mockImplementation(() => ({\n      actions: {\n        insertElement: insertElement,\n      },\n    }));\n  });\n\n  it('should render', () => {\n    const canvasValue = {\n      state: {\n        nodesById: {},\n        pageSize: {},\n        pageContainer: document.body,\n        canvasContainer: document.body,\n        designSpaceGuideline: {},\n        boundingBoxes: {},\n      },\n      actions: {},\n    };\n    renderWithTheme(\n      <CanvasContext.Provider value={canvasValue}>\n        <UnitsProvider\n          pageSize={{\n            width: TEXT_SET_SIZE,\n            height: TEXT_SET_SIZE / PAGE_RATIO,\n          }}\n          dataToEditorX={jest.fn()}\n          dataToEditorY={jest.fn()}\n        >\n          <ShapePreview mask={rectangleMask} />\n        </UnitsProvider>\n      </CanvasContext.Provider>\n    );\n    expect(screen.getByLabelText(rectangleMask.name)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/shapes/stickerPreview.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { UnitsProvider, PAGE_RATIO } from '@googleforcreators/units';\nimport STICKERS from '@googleforcreators/stickers';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StickerPreview from '../../panes/shapes/stickerPreview';\nimport useLibrary from '../../useLibrary';\nimport { TEXT_SET_SIZE } from '../../../../constants';\nimport CanvasContext from '../../../../app/canvas/context';\n\njest.mock('../../useLibrary');\n\ndescribe('StickerPreview', () => {\n  const insertElement = jest.fn();\n\n  beforeAll(() => {\n    useLibrary.mockImplementation(() => ({\n      actions: {\n        insertElement: insertElement,\n      },\n    }));\n  });\n\n  it('should render', () => {\n    const canvasValue = {\n      state: {\n        nodesById: {},\n        pageSize: {},\n        pageContainer: document.body,\n        canvasContainer: document.body,\n        designSpaceGuideline: {},\n        boundingBoxes: {},\n      },\n      actions: {},\n    };\n    renderWithTheme(\n      <CanvasContext.Provider value={canvasValue}>\n        <UnitsProvider\n          pageSize={{\n            width: TEXT_SET_SIZE,\n            height: TEXT_SET_SIZE / PAGE_RATIO,\n          }}\n          dataToEditorX={jest.fn()}\n          dataToEditorY={jest.fn()}\n        >\n          <StickerPreview stickerType={'beautyCta'} />\n        </UnitsProvider>\n      </CanvasContext.Provider>\n    );\n\n    // Stickers render title in svg <title>...</title> element\n    expect(screen.getByText(STICKERS.beautyCta.title)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/termsDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, fireEvent, screen } from '@testing-library/react';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport TermsDialog from '../panes/media/media3p/termsDialog';\n\njest.mock('@googleforcreators/design-system', () => ({\n  __esModule: true,\n  ...jest.requireActual('@googleforcreators/design-system'),\n  localStore: {\n    setItemByKey: jest.fn(),\n    getItemByKey: jest.fn(() => false),\n  },\n}));\n\ndescribe('TermsDialog', () => {\n  it('should store the acknowledgement in the localStore when the window is dismissed', async () => {\n    renderWithTheme(<TermsDialog />);\n    const dismiss = screen.queryByText(/^Dismiss/);\n    expect(localStore.getItemByKey).toHaveBeenCalledWith(\n      LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P\n    );\n\n    fireEvent.click(dismiss);\n\n    await waitFor(() =>\n      expect(localStore.setItemByKey).toHaveBeenCalledWith(\n        LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P,\n        true\n      )\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/test/text/textPane.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, waitFor } from '@testing-library/react';\nimport { FlagsProvider } from 'flagged';\nimport { PAGE_RATIO, UnitsProvider } from '@googleforcreators/units';\nimport { CURATED_FONT_NAMES } from '@googleforcreators/fonts';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport FontContext from '../../../../app/font/context';\nimport useFont from '../../../../app/font/useFont';\nimport fontsListResponse from '../../../panels/design/textStyle/test/fontsResponse.json';\nimport TextPane from '../../panes/text/textPane';\nimport { PRESETS } from '../../panes/text/textPresets';\nimport useLibrary from '../../useLibrary';\nimport useInsertPreset from '../../panes/text/useInsertPreset';\nimport { TEXT_SET_SIZE } from '../../../../constants';\nimport CanvasContext from '../../../../app/canvas/context';\nimport StoryContext from '../../../../app/story/context';\n\njest.mock('../../useLibrary');\njest.mock('../../../../app/font/useFont');\njest.mock('../../panes/text/useInsertPreset');\n\ndescribe('TextPane', () => {\n  const maybeEnqueueFontStyle = jest.fn();\n  const insertPreset = jest.fn();\n  const getPosition = jest.fn();\n  beforeAll(() => {\n    useLibrary.mockImplementation((selector) =>\n      selector({\n        state: {\n          textSets: {},\n        },\n        actions: {\n          insertElement: jest.fn(),\n        },\n      })\n    );\n\n    useFont.mockImplementation(() => ({\n      actions: {\n        maybeEnqueueFontStyle: maybeEnqueueFontStyle,\n      },\n    }));\n\n    useInsertPreset.mockImplementation(() => ({\n      insertPreset,\n      getPosition,\n    }));\n  });\n\n  it('should insert text with preset text style when clicking Enter', async () => {\n    const availableCuratedFonts = fontsListResponse.filter(\n      (font) => CURATED_FONT_NAMES.indexOf(font.name) > 0\n    );\n\n    const fontContextValues = {\n      state: {\n        fonts: fontsListResponse,\n        recentFonts: [],\n        curatedFonts: availableCuratedFonts,\n      },\n      actions: {\n        ensureMenuFontsLoaded: () => {},\n        ensureCustomFontsLoaded: () => {},\n        loadCustomFonts: jest.fn(),\n        loadCuratedFonts: jest.fn(),\n      },\n    };\n\n    const canvasContextValue = {\n      state: {\n        nodesById: {},\n        pageSize: {},\n        pageContainer: document.body,\n        canvasContainer: document.body,\n        designSpaceGuideline: {},\n      },\n      actions: {},\n    };\n\n    const storyContextValue = {\n      state: {\n        currentPage: {\n          elements: [\n            {\n              id: 'bg',\n              type: 'shape',\n            },\n          ],\n        },\n        selectedElementIds: [],\n        selectedElements: [],\n        story: {\n          globalStoryStyles: {\n            colors: [],\n            textStyles: [],\n          },\n          currentStoryStyles: {\n            colors: [],\n          },\n        },\n      },\n      actions: {},\n    };\n\n    renderWithTheme(\n      <FlagsProvider\n        features={{\n          showTextSets: false,\n          showTextAndShapesSearchInput: false,\n        }}\n      >\n        <StoryContext.Provider value={storyContextValue}>\n          <CanvasContext.Provider value={canvasContextValue}>\n            <FontContext.Provider value={fontContextValues}>\n              <UnitsProvider\n                pageSize={{\n                  width: TEXT_SET_SIZE,\n                  height: TEXT_SET_SIZE / PAGE_RATIO,\n                }}\n                dataToEditorX={jest.fn()}\n                dataToEditorY={jest.fn()}\n              >\n                <TextPane isActive />\n              </UnitsProvider>\n            </FontContext.Provider>\n          </CanvasContext.Provider>\n        </StoryContext.Provider>\n      </FlagsProvider>\n    );\n\n    // Note: onClick handler is in Moveable so we can't test that directly in this component\n    // and have to test using key handlers instead.\n    fireEvent.keyDown(screen.getByRole('button', { name: 'Title 1' }), {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() => expect(insertPreset).toHaveBeenCalledOnce());\n\n    // Height is being assigned in the process of text insertion.\n    await waitFor(() =>\n      expect(insertPreset).toHaveBeenCalledWith(PRESETS[0].element, {\n        isPositioned: false,\n        accessibleColors: undefined,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/library/useLibrary.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useLibrary(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useLibrary;\n"
  },
  {
    "path": "packages/story-editor/src/components/localAutoSaveHandler/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './localAutoSave';\n"
  },
  {
    "path": "packages/story-editor/src/components/localAutoSaveHandler/localAutoSave.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useState, useRef } from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonType,\n  ButtonSize,\n  TextSize,\n  Text,\n  sessionStore,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useConfig, useHistory, useStory } from '../../app';\nimport useIsUploadingToStory from '../../utils/useIsUploadingToStory';\nimport Dialog from '../dialog';\nimport getSessionStorageKey from '../../utils/getSessionStorageKey';\n\nfunction LocalAutoSave() {\n  const { localAutoSaveInterval = 15 } = useConfig();\n  const {\n    state: { hasNewChanges },\n  } = useHistory();\n  const isUploading = useIsUploadingToStory();\n  const { isAutoSavingStory } = useStory(({ state }) => ({\n    isAutoSavingStory: state.meta.isAutoSavingStory,\n  }));\n\n  const { story, pages, restoreLocalAutoSave } = useStory(\n    ({ state, actions }) => ({\n      story: state.story,\n      pages: state.pages,\n      restoreLocalAutoSave: actions.restoreLocalAutoSave,\n    })\n  );\n  const { storyId, status } = story;\n  const isNew = 'auto-draft' === status;\n\n  const [backup, setBackup] = useState(null);\n\n  // Store into ref for not triggering autosave display when these change.\n  const storyRef = useRef();\n  const pagesRef = useRef();\n  useEffect(() => {\n    storyRef.current = story;\n    pagesRef.current = pages;\n  }, [story, pages]);\n\n  // Save the local autosave.\n  useEffect(() => {\n    if (\n      !hasNewChanges ||\n      !localAutoSaveInterval ||\n      isUploading ||\n      isAutoSavingStory\n    ) {\n      return undefined;\n    }\n\n    // This is only a timeout (and not an interval), as `hasNewChanges` will come\n    // back false after the save.\n    // This timeout will thus be re-started when some new change occurs after an autosave.\n    const timeout = setTimeout(\n      () =>\n        sessionStore.setItemByKey(getSessionStorageKey(storyId, isNew), {\n          story,\n          pages,\n        }),\n      localAutoSaveInterval * 1000\n    );\n\n    return () => clearTimeout(timeout);\n  }, [\n    localAutoSaveInterval,\n    hasNewChanges,\n    isUploading,\n    pages,\n    story,\n    storyId,\n    isNew,\n    isAutoSavingStory,\n  ]);\n\n  const onClose = () => {\n    sessionStore.deleteItemByKey(getSessionStorageKey(storyId, isNew));\n    setBackup(null);\n  };\n\n  const didAutoSaveRef = useRef(isAutoSavingStory);\n  useEffect(() => {\n    if (isAutoSavingStory) {\n      didAutoSaveRef.current = true;\n      // If we auto-saved to DB before but are not auto-saving anymore, let's delete the local backup.\n      // No need for both local and DB backup together.\n    } else if (didAutoSaveRef.current && !backup) {\n      sessionStore.deleteItemByKey(getSessionStorageKey(storyId, false));\n      didAutoSaveRef.current = false;\n    }\n  }, [isAutoSavingStory, backup, storyId]);\n\n  const handleNewChangesRef = useRef(false);\n  const wasNewRef = useRef(isNew);\n  useEffect(() => {\n    // If we have new changes, track that we had new changes.\n    if (hasNewChanges) {\n      handleNewChangesRef.current = true;\n      // If we don't have new changes but had before, we are in a saved state. Delete existing storage.\n      // Let's not delete the auto-draft if the restore message is currently displayed.\n    } else if (handleNewChangesRef.current && !backup) {\n      if (wasNewRef.current) {\n        sessionStore.deleteItemByKey(getSessionStorageKey(null, true));\n      } else {\n        sessionStore.deleteItemByKey(getSessionStorageKey(storyId, false));\n      }\n      handleNewChangesRef.current = false;\n      wasNewRef.current = isNew;\n    }\n  }, [hasNewChanges, backup, storyId, isNew]);\n\n  // Display\n  useEffect(() => {\n    const existingAutoSave = sessionStore.getItemByKey(\n      getSessionStorageKey(storyId, isNew)\n    );\n    if (!existingAutoSave) {\n      return;\n    }\n\n    const autoSaveHasChanges =\n      JSON.stringify(existingAutoSave.pages) !==\n        JSON.stringify(pagesRef.current) &&\n      JSON.stringify(existingAutoSave.story) !==\n        JSON.stringify(storyRef.current);\n\n    // If we have an autosave and it differs from the current state.\n    if (autoSaveHasChanges) {\n      setBackup(existingAutoSave);\n      return;\n    }\n\n    // Otherwise, delete the autosave.\n    sessionStore.deleteItemByKey(getSessionStorageKey(storyId, isNew));\n  }, [setBackup, isNew, storyId]);\n\n  if (!backup) {\n    return null;\n  }\n\n  const restoreBackup = () => {\n    restoreLocalAutoSave();\n    sessionStore.deleteItemByKey(getSessionStorageKey(storyId, isNew));\n    setBackup(null);\n  };\n\n  return (\n    <Dialog\n      isOpen\n      secondaryText={__('Dismiss', 'web-stories')}\n      onClose={onClose}\n      actions={\n        <>\n          <Button\n            type={ButtonType.Tertiary}\n            size={ButtonSize.Small}\n            onClick={onClose}\n          >\n            {__('Dismiss', 'web-stories')}\n          </Button>\n          <Button\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            onClick={restoreBackup}\n          >\n            {__('Restore Backup', 'web-stories')}\n          </Button>\n        </>\n      }\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'The backup of this story in your browser is different from the current version.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nexport default LocalAutoSave;\n"
  },
  {
    "path": "packages/story-editor/src/components/localAutoSaveHandler/test/localAutoSaveHandler.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport HistoryContext from '../../../app/history/context';\nimport StoryContext from '../../../app/story/context';\nimport ConfigContext from '../../../app/config/context';\nimport LocalAutoSaveHandler from '..';\nimport useIsUploadingToStory from '../../../utils/useIsUploadingToStory';\n\njest.mock('../../../utils/useIsUploadingToStory');\n\nconst mockSaveLocal = jest.fn();\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  sessionStore: {\n    getItemByKey: jest.fn(() => false),\n    setItemByKey: (key, data) => mockSaveLocal(key, data),\n    deleteItemByKey: jest.fn(),\n  },\n}));\n\nfunction setup({\n  hasNewChanges = true,\n  status = 'auto-draft',\n  isUploading = false,\n}) {\n  const historyContextValue = { state: { hasNewChanges } };\n  const configValue = {\n    localAutoSaveInterval: 0.1,\n  };\n  const storyContextValue = {\n    state: {\n      story: { status, storyId: 1 },\n      pages: [{ id: 1 }],\n      meta: {\n        isAutoSavingStory: false,\n      },\n    },\n    actions: {\n      restoreLocalAutoSave: jest.fn(),\n    },\n  };\n\n  useIsUploadingToStory.mockImplementation(() => isUploading);\n\n  render(\n    <ConfigContext.Provider value={configValue}>\n      <HistoryContext.Provider value={historyContextValue}>\n        <StoryContext.Provider value={storyContextValue}>\n          <LocalAutoSaveHandler />\n        </StoryContext.Provider>\n      </HistoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n}\n\ndescribe('AutoSaveHandler', () => {\n  beforeEach(() => {\n    jest.useFakeTimers();\n  });\n\n  afterEach(() => {\n    mockSaveLocal.mockRestore();\n  });\n\n  it('should trigger saving for auto-draft', () => {\n    setup({});\n    jest.runAllTimers();\n    expect(mockSaveLocal).toHaveBeenLastCalledWith(\n      'wp_stories_autosave_story_auto-draft',\n      {\n        pages: [{ id: 1 }],\n        story: { status: 'auto-draft', storyId: 1 },\n      }\n    );\n  });\n\n  it('should trigger saving for a saved story', () => {\n    setup({ status: 'draft' });\n    jest.runAllTimers();\n    expect(mockSaveLocal).toHaveBeenLastCalledWith(\n      'wp_stories_autosave_story_1',\n      {\n        pages: [{ id: 1 }],\n        story: { status: 'draft', storyId: 1 },\n      }\n    );\n  });\n\n  it('should not trigger saving in case of not having new changes', () => {\n    setup({ hasNewChanges: false });\n    jest.runAllTimers();\n    expect(mockSaveLocal).toHaveBeenCalledTimes(0);\n  });\n\n  it('should not trigger saving when media is uploading', () => {\n    setup({\n      isUploading: true,\n    });\n    jest.runAllTimers();\n    expect(mockSaveLocal).toHaveBeenCalledTimes(0);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/audio.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\n\nconst AudioWrapper = styled.div`\n  background: ${({ theme }) => theme.colors.bg.secondary};\n  border-radius: 5px;\n  width: 100%;\n  height: 100%;\n`;\n\nfunction Audio({ liveStream }) {\n  return (\n    <AudioWrapper>\n      <AudioAnalyser source={liveStream} />\n    </AudioWrapper>\n  );\n}\n\nAudio.propTypes = {\n  liveStream: PropTypes.object,\n};\n\nconst AudioAnalyser = ({ source }) => {\n  const [data, setData] = useState([]);\n  const rafRef = useRef();\n  const audioContextRef = useRef();\n  const analyserRef = useRef();\n  const prevRafTimeRef = useRef();\n\n  if (!analyserRef.current) {\n    audioContextRef.current = new window.AudioContext();\n    analyserRef.current = audioContextRef.current.createAnalyser();\n  }\n\n  useEffect(() => {\n    if (source.getAudioTracks().length === 0) {\n      return noop;\n    }\n\n    const audioNode = audioContextRef.current.createMediaStreamSource(source);\n    audioNode.connect(analyserRef.current);\n\n    const tick = (time) => {\n      if (prevRafTimeRef.current !== undefined) {\n        const dataArray = new Uint8Array(analyserRef.current.frequencyBinCount);\n        analyserRef.current.getByteTimeDomainData(dataArray);\n        setData(dataArray);\n      }\n      prevRafTimeRef.current = time;\n      rafRef.current = requestAnimationFrame(tick);\n    };\n\n    rafRef.current = requestAnimationFrame(tick);\n    return () => {\n      cancelAnimationFrame(rafRef.current);\n      analyserRef.current.disconnect();\n      audioNode.disconnect();\n    };\n  }, [source]);\n\n  return <AudioVisualiser data={data} />;\n};\n\nAudioAnalyser.propTypes = {\n  source: PropTypes.object,\n};\n\nconst AudioVisualiser = ({ data }) => {\n  const ref = useRef();\n  const canvas = ref.current;\n  if (canvas) {\n    canvas.style.width = '100%';\n    canvas.style.height = '100%';\n    canvas.width = canvas.offsetWidth;\n    canvas.height = canvas.offsetHeight;\n\n    const height = canvas.height;\n    const width = canvas.width;\n    const context = canvas.getContext('2d');\n    const sliceWidth = Number(width) / data.length;\n\n    context.lineWidth = 2;\n    context.strokeStyle = '#FFF';\n    context.clearRect(0, 0, width, height);\n\n    context.beginPath();\n    context.moveTo(0, height / 2);\n    let x = 0;\n    for (const item of data) {\n      const y = (item / 255.0) * height;\n      context.lineTo(x, y);\n      x += sliceWidth;\n    }\n    context.lineTo(x, height / 2);\n    context.stroke();\n  }\n\n  return <canvas ref={ref} />;\n};\n\nAudioVisualiser.propTypes = {\n  data: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),\n};\n\nexport default Audio;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/blur.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst blur = (context, amount) => {\n  if (amount <= 0) {\n    return context;\n  }\n\n  const { height, width } = context.canvas;\n  const imageData = context.getImageData(0, 0, width, height);\n  const { data } = imageData;\n\n  // http://www.quasimondo.com/BoxBlurForCanvas/FastBlur.js\n  const wm = width - 1;\n  const hm = height - 1;\n  const rad1 = amount + 1;\n\n  const mulTable = [\n    1, 57, 41, 21, 203, 34, 97, 73, 227, 91, 149, 62, 105, 45, 39, 137, 241,\n    107, 3, 173, 39, 71, 65, 238, 219, 101, 187, 87, 81, 151, 141, 133, 249,\n    117, 221, 209, 197, 187, 177, 169, 5, 153, 73, 139, 133, 127, 243, 233, 223,\n    107, 103, 99, 191, 23, 177, 171, 165, 159, 77, 149, 9, 139, 135, 131, 253,\n    245, 119, 231, 224, 109, 211, 103, 25, 195, 189, 23, 45, 175, 171, 83, 81,\n    79, 155, 151, 147, 9, 141, 137, 67, 131, 129, 251, 123, 30, 235, 115, 113,\n    221, 217, 53, 13, 51, 50, 49, 193, 189, 185, 91, 179, 175, 43, 169, 83, 163,\n    5, 79, 155, 19, 75, 147, 145, 143, 35, 69, 17, 67, 33, 65, 255, 251, 247,\n    243, 239, 59, 29, 229, 113, 111, 219, 27, 213, 105, 207, 51, 201, 199, 49,\n    193, 191, 47, 93, 183, 181, 179, 11, 87, 43, 85, 167, 165, 163, 161, 159,\n    157, 155, 77, 19, 75, 37, 73, 145, 143, 141, 35, 138, 137, 135, 67, 33, 131,\n    129, 255, 63, 250, 247, 61, 121, 239, 237, 117, 29, 229, 227, 225, 111, 55,\n    109, 216, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 48, 190,\n    47, 93, 185, 183, 181, 179, 178, 176, 175, 173, 171, 85, 21, 167, 165, 41,\n    163, 161, 5, 79, 157, 78, 154, 153, 19, 75, 149, 74, 147, 73, 144, 143, 71,\n    141, 140, 139, 137, 17, 135, 134, 133, 66, 131, 65, 129, 1,\n  ];\n  const mulSum = mulTable[amount];\n\n  const shgTable = [\n    0, 9, 10, 10, 14, 12, 14, 14, 16, 15, 16, 15, 16, 15, 15, 17, 18, 17, 12,\n    18, 16, 17, 17, 19, 19, 18, 19, 18, 18, 19, 19, 19, 20, 19, 20, 20, 20, 20,\n    20, 20, 15, 20, 19, 20, 20, 20, 21, 21, 21, 20, 20, 20, 21, 18, 21, 21, 21,\n    21, 20, 21, 17, 21, 21, 21, 22, 22, 21, 22, 22, 21, 22, 21, 19, 22, 22, 19,\n    20, 22, 22, 21, 21, 21, 22, 22, 22, 18, 22, 22, 21, 22, 22, 23, 22, 20, 23,\n    22, 22, 23, 23, 21, 19, 21, 21, 21, 23, 23, 23, 22, 23, 23, 21, 23, 22, 23,\n    18, 22, 23, 20, 22, 23, 23, 23, 21, 22, 20, 22, 21, 22, 24, 24, 24, 24, 24,\n    22, 21, 24, 23, 23, 24, 21, 24, 23, 24, 22, 24, 24, 22, 24, 24, 22, 23, 24,\n    24, 24, 20, 23, 22, 23, 24, 24, 24, 24, 24, 24, 24, 23, 21, 23, 22, 23, 24,\n    24, 24, 22, 24, 24, 24, 23, 22, 24, 24, 25, 23, 25, 25, 23, 24, 25, 25, 24,\n    22, 25, 25, 25, 24, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n    23, 25, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 22, 25, 25, 23, 25,\n    25, 20, 24, 25, 24, 25, 25, 22, 24, 25, 24, 25, 24, 25, 25, 24, 25, 25, 25,\n    25, 22, 25, 25, 25, 24, 25, 24, 25, 18,\n  ];\n  const shgSum = shgTable[amount];\n\n  const r = [];\n  const g = [];\n  const b = [];\n  const a = [];\n\n  const vmin = [];\n  const vmax = [];\n\n  let iterations = 3;\n  let p, p1, p2, pa;\n\n  while (iterations-- > 0) {\n    let yw = 0;\n    let yi = 0;\n\n    for (let y = 0; y < height; y++) {\n      let rsum = data[yw] * rad1;\n      let gsum = data[yw + 1] * rad1;\n      let bsum = data[yw + 2] * rad1;\n      let asum = data[yw + 3] * rad1;\n\n      for (let i = 1; i <= amount; i++) {\n        p = yw + ((i > wm ? wm : i) << 2);\n        rsum += data[p++];\n        gsum += data[p++];\n        bsum += data[p++];\n        asum += data[p];\n      }\n\n      for (let x = 0; x < width; x++) {\n        r[yi] = rsum;\n        g[yi] = gsum;\n        b[yi] = bsum;\n        a[yi] = asum;\n\n        if (y === 0) {\n          vmin[x] = ((p = x + rad1) < wm ? p : wm) << 2;\n          vmax[x] = (p = x - amount) > 0 ? p << 2 : 0;\n        }\n\n        p1 = yw + vmin[x];\n        p2 = yw + vmax[x];\n\n        rsum += data[p1++] - data[p2++];\n        gsum += data[p1++] - data[p2++];\n        bsum += data[p1++] - data[p2++];\n        asum += data[p1] - data[p2];\n\n        yi++;\n      }\n      yw += width << 2;\n    }\n\n    for (let x = 0; x < width; x++) {\n      let yp = x;\n      let rsum = r[yp] * rad1;\n      let gsum = g[yp] * rad1;\n      let bsum = b[yp] * rad1;\n      let asum = a[yp] * rad1;\n\n      for (let i = 1; i <= amount; i++) {\n        yp += i > hm ? 0 : width;\n        rsum += r[yp];\n        gsum += g[yp];\n        bsum += b[yp];\n        asum += a[yp];\n      }\n\n      yi = x << 2;\n\n      for (let y = 0; y < height; y++) {\n        data[yi + 3] = pa = (asum * mulSum) >>> shgSum;\n\n        if (pa > 0) {\n          pa = 255 / pa;\n          data[yi] = ((rsum * mulSum) >>> shgSum) * pa;\n          data[yi + 1] = ((gsum * mulSum) >>> shgSum) * pa;\n          data[yi + 2] = ((bsum * mulSum) >>> shgSum) * pa;\n        } else {\n          data[yi] = data[yi + 1] = data[yi + 2] = 0;\n        }\n\n        if (x === 0) {\n          vmin[y] = ((p = y + rad1) < hm ? p : hm) * width;\n          vmax[y] = (p = y - amount) > 0 ? p * width : 0;\n        }\n\n        p1 = x + vmin[y];\n        p2 = x + vmax[y];\n\n        rsum += r[p1] - r[p2];\n        gsum += g[p1] - g[p2];\n        bsum += b[p1] - b[p2];\n        asum += a[p1] - a[p2];\n\n        yi += width << 2;\n      }\n    }\n  }\n\n  context.putImageData(imageData, 0, 0);\n  return context;\n};\n\nexport default blur;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/components.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\nexport const MessageWrap = styled.div`\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  align-content: center;\n  padding: 20px;\n  height: 100%;\n  justify-content: center;\n  text-align: center;\n  user-select: text;\n`;\n\nexport const MessageHeading = styled(Text.Paragraph).attrs({\n  size: TextSize.XLarge,\n})`\n  margin: 0 0 14px;\n`;\n\nexport const MessageText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  margin: 0 0 14px;\n`;\n\nexport const Wrapper = styled.div`\n  background-color: ${({ theme }) => theme.colors.standard.white};\n  border-radius: 5px;\n  position: absolute;\n  transform: translateZ(0);\n  top: 0;\n  left: 0;\n  bottom: 0;\n  right: 0;\n  cursor: default;\n`;\n\nexport const VideoWrapper = styled.div`\n  width: 100%;\n  height: 100%;\n  background: #000;\n  margin: 0 auto;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  overflow: hidden;\n`;\n\nexport const Photo = styled.img`\n  display: block;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  border-radius: 5px;\n`;\n\nexport const Video = styled.video.attrs({\n  autoPlay: true,\n  disablePictureInPicture: true,\n})`\n  display: block;\n  position: absolute;\n  z-index: 1;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  border-radius: 5px;\n  ${({ $isProcessing }) => $isProcessing && 'filter: blur(5px)'};\n`;\n\nexport const Canvas = styled.canvas`\n  display: block;\n  position: absolute;\n  z-index: 2;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  border-radius: 5px;\n  ${({ $isProcessing }) => $isProcessing && 'filter: blur(5px)'};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const MAX_RECORDING_DURATION_IN_SECONDS = 120;\nexport const MAX_RECORDING_DURATION_IN_MINUTES = 2;\nexport const COUNTDOWN_TIME_IN_SECONDS = 3;\n\nexport const BACKGROUND_BLUR_PX = 3;\n\nexport const VIDEO_MIME_TYPE = 'video/mp4';\nexport const VIDEO_FILE_TYPE = 'mp4';\n\nexport const AUDIO_MIME_TYPE = 'audio/mpeg';\nexport const AUDIO_FILE_TYPE = 'mp3';\n\nexport const PHOTO_MIME_TYPE = 'image/jpeg';\nexport const PHOTO_FILE_TYPE = 'jpeg';\n\nexport const SETTINGS_POPUP_ZINDEX = 11;\n\nexport const VIDEO_EFFECTS = { NONE: 'none', BLUR: 'blur' };\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nconst MediaRecordingContext = createContext({ state: {}, actions: {} });\n\nexport default MediaRecordingContext;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/countdown.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useMediaRecording from './useMediaRecording';\n\nconst Number = styled(Text.Paragraph).attrs({ as: 'div' })`\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  right: 0;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 70px;\n  font-weight: bold;\n  color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nfunction Countdown() {\n  const { countdown } = useMediaRecording(({ state }) => ({\n    countdown: state.countdown,\n  }));\n\n  if (countdown > 0) {\n    return <Number>{countdown}</Number>;\n  }\n\n  return null;\n}\n\nexport default Countdown;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/durationIndicator.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text, TextSize, Placement } from '@googleforcreators/design-system';\nimport { _n, sprintf } from '@googleforcreators/i18n';\nimport { getVideoLengthDisplay } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../tooltip';\nimport useMediaRecording from './useMediaRecording';\nimport { MAX_RECORDING_DURATION_IN_MINUTES } from './constants';\n\nconst Wrapper = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  font-variant-numeric: tabular-nums;\n\n  &:before {\n    content: '';\n    display: inline-block;\n    width: 10px;\n    height: 10px;\n    margin-right: 5px;\n    border-radius: 100%;\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.negativeNormal};\n  }\n`;\n\nfunction DurationIndicator() {\n  const { duration, isRecording } = useMediaRecording(({ state }) => ({\n    duration: state.duration,\n    isRecording: ['recording', 'paused'].includes(state.status),\n  }));\n\n  if (!isRecording) {\n    return null;\n  }\n\n  return (\n    <Tooltip\n      position={Placement.Top}\n      title={sprintf(\n        /* translators: %d: number of minutes */\n        _n(\n          'Maximum duration is %d minute',\n          'Maximum duration is %d minutes',\n          MAX_RECORDING_DURATION_IN_MINUTES,\n          'web-stories'\n        ),\n        String(MAX_RECORDING_DURATION_IN_MINUTES)\n      )}\n      styleOverride={{ maxWidth: '20em' }}\n    >\n      <Wrapper>{getVideoLengthDisplay(duration)}</Wrapper>\n    </Tooltip>\n  );\n}\n\nexport default DurationIndicator;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/errorDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { ThemeProvider } from 'styled-components';\nimport {\n  Icons,\n  lightMode,\n  theme as dsTheme,\n} from '@googleforcreators/design-system';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport {\n  MessageWrap,\n  MessageText,\n  MessageHeading,\n  Wrapper,\n} from './components';\nimport useMediaRecording from './useMediaRecording';\n\nconst StyledHeading = styled(MessageHeading)`\n  display: flex;\n  align-items: center;\n`;\n\nfunction ErrorMessage({ error, hasVideo }) {\n  let errorMessage = error?.message;\n\n  // Use some more human-readable error messages for most common scenarios.\n  // See https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#exceptions\n  if (!window.isSecureContext) {\n    errorMessage = __(\n      'Requires a secure browsing context (HTTPS)',\n      'web-stories'\n    );\n  } else if (error?.name === 'NotAllowedError') {\n    errorMessage = __('Permission denied', 'web-stories');\n  } else if (\n    !hasVideo ||\n    error?.name === 'NotFoundError' ||\n    error?.name === 'OverConstrainedError'\n  ) {\n    errorMessage = __('No camera found', 'web-stories');\n  }\n\n  return (\n    <MessageWrap>\n      <ThemeProvider theme={{ ...dsTheme, colors: lightMode }}>\n        <StyledHeading>\n          <Icons.ExclamationTriangle size={32} height={32} aria-hidden />\n          {__('Error', 'web-stories')}\n        </StyledHeading>\n        <MessageText>\n          {__('Could not initialize recording.', 'web-stories')}\n        </MessageText>\n        {errorMessage && (\n          <MessageText>\n            {sprintf(\n              /* translators: %s: error message. */\n              __('Reason: %s', 'web-stories'),\n              errorMessage\n            )}\n          </MessageText>\n        )}\n      </ThemeProvider>\n    </MessageWrap>\n  );\n}\n\nErrorMessage.propTypes = {\n  error: PropTypes.shape({\n    name: PropTypes.string,\n    message: PropTypes.string,\n  }),\n  hasVideo: PropTypes.bool.isRequired,\n};\n\nfunction ErrorDialog() {\n  const { error, hasVideo } = useMediaRecording(({ state }) => ({\n    error: state.error,\n    hasVideo: Boolean(state.videoInput),\n  }));\n  return (\n    <Wrapper>\n      <ErrorMessage error={error} hasVideo={hasVideo} />\n    </Wrapper>\n  );\n}\n\nexport default ErrorDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/footer.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  Icons,\n  useLiveRegion,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport {\n  useCallback,\n  useDebouncedCallback,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport { trackEvent, trackError } from '@googleforcreators/tracking';\nimport {\n  getVideoLength,\n  getVideoLengthDisplay,\n  blobToFile,\n  createBlob,\n  getImageFromVideo,\n  getCanvasBlob,\n  BackgroundAudioPropTypeShape,\n} from '@googleforcreators/media';\nimport { format } from '@googleforcreators/date';\n\n/**\n * Internal dependencies\n */\nimport useVideoTrim from '../videoTrim/useVideoTrim';\nimport getResourceFromLocalFile from '../../app/media/utils/getResourceFromLocalFile';\nimport useUploadWithPreview from '../canvas/useUploadWithPreview';\nimport { useUploader } from '../../app/uploader';\nimport { useConfig, useStory } from '../../app';\nimport { states, useHighlights } from '../../app/highlights';\nimport useFFmpeg from '../../app/media/utils/useFFmpeg';\nimport objectPick from '../../utils/objectPick';\nimport useMediaRecording from './useMediaRecording';\nimport {\n  COUNTDOWN_TIME_IN_SECONDS,\n  PHOTO_MIME_TYPE,\n  PHOTO_FILE_TYPE,\n  VIDEO_EFFECTS,\n} from './constants';\n\nconst BaseButton = styled(Button).attrs({\n  type: ButtonType.Primary,\n  size: ButtonSize.Small,\n})``;\n\nconst RecordingButton = styled(BaseButton)`\n  margin-right: 20px;\n  padding-top: 12px;\n  padding-bottom: 12px;\n\n  svg {\n    margin: -9px 10px -9px 0;\n  }\n`;\n\nconst PauseButton = styled(BaseButton).attrs({\n  type: ButtonType.Secondary,\n})`\n  margin-right: 20px;\n  padding-top: 12px;\n  padding-bottom: 12px;\n`;\n\nconst StopButton = styled(BaseButton)`\n  padding-top: 12px;\n  padding-bottom: 12px;\n\n  background-color: ${({ theme }) => theme.colors.interactiveBg.negativeNormal};\n  border-color: ${({ theme }) => theme.colors.interactiveBg.negativeNormal};\n  color: ${({ theme }) => theme.colors.gray[5]};\n\n  &:active,\n  &:hover,\n  &:focus {\n    background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.negativeHover};\n    border-color: ${({ theme }) => theme.colors.interactiveBg.negativeHover};\n  }\n`;\n\nconst CaptureButton = styled(BaseButton).attrs({\n  type: ButtonType.Quaternary,\n})`\n  background-color: ${({ theme }) => theme.colors.opacity.overlayDark};\n  padding-top: 12px;\n  padding-bottom: 12px;\n\n  svg {\n    margin: -9px 10px -9px 0;\n  }\n`;\n\nconst InsertButton = styled(Button).attrs({\n  type: ButtonType.Primary,\n  size: ButtonSize.Small,\n})``;\n\nconst RetryButton = styled(Button).attrs({\n  type: ButtonType.Plain,\n  size: ButtonSize.Small,\n})`\n  margin-right: 20px;\n`;\n\nfunction Footer() {\n  const {\n    status,\n    file,\n    isGif,\n    isMuted,\n    hasMediaToInsert,\n    countdown,\n    duration,\n    isCountingDown,\n    setMediaBlobUrl,\n    setDuration,\n    setCountdown,\n    startRecording,\n    stopRecording,\n    setFile,\n    toggleRecordingMode,\n    getMediaStream,\n    resetState,\n    resetStream,\n    streamNode,\n    canvasStream,\n    liveStream,\n    hasVideo,\n    videoEffect,\n    pauseRecording,\n    resumeRecording,\n    isProcessingTrim,\n    cancelTrim,\n    canvasNode,\n  } = useMediaRecording(({ state, actions }) => ({\n    status: state.status,\n    file: state.file,\n    isGif: state.isGif,\n    isMuted: !state.hasAudio || state.isGif,\n    countdown: state.countdown,\n    duration: state.duration,\n    isCountingDown: state.isCountingDown,\n    hasVideo: state.hasVideo,\n    videoEffect: state.videoEffect,\n    hasMediaToInsert: Boolean(state.mediaBlobUrl),\n    liveStream: state.liveStream,\n    streamNode: state.streamNode,\n    canvasStream: state.canvasStream,\n    isProcessingTrim: state.isProcessingTrim,\n    startRecording: actions.startRecording,\n    stopRecording: actions.stopRecording,\n    setFile: actions.setFile,\n    setMediaBlobUrl: actions.setMediaBlobUrl,\n    setDuration: actions.setDuration,\n    setCountdown: actions.setCountdown,\n    toggleRecordingMode: actions.toggleRecordingMode,\n    getMediaStream: actions.getMediaStream,\n    resetState: actions.resetState,\n    resetStream: actions.resetStream,\n    pauseRecording: actions.pauseRecording,\n    resumeRecording: actions.resumeRecording,\n    cancelTrim: actions.cancelTrim,\n    canvasNode: state.canvasNode,\n  }));\n  const videoNode = useVideoTrim(({ state: { videoNode } }) => videoNode);\n\n  const uploadWithPreview = useUploadWithPreview();\n\n  const speak = useLiveRegion();\n\n  const {\n    allowedMimeTypes: { audio: allowedAudioMimeTypes },\n  } = useConfig();\n\n  const onPause = useCallback(() => {\n    pauseRecording();\n    trackEvent('media_recording_pause');\n  }, [pauseRecording]);\n\n  const onResume = useCallback(() => {\n    resumeRecording();\n    trackEvent('media_recording_resume');\n  }, [resumeRecording]);\n\n  const onRetry = useCallback(async () => {\n    resetState();\n    await getMediaStream();\n\n    trackEvent('media_recording_retry');\n  }, [getMediaStream, resetState]);\n\n  const debouncedStartRecording = useDebouncedCallback(\n    startRecording,\n    COUNTDOWN_TIME_IN_SECONDS * 1000\n  );\n\n  const onStart = useCallback(() => {\n    speak(\n      sprintf(\n        /* translators: %d: countdown time in seconds. */\n        _n(\n          'Starting recording in %d second',\n          'Starting recording in %d seconds',\n          COUNTDOWN_TIME_IN_SECONDS,\n          'web-stories'\n        ),\n        COUNTDOWN_TIME_IN_SECONDS\n      )\n    );\n\n    setDuration(0);\n    setCountdown(COUNTDOWN_TIME_IN_SECONDS);\n    debouncedStartRecording();\n  }, [debouncedStartRecording, setCountdown, setDuration, speak]);\n\n  const [isInserting, setIsInserting] = useState(false);\n\n  const isRecording = ['recording', 'stopping', 'stopped', 'paused'].includes(\n    status\n  );\n  const isPaused = status === 'paused';\n\n  const onInsert = useCallback(async () => {\n    setIsInserting(true);\n    speak(__('Inserting…', 'web-stories'));\n\n    const args = {\n      additionalData: {\n        mediaSource: 'recording',\n        // Used for uploading via uploadFile().\n        altText: __('Camera Capture', 'web-stories'),\n      },\n    };\n    const { resource, posterFile } = await getResourceFromLocalFile(file);\n\n    args.resource = {\n      ...resource,\n      // Used for displaying the recorded file on canvas in the meantime.\n      alt: __('Camera Capture', 'web-stories'),\n    };\n\n    if (file.type.startsWith('video')) {\n      args.additionalData.isMuted = isMuted;\n      args.additionalData.isGif = isGif;\n\n      args.resource.length = duration;\n      args.resource.lengthFormatted = getVideoLengthDisplay(duration);\n\n      args.resource.isOptimized = true;\n      args.resource.isMuted = isMuted;\n      args.posterFile = posterFile;\n\n      const { length, lengthFormatted } = getVideoLength(videoNode);\n      args.resource.length = length || duration;\n      args.resource.lengthFormatted = length\n        ? lengthFormatted\n        : getVideoLengthDisplay(duration);\n    }\n\n    uploadWithPreview([file], true, args);\n\n    // handling cleanup for Image capture\n    // in this case we don't want onStop to override the file\n    if (isRecording) {\n      setMediaBlobUrl(null);\n      setFile(null);\n    }\n\n    trackEvent('media_recording_capture', {\n      type: isGif ? 'gif' : 'video',\n      muted: isMuted,\n      duration,\n    });\n\n    setIsInserting(false);\n\n    toggleRecordingMode();\n  }, [\n    speak,\n    file,\n    uploadWithPreview,\n    isRecording,\n    isGif,\n    isMuted,\n    duration,\n    toggleRecordingMode,\n    videoNode,\n    setMediaBlobUrl,\n    setFile,\n  ]);\n\n  useEffect(() => {\n    // Checking for srcObject avoids flickering due to the stream changing constantly.\n    if (streamNode && !streamNode.srcObject && liveStream) {\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      streamNode.srcObject = liveStream;\n    }\n\n    if (streamNode && !liveStream) {\n      streamNode.srcObject = null;\n    }\n  }, [streamNode, liveStream]);\n\n  const { showSnackbar } = useSnackbar();\n\n  const captureImage = useCallback(async () => {\n    const hasVideoEffect = videoEffect && videoEffect !== VIDEO_EFFECTS.NONE;\n    const inputStream = hasVideoEffect ? canvasStream : streamNode;\n    if (!inputStream) {\n      return;\n    }\n\n    let blob;\n\n    try {\n      if (hasVideoEffect) {\n        blob = await getCanvasBlob(canvasNode);\n      } else {\n        blob = await getImageFromVideo(inputStream);\n      }\n      setMediaBlobUrl(createBlob(blob));\n    } catch (e) {\n      trackError('media_recording_capture', e.message);\n\n      showSnackbar({\n        message: __(\n          'There was an error taking a photo. Please try again.',\n          'web-stories'\n        ),\n        dismissable: true,\n      });\n    }\n\n    const imageFile = blobToFile(\n      blob,\n      `image-capture-${format(new Date(), 'Y-m-d-H-i')}.${PHOTO_FILE_TYPE}`,\n      PHOTO_MIME_TYPE\n    );\n    setFile(imageFile);\n    resetStream();\n  }, [\n    resetStream,\n    setFile,\n    setMediaBlobUrl,\n    showSnackbar,\n    streamNode,\n    canvasStream,\n    videoEffect,\n    canvasNode,\n  ]);\n\n  const debouncedCaptureImage = useDebouncedCallback(\n    captureImage,\n    COUNTDOWN_TIME_IN_SECONDS * 1000\n  );\n  const onCapture = useCallback(() => {\n    speak(\n      sprintf(\n        /* translators: %d: countdown time in seconds. */\n        _n(\n          'Taking photo in %d second',\n          'Taking photo in %d seconds',\n          COUNTDOWN_TIME_IN_SECONDS,\n          'web-stories'\n        ),\n        COUNTDOWN_TIME_IN_SECONDS\n      )\n    );\n\n    setCountdown(COUNTDOWN_TIME_IN_SECONDS);\n    debouncedCaptureImage();\n\n    trackEvent('media_recording_capture', { type: 'image' });\n  }, [debouncedCaptureImage, setCountdown, speak]);\n  const {\n    actions: { uploadFile },\n  } = useUploader();\n\n  const {\n    updateCurrentPageProperties,\n    backgroundElementId,\n    setSelectedElementsById,\n  } = useStory(\n    ({\n      state: { currentPage },\n      actions: { updateCurrentPageProperties, setSelectedElementsById },\n    }) => ({\n      backgroundElementId: currentPage?.elements.find(\n        ({ isBackground }) => isBackground\n      )?.id,\n      updateCurrentPageProperties,\n      setSelectedElementsById,\n      currentPage,\n    })\n  );\n  const { setHighlights } = useHighlights(({ setHighlights }) => ({\n    setHighlights,\n  }));\n\n  const { convertToMp3 } = useFFmpeg();\n\n  const onAudioInsert = async () => {\n    setIsInserting(true);\n    speak(__('Inserting…', 'web-stories'));\n\n    const mp3File = await convertToMp3(file);\n    const resource = await uploadFile(\n      mp3File,\n      {\n        mediaSource: 'recording',\n      },\n      allowedAudioMimeTypes\n    );\n    const backgroundAudio = {\n      resource: objectPick(resource, Object.keys(BackgroundAudioPropTypeShape)),\n    };\n\n    setSelectedElementsById({ elementIds: [backgroundElementId] });\n    setHighlights({\n      highlight: states.PageBackgroundAudio,\n    });\n\n    updateCurrentPageProperties({\n      properties: {\n        backgroundAudio,\n      },\n    });\n    setIsInserting(false);\n    toggleRecordingMode();\n  };\n\n  if ('acquiring_media' === status) {\n    return null;\n  }\n\n  if (isProcessingTrim) {\n    return (\n      <RetryButton onClick={cancelTrim}>\n        {__('Cancel trimming', 'web-stories')}\n      </RetryButton>\n    );\n  }\n\n  if (hasMediaToInsert) {\n    return (\n      <>\n        <RetryButton onClick={onRetry} disabled={isInserting}>\n          {__('Retry', 'web-stories')}\n        </RetryButton>\n        <InsertButton\n          onClick={hasVideo ? onInsert : onAudioInsert}\n          disabled={isInserting}\n        >\n          {isInserting\n            ? __('Inserting…', 'web-stories')\n            : hasVideo\n              ? __('Insert', 'web-stories')\n              : __('Insert page background audio', 'web-stories')}\n        </InsertButton>\n      </>\n    );\n  }\n\n  if (countdown === 0) {\n    return (\n      <>\n        {isRecording && (\n          <>\n            <PauseButton\n              onClick={isPaused ? onResume : onPause}\n              aria-label={\n                isPaused\n                  ? __('Resume Recording', 'web-stories')\n                  : __('Pause Recording', 'web-stories')\n              }\n            >\n              {isPaused\n                ? __('Resume', 'web-stories')\n                : __('Pause', 'web-stories')}\n            </PauseButton>\n            <StopButton\n              onClick={stopRecording}\n              aria-label={__('Stop Recording', 'web-stories')}\n            >\n              {__('Stop', 'web-stories')}\n            </StopButton>\n          </>\n        )}\n        {!isRecording &&\n          !isCountingDown &&\n          (hasVideo ? (\n            <>\n              <RecordingButton onClick={onStart}>\n                <Icons.Camera width={24} height={24} aria-hidden />\n                {__('Record Video', 'web-stories')}\n              </RecordingButton>\n              <CaptureButton onClick={onCapture}>\n                <Icons.PhotoCamera width={24} height={24} aria-hidden />\n                {__('Take a photo', 'web-stories')}\n              </CaptureButton>\n            </>\n          ) : (\n            <RecordingButton onClick={onStart}>\n              <Icons.Mic width={24} height={24} aria-hidden />\n              {__('Record Audio', 'web-stories')}\n            </RecordingButton>\n          ))}\n      </>\n    );\n  }\n\n  return null;\n}\n\nexport default Footer;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as useMediaRecording } from './useMediaRecording';\nexport { default as MediaRecording } from './mediaRecording';\nexport { default as MediaRecordingProvider } from './provider';\nexport { default as SettingsModal } from './settingsModal';\nexport { default as ErrorDialog } from './errorDialog';\nexport { default as PermissionsDialog } from './permissionsDialog';\nexport { default as Footer } from './footer';\nexport { default as DurationIndicator } from './durationIndicator';\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/karma/mediaRecording.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { preloadVideo } from '@googleforcreators/media';\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { COUNTDOWN_TIME_IN_SECONDS } from '../constants';\n\nconst mediaDevices = [\n  {\n    kind: 'videoinput',\n    deviceId: 'video-a',\n    label: 'Video Device A',\n  },\n  {\n    kind: 'videoinput',\n    deviceId: 'video-b',\n    label: 'Video Device B',\n  },\n  {\n    kind: 'videoinput',\n    deviceId: 'video-c',\n    label: 'Video Device C',\n  },\n  {\n    kind: 'audioinput',\n    deviceId: 'audio-a',\n    label: 'Audio Device A',\n  },\n  {\n    kind: 'audioinput',\n    deviceId: 'audio-b',\n    label: 'Audio Device B',\n  },\n  {\n    kind: 'audioinput',\n    deviceId: 'audio-c',\n    label: 'Audio Device C',\n  },\n];\n\ndescribe('Media Recording', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    const video = await preloadVideo(\n      'http://localhost:9876/__static__/beach.webm'\n    );\n    video.loop = true;\n    try {\n      await video.play();\n    } catch {\n      // Do nothing.\n    }\n    const videoStream = video.captureStream();\n    spyOn(navigator.mediaDevices, 'getUserMedia').and.resolveTo(videoStream);\n    spyOn(navigator.mediaDevices, 'enumerateDevices').and.resolveTo(\n      mediaDevices\n    );\n\n    spyOnProperty(window, 'crossOriginIsolated', 'get').and.returnValue(true);\n\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('Creator can self-record video using their webcam', () => {\n    it('should toggle media recording layer via library and quick actions', async () => {\n      // Open media recording.\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n\n      // Close it again.\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n\n      await expect(\n        fixture.screen.queryByRole('region', {\n          name: /^Media Recording layer$/i,\n        })\n      ).toBeNull();\n\n      // Open it again.\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n\n      // Now close it via quick actions.\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.closeButton\n      );\n\n      await expect(\n        fixture.screen.queryByRole('region', {\n          name: /^Media Recording layer$/i,\n        })\n      ).toBeNull();\n    });\n\n    it('should error when trying to record a video', async () => {\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n      await waitFor(() => {\n        expect(fixture.editor.canvas.mediaRecordingLayer).not.toBeNull();\n      });\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.takePhoto\n      ).not.toBeNull();\n\n      await fixture.snapshot();\n\n      await fixture.events.click(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      );\n\n      expect(\n        fixture.editor.canvas.quickActionMenu.optionsButton.disabled\n      ).toBeTrue();\n\n      await fixture.events.sleep((COUNTDOWN_TIME_IN_SECONDS + 1) * 1000);\n\n      const errorMessage = fixture.screen.queryByText(\n        'Could not initialize recording.'\n      );\n      expect(errorMessage).toBeTruthy();\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- MediaRecorder does not seem to work in tests.\n    xit('should record a video', async () => {\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n      await waitFor(() => {\n        expect(fixture.editor.canvas.mediaRecordingLayer).not.toBeNull();\n      });\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.takePhoto\n      ).not.toBeNull();\n\n      await fixture.snapshot();\n\n      await fixture.events.click(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      );\n\n      expect(\n        fixture.editor.canvas.quickActionMenu.optionsButton.disabled\n      ).toBeTrue();\n\n      await fixture.events.sleep((COUNTDOWN_TIME_IN_SECONDS + 1) * 1000);\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.stopRecording\n      ).not.toBeNull();\n\n      await fixture.events.click(\n        fixture.editor.canvas.mediaRecordingLayer.stopRecording\n      );\n\n      expect(fixture.editor.canvas.mediaRecordingLayer.retry).not.toBeNull();\n      expect(fixture.editor.canvas.mediaRecordingLayer.insert).not.toBeNull();\n\n      await fixture.events.click(\n        fixture.editor.canvas.mediaRecordingLayer.retry\n      );\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.takePhoto\n      ).not.toBeNull();\n    });\n\n    it('should take a photo', async () => {\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n      await waitFor(() => {\n        expect(fixture.editor.canvas.mediaRecordingLayer).not.toBeNull();\n      });\n\n      await fixture.events.click(\n        fixture.editor.canvas.mediaRecordingLayer.takePhoto\n      );\n\n      await fixture.events.sleep((COUNTDOWN_TIME_IN_SECONDS + 1) * 1000);\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.previewImage\n      ).not.toBeNull();\n    });\n  });\n\n  describe('Creator can self-record audio using their webcam or microphone', () => {\n    it('should change media recording type to audio via disable video button', async () => {\n      // Open media recording.\n      await fixture.events.click(fixture.editor.library.media.mediaRecording);\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordVideo\n      ).not.toBeNull();\n\n      // Disable video.\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.disableVideoButton\n      );\n\n      expect(\n        fixture.editor.canvas.mediaRecordingLayer.recordAudio\n      ).not.toBeNull();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/mediaRecording.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport useMediaRecording from './useMediaRecording';\nimport Countdown from './countdown';\nimport ProgressBar from './progressBar';\nimport PlaybackMedia from './playbackMedia';\nimport ErrorDialog from './errorDialog';\nimport PermissionsDialog from './permissionsDialog';\nimport ProcessingOverlay from './processingOverlay';\nimport { Wrapper } from './components';\n\nfunction MediaRecording() {\n  const { status, error, needsPermissions, isProcessingTrim } =\n    useMediaRecording(({ state }) => ({\n      status: state.status,\n      error: state.error,\n      needsPermissions:\n        ('idle' === state.status || 'acquiring_media' === state.status) &&\n        !state.videoInput,\n      isProcessingTrim: state.isProcessingTrim,\n    }));\n\n  const isFailed = 'failed' === status || Boolean(error);\n\n  if (isFailed) {\n    return <ErrorDialog />;\n  }\n\n  if (needsPermissions) {\n    return <PermissionsDialog />;\n  }\n\n  return (\n    <>\n      <Wrapper>\n        <PlaybackMedia />\n        {isProcessingTrim && <ProcessingOverlay />}\n      </Wrapper>\n      <ProgressBar />\n      <Countdown />\n    </>\n  );\n}\n\nexport default MediaRecording;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/permissionsDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ThemeProvider } from 'styled-components';\nimport { lightMode, theme as dsTheme } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport {\n  Wrapper,\n  MessageWrap,\n  MessageText,\n  MessageHeading,\n} from './components';\n\nfunction PermissionsDialog() {\n  return (\n    <Wrapper>\n      <MessageWrap>\n        <ThemeProvider theme={{ ...dsTheme, colors: lightMode }}>\n          <MessageHeading>\n            {__('Media Recording', 'web-stories')}\n          </MessageHeading>\n\n          <MessageText>\n            {__(\n              'To get started, you need to allow access to your camera and microphone.',\n              'web-stories'\n            )}\n          </MessageText>\n        </ThemeProvider>\n      </MessageWrap>\n    </Wrapper>\n  );\n}\n\nexport default PermissionsDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/playPauseButton.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { rgba } from 'polished';\nimport styled, { css } from 'styled-components';\nimport { useEffect, useState, useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons, useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app/config';\nimport { noop } from '../../utils/noop';\n\nconst PLAY_BUTTON_SIZE = 82;\nconst ICON_SVG_SIZE = 72;\n\nconst Controls = styled.div`\n  position: absolute;\n  z-index: 2;\n`;\n\nconst ButtonWrapper = styled.button.attrs({ tabIndex: -1 })`\n  cursor: pointer;\n  pointer-events: initial;\n  width: ${PLAY_BUTTON_SIZE}px;\n  height: ${PLAY_BUTTON_SIZE}px;\n  overflow: hidden;\n  background: transparent;\n  border: none;\n  padding: 0;\n`;\n\nconst iconCss = css`\n  width: ${ICON_SVG_SIZE}px;\n  height: ${ICON_SVG_SIZE}px;\n  color: ${({ theme }) => theme.colors.standard.white};\n  filter: drop-shadow(\n    0px 0px 10px ${({ theme }) => rgba(theme.colors.bg.primary, 0.4)}\n  );\n`;\n\nconst Play = styled(Icons.PlayFilled)`\n  ${iconCss};\n`;\n\nconst Pause = styled(Icons.StopFilled)`\n  ${iconCss};\n`;\n\nfunction PlayPauseButton({ videoRef }) {\n  const { isRTL } = useConfig();\n\n  const [showControls, setShowControls] = useState(true);\n  const [isPlaying, setIsPlaying] = useState(true);\n\n  useEffect(() => {\n    const videoNode = videoRef?.current;\n\n    const onVideoEnd = () => {\n      if (videoNode) {\n        videoNode.currentTime = 0;\n      }\n      setIsPlaying(false);\n    };\n\n    videoNode?.addEventListener('ended', onVideoEnd);\n    return () => videoNode?.removeEventListener('ended', onVideoEnd);\n  }, [videoRef]);\n\n  useEffect(() => {\n    const videoNode = videoRef?.current;\n\n    if (!videoNode) {\n      return undefined;\n    }\n\n    const onVideoPlay = () => setIsPlaying(true);\n    const onVideoPause = () => setIsPlaying(false);\n    const onTimeUpdate = ({ target: { paused } }) => setIsPlaying(!paused);\n\n    videoNode.addEventListener('play', onVideoPlay);\n    videoNode.addEventListener('pause', onVideoPause);\n    videoNode.addEventListener('timeupdate', onTimeUpdate);\n    return () => {\n      videoNode.removeEventListener('play', onVideoPlay);\n      videoNode.removeEventListener('pause', onVideoPause);\n      videoNode.removeEventListener('timeupdate', onTimeUpdate);\n    };\n  }, [videoRef]);\n\n  const handlePlayPause = (evt) => {\n    evt.stopPropagation();\n\n    const videoNode = videoRef?.current;\n\n    if (!videoNode) {\n      return;\n    }\n\n    if (isPlaying) {\n      videoNode.pause();\n      setShowControls(true);\n    } else {\n      videoNode.play().catch(noop);\n    }\n  };\n\n  useKeyDownEffect(\n    videoRef,\n    {\n      key: ['space'],\n    },\n    handlePlayPause,\n    [handlePlayPause]\n  );\n\n  const nodeRef = useRef();\n\n  const buttonLabel = isPlaying\n    ? __('Click to pause', 'web-stories')\n    : __('Click to play', 'web-stories');\n\n  const Icon = isPlaying ? Pause : Play;\n  return (\n    <Controls>\n      {showControls && (\n        <ButtonWrapper\n          ref={nodeRef}\n          aria-label={buttonLabel}\n          aria-pressed={isPlaying}\n          key=\"wrapper\"\n          onClick={handlePlayPause}\n        >\n          <Icon $isRTL={isRTL} />\n        </ButtonWrapper>\n      )}\n    </Controls>\n  );\n}\n\nPlayPauseButton.propTypes = {\n  videoRef: PropTypes.object,\n};\n\nexport default PlayPauseButton;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/playbackMedia.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint-disable jsx-a11y/media-has-caption -- Not required for recording */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useRef, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useVideoTrim from '../videoTrim/useVideoTrim';\nimport { noop } from '../../utils/noop';\nimport useMediaRecording from './useMediaRecording';\nimport VideoMode from './videoMode';\nimport PlayPauseButton from './playPauseButton';\nimport { VideoWrapper, Video, Photo, Canvas } from './components';\nimport Audio from './audio';\nimport { BACKGROUND_BLUR_PX, VIDEO_EFFECTS } from './constants';\nimport blur from './blur';\n\nfunction PlaybackMedia() {\n  const {\n    mediaBlob,\n    mediaBlobUrl,\n    originalMediaBlobUrl,\n    liveStream,\n    hasVideo,\n    hasAudio,\n    videoEffect,\n    isGif,\n    isImageCapture,\n    isAdjustingTrim,\n    toggleIsGif,\n    streamNode,\n    setStreamNode,\n    isProcessingTrim,\n    setCanvasStream,\n    setCanvasNode,\n  } = useMediaRecording(({ state, actions }) => ({\n    mediaBlob: state.mediaBlob,\n    mediaBlobUrl: state.mediaBlobUrl,\n    originalMediaBlobUrl: state.originalMediaBlobUrl,\n    liveStream: state.liveStream,\n    hasVideo: state.hasVideo,\n    hasAudio: state.hasAudio,\n    videoEffect: state.videoEffect,\n    isGif: state.isGif,\n    streamNode: state.streamNode,\n    isImageCapture: Boolean(state.file?.type?.startsWith('image')),\n    isAdjustingTrim: state.isAdjustingTrim,\n    toggleIsGif: actions.toggleIsGif,\n    setStreamNode: actions.setStreamNode,\n    isProcessingTrim: state.isProcessingTrim,\n    setCanvasStream: actions.setCanvasStream,\n    setCanvasNode: actions.setCanvasNode,\n  }));\n  const setVideoNode = useVideoTrim(\n    ({ actions: { setVideoNode } }) => setVideoNode\n  );\n\n  const isMuted = !hasAudio || isGif;\n  const hasVideoEffect = videoEffect && videoEffect !== VIDEO_EFFECTS.NONE;\n\n  const onToggleVideoMode = useCallback(() => {\n    toggleIsGif();\n    if (videoRef.current) {\n      videoRef.current.play().catch(noop);\n    }\n  }, [toggleIsGif]);\n\n  const rafRef = useRef();\n  const canvasRef = useRef();\n  const videoRef = useRef();\n  const updateVideoNode = useCallback(\n    (node) => {\n      setVideoNode(node);\n      videoRef.current = node;\n    },\n    [setVideoNode]\n  );\n\n  const selfieSegmentation = useRef();\n\n  const onSelfieSegmentationResults = (results) => {\n    const canvas = canvasRef.current;\n    if (!canvas || !results.image || results.image.width === 0) {\n      return;\n    }\n    const context = canvasRef.current.getContext('2d');\n    const canvasBlur = 'filter' in CanvasRenderingContext2D.prototype;\n\n    context.save();\n\n    if (!canvasBlur) {\n      context.drawImage(results.image, 0, 0, canvas.width, canvas.height);\n\n      blur(context, BACKGROUND_BLUR_PX);\n\n      context.globalCompositeOperation = 'destination-out';\n      context.drawImage(\n        results.segmentationMask,\n        0,\n        0,\n        canvas.width,\n        canvas.height\n      );\n      context.globalCompositeOperation = 'destination-over';\n      context.drawImage(results.image, 0, 0, canvas.width, canvas.height);\n    } else {\n      context.globalCompositeOperation = 'copy';\n      context.filter = `blur(${BACKGROUND_BLUR_PX}px)`;\n      context.drawImage(\n        results.segmentationMask,\n        0,\n        0,\n        canvas.width,\n        canvas.height\n      );\n\n      context.globalCompositeOperation = 'source-in';\n      context.filter = 'none';\n      context.drawImage(results.image, 0, 0, canvas.width, canvas.height);\n\n      context.globalCompositeOperation = 'destination-over';\n      context.filter = `blur(${BACKGROUND_BLUR_PX}px)`;\n      context.drawImage(results.image, 0, 0, canvas.width, canvas.height);\n    }\n\n    context.restore();\n  };\n\n  useEffect(() => {\n    if (!hasVideoEffect || selfieSegmentation.current) {\n      return;\n    }\n\n    (async () => {\n      const { SelfieSegmentation } = await import(\n        /* webpackChunkName: \"chunk-selfie-segmentation\" */ '@mediapipe/selfie_segmentation'\n      );\n\n      selfieSegmentation.current = new SelfieSegmentation({\n        // TODO: Consider fetching from wp.stories.google instead.\n        locateFile: (file) =>\n          `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`,\n      });\n\n      selfieSegmentation.current.setOptions({\n        modelSelection: 1,\n      });\n\n      await selfieSegmentation.current.initialize();\n    })();\n  }, [hasVideoEffect]);\n\n  useEffect(() => {\n    async function run() {\n      if (hasVideoEffect && canvasRef.current) {\n        canvasRef.current.getContext('2d');\n        setCanvasNode(canvasRef.current);\n        const canvasStreamRaw = canvasRef.current.captureStream();\n        const liveStreamAudio = liveStream.getAudioTracks();\n        if (liveStreamAudio.length > 0) {\n          canvasStreamRaw.addTrack(liveStreamAudio[0]);\n        }\n        setCanvasStream(canvasStreamRaw);\n      }\n      if (videoEffect === VIDEO_EFFECTS.BLUR && selfieSegmentation.current) {\n        selfieSegmentation.current.onResults(onSelfieSegmentationResults);\n        const sendFrame = async () => {\n          if (streamNode && streamNode.videoWidth && canvasRef.current) {\n            try {\n              await selfieSegmentation.current.send({ image: streamNode });\n            } catch {\n              // We can't do much about the WASM memory issue.\n            }\n          }\n          if (canvasRef.current) {\n            rafRef.current = requestAnimationFrame(sendFrame);\n          }\n        };\n        if (streamNode && hasVideoEffect) {\n          await sendFrame();\n        }\n      }\n    }\n\n    run();\n\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- including liveStream will cause freeze\n  }, [videoEffect, hasVideoEffect, streamNode, setCanvasStream, setCanvasNode]);\n\n  // Only previewing a gif means that the play button is hidden,\n  // not while trimming (even if gif)\n  const hasPlayButton = (!isGif && !isProcessingTrim) || isAdjustingTrim;\n  const mediaSrc = isAdjustingTrim ? originalMediaBlobUrl : mediaBlobUrl;\n\n  const hasVideoModeSwitch =\n    mediaBlobUrl && hasVideo && !isAdjustingTrim && !isProcessingTrim;\n\n  useEffect(() => {\n    if (mediaBlobUrl) {\n      if (rafRef.current) {\n        cancelAnimationFrame(rafRef.current);\n      }\n    }\n    return () => {\n      if (rafRef.current) {\n        cancelAnimationFrame(rafRef.current);\n      }\n    };\n  }, [mediaBlobUrl]);\n\n  if (isImageCapture) {\n    return (\n      <VideoWrapper>\n        <Photo\n          decoding=\"async\"\n          src={mediaBlobUrl}\n          alt={__('Image capture', 'web-stories')}\n        />\n      </VideoWrapper>\n    );\n  }\n\n  const onLoadedMetadata = () => {\n    if (!canvasRef.current) {\n      return;\n    }\n    canvasRef.current.width = streamNode.videoWidth;\n    canvasRef.current.height = streamNode.videoHeight;\n  };\n\n  return (\n    <>\n      {hasVideoModeSwitch && (\n        <VideoMode value={!isGif} onChange={onToggleVideoMode} />\n      )}\n      <VideoWrapper>\n        {mediaBlobUrl &&\n          (hasVideo ? (\n            <>\n              <Video\n                ref={updateVideoNode}\n                src={mediaSrc}\n                muted={isMuted}\n                loop={isGif || isAdjustingTrim}\n                $isProcessing={isProcessingTrim}\n                tabIndex={0}\n              />\n              {hasPlayButton && <PlayPauseButton videoRef={videoRef} />}\n            </>\n          ) : (\n            <audio controls=\"controls\" src={mediaBlobUrl} />\n          ))}\n        {!mediaBlob &&\n          !mediaBlobUrl &&\n          liveStream &&\n          (hasVideo ? (\n            <>\n              <Video\n                ref={setStreamNode}\n                muted\n                onLoadedMetadata={onLoadedMetadata}\n              />\n              {hasVideoEffect && (\n                <Canvas ref={canvasRef} width={640} height={480} />\n              )}\n            </>\n          ) : (\n            <Audio liveStream={liveStream} />\n          ))}\n      </VideoWrapper>\n    </>\n  );\n}\n\nexport default PlaybackMedia;\n\n/* eslint-enable jsx-a11y/media-has-caption -- Reenabling */\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/processingOverlay.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Text,\n  LoadingSpinner,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport { useEffect } from '@googleforcreators/react';\n\nconst Wrapper = styled.div`\n  position: absolute;\n  left: 0;\n  top: 0;\n  height: 100%;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n  background-color: rgba(0 0 0 / 0.5);\n  gap: 2em;\n  padding: 3em;\n`;\n\nfunction ProcessingOverlay() {\n  const speak = useLiveRegion();\n  useEffect(() => {\n    speak(\n      __(\n        'Video trimming in progress. Please wait up to a few minutes depending on output video length.',\n        'web-stories'\n      )\n    );\n  }, [speak]);\n\n  return (\n    <Wrapper>\n      <LoadingSpinner />\n      <Text.Paragraph>\n        {__(\n          'Video trimming in progress. Please wait up to a few minutes depending on output video length.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Wrapper>\n  );\n}\n\nexport default ProcessingOverlay;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/progressBar.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\n\n/**\n * Internal dependencies\n */\nimport useMediaRecording from './useMediaRecording';\nimport { MAX_RECORDING_DURATION_IN_SECONDS } from './constants';\n\nconst ProgressIndicator = styled.progress`\n  appearance: none;\n  border: none;\n  width: 100%;\n  height: 8px;\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n\n  background-color: ${({ theme }) => rgba(theme.colors.fg.primary, 0.3)};\n  border-top-left-radius: 5px;\n  border-top-right-radius: 5px;\n\n  &::-webkit-progress-bar {\n    background-color: ${({ theme }) => rgba(theme.colors.fg.primary, 0.3)};\n    border-top-left-radius: 5px;\n    border-top-right-radius: 5px;\n  }\n\n  &::-webkit-progress-value {\n    background-color: ${({ theme }) => theme.colors.fg.primary};\n    border-top-left-radius: 5px;\n  }\n\n  &::-moz-progress-bar {\n    background-color: ${({ theme }) => theme.colors.fg.primary};\n    border-top-left-radius: 5px;\n  }\n`;\n\nfunction ProgressBar() {\n  const { duration, isRecording } = useMediaRecording(({ state }) => ({\n    duration: state.duration,\n    isRecording: ['recording', 'paused'].includes(state.status),\n  }));\n\n  if (!isRecording) {\n    return null;\n  }\n\n  return (\n    <ProgressIndicator\n      value={duration}\n      max={MAX_RECORDING_DURATION_IN_SECONDS}\n    />\n  );\n}\n\nexport default ProgressBar;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport useMediaRecorder from '@wmik/use-media-recorder';\nimport {\n  useState,\n  useMemo,\n  useCallback,\n  useEffect,\n  usePrevious,\n} from '@googleforcreators/react';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n  useLiveRegion,\n  useSnackbar,\n} from '@googleforcreators/design-system';\nimport { blobToFile, createBlob, revokeBlob } from '@googleforcreators/media';\nimport { format } from '@googleforcreators/date';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from './context';\nimport useTrim from './useTrim';\nimport {\n  MAX_RECORDING_DURATION_IN_SECONDS,\n  VIDEO_FILE_TYPE,\n  VIDEO_MIME_TYPE,\n  AUDIO_FILE_TYPE,\n  AUDIO_MIME_TYPE,\n} from './constants';\n\nfunction createFile(blob, hasVideo) {\n  const FILE_TYPE = hasVideo ? VIDEO_FILE_TYPE : AUDIO_FILE_TYPE;\n  const MIME_TYPE = hasVideo ? VIDEO_MIME_TYPE : AUDIO_MIME_TYPE;\n  const captureType = hasVideo ? 'webcam' : 'audio';\n  return blobToFile(\n    blob,\n    `${captureType}-capture-${format(new Date(), 'Y-m-d-H-i')}.${FILE_TYPE}`,\n    MIME_TYPE\n  );\n}\n\nfunction MediaRecordingProvider({ children }) {\n  const [isInRecordingMode, setIsInRecordingMode] = useState(false);\n  const [isSettingsOpen, setIsSettingsOpen] = useState(false);\n  const [isProcessing, setIsProcessing] = useState(false);\n\n  const [streamNode, setStreamNode] = useState(null);\n  const [canvasStream, setCanvasStream] = useState(null);\n  const [canvasNode, setCanvasNode] = useState(null);\n\n  const [countdown, setCountdown] = useState(0);\n  const [duration, setDuration] = useState(0);\n\n  const [isGif, setIsGif] = useState(false);\n\n  const [hasVideo, setHasVideo] = useState(true);\n  const [hasAudio, setHasAudio] = useState(true);\n  const [videoInput, setVideoInput] = useState(\n    localStore.getItemByKey(LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_VIDEO_INPUT)\n  );\n  const [audioInput, setAudioInput] = useState(\n    localStore.getItemByKey(LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_AUDIO_INPUT)\n  );\n  const [videoEffect, setVideoEffect] = useState(\n    localStore.getItemByKey(LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_VIDEO_EFFECT)\n  );\n\n  const [mediaDevices, setMediaDevices] = useState([]);\n\n  const [file, setFile] = useState(null);\n  const [originalFile, setOriginalFile] = useState(null);\n\n  useEffect(() => {\n    if (!mediaDevices.length) {\n      return;\n    }\n\n    // Video device not set yet, or was detached. Choose first available video device.\n    setVideoInput(\n      mediaDevices.find((device) => device.deviceId === videoInput)?.deviceId ||\n        mediaDevices.find((device) => device.kind === 'videoinput')?.deviceId\n    );\n\n    // Audio device not set yet, or was detached. Choose first available audio device.\n    setAudioInput(\n      mediaDevices.find((device) => device.deviceId === audioInput)?.deviceId ||\n        mediaDevices.find((device) => device.kind === 'audioinput')?.deviceId\n    );\n  }, [audioInput, mediaDevices, videoInput]);\n\n  const [mediaBlobUrl, setMediaBlobUrl] = useState();\n  const [originalMediaBlobUrl, setOriginalMediaBlobUrl] = useState();\n\n  const { showSnackbar } = useSnackbar();\n\n  const onStop = useCallback(\n    (blob) => {\n      try {\n        const recordedBlob = createBlob(blob);\n        setOriginalMediaBlobUrl(recordedBlob);\n        setMediaBlobUrl(recordedBlob);\n\n        const recordedFile = createFile(blob, hasVideo);\n        setOriginalFile(recordedFile);\n        setFile(recordedFile);\n      } catch (e) {\n        trackError('media_recording_capture', e.message);\n        showSnackbar({\n          message: __(\n            'There was an error recording a video. Please try again.',\n            'web-stories'\n          ),\n          dismissable: true,\n        });\n      }\n    },\n    [showSnackbar, hasVideo]\n  );\n\n  const mediaRecorder = useMediaRecorder({\n    recordScreen: false,\n    // If the device does not have a microphone or camera, this could result\n    // in an OverconstrainedError.\n    // However, this error can occur even when the user has not yet\n    // granted permission, so it's not easy to detect.\n    // TODO: Figure out how to retry without microphone if possible.\n    mediaStreamConstraints: {\n      audio: hasAudio ? (audioInput ? { deviceId: audioInput } : true) : false,\n      video: hasVideo ? (videoInput ? { deviceId: videoInput } : true) : false,\n    },\n    onStop,\n  });\n\n  const canvasRecorder = useMediaRecorder({\n    recordScreen: false,\n    customMediaStream: canvasStream,\n    onStop,\n  });\n\n  const currentRecorder =\n    videoEffect && videoEffect !== 'none' && hasVideo\n      ? {\n          ...mediaRecorder,\n          inputStatus: mediaRecorder.status,\n          status: canvasRecorder.status,\n          startRecording: canvasRecorder.startRecording,\n          pauseRecording: canvasRecorder.pauseRecording,\n          resumeRecording: canvasRecorder.resumeRecording,\n          stopRecording: canvasRecorder.stopRecording,\n          mediaBlob: canvasRecorder.mediaBlob,\n          clearMediaBlob: canvasRecorder.clearMediaBlob,\n          getMediaStream: async () => {\n            canvasRecorder.clearMediaStream();\n            await mediaRecorder.getMediaStream();\n          },\n        }\n      : {\n          ...mediaRecorder,\n          inputStatus: mediaRecorder.status,\n        };\n\n  const {\n    error,\n    inputStatus,\n    status,\n    mediaBlob,\n    stopRecording: originalStopRecording,\n    startRecording,\n    liveStream,\n    getMediaStream,\n    clearMediaStream,\n    clearMediaBlob,\n    muteAudio,\n    unMuteAudio,\n    pauseRecording,\n    resumeRecording,\n  } = currentRecorder;\n\n  const isRecording = 'recording' === status;\n\n  const onTrimmed = useCallback((trimmedFile) => {\n    setMediaBlobUrl(createBlob(trimmedFile));\n    setFile(trimmedFile);\n  }, []);\n\n  const {\n    trimData,\n    isAdjustingTrim,\n    isProcessingTrim,\n    startTrim,\n    onTrim,\n    resetTrim,\n    cancelTrim,\n  } = useTrim({ setDuration, onTrimmed, file: originalFile, isRecording });\n\n  useEffect(() => {\n    if (\n      error?.name === 'NotFoundError' ||\n      error?.name === 'NotReadableError' ||\n      error?.name === 'OverConstrainedError'\n    ) {\n      setHasVideo(false);\n      setVideoInput(null);\n    }\n  }, [error]);\n\n  const speak = useLiveRegion();\n\n  const stopRecording = useCallback(() => {\n    setIsProcessing(true);\n    originalStopRecording();\n    speak(__('Recording stopped', 'web-stories'));\n  }, [originalStopRecording, speak]);\n\n  const updateMediaDevices = useCallback(async () => {\n    // navigator.mediaDevices is undefined in insecure browsing contexts.\n    if (!navigator.mediaDevices) {\n      return;\n    }\n\n    try {\n      const devices = await navigator.mediaDevices.enumerateDevices();\n      setMediaDevices(\n        devices\n          .filter((device) => device.kind !== 'audiooutput')\n          // Label is empty if permissions somehow changed meantime,\n          // remove these devices from the list.\n          .filter((device) => device.label)\n      );\n    } catch {\n      // Do nothing for now.\n    }\n  }, []);\n\n  useEffect(() => {\n    // navigator.mediaDevices is undefined in insecure browsing contexts.\n    if (!navigator.mediaDevices) {\n      return undefined;\n    }\n\n    // Note: Safari will fire the devicechange event right after granting permissions,\n    // and then calling enumerateDevices() will trigger another permission prompt.\n    // TODO: Figure out a good way to work around that.\n    navigator.mediaDevices.addEventListener('devicechange', updateMediaDevices);\n\n    return () => {\n      navigator.mediaDevices.removeEventListener(\n        'devicechange',\n        updateMediaDevices\n      );\n    };\n  }, [updateMediaDevices]);\n\n  const toggleVideo = useCallback(() => {\n    setHasVideo(!hasVideo);\n  }, [hasVideo]);\n\n  const toggleAudio = useCallback(() => {\n    setHasAudio(!hasAudio);\n    if (hasAudio) {\n      muteAudio();\n    } else {\n      unMuteAudio();\n    }\n  }, [hasAudio, muteAudio, unMuteAudio]);\n\n  const previousBlobUrl = usePrevious(mediaBlobUrl);\n\n  useEffect(() => {\n    if (\n      previousBlobUrl &&\n      previousBlobUrl !== mediaBlobUrl &&\n      previousBlobUrl !== originalMediaBlobUrl\n    ) {\n      revokeBlob(previousBlobUrl);\n    }\n  }, [mediaBlobUrl, previousBlobUrl, originalMediaBlobUrl]);\n\n  useEffect(() => {\n    let timeout;\n\n    if (duration >= 0 && isRecording) {\n      timeout = setTimeout(() => setDuration((seconds) => seconds + 1), 1000);\n    }\n\n    return () => clearTimeout(timeout);\n  }, [duration, isRecording]);\n\n  useEffect(() => {\n    let timeout;\n\n    if (countdown > 0) {\n      timeout = setTimeout(() => setCountdown(countdown - 1), 1000);\n    }\n\n    return () => clearTimeout(timeout);\n  }, [countdown]);\n\n  useEffect(() => {\n    if (duration > MAX_RECORDING_DURATION_IN_SECONDS) {\n      stopRecording();\n    }\n  }, [duration, stopRecording]);\n\n  const resetStream = useCallback(() => {\n    // clearMediaStream() is supposed to do this, but it doesn't have an effect.\n    // Probably because liveStream is a new MediaStream instance.\n    // Anyway, this stops the camera/mic from being used.\n    if (liveStream) {\n      liveStream.getTracks().forEach((track) => track.stop());\n    }\n    if (canvasRecorder.liveStream) {\n      canvasRecorder.liveStream.getTracks().forEach((track) => track.stop());\n    }\n\n    clearMediaBlob();\n    clearMediaStream();\n\n    canvasRecorder.clearMediaStream();\n  }, [clearMediaBlob, clearMediaStream, liveStream, canvasRecorder]);\n\n  const resetState = useCallback(() => {\n    setFile(null);\n    setIsGif(false);\n    setMediaBlobUrl(null);\n    setCountdown(0);\n    setIsProcessing(false);\n    setDuration(0);\n    resetTrim();\n\n    resetStream();\n  }, [resetStream, resetTrim]);\n\n  const toggleRecordingMode = useCallback(() => {\n    setIsInRecordingMode((state) => !state);\n    if (canvasRecorder.status === 'recording') {\n      stopRecording();\n    } else {\n      resetState();\n      if (isInRecordingMode === true) {\n        canvasRecorder.clearMediaStream();\n      }\n    }\n  }, [resetState, canvasRecorder, isInRecordingMode, stopRecording]);\n\n  const toggleSettings = useCallback(\n    () => setIsSettingsOpen((state) => !state),\n    []\n  );\n\n  const toggleIsGif = useCallback(() => setIsGif((state) => !state), []);\n\n  const isCountingDown = countdown > 0;\n  const wasCountingDown = usePrevious(isCountingDown);\n\n  const value = useMemo(\n    () => ({\n      state: {\n        isInRecordingMode,\n        hasVideo,\n        hasAudio,\n        mediaDevices,\n        audioInput,\n        videoInput,\n        videoEffect,\n        isSettingsOpen,\n        error,\n        inputStatus,\n        status,\n        mediaBlob,\n        mediaBlobUrl,\n        originalMediaBlobUrl,\n        liveStream,\n        file,\n        isGif,\n        duration,\n        countdown,\n        isProcessing,\n        isCountingDown: isCountingDown || wasCountingDown,\n        trimData,\n        isAdjustingTrim,\n        streamNode,\n        isProcessingTrim,\n        canvasStream,\n        canvasNode,\n      },\n      actions: {\n        toggleRecordingMode,\n        setMediaBlobUrl,\n        toggleVideo,\n        toggleAudio,\n        toggleSettings,\n        toggleIsGif,\n        setAudioInput,\n        setVideoInput,\n        setVideoEffect,\n        updateMediaDevices,\n        stopRecording,\n        startRecording,\n        getMediaStream,\n        clearMediaStream,\n        clearMediaBlob,\n        setFile,\n        muteAudio,\n        unMuteAudio,\n        setDuration,\n        setCountdown,\n        resetState,\n        resetStream,\n        onTrim,\n        startTrim,\n        setStreamNode,\n        pauseRecording,\n        resumeRecording,\n        cancelTrim,\n        setCanvasStream,\n        setCanvasNode,\n      },\n    }),\n    [\n      isInRecordingMode,\n      hasVideo,\n      hasAudio,\n      mediaDevices,\n      audioInput,\n      videoInput,\n      videoEffect,\n      isSettingsOpen,\n      error,\n      inputStatus,\n      status,\n      mediaBlob,\n      mediaBlobUrl,\n      originalMediaBlobUrl,\n      liveStream,\n      file,\n      isGif,\n      duration,\n      countdown,\n      isCountingDown,\n      wasCountingDown,\n      isProcessing,\n      trimData,\n      isAdjustingTrim,\n      streamNode,\n      isProcessingTrim,\n      toggleRecordingMode,\n      toggleVideo,\n      toggleAudio,\n      toggleSettings,\n      toggleIsGif,\n      updateMediaDevices,\n      stopRecording,\n      startRecording,\n      getMediaStream,\n      clearMediaStream,\n      clearMediaBlob,\n      muteAudio,\n      unMuteAudio,\n      resetState,\n      resetStream,\n      onTrim,\n      startTrim,\n      setStreamNode,\n      pauseRecording,\n      resumeRecording,\n      cancelTrim,\n      canvasStream,\n      setCanvasStream,\n      canvasNode,\n      setCanvasNode,\n    ]\n  );\n\n  return (\n    <MediaRecordingContext.Provider value={value}>\n      {children}\n    </MediaRecordingContext.Provider>\n  );\n}\n\nMediaRecordingProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default MediaRecordingProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/settingsModal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Text,\n  DropDown,\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\nimport useMediaRecording from './useMediaRecording';\nimport { SETTINGS_POPUP_ZINDEX, VIDEO_EFFECTS } from './constants';\n\nconst Row = styled.div`\n  margin-bottom: 16px;\n`;\n\nconst Label = styled(Text.Paragraph).attrs({\n  as: 'label',\n  size: TextSize.Small,\n})`\n  display: inline-block;\n  margin-bottom: 8px;\n`;\n\nfunction SettingsModal() {\n  const {\n    mediaDevices,\n    hasAudio,\n    videoInput,\n    audioInput,\n    videoEffect,\n    isSettingsOpen,\n    setAudioInput,\n    setVideoInput,\n    setVideoEffect,\n    clearMediaStream,\n    clearMediaBlob,\n    toggleSettings,\n  } = useMediaRecording(({ state, actions }) => ({\n    mediaDevices: state.mediaDevices,\n    hasAudio: state.hasAudio,\n    videoInput: state.videoInput,\n    audioInput: state.audioInput,\n    videoEffect: state.videoEffect,\n    isSettingsOpen: state.isSettingsOpen,\n    setAudioInput: actions.setAudioInput,\n    setVideoInput: actions.setVideoInput,\n    setVideoEffect: actions.setVideoEffect,\n    clearMediaStream: actions.clearMediaStream,\n    clearMediaBlob: actions.clearMediaBlob,\n    toggleSettings: actions.toggleSettings,\n  }));\n\n  const [localVideoInput, setLocalVideoInput] = useState(videoInput);\n  const [localAudioInput, setLocalAudioInput] = useState(audioInput);\n  const [localVideoEffect, setLocalVideoEffect] = useState(videoEffect);\n\n  useEffect(() => setLocalVideoInput(videoInput), [videoInput]);\n  useEffect(() => setLocalAudioInput(audioInput), [audioInput]);\n\n  const onSaveChanges = useCallback(() => {\n    toggleSettings();\n\n    setVideoInput(localVideoInput);\n    localStore.setItemByKey(\n      LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_VIDEO_INPUT,\n      localVideoInput\n    );\n\n    setAudioInput(localAudioInput);\n    localStore.setItemByKey(\n      LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_AUDIO_INPUT,\n      localAudioInput\n    );\n\n    setVideoEffect(localVideoEffect);\n    localStore.setItemByKey(\n      LOCAL_STORAGE_PREFIX.MEDIA_RECORDING_VIDEO_EFFECT,\n      localVideoEffect\n    );\n\n    if (\n      videoInput !== localVideoInput ||\n      audioInput !== localAudioInput ||\n      videoEffect !== localVideoEffect\n    ) {\n      trackEvent('media_recording_settings_changed');\n      clearMediaStream();\n      clearMediaBlob();\n    }\n  }, [\n    audioInput,\n    clearMediaBlob,\n    clearMediaStream,\n    localAudioInput,\n    localVideoInput,\n    localVideoEffect,\n    setAudioInput,\n    setVideoInput,\n    setVideoEffect,\n    toggleSettings,\n    videoInput,\n    videoEffect,\n  ]);\n\n  const videoInputs = mediaDevices\n    .filter((device) => device.kind === 'videoinput')\n    .map(({ deviceId, label }) => ({ value: deviceId, label }));\n  const audioInputs = mediaDevices\n    .filter((device) => device.kind === 'audioinput')\n    .map(({ deviceId, label }) => ({ value: deviceId, label }));\n  const videoEffects = [\n    { value: VIDEO_EFFECTS.NONE, label: __('None', 'web-stories') },\n    { value: VIDEO_EFFECTS.BLUR, label: __('Background blur', 'web-stories') },\n  ];\n\n  const onChangeVideoInput = useCallback(\n    (_event, value) => setLocalVideoInput(value),\n    []\n  );\n\n  const onChangeAudioInput = useCallback(\n    (evt, value) => setLocalAudioInput(value),\n    []\n  );\n\n  const onChangeVideoEffect = useCallback(\n    (_event, value) => setLocalVideoEffect(value),\n    []\n  );\n\n  const onClose = useCallback(() => {\n    toggleSettings();\n    // Reset local state after closing dialog.\n    setLocalVideoInput(videoInput);\n    setLocalAudioInput(audioInput);\n  }, [audioInput, toggleSettings, videoInput]);\n\n  return (\n    <Dialog\n      onClose={onClose}\n      isOpen={isSettingsOpen}\n      contentLabel={__('Media Recording Options', 'web-stories')}\n      title={__('Options', 'web-stories')}\n      onPrimary={onSaveChanges}\n      primaryText={__('Save', 'web-stories')}\n      secondaryText={__('Cancel', 'web-stories')}\n    >\n      <Row>\n        <Text.Paragraph>\n          {__(\n            'Choose the camera and microphone to use for the recording.',\n            'web-stories'\n          )}\n        </Text.Paragraph>\n      </Row>\n\n      {videoInputs.length > 0 && (\n        <Row>\n          <Label htmlFor=\"camera\">{__('Camera', 'web-stories')}</Label>\n          <DropDown\n            id=\"camera\"\n            ariaLabel={__('Video Input', 'web-stories')}\n            placeholder={__('Select Video Input', 'web-stories')}\n            options={videoInputs}\n            onMenuItemClick={onChangeVideoInput}\n            selectedValue={localVideoInput}\n            popupZIndex={SETTINGS_POPUP_ZINDEX}\n          />\n        </Row>\n      )}\n      {audioInputs.length > 0 && (\n        <Row>\n          <Label htmlFor=\"microphone\">{__('Microphone', 'web-stories')}</Label>\n          <DropDown\n            id=\"microphone\"\n            ariaLabel={__('Audio Input', 'web-stories')}\n            placeholder={__('Select Audio Input', 'web-stories')}\n            options={audioInputs}\n            onMenuItemClick={onChangeAudioInput}\n            selectedValue={localAudioInput}\n            disabled={!hasAudio}\n            popupZIndex={SETTINGS_POPUP_ZINDEX}\n          />\n        </Row>\n      )}\n      {videoInputs.length > 0 && (\n        <Row>\n          <Label htmlFor=\"video-effect\">\n            {__('Video Effect', 'web-stories')}\n          </Label>\n          <DropDown\n            id=\"video-effect\"\n            ariaLabel={__('Video Effect', 'web-stories')}\n            placeholder={__('Select Video Effect', 'web-stories')}\n            options={videoEffects}\n            onMenuItemClick={onChangeVideoEffect}\n            selectedValue={localVideoEffect}\n            popupZIndex={SETTINGS_POPUP_ZINDEX}\n          />\n        </Row>\n      )}\n    </Dialog>\n  );\n}\n\nexport default SettingsModal;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/countdown.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from '../context';\nimport Countdown from '../countdown';\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/Countdown',\n  component: Countdown,\n  args: {\n    countdown: 7,\n  },\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <MediaRecordingContext.Provider value={{ state: { ...args } }}>\n        <Countdown />\n      </MediaRecordingContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/durationIndicator.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from '../context';\nimport DurationIndicator from '../durationIndicator';\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/DurationIndicator',\n  component: DurationIndicator,\n  args: {\n    duration: 199,\n    isRecording: true,\n  },\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <MediaRecordingContext.Provider\n        value={{\n          state: {\n            ...args,\n            status: args.isRecording ? 'recording' : 'stopped',\n          },\n        }}\n      >\n        <DurationIndicator />\n      </MediaRecordingContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/errorDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from '../context';\nimport ErrorDialog from '../errorDialog';\n\nconst errors = {\n  None: {},\n  NotAllowedError: new DOMException(\n    'Not allowed to access camera',\n    'NotAllowedError'\n  ),\n  NotFoundError: new DOMException('Not camera found', 'NotFoundError'),\n  OverConstrainedError: new DOMException(\n    'Over constrained',\n    'OverConstrainedError'\n  ),\n  UnknownError: new DOMException('Some unknown error message', 'UnknownError'),\n};\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/Error Dialog',\n  component: ErrorDialog,\n  args: {\n    error: 'None',\n    hasVideo: true,\n  },\n  argTypes: {\n    error: {\n      options: Object.keys(errors),\n      control: 'select',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <MediaRecordingContext.Provider\n        value={{\n          state: { error: errors[args.error], videoInput: args?.hasVideo },\n        }}\n      >\n        <ErrorDialog />\n      </MediaRecordingContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/permissionsDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport PermissionsDialog from '../permissionsDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/Permissions Dialog',\n  component: PermissionsDialog,\n  args: {\n    adNetwork: 'foo',\n  },\n  argTypes: {\n    adNetwork: {\n      options: [],\n      control: 'select',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <PermissionsDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/settingsModal.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from '../context';\nimport SettingsModal from '../settingsModal';\nimport { noop } from '../../../utils/noop';\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/Settings Dialog',\n  component: SettingsModal,\n  args: {\n    mediaDevices: [\n      {\n        kind: 'videoinput',\n        deviceId: 'video-a',\n        label: 'Video Device A',\n      },\n      {\n        kind: 'videoinput',\n        deviceId: 'video-b',\n        label: 'Video Device B',\n      },\n      {\n        kind: 'videoinput',\n        deviceId: 'video-c',\n        label: 'Video Device C',\n      },\n      {\n        kind: 'audioinput',\n        deviceId: 'audio-a',\n        label: 'Audio Device A',\n      },\n      {\n        kind: 'audioinput',\n        deviceId: 'audio-b',\n        label: 'Audio Device B',\n      },\n      {\n        kind: 'audioinput',\n        deviceId: 'audio-c',\n        label: 'Audio Device C',\n      },\n    ],\n    videoInput: 'video-b',\n    audioInput: 'audio-c',\n  },\n  argTypes: {\n    toggleSettings: { action: 'Settings toggled' },\n  },\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <MediaRecordingContext.Provider\n        value={{\n          state: {\n            hasAudio: true,\n            isSettingsOpen: true,\n            ...args,\n          },\n          actions: {\n            setAudioInput: noop,\n            setVideoInput: noop,\n            clearMediaStream: noop,\n            clearMediaBlob: noop,\n            ...args,\n          },\n        }}\n      >\n        <SettingsModal />\n      </MediaRecordingContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/stories/videoMode.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport VideoMode from '../videoMode';\n\nexport default {\n  title: 'Stories Editor/Components/Media Recording/Video Mode',\n  component: VideoMode,\n  args: {\n    value: false,\n  },\n  argTypes: {\n    value: { name: 'Is video?' },\n    onChange: { action: 'Value changed' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <VideoMode {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/useMediaRecording.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport MediaRecordingContext from './context';\n\nfunction useMediaRecording(selector) {\n  return useContextSelector(MediaRecordingContext, selector ?? identity);\n}\n\nexport default useMediaRecording;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/useTrim.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { formatMsToHMS } from '@googleforcreators/media';\nimport {\n  useState,\n  useCallback,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useFFmpeg from '../../app/media/utils/useFFmpeg';\n\nfunction useTrim({ setDuration, onTrimmed, file, isRecording }) {\n  const [trimData, setTrimData] = useState({ start: 0, end: null });\n  const [isAdjustingTrim, setIsAdjustingTrim] = useState(false);\n  const [isProcessingTrim, setIsProcessingTrim] = useState(false);\n  const { trimVideo } = useFFmpeg();\n  const hasCancelledTrimRef = useRef();\n  const onTrim = useCallback(\n    async (newTrimData) => {\n      setIsAdjustingTrim(false);\n      if (newTrimData) {\n        hasCancelledTrimRef.current = false;\n        setIsProcessingTrim(true);\n        const start = formatMsToHMS(newTrimData.start);\n        const end = formatMsToHMS(newTrimData.end);\n        const result = await trimVideo(file, start, end);\n        // If it was cancelled in the meantime, just abort\n        if (hasCancelledTrimRef.current) {\n          return;\n        }\n        setTrimData(newTrimData);\n        setIsProcessingTrim(false);\n        onTrimmed(result);\n        setDuration(newTrimData.end - newTrimData.start);\n      }\n    },\n    [file, onTrimmed, setDuration, trimVideo]\n  );\n  const startTrim = useCallback(() => setIsAdjustingTrim(true), []);\n  const resetTrim = useCallback(() => {\n    setIsAdjustingTrim(false);\n    setTrimData({ start: 0, end: null });\n  }, []);\n  const cancelTrim = useCallback(() => {\n    hasCancelledTrimRef.current = true;\n    setIsProcessingTrim(false);\n  }, []);\n  // Whenever a new recording starts, reset any previously captured trim data\n  useEffect(() => {\n    if (isRecording) {\n      resetTrim();\n    }\n  }, [isRecording, resetTrim]);\n\n  return {\n    trimData,\n    isAdjustingTrim,\n    isProcessingTrim,\n    onTrim,\n    startTrim,\n    resetTrim,\n    cancelTrim,\n  };\n}\n\nexport default useTrim;\n"
  },
  {
    "path": "packages/story-editor/src/components/mediaRecording/videoMode.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Switch } from '../form';\n\nconst Wrapper = styled.div`\n  position: absolute;\n  z-index: 2;\n  top: 20px;\n  right: 20px;\n  width: 70px;\n`;\n\nconst StyledSwitch = styled(Switch)`\n  background: ${({ theme }) => theme.colors.bg.tertiary};\n`;\n\nconst CameraIcon = styled(Icons.Camera).attrs({\n  title: __('Use as video', 'web-stories'),\n})`\n  flex: 1;\n`;\n\nconst GifIcon = styled(Icons.Gif).attrs({\n  title: __('Use as GIF', 'web-stories'),\n})`\n  flex: 1;\n`;\n\nfunction VideoMode({ value, onChange }) {\n  return (\n    <Wrapper>\n      <StyledSwitch\n        groupLabel={__('Video Mode', 'web-stories')}\n        name=\"video-mode-switch\"\n        value={value}\n        onLabel={<CameraIcon />}\n        offLabel={<GifIcon />}\n        onChange={onChange}\n      />\n    </Wrapper>\n  );\n}\n\nVideoMode.propTypes = {\n  value: PropTypes.bool.isRequired,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport default VideoMode;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/alignment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useCallback, useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useKeyDownEffect,\n  Icons,\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app';\nimport { Panel } from '../../panel';\nimport Tooltip from '../../../tooltip';\nimport useAlignment from './useAlignment';\n\nconst ElementRow = styled.div`\n  display: flex;\n  flex-direction: row;\n  justify-content: center;\n  align-items: center;\n  padding: 16px;\n  overflow: auto;\n`;\n\nconst alignmentButtonIds = [\n  'distributeHorizontally',\n  'distributeVertically',\n  'alignLeft',\n  'alignCenter',\n  'alignRight',\n  'alignTop',\n  'alignMiddle',\n  'alignBottom',\n];\n\nconst AlignmentButton = styled(Button).attrs({\n  variant: ButtonVariant.Square,\n  type: ButtonType.Tertiary,\n  size: ButtonSize.Small,\n})`\n  position: relative;\n\n  :focus {\n    z-index: 1;\n  }\n\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(theme.colors.border.focus, '#1d1f20')};\n`;\n\nconst StyledPanel = styled(Panel)`\n  background-color: ${({ theme }) => theme.colors.opacity.black24};\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.secondary};\n`;\n\nfunction ElementAlignmentPanel({ selectedElements, pushUpdate }) {\n  const { isRTL } = useConfig();\n\n  const updateElements = (callback) => pushUpdate(callback, true);\n\n  const {\n    isDistributionEnabled,\n    handleAlignLeft,\n    handleAlignCenter,\n    handleAlignRight,\n    handleAlignTop,\n    handleAlignMiddle,\n    handleAlignBottom,\n    handleHorizontalDistribution,\n    handleVerticalDistribution,\n  } = useAlignment({ selectedElements, updateElements });\n\n  const ref = useRef();\n  const [currentButton, setCurrentButton] = useState(null);\n\n  const handleNavigation = useCallback(\n    (direction) => () => {\n      const currentIndex = alignmentButtonIds.findIndex(\n        (id) => id === currentButton\n      );\n      const nextButtonId = alignmentButtonIds[currentIndex + direction];\n      if (!nextButtonId) {\n        return;\n      }\n      setCurrentButton(nextButtonId);\n      ref.current.querySelector(`#${nextButtonId}`).focus();\n    },\n    [currentButton, setCurrentButton]\n  );\n\n  const forward = isRTL ? -1 : 1;\n  useKeyDownEffect(ref, 'left', () => handleNavigation(forward), [\n    handleNavigation,\n    forward,\n  ]);\n  useKeyDownEffect(ref, 'right', () => handleNavigation(-forward), [\n    handleNavigation,\n    forward,\n  ]);\n\n  return (\n    <StyledPanel\n      name=\"alignment\"\n      canCollapse={false}\n      ariaLabel={__('Alignment', 'web-stories')}\n    >\n      <ElementRow ref={ref}>\n        <Tooltip title={__('Distribute horizontally', 'web-stories')}>\n          <AlignmentButton\n            disabled={!isDistributionEnabled}\n            onClick={handleHorizontalDistribution}\n            aria-label={__('Distribute horizontally', 'web-stories')}\n            id={alignmentButtonIds[0]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[0])}\n          >\n            <Icons.DistributeHorizontal />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Distribute vertically', 'web-stories')}>\n          <AlignmentButton\n            disabled={!isDistributionEnabled}\n            onClick={handleVerticalDistribution}\n            aria-label={__('Distribute vertically', 'web-stories')}\n            id={alignmentButtonIds[1]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[1])}\n          >\n            <Icons.DistributeVertical />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align left', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignLeft}\n            aria-label={__('Align left', 'web-stories')}\n            id={alignmentButtonIds[2]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[2])}\n          >\n            <Icons.AlignLeft />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align center', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignCenter}\n            aria-label={__('Align center', 'web-stories')}\n            id={alignmentButtonIds[3]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[3])}\n          >\n            <Icons.AlignCenter />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align right', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignRight}\n            aria-label={__('Align right', 'web-stories')}\n            id={alignmentButtonIds[4]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[4])}\n          >\n            <Icons.AlignRight />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align top', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignTop}\n            aria-label={__('Align top', 'web-stories')}\n            id={alignmentButtonIds[5]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[5])}\n          >\n            <Icons.AlignTop />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align vertical center', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignMiddle}\n            aria-label={__('Align vertical center', 'web-stories')}\n            id={alignmentButtonIds[6]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[6])}\n          >\n            <Icons.AlignMiddle />\n          </AlignmentButton>\n        </Tooltip>\n        <Tooltip title={__('Align bottom', 'web-stories')}>\n          <AlignmentButton\n            onClick={handleAlignBottom}\n            aria-label={__('Align bottom', 'web-stories')}\n            id={alignmentButtonIds[7]}\n            onFocus={() => setCurrentButton(alignmentButtonIds[7])}\n          >\n            <Icons.AlignBottom />\n          </AlignmentButton>\n        </Tooltip>\n      </ElementRow>\n    </StyledPanel>\n  );\n}\n\nElementAlignmentPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default ElementAlignmentPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './alignment';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/karma/alignment.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Alignment Panel', () => {\n  let fixture;\n\n  let textA;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    textA = (await getElements())[0].id;\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n  xit('should have no active alignment buttons');\n\n  describe('When there is one element on canvas', () => {\n    beforeEach(async () => {\n      // Add first text element\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n      });\n\n      // It will correctly be selected now\n    });\n\n    describe('CUJ: Creator can Transform an Element: Align element to page', () => {\n      it('should not show a border when focusing an alignment button using mouse', async () => {\n        // Click left align\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.alignment.left\n        );\n\n        // Expect button to have focus\n        expect(fixture.editor.sidebar.designPanel.alignment.left).toHaveFocus();\n\n        // Expect element to be left-aligned\n        const textFrame = fixture.editor.canvas.framesLayer.frame(textA);\n        expect(textFrame.node).toHaveStyle('left', '0px');\n\n        // Get screenshot with left-aligned element and button without visible outline\n        await fixture.snapshot(\n          'Element is left-aligned, \"Left align\" has no visible focus'\n        );\n      });\n\n      it('should show a border when focusing an alignment button using keyboard', async () => {\n        // Click left align\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.alignment.left\n        );\n\n        // Press \"tab\" once - focus should now be on \"center align\"\n        await fixture.events.keyboard.press('tab');\n        expect(\n          fixture.editor.sidebar.designPanel.alignment.center\n        ).toHaveFocus();\n\n        // Expect \"center align\" button to have visible outline\n        await fixture.snapshot(\n          'Element is left-aligned, \"Center align\" has visible focus'\n        );\n      });\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should have the correct active alignment buttons');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element left on canvas');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element center on canvas');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element right on canvas');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element top on canvas');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element middle on canvas');\n\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xit('should align element bottom on canvas');\n    });\n\n    describe('CUJ: Creator can Transform an Element: Align element to on another', () => {\n      // eslint-disable-next-line jasmine/no-disabled-tests -- not implemented yet\n      xdescribe('When there are two elements on canvas', () => {\n        beforeEach(async () => {\n          // Add second text element\n          await fixture.editor.library.textTab.click();\n          await fixture.events.click(\n            fixture.editor.library.text.preset('Paragraph')\n          );\n\n          // TODO: move second text element to appropriate place\n\n          // TODO: Select both\n        });\n\n        it('should have the correct active alignment buttons');\n\n        it('should align elements left');\n\n        it('should align elements center');\n\n        it('should align elements right');\n\n        it('should align elements top');\n\n        it('should align elements middle');\n\n        it('should align elements bottom');\n\n        describe('When there are three elements on canvas', () => {\n          beforeEach(async () => {\n            // Add third text element\n            await fixture.editor.library.textTab.click();\n            await fixture.events.click(\n              fixture.editor.library.text.preset('Paragraph')\n            );\n\n            // TODO: move third text element to appropriate place\n\n            // TODO: Select all three\n          });\n\n          it('should have the correct active alignment buttons');\n\n          it('should distribute elements horizontally');\n\n          it('should distribute elements vertically');\n        });\n      });\n    });\n  });\n\n  async function getElements() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/test/alignment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport Alignment from '../alignment';\nimport { renderPanel } from '../../../shared/test/_utils';\n\njest.mock('@googleforcreators/element-library');\n\ndescribe('Panels/Alignment', () => {\n  let defaultElement, defaultText, defaultImage;\n  const horizontalDistributionButtonLabel = 'Distribute horizontally';\n  const verticalDistributionButtonLabel = 'Distribute vertically';\n  const justifyLeftButtonLabel = 'Align left';\n  const justifyCenterButtonLabel = 'Align center';\n  const justifyRightButtonLabel = 'Align right';\n  const justifyTopButtonLabel = 'Align top';\n  const justifyMiddleButtonLabel = 'Align vertical center';\n  const justifyBottomButtonLabel = 'Align bottom';\n\n  beforeEach(() => {\n    defaultElement = {\n      id: '1',\n      isBackground: false,\n      x: 10,\n      y: 10,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n    };\n    defaultText = {\n      ...defaultElement,\n      type: 'text',\n    };\n    defaultImage = {\n      ...defaultElement,\n      type: 'image',\n    };\n  });\n\n  function arrange(...args) {\n    const view = renderPanel(Alignment, ...args);\n    const horizontalDistributionButton = screen.getByLabelText(\n      horizontalDistributionButtonLabel\n    );\n    const verticalDistributionButton = screen.getByLabelText(\n      verticalDistributionButtonLabel\n    );\n    const justifyLeftButton = screen.getByLabelText(justifyLeftButtonLabel);\n    const justifyCenterButton = screen.getByLabelText(justifyCenterButtonLabel);\n    const justifyRightButton = screen.getByLabelText(justifyRightButtonLabel);\n    const justifyTopButton = screen.getByLabelText(justifyTopButtonLabel);\n    const justifyMiddleButton = screen.getByLabelText(justifyMiddleButtonLabel);\n    const justifyBottomButton = screen.getByLabelText(justifyBottomButtonLabel);\n\n    return {\n      ...view,\n      horizontalDistributionButton,\n      verticalDistributionButton,\n      justifyLeftButton,\n      justifyCenterButton,\n      justifyRightButton,\n      justifyTopButton,\n      justifyMiddleButton,\n      justifyBottomButton,\n    };\n  }\n\n  describe('single selection', () => {\n    it('should render disabled distribution buttons', () => {\n      const {\n        pushUpdate,\n        horizontalDistributionButton,\n        verticalDistributionButton,\n      } = arrange([defaultElement]);\n\n      expect(horizontalDistributionButton).toBeDisabled();\n      expect(verticalDistributionButton).toBeDisabled();\n\n      fireEvent.click(horizontalDistributionButton);\n      expect(pushUpdate).toHaveBeenCalledTimes(0);\n\n      fireEvent.click(verticalDistributionButton);\n      expect(pushUpdate).toHaveBeenCalledTimes(0);\n    });\n\n    it('should render align and justify buttons for default element', () => {\n      const {\n        justifyLeftButton,\n        justifyCenterButton,\n        justifyRightButton,\n        justifyTopButton,\n        justifyMiddleButton,\n        justifyBottomButton,\n      } = arrange([defaultElement]);\n\n      expect(justifyLeftButton).toBeEnabled();\n      expect(justifyCenterButton).toBeEnabled();\n      expect(justifyRightButton).toBeEnabled();\n      expect(justifyTopButton).toBeEnabled();\n      expect(justifyMiddleButton).toBeEnabled();\n      expect(justifyBottomButton).toBeEnabled();\n    });\n\n    it('should update element on alignleft button click', () => {\n      const { justifyLeftButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyLeftButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n\n    it('should update element on alignright button click', () => {\n      const { justifyRightButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyRightButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n\n    it('should update element on aligncenter button click', () => {\n      const { justifyCenterButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyCenterButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n\n    it('should update element on justifytop button click', () => {\n      const { justifyTopButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyTopButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n\n    it('should update element on justifybottom button click', () => {\n      const { justifyBottomButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyBottomButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n\n    it('should update element on justifymiddle button click', () => {\n      const { justifyMiddleButton, pushUpdate } = arrange([defaultElement]);\n\n      fireEvent.click(justifyMiddleButton);\n      expect(pushUpdate).toHaveBeenCalledOnce();\n    });\n  });\n\n  describe('2 element selection', () => {\n    it('should render disabled distribution and enabled align and justify buttons for multi default element', () => {\n      const {\n        horizontalDistributionButton,\n        verticalDistributionButton,\n        justifyLeftButton,\n        justifyCenterButton,\n        justifyRightButton,\n        justifyTopButton,\n        justifyMiddleButton,\n        justifyBottomButton,\n      } = arrange([defaultElement, defaultText]);\n\n      expect(horizontalDistributionButton).toBeDisabled();\n      expect(verticalDistributionButton).toBeDisabled();\n      expect(justifyLeftButton).toBeEnabled();\n      expect(justifyCenterButton).toBeEnabled();\n      expect(justifyRightButton).toBeEnabled();\n      expect(justifyTopButton).toBeEnabled();\n      expect(justifyMiddleButton).toBeEnabled();\n      expect(justifyBottomButton).toBeEnabled();\n    });\n  });\n\n  describe('3 element selection', () => {\n    it('should render enabled distribution, align and justify buttons for multi default element', () => {\n      const {\n        horizontalDistributionButton,\n        verticalDistributionButton,\n        justifyLeftButton,\n        justifyCenterButton,\n        justifyRightButton,\n        justifyTopButton,\n        justifyMiddleButton,\n        justifyBottomButton,\n      } = arrange([defaultElement, defaultText, defaultImage]);\n\n      expect(horizontalDistributionButton).toBeEnabled();\n      expect(verticalDistributionButton).toBeEnabled();\n      expect(justifyLeftButton).toBeEnabled();\n      expect(justifyCenterButton).toBeEnabled();\n      expect(justifyRightButton).toBeEnabled();\n      expect(justifyTopButton).toBeEnabled();\n      expect(justifyMiddleButton).toBeEnabled();\n      expect(justifyBottomButton).toBeEnabled();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/test/useAlignment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { PAGE_WIDTH, PAGE_HEIGHT } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport useAlignment from '../useAlignment';\n\nconst WIDTH = 40;\nconst DESIGN_GUIDE = 48;\nconst ROTATED_OFFSET = 8; // Math.floor(Math.sqrt(WIDTH^2/2) - WIDTH/2)\nconst SHAPE = {\n  width: WIDTH,\n  height: WIDTH,\n  rotationAngle: 0,\n  type: 'shape',\n};\nconst TOPLEFT_SHAPE = {\n  ...SHAPE,\n  id: '1',\n  x: DESIGN_GUIDE,\n  y: 0,\n};\nconst TOPLEFT_ROTATED_SHAPE = {\n  ...TOPLEFT_SHAPE,\n  id: '1r',\n  rotationAngle: 45,\n};\nconst CENTER_SHAPE = {\n  ...SHAPE,\n  id: '2',\n  x: (PAGE_WIDTH - WIDTH) / 2,\n  y: (PAGE_HEIGHT - WIDTH) / 2,\n};\nconst CENTER_ROTATED_SHAPE = {\n  ...CENTER_SHAPE,\n  id: '2r',\n  rotationAngle: 45,\n};\nconst BOTTOMRIGHT_SHAPE = {\n  ...SHAPE,\n  id: '3',\n  x: PAGE_WIDTH - 2 * WIDTH - DESIGN_GUIDE,\n  y: PAGE_HEIGHT - 2 * WIDTH,\n};\n\nfunction renderUseAlignment(selectedElements) {\n  const updateElements = jest.fn();\n  const {\n    result: { current },\n  } = renderHook(() => useAlignment({ selectedElements, updateElements }));\n  const getResult = () => {\n    const updateFunction = updateElements.mock.calls[0][0];\n    return selectedElements.map(updateFunction);\n  };\n  return {\n    ...current,\n    getResult,\n  };\n}\n\ndescribe('useAlignment', () => {\n  describe('with a single element', () => {\n    describe('that is not rotated', () => {\n      it('should not be distributable', () => {\n        const { isDistributionEnabled } = renderUseAlignment([CENTER_SHAPE]);\n        expect(isDistributionEnabled).toBeFalse();\n      });\n      it('should attempt to set x to 0 when aligning left', () => {\n        const hookResult = renderUseAlignment([CENTER_SHAPE]);\n        const { handleAlignLeft, getResult } = hookResult;\n        handleAlignLeft();\n        const [leftAlignedShape] = getResult();\n        expect(leftAlignedShape).toMatchObject({\n          x: 0,\n        });\n      });\n      it('should attempt to set x to (page width - object width)/2 when aligning center', () => {\n        const hookResult = renderUseAlignment([TOPLEFT_SHAPE]);\n        const { handleAlignCenter, getResult } = hookResult;\n        handleAlignCenter();\n        const [centerAlignedShape] = getResult();\n        expect(centerAlignedShape).toMatchObject({\n          x: (PAGE_WIDTH - WIDTH) / 2,\n        });\n      });\n      it('should attempt to set x to (page width - object width) when aligning right', () => {\n        const hookResult = renderUseAlignment([CENTER_SHAPE]);\n        const { handleAlignRight, getResult } = hookResult;\n        handleAlignRight();\n        const [rightAlignedShape] = getResult();\n        expect(rightAlignedShape).toMatchObject({\n          x: PAGE_WIDTH - WIDTH,\n        });\n      });\n      it('should attempt to set y to 0 when aligning top', () => {\n        const hookResult = renderUseAlignment([CENTER_SHAPE]);\n        const { handleAlignTop, getResult } = hookResult;\n        handleAlignTop();\n        const [topAlignedShape] = getResult();\n        expect(topAlignedShape).toMatchObject({\n          y: 0,\n        });\n      });\n      it('should attempt to set y to (page height - object height)/2 when aligning middle', () => {\n        const hookResult = renderUseAlignment([CENTER_SHAPE]);\n        const { handleAlignMiddle, getResult } = hookResult;\n        handleAlignMiddle();\n        const [middleAlignedShape] = getResult();\n        expect(middleAlignedShape).toMatchObject({\n          y: (PAGE_HEIGHT - WIDTH) / 2,\n        });\n      });\n      it('should attempt to set y to (page height - object height) when aligning bottom', () => {\n        const hookResult = renderUseAlignment([TOPLEFT_SHAPE]);\n        const { handleAlignBottom, getResult } = hookResult;\n        handleAlignBottom();\n        const [bottomAlignedShape] = getResult();\n        expect(bottomAlignedShape).toMatchObject({\n          y: PAGE_HEIGHT - WIDTH,\n        });\n      });\n    });\n    describe('that is rotated', () => {\n      it('should not be distributable', () => {\n        const { isDistributionEnabled } = renderUseAlignment([CENTER_SHAPE]);\n        expect(isDistributionEnabled).toBeFalse();\n      });\n      it('should attempt to set x to OFFSET when aligning left', () => {\n        const hookResult = renderUseAlignment([CENTER_ROTATED_SHAPE]);\n        const { handleAlignLeft, getResult } = hookResult;\n        handleAlignLeft();\n        const [leftAlignedShape] = getResult();\n        expect(leftAlignedShape).toMatchObject({\n          x: ROTATED_OFFSET,\n        });\n      });\n      it('should attempt to set x to (page width - object width)/2 when aligning center', () => {\n        const hookResult = renderUseAlignment([TOPLEFT_ROTATED_SHAPE]);\n        const { handleAlignCenter, getResult } = hookResult;\n        handleAlignCenter();\n        const [centerAlignedShape] = getResult();\n        expect(centerAlignedShape).toMatchObject({\n          x: (PAGE_WIDTH - WIDTH) / 2,\n        });\n      });\n      it('should attempt to set x to (page width - object width - offset) when aligning right', () => {\n        const hookResult = renderUseAlignment([CENTER_ROTATED_SHAPE]);\n        const { handleAlignRight, getResult } = hookResult;\n        handleAlignRight();\n        const [rightAlignedShape] = getResult();\n        expect(rightAlignedShape).toMatchObject({\n          x: PAGE_WIDTH - WIDTH - ROTATED_OFFSET,\n        });\n      });\n      it('should attempt to set y to offset when aligning top', () => {\n        const hookResult = renderUseAlignment([CENTER_ROTATED_SHAPE]);\n        const { handleAlignTop, getResult } = hookResult;\n        handleAlignTop();\n        const [topAlignedShape] = getResult();\n        expect(topAlignedShape).toMatchObject({\n          y: ROTATED_OFFSET,\n        });\n      });\n      it('should attempt to set y to (page height - object height)/2 when aligning middle', () => {\n        const hookResult = renderUseAlignment([CENTER_ROTATED_SHAPE]);\n        const { handleAlignMiddle, getResult } = hookResult;\n        handleAlignMiddle();\n        const [middleAlignedShape] = getResult();\n        expect(middleAlignedShape).toMatchObject({\n          y: (PAGE_HEIGHT - WIDTH) / 2,\n        });\n      });\n      it('should attempt to set y to (page height - object height - offset) when aligning bottom', () => {\n        const hookResult = renderUseAlignment([TOPLEFT_ROTATED_SHAPE]);\n        const { handleAlignBottom, getResult } = hookResult;\n        handleAlignBottom();\n        const [bottomAlignedShape] = getResult();\n        expect(bottomAlignedShape).toMatchObject({\n          y: PAGE_HEIGHT - WIDTH - ROTATED_OFFSET,\n        });\n      });\n    });\n  });\n  describe('with two elements', () => {\n    it('should not be distributable', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const { isDistributionEnabled } = hookResult;\n      expect(isDistributionEnabled).toBeFalse();\n    });\n    it('should attempt to set x to min x when aligning left', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedX = TOPLEFT_SHAPE.x;\n      const { handleAlignLeft, getResult } = hookResult;\n      handleAlignLeft();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ x: expectedX }));\n    });\n    it('should attempt to set x to middle x when aligning center', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedX =\n        TOPLEFT_SHAPE.x + (CENTER_SHAPE.x - TOPLEFT_SHAPE.x) / 2;\n      const { handleAlignCenter, getResult } = hookResult;\n      handleAlignCenter();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ x: expectedX }));\n    });\n    it('should attempt to set x to max x when aligning right', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedX = CENTER_SHAPE.x;\n      const { handleAlignRight, getResult } = hookResult;\n      handleAlignRight();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ x: expectedX }));\n    });\n    it('should attempt to set y to min y when aligning top', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedY = TOPLEFT_SHAPE.y;\n      const { handleAlignTop, getResult } = hookResult;\n      handleAlignTop();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ y: expectedY }));\n    });\n    it('should attempt to set y to middle y when aligning middle', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedY =\n        TOPLEFT_SHAPE.y + (CENTER_SHAPE.y - TOPLEFT_SHAPE.y) / 2;\n      const { handleAlignMiddle, getResult } = hookResult;\n      handleAlignMiddle();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ y: expectedY }));\n    });\n    it('should attempt to set y to max y when aligning bottom', () => {\n      const hookResult = renderUseAlignment([TOPLEFT_SHAPE, CENTER_SHAPE]);\n      const expectedY = CENTER_SHAPE.y;\n      const { handleAlignBottom, getResult } = hookResult;\n      handleAlignBottom();\n      const shapes = getResult();\n      shapes.forEach((shape) => expect(shape).toMatchObject({ y: expectedY }));\n    });\n  });\n  describe('with three elements', () => {\n    it('should be distributable', () => {\n      const hookResult = renderUseAlignment([\n        TOPLEFT_SHAPE,\n        CENTER_SHAPE,\n        BOTTOMRIGHT_SHAPE,\n      ]);\n      const { isDistributionEnabled } = hookResult;\n      expect(isDistributionEnabled).toBeTrue();\n    });\n    it('should attempt to set middle element x to center when distributing horizontally', () => {\n      const hookResult = renderUseAlignment([\n        TOPLEFT_SHAPE,\n        CENTER_SHAPE,\n        BOTTOMRIGHT_SHAPE,\n      ]);\n      const expectedX =\n        TOPLEFT_SHAPE.x + (BOTTOMRIGHT_SHAPE.x - TOPLEFT_SHAPE.x) / 2;\n      const { handleHorizontalDistribution, getResult } = hookResult;\n      handleHorizontalDistribution();\n      const shapes = getResult();\n      expect(shapes[1]).toMatchObject({ x: expectedX });\n    });\n    it('should attempt to set middle element y to center when distributing vertically', () => {\n      const hookResult = renderUseAlignment([\n        TOPLEFT_SHAPE,\n        CENTER_SHAPE,\n        BOTTOMRIGHT_SHAPE,\n      ]);\n      const expectedY =\n        TOPLEFT_SHAPE.y + (BOTTOMRIGHT_SHAPE.y - TOPLEFT_SHAPE.y) / 2;\n      const { handleVerticalDistribution, getResult } = hookResult;\n      handleVerticalDistribution();\n      const shapes = getResult();\n      expect(shapes[1]).toMatchObject({ y: expectedY });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/alignment/useAlignment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport {\n  PAGE_WIDTH,\n  PAGE_HEIGHT,\n  getBoundRect,\n  calcRotatedObjectPositionAndSize,\n  dataPixels,\n} from '@googleforcreators/units';\nimport { trackEvent } from '@googleforcreators/tracking';\n\nconst PAGE_RECT = {\n  startX: 0,\n  startY: 0,\n  endX: PAGE_WIDTH,\n  endY: PAGE_HEIGHT,\n  width: PAGE_WIDTH,\n  height: PAGE_HEIGHT,\n};\n\nconst ALIGNMENT = {\n  LEFT: 'left',\n  RIGHT: 'right',\n  TOP: 'top',\n  BOTTOM: 'bottom',\n};\n\nfunction useAlignment({ selectedElements, updateElements, isFloatingMenu }) {\n  const isDistributionEnabled = selectedElements.length > 2;\n  const selectedElementsWithFrame = useMemo(\n    () =>\n      selectedElements.map((item) => {\n        const { id, groupId, x, y, width, height, rotationAngle } = item;\n        let frameX = x;\n        let frameY = y;\n        let frameWidth = width;\n        let frameHeight = height;\n        if (rotationAngle) {\n          const elementFrame = calcRotatedObjectPositionAndSize(\n            rotationAngle,\n            x,\n            y,\n            width,\n            height\n          );\n          frameX = elementFrame.x;\n          frameY = elementFrame.y;\n          frameWidth = elementFrame.width;\n          frameHeight = elementFrame.height;\n        }\n        return {\n          id,\n          groupId,\n          x,\n          y,\n          width,\n          height,\n          frameX,\n          frameY,\n          frameWidth,\n          frameHeight,\n        };\n      }),\n    [selectedElements]\n  );\n  // Set boundRect with pageSize when there is only one element selected or only group is selected\n  const selectedGroupId = selectedElements[0].groupId;\n  const isOnlyGroupSelected =\n    selectedGroupId &&\n    selectedElements.every(\n      (el) => el.groupId && el.groupId === selectedGroupId\n    );\n  const boundRect =\n    selectedElements.length === 1 || isOnlyGroupSelected\n      ? PAGE_RECT\n      : getBoundRect(selectedElements);\n\n  const handleTrackEvent = (direction) => {\n    trackEvent(isFloatingMenu ? 'floating_menu' : 'design_panel', {\n      name: `set_alignment_${direction}`,\n      element: 'multiple',\n    });\n  };\n\n  const handleAlign = (direction) => {\n    handleTrackEvent(direction);\n    updateElements((properties) => {\n      const { id, groupId } = properties;\n      const groupRect = groupId\n        ? getBoundRect(selectedElements.filter((el) => el.groupId === groupId))\n        : null;\n\n      const element = selectedElementsWithFrame.find((item) => item.id === id);\n      const {\n        width = 0,\n        height = 0,\n        frameWidth = 0,\n        frameHeight = 0,\n      } = element || {};\n      const offset =\n        direction === ALIGNMENT.LEFT || direction === ALIGNMENT.RIGHT\n          ? (frameWidth - width) / 2\n          : (frameHeight - height) / 2;\n      const offsetInGroup = groupId\n        ? direction === ALIGNMENT.LEFT || direction === ALIGNMENT.RIGHT\n          ? element.frameX - groupRect.startX\n          : element.frameY - groupRect.startY\n        : 0;\n\n      const calcWidth = groupId ? groupRect.width : width;\n      const calcHeight = groupId ? groupRect.height : height;\n\n      if (direction === ALIGNMENT.LEFT || direction === ALIGNMENT.RIGHT) {\n        return {\n          x:\n            direction === ALIGNMENT.LEFT\n              ? boundRect.startX + offset + offsetInGroup\n              : boundRect.endX - calcWidth - offset + offsetInGroup,\n        };\n      }\n      return {\n        y:\n          direction === ALIGNMENT.TOP\n            ? boundRect.startY + offset + offsetInGroup\n            : boundRect.endY - calcHeight - offset + offsetInGroup,\n      };\n    });\n  };\n\n  const handleAlignCenter = () => {\n    handleTrackEvent('center');\n    const centerX = (boundRect.endX + boundRect.startX) / 2;\n    updateElements((properties) => {\n      const { id, width, groupId } = properties;\n      const groupRect = groupId\n        ? getBoundRect(selectedElements.filter((el) => el.groupId === groupId))\n        : null;\n      const calcWidth = groupId ? groupRect.width : width;\n      const element = selectedElementsWithFrame.find((item) => item.id === id);\n      const offsetInGroup = groupId ? element.frameX - groupRect.startX : 0;\n      return {\n        x: centerX - calcWidth / 2 + offsetInGroup,\n      };\n    });\n  };\n\n  const handleAlignMiddle = () => {\n    handleTrackEvent('middle');\n    const centerY = (boundRect.endY + boundRect.startY) / 2;\n    updateElements((properties) => {\n      const { id, height, groupId } = properties;\n      const groupRect = groupId\n        ? getBoundRect(selectedElements.filter((el) => el.groupId === groupId))\n        : null;\n      const calcHeight = groupId ? groupRect.height : height;\n      const element = selectedElementsWithFrame.find((item) => item.id === id);\n      const offsetInGroup = groupId ? element.frameY - groupRect.startY : 0;\n      return {\n        y: centerY - calcHeight / 2 + offsetInGroup,\n      };\n    });\n  };\n\n  const handleHorizontalDistribution = () => {\n    handleTrackEvent('horizontal_distribution');\n    const sortedElementsWithFrame = [...selectedElementsWithFrame];\n    sortedElementsWithFrame.sort(\n      (a, b) => (a.frameX + a.frameWidth) / 2 - (b.frameX + b.frameWidth) / 2\n    );\n    const elementWidthSum = sortedElementsWithFrame.reduce(\n      (sum, element) => sum + element.frameWidth,\n      0\n    );\n    const commonSpaceWidth = boundRect.width - elementWidthSum;\n    const commonSpaceWidthPerElement = dataPixels(\n      commonSpaceWidth / (sortedElementsWithFrame.length - 1)\n    );\n    const updatedX = {};\n    let offsetX = 0;\n    sortedElementsWithFrame.forEach((element, index) => {\n      const { id, x, width, frameWidth } = element;\n      if (index === 0 || index === sortedElementsWithFrame.length - 1) {\n        updatedX[id] = { x };\n        offsetX = x;\n      } else {\n        updatedX[id] = {\n          x: offsetX + (frameWidth - width) / 2,\n        };\n      }\n      offsetX += frameWidth + commonSpaceWidthPerElement;\n    });\n    updateElements(({ id }) => updatedX[id]);\n  };\n\n  const handleVerticalDistribution = () => {\n    handleTrackEvent('vertical_distribution');\n    const sortedElementsWithFrame = [...selectedElementsWithFrame];\n    sortedElementsWithFrame.sort(\n      (a, b) => (a.frameY + a.frameHeight) / 2 - (b.frameY + b.frameHeight) / 2\n    );\n    const elementHeightSum = sortedElementsWithFrame.reduce(\n      (sum, element) => sum + element.frameHeight,\n      0\n    );\n    const commonSpaceHeight = boundRect.height - elementHeightSum;\n    const commonSpaceHeightPerElement = dataPixels(\n      commonSpaceHeight / (sortedElementsWithFrame.length - 1)\n    );\n    const updatedY = {};\n    let offsetY = 0;\n    sortedElementsWithFrame.forEach((element, index) => {\n      const { id, y, height, frameHeight } = element;\n      if (index === 0 || index === sortedElementsWithFrame.length - 1) {\n        updatedY[id] = { y };\n        offsetY = y;\n      } else {\n        updatedY[id] = {\n          y: offsetY + (frameHeight - height) / 2,\n        };\n      }\n      offsetY += frameHeight + commonSpaceHeightPerElement;\n    });\n    updateElements(({ id }) => updatedY[id]);\n  };\n\n  return {\n    isDistributionEnabled,\n    handleAlignLeft: () => handleAlign(ALIGNMENT.LEFT),\n    handleAlignCenter,\n    handleAlignRight: () => handleAlign(ALIGNMENT.RIGHT),\n    handleAlignTop: () => handleAlign(ALIGNMENT.TOP),\n    handleAlignMiddle,\n    handleAlignBottom: () => handleAlign(ALIGNMENT.BOTTOM),\n    handleHorizontalDistribution,\n    handleVerticalDistribution,\n  };\n}\n\nexport default useAlignment;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/animation.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useMemo,\n  useEffect,\n  useRef,\n  useDebouncedCallback,\n  shallowEqual,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  BACKGROUND_ANIMATION_EFFECTS,\n  BG_MAX_SCALE,\n  BG_MIN_SCALE,\n  AnimationDirection,\n  ScaleDirection,\n  StoryAnimationState,\n  getAnimationEffectDefaults,\n  getHasElementOffsets,\n  DEFAULT_HAS_OFFSETS,\n} from '@googleforcreators/animation';\nimport { progress } from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes, AnimationPropType } from '../../../../propTypes';\nimport { useStory } from '../../../../app';\nimport { DESIGN_COPY } from '../../../checklist';\nimport Warning from '../warning';\nimport { Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport EffectPanel, { getEffectName, getEffectDirection } from './effectPanel';\nimport { EffectChooserDropdown } from './effectChooserDropdown';\n\nconst ANIMATION_PROPERTY = 'animation';\n\nconst StyledRow = styled(Row)`\n  margin-bottom: -1px;\n`;\n\nconst GroupWrapper = styled.div`\n  ${({ hasAnimation, theme }) =>\n    hasAnimation &&\n    `\n    border: 1px solid ${theme.colors.border.defaultNormal};\n    border-radius: ${theme.borders.radius.small};\n  `}\n  margin-bottom: 16px;\n`;\n\nconst backgroundAnimationTooltip = __(\n  'The background image is too small to animate. Double click on the bg & scale the image before applying the animation.',\n  'web-stories'\n);\n\nfunction AnimationPanel({\n  selectedElements,\n  selectedElementAnimations,\n  pushUpdateForObject,\n  updateAnimationState,\n}) {\n  const isFirstPage = useStory(\n    ({ state: { currentPageNumber } }) => currentPageNumber === 1\n  );\n  const playUpdatedAnimationRef = useRef(false);\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.Animation],\n    resetHighlight: state.onFocusOut,\n    cancelHighlight: state.cancelEffect,\n  }));\n\n  const isBackground =\n    selectedElements.length === 1 && selectedElements[0].isBackground;\n  const updatedAnimations = useMemo(() => {\n    // Combining local element updates with the\n    // page level applied updates\n    const updated = selectedElements\n      .map((element) => element.animation)\n      .filter(Boolean);\n    return selectedElementAnimations\n      .map((anim) => ({\n        ...(updated.find((a) => a.id === anim.id) || anim),\n      }))\n      .filter((a) => !a.delete);\n  }, [selectedElements, selectedElementAnimations]);\n\n  const handlePanelChange = useCallback(\n    (animation, submitArg = false) => {\n      if (shallowEqual(animation, updatedAnimations[0])) {\n        return;\n      }\n\n      updateAnimationState({\n        animationState: StoryAnimationState.Reset,\n      });\n      pushUpdateForObject(ANIMATION_PROPERTY, animation, null, submitArg);\n      playUpdatedAnimationRef.current = true;\n    },\n    [pushUpdateForObject, updatedAnimations, updateAnimationState]\n  );\n\n  const handleAddOrUpdateElementEffect = useCallback(\n    ({ animation, ...options }) => {\n      if (!animation) {\n        return;\n      }\n\n      const id = selectedElementAnimations[0]?.id || uuidv4();\n      const defaults = getAnimationEffectDefaults(animation);\n      const persisted =\n        selectedElementAnimations[0]?.type === animation\n          ? {\n              duration: selectedElementAnimations[0]?.duration,\n              delay: selectedElementAnimations[0]?.delay,\n            }\n          : {};\n\n      pushUpdateForObject(\n        ANIMATION_PROPERTY,\n        {\n          id,\n          type: animation,\n          ...defaults,\n          ...persisted,\n          ...options,\n        },\n        null,\n        true\n      );\n\n      // There's nothing unique to the animation data to signify that it\n      // was changed by the effect chooser, so we track it here.\n      playUpdatedAnimationRef.current = true;\n    },\n    [selectedElementAnimations, pushUpdateForObject]\n  );\n\n  // Play animation of selected elements when effect chooser signals\n  // that it has changed the data and the data comes back changed.\n  //\n  // Currently, animations get reset whenever the designInspector\n  // gains focus, adding this debouncer and scheduling it after\n  // the all the focus updates go through prevents the reset from\n  // overriding this play call.\n  const activeElement = document.activeElement;\n  const debouncedUpdateAnimationState = useDebouncedCallback(() => {\n    if (playUpdatedAnimationRef.current) {\n      updateAnimationState({\n        animationState: StoryAnimationState.PlayingSelected,\n      });\n      playUpdatedAnimationRef.current = false;\n    }\n  }, 300);\n  useEffect(debouncedUpdateAnimationState, [\n    selectedElementAnimations,\n    updateAnimationState,\n    activeElement,\n    debouncedUpdateAnimationState,\n  ]);\n\n  const handleRemoveEffect = useCallback(() => {\n    pushUpdateForObject(\n      ANIMATION_PROPERTY,\n      {\n        ...updatedAnimations[0],\n        delete: true,\n      },\n      null,\n      true\n    );\n  }, [pushUpdateForObject, updatedAnimations]);\n\n  // Figure out if any options are disabled\n  // for an animation type input\n  const selectedElement = selectedElements[0];\n  const disabledTypeOptionsMap = useMemo(() => {\n    if (!selectedElement) {\n      return {};\n    }\n    if (selectedElement.isBackground) {\n      const { isMedia } = getDefinitionForType(selectedElement.type);\n      const hasOffset = isMedia\n        ? getHasElementOffsets(selectedElement)\n        : DEFAULT_HAS_OFFSETS;\n      const normalizedScale = progress(selectedElement.scale || 0, {\n        MIN: BG_MIN_SCALE,\n        MAX: BG_MAX_SCALE,\n      });\n      return {\n        [BACKGROUND_ANIMATION_EFFECTS.PAN.value]: {\n          tooltip: backgroundAnimationTooltip,\n          options: [\n            !hasOffset.bottom && AnimationDirection.TopToBottom,\n            !hasOffset.left && AnimationDirection.RightToLeft,\n            !hasOffset.top && AnimationDirection.BottomToTop,\n            !hasOffset.right && AnimationDirection.LeftToRight,\n          ].filter(Boolean),\n        },\n        [BACKGROUND_ANIMATION_EFFECTS.ZOOM.value]: {\n          tooltip: backgroundAnimationTooltip,\n          options: [\n            normalizedScale <= 0.01 && ScaleDirection.ScaleIn,\n            normalizedScale >= 0.99 && ScaleDirection.ScaleOut,\n          ].filter(Boolean),\n        },\n        [BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value]: {\n          tooltip: backgroundAnimationTooltip,\n          options: [\n            !hasOffset.bottom && AnimationDirection.TopToBottom,\n            !hasOffset.left && AnimationDirection.RightToLeft,\n            !hasOffset.top && AnimationDirection.BottomToTop,\n            !hasOffset.right && AnimationDirection.LeftToRight,\n            normalizedScale <= 0.01 && ScaleDirection.ScaleIn,\n            normalizedScale >= 0.99 && ScaleDirection.ScaleOut,\n          ].filter(Boolean),\n        },\n      };\n    }\n    return {};\n  }, [selectedElement]);\n\n  const selectedEffectTitle = getEffectName(updatedAnimations[0]?.type);\n  return selectedElements.length > 1 ? null : (\n    <SimplePanel\n      name=\"animation\"\n      title={__('Animation', 'web-stories')}\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      isPersistable={!highlight}\n    >\n      <GroupWrapper hasAnimation={selectedEffectTitle}>\n        <StyledRow>\n          <EffectChooserDropdown\n            ref={(node) => {\n              if (node && highlight?.focus && highlight?.showEffect) {\n                node.focus();\n              }\n            }}\n            onAnimationSelected={handleAddOrUpdateElementEffect}\n            onNoEffectSelected={handleRemoveEffect}\n            isBackgroundEffects={isBackground}\n            disabledTypeOptionsMap={disabledTypeOptionsMap}\n            direction={getEffectDirection(updatedAnimations[0])}\n            selectedEffectType={updatedAnimations[0]?.type}\n            selectButtonStylesOverride={highlight?.focus && styles.OUTLINE}\n            disabled={isFirstPage}\n          />\n        </StyledRow>\n        {updatedAnimations[0] && (\n          <EffectPanel\n            animation={updatedAnimations[0]}\n            onChange={handlePanelChange}\n            disabledTypeOptionsMap={disabledTypeOptionsMap}\n            disabled={isFirstPage}\n          />\n        )}\n      </GroupWrapper>\n      {isFirstPage && (\n        <Warning message={DESIGN_COPY.firstPageAnimation.animationPanel} />\n      )}\n    </SimplePanel>\n  );\n}\n\nAnimationPanel.propTypes = {\n  selectedElements: PropTypes.arrayOf(StoryPropTypes.element).isRequired,\n  selectedElementAnimations: PropTypes.arrayOf(AnimationPropType),\n  pushUpdateForObject: PropTypes.func.isRequired,\n  updateAnimationState: PropTypes.func,\n};\n\nexport default AnimationPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const INPUT_HEIGHT = 45;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/directionRadioInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __, _x } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n} from '@googleforcreators/design-system';\nimport {\n  AnimationDirection,\n  Rotation,\n  ScaleDirection,\n  SCALE_DIRECTIONS,\n} from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\nimport useRadioNavigation from '../../../form/shared/useRadioNavigation';\nimport Tooltip from '../../../tooltip';\n\nconst StyledButton = styled(Button)`\n  z-index: 0;\n  width: 28px;\n  height: 28px;\n  ${({ selected, disabled, theme }) =>\n    selected &&\n    !disabled &&\n    css`\n      background-color: ${theme.colors.interactiveBg.secondaryPress};\n    `}\n\n  svg {\n    transform-origin: 50% 50%;\n    transform: ${({ direction }) => {\n      switch (direction) {\n        case AnimationDirection.RightToLeft:\n          return 'rotate(270deg)';\n        case AnimationDirection.TopToBottom:\n          return 'rotate(180deg)';\n        case AnimationDirection.LeftToRight:\n          return 'rotate(90deg)';\n        case Rotation.CounterClockwise:\n          return 'rotateX(180deg) rotateZ(90deg)';\n        case ScaleDirection.ScaleOutBottomLeft:\n          return 'rotate(-135deg)';\n        case ScaleDirection.ScaleInTopLeft:\n          return 'rotate(135deg)';\n        case ScaleDirection.ScaleOutTopRight:\n          return 'rotate(-315deg)';\n        case ScaleDirection.ScaleInBottomRight:\n          return 'rotate(315deg)';\n        default:\n          return 'rotate(0deg)';\n      }\n    }};\n  }\n`;\n\nconst Direction = ({ className, direction, ...rest }) => (\n  <StyledButton\n    variant={ButtonVariant.Square}\n    type={ButtonType.Tertiary}\n    size={ButtonSize.Small}\n    className={className}\n    direction={direction}\n    {...rest}\n  >\n    {[\n      ...Object.values(AnimationDirection),\n      ...Object.values(ScaleDirection),\n    ].includes(direction) && <Icons.ArrowUp />}\n  </StyledButton>\n);\n\n// Must be a styled component to add component selectors in css\nconst DirectionIndicator = styled(Direction)``;\n\nconst Fieldset = styled.fieldset`\n  position: relative;\n  height: 91px;\n  width: 88px;\n  margin-top: 1px;\n  border-right: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n`;\n\nconst Figure = styled.div`\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  width: 8px;\n  height: 8px;\n  background-color: ${({ theme }) => theme.colors.fg.primary};\n  border-radius: 2px;\n  transform: translate(-50%, -50%);\n`;\n\nconst SPACE_FROM_EDGE = 3;\nconst Label = styled.label`\n  position: absolute;\n  cursor: ${({ disabled }) => (disabled ? 'default' : 'pointer')};\n\n  ${({ direction }) => {\n    switch (direction) {\n      case AnimationDirection.RightToLeft:\n        return css`\n          top: 50%;\n          right: ${SPACE_FROM_EDGE}px;\n          transform: translateY(-50%);\n        `;\n      case AnimationDirection.TopToBottom:\n        return css`\n          top: ${SPACE_FROM_EDGE}px;\n          left: 50%;\n          transform: translateX(-50%);\n        `;\n      case AnimationDirection.LeftToRight:\n        return css`\n          top: 50%;\n          left: ${SPACE_FROM_EDGE}px;\n          transform: translateY(-50%);\n        `;\n      case Rotation.CounterClockwise:\n        return css`\n          bottom: ${SPACE_FROM_EDGE}px;\n          right: ${SPACE_FROM_EDGE}px;\n          transform: translate(-10%, -10%);\n        `;\n\n      case ScaleDirection.ScaleOutBottomLeft:\n        return css`\n          bottom: ${SPACE_FROM_EDGE}px;\n          left: ${SPACE_FROM_EDGE}px;\n        `;\n      case ScaleDirection.ScaleInTopLeft:\n        return css`\n          top: ${SPACE_FROM_EDGE}px;\n          left: ${SPACE_FROM_EDGE}px;\n        `;\n      case ScaleDirection.ScaleOutTopRight:\n        return css`\n          top: ${SPACE_FROM_EDGE}px;\n          right: ${SPACE_FROM_EDGE}px;\n        `;\n      case ScaleDirection.ScaleInBottomRight:\n        return css`\n          bottom: ${SPACE_FROM_EDGE}px;\n          right: ${SPACE_FROM_EDGE}px;\n        `;\n\n      default:\n        return css`\n          bottom: ${SPACE_FROM_EDGE}px;\n          left: 50%;\n          transform: translateX(-50%);\n        `;\n    }\n  }}\n`;\n\nconst HiddenLegend = styled.legend`\n  position: absolute;\n  opacity: 0;\n  clip-path: polygon(0 0);\n  cursor: pointer;\n`;\n\nconst RadioGroup = styled.div`\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n`;\n\nconst translations = {\n  [AnimationDirection.RightToLeft]: _x(\n    'right to left',\n    'animation direction',\n    'web-stories'\n  ),\n  [AnimationDirection.LeftToRight]: _x(\n    'left to right',\n    'animation direction',\n    'web-stories'\n  ),\n  [AnimationDirection.TopToBottom]: _x(\n    'top to bottom',\n    'animation direction',\n    'web-stories'\n  ),\n  [AnimationDirection.BottomToTop]: _x(\n    'bottom to top',\n    'animation direction',\n    'web-stories'\n  ),\n  [Rotation.Clockwise]: _x('clockwise', 'rotation direction', 'web-stories'),\n  [Rotation.CounterClockwise]: _x(\n    'counterclockwise',\n    'rotation direction',\n    'web-stories'\n  ),\n  [ScaleDirection.ScaleIn]: _x('scale in', 'scale direction', 'web-stories'),\n  [ScaleDirection.ScaleOut]: _x('scale out', 'scale direction', 'web-stories'),\n};\n\nconst valueForInternalValue = (value) => {\n  switch (value) {\n    case ScaleDirection.ScaleInTopLeft:\n      return ScaleDirection.ScaleIn;\n    case ScaleDirection.ScaleInBottomRight:\n      return ScaleDirection.ScaleIn;\n    case ScaleDirection.ScaleOutBottomLeft:\n      return ScaleDirection.ScaleOut;\n    case ScaleDirection.ScaleOutTopRight:\n      return ScaleDirection.ScaleOut;\n    default:\n      return value;\n  }\n};\nconst isInternalScaleDirection = (value) =>\n  [...SCALE_DIRECTIONS.IN, ...SCALE_DIRECTIONS.OUT].includes(value);\n\nconst splitCamelCase = (camelCase = '') =>\n  camelCase\n    ?.replace(/([a-z])([A-Z])/g, '$1 $2')\n    ?.toLocaleLowerCase()\n    ?.split(' ') || [];\n\nconst getPrefixFromCamelCase = (camelCase = '') =>\n  splitCamelCase(camelCase)?.[0];\n\nconst getPostfixFromCamelCase = (camelCase = '') => {\n  const split = splitCamelCase(camelCase);\n  return split[split.length - 1];\n};\n\nconst STANDARD_NAV_ORDER = [\n  AnimationDirection.TopToBottom,\n  AnimationDirection.RightToLeft,\n  AnimationDirection.BottomToTop,\n  AnimationDirection.LeftToRight,\n];\n\nconst SCALE_NAV_ORDER = [\n  ScaleDirection.ScaleInTopLeft,\n  ScaleDirection.ScaleOutTopRight,\n  ScaleDirection.ScaleInBottomRight,\n  ScaleDirection.ScaleOutBottomLeft,\n];\n\nconst sortInputOrderForKeyboardUsability = (\n  directions,\n  directionOrder,\n  isRTL\n) => {\n  const referenceOrder = isRTL ? directionOrder.reverse() : directionOrder;\n\n  return directions.sort(\n    (a, b) => referenceOrder.indexOf(a) - referenceOrder.indexOf(b)\n  );\n};\n\nexport const DirectionRadioInput = ({\n  value,\n  directions = [],\n  onChange,\n  disabled = [],\n  tooltip,\n}) => {\n  const inputRef = useRef();\n  const { isRTL } = useConfig();\n\n  const flattenedDirections = useMemo(() => {\n    const dir = [];\n    if (\n      !directions.includes(ScaleDirection.ScaleOut) &&\n      !directions.includes(ScaleDirection.ScaleIn)\n    ) {\n      dir.push(\n        ...sortInputOrderForKeyboardUsability(\n          directions,\n          STANDARD_NAV_ORDER,\n          isRTL\n        )\n      );\n    } else {\n      const scaleDir = [];\n\n      directions.includes(ScaleDirection.ScaleOut) &&\n        scaleDir.push(...SCALE_DIRECTIONS.OUT);\n      directions.includes(ScaleDirection.ScaleIn) &&\n        scaleDir.push(...SCALE_DIRECTIONS.IN);\n      dir.push(\n        ...sortInputOrderForKeyboardUsability(scaleDir, SCALE_NAV_ORDER, isRTL)\n      );\n    }\n    return dir;\n  }, [directions, isRTL]);\n\n  useRadioNavigation(inputRef);\n\n  return (\n    <Fieldset>\n      <Figure />\n      <HiddenLegend>{__('Which Direction?', 'web-stories')}</HiddenLegend>\n      <RadioGroup ref={inputRef}>\n        {flattenedDirections.map((direction) => {\n          const isDisabled = disabled?.includes(\n            valueForInternalValue(direction)\n          );\n          return (\n            <Label\n              key={direction}\n              aria-label={translations[direction]}\n              htmlFor={direction}\n              direction={direction}\n              disabled={isDisabled}\n            >\n              <Tooltip\n                title={isDisabled ? tooltip : ''}\n                placement={\n                  isInternalScaleDirection(direction)\n                    ? getPostfixFromCamelCase(direction)\n                    : getPrefixFromCamelCase(direction)\n                }\n              >\n                <DirectionIndicator\n                  direction={direction}\n                  selected={value === direction || direction?.includes(value)}\n                  disabled={isDisabled}\n                  onClick={() => onChange(valueForInternalValue(direction))}\n                />\n              </Tooltip>\n            </Label>\n          );\n        })}\n      </RadioGroup>\n    </Fieldset>\n  );\n};\n\nconst directionPropType = PropTypes.oneOf([\n  ...Object.values(AnimationDirection),\n  ...Object.values(Rotation),\n  ...Object.values(ScaleDirection),\n]);\n\nDirectionRadioInput.propTypes = {\n  value: directionPropType,\n  directions: PropTypes.arrayOf(directionPropType),\n  disabled: PropTypes.arrayOf(directionPropType),\n  onChange: PropTypes.func,\n  tooltip: PropTypes.string,\n};\n\nDirection.propTypes = {\n  className: PropTypes.string,\n  direction: directionPropType,\n  selected: PropTypes.bool,\n  disabled: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/dropdownConstants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x, sprintf } from '@googleforcreators/i18n';\nimport {\n  ANIMATION_EFFECTS,\n  BACKGROUND_ANIMATION_EFFECTS,\n  AnimationDirection,\n  ScaleDirection,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport {\n  DropAnimation,\n  FadeInAnimation,\n  FlyInLeftAnimation,\n  FlyInRightAnimation,\n  FlyInTopAnimation,\n  FlyInBottomAnimation,\n  PulseAnimation,\n  RotateInLeftAnimation,\n  RotateInRightAnimation,\n  TwirlInAnimation,\n  WhooshInLeftAnimation,\n  WhooshInRightAnimation,\n  ZoomInAnimation,\n  ZoomOutAnimation,\n  PanTopAnimation,\n  PanRightAnimation,\n  PanBottomAnimation,\n  PanLeftAnimation,\n  PanAndZoomAnimation,\n} from './effectChooserElements';\n\nexport const getDirectionalEffect = (effect, direction) => {\n  if (effectValueExceptions.includes(effect)) {\n    return effect;\n  }\n  return direction ? `${effect} ${direction}`.trim() : effect;\n};\n\nexport const NO_ANIMATION = 'none';\n\nexport const DYNAMIC_PROPERTY_VALUE = 'dynamicPropertyValue';\n\n/**\n * GRID_SIZING is used for how to present effect options visually in dropDown\n */\nexport const GRID_SIZING = {\n  HALF: 'half',\n  QUARTER: 'quarter',\n};\n\n/**\n * Some effects are more complicated or have just 1 prebaked option in the effect drop down.\n * For these we want to make sure we're mapping the appropriate value to the drop down selectedValue\n * which means ignoring direction which `getDirectionalEffect` ties into to give 1 effect several\n * options in the drop down.\n */\nexport const effectValueExceptions = [\n  BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value,\n];\n\n/**\n * backgroundEffectOptions and foregroundEffectOptions are the structure used to generate\n * options for the animation effect menu dynamically.\n * Each option's key is the value that the dropdown will respect as the selectedValue.\n * Inside of each grouping is nested `animation` object\n * which specifies ariaLabel, animation options, true animation name (since some duplicate),\n * the keyframes Element for rendering the animation internal to the dropdown,\n * as well as UI specifications like how much of the grid the item should take up inside the menu\n * and what size font.\n * Everything that is dependent on circumstances - like if the animation is\n * disabled or if there's a tooltip or if the animation is hidden by an experiment\n * is set within the component itself.\n */\n\nexport const backgroundEffectOptions = {\n  NO_ANIMATION: {\n    value: NO_ANIMATION,\n    label: _x('None', 'animation effect', 'web-stories'),\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n    AnimationDirection.LeftToRight\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      AnimationDirection.LeftToRight\n    ),\n    label: _x('Pan Left', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Pan Left', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      panDirection: AnimationDirection.LeftToRight,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: PanLeftAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n    AnimationDirection.RightToLeft\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      AnimationDirection.RightToLeft\n    ),\n    label: _x('Pan Right', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Pan Right', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      panDirection: AnimationDirection.RightToLeft,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: PanRightAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n    AnimationDirection.BottomToTop\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      AnimationDirection.BottomToTop\n    ),\n    label: _x('Pan Up', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Pan Up', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      panDirection: AnimationDirection.BottomToTop,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: PanBottomAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n    AnimationDirection.TopToBottom\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      AnimationDirection.TopToBottom\n    ),\n    label: _x('Pan Down', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Pan Down', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.PAN.value,\n      panDirection: AnimationDirection.TopToBottom,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: PanTopAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n    ScaleDirection.ScaleIn\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n      ScaleDirection.ScaleIn\n    ),\n    label: _x('Zoom In', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Zoom In', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n      zoomDirection: ScaleDirection.ScaleIn,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: ZoomInAnimation,\n      size: 14,\n    },\n  },\n  [getDirectionalEffect(\n    BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n    ScaleDirection.ScaleOut\n  )]: {\n    value: getDirectionalEffect(\n      BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n      ScaleDirection.ScaleOut\n    ),\n    label: _x('Zoom Out', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Zoom Out', 'animation effect', 'web-stories')\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.ZOOM.value,\n      zoomDirection: ScaleDirection.ScaleOut,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: ZoomOutAnimation,\n      size: 20,\n    },\n  },\n  [BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value]: {\n    value: BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value,\n    label: BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.name\n      ),\n      value: BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value,\n      zoomDirection: DYNAMIC_PROPERTY_VALUE,\n      Effect: PanAndZoomAnimation,\n      size: 26,\n    },\n  },\n};\n\nexport const foregroundEffectOptions = {\n  NO_ANIMATION: {\n    value: NO_ANIMATION,\n    label: _x('None', 'animation effect', 'web-stories'),\n  },\n  [ANIMATION_EFFECTS.DROP.value]: {\n    value: ANIMATION_EFFECTS.DROP.value,\n    label: ANIMATION_EFFECTS.DROP.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        ANIMATION_EFFECTS.DROP.name\n      ),\n      value: ANIMATION_EFFECTS.DROP.value,\n      Effect: DropAnimation,\n    },\n  },\n  [ANIMATION_EFFECTS.FADE_IN.value]: {\n    value: ANIMATION_EFFECTS.FADE_IN.value,\n    label: ANIMATION_EFFECTS.FADE_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        ANIMATION_EFFECTS.FADE_IN.name\n      ),\n      value: ANIMATION_EFFECTS.FADE_IN.value,\n      Effect: FadeInAnimation,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.FLY_IN.value,\n    AnimationDirection.LeftToRight\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.FLY_IN.value,\n      AnimationDirection.LeftToRight\n    ),\n    label: ANIMATION_EFFECTS.FLY_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Fly In from Left', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.FLY_IN.value,\n      flyInDirection: AnimationDirection.LeftToRight,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: FlyInLeftAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.FLY_IN.value,\n    AnimationDirection.TopToBottom\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.FLY_IN.value,\n      AnimationDirection.TopToBottom\n    ),\n    label: ANIMATION_EFFECTS.FLY_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Fly In from Top', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.FLY_IN.value,\n      flyInDirection: AnimationDirection.TopToBottom,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: FlyInTopAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.FLY_IN.value,\n    AnimationDirection.BottomToTop\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.FLY_IN.value,\n      AnimationDirection.BottomToTop\n    ),\n    label: ANIMATION_EFFECTS.FLY_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Fly In from Bottom', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.FLY_IN.value,\n      flyInDirection: AnimationDirection.BottomToTop,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: FlyInBottomAnimation,\n      size: 16,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.FLY_IN.value,\n    AnimationDirection.RightToLeft\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.FLY_IN.value,\n      AnimationDirection.RightToLeft\n    ),\n    label: ANIMATION_EFFECTS.FLY_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Fly In from Right', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.FLY_IN.value,\n      flyInDirection: AnimationDirection.RightToLeft,\n      gridSpace: GRID_SIZING.QUARTER,\n      Effect: FlyInRightAnimation,\n      size: 16,\n    },\n  },\n  [ANIMATION_EFFECTS.PULSE.value]: {\n    value: ANIMATION_EFFECTS.PULSE.value,\n    label: ANIMATION_EFFECTS.PULSE.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        ANIMATION_EFFECTS.PULSE.name\n      ),\n      value: ANIMATION_EFFECTS.PULSE.value,\n      Effect: PulseAnimation,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.ROTATE_IN.value,\n    AnimationDirection.LeftToRight\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.ROTATE_IN.value,\n      AnimationDirection.LeftToRight\n    ),\n    label: _x('Rotate', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Rotate In from Left', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.ROTATE_IN.value,\n      rotateInDirection: AnimationDirection.LeftToRight,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: RotateInLeftAnimation,\n      size: 18,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.ROTATE_IN.value,\n    AnimationDirection.RightToLeft\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.ROTATE_IN.value,\n      AnimationDirection.RightToLeft\n    ),\n    label: _x('Rotate', 'animation effect', 'web-stories'),\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Rotate In from Right', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.ROTATE_IN.value,\n      rotateInDirection: AnimationDirection.RightToLeft,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: RotateInRightAnimation,\n      size: 18,\n    },\n  },\n  [ANIMATION_EFFECTS.TWIRL_IN.value]: {\n    value: ANIMATION_EFFECTS.TWIRL_IN.value,\n    label: ANIMATION_EFFECTS.TWIRL_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        ANIMATION_EFFECTS.TWIRL_IN.name\n      ),\n      value: ANIMATION_EFFECTS.TWIRL_IN.value,\n      Effect: TwirlInAnimation,\n      size: 26,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.WHOOSH_IN.value,\n    AnimationDirection.LeftToRight\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.WHOOSH_IN.value,\n      AnimationDirection.LeftToRight\n    ),\n    label: ANIMATION_EFFECTS.WHOOSH_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Whoosh In from Left', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.WHOOSH_IN.value,\n      whooshInDirection: AnimationDirection.LeftToRight,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: WhooshInLeftAnimation,\n      size: 20,\n    },\n  },\n  [getDirectionalEffect(\n    ANIMATION_EFFECTS.WHOOSH_IN.value,\n    AnimationDirection.RightToLeft\n  )]: {\n    value: getDirectionalEffect(\n      ANIMATION_EFFECTS.WHOOSH_IN.value,\n      AnimationDirection.RightToLeft\n    ),\n    label: ANIMATION_EFFECTS.WHOOSH_IN.name,\n    animation: {\n      ariaLabel: sprintf(\n        /* translators: %s: animation effect. */\n        __('\"%s\" Effect', 'web-stories'),\n        _x('Whoosh In from Right', 'animation effect', 'web-stories')\n      ),\n      value: ANIMATION_EFFECTS.WHOOSH_IN.value,\n      whooshInDirection: AnimationDirection.RightToLeft,\n      gridSpace: GRID_SIZING.HALF,\n      Effect: WhooshInRightAnimation,\n      size: 20,\n    },\n  },\n  [getDirectionalEffect(ANIMATION_EFFECTS.ZOOM.value, ScaleDirection.ScaleIn)]:\n    {\n      value: getDirectionalEffect(\n        ANIMATION_EFFECTS.ZOOM.value,\n        ScaleDirection.ScaleIn\n      ),\n      label: _x('Scale In', 'animation effect', 'web-stories'),\n      animation: {\n        ariaLabel: sprintf(\n          /* translators: %s: animation effect. */\n          __('\"%s\" Effect', 'web-stories'),\n          _x('Scale In', 'animation effect', 'web-stories')\n        ),\n        value: ANIMATION_EFFECTS.ZOOM.value,\n        scaleDirection: ScaleDirection.ScaleIn,\n        gridSpace: GRID_SIZING.HALF,\n        Effect: ZoomInAnimation,\n        size: 14,\n      },\n    },\n  [getDirectionalEffect(ANIMATION_EFFECTS.ZOOM.value, ScaleDirection.ScaleOut)]:\n    {\n      value: getDirectionalEffect(\n        ANIMATION_EFFECTS.ZOOM.value,\n        ScaleDirection.ScaleOut\n      ),\n      label: __('Scale Out', 'web-stories'),\n      animation: {\n        ariaLabel: sprintf(\n          /* translators: %s: animation effect. */\n          __('\"%s\" Effect', 'web-stories'),\n          _x('Scale Out', 'animation effect', 'web-stories')\n        ),\n        value: ANIMATION_EFFECTS.ZOOM.value,\n        scaleDirection: ScaleDirection.ScaleOut,\n        gridSpace: GRID_SIZING.HALF,\n        Effect: ZoomOutAnimation,\n        size: 20,\n      },\n    },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/dropdownItem.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../../../tooltip';\nimport { AnimationListItem, ContentWrapper } from './styles';\nimport { ANIMATION_DROPDOWN_OPTION_PROP_TYPE } from './types';\n\nconst DropDownItem = forwardRef(({ option, ...rest }, ref) => (\n  <AnimationListItem\n    ref={ref}\n    aria-label={option.animation?.ariaLabel || option.label}\n    disabled={option.disabled}\n    aria-disabled={option.disabled}\n    size={option.animation?.size}\n    gridSpace={option.animation?.gridSpace}\n    noEffect={!option.animation?.Effect}\n    {...rest}\n  >\n    <Tooltip title={option?.tooltip || ''}>\n      <ContentWrapper>{option.label}</ContentWrapper>\n      {option.animation?.Effect && (\n        <option.animation.Effect>{option.label}</option.animation.Effect>\n      )}\n    </Tooltip>\n  </AnimationListItem>\n));\n\nexport default DropDownItem;\n\nDropDownItem.displayName = 'DropDownItem';\n\nDropDownItem.propTypes = {\n  option: PropTypes.shape(ANIMATION_DROPDOWN_OPTION_PROP_TYPE),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/effectChooserDropdown.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef, useCallback, useMemo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, _x } from '@googleforcreators/i18n';\nimport { css } from 'styled-components';\nimport { DropDown, Placement } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../../../shared/styles';\nimport {\n  backgroundEffectOptions,\n  NO_ANIMATION,\n  foregroundEffectOptions,\n  getDirectionalEffect,\n} from './dropdownConstants';\nimport { ANIMATION_DIRECTION_PROP_TYPE } from './types';\nimport getDisabledBackgroundEffects from './utils/getDisabledBackgroundEffects';\nimport generateDynamicProps from './utils/generateDynamicProps';\nimport {\n  styleOverrideForSelectButton,\n  styleOverrideForAnimationEffectMenu,\n} from './styles';\nimport DropDownItem from './dropdownItem';\n\nconst EffectChooserDropdown = forwardRef(function EffectChooserDropdown(\n  {\n    onAnimationSelected,\n    onNoEffectSelected,\n    isBackgroundEffects = false,\n    selectedEffectType,\n    disabledTypeOptionsMap,\n    direction,\n    selectButtonStylesOverride,\n    disabled = false,\n  },\n  ref\n) {\n  const selectedValue = useMemo(\n    () => getDirectionalEffect(selectedEffectType, direction),\n    [selectedEffectType, direction]\n  );\n\n  // Determine if any background effects are disabled due to element positioning\n  const disabledBackgroundEffects = useMemo(\n    () =>\n      isBackgroundEffects &&\n      getDisabledBackgroundEffects(\n        backgroundEffectOptions,\n        disabledTypeOptionsMap\n      ),\n    [disabledTypeOptionsMap, isBackgroundEffects]\n  );\n\n  // Set up dropdown options by effect type (background vs foreground)\n  const expandedPlacement = isBackgroundEffects\n    ? Placement.Bottom\n    : Placement.Top;\n  const animationOptionsObject = isBackgroundEffects\n    ? backgroundEffectOptions\n    : foregroundEffectOptions;\n\n  const availableAnimationOptions = Object.values(animationOptionsObject);\n\n  const assembledOptions = useMemo(\n    () =>\n      availableAnimationOptions?.map((option) => {\n        const isDisabled =\n          isBackgroundEffects &&\n          disabledBackgroundEffects.includes(option.value);\n        return {\n          ...option,\n          disabled: isDisabled,\n          tooltip:\n            isDisabled &&\n            disabledTypeOptionsMap[option.animation?.value]?.tooltip,\n        };\n      }),\n    [\n      availableAnimationOptions,\n      isBackgroundEffects,\n      disabledBackgroundEffects,\n      disabledTypeOptionsMap,\n    ]\n  );\n\n  const handleSelect = useCallback(\n    (event, value) => {\n      event.preventDefault();\n      if (value === NO_ANIMATION) {\n        Boolean(selectedValue) && onNoEffectSelected();\n        return;\n      }\n\n      const selectedAnimation = animationOptionsObject[value]?.animation;\n      const animationWithDynamicProps = generateDynamicProps({\n        animation: selectedAnimation,\n        disabledTypeOptionsMap,\n      });\n      onAnimationSelected({\n        animation: animationWithDynamicProps.value,\n        panDir: animationWithDynamicProps?.panDirection,\n        zoomDirection: animationWithDynamicProps?.zoomDirection,\n        flyInDir: animationWithDynamicProps?.flyInDirection,\n        rotateInDir: animationWithDynamicProps?.rotateInDirection,\n        whooshInDir: animationWithDynamicProps?.whooshInDirection,\n        scaleDirection: animationWithDynamicProps?.scaleDirection,\n      });\n    },\n    [\n      animationOptionsObject,\n      disabledTypeOptionsMap,\n      onAnimationSelected,\n      selectedValue,\n      onNoEffectSelected,\n    ]\n  );\n\n  const innerStyleOverrides =\n    selectedValue && selectedValue !== NO_ANIMATION\n      ? styleOverrideForSelectButton\n      : focusStyle;\n  const buttonStyleOverride = css`\n    ${innerStyleOverrides}\n    ${typeof selectButtonStylesOverride !== 'undefined' &&\n    selectButtonStylesOverride}\n  `;\n\n  return (\n    <DropDown\n      ref={ref}\n      options={assembledOptions}\n      placeholder={_x('None', 'animation effect', 'web-stories')}\n      selectedValue={selectedValue}\n      ariaLabel={__('Animation: Effect Chooser', 'web-stories')}\n      menuStylesOverride={styleOverrideForAnimationEffectMenu}\n      renderItem={DropDownItem}\n      onMenuItemClick={handleSelect}\n      placement={expandedPlacement}\n      isKeepMenuOpenOnSelection\n      selectButtonStylesOverride={buttonStyleOverride}\n      disabled={disabled}\n    />\n  );\n});\n\nEffectChooserDropdown.propTypes = {\n  onAnimationSelected: PropTypes.func.isRequired,\n  direction: ANIMATION_DIRECTION_PROP_TYPE,\n  isBackgroundEffects: PropTypes.bool,\n  selectedEffectType: PropTypes.string,\n  onNoEffectSelected: PropTypes.func.isRequired,\n  disabledTypeOptionsMap: PropTypes.objectOf(\n    PropTypes.shape({\n      tooltip: PropTypes.string,\n      options: PropTypes.arrayOf(PropTypes.string),\n    })\n  ),\n  disabled: PropTypes.bool,\n  selectButtonStylesOverride: PropTypes.oneOfType([\n    PropTypes.object,\n    PropTypes.array,\n  ]),\n};\n\nexport default EffectChooserDropdown;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/effectChooserElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { keyframes } from 'styled-components';\n\nexport const GRID_ITEM_HEIGHT = 56;\n\nexport const BaseAnimationCell = styled.div`\n  display: none;\n  transform-origin: 50% 50%;\n`;\n\nconst dropKeyframes = keyframes`\n  0% {\n    transform: translateY(-100%);\n    animation-timing-function: cubic-bezier(.75,.05,.86,.08);\n  }\n  15% {\n    transform: translateY(0%);\n    animation-timing-function: cubic-bezier(.22,.61,.35,1);\n  }\n  26% {\n    transform: translateY(-62%);\n    animation-timing-function: cubic-bezier(.75,.05,.86,.08);\n  }\n  37% {\n    transform: translateY(-0%);\n    animation-timing-function: cubic-bezier(.22,.61,.35,1);\n  }\n  41.5% {\n    transform: translateY(-30%);\n    animation-timing-function: cubic-bezier(.75,.05,.86,.08);\n  }\n  50%, 100% {\n    transform: translateY(0%);\n    animation-timing-function: cubic-bezier(.22,.61,.35,1);\n  }\n`;\n\nexport const DropAnimation = styled(BaseAnimationCell)`\n  animation: ${dropKeyframes} 3.2s linear infinite;\n`;\n\nconst fadeInKeyframes = keyframes`\n  0% {\n    opacity: 0;\n  }\n  50%, 100% {\n    opacity: 1;\n  }\n`;\n\nexport const FadeInAnimation = styled(BaseAnimationCell)`\n  animation: ${fadeInKeyframes} 2.5s linear infinite;\n`;\n\nconst flyInLeftKeyframes = keyframes`\n  0% {\n    transform: translateX(-100%);\n  }\n  50%, 100% {\n    transform: translateX(0%);\n  }\n`;\n\nexport const FlyInLeftAnimation = styled(BaseAnimationCell)`\n  animation: ${flyInLeftKeyframes} 2s linear infinite;\n`;\n\nconst flyInRightKeyframes = keyframes`\n  0% {\n    transform: translateX(100%);\n  }\n  50%, 100% {\n    transform: translateX(0%);\n  }\n`;\n\nexport const FlyInRightAnimation = styled(BaseAnimationCell)`\n  animation: ${flyInRightKeyframes} 2s linear infinite;\n`;\n\nconst flyInTopKeyframes = keyframes`\n  0% {\n    transform: translateY(-100%);\n  }\n  50%, 100% {\n    transform: translateY(0%);\n  }\n`;\n\nexport const FlyInTopAnimation = styled(BaseAnimationCell)`\n  animation: ${flyInTopKeyframes} 2s linear infinite;\n`;\n\nconst flyInBottomKeyframes = keyframes`\n  0% {\n    transform: translateY(100%);\n  }\n  50%, 100% {\n    transform: translateY(0%);\n  }\n`;\n\nexport const FlyInBottomAnimation = styled(BaseAnimationCell)`\n  animation: ${flyInBottomKeyframes} 2s linear infinite;\n`;\n\nconst pulseKeyframes = keyframes`\n  0% {\n    transform: scale(1);\n  }\n  12.5% {\n    transform: scale(0.75);\n  }\n  37.5% {\n    transform: scale(1.25);\n  }\n  50%, 100% {\n    transform: scale(1);\n  }\n`;\n\nexport const PulseAnimation = styled(BaseAnimationCell)`\n  animation: ${pulseKeyframes} 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;\n`;\n\nconst rotateInLeftKeyframes = keyframes`\n  0% {\n    transform: translateX(-100%) rotate(-360deg);\n  }\n  50%, 100% {\n    transform: translateX(0%);\n  }\n`;\n\nexport const RotateInLeftAnimation = styled(BaseAnimationCell)`\n  animation: ${rotateInLeftKeyframes} 2s linear infinite;\n`;\n\nconst rotateInRightKeyframes = keyframes`\n  0% {\n    transform: translateX(100%) rotate(360deg);\n  }\n  50%, 100% {\n    transform: translateX(0%);\n  }\n`;\n\nexport const RotateInRightAnimation = styled(BaseAnimationCell)`\n  animation: ${rotateInRightKeyframes} 2s linear infinite;\n`;\n\nconst twirlInKeyframes = keyframes`\n  0% {\n    transform: rotate(-540deg) scale(0.1);\n    opacity: 0;\n  }\n  50%, 100% {\n    transform: none;\n    opacity: 1;\n  }\n`;\n\nexport const TwirlInAnimation = styled(BaseAnimationCell)`\n  animation: ${twirlInKeyframes} 2s cubic-bezier(0.2, 0.75, 0.4, 1) infinite;\n`;\n\nconst whooshInLeftKeyframes = keyframes`\n  0% {\n    transform: translateX(-100%);\n    opacity: 0;\n  }\n  50%, 100% {\n    transform: translateX(0%);\n    opacity: 1;\n  }\n`;\n\nexport const WhooshInLeftAnimation = styled(BaseAnimationCell)`\n  animation: ${whooshInLeftKeyframes} 2s cubic-bezier(0, 0, 0.2, 1) infinite;\n`;\n\nconst whooshInRightKeyframes = keyframes`\n  0% {\n    transform: translateX(100%);\n    opacity: 0;\n  }\n  50%, 100% {\n    transform: translateX(0%);\n    opacity: 1;\n  }\n`;\n\nexport const WhooshInRightAnimation = styled(BaseAnimationCell)`\n  animation: ${whooshInRightKeyframes} 2s cubic-bezier(0, 0, 0.2, 1) infinite;\n`;\n\nconst panLeftKeyframes = keyframes`\n  0% {\n    transform: translateX(-100%) scale(1.5);\n  }\n  50%, 100% {\n    transform: translateX(200%) scale(1.5);\n  }\n`;\n\nexport const PanLeftAnimation = styled(BaseAnimationCell)`\n  animation: ${panLeftKeyframes} 3s linear infinite;\n`;\n\nconst panRightKeyframes = keyframes`\n  0% {\n    transform: translateX(100%) scale(1.5);\n  }\n  50%, 100% {\n    transform: translateX(-200%) scale(1.5);\n  }\n`;\n\nexport const PanRightAnimation = styled(BaseAnimationCell)`\n  animation: ${panRightKeyframes} 3s linear infinite;\n`;\n\nconst panTopKeyframes = keyframes`\n  0% {\n    transform: translateY(-100%) scale(1.5);\n  }\n  50%, 100% {\n    transform: translateY(200%) scale(1.5);\n  }\n`;\n\nexport const PanTopAnimation = styled(BaseAnimationCell)`\n  animation: ${panTopKeyframes} 3s linear infinite;\n`;\n\nconst panBottomKeyframes = keyframes`\n  0% {\n    transform: translateY(100%) scale(1.5);\n  }\n  50%, 100% {\n    transform: translateY(-200%) scale(1.5);\n  }\n`;\n\nexport const PanBottomAnimation = styled(BaseAnimationCell)`\n  animation: ${panBottomKeyframes} 3s linear infinite;\n`;\n\nconst zoomInKeyframes = keyframes`\n  0% {\n    opacity: 0;\n    transform: scale(0);\n  }\n  50%, 100% {\n    opacity: 1;\n    transform: scale(1);\n  }\n`;\n\nexport const ZoomInAnimation = styled(BaseAnimationCell)`\n  animation: ${zoomInKeyframes} 2s linear infinite;\n`;\n\nconst zoomOutKeyframes = keyframes`\n  0% {\n    opacity: 0;\n    transform: scale(2);\n  }\n  50%, 100% {\n    opacity: 1;\n    transform: scale(1);\n  }\n`;\n\nexport const ZoomOutAnimation = styled(BaseAnimationCell)`\n  animation: ${zoomOutKeyframes} 2s linear infinite;\n`;\n\nconst panAndZoomKeyframes = keyframes`\n  0% {\n    opacity: 0;\n    transform: translate3d(-50%, 0, 0) scale(2);\n  }\n  50%, 100% {\n    opacity: 1;\n    transform: none;\n  }\n`;\n\nexport const PanAndZoomAnimation = styled(BaseAnimationCell)`\n  animation: ${panAndZoomKeyframes} 2s linear infinite;\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as EffectChooserDropdown } from './effectChooserDropdown';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/styles.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\n/**\n * Internal dependencies\n */\nimport { INPUT_HEIGHT } from '../constants';\nimport { focusStyle } from '../../../shared/styles';\nimport { BaseAnimationCell, GRID_ITEM_HEIGHT } from './effectChooserElements';\nimport { GRID_SIZING } from './dropdownConstants';\n\nexport const ContentWrapper = styled.div`\n  display: inline-block;\n`;\n\nconst getGridColumnStart = (gridSpace) => {\n  switch (gridSpace) {\n    case GRID_SIZING.HALF:\n      return 'span 2';\n\n    case GRID_SIZING.QUARTER:\n      return 'span 1';\n\n    default:\n      return 'span 4';\n  }\n};\n\nexport const AnimationListItem = styled.li`\n  border: none;\n  background: ${({ active, theme }) =>\n    active\n      ? theme.colors.interactiveBg.secondaryPress\n      : theme.colors.interactiveBg.secondaryNormal};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  height: ${GRID_ITEM_HEIGHT}px;\n  position: relative;\n  grid-column-start: ${({ gridSpace }) => getGridColumnStart(gridSpace)};\n  overflow: hidden;\n  font-family: 'Teko', sans-serif;\n  font-size: ${({ size = 28 }) => size}px;\n  line-height: 1;\n  color: ${({ theme }) => theme.colors.fg.primary};\n  text-transform: uppercase;\n  transition: background 0.1s linear;\n  margin: 0;\n  /* Account for tooltip nested inside of list items wrapping actual content */\n  & > div {\n    height: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    text-align: center;\n  }\n\n  &[aria-disabled='true'] {\n    background: ${({ theme }) => theme.colors.interactiveBg.disable};\n  }\n\n  &:hover:not([aria-disabled='true']) {\n    cursor: pointer;\n  }\n\n  &:hover:not([aria-disabled='true']),\n  &:focus:not([aria-disabled='true']) {\n    background: ${({ active, theme }) =>\n      active\n        ? theme.colors.interactiveBg.secondaryPress\n        : theme.colors.interactiveBg.secondaryHover};\n\n    ${BaseAnimationCell} {\n      display: inline-block;\n    }\n    ${ContentWrapper} {\n      display: none;\n    }\n  }\n\n  ${({ noEffect }) =>\n    noEffect &&\n    css`\n      height: 36px;\n      font-size: 14px;\n      text-transform: none;\n\n      /* noEffect doesn't have an active style so we want to just leave the display alone */\n      ${ContentWrapper} {\n        display: inline-block !important;\n      }\n    `}\n\n  ${focusStyle};\n`;\n\nexport const styleOverrideForAnimationEffectMenu = css`\n  display: inline-block;\n  margin-top: 0;\n  padding: 16px 4px 16px 16px;\n  ul {\n    display: grid;\n    justify-content: center;\n    gap: 12px 4px;\n    grid-template-columns: repeat(4, 1fr);\n    position: relative;\n  }\n`;\n\nexport const styleOverrideForSelectButton = ({ theme }) => css`\n  margin: -1px -1px 0 -1px;\n  width: calc(100% + 2px);\n  border-color: transparent transparent ${theme.colors.border.defaultNormal}\n    transparent;\n  height: ${INPUT_HEIGHT}px;\n  &:hover {\n    border-color: transparent transparent ${theme.colors.border.defaultNormal}\n      transparent;\n  }\n\n  ${focusStyle}\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/types.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  AnimationDirection,\n  ScaleDirection,\n} from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { GRID_SIZING } from './dropdownConstants';\n\nconst ANIMATION_OPTION_PROP_TYPE = {\n  ariaLabel: PropTypes.string,\n  value: PropTypes.string.isRequired,\n  Effect: PropTypes.any,\n  gridSpace: PropTypes.oneOf(Object.values(GRID_SIZING)),\n  size: PropTypes.number,\n  scaleDirection: PropTypes.oneOf(Object.values(ScaleDirection)),\n  panDirection: PropTypes.oneOf(Object.values(AnimationDirection)),\n  zoomDirection: PropTypes.oneOf(Object.values(ScaleDirection)),\n  flyInDirection: PropTypes.oneOf(Object.values(AnimationDirection)),\n  rotateInDirection: PropTypes.oneOf(Object.values(AnimationDirection)),\n  whooshInDirection: PropTypes.oneOf(Object.values(AnimationDirection)),\n};\n\nexport const ANIMATION_DROPDOWN_OPTION_PROP_TYPE = {\n  value: PropTypes.string.isRequired,\n  label: PropTypes.string.isRequired,\n  animation: PropTypes.shape(ANIMATION_OPTION_PROP_TYPE),\n};\n\nexport const ANIMATION_DIRECTION_PROP_TYPE = PropTypes.oneOf([\n  ...Object.values(AnimationDirection),\n  ...Object.values(ScaleDirection),\n  false,\n]);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/utils/generateDynamicProps.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport hasDynamicProperty from './hasDynamicProperty';\nimport updateDynamicProps from './updateDynamicProps';\n\nconst generateDynamicProps = ({ animation, disabledTypeOptionsMap }) => {\n  return hasDynamicProperty(animation)\n    ? updateDynamicProps({\n        animation,\n        disabledOptions: disabledTypeOptionsMap[animation.value]?.options,\n      })\n    : animation;\n};\n\nexport default generateDynamicProps;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/utils/getDisabledBackgroundEffects.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  effectValueExceptions,\n  getDirectionalEffect,\n} from '../dropdownConstants';\n\nconst getDisabledBackgroundEffects = (\n  backgroundEffectOptions,\n  disabledTypeOptionsMap\n) => {\n  const disabledDirectionalEffects = Object.entries(disabledTypeOptionsMap)\n    // rn we don't ever disable the exceptions, but do dynamic props instead.\n    .filter(([effect]) => effectValueExceptions.indexOf(effect) === -1)\n    .map(([effect, val]) => [effect, val.options])\n    .reduce(\n      (directionalEffects, [effect, directions]) => [\n        ...directionalEffects,\n        ...(directions || []).map((dir) => getDirectionalEffect(effect, dir)),\n      ],\n      []\n    );\n  return Object.keys(backgroundEffectOptions).filter((directionalEffect) =>\n    disabledDirectionalEffects.includes(directionalEffect)\n  );\n};\n\nexport default getDisabledBackgroundEffects;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/utils/hasDynamicProperty.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { DYNAMIC_PROPERTY_VALUE } from '../dropdownConstants';\n\nconst hasDynamicProperty = (animation) => {\n  return Object.values(animation).includes(DYNAMIC_PROPERTY_VALUE);\n};\n\nexport default hasDynamicProperty;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/utils/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as generateDynamicProps } from './generateDynamicProps';\nexport { default as getDisabledBackgroundEffects } from './getDisabledBackgroundEffects';\nexport { default as hasDynamicProperty } from './hasDynamicProperty';\nexport { default as updateDynamicProps } from './updateDynamicProps';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectChooserDropdown/utils/updateDynamicProps.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  BACKGROUND_ANIMATION_EFFECTS,\n  AnimationDirection,\n  ScaleDirection,\n} from '@googleforcreators/animation';\n\nconst updateDynamicProps = ({ animation, disabledOptions = [] }) => {\n  // we don't want to have a disabled direction initially selected either.\n  const panDirection =\n    animation.panDirection && !disabledOptions.includes(animation.panDirection)\n      ? animation.panDirection\n      : Object.values(AnimationDirection).filter(\n          (direction) => !disabledOptions.includes(direction)\n        )?.[0] || undefined;\n\n  switch (animation.value) {\n    case BACKGROUND_ANIMATION_EFFECTS.PAN_AND_ZOOM.value:\n      return {\n        ...animation,\n        // Default zoomDirection to scale in unless disabled\n        zoomDirection: disabledOptions.includes(ScaleDirection.ScaleIn)\n          ? ScaleDirection.ScaleOut\n          : ScaleDirection.ScaleIn,\n        panDirection,\n      };\n    default:\n      return animation;\n  }\n};\n\nexport default updateDynamicProps;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { NumericInput, DropDown } from '@googleforcreators/design-system';\nimport {\n  FieldType,\n  AnimationDirection,\n  Rotation,\n  ScaleDirection,\n  GeneralAnimationPropTypes,\n  AnimationFormPropTypes,\n} from '@googleforcreators/animation';\n/**\n * Internal dependencies\n */\nimport { inputContainerStyleOverride } from '../../shared/styles';\nimport { DirectionRadioInput } from './directionRadioInput';\nimport { INPUT_HEIGHT } from './constants';\n\nconst outerGridBordersCss = css`\n  border-radius: 0;\n  border-color: ${({ theme }) => theme.colors.border.defaultNormal} transparent\n    transparent transparent;\n`;\n\nconst StyledInput = styled(NumericInput)`\n  height: ${INPUT_HEIGHT}px;\n  div {\n    height: calc(100% + 1px);\n    ${outerGridBordersCss}\n    &:focus-within {\n      border-radius: ${({ theme }) => theme.borders.radius.small};\n    }\n  }\n`;\n\nconst StyledDropDown = styled(DropDown)`\n  button {\n    height: 46px;\n    ${outerGridBordersCss}\n    &:hover {\n      ${outerGridBordersCss}\n    }\n    &:focus-visible {\n      border-radius: ${({ theme }) => theme.borders.radius.small};\n    }\n  }\n`;\n\nconst allAnimations = [\n  ...Object.values(AnimationDirection),\n  ...Object.values(Rotation),\n  ...Object.values(ScaleDirection),\n];\n\nfunction EffectInput({\n  effectProps,\n  effectConfig,\n  field,\n  onChange,\n  disabledOptions,\n  disabled = false,\n  tooltip,\n}) {\n  const directionControlOnChange = useCallback(\n    (value) => onChange(value, true),\n    [onChange]\n  );\n\n  const _disabledOptions = useMemo(() => {\n    return disabled ? allAnimations : disabledOptions;\n  }, [disabledOptions, disabled]);\n\n  const valueForField = effectConfig[field] ?? effectProps[field].defaultValue;\n  const isFloat = effectProps[field].type === FieldType.Float;\n  switch (effectProps[field].type) {\n    case FieldType.Dropdown:\n      return (\n        <StyledDropDown\n          options={(effectProps[field].values || []).map(\n            ({ name, ...rest }) => ({\n              ...rest,\n              label: name,\n              disabled: disabled || disabledOptions.includes(rest.value),\n            })\n          )}\n          placeholder={__('Select a value', 'web-stories')}\n          ariaLabel={__('Select effect value', 'web-stories')}\n          isKeepMenuOpenOnSelection={false}\n          selectedValue={valueForField}\n          onMenuItemClick={(evt) => onChange(evt.target.value, true)}\n          disabled={disabled}\n        />\n      );\n    case FieldType.DirectionPicker:\n      return (\n        <DirectionRadioInput\n          value={valueForField}\n          directions={effectProps[field].values}\n          onChange={directionControlOnChange}\n          disabled={_disabledOptions}\n          tooltip={tooltip}\n        />\n      );\n    default:\n      return (\n        <StyledInput\n          aria-label={effectProps[field].label}\n          suffix={effectProps[field].label}\n          unit={effectProps[field].unit}\n          value={valueForField}\n          min={0}\n          onChange={(evt) =>\n            onChange(\n              isFloat\n                ? Number.parseFloat(evt.target.value)\n                : Number.parseInt(evt.target.value),\n              true\n            )\n          }\n          isFloat={isFloat}\n          containerStyleOverride={inputContainerStyleOverride}\n          disabled={disabled}\n        />\n      );\n  }\n}\n\nEffectInput.propTypes = {\n  effectProps: AnimationFormPropTypes.isRequired,\n  effectConfig: PropTypes.shape(GeneralAnimationPropTypes).isRequired,\n  field: PropTypes.string.isRequired,\n  onChange: PropTypes.func.isRequired,\n  disabledOptions: PropTypes.arrayOf(PropTypes.string),\n  disabled: PropTypes.bool,\n  tooltip: PropTypes.string,\n};\n\nexport default EffectInput;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/effectPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  ANIMATION_EFFECTS,\n  ANIMATION_PARTS,\n  BACKGROUND_ANIMATION_EFFECTS,\n  FieldType,\n  getAnimationEffectFields,\n  AnimationProps,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport EffectInput from './effectInput';\n\nexport function getEffectName(type) {\n  return (\n    [\n      ...Object.values(ANIMATION_EFFECTS),\n      ...Object.values(ANIMATION_PARTS),\n      ...Object.values(BACKGROUND_ANIMATION_EFFECTS),\n    ].find((o) => o.value === type)?.name || ''\n  );\n}\n\nexport function getEffectDirection(effect = {}) {\n  if (effect.zoomDirection && effect.panDir) {\n    return false;\n  } else if (effect.zoomDirection) {\n    return effect.zoomDirection;\n  } else if (effect.scaleDirection) {\n    return effect.scaleDirection;\n  } else if (effect.flyInDir) {\n    return effect.flyInDir;\n  } else if (effect.rotateInDir) {\n    return effect.rotateInDir;\n  } else if (effect.whooshInDir) {\n    return effect.whooshInDir;\n  } else if (effect.panDir) {\n    return effect.panDir;\n  }\n  return false;\n}\nconst AnimationGrid = styled.div`\n  display: grid;\n  grid-template-columns: auto auto;\n`;\n\nconst AnimationGridField = styled.div(\n  ({ isRotationComponent, isHalfWidthField }) => [\n    {\n      gridColumn: '1/3',\n    },\n    isRotationComponent && {\n      gridRow: '1/3',\n      gridColumn: 'auto',\n    },\n    isHalfWidthField && {\n      gridColumn: 'auto',\n    },\n  ]\n);\n\nfunction EffectPanel({\n  animation: { id, type, ...config },\n  onChange,\n  disabledTypeOptionsMap,\n  disabled = false,\n}) {\n  const fields = getAnimationEffectFields(type);\n\n  const handleInputChange = useCallback(\n    (updates, submitArg) => {\n      onChange(\n        {\n          id,\n          type,\n          ...config,\n          ...updates,\n        },\n        submitArg\n      );\n    },\n    [id, type, config, onChange]\n  );\n\n  const containsVisualPicker = useMemo(() => {\n    return Object.keys(fields).reduce((memo, current) => {\n      return (\n        fields[current].type === FieldType.DirectionPicker ||\n        fields[current].type === FieldType.RotationPicker ||\n        memo\n      );\n    }, false);\n  }, [fields]);\n\n  const content = Object.keys(fields).map((field, index) => (\n    <AnimationGridField\n      key={field}\n      isRotationComponent={containsVisualPicker && index === 0}\n      isHalfWidthField={containsVisualPicker && (index === 1 || index === 2)}\n    >\n      <EffectInput\n        effectProps={fields}\n        effectConfig={config}\n        field={field}\n        onChange={(value, submitArg) => {\n          const fittedValue =\n            typeof value === 'number' ? Math.max(value, 0) : value;\n          handleInputChange({ [field]: fittedValue }, submitArg);\n        }}\n        disabledOptions={disabledTypeOptionsMap[type]?.options || []}\n        disabled={disabled}\n        tooltip={disabledTypeOptionsMap[type]?.tooltip}\n      />\n    </AnimationGridField>\n  ));\n\n  return <AnimationGrid>{content}</AnimationGrid>;\n}\n\nEffectPanel.propTypes = {\n  animation: PropTypes.shape(AnimationProps),\n  onChange: PropTypes.func.isRequired,\n  disabledTypeOptionsMap: PropTypes.objectOf(\n    PropTypes.shape({\n      tooltip: PropTypes.string,\n      options: PropTypes.arrayOf(PropTypes.string),\n    })\n  ),\n  disabled: PropTypes.bool,\n};\n\nexport default EffectPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './animation';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/karma/animation.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryAnimationState } from '@googleforcreators/animation';\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma/fixture';\nimport { useStory } from '../../../../../app';\n\ndescribe('Animation Panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getCurrentPage() {\n    const {\n      state: { currentPage },\n    } = await fixture.renderHook(() => useStory());\n    return currentPage;\n  }\n\n  it('should render the animation panel when an element is selected.', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.editor.sidebar.designPanel.animation;\n    expect(panel).not.toBeNull();\n  });\n\n  it('should not render the animation panel when multiple elements are selected.', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    // add shape to canvas\n    await fixture.editor.library.shapesTab.click();\n    await fixture.events.click(fixture.editor.library.shapes.shape('Triangle'));\n\n    // add text to canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await fixture.editor.canvas.framesLayer.waitFocusedWithin();\n\n    // select both text and shape elements\n    await fixture.events.keyboard.down('Shift');\n    const triangle = fixture.editor.canvas.framesLayer.frames[1].node;\n    await fixture.events.click(triangle);\n    await fixture.events.keyboard.up('Shift');\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.screen.queryByRole('region', {\n      name: /^Animation$/,\n    });\n    expect(panel).toBeNull();\n  });\n\n  // TODO #6953\n  // eslint-disable-next-line jasmine/no-disabled-tests\n  xit('can click the animation chooser and select an effect.', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.editor.sidebar.designPanel.animation;\n\n    const effectChooser = panel.effectChooser;\n    await fixture.events.click(effectChooser);\n    await fixture.events.sleep(300);\n    const fadeIn = fixture.screen.getByRole('option', {\n      name: /^\"Fade In\" Effect$/,\n    });\n    await fixture.events.click(fadeIn);\n    await fixture.events.sleep(300);\n    expect(effectChooser.innerText).toBe('Fade In');\n  });\n\n  it('replaces an existing effect with a new one.', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.editor.sidebar.designPanel.animation;\n\n    const effectChooser = panel.effectChooser;\n    await fixture.events.click(effectChooser);\n\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n\n    expect(effectChooser.innerText).toBe('Fade In');\n\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Drop\" Effect$/ })\n    );\n\n    expect(effectChooser.innerText).toBe('Drop');\n  });\n\n  it('plays the animation when a control in the panel is changed.', async () => {\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const panel = fixture.editor.sidebar.designPanel.animation;\n\n    const effectChooser = panel.effectChooser;\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n    await fixture.events.sleep(300);\n\n    const { animationState } = await fixture.renderHook(() =>\n      useStory(({ state }) => {\n        return {\n          animationState: state.animationState,\n        };\n      })\n    );\n\n    expect(animationState).toBe(StoryAnimationState.PlayingSelected);\n  });\n\n  it('should render the animation panel with warning if on the first page.', async () => {\n    // add text to the canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // navigate to the animations panel\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n\n    // A warning should be displayed per AMP spec - animations are disabled on first page\n    const contrastWarning =\n      await fixture.screen.findByTestId('warningContainer');\n\n    await expectAsync(contrastWarning).toHaveNoViolations();\n  });\n\n  it('should render the animation panel with effectChooser input disabled if on the first page.', async () => {\n    // add text to the canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // navigate to animations panel\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n\n    const panel = fixture.editor.sidebar.designPanel.animation;\n    // the effectChooser should be disabled on the first page\n    expect(panel.effectChooser.disabled).toBeTrue();\n  });\n\n  it('should render the animation panel with inputs disabled when page becomes the first page', async () => {\n    const { id: firstPageId } = await getCurrentPage();\n    // create a new page with in the story\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    const { id: secondPageId } = await getCurrentPage();\n\n    // add text to the canvas\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n    });\n\n    // navigate to the animations panel\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n\n    // get the second pages panel info\n    // animations should be enabled on all pages other than the first page\n    let effectChooser =\n      fixture.editor.sidebar.designPanel.animation.effectChooser;\n    expect(effectChooser.disabled).toBeFalsy();\n\n    // set the text animation\n    await fixture.events.click(effectChooser, { clickCount: 1 });\n\n    await fixture.events.click(\n      fixture.screen.getByRole('option', { name: /^\"Fade In\" Effect$/ })\n    );\n    expect(effectChooser.innerText).toBe('Fade In');\n\n    // switch to the first page\n    const pageAtIndex = fixture.editor.footer.carousel.pages[0].node;\n    await fixture.events.click(pageAtIndex);\n\n    const { id: shouldBeFirstPageId } = await getCurrentPage();\n    expect(shouldBeFirstPageId).toBe(firstPageId);\n\n    // delete the first page making the second page move to the first page\n    await fixture.events.keyboard.down('del');\n    await fixture.events.keyboard.up('del');\n\n    const { id: shouldBeSecondPageId } = await getCurrentPage();\n    expect(shouldBeSecondPageId).toBe(secondPageId);\n\n    // select the text component in the canvas\n    await fixture.events.click(\n      fixture.editor.canvas.framesLayer.frames[1].node\n    );\n\n    effectChooser = fixture.editor.sidebar.designPanel.animation.effectChooser;\n\n    // the animation information should still be present in the animation panel but not editable\n    expect(effectChooser.disabled).toBeTrue();\n    const duration = fixture.screen.getByLabelText('Duration');\n    const delay = fixture.screen.getByLabelText('Delay');\n    expect(duration.disabled).toBeTrue();\n    expect(delay.disabled).toBeTrue();\n\n    // A warning should be displayed per AMP spec - animations are disabled on first page\n    const contrastWarning =\n      await fixture.screen.findByTestId('warningContainer');\n    await expectAsync(contrastWarning).toHaveNoViolations();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/stories/directionRadioInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport {\n  AnimationDirection,\n  Rotation,\n  ScaleDirection,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { DirectionRadioInput } from '../directionRadioInput';\n\nexport default {\n  title: 'Stories Editor/Components/Panels/Animations/Direction Radio Input',\n  component: DirectionRadioInput,\n};\n\nconst Panel = styled.div`\n  padding: 20px;\n  background-color: #1c1c1c;\n`;\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <Panel>\n        <DirectionRadioInput\n          directions={Object.values(AnimationDirection)}\n          defaultChecked={AnimationDirection.TopToBottom}\n        />\n      </Panel>\n    );\n  },\n};\n\nexport const WithRotation = {\n  render: function Render() {\n    return (\n      <Panel>\n        <DirectionRadioInput\n          directions={[Rotation.Clockwise, Rotation.CounterClockwise]}\n          defaultChecked={Rotation.Clockwise}\n        />\n      </Panel>\n    );\n  },\n};\n\nexport const Scale = {\n  render: function Render() {\n    const [value, setValue] = useState(ScaleDirection.ScaleIn);\n    return (\n      <Panel>\n        <DirectionRadioInput\n          value={value}\n          onChange={({ target }) => setValue(target.value)}\n          directions={[ScaleDirection.ScaleIn, ScaleDirection.ScaleOut]}\n          defaultChecked={ScaleDirection.ScaleIn}\n        />\n      </Panel>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/stories/effectChooser.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  ScaleDirection,\n  AnimationDirection,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { EffectChooserDropdown } from '../effectChooserDropdown';\nimport {\n  backgroundEffectOptions,\n  foregroundEffectOptions,\n} from '../effectChooserDropdown/dropdownConstants';\n\nconst allEffectTypes = [\n  ...Object.keys(foregroundEffectOptions),\n  ...Object.keys(backgroundEffectOptions),\n];\nconst allDirections = [\n  ...Object.values(AnimationDirection),\n  ...Object.values(ScaleDirection),\n];\n\nexport default {\n  title: 'Stories Editor/Components/Panels/Animations/Effect Chooser',\n  component: EffectChooserDropdown,\n  args: {\n    isBackgroundEffects: false,\n  },\n  argTypes: {\n    selectedEffectType: {\n      options: allEffectTypes,\n      control: 'select',\n    },\n    direction: {\n      options: allDirections,\n      control: 'select',\n    },\n    onAnimationSelected: { action: 'onAnimationSelected' },\n    onNoEffectSelected: { action: 'onNoEffectSelected' },\n  },\n};\n\nconst Container = styled.div`\n  width: 276px;\n  margin: 25vh 30px 0;\n`;\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Container>\n        <EffectChooserDropdown\n          onAnimationSelected={(sender) => args.onAnimationSelected(sender)}\n          onNoEffectSelected={() => args.onNoEffectSelected}\n          disabledTypeOptionsMap={[]}\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/test/directionRadioInput.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { fireEvent, screen } from '@testing-library/react';\nimport PropTypes from 'prop-types';\nimport {\n  AnimationDirection,\n  ScaleDirection,\n} from '@googleforcreators/animation';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { DirectionRadioInput } from '../directionRadioInput';\n\nfunction DirectionRadioInputUncontrolled({ onChange, directions }) {\n  const [state, setState] = useState(null);\n  return (\n    <DirectionRadioInput\n      value={state}\n      onChange={(e) => {\n        setState(e.target.value);\n        onChange(e);\n      }}\n      directions={directions}\n    />\n  );\n}\n\nDirectionRadioInputUncontrolled.propTypes = {\n  onChange: PropTypes.func,\n  directions: PropTypes.arrayOf(PropTypes.string),\n};\n\ndescribe('<DirectionRadioInput />', () => {\n  it('should render', () => {\n    renderWithTheme(<DirectionRadioInput />);\n    const fieldset = screen.getByRole('group');\n    expect(fieldset).toBeInTheDocument();\n  });\n\n  it('should render directions supplied as buttons', () => {\n    renderWithTheme(\n      <DirectionRadioInput\n        directions={[\n          AnimationDirection.TopToBottom,\n          AnimationDirection.BottomToTop,\n        ]}\n        onChange={() => {}}\n      />\n    );\n    const buttons = screen.getAllByRole('button');\n    expect(buttons).toHaveLength(2);\n  });\n\n  it('should call onChange when button clicked', () => {\n    const onChange = jest.fn((value) => value);\n    const directions = [\n      AnimationDirection.TopToBottom,\n      AnimationDirection.BottomToTop,\n    ];\n    renderWithTheme(\n      <DirectionRadioInput onChange={onChange} directions={directions} />\n    );\n\n    const buttons = screen.getAllByRole('button');\n    fireEvent.click(buttons[1]);\n\n    expect(onChange).toHaveBeenCalledOnce();\n    expect(onChange).toHaveBeenCalledWith(directions[1]);\n  });\n\n  it('should render the correct number of arrows for scale direction', () => {\n    const onChange = jest.fn();\n    renderWithTheme(\n      <DirectionRadioInputUncontrolled\n        onChange={onChange}\n        directions={[ScaleDirection.ScaleIn, ScaleDirection.ScaleOut]}\n      />\n    );\n\n    const buttons = screen.getAllByRole('button');\n\n    expect(buttons).toHaveLength(4);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/animation/test/effectInput.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { FieldType } from '@googleforcreators/animation';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport EffectInput from '../effectInput';\n\ndescribe('<EffectInput />', () => {\n  const testFieldKey = 'testField';\n  const testValue = 500;\n  const defaultProps = {\n    effectProps: {\n      [testFieldKey]: {\n        type: FieldType.Number,\n        label: testFieldKey,\n      },\n    },\n    effectConfig: {\n      [testFieldKey]: testValue,\n    },\n    onChange: jest.fn(),\n    field: testFieldKey,\n  };\n\n  it('should render', () => {\n    renderWithTheme(<EffectInput {...defaultProps} />);\n    const input = screen.getByLabelText(testFieldKey);\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should render falsey defined values', () => {\n    renderWithTheme(\n      <EffectInput {...defaultProps} effectConfig={{ [testFieldKey]: 0 }} />\n    );\n    const testInput = screen.getByDisplayValue(0);\n    expect(testInput).toBeInTheDocument();\n    expect(testInput).toHaveAttribute('aria-label', testFieldKey);\n  });\n\n  it('should reject negative values and replace with \"0\"', () => {\n    renderWithTheme(<EffectInput {...defaultProps} />);\n    const input = screen.getByLabelText(testFieldKey);\n    fireEvent.change(input, {\n      target: { value: '-1' },\n    });\n    // negative value should be reset to 0 on blur\n    fireEvent.blur(input);\n    expect(input.value).toBe('0');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/audioStickerStyle.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport StickerSize from './stickerSize';\nimport StickerType from './stickerType';\nimport StickerStyle from './stickerStyle';\n\nfunction AudioStickerStylePanel({ selectedElements, pushUpdate }) {\n  return (\n    <>\n      <StickerType\n        selectedElements={selectedElements}\n        pushUpdate={pushUpdate}\n      />\n      <StickerSize\n        selectedElements={selectedElements}\n        pushUpdate={pushUpdate}\n      />\n      <StickerStyle\n        selectedElements={selectedElements}\n        pushUpdate={pushUpdate}\n      />\n    </>\n  );\n}\n\nexport default AudioStickerStylePanel;\n\nAudioStickerStylePanel.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './audioStickerStyle';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/stickerSize.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { SimplePanel } from '../../panel';\nimport { Row, Switch } from '../../../form';\n\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport { getDimensionsForAudioSticker } from './utils';\n\nfunction StickerSize({ selectedElements, pushUpdate }) {\n  const stickerObj = selectedElements[0];\n  const size = stickerObj.size;\n  const type = stickerObj.sticker;\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.Style],\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onSizeChange = useCallback(\n    (_, isSmall) => {\n      const stickerSize = isSmall ? 'small' : 'large';\n      const { width, height } = getDimensionsForAudioSticker(type, stickerSize);\n\n      pushUpdate(\n        {\n          width: width,\n          height: height,\n          size: stickerSize,\n        },\n        true\n      );\n    },\n    [pushUpdate, type]\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"audioStickerSize\"\n      title={__('Size', 'web-stories')}\n      isPersistable={!highlight}\n      aria-labelledby={null}\n      aria-label={__('Audio Sticker Size', 'web-stories')}\n    >\n      <Row>\n        <Switch\n          groupLabel={__('Size', 'web-stories')}\n          name=\"audio-sticker-size-switch\"\n          value={size === 'small'}\n          onLabel={__('Small', 'web-stories')}\n          offLabel={__('Large', 'web-stories')}\n          onChange={onSizeChange}\n        />\n      </Row>\n    </SimplePanel>\n  );\n}\n\nexport default StickerSize;\n\nStickerSize.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/stickerStyle.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  AUDIO_STICKER_STYLES,\n  AUDIO_STICKER_LABELS,\n} from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\nimport { Row, FilterToggle } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\n\nexport const AudioStickerStylePreset = {\n  none: {\n    label: __('None', 'web-stories'),\n  },\n  outline: {\n    label: __('Outline', 'web-stories'),\n  },\n  dropshadow: {\n    label: __('Drop shadow', 'web-stories'),\n  },\n};\n\nconst StickerImage = styled.img`\n  width: 100%;\n  ${({ stickerStyle }) => AUDIO_STICKER_STYLES[stickerStyle]}\n`;\n\nfunction StickerStyle({ selectedElements, pushUpdate }) {\n  const { cdnURL } = useConfig();\n\n  const stickerObj = selectedElements[0];\n  const style = stickerObj.style;\n  const type = stickerObj.sticker;\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.Style],\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onStickerStyleChange = useCallback(\n    (stickerStyle) => {\n      pushUpdate(\n        {\n          style: stickerStyle,\n        },\n        true\n      );\n    },\n    [pushUpdate]\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"audioStickerStyle\"\n      title={__('Style', 'web-stories')}\n      isPersistable={!highlight}\n      aria-labelledby={null}\n      aria-label={__('Audio Sticker Style', 'web-stories')}\n    >\n      <Row style={{ alignItems: 'flex-start' }}>\n        {Object.keys(AudioStickerStylePreset).map((stickerStyle) => {\n          const { label } = AudioStickerStylePreset[stickerStyle];\n          return (\n            <FilterToggle\n              key={stickerStyle}\n              element={selectedElements[0]}\n              label={label}\n              isToggled={stickerStyle === style}\n              onClick={() => {\n                onStickerStyleChange(stickerStyle);\n              }}\n              aria-label={sprintf(\n                /* translators: %s: Sticker style */\n                __('Sticker Style: %s', 'web-stories'),\n                label\n              )}\n            >\n              <StickerImage\n                src={`${cdnURL}images/audio-sticker/${type}-pretap.png`}\n                crossOrigin=\"anonymous\"\n                alt={AUDIO_STICKER_LABELS[type].label}\n                stickerStyle={stickerStyle}\n              />\n            </FilterToggle>\n          );\n        })}\n      </Row>\n    </SimplePanel>\n  );\n}\n\nexport default StickerStyle;\n\nStickerStyle.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/stickerType.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { AUDIO_STICKER_LABELS } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\nimport { Row, FilterToggle } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\n\nexport const AudioStickerPreset = {\n  'headphone-cat': {\n    label: __('Headphone Cat', 'web-stories'),\n  },\n  'tape-player': {\n    label: __('Tape Player', 'web-stories'),\n  },\n  'loud-speaker': {\n    label: __('Loud Speaker', 'web-stories'),\n  },\n  'audio-cloud': {\n    label: __('Audio Cloud', 'web-stories'),\n  },\n};\n\nconst StickerImage = styled.img`\n  width: 100%;\n`;\n\nfunction StickerType({ selectedElements, pushUpdate }) {\n  const { cdnURL } = useConfig();\n\n  const stickerObj = selectedElements[0];\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.Style],\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onStickerTypeChange = useCallback(\n    (stickerType) => {\n      pushUpdate(\n        {\n          sticker: stickerType,\n        },\n        true\n      );\n    },\n    [pushUpdate]\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"audioStickerType\"\n      title={__('Type', 'web-stories')}\n      isPersistable={!highlight}\n      aria-labelledby={null}\n      aria-label={__('Audio Sticker Type', 'web-stories')}\n    >\n      <Row>\n        {Object.keys(AudioStickerPreset).map((type) => {\n          const { label } = AudioStickerPreset[type];\n          return (\n            <FilterToggle\n              key={type}\n              element={stickerObj}\n              label={label}\n              isToggled={type === stickerObj.sticker}\n              onClick={() => {\n                onStickerTypeChange(type);\n              }}\n              aria-label={sprintf(\n                /* translators: %s: Sticker type */\n                __('Sticker Type: %s', 'web-stories'),\n                label\n              )}\n            >\n              <StickerImage\n                src={`${cdnURL}images/audio-sticker/${type}-pretap.png`}\n                crossOrigin=\"anonymous\"\n                alt={AUDIO_STICKER_LABELS[type].label}\n              />\n            </FilterToggle>\n          );\n        })}\n      </Row>\n    </SimplePanel>\n  );\n}\n\nexport default StickerType;\n\nStickerType.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/test/stickerSize.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderPanel } from '../../../shared/test/_utils';\nimport AudioStickerStylePanel from '../audioStickerStyle';\n\ndescribe('Panels/AudioStickerSize', () => {\n  const DEFAULT_ELEMENT = {\n    opacity: 100,\n    flip: {\n      vertical: false,\n      horizontal: false,\n    },\n    rotationAngle: 0,\n    lockAspectRatio: true,\n    size: 'small',\n    sticker: 'headphone-cat',\n    style: 'none',\n    lockDimensions: true,\n    x: 100,\n    y: 100,\n    width: 149,\n    height: 120,\n    type: 'audioSticker',\n    id: '8c0c1b7e-7ad3-4140-aa69-4c2011373370',\n  };\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:audioStickerSize',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  function arrange(...args) {\n    const view = renderPanel(AudioStickerStylePanel, ...args);\n    const sizeSmallSwitch = screen.getByText('Small');\n    const sizeLargeSwitch = screen.getByText('Large');\n\n    return {\n      ...view,\n      sizeSmallSwitch,\n      sizeLargeSwitch,\n    };\n  }\n\n  it('should render sticker size Small button', () => {\n    const { sizeSmallSwitch } = arrange([DEFAULT_ELEMENT]);\n    expect(sizeSmallSwitch).toBeInTheDocument();\n  });\n\n  it('should render sticker size Large button', () => {\n    const { sizeLargeSwitch } = arrange([DEFAULT_ELEMENT]);\n    expect(sizeLargeSwitch).toBeInTheDocument();\n  });\n\n  it('should update element on changing sticker size to Small', () => {\n    const { sizeSmallSwitch, pushUpdate } = arrange([\n      { ...DEFAULT_ELEMENT, size: 'large' },\n    ]);\n    fireEvent.click(sizeSmallSwitch);\n\n    expect(pushUpdate).toHaveBeenCalledWith(\n      { width: expect.any(Number), height: expect.any(Number), size: 'small' },\n      true\n    );\n  });\n\n  it('should update element on changing sticker size to Large', () => {\n    const { sizeLargeSwitch, pushUpdate } = arrange([DEFAULT_ELEMENT]);\n    fireEvent.click(sizeLargeSwitch);\n\n    expect(pushUpdate).toHaveBeenCalledWith(\n      { width: expect.any(Number), height: expect.any(Number), size: 'large' },\n      true\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/test/stickerStyle.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport AudioStickerStylePanel from '../audioStickerStyle';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport { AudioStickerStylePreset } from '../stickerStyle';\n\ndescribe('Panels/AudioStickerStyle', () => {\n  const DEFAULT_ELEMENT = {\n    opacity: 100,\n    flip: { vertical: false, horizontal: false },\n    rotationAngle: 0,\n    lockAspectRatio: true,\n    size: 'small',\n    sticker: 'headphone-cat',\n    style: 'none',\n    lockDimensions: true,\n    x: 100,\n    y: 100,\n    width: 149,\n    height: 120,\n    type: 'audioSticker',\n    id: '8c0c1b7e-7ad3-4140-aa69-4c2011373370',\n  };\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:audioStickerStyle',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  function arrange() {\n    const view = renderPanel(AudioStickerStylePanel, [DEFAULT_ELEMENT]);\n    const buttons = {};\n    Object.entries(AudioStickerStylePreset).forEach(([style, { label }]) => {\n      buttons[style] = screen.getByLabelText(`Sticker Style: ${label}`);\n    });\n    return { ...view, buttons };\n  }\n\n  describe('Buttons Rendering and Click Handling', () => {\n    it.each(Object.entries(AudioStickerStylePreset))(\n      'should render %s button',\n      (style) => {\n        const { buttons } = arrange([DEFAULT_ELEMENT]);\n        const button = buttons[style];\n        expect(button).toBeInTheDocument();\n      }\n    );\n\n    it.each(Object.entries(AudioStickerStylePreset))(\n      'should update element on %s button click',\n      (style) => {\n        const { buttons, pushUpdate } = arrange([DEFAULT_ELEMENT]);\n        const button = buttons[style];\n        fireEvent.click(button);\n        expect(pushUpdate).toHaveBeenCalledWith({ style }, true);\n      }\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/test/stickerType.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderPanel } from '../../../shared/test/_utils';\nimport AudioStickerStylePanel from '../audioStickerStyle';\nimport { AudioStickerPreset } from '../stickerType';\n\ndescribe('Panels/AudioStickerType', () => {\n  const DEFAULT_ELEMENT = {\n    opacity: 100,\n    flip: {\n      vertical: false,\n      horizontal: false,\n    },\n    rotationAngle: 0,\n    lockAspectRatio: true,\n    size: 'small',\n    sticker: 'headphone-cat',\n    style: 'none',\n    lockDimensions: true,\n    x: 100,\n    y: 100,\n    width: 149,\n    height: 120,\n    type: 'audioSticker',\n    id: '8c0c1b7e-7ad3-4140-aa69-4c2011373370',\n  };\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:audioStickerType',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  function arrange(...args) {\n    const view = renderPanel(AudioStickerStylePanel, ...args);\n    const buttons = {};\n    Object.keys(AudioStickerPreset).forEach((sticker) => {\n      const label = AudioStickerPreset[sticker].label;\n      buttons[sticker] = screen.getByLabelText(`Sticker Type: ${label}`);\n    });\n    return { ...view, buttons };\n  }\n\n  describe('Buttons Rendering and Click Handling', () => {\n    it.each(Object.keys(AudioStickerPreset))(\n      'should render %s button',\n      (sticker) => {\n        const { buttons } = arrange([DEFAULT_ELEMENT]);\n        const button = buttons[sticker];\n        expect(button).toBeInTheDocument();\n      }\n    );\n\n    it.each(Object.keys(AudioStickerPreset))(\n      'should update element on %s button click',\n      (sticker) => {\n        const { buttons, pushUpdate } = arrange([DEFAULT_ELEMENT]);\n        const button = buttons[sticker];\n        fireEvent.click(button);\n        expect(pushUpdate).toHaveBeenCalledWith({ sticker }, true);\n      }\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/audioSticker/utils.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport {\n  AUDIO_STICKER_ASPECT_RATIOS,\n  AUDIO_STICKER_WIDTH_PRESETS,\n} from '../../../../constants';\n\nexport function getDimensionsForAudioSticker(type, size) {\n  let width, height;\n  if (size === 'small') {\n    width =\n      AUDIO_STICKER_WIDTH_PRESETS.SMALL * AUDIO_STICKER_ASPECT_RATIOS[type];\n    height = AUDIO_STICKER_WIDTH_PRESETS.SMALL;\n  } else {\n    width =\n      AUDIO_STICKER_WIDTH_PRESETS.LARGE * AUDIO_STICKER_ASPECT_RATIOS[type];\n    height = AUDIO_STICKER_WIDTH_PRESETS.LARGE;\n  }\n\n  return { width, height };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/border/border.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  canSupportMultiBorder,\n  canMaskHaveBorder,\n} from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\n\nimport { Color, Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { useCommonObjectValue } from '../../shared';\nimport { DEFAULT_BORDER } from './shared';\nimport WidthControls from './borderWidth';\n\nfunction BorderStylePanel(props) {\n  const { selectedElements, pushUpdate } = props;\n  const border = useCommonObjectValue(\n    selectedElements,\n    'border',\n    DEFAULT_BORDER\n  );\n  const { color, left, top, right, bottom } = border;\n\n  const allSupportBorder = selectedElements.every((el) =>\n    canMaskHaveBorder(el)\n  );\n\n  const handleChange = useCallback(\n    (value, name) =>\n      pushUpdate(\n        {\n          border: {\n            ...border,\n            [name]: value,\n          },\n        },\n        true\n      ),\n    [border, pushUpdate]\n  );\n\n  // If any of the elements doesn't support border, don't display.\n  if (!allSupportBorder) {\n    return null;\n  }\n\n  // Some shapes i.e all non-rectangular shapes only support a single border width value\n  // If so, they also don't support opacity for the border color, so that has to be removed here\n  const hasMultiBorderSupport = selectedElements.every(canSupportMultiBorder);\n\n  const hasBorder = [left, top, right, bottom].some((value) => value > 0);\n  return (\n    <SimplePanel name=\"borderStyle\" title={__('Border', 'web-stories')}>\n      <WidthControls {...props} />\n      {hasBorder && (\n        <Row>\n          <Color\n            value={color}\n            onChange={(value) => {\n              handleChange(value, 'color');\n            }}\n            label={__('Border color', 'web-stories')}\n            hasEyedropper\n            allowsOpacity={hasMultiBorderSupport}\n          />\n        </Row>\n      )}\n    </SimplePanel>\n  );\n}\n\nBorderStylePanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default BorderStylePanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/border/borderWidth.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { LockToggle, Icons } from '@googleforcreators/design-system';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { StackableGroup, StackableInput } from '../../../form/stackable';\nimport Tooltip from '../../../tooltip';\nimport { focusStyle } from '../../shared/styles';\nimport { useCommonObjectValue } from '../../shared';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport { DEFAULT_BORDER } from './shared';\n\nconst BorderInputsFlexContainer = styled.div`\n  display: flex;\n  gap: 7px;\n  margin-bottom: 16px;\n`;\n\nconst StyledLockToggle = styled(LockToggle)`\n  ${focusStyle};\n`;\n\nconst ToggleWrapper = styled.div`\n  padding-top: 2px;\n  ${({ locked }) =>\n    locked &&\n    `\n    padding-left: 8px;\n  `}\n  align-self: stretch;\n`;\n\nconst BorderTop = styled(Icons.Border)`\n  transform: rotate(90deg);\n`;\n\nconst BorderBottom = styled(Icons.Border)`\n  transform: rotate(-90deg);\n`;\n\nconst BorderRight = styled(Icons.Border)`\n  transform: scaleX(-1);\n`;\n\nfunction WidthControls({ selectedElements, pushUpdateForObject }) {\n  const border = useCommonObjectValue(\n    selectedElements,\n    'border',\n    DEFAULT_BORDER\n  );\n\n  // Some shapes i.e all non-rectangular shapes only support a single border width value\n  const hasMultiBorderSupport = selectedElements.every(canSupportMultiBorder);\n\n  // Only if true for all selected elements.\n  const lockBorder = border.lockedWidth === true || !hasMultiBorderSupport;\n\n  const handleChange = useCallback(\n    (name) => (evt, value) => {\n      const newBorder = !lockBorder\n        ? {\n            [name]: value,\n          }\n        : {\n            left: value,\n            top: value,\n            right: value,\n            bottom: value,\n          };\n      pushUpdateForObject('border', newBorder, DEFAULT_BORDER, true);\n    },\n    [pushUpdateForObject, lockBorder]\n  );\n\n  const handleLockChange = useCallback(\n    (newBorder) => {\n      pushUpdateForObject('border', newBorder, DEFAULT_BORDER, true);\n    },\n    [pushUpdateForObject]\n  );\n\n  const firstInputLabel = lockBorder\n    ? __('Border', 'web-stories')\n    : __('Left border', 'web-stories');\n\n  const getMixedValueProps = useCallback((value) => {\n    return {\n      isIndeterminate: MULTIPLE_VALUE === value,\n      placeholder: MULTIPLE_VALUE === value ? MULTIPLE_DISPLAY_VALUE : null,\n    };\n  }, []);\n  return (\n    <BorderInputsFlexContainer>\n      <StackableGroup locked={lockBorder}>\n        <StackableInput\n          value={border.left}\n          onChange={handleChange('left')}\n          aria-label={firstInputLabel}\n          suffix={!lockBorder && <Icons.Border />}\n          min={0}\n          {...getMixedValueProps(border.left)}\n        />\n\n        {!lockBorder && (\n          <>\n            <StackableInput\n              value={border.top}\n              onChange={handleChange('top')}\n              aria-label={__('Top border', 'web-stories')}\n              labelText={__('Top', 'web-stories')}\n              suffix={<BorderTop />}\n              min={0}\n              {...getMixedValueProps(border.top)}\n            />\n\n            <StackableInput\n              value={border.right}\n              onChange={handleChange('right')}\n              aria-label={__('Right border', 'web-stories')}\n              labelText={__('Right', 'web-stories')}\n              suffix={<BorderRight />}\n              min={0}\n              {...getMixedValueProps(border.right)}\n            />\n\n            <StackableInput\n              value={border.bottom}\n              onChange={handleChange('bottom')}\n              aria-label={__('Bottom border', 'web-stories')}\n              labelText={__('Bottom', 'web-stories')}\n              suffix={<BorderBottom />}\n              min={0}\n              {...getMixedValueProps(border.bottom)}\n            />\n          </>\n        )}\n      </StackableGroup>\n      {hasMultiBorderSupport && (\n        <ToggleWrapper locked={lockBorder}>\n          <Tooltip title={__('Toggle consistent border', 'web-stories')}>\n            <StyledLockToggle\n              isLocked={lockBorder}\n              onClick={() => {\n                let args = {\n                  lockedWidth: !lockBorder,\n                };\n                // If the border width wasn't locked before (and is now), unify all the values.\n                if (!lockBorder) {\n                  args = {\n                    ...args,\n                    top: border.left,\n                    right: border.left,\n                    bottom: border.left,\n                  };\n                }\n                handleLockChange(args);\n              }}\n              aria-label={__('Toggle consistent border', 'web-stories')}\n            />\n          </Tooltip>\n        </ToggleWrapper>\n      )}\n    </BorderInputsFlexContainer>\n  );\n}\n\nWidthControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdateForObject: PropTypes.func.isRequired,\n};\n\nexport default WidthControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/border/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './border';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/border/karma/border.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Border Panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelection = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  };\n\n  describe('CUJ: Creator can Manipulate Shape: Border', () => {\n    it('should allow the user to add border for text element', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n      });\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      const panel = fixture.editor.sidebar.designPanel.border;\n\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('2');\n      await fixture.events.keyboard.press('tab');\n\n      const [element] = await getSelection();\n      // Since the default state is locked, verify that all the values were set to 10.\n      expect(element.border.left).toBe(2);\n      expect(element.border.top).toBe(2);\n      expect(element.border.right).toBe(2);\n      expect(element.border.bottom).toBe(2);\n\n      // Take off lock.\n      await fixture.events.click(panel.lockBorderWidth);\n\n      await fixture.events.click(panel.width('Top'), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      // Verify the value changed but stayed the same for the left width.\n      const [updatedElement] = await getSelection();\n      expect(updatedElement.border.left).toBe(2);\n      expect(updatedElement.border.top).toBe(10);\n\n      await fixture.snapshot('Text element with inner border');\n    });\n\n    it('should allow user to add border for media', async () => {\n      // Add media element and basic border.\n      const mediaItem = fixture.editor.library.media.item(0);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      const panel = fixture.editor.sidebar.designPanel.border;\n      await fixture.events.click(panel.width(), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('Tab');\n\n      const borderColor = panel.borderColor;\n      await fixture.events.focus(borderColor.opacity);\n      await fixture.events.click(borderColor.opacity, { clickCount: 3 });\n      await fixture.events.keyboard.type('30');\n      await fixture.events.keyboard.press('Tab');\n\n      await waitFor(() => {\n        if (borderColor.opacity.getAttribute('value') !== '30%') {\n          throw new Error('opacity not set yet');\n        }\n        expect(borderColor.opacity.getAttribute('value')).toBe('30%');\n      });\n\n      const [element] = await getSelection();\n      const {\n        border: { left, top, right, bottom, color },\n      } = element;\n      expect(left).toBe(10);\n      expect(top).toBe(10);\n      expect(right).toBe(10);\n      expect(bottom).toBe(10);\n      expect(color.color.a).toBe(0.3);\n\n      await fixture.snapshot('Media element with border');\n    });\n  });\n\n  it('should allow user to add border for shape', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const panel = fixture.editor.sidebar.designPanel.border;\n    await fixture.events.click(panel.width(), { clickCount: 3 });\n    await fixture.events.keyboard.type('5');\n    await fixture.events.keyboard.press('Tab');\n\n    const [element] = await getSelection();\n    const {\n      border: { right },\n    } = element;\n    expect(right).toBe(5);\n\n    await fixture.snapshot('Shape element with border');\n  });\n\n  it('should allow border for non-rectangular shape', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Circle'));\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const panel = fixture.editor.sidebar.designPanel.border;\n    await fixture.events.click(panel.width(), { clickCount: 3 });\n    await fixture.events.keyboard.type('10');\n    await fixture.events.keyboard.press('Tab');\n\n    const [element] = await getSelection();\n    const {\n      border: { left },\n    } = element;\n    expect(left).toBe(10);\n\n    await fixture.snapshot('Non-rectangular shape element with border');\n\n    // Verify that border cannot have opacity\n    expect(() => panel.borderColor.opacity).toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/border/shared.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\n\nexport const DEFAULT_BORDER = {\n  left: 0,\n  right: 0,\n  top: 0,\n  bottom: 0,\n  lockedWidth: true,\n  color: createSolid(0, 0, 0),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/captions/captions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { usePresubmitHandler } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { getCommonValue } from '../../shared';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport CaptionsPanelContent from '../../shared/media/captionsPanelContent';\nimport { MULTIPLE_VALUE } from '../../../../constants';\n\nconst StyledButton = styled(Button)`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst UploadButton = styled(StyledButton)`\n  padding: 12px 8px;\n`;\n\nexport const MIN_MAX = {\n  ALT_TEXT: {\n    MAX: 1000,\n  },\n};\n\nfunction CaptionsPanel({ selectedElements, pushUpdate }) {\n  const tracks = getCommonValue(selectedElements, 'tracks', []);\n  const isIndeterminate = tracks === MULTIPLE_VALUE;\n\n  usePresubmitHandler(\n    ({ resource: newResource }) => ({\n      resource: {\n        ...newResource,\n        alt: newResource.alt?.slice(0, MIN_MAX.ALT_TEXT.MAX),\n      },\n    }),\n    []\n  );\n\n  const handleRemoveTrack = useCallback(\n    (idToDelete) => {\n      let newTracks = [];\n      if (idToDelete) {\n        const trackIndex = tracks.findIndex(({ id }) => id === idToDelete);\n        newTracks = [\n          ...tracks.slice(0, trackIndex),\n          ...tracks.slice(trackIndex + 1),\n        ];\n      }\n      pushUpdate({ tracks: newTracks }, true);\n    },\n    [tracks, pushUpdate]\n  );\n\n  const handleChangeTrack = useCallback(\n    ({ src = '', id, needsProxy = false }) => {\n      const newTrack = {\n        track: src,\n        trackId: id,\n        id: uuidv4(),\n        kind: 'captions',\n        srclang: '',\n        label: '',\n        needsProxy,\n      };\n\n      pushUpdate({ tracks: [newTrack] }, true);\n    },\n    [pushUpdate]\n  );\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: state[states.Captions],\n    resetHighlight: state.onFocusOut,\n    cancelHighlight: state.cancelEffect,\n  }));\n\n  const renderUploadButton = useCallback(\n    (open) => (\n      <UploadButton\n        css={highlight?.showEffect && styles.OUTLINE}\n        onAnimationEnd={() => resetHighlight()}\n        ref={(node) => {\n          if (node && highlight?.focus && highlight?.showEffect) {\n            node.focus();\n          }\n        }}\n        onClick={open}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Rectangle}\n      >\n        {__('Upload a file', 'web-stories')}\n      </UploadButton>\n    ),\n    [resetHighlight, highlight?.focus, highlight?.showEffect]\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"caption\"\n      title={__('Caption and Subtitles', 'web-stories')}\n      isPersistable={!highlight}\n    >\n      <CaptionsPanelContent\n        isIndeterminate={isIndeterminate}\n        tracks={!isIndeterminate ? tracks : []}\n        handleChangeTrack={handleChangeTrack}\n        handleRemoveTrack={handleRemoveTrack}\n        renderUploadButton={renderUploadButton}\n      />\n    </SimplePanel>\n  );\n}\n\nCaptionsPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default CaptionsPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/captions/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './captions';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/captions/test/captions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport ConfigContext from '../../../../../app/config/context';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport Captions from '../captions';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../../../../constants';\n\nfunction MediaUpload({ render }) {\n  const open = jest.fn();\n  return render(open);\n}\n\ndescribe('Panels/Captions', () => {\n  const defaultElement = {\n    type: 'video',\n    resource: { posterId: 0, poster: '', alt: '' },\n    tracks: [],\n  };\n  function arrange(config, selectedElements) {\n    const configValue = {\n      capabilities: {\n        hasUploadMediaAction: true,\n      },\n      allowedMimeTypes: { caption: ['text/vtt'] },\n      ...config,\n      MediaUpload,\n    };\n\n    const wrapper = ({ children }) => (\n      <ConfigContext.Provider value={configValue}>\n        {children}\n      </ConfigContext.Provider>\n    );\n\n    return renderPanel(Captions, selectedElements, wrapper);\n  }\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:caption',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render <Captions /> panel', () => {\n    arrange({}, [defaultElement]);\n    const captionRegion = screen.getByRole('region', {\n      name: /Caption and subtitles/i,\n    });\n    expect(captionRegion).toBeInTheDocument();\n\n    const captionButton = screen.queryByRole('button', {\n      name: /Upload a file/i,\n    });\n    expect(captionButton).toBeInTheDocument();\n\n    const captionHotlinkButton = screen.queryByRole('button', {\n      name: /Link to caption file/i,\n    });\n    expect(captionHotlinkButton).toBeInTheDocument();\n  });\n\n  it('should not render captions upload button', () => {\n    arrange(\n      {\n        capabilities: {\n          hasUploadMediaAction: false,\n        },\n      },\n      [defaultElement]\n    );\n    const captionButton = screen.queryByRole('button', {\n      name: /Upload a file/i,\n    });\n    expect(captionButton).not.toBeInTheDocument();\n\n    const captionHotlinkButton = screen.queryByRole('button', {\n      name: /Link to caption file/i,\n    });\n    expect(captionHotlinkButton).toBeInTheDocument();\n  });\n\n  it('should display Mixed in case of mixed value multi-selection', () => {\n    arrange({}, [\n      defaultElement,\n      {\n        resource: {\n          posterId: 0,\n          title: 'Hello, video!',\n          poster: '',\n          alt: 'Hello!',\n        },\n        tracks: ['Some track here'],\n      },\n    ]);\n\n    expect(screen.getByText(MULTIPLE_DISPLAY_VALUE)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/filter/convertOverlay.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { OverlayType } from '@googleforcreators/elements';\n\nfunction convertToSolid(currentOverlay, currentType) {\n  switch (currentType) {\n    case OverlayType.NONE:\n      // default color\n      return {\n        color: { r: 0, g: 0, b: 0, a: 0.5 },\n      };\n\n    case OverlayType.LINEAR:\n    case OverlayType.RADIAL: {\n      // converting from any gradient to SOLID\n      // use \"opaque'st\" stop as primary color, but fix alpha at .3\n      const { stops } = currentOverlay;\n      const stopsByAlpha = stops\n        .slice()\n        .sort((x, y) => (y.color.a ?? 1) - (x.color.a ?? 1));\n      const {\n        color: { r, g, b },\n      } = stopsByAlpha[0];\n      return {\n        color: { r, g, b, a: 0.5 },\n      };\n    }\n\n    default:\n      return currentOverlay;\n  }\n}\nfunction convertToLinear(currentOverlay, currentType) {\n  switch (currentType) {\n    case OverlayType.NONE:\n      // default pattern\n      return {\n        type: 'linear',\n        rotation: 0,\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.7,\n      };\n\n    case OverlayType.SOLID: {\n      // converting from SOLID to RADIAL\n      const {\n        color: { r, g, b, a },\n      } = currentOverlay;\n      return {\n        type: 'linear',\n        rotation: 0,\n        stops: [\n          { color: { r, g, b, a: 0 }, position: 0.4 },\n          { color: { r, g, b, a: 1 }, position: 1 },\n        ],\n        alpha: a,\n      };\n    }\n\n    case OverlayType.RADIAL: {\n      // converting from LINEAR to RADIAL\n      const { stops, alpha } = currentOverlay;\n      return {\n        type: 'linear',\n        rotation: 0,\n        stops,\n        alpha,\n      };\n    }\n\n    default:\n      return currentOverlay;\n  }\n}\nfunction convertToRadial(currentOverlay, currentType) {\n  switch (currentType) {\n    case OverlayType.NONE:\n      // default pattern\n      return {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.7,\n      };\n\n    case OverlayType.SOLID: {\n      // converting from SOLID to RADIAL\n      const {\n        color: { r, g, b, a },\n      } = currentOverlay;\n      return {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops: [\n          { color: { r, g, b, a: 0 }, position: 0 },\n          { color: { r, g, b, a: 1 }, position: 1 },\n        ],\n        alpha: a,\n      };\n    }\n\n    case OverlayType.LINEAR: {\n      // converting from LINEAR to RADIAL\n      const { stops, alpha } = currentOverlay;\n      return {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops,\n        alpha,\n      };\n    }\n\n    default:\n      return currentOverlay;\n  }\n}\n\nfunction convertOverlay(currentOverlay, currentType, newType) {\n  switch (newType) {\n    case OverlayType.NONE:\n      return null;\n\n    case OverlayType.SOLID:\n      return convertToSolid(currentOverlay, currentType);\n\n    case OverlayType.LINEAR:\n      return convertToLinear(currentOverlay, currentType);\n\n    case OverlayType.RADIAL:\n      return convertToRadial(currentOverlay, currentType);\n\n    default:\n      return currentOverlay;\n  }\n}\n\nexport default convertOverlay;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/filter/filter.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, _x, sprintf } from '@googleforcreators/i18n';\nimport { getDefinitionForType, OverlayType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Row, Color, FilterToggle } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { useCommonColorValue } from '../../shared';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\nimport { useStory } from '../../../../app';\nimport { MULTIPLE_VALUE } from '../../../../constants';\nimport convertOverlay from './convertOverlay';\n\nconst OverlayPreset = {\n  [OverlayType.NONE]: {\n    label: _x('None', 'overlay', 'web-stories'),\n  },\n  [OverlayType.SOLID]: {\n    label: __('Tint', 'web-stories'),\n  },\n  [OverlayType.LINEAR]: {\n    label: __('Linear', 'web-stories'),\n  },\n  [OverlayType.RADIAL]: {\n    label: __('Vignette', 'web-stories'),\n  },\n};\n\nfunction FilterPanel({ selectedElements, pushUpdate }) {\n  const overlay = useCommonColorValue(selectedElements, 'overlay');\n  const isMultiple = overlay === MULTIPLE_VALUE;\n  const overlayType = !overlay\n    ? OverlayType.NONE\n    : overlay.type || OverlayType.SOLID;\n  const { getProxiedUrl } = useCORSProxy();\n  const { isDefaultBackground } = selectedElements[0];\n  const currentPageBackgroundColor = useStory(\n    (v) => !isDefaultBackground || v.state.currentPage?.backgroundColor\n  );\n\n  const updateOverlay = useCallback(\n    (value) => pushUpdate({ overlay: value }, true),\n    [pushUpdate]\n  );\n\n  // Enable eyedropper only for solid colors\n  // https://github.com/googleforcreators/web-stories-wp/pull/9488#issuecomment-950679465\n  const hasEyedropper =\n    overlayType !== OverlayType.RADIAL && overlayType !== OverlayType.LINEAR;\n\n  const { LayerIcon } = getDefinitionForType(selectedElements[0].type);\n  return (\n    <SimplePanel name=\"filter\" title={__('Filters', 'web-stories')}>\n      {!isMultiple && (\n        <Row>\n          {Object.keys(OverlayPreset).map((type) => {\n            const { label } = OverlayPreset[type];\n            return (\n              <FilterToggle\n                key={type}\n                element={selectedElements[0]}\n                label={label}\n                isToggled={overlayType === type}\n                onClick={() =>\n                  updateOverlay(convertOverlay(overlay, overlayType, type))\n                }\n                filter={convertOverlay(overlay, OverlayType.NONE, type)}\n                aria-label={sprintf(\n                  /* translators: %s: Filter type */\n                  __('Filter: %s', 'web-stories'),\n                  label\n                )}\n              >\n                <LayerIcon\n                  element={selectedElements[0]}\n                  getProxiedUrl={getProxiedUrl}\n                  currentPageBackgroundColor={currentPageBackgroundColor}\n                />\n              </FilterToggle>\n            );\n          })}\n        </Row>\n      )}\n      {overlayType !== OverlayType.NONE && (\n        <Row>\n          <Color\n            label={__('Color', 'web-stories')}\n            value={overlay}\n            onChange={updateOverlay}\n            allowsGradient\n            hasEyedropper={hasEyedropper}\n          />\n        </Row>\n      )}\n    </SimplePanel>\n  );\n}\n\nFilterPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default FilterPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/filter/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './filter';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/filter/karma/filter.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Filter Panel', () => {\n  let fixture;\n  let bgImageId;\n  let filterPanel;\n  let getBackgroundElementOverlay;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function getElements() {\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return elements;\n  }\n\n  describe('CUJ: Creator Can Manipulate an Image/Video on Canvas: Apply a solid or gradient overlay', () => {\n    describe('background', () => {\n      beforeEach(async () => {\n        // Drag first media element straight to canvas edge to set as background\n        const media = fixture.editor.library.media.item(0);\n        const canvas = fixture.editor.canvas.framesLayer.fullbleed;\n        await fixture.events.mouse.seq(({ down, moveRel, up }) => [\n          moveRel(media, 20, 20),\n          down(),\n          moveRel(canvas, 5, 5),\n          up(),\n        ]);\n\n        const elements = await getElements();\n        bgImageId = elements[0].id;\n\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        filterPanel = fixture.editor.sidebar.designPanel.filters;\n        getBackgroundElementOverlay = () =>\n          fixture.editor.canvas.displayLayer.display(bgImageId).overlay;\n      });\n\n      it('should render panel when there is an image in the background', () => {\n        expect(filterPanel).toBeTruthy();\n      });\n\n      it('should not render an overlay when there is none', () => {\n        expect(filterPanel.none.getAttribute('aria-pressed')).toBeTruthy();\n        expect(getBackgroundElementOverlay()).not.toBeTruthy();\n      });\n\n      it('should correctly show focus border only when using keyboard', async () => {\n        // Click solid button\n        await fixture.events.click(filterPanel.solid);\n\n        // Verify button is clicked and has focus\n        expect(filterPanel.solid.getAttribute('aria-pressed')).toBeTruthy();\n        expect(filterPanel.solid).toHaveFocus();\n\n        // Verify an overlay has been added\n        const overlay = await waitFor(getBackgroundElementOverlay);\n        expect(overlay).toBeTruthy();\n\n        // Screenshot it\n        await fixture.snapshot(\n          'BG has solid overlay, \"solid\" button is toggled and has no visible focus'\n        );\n\n        // shift-tab to none button\n        await fixture.events.keyboard.shortcut('shift+tab');\n\n        // Verify none button has focus\n        expect(filterPanel.none).toHaveFocus();\n\n        // Press space to activate none button\n        await fixture.events.keyboard.press('Space');\n\n        // Verify none button is toggled and overlay has been removed\n        expect(getBackgroundElementOverlay()).not.toBeTruthy();\n        expect(filterPanel.none.getAttribute('aria-pressed')).toBeTruthy();\n\n        // Screenshot it\n        await fixture.snapshot(\n          'BG has no overlay, \"none\" button is toggled and has visible focus'\n        );\n      });\n\n      it('should render correct overlay when clicking \"solid\"', async () => {\n        await fixture.events.click(filterPanel.solid);\n\n        const overlay = await waitFor(getBackgroundElementOverlay);\n        expect(overlay).toBeTruthy();\n        expect(overlay).toHaveStyle('background-color', 'rgba(0, 0, 0, 0.5)');\n      });\n\n      it('should render correct overlay when clicking \"linear\"', async () => {\n        await fixture.events.click(filterPanel.linear);\n\n        const overlay = await waitFor(getBackgroundElementOverlay);\n        expect(overlay).toBeTruthy();\n        expect(overlay).toHaveStyle(\n          'background-image',\n          'linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%)'\n        );\n      });\n\n      it('should render correct overlay when clicking \"radial\"', async () => {\n        await fixture.events.click(filterPanel.radial);\n\n        const overlay = await waitFor(getBackgroundElementOverlay);\n        expect(overlay).toBeTruthy();\n        expect(overlay).toHaveStyle(\n          'background-image',\n          'radial-gradient(67% 67%, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.7) 100%)'\n        );\n      });\n    });\n\n    describe('media elements', () => {\n      let elements;\n      beforeEach(async () => {\n        const mediaItem = fixture.editor.library.media.item(0);\n        await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        filterPanel = fixture.editor.sidebar.designPanel.filters;\n      });\n\n      it('should display the filter panel for non-bg media', () => {\n        expect(filterPanel).toBeTruthy();\n      });\n\n      it('should apply correct overlay when clicking \"solid\"', async () => {\n        await fixture.events.click(filterPanel.solid);\n\n        elements = await getElements();\n        expect(elements[1].overlay).toEqual({\n          color: { r: 0, g: 0, b: 0, a: 0.5 },\n        });\n      });\n\n      it('should apply correct overlay when clicking \"linear\"', async () => {\n        await fixture.events.click(filterPanel.linear);\n\n        elements = await getElements();\n        expect(elements[1].overlay).toEqual({\n          type: 'linear',\n          rotation: 0,\n          stops: [\n            { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n          ],\n          alpha: 0.7,\n        });\n      });\n\n      it('should apply correct overlay when clicking \"radial\"', async () => {\n        await fixture.events.click(filterPanel.radial);\n\n        elements = await getElements();\n        expect(elements[1].overlay).toEqual({\n          type: 'radial',\n          size: { w: 0.67, h: 0.67 },\n          stops: [\n            { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n            { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n          ],\n          alpha: 0.7,\n        });\n      });\n    });\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n  xdescribe('CUJ: Creator Can Manipulate an Image/Video on Canvas: Set overlay color(s) & other gradient properties', () => {\n    it('should render overlay color component iff it has an overlay');\n\n    it('should render correct solid overlay as customized');\n\n    it('should render correct linear gradient overlay as customized');\n\n    it('should render correct radial gradient overlay as customized');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/filter/test/convertOverlay.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { OverlayType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport convertOverlay from '../convertOverlay';\n\ndescribe('convertOverlay', () => {\n  it('should return null if converting any overlay to none', () => {\n    expect(convertOverlay(null, OverlayType.NONE, OverlayType.NONE)).toBeNull();\n    expect(convertOverlay({}, OverlayType.SOLID, OverlayType.NONE)).toBeNull();\n    expect(convertOverlay({}, OverlayType.RADIAL, OverlayType.NONE)).toBeNull();\n    expect(convertOverlay({}, OverlayType.LINEAR, OverlayType.NONE)).toBeNull();\n  });\n\n  describe('when converting from no overlay', () => {\n    it('should return default 50% black when converting to solid overlay', () => {\n      const result = convertOverlay(null, OverlayType.NONE, OverlayType.SOLID);\n      // expect 50% black\n      const expected = { color: { r: 0, g: 0, b: 0, a: 0.5 } };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return default transparent-to-black when converting to linear overlay', () => {\n      const result = convertOverlay(null, OverlayType.NONE, OverlayType.LINEAR);\n      // expect 0-70% transparent-to-black (top-to-bottom) linear gradient as specified\n      const expected = {\n        type: 'linear',\n        rotation: 0,\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.7,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return default black vignette when converting to radial overlay', () => {\n      const result = convertOverlay(null, OverlayType.NONE, OverlayType.RADIAL);\n      const expected = {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops: [\n          { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n          { color: { r: 0, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.7,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n  });\n\n  describe('when converting from solid 20% red overlay', () => {\n    const red = { color: { r: 255, g: 0, b: 0, a: 0.2 } };\n\n    it('should return exact same overlay when \"converting\" to solid overlay', () => {\n      const result = convertOverlay(red, OverlayType.SOLID, OverlayType.SOLID);\n      expect(result).toStrictEqual(red);\n    });\n\n    it('should return default transparent-to-black when converting to linear overlay', () => {\n      const result = convertOverlay(red, OverlayType.SOLID, OverlayType.LINEAR);\n      // expect 20% transparent-to-red (top-to-bottom) linear gradient\n      const expected = {\n        type: 'linear',\n        rotation: 0,\n        stops: [\n          { color: { r: 255, g: 0, b: 0, a: 0 }, position: 0.4 },\n          { color: { r: 255, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.2,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return default black vignette when converting to radial overlay', () => {\n      const result = convertOverlay(red, OverlayType.SOLID, OverlayType.RADIAL);\n      // expect 20% red vignette\n      const expected = {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops: [\n          { color: { r: 255, g: 0, b: 0, a: 0 }, position: 0 },\n          { color: { r: 255, g: 0, b: 0, a: 1 }, position: 1 },\n        ],\n        alpha: 0.2,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n  });\n\n  describe('when converting from green-to-blue linear overlay', () => {\n    const gb = {\n      type: 'linear',\n      rotation: 0,\n      stops: [\n        { color: { r: 0, g: 255, b: 0, a: 0.4 }, position: 0 },\n        { color: { r: 0, g: 0, b: 255, a: 0.7 }, position: 1 },\n      ],\n      alpha: 0.8,\n    };\n\n    it('should return most opaque color stop (blue) at 50% opacity', () => {\n      const result = convertOverlay(gb, OverlayType.LINEAR, OverlayType.SOLID);\n      // expect 30% blue\n      const expected = { color: { r: 0, g: 0, b: 255, a: 0.5 } };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return the same when \"converting\" to linear', () => {\n      const result = convertOverlay(gb, OverlayType.LINEAR, OverlayType.LINEAR);\n      expect(result).toStrictEqual(gb);\n    });\n\n    it('should return vignette with exact same stops and alpha', () => {\n      const result = convertOverlay(gb, OverlayType.LINEAR, OverlayType.RADIAL);\n      const expected = {\n        type: 'radial',\n        size: { w: 0.67, h: 0.67 },\n        stops: gb.stops,\n        alpha: gb.alpha,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n  });\n\n  describe('when converting from pink vignette (radial) overlay', () => {\n    const p = {\n      type: 'radial',\n      size: { w: 0.8, h: 0.5 },\n      stops: [\n        { color: { r: 0, g: 0, b: 0, a: 0 }, position: 0 },\n        { color: { r: 255, g: 192, b: 203, a: 1 }, position: 1 },\n      ],\n      alpha: 0.8,\n    };\n\n    it('should return most opaque color stop (pink) at 30% opacity', () => {\n      const result = convertOverlay(p, OverlayType.RADIAL, OverlayType.SOLID);\n      // expect 50% pink\n      const expected = { color: { r: 255, g: 192, b: 203, a: 0.5 } };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return linear gradient with exact same stops and alpha', () => {\n      const result = convertOverlay(p, OverlayType.RADIAL, OverlayType.LINEAR);\n      const expected = {\n        type: 'linear',\n        rotation: 0,\n        stops: p.stops,\n        alpha: p.alpha,\n      };\n      expect(result).toStrictEqual(expected);\n    });\n\n    it('should return the same when \"converting\" to radial', () => {\n      const result = convertOverlay(p, OverlayType.RADIAL, OverlayType.RADIAL);\n      expect(result).toStrictEqual(p);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/imageAccessibility/imageAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Row, TextArea } from '../../../form';\nimport { getCommonValue, useCommonObjectValue } from '../../shared';\nimport { SimplePanel } from '../../panel';\nimport { useHighlights, states } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\n\nconst StyledText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin-bottom: 10px;\n`;\n\nconst DEFAULT_RESOURCE = { alt: null };\nconst MIN_MAX = {\n  ALT_TEXT: {\n    MAX: 1000,\n  },\n};\n\nfunction ImageAccessibilityPanel({ selectedElements, pushUpdate }) {\n  const resource = useCommonObjectValue(\n    selectedElements,\n    'resource',\n    DEFAULT_RESOURCE\n  );\n  const alt = getCommonValue(selectedElements, 'alt', resource.alt);\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.AssistiveText],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  return (\n    <SimplePanel\n      css={highlight && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"imageAccessibility\"\n      title={__('Accessibility', 'web-stories')}\n      isPersistable={!highlight}\n    >\n      <StyledText size={TextSize.Small}>\n        {__('Add a brief description of the image.', 'web-stories')}\n      </StyledText>\n      <Row>\n        <TextArea\n          ref={(node) => {\n            if (node && highlight?.focus && highlight?.showEffect) {\n              node.addEventListener('keydown', cancelHighlight, { once: true });\n              node.focus();\n            }\n          }}\n          placeholder={alt === MULTIPLE_VALUE ? MULTIPLE_DISPLAY_VALUE : ''}\n          value={alt || ''}\n          onChange={(evt) =>\n            pushUpdate({ alt: evt?.target?.value?.trim() || null }, true)\n          }\n          aria-label={__('Assistive text', 'web-stories')}\n          maxLength={MIN_MAX.ALT_TEXT.MAX}\n          rows={2}\n          isIndeterminate={alt === MULTIPLE_VALUE}\n        />\n      </Row>\n    </SimplePanel>\n  );\n}\n\nImageAccessibilityPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default ImageAccessibilityPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/imageAccessibility/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './imageAccessibility';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/imageAccessibility/test/imageAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { renderPanel } from '../../../shared/test/_utils';\nimport ImageAccessibility from '../imageAccessibility';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../../../../constants';\n\ndescribe('Panels/ImageAccessibility', () => {\n  const defaultElement = {\n    type: 'image',\n    resource: { alt: '', src: '1' },\n  };\n  function arrange(...args) {\n    return renderPanel(ImageAccessibility, ...args);\n  }\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:imageAccessibility',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render <ImageAccessibility /> panel', () => {\n    arrange([defaultElement]);\n    const input = screen.getByRole('textbox', { name: 'Assistive text' });\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should display Mixed placeholder in case of mixed multi-selection', () => {\n    arrange([\n      defaultElement,\n      {\n        type: 'image',\n        resource: { alt: 'Hello!', src: '2' },\n      },\n    ]);\n    const input = screen.getByRole('textbox', { name: 'Assistive text' });\n    expect(input.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n    expect(input).toHaveValue('');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as AnimationPanel } from './animation';\nexport { default as AudioStickerPanel } from './audioSticker';\nexport { default as BorderStylePanel } from './border';\nexport { default as CaptionsPanel } from './captions';\nexport { default as ElementAlignmentPanel } from './alignment';\nexport { default as FilterPanel } from './filter';\nexport { default as ImageAccessibilityPanel } from './imageAccessibility';\nexport { default as LinkPanel } from './link';\nexport { default as PageAdvancementPanel } from './pageAdvancement';\nexport { default as PageAttachmentPanel } from './pageAttachment';\nexport { default as PageBackgroundAudioPanel } from './pageBackgroundAudio';\nexport { default as PageBackgroundPanel } from './pageBackground';\nexport { default as ProductPanel } from './product';\nexport { default as ShapeStylePanel } from './shapeStyle';\nexport { default as SizePositionPanel } from './sizePosition';\nexport { default as TextAccessibilityPanel } from './textAccessibility';\nexport { default as TextStylePanel } from './textStyle';\nexport { default as VideoAccessibilityPanel } from './videoAccessibility';\nexport { default as VideoOptionsPanel } from './videoOptions';\nexport { default as VideoSegmentPanel } from './videoSegment';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/link/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './link';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/link/karma/link.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport useInsertElement from '../../../../canvas/useInsertElement';\n\ndescribe('Link Panel', () => {\n  let fixture;\n  let linkPanel;\n  let safezone;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const moveElementToBottom = async (frame, frameY = 0) => {\n    safezone = fixture.querySelector('[data-testid=\"safezone\"]');\n    const safezoneHeight = safezone?.getBoundingClientRect()?.height;\n    const frameHeight = frame?.getBoundingClientRect()?.height;\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(frame, 10, 10),\n      down(),\n      moveBy(0, safezoneHeight - frameHeight - frameY - 50, { steps: 10 }),\n      up(),\n    ]);\n  };\n\n  const setPageAttachmentLink = async (link) => {\n    const input = fixture.screen.getByLabelText(\n      'Type an address to add a page attachment link'\n    );\n    await fixture.events.click(input, { clickCount: 3 });\n    await fixture.events.keyboard.type(link);\n    await fixture.events.keyboard.press('tab');\n  };\n\n  async function clickOnTarget(target, key = false) {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    if (key) {\n      await fixture.events.keyboard.down(key);\n    }\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n    if (key) {\n      await fixture.events.keyboard.up(key);\n    }\n  }\n\n  async function closePanel(name) {\n    const btn = fixture.screen.getByRole('button', { name });\n    await fixture.events.click(btn);\n  }\n\n  describe('CUJ: Creator Can Add A Link: Apply a link to any element', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n      });\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      linkPanel = fixture.editor.sidebar.designPanel.link;\n    });\n\n    it('should correctly show focus border both when using keyboard and mouse', async () => {\n      // Click input\n      await fixture.events.click(linkPanel.address);\n\n      // Verify input has focus\n      expect(linkPanel.address).toHaveFocus();\n\n      // Screenshot it\n      await fixture.snapshot('Link input has focus from mouse');\n\n      // shift-tab, then tab to re-focus\n      await fixture.events.keyboard.shortcut('shift+tab');\n      await fixture.events.keyboard.press('tab');\n\n      // Verify input still has focus\n      expect(linkPanel.address).toHaveFocus();\n\n      // Screenshot it\n      await fixture.snapshot('Link input has focus from keyboard');\n    });\n\n    it('should add protocol automatically on blurring', async () => {\n      await fixture.events.click(linkPanel.address);\n      await fixture.events.keyboard.type('example.com');\n\n      await fixture.events.keyboard.press('tab');\n      expect(linkPanel.address.value).toBe('https://example.com');\n    });\n\n    it('should not add additional protocol if already present', async () => {\n      await fixture.events.click(linkPanel.address);\n      await fixture.events.keyboard.type('https://example.com');\n\n      await fixture.events.keyboard.press('tab');\n      expect(linkPanel.address.value).toBe('https://example.com');\n    });\n\n    it('should display the link tooltip correctly', async () => {\n      const linkDescription = 'Example description';\n      // make sure address input exists\n      await waitFor(() => {\n        if (!linkPanel.address) {\n          throw new Error('address input not ready');\n        }\n      });\n\n      await fixture.events.click(linkPanel.address);\n      await fixture.events.keyboard.type('example.com');\n\n      // Debounce time for populating meta-data.\n      await fixture.events.keyboard.press('tab');\n      // make sure description input exists\n      await waitFor(() => {\n        if (!linkPanel.description) {\n          throw new Error('description input not ready');\n        }\n      });\n      await fixture.events.click(linkPanel.description, { clickCount: 3 });\n      // needed to ensure all text gets entered otherwise the click event can\n      // overlap the text input and we end up not typing all letters.\n      await fixture.events.sleep(500);\n      await fixture.events.keyboard.type(linkDescription);\n      await fixture.events.keyboard.press('tab');\n      const container = fixture.container;\n      // Unselect element.\n      const fullbleedElements = await within(container).findAllByTestId(\n        'fullbleed',\n        {\n          timeout: 2000,\n        }\n      );\n      // There are three fullbleed elements; [0](Display layer), [1](Frames layer), and [2](Edit layer),\n      const { left, top } = fullbleedElements[1].getBoundingClientRect();\n      await fixture.events.mouse.click(left - 5, top - 5);\n\n      // Move mouse to hover over the element.\n      const frame = await waitFor(() => {\n        const frameNode = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!frameNode) {\n          throw new Error('node not ready');\n        }\n        expect(frameNode).toBeTruthy();\n        return frameNode;\n      });\n\n      await fixture.events.mouse.moveRel(frame, 10, 10);\n      const tooltip = await fixture.screen.findByText(linkDescription);\n      expect(tooltip).toHaveTextContent(linkDescription);\n      await fixture.snapshot(\n        'Element is hovered on. The link tooltip is visible'\n      );\n\n      // Select the element again.\n      await fixture.events.click(frame);\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await waitFor(() => {\n        if (!fixture.editor.sidebar.designPanel.link.address) {\n          throw new Error('address element not ready');\n        }\n      });\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.link.address,\n        { clickCount: 3 }\n      );\n      await fixture.events.sleep(500);\n      await fixture.events.keyboard.press('del');\n\n      // Verify that the description is not displayed when hovering without url.\n      await fixture.events.mouse.click(left - 5, top - 5);\n      await fixture.events.mouse.moveRel(frame, 50, 10);\n      const removedDescription = fixture.screen.queryByText(linkDescription);\n      expect(removedDescription).toBeNull();\n      await fixture.snapshot(\n        'Element is hovered on. The link tooltip is not visible'\n      );\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should invoke API when looking up link');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should display error when API errors');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should display link details when API succeeds');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should be able to apply a link to a shape element');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should be able to apply a link to a image element');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should be able to apply a link to a video element');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should not be able to apply a link to a background shape element');\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should not be able to apply a link to a background media element');\n  });\n\n  describe('CUJ: Creator Can Add A Link: Link with Page Attachment', () => {\n    beforeEach(async () => {\n      // Open Style Pane\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n\n      // Select Page.\n      // Click the background element\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        10,\n        10\n      );\n\n      // Add Page Attachment\n      await setPageAttachmentLink('http://pageattachment.com');\n    });\n\n    it('should not allow adding link in Page Attachment area', async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const element = await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: createSolidFromString('#ff00ff'),\n          mask: { type: 'rectangle' },\n          x: 100,\n          y: 100,\n          width: 50,\n          height: 50,\n        })\n      );\n      const frame = fixture.editor.canvas.framesLayer.frame(element.id).node;\n      await moveElementToBottom(frame, 0);\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await closePanel('Selection');\n      await closePanel('Color');\n      await closePanel('Border');\n\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      linkPanel = fixture.editor.sidebar.designPanel.link;\n      await fixture.events.click(linkPanel.address);\n\n      await fixture.snapshot('Page Attachment warning & dashed line visible');\n\n      const warning = await waitFor(() =>\n        fixture.screen.getByText(\n          'Link can not reside below the dashed line when a page attachment is present'\n        )\n      );\n      expect(warning).toBeDefined();\n    });\n\n    it('should not allow adding link to multi-selection in Page Attachment area', async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const element1 = await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'Hello World!',\n          x: 40,\n          y: 140,\n          width: 250,\n        })\n      );\n      const frame = fixture.editor.canvas.framesLayer.frame(element1.id).node;\n      await fixture.act(() =>\n        insertElement('shape', {\n          backgroundColor: createSolidFromString('#ff00ff'),\n          mask: { type: 'rectangle' },\n          x: 40,\n          y: 0,\n          width: 50,\n          height: 50,\n        })\n      );\n      // Select the first element as well.\n      await clickOnTarget(frame, 'Shift');\n\n      await moveElementToBottom(frame);\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      linkPanel = fixture.editor.sidebar.designPanel.link;\n      await fixture.events.click(linkPanel.address);\n\n      await fixture.snapshot(\n        'Warning & dashed line visible with multi-selection'\n      );\n\n      const warning = fixture.screen.getByText(\n        'Link can not reside below the dashed line when a page attachment is present'\n      );\n      expect(warning).toBeDefined();\n    });\n  });\n\n  describe('CUJ: Creator Can Add A Link: Apply a link to multi-selection', () => {\n    let frame1;\n    let frame2;\n\n    beforeEach(async () => {\n      safezone = fixture.querySelector('[data-testid=\"safezone\"]');\n      // Add two elements.\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      // First one with link.\n      const element1 = await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'Hello World!',\n          x: 40,\n          y: 0,\n          width: 250,\n          link: {\n            url: 'https://example.com',\n          },\n        })\n      );\n      frame1 = fixture.editor.canvas.framesLayer.frame(element1.id).node;\n      const element2 = await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'Hello again!',\n          x: 40,\n          y: 100,\n          width: 250,\n        })\n      );\n      frame2 = fixture.editor.canvas.framesLayer.frame(element2.id).node;\n\n      // Select both elements.\n      await clickOnTarget(frame1, 'Shift');\n    });\n\n    it('should allow changing link for two elements at the same time', async () => {\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      linkPanel = fixture.editor.sidebar.designPanel.link;\n      await fixture.events.click(linkPanel.address);\n\n      expect(linkPanel.address.value).toBe('');\n\n      await fixture.events.keyboard.type('http://google.com');\n\n      await fixture.events.keyboard.press('tab');\n\n      // Click the elements separately to verify having the new link set.\n      await clickOnTarget(frame1);\n      expect(linkPanel.address.value).toBe('http://google.com');\n\n      await clickOnTarget(frame2);\n      expect(linkPanel.address.value).toBe('http://google.com');\n    });\n  });\n\n  describe('CUJ: Creator Can Add A Link: Remove applied link', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n      });\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.linkSection\n      );\n      linkPanel = fixture.editor.sidebar.designPanel.link;\n      await fixture.events.click(linkPanel.address);\n      await fixture.events.keyboard.type('http://google.com');\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n    xit('should be able to removed an applied a link');\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n  xdescribe('CUJ: Creator Can Add A Link: Edit brand icon', () => {\n    it('should be able to edit brand icon');\n\n    it('should be able to remove brand icon');\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- tests not implemented yet\n  xdescribe('CUJ: Creator Can Add A Link: Edit description', () => {\n    it('should be able to edit description');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/link/link.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n  useDebouncedCallback,\n  useBatchingCallback,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  DropDown,\n  Input,\n  Placement,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport {\n  isValidUrl,\n  toAbsoluteUrl,\n  withProtocol,\n} from '@googleforcreators/url';\nimport { LinkType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport { useAPI, useCanvas, useStory } from '../../../../app';\nimport useElementsWithLinks from '../../../../utils/useElementsWithLinks';\nimport { Row, LinkInput, LinkIcon, Switch } from '../../../form';\nimport { createLink } from '../../../elementLink';\nimport { SimplePanel } from '../../panel';\nimport { inputContainerStyleOverride } from '../../shared/styles';\nimport { LinkRelations, useCommonObjectValue } from '../../shared';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\n\nconst IconInfo = styled.div`\n  display: flex;\n  flex-direction: column;\n  margin-left: 20px;\n`;\n\nconst IconText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst Error = styled.span`\n  font-size: 12px;\n  line-height: 16px;\n  color: ${({ theme }) => theme.colors.fg.negative};\n`;\n\nconst StyledSwitch = styled(Switch)`\n  width: 100%;\n`;\n\nfunction LinkPanel({ selectedElements, pushUpdateForObject }) {\n  const { clearEditing, setDisplayLinkGuidelines, displayLinkGuidelines } =\n    useCanvas((state) => ({\n      clearEditing: state.actions.clearEditing,\n      setDisplayLinkGuidelines: state.actions.setDisplayLinkGuidelines,\n      displayLinkGuidelines: state.state.displayLinkGuidelines,\n    }));\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.Link],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  const pages = useStory(\n    ({ state }) =>\n      state?.pages\n        ?.map(({ id }, index) => ({\n          value: id,\n          label: sprintf(\n            /* translators: %s: page number. */\n            __('Page %s', 'web-stories'),\n            index + 1\n          ),\n        }))\n        .filter(({ value }) => value !== state.currentPage?.id) || []\n  );\n\n  const { hasElementsInAttachmentArea } = useElementsWithLinks();\n\n  const defaultLink = useMemo(() => createLink({ icon: null, desc: null }), []);\n\n  const linkRaw = useCommonObjectValue(selectedElements, 'link', defaultLink);\n  const link = createLink(linkRaw);\n  const {\n    url = '',\n    desc = '',\n    icon,\n    rel = [],\n    type: linkType = LinkType.Regular,\n    pageId = null,\n  } = link;\n\n  const [fetchingMetadata, setFetchingMetadata] = useState(false);\n  const [isLinkFocused, setIsLinkFocused] = useState(false);\n\n  const {\n    actions: { getLinkMetadata },\n  } = useAPI();\n\n  const { getProxiedUrl, checkResourceAccess } = useCORSProxy();\n\n  const updateLinkFromMetadataApi = useBatchingCallback(\n    ({ newUrl, newTitle, newIcon, needsProxy }) =>\n      pushUpdateForObject(\n        'link',\n        () =>\n          newUrl\n            ? createLink({\n                url: newUrl,\n                needsProxy,\n                desc: newTitle ? newTitle : '',\n                icon: newIcon ? toAbsoluteUrl(newUrl, newIcon) : '',\n              })\n            : null,\n        defaultLink,\n        true\n      ),\n    [pushUpdateForObject, defaultLink]\n  );\n\n  const [isInvalidUrl, setIsInvalidUrl] = useState(\n    !isValidUrl(withProtocol(url))\n  );\n\n  const populateMetadata = useDebouncedCallback(\n    useCallback(\n      async (newUrl) => {\n        // Nothing to fetch for tel: or mailto: links.\n        if (!newUrl.startsWith('http://') && !newUrl.startsWith('https://')) {\n          return;\n        }\n\n        setFetchingMetadata(true);\n        try {\n          const { title: newTitle, image: newIcon } = getLinkMetadata\n            ? await getLinkMetadata(newUrl)\n            : {};\n          const needsProxy = newIcon\n            ? await checkResourceAccess(newIcon)\n            : false;\n\n          updateLinkFromMetadataApi({\n            newUrl,\n            newTitle,\n            newIcon,\n            needsProxy,\n          });\n        } catch {\n          setIsInvalidUrl(true);\n        } finally {\n          setFetchingMetadata(false);\n        }\n      },\n      [checkResourceAccess, getLinkMetadata, updateLinkFromMetadataApi]\n    ),\n    1200\n  );\n\n  const handleChange = useCallback(\n    (properties, submit) => {\n      clearEditing();\n\n      populateMetadata.cancel();\n\n      if (properties.url) {\n        // Don't submit any changes in case of multiple value.\n        if (MULTIPLE_VALUE === properties.url) {\n          return;\n        }\n        const urlWithProtocol = withProtocol(properties.url);\n        const valid = isValidUrl(urlWithProtocol);\n        setIsInvalidUrl(!valid);\n\n        if (valid) {\n          populateMetadata(urlWithProtocol);\n        }\n      }\n\n      pushUpdateForObject(\n        'link',\n        properties.url !== ''\n          ? {\n              ...properties,\n            }\n          : null,\n        defaultLink,\n        submit\n      );\n    },\n    [clearEditing, pushUpdateForObject, defaultLink, populateMetadata]\n  );\n\n  const handleChangeIcon = useCallback(\n    /**\n     * Handle link icon change.\n     *\n     * @param {import('@googleforcreators/media').Resource} resource The new image.\n     */\n    (resource) => {\n      handleChange({ icon: resource?.src }, true);\n    },\n    [handleChange]\n  );\n\n  const hasLinkSet = Boolean(url?.length);\n  const displayMetaFields =\n    (hasLinkSet && !isInvalidUrl) ||\n    (linkType === LinkType.Branching && pageId);\n\n  // If we're focusing on the link input and any of the relevant values changes,\n  // Check if we need to hide/display the guidelines.\n  useEffect(() => {\n    if (isLinkFocused) {\n      // Display the guidelines if there's no link / if it's multiple value.\n      const hasLink = hasLinkSet && url !== MULTIPLE_VALUE;\n      setDisplayLinkGuidelines(hasElementsInAttachmentArea && !hasLink);\n    }\n  }, [\n    selectedElements,\n    isLinkFocused,\n    hasElementsInAttachmentArea,\n    hasLinkSet,\n    setDisplayLinkGuidelines,\n    url,\n  ]);\n\n  const linkIcon = icon ? getProxiedUrl(link, icon) : null;\n\n  const isMultipleLinkType = MULTIPLE_VALUE === linkType;\n  const isMultiplePageId = MULTIPLE_VALUE === pageId;\n  const isMultipleUrl = MULTIPLE_VALUE === url;\n  const isMultipleDesc = MULTIPLE_VALUE === desc;\n  const isMultipleRel = MULTIPLE_VALUE === rel;\n\n  const onChangeRel = useCallback(\n    (newRel) => handleChange({ rel: newRel }, true),\n    [handleChange]\n  );\n\n  const onChangeLinkType = useCallback(() => {\n    handleChange(\n      {\n        type:\n          linkType === LinkType.Regular ? LinkType.Branching : LinkType.Regular,\n      },\n      true\n    );\n  }, [handleChange, linkType]);\n  const onChangePageId = useCallback(\n    (_event, value) => {\n      handleChange({ pageId: value }, true);\n    },\n    [handleChange]\n  );\n\n  return (\n    <SimplePanel\n      name=\"link\"\n      title={__('Link', 'web-stories')}\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      isPersistable={!highlight}\n    >\n      <Row>\n        <StyledSwitch\n          groupLabel={__('Link Type', 'web-stories')}\n          name=\"link-type-switch\"\n          value={linkType === LinkType.Regular}\n          onLabel={__('Link to website', 'web-stories')}\n          offLabel={__('Link to story page', 'web-stories')}\n          disabled={isMultipleLinkType}\n          onChange={onChangeLinkType}\n        />\n      </Row>\n      {linkType === LinkType.Branching ? (\n        <Row>\n          <DropDown\n            ariaLabel={__('Page', 'web-stories')}\n            dropDownLabel={__('Page', 'web-stories')}\n            placeholder={__('Select Page', 'web-stories')}\n            options={pages}\n            placement={Placement.TopStart}\n            onMenuItemClick={onChangePageId}\n            selectedValue={pageId}\n            disabled={!pages.length || isMultiplePageId}\n          />\n        </Row>\n      ) : (\n        <LinkInput\n          ref={(node) => {\n            if (node && highlight?.focus && highlight?.showEffect) {\n              node.addEventListener('keydown', cancelHighlight, { once: true });\n              node.focus();\n            }\n          }}\n          onChange={(value) =>\n            !displayLinkGuidelines &&\n            handleChange({ url: value }, !value /* submit */)\n          }\n          onBlur={() => {\n            setDisplayLinkGuidelines(false);\n            setIsLinkFocused(false);\n          }}\n          onFocus={() => {\n            setIsLinkFocused(true);\n          }}\n          value={url || ''}\n          placeholder={\n            isMultipleUrl\n              ? MULTIPLE_DISPLAY_VALUE\n              : __('Enter an address to apply a link', 'web-stories')\n          }\n          isIndeterminate={isMultipleUrl}\n          aria-label={__('Element link', 'web-stories')}\n          hasError={displayLinkGuidelines}\n        />\n      )}\n      {displayLinkGuidelines && (\n        <Row>\n          <Error>\n            {__(\n              'Link can not reside below the dashed line when a page attachment is present',\n              'web-stories'\n            )}\n          </Error>\n        </Row>\n      )}\n\n      {displayMetaFields && (\n        <>\n          <Row>\n            <Input\n              placeholder={\n                isMultipleDesc\n                  ? MULTIPLE_DISPLAY_VALUE\n                  : __('Optional description', 'web-stories')\n              }\n              onChange={({ target }) =>\n                handleChange({ desc: target.value }, !target.value /* submit */)\n              }\n              value={desc}\n              aria-label={__('Link description', 'web-stories')}\n              isIndeterminate={isMultipleDesc}\n              disabled={fetchingMetadata}\n              containerStyleOverride={inputContainerStyleOverride}\n            />\n          </Row>\n          <Row spaceBetween={false}>\n            <LinkIcon\n              handleChange={handleChangeIcon}\n              icon={linkIcon}\n              isLoading={fetchingMetadata}\n              disabled={fetchingMetadata}\n            />\n            <IconInfo>\n              <IconText size={TextSize.Small}>\n                {__('Optional brand icon', 'web-stories')}\n              </IconText>\n            </IconInfo>\n          </Row>\n          {!isMultipleRel && linkType === LinkType.Regular && (\n            <LinkRelations onChangeRel={onChangeRel} rel={rel} />\n          )}\n        </>\n      )}\n    </SimplePanel>\n  );\n}\n\nLinkPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdateForObject: PropTypes.func.isRequired,\n};\n\nexport default LinkPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/link/test/link.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport APIContext from '../../../../../app/api/context';\nimport ConfigContext from '../../../../../app/config/context';\nimport StoryContext from '../../../../../app/story/context';\nimport CanvasContext from '../../../../../app/canvas/context';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport LinkPanel from '../link';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../../../../constants';\n\njest.mock('@googleforcreators/element-library');\n\nfunction MediaUpload({ render }) {\n  const open = jest.fn();\n  return render(open);\n}\n\nfunction arrange(selectedElements) {\n  const configValue = {\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    MediaUpload,\n  };\n\n  const canvasContext = {\n    state: {\n      displayLinkGuidelines: true,\n    },\n    actions: {\n      clearEditing: jest.fn(),\n      setDisplayLinkGuidelines: jest.fn(),\n    },\n  };\n\n  const storyContextValue = {\n    state: {\n      currentPage: { elements: [] },\n    },\n  };\n\n  const apiValue = {\n    actions: {\n      getProxyUrl: (src) => {\n        return 'http://proxy?url=' + src;\n      },\n      getLinkMetadata: jest.fn(),\n    },\n  };\n\n  const wrapper = ({ children }) => (\n    <APIContext.Provider value={apiValue}>\n      <ConfigContext.Provider value={configValue}>\n        <StoryContext.Provider value={storyContextValue}>\n          <CanvasContext.Provider value={canvasContext}>\n            {children}\n          </CanvasContext.Provider>\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    </APIContext.Provider>\n  );\n\n  return renderPanel(LinkPanel, selectedElements, wrapper);\n}\n\ndescribe('Panels/Link', () => {\n  const DEFAULT_ELEMENT = {\n    id: '1',\n    isBackground: false,\n    x: 10,\n    y: 10,\n    width: 100,\n    height: 80,\n    rotationAngle: 0,\n    link: {\n      url: '',\n    },\n  };\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:link',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should not display metadata fields if URL is missing', () => {\n    arrange([DEFAULT_ELEMENT]);\n    expect(\n      screen.getByRole('textbox', {\n        name: 'Element link',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.queryByRole('textbox', {\n        name: 'Link description',\n      })\n    ).not.toBeInTheDocument();\n    expect(\n      screen.queryByRole('button', {\n        name: 'Edit link icon',\n      })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should display an error message for invalid URLs', () => {\n    arrange([\n      {\n        ...DEFAULT_ELEMENT,\n        link: {\n          url: 'http://',\n        },\n      },\n    ]);\n    expect(screen.getByText('Invalid web address.')).toBeInTheDocument();\n  });\n\n  it('should not display metadata fields if URL is invalid', () => {\n    arrange([\n      {\n        ...DEFAULT_ELEMENT,\n        link: {\n          url: 'http://',\n        },\n      },\n    ]);\n    expect(\n      screen.queryByRole('textbox', {\n        name: 'Link description',\n      })\n    ).not.toBeInTheDocument();\n    expect(\n      screen.queryByRole('button', {\n        name: 'Edit link icon',\n      })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should display icon', () => {\n    arrange([\n      {\n        ...DEFAULT_ELEMENT,\n        link: {\n          url: 'http://example.com',\n          desc: 'Example',\n          icon: 'http://example.com/image.png',\n          needsProxy: true,\n        },\n      },\n    ]);\n\n    const descInput = screen.queryByRole('textbox', {\n      name: 'Link description',\n    });\n    expect(descInput).toHaveValue('Example');\n    const imgTags = screen.getByRole('img');\n    expect(screen.getByRole('img')).toBeInTheDocument();\n    expect(imgTags.src).toBe('http://proxy/?url=http://example.com/image.png');\n  });\n\n  it('should display Mixed placeholder in case of mixed values multi-selection', () => {\n    arrange([\n      {\n        ...DEFAULT_ELEMENT,\n        link: {\n          url: 'http://example.com',\n          desc: 'Example',\n        },\n      },\n      {\n        ...DEFAULT_ELEMENT,\n        id: 2,\n      },\n    ]);\n\n    const linkInput = screen.getByRole('textbox', {\n      name: 'Element link',\n    });\n    expect(linkInput.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n    expect(linkInput).toHaveValue('');\n\n    const descInput = screen.queryByRole('textbox', {\n      name: 'Link description',\n    });\n    expect(descInput.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n    expect(descInput).toHaveValue('');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAdvancement/customPageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport GeneralPageAdvancementPanel from '../../shared/generalPageAdvancement';\n\nfunction CustomPageAdvancementPanel() {\n  const {\n    isOverridden,\n    autoAdvance,\n    pageDuration,\n    updateCurrentPageProperties,\n  } = useStory(\n    ({\n      state: {\n        story: { autoAdvance: defaultAutoAdvance, defaultPageDuration },\n        currentPage: { advancement },\n      },\n      actions: { updateCurrentPageProperties },\n    }) => ({\n      isOverridden: typeof advancement === 'object',\n      autoAdvance: advancement?.autoAdvance ?? defaultAutoAdvance,\n      pageDuration: advancement?.pageDuration ?? defaultPageDuration,\n      updateCurrentPageProperties,\n    })\n  );\n\n  const onUpdate = useCallback(\n    (properties) => {\n      if (properties.override === false) {\n        updateCurrentPageProperties({ properties: { advancement: undefined } });\n      } else {\n        const { override, ...rest } = properties;\n        const advancement = {\n          autoAdvance,\n          pageDuration,\n          ...rest,\n        };\n        updateCurrentPageProperties({ properties: { advancement } });\n      }\n    },\n    [autoAdvance, pageDuration, updateCurrentPageProperties]\n  );\n\n  return (\n    <GeneralPageAdvancementPanel\n      panelName={'customPageAdvancement'}\n      onUpdate={onUpdate}\n      autoAdvance={autoAdvance}\n      pageDuration={pageDuration}\n      hasOverrideEnabled={isOverridden}\n      allowsOverride\n      collapsedByDefault\n    >\n      {__(\n        'Control whether this page auto-advances to the next page, or whether the reader has to manually tap to advance.',\n        'web-stories'\n      )}\n    </GeneralPageAdvancementPanel>\n  );\n}\n\nexport default CustomPageAdvancementPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAdvancement/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './customPageAdvancement';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAttachment/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './pageAttachment';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAttachment/outlink.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useState, useEffect } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { isValidUrl, withProtocol } from '@googleforcreators/url';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas } from '../../../../app';\nimport useElementsWithLinks from '../../../../utils/useElementsWithLinks';\nimport { LinkRelations } from '../../shared';\nimport { CallToActionText, Theme, Icon, LinkUrl } from './shared';\n\nfunction Outlink({ pageAttachment, updatePageAttachment }) {\n  const { setDisplayLinkGuidelines } = useCanvas((state) => ({\n    setDisplayLinkGuidelines: state.actions.setDisplayLinkGuidelines,\n  }));\n\n  const { url, ctaText, icon, theme, rel = [], needsProxy } = pageAttachment;\n  const [displayWarning, setDisplayWarning] = useState(false);\n  const [isFetching, setIsFetching] = useState(false);\n\n  const [isInvalidUrl, setIsInvalidUrl] = useState(\n    url && !isValidUrl(withProtocol(url).trim())\n  );\n\n  const hasValidUrl = Boolean(url) && !isInvalidUrl;\n\n  const { hasLinksInAttachmentArea } = useElementsWithLinks();\n\n  // Stop displaying guidelines when unmounting.\n  useEffect(() => {\n    return () => {\n      setDisplayLinkGuidelines(false);\n    };\n  }, [hasLinksInAttachmentArea, setDisplayLinkGuidelines, url]);\n\n  // If we focus on the field and there are links in the area.\n  const onFocus = useCallback(() => {\n    if (hasLinksInAttachmentArea && !url?.length) {\n      setDisplayWarning(true);\n      setDisplayLinkGuidelines(true);\n    }\n  }, [hasLinksInAttachmentArea, setDisplayLinkGuidelines, url?.length]);\n\n  // If the Page Attachment is added, stop displaying the warning.\n  useEffect(() => {\n    if (displayWarning && url?.length) {\n      setDisplayWarning(false);\n    }\n  }, [url, displayWarning]);\n\n  const onChangeRel = useCallback(\n    (newRel) => updatePageAttachment({ rel: newRel }, true),\n    [updatePageAttachment]\n  );\n\n  let hint;\n  const hasError = displayWarning || isInvalidUrl;\n  if (hasError) {\n    hint = displayWarning\n      ? __(\n          'Links cannot reside below the dashed line when a page attachment is present. If you add a page attachment, your viewers will not be able to click on the link.',\n          'web-stories'\n        )\n      : __('Invalid link', 'web-stories');\n  }\n\n  return (\n    <>\n      <LinkUrl\n        value={url}\n        onChange={updatePageAttachment}\n        isFetching={isFetching}\n        setIsFetching={setIsFetching}\n        setIsInvalidUrl={setIsInvalidUrl}\n        hint={hint}\n        onFocus={onFocus}\n        hasError={hasError}\n      />\n      {hasValidUrl && (\n        <>\n          <CallToActionText\n            value={ctaText}\n            defaultValue={__('Learn more', 'web-stories')}\n            onChange={updatePageAttachment}\n          />\n          <Theme theme={theme} onChange={updatePageAttachment} />\n        </>\n      )}\n      {hasValidUrl && (\n        <>\n          <Icon\n            icon={icon}\n            isFetching={isFetching}\n            needsProxy={needsProxy}\n            onChange={updatePageAttachment}\n          />\n          <LinkRelations onChangeRel={onChangeRel} rel={rel} />\n        </>\n      )}\n    </>\n  );\n}\n\nOutlink.propTypes = {\n  pageAttachment: PropTypes.shape({\n    url: PropTypes.string,\n    ctaText: PropTypes.string,\n    icon: PropTypes.string,\n    theme: PropTypes.string,\n    rel: PropTypes.arrayOf(PropTypes.string),\n    needsProxy: PropTypes.bool,\n  }).isRequired,\n  updatePageAttachment: PropTypes.func.isRequired,\n};\n\nexport default Outlink;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAttachment/pageAttachment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app';\nimport { SimplePanel } from '../../panel';\nimport Outlink from './outlink';\nimport ShoppingAttachment from './shoppingAttachment';\n\nfunction PageAttachmentPanel() {\n  const {\n    pageAttachment,\n    shoppingAttachment,\n    updateCurrentPageProperties,\n    hasProducts,\n  } = useStory(({ state, actions }) => ({\n    updateCurrentPageProperties: actions.updateCurrentPageProperties,\n    currentPage: state.currentPage,\n    pageAttachment: state.currentPage.pageAttachment || {},\n    shoppingAttachment: state.currentPage.shoppingAttachment || {},\n    hasProducts: state.currentPage.elements?.some(\n      ({ type, product }) =>\n        type === ELEMENT_TYPES.PRODUCT && product?.productId\n    ),\n  }));\n\n  const updateShoppingAttachment = useCallback(\n    (value) => {\n      updateCurrentPageProperties({\n        properties: {\n          shoppingAttachment: {\n            ...shoppingAttachment,\n            ...value,\n          },\n        },\n      });\n    },\n    [updateCurrentPageProperties, shoppingAttachment]\n  );\n\n  const updatePageAttachment = useCallback(\n    (value) => {\n      updateCurrentPageProperties({\n        properties: {\n          pageAttachment: {\n            ...pageAttachment,\n            ...value,\n          },\n        },\n      });\n    },\n    [updateCurrentPageProperties, pageAttachment]\n  );\n\n  return (\n    <SimplePanel\n      name=\"pageAttachment\"\n      title={__('Call to Action', 'web-stories')}\n      collapsedByDefault={false}\n    >\n      {hasProducts && (\n        <ShoppingAttachment\n          shoppingAttachment={shoppingAttachment}\n          updateShoppingAttachment={updateShoppingAttachment}\n        />\n      )}\n      {!hasProducts && (\n        <Outlink\n          pageAttachment={pageAttachment}\n          updatePageAttachment={updatePageAttachment}\n        />\n      )}\n    </SimplePanel>\n  );\n}\n\nexport default PageAttachmentPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAttachment/shared.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  useCallback,\n  useDebouncedCallback,\n  useMemo,\n  useState,\n} from '@googleforcreators/react';\nimport {\n  Checkbox,\n  Input,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  isValidUrl,\n  toAbsoluteUrl,\n  withProtocol,\n} from '@googleforcreators/url';\n\n/**\n * Internal dependencies\n */\nimport { LinkIcon, LinkInput, Row } from '../../../form';\nimport { OUTLINK_THEME } from '../../../../constants';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\nimport { useAPI } from '../../../../app';\n\nconst Label = styled.label`\n  margin-left: 12px;\n`;\n\nconst StyledCheckbox = styled(Checkbox)`\n  ${({ theme }) => `\n    input[type='checkbox']:focus-visible ~ div, input[type='checkbox']:focus ~ div {\n      box-shadow: 0px 0px 0 2px ${theme.colors.bg.secondary}, 0px 0px 0 4px ${theme.colors.border.focus} !important;\n    }\n  `}\n`;\n\nconst StyledRow = styled(Row)`\n  justify-content: flex-start;\n`;\n\nconst Space = styled.div`\n  width: 20px;\n`;\n\nexport function CallToActionText({ value, defaultValue, onChange }) {\n  const [text, setText] = useState(value || defaultValue);\n\n  const debouncedUpdate = useDebouncedCallback(onChange, 300);\n\n  const handleBlur = useCallback(\n    ({ target }) => {\n      if (!target.value) {\n        onChange({ ctaText: undefined });\n        setText(defaultValue);\n      } else {\n        debouncedUpdate.cancel();\n        onChange({\n          ctaText: text || undefined,\n        });\n      }\n    },\n    [text, debouncedUpdate, defaultValue, onChange]\n  );\n\n  const handleChangeCta = useCallback(\n    ({ target }) => {\n      const { value: newText } = target;\n      // This allows smooth input value change without any lag.\n      setText(newText);\n      debouncedUpdate({ ctaText: newText });\n    },\n    [debouncedUpdate]\n  );\n\n  const isDefault = value === defaultValue;\n\n  return (\n    <Row>\n      <Input\n        onChange={handleChangeCta}\n        onBlur={handleBlur}\n        value={text}\n        aria-label={__('Call to Action text', 'web-stories')}\n        suffix={isDefault ? __('Default', 'web-stories') : null}\n      />\n    </Row>\n  );\n}\n\nCallToActionText.propTypes = {\n  value: PropTypes.string,\n  defaultValue: PropTypes.string.isRequired,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport function Theme({ theme, onChange }) {\n  const checkboxId = useMemo(() => `cb-${uuidv4()}`, []);\n\n  const handleChangeTheme = useCallback(\n    (evt) => {\n      onChange({\n        theme: evt.target.checked ? OUTLINK_THEME.DARK : OUTLINK_THEME.LIGHT,\n      });\n    },\n    [onChange]\n  );\n\n  return (\n    <StyledRow>\n      {/* The default is light theme, only if checked, use dark theme */}\n      <StyledCheckbox\n        id={checkboxId}\n        checked={theme === OUTLINK_THEME.DARK}\n        onChange={handleChangeTheme}\n      />\n      <Label htmlFor={checkboxId}>\n        <Text.Span size={TextSize.Small}>\n          {__('Use dark theme', 'web-stories')}\n        </Text.Span>\n      </Label>\n    </StyledRow>\n  );\n}\n\nTheme.propTypes = {\n  theme: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport function Icon({ icon, onChange, isFetching, needsProxy }) {\n  const { getProxiedUrl } = useCORSProxy();\n\n  const handleChangeIcon = useCallback(\n    /**\n     * Handle page attachment icon change.\n     *\n     * @param {import('@googleforcreators/media').Resource} resource The new image.\n     */\n    (resource) => {\n      onChange({ icon: resource?.src }, true);\n    },\n    [onChange]\n  );\n\n  const iconUrl = icon ? getProxiedUrl({ needsProxy }, icon) : null;\n\n  return (\n    <StyledRow>\n      <LinkIcon\n        handleChange={handleChangeIcon}\n        icon={iconUrl}\n        isLoading={isFetching}\n        disabled={isFetching}\n      />\n      <Space />\n      <Text.Span size={TextSize.Small}>\n        {__('Link icon', 'web-stories')}\n      </Text.Span>\n    </StyledRow>\n  );\n}\n\nIcon.propTypes = {\n  icon: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n  isFetching: PropTypes.bool,\n  needsProxy: PropTypes.bool,\n};\n\nexport function LinkUrl({\n  value,\n  onChange,\n  setIsInvalidUrl,\n  setIsFetching,\n  onFocus,\n  hint,\n  hasError,\n}) {\n  const {\n    actions: { getLinkMetadata },\n  } = useAPI();\n\n  const [_url, _setUrl] = useState(value);\n\n  const debouncedUpdate = useDebouncedCallback(onChange, 300);\n  const { checkResourceAccess } = useCORSProxy();\n\n  const populateUrlData = useDebouncedCallback(\n    useCallback(\n      async (newValue) => {\n        // Nothing to fetch for tel: or mailto: links.\n        if (\n          !newValue.startsWith('http://') &&\n          !newValue.startsWith('https://')\n        ) {\n          return;\n        }\n\n        setIsFetching(true);\n        try {\n          const { image } = getLinkMetadata\n            ? await getLinkMetadata(newValue)\n            : {};\n          const iconUrl = image ? toAbsoluteUrl(newValue, image) : '';\n          const needsProxy = iconUrl\n            ? await checkResourceAccess(iconUrl)\n            : false;\n\n          onChange({\n            url: newValue,\n            icon: iconUrl,\n            needsProxy,\n          });\n        } catch {\n          // We're allowing to save invalid URLs, however, remove icon in this case.\n          onChange({ url: newValue, icon: '', needsProxy: false });\n          setIsInvalidUrl(true);\n        } finally {\n          setIsFetching(false);\n        }\n      },\n      [\n        checkResourceAccess,\n        getLinkMetadata,\n        onChange,\n        setIsFetching,\n        setIsInvalidUrl,\n      ]\n    ),\n    1200\n  );\n\n  const handleChangeUrl = useCallback(\n    (newValue) => {\n      populateUrlData.cancel();\n\n      _setUrl(newValue);\n      setIsInvalidUrl(false);\n      const urlWithProtocol = withProtocol(newValue.trim());\n      const valid = isValidUrl(urlWithProtocol);\n      if (valid) {\n        populateUrlData(urlWithProtocol);\n      }\n    },\n    [populateUrlData, setIsInvalidUrl]\n  );\n\n  const onBlur = useCallback(() => {\n    debouncedUpdate.cancel();\n    onChange({\n      url: _url?.trim().length ? withProtocol(_url.trim()) : '',\n    });\n  }, [_url, debouncedUpdate, onChange]);\n\n  return (\n    <LinkInput\n      onChange={(newValue) => handleChangeUrl(newValue?.trim())}\n      onBlur={onBlur}\n      onFocus={onFocus}\n      value={_url}\n      clear\n      aria-label={__(\n        'Type an address to add a page attachment link',\n        'web-stories'\n      )}\n      hasError={hasError}\n      hint={hint}\n    />\n  );\n}\n\nLinkUrl.propTypes = {\n  value: PropTypes.string,\n  onChange: PropTypes.func.isRequired,\n  setIsInvalidUrl: PropTypes.func.isRequired,\n  hasError: PropTypes.bool,\n  setIsFetching: PropTypes.func.isRequired,\n  onFocus: PropTypes.func.isRequired,\n  hint: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageAttachment/shoppingAttachment.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Row } from '../../../form';\nimport { CallToActionText, Theme } from './shared';\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nfunction ShoppingAttachment({ shoppingAttachment, updateShoppingAttachment }) {\n  const { ctaText, theme } = shoppingAttachment;\n\n  return (\n    <>\n      <Row>\n        <HelperText>\n          {__(\n            'Since there are products on this page, you cannot add a regular page attachment, but only customize the appearance of the shopping call to action.',\n            'web-stories'\n          )}\n        </HelperText>\n      </Row>\n      <CallToActionText\n        value={ctaText}\n        defaultValue={__('Shop Now', 'web-stories')}\n        onChange={updateShoppingAttachment}\n      />\n      <Theme theme={theme} onChange={updateShoppingAttachment} />\n    </>\n  );\n}\n\nShoppingAttachment.propTypes = {\n  shoppingAttachment: PropTypes.shape({\n    ctaText: PropTypes.string,\n    theme: PropTypes.string,\n  }).isRequired,\n  updateShoppingAttachment: PropTypes.func.isRequired,\n};\n\nexport default ShoppingAttachment;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackground/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './pageBackground';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackground/karma/pageBackground.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Page background panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('CUJ: Creator Can Manipulate an Image/Video on Canvas: Remove background media', () => {\n    it('should select page after removing background media', async () => {\n      const bgFrame = fixture.editor.canvas.framesLayer.frames[0].node;\n      const mediaItem = fixture.editor.library.media.item(0);\n      await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n        moveRel(mediaItem, 20, 20),\n        down(),\n        moveRel(bgFrame, 15, 15, { steps: 30 }),\n        up(),\n      ]);\n\n      // Allow the background to be set.\n      await fixture.events.sleep(300);\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.pageBackground.detachBg\n      );\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(\n        storyContext.state.selectedElements[0].isDefaultBackground\n      ).toBeTrue();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackground/pageBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  Text as DefaultText,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  getDefinitionForType,\n  createNewElement,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Color, MediaUploadButton, Row as DefaultRow } from '../../../form';\nimport { useConfig, useStory, useLayout } from '../../../../app';\nimport {\n  getPagesWithFailedContrast,\n  ACCESSIBILITY_COPY,\n} from '../../../checklist';\nimport { SimplePanel } from '../../panel';\nimport { FlipControls } from '../../shared';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport getElementProperties from '../../../canvas/utils/getElementProperties';\nimport Warning from '../warning';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\nimport Tooltip from '../../../tooltip';\nimport { noop } from '../../../../utils/noop';\n\nconst DEFAULT_FLIP = { horizontal: false, vertical: false };\n\nconst Row = styled(DefaultRow)`\n  justify-content: flex-start;\n`;\n\nconst SelectedMedia = styled.div`\n  width: 128px;\n  height: 36px;\n  border-radius: 4px;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  display: flex;\n  justify-content: space-between;\n  margin-right: 12px;\n`;\n\nconst MediaWrapper = styled.div`\n  height: 24px;\n  width: 24px;\n  border-radius: 4px;\n  overflow: hidden;\n  margin: 5px;\n  img {\n    object-fit: cover;\n    max-height: 100%;\n    max-width: 100%;\n  }\n`;\n\nconst RemoveButton = styled(Button)`\n  margin: 1px;\n  align-self: center;\n`;\n\nconst ReplaceButton = styled(Button).attrs({\n  size: ButtonSize.Small,\n  variant: ButtonVariant.Square,\n  type: ButtonType.Tertiary,\n})`\n  margin-right: 8px;\n`;\n\nconst Text = styled(DefaultText.Paragraph)`\n  align-self: center;\n  width: 55px;\n`;\n\nfunction PageBackgroundPanel({ selectedElements, pushUpdate }) {\n  const { isDefaultBackground } = selectedElements[0];\n  const {\n    combineElements,\n    currentPage,\n    clearBackgroundElement,\n    updateCurrentPageProperties,\n    currentPageBackgroundColor,\n  } = useStory(({ state, actions }) => ({\n    currentPage: state.currentPage,\n    clearBackgroundElement: actions.clearBackgroundElement,\n    combineElements: actions.combineElements,\n    updateCurrentPageProperties: actions.updateCurrentPageProperties,\n    currentPageBackgroundColor:\n      !isDefaultBackground || state.currentPage?.backgroundColor,\n  }));\n  const { getProxiedUrl } = useCORSProxy();\n\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n\n  const [failedContrast, setFailedContrast] = useState(false);\n\n  const updateBackgroundColor = useCallback(\n    (value) => {\n      updateCurrentPageProperties({ properties: { backgroundColor: value } });\n    },\n    [updateCurrentPageProperties]\n  );\n\n  const removeAsBackground = useCallback(() => {\n    pushUpdate(\n      {\n        isBackground: false,\n        opacity: 100,\n      },\n      true\n    );\n    clearBackgroundElement();\n  }, [pushUpdate, clearBackgroundElement]);\n\n  /**\n   * Callback of select in media picker to replace background media.\n   *\n   * @param {Object} resource Object coming from backbone media picker.\n   */\n  const onSelect = useCallback(\n    (resource) => {\n      const element = createNewElement(\n        resource.type,\n        getElementProperties(resource.type, { resource })\n      );\n      combineElements({\n        firstElement: element,\n        secondId: selectedElements[0].id,\n      });\n      trackEvent('replace_background_media');\n    },\n    [combineElements, selectedElements]\n  );\n\n  const renderReplaceButton = useCallback(\n    (open) => (\n      <ReplaceButton onClick={open} aria-label={__('Replace', 'web-stories')}>\n        <Icons.ArrowCloud />\n      </ReplaceButton>\n    ),\n    []\n  );\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.PageBackground],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  useEffect(() => {\n    getPagesWithFailedContrast([currentPage], pageSize)\n      .then((failedPages) => {\n        // getPagesWithFailedContrast returns an array of pages, since we only care\n        // about currentPage, we can grab the single page result.\n        const result = failedPages[0]?.result;\n        // We only want to show the warning if the text is on the background element\n        const isBackgroundElement = result?.some(\n          ({ isBackground }) => isBackground\n        );\n        setFailedContrast(Boolean(isBackgroundElement));\n      })\n      .catch(noop);\n  }, [currentPage, pageSize]);\n\n  const backgroundEl = selectedElements[0];\n  if (!backgroundEl || !backgroundEl.isBackground) {\n    return null;\n  }\n  const isMedia = backgroundEl.isBackground && !isDefaultBackground;\n\n  const { backgroundColor } = currentPage;\n  const { LayerIcon } = getDefinitionForType(backgroundEl.type);\n\n  // Background can only have one selected element.\n  const flip = selectedElements[0]?.flip || DEFAULT_FLIP;\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"pageBackground\"\n      title={__('Page Background', 'web-stories')}\n      isPersistable={!highlight}\n      collapsedByDefault={false}\n    >\n      {isDefaultBackground && (\n        <Row>\n          <Color\n            ref={(node) => {\n              if (node && highlight?.focus && highlight?.showEffect) {\n                node.addEventListener('keydown', cancelHighlight, {\n                  once: true,\n                });\n                node.focus();\n              }\n            }}\n            allowsGradient\n            value={backgroundColor}\n            onChange={updateBackgroundColor}\n            label={__('Background color', 'web-stories')}\n            allowsSavedColors\n            allowsOpacity={false}\n          />\n        </Row>\n      )}\n      {isMedia && (\n        <Row expand={false}>\n          <SelectedMedia>\n            <MediaWrapper>\n              <LayerIcon\n                element={backgroundEl}\n                getProxiedUrl={getProxiedUrl}\n                currentPageBackgroundColor={currentPageBackgroundColor}\n              />\n            </MediaWrapper>\n            <Text size={TextSize.Small}>{__('Media', 'web-stories')}</Text>\n            <RemoveButton\n              aria-label={__('Detach background', 'web-stories')}\n              onClick={removeAsBackground}\n              size={ButtonSize.Small}\n              variant={ButtonVariant.Square}\n              type={ButtonType.Tertiary}\n            >\n              <Icons.Cross />\n            </RemoveButton>\n          </SelectedMedia>\n          {hasUploadMediaAction && (\n            <Tooltip title={__('Replace', 'web-stories')}>\n              <MediaUploadButton\n                buttonInsertText={__('Use as background', 'web-stories')}\n                onInsert={onSelect}\n                renderButton={renderReplaceButton}\n              />\n            </Tooltip>\n          )}\n          <FlipControls\n            onChange={(value) => pushUpdate({ flip: value }, true)}\n            value={flip}\n          />\n        </Row>\n      )}\n      {failedContrast && (\n        <Warning message={ACCESSIBILITY_COPY.lowContrast.backgroundPanel} />\n      )}\n    </SimplePanel>\n  );\n}\n\nPageBackgroundPanel.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n\nexport default PageBackgroundPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackground/test/pageBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport PageBackgroundPanel from '../pageBackground';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport ConfigContext from '../../../../../app/config/context';\nimport { StoryContext } from '../../../../../app/story';\nimport useFFmpeg from '../../../../../app/media/utils/useFFmpeg';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: jest.fn(() => ({ showSnackbar: jest.fn() })),\n}));\njest.mock('../../../../../app/media/utils/useFFmpeg');\n\nconst mockUseFFmpeg = useFFmpeg;\n\nfunction MediaUpload({ render, onSelect }) {\n  const open = () => {\n    const image = { type: 'image', src: 'media1' };\n    onSelect(image);\n  };\n\n  return render(open);\n}\n\nfunction arrange(selectedElements) {\n  const configValue = {\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    allowedTranscodableMimeTypes: [],\n    MediaUpload,\n  };\n\n  const combineElements = jest.fn();\n  const storyValue = {\n    state: {\n      currentPage: {\n        backgroundColor: {},\n      },\n    },\n    actions: {\n      clearBackgroundElement: jest.fn(),\n      combineElements,\n      updateCurrentPageProperties: jest.fn(),\n    },\n  };\n\n  const wrapper = ({ children }) => (\n    <ConfigContext.Provider value={configValue}>\n      <StoryContext.Provider value={storyValue}>\n        {children}\n      </StoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n\n  return {\n    ...renderPanel(PageBackgroundPanel, selectedElements, wrapper),\n    combineElements,\n  };\n}\n\ndescribe('Panels/PageBackground', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:pageBackground',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should simulate a click on the replace button', () => {\n    mockUseFFmpeg.mockReturnValue({ isTranscodingEnabled: false });\n    const backgroundImage = {\n      x: 0,\n      y: 0,\n      width: 1,\n      height: 1,\n      id: '123',\n      isBackground: true,\n      type: 'image',\n      rotationAngle: 0,\n      resource: {\n        id: 'resource/123',\n        src: 'media.jpg',\n        alt: 'Media',\n      },\n    };\n    const { combineElements } = arrange([backgroundImage]);\n    const replaceButton = screen.getByRole('button', { name: 'Replace' });\n    fireEvent.click(replaceButton);\n    expect(combineElements).toHaveBeenCalledOnce();\n    expect(combineElements).toHaveBeenCalledWith({\n      firstElement: expect.any(Object),\n      secondId: '123',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackgroundAudio/backgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app';\nimport { Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport BackgroundAudioPanelContent from '../../shared/media/backgroundAudioPanelContent';\nimport useHighlights from '../../../../app/highlights/useHighlights';\nimport { states } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst HighlightRow = styled(Row).attrs({\n  spaceBetween: false,\n})`\n  position: relative;\n  &::after {\n    content: '';\n    position: absolute;\n    top: -10px;\n    bottom: -10px;\n    left: -20px;\n    right: -10px;\n    ${({ isHighlighted }) => isHighlighted && styles.FLASH}\n    pointer-events: none;\n  }\n`;\n\nfunction PageBackgroundAudioPanel() {\n  const { backgroundAudio, currentPageId, updateCurrentPageProperties } =\n    useStory((state) => ({\n      updateCurrentPageProperties: state.actions.updateCurrentPageProperties,\n      backgroundAudio: state.state.currentPage?.backgroundAudio,\n      currentPageId: state.state.currentPage?.id,\n    }));\n\n  const { highlightBackgroundAudio, resetHighlight } = useHighlights(\n    (state) => ({\n      highlightBackgroundAudio: state[states.PageBackgroundAudio],\n      resetHighlight: state.onFocusOut,\n    })\n  );\n\n  const updateBackgroundAudio = useCallback(\n    (updatedBackgroundAudio) => {\n      updateCurrentPageProperties({\n        properties: {\n          backgroundAudio: updatedBackgroundAudio,\n        },\n      });\n    },\n    [updateCurrentPageProperties]\n  );\n\n  return (\n    <SimplePanel\n      name=\"pageBackgroundAudio\"\n      title={__('Page Background Audio', 'web-stories')}\n      collapsedByDefault={false}\n      isPersistable={!highlightBackgroundAudio}\n    >\n      <HighlightRow\n        isHighlighted={highlightBackgroundAudio?.showEffect}\n        onAnimationEnd={() => resetHighlight()}\n      >\n        <HelperText>\n          {__(\n            'Select an audio file that plays while this page is in view.',\n            'web-stories'\n          )}\n        </HelperText>\n      </HighlightRow>\n      <BackgroundAudioPanelContent\n        backgroundAudio={backgroundAudio}\n        updateBackgroundAudio={updateBackgroundAudio}\n        showCaptions\n        showLoopControl\n        audioId={`page-${currentPageId}-background-audio`}\n      />\n    </SimplePanel>\n  );\n}\n\nexport default PageBackgroundAudioPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackgroundAudio/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './backgroundAudio';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackgroundAudio/karma/pageBackgroundAudio.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen, waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Page background audio panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('Page background audio', () => {\n    beforeEach(async () => {\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await clickCanvas();\n    });\n\n    it('should able to upload background audio ', async () => {\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.pageBackgroundAudio.uploadButton\n      );\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(\n        storyContext.state.currentPage.backgroundAudio.resource.src\n      ).not.toBeNull();\n    });\n\n    it('should able to hotlink background audio', async () => {\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.pageBackgroundAudio.hotlinkButton\n      );\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use audio file',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type(\n        'http://localhost:9876/__static__/audio.mp3'\n      );\n\n      await fixture.events.click(insertBtn);\n      await waitFor(\n        async () => {\n          const storyContext = await fixture.renderHook(() => useStory());\n          // Check if the background audio source is set\n          if (!storyContext.state.currentPage.backgroundAudio?.resource?.src) {\n            throw new Error('resource not ready');\n          }\n          expect(\n            storyContext.state.currentPage.backgroundAudio.resource.src\n          ).toMatch('http://localhost:9876/__static__/audio.mp3');\n        },\n        {\n          timeout: 1500,\n        }\n      );\n    });\n\n    it('should not able to hotlink background audio with invalid', async () => {\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.pageBackgroundAudio.hotlinkButton\n      );\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use audio file',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type(\n        'http://localhost:9876/__static__/ranger9.jpg'\n      );\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        const dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        expect(dialog.textContent).toContain('Invalid link');\n      });\n    });\n  });\n\n  async function clickCanvas() {\n    const focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n    await fixture.events.click(focusContainer);\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/pageBackgroundAudio/test/backgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport ConfigContext from '../../../../../app/config/context';\nimport StoryContext from '../../../../../app/story/context';\nimport BackgroundAudioPanel from '../backgroundAudio';\n\nfunction MediaUpload({ render }) {\n  const open = jest.fn();\n  return render(open);\n}\n\nfunction arrange({ backgroundAudio, hasUploadMediaAction = true } = {}) {\n  const updateStory = jest.fn();\n\n  const configValue = {\n    capabilities: {\n      hasUploadMediaAction,\n    },\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    MediaUpload,\n  };\n\n  const storyContextValue = {\n    state: {\n      currentPage: {\n        backgroundAudio,\n      },\n    },\n    actions: { updateStory },\n  };\n\n  return renderWithTheme(\n    <ConfigContext.Provider value={configValue}>\n      <StoryContext.Provider value={storyContextValue}>\n        <BackgroundAudioPanel />\n      </StoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n}\n\ndescribe('BackgroundAudioPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:backgroundAudio',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render nothing if lacking upload capabilities', () => {\n    arrange({ hasUploadMediaAction: false });\n    expect(\n      screen.queryByRole('button', {\n        name: 'Upload an audio file',\n      })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render button to upload audio', () => {\n    arrange();\n    expect(\n      screen.getByRole('button', {\n        name: 'Upload an audio file',\n      })\n    ).toBeInTheDocument();\n  });\n\n  it('should render button to play and delete audio', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        loop: true,\n      },\n    });\n    expect(\n      screen.getByRole('button', {\n        name: 'Remove file',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', {\n        name: 'Play',\n      })\n    ).toBeInTheDocument();\n  });\n\n  it('should render loop button', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n          length: 60,\n          lengthFormatted: '1:00',\n        },\n        loop: true,\n      },\n    });\n    expect(\n      screen.getByRole('button', {\n        name: 'Remove file',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', {\n        name: 'Play',\n      })\n    ).toBeInTheDocument();\n\n    expect(screen.getByText('Loop')).toBeInTheDocument();\n  });\n\n  it('should render existing captions', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        tracks: [\n          {\n            track: 'https://example.com/track.vtt',\n            trackId: 123,\n            id: 'rersd-fdfd-fdfd-fdfd',\n            srcLang: '',\n            label: '',\n            kind: 'captions',\n          },\n        ],\n        loop: true,\n      },\n    });\n    expect(screen.getByText('track.vtt')).toBeInTheDocument();\n  });\n\n  it('should render upload button for captions', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        tracks: [],\n        loop: true,\n      },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Upload audio captions' })\n    ).toBeInTheDocument();\n  });\n\n  it('should not render upload button for captions without hasUploadMediaAction', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        tracks: [],\n        loop: true,\n      },\n      hasUploadMediaAction: false,\n    });\n    expect(\n      screen.queryByRole('button', { name: 'Upload audio captions' })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render existing captions without hasUploadMediaAction', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n        tracks: [\n          {\n            track: 'https://example.com/track.vtt',\n            trackId: 123,\n            id: 'rersd-fdfd-fdfd-fdfd',\n            srcLang: '',\n            label: '',\n            kind: 'captions',\n          },\n        ],\n        loop: true,\n      },\n      hasUploadMediaAction: false,\n    });\n\n    expect(screen.getByText('track.vtt')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/product/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './product';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/product/product.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { Input } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { MULTIPLE_DISPLAY_VALUE, MULTIPLE_VALUE } from '../../../../constants';\nimport ProductDropdown from '../../../library/panes/shopping/productDropdown';\nimport { getCommonValue } from '../../shared';\nimport { noop } from '../../../../utils/noop';\n\nfunction ProductPanel({ selectedElements, pushUpdate }) {\n  const product = getCommonValue(selectedElements, 'product', []);\n  const isMultiple = product === MULTIPLE_VALUE;\n\n  const setProduct = useCallback(\n    (newProduct) => pushUpdate({ product: newProduct }),\n    [pushUpdate]\n  );\n\n  // TODO: Provide opportunity to manually override information here.\n  return (\n    <SimplePanel\n      name=\"product\"\n      title={__('Product', 'web-stories')}\n      collapsedByDefault={false}\n    >\n      <Row>\n        {isMultiple && (\n          <Input\n            onChange={noop}\n            disabled\n            value={MULTIPLE_DISPLAY_VALUE}\n            aria-label={__('Product', 'web-stories')}\n          />\n        )}\n        {!isMultiple && (\n          <ProductDropdown\n            product={selectedElements[0].product}\n            setProduct={setProduct}\n          />\n        )}\n      </Row>\n    </SimplePanel>\n  );\n}\n\nProductPanel.propTypes = {\n  selectedElements: PropTypes.array,\n  pushUpdate: PropTypes.func,\n};\n\nexport default ProductPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/shapeStyle/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './shapeStyle';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/shapeStyle/shapeStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Row, Color } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { getCommonValue } from '../../shared';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\n\nfunction ShapeStylePanel({ selectedElements, pushUpdate }) {\n  const backgroundColor = getCommonValue(selectedElements, 'backgroundColor');\n\n  const onChange = useCallback(\n    (value) => {\n      pushUpdate({ backgroundColor: value }, true);\n    },\n    [pushUpdate]\n  );\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.Style],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"shapeStyle\"\n      title={__('Color', 'web-stories')}\n      isPersistable={!highlight}\n      aria-labelledby={null}\n      aria-label={__('Shape style', 'web-stories')}\n    >\n      <Row>\n        <Color\n          ref={(node) => {\n            if (node && highlight?.focus && highlight?.showEffect) {\n              node.addEventListener('keydown', cancelHighlight, { once: true });\n              node.focus();\n            }\n          }}\n          allowsGradient\n          value={backgroundColor}\n          isMultiple={backgroundColor === ''}\n          onChange={onChange}\n          label={__('Background color', 'web-stories')}\n          allowsSavedColors\n        />\n      </Row>\n    </SimplePanel>\n  );\n}\n\nShapeStylePanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default ShapeStylePanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n  DANGER_ZONE_HEIGHT,\n} from '@googleforcreators/units';\n\nexport const MIN_MAX = {\n  // TODO: with %360 logic this is not used, but can be utilized via keyboard arrows\n  ROTATION: {\n    MIN: -360,\n    MAX: 360,\n  },\n  WIDTH: {\n    MIN: 1,\n    MAX: 1000,\n  },\n  HEIGHT: {\n    MIN: 1,\n    MAX: 1000,\n  },\n  X: {\n    MIN: 1,\n    MAX: PAGE_WIDTH - 1,\n  },\n  Y: {\n    MIN: 1 - Math.floor(DANGER_ZONE_HEIGHT),\n    MAX: PAGE_HEIGHT + Math.floor(DANGER_ZONE_HEIGHT) - 1,\n  },\n};\n\nexport const DEFAULT_FLIP = { horizontal: false, vertical: false };\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './sizePosition';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/karma/borderRadius.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Border Radius', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const getSelection = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  };\n\n  describe('CUJ: Creator can Manipulate Shape: Border Radius', () => {\n    it('should allow the user to add border radius for text element', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n      });\n      // Choose Fill as background for visibility.\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.fill\n      );\n\n      const panel = fixture.editor.sidebar.designPanel.sizePosition;\n      await fixture.events.click(panel.radius(), { clickCount: 3 });\n      await fixture.events.keyboard.type('30');\n      await fixture.events.keyboard.press('tab');\n\n      const [element] = await getSelection();\n      // Since the default state is locked, verify that all the values were set to 30.\n      expect(element.borderRadius).toEqual(\n        jasmine.objectContaining({\n          topLeft: 30,\n          topRight: 30,\n          bottomLeft: 30,\n          bottomRight: 30,\n        })\n      );\n\n      // Take off lock.\n      await fixture.events.click(panel.lockBorderRadius);\n\n      await fixture.events.click(panel.radius('Top left'), { clickCount: 3 });\n      await fixture.events.keyboard.type('10');\n      await fixture.events.keyboard.press('tab');\n\n      // Verify the value change only for the top-left corner.\n      const [updatedElement] = await getSelection();\n      expect(updatedElement.borderRadius.topLeft).toBe(10);\n      expect(updatedElement.borderRadius.topRight).toBe(30);\n\n      await fixture.snapshot('Text element with border radius');\n    });\n\n    it('should allow user to add border radius for media', async () => {\n      const mediaItem = fixture.editor.library.media.item(0);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      const panel = fixture.editor.sidebar.designPanel.sizePosition;\n\n      // Take off lock.\n      await fixture.events.click(panel.lockBorderRadius);\n      // Focus the input first so that tooltip is not in the way of click.\n      await fixture.events.focus(panel.radius('Bottom left'));\n      await fixture.events.click(panel.radius('Bottom left'), {\n        clickCount: 3,\n      });\n      await fixture.events.keyboard.type('50');\n      await fixture.events.keyboard.press('tab');\n\n      const [element] = await getSelection();\n      const {\n        borderRadius: { topLeft, topRight, bottomLeft, bottomRight },\n      } = element;\n\n      expect(topLeft).toBe(0);\n      expect(topRight).toBe(0);\n      expect(bottomLeft).toBe(50);\n      expect(bottomRight).toBe(0);\n      expect(element.borderRadius).toEqual(\n        jasmine.objectContaining({\n          topLeft: 0,\n          topRight: 0,\n          bottomLeft: 50,\n          bottomRight: 0,\n        })\n      );\n\n      await fixture.snapshot('Media element with bottom left corner radius');\n    });\n  });\n\n  it('should allow user to add border radius for shape if rectangular', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(\n      fixture.editor.library.shapes.shape('Rectangle')\n    );\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    const panel = fixture.editor.sidebar.designPanel.sizePosition;\n    await fixture.events.click(panel.radius(), {\n      clickCount: 3,\n    });\n    await fixture.events.keyboard.type('50');\n    await fixture.events.keyboard.press('tab');\n\n    const [element] = await getSelection();\n    const {\n      borderRadius: { topLeft },\n    } = element;\n    expect(topLeft).toBe(50);\n    await fixture.snapshot('Shape element with locked border radius');\n  });\n\n  it('should not allow border radius for non-rectangular shape', async () => {\n    await fixture.events.click(fixture.editor.library.shapesTab);\n    await fixture.events.click(fixture.editor.library.shapes.shape('Circle'));\n    // Verify that the radius input is not found.\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    expect(() =>\n      fixture.editor.sidebar.designPanel.sizePosition.radius()\n    ).toThrow();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/karma/sizePosition.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\n\ndescribe('Selection Panel', () => {\n  let fixture;\n  let panel;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const selectTarget = async (target) => {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.keyboard.down('Shift');\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n    await fixture.events.keyboard.up('Shift');\n  };\n\n  const getSelection = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements;\n  };\n\n  describe('CUJ: Creator can Transform an Element: Set height and width', () => {\n    it('should have correct default aspect ratio lock values', async () => {\n      const mediaItem = fixture.editor.library.media.item(0);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20);\n      const [image] = await getSelection();\n      expect(image.lockAspectRatio).toBeFalse();\n\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n      const [triangle] = await getSelection();\n      expect(triangle.lockAspectRatio).toBeTrue();\n\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Rectangle')\n      );\n      const [rectangle] = await getSelection();\n      expect(rectangle.lockAspectRatio).toBeFalse();\n\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      const [text] = await getSelection();\n      expect(text.lockAspectRatio).not.toBeFalse();\n    });\n\n    it('should allow the user to change the height & width of a text element', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => fixture.editor.canvas.framesLayer.frames[1].node);\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.sizePosition;\n\n      // Store original width and height\n      const ratio = panel.width.value / panel.height.value;\n\n      await fixture.events.click(panel.width);\n      await fixture.events.keyboard.type('300');\n      await fixture.events.keyboard.press('tab');\n\n      const [element] = await getSelection();\n      expect(element.width).toBe(300);\n      const newHeight = element.height;\n      expect(Math.round(newHeight)).toBe(Math.round(300 / ratio));\n\n      // Take off lock ratio by clicking on the visible part of the lock aspect ratio checkbox.\n      await fixture.events.click(panel.lockAspectRatio);\n      expect(panel.height.placeholder).toBe('Auto');\n      expect(panel.height.disabled).toBeTrue();\n\n      await fixture.snapshot('Unlocked element with height disabled');\n\n      await fixture.events.click(panel.width);\n      await fixture.events.keyboard.type('100');\n      await fixture.events.keyboard.press('tab');\n\n      const [updatedElement] = await getSelection();\n      expect(updatedElement.height).toBe(newHeight);\n    });\n\n    it('should disable setting height independently of multi-selection containing text', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => fixture.editor.canvas.framesLayer.frames[1].node);\n\n      // Switch to shapes tab and click the triangle\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.events.click(fixture.editor.library.shapesTab);\n      await fixture.events.click(\n        fixture.editor.library.shapes.shape('Triangle')\n      );\n      // Select the text, too.\n      await selectTarget(fixture.editor.canvas.framesLayer.frames[1].node);\n\n      const elements = await getSelection();\n      const oHeight1 = elements[0].height;\n      const oHeight2 = elements[1].height;\n\n      // Take off lock ratio by clicking on the visible part of the lock aspect ratio checkbox.\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.sizePosition;\n      await fixture.events.click(panel.lockAspectRatio);\n      expect(panel.height.placeholder).toBe('Auto');\n\n      await fixture.snapshot('Unlocked multi-selection with height disabled');\n\n      expect(panel.height.value).toBe('');\n      expect(panel.height.placeholder).toBe('Auto');\n      expect(panel.height.disabled).toBeTrue();\n      await fixture.events.click(panel.width);\n      await fixture.events.keyboard.type('300');\n      await fixture.events.keyboard.press('tab');\n\n      const updatedElements = await getSelection();\n      // The height of the text was reduced automatically due to the number of rows decreasing.\n      expect(updatedElements[0].height).toBeLessThanOrEqual(oHeight1);\n      expect(updatedElements[1].height).toBe(oHeight2);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/opacity.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, _x } from '@googleforcreators/i18n';\nimport { Icons, NumericInput } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport getCommonValue from '../../shared/getCommonValue';\nimport { inputContainerStyleOverride } from '../../shared/styles';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\n\nexport const MIN_MAX = {\n  OPACITY: {\n    MIN: 0,\n    MAX: 100,\n  },\n};\n\nfunction defaultOpacity({ opacity }) {\n  return typeof opacity !== 'undefined' ? opacity : MIN_MAX.OPACITY.MAX;\n}\n\nfunction OpacityControls({ selectedElements, pushUpdate }) {\n  const opacity = getCommonValue(selectedElements, defaultOpacity);\n\n  const handleChange = useCallback(\n    (evt, value) => pushUpdate({ opacity: value ?? 100 }, true),\n    [pushUpdate]\n  );\n\n  return (\n    <NumericInput\n      suffix={<Icons.ColorDrop />}\n      unit={_x('%', 'Percentage', 'web-stories')}\n      value={opacity}\n      onChange={handleChange}\n      min={MIN_MAX.OPACITY.MIN}\n      max={MIN_MAX.OPACITY.MAX}\n      aria-label={__('Opacity in percent', 'web-stories')}\n      placeholder={opacity === MULTIPLE_VALUE ? MULTIPLE_DISPLAY_VALUE : ''}\n      isIndeterminate={opacity === MULTIPLE_VALUE}\n      containerStyleOverride={inputContainerStyleOverride}\n    />\n  );\n}\n\nOpacityControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default OpacityControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/radius.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { LockToggle, Icons } from '@googleforcreators/design-system';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport { StackableGroup, StackableInput } from '../../../form/stackable';\nimport useCommonObjectValue from '../../shared/useCommonObjectValue';\nimport { focusStyle } from '../../shared/styles';\nimport Tooltip from '../../../tooltip';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\n\nexport const DEFAULT_BORDER_RADIUS = {\n  topLeft: 0,\n  topRight: 0,\n  bottomRight: 0,\n  bottomLeft: 0,\n  locked: true,\n};\n\nconst FlexContainer = styled.div`\n  display: flex;\n`;\n\nconst LockContainer = styled.div`\n  position: relative;\n  display: flex;\n  align-items: center;\n  width: 32px;\n  margin-left: 8px;\n`;\n\nconst StyledLockToggle = styled(LockToggle)`\n  ${focusStyle};\n`;\n\nconst TopLeft = styled(Icons.Corner)`\n  transform: rotate(90deg);\n`;\n\nconst TopRight = styled(Icons.Corner)`\n  transform: rotate(180deg);\n`;\n\nconst BottomRight = styled(Icons.Corner)`\n  transform: rotate(270deg);\n`;\n\nfunction RadiusControls({\n  selectedElements,\n  pushUpdateForObject,\n  stackableGroupStyleOverride,\n}) {\n  const borderRadius = useCommonObjectValue(\n    selectedElements,\n    'borderRadius',\n    DEFAULT_BORDER_RADIUS\n  );\n\n  const allSupportBorder = selectedElements.every((el) =>\n    canSupportMultiBorder(el)\n  );\n\n  const lockRadius = borderRadius.locked === true;\n\n  const handleChange = useCallback(\n    (name, value) => {\n      const newRadius = !lockRadius\n        ? {\n            [name]: value,\n          }\n        : {\n            topLeft: value,\n            topRight: value,\n            bottomRight: value,\n            bottomLeft: value,\n          };\n      pushUpdateForObject(\n        'borderRadius',\n        newRadius,\n        DEFAULT_BORDER_RADIUS,\n        true\n      );\n    },\n    [pushUpdateForObject, lockRadius]\n  );\n\n  const handleLockChange = useCallback(\n    (locked) => {\n      const newRadius = locked\n        ? {\n            locked,\n            topLeft: borderRadius.topLeft,\n            topRight: borderRadius.topLeft,\n            bottomRight: borderRadius.topLeft,\n            bottomLeft: borderRadius.topLeft,\n          }\n        : {\n            locked,\n          };\n      pushUpdateForObject(\n        'borderRadius',\n        newRadius,\n        DEFAULT_BORDER_RADIUS,\n        true\n      );\n    },\n    [pushUpdateForObject, borderRadius]\n  );\n\n  if (!allSupportBorder) {\n    return null;\n  }\n\n  const firstInputLabel = lockRadius\n    ? __('Corner Radius', 'web-stories')\n    : __('Top left corner radius', 'web-stories');\n\n  return (\n    <FlexContainer>\n      <StackableGroup\n        stackableGroupStyleOverride={stackableGroupStyleOverride}\n        locked={lockRadius}\n      >\n        <StackableInput\n          suffix={<TopLeft />}\n          value={\n            borderRadius.topLeft === MULTIPLE_VALUE ? '' : borderRadius.topLeft\n          }\n          aria-label={firstInputLabel}\n          onChange={(_, value) => handleChange('topLeft', value)}\n          placeholder={\n            borderRadius.topLeft === MULTIPLE_VALUE\n              ? MULTIPLE_DISPLAY_VALUE\n              : ''\n          }\n          isIndeterminate={borderRadius.topLeft === MULTIPLE_VALUE}\n        />\n\n        {!lockRadius && (\n          <>\n            <StackableInput\n              suffix={<TopRight />}\n              value={\n                borderRadius.topRight === MULTIPLE_VALUE\n                  ? ''\n                  : borderRadius.topRight\n              }\n              aria-label={__('Top right corner radius', 'web-stories')}\n              onChange={(_, value) => handleChange('topRight', value)}\n              placeholder={\n                borderRadius.topRight === MULTIPLE_VALUE\n                  ? MULTIPLE_DISPLAY_VALUE\n                  : ''\n              }\n              isIndeterminate={borderRadius.topRight === MULTIPLE_VALUE}\n            />\n            <StackableInput\n              value={\n                borderRadius.bottomLeft === MULTIPLE_VALUE\n                  ? ''\n                  : borderRadius.bottomLeft\n              }\n              aria-label={__('Bottom left corner radius', 'web-stories')}\n              onChange={(_, value) => handleChange('bottomLeft', value)}\n              placeholder={\n                borderRadius.bottomLeft === MULTIPLE_VALUE\n                  ? MULTIPLE_DISPLAY_VALUE\n                  : ''\n              }\n              suffix={<Icons.Corner />}\n              isIndeterminate={borderRadius.bottomLeft === MULTIPLE_VALUE}\n            />\n            <StackableInput\n              value={\n                borderRadius.bottomRight === MULTIPLE_VALUE\n                  ? ''\n                  : borderRadius.bottomRight\n              }\n              aria-label={__('Bottom right corner radius', 'web-stories')}\n              onChange={(_, value) => handleChange('bottomRight', value)}\n              placeholder={\n                borderRadius.bottomRight === MULTIPLE_VALUE\n                  ? MULTIPLE_DISPLAY_VALUE\n                  : ''\n              }\n              suffix={<BottomRight />}\n              isIndeterminate={borderRadius.bottomRight === MULTIPLE_VALUE}\n            />\n          </>\n        )}\n      </StackableGroup>\n\n      <LockContainer>\n        <Tooltip\n          title={__('Toggle consistent corner radius', 'web-stories')}\n          // Key is needed to remount the component when `borderRadius.locked` changes. Otherwise when toggle is open,\n          // tooltip may cover content.\n          key={borderRadius.locked.toString()}\n        >\n          <StyledLockToggle\n            isLocked={borderRadius.locked}\n            onClick={() => handleLockChange(!borderRadius.locked)}\n            aria-label={__('Toggle consistent corner radius', 'web-stories')}\n          />\n        </Tooltip>\n      </LockContainer>\n    </FlexContainer>\n  );\n}\n\nRadiusControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdateForObject: PropTypes.func.isRequired,\n  stackableGroupStyleOverride: PropTypes.array,\n};\n\nexport default RadiusControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/sizePosition.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { useCallback, useMemo, useRef } from '@googleforcreators/react';\nimport { __, _x } from '@googleforcreators/i18n';\nimport stickers from '@googleforcreators/stickers';\nimport {\n  calcRotatedObjectPositionAndSize,\n  dataPixels,\n} from '@googleforcreators/units';\nimport {\n  Button,\n  LockToggle,\n  NumericInput,\n  Icons,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { SimplePanel } from '../../panel';\nimport FlipControls from '../../shared/flipControls';\nimport { focusStyle, inputContainerStyleOverride } from '../../shared/styles';\nimport { getCommonValue, useCommonObjectValue } from '../../shared';\nimport useStory from '../../../../app/story/useStory';\nimport {\n  MULTIPLE_VALUE,\n  MULTIPLE_DISPLAY_VALUE,\n  TRACKING_EVENTS,\n} from '../../../../constants';\nimport usePerformanceTracking from '../../../../utils/usePerformanceTracking';\nimport Tooltip from '../../../tooltip';\nimport usePresubmitHandlers from './usePresubmitHandlers';\nimport { getMultiSelectionMinMaxXY, isNum } from './utils';\nimport { MIN_MAX, DEFAULT_FLIP } from './constants';\nimport OpacityControls from './opacity';\nimport RadiusControls from './radius';\n\nconst StyledLockToggle = styled(LockToggle)`\n  ${focusStyle};\n`;\n\nconst stackableGroupStyleOverride = css`\n  max-width: none;\n`;\n\nfunction getStickerAspectRatio(element) {\n  return stickers?.[element?.sticker?.type].aspectRatio || 1;\n}\n\nconst gridWithoutFlip = css`\n  grid-template-areas:\n    ${({ isSingleMedia }) => (isSingleMedia ? `'b b b b b . .'` : null)}\n    'x . . . y . .'\n    'w . d . h . l'\n    'r . . . o . .'\n    'c c c c c c c';\n`;\n\nconst unlockedRadiusLines = `\n  'o . . . . . .'\n  'c c c c c c c'\n`;\nconst gridWithFlip = css`\n  grid-template-areas:\n    ${({ isSingleMedia }) => (isSingleMedia ? `'b b b b b . .'` : null)}\n    'x . . . y . .'\n    'w . d . h . l'\n    'r . . . f . .'\n    ${({ unlockedRadius }) =>\n      !unlockedRadius ? `'o . . . c c c'` : unlockedRadiusLines};\n`;\n\nconst Grid = styled.div`\n  display: grid;\n  ${({ canFlip }) => (canFlip ? gridWithFlip : gridWithoutFlip)}\n  grid-template-columns: 1fr 4px 8px 4px 1fr 8px 32px;\n  grid-template-rows: repeat(4, 36px);\n  row-gap: 16px;\n  align-items: center;\n  justify-items: start;\n  margin-bottom: 16px;\n`;\n\nconst Area = styled.div`\n  grid-area: ${({ area }) => area};\n  width: 100%;\n`;\n\nconst Dash = styled.div`\n  height: 1px;\n  width: 100%;\n  background: ${({ theme }) => theme.colors.divider.primary};\n`;\n\nconst StyledButton = styled(Button)`\n  padding: 10px 16px;\n  width: 100%;\n\n  ${focusStyle};\n`;\n\nfunction SizePositionPanel(props) {\n  const {\n    selectedElements,\n    submittedSelectedElements,\n    pushUpdate,\n    pushUpdateForObject,\n  } = props;\n\n  const x = getCommonValue(selectedElements, 'x');\n  const y = getCommonValue(selectedElements, 'y');\n  const width = getCommonValue(selectedElements, 'width');\n  const height = getCommonValue(selectedElements, 'height');\n  const rotationAngle = getCommonValue(selectedElements, 'rotationAngle');\n  const flip = useCommonObjectValue(selectedElements, 'flip', DEFAULT_FLIP);\n  const borderRadius = useCommonObjectValue(selectedElements, 'borderRadius', {\n    locked: true,\n  });\n\n  const origRatio = useMemo(() => {\n    const origWidth = getCommonValue(submittedSelectedElements, 'width');\n    const origHeight = getCommonValue(submittedSelectedElements, 'height');\n    return origWidth / origHeight;\n  }, [submittedSelectedElements]);\n  const rawLockAspectRatio = getCommonValue(\n    selectedElements,\n    'lockAspectRatio'\n  );\n\n  const bgButtonRef = useRef(null);\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: bgButtonRef.current,\n    eventData: TRACKING_EVENTS.SET_BACKGROUND_MEDIA,\n  });\n\n  // When multiple element selected with aspect lock ratio value combined, it treated as true, reversed behavior with padding lock ratio.\n  const lockAspectRatio =\n    rawLockAspectRatio === MULTIPLE_VALUE ? true : rawLockAspectRatio;\n\n  const { currentPage, combineElements } = useStory((state) => ({\n    currentPage: state.state.currentPage,\n    combineElements: state.actions.combineElements,\n  }));\n  const currentBackgroundId = currentPage?.elements[0].id;\n\n  const isSingleElement = selectedElements.length === 1;\n  const { isMedia } = getDefinitionForType(selectedElements[0].type);\n\n  const canFlip = selectedElements.every(\n    ({ type }) => getDefinitionForType(type).canFlip\n  );\n\n  const isAspectAlwaysLocked = selectedElements.some(\n    ({ type }) => getDefinitionForType(type).isAspectAlwaysLocked\n  );\n\n  const hasText = selectedElements.some(({ type }) => 'text' === type);\n\n  const actualDimensions = useMemo(() => {\n    if (isSingleElement) {\n      return calcRotatedObjectPositionAndSize(\n        rotationAngle,\n        x,\n        y,\n        width,\n        height\n      );\n    }\n    return {};\n  }, [rotationAngle, x, y, width, height, isSingleElement]);\n\n  const xOffset = x - actualDimensions.x;\n  const yOffset = y - actualDimensions.y;\n  const minMaxXY = isSingleElement\n    ? {\n        minX: MIN_MAX.X.MIN + xOffset - actualDimensions.width,\n        minY: MIN_MAX.Y.MIN + yOffset - actualDimensions.height,\n        maxX: MIN_MAX.X.MAX + xOffset,\n        maxY: MIN_MAX.Y.MAX + yOffset,\n      }\n    : getMultiSelectionMinMaxXY(selectedElements);\n\n  const getUpdateObject = (nWidth, nHeight) =>\n    rawLockAspectRatio === MULTIPLE_VALUE\n      ? {\n          lockAspectRatio,\n          height: nHeight,\n          width: nWidth,\n        }\n      : {\n          height: nHeight,\n          width: nWidth,\n        };\n\n  usePresubmitHandlers(lockAspectRatio, height, width);\n\n  const handleSetBackground = useCallback(() => {\n    combineElements({\n      firstElement: selectedElements[0],\n      secondId: currentBackgroundId,\n    });\n  }, [selectedElements, combineElements, currentBackgroundId]);\n\n  const disableHeight = !lockAspectRatio && hasText;\n  const enabledHeightPlaceholder =\n    MULTIPLE_VALUE === height ? MULTIPLE_DISPLAY_VALUE : null;\n  const heightPlaceholder = disableHeight\n    ? __('Auto', 'web-stories')\n    : enabledHeightPlaceholder;\n\n  const getMixedValueProps = useCallback((value) => {\n    return {\n      isIndeterminate: MULTIPLE_VALUE === value,\n      placeholder: MULTIPLE_VALUE === value ? MULTIPLE_DISPLAY_VALUE : null,\n    };\n  }, []);\n  return (\n    <SimplePanel name=\"size\" title={__('Selection', 'web-stories')}>\n      <Grid\n        isSingleMedia={isMedia && isSingleElement}\n        canFlip={canFlip}\n        unlockedRadius={!borderRadius.locked}\n      >\n        {isMedia && isSingleElement && (\n          <Area area=\"b\">\n            <StyledButton\n              ref={bgButtonRef}\n              onClick={handleSetBackground}\n              type={ButtonType.Secondary}\n              size={ButtonSize.Small}\n              variant={ButtonVariant.Rectangle}\n            >\n              {__('Set as background', 'web-stories')}\n            </StyledButton>\n          </Area>\n        )}\n        <Area area=\"x\">\n          <NumericInput\n            suffix={_x('X', 'Position on X axis', 'web-stories')}\n            value={x}\n            min={minMaxXY.minX}\n            max={minMaxXY.maxX}\n            onChange={(evt, value) => pushUpdate({ x: value }, true)}\n            aria-label={__('X position', 'web-stories')}\n            canBeNegative\n            {...getMixedValueProps(x)}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </Area>\n        <Area area=\"y\">\n          <NumericInput\n            suffix={_x('Y', 'Position on Y axis', 'web-stories')}\n            value={y}\n            min={minMaxXY.minY}\n            max={minMaxXY.maxY}\n            onChange={(evt, value) => pushUpdate({ y: value }, true)}\n            aria-label={__('Y position', 'web-stories')}\n            canBeNegative\n            {...getMixedValueProps(y)}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </Area>\n        {/** Width/height & lock ratio */}\n        <Area area=\"w\">\n          <NumericInput\n            suffix={_x('W', 'The Width dimension', 'web-stories')}\n            value={width}\n            min={MIN_MAX.WIDTH.MIN}\n            max={MIN_MAX.WIDTH.MAX}\n            onChange={(evt, value) => {\n              const newWidth = value;\n              let newHeight = height;\n              if (lockAspectRatio) {\n                if (newWidth === '') {\n                  newHeight = '';\n                } else if (isNum(newWidth / origRatio)) {\n                  newHeight = dataPixels(newWidth / origRatio);\n                }\n              }\n              pushUpdate((element) => {\n                // For stickers, we maintain aspect ratio of the sticker\n                // regardless of input and selected elements.\n                if (element?.type === 'sticker') {\n                  const aspectRatio = getStickerAspectRatio(element);\n                  return getUpdateObject(\n                    newWidth,\n                    Math.floor(newWidth / aspectRatio)\n                  );\n                }\n                return getUpdateObject(newWidth, newHeight);\n              }, true);\n            }}\n            aria-label={__('Width', 'web-stories')}\n            {...getMixedValueProps(width)}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </Area>\n        <Area area=\"d\">\n          <Dash />\n        </Area>\n        <Area area=\"h\">\n          <NumericInput\n            allowEmpty={disableHeight}\n            suffix={_x('H', 'The Height dimension', 'web-stories')}\n            value={disableHeight ? '' : height}\n            disabled={disableHeight}\n            min={MIN_MAX.HEIGHT.MIN}\n            max={MIN_MAX.HEIGHT.MAX}\n            onChange={(evt, value) => {\n              const newHeight = value;\n              let newWidth = width;\n              if (lockAspectRatio) {\n                if (newHeight === '') {\n                  newWidth = '';\n                } else if (isNum(newHeight * origRatio)) {\n                  newWidth = dataPixels(newHeight * origRatio);\n                }\n              }\n              pushUpdate((element) => {\n                // For stickers, we maintain aspect ratio of the sticker\n                // regardless of input and selected elements.\n                if (element?.type === 'sticker') {\n                  const aspectRatio = getStickerAspectRatio(element);\n                  return getUpdateObject(\n                    Math.floor(newHeight * aspectRatio),\n                    newHeight\n                  );\n                }\n                return getUpdateObject(newWidth, newHeight);\n              }, true);\n            }}\n            aria-label={__('Height', 'web-stories')}\n            isIndeterminate={MULTIPLE_VALUE === height}\n            placeholder={heightPlaceholder}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </Area>\n        <Area area=\"l\">\n          <Tooltip title={__('Lock aspect ratio', 'web-stories')}>\n            <StyledLockToggle\n              aria-label={__('Lock aspect ratio', 'web-stories')}\n              isLocked={lockAspectRatio || isAspectAlwaysLocked}\n              disabled={isAspectAlwaysLocked}\n              onClick={() =>\n                !isAspectAlwaysLocked &&\n                pushUpdate({ lockAspectRatio: !lockAspectRatio }, true)\n              }\n            />\n          </Tooltip>\n        </Area>\n        <Area area=\"r\">\n          <NumericInput\n            suffix={<Icons.Angle />}\n            unit={_x('°', 'Degrees, 0 — 360.', 'web-stories')}\n            value={rotationAngle}\n            min={MIN_MAX.ROTATION.MIN}\n            max={MIN_MAX.ROTATION.MAX}\n            onChange={(evt, value) =>\n              pushUpdate({ rotationAngle: value }, true)\n            }\n            aria-label={__('Rotation', 'web-stories')}\n            canBeNegative\n            {...getMixedValueProps(rotationAngle)}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </Area>\n        {canFlip && (\n          <Area area=\"f\">\n            <FlipControls\n              onChange={(value) =>\n                pushUpdateForObject('flip', value, DEFAULT_FLIP, true)\n              }\n              value={flip}\n            />\n          </Area>\n        )}\n        <Area area=\"o\">\n          <OpacityControls {...props} />\n        </Area>\n        <Area area=\"c\">\n          <RadiusControls\n            stackableGroupStyleOverride={stackableGroupStyleOverride}\n            {...props}\n          />\n        </Area>\n      </Grid>\n    </SimplePanel>\n  );\n}\n\nSizePositionPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  submittedSelectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n  pushUpdateForObject: PropTypes.func.isRequired,\n};\n\nexport default SizePositionPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/test/sizePosition.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport { dataPixels } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { renderPanel } from '../../../shared/test/_utils';\nimport SizePosition from '../sizePosition';\nimport {\n  MULTIPLE_VALUE,\n  MULTIPLE_DISPLAY_VALUE,\n} from '../../../../../constants';\n\njest.mock('@googleforcreators/element-library');\njest.mock('@googleforcreators/elements');\n\ndescribe('panels/SizePosition', () => {\n  let defaultElement, defaultImage, defaultText, unlockAspectRatioElement;\n  let defaultFlip;\n  const aspectRatioLockButtonLabel = 'Lock aspect ratio';\n\n  beforeEach(() => {\n    defaultFlip = { horizontal: false, vertical: false };\n    defaultElement = {\n      id: '1',\n      isBackground: false,\n      x: 20,\n      y: 20,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      opacity: 100,\n    };\n    unlockAspectRatioElement = {\n      id: '1',\n      isBackground: false,\n      x: 20,\n      y: 20,\n      width: 100,\n      height: 80,\n      rotationAngle: 0,\n      lockAspectRatio: false,\n    };\n    defaultImage = {\n      ...defaultElement,\n      type: 'image',\n    };\n    defaultText = {\n      ...defaultElement,\n      type: 'text',\n    };\n    getDefinitionForType.mockImplementation((type) => {\n      return {\n        isMedia: 'image' === type,\n        canFlip: 'image' === type,\n      };\n    });\n  });\n\n  function renderSizePosition(...args) {\n    return renderPanel(SizePosition, ...args);\n  }\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:size',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render <SizePosition /> panel', () => {\n    renderSizePosition([defaultElement]);\n    const element = screen.getByRole('button', { name: 'Selection' });\n    expect(element).toBeInTheDocument();\n  });\n\n  describe('single selection', () => {\n    describe('opacity', () => {\n      it('should set opacity to 100 if not set', () => {\n        renderSizePosition([defaultElement]);\n        const input = screen.getByRole('textbox', {\n          name: 'Opacity in percent',\n        });\n        expect(input).toHaveValue('100%');\n      });\n\n      it('should set opacity to 0 if set to 0', () => {\n        renderSizePosition([{ ...defaultElement, opacity: 0 }]);\n        const input = screen.getByRole('textbox', {\n          name: 'Opacity in percent',\n        });\n        expect(input).toHaveValue('0%');\n      });\n\n      it('should set opacity to 49 if set to 49', () => {\n        renderSizePosition([{ ...defaultElement, opacity: 49 }]);\n        const input = screen.getByRole('textbox', {\n          name: 'Opacity in percent',\n        });\n        expect(input).toHaveValue('49%');\n      });\n\n      it('should update opacity value on change', () => {\n        const { pushUpdate } = renderSizePosition([\n          { ...defaultElement, opacity: 49 },\n        ]);\n        const input = screen.getByRole('textbox', {\n          name: 'Opacity in percent',\n        });\n        fireEvent.change(input, { target: { value: '23' } });\n        fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n        expect(pushUpdate).toHaveBeenCalledWith({ opacity: 23 }, true);\n      });\n\n      it('should display mixed in case of multi-selection with different values', () => {\n        renderSizePosition([\n          { ...defaultElement, opacity: 50 },\n          { id: 2, opacity: 80 },\n        ]);\n        const input = screen.getByRole('textbox', {\n          name: 'Opacity in percent',\n        });\n        expect(input.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n        expect(input).toHaveValue('');\n      });\n    });\n\n    it('should not render flip controls when not allowed', () => {\n      renderSizePosition([defaultText]);\n      const horiz = screen.queryByTitle('Flip horizontally');\n      const vert = screen.queryByTitle('Flip vertically');\n      expect(horiz).not.toBeInTheDocument();\n      expect(vert).not.toBeInTheDocument();\n    });\n\n    it('should render default flip controls', () => {\n      renderSizePosition([defaultImage]);\n      const horiz = screen.getByRole('button', { name: 'Flip horizontally' });\n      const vert = screen.getByRole('button', { name: 'Flip vertically' });\n      expect(horiz).not.toBeChecked();\n      expect(vert).not.toBeChecked();\n    });\n\n    it('should render specified flip controls', () => {\n      renderSizePosition([\n        {\n          ...defaultImage,\n          flip: { horizontal: true, vertical: true },\n        },\n      ]);\n      const horiz = screen.getByRole('button', { name: 'Flip horizontally' });\n      const vert = screen.getByRole('button', { name: 'Flip vertically' });\n      expect(horiz).toHaveAttribute('aria-pressed', 'true');\n      expect(vert).toHaveAttribute('aria-pressed', 'true');\n    });\n\n    it('should update flip horizontal controls', () => {\n      const { pushUpdateForObject } = renderSizePosition([defaultImage]);\n      const horiz = screen.getByRole('button', { name: 'Flip horizontally' });\n      fireEvent.click(horiz);\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'flip',\n        { horizontal: true, vertical: false },\n        defaultFlip,\n        true\n      );\n    });\n\n    it('should update flip vertical controls', () => {\n      const { pushUpdateForObject } = renderSizePosition([defaultImage]);\n      const vert = screen.getByRole('button', { name: 'Flip vertically' });\n      fireEvent.click(vert);\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'flip',\n        { horizontal: false, vertical: true },\n        defaultFlip,\n        true\n      );\n    });\n\n    it('should update width with lock ratio', () => {\n      const { pushUpdate } = renderSizePosition([defaultImage]);\n      const input = screen.getByRole('textbox', { name: 'Width' });\n      fireEvent.change(input, { target: { value: '150' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        width: 150,\n        height: 150 / (100 / 80),\n      });\n      expect(submitArg).toBeTrue();\n    });\n\n    it('should update height with lock ratio', () => {\n      const { pushUpdate } = renderSizePosition([defaultImage]);\n      const input = screen.getByRole('textbox', { name: 'Height' });\n      fireEvent.change(input, { target: { value: '160' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        height: 160,\n        width: 160 * (100 / 80),\n      });\n      expect(submitArg).toBeTrue();\n    });\n\n    it('should update width without lock ratio', () => {\n      const { pushUpdate } = renderSizePosition([unlockAspectRatioElement]);\n\n      const input = screen.getByRole('textbox', { name: 'Width' });\n      fireEvent.change(input, { target: { value: '150' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({ width: 150, height: 80 });\n      expect(submitArg).toBeTrue();\n    });\n\n    it('should disable height without lock ratio for text element', () => {\n      renderSizePosition([\n        {\n          ...unlockAspectRatioElement,\n          type: 'text',\n        },\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Height' });\n      expect(input).toBeDisabled();\n      expect(input).toHaveValue('');\n      expect(input.placeholder).toBe('Auto');\n    });\n\n    it('should disable height without lock ratio for multi-selection with text', () => {\n      renderSizePosition([\n        {\n          ...unlockAspectRatioElement,\n          type: 'text',\n        },\n        {\n          ...defaultImage,\n          lockAspectRatio: false,\n        },\n      ]);\n\n      const input = screen.getByRole('textbox', { name: 'Height' });\n      expect(input).toBeDisabled();\n      expect(input).toHaveValue('');\n      expect(input.placeholder).toBe('Auto');\n    });\n\n    it('should not update width if empty value is submitted', () => {\n      const { pushUpdate } = renderSizePosition([defaultImage]);\n      const inputWidth = screen.getByRole('textbox', { name: 'Width' });\n      fireEvent.change(inputWidth, { target: { value: '' } });\n      fireEvent.keyDown(inputWidth, { key: 'Enter', which: 13 });\n      expect(pushUpdate).not.toHaveBeenCalled();\n    });\n\n    it('should not update height if empty value is submitted', () => {\n      const { pushUpdate } = renderSizePosition([defaultImage]);\n      const inputHeight = screen.getByRole('textbox', { name: 'Height' });\n      fireEvent.change(inputHeight, { target: { value: '' } });\n      fireEvent.keyDown(inputHeight, { key: 'Enter', which: 13 });\n      expect(pushUpdate).not.toHaveBeenCalled();\n    });\n\n    it('should update lock ratio to false for element', () => {\n      const { pushUpdate } = renderSizePosition([defaultImage]);\n      fireEvent.click(\n        screen.getByRole('button', { name: aspectRatioLockButtonLabel })\n      );\n      expect(pushUpdate).toHaveBeenCalledWith({ lockAspectRatio: false }, true);\n    });\n\n    it('should update lock ratio to true for unlock aspect ratio element', () => {\n      const { pushUpdate } = renderSizePosition([unlockAspectRatioElement]);\n      fireEvent.click(\n        screen.getByRole('button', { name: aspectRatioLockButtonLabel })\n      );\n      expect(pushUpdate).toHaveBeenCalledWith({ lockAspectRatio: true }, true);\n    });\n  });\n\n  describe('multi selection', () => {\n    let image, imageWithSameSize, imageWithDifferentSize;\n    let unlockImage, unlockImageWithSameSize;\n\n    beforeEach(() => {\n      image = defaultImage;\n      unlockImage = {\n        ...defaultImage,\n        lockAspectRatio: false,\n      };\n      imageWithSameSize = { ...image, id: 'imageWithSameSize' };\n      unlockImageWithSameSize = {\n        ...imageWithSameSize,\n        lockAspectRatio: false,\n      };\n      imageWithDifferentSize = {\n        ...image,\n        id: 'imageWithDifferentSize',\n        width: 200,\n        height: 120,\n      };\n    });\n\n    it('should update flip controls', () => {\n      const { pushUpdateForObject } = renderSizePosition([\n        {\n          ...image,\n          flip: { horizontal: true, vertical: false },\n        },\n        {\n          ...image,\n          flip: { horizontal: false, vertical: true },\n        },\n      ]);\n      const horiz = screen.getByRole('button', { name: 'Flip horizontally' });\n      fireEvent.click(horiz);\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'flip',\n        { horizontal: true, vertical: MULTIPLE_VALUE },\n        defaultFlip,\n        true\n      );\n    });\n\n    it('should update width with lock ratio and same size', () => {\n      const { pushUpdate, submit } = renderSizePosition([\n        image,\n        imageWithSameSize,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Width' });\n      fireEvent.change(input, { target: { value: '150' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        width: 150,\n        height: dataPixels(150 / (100 / 80)),\n      });\n      expect(submitArg).toBeTrue();\n\n      const submits = submit({ width: 150, height: MULTIPLE_VALUE });\n      expect(submits[image.id]).toStrictEqual(\n        expect.objectContaining({\n          width: 150,\n          height: dataPixels(150 / (100 / 80)),\n        })\n      );\n      expect(submits[imageWithSameSize.id]).toStrictEqual(\n        expect.objectContaining({\n          width: 150,\n          height: dataPixels(150 / (100 / 80)),\n        })\n      );\n    });\n\n    it('should update width with lock ratio and different size', () => {\n      const { pushUpdate, submit } = renderSizePosition([\n        image,\n        imageWithDifferentSize,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Width' });\n      fireEvent.change(input, { target: { value: '150' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        width: 150,\n        height: MULTIPLE_VALUE,\n      });\n      expect(submitArg).toBeTrue();\n\n      const submits = submit({ width: 150, height: MULTIPLE_VALUE });\n      expect(submits[image.id]).toStrictEqual(\n        expect.objectContaining({\n          width: 150,\n          height: 150 / (100 / 80),\n        })\n      );\n      expect(submits[imageWithDifferentSize.id]).toStrictEqual(\n        expect.objectContaining({\n          width: 150,\n          height: dataPixels(150 / (200 / 120)),\n        })\n      );\n    });\n\n    it('should update height with lock ratio and different size', () => {\n      const { pushUpdate, submit } = renderSizePosition([\n        image,\n        imageWithDifferentSize,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Height' });\n      fireEvent.change(input, { target: { value: '160' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        height: 160,\n        width: MULTIPLE_VALUE,\n      });\n      expect(submitArg).toBeTrue();\n\n      const submits = submit({ height: 160, width: MULTIPLE_VALUE });\n      expect(submits[image.id]).toStrictEqual(\n        expect.objectContaining({\n          height: 160,\n          width: 160 * (100 / 80),\n        })\n      );\n      expect(submits[imageWithDifferentSize.id]).toStrictEqual(\n        expect.objectContaining({\n          height: 160,\n          width: dataPixels(160 * (200 / 120)),\n        })\n      );\n    });\n\n    it('should disable aspect ratio lock if all elements had lock enabled', () => {\n      const { pushUpdate } = renderSizePosition([image, imageWithSameSize]);\n      fireEvent.click(\n        screen.getByRole('button', { name: aspectRatioLockButtonLabel })\n      );\n      expect(pushUpdate).toHaveBeenCalledWith({ lockAspectRatio: false }, true);\n    });\n\n    it('should disable aspect ratio lock if elements had different settings for aspect ratio lock', () => {\n      const { pushUpdate } = renderSizePosition([\n        unlockImage,\n        imageWithSameSize,\n      ]);\n      fireEvent.click(\n        screen.getByRole('button', { name: aspectRatioLockButtonLabel })\n      );\n      expect(pushUpdate).toHaveBeenCalledWith({ lockAspectRatio: false }, true);\n    });\n\n    it('should enable aspect ratio lock only if all elements had lock disabled', () => {\n      const { pushUpdate } = renderSizePosition([\n        unlockImageWithSameSize,\n        unlockImage,\n      ]);\n      fireEvent.click(\n        screen.getByRole('button', { name: aspectRatioLockButtonLabel })\n      );\n      expect(pushUpdate).toHaveBeenCalledWith({ lockAspectRatio: true }, true);\n    });\n\n    it('should update height with lock ratio and extrapolated size and reset to max allowed', () => {\n      const { pushUpdate, submit } = renderSizePosition([image]);\n      const input = screen.getByRole('textbox', { name: 'Height' });\n      // Note: With PR#13339, value 200 is accepted but 2000 will be reverted to 0.\n      fireEvent.change(input, { target: { value: '1000' } });\n      fireEvent.blur(input);\n      const [updateArg, submitArg] = pushUpdate.mock.calls[0];\n      expect(updateArg()).toStrictEqual({\n        height: 1000,\n        width: 1000 * (100 / 80),\n      });\n      expect(submitArg).toBeTrue();\n\n      const submits = submit({ height: 2000, width: 2000 * (100 / 80) });\n      expect(submits[image.id]).toStrictEqual(\n        expect.objectContaining({\n          height: 1000 / (100 / 80),\n          width: 1000,\n        })\n      );\n    });\n\n    it('should display Mixed as placeholder in case of mixed values multi-selectio', () => {\n      renderSizePosition([\n        defaultText,\n        {\n          ...defaultImage,\n          width: 200,\n          height: 200,\n          rotationAngle: 20,\n        },\n      ]);\n\n      const height = screen.getByRole('textbox', { name: 'Height' });\n      expect(height.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n      expect(height).toHaveValue('');\n\n      const width = screen.getByRole('textbox', { name: 'Width' });\n      expect(width.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n      expect(width).toHaveValue('');\n\n      const rotationAngle = screen.getByRole('textbox', { name: 'Rotation' });\n      expect(rotationAngle.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n      expect(rotationAngle).toHaveValue('');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/usePresubmitHandlers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  dataPixels,\n  calcRotatedObjectPositionAndSize,\n  clamp,\n} from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\n\nimport usePresubmitHandler from '../../../form/usePresubmitHandler';\nimport { MIN_MAX } from './constants';\nimport { isNum } from './utils';\n\nfunction usePresubmitHandlers(lockAspectRatio, height, width) {\n  // Recalculate width/height if ratio locked.\n  usePresubmitHandler(\n    (\n      newElement,\n      { width: newWidth, height: newHeight },\n      { width: oldWidth, height: oldHeight }\n    ) => {\n      const { type } = newElement;\n\n      const isResizeWidth = Boolean(newWidth);\n      const isResizeHeight = Boolean(newHeight);\n      if (!isResizeWidth && !isResizeHeight) {\n        return null;\n      }\n\n      // Use resize rules if available.\n      const { updateForResizeEvent } = getDefinitionForType(type);\n      if (updateForResizeEvent) {\n        const direction = [isResizeWidth ? 1 : 0, isResizeHeight ? 1 : 0];\n        return updateForResizeEvent(\n          newElement,\n          direction,\n          clamp(newWidth, MIN_MAX.WIDTH),\n          clamp(newHeight, MIN_MAX.HEIGHT)\n        );\n      }\n\n      // Fallback to ratio.\n      if (lockAspectRatio) {\n        const ratio = oldWidth / oldHeight;\n        if (!isResizeWidth) {\n          return {\n            width: clamp(dataPixels(newHeight * ratio), MIN_MAX.WIDTH),\n          };\n        }\n        if (!isResizeHeight) {\n          return {\n            height: clamp(dataPixels(newWidth / ratio), MIN_MAX.HEIGHT),\n          };\n        }\n      }\n\n      return null;\n    },\n    [lockAspectRatio]\n  );\n\n  usePresubmitHandler(({ rotationAngle: newRotationAngle }) => {\n    return {\n      rotationAngle: newRotationAngle % 360,\n    };\n  }, []);\n\n  usePresubmitHandler(\n    ({ rotationAngle: na, x: nx, y: ny, width: nw, height: nh }) => {\n      const newDims = calcRotatedObjectPositionAndSize(na, nx, ny, nw, nh);\n      const newXOffset = nx - newDims.x;\n      const newYOffset = ny - newDims.y;\n      return {\n        x: clamp(nx, {\n          MIN: MIN_MAX.X.MIN + newXOffset - newDims.width,\n          MAX: MIN_MAX.X.MAX + newXOffset,\n        }),\n        y: clamp(ny, {\n          MIN: MIN_MAX.Y.MIN + newYOffset - newDims.height,\n          MAX: MIN_MAX.Y.MAX + newYOffset,\n        }),\n      };\n    },\n    []\n  );\n\n  const setDimensionMinMax = useCallback(\n    (value, ratio, minmax) => {\n      if (lockAspectRatio && value >= minmax.MAX) {\n        return clamp(minmax.MAX * ratio, minmax);\n      }\n\n      return clamp(value, minmax);\n    },\n    [lockAspectRatio]\n  );\n\n  usePresubmitHandler(\n    ({ height: newHeight }, { width: oldWidth, height: oldHeight }) => {\n      const ratio = oldHeight / oldWidth;\n      newHeight = clamp(newHeight, MIN_MAX.HEIGHT);\n      if (isNum(ratio)) {\n        return {\n          height: setDimensionMinMax(\n            dataPixels(newHeight),\n            ratio,\n            MIN_MAX.HEIGHT\n          ),\n        };\n      }\n      return {\n        height: clamp(newHeight, MIN_MAX.HEIGHT),\n      };\n    },\n    [height, lockAspectRatio]\n  );\n\n  usePresubmitHandler(\n    ({ width: newWidth }, { width: oldWidth, height: oldHeight }) => {\n      const ratio = oldWidth / oldHeight;\n      newWidth = clamp(newWidth, MIN_MAX.WIDTH);\n      if (isNum(ratio)) {\n        return {\n          width: setDimensionMinMax(dataPixels(newWidth), ratio, MIN_MAX.WIDTH),\n        };\n      }\n      return {\n        width: clamp(newWidth, MIN_MAX.WIDTH),\n      };\n    },\n    [width, lockAspectRatio]\n  );\n}\n\nexport default usePresubmitHandlers;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/sizePosition/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { calcRotatedObjectPositionAndSize } from '@googleforcreators/units';\n/**\n * Internal dependencies\n */\nimport { MIN_MAX } from './constants';\n\nexport function getReducedValue(items, key, smallest = true) {\n  return items.reduce((val, el) => {\n    if (smallest && el[key] < val) {\n      return el;\n    } else if (!smallest && el[key] > val) {\n      return el;\n    }\n    return val;\n  });\n}\n\nexport function getMultiSelectionMinMaxXY(selectedElements) {\n  // Gets all real dimensions of the selected elements.\n  const allDimensions = selectedElements.map((element) => {\n    return calcRotatedObjectPositionAndSize(\n      element.rotationAngle,\n      element.x,\n      element.y,\n      element.width,\n      element.height\n    );\n  });\n\n  return selectedElements.reduce((values, element, i) => {\n    const actualDimensions = allDimensions[i];\n    const xOffset = element.x - actualDimensions.x;\n    const yOffset = element.y - actualDimensions.y;\n    const minX = MIN_MAX.X.MIN + xOffset - actualDimensions.width;\n    const minY = MIN_MAX.Y.MIN + yOffset - actualDimensions.height;\n    const maxX = MIN_MAX.X.MAX + xOffset;\n    const maxY = MIN_MAX.Y.MAX + yOffset;\n    // For min values: get min value for each element and choose the highest.\n    // For max values: get max value for each and choose the lowest.\n    return {\n      minX: values.minX ? Math.max(values.minX, minX) : minX,\n      minY: values.minY ? Math.max(values.minY, minY) : minY,\n      maxX: values.maxX ? Math.min(values.maxX, maxX) : maxX,\n      maxY: values.maxY ? Math.min(values.maxY, maxY) : maxY,\n    };\n  }, {});\n}\n\nexport function isNum(v) {\n  return typeof v === 'number' && !isNaN(v);\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textAccessibility/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './textAccessibility';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textAccessibility/test/textAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { useFeature } from 'flagged';\n\n/**\n * Internal dependencies\n */\n\nimport StoryContext from '../../../../../app/story/context';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport TextAccessibilityPanel from '../textAccessibility';\n\njest.mock('flagged');\n\ndescribe('Panels/TextAccessibility', () => {\n  const defaultElement = {\n    type: 'text',\n    tagName: 'p',\n    content: 'Hello!',\n  };\n\n  const storyContextValue = {\n    state: {\n      currentPage: { elements: [] },\n    },\n  };\n\n  const wrapper = ({ children }) => (\n    <StoryContext.Provider value={storyContextValue}>\n      {children}\n    </StoryContext.Provider>\n  );\n\n  function arrange(selectedElements) {\n    return renderPanel(TextAccessibilityPanel, selectedElements, wrapper);\n  }\n\n  beforeAll(() => {\n    useFeature.mockImplementation(() => true);\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:textAccessibility',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render <TextAccessibilityPanel /> when experiment is enabled', () => {\n    arrange([\n      defaultElement,\n      {\n        type: 'text',\n        tagName: 'h2',\n        content: 'Hello friends!',\n      },\n      {\n        type: 'text',\n        tagName: 'h1',\n        content: 'Zorak here!',\n      },\n    ]);\n    const input = screen.getByTestId('text-accessibility-dropdown');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should call pushUpdate when dropdown has been updated', () => {\n    const { pushUpdate } = arrange([defaultElement]);\n    const input = screen.getByTestId('text-accessibility-dropdown');\n    fireEvent.click(input);\n    const option2 = screen.queryAllByRole('option')[1];\n    fireEvent.click(option2);\n    expect(pushUpdate).toHaveBeenCalledOnce();\n  });\n\n  it('should call pushUpdate three times when multiple items have been updated', () => {\n    const { pushUpdate } = arrange([\n      defaultElement,\n      {\n        type: 'text',\n        tagName: 'h2',\n        content: 'Hello friends!',\n      },\n      {\n        type: 'text',\n        tagName: 'h1',\n        content: 'Zorak here!',\n      },\n    ]);\n    const input = screen.getByTestId('text-accessibility-dropdown');\n    fireEvent.click(input);\n    const option2 = screen.queryAllByRole('option')[1];\n    fireEvent.click(option2);\n    expect(pushUpdate).toHaveBeenCalledTimes(3);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textAccessibility/textAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __, sprintf, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport {\n  DropDown,\n  Text,\n  TextSize,\n  Link,\n} from '@googleforcreators/design-system';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { getTextElementTagNames } from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport { Row } from '../../../form';\nimport { getCommonValue } from '../../shared';\nimport { SimplePanel } from '../../panel';\nimport {\n  MULTIPLE_VALUE,\n  MULTIPLE_DISPLAY_VALUE,\n  HEADING_LEVELS,\n} from '../../../../constants';\n\nfunction TextAccessibilityPanel({ selectedElements, pushUpdate }) {\n  const [tagNamesOverrides, setTagNamesOverrides] = useState();\n\n  const { textElements } = useStory(({ state }) => ({\n    textElements: state.currentPage?.elements\n      ?.filter(({ type }) => 'text' === type)\n      .map(({ id, tagName, ...rest }) => ({\n        id,\n        ...rest,\n        tagName: tagNamesOverrides?.get(id) || tagName,\n      })),\n  }));\n\n  const onLinkClick = useCallback((evt) => {\n    trackClick(evt, 'click_headings_docs');\n  }, []);\n\n  const handleChange = useCallback(\n    (evt, value) => {\n      setTagNamesOverrides(\n        new Map(selectedElements.map(({ id }) => [id, value]))\n      );\n\n      selectedElements.forEach(() => {\n        pushUpdate({ tagName: value }, true);\n      });\n    },\n    [pushUpdate, selectedElements]\n  );\n\n  const tagNamesMap = getTextElementTagNames(textElements);\n\n  const selectedElementsWithTagNames = selectedElements.map((element) => ({\n    ...element,\n    tagName: tagNamesMap.get(element.id),\n    defaultTagName: element.tagName || 'auto',\n  }));\n\n  const uniqueTagNames = [\n    ...new Set(\n      selectedElementsWithTagNames.map(({ tagName }) => tagName || 'auto')\n    ),\n  ];\n\n  const currentValue =\n    uniqueTagNames.length === 1 ? uniqueTagNames[0] : MULTIPLE_VALUE;\n\n  const tagName = getCommonValue(\n    selectedElementsWithTagNames,\n    'defaultTagName',\n    'auto'\n  );\n\n  const isIndeterminate = MULTIPLE_VALUE === tagName;\n  const selectedValue = 'auto' === tagName ? 'auto' : currentValue;\n\n  const options = [\n    {\n      label:\n        'auto' === selectedValue\n          ? sprintf(\n              /* translators: %s: heading level. */\n              __('Automatic (%s)', 'web-stories'),\n              HEADING_LEVELS[currentValue] || MULTIPLE_DISPLAY_VALUE\n            )\n          : __('Automatic', 'web-stories'),\n      value: 'auto',\n    },\n    {\n      label: HEADING_LEVELS.h1,\n      value: 'h1',\n    },\n    {\n      label: HEADING_LEVELS.h2,\n      value: 'h2',\n    },\n    {\n      label: HEADING_LEVELS.h3,\n      value: 'h3',\n    },\n    {\n      label: HEADING_LEVELS.p,\n      value: 'p',\n    },\n  ];\n\n  return (\n    <SimplePanel\n      name=\"textAccessibility\"\n      title={__('Accessibility', 'web-stories')}\n    >\n      <Row>\n        <DropDown\n          data-testid=\"text-accessibility-dropdown\"\n          title={__('Heading Levels', 'web-stories')}\n          dropdownButtonLabel={__('Heading Levels', 'web-stories')}\n          options={options}\n          selectedValue={selectedValue}\n          placeholder={isIndeterminate ? MULTIPLE_DISPLAY_VALUE : currentValue}\n          onMenuItemClick={handleChange}\n          dropDownLabel={__('Heading Level', 'web-stories')}\n        />\n      </Row>\n      <Text.Paragraph size={TextSize.XSmall}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                href={__('https://wp.stories.google/docs/seo/', 'web-stories')}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                onClick={onLinkClick}\n                size={TextSize.XSmall}\n              />\n            ),\n          }}\n        >\n          {__(\n            '<a>Learn more</a> about using headings in stories.',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </SimplePanel>\n  );\n}\n\nTextAccessibilityPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default TextAccessibilityPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/backgroundColor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useCallback, useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { PillGroup } from '@googleforcreators/design-system';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Color, Row } from '../../../form';\nimport { focusStyle } from '../../shared/styles';\nimport useCommonColorValue from '../../shared/useCommonColorValue';\nimport getCommonValue from '../../shared/getCommonValue';\nimport { applyHiddenPadding, removeHiddenPadding } from './utils';\n\nconst FillRow = styled(Row)`\n  align-items: flex-start;\n  justify-content: space-between;\n  button {\n    flex: 1;\n    z-index: 1;\n  }\n`;\n\nconst FILL_OPTIONS = [\n  { id: BACKGROUND_TEXT_MODE.NONE, label: __('None', 'web-stories') },\n  { id: BACKGROUND_TEXT_MODE.FILL, label: __('Fill', 'web-stories') },\n  { id: BACKGROUND_TEXT_MODE.HIGHLIGHT, label: __('Highlight', 'web-stories') },\n];\n\nfunction BackgroundControls({ selectedElements, pushUpdate }) {\n  const backgroundColor = useCommonColorValue(\n    selectedElements,\n    'backgroundColor'\n  );\n  const backgroundTextMode = getCommonValue(\n    selectedElements,\n    'backgroundTextMode'\n  );\n  const fillRow = useRef();\n  const pushBackgroundTextMode = useCallback(\n    (mode) => {\n      pushUpdate(\n        (element) => ({\n          backgroundTextMode: mode,\n          padding: [\n            BACKGROUND_TEXT_MODE.FILL,\n            BACKGROUND_TEXT_MODE.HIGHLIGHT,\n          ].includes(mode)\n            ? applyHiddenPadding(element)\n            : removeHiddenPadding(element),\n        }),\n        true\n      );\n    },\n    [pushUpdate]\n  );\n\n  const onSelect = useCallback(\n    (mode) => {\n      pushBackgroundTextMode(mode);\n    },\n    [pushBackgroundTextMode]\n  );\n\n  return (\n    <>\n      <FillRow ref={fillRow}>\n        <PillGroup\n          value={backgroundTextMode}\n          onSelect={onSelect}\n          options={FILL_OPTIONS}\n          pillStyleOverride={focusStyle}\n        />\n      </FillRow>\n      {backgroundTextMode !== BACKGROUND_TEXT_MODE.NONE && (\n        <Row>\n          <Color\n            data-testid=\"text.backgroundColor\"\n            allowsGradient\n            allowsSavedColors\n            value={backgroundColor}\n            onChange={(value) =>\n              pushUpdate(\n                {\n                  backgroundColor: value,\n                },\n                true\n              )\n            }\n            label={__('Background color', 'web-stories')}\n            labelId=\"background-color-label\"\n            changedStyle=\"background\"\n            hasEyedropper\n          />\n        </Row>\n      )}\n    </>\n  );\n}\n\nBackgroundControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default BackgroundControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/color.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  hasGradient,\n  createSolid,\n  DEFAULT_GRADIENT,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { Color, Row } from '../../../form';\nimport { MULTIPLE_VALUE } from '../../../../constants';\nimport useRichTextFormatting from './useRichTextFormatting';\n\nfunction ColorControls({ selectedElements, pushUpdate, textColorRef }) {\n  const {\n    textInfo: { color, gradientColor },\n    handlers: { handleSetColor, handleSetGradientColor },\n  } = useRichTextFormatting(selectedElements, pushUpdate);\n\n  const onColorChange = (colorValue) => {\n    if (hasGradient(colorValue)) {\n      handleSetColor(createSolid(0, 0, 0));\n      handleSetGradientColor(colorValue);\n    } else {\n      handleSetGradientColor(DEFAULT_GRADIENT);\n      handleSetColor(colorValue);\n    }\n  };\n\n  const colorInputValue =\n    gradientColor === MULTIPLE_VALUE\n      ? MULTIPLE_VALUE\n      : hasGradient(gradientColor)\n        ? gradientColor\n        : color;\n\n  return (\n    <Row>\n      <Color\n        data-testid=\"text.color\"\n        value={colorInputValue}\n        onChange={onColorChange}\n        allowsSavedColors\n        label={__('Text color', 'web-stories')}\n        labelId=\"text-color-label\"\n        ref={textColorRef}\n        hasEyedropper\n        allowsGradient\n      />\n    </Row>\n  );\n}\n\nColorControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n  textColorRef: PropTypes.func,\n};\n\nexport default ColorControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/font.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useMemo, useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { DropDown, NumericInput } from '@googleforcreators/design-system';\nimport { stripHTML } from '@googleforcreators/dom';\nimport { clamp } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useFont } from '../../../../app/font';\nimport { Row, usePresubmitHandler } from '../../../form';\nimport { focusStyle, inputContainerStyleOverride } from '../../shared/styles';\nimport { getCommonValue } from '../../shared';\nimport StoryFontPicker from '../../../storyFontPicker';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport useRichTextFormatting from './useRichTextFormatting';\nimport getFontWeights from './getFontWeights';\n\nexport const MIN_MAX = {\n  FONT_SIZE: {\n    MIN: 8,\n    MAX: 800,\n  },\n};\n\nconst Space = styled.div`\n  flex: 0 0 10px;\n`;\n\nconst StyledNumericInput = styled(NumericInput)`\n  flex-basis: 80px;\n  text-align: center;\n`;\n\nconst StyledDropDown = styled(DropDown)`\n  background-color: transparent;\n`;\n\nfunction FontControls({\n  selectedElements,\n  pushUpdate,\n  highlightStylesOverride,\n  fontDropdownRef,\n}) {\n  const fontFamily = getCommonValue(\n    selectedElements,\n    ({ font }) => font?.family\n  );\n  const fontSize = getCommonValue(selectedElements, 'fontSize');\n  const {\n    textInfo: { fontWeight, isItalic },\n    handlers: { handleSelectFontWeight },\n  } = useRichTextFormatting(selectedElements, pushUpdate);\n\n  const {\n    fonts = [],\n    maybeEnqueueFontStyle,\n    getFontByName,\n  } = useFont(\n    ({\n      actions: { maybeEnqueueFontStyle, getFontByName },\n      state: { fonts },\n    }) => ({\n      maybeEnqueueFontStyle,\n      getFontByName,\n      fonts,\n    })\n  );\n\n  const fontWeights = useMemo(\n    () => getFontWeights(getFontByName(fontFamily)),\n    [getFontByName, fontFamily]\n  );\n  const fontStyle = isItalic ? 'italic' : 'normal';\n\n  const handleFontWeightPickerChange = useCallback(\n    async (evt, value) => {\n      await maybeEnqueueFontStyle(\n        selectedElements.map(({ font, content }) => {\n          return {\n            font,\n            fontStyle,\n            fontWeight: Number.parseInt(value),\n            content: stripHTML(content),\n          };\n        })\n      );\n      handleSelectFontWeight(value);\n    },\n    [fontStyle, handleSelectFontWeight, maybeEnqueueFontStyle, selectedElements]\n  );\n\n  usePresubmitHandler(\n    ({ fontSize: newFontSize }) => ({\n      fontSize: clamp(newFontSize, MIN_MAX.FONT_SIZE),\n    }),\n    []\n  );\n\n  return (\n    <>\n      {fonts && (\n        <Row>\n          <StoryFontPicker\n            ref={fontDropdownRef}\n            highlightStylesOverride={highlightStylesOverride}\n            showDropdownLabel\n            selectedElements={selectedElements}\n          />\n        </Row>\n      )}\n      <Row>\n        {fontWeights && (\n          <>\n            <StyledDropDown\n              ariaLabel={__('Font weight', 'web-stories')}\n              placeholder={MULTIPLE_DISPLAY_VALUE}\n              options={fontWeights}\n              selectedValue={MULTIPLE_VALUE === fontWeight ? '' : fontWeight}\n              onMenuItemClick={handleFontWeightPickerChange}\n              selectButtonStylesOverride={focusStyle}\n            />\n            <Space />\n          </>\n        )}\n        <StyledNumericInput\n          aria-label={__('Font size', 'web-stories')}\n          isFloat\n          value={fontSize}\n          onChange={(evt, value) => pushUpdate({ fontSize: value }, true)}\n          min={MIN_MAX.FONT_SIZE.MIN}\n          max={MIN_MAX.FONT_SIZE.MAX}\n          isIndeterminate={MULTIPLE_VALUE === fontSize}\n          placeholder={\n            MULTIPLE_VALUE === fontSize ? MULTIPLE_DISPLAY_VALUE : null\n          }\n          containerStyleOverride={inputContainerStyleOverride}\n        />\n      </Row>\n    </>\n  );\n}\n\nFontControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n  fontDropdownRef: PropTypes.func,\n  highlightStylesOverride: PropTypes.array,\n};\n\nexport default FontControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/getClosestFontWeight.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns a number representing closest available font weight to previously selected.\n *\n * @param {number} existingWeight previously selected font weight value to get as close to as possible, defaults to 400 (normal).\n * @param {Array<string>} availableWeights available font weights for newly selected font.\n * @return {number} Closest font weight available for given font.\n */\n\nconst DEFAULT_FONT_WEIGHT = 400;\n\nfunction getClosestFontWeight(\n  existingWeight = DEFAULT_FONT_WEIGHT,\n  availableWeights\n) {\n  existingWeight = Number.parseInt(existingWeight);\n  // if the passed in existing weight is \"(multiple)\" we want to reset the value for the new font family in use\n  if (isNaN(Number.parseInt(existingWeight))) {\n    return DEFAULT_FONT_WEIGHT;\n  }\n\n  if (!availableWeights || availableWeights.length === 0) {\n    return existingWeight;\n  }\n\n  return availableWeights.reduce((a, b) => {\n    a = Number.parseInt(a);\n    b = Number.parseInt(b);\n\n    const aDiff = Math.abs(a - existingWeight);\n    const bDiff = Math.abs(b - existingWeight);\n\n    if (aDiff === bDiff) {\n      return a < b ? a : b;\n    }\n\n    return bDiff < aDiff ? b : a;\n  });\n}\n\nexport default getClosestFontWeight;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/getFontWeights.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { FONT_WEIGHT_NAMES } from '../../../../constants';\n\n/**\n * Returns a list of human-readable font weights.\n *\n * @param {Object} [font] Font object.\n * @param {Array<number>} font.weights Font weights.\n * @return {Array<Object<{name: string, value: string}>>}} Font weights list.\n */\nfunction getFontWeights(font) {\n  const defaultFontWeights = [{ label: FONT_WEIGHT_NAMES[400], value: '400' }];\n\n  if (!font?.weights) {\n    return defaultFontWeights;\n  }\n\n  return font.weights.map((weight) => ({\n    label: FONT_WEIGHT_NAMES[weight],\n    value: weight.toString(),\n  }));\n}\n\nexport default getFontWeights;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './textStyle';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/karma/contrast.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\n\ndescribe('Text Panel: Contrast Warning', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should have no aXe violations', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n      expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n    }); //change font color to white\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.textStyle.fontColor.button\n    );\n    await fixture.events.click(\n      await fixture.screen.findByRole('option', { name: '#fff' })\n    );\n\n    const contrastWarning =\n      await fixture.screen.findByTestId('warningContainer');\n    await expectAsync(contrastWarning).toHaveNoViolations();\n  });\n\n  it('should show contrast warning', async () => {\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Paragraph'));\n    await waitFor(() => {\n      if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n        throw new Error('node not ready');\n      }\n      expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n    }); //change font color to white\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.textStyle.fontColor.button\n    );\n    await fixture.events.click(\n      await fixture.screen.findByRole('option', { name: '#fff' })\n    );\n    // check that the warning icon is on screen\n    await expect(fixture.screen.queryByTitle('Low Warning')).toBeDefined();\n    // change font color back to black\n    await fixture.events.click(\n      await fixture.screen.findByRole('option', { name: '#000' })\n    );\n    // Check that the warning icon has been removed from screen. We cannot check\n    // for the text, since useLiveRegion will leave the message on the dom.\n    await expect(fixture.screen.queryByTitle('Low Warning')).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/karma/stylePresets.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\nimport { useStory } from '../../../../../app/story';\nimport { DEFAULT_PRESET } from '../../../../library/panes/text/textPresets';\n\ndescribe('Panel: Style Presets', () => {\n  let fixture;\n  let panel;\n\n  const selectTarget = async (target) => {\n    await fixture.events.keyboard.down('Shift');\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(target, 10, 10),\n      down(),\n      up(),\n    ]);\n    await fixture.events.keyboard.up('Shift');\n  };\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n    localStorage.clear();\n  });\n\n  describe('CUJ: Creator can Apply or Save Text Style from/to Their Preset Library: Save Text Style', () => {\n    it('should allow adding new text style from a text element', async () => {\n      await fixture.editor.library.textTab.click();\n\n      // Verify that no styles are added currently.\n      const noStylesText = fixture.screen.getByText('No Styles Saved');\n      expect(noStylesText).toBeDefined();\n\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      // Click to add a style and verify it was added.\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.click(panel.addStyle);\n      expect(panel.applyStyle).toBeDefined();\n    });\n\n    // Disable reason: failing since commit 4a93ee5fc82dcdb39d402ebea64c9c34c3045a13\n    // eslint-disable-next-line jasmine/no-disabled-tests\n    xit('should allow adding new text style from multi-selection', async () => {\n      await fixture.editor.library.textTab.click();\n      // Add a paragraph.\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n\n      // Select background for being able to insert a text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      // Add a heading.\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[2].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[2].node).toBeTruthy();\n      });\n      // Select the paragraph as well.\n      await selectTarget(fixture.editor.canvas.framesLayer.frames[1].node);\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n\n      // Verify that two presets have been added.\n      await fixture.events.click(panel.addStyle);\n      expect(panel.presets.length).toBe(2);\n      await fixture.snapshot('2 style presets added');\n    });\n  });\n\n  describe('CUJ: Creator can Apply or Save Text Style from/to Their Preset Library: Manage Text Style Presets', () => {\n    it('should allow deleting a text style preset', async () => {\n      // Add text element and style preset.\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.click(panel.addStyle);\n\n      // Open the style manager.\n      await fixture.events.click(panel.moreStyles);\n      await fixture.events.click(panel.styleManager.edit);\n\n      await fixture.snapshot('Style presets in edit mode');\n\n      // Verify being in edit mode.\n      expect(panel.styleManager.exit).toBeTruthy();\n\n      expect(panel.styleManager.delete).toBeTruthy();\n      await fixture.events.click(panel.styleManager.delete);\n\n      // Confirm in the dialog since it's a global preset.\n\n      // We have two dialogues open now.\n      const dialogs = await fixture.screen.findAllByRole('dialog');\n      expect(dialogs.length).toBe(2);\n      await fixture.events.click(\n        fixture.screen.getByRole('button', { name: 'Delete' })\n      );\n\n      // Verify the picker was closed (due to removing all elements).\n      expect(() => panel.styleManager.exit).toThrow();\n    });\n  });\n\n  describe('CUJ: Creator can Apply or Save Text Style from/to Their Preset Library: Apply Text Style Presets', () => {\n    it('should apply text style to a single text element', async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n\n      // Add a preset\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.click(panel.addStyle);\n\n      // Select background for being able to insert a text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n\n      // Add a heading.\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.click(panel.applyStyle);\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElements[0].fontSize).toEqual(\n        DEFAULT_PRESET.fontSize\n      );\n      await fixture.snapshot('2 texts same attributes');\n    });\n\n    // Disable reason: failing since commit 4a93ee5fc82dcdb39d402ebea64c9c34c3045a13\n    // eslint-disable-next-line jasmine/no-disabled-tests\n    xit('should apply text style to multiple text elements', async () => {\n      await fixture.editor.library.textTab.click();\n      // Add a paragraph.\n      const paragraphButton = await waitFor(() => {\n        if (!fixture.editor.library.text.preset('Paragraph')) {\n          throw new Error('paragraph button not ready');\n        }\n        return fixture.editor.library.text.preset('Paragraph');\n      });\n      await fixture.events.click(paragraphButton);\n\n      // Select background for being able to insert a text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      // Add a heading.\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      panel = fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.click(panel.addStyle);\n\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[1].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[1].node).toBeTruthy();\n      });\n      // Select both.\n      await selectTarget(fixture.editor.canvas.framesLayer.frames[1].node);\n\n      await fixture.events.click(panel.applyStyle);\n      const storyContext = await fixture.renderHook(() => useStory());\n      // Verify that both now have bold.\n      expect(storyContext.state.selectedElements[0].content).toContain(\n        '<span style=\"font-weight: 700\">'\n      );\n      expect(storyContext.state.selectedElements[1].content).toContain(\n        '<span style=\"font-weight: 700\">'\n      );\n      await fixture.snapshot('2 selected texts, same style');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/karma/textStyle.other.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, waitForElementToBeRemoved } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../../app/story';\nimport { Fixture } from '../../../../../karma/fixture';\n\ndescribe('Text Style Panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    localStorage.clear();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('Panel state', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n    });\n\n    it('should have the style panel always expanded', async () => {\n      await fixture.snapshot('Default panels state with only style panel open');\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.collapse\n      );\n      // Expect the inputs not to be visible since the panel is collapsed.\n      expect(\n        () => fixture.editor.sidebar.designPanel.textStyle.lineHeight\n      ).toThrow();\n      await fixture.snapshot('Collapsed style panel');\n\n      // Select background for being able to insert a text.\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      // Add a new text now.\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        if (!fixture.editor.canvas.framesLayer.frames[2].node) {\n          throw new Error('node not ready');\n        }\n        expect(fixture.editor.canvas.framesLayer.frames[2].node).toBeTruthy();\n      });\n      // Expect the inputs to be visible again, since the panel should be expanded again.\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      expect(\n        fixture.editor.sidebar.designPanel.textStyle.lineHeight\n      ).toBeDefined();\n    });\n  });\n\n  describe('Adaptive text color', () => {\n    it('should not allow triggering adaptive text color for multi-selection', async () => {\n      // Add 2 text elements.\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      await fixture.events.click(fixture.editor.library.text.preset('Title 2'));\n\n      // Select first text as well (the second is selected by default).\n      await fixture.events.keyboard.down('Shift');\n      await fixture.events.mouse.clickOn(\n        fixture.editor.canvas.framesLayer.frames[1].node,\n        10,\n        10\n      );\n      // await fixture.events.click(\n      //   fixture.editor.canvas.framesLayer.frames[1].node\n      // );\n      await fixture.events.keyboard.up('Shift');\n\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      expect(\n        fixture.editor.sidebar.designPanel.textStyle.adaptiveColor.disabled\n      ).toBeTrue();\n    });\n\n    it('should change the text color to white on black background', async () => {\n      // Assign black BG color.\n      await fixture.events.click(\n        fixture.editor.canvas.quickActionMenu.changeBackgroundColorButton\n      );\n      await fixture.events.keyboard.type('000');\n      await fixture.events.keyboard.press('Tab');\n\n      // Add text element.\n      await fixture.events.click(fixture.editor.sidebar.insertTab);\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.textStyle.adaptiveColor\n      );\n\n      await waitFor(\n        async () => {\n          const texts = await fixture.screen.findAllByText(\n            'Fill in some text',\n            { timeout: 2000 }\n          );\n          await expect(texts.length).toBeGreaterThan(1);\n\n          const whiteTexts = texts.filter((text) =>\n            text.outerHTML.includes('color: #fff')\n          );\n          await waitFor(\n            () => {\n              if (!whiteTexts.length) {\n                throw new Error('white text not ready');\n              }\n              expect(whiteTexts.length).toBeGreaterThan(0);\n            },\n            { timeout: 3000 }\n          );\n\n          const html = whiteTexts[0].outerHTML;\n          expect(html).toBeDefined();\n\n          expect(html).toContain('color: #fff');\n          const {\n            state: {\n              currentPage: { elements },\n            },\n          } = await fixture.renderHook(() => useStory());\n\n          if (!elements) {\n            throw new Error('story elements not ready');\n          }\n\n          expect(elements[1].content).toBe(\n            '<span style=\"color: #fff\">Fill in some text</span>'\n          );\n        },\n        { timeout: 9000 }\n      );\n    });\n  });\n\n  describe('Line-height & Padding', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n    });\n\n    it('should display padding and line-height correctly', async () => {\n      const { padding, lineHeight } =\n        fixture.editor.sidebar.designPanel.textStyle;\n      await fixture.events.focus(padding);\n      await fixture.events.keyboard.type('10');\n\n      await fixture.events.focus(lineHeight);\n      await fixture.events.keyboard.type('4');\n      await fixture.events.keyboard.press('tab');\n\n      const texts = await fixture.screen.findAllByText('Fill in some text');\n\n      // Display layer.\n      const displayStyle = await waitFor(() =>\n        window.getComputedStyle(texts[0])\n      );\n      // This verifies it includes correct units.\n      const splits = displayStyle.margin.split('px');\n      // Verify the top-bottom margin is negative.\n      expect(Number.parseInt(splits[0].trim())).toBeLessThanOrEqual(0);\n      // Verify the left-right margin is 0.\n      expect(splits[1].trim() || '0').toBe('0');\n      // Verify units are correctly added to padding.\n      expect(displayStyle.padding).toContain('px');\n\n      // Verify the same things for the frames layer.\n      const frameStyle = await waitFor(() => window.getComputedStyle(texts[1]));\n      const frameSplits = frameStyle.margin.split('px');\n      expect(Number.parseInt(frameSplits[0].trim())).toBeLessThanOrEqual(0);\n      expect(frameSplits[1].trim() || '0').toBe('0');\n      expect(frameStyle.padding).toContain('px');\n\n      await fixture.snapshot('Applied padding and line-height');\n    });\n  });\n\n  describe('Font controls', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n    });\n\n    it('should allow whole number font sizes', async () => {\n      const { fontSize } = fixture.editor.sidebar.designPanel.textStyle;\n\n      const size = 42;\n\n      await fixture.events.focus(fontSize);\n      await fixture.events.keyboard.type(`${size}`);\n      await fixture.events.keyboard.press('tab');\n\n      const {\n        state: {\n          currentPage: { elements },\n        },\n      } = await fixture.renderHook(() => useStory());\n      expect(elements[1].fontSize).toBe(size);\n    });\n\n    it('should allow fractional font sizes', async () => {\n      const { fontSize } = fixture.editor.sidebar.designPanel.textStyle;\n\n      const size = 15.25;\n\n      await fixture.events.focus(fontSize);\n      await fixture.events.keyboard.type(`${size}`);\n      await fixture.events.keyboard.press('tab');\n\n      const {\n        state: {\n          currentPage: { elements },\n        },\n      } = await fixture.renderHook(() => useStory());\n      expect(elements[1].fontSize).toBe(size);\n    });\n  });\n\n  describe('Font picker', () => {\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n    });\n    const getOptions = () => {\n      return fixture.screen\n        .getByRole('listbox', {\n          name: /Option List Selector/,\n        })\n        .querySelectorAll('li[role=\"option\"]');\n    };\n\n    describe('CUJ: Creator Can Style Text: Use font picker', () => {\n      // There are 3 curated fonts included by default even though the total is more.\n      const DEFAULT_VISIBLE_FONTS = 3;\n      const DEFAULT_CUSTOM_FONTS = 2;\n      // Timeout used for submitting / search update + 250ms (250 + 250).\n      const TIMEOUT = 500;\n      const openFontPicker = async (i = 0) => {\n        const inputs = fixture.screen.getAllByLabelText('Font family');\n        const input = i > 0 && inputs.length > i ? inputs[i] : inputs[0];\n        await fixture.events.click(input);\n      };\n\n      beforeEach(async () => {\n        await openFontPicker();\n      });\n\n      it('should render the font picker', async () => {\n        await fixture.snapshot('font picker open');\n      });\n\n      it('should apply the selected font', async () => {\n        await fixture.events.keyboard.type('Yrsa');\n        // Ensure the debounced callback has taken effect.\n        await fixture.events.sleep(TIMEOUT);\n        const option = fixture.screen.getByText('Yrsa');\n        await fixture.events.click(option);\n        await fixture.events.sleep(TIMEOUT);\n        await openFontPicker();\n        const selected = fixture.screen.getAllByRole('option', {\n          name: 'Selected Yrsa',\n        });\n        expect(selected.length).toBe(1);\n\n        const {\n          state: {\n            currentPage: { elements },\n          },\n        } = await fixture.renderHook(() => useStory());\n        expect(elements[1].font.family).toBe('Yrsa');\n      });\n\n      it('should reset font weight when font family is updated', async () => {\n        await fixture.events.keyboard.type('Yrsa');\n        // Ensure the debounced callback has taken effect.\n        await fixture.events.sleep(TIMEOUT);\n        const option = fixture.screen.getByText('Yrsa');\n        await fixture.events.click(option);\n        await fixture.events.sleep(TIMEOUT);\n\n        const { fontWeight } = fixture.editor.sidebar.designPanel.textStyle;\n        expect(fontWeight.value).toBe('Regular');\n\n        await fixture.events.click(fontWeight.select);\n\n        await fixture.events.sleep(TIMEOUT);\n        await fixture.events.click(await fontWeight.option('Bold'));\n        await fixture.events.sleep(TIMEOUT);\n        expect(fontWeight.value).toBe('Bold');\n\n        await openFontPicker();\n\n        await fixture.events.keyboard.type('Roboto');\n        // Ensure the debounced callback has taken effect.\n        await fixture.events.sleep(TIMEOUT);\n        const option2 = fixture.screen.getByText('Roboto');\n        await fixture.events.click(option2);\n        await fixture.events.sleep(600);\n        const updatedFontWeight =\n          fixture.editor.sidebar.designPanel.textStyle.fontWeight;\n\n        expect(updatedFontWeight.value).toBe('Regular');\n      });\n\n      it('should display the fonts from curated list and custom fonts by default', () => {\n        const options = getOptions();\n        expect(options.length).toBe(\n          DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS\n        );\n      });\n\n      it('should display custom fonts as the first', () => {\n        const options = getOptions();\n        expect(options[0].textContent).toBe('Overpass Regular');\n        expect(options[1].textContent).toBe('Vazir Regular');\n      });\n\n      describe('when searching fonts', () => {\n        it('should display the correct fonts when searching', async () => {\n          await fixture.events.keyboard.type('Ab');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          let options = getOptions();\n          expect(options.length).toBe(2);\n          expect(options[0].textContent).toBe('Abel');\n          expect(options[1].textContent).toBe('Abhaya Libre');\n\n          // Adding \"el\" to the search now only finds \"Abel\"\n          await fixture.events.keyboard.type('el');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          options = getOptions();\n          expect(options.length).toBe(1);\n        });\n\n        it('should include custom fonts in search', async () => {\n          await fixture.events.keyboard.type('Vazir');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          const options = getOptions();\n          expect(options.length).toBe(1);\n          expect(options[0].textContent).toBe('Vazir Regular');\n        });\n\n        it('should not search with less than 2 characters', async () => {\n          await fixture.events.keyboard.type('A');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          const options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS\n          );\n        });\n\n        it('should restore default fonts list when emptying search', async () => {\n          await fixture.events.keyboard.type('Ab');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          const options = getOptions();\n          expect(options.length).toBe(2);\n\n          await fixture.events.keyboard.press('Backspace');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          const defaultOptions = getOptions();\n          // Back to all options.\n          expect(defaultOptions.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS\n          );\n        });\n\n        it('should show empty list in case of no results', async () => {\n          await fixture.events.keyboard.type('No fonts here');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          expect(fixture.screen.getByText('No matches found')).toBeDefined();\n        });\n      });\n\n      describe('with recent fonts', () => {\n        it('should not display any recent fonts by default', () => {\n          const options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS\n          );\n        });\n\n        it('should add up to 5 recent fonts, displaying the most recent after the custom fonts', async () => {\n          await fixture.events.keyboard.type('Space Mono');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          let option = fixture.screen.getByText('Space Mono');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n\n          let options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 1\n          );\n          expect(options[DEFAULT_CUSTOM_FONTS].textContent).toBe('Space Mono');\n\n          await fixture.events.keyboard.type('Abel');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          option = fixture.screen.getByText('Abel');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n          options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 2\n          );\n\n          await fixture.events.keyboard.type('Abhaya Libre');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          option = fixture.screen.getByText('Abhaya Libre');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n          options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 3\n          );\n\n          await fixture.events.keyboard.type('Source Serif 4');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          option = fixture.screen.getByText('Source Serif 4');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n          options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 4\n          );\n\n          await fixture.events.keyboard.type('Roboto');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          option = fixture.screen.getByText('Roboto');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n          options = getOptions();\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 5\n          );\n\n          await fixture.events.keyboard.type('Yrsa');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          option = fixture.screen.getByText('Yrsa');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n\n          options = getOptions();\n\n          // Ensure there are only 5 extra options added.\n          expect(options.length).toBe(\n            DEFAULT_VISIBLE_FONTS + DEFAULT_CUSTOM_FONTS + 5\n          );\n          // Ensure the first one is the last chosen.\n          expect(options[DEFAULT_CUSTOM_FONTS].textContent).toBe('Yrsa');\n        });\n\n        it('should display the selected recent font with a tick', async () => {\n          const option = fixture.screen.getByText('Source Serif 4');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n          const selected = fixture.screen.getAllByRole('option', {\n            name: 'Selected Source Serif 4',\n          });\n          // One from the recent fonts and one from the general list.\n          expect(selected.length).toBe(2);\n        });\n\n        it('should not include recent fonts to search', async () => {\n          await fixture.events.keyboard.type('Abe');\n          await fixture.events.sleep(TIMEOUT);\n          const option = fixture.screen.getByText('Abel');\n          await fixture.events.click(option);\n          await fixture.events.sleep(TIMEOUT);\n          await openFontPicker();\n\n          await fixture.events.keyboard.type('Abe');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          const options = getOptions();\n\n          // Only showing up once for 'Abel'\n          expect(options.length).toBe(1);\n        });\n      });\n\n      describe('using keyboard only', () => {\n        it('should allow selecting a font with arrow keys and Enter', async () => {\n          // Select the fifth item in the already opened fontpicker,\n          // which happens to be Ubuntu\n          await fixture.events.keyboard.press('down');\n          await fixture.events.keyboard.press('down');\n          await fixture.events.keyboard.press('down');\n          await fixture.events.keyboard.press('down');\n          await fixture.events.keyboard.press('down');\n          await fixture.events.keyboard.press('Enter');\n          await fixture.events.sleep(TIMEOUT);\n\n          // Then open again and verify, that Ubuntu is listed as selected\n          await openFontPicker();\n          await fixture.events.keyboard.type('ubuntu');\n          // Ensure the debounced callback has taken effect.\n          await fixture.events.sleep(TIMEOUT);\n          // Only 1 selected (no recent fonts displayed when searching)\n          const selected = fixture.screen.getByRole('option', {\n            name: /selected ubuntu/i,\n          });\n          expect(selected).toBeTruthy();\n        });\n\n        it('should close the font picker with Esc', async () => {\n          const input = fixture.screen.getAllByLabelText('Font family')[0];\n          expect(input.getAttribute('aria-expanded')).toBe('true');\n          await fixture.events.keyboard.press('Esc');\n          await waitForElementToBeRemoved(\n            fixture.screen.getByRole('listbox', {\n              name: /Option List Selector/,\n            })\n          );\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/padding.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Icons,\n  LockToggle as DefaultLockToggle,\n  NumericInput,\n} from '@googleforcreators/design-system';\nimport { clamp } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { Row as DefaultRow, usePresubmitHandler } from '../../../form';\nimport { focusStyle, inputContainerStyleOverride } from '../../shared/styles';\nimport { useCommonObjectValue } from '../../shared';\nimport { metricsForTextPadding } from '../../utils/metricsForTextPadding';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport { getHiddenPadding, removeHiddenPadding } from './utils';\n\nconst DEFAULT_PADDING = {\n  horizontal: 0,\n  vertical: 0,\n  locked: true,\n  hasHiddenPadding: false,\n};\n\nconst MIN_MAX = {\n  PADDING: {\n    MIN: 0,\n    MAX: 300,\n  },\n};\n\nconst Space = styled.div`\n  flex: 0 0 8px;\n`;\n\nconst LockToggle = styled(DefaultLockToggle)`\n  ${({ isLocked }) =>\n    !isLocked &&\n    `\n    position: absolute;\n    right: 0;\n    top: calc(100% - 8px);\n  `}\n  ${focusStyle};\n`;\n\nconst Row = styled(DefaultRow)`\n  position: relative;\n`;\n\nconst IconWrapper = styled.div`\n  width: 44px;\n  margin-left: 6px;\n  color: ${({ theme }) => theme.colors.divider.primary};\n  ${({ reverse }) => reverse && 'transform: scaleY(-1);'}\n  svg {\n    width: 22px;\n  }\n`;\n\nfunction PaddingControls({\n  selectedElements,\n  pushUpdateForObject,\n  pushUpdate,\n}) {\n  const displayedPadding = useCommonObjectValue(\n    // Map over all elements and update display\n    // values to not include hidden padding\n    // if hidden padding is present\n    selectedElements.map((el) => ({\n      ...el,\n      padding: removeHiddenPadding(el),\n    })),\n    'padding',\n    DEFAULT_PADDING\n  );\n\n  // Only if true for all selected elements, will the toggle be true\n  // (Note that this behavior is different from aspect lock ratio)\n  const lockPadding = displayedPadding.locked === true;\n\n  const handleChange = useCallback(\n    (updater) => {\n      pushUpdate((el) => {\n        const { x, y, width, height } = el;\n        const newPadding = updater(el);\n        return metricsForTextPadding({\n          x,\n          y,\n          height,\n          width,\n          currentPadding: el.padding,\n          newPadding,\n        });\n      });\n      pushUpdateForObject(\n        'padding',\n        (v) => updater({ padding: v }),\n        DEFAULT_PADDING,\n        true\n      );\n    },\n    [pushUpdate, pushUpdateForObject]\n  );\n\n  usePresubmitHandler(\n    ({ padding: { horizontal, vertical, ...rest } }) => ({\n      padding: {\n        ...rest,\n        horizontal: clamp(horizontal, MIN_MAX.PADDING),\n        vertical: clamp(vertical, MIN_MAX.PADDING),\n      },\n    }),\n    []\n  );\n\n  const firstInputProperties = lockPadding\n    ? {\n        suffix: __('Padding', 'web-stories'),\n        'aria-label': __('Padding', 'web-stories'),\n        onChange: (evt, value) => {\n          handleChange((el) => {\n            return {\n              horizontal: value + getHiddenPadding(el, 'horizontal'),\n              vertical: value + getHiddenPadding(el, 'vertical'),\n            };\n          });\n        },\n        stretch: true,\n      }\n    : {\n        suffix: __('Horizontal padding', 'web-stories'),\n        'aria-label': __('Horizontal padding', 'web-stories'),\n        onChange: (evt, value) => {\n          handleChange((el) => ({\n            horizontal: value + getHiddenPadding(el, 'horizontal'),\n          }));\n        },\n      };\n\n  return (\n    <>\n      <Row>\n        <NumericInput\n          value={displayedPadding.horizontal}\n          isIndeterminate={displayedPadding.horizontal === MULTIPLE_VALUE}\n          placeholder={\n            displayedPadding.horizontal === MULTIPLE_VALUE\n              ? MULTIPLE_DISPLAY_VALUE\n              : null\n          }\n          {...firstInputProperties}\n          containerStyleOverride={inputContainerStyleOverride}\n        />\n        {lockPadding && <Space />}\n        <LockToggle\n          isLocked={lockPadding}\n          onClick={() =>\n            handleChange((el) =>\n              lockPadding\n                ? {\n                    locked: false,\n                  }\n                : {\n                    locked: true,\n                    // When setting the lock, set both dimensions to the value of horizontal\n                    horizontal: el.padding.horizontal,\n                    vertical:\n                      el.padding.horizontal +\n                      getHiddenPadding(el, 'vertical') -\n                      getHiddenPadding(el, 'horizontal'),\n                  }\n            )\n          }\n          aria-label={__('Toggle padding ratio lock', 'web-stories')}\n        />\n        {!lockPadding && (\n          <IconWrapper reverse>\n            <Icons.TurningLine />\n          </IconWrapper>\n        )}\n      </Row>\n      {!lockPadding && (\n        <Row>\n          <NumericInput\n            isIndeterminate={displayedPadding.vertical === MULTIPLE_VALUE}\n            placeholder={\n              displayedPadding.vertical === MULTIPLE_VALUE\n                ? MULTIPLE_DISPLAY_VALUE\n                : null\n            }\n            suffix={__('Vertical padding', 'web-stories')}\n            value={displayedPadding.vertical}\n            onChange={(evt, value) => {\n              handleChange((el) => ({\n                vertical: Number(value) + getHiddenPadding(el, 'vertical'),\n              }));\n            }}\n            aria-label={__('Vertical padding', 'web-stories')}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n          <IconWrapper>\n            <Icons.TurningLine />\n          </IconWrapper>\n        </Row>\n      )}\n    </>\n  );\n}\n\nPaddingControls.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdateForObject: PropTypes.func.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default PaddingControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/panelHeader.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { useContext } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport useApplyTextAutoStyle from '../../../../utils/useApplyTextAutoStyle';\nimport Tooltip from '../../../tooltip';\nimport PanelTitle from '../../panel/shared/title';\nimport panelContext from '../../panel/context';\n\nconst AutoStyleButton = styled(Button).attrs({\n  variant: ButtonVariant.Square,\n  type: ButtonType.Tertiary,\n  size: ButtonSize.Small,\n})`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(theme.colors.border.focus, '#1d1f20')};\n`;\n\nfunction PanelHeader({ selectedElements, pushUpdate }) {\n  const {\n    state: { isCollapsed },\n  } = useContext(panelContext);\n  const applyTextAutoStyle = useApplyTextAutoStyle(\n    selectedElements[0],\n    (textProps) => {\n      pushUpdate(textProps, true);\n      trackEvent('auto_style_text');\n    }\n  );\n\n  const getActions = () => {\n    if (isCollapsed) {\n      return null;\n    }\n    return (\n      <Tooltip title={__('Adaptive text colors', 'web-stories')}>\n        <AutoStyleButton\n          aria-label={__('Adaptive text colors', 'web-stories')}\n          onClick={applyTextAutoStyle}\n          disabled={selectedElements?.length > 1}\n        >\n          <Icons.ColorBucket />\n        </AutoStyleButton>\n      </Tooltip>\n    );\n  };\n  const panelTitle = __('Text', 'web-stories');\n  return (\n    <PanelTitle ariaLabel={panelTitle} secondaryAction={getActions()}>\n      {panelTitle}\n    </PanelTitle>\n  );\n}\n\nPanelHeader.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default PanelHeader;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/style.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  NumericInput,\n  Icons,\n  ToggleButton,\n  ButtonSize,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { stripHTML } from '@googleforcreators/dom';\nimport { clamp } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { useFont } from '../../../../app/font';\nimport { Row, usePresubmitHandler } from '../../../form';\nimport { focusStyle, inputContainerStyleOverride } from '../../shared/styles';\nimport { getCommonValue } from '../../shared';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport useRichTextFormatting from './useRichTextFormatting';\n\nconst MIN_MAX = {\n  LINE_HEIGHT: {\n    MIN: 0.5,\n    MAX: 10,\n  },\n  LETTER_SPACING: {\n    MIN: 0,\n    MAX: 300,\n  },\n};\n\nconst StyledNumericInput = styled(NumericInput)`\n  flex-grow: 1;\n`;\n\nconst Space = styled.div`\n  flex: 0 0 3px;\n`;\n\nconst StyledToggle = styled(ToggleButton)`\n  ${focusStyle};\n`;\n\nfunction Toggle(props) {\n  return (\n    <StyledToggle\n      size={ButtonSize.Small}\n      variant={ButtonVariant.Square}\n      {...props}\n    />\n  );\n}\n\nfunction StylePanel({ selectedElements, pushUpdate }) {\n  const {\n    actions: { maybeEnqueueFontStyle },\n  } = useFont();\n  const textAlign = getCommonValue(selectedElements, 'textAlign');\n  const lineHeight = getCommonValue(selectedElements, 'lineHeight');\n\n  const {\n    textInfo: {\n      isBold,\n      isItalic,\n      isUnderline,\n      isUppercase,\n      letterSpacing,\n      fontWeight,\n    },\n    handlers: {\n      handleClickBold,\n      handleClickItalic,\n      handleClickUnderline,\n      handleClickUppercase,\n      handleSetLetterSpacing,\n    },\n  } = useRichTextFormatting(selectedElements, pushUpdate);\n\n  const setLetterSpacingMinMax = useCallback(\n    (evt, value) =>\n      handleSetLetterSpacing(clamp(value, MIN_MAX.LETTER_SPACING)),\n    [handleSetLetterSpacing]\n  );\n\n  usePresubmitHandler(({ lineHeight: newLineHeight }) => {\n    return {\n      lineHeight: clamp(newLineHeight, MIN_MAX.LINE_HEIGHT),\n    };\n  }, []);\n\n  const handleTextAlign = useCallback(\n    (alignment) => () => {\n      pushUpdate({ textAlign: textAlign === alignment ? '' : alignment }, true);\n    },\n    [pushUpdate, textAlign]\n  );\n\n  // We need to weed out the chance, that either of these are MULTIPLE_VALUE.\n  // If not strictly true, treat as false in every way.\n  const isTrulyBold = isBold === true;\n  const isTrulyItalic = isItalic === true;\n  const isTrulyUnderline = isUnderline === true;\n  const isTrulyUppercase = isUppercase === true;\n\n  return (\n    <>\n      <Row>\n        <StyledNumericInput\n          aria-label={__('Line-height', 'web-stories')}\n          isFloat\n          value={lineHeight}\n          min={MIN_MAX.LINE_HEIGHT.MIN}\n          max={MIN_MAX.LINE_HEIGHT.MAX}\n          suffix={<Icons.LetterAHeight />}\n          onChange={(evt, value) => pushUpdate({ lineHeight: value }, true)}\n          allowEmpty\n          isIndeterminate={MULTIPLE_VALUE === lineHeight}\n          placeholder={\n            MULTIPLE_VALUE === lineHeight ? MULTIPLE_DISPLAY_VALUE : null\n          }\n          containerStyleOverride={inputContainerStyleOverride}\n        />\n        <Space />\n        <StyledNumericInput\n          aria-label={__('Letter-spacing', 'web-stories')}\n          value={letterSpacing}\n          min={MIN_MAX.LETTER_SPACING.MIN}\n          max={MIN_MAX.LETTER_SPACING.MAX}\n          suffix={<Icons.LetterAWidth />}\n          unit=\"%\"\n          onChange={setLetterSpacingMinMax}\n          allowEmpty\n          isIndeterminate={MULTIPLE_VALUE === letterSpacing}\n          placeholder={\n            MULTIPLE_VALUE === letterSpacing ? MULTIPLE_DISPLAY_VALUE : null\n          }\n          containerStyleOverride={inputContainerStyleOverride}\n        />\n      </Row>\n      <Row>\n        <Toggle\n          isToggled={textAlign === 'left'}\n          onClick={handleTextAlign('left')}\n          aria-label={__('Align text left', 'web-stories')}\n        >\n          <Icons.AlignTextLeft />\n        </Toggle>\n        <Toggle\n          isToggled={textAlign === 'center'}\n          onClick={handleTextAlign('center')}\n          aria-label={__('Align text center', 'web-stories')}\n        >\n          <Icons.AlignTextCenter />\n        </Toggle>\n        <Toggle\n          isToggled={textAlign === 'right'}\n          onClick={handleTextAlign('right')}\n          aria-label={__('Align text right', 'web-stories')}\n        >\n          <Icons.AlignTextRight />\n        </Toggle>\n        <Toggle\n          isToggled={textAlign === 'justify'}\n          onClick={handleTextAlign('justify')}\n          aria-label={__('Align text justified', 'web-stories')}\n        >\n          <Icons.AlignTextJustified />\n        </Toggle>\n        <Toggle\n          isToggled={isTrulyBold}\n          onClick={() => handleClickBold(!isTrulyBold)}\n          aria-label={__('Bold', 'web-stories')}\n        >\n          <Icons.LetterBBold />\n        </Toggle>\n        <Toggle\n          isToggled={isTrulyItalic}\n          onClick={async () => {\n            await maybeEnqueueFontStyle(\n              selectedElements.map(({ font, content }) => {\n                return {\n                  font,\n                  fontStyle: isTrulyItalic ? 'normal' : 'italic',\n                  fontWeight,\n                  content: stripHTML(content),\n                };\n              })\n            );\n            handleClickItalic(!isTrulyItalic);\n          }}\n          aria-label={__('Italic', 'web-stories')}\n        >\n          <Icons.LetterIItalic />\n        </Toggle>\n        <Toggle\n          isToggled={isTrulyUnderline}\n          onClick={() => handleClickUnderline(!isTrulyUnderline)}\n          aria-label={__('Underline', 'web-stories')}\n        >\n          <Icons.LetterUUnderline />\n        </Toggle>\n        <Toggle\n          isToggled={isTrulyUppercase}\n          onClick={() => handleClickUppercase(!isTrulyUppercase)}\n          aria-label={__('Uppercase', 'web-stories')}\n        >\n          <Icons.LetterTUppercase />\n        </Toggle>\n      </Row>\n    </>\n  );\n}\n\nStylePanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default StylePanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/stylePresets.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  TextSize,\n  Text,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n  Icons,\n  Button,\n  Placement,\n  Popup,\n  Disclosure,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { useRef, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app';\nimport { PRESET_TYPES } from '../../../../constants';\nimport useAddPreset from '../../../../utils/useAddPreset';\nimport useSidebar from '../../../sidebar/useSidebar';\nimport StyleGroup from '../../../styleManager/styleGroup';\nimport StyleManager, {\n  NoStylesWrapper as DefaultNoStylesWrapper,\n  MoreButton,\n} from '../../../styleManager';\nimport useApplyStyle from '../../../styleManager/useApplyStyle';\n\nconst PresetsHeader = styled.div`\n  display: flex;\n  padding: 8px 0;\n  justify-content: space-between;\n`;\n\nconst StylesWrapper = styled.div``;\n\nconst NoStylesWrapper = styled(DefaultNoStylesWrapper)`\n  width: calc(100% + 28px);\n`;\n\nconst SubHeading = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin: 6px 0;\n  font-weight: ${({ theme }) => theme.typography.weight.bold};\n`;\n\nconst StyledButton = styled(Button)`\n  margin-left: auto;\n`;\n\nconst NoStylesText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst SPACING = { x: 12 };\n\nfunction PresetPanel({ pushUpdate }) {\n  const textStyles = useStory(\n    ({ state }) => state.story.globalStoryStyles.textStyles\n  );\n\n  const {\n    refs: { sidebar },\n  } = useSidebar();\n  const buttonRef = useRef(null);\n  const [isPopupOpen, setIsPopupOpen] = useState(false);\n  const hasPresets = textStyles.length > 0;\n\n  const handleApplyStyle = useApplyStyle({ pushUpdate });\n  const { addGlobalPreset } = useAddPreset({ presetType: PRESET_TYPES.STYLE });\n\n  const handlePresetClick = (preset) => {\n    handleApplyStyle(preset);\n  };\n\n  return (\n    <>\n      <PresetsHeader>\n        <SubHeading size={TextSize.Small}>\n          {__('Recently Saved Styles', 'web-stories')}\n        </SubHeading>\n        <StyledButton\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          onClick={addGlobalPreset}\n          aria-label={__('Add style', 'web-stories')}\n        >\n          <Icons.Plus />\n        </StyledButton>\n      </PresetsHeader>\n      {hasPresets && (\n        <>\n          <StylesWrapper>\n            <StyleGroup\n              styles={[...textStyles].reverse().slice(0, 2)}\n              handleClick={handlePresetClick}\n            />\n          </StylesWrapper>\n          <MoreButton\n            ref={buttonRef}\n            onClick={() => setIsPopupOpen(true)}\n            aria-haspopup=\"dialog\"\n            aria-expanded={isPopupOpen}\n          >\n            {__('More styles', 'web-stories')}\n            <Disclosure $isOpen={isPopupOpen} />\n          </MoreButton>\n          <Popup\n            anchor={buttonRef}\n            dock={sidebar}\n            isOpen={isPopupOpen}\n            placement={Placement.RightStart}\n            spacing={SPACING}\n            renderContents={() => (\n              <StyleManager\n                styles={textStyles}\n                applyStyle={handlePresetClick}\n                onClose={() => setIsPopupOpen(false)}\n              />\n            )}\n          />\n        </>\n      )}\n      {!hasPresets && (\n        <NoStylesWrapper>\n          <NoStylesText size={TextSize.Small}>\n            {__('No Styles Saved', 'web-stories')}\n          </NoStylesText>\n        </NoStylesWrapper>\n      )}\n    </>\n  );\n}\n\nPresetPanel.propTypes = {\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default PresetPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/fontPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\nimport { DatalistDropdown } from '@googleforcreators/design-system';\nimport { CURATED_FONT_NAMES } from '@googleforcreators/fonts';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport FontContext from '../../../../../app/font/context';\nimport fontsListResponse from './fontsResponse';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  Popup: ({ children, isOpen }) => (isOpen ? children : null),\n}));\n\nconst fonts = fontsListResponse.map((font) => {\n  return { ...font, id: font.name };\n});\nconst availableCuratedFonts = fonts.filter(\n  (font) => CURATED_FONT_NAMES.indexOf(font.name) > 0\n);\n\nfunction arrange(options) {\n  const fontContextValues = {\n    actions: {\n      ensureMenuFontsLoaded: () => {},\n      ensureCustomFontsLoaded: () => {},\n      loadCustomFonts: jest.fn(),\n      loadCuratedFonts: jest.fn(),\n    },\n  };\n  const props = {\n    onChange: jest.fn(),\n    value: 'Roboto',\n    'aria-label': 'Font family',\n    options: fonts,\n    primaryOptions: availableCuratedFonts,\n    primaryLabel: 'Recommended',\n    priorityOptions: [],\n    priorityLabel: 'Recently used',\n    selectedId: 'Roboto',\n    placeholder: 'Roboto',\n    hasSearch: true,\n    ...options,\n  };\n\n  return renderWithTheme(\n    <FontContext.Provider value={fontContextValues}>\n      <DatalistDropdown {...props} />\n    </FontContext.Provider>\n  );\n}\n\nconst scrollTo = jest.fn();\n\ndescribe('DropDown: Font Picker', () => {\n  beforeAll(() => {\n    // Mock scrollTo\n    Object.defineProperty(window.Element.prototype, 'scrollTo', {\n      writable: true,\n      value: scrollTo,\n    });\n  });\n\n  it('should render font picker title and clicking the button should open the font picker', () => {\n    arrange();\n\n    // Fire a click event.\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    // Listbox should be showing after click\n    const fontsList = screen.getByRole('listbox');\n    expect(fontsList).toBeInTheDocument();\n\n    // Should render all options\n    const allOptionItems = screen.getAllByRole('option');\n    expect(allOptionItems).toHaveLength(availableCuratedFonts.length);\n  });\n\n  it('should mark the currently selected font', () => {\n    scrollTo.mockReset();\n    arrange();\n\n    // Fire a click event.\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    // Listbox should be showing after click\n    const fontsList = screen.getByRole('listbox');\n    expect(fontsList).toBeInTheDocument();\n\n    // Roboto option should be visible and have a selected checkmark\n    const selectedRobotoOption = screen.getByRole('option', {\n      // The \"accessible name\" is derived by concatenating the accessible names\n      // of all children,  which in this case is an SVG with aria-label=\"Selected\"\n      // and a plain text node with the font name. Thus this works!\n      name: 'Selected Roboto',\n    });\n    expect(selectedRobotoOption).toBeInTheDocument();\n\n    // We can't really validate this number anyway in JSDom (no actual\n    // layout is happening), so just expect it to be called\n    expect(scrollTo).toHaveBeenCalledWith(0, expect.any(Number));\n  });\n\n  it('should select the next font in the list when using the down arrow plus enter key', () => {\n    const onChangeFn = jest.fn();\n    arrange({ onChange: onChangeFn });\n\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    const fontsList = screen.getByRole('listbox');\n    expect(fontsList).toBeInTheDocument();\n\n    // focus first element in list\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowDown',\n    });\n\n    // focus second element in list\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowDown',\n    });\n\n    fireEvent.keyDown(fontsList, { key: 'Enter' });\n\n    // The second font in the list.\n    expect(onChangeFn).toHaveBeenCalledWith(availableCuratedFonts[1]);\n  });\n\n  it('should close the menu when the Esc key is pressed.', async () => {\n    const onChangeFn = jest.fn();\n    arrange({ onChange: onChangeFn });\n\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    const fontsList = screen.getByRole('listbox');\n    expect(fontsList).toBeInTheDocument();\n\n    fireEvent.keyDown(fontsList, {\n      key: 'Escape',\n    });\n\n    await waitFor(() => expect(fontsList).not.toBeInTheDocument());\n  });\n\n  it('should select the previous font in the list when using the up arrow plus enter key', () => {\n    const onChangeFn = jest.fn();\n    arrange({ onChange: onChangeFn });\n\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    const fontsList = screen.getByRole('listbox');\n    expect(fontsList).toBeInTheDocument();\n\n    // Move to first element in list\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowDown',\n    });\n\n    // Move to second element in list\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowDown',\n    });\n\n    // Move to third element in list\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowDown',\n    });\n\n    fireEvent.keyDown(fontsList, {\n      key: 'ArrowUp',\n    });\n\n    fireEvent.keyDown(fontsList, { key: 'Enter' });\n\n    // Moving down by 2 and back 1 up should end up with the second font: Roboto Condensed.\n    expect(onChangeFn).toHaveBeenCalledWith(availableCuratedFonts[1]);\n  });\n\n  it('should search and filter the list to match the results.', async () => {\n    arrange();\n\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    expect(screen.queryAllByRole('option')).toHaveLength(\n      availableCuratedFonts.length\n    );\n\n    // Search for \"Ab\" which is the prefix of 3 font, and the substring of another 2 fonts\n    // should match all 5 fonts\n    fireEvent.change(screen.getByRole('combobox'), {\n      target: { value: 'Ab' },\n    });\n\n    await waitFor(\n      () => expect(screen.queryAllByRole('option')).toHaveLength(5),\n      {\n        timeout: 500,\n      }\n    );\n  });\n\n  it('should show an empty list when the search keyword has no results.', async () => {\n    arrange();\n\n    const selectButton = screen.getByRole('button');\n    fireEvent.click(selectButton);\n\n    expect(screen.queryAllByRole('option')).toHaveLength(\n      availableCuratedFonts.length\n    );\n\n    fireEvent.change(screen.getByRole('combobox'), {\n      target: { value: 'Not a font!' },\n    });\n\n    await waitFor(\n      () => expect(screen.queryByRole('option')).not.toBeInTheDocument(),\n      {\n        timeout: 500,\n      }\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/fontsResponse.json",
    "content": "[\n  {\n    \"name\": \"ABeeZee\",\n    \"value\": \"ABeeZee\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ]\n  },\n  {\n    \"name\": \"Abel\",\n    \"value\": \"Abel\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Abhaya Libre\",\n    \"value\": \"Abhaya Libre\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 500, 600, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700],\n      [0, 800]\n    ]\n  },\n  {\n    \"name\": \"Alfa Slab One\",\n    \"value\": \"Alfa Slab One\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Alice\",\n    \"value\": \"Alice\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Alike\",\n    \"value\": \"Alike\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Alike Angular\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Allan\",\n    \"value\": \"Allan\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ]\n  },\n  {\n    \"name\": \"Allerta\",\n    \"value\": \"Allerta\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Allerta Stencil\",\n    \"value\": \"Allerta Stencil\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Allura\",\n    \"value\": \"Allura\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Almarai\",\n    \"value\": \"Almarai\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [300, 400, 700, 800],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 700],\n      [0, 800]\n    ]\n  },\n  {\n    \"name\": \"Almendra\",\n    \"value\": \"Almendra\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Almendra Display\",\n    \"value\": \"Almendra Display\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Almendra SC\",\n    \"value\": \"Almendra SC\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Gelasio\",\n    \"value\": \"Gelasio\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 500, 600, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 600],\n      [1, 600],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Gentium Basic\",\n    \"value\": \"Gentium Basic\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Gentium Book Basic\",\n    \"value\": \"Gentium Book Basic\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Geo\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400]\n    ]\n  },\n  {\n    \"name\": \"Gochi Hand\",\n    \"value\": \"Gochi Hand\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Gorditas\",\n    \"value\": \"Gorditas\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 700]\n    ]\n  },\n  {\n    \"name\": \"Gugi\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Gupter\",\n    \"value\": \"Gupter\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 500, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 500],\n      [0, 700]\n    ]\n  },\n  {\n    \"name\": \"Gurajada\",\n    \"value\": \"Gurajada\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Habibi\",\n    \"value\": \"Habibi\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Halant\",\n    \"value\": \"Halant\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ]\n  },\n  {\n    \"name\": \"Hammersmith One\",\n    \"value\": \"Hammersmith One\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Hanalei\",\n    \"value\": \"Hanalei\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Hanalei Fill\",\n    \"value\": \"Hanalei Fill\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Handlee\",\n    \"value\": \"Handlee\",\n    \"fallbacks\": [\"cursive\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400],\n    \"styles\": [\"regular\"],\n    \"variants\": [[0, 400]]\n  },\n  {\n    \"name\": \"Roboto\",\n    \"value\": \"Roboto\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [100, 300, 400, 500, 700, 900],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700],\n      [0, 900],\n      [1, 900]\n    ]\n  },\n  {\n    \"name\": \"Roboto Condensed\",\n    \"value\": \"Roboto Condensed\",\n    \"fallbacks\": [\"sans-serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [300, 400, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Roboto Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [100, 300, 400, 500, 700],\n    \"styles\": [\"italic\", \"regular\"],\n    \"variants\": [\n      [0, 100],\n      [1, 100],\n      [0, 300],\n      [1, 300],\n      [0, 400],\n      [1, 400],\n      [0, 500],\n      [1, 500],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Source Serif 4\",\n    \"value\": \"Source Serif 4\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 400],\n      [0, 600],\n      [0, 700]\n    ]\n  },\n  {\n    \"name\": \"Space Mono\",\n    \"value\": \"Space Mono\",\n    \"fallbacks\": [\"monospace\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [400, 700],\n    \"styles\": [\"regular\", \"italic\"],\n    \"variants\": [\n      [0, 400],\n      [1, 400],\n      [0, 700],\n      [1, 700]\n    ]\n  },\n  {\n    \"name\": \"Yrsa\",\n    \"value\": \"Yrsa\",\n    \"fallbacks\": [\"serif\"],\n    \"service\": \"fonts.google.com\",\n    \"weights\": [300, 400, 500, 600, 700],\n    \"styles\": [\"regular\"],\n    \"variants\": [\n      [0, 300],\n      [0, 400],\n      [0, 500],\n      [0, 600],\n      [0, 700]\n    ]\n  }\n]\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/getClosestFontWeight.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getClosestFontWeight from '../getClosestFontWeight';\n\ndescribe('getClosestFontWeight', () => {\n  it('should return existing font weight when no availableWeights are present', () => {\n    const result = getClosestFontWeight(300);\n    expect(result).toBe(300);\n  });\n\n  it('should return default 400 font weight when no existingWeight or availableWeights are present', () => {\n    const result = getClosestFontWeight();\n    expect(result).toBe(400);\n  });\n\n  it('should return 600 when availableWeight of 600 is present and existingWeight is 600', () => {\n    const result = getClosestFontWeight(600, [100, 300, 600, 700]);\n    expect(result).toBe(600);\n  });\n\n  it('should return 600 when availableWeight of 600 is present even when weights are not listed in ascending order and existingWeight is 600', () => {\n    const result = getClosestFontWeight(600, [700, 300, 600, 100]);\n    expect(result).toBe(600);\n  });\n\n  it('should return 400 when availableWeights are [100, 300, 400, 600] and existingWeight is 500', () => {\n    const result = getClosestFontWeight(500, [100, 300, 400, 600]);\n    expect(result).toBe(400);\n  });\n\n  it('should return 400 when availableWeights are [600, 300, 400, 100] even when not listed in ascending order and existingWeight is 500', () => {\n    const result = getClosestFontWeight(500, [600, 300, 400, 400]);\n    expect(result).toBe(400);\n  });\n\n  it('should return 800 when availableWeights are [400, 800] and existingWeight is 700', () => {\n    const result = getClosestFontWeight(700, [400, 800]);\n    expect(result).toBe(800);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/getFontWeights.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getFontWeights from '../getFontWeights';\n\ndescribe('getFontWeights', () => {\n  it('should return a default value if no font provided', () => {\n    const result = getFontWeights();\n    expect(result).toHaveLength(1);\n    expect(result[0]).toMatchObject({\n      label: 'Regular',\n      value: '400',\n    });\n  });\n\n  it('should return a default value if no weights provided', () => {\n    const result = getFontWeights({ family: 'Roboto' });\n    expect(result).toHaveLength(1);\n    expect(result[0]).toMatchObject({\n      label: 'Regular',\n      value: '400',\n    });\n  });\n\n  it('should return a list of font weights with strings as values', () => {\n    const result = getFontWeights({ weights: [200, 400, 700] });\n    expect(result).toHaveLength(3);\n    expect(result).toStrictEqual([\n      {\n        label: 'Extra-light',\n        value: '200',\n      },\n      {\n        label: 'Regular',\n        value: '400',\n      },\n      {\n        label: 'Bold',\n        value: '700',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/stylePresetPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport {\n  TEXT_ELEMENT_DEFAULT_FONT,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StylePresetPanel from '../stylePresets';\nimport StoryContext from '../../../../../app/story/context';\nimport { getTextPresets, areAllType } from '../../../../../utils/presetUtils';\n\njest.mock('../../../../../utils/presetUtils');\n\nfunction arrange(extraStylePresets, extraStateProps) {\n  const updateStory = jest.fn();\n  const updateElementsById = jest.fn();\n  const pushUpdate = jest.fn();\n\n  const textElement = {\n    id: '1',\n    type: 'text',\n    content: 'Hello, styles',\n  };\n  const storyContextValue = {\n    state: {\n      currentPage: {\n        elements: [\n          {\n            id: 'bg',\n            type: 'shape',\n          },\n          textElement,\n        ],\n      },\n      selectedElementIds: ['1'],\n      selectedElements: [textElement],\n      ...extraStateProps,\n      story: {\n        globalStoryStyles: {\n          colors: [],\n          textStyles: [],\n          ...extraStylePresets,\n        },\n        currentStoryStyles: {\n          colors: [],\n        },\n      },\n    },\n    actions: { updateStory, updateElementsById },\n  };\n\n  const {\n    getAllByRole,\n    getByRole,\n    getByText,\n    queryByLabelText,\n    getByLabelText,\n    queryByText,\n    queryAllByLabelText,\n  } = renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <StylePresetPanel pushUpdate={pushUpdate} />\n    </StoryContext.Provider>\n  );\n  return {\n    getAllByRole,\n    getByRole,\n    getByText,\n    queryByText,\n    getByLabelText,\n    pushUpdate,\n    queryByLabelText,\n    queryAllByLabelText,\n    updateStory,\n    updateElementsById,\n  };\n}\n\nconst APPLY_PRESET = 'Apply style';\nconst TEST_COLOR = {\n  color: {\n    r: 1,\n    g: 1,\n    b: 1,\n  },\n};\nconst BACKGROUND_PROPS = {\n  backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n  backgroundColor: TEST_COLOR,\n};\n\nconst TEST_STYLE = {\n  color: TEST_COLOR,\n  letterSpacing: 1,\n  lineHeight: 2,\n  ...BACKGROUND_PROPS,\n  fontWeight: 700,\n  font: TEXT_ELEMENT_DEFAULT_FONT,\n};\n\ndescribe('panels/Text/Style', () => {\n  beforeAll(() => {\n    areAllType.mockImplementation((elType, els) => {\n      return els.length > 0 && els.every(({ type }) => elType === type);\n    });\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  describe('panels/Text/Style/Header', () => {\n    it('should add a text style preset', () => {\n      const extraStateProps = {\n        selectedElements: [\n          {\n            id: '1',\n            type: 'text',\n            content:\n              '<span style=\"letter-spacing: 2px; color: rgb(1, 1, 1)\">Content</span>',\n            backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n            backgroundColor: TEST_COLOR,\n            font: TEXT_ELEMENT_DEFAULT_FONT,\n          },\n        ],\n      };\n      const { updateStory } = arrange(null, extraStateProps);\n\n      getTextPresets.mockImplementation(() => {\n        return {\n          colors: [],\n          textStyles: [TEST_STYLE],\n        };\n      });\n\n      const addButton = screen.queryByLabelText('Add style');\n      fireEvent.click(addButton);\n\n      expect(updateStory).toHaveBeenCalledOnce();\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          globalStoryStyles: {\n            colors: [],\n            textStyles: [TEST_STYLE],\n          },\n        },\n      });\n    });\n  });\n\n  describe('panels/Text/Style/Styles', () => {\n    it('should allow applying styles for text', () => {\n      const extraStylePresets = {\n        textStyles: [TEST_STYLE],\n      };\n      const { pushUpdate } = arrange(extraStylePresets);\n\n      const applyPreset = screen.getByRole('button', { name: APPLY_PRESET });\n      expect(applyPreset).toBeInTheDocument();\n\n      fireEvent.click(applyPreset);\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function), true);\n      const updaterFunction = pushUpdate.mock.calls[0][0];\n      const partiallyBlueContent = {\n        content: 'Hello <span style=\"color: blue\">World</span>',\n      };\n      const updatedContent = updaterFunction(partiallyBlueContent);\n      const expectedContent = {\n        content: '<span style=\"color: #010101\">Hello World</span>',\n      };\n      expect(updatedContent).toStrictEqual(\n        expect.objectContaining(expectedContent)\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/textBox.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { fireEvent, screen } from '@testing-library/react';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport TextStyle from '../textStyle';\nimport {\n  HIDDEN_PADDING,\n  MULTIPLE_DISPLAY_VALUE,\n} from '../../../../../constants';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport FontContext from '../../../../../app/font/context';\nimport { StoryContext } from '../../../../../app/story';\n\nlet mockControls;\njest.mock('../../../../form/color/color', () => {\n  const React = require('@googleforcreators/react');\n\n  const _PropTypes = require('prop-types');\n\n  const FakeControl = React.forwardRef(function FakeControl(props, ref) {\n    mockControls[props['data-testid']] = props;\n    return <div ref={ref} />;\n  });\n  FakeControl.propTypes = {\n    'data-testid': _PropTypes.string,\n  };\n  return {\n    __esModule: true,\n    default: FakeControl,\n  };\n});\n\nfunction Wrapper({ children }) {\n  const storyContextValue = {\n    state: {\n      selectedElements: [\n        {\n          font: {\n            family: 'ABeeZee',\n          },\n        },\n      ],\n      story: {\n        globalStoryStyles: {\n          colors: [],\n          textStyles: [],\n        },\n        currentStoryStyles: {\n          colors: [],\n        },\n      },\n    },\n    actions: { updateStory: jest.fn(), updateElementsById: jest.fn() },\n  };\n  return (\n    <StoryContext.Provider value={storyContextValue}>\n      <FontContext.Provider\n        value={{\n          state: {\n            fonts: [],\n          },\n          actions: {\n            maybeEnqueueFontStyle: () => Promise.resolve(),\n            getFontByName: jest.fn(),\n            loadCustomFonts: jest.fn(),\n            loadCuratedFonts: jest.fn(),\n          },\n        }}\n      >\n        {children}\n      </FontContext.Provider>\n    </StoryContext.Provider>\n  );\n}\n\nWrapper.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n\nconst DEFAULT_PADDING = {\n  horizontal: 0,\n  vertical: 0,\n  locked: true,\n  hasHiddenPadding: false,\n};\n\ndescribe('panels/TextStyle/TextBox', () => {\n  mockControls = {};\n  let textElement, unlockPaddingTextElement;\n  const paddingRatioLockLabel = 'Toggle padding ratio lock';\n\n  beforeEach(() => {\n    window.fetch.resetMocks();\n\n    unlockPaddingTextElement = {\n      id: '1',\n      textAlign: 'normal',\n      fontSize: 30,\n      lineHeight: 1,\n      font: {\n        family: 'ABeeZee',\n      },\n      x: 0,\n      y: 0,\n      height: 100,\n      width: 120,\n      rotationAngle: 0,\n      padding: { vertical: 0, horizontal: 0, locked: false },\n      backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n    };\n\n    textElement = {\n      ...unlockPaddingTextElement,\n      padding: DEFAULT_PADDING,\n    };\n  });\n\n  function renderTextBox(selectedElements, ...args) {\n    return renderPanel(TextStyle, selectedElements, Wrapper, ...args);\n  }\n\n  describe('paddingControls', () => {\n    let textSamePadding,\n      unlockPaddingTextSamePadding,\n      textDifferentPadding,\n      unlockPaddingTextDifferentPadding;\n\n    function testUpdaterOnElementVariations({\n      pushUpdate,\n      pushUpdateForObject,\n      expectedPaddingProperties,\n    }) {\n      // Test that padding in closure of updater is expected\n      const pufoUpdateArg = pushUpdateForObject.mock.calls[0][1];\n      const padding = {};\n      const updatedProperties = pufoUpdateArg(padding);\n      expect(updatedProperties).toStrictEqual(expectedPaddingProperties);\n\n      // Test that element with hidden padding retains hidden padding\n      const withHiddenPadding = { hasHiddenPadding: true };\n      const updatedPropertiesWithHiddenPadding =\n        pufoUpdateArg(withHiddenPadding);\n      const expectedPropertiesWithHiddenPadding = [\n        'horizontal',\n        'vertical',\n      ].reduce((accum, key) => {\n        if (key in expectedPaddingProperties) {\n          accum[key] = expectedPaddingProperties[key] + HIDDEN_PADDING[key];\n        }\n        return accum;\n      }, {});\n      expect(updatedPropertiesWithHiddenPadding).toStrictEqual(\n        expectedPropertiesWithHiddenPadding\n      );\n\n      // Test that element coords are updated to not move visual center\n      const puUpdateArg = pushUpdate.mock.calls[0][0];\n      [\n        {\n          x: 40,\n          y: 40,\n          width: 100,\n          height: 100,\n          padding: {},\n        },\n        // Test that element with hidden padding retains visual center\n        {\n          x: 70,\n          y: 80,\n          width: 90,\n          height: 100,\n          padding: { hasHiddenPadding: true },\n        },\n      ].forEach((el) => {\n        const updated = puUpdateArg(el);\n        const expectedPadding = el.padding.hasHiddenPadding\n          ? expectedPropertiesWithHiddenPadding\n          : expectedPaddingProperties;\n\n        const expected = {};\n        if ('horizontal' in expectedPadding) {\n          expected.x = el.x - (expectedPadding.horizontal || 0);\n          expected.width = el.width + (expectedPadding.horizontal || 0) * 2;\n        }\n\n        if ('vertical' in expectedPadding) {\n          expected.y = el.y - (expectedPadding.vertical || 0);\n          expected.height = el.height + (expectedPadding.vertical || 0) * 2;\n        }\n\n        expect(updated).toStrictEqual(expected);\n      });\n    }\n\n    beforeEach(() => {\n      textSamePadding = {\n        ...textElement,\n        id: 'textSamePadding',\n        padding: DEFAULT_PADDING,\n      };\n      unlockPaddingTextSamePadding = {\n        ...textSamePadding,\n        padding: { ...DEFAULT_PADDING, locked: false },\n      };\n      textDifferentPadding = {\n        ...textElement,\n        id: 'textDifferentPadding',\n        padding: { horizontal: 10, vertical: 20, locked: true },\n      };\n      unlockPaddingTextDifferentPadding = {\n        ...textDifferentPadding,\n        padding: { horizontal: 10, vertical: 20, locked: false },\n      };\n    });\n\n    it('should render default padding controls', () => {\n      renderTextBox([textElement]);\n      const multi = screen.getByRole('textbox', {\n        name: 'Padding',\n      });\n      const lock = screen.getByRole('button', { name: paddingRatioLockLabel });\n      expect(multi).toHaveValue('0');\n      expect(lock).toHaveAttribute('aria-pressed', 'true');\n    });\n\n    it('should render specified padding controls', () => {\n      renderTextBox([\n        {\n          ...textElement,\n          padding: {\n            horizontal: 11,\n            vertical: 12,\n            locked: false,\n          },\n        },\n      ]);\n      const horiz = screen.getByRole('textbox', { name: 'Horizontal padding' });\n      const vert = screen.getByRole('textbox', { name: 'Vertical padding' });\n      expect(horiz).toHaveValue('11');\n      expect(vert).toHaveValue('12');\n    });\n\n    it('should update horizontal padding with lock', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([textElement]);\n      const input = screen.getByRole('textbox', {\n        name: 'Padding',\n      });\n      fireEvent.change(input, { target: { value: '20' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 20, vertical: 20 },\n      });\n    });\n\n    it('should update horizontal padding without lock', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        unlockPaddingTextElement,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Horizontal padding' });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11 },\n      });\n    });\n\n    it('should update vertical padding without lock', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        unlockPaddingTextElement,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Vertical padding' });\n      fireEvent.change(input, { target: { value: '12' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { vertical: 12 },\n      });\n    });\n\n    it('should not update padding if empty string is submitted', () => {\n      renderTextBox([\n        {\n          ...textSamePadding,\n          padding: { ...DEFAULT_PADDING, horizontal: 10, vertical: 10 },\n        },\n      ]);\n      const input = screen.getByRole('textbox', {\n        name: 'Padding',\n      });\n      fireEvent.change(input, { target: { value: '' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      fireEvent.blur(input);\n\n      expect(input).toHaveValue('10');\n    });\n\n    it('should update multi padding with lock and same padding', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        textElement,\n        textSamePadding,\n      ]);\n      const input = screen.getByRole('textbox', {\n        name: 'Padding',\n      });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11, vertical: 11 },\n      });\n    });\n\n    it('should update multi padding with lock and different padding', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        textElement,\n        textDifferentPadding,\n      ]);\n      const input = screen.getByRole('textbox', {\n        name: 'Padding',\n      });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      fireEvent.blur(input);\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11, vertical: 11 },\n      });\n    });\n\n    it('should update multi padding without lock and same padding', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        unlockPaddingTextElement,\n        unlockPaddingTextSamePadding,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Horizontal padding' });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11 },\n      });\n    });\n\n    it('should update multi padding without lock and different padding', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        unlockPaddingTextElement,\n        unlockPaddingTextDifferentPadding,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Horizontal padding' });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11 },\n      });\n    });\n\n    it('should correctly update only horizontal padding when multiple elements with different padding lock settings are selected', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        textElement,\n        unlockPaddingTextDifferentPadding,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Horizontal padding' });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { horizontal: 11 },\n      });\n    });\n\n    it('should correctly update only vertical padding when multiple elements with different padding lock settings are selected', () => {\n      const { pushUpdateForObject, pushUpdate } = renderTextBox([\n        textElement,\n        unlockPaddingTextDifferentPadding,\n      ]);\n      const input = screen.getByRole('textbox', { name: 'Vertical padding' });\n      fireEvent.change(input, { target: { value: '11' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n\n      // See that updates were pushed\n      expect(pushUpdate).toHaveBeenCalledWith(expect.any(Function));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      // See that updates are proper for element variations\n      testUpdaterOnElementVariations({\n        pushUpdateForObject,\n        pushUpdate,\n        expectedPaddingProperties: { vertical: 11 },\n      });\n    });\n\n    it('should update default element lockPadding to false when padding lock clicked', () => {\n      const { pushUpdateForObject } = renderTextBox([textElement]);\n      fireEvent.click(screen.getByLabelText(paddingRatioLockLabel));\n      const pufoUpdater = pushUpdateForObject.mock.calls[0][1];\n      const el = { padding: {} };\n      const updatedProperties = pufoUpdater(el);\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n      expect(updatedProperties).toStrictEqual({\n        locked: false,\n      });\n    });\n\n    it('should update unlock padding element lockPadding to true when padding lock clicked', () => {\n      const { pushUpdateForObject } = renderTextBox([unlockPaddingTextElement]);\n      fireEvent.click(screen.getByLabelText(paddingRatioLockLabel));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      const pufoUpdater = pushUpdateForObject.mock.calls[0][1];\n      const updatedProperties = pufoUpdater({\n        horizontal: 0,\n      });\n      expect(updatedProperties).toStrictEqual({\n        horizontal: 0,\n        vertical: 0,\n        locked: true,\n      });\n    });\n\n    it('should update multiple elements with default text element and unlock padding elements lockPadding to false when padding lock clicked', () => {\n      const { pushUpdateForObject } = renderTextBox([\n        unlockPaddingTextElement,\n        textElement,\n      ]);\n      fireEvent.click(screen.getByLabelText(paddingRatioLockLabel));\n      expect(pushUpdateForObject).toHaveBeenCalledWith(\n        'padding',\n        expect.any(Function),\n        DEFAULT_PADDING,\n        true\n      );\n\n      const pufoUpdater = pushUpdateForObject.mock.calls[0][1];\n      const updatedProperties = pufoUpdater({\n        horizontal: 0,\n      });\n      expect(updatedProperties).toStrictEqual({\n        horizontal: 0,\n        vertical: 0,\n        locked: true,\n      });\n    });\n  });\n\n  describe('mixed value multi-selection', () => {\n    it('should display Mixed value in case of mixed value multi-selection', () => {\n      const textElement1 = textElement;\n      const textElement2 = {\n        ...textElement,\n        padding: {\n          vertical: 1,\n          horizontal: 1,\n        },\n      };\n\n      renderTextBox([textElement1, textElement2]);\n\n      const paddingH = screen.getByRole('textbox', {\n        name: 'Horizontal padding',\n      });\n      expect(paddingH.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n\n      const paddingV = screen.getByRole('textbox', {\n        name: 'Vertical padding',\n      });\n      expect(paddingV.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/test/textStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { act, fireEvent, screen } from '@testing-library/react';\nimport { createSolid } from '@googleforcreators/patterns';\nimport { RichTextContext } from '@googleforcreators/rich-text';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\nimport { calculateTextHeight } from '@googleforcreators/element-library';\nimport { calcRotatedResizeOffset } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport TextStyle from '../textStyle';\nimport FontContext from '../../../../../app/font/context';\nimport { StoryContext } from '../../../../../app/story';\nimport CanvasContext from '../../../../../app/canvas/context';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport {\n  MULTIPLE_VALUE,\n  MULTIPLE_DISPLAY_VALUE,\n} from '../../../../../constants';\n\nlet mockControls;\njest.mock('@googleforcreators/design-system', () => {\n  const React = require('@googleforcreators/react');\n\n  const _PropTypes = require('prop-types');\n\n  const FakeControl = React.forwardRef(function FakeControl(props, ref) {\n    mockControls[props['data-testid']] = props;\n    return <div ref={ref} />;\n  });\n  FakeControl.propTypes = {\n    'data-testid': _PropTypes.string,\n  };\n  return {\n    __esModule: true,\n    ...jest.requireActual('@googleforcreators/design-system'),\n    DatalistDropdown: FakeControl,\n  };\n});\njest.mock('@googleforcreators/element-library');\njest.mock('../../../../form/color/color', () => {\n  const React = require('@googleforcreators/react');\n\n  const _PropTypes = require('prop-types');\n\n  const FakeControl = React.forwardRef(function FakeControl(props, ref) {\n    mockControls[props['data-testid']] = props;\n    return <div ref={ref} />;\n  });\n  FakeControl.propTypes = {\n    'data-testid': _PropTypes.string,\n  };\n  return {\n    __esModule: true,\n    default: FakeControl,\n  };\n});\n\nconst DEFAULT_PADDING = {\n  horizontal: 0,\n  vertical: 0,\n  locked: true,\n  hasHiddenPadding: false,\n};\n\nconst textElement = {\n  id: '1',\n  type: 'text',\n  textAlign: 'normal',\n  fontSize: 30,\n  lineHeight: 1,\n  font: {\n    family: 'ABeeZee',\n  },\n  x: 0,\n  y: 0,\n  height: 100,\n  width: 120,\n  rotationAngle: 0,\n  padding: DEFAULT_PADDING,\n  backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n};\n\nlet mockUpdateSelectedElements;\n\nfunction getAndSetMockUpdateSelectedElements() {\n  mockUpdateSelectedElements = jest.fn();\n  return mockUpdateSelectedElements;\n}\nfunction Wrapper({ selectedElements, children }) {\n  const storyContextValue = {\n    state: {\n      selectedElements: selectedElements,\n      story: {\n        globalStoryStyles: {\n          colors: [],\n          textStyles: [],\n        },\n        currentStoryStyles: {\n          colors: [],\n        },\n      },\n    },\n    actions: {\n      updateStory: jest.fn(),\n      updateElementsById: getAndSetMockUpdateSelectedElements(),\n    },\n  };\n  return (\n    <StoryContext.Provider value={storyContextValue}>\n      <CanvasContext.Provider\n        value={{\n          state: {},\n          actions: {\n            clearEditing: jest.fn(),\n          },\n        }}\n      >\n        <FontContext.Provider\n          value={{\n            state: {\n              fonts: [\n                {\n                  name: 'ABeeZee',\n                  value: 'ABeeZee',\n                  service: 'foo.bar.baz',\n                  weights: [400],\n                  styles: ['italic', 'regular'],\n                  variants: [\n                    [0, 400],\n                    [1, 400],\n                  ],\n                  fallbacks: ['serif'],\n                },\n                {\n                  name: 'Neu Font',\n                  value: 'Neu Font',\n                  service: 'foo.bar.baz',\n                  weights: [400],\n                  styles: ['italic', 'regular'],\n                  variants: [\n                    [0, 400],\n                    [1, 400],\n                  ],\n                  fallbacks: ['fallback1'],\n                },\n              ],\n            },\n            actions: {\n              maybeEnqueueFontStyle: () => Promise.resolve(),\n              getFontByName: () => ({\n                name: 'Neu Font',\n                value: 'Neu Font',\n                service: 'foo.bar.baz',\n                weights: [400],\n                styles: ['italic', 'regular'],\n                variants: [\n                  [0, 400],\n                  [1, 400],\n                ],\n                fallbacks: ['fallback1'],\n              }),\n              addRecentFont: jest.fn(),\n              loadCustomFonts: jest.fn(),\n              loadCuratedFonts: jest.fn(),\n            },\n          }}\n        >\n          <RichTextContext.Provider\n            value={{ state: {}, actions: { selectionActions: {} } }}\n          >\n            {children}\n          </RichTextContext.Provider>\n        </FontContext.Provider>\n      </CanvasContext.Provider>\n    </StoryContext.Provider>\n  );\n}\n\nWrapper.propTypes = {\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n\ndescribe('Panels/TextStyle', () => {\n  beforeEach(() => {\n    window.fetch.resetMocks();\n\n    mockControls = {};\n  });\n\n  function arrange(selectedElements, ...args) {\n    return renderPanel(TextStyle, selectedElements, Wrapper, ...args);\n  }\n\n  it('should render <TextStyle /> panel', () => {\n    arrange([textElement]);\n    const element = screen.getByRole('button', { name: 'Text' });\n    expect(element).toBeInTheDocument();\n  });\n\n  it('should recalculate height and offset', () => {\n    const { submit } = arrange([textElement]);\n    calculateTextHeight.mockImplementation(() => 171);\n\n    const [dx, dy] = calcRotatedResizeOffset(0, 0, 0, 0, 171 - 100);\n    const submits = submit({ fontSize: 70 });\n    expect(submits[textElement.id]).toStrictEqual({\n      fontSize: 70,\n      height: 171,\n      lineHeight: 1,\n      x: dx,\n      y: dy,\n      padding: {\n        hasHiddenPadding: false,\n        horizontal: 0,\n        locked: true,\n        vertical: 0,\n      },\n    });\n  });\n\n  describe('FontControls', () => {\n    it('should select font', async () => {\n      arrange([textElement]);\n      const newFont = {\n        id: 'Neu Font',\n        family: 'Neu Font',\n        service: 'foo.bar.baz',\n        styles: ['italic', 'regular'],\n        weights: [400],\n        variants: [\n          [0, 400],\n          [1, 400],\n        ],\n        fallbacks: ['fallback1'],\n      };\n      await act(() => mockControls.font.onChange(newFont));\n      const expectedFont = newFont;\n      delete expectedFont.id;\n      // updateSelectedElement should get called with the updated font object when the font gets updated,\n      // useRichText also calls updateSelectedElements with the element's content as a side effect. We want to check\n      // that the call for the font update matches. So just grab the first mock.call\n      const updatingFontFunction = mockUpdateSelectedElements.mock.calls[0][0];\n      expect(updatingFontFunction.properties(textElement)).toMatchObject(\n        expect.objectContaining({\n          font: expectedFont,\n        })\n      );\n    });\n\n    // eslint-disable-next-line jest/no-disabled-tests -- Can't figure out a good way to test this easily\n    it.skip('should select font weight', () => {\n      const { pushUpdate } = arrange([textElement]);\n      fireEvent.click(screen.getByRole('button', { name: 'Font weight' }));\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({ content: 'Hello world' });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: '<span style=\"font-weight: 300\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should select font size', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Font size' });\n\n      fireEvent.change(input, { target: { value: '32' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      expect(pushUpdate).toHaveBeenCalledWith({ fontSize: 32 }, true);\n    });\n\n    it('should not update font size if empty string is submitted', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Font size' });\n      fireEvent.change(input, { target: { value: '' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      expect(pushUpdate).not.toHaveBeenCalled();\n    });\n\n    it('should set the text bold when the key command is pressed', () => {\n      const { pushUpdate, container } = arrange([textElement]);\n\n      fireEvent.keyDown(container, {\n        key: 'b',\n        which: 66,\n        ctrlKey: true,\n      });\n\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({ content: 'Hello world' });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: '<span style=\"font-weight: 700\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should set the text underline when the key command is pressed', () => {\n      const { pushUpdate, container } = arrange([textElement]);\n\n      fireEvent.keyDown(container, {\n        key: 'u',\n        which: 85,\n        ctrlKey: true,\n      });\n\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({ content: 'Hello world' });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content:\n            '<span style=\"text-decoration: underline\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should set the text italics when the key command is pressed', () => {\n      const { pushUpdate, container } = arrange([textElement]);\n\n      fireEvent.keyDown(container, {\n        key: 'i',\n        which: 73,\n        ctrlKey: true,\n      });\n\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({ content: 'Hello world' });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: '<span style=\"font-style: italic\">Hello world</span>',\n        },\n        true\n      );\n    });\n  });\n\n  describe('TextStyleControls', () => {\n    it('should set lineHeight', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Line-height' });\n      fireEvent.change(input, { target: { value: '1.5' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      expect(pushUpdate).toHaveBeenCalledWith({ lineHeight: 1.5 }, true);\n    });\n\n    it('should clear line height if set to empty', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Line-height' });\n      fireEvent.change(input, { target: { value: '' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      expect(pushUpdate).toHaveBeenCalledWith({ lineHeight: '' }, true);\n    });\n\n    it('should set letterSpacing', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Letter-spacing' });\n      fireEvent.change(input, { target: { value: '150' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({ content: 'Hello world' });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: '<span style=\"letter-spacing: 1.5em\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should clear letterSpacing if set to empty', () => {\n      const { pushUpdate } = arrange([textElement]);\n      const input = screen.getByRole('textbox', { name: 'Letter-spacing' });\n      fireEvent.change(input, { target: { value: '' } });\n      fireEvent.keyDown(input, { key: 'Enter', which: 13 });\n      const updatingFunction = pushUpdate.mock.calls[0][0];\n      const resultOfUpdating = updatingFunction({\n        content: '<span style=\"letter-spacing: 1.5em\">Hello world</span>',\n      });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: 'Hello world',\n        },\n        true\n      );\n    });\n  });\n\n  describe('ColorControls', () => {\n    it('should render default black color', () => {\n      arrange([textElement]);\n      expect(mockControls['text.color'].value).toStrictEqual(\n        createSolid(0, 0, 0)\n      );\n    });\n\n    it('should render a color', () => {\n      const textWithColor = {\n        ...textElement,\n        content: '<span style=\"color: rgb(255, 0, 0)\">Hello world</span>',\n      };\n      arrange([textWithColor]);\n      expect(mockControls['text.color'].value).toStrictEqual(\n        createSolid(255, 0, 0)\n      );\n    });\n\n    it('should set color', () => {\n      const { pushUpdate } = arrange([textElement]);\n      act(() => mockControls['text.color'].onChange(createSolid(0, 255, 0)));\n      const updatingFunction = pushUpdate.mock.calls[1][0];\n      const resultOfUpdating = updatingFunction({\n        content: 'Hello world',\n      });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content: '<span style=\"color: #0f0\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should set gradient color', () => {\n      const { pushUpdate } = arrange([textElement]);\n      act(() =>\n        mockControls['text.color'].onChange({\n          type: 'linear',\n          stops: [\n            {\n              color: {\n                r: 0,\n                g: 0,\n                b: 0,\n              },\n              position: 0,\n            },\n            {\n              color: {\n                r: 1,\n                g: 1,\n                b: 1,\n              },\n              position: 1,\n            },\n          ],\n          rotation: 0.5,\n        })\n      );\n      const updatingFunction = pushUpdate.mock.calls[1][0];\n      const resultOfUpdating = updatingFunction({\n        content: 'Hello world',\n      });\n      expect(resultOfUpdating).toStrictEqual(\n        {\n          content:\n            '<span style=\"-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-image: linear-gradient(0.5turn, #000 0%, #010101 100%); background-clip: text\">Hello world</span>',\n        },\n        true\n      );\n    });\n\n    it('should detect color with multi selection, same values', () => {\n      const textWithColor1 = {\n        ...textElement,\n        content: '<span style=\"color: rgb(0, 0, 255)\">Hello world</span>',\n      };\n      const textWithColor2 = {\n        ...textElement,\n        content: '<span style=\"color: rgb(0, 0, 255)\">Hello world</span>',\n      };\n      arrange([textWithColor1, textWithColor2]);\n      expect(mockControls['text.color'].value).toStrictEqual(\n        createSolid(0, 0, 255)\n      );\n    });\n\n    it('should set color with multi selection, mixed values', () => {\n      const textWithColor1 = {\n        ...textElement,\n        content: '<span style=\"color: rgb(0, 0, 255)\">Hello world</span>',\n      };\n      const textWithColor2 = {\n        ...textElement,\n        content:\n          '<span style=\"background-image: linear-gradient(0.5turn, #111 0%, #eee 100%); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent\">Hello world</span>',\n      };\n      arrange([textWithColor1, textWithColor2]);\n      expect(mockControls['text.color'].value).toStrictEqual(MULTIPLE_VALUE);\n    });\n  });\n\n  describe('Mixed value multi-selection', () => {\n    it('should display Mixed value in case of mixed value multi-selection', () => {\n      const textElement1 = {\n        ...textElement,\n        font: {\n          family: 'Neu Font',\n          service: 'foo.bar.baz',\n          styles: ['italic', 'regular'],\n          weights: [400],\n          variants: [\n            [0, 400],\n            [1, 400],\n          ],\n          fallbacks: ['fallback1'],\n        },\n      };\n      const textElement2 = {\n        ...textElement,\n        font: {\n          name: 'ABeeZee',\n          value: 'ABeeZee',\n          service: 'foo.bar.baz',\n          weights: [400, 700],\n          styles: ['italic', 'regular'],\n          variants: [\n            [0, 400],\n            [1, 400],\n            [0, 700],\n          ],\n          fallbacks: ['serif'],\n        },\n        fontSize: 36,\n        lineHeight: 2.2,\n        content:\n          '<span style=\"font-weight: 700; letter-spacing: 0.2em\">Hello world</span>',\n      };\n\n      arrange([textElement1, textElement2]);\n\n      const letterSpacing = screen.getByRole('textbox', {\n        name: 'Letter-spacing',\n      });\n      expect(letterSpacing.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n\n      const lineHeight = screen.getByRole('textbox', { name: 'Line-height' });\n      expect(lineHeight.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n\n      const fontSize = screen.getByRole('textbox', { name: 'Font size' });\n      expect(fontSize.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n\n      expect(mockControls.font.placeholder).toStrictEqual(\n        MULTIPLE_DISPLAY_VALUE\n      );\n\n      const fontWeight = screen.getByRole('button', { name: 'Font weight' });\n      expect(fontWeight).toHaveTextContent(MULTIPLE_DISPLAY_VALUE);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/textStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useState, useEffect } from '@googleforcreators/react';\nimport { Text, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport getUpdatedSizeAndPosition from '../../../../utils/getUpdatedSizeAndPosition';\nimport { useHighlights, states } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport { useStory, useLayout } from '../../../../app';\nimport {\n  getPagesWithFailedContrast,\n  ACCESSIBILITY_COPY,\n} from '../../../checklist';\nimport { usePresubmitHandler } from '../../../form';\nimport PanelContent from '../../panel/shared/content';\nimport Panel from '../../panel/panel';\nimport Warning from '../warning';\nimport { noop } from '../../../../utils/noop';\nimport StyleControls from './style';\nimport ColorControls from './color';\nimport FontControls from './font';\nimport BackgroundColorControls from './backgroundColor';\nimport PaddingControls from './padding';\nimport PanelHeader from './panelHeader';\nimport StylePresets from './stylePresets';\n\nconst SubSection = styled.section`\n  border-top: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  display: flex;\n  flex-direction: column;\n`;\nconst SubHeading = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin: 14px 0;\n  font-weight: ${({ theme }) => theme.typography.weight.bold};\n`;\n\nfunction StylePanel(props) {\n  // use highlights to update panel styles\n  // but don't dynamically adjust the `isPersistable` prop on `SimplePanel`\n  // the textStyle panel automatically opens already whenever a text element is selected\n  // if we update this to only be when there's a highlight the functionality that is expected\n  // will be wrong.\n  const { dropdownHighlight, colorHighlight, resetHighlight, cancelHighlight } =\n    useHighlights((state) => ({\n      dropdownHighlight: state[states.Font],\n      colorHighlight: state[states.TextColor],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    }));\n\n  const [fontsFocused, setFontsFocused] = useState(false);\n  const [failedElementIds, setFailedElementIds] = useState([]);\n  const { selectedElements } = props;\n\n  // Update size and position if relevant values have changed.\n  usePresubmitHandler(getUpdatedSizeAndPosition, []);\n\n  const { currentPage } = useStory(({ state: { currentPage } }) => ({\n    currentPage,\n  }));\n  const pageSize = useLayout(({ state: { pageWidth, pageHeight } }) => ({\n    width: pageWidth,\n    height: pageHeight,\n  }));\n  const selectedElementIds = selectedElements.map(({ id }) => id);\n  const showContrastWarning = failedElementIds?.some(({ id }) =>\n    selectedElementIds.includes(id)\n  );\n\n  useEffect(() => {\n    getPagesWithFailedContrast([currentPage], pageSize)\n      .then((pages) => {\n        // getPagesWithFailedContrast returns an array of pages, since we only care\n        // about currentPage, we can grab the single page result.\n        const elementIds = pages[0]?.result;\n        setFailedElementIds(elementIds);\n      })\n      .catch(noop);\n  }, [currentPage, pageSize]);\n\n  return (\n    <Panel\n      name=\"textStyle\"\n      css={\n        (dropdownHighlight?.showEffect || colorHighlight?.showEffect) &&\n        styles.FLASH\n      }\n      onAnimationEnd={() => resetHighlight()}\n      isPersistable={false}\n    >\n      <PanelHeader {...props} />\n      <PanelContent>\n        <FontControls\n          {...props}\n          fontDropdownRef={(node) => {\n            if (\n              node &&\n              dropdownHighlight?.focus &&\n              dropdownHighlight?.showEffect\n            ) {\n              node.focus();\n              setFontsFocused(true);\n            }\n          }}\n          highlightStylesOverride={fontsFocused ? styles.OUTLINE : []}\n        />\n        <StyleControls {...props} />\n        <ColorControls\n          {...props}\n          textColorRef={(node) => {\n            if (node && colorHighlight?.focus && colorHighlight?.showEffect) {\n              node.addEventListener('keydown', cancelHighlight, { once: true });\n              node.focus();\n              setFontsFocused(false);\n            }\n          }}\n        />\n        {showContrastWarning && (\n          <Warning message={ACCESSIBILITY_COPY.lowContrast.textPanel} />\n        )}\n        <SubSection>\n          <SubHeading size={TextSize.Small}>\n            {__('Text Box', 'web-stories')}\n          </SubHeading>\n          <BackgroundColorControls {...props} />\n          <PaddingControls {...props} />\n        </SubSection>\n        <SubSection>\n          <StylePresets {...props} />\n        </SubSection>\n      </PanelContent>\n    </Panel>\n  );\n}\n\nStylePanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default StylePanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/useRichTextFormatting.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useMemo,\n  useCallback,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\nimport { isPatternEqual } from '@googleforcreators/patterns';\nimport { useGlobalKeyDownEffect } from '@googleforcreators/design-system';\nimport {\n  useRichText,\n  getHTMLFormatters,\n  getHTMLInfo,\n} from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas } from '../../../../app';\nimport { MULTIPLE_VALUE } from '../../../../constants';\n\n/**\n * Equality function for *primitives and color patterns* only.\n *\n * @param {any} a  First value to compare\n * @param {any} b  Second value to compare\n * @return {boolean} True if equal\n */\nfunction isEqual(a, b) {\n  // patterns are truthy objects with either a type or a color attribute.\n  // Note: `null` is a falsy object, that would cause an error if first\n  // check is removed.\n  const isAPattern = a && typeof a === 'object' && (a.type || a.color);\n  const isBPattern = b && typeof b === 'object' && (b.type || b.color);\n\n  return isAPattern && isBPattern ? isPatternEqual(a, b) : a === b;\n}\n\n/**\n * A function to gather the text info for multiple elements into a single\n * one.\n *\n * The text info object contains a number of values that can be either\n * primitives or a color object.\n *\n * If any two objects for the same key have different values, return\n * `MULTIPLE_VALUE`. Uses `isEqual` to determine this equality.`\n *\n * @param {Object} reduced  Currently reduced object from previous elements\n * - will be empty for first object\n * @param {Object} info  Info about current object\n * @return {Object} Combination of object as described.\n */\nfunction reduceWithMultiple(reduced, info) {\n  return Object.fromEntries(\n    Object.keys(info).map((key) => {\n      const wasMultiple = reduced[key] === MULTIPLE_VALUE;\n      const hadValue = typeof reduced[key] !== 'undefined';\n      const areDifferent = hadValue && !isEqual(reduced[key], info[key]);\n      if (wasMultiple || areDifferent) {\n        return [key, MULTIPLE_VALUE];\n      }\n      return [key, info[key]];\n    })\n  );\n}\n\nfunction useRichTextFormatting(selectedElements, pushUpdate) {\n  const { hasCurrentEditor, selectionInfo, selectionActions } = useRichText(\n    ({ state, actions }) => ({\n      hasCurrentEditor: state.hasCurrentEditor,\n      selectionInfo: state.selectionInfo,\n      selectionActions: actions.selectionActions,\n    })\n  );\n\n  const { clearEditing } = useCanvas(({ actions: { clearEditing } }) => ({\n    clearEditing,\n  }));\n\n  const textInfo = useMemo(() => {\n    if (hasCurrentEditor) {\n      return selectionInfo;\n    }\n\n    // loop over all text elements, find info for content and reduce to common value\n    // (setting MULTIPLE_VALUE appropriately)\n    return selectedElements\n      .map(({ content }) => content)\n      .map(getHTMLInfo)\n      .reduce(reduceWithMultiple, {});\n  }, [hasCurrentEditor, selectionInfo, selectedElements]);\n\n  const push = useCallback(\n    (updater, ...args) =>\n      pushUpdate(\n        ({ content }) => ({ content: updater(content, ...args) }),\n        true\n      ),\n    [pushUpdate]\n  );\n\n  const queuedPushRef = useRef(null);\n  const queuePush = useCallback(\n    (...args) => {\n      queuedPushRef.current = args;\n    },\n    [queuedPushRef]\n  );\n\n  // when selected elements update, run any queued pushes\n  useEffect(() => {\n    const pushArgs = queuedPushRef.current;\n    if (pushArgs) {\n      push(...pushArgs);\n      queuedPushRef.current = null;\n    }\n  }, [selectedElements, queuedPushRef, push]);\n\n  const handlers = useMemo(() => {\n    const htmlFormatters = getHTMLFormatters();\n\n    if (hasCurrentEditor) {\n      return {\n        // This particular function ignores the flag argument.\n        // Bold for inline selection has its own logic for\n        // determining proper resulting bold weight\n        handleClickBold: () => selectionActions.toggleBoldInSelection(),\n        // All these keep their arguments:\n        handleSelectFontWeight: selectionActions.setFontWeightInSelection,\n        handleClickItalic: selectionActions.toggleItalicInSelection,\n        handleClickUnderline: selectionActions.toggleUnderlineInSelection,\n        handleClickUppercase: selectionActions.toggleUppercaseInSelection,\n        handleSetLetterSpacing: selectionActions.setLetterSpacingInSelection,\n        handleSetColor: selectionActions.setColorInSelection,\n        handleSetGradientColor: selectionActions.setGradientColorInSelection,\n        // when editing, resetting font weight needs to save before resetting\n        handleResetFontWeight: async (weight) => {\n          // clear editing to save any pending updates\n          await clearEditing();\n          // queue push until selectedElements are saved and content is updated\n          queuePush(htmlFormatters.setFontWeight, weight);\n        },\n      };\n    }\n\n    return {\n      handleClickBold: (flag) => push(htmlFormatters.toggleBold, flag),\n      handleSelectFontWeight: (weight) =>\n        push(htmlFormatters.setFontWeight, weight),\n      handleClickItalic: (flag) => push(htmlFormatters.toggleItalic, flag),\n      handleClickUnderline: (flag) =>\n        push(htmlFormatters.toggleUnderline, flag),\n      handleClickUppercase: (flag) =>\n        push(htmlFormatters.toggleUppercase, flag),\n      handleSetLetterSpacing: (letterSpacing) =>\n        push(htmlFormatters.setLetterSpacing, letterSpacing),\n      handleSetColor: (color) => push(htmlFormatters.setColor, color),\n      handleSetGradientColor: (color) =>\n        push(htmlFormatters.setGradientColor, color),\n      handleResetFontWeight: (weight) =>\n        push(htmlFormatters.setFontWeight, weight),\n    };\n  }, [hasCurrentEditor, selectionActions, push, clearEditing, queuePush]);\n\n  const hasText = selectedElements.find(({ type }) => type === 'text');\n\n  useGlobalKeyDownEffect(\n    { key: ['mod+b', 'mod+u', 'mod+i'] },\n    ({ key }) => {\n      if (!hasText) {\n        return;\n      }\n      switch (key) {\n        case 'b':\n          handlers.handleClickBold();\n          break;\n        case 'i':\n          handlers.handleClickItalic();\n          break;\n        case 'u':\n          handlers.handleClickUnderline();\n          break;\n        default:\n          break;\n      }\n    },\n    [handlers, hasText]\n  );\n\n  return {\n    textInfo,\n    handlers,\n  };\n}\n\nexport default useRichTextFormatting;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/textStyle/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { HIDDEN_PADDING } from '../../../../constants';\n\n/**\n * Applies hidden padding to element padding and sets the hidden\n * padding flag to true. returns entire element.padding object\n * while retaining existing properties on it.\n *\n * @param {Object} element - story element.\n * @return {Object} element.padding with hidden padding properties applied\n */\nexport function applyHiddenPadding(element) {\n  return element?.padding?.hasHiddenPadding\n    ? element.padding\n    : {\n        ...element.padding,\n        hasHiddenPadding: true,\n        ...['vertical', 'horizontal'].reduce((padding, axis) => {\n          padding[axis] =\n            (element?.padding?.[axis] || 0) + HIDDEN_PADDING[axis];\n          return padding;\n        }, {}),\n      };\n}\n\n/**\n * Removes hidden padding on element padding and sets the hidden\n * padding flag to false. returns entire element.padding object\n * while retaining existing properties on it.\n *\n * @param {Object} element - story element.\n * @return {Object} element.padding with hidden padding properties removed\n */\nexport function removeHiddenPadding(element) {\n  return element?.padding?.hasHiddenPadding\n    ? {\n        ...element.padding,\n        hasHiddenPadding: false,\n        ...['vertical', 'horizontal'].reduce((padding, axis) => {\n          padding[axis] =\n            (element?.padding?.[axis] || 0) - HIDDEN_PADDING[axis];\n          return padding;\n        }, {}),\n      }\n    : element.padding;\n}\n\n/**\n * Takes an element and a padding axis and returns the\n * hidden padding or 0 depending on elements `hasHiddenPadding`\n * flag.\n *\n * @param {Object} element - story element\n * @param {'horizontal' | 'vertical'} axis - requested padding axis\n * @return {number} - hidden padding value\n */\nexport function getHiddenPadding(element = {}, axis = 'horizontal') {\n  return element?.padding?.hasHiddenPadding ? HIDDEN_PADDING[axis] : 0;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoAccessibility/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './videoAccessibility';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoAccessibility/karma/videoPoster.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { screen, waitFor } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../../karma';\n\ndescribe('Video Accessibility Panel', () => {\n  let fixture;\n  let vaPanel;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function focusOnTitle() {\n    await fixture.events.click(vaPanel.panelTitle);\n    await fixture.events.sleep(100);\n    await fixture.events.click(vaPanel.panelTitle);\n  }\n\n  describe('CUJ: Creator Can Manipulate an Image/Video on Canvas: Set different poster image', () => {\n    beforeEach(async () => {\n      const mediaItem = fixture.editor.library.media.item(5);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20); // item 5 is a video\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      vaPanel = fixture.editor.sidebar.designPanel.videoAccessibility;\n    });\n\n    it('should allow user to edit and reset poster image using mouse', async () => {\n      // Remember original poster image\n      const originalPoster = vaPanel.posterImage.src;\n\n      vaPanel.posterMenuButton.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.posterMenuButton).toBeTruthy();\n\n      // Open the menu\n      await fixture.events.click(vaPanel.posterMenuButton);\n      await fixture.snapshot('Menu open');\n\n      // And click on edit\n      await fixture.events.click(vaPanel.posterMenuEdit);\n\n      // Expect poster image to have updated ( See MediaUpload component in fixture.js )\n      expect(vaPanel.posterImage.src).toMatch(/^http.+\\/saturn.jpg$/);\n\n      // Now open menu and click reset\n      await fixture.events.click(vaPanel.posterMenuButton);\n      await fixture.events.click(vaPanel.posterMenuReset);\n\n      // Expect poster image to have been reset\n      expect(vaPanel.posterImage.src).toBe(originalPoster);\n    });\n\n    it('should allow user to edit and reset poster image using keyboard', async () => {\n      // Remember original poster image\n      const originalPoster = vaPanel.posterImage.src;\n\n      // Ensure focus right before the menu button.\n      vaPanel.panelTitle.scrollIntoView();\n      await focusOnTitle();\n\n      // Expect menu button to exist\n      expect(vaPanel.posterMenuButton).toBeTruthy();\n      await fixture.snapshot('Menu button visible');\n\n      // Tab to the menu button to focus on it.\n      await fixture.events.keyboard.press('tab');\n      expect(vaPanel.posterMenuButton).toHaveFocus();\n\n      await fixture.events.keyboard.press('Enter');\n      expect(vaPanel.posterMenuEdit).toBeDefined();\n      await fixture.snapshot('Menu open');\n\n      // The first option is already for editing.\n      expect(vaPanel.posterMenuEdit).toHaveFocus();\n      await fixture.events.keyboard.press('Enter');\n\n      // Expect poster image to have updated ( See MediaUpload component in fixture.js )\n      expect(vaPanel.posterImage.src).toMatch(/^http.+\\/saturn.jpg$/);\n\n      // Now open menu and click reset\n      await focusOnTitle();\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('Enter');\n      await fixture.events.keyboard.press('down');\n      await fixture.events.keyboard.press('down');\n      await fixture.events.keyboard.press('down');\n      expect(vaPanel.posterMenuReset).toHaveFocus();\n      await fixture.events.keyboard.press('Enter');\n\n      // Expect poster image to have been reset\n      expect(vaPanel.posterImage.src).toBe(originalPoster);\n    });\n\n    it('should allow user to hotlink and reset poster image using mouse', async () => {\n      // Remember original poster image\n      const originalPoster = vaPanel.posterImage.src;\n\n      vaPanel.posterMenuButton.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.posterMenuButton).toBeTruthy();\n\n      // Open the menu\n      await fixture.events.click(vaPanel.posterMenuButton);\n\n      // And click on edit\n      await fixture.events.click(vaPanel.posterMenuHotlink);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as video poster',\n      });\n      await fixture.events.click(input);\n      await fixture.events.keyboard.type(\n        'http://localhost:9876/__static__/ranger9.jpg'\n      );\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        if (!vaPanel?.posterImage?.src) {\n          throw new Error('image not available');\n        }\n        // Expect poster image to have updated ( See MediaUpload component in fixture.js )\n        expect(vaPanel.posterImage.src).toMatch(/^http.+\\/ranger9.jpg$/);\n      });\n\n      // Now open menu and click reset\n      await fixture.events.click(vaPanel.posterMenuButton);\n      await fixture.events.click(vaPanel.posterMenuReset);\n\n      // Expect poster image to have been reset\n      expect(vaPanel.posterImage.src).toBe(originalPoster);\n    });\n\n    it('should not be allowed to hotlink images with incorrect dimensions', async () => {\n      vaPanel.posterMenuButton.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.posterMenuButton).toBeTruthy();\n\n      // Open the menu\n      await fixture.events.click(vaPanel.posterMenuButton);\n\n      // And click on edit\n      await fixture.events.click(vaPanel.posterMenuHotlink);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as video poster',\n      });\n      await fixture.events.click(input);\n      const hotlinkUrl = 'http://localhost:9876/__static__/saturn.jpg';\n      await fixture.events.keyboard.type(hotlinkUrl);\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        const dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        if (\n          -1 ===\n          dialog.textContent.indexOf('do not match required image dimensions')\n        ) {\n          throw new Error('dimensions not available');\n        }\n        expect(dialog.textContent).toContain(\n          'do not match required image dimensions'\n        );\n      });\n    });\n\n    it('should not be allowed to hotlink images with invalid url', async () => {\n      vaPanel.posterMenuButton.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.posterMenuButton).toBeTruthy();\n\n      // Open the menu\n      await fixture.events.click(vaPanel.posterMenuButton);\n\n      // And click on edit\n      await fixture.events.click(vaPanel.posterMenuHotlink);\n\n      const input = fixture.screen.getByRole('textbox', { name: 'URL' });\n      const insertBtn = fixture.screen.getByRole('button', {\n        name: 'Use image as video poster',\n      });\n      await fixture.events.click(input);\n      const hotlinkUrl = 'invalid';\n      await fixture.events.keyboard.type(hotlinkUrl);\n\n      await fixture.events.click(insertBtn);\n      await waitFor(() => {\n        const dialog = screen.getByRole('dialog');\n        if (!dialog) {\n          throw new Error('dialog not ready');\n        }\n        expect(dialog.textContent).toContain('Invalid link');\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoAccessibility/test/videoAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport VideoAccessibility, { MIN_MAX } from '../videoAccessibility';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport ConfigContext from '../../../../../app/config/context';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../../../../constants';\n\nfunction MediaUpload({ render, onSelect }) {\n  const open = () => {\n    const image = { src: 'media1' };\n    onSelect(image);\n  };\n\n  return render(open);\n}\n\nfunction arrange(selectedElements) {\n  const configValue = {\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    MediaUpload,\n  };\n\n  const wrapper = ({ children }) => (\n    <ConfigContext.Provider value={configValue}>\n      {children}\n    </ConfigContext.Provider>\n  );\n\n  return renderPanel(VideoAccessibility, selectedElements, wrapper);\n}\n\ndescribe('Panels/VideoAccessibility', () => {\n  const defaultElement = {\n    type: 'video',\n    resource: { posterId: 0, poster: '', alt: '' },\n  };\n\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:videoAccessibility',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should trim video description to maximum allowed length if exceeding', () => {\n    arrange([defaultElement]);\n    const input = screen.getByRole('textbox', { name: 'Assistive text' });\n    expect(input.maxLength).toBe(MIN_MAX.ALT_TEXT.MAX);\n  });\n\n  it('should display Mixed as placeholder in case of mixed value multi-selection', () => {\n    arrange([\n      defaultElement,\n      {\n        resource: {\n          posterId: 0,\n          poster: '',\n          alt: 'Hello!',\n        },\n      },\n    ]);\n    const description = screen.getByRole('textbox', { name: 'Assistive text' });\n    expect(description.placeholder).toStrictEqual(MULTIPLE_DISPLAY_VALUE);\n    expect(description).toHaveValue('');\n  });\n\n  it('should simulate a click on <Poster />', () => {\n    const { pushUpdate } = arrange([defaultElement]);\n    const menuToggle = screen.getByRole('button', { name: 'Video poster' });\n    fireEvent.click(menuToggle);\n    const editMenuItem = screen.getByRole('menuitem', {\n      name: 'Upload a file',\n    });\n    fireEvent.click(editMenuItem);\n    expect(pushUpdate).toHaveBeenCalledOnce();\n    expect(pushUpdate).toHaveBeenCalledWith({ poster: 'media1' }, true);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoAccessibility/videoAccessibility.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Media, Row, TextArea } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { getCommonValue, useCommonObjectValue } from '../../shared';\nimport { useConfig } from '../../../../app/config';\nimport { states, useHighlights } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\nimport { MULTIPLE_VALUE, MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\n\nconst DEFAULT_RESOURCE = {\n  alt: null,\n  poster: null,\n  height: 0,\n  width: 0,\n};\n\nexport const MIN_MAX = {\n  ALT_TEXT: {\n    MAX: 1000,\n  },\n};\n\nconst StyledMedia = styled(Media)`\n  height: 114px;\n  width: 64px;\n`;\n\nconst InputsWrapper = styled.div`\n  align-self: flex-start;\n  margin-left: 16px;\n`;\n\nconst StyledText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin-bottom: 10px;\n`;\n\nfunction VideoAccessibilityPanel({ selectedElements, pushUpdate }) {\n  const resource = useCommonObjectValue(\n    selectedElements,\n    'resource',\n    DEFAULT_RESOURCE\n  );\n  const alt = getCommonValue(selectedElements, 'alt', resource.alt);\n  const { height, width } = resource;\n\n  const rawPoster = getCommonValue(selectedElements, 'poster');\n  const poster = getCommonValue(selectedElements, 'poster', resource.poster);\n  const {\n    allowedMimeTypes: { image: allowedImageMimeTypes },\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const options = [\n    hasUploadMediaAction && 'upload',\n    hasUploadMediaAction && 'edit',\n    'hotlink',\n    poster !== resource.poster && 'reset',\n  ].filter(Boolean);\n\n  const allowedImageFileTypes = useMemo(\n    () =>\n      allowedImageMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedImageMimeTypes]\n  );\n\n  const handleChangePoster = useCallback(\n    /**\n     * Handle video poster change.\n     *\n     * @param {import('@googleforcreators/media').Resource} [newPoster] The new image. Or null if reset.\n     */\n    (newPoster) => {\n      if (newPoster?.src === rawPoster) {\n        return;\n      }\n      pushUpdate({ poster: newPoster?.src }, true);\n    },\n    [pushUpdate, rawPoster]\n  );\n\n  const posterErrorMessage = useMemo(() => {\n    let message = __('No file types are currently supported.', 'web-stories');\n\n    if (allowedImageFileTypes.length) {\n      message = sprintf(\n        /* translators: %s: list of allowed file types. */\n        __('Please choose only %s as a poster.', 'web-stories'),\n        translateToExclusiveList(allowedImageFileTypes)\n      );\n    }\n\n    return message;\n  }, [allowedImageFileTypes]);\n\n  const {\n    highlightInput,\n    highlightMediaPicker,\n    resetHighlight,\n    cancelHighlight,\n  } = useHighlights((state) => ({\n    highlightInput: state[states.AssistiveText],\n    highlightMediaPicker: state[states.VideoA11yPoster],\n    resetHighlight: state.onFocusOut,\n    cancelHighlight: state.cancelEffect,\n  }));\n\n  let cropParams = null;\n  if (\n    height &&\n    height !== MULTIPLE_VALUE &&\n    width &&\n    width !== MULTIPLE_VALUE\n  ) {\n    cropParams = {\n      height,\n      width,\n    };\n  }\n\n  return (\n    <SimplePanel\n      css={(highlightInput || highlightMediaPicker) && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name=\"videoAccessibility\"\n      title={__('Accessibility', 'web-stories')}\n      isPersistable={!highlightInput && !highlightMediaPicker}\n    >\n      <Row>\n        <StyledMedia\n          ref={(node) => {\n            if (\n              node &&\n              highlightMediaPicker?.focus &&\n              highlightMediaPicker?.showEffect\n            ) {\n              node.focus();\n            }\n          }}\n          value={poster}\n          cropParams={cropParams}\n          onChange={handleChangePoster}\n          onChangeErrorText={posterErrorMessage}\n          title={__('Select as video poster', 'web-stories')}\n          hotlinkTitle={__('Use external image as video poster', 'web-stories')}\n          hotlinkInsertText={__('Use image as video poster', 'web-stories')}\n          hotlinkInsertingText={__(\n            'Using image as video poster',\n            'web-stories'\n          )}\n          buttonInsertText={__('Set as video poster', 'web-stories')}\n          alt={__('Preview poster image', 'web-stories')}\n          type={allowedImageMimeTypes}\n          ariaLabel={__('Video poster', 'web-stories')}\n          menuOptions={options}\n          imgProps={cropParams}\n          canUpload={options.length !== 0}\n        />\n        <InputsWrapper>\n          <StyledText size={TextSize.Small}>\n            {__('Add a brief description of the video.', 'web-stories')}\n          </StyledText>\n          <TextArea\n            ref={(node) => {\n              if (node && highlightInput?.focus && highlightInput?.showEffect) {\n                node.addEventListener('keydown', cancelHighlight, {\n                  once: true,\n                });\n                node.focus();\n              }\n            }}\n            placeholder={alt === MULTIPLE_VALUE ? MULTIPLE_DISPLAY_VALUE : ''}\n            value={alt || ''}\n            onChange={(evt) =>\n              pushUpdate(\n                {\n                  alt: evt?.target?.value?.trim() || null,\n                },\n                true\n              )\n            }\n            aria-label={__('Assistive text', 'web-stories')}\n            maxLength={MIN_MAX.ALT_TEXT.MAX}\n            rows={2}\n            isIndeterminate={alt === MULTIPLE_VALUE}\n          />\n        </InputsWrapper>\n      </Row>\n    </SimplePanel>\n  );\n}\n\nVideoAccessibilityPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default VideoAccessibilityPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoOptions/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './videoOptions';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoOptions/karma/videoOptions.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../../app/story';\nimport { Fixture } from '../../../../../karma';\n\ndescribe('Video Options Panel', () => {\n  let fixture;\n  let vaPanel;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    fixture.setFlags({ videoVolume: true });\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function focusOnTitle() {\n    await fixture.events.click(vaPanel.panelTitle);\n    await fixture.events.sleep(100);\n    await fixture.events.click(vaPanel.panelTitle);\n  }\n\n  describe('CUJ: Creator Can Manipulate an Video on Canvas: Set different video options', () => {\n    beforeEach(async () => {\n      const mediaItem = fixture.editor.library.media.item(5);\n      await fixture.events.mouse.clickOn(mediaItem, 20, 20); // item 5 is a video\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      vaPanel = fixture.editor.sidebar.designPanel.videoOptions;\n    });\n\n    it('should allow user to edit volume using mouse', async () => {\n      vaPanel.volume.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.volume).toBeTruthy();\n\n      await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n        moveRel(vaPanel.volume, 1, 1),\n        down(),\n        moveBy(10, 0, { steps: 2 }),\n        up(),\n      ]);\n      // Click just below the slider to exit edit mode\n      await fixture.events.mouse.clickOn(vaPanel.volume, 0, 20);\n\n      await fixture.events.sleep(300);\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElements[0].volume).toBe(0.1);\n    });\n\n    it('should allow user to edit volume using keyboard', async () => {\n      // Ensure focus right before the menu button.\n      vaPanel.panelTitle.scrollIntoView();\n      await focusOnTitle();\n\n      // Expect menu button to exist\n      vaPanel.volume.scrollIntoView();\n\n      // Expect menu button to exist\n      expect(vaPanel.volume).toBeTruthy();\n\n      // Tab to the menu button to focus on it.\n      await fixture.events.keyboard.press('tab');\n      await fixture.events.keyboard.press('tab');\n      expect(vaPanel.volume).toHaveFocus();\n      await fixture.events.keyboard.press('left');\n      await fixture.events.keyboard.press('left');\n      await fixture.events.keyboard.press('left');\n\n      await fixture.events.sleep(300);\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElements[0].volume).toBe(0.7);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoOptions/test/videoOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { useFeature } from 'flagged';\n/**\n * Internal dependencies\n */\nimport VideoOptions from '../videoOptions';\nimport { renderPanel } from '../../../shared/test/_utils';\nimport { useLocalMedia } from '../../../../../app/media';\n\njest.mock('flagged');\n\njest.mock('../../../../../app/media');\n\njest.mock('../../../../../app/config', () => ({\n  useConfig: jest.fn(() => ({\n    capabilities: { hasUploadMediaAction: true },\n  })),\n}));\njest.mock('../../../../../app/currentUser', () => ({\n  useCurrentUser: jest.fn(() => ({\n    state: {\n      currentUser: {\n        mediaOptimization: true,\n      },\n    },\n  })),\n}));\n\ndescribe('Panels/VideoOptions', () => {\n  const defaultElement = {\n    id: 123,\n    type: 'video',\n    volume: 1,\n    resource: { posterId: 0, poster: '', alt: '', isMuted: false },\n  };\n  function arrange(...args) {\n    return renderPanel(VideoOptions, ...args);\n  }\n\n  beforeAll(() => {\n    useFeature.mockImplementation(() => true);\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:videoOptions',\n      JSON.stringify({ isCollapsed: false })\n    );\n\n    useLocalMedia.mockReturnValue({\n      isElementTrimming: jest.fn(),\n      isNewResourceMuting: jest.fn(),\n      canTranscodeResource: jest.fn(),\n    });\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render <VideoOptions /> panel', () => {\n    arrange([defaultElement]);\n    const panel = screen.getByText('Video Settings');\n    expect(panel).toBeInTheDocument();\n  });\n\n  it('should render volume input', () => {\n    arrange([defaultElement]);\n    expect(screen.getByLabelText('Volume')).toBeInTheDocument();\n  });\n\n  it('should not render volume input if video is muted', () => {\n    arrange([\n      {\n        type: 'video',\n        volume: 1,\n        resource: { posterId: 0, poster: '', alt: '', isMuted: true },\n      },\n    ]);\n    expect(screen.queryByLabelText('Volume')).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoOptions/videoOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Text,\n  CircularProgress,\n  TextSize,\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  useLiveRegion,\n  Slider,\n} from '@googleforcreators/design-system';\nimport { useEffect, useInitializedValue } from '@googleforcreators/react';\nimport { useFeature } from 'flagged';\nimport { v4 as uuidv4 } from 'uuid';\n/**\n * Internal dependencies\n */\nimport useVideoElementTranscoding from '../../../../app/media/utils/useVideoElementTranscoding';\nimport { Row as DefaultRow } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { getCommonValue } from '../../shared';\nimport LoopPanelContent from '../../shared/media/loopPanelContent';\n\nconst Row = styled(DefaultRow)`\n  margin-top: 2px;\n`;\n\nconst StyledButton = styled(Button)`\n  padding: 12px 8px;\n`;\n\nconst TrimButton = styled(StyledButton)`\n  margin-left: 20px;\n`;\n\nconst TrimWrapper = styled.div`\n  position: relative;\n  display: flex;\n`;\n\nconst Spinner = styled.div`\n  margin-left: 4px;\n  margin-top: 4px;\n`;\nconst StyledSlider = styled(Slider)`\n  width: 100%;\n`;\nconst VolumeWrapper = styled.div`\n  margin-bottom: 20px;\n`;\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst Processing = () => {\n  return (\n    <Spinner>\n      <CircularProgress size={24} />\n    </Spinner>\n  );\n};\n\nfunction VideoOptionsPanel({ selectedElements, pushUpdate }) {\n  const resource = getCommonValue(selectedElements, 'resource');\n  const elementId = getCommonValue(selectedElements, 'id');\n  const loop = getCommonValue(selectedElements, 'loop');\n  const volume = getCommonValue(selectedElements, 'volume', 1);\n  const isSingleElement = selectedElements.length === 1;\n  const enableVideoVolume = useFeature('videoVolume');\n  const showVolumeControl =\n    enableVideoVolume && isSingleElement && !resource?.isMuted;\n\n  const {\n    state: { canTrim, canMute, isTrimming, isMuting, isDisabled },\n    actions: { handleMute, handleTrim },\n  } = useVideoElementTranscoding({ resource, elementId, isSingleElement });\n\n  const muteButtonText = isMuting\n    ? __('Removing audio…', 'web-stories')\n    : __('Remove audio', 'web-stories');\n\n  const trimButtonText = isTrimming\n    ? __('Trimming…', 'web-stories')\n    : __('Trim', 'web-stories');\n\n  const speak = useLiveRegion();\n\n  useEffect(() => {\n    if (isMuting) {\n      speak(muteButtonText);\n    }\n  }, [isMuting, muteButtonText, speak]);\n\n  useEffect(() => {\n    if (isTrimming) {\n      speak(trimButtonText);\n    }\n  }, [isTrimming, trimButtonText, speak]);\n\n  const onChange = (evt) => pushUpdate({ loop: evt.target.checked }, true);\n  const onChangeVolume = (value) => {\n    const newVolume = Math.max(0.1, value / 100);\n    pushUpdate({ volume: newVolume }, true);\n  };\n\n  const slideId = useInitializedValue(() => `slide-${uuidv4()}`);\n\n  return (\n    <SimplePanel\n      name=\"videoOptions\"\n      title={__('Video Settings', 'web-stories')}\n    >\n      <Row spaceBetween={false}>\n        <LoopPanelContent loop={loop} onChange={onChange} />\n        {canTrim && (\n          <TrimWrapper>\n            <TrimButton\n              disabled={isDisabled}\n              variant={ButtonVariant.Rectangle}\n              type={ButtonType.Secondary}\n              size={ButtonSize.Small}\n              onClick={handleTrim}\n            >\n              {trimButtonText}\n            </TrimButton>\n            {isTrimming && <Processing />}\n          </TrimWrapper>\n        )}\n      </Row>\n      {showVolumeControl && (\n        <VolumeWrapper>\n          <Text.Label size={TextSize.Small} htmlFor={slideId}>\n            {__('Volume', 'web-stories')}\n          </Text.Label>\n          <StyledSlider\n            value={Math.round(volume * 100)}\n            handleChange={onChangeVolume}\n            minorStep={5}\n            majorStep={10}\n            min={0}\n            max={100}\n            id={slideId}\n            aria-label={__('Volume', 'web-stories')}\n          />\n        </VolumeWrapper>\n      )}\n      {canMute && (\n        <>\n          <Row spaceBetween={false}>\n            <StyledButton\n              disabled={isDisabled}\n              variant={ButtonVariant.Rectangle}\n              type={ButtonType.Secondary}\n              size={ButtonSize.Small}\n              onClick={handleMute}\n            >\n              {muteButtonText}\n            </StyledButton>\n            {isMuting && <Processing />}\n          </Row>\n          <Row>\n            <HelperText>\n              {__(\n                'Removing the audio from this video will upload a new muted version of it to the media library. This might take a couple of seconds.',\n                'web-stories'\n              )}\n            </HelperText>\n          </Row>\n        </>\n      )}\n    </SimplePanel>\n  );\n}\n\nVideoOptionsPanel.propTypes = {\n  selectedElements: PropTypes.array.isRequired,\n  pushUpdate: PropTypes.func.isRequired,\n};\n\nexport default VideoOptionsPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoSegment/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './videoSegment';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/videoSegment/videoSegment.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Text,\n  Button,\n  TextSize,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  useSnackbar,\n  Slider,\n} from '@googleforcreators/design-system';\nimport { useCallback, useState, useEffect } from '@googleforcreators/react';\nimport { createNewElement, createPage } from '@googleforcreators/elements';\nimport { useFeature } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport { Row as DefaultRow } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { getCommonValue } from '../../shared';\nimport { useLocalMedia } from '../../../../app/media';\nimport { useStory } from '../../../../app/story';\nimport getElementProperties from '../../../canvas/utils/getElementProperties';\n\nconst Row = styled(DefaultRow)`\n  margin-top: 2px;\n`;\n\nconst StyledButton = styled(Button)`\n  padding: 12px 8px;\n`;\n\nconst SliderWrapper = styled.div`\n  flex: 1;\n  margin-right: 20px;\n`;\n\nconst StyledSlider = styled(Slider)`\n  width: 100%;\n`;\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.XSmall,\n})`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nfunction VideoSegmentPanel({ pushUpdate, selectedElements }) {\n  const MIN_SEGMENT_LENGTH = 10;\n  const MAX_SEGMENT_LENGTH = 60;\n  const resource = getCommonValue(selectedElements, 'resource');\n  const elementId = getCommonValue(selectedElements, 'id');\n  const enableSegmentVideo = useFeature('segmentVideo');\n\n  const onChangeSegmentTime = (value) => {\n    pushUpdate({ segmentTime: value }, true);\n  };\n\n  const segmentTime = getCommonValue(selectedElements, 'segmentTime', 20);\n\n  const { pageIds, currentPageId, deleteElementById, addElementsAcrossPages } =\n    useStory(\n      ({\n        state: { pages, currentPageId },\n        actions: { deleteElementById, addElementsAcrossPages },\n      }) => ({\n        pageIds: pages.map(({ id }) => id),\n        currentPageId,\n        deleteElementById,\n        addElementsAcrossPages,\n      })\n    );\n\n  const { isBatchUploading, segmentVideo } = useLocalMedia(\n    ({ state: { isBatchUploading }, actions: { segmentVideo } }) => ({\n      segmentVideo,\n      isBatchUploading,\n    })\n  );\n\n  // @todo state needs to persist across tabs\n  // https://github.com/GoogleForCreators/web-stories-wp/issues/12463\n  const [batchId, setBatchId] = useState();\n  const [isSegmenting, setIsSegmenting] = useState();\n  const [segmentedFiles, setSegmentedFiles] = useState([]);\n  const [segmentElementId, setSegmentElementId] = useState();\n  const [segmentPageId, setSegmentPageId] = useState();\n\n  const isUploading = batchId && isBatchUploading(batchId);\n\n  const showSnackbar = useSnackbar(({ showSnackbar }) => showSnackbar);\n\n  const segmentButtonText = isSegmenting\n    ? __('Segmenting…', 'web-stories')\n    : __('Segment', 'web-stories');\n\n  const addElementsToPages = useCallback(() => {\n    if (!segmentPageId || !segmentElementId) {\n      return;\n    }\n\n    showSnackbar({\n      message: __('Inserting video segments', 'web-stories'),\n      dismissible: false,\n    });\n\n    const elements = segmentedFiles.map((segmentedResource) =>\n      createNewElement(\n        segmentedResource.type,\n        getElementProperties(segmentedResource.type, {\n          resource: segmentedResource,\n        })\n      )\n    );\n\n    const page = createPage();\n    const position = pageIds.indexOf(segmentPageId);\n\n    addElementsAcrossPages({\n      elements,\n      page,\n      position,\n    });\n\n    deleteElementById({ elementId: segmentElementId });\n\n    setSegmentedFiles([]);\n    setIsSegmenting(false);\n    setBatchId(null);\n  }, [\n    segmentPageId,\n    segmentElementId,\n    showSnackbar,\n    segmentedFiles,\n    pageIds,\n    addElementsAcrossPages,\n    deleteElementById,\n  ]);\n\n  const onClick = useCallback(async () => {\n    setIsSegmenting(true);\n    setSegmentElementId(elementId);\n    setSegmentPageId(currentPageId);\n\n    showSnackbar({\n      message: __('Video segmentation in progress', 'web-stories'),\n      dismissible: true,\n    });\n\n    const onUploadSuccess = ({ resource: newResource, batchPosition }) => {\n      setSegmentedFiles((f) => {\n        f[batchPosition] = newResource;\n        return f;\n      });\n    };\n\n    const batchId_ = await segmentVideo(\n      { resource, segmentTime },\n      onUploadSuccess\n    );\n\n    if (!batchId_) {\n      showSnackbar({\n        message: __('Segmentation failed', 'web-stories'),\n        dismissible: true,\n      });\n\n      setIsSegmenting(false);\n\n      return;\n    }\n\n    setBatchId(batchId_);\n  }, [\n    elementId,\n    currentPageId,\n    showSnackbar,\n    segmentVideo,\n    segmentTime,\n    resource,\n  ]);\n\n  useEffect(() => {\n    if (!isUploading && segmentedFiles.length >= 1) {\n      addElementsToPages();\n    }\n  }, [isUploading, segmentedFiles, addElementsToPages]);\n\n  if (!enableSegmentVideo || resource.length <= MIN_SEGMENT_LENGTH) {\n    return null;\n  }\n\n  return (\n    <SimplePanel\n      name=\"videoOptions\"\n      title={__('Video Segment Settings', 'web-stories')}\n    >\n      <Row spaceBetween>\n        <SliderWrapper>\n          <StyledSlider\n            value={segmentTime}\n            handleChange={onChangeSegmentTime}\n            minorStep={1}\n            majorStep={5}\n            min={MIN_SEGMENT_LENGTH}\n            max={Math.max(\n              MIN_SEGMENT_LENGTH,\n              Math.min(resource.length, MAX_SEGMENT_LENGTH)\n            )}\n            aria-label={__('Segment length', 'web-stories')}\n            suffix={'s'}\n          />\n        </SliderWrapper>\n        <StyledButton\n          disabled={isSegmenting}\n          variant={ButtonVariant.Rectangle}\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          onClick={onClick}\n        >\n          {segmentButtonText}\n        </StyledButton>\n      </Row>\n      <Row>\n        <HelperText>\n          {__(\n            'Segmenting your video will split the video across multiple pages',\n            'web-stories'\n          )}\n        </HelperText>\n      </Row>\n    </SimplePanel>\n  );\n}\n\nVideoSegmentPanel.propTypes = {\n  pushUpdate: PropTypes.func.isRequired,\n  selectedElements: PropTypes.array.isRequired,\n};\n\nexport default VideoSegmentPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/warning/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './warning';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/design/warning/warning.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useEffect } from '@googleforcreators/react';\nimport {\n  Text,\n  Icons,\n  useLiveRegion,\n  TextSize,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { ACCESSIBILITY_COPY } from '../../../checklist/constants';\n\nconst WarningContainer = styled.div`\n  display: flex;\n  gap: 8px;\n  margin: 14px auto;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultHover};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  padding: 8px;\n`;\n\nconst WarningIcon = styled(Icons.ExclamationTriangle)`\n  width: 32px;\n  height: 100%;\n  color: ${({ theme }) => theme.colors.status.warning};\n`;\n\nconst Message = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  max-width: calc(100% - 40px);\n`;\n\nfunction Warning({ message }) {\n  const speak = useLiveRegion('assertive');\n\n  useEffect(() => {\n    speak(message);\n  }, [message, speak]);\n  return (\n    <WarningContainer data-testid={'warningContainer'}>\n      <WarningIcon title={ACCESSIBILITY_COPY.lowContrast.warningIcon} />\n      <Message>{message}</Message>\n    </WarningContainer>\n  );\n}\n\nWarning.propTypes = {\n  message: PropTypes.string,\n};\n\nexport default Warning;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/backgroundAudio/backgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport { useConfig } from '../../../../app';\nimport { Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport BackgroundAudioPanelContent from '../../shared/media/backgroundAudioPanelContent';\n\nconst HelperText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nfunction BackgroundAudioPanel({ nameOverride }) {\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n\n  const { backgroundAudio, updateStory } = useStory(\n    ({\n      state: {\n        story: { backgroundAudio },\n      },\n      actions: { updateStory },\n    }) => ({ backgroundAudio, updateStory })\n  );\n\n  const updateBackgroundAudio = useCallback(\n    (updatedBackgroundAudio) => {\n      updateStory({\n        properties: { backgroundAudio: updatedBackgroundAudio },\n      });\n    },\n    [updateStory]\n  );\n\n  if (!backgroundAudio && !hasUploadMediaAction) {\n    return null;\n  }\n\n  return (\n    <SimplePanel\n      name={nameOverride || 'backgroundAudio'}\n      title={__('Background Audio', 'web-stories')}\n      collapsedByDefault\n    >\n      <Row>\n        <HelperText>\n          {__(\n            'Select an audio file that plays throughout the story.',\n            'web-stories'\n          )}\n        </HelperText>\n      </Row>\n      <Row>\n        <BackgroundAudioPanelContent\n          backgroundAudio={backgroundAudio}\n          updateBackgroundAudio={updateBackgroundAudio}\n        />\n      </Row>\n    </SimplePanel>\n  );\n}\n\nexport default BackgroundAudioPanel;\n\nBackgroundAudioPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/backgroundAudio/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './backgroundAudio';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/backgroundAudio/test/backgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport ConfigContext from '../../../../../app/config/context';\nimport StoryContext from '../../../../../app/story/context';\nimport BackgroundAudioPanel from '../backgroundAudio';\n\nfunction MediaUpload({ render }) {\n  const open = jest.fn();\n  return render(open);\n}\n\nfunction arrange({ backgroundAudio, hasUploadMediaAction = true } = {}) {\n  const updateStory = jest.fn();\n\n  const configValue = {\n    capabilities: {\n      hasUploadMediaAction,\n    },\n    allowedMimeTypes: {\n      audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n      image: [\n        'image/png',\n        'image/jpeg',\n        'image/jpg',\n        'image/gif',\n        'image/webp',\n      ],\n      caption: ['text/vtt'],\n      vector: [],\n      video: ['video/mp4', 'video/webm'],\n    },\n    MediaUpload,\n  };\n\n  const storyContextValue = {\n    state: {\n      story: {\n        backgroundAudio,\n      },\n    },\n    actions: { updateStory },\n  };\n\n  return renderWithTheme(\n    <ConfigContext.Provider value={configValue}>\n      <StoryContext.Provider value={storyContextValue}>\n        <BackgroundAudioPanel />\n      </StoryContext.Provider>\n    </ConfigContext.Provider>\n  );\n}\n\ndescribe('BackgroundAudioPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:backgroundAudio',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render nothing if lacking upload capabilities', () => {\n    arrange({ hasUploadMediaAction: false });\n    expect(\n      screen.queryByRole('button', {\n        name: 'Upload an audio file',\n      })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should render button to upload audio', () => {\n    arrange();\n    expect(\n      screen.getByRole('button', {\n        name: 'Upload an audio file',\n      })\n    ).toBeInTheDocument();\n  });\n\n  it('should render button to play and delete audio', () => {\n    arrange({\n      backgroundAudio: {\n        resource: {\n          src: 'https://example.com/audio.mp3',\n          id: 123,\n          mimeType: 'audio/mpeg',\n        },\n      },\n    });\n    expect(\n      screen.getByRole('button', {\n        name: 'Remove file',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', {\n        name: 'Play',\n      })\n    ).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/excerpt/excerpt.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport { Row, TextArea } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { useHighlights, states } from '../../../../app/highlights';\nimport styles from '../../../../app/highlights/styles';\n\n// Margin -4px is making up for extra margin added by rows.\nconst StyledText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  margin-top: -4px;\n`;\n\nexport const EXCERPT_MAX_LENGTH = 200;\n\nfunction ExcerptPanel({ nameOverride }) {\n  const { excerpt, updateStory } = useStory(\n    ({\n      state: {\n        story: { excerpt = '' },\n      },\n      actions: { updateStory },\n    }) => ({ excerpt, updateStory })\n  );\n\n  const handleTextChange = useCallback(\n    (evt) => {\n      updateStory({\n        properties: { excerpt: evt.target.value },\n      });\n    },\n    [updateStory]\n  );\n\n  const { highlight, resetHighlight, cancelHighlight } = useHighlights(\n    (state) => ({\n      highlight: state[states.Excerpt],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  return (\n    <SimplePanel\n      css={highlight?.showEffect && styles.FLASH}\n      onAnimationEnd={() => resetHighlight()}\n      name={nameOverride || 'excerpt'}\n      title={__('Story Description', 'web-stories')}\n      collapsedByDefault={false}\n      isPersistable={!highlight}\n    >\n      <Row>\n        <TextArea\n          ref={(node) => {\n            if (node && highlight?.focus && highlight?.showEffect) {\n              node.addEventListener('keydown', cancelHighlight, { once: true });\n              node.focus();\n            }\n          }}\n          value={excerpt}\n          onChange={handleTextChange}\n          placeholder={__('Write a description of the story', 'web-stories')}\n          aria-label={__('Story Description', 'web-stories')}\n          maxLength={EXCERPT_MAX_LENGTH}\n          showCount\n          rows={4}\n          css={highlight?.showEffect && styles.OUTLINE}\n        />\n      </Row>\n      <Row>\n        <StyledText size={TextSize.XSmall}>\n          {__(\n            'Stories with a description tend to do better on search and have a wider reach',\n            'web-stories'\n          )}\n        </StyledText>\n      </Row>\n    </SimplePanel>\n  );\n}\n\nexport default ExcerptPanel;\n\nExcerptPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/excerpt/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default, EXCERPT_MAX_LENGTH } from './excerpt';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/excerpt/test/excerpt.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../../app/story/context';\nimport ExcerptPanel, { EXCERPT_MAX_LENGTH } from '../excerpt';\n\nfunction arrange() {\n  const updateStory = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      story: {\n        excerpt: 'This is the story excerpt.',\n      },\n    },\n    actions: { updateStory },\n  };\n\n  return renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <ExcerptPanel />\n    </StoryContext.Provider>\n  );\n}\n\ndescribe('ExcerptPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:excerpt',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render Excerpt Panel', () => {\n    arrange();\n    const element = screen.getByRole('button', { name: 'Story Description' });\n    expect(element).toBeInTheDocument();\n  });\n\n  it('should display textbox', () => {\n    arrange();\n    const input = screen.getByRole('textbox', { name: 'Story Description' });\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should respect excerpt character limit', () => {\n    arrange();\n    const input = screen.getByRole('textbox', { name: 'Story Description' });\n\n    expect(input.maxLength).toBe(EXCERPT_MAX_LENGTH);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as ExcerptPanel } from './excerpt';\nexport { default as PageAdvancementPanel } from './pageAdvancement';\nexport { default as SlugPanel } from './slug';\nexport { default as BackgroundAudioPanel } from './backgroundAudio';\nexport { default as TaxonomiesPanel } from './taxonomies';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/pageAdvancement/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './pageAdvancement';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/pageAdvancement/pageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport { useConfig } from '../../../../app/config';\nimport GeneralPageAdvancementPanel from '../../shared/generalPageAdvancement';\n\nfunction PageAdvancementPanel({ nameOverride }) {\n  const { globalPageDuration } = useConfig();\n  const { autoAdvance, defaultPageDuration, updateStory } = useStory(\n    ({\n      state: {\n        story: { autoAdvance, defaultPageDuration },\n      },\n      actions: { updateStory },\n    }) => ({\n      autoAdvance,\n      defaultPageDuration: defaultPageDuration || globalPageDuration,\n      updateStory,\n    })\n  );\n\n  const onUpdate = useCallback(\n    (newProps) => {\n      // Rename \"pageDuration\" property to \"defaultPageDuration\"\n      const { pageDuration, ...rest } = newProps;\n      const properties = { ...rest, defaultPageDuration: pageDuration };\n      updateStory({ properties });\n    },\n    [updateStory]\n  );\n\n  return (\n    <GeneralPageAdvancementPanel\n      panelName={nameOverride || 'pageAdvancement'}\n      collapsedByDefault={false}\n      onUpdate={onUpdate}\n      autoAdvance={autoAdvance}\n      pageDuration={defaultPageDuration}\n    >\n      {__(\n        'Control whether a story auto-advances between pages, or whether the reader has to manually tap to advance.',\n        'web-stories'\n      )}\n    </GeneralPageAdvancementPanel>\n  );\n}\n\nexport default PageAdvancementPanel;\n\nPageAdvancementPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/pageAdvancement/test/pageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../../app/story/context';\nimport PageAdvancementPanel from '../pageAdvancement';\n\nfunction arrange(configs = {}) {\n  const updateStory = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      story: {\n        autoAdvance: false,\n        defaultPageDuration: 7,\n        ...configs,\n      },\n    },\n    actions: { updateStory },\n  };\n\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <PageAdvancementPanel />\n    </StoryContext.Provider>\n  );\n\n  return {\n    updateStory,\n  };\n}\n\ndescribe('PageAdvancementPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:pageAdvancement',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render Page Advancement Panel with default settings if undefined in story', () => {\n    arrange({ autoAdvance: undefined, defaultPageDuration: undefined });\n    const durationInput = screen.getByLabelText(\n      'Default page duration in seconds'\n    );\n    expect(durationInput).toHaveValue('7 seconds');\n  });\n\n  it('should render Page Advancement Panel', () => {\n    const { updateStory } = arrange();\n    const element = screen.getByRole('button', { name: 'Page Advancement' });\n    expect(element).toBeInTheDocument();\n    fireEvent.click(screen.getByRole('radio', { name: 'Auto' }));\n    expect(updateStory).toHaveBeenCalledWith({\n      properties: {\n        autoAdvance: true,\n      },\n    });\n  });\n\n  it('should set Page Duration', async () => {\n    const { updateStory } = arrange({\n      autoAdvance: true,\n    });\n    const element = screen.getByRole('button', { name: 'Page Advancement' });\n    expect(element).toBeInTheDocument();\n\n    const input = screen.getByRole('textbox', {\n      name: 'Default page duration in seconds',\n    });\n\n    fireEvent.change(input, {\n      target: { value: '0' },\n    });\n    fireEvent.blur(input);\n\n    await waitFor(() =>\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          defaultPageDuration: 1,\n        },\n      })\n    );\n\n    expect(updateStory).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, {\n      // Note: With PR#13339, if value exceeds max, it will remove leading character to get value into the valid range.\n      target: { value: '21' },\n    });\n    fireEvent.blur(input);\n\n    await waitFor(() =>\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          defaultPageDuration: 1,\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/slug/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './slug';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/slug/slug.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Input, Link, TextSize } from '@googleforcreators/design-system';\nimport { safeDecodeURIComponent } from '@googleforcreators/url';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../app/story';\nimport cleanForSlug from '../../../../utils/cleanForSlug';\nimport { Row } from '../../../form';\nimport { SimplePanel } from '../../panel';\nimport { inputContainerStyleOverride } from '../../shared/styles';\n\nconst inRange = (value, { MIN, MAX }) => value >= MIN && value <= MAX;\n\nexport const MIN_MAX = {\n  PERMALINK: {\n    MIN: 1,\n    MAX: 200,\n  },\n};\n\nconst PermalinkRow = styled(Row)`\n  margin-bottom: 12px;\n\n  input {\n    color: ${({ theme }) => theme.colors.fg.tertiary};\n\n    :active,\n    :focus,\n    :focus-visible {\n      color: ${({ theme }) => theme.colors.fg.primary};\n    }\n  }\n`;\n\nconst LinkContainer = styled.div`\n  margin-bottom: 16px;\n`;\n\nfunction SlugPanel({ nameOverride }) {\n  const {\n    slug: savedSlug,\n    link,\n    permalinkConfig,\n    updateStory,\n  } = useStory(\n    ({\n      state: {\n        story: { slug = '', link, permalinkConfig },\n      },\n      actions: { updateStory },\n    }) => ({\n      slug: safeDecodeURIComponent(slug),\n      link,\n      permalinkConfig,\n      updateStory,\n    })\n  );\n  const [slug, setSlug] = useState(savedSlug);\n\n  useEffect(() => {\n    /* Update shown slug when slug updates externally */\n    setSlug(savedSlug);\n  }, [savedSlug]);\n\n  const updateSlug = useCallback(\n    (value) => {\n      const newSlug = value.slice(0, MIN_MAX.PERMALINK.MAX);\n\n      updateStory({\n        properties: { slug: cleanForSlug(newSlug) },\n      });\n    },\n    [updateStory]\n  );\n\n  const handleChange = useCallback(\n    (evt) => setSlug(cleanForSlug(evt.target.value, true)),\n    []\n  );\n\n  const handleBlur = useCallback(\n    (evt) => updateSlug(evt.target.value),\n    [updateSlug]\n  );\n\n  const displayLink =\n    slug && permalinkConfig && inRange(slug.length, MIN_MAX.PERMALINK)\n      ? permalinkConfig.prefix + slug + permalinkConfig.suffix\n      : link;\n\n  // In case of non-pretty permalinks, we're not showing the input.\n  return (\n    <SimplePanel\n      name={nameOverride || 'permalink'}\n      title={__('Permalink', 'web-stories')}\n      collapsedByDefault={false}\n    >\n      {permalinkConfig && (\n        <PermalinkRow>\n          <Input\n            value={String(slug)}\n            onChange={handleChange}\n            onBlur={handleBlur}\n            placeholder={__('Enter slug', 'web-stories')}\n            aria-label={__('URL slug', 'web-stories')}\n            minLength={MIN_MAX.PERMALINK.MIN}\n            maxLength={MIN_MAX.PERMALINK.MAX}\n            containerStyleOverride={inputContainerStyleOverride}\n          />\n        </PermalinkRow>\n      )}\n      <LinkContainer>\n        <Link\n          rel=\"noreferrer\"\n          target=\"_blank\"\n          href={link}\n          size={TextSize.Small}\n        >\n          {displayLink}\n        </Link>\n      </LinkContainer>\n    </SimplePanel>\n  );\n}\n\nexport default SlugPanel;\n\nSlugPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/slug/test/slug.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../../../app/story/context';\nimport SlugPanel, { MIN_MAX } from '../slug';\n\nfunction arrange(storyConfig = {}) {\n  const updateStory = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      story: {\n        slug: 'foo',\n        link: 'https://example.com',\n        permalinkConfig: {\n          prefix: 'https://example.com/',\n          suffix: '',\n        },\n        ...storyConfig,\n      },\n    },\n    actions: { updateStory },\n  };\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <SlugPanel />\n    </StoryContext.Provider>\n  );\n  return {\n    updateStory,\n  };\n}\n\ndescribe('SlugPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:permalink',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render Slug Panel', () => {\n    arrange();\n    const element = screen.getByRole('button', { name: 'Permalink' });\n    expect(element).toBeInTheDocument();\n  });\n\n  it('should display permalink', () => {\n    arrange();\n    const url = screen.getByRole('link', { name: 'https://example.com/foo' });\n    expect(url).toBeInTheDocument();\n  });\n\n  it('should not display the input when using non-pretty permalinks', () => {\n    arrange({ permalinkConfig: null });\n    expect(() => screen.getByRole('textbox', { name: 'URL slug' })).toThrow(\n      'Unable to find an accessible element with the role \"textbox\" and name \"URL slug\"'\n    );\n  });\n\n  it('should not allow trailing spaces while typing and onblur', async () => {\n    const { updateStory } = arrange();\n    const input = screen.getByRole('textbox', { name: 'URL slug' });\n\n    fireEvent.change(input, {\n      target: { value: 'name with spaces ' },\n    });\n\n    expect(input).toHaveValue('name-with-spaces-');\n\n    fireEvent.blur(input, {\n      target: { value: 'different name with spaces ' },\n    });\n\n    await waitFor(() =>\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          slug: 'different-name-with-spaces',\n        },\n      })\n    );\n  });\n\n  it('should respect the link limit', async () => {\n    const { updateStory } = arrange();\n    const input = screen.getByRole('textbox', { name: 'URL slug' });\n    expect(input).toBeInTheDocument();\n\n    const bigSlug = ''.padStart(MIN_MAX.PERMALINK.MAX + 10, '1');\n\n    fireEvent.blur(input, {\n      target: { value: bigSlug },\n    });\n\n    await waitFor(() =>\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          // It will return only 200 even receiving 201+\n          slug: bigSlug.slice(0, MIN_MAX.PERMALINK.MAX),\n        },\n      })\n    );\n\n    fireEvent.blur(input, {\n      target: { value: '1234' },\n    });\n\n    await waitFor(() =>\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: {\n          slug: '1234',\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/FlatTermSelector.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useDebouncedCallback,\n  useMemo,\n  useState,\n  useEffect,\n} from '@googleforcreators/react';\nimport { __, sprintf, _n } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { useLiveRegion } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport Tags from '../../../form/tags';\nimport cleanForSlug from '../../../../utils/cleanForSlug';\nimport { useTaxonomy } from '../../../../app/taxonomy';\nimport { useHistory } from '../../../../app';\nimport { ContentHeading, TaxonomyPropType, WordCloud } from './shared';\n\nfunction FlatTermSelector({ taxonomy, canCreateTerms }) {\n  const [mostUsed, setMostUsed] = useState([]);\n  const {\n    createTerm,\n    termCache,\n    addSearchResultsToCache,\n    terms = [],\n    addTerms,\n    removeTerms,\n  } = useTaxonomy(\n    ({\n      state: { termCache, terms },\n      actions: { createTerm, addSearchResultsToCache, addTerms, removeTerms },\n    }) => ({\n      termCache,\n      createTerm,\n      addSearchResultsToCache,\n      terms,\n      addTerms,\n      removeTerms,\n    })\n  );\n\n  const { undo } = useHistory(({ actions: { undo } }) => ({ undo }));\n  const [searchResults, setSearchResults] = useState([]);\n  const speak = useLiveRegion('assertive');\n\n  const handleFreeformTermsChange = useCallback(\n    (termNames) => {\n      const currentTerms = termCache.filter(\n        (term) =>\n          term.taxonomy === taxonomy.slug && termNames.includes(term.name)\n      );\n      const removeToTerms = terms.filter(\n        (term) =>\n          term.taxonomy === taxonomy.slug && !termNames.includes(term.name)\n      );\n      removeTerms(removeToTerms);\n      addTerms(currentTerms);\n\n      // Return early if user doesn't have capability to create new terms\n      if (!canCreateTerms) {\n        return;\n      }\n\n      // set terms that exist in the cache\n      const termNameSlugTuples = termNames.map((name) => [\n        cleanForSlug(name),\n        name,\n      ]);\n\n      const termNamesNotInCache = termNameSlugTuples\n        .filter(\n          ([slug]) =>\n            !termCache\n              .filter((term) => term.taxonomy === taxonomy.slug)\n              .map(({ slug: thisSlug }) => thisSlug.toLowerCase())\n              .includes(slug)\n        )\n        .map(([, name]) => name);\n\n      // create new terms for ones that don't\n      termNamesNotInCache.forEach((name) =>\n        createTerm({\n          taxonomy,\n          termName: name,\n          parent: null,\n          addToSelection: true,\n        })\n      );\n    },\n    [\n      termCache,\n      removeTerms,\n      terms,\n      addTerms,\n      canCreateTerms,\n      createTerm,\n      taxonomy,\n    ]\n  );\n\n  const handleFreeformInputChange = useDebouncedCallback(async (value) => {\n    if (value.length === 0) {\n      setSearchResults([]);\n      return;\n    }\n\n    if (value.length < 3) {\n      return;\n    }\n    const results = await addSearchResultsToCache({\n      taxonomy,\n      args: {\n        search: value,\n        // This is the per_page value Gutenberg is using\n        per_page: 20,\n      },\n    });\n    setSearchResults(results);\n\n    const count = results.length;\n    const message = sprintf(\n      /* translators: %d: number of results. */\n      _n('%d result found.', '%d results found.', count, 'web-stories'),\n      count\n    );\n    speak(message);\n  }, 300);\n\n  const tokens = useMemo(() => {\n    return terms\n      .filter((term) => term.taxonomy === taxonomy.slug)\n      .filter((term) => term !== undefined)\n      .map((term) => term.name);\n  }, [terms, taxonomy]);\n\n  const termDisplayTransformer = useCallback(\n    (tagName) => termCache.filter((term) => term.name === tagName)?.[0]?.name,\n    [termCache]\n  );\n\n  useEffect(() => {\n    (async () => {\n      const results = await addSearchResultsToCache({\n        taxonomy,\n        args: {\n          orderby: 'count',\n          order: 'desc',\n          hide_empty: true,\n        },\n      });\n      setMostUsed(results);\n    })();\n  }, [taxonomy, addSearchResultsToCache]);\n\n  return (\n    <>\n      <ContentHeading>{taxonomy.labels.name}</ContentHeading>\n      <div key={taxonomy.slug}>\n        <Tags.Label htmlFor={`${taxonomy.slug}-input`}>\n          {taxonomy.labels.addNewItem}\n        </Tags.Label>\n        <Tags.Input\n          id={`${taxonomy.slug}-input`}\n          aria-describedby={`${taxonomy.slug}-description`}\n          name={taxonomy.slug}\n          onTagsChange={handleFreeformTermsChange}\n          onInputChange={handleFreeformInputChange}\n          tagDisplayTransformer={termDisplayTransformer}\n          tokens={tokens}\n          onUndo={undo}\n          suggestedTerms={searchResults}\n          suggestedTermsLabel={taxonomy?.labels?.itemsList}\n        />\n        <Tags.Description id={`${taxonomy.slug}-description`}>\n          {taxonomy.labels.separateItemsWithCommas}\n        </Tags.Description>\n        {mostUsed?.length > 0 && (\n          <WordCloud.Wrapper data-testid={`${taxonomy.slug}-most-used`}>\n            <WordCloud.Heading>{taxonomy.labels.mostUsed}</WordCloud.Heading>\n            <WordCloud.List>\n              {mostUsed.map((term, i) => (\n                <WordCloud.ListItem key={term.id}>\n                  <WordCloud.Word\n                    onClick={() => {\n                      if (terms.map(({ id }) => id).includes(term.id)) {\n                        return;\n                      }\n                      addTerms([term]);\n                    }}\n                  >\n                    {term.name}\n\n                    {i < mostUsed.length - 1 &&\n                      /* translators: delimiter used in a list */\n                      __(',', 'web-stories')}\n                  </WordCloud.Word>\n                  {\n                    /* Browser only respects the white space in the li, not the button */\n                    i < mostUsed.length - 1 && ' '\n                  }\n                </WordCloud.ListItem>\n              ))}\n            </WordCloud.List>\n          </WordCloud.Wrapper>\n        )}\n      </div>\n    </>\n  );\n}\n\nFlatTermSelector.propTypes = {\n  taxonomy: TaxonomyPropType,\n  canCreateTerms: PropTypes.bool,\n};\n\nexport default FlatTermSelector;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/HierarchicalTermSelector.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x, sprintf } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  DropDown,\n  Input,\n  Text,\n  TextSize,\n  themeHelpers,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * Internal dependencies\n */\nimport { HierarchicalInput, makeFlatOptionTree } from '../../../form';\nimport { useTaxonomy } from '../../../../app/taxonomy';\nimport { ContentHeading, TaxonomyPropType, LinkButton } from './shared';\n\nconst NO_PARENT_VALUE = 'NO_PARENT_VALUE';\n\nconst ContentArea = styled.div`\n  label,\n  * > label {\n    ${({ theme }) =>\n      themeHelpers.expandPresetStyles({\n        preset: theme.typography.presets.label[TextSize.Small],\n        theme,\n      })};\n\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\n\nconst AddNewCategoryForm = styled.form`\n  margin: 24px 0 16px;\n`;\n\nconst ButtonContainer = styled.div`\n  display: flex;\n  gap: 8px;\n`;\n\nconst Label = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  display: inline-block;\n  margin: 12px 0;\n`;\n\nconst AddNewCategoryButton = styled(Button).attrs({\n  variant: ButtonVariant.Rectangle,\n  size: ButtonSize.Small,\n  type: ButtonType.Secondary,\n})`\n  margin-top: 20px;\n`;\n\nfunction HierarchicalTermSelector({\n  noParentId = NO_PARENT_VALUE,\n  taxonomy,\n  canCreateTerms,\n}) {\n  const { createTerm, termCache, terms, addTerms, removeTerms } = useTaxonomy(\n    ({\n      state: { termCache, terms },\n      actions: { createTerm, addTerms, removeTerms },\n    }) => ({\n      createTerm,\n      addTerms,\n      removeTerms,\n      termCache,\n      terms,\n    })\n  );\n\n  const categories = useMemo(() => {\n    if (termCache) {\n      return termCache\n        .filter((term) => term.taxonomy === taxonomy.slug)\n        .map((category) => ({\n          id: category.id,\n          parent: category.parent,\n          value: category.id,\n          label: category.name,\n          checked: terms\n            ? terms.map(({ id }) => id).includes(category.id)\n            : false,\n          slug: category.slug,\n        }));\n    }\n\n    return [];\n  }, [taxonomy, termCache, terms]);\n\n  const [showAddNewCategory, setShowAddNewCategory] = useState(false);\n  const [newCategoryName, setNewCategoryName] = useState('');\n  const [selectedParent, setSelectedParent] = useState(noParentId);\n  const dropdownId = useMemo(uuidv4, []);\n  const [hasFocus, setHasFocus] = useState(false);\n  const formRef = useRef();\n  const toggleRef = useRef();\n  const [toggleFocus, setToggleFocus] = useState(false);\n  const [searchText, setSearchText] = useState('');\n\n  const handleInputChange = useCallback((value) => setSearchText(value), []);\n  const speak = useLiveRegion('assertive');\n\n  const resetInputs = useCallback(() => {\n    setNewCategoryName('');\n    setSelectedParent(noParentId);\n  }, [noParentId]);\n\n  const handleClickCategory = useCallback(\n    (_evt, { id, checked }) => {\n      const term = termCache.find(\n        (category) => category.id === id && category.taxonomy === taxonomy.slug\n      );\n      if (checked) {\n        // find the already selected slugs + update those.\n        addTerms([term]);\n      } else {\n        removeTerms([term]);\n      }\n    },\n    [termCache, taxonomy.slug, addTerms, removeTerms]\n  );\n\n  const handleToggleNewCategory = useCallback(() => {\n    setShowAddNewCategory(!showAddNewCategory);\n    resetInputs();\n    setHasFocus(!showAddNewCategory);\n    setToggleFocus(showAddNewCategory);\n  }, [resetInputs, showAddNewCategory]);\n\n  const handleChangeNewCategoryName = useCallback((evt) => {\n    setNewCategoryName(evt.target.value);\n  }, []);\n\n  const selectedParentSlug = useMemo(\n    () => categories.find((category) => category.id === selectedParent)?.slug,\n    [selectedParent, categories]\n  );\n\n  const handleSubmit = useCallback(\n    (evt) => {\n      evt.preventDefault();\n\n      const parentValue = {\n        id: selectedParent === noParentId ? 0 : selectedParent,\n        slug: selectedParentSlug,\n      };\n      createTerm({\n        taxonomy,\n        termName: newCategoryName,\n        parent: parentValue,\n        addToSelection: true,\n      });\n      speak(\n        sprintf(\n          /* Translators: %s: Taxonomy label name. */\n          __('%s added.', 'web-stories'),\n          taxonomy.labels.singular_name\n        )\n      );\n      setShowAddNewCategory(false);\n      resetInputs();\n      setToggleFocus(showAddNewCategory);\n    },\n    [\n      createTerm,\n      speak,\n      newCategoryName,\n      noParentId,\n      resetInputs,\n      selectedParent,\n      showAddNewCategory,\n      taxonomy,\n      selectedParentSlug,\n    ]\n  );\n  const handleParentSelect = useCallback(\n    (_evt, menuItem) => setSelectedParent(menuItem),\n    []\n  );\n\n  useEffect(() => {\n    const node = formRef.current;\n    if (node) {\n      const handleEnter = (evt) => {\n        if (evt.key === 'Enter') {\n          handleSubmit(evt);\n        }\n      };\n\n      node.addEventListener('keypress', handleEnter);\n      return () => {\n        node.removeEventListener('keypress', handleEnter);\n      };\n    }\n    return null;\n  }, [handleSubmit, formRef]);\n\n  useEffect(() => {\n    if (toggleFocus) {\n      toggleRef.current.focus();\n    }\n  }, [toggleFocus]);\n\n  const orderedCategories = useMemo(\n    () => makeFlatOptionTree(categories, searchText),\n    [categories, searchText]\n  );\n\n  const dropdownCategories = useMemo(\n    () =>\n      [\n        {\n          value: NO_PARENT_VALUE,\n          label: _x('None', 'parent taxonomy', 'web-stories'),\n        },\n      ]\n        .concat(orderedCategories)\n        .map(({ $level, label, ...opt }) => ({\n          ...opt,\n          label: `${Array.from({ length: $level }, () => '— ').join(\n            ''\n          )} ${label}`,\n        })),\n    [orderedCategories]\n  );\n\n  return (\n    <ContentArea>\n      <ContentHeading>{taxonomy.labels.name}</ContentHeading>\n      <HierarchicalInput\n        inputValue={searchText}\n        onInputChange={handleInputChange}\n        label={taxonomy.labels.searchItems}\n        options={orderedCategories}\n        onChange={handleClickCategory}\n        noOptionsText={taxonomy.labels?.notFound}\n      />\n      {canCreateTerms ? (\n        <>\n          {!showAddNewCategory && (\n            <LinkButton\n              ref={toggleRef}\n              aria-expanded={false}\n              onClick={handleToggleNewCategory}\n            >\n              {taxonomy.labels.addNewItem}\n            </LinkButton>\n          )}\n          {showAddNewCategory ? (\n            <AddNewCategoryForm ref={formRef} onSubmit={handleSubmit}>\n              <Input\n                name={taxonomy.labels.newItemName}\n                label={taxonomy.labels.newItemName}\n                value={newCategoryName}\n                onChange={handleChangeNewCategoryName}\n                hasFocus={hasFocus}\n              />\n              <Label htmlFor={dropdownId}>{taxonomy.labels.parentItem}</Label>\n              <DropDown\n                id={dropdownId}\n                ariaLabel={taxonomy.labels.parentItem}\n                options={dropdownCategories}\n                selectedValue={selectedParent}\n                onMenuItemClick={handleParentSelect}\n              />\n              <ButtonContainer>\n                <AddNewCategoryButton\n                  disabled={!newCategoryName.length}\n                  type=\"submit\"\n                >\n                  {taxonomy.labels.addNewItem}\n                </AddNewCategoryButton>\n                <AddNewCategoryButton\n                  aria-expanded\n                  onClick={handleToggleNewCategory}\n                >\n                  {__('Cancel', 'web-stories')}\n                </AddNewCategoryButton>\n              </ButtonContainer>\n            </AddNewCategoryForm>\n          ) : null}\n        </>\n      ) : null}\n    </ContentArea>\n  );\n}\n\nHierarchicalTermSelector.propTypes = {\n  noParentId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n  taxonomy: TaxonomyPropType,\n  canCreateTerms: PropTypes.bool,\n};\n\nexport default HierarchicalTermSelector;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './taxonomies';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/karma/taxonomies.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../../../app';\nimport { Fixture } from '../../../../../karma';\n\ndescribe('Taxonomies Panel', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  async function openTaxonomiesPanel() {\n    // open document panel\n    await fixture.events.click(fixture.editor.sidebar.documentTab);\n\n    // expand the taxonomies panel\n    await fixture.events.click(\n      fixture.editor.sidebar.documentPanel.taxonomies.taxonomiesButton\n    );\n  }\n\n  async function getStoryTerms() {\n    const {\n      state: {\n        story: { terms },\n      },\n    } = await fixture.renderHook(() => useStory());\n\n    return terms;\n  }\n\n  it('should have no aXe accessibility violations', async () => {\n    await openTaxonomiesPanel();\n    const { taxonomies } = fixture.editor.sidebar.documentPanel;\n    await expectAsync(taxonomies.node).toHaveNoViolations({\n      rules: {\n        // Disabled because of some false positives.\n        // See https://github.com/GoogleForCreators/web-stories-wp/issues/11071\n        'color-contrast': {\n          enabled: false,\n        },\n      },\n    });\n  });\n\n  describe('Categories', () => {\n    describe('cursor interactions', () => {\n      it('should add categories and remove categories', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // track initial story categories\n        const initialStoryTerms = await getStoryTerms();\n\n        // click a checkbox\n        expect(taxonomies.categories[0].checked).toBe(true);\n        await fixture.events.click(taxonomies.categories[0]);\n        expect(taxonomies.categories[0].checked).toBe(false);\n\n        // verify category was removed from story\n        let currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        ).toBe(\n          initialStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length - 1\n        );\n\n        // click a checkbox again\n        await fixture.events.click(taxonomies.categories[0]);\n        expect(taxonomies.categories[0].checked).toBe(true);\n\n        // verify category was added to story\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        ).toBe(\n          initialStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        );\n      });\n\n      it('should add new categories', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // track initial categories\n        const initialCategories = taxonomies.categories;\n\n        // open the new category section\n        await fixture.events.click(taxonomies.addNewCategoryButton);\n\n        // Add new category\n        await fixture.events.focus(taxonomies.newCategoryNameInput);\n        await fixture.events.keyboard.type('deer');\n\n        await fixture.events.click(taxonomies.addNewCategoryButton);\n\n        // validate new checkbox was added\n        const finalCategories = taxonomies.categories;\n        initialCategories.map((checkbox) =>\n          expect(checkbox.name).not.toBe('hierarchical_term_deer')\n        );\n        expect(finalCategories.length).toBe(initialCategories.length + 1);\n        expect(\n          finalCategories.filter(\n            (category) => category.name === 'hierarchical_term_deer'\n          ).length\n        ).toBe(1);\n\n        // TODO: 9058 - validate new category exists on story once category is checked when added.\n      });\n\n      it('should add a new category as a child of an existing category', async () => {\n        await openTaxonomiesPanel();\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n        // find initial categories\n        const initialCategories = taxonomies.categories;\n\n        // open the new category section\n        await fixture.events.click(taxonomies.addNewCategoryButton);\n        // Input should be focused\n        expect(document.activeElement).toBe(taxonomies.newCategoryNameInput);\n        // Add new category\n        await fixture.events.focus(taxonomies.newCategoryNameInput);\n        await fixture.events.keyboard.type('deer');\n        await fixture.events.click(taxonomies.parentDropdownButton);\n\n        await fixture.events.click(\n          fixture.screen.getByRole('option', {\n            name: 'Booger',\n          })\n        );\n\n        await fixture.events.click(taxonomies.addNewCategoryButton);\n        // validate new checkbox was added\n        const finalCategories = taxonomies.categories;\n        initialCategories.map((checkbox) =>\n          expect(checkbox.name).not.toBe('deer')\n        );\n        expect(finalCategories.length).toBe(initialCategories.length + 1);\n        expect(\n          finalCategories.filter(\n            (category) => category.name === 'hierarchical_term_deer'\n          ).length\n        ).toBe(1);\n        // validate new checkbox was added as a child\n        // New checkbox will have been added directly after the parent option\n        const boogerIndex = finalCategories.findIndex(\n          (category) => category.name === 'hierarchical_term_Booger'\n        );\n        const deerIndex = finalCategories.findIndex(\n          (category) => category.name === 'hierarchical_term_deer'\n        );\n        expect(deerIndex).toBe(boogerIndex + 1);\n        // TODO: 9058 - validate new category exists on story once category is checked when added.\n      });\n    });\n\n    describe('keyboard interactions', () => {\n      // TODO(#9226): Fix flaky test.\n      // eslint-disable-next-line jasmine/no-disabled-tests\n      xit('should add categories and remove categories', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // track initial story categories\n        const initialStoryTerms = await getStoryTerms();\n\n        // focus the panel button\n        await fixture.events.focus(taxonomies.taxonomiesButton);\n\n        // tab to first checkbox and un-check\n        expect(taxonomies.categories[0].checked).toBe(true);\n        await fixture.events.keyboard.press('Tab');\n        await fixture.events.keyboard.press('Tab');\n        expect(document.activeElement.type).toBe('checkbox');\n        await fixture.events.keyboard.press('Space');\n        expect(taxonomies.categories[0].checked).toBe(false);\n\n        // verify category was removed from story\n        let currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        ).toBe(\n          initialStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length - 1\n        );\n\n        // check the checkbox again\n        await fixture.events.keyboard.press('Space');\n        expect(taxonomies.categories[0].checked).toBe(true);\n\n        // verify category was added to story\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        ).toBe(\n          initialStoryTerms.filter(\n            (term) => term.taxonomy === 'web_story_category'\n          ).length\n        );\n      });\n\n      it('should add new categories', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // focus the panel button\n        await fixture.events.focus(taxonomies.taxonomiesButton);\n\n        // track initial categories\n        const initialCategories = taxonomies.categories;\n\n        // tab and to new category section\n        let maxTabs = 0;\n        while (\n          maxTabs < 20 &&\n          document.activeElement !== taxonomies.addNewCategoryButton\n        ) {\n          // eslint-disable-next-line no-await-in-loop\n          await fixture.events.keyboard.press('Tab');\n          maxTabs++;\n        }\n        await fixture.events.keyboard.press('Space');\n\n        // Input should be focused\n        expect(document.activeElement).toBe(taxonomies.newCategoryNameInput);\n\n        // Enter name and submit\n        await fixture.events.keyboard.type('deer');\n        await fixture.events.keyboard.press('Tab');\n        await fixture.events.keyboard.press('Tab');\n        expect(document.activeElement).toBe(taxonomies.addNewCategoryButton);\n        await fixture.events.keyboard.press('Enter');\n\n        // validate new checkbox was added\n        const finalCategories = taxonomies.categories;\n        initialCategories.map((checkbox) =>\n          expect(checkbox.name).not.toBe('hierarchical_term_deer')\n        );\n        expect(finalCategories.length).toBe(initialCategories.length + 1);\n        expect(\n          finalCategories.filter(\n            (category) => category.name === 'hierarchical_term_deer'\n          ).length\n        ).toBe(1);\n\n        // TODO: 9058 - validate new category exists on story once category is checked when added.\n      });\n\n      it('should add a new category as a child of an existing category', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // focus the panel button\n        await fixture.events.focus(taxonomies.taxonomiesButton);\n\n        // track initial categories\n        const initialCategories = taxonomies.categories;\n\n        // tab and to new category section\n        let maxTabs = 0;\n        while (\n          maxTabs < 20 &&\n          document.activeElement !== taxonomies.addNewCategoryButton\n        ) {\n          // eslint-disable-next-line no-await-in-loop\n          await fixture.events.keyboard.press('Tab');\n          maxTabs++;\n        }\n        await fixture.events.keyboard.press('Space');\n\n        // Input should be focused\n        expect(document.activeElement).toBe(taxonomies.newCategoryNameInput);\n\n        // Enter name\n        await fixture.events.keyboard.type('deer');\n\n        // Add parent\n        await fixture.events.keyboard.press('Tab');\n        await fixture.events.keyboard.press('Space');\n        await fixture.events.keyboard.press('down');\n        await fixture.events.keyboard.press('Enter');\n\n        // Submit\n        await fixture.events.keyboard.press('Tab');\n        expect(document.activeElement).toBe(taxonomies.addNewCategoryButton);\n        await fixture.events.keyboard.press('Enter');\n\n        // validate new checkbox was added\n        const finalCategories = taxonomies.categories;\n        initialCategories.map((checkbox) =>\n          expect(checkbox.name).not.toBe('deer')\n        );\n        expect(finalCategories.length).toBe(initialCategories.length + 1);\n        expect(\n          finalCategories.filter(\n            (category) => category.name === 'hierarchical_term_deer'\n          ).length\n        ).toBe(1);\n\n        // validate new checkbox was added as a child\n        // New checkbox will have been added directly after the parent option\n        const boogerIndex = finalCategories.findIndex(\n          (category) => category.name === 'hierarchical_term_Booger'\n        );\n        const deerIndex = finalCategories.findIndex(\n          (category) => category.name === 'hierarchical_term_deer'\n        );\n        expect(deerIndex).toBe(boogerIndex + 1);\n\n        // TODO: 9058 - validate new category exists on story once category is checked when added.\n      });\n\n      it('should submit new categories with Enter button', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // focus the panel button\n        await fixture.events.focus(taxonomies.taxonomiesButton);\n\n        // track initial categories\n        const initialCategories = taxonomies.categories;\n\n        // tab to `Add New Category` button / section\n        let maxTabs = 0;\n        while (\n          maxTabs < 20 &&\n          document.activeElement !== taxonomies.addNewCategoryButton\n        ) {\n          // eslint-disable-next-line no-await-in-loop\n          await fixture.events.keyboard.press('Tab');\n          maxTabs++;\n        }\n        // Toggle `Add New Category`\n        await fixture.events.keyboard.press('Space');\n\n        // Input should be focused\n        expect(document.activeElement).toBe(taxonomies.newCategoryNameInput);\n\n        // Enter name and submit\n        await fixture.events.keyboard.type('deer');\n        await fixture.events.keyboard.press('Enter');\n\n        // validate new checkbox was added\n        const finalCategories = taxonomies.categories;\n        initialCategories.map((checkbox) =>\n          expect(checkbox.name).not.toBe('hierarchical_term_deer')\n        );\n        expect(finalCategories.length).toBe(initialCategories.length + 1);\n        expect(\n          finalCategories.filter(\n            (category) => category.name === 'hierarchical_term_deer'\n          ).length\n        ).toBe(1);\n\n        // TODO: 9058 - validate new category exists on story once category is checked when added.\n      });\n\n      it('should focus toggle on cancel', async () => {\n        await openTaxonomiesPanel();\n\n        const { taxonomies } = fixture.editor.sidebar.documentPanel;\n\n        // focus the panel button\n        await fixture.events.focus(taxonomies.taxonomiesButton);\n\n        // tab to `Add New Category` section\n        let maxTabs = 0;\n        while (\n          maxTabs < 20 &&\n          document.activeElement !== taxonomies.addNewCategoryButton\n        ) {\n          // eslint-disable-next-line no-await-in-loop\n          await fixture.events.keyboard.press('Tab');\n          maxTabs++;\n        }\n        // Toggle `Add New Category`\n        await fixture.events.keyboard.press('Space');\n\n        // Input should be focused\n        expect(document.activeElement).toBe(taxonomies.newCategoryNameInput);\n\n        // Enter name and submit\n        await fixture.events.keyboard.type('deer');\n        // Tab to Cancel button\n        await fixture.events.keyboard.press('Tab');\n        await fixture.events.keyboard.press('Tab');\n        await fixture.events.keyboard.press('Tab');\n        // Hit Cancel button\n        await fixture.events.keyboard.press('Enter');\n\n        // The toggle `Add New Category` should be focused\n        expect(document.activeElement).toBe(taxonomies.addNewCategoryButton);\n      });\n    });\n  });\n\n  describe('Tags', () => {\n    it('populates the tags correctly from the story', async () => {\n      await openTaxonomiesPanel();\n      const currentStoryTerms = await getStoryTerms();\n      const renderedTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      expect(renderedTokens.length).toEqual(\n        currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n          .length\n      );\n    });\n\n    it('can add tags with input', async () => {\n      await openTaxonomiesPanel();\n      const tag1Name = 'new tag';\n      const tag2Name = 'another tag';\n      let currentStoryTerms = await getStoryTerms();\n      const initialTagsLength = currentStoryTerms.filter(\n        (term) => term.taxonomy === 'web_story_tag'\n      ).length;\n      const { taxonomies } = fixture.editor.sidebar.documentPanel;\n      const tagsInput = taxonomies.tagsInput;\n      // enter in the first tag\n      await fixture.events.focus(tagsInput);\n      await fixture.events.keyboard.type(tag1Name);\n      await fixture.events.keyboard.press('Enter');\n      let tags = await fixture.screen.findAllByTestId(/^flat-term-token/);\n      await expect(tags.length).toBe(initialTagsLength + 1);\n      // See that terms are persisted on the story\n      await waitFor(async () => {\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n            .length\n        ).toEqual(initialTagsLength + 1);\n      });\n\n      // enter in a second tag\n      await fixture.events.keyboard.type(tag2Name);\n      await fixture.events.keyboard.press('Enter');\n      tags = await fixture.screen.findAllByTestId(/^flat-term-token/);\n\n      await expect(tags.length).toBe(initialTagsLength + 2);\n      // See that terms are persisted on the story\n      await waitFor(async () => {\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n            .length\n        ).toEqual(initialTagsLength + 2);\n      });\n      const tagTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      expect(tagTokens[initialTagsLength].innerText).toBe(tag1Name);\n      expect(tagTokens[initialTagsLength + 1].innerText).toBe(tag2Name);\n    });\n\n    it('can add tags with Most Used', async () => {\n      await openTaxonomiesPanel();\n      const initialTagsLength = (await getStoryTerms()).filter(\n        (term) => term.taxonomy === 'web_story_tag'\n      ).length;\n\n      // get all most used terms\n      const storyTagsMostUsed = fixture.screen.getByTestId(\n        /^web_story_tag-most-used/\n      );\n      const mostUsedButtons = within(storyTagsMostUsed).getAllByRole('button');\n\n      // click on the first most used term\n      await fixture.events.click(mostUsedButtons[0]);\n\n      // see that the term appears in the input\n      const tagTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      expect(tagTokens[tagTokens.length - 1].innerText).toBe(\n        // most used buttons have comma separators in them\n        mostUsedButtons[0].innerText.split(',')[0]\n      );\n\n      // see that the term id is associated with the story\n      const currentStoryTerms = await getStoryTerms();\n      expect(\n        currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n          .length\n      ).toEqual(initialTagsLength + 1);\n    });\n\n    it('can delete tags with keyboard', async () => {\n      await openTaxonomiesPanel();\n      let currentStoryTerms = await getStoryTerms();\n      const initialTagsLength = currentStoryTerms.filter(\n        (term) => term.taxonomy === 'web_story_tag'\n      ).length;\n      const { tagsInput } = fixture.editor.sidebar.documentPanel.taxonomies;\n      const initialTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      // delete the first tag with keyboard navigation\n      await fixture.events.focus(tagsInput);\n      await fixture.events.keyboard.press('ArrowLeft');\n      await fixture.events.keyboard.press('Backspace');\n      await waitFor(\n        () =>\n          fixture.screen.getAllByTestId(/^flat-term-token/).length ===\n          initialTagsLength - 1\n      );\n      // See that terms are persisted on the story\n      await waitFor(async () => {\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n            .length\n        ).toEqual(initialTagsLength - 1);\n      });\n      // See that the right tag was deleted\n      const tagTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      expect(tagTokens[0].innerText).toEqual(initialTokens[0].innerText);\n      expect(tagTokens[1].innerText).toEqual(initialTokens[2].innerText);\n    });\n\n    it('can delete tags with mouse', async () => {\n      await openTaxonomiesPanel();\n      let currentStoryTerms = await getStoryTerms();\n      const { taxonomies } = fixture.editor.sidebar.documentPanel;\n      const initialTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      const initialTagsLength = currentStoryTerms.filter(\n        (term) => term.taxonomy === 'web_story_tag'\n      ).length;\n      // delete tag with mouse\n      const removeTagButtons = taxonomies.tagTokenRemoveButtons;\n      await fixture.events.click(removeTagButtons[0]);\n      await waitFor(\n        () =>\n          fixture.screen.getAllByTestId(/^flat-term-token/).length ===\n          initialTagsLength - 1\n      );\n      // See that terms are persisted on the story\n      await waitFor(async () => {\n        currentStoryTerms = await getStoryTerms();\n        expect(\n          currentStoryTerms.filter((term) => term.taxonomy === 'web_story_tag')\n            .length\n        ).toEqual(initialTagsLength - 1);\n      });\n      // see that the correct token was removed\n      const tagTokens = fixture.screen.getAllByTestId(/^flat-term-token/);\n      expect(tagTokens[0].innerText).toEqual(initialTokens[1].innerText);\n      expect(tagTokens[1].innerText).toEqual(initialTokens[2].innerText);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/shared.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Headline,\n  TextSize,\n  themeHelpers,\n  Button,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\n\nexport const TaxonomyPropType = PropTypes.shape({\n  capabilities: PropTypes.object,\n  description: PropTypes.string,\n  hierarchical: PropTypes.bool,\n  labels: PropTypes.object,\n  name: PropTypes.string.isRequired,\n  restBase: PropTypes.string.isRequired,\n  showCloud: PropTypes.bool,\n  slug: PropTypes.string.isRequired,\n  types: PropTypes.arrayOf(PropTypes.string),\n  visibility: PropTypes.object,\n});\n\nexport const ContentHeading = styled(Headline).attrs({\n  as: 'h3',\n  size: TextSize.XXXSmall,\n})`\n  margin: 4px 0 16px;\n  font-weight: ${({ theme }) => theme.typography.weight.regular};\n`;\n\nexport const LinkButton = styled(Button).attrs({\n  variant: ButtonVariant.Link,\n})`\n  ${themeHelpers.expandTextPreset(({ link }, { XSmall }) => link[XSmall])}\n  margin-bottom: 16px;\n  font-weight: 500;\n`;\n\nexport const SiblingBorder = styled.div`\n  padding-left: 16px;\n  padding-right: 16px;\n\n  & + & {\n    border-top: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n    padding-top: 16px;\n    padding-bottom: 8px;\n  }\n`;\n\nexport const WordCloud = {\n  Heading: styled(ContentHeading).attrs({ as: 'h4' })`\n    margin-bottom: 4px;\n  `,\n  Wrapper: styled.div`\n    padding: 18px 0px;\n  `,\n  List: styled.ul`\n    all: unset;\n    /* Only adding this here to prevent cursor flash between text/pointer when hovering*/\n    cursor: pointer;\n  `,\n  ListItem: styled.li`\n    all: unset;\n  `,\n  Word: styled(LinkButton)`\n    margin: 0;\n    display: revert;\n  `,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport TaxonomiesPanel from '../taxonomies';\n\nconst Taxonomies = styled(TaxonomiesPanel)`\n  background: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nexport default {\n  title: 'Stories Editor/Components/Taxonomies',\n  component: TaxonomiesPanel,\n};\n\nexport const _default = {\n  render: function Render() {\n    return <Taxonomies />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/taxonomies.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useTaxonomy } from '../../../../app/taxonomy';\nimport { SimplePanel } from '../../panel';\nimport { useStory } from '../../../../app';\nimport HierarchicalTermSelector from './HierarchicalTermSelector';\nimport FlatTermSelector from './FlatTermSelector';\nimport { SiblingBorder } from './shared';\n\nconst StyledSimplePanel = styled(SimplePanel)`\n  padding-left: 0;\n  padding-right: 0;\n`;\n\nfunction TaxonomiesPanel({ nameOverride, ...props }) {\n  const { capabilities } = useStory(({ state: { capabilities } }) => ({\n    capabilities,\n  }));\n  const { taxonomies } = useTaxonomy(({ state: { taxonomies } }) => ({\n    taxonomies,\n  }));\n\n  if (!taxonomies?.length) {\n    return null;\n  }\n\n  const availableTaxonomies = taxonomies.filter((taxonomy) =>\n    Boolean(\n      capabilities[`assign-${taxonomy?.restBase}`] ||\n      capabilities[`assign-${taxonomy?.slug}`]\n    )\n  );\n\n  if (availableTaxonomies.length === 0) {\n    return null;\n  }\n\n  return (\n    <StyledSimplePanel\n      name={nameOverride || 'taxonomies'}\n      title={__('Taxonomies', 'web-stories')}\n      {...props}\n    >\n      {availableTaxonomies.map((taxonomy) => {\n        const canCreateTerms = Boolean(\n          capabilities[`create-${taxonomy?.restBase}`] ||\n          capabilities[`create-${taxonomy?.slug}`]\n        );\n\n        return (\n          <SiblingBorder key={taxonomy.slug}>\n            {taxonomy.hierarchical ? (\n              <HierarchicalTermSelector\n                taxonomy={taxonomy}\n                canCreateTerms={canCreateTerms}\n              />\n            ) : (\n              <FlatTermSelector\n                taxonomy={taxonomy}\n                canCreateTerms={canCreateTerms}\n              />\n            )}\n          </SiblingBorder>\n        );\n      })}\n    </StyledSimplePanel>\n  );\n}\n\nexport default TaxonomiesPanel;\n\nTaxonomiesPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/document/taxonomies/test/taxonomies.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport TaxonomyContext from '../../../../../app/taxonomy/context';\nimport TaxonomiesPanel from '../taxonomies';\nimport { StoryContext } from '../../../../../app/story';\n\nfunction arrange({ taxonomies, isCapable }) {\n  const storyContextValue = {\n    state: {\n      capabilities: taxonomies.reduce((acc, curr) => {\n        acc[`assign-${curr.slug}`] = isCapable;\n        acc[`create-${curr.slug}`] = isCapable;\n        return acc;\n      }, {}),\n    },\n  };\n\n  const taxonomyContextValue = {\n    state: {\n      taxonomies,\n    },\n    actions: {\n      createTerm: jest.fn(),\n      addSearchResultsToCache: jest.fn(() => new Promise((res) => res([]))),\n      setSelectedTaxonomySlugs: jest.fn(),\n    },\n  };\n\n  return renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <TaxonomyContext.Provider value={taxonomyContextValue}>\n        <TaxonomiesPanel />\n      </TaxonomyContext.Provider>\n    </StoryContext.Provider>\n  );\n}\n\ndescribe('TaxonomiesPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:taxonomies',\n      JSON.stringify({ isCollapsed: false })\n    );\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should not render Taxonomies Panel if there are no taxonomies', () => {\n    arrange({ taxonomies: [], isCapable: true });\n    const element = screen.queryByRole('button', {\n      name: 'Taxonomies',\n    });\n    expect(element).not.toBeInTheDocument();\n  });\n\n  it('should not render Taxonomies Panel if there are no visible or assignable taxonomies', () => {\n    arrange({\n      taxonomies: [\n        {\n          slug: 'web_story_tag',\n          restBase: 'web_story_tag',\n          name: 'Tags',\n          labels: {},\n          hierarchical: false,\n        },\n        {\n          slug: 'web_story_category',\n          restBase: 'web_story_category',\n          name: 'Categories',\n          labels: { notFound: '' },\n          hierarchical: false,\n        },\n      ],\n      isCapable: false,\n    });\n    const element = screen.queryByRole('button', {\n      name: 'Taxonomies',\n    });\n    expect(element).not.toBeInTheDocument();\n  });\n\n  it('should render Taxonomies Panel', async () => {\n    arrange({\n      taxonomies: [\n        {\n          slug: 'web_story_tag',\n          restBase: 'web_story_tag',\n          name: 'Tags',\n          labels: {},\n          hierarchical: false,\n          visibility: {\n            show_ui: true,\n          },\n        },\n        {\n          slug: 'web_story_category',\n          restBase: 'web_story_category',\n          name: 'Categories',\n          labels: {\n            searchItems: 'Story Categories',\n            addNewItem: 'Add New',\n            notFound: '',\n          },\n          hierarchical: true,\n          visibility: {\n            show_ui: true,\n          },\n        },\n      ],\n      isCapable: true,\n    });\n    const element = await screen.findByRole('button', {\n      name: 'Taxonomies',\n    });\n    expect(element).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const LAYER_HEIGHT = 35;\nexport const NESTED_PX = 30;\n\nexport const nestedOffsetCalcFunc = (evt) => evt.offsetY < LAYER_HEIGHT / 1.7;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/elementLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport { Icons } from '@googleforcreators/design-system';\nimport { memo, useCallback } from '@googleforcreators/react';\nimport {\n  getDefinitionForType,\n  getLayerName,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../../propTypes';\nimport { useStory } from '../../../app';\nimport useCORSProxy from '../../../utils/useCORSProxy';\nimport { TRACKING_EVENTS } from '../../../constants';\nimport useLayerSelection from './useLayerSelection';\nimport ShapeMaskWrapper from './shapeMaskWrapper';\nimport ElementLayerActions from './elementLayerActions';\nimport Layer from './layer';\n\nconst LayerIconWrapper = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  color: ${({ theme }) => theme.colors.fg.primary};\n\n  :hover {\n    background: ${({ theme }) => theme.colors.interactiveBg.tertiaryHover};\n  }\n  :hover,\n  :hover + * {\n    --background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.tertiaryHover};\n    --background-color-opaque: ${({ theme }) =>\n      rgba(theme.colors.interactiveBg.tertiaryHover, 0)};\n  }\n`;\n\nfunction ElementLayer({ element }) {\n  const layerName = getLayerName(element);\n  const { LayerIcon } = getDefinitionForType(element.type);\n  const { isSelected, handleClick } = useLayerSelection(element);\n  const { id, isDefaultBackground, isBackground, type } = element;\n  const { updateElementById, currentPageBackgroundColor, groups } = useStory(\n    ({ actions, state }) => ({\n      updateElementById: actions.updateElementById,\n      groups: state.currentPage?.groups || {},\n      currentPageBackgroundColor:\n        !isDefaultBackground || state.currentPage?.backgroundColor,\n    })\n  );\n\n  const { getProxiedUrl } = useCORSProxy();\n\n  const isNested = Boolean(element.groupId);\n\n  const group = groups[element.groupId];\n\n  const CompoundLayerIcon = useCallback(\n    () => (\n      <LayerIconWrapper>\n        <ShapeMaskWrapper element={element}>\n          <LayerIcon\n            element={element}\n            getProxiedUrl={getProxiedUrl}\n            currentPageBackgroundColor={currentPageBackgroundColor}\n          />\n        </ShapeMaskWrapper>\n      </LayerIconWrapper>\n    ),\n    [currentPageBackgroundColor, element, getProxiedUrl]\n  );\n\n  const hasLayerHiddenIcon = element.isHidden;\n  const hasLayerLockIcon = Boolean(isBackground || element.isLocked);\n  const LayerLockIcon = useCallback(\n    () =>\n      isBackground || isNested ? (\n        <Icons.LockFilledClosed />\n      ) : (\n        <Icons.LockClosed />\n      ),\n    [isBackground, isNested]\n  );\n  const LayerVisibilityIcon = () => element.isHidden && <Icons.VisibilityOff />;\n\n  return (\n    <Layer\n      id={id}\n      handleNewLayerName={(newLayerName) =>\n        updateElementById({\n          elementId: element.id,\n          properties: { layerName: newLayerName },\n        })\n      }\n      layerName={layerName}\n      handleClick={handleClick}\n      isSelected={isSelected}\n      LayerIcon={CompoundLayerIcon}\n      hasLayerLockIcon={hasLayerLockIcon}\n      hasLayerHiddenIcon={hasLayerHiddenIcon}\n      LayerLockIcon={LayerLockIcon}\n      LayerVisibilityIcon={LayerVisibilityIcon}\n      hasActions={!isBackground}\n      actions={<ElementLayerActions element={element} />}\n      isNested={isNested}\n      skipLayer={group?.isCollapsed}\n      trackingData={{ ...TRACKING_EVENTS.SELECT_ELEMENT, label: type }}\n    />\n  );\n}\n\nElementLayer.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n};\n\nexport default memo(ElementLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/elementLayerActions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport { memo, useMemo, useCallback } from '@googleforcreators/react';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../../propTypes';\nimport { useStory } from '../../../app';\nimport { TRACKING_EVENTS } from '../../../constants';\nimport useShapeMask from '../../../utils/useShapeMask';\nimport LayerAction from './layerAction';\n\nfunction ElementLayerActions({ element }) {\n  const { hasDuplicateMenu } = getDefinitionForType(element.type);\n\n  const { duplicateElementsById, updateElementById, deleteElementById } =\n    useStory(({ actions }) => ({\n      duplicateElementsById: actions.duplicateElementsById,\n      deleteElementById: actions.deleteElementById,\n      updateElementById: actions.updateElementById,\n    }));\n\n  const { hasShapeMask, removeShapeMask } = useShapeMask(element);\n  const removeMaskTitle = __('Unmask', 'web-stories');\n\n  const isNested = Boolean(element.groupId);\n  const { isLocked, isHidden } = element;\n\n  const lockTitle = useMemo(\n    () =>\n      isNested\n        ? isLocked\n          ? __('Group is Locked', 'web-stories')\n          : __('Group is Unlocked', 'web-stories')\n        : isLocked\n          ? __('Unlock Layer', 'web-stories')\n          : __('Lock Layer', 'web-stories'),\n    [isLocked, isNested]\n  );\n  const visibilityTitle = isHidden\n    ? __('Show Layer', 'web-stories')\n    : __('Hide Layer', 'web-stories');\n\n  const handleDeleteElement = useCallback(\n    () => deleteElementById({ elementId: element.id }),\n    [deleteElementById, element.id]\n  );\n\n  const handleDuplicateElement = useCallback(\n    () => duplicateElementsById({ elementIds: [element.id] }),\n    [duplicateElementsById, element.id]\n  );\n\n  const handleLockElement = useCallback(\n    () =>\n      updateElementById({\n        elementId: element.id,\n        properties: { isLocked: !isLocked },\n      }),\n    [element.id, isLocked, updateElementById]\n  );\n\n  const handleHideElement = useCallback(\n    () =>\n      updateElementById({\n        elementId: element.id,\n        properties: { isHidden: !isHidden },\n      }),\n    [element.id, isHidden, updateElementById]\n  );\n\n  const LockIcon = isLocked ? Icons.LockClosed : Icons.LockOpen;\n  const VisibilityIcon = isHidden ? Icons.VisibilityOff : Icons.Visibility;\n\n  return (\n    <>\n      <LayerAction\n        isActive={hasShapeMask}\n        label={removeMaskTitle}\n        handleClick={removeShapeMask}\n      >\n        <Icons.RemoveMask />\n      </LayerAction>\n      <LayerAction\n        label={__('Delete Layer', 'web-stories')}\n        handleClick={handleDeleteElement}\n        trackingData={{\n          ...TRACKING_EVENTS.DELETE_ELEMENT,\n          label: element.type,\n        }}\n      >\n        <Icons.Trash />\n      </LayerAction>\n      <LayerAction\n        isActive={hasDuplicateMenu}\n        label={__('Duplicate Layer', 'web-stories')}\n        handleClick={handleDuplicateElement}\n      >\n        <Icons.PagePlus />\n      </LayerAction>\n      <LayerAction label={visibilityTitle} handleClick={handleHideElement}>\n        <VisibilityIcon />\n      </LayerAction>\n      <LayerAction\n        label={lockTitle}\n        disabled={isNested}\n        handleClick={handleLockElement}\n      >\n        {isNested ? <Icons.LockFilledClosed /> : <LockIcon />}\n      </LayerAction>\n    </>\n  );\n}\n\nElementLayerActions.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n};\n\nexport default memo(ElementLayerActions);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/groupLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\nimport { memo, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useStory } from '../../../app';\nimport useGroupSelection from './useGroupSelection';\nimport GroupLayerActions from './groupLayerActions';\nimport Layer from './layer';\n\nconst GroupIconsWrapper = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  width: 48px;\n\n  svg {\n    position: relative;\n    display: block;\n    width: 100%;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n\n  /*\n  * moves the click target + positioning to the left\n  * this ensures a better click target for\n  * the arrow expand collapse state\n  */\n  transform: translateX(-12px);\n  margin-right: -12px;\n`;\n\nconst ChevronDown = styled(Icons.ChevronDown)`\n  min-width: 32px;\n  min-height: 32px;\n`;\n\nconst ChevronRight = styled(Icons.ChevronDown)`\n  /*\n  * Using ChevronDown and rotating it here\n  * vs ChevronRightSmall to keep consistent sizing between states\n  */\n  min-width: 32px;\n  min-height: 32px;\n  transform: rotate(-90deg);\n`;\n\nfunction GroupLayer({ groupId }) {\n  const { groups, updateGroupById, groupLayers } = useStory(\n    ({ actions, state }) => ({\n      groups: state.currentPage.groups,\n      updateGroupById: actions.updateGroupById,\n      groupLayers: state.currentPage.elements.filter(\n        (el) => el.groupId === groupId\n      ),\n    })\n  );\n\n  // Destructuring with default values in case groups[groupId] is undefined\n  const {\n    name = '',\n    isLocked = false,\n    isCollapsed = false,\n  } = groups?.[groupId] || {};\n\n  const { isSelected, handleClick } = useGroupSelection(groupId);\n\n  const handleGroupArrowClick = useCallback(() => {\n    updateGroupById({\n      groupId,\n      properties: { isCollapsed: !isCollapsed },\n    });\n  }, [isCollapsed, groupId, updateGroupById]);\n\n  const GroupLayerIcon = useCallback(\n    () => (\n      <GroupIconsWrapper>\n        {isCollapsed ? (\n          <ChevronRight onClick={handleGroupArrowClick} />\n        ) : (\n          <ChevronDown onClick={handleGroupArrowClick} />\n        )}\n        <Icons.Group />\n      </GroupIconsWrapper>\n    ),\n    [handleGroupArrowClick, isCollapsed]\n  );\n\n  const allLayersHidden = groupLayers.every((layer) => layer.isHidden);\n  const LayerVisibilityIcon = () => allLayersHidden && <Icons.VisibilityOff />;\n\n  return (\n    <Layer\n      id={groupId}\n      handleNewLayerName={(newLayerName) =>\n        updateGroupById({\n          groupId,\n          properties: {\n            name: newLayerName,\n          },\n        })\n      }\n      layerName={name}\n      handleClick={handleClick}\n      hasLayerHiddenIcon={allLayersHidden}\n      isSelected={isSelected}\n      LayerIcon={GroupLayerIcon}\n      LayerVisibilityIcon={LayerVisibilityIcon}\n      hasLayerLockIcon={isLocked}\n      LayerLockIcon={Icons.LockClosed}\n      actions={<GroupLayerActions groupId={groupId} />}\n    />\n  );\n}\n\nGroupLayer.propTypes = {\n  groupId: PropTypes.string.isRequired,\n};\n\nexport default memo(GroupLayer);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/groupLayerActions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\nimport { memo, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useStory } from '../../../app';\nimport generateGroupName from '../../../utils/generateGroupName';\nimport LayerAction from './layerAction';\n\nfunction GroupLayerActions({ groupId }) {\n  const {\n    groups,\n    updateGroupById,\n    deleteGroupAndElementsById,\n    updateElementsById,\n    duplicateGroupById,\n    groupLayers,\n  } = useStory(({ actions, state }) => ({\n    groups: state.currentPage.groups,\n    updateGroupById: actions.updateGroupById,\n    deleteGroupAndElementsById: actions.deleteGroupAndElementsById,\n    updateElementsById: actions.updateElementsById,\n    duplicateGroupById: actions.duplicateGroupById,\n    groupLayers: state.currentPage.elements.filter(\n      (el) => el.groupId === groupId\n    ),\n  }));\n\n  const group = groups?.[groupId] || {\n    name: '',\n    isLocked: false,\n    isCollapsed: false,\n  };\n\n  const allLayersHidden = groupLayers.every((layer) => layer.isHidden);\n\n  const visibilityTitle = allLayersHidden\n    ? __('Show Group', 'web-stories')\n    : __('Hide Group', 'web-stories');\n  const lockTitle = group.isLocked\n    ? __('Unlock Group', 'web-stories')\n    : __('Lock Group', 'web-stories');\n\n  const { name, isLocked, isCollapsed } = group;\n\n  const handleHideGroup = useCallback(() => {\n    updateElementsById({\n      elementIds: groupLayers.map((layer) => layer.id),\n      properties: { isHidden: !allLayersHidden },\n    });\n  }, [allLayersHidden, groupLayers, updateElementsById]);\n\n  const handleLockGroup = useCallback(() => {\n    updateGroupById({\n      groupId,\n      properties: { isLocked: !isLocked },\n    });\n    updateElementsById({\n      elementIds: groupLayers.map((layer) => layer.id),\n      properties: { isLocked: !isLocked },\n    });\n  }, [groupId, groupLayers, isLocked, updateElementsById, updateGroupById]);\n\n  const handleDuplicateGroup = useCallback(() => {\n    const newGroupId = uuidv4();\n    const newGroupName = generateGroupName(groups, name);\n    duplicateGroupById({\n      oldGroupId: groupId,\n      groupId: newGroupId,\n      name: newGroupName,\n      isLocked: isLocked,\n      isCollapsed: isCollapsed,\n    });\n  }, [duplicateGroupById, name, isLocked, isCollapsed, groupId, groups]);\n\n  const handleDeleteGroup = useCallback(\n    () => deleteGroupAndElementsById({ groupId }),\n    [groupId, deleteGroupAndElementsById]\n  );\n\n  const VisibilityIcon = allLayersHidden\n    ? Icons.VisibilityOff\n    : Icons.Visibility;\n\n  return (\n    <>\n      <LayerAction\n        label={__('Delete Group', 'web-stories')}\n        handleClick={handleDeleteGroup}\n      >\n        <Icons.Trash />\n      </LayerAction>\n\n      <LayerAction\n        label={__('Duplicate Group', 'web-stories')}\n        handleClick={handleDuplicateGroup}\n      >\n        <Icons.PagePlus />\n      </LayerAction>\n\n      <LayerAction label={visibilityTitle} handleClick={handleHideGroup}>\n        <VisibilityIcon />\n      </LayerAction>\n\n      <LayerAction label={lockTitle} handleClick={handleLockGroup}>\n        {isLocked ? <Icons.LockClosed /> : <Icons.LockOpen />}\n      </LayerAction>\n    </>\n  );\n}\n\nGroupLayerActions.propTypes = {\n  groupId: PropTypes.string.isRequired,\n};\n\nexport default memo(GroupLayerActions);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as LayerPanel } from './layerPanel';\nexport { default as useLayers } from './useLayers';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/karma/layer.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { within } from '@testing-library/react';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../../karma';\nimport { useInsertElement } from '../../../canvas';\nimport { useStory } from '../../../../app/story';\n\ndescribe('Layer Panel', () => {\n  let fixture;\n  let layerPanel;\n  let insertElement;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    layerPanel = fixture.editor.footer.layerPanel;\n    await fixture.events.click(layerPanel.togglePanel);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n\n    insertElement = await fixture.renderHook(() => useInsertElement());\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should show the number of layers', async () => {\n    expect(layerPanel.layers.length).toBe(1);\n    expect(layerPanel.togglePanel.textContent).toBe('Layers1');\n\n    await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content:\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur tincidunt egestas velit quis tincidunt.',\n        x: 40,\n        y: 40,\n        width: 250,\n      })\n    );\n\n    expect(layerPanel.layers.length).toBe(2);\n    expect(layerPanel.togglePanel.textContent).toBe('Layers2');\n\n    await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: 'Doo doo doo',\n        x: 40,\n        y: 40,\n        width: 250,\n      })\n    );\n\n    expect(layerPanel.layers.length).toBe(3);\n    expect(layerPanel.togglePanel.textContent).toBe('Layers3');\n  });\n\n  it('should show ellipsis for overflowing text', async () => {\n    expect(layerPanel.layers.length).toBe(1);\n    await fixture.act(() =>\n      insertElement('text', {\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content:\n          'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur tincidunt egestas velit quis tincidunt.',\n        x: 40,\n        y: 40,\n        width: 250,\n      })\n    );\n\n    expect(layerPanel.layers.length).toBe(2);\n\n    await fixture.snapshot();\n  });\n\n  it('should be able to delete elements with delete action', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n    // Select background for being able to insert another text.\n    const bgLayer = layerPanel.getLayerByInnerText('Background');\n    await fixture.events.click(bgLayer);\n    await fixture.events.click(fixture.editor.library.text.preset('Title 2'));\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    expect(layerPanel.layers.length).toBe(3);\n    const elementALayer = layerPanel.getLayerByInnerText('Title 1');\n    await fixture.events.hover(elementALayer);\n    const deleteElementAButton = within(elementALayer).getByLabelText(/Delete/);\n    await fixture.events.click(deleteElementAButton);\n\n    expect(layerPanel.layers.length).toBe(2);\n    expect(\n      layerPanel.layers.every((layer) => layer.innerText !== 'Title 1')\n    ).toBeTrue();\n  });\n\n  it('should be able to rename a layer by clicking Enter', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n\n    const titleLayer = layerPanel.getLayerByInnerText('Title 1');\n\n    await fixture.events.click(titleLayer, { clickCount: 2 });\n    await fixture.events.keyboard.type('New Title Name');\n    await fixture.events.keyboard.press('Enter');\n\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'New Title Name')\n        ?.length\n    ).toBe(1);\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'Title 1')?.length\n    ).toBe(0);\n  });\n\n  it('should be able to rename a layer on blur (e.g. clicking on another layer)', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n\n    const titleLayer = layerPanel.getLayerByInnerText('Title 1');\n\n    await fixture.events.click(titleLayer, { clickCount: 2 });\n    await fixture.events.keyboard.type('New Title Name');\n\n    const bgLayer = layerPanel.getLayerByInnerText('Background');\n\n    await fixture.events.click(bgLayer);\n\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'New Title Name')\n        ?.length\n    ).toBe(1);\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'Title 1')?.length\n    ).toBe(0);\n  });\n\n  it('should be able to exit renaming a layer by clicking Esc', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n\n    const titleLayer = layerPanel.getLayerByInnerText('Title 1');\n\n    await fixture.events.click(titleLayer, { clickCount: 2 });\n    await fixture.events.keyboard.type('New Title Name');\n    await fixture.events.keyboard.press('Esc');\n\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'New Title Name')\n        ?.length\n    ).toBe(0);\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'Title 1')?.length\n    ).toBe(1);\n  });\n\n  it('should be able to duplicate elements with duplicate action', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n    // Select background for being able to insert another text.\n    const bgLayer = layerPanel.getLayerByInnerText('Background');\n    await fixture.events.click(bgLayer);\n    await fixture.events.click(fixture.editor.library.text.preset('Title 2'));\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    expect(layerPanel.layers.length).toBe(3);\n    const elementALayer = layerPanel.getLayerByInnerText('Title 1');\n    await fixture.events.hover(elementALayer);\n    const duplicateElementAButton =\n      within(elementALayer).getByLabelText(/Duplicate/);\n    await fixture.events.click(duplicateElementAButton);\n\n    expect(layerPanel.layers.length).toBe(4);\n    expect(\n      layerPanel.layers.filter((layer) => layer.innerText === 'Title 1')?.length\n    ).toBe(2);\n  });\n\n  it('should be able to hide and show elements with hide/show action', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n    // Select background for being able to insert another text.\n    const bgLayer = layerPanel.getLayerByInnerText('Background');\n    await fixture.events.click(bgLayer);\n    await fixture.events.click(fixture.editor.library.text.preset('Title 2'));\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    expect(layerPanel.layers.length).toBe(3);\n    const elementALayer = layerPanel.getLayerByInnerText('Title 1');\n    const elementBLayer = layerPanel.getLayerByInnerText('Title 2');\n\n    let visibleCanvasElements = fixture.querySelectorAll(\n      `[data-testid=\"DisplayLayer\"] [data-element-id]`\n    );\n    expect(visibleCanvasElements.length).toBe(3);\n\n    // Hover layer, hide it, and hover somewhere else\n    await fixture.events.hover(elementALayer);\n    const hideButton = within(elementALayer).getByLabelText(/Hide/);\n    await fixture.events.click(hideButton);\n    await fixture.events.hover(elementBLayer);\n\n    visibleCanvasElements = fixture.querySelectorAll(\n      `[data-testid=\"DisplayLayer\"] [data-element-id]`\n    );\n    expect(visibleCanvasElements.length).toBe(2);\n\n    // Hover layer, disable lock, and hover somewhere else\n    await fixture.events.hover(elementALayer);\n    const showButton = within(elementALayer).getByLabelText(/Show/);\n    await fixture.events.click(showButton);\n    await fixture.events.hover(elementBLayer);\n    visibleCanvasElements = fixture.querySelectorAll(\n      `[data-testid=\"DisplayLayer\"] [data-element-id]`\n    );\n    expect(visibleCanvasElements.length).toBe(3);\n  });\n\n  it('should be able to lock and unlock elements with lock action', async () => {\n    await fixture.events.click(fixture.editor.sidebar.insertTab);\n    await fixture.editor.library.textTab.click();\n    await fixture.events.click(fixture.editor.library.text.preset('Title 1'));\n    // Select background for being able to insert another text.\n    const bgLayer = layerPanel.getLayerByInnerText('Background');\n    await fixture.events.click(bgLayer);\n    await fixture.events.click(fixture.editor.library.text.preset('Title 2'));\n\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    expect(layerPanel.layers.length).toBe(3);\n    const elementALayer = layerPanel.getLayerByInnerText('Title 1');\n    const elementBLayer = layerPanel.getLayerByInnerText('Title 2');\n\n    // Hover layer, enable lock, and hover somewhere else\n    await fixture.events.hover(elementALayer);\n    const lockButton = within(elementALayer).getByLabelText(/Lock/);\n    await fixture.events.click(lockButton);\n    await fixture.events.hover(elementBLayer);\n\n    // Check that lock is now permanently displayed and the element actually has a lock\n    const lockIcon = within(elementALayer).queryByLabelText('Locked');\n    expect(lockIcon).toBeDefined();\n    const elementsAfterLocking = await getElements();\n    const title1AfterLocking = elementsAfterLocking.find(({ content }) =>\n      content?.includes('Title 1')\n    );\n    expect(title1AfterLocking.isLocked).toBe(true);\n\n    // Hover layer, disable lock, and hover somewhere else\n    await fixture.events.hover(elementALayer);\n    const unlockButton = within(elementALayer).getByLabelText(/Unlock/);\n    await fixture.events.click(unlockButton);\n    await fixture.events.hover(elementBLayer);\n\n    // Check that lock is now permanently displayed and the element actually has a lock\n    const noLockIcon = within(elementALayer).queryByLabelText('Locked');\n    expect(noLockIcon).toBe(null);\n    const elementsAfterUnlocking = await getElements();\n    const title1AfterUnlocking = elementsAfterUnlocking.find(({ content }) =>\n      content?.includes('Title 1')\n    );\n    expect(title1AfterUnlocking.isLocked).not.toBe(true);\n  });\n\n  async function getElements() {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  }\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useRef, memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas } from '../../../app';\nimport usePerformanceTracking from '../../../utils/usePerformanceTracking';\nimport LayerIdContext from './layerIdContext';\nimport LayerForm from './layerForm';\nimport {\n  ActionsContainer,\n  LayerContainer,\n  LayerButton,\n  LayerInputWrapper,\n  LayerDescription,\n  LayerText,\n  IconWrapper,\n  LayerContentContainer,\n  HiddenIconWrapper,\n  LayerIconWrapper,\n  FadeOutWrapper,\n} from './layerComponents.js';\n\nfunction Layer({\n  id,\n  handleNewLayerName,\n  layerName,\n  handleClick,\n  isSelected,\n  LayerIcon,\n  hasLayerLockIcon,\n  hasLayerHiddenIcon,\n  LayerLockIcon,\n  LayerVisibilityIcon,\n  actions,\n  hasActions = true,\n  isNested = false,\n  skipLayer = false,\n  trackingData = null,\n}) {\n  const renamableLayer = useCanvas(({ state }) => state.renamableLayer);\n\n  const layerRef = useRef(null);\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: trackingData ? layerRef.current : null,\n    eventData: trackingData,\n  });\n\n  if (skipLayer) {\n    return null;\n  }\n\n  const layerId = `layer-${id}`;\n  const isRenameable = renamableLayer?.elementId === id;\n\n  return (\n    <LayerContainer>\n      {isRenameable ? (\n        <LayerInputWrapper isNested={isNested}>\n          <LayerIcon />\n          <LayerForm\n            handleNewLayerName={handleNewLayerName}\n            layerName={layerName}\n          />\n        </LayerInputWrapper>\n      ) : (\n        <LayerIdContext.Provider value={layerId}>\n          <LayerButton\n            ref={layerRef}\n            id={layerId}\n            onClick={handleClick}\n            isSelected={isSelected}\n            isNested={isNested}\n          >\n            <LayerIconWrapper isHidden={hasLayerHiddenIcon}>\n              <LayerIcon />\n            </LayerIconWrapper>\n            <LayerDescription>\n              <LayerContentContainer>\n                <LayerText isHidden={hasLayerHiddenIcon}>{layerName}</LayerText>\n              </LayerContentContainer>\n              {(hasLayerHiddenIcon || hasLayerLockIcon) && (\n                <FadeOutWrapper>\n                  {hasLayerHiddenIcon && (\n                    <HiddenIconWrapper>\n                      {hasLayerHiddenIcon && <LayerVisibilityIcon />}\n                    </HiddenIconWrapper>\n                  )}\n                  {(hasLayerHiddenIcon || hasLayerLockIcon) && (\n                    <IconWrapper>\n                      {hasLayerLockIcon && <LayerLockIcon />}\n                    </IconWrapper>\n                  )}\n                </FadeOutWrapper>\n              )}\n            </LayerDescription>\n          </LayerButton>\n          {hasActions && <ActionsContainer>{actions}</ActionsContainer>}\n        </LayerIdContext.Provider>\n      )}\n    </LayerContainer>\n  );\n}\n\nLayer.propTypes = {\n  id: PropTypes.string.isRequired,\n  handleNewLayerName: PropTypes.func.isRequired,\n  layerName: PropTypes.string.isRequired,\n  handleClick: PropTypes.func.isRequired,\n  isSelected: PropTypes.bool.isRequired,\n  LayerIcon: PropTypes.elementType.isRequired,\n  LayerVisibilityIcon: PropTypes.elementType.isRequired,\n  hasLayerLockIcon: PropTypes.bool,\n  hasLayerHiddenIcon: PropTypes.bool,\n  LayerLockIcon: PropTypes.elementType.isRequired,\n  actions: PropTypes.object.isRequired,\n  hasActions: PropTypes.bool,\n  isNested: PropTypes.bool,\n  skipLayer: PropTypes.bool,\n  trackingData: PropTypes.object,\n};\n\nexport default memo(Layer);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerAction.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonType,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { useRef, memo, useContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport usePerformanceTracking from '../../../utils/usePerformanceTracking';\nimport Tooltip from '../../tooltip';\nimport LayerIdContext from './layerIdContext';\n\nconst ActionButton = styled(Button).attrs({\n  type: ButtonType.Plain,\n  tabIndex: -1,\n})`\n  position: relative;\n  aspect-ratio: 1;\n  width: 20px;\n  padding: 0;\n\n  /*\n   * all of our Icons right now have an embedded padding,\n   * however the new designs just disregard this embedded\n   * padding, so to accommodate, we'll make the icon its\n   * intended size and manually center it within the button.\n   */\n  svg {\n    position: absolute;\n    width: 32px;\n    height: auto;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n  }\n\n  /*\n   * override base button background color so we can receive the\n   * proper background color from the parent.\n   */\n  && {\n    transition: revert;\n    background: var(--background-color);\n  }\n\n  :disabled {\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n\n  :hover {\n    color: var(\n      --selected-hover-color,\n      ${({ theme }) => theme.colors.fg.secondary}\n    );\n  }\n\n  & + & {\n    margin-left: 4px;\n  }\n\n  * {\n    pointer-events: none;\n  }\n\n  :focus {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        'var(--background-color)'\n      )}\n  }\n`;\n\nfunction preventReorder(e) {\n  e.stopPropagation();\n  e.preventDefault();\n}\n\nfunction LayerAction({\n  label,\n  handleClick,\n  children,\n  disabled = false,\n  isActive = true,\n  trackingData = null,\n}) {\n  const buttonRef = useRef(null);\n  usePerformanceTracking({\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    node: trackingData ? buttonRef.current : null,\n    eventData: trackingData,\n  });\n\n  const layerId = useContext(LayerIdContext);\n\n  if (!isActive) {\n    return null;\n  }\n\n  return (\n    <Tooltip title={label} hasTail isDelayed>\n      <ActionButton\n        aria-label={label}\n        aria-describedby={layerId}\n        onPointerDown={preventReorder}\n        disabled={disabled}\n        onClick={handleClick}\n        ref={buttonRef}\n      >\n        {children}\n      </ActionButton>\n    </Tooltip>\n  );\n}\n\nLayerAction.propTypes = {\n  label: PropTypes.string.isRequired,\n  handleClick: PropTypes.func.isRequired,\n  children: PropTypes.node.isRequired,\n  disabled: PropTypes.bool,\n  isActive: PropTypes.bool,\n  trackingData: PropTypes.object,\n};\n\nexport default memo(LayerAction);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerComponents.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { rgba } from 'polished';\nimport {\n  Button,\n  ButtonType,\n  Input,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { LAYER_HEIGHT, NESTED_PX } from './constants';\n\nconst fadeOutCss = css`\n  background-color: var(--background-color);\n\n  ::before {\n    position: absolute;\n    content: '';\n    width: 32px;\n    height: 100%;\n    top: 0;\n    left: 0;\n    transform: translateX(-100%);\n    background: linear-gradient(\n      to right,\n      var(--background-color-opaque),\n      var(--background-color)\n    );\n    pointer-events: none;\n  }\n`;\n\nexport const ActionsContainer = styled.div`\n  position: absolute;\n  display: none;\n  align-items: center;\n  height: 100%;\n  top: 0;\n  right: 0;\n  padding-right: 6px;\n  column-gap: 6px;\n\n  ${fadeOutCss}\n`;\n\nexport const LayerContainer = styled.div.attrs({\n  // Because the layer panel is aria-hidden, we need something else to select by\n  'data-testid': 'layer-option',\n})`\n  position: relative;\n  height: ${LAYER_HEIGHT}px;\n  width: 100%;\n  overflow: hidden;\n\n  --background-color: ${({ theme }) => theme.colors.bg.secondary};\n  --background-color-opaque: ${({ theme }) =>\n    rgba(theme.colors.bg.secondary, 0)};\n\n  :is(:hover, :focus-within) ${ActionsContainer} {\n    display: inline-flex;\n  }\n`;\n\nexport const LayerButton = styled(Button).attrs({\n  type: ButtonType.Plain,\n  tabIndex: -1,\n  role: 'option',\n})`\n  position: relative;\n  display: grid;\n  grid-template-columns: auto 1fr;\n  gap: 12px;\n\n  border: 0;\n  padding: 0;\n  background: transparent;\n  height: 100%;\n  width: 100%;\n  overflow: hidden;\n  align-items: center;\n  user-select: none;\n  border-radius: 0;\n  padding-left: ${({ isNested }) => (isNested ? NESTED_PX : 12)}px;\n  transition: revert;\n\n  ${({ isSelected, theme }) =>\n    isSelected &&\n    css`\n      background: ${theme.colors.interactiveBg.tertiaryPress};\n      &,\n      & + * {\n        --background-color: ${theme.colors.interactiveBg.tertiaryPress};\n        --background-color-opaque: ${rgba(\n          theme.colors.interactiveBg.tertiaryPress,\n          0\n        )};\n        --selected-hover-color: ${theme.colors.interactiveBg.tertiaryHover};\n      }\n    `}\n\n  :hover {\n    background: ${({ theme }) => theme.colors.interactiveBg.tertiaryHover};\n  }\n  :hover,\n  :hover + * {\n    --background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.tertiaryHover};\n    --background-color-opaque: ${({ theme }) =>\n      rgba(theme.colors.interactiveBg.tertiaryHover, 0)};\n  }\n\n  :active {\n    background: ${({ theme }) => theme.colors.interactiveBg.tertiaryPress};\n  }\n  :active,\n  :active + * {\n    --background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.tertiaryPress};\n    --background-color-opaque: ${({ theme }) =>\n      rgba(theme.colors.interactiveBg.tertiaryPress, 0)};\n  }\n`;\n\nexport const LayerInputWrapper = styled.div`\n  display: grid;\n  grid-template-columns: 23px 1fr;\n  gap: 12px;\n  height: 100%;\n  width: 100%;\n  padding-left: ${({ isNested }) => (isNested ? NESTED_PX : 12)}px;\n  padding-right: 10px;\n\n  :hover {\n    background: ${({ theme }) => theme.colors.interactiveBg.tertiaryHover};\n  }\n  :hover,\n  :hover + * {\n    --background-color: ${({ theme }) =>\n      theme.colors.interactiveBg.tertiaryHover};\n    --background-color-opaque: ${({ theme }) =>\n      rgba(theme.colors.interactiveBg.tertiaryHover, 0)};\n  }\n`;\n\nexport const LayerDescription = styled.div`\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n  display: flex;\n  align-items: center;\n  margin-left: 0;\n  text-align: left;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nexport const LayerText = styled(Text.Span).attrs({\n  size: TextSize.Small,\n})`\n  color: inherit;\n  white-space: nowrap;\n  text-overflow: ' ';\n  overflow: hidden;\n  max-width: 100%;\n  ${({ isHidden }) =>\n    isHidden &&\n    css`\n      opacity: 0.3;\n    `};\n`;\n\nexport const LayerIconWrapper = styled.div`\n  ${({ isHidden }) =>\n    isHidden &&\n    css`\n      opacity: 0.3;\n    `};\n`;\n\nexport const FadeOutWrapper = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  position: absolute;\n  right: 0;\n  aspect-ratio: 1;\n  ${fadeOutCss}\n`;\n\nexport const IconWrapper = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n  width: 32px;\n  aspect-ratio: 1;\n  svg {\n    position: relative;\n    display: block;\n    width: 100%;\n    color: ${({ theme }) => theme.colors.fg.secondary};\n  }\n`;\nexport const HiddenIconWrapper = styled(IconWrapper)`\n  margin-right: -6px;\n`;\n\nexport const LayerContentContainer = styled.div`\n  margin-right: 8px;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n`;\n\nexport const LayerInput = styled(Input)`\n  overflow: visible;\n\n  div {\n    height: 100%;\n  }\n`;\n\nexport const LayerInputForm = styled(LayerDescription).attrs({ as: 'form' })`\n  overflow: visible;\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerForm.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { memo, useState, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas } from '../../../app';\nimport { LayerInputForm, LayerInput } from './layerComponents';\n\n// We need to prevent the pointer-down event from propagating to the\n// reorderable when you click on the input. If not, the reorderable will\n// move focus, which will blur the input, which will cancel renaming.\nconst stopPropagation = (evt) => evt.stopPropagation();\n\nfunction LayerForm({ layerName, handleNewLayerName }) {\n  const [newLayerName, setNewLayerName] = useState(layerName);\n\n  const setRenamableLayer = useCanvas(\n    ({ actions }) => actions.setRenamableLayer\n  );\n\n  useEffect(() => {\n    setNewLayerName(layerName);\n  }, [layerName]);\n\n  const handleChange = (evt) => {\n    setNewLayerName(evt.target.value);\n  };\n\n  const handleKeyDown = (evt) => {\n    if (evt.key === 'Escape') {\n      setNewLayerName(layerName);\n      setRenamableLayer(null);\n    }\n  };\n\n  const updateLayerName = () => {\n    setRenamableLayer(null);\n    const trimmedLayerName = newLayerName.trim();\n    // Only update name if trimmed layer name is not empty.\n    if (trimmedLayerName) {\n      handleNewLayerName(trimmedLayerName);\n    }\n  };\n\n  const handleSubmit = (evt) => {\n    evt.preventDefault();\n    updateLayerName();\n  };\n\n  return (\n    <LayerInputForm onSubmit={handleSubmit}>\n      <LayerInput\n        tabIndex={-1}\n        aria-label={__('Layer Name', 'web-stories')}\n        value={newLayerName}\n        onChange={handleChange}\n        onKeyDown={handleKeyDown}\n        onBlur={updateLayerName}\n        onPointerDown={stopPropagation}\n        hasFocus\n      />\n      <button hidden />\n    </LayerInputForm>\n  );\n}\n\nLayerForm.propTypes = {\n  layerName: PropTypes.string.isRequired,\n  handleNewLayerName: PropTypes.func.isRequired,\n};\n\nexport default memo(LayerForm);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerIdContext.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext('');\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerList.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Reorderable } from '../../reorderable';\nimport { useRightClickMenu } from '../../../app';\nimport { LAYER_HEIGHT } from './constants';\nimport ReorderableLayer from './reorderableLayer';\nimport useLayers from './useLayers';\n\nconst ReorderableLayerList = styled(Reorderable).attrs({\n  'aria-orientation': 'vertical',\n  'aria-label': __('Layers List', 'web-stories'),\n})`\n  flex-direction: column;\n  width: 100%;\n  height: 100%;\n  align-items: stretch;\n  user-select: ${({ hasUserSelect }) => (hasUserSelect ? 'none' : 'initial')};\n  overflow-y: auto;\n  padding-bottom: 4px; /* for when panel has scroll */\n`;\n\nfunction LayerList() {\n  const onOpenMenu = useRightClickMenu((value) => value.onOpenMenu);\n\n  // This is a list of elements and groups in the order they're displayed\n  const { layers, handleDragPosition } = useLayers();\n\n  if (layers.length === 0) {\n    return null;\n  }\n\n  return (\n    <ReorderableLayerList\n      onContextMenu={onOpenMenu}\n      onPositionChange={handleDragPosition}\n      mode={'vertical'}\n      getItemSize={() => LAYER_HEIGHT}\n    >\n      {layers.map((layer) => (\n        <ReorderableLayer key={layer.id} {...layer} />\n      ))}\n    </ReorderableLayerList>\n  );\n}\n\nexport default LayerList;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/layerPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { PanelContent } from '../panel';\nimport useSidebar from '../../sidebar/useSidebar';\nimport LayerList from './layerList';\n\nconst Container = styled.div`\n  filter: drop-shadow(0px -4px 8px rgba(0, 0, 0, 0.2));\n  max-height: ${({ maxHeight }) => maxHeight}px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n`;\n\nfunction LayerPanel() {\n  const sidebarContentHeight = useSidebar(\n    ({ state }) => state.sidebarContentHeight\n  );\n\n  return (\n    <Container maxHeight={sidebarContentHeight}>\n      <PanelContent padding=\"0\">\n        <LayerList />\n      </PanelContent>\n    </Container>\n  );\n}\n\nexport default memo(LayerPanel);\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/reorderableElementLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Fragment, memo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { ReorderableSeparator, ReorderableItem } from '../../reorderable';\nimport { useStory } from '../../../app';\nimport { LAYER_HEIGHT } from './constants';\nimport ElementLayer from './elementLayer';\n\nconst LayerSeparator = styled(ReorderableSeparator)`\n  height: ${LAYER_HEIGHT}px;\n  margin: -${LAYER_HEIGHT / 2}px 0;\n  padding: ${LAYER_HEIGHT / 2}px 0;\n`;\n\nconst ReorderableLayer = memo(function ReorderableLayer({\n  id,\n  position,\n  nestedOffset,\n  nestedOffsetCalcFunc,\n  handleStartReordering,\n}) {\n  const element = useStory(({ state }) =>\n    state.currentPage?.elements.find((el) => el.id === id)\n  );\n  return element ? (\n    <Fragment key={id}>\n      <LayerSeparator\n        groupId={element.groupId}\n        nestedOffset={Boolean(nestedOffset)}\n        nestedOffsetCalcFunc={nestedOffsetCalcFunc}\n        position={position + 1}\n        isNested={element.groupId}\n      />\n      <ReorderableItem\n        position={position}\n        onStartReordering={handleStartReordering(element)}\n        disabled={element.isBackground}\n      >\n        <ElementLayer element={element} />\n      </ReorderableItem>\n    </Fragment>\n  ) : null;\n});\n\nReorderableLayer.propTypes = {\n  id: PropTypes.string.isRequired,\n  position: PropTypes.number.isRequired,\n  handleStartReordering: PropTypes.func.isRequired,\n};\n\nexport default ReorderableLayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/reorderableGroupLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { memo } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { ReorderableSeparator, ReorderableItem } from '../../reorderable';\nimport { LAYER_HEIGHT } from './constants';\nimport GroupLayer from './groupLayer';\n\nconst LayerSeparator = styled(ReorderableSeparator)`\n  height: ${LAYER_HEIGHT}px;\n  margin: -${LAYER_HEIGHT / 2}px 0;\n  padding: ${LAYER_HEIGHT / 2}px 0;\n`;\n\nconst ReorderableGroup = memo(function ReorderableGroup({\n  id,\n  position,\n  handleStartReordering,\n}) {\n  // This is counterintuitive but the top separator is outside of the group header.\n  const separatorGroupId = null;\n  return (\n    <>\n      <LayerSeparator groupId={separatorGroupId} position={position + 1} />\n      <ReorderableItem\n        position={position}\n        data={{ group: id }}\n        onStartReordering={handleStartReordering({ id })}\n      >\n        <GroupLayer groupId={id} />\n      </ReorderableItem>\n    </>\n  );\n});\n\nReorderableGroup.propTypes = {\n  id: PropTypes.string.isRequired,\n  name: PropTypes.string.isRequired,\n  position: PropTypes.number.isRequired,\n  handleStartReordering: PropTypes.func.isRequired,\n};\n\nexport default ReorderableGroup;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/reorderableLayer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../../app';\nimport useFocusCanvas from '../../canvas/useFocusCanvas';\nimport { nestedOffsetCalcFunc } from './constants';\nimport ReorderableGroupLayer from './reorderableGroupLayer';\nimport ReorderableElementLayer from './reorderableElementLayer';\n\nfunction ReorderableElement({\n  isGroup,\n  isFirstElementAfterGroup = false,\n  ...rest\n}) {\n  const setSelectedElementsById = useStory(\n    ({ actions }) => actions.setSelectedElementsById\n  );\n  const focusCanvas = useFocusCanvas();\n  const renamableLayer = useCanvas(({ state }) => state.renamableLayer);\n\n  const handleStartReordering = useCallback(\n    (element) => () => {\n      setSelectedElementsById({ elementIds: [element.id] });\n\n      if (renamableLayer) {\n        focusCanvas();\n      }\n    },\n    [setSelectedElementsById, focusCanvas, renamableLayer]\n  );\n\n  const props = { ...rest, handleStartReordering };\n\n  if (isGroup) {\n    return <ReorderableGroupLayer {...props} />;\n  }\n  return (\n    <ReorderableElementLayer\n      nestedOffset={isFirstElementAfterGroup}\n      nestedOffsetCalcFunc={nestedOffsetCalcFunc}\n      {...props}\n    />\n  );\n}\n\nReorderableElement.propTypes = {\n  isGroup: PropTypes.bool.isRequired,\n  isFirstElementAfterGroup: PropTypes.bool,\n};\n\nexport default ReorderableElement;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/shapeMaskWrapper.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { generateMaskId } from '@googleforcreators/masks';\n/**\n * Internal dependencies\n */\nimport useShapeMask from '../../../utils/useShapeMask';\nimport { StoryPropTypes } from '../../../propTypes';\n\nconst MaskedIconWrapper = styled.div`\n  position: relative;\n  clip-path: url(#${({ maskId }) => maskId});\n`;\n\nfunction ShapeMaskWrapper({ element, children }) {\n  const { hasShapeMask } = useShapeMask(element);\n\n  if (!hasShapeMask) {\n    return children;\n  }\n\n  return (\n    <MaskedIconWrapper maskId={generateMaskId(element, 'frame')}>\n      {children}\n    </MaskedIconWrapper>\n  );\n}\n\nexport default ShapeMaskWrapper;\nShapeMaskWrapper.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n  children: PropTypes.node.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/useGroupSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../../app';\n\nfunction useGroupSelection(groupId) {\n  const { toggleLayer, groupLayers, selectedElementIds } = useStory(\n    ({ state, actions }) => ({\n      groupLayers: state.currentPage.elements.filter(\n        (el) => el.groupId === groupId\n      ),\n      selectedElementIds: state.selectedElementIds,\n      toggleLayer: actions.toggleLayer,\n    })\n  );\n  const setRenamableLayer = useCanvas(\n    ({ actions }) => actions.setRenamableLayer\n  );\n\n  const isSelected = groupLayers.every((gl) =>\n    selectedElementIds.includes(gl.id)\n  );\n\n  const handleClick = useCallback(\n    (evt) => {\n      evt.preventDefault();\n      evt.stopPropagation();\n\n      // Utilize the withLinked option and use only first layer id\n      toggleLayer({\n        elementId: groupLayers[0].id,\n        metaKey: evt.metaKey,\n        shiftKey: evt.shiftKey,\n        withLinked: true,\n      });\n\n      const isDoubleClick = evt.detail === 2;\n      if (isDoubleClick) {\n        setRenamableLayer({ elementId: groupId });\n      }\n    },\n    [toggleLayer, groupLayers, setRenamableLayer, groupId]\n  );\n\n  return { isSelected, handleClick };\n}\nexport default useGroupSelection;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/useLayerSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory, useCanvas } from '../../../app';\n\nfunction useLayerSelection(layer) {\n  const { id: elementId } = layer;\n  const { isSelected, toggleLayer } = useStory(({ state, actions }) => ({\n    isSelected: state.selectedElementIds.includes(elementId),\n    toggleLayer: actions.toggleLayer,\n  }));\n  const setRenamableLayer = useCanvas(\n    ({ actions }) => actions.setRenamableLayer\n  );\n\n  const handleClick = useCallback(\n    (evt) => {\n      evt.preventDefault();\n      evt.stopPropagation();\n\n      toggleLayer({\n        elementId,\n        metaKey: evt.metaKey,\n        shiftKey: evt.shiftKey,\n        withLinked: false,\n      });\n\n      const isDoubleClick = evt.detail === 2;\n      if (isDoubleClick) {\n        setRenamableLayer({ elementId: elementId });\n      }\n    },\n    [toggleLayer, elementId, setRenamableLayer]\n  );\n\n  return { isSelected, handleClick };\n}\nexport default useLayerSelection;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/layer/useLayers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { nestedOffsetCalcFunc } from './constants';\n\nfunction useLayers() {\n  const { elements, arrangeElement, arrangeGroup } = useStory(\n    ({ state, actions }) => ({\n      elements: state.currentPage?.elements || [],\n      arrangeElement: actions.arrangeElement,\n      arrangeGroup: actions.arrangeGroup,\n    })\n  );\n  const elementLayers = useMemo(\n    () =>\n      elements.map(({ id, groupId, layerName }, position) => ({\n        id,\n        groupId,\n        layerName,\n        position,\n      })),\n    [elements]\n  );\n  elementLayers.reverse();\n\n  // This is a list of elements and groups in the order they're displayed\n  const layers = useMemo(() => {\n    const groupIds = new Set();\n    return (\n      elementLayers\n        // If an element has a new group, add both group and element\n        .flatMap((element, index, list) => {\n          const elementLayer = {\n            isGroup: false,\n            isFirstElementAfterGroup:\n              index > 0 && Boolean(list[index - 1].groupId),\n            id: element.id,\n            position: element.position,\n          };\n          const isGroup = element.groupId && !groupIds.has(element.groupId);\n          if (!isGroup) {\n            return elementLayer;\n          }\n          groupIds.add(element.groupId);\n          const groupLayer = {\n            isGroup: true,\n            id: element.groupId,\n            position: element.position,\n            name: element.groupId,\n          };\n          return [groupLayer, elementLayer];\n        })\n    );\n  }, [elementLayers]);\n\n  const handleDragPosition = useCallback(\n    (oldPosObj, newPosObj, evt) => {\n      const { position: oldPos } = oldPosObj;\n      const {\n        position: newPos,\n        data: { groupId: newGroupId },\n      } = newPosObj;\n      const offsetTopHalf = nestedOffsetCalcFunc(evt); // Only relevant if isNewPosLastInGroup\n      const oldPosElement = elementLayers.find((e) => e.position === oldPos);\n      const elementAboveNewPos = elementLayers.find(\n        (e) => e.position === (newPos <= 2 ? 1 : newPos + 1)\n      ); // Above in LP is below in array.\n\n      let groupId = newGroupId;\n      if (offsetTopHalf && elementAboveNewPos?.groupId) {\n        groupId = elementAboveNewPos.groupId;\n      }\n\n      if (oldPosObj.data?.group) {\n        // We are holding the whole group.\n        if (!newPosObj.data?.groupId) {\n          arrangeGroup({\n            groupId: oldPosObj.data.group,\n            position: newPos,\n          });\n        }\n      } else {\n        arrangeElement({\n          elementId: oldPosElement.id,\n          position: newPos,\n          groupId,\n        });\n      }\n    },\n    [arrangeElement, arrangeGroup, elementLayers]\n  );\n\n  return { layers, handleDragPosition };\n}\n\nexport default useLayers;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nconst panelContext = createContext({ state: {}, actions: {} });\n\nexport default panelContext;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Panel, MAX_HEIGHT_DEFAULT } from './panel';\nexport { default as panelContext } from './context';\nexport { default as PanelTitle } from './shared/title';\nexport { default as PanelContent } from './shared/content';\nexport { default as SimplePanel } from './simplePanel';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/panel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  useState,\n  useCallback,\n  useEffect,\n  useMemo,\n} from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  localStore,\n  LOCAL_STORAGE_PREFIX,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app/story';\nimport panelContext from './context';\n\nexport const PANEL_COLLAPSED_THRESHOLD = 10;\nexport const MAX_HEIGHT_DEFAULT = 999999999;\n\nconst Wrapper = styled.section`\n  display: flex;\n  flex-direction: column;\n  position: relative;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n  ${({ noBorder }) => noBorder && 'border-bottom: none;'}\n`;\n\nfunction Panel({\n  name,\n  children,\n  resizable = false,\n  showDragHandle,\n  showFocusStyles,\n  canCollapse = true,\n  collapsedByDefault = true,\n  initialHeight = null,\n  maxHeight: _maxHeight = MAX_HEIGHT_DEFAULT,\n  ariaLabel = null,\n  ariaHidden = false,\n  isPersistable = true,\n  ...rest\n}) {\n  // If max height is 0 - fallback to default\n  // Allows us to save persisted heights if layers aren't loaded yet\n  const maxHeight = _maxHeight === 0 ? MAX_HEIGHT_DEFAULT : _maxHeight;\n  const { selectedElementIds } = useStory(\n    ({ state: { selectedElementIds } }) => {\n      return {\n        selectedElementIds,\n      };\n    }\n  );\n\n  const persisted = useMemo(\n    () =>\n      isPersistable\n        ? localStore.getItemByKey(`${LOCAL_STORAGE_PREFIX.PANEL}:${name}`)\n        : null,\n    [name, isPersistable]\n  );\n\n  const [isCollapsed, setIsCollapsed] = useState(() => {\n    // If not persisted, always default to expanded.\n    if (!isPersistable) {\n      return false;\n    }\n    // If isCollapsed is not defined, return the default value.\n    return persisted?.isCollapsed ?? collapsedByDefault;\n  });\n  const [expandToHeight, _setExpandToHeight] = useState(\n    Math.min(persisted?.expandToHeight, maxHeight) || initialHeight\n  );\n  const [height, _setHeight] = useState(\n    Math.min(persisted?.height, maxHeight) || initialHeight\n  );\n  const [hasTitle, setHasTitle] = useState(false);\n  const [manuallyChanged, setManuallyChanged] = useState(false);\n\n  // When setting height, compare to maxHeight\n  const setHeight = useCallback(\n    (newHeight) => {\n      _setHeight(Math.min(newHeight, maxHeight));\n    },\n    [maxHeight]\n  );\n  // When setting expand to height, compare to maxHeight\n  const setExpandToHeight = useCallback(\n    (newHeight) => {\n      _setExpandToHeight(Math.min(newHeight, maxHeight));\n    },\n    [maxHeight]\n  );\n\n  const confirmTitle = useCallback(() => setHasTitle(true), []);\n\n  const collapse = useCallback(() => {\n    if (!canCollapse) {\n      return;\n    }\n    setIsCollapsed(true);\n    setManuallyChanged(true);\n    if (resizable) {\n      setHeight(0);\n    }\n  }, [resizable, canCollapse, setHeight]);\n\n  const onCollapse = useCallback(() => {\n    if (!canCollapse) {\n      return;\n    }\n\n    collapse();\n\n    trackEvent('panel_toggled', {\n      name: name,\n      status: 'collapsed',\n    });\n  }, [canCollapse, collapse, name]);\n\n  const expand = useCallback(\n    (restoreHeight = true) => {\n      setIsCollapsed(false);\n      setManuallyChanged(true);\n      if (restoreHeight && resizable) {\n        setHeight(expandToHeight);\n      }\n    },\n    [resizable, expandToHeight, setHeight]\n  );\n\n  const onExpand = useCallback(\n    (restoreHeight = true) => {\n      expand(restoreHeight);\n\n      trackEvent('panel_toggled', {\n        name: name,\n        status: 'expanded',\n      });\n    },\n    [expand, name]\n  );\n\n  // Expand panel on first mount/on selection change if it can't be persisted.\n  useEffect(() => {\n    if (!isPersistable) {\n      expand(true);\n    }\n  }, [expand, isPersistable, selectedElementIds]);\n\n  // Collapse panel if height is lower than threshold\n  useEffect(() => {\n    if (resizable && height <= PANEL_COLLAPSED_THRESHOLD && !isCollapsed) {\n      collapse();\n    }\n  }, [collapse, height, resizable, isCollapsed]);\n\n  // Automatically set height of panel. Only happens when:\n  // 1. `manuallyChanged` is false\n  // 2. Nothing exists in local storage\n  // 3. `resizable` is true\n  useEffect(() => {\n    if (manuallyChanged || persisted || !resizable) {\n      return;\n    }\n    setHeight(initialHeight);\n    setExpandToHeight(initialHeight);\n  }, [\n    manuallyChanged,\n    initialHeight,\n    resizable,\n    persisted,\n    name,\n    setExpandToHeight,\n    setHeight,\n  ]);\n\n  // Make sure panel height is constrained by maxHeight\n  useEffect(() => {\n    if (maxHeight < height) {\n      setHeight(maxHeight);\n    }\n    if (maxHeight < expandToHeight) {\n      setExpandToHeight(maxHeight);\n    }\n  }, [expandToHeight, height, maxHeight, setHeight, setExpandToHeight]);\n\n  // Persist when user collapses\n  useEffect(() => {\n    if (!isPersistable || !manuallyChanged) {\n      return;\n    }\n\n    // Persist only when after user interacts\n    localStore.setItemByKey(`${LOCAL_STORAGE_PREFIX.PANEL}:${name}`, {\n      height,\n      isCollapsed,\n      expandToHeight,\n    });\n  }, [\n    name,\n    isCollapsed,\n    height,\n    expandToHeight,\n    manuallyChanged,\n    isPersistable,\n  ]);\n\n  const manuallySetHeight = useCallback(\n    (h) => {\n      if (!resizable) {\n        return;\n      }\n      setManuallyChanged(true);\n      setHeight(Math.min(h(height), maxHeight));\n      if (isCollapsed && h(height) > PANEL_COLLAPSED_THRESHOLD) {\n        expand(false);\n      }\n    },\n    [\n      expand,\n      height,\n      isCollapsed,\n      maxHeight,\n      resizable,\n      setHeight,\n      setManuallyChanged,\n    ]\n  );\n\n  const resetHeight = useCallback(() => {\n    setManuallyChanged(false);\n    if (isCollapsed) {\n      expand(true);\n    }\n  }, [expand, isCollapsed]);\n\n  const panelContentId = `panel-${name}-${uuidv4()}`;\n  const panelTitleId = `panel-title-${name}-${uuidv4()}`;\n  const panelTitleReadable = `panel-title-${name}`;\n\n  const contextValue = {\n    state: {\n      height,\n      resizable,\n      showDragHandle,\n      showFocusStyles,\n      isCollapsed,\n      panelContentId,\n      panelTitleId,\n      panelTitleReadable,\n      ariaHidden,\n    },\n    actions: {\n      setHeight: manuallySetHeight,\n      setExpandToHeight,\n      collapse: onCollapse,\n      expand: onExpand,\n      resetHeight,\n      confirmTitle,\n    },\n  };\n\n  const ContextProvider = panelContext.Provider;\n\n  const wrapperProps = useMemo(\n    () =>\n      hasTitle\n        ? { 'aria-labelledby': panelTitleId }\n        : { 'aria-label': ariaLabel },\n    [hasTitle, panelTitleId, ariaLabel]\n  );\n\n  return (\n    <Wrapper {...wrapperProps} aria-hidden={ariaHidden} {...rest}>\n      <ContextProvider value={contextValue}>{children}</ContextProvider>\n    </Wrapper>\n  );\n}\n\nPanel.propTypes = {\n  name: PropTypes.string.isRequired,\n  children: PropTypes.node,\n  initialHeight: PropTypes.number,\n  maxHeight: PropTypes.number,\n  resizable: PropTypes.bool,\n  showDragHandle: PropTypes.bool,\n  showFocusStyles: PropTypes.bool,\n  canCollapse: PropTypes.bool,\n  collapsedByDefault: PropTypes.bool,\n  ariaLabel: PropTypes.string,\n  ariaHidden: PropTypes.bool,\n  isPersistable: PropTypes.bool,\n};\n\nexport default Panel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/shared/content.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport panelContext from '../context';\n\nconst Container = styled.div`\n  padding: ${({ padding }) => padding || '8px 12px 8px'};\n  overflow: auto;\n  background-color: ${({ isSecondary, theme }) =>\n    isSecondary ? theme.colors.interactiveBg.secondaryNormal : 'transparent'};\n`;\n\nfunction Content({ children, ...rest }) {\n  const {\n    state: { isCollapsed, height, resizable, panelContentId },\n  } = useContext(panelContext);\n\n  const formStyle = {\n    height: resizable ? `${height}px` : 'auto',\n  };\n\n  // Don't render panel content/children when collapsed.\n  return isCollapsed ? null : (\n    <Container style={formStyle} {...rest} id={panelContentId}>\n      {children}\n    </Container>\n  );\n}\n\nContent.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default Content;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/shared/handle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useRef } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport useDragHandlers from '../useDragHandlers';\nimport useKeyboardHandlers from '../useKeyboardHandlers';\n\nconst HEIGHT = 8;\n\nconst Handle = styled.div`\n  border: 0;\n  padding: 0;\n  height: ${HEIGHT}px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  cursor: row-resize;\n  user-select: none;\n  position: absolute;\n  ${({ $position }) => 'top' === $position && `top: 0`};\n  ${({ $position }) => 'bottom' === $position && `bottom: 0`};\n  left: 0;\n  right: 0;\n  width: 100%;\n\n  ${({ $showFocusStyles }) =>\n    $showFocusStyles &&\n    css`\n      border-bottom: 1px solid transparent;\n\n      &:focus {\n        border-color: ${({ theme }) => theme.colors.border.focus};\n      }\n    `};\n`;\n\nconst DragBar = styled.div`\n  position: absolute;\n  width: 35px;\n  height: 3px;\n  top: ${HEIGHT - 4}px;\n  background: ${({ theme }) => theme.colors.bg.quaternary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  cursor: inherit;\n`;\n\nfunction DragHandle({\n  height,\n  minHeight,\n  maxHeight,\n  handleHeightChange,\n  handleExpandToHeightChange,\n  handleDoubleClick,\n  position = 'top',\n  showDragHandle,\n  showFocusStyles = true,\n  ...rest\n}) {\n  const handle = useRef();\n  useDragHandlers(handle, handleHeightChange, handleExpandToHeightChange);\n  useKeyboardHandlers(handle, handleHeightChange);\n\n  return (\n    // eslint-disable-next-line styled-components-a11y/click-events-have-key-events -- handled via useKeyboardHandlers.\n    <Handle\n      ref={handle}\n      onClick={(e) => e.stopPropagation()}\n      onDoubleClick={handleDoubleClick}\n      tabIndex={0}\n      $position={position}\n      role=\"slider\"\n      aria-orientation=\"vertical\"\n      aria-valuenow={height}\n      aria-valuemin={minHeight}\n      aria-valuemax={maxHeight}\n      aria-label={__('Set panel height', 'web-stories')}\n      $showFocusStyles={showFocusStyles}\n      {...rest}\n    >\n      {showDragHandle && <DragBar />}\n    </Handle>\n  );\n}\n\nDragHandle.propTypes = {\n  handleHeightChange: PropTypes.func.isRequired,\n  handleExpandToHeightChange: PropTypes.func.isRequired,\n  handleDoubleClick: PropTypes.func.isRequired,\n  height: PropTypes.number.isRequired,\n  minHeight: PropTypes.number.isRequired,\n  maxHeight: PropTypes.number.isRequired,\n  position: PropTypes.oneOf(['top', 'bottom']),\n  showDragHandle: PropTypes.bool,\n  showFocusStyles: PropTypes.bool,\n};\n\nexport default DragHandle;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/shared/test/handle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport DragHandle from '../handle';\nimport { noop } from '../../../../../utils/noop';\n\nconst handleHeightChange = jest.fn();\n\ndescribe('DragHandle', () => {\n  describe('should raise handleHeightChange when up or down key is pressed', () => {\n    afterEach(() => {\n      handleHeightChange.mockReset();\n    });\n\n    it('when up key is pressed', () => {\n      renderWithTheme(\n        <DragHandle\n          handleHeightChange={handleHeightChange}\n          handleExpandToHeightChange={noop}\n          handleDoubleClick={noop}\n          height={100}\n          maxHeight={200}\n          minHeight={50}\n        />\n      );\n\n      fireEvent.keyDown(screen.getByRole('slider'), {\n        key: 'ArrowUp',\n        which: 38,\n      });\n\n      expect(handleHeightChange).toHaveBeenCalledWith(20);\n    });\n\n    it('when down key is pressed', () => {\n      renderWithTheme(\n        <DragHandle\n          handleHeightChange={handleHeightChange}\n          handleExpandToHeightChange={noop}\n          handleDoubleClick={noop}\n          height={100}\n          maxHeight={200}\n          minHeight={50}\n        />\n      );\n\n      fireEvent.keyDown(screen.getByRole('slider'), {\n        key: 'ArrowDown',\n        which: 40,\n      });\n\n      expect(handleHeightChange).toHaveBeenCalledWith(-20);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/shared/title.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback, useEffect, useContext } from '@googleforcreators/react';\nimport {\n  BUTTON_TRANSITION_TIMING,\n  Icons,\n  TextSize,\n  Headline,\n  themeHelpers,\n  NotificationBubble,\n  BubbleVariant,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useSidebar from '../../../sidebar/useSidebar';\nimport panelContext from '../context';\nimport { PANEL_COLLAPSED_THRESHOLD } from '../panel';\nimport { focusStyle } from '../../shared/styles';\nimport DragHandle from './handle';\n\n// If the header is collapsed, we're leaving 8px less padding to apply that from the content.\nconst Header = styled(Headline).attrs({\n  as: 'h2',\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  background-color: ${({ isSecondary, theme }) =>\n    isSecondary && theme.colors.interactiveBg.secondaryNormal};\n  ${({ hasResizeHandle }) => hasResizeHandle && 'padding-top: 0;'}\n  margin: 0;\n  position: relative;\n  display: flex;\n  flex-direction: row;\n  user-select: none;\n  align-items: center;\n  justify-content: space-between;\n  padding: ${({ isCollapsed }) =>\n    isCollapsed ? '14px 16px' : '14px 16px 6px 16px'};\n`;\n\nconst Heading = styled.span`\n  color: ${({ theme, isCollapsed }) =>\n    isCollapsed ? theme.colors.fg.secondary : theme.colors.fg.primary};\n  display: flex;\n  ${({ theme }) =>\n    themeHelpers.expandPresetStyles({\n      preset: theme.typography.presets.headline[TextSize.XXSmall],\n      theme,\n    })};\n`;\n\nconst StyledNotificationBubble = styled(NotificationBubble)`\n  margin-left: 12px;\n`;\n\nconst HeaderActions = styled.div`\n  display: flex;\n  align-items: center;\n`;\n\n// Keeps the space for the icon even if it's not displayed.\nconst IconWrapper = styled.div`\n  position: relative;\n  width: 32px;\n  height: 32px;\n  svg {\n    position: relative;\n    z-index: 1;\n  }\n`;\n\n// -12px margin-left comes from 16px panel padding - 4px that it actually should be.\n// Since the svg-s are 32px and have extra room around, this needs to be removed\nconst Collapse = styled.button`\n  border: none;\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  background: transparent;\n  color: ${({ theme, isCollapsed }) =>\n    isCollapsed ? theme.colors.fg.secondary : theme.colors.fg.primary};\n  height: 32px;\n  display: flex; /* removes implicit line-height padding from child element */\n  padding: 0 4px 0 0;\n  align-items: center;\n  justify-content: flex-start;\n  cursor: pointer;\n  margin-left: -12px;\n  transition: ${BUTTON_TRANSITION_TIMING};\n  &:hover,\n  &:focus-visible {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n\n  ${focusStyle};\n\n  svg {\n    width: 32px;\n    height: 32px;\n    ${({ $isCollapsed, theme }) =>\n      $isCollapsed &&\n      css`\n        color: ${theme.colors.fg.secondary};\n        transform: rotate(-90deg);\n      `};\n  }\n\n  :hover ${IconWrapper}:after {\n    content: '';\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    height: 16px;\n    width: 16px;\n    border-radius: ${({ theme }) => theme.borders.radius.round};\n    background: ${({ theme }) => theme.colors.bg.quaternary};\n  }\n`;\n\nfunction Toggle({ children, isCollapsed, toggle, ...rest }) {\n  return (\n    <Collapse\n      onClick={(evt) => {\n        evt.stopPropagation();\n        toggle();\n      }}\n      $isCollapsed={isCollapsed}\n      {...rest}\n    >\n      {children}\n    </Collapse>\n  );\n}\n\nToggle.propTypes = {\n  children: PropTypes.node.isRequired,\n  isCollapsed: PropTypes.bool,\n  toggle: PropTypes.func.isRequired,\n};\n\nfunction Title({\n  ariaLabel,\n  children,\n  isPrimary = false,\n  isSecondary = false,\n  secondaryAction,\n  isResizable = false,\n  canCollapse = true,\n  maxHeight: maxHeightOverride,\n  count,\n  ...props\n}) {\n  const {\n    state: {\n      isCollapsed,\n      height,\n      resizable,\n      showDragHandle,\n      showFocusStyles,\n      panelContentId,\n      panelTitleId,\n      ariaHidden,\n    },\n    actions: {\n      collapse,\n      expand,\n      setHeight,\n      setExpandToHeight,\n      resetHeight,\n      confirmTitle,\n    },\n  } = useContext(panelContext);\n  const {\n    state: { sidebarContentHeight },\n  } = useSidebar();\n\n  useEffect(confirmTitle, [confirmTitle]);\n\n  // Default max panel height is set to 70% of full available height.\n  const maxHeight = maxHeightOverride || Math.round(sidebarContentHeight * 0.7);\n\n  const handleHeightChange = useCallback(\n    (deltaHeight) =>\n      resizable\n        ? setHeight((value) =>\n            Math.max(0, Math.min(maxHeight, value + deltaHeight))\n          )\n        : null,\n    [resizable, setHeight, maxHeight]\n  );\n\n  const handleExpandToHeightChange = useCallback(() => {\n    if (resizable && height >= PANEL_COLLAPSED_THRESHOLD) {\n      setExpandToHeight(height);\n    }\n  }, [setExpandToHeight, height, resizable]);\n\n  const toggle = isCollapsed ? expand : collapse;\n\n  const hasCount = count === 0 || Boolean(count);\n\n  return (\n    <Header\n      isPrimary={isPrimary}\n      isSecondary={isSecondary}\n      hasResizeHandle={isResizable && !isCollapsed}\n      isCollapsed={isCollapsed}\n      {...props}\n    >\n      {isResizable && (\n        <DragHandle\n          height={height}\n          minHeight={0}\n          maxHeight={maxHeight}\n          handleHeightChange={handleHeightChange}\n          handleExpandToHeightChange={handleExpandToHeightChange}\n          handleDoubleClick={resetHeight}\n          tabIndex={ariaHidden ? -1 : 0}\n          showDragHandle={showDragHandle}\n          showFocusStyles={showFocusStyles}\n        />\n      )}\n      <Toggle\n        toggle={toggle}\n        disabled={!canCollapse}\n        tabIndex={ariaHidden ? -1 : 0}\n        aria-label={ariaLabel}\n        aria-expanded={!isCollapsed}\n        aria-controls={panelContentId}\n        isCollapsed={isCollapsed}\n      >\n        {canCollapse && (\n          <IconWrapper>\n            <Icons.ChevronDownSmall />\n          </IconWrapper>\n        )}\n        <Heading\n          isCollapsed={isCollapsed}\n          id={panelTitleId}\n          size={TextSize.XXSmall}\n        >\n          {children}\n        </Heading>\n        {hasCount && (\n          <StyledNotificationBubble\n            data-testid=\"panel-badge\"\n            notificationCount={count}\n            variant={BubbleVariant.Primary}\n            aria-hidden\n          />\n        )}\n      </Toggle>\n      {secondaryAction && <HeaderActions>{secondaryAction}</HeaderActions>}\n    </Header>\n  );\n}\n\nTitle.propTypes = {\n  ariaLabel: PropTypes.string,\n  children: PropTypes.node,\n  isPrimary: PropTypes.bool,\n  isSecondary: PropTypes.bool,\n  isResizable: PropTypes.bool,\n  maxHeight: PropTypes.number,\n  secondaryAction: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n  canCollapse: PropTypes.bool,\n  count: PropTypes.number,\n};\n\nexport default Title;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/simplePanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Panel from './panel';\nimport PanelTitle from './shared/title';\nimport PanelContent from './shared/content';\n\nfunction SimplePanel({ children, name, ariaLabel, title, className, ...rest }) {\n  return (\n    <Panel name={name} {...rest}>\n      <PanelTitle\n        ariaLabel={ariaLabel ?? (typeof title === 'string' ? title : '')}\n        {...rest}\n      >\n        {title}\n      </PanelTitle>\n      <PanelContent className={className}>{children}</PanelContent>\n    </Panel>\n  );\n}\n\nSimplePanel.propTypes = {\n  children: PropTypes.node,\n  name: PropTypes.string.isRequired,\n  title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,\n  ariaLabel: PropTypes.string,\n  className: PropTypes.string,\n};\n\nexport default SimplePanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/test/simplePanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport SimplePanel from '../simplePanel';\n\ndescribe('Panels/Panel/SimplePanel', () => {\n  it('should render <SimplePanel /> (collapsed)', () => {\n    renderWithTheme(\n      <SimplePanel name=\"simple-panel\" title=\"Simple Panel\">\n        <div>{'Simple Panel Content'}</div>\n      </SimplePanel>\n    );\n\n    const titleElement = screen.getByText('Simple Panel');\n    expect(titleElement).toBeInTheDocument();\n\n    // <PanelContent> is not rendered when the panel itself is collapsed.\n    const contentElement = screen.queryByText('Simple Panel Content');\n    expect(contentElement).not.toBeInTheDocument();\n  });\n\n  it('should render <SimplePanel /> (expanded)', () => {\n    renderWithTheme(\n      <SimplePanel\n        name=\"simple-panel\"\n        title=\"Simple Panel\"\n        collapsedByDefault={false}\n      >\n        <div>{'Simple Panel Content'}</div>\n      </SimplePanel>\n    );\n\n    const titleElement = screen.getByText('Simple Panel');\n    expect(titleElement).toBeInTheDocument();\n\n    const contentElement = screen.getByText('Simple Panel Content');\n    expect(contentElement).toBeInTheDocument();\n  });\n\n  describe('should render <PanelTitle>', () => {\n    const titleName = 'Selection';\n    const contentText = 'Panel Content';\n\n    it('should have a label that matches the title name', () => {\n      renderWithTheme(\n        <SimplePanel name=\"simple-panel\" title={titleName}>\n          <div>{contentText}</div>\n        </SimplePanel>\n      );\n\n      const titleElement = screen.getByRole('button', { name: titleName });\n      const label = titleElement.getAttribute('aria-label');\n      expect(label).toStrictEqual(titleName);\n    });\n\n    it('should have an expand status by default', () => {\n      renderWithTheme(\n        <SimplePanel name=\"simple-panel\" title={titleName}>\n          <div>{contentText}</div>\n        </SimplePanel>\n      );\n\n      const titleElement = screen.getByRole('button', { name: titleName });\n      const isExpanded = titleElement.getAttribute('aria-expanded');\n      expect(isExpanded).toBeTruthy();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/useDragHandlers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useRef,\n  useState,\n  useCallback,\n  useLayoutEffect,\n} from '@googleforcreators/react';\n\nfunction useDragHandlers(handle, onDrag, onDragEnd) {\n  const lastPositionRef = useRef();\n  const [isDragging, setIsDragging] = useState(false);\n\n  // On pointer move, check difference since last record vertical pointer position\n  // and invoke callback with this difference.\n  // Then record new vertical pointer position for next iteration.\n  const handlePointerMove = useCallback(\n    (evt) => {\n      const delta = lastPositionRef.current - evt.pageY;\n      onDrag(delta);\n      lastPositionRef.current = evt.pageY;\n    },\n    [onDrag]\n  );\n\n  // On pointer up, set dragging as false\n  // - will cause useLayoutEffect to unregister listeners.\n  const handlePointerUp = useCallback(\n    (evt) => {\n      evt.target.releasePointerCapture(evt.pointerId);\n      setIsDragging(false);\n      onDragEnd();\n    },\n    [onDragEnd]\n  );\n\n  // On pointer down, set dragging as true\n  // - will cause useLayoutEffect to register listeners.\n  // Also record the initial vertical pointer position on the page.\n  const handlePointerDown = useCallback((evt) => {\n    evt.target.setPointerCapture(evt.pointerId);\n    lastPositionRef.current = evt.pageY;\n    setIsDragging(true);\n  }, []);\n\n  // On initial render *and* every time `isDragging` changes value,\n  // register all relevant listeners. Note that all listeners registered\n  // will be correctly unregistered due to the cleanup function.\n  useLayoutEffect(() => {\n    const element = handle.current;\n    element.addEventListener('pointerdown', handlePointerDown);\n\n    if (isDragging) {\n      element.addEventListener('pointermove', handlePointerMove);\n      element.addEventListener('pointerup', handlePointerUp);\n    }\n\n    return () => {\n      element.removeEventListener('pointerdown', handlePointerDown);\n\n      if (isDragging) {\n        element.removeEventListener('pointermove', handlePointerMove);\n        element.removeEventListener('pointerup', handlePointerUp);\n      }\n    };\n  }, [\n    isDragging,\n    handlePointerUp,\n    handlePointerMove,\n    handlePointerDown,\n    handle,\n  ]);\n}\n\nexport default useDragHandlers;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/panel/useKeyboardHandlers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyEffect } from '@googleforcreators/design-system';\n\nconst DELTA_CHANGE = 20; // change in pixels when pressing arrow keys\n\nfunction useKeyboardHandlers(handle, handleHeightChange) {\n  useKeyEffect(handle, 'up', () => handleHeightChange(DELTA_CHANGE), [\n    handleHeightChange,\n  ]);\n\n  useKeyEffect(handle, 'down', () => handleHeightChange(-DELTA_CHANGE), [\n    handleHeightChange,\n  ]);\n}\n\nexport default useKeyboardHandlers;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/flipControls.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  ButtonSize,\n  ButtonVariant,\n  ToggleButton,\n  Icons,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../../tooltip';\nimport { focusStyle } from './styles';\n\nconst ControlsContainer = styled.div`\n  display: flex;\n  justify-content: left;\n  align-items: flex-start;\n`;\n\nconst Space = styled.div`\n  width: 8px;\n`;\n\nconst StyledToggleButton = styled(ToggleButton)`\n  ${focusStyle};\n`;\n\n/**\n * @callback ChangeCallback\n * @param {Object} flip Flip value.\n * @param {boolean} flip.horizontal Horizontal value.\n * @param {boolean} flip.vertical Vertical value.\n */\n\n/**\n * Get flip controls for flipping elements horizontally and vertically.\n *\n * @param {Object} props Component props.\n * @param {Object} props.value Element's flip object.\n * @param {ChangeCallback} props.onChange Callback to flip element.\n * @return {*} Rendered component.\n */\nfunction FlipControls({ value, onChange }) {\n  const getCurrentFlipValue = useCallback(\n    (prop) => value[prop] === true,\n    [value]\n  );\n  return (\n    <ControlsContainer>\n      <Tooltip title={__('Flip horizontally', 'web-stories')}>\n        <StyledToggleButton\n          variant={ButtonVariant.Square}\n          size={ButtonSize.Small}\n          isToggled={value.horizontal === true}\n          onClick={() =>\n            onChange({\n              ...value,\n              horizontal: !getCurrentFlipValue('horizontal'),\n            })\n          }\n          aria-label={__('Flip horizontally', 'web-stories')}\n        >\n          <Icons.MirrorLeftRight />\n        </StyledToggleButton>\n      </Tooltip>\n      <Space />\n      <Tooltip title={__('Flip vertically', 'web-stories')}>\n        <StyledToggleButton\n          variant={ButtonVariant.Square}\n          size={ButtonSize.Small}\n          isToggled={value.vertical === true}\n          onClick={() =>\n            onChange({ ...value, vertical: !getCurrentFlipValue('vertical') })\n          }\n          aria-label={__('Flip vertically', 'web-stories')}\n        >\n          <Icons.MirrorUpDown />\n        </StyledToggleButton>\n      </Tooltip>\n    </ControlsContainer>\n  );\n}\n\nFlipControls.propTypes = {\n  value: PropTypes.object.isRequired,\n  onChange: PropTypes.func.isRequired,\n};\n\nexport default FlipControls;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/generalPageAdvancement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useEffect,\n  useState,\n  useMemo,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  NumericInput,\n  Text,\n  TextSize,\n  Toggle,\n} from '@googleforcreators/design-system';\nimport { clamp } from '@googleforcreators/units';\nimport {\n  DEFAULT_PAGE_DURATION,\n  DEFAULT_AUTO_ADVANCE,\n} from '@googleforcreators/output';\n\n/**\n * Internal dependencies\n */\nimport { Row, Switch } from '../../form';\nimport { SimplePanel } from '../panel';\nimport { inputContainerStyleOverride } from './styles';\n\nconst SwitchRow = styled.div`\n  margin-bottom: 16px;\n`;\n\nconst JustifyEndRow = styled(Row)`\n  justify-content: flex-end;\n  gap: 8px;\n`;\n\nconst MutedText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst LabelText = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\nconst MIN_MAX = {\n  PAGE_DURATION: {\n    MIN: 1,\n    MAX: 20,\n  },\n};\n\nfunction GeneralPageAdvancementPanel({\n  pageDuration = DEFAULT_PAGE_DURATION,\n  autoAdvance = DEFAULT_AUTO_ADVANCE,\n  onUpdate,\n  allowsOverride = false,\n  hasOverrideEnabled = false,\n  children,\n  panelName,\n  ...rest\n}) {\n  const [duration, setDuration] = useState(pageDuration);\n\n  useEffect(() => {\n    setDuration(pageDuration);\n  }, [pageDuration]);\n\n  const onAdvanceChange = useCallback(\n    (_evt, value) => {\n      onUpdate({ autoAdvance: value });\n      trackEvent('change_page_advancement', {\n        status: value ? 'auto' : 'manual',\n        duration: duration,\n      });\n    },\n    [onUpdate, duration]\n  );\n\n  const updatePageDuration = useDebouncedCallback((value) => {\n    const newValue = clamp(value, MIN_MAX.PAGE_DURATION);\n    if (value !== newValue) {\n      setDuration(newValue);\n    }\n    if (pageDuration !== newValue) {\n      onUpdate({ pageDuration: newValue });\n      trackEvent('change_page_advancement', {\n        status: autoAdvance ? 'auto' : 'manual',\n        duration: newValue,\n      });\n    }\n  }, 800);\n\n  const onDurationChange = useCallback(\n    (_evt, newValue) => {\n      setDuration(newValue);\n      updatePageDuration(newValue);\n    },\n    [updatePageDuration]\n  );\n\n  const onOverrideChange = useCallback(\n    () => onUpdate({ override: !hasOverrideEnabled }),\n    [hasOverrideEnabled, onUpdate]\n  );\n\n  const customAdvancementDisabled = allowsOverride && !hasOverrideEnabled;\n  const toggleId = useMemo(() => `toggle_${uuidv4()}`, []);\n\n  return (\n    <SimplePanel\n      name={panelName}\n      title={__('Page Advancement', 'web-stories')}\n      {...rest}\n    >\n      <Row>\n        <MutedText>{children}</MutedText>\n      </Row>\n      {allowsOverride && (\n        <JustifyEndRow>\n          <LabelText htmlFor={toggleId}>\n            {__('Override Story Defaults', 'web-stories')}\n          </LabelText>\n          <Toggle\n            id={toggleId}\n            checked={hasOverrideEnabled}\n            onChange={onOverrideChange}\n          />\n        </JustifyEndRow>\n      )}\n      <SwitchRow>\n        <Switch\n          groupLabel={__('Page Advancement', 'web-stories')}\n          name=\"page-advancement-switch\"\n          value={autoAdvance}\n          onLabel={__('Auto', 'web-stories')}\n          offLabel={__('Manual', 'web-stories')}\n          disabled={customAdvancementDisabled}\n          onChange={onAdvanceChange}\n        />\n      </SwitchRow>\n      {autoAdvance && (\n        <>\n          <Row>\n            <NumericInput\n              unit={` ${__('seconds', 'web-stories')}`}\n              suffix={__('Duration', 'web-stories')}\n              value={duration}\n              onChange={onDurationChange}\n              aria-label={__('Default page duration in seconds', 'web-stories')}\n              min={MIN_MAX.PAGE_DURATION.MIN}\n              max={MIN_MAX.PAGE_DURATION.MAX}\n              disabled={customAdvancementDisabled}\n              containerStyleOverride={inputContainerStyleOverride}\n            />\n          </Row>\n          <MutedText>\n            {sprintf(\n              /* translators: 1: minimum duration. 2: maximum duration. */\n              _n(\n                'Duration between %1$d and %2$d second.',\n                'Duration between %1$d and %2$d seconds.',\n                MIN_MAX.PAGE_DURATION.MAX,\n                'web-stories'\n              ),\n              MIN_MAX.PAGE_DURATION.MIN,\n              MIN_MAX.PAGE_DURATION.MAX\n            )}\n          </MutedText>\n        </>\n      )}\n    </SimplePanel>\n  );\n}\n\nexport default GeneralPageAdvancementPanel;\n\nGeneralPageAdvancementPanel.propTypes = {\n  pageDuration: PropTypes.number,\n  autoAdvance: PropTypes.bool,\n  onUpdate: PropTypes.func.isRequired,\n  allowsOverride: PropTypes.bool,\n  hasOverrideEnabled: PropTypes.bool,\n  children: PropTypes.node,\n  panelName: PropTypes.string.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/getCommonObjectValue.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getCommonValue from './getCommonValue';\n\n// @todo Test.\n/**\n * Get the common value object for `property` for all objects in `list`, based on the property names\n * specified in the `properties` array. If common value is not found, `defaultValue` is assigned instead.\n *\n * @param {Array.<Object>} list  List of objects\n * @param {string} property Property to check on all objects\n * @param {Object} defaultValue Default object when an element is missing it.\n * @return {Object} Found common object values or default values.\n */\nfunction getCommonObjectValue(list, property, defaultValue) {\n  const commonValue = {};\n  const propertyObjects = list.map(\n    (element) => element[property] || defaultValue\n  );\n  Object.keys(defaultValue).forEach((prop) => {\n    commonValue[prop] = getCommonValue(propertyObjects, prop);\n  });\n  return commonValue;\n}\n\nexport default getCommonObjectValue;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/getCommonValue.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../../constants';\n\n/**\n * Get the common value `property` for all objects in `list`, if they\n * in fact are all the same. If they are not all equal, return an empty string.\n *\n * Example usage:\n *\n * ```\n * getCommonValue( [ { a: 1 }, { a:  1  } ], 'a' );  // returns: 1\n * getCommonValue( [ { a: 1 }, {        } ], 'a' );  // returns: MULTIPLE_VALUE\n * getCommonValue( [ { a: 1 }, { a:  2  } ], 'a' );  // returns: MULTIPLE_VALUE\n * getCommonValue( [ { a: 1 }, { a: '1' } ], 'a' );  // returns: MULTIPLE_VALUE\n * ```\n *\n * @param {Array<Object>} list List of objects\n * @param {string|function(Object):any} propertyOrFunc Property to check on all objects.\n * @param {any} def The default value.\n * @return {any} Returns common value or empty string if not similar\n */\nfunction getCommonValue(list, propertyOrFunc, def = undefined) {\n  const func =\n    typeof propertyOrFunc === 'function'\n      ? propertyOrFunc\n      : (item) => item[propertyOrFunc];\n  const first = ifDef(func(list[0]), def);\n  const allMatch = list.every((el) => ifDef(func(el), def) === first);\n  return allMatch ? first : MULTIPLE_VALUE;\n}\n\nfunction ifDef(value, def) {\n  return value === undefined ? def : value;\n}\n\nexport default getCommonValue;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as FlipControls } from './flipControls';\nexport { default as LinkRelations } from './linkRelations';\nexport { default as getCommonValue } from './getCommonValue';\nexport { default as getCommonObjectValue } from './getCommonObjectValue';\nexport { default as useCommonColorValue } from './useCommonColorValue';\nexport { default as useCommonObjectValue } from './useCommonObjectValue';\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/linkRelations.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  Checkbox,\n  Link,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Row } from '../../form';\n\nconst LinkTypes = [\n  { key: 'sponsored', title: __('Sponsored', 'web-stories') },\n  { key: 'nofollow', title: __('Nofollow', 'web-stories') },\n];\n\nconst CheckboxWrapper = styled.div`\n  display: flex;\n  padding: 9px 0;\n`;\n\nconst Label = styled.label`\n  margin-left: 12px;\n`;\n\nconst StyledText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  padding: 8px 0;\n`;\n\nfunction LinkRelations({ rel, onChangeRel }) {\n  const relHelpLink = __(\n    'https://developers.google.com/search/docs/advanced/guidelines/qualify-outbound-links?hl=en',\n    'web-stories'\n  );\n\n  const onChange = useCallback(\n    (value) => {\n      const newRel = rel.includes(value)\n        ? rel.filter((el) => el !== value)\n        : [...rel, value];\n      onChangeRel(newRel);\n    },\n    [onChangeRel, rel]\n  );\n\n  return (\n    <Row>\n      <div>\n        <StyledText size={TextSize.Small}>\n          {__('Qualify outbound links', 'web-stories')}\n        </StyledText>\n        {LinkTypes.map(({ key, title }) => (\n          <CheckboxWrapper key={key}>\n            <Checkbox\n              id={key}\n              name={key}\n              checked={rel?.includes(key)}\n              onChange={() => onChange(key)}\n            />\n            <Label htmlFor={key}>\n              <Text.Span size={TextSize.Small}>{title}</Text.Span>\n            </Label>\n          </CheckboxWrapper>\n        ))}\n        <Link\n          rel=\"noreferrer\"\n          target=\"_blank\"\n          href={relHelpLink}\n          size={TextSize.XSmall}\n        >\n          {__('Learn more', 'web-stories')}\n        </Link>\n      </div>\n    </Row>\n  );\n}\nLinkRelations.propTypes = {\n  rel: PropTypes.array.isRequired,\n  onChangeRel: PropTypes.func.isRequired,\n};\n\nexport default LinkRelations;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/audioPlayer.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport {\n  TextSize,\n  themeHelpers,\n  Icons,\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { ResourcePropTypes } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_STORY_DETAILS } from '../../../../constants/zIndex';\nimport Tooltip from '../../../tooltip';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\nimport { noop } from '../../../../utils/noop';\n\nconst Play = styled(Icons.PlayFilled)`\n  width: 30px !important;\n  height: 30px !important;\n`;\n\nconst Stop = styled(Icons.StopFilled)`\n  width: 30px !important;\n  height: 30px !important;\n`;\n\nconst StyledButton = styled(Button)`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst Wrapper = styled.div(\n  ({ theme }) => css`\n    color: ${theme.colors.fg.primary};\n\n    ${themeHelpers.expandPresetStyles({\n      preset: {\n        ...theme.typography.presets.paragraph[TextSize.Small],\n      },\n      theme,\n    })};\n  `\n);\n\nconst Audio = styled.audio`\n  display: none;\n`;\n\nfunction AudioPlayer({ src, mimeType, tracks = [], audioId, loop, playerRef }) {\n  const [isPlaying, setIsPlaying] = useState(false);\n\n  const { getProxiedUrl } = useCORSProxy();\n\n  const handlePlayPause = useCallback(() => {\n    /**\n     * @type {HTMLAudioElement}\n     */\n    const player = playerRef.current;\n\n    if (!player) {\n      return;\n    }\n\n    if (isPlaying) {\n      player.pause();\n    } else {\n      player.play().catch(noop);\n    }\n  }, [isPlaying, playerRef]);\n\n  useEffect(() => {\n    /**\n     * @type {HTMLAudioElement}\n     */\n    const player = playerRef.current;\n\n    if (!player) {\n      return undefined;\n    }\n\n    const onAudioPlay = () => setIsPlaying(true);\n    const onAudioPause = () => setIsPlaying(false);\n    const onAudioEnd = () => {\n      player.currentTime = 0;\n      setIsPlaying(false);\n    };\n\n    player.addEventListener('play', onAudioPlay);\n    player.addEventListener('pause', onAudioPause);\n    player.addEventListener('ended', onAudioEnd);\n    return () => {\n      player.removeEventListener('play', onAudioPlay);\n      player.removeEventListener('pause', onAudioPause);\n      player.removeEventListener('ended', onAudioEnd);\n    };\n  }, [playerRef]);\n\n  const buttonTitle = isPlaying\n    ? __('Pause', 'web-stories')\n    : __('Play', 'web-stories');\n\n  const tracksFormatted = tracks.map((track) => {\n    const trackSrc = getProxiedUrl(track, track?.track);\n    return {\n      ...track,\n      track: trackSrc,\n    };\n  });\n\n  return (\n    <Wrapper>\n      {/* eslint-disable-next-line jsx-a11y/media-has-caption, styled-components-a11y/media-has-caption -- No captions wanted/needed here. */}\n      <Audio crossOrigin=\"anonymous\" loop={loop} ref={playerRef} id={audioId}>\n        <source src={src} type={mimeType} />\n        {tracksFormatted &&\n          tracksFormatted.map(\n            ({ srclang, label, track: trackSrc, id: key }, i) => (\n              <track\n                srcLang={srclang}\n                label={label}\n                // Hides the track from the user.\n                // Displaying happens in MediaCaptionsLayer instead.\n                kind=\"metadata\"\n                src={trackSrc}\n                key={key}\n                default={i === 0}\n              />\n            )\n          )}\n      </Audio>\n      <Tooltip\n        hasTail\n        title={buttonTitle}\n        popupZIndexOverride={Z_INDEX_STORY_DETAILS}\n      >\n        <StyledButton\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          aria-label={buttonTitle}\n          onClick={handlePlayPause}\n        >\n          {isPlaying ? <Stop /> : <Play />}\n        </StyledButton>\n      </Tooltip>\n    </Wrapper>\n  );\n}\n\nAudioPlayer.propTypes = {\n  src: PropTypes.string.isRequired,\n  mimeType: PropTypes.string.isRequired,\n  audioId: PropTypes.string,\n  loop: PropTypes.bool,\n  tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  playerRef: PropTypes.shape({ current: PropTypes.instanceOf(Element) })\n    .isRequired,\n};\n\nexport default AudioPlayer;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/backgroundAudioPanelContent.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Text,\n  TextSize,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport {\n  useCallback,\n  useMemo,\n  useState,\n  useRef,\n} from '@googleforcreators/react';\nimport {\n  ResourcePropTypes,\n  getExtensionsFromMimeType,\n  preloadVideo,\n  getVideoLength,\n  BackgroundAudioPropType,\n} from '@googleforcreators/media';\nimport { v4 as uuidv4 } from 'uuid';\nimport { trackError, trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app/config';\nimport { Row } from '../../../form';\nimport useCORSProxy from '../../../../utils/useCORSProxy';\nimport HotlinkModal from '../../../hotlinkModal';\nimport { noop } from '../../../../utils/noop';\nimport CaptionsPanelContent from './captionsPanelContent';\nimport LoopPanelContent from './loopPanelContent';\nimport AudioPlayer from './audioPlayer';\nimport FileRow from './fileRow';\n\nconst StyledButton = styled(Button)`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst UploadButton = styled(StyledButton)`\n  padding: 12px 8px;\n`;\n\nconst ButtonRow = styled(Row)`\n  gap: 12px;\n`;\n\nconst SectionHeading = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  font-weight: bold;\n  margin-bottom: 12px;\n`;\nconst eventName = 'hotlink_audio';\n\nfunction BackgroundAudioPanelContent({\n  backgroundAudio,\n  updateBackgroundAudio,\n  showCaptions = false,\n  showLoopControl = false,\n  audioId,\n}) {\n  const {\n    allowedMimeTypes: { audio: allowedAudioMimeTypes },\n    capabilities: { hasUploadMediaAction },\n    MediaUpload,\n  } = useConfig();\n  const [isOpen, setIsOpen] = useState(false);\n  const { getProxiedUrl } = useCORSProxy();\n\n  const allowedAudioFileTypes = useMemo(\n    () =>\n      allowedAudioMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedAudioMimeTypes]\n  );\n  const { resource = {}, tracks = [], loop = true } = backgroundAudio || {};\n\n  const playerRef = useRef();\n\n  const audioSrcProxied = getProxiedUrl(resource, resource?.src);\n\n  const onSelectErrorMessage = sprintf(\n    /* translators: %s: list of allowed file types. */\n    __('Please choose only %s to insert into page.', 'web-stories'),\n    translateToExclusiveList(allowedAudioFileTypes)\n  );\n\n  const onSelect = useCallback(\n    /**\n     * @param {import('@googleforcreators/media').AudioResource} resource Audio resource.\n     */\n    ({ src, id, mimeType, needsProxy, length, lengthFormatted }) => {\n      const updatedBackgroundAudio = {\n        resource: {\n          src,\n          id,\n          mimeType,\n          length,\n          lengthFormatted,\n          needsProxy,\n        },\n      };\n\n      if (showCaptions) {\n        updatedBackgroundAudio.tracks = [];\n      }\n      if (showLoopControl) {\n        updatedBackgroundAudio.loop = true;\n      }\n      updateBackgroundAudio(updatedBackgroundAudio);\n    },\n    [showCaptions, showLoopControl, updateBackgroundAudio]\n  );\n\n  const onSelectHotlink = useCallback(\n    async ({ link, hotlinkInfo, needsProxy }) => {\n      const { mimeType } = hotlinkInfo;\n      const audioProxied = getProxiedUrl({ needsProxy }, link);\n      const videoEl = await preloadVideo(audioProxied);\n      const { length, lengthFormatted } = getVideoLength(videoEl);\n\n      onSelect({\n        src: link,\n        mimeType,\n        length,\n        lengthFormatted,\n        needsProxy,\n      });\n      setIsOpen(false);\n      trackEvent(eventName, {\n        event_label: link,\n        file_size: hotlinkInfo.fileSize,\n        file_type: hotlinkInfo.mimeType,\n        needs_proxy: needsProxy,\n      });\n      setIsOpen(false);\n    },\n    [getProxiedUrl, onSelect]\n  );\n\n  const onError = useCallback((err) => trackError(eventName, err?.message), []);\n\n  const updateTracks = useCallback(\n    (newTracks) => {\n      updateBackgroundAudio({ ...backgroundAudio, tracks: newTracks });\n    },\n    [backgroundAudio, updateBackgroundAudio]\n  );\n\n  const onChangeLoop = useCallback(\n    (evt) => {\n      updateBackgroundAudio({ ...backgroundAudio, loop: evt.target.checked });\n    },\n    [backgroundAudio, updateBackgroundAudio]\n  );\n\n  const handleRemoveTrack = useCallback(\n    (idToDelete) => {\n      let newTracks = [];\n      if (idToDelete) {\n        const trackIndex = tracks.findIndex(({ id }) => id === idToDelete);\n        newTracks = [\n          ...tracks.slice(0, trackIndex),\n          ...tracks.slice(trackIndex + 1),\n        ];\n      }\n      updateTracks(newTracks);\n    },\n    [tracks, updateTracks]\n  );\n\n  const handleChangeTrack = useCallback(\n    ({ src = '', id, needsProxy = false }) => {\n      const newTrack = {\n        track: src,\n        trackId: id,\n        id: uuidv4(),\n        kind: 'captions',\n        srclang: '',\n        label: '',\n        needsProxy,\n      };\n      updateTracks([newTrack]);\n    },\n    [updateTracks]\n  );\n\n  const renderUploadButton = useCallback(\n    (open) => (\n      <UploadButton\n        onClick={open}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Rectangle}\n      >\n        {__('Upload an audio file', 'web-stories')}\n      </UploadButton>\n    ),\n    []\n  );\n\n  const renderUploadCaptionButton = useCallback(\n    (open) => (\n      <UploadButton\n        onClick={open}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Rectangle}\n      >\n        {__('Upload audio captions', 'web-stories')}\n      </UploadButton>\n    ),\n    []\n  );\n\n  const handleRemove = useCallback(() => {\n    if (playerRef.current) {\n      playerRef.current.pause();\n    }\n    updateBackgroundAudio(null);\n  }, [updateBackgroundAudio, playerRef]);\n\n  const options = [\n    hasUploadMediaAction && {\n      label: __('Upload a file', 'web-stories'),\n      value: 'upload',\n      onClick: noop,\n      mediaPickerProps: {\n        onSelect,\n        onSelectErrorMessage: __(\n          'Please choose a VTT file to use as caption.',\n          'web-stories'\n        ),\n        type: allowedAudioMimeTypes,\n        title: __('Upload an audio file', 'web-stories'),\n        buttonInsertText: __('Select audio file', 'web-stories'),\n      },\n    },\n    {\n      label: __('Link to a file', 'web-stories'),\n      value: 'hotlink',\n      onClick: () => {\n        setIsOpen(true);\n      },\n    },\n  ].filter(Boolean);\n\n  return (\n    <>\n      {!resource?.src && (\n        <ButtonRow spaceBetween={false}>\n          {hasUploadMediaAction && (\n            <MediaUpload\n              onSelect={onSelect}\n              onSelectErrorMessage={onSelectErrorMessage}\n              type={allowedAudioMimeTypes}\n              title={__('Upload an audio file', 'web-stories')}\n              buttonInsertText={__('Select audio file', 'web-stories')}\n              render={renderUploadButton}\n            />\n          )}\n          <UploadButton\n            variant={ButtonVariant.Rectangle}\n            type={ButtonType.Secondary}\n            size={ButtonSize.Small}\n            onClick={() => setIsOpen(true)}\n          >\n            {__('Link to audio file', 'web-stories')}\n          </UploadButton>\n        </ButtonRow>\n      )}\n      {resource?.src && (\n        <>\n          <FileRow\n            id={resource.id}\n            src={resource.src}\n            title={resource.src.split('/').pop()}\n            isExternal={!resource.id}\n            options={options}\n            onRemove={handleRemove}\n            removeItemLabel={__('Remove file', 'web-stories')}\n          >\n            <AudioPlayer\n              title={resource.src.substring(resource?.src.lastIndexOf('/') + 1)}\n              src={audioSrcProxied}\n              mimeType={resource.mimeType}\n              tracks={tracks}\n              audioId={audioId}\n              playerRef={playerRef}\n              loop={loop}\n            />\n          </FileRow>\n          {showCaptions && (\n            <>\n              <SectionHeading>\n                {__('Caption and Subtitles', 'web-stories')}\n              </SectionHeading>\n              <CaptionsPanelContent\n                captionText={__('Upload a file', 'web-stories')}\n                tracks={tracks || []}\n                handleChangeTrack={handleChangeTrack}\n                handleRemoveTrack={handleRemoveTrack}\n                renderUploadButton={renderUploadCaptionButton}\n              />\n            </>\n          )}\n          {showLoopControl && resource?.length > 0 && (\n            <>\n              <SectionHeading>{__('Options', 'web-stories')}</SectionHeading>\n              <Row spaceBetween={false}>\n                <LoopPanelContent loop={loop} onChange={onChangeLoop} />\n              </Row>\n            </>\n          )}\n        </>\n      )}\n      <HotlinkModal\n        title={__('Insert external background audio', 'web-stories')}\n        isOpen={isOpen}\n        onError={onError}\n        onSelect={onSelectHotlink}\n        onClose={() => setIsOpen(false)}\n        allowedFileTypes={allowedAudioFileTypes}\n        insertText={__('Use audio file', 'web-stories')}\n        insertingText={__('Selecting audio file', 'web-stories')}\n        // See https://github.com/GoogleForCreators/web-stories-wp/issues/11479\n        canUseProxy={!showCaptions && !showLoopControl}\n      />\n    </>\n  );\n}\n\nBackgroundAudioPanelContent.propTypes = {\n  backgroundAudio: PropTypes.shape({\n    resource: BackgroundAudioPropType,\n    loop: PropTypes.bool,\n    tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  }),\n  updateBackgroundAudio: PropTypes.func.isRequired,\n  showCaptions: PropTypes.bool,\n  showLoopControl: PropTypes.bool,\n  audioId: PropTypes.string,\n};\n\nexport default BackgroundAudioPanelContent;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/captionsPanelContent.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport { useState, useMemo, useCallback } from '@googleforcreators/react';\nimport {\n  getExtensionsFromMimeType,\n  ResourcePropTypes,\n} from '@googleforcreators/media';\nimport { trackError, trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { Row } from '../../../form';\nimport { useConfig } from '../../../../app/config';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../../../constants';\nimport HotlinkModal from '../../../hotlinkModal';\nimport { noop } from '../../../../utils/noop';\nimport FileRow from './fileRow';\n\nconst ButtonRow = styled(Row)`\n  gap: 12px;\n`;\n\nconst FileName = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst HotlinkButton = styled(Button)`\n  padding: 12px 8px;\n`;\n\nconst eventName = 'hotlink_caption';\n\nfunction CaptionsPanelContent({\n  isIndeterminate = false,\n  tracks = [],\n  captionText = __('Upload a file', 'web-stories'),\n  handleChangeTrack,\n  handleRemoveTrack,\n  renderUploadButton,\n  removeItemLabel = __('Remove file', 'web-stories'),\n}) {\n  const {\n    allowedMimeTypes: { caption: allowedCaptionMimeTypes = [] },\n    capabilities: { hasUploadMediaAction },\n    MediaUpload,\n  } = useConfig();\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  const allowedFileTypes = useMemo(\n    () =>\n      allowedCaptionMimeTypes.flatMap((type) =>\n        getExtensionsFromMimeType(type)\n      ),\n    [allowedCaptionMimeTypes]\n  );\n\n  const onSelect = useCallback(\n    ({ link, hotlinkInfo, needsProxy }) => {\n      const track = {\n        src: link,\n        needsProxy,\n      };\n      handleChangeTrack(track);\n      trackEvent(eventName, {\n        event_label: link,\n        file_size: hotlinkInfo.fileSize,\n        file_type: hotlinkInfo.mimeType,\n        needs_proxy: needsProxy,\n      });\n      setIsOpen(false);\n    },\n    [handleChangeTrack]\n  );\n\n  const onError = useCallback((err) => trackError(eventName, err?.message), []);\n\n  if (!allowedCaptionMimeTypes?.length) {\n    return null;\n  }\n\n  const options = [\n    hasUploadMediaAction && {\n      label: __('Upload a file', 'web-stories'),\n      value: 'upload',\n      onClick: noop,\n      mediaPickerProps: {\n        onSelect: handleChangeTrack,\n        onSelectErrorMessage: __(\n          'Please choose a VTT file to use as caption.',\n          'web-stories'\n        ),\n        type: allowedCaptionMimeTypes,\n        title: captionText,\n        buttonInsertText: __('Select caption', 'web-stories'),\n      },\n    },\n    {\n      label: __('Link to a file', 'web-stories'),\n      value: 'hotlink',\n      onClick: () => {\n        setIsOpen(true);\n      },\n    },\n  ].filter(Boolean);\n\n  return (\n    <>\n      {isIndeterminate && (\n        <Row>\n          <FileName>{MULTIPLE_DISPLAY_VALUE}</FileName>\n        </Row>\n      )}\n      {tracks.map((track) => (\n        <FileRow\n          key={track.id}\n          id={track.id}\n          src={track.track}\n          title={track.track.split('/').pop()}\n          isExternal={!track.trackId}\n          options={options}\n          onRemove={handleRemoveTrack}\n          removeItemLabel={removeItemLabel}\n        />\n      ))}\n      {!tracks.length && !isIndeterminate && (\n        <ButtonRow spaceBetween={false}>\n          {hasUploadMediaAction && (\n            <MediaUpload\n              onSelect={handleChangeTrack}\n              onSelectErrorMessage={__(\n                'Please choose a VTT file to use as caption.',\n                'web-stories'\n              )}\n              type={allowedCaptionMimeTypes}\n              title={captionText}\n              buttonInsertText={__('Select caption', 'web-stories')}\n              render={renderUploadButton}\n            />\n          )}\n          <HotlinkButton\n            variant={ButtonVariant.Rectangle}\n            type={ButtonType.Secondary}\n            size={ButtonSize.Small}\n            onClick={() => setIsOpen(true)}\n          >\n            {__('Link to caption file', 'web-stories')}\n          </HotlinkButton>\n        </ButtonRow>\n      )}\n      <HotlinkModal\n        title={__('Insert external captions', 'web-stories')}\n        isOpen={isOpen}\n        onSelect={onSelect}\n        onError={onError}\n        onClose={() => setIsOpen(false)}\n        allowedFileTypes={allowedFileTypes}\n        insertText={__('Use caption', 'web-stories')}\n        insertingText={__('Selecting caption', 'web-stories')}\n        canUseProxy={false}\n      />\n    </>\n  );\n}\n\nCaptionsPanelContent.propTypes = {\n  isIndeterminate: PropTypes.bool,\n  tracks: PropTypes.arrayOf(ResourcePropTypes.trackResource),\n  captionText: PropTypes.string,\n  removeItemLabel: PropTypes.string,\n  handleChangeTrack: PropTypes.func,\n  handleRemoveTrack: PropTypes.func,\n  renderUploadButton: PropTypes.func,\n};\n\nexport default CaptionsPanelContent;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/dropDownMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useRef,\n  useMemo,\n  forwardRef,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { v4 as uuidv4 } from 'uuid';\nimport {\n  Menu,\n  Popup,\n  noop,\n  Placement,\n  Icons,\n  Button,\n  ButtonVariant,\n  ButtonType,\n  ButtonSize,\n  TextSize,\n  DefaultListItemInner,\n  DefaultListItemLabelDisplayText,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../app';\nimport DropDownKeyEvents from '../../utils/dropDownKeyEvents';\n\nconst MenuButton = styled(Button)`\n  top: 4px;\n  right: 4px;\n`;\n\nconst DropDownContainer = styled.div`\n  margin-top: 10px;\n`;\n\nconst MenuContainer = styled.div`\n  z-index: 1;\n`;\n\nconst menuStylesOverride = css`\n  min-width: 160px;\n  margin-top: 0;\n`;\n\nconst ActiveIcon = styled(Icons.CheckmarkSmall)`\n  position: absolute;\n  left: 4px;\n  top: 50%;\n  transform: translateY(-50%);\n`;\n\nconst CustomItemRenderer = forwardRef(function CustomItemRenderer(\n  { option, isSelected, ...rest },\n  ref\n) {\n  const { MediaUpload } = useConfig();\n\n  if (option.mediaPickerProps) {\n    return (\n      <MediaUpload\n        {...option.mediaPickerProps}\n        render={(open) => (\n          <DefaultListItemInner\n            {...rest}\n            ref={ref}\n            isSelected={isSelected}\n            disabled={option.disabled}\n            aria-disabled={option.disabled}\n            onClick={(evt) => {\n              rest.onClick?.(evt);\n              open(evt);\n            }}\n          >\n            <DefaultListItemLabelDisplayText size={TextSize.Small}>\n              {option.label}\n            </DefaultListItemLabelDisplayText>\n          </DefaultListItemInner>\n        )}\n      />\n    );\n  }\n\n  return (\n    <DefaultListItemInner\n      {...rest}\n      ref={ref}\n      isSelected={isSelected}\n      disabled={option.disabled}\n      aria-disabled={option.disabled}\n    >\n      {isSelected && (\n        <ActiveIcon\n          data-testid={'dropdownMenuItem_active_icon'}\n          aria-label={__('Selected', 'web-stories')}\n          width={32}\n          height={32}\n        />\n      )}\n      <DefaultListItemLabelDisplayText size={TextSize.Small}>\n        {option.label}\n      </DefaultListItemLabelDisplayText>\n    </DefaultListItemInner>\n  );\n});\n\nCustomItemRenderer.propTypes = {\n  option: PropTypes.object,\n  isSelected: PropTypes.bool,\n};\n\n/**\n * An icon button that displays a dropdown menu on click.\n *\n * @param {Object} props Component props.\n * @param {boolean} props.display Whether the more icon should be displayed.\n * @param {boolean} props.isMenuOpen If the dropdown menu is open.\n * @param {Function} props.onMenuOpen Callback for when menu is opened.\n * @param {Function} props.onMenuClose Callback for when menu is closed without any selections.\n * @param {Function} props.onMenuSelected Callback for when menu is closed and an option selected.\n * @param {Function} props.setParentActive Sets the parent element active.\n * @param {Array} props.groups Menu items.\n * @param {Object} props.children Children.\n * @param {string} props.ariaLabel ARIA label for the toggle button.\n * @param {string} props.className Class name.\n * @return {null|*} Element or null.\n */\nfunction DropDownMenu({\n  display,\n  isMenuOpen,\n  onMenuOpen,\n  onMenuClose,\n  onMenuSelected,\n  setParentActive = noop,\n  groups,\n  children,\n  ariaLabel = __('More', 'web-stories'),\n  className,\n  ...rest\n}) {\n  const MenuButtonRef = useRef();\n\n  const onClose = useCallback(() => {\n    onMenuClose();\n    MenuButtonRef.current?.focus();\n    // Activeness of the parent is lost then due to blurring, we need to set it active \"manually\"\n    // to focus back on the original button.\n    setParentActive();\n  }, [onMenuClose, setParentActive]);\n\n  const onMenuItemClick = (evt, value) => {\n    onMenuSelected(value);\n  };\n\n  const listId = useMemo(() => `list-${uuidv4()}`, []);\n  const buttonId = useMemo(() => `button-${uuidv4()}`, []);\n\n  // Keep icon and menu displayed if menu is open (even if user's mouse leaves the area).\n  return (\n    <MenuContainer className={className}>\n      {/* eslint-disable react-hooks/refs -- FIXME */}\n      {MenuButtonRef.current && (\n        <DropDownKeyEvents target={MenuButtonRef.current} />\n      )}\n      {/* eslint-enable react-hooks/refs -- FIXME */}\n      <MenuButton\n        type={ButtonType.Tertiary}\n        size={ButtonSize.Small}\n        variant={ButtonVariant.Square}\n        ref={MenuButtonRef}\n        onClick={onMenuOpen}\n        aria-label={ariaLabel}\n        aria-pressed={isMenuOpen}\n        aria-haspopup\n        aria-expanded={isMenuOpen}\n        aria-owns={isMenuOpen ? listId : null}\n        id={buttonId}\n        $display={display}\n        tabIndex={display || isMenuOpen ? 0 : -1}\n      >\n        {children}\n      </MenuButton>\n      {(display || isMenuOpen) && (\n        <Popup\n          anchor={MenuButtonRef}\n          placement={Placement.BottomStart}\n          isOpen={isMenuOpen}\n        >\n          <DropDownContainer>\n            <Menu\n              parentId={buttonId}\n              listId={listId}\n              handleMenuItemSelect={onMenuItemClick}\n              groups={groups}\n              onDismissMenu={onClose}\n              hasMenuRole\n              menuStylesOverride={menuStylesOverride}\n              renderItem={CustomItemRenderer}\n              {...rest}\n            />\n          </DropDownContainer>\n        </Popup>\n      )}\n    </MenuContainer>\n  );\n}\n\nDropDownMenu.propTypes = {\n  display: PropTypes.bool.isRequired,\n  isMenuOpen: PropTypes.bool.isRequired,\n  onMenuOpen: PropTypes.func.isRequired,\n  onMenuClose: PropTypes.func.isRequired,\n  onMenuSelected: PropTypes.func.isRequired,\n  setParentActive: PropTypes.func,\n  groups: PropTypes.array,\n  children: PropTypes.node,\n  ariaLabel: PropTypes.string,\n  className: PropTypes.string,\n};\n\nexport default DropDownMenu;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/fileRow.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  Text,\n  TextSize,\n  themeHelpers,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\nimport { useState, useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { Row } from '../../../form';\nimport Tooltip from '../../../tooltip';\nimport DropDownMenu from './dropDownMenu';\n\nconst InputRow = styled.div`\n  flex-grow: 1;\n  margin: 0 8px;\n  min-width: 0;\n`;\n\nconst ReplaceIcon = styled(Icons.Rotate)`\n  vertical-align: bottom;\n`;\n\nconst LinkIcon = styled(Icons.Link)`\n  width: 24px;\n  height: 24px;\n  vertical-align: bottom;\n`;\n\nconst UploadIcon = styled(Icons.ArrowOutline)`\n  width: 24px;\n  height: 24px;\n  vertical-align: bottom;\n`;\n\nconst Link = styled.a`\n  ${({ theme }) => css`\n    color: ${theme.colors.fg.primary};\n    text-decoration: none;\n    cursor: pointer;\n\n    :hover,\n    :active,\n    :focus {\n      text-decoration: underline;\n      /* Override WordPress's common css */\n      color: ${theme.colors.fg.primary} !important;\n    }\n\n    ${themeHelpers.focusableOutlineCSS(theme.colors.border.focus)}\n  `};\n`;\n\nconst StyledButton = styled(Button)`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nconst FileName = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.primary};\n  text-overflow: ellipsis;\n  overflow: hidden;\n`;\n\nfunction FileRow({\n  id,\n  isExternal,\n  src,\n  title,\n  options,\n  removeItemLabel,\n  onRemove,\n  children,\n}) {\n  const groups = [\n    {\n      options,\n    },\n  ];\n\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n  const speak = useLiveRegion();\n\n  const onMenuOpen = () => setIsMenuOpen(true);\n  const onMenuClose = () => setIsMenuOpen(false);\n  const onMenuSelected = useCallback(\n    (value) => {\n      setIsMenuOpen(false);\n      options.find((item) => item.value === value)?.onClick();\n    },\n    [options]\n  );\n\n  const onItemRemove = useCallback(() => {\n    onRemove(id);\n    speak(__('File removed', 'web-stories'));\n  }, [id, onRemove, speak]);\n\n  const label = isExternal\n    ? __('External file', 'web-stories')\n    : __('Local file', 'web-stories');\n\n  return (\n    <Row key={`row-filename-${id}`}>\n      <Tooltip title={label}>\n        {isExternal ? <LinkIcon title={label} /> : <UploadIcon title={label} />}\n      </Tooltip>\n      <InputRow>\n        <FileName>\n          <Link href={src} rel=\"noreferrer\" target=\"_blank\">\n            {title}\n          </Link>\n        </FileName>\n      </InputRow>\n      {children}\n      {options.length > 0 && (\n        <DropDownMenu\n          onMenuOpen={onMenuOpen}\n          isMenuOpen={isMenuOpen}\n          onMenuSelected={onMenuSelected}\n          display\n          onMenuClose={onMenuClose}\n          groups={groups}\n          ariaLabel={__('Replace file', 'web-stories')}\n        >\n          <Tooltip title={__('Replace', 'web-stories')}>\n            <ReplaceIcon />\n          </Tooltip>\n        </DropDownMenu>\n      )}\n      <Tooltip hasTail title={removeItemLabel}>\n        <StyledButton\n          aria-label={removeItemLabel}\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          onClick={onItemRemove}\n        >\n          <Icons.Trash />\n        </StyledButton>\n      </Tooltip>\n    </Row>\n  );\n}\n\nFileRow.propTypes = {\n  id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n  isExternal: PropTypes.bool,\n  src: PropTypes.string,\n  title: PropTypes.string,\n  options: PropTypes.array,\n  removeItemLabel: PropTypes.string,\n  onRemove: PropTypes.func,\n  children: PropTypes.node,\n};\n\nexport default FileRow;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/media/loopPanelContent.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport { Checkbox, Text, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useInitializedValue } from '@googleforcreators/react';\n\nconst StyledCheckbox = styled(Checkbox)`\n  ${({ theme }) => `\n    input[type='checkbox']:focus-visible ~ div, input[type='checkbox']:focus ~ div {\n      box-shadow: 0px 0px 0 2px ${theme.colors.bg.secondary}, 0px 0px 0 4px ${theme.colors.border.focus} !important;\n    }\n  `}\n`;\n\nconst Wrapper = styled.div`\n  display: flex;\n  gap: 12px;\n  align-items: center;\n`;\n\nfunction LoopPanelContent({ loop, className = '', onChange, ...props }) {\n  const checkboxId = useInitializedValue(() => `cb-${uuidv4()}`);\n\n  return (\n    <Wrapper className={className}>\n      <StyledCheckbox\n        id={checkboxId}\n        checked={loop}\n        onChange={onChange}\n        {...props}\n      />\n      <Text.Label size={TextSize.Small} htmlFor={checkboxId}>\n        {__('Loop', 'web-stories')}\n      </Text.Label>\n    </Wrapper>\n  );\n}\n\nLoopPanelContent.propTypes = {\n  onChange: PropTypes.func.isRequired,\n  className: PropTypes.string,\n  loop: PropTypes.bool,\n};\n\nexport default LoopPanelContent;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { css } from 'styled-components';\nimport { themeHelpers } from '@googleforcreators/design-system';\n\nexport const focusStyle = css`\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n`;\n\nexport const inputContainerStyleOverride = css`\n  :focus-within {\n    ${({ theme }) =>\n      themeHelpers.focusCSS(\n        theme.colors.border.focus,\n        theme.colors.bg.secondary\n      )};\n  }\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/test/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ThemeProvider } from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { render } from '@testing-library/react';\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport theme from '../../../../theme';\nimport useHandlers from '../../../../utils/useHandlers';\nimport FormContext from '../../../form/context';\nimport updateProperties from '../../../style/updateProperties';\n\nfunction TestPanel({\n  panelType,\n  selectedElements,\n  setPresubmitHandlers,\n  wrapperComp,\n  ...rest\n}) {\n  const [presubmitHandlers, registerPresubmitHandler] = useHandlers();\n  setPresubmitHandlers(presubmitHandlers);\n  const formContext = useMemo(\n    () => ({\n      isMultiple: selectedElements.length > 1,\n      registerPresubmitHandler,\n    }),\n    [selectedElements, registerPresubmitHandler]\n  );\n\n  const Panel = panelType;\n  const panel = (\n    <FormContext.Provider value={formContext}>\n      <Panel\n        selectedElements={selectedElements}\n        submittedSelectedElements={selectedElements}\n        {...rest}\n      />\n    </FormContext.Provider>\n  );\n  const Wrapper = wrapperComp;\n  if (Wrapper) {\n    return <Wrapper selectedElements={selectedElements}>{panel}</Wrapper>;\n  }\n  return panel;\n}\n\nTestPanel.propTypes = {\n  panelType: PropTypes.func.isRequired,\n  selectedElements: PropTypes.array.isRequired,\n  setPresubmitHandlers: PropTypes.func.isRequired,\n  wrapperComp: PropTypes.func,\n};\n\n/**\n * @param {Function} panelType The panel component function.\n * @param {Array<Object>} selectedElements The array of the selected elements.\n * @param {Function} [wrapperComp] An optional wrapper component.\n * @return {Object} The result of rendering. Includes `pushUpdate`, `pushUpdateForObject`, and `submit` callbacks.\n */\nexport function renderPanel(panelType, selectedElements, wrapperComp) {\n  const pushUpdate = jest.fn();\n  const pushUpdateForObject = jest.fn();\n\n  let presubmitHandlers = [];\n  const setPresubmitHandlers = (handlers) => {\n    presubmitHandlers = handlers;\n  };\n\n  const submit = (updates) => {\n    const commitUpdates = {};\n    selectedElements.forEach((element) => {\n      const precommitUpdate = updateProperties(\n        element,\n        updates,\n        /* commitValues */ true\n      );\n      let commitUpdate = precommitUpdate;\n      presubmitHandlers.forEach((handler) => {\n        const handlerUpdate = handler(\n          { ...element, ...commitUpdate },\n          precommitUpdate,\n          element\n        );\n        commitUpdate = { ...commitUpdate, ...handlerUpdate };\n      });\n      commitUpdates[element.id] = commitUpdate;\n    });\n    return commitUpdates;\n  };\n\n  const view = render(\n    <ThemeProvider theme={theme}>\n      <TestPanel\n        panelType={panelType}\n        wrapperComp={wrapperComp}\n        selectedElements={selectedElements}\n        pushUpdate={pushUpdate}\n        pushUpdateForObject={pushUpdateForObject}\n        setPresubmitHandlers={setPresubmitHandlers}\n      />\n    </ThemeProvider>\n  );\n  return {\n    ...view,\n    pushUpdate,\n    pushUpdateForObject,\n    submit,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/test/getCommonObjectValue.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport getCommonObjectValue from '../getCommonObjectValue';\nimport { MULTIPLE_VALUE } from '../../../../constants';\n\ndescribe('getCommonObjectValue', () => {\n  it('should return matching values for the defined properties', () => {\n    const matchingValue = 1;\n    const elements = [\n      {\n        foo: {\n          a: matchingValue,\n          b: 2,\n        },\n      },\n      {\n        foo: {\n          a: matchingValue,\n          b: 1,\n        },\n      },\n    ];\n    const defaultShape = { a: 0, b: 0 };\n    const obj = getCommonObjectValue(elements, 'foo', defaultShape);\n    expect(obj.a).toStrictEqual(matchingValue);\n  });\n\n  it('should return default value for unmatching properties', () => {\n    const matchingValue = 1;\n    const elements = [\n      {\n        foo: {\n          a: matchingValue,\n          b: 2,\n        },\n      },\n      {\n        foo: {\n          a: matchingValue,\n          b: 1,\n        },\n      },\n    ];\n    const defaultShape = { a: 0, b: 0 };\n    const obj = getCommonObjectValue(elements, 'foo', defaultShape);\n    expect(obj.b).toStrictEqual(MULTIPLE_VALUE);\n  });\n\n  it('should only return defined properties', () => {\n    const matchingValue = 1;\n    const elements = [\n      {\n        foo: {\n          a: matchingValue,\n          b: 2,\n          c: 1,\n        },\n      },\n      {\n        foo: {\n          a: matchingValue,\n          b: 1,\n          c: 1,\n        },\n      },\n    ];\n    const defaultShape = { b: 0, c: 0 };\n    const obj = getCommonObjectValue(elements, 'foo', defaultShape);\n    expect(obj.a).toBeUndefined();\n    expect(obj.b).toBeDefined();\n    expect(obj.c).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/test/linkRelations.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport LinkRelations from '../linkRelations';\n\n/**\n * Internal dependencies\n */\n\ndescribe('LinkRelations', () => {\n  function arrange(props) {\n    return renderWithTheme(<LinkRelations {...props} />);\n  }\n\n  it('should display rel options for valid url', () => {\n    arrange({ onChangeRel: jest.fn(), rel: [] });\n    expect(screen.getByText('Qualify outbound links')).toBeInTheDocument();\n  });\n\n  it('should check rel options for valid url', () => {\n    arrange({ onChangeRel: jest.fn(), rel: ['nofollow'] });\n    expect(screen.getByText('Qualify outbound links')).toBeInTheDocument();\n    const optionA = screen.getByRole('checkbox', { name: 'Nofollow' });\n    expect(optionA).toBeChecked();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/useCommonColorValue.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\nimport {\n  convertToCSS,\n  generatePatternStyles,\n} from '@googleforcreators/patterns';\n\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../../constants';\n\n/**\n * Memoizes the common color value.\n *\n * @param {Array.<Object>} list List of objects.\n * @param {string} property Property to check on all objects.\n * @return {Object} Found common color value.\n */\nfunction useCommonColorValue(list, property) {\n  return useMemo(() => {\n    const allValues = list.map((element) => element[property]);\n    if (allValues.length === 0) {\n      return null;\n    }\n    if (allValues.length === 1) {\n      return allValues[0];\n    }\n    const uniqueValues = {};\n    allValues.forEach((value) => {\n      const serialized = convertToCSS(generatePatternStyles(value));\n      if (!(serialized in uniqueValues)) {\n        uniqueValues[serialized] = value;\n      }\n    });\n    return Object.keys(uniqueValues).length === 1\n      ? Object.values(uniqueValues)[0]\n      : MULTIPLE_VALUE;\n  }, [list, property]);\n}\n\nexport default useCommonColorValue;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/shared/useCommonObjectValue.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport getCommonObjectValue from './getCommonObjectValue';\n\n/**\n * Memoizes the value returned by the `getCommonObjectValue`.\n *\n * @param {Array.<Object>} list  List of objects\n * @param {string} property Property to check on all objects\n * @param {Object} defaultValue Default object when an element is missing it.\n * @return {Object} Found common object values or default values.\n */\nfunction useCommonObjectValue(list, property, defaultValue) {\n  const commonValue = getCommonObjectValue(list, property, defaultValue);\n  const parts = Object.keys(defaultValue).map((prop) => commonValue[prop]);\n  return useMemo(\n    () => commonValue,\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- We don't want commonValue as a dep.\n    parts\n  );\n}\n\nexport default useCommonObjectValue;\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/utils/dropDownKeyEvents.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useFocusCanvas from '../../canvas/useFocusCanvas';\nimport useRovingTabIndex from '../../../utils/useRovingTabIndex';\n\n// This is used for nested roving tab index to detect parent siblings.\nconst BUTTON_NESTING_DEPTH = 3;\n\nexport default function DropDownKeyEvents({ target }) {\n  useRovingTabIndex({ ref: target }, [], BUTTON_NESTING_DEPTH);\n  const focusCanvas = useFocusCanvas();\n  useKeyDownEffect(target, 'tab', focusCanvas, [focusCanvas]);\n  return null;\n}\n\nDropDownKeyEvents.propTypes = {\n  target: PropTypes.shape({ current: PropTypes.instanceOf(Element) }),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/utils/metricsForTextPadding.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function metricsForTextPadding({\n  currentPadding,\n  newPadding,\n  x,\n  y,\n  width,\n  height,\n}) {\n  const updates = {};\n\n  if ('horizontal' in newPadding) {\n    updates.x = x - (newPadding.horizontal - (currentPadding.horizontal || 0));\n    updates.width =\n      width + (newPadding.horizontal - (currentPadding.horizontal || 0)) * 2;\n  }\n\n  if ('vertical' in newPadding) {\n    updates.y = y - (newPadding.vertical - (currentPadding.vertical || 0));\n    updates.height =\n      height + (newPadding.vertical - (currentPadding.vertical || 0)) * 2;\n  }\n\n  return updates;\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/panels/utils/test/metricsForTextPadding.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { metricsForTextPadding } from '../metricsForTextPadding';\n\ndescribe('metricsForTextPadding()', () => {\n  it('should calculate metrics for new padding with no existing padding.', () => {\n    expect(\n      metricsForTextPadding({\n        newPadding: { horizontal: 10, vertical: 8 },\n        currentPadding: { horizontal: 0, vertical: 0 },\n        width: 100,\n        height: 100,\n        y: 30,\n        x: 20,\n      })\n    ).toStrictEqual({\n      height: 116,\n      width: 120,\n      x: 10,\n      y: 22,\n    });\n  });\n\n  it('should calculate metrics for shrinking (new padding is smaller than current).', () => {\n    expect(\n      metricsForTextPadding({\n        newPadding: { horizontal: 10, vertical: 8 },\n        currentPadding: { horizontal: 32, vertical: 14 },\n        width: 100,\n        height: 100,\n        y: 30,\n        x: 20,\n      })\n    ).toStrictEqual({\n      height: 88,\n      width: 56,\n      x: 42,\n      y: 36,\n    });\n  });\n\n  it('should calculate metrics for growing (new padding is smaller than current).', () => {\n    expect(\n      metricsForTextPadding({\n        newPadding: { horizontal: 64, vertical: 28 },\n        currentPadding: { horizontal: 32, vertical: 14 },\n        width: 100,\n        height: 100,\n        y: 30,\n        x: 40,\n      })\n    ).toStrictEqual({\n      height: 128,\n      width: 164,\n      x: 8,\n      y: 16,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/previewPage/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as PreviewPage } from './previewPage';\nexport { default as PreviewErrorBoundary } from './previewErrorBoundary';\n"
  },
  {
    "path": "packages/story-editor/src/components/previewPage/previewErrorBoundary.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { Component } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\nexport default class PreviewErrorBoundary extends Component {\n  static propTypes = {\n    children: PropTypes.node.isRequired,\n  };\n\n  state = {\n    hasError: false,\n  };\n\n  static getDerivedStateFromError() {\n    return { hasError: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    // eslint-disable-next-line no-console -- We want to surface this error.\n    console.error(error, errorInfo);\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return <div />;\n    }\n    return this.props.children;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/previewPage/previewPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useEffect, memo, forwardRef } from '@googleforcreators/react';\nimport styled, { StyleSheetManager } from 'styled-components';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport {\n  AnimationProvider,\n  useStoryAnimationContext,\n  StoryAnimationState,\n} from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes, PageSizePropType } from '../../propTypes';\nimport { noop } from '../../utils/noop';\nimport PagePreviewElements from './previewPageElements';\n\n/*\n * A quick note about how height works with the 9:16 aspect ratio (FULLBLEED_RATIO)\n * The unitProvider that sizes page previews still needs the 2:3 ratio,\n * this is passed in here as pageSize.height. It is the true height of the story\n * That said, we also need a height for the 9:16 that acts as the container for the story\n * to allow for fullBleed overflow.\n * So, you'll notice that containerHeight is getting used to wrap the PreviewSafeZone height\n * to make sure that the overflow has the proper size.\n * Reference story-editor/components/canvas/layout for more details\n *\n */\n\nconst FullBleedPreviewWrapper = styled.div`\n  height: ${({ pageSize }) => `${pageSize.containerHeight}px`};\n  width: 100%;\n  overflow: hidden;\n  position: relative;\n  display: flex;\n  align-items: center;\n  background-color: white;\n  ${({ background }) => generatePatternStyles(background)};\n`;\n\nconst PreviewSafeZone = styled.div`\n  width: 100%;\n  height: ${({ pageSize }) => `${pageSize.height}px`};\n  overflow: visible;\n  position: absolute;\n  margin: 0;\n`;\n\nfunction PreviewPageAnimationController({ animationState }) {\n  const WAAPIAnimationMethods = useStoryAnimationContext(\n    ({ actions }) => actions.WAAPIAnimationMethods\n  );\n\n  useEffect(() => {\n    switch (animationState) {\n      case StoryAnimationState.Playing:\n        WAAPIAnimationMethods.play();\n        return noop;\n      case StoryAnimationState.Reset:\n        WAAPIAnimationMethods.reset();\n        return noop;\n      case StoryAnimationState.Scrubbing:\n      case StoryAnimationState.Paused:\n        WAAPIAnimationMethods.pause();\n        return noop;\n      default:\n        return noop;\n    }\n  }, [animationState, WAAPIAnimationMethods]);\n\n  /**\n   * Reset everything on unmount;\n   */\n  useEffect(() => () => WAAPIAnimationMethods.reset(), [WAAPIAnimationMethods]);\n\n  return null;\n}\n\nconst PreviewPageDisplay = memo(\n  forwardRef(function PreviewPageDisplay({ page, pageSize }, ref) {\n    return (\n      <FullBleedPreviewWrapper\n        ref={ref}\n        pageSize={pageSize}\n        background={page.backgroundColor}\n      >\n        <PreviewSafeZone pageSize={pageSize}>\n          <PagePreviewElements page={page} />\n        </PreviewSafeZone>\n      </FullBleedPreviewWrapper>\n    );\n  })\n);\n\nconst PreviewPage = forwardRef(function PreviewPage(\n  {\n    page,\n    pageSize,\n    animationState = StoryAnimationState.Reset,\n    onAnimationComplete,\n  },\n  ref\n) {\n  // Preview is wrapped in StyleSheetManager w/ stylisPlugins={[]} in order to prevent\n  // elements from shifting when in RTL mode since these aren't relevant for story previews\n  return (\n    <StyleSheetManager stylisPlugins={[]}>\n      <AnimationProvider\n        animations={page.animations}\n        elements={page.elements}\n        onWAAPIFinish={onAnimationComplete}\n      >\n        <PreviewPageDisplay ref={ref} page={page} pageSize={pageSize} />\n        <PreviewPageAnimationController animationState={animationState} />\n      </AnimationProvider>\n    </StyleSheetManager>\n  );\n});\n\nPreviewPage.propTypes = {\n  page: StoryPropTypes.page.isRequired,\n  pageSize: PageSizePropType.isRequired,\n  animationState: PropTypes.oneOf(Object.values(StoryAnimationState)),\n  onAnimationComplete: PropTypes.func,\n};\n\nPreviewPageDisplay.propTypes = {\n  page: StoryPropTypes.page.isRequired,\n  pageSize: PageSizePropType.isRequired,\n};\n\nPreviewPageAnimationController.propTypes = {\n  animationState: PropTypes.oneOf(Object.values(StoryAnimationState)),\n};\n\nexport default PreviewPage;\n"
  },
  {
    "path": "packages/story-editor/src/components/previewPage/previewPageElements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport DisplayElement from '../canvas/displayElement';\nimport { StoryPropTypes } from '../../propTypes';\n\nfunction PreviewPageElements({ page }) {\n  return page.elements.map((element) => (\n    <DisplayElement\n      previewMode\n      key={element.id}\n      page={page}\n      element={element}\n      isAnimatable\n    />\n  ));\n}\n\nPreviewPageElements.propTypes = {\n  page: StoryPropTypes.page.isRequired,\n};\n\nexport default memo(PreviewPageElements);\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/constants.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const INPUT_KEYS = {\n  EXCERPT: 'excerpt',\n  SLUG: 'slug',\n  TITLE: 'title',\n};\n\nexport const HEADER_BAR_HEIGHT = '44px';\nexport const HEADER_BAR_MARGIN = '1px';\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/content/checklistButton.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { Icons } from '@googleforcreators/design-system';\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\n/**\n * Internal dependencies\n */\nimport { Z_INDEX_STORY_DETAILS } from '../../../constants/zIndex';\nimport { ISSUE_TYPES } from '../../checklist/constants';\nimport { useCategoryCount } from '../../checklist/countContext';\nimport { ToggleButton } from '../../toggleButton';\n\nconst ChecklistButton = ({ handleReviewChecklist }) => {\n  const priorityCount = useCategoryCount(ISSUE_TYPES.PRIORITY);\n\n  return (\n    <ToggleButton\n      MainIcon={Icons.Checkbox}\n      label={__('Checklist', 'web-stories')}\n      aria-label={__('Checklist', 'web-stories')}\n      popupZIndexOverride={Z_INDEX_STORY_DETAILS}\n      onClick={handleReviewChecklist}\n      notificationCount={priorityCount}\n    />\n  );\n};\n\nexport default ChecklistButton;\n\nChecklistButton.propTypes = {\n  handleReviewChecklist: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/content/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { themeHelpers } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport useSidebar from '../../sidebar/useSidebar';\nimport { useHasChecklist } from '../../checklist';\nimport { HEADER_BAR_HEIGHT, HEADER_BAR_MARGIN } from '../constants';\nimport MainStoryInfo from './mainStoryInfo';\nimport StoryPreview from './storyPreview';\nimport ChecklistButton from './checklistButton';\n\nconst Main = styled.div`\n  display: grid;\n  min-width: 917px;\n  width: 100%;\n  height: calc(100% - ${HEADER_BAR_MARGIN} - ${HEADER_BAR_HEIGHT});\n  /* grid-template-columns: 281px 313px 326.5px; */\n  grid-template-columns: 30.5% 34% 35.5%;\n  grid-template-rows: auto;\n  grid-template-areas:\n    'preview mainPanel sidePanel'\n    'footer mainPanel sidePanel';\n`;\n\nconst _StoryPreview = styled.div`\n  grid-area: preview;\n  margin: 20px 18px 0 32px;\n`;\n\nconst _MainStoryInfo = styled.div`\n  grid-area: mainPanel;\n  display: flex;\n  flex-direction: column;\n  padding: 0 16px;\n  overflow-y: scroll;\n  gap: 34px;\n\n  & > section {\n    /* Override the default border that is part of the base panel structure since this is destructured */\n    border: none;\n    /* overriding this way because of how isolated panel is inserted */\n    & > h2 {\n      padding-top: 0;\n      padding-bottom: 2px;\n      & > button {\n        height: 1em;\n      }\n    }\n  }\n`;\n\nconst PanelContainer = styled.div.attrs({ role: 'tabpanel' })`\n  grid-area: sidePanel;\n  height: 100%;\n  margin-left: 18px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  border-bottom-right-radius: ${({ theme }) => theme.borders.radius.medium};\n  overflow-y: scroll;\n\n  ${themeHelpers.scrollbarCSS};\n`;\n\nconst Footer = styled.div`\n  grid-area: footer;\n  display: flex;\n  align-items: flex-end;\n  margin: 0 18px 20px 32px;\n`;\n\nconst Content = ({ handleReviewChecklist }) => {\n  const { DocumentPane, id: paneId } = useSidebar(\n    ({ data }) => data?.modalSidebarTab || {}\n  );\n  const hasChecklist = useHasChecklist();\n\n  return (\n    <Main>\n      <_StoryPreview>\n        <StoryPreview />\n      </_StoryPreview>\n      <_MainStoryInfo>\n        <MainStoryInfo />\n      </_MainStoryInfo>\n      {DocumentPane && (\n        <PanelContainer\n          aria-label={__('Story Settings', 'web-stories')}\n          id={paneId}\n        >\n          <DocumentPane />\n        </PanelContainer>\n      )}\n      {hasChecklist && (\n        <Footer>\n          <ChecklistButton handleReviewChecklist={handleReviewChecklist} />\n        </Footer>\n      )}\n    </Main>\n  );\n};\n\nexport default Content;\n\nContent.propTypes = {\n  handleReviewChecklist: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/content/mainStoryInfo.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { Headline, TextArea, TextSize } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { updateSlug } from '../../../utils/storyUpdates';\nimport useSidebar from '../../sidebar/useSidebar';\nimport { EXCERPT_MAX_LENGTH } from '../../panels/document/excerpt';\nimport { INPUT_KEYS } from '../constants';\n\nconst FormSection = styled.div`\n  padding: 0 4px;\n  &:first-of-type {\n    margin: 20px 0px 0px;\n  }\n`;\n\nconst _TextArea = styled(TextArea)`\n  margin: 8px 0 0;\n  /*\n   We want 34px between each section on the main content panel. The TextArea's \"hint\" has a line height that forces the\n   space between sections to be too large, so this is to account for the extra space.\n  */\n  & > p {\n    margin-bottom: -4px;\n  }\n`;\n\nconst MainStoryInfo = () => {\n  const updateStory = useStory(({ actions }) => actions.updateStory);\n  const _inputValues = useStory(({ state: { story } }) => ({\n    [INPUT_KEYS.EXCERPT]: story.excerpt,\n    [INPUT_KEYS.TITLE]: story.title || '',\n  }));\n  // Keep slug isolated from other input values to limit changes and keep in sync on handleSlugUpdate\n  const slug = useStory(\n    ({\n      state: {\n        story: { slug },\n      },\n    }) => slug\n  );\n\n  const IsolatedStatusPanel = useSidebar(\n    ({ data }) => data?.modalSidebarTab?.IsolatedStatusPanel\n  );\n\n  const [inputValues, setInputValues] = useState(_inputValues);\n\n  const handleUpdateSlug = useCallback(\n    (newTitle) => {\n      updateSlug({\n        currentSlug: slug,\n        currentTitle: newTitle,\n        updateStory,\n      });\n    },\n    [slug, updateStory]\n  );\n\n  const handleUpdateStoryInfo = useCallback(\n    ({ target }) => {\n      const { value, name } = target;\n      updateStory({\n        properties: { [name]: value },\n      });\n\n      if (name === INPUT_KEYS.TITLE) {\n        handleUpdateSlug(value);\n      }\n    },\n    [handleUpdateSlug, updateStory]\n  );\n\n  const onInputChange = ({ currentTarget }) => {\n    setInputValues((prev) => ({\n      ...prev,\n      [currentTarget.name]: currentTarget.value,\n    }));\n  };\n  return (\n    <>\n      <FormSection>\n        <Headline as=\"label\" size={TextSize.XXSmall} htmlFor=\"story-title\">\n          {__('Story Title', 'web-stories')}\n        </Headline>\n        <_TextArea\n          name={INPUT_KEYS.TITLE}\n          id=\"story-title\"\n          showCount\n          value={inputValues[INPUT_KEYS.TITLE]}\n          onChange={onInputChange}\n          onBlur={handleUpdateStoryInfo}\n          aria-label={__('Story Title', 'web-stories')}\n          placeholder={__('Add title', 'web-stories')}\n        />\n      </FormSection>\n      <FormSection>\n        <Headline as=\"label\" size={TextSize.XXSmall} htmlFor=\"story-excerpt\">\n          {__('Story Description', 'web-stories')}\n        </Headline>\n        <_TextArea\n          name={INPUT_KEYS.EXCERPT}\n          id=\"story-excerpt\"\n          showCount\n          maxLength={EXCERPT_MAX_LENGTH}\n          value={inputValues[INPUT_KEYS.EXCERPT]}\n          aria-label={__('Story Description', 'web-stories')}\n          placeholder={__('Write a description of the story', 'web-stories')}\n          hint={__(\n            'Stories with a description tend to do better on search and have a wider reach',\n            'web-stories'\n          )}\n          onChange={onInputChange}\n          onBlur={handleUpdateStoryInfo}\n        />\n      </FormSection>\n      {/* eslint-disable-next-line react-hooks/static-components -- FIXME */}\n      {IsolatedStatusPanel && <IsolatedStatusPanel />}\n    </>\n  );\n};\n\nexport default MainStoryInfo;\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/content/storyPreview.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  Headline,\n  Text,\n  TextSize,\n  MediaVariant,\n} from '@googleforcreators/design-system';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { PAGE_RATIO } from '@googleforcreators/units';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\n/**\n * Internal dependencies\n */\nimport { useConfig, useStory } from '../../../app';\nimport { STABLE_ARRAY } from '../../../constants';\nimport { Media } from '../../form';\n\n// Set the available space for cover preview image + overlay\nconst PreviewWrapper = styled.div`\n  width: ${({ width }) => width}px;\n  height: ${({ height }) => height}px;\n  position: relative;\n  margin-top: 8px;\n`;\nPreviewWrapper.propTypes = {\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n};\n\nconst PreviewContainer = styled.div`\n  width: ${({ width }) => width}px;\n  height: ${({ height }) => height}px;\n  position: absolute;\n`;\nPreviewContainer.propTypes = {\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n};\n\n// In ascending order, the featured image is set as the full available 2:3 space.\nexport const Image = styled.img`\n  height: 100%;\n  width: 100%;\n  display: block;\n  aspect-ratio: ${PAGE_RATIO};\n  object-fit: cover;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.interactiveBg.primaryNormal};\n`;\n\n// If there's no featured image, a div gets set to take its place.\n// Mostly this prevents an empty image tag and sets a background color\n// so that any story title or site name is visible on top of it.\nconst EmptyPlaceholder = styled.div`\n  height: 100%;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.interactiveBg.primaryNormal};\n`;\n\n// On top of the featured media we position a gradient.\n// This is pulled directly from the gradient styles seen in Search results\n// so it mirrors the actual Cover preview.\nconst Gradient = styled.div`\n  position: absolute;\n  bottom: 0;\n  height: 67%;\n  width: 100%;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.gradient.posterOverlay};\n`;\n\n// Next we establish the scrim, this is where everything either\n// a) interactive or b) overlay on top of the featured media and gradient lives\nconst ScrimWrapper = styled.div`\n  position: absolute;\n  top: 0;\n  box-sizing: border-box;\n  width: 100%;\n  height: 100%;\n  border-radius: ${({ theme }) => theme.borders.radius.medium};\n  background: ${({ theme }) => theme.colors.opacity.black3};\n  padding: 8px;\n`;\n\n// While the above wrapper sets positioning to keep it directly on top of the\n// previous elements, the container gives the children their general display.\nconst ScrimContainer = styled.div`\n  display: flex;\n  height: 100%;\n  width: 100%;\n  flex-wrap: wrap;\n  justify-content: space-between;\n`;\n\n// Scrim has two sections, the first is positioned at the top, second the bottom.\n// They have pretty different requirements, so they each get their own container.\n// The top has one row with 2 columns, content is positioned along the edges.\n// Content may or may not be present, it needs to be in its true visual position\n// regardless of if its siblings are there.\nconst ScrimTop = styled.div`\n  display: grid;\n  grid-template-columns: 50% 50%;\n  grid-template-rows: auto;\n  grid-template-areas: 'publisherLogo editButton';\n  justify-content: inherit;\n  width: 100%;\n`;\n// Publisher logo border radius and box shadow are outside of theme to match Search Cover Preview\nconst PublisherLogo = styled.img`\n  grid-area: publisherLogo;\n  height: 24px;\n  width: 24px;\n  border-radius: 2px;\n  box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);\n`;\n\nconst StyledMedia = styled(Media)`\n  grid-area: editButton;\n  display: flex;\n  flex-direction: row-reverse;\n`;\n\n// The bottom section of the scrim is full width.\nconst ScrimBottom = styled.div`\n  width: 100%;\n  margin: auto 0 0;\n  align-self: flex-end;\n`;\n\n// Title styles are taken from Search cover preview styles.\n// There's some specific overrides happening here though because,\n// while Search shows Story Cover Previews in Chrome, we have to make\n// sure these styles will show Creators using Web Stories in other browsers\n// the same results. So we specifically want prefixes to stay put and not compile\n// the lines that have stylelint disabled.\nconst Title = styled(Headline).attrs({\n  as: 'h3',\n  size: TextSize.XSmall,\n})`\n  max-height: calc(1.2em * 3);\n  /* stylelint-disable-next-line */\n  display: -webkit-box;\n  -webkit-line-clamp: 3;\n  /* stylelint-disable-next-line */\n  -webkit-box-orient: vertical;\n  padding: 0;\n  margin: 0 0 4px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nconst Publisher = styled(Text.Span).attrs({\n  size: TextSize.Medium,\n})`\n  display: block;\n  margin: 0;\n  padding: 0;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst StoryPreview = () => {\n  const { title, featuredMedia, publisherLogo, updateStory } = useStory(\n    ({ state: { story }, actions }) => ({\n      title: story?.title,\n      featuredMedia: story?.featuredMedia || {},\n      publisherLogo: story?.publisherLogo || {},\n      updateStory: actions.updateStory,\n    })\n  );\n\n  const { allowedImageMimeTypes, hasUploadMediaAction, publisher } = useConfig(\n    ({ allowedMimeTypes, capabilities, metadata }) => ({\n      allowedImageMimeTypes: allowedMimeTypes?.image || STABLE_ARRAY,\n      hasUploadMediaAction: capabilities?.hasUploadMediaAction,\n      publisher: metadata?.publisher,\n    })\n  );\n\n  const allowedImageFileTypes = useMemo(\n    () =>\n      allowedImageMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedImageMimeTypes]\n  );\n\n  // Honor 2:3 aspect ratio that cover previews have\n  const mediaWidth = 232;\n  const mediaHeight = Math.round(mediaWidth / PAGE_RATIO);\n\n  const handleChangePoster = useCallback(\n    /**\n     * Handle story poster change.\n     *\n     * @param {import('@googleforcreators/media').Resource} newPoster The new image.\n     * @return {void}\n     */\n    (newPoster) => {\n      return updateStory({\n        properties: {\n          featuredMedia: {\n            id: newPoster.id,\n            url: newPoster.src,\n            height: newPoster.height,\n            width: newPoster.width,\n            isExternal: newPoster.isExternal,\n            needsProxy: newPoster.needsProxy,\n          },\n        },\n      });\n    },\n    [updateStory]\n  );\n\n  let posterErrorMessage = __(\n    'No file types are currently supported.',\n    'web-stories'\n  );\n\n  if (allowedImageFileTypes.length) {\n    posterErrorMessage = sprintf(\n      /* translators: %s: list of allowed file types. */\n      __('Please choose only %s as a poster.', 'web-stories'),\n      translateToExclusiveList(allowedImageFileTypes)\n    );\n  }\n\n  const menuOptions = [hasUploadMediaAction && 'upload', 'hotlink'].filter(\n    Boolean\n  );\n\n  return (\n    <>\n      <Headline as=\"label\" size={TextSize.XXSmall}>\n        {__('Cover Preview', 'web-stories')}\n      </Headline>\n      <PreviewWrapper width={mediaWidth} height={mediaHeight}>\n        <PreviewContainer width={mediaWidth} height={mediaHeight}>\n          {featuredMedia?.url ? (\n            <Image\n              crossOrigin=\"anonymous\"\n              decoding=\"async\"\n              src={featuredMedia.url}\n              width={featuredMedia.width}\n              height={featuredMedia.height}\n              alt={__('Preview image', 'web-stories')}\n              data-testid=\"story_preview_featured_media\"\n            />\n          ) : (\n            <EmptyPlaceholder />\n          )}\n          <Gradient />\n          <ScrimWrapper>\n            <ScrimContainer>\n              <ScrimTop>\n                {publisherLogo?.url?.length > 0 && (\n                  <PublisherLogo\n                    crossOrigin=\"anonymous\"\n                    decoding=\"async\"\n                    width={publisherLogo.width}\n                    height={publisherLogo.height}\n                    src={publisherLogo.url}\n                    alt={__('Publisher Logo', 'web-stories')}\n                  />\n                )}\n                <StyledMedia\n                  onChange={handleChangePoster}\n                  title={__('Select as poster image', 'web-stories')}\n                  hotlinkTitle={__(\n                    'Use external image as poster image',\n                    'web-stories'\n                  )}\n                  hotlinkInsertText={__(\n                    'Use image as poster image',\n                    'web-stories'\n                  )}\n                  hotlinkInsertingText={__(\n                    'Using image as poster image',\n                    'web-stories'\n                  )}\n                  buttonInsertText={__('Select as poster image', 'web-stories')}\n                  type={allowedImageMimeTypes}\n                  ariaLabel={__('Poster image', 'web-stories')}\n                  onChangeErrorText={posterErrorMessage}\n                  imgProps={featuredMedia}\n                  variant={MediaVariant.None}\n                  menuOptions={menuOptions}\n                  cropParams={{\n                    width: 640,\n                    height: 853,\n                  }}\n                />\n              </ScrimTop>\n              <ScrimBottom>\n                {title && <Title>{title}</Title>}\n                {publisher && (\n                  <Publisher data-testid=\"story_preview_publisher\">\n                    {publisher}\n                  </Publisher>\n                )}\n              </ScrimBottom>\n            </ScrimContainer>\n          </ScrimWrapper>\n        </PreviewContainer>\n      </PreviewWrapper>\n    </>\n  );\n};\n\nexport default StoryPreview;\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/header/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Headline,\n  Icons,\n  TextSize,\n} from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { HEADER_BAR_HEIGHT, HEADER_BAR_MARGIN } from '../constants';\nimport ButtonWithChecklistWarning from '../../header/buttons/buttonWithChecklistWarning';\n\nconst _Header = styled.header`\n  width: 100%;\n  height: ${HEADER_BAR_HEIGHT};\n  display: flex;\n  align-items: center;\n  margin-bottom: ${HEADER_BAR_MARGIN};\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  border-top-left-radius: ${({ theme }) => theme.borders.radius.medium};\n  border-top-right-radius: ${({ theme }) => theme.borders.radius.medium};\n`;\n\nconst CloseButton = styled(Button)`\n  margin: 6px auto 5px 6px;\n`;\n\nconst PublishButtonWrapper = styled.div`\n  margin: 6px 6px 5px auto;\n`;\n\nconst Header = ({\n  onClose,\n  onPublish,\n  publishButtonDisabled,\n  hasFutureDate,\n}) => {\n  return (\n    <_Header>\n      <CloseButton\n        variant={ButtonVariant.Square}\n        size={ButtonSize.Small}\n        type={ButtonType.Tertiary}\n        onClick={onClose}\n        aria-label={__('Close', 'web-stories')}\n      >\n        <Icons.Cross />\n      </CloseButton>\n      <Headline as=\"h2\" size={TextSize.XXXSmall}>\n        {__('Story Details', 'web-stories')}\n      </Headline>\n      <PublishButtonWrapper>\n        <ButtonWithChecklistWarning\n          onClick={onPublish}\n          disabled={publishButtonDisabled}\n          hasFutureDate={hasFutureDate}\n        />\n      </PublishButtonWrapper>\n    </_Header>\n  );\n};\n\nexport default Header;\n\nHeader.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onPublish: PropTypes.func.isRequired,\n  publishButtonDisabled: PropTypes.bool,\n  hasFutureDate: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as PublishModal } from './publishModal';\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/karma/publishModal.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor, within } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\nimport { useStory } from '../../../app/story';\n\ndescribe('Publish Story Modal', () => {\n  let fixture;\n  let publishModal;\n\n  async function openPublishModal() {\n    const { publish } = fixture.editor.titleBar;\n    await fixture.events.click(publish);\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n\n    await openPublishModal();\n    publishModal = await fixture.screen.findByRole('dialog', {\n      name: /^Story details$/,\n    });\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  function getPublishModalElement(role, name) {\n    const { findByRole } = within(publishModal);\n\n    return findByRole(role, {\n      name,\n    });\n  }\n\n  describe('Basic structure', () => {\n    it('should have no aXe accessibility violations', async () => {\n      await expectAsync(publishModal).toHaveNoViolations();\n    });\n  });\n\n  describe('Functionality', () => {\n    it('should close the publish modal and focus the publish button', async () => {\n      const closeButton = await getPublishModalElement('button', /Close/);\n      await fixture.events.click(closeButton);\n\n      let publish;\n      await waitFor(async () => {\n        // modal may still be mounted, so wait until publish button is visible\n        // this is a `getBy` call, so it will throw an error if it fails\n        publish = await fixture.editor.titleBar.publish;\n      });\n\n      expect(document.activeElement).toBe(publish);\n    });\n\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Needs further investigation.\n    xit('should close the publish modal and open (and focus) the checklist when checklist button is clicked', async () => {\n      const checklistButton = await getPublishModalElement(\n        'button',\n        'Checklist'\n      );\n      await fixture.events.click(checklistButton);\n\n      const updatedPublishModal = fixture.screen.queryByRole('dialog', {\n        name: /^Story details$/,\n      });\n\n      expect(updatedPublishModal).toBeNull();\n      expect(\n        fixture.editor.checklist.issues.getAttribute('data-isexpanded')\n      ).toBe('true');\n\n      // Checklist should be focused\n      expect(document.activeElement).toBe(fixture.editor.checklist.closeButton);\n    });\n\n    it('should not update story permalink when title is updated if permalink already exists', async () => {\n      // Give story initial title\n      const storyTitle = await getPublishModalElement('textbox', 'Story Title');\n      await fixture.events.focus(storyTitle);\n      await fixture.events.keyboard.type('Stews for long journeys');\n      await fixture.events.keyboard.press('tab');\n\n      const storySlug = await getPublishModalElement('textbox', 'URL slug');\n      // that initial title should give us an initial slug\n      expect(storySlug.getAttribute('value')).toBe('stews-for-long-journeys');\n\n      await fixture.events.focus(storySlug);\n      await fixture.events.keyboard.type(\n        \"bilbo's favorite 30 minute rabbit stew\"\n      );\n      await fixture.events.keyboard.press('tab');\n      // now we've updated the slug independent of title\n      expect(storySlug.getAttribute('value')).toBe(\n        'bilbos-favorite-30-minute-rabbit-stew'\n      );\n\n      // Update the title\n      await fixture.events.focus(storyTitle);\n      await fixture.events.keyboard.type('Travel Stews With Bilbo');\n      await fixture.events.keyboard.press('tab');\n\n      // slug should remain as it was\n      expect(storySlug.getAttribute('value')).toBe(\n        'bilbos-favorite-30-minute-rabbit-stew'\n      );\n    });\n\n    it('should toggle from auto page advancement by default to manual', async () => {\n      const manualInput = await getPublishModalElement('radio', 'Manual');\n      const autoInput = await getPublishModalElement('radio', 'Auto');\n\n      await fixture.events.click(manualInput.closest('label'));\n\n      expect(typeof autoInput.getAttribute('checked')).toBe('string');\n      expect(manualInput.getAttribute('checked')).toBeNull();\n    });\n\n    it('should update the featured media', async () => {\n      const originalPoster = fixture.renderHook(() =>\n        useStory(({ state }) => state.story.featuredMedia)\n      );\n\n      const posterImageButton = await getPublishModalElement(\n        'button',\n        'Poster image'\n      );\n\n      await fixture.events.click(posterImageButton);\n\n      const newPoster = fixture.renderHook(() =>\n        useStory(({ state }) => state.story.featuredMedia)\n      );\n\n      expect(originalPoster).not.toEqual(newPoster);\n    });\n  });\n\n  describe('Keyboard navigation', () => {\n    it('should navigate modal by keyboard', async () => {\n      expect(publishModal).toHaveFocus();\n\n      await fixture.events.keyboard.press('tab');\n\n      const closeButton = await getPublishModalElement('button', 'Close');\n      expect(closeButton).toHaveFocus();\n\n      await fixture.events.keyboard.press('tab');\n\n      const publishButton = await getPublishModalElement('button', 'Publish');\n      expect(publishButton).toHaveFocus();\n\n      await fixture.events.keyboard.press('tab');\n\n      const updatePosterImageButton = await getPublishModalElement(\n        'button',\n        'Poster image'\n      );\n      expect(updatePosterImageButton).toHaveFocus();\n\n      await fixture.events.keyboard.press('tab');\n\n      const storyTitle = await getPublishModalElement('textbox', 'Story Title');\n      expect(storyTitle).toHaveFocus();\n\n      await fixture.events.keyboard.press('tab');\n\n      const storyDescription = await getPublishModalElement(\n        'textbox',\n        'Story Description'\n      );\n      expect(storyDescription).toHaveFocus();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/publishModal.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { Modal, theme } from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useCallback, useEffect } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useCheckpoint } from '../checklist';\nimport DirectionAware from '../directionAware';\nimport Header from './header';\nimport Content from './content';\n\nconst Container = styled.div`\n  height: 100%;\n  color: ${theme.colors.fg.primary};\n  background-color: ${theme.colors.bg.primary};\n  border: ${`1px solid ${theme.colors.divider.primary}`};\n  border-radius: ${theme.borders.radius.medium};\n`;\n\nfunction PublishModal({\n  isOpen,\n  onPublish,\n  onClose,\n  publishButtonDisabled,\n  hasFutureDate,\n}) {\n  const openChecklist = useCheckpoint(\n    ({ actions }) => actions.handleReviewChecklist\n  );\n\n  useEffect(() => {\n    if (isOpen) {\n      trackEvent('publish_modal');\n    }\n  }, [isOpen]);\n\n  const handleReviewChecklist = useCallback(() => {\n    trackEvent('review_prepublish_checklist');\n    onClose({ focusPublishButton: false });\n    openChecklist();\n  }, [onClose, openChecklist]);\n\n  return (\n    <Modal\n      isOpen={isOpen}\n      onClose={onClose}\n      contentLabel={__('Story details', 'web-stories')}\n      contentStyles={{\n        display: 'block',\n        width: '71vw',\n        minWidth: '917px',\n        height: '66vh',\n        minHeight: '580px',\n        overflow: 'hidden',\n      }}\n      overlayStyles={{\n        backgroundColor: theme.colors.inverted.interactiveBg.modalScrim,\n      }}\n    >\n      {isOpen && (\n        <DirectionAware>\n          <Container>\n            <Header\n              hasFutureDate={hasFutureDate}\n              publishButtonDisabled={publishButtonDisabled}\n              onClose={onClose}\n              onPublish={onPublish}\n            />\n            <Content handleReviewChecklist={handleReviewChecklist} />\n          </Container>\n        </DirectionAware>\n      )}\n    </Modal>\n  );\n}\n\nexport default PublishModal;\n\nPublishModal.propTypes = {\n  isOpen: PropTypes.bool,\n  onPublish: PropTypes.func.isRequired,\n  onClose: PropTypes.func.isRequired,\n  hasFutureDate: PropTypes.bool,\n  publishButtonDisabled: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../app/story/context';\nimport { ConfigContext } from '../../../app/config';\nimport {\n  ChecklistCountProvider,\n  CheckpointContext,\n  PPC_CHECKPOINT_STATE,\n} from '../../checklist';\nimport SidebarContext from '../../sidebar/context';\nimport { PageAdvancementPanel, SlugPanel } from '../../panels/document';\nimport PublishModal from '../publishModal';\n\nconst MockDocumentPane = () => (\n  <>\n    <SlugPanel />\n    <PageAdvancementPanel />\n  </>\n);\nexport default {\n  title: 'Stories Editor/Components/Dialog/Publish Modal',\n  args: {\n    canPublish: true,\n    hasChecklist: true,\n    hasFutureDate: false,\n    hasPublisherLogo: true,\n    hasFeaturedMedia: true,\n    hasUploadMediaAction: true,\n    hasPriorityIssues: true,\n    publishButtonDisabled: true,\n    publisher: 'Gotham Bugle',\n    isOpen: true,\n    isSaving: false,\n  },\n  argTypes: {\n    onPublish: { action: 'onPublish clicked' },\n    onClose: { action: 'onClose clicked' },\n    handleReviewChecklist: {\n      action: 'handleReviewChecklist clicked',\n    },\n    checkpoint: {\n      options: Object.values(PPC_CHECKPOINT_STATE),\n      control: { type: 'select' },\n      name: \"Checklist's given checkpoint\",\n    },\n    storyStatus: {\n      options: ['publish', 'future', 'private', 'draft'],\n      control: { type: 'select' },\n      name: 'Status of Story',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const {\n      canPublish,\n      checkpoint,\n      isSaving,\n      hasChecklist,\n      hasUploadMediaAction,\n      hasFeaturedMedia,\n      hasPublisherLogo,\n      hasPriorityIssues,\n      handleReviewChecklist,\n      publisher,\n      storyStatus,\n    } = args;\n    const [inputValues, setInputValues] = useState({\n      excerpt: '',\n      title: '',\n      link: 'http://sample.com/post_type=web-story&p=274',\n    });\n\n    const handleUpdateStory = useCallback(({ properties }) => {\n      setInputValues((prevVal) => ({\n        ...prevVal,\n        ...properties,\n      }));\n    }, []);\n    return (\n      <ConfigContext.Provider\n        value={{\n          metadata: {\n            publisher: publisher,\n          },\n          capabilities: {\n            hasUploadMediaAction: hasUploadMediaAction,\n          },\n        }}\n      >\n        <StoryContext.Provider\n          value={{\n            actions: { updateStory: handleUpdateStory },\n            state: {\n              capabilities: { publish: canPublish },\n              meta: { isSaving: isSaving },\n              story: {\n                ...inputValues,\n                permalinkConfig: {\n                  prefix: 'http://sample.com/',\n                  suffix: '',\n                },\n                featuredMedia: {\n                  url: hasFeaturedMedia ? 'http://placekitten.com/230/342' : '',\n                  height: 333,\n                  width: 250,\n                },\n                publisherLogo: {\n                  url: hasPublisherLogo ? 'http://placekitten.com/158/96' : '',\n                  height: 96,\n                  width: 158,\n                },\n                status: storyStatus,\n              },\n            },\n          }}\n        >\n          <SidebarContext.Provider\n            value={{\n              actions: {\n                loadUsers: () => {},\n              },\n              data: {\n                modalSidebarTab: {\n                  title: 'document panel',\n                  DocumentPane: MockDocumentPane,\n                },\n              },\n              state: {\n                users: {},\n                sidebarContentHeight: 600,\n              },\n            }}\n          >\n            <ChecklistCountProvider hasChecklist={hasChecklist}>\n              <CheckpointContext.Provider\n                value={{\n                  actions: {\n                    handleReviewChecklist: handleReviewChecklist,\n                  },\n                  state: {\n                    hasHighPriorityIssues: hasPriorityIssues,\n                    checkpoint: checkpoint,\n                  },\n                }}\n              >\n                <PublishModal {...args} />\n              </CheckpointContext.Provider>\n            </ChecklistCountProvider>\n          </SidebarContext.Provider>\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/test/content.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { ConfigContext } from '../../../app/config';\nimport StoryContext from '../../../app/story/context';\nimport { noop } from '../../../utils/noop';\nimport { ChecklistCountProvider } from '../../checklist';\nimport SidebarContext from '../../sidebar/context';\nimport { INPUT_KEYS } from '../constants';\nimport Content from '../content';\n\nconst mockInputValues = {\n  [INPUT_KEYS.EXCERPT]:\n    'A voyage to the great beyond, where none have gone and going back is impossible.',\n  [INPUT_KEYS.TITLE]: \"David Bowman's Odyssey\",\n  [INPUT_KEYS.SLUG]: '2001-space-odyssey',\n};\n\ndescribe('publishModal/content', () => {\n  const mockHandleReviewChecklist = jest.fn();\n\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  const configContextValue = {\n    allowedMimeTypes: { image: [] },\n    metadata: {\n      publisher: '',\n    },\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    MediaUpload: () => <button onClick={noop}>{'Media Upload Button!'}</button>,\n  };\n\n  const sidebarContextValue = {\n    actions: { loadUsers: jest.fn() },\n    state: {\n      users: [{ value: 'foo' }, { value: 'bar' }],\n    },\n    data: {\n      modalSidebarTab: {\n        DocumentPane: null,\n      },\n    },\n  };\n\n  const view = () => {\n    return renderWithTheme(\n      <ConfigContext.Provider value={configContextValue}>\n        <StoryContext.Provider\n          value={{\n            actions: { updateStory: jest.fn() },\n            state: {\n              story: {\n                ...mockInputValues,\n              },\n            },\n          }}\n        >\n          <SidebarContext.Provider value={sidebarContextValue}>\n            <ChecklistCountProvider hasChecklist>\n              <Content handleReviewChecklist={mockHandleReviewChecklist} />\n            </ChecklistCountProvider>\n          </SidebarContext.Provider>\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    );\n  };\n  it('should have no accessibility issues', async () => {\n    const { container } = view();\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should trigger handleReviewChecklist on checklist button click', () => {\n    view();\n\n    const checklistButton = screen.getByRole('button', { name: 'Checklist' });\n\n    fireEvent.click(checklistButton);\n\n    expect(mockHandleReviewChecklist).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/test/header.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { StoryContext } from '../../../app/story';\nimport { CheckpointContext } from '../../checklist';\nimport Header from '../header';\n\ndescribe('publishModal/header', () => {\n  const mockOnClose = jest.fn();\n  const mockOnPublish = jest.fn();\n\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  const view = (args) => {\n    const { storyArgs = {}, capabilitiesArgs = {} } = args || {};\n    return renderWithTheme(\n      <StoryContext.Provider\n        value={{\n          state: {\n            story: {\n              story: { status: 'draft', ...storyArgs },\n            },\n            capabilities: { publish: true, ...capabilitiesArgs },\n            meta: { isSaving: false },\n          },\n        }}\n      >\n        <CheckpointContext.Provider\n          value={{\n            state: {\n              hasHighPriorityIssues: true,\n              checkpoint: 'all',\n            },\n          }}\n        >\n          <Header\n            onClose={mockOnClose}\n            onPublish={mockOnPublish}\n            hasFutureDate={false}\n          />\n        </CheckpointContext.Provider>\n      </StoryContext.Provider>\n    );\n  };\n\n  it('should have no accessibility issues', async () => {\n    const { container } = view();\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should call onClose when close button is clicked', () => {\n    view();\n\n    const closeButton = screen.getByLabelText('Close');\n    fireEvent.click(closeButton);\n\n    expect(mockOnClose).toHaveBeenCalledOnce();\n  });\n\n  it('should call onPublish when publish button is clicked', () => {\n    view();\n\n    const publishButton = screen.getByText('Publish');\n    fireEvent.click(publishButton);\n\n    expect(mockOnPublish).toHaveBeenCalledOnce();\n  });\n\n  it('should show submit for review when capability of publish is false', () => {\n    view({ capabilitiesArgs: { publish: false } });\n\n    const reviewButton = screen.getByText('Submit for review');\n    fireEvent.click(reviewButton);\n\n    expect(mockOnPublish).toHaveBeenCalledOnce();\n  });\n\n  it('should show tooltip in button when priority issues present', () => {\n    view();\n\n    const publishButton = screen.getByText('Publish');\n    fireEvent.focus(publishButton);\n\n    expect('Make updates before publishing to improve').toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/test/mainStoryInfo.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../../app/story/context';\nimport { ChecklistCountProvider } from '../../checklist';\nimport SidebarContext from '../../sidebar/context';\nimport { INPUT_KEYS } from '../constants';\nimport MainStoryInfo from '../content/mainStoryInfo';\n\nconst mockInputValues = {\n  [INPUT_KEYS.EXCERPT]:\n    'A voyage to the great beyond, where none have gone and going back is impossible.',\n  [INPUT_KEYS.TITLE]: \"David Bowman's Odyssey\",\n  [INPUT_KEYS.SLUG]: '2001-space-odyssey',\n};\n\ndescribe('publishModal/mainStoryInfo', () => {\n  const mockHandleUpdateStory = jest.fn();\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  const sidebarContextValue = {\n    actions: { loadUsers: jest.fn() },\n    state: {\n      users: [{ value: 'foo' }, { value: 'bar' }],\n    },\n    data: {\n      modalSidebarTab: {\n        DocumentPane: null,\n      },\n    },\n  };\n\n  const view = () => {\n    return renderWithTheme(\n      <StoryContext.Provider\n        value={{\n          actions: { updateStory: mockHandleUpdateStory },\n          state: {\n            story: {\n              ...mockInputValues,\n            },\n          },\n        }}\n      >\n        <SidebarContext.Provider value={sidebarContextValue}>\n          <ChecklistCountProvider hasChecklist>\n            <MainStoryInfo />\n          </ChecklistCountProvider>\n        </SidebarContext.Provider>\n      </StoryContext.Provider>\n    );\n  };\n  it('should have no accessibility issues', async () => {\n    const { container } = view();\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should trigger mockHandleUpdateStory on title input blur', () => {\n    view();\n\n    const titleInput = screen.getByRole('textbox', { name: 'Story Title' });\n\n    fireEvent.change(titleInput, {\n      target: { value: \"David Bowman (and HAL's) Odyseey\" },\n    });\n\n    fireEvent.blur(titleInput);\n\n    expect(mockHandleUpdateStory).toHaveBeenCalledOnce();\n  });\n\n  it('should trigger mockHandleUpdateStory on excerpt input change', () => {\n    view();\n\n    const descriptionInput = screen.getByRole('textbox', {\n      name: 'Story Description',\n    });\n\n    fireEvent.change(descriptionInput, {\n      target: { value: 'Lorem ipsum' },\n    });\n\n    fireEvent.blur(descriptionInput);\n\n    expect(mockHandleUpdateStory).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/publishModal/test/storyPreview.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { axe } from 'jest-axe';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport { StoryContext } from '../../../app/story';\nimport { ConfigContext } from '../../../app/config';\nimport StoryPreview from '../content/storyPreview';\n\nconst newPoster = {\n  id: 'new-poster',\n  src: 'new-poster-url',\n  height: '36px',\n  width: '100000px',\n};\n\ndescribe('publishModal/storyPreview', () => {\n  const mockUpdateStory = jest.fn();\n\n  const view = (props) => {\n    const {\n      allowedImageMimeTypes = [],\n      featuredMedia = '',\n      hasUploadMediaAction = false,\n      publisher = '',\n      publisherLogo = '',\n      storyTitle = '',\n    } = props || {};\n\n    return renderWithTheme(\n      <ConfigContext.Provider\n        value={{\n          allowedMimeTypes: { image: allowedImageMimeTypes },\n          metadata: {\n            publisher: publisher,\n          },\n          capabilities: {\n            hasUploadMediaAction,\n          },\n          MediaUpload: ({ onSelect }) => (\n            <button\n              data-testid=\"media-upload-button\"\n              onClick={() => onSelect(newPoster)}\n            >\n              {'Media Upload Button!'}\n            </button>\n          ),\n        }}\n      >\n        <StoryContext.Provider\n          value={{\n            actions: {\n              updateStory: mockUpdateStory,\n            },\n            state: {\n              story: {\n                title: storyTitle,\n                featuredMedia: {\n                  url: featuredMedia,\n                  width: 250,\n                  height: 355,\n                },\n                publisherLogo: {\n                  url: publisherLogo,\n                  width: 25,\n                  height: 25,\n                },\n              },\n            },\n          }}\n        >\n          <StoryPreview />\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    );\n  };\n\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  it('should have no accessibility issues', async () => {\n    const { container } = view({\n      storyTitle: 'Great books to read',\n      featuredMedia: 'http://test.com/imageurl',\n      publisherLogo: 'http://test.com/imageurl',\n      publisher: 'My Site Title',\n    });\n\n    const results = await axe(container);\n    expect(results).toHaveNoViolations();\n  });\n\n  it('should render the story title when present', () => {\n    view({ storyTitle: 'Great books to read' });\n    const storyTitle = screen.getByText('Great books to read');\n\n    expect(storyTitle).toBeInTheDocument();\n  });\n\n  it('should render the site title when present', () => {\n    view({ publisher: 'My Site Title' });\n    const siteTitle = screen.getByText('My Site Title');\n\n    expect(siteTitle).toBeInTheDocument();\n  });\n\n  it('should render the featured media image when present', () => {\n    view({ featuredMedia: 'http://test.com/imageurl' });\n    const featuredMedia = screen.getByTestId('story_preview_featured_media');\n\n    expect(featuredMedia).toBeInTheDocument();\n  });\n\n  it('should render the publisher logo when present', () => {\n    view({ publisherLogo: 'http://test.com/imageurl' });\n    const publisherLogo = screen.getByRole('img', { alt: 'Publisher Logo' });\n\n    expect(publisherLogo).toBeInTheDocument();\n  });\n\n  it('should not render the story title when not present', () => {\n    view();\n    const storyTitle = screen.queryByRole('heading', { level: 3 });\n\n    expect(storyTitle).not.toBeInTheDocument();\n  });\n\n  it('should not render the site title when not present', () => {\n    view();\n    const siteTitle = screen.queryByTestId('story_preview_publisher');\n\n    expect(siteTitle).not.toBeInTheDocument();\n  });\n\n  it('should not render the featured media image when not present', () => {\n    view();\n    const featuredMedia = screen.queryByTestId('story_preview_featured_media');\n\n    expect(featuredMedia).not.toBeInTheDocument();\n  });\n\n  it('should not render the publisher logo when not present', () => {\n    view();\n    const publisherLogo = screen.queryByRole('img', { alt: 'Publisher Logo' });\n\n    expect(publisherLogo).not.toBeInTheDocument();\n  });\n\n  it('should update the poster image when the upload media button is clicked', () => {\n    view({ hasUploadMediaAction: true });\n    const uploadMediaButton = screen.queryByText('Media Upload Button!');\n\n    fireEvent.click(uploadMediaButton);\n\n    expect(mockUpdateStory).toHaveBeenCalledWith({\n      properties: {\n        featuredMedia: {\n          id: newPoster.id,\n          url: newPoster.src,\n          height: newPoster.height,\n          width: newPoster.width,\n          isExternal: newPoster.isExternal,\n          needsProxy: newPoster.needsProxy,\n        },\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as Reorderable } from './reorderable';\nexport { default as ReorderableItem } from './reorderableItem';\nexport { default as ReorderableSeparator } from './reorderableSeparator';\nexport { default as useReorderable } from './useReorderable';\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/reorderable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { forwardRef, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport useReordering from './useReordering';\nimport ReorderableScroller from './reorderableScroller';\nimport useScroll from './useScroll';\n\nconst ReorderableContainer = styled.div.attrs({ role: 'listbox' })`\n  display: flex;\n`;\n\nconst Reorderable = forwardRef(function Reorderable(\n  {\n    children,\n    onPositionChange,\n    getItemSize,\n    scrollSize = null,\n    mode = 'horizontal',\n    ...props\n  },\n  forwardedRef\n) {\n  const ref = useRef(null);\n  const containerRef = forwardedRef || ref;\n  const {\n    isReordering,\n    currentSeparator,\n    setCurrentSeparator,\n    handleStartReordering,\n    currentPosition,\n  } = useReordering(onPositionChange, children.length);\n\n  const { startScroll, canScrollEnd, canScrollStart } = useScroll(\n    mode,\n    isReordering,\n    containerRef,\n    getItemSize()\n  );\n\n  const state = {\n    state: {\n      isReordering,\n      currentSeparator,\n      containerRef,\n      mode,\n      canScrollEnd,\n      canScrollStart,\n      currentPosition,\n    },\n    actions: {\n      setCurrentSeparator,\n      handleStartReordering,\n      startScroll,\n    },\n  };\n\n  const scrollerSize = scrollSize || getItemSize();\n\n  return (\n    <Context.Provider value={state}>\n      <ReorderableContainer ref={containerRef} {...props}>\n        <ReorderableScroller direction={-1} size={scrollerSize} />\n        {children}\n        <ReorderableScroller direction={1} size={scrollerSize} />\n      </ReorderableContainer>\n    </Context.Provider>\n  );\n});\n\nReorderable.propTypes = {\n  children: PropTypes.node,\n  onPositionChange: PropTypes.func.isRequired,\n  getItemSize: PropTypes.func.isRequired,\n  scrollSize: PropTypes.number,\n  mode: PropTypes.string,\n};\n\nexport default Reorderable;\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/reorderableItem.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport useReorderable from './useReorderable';\n\nconst Container = styled.div`\n  z-index: 1;\n`;\n\nfunction ReorderableItem({\n  children,\n  position,\n  onStartReordering,\n  disabled,\n  data,\n  ...props\n}) {\n  const handleStartReordering = useReorderable(\n    ({ actions }) => actions.handleStartReordering\n  );\n\n  return (\n    <Container\n      {...(disabled\n        ? null\n        : {\n            onPointerDown: handleStartReordering({\n              position,\n              onStartReordering,\n              data,\n            }),\n          })}\n      {...props}\n    >\n      {children}\n    </Container>\n  );\n}\n\nReorderableItem.propTypes = {\n  children: PropTypes.node,\n  position: PropTypes.number.isRequired,\n  onStartReordering: PropTypes.func,\n  disabled: PropTypes.bool,\n  data: PropTypes.object,\n};\n\nexport default ReorderableItem;\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/reorderableScroller.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport {\n  useEffect,\n  useState,\n  useCallback,\n  useContext,\n  memo,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport ReorderableContext from './context';\n\nconst Scroller = styled.div`\n  z-index: 3;\n  opacity: 0;\n  position: sticky;\n`;\n\nconst HorizontalScroller = styled(Scroller)`\n  padding-left: ${({ size }) => size}px;\n  height: 100%;\n\n  ${({ direction, size }) =>\n    direction === -1\n      ? `\n        left: 0px;\n        margin-right: -${size}px;\n        `\n      : `\n        right: 0px;\n        margin-left: -${size}px;\n        `}\n`;\nconst VerticalScroller = styled(Scroller)`\n  padding-top: ${({ size }) => size}px;\n  width: 100%;\n\n  ${({ direction, size }) =>\n    direction === -1\n      ? `\n        top: 0px;\n        margin-bottom: -${size}px;\n        `\n      : `\n        bottom: 0px;\n        margin-top: -${size}px;\n        `}\n`;\n\nfunction ReorderableScroller({ direction, size }) {\n  const {\n    state: { canScrollEnd, canScrollStart, mode },\n    actions: { startScroll },\n  } = useContext(ReorderableContext);\n  const [isHovering, setIsHovering] = useState(false);\n  const handlePointerEnter = useCallback(() => setIsHovering(true), []);\n  const handlePointerLeave = useCallback(() => setIsHovering(false), []);\n  useEffect(() => {\n    if (!isHovering) {\n      return undefined;\n    }\n\n    return startScroll(direction);\n  }, [direction, startScroll, isHovering]);\n\n  const isScrollingStart = direction === -1;\n  const isScrollingEnd = direction === 1;\n  const isVisible =\n    (isScrollingStart && canScrollStart) || (isScrollingEnd && canScrollEnd);\n\n  // Make sure to clear hovering flag when hiding element\n  // (pointerLeave won't trigger when element is removed)\n  useEffect(() => {\n    if (!isVisible) {\n      setIsHovering(false);\n    }\n  }, [isVisible]);\n\n  if (!isVisible) {\n    return null;\n  }\n\n  const ScrollerElement =\n    mode === 'horizontal' ? HorizontalScroller : VerticalScroller;\n\n  return (\n    <ScrollerElement\n      size={size}\n      direction={direction}\n      onPointerEnter={handlePointerEnter}\n      onPointerLeave={handlePointerLeave}\n      mode={mode}\n    />\n  );\n}\n\nReorderableScroller.propTypes = {\n  direction: PropTypes.number.isRequired,\n  size: PropTypes.number.isRequired,\n};\n\nexport default memo(ReorderableScroller);\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/reorderableSeparator.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { NESTED_PX } from '../panels/layer/constants';\nimport { noop } from '../../utils/noop';\nimport useReorderable from './useReorderable';\n\nconst Wrapper = styled.div`\n  opacity: 0;\n  position: relative;\n  z-index: ${({ isReordering, isNested }) =>\n    isReordering ? (isNested ? 3 : 2) : -1};\n\n  &:hover {\n    opacity: ${({ isReordering }) => (isReordering ? 1 : 0)};\n  }\n`;\n\nconst Line = styled.div`\n  height: 4px;\n  margin: 0 0 -4px;\n  background: ${({ theme }) => theme.colors.accent.secondary};\n  width: 100%;\n  ${({ isNested }) => isNested && `margin-left: ${NESTED_PX}px;`}\n  width: ${({ isNested }) =>\n    isNested ? `calc(100% - ${NESTED_PX}px)` : '100%'}\n`;\n\nfunction ReorderableSeparator({\n  position,\n  groupId = null,\n  isNested = false,\n  nestedOffset = false,\n  nestedOffsetCalcFunc = noop,\n  children = null,\n  ...props\n}) {\n  const separatorRef = useRef(null);\n  const [isTempNested, setIsTempNested] = useState(false);\n\n  const { isReordering, setCurrentSeparator } = useReorderable(\n    ({ state, actions }) => {\n      const currentPosition = state.currentPosition?.position;\n      const isNextToCurrentItem =\n        currentPosition === position || currentPosition === position - 1;\n      return {\n        isReordering: state.isReordering && !isNextToCurrentItem,\n        isNextToCurrentItem,\n        setCurrentSeparator: actions.setCurrentSeparator,\n      };\n    }\n  );\n\n  const handlePointerEnter = useCallback(() => {\n    if (!isReordering) {\n      return;\n    }\n    setCurrentSeparator({ position, data: { groupId } });\n  }, [setCurrentSeparator, isReordering, position, groupId]);\n\n  const handlePointerMove = (evt) => {\n    if (!nestedOffset) {\n      return;\n    }\n    setIsTempNested(nestedOffsetCalcFunc(evt.nativeEvent));\n  };\n\n  if (children === null) {\n    children = <Line isNested={isNested || isTempNested} />;\n  }\n\n  return (\n    <Wrapper\n      onPointerOver={handlePointerEnter}\n      onPointerMove={handlePointerMove}\n      ref={separatorRef}\n      isReordering={isReordering}\n      isNested={isNested || isTempNested}\n      {...props}\n    >\n      {children}\n    </Wrapper>\n  );\n}\n\nReorderableSeparator.propTypes = {\n  position: PropTypes.number.isRequired,\n  groupId: PropTypes.string,\n  isNested: PropTypes.string,\n  nestedOffset: PropTypes.bool,\n  nestedOffsetCalcFunc: PropTypes.func,\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n};\n\nexport default ReorderableSeparator;\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/useReorderable.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useReorderable(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useReorderable;\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/useReordering.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport {\n  useState,\n  useCallback,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\nimport { useLiveRegion } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\n\nfunction useReordering(onPositionChange, numChildren) {\n  const [isReordering, setIsReordering] = useState(false);\n  const [currentSeparator, setCurrentSeparator] = useState(null);\n  const [currentPosition, setCurrentPosition] = useState(null);\n  const [dragTarget, setDragTarget] = useState(null);\n\n  const speak = useLiveRegion('assertive');\n  const handleStartReordering = useCallback(\n    ({ position: currentPos, data = {}, onStartReordering = noop }) =>\n      (evt) => {\n        // Only allow reordering with non-modified left-click.\n        // Modified (shift, meta, alt, ctrl) clicks are for selection.\n        const isModified =\n          evt.shiftKey || evt.metaKey || evt.ctrlKey || evt.altKey;\n        // Right-clicks (button===2) are for context menu.\n        const isLeftButton = evt.button === 0;\n        if (!isModified && isLeftButton) {\n          onStartReordering();\n          setCurrentPosition({ position: currentPos, data });\n          setDragTarget(evt.target);\n        }\n      },\n    []\n  );\n\n  const separatorRef = useRef(null);\n  useEffect(() => {\n    separatorRef.current = currentSeparator;\n  }, [currentSeparator]);\n\n  useEffect(() => {\n    if (!dragTarget) {\n      return undefined;\n    }\n\n    const onRelease = (evt) => {\n      evt.preventDefault();\n      if (separatorRef.current !== null) {\n        const newPosition = separatorRef.current;\n        const position =\n          newPosition.position > currentPosition.position\n            ? newPosition.position - 1\n            : newPosition.position;\n        onPositionChange(\n          currentPosition,\n          { ...separatorRef.current, position },\n          evt\n        );\n      }\n      setDragTarget(null);\n    };\n\n    // only mark as reordering when starting to drag\n    const onMove = () => setIsReordering(true);\n\n    // abort on esc\n    // TODO: rewrite to useKeyDown() once either is merged.\n    const onAbort = (evt) => {\n      if (evt.key === 'Escape') {\n        setDragTarget(null);\n        evt.stopPropagation();\n      }\n    };\n\n    dragTarget.ownerDocument.addEventListener('pointerup', onRelease);\n    dragTarget.ownerDocument.addEventListener('keydown', onAbort, true);\n    dragTarget.addEventListener('pointermove', onMove);\n\n    return () => {\n      setCurrentSeparator(null);\n      setIsReordering(false);\n      dragTarget.removeEventListener('pointermove', onMove);\n      dragTarget.ownerDocument.removeEventListener('pointerup', onRelease);\n      dragTarget.ownerDocument.removeEventListener('keydown', onAbort, true);\n    };\n  }, [\n    dragTarget,\n    currentPosition,\n    setCurrentSeparator,\n    setIsReordering,\n    onPositionChange,\n  ]);\n\n  useEffect(() => {\n    if (isReordering && currentSeparator) {\n      const position = numChildren - currentSeparator.position;\n      const message = sprintf(\n        /* translators: %d: new position. */\n        __(\n          'Reordering. Press Escape to abort. Release mouse to drop in position %d.',\n          'web-stories'\n        ),\n        String(position)\n      );\n      speak(message);\n    }\n  }, [isReordering, currentSeparator, numChildren, speak]);\n\n  return {\n    isReordering,\n    currentSeparator,\n    setCurrentSeparator,\n    handleStartReordering,\n    currentPosition,\n  };\n}\n\nexport default useReordering;\n"
  },
  {
    "path": "packages/story-editor/src/components/reorderable/useScroll.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useEffect,\n  useBatchingCallback,\n} from '@googleforcreators/react';\n\nconst SCROLL_PERCENT = 0.2;\nconst MAX_SCROLL_STEP = 10;\n\nfunction useScroll(mode = 'horizontal', isReordering, scrollTargetRef, size) {\n  const [hasScrollAbove, setHasScrollAbove] = useState(false);\n  const [hasScrollBelow, setHasScrollBelow] = useState(false);\n  const [scrollDirection, setScrollDirection] = useState(0);\n\n  const updateScrollMarkers = useBatchingCallback(() => {\n    const node = scrollTargetRef.current;\n    if (!node) {\n      return;\n    }\n    if (mode === 'horizontal') {\n      const possibleScroll = node.scrollWidth - node.clientWidth;\n      if (possibleScroll <= 0) {\n        setHasScrollAbove(false);\n        setHasScrollBelow(false);\n      } else {\n        setHasScrollAbove(node.scrollLeft > 0);\n        setHasScrollBelow(node.scrollLeft < possibleScroll);\n      }\n    } else {\n      const possibleScroll = node.scrollHeight - node.clientHeight;\n      if (possibleScroll <= 0) {\n        setHasScrollAbove(false);\n        setHasScrollBelow(false);\n      } else {\n        setHasScrollAbove(node.scrollTop > 0);\n        setHasScrollBelow(node.scrollTop < possibleScroll);\n      }\n    }\n  }, [mode, scrollTargetRef]);\n\n  const startScroll = useCallback(\n    (dir) => {\n      setScrollDirection(dir);\n      return () => setScrollDirection(0);\n    },\n    [setScrollDirection]\n  );\n\n  const canScrollStart = isReordering && hasScrollAbove;\n  const canScrollEnd = isReordering && hasScrollBelow;\n\n  useEffect(() => {\n    const isNotScrolling = scrollDirection === 0;\n    const isScrollingStart = canScrollStart && scrollDirection < 0;\n    const isScrollingEnd = canScrollEnd && scrollDirection > 0;\n    const isScrollingAnywhere = isScrollingStart || isScrollingEnd;\n    if (isNotScrolling || !isScrollingAnywhere) {\n      return undefined;\n    }\n\n    let mounted = true;\n    const update = () => {\n      const scrollStep = Math.max(\n        Math.min(SCROLL_PERCENT * size, MAX_SCROLL_STEP),\n        0\n      );\n      if (mode === 'horizontal') {\n        scrollTargetRef.current.scrollLeft += scrollDirection * scrollStep;\n      } else {\n        scrollTargetRef.current.scrollTop += scrollDirection * scrollStep;\n      }\n      updateScrollMarkers();\n      if (mounted) {\n        window.requestAnimationFrame(update);\n      }\n    };\n    update();\n\n    return () => {\n      mounted = false;\n    };\n  }, [\n    scrollDirection,\n    updateScrollMarkers,\n    canScrollStart,\n    canScrollEnd,\n    size,\n    mode,\n    scrollTargetRef,\n  ]);\n\n  // Update scroll markers whenever isReordering changes (to true really, but no harm)\n  useEffect(() => updateScrollMarkers(), [isReordering, updateScrollMarkers]);\n\n  return {\n    startScroll,\n    canScrollEnd,\n    canScrollStart,\n  };\n}\n\nexport default useScroll;\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/components.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Button, themeHelpers } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\nimport { NAVIGATION_HEIGHT } from './constants';\n\nexport const NavBar = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  width: 100%;\n  height: ${NAVIGATION_HEIGHT}px;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  ${themeHelpers.expandTextPreset(({ label }, { Medium }) => label[Medium])}\n`;\n\nexport const NavButton = styled(Button)`\n  ${themeHelpers.expandTextPreset(({ label }, { Medium }) => label[Medium])}\n  ${focusStyle};\n\n  svg {\n    width: 32px;\n  }\n\n  * + * {\n    margin-left: 12px;\n  }\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const NAVIGATION_HEIGHT = 48;\nexport const NAVIGATION_WIDTH = 308;\nexport const CARD_WIDTH = 272;\nexport const DISTANCE_FROM_TOP = 60 + 32; // toolbar height + input height\nexport const DISTANCE_FROM_BOTTOM = 69;\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport { BEZIER } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { ScheduledTransition } from '../transition/scheduledTransition';\nimport { noop } from '../../utils/noop';\n\nconst DURATION = 300;\n\nconst enterStyles = css`\n  opacity: 1;\n  transform: none;\n`;\nconst exitStyles = (placement) => css`\n  opacity: 0;\n  transform: translateX(${placement === 'left' ? -20 : 20}px);\n`;\n\nconst transitionStyles = {\n  entering: enterStyles,\n  entered: enterStyles,\n  exiting: exitStyles,\n  exited: exitStyles,\n};\n\nconst Controller = styled.div`\n  display: ${({ visible }) => (visible ? 'block' : 'none')};\n  position: absolute;\n  top: -12px;\n  ${({ placement }) => placement}: 0px;\n  opacity: 0;\n  transform: translateX(-20px);\n  transition:\n    opacity ${DURATION}ms ${BEZIER.default},\n    transform ${DURATION}ms ${BEZIER.default};\n  ${({ state }) => transitionStyles[state]}\n`;\n\nfunction Popup({\n  isOpen,\n  popupId,\n  children,\n  ariaLabel,\n  shouldKeepMounted,\n  placement = 'left',\n  onEnter = noop,\n  onExited = noop,\n}) {\n  return (\n    <ScheduledTransition\n      in={isOpen}\n      timeout={DURATION}\n      mountOnEnter={!shouldKeepMounted}\n      unmountOnExit={!shouldKeepMounted}\n      onEnter={onEnter}\n      onExited={onExited}\n    >\n      {(state) => (\n        <Controller\n          id={popupId}\n          role=\"dialog\"\n          aria-label={ariaLabel}\n          state={state}\n          placement={placement}\n          visible={isOpen}\n        >\n          {children}\n        </Controller>\n      )}\n    </ScheduledTransition>\n  );\n}\nPopup.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  children: PropTypes.node.isRequired,\n  popupId: PropTypes.string,\n  ariaLabel: PropTypes.string,\n  placement: PropTypes.oneOf(['left', 'right', 'bottom', 'top']),\n  shouldKeepMounted: PropTypes.bool,\n  onEnter: PropTypes.func,\n  onExited: PropTypes.func,\n};\n\nexport default Popup;\nexport { default as NavigationWrapper } from './navigationWrapper';\nexport {\n  NAVIGATION_HEIGHT,\n  NAVIGATION_WIDTH,\n  CARD_WIDTH,\n  DISTANCE_FROM_TOP,\n  DISTANCE_FROM_BOTTOM,\n} from './constants';\nexport { TopNavigation } from './topNavigation';\nexport { NavBar, NavButton } from './components';\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/navigationWrapper.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport {\n  NAVIGATION_WIDTH,\n  DISTANCE_FROM_TOP,\n  DISTANCE_FROM_BOTTOM,\n} from './constants';\n\nconst NavigationWrapper = styled.div`\n  position: absolute;\n  ${({ alignRight = false }) => (alignRight ? 'right: 0' : 'left: 0')};\n  bottom: 0;\n  max-height: calc(100vh - ${DISTANCE_FROM_TOP + DISTANCE_FROM_BOTTOM}px);\n  width: ${NAVIGATION_WIDTH + 2}px; /* account for border width */\n  color: ${({ theme }) => theme.colors.fg.primary};\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.bg.tertiary};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  overflow: hidden;\n\n  ${({ isOpen }) =>\n    !isOpen &&\n    css`\n      &,\n      * {\n        height: 0;\n        visibility: hidden;\n      }\n    `}\n`;\nNavigationWrapper.propTypes = {\n  alignRight: PropTypes.bool,\n  isOpen: PropTypes.bool,\n};\n\nexport default NavigationWrapper;\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/topNavigation.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { forwardRef } from '@googleforcreators/react';\nimport {\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Headline,\n  Icons,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { forceFocusCompanionToggle } from './utils';\nimport { NavBar, NavButton } from './components';\n\nconst TopNavButtons = styled.div`\n  padding-right: 15px;\n`;\n\nconst Label = styled(Headline).attrs({\n  as: 'h2',\n  size: TextSize.XXSmall,\n})`\n  padding-left: 24px;\n  font-weight: ${({ theme }) => theme.typography.weight.regular};\n`;\n\nexport const TopNavigation = forwardRef(function TopNavigation(\n  { onClose, label, popupId },\n  ref\n) {\n  return (\n    <NavBar>\n      <Label>{label}</Label>\n      <TopNavButtons>\n        <NavButton\n          ref={ref}\n          aria-label={__('Close', 'web-stories')}\n          onClick={() => {\n            forceFocusCompanionToggle(popupId);\n            onClose();\n          }}\n          type={ButtonType.Plain}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Circle}\n        >\n          <Icons.Cross />\n        </NavButton>\n      </TopNavButtons>\n    </NavBar>\n  );\n});\n\nTopNavigation.propTypes = {\n  isOpen: PropTypes.bool,\n  onClose: PropTypes.func.isRequired,\n  label: PropTypes.string.isRequired,\n  popupId: PropTypes.string.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/secondaryPopup/utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport function forceFocusCompanionToggle(popupId) {\n  document.querySelector(`[aria-owns=${popupId}]`)?.focus();\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/shopping/frame.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { Placement } from '@googleforcreators/design-system';\nimport { ELEMENT_TYPES } from '@googleforcreators/elements';\nimport { useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../propTypes';\nimport Tooltip from '../tooltip';\nimport { useConfig, useFont } from '../../app';\nimport PillIcon from './icons/pill.svg';\n\n// See https://github.com/ampproject/amphtml/blob/b2dbb6b805529b7cf699dad3a91f6d7556131543/extensions/amp-story-shopping/0.1/amp-story-shopping-tag.css\n\nconst StyledTooltip = styled(Tooltip)`\n  align-items: center;\n  p {\n    display: flex;\n    max-width: 100%;\n    color: #fff;\n    font-family: 'Poppins', sans-serif;\n    font-weight: 700;\n    font-size: 14px;\n    line-height: 24px;\n    padding: 0;\n  }\n\n  background-color: rgba(125, 125, 125, 0.75);\n  border-radius: 18px;\n  padding-inline-start: 6px;\n  padding-inline-end: 12px;\n  cursor: pointer;\n  height: 36px;\n`;\n\nconst PillImage = styled.span`\n  width: 24px;\n  height: 24px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background-color: rgba(0, 0, 0, 0.6);\n  border-radius: 100%;\n  flex-shrink: 0;\n  margin-inline-end: 4px;\n`;\n\nfunction TooltipTitle({ productTagText }) {\n  return (\n    <>\n      <PillImage>\n        <PillIcon width={14} height={14} aria-hidden />\n      </PillImage>\n      {productTagText}\n    </>\n  );\n}\n\nTooltipTitle.propTypes = {\n  productTagText: PropTypes.string.isRequired,\n};\n\nfunction WithProductPill({ element, active, children, anchorRef }) {\n  const {\n    actions: { maybeEnqueueFontStyle },\n  } = useFont();\n\n  const {\n    locale: { locale },\n  } = useConfig();\n\n  const elementType = element.type;\n  useEffect(() => {\n    if (elementType !== ELEMENT_TYPES.PRODUCT) {\n      return;\n    }\n\n    maybeEnqueueFontStyle([\n      {\n        font: {\n          family: 'Poppins',\n          service: 'fonts.google.com',\n          weights: [700],\n          styles: ['regular'],\n          variants: [[0, 700]],\n        },\n        fontWeight: 700,\n      },\n    ]);\n  }, [elementType, maybeEnqueueFontStyle]);\n\n  if (elementType !== ELEMENT_TYPES.PRODUCT) {\n    return children;\n  }\n\n  const { productPrice, productPriceCurrency, productTitle } = element.product;\n\n  const productTagText =\n    productPrice && productPriceCurrency && locale\n      ? new Intl.NumberFormat(locale, {\n          style: 'currency',\n          currency: productPriceCurrency,\n        }).format(productPrice)\n      : productTitle;\n\n  return (\n    <StyledTooltip\n      forceAnchorRef={anchorRef}\n      placement={Placement.Right}\n      hasTail={false}\n      title={active ? <TooltipTitle productTagText={productTagText} /> : null}\n    >\n      {children}\n    </StyledTooltip>\n  );\n}\n\nWithProductPill.propTypes = {\n  element: StoryPropTypes.element.isRequired,\n  anchorRef: PropTypes.object,\n  active: PropTypes.bool.isRequired,\n  children: PropTypes.node.isRequired,\n};\n\nexport default WithProductPill;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const INSERT = 'insert';\nexport const STYLE = 'design';\nexport const DOCUMENT = 'document';\nexport const PUBLISH_MODAL_DOCUMENT = 'publish_modal_document';\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {}, tabs: {}, refs: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { INSERT, DOCUMENT, STYLE } from './constants';\nexport { default } from './sidebar';\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/karma/sidebarTabs.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../../karma';\n\ndescribe('Sidebar Tabs integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('Sidebar Tabs aXe tests', () => {\n    it('should have no aXe violations', async () => {\n      const { documentTab } = fixture.editor.sidebar;\n\n      // Click document tab\n      await fixture.events.click(documentTab);\n      // actual color contrast of toggle is 7.1 however it's set on a child span absolutely positioned so aXe doesn't pick it up\n      await expectAsync(\n        fixture.editor.sidebar.documentPanel.node\n      ).toHaveNoViolations();\n    });\n  });\n\n  describe('keyboard navigation', () => {\n    it('should return focus to current tab when pressing mod+alt+3', async () => {\n      const { documentTab } = fixture.editor.sidebar;\n\n      // Click document tab\n      await fixture.events.click(documentTab);\n      await waitFor(() => {\n        if (!fixture.editor.sidebar.documentPanel) {\n          throw new Error('panel not ready');\n        }\n        expect(fixture.editor.sidebar.documentPanel).toBeTruthy();\n      });\n\n      expect(documentTab).toHaveFocus();\n\n      // Click elsewhere\n      await fixture.events.click(fixture.editor.canvas.header.title);\n      expect(documentTab).not.toHaveFocus();\n\n      // Return focus with shortcut\n      await fixture.events.keyboard.shortcut('mod+alt+3');\n      expect(documentTab).toHaveFocus();\n      await fixture.snapshot('document tab has focus');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/sidebar.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { UploadDropTarget } from '../uploadDropTarget';\n\nimport SidebarLayout from './sidebarLayout';\n\nfunction Sidebar() {\n  return (\n    <UploadDropTarget disabled>\n      <SidebarLayout />\n    </UploadDropTarget>\n  );\n}\n\nexport default Sidebar;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/sidebarContent.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n/**\n * Internal dependencies\n */\nimport useSidebar from './useSidebar';\nimport { getTabId } from './utils';\n\nconst SidebarPane = styled.div.attrs({ role: 'tabpanel' })`\n  height: 100%;\n  overflow: auto;\n`;\n\nconst SidebarPanes = styled.section`\n  height: 100%;\n`;\n\nfunction Sidebar() {\n  const { tab, tabs } = useSidebar(({ state: { tab }, data: { tabs } }) => ({\n    tab,\n    tabs,\n  }));\n\n  return (\n    <SidebarPanes>\n      {tabs.map(({ id, Pane }) => (\n        <SidebarPane\n          aria-labelledby={id}\n          id={getTabId(id)}\n          key={id}\n          hidden={id !== tab}\n        >\n          {id === tab && <Pane />}\n        </SidebarPane>\n      ))}\n    </SidebarPanes>\n  );\n}\n\nexport default Sidebar;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/sidebarLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useEscapeToBlurEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport TabView from '../tabview';\nimport useHighlights from '../../app/highlights/useHighlights';\nimport useSidebar from './useSidebar';\nimport SidebarContent from './sidebarContent';\nimport { getTabId } from './utils';\n\nconst Layout = styled.section.attrs({\n  'aria-label': __('Sidebar', 'web-stories'),\n})`\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst SidebarContainer = styled.div`\n  height: 100%;\n  padding: 0;\n  overflow: auto;\n`;\n\nconst UnjustifiedTabView = styled(TabView)`\n  justify-content: center;\n`;\n\nfunction SidebarLayout() {\n  const { tab, tabRefs, setSidebarContentNode, setTab, sidebar, tabs } =\n    useSidebar(\n      ({\n        state: { tab, tabRefs },\n        actions: { setSidebarContentNode, setTab },\n        refs: { sidebar },\n        data: { tabs },\n      }) => ({\n        tab,\n        tabRefs,\n        setSidebarContentNode,\n        setTab,\n        sidebar,\n        tabs,\n      })\n    );\n\n  const { resetHighlight } = useHighlights((state) => ({\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onTabChange = useCallback(\n    (id) => {\n      setTab(id);\n      resetHighlight();\n      trackEvent('inspector_tab_change', {\n        name: id,\n      });\n    },\n    [setTab, resetHighlight]\n  );\n\n  useEscapeToBlurEffect(sidebar);\n  return (\n    <Layout ref={sidebar}>\n      <UnjustifiedTabView\n        label={__('Sidebar Selection', 'web-stories')}\n        tabs={tabs}\n        tab={tab}\n        tabRefs={tabRefs}\n        onTabChange={onTabChange}\n        getAriaControlsId={getTabId}\n        shortcut=\"mod+option+3\"\n      />\n      <SidebarContainer ref={setSidebarContentNode}>\n        <SidebarContent />\n      </SidebarContainer>\n    </Layout>\n  );\n}\n\nexport default SidebarLayout;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/sidebarProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useState,\n  useRef,\n  useEffect,\n  useMemo,\n  useResizeEffect,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../../app/api';\nimport { useStory } from '../../app/story';\nimport { states, useHighlights } from '../../app/highlights';\nimport Library from '../library';\nimport Style from '../style';\nimport { DOCUMENT, STYLE, PUBLISH_MODAL_DOCUMENT, INSERT } from './constants';\nimport Context from './context';\n\nconst TABS = [\n  {\n    id: INSERT,\n    title: __('Insert', 'web-stories'),\n    Pane: Library,\n  },\n  {\n    id: STYLE,\n    title: __('Style', 'web-stories'),\n    Pane: Style,\n  },\n];\n\nconst SIDEBAR_TAB_IDS = new Set([INSERT, DOCUMENT, STYLE]);\nfunction SidebarProvider({ sidebarTabs, children }) {\n  const {\n    actions: { getAuthors },\n  } = useAPI();\n  const { selectedElementIds, currentPage } = useStory(({ state }) => ({\n    selectedElementIds: state.selectedElementIds,\n    currentPage: state.currentPage,\n  }));\n\n  const { tab: highlightedTab, highlight } = useHighlights((state) => ({\n    tab: state.tab,\n    highlight: state[states.StylePane],\n  }));\n\n  const sidebarRef = useRef(null);\n\n  const [tab, setTab] = useState(INSERT);\n  const [users, setUsers] = useState([]);\n  const [sidebarContentHeight, setSidebarContentHeight] = useState(null);\n  const sidebarContentRef = useRef();\n  const tabRef = useRef(tab);\n\n  // set tab when content is highlighted\n  useEffect(() => {\n    if (SIDEBAR_TAB_IDS.has(highlightedTab)) {\n      setTab(highlightedTab);\n      trackEvent('quick_action_tab_change', {\n        name: highlightedTab,\n      });\n    }\n  }, [highlightedTab]);\n\n  const insertPaneRef = useRef(null);\n  const designPaneRef = useRef(null);\n  const documentPaneRef = useRef(null);\n\n  const tabRefs = useMemo(\n    () => ({\n      [INSERT]: insertPaneRef,\n      [STYLE]: designPaneRef,\n      [DOCUMENT]: documentPaneRef,\n    }),\n    []\n  );\n\n  const [usersLoadingState, setUsersLoadingState] = useState('idle');\n\n  const setSidebarContentNode = useCallback((node) => {\n    sidebarContentRef.current = node;\n  }, []);\n\n  useResizeEffect(\n    sidebarContentRef,\n    ({ height }) => setSidebarContentHeight(height),\n    []\n  );\n\n  useEffect(() => {\n    if (selectedElementIds.length > 0 && tabRef.current === DOCUMENT) {\n      setTab(STYLE);\n    }\n  }, [selectedElementIds]);\n\n  useEffect(() => {\n    if (tabRef.current === DOCUMENT) {\n      setTab(STYLE);\n    }\n  }, [currentPage]);\n\n  // focus design pane when highlighted\n  useEffect(() => {\n    const node = designPaneRef.current;\n    if (node && highlight?.focus && highlight?.showEffect) {\n      node.focus();\n    }\n  }, [highlight]);\n\n  const loadUsers = useCallback(() => {\n    if (\n      usersLoadingState !== 'finished' &&\n      usersLoadingState !== 'errored' &&\n      users.length === 0\n    ) {\n      setUsersLoadingState('loading');\n      getAuthors()\n        .then((data) => {\n          const saveData = data.map(({ id, name }) => ({\n            id,\n            name,\n          }));\n          setUsers(saveData);\n          setUsersLoadingState('finished');\n        })\n        .catch(() => {\n          // Do nothing for now.\n          setUsersLoadingState('errored');\n        });\n    }\n  }, [usersLoadingState, users.length, getAuthors]);\n\n  const tabs = useMemo(\n    () =>\n      [\n        ...TABS,\n        sidebarTabs?.document && {\n          id: DOCUMENT,\n          ...sidebarTabs.document,\n        },\n      ].filter(Boolean),\n    [sidebarTabs]\n  );\n\n  const data = useMemo(\n    () => ({\n      tabs,\n      modalSidebarTab: sidebarTabs?.publishModal && {\n        id: PUBLISH_MODAL_DOCUMENT,\n        ...sidebarTabs.publishModal,\n      },\n    }),\n    [tabs, sidebarTabs]\n  );\n\n  const state = {\n    state: {\n      tab,\n      tabRefs,\n      users,\n      sidebarContentHeight,\n      usersLoadingState,\n    },\n    refs: {\n      sidebar: sidebarRef,\n    },\n    actions: {\n      setTab,\n      loadUsers,\n      setSidebarContentNode,\n    },\n    data,\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nSidebarProvider.propTypes = {\n  children: PropTypes.node,\n  sidebarTabs: PropTypes.object,\n};\n\nexport default SidebarProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/useSidebar.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useSidebar(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useSidebar;\n"
  },
  {
    "path": "packages/story-editor/src/components/sidebar/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Helper to generate tab html ID.\n *\n * @param {string}id ID as string\n * @return {string} Formatted ID.\n */\nexport const getTabId = (id) => {\n  return `sidebar-tab-${id}`;\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/storyFontPicker/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { forwardRef, useCallback } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { stripHTML } from '@googleforcreators/dom';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useFont, useStory } from '../../app';\nimport getUpdatedSizeAndPosition from '../../utils/getUpdatedSizeAndPosition';\nimport useRichTextFormatting from '../panels/design/textStyle/useRichTextFormatting';\nimport getClosestFontWeight from '../panels/design/textStyle/getClosestFontWeight';\nimport { getCommonValue } from '../panels/shared';\nimport FontPicker from '../fontPicker';\nimport updateProperties from '../style/updateProperties';\n\nconst StoryFontPicker = forwardRef(function StoryFontPicker(\n  { selectedElements, ...rest },\n  ref\n) {\n  const { updateElementsById } = useStory(({ actions }) => ({\n    updateElementsById: actions.updateElementsById,\n  }));\n\n  const selectedElementIds = selectedElements.map(({ id }) => id);\n\n  const pushUpdate = useCallback(\n    (update, commitValues) => {\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: (element) => {\n          const updates = updateProperties(element, update, commitValues);\n          const sizeUpdates = getUpdatedSizeAndPosition({\n            ...element,\n            ...updates,\n          });\n          return {\n            ...updates,\n            ...sizeUpdates,\n          };\n        },\n      });\n    },\n    [updateElementsById, selectedElementIds]\n  );\n\n  const {\n    textInfo: { fontWeight, isItalic },\n    handlers: { handleResetFontWeight },\n  } = useRichTextFormatting(selectedElements, pushUpdate);\n\n  const { addRecentFont, maybeEnqueueFontStyle } = useFont(({ actions }) => ({\n    addRecentFont: actions.addRecentFont,\n    maybeEnqueueFontStyle: actions.maybeEnqueueFontStyle,\n  }));\n\n  const fontFamily = getCommonValue(\n    selectedElements,\n    ({ font }) => font?.family\n  );\n\n  const fontStyle = isItalic ? 'italic' : 'normal';\n\n  const onChange = useCallback(\n    async (newFont) => {\n      const { id, name, value, ...newFontFormatted } = newFont;\n      void trackEvent('font_family_changed', { name });\n\n      await maybeEnqueueFontStyle(\n        selectedElements.map(({ content }) => {\n          return {\n            font: newFontFormatted,\n            fontStyle,\n            fontWeight,\n            content: stripHTML(content),\n          };\n        })\n      );\n      addRecentFont(newFont);\n      pushUpdate({ font: newFontFormatted }, true);\n\n      const newFontWeight = getClosestFontWeight(400, newFontFormatted.weights);\n      await handleResetFontWeight(newFontWeight);\n    },\n    [\n      addRecentFont,\n      fontStyle,\n      fontWeight,\n      maybeEnqueueFontStyle,\n      pushUpdate,\n      selectedElements,\n      handleResetFontWeight,\n    ]\n  );\n\n  return (\n    <FontPicker\n      onChange={onChange}\n      currentValue={fontFamily}\n      {...rest}\n      ref={ref}\n    />\n  );\n});\n\nStoryFontPicker.propTypes = {\n  highlightStylesOverride: PropTypes.array,\n};\n\nexport default StoryFontPicker;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { STYLE_PANE_IDS } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport SelectionIcon from './icons/selectionIcon';\nimport LinkIcon from './icons/linkIcon';\nimport AnimationIcon from './icons/animationIcon';\n\nexport const SELECTION = {\n  id: STYLE_PANE_IDS.Selection,\n  icon: SelectionIcon,\n  tooltip: __('Selection', 'web-stories'),\n};\nexport const LINK = {\n  id: STYLE_PANE_IDS.Link,\n  icon: LinkIcon,\n  tooltip: __('Link', 'web-stories'),\n};\nexport const ANIMATION = {\n  id: STYLE_PANE_IDS.Animation,\n  icon: AnimationIcon,\n  tooltip: __('Animation', 'web-stories'),\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/style/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {}, tabs: {}, refs: {} });\n"
  },
  {
    "path": "packages/story-editor/src/components/style/designPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { StoryPropTypes } from '../../propTypes';\nimport FormContext from '../form/context';\nimport useHandlers from '../../utils/useHandlers';\nimport updateProperties from './updateProperties';\n\nconst Form = styled.form`\n  padding: 0;\n  margin: 0;\n`;\n\nconst AutoSubmitButton = styled.input.attrs({ type: 'submit' })`\n  display: none;\n`;\n\n// NOTE: data flow for updating elements with pushUpdate documented in `docs/design-panel-push-update-flow.md`\n\nfunction DesignPanel({\n  panelType,\n  selectedElements,\n  selectedElementIds,\n  onSetProperties,\n  registerSubmitHandler,\n  ...rest\n}) {\n  const formRef = useRef(null);\n  const [presubmitHandlers, registerPresubmitHandler] = useHandlers();\n\n  const formContext = useMemo(\n    () => ({\n      isMultiple: selectedElements.length > 1,\n      registerPresubmitHandler,\n    }),\n    [selectedElements, registerPresubmitHandler]\n  );\n\n  const [elementUpdates, setElementUpdates] = useState({});\n\n  const updatedElements = useMemo(() => {\n    return selectedElements.map((element) => ({\n      ...element,\n      ...elementUpdates[element.id],\n    }));\n  }, [selectedElements, elementUpdates]);\n\n  const internalSubmit = useCallback(\n    (updates) => {\n      if (Object.keys(updates).length === 0) {\n        return;\n      }\n\n      const commitUpdates = updates;\n      if (presubmitHandlers.length > 0) {\n        selectedElements.forEach((element) => {\n          const precommitUpdate = updateProperties(\n            element,\n            updates[element.id],\n            /* commitValues */ true\n          );\n          let commitUpdate = precommitUpdate;\n          presubmitHandlers.forEach((handler) => {\n            const handlerUpdate = handler(\n              { ...element, ...commitUpdate },\n              precommitUpdate,\n              element\n            );\n            commitUpdate = { ...commitUpdate, ...handlerUpdate };\n          });\n          commitUpdates[element.id] = commitUpdate;\n        });\n      }\n\n      onSetProperties((element) => commitUpdates[element.id]);\n    },\n    [presubmitHandlers, selectedElements, onSetProperties]\n  );\n\n  const onSubmit = registerSubmitHandler(\n    useCallback(\n      (evt) => {\n        if (evt) {\n          evt.preventDefault();\n          // Reset.\n          setElementUpdates({});\n        }\n        internalSubmit(elementUpdates);\n      },\n      [internalSubmit, elementUpdates]\n    )\n  );\n\n  const internalSubmitRef = useRef();\n  useEffect(() => {\n    internalSubmitRef.current = internalSubmit;\n  }, [internalSubmit]);\n\n  const elementUpdatesRef = useRef();\n  useEffect(() => {\n    elementUpdatesRef.current = elementUpdates;\n  }, [elementUpdates]);\n\n  useEffect(() => {\n    setElementUpdates({});\n    internalSubmitRef.current(elementUpdatesRef.current);\n  }, []);\n\n  const submit = useCallback(() => {\n    // eslint-disable-next-line @wordpress/react-no-unsafe-timeout -- Only depends on the `ref` and thus save from dismount issues.\n    setTimeout(() => {\n      const form = formRef.current;\n      if (form) {\n        form.dispatchEvent(\n          new window.Event('submit', { cancelable: true, bubbles: true })\n        );\n      }\n    });\n  }, []);\n\n  const pushUpdate = useCallback(\n    (update, submitArg = false) => {\n      setElementUpdates((prevUpdates) => {\n        const newUpdates = {};\n        selectedElements.forEach((element) => {\n          const prevUpdatedElement = { ...element, ...prevUpdates[element.id] };\n          const newUpdate = updateProperties(prevUpdatedElement, update, false);\n          newUpdates[element.id] = { ...prevUpdates[element.id], ...newUpdate };\n        });\n        return newUpdates;\n      });\n      if (submitArg) {\n        submit();\n      }\n    },\n    [selectedElements, submit]\n  );\n\n  const pushUpdateForObject = useCallback(\n    (propertyName, update, defaultObject, submitArg = false) => {\n      pushUpdate((prevUpdatedElement) => {\n        const prevObject = prevUpdatedElement[propertyName] || defaultObject;\n        return {\n          [propertyName]: update\n            ? {\n                ...prevObject,\n                ...updateProperties(prevObject, update, false),\n              }\n            : null,\n        };\n      }, submitArg);\n    },\n    [pushUpdate]\n  );\n\n  const Panel = panelType;\n  return (\n    <Form ref={formRef} onSubmit={onSubmit}>\n      <AutoSubmitButton />\n      <FormContext.Provider value={formContext}>\n        <Panel\n          selectedElements={updatedElements}\n          submittedSelectedElements={selectedElements}\n          pushUpdate={pushUpdate}\n          pushUpdateForObject={pushUpdateForObject}\n          submit={submit}\n          {...rest}\n        />\n      </FormContext.Provider>\n    </Form>\n  );\n}\n\nDesignPanel.propTypes = {\n  panelType: PropTypes.func.isRequired,\n  selectedElements: PropTypes.arrayOf(StoryPropTypes.element).isRequired,\n  selectedElementIds: PropTypes.arrayOf(PropTypes.string).isRequired,\n  onSetProperties: PropTypes.func.isRequired,\n  registerSubmitHandler: PropTypes.func.isRequired,\n};\n\nexport default DesignPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/getDesignPanelsForSelection.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PanelTypes } from '@googleforcreators/design-system';\nimport { elementTypes } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport {\n  AnimationPanel,\n  BorderStylePanel,\n  CaptionsPanel,\n  FilterPanel,\n  ImageAccessibilityPanel,\n  LinkPanel,\n  PageAttachmentPanel,\n  PageBackgroundPanel,\n  ShapeStylePanel,\n  SizePositionPanel,\n  TextAccessibilityPanel,\n  TextStylePanel,\n  VideoAccessibilityPanel,\n  ElementAlignmentPanel,\n  VideoOptionsPanel,\n  VideoSegmentPanel,\n  PageBackgroundAudioPanel,\n  PageAdvancementPanel,\n  ProductPanel,\n  AudioStickerPanel,\n} from '../panels/design';\n\nconst ALL = Object.values(PanelTypes);\n\nfunction intersect(a, b) {\n  return a.filter((v) => b.includes(v));\n}\n\nfunction getDesignPanelsForSelection(elements) {\n  if (elements.length === 0) {\n    return [];\n  }\n\n  const isBackground = elements.length === 1 && elements[0].isBackground;\n\n  // Only display background panel in case of background element.\n  if (isBackground) {\n    const panels = [];\n\n    const isBackgroundMedia = !elements[0].isDefaultBackground;\n    if (isBackgroundMedia) {\n      panels.push({\n        type: PanelTypes.PageBackground,\n        Panel: PageBackgroundPanel,\n      });\n      panels.push({\n        type: PanelTypes.Filter,\n        Panel: FilterPanel,\n      });\n      panels.push({ type: PanelTypes.Animation, Panel: AnimationPanel });\n    }\n\n    // If the selected element's type is video / image , display accessibility panel, too.\n    if ('video' === elements[0].type) {\n      panels.push({ type: PanelTypes.VideoOptions, Panel: VideoOptionsPanel });\n      panels.push({ type: PanelTypes.VideoSegment, Panel: VideoSegmentPanel });\n      panels.push({\n        type: PanelTypes.Captions,\n        Panel: CaptionsPanel,\n      });\n      panels.push({\n        type: PanelTypes.VideoAcessibility,\n        Panel: VideoAccessibilityPanel,\n      });\n    } else if (['gif', 'image'].includes(elements[0].type)) {\n      panels.push({\n        type: PanelTypes.ImageAccessibility,\n        Panel: ImageAccessibilityPanel,\n      });\n      // In case of default background without media:\n    } else {\n      panels.unshift({\n        type: PanelTypes.PageBackground,\n        Panel: PageBackgroundPanel,\n      });\n    }\n\n    panels.push({\n      type: PanelTypes.PageAttachment,\n      Panel: PageAttachmentPanel,\n    });\n\n    panels.push({\n      type: PanelTypes.PageBackgroundAudio,\n      Panel: PageBackgroundAudioPanel,\n    });\n\n    panels.push({\n      type: PanelTypes.PageAdvancement,\n      Panel: PageAdvancementPanel,\n    });\n\n    return panels;\n  }\n\n  // Find which panels all the selected elements have in common\n  return elements\n    .map(({ type }) => elementTypes[type].panels)\n    .reduce((commonPanels, panels) => intersect(commonPanels, panels), ALL)\n    .map((type) => {\n      switch (type) {\n        case PanelTypes.Animation:\n          return { type, Panel: AnimationPanel };\n        case PanelTypes.PageBackground:\n          // Only display when isBackground.\n          return null;\n        case PanelTypes.Filter:\n          return { type, Panel: FilterPanel };\n        case PanelTypes.SizePosition:\n          return { type, Panel: SizePositionPanel };\n        case PanelTypes.Link:\n          return { type, Panel: LinkPanel };\n        case PanelTypes.TextStyle:\n          return { type, Panel: TextStylePanel };\n        case PanelTypes.TextAccessibility:\n          return { type, Panel: TextAccessibilityPanel };\n        case PanelTypes.ShapeStyle:\n          return { type, Panel: ShapeStylePanel };\n        case PanelTypes.Border:\n          return { type, Panel: BorderStylePanel };\n        case PanelTypes.VideoOptions:\n          return { type, Panel: VideoOptionsPanel };\n        case PanelTypes.VideoSegment:\n          return { type, Panel: VideoSegmentPanel };\n        case PanelTypes.Captions:\n          return { type, Panel: CaptionsPanel };\n        case PanelTypes.VideoAcessibility:\n          return { type, Panel: VideoAccessibilityPanel };\n        case PanelTypes.ImageAccessibility:\n          return { type, Panel: ImageAccessibilityPanel };\n        case PanelTypes.ElementAlignment:\n          return { type, Panel: ElementAlignmentPanel };\n        case PanelTypes.Product: {\n          return { type, Panel: ProductPanel };\n        }\n        case PanelTypes.AudioSticker: {\n          return { type, Panel: AudioStickerPanel };\n        }\n        default:\n          throw new Error(`Unknown panel: ${type}`);\n      }\n    })\n    .filter((panel) => panel);\n}\n\nexport default getDesignPanelsForSelection;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/animationIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction AnimationIcon() {\n  return <Icons.CircleSpeed title={__('Animation', 'web-stories')} />;\n}\n\nexport default AnimationIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/audioStickerSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction AudioStickerSelectionIcon() {\n  return (\n    <Icons.AudioSticker title={__('Audio Sticker selection', 'web-stories')} />\n  );\n}\n\nexport default AudioStickerSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/imageSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction ImageSelectionIcon() {\n  return <Icons.Picture title={__('Image selection', 'web-stories')} />;\n}\n\nexport default ImageSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/linkIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction LinkIcon() {\n  return <Icons.Link title={__('Link', 'web-stories')} />;\n}\n\nexport default LinkIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/multiSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction MultiSelectionIcon() {\n  return <Icons.Dots title={__('Multi selection', 'web-stories')} />;\n}\n\nexport default MultiSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/productSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\nconst StyledIcon = styled(Icons.Shopping)`\n  width: 32px !important;\n  height: 32px !important;\n`;\n\nfunction ProductSelectionIcon() {\n  return <StyledIcon title={__('Product selection', 'web-stories')} />;\n}\n\nexport default ProductSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/selectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction SelectionIcon() {\n  return <Icons.Box4 title={__('Selection', 'web-stories')} />;\n}\n\nexport default SelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/shapeSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction ShapeSelectionIcon() {\n  return <Icons.Shapes title={__('Shape selection', 'web-stories')} />;\n}\n\nexport default ShapeSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/textSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction TextSelectionIcon() {\n  return <Icons.LetterT title={__('Text selection', 'web-stories')} />;\n}\n\nexport default TextSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/icons/videoSelectionIcon.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { Icons } from '@googleforcreators/design-system';\n\nfunction VideoSelectionIcon() {\n  return <Icons.Video title={__('Video selection', 'web-stories')} />;\n}\n\nexport default VideoSelectionIcon;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './style';\nexport * from './constants';\n"
  },
  {
    "path": "packages/story-editor/src/components/style/style.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport StyleProvider from './styleProvider';\nimport StyleLayout from './styleLayout';\n\nfunction Style() {\n  return (\n    <StyleProvider>\n      <StyleLayout />\n    </StyleProvider>\n  );\n}\n\nexport default Style;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/styleLayout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport { TextSize, Text } from '@googleforcreators/design-system';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport TabView from '../tabview';\nimport { states, useHighlights } from '../../app/highlights';\nimport { getTabId, getPaneId } from '../library/panes/shared';\nimport { useStory } from '../../app/story';\nimport useStyle from './useStyle';\nimport { SELECTION, LINK, ANIMATION } from './constants';\nimport StylePanes from './stylePanes';\n\nconst Layout = styled.section.attrs({\n  'aria-label': __('Style', 'web-stories'),\n  'data-testid': 'styleLayout',\n})`\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n  background-color: ${({ theme }) => theme.colors.bg.secondary};\n  color: ${({ theme }) => theme.colors.fg.primary};\n  max-height: 100%;\n`;\n\nconst TabsArea = styled.nav.attrs({\n  'aria-label': __('Style tabs', 'web-stories'),\n})``;\n\nconst UnjustifiedTabView = styled(TabView)`\n  justify-content: center;\n`;\n\nconst StylePaneContainer = styled.div`\n  height: 100%;\n  overflow-y: auto;\n  min-height: 0;\n`;\n\nconst NoSelection = styled.div`\n  height: 100%;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst Note = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nfunction StyleLayout() {\n  const {\n    state: { tab },\n    actions: { setTab },\n    refs: { tabRefs },\n    data: { tabs },\n  } = useStyle();\n\n  const { selectedElementIds } = useStory(({ state }) => ({\n    selectedElementIds: state.selectedElementIds,\n  }));\n\n  const { highlight, resetHighlight } = useHighlights((state) => ({\n    highlight: {\n      [SELECTION.id]: state[states.Style],\n      [LINK.id]: state[states.Style],\n      [ANIMATION.id]: state[states.Style],\n    },\n    resetHighlight: state.onFocusOut,\n  }));\n\n  const onTabChange = useCallback(\n    (id) => {\n      setTab(id);\n      resetHighlight();\n      trackEvent('style_tab_change', {\n        name: id,\n      });\n    },\n    [setTab, resetHighlight]\n  );\n\n  if (selectedElementIds.length === 0) {\n    return (\n      <NoSelection>\n        <Note size={TextSize.Medium}>\n          {__('Nothing selected', 'web-stories')}\n        </Note>\n      </NoSelection>\n    );\n  }\n\n  return (\n    <Layout>\n      <TabsArea>\n        <UnjustifiedTabView\n          label={__('Style Selection', 'web-stories')}\n          tabs={tabs}\n          tabRefs={tabRefs}\n          tab={tab}\n          onTabChange={onTabChange}\n          onTabRefUpdated={(node, tabId) => {\n            const h = highlight[tabId];\n            if (node && h?.focus && h?.showEffect) {\n              node.focus();\n            }\n          }}\n          getTabId={getTabId}\n          getAriaControlsId={getPaneId}\n        />\n      </TabsArea>\n      <StylePaneContainer>\n        <StylePanes />\n      </StylePaneContainer>\n    </Layout>\n  );\n}\n\nexport default StyleLayout;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/stylePanes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { PanelSections } from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { Pane, getTabId, getPaneId } from '../library/panes/shared';\nimport useStyle from './useStyle';\nimport { SELECTION, LINK, ANIMATION } from './constants';\nimport DesignPanel from './designPanel';\nimport useDesignPanels from './useDesignPanels';\n\nexport const StyledPane = styled(Pane)`\n  height: 100%;\n  padding: 0;\n  overflow-y: auto;\n`;\n\nfunction StylePanes() {\n  const { tab, tabs } = useStyle((state) => ({\n    tab: state.state.tab,\n    tabs: state.data.tabs,\n  }));\n  const { panels, createSubmitHandlerForPanel, panelProperties } =\n    useDesignPanels();\n\n  const getPanelsByType = useCallback(\n    (types, paneProps) => {\n      const panelsList = panels\n        .filter(({ type }) => types.includes(type))\n        .map(({ Panel, type }) => (\n          <DesignPanel\n            key={type}\n            panelType={Panel}\n            registerSubmitHandler={createSubmitHandlerForPanel(type)}\n            {...panelProperties}\n          />\n        ));\n      return (\n        <StyledPane id={getPaneId(paneProps.key)} {...paneProps}>\n          {panelsList}\n        </StyledPane>\n      );\n    },\n    [panels, createSubmitHandlerForPanel, panelProperties]\n  );\n\n  return tabs.map(({ id }) => {\n    const isActive = id === tab;\n    const paneProps = {\n      key: id,\n      isActive,\n      'aria-labelledby': getTabId(id),\n    };\n\n    if (!isActive) {\n      return <Pane key={id} {...paneProps} />;\n    }\n\n    switch (id) {\n      case SELECTION.id:\n        return getPanelsByType(PanelSections[id], paneProps);\n      case LINK.id:\n        return getPanelsByType(PanelSections[id], paneProps);\n      case ANIMATION.id:\n        return getPanelsByType(PanelSections[id], paneProps);\n      default:\n        return null;\n    }\n  });\n}\n\nexport default StylePanes;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/styleProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useState, useRef, useEffect, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app/story';\nimport { useHighlights } from '../../app/highlights';\nimport { SELECTION, LINK, ANIMATION } from './constants';\nimport Context from './context';\nimport TextSelectionIcon from './icons/textSelectionIcon';\nimport ImageSelectionIcon from './icons/imageSelectionIcon';\nimport VideoSelectionIcon from './icons/videoSelectionIcon';\nimport ShapeSelectionIcon from './icons/shapeSelectionIcon';\nimport MultiSelectionIcon from './icons/multiSelectionIcon';\nimport ProductSelectionIcon from './icons/productSelectionIcon';\nimport AudioStickerSelectionIcon from './icons/audioStickerSelectionIcon';\n\nconst STYLE_TAB_IDS = new Set([SELECTION.id, LINK.id, ANIMATION.id]);\n\nfunction StyleProvider({ children }) {\n  const { selectedElements } = useStory(({ state }) => ({\n    selectedElements: state.selectedElements,\n  }));\n\n  const { tab: highlightedTab } = useHighlights((state) => ({\n    tab: state.section,\n  }));\n\n  const styleRef = useRef(null);\n  const [tab, setTab] = useState(SELECTION.id);\n  const selectionPaneRef = useRef(null);\n  const linkPaneRef = useRef(null);\n  const animationPaneRef = useRef(null);\n\n  // set tab when content is highlighted\n  useEffect(() => {\n    if (STYLE_TAB_IDS.has(highlightedTab)) {\n      setTab(highlightedTab);\n    }\n  }, [highlightedTab]);\n\n  const tabRefs = useMemo(\n    () => ({\n      [SELECTION.id]: selectionPaneRef,\n      [LINK.id]: linkPaneRef,\n      [ANIMATION.id]: animationPaneRef,\n    }),\n    []\n  );\n\n  let selectionIcon = MultiSelectionIcon;\n  const icons = [...new Set(selectedElements.map(({ type }) => type))];\n  if (icons.length === 1) {\n    if (icons[0] === 'text') {\n      selectionIcon = TextSelectionIcon;\n    }\n    if (icons[0] === 'image' || selectedElements[0].isBackground) {\n      selectionIcon = ImageSelectionIcon;\n    }\n    if (icons[0] === 'video') {\n      selectionIcon = VideoSelectionIcon;\n    }\n    if (icons[0] === 'shape' || icons[0] === 'sticker') {\n      selectionIcon = ShapeSelectionIcon;\n    }\n    if (icons[0] === 'product') {\n      selectionIcon = ProductSelectionIcon;\n    }\n    if (icons[0] === 'audioSticker') {\n      selectionIcon = AudioStickerSelectionIcon;\n    }\n  } else {\n    selectionIcon = MultiSelectionIcon;\n  }\n\n  const state = {\n    state: {\n      tab,\n    },\n    refs: {\n      styleRef,\n      tabRefs,\n    },\n    actions: {\n      setTab,\n    },\n    data: {\n      tabs: [{ ...SELECTION, icon: selectionIcon }],\n    },\n  };\n\n  const isBackgroundSelected =\n    selectedElements[0]?.isBackground ||\n    selectedElements[0]?.isDefaultBackground;\n\n  const hasProductsSelected = selectedElements.some(\n    ({ type }) => type === 'product'\n  );\n\n  const hasAudioStickersSelected = selectedElements.some(\n    ({ type }) => type === 'audioSticker'\n  );\n\n  if (\n    !isBackgroundSelected &&\n    !hasProductsSelected &&\n    !hasAudioStickersSelected\n  ) {\n    state.data.tabs.push(LINK);\n  }\n\n  if (\n    !selectedElements[0]?.isDefaultBackground &&\n    !hasProductsSelected &&\n    !hasAudioStickersSelected\n  ) {\n    state.data.tabs.push(ANIMATION);\n  }\n\n  // Reset the tab to Selection if the currently selected tab doesn't exist for the given selection.\n  useEffect(() => {\n    if (!state.data.tabs.find((t) => t.id === tab)) {\n      setTab(SELECTION.id);\n    }\n  }, [state.data.tabs, tab]);\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nStyleProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default StyleProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/test/designPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, act, fireEvent } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport useFormContext from '../../form/useFormContext';\nimport { usePresubmitHandler } from '../../form';\nimport DesignPanel from '../designPanel';\nimport { MULTIPLE_VALUE } from '../../../constants';\n\ndescribe('DesignPanel', () => {\n  let element1, element2;\n  let presubmitHandler1, presubmitHandler2;\n  let registerSubmitHandler;\n  let submitHandler;\n  let onSetProperties;\n  let formContext;\n  let lastProps;\n\n  beforeEach(() => {\n    element1 = {\n      id: '1',\n      type: 'image',\n      x: 11,\n      y: 12,\n      width: 111,\n      height: 121,\n      rotationAngle: 0,\n      z: 17,\n    };\n    element2 = {\n      id: '2',\n      type: 'text',\n      x: 111,\n      y: 112,\n      width: 211,\n      height: 221,\n      rotationAngle: 1,\n    };\n    onSetProperties = jest.fn();\n    formContext = null;\n    presubmitHandler1 = jest.fn(({ x }) => ({ x: x + 1 }));\n    presubmitHandler2 = jest.fn(({ y }) => ({ y: y + 1 }));\n    registerSubmitHandler = (handler) => {\n      submitHandler = handler;\n      return handler;\n    };\n  });\n\n  function CustomPanel(props) {\n    lastProps = { ...props };\n    formContext = useFormContext();\n    usePresubmitHandler(presubmitHandler1, []);\n    usePresubmitHandler(presubmitHandler2, []);\n    return <div />;\n  }\n\n  describe('single element', () => {\n    it('should configure form context', () => {\n      render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1]}\n          selectedElementIds={[element1.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      expect(formContext.isMultiple).toBeFalse();\n      expect(formContext.registerPresubmitHandler).toStrictEqual(\n        expect.any(Function)\n      );\n    });\n\n    it('should push and accumulate updates', () => {\n      render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1]}\n          selectedElementIds={[element1.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      const { pushUpdate } = lastProps;\n\n      // First update.\n      act(() => pushUpdate({ x: 12, y: MULTIPLE_VALUE, z: '' }));\n      const {\n        selectedElements: [updatedElementA],\n      } = lastProps;\n      expect(updatedElementA).toStrictEqual({\n        ...element1,\n        x: 12,\n        z: '',\n      });\n\n      // Second update.\n      act(() => pushUpdate({ x: 12, y: 14 }));\n      const {\n        selectedElements: [updatedElementB],\n      } = lastProps;\n      expect(updatedElementB).toStrictEqual({\n        ...element1,\n        x: 12,\n        y: 14,\n        z: '',\n      });\n\n      const any = expect.anything();\n      expect(presubmitHandler1).not.toHaveBeenCalledWith(any, any, any);\n      expect(presubmitHandler2).not.toHaveBeenCalledWith(any, any, any);\n      expect(onSetProperties).not.toHaveBeenCalledWith(any);\n    });\n\n    it('should submit updates and run presubmits', () => {\n      const { container } = render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1]}\n          selectedElementIds={[element1.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      const { pushUpdate } = lastProps;\n\n      // First update.\n      act(() => pushUpdate({ x: 12, y: MULTIPLE_VALUE, z: '' }));\n      const {\n        selectedElements: [updatedElementA],\n      } = lastProps;\n      expect(updatedElementA).toStrictEqual({\n        ...element1,\n        x: 12,\n        z: '',\n      });\n\n      // eslint-disable-next-line testing-library/no-node-access\n      fireEvent.submit(container.firstElementChild);\n\n      const any = expect.anything();\n      expect(presubmitHandler1).toHaveBeenCalledWith(any, any, any);\n      expect(presubmitHandler2).toHaveBeenCalledWith(any, any, any);\n\n      const presubmitArgs = presubmitHandler1.mock.calls[0];\n      // Based on: presubmit(newElement, update, oldElement).\n      expect(presubmitArgs[0]).toStrictEqual({\n        ...element1,\n        x: 12,\n      });\n      expect(presubmitArgs[1]).toStrictEqual({\n        x: 12,\n      });\n      expect(presubmitArgs[2]).toStrictEqual(element1);\n\n      expect(onSetProperties).toHaveBeenCalledWith(any);\n      const func = onSetProperties.mock.calls[0][0];\n      expect(func(element1)).toStrictEqual({\n        x: 12 + 1,\n        y: element1.y + 1,\n      });\n    });\n\n    it('should submit updates and run presubmits on exit', () => {\n      render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1]}\n          selectedElementIds={[element1.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      const { pushUpdate } = lastProps;\n\n      // First update.\n      act(() => pushUpdate({ x: 12, y: MULTIPLE_VALUE }));\n      const {\n        selectedElements: [updatedElementA],\n      } = lastProps;\n      expect(updatedElementA).toStrictEqual({\n        ...element1,\n        x: 12,\n      });\n\n      // Submit on exit.\n      act(() => submitHandler());\n      const any = expect.anything();\n      expect(presubmitHandler1).toHaveBeenCalledWith(any, any, any);\n      expect(presubmitHandler2).toHaveBeenCalledWith(any, any, any);\n      expect(onSetProperties).toHaveBeenCalledWith(any);\n      const func = onSetProperties.mock.calls[0][0];\n      expect(func(element1)).toStrictEqual({\n        x: 12 + 1,\n        y: element1.y + 1,\n      });\n    });\n  });\n\n  describe('multiple elements', () => {\n    it('should configure form context', () => {\n      render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1, element2]}\n          selectedElementIds={[element1.id, element2.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      expect(formContext.isMultiple).toBeTrue();\n    });\n\n    it('should push updates to all elements', () => {\n      render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1, element2]}\n          selectedElementIds={[element1.id, element2.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      const { pushUpdate } = lastProps;\n\n      act(() => pushUpdate({ x: 12, y: MULTIPLE_VALUE }));\n      const {\n        selectedElements: [updatedElement1, updatedElement2],\n      } = lastProps;\n      expect(updatedElement1).toStrictEqual({\n        ...element1,\n        x: 12,\n      });\n      expect(updatedElement2).toStrictEqual({\n        ...element2,\n        x: 12,\n      });\n    });\n\n    it('should submit updates and run presubmits', () => {\n      const { container } = render(\n        <DesignPanel\n          panelType={CustomPanel}\n          selectedElements={[element1, element2]}\n          selectedElementIds={[element1.id, element2.id]}\n          onSetProperties={onSetProperties}\n          registerSubmitHandler={registerSubmitHandler}\n        />\n      );\n\n      const { pushUpdate } = lastProps;\n\n      // First update.\n      act(() => pushUpdate({ x: 12, y: MULTIPLE_VALUE }));\n      const {\n        selectedElements: [updatedElementA],\n      } = lastProps;\n      expect(updatedElementA).toStrictEqual({\n        ...element1,\n        x: 12,\n      });\n\n      // eslint-disable-next-line testing-library/no-node-access\n      fireEvent.submit(container.firstElementChild);\n      expect(presubmitHandler1).toHaveBeenCalledTimes(2);\n      expect(presubmitHandler2).toHaveBeenCalledTimes(2);\n      expect(onSetProperties).toHaveBeenCalledOnce();\n      const func = onSetProperties.mock.calls[0][0];\n      expect(func(element1)).toStrictEqual({\n        x: 12 + 1,\n        y: element1.y + 1,\n      });\n      expect(func(element2)).toStrictEqual({\n        x: 12 + 1,\n        y: element2.y + 1,\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/style/test/updateProperties.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport updateProperties from '../updateProperties';\nimport { MULTIPLE_VALUE } from '../../../constants';\n\ndescribe('updateProperties', () => {\n  let element;\n\n  beforeEach(() => {\n    element = {\n      x: 11,\n      y: 12,\n      width: 111,\n      height: 121,\n    };\n  });\n\n  it('should update properties with a map', () => {\n    const update = updateProperties(element, { x: 21, y: 22 });\n    expect(update).toStrictEqual({ x: 21, y: 22 });\n  });\n\n  it('should update properties with a function', () => {\n    const update = updateProperties(element, ({ x, y }) => ({\n      x: x + 1,\n      y: y + 1,\n    }));\n    expect(update).toStrictEqual({ x: 12, y: 13 });\n  });\n\n  it('should tolerate null/undefined', () => {\n    expect(updateProperties(element, null)).toStrictEqual({});\n    expect(updateProperties(element, undefined)).toStrictEqual({});\n    expect(updateProperties(element, () => null)).toStrictEqual({});\n    expect(updateProperties(element, () => undefined)).toStrictEqual({});\n  });\n\n  it('should remove \"multi\" values', () => {\n    expect(\n      updateProperties(element, { x: MULTIPLE_VALUE, y: 1 })\n    ).toStrictEqual({ y: 1 });\n  });\n\n  it('should keep intermediary \"empty\" values', () => {\n    expect(updateProperties(element, { x: '', y: 1 })).toStrictEqual({\n      x: '',\n      y: 1,\n    });\n  });\n\n  it('should remove final \"empty\" values', () => {\n    expect(updateProperties(element, { x: '', y: 1 }, true)).toStrictEqual({\n      y: 1,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/style/updateProperties.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { MULTIPLE_VALUE } from '../../constants';\n\n/**\n * @param {Object} currentProperties The existing element properties.\n * @param {Object|function(Object):Object} newPropertiesOrUpdater Either a map\n * of the updated properties or a function that will return a map of the updated\n * properties.\n * @param {boolean} commitValues Commit values.\n * @return {Object} The updated properties.\n */\nfunction updateProperties(\n  currentProperties,\n  newPropertiesOrUpdater,\n  commitValues\n) {\n  const newProperties =\n    typeof newPropertiesOrUpdater === 'function'\n      ? newPropertiesOrUpdater(currentProperties)\n      : newPropertiesOrUpdater;\n  if (!newProperties) {\n    return {};\n  }\n\n  let updatedKeys = Object.keys(newProperties);\n  // Always filter out \"multi\" values since they can be easily recalculated at\n  // any time.\n  updatedKeys = updatedKeys.filter(\n    (key) => newProperties[key] !== MULTIPLE_VALUE\n  );\n  // Only filter out the empty values at the commit time since an empty value\n  // is a valid intermediary value.\n  if (commitValues) {\n    updatedKeys = updatedKeys.filter((key) => newProperties[key] !== '');\n  }\n  if (updatedKeys.length === 0) {\n    // Of course abort if no keys have a value\n    return {};\n  }\n  return Object.fromEntries(\n    updatedKeys.map((key) => [key, newProperties[key]])\n  );\n}\n\nexport default updateProperties;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/useDesignPanels.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app';\nimport useHandlers from '../../utils/useHandlers';\nimport updateProperties from './updateProperties';\nimport getDesignPanelsForSelection from './getDesignPanelsForSelection';\n\nfunction useDesignPanels() {\n  const {\n    selectedElementIds,\n    selectedElements,\n    selectedElementAnimations,\n    deleteSelectedElements,\n    updateElementsById,\n    updateAnimationState,\n  } = useStory(\n    ({\n      state: {\n        selectedElementIds,\n        selectedElements,\n        selectedElementAnimations,\n      },\n      actions: {\n        deleteSelectedElements,\n        updateElementsById,\n        updateAnimationState,\n      },\n    }) => {\n      return {\n        selectedElementIds,\n        selectedElements,\n        selectedElementAnimations,\n        deleteSelectedElements,\n        updateElementsById,\n        updateAnimationState,\n      };\n    }\n  );\n\n  const panels = useMemo(\n    () => getDesignPanelsForSelection(selectedElements),\n    [selectedElements]\n  );\n  const [submitHandlers, registerSubmitHandler] = useHandlers();\n  const onSetProperties = useCallback(\n    (newPropertiesOrUpdater) => {\n      updateElementsById({\n        elementIds: selectedElementIds,\n        properties: (element) => {\n          const updates = updateProperties(\n            element,\n            newPropertiesOrUpdater,\n            /* commitValues */ true\n          );\n\n          return updates;\n        },\n      });\n    },\n    [selectedElementIds, updateElementsById]\n  );\n\n  const createSubmitHandlerForPanel = useCallback(\n    (panelId) => (submit) => {\n      submitHandlers.forEach((handler) =>\n        handler(onSetProperties, panelId, submit)\n      );\n      return submit;\n    },\n    [onSetProperties, submitHandlers]\n  );\n\n  useEffect(() => {\n    const submits = {};\n    const handler = (onSetPropertiesArg, panelId, submit) => {\n      if (onSetProperties === onSetPropertiesArg) {\n        submits[panelId] = submit;\n      }\n    };\n    const unregister = registerSubmitHandler(handler);\n    return () => {\n      unregister();\n      Object.values(submits).forEach((submit) => submit());\n    };\n  }, [onSetProperties, registerSubmitHandler]);\n\n  return useMemo(\n    () => ({\n      panels,\n      createSubmitHandlerForPanel,\n      panelProperties: {\n        onSetProperties,\n        deleteSelectedElements,\n        selectedElements,\n        selectedElementIds,\n        selectedElementAnimations,\n        updateAnimationState,\n      },\n    }),\n    [\n      panels,\n      createSubmitHandlerForPanel,\n      onSetProperties,\n      deleteSelectedElements,\n      selectedElements,\n      selectedElementIds,\n      selectedElementAnimations,\n      updateAnimationState,\n    ]\n  );\n}\n\nexport default useDesignPanels;\n"
  },
  {
    "path": "packages/story-editor/src/components/style/useStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useStyle(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useStyle;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/components.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  Button,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\n\nexport const NoStylesWrapper = styled.div`\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  width: calc(100% + 32px);\n  margin: 0 0 -8px -16px;\n  background-color: ${({ theme }) => theme.colors.opacity.black24};\n  height: 64px;\n`;\n\nexport const MoreButton = styled(Button).attrs({\n  type: ButtonType.Plain,\n  size: ButtonSize.Small,\n  variant: ButtonVariant.Rectangle,\n})`\n  ${focusStyle};\n  margin: 12px 0;\n  padding: 0 16px;\n  justify-content: center;\n  align-self: center;\n  width: 100%;\n  svg {\n    transform: rotate(-90deg);\n    height: 32px;\n    width: 32px;\n    margin-left: -4px;\n  }\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/confirmationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { v4 as uuidv4 } from 'uuid';\nimport { useState } from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport {\n  Text,\n  Checkbox,\n  TextSize,\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Dialog from '../dialog';\nimport { STORAGE_KEY } from './constants';\n\nconst Label = styled.label`\n  margin-left: 12px;\n`;\n\nconst CheckboxWrapper = styled.footer`\n  display: flex;\n  margin-top: 12px;\n  padding: 14px 0 0 9px;\n  border-top: 1px solid ${({ theme }) => theme.colors.divider.primary};\n`;\n\nfunction ConfirmationDialog({ onClose, onPrimary }) {\n  const [isDialogDismissed, setIsDialogDismissed] = useState(\n    localStore.getItemByKey(LOCAL_STORAGE_PREFIX[STORAGE_KEY])\n  );\n  const dialogText = __(\n    'This is a global style. Deleting this style will remove it from the Saved Styles across all stories and the style will no longer be available to any other users on the site.',\n    'web-stories'\n  );\n  const cbId = `cb-${uuidv4()}`;\n  return (\n    <Dialog\n      isOpen\n      onClose={onClose}\n      secondaryText={__('Cancel', 'web-stories')}\n      onPrimary={onPrimary}\n      primaryText={__('Delete', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>{dialogText}</Text.Paragraph>\n      <CheckboxWrapper>\n        <Checkbox\n          id={cbId}\n          checked={isDialogDismissed}\n          onChange={() => {\n            localStore.setItemByKey(\n              LOCAL_STORAGE_PREFIX[STORAGE_KEY],\n              !isDialogDismissed\n            );\n            setIsDialogDismissed(!isDialogDismissed);\n          }}\n        />\n        <Label htmlFor={cbId}>\n          <Text.Span size={TextSize.Small}>\n            {__(\"Don't ask for confirmation again.\", 'web-stories')}\n          </Text.Span>\n        </Label>\n      </CheckboxWrapper>\n    </Dialog>\n  );\n}\n\nConfirmationDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onPrimary: PropTypes.func.isRequired,\n};\n\nexport default ConfirmationDialog;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const STORAGE_KEY = 'DELETE_STYLE_PRESET_DIALOG_DISMISSED';\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useRef, useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  Button,\n  Icons,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { focusStyle } from '../panels/shared/styles';\nimport { noop } from '../../utils/noop';\n\nconst HEADER_HEIGHT = 44;\n\nconst Wrapper = styled.div`\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  height: ${HEADER_HEIGHT}px;\n  padding: 4px 8px 4px 8px;\n  position: relative;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.tertiary};\n`;\n\nconst Actions = styled.div`\n  display: flex;\n  margin-left: auto;\n`;\n\nconst StyledButton = styled(Button)`\n  margin-left: 8px;\n  ${focusStyle};\n`;\n\nfunction Header({\n  children,\n  handleClose,\n  isEditMode = false,\n  setIsEditMode = noop,\n}) {\n  const ref = useRef();\n  useEffect(() => {\n    ref.current?.focus();\n  }, []);\n\n  const buttonProps = {\n    type: ButtonType.Tertiary,\n    size: ButtonSize.Small,\n    onClick: (evt) => {\n      evt.stopPropagation();\n      setIsEditMode(!isEditMode);\n    },\n    isEditMode,\n  };\n\n  return (\n    <Wrapper>\n      {children}\n      <Actions>\n        {isEditMode ? (\n          <StyledButton\n            {...buttonProps}\n            variant={ButtonVariant.Rectangle}\n            aria-label={__('Exit edit mode', 'web-stories')}\n          >\n            {__('Done', 'web-stories')}\n          </StyledButton>\n        ) : (\n          <StyledButton\n            {...buttonProps}\n            variant={ButtonVariant.Square}\n            aria-label={__('Edit style', 'web-stories')}\n          >\n            <Icons.Pencil />\n          </StyledButton>\n        )}\n        <StyledButton\n          aria-label={__('Close', 'web-stories')}\n          onClick={handleClose}\n          type={ButtonType.Tertiary}\n          size={ButtonSize.Small}\n          variant={ButtonVariant.Square}\n          ref={ref}\n        >\n          <Icons.Cross />\n        </StyledButton>\n      </Actions>\n    </Wrapper>\n  );\n}\n\nHeader.propTypes = {\n  children: PropTypes.node,\n  handleClose: PropTypes.func.isRequired,\n  isEditMode: PropTypes.bool,\n  setIsEditMode: PropTypes.func,\n  hasPresets: PropTypes.bool,\n};\n\nexport default Header;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './styleManager';\nexport * from './components';\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/stories/confirmationDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport ConfirmationDialog from '../confirmationDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Panels/TextStyle/StylePresets/Dialog',\n  component: ConfirmationDialog,\n  argTypes: {\n    onClose: { action: 'closed' },\n    onPrimary: { action: 'confirmed' },\n  },\n  parameters: {\n    controls: { hideNoControlsWarning: true },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <ConfirmationDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/styleGroup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { useState, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { SAVED_STYLE_HEIGHT, PRESET_TYPES } from '../../constants';\nimport useKeyboardNavigation from './useKeyboardNavigation';\nimport StyleItem from './styleItem';\n\nconst Group = styled.div`\n  display: grid;\n  grid-template-columns: repeat(2, 1fr);\n  grid-column-gap: 20px;\n  grid-row-gap: 16px;\n`;\n\nconst ButtonWrapper = styled.div`\n  height: ${SAVED_STYLE_HEIGHT}px;\n  width: ${({ width }) => width}px;\n`;\n\nfunction StyleGroup({\n  styles,\n  isEditMode = false,\n  handleClick,\n  buttonWidth = 128,\n  ...rest\n}) {\n  const [activeIndex, setActiveIndex] = useState(0);\n  const groupRef = useRef(null);\n\n  useKeyboardNavigation({\n    activeIndex,\n    setActiveIndex,\n    groupRef,\n    type: PRESET_TYPES.STYLE,\n  });\n\n  return (\n    <Group ref={groupRef}>\n      {styles.map((style, i) => (\n        <ButtonWrapper key={JSON.stringify(style)} width={buttonWidth}>\n          <StyleItem\n            style={style}\n            i={i}\n            activeIndex={activeIndex}\n            handleOnClick={handleClick}\n            isEditMode={isEditMode}\n            {...rest}\n          />\n        </ButtonWrapper>\n      ))}\n    </Group>\n  );\n}\n\nStyleGroup.propTypes = {\n  styles: PropTypes.array.isRequired,\n  handleClick: PropTypes.func.isRequired,\n  isEditMode: PropTypes.bool,\n  buttonWidth: PropTypes.number,\n};\n\nexport default StyleGroup;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/styleItem.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { generatePatternStyles } from '@googleforcreators/patterns';\nimport { Icons } from '@googleforcreators/design-system';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\nimport { useState } from '@googleforcreators/react';\nimport { stripHTML } from '@googleforcreators/dom';\n\n/**\n * Internal dependencies\n */\nimport { generatePresetStyle } from '../../utils/presetUtils';\nimport { useStory } from '../../app/story';\nimport { focusStyle } from '../panels/shared/styles';\n\nconst REMOVE_ICON_SIZE = 32;\n\nconst PresetButton = styled.button`\n  background-color: ${({ theme }) =>\n    theme.colors.interactiveBg.secondaryNormal};\n  border-color: transparent;\n  position: relative;\n  cursor: pointer;\n  border-width: 0;\n  border-radius: 4px;\n  padding: 3px;\n  height: 100%;\n  width: 100%;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  > svg {\n    width: ${REMOVE_ICON_SIZE}px;\n    height: ${REMOVE_ICON_SIZE}px;\n    position: absolute;\n    top: calc(50% - ${REMOVE_ICON_SIZE / 2}px);\n    left: calc(50% - ${REMOVE_ICON_SIZE / 2}px);\n    color: ${({ theme }) => theme.colors.fg.primary};\n    filter: drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.4));\n  }\n  ${focusStyle}\n`;\n\nconst HighLight = styled.span`\n  padding: 0 2px;\n  ${({ background }) => generatePatternStyles(background)}\n  box-decoration-break: clone;\n`;\n\nconst LINE_HEIGHT = 20;\nconst TextWrapper = styled.div`\n  position: relative;\n  display: inline-block;\n  line-height: ${LINE_HEIGHT}px;\n  max-height: ${LINE_HEIGHT * 2 + 3}px;\n  overflow: hidden;\n  border-radius: 4px;\n  padding: 3px;\n  max-width: 100%;\n  ${({ styles }) => styles}\n  font-size: 12px;\n  ${({ background }) => (background ? generatePatternStyles(background) : null)}\n`;\n\nfunction StyleItem({\n  style,\n  i,\n  activeIndex,\n  handleOnClick,\n  isEditMode,\n  activeItemOverlay,\n  applyLabel = __('Apply style', 'web-stories'),\n}) {\n  const selectedElements = useStory(({ state }) => state.selectedElements);\n  const [isActive, setIsActive] = useState(false);\n  // We only want to change this state if we have the active item overlay.\n  const makeActive = () => {\n    activeItemOverlay && setIsActive(true);\n  };\n  const makeInactive = () => {\n    activeItemOverlay && setIsActive(false);\n  };\n\n  if (!style) {\n    return null;\n  }\n\n  const textContent = selectedElements[0]?.content\n    ? stripHTML(selectedElements[0].content)\n    : __('Lorem ipsum dolor sit amet', 'web-stories');\n\n  const getStylePresetText = () => {\n    const isHighLight =\n      style.backgroundTextMode === BACKGROUND_TEXT_MODE.HIGHLIGHT;\n    const isFill = style.backgroundTextMode === BACKGROUND_TEXT_MODE.FILL;\n    return (\n      <TextWrapper\n        styles={generatePresetStyle(style, true)}\n        background={isFill ? style.backgroundColor : null}\n      >\n        {isHighLight ? (\n          <HighLight background={style.backgroundColor}>\n            {textContent}\n          </HighLight>\n        ) : (\n          textContent\n        )}\n      </TextWrapper>\n    );\n  };\n\n  return (\n    <PresetButton\n      tabIndex={activeIndex === i ? 0 : -1}\n      style={style}\n      onClick={() => handleOnClick(style)}\n      onPointerEnter={makeActive}\n      onFocus={makeActive}\n      onPointerLeave={makeInactive}\n      onBlur={makeInactive}\n      aria-label={isEditMode ? __('Delete style', 'web-stories') : applyLabel}\n    >\n      {getStylePresetText()}\n      {isEditMode && <Icons.Cross />}\n      {!isEditMode && isActive && activeItemOverlay}\n    </PresetButton>\n  );\n}\n\nStyleItem.propTypes = {\n  style: PropTypes.object.isRequired,\n  i: PropTypes.number.isRequired,\n  activeIndex: PropTypes.number,\n  handleOnClick: PropTypes.func.isRequired,\n  isEditMode: PropTypes.bool.isRequired,\n  activeItemOverlay: PropTypes.node,\n  applyLabel: PropTypes.string,\n};\n\nexport default StyleItem;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/styleManager.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { CSSTransition } from 'react-transition-group';\nimport {\n  useFocusOut,\n  useRef,\n  useState,\n  useCallback,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n  Text,\n  TextSize,\n  useKeyDownEffect,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport useFocusTrapping from '../../utils/useFocusTrapping';\nimport Header from './header';\nimport StyleGroup from './styleGroup';\nimport useDeleteStyle from './useDeleteStyle';\nimport ConfirmationDialog from './confirmationDialog';\nimport { STORAGE_KEY } from './constants';\n\nconst Container = styled.div`\n  border-radius: 8px;\n  background: ${({ theme }) => theme.colors.bg.secondary};\n  width: 256px;\n  user-select: none;\n  display: flex;\n  flex-direction: column;\n  align-items: stretch;\n  overflow: hidden;\n\n  &.style-manager-appear {\n    opacity: 0.01;\n    margin-top: -10px;\n\n    &.style-manager-appear-active {\n      opacity: 1;\n      margin-top: 0;\n      transition: 300ms ease-out;\n      transition-property: opacity, margin-top;\n    }\n  }\n`;\n\nconst Body = styled.div`\n  display: flex;\n  margin: 8px 12px 16px;\n`;\n\nconst StyledText = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  margin: 0 0 0 8px;\n  color: ${({ theme }) => theme.colors.fg.primary};\n`;\n\nfunction StyleManager({ styles, onClose, applyStyle, ...rest }) {\n  const [isEditMode, setIsEditMode] = useState(false);\n  const [showDialog, setShowDialog] = useState(false);\n  const [toDelete, setToDelete] = useState(null);\n  const containerRef = useRef(null);\n\n  // Re-establish focus when actively exiting by button or key press\n  const previousFocus = useRef(document.activeElement);\n  const handleCloseAndRefocus = useCallback(\n    (evt) => {\n      // Ignore reason: In Jest, focus is always on document.body if not on any specific\n      // element, so it can never be falsy, as it can be in a real browser.\n\n      // istanbul ignore else\n      if (previousFocus.current) {\n        previousFocus.current.focus();\n      }\n      onClose(evt);\n    },\n    [onClose]\n  );\n  useKeyDownEffect(containerRef, 'esc', handleCloseAndRefocus);\n\n  const deleteStyle = useDeleteStyle({ onEmpty: handleCloseAndRefocus });\n\n  const maybeClose = () => {\n    // If we're focusing out of the style manager but it's for confirmation dialog, don't close.\n    if (!showDialog) {\n      onClose();\n    }\n  };\n  // Detect focus out of the style manager\n  useFocusOut(containerRef, maybeClose, [showDialog]);\n  // Focus trapping.\n  useFocusTrapping({ ref: containerRef });\n\n  const handleClick = (style) => {\n    if (!isEditMode) {\n      applyStyle(style);\n      return;\n    }\n\n    const isDialogDismissed = localStore.getItemByKey(\n      LOCAL_STORAGE_PREFIX[STORAGE_KEY]\n    );\n    if (isDialogDismissed) {\n      deleteStyle(style);\n      return;\n    }\n\n    // Ask confirmation for a global style.\n    setShowDialog(true);\n    setToDelete(style);\n  };\n  return (\n    <CSSTransition\n      nodeRef={containerRef}\n      in\n      appear\n      classNames=\"style-manager\"\n      timeout={300}\n    >\n      <Container\n        role=\"dialog\"\n        aria-label={__('Style presets manager', 'web-stories')}\n        ref={containerRef}\n      >\n        <Header\n          handleClose={handleCloseAndRefocus}\n          isEditMode={isEditMode}\n          setIsEditMode={setIsEditMode}\n        >\n          <StyledText>{__('Saved Styles', 'web-stories')}</StyledText>\n        </Header>\n        <Body>\n          <StyleGroup\n            styles={[...styles].reverse()}\n            handleClick={handleClick}\n            isEditMode={isEditMode}\n            buttonWidth={106}\n            {...rest}\n          />\n        </Body>\n        {showDialog && (\n          <ConfirmationDialog\n            onClose={() => setShowDialog(false)}\n            onPrimary={() => {\n              deleteStyle(toDelete);\n              setToDelete(null);\n              setShowDialog(false);\n            }}\n          />\n        )}\n      </Container>\n    </CSSTransition>\n  );\n}\n\nStyleManager.propTypes = {\n  styles: PropTypes.array.isRequired,\n  onClose: PropTypes.func.isRequired,\n  applyStyle: PropTypes.func.isRequired,\n};\n\nexport default StyleManager;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/useApplyStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useRichTextFormatting from '../panels/design/textStyle/useRichTextFormatting';\nimport { useStory } from '../../app';\nimport { usePresubmitHandler } from '../form';\nimport getUpdatedSizeAndPosition from '../../utils/getUpdatedSizeAndPosition';\nimport { STABLE_ARRAY } from '../../constants';\n\nfunction useApplyStyle({ pushUpdate }) {\n  // Update size and position if relevant values have changed.\n  usePresubmitHandler(getUpdatedSizeAndPosition, []);\n\n  const selectedTextElements = useStory(({ state: { selectedElements } }) => {\n    return selectedElements\n      ? selectedElements?.filter(({ type }) => type === 'text')\n      : STABLE_ARRAY;\n  });\n\n  const extraPropsToAddRef = useRef(null);\n  const push = useCallback(\n    (updater) => {\n      const extraProps = extraPropsToAddRef.current || {};\n      extraPropsToAddRef.current = null;\n      pushUpdate((oldProps) => {\n        return {\n          ...updater(oldProps),\n          ...extraProps,\n        };\n      }, true);\n    },\n    [pushUpdate]\n  );\n\n  const {\n    handlers: {\n      handleSetColor,\n      handleSetLetterSpacing,\n      handleClickUnderline,\n      handleClickItalic,\n      handleSelectFontWeight,\n    },\n  } = useRichTextFormatting(selectedTextElements, push);\n\n  const handleApplyStyle = useCallback(\n    (preset) => {\n      const {\n        color,\n        fontWeight,\n        isItalic,\n        isUnderline,\n        letterSpacing,\n        ...rest\n      } = preset;\n      extraPropsToAddRef.current = rest;\n      handleSetColor(color);\n      handleSetLetterSpacing(letterSpacing);\n      handleSelectFontWeight(fontWeight);\n      handleClickUnderline(isUnderline);\n      handleClickItalic(isItalic);\n    },\n    [\n      handleSetColor,\n      handleSetLetterSpacing,\n      handleClickUnderline,\n      handleClickItalic,\n      handleSelectFontWeight,\n    ]\n  );\n  return handleApplyStyle;\n}\n\nexport default useApplyStyle;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/useDeleteStyle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app';\n\nfunction useDeletePreset({ onEmpty }) {\n  const { globalStoryStyles, updateStory } = useStory(\n    ({\n      state: {\n        story: { globalStoryStyles },\n      },\n      actions: { updateStory },\n    }) => {\n      return {\n        globalStoryStyles,\n        updateStory,\n      };\n    }\n  );\n\n  const { textStyles } = globalStoryStyles || {};\n\n  const deleteGlobalPreset = useCallback(\n    (toDelete) => {\n      const updatedStyles = textStyles.filter((style) => style !== toDelete);\n      updateStory({\n        properties: {\n          globalStoryStyles: {\n            ...globalStoryStyles,\n            textStyles: updatedStyles,\n          },\n        },\n      });\n      // If no styles left, exit edit mode.\n      if (updatedStyles.length === 0) {\n        onEmpty();\n      }\n    },\n    [textStyles, updateStory, globalStoryStyles, onEmpty]\n  );\n\n  return deleteGlobalPreset;\n}\n\nexport default useDeletePreset;\n"
  },
  {
    "path": "packages/story-editor/src/components/styleManager/useKeyboardNavigation.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nconst PRESETS_PER_ROW = 2;\n\nfunction useKeyboardNavigation({ activeIndex, setActiveIndex, groupRef }) {\n  const getIndexDiff = (key, rowLength) => {\n    switch (key) {\n      case 'ArrowUp':\n        return -rowLength;\n      case 'ArrowDown':\n        return rowLength;\n      case 'ArrowLeft':\n        return -1;\n      case 'ArrowRight':\n        return 1;\n      default:\n        return 0;\n    }\n  };\n\n  useKeyDownEffect(\n    groupRef,\n    { key: ['up', 'down', 'left', 'right'] },\n    ({ key }) => {\n      // When the user navigates in the colors using the arrow keys,\n      // Let's change the active index accordingly, to indicate which preset should be focused\n      if (groupRef.current) {\n        const diff = getIndexDiff(key, PRESETS_PER_ROW);\n        const buttons = groupRef.current.querySelectorAll(\n          'button:not([disabled])'\n        );\n        const maxIndex = buttons.length - 1;\n        const val = (activeIndex ?? 0) + diff;\n        const newIndex = Math.max(0, Math.min(maxIndex, val));\n        setActiveIndex(newIndex);\n        if (buttons[newIndex]) {\n          buttons[newIndex].focus();\n        }\n      }\n    },\n    [activeIndex, setActiveIndex, groupRef]\n  );\n}\n\nexport default useKeyboardNavigation;\n"
  },
  {
    "path": "packages/story-editor/src/components/tablist/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const PANEL_STATES = {\n  NORMAL: 'normal',\n  DANGER: 'danger',\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/tablist/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as TablistPanel } from './tablistPanel';\nexport { PANEL_STATES } from './constants';\nexport { Tablist } from './styles';\n"
  },
  {
    "path": "packages/story-editor/src/components/tablist/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  TextSize,\n  Link,\n  Tooltip as BaseTooltip,\n  Text,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { Thumbnail, THUMBNAIL_TYPES } from '../../thumbnail';\nimport { THUMBNAIL_BG } from '../../thumbnail/stories/demoThumbnails';\nimport { StyledVideoOptimizationIcon } from '../../checklistCard/styles';\nimport { Tablist } from '../styles';\nimport TablistPanel from '../tablistPanel';\nimport { CheckboxCta } from '../../checklistCard/checkboxCta';\nimport {\n  ChecklistCard,\n  CARD_TYPE,\n  DefaultCtaButton,\n  DefaultFooterText,\n} from '../../checklistCard';\nimport { PANEL_STATES } from '../constants';\n\nexport default {\n  title: 'Stories Editor/Components/Tablist',\n  component: Tablist,\n  parameters: {\n    controls: { hideNoControlsWarning: true },\n  },\n};\n\nconst Container = styled.div`\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  display: grid;\n  grid-template-rows: 1fr auto;\n  padding: 16px;\n  width: 900px;\n  height: 900px;\n\n  ${Tablist} {\n    grid-row-start: 2;\n    grid-row-end: 3;\n  }\n`;\n\nexport const _default = {\n  render: function Render() {\n    const [openPanel, setOpenPanel] = useState(false);\n\n    const handleClick = (title) => () => {\n      setOpenPanel((currentlyOpenPanel) => {\n        if (currentlyOpenPanel === title) {\n          return null;\n        }\n\n        return title;\n      });\n    };\n\n    return (\n      <Container>\n        <Text.Paragraph>\n          {'Scroll Down or collapse actions bar to see the tabs'}\n        </Text.Paragraph>\n        <Tablist aria-label={'Pre publish checklist example'}>\n          <TablistPanel\n            title={'High Priority'}\n            isExpanded={openPanel === 'highPriority'}\n            onClick={handleClick('highPriority')}\n            badgeCount={3}\n            status={PANEL_STATES.DANGER}\n          >\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n              thumbnailCount={1}\n              thumbnails={\n                <Thumbnail\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />\n              }\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={3}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Videos not optimized\"\n              cta={\n                <>\n                  <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                    {'Optimize all videos'}\n                  </DefaultCtaButton>\n                  <CheckboxCta\n                    id=\"demo-optimize\"\n                    aria-label=\"check this box to optimize videos by default\"\n                  >\n                    {'Enable auto optimization'}\n                  </CheckboxCta>\n                </>\n              }\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {'Unoptimized video may cause playback issues. '}\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={6}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={4}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n              ]}\n            />\n          </TablistPanel>\n          <TablistPanel\n            title={'Style'}\n            isExpanded={openPanel === 'design'}\n            onClick={handleClick('design')}\n            badgeCount={1}\n          >\n            <ChecklistCard\n              title=\"Videos not optimized\"\n              cta={\n                <>\n                  <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                    {'Optimize all videos'}\n                  </DefaultCtaButton>\n                  <CheckboxCta\n                    id=\"demo-optimize\"\n                    aria-label=\"check this box to optimize videos by default\"\n                  >\n                    {'Enable auto optimization'}\n                  </CheckboxCta>\n                </>\n              }\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {'Unoptimized video may cause playback issues. '}\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={6}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={4}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n              ]}\n            />\n          </TablistPanel>\n          <TablistPanel\n            title={'Accessibility'}\n            isExpanded={openPanel === 'accessibility'}\n            onClick={handleClick('accessibility')}\n            badgeCount={9}\n          >\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n              thumbnailCount={1}\n              thumbnails={\n                <Thumbnail\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />\n              }\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={3}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Videos not optimized\"\n              cta={\n                <>\n                  <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                    {'Optimize all videos'}\n                  </DefaultCtaButton>\n                  <CheckboxCta\n                    id=\"demo-optimize\"\n                    aria-label=\"check this box to optimize videos by default\"\n                  >\n                    {'Enable auto optimization'}\n                  </CheckboxCta>\n                </>\n              }\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {'Unoptimized video may cause playback issues. '}\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={6}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={4}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n              thumbnailCount={1}\n              thumbnails={\n                <Thumbnail\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />\n              }\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={3}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Videos not optimized\"\n              cta={\n                <>\n                  <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                    {'Optimize all videos'}\n                  </DefaultCtaButton>\n                  <CheckboxCta\n                    id=\"demo-optimize\"\n                    aria-label=\"check this box to optimize videos by default\"\n                  >\n                    {'Enable auto optimization'}\n                  </CheckboxCta>\n                </>\n              }\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {'Unoptimized video may cause playback issues. '}\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={6}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={4}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cta={<DefaultCtaButton>{'Replace File'}</DefaultCtaButton>}\n              thumbnailCount={1}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Add video captions\"\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {\n                    'Keep the audience engaged even when they can’t listen to the audio. '\n                  }\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={3}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                />,\n              ]}\n            />\n            <ChecklistCard\n              title=\"Videos not optimized\"\n              cta={\n                <>\n                  <DefaultCtaButton aria-label={'Optimize all 6 videos'}>\n                    {'Optimize all videos'}\n                  </DefaultCtaButton>\n                  <CheckboxCta\n                    id=\"demo-optimize\"\n                    aria-label=\"check this box to optimize videos by default\"\n                  >\n                    {'Enable auto optimization'}\n                  </CheckboxCta>\n                </>\n              }\n              footer={\n                <DefaultFooterText.Paragraph>\n                  {'Unoptimized video may cause playback issues. '}\n                  <Link href=\"/demo\" size={TextSize.XSmall}>\n                    {'Learn more'}\n                  </Link>\n                </DefaultFooterText.Paragraph>\n              }\n              cardType={CARD_TYPE.MULTIPLE_ISSUE}\n              thumbnailCount={6}\n              thumbnails={[\n                <Thumbnail\n                  key={1}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={2}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={3}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n                <Thumbnail\n                  key={4}\n                  type={THUMBNAIL_TYPES.IMAGE}\n                  displayBackground={THUMBNAIL_BG[THUMBNAIL_TYPES.IMAGE]}\n                  aria-label=\"my helper text describing this thumbnail image\"\n                >\n                  <BaseTooltip title=\"Optimize\">\n                    <StyledVideoOptimizationIcon />\n                  </BaseTooltip>\n                </Thumbnail>,\n              ]}\n            />\n          </TablistPanel>\n        </Tablist>\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/tablist/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  Button,\n  ButtonVariant,\n  Headline,\n  themeHelpers,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { PANEL_STATES } from './constants';\n\nexport const Tablist = styled.div.attrs({ role: 'tablist' })`\n  background: ${({ theme }) => theme.colors.bg.primary};\n\n  * {\n    user-select: text;\n  }\n`;\nTablist.propTypes = {\n  // label to describe purpose of tabs\n  'aria-label': PropTypes.string.isRequired,\n};\n\nexport const PanelText = styled(Headline).attrs({\n  as: 'h3',\n  size: TextSize.XXXSmall,\n})`\n  transition: background-color 300ms ease-in;\n`;\n\nexport const TabButtonWrapper = styled.div`\n  position: relative;\n  height: 60px;\n  width: 100%;\n  padding: 5px 4px;\n\n  &,\n  :hover,\n  :focus-within,\n  :focus-visible {\n    background-color: ${({ theme }) => theme.colors.bg.secondary};\n  }\n`;\n\nexport const TabButton = styled(Button).attrs({\n  variant: ButtonVariant.PLAIN,\n})`\n  position: absolute;\n  display: flex;\n  justify-content: space-between;\n  width: calc(100% - 8px);\n  height: calc(100% - 10px);\n  padding: 16px;\n  border-radius: 0;\n\n  &,\n  :hover,\n  :focus,\n  :focus-visible {\n    background-color: ${({ theme }) => theme.colors.bg.secondary};\n  }\n\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n\n  ${PanelText} {\n    opacity: 0.8;\n  }\n\n  ${({ status }) =>\n    status === PANEL_STATES.DANGER &&\n    css`\n      &,\n      ${PanelText} {\n        color: ${({ theme }) => theme.colors.fg.negative};\n      }\n\n      ${Badge} {\n        background-color: ${({ theme }) => theme.colors.fg.negative};\n      }\n    `};\n`;\n\nexport const PanelWrapper = styled.div`\n  width: 100%;\n  background: ${({ theme }) => theme.colors.bg.primary};\n\n  &:not(:first-child) > ${TabButton} {\n    box-shadow: 0px -1px 0 0 ${({ theme }) => theme.colors.divider.tertiary};\n    margin-top: 1px;\n  }\n\n  ${({ isExpanded, theme }) =>\n    isExpanded &&\n    css`\n      & ${TabButton}, & ${TabButtonWrapper} {\n        :not(:last-child) {\n          box-shadow: none;\n        }\n\n        ${themeHelpers.focusableOutlineCSS};\n\n        ${PanelText} {\n          opacity: 1;\n        }\n\n        &,\n        :hover,\n        :focus {\n          background-color: ${theme.colors.bg.primary};\n        }\n\n        svg {\n          transform: rotate(0);\n        }\n      }\n\n      ${ScrollableContent} {\n        height: 560px;\n\n        ${TabPanel} {\n          visibility: visible;\n        }\n      }\n    `};\n`;\n\nexport const ButtonText = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  margin-left: -12px;\n`;\n\nexport const IconContainer = styled.div`\n  height: 32px;\n  width: 32px;\n\n  color: ${({ theme }) => theme.colors.fg.primary};\n\n  svg {\n    transform: rotate(-90deg);\n    transition: transform 300ms ease-in-out;\n  }\n`;\n\nexport const Badge = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 20px;\n  width: 20px;\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n  background-color: ${({ theme }) => theme.colors.fg.primary};\n\n  ${PanelText} {\n    color: ${({ theme }) => theme.colors.inverted.fg.primary};\n    line-height: 20px;\n  }\n`;\n\nexport const ScrollableContent = styled.div`\n  height: 0;\n  max-height: ${({ maxHeight }) => (maxHeight ? `calc(${maxHeight})` : 'none')};\n  overflow-y: ${({ maxHeight }) => (maxHeight ? 'scroll' : 'hidden')};\n  transition: height 300ms ease-in;\n`;\n\nexport const TabPanel = styled.div`\n  padding: 0;\n  visibility: hidden;\n  overflow: hidden;\n  background: ${({ theme }) => theme.colors.bg.primary};\n  transition: all 300ms ease-in;\n  margin: 0 0 16px 16px;\n\n  ${themeHelpers.scrollbarCSS};\n`;\n"
  },
  {
    "path": "packages/story-editor/src/components/tablist/tablistPanel.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, _n } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { Icons } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { PANEL_STATES } from './constants';\nimport {\n  Badge,\n  ButtonText,\n  IconContainer,\n  PanelText,\n  PanelWrapper,\n  ScrollableContent,\n  TabButton,\n  TabPanel,\n  TabButtonWrapper,\n} from './styles';\n\nconst TablistPanel = ({\n  badgeCount = 0,\n  children,\n  className,\n  id,\n  isExpanded,\n  onClick,\n  maxHeight,\n  status = PANEL_STATES.NORMAL,\n  title,\n}) => {\n  const backupId = useMemo(uuidv4, []);\n  const panelId = id || backupId;\n\n  return (\n    <PanelWrapper className={className} isExpanded={isExpanded}>\n      <TabButtonWrapper>\n        <TabButton\n          aria-controls={panelId}\n          aria-selected={isExpanded}\n          onClick={onClick}\n          role=\"tab\"\n          status={status}\n        >\n          <ButtonText>\n            <IconContainer>\n              <Icons.ChevronDownSmall />\n            </IconContainer>\n            <PanelText\n              id={`${title}-${panelId}`}\n              aria-label={sprintf(\n                /* translators: 1: number of issues. 2: type of issue, for example \"High Priority\". */\n                _n(\n                  '%1$d %2$s issue',\n                  '%1$d %2$s issues',\n                  badgeCount,\n                  'web-stories'\n                ),\n                badgeCount,\n                title\n              )}\n            >\n              {title}\n            </PanelText>\n          </ButtonText>\n          <Badge>\n            <PanelText aria-hidden>{badgeCount}</PanelText>\n          </Badge>\n        </TabButton>\n      </TabButtonWrapper>\n      <ScrollableContent aria-hidden={!isExpanded} maxHeight={maxHeight}>\n        <TabPanel\n          id={panelId}\n          aria-labelledby={`${title}-${panelId}`}\n          role=\"tabpanel\"\n        >\n          {children}\n        </TabPanel>\n      </ScrollableContent>\n    </PanelWrapper>\n  );\n};\nTablistPanel.propTypes = {\n  badgeCount: PropTypes.number,\n  children: PropTypes.node,\n  className: PropTypes.string,\n  id: PropTypes.string,\n  isExpanded: PropTypes.bool,\n  onClick: PropTypes.func.isRequired,\n  maxHeight: PropTypes.string,\n  status: PropTypes.oneOf(Object.values(PANEL_STATES)),\n  title: PropTypes.string.isRequired,\n};\n\nexport default TablistPanel;\n"
  },
  {
    "path": "packages/story-editor/src/components/tabview/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport { useRef, useCallback, forwardRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport {\n  useKeyDownEffect,\n  useGlobalKeyDownEffect,\n  Headline,\n  TextSize,\n  themeHelpers,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app';\nimport Tooltip from '../tooltip';\nimport usePerformanceTracking from '../../utils/usePerformanceTracking';\nimport { TRACKING_EVENTS } from '../../constants';\nimport { noop } from '../../utils/noop';\n\nconst ALERT_ICON_SIZE = 28;\nexport const TAB_HEIGHT = 32;\nexport const TAB_VERTICAL_MARGIN = 10;\n\nconst Tabs = styled.ul.attrs({\n  role: 'tablist',\n  'aria-orientation': 'horizontal',\n})`\n  display: flex;\n  flex-direction: row;\n  align-items: stretch;\n  width: 100%;\n  max-width: 100%;\n  justify-content: space-between;\n  margin: 0;\n  padding: 0;\n  list-style: none;\n  border-bottom: 1px solid ${({ theme }) => theme.colors.divider.secondary};\n`;\n\nconst TabElement = styled.li.attrs(({ isActive }) => ({\n  tabIndex: isActive ? 0 : -1,\n  role: 'tab',\n  'aria-selected': isActive,\n}))`\n  cursor: pointer;\n  border: none;\n  background: none;\n  padding: 0 4px;\n  margin: ${TAB_VERTICAL_MARGIN}px 12px 9px;\n  height: ${TAB_HEIGHT}px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  position: relative;\n  transition: color 0.2s ease;\n  color: ${({ theme, isActive }) =>\n    isActive ? theme.colors.fg.primary : theme.colors.fg.tertiary};\n\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  ${({ theme }) =>\n    themeHelpers.focusableOutlineCSS(\n      theme.colors.border.focus,\n      theme.colors.bg.secondary\n    )};\n\n  :hover {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n\n  ${({ isActive, theme }) =>\n    isActive &&\n    css`\n      ::after {\n        content: '';\n        position: absolute;\n        background-color: ${theme.colors.border.selection};\n        height: 2px;\n        border-radius: 1px;\n        bottom: -10px;\n        left: 4px;\n        right: 4px;\n      }\n    `}\n\n  svg {\n    display: block;\n    width: 32px;\n    height: 32px;\n    margin: 0 -4px;\n    transform-origin: center center;\n    transition:\n      transform 0.3s ease,\n      color 0.2s ease;\n    color: ${({ theme }) => theme.colors.fg.tertiary};\n    border-radius: ${({ theme }) => theme.borders.radius.small};\n    pointer-events: none;\n  }\n\n  svg.alert {\n    width: ${ALERT_ICON_SIZE}px;\n    margin-left: 4px;\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n\n  span,\n  svg:not(.alert) {\n    ${({ isActive, theme }) => isActive && `color: ${theme.colors.fg.primary}`};\n  }\n\n  &:hover span,\n  &:hover svg:not(.alert),\n  &:active span,\n  &:active svg:not(.alert) {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n\n  &:focus-visible {\n    svg:not(.alert) {\n      background-color: ${({ theme }) =>\n        theme.colors.interactiveBg.tertiaryHover};\n    }\n  }\n`;\n\nconst TabText = styled(Headline).attrs({\n  as: 'p',\n  size: TextSize.XXXSmall,\n})`\n  color: inherit;\n`;\n\nfunction UnreffedTab(\n  { children, tooltip = null, placement, refId, tabRefs, ...rest },\n  ref\n) {\n  const { id } = rest;\n  const eventData = id.includes('library')\n    ? TRACKING_EVENTS.LIBRARY_PANEL_CLICK\n    : TRACKING_EVENTS.DESIGN_PANEL_CLICK;\n  usePerformanceTracking({\n    node: tabRefs?.[refId]?.current,\n    eventData: {\n      ...eventData,\n      label: `${refId}_tab`,\n    },\n  });\n  const tab = (\n    <TabElement ref={ref} {...rest}>\n      {children}\n    </TabElement>\n  );\n  if (tooltip !== null) {\n    return (\n      <Tooltip title={tooltip} placement={placement} isDelayed>\n        {tab}\n      </Tooltip>\n    );\n  }\n  return tab;\n}\n\nconst Tab = forwardRef(UnreffedTab);\n\nUnreffedTab.propTypes = {\n  children: PropTypes.node,\n  tooltip: PropTypes.string,\n  placement: PropTypes.string,\n  refId: PropTypes.string,\n  tabRefs: PropTypes.object,\n};\n\nfunction TabView({\n  getTabId = (id) => id,\n  getAriaControlsId,\n  onTabChange = noop,\n  onTabRefUpdated = noop,\n  tabs = [],\n  label = '',\n  shortcut = '',\n  tab,\n  tabRefs,\n  ...rest\n}) {\n  const { isRTL } = useConfig();\n\n  const ref = useRef();\n  const focused = useRef();\n  const internalTabRefs = useRef({}); // fallback if tabRefs aren't passed in\n\n  const focusChanged = useCallback(\n    (id) => {\n      if (tabRefs?.[id]?.current) {\n        tabRefs[id].current?.focus();\n      } else if (internalTabRefs?.current[id]) {\n        internalTabRefs.current[id]?.focus();\n      }\n      focused.current = id;\n    },\n    [tabRefs]\n  );\n\n  const selectTab = useCallback(\n    (id) => {\n      focusChanged(id);\n      onTabChange(id);\n    },\n    [focusChanged, onTabChange]\n  );\n\n  useGlobalKeyDownEffect(\n    { key: shortcut, editable: true },\n    () => selectTab(tab),\n    [selectTab, tab]\n  );\n\n  const focusTabByIndex = useCallback(\n    (index) => {\n      // Index wraps, so -1 is last element\n      const nextTab = tabs[(index + tabs.length) % tabs.length];\n      focusChanged(nextTab.id);\n    },\n    [tabs, focusChanged]\n  );\n\n  const handleNavigation = useCallback(\n    (direction) => {\n      const directionWithRTL = isRTL ? -direction : direction;\n      const currentIndex = tabs.findIndex(({ id }) => id === focused.current);\n      focusTabByIndex(currentIndex + directionWithRTL);\n    },\n    [isRTL, tabs, focusTabByIndex]\n  );\n\n  // Left-right keys navigate to next tab\n  useKeyDownEffect(ref, 'left', () => handleNavigation(-1), [handleNavigation]);\n  useKeyDownEffect(ref, 'right', () => handleNavigation(1), [handleNavigation]);\n\n  // Empty up/down handlers for consistency with left/right.\n  useKeyDownEffect(ref, ['up', 'down'], noop, []);\n\n  // Home/end keys navigate to first/last tab regardless of direction\n  useKeyDownEffect(ref, 'home', () => focusTabByIndex(0), [focusTabByIndex]);\n  useKeyDownEffect(ref, 'end', () => focusTabByIndex(-1), [focusTabByIndex]);\n\n  // Enter/space to select currently focused tab.\n  useKeyDownEffect(\n    ref,\n    { key: ['enter', 'space'], allowDefault: true },\n    (evt) => {\n      if (evt.target.getAttribute('role') === 'tab') {\n        selectTab(focused.current);\n        evt.preventDefault();\n      }\n    },\n    [selectTab],\n    {}\n  );\n\n  return (\n    <Tabs aria-label={label} ref={ref} {...rest}>\n      {tabs.map(({ id, title, icon: Icon, ...tabRest }) => (\n        <Tab\n          key={id}\n          ref={(node) => {\n            if (tabRefs?.[id]) {\n              tabRefs[id].current = node;\n            } else {\n              internalTabRefs.current[id] = node;\n            }\n            onTabRefUpdated(node, id);\n          }}\n          id={getTabId(id)}\n          isActive={tab === id}\n          aria-controls={getAriaControlsId ? getAriaControlsId(id) : null}\n          aria-selected={tab === id}\n          onClick={() => selectTab(id)}\n          onFocus={() => {\n            focused.current = tab;\n          }}\n          refId={id}\n          tabRefs={tabRefs}\n          {...tabRest}\n        >\n          {Boolean(title) && <TabText>{title}</TabText>}\n          {Boolean(Icon) && <Icon isActive={id === tab} />}\n        </Tab>\n      ))}\n    </Tabs>\n  );\n}\n\nTabView.propTypes = {\n  getTabId: PropTypes.func,\n  getAriaControlsId: PropTypes.func,\n  onTabChange: PropTypes.func,\n  onTabRefUpdated: PropTypes.func,\n  tabs: PropTypes.array.isRequired,\n  tab: PropTypes.string.isRequired,\n  tabRefs: PropTypes.objectOf(\n    PropTypes.shape({ current: PropTypes.instanceOf(Element) })\n  ),\n  label: PropTypes.string,\n  shortcut: PropTypes.string,\n};\n\nexport default TabView;\n"
  },
  {
    "path": "packages/story-editor/src/components/tabview/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { Icons, Text } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport TabView from '..';\n\nconst Wrapper = styled.div`\n  display: grid;\n  grid-template-columns: repeat(2, 40%);\n  column-gap: 32px;\n`;\n\nconst TabWrapper = styled.div`\n  background: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst TabContent = styled.section`\n  padding: 16px;\n`;\nconst UnjustifiedTabView = styled(TabView)`\n  justify-content: center;\n`;\n\nexport default {\n  title: 'Stories Editor/Components/TabView',\n  component: TabView,\n};\n\nconst ICON_TABS = [\n  {\n    id: 'media',\n    content: 'Media',\n    icon: Icons.ArrowCloud,\n  },\n  {\n    id: 'thirdparty',\n    content: 'Thirdparty',\n    icon: Icons.Picture,\n  },\n  {\n    id: 'text',\n    content: 'Text',\n    icon: Icons.LetterT,\n  },\n  {\n    id: 'shapes',\n    content: 'Shapes',\n    icon: Icons.Shapes,\n  },\n  {\n    id: 'layouts',\n    content: 'Layouts',\n    icon: Icons.Box4Alternate,\n  },\n];\n\nconst TEXT_TABS = [\n  {\n    id: 'design',\n    title: 'Design',\n  },\n  {\n    id: 'document',\n    title: 'Document',\n  },\n  {\n    id: 'pre-publish',\n    title: 'Pre-publish',\n    icon: function Error() {\n      return <Icons.ExclamationOutline className=\"alert error\" />;\n    },\n  },\n];\n\nfunction TabDisplay({ TabsComponent, tabs }) {\n  const [tab, setTab] = useState(tabs[0].id);\n  const activeTab = tabs.find(({ id }) => id === tab);\n  return (\n    <TabWrapper>\n      <TabsComponent onTabChange={(id) => setTab(id)} tabs={tabs} />\n      <TabContent>\n        <Text.Paragraph>{`Tab content: ${\n          activeTab.content || activeTab.title\n        }`}</Text.Paragraph>\n      </TabContent>\n    </TabWrapper>\n  );\n}\n\nTabDisplay.propTypes = {\n  TabsComponent: PropTypes.func.isRequired,\n  tabs: PropTypes.array.isRequired,\n};\n\nexport const _default = {\n  render: () => {\n    return (\n      <Wrapper>\n        <TabDisplay TabsComponent={TabView} tabs={ICON_TABS} />\n        <TabDisplay TabsComponent={UnjustifiedTabView} tabs={TEXT_TABS} />\n      </Wrapper>\n    );\n  },\n\n  parameters: {\n    backgrounds: {\n      default: 'Dark',\n    },\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/components/LayerThumbnail.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport useCORSProxy from '../../../utils/useCORSProxy';\nimport { useStory } from '../../../app';\n\nexport const LayerThumbnail = ({ page }) => {\n  const { LayerIcon } = getDefinitionForType(page?.type);\n  const { getProxiedUrl } = useCORSProxy();\n  const { isDefaultBackground } = page;\n  const currentPageBackgroundColor = useStory(\n    ({ state }) => !isDefaultBackground || state.currentPage?.backgroundColor\n  );\n\n  const props = { element: page, getProxiedUrl, currentPageBackgroundColor };\n\n  if (page?.type === 'video') {\n    props.showVideoPreviewAsBackup = true;\n  }\n\n  return <LayerIcon {...props} />;\n};\n\nLayerThumbnail.propTypes = {\n  page: PropTypes.object.isRequired,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/constants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const THUMBNAIL_DIMENSIONS = {\n  WIDTH: 54,\n  HEIGHT: 96,\n  NESTED_ICON: 32,\n  THUMBNAIL_SHAPE: 36,\n};\nexport const THUMBNAIL_TYPES = {\n  VIDEO: 'VIDEO',\n  IMAGE: 'IMAGE',\n  TEXT: 'TEXT',\n  SHAPE: 'SHAPE',\n  PAGE: 'PAGE',\n};\n\nexport const THUMBNAIL_SCRIM_CLASSNAME = 'thumbnail-scrim';\nexport const THUMBNAIL_SHOW_ON_HOVER_FOCUS = 'thumbnail-show-hover-focus';\nexport const DEFAULT_LOADING_MESSAGE = __('Loading', 'web-stories');\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { THUMBNAIL_DIMENSIONS, THUMBNAIL_TYPES } from './constants';\nexport { default as Thumbnail } from './thumbnail';\nexport { default as OverflowThumbnail } from './overflowThumbnail';\nexport { LayerThumbnail } from './components/LayerThumbnail';\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/overflowThumbnail.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { sprintf, __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { TextSize, Text } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { Container } from './styles';\n\n/**\n * Element and page thumbnails, used in the prepublish checklist\n *\n * @param {Object} props Component props.\n * @param {number} props.overflowCount The number of thumbnails that are overflowing.\n * @return {Node} Overflow Thumbnail to render\n */\nconst OverflowThumbnail = ({ overflowCount, ...rest }) => (\n  <Container $isOverflow as=\"div\" {...rest}>\n    <Text.Paragraph size={TextSize.Medium}>\n      {sprintf(\n        /* translators: %s: number of thumbnails in overflow */\n        __('+ %s', 'web-stories'),\n        overflowCount\n      )}\n    </Text.Paragraph>\n  </Container>\n);\n\nOverflowThumbnail.propTypes = {\n  overflowCount: PropTypes.number.isRequired,\n};\nexport default OverflowThumbnail;\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/stories/demoThumbnails.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PagePreview from '../../footer/pagepreview';\nimport { THUMBNAIL_TYPES, THUMBNAIL_DIMENSIONS } from '..';\n\nconst LayerIconImageOutput = (\n  <img\n    src=\"http://placekitten.com/200/300\"\n    alt=\"a cute little kitten\"\n    height=\"20\"\n    crossOrigin=\"anonymous\"\n  />\n);\n\nconst LayerIconVideoOutput = (\n  <img\n    src=\"https://storage.coverr.co/p/rhOM3iuhDqxedD7lKLpPO34yN2lhf5Kk\"\n    alt=\"media/coverr:hWGAKF358u\"\n    width=\"28\"\n    height=\"28\"\n    crossOrigin=\"anonymous\"\n  />\n);\n\nconst LayerIconShapeOutput = (\n  <div className=\"icon__Container-sc-1f3yf81-0 eqIMqM\">\n    <div\n      width=\"16\"\n      height=\"16\"\n      className=\"icon__ShapePreview-sc-1f3yf81-1 iLoXqT\"\n      style={{\n        clipPath:\n          \"url('#mask-triangle-94fcc48e-5e07-48db-9ab5-a4d8b2314a3f-layer-preview')\",\n        backgroundColor: '#691818',\n      }}\n    >\n      <svg width=\"0\" height=\"0\">\n        <defs>\n          <clipPath\n            id=\"mask-triangle-94fcc48e-5e07-48db-9ab5-a4d8b2314a3f-layer-preview\"\n            transform=\"scale(1 1)\"\n            clipPathUnits=\"objectBoundingBox\"\n          >\n            <path d=\"M 0.5 0 L 1 1 L 0 1 Z\" />\n          </clipPath>\n        </defs>\n      </svg>\n    </div>\n  </div>\n);\n\nconst LayerIconTextOutput = (\n  <div>\n    <svg\n      viewBox=\"0 0 32 32\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      height=\"30px\"\n      width=\"30px\"\n    >\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M10.5 9.5a.5.5 0 00-.5.5v1.178a.5.5 0 01-1 0V10a1.5 1.5 0 011.5-1.5h11A1.5 1.5 0 0123 10v1.178a.5.5 0 01-1 0V10a.5.5 0 00-.5-.5h-5v13h2.1a.5.5 0 010 1h-5.2a.5.5 0 010-1h2.1v-13h-5z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  </div>\n);\n\nconst page = {\n  elements: [\n    {\n      opacity: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundColor: {\n        color: {\n          r: 255,\n          g: 255,\n          b: 255,\n        },\n      },\n      x: 1,\n      y: 1,\n      width: 1,\n      height: 1,\n      mask: {\n        type: 'rectangle',\n      },\n      isBackground: true,\n      isDefaultBackground: true,\n      type: 'shape',\n      id: 'd5753439-bb84-45df-b348-e8d018e05aec',\n    },\n    {\n      opacity: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundColor: {\n        color: {\n          r: 242,\n          g: 242,\n          b: 8,\n        },\n      },\n      type: 'shape',\n      x: 0,\n      y: -49,\n      width: 269,\n      height: 256,\n      scale: 100,\n      focalX: 50,\n      focalY: 50,\n      mask: {\n        type: 'star',\n      },\n      id: '81d3fd2e-2acf-4af1-95fa-373c647621f5',\n    },\n    {\n      opacity: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundColor: {\n        color: {\n          r: 242,\n          g: 242,\n          b: 8,\n        },\n      },\n      type: 'shape',\n      width: 155,\n      height: 148,\n      scale: 100,\n      focalX: 50,\n      focalY: 50,\n      mask: {\n        type: 'star',\n      },\n      id: 'd2a7bed9-b81b-4f65-9bc5-17a14471e178',\n      x: 258,\n      y: 136,\n    },\n    {\n      opacity: 100,\n      flip: {\n        vertical: false,\n        horizontal: false,\n      },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundColor: {\n        color: {\n          r: 242,\n          g: 242,\n          b: 8,\n        },\n      },\n      type: 'shape',\n      width: 301,\n      height: 287,\n      scale: 100,\n      focalX: 50,\n      focalY: 50,\n      mask: {\n        type: 'star',\n      },\n      id: '318a9c26-2d6e-43b5-99c0-f6f249c22f6a',\n      x: 34,\n      y: 330,\n    },\n  ],\n  backgroundColor: {\n    color: {\n      r: 242,\n      g: 12,\n      b: 217,\n    },\n  },\n  type: 'page',\n  id: '02fef47d-d072-4e4b-a49f-6253eca35fda',\n};\n\nconst PageThumbnail = (\n  <PagePreview\n    page={page}\n    width={THUMBNAIL_DIMENSIONS.WIDTH}\n    height={THUMBNAIL_DIMENSIONS.HEIGHT}\n    as=\"div\"\n    label=\"Page Thumbnail\"\n  />\n);\n\nexport const THUMBNAIL_BG = {\n  [THUMBNAIL_TYPES.IMAGE]: LayerIconImageOutput,\n  [THUMBNAIL_TYPES.SHAPE]: LayerIconShapeOutput,\n  [THUMBNAIL_TYPES.TEXT]: LayerIconTextOutput,\n  [THUMBNAIL_TYPES.VIDEO]: LayerIconVideoOutput,\n  [THUMBNAIL_TYPES.PAGE]: PageThumbnail,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  Tooltip as BaseTooltip,\n  Icons,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { Thumbnail, THUMBNAIL_TYPES } from '..';\nimport { THUMBNAIL_BG } from './demoThumbnails';\n\nexport default {\n  title: 'Stories Editor/Components/Thumbnail',\n  component: Thumbnail,\n  args: {\n    isError: false,\n    isLoading: false,\n    loadingMessage: 'some aria specific loading copy',\n    ariaLabel:\n      'I am some helper text for screen readers. If a tooltip is present, that content should also go here',\n  },\n  argTypes: {\n    onClick: { action: 'button clicked' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['displayBackground', 'type', 'children'],\n    },\n  },\n};\nconst Container = styled.div`\n  background-color: #28292b;\n  padding: 30px;\n  display: flex;\n  gap: 20px;\n`;\n\nconst StyledVideoOptimizationIcon = styled(Icons.GearWithGauge)`\n  rect {\n    color: ${({ theme }) => theme.colors.opacity.black64};\n  }\n\n  path {\n    color: ${({ theme }) => theme.colors.fg.primary};\n  }\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    const thumbnails = Object.values(THUMBNAIL_TYPES).map((thumbnailType) => (\n      <Thumbnail\n        key={`${thumbnailType}_key`}\n        type={thumbnailType}\n        displayBackground={THUMBNAIL_BG[thumbnailType]}\n        {...args}\n        aria-label={args.ariaLabel}\n        onClick={() => args.onClick(thumbnailType)}\n      >\n        {thumbnailType === THUMBNAIL_TYPES.VIDEO && (\n          <BaseTooltip title=\"test tooltip\">\n            <StyledVideoOptimizationIcon />\n          </BaseTooltip>\n        )}\n      </Thumbnail>\n    ));\n\n    return <Container>{thumbnails}</Container>;\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/styles.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport {\n  THUMBNAIL_DIMENSIONS,\n  THUMBNAIL_SCRIM_CLASSNAME,\n  THUMBNAIL_SHOW_ON_HOVER_FOCUS,\n} from './constants';\n\n/**\n * Set Scrim styles on button state here with the THUMBNAIL_SCRIM_CLASSNAME\n * since the Container is the only interactive element here.\n * The Scrim is separated from the Container button because sometimes there\n * are nested icons that need to be on top of the main content of a thumbnail.\n * And the contents of the button may not be able to be a background image\n * depending on the thumbnail type.\n */\nexport const Container = styled.button(\n  ({ theme, $isError, $isOverflow }) => css`\n    position: relative;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: ${THUMBNAIL_DIMENSIONS.WIDTH}px;\n    height: ${THUMBNAIL_DIMENSIONS.HEIGHT}px;\n    padding: 0;\n    outline: none;\n    border: none;\n    border-radius: ${theme.borders.radius.small};\n    background-color: ${$isOverflow\n      ? theme.colors.interactiveBg.secondaryNormal\n      : 'transparent'};\n    cursor: pointer;\n\n    .${THUMBNAIL_SHOW_ON_HOVER_FOCUS} {\n      display: none;\n    }\n\n    &:hover {\n      .${THUMBNAIL_SHOW_ON_HOVER_FOCUS} {\n        display: flex;\n      }\n    }\n    ${$isError &&\n    css`\n      .${THUMBNAIL_SCRIM_CLASSNAME} {\n        border: 1px solid ${theme.colors.border.negativeNormal};\n        background-color: ${theme.colors.opacity.black24};\n      }\n      &:hover .${THUMBNAIL_SCRIM_CLASSNAME} {\n        background-color: ${theme.colors.opacity.black24};\n      }\n    `}\n\n    &:focus,\n      &:focus-within {\n      .${THUMBNAIL_SHOW_ON_HOVER_FOCUS} {\n        display: flex;\n      }\n      .${THUMBNAIL_SCRIM_CLASSNAME} {\n        background-color: ${theme.colors.opacity.black64};\n        border: 1px solid\n          ${theme.colors.border[$isError ? 'negativeNormal' : 'focus']};\n      }\n    }\n  `\n);\nContainer.propTypes = {\n  $isError: PropTypes.bool,\n};\n\n/**\n * Backgrounds can be a few different things based on thumbnail types\n * all of which require some overriding in specific ways:\n * - video and image are going to be 1 <img> tag.\n * - shape is going to be 2 divs then an svg, the shape is a clipPath.\n * - text is going to be 1 div and an svg with a traditional path.\n * - page is going to harness the `PagePreview` component as a div rather than the default button. This requires 2 nested divs.\n * - page and shape, since they have some fun nesting going on have their own props to help legibility and why the styles are nested.\n */\nexport const Background = styled.div(\n  ({ theme, $isShape, $isPage }) => css`\n    width: 100%;\n    height: 100%;\n    display: flex;\n    border-radius: ${theme.borders.radius.small};\n\n    /*\n    Only reach one level deep so that images and videos\n    in stories are not affected.\n    */\n    & > img,\n    & > video {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n      border-radius: ${theme.borders.radius.small};\n    }\n\n    & > div {\n      display: flex;\n      height: 100%;\n      margin: 0 auto;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      color: ${theme.colors.fg.primary};\n    }\n\n    ${$isShape &&\n    css`\n      /* stylelint-disable-next-line */\n      & > div {\n        width: ${THUMBNAIL_DIMENSIONS.THUMBNAIL_SHAPE}px;\n        height: ${THUMBNAIL_DIMENSIONS.THUMBNAIL_SHAPE}px;\n\n        & > div {\n          width: 100%;\n          height: 100%;\n        }\n      }\n    `}\n\n    ${$isPage &&\n    css`\n      /* Specific overrides for PagePreview that is borrowed for checklist's thumbnails */\n      .pagePreviewOverrides {\n        border-color: transparent;\n\n        &::after {\n          content: none;\n          border: none;\n        }\n      }\n      /* stylelint-disable-next-line */\n      & > div > div {\n        width: 100%;\n      }\n    `}\n  `\n);\nBackground.propTypes = {\n  $isPage: PropTypes.bool,\n  $isShape: PropTypes.bool,\n};\n\n// The nested div here is to center a tooltip if one is present.\nexport const NestedIconContainer = styled.div(\n  ({ theme, $isError }) => css`\n    display: flex;\n    position: absolute;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    align-items: center;\n    justify-content: center;\n    z-index: 5;\n\n    & > div {\n      margin: auto;\n      width: ${THUMBNAIL_DIMENSIONS.NESTED_ICON}px;\n    }\n\n    svg {\n      width: 100%;\n      height: auto;\n      ${$isError &&\n      css`\n        color: ${theme.colors.fg.negative};\n      `}\n    }\n  `\n);\nNestedIconContainer.propTypes = {\n  $isError: PropTypes.bool,\n};\n\n// Keep scrim above intended background - PagePreviews have a z-index of 1.\nexport const Scrim = styled.div(\n  ({ theme, $showDefaultBackground }) => css`\n    position: absolute;\n    box-sizing: border-box;\n    top: 0;\n    width: 100%;\n    height: 100%;\n    border: 1px solid transparent;\n    border-radius: ${theme.borders.radius.small};\n    z-index: 2;\n    ${$showDefaultBackground &&\n    css`\n      background-color: ${theme.colors.opacity.black24};\n    `};\n\n    &:hover {\n      background-color: ${theme.colors.opacity.black64};\n    }\n  `\n);\nScrim.propTypes = {\n  $showDefaultBackground: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/thumbnail/thumbnail.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Icons, LoadingBar } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport {\n  THUMBNAIL_TYPES,\n  THUMBNAIL_SCRIM_CLASSNAME,\n  DEFAULT_LOADING_MESSAGE,\n  THUMBNAIL_SHOW_ON_HOVER_FOCUS,\n} from './constants';\nimport { Container, Background, NestedIconContainer, Scrim } from './styles';\n\nconst includeDefaultScrimBackground = [\n  THUMBNAIL_TYPES.SHAPE,\n  THUMBNAIL_TYPES.TEXT,\n];\n\n/**\n * Element and page thumbnails, used in the prepublish checklist\n *\n * @param {Object} props Component props.\n * @param {Node} props.displayBackground Node that renders the element. Relies on PagePreview or LayerIcon (getDefinitionForType, see panels/layer) to keep element rendering consistent with carousel and layer panels. See /storybook for demo.\n * @param {boolean} props.isError Thumbnail errors don't prevent further interaction with the thumbnail, they just change the presentation so user knows the action failed.\n * @param {boolean} props.isLoading If a thumbnail needs to show a loading progress bar this should be true.\n * @param {string} props.loadingMessage If a thumbnail needs an aria alert with loading bar this should be used.\n * @param {Function} props.onClick If a thumbnail has an action, it's called on onClick. Responsible for making sure the thumbnail is rendered as a button instead of a div.\n * @param {string} props.type One of the values of THUMBNAIL_TYPES. Responsible for specific context renderings based on thumbnail type.\n * @param {Node} props.children Content rendered within a thumbnail, according to designs, are icons with tooltips.\n * @return {Node} Thumbnail to render\n */\nconst Thumbnail = ({\n  displayBackground,\n  isError,\n  onClick,\n  type,\n  isLoading,\n  loadingMessage = DEFAULT_LOADING_MESSAGE,\n  children,\n  ...rest\n}) => (\n  <Container\n    as={!onClick ? 'div' : 'button'}\n    onClick={onClick}\n    $isError={isError}\n    {...rest}\n  >\n    {isLoading && <LoadingBar loadingMessage={loadingMessage} />}\n    {!isError && !isLoading && children && (\n      <NestedIconContainer className={THUMBNAIL_SHOW_ON_HOVER_FOCUS}>\n        {children}\n      </NestedIconContainer>\n    )}\n    {isError && (\n      <NestedIconContainer $isError={isError}>\n        <Icons.ExclamationOutline />\n      </NestedIconContainer>\n    )}\n    <Scrim\n      $showDefaultBackground={includeDefaultScrimBackground.indexOf(type) > -1}\n      className={THUMBNAIL_SCRIM_CLASSNAME}\n    />\n    <Background\n      $isShape={type === THUMBNAIL_TYPES.SHAPE}\n      $isPage={type === THUMBNAIL_TYPES.PAGE}\n    >\n      {displayBackground}\n    </Background>\n  </Container>\n);\n\nThumbnail.propTypes = {\n  displayBackground: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n  ]),\n  type: PropTypes.oneOf(Object.values(THUMBNAIL_TYPES)).isRequired,\n  children: PropTypes.oneOfType([\n    PropTypes.arrayOf(PropTypes.node),\n    PropTypes.node,\n    PropTypes.bool,\n  ]),\n  onClick: PropTypes.func,\n  isError: PropTypes.bool,\n  isLoading: PropTypes.bool,\n  loadingMessage: PropTypes.string,\n};\nexport default Thumbnail;\n"
  },
  {
    "path": "packages/story-editor/src/components/toggleButton/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled, { css } from 'styled-components';\nimport {\n  Button as dsButton,\n  ButtonType,\n  ButtonVariant,\n  ButtonSize,\n  Disclosure,\n  Text,\n  Placement,\n  themeHelpers,\n  TextSize,\n  theme as dsTheme,\n  THEME_CONSTANTS,\n} from '@googleforcreators/design-system';\nimport { forwardRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Tooltip from '../tooltip';\n\nconst buttonHeight = 36;\n\nconst Button = styled(dsButton)`\n  width: auto;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  border-width: 1px;\n  border-style: solid;\n  padding: 0 10px;\n  white-space: nowrap;\n  /* Handle props-dependent styling in one place */\n  ${({ isOpen, hasText, height = buttonHeight, theme }) => css`\n    height: ${height}px;\n    min-width: ${height}px;\n    color: ${theme.colors.fg.primary};\n    border-color: ${isOpen\n      ? theme.colors.bg.secondary\n      : theme.colors.border.defaultNormal};\n    background-color: ${isOpen\n      ? theme.colors.bg.secondary\n      : theme.colors.bg.primary};\n    ${hasText &&\n    css`\n      ${themeHelpers.expandPresetStyles({\n        preset: {\n          ...theme.typography.presets.paragraph[TextSize.Small],\n        },\n        theme,\n      })};\n    `}\n  `}\n\n  /* This should be sufficient to ensure proper spacing of button content */\n  > :not(svg):last-child {\n    margin-right: 0;\n  }\n\n  /*\n   Margin is set to -8px to compensate for empty space\n   around the actual icon graphic in the svg\n  */\n  .main-icon {\n    height: ${THEME_CONSTANTS.ICON_SIZE}px;\n    width: auto;\n    margin: -8px;\n    display: block;\n  }\n`;\nButton.propTypes = {\n  hasText: PropTypes.bool,\n  isOpen: PropTypes.bool,\n  height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n};\n\n// `badgeSize` is the default height and min-width of the badge circle/oval\n// Hard-coded here, but can be overridden by `size` prop in the component\nconst badgeSize = 22;\n\n// Defaults for badge come from typography.presets.label.small\nconst badgeText = dsTheme.typography.presets.label[TextSize.Small];\n\n// TODO: Extract `CountBadge` to its own component?\nconst CountBadge = styled(Text.Span)`\n  ${({ size = badgeSize, fontSize = badgeText.size, theme }) => css`\n    min-width: ${size}px;\n    width: auto;\n    height: ${size}px;\n    padding: 0 ${size / 4}px;\n    margin: 0 8px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    color: ${theme.colors.fg.primary};\n    background-color: ${theme.colors.bg.quaternary};\n    border-radius: 9999px;\n    font-size: ${fontSize}px;\n    line-height: 0;\n  `}\n`;\nCountBadge.propTypes = {\n  size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n  fontSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n};\n\nexport const ToggleButton = forwardRef(\n  (\n    {\n      copy,\n      isOpen = false,\n      notificationCount = 0,\n      MainIcon,\n      label,\n      shortcut,\n      popupZIndexOverride,\n      hasMenuList = false,\n      ...rest\n    },\n    ref\n  ) => {\n    const hasNotifications = notificationCount > 0;\n\n    return (\n      <Tooltip\n        hasTail\n        title={label}\n        placement={Placement.Top}\n        shortcut={shortcut}\n        popupZIndexOverride={popupZIndexOverride}\n      >\n        <Button\n          ref={ref}\n          aria-haspopup\n          aria-pressed={isOpen}\n          aria-expanded={isOpen}\n          hasText={Boolean(copy)}\n          isOpen={isOpen}\n          isSquare={!hasNotifications}\n          type={ButtonType.Tertiary}\n          variant={ButtonVariant.Rectangle}\n          size={ButtonSize.Medium}\n          {...rest}\n        >\n          {MainIcon && <MainIcon className=\"main-icon\" />}\n          {copy}\n          {hasNotifications && <CountBadge>{notificationCount}</CountBadge>}\n          {hasMenuList && <Disclosure direction=\"down\" $isOpen={isOpen} />}\n        </Button>\n      </Tooltip>\n    );\n  }\n);\n\nToggleButton.displayName = 'ToggleButton';\n\nToggleButton.propTypes = {\n  copy: PropTypes.string,\n  isOpen: PropTypes.bool,\n  label: PropTypes.string,\n  MainIcon: PropTypes.any,\n  notificationCount: PropTypes.number,\n  shortcut: PropTypes.string,\n  popupZIndexOverride: PropTypes.number,\n  hasMenuList: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/toggleButton/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Icons } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { ToggleButton } from '..';\n\nexport default {\n  title: 'Stories Editor/Components/ToggleButton',\n  args: {\n    ariaLabel: 'my help center label',\n    isOpen: false,\n    notificationCount: 0,\n  },\n  argTypes: {\n    helpCenterClick: { action: 'help center clicked' },\n    checklistClicked: { action: 'checklist clicked' },\n  },\n};\n\nconst Container = styled.div`\n  margin: 20px;\n  display: grid;\n  grid-gap: 8px;\n  padding: 8px;\n  grid-template-columns: 200px 200px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <Container>\n        <ToggleButton\n          label=\"Help\"\n          MainIcon={Icons.QuestionMarkOutline}\n          onClick={() => args.helpCenterClick()}\n          aria-owns=\"my popupId\"\n          {...args}\n        />\n        <ToggleButton\n          label=\"Checklist\"\n          MainIcon={Icons.Checkbox}\n          onClick={() => args.checklistClicked()}\n          aria-owns=\"my popupId\"\n          {...args}\n        />\n      </Container>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/tooltip/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './tooltip';\n"
  },
  {
    "path": "packages/story-editor/src/components/tooltip/tooltip.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  Tooltip as BaseTooltip,\n  Placement,\n} from '@googleforcreators/design-system';\n\nexport default function Tooltip({\n  hasTail = true,\n  placement = Placement.Bottom,\n  ...props\n}) {\n  // The <BaseTooltip> component will handle proper placement for RTL layout\n  return <BaseTooltip placement={placement} hasTail={hasTail} {...props} />;\n}\nTooltip.propTypes = {\n  children: PropTypes.node.isRequired,\n  hasTail: PropTypes.bool,\n  placement: PropTypes.oneOf(Object.values(Placement)),\n  onBlur: PropTypes.func,\n  onFocus: PropTypes.func,\n  shortcut: PropTypes.string,\n  title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),\n  forceAnchorRef: PropTypes.object,\n  styleOverride: PropTypes.object,\n  className: PropTypes.string,\n  isDelayed: PropTypes.bool,\n  popupZIndexOverride: PropTypes.number,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/transition/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './scheduledTransition';\n"
  },
  {
    "path": "packages/story-editor/src/components/transition/scheduledTransition.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useReducer,\n  useEffect,\n  useState,\n  useRef,\n  forwardRef,\n  cloneElement,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { Transition } from 'react-transition-group';\n\nconst entering = 'entering';\nconst entered = 'entered';\nconst exiting = 'exiting';\nconst exited = 'exited';\n\nconst machine = {\n  initial: 'default',\n  states: {\n    default: { entering },\n    entering: { entered },\n    entered: { exiting },\n    exiting: { exited },\n    exited: { entering },\n  },\n};\n\nconst reducer = (state, action) => machine.states[state]?.[action] || state;\n\n// Used as an interpretation layer between Transition\n// and children being called with state. Allows for first\n// render of default styles while keeping timeout in sync\n// with state. Fixes issues discussed here:\n// https://github.com/reactjs/react-transition-group/issues/284#issuecomment-771037685\nexport const Interpreter = forwardRef(({ state, children }, ref) => {\n  const [scheduledState, dispatch] = useReducer(\n    reducer,\n    state === entered ? state : machine.initial\n  );\n  const [nextRender, setNextRender] = useState(state);\n\n  // Ensures we get a paint with every current state\n  // we are on before we interpret an update.\n  useEffect(() => {\n    const id = requestAnimationFrame(() => setNextRender(state));\n    return () => cancelAnimationFrame(id);\n  }, [state]);\n\n  // Use our state machine implementation to deterministically order state\n  // transitions. Ensures following order & at least one render on each state:\n  // default -> entering -> entered -> exiting -> exited\n  useEffect(() => {\n    dispatch(nextRender);\n  }, [nextRender]);\n\n  // We want to opt out of our expected behavior immediately if there's a premature\n  // enter or exit scenario.\n  //\n  // It's important that these state changes are reflected on exactly this render,\n  // as opposed to in the state machine, to prevent content flash where two children\n  // of a transition group can both be in an `enter` or `exit` state in the same paint.\n  const isPrematureExit =\n    [entering, entered].includes(scheduledState) && state === 'exiting';\n  const isPrematureEntrance =\n    [exiting].includes(scheduledState) && [entering, entered].includes(state);\n  const shouldUseBaseState = isPrematureEntrance || isPrematureExit;\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  return cloneElement(children(shouldUseBaseState ? state : scheduledState), {\n    ref,\n  });\n});\n\nexport function ScheduledTransition({ children, ...props }) {\n  const nodeRef = useRef();\n  return (\n    <Transition nodeRef={nodeRef} {...props}>\n      {(state) => (\n        <Interpreter ref={nodeRef} state={state}>\n          {(scheduledState) => children(scheduledState)}\n        </Interpreter>\n      )}\n    </Transition>\n  );\n}\nScheduledTransition.propTypes = {\n  children: PropTypes.func,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({});\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/dropTarget.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useCallback, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { isDraggingFile } from '../../utils/dragEvent';\nimport Context from './context';\n\nconst DropTargetComponent = styled.div`\n  position: relative;\n  width: 100%;\n  height: 100%;\n`;\n\nconst Content = styled.div`\n  position: relative;\n  width: 100%;\n  height: 100%;\n`;\n\n// The glasspane is displayed above everything and takes over the DND events.\n// This is the safest way to avoid false-positive enter/leave events.\nconst Glasspane = styled.div`\n  position: absolute;\n  z-index: 1000;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n`;\n\nfunction disableDefaults(evt) {\n  evt.preventDefault();\n  evt.stopPropagation();\n}\n\nfunction UploadDropTarget({\n  disabled = false,\n  label = null,\n  labelledBy = null,\n  onDrop = null,\n  children,\n}) {\n  const [isDragging, setIsDragging] = useState(false);\n\n  const onDragEnter = useCallback(\n    (e) => {\n      const { dataTransfer } = e;\n      if (!isDraggingFile(e)) {\n        // Only consider DND with files.\n        return;\n      }\n      disableDefaults(e);\n      if (disabled) {\n        dataTransfer.effectAllowed = 'none';\n      } else {\n        dataTransfer.effectAllowed = 'copy';\n        setIsDragging(true);\n      }\n    },\n    [disabled]\n  );\n\n  const onDragLeave = useCallback((evt) => {\n    disableDefaults(evt);\n    setIsDragging(false);\n  }, []);\n\n  const onDropHandler = useCallback(\n    (evt) => {\n      disableDefaults(evt);\n      setIsDragging(false);\n      if (!disabled && onDrop) {\n        onDrop([...evt.dataTransfer.files]);\n      }\n    },\n    [disabled, onDrop]\n  );\n\n  return (\n    <DropTargetComponent\n      onDragEnter={onDragEnter}\n      onDrop={onDropHandler}\n      onDragOver={disableDefaults}\n    >\n      {isDragging && (\n        <Glasspane\n          onDragEnter={onDragEnter}\n          onDragLeave={onDragLeave}\n          onDragOver={disableDefaults}\n          onDrop={onDropHandler}\n          aria-label={label}\n          aria-labelledby={labelledBy}\n        />\n      )}\n      <Context.Provider value={{ isDragging }}>\n        <Content>{children}</Content>\n      </Context.Provider>\n    </DropTargetComponent>\n  );\n}\n\nUploadDropTarget.propTypes = {\n  disabled: PropTypes.bool,\n  label: PropTypes.string,\n  labelledBy: PropTypes.string,\n  onDrop: PropTypes.func,\n  children: PropTypes.node.isRequired,\n};\n\nexport default UploadDropTarget;\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as UploadDropTarget } from './dropTarget';\nexport { default as UploadDropTargetMessage } from './message';\nexport { default as UploadDropTargetOverlay } from './overlay';\nexport { default as useUploadDropTarget } from './use';\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/message.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { memo, useMemo } from '@googleforcreators/react';\nimport {\n  Icons,\n  Text as DefaultText,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app/config';\nimport UploadDropTargetOverlay from './overlay';\n\nconst Container = styled(UploadDropTargetOverlay)`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n`;\n\nconst Box = styled.div`\n  width: 100%;\n  max-width: 240px;\n  padding: 16px;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n`;\n\nconst Text = styled(DefaultText.Paragraph)`\n  color: ${({ theme }) => theme.colors.standard.white};\n  margin-bottom: 14px;\n  margin-top: 0px;\n`;\n\nconst Icon = styled(Icons.ArrowCloud)`\n  height: 52px;\n  width: 52px;\n  color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nfunction UploadDropTargetMessage({ message, ...rest }) {\n  const {\n    allowedMimeTypes: {\n      image: allowedImageMimeTypes,\n      vector: allowedVectorMimeTypes,\n      video: allowedVideoMimeTypes,\n    },\n  } = useConfig();\n\n  const allowedMimeTypes = useMemo(\n    () => [\n      ...allowedImageMimeTypes,\n      ...allowedVectorMimeTypes,\n      ...allowedVideoMimeTypes,\n    ],\n    [allowedImageMimeTypes, allowedVideoMimeTypes, allowedVectorMimeTypes]\n  );\n  const allowedFileTypes = useMemo(\n    () => allowedMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedMimeTypes]\n  );\n\n  let description = __('No file types are currently supported.', 'web-stories');\n\n  if (allowedFileTypes.length) {\n    description = sprintf(\n      /* translators: %s is a list of allowed file extensions. */\n      __('You can upload %s.', 'web-stories'),\n      translateToExclusiveList(allowedFileTypes)\n    );\n  }\n\n  return (\n    <Container {...rest}>\n      <Box>\n        <Icon />\n        <Text isBold size={TextSize.Medium}>\n          {message}\n        </Text>\n        <Text size={TextSize.Small}>{description}</Text>\n      </Box>\n    </Container>\n  );\n}\n\nUploadDropTargetMessage.propTypes = {\n  message: PropTypes.string.isRequired,\n};\n\nexport default memo(UploadDropTargetMessage);\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/overlay.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport { forwardRef } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useUploadDropTarget from './use';\n\nconst Overlay = styled.div`\n  position: absolute;\n  z-index: 999;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background-color: ${({ theme }) => rgba(theme.colors.bg.primary, 0.6)};\n`;\n\nfunction UploadDropTargetOverlayWithRef(props, ref) {\n  const { isDragging } = useUploadDropTarget((state) => ({\n    isDragging: state.isDragging,\n  }));\n  if (!isDragging) {\n    return null;\n  }\n  return <Overlay ref={ref} {...props} />;\n}\n\nconst UploadDropTargetOverlay = forwardRef(UploadDropTargetOverlayWithRef);\n\nexport default UploadDropTargetOverlay;\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/test/dropTarget.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, createEvent, fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport UploadDropTarget from '../dropTarget';\nimport useUploadDropTarget from '../use';\n\nconst onDropSpy = jest.fn();\n\nfunction UseUploadDropTargetConsumer() {\n  const { isDragging: isDraggingContext } = useUploadDropTarget();\n  return (\n    <div data-testid=\"isDragging\" data-value={String(isDraggingContext)} />\n  );\n}\n\ndescribe('UploadDropTarget', () => {\n  let view;\n  let container;\n  let content1, isDraggingElement;\n  let dataTransfer;\n  let transferFile1;\n\n  afterEach(() => {\n    onDropSpy.mockClear();\n  });\n\n  function getGlasspane() {\n    // eslint-disable-next-line testing-library/no-node-access\n    return container.querySelector('[aria-labelledby=\"glasspane\"]');\n  }\n\n  function isDragging() {\n    return Boolean(getGlasspane());\n  }\n\n  function fireDragEvent(target, type) {\n    const event = createEvent[type](target);\n    Object.defineProperty(event, 'dataTransfer', { value: dataTransfer });\n    Object.defineProperty(event, 'stopPropagation', { value: jest.fn() });\n    Object.defineProperty(event, 'preventDefault', { value: jest.fn() });\n    fireEvent(target, event);\n    return event;\n  }\n\n  describe('enter dragging mode', () => {\n    it('should start in a non-dragging mode', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      expect(isDragging()).toBeFalse();\n      expect(getGlasspane()).toBeNull();\n      expect(isDraggingElement).toHaveAttribute('data-value', 'false');\n    });\n\n    it('should start dragging on the container', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      const event = fireDragEvent(container, 'dragEnter');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n\n      expect(isDragging()).toBeTrue();\n      const glasspane = getGlasspane();\n      expect(glasspane).toHaveAttribute('aria-label', 'drop target');\n      expect(event.dataTransfer.effectAllowed).toBe('copy');\n    });\n\n    it('should start dragging on a child', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      const event = fireDragEvent(content1, 'dragEnter');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n      expect(isDragging()).toBeTrue();\n    });\n\n    it('should ignore non-file payloads', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      dataTransfer.types = ['text/html'];\n      dataTransfer.files = [];\n      const event = fireDragEvent(content1, 'dragEnter');\n      expect(event.preventDefault).not.toHaveBeenCalledWith();\n      expect(event.stopPropagation).not.toHaveBeenCalledWith();\n      expect(isDragging()).toBeFalse();\n    });\n  });\n\n  describe('in dragging mode', () => {\n    it('should have the glasspane and the context in dragging mode', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n      const glasspane = getGlasspane();\n\n      expect(isDragging()).toBeTrue();\n      expect(getGlasspane()).not.toBeNull();\n      expect(getGlasspane()).toBe(glasspane);\n      expect(isDraggingElement).toHaveAttribute('data-value', 'true');\n    });\n\n    it('should continue dragging when the container exits', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n\n      const event = fireDragEvent(container, 'dragLeave');\n      expect(event.preventDefault).not.toHaveBeenCalledWith();\n      expect(event.stopPropagation).not.toHaveBeenCalledWith();\n      expect(isDragging()).toBeTrue();\n    });\n\n    it('should continue dragging when a child exits', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n\n      const event = fireDragEvent(content1, 'dragLeave');\n      expect(event.preventDefault).not.toHaveBeenCalledWith();\n      expect(event.stopPropagation).not.toHaveBeenCalledWith();\n      expect(isDragging()).toBeTrue();\n    });\n\n    it('should cancel dragging over the container', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n\n      const event = fireDragEvent(container, 'dragOver');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n      expect(isDragging()).toBeTrue();\n    });\n\n    it('should intercept dragging over the glasspane', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n      const glasspane = getGlasspane();\n\n      const event = fireDragEvent(glasspane, 'dragOver');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n      expect(isDragging()).toBeTrue();\n    });\n\n    it('should cancel dragging when the glasspane exits', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n      const glasspane = getGlasspane();\n\n      const event = fireDragEvent(glasspane, 'dragLeave');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n      expect(onDropSpy).not.toHaveBeenCalledWith();\n\n      // State is reset.\n      expect(isDragging()).toBeFalse();\n      expect(getGlasspane()).toBeNull();\n      expect(isDraggingElement).toHaveAttribute('data-value', 'false');\n    });\n\n    it('should drop and exit the dragging mode', () => {\n      view = render(\n        <UploadDropTarget\n          label=\"drop target\"\n          labelledBy=\"glasspane\"\n          onDrop={onDropSpy}\n        >\n          <div data-testid=\"content1\">{'content 1'}</div>\n          <UseUploadDropTargetConsumer />\n        </UploadDropTarget>\n      );\n      // eslint-disable-next-line testing-library/no-node-access\n      container = view.container.firstElementChild;\n      content1 = screen.getByTestId('content1');\n      isDraggingElement = screen.getByTestId('isDragging');\n      transferFile1 = {};\n      dataTransfer = {\n        effectAllowed: 'none',\n        types: ['Files'],\n        files: [transferFile1],\n      };\n\n      fireDragEvent(container, 'dragEnter');\n      const glasspane = getGlasspane();\n\n      const event = fireDragEvent(glasspane, 'drop');\n      expect(event.preventDefault).toHaveBeenCalledWith();\n      expect(event.stopPropagation).toHaveBeenCalledWith();\n      expect(onDropSpy).toHaveBeenCalledWith([...dataTransfer.files]);\n\n      // State is reset.\n      expect(isDragging()).toBeFalse();\n      expect(getGlasspane()).toBeNull();\n      expect(isDraggingElement).toHaveAttribute('data-value', 'false');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/uploadDropTarget/use.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useUploadDropTarget(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useUploadDropTarget;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/constants.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const RAIL_HEIGHT = 36;\nexport const RAIL_PADDING = 2;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/currentTime.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport Slider from './slider';\nimport useVideoTrim from './useVideoTrim';\n\nconst StyledSlider = styled(Slider)`\n  top: -3px;\n  bottom: -3px;\n  width: 6px;\n  margin-left: -3px;\n  border-radius: 6px;\n  border-width: 0;\n  background-color: ${({ theme }) => theme.colors.interactiveBg.primaryNormal};\n  box-shadow:\n    0px 1px 2px rgba(60, 64, 67, 0.3),\n    0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n`;\n\nfunction CurrentTime(props) {\n  const currentTime = useVideoTrim(({ state: { currentTime } }) => currentTime);\n  return (\n    <StyledSlider\n      aria-label={__('Current time', 'web-stories')}\n      value={currentTime}\n      disabled\n      {...props}\n    />\n  );\n}\n\nexport default CurrentTime;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/generateVideoStrip.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  getMediaSizePositionProps,\n  preloadVideo,\n  seekVideo,\n} from '@googleforcreators/media';\n\nconst CACHE = new Map();\n\n/**\n * Returns an image data URL with a video strip of the frames of the video.\n *\n * @param {Object} element Canvas element with information about size, scale, and focal point.\n * @param {Object} resource Resource object with url and video length.\n * @param {number} stripWidth Target strip width.\n * @param {number} stripHeight Video src URL.\n * @return {Promise<string|null>} The video strip as a data URL or null if there was an error.\n */\nasync function generateVideoStrip(element, resource, stripWidth, stripHeight) {\n  const {\n    width: frameWidth,\n    height: frameHeight,\n    scale,\n    focalX,\n    focalY,\n    flip,\n  } = element;\n\n  const { src, length } = resource;\n\n  // First check if we already generated this exact strip\n  const cacheKey = JSON.stringify([\n    src,\n    stripWidth,\n    stripHeight,\n    scale,\n    focalX,\n    focalY,\n    flip,\n    frameWidth,\n    frameHeight,\n  ]);\n  if (CACHE.has(cacheKey)) {\n    return CACHE.get(cacheKey);\n  }\n\n  // Calculate the scaled frame width in the strip\n  const stripFrameHeight = stripHeight;\n  const stripFrameWidth = (stripFrameHeight / frameHeight) * frameWidth;\n\n  // Calculate how many frames we can fit in the strip (rounded up)\n  const frameCount = Math.ceil(stripWidth / stripFrameWidth);\n\n  // Calculate what the actual width of each frame will have to be to squeeze the images in\n  const actualStripFrameWidth = stripWidth / frameCount;\n\n  // Scale the original frame width down by the same amount so we don't squish the frames\n  const actualFrameWidth =\n    (actualStripFrameWidth / stripFrameWidth) * frameWidth;\n\n  // get video size based on scale and focal\n  const {\n    width: videoWidth,\n    height: videoHeight,\n    offsetX,\n    offsetY,\n  } = getMediaSizePositionProps(\n    resource,\n    actualFrameWidth,\n    frameHeight,\n    scale,\n    flip?.horizontal ? 100 - focalX : focalX,\n    flip?.vertical ? 100 - focalY : focalY\n  );\n\n  // Calculate the offset between each frame to be grabbed\n  const frameDistance = length / (frameCount - 1);\n\n  // Preload video and adjust size\n  const video = await preloadVideo(src);\n  video.width = videoWidth;\n  video.height = videoHeight;\n\n  // Skipping the first fraction of a millisecond to prevent blank frames in chrome\n  await seekVideo(video, 0.000001);\n\n  // Create the target canvas\n  const canvas = document.createElement('canvas');\n  canvas.width = stripWidth;\n  canvas.height = stripHeight;\n  const ctx = canvas.getContext('2d');\n\n  // If the contextType doesn't match a possible drawing context,\n  // or differs from the first contextType requested, null is returned.\n  if (!ctx) {\n    return Promise.resolve(null);\n  }\n\n  // Create a function to grab the current frame and either schedule next or abort\n  let timeOffset = 0;\n  let frame = 0;\n  const grabFrame = async () => {\n    // Seek to the next offset\n    await seekVideo(video, timeOffset);\n\n    const dx = frame * actualStripFrameWidth;\n\n    if (flip.vertical || flip.horizontal) {\n      // Translate context to center of canvas\n      ctx.translate(dx + actualStripFrameWidth / 2, stripFrameHeight / 2);\n      // Flip context\n      ctx.scale(flip.horizontal ? -1 : 1, flip.vertical ? -1 : 1);\n      // Translate context back to origin\n      ctx.translate(-(dx + actualStripFrameWidth / 2), -(stripFrameHeight / 2));\n    }\n\n    // Now copy the correct part of the video to the correct part of the context\n    ctx.drawImage(\n      video,\n      // Source position\n      offsetX,\n      offsetY,\n      // Source dimension\n      actualFrameWidth,\n      frameHeight,\n      // Destination position\n      dx,\n      0,\n      // Destination dimension\n      actualStripFrameWidth,\n      stripFrameHeight\n    );\n\n    // Restore default matrix instead of calling `ctx.restore`\n    ctx.setTransform(1, 0, 0, 1, 0, 0);\n\n    // If there are no more frames, return resolved promise\n    frame += 1;\n    if (frame === frameCount) {\n      return Promise.resolve();\n    }\n\n    // Else, advance time and grab next frame\n    timeOffset += frameDistance;\n    return grabFrame();\n  };\n\n  return grabFrame().then(() => {\n    const finalStrip = canvas.toDataURL();\n    CACHE.set(cacheKey, finalStrip);\n    return finalStrip;\n  });\n}\n\nexport default generateVideoStrip;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { default as VideoTrimProvider } from './provider';\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/provider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { formatMsToHMS, getVideoLengthDisplay } from '@googleforcreators/media';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport { useLocalMedia } from '../../app';\nimport VideoTrimContext from './videoTrimContext';\nimport useVideoTrimMode from './useVideoTrimMode';\nimport useVideoNode from './useVideoNode';\n\nfunction VideoTrimProvider({ children }) {\n  const { trimExistingVideo } = useLocalMedia(\n    ({ actions: { trimExistingVideo } }) => ({\n      trimExistingVideo,\n    })\n  );\n  const { isTrimMode, hasTrimMode, toggleTrimMode, videoData } =\n    useVideoTrimMode();\n  const {\n    hasChanged,\n    currentTime,\n    startOffset,\n    endOffset,\n    maxOffset,\n    videoNode,\n    setStartOffset,\n    setEndOffset,\n    setVideoNode,\n    setIsDraggingHandles,\n  } = useVideoNode(videoData);\n\n  const performTrim = useCallback(() => {\n    const { resource, element } = videoData;\n    if (!resource) {\n      return;\n    }\n    const lengthInSeconds = Math.round(endOffset / 1000 - startOffset / 1000);\n    trimExistingVideo({\n      resource: {\n        ...resource,\n        length: lengthInSeconds,\n        lengthFormatted: getVideoLengthDisplay(lengthInSeconds),\n      },\n      // This is the ID of the resource that's currently on canvas and needs to be cloned.\n      // It's only different from the above resource, if the canvas resource is a trim of the other.\n      canvasResourceId: element.resource.id,\n      elementId: element.id,\n      start: formatMsToHMS(startOffset),\n      end: formatMsToHMS(endOffset),\n    });\n    trackEvent('video_trim', {\n      original_length: resource.length,\n      new_length: lengthInSeconds,\n      start_offset: startOffset,\n      end_offset: endOffset,\n    });\n    toggleTrimMode();\n  }, [endOffset, startOffset, trimExistingVideo, toggleTrimMode, videoData]);\n\n  const value = {\n    state: {\n      videoData,\n      hasChanged,\n      isTrimMode,\n      hasTrimMode,\n      currentTime,\n      startOffset,\n      endOffset,\n      maxOffset,\n      videoNode,\n    },\n    actions: {\n      performTrim,\n      toggleTrimMode,\n      setVideoNode,\n      setStartOffset,\n      setEndOffset,\n      setIsDraggingHandles,\n    },\n  };\n\n  return (\n    <VideoTrimContext.Provider value={value}>\n      {children}\n    </VideoTrimContext.Provider>\n  );\n}\n\nVideoTrimProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n};\n\nexport default VideoTrimProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/recordingProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport VideoTrimContext from './videoTrimContext';\nimport useVideoNode from './useVideoNode';\n\nfunction VideoRecordingTrimProvider({ children, onTrim, videoData }) {\n  const {\n    hasChanged,\n    currentTime,\n    startOffset,\n    endOffset,\n    maxOffset,\n    videoNode,\n    setStartOffset,\n    setEndOffset,\n    setVideoNode,\n    setIsDraggingHandles,\n  } = useVideoNode(videoData);\n\n  const performTrim = useCallback(() => {\n    onTrim({\n      start: startOffset,\n      end: endOffset,\n    });\n    trackEvent('recording_video_trim', {\n      start_offset: startOffset,\n      end_offset: endOffset,\n    });\n  }, [endOffset, startOffset, onTrim]);\n\n  const value = {\n    state: {\n      videoData,\n      hasChanged,\n      isTrimMode: true,\n      currentTime,\n      startOffset,\n      endOffset,\n      maxOffset,\n      videoNode,\n    },\n    actions: {\n      performTrim,\n      setVideoNode,\n      setStartOffset,\n      setEndOffset,\n      setIsDraggingHandles,\n      toggleTrimMode: () => onTrim(),\n    },\n  };\n\n  return (\n    <VideoTrimContext.Provider value={value}>\n      {children}\n    </VideoTrimContext.Provider>\n  );\n}\n\nVideoRecordingTrimProvider.propTypes = {\n  children: PropTypes.node.isRequired,\n  onTrim: PropTypes.func.isRequired,\n  videoData: PropTypes.object,\n};\n\nexport default VideoRecordingTrimProvider;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/slider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { useRef, useCallback } from '@googleforcreators/react';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { noop } from '../../utils/noop';\n\nconst Thumb = styled.button`\n  position: absolute;\n  padding: 0;\n`;\n\nfunction getPageX(evt) {\n  return evt.pageX || evt.clientX;\n}\n\nfunction Slider({\n  railWidth,\n  min,\n  max,\n  step,\n  minorStep = null,\n  value = 0,\n  onChange = noop,\n  getValueText = null,\n  onPointerDown = noop,\n  onNudge = noop,\n  ...rest\n}) {\n  const ref = useRef();\n\n  const handlePointerDown = useCallback(\n    (downEvent) => {\n      // Stop propagation, but manually set focus\n      downEvent.preventDefault();\n      downEvent.stopPropagation();\n      ref.current.focus();\n\n      onPointerDown?.();\n\n      const handlePointerMove = (event) => {\n        const deltaX = getPageX(event) - getPageX(downEvent);\n        const deltaRatio = deltaX / railWidth;\n        const deltaValue = deltaRatio * (max - min);\n        const newValue = value + deltaValue;\n        onChange(newValue);\n\n        event.preventDefault();\n        event.stopPropagation();\n      };\n\n      const handlePointerUp = () => {\n        document.removeEventListener('pointermove', handlePointerMove);\n        document.removeEventListener('pointerup', handlePointerUp);\n      };\n\n      document.addEventListener('pointermove', handlePointerMove);\n      document.addEventListener('pointerup', handlePointerUp);\n\n      return handlePointerUp;\n    },\n    [value, max, min, onChange, railWidth, onPointerDown]\n  );\n\n  const handleNudge = useCallback(\n    (delta) => {\n      onChange(value + delta);\n      onNudge?.();\n    },\n    [onChange, onNudge, value]\n  );\n\n  useKeyDownEffect(ref, 'left', () => handleNudge(-step), [handleNudge, step]);\n  useKeyDownEffect(ref, 'shift+left', () => handleNudge(-minorStep), [\n    handleNudge,\n    minorStep,\n  ]);\n  useKeyDownEffect(ref, 'right', () => handleNudge(step), [handleNudge, step]);\n  useKeyDownEffect(ref, 'shift+right', () => handleNudge(minorStep), [\n    handleNudge,\n    minorStep,\n  ]);\n\n  const ratio = (value - min) / (max - min);\n  const cssValue = `${(ratio * railWidth).toFixed(2)}px`;\n  const sliderStyle = { left: cssValue };\n\n  return (\n    <Thumb\n      ref={ref}\n      onPointerDown={handlePointerDown}\n      style={sliderStyle}\n      role=\"slider\"\n      aria-valuemin={min}\n      aria-valuemax={max}\n      aria-valuenow={value}\n      aria-valuetext={getValueText?.(value)}\n      {...rest}\n    />\n  );\n}\n\nSlider.propTypes = {\n  railWidth: PropTypes.number.isRequired,\n  min: PropTypes.number.isRequired,\n  max: PropTypes.number.isRequired,\n  step: PropTypes.number.isRequired,\n  minorStep: PropTypes.number.isRequired,\n  value: PropTypes.number,\n  onChange: PropTypes.func,\n  getValueText: PropTypes.func,\n  onPointerDown: PropTypes.func,\n  onNudge: PropTypes.func,\n};\n\nexport default Slider;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/test/useVideoNode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport { MEDIA_VIDEO_MINIMUM_DURATION } from '../../../constants';\nimport useVideoNode from '../useVideoNode';\n\nfunction setup(videoData = {}) {\n  return renderHook(() => useVideoNode({ start: 0, end: null, ...videoData }));\n}\n\nfunction loadVideo(result, duration) {\n  const videoNode = new DummyVideo();\n  act(() => {\n    result.current.setVideoNode(videoNode);\n  });\n  act(() => {\n    videoNode.loadedmetadata({ target: { duration } });\n  });\n  return videoNode;\n}\n\ndescribe('useVideoNode', () => {\n  it('should initially be empty when no video has loaded', () => {\n    const { result } = setup();\n\n    expect(result.current.hasChanged).toBeFalse();\n    expect(result.current.startOffset).toBeNull();\n    expect(result.current.endOffset).toBeNull();\n    expect(result.current.maxOffset).toBeNull();\n  });\n\n  it('should set offsets when video has loaded', () => {\n    const { result } = setup();\n\n    const videoNode = loadVideo(result, 10);\n\n    // Expect offsets to have been set:\n    expect(result.current.hasChanged).toBeFalse();\n    expect(result.current.startOffset).toBe(0);\n    expect(result.current.endOffset).toBe(10000);\n    expect(result.current.maxOffset).toBe(10000);\n\n    // Expect video to be playing from 0 second on\n    expect(videoNode.playing).toBeTrue();\n    expect(videoNode.currentTime).toBe(0);\n  });\n\n  it('should set offsets from video data when video has loaded', () => {\n    const { result } = setup({ start: 1000, end: 9000 });\n\n    const videoNode = loadVideo(result, 10);\n\n    // Expect offsets to have been set:\n    expect(result.current.hasChanged).toBeFalse();\n    expect(result.current.startOffset).toBe(1000);\n    expect(result.current.endOffset).toBe(9000);\n    expect(result.current.maxOffset).toBe(10000);\n\n    // Expect video to be playing from 1 second on\n    expect(videoNode.playing).toBeTrue();\n    expect(videoNode.currentTime).toBe(1);\n  });\n\n  it('should update current time and loop correctly', () => {\n    const { result } = setup({ start: 1000 });\n\n    const videoNode = loadVideo(result, 10);\n\n    // Expect currentTime to be initial\n    expect(result.current.currentTime).toBe(1000);\n\n    // Forward playhead to 2s\n    videoNode.setCurrentTime(2);\n\n    // Expect currentTime to be updated\n    expect(result.current.currentTime).toBe(2000);\n\n    // Forward playhead to 11s, which is beyond the end\n    videoNode.setCurrentTime(11);\n\n    // Expect currentTime in hook to be at end\n    expect(result.current.currentTime).toBe(10000);\n\n    // But expect video node to have been looped back to start\n    expect(videoNode.currentTime).toBe(1);\n\n    // Set start offset to 2000\n    act(() => result.current.setStartOffset(2000));\n\n    // Expect video node to be set to new offset\n    expect(videoNode.currentTime).toBe(2);\n\n    // Set end offset to 8000\n    act(() => result.current.setEndOffset(8000));\n\n    // Expect video node to be set to new offset\n    expect(videoNode.currentTime).toBe(8);\n\n    // Forward playhead to 9s, which is before the real end but after current end offset\n    videoNode.setCurrentTime(9);\n\n    // Expect currentTime in hook to be at end\n    expect(result.current.currentTime).toBe(8000);\n\n    // But expect video node to have been looped back to the new start offset\n    expect(videoNode.currentTime).toBe(2);\n  });\n\n  it('should update hasChanged flag correctly', () => {\n    const { result } = setup({ start: 1000 });\n\n    loadVideo(result, 10);\n\n    // Expect currentTime to be initial\n    expect(result.current.hasChanged).toBeFalse();\n\n    /// Set start offset to 2000\n    act(() => result.current.setStartOffset(2000));\n\n    // Expect hasChanged to be true\n    expect(result.current.hasChanged).toBeTrue();\n\n    /// Set start offset back to 1000\n    act(() => result.current.setStartOffset(1000));\n\n    // Expect hasChanged to be back at false\n    expect(result.current.hasChanged).toBeFalse();\n\n    // Set end offset to 8000\n    act(() => result.current.setEndOffset(8000));\n\n    // Expect hasChanged to be true again\n    expect(result.current.hasChanged).toBeTrue();\n  });\n\n  it('should enforce minimum video duration', () => {\n    const { result } = setup({ start: 1000 });\n\n    loadVideo(result, 10);\n\n    /// Set start and end offset to the same value\n    // Note, this must be done in two separate act()'s!\n    act(() => result.current.setStartOffset(5000));\n    act(() => result.current.setEndOffset(5000));\n\n    // Expect start offset to be correct, but end offset to be min duration off\n    expect(result.current.startOffset).toBe(5000);\n    expect(result.current.endOffset).toBe(5000 + MEDIA_VIDEO_MINIMUM_DURATION);\n  });\n});\n\nfunction DummyVideo() {\n  this.currentTime = 0;\n  this.playing = false;\n  this.duration = null;\n  this.play = () => {\n    this.playing = true;\n    return Promise.resolve(true);\n  };\n  this.addEventListener = (event, callback) => {\n    this[event] = callback;\n  };\n  this.removeEventListener = () => {};\n  this.setCurrentTime = (newCurrentTime) => {\n    this.currentTime = newCurrentTime;\n    act(() => this.timeupdate({ target: this }));\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/test/useVideoTrimMode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport CanvasContext from '../../../app/canvas/context';\nimport APIContext from '../../../app/api/context';\nimport StoryContext from '../../../app/story/context';\nimport useVideoTrimMode from '../useVideoTrimMode';\nimport { useLocalMedia } from '../../../app/media';\n\njest.mock('../../../app/media');\n\nconst mockTranscodingEnabled = jest.fn().mockImplementation(() => true);\n\njest.mock('../../../app/media/utils/useFFmpeg', () => () => ({\n  isTranscodingEnabled: mockTranscodingEnabled(),\n}));\n\nfunction setup({\n  mockGetMediaById,\n  canvas = {},\n  element = {},\n  extraElements = [],\n} = {}) {\n  const canvasCtx = {\n    state: {\n      isEditing: false,\n      editingElementState: undefined,\n      ...canvas,\n    },\n    actions: {\n      setEditingElementWithState: jest.fn(),\n      clearEditing: jest.fn(),\n    },\n  };\n  const apiCtx = {\n    actions: {\n      getMediaById: mockGetMediaById ? mockGetMediaById : jest.fn(),\n    },\n  };\n  const storyCtx = {\n    state: {\n      selectedElements: [\n        {\n          type: 'video',\n          id: 'video123',\n          ...element,\n          resource: { isExternal: false, src: 'bar', ...element?.resource },\n        },\n        ...extraElements,\n      ],\n    },\n  };\n  const wrapper = ({ children }) => (\n    <CanvasContext.Provider value={canvasCtx}>\n      <APIContext.Provider value={apiCtx}>\n        <StoryContext.Provider value={storyCtx}>\n          {children}\n        </StoryContext.Provider>\n      </APIContext.Provider>\n    </CanvasContext.Provider>\n  );\n  const rendering = renderHook(() => useVideoTrimMode(), { wrapper });\n\n  return {\n    ...rendering,\n    ...canvasCtx.actions,\n    ...apiCtx.actions,\n  };\n}\n\ndescribe('useVideoTrimMode', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    useLocalMedia.mockReturnValue({\n      canTranscodeResource: jest.fn(() => true),\n      isCurrentResourceUploading: jest.fn(() => false),\n    });\n  });\n  it('should allow trim mode for single video element', () => {\n    const { result } = setup();\n\n    expect(result.current.isTrimMode).toBeFalse();\n    expect(result.current.hasTrimMode).toBeTrue();\n  });\n\n  it('should not allow trim mode for non-video', () => {\n    const { result } = setup({ element: { type: 'image' } });\n\n    expect(result.current.hasTrimMode).toBeFalse();\n  });\n\n  it('should not allow trim mode for resource that is currently being uploaded', () => {\n    useLocalMedia.mockReturnValue({\n      isCurrentResourceUploading: jest.fn(() => true),\n    });\n    const { result } = setup({ element: { resource: { id: 123 } } });\n\n    expect(result.current.hasTrimMode).toBeFalse();\n  });\n\n  it('should not allow trim mode for third-party video', () => {\n    useLocalMedia.mockReturnValue({\n      canTranscodeResource: jest.fn(),\n    });\n\n    const { result } = setup({ element: { resource: { isExternal: true } } });\n\n    expect(result.current.hasTrimMode).toBeFalse();\n  });\n\n  it('should not allow trim mode if multiple videos selected', () => {\n    const { result } = setup({ extraElements: [{ type: 'image' }] });\n\n    expect(result.current.hasTrimMode).toBeFalse();\n  });\n\n  it('should not allow trim mode if transcoding is not supported', () => {\n    mockTranscodingEnabled.mockImplementationOnce(() => false);\n    const { result } = setup();\n\n    expect(result.current.hasTrimMode).toBeFalse();\n  });\n\n  it('should not in trim mode if editing element without trim mode state', () => {\n    const { result } = setup({ canvas: { isEditing: true } });\n\n    expect(result.current.isTrimMode).toBeFalse();\n  });\n\n  it('should be in trim mode if editing element in trim mode state', () => {\n    const { result } = setup({\n      canvas: { isEditing: true, editingElementState: { isTrimMode: true } },\n    });\n\n    expect(result.current.isTrimMode).toBeTrue();\n  });\n\n  it('should exit trim mode if editing any element and toggling', () => {\n    const { result, clearEditing } = setup({\n      canvas: { isEditing: true, editingElementState: { isTrimMode: true } },\n    });\n\n    act(() => result.current.toggleTrimMode());\n    expect(clearEditing).toHaveBeenCalledWith();\n  });\n\n  it('should enter edit mode for original video', () => {\n    const { result, setEditingElementWithState } = setup();\n\n    act(() => result.current.toggleTrimMode());\n\n    expect(setEditingElementWithState).toHaveBeenCalledWith(\n      'video123',\n      expect.objectContaining({ isTrimMode: true })\n    );\n\n    expect(result.current.videoData).toStrictEqual({\n      element: expect.objectContaining({ id: 'video123' }),\n      resource: expect.any(Object),\n      start: 0,\n      end: null,\n    });\n  });\n\n  it('should enter edit mode for trimmed video with working original', async () => {\n    const originalId = 'video456';\n    const originalResource = { id: originalId };\n    const mockGetMediaById = jest\n      .fn()\n      .mockImplementation(() => Promise.resolve(originalResource));\n    const {\n      result,\n      setEditingElementWithState,\n      getMediaById,\n      waitForNextUpdate,\n    } = setup({\n      mockGetMediaById,\n      element: {\n        resource: {\n          trimData: {\n            original: originalId,\n            start: '00:00:02',\n            end: '00:00:08',\n          },\n        },\n      },\n    });\n\n    act(() => result.current.toggleTrimMode());\n\n    await waitForNextUpdate();\n\n    expect(getMediaById).toHaveBeenCalledWith(originalId);\n\n    expect(setEditingElementWithState).toHaveBeenCalledWith(\n      'video123',\n      expect.objectContaining({ isTrimMode: true })\n    );\n\n    expect(result.current.videoData).toStrictEqual({\n      element: expect.objectContaining({ id: 'video123' }),\n      resource: originalResource,\n      start: 2000,\n      end: 8000,\n    });\n\n    mockGetMediaById.mockClear();\n  });\n\n  it('should enter edit mode for trimmed video with broken original', async () => {\n    const originalId = 'video456';\n    const mockGetMediaById = jest\n      .fn()\n      .mockImplementation(() => Promise.reject(new Error('404')));\n\n    const {\n      result,\n      setEditingElementWithState,\n      getMediaById,\n      waitForNextUpdate,\n    } = setup({\n      mockGetMediaById,\n      element: {\n        resource: {\n          trimData: {\n            original: originalId,\n            start: '00:00:02',\n            end: '00:00:08',\n          },\n        },\n      },\n    });\n\n    act(() => result.current.toggleTrimMode());\n\n    await waitForNextUpdate();\n\n    expect(getMediaById).toHaveBeenCalledWith(originalId);\n\n    expect(setEditingElementWithState).toHaveBeenCalledWith(\n      'video123',\n      expect.objectContaining({ isTrimMode: true })\n    );\n\n    expect(result.current.videoData).toStrictEqual({\n      element: expect.objectContaining({ id: 'video123' }),\n      resource: expect.any(Object),\n      start: 0,\n      end: null,\n    });\n\n    mockGetMediaById.mockClear();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/test/videoTrimmer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport {\n  renderWithTheme,\n  firePointerEvent,\n} from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport VideoTrimmer from '../videoTrimmer';\nimport VideoTrimContext from '../videoTrimContext';\nimport LayoutContext from '../../../app/layout/context';\n\njest.mock('../useRailBackground');\n\nfunction setup({ trim, layout } = {}) {\n  const layoutCtx = {\n    state: {\n      workspaceWidth: 1000,\n      pageWidth: 100,\n      ...layout,\n    },\n  };\n  const trimCtx = {\n    state: {\n      currentTime: 0,\n      startOffset: 0,\n      endOffset: 10000,\n      maxOffset: 10000,\n      hasChanged: false,\n      videoData: {},\n      ...trim,\n    },\n    actions: {\n      setStartOffset: jest.fn(),\n      setEndOffset: jest.fn(),\n      performTrim: jest.fn(),\n      toggleTrimMode: jest.fn(),\n      setIsDraggingHandles: jest.fn(),\n    },\n  };\n  const view = renderWithTheme(\n    <LayoutContext.Provider value={layoutCtx}>\n      <VideoTrimContext.Provider value={trimCtx}>\n        <VideoTrimmer />\n      </VideoTrimContext.Provider>\n    </LayoutContext.Provider>\n  );\n  const getVideoTrimmer = () =>\n    screen.getByRole('complementary', {\n      name: 'Video trimmer',\n    });\n  const getStartHandle = () =>\n    screen.getByRole('slider', { name: 'Start offset' });\n  const getEndHandle = () => screen.getByRole('slider', { name: 'End offset' });\n  const getCancel = () => screen.getByRole('button', { name: 'Cancel' });\n  const getSubmit = () => screen.getByRole('button', { name: 'Trim' });\n  const rerender = ({ layout: reLayout, trim: reTrim }) => {\n    const reLayoutCtx = {\n      ...layoutCtx,\n      state: { ...layoutCtx.state, ...reLayout },\n    };\n    const reTrimCtx = { ...trimCtx, state: { ...trimCtx.state, ...reTrim } };\n    view.rerender(\n      <LayoutContext.Provider value={reLayoutCtx}>\n        <VideoTrimContext.Provider value={reTrimCtx}>\n          <VideoTrimmer />\n        </VideoTrimContext.Provider>\n      </LayoutContext.Provider>\n    );\n  };\n  return {\n    ...view,\n    getVideoTrimmer,\n    getStartHandle,\n    getEndHandle,\n    getCancel,\n    getSubmit,\n    rerender,\n    layout: layoutCtx.state,\n    trim: trimCtx.state,\n    actions: trimCtx.actions,\n  };\n}\n\ndescribe('Video Trimmer', () => {\n  describe('as it loads', () => {\n    it('should render empty trimmer if missing page width', () => {\n      const { getVideoTrimmer } = setup({\n        layout: { pageWidth: null },\n      });\n\n      const videoTrimmer = getVideoTrimmer();\n      expect(videoTrimmer).toBeInTheDocument();\n      expect(videoTrimmer).toBeEmptyDOMElement();\n    });\n\n    it('should render empty trimmer if no video length', () => {\n      const { getVideoTrimmer } = setup({\n        trim: { maxOffset: null },\n      });\n\n      const videoTrimmer = getVideoTrimmer();\n      expect(videoTrimmer).toBeInTheDocument();\n      expect(videoTrimmer).toBeEmptyDOMElement();\n    });\n\n    it('should render empty trimmer if no video data', () => {\n      const { getVideoTrimmer } = setup({\n        trim: { videoData: null },\n      });\n\n      const videoTrimmer = getVideoTrimmer();\n      expect(videoTrimmer).toBeInTheDocument();\n      expect(videoTrimmer).toBeEmptyDOMElement();\n    });\n\n    it('should render correctly if all data ready', () => {\n      const { getVideoTrimmer } = setup();\n\n      const videoTrimmer = getVideoTrimmer();\n      expect(videoTrimmer).toBeInTheDocument();\n      expect(videoTrimmer).not.toBeEmptyDOMElement();\n    });\n\n    it('should display initial handles correctly if new trim', () => {\n      const { getStartHandle, getEndHandle } = setup();\n\n      expect(getStartHandle()).toHaveStyle('left: 0.00px');\n      expect(getEndHandle()).toHaveStyle('left: 100.00px');\n    });\n\n    it('should display initial handles correctly if re-trimming', () => {\n      const { getStartHandle, getEndHandle } = setup({\n        trim: { startOffset: 1000, endOffset: 9000 },\n      });\n\n      expect(getStartHandle()).toHaveStyle('left: 10.00px');\n      expect(getEndHandle()).toHaveStyle('left: 90.00px');\n    });\n\n    it('should have enabled cancel button', () => {\n      const { getCancel } = setup();\n\n      expect(getCancel()).toBeEnabled();\n    });\n\n    it('should have enabled trim button if and only if component handles have updated', () => {\n      const { getSubmit, rerender } = setup();\n      expect(getSubmit()).toBeDisabled();\n\n      rerender({ trim: { hasChanged: true } });\n      expect(getSubmit()).toBeEnabled();\n    });\n  });\n\n  describe('when interacted with', () => {\n    it('should invoke callbacks when using mouse to move start handle', () => {\n      const {\n        getStartHandle,\n        actions: { setStartOffset, setIsDraggingHandles },\n      } = setup();\n\n      const handle = getStartHandle();\n\n      // Click at position 0\n      firePointerEvent.pointerDown(handle, { clientX: 0 });\n\n      expect(setIsDraggingHandles).toHaveBeenCalledWith(true);\n      setIsDraggingHandles.mockReset();\n\n      // Move to the 10% mark\n      firePointerEvent.pointerMove(handle, { clientX: 10 });\n\n      expect(setStartOffset).toHaveBeenCalledWith(1000);\n      setStartOffset.mockReset();\n\n      // Move to the 30% mark\n      firePointerEvent.pointerMove(handle, { clientX: 30 });\n\n      expect(setStartOffset).toHaveBeenCalledWith(3000);\n      setStartOffset.mockReset();\n\n      // Release it\n      firePointerEvent.pointerUp(handle);\n\n      expect(setIsDraggingHandles).toHaveBeenCalledWith(false);\n    });\n\n    it('should invoke callbacks when using mouse to move end handle', () => {\n      const {\n        getEndHandle,\n        actions: { setEndOffset, setIsDraggingHandles },\n      } = setup();\n\n      const handle = getEndHandle();\n\n      // Click at position 0\n      firePointerEvent.pointerDown(handle, { clientX: 100 });\n\n      expect(setIsDraggingHandles).toHaveBeenCalledWith(true);\n      setIsDraggingHandles.mockReset();\n\n      // Move to the 90% mark\n      firePointerEvent.pointerMove(handle, { clientX: 90 });\n\n      expect(setEndOffset).toHaveBeenCalledWith(9000);\n      setEndOffset.mockReset();\n\n      // Move to the 70% mark\n      firePointerEvent.pointerMove(handle, { clientX: 70 });\n\n      expect(setEndOffset).toHaveBeenCalledWith(7000);\n\n      // Release it\n      firePointerEvent.pointerUp(handle);\n\n      expect(setIsDraggingHandles).toHaveBeenCalledWith(false);\n    });\n\n    describe('when using a keyboard', () => {\n      beforeEach(() => {\n        jest.useFakeTimers();\n      });\n\n      it('should invoke callbacks when moving start handle', () => {\n        const {\n          getStartHandle,\n          actions: { setStartOffset, setIsDraggingHandles },\n        } = setup();\n\n        const handle = getStartHandle();\n\n        // Move once to the right\n        fireEvent.keyDown(handle, { key: 'ArrowRight', which: 39 });\n\n        expect(setIsDraggingHandles).toHaveBeenCalledWith(true);\n        setIsDraggingHandles.mockReset();\n\n        expect(setStartOffset).toHaveBeenCalledWith(100);\n\n        // Run all timers to trigger the debounced release\n        jest.runAllTimers();\n\n        expect(setIsDraggingHandles).toHaveBeenCalledWith(false);\n      });\n\n      it('should invoke callbacks when moving end handle', () => {\n        const {\n          getEndHandle,\n          actions: { setEndOffset, setIsDraggingHandles },\n        } = setup();\n\n        const handle = getEndHandle();\n\n        // Move once to the left\n        fireEvent.keyDown(handle, { key: 'ArrowLeft', which: 37 });\n\n        expect(setIsDraggingHandles).toHaveBeenCalledWith(true);\n        setIsDraggingHandles.mockReset();\n\n        expect(setEndOffset).toHaveBeenCalledWith(9900);\n\n        // Run all timers to trigger the debounced release\n        jest.runAllTimers();\n\n        expect(setIsDraggingHandles).toHaveBeenCalledWith(false);\n      });\n    });\n\n    it('should invoke callback when cancelling', () => {\n      const {\n        getCancel,\n        actions: { toggleTrimMode },\n      } = setup();\n\n      fireEvent.click(getCancel());\n\n      expect(toggleTrimMode).toHaveBeenCalledWith(expect.any(Object));\n    });\n\n    it('should invoke callback when trimming', () => {\n      const {\n        getSubmit,\n        actions: { performTrim },\n      } = setup({ trim: { hasChanged: true } });\n\n      fireEvent.click(getSubmit());\n\n      expect(performTrim).toHaveBeenCalledWith(expect.any(Object));\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/trimmerComponents.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport { Text, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport Slider from './slider';\nimport { RAIL_HEIGHT, RAIL_PADDING } from './constants';\n\nexport const Menu = styled.aside`\n  display: flex;\n  justify-content: center;\n  align-items: flex-start;\n  height: ${RAIL_HEIGHT + RAIL_PADDING * 2}px;\n  gap: 14px;\n`;\n\nexport const RailWrapper = styled.div`\n  display: flex;\n  flex-direction: column;\n  justify-content: flex-start;\n  align-items: flex-end;\n`;\n\nexport const Rail = styled.div`\n  position: relative;\n  width: ${({ width }) => width}px;\n  height: ${RAIL_HEIGHT}px;\n  border-radius: 4px;\n  border: 1px solid ${({ theme }) => theme.colors.standard.white};\n  background-color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nexport function Duration({ children }) {\n  return <Text.Span size={TextSize.XSmall}>{children}</Text.Span>;\n}\nDuration.propTypes = {\n  children: PropTypes.node,\n};\n\nexport const Handle = styled(Slider)`\n  top: 6px;\n  bottom: 6px;\n  width: 6px;\n  margin-left: -3px;\n  border-radius: 6px;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  box-shadow:\n    0px 1px 2px rgba(60, 64, 67, 0.3),\n    0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n  cursor: col-resize;\n\n  &:focus {\n    border-color: ${({ theme }) => theme.colors.border.focus};\n  }\n\n  &:focus-visible {\n    outline: none !important;\n  }\n`;\n\nconst SVG = styled.svg`\n  position: absolute;\n  top: -1px;\n`;\n\nexport const ButtonWrapper = styled.div`\n  flex-grow: 1;\n  flex-basis: 100px;\n  display: flex;\n  justify-content: ${({ isStart }) => (isStart ? 'flex-end' : 'flex-start')};\n`;\n\nexport function Scrim({ width, isLeftAligned = false }) {\n  const floatStyle = isLeftAligned ? { left: '-1px' } : { right: '-1px' };\n  // These paths appear to be a bit magic, but are exactly what's required to draw the\n  // desired shape, which includes negative border radii and thus cannot be done in CSS only\n  const path = isLeftAligned\n    ? `M 4 0 h ${width} a 4 4 0 0 0 -4 4 v 28 a 4 4 0 0 0 4 4 h -${width} a 4 4 0 0 1 -4 -4 v -28 a 4 4 0 0 1 4 -4 Z`\n    : `M 0 0 h ${width} a 4 4 0 0 1 4 4 v 28 a 4 4 0 0 1 -4 4 h -${width} a 4 4 0 0 0 4 -4 v -28 a 4 4 0 0 0 -4 -4 Z`;\n\n  return (\n    <SVG\n      style={{ width: `${width + 4}px`, ...floatStyle }}\n      viewBox={`0 0 ${width + 4} 36`}\n    >\n      <path stroke=\"transparent\" fill=\"black\" fillOpacity=\"0.5\" d={path} />\n    </SVG>\n  );\n}\n\nScrim.propTypes = {\n  width: PropTypes.number.isRequired,\n  isLeftAligned: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/useRailBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { RAIL_HEIGHT } from './constants';\nimport generateVideoStrip from './generateVideoStrip';\n\nfunction useRailBackground(isReady, videoData, railWidth) {\n  const [railBackgroundImage, setRailBackgroundImage] = useState(null);\n  useEffect(() => {\n    if (!isReady) {\n      return;\n    }\n    const { element, resource } = videoData;\n    generateVideoStrip(element, resource, railWidth, RAIL_HEIGHT).then(\n      setRailBackgroundImage\n    );\n  }, [isReady, videoData, railWidth]);\n\n  return railBackgroundImage;\n}\n\nexport default useRailBackground;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/useVideoNode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useEffect,\n  useState,\n  useCallback,\n  useMemo,\n  useRef,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { MEDIA_VIDEO_MINIMUM_DURATION } from '../../constants';\nimport { noop } from '../../utils/noop';\n\nfunction useVideoNode(videoData) {\n  const [currentTime, setCurrentTime] = useState(null);\n  const [startOffset, rawSetStartOffset] = useState(null);\n  const [originalStartOffset, setOriginalStartOffset] = useState(null);\n  const [endOffset, rawSetEndOffset] = useState(null);\n  const [originalEndOffset, setOriginalEndOffset] = useState(null);\n  const [maxOffset, setMaxOffset] = useState(null);\n  const [videoNode, setVideoNode] = useState(null);\n  const [isDraggingHandles, setIsDraggingHandles] = useState(false);\n  // Video plays by default.\n  const isPausedTrackerRef = useRef(false);\n\n  useEffect(() => {\n    if (!videoNode) {\n      return;\n    }\n    // If the video has been paused manually, skip playing.\n    if (isPausedTrackerRef.current) {\n      return;\n    }\n    if (isDraggingHandles) {\n      videoNode.pause();\n    } else {\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      videoNode.currentTime = startOffset / 1000;\n      videoNode.play().catch(noop);\n    }\n  }, [videoNode, isDraggingHandles, startOffset]);\n\n  const paused = videoNode ? videoNode.paused : null;\n  useEffect(() => {\n    // Don't change manual tracker while dragging.\n    if (isDraggingHandles) {\n      return;\n    }\n    // Update the tracker when the pause state changes while not dragging.\n    isPausedTrackerRef.current = paused;\n  }, [paused, isDraggingHandles]);\n\n  useEffect(() => {\n    if (!videoData) {\n      // Reset all the things\n      rawSetStartOffset(null);\n      setOriginalStartOffset(null);\n      setCurrentTime(null);\n      rawSetEndOffset(null);\n      setOriginalEndOffset(null);\n      setMaxOffset(null);\n    }\n  }, [videoData]);\n\n  useEffect(() => {\n    if (!videoNode || !videoData) {\n      return undefined;\n    }\n\n    function restart(at) {\n      videoNode.currentTime = at / 1000;\n      videoNode.play().catch(noop);\n    }\n\n    function onLoadedMetadata(evt) {\n      if (!isFinite(evt.target.duration)) {\n        // Keep waiting\n        return;\n      }\n      const duration = Math.floor(evt.target.duration * 1000);\n      rawSetStartOffset(videoData.start);\n      setOriginalStartOffset(videoData.start);\n      setCurrentTime(videoData.start);\n      rawSetEndOffset(videoData.end ?? duration);\n      setOriginalEndOffset(videoData.end ?? duration);\n      setMaxOffset(duration);\n      restart(videoData.start);\n    }\n    function onTimeUpdate(evt) {\n      if (!endOffset) {\n        return;\n      }\n      const currentOffset = Math.floor(evt.target.currentTime * 1000);\n      setCurrentTime(Math.min(currentOffset, endOffset));\n      // If we've reached the end of the video, start again unless the user has paused the video.\n      if (currentOffset > endOffset && !isPausedTrackerRef.current) {\n        restart(startOffset);\n      }\n    }\n\n    // We might already have metadata, if so invoke the event handler directly.\n    // Note that on first playback before completion, duration is Infinite, so\n    // so we need to wait until it isn't anymore.\n    if (isFinite(videoNode.duration) && startOffset === null) {\n      onLoadedMetadata({ target: videoNode });\n    } else if (!isFinite(videoNode.duration)) {\n      // Video is a blob of unknown length, seek to infinity and wait until it's ready\n      // @see https://crbug.com/642012\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      videoNode.currentTime = Number.MAX_SAFE_INTEGER;\n      videoNode.addEventListener('timeupdate', onLoadedMetadata);\n    } else {\n      // Video hasn't loaded yet, wait for that\n      videoNode.addEventListener('loadedmetadata', onLoadedMetadata);\n    }\n\n    // We only start scheduling the restart listener once we have the end offset\n    if (endOffset) {\n      videoNode.addEventListener('timeupdate', onTimeUpdate);\n    }\n\n    return () => {\n      videoNode.removeEventListener('timeupdate', onTimeUpdate);\n      videoNode.removeEventListener('timeupdate', onLoadedMetadata);\n      videoNode.removeEventListener('loadedmetadata', onLoadedMetadata);\n    };\n  }, [startOffset, endOffset, videoData, videoNode]);\n\n  const setStartOffset = useCallback(\n    (offset) => {\n      // Start offset must be at least this smaller than end offset\n      offset = Math.min(endOffset - MEDIA_VIDEO_MINIMUM_DURATION, offset);\n      offset = Math.max(0, offset);\n      rawSetStartOffset(offset);\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      videoNode.currentTime = offset / 1000;\n    },\n    [videoNode, endOffset]\n  );\n\n  const setEndOffset = useCallback(\n    (offset) => {\n      // End offset must be at least this larger than start offset\n      offset = Math.max(startOffset + MEDIA_VIDEO_MINIMUM_DURATION, offset);\n      offset = Math.min(maxOffset, offset);\n      rawSetEndOffset(offset);\n      // eslint-disable-next-line react-hooks/immutability -- FIXME\n      videoNode.currentTime = offset / 1000;\n    },\n    [videoNode, startOffset, maxOffset]\n  );\n\n  const hasChanged = useMemo(\n    () =>\n      startOffset !== originalStartOffset || endOffset !== originalEndOffset,\n    [startOffset, originalStartOffset, endOffset, originalEndOffset]\n  );\n\n  return {\n    hasChanged,\n    currentTime,\n    startOffset,\n    endOffset,\n    maxOffset,\n    videoNode,\n    setStartOffset,\n    setEndOffset,\n    setVideoNode,\n    setIsDraggingHandles,\n  };\n}\n\nexport default useVideoNode;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/useVideoTrim.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport VideoTrimContext from './videoTrimContext';\n\nfunction useVideoTrim(selector) {\n  return useContextSelector(VideoTrimContext, selector ?? identity);\n}\n\nexport default useVideoTrim;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/useVideoTrimMode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { getMsFromHMS } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useCanvas, useStory, useAPI, useLocalMedia } from '../../app';\nimport useFFmpeg from '../../app/media/utils/useFFmpeg';\n\nfunction useVideoTrimMode() {\n  const { isEditing, isTrimMode, setEditingElementWithState, clearEditing } =\n    useCanvas(\n      ({\n        state: { isEditing, editingElementState: { isTrimMode } = {} },\n        actions: { setEditingElementWithState, clearEditing },\n      }) => ({\n        isEditing,\n        isTrimMode,\n        setEditingElementWithState,\n        clearEditing,\n      })\n    );\n  const { selectedElement, selectedId, selectedResource, isVideo } = useStory(\n    ({ state: { selectedElements } }) => {\n      const selectedElement =\n        selectedElements.length === 1 ? selectedElements[0] : null;\n      return {\n        selectedElement,\n        selectedId: selectedElement ? selectedElement?.id : null,\n        selectedResource: selectedElement?.resource || {},\n        isVideo: selectedElement?.type === 'video',\n      };\n    }\n  );\n\n  const {\n    actions: { getMediaById },\n  } = useAPI();\n  const [videoData, setVideoData] = useState(null);\n\n  const { isCurrentResourceUploading } = useLocalMedia(\n    ({ state: { isCurrentResourceUploading } }) => ({\n      isCurrentResourceUploading,\n    })\n  );\n\n  const getVideoData = useCallback(() => {\n    const { trimData } = selectedResource;\n\n    const defaultVideoData = {\n      element: selectedElement,\n      resource: selectedResource,\n      start: 0,\n      end: null,\n    };\n\n    if (getMediaById && trimData?.original) {\n      // First clear any existing data\n      setVideoData(null);\n      // Load correct video resource\n      getMediaById(trimData.original)\n        .then(\n          // If exists, use as resource with offsets\n          (originalResource) => ({\n            element: selectedElement,\n            resource: originalResource,\n            start: getMsFromHMS(trimData.start),\n            end: getMsFromHMS(trimData.end),\n          }),\n          // If load fails, pretend there's no original\n          () => defaultVideoData\n        )\n        // Regardless, set resulting data as video data\n        .then((data) => setVideoData(data));\n    } else {\n      setVideoData(defaultVideoData);\n    }\n  }, [getMediaById, selectedElement, selectedResource]);\n\n  const toggleTrimMode = useCallback(() => {\n    if (isEditing) {\n      clearEditing();\n    } else if (selectedId) {\n      setEditingElementWithState(selectedId, {\n        isTrimMode: true,\n        hasEditMenu: true,\n        showOverflow: false,\n      });\n\n      getVideoData();\n    }\n    trackEvent('video_trim_mode_toggled', {\n      status: isEditing ? 'closed' : 'open',\n    });\n  }, [\n    isEditing,\n    clearEditing,\n    setEditingElementWithState,\n    selectedId,\n    getVideoData,\n  ]);\n\n  const { isTranscodingEnabled } = useFFmpeg();\n\n  const hasTrimMode = useMemo(() => {\n    if (!isVideo) {\n      return false;\n    }\n\n    return (\n      isTranscodingEnabled &&\n      !selectedResource.isExternal &&\n      !isCurrentResourceUploading(selectedResource.id)\n    );\n  }, [\n    isVideo,\n    selectedResource,\n    isTranscodingEnabled,\n    isCurrentResourceUploading,\n  ]);\n\n  return {\n    isTrimMode: Boolean(isEditing && isTrimMode),\n    hasTrimMode,\n    toggleTrimMode,\n    videoData,\n  };\n}\n\nexport default useVideoTrimMode;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/videoTrimContext.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nconst VideoTrimContext = createContext({ state: {}, actions: {} });\n\nexport default VideoTrimContext;\n"
  },
  {
    "path": "packages/story-editor/src/components/videoTrim/videoTrimmer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  useRef,\n  useCallback,\n  useDebouncedCallback,\n} from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n} from '@googleforcreators/design-system';\nimport { getVideoLengthDisplay } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport useLayout from '../../app/layout/useLayout';\nimport useFocusTrapping from '../../utils/useFocusTrapping';\nimport useVideoTrim from './useVideoTrim';\nimport useRailBackground from './useRailBackground';\nimport CurrentTime from './currentTime';\nimport {\n  Menu,\n  RailWrapper,\n  Rail,\n  Duration,\n  Handle,\n  Scrim,\n  ButtonWrapper,\n} from './trimmerComponents';\n\nconst BUTTON_SPACE = 130;\n\nfunction VideoTrimmer() {\n  const {\n    startOffset,\n    endOffset,\n    maxOffset,\n    setStartOffset,\n    setEndOffset,\n    hasChanged,\n    performTrim,\n    setIsDraggingHandles,\n    toggleTrimMode,\n    videoData,\n  } = useVideoTrim(\n    ({\n      state: { startOffset, endOffset, maxOffset, hasChanged, videoData },\n      actions: {\n        setStartOffset,\n        setEndOffset,\n        performTrim,\n        toggleTrimMode,\n        setIsDraggingHandles,\n      },\n    }) => ({\n      startOffset,\n      endOffset,\n      maxOffset,\n      setStartOffset,\n      setEndOffset,\n      hasChanged,\n      performTrim,\n      setIsDraggingHandles,\n      toggleTrimMode,\n      videoData,\n    })\n  );\n  const { workspaceWidth, pageWidth } = useLayout(\n    ({ state: { workspaceWidth, pageWidth } }) => ({\n      workspaceWidth,\n      pageWidth,\n    })\n  );\n\n  const debouncedNudge = useDebouncedCallback(\n    () => setIsDraggingHandles(false),\n    1000\n  );\n\n  const menu = useRef(null);\n\n  // Keep focus trapped within the menu\n  useFocusTrapping({ ref: menu });\n\n  // Auto-focus the cancel button on mount\n  const setCancelRef = useCallback((node) => {\n    if (node) {\n      node.focus();\n    }\n  }, []);\n\n  const railWidth = Math.min(pageWidth, workspaceWidth - 2 * BUTTON_SPACE);\n\n  const isReady = pageWidth && maxOffset && videoData;\n\n  const railBackgroundImage = useRailBackground(isReady, videoData, railWidth);\n\n  const menuProps = {\n    ref: menu,\n    'aria-label': __('Video trimmer', 'web-stories'),\n  };\n\n  if (!isReady) {\n    // We still need a reffed element, or the focus trap will break,\n    // so just return an empty element\n    return <Menu {...menuProps} />;\n  }\n\n  const sliderProps = {\n    min: 0,\n    max: maxOffset,\n    step: 100,\n    minorStep: 10,\n    onPointerDown: () => setIsDraggingHandles(true),\n    onPointerUp: () => setIsDraggingHandles(false),\n    onNudge: () => {\n      setIsDraggingHandles(true);\n      debouncedNudge();\n    },\n  };\n\n  return (\n    <Menu {...menuProps}>\n      <ButtonWrapper isStart>\n        <Button\n          variant={ButtonVariant.Rectangle}\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          onClick={toggleTrimMode}\n          ref={setCancelRef}\n        >\n          {__('Cancel', 'web-stories')}\n        </Button>\n      </ButtonWrapper>\n      <RailWrapper>\n        <Rail\n          width={railWidth}\n          style={{\n            backgroundImage: railBackgroundImage\n              ? `url(${railBackgroundImage})`\n              : undefined,\n          }}\n        >\n          <Scrim isLeftAligned width={(startOffset / maxOffset) * railWidth} />\n          <Scrim width={((maxOffset - endOffset) / maxOffset) * railWidth} />\n          <CurrentTime railWidth={railWidth} {...sliderProps} />\n          <Handle\n            railWidth={railWidth}\n            value={startOffset}\n            aria-label={__('Start offset', 'web-stories')}\n            onChange={(val) => setStartOffset(val)}\n            {...sliderProps}\n          />\n          <Handle\n            railWidth={railWidth}\n            value={endOffset}\n            aria-label={__('End offset', 'web-stories')}\n            onChange={(val) => setEndOffset(val)}\n            {...sliderProps}\n          />\n        </Rail>\n        <Duration>\n          {getVideoLengthDisplay(Math.ceil((endOffset - startOffset) / 1000))}\n        </Duration>\n      </RailWrapper>\n      <ButtonWrapper>\n        <Button\n          variant={ButtonVariant.Rectangle}\n          type={ButtonType.Primary}\n          size={ButtonSize.Small}\n          onClick={performTrim}\n          disabled={!hasChanged}\n        >\n          {__('Trim', 'web-stories')}\n        </Button>\n      </ButtonWrapper>\n    </Menu>\n  );\n}\n\nexport default VideoTrimmer;\n"
  },
  {
    "path": "packages/story-editor/src/components/workspace/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { RichTextProvider } from '@googleforcreators/rich-text';\n\n/**\n * Internal dependencies\n */\nimport Sidebar from '../sidebar';\nimport Canvas from '../canvas';\nimport { VideoTrimProvider } from '../videoTrim';\nimport ErrorBoundary from '../errorBoundary';\nimport { useCanvas } from '../../app';\nimport { CanvasArea, SidebarArea } from './layout';\n\nfunction Workspace({ header, footer }) {\n  const { editingElementState } = useCanvas((state) => ({\n    editingElementState: state.state.editingElementState,\n  }));\n\n  return (\n    <VideoTrimProvider>\n      <RichTextProvider editingState={editingElementState}>\n        <SidebarArea>\n          <ErrorBoundary>\n            <Sidebar />\n          </ErrorBoundary>\n        </SidebarArea>\n        <CanvasArea>\n          <ErrorBoundary>\n            <Canvas header={header} footer={footer} />\n          </ErrorBoundary>\n        </CanvasArea>\n      </RichTextProvider>\n    </VideoTrimProvider>\n  );\n}\n\nWorkspace.propTypes = {\n  header: PropTypes.node,\n  footer: PropTypes.object,\n};\n\nexport default Workspace;\n"
  },
  {
    "path": "packages/story-editor/src/components/workspace/layout.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\n\nconst Area = styled.div`\n  grid-area: ${({ area }) => area};\n  position: relative;\n  overflow: hidden;\n  z-index: ${({ zIndex }) => zIndex};\n`;\n\nconst CanvasArea = styled(Area).attrs({ area: 'canv', zIndex: 1 })``;\nconst SidebarArea = styled(Area).attrs({ area: 'sidebar', zIndex: 2 })``;\n\nexport { CanvasArea, SidebarArea };\n"
  },
  {
    "path": "packages/story-editor/src/constants/audioSticker.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const AUDIO_STICKER_WIDTH_PRESETS = {\n  SMALL: 120,\n  LARGE: 180,\n};\n\nexport const AUDIO_STICKER_ASPECT_RATIOS = {\n  'headphone-cat': 1.24,\n  'tape-player': 1.18,\n  'loud-speaker': 1,\n  'audio-cloud': 1.54,\n};\n\nexport const AUDIO_STICKER_DEFAULT_PRESET = {\n  x: 100,\n  y: 100,\n  width:\n    AUDIO_STICKER_WIDTH_PRESETS.SMALL *\n    AUDIO_STICKER_ASPECT_RATIOS['headphone-cat'],\n  height: AUDIO_STICKER_WIDTH_PRESETS.SMALL,\n  sticker: 'headphone-cat',\n  size: 'small',\n};\n"
  },
  {
    "path": "packages/story-editor/src/constants/fonts.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { _x } from '@googleforcreators/i18n';\n\nexport const FONT_WEIGHT_NAMES = {\n  100: _x('Thin', 'font weight', 'web-stories'),\n  200: _x('Extra-light', 'font weight', 'web-stories'),\n  300: _x('Light', 'font weight', 'web-stories'),\n  400: _x('Regular', 'font weight', 'web-stories'),\n  500: _x('Medium', 'font weight', 'web-stories'),\n  600: _x('Semi-bold', 'font weight', 'web-stories'),\n  700: _x('Bold', 'font weight', 'web-stories'),\n  800: _x('Extra-bold', 'font weight', 'web-stories'),\n  900: _x('Black', 'font weight', 'web-stories'),\n};\n"
  },
  {
    "path": "packages/story-editor/src/constants/headings.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const HEADING_LEVELS = {\n  h1: __('Heading 1', 'web-stories'),\n  h2: __('Heading 2', 'web-stories'),\n  h3: __('Heading 3', 'web-stories'),\n  p: __('Paragraph', 'web-stories'),\n};\n"
  },
  {
    "path": "packages/story-editor/src/constants/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './fonts';\nexport * from './media';\nexport * from './multipleValue';\nexport * from './performanceTrackingEvents';\nexport * from './headings';\nexport * from './audioSticker';\n\nexport const ADMIN_TOOLBAR_HEIGHT = 32;\nexport const HEADER_HEIGHT = 64;\nexport const HEADER_GAP = 52;\nexport const CANVAS_MIN_WIDTH = 570;\nexport const SIDEBAR_WIDTH = 360;\nexport const PAGE_NAV_PADDING = 60;\nexport const PAGE_NAV_BUTTON_SIZE = 40;\nexport const PAGE_NAV_WIDTH = PAGE_NAV_PADDING + PAGE_NAV_BUTTON_SIZE;\nexport const FLOATING_MENU_DISTANCE = 10;\nexport const MAX_PRODUCTS_PER_PAGE = 6;\n\nexport enum ZoomSetting {\n  Fill = 'FILL',\n  Fit = 'FIT',\n  Fixed = 'FIXED',\n}\n\nexport enum CarouselState {\n  Open = 'OPEN',\n  Opening = 'OPENING',\n  Closed = 'CLOSED',\n  Closing = 'CLOSING',\n}\n\nexport const CAROUSEL_TRANSITION_DURATION = 300;\n\nexport const PAGE_WIDTH_FACTOR = 12;\nexport const MAX_EXTRA_PAGES = 4;\n\nexport const DESIGN_SPACE_MARGIN = 48;\n\nexport const TEXT_SET_SIZE = 150;\n\nexport enum LayerDirection {\n  Front = 'FRONT',\n  Back = 'BACK',\n  Forward = 'FORWARD',\n  Backward = 'BACKWARD',\n}\n\nexport const FONT_WEIGHT = {\n  NORMAL: 400,\n  MEDIUM: 500,\n  BOLD: 700,\n};\n\nexport const HIDDEN_PADDING = {\n  horizontal: 8,\n  vertical: 4,\n};\n\nexport const SAVED_COLOR_SIZE = 32;\nexport const SAVED_STYLE_HEIGHT = 64;\n\nexport const OUTLINK_THEME = {\n  DARK: 'dark',\n  LIGHT: 'light',\n  CUSTOM: 'custom',\n};\n\nexport const PRESET_TYPES = {\n  STYLE: 'style',\n  COLOR: 'colors',\n};\n\nexport const STABLE_ARRAY = [];\n"
  },
  {
    "path": "packages/story-editor/src/constants/media.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst GB_IN_BYTES = 1024 * 1024 * 1024;\n\nexport const MEDIA_TRANSCODING_MAX_FILE_SIZE = 2 * GB_IN_BYTES;\n\nexport const MEDIA_POSTER_IMAGE_FILE_TYPE = 'jpeg';\nexport const MEDIA_POSTER_IMAGE_MIME_TYPE = 'image/jpeg';\n\nexport const MEDIA_TRANSCODED_MIME_TYPE = 'video/mp4';\nexport const MEDIA_TRANSCODED_FILE_TYPE = 'mp4';\n\n// Minimum duration time in milliseconds for a video\nexport const MEDIA_VIDEO_MINIMUM_DURATION = 100;\n\nexport const MEDIA_VIDEO_DIMENSIONS_THRESHOLD = {\n  HEIGHT: 720,\n  WIDTH: 1280,\n};\n\nexport const MEDIA_VIDEO_FILE_SIZE_THRESHOLD = 4_000_000;\n\n// This could eventually also include WebM/VP9\nexport const MEDIA_MIME_TYPES_OPTIMIZED_VIDEOS = ['video/mp4'];\n\nexport const MEDIA_RECOMMENDED_MAX_VIDEO_DURATION = 15;\n\nexport const MEDIA_RECOMMENDED_MIN_VIDEO_FPS = 24;\n"
  },
  {
    "path": "packages/story-editor/src/constants/multipleValue.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const MULTIPLE_VALUE = '((MULTIPLE))';\n\nexport const MULTIPLE_DISPLAY_VALUE = __('Mixed', 'web-stories');\n"
  },
  {
    "path": "packages/story-editor/src/constants/performanceTrackingEvents.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const TRACKING_EVENTS = {\n  PAGE_NAVIGATION: {\n    category: 'page',\n    label: 'arrow_navigate',\n  },\n  PAGE_PREVIEW_CLICK: {\n    category: 'page',\n    label: 'carousel_navigate',\n  },\n  PAGE_ADD: {\n    category: 'page',\n    label: 'add_new',\n  },\n  PAGE_DELETE: {\n    category: 'page',\n    label: 'delete',\n  },\n  SELECT_ELEMENT: {\n    category: 'select_element',\n  },\n  LIBRARY_PANEL_CLICK: {\n    category: 'library_panel',\n  },\n  DESIGN_PANEL_CLICK: {\n    category: 'design_panel',\n  },\n  INSERT_ELEMENT: {\n    category: 'insert_element',\n  },\n  DELETE_ELEMENT: {\n    category: 'delete_element',\n  },\n  SET_BACKGROUND_MEDIA: {\n    category: 'background',\n    label: 'set_media_as_bg',\n  },\n};\n"
  },
  {
    "path": "packages/story-editor/src/constants/zIndex.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Bring element in front of story details modal\nexport const Z_INDEX_STORY_DETAILS = 10;\n\n// Floating menu lays on top of side menu\nexport const Z_INDEX_CANVAS_SIDE_MENU = 3;\n\n// Floating element menu (a context menu) should be behind other popups\nexport const Z_INDEX_FLOATING_MENU = 4;\n\n// Edit Layer holds footer, popups in footer need to be in front of floating menu\nexport const Z_INDEX_EDIT_LAYER = 3;\n\n// Nav layer doesn't have its own stacking context, so we apply this\n// to the header and footer to be in the same stacking context as\n// floating menu layer & edit layer\nexport const Z_INDEX_NAV_LAYER = 5;\n\n// Media recording mode should overlay most things, but not the side menu.\nexport const Z_INDEX_RECORDING_MODE = 6;\nexport const Z_INDEX_CANVAS_SIDE_MENU_RECORDING_MODE = 7;\n\n// idk why these are defined in here. they're used throughout parts of the\n// codebase, but they're not in the same stacking as the other layers in this\n// file. Keeping them in here to avoid regressions in the codebase, but\n// we should look into only storing z-index constants that apply to the same\n// stacking context\nexport const Z_INDEX_FOOTER = 3;\n\n// The Grid View component is a modal, the Slider that is used inside\n// needs to be pulled on top.\nexport const Z_INDEX_GRID_VIEW_SLIDER = 11;\n\n// In PublishTime, the time picker's tooltip's z-index needs to be higher than\n// the z-index of the date picker popup itself.\nexport const Z_INDEX_TIME_PICKER_TOOLTIP = 11;\n\n// In the library, the action button has to be on top of the other layers.\nexport const Z_INDEX_LIBRARY_ACTION_BUTTON = 20;\n"
  },
  {
    "path": "packages/story-editor/src/dataUtils/formattedTemplatesArray.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// @todo Temporarily copied here to resolve dependencies. Move this file to some other package.\n\n/**\n * External dependencies\n */\nimport { toUTCDate } from '@googleforcreators/date';\n\nconst formattedTemplatesArray = [\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 10,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID1',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        animations: [],\n        type: 'page',\n        id: 'ID1',\n        pageTemplateType: 'cover',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '4e5d3a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID3',\n        pageTemplateType: 'quote',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID4',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID4',\n        pageTemplateType: 'editorial',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID5',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID5',\n        pageTemplateType: 'list',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID6',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID6',\n        pageTemplateType: 'table',\n      },\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: 'ID7',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: 'ID7',\n        pageTemplateType: 'steps',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n        type: 'cover',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n        type: 'section',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n        type: 'quote',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n        type: 'editorial',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n        type: 'list',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n        type: 'table',\n      },\n      {\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n        type: 'steps',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Cooking',\n    slug: 'cooking',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 9,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'cover',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n        type: 'cover',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'DIY',\n    slug: 'diy',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 3,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n        type: 'section',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Entertainment',\n    slug: 'entertainment',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 4,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'editorial',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n        type: 'editorial',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Fashion',\n    slug: 'fashion',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 5,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'steps',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n        type: 'steps',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Fitness',\n    slug: 'fitness',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 6,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'cover',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-1.png',\n        type: 'cover',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Travel',\n    slug: 'travel',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 7,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'section',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-3.png',\n        type: 'section',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    title: 'Wellbeing',\n    slug: 'wellbeing',\n  },\n  {\n    version: 2,\n    createdBy: 'Google',\n    description:\n      'Maecenas ultrices tortor nibh, eu consequat magna maximus non. Quisque nec tellus lacus.',\n    id: 8,\n    isLocal: false,\n    modified: toUTCDate('04-04-2020'),\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundColor: {\n              color: {\n                r: 233,\n                g: 213,\n                b: 197,\n              },\n            },\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: 'ef056bde-fdc3-4f71-809a-e69c62ae914d',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '51e3dfb3-fe95-4132-ade1-cd226982cf68',\n            x: 65,\n            y: 28,\n            content:\n              '<span style=\"color: #fff; letter-spacing: 0.09em\">I</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">WOKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">UP</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">LIKE</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">THIS</span>\\n<span style=\"color: #fff; letter-spacing: 0.09em\">”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Bungee Shade',\n              service: 'fonts.google.com',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n            },\n            fontSize: 84,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.1,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 56,\n            y: 28,\n            width: 330,\n            height: 552,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '53004538-6bca-4ac6-810e-18bd81e84276',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\">I\\nWOKE\\nUP\\nLIKE\\nTHIS\\n”</span>',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Chivo',\n              service: 'fonts.google.com',\n              fallbacks: ['sans-serif'],\n              weights: [300, 400, 700, 900],\n              styles: ['italic', 'regular'],\n              variants: [\n                [0, 300],\n                [0, 400],\n                [0, 700],\n                [0, 900],\n                [1, 300],\n                [1, 400],\n                [1, 700],\n                [1, 900],\n              ],\n            },\n            fontSize: 40,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.3,\n            textAlign: 'center',\n            padding: {\n              vertical: 0,\n              horizontal: 0,\n              locked: true,\n            },\n            x: 110,\n            y: 580,\n            width: 202,\n            height: 52,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            type: 'text',\n            id: '96e93ceb-accb-4c38-b603-7d616174e5d3',\n            content:\n              '<span style=\"color: rgba(40, 41, 43, 1)\"><span style=\"font-weight: 900\">Beyoncé</span></span>',\n          },\n        ],\n        type: 'page',\n        id: '65359a38-f1fa-4048-9b99-9415147b74d3',\n        pageTemplateType: 'editorial',\n      },\n    ],\n    postersByPage: [\n      {\n        png: 'http://localhost:9876/__static__/featured-media-2.png',\n        type: 'editorial',\n      },\n    ],\n    status: 'template',\n    tags: ['Delicious', 'Baker', 'Cook'],\n    colors: [\n      { label: 'Pink', color: '#f3d9e1' },\n      { label: 'Green', color: '#d8ddcc' },\n      { label: 'Black', color: '#28292b' },\n      { label: 'White', color: '#fff' },\n      { label: 'Brown', color: '#eadfd6' },\n    ],\n    slug: 'beauty',\n    title: 'Beauty',\n  },\n];\n\nexport default formattedTemplatesArray;\n"
  },
  {
    "path": "packages/story-editor/src/getDefaultConfig.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst getDefaultConfig = () => ({\n  locale: {\n    locale: 'en-US',\n    dateFormat: 'F j, Y',\n    timeFormat: 'g:i a',\n    gmtOffset: '0',\n    timezone: '',\n    months: [\n      'January',\n      'February',\n      'March',\n      'April',\n      'May',\n      'June',\n      'July',\n      'August',\n      'September',\n      'October',\n      'November',\n      'December',\n    ],\n    monthsShort: [\n      'Jan',\n      'Feb',\n      'Mar',\n      'Apr',\n      'May',\n      'Jun',\n      'Jul',\n      'Aug',\n      'Sep',\n      'Oct',\n      'Nov',\n      'Dec',\n    ],\n    weekdays: [\n      'Sunday',\n      'Monday',\n      'Tuesday',\n      'Wednesday',\n      'Thursday',\n      'Friday',\n      'Saturday',\n    ],\n    weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n    weekdaysInitials: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n    weekStartsOn: 1,\n  },\n  allowedMimeTypes: {\n    audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n    image: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'],\n    caption: ['text/vtt'],\n    vector: ['image/svg+xml'],\n    video: ['video/mp4', 'video/webm'],\n  },\n  isRTL: false,\n  storyId: 1,\n  cdnURL: 'https://wp.stories.google/static/main/',\n  maxUpload: 314572800,\n  capabilities: {\n    hasUploadMediaAction: false,\n    canManageSettings: false,\n  },\n  metadata: {\n    publisher: '',\n  },\n  canViewDefaultTemplates: true,\n  showMedia3p: true,\n  encodeMarkup: true,\n  ffmpegCoreUrl:\n    'https://wp.stories.google/static/main/js/@ffmpeg/core@0.11.0/dist/ffmpeg-core.js',\n  apiCallbacks: {},\n  MediaUpload: () => null,\n  styleConstants: {\n    topOffset: 0,\n    leftOffset: 0,\n  },\n});\n\nexport default getDefaultConfig;\n"
  },
  {
    "path": "packages/story-editor/src/icons/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as TenorLogoFull } from './tenor_logo_white.svg';\nexport { default as UnsplashLogoFull } from './unsplash_logo_full.svg';\n"
  },
  {
    "path": "packages/story-editor/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nexport { default as Dialog } from './components/dialog';\n\nexport { default as StoryEditor } from './storyEditor';\n\nexport * from './components/previewPage';\nexport * from './app/config';\nexport * from './app/story';\nexport * from './app/api';\nexport * from './app/media';\nexport * from './app/history';\nexport * from './components/header';\nexport * from './components/panels/document';\nexport * from './components/form';\nexport * from './components/panels/panel';\nexport * from './components/panels/shared';\nexport * from './components/checklist';\nexport { default as FontPicker } from './components/fontPicker';\nexport { focusStyle } from './components/panels/shared/styles';\nexport * from './components/checklistCard';\nexport * from './app/currentUser';\n\nexport { default as getStoryPropsToSave } from './app/story/utils/getStoryPropsToSave';\nexport { default as useRefreshPostEditURL } from './utils/useRefreshPostEditURL';\nexport { default as FontContext } from './app/font/context';\nexport { default as useLoadFontFiles } from './app/font/actions/useLoadFontFiles';\nexport { StoryPropTypes } from './propTypes';\nexport { GlobalStyle, default as theme } from './theme'; // @todo To be refactored.\nexport { default as InterfaceSkeleton } from './components/layout';\nexport { default as Tooltip } from './components/tooltip';\nexport { default as useSidebar } from './components/sidebar/useSidebar';\nexport { default as SidebarContext } from './components/sidebar/context';\nexport { AutoSaveCheck } from './components/autoSaveCheck';\nexport { default as useIsUploadingToStory } from './utils/useIsUploadingToStory';\nexport { getInUseFontsForPages } from './utils/getInUseFonts';\nexport { states as highlightStates, useHighlights } from './app/highlights';\nexport { default as highlightStyles } from './app/highlights/styles';\nexport { ConfigProvider as EditorConfigProvider } from './app/config';\n"
  },
  {
    "path": "packages/story-editor/src/karma/copyAndPaste.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport useInsertElement from '../components/canvas/useInsertElement';\nimport { useStory } from '../app/story';\nimport { Fixture } from './fixture';\n\n/**\n * Takes an HTMLCollection and sequentially performs an\n * async action on each element in the collection.\n *\n * Call order of operations is based on the order of\n * the elements in the collection\n *\n * @param {HTMLCollection} htmlCollection - collection of html elements to perform operation on.\n * @param {(el: HTMLElement, i: number) => Promise<void>} op - async operation\n * @return {Promise<void>}\n */\nfunction sequencedForEach(htmlCollection, op) {\n  return new Promise((res) => {\n    Array.from(htmlCollection)\n      .map((htmlElement, i) => async () => {\n        await op(htmlElement, i);\n      })\n      // [p1, p2, p3, p4] -> promise.resolve().then(p1).then(p2).then(p3).then(p4)\n      .reduce((p, fn) => p.then(fn), Promise.resolve())\n      .then(res);\n  });\n}\n\n[\n  {\n    title: 'Foreground Copy & Paste',\n    action: async (fixture) => {\n      await fixture.events.clipboard.copy();\n      await fixture.events.clipboard.paste();\n    },\n  },\n  {\n    title: 'Duplicate',\n    action: async (fixture) => {\n      await fixture.events.keyboard.shortcut('mod+d');\n    },\n  },\n].forEach(({ title, action }) => {\n  describe(title, () => {\n    let fixture;\n    let element;\n\n    beforeEach(async () => {\n      fixture = new Fixture();\n      await fixture.render();\n      await fixture.collapseHelpCenter();\n\n      // Insert selected element to perform operations on.\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      element = await fixture.act(() =>\n        insertElement('text', {\n          x: 10,\n          y: 10,\n          width: 100,\n          height: 50,\n          content: 'Hello, Stories!',\n        })\n      );\n    });\n\n    afterEach(() => {\n      fixture.restore();\n    });\n\n    it('pastes copied element in a new location and selects it', async () => {\n      await action(fixture);\n      const currentPage = await fixture.renderHook(() =>\n        useStory(({ state }) => state.currentPage)\n      );\n\n      // get pasted element\n      // elements = [background, originalElement, pastedElement]\n      const newElements = currentPage.elements\n        .filter((el) => !el.isBackground)\n        .filter((el) => el.id !== element.id);\n      // only one element should have been added\n      expect(newElements.length).toEqual(1);\n\n      // see that the new element retains important properties\n      // and doesn't have the same position as original element\n      const newElement = newElements[0];\n      ['type', 'content', 'width', 'height'].forEach((key) =>\n        expect(newElement[key]).toEqual(element[key])\n      );\n      ['x', 'y'].forEach((key) =>\n        expect(newElement[key]).not.toEqual(element[key])\n      );\n\n      // see that new element gains selection\n      const selection = await fixture.renderHook(() =>\n        useStory(({ state }) => state.selectedElementIds)\n      );\n      expect(selection).toEqual([newElement.id]);\n    });\n\n    /* eslint-disable-next-line jasmine/no-disabled-tests --\n     * flakey tests.\n     * See https://github.com/googleforcreators/web-stories-wp/pull/6162\n     **/\n    xit('retains all foreground animations', async () => {\n      // open effect\n      await fixture.events.click(fixture.editor.sidebar.designTab);\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.animationSection\n      );\n      const effectChooserToggle =\n        fixture.editor.sidebar.designPanel.animation.effectChooser;\n      await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n      // see that effect chooser is open\n      const effectChooser = await fixture.screen.findByRole('list', {\n        name: /Available Animations To Select/,\n      });\n\n      // iterate through children with process\n      await sequencedForEach(\n        effectChooser.children,\n        async (effectButton, i) => {\n          // first button is `none` and doesn't apply animation\n          if (\n            i === 0 ||\n            effectButton.getAttribute('aria-disabled') === 'true'\n          ) {\n            return;\n          }\n          // apply animation to element\n          await fixture.events.click(effectButton, { clickCount: 1 });\n\n          // copy and paste animated element with Animations\n          const copied = await fixture.renderHook(() =>\n            useStory(({ state }) => ({\n              elements: state.selectedElements,\n              elementAnimations: state.selectedElementAnimations,\n            }))\n          );\n          expect(copied.elementAnimations.length).toEqual(1);\n          await action(fixture);\n          const pasted = await fixture.renderHook(() =>\n            useStory(({ state }) => ({\n              elements: state.selectedElements,\n              elementAnimations: state.selectedElementAnimations,\n            }))\n          );\n          expect(pasted.elementAnimations.length).toEqual(1);\n\n          // Copied and Pasted animations should share all attributes\n          // Except `id` & `targets`\n          const {\n            id: cId,\n            targets: cTargets,\n            ...cPersisted\n          } = copied.elementAnimations[0];\n          const {\n            id: pId,\n            targets: pTargets,\n            ...pPersisted\n          } = pasted.elementAnimations[0];\n          expect(cPersisted).toEqual(pPersisted);\n\n          // pasted animations should contain the newly pasted\n          // element's id as it's only target\n          const pastedElId = pasted.elements[0].id;\n          expect(pTargets).toEqual([pastedElId]);\n\n          // see that current page has new animation\n          const { animations, elements } = await fixture.renderHook(() =>\n            useStory(({ state }) => state.currentPage)\n          );\n\n          // 2 comes from background + initial copied element\n          expect(elements.length).toEqual(i + 2);\n          // 1 comes from original copied element animation\n          expect(animations.length).toEqual(i + 1);\n        }\n      );\n    });\n  });\n});\n\ndescribe('Background Copy & Paste', () => {\n  let fixture;\n\n  const goToNextPage = async () => {\n    const nextPageButton = fixture.screen.getByRole('button', {\n      name: /Next Page/,\n    });\n    await fixture.events.click(nextPageButton, { clickCount: 1 });\n  };\n\n  const goToPreviousPage = async () => {\n    const previousPageButton = fixture.screen.getByRole('button', {\n      name: /Previous Page/,\n    });\n    await fixture.events.click(previousPageButton, { clickCount: 1 });\n  };\n\n  const openEffectChooser = async () => {\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const effectChooserToggle =\n      fixture.editor.sidebar.designPanel.animation.effectChooser;\n    await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n  };\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    // #11321 adding/editing animations on the first page is disabled\n    // add a third page here to copy and paste between the second and third pages\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n\n    // Navigate back to previous page and add Background image\n    await goToPreviousPage();\n    const bgMedia = fixture.editor.library.media.item(0);\n    await fixture.events.mouse.clickOn(bgMedia, 20, 20);\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.sizePosition.setAsBackground\n    );\n\n    // we want to zoom in a little bit so background\n    // is big enough for all background animations.\n    // scale is between 100 -> 400\n    const backgroundElement = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[0])\n    );\n    const bgFrame = fixture.editor.canvas.framesLayer.frame(\n      backgroundElement.id\n    ).node;\n    // Click twice to enter edit mode\n    await fixture.events.click(bgFrame);\n    await fixture.events.click(bgFrame);\n    await waitFor(() => {\n      if (!fixture.editor.canvas.editLayer.sizeSlider) {\n        throw new Error('sizeSlider not ready');\n      }\n    });\n    const slider = fixture.editor.canvas.editLayer.sizeSlider;\n    await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n      moveRel(slider, 5, 5),\n      down(),\n      moveBy(50, 0, { steps: 4 }),\n      up(),\n    ]);\n    // Click just below the slider to exit edit mode\n    await fixture.events.mouse.clickOn(slider, 0, 20);\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('works for all background animations', async () => {\n    // open effect chooser\n    await openEffectChooser();\n\n    // see that effect chooser is open\n    const effectChooser = fixture.screen.getByRole('listbox', {\n      name: /Animation: Effect Chooser Option List Selector/,\n    });\n\n    // iterate through children with process\n    await sequencedForEach(effectChooser.children, async (_, i) => {\n      // need to regrab the button because we're opening\n      // and closing effect chooser causing karma ids to change\n      const effectButton = fixture.screen.getByRole('listbox', {\n        name: /Animation: Effect Chooser Option List Selector/,\n      }).children[i];\n\n      // first button is `none` and doesn't apply animation\n      if (i === 0 || effectButton.getAttribute('aria-disabled') === 'true') {\n        return;\n      }\n      // apply animation to element\n      await fixture.events.click(effectButton, { clickCount: 1 });\n\n      // copy background element with animation\n      const copied = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          elements: state.selectedElements,\n          elementAnimations: state.selectedElementAnimations,\n        }))\n      );\n      expect(copied.elementAnimations.length).toEqual(1);\n      await fixture.events.clipboard.copy();\n\n      // Go to third page\n      await goToNextPage();\n\n      // Paste background with animation to third page\n      await fixture.events.clipboard.paste();\n      const pasted = await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          elements: state.selectedElements,\n          elementAnimations: state.selectedElementAnimations,\n        }))\n      );\n      expect(pasted.elementAnimations.length).toEqual(1);\n\n      // Copied and Pasted animations should share all attributes\n      // except `id` & `targets`\n      const {\n        id: cId,\n        targets: cTargets,\n        ...cPersisted\n      } = copied.elementAnimations[0] || {};\n      const {\n        id: pId,\n        targets: pTargets,\n        ...pPersisted\n      } = pasted.elementAnimations[0] || {};\n\n      // animation properties are explicitly passed as of #6888\n      // https://github.com/googleforcreators/web-stories-wp/pull/6888/files#diff-e2509f6271734915fc6fb3d6b0fd1a78d6d34df81e215f0a79f2fce50586bb86R119\n      // so undefined properties are removed to check for object equality\n      Object.keys(cPersisted).forEach((key) =>\n        cPersisted[key] === undefined ? delete cPersisted[key] : {}\n      );\n      Object.keys(pPersisted).forEach((key) =>\n        pPersisted[key] === undefined ? delete pPersisted[key] : {}\n      );\n\n      expect(cPersisted).toEqual(pPersisted);\n\n      // pasted animations should contain the newly pasted\n      // element's id as it's only target\n      const pastedElId = pasted.elements[0].id;\n      expect(pTargets).toEqual([pastedElId]);\n\n      // see that current page has new animation\n      const { animations, elements } = await fixture.renderHook(() =>\n        useStory(({ state }) => state.currentPage)\n      );\n\n      // Pages should only contain background\n      expect(elements.length).toEqual(1);\n      // Pages should only contain background animation\n      expect(animations.length).toEqual(1);\n\n      // Go back to previous page to restart process\n      await goToPreviousPage();\n      // Select Background\n      const setSelectedById = await fixture.renderHook(() =>\n        useStory(({ actions }) => actions.setSelectedElementsById)\n      );\n      setSelectedById({ elementIds: [copied.elements[0].id] });\n      // reopen effect chooser\n      await openEffectChooser();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/duplicate.cuj.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport useInsertElement from '../components/canvas/useInsertElement';\nimport { useStory } from '../app/story';\nimport { Fixture } from './fixture';\n\ndescribe('Duplicate Page', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    // #11321 adding/editing animations on the first page is disabled\n    await fixture.events.click(fixture.editor.canvas.pageActions.addPage);\n    // Insert selected element to perform operations on.\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    await fixture.act(() =>\n      insertElement('text', {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        content: 'Hello, Stories!',\n      })\n    );\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should duplicate an animation', async () => {\n    const startPageIndex = await fixture.renderHook(() =>\n      useStory(({ state: { currentPageIndex } }) => currentPageIndex)\n    );\n    // open effect chooser\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.animationSection\n    );\n    const effectChooserToggle =\n      fixture.editor.sidebar.designPanel.animation.effectChooser;\n    await fixture.events.click(effectChooserToggle, { clickCount: 1 });\n\n    // animation\n    const animation = fixture.screen.getByRole('option', {\n      name: '\"Pulse\" Effect',\n    });\n\n    // apply animation to element\n    await fixture.events.click(animation, { clickCount: 1 });\n\n    // get original element\n    const { animations: originalAnimations, elements: originalElements } =\n      await fixture.renderHook(() =>\n        useStory(({ state }) => ({\n          animations: state.pages[startPageIndex].animations,\n          elements: state.currentPage.elements,\n        }))\n      );\n    expect(originalAnimations.length).toBe(1);\n\n    const {\n      delay: originalDelay,\n      duration: originalDuration,\n      type: originalType,\n      targets: originalTargets,\n    } = originalAnimations[0];\n\n    // Verify that animation is assigned to correct element\n    expect(originalTargets.length).toEqual(1);\n    expect(\n      originalElements.find((element) => element.id === originalTargets[0])\n    ).not.toBeUndefined();\n\n    // duplicate page\n    await fixture.events.click(\n      fixture.editor.canvas.pageActions.duplicatePage,\n      { clickCount: 1 }\n    );\n\n    // get the duplicated element\n    const { animations, elements } = await fixture.renderHook(() =>\n      useStory(({ state }) => ({\n        animations: state.pages[startPageIndex + 1].animations,\n        elements: state.pages[startPageIndex + 1].elements,\n      }))\n    );\n    expect(animations.length).toBe(1);\n\n    const { delay, duration, type, targets } = animations[0];\n\n    // Verify that animation values are identical\n    expect(delay).toBe(originalDelay);\n    expect(duration).toBe(originalDuration);\n    expect(type).toBe(originalType);\n\n    // Verify that animation is assigned to correct element\n    expect(targets.length).toEqual(1);\n    expect(\n      elements.find((element) => element.id === targets[0])\n    ).not.toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/audio-sticker/audioSticker.karma.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../../app';\nimport { Fixture } from '../../fixture';\n\nconst stickerTypes = [\n  ['headphone-cat', 'headphoneCat'],\n  ['tape-player', 'tapePlayer'],\n  ['loud-speaker', 'loudSpeaker'],\n  ['audio-cloud', 'audioCloud'],\n];\nconst stickerSizes = ['small', 'large'];\nconst stickerStyles = ['none', 'outline', 'dropshadow'];\n\ndescribe('Audio Sticker', () => {\n  let fixture;\n\n  async function clickCanvas() {\n    const focusContainer = fixture.screen.getByTestId('canvas-focus-container');\n    await fixture.events.click(focusContainer);\n  }\n\n  async function insertAudioSticker() {\n    await fixture.events.click(fixture.editor.sidebar.designTab);\n    await clickCanvas();\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.pageBackgroundAudio.uploadButton\n    );\n    const storyContext = await fixture.renderHook(() => useStory());\n\n    expect(\n      storyContext.state.currentPage.backgroundAudio.resource.src\n    ).not.toBeNull();\n\n    await fixture.events.click(\n      fixture.editor.canvas.quickActionMenu.insertAudioStickerButton\n    );\n  }\n\n  async function clickAudioStickerTypeButton(type) {\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.audioStickerType[type]\n    );\n  }\n\n  async function clickAudioStickerStyleButton(style) {\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.audioStickerStyle[style]\n    );\n  }\n\n  async function clickAudioStickerSizeButton(size) {\n    await fixture.events.click(\n      fixture.editor.sidebar.designPanel.audioStickerSize[size]\n    );\n  }\n\n  async function getSelectedAudioStickerElement() {\n    const element = await fixture.renderHook(() =>\n      useStory(({ state }) => state.currentPage.elements[1])\n    );\n    return element;\n  }\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    await fixture.showFloatingMenu();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should render', async () => {\n    await insertAudioSticker();\n    const selectedElement = await getSelectedAudioStickerElement();\n    expect(selectedElement.type).toBe('audioSticker');\n  });\n\n  describe('should update sticker type', () => {\n    beforeEach(async () => {\n      await insertAudioSticker();\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.audioStickerType.sectionHeading\n      );\n    });\n\n    for (const [stickerType, buttonName] of stickerTypes) {\n      it(`on pressing ${stickerType} button`, async () => {\n        await clickAudioStickerTypeButton(buttonName);\n        const selectedElement = await getSelectedAudioStickerElement();\n        expect(selectedElement.sticker).toBe(stickerType);\n      });\n    }\n  });\n\n  describe('should update sticker style', () => {\n    beforeEach(async () => {\n      await insertAudioSticker();\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.audioStickerStyle.sectionHeading\n      );\n    });\n\n    for (const stickerStyle of stickerStyles) {\n      it(`on pressing ${stickerStyle} button`, async () => {\n        await clickAudioStickerStyleButton(stickerStyle);\n        const selectedElement = await getSelectedAudioStickerElement();\n        expect(selectedElement.style).toBe(stickerStyle);\n      });\n    }\n  });\n\n  describe('should update sticker size', () => {\n    beforeEach(async () => {\n      await insertAudioSticker();\n      await fixture.events.click(\n        fixture.editor.sidebar.designPanel.audioStickerSize.sectionHeading\n      );\n    });\n\n    for (const stickerSize of stickerSizes) {\n      it(`on pressing ${stickerSize} button`, async () => {\n        await clickAudioStickerSizeButton(stickerSize);\n        const selectedElement = await getSelectedAudioStickerElement();\n        expect(selectedElement.size).toBe(stickerSize);\n      });\n    }\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/image/edit.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../fixture';\nimport { useStory } from '../../../app/story';\n\ndescribe('Image Editor', () => {\n  let fixture;\n  let elementId;\n  let frame;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n\n    // Add first image to canvas\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(fixture.editor.library.media.item(0), '30%', '30%'),\n      down(),\n      up(),\n    ]);\n\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    elementId = elements[1].id;\n    frame = fixture.editor.canvas.framesLayer.frame(elementId).node;\n  });\n\n  async function getCurrentImageData() {\n    const {\n      state: {\n        currentPage: { elements },\n      },\n    } = await fixture.renderHook(() => useStory());\n    return elements[1];\n  }\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  describe('CUJ: Creator Can Manipulate an Image/Video on Canvas: Enter edit mode', () => {\n    it('should render initial content', () => {\n      expect(frame).toBeTruthy();\n    });\n\n    describe('edit mode', () => {\n      beforeEach(async () => {\n        await fixture.events.click(frame);\n        await fixture.events.click(frame);\n      });\n\n      it('should mount editor', async () => {\n        expect(fixture.editor.canvas.editLayer.media).toBeTruthy();\n        await fixture.snapshot();\n      });\n\n      it('should have no aXe violations', async () => {\n        await expectAsync(\n          fixture.editor.canvas.editLayer.node\n        ).toHaveNoViolations();\n      });\n\n      it('should allow image to be scaled and moved using mouse', async () => {\n        const image = fixture.editor.canvas.editLayer.media;\n        const originalRect = image.getBoundingClientRect();\n        const originalImageData = await getCurrentImageData();\n\n        // First drag the slider handle 30px right\n        const slider = fixture.editor.canvas.editLayer.sizeSlider;\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(slider, 5, 5),\n          down(),\n          moveBy(30, 0, { steps: 2 }),\n          up(),\n        ]);\n\n        // Expect image to be scaled up\n        const scaledUpRect = image.getBoundingClientRect();\n        expect(scaledUpRect.width).toBeGreaterThan(originalRect.width);\n        expect(scaledUpRect.height).toBeGreaterThan(originalRect.height);\n\n        await fixture.snapshot('Image scaled up');\n\n        // Expect global image data to be unchanged while in editor\n        const imageDataAfterScale = await getCurrentImageData();\n        expect(imageDataAfterScale).toEqual(originalImageData);\n\n        // Then drag image 20px left\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(image, image.width / 2, image.height / 2),\n          down(),\n          moveBy(-20, 0, { steps: 2 }),\n          up(),\n        ]);\n\n        // Expect image to be moved left, not up or down\n        const movedRect = image.getBoundingClientRect();\n        expect(movedRect.left).toBeLessThan(scaledUpRect.left);\n        expect(movedRect.top).toBe(scaledUpRect.top);\n        await fixture.snapshot('Image moved');\n\n        // Expect global image data to still be unchanged while in editor\n        const imageDataAfterDrag = await getCurrentImageData();\n        expect(imageDataAfterDrag).toEqual(originalImageData);\n\n        // Click outside image to exit edit-mode\n        await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n          moveRel(image, -10, -10),\n          down(),\n          up(),\n        ]);\n        await fixture.snapshot('Image editor exited');\n\n        // Expect global image data to now be changed after exiting in editor\n        const imageDataAfterExit = await getCurrentImageData();\n        expect(imageDataAfterExit).not.toEqual(originalImageData);\n      });\n\n      it('should allow image to be scaled and moved using keyboard', async () => {\n        const originalImageData = await getCurrentImageData();\n\n        // Validate that image has focus\n        const slider = fixture.editor.canvas.editLayer.sizeSlider;\n        const image = fixture.editor.canvas.editLayer.media;\n        expect(image).toHaveFocus();\n\n        const originalRect = image.getBoundingClientRect();\n\n        // Press tab to move focus to slider\n        await fixture.events.keyboard.press('tab');\n        expect(slider).toHaveFocus();\n\n        // First move size slider 3 steps right\n        await fixture.events.keyboard.press('right');\n        await fixture.events.keyboard.press('right');\n        await fixture.events.keyboard.press('right');\n\n        // Expect image to be scaled up\n        const scaledUpRect = image.getBoundingClientRect();\n        expect(scaledUpRect.width).toBeGreaterThan(originalRect.width);\n        expect(scaledUpRect.height).toBeGreaterThan(originalRect.height);\n\n        await fixture.snapshot('Image scaled up');\n\n        // Expect global image data to be unchanged while in editor\n        const imageDataAfterScale = await getCurrentImageData();\n        expect(imageDataAfterScale).toEqual(originalImageData);\n\n        // Press shift-tab to move focus back to image\n        await fixture.events.keyboard.shortcut('shift+tab');\n        expect(image).toHaveFocus();\n\n        // Then move image 3 steps left\n        await fixture.events.keyboard.press('left');\n        await fixture.events.keyboard.press('left');\n        await fixture.events.keyboard.press('left');\n\n        // Expect image to be moved left, not up or down\n        const movedRect = image.getBoundingClientRect();\n        expect(movedRect.left).toBeLessThan(scaledUpRect.left);\n        expect(movedRect.top).toBe(scaledUpRect.top);\n        await fixture.snapshot('Image moved');\n\n        // Expect global image data to still be unchanged while in editor\n        const imageDataAfterDrag = await getCurrentImageData();\n        expect(imageDataAfterDrag).toEqual(originalImageData);\n\n        // Click 'esc' to exit edit-mode\n        await fixture.events.keyboard.press('esc');\n        await fixture.snapshot('Image editor exited');\n\n        // Expect global image data to now be changed after exiting in editor\n        const imageDataAfterExit = await getCurrentImageData();\n        expect(imageDataAfterExit).not.toEqual(originalImageData);\n      });\n\n      it('should allow image to be scaled using mouse-wheel', async () => {\n        // Validate that image has focus\n        const image = fixture.editor.canvas.editLayer.media;\n        expect(image).toHaveFocus();\n        const originalRect = image.getBoundingClientRect();\n\n        // Scale image up by scrolling three steps\n        await fixture.events.mouse.moveRel(image, 10, 10);\n        await fixture.events.mouse.wheel({ deltaY: 5 });\n        await fixture.events.mouse.wheel({ deltaY: 5 });\n        await fixture.events.mouse.wheel({ deltaY: 5 });\n\n        // Expect image to be scaled up\n        const scaledUpRect = image.getBoundingClientRect();\n        expect(scaledUpRect.width).toBeGreaterThan(originalRect.width);\n        expect(scaledUpRect.height).toBeGreaterThan(originalRect.height);\n        await fixture.snapshot('Image scaled up');\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/image/resourceLoading.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { resourceList } from '@googleforcreators/media';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../fixture';\nimport { useStory } from '../../../app/story';\n\ndescribe('Image resource loading integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should use cached thumbnail then switch to fullsize', async () => {\n    // Sleep a bit to ensure the media gallery grid is properly laid out.\n    await fixture.events.sleep(50);\n\n    const image = fixture.screen.getAllByAltText(\n      'image with transparent background'\n    );\n    await fixture.events.mouse.clickOn(image[0], 20, 20);\n\n    // We don't check for immediately cached value here because we would have to set a timeout of about 100ms in image/display in order to catch it here\n    // expect(resourceList.get(2).type).toEqual('cached');\n\n    await fixture.events.sleep(100); // Wait a bit for fullsize timeout\n\n    expect(resourceList.get(8).type).toEqual('fullsize');\n    const frames = fixture.screen.getAllByTestId('frameElement');\n    const imageFrame = frames[1];\n    const imageId = imageFrame.dataset.elementId;\n    const imageTag = fixture.editor.canvas.displayLayer\n      .display(imageId)\n      .node.querySelector('img');\n\n    const storyContext = await fixture.renderHook(() => useStory());\n    const storyDataSrc =\n      storyContext.state.currentPage.elements[1].resource.src;\n\n    await fixture.snapshot(\n      'Image with transparent background is displayed properly'\n    );\n\n    expect(imageTag.src).toEqual(storyDataSrc);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/text/edit.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../fixture';\nimport { useStory } from '../../../app/story';\n\ndescribe('TextEdit integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  function repeatPress(key, count) {\n    let remaining = count;\n    const press = () => {\n      if (remaining === 0) {\n        return Promise.resolve(true);\n      }\n      remaining--;\n      return fixture.events.keyboard.press(key).then(press);\n    };\n    return press();\n  }\n\n  it('should render ok', () => {\n    expect(\n      fixture.container.querySelector('[data-testid=\"fullbleed\"]')\n    ).toBeTruthy();\n  });\n\n  describe('add a text', () => {\n    let frame;\n\n    beforeEach(async () => {\n      await fixture.editor.library.textTab.click();\n      await fixture.events.click(\n        fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(() => {\n        const node = fixture.editor.canvas.framesLayer.frames[1].node;\n        if (!node) {\n          throw new Error('node not ready');\n        }\n        frame = fixture.editor.canvas.framesLayer.frames[1].node;\n      });\n      frame = fixture.editor.canvas.framesLayer.frames[1].node;\n    });\n\n    it('should render initial content', () => {\n      expect(frame.textContent).toEqual('Fill in some text');\n    });\n\n    it('should delete the element if content is empty', async () => {\n      expect(fixture.querySelector('[data-testid=\"textEditor\"]')).toBeNull();\n      await fixture.events.focus(\n        fixture.editor.canvas.framesLayer.frames[1].node\n      );\n      await fixture.events.keyboard.press('Enter');\n      expect(fixture.querySelector('[data-testid=\"textEditor\"]')).toBeDefined();\n      // Remove all text\n      await fixture.events.keyboard.press('Backspace');\n      // Exit edit mode using the Esc key\n      await fixture.events.keyboard.press('Esc');\n      // The element should be deleted.\n      const layerPanel = fixture.editor.footer.layerPanel;\n      await fixture.events.click(layerPanel.togglePanel);\n      expect(layerPanel.layers.length).toBe(1);\n    });\n\n    describe('edit mode', () => {\n      let editor;\n      let editLayer;\n      let boldToggle;\n\n      beforeEach(async () => {\n        await fixture.events.mouse.clickOn(frame, 30, 5);\n        editor = await fixture.screen.findByTestId('textEditor');\n        editLayer = await fixture.screen.findByTestId('editLayer');\n        await fixture.events.click(fixture.editor.sidebar.designTab);\n        boldToggle = fixture.editor.sidebar.designPanel.textStyle.bold;\n      });\n\n      it('should mount editor', async () => {\n        expect(editor).toBeTruthy();\n        expect(editLayer).toBeTruthy();\n        await fixture.snapshot();\n      });\n\n      it('should handle a command, exit and save', async () => {\n        // Increase the font size for ensuring the clicks to be in correct places.\n        await fixture.events.click(\n          fixture.editor.sidebar.designPanel.textStyle.fontSize,\n          { clickCount: 3 }\n        );\n        await fixture.events.keyboard.type('30');\n        await fixture.events.keyboard.press('tab');\n        // Give time for the font size to be applied.\n        await fixture.events.sleep(100);\n\n        // Select all.\n        await fixture.events.mouse.clickOn(frame, 30, 5);\n        await repeatPress('ArrowUp', 10);\n        await fixture.events.keyboard.down('shift');\n        await repeatPress('ArrowDown', 3);\n        await repeatPress('ArrowRight', 20);\n        await fixture.events.keyboard.up('shift');\n\n        expect(boldToggle.checked).toEqual(false);\n\n        await fixture.snapshot('before mod+b');\n\n        await fixture.events.keyboard.shortcut('mod+b');\n\n        await fixture.snapshot('after mod+b');\n\n        expect(boldToggle.checked).toEqual(true);\n\n        // Exit edit mode by clicking right outside the editor.\n        await fixture.events.mouse.seq(({ moveRel, down }) => [\n          moveRel(editor, -10),\n          down(),\n        ]);\n\n        expect(fixture.querySelector('[data-testid=\"textEditor\"]')).toBeNull();\n\n        // The element is still selected and updated.\n        const storyContext = await fixture.renderHook(() => useStory());\n        expect(storyContext.state.selectedElements[0].content).toEqual(\n          '<span style=\"font-weight: 700\">Fill in some text</span>'\n        );\n\n        // The content is updated in the frame.\n        // @todo: What to do with `<p>` and containers?\n        expect(frame.querySelector('p').innerHTML).toEqual(\n          '<span style=\"font-weight: 700\">Fill in some text</span>'\n        );\n      });\n\n      it('should select all text and delete it', async () => {\n        await fixture.events.mouse.clickOn(frame, 30, 5); // enter the edit mode by clicking\n\n        // Needed because of https://github.com/puppeteer/puppeteer/issues/1313\n        if (navigator.userAgentData.platform === 'macOS') {\n          document.execCommand('selectAll'); // not the same as mod+a, but does work on macOS\n        } else {\n          await fixture.events.keyboard.shortcut('mod+a'); // doesn't work on macOS, works on Ubuntu\n        }\n        const text = '461';\n        await fixture.events.keyboard.type(text);\n\n        // Exit edit mode using the Esc key\n        await fixture.events.keyboard.press('Esc');\n\n        // The element is still selected and updated.\n        await waitFor(async () => {\n          const story = await fixture.renderHook(() => useStory());\n          if (!story.state.selectedElements.length) {\n            throw new Error('story not ready');\n          }\n\n          expect(story.state.selectedElements[0].content).toEqual(text);\n        });\n      });\n    });\n\n    describe('shortcuts', () => {\n      it('should enter/exit edit mode using the keyboard', async () => {\n        // Enter edit mode using the Enter key\n        expect(fixture.querySelector('[data-testid=\"textEditor\"]')).toBeNull();\n        await fixture.events.keyboard.press('Enter');\n        expect(\n          fixture.querySelector('[data-testid=\"textEditor\"]')\n        ).toBeDefined();\n        await fixture.events.sleep(500);\n        await fixture.events.keyboard.type('This is some test text.');\n\n        // Exit edit mode using the Esc key\n        await fixture.events.keyboard.press('Esc');\n\n        // The element is still selected and updated.\n        await waitFor(async () => {\n          const story = await fixture.renderHook(() => useStory());\n          if (!story.state.selectedElements.length) {\n            throw new Error('story not ready');\n          }\n\n          expect(story.state.selectedElements[0].content).toEqual(\n            'This is some test text.'\n          );\n        });\n      });\n    });\n  });\n\n  describe('add a multiline text element', () => {\n    let frame;\n    let textElement;\n    let initialHeight;\n\n    describe('edit mode', () => {\n      // TODO: Fix flakey test.\n      // eslint-disable-next-line jasmine/no-disabled-tests\n      xit('should not change height when entering and exiting edit mode', async () => {\n        await fixture.editor.library.textTab.click();\n        await fixture.events.click(\n          fixture.editor.library.text.preset('Paragraph')\n        );\n        await waitFor(() => {\n          const node = fixture.editor.canvas.framesLayer.frames[1].node;\n          if (!node) {\n            throw new Error('node not ready');\n          }\n          expect(node).toBeTruthy();\n          frame = fixture.editor.canvas.framesLayer.frames[1].node;\n        });\n        const { width } = frame.getBoundingClientRect();\n\n        // Enter edit mode.\n        await fixture.events.keyboard.press('Enter');\n        await fixture.events.sleep(300);\n        await fixture.events.keyboard.type('This is some test text.');\n        await fixture.events.keyboard.press('Enter');\n        await fixture.events.keyboard.press('Enter');\n        await fixture.events.keyboard.type('This is more test text.');\n        await fixture.events.keyboard.press('Enter');\n\n        // Get the initial height.\n        textElement = await fixture.screen.findByTestId('textEditor');\n        initialHeight = textElement.getBoundingClientRect()?.height;\n\n        await fixture.snapshot('Trailing and leading newlines, in edit mode');\n\n        // Exit edit mode using the Esc key\n        await fixture.events.keyboard.press('Esc');\n\n        await fixture.snapshot(\n          'Trailing and leading newlines, after edit mode'\n        );\n\n        const { height: heightAfterExitingEditMode } =\n          frame.getBoundingClientRect();\n\n        expect(initialHeight).toBeCloseTo(heightAfterExitingEditMode, 0);\n\n        // Reenter edit mode\n        await fixture.events.mouse.clickOn(\n          frame,\n          width / 2,\n          heightAfterExitingEditMode / 2\n        );\n        textElement = await fixture.screen.findByTestId('textEditor');\n\n        const { height: heightAfterReenteringEditMode } =\n          textElement.getBoundingClientRect();\n\n        expect(heightAfterReenteringEditMode).toBeCloseTo(initialHeight, 0);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/text/frame.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../fixture';\nimport { useStory } from '../../../app/story';\nimport { useInsertElement } from '../../../components/canvas';\n\ndescribe('TextFrame integration', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should render ok', () => {\n    expect(\n      fixture.container.querySelector('[data-testid=\"fullbleed\"]')\n    ).toBeTruthy();\n  });\n\n  describe('interop with edit mode', () => {\n    let element;\n    let frame;\n    let editor;\n    let canvas;\n\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n\n      element = await fixture.act(() =>\n        insertElement('text', {\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          content: 'hello world!',\n          x: 40,\n          y: 40,\n          width: 250,\n        })\n      );\n      canvas = fixture.querySelector('[data-testid=\"fullbleed\"]');\n    });\n\n    it('clicking', async () => {\n      await fixture.events.mouse.clickOn(canvas);\n\n      frame = fixture.editor.canvas.framesLayer.frame(element.id);\n\n      await fixture.events.click(frame.node, { clickCount: 3 });\n\n      await fixture.events.keyboard.type('hello world after select element!');\n\n      editor = fixture.querySelector(`[data-testid=\"textEditor\"]`);\n      await fixture.events.mouse.clickOn(editor, -10, 0);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds).toEqual([element.id]);\n      expect(storyContext.state.selectedElements[0].content).toEqual(\n        'hello world after select element!'\n      );\n\n      expect(frame.node.textContent).toEqual(\n        'hello world after select element!'\n      );\n    });\n\n    it('pressing Enter', async () => {\n      await fixture.events.mouse.clickOn(canvas);\n\n      frame = fixture.editor.canvas.framesLayer.frame(element.id);\n\n      await fixture.events.mouse.clickOn(frame.node);\n\n      await fixture.events.keyboard.press('Enter');\n\n      await fixture.events.keyboard.type('hello world after press Enter!');\n\n      editor = fixture.querySelector(`[data-testid=\"textEditor\"]`);\n      await fixture.events.mouse.clickOn(editor, -10, 0);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds).toEqual([element.id]);\n      expect(storyContext.state.selectedElements[0].content).toEqual(\n        'hello world after press Enter!'\n      );\n\n      expect(frame.node.textContent).toEqual('hello world after press Enter!');\n    });\n\n    it('typing', async () => {\n      await fixture.events.mouse.clickOn(canvas);\n\n      frame = fixture.editor.canvas.framesLayer.frame(element.id);\n\n      await fixture.events.mouse.clickOn(frame.node);\n\n      await fixture.events.keyboard.type('hello world after type!');\n\n      editor = fixture.querySelector(`[data-testid=\"textEditor\"]`);\n      await fixture.events.mouse.clickOn(editor, -10, 0);\n\n      const storyContext = await fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElementIds).toEqual([element.id]);\n      expect(storyContext.state.selectedElements[0].content).toEqual(\n        'hello world after type!'\n      );\n\n      expect(frame.node.textContent).toEqual('hello world after type!');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/video/autoplay.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../../fixture';\nimport { useStory } from '../../../app/story';\n\ndescribe('Autoplay video', () => {\n  let fixture;\n  let mediaPane;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n    mediaPane = fixture.container.querySelector('#library-pane-media');\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const clickOnTarget = async (target) => {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n  };\n\n  it('should render ok', () => {\n    expect(\n      fixture.container.querySelector('[data-testid=\"fullbleed\"]')\n    ).toBeTruthy();\n  });\n\n  // TODO https://github.com/googleforcreators/web-stories-wp/issues/9931\n  // eslint-disable-next-line jasmine/no-disabled-tests\n  xit('should autoplay on insert and on drop', async () => {\n    const video = Array.from(mediaPane.querySelectorAll('video')).filter(\n      (el) => el.title === 'ranger9'\n    );\n    await clickOnTarget(video[0]);\n\n    const videoFrame = fixture.editor.canvas.framesLayer.frames[1].node;\n    const videoId = videoFrame.dataset.elementId;\n\n    const video1El = fixture.editor.canvas.displayLayer\n      .display(videoId)\n      .node.querySelector('video');\n    expect(video1El.paused).toBe(false);\n\n    const fullbleed = fixture.editor.canvas.framesLayer.fullbleed;\n    await fixture.events.mouse.seq(({ moveRel, down, up }) => [\n      moveRel(videoFrame, '10%', '10%'),\n      down(),\n      moveRel(fullbleed, 10, 10),\n      up(),\n    ]);\n    // Should not play during the drag\n    expect(video1El.paused).toBe(true);\n    await fixture.events.mouse.up();\n    const backgroundId = (await getElements(fixture))[0].id;\n    const backgroundElVideo = fixture.editor.canvas.displayLayer\n      .display(backgroundId)\n      .node.querySelector('video');\n    expect(backgroundElVideo.paused).toBe(false);\n\n    // Bug #2618 coverage\n    await fixture.events.mouse.seq(({ moveRel }) => [\n      moveRel(fullbleed, '10%', '10%'),\n    ]);\n    await waitFor(\n      () => fixture.editor.canvas.framesLayer.controls(backgroundId).pause\n    );\n    await fixture.events.click(\n      fixture.editor.canvas.framesLayer.controls(backgroundId).pause\n    );\n    expect(backgroundElVideo.paused).toBe(true);\n    await fixture.events.click(\n      fixture.editor.canvas.framesLayer.controls(backgroundId).play\n    );\n    expect(backgroundElVideo.paused).toBe(false);\n  });\n});\n\nasync function getElements(fixture) {\n  const {\n    state: {\n      currentPage: { elements },\n    },\n  } = await fixture.renderHook(() => useStory());\n  return elements;\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/element-library/video/elementMinSizeAndPlayback.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../..';\nimport { useInsertElement } from '../../../components/canvas';\n\ndescribe('Element min size and playback', () => {\n  let fixture;\n\n  beforeEach(async () => {\n    fixture = new Fixture();\n    await fixture.render();\n    await fixture.collapseHelpCenter();\n  });\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  it('should render ok', () => {\n    expect(\n      fixture.container.querySelector('[data-testid=\"fullbleed\"]')\n    ).toBeTruthy();\n  });\n\n  describe('add 2 videos', () => {\n    let video1;\n    let video2;\n    let video1Frame;\n\n    beforeEach(async () => {\n      const insertElement = await fixture.renderHook(() => useInsertElement());\n      const videoProps = {\n        x: 0,\n        y: 0,\n        width: 260,\n        height: 120,\n        resource: {\n          type: 'video',\n          mimeType: 'video/ogg',\n          src: 'http://localhost:9876/__static__/asteroid.ogg',\n          poster: 'http://localhost:9876/__static__/asteroid.png',\n          width: 1080,\n          height: 720,\n          alt: 'Asteroid',\n        },\n      };\n      video1 = await fixture.act(() => insertElement('video', videoProps));\n      // fix flaky tests\n      await fixture.events.sleep();\n      video2 = await fixture.act(() =>\n        insertElement('video', { ...videoProps, x: 20, y: 20 })\n      );\n      video1Frame = fixture.querySelector(\n        `[data-element-id=\"${video1.id}\"][data-testid=\"frameElement\"]`\n      );\n    });\n\n    it('hit play button on the covered element', async () => {\n      // video1 is covered by video2\n      // select video1, hover on play button, hit play, verify that it's playing\n      const video1bb = video1Frame.getBoundingClientRect();\n\n      await fixture.events.mouse.click(video1bb.x, video1bb.y);\n\n      await fixture.events.mouse.click(\n        video1bb.x + video1bb.width / 2,\n        video1bb.y + video1bb.height / 2\n      );\n      const video1El = fixture.querySelector(`#video-${video1.id}`);\n      const video2El = fixture.querySelector(`#video-${video2.id}`);\n      const video1isPlaying = video1El.paused === false;\n      const video2isPlaying = video2El.paused === false;\n\n      expect(video1isPlaying).toBe(true);\n      expect(video2isPlaying).toBe(false);\n    });\n\n    it('hit spacebar on the covered element', async () => {\n      // video1 is covered by video2\n      // select video1, press spacebar, verify video1 is playing\n      const video1bb = video1Frame.getBoundingClientRect();\n\n      await fixture.events.mouse.click(video1bb.x, video1bb.y);\n\n      await fixture.events.keyboard.press('Space');\n      const video1El = fixture.querySelector(`#video-${video1.id}`);\n      const video2El = fixture.querySelector(`#video-${video2.id}`);\n      const video1isPlaying = video1El.paused === false;\n      const video2isPlaying = video2El.paused === false;\n\n      expect(video1isPlaying).toBe(true);\n      expect(video2isPlaying).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/elementTransform.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport useInsertElement from '../components/canvas/useInsertElement';\nimport { useStory } from '../app/story';\nimport { Fixture } from './fixture';\n\ndescribe('Element transform', () => {\n  let fixture;\n  let frame;\n\n  const clickOnTarget = async (target) => {\n    const { x, y, width, height } = target.getBoundingClientRect();\n    await fixture.events.mouse.click(x + width / 2, y + height / 2);\n  };\n\n  const addTextInEditMode = async () => {\n    const insertElement = await fixture.renderHook(() => useInsertElement());\n    const element = await fixture.act(() =>\n      insertElement('text', {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        content: 'Hello, Stories!',\n      })\n    );\n    frame = fixture.editor.canvas.framesLayer.frame(element.id).node;\n    await clickOnTarget(frame);\n  };\n\n  const getSelectedElement = async () => {\n    const storyContext = await fixture.renderHook(() => useStory());\n    return storyContext.state.selectedElements[0];\n  };\n\n  describe('Element: Text', () => {\n    beforeEach(async () => {\n      fixture = new Fixture();\n      await fixture.render();\n      await fixture.collapseHelpCenter();\n\n      // Switch to 100% zoom to make sure all full pixels are valid coordinates\n      const { zoomSelector } = fixture.editor.footer;\n      await fixture.events.click(zoomSelector.select);\n      await fixture.events.sleep(300);\n      await fixture.events.click(await zoomSelector.option('100%'));\n      await fixture.events.sleep(300);\n\n      // Add a text element and enter edit mode.\n      await addTextInEditMode();\n    });\n\n    afterEach(() => {\n      fixture.restore();\n    });\n\n    describe('CUJ: Creator can Transform an Element: Resize', () => {\n      it('it should allow resizing in text edit mode', async () => {\n        // Test that resize handle exists in edit mode.\n        const rightResizeHandle = fixture.container.querySelector(\n          '.moveable-control.moveable-e'\n        );\n        expect(rightResizeHandle).toBeDefined();\n\n        const widthBefore = window.getComputedStyle(frame).width;\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(rightResizeHandle, 1, 1),\n          down(),\n          moveBy(20, 0, { steps: 1 }),\n          up(),\n        ]);\n        const widthAfter = window.getComputedStyle(frame).width;\n        // It should just be within a pixel of correct\n        expect(\n          Number.parseInt(widthAfter) - Number.parseInt(widthBefore)\n        ).toBeOneOf([19, 20, 21]);\n      });\n    });\n\n    describe('CUJ: Creator can Transform an Element: Rotate', () => {\n      it('it should allow rotating in text edit mode', async () => {\n        // Test that rotation handle exists in edit mode.\n        const rotationHandle = fixture.container.querySelector(\n          '.moveable-rotation-control'\n        );\n        expect(rotationHandle).toBeDefined();\n\n        const elementBefore = await getSelectedElement();\n        expect(elementBefore.rotationAngle).toEqual(0);\n        await fixture.events.mouse.seq(({ moveRel, moveBy, down, up }) => [\n          moveRel(rotationHandle, 3, 5),\n          down(),\n          moveBy(10, 0, { steps: 1 }),\n          up(),\n        ]);\n        const elementAfter = await getSelectedElement();\n        await expect(elementAfter.rotationAngle).not.toEqual(0);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/checklist/accessibility/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  ElementLinkTappableRegionTooSmall,\n  ElementLinkTappableRegionTooBig,\n  ImageElementMissingAlt,\n  PageBackgroundTextLowContrast,\n  TextElementFontSizeTooSmall,\n  VideoElementMissingCaptions,\n  VideoElementMissingDescription,\n} from '../../../../../components/checklist';\nimport { useConfig } from '../../../../../app/config';\n\nfunction Accessibility() {\n  const { hasUploadMediaAction } = useConfig(({ capabilities }) => ({\n    hasUploadMediaAction: capabilities.hasUploadMediaAction,\n  }));\n  return (\n    <>\n      <PageBackgroundTextLowContrast />\n      <TextElementFontSizeTooSmall />\n      <VideoElementMissingDescription />\n      {hasUploadMediaAction && <VideoElementMissingCaptions />}\n      <ElementLinkTappableRegionTooSmall />\n      <ElementLinkTappableRegionTooBig />\n      <ImageElementMissingAlt />\n    </>\n  );\n}\n\nexport default Accessibility;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/checklist/design/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  PageTooManyLinks,\n  PageTooMuchText,\n  PageTooLittleText,\n  VideoElementResolution,\n  ImageElementResolution,\n  StoryPagesCount,\n  FirstPageAnimation,\n} from '../../../../../components/checklist';\nimport { useConfig } from '../../../../../app/config';\n\nfunction Design() {\n  const { hasUploadMediaAction } = useConfig(({ capabilities }) => ({\n    hasUploadMediaAction: capabilities.hasUploadMediaAction,\n  }));\n  return (\n    <>\n      <StoryPagesCount />\n      <PageTooMuchText />\n      <PageTooLittleText />\n      <PageTooManyLinks />\n      <FirstPageAnimation />\n      {hasUploadMediaAction && <VideoElementResolution />}\n      {hasUploadMediaAction && <ImageElementResolution />}\n    </>\n  );\n}\n\nexport default Design;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/checklist/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Accessibility } from './accessibility';\nexport { default as Design } from './design';\nexport { default as Priority } from './priority';\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/checklist/priority/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../../../../app/config';\nimport {\n  PublisherLogoSize,\n  StoryMissingExcerpt,\n  StoryMissingTitle,\n  StoryPosterSize,\n  StoryPosterAttached,\n  StoryTitleLength,\n  VideoElementMissingPoster,\n  VideoOptimization,\n  StoryAmpValidationErrors,\n  PublisherLogoMissing,\n} from '../../../../../components/checklist';\nimport useFFmpeg from '../../../../../app/media/utils/useFFmpeg';\n\nfunction Priority() {\n  const { hasUploadMediaAction } = useConfig(({ capabilities }) => ({\n    canManageSettings: capabilities.canManageSettings,\n    hasUploadMediaAction: capabilities.hasUploadMediaAction,\n  }));\n  const { isTranscodingEnabled } = useFFmpeg();\n\n  return (\n    <>\n      <StoryMissingTitle />\n      <StoryTitleLength />\n      <StoryMissingExcerpt />\n      {hasUploadMediaAction && <StoryPosterAttached />}\n      {hasUploadMediaAction && <StoryPosterSize />}\n      {hasUploadMediaAction && <PublisherLogoMissing />}\n      {hasUploadMediaAction && <PublisherLogoSize />}\n      {hasUploadMediaAction && <VideoElementMissingPoster />}\n      {/* `isTranscodingEnabled` already checks for `hasUploadMediaAction` */}\n      {isTranscodingEnabled && <VideoOptimization />}\n      <StoryAmpValidationErrors />\n    </>\n  );\n}\n\nexport default Priority;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/documentPane/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  ExcerptPanel,\n  SlugPanel,\n  PageAdvancementPanel,\n  BackgroundAudioPanel,\n  TaxonomiesPanel,\n} from '../../../../components/panels/document';\nfunction DocumentPane() {\n  return (\n    <>\n      <ExcerptPanel />\n      <SlugPanel />\n      <PageAdvancementPanel />\n      <BackgroundAudioPanel />\n      <TaxonomiesPanel />\n    </>\n  );\n}\n\nexport function PublishModalDocumentPane() {\n  return (\n    <>\n      <SlugPanel nameOverride=\"storyDetailsExcerpt\" />\n      <PageAdvancementPanel nameOverride=\"storyDetailsPageAdvancement\" />\n      <BackgroundAudioPanel nameOverride=\"storyDetailsBackgroundAudio\" />\n      <TaxonomiesPanel nameOverride=\"storyDetailsTaxonomies\" />\n    </>\n  );\n}\n\nexport default DocumentPane;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/header/buttons/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { CircularProgress } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../../../../../app/story/useStory';\nimport {\n  RedoButton,\n  PreviewButton,\n  SwitchToDraftButton,\n  UndoButton,\n  UpdateButton,\n  PublishButton,\n} from '../../../../../components/header/buttons';\n\nconst ButtonList = styled.nav`\n  display: flex;\n  justify-content: flex-end;\n  padding: 1em;\n  height: 100%;\n`;\n\nconst List = styled.div`\n  display: flex;\n  align-items: center;\n  gap: 8px;\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  top: 0;\n`;\n\nconst IconWithSpinner = styled.div`\n  position: relative;\n`;\n\nfunction Loading() {\n  const { isSaving } = useStory((state) => ({\n    isSaving: state.state.meta.isSaving,\n  }));\n  return (\n    isSaving && (\n      <Spinner>\n        <CircularProgress size={32} />\n      </Spinner>\n    )\n  );\n}\n\nfunction Buttons() {\n  const { status, canPublish } = useStory(\n    ({\n      state: {\n        story: { status },\n        capabilities,\n      },\n    }) => ({\n      status,\n      canPublish: Boolean(capabilities?.publish),\n    })\n  );\n\n  const isPending = 'pending' === status;\n  const isDraft =\n    ['draft', 'auto-draft'].includes(status) || isPending || !status;\n  const isDraftOrPending = isDraft || isPending;\n\n  return (\n    <ButtonList>\n      <List>\n        <UndoButton />\n        <RedoButton />\n        <IconWithSpinner>\n          <PreviewButton />\n          <Loading />\n        </IconWithSpinner>\n        {isPending && <SwitchToDraftButton />}\n        {(isDraft || (isPending && canPublish)) && <UpdateButton />}\n        {isDraftOrPending && <PublishButton />}\n        {!isDraftOrPending && (\n          <>\n            <SwitchToDraftButton />\n            <UpdateButton />\n          </>\n        )}\n      </List>\n    </ButtonList>\n  );\n}\n\nexport default Buttons;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/components/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { memo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport HeaderTitle from '../../../../components/header/title';\nimport Buttons from './buttons';\n\nconst Background = styled.header.attrs({\n  role: 'group',\n  'aria-label': __('Story canvas header', 'web-stories'),\n})`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Head = styled.div`\n  flex: 1 1 auto;\n  padding: 1em;\n`;\n\nconst ButtonCell = styled.div`\n  grid-area: buttons;\n`;\n\nfunction HeaderLayout() {\n  return (\n    <Background>\n      <Head>\n        <HeaderTitle />\n      </Head>\n      <ButtonCell>\n        <Buttons />\n      </ButtonCell>\n    </Background>\n  );\n}\n\n// Don't rerender the header needlessly e.g. on element selection change.\nexport default memo(HeaderLayout);\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/canvas.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\nimport { QuickActionMenu } from './quickActionMenu';\nimport { DesignMenu } from './designMenu';\n\n/**\n * The editor's canvas. Includes: display, frames, editor layers,\n * navigation buttons, page menu.\n */\nexport class Canvas extends Container {\n  get displayLayer() {\n    return this._get(\n      this.getByRole('region', { name: 'Display layer' }),\n      'displayLayer',\n      DisplayLayer\n    );\n  }\n\n  get framesLayer() {\n    return this._get(\n      this.getByRole('region', { name: 'Frames layer' }),\n      'framesLayer',\n      FramesLayer\n    );\n  }\n\n  get editLayer() {\n    return this._get(\n      this.getByRole('region', { name: 'Edit layer' }),\n      'editLayer',\n      EditLayer\n    );\n  }\n\n  get mediaRecordingLayer() {\n    return this._get(\n      this.getByRole('region', { name: /^Media Recording layer$/i }),\n      'mediaRecordingLayer',\n      MediaRecordingLayer\n    );\n  }\n\n  get header() {\n    return this._get(\n      this.getAllByRole('group', { name: 'Story canvas header' })[0],\n      'header',\n      Header\n    );\n  }\n\n  get quickActionMenu() {\n    return this._get(\n      this.getByRole('menu', { name: /Group of available options/ }),\n      'quickActionMenu',\n      QuickActionMenu\n    );\n  }\n\n  get pageActions() {\n    return this._get(\n      this.getByRole('group', { name: 'Page actions' }),\n      'pageActions',\n      PageActions\n    );\n  }\n\n  get designMenu() {\n    return this._get(\n      this.getByRole('region', { name: 'Design menu' }),\n      'designMenu',\n      DesignMenu\n    );\n  }\n}\n\n/**\n * Abstract layer.\n */\nclass AbstractLayer extends Container {\n  get scrollContainer() {\n    return this.node.querySelector('[data-scroll-container]');\n  }\n\n  get fullbleed() {\n    return this.getByRole('region', { name: /^Fullbleed area/ });\n  }\n}\n\n/**\n * Contains element displays.\n */\nclass DisplayLayer extends AbstractLayer {\n  get displays() {\n    return this._getAll(\n      // @todo: improve query.\n      this.node.querySelectorAll('[data-element-id]'),\n      (node) => `displays[${node.getAttribute('data-element-id')}]`,\n      Frame\n    );\n  }\n\n  display(elementId) {\n    return this._get(\n      // @todo: improve query.\n      this.node.querySelector(`[data-element-id=\"${elementId}\"]`),\n      `displays[${elementId}]`,\n      Display\n    );\n  }\n}\n\n/**\n * An element's display.\n */\nclass Display extends Container {\n  get overlay() {\n    return this.node.querySelector(\n      '[class^=\"displayElement__BackgroundOverlay-sc-\"]'\n    );\n  }\n\n  get element() {\n    return this.node.querySelector('[class^=\"display__Element-sc-\"]');\n  }\n\n  get replacement() {\n    return this.node.querySelector(\n      '[class^=\"displayElement__ReplacementContainer-sc-\"]'\n    );\n  }\n}\n\n/**\n * Contains element frames.\n */\nclass FramesLayer extends AbstractLayer {\n  get container() {\n    return this.node;\n  }\n\n  get frames() {\n    return this._getAll(\n      // @todo: improve query.\n      this.node.querySelectorAll(\n        '[data-testid=\"frameElement\"][data-element-id]'\n      ),\n      (node) => `frames[${node.getAttribute('data-element-id')}]`,\n      Frame\n    );\n  }\n\n  frame(elementId) {\n    return this._get(\n      // @todo: improve query.\n      this.node.querySelector(\n        `[data-testid=\"frameElement\"][data-element-id=\"${elementId}\"]`\n      ),\n      `frames[${elementId}]`,\n      Frame\n    );\n  }\n\n  controls(elementId) {\n    return this._get(\n      this.node.querySelector(`[data-controls-id=\"${elementId}\"]`),\n      `controls[${elementId}]`,\n      Controls\n    );\n  }\n\n  get prevPage() {\n    return this.getByRole('button', { name: 'Previous Page' });\n  }\n}\n\n/**\n * Contains elements in edit-mode.\n */\nclass EditLayer extends AbstractLayer {\n  get text() {\n    return this.node.querySelector('[data-testid=\"textEditor\"]');\n  }\n\n  get media() {\n    return this.getByRole('img', { name: /move/i });\n  }\n\n  get sizeSlider() {\n    return this.getByRole('slider');\n  }\n}\n\nclass MediaRecordingSettings extends Container {\n  get videoInput() {\n    return this.getByRole('button', { name: 'Video Input' });\n  }\n\n  get audioInput() {\n    return this.getByRole('button', { name: 'Audio Input' });\n  }\n\n  get cancel() {\n    return this.getByRole('button', { name: 'Cancel' });\n  }\n\n  get save() {\n    return this.getByRole('button', { name: 'Save' });\n  }\n}\n\nclass MediaRecordingLayer extends Container {\n  get recordVideo() {\n    return this.getByRole('button', { name: 'Record Video' });\n  }\n\n  get recordAudio() {\n    return this.getByRole('button', { name: 'Record Audio' });\n  }\n\n  get takePhoto() {\n    return this.getByRole('button', { name: 'Take a photo' });\n  }\n\n  get stopRecording() {\n    return this.getByRole('button', { name: 'Stop Recording' });\n  }\n\n  get insert() {\n    return this.getByRole('button', { name: 'Insert' });\n  }\n\n  get retry() {\n    return this.getByRole('button', { name: 'Retry' });\n  }\n\n  get previewVideo() {\n    return this.getByRole('video');\n  }\n\n  get previewImage() {\n    return this.getByRole('img');\n  }\n\n  get settingsDialog() {\n    return this._get(\n      this.getByRole('dialog', { name: /^Media Recording Options$/ }),\n      'mediaRecordingSettings',\n      MediaRecordingSettings\n    );\n  }\n}\n\n/**\n * An element's frame.\n */\nclass Frame extends Container {\n  get textContentHTML() {\n    return this.node.querySelector('p')?.innerHTML;\n  }\n}\n\n/**\n * An element's controls.\n */\nclass Controls extends Container {\n  get play() {\n    return this.getByRole('button', { name: 'Click to play' });\n  }\n\n  get pause() {\n    return this.getByRole('button', { name: 'Click to pause' });\n  }\n}\n\n/**\n * The story header\n */\nclass Header extends Container {\n  get title() {\n    return this.getByRole('textbox', { name: 'Story title' });\n  }\n\n  get saveDraft() {\n    return this.getByRole('button', { name: 'Save draft' });\n  }\n\n  get switchToDraft() {\n    return this.getByRole('button', { name: 'Switch to draft' });\n  }\n\n  get update() {\n    return this.getByRole('button', { name: 'Update' });\n  }\n\n  get publish() {\n    return this.getByRole('button', { name: 'Publish' });\n  }\n\n  get preview() {\n    return this.getByRole('button', { name: 'Preview' });\n  }\n\n  get schedule() {\n    return this.getByRole('button', { name: 'Schedule' });\n  }\n}\n\n/**\n * Page action buttons.\n */\nclass PageActions extends Container {\n  get addPage() {\n    return this.getByRole('button', { name: 'Add New Page' });\n  }\n\n  get duplicatePage() {\n    return this.getByRole('button', { name: 'Duplicate Page' });\n  }\n\n  get deletePage() {\n    return this.getByRole('button', { name: 'Delete Page' });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/carousel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The page carousel.\n */\nexport class Carousel extends Container {\n  get pages() {\n    const pageList = this.queryByRole('listbox', { name: 'Pages List' });\n    if (!pageList) {\n      return [];\n    }\n    return this._getAll(\n      // @todo: improve query.\n      pageList.querySelectorAll('button[role=\"option\"]'),\n      (node) => `pages[${node.getAttribute('data-page-id')}]`,\n      PageThumb\n    );\n  }\n\n  page(pageId) {\n    return this.pages.find(\n      (page) => page.node.getAttribute('data-page-id') === pageId\n    );\n  }\n\n  get previous() {\n    return this.queryByRole('button', { name: 'Scroll Back' });\n  }\n\n  get next() {\n    return this.queryByRole('button', { name: 'Scroll Forward' });\n  }\n\n  get toggle() {\n    return this.queryByRole('button', { name: 'Toggle page carousel' });\n  }\n}\n\n/**\n * A page thumbnail.\n */\nclass PageThumb extends Container {}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/checklist.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The checklist that can be toggled open\n * that will show different types of issues to the user.\n *\n * Some issues may prompt extra actions.\n */\nexport class Checklist extends Container {\n  get toggleButton() {\n    return this.getByRole('button', { name: /^Checklist/ });\n  }\n\n  get issues() {\n    return this.getByRole('tablist', {\n      name: /^Potential Story issues by category$/,\n    });\n  }\n\n  get closeButton() {\n    return this.getByRole('button', { name: /^Close/ });\n  }\n\n  get priorityTab() {\n    return this.queryByRole('tab', { name: /Priority issue/ });\n  }\n\n  get priorityPanel() {\n    return this.queryByRole('tabpanel', { name: /^Priority/ });\n  }\n\n  get expandedPriorityTab() {\n    return this.getByRole('tab', { name: /Priority issue/, selected: true });\n  }\n\n  get designTab() {\n    return this.queryByRole('tab', { name: /Design issue/ });\n  }\n\n  get expandedDesignTab() {\n    return this.getByRole('tab', { name: /Design issue/, selected: true });\n  }\n\n  get designPanel() {\n    return this.queryByRole('tabpanel', { name: /^Design/ });\n  }\n\n  get accessibilityTab() {\n    return this.queryByRole('tab', { name: /Accessibility issue/ });\n  }\n\n  get expandedAccessibilityTab() {\n    return this.getByRole('tab', {\n      name: /Accessibility issue/,\n      selected: true,\n    });\n  }\n\n  get accessibilityPanel() {\n    return this.queryByRole('tabpanel', { name: /^Accessibility/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/color.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * The color input containing both a button to open color picker, a hex input and an opacity input\n */\nexport class Color extends Container {\n  label = 'Unset';\n\n  get button() {\n    return this.getByRole('button', { name: this.label });\n  }\n\n  get opacity() {\n    return this.getByRole('textbox', { name: /Opacity/i });\n  }\n\n  get hex() {\n    return this.getByRole('textbox', { name: this.label });\n  }\n\n  get output() {\n    return this.button.innerText;\n  }\n\n  get picker() {\n    return this._get(\n      this.getByRoleIn(this.node.ownerDocument, 'dialog', {\n        name: /Color and gradient picker/,\n      }),\n      'picker',\n      ColorPicker\n    );\n  }\n}\n\nclass ColorPicker extends Container {\n  get hexButton() {\n    return this.getByRole('button', { name: /Edit hex value/i });\n  }\n\n  get hexInput() {\n    return this.getByRole('button', { name: /Edit hex value/i });\n  }\n\n  get opacityButton() {\n    return this.getByRole('button', { name: /Edit opacity value/i });\n  }\n\n  get opacityInput() {\n    return this.getByRole('textbox', { name: /Edit opacity value/i });\n  }\n\n  get saveColor() {\n    return this.getByRole('button', { name: /Add color/i });\n  }\n\n  applySavedColor(pattern) {\n    return this.getByRole('option', {\n      name: pattern,\n    });\n  }\n\n  addSavedColor(type) {\n    return this.getByRole('button', { name: `Add ${type} color` });\n  }\n\n  get colorTypeSelect() {\n    return this.getByRole('button', { name: 'Select color type' });\n  }\n\n  get eyedropper() {\n    return this.getByRole('button', { name: /Pick a color from canvas/i });\n  }\n\n  get editButton() {\n    return this.getByRole('button', { name: /Edit colors/ });\n  }\n\n  get exitEditButton() {\n    return this.getByRole('button', { name: /Exit edit mode/ });\n  }\n\n  get deleteStoryColor() {\n    return this.getByRole('option', {\n      name: /Delete local color/,\n    });\n  }\n\n  get deleteGlobalColor() {\n    return this.getByRole('option', {\n      name: /Delete global color/,\n    });\n  }\n\n  get custom() {\n    return this.getByRole('button', { name: /Custom/i });\n  }\n\n  defaultColor(name) {\n    return this.getByRole('option', { name });\n  }\n\n  get linearGradientPickerButton() {\n    return this.getByRole('button', { name: /Linear gradient pattern type/i });\n  }\n\n  get radialGradientPickerButton() {\n    return this.getByRole('button', { name: /Radial gradient pattern type/i });\n  }\n\n  get gradientStopEndButton() {\n    return this.getByRole('button', { name: /Gradient stop at 100%/i });\n  }\n\n  // @todo: add accessors for remaining options\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nexport { Radio } from './radio';\nexport { Toggle } from './toggle';\nexport { ToggleButton } from './toggleButton';\nexport { Select } from './select';\nexport { Color } from './color';\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/radio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * An icon-based radio, that is either on or off and is surrounded by a label\n * acting as the button to trigger it. The actual radio element (the\n * `<input type=\"radio\" />`) is visually hidden so any mouse-user would\n * click the surrounding label rather than the input.\n */\nexport class Radio extends Container {\n  get checked() {\n    return this.node.checked;\n  }\n\n  get button() {\n    return this.node.closest('label');\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/select.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * The select dropdown, which is actually just a button that open a popup\n * containing the actual dropdown options.\n */\nexport class Select extends Container {\n  constructor(node, path) {\n    super(node, path);\n    this.name = this.node.getAttribute('aria-label');\n  }\n\n  get select() {\n    return this.node;\n  }\n\n  get value() {\n    return this.node.innerText;\n  }\n\n  get optionList() {\n    return this.getByRoleIn(this.node.ownerDocument, 'listbox', {\n      name: new RegExp(this.name),\n    });\n  }\n\n  option(name) {\n    return this.getByRoleIn(this.optionList, 'option', { name });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/toggle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * An icon-based toggle, that is either on or off and is surrounded by a label\n * acting as the button to trigger it. The actual toggle element (the\n * `<input type=\"checkbox\" />`) is visually hidden so any mouse-user would\n * click the surrounding label rather than the input.\n */\nexport class Toggle extends Container {\n  get checked() {\n    return this.node.checked;\n  }\n\n  get button() {\n    return this.node.closest('label');\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/common/toggleButton.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * An icon-based toggle, that is either on or off and is surrounded by a label\n * acting as the button to trigger it. The actual toggle element (the\n * `<input type=\"checkbox\" />`) is visually hidden so any mouse-user would\n * click the surrounding label rather than the input.\n */\nexport class ToggleButton extends Container {\n  get checked() {\n    return this.node.getAttribute('aria-pressed') === 'true';\n  }\n\n  get button() {\n    return this.node;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/container.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  getByTestId,\n  getAllByTestId,\n  getByRole,\n  getAllByRole,\n  queryByRole,\n  waitFor,\n  getByText,\n} from '@testing-library/react';\n\n/** @typedef {import('@testing-library/dom').Matcher} Matcher */\n/** @typedef {import('@testing-library/dom').ByRoleOptions} ByRoleOptions */\n/** @typedef {import('@testing-library/dom').ByTestIdOptions} ByTestIdOptions */\n\nexport class Container {\n  /**\n   * @param {Element} node Node.\n   * @param {string} path Path.\n   */\n  constructor(node, path) {\n    this._node = node;\n    this._path = path;\n  }\n\n  get node() {\n    return this._node;\n  }\n\n  get path() {\n    return this._path;\n  }\n\n  /**\n   * The container can indicate that it's not ready by setting the\n   * `data-ready=\"false\"` attribute.\n   *\n   * @return {!Promise} Resolve when the container is ready.\n   */\n  waitReady() {\n    // @todo: consider joining on the parent waitReady as well.\n    return waitFor(() => {\n      if (this._node.getAttribute('data-ready') === 'false') {\n        throw new Error(`Container <${this._path}>is not ready  yet`);\n      }\n    });\n  }\n\n  /**\n   * @return {!Promise} Resolve when the element or one of its children becomes\n   * focused.\n   */\n  waitFocusedWithin() {\n    return waitFor(() => {\n      if (!this._node.contains(document.activeElement)) {\n        throw new Error(`Focus is not set within the <${this._path}> yet`);\n      }\n    });\n  }\n\n  /**\n   * See https://testing-library.com/docs/queries/bytestid\n   *\n   * @param {Matcher} text test id.\n   * @param {ByRoleOptions} options Options.\n   * @return {HTMLElement} The found element.\n   */\n  getByTestId(text, options) {\n    return getByTestId(this._node, text, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/queries/bytestid\n   *\n   * @param {Matcher} text test id.\n   * @param {ByRoleOptions} options Options.\n   * @return {HTMLElement} The found element.\n   */\n  getAllByTestId(text, options) {\n    return getAllByTestId(this._node, text, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n   *\n   * @param {Matcher} role Role name.\n   * @param {ByRoleOptions} options Options.\n   * @return {HTMLElement} The found element.\n   */\n  getByRole(role, options) {\n    return getByRole(this._node, role, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n   *\n   * @param {Matcher} role Role name.\n   * @param {ByRoleOptions} options Options.\n   * @return {Array.<HTMLElement>} The found elements.\n   */\n  getAllByRole(role, options) {\n    return getAllByRole(this._node, role, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n   *\n   * @param {HTMLElement} root Root node\n   * @param {Matcher} role Role name.\n   * @param {ByRoleOptions} options Options.\n   * @return {HTMLElement} The found element.\n   */\n  getByRoleIn(root, role, options) {\n    return getByRole(root, role, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n   *\n   * @param {HTMLElement} root Root node\n   * @param {Matcher} role Role name.\n   * @param {ByRoleOptions} options Options.\n   * @return {Array.<HTMLElement>} The found elements.\n   */\n  getAllByRoleIn(root, role, options) {\n    return getAllByRole(root, role, options);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#bytext\n   *\n   * @param {string} text Text.\n   * @return {HTMLElement} The found element.\n   */\n  getByText(text) {\n    return getByText(this._node, text);\n  }\n\n  /**\n   * See https://testing-library.com/docs/dom-testing-library/api-queries#byrole\n   *\n   * @param {Matcher} role Role name.\n   * @param {ByRoleOptions} options Options.\n   * @return {HTMLElement} The found element.\n   */\n  queryByRole(role, options) {\n    return queryByRole(this._node, role, options);\n  }\n\n  _get(node, name, constr) {\n    if (!node) {\n      return null;\n    }\n    const path = `${this._path}.${name}`;\n    const key = `FixturePath(${path})`;\n    if (!node[key]) {\n      node[key] = new constr(node, path);\n    }\n    return node[key];\n  }\n\n  _getAll(nodeList, nameFn, constr) {\n    return Array.from(nodeList).map((node) =>\n      this._get(node, nameFn(node), constr)\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\nimport { ToggleButton, Color } from './common';\n\nexport class DesignMenu extends Container {\n  get flipVertical() {\n    return this._get(\n      this.getByRole('button', { name: 'Flip vertically' }),\n      'flipVertical',\n      ToggleButton\n    );\n  }\n\n  get flipHorizontal() {\n    return this._get(\n      this.getByRole('button', { name: 'Flip horizontally' }),\n      'flipHorizontal',\n      ToggleButton\n    );\n  }\n\n  get borderRadius() {\n    return this.queryByRole('textbox', { name: 'Corner Radius' });\n  }\n\n  get borderWidth() {\n    return this.queryByRole('textbox', { name: 'Border width' });\n  }\n\n  get borderColor() {\n    const region = this.queryByRole('region', {\n      name: 'Color input (floating menu): Border color',\n    });\n    if (!region) {\n      return null;\n    }\n    const element = this._get(region, 'borderColor', Color);\n    element.label = 'Border color';\n    return element;\n  }\n\n  get swapMedia() {\n    return this.getByRole('menuitem', { name: 'Replace media' });\n  }\n\n  get loop() {\n    return this.getByRole('checkbox', { name: 'Loop' });\n  }\n\n  get textAlign() {\n    return this.getByRole('menuitem', { name: 'Change text alignment' });\n  }\n\n  textAlignIcon(name) {\n    return this.getByRoleIn(this.textAlign, 'img', { name });\n  }\n\n  textAlignOption(name) {\n    const dialog = this.getByRole('dialog', { name: 'Text alignment options' });\n    return this.getByRoleIn(dialog, 'button', { name });\n  }\n\n  get fontSize() {\n    return this.getByRole('textbox', { name: /Font size/ });\n  }\n\n  get fontColor() {\n    const region = this.queryByRole('region', {\n      name: 'Color input (floating menu): Text color',\n    });\n    if (!region) {\n      return null;\n    }\n    const element = this._get(region, 'textColor', Color);\n    element.label = 'Text color';\n    return element;\n  }\n\n  get opacity() {\n    return this.getByRole('textbox', { name: /^Opacity in percent$/ });\n  }\n\n  get bold() {\n    return this._get(\n      this.getByRole('button', { name: /Toggle bold/ }),\n      'toggleBold',\n      ToggleButton\n    );\n  }\n\n  get italic() {\n    return this._get(\n      this.getByRole('button', { name: /Toggle italic/ }),\n      'toggleItalic',\n      ToggleButton\n    );\n  }\n\n  get underline() {\n    return this._get(\n      this.getByRole('button', { name: /Toggle underline/ }),\n      'toggleUnderline',\n      ToggleButton\n    );\n  }\n\n  get more() {\n    return this.getByRole('menuitem', { name: /^More$/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/abstractPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * An abstract panel supporting properties that all panels have -\n * such as title and collapsed status.\n */\nexport class AbstractPanel extends Container {\n  get title() {\n    // @todo: implement\n    return null;\n  }\n\n  get isCollapsed() {\n    // @todo: implement\n    return null;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/alignment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The alignment panel containing buttons for aligning elements to each other\n * or the page depending on whether one or more elements are selected.\n */\nexport class Alignment extends AbstractPanel {\n  get distributeHorizontally() {\n    return this.getByRole('button', { name: /Distribute horizontally/i });\n  }\n\n  get distributeVertically() {\n    return this.getByRole('button', { name: /Distribute vertically/i });\n  }\n\n  get left() {\n    return this.getByRole('button', { name: /Align left/i });\n  }\n\n  get center() {\n    return this.getByRole('button', { name: /Align center/i });\n  }\n\n  get right() {\n    return this.getByRole('button', { name: /Align right/i });\n  }\n\n  get top() {\n    return this.getByRole('button', { name: /Align top/i });\n  }\n\n  get middle() {\n    return this.getByRole('button', { name: /Align vertical center/i });\n  }\n\n  get bottom() {\n    return this.getByRole('button', { name: /Align bottom/i });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/animationPanel.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\nexport class Animation extends AbstractPanel {\n  get effectChooser() {\n    return this.getByRole('button', { name: /Animation: Effect Chooser/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/audioStickerSize.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\nexport class AudioStickerSize extends AbstractPanel {\n  get sectionHeading() {\n    return this.getByRole('button', { name: /Size/i });\n  }\n\n  get small() {\n    return this.getByText('Small');\n  }\n\n  get large() {\n    return this.getByText('Large');\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/audioStickerStyle.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\nexport class AudioStickerStyle extends AbstractPanel {\n  get sectionHeading() {\n    return this.getByRole('button', { name: /Style/i });\n  }\n\n  get none() {\n    return this.getByRole('button', { name: /Sticker Style: None/i });\n  }\n\n  get outline() {\n    return this.getByRole('button', { name: /Sticker Style: Outline/i });\n  }\n\n  get dropshadow() {\n    return this.getByRole('button', { name: /Sticker Style: Drop shadow/i });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/audioStickerType.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\nexport class AudioStickerType extends AbstractPanel {\n  get sectionHeading() {\n    return this.getByRole('button', { name: /Type/i });\n  }\n\n  get headphoneCat() {\n    return this.getByRole('button', { name: /Sticker Type: Headphone Cat/i });\n  }\n\n  get tapePlayer() {\n    return this.getByRole('button', { name: /Sticker Type: Tape Player/i });\n  }\n\n  get loudSpeaker() {\n    return this.getByRole('button', { name: /Sticker Type: Loud Speaker/i });\n  }\n\n  get audioCloud() {\n    return this.getByRole('button', { name: /Sticker Type: Audio Cloud/i });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/border.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Color, Radio } from '../common';\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The size position panel containing inputs for adding managing the size, position and rotationAngle.\n */\nexport class Border extends AbstractPanel {\n  width(side = null) {\n    return this.getByRole('textbox', {\n      name: side ? `${side} border` : 'Border',\n    });\n  }\n\n  position(mode) {\n    return this._get(\n      this.getByRole('radio', { name: `Border position mode: ${mode}` }),\n      'borderPosition',\n      Radio\n    );\n  }\n\n  get lockBorderWidth() {\n    return this.getByRole('button', { name: /Toggle consistent border/ });\n  }\n\n  get borderColor() {\n    return this._get(\n      this.getByRole('region', { name: /Color input: Border color/ }),\n      'borderColor',\n      Color\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/captions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The captions panel containing inputs for adding captions and subtitles.\n */\nexport class Captions extends AbstractPanel {\n  get addCaptionsButton() {\n    return this.getByRole('button', { name: /upload a file/i });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/colorPreset.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\nimport { AbstractPanel } from './abstractPanel';\n\nclass ColorPresetType extends Container {\n  constructor(node, path) {\n    super(node, path);\n    // Name is added as the last part of path after dot.\n    this._type = /[^.]*$/.exec(path)[0];\n  }\n  get add() {\n    return this.getByRole('button', { name: `Add ${this._type} color` });\n  }\n  get apply() {\n    return this.getByRole('button', { name: `Apply ${this._type} color` });\n  }\n  get delete() {\n    return this.getByRole('button', { name: `Delete ${this._type} color` });\n  }\n}\n\n/**\n * The text style panel containing inputs, toggles, dropdowns and other form elements\n * to view and manipulate the style of one or more currently selected text elements.\n */\nexport class ColorPreset extends AbstractPanel {\n  get local() {\n    return this._get(this.node, 'local', ColorPresetType);\n  }\n  get global() {\n    return this._get(this.node, 'global', ColorPresetType);\n  }\n\n  get edit() {\n    return this.getByRole('button', { name: /Edit colors/ });\n  }\n\n  get exit() {\n    return this.getByRole('button', { name: /Exit edit mode/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/filter.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The background filter panel containing buttons for toggling which filter\n * is shown for a given background plus options for manipulating said filter.\n */\nexport class Filter extends AbstractPanel {\n  get none() {\n    return this.getByRole('button', { name: /Filter: None/i });\n  }\n\n  get solid() {\n    return this.getByRole('button', { name: /Filter: Tint/i });\n  }\n\n  get linear() {\n    return this.getByRole('button', { name: /Filter: Linear/i });\n  }\n\n  get radial() {\n    return this.getByRole('button', { name: /Filter: Vignette/i });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\nimport { Alignment } from './alignment';\nimport { Animation } from './animationPanel';\nimport { Filter } from './filter';\nimport { Border } from './border';\nimport { ColorPreset } from './colorPreset';\nimport { Link } from './link';\nimport { PageBackground } from './pageBackground';\nimport { PageBackgroundAudio } from './pageBackgroundAudio';\nimport { SizePosition } from './sizePosition';\nimport { TextStyle } from './textStyle';\nimport { VideoPoster } from './videoPoster';\nimport { VideoOptions } from './videoOptions';\nimport { Captions } from './captions';\nimport { ShapeStyle } from './shapeStyle';\nimport { AudioStickerType } from './audioStickerType';\nimport { AudioStickerStyle } from './audioStickerStyle';\nimport { AudioStickerSize } from './audioStickerSize';\n\n/**\n * The editor's canvas. Includes: display, frames, editor layers, carousel,\n * navigation buttons, page menu.\n */\nexport class DesignPanel extends Container {\n  get selectionSection() {\n    return this.getByRole('tab', { name: /Selection/i });\n  }\n\n  get linkSection() {\n    return this.getByRole('tab', { name: /Link/ });\n  }\n\n  get animationSection() {\n    return this.getByRole('tab', { name: /Animation/ });\n  }\n\n  get textStyle() {\n    return this._get(\n      this.getByRole('region', { name: 'Text' }),\n      'textStyle',\n      TextStyle\n    );\n  }\n\n  get alignment() {\n    return this._get(\n      this.getByRole('region', { name: /Alignment/ }),\n      'alignment',\n      Alignment\n    );\n  }\n\n  get filters() {\n    return this._get(\n      this.getByRole('region', { name: /Filters/ }),\n      'filters',\n      Filter\n    );\n  }\n\n  get link() {\n    return this._get(this.getByRole('region', { name: /Link/ }), 'link', Link);\n  }\n\n  get videoAccessibility() {\n    return this._get(\n      this.getByRole('region', { name: /Accessibility/ }),\n      'poster',\n      VideoPoster\n    );\n  }\n\n  get colorPreset() {\n    return this._get(\n      this.getByRole('region', { name: /Saved Colors/i }),\n      'colorPreset',\n      ColorPreset\n    );\n  }\n\n  get imageAccessibility() {\n    // @todo: implement\n    return null;\n  }\n\n  get shapeStyle() {\n    return this._get(\n      this.getByRole('region', { name: /Shape style/i }),\n      'shapeStyle',\n      ShapeStyle\n    );\n  }\n\n  get sizePosition() {\n    return this._get(\n      this.getByRole('region', { name: /Selection/i }),\n      'sizePosition',\n      SizePosition\n    );\n  }\n\n  get border() {\n    return this._get(\n      this.getByRole('region', { name: /Border/i }),\n      'borderStyle',\n      Border\n    );\n  }\n\n  get videoOptions() {\n    return this._get(\n      this.getByRole('region', { name: /Video settings/i }),\n      'videoOptions',\n      VideoOptions\n    );\n  }\n\n  get captions() {\n    return this._get(\n      this.getByRole('region', { name: /Caption and Subtitles/i }),\n      'captions',\n      Captions\n    );\n  }\n\n  get animation() {\n    return this._get(\n      this.getByRole('region', { name: /Animation/ }),\n      'animation',\n      Animation\n    );\n  }\n\n  get pageBackground() {\n    return this._get(\n      this.getByRole('region', { name: /^Page Background$/i }),\n      'pageBackground',\n      PageBackground\n    );\n  }\n\n  get pageBackgroundAudio() {\n    return this._get(\n      this.getByRole('region', { name: /^Page Background Audio$/i }),\n      'pageBackgroundAudio',\n      PageBackgroundAudio\n    );\n  }\n\n  get audioStickerType() {\n    return this._get(\n      this.getByRole('region', { name: /Audio Sticker Type/i }),\n      'audioStickerType',\n      AudioStickerType\n    );\n  }\n\n  get audioStickerStyle() {\n    return this._get(\n      this.getByRole('region', { name: /Audio Sticker Style/i }),\n      'audioStickerStyle',\n      AudioStickerStyle\n    );\n  }\n\n  get audioStickerSize() {\n    return this._get(\n      this.getByRole('region', { name: /Audio Sticker Size/i }),\n      'audioStickerSize',\n      AudioStickerSize\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/layers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getByLabelText, getAllByTestId } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The layers panel.\n */\nexport class Layers extends AbstractPanel {\n  get togglePanel() {\n    return this._node;\n  }\n\n  get layersList() {\n    return getByLabelText(this.node.ownerDocument, /layers list/i);\n  }\n\n  get layers() {\n    return getAllByTestId(this.layersList, 'layer-option');\n  }\n\n  getLayerByInnerText(text) {\n    return getAllByTestId(this.layersList, 'layer-option').find(\n      (option) => option.innerText === text\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/link.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The link panel containing inputs for adding links to elements.\n */\nexport class Link extends AbstractPanel {\n  get address() {\n    return this.getByRole('textbox', { name: 'Element link' });\n  }\n\n  get icon() {\n    return this.queryByRole('button', { name: 'Edit link icon' });\n  }\n\n  get description() {\n    return this.queryByRole('textbox', { name: 'Link description' });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/pageBackground.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Color } from '../common';\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The page background panel containing inputs flipping and detaching images as well as setting bg color.\n */\nexport class PageBackground extends AbstractPanel {\n  get flipVertical() {\n    return this.getByRole('button', { name: /Flip vertically/i });\n  }\n\n  get flipHorizontal() {\n    return this.getByRole('button', { name: /Flip horizontally/i });\n  }\n\n  get detachBg() {\n    return this.getByRole('button', { name: /Detach background/i });\n  }\n\n  get backgroundColor() {\n    const color = this._get(\n      this.getByRole('region', { name: /Color input: Background color/ }),\n      'backgroundColor',\n      Color\n    );\n    color.label = 'Background color';\n    return color;\n  }\n\n  get backgroundColorInput() {\n    return this.getByRole('textbox', { name: /Background color/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/pageBackgroundAudio.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The page background panel containing inputs flipping and detaching images as well as setting bg color.\n */\nexport class PageBackgroundAudio extends AbstractPanel {\n  get uploadButton() {\n    return this.getByRole('button', {\n      name: /upload an audio file/i,\n    });\n  }\n\n  get hotlinkButton() {\n    return this.getByRole('button', {\n      name: /link to audio file/i,\n    });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/shapeStyle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Color } from '../common';\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The shape style panel containing inputs for adding managing the background color and opacity\n */\nexport class ShapeStyle extends AbstractPanel {\n  get backgroundColor() {\n    const color = this._get(\n      this.getByRole('region', { name: /Color input: Background color/ }),\n      'backgroundColor',\n      Color\n    );\n    color.label = 'Background color';\n    return color;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/sizePosition.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The size position panel containing inputs for adding managing the size, position and rotationAngle.\n */\nexport class SizePosition extends AbstractPanel {\n  get width() {\n    return this.getByRole('textbox', { name: /Width/i });\n  }\n\n  get height() {\n    return this.getByRole('textbox', { name: /Height/i });\n  }\n\n  get lockAspectRatio() {\n    return this.getByRole('button', { name: /Lock aspect ratio/ });\n  }\n\n  get rotate() {\n    // @todo Implement.\n    return null;\n  }\n\n  get flipVertical() {\n    return this.getByRole('button', { name: /Flip vertically/i });\n  }\n\n  get flipHorizontal() {\n    return this.getByRole('button', { name: /Flip horizontally/i });\n  }\n\n  get opacity() {\n    return this.getByRole('textbox', { name: /Opacity in percent/i });\n  }\n\n  radius(corner = null) {\n    return this.getByRole('textbox', {\n      name: corner ? `${corner} corner radius` : 'Corner Radius',\n    });\n  }\n\n  get lockBorderRadius() {\n    return this.getByRole('button', {\n      name: /Toggle consistent corner radius/,\n    });\n  }\n\n  get setAsBackground() {\n    return this.getByRole('button', {\n      name: /Set as background/i,\n    });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/textStyle.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ToggleButton, Select, Color } from '../common';\nimport { Container } from '../container';\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The text style panel containing inputs, toggles, dropdowns and other form elements\n * to view and manipulate the style of one or more currently selected text elements.\n */\nexport class TextStyle extends AbstractPanel {\n  get bold() {\n    return this._get(\n      this.getByRole('button', { name: /Bold/ }),\n      'bold',\n      ToggleButton\n    );\n  }\n\n  get italic() {\n    return this._get(\n      this.getByRole('button', { name: /Italic/ }),\n      'italic',\n      ToggleButton\n    );\n  }\n\n  get underline() {\n    return this._get(\n      this.getByRole('button', { name: /Underline/ }),\n      'underline',\n      ToggleButton\n    );\n  }\n\n  get uppercase() {\n    return this._get(\n      this.getByRole('button', { name: /Uppercase/ }),\n      'uppercase',\n      ToggleButton\n    );\n  }\n\n  get fontWeight() {\n    return this._get(\n      this.getByRole('button', { name: /Font weight/ }),\n      'fontWeight',\n      Select\n    );\n  }\n\n  get letterSpacing() {\n    return this.getByRole('textbox', { name: /Letter-spacing/ });\n  }\n\n  get lineHeight() {\n    return this.getByRole('textbox', { name: /Line-height/ });\n  }\n\n  align(name) {\n    return this.getByRole('button', { name });\n  }\n\n  get padding() {\n    return this.getByRole('textbox', { name: /Padding/ });\n  }\n\n  get fontColor() {\n    const color = this._get(\n      this.getByRole('region', { name: /Color input: Text/ }),\n      'fontColor',\n      Color\n    );\n    color.label = 'Text color';\n    return color;\n  }\n\n  get backgroundColor() {\n    const bgColor = this._get(\n      this.getByRole('region', { name: /Color input: Background color/ }),\n      'backgroundColor',\n      Color\n    );\n    bgColor.label = 'Background color';\n    return bgColor;\n  }\n\n  get fontSize() {\n    return this.getByRole('textbox', { name: /Font size/ });\n  }\n\n  get collapse() {\n    return this.getByRole('button', { name: 'Text' });\n  }\n\n  get adaptiveColor() {\n    return this.getByRole('button', { name: /Adaptive text colors/ });\n  }\n\n  get fill() {\n    return this.getByRole('option', { name: /fill/i });\n  }\n\n  get addStyle() {\n    return this.getByRole('button', { name: /Add style/ });\n  }\n\n  get applyStyle() {\n    return this.getByRole('button', { name: /Apply style/ });\n  }\n\n  get presets() {\n    return this.getAllByRole('button', { name: /Apply style/ });\n  }\n\n  get moreStyles() {\n    return this.getByRole('button', { name: /More styles/ });\n  }\n\n  get styleManager() {\n    return this._get(\n      this.getByRoleIn(this.node.ownerDocument, 'dialog', {\n        name: /Style presets manager/,\n      }),\n      'styleManager',\n      StyleManager\n    );\n  }\n\n  // @todo: add remaining input options:\n  // * font family and size\n  // * justify toggles\n}\n\nclass StyleManager extends Container {\n  get apply() {\n    return this.getByRole('button', { name: /Apply style/ });\n  }\n\n  get presets() {\n    return this.getAllByRole('button', { name: /Apply style/ });\n  }\n\n  get delete() {\n    return this.getByRole('button', { name: /Delete style/ });\n  }\n\n  get edit() {\n    return this.getByRole('button', { name: /Edit style/ });\n  }\n\n  get exit() {\n    return this.getByRole('button', { name: /Exit edit mode/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/videoOptions.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The video options panel containing controls for loop, mute, and trim.\n */\nexport class VideoOptions extends AbstractPanel {\n  get loop() {\n    return this.getByRole('checkbox', { name: 'Loop' });\n  }\n\n  get volume() {\n    return this.getByRole('slider');\n  }\n\n  get panelTitle() {\n    return this.getByRole('button', { name: 'Video Settings' });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/designPanel/videoPoster.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { AbstractPanel } from './abstractPanel';\n\n/**\n * The poster panel containing inputs for adding poster.\n */\nexport class VideoPoster extends AbstractPanel {\n  get posterImage() {\n    return this.getByRole('img', { alt: 'Preview poster image' });\n  }\n\n  get posterMenuButton() {\n    return this.getByRole('button', {\n      name: /video poster/i,\n    });\n  }\n\n  get posterMenuEdit() {\n    return this.getByRoleIn(this.node.ownerDocument, 'menuitem', {\n      name: /upload a file/i,\n    });\n  }\n\n  get posterMenuHotlink() {\n    return this.getByRoleIn(this.node.ownerDocument, 'menuitem', {\n      name: /link to a file/i,\n    });\n  }\n\n  get posterMenuReset() {\n    return this.getByRoleIn(this.node.ownerDocument, 'menuitem', {\n      name: /reset/i,\n    });\n  }\n\n  get panelTitle() {\n    return this.getByRole('button', { name: 'Accessibility' });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/documentPanel/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\nimport { Taxonomies } from './taxonomies';\n\nexport class DocumentPanel extends Container {\n  get author() {\n    return this.getByRole('button', { name: /Author/ });\n  }\n\n  get posterMenuButton() {\n    return this.getByRole('button', {\n      name: /Poster image/i,\n    });\n  }\n\n  get taxonomies() {\n    return this._get(\n      this.getByRole('region', { name: /Taxonomies/ }),\n      'taxonomies',\n      Taxonomies\n    );\n  }\n\n  // @TODO: rest of the fields.\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/documentPanel/taxonomies.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\n/**\n * The taxonomies panel containing taxonomy and metadata about the story.\n */\nexport class Taxonomies extends Container {\n  get taxonomiesButton() {\n    return this.getByRole('button', { name: /Taxonomies/ });\n  }\n\n  get categories() {\n    return this.getAllByRole('checkbox');\n  }\n\n  get addNewCategoryButton() {\n    return this.getByRole('button', { name: /Add New Category/ });\n  }\n\n  get newCategoryNameInput() {\n    return this.getByRole('textbox', {\n      name: /New Category Name/,\n    });\n  }\n\n  get parentDropdownButton() {\n    return this.getByRole('button', { name: /Parent Category/ });\n  }\n\n  get tagTokenRemoveButtons() {\n    return this.getAllByRole('button', { name: /Remove Tag/ });\n  }\n\n  get tagsInput() {\n    return this.getByRole('combobox', { name: /Add New Tag/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/editor.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\nimport { Canvas } from './canvas';\nimport { GridView } from './gridView';\nimport { Footer } from './footer';\nimport { Library } from './library';\nimport { Sidebar } from './sidebar';\nimport { Header } from './header';\nimport { HelpCenter } from './helpCenter';\nimport { Checklist } from './checklist';\nimport { KeyboardShortcuts } from './keyboardShortcuts';\n\n/**\n * The complete editor container, including library, canvas, sidebar, etc.\n */\nexport class Editor extends Container {\n  get canvas() {\n    return this._get(\n      this.getByRole('region', { name: 'Canvas' }),\n      'canvas',\n      Canvas\n    );\n  }\n\n  get titleBar() {\n    return this._get(\n      this.getByRole('group', { name: /^Story canvas header$/ }),\n      'titleBar',\n      Header\n    );\n  }\n\n  get library() {\n    return this._get(\n      this.getByRole('region', { name: 'Library' }),\n      'library',\n      Library\n    );\n  }\n\n  get sidebar() {\n    return this._get(\n      this.getByRole('region', { name: 'Sidebar' }),\n      'sidebar',\n      Sidebar\n    );\n  }\n\n  get footer() {\n    return this._get(\n      this.getByRole('region', { name: 'Workspace Footer' }),\n      'footer',\n      Footer\n    );\n  }\n\n  get gridView() {\n    return this._get(\n      this.getByRoleIn(this.node.ownerDocument, 'region', {\n        name: 'Grid View',\n      }),\n      'gridView',\n      GridView\n    );\n  }\n\n  get helpCenter() {\n    return this._get(\n      this.getByRole('region', { name: 'Workspace Footer' }),\n      'helpCenter',\n      HelpCenter\n    );\n  }\n\n  get checklist() {\n    return this._get(\n      this.getByRole('region', { name: 'Checklist' }),\n      'checklist',\n      Checklist\n    );\n  }\n\n  get keyboardShortcuts() {\n    return this._get(\n      this.getByRole('region', { name: 'Workspace Footer' }),\n      'keyboardShortcuts',\n      KeyboardShortcuts\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/footer.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\nimport { Select } from './common';\nimport { Carousel } from './carousel';\nimport { Layers } from './designPanel/layers';\n\n/**\n * The workspace footer.\n */\nexport class Footer extends Container {\n  get carousel() {\n    return this._get(\n      this.getByRole('region', { name: 'Page Carousel' }),\n      'carousel',\n      Carousel\n    );\n  }\n\n  get gridViewToggle() {\n    return this.getByRole('button', { name: 'Grid View' });\n  }\n\n  get helpCenterToggle() {\n    return this.getByRole('button', { name: /^Help Center/ });\n  }\n\n  get checklistToggle() {\n    return this.getByRole('button', { name: /^Checklist/ });\n  }\n\n  get keyboardShortcutsToggle() {\n    return this.getByRole('button', { name: /^Keyboard Shortcuts$/ });\n  }\n\n  get zoomSelector() {\n    return this._get(\n      this.getByRole('button', { name: 'Zoom Level' }),\n      'zoomSelector',\n      Select\n    );\n  }\n\n  get layerPanel() {\n    // The whole panel is aria-hidden for accessibility reasons\n    return this._get(\n      this.getByRole('button', { name: /^Layers/ }),\n      'layerPanel',\n      Layers\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/gridView.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The gid view dialog.\n */\nexport class GridView extends Container {\n  get pages() {\n    const pageList = this.getByRole('listbox', {\n      name: 'Grid View Pages List',\n    });\n    if (!pageList) {\n      return [];\n    }\n    return this._getAll(\n      // @todo: improve query.\n      pageList.querySelectorAll('button[role=\"option\"]'),\n      (node) => `pages[${node.getAttribute('data-page-id')}]`,\n      PageThumb\n    );\n  }\n\n  page(pageName) {\n    return this.getByRole('option', { name: new RegExp(`${pageName}`) });\n  }\n\n  get currentPage() {\n    return this.getByRole('option', { name: /current page/ });\n  }\n\n  get close() {\n    return this.getByRole('button', { name: 'Close' });\n  }\n\n  get size() {\n    return this.getByRole('slider', { name: 'Pages per row' });\n  }\n}\n\n/**\n * A page thumbnail.\n */\nclass PageThumb extends Container {}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/header.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The titleBar or app header. Includes title input, save, draft and publish buttons\n */\nexport class Header extends Container {\n  get publish() {\n    return this.getByRole('button', { name: /^Publish$/ });\n  }\n\n  get saveDraft() {\n    return this.getByRole('button', { name: /^Save draft$/ });\n  }\n\n  get switchToDraft() {\n    return this.getByRole('button', { name: /^Switch to draft$/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/helpCenter.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The help center that can be toggled open\n * or will show for specific interaction to help first time users.\n */\nexport class HelpCenter extends Container {\n  get toggleButton() {\n    return this.getByRole('button', { name: /^Help Center/ });\n  }\n\n  get quickTips() {\n    return this.queryByRole('dialog', { name: /^Help Center$/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { Editor } from './editor';\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/keyboardShortcuts.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\n\n/**\n * The help center that can be toggled open\n * or will show for specific interaction to help first time users.\n */\nexport class KeyboardShortcuts extends Container {\n  get keyboardShortcutsMenu() {\n    return this.queryByRole('dialog', {\n      name: /^Keyboard Shortcuts$/,\n    });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/library/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\nimport Text from './text';\nimport PageTemplates from './pageTemplates';\n\n/**\n * The library wrapper - containing tabs and panes for media, text and shapes.\n */\nexport class Library extends Container {\n  get mediaTab() {\n    return this.getByRole('tab', { name: /Media Gallery/ });\n  }\n\n  get media() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Media Gallery/ }),\n      'media',\n      Media\n    );\n  }\n\n  get media3pTab() {\n    return this.getByRole('tab', { name: /Explore Media/ });\n  }\n\n  get media3p() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Explore Media/ }),\n      'media3p',\n      Media3P\n    );\n  }\n\n  get textTab() {\n    return this.getByRole('tab', { name: /Text library/ });\n  }\n\n  get text() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Text library/ }),\n      'text',\n      Text\n    );\n  }\n\n  get shapesTab() {\n    return this.getByRole('tab', { name: /Shapes library/ });\n  }\n\n  get shapes() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Shapes library/ }),\n      'shapes',\n      Shapes\n    );\n  }\n\n  get shoppingTab() {\n    return this.getByRole('tab', { name: /Shopping library/ });\n  }\n\n  get pageTemplatesTab() {\n    return this.getByRole('tab', { name: /Page templates library/ });\n  }\n\n  get pageTemplatesPane() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Page templates library/ }),\n      'pageTemplates',\n      PageTemplates\n    );\n  }\n}\n\nexport class Shapes extends Container {\n  shape(name) {\n    return this.getByRole('button', {\n      name,\n    });\n  }\n\n  sticker(type) {\n    return this.getByTestId(`library-sticker-${type}`);\n  }\n}\n\nexport class Media extends Container {\n  get mediaRecording() {\n    return this.getByRole('button', {\n      name: 'Record Video/Audio',\n    });\n  }\n\n  get searchBar() {\n    return this.getByRole('searchbox');\n  }\n\n  item(index) {\n    return this.node.querySelectorAll('[data-testid^=mediaElement]')[index];\n  }\n}\n\nexport class Media3P extends Container {\n  get tabs() {\n    return this.getAllByRole('tab');\n  }\n\n  get unsplashTab() {\n    return this.getByRole('tab', { name: /^Images$/ });\n  }\n\n  get coverrTab() {\n    return this.getByRole('tab', { name: /^Video$/ });\n  }\n\n  get tenorTab() {\n    return this.getByRole('tab', { name: /^GIFs$/ });\n  }\n\n  get stickersTab() {\n    return this.getByRole('tab', { name: /^Stickers$/ });\n  }\n\n  get coverrSection() {\n    return this.getByRole('tabpanel', { name: /^Video$/ });\n  }\n\n  get unsplashSection() {\n    return this.getByRole('tabpanel', { name: /^Images$/ });\n  }\n\n  get tenorSection() {\n    return this.getByRole('tabpanel', { name: /^GIFs$/ });\n  }\n\n  get filters() {\n    return this.getAllByRoleIn(\n      this.getByRole('listbox', { name: /List of filtering options/ }),\n      'option'\n    );\n  }\n\n  get expandFiltersButton() {\n    return this.getByRole('button', { name: /Expand/ });\n  }\n\n  get mediaGallery() {\n    return this.getByTestId('media-gallery-container');\n  }\n\n  get mediaElements() {\n    return this.getAllByTestId(/^mediaElement/);\n  }\n\n  insertionBtnByIndex(index) {\n    const buttons = this.getAllByRole('button', {\n      name: /Open insertion menu/,\n    });\n    return buttons[index];\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/library/pageTemplates.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\nexport default class PageTemplates extends Container {\n  get pageTemplates() {\n    return this.getAllByRole('listitem');\n  }\n\n  get pageTemplateButtons() {\n    return this.node.querySelectorAll('[data-testid^=page_template_]');\n  }\n\n  pageTemplate(name) {\n    return this.getByRole('listitem', { name });\n  }\n\n  pageTemplateButton(name) {\n    return this.getByRole('button', { name });\n  }\n\n  get dropDown() {\n    return this.queryByRole('button', { name: 'Select templates type' });\n  }\n\n  dropDownOption(name) {\n    return this.getByRole('option', { name: new RegExp(`${name}$`, 'i') });\n  }\n\n  get saveTemplateBtn() {\n    return this.getByRole('button', { name: 'Save current page as template' });\n  }\n\n  moreBtnByIndex(index) {\n    const moreButtons = this.getAllByRole('button', {\n      name: 'More',\n    });\n    return moreButtons[index];\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/library/text.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from '../container';\n\nexport default class Text extends Container {\n  preset(name) {\n    return this.getByRole('button', { name });\n  }\n\n  get textSetList() {\n    return this.getByRole('group', { name: /Text Set Options/ });\n  }\n\n  get textSets() {\n    return this.getAllByRoleIn(this.textSetList, 'button');\n  }\n\n  textSetFilter(name) {\n    return this.getByRole('option', { name });\n  }\n\n  get smartColorToggle() {\n    return this.getByRole('checkbox', {\n      name: 'Adaptive text colors',\n    });\n  }\n\n  get addStyleButton() {\n    return this.getByRole('button', { name: /Add style/ });\n  }\n\n  get addTextWithStyleButtons() {\n    return this.getAllByRole('button', { name: /Add new text/ });\n  }\n\n  get applyStyleButtons() {\n    return this.getAllByRole('button', { name: /Apply style/ });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/quickActionMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { ACTIONS } from '../../../app/quickActions';\nimport { Container } from './container';\n\nexport class QuickActionMenu extends Container {\n  get changeBackgroundColorButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.CHANGE_BACKGROUND_COLOR.text,\n    });\n  }\n\n  get changeColorButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.CHANGE_COLOR.text,\n    });\n  }\n\n  get insertBackgroundMediaButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.INSERT_BACKGROUND_MEDIA.text,\n    });\n  }\n\n  get insertTextButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.INSERT_TEXT.text,\n    });\n  }\n\n  get replaceMediaButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.REPLACE_MEDIA.text,\n    });\n  }\n\n  get replaceBackgroundMediaButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.REPLACE_BACKGROUND_MEDIA.text,\n    });\n  }\n\n  get addAnimationButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.ADD_ANIMATION.text,\n    });\n  }\n\n  get addLinkButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.ADD_LINK.text,\n    });\n  }\n\n  get addCaptionsButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.ADD_CAPTIONS.text,\n    });\n  }\n\n  get resetElementButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.RESET_ELEMENT.text,\n    });\n  }\n\n  get textColorButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.CHANGE_TEXT_COLOR.text,\n    });\n  }\n\n  get fontButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.CHANGE_FONT.text,\n    });\n  }\n\n  get closeButton() {\n    return this.queryByRole('menuitem', {\n      name: 'Close',\n    });\n  }\n\n  get optionsButton() {\n    return this.queryByRole('menuitem', {\n      name: 'Options',\n    });\n  }\n\n  get disableAudioButton() {\n    return this.queryByRole('menuitem', {\n      name: 'Disable Audio',\n    });\n  }\n\n  get disableVideoButton() {\n    return this.queryByRole('menuitem', {\n      name: 'Disable Video',\n    });\n  }\n\n  get enableAudioButton() {\n    return this.queryByRole('menuitem', {\n      name: 'Enable Audio',\n    });\n  }\n\n  get insertAudioStickerButton() {\n    return this.queryByRole('menuitem', {\n      name: ACTIONS.INSERT_AUDIO_STICKER.text,\n    });\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/containers/sidebar.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Container } from './container';\nimport { DesignPanel } from './designPanel';\nimport { DocumentPanel } from './documentPanel';\nimport { Library } from './library';\n\n/**\n * Sidebar containing tabs and panes for insert, style and document panels.\n */\nexport class Sidebar extends Container {\n  get insertTab() {\n    return this.getByRole('tab', { name: /Insert/ });\n  }\n\n  get insertPanel() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Insert/ }),\n      'library',\n      Library\n    );\n  }\n\n  get designTab() {\n    return this.getByRole('tab', { name: /Style/ });\n  }\n\n  get designPanel() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Style/ }),\n      'designPanel',\n      DesignPanel\n    );\n  }\n\n  get documentTab() {\n    return this.getByRole('tab', { name: /Document/ });\n  }\n\n  get documentPanel() {\n    return this._get(\n      this.getByRole('tabpanel', { name: /Document/ }),\n      'documentPanel',\n      DocumentPanel\n    );\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/getMediaResponse.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default [\n  {\n    baseColor: '#734727',\n    blurHash: 'L9D]rV~X004n9EjF-=WX00ITM^t7',\n    type: 'image',\n    id: 1,\n    src: 'http://localhost:9876/__static__/blue-marble.jpg',\n    alt: 'blue-marble',\n    mimeType: 'image/jpeg',\n    width: 600,\n    height: 600,\n    sizes: {\n      medium: {\n        file: 'blue-marble.jpg',\n        width: 600,\n        height: 600,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/blue-marble.jpg',\n      },\n      thumbnail: {\n        file: 'blue-marble.jpg',\n        width: 600,\n        height: 600,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/blue-marble.jpg',\n      },\n      web_stories_thumbnail: {\n        file: 'blue-marble.jpg',\n        width: 600,\n        height: 600,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/blue-marble.jpg',\n      },\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n  {\n    baseColor: '#734727',\n    blurHash: 'LPJjI_WBjZR+~VR*f6oL?GNHj[s,',\n    type: 'image',\n    id: 2,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/curiosity.jpg',\n    },\n    src: 'http://localhost:9876/__static__/curiosity.jpg',\n    title: {\n      raw: 'curiosity',\n    },\n    description: {\n      raw: '',\n    },\n    alt: 'curiosity',\n    mimeType: 'image/jpeg',\n    featuredMediaSrc: {},\n    posterId: 0,\n    width: 953,\n    height: 1280,\n    sizes: {\n      medium: {\n        file: 'curiosity.jpg',\n        width: 953,\n        height: 1280,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/curiosity.jpg',\n      },\n      thumbnail: {\n        file: 'curiosity.jpg',\n        width: 953,\n        height: 1280,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/curiosity.jpg',\n      },\n      web_stories_thumbnail: {\n        file: 'curiosity.jpg',\n        width: 953,\n        height: 1280,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/curiosity.jpg',\n      },\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n  {\n    baseColor: '#734727',\n    blurHash: 'L4BM_PIU00%MD%M{j[xu00%M~qM{',\n    type: 'image',\n    id: 3,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/earth.jpg',\n    },\n    src: 'http://localhost:9876/__static__/earth.jpg',\n    title: {\n      raw: 'earth',\n    },\n    description: {\n      raw: '',\n    },\n    alt: 'earth',\n    mimeType: 'image/jpeg',\n    featuredMediaSrc: {},\n    posterId: 0,\n    width: 640,\n    height: 529,\n    sizes: {\n      medium: {\n        file: 'earth.jpg',\n        width: 640,\n        height: 529,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/earth.jpg',\n      },\n      thumbnail: {\n        file: 'earth.jpg',\n        width: 640,\n        height: 529,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/earth.jpg',\n      },\n      web_stories_thumbnail: {\n        file: 'earth.jpg',\n        width: 640,\n        height: 529,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/earth.jpg',\n      },\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n  {\n    baseColor: '#734727',\n    blurHash: 'LA6tp]0M~U4;E3%1IpxsRls.WXjZ',\n    type: 'image',\n    id: 4,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/saturn.jpg',\n    },\n    src: 'http://localhost:9876/__static__/saturn.jpg',\n    title: {\n      raw: 'saturn',\n    },\n    description: {\n      raw: '',\n    },\n    alt: 'saturn',\n    mimeType: 'image/jpeg',\n    featuredMediaSrc: {},\n    posterId: 0,\n    width: 634,\n    height: 640,\n    sizes: {\n      medium: {\n        file: 'saturn.jpg',\n        width: 634,\n        height: 640,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/saturn.jpg',\n      },\n      thumbnail: {\n        file: 'saturn.jpg',\n        width: 634,\n        height: 640,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/saturn.jpg',\n      },\n      web_stories_thumbnail: {\n        file: 'saturn.jpg',\n        width: 634,\n        height: 640,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/saturn.jpg',\n      },\n    },\n    meta: {\n      web_stories_is_poster: false,\n      web_stories_poster_id: 0,\n      web_stories_trim_data: {},\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n  {\n    baseColor: '#46372e',\n    blurHash: 'L8B{u=^j00E2s,oeW=WC009b~V%0',\n    type: 'image',\n    id: 5,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/mars.jpg',\n    },\n    src: 'http://localhost:9876/__static__/mars.jpg',\n    alt: 'mars',\n    mimeType: 'image/jpeg',\n    featuredMediaSrc: {},\n    posterId: 0,\n    width: 540,\n    height: 810,\n    sizes: {\n      medium: {\n        file: 'mars.jpg',\n        width: 540,\n        height: 810,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/mars.jpg',\n      },\n      thumbnail: {\n        file: 'mars.jpg',\n        width: 540,\n        height: 810,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/mars.jpg',\n      },\n      web_stories_thumbnail: {\n        file: 'mars.jpg',\n        width: 540,\n        height: 810,\n        mimeType: 'image/jpeg',\n        sourceUrl: 'http://localhost:9876/__static__/mars.jpg',\n      },\n    },\n    meta: {\n      web_stories_is_poster: false,\n      web_stories_poster_id: 0,\n      web_stories_trim_data: {},\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n  {\n    baseColor: '#484846',\n    blurHash: 'LHBzC3~q4n00RjRja{t79FM{xuxu',\n    type: 'video',\n    id: 6,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/ranger9.ogg',\n    },\n    src: 'http://localhost:9876/__static__/ranger9.ogg',\n    alt: 'ranger9',\n    poster: 'http://localhost:9876/__static__/ranger9.png',\n    mimeType: 'video/ogg',\n    posterId: 106,\n    length: 6,\n    lengthFormatted: '0:06',\n    width: 640,\n    height: 480,\n    sizes: {},\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n    trimData: {\n      original: 0,\n    },\n  },\n  {\n    baseColor: '#734727',\n    blurHash: 'LF9HFU00IV~qxvM{tRaxMxxuWARk',\n    type: 'video',\n    id: 7,\n    src: 'http://localhost:9876/__static__/asteroid.ogg',\n    alt: 'asteroid',\n    mimeType: 'video/ogg',\n    poster: 'http://localhost:9876/__static__/asteroid.png',\n    posterId: 106,\n    length: 8,\n    lengthFormatted: '0:08',\n    width: 640,\n    height: 360,\n    sizes: {},\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n    trimData: {\n      original: 0,\n    },\n  },\n  {\n    baseColor: '#ffffff',\n    blurHash: 'LE97nm00IV~qx]M_t8j?MyxuWARk',\n    type: 'image',\n    id: 8,\n    guid: {\n      rendered: 'http://localhost:9876/__static__/transparent.png',\n    },\n    src: 'http://localhost:9876/__static__/transparent.png',\n    alt: 'image with transparent background',\n    mimeType: 'image/png',\n    featuredMediaSrc: {},\n    posterId: 0,\n    width: 400,\n    height: 400,\n    sizes: {\n      medium: {\n        file: 'transparent.png',\n        width: 400,\n        height: 400,\n        mimeType: 'image/png',\n        sourceUrl: 'http://localhost:9876/__static__/transparent.png',\n      },\n      thumbnail: {\n        file: 'transparent.png',\n        width: 400,\n        height: 400,\n        mimeType: 'image/png',\n        sourceUrl: 'http://localhost:9876/__static__/transparent.png',\n      },\n      web_stories_thumbnail: {\n        file: 'transparent.png',\n        width: 400,\n        height: 400,\n        mimeType: 'image/png',\n        sourceUrl: 'http://localhost:9876/__static__/transparent.png',\n      },\n    },\n    isPlaceholder: false,\n    isOptimized: false,\n    isMuted: false,\n    isExternal: false,\n  },\n];\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/getProductsResponse.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport default [\n  {\n    productId: 'kt-38',\n    productTitle: 'Logo Collection',\n    productBrand: '',\n    productPrice: 18,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      { url: false, alt: '' },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/logo-collection',\n    },\n    productDetails: 'This is a grouped product.',\n    productUrl: 'http://example.com/product/logo-collection',\n  },\n  {\n    productId: 'kt-138',\n    productTitle: 'Big Logo Collection',\n    productBrand: '',\n    productPrice: 28,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      { url: false, alt: '' },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/logo-collection',\n    },\n    productDetails: 'This is a grouped product.',\n    productUrl: 'http://example.com/product/logo-collection',\n  },\n  {\n    productId: 'kt-139',\n    productTitle: 'Massive Logo Collection',\n    productBrand: '',\n    productPrice: 58,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      { url: false, alt: '' },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/logo-collection',\n    },\n    productDetails: 'This is a grouped product.',\n    productUrl: 'http://example.com/product/logo-collection',\n  },\n  {\n    productId: 'kt-39',\n    productTitle: 'WordPress Pennant',\n    productBrand: '',\n    productPrice: 11.05,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/wordpress-pennant',\n    },\n    productDetails: 'This is an external product.',\n    productUrl: 'http://example.com/product/wordpress-pennant',\n  },\n  {\n    productId: 'kt-36',\n    productTitle: 'T-Shirt with Logo',\n    productBrand: '',\n    productPrice: 18,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/t-shirt-with-logo',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://example.com/product/t-shirt-with-logo',\n  },\n  {\n    productId: 'kt-37',\n    productTitle: 'Beanie with Logo',\n    productBrand: '',\n    productPrice: 18,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      { url: false, alt: '' },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/beanie-with-logo',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://example.com/product/beanie-with-logo',\n  },\n  {\n    productId: 'kt-28',\n    productTitle: 'Album',\n    productBrand: '',\n    productPrice: 15,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/album',\n    },\n    productDetails: 'This is a simple, virtual product.',\n    productUrl: 'http://example.com//product/album',\n  },\n  {\n    productId: 'kt-29',\n    productTitle: 'Single',\n    productBrand: '',\n    productPrice: 2,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/beach.jpg',\n        alt: '',\n      },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://example.com/product/single',\n    },\n    productDetails: 'This is a simple, virtual product.',\n    productUrl: 'http://example.com/product/single',\n  },\n  {\n    productId: 'kt-25',\n    productTitle: 'Hoodie with Pocket',\n    productBrand: '',\n    productPrice: 35,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-pocket/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-pocket/',\n  },\n  {\n    productId: 'kt-26',\n    productTitle: 'Hoodie with Zipper',\n    productBrand: '',\n    productPrice: 45,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-zipper/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-zipper/',\n  },\n  {\n    productId: 'kt-18',\n    productTitle: 'Hoodie',\n    productBrand: '',\n    productPrice: 42,\n    productPriceCurrency: 'USD',\n    productImages: [\n      {\n        url: 'http://localhost:9876/__static__/saturn.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/saturn.jpg',\n        alt: '',\n      },\n      {\n        url: 'http://localhost:9876/__static__/saturn.jpg',\n        alt: '',\n      },\n    ],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie/',\n    },\n    productDetails: 'This is a variable product.',\n    productUrl: 'http://localhost:10004/product/hoodie/',\n  },\n  {\n    productId: 'kt-19',\n    productTitle: 'Hoodie with Logo',\n    productBrand: '',\n    productPrice: 45,\n    productPriceCurrency: 'USD',\n    productImages: [],\n    aggregateRating: {\n      ratingValue: 0,\n      reviewCount: 0,\n      reviewUrl: 'http://localhost:10004/product/hoodie-with-logo/',\n    },\n    productDetails: 'This is a simple product.',\n    productUrl: 'http://localhost:10004/product/hoodie-with-logo/',\n  },\n];\n\nfunction compareStrings(key, order = 'asc') {\n  return (a, b) => {\n    const comparison = a[key].localeCompare(b[key]);\n    return order === 'desc' ? comparison * -1 : comparison;\n  };\n}\n\nexport const sortStrings = (obj, key, order) => {\n  return obj.sort(compareStrings(key, order));\n};\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/getTaxonomiesResponse.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default [\n  {\n    name: 'Categories',\n    slug: 'web_story_category',\n    capabilities: {\n      manage_terms: 'manage_categories',\n      edit_terms: 'manage_categories',\n      delete_terms: 'manage_categories',\n      assign_terms: 'edit_posts',\n    },\n    description: 'Story Categories',\n    labels: {\n      name: 'Categories',\n      singularName: 'Category',\n      searchItems: 'Search Categories',\n      popularItems: null,\n      allItems: 'All Categories',\n      parentItem: 'Parent Category',\n      parentItemColon: 'Parent Category:',\n      editItem: 'Edit Category',\n      viewItem: 'View Category',\n      updateItem: 'Update Category',\n      addNewItem: 'Add New Category',\n      newItemName: 'New Category Name',\n      separateItemsWithCommas: null,\n      addOrRemoveItems: null,\n      chooseFromMostUsed: null,\n      notFound: 'No categories found.',\n      noTerms: 'No categories',\n      filterByItem: 'Filter by category',\n      itemsListNavigation: 'Categories list navigation',\n      itemsList: 'Categories list',\n      mostUsed: 'Most Used',\n      backToItems: '&larr; Go to Categories',\n      itemLink: 'Category Link',\n      itemLinkDescription: 'A link to a category.',\n      menuName: 'Categories',\n      nameAdminBar: 'story-category',\n    },\n    types: ['web-story'],\n    showCloud: true,\n    hierarchical: true,\n    restBase: 'web_story_category',\n    visibility: {\n      public: true,\n      publicly_queryable: true,\n      show_admin_column: false,\n      show_in_nav_menus: true,\n      show_in_quick_edit: true,\n      show_ui: true,\n    },\n    restPath: 'http://localhost:8899/wp-json/wp/v2/web_story_category',\n  },\n  {\n    name: 'Tags',\n    slug: 'web_story_tag',\n    capabilities: {\n      manage_terms: 'manage_categories',\n      edit_terms: 'manage_categories',\n      delete_terms: 'manage_categories',\n      assign_terms: 'edit_posts',\n    },\n    description: 'Story Tags',\n    labels: {\n      name: 'Tags',\n      singularName: 'Tag',\n      searchItems: 'Search Tags',\n      popularItems: 'Popular Tags',\n      allItems: 'All Tags',\n      parentItem: null,\n      parentItemColon: null,\n      editItem: 'Edit Tag',\n      viewItem: 'View Tag',\n      updateItem: 'Update Tag',\n      addNewItem: 'Add New Tag',\n      newItemName: 'New Tag Name',\n      separateItemsWithCommas: 'Separate tags with commas',\n      addOrRemoveItems: 'Add or remove tags',\n      chooseFromMostUsed: 'Choose from the most used tags',\n      notFound: 'No tags found.',\n      noTerms: 'No tags',\n      filterByItem: null,\n      itemsListNavigation: 'Tags list navigation',\n      itemsList: 'Tags list',\n      mostUsed: 'Most Used',\n      backToItems: '&larr; Go to Tags',\n      itemLink: 'Tag Link',\n      itemLinkDescription: 'A link to a tag.',\n      menuName: 'Tags',\n      nameAdminBar: 'web_story_tag',\n    },\n    types: ['web-story'],\n    showCloud: true,\n    hierarchical: false,\n    restBase: 'web_story_tag',\n    visibility: {\n      public: true,\n      publicly_queryable: true,\n      show_admin_column: false,\n      show_in_nav_menus: true,\n      show_in_quick_edit: true,\n      show_ui: true,\n    },\n    restPath: 'http://localhost:8899/wp-json/web-stories/v1/web_story_tag',\n  },\n  {\n    name: 'Colors',\n    slug: 'story_color',\n    capabilities: {\n      manage_terms: 'manage_categories',\n      edit_terms: 'manage_categories',\n      delete_terms: 'manage_categories',\n      assign_terms: 'edit_posts',\n    },\n    description: 'Story Colors',\n    labels: {\n      name: 'Colors',\n      singularName: 'Color',\n      searchItems: 'Search Colors',\n      popularItems: 'Popular Colors',\n      allItems: 'All Colors',\n      parentItem: null,\n      parentItemColon: null,\n      editItem: 'Edit Color',\n      viewItem: 'View Color',\n      updateItem: 'Update Color',\n      addNewItem: 'Add New Color',\n      newItemName: 'New Color Name',\n      separateItemsWithCommas: 'Separate colors with commas',\n      addOrRemoveItems: 'Add or remove colors',\n      chooseFromMostUsed: 'Choose from the most used colors',\n      notFound: 'No colors found.',\n      noTerms: 'No colors',\n      filterByItem: null,\n      itemsListNavigation: 'Colors list navigation',\n      itemsList: 'Colors list',\n      mostUsed: 'Most Used',\n      backToItems: '&larr; Go to Colors',\n      itemLink: 'Color Color',\n      itemLinkDescription: 'A link to a color.',\n      menuName: 'Colors',\n      nameAdminBar: 'Color',\n      archives: 'All Colors',\n    },\n    types: ['web-story'],\n    showCloud: true,\n    hierarchical: false,\n    restBase: 'story_colors',\n    visibility: {\n      public: true,\n      publicly_queryable: true,\n      show_admin_column: false,\n      show_in_nav_menus: true,\n      show_in_quick_edit: true,\n      show_ui: true,\n    },\n    restPath: 'http://localhost:8899/wp-json/wp/v2/story-colors',\n  },\n  {\n    name: 'Verticals',\n    slug: 'story-vertical',\n    capabilities: {\n      manage_terms: 'manage_categories',\n      edit_terms: 'manage_categories',\n      delete_terms: 'manage_categories',\n      assign_terms: 'edit_posts',\n    },\n    description: 'Story Verticals',\n    labels: {\n      name: 'Verticals',\n      singularName: 'Vertical',\n      searchItems: 'Search Verticals',\n      popularItems: null,\n      allItems: 'All Verticals',\n      parentItem: 'Parent Vertical',\n      parentItemColon: 'Parent Vertical:',\n      editItem: 'Edit Vertical',\n      viewItem: 'View Vertical',\n      updateItem: 'Update Vertical',\n      addNewItem: 'Add New Vertical',\n      newItemName: 'New Vertical Name',\n      separateItemsWithCommas: null,\n      addOrRemoveItems: null,\n      chooseFromMostUsed: null,\n      notFound: 'No verticals found.',\n      noTerms: 'No verticals',\n      filterByItem: 'Filter by vertical',\n      itemsListNavigation: 'Verticals list navigation',\n      itemsList: 'Verticals list',\n      mostUsed: 'Most Used',\n      backToItems: '&larr; Go to Verticals',\n      itemLink: 'Color Vertical',\n      itemLinkDescription: 'A link to a vertical.',\n      menuName: 'Verticals',\n      nameAdminBar: 'Vertical',\n      archives: 'All Verticals',\n    },\n    types: ['web-story'],\n    showCloud: true,\n    hierarchical: true,\n    restBase: 'story-verticals',\n    visibility: {\n      public: true,\n      publicly_queryable: true,\n      show_admin_column: false,\n      show_in_nav_menus: true,\n      show_in_quick_edit: true,\n      show_ui: true,\n    },\n    restPath: 'http://localhost:8899/wp-json/web-stories/v1/web_story_category',\n  },\n];\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/getTaxonomyTermResponse.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getTaxonomiesResponse from './getTaxonomiesResponse';\n\nconst defaultResponse = [\n  {\n    id: 4,\n    count: 10,\n    description: '',\n    link: '',\n    name: 'tag',\n    slug: 'tag',\n    taxonomy: 'web_story_tag',\n    meta: [],\n  },\n  {\n    id: 1,\n    count: 3,\n    description: '',\n    link: '',\n    name: 'pizza',\n    slug: 'pizza',\n    taxonomy: 'web_story_tag',\n    meta: [],\n  },\n  {\n    id: 2,\n    count: 2,\n    description: '',\n    link: '',\n    name: 'burger',\n    slug: 'burger',\n    taxonomy: 'web_story_tag',\n    meta: [],\n  },\n  {\n    id: 3,\n    count: 3,\n    description: '',\n    link: '',\n    name: 'frenchFry',\n    slug: 'frenchFry',\n    taxonomy: 'web_story_tag',\n    meta: [],\n  },\n  {\n    id: 11,\n    count: 3,\n    description: '',\n    link: '',\n    name: 'Booger',\n    slug: 'booger',\n    taxonomy: 'web_story_category',\n    meta: [],\n    parent: 0,\n  },\n  {\n    id: 12,\n    count: 3,\n    description: '',\n    link: '',\n    name: 'Multiple words',\n    slug: 'multiple-words',\n    taxonomy: 'web_story_category',\n    meta: [],\n    parent: 0,\n  },\n  {\n    id: 13,\n    count: 3,\n    description: '',\n    link: '',\n    name: 'gold',\n    slug: 'gold',\n    taxonomy: 'web_story_category',\n    meta: [],\n    parent: 0,\n  },\n];\n\nconst categoryRestPath = getTaxonomiesResponse.find(\n  ({ slug }) => slug === 'web_story_category'\n).restPath;\n\nconst tagRestPath = getTaxonomiesResponse.find(\n  ({ slug }) => slug === 'web_story_tag'\n).restPath;\n\nexport default function generateResponse(endpoint) {\n  if (endpoint === categoryRestPath) {\n    return defaultResponse.filter(\n      ({ taxonomy }) => taxonomy === 'web_story_category'\n    );\n  } else if (endpoint === tagRestPath) {\n    return defaultResponse.filter(\n      ({ taxonomy }) => taxonomy === 'web_story_tag'\n    );\n  } else {\n    return defaultResponse;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/singleSavedTemplate.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst savedPageTemplate = {\n  elements: [\n    {\n      opacity: 100,\n      flip: { vertical: false, horizontal: false },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n      x: 1,\n      y: 1,\n      width: 1,\n      height: 1,\n      mask: { type: 'rectangle' },\n      isBackground: true,\n      isDefaultBackground: true,\n      type: 'shape',\n      id: '0243c16d-5c13-48b7-b297-7608eba36119',\n    },\n    {\n      opacity: 100,\n      flip: { vertical: false, horizontal: false },\n      rotationAngle: 0,\n      lockAspectRatio: true,\n      backgroundTextMode: 'NONE',\n      font: {\n        family: 'Roboto',\n        weights: [100, 300, 400, 500, 700, 900],\n        styles: ['italic', 'regular'],\n        variants: [\n          [0, 100],\n          [1, 100],\n          [0, 300],\n          [1, 300],\n          [0, 400],\n          [1, 400],\n          [0, 500],\n          [1, 500],\n          [0, 700],\n          [1, 700],\n          [0, 900],\n          [1, 900],\n        ],\n        fallbacks: ['Helvetica Neue', 'Helvetica', 'sans-serif'],\n        service: 'fonts.google.com',\n        metrics: {\n          upm: 2048,\n          asc: 1900,\n          des: -500,\n          tAsc: 1536,\n          tDes: -512,\n          tLGap: 102,\n          wAsc: 1946,\n          wDes: 512,\n          xH: 1082,\n          capH: 1456,\n          yMin: -555,\n          yMax: 2163,\n          hAsc: 1900,\n          hDes: -500,\n          lGap: 0,\n        },\n      },\n      fontSize: 16.2,\n      backgroundColor: { color: { r: 196, g: 196, b: 196 } },\n      lineHeight: 1.5,\n      textAlign: 'center',\n      padding: { vertical: 0, horizontal: 0, locked: true },\n      type: 'text',\n      content: 'Fill in some text',\n      borderRadius: {\n        locked: true,\n        topLeft: 2,\n        topRight: 2,\n        bottomRight: 2,\n        bottomLeft: 2,\n      },\n      x: 40,\n      y: 299,\n      width: 165,\n      height: 19,\n      scale: 100,\n      focalX: 50,\n      focalY: 50,\n      id: '139acf63-c442-4d07-9360-059df047b5e9',\n    },\n  ],\n  backgroundColor: { color: { r: 255, g: 255, b: 255 } },\n  type: 'page',\n  id: 'c8265226-4c4c-4827-b860-61506be619b6',\n  title: { rendered: 'Template name', raw: 'Template name' },\n};\n\nexport default savedPageTemplate;\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/db/storyResponse.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { DATA_VERSION } from '@googleforcreators/migration';\n\nconst storyTags = [\n  {\n    id: 1,\n    link: 'http://localhost:8899/web_story_tag/gold/pizza',\n    name: 'pizza',\n    slug: 'pizza',\n    taxonomy: 'web_story_tag',\n  },\n  {\n    id: 2,\n    link: 'http://localhost:8899/web_story_tag/burger',\n    name: 'burger',\n    slug: 'burger',\n    taxonomy: 'web_story_tag',\n  },\n  {\n    id: 3,\n    link: 'http://localhost:8899/web_story_tag/frenchFry',\n    name: 'frenchFry',\n    slug: 'frenchFry',\n    taxonomy: 'web_story_tag',\n  },\n];\nconst storyVerticals = [];\nconst storyColors = [];\nconst storyCategories = [\n  {\n    id: 11,\n    link: 'http://localhost:8899/web_story_category/booger',\n    name: 'Booger',\n    slug: 'booger',\n    taxonomy: 'web_story_category',\n    parent: 0,\n  },\n  {\n    id: 12,\n    link: 'http://localhost:8899/web_story_category/multiple-words',\n    name: 'Multiple words',\n    slug: 'multiple-words',\n    taxonomy: 'web_story_category',\n    parent: 0,\n  },\n  {\n    id: 13,\n    link: 'http://localhost:8899/web_story_category/gold',\n    name: 'gold',\n    slug: 'gold',\n    taxonomy: 'web_story_category',\n    parent: 0,\n  },\n];\n\nexport default {\n  title: { raw: '' },\n  status: 'draft',\n  slug: '',\n  date: '2020-05-06T22:32:37',\n  dateGmt: '2020-05-06T22:32:37',\n  modified: '2020-05-06T22:32:37',\n  excerpt: { raw: '' },\n  link: 'http://stories.local/?post_type=web-story&p=1',\n  previewLink: 'http://stories.local/?post_type=web-story&p=1',\n  storyData: {\n    version: DATA_VERSION,\n    pages: [],\n  },\n  permalinkTemplate: 'http://stories3.local/stories/%pagename%/',\n  stylePresets: { textStyles: [], colors: [] },\n  password: '',\n  author: { id: 1, name: 'John Doe' },\n  capabilities: {\n    publish: true,\n    'assign-author': true,\n    'assign-web_story_tag': true,\n    'create-web_story_tag': true,\n    'assign-web_story_category': true,\n    'create-web_story_category': true,\n  },\n  featuredMedia: {\n    id: 0,\n    height: 0,\n    width: 0,\n    url: '',\n  },\n  publisherLogo: {\n    id: 0,\n    height: 0,\n    width: 0,\n    url: 'http://stories.local/wp-content/plugins/web-stories/assets/images/logo.png',\n  },\n  taxonomies: [\n    {\n      taxonomy: 'web-story_tag',\n      embeddable: true,\n      href: 'http://localhost:8899/wp-json/web-stories/v1/web_story_tag?post=1014',\n    },\n    {\n      taxonomy: 'web-story_category',\n      embeddable: true,\n      href: 'http://localhost:8899/wp-json/web-stories/v1/web_story_category?post=1014',\n    },\n  ],\n  terms: [...storyTags, ...storyColors, ...storyCategories, ...storyVerticals],\n};\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/fixture.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  configure,\n  render,\n  act,\n  screen,\n  waitFor,\n} from '@testing-library/react';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  setAppElement,\n} from '@googleforcreators/design-system';\nimport { FixtureEvents } from '@googleforcreators/karma-fixture';\nimport { DATA_VERSION } from '@googleforcreators/migration';\nimport {\n  createPage,\n  TEXT_ELEMENT_DEFAULT_FONT,\n  registerElementType,\n} from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport StoryEditor from '../../storyEditor';\nimport APIProvider from '../../app/api/apiProvider';\nimport APIContext from '../../app/api/context';\nimport Layout from '../../components/layout';\nimport formattedTemplatesArray from '../../dataUtils/formattedTemplatesArray';\nimport { PRESET_TYPES } from '../../constants';\nimport getMediaResponse from './db/getMediaResponse';\nimport getProductsResponse, { sortStrings } from './db/getProductsResponse';\nimport { Editor as EditorContainer } from './containers';\nimport taxonomiesResponse from './db/getTaxonomiesResponse';\nimport singleSavedTemplate from './db/singleSavedTemplate';\nimport HeaderLayout from './components/header';\nimport storyResponse from './db/storyResponse';\nimport DocumentPane, {\n  PublishModalDocumentPane,\n} from './components/documentPane';\nimport { Accessibility, Design, Priority } from './components/checklist';\nimport generateTaxonomiesResponse from './db/getTaxonomyTermResponse';\n\nconst React = require('react');\nconst { useCallback, useState, useMemo, forwardRef } = React;\n\nif ('true' === WEB_STORIES_CI) {\n  configure({\n    getElementError: (message) => {\n      const error = new Error(message);\n      error.name = 'TestingLibraryElementError';\n      error.stack = null;\n      return error;\n    },\n    asyncUtilTimeout: 5000,\n  });\n}\n\nexport const MEDIA_PER_PAGE = 20;\nexport const LOCAL_MEDIA_PER_PAGE = 50;\n\nfunction MediaUpload({ render: _render, onSelect }) {\n  const open = () => {\n    const image = {\n      type: 'image',\n      src: 'http://localhost:9876/__static__/saturn.jpg',\n      baseColor: '#734727',\n      id: 4,\n      guid: {\n        rendered: 'http://localhost:9876/__static__/saturn.jpg',\n      },\n      alt: 'saturn',\n      mimeType: 'image/jpeg',\n      width: 634,\n      height: 640,\n    };\n    onSelect(image);\n  };\n\n  return _render(open);\n}\n\nexport const FIXTURE_DEFAULT_CONFIG = {\n  storyId: 1,\n  allowedMimeTypes: {\n    audio: ['audio/mpeg', 'audio/aac', 'audio/wav', 'audio/ogg'],\n    image: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'],\n    caption: ['text/vtt'],\n    vector: ['image/svg+xml'],\n    video: ['video/mp4', 'video/webm'],\n  },\n  capabilities: {\n    hasUploadMediaAction: true,\n  },\n  nonce: '123456789',\n  version: '1.0.0-alpha.9',\n  isRTL: false,\n  showMedia3p: true,\n  canViewDefaultTemplates: true,\n  locale: {\n    dateFormat: 'F j, Y',\n    timeFormat: 'g:i a',\n    gmtOffset: -4,\n    timezone: 'America/New_York',\n    weekStartsOn: 0,\n  },\n  shoppingProvider: 'karma',\n  flags: {},\n  MediaUpload,\n};\n\n/**\n * The fixture mainly follows the `@testing-library/react` library pattern, but\n * in the scope of the whole editor and the real browser. As such:\n *\n * - Call `set` and `stub` methods to configure the fixture before calling\n * the `render()` method.\n * - Call the `fixture.render()` method similarly to the\n * `@testing-library/react`'s `render()` before doing the actual tests.\n * - Call the `fixture.renderHook()` method similarly to the\n * `@testing-library/react`'s `renderHook()` to render a hook in the context\n * of the whole editor. A more fine-grained `renderHook()` can also be called\n * on a component stub. See the `fixture.stubComponent()` for more info.\n * - Call the `await fixture.act()` method similarly to the\n * `@testing-library/react`'s `act()` method for any action. Notice that events\n * automatically use `act()` internally.\n * - Call the `await fixture.events` methods to drive the events similarly\n * to the `@testing-library/react`'s `fireEvent`, except that these events will\n * be executed natively in the browser.\n *\n * Network calls are mocked out in the `APIProviderFixture` but can be\n * overridden by passing `mocks` when initializing the fixture\n * Ex: `new Fixture({ mocks: { getCurrentUser: noop, updateCurrentUser: noop } })\n */\nexport class Fixture {\n  /**\n   *\n   * @param {Object} config The configuration object\n   * @param {Object} config.mocks An object containing functions to be used as stubs for the api.\n   */\n  constructor({ mocks } = {}) {\n    this._config = { ...FIXTURE_DEFAULT_CONFIG };\n\n    this._componentStubs = new Map();\n    const origCreateElement = React.createElement;\n    //eslint-disable-next-line jasmine/no-unsafe-spy\n    spyOn(React, 'createElement').and.callFake((type, props, ...children) => {\n      if (!props?._wrapped) {\n        const stubs = this._componentStubs.get(type);\n        if (stubs) {\n          const match = stubs.find((stub) => {\n            if (!stub._matcher) {\n              return true;\n            }\n            return stub._matcher(props);\n          });\n          if (match) {\n            type = match._wrapper;\n          }\n        }\n      }\n      return origCreateElement(type, props, ...children);\n    });\n\n    this.apiProviderFixture_ = new APIProviderFixture({ mocks });\n    this.stubComponent(APIProvider).callFake(\n      this.apiProviderFixture_.Component\n    );\n\n    this._layoutStub = this.stubComponent(Layout);\n\n    this._events = new FixtureEvents(this.act.bind(this));\n\n    this._container = null;\n\n    this._editor = null;\n\n    const panels = [\n      'animation',\n      'borderStyle',\n      'captions',\n      'globalStoryStyles',\n      'colorPresets',\n      'filter',\n      'imageAccessibility',\n      'link',\n      'pageAttachment',\n      'pageBackground',\n      'videoPoster',\n      'size',\n      'shapeStyle',\n      'text',\n      'textBox',\n      'textStyle',\n      'videoOptions',\n      'videoAccessibility',\n      'elementAlignment',\n      'noselection',\n      'publishing',\n      'status',\n      `stylepreset-${PRESET_TYPES.STYLE}`,\n    ];\n    // Open all panels by default.\n    panels.forEach((panel) => {\n      localStorage.setItem(\n        `web_stories_ui_panel_settings:${panel}`,\n        JSON.stringify({ isCollapsed: false })\n      );\n    });\n\n    // Hide Floating Menu by default, it obstructs too many elements.\n    localStorage.setItem(\n      LOCAL_STORAGE_PREFIX.ELEMENT_TOOLBAR_SETTINGS,\n      JSON.stringify({ isDisplayed: false })\n    );\n\n    elementTypes.forEach(registerElementType);\n  }\n\n  restore() {\n    window.location.hash = '#';\n    localStorage.clear();\n  }\n\n  get container() {\n    return this._container;\n  }\n\n  get document() {\n    return this._container.ownerDocument;\n  }\n\n  get screen() {\n    return this._screen;\n  }\n\n  get editor() {\n    return this._editor;\n  }\n\n  /**\n   * A fixture utility to fire native browser events. See `FixtureEvents` for\n   * more info.\n   *\n   * @return {FixtureEvents} fixture events that are executed on the native\n   * browser.\n   */\n  get events() {\n    return this._events;\n  }\n\n  /**\n   * Stubs a component. Can be used to render hooks on this component's level\n   * or even to completely replace the implementation of the component.\n   *\n   * All components must be stubbed before the `fixture.render()` is called.\n   *\n   * Use sparingly. See `ComponentStub` for more info.\n   *\n   * @param {Function} component Component to stub.\n   * @param {Function|undefined} matcher Matcher.\n   * @return {ComponentStub} The component's stub.\n   */\n  stubComponent(component, matcher) {\n    const stub = new ComponentStub(this, component, matcher);\n    let stubs = this._componentStubs.get(component);\n    if (!stubs) {\n      stubs = [];\n      this._componentStubs.set(component, stubs);\n    }\n    stubs.push(stub);\n    return stub;\n  }\n\n  /**\n   * Set the feature flags. See `flags.js` for the list of flags.\n   *\n   * For instance, to enable a flag in your test call `setFlags` before\n   * calling the `render()` method:\n   * ```\n   * beforeEach(async () => {\n   *   fixture = new Fixture();\n   *   fixture.setFlags({FEATURE_NAME: true});\n   *   await fixture.render();\n   * });\n   * ```\n   *\n   * @param {Object} flags Flags.\n   */\n  setFlags(flags) {\n    this._flags = { ...this._config.flags, ...flags };\n    this._config.flags = this._flags;\n  }\n\n  setConfig(config) {\n    this._config = { ...this._config, ...config };\n  }\n\n  /**\n   * @param {Array<Object>} pages Pages.\n   */\n  setPages(pages) {\n    this.apiProviderFixture_.setPages(pages);\n  }\n\n  /**\n   * Renders the editor similarly to the `@testing-library/react`'s `render()`\n   * method.\n   *\n   * @return {Promise} Yields when the editor rendering is complete.\n   */\n  async render() {\n    const root = document.querySelector('test-root');\n    root.setAttribute('dir', this._config.isRTL ? 'rtl' : 'ltr');\n\n    // see http://reactcommunity.org/react-modal/accessibility/\n    setAppElement(root);\n\n    const { container, getByRole } = render(\n      <StoryEditor key={Math.random()} config={this._config}>\n        <Layout\n          header={<HeaderLayout />}\n          footer={{\n            secondaryMenu: {\n              checklist: {\n                Priority,\n                Design,\n                Accessibility,\n              },\n            },\n          }}\n          sidebarTabs={{\n            document: {\n              title: 'Document',\n              Pane: DocumentPane,\n            },\n            publishModal: {\n              DocumentPane: PublishModalDocumentPane,\n            },\n          }}\n        />\n      </StoryEditor>,\n      {\n        container: root,\n      }\n    );\n    // The editor should always be given 100%:100% size. The testing-library\n    // renders an extra container so it should be given the same size.\n    container.style.width = '100%';\n    container.style.height = '100%';\n    this._container = container;\n    this._screen = screen;\n\n    this._editor = new EditorContainer(\n      getByRole('region', { name: 'Web Stories Editor' }),\n      'editor'\n    );\n\n    // wait for the media gallery items to load, as many tests assume they're\n    // there\n    let mediaElements;\n    await waitFor(\n      () => {\n        mediaElements = this.querySelectorAll('[data-testid^=mediaElement]');\n        if (!mediaElements?.length) {\n          throw new Error(\n            `Not ready: only found ${mediaElements?.length} media elements`\n          );\n        }\n      },\n      { timeout: 5000 }\n    );\n\n    // Check to see if Google Sans font is loaded.\n    await waitFor(async () => {\n      const weights = ['400', '700'];\n      const font = '12px \"Google Sans\"';\n      const fonts = weights.map((weight) => `${weight} ${font}`);\n      await Promise.all(\n        fonts.map((thisFont) => document.fonts.load(thisFont, ''))\n      );\n      fonts.forEach((thisFont) => {\n        if (!document.fonts.check(thisFont, '')) {\n          throw new Error('Not ready: Google Sans font could not be loaded');\n        }\n      });\n    });\n  }\n\n  /**\n   * Tells the fixture to close the help center\n   * which will default to open the first time the fixture renders.\n   *\n   * @return {Promise<Object>} Resolves when help center toggle is clicked.\n   */\n  collapseHelpCenter() {\n    const { _editor, _events } = this;\n    if (!_editor || !_events) {\n      throw new Error('Not ready: Help Center unable to collapse');\n    }\n\n    const { toggleButton } = _editor.helpCenter;\n\n    return _events.click(toggleButton);\n  }\n\n  /**\n   * Floating menu is hidden by default, this will make it visible.\n   *\n   * @return {Promise<Object>} Resolves when floating menu show button is clicked.\n   */\n  showFloatingMenu() {\n    return this._events.click(\n      screen.getByRole('button', { name: /Show element toolbar/ })\n    );\n  }\n\n  /**\n   * Calls a hook in the context of the whole editor.\n   *\n   * Similar to the `@testing-library/react`'s `renderHook()` method.\n   *\n   * @param {Function} func The hook function. E.g. `useStory`.\n   * @return {Promise<Object>} Resolves when the hook is rendered with the\n   * value of the hook.\n   */\n  renderHook(func) {\n    return this._layoutStub.renderHook(func);\n  }\n\n  /**\n   * Calls the specified callback and performs rendering actions on the\n   * whole editor.\n   *\n   * Similar to the `@testing-library/react`'s `act()` method.\n   *\n   * @param {Function} callback Callback.\n   * @return {Promise<Object>} Yields when the `act()` and all related\n   * editor rendering activity is complete. Resolves to the result of the\n   * callback.\n   */\n  act(callback) {\n    return actPromise(callback);\n  }\n\n  /**\n   * To be deprecated.\n   *\n   * @param {string} selector Selector.\n   * @return {Element|null} The found element or null.\n   */\n  querySelector(selector) {\n    return this._container.querySelector(selector);\n  }\n\n  /**\n   * To be deprecated?\n   *\n   * @param {string} selector Selector.\n   * @return {Array.<Element>} The potentially empty list of found elements.\n   */\n  querySelectorAll(selector) {\n    return this._container.querySelectorAll(selector);\n  }\n\n  /**\n   * @param {Element} element Element.\n   * @return {Promise} Yields when the element is displayed on the screen.\n   */\n  waitOnScreen(element) {\n    return new Promise((resolve) => {\n      const io = new IntersectionObserver((records) => {\n        records.forEach((record) => {\n          if (record.isIntersecting) {\n            resolve();\n            io.disconnect();\n          }\n        });\n      });\n      io.observe(element);\n    });\n  }\n\n  /**\n   * Makes a DOM snapshot of the current editor state. Karma must be run\n   * with the `--snapshots` option for the snapshotting to be enabled. When\n   * enabled, all snapshots are stored in the `/.test_artifacts/karma_snapshots`\n   * directory.\n   *\n   * @param {string} name Snapshot name.\n   * @return {Promise} Yields when the snapshot is completed.\n   */\n  snapshot(name) {\n    return karmaSnapshot(name);\n  }\n}\n\n/**\n * A component stub. Allows two main features:\n * 1. Mock a component's implementation.\n * 2. Execute a hook against a component.\n */\nclass ComponentStub {\n  constructor(fixture, Component, matcher) {\n    this._fixture = fixture;\n    this._matcher = matcher;\n    this._implementation = null;\n\n    this._props = null;\n\n    let setRefresher;\n    this._refresh = () => {\n      act(() => {\n        if (setRefresher) {\n          setRefresher((v) => v + 1);\n        }\n      });\n    };\n\n    const pendingHooks = [];\n    this._pushPendingHook = (func) => {\n      let resolver;\n      const promise = new Promise((resolve) => {\n        resolver = resolve;\n      });\n      pendingHooks.push(() => {\n        const result = func();\n        resolver(result);\n      });\n      this._refresh();\n      return promise;\n    };\n\n    const Wrapper = forwardRef((props, ref) => {\n      this._props = props;\n\n      const [refresher, setRefresherInternal] = useState(0);\n      setRefresher = setRefresherInternal;\n      const hooks = useMemo(\n        () => {\n          const hooksToExecute = pendingHooks.slice(0);\n          pendingHooks.length = 0;\n          return hooksToExecute;\n        },\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [refresher]\n      );\n\n      const Impl = useMemo(\n        () => {\n          if (this._implementation) {\n            const MockImpl = forwardRef((fProps, fRef) =>\n              this._implementation(fProps, fRef)\n            );\n            MockImpl.displayName = `Stub(${\n              Component.displayName || Component.name || ''\n            })`;\n            return MockImpl;\n          }\n          return Component;\n        },\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [refresher]\n      );\n\n      return (\n        <>\n          <HookExecutor key={refresher} hooks={hooks} />\n          <Impl _wrapped ref={ref} {...props} />\n        </>\n      );\n    });\n    Wrapper.displayName = `Mock(${\n      Component.displayName || Component.name || ''\n    })`;\n    this._wrapper = Wrapper;\n  }\n\n  get and() {\n    return this;\n  }\n\n  get props() {\n    return this._props;\n  }\n\n  mockImplementation(implementation) {\n    this._implementation = implementation;\n    this._refresh();\n    return this;\n  }\n\n  callFake(implementation) {\n    return this.mockImplementation(implementation);\n  }\n\n  renderHook(func) {\n    return this._fixture.act(() => this._pushPendingHook(func));\n  }\n}\n\n/* eslint-disable react/prop-types, react/jsx-no-useless-fragment */\nfunction HookExecutor({ hooks }) {\n  hooks.forEach((func) => func());\n  return <></>;\n}\n/* eslint-enable react/prop-types, react/jsx-no-useless-fragment */\n\n/* eslint-disable jasmine/no-unsafe-spy */\nclass APIProviderFixture {\n  /**\n   * @param {Object} config The configuration object\n   * @param {Object} config.mocks function that will be used as a stub. Property name must match the action name exactly.\n   */\n  constructor({ mocks = {} } = {}) {\n    this._pages = [];\n    // begins at 100 because may have mocks have children with ids less than 100\n    this._termAutoIncrementId = 100;\n\n    // eslint-disable-next-line react/prop-types\n    const Comp = ({ children }) => {\n      const getStoryById = useCallback(\n        () =>\n          asyncResponse({\n            ...storyResponse,\n            storyData: {\n              version: DATA_VERSION,\n              pages: this._pages,\n            },\n          }),\n        []\n      );\n\n      const autoSaveById = useCallback(\n        () => jasmine.createSpy('autoSaveById'),\n        []\n      );\n      const saveStoryById = useCallback(\n        () => jasmine.createSpy('saveStoryById'),\n        []\n      );\n\n      const getMedia = useCallback(({ mediaType, searchTerm, pagingNum }) => {\n        const filterByMediaType = mediaType\n          ? ({ mimeType }) => mimeType.startsWith(mediaType)\n          : () => true;\n        const filterBySearchTerm = searchTerm\n          ? ({ alt_text }) => alt_text.includes(searchTerm)\n          : () => true;\n        // Generate 8*13=104 items, 3 pages\n        const clonedMedia = Array(13)\n          .fill(getMediaResponse)\n          .flat()\n          .map((media, i) => ({ ...media, id: i + 1 }));\n        return asyncResponse({\n          data: clonedMedia\n            .slice(\n              (pagingNum - 1) * LOCAL_MEDIA_PER_PAGE,\n              pagingNum * LOCAL_MEDIA_PER_PAGE\n            )\n            .filter(filterByMediaType)\n            .filter(filterBySearchTerm),\n          headers: { totalPages: 3 },\n        });\n      }, []);\n      const uploadMedia = useCallback(\n        () => jasmine.createSpy('uploadMedia'),\n        []\n      );\n      const updateMedia = useCallback(\n        () => jasmine.createSpy('updateMedia'),\n        []\n      );\n\n      const getLinkMetadata = useCallback(\n        () =>\n          asyncResponse({\n            url: 'https://example.com',\n            title: 'Example Site',\n            image: 'example.jpg',\n          }),\n        []\n      );\n\n      const getHotlinkInfo = useCallback((link) => {\n        if (link.endsWith('mp3')) {\n          return asyncResponse({\n            ext: 'mp3',\n            mimeType: 'audio/mp3',\n            type: 'audio',\n            fileName: 'example.mp3',\n          });\n        }\n\n        return asyncResponse({\n          ext: 'jpg',\n          mimeType: 'image/jpeg',\n          type: 'image',\n          fileName: 'example.jpg',\n        });\n      }, []);\n\n      const getProxyUrl = useCallback(\n        () => 'http://localhost:9876/__static__/saturn.jpg',\n        []\n      );\n\n      const getAllStatuses = useCallback(\n        () => jasmine.createSpy('getAllStatuses'),\n        []\n      );\n\n      const users = useMemo(\n        () => [\n          { id: 1, name: 'John Doe' },\n          { id: 2, name: 'Jane Doe' },\n        ],\n        []\n      );\n\n      const getAuthors = useCallback(() => asyncResponse(users), [users]);\n\n      const getCurrentUser = useCallback(\n        () =>\n          asyncResponse({\n            id: 1,\n            trackingOptin: false,\n            onboarding: {},\n            mediaOptimization: true,\n          }),\n        []\n      );\n\n      const updateCurrentUser = useCallback(\n        () =>\n          asyncResponse({\n            id: 1,\n            trackingOptin: false,\n            onboarding: {},\n            mediaOptimization: true,\n          }),\n        []\n      );\n\n      const getStatusCheck = useCallback(\n        () =>\n          asyncResponse({\n            success: true,\n          }),\n        []\n      );\n\n      const getPageTemplates = useCallback(\n        () => asyncResponse(formattedTemplatesArray),\n        []\n      );\n\n      const getCustomPageTemplates = useCallback(\n        () => asyncResponse({ templates: [], hasMore: false }),\n        []\n      );\n      const addPageTemplate = useCallback(\n        () => asyncResponse({ ...singleSavedTemplate, templateId: 123 }),\n        []\n      );\n      const deletePageTemplate = useCallback(() => asyncResponse(), []);\n\n      const getTaxonomyTerm = useCallback((endpoint, args) => {\n        return asyncResponse(generateTaxonomiesResponse(endpoint, args));\n      }, []);\n\n      const createTaxonomyTerm = useCallback((_endpoint, data) => {\n        return asyncResponse({\n          id: this._termAutoIncrementId++,\n          count: 0,\n          description: '',\n          link: '',\n          name: 'random name',\n          slug:\n            data?.name?.toLowerCase().replace(/[\\s./_]/, '-') || 'random-slug',\n          taxonomy: _endpoint.split('/').pop(),\n          parent: 0,\n          meta: [],\n          ...data,\n        });\n      }, []);\n\n      const getTaxonomies = useCallback(\n        () => asyncResponse(taxonomiesResponse),\n        []\n      );\n\n      const getFonts = useCallback((params) => {\n        let fonts = [\n          {\n            name: 'Abel',\n            value: 'Abel',\n            family: 'Abel',\n            fallbacks: ['sans-serif'],\n            weights: [400],\n            styles: ['regular'],\n            variants: [[0, 400]],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 2048,\n              asc: 2006,\n              des: -604,\n              tAsc: 2006,\n              tDes: -604,\n              tLGap: 0,\n              wAsc: 2006,\n              wDes: 604,\n              xH: 1044,\n              capH: 1434,\n              yMin: -604,\n              yMax: 2005,\n              hAsc: 2006,\n              hDes: -604,\n              lGap: 0,\n            },\n          },\n          {\n            name: 'Abhaya Libre',\n            value: 'Abhaya Libre',\n            family: 'Abhaya Libre',\n            fallbacks: ['serif'],\n            weights: [400, 500, 600, 700, 800],\n            styles: ['regular'],\n            variants: [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n            ],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 1024,\n              asc: 860,\n              des: -348,\n              tAsc: 860,\n              tDes: -348,\n              tLGap: 0,\n              wAsc: 860,\n              wDes: 348,\n              yMin: -340,\n              yMax: 856,\n              hAsc: 860,\n              hDes: -348,\n              lGap: 0,\n            },\n          },\n          {\n            value: 'Overpass Regular',\n            name: 'Overpass Regular',\n            family: 'Overpass Regular',\n            fallbacks: ['sans-serif'],\n            weights: [400],\n            styles: ['regular'],\n            variants: [[0, 400]],\n            url: 'https://overpass-30e2.kxcdn.com/overpass-regular.ttf',\n            service: 'custom',\n            metrics: {\n              upm: 1000,\n              asc: 982,\n              des: -284,\n              tAsc: 750,\n              tDes: -250,\n              tLGap: 266,\n              wAsc: 1062,\n              wDes: 378,\n              xH: 511,\n              capH: 700,\n              yMin: -378,\n              yMax: 1062,\n              hAsc: 982,\n              hDes: -284,\n              lGap: 266,\n            },\n          },\n          {\n            ...TEXT_ELEMENT_DEFAULT_FONT,\n            name: TEXT_ELEMENT_DEFAULT_FONT.family,\n            value: TEXT_ELEMENT_DEFAULT_FONT.family,\n          },\n          {\n            name: 'Source Serif 4',\n            value: 'Source Serif 4',\n            family: 'Source Serif 4',\n            fallbacks: ['serif'],\n            weights: [200, 300, 400, 600, 700, 900],\n            styles: ['italic', 'regular'],\n            variants: [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900],\n            ],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 1000,\n              asc: 918,\n              des: -335,\n              tAsc: 918,\n              tDes: -335,\n              tLGap: 0,\n              wAsc: 1036,\n              wDes: 335,\n              xH: 475,\n              capH: 670,\n              yMin: -335,\n              yMax: 1002,\n              hAsc: 918,\n              hDes: -335,\n              lGap: 0,\n            },\n          },\n          {\n            name: 'Space Mono',\n            value: 'Space Mono',\n            family: 'Space Mono',\n            fallbacks: ['monospace'],\n            weights: [400, 700],\n            styles: ['regular', 'italic'],\n            variants: [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n            ],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 1000,\n              asc: 1120,\n              des: -361,\n              tAsc: 1120,\n              tDes: -361,\n              tLGap: 0,\n              wAsc: 1120,\n              wDes: 361,\n              xH: 496,\n              capH: 700,\n              yMin: -309,\n              yMax: 1090,\n              hAsc: 1120,\n              hDes: -361,\n              lGap: 0,\n            },\n          },\n          {\n            name: 'Ubuntu',\n            value: 'Ubuntu',\n            family: 'Ubuntu',\n            fallbacks: ['sans-serif'],\n            weights: [300, 400, 500, 700],\n            styles: ['italic', 'regular'],\n            variants: [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n            ],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 1000,\n              asc: 932,\n              des: -189,\n              tAsc: 776,\n              tDes: -185,\n              tLGap: 56,\n              wAsc: 932,\n              wDes: 189,\n              xH: 520,\n              capH: 693,\n              yMin: -189,\n              yMax: 962,\n              hAsc: 932,\n              hDes: -189,\n              lGap: 28,\n            },\n          },\n          {\n            name: 'Vazir Regular',\n            value: 'Vazir Regular',\n            family: 'Vazir Regular',\n            fallbacks: ['sans-serif'],\n            weights: [400],\n            styles: ['regular'],\n            variants: [[0, 400]],\n            url: 'https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf',\n            service: 'custom',\n            metrics: {\n              upm: 2048,\n              asc: 2200,\n              des: -1100,\n              tAsc: 2200,\n              tDes: -1100,\n              tLGap: 0,\n              wAsc: 2200,\n              wDes: 1100,\n              xH: 1082,\n              capH: 1638,\n              yMin: -1116,\n              yMax: 2163,\n              hAsc: 2200,\n              hDes: -1100,\n              lGap: 0,\n            },\n          },\n          {\n            name: 'Yrsa',\n            value: 'Yrsa',\n            family: 'Yrsa',\n            fallbacks: ['serif'],\n            weights: [300, 400, 500, 600, 700],\n            styles: ['regular', 'italic'],\n            variants: [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n            ],\n            service: 'fonts.google.com',\n            metrics: {\n              upm: 1000,\n              asc: 728,\n              des: -272,\n              tAsc: 728,\n              tDes: -272,\n              tLGap: 218,\n              wAsc: 971,\n              wDes: 422,\n              xH: 413,\n              capH: 568,\n              yMin: -211,\n              yMax: 925,\n              hAsc: 728,\n              hDes: -272,\n              lGap: 218,\n            },\n          },\n        ];\n\n        if (params.include) {\n          fonts = fonts.filter(({ family }) => params.include.includes(family));\n        }\n\n        if (params.search) {\n          fonts = fonts.filter(({ family }) =>\n            family.toLowerCase().includes(params.search.toLowerCase())\n          );\n        }\n\n        // If we're getting custom fonts, return custom only.\n        if (params.service) {\n          fonts = fonts.filter(({ service }) => {\n            if ('custom' === params.service) {\n              return service === params.service;\n            }\n            if ('builtin' === params.service) {\n              return 'fonts.google.com' === params.service;\n            }\n            return false;\n          });\n        }\n\n        return asyncResponse(fonts);\n      }, []);\n\n      const getProducts = useCallback((search, page, orderby, order) => {\n        let products = getProductsResponse;\n        if (search) {\n          products = products.filter(({ productTitle }) =>\n            productTitle.toLowerCase().includes(search.toLowerCase())\n          );\n        }\n\n        // handling title sorting (asc, desc) only here\n        if (orderby === 'title') {\n          products = sortStrings(products, 'productTitle', order);\n        }\n\n        return { products, hasNextPage: false };\n      }, []);\n\n      const state = {\n        actions: {\n          autoSaveById,\n          getStoryById,\n          getMedia,\n          getLinkMetadata,\n          getHotlinkInfo,\n          getProxyUrl,\n          saveStoryById,\n          getAllStatuses,\n          getAuthors,\n          uploadMedia,\n          updateMedia,\n          getStatusCheck,\n          addPageTemplate,\n          getCustomPageTemplates,\n          deletePageTemplate,\n          getPageTemplates,\n          getCurrentUser,\n          updateCurrentUser,\n          getTaxonomyTerm,\n          createTaxonomyTerm,\n          getTaxonomies,\n          getFonts,\n          getProducts,\n          ...mocks,\n        },\n      };\n      return (\n        <APIContext.Provider value={state}>{children}</APIContext.Provider>\n      );\n    };\n    Comp.displayName = 'Fixture(APIProvider)';\n    this._comp = Comp;\n  }\n\n  /**\n   * @param {Array<Object>} pages Pages.\n   */\n  setPages(pages) {\n    this._pages = pages.map((page) => {\n      const result = createPage(page);\n      // Overwrite ID used in testing.\n      if (page.id !== undefined) {\n        result.id = page.id;\n      }\n      return result;\n    });\n  }\n\n  get Component() {\n    return this._comp;\n  }\n}\n/* eslint-enable jasmine/no-unsafe-spy */\n\n/**\n * Wraps a fixture response in a promise. May additionally add `act()` calls as\n * needed.\n *\n * @param {*} value The response value.\n * @return {!Promise} The promise of the response.\n */\nfunction asyncResponse(value) {\n  return Promise.resolve(value);\n}\n\n/**\n * For integration fixture tests we want `act()` to be always async, otherwise\n * a tester would never know what to expect: switching from sync to async\n * is often an implementation detail.\n *\n * See https://github.com/facebook/react/blob/master/packages/react-dom/src/test-utils/ReactTestUtilsAct.js.\n *\n * @param {function():(!Promise|undefined)} callback The body of the `act()`.\n * @return {!Promise} The `act()` promise.\n */\nfunction actPromise(callback) {\n  return new Promise((resolve) => {\n    let callbackResult;\n    const actResult = act(() => {\n      callbackResult = callback();\n      return Promise.resolve(callbackResult);\n    });\n    resolve(\n      new Promise((aResolve, aReject) => {\n        actResult.then(aResolve, aReject);\n      }).then(() => callbackResult)\n    );\n  });\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/fixture/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport {\n  Fixture,\n  MEDIA_PER_PAGE,\n  LOCAL_MEDIA_PER_PAGE,\n  FIXTURE_DEFAULT_CONFIG,\n} from './fixture';\n"
  },
  {
    "path": "packages/story-editor/src/karma/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { Fixture } from './fixture';\n"
  },
  {
    "path": "packages/story-editor/src/karma/integrationLayerTesting/config.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nimport getDefaultConfig from '../../getDefaultConfig';\nimport { Fixture, FIXTURE_DEFAULT_CONFIG } from '../fixture';\nimport storyResponse from '../fixture/db/storyResponse';\n\ndescribe('Integration Layer tests : EditorConfig Params :', () => {\n  let fixture;\n\n  // fixture.setConfig() doesn't overwrite the whole object but merges\n  // therefore optional params need to be set undefined explicitly.\n  const MINIMUM_CONFIG = {};\n\n  for (const key of Object.keys(getDefaultConfig())) {\n    MINIMUM_CONFIG[key] = undefined;\n  }\n\n  MINIMUM_CONFIG.storyId = 1;\n  MINIMUM_CONFIG.apiCallbacks = {\n    saveStoryById: () => Promise.resolve({}),\n  };\n\n  afterEach(() => {\n    fixture.restore();\n  });\n\n  const shouldRenderWithConfig = async (config) => {\n    let error;\n    try {\n      fixture.setConfig(config);\n      await fixture.render();\n    } catch (e) {\n      error = e;\n    }\n    expect(error).toBeUndefined();\n  };\n\n  it('should work with optional params being undefined', async () => {\n    fixture = new Fixture();\n    await shouldRenderWithConfig(MINIMUM_CONFIG);\n  });\n\n  it('should NOT show media 3p panel if showMedia3p param is false', async () => {\n    fixture = new Fixture();\n    await shouldRenderWithConfig({\n      ...MINIMUM_CONFIG,\n      showMedia3p: false,\n    });\n    await fixture.collapseHelpCenter();\n\n    const firstMediaButton = fixture.querySelector(`[id=library-tab-media]`);\n    const thirdMediaButton = fixture.querySelector(`[id=library-tab-media3p]`);\n\n    expect(firstMediaButton).toBeTruthy();\n    expect(thirdMediaButton).toBeFalsy();\n  });\n\n  it('should add new tip using additionalTips param into helpcenter', async () => {\n    fixture = new Fixture();\n\n    const exampleTip = {\n      title: 'Example Tip Title',\n      figureSrcImg: 'images/help-center/story_embed_module_1',\n      figureAlt: 'Figure alt text',\n      description: [\n        'This is an example tip used for testing. <a>Learn more</a>',\n      ],\n      href: 'https://github.com/googleforcreators/web-stories-wp',\n    };\n    await shouldRenderWithConfig({\n      ...MINIMUM_CONFIG,\n      additionalTips: {\n        exampleTip,\n      },\n    });\n\n    //do not close helpcenter, check for additional tip\n\n    await expect(fixture.screen.findByText(exampleTip.title)).toBeTruthy();\n  });\n\n  it('should call getStoryById with storyId passed in editorConfig', async () => {\n    const STORY_ID = 11;\n    const getStoryById = jasmine\n      .createSpy('getStoryById')\n      .and.callFake((storyId) => {\n        return Promise.resolve({\n          storyId,\n          ...storyResponse,\n          status: 'publish',\n        });\n      });\n\n    fixture = new Fixture({\n      mocks: { getStoryById },\n    });\n\n    await shouldRenderWithConfig({\n      ...MINIMUM_CONFIG,\n      storyId: STORY_ID,\n    });\n\n    expect(getStoryById).toHaveBeenCalledWith(STORY_ID);\n  });\n\n  it('should render upload button if capabilities.hasUploadMediaAction is true', async () => {\n    fixture = new Fixture();\n\n    await shouldRenderWithConfig({\n      ...MINIMUM_CONFIG,\n      apiCallbacks: {\n        ...MINIMUM_CONFIG.apiCallbacks,\n      },\n      capabilities: {\n        hasUploadMediaAction: true,\n      },\n      MediaUpload: FIXTURE_DEFAULT_CONFIG.MediaUpload,\n    });\n\n    await fixture.collapseHelpCenter();\n\n    const uploadButton = await fixture.screen.findByRole('button', {\n      name: 'Upload',\n    });\n\n    expect(uploadButton).toBeTruthy();\n  });\n\n  it('should not render upload button if capabilities.hasUploadMediaAction is false', async () => {\n    fixture = new Fixture();\n\n    await shouldRenderWithConfig({\n      ...MINIMUM_CONFIG,\n      apiCallbacks: {\n        ...MINIMUM_CONFIG.apiCallbacks,\n      },\n      capabilities: {\n        hasUploadMediaAction: false,\n      },\n      MediaUpload: FIXTURE_DEFAULT_CONFIG.MediaUpload,\n    });\n\n    await fixture.collapseHelpCenter();\n\n    //wait for mediaPane to stabalize\n    await fixture.events.sleep(500);\n\n    const uploadButton = fixture.screen.queryByRole('button', {\n      name: 'Upload',\n    });\n    expect(uploadButton).toBeFalsy();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/integrationLayerTesting/optionalCallbacks.karma.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n\nimport { Fixture, FIXTURE_DEFAULT_CONFIG } from '../fixture';\nimport storyResponse from '../fixture/db/storyResponse';\n\ndescribe('Integration Layer tests : Optional API Callbacks', () => {\n  let fixture;\n\n  const shouldRenderWithoutError = async () => {\n    let error;\n    try {\n      await fixture.render();\n    } catch (e) {\n      error = e;\n    }\n    expect(error).toBeUndefined();\n  };\n\n  it('should not break editor, if getCurrentUser callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { getCurrentUser: undefined } });\n    await shouldRenderWithoutError();\n  });\n\n  it('should not break editor, if updateCurrentUser callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { updateCurrentUser: undefined } });\n    await shouldRenderWithoutError();\n  });\n\n  it('should not break editor, if getProxyUrl callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { getProxyUrl: undefined } });\n    await shouldRenderWithoutError();\n  });\n\n  it('should not break editor, if getPublisherLogos callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { getPublisherLogos: undefined } });\n    await shouldRenderWithoutError();\n  });\n\n  it('should not break editor, if addPublisherLogo callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { addPublisherLogo: undefined } });\n    await shouldRenderWithoutError();\n  });\n\n  it('if initialEdits is NOT passed, getStoryById should be called to load a story', async () => {\n    const getStoryById = jasmine\n      .createSpy('getStoryById')\n      .and.callFake((storyId) => {\n        return Promise.resolve({\n          storyId,\n          ...storyResponse,\n        });\n      });\n    fixture = new Fixture({ mocks: { getStoryById } });\n    await shouldRenderWithoutError();\n    expect(getStoryById).toHaveBeenCalledWith(FIXTURE_DEFAULT_CONFIG.storyId);\n  });\n\n  it('should not render 1p media panel if getMedia callback is not defined', async () => {\n    fixture = new Fixture({ mocks: { getMedia: undefined } });\n    await fixture.render();\n\n    //clear localStorage to force 3p media usage notice to appear\n    localStorage.clear();\n\n    const dismiss = await fixture.screen.findByText('Dismiss');\n    await fixture.events.click(dismiss);\n\n    await fixture.collapseHelpCenter();\n\n    const firstMediaButton = fixture.querySelector(`[id=library-tab-media]`);\n    const thirdMediaButton = fixture.querySelector(`[id=library-tab-media3p]`);\n\n    expect(firstMediaButton).not.toBeTruthy();\n    expect(thirdMediaButton).toBeTruthy();\n  });\n\n  it('should not render custom page templates option if getCustomPageTemplates callback is undefined', async () => {\n    fixture = new Fixture({ mocks: { getCustomPageTemplates: undefined } });\n    await shouldRenderWithoutError();\n\n    //clear localStorage to force selection of default page templates.\n    localStorage.clear();\n\n    await fixture.collapseHelpCenter();\n\n    await fixture.events.click(fixture.editor.library.pageTemplatesTab);\n\n    expect(fixture.editor.library.pageTemplatesPane.dropDown).toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/media.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndescribe('CUJ: Creator Can Add Image/Video to Page: Upload media via upload button', () => {\n  // eslint-disable-next-line jasmine/no-disabled-tests -- Not implemented yet\n  xit('it should upload image via upload button');\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- Not implemented yet\n  xit('it should upload video via upload button');\n\n  describe('CUJ: Creator Can Add Image/Video to Page: Search media, Drag image/video from desktop to canvas', () => {\n    // eslint-disable-next-line jasmine/no-disabled-tests -- Not implemented yet\n    xit('it should allow searching for media and adding it to the canvas');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/richText/_utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../../app';\n\nexport function initHelpers(data) {\n  async function getElements() {\n    const storyContext = await data.fixture.renderHook(() => useStory());\n    return storyContext.state.currentPage.elements;\n  }\n\n  async function setFontSize(size) {\n    const fontSize = data.fixture.editor.sidebar.designPanel.textStyle.fontSize;\n    await data.fixture.events.click(fontSize, { clickCount: 3 });\n    await data.fixture.events.keyboard.type(size);\n    await data.fixture.events.keyboard.press('tab');\n    // Give time for the font size to be applied.\n    await data.fixture.events.sleep(100);\n  }\n\n  async function addInitialText(addExtra = false) {\n    await data.fixture.editor.library.textTab.click();\n    await data.fixture.events.click(\n      data.fixture.editor.library.text.preset('Paragraph')\n    );\n    await waitFor(() => data.fixture.editor.canvas.framesLayer.frames[1].node);\n\n    if (addExtra) {\n      // Move the first text field 10 steps down to avoid placing these on top of each other.\n      await repeatPress('ArrowDown', 10);\n      await data.fixture.editor.library.textTab.click();\n      // Select background for being able to insert another text.\n      await data.fixture.events.mouse.clickOn(\n        data.fixture.editor.canvas.framesLayer.frames[0].node,\n        '90%',\n        '90%'\n      );\n      await data.fixture.events.click(\n        data.fixture.editor.library.text.preset('Paragraph')\n      );\n      await waitFor(\n        () => data.fixture.editor.canvas.framesLayer.frames[2].node\n      );\n    }\n\n    await richTextHasFocus();\n\n    const elements = await getElements();\n    data.bgId = elements[0].id;\n    data.textId = elements[1].id;\n\n    if (addExtra) {\n      data.extraId = elements[2].id;\n\n      // Second text field is currently selected as it was last to be added\n      // Change value of second text field and exit edit mode\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.type('Number #2');\n      await data.fixture.events.keyboard.press('Escape');\n    }\n  }\n\n  async function selectTextField(index = 0) {\n    const node = data.fixture.editor.canvas.framesLayer.frame(\n      index === 0 ? data.textId : data.extraId\n    ).node;\n    await data.fixture.events.click(node);\n  }\n\n  async function selectBothTextFields() {\n    await selectTextField(0);\n    await data.fixture.events.keyboard.down('shift');\n    await selectTextField(1);\n    await data.fixture.events.keyboard.up('shift');\n  }\n\n  function getTextContent(index = 0) {\n    return data.fixture.editor.canvas.framesLayer.frame(\n      index === 0 ? data.textId : data.extraId\n    ).textContentHTML;\n  }\n\n  async function richTextHasFocus() {\n    await data.fixture.editor.canvas.waitFocusedWithin();\n  }\n\n  function repeatPress(key, count) {\n    let remaining = count;\n    const press = () => {\n      if (remaining === 0) {\n        return Promise.resolve(true);\n      }\n      remaining--;\n      return data.fixture.events.keyboard.press(key).then(press);\n    };\n    return press();\n  }\n\n  async function setSelection(startOffset, endOffset) {\n    // Assume text is in edit-mode - click inside editable text field\n    // and then press \"up\" a number of times to ensure cursor is at start\n    const textEditor = data.fixture.querySelector('[data-testid=\"textEditor\"]');\n    const { height } = textEditor.getBoundingClientRect();\n    await data.fixture.events.mouse.clickOn(textEditor, 30, height / 2);\n    await repeatPress('ArrowUp', 10);\n    // Move to start of selection and hold shift while selecting\n    await repeatPress('ArrowRight', startOffset);\n    await data.fixture.events.keyboard.down('shift');\n    await repeatPress('ArrowRight', endOffset - startOffset);\n    await data.fixture.events.keyboard.up('shift');\n  }\n\n  return {\n    getElements,\n    addInitialText,\n    getTextContent,\n    setSelection,\n    richTextHasFocus,\n    selectTextField,\n    selectBothTextFields,\n    setFontSize,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/karma/richText/inlineSelection.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../fixture';\nimport { useStory } from '../../app';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../constants';\nimport { initHelpers } from './_utils';\n\ndescribe('CUJ: Creator can Add and Write Text: Select an individual word to edit', () => {\n  const data = {};\n\n  const {\n    getTextContent,\n    addInitialText,\n    setSelection,\n    richTextHasFocus,\n    setFontSize,\n  } = initHelpers(data);\n\n  beforeEach(async () => {\n    data.fixture = new Fixture();\n    await data.fixture.render();\n    await data.fixture.collapseHelpCenter();\n\n    // Add a text box\n    await addInitialText();\n  });\n\n  afterEach(() => {\n    data.fixture.restore();\n  });\n\n  it('should have the correct initial text and no formatting', () => {\n    expect(getTextContent()).toBe('Fill in some text');\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply U, Apply I, Set text color, Set kerning', () => {\n    it('should apply inline formats correctly for both single style and multiple styles', async () => {\n      let storyContext = await data.fixture.renderHook(() => useStory());\n      expect(storyContext.state.selectedElements[0].content).toBe(\n        'Fill in some text'\n      );\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const {\n        bold,\n        italic,\n        underline,\n        fontWeight,\n        letterSpacing,\n        fontColor,\n        uppercase,\n      } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Enter edit-mode\n      await data.fixture.events.focus(\n        data.fixture.editor.canvas.framesLayer.frames[1].node\n      );\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.screen.findByTestId('textEditor');\n\n      await setFontSize('30');\n\n      // Select character 7 and 8 (the part \"ip\" in \"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\")\n      await setSelection(6, 8);\n\n      // Check all styles are default\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(uppercase.checked).toBe(false);\n      expect(fontWeight.value).toBe('Regular');\n      expect(letterSpacing.value).toBe('0%');\n      expect(fontColor.hex.value).toBe('000000');\n\n      // Toggle italic and underline and uppercase - wait for autofocus to return\n      await data.fixture.events.click(italic.button);\n      await richTextHasFocus();\n      await data.fixture.events.click(underline.button);\n      await richTextHasFocus();\n      await data.fixture.events.click(uppercase.button);\n      await richTextHasFocus();\n      // Set font weight (should also toggle bold, as \"Black\" is >700)\n      // - wait for autofocus to return\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n\n      // Set letter spacing\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('50');\n      await data.fixture.events.keyboard.press('Enter');\n      // Press escape to leave input field (does not leave edit-mode)\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Set color using 3 digit hex input\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('A1F');\n      await data.fixture.events.keyboard.press('Tab');\n\n      expect(fontColor.hex.value).toBe('AA11FF');\n\n      // Set color using 6 digit hex input\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('FF6600');\n      await data.fixture.events.keyboard.press('Tab');\n\n      // Press escape to leave input field (does not leave edit-mode)\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      expect(uppercase.checked).toBe(true);\n      expect(fontWeight.value).toBe('Black');\n      expect(letterSpacing.value).toBe('50%');\n      expect(fontColor.hex.value).toBe('FF6600');\n\n      // Move selection to characters 7-10 (partially overlapping new styles and no styles)\n      await setSelection(7, 10);\n\n      // Verify that the toggles are off (as to be expected with mixed styles)\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(uppercase.checked).toBe(false);\n\n      // Expect font weight, letter spacing and font color to be \"multiple\"\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n      expect(letterSpacing.value).toBe('');\n      expect(letterSpacing.placeholder).toBe(MULTIPLE_DISPLAY_VALUE);\n      expect(fontColor.output).toBe('');\n\n      // Now toggle all toggles, and set new color and letter spacing\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.click(underline.button);\n      await data.fixture.events.click(bold.button);\n      await data.fixture.events.click(uppercase.button);\n\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('100');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n\n      // We have to open the color picker, as there's no direct hex input when \"multiple\"\n      await data.fixture.events.click(fontColor.button);\n      await data.fixture.events.click(fontColor.picker.applySavedColor('#eee'));\n      // Wait for debounce in color picker (100ms)\n      await data.fixture.events.sleep(100);\n\n      // Verify all styles again\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      // Note that entire selection is made black, because some part was black, when bold was pressed\n      expect(fontWeight.value).toBe('Black');\n      expect(letterSpacing.value).toBe('100%');\n      expect(fontColor.hex.value).toBe('EEEEEE');\n\n      // Exit edit-mode\n      const safezone = data.fixture.querySelector('[data-testid=\"safezone\"]');\n      const rect = safezone.getBoundingClientRect();\n      await data.fixture.events.mouse.click(rect.left + 10, rect.top + 10);\n      await data.fixture.snapshot('With inline style applied');\n\n      // Assume text content to match expectation\n      storyContext = await data.fixture.renderHook(() => useStory());\n      const actual = storyContext.state.selectedElements[0].content;\n      const firstCSS = [\n        'font-weight: 900',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #f60',\n        'letter-spacing: 0.5em',\n        'text-transform: uppercase',\n      ].join('; ');\n      const secondCSS = [\n        'font-weight: 900',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #eee',\n        'letter-spacing: 1em',\n        'text-transform: uppercase',\n      ].join('; ');\n      const expected = `Fill i<span style=\"${firstCSS}\">n</span><span style=\"${secondCSS}\"> </span><span style=\"${secondCSS}\">so</span>me text`;\n      expect(actual).toBe(expected);\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply U, Apply I, Apply Uppercase', () => {\n    it('should apply inline formats using shortcuts', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, italic, underline } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Enter edit-mode\n      await data.fixture.events.keyboard.press('Enter');\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n\n      // Check all styles are default\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n\n      // Toggle italic, underline and bold using shortcut\n      await data.fixture.events.keyboard.shortcut('mod+u');\n      await data.fixture.events.keyboard.shortcut('mod+i');\n      await data.fixture.events.keyboard.shortcut('mod+b');\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Assume text content to match expectation\n      const actual = getTextContent();\n      const firstCSS = [\n        'font-weight: 700',\n        'font-style: italic',\n        'text-decoration: underline',\n      ].join('; ');\n      const expected = `Fill <span style=\"${firstCSS}\">in</span> some text`;\n      expect(actual).toBe(expected);\n    });\n\n    it('should apply inline format for uppercase', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { uppercase } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Enter edit-mode\n      await data.fixture.events.keyboard.press('Enter');\n\n      // Select character 6 and 7 (the part \"in\" in \"Fill in some text\")\n      await setSelection(5, 7);\n\n      // Check style is default.\n      expect(uppercase.checked).toBe(false);\n\n      // Toggle uppercase\n      await data.fixture.events.click(uppercase.button);\n\n      // Verify the updated style.\n      expect(uppercase.checked).toBe(true);\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Assume text content to match expectation\n      const actual = getTextContent();\n      const expected = `Fill <span style=\"text-transform: uppercase\">in</span> some text`;\n      expect(actual).toBe(expected);\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Select weight', () => {\n    describe('when there is a mix of font weights', () => {\n      beforeEach(async () => {\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { fontWeight } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n\n        // Enter edit-mode\n        await data.fixture.events.focus(\n          data.fixture.editor.canvas.framesLayer.frames[1].node\n        );\n        await data.fixture.editor.canvas.waitFocusedWithin();\n        await data.fixture.events.keyboard.press('Enter');\n\n        const selectFontWeight = async (weight) => {\n          await data.fixture.events.click(fontWeight.select);\n          await data.fixture.events.sleep(300);\n          await data.fixture.events.click(await fontWeight.option(weight));\n          await data.fixture.events.sleep(300);\n          await richTextHasFocus();\n        };\n\n        // Select first character and make it black (900)\n        await setSelection(0, 1);\n        await selectFontWeight('Black');\n\n        // Select second character and make it bold (700)\n        await setSelection(1, 2);\n        await selectFontWeight('Bold');\n      });\n\n      it('should make black+bold selection non-bold when toggling', async () => {\n        // Select first two characters (900 and 700)\n        await setSelection(0, 2);\n\n        const { bold, fontWeight } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n\n        // Check that bold toggle is on but font weight is \"multiple\"\n        expect(bold.checked).toBe(true);\n        expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n        // Toggle it by pressing the bold button\n        await data.fixture.events.click(bold.button);\n\n        // Verify bold is now off and font weight is Regular\n        expect(bold.checked).toBe(false);\n        expect(fontWeight.value).toBe('Regular');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Assume text content to now be formatting-free\n        const actual = getTextContent();\n        const expected = `Fill in some text`;\n        expect(actual).toBe(expected);\n      });\n\n      it('should make bold+regular selection bold when toggling', async () => {\n        const { bold, fontWeight } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n\n        // Select second and third characters (700 and 400)\n        await setSelection(1, 3);\n\n        // Check that bold toggle is off but font weight is \"multiple\"\n        expect(bold.checked).toBe(false);\n        expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n        // Toggle it by pressing the bold button\n        await data.fixture.events.click(bold.button);\n\n        // Verify bold is now on and font weight is Bold\n        expect(bold.checked).toBe(true);\n        expect(fontWeight.value).toBe('Bold');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Assume text content to be correctly formatted\n        // NOTE: Sometimes returned HTML has two single-letter bold spans, sometimes they're joined into one:\n        const actual = getTextContent();\n        const expectedDouble = `<span style=\"font-weight: 900\">F</span><span style=\"font-weight: 700\">i</span><span style=\"font-weight: 700\">l</span>l in some text`;\n        const expectedSingle = `<span style=\"font-weight: 900\">F</span><span style=\"font-weight: 700\">il</span>l in some text`;\n        expect(actual).toBeOneOf([expectedDouble, expectedSingle]);\n\n        await data.fixture.snapshot(\n          'First letter black, next two bold, rest regular'\n        );\n      });\n\n      it('should make black+bold+regular selection black when toggling', async () => {\n        const { bold, fontWeight } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n\n        // Select first three characters (900, 700 and 400)\n        await setSelection(0, 3);\n\n        // Check that bold toggle is off but font weight is \"multiple\"\n        expect(bold.checked).toBe(false);\n        expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n        // Toggle it by pressing the bold button\n        await data.fixture.events.click(bold.button);\n\n        // Verify bold is now on and font weight is Black\n        expect(bold.checked).toBe(true);\n        expect(fontWeight.value).toBe('Black');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // NOTE: Sometimes returned HTML has two black spans, sometimes they're joined into one:\n        const actual = getTextContent();\n        const expectedDouble = `<span style=\"font-weight: 900\">Fi</span><span style=\"font-weight: 900\">l</span>l in some text`;\n        const expectedSingle = `<span style=\"font-weight: 900\">Fil</span>l in some text`;\n        expect(actual).toBeOneOf([expectedDouble, expectedSingle]);\n\n        await data.fixture.snapshot('First three letters black, rest regular');\n      });\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Set line height', () => {\n    it('should apply global formats (here line height) even when a selection is present', async () => {\n      const { displayLayer } = data.fixture.editor.canvas;\n      const getDisplayTextStyles = () => {\n        const displayNode = displayLayer.display(data.textId).node;\n        const paragraph = displayNode.querySelector('p');\n        return window.getComputedStyle(paragraph);\n      };\n\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const initialLineHeight = Number.parseFloat(\n        getDisplayTextStyles().lineHeight\n      );\n\n      const { lineHeight } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Enter edit-mode\n      await data.fixture.events.keyboard.press('Enter');\n\n      // Select something\n      await setSelection(5, 7);\n\n      // Change line height to 5\n      await data.fixture.events.click(lineHeight, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('5');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Exit edit-mode by refocusing text field and pressing Esc\n      await setSelection(1, 2);\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Expect text content to be unchanged\n      expect(getTextContent()).toBe('Fill in some text');\n\n      // Expect line height to have changed\n      const currentLineHeight = Number.parseFloat(\n        getDisplayTextStyles().lineHeight\n      );\n      expect(currentLineHeight).not.toBe(initialLineHeight);\n    });\n  });\n\n  describe('when copy-pasting', () => {\n    beforeEach(async () => {\n      // Enter edit-mode\n      await data.fixture.events.keyboard.press('Enter');\n\n      // Select everything and make bold\n      await setSelection(0, 17);\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold } = data.fixture.editor.sidebar.designPanel.textStyle;\n      await data.fixture.events.click(bold.button);\n    });\n\n    it('should paste and match styles on collapsed selection', async () => {\n      // Select nothing and paste\n      await setSelection(12, 12);\n      await data.fixture.events.clipboard.pastePlain(' extra');\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Expect text content to have style and content\n      expect(getTextContent()).toBe(\n        '<span style=\"font-weight: 700\">Fill in some extra text</span>'\n      );\n\n      await data.fixture.snapshot('Pasting between text');\n    });\n\n    it('should paste and match styles on non-empty selection', async () => {\n      // Select \"some\" and paste\n      await setSelection(8, 12);\n      await data.fixture.events.clipboard.pastePlain('extra');\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Expect text content to have style and content\n      expect(getTextContent()).toBe(\n        '<span style=\"font-weight: 700\">Fill in extra text</span>'\n      );\n\n      await data.fixture.snapshot('Pasting and replacing text');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/richText/inlineStyleOverride.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../fixture';\nimport { initHelpers } from './_utils';\n\ndescribe('Inline style override', () => {\n  const data = {};\n\n  const { getTextContent, addInitialText, setSelection, richTextHasFocus } =\n    initHelpers(data);\n\n  beforeEach(async () => {\n    data.fixture = new Fixture();\n    await data.fixture.render();\n    await data.fixture.collapseHelpCenter();\n\n    // Add a text box\n    await addInitialText();\n\n    // Enter edit-mode\n    await data.fixture.events.keyboard.press('Enter');\n  });\n\n  afterEach(() => {\n    data.fixture.restore();\n  });\n\n  describe('when cursor is placed after second character', () => {\n    beforeEach(async () => {\n      // Place cursor at start and them move to after second character\n      await setSelection(2, 2);\n    });\n\n    describe('CUJ: Creator Can Style Text: Apply Uppercase', () => {\n      it('should have correct formatting when pressing uppercase toggle, then inserting text', async () => {\n        // Verify that uppercase is untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { uppercase } = data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(uppercase.checked).toBe(false);\n\n        // Toggle uppercase by button\n        await data.fixture.events.click(uppercase.button);\n\n        // Verify that uppercase is now toggled on\n        expect(uppercase.checked).toBe(true);\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"text-transform: uppercase\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n    });\n\n    describe('CUJ: Creator Can Style Text: Apply B', () => {\n      it('should have correct formatting when pressing mod+b for bold, then inserting text', async () => {\n        // Verify that bold is untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { bold } = data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(bold.checked).toBe(false);\n\n        // Toggle bold by keyboard command\n        await data.fixture.events.keyboard.shortcut('mod+b');\n\n        // Verify that bold is now toggled on\n        expect(bold.checked).toBe(true);\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"font-weight: 700\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n\n      it('should have correct formatting when pressing bold toggle, then inserting text', async () => {\n        // Verify that bold is untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { bold } = data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(bold.checked).toBe(false);\n\n        // Toggle bold by button\n        await data.fixture.events.click(bold.button);\n\n        // Verify that bold is now toggled on\n        expect(bold.checked).toBe(true);\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"font-weight: 700\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n    });\n\n    describe('CUJ: Creator Can Style Text: Apply U, Apply I', () => {\n      it('should have correct formatting when pressing underline toggle, then mod+i, then inserting text', async () => {\n        // Verify that italic and underline are untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { italic, underline } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(italic.checked).toBe(false);\n        expect(underline.checked).toBe(false);\n\n        // Toggle underline by click, then italic by shortcut\n        await data.fixture.events.click(underline.button);\n        await data.fixture.events.keyboard.shortcut('mod+i');\n\n        // Verify that italic and underline are now toggled on\n        expect(italic.checked).toBe(true);\n        expect(underline.checked).toBe(true);\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"font-style: italic; text-decoration: underline\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n\n      /* eslint-disable-next-line jasmine/no-disabled-tests --\n       * This doesn't work due to bug #1606:\n       * https://github.com/googleforcreators/web-stories-wp/issues/1606\n       **/\n      xit('should have correct formatting when pressing mod+i, then underline toggle, then inserting text', async () => {\n        // Verify that italic and underline are untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { italic, underline } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(italic.checked).toBe(false);\n        expect(underline.checked).toBe(false);\n\n        // Toggle italic by shortcut and then underline by click\n        await data.fixture.events.keyboard.shortcut('mod+i');\n        await data.fixture.events.click(underline.button);\n\n        // Verify that italic and underline are now toggled on\n        expect(italic.checked).toBe(true);\n        expect(underline.checked).toBe(true);\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"font-style: italic; text-decoration: underline\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n    });\n\n    describe('CUJ: Creator Can Style Text: Select weight', () => {\n      it('should have correct formatting when selecting font weight, then inserting text', async () => {\n        // Verify that bold is untoggled in design panel\n        await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n        const { fontWeight } =\n          data.fixture.editor.sidebar.designPanel.textStyle;\n        expect(fontWeight.value).toBe('Regular');\n\n        // Open dropdown and select \"Black\"\n        await data.fixture.events.click(fontWeight.select);\n        await data.fixture.events.sleep(300);\n        await data.fixture.events.click(await fontWeight.option('Black'));\n        await data.fixture.events.sleep(300);\n\n        // Wait for focus to return to text\n        await richTextHasFocus();\n\n        // Verify that bold is now toggled on\n        expect(fontWeight.value).toBe('Black');\n\n        // Type \"foo\"\n        await data.fixture.events.keyboard.type('foo');\n\n        // Exit edit-mode\n        await data.fixture.events.keyboard.press('Escape');\n\n        // Expect correct result\n        const actual = getTextContent();\n        const expected =\n          'Fi<span style=\"font-weight: 900\">foo</span>ll in some text';\n        expect(actual).toBe(expected);\n\n        await data.fixture.snapshot(\n          '\"Fifooll in some text\" in mixed formatting'\n        );\n      });\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply I', () => {\n    it('should have correct formatting when already italic, then inline removing italic and adding bold, then inserting text', async () => {\n      // Toggle italic for entire selection\n      await data.fixture.events.keyboard.shortcut('mod+i');\n\n      // Place cursor at start and then move to after second character\n      await setSelection(2, 2);\n\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { italic, bold } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Verify that italic is toggled, bold is not\n      expect(italic.checked).toBe(true);\n      expect(bold.checked).toBe(false);\n\n      // (Un)toggle italic by button and then toggle bold by shortcut\n      // (also here the reverse would not work due to #1606 mentioned above)\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.keyboard.shortcut('mod+b');\n\n      // Verify that toggles are reversed\n      expect(italic.checked).toBe(false);\n      expect(bold.checked).toBe(true);\n\n      // Type \"foo\"\n      await data.fixture.events.keyboard.type('foo');\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Expect correct result\n      const actual = getTextContent();\n      const expected =\n        '<span style=\"font-style: italic\">Fi</span><span style=\"font-weight: 700\">foo</span><span style=\"font-style: italic\">ll in some text</span>';\n      expect(actual).toBe(expected);\n\n      await data.fixture.snapshot('\"Fifooll in some text\" in mixed formatting');\n    });\n  });\n\n  it('should have correct formatting deleting text with one formatting, ending up in different formatting', async () => {\n    // Toggle bold for entire selection\n    await data.fixture.events.keyboard.shortcut('mod+b');\n\n    // Select 2nd character\n    await setSelection(1, 2);\n\n    // Make just this character italic\n    await data.fixture.events.keyboard.shortcut('mod+i');\n\n    await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n    const { italic, bold } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n    // Verify that both italic and bold are toggled\n    expect(italic.checked).toBe(true);\n    expect(bold.checked).toBe(true);\n\n    // Delete the italic character\n    await data.fixture.events.focus(\n      data.fixture.editor.canvas.framesLayer.frames[1].node\n    );\n    await setSelection(1, 2);\n    await data.fixture.events.keyboard.press('Delete');\n    // Verify that bold is still on, italic is off\n    expect(bold.checked).toBe(true);\n    expect(italic.checked).toBe(false);\n\n    // Type something\n    await data.fixture.events.keyboard.type('u');\n\n    // Exit edit-mode\n    await data.fixture.events.keyboard.press('Escape');\n\n    // Expect correct result\n    const actual = getTextContent();\n    const expected = '<span style=\"font-weight: 700\">Full in some text</span>';\n    expect(actual).toBe(expected);\n    await data.fixture.snapshot('\"Full in some text\" in bold');\n  });\n\n  it('should keep formatting when all text is replaced', async () => {\n    // Make it all bold while selected\n    await data.fixture.events.keyboard.shortcut('mod+b');\n\n    // Replace text while entire text is selected\n    await data.fixture.events.keyboard.type('A new text');\n\n    // Exit edit-mode\n    await data.fixture.events.keyboard.press('Escape');\n\n    const actual = getTextContent();\n    const expected = '<span style=\"font-weight: 700\">A new text</span>';\n    expect(actual).toBe(expected);\n\n    await data.fixture.snapshot('\"A new text\" in bold');\n  });\n\n  describe('CUJ: Creator can Add and Write Text: Select all text inside a textbox, Write/edit text', () => {\n    it('should keep formatting when all text is removed, then replaced', async () => {\n      // Make it all bold while selected\n      await data.fixture.events.keyboard.shortcut('mod+b');\n\n      // Delete existing text by pressing backspace, then add new text\n      await data.fixture.events.keyboard.shortcut('Backspace');\n      await data.fixture.events.keyboard.type('Even more text');\n\n      // Exit edit-mode\n      await data.fixture.events.keyboard.press('Escape');\n\n      const actual = getTextContent();\n      const expected = '<span style=\"font-weight: 700\">Even more text</span>';\n      expect(actual).toBe(expected);\n\n      await data.fixture.snapshot('\"Even more text\" in bold');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/richText/multiSelection.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../fixture';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../constants';\nimport { initHelpers } from './_utils';\n\ndescribe('Styling multiple text fields', () => {\n  const data = {};\n\n  const {\n    getTextContent,\n    addInitialText,\n    selectBothTextFields,\n    selectTextField,\n  } = initHelpers(data);\n\n  beforeEach(async () => {\n    data.fixture = new Fixture();\n    await data.fixture.render();\n    await data.fixture.collapseHelpCenter();\n\n    // Add text box + extra\n    await addInitialText(true);\n  });\n\n  afterEach(() => {\n    data.fixture.restore();\n  });\n\n  it('should both have the correct initial text and formatting', () => {\n    // Get content of first textfield\n    expect(getTextContent(0)).toBe('Fill in some text');\n    // Get content of second textfield\n    expect(getTextContent(1)).toBe('Number #2');\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply U, Apply I, Set text color, Set kerning', () => {\n    // TODO #6955\n    // When fixing this, ensure that uppercase is also handled here.\n    // eslint-disable-next-line jasmine/no-disabled-tests\n    xit('should apply formatting correctly for identically styled text fields', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, italic, underline, fontWeight, letterSpacing, fontColor } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Select both text fields\n      await selectBothTextFields();\n\n      // Check all styles are default\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(fontWeight.value).toBe('Regular');\n      expect(letterSpacing.value).toBe('0%');\n      expect(fontColor.hex.value).toBe('000000');\n\n      // Toggle all styles\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.click(underline.button);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('50');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('F54');\n      await data.fixture.events.keyboard.press('Tab');\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      expect(fontWeight.value).toBe('Black');\n      expect(letterSpacing.value).toBe('50%');\n      expect(fontColor.hex.value).toBe('FF5544');\n\n      // Assume text contents to match expectation\n      const css = [\n        'font-weight: 900',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #f54',\n        'letter-spacing: 0.5em',\n      ].join('; ');\n      const getExpected = (content) => `<span style=\"${css}\">${content}</span>`;\n      expect(getTextContent(0)).toBe(\n        getExpected('Lorem ipsum dolor sit amet, consectetur adipiscing elit.')\n      );\n      expect(getTextContent(1)).toBe(getExpected('Number #2'));\n\n      await data.fixture.snapshot(\n        'Two texts in black,italic,underline,magenta,narrow'\n      );\n    });\n\n    it('should apply formatting correctly for multi-style text field', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const {\n        bold,\n        italic,\n        underline,\n        uppercase,\n        fontWeight,\n        letterSpacing,\n        fontColor,\n      } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Edit formatting for second text field\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('50');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('FF00FF');\n      await data.fixture.events.keyboard.press('Tab');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.click(underline.button);\n      await data.fixture.events.click(uppercase.button);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n\n      // Select both text fields\n      await selectBothTextFields();\n\n      // Check all styles reflect the proper mixed status of the text field\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(uppercase.checked).toBe(false);\n      expect(fontWeight.value).toBe('Mixed');\n      expect(letterSpacing.value).toBe('');\n      expect(letterSpacing.placeholder).toBe(MULTIPLE_DISPLAY_VALUE);\n      expect(fontColor.output).toBe('');\n\n      // Toggle all styles\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.click(underline.button);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('100');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.click(uppercase.button);\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(fontColor.button);\n      await data.fixture.events.click(fontColor.picker.custom);\n      await data.fixture.events.click(fontColor.picker.hexButton);\n      await data.fixture.events.keyboard.type('00FF00');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.sleep(100);\n      await data.fixture.events.keyboard.press('Escape');\n      // Wait for debounce in color picker (100ms)\n      await data.fixture.events.sleep(100);\n      await selectBothTextFields();\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      expect(uppercase.checked).toBe(true);\n      expect(fontWeight.value).toBe('Bold');\n      expect(letterSpacing.value).toBe('100%');\n      expect(fontColor.hex.value).toBe('00FF00');\n\n      // Assume text content to match expectation\n      const actual = getTextContent();\n      const css = [\n        'font-weight: 700',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #0f0',\n        'letter-spacing: 1em',\n        'text-transform: uppercase',\n      ].join('; ');\n      const expected = `<span style=\"${css}\">Fill in some text</span>`;\n      expect(actual).toBe(expected);\n\n      await data.fixture.snapshot('Two texts in bold,italic,underline,green');\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Select weight', () => {\n    it('should make black text field + bold text field non-bold when toggling', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, fontWeight } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Make text field 1 black\n      await selectTextField(0);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n\n      // Make text field 2 bold\n      await selectTextField(1);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n\n      // Select both text fields\n      await selectBothTextFields();\n\n      // Check that bold toggle is on but font weight is \"multiple\"\n      expect(bold.checked).toBe(true);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n      // Toggle it by pressing the bold button\n      await data.fixture.events.click(bold.button);\n\n      // Verify bold is now off and font weight is Regular\n      expect(bold.checked).toBe(false);\n      expect(fontWeight.value).toBe('Regular');\n\n      // Assume both texts' content to now be formatting-free\n      expect(getTextContent(0)).toBe('Fill in some text');\n      expect(getTextContent(1)).toBe('Number #2');\n\n      await data.fixture.snapshot('Two texts without formatting');\n    });\n\n    it('should make bold text field + light text field bold when toggling', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, fontWeight } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Make text field 1 black\n      await selectTextField(0);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n\n      // Make text field 2 light\n      await selectTextField(1);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Light'));\n      await data.fixture.events.sleep(300);\n\n      // Select both text fields\n      await selectBothTextFields();\n\n      // Check that bold toggle is off but font weight is \"multiple\"\n      expect(bold.checked).toBe(false);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n      // Toggle it by pressing the bold button\n      await data.fixture.events.click(bold.button);\n\n      // Verify bold is now on and font weight is Bold\n      expect(bold.checked).toBe(true);\n      expect(fontWeight.value).toBe('Bold');\n\n      // Assume texts' content to now be correctly bold\n      expect(getTextContent(0)).toBe(\n        '<span style=\"font-weight: 700\">Fill in some text</span>'\n      );\n      expect(getTextContent(1)).toBe(\n        '<span style=\"font-weight: 700\">Number #2</span>'\n      );\n\n      await data.fixture.snapshot('Two texts in bold');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/richText/singleSelection.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { waitFor } from '@testing-library/react';\n/**\n * Internal dependencies\n */\nimport { Fixture } from '../fixture';\nimport { MULTIPLE_DISPLAY_VALUE } from '../../constants';\nimport { initHelpers } from './_utils';\n\ndescribe('Styling single text field', () => {\n  const data = {};\n\n  const { getTextContent, addInitialText, setSelection, richTextHasFocus } =\n    initHelpers(data);\n\n  beforeEach(async () => {\n    data.fixture = new Fixture();\n    await data.fixture.render();\n    await data.fixture.collapseHelpCenter();\n\n    // Add a text box\n    await addInitialText();\n  });\n\n  afterEach(() => {\n    data.fixture.restore();\n  });\n\n  it('should have the correct initial text and no formatting', () => {\n    expect(getTextContent()).toBe('Fill in some text');\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply U, Apply I, Set text color, Set kerning', () => {\n    it('should apply inline formatting correctly for single-style text field', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const {\n        bold,\n        italic,\n        underline,\n        uppercase,\n        fontWeight,\n        letterSpacing,\n        fontColor,\n      } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Check all styles are default\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(uppercase.checked).toBe(false);\n      expect(fontWeight.value).toBe('Regular');\n      expect(letterSpacing.value).toBe('0%');\n      expect(fontColor.hex.value).toBe('000000');\n\n      // Toggle italic, underline, and uppercase\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(underline.button, { clickCount: 1 });\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(uppercase.button, { clickCount: 1 });\n      await data.fixture.events.sleep(300);\n      // Set font weight (should also toggle bold, as \"Black\" is >700)\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      // Set letter spacing\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.keyboard.type('50');\n      await data.fixture.events.keyboard.press('Enter');\n      // Press escape to leave input field (does not unselect element)\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Set color using hex input\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.keyboard.type('A40');\n      await data.fixture.events.keyboard.press('Tab');\n      // Press escape to leave input field (does not unselect element)\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      expect(uppercase.checked).toBe(true);\n      expect(fontWeight.value).toBe('Black');\n      expect(letterSpacing.value).toBe('50%');\n      expect(fontColor.hex.value).toBe('AA4400');\n\n      // Assume text content to match expectation\n      const actual = getTextContent();\n      const css = [\n        'font-weight: 900',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #a40',\n        'letter-spacing: 0.5em',\n        'text-transform: uppercase',\n      ].join('; ');\n      const expected = `<span style=\"${css}\">Fill in some text</span>`;\n      expect(actual).toBe(expected);\n    });\n\n    it('should apply inline formatting correctly for multi-style text field', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const {\n        bold,\n        italic,\n        underline,\n        uppercase,\n        fontWeight,\n        letterSpacing,\n        fontColor,\n      } = data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // First enter edit mode, select something, style it with all styles and exit edit mode\n      await data.fixture.events.focus(\n        data.fixture.editor.canvas.framesLayer.frames[1].node\n      );\n      await data.fixture.events.keyboard.press('Enter');\n      await setSelection(6, 8);\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('50');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(fontColor.hex, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('FF00FF');\n      await data.fixture.events.keyboard.press('Tab');\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.click(italic.button);\n      await richTextHasFocus();\n      await data.fixture.events.click(underline.button);\n      await richTextHasFocus();\n      await data.fixture.events.click(uppercase.button);\n      await richTextHasFocus();\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Check all styles reflect the proper mixed status of the text field\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n      expect(uppercase.checked).toBe(false);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n      expect(letterSpacing.value).toBe('');\n      expect(letterSpacing.placeholder).toBe(MULTIPLE_DISPLAY_VALUE);\n      expect(fontColor.output).toBe('');\n\n      // Toggle all styles\n      await data.fixture.events.click(italic.button);\n      await data.fixture.events.click(underline.button);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(letterSpacing, { clickCount: 3 });\n      await data.fixture.events.keyboard.type('100');\n      await data.fixture.events.keyboard.press('Enter');\n      await data.fixture.events.click(uppercase.button);\n      await data.fixture.events.keyboard.press('Escape');\n      await data.fixture.events.sleep(200);\n      await data.fixture.events.click(fontColor.button);\n      await data.fixture.events.click(fontColor.picker.custom);\n      await data.fixture.events.click(fontColor.picker.hexButton);\n      await data.fixture.events.keyboard.type('00FF00');\n      // Wait for color panel debounce\n      await waitFor(() => {\n        if (fontColor.hex.value !== '00FF00') {\n          throw new Error('Color not updated yet');\n        }\n      });\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n      expect(uppercase.checked).toBe(true);\n      expect(fontWeight.value).toBe('Bold');\n      expect(letterSpacing.value).toBe('100%');\n\n      // Assume text content to match expectation\n      const css = [\n        'font-weight: 700',\n        'font-style: italic',\n        'text-decoration: underline',\n        'color: #0f0',\n        'letter-spacing: 1em',\n        'text-transform: uppercase',\n      ].join('; ');\n      const expected = `<span style=\"${css}\">Fill in some text</span>`;\n      await waitFor(() => {\n        if (getTextContent() !== expected) {\n          throw new Error('Text not updated yet');\n        }\n      });\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Apply U, Apply I', () => {\n    it('should apply inline formatting using shortcuts', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, italic, underline } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Check all styles are default\n      expect(bold.checked).toBe(false);\n      expect(italic.checked).toBe(false);\n      expect(underline.checked).toBe(false);\n\n      // Toggle italic, underline and bold using shortcut\n      await data.fixture.events.keyboard.shortcut('mod+u');\n      await data.fixture.events.keyboard.shortcut('mod+i');\n      await data.fixture.events.keyboard.shortcut('mod+b');\n\n      // Verify all styles, now expected to be updated\n      expect(bold.checked).toBe(true);\n      expect(italic.checked).toBe(true);\n      expect(underline.checked).toBe(true);\n\n      // Assume text content to match expectation\n      const actual = getTextContent();\n      const firstCSS = [\n        'font-weight: 700',\n        'font-style: italic',\n        'text-decoration: underline',\n      ].join('; ');\n      const expected = `<span style=\"${firstCSS}\">Fill in some text</span>`;\n      expect(actual).toBe(expected);\n    });\n  });\n\n  describe('CUJ: Creator Can Style Text: Apply B, Select weight', () => {\n    it('should make black+bold text field non-bold when toggling', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, fontWeight } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Edit and make some content black, rest of content bold\n      await data.fixture.events.keyboard.press('Enter');\n      await setSelection(0, 1);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await setSelection(1, 'Fill in some text'.length);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Check that bold toggle is on but font weight is \"mixed\"\n      expect(bold.checked).toBe(true);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n      // Toggle it by pressing the bold button\n      await data.fixture.events.click(bold.button);\n\n      // Verify bold is now off and font weight is Regular\n      expect(bold.checked).toBe(false);\n      expect(fontWeight.value).toBe('Regular');\n\n      // Assume text content to now be formatting-free\n      const actual = getTextContent();\n      const expected = `Fill in some text`;\n      expect(actual).toBe(expected);\n    });\n\n    it('should make bold+regular text field bold when toggling', async () => {\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, fontWeight } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Edit and make some content bold, rest of content unchanged\n      await data.fixture.events.keyboard.press('Enter');\n      await setSelection(0, 1);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Check that bold toggle is on but font weight is \"mixed\"\n      expect(bold.checked).toBe(false);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n      // Toggle it by pressing the bold button\n      await data.fixture.events.click(bold.button);\n\n      // Verify bold is now off and font weight is Bold\n      expect(bold.checked).toBe(true);\n      expect(fontWeight.value).toBe('Bold');\n\n      // Assume text content to now be correctly bold\n      const actual = getTextContent();\n      const expected = `<span style=\"font-weight: 700\">Fill in some text</span>`;\n      expect(actual).toBe(expected);\n    });\n\n    it('should make black+bold+regular text field bold when toggling', async () => {\n      // Note that this works differently than multiple styles in an inline selection,\n      // where a bolding anything including non-bolds *and* black would result in the\n      // entire selection becoming black.\n      // This is on purpose and by design.\n      // See more in `richText/formatters/weight.js@toggleBold`\n\n      await data.fixture.events.click(data.fixture.editor.sidebar.designTab);\n      const { bold, fontWeight } =\n        data.fixture.editor.sidebar.designPanel.textStyle;\n\n      // Edit and make some content black, some bold, rest unchanged\n      await data.fixture.events.keyboard.press('Enter');\n      await setSelection(0, 1);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Black'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await setSelection(1, 2);\n      await data.fixture.events.click(fontWeight.select);\n      await data.fixture.events.sleep(300);\n      await data.fixture.events.click(await fontWeight.option('Bold'));\n      await data.fixture.events.sleep(300);\n      await richTextHasFocus();\n      await data.fixture.events.keyboard.press('Escape');\n\n      // Check that bold toggle is off but font weight is \"mixed\"\n      expect(bold.checked).toBe(false);\n      expect(fontWeight.value).toBe(MULTIPLE_DISPLAY_VALUE);\n\n      // Toggle it by pressing the bold button\n      await data.fixture.events.click(bold.button);\n\n      // Verify bold is now on and font weight is Bold\n      expect(bold.checked).toBe(true);\n      expect(fontWeight.value).toBe('Bold');\n\n      // Assume text content to now be correctly bold\n      const actual = getTextContent();\n      const expected = `<span style=\"font-weight: 700\">Fill in some text</span>`;\n      expect(actual).toBe(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/karma/text.cuj.karma.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndescribe('CUJ: Creator can Add and Write Text: Delete textbox', () => {\n  describe('when a textbox is selected', () => {\n    it('should be removed when pressing backspace', () => {\n      // Implementation goes here\n    });\n\n    it('should be removed when pressing delete', () => {\n      // Implementation goes here\n    });\n  });\n\n  // eslint-disable-next-line jasmine/no-disabled-tests -- Not implemented yet\n  xit('should allow you to delete a text box by dragging it off-stage', () => {});\n});\n"
  },
  {
    "path": "packages/story-editor/src/propTypes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { AnimationProps } from '@googleforcreators/animation';\nimport { BackgroundAudioPropType } from '@googleforcreators/media';\nimport { StoryPropTypes } from '@googleforcreators/elements';\n\nexport const PageSizePropType = PropTypes.shape({\n  width: PropTypes.number,\n  height: PropTypes.number,\n  containerHeight: PropTypes.number,\n});\n\nStoryPropTypes.story = PropTypes.shape({\n  storyId: PropTypes.number,\n  title: PropTypes.string.isRequired,\n  status: PropTypes.string.isRequired,\n  author: PropTypes.shape({\n    id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n    name: PropTypes.string.isRequired,\n  }),\n  slug: PropTypes.string.isRequired,\n  date: PropTypes.string.isRequired,\n  modified: PropTypes.string.isRequired,\n  excerpt: PropTypes.string.isRequired,\n  featuredMedia: PropTypes.shape({\n    id: PropTypes.number.isRequired,\n    url: PropTypes.string.isRequired,\n    width: PropTypes.number.isRequired,\n    height: PropTypes.number.isRequired,\n    isExternal: PropTypes.bool,\n    needsProxy: PropTypes.bool,\n  }),\n  password: PropTypes.string.isRequired,\n  currentStoryStyles: PropTypes.object,\n  autoAdvance: PropTypes.bool,\n  defaultPageDuration: PropTypes.number,\n  backgroundAudio: PropTypes.shape({\n    resource: BackgroundAudioPropType,\n  }),\n});\n\nStoryPropTypes.size = PropTypes.exact({\n  width: PropTypes.number.isRequired,\n  height: PropTypes.number.isRequired,\n});\n\nexport const AnimationPropType = PropTypes.shape(AnimationProps);\n\nexport { StoryPropTypes };\n\n/**\n * Page object.\n *\n * @typedef {Page} Page\n * @property {Element[]} elements Array of all elements.\n */\n\n/**\n * Story object.\n *\n * @typedef {Story} Story\n * @property {Object} story - A story object.\n * @property {number} storyId Story post id.\n * @property {string} title Story title.\n * @property {string} status Post status, draft or published.\n * @property {Array<Page>} pages Array of all pages.\n * @property {Object} author Story author.\n * @property {string} slug The slug of the story.\n * @property {string} date The publish date of the story.\n * @property {string} modified The modified date of the story.\n * @property {string} content AMP HTML content.\n * @property {string} excerpt Short description.\n * @property {Object} featuredMedia Featured media object.\n * @property {string} password Password\n */\n"
  },
  {
    "path": "packages/story-editor/src/storyEditor.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StyleSheetManager, ThemeProvider } from 'styled-components';\nimport stylisRTLPlugin from 'stylis-plugin-rtl';\nObject.defineProperty(stylisRTLPlugin, 'name', { value: 'stylisRTLPlugin' });\nimport PropTypes from 'prop-types';\nimport {\n  SnackbarProvider,\n  ModalGlobalStyle,\n  PopupProvider,\n  deepMerge,\n} from '@googleforcreators/design-system';\nimport { FlagsProvider } from 'flagged';\nimport { TransformProvider } from '@googleforcreators/transform';\nimport {\n  DefaultMoveableGlobalStyle,\n  CropMoveableGlobalStyle,\n} from '@googleforcreators/moveable';\n\n/**\n * Internal dependencies\n */\nimport theme, { GlobalStyle } from './theme';\nimport ErrorBoundary from './components/errorBoundary';\nimport { ConfigProvider } from './app/config';\nimport { APIProvider } from './app/api';\nimport { Media3pApiProvider } from './app/media/media3p/api';\nimport { HistoryProvider } from './app/history';\nimport { StoryProvider } from './app/story';\nimport { FontProvider } from './app/font';\nimport { MediaProvider } from './app/media';\nimport { CurrentUserProvider } from './app/currentUser';\nimport { TaxonomyProvider } from './app/taxonomy';\nimport AutoSaveHandler from './components/autoSaveHandler';\nimport LocalAutoSaveHandler from './components/localAutoSaveHandler';\nimport { DropTargetsProvider } from './components/dropTargets';\nimport { HelpCenterProvider } from './app/helpCenter';\nimport { PageDataUrlProvider } from './app/pageDataUrls';\nimport { PageCanvasProvider } from './app/pageCanvas';\nimport DevTools from './components/devTools';\nimport KeyboardOnlyOutlines from './utils/keyboardOnlyOutline';\nimport getDefaultConfig from './getDefaultConfig';\n\nfunction StoryEditor({ config, initialEdits, children }) {\n  const _config = deepMerge(getDefaultConfig(), config);\n  const {\n    storyId,\n    isRTL,\n    flags,\n    styleConstants: { leftOffset, topOffset } = {},\n  } = _config;\n\n  return (\n    <FlagsProvider features={flags}>\n      <StyleSheetManager stylisPlugins={isRTL ? [stylisRTLPlugin] : []}>\n        <ThemeProvider theme={theme}>\n          <ErrorBoundary>\n            <ConfigProvider config={_config}>\n              <APIProvider>\n                <Media3pApiProvider>\n                  <HistoryProvider size={50}>\n                    <SnackbarProvider>\n                      <StoryProvider\n                        storyId={storyId}\n                        initialEdits={initialEdits}\n                      >\n                        <TaxonomyProvider>\n                          <CurrentUserProvider>\n                            <FontProvider>\n                              <MediaProvider>\n                                <LocalAutoSaveHandler />\n                                <AutoSaveHandler />\n                                <TransformProvider>\n                                  <DropTargetsProvider>\n                                    <HelpCenterProvider>\n                                      <PageCanvasProvider>\n                                        <PageDataUrlProvider>\n                                          <PopupProvider\n                                            value={{\n                                              isRTL,\n                                              leftOffset,\n                                              topOffset,\n                                            }}\n                                          >\n                                            <GlobalStyle />\n                                            <DevTools />\n                                            <DefaultMoveableGlobalStyle />\n                                            <CropMoveableGlobalStyle />\n                                            <ModalGlobalStyle />\n                                            <KeyboardOnlyOutlines />\n                                            {children}\n                                          </PopupProvider>\n                                        </PageDataUrlProvider>\n                                      </PageCanvasProvider>\n                                    </HelpCenterProvider>\n                                  </DropTargetsProvider>\n                                </TransformProvider>\n                              </MediaProvider>\n                            </FontProvider>\n                          </CurrentUserProvider>\n                        </TaxonomyProvider>\n                      </StoryProvider>\n                    </SnackbarProvider>\n                  </HistoryProvider>\n                </Media3pApiProvider>\n              </APIProvider>\n            </ConfigProvider>\n          </ErrorBoundary>\n        </ThemeProvider>\n      </StyleSheetManager>\n    </FlagsProvider>\n  );\n}\n\nStoryEditor.propTypes = {\n  config: PropTypes.object.isRequired,\n  initialEdits: PropTypes.object,\n  children: PropTypes.node,\n};\n\nexport default StoryEditor;\n"
  },
  {
    "path": "packages/story-editor/src/theme.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle, ThemeContext } from 'styled-components';\nimport { theme, themeHelpers } from '@googleforcreators/design-system';\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\nexport const GlobalStyle = createGlobalStyle`\n  /* WP admin menu arrow color */\n  ul#adminmenu a.wp-has-current-submenu::after {\n    border-right-color: ${theme.colors.bg.secondary};\n  }\n\n  /**\n   * Override the shell (WP) the default styling used for stories content.\n   */\n  .web-stories-content b, .web-stories-content strong {\n    font-weight: bold;\n  }\n\n  /*\n   * Scrollbars are scoped to <Editor> to make sure we don't mess with\n   * WP dialogs like the Backbone Media Gallery dialog.\n   */\n  body.edit-story #wpbody * {\n    ${themeHelpers.scrollbarCSS};\n  }\n`;\n\nexport function useTheme(selector) {\n  return useContextSelector(ThemeContext, selector ?? identity);\n}\n\nexport default theme;\n"
  },
  {
    "path": "packages/story-editor/src/types/apiProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  Taxonomy,\n  Term,\n  FontData,\n  ProductData,\n} from '@googleforcreators/elements';\nimport type {\n  Resource,\n  ResourceId,\n  TrimData,\n  VideoResource,\n} from '@googleforcreators/media';\nimport type { Template } from '@googleforcreators/templates';\n\n/**\n * Internal dependencies\n */\nimport type { RawStory, StoryReturnData, StorySaveData } from './story';\nimport type { PageTemplate } from './configProvider';\nimport type { User } from './storyEditor';\n\ninterface TemplateData {\n  story_data: PageTemplate;\n  featured_media: number;\n  title?: string;\n}\n\ntype Author = {\n  id: number;\n  name: string;\n  url?: string;\n  description?: string;\n  slug: string;\n  link: string;\n  avatarUrls?: Record<number, string>;\n};\n\ntype GetFontProps = {\n  service?: string;\n  include?: string;\n  search?: string;\n};\n\ntype HotlinkInfo = {\n  ext?: string;\n  fileName?: string;\n  fileSize?: number;\n  mimeType?: string;\n  type?: string;\n  width?: number;\n  height?: number;\n};\n\ntype LinkMetaData = {\n  title: string;\n  image: string;\n};\n\ntype UploadMediaProps = {\n  originalId?: ResourceId;\n  mediaId?: ResourceId;\n  storyId?: number | null;\n  templateId?: number;\n  optimizedId?: ResourceId;\n  cropOriginId?: ResourceId;\n  mutedId?: ResourceId;\n  posterId?: ResourceId;\n  isMuted?: boolean;\n  mediaSource?: string;\n  trimData?: TrimData;\n  baseColor?: string;\n  blurHash?: string;\n  isGif?: boolean;\n  altText?: string;\n};\n\ntype UpdateMediaProps = {\n  storyId?: number | null;\n  optimizedId?: ResourceId;\n  cropOriginId?: ResourceId;\n  mutedId?: number;\n  posterId?: ResourceId;\n  isMuted?: boolean;\n  mediaSource?: string;\n  baseColor?: string;\n  blurHash?: string;\n  altText?: string;\n};\nexport interface APICallbacks {\n  addPageTemplate?: (data: TemplateData) => Promise<PageTemplate>;\n  autoSaveById?: (story: StorySaveData) => Promise<StoryReturnData>;\n  createTaxonomyTerm?: (\n    endpoint: string,\n    term: {\n      name: string;\n      parent?: number;\n      slug?: string;\n    }\n  ) => Promise<Term>;\n  deleteMedia?: (id: number) => Promise<boolean>;\n  deletePageTemplate?: (id: number) => Promise<boolean>;\n  getAuthors?: (search_term: string) => Promise<Author[]>;\n  getCurrentUser?: () => Promise<User>;\n  getCustomPageTemplates?: (page: number | boolean) => Promise<{\n    hasMore: boolean;\n    templates: PageTemplate[];\n  }>;\n  getFonts?: (props: GetFontProps) => Promise<FontData[]>;\n  getHotlinkInfo?: (link: string) => Promise<HotlinkInfo>;\n  getLinkMetadata?: (link: string) => Promise<LinkMetaData>;\n  getMedia?: (props: {\n    mediaType: string;\n    searchTerm: string;\n    pagingNum: number;\n  }) => Promise<{\n    data: Resource[];\n    headers: Record<string, string>;\n  }>;\n  getMediaById?: (id: number) => Promise<Resource>;\n  getMediaForCorsCheck?: () => Promise<Resource[]>;\n  getMutedMediaById?: (id: ResourceId) => Promise<VideoResource>;\n  getOptimizedMediaById?: (id: ResourceId) => Promise<Resource>;\n  getPageTemplates?: (search: string) => Promise<Template[]>;\n  getPosterMediaById?: (id: ResourceId) => Promise<Resource>;\n  getProducts?: () => Promise<ProductData[]>;\n  getProxyUrl?: (src: string) => string;\n  getStoryById?: (id: number) => Promise<RawStory>;\n  getTaxonomies?: () => Promise<Taxonomy[]>;\n  getTaxonomyTerm?: (\n    termsEndpoint: string,\n    props: {\n      search?: string;\n      per_page?: number;\n    }\n  ) => Promise<Term[] | []>;\n  saveStoryById?: (data: StorySaveData) => Promise<StoryReturnData>;\n  updateCurrentUser?: (data: Partial<User>) => Promise<User>;\n  updateMedia?: (id: ResourceId, data: UpdateMediaProps) => Promise<Resource>;\n  updatePageTemplate?: (\n    id: number,\n    data: Partial<PageTemplate>\n  ) => Promise<PageTemplate>;\n  uploadMedia?: (file: File, props: UploadMediaProps) => Promise<Resource>;\n}\n\nexport interface APIState {\n  actions: APICallbacks;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/canvasProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Hex } from '@googleforcreators/patterns';\nimport type { EditingState } from '@googleforcreators/rich-text';\nimport type { Dispatch, SetStateAction } from 'react';\n\ntype NodeSetter = Dispatch<SetStateAction<Node | null>>;\ntype BoolSetter = Dispatch<SetStateAction<boolean>>;\nexport type EyedropperCallback = (rgb: Hex) => void;\nexport type RenamableLayer = null | {\n  elementId: string;\n};\nexport type VoidFuncWithNoProps = () => void;\n\ninterface CanvasActions {\n  setPageContainer: NodeSetter;\n  setFullbleedContainer: NodeSetter;\n  getNodeForElement: (id: string) => Node | undefined;\n  setNodeForElement: (id: string, ref: Node) => void;\n  setEditingElement: (element: string) => void;\n  setEditingElementWithState: (id: string, state: EditingState) => void;\n  clearEditing: VoidFuncWithNoProps;\n  handleSelectElement: (id: string, evt: MouseEvent) => void;\n  setDisplayLinkGuidelines: BoolSetter;\n  setPageAttachmentContainer: NodeSetter;\n  setCanvasContainer: NodeSetter;\n  setDesignSpaceGuideline: NodeSetter;\n  setIsEyedropperActive: BoolSetter;\n  setEyedropperCallback: Dispatch<SetStateAction<EyedropperCallback | null>>;\n  setEyedropperImg: Dispatch<SetStateAction<string | null>>;\n  setEyedropperPixelData: Dispatch<SetStateAction<Uint8ClampedArray | null>>;\n  setMoveableMount: Dispatch<SetStateAction<VoidFuncWithNoProps | null>>;\n  setRenamableLayer: Dispatch<SetStateAction<RenamableLayer>>;\n  setFloatingMenuPosition: Dispatch<SetStateAction<string | undefined>>;\n  setDisplayFloatingMenu: Dispatch<SetStateAction<boolean | undefined>>;\n}\nexport interface BoundingBoxes {\n  canvasContainer?: DOMRectReadOnly;\n  pageContainer?: DOMRectReadOnly;\n}\nexport interface CanvasState {\n  pageContainer: Node | null;\n  canvasContainer: Node | null;\n  fullbleedContainer: Node | null;\n  nodesById: Record<string, Node>;\n  // Element ID.\n  editingElement: string | null;\n  editingElementState: EditingState;\n  isEditing: boolean;\n  lastSelectionEvent: MouseEvent | null;\n  displayLinkGuidelines: boolean;\n  pageAttachmentContainer: Node | null;\n  designSpaceGuideline: Node | null;\n  isEyedropperActive: boolean;\n  eyedropperCallback: null | EyedropperCallback;\n  eyedropperImg: string | null;\n  eyedropperPixelData: Uint8ClampedArray | null;\n  boundingBoxes: BoundingBoxes;\n  clientRectObserver: IntersectionObserver | null;\n  onMoveableMount: VoidFuncWithNoProps | null;\n  renamableLayer: RenamableLayer;\n  floatingMenuPosition: string | undefined;\n  displayFloatingMenu: boolean | undefined;\n}\nexport interface CanvasProviderState {\n  state: CanvasState;\n  actions: CanvasActions;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/configProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { APICallbacks } from './apiProvider';\nimport type { Flags } from './storyEditor';\n\nexport interface Capabilities {\n  /** If the user has permissions to upload files. */\n  hasUploadMediaAction?: boolean;\n  /** If the user has permissions to manage site settings. */\n  canManageSettings?: boolean;\n}\n\ninterface MimeTypes {\n  audio?: string[];\n  image?: string[];\n  caption?: string[];\n  vector?: string[];\n  video?: string[];\n}\n\ninterface Locale {\n  locale?: string;\n  dateFormat?: string;\n  timeFormat?: string;\n  gmtOffset?: number;\n  timeZone?: string;\n  months?: string[];\n  monthsShort?: string[];\n  weekdays?: string[];\n  weekdaysShort?: string[];\n  weekdaysInitials?: string[];\n  weekStartsOn?: number;\n  timezoneAbbr?: string;\n}\n\nexport interface MetaData {\n  publisher?: string;\n}\n\nexport interface Tip {\n  title: string;\n  figureSrcImg?: string;\n  figureAlt?: string;\n  description: string[];\n  href?: string;\n}\n\nexport interface PageTemplate extends Page {\n  version: string;\n}\n\nexport interface ConfigState {\n  /** Interval in seconds. */\n  autoSaveInterval: number | null;\n  /** Interval in seconds. */\n  localAutoSaveInterval: number;\n  autoSaveLink: string;\n  isRTL: boolean;\n  locale?: Locale;\n  allowedMimeTypes: MimeTypes;\n  storyId: number | null;\n  dashboardLink: string;\n  dashboardSettingsLink: string;\n  generalSettingsLink: string;\n  cdnURL: string;\n  /** Max allowed upload in bytes */\n  maxUpload: number;\n  capabilities: Capabilities;\n  metadata: MetaData;\n  canViewDefaultTemplates: boolean;\n  /** If to show the 3rd party media in the library */\n  showMedia3p: boolean;\n  encodeMarkup: boolean;\n  ffmpegCoreUrl: string;\n  apiCallbacks: APICallbacks;\n  styleConstants: {\n    topOffset: number;\n    leftOffset: number;\n  };\n  /** Plugin version */\n  version: string;\n  /** If true, the story advances automatically */\n  globalAutoAdvance?: boolean;\n  /** Page duration in seconds in case of auto-advancing */\n  globalPageDuration?: number;\n  shoppingProvider: string;\n  mediainfoUrl: string;\n  /** Feature flags */\n  flags: Flags;\n  additionalTips: Record<string, Tip>;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/currentUserProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport type { User } from './storyEditor';\n\nexport interface CurrentUserState {\n  state: {\n    currentUser: User | null;\n  };\n  actions: {\n    toggleWebStoriesMediaOptimization: () => Promise<void> | null;\n    updateCurrentUser: (data: Partial<User>) => Promise<void> | null;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/highlightsProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Element, ElementId } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { HighlightType } from '../app/highlights/states';\n\nexport interface selectElementProps {\n  elements?: Element[];\n  elementId?: ElementId;\n  pageId?: string;\n}\n\nexport interface setHighlightProps {\n  elements?: Element[];\n  elementId?: ElementId;\n  pageId?: string;\n  highlight?: HighlightType;\n}\n\nexport type Highlight = {\n  focus: boolean;\n  showEffect?: boolean;\n  tab?: string;\n  section?: string;\n};\nexport type HighlightState = {\n  [k in HighlightType]?: Highlight;\n};\n\nexport interface HighlightsState extends HighlightState {\n  tab?: string;\n  section?: string;\n}\n\nexport interface HighlightProviderState {\n  cancelEffect: (stateKey: HighlightType) => void;\n  onFocusOut: () => void;\n  setHighlights: (highlights: setHighlightProps) => void;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/historyProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page, Story } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { ActionType } from '../app/history/reducer';\nimport type { Capabilities } from './configProvider';\n\nexport interface HistoryEntry {\n  story: Story;\n  selection: string[];\n  current: string | null;\n  pages: Page[];\n  capabilities: Capabilities;\n}\n\ninterface SetCurrentStateProps {\n  type: ActionType.SetCurrentState;\n  payload: HistoryEntry;\n}\n\ninterface ClearHistoryProps {\n  type: ActionType.ClearHistory;\n  payload?: null;\n}\n\ninterface ReplayProps {\n  type: ActionType.Replay;\n  payload: number;\n}\nexport type ReducerProps =\n  | SetCurrentStateProps\n  | ClearHistoryProps\n  | ReplayProps;\n\nexport interface HistoryReducerState {\n  entries: HistoryEntry[];\n  offset: number;\n  requestedState: null | HistoryEntry;\n  versionNumber: number;\n}\n\nexport interface Actions {\n  stateToHistory: (state: HistoryEntry) => void;\n  clearHistory: () => void;\n  resetNewChanges: () => void;\n  undo: (offset: number) => boolean;\n  redo: (offset: number) => boolean;\n}\nexport interface HistoryState {\n  currentEntry: HistoryEntry;\n  hasNewChanges: boolean;\n  requestedState: HistoryEntry | null;\n  canUndo: boolean;\n  canRedo: boolean;\n  versionNumber: number;\n}\nexport interface HistoryProviderState {\n  state: HistoryState;\n  actions: Actions;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './apiProvider';\nexport * from './canvasProvider';\nexport * from './configProvider';\nexport * from './currentUserProvider';\nexport * from './historyProvider';\nexport * from './layoutProvider';\nexport * from './pageCanvas';\nexport * from './pageDataUrls';\nexport * from './story';\nexport * from './storyEditor';\nexport * from './storyProvider';\nexport * from './storyTriggers';\nexport * from './taxonomyProvider';\n"
  },
  {
    "path": "packages/story-editor/src/types/layoutProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { CarouselState, ZoomSetting } from '../constants';\n\ninterface ScrollOffset {\n  left: number;\n  top: number;\n}\nexport interface LayoutProviderState {\n  state: {\n    pageWidth: number;\n    pageHeight: number;\n    hasHorizontalOverflow: boolean;\n    hasVerticalOverflow: boolean;\n    hasPageNavigation: boolean;\n    pagePadding: number;\n    viewportWidth: number;\n    viewportHeight: number;\n    hasExtraPages: boolean;\n    extraPageWidth: number;\n    extraPageCount: number;\n    zoomSetting: ZoomSetting;\n    zoomLevel: number;\n    workspaceWidth: number;\n    workspaceHeight: number;\n    scrollLeft: number;\n    scrollTop: number;\n    carouselState: CarouselState;\n    isCarouselInTransition: boolean;\n  };\n  actions: {\n    closeCarousel: () => void;\n    openCarousel: () => void;\n    setScrollOffset: (payload?: ScrollOffset) => void;\n    setZoomLevel: (prevState: number) => void;\n    setZoomSetting: (prevState: ZoomSetting) => void;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/pageCanvas.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { TextElement, Page } from '@googleforcreators/elements';\nimport type { Hex } from '@googleforcreators/patterns';\n\nexport type PageCanvasMap = Record<string, HTMLCanvasElement>;\nexport interface PageCanvasProviderState {\n  state: {\n    pageCanvasMap: PageCanvasMap;\n  };\n  actions: {\n    calculateAccessibleTextColors: (el: TextElement) => Promise<{\n      color?: Hex;\n      backgroundColor?: Hex;\n    }>;\n    generateDeferredPageCanvas: (props: [string, Page]) => () => void;\n    generateDeferredCurrentPageCanvas: () => void;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/pageDataUrls.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\n\nexport interface PageDataUrlsActions {\n  queuePageImageGeneration: (Page: Page) => void;\n}\n\nexport type PageDataUrls = Record<string, string>;\n\nexport type QueuePageImageGeneration = (page: Page) => void;\n\nexport interface PageDataUrlsContext {\n  state: { dataUrls: PageDataUrls };\n  actions: { queuePageImageGeneration: QueuePageImageGeneration };\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/story.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  Page,\n  ProductData,\n  StoryData,\n  Story,\n  TextElement,\n  Term,\n} from '@googleforcreators/elements';\nimport type { Pattern } from '@googleforcreators/patterns';\n\ninterface FeaturedMedia {\n  id: number;\n  height: number;\n  width: number;\n  url: string;\n  needsProxy: boolean;\n  isExternal: boolean;\n}\n\n// Data required by API callbacks for saving a story.\nexport interface StorySaveData extends Pick<\n  Story,\n  | 'title'\n  | 'status'\n  | 'author'\n  | 'date'\n  | 'modified'\n  | 'slug'\n  | 'excerpt'\n  | 'featuredMedia'\n  | 'publisherLogo'\n  | 'password'\n  | 'currentStoryStyles'\n  | 'globalStoryStyles'\n  | 'autoAdvance'\n  | 'defaultPageDuration'\n  | 'backgroundAudio'\n> {\n  storyId?: number;\n  content: string;\n  products: ProductData[];\n  pages: Page[];\n  // Term IDs.\n  web_story_data?: number[];\n}\n\n// Data that's returned from API after saving.\nexport interface StoryReturnData {\n  date: string;\n  modified: string;\n  slug: string;\n  status: string;\n  link: string;\n  previewLink: string;\n  editLink: string;\n  embedPostLink: string;\n  featuredMedia: FeaturedMedia;\n  revisions: {\n    count: number;\n    id: number;\n  };\n}\n\n// Raw story that comes to the provider from API callback.\nexport interface RawStory {\n  id: number;\n  date: string;\n  modified: string;\n  password: string;\n  slug: string;\n  status: string;\n  link: string;\n  title: {\n    raw?: string;\n    rendered?: string;\n  };\n  excerpt: {\n    raw?: string;\n    rendered?: string;\n    protected?: boolean;\n  };\n  permalinkTemplate: string;\n  storyData: StoryData;\n  stylePresets: {\n    colors?: Pattern[];\n    textStyles?: Partial<TextElement>[];\n  };\n  previewLink: string;\n  editLink: string;\n  embedPostLink: string;\n  author: {\n    id: number;\n    name: string;\n  };\n  capabilities: Record<string, boolean>;\n  extras: Record<string, unknown>;\n  featuredMedia: {\n    id: number;\n    height: number;\n    width: number;\n    url: string;\n    needsProxy: boolean;\n    isExternal: boolean;\n  };\n  publisherLogo: {\n    id: number;\n    height: number;\n    width: number;\n    url: string;\n  };\n  taxonomies: string[];\n  revisions: {\n    count: number;\n  };\n  terms: Term[] | null;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/storyEditor.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport type Flags = Record<string, boolean>;\n\nexport interface RESTError {\n  message?: string;\n  data?: {\n    status: 400 | 401 | 403 | 500;\n  };\n}\n\nexport type User = {\n  id: number;\n  mediaOptimization: boolean;\n  onboarding: Record<string, boolean>;\n  trackingOptin: boolean;\n};\n"
  },
  {
    "path": "packages/story-editor/src/types/storyProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type {\n  Page,\n  Element,\n  Group,\n  Story,\n  MediaElement,\n} from '@googleforcreators/elements';\nimport type { ResourceId } from '@googleforcreators/media';\nimport type {\n  StoryAnimation,\n  StoryAnimationState,\n} from '@googleforcreators/animation';\nimport type { Draft } from 'immer';\n\n/**\n * Internal dependencies\n */\nimport type { ActionTypes } from '../app/story/useStoryReducer/types';\nimport type { LayerDirection } from '../constants';\nimport type { StorySaveData } from './story';\nimport type { Capabilities } from './configProvider';\n\nexport type AddPageProps = {\n  page: Page;\n  position: null | number;\n  updateSelection?: boolean;\n};\nexport type AddPageAction = {\n  type: ActionTypes.AddPage;\n  payload: AddPageProps;\n};\n\nexport type DeletePageProps = {\n  pageId: string | null;\n};\nexport type DeletePageAction = {\n  type: ActionTypes.DeletePage;\n  payload: DeletePageProps;\n};\n\nexport type UpdatePageProps = {\n  pageId: string | null;\n  properties: Partial<Page>;\n};\nexport type UpdateCurrentPageProps = {\n  properties: Partial<Page>;\n};\nexport type UpdatePageAction = {\n  type: ActionTypes.UpdatePage;\n  payload: UpdatePageProps;\n};\n\nexport type ArrangePageProps = {\n  pageId: string;\n  position: number;\n};\nexport type ArrangePageAction = {\n  type: ActionTypes.ArrangePage;\n  payload: ArrangePageProps;\n};\n\nexport type SetCurrentPageProps = {\n  pageId: string;\n};\nexport type SetCurrentPagePageAction = {\n  type: ActionTypes.SetCurrentPage;\n  payload: SetCurrentPageProps;\n};\n\nexport type AddElementsProps = {\n  elements: Element[];\n  pageId?: string;\n  updateSelection?: boolean;\n};\nexport interface AddElementProps extends Omit<AddElementsProps, 'elements'> {\n  element: Element;\n}\n\nexport type AddElementsAction = {\n  type: ActionTypes.AddElements;\n  payload: AddElementsProps;\n};\n\nexport type DeleteElementsProps = {\n  elementIds: string[] | null;\n};\nexport type DeleteElementsAction = {\n  type: ActionTypes.DeleteElements;\n  payload: DeleteElementsProps;\n};\n\nexport type ElementUpdater<T = Element> = (prevProps: T) => T | Partial<T>;\nexport type UpdateElementsProps = {\n  elementIds?: string[] | null;\n  properties: Partial<Element> | ElementUpdater;\n};\nexport type UpdateElementsAction = {\n  type: ActionTypes.UpdateElements;\n  payload: UpdateElementsProps;\n};\n\nexport type UpdateElementsByResourceIdProps = {\n  id: ResourceId;\n  properties: Partial<MediaElement> | ElementUpdater<MediaElement>;\n};\nexport type UpdateElementsByResourceIdAction = {\n  type: ActionTypes.UpdateElementsByResourceId;\n  payload: UpdateElementsByResourceIdProps;\n};\n\nexport type DeleteElementsByResourceIdProps = {\n  id: ResourceId;\n};\nexport type DeleteElementsByResourceIdAction = {\n  type: ActionTypes.DeleteElementsByResourceId;\n  payload: DeleteElementsByResourceIdProps;\n};\n\nexport type CombineElementsProps = {\n  firstElement: Element;\n  secondId: string;\n  shouldRetainAnimations?: boolean;\n};\nexport type CombineElementsAction = {\n  type: ActionTypes.CombineElements;\n  payload: CombineElementsProps;\n};\n\nexport type SetBackgroundElementProps = {\n  elementId: string | null;\n};\nexport type SetBackgroundElementAction = {\n  type: ActionTypes.SetBackgroundElement;\n  payload: SetBackgroundElementProps;\n};\n\nexport type ArrangeElementProps = {\n  elementId?: string | null;\n  position: number | LayerDirection;\n  groupId?: string | false | null;\n};\nexport type ArrangeElementAction = {\n  type: ActionTypes.ArrangeElement;\n  payload: ArrangeElementProps;\n};\n\nexport type ArrangeGroupProps = {\n  groupId: string;\n  position: number | LayerDirection;\n};\nexport type ArrangeGroupAction = {\n  type: ActionTypes.ArrangeGroup;\n  payload: ArrangeGroupProps;\n};\n\ntype ElementIdsFunc = (props: string[]) => string[];\nexport type SetSelectedElementsProps = {\n  elementIds: string[] | ElementIdsFunc;\n  withLinked?: boolean;\n};\nexport type SetSelectedElementsAction = {\n  type: ActionTypes.SetSelectedElements;\n  payload: SetSelectedElementsProps;\n};\n\nexport type SelectElementProps = {\n  elementId: string;\n};\nexport type SelectElementAction = {\n  type: ActionTypes.SelectElement;\n  payload: SelectElementProps;\n};\n\nexport type UnselectElementProps = {\n  elementId: string;\n};\nexport type UnselectElementAction = {\n  type: ActionTypes.UnselectElement;\n  payload: UnselectElementProps;\n};\n\nexport type ToggleElementInSelectionProps = {\n  elementId: string;\n  withLinked?: boolean;\n};\nexport type ToggleElementInSelectionAction = {\n  type: ActionTypes.ToggleElementInSelection;\n  payload: ToggleElementInSelectionProps;\n};\n\nexport type ToggleLayerProps = {\n  elementId: string;\n  metaKey: boolean;\n  shiftKey: boolean;\n  withLinked?: boolean;\n};\nexport type ToggleLayerAction = {\n  type: ActionTypes.ToggleLayer;\n  payload: ToggleLayerProps;\n};\n\nexport type DuplicateElementsByIdProps = {\n  elementIds: string[];\n};\nexport type DuplicateElementsByIdAction = {\n  type: ActionTypes.DuplicateElementsById;\n  payload: DuplicateElementsByIdProps;\n};\n\ntype StoryUpdater = <T = Story>(story: T) => T;\nexport type UpdateStoryProps = {\n  properties: Partial<Story> | StoryUpdater;\n};\nexport type UpdateStoryAction = {\n  type: ActionTypes.UpdateStory;\n  payload: UpdateStoryProps;\n};\n\nexport type UpdateAnimationStateProps = {\n  animationState: StoryAnimationState;\n};\nexport type UpdateAnimationStateAction = {\n  type: ActionTypes.UpdateAnimationState;\n  payload: UpdateAnimationStateProps;\n};\n\nexport type AddAnimationsProps = {\n  animations: StoryAnimation[];\n};\nexport type AddAnimationsAction = {\n  type: ActionTypes.AddAnimations;\n  payload: AddAnimationsProps;\n};\n\nexport type CopySelectedElementAction = {\n  type: ActionTypes.CopySelectedElement;\n  payload: null;\n};\n\nexport type RestoreProps = Partial<ReducerState>;\nexport type RestoreAction = {\n  type: ActionTypes.Restore;\n  payload: RestoreProps;\n};\n\nexport type UpdateElementsByFontFamilyProps = {\n  family: string;\n  properties: Partial<Element> | ElementUpdater;\n};\nexport type UpdateElementsByFontFamilyAction = {\n  type: ActionTypes.UpdateElementsByFontFamily;\n  payload: UpdateElementsByFontFamilyProps;\n};\n\nexport type AddGroupProps = {\n  groupId: string;\n  name: string;\n  isLocked?: boolean;\n};\nexport type AddGroupAction = {\n  type: ActionTypes.AddGroup;\n  payload: AddGroupProps;\n};\n\nexport type UpdateGroupProps = {\n  groupId: string;\n  properties: Partial<Group>;\n};\nexport type UpdateGroupAction = {\n  type: ActionTypes.UpdateGroup;\n  payload: UpdateGroupProps;\n};\n\nexport type DeleteGroupProps = { groupId: string; includeElements?: boolean };\nexport type DeleteGroupAction = {\n  type: ActionTypes.DeleteGroup;\n  payload: DeleteGroupProps;\n};\n\nexport type DuplicateGroupProps = {\n  oldGroupId: string;\n  groupId: string;\n  name: string;\n  isLocked: boolean;\n};\nexport type DuplicateGroupAction = {\n  type: ActionTypes.DuplicateGroup;\n  payload: DuplicateGroupProps;\n};\n\nexport type RemoveElementFromGroupProps = {\n  elementId: string;\n  groupId: string;\n};\nexport type RemoveElementFromGroupAction = {\n  type: ActionTypes.RemoveElementFromGroup;\n  payload: RemoveElementFromGroupProps;\n};\n\nexport type AddElementsAcrossPagesProps = {\n  page: Page;\n  position: number;\n  elements: Element[];\n};\nexport type AddElementsAcrossPagesAction = {\n  type: ActionTypes.AddElementsAcrossPages;\n  payload: AddElementsAcrossPagesProps;\n};\n\nexport type ReducerActionProps =\n  | AddPageAction\n  | DeletePageAction\n  | UpdatePageAction\n  | ArrangePageAction\n  | SetCurrentPagePageAction\n  | AddElementsAction\n  | DeleteElementsAction\n  | UpdateElementsAction\n  | UpdateElementsByResourceIdAction\n  | DeleteElementsByResourceIdAction\n  | CombineElementsAction\n  | SetBackgroundElementAction\n  | ArrangeElementAction\n  | ArrangeGroupAction\n  | SetSelectedElementsAction\n  | SelectElementAction\n  | UnselectElementAction\n  | ToggleElementInSelectionAction\n  | ToggleLayerAction\n  | DuplicateElementsByIdAction\n  | UpdateStoryAction\n  | UpdateAnimationStateAction\n  | AddAnimationsAction\n  | CopySelectedElementAction\n  | RestoreAction\n  | UpdateElementsByFontFamilyAction\n  | AddGroupAction\n  | UpdateGroupAction\n  | DeleteGroupAction\n  | DuplicateGroupAction\n  | RemoveElementFromGroupAction\n  | AddElementsAcrossPagesAction;\n\nexport type Restore = (props: RestoreProps) => ReducerState;\nexport type InternalActions = {\n  restore: Restore;\n};\n\ninterface DeleteElementProps {\n  elementId: string;\n}\ninterface UpdateElementProps<T extends Element = Element> {\n  elementId: string;\n  properties: Partial<T> | ElementUpdater<T>;\n}\nexport type ExternalActions = {\n  addAnimations: (props: AddAnimationsProps) => ReducerState;\n  updateStory: (props: UpdateStoryProps) => ReducerState;\n  addPage: (props: AddPageProps) => ReducerState;\n  addPageAt: (props: AddPageProps) => ReducerState;\n  copySelectedElement: () => ReducerState;\n  deletePage: (props: DeletePageProps) => ReducerState;\n  deleteCurrentPage: () => ReducerState;\n  updatePageProperties: (props: UpdatePageProps) => ReducerState;\n  updateCurrentPageProperties: (props: UpdateCurrentPageProps) => ReducerState;\n  arrangePage: (props: ArrangePageProps) => ReducerState;\n  setCurrentPage: (props: SetCurrentPageProps) => ReducerState;\n  addElements: (props: AddElementsProps) => ReducerState;\n  addElement: (props: AddElementProps) => ReducerState;\n  deleteElementsById: (props: DeleteElementsProps) => ReducerState;\n  deleteElementById: (props: DeleteElementProps) => ReducerState;\n  deleteSelectedElements: () => ReducerState;\n  updateElementsById: (props: UpdateElementsProps) => ReducerState;\n  updateElementsByResourceId: (\n    props: UpdateElementsByResourceIdProps\n  ) => ReducerState;\n  deleteElementsByResourceId: (\n    props: DeleteElementsByResourceIdProps\n  ) => ReducerState;\n  updateElementById: <T extends Element = Element>(\n    props: UpdateElementProps<T>\n  ) => ReducerState;\n  duplicateElementsById: (props: DuplicateElementsByIdProps) => ReducerState;\n  updateSelectedElements: (props: UpdateElementsProps) => ReducerState;\n  combineElements: (props: CombineElementsProps) => ReducerState;\n  setBackgroundElement: (props: SetBackgroundElementProps) => ReducerState;\n  clearBackgroundElement: () => ReducerState;\n  arrangeElement: (props: ArrangeElementProps) => ReducerState;\n  arrangeGroup: (props: ArrangeGroupProps) => ReducerState;\n  arrangeSelection: (props: ArrangeElementProps) => ReducerState;\n  setSelectedElementsById: (props: SetSelectedElementsProps) => ReducerState;\n  clearSelection: () => ReducerState;\n  addElementToSelection: (props: SelectElementProps) => ReducerState;\n  removeElementFromSelection: (props: UnselectElementProps) => ReducerState;\n  toggleElementInSelection: (\n    props: ToggleElementInSelectionProps\n  ) => ReducerState;\n  updateAnimationState: (props: UpdateAnimationStateProps) => ReducerState;\n  toggleLayer: (props: ToggleLayerProps) => ReducerState;\n  updateElementsByFontFamily: (\n    props: UpdateElementsByFontFamilyProps\n  ) => ReducerState;\n  addGroup: (props: AddGroupProps) => ReducerState;\n  updateGroupById: (props: UpdateGroupProps) => ReducerState;\n  deleteGroupById: (props: DeleteGroupProps) => ReducerState;\n  deleteGroupAndElementsById: (props: DeleteGroupProps) => ReducerState;\n  duplicateGroupById: (props: DuplicateGroupProps) => ReducerState;\n  removeElementFromGroup: (props: RemoveElementFromGroupProps) => ReducerState;\n  addElementsAcrossPages: (props: AddElementsAcrossPagesProps) => ReducerState;\n};\nexport interface ReducerProviderState {\n  state: ReducerState;\n  internal: InternalActions;\n  api: ExternalActions;\n}\n\nexport interface CopiedElementState {\n  animations?: StoryAnimation[];\n  styles?: Record<string, unknown>;\n  type?: string;\n}\nexport interface ReducerState {\n  story: Story;\n  selection: string[];\n  current: string | null;\n  pages: Page[];\n  animationState: StoryAnimationState;\n  capabilities: Capabilities;\n  copiedElementState?: CopiedElementState;\n}\nexport type ReducerStateDraft = Draft<ReducerState>;\n\nexport interface State extends Omit<ReducerState, 'current' | 'selection'> {\n  currentPage: Page | null;\n  currentPageId: string | null;\n  currentPageIndex: number | null;\n  currentPageNumber: number | null;\n  selectedElementIds: string[];\n  selectedElements: Element[];\n  selectedElementAnimations: StoryAnimation[];\n  hasSelection: boolean;\n  meta: {\n    isSaving: boolean;\n    isSavingStory: boolean;\n    isAutoSavingStory: boolean;\n    isFreshlyPublished: boolean;\n    isFreshlyPending: boolean;\n  };\n}\n\ninterface SaveActions {\n  autoSave: (props: Partial<StorySaveData>) => void;\n  saveStory: (props: Partial<StorySaveData>) => void;\n  restoreLocalAutoSave: () => void;\n}\nexport interface StoryProviderState {\n  state: State;\n  actions: ExternalActions & SaveActions;\n  internal: {\n    reducerState: ReducerState;\n    restore: Restore;\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/storyTriggers.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport type { State } from './storyProvider';\n\nexport type Listener = (props?: State) => void;\nexport type StoryTriggersState = (\n  | ((eventType: string, listener: Listener) => () => void)\n  | ((eventType: string) => void)\n)[];\n\nexport interface OnActionProps {\n  currentStory: State;\n  dispatchStoryEvent: (eventType: string) => void;\n  previousStory: State | null;\n}\n"
  },
  {
    "path": "packages/story-editor/src/types/taxonomyProvider.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Taxonomy, Term, TermId } from '@googleforcreators/elements';\n\nexport interface TaxonomySearchArgs {\n  search?: string;\n  per_page?: number;\n}\n\nexport interface createTermProps {\n  taxonomy: Taxonomy;\n  termName: string;\n  parent: { id?: TermId; slug: string; addToSelection: boolean };\n  addToSelection?: boolean;\n}\n\nexport interface addSearchResultsToCacheProps {\n  taxonomy: Taxonomy;\n  args: TaxonomySearchArgs;\n  addNameToSelection?: boolean;\n}\n\nexport interface TaxonomyState {\n  state: { taxonomies: Taxonomy[]; termCache: Term[]; terms: Term[] };\n  actions: {\n    createTerm: (props: createTermProps) => Promise<void>;\n    addSearchResultsToCache: (\n      props: addSearchResultsToCacheProps\n    ) => Promise<Term[] | void>;\n    addTerms: (newTerms: Term[]) => void;\n    removeTerms: (deleteTerms: Term[]) => void;\n  };\n}\n\nexport interface TaxonomyRestError {\n  message?: string;\n  data?: {\n    status: 400 | 401 | 403 | 500;\n  };\n  code: string;\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/apcx-hues.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\ndeclare module '@ap.cx/hues' {\n  interface Rgba {\n    r: number;\n    g: number;\n    b: number;\n    a?: number;\n  }\n  export function relativeLuminance(rgba: Rgba): number;\n  export function str2rgba(str: string): Rgba;\n  export function contrast(l1: number, l2: number): number;\n  export function aa(ratio: number, font: number): boolean;\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/colorthief.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '@pioug/colorthief' {\n  type Color = [number, number, number];\n\n  export default class ColorThief {\n    getColor: (img: HTMLImageElement | null) => Color;\n    getPalette: (img: HTMLImageElement | null) => Color[];\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/dom.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// See https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#more-libdomdts-refinements\n\ninterface AudioTrack {\n  enabled: boolean;\n  id: string;\n  kind:\n    | 'alternative'\n    | 'descriptions'\n    | 'main'\n    | 'main-desc'\n    | 'translation'\n    | 'commentary'\n    | '';\n  label: string;\n  language: string;\n  sourceBuffer: SourceBuffer | null;\n}\n\ninterface AudioTrackList {\n  [Symbol.iterator](): IterableIterator<AudioTrack>;\n  length: number;\n}\n\ninterface HTMLVideoElement {\n  readonly audioTracks?: AudioTrackList;\n  readonly mozHasAudio?: boolean;\n  readonly webkitAudioDecodedByteCount?: number;\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/global.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { HeifDecoder } from 'libheif-js';\n\ndeclare global {\n  var WEB_STORIES_ENV: string;\n}\n\ndeclare global {\n  interface Array<T> {\n    findLastIndex(\n      predicate: (value: T, index: number, obj: T[]) => unknown,\n      thisArg?: unknown\n    ): number;\n  }\n\n  interface Window {\n    // Made available by Editor.php\n    // See https://github.com/GoogleForCreators/web-stories-wp/pull/13015\n    libheif: {\n      HeifDecoder: typeof HeifDecoder;\n    };\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/libheif-js.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\ndeclare module 'libheif-js' {\n  interface DecodeResult {\n    img: {\n      is_primary: boolean;\n      thumbnails: number;\n      width: number;\n      height: number;\n    } | null;\n    get_width: () => number;\n    get_height: () => number;\n    is_primary: () => boolean;\n    display: (\n      base: ImageData,\n      callback: (result: ImageData | null) => void\n    ) => void;\n  }\n\n  type DecodeResultType = DecodeResult[];\n\n  class HeifDecoder implements HeifDecoder {\n    constructor();\n    decode(buffer: ArrayBuffer): DecodeResultType;\n  }\n}\n"
  },
  {
    "path": "packages/story-editor/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/__mocks__/getBlurHashFromImage.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * mock function for getBlurHashFromImage. Prevents `import.meta` from being called in the jest context.\n *\n * @param {string} src The url.\n * @return {string} The blur hash string.\n */\nconst getBlurHashFromImageMock = (src = 'default') => {\n  return `${src}-blur-hash`;\n};\n\nexport default getBlurHashFromImageMock;\n"
  },
  {
    "path": "packages/story-editor/src/utils/cleanForSlug.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport removeAccents from 'remove-accents';\n\n/**\n * Performs some basic cleanup of a string for use as a post slug.\n *\n * This replicates some of what `sanitize_title()` does in WordPress core, but\n * is only designed to approximate what the slug will be.\n *\n * Converts Latin-1 Supplement and Latin Extended-A letters to basic Latin\n * letters. Removes combining diacritical marks. Converts whitespace, periods,\n * and forward slashes to hyphens. Removes any remaining non-word characters\n * except hyphens. Converts remaining string to lowercase. It does not account\n * for octets, HTML entities, or other encoded characters.\n *\n * @see https://github.com/WordPress/gutenberg/blob/5ff5acd2815d5260db15ab155fcaf4b3b80d7c1b/packages/url/src/clean-for-slug.js\n * @param string Title or slug to be processed.\n * @param isEditing Flag the user is currently editing the input\n allowing extra hyphens (default false)\n * @return Processed string.\n */\nexport default function cleanForSlug(string: string, isEditing = false) {\n  if (!string) {\n    return '';\n  }\n\n  const pipe: [string] = [string];\n\n  return (\n    pipe\n      .map((s) => removeAccents(s))\n      // Convert each group of whitespace, periods, and forward slashes to a hyphen.\n      .map((s) => s.replace(/[\\s./_]/g, '-'))\n      // If not editing, remove hyphens from the beginning and ending.\n      .map((s) => (isEditing ? s : s.replace(/^-+|-+$/g, '')))\n      .map((s) => s.normalize('NFC'))\n      // Remove anything that's not a letter, number, underscore or hyphen.\n      .map((s) => (isEditing ? s : s.replace(/[^\\p{L}\\p{N}_-]+/gu, '')))\n      .map((s) => (isEditing ? s : s.replace(/--+/g, '-')))\n      .map((s) => s.toLowerCase())\n      .pop() as string\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/contrastUtils.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\nimport * as hues from '@ap.cx/hues';\nimport type { Hex } from '@googleforcreators/patterns';\n\n/**\n * Calculate luminance from RGB Object\n */\nexport function calculateLuminanceFromRGB(rgb: Hex) {\n  const { r, g, b, a = 1.0 } = rgb;\n  const luminance = hues.relativeLuminance({\n    r: r / 255.0,\n    g: g / 255.0,\n    b: b / 255.0,\n    a,\n  });\n  return luminance;\n}\n\n/**\n * Calculate luminance from style color string\n */\nexport function calculateLuminanceFromStyleColor(styleColor: string) {\n  const rgb = hues.str2rgba(styleColor);\n  return hues.relativeLuminance(rgb);\n}\n\ninterface ContrastReturn {\n  ratio: number;\n  WCAG_AA: boolean;\n}\n/**\n * 18 point text or 14 point bold text is judged to be large enough to require a lower contrast ratio.\n * https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html\n */\n/**\n * Check contrast ratios from luminances for WCAG guidelines\n */\nexport function checkContrastFromLuminances(\n  luminanceA: number,\n  luminanceB: number,\n  fontSize: number\n): ContrastReturn {\n  const ratio = hues.contrast(luminanceA, luminanceB);\n  return { ratio, WCAG_AA: hues.aa(ratio, fontSize) };\n}\n\ntype RgbArray = [number, number, number, number?];\n/**\n * Calculates contrast between two rgb colors, considering font size.\n */\nfunction calculateContrast(\n  rgb1: RgbArray,\n  rgb2: RgbArray,\n  fontSize: number\n): ContrastReturn {\n  const lum1 = calculateLuminanceFromRGB({\n    r: rgb1[0],\n    g: rgb1[1],\n    b: rgb1[2],\n  });\n  const lum2 = calculateLuminanceFromRGB({\n    r: rgb2[0],\n    g: rgb2[1],\n    b: rgb2[2],\n  });\n  return checkContrastFromLuminances(lum1, lum2, fontSize);\n}\n\n/**\n * Gets accessible colors from pixel data. Returns the text color and background color.\n */\nexport function getAccessibleTextColorsFromPixels(\n  pixelData: Uint8ClampedArray,\n  fontSize: number\n) {\n  const white: RgbArray = [255, 255, 255, 255];\n  const black: RgbArray = [0, 0, 0, 255];\n  const colors: RgbArray[] = [];\n\n  const whiteRgb = {\n    r: 255,\n    g: 255,\n    b: 255,\n    a: 1,\n  };\n  const blackRgb = {\n    r: 0,\n    g: 0,\n    b: 0,\n    a: 1,\n  };\n\n  for (let i = 0; i < pixelData.length; i += 4) {\n    colors.push([\n      pixelData[i],\n      pixelData[i + 1],\n      pixelData[i + 2],\n      pixelData[i + 3],\n    ]);\n  }\n\n  const contrasts = colors.map((c) => calculateContrast(black, c, fontSize));\n  const contrastIsOK = !contrasts.some(({ WCAG_AA }) => !WCAG_AA);\n\n  if (contrastIsOK) {\n    return {\n      color: blackRgb,\n    };\n  }\n\n  // Try white color.\n  const altContrasts = colors.map((c) => calculateContrast(white, c, fontSize));\n  const altContrastIsOK = !altContrasts.some(({ WCAG_AA }) => !WCAG_AA);\n\n  if (altContrastIsOK) {\n    return {\n      color: whiteRgb,\n    };\n  }\n\n  const whiteHighlightWorksBetter =\n    contrasts.reduce((a, c) => a + c.ratio, 0) <\n    altContrasts.reduce((a, c) => a + c.ratio, 0);\n\n  if (whiteHighlightWorksBetter) {\n    // Black fg color and white bg color.\n    return {\n      color: blackRgb,\n      backgroundColor: { ...whiteRgb, a: 0.7 },\n    };\n  }\n\n  // White fg color and black bg color.\n  return {\n    color: whiteRgb,\n    backgroundColor: { ...blackRgb, a: 0.7 },\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/copyPaste.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderToStaticMarkup } from '@googleforcreators/react';\nimport {\n  getDefinitionForType,\n  duplicateElement,\n  elementIs,\n} from '@googleforcreators/elements';\nimport type { Groups, Element, Page } from '@googleforcreators/elements';\nimport type { StoryAnimation } from '@googleforcreators/animation';\n\n/**\n * Internal dependencies\n */\nimport generateGroupName from './generateGroupName';\n\nconst DOUBLE_DASH_ESCAPE = '_DOUBLEDASH_';\n\ninterface ProcessPastedElementsReturn {\n  animations: StoryAnimation[];\n  elements: Element[];\n  groups?: Groups;\n}\n\ninterface Payload {\n  sentinel?: string;\n  items?: Element[];\n  groups?: Groups;\n  animations?: StoryAnimation[];\n  selectedElements?: Element[];\n}\n/**\n * Processes pasted content to find story elements.\n */\nexport function processPastedElements(\n  content: DocumentFragment,\n  currentPage: Page,\n  selectedElements?: Element[]\n): ProcessPastedElementsReturn {\n  let foundElementsAndAnimations: ProcessPastedElementsReturn = {\n    animations: [],\n    elements: [],\n  };\n  for (let n = content.firstChild; n; n = n.nextSibling) {\n    if (\n      n.nodeType !== /* COMMENT */ 8 ||\n      n.nodeValue?.indexOf('Fragment') !== -1\n    ) {\n      continue;\n    }\n    const payload = JSON.parse(\n      n.nodeValue.replace(new RegExp(DOUBLE_DASH_ESCAPE, 'g'), '--')\n    ) as Payload;\n    if (payload.sentinel !== 'story-elements' || !payload.items) {\n      continue;\n    }\n\n    const processedPayload = payload.items.reduce(\n      (\n        {\n          elements,\n          animations,\n        }: { elements: Element[]; animations: StoryAnimation[] },\n        payloadElement: Element,\n        index: number\n      ) => {\n        const offsetBase =\n          selectedElements && selectedElements[index]\n            ? {\n                x: selectedElements[index].x,\n                y: selectedElements[index].y,\n              }\n            : undefined;\n        const { element, elementAnimations } = duplicateElement({\n          element: payloadElement,\n          animations: payload.animations,\n          currentElements: currentPage.elements,\n          offsetBase,\n        });\n\n        return {\n          elements: [...elements, element],\n          animations: [...animations, ...elementAnimations],\n        };\n      },\n      { animations: [], elements: [] }\n    );\n\n    const groups = { ...payload.groups };\n    for (const prop of Object.keys(groups)) {\n      groups[prop].name = generateGroupName(groups, groups[prop].name);\n    }\n\n    foundElementsAndAnimations = {\n      animations: [\n        ...foundElementsAndAnimations.animations,\n        ...processedPayload.animations,\n      ],\n      elements: [\n        ...foundElementsAndAnimations.elements,\n        ...processedPayload.elements,\n      ],\n      groups: groups,\n    };\n    return foundElementsAndAnimations;\n  }\n  return foundElementsAndAnimations;\n}\n\n/**\n * Processes copied/cut content for preparing elements to add to clipboard.\n */\nexport function addElementsToClipboard(\n  page: Page,\n  elements: Element[],\n  animations: StoryAnimation[],\n  groups: Groups,\n  evt: ClipboardEvent\n) {\n  if (!elements.length || !evt) {\n    return;\n  }\n  const { clipboardData } = evt;\n  if (!clipboardData) {\n    return;\n  }\n  const payload = {\n    sentinel: 'story-elements',\n    // @todo: Ensure that there's no unserializable data here. The easiest\n    // would be to keep all serializable data together and all non-serializable\n    // in a separate property.\n    items: elements.map((element) => ({\n      ...element,\n      ...(elementIs.defaultBackground(element)\n        ? { backgroundColor: page.backgroundColor }\n        : null),\n    })),\n    animations,\n    groups,\n  };\n  const serializedPayload = JSON.stringify(payload).replace(\n    /--/g,\n    DOUBLE_DASH_ESCAPE\n  );\n\n  const textContent = elements\n    .map((el) => {\n      const { type } = el;\n      const { TextContent } = getDefinitionForType(type);\n      if (TextContent) {\n        return TextContent(el);\n      }\n      return type;\n    })\n    .join('\\n');\n\n  const htmlContent = elements\n    .map((el) => {\n      const { type, x, y, rotationAngle } = el;\n      const { Output } = getDefinitionForType(type);\n      return renderToStaticMarkup(\n        <Output\n          element={el}\n          box={{ width: 100, height: 100, x, y, rotationAngle }}\n          flags={{}}\n        />\n      );\n    })\n    .join('\\n');\n\n  clipboardData.setData('text/plain', textContent);\n  clipboardData.setData(\n    'text/html',\n    `<!-- ${serializedPayload} -->${htmlContent}`\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/createError.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nclass CustomError extends Error {\n  public file = '';\n  public isUserError = false;\n}\n/**\n * Helper function to get create a js error.\n *\n * @param name Error name.\n * @param fileName File name.\n * @param message Message in error.\n * @return Error Object.\n */\nfunction createError(name: string, fileName: string, message: string) {\n  const validError = new CustomError();\n\n  validError.name = name;\n  validError.file = fileName;\n  validError.isUserError = true;\n  validError.message = message;\n\n  return validError;\n}\n\nexport default createError;\n"
  },
  {
    "path": "packages/story-editor/src/utils/createThumbnailCanvasFromFullbleedCanvas.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { PAGE_RATIO } from '@googleforcreators/units';\n\n/**\n * Creates a thumbnail aspect ratio canvas when given a fullbleed aspect\n * ratio canvas.\n *\n * @param fullbleedCanvas fullbleed aspect ratio canvas element\n * @return a new thumbnail aspect ratio canvas element\n */\nfunction createThumbnailCanvasFromFullbleedCanvas(\n  fullbleedCanvas: HTMLCanvasElement\n) {\n  const thumbnailCanvas = document.createElement('canvas');\n  const thumbnailContext = thumbnailCanvas.getContext('2d');\n\n  const fullbleedHeight = Number(fullbleedCanvas.height);\n  const thumbnailHeight = Number(fullbleedCanvas.width) / PAGE_RATIO;\n  const dy = (fullbleedHeight - thumbnailHeight) / 2;\n  thumbnailCanvas.width = fullbleedCanvas.width;\n  thumbnailCanvas.height = thumbnailHeight;\n  if (thumbnailContext) {\n    thumbnailContext.drawImage(fullbleedCanvas, 0, -dy);\n  }\n  return thumbnailCanvas;\n}\n\nexport default createThumbnailCanvasFromFullbleedCanvas;\n"
  },
  {
    "path": "packages/story-editor/src/utils/dragEvent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { DragEvent } from 'react';\n\n/**\n * Get Drag Type from event.\n *\n * @param  e The drag event.\n * @param type The type of transfer payload to test against\n * @return Whether the drag is of the specified type\n */\nexport function isDragType(e: DragEvent, type: string) {\n  if (!e?.dataTransfer?.types) {\n    return false;\n  }\n  return e.dataTransfer.types.includes(type);\n}\n\n/**\n * Get Drag Type from event.\n *\n * @param e The drag event.\n * @return Whether the drag event is relating to a file transfer\n */\nexport function isDraggingFile(e: DragEvent) {\n  return isDragType(e, 'Files');\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/generateBlurhash.worker.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { encode } from 'blurhash';\n\nconst callback = (event) => {\n  const { image, width, height, componentX, componentY } = event.data;\n\n  // Bail early if the message is not for us.\n  if (!image) {\n    return;\n  }\n\n  try {\n    const blurHash = encode(image, width, height, componentX, componentY);\n    postMessage({\n      type: 'success',\n      blurHash,\n    });\n  } catch (error) {\n    postMessage({\n      type: 'error',\n      error,\n    });\n  }\n};\n\nself.addEventListener('message', callback);\n\n// Only needed for Rollup, not webpack v4.\nexport default { callback };\n"
  },
  {
    "path": "packages/story-editor/src/utils/generateGroupName.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport type { Groups } from '@googleforcreators/elements';\n\nexport function getNextGroupNumber(groups: Groups) {\n  const nums = [0];\n  const defaultName = __('Group', 'web-stories');\n  for (const prop in groups) {\n    if (!Object.prototype.hasOwnProperty.call(groups[prop], 'name')) {\n      continue;\n    }\n    const parts = groups[prop]?.name.split(' ');\n    if (parts[0] === defaultName && parts[1]) {\n      nums.push(Number(parts[1]));\n    }\n  }\n  return Math.max(...nums) + 1;\n}\n\nfunction generateGroupName(groups: Groups, name = '') {\n  if (!name) {\n    const groupNumber = getNextGroupNumber(groups);\n    return sprintf(\n      /* translators: %d: group number. */\n      __('Group %d', 'web-stories'),\n      groupNumber\n    );\n  }\n\n  return sprintf(\n    /* translators: %s: name of layer. */\n    __('%s Copy', 'web-stories'),\n    name\n  );\n}\n\nexport default generateGroupName;\n"
  },
  {
    "path": "packages/story-editor/src/utils/getBlurHashFromImage.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { preloadImage } from '@googleforcreators/media';\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport Worker from './generateBlurhash.worker';\n\nconst getImageData = (image) => {\n  const { width, height } = image;\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n\n  const ctx = canvas.getContext('2d');\n  ctx.drawImage(image, 0, 0);\n  return ctx.getImageData(0, 0, width, height);\n};\n\nconst getBlurHashFromImage = async (src) => {\n  let image;\n  try {\n    image = await preloadImage({ src });\n  } catch {\n    return Promise.reject(new Error('Failed to get blurhash from image'));\n  }\n\n  let imageData;\n\n  try {\n    imageData = getImageData(image);\n  } catch {\n    // For example if `CanvasRenderingContext2D.getImageData()` throws.\n    return Promise.reject(new Error('Failed to get blurhash from image'));\n  }\n\n  const { data, width, height } = imageData;\n\n  const trackTiming = getTimeTracker('load_get_blurhash');\n  return new Promise((resolve, reject) => {\n    const worker = new Worker();\n\n    worker.postMessage({\n      image: data,\n      width,\n      height,\n      componentX: 4,\n      componentY: 4,\n    });\n    worker.addEventListener('message', (event) => {\n      worker.terminate();\n      trackTiming();\n      if (event.data.type === 'success') {\n        resolve(event.data.blurHash);\n      } else {\n        trackError('blurhash_generation', event.data.error?.message);\n        reject(event.data.error);\n      }\n    });\n    worker.addEventListener('error', (e) => {\n      worker.terminate();\n      trackTiming();\n      trackError('blurhash_generation', e?.message);\n      reject(e);\n    });\n  });\n};\nexport default getBlurHashFromImage;\n"
  },
  {
    "path": "packages/story-editor/src/utils/getCropParams.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { MediaElement } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport type { CropParams } from '../app/media/types';\nimport { isOffCanvas } from './isOffCanvas';\n\nexport function getCropParams({\n  x,\n  y,\n  width,\n  height,\n  rotationAngle,\n  resource,\n}: MediaElement): CropParams {\n  const { offCanvasLeft, offCanvasRight, offCanvasTop, offCanvasBottom } =\n    isOffCanvas({ x, y, width, height, rotationAngle });\n  const percentage = width / resource.width;\n  const multiplier = 100 / (percentage * 100);\n  const offCanvasX = Math.floor((offCanvasLeft + offCanvasRight) * multiplier);\n  const offCanvasY = Math.floor((offCanvasTop + offCanvasBottom) * multiplier);\n  const cropWidth = resource.width - offCanvasX;\n  const cropHeight = resource.height - offCanvasY;\n  const cropX = Math.floor(offCanvasLeft * multiplier);\n  const cropY = Math.floor(offCanvasTop * multiplier);\n  return {\n    cropElement: { x, y },\n    cropWidth,\n    cropHeight,\n    cropX,\n    cropY,\n    newWidth: width - offCanvasLeft - offCanvasRight,\n    newHeight: height - offCanvasTop - offCanvasBottom,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/getInUseFonts.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { Page } from '@googleforcreators/elements';\nimport type { TextSet } from '@googleforcreators/text-sets';\nimport { elementIs } from '@googleforcreators/elements';\n\n/**\n * Returns a list of font names used across all pages in a story.\n */\nexport function getInUseFontsForPages(pages: Page[]) {\n  return (\n    Array.from(\n      new Set(\n        pages\n          .flatMap(({ elements = [] }) =>\n            elements.map((element) =>\n              elementIs.text(element) ? element.font.family : null\n            )\n          )\n          .filter(Boolean)\n      )\n    ) || []\n  );\n}\n\ninterface GetTextSetsForFontsProps {\n  fonts: string[];\n  textSets: TextSet[];\n}\n\n/**\n * Returns a list of text sets that include the fonts provided in the options object.\n *\n * @param options Object containing an array of fonts and text sets to filter.\n * @return List of text sets that match the array of fonts.\n */\nexport function getTextSetsForFonts({\n  fonts,\n  textSets,\n}: GetTextSetsForFontsProps) {\n  return textSets\n    .map((currentTextSet) => {\n      const hasFontInUse = currentTextSet.elements.reduce(\n        (elementMemo, currentElement) => {\n          if (!elementIs.text(currentElement)) {\n            return elementMemo;\n          }\n\n          return (\n            elementMemo || fonts.indexOf(currentElement.font.family) !== -1\n          );\n        },\n        false\n      );\n      return hasFontInUse && currentTextSet;\n    })\n    .filter(Boolean);\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/getInsertedElementSize.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  dataPixels,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n  DEFAULT_DPR,\n} from '@googleforcreators/units';\nimport { getDefinitionForType } from '@googleforcreators/elements';\nimport type {\n  Element,\n  ElementType,\n  Direction,\n} from '@googleforcreators/elements';\nimport type { Resource } from '@googleforcreators/media';\n\nconst RESIZE_WIDTH_DIRECTION: Direction = [1, 0];\n\nfunction isNum(value: unknown): value is number {\n  return typeof value === 'number';\n}\n\nfunction getInsertedElementSize(\n  type: ElementType,\n  width?: number,\n  height?: number,\n  attrs = {},\n  ratio = 1,\n  resource?: Resource\n) {\n  if (!isNum(width)) {\n    if (isNum(height)) {\n      // Height is known: use aspect ratio.\n      width = height * ratio;\n    } else if (resource) {\n      // Resource is available: take resource's width with DPR, but limit\n      // to fit on the page (80% max).\n      width = Math.min(resource.width * DEFAULT_DPR, PAGE_WIDTH * 0.8);\n    } else {\n      // Default to half of page.\n      width = PAGE_WIDTH / 2;\n    }\n  }\n  if (!isNum(height)) {\n    const elementType = getDefinitionForType(type);\n    if (\n      elementType &&\n      elementType.updateForResizeEvent &&\n      elementType.defaultAttributes\n    ) {\n      const { updateForResizeEvent, defaultAttributes } = elementType;\n\n      // Try resize API with width-only direction.\n      const { height: newHeight } = updateForResizeEvent(\n        {\n          ...defaultAttributes,\n          ...attrs,\n        } as Element,\n        RESIZE_WIDTH_DIRECTION,\n        width,\n        0\n      );\n      height = newHeight;\n    }\n  }\n  if (!isNum(height)) {\n    // Fallback to simple ratio calculation.\n    height = width / ratio;\n  }\n\n  // Ensure that the element fits on the page.\n  if (width > PAGE_WIDTH || height > PAGE_HEIGHT) {\n    const pageRatio = PAGE_WIDTH / PAGE_HEIGHT;\n    const newRatio = width / height;\n    if (newRatio <= pageRatio) {\n      width = Math.min(width, PAGE_WIDTH);\n      height = width / newRatio;\n    } else {\n      height = Math.min(height, PAGE_HEIGHT);\n      width = height * newRatio;\n    }\n  }\n  width = dataPixels(width);\n  height = dataPixels(height);\n  return { width, height };\n}\n\nexport default getInsertedElementSize;\n"
  },
  {
    "path": "packages/story-editor/src/utils/getMediaBaseColor.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getTimeTracker, trackError } from '@googleforcreators/tracking';\nimport { getHexFromSolidArray } from '@googleforcreators/patterns';\nimport { preloadImage } from '@googleforcreators/media';\n\n/**\n * Extracts the base color from an image element.\n *\n * @param img Image.\n * @return Hex color.\n */\nasync function extractColorFromImage(img: HTMLImageElement): Promise<string> {\n  const { default: ColorThief } = await import(\n    /* webpackChunkName: \"chunk-colorthief\" */ '@pioug/colorthief'\n  );\n\n  return new Promise((resolve, reject) => {\n    try {\n      const thief = new ColorThief();\n      const rgb = thief.getColor(img);\n      resolve(getHexFromSolidArray(rgb));\n    } catch (err) {\n      if (err instanceof Error) {\n        void trackError('image_base_color', err.message);\n      }\n      reject(err as Error);\n    }\n  });\n}\n\n/**\n * Returns an images media base color as a hex string.\n *\n * @param src Image src.\n * @param [width] Image width.\n * @param [height] Image height.\n * @return Hex color.\n */\nasync function getMediaBaseColor(src: string, width = 10, height = 'auto') {\n  if (!src) {\n    throw new Error('No source to image');\n  }\n\n  let color, image;\n  const trackTiming = getTimeTracker('load_get_base_color');\n  try {\n    image = await preloadImage({ src, width, height });\n    color = await extractColorFromImage(image);\n  } catch (error) {\n    // Known error of color thief with white only images.\n    if (!(error instanceof TypeError)) {\n      throw error;\n    }\n    color = '#ffffff';\n  } finally {\n    image?.remove();\n    trackTiming();\n  }\n  return color;\n}\n\nexport default getMediaBaseColor;\n"
  },
  {
    "path": "packages/story-editor/src/utils/getSessionStorageKey.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { SESSION_STORAGE_PREFIX } from '@googleforcreators/design-system';\n\n// Note: this key format is also used in the `dashboard` package which should be updated in case of changes.\n// See https://github.com/GoogleForCreators/web-stories-wp/pull/12416/files#diff-a314e9df4ccf61e1a84cd3ca5b318a729c086e49e92da545b5a6272da3666b98R43\nexport default function getSessionStorageKey(storyId: number, isNew: boolean) {\n  return `${SESSION_STORAGE_PREFIX.LOCAL_AUTOSAVE_PREFIX}_${\n    isNew ? 'auto-draft' : storyId\n  }`;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/getUniquePresets.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { Pattern } from '@googleforcreators/patterns';\nimport type { TextElement } from '@googleforcreators/elements';\n\nfunction getUniquePresets<T extends Pattern | Partial<TextElement>>(\n  presets: T[]\n): T[] {\n  const list = presets.map((preset) => JSON.stringify(preset));\n  return Array.from(new Set(list)).map((preset) => JSON.parse(preset) as T);\n}\n\nexport default getUniquePresets;\n"
  },
  {
    "path": "packages/story-editor/src/utils/getUpdatedSizeAndPosition.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { dataPixels, calcRotatedResizeOffset } from '@googleforcreators/units';\nimport { calculateTextHeight } from '@googleforcreators/element-library';\n\n/**\n * Gets updated size and position of the element if relevant properties have changed.\n *\n * @param {Object} properties Original properties.\n * @return {{x: number, y: number, height: number}} Updated values.\n */\nfunction getUpdatedSizeAndPosition(properties) {\n  const { width, height: oldHeight, rotationAngle, x, y } = properties;\n  const newHeight = dataPixels(calculateTextHeight(properties, width));\n  const [dx, dy] = calcRotatedResizeOffset(\n    rotationAngle,\n    0,\n    0,\n    0,\n    newHeight - oldHeight\n  );\n  return {\n    height: newHeight,\n    x: dataPixels(x + dx),\n    y: dataPixels(y + dy),\n  };\n}\n\nexport default getUpdatedSizeAndPosition;\n"
  },
  {
    "path": "packages/story-editor/src/utils/idleCallback.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* Source: https://github.com/behnammodi/polyfill/blob/master/window.polyfill.js */\nconst requestIdleCallback =\n  window.requestIdleCallback ||\n  ((callback: IdleRequestCallback, options: IdleRequestOptions = {}) => {\n    const relaxation = 1;\n    const timeout = options.timeout || relaxation;\n    const start = performance.now();\n    return setTimeout(() => {\n      callback({\n        get didTimeout() {\n          return typeof options.timeout !== 'undefined'\n            ? false\n            : performance.now() - start - relaxation > timeout;\n        },\n        timeRemaining: () =>\n          Math.max(0, relaxation + (performance.now() - start)),\n      });\n    }, relaxation);\n  });\n\nconst cancelIdleCallback =\n  window.cancelIdleCallback ||\n  ((id: number) => {\n    clearTimeout(id);\n  });\n\nexport { requestIdleCallback, cancelIdleCallback };\n"
  },
  {
    "path": "packages/story-editor/src/utils/isDefaultPage.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { shallowEqual } from '@googleforcreators/react';\nimport { createPage, elementIs } from '@googleforcreators/elements';\nimport type { Page } from '@googleforcreators/elements';\n\n/**\n * Determine if a page has background or element changes different from the default page.\n *\n * @param page Page object.\n * @return If the page is equivalent to the default page.\n */\nconst isDefaultPage = (page: Page) => {\n  // Check if page has more than just the single default background element\n  if (page.elements.length > 1) {\n    return false;\n  }\n\n  const defaultPage = createPage();\n\n  // Check if background color is different\n  if (\n    'color' in page.backgroundColor &&\n    'color' in defaultPage.backgroundColor &&\n    !shallowEqual(page.backgroundColor.color, defaultPage.backgroundColor.color)\n  ) {\n    return false;\n  }\n\n  // Check if background element is not default\n  const backgroundElement = page.elements.find(\n    (e) => elementIs.backgroundable(e) && e.isBackground\n  );\n  if (backgroundElement) {\n    if (\n      !elementIs.defaultBackground(backgroundElement) ||\n      !backgroundElement.isDefaultBackground\n    ) {\n      return false;\n    }\n  }\n\n  return true;\n};\n\nexport default isDefaultPage;\n"
  },
  {
    "path": "packages/story-editor/src/utils/isOffCanvas.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  DANGER_ZONE_HEIGHT,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n} from '@googleforcreators/units';\nimport type { ElementBox } from '@googleforcreators/units';\n\nexport function isOffCanvas(selectedElement: ElementBox) {\n  const { x, y, width, height } = selectedElement;\n  let offCanvas = false;\n  let offCanvasTop = 0;\n  let offCanvasRight = 0;\n  let offCanvasBottom = 0;\n  let offCanvasLeft = 0;\n\n  // if x is a negative #\n  if (x < 0) {\n    offCanvasLeft = Math.abs(x);\n  }\n\n  // We have to adjust the y value since y = 0 is the top edge of the page container, not the top edge of the fullbleed container.\n  const adjustedY = y + DANGER_ZONE_HEIGHT;\n  // if y is a negative #\n  if (adjustedY < 0) {\n    offCanvasTop = Math.abs(adjustedY);\n  }\n\n  // check for off-canvas right side\n  if (x > 0) {\n    if (x + width > PAGE_WIDTH) {\n      offCanvasRight = x + width - PAGE_WIDTH;\n    }\n  } else {\n    const r = width - Math.abs(x) - PAGE_WIDTH;\n    offCanvasRight = r > 0 ? r : 0;\n  }\n\n  // check if off-canvas bottom\n  if (adjustedY > 0) {\n    if (y + height > PAGE_HEIGHT) {\n      const b = Math.floor(y + height - (PAGE_HEIGHT + DANGER_ZONE_HEIGHT));\n      offCanvasBottom = b > 0 ? b : 0;\n    }\n  } else {\n    const b = height - Math.abs(y) - PAGE_HEIGHT;\n    offCanvasBottom = b > 0 ? b : 0;\n  }\n\n  if (\n    offCanvasTop > 0 ||\n    offCanvasRight > 0 ||\n    offCanvasBottom > 0 ||\n    offCanvasLeft > 0\n  ) {\n    offCanvas = true;\n  }\n\n  return {\n    offCanvas,\n    offCanvasTop,\n    offCanvasRight,\n    offCanvasBottom,\n    offCanvasLeft,\n  };\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/isTargetOutOfContainer.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction isTargetOutOfContainer(target: Element, container: Element) {\n  const { left, right, top, bottom } = target.getBoundingClientRect();\n  const containerRect = container.getBoundingClientRect();\n  return (\n    left > containerRect.right ||\n    right < containerRect.left ||\n    bottom < containerRect.top ||\n    top > containerRect.bottom\n  );\n}\n\nexport default isTargetOutOfContainer;\n"
  },
  {
    "path": "packages/story-editor/src/utils/keyboardOnlyOutline.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Inspired by https://github.com/moxystudio/js-keyboard-only-outlines/blob/master/src/index.js\n\n/**\n * External dependencies\n */\nimport { useEffect, useState } from '@googleforcreators/react';\nimport { createGlobalStyle } from 'styled-components';\n\nconst KEYBOARD_USER_CLASS = `useskeyboard`;\nexport const KEYBOARD_USER_SELECTOR = `.${KEYBOARD_USER_CLASS}`;\n\nconst OutlineStyles = createGlobalStyle`\n    body:not(${KEYBOARD_USER_SELECTOR}) *:focus {\n        outline: none !important;\n    }\n`;\n\nconst ACCEPTED_KEYS = [\n  'ArrowUp',\n  'ArrowDown',\n  'ArrowLeft',\n  'ArrowRight',\n  'Tab',\n  'Digit1',\n  'Digit2',\n  'Digit3',\n];\n\nconst KeyboardOnlyOutline = () => {\n  const [usingKeyboard, setUsingKeyboard] = useState(false);\n  const handleKeydown = (e) => {\n    if (!usingKeyboard && ACCEPTED_KEYS.includes(e.code)) {\n      setUsingKeyboard(true);\n    }\n  };\n\n  const handleMousedown = () => {\n    if (usingKeyboard) {\n      setUsingKeyboard(false);\n    }\n  };\n\n  useEffect(() => {\n    document.addEventListener('keydown', handleKeydown, true);\n    document.addEventListener('mousedown', handleMousedown, true);\n\n    return function cleanup() {\n      document.removeEventListener('keydown', handleKeydown, true);\n      document.removeEventListener('mousedown', handleMousedown, true);\n    };\n  });\n\n  useEffect(() => {\n    document.body.classList.toggle(KEYBOARD_USER_CLASS, usingKeyboard);\n  }, [usingKeyboard]);\n\n  return <OutlineStyles />;\n};\n\nexport function isKeyboardUser() {\n  return document.body.classList.contains(KEYBOARD_USER_CLASS);\n}\n\nKeyboardOnlyOutline.propTypes = {};\n\nexport default KeyboardOnlyOutline;\n"
  },
  {
    "path": "packages/story-editor/src/utils/nativeCopyPasteExpected.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Checks if the native copy paste should proceed,\n * either if text is selected or if there's focus on a text/number input.\n *\n * @return If native handling is expected.\n */\nfunction nativeCopyPasteExpected() {\n  const { activeElement } = document;\n\n  if (activeElement) {\n    const { tagName, type, contentEditable } = activeElement as\n      | HTMLInputElement\n      | HTMLAnchorElement\n      | HTMLTextAreaElement;\n\n    // If it's an input in focus, do native handling.\n    if (\n      'true' === contentEditable ||\n      'textarea' === tagName.toLowerCase() ||\n      ('input' === tagName.toLowerCase() &&\n        typeof type === 'string' &&\n        ['text', 'number', 'search', 'email', 'tel', 'url'].includes(type))\n    ) {\n      return true;\n    }\n  }\n  const selection = window.getSelection();\n  const range =\n    selection && selection.rangeCount ? selection.getRangeAt(0) : null;\n\n  return Boolean(range && !range.collapsed);\n}\n\nexport default nativeCopyPasteExpected;\n"
  },
  {
    "path": "packages/story-editor/src/utils/noop.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport function noop() {\n  return undefined;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/objectPick.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default function pick<T extends object>(\n  o: T,\n  fields: string[] = []\n): Partial<T> {\n  return Object.assign(\n    {},\n    ...fields.map((prop) =>\n      o && prop in o ? { [prop]: o && o[prop as keyof T] } : {}\n    )\n  ) as Partial<T>;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/objectWithout.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default function objectWithout<T extends object>(\n  obj: T,\n  propertiesToRemove: string[]\n): Partial<T> {\n  return Object.keys(obj)\n    .filter((key) => !propertiesToRemove.includes(key))\n    .reduce((newObj, key) => ({ ...newObj, [key]: obj[key as keyof T] }), {});\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/presetUtils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  convertToCSS,\n  createSolid,\n  generatePatternStyles,\n  isPatternEqual,\n} from '@googleforcreators/patterns';\nimport { getHTMLInfo } from '@googleforcreators/rich-text';\nimport { generateFontFamily } from '@googleforcreators/element-library';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { PRESET_TYPES, MULTIPLE_VALUE } from '../constants';\nimport objectPick from './objectPick';\n\nconst TEXT_PRESET_STYLES = [\n  'backgroundColor',\n  'backgroundTextMode',\n  'font',\n  'fontSize',\n  'lineHeight',\n  'padding',\n  'textAlign',\n];\n\nexport function findMatchingColor(color, storyStyles, isText) {\n  const colorsToMatch = storyStyles.colors;\n  const patternType = isText ? 'color' : 'background';\n  return colorsToMatch.find((value) => {\n    try {\n      return isPatternEqual(value, color, patternType);\n    } catch {\n      // Some preset couldn't be rendered as patternType\n      return false;\n    }\n  });\n}\n\nexport function findMatchingStylePreset(preset, storyStyles) {\n  const stylesToMatch = storyStyles.textStyles;\n  const toAdd = convertToCSS(generatePresetStyle(preset));\n  return stylesToMatch.find(\n    (value) => toAdd === convertToCSS(generatePresetStyle(value))\n  );\n}\n\nexport function generatePresetStyle(preset, prepareForCSS) {\n  const {\n    color,\n    backgroundColor,\n    font,\n    fontWeight,\n    backgroundTextMode,\n    textAlign,\n    letterSpacing,\n    lineHeight,\n    isItalic,\n    isUnderline,\n    padding,\n    fontSize,\n  } = preset;\n  let style = {\n    textAlign,\n    letterSpacing: `${letterSpacing / 100}em`,\n    fontWeight,\n    textDecoration: isUnderline ? 'underline' : null,\n    fontStyle: isItalic ? 'italic' : null,\n    fontFamily: generateFontFamily(font),\n    ...generatePatternStyles(color, 'color'),\n  };\n\n  if (!prepareForCSS) {\n    // If we're not preparing the matching style for actual CSS, add background text mode as well here.\n    style = {\n      ...style,\n      fontSize,\n      lineHeight,\n      padding,\n      backgroundTextMode,\n    };\n  }\n\n  // Generate background only if it's on.\n  // If it's highlight mode then the highlight is displayed on the text wrapper instead.\n  if (\n    backgroundTextMode !== BACKGROUND_TEXT_MODE.NONE &&\n    (!prepareForCSS || backgroundTextMode !== BACKGROUND_TEXT_MODE.HIGHLIGHT)\n  ) {\n    style = {\n      ...style,\n      ...generatePatternStyles(backgroundColor, 'background'),\n    };\n  }\n  return style;\n}\n\nfunction getExtractedInlineValue(value) {\n  return value !== MULTIPLE_VALUE ? value : null;\n}\n\nexport function getTextInlineStyles(content) {\n  const { color, fontWeight, isItalic, isUnderline, letterSpacing } =\n    getHTMLInfo(content);\n  return {\n    color: color !== MULTIPLE_VALUE ? color : createSolid(0, 0, 0),\n    fontWeight: getExtractedInlineValue(fontWeight),\n    isItalic: getExtractedInlineValue(isItalic),\n    isUnderline: getExtractedInlineValue(isUnderline),\n    letterSpacing: getExtractedInlineValue(letterSpacing),\n  };\n}\n\nexport function getTextPresets(elements, storyStyles, type, isBackgroundColor) {\n  const colors =\n    PRESET_TYPES.STYLE === type\n      ? []\n      : elements\n          .map(({ content, backgroundColor }) =>\n            isBackgroundColor ? backgroundColor : getHTMLInfo(content).color\n          )\n          .filter((color) => color !== MULTIPLE_VALUE)\n          .filter(\n            (color) => color && !findMatchingColor(color, storyStyles, true)\n          );\n\n  const textStyles =\n    PRESET_TYPES.COLOR === type\n      ? []\n      : elements\n          .map((text) => {\n            return {\n              ...objectPick(text, TEXT_PRESET_STYLES),\n              ...getTextInlineStyles(text.content),\n            };\n          })\n          .filter((preset) => !findMatchingStylePreset(preset, storyStyles));\n  return {\n    colors,\n    textStyles,\n  };\n}\n\nexport function getShapePresets(elements, storyStyles) {\n  const colors = elements\n    .map(({ backgroundColor }) => {\n      return backgroundColor ? backgroundColor : null;\n    })\n    .filter((color) => color && !findMatchingColor(color, storyStyles, false));\n  return {\n    colors,\n  };\n}\n\nexport function getPagePreset(page, storyStyles) {\n  return {\n    colors: [page.backgroundColor].filter(\n      (color) => color && !findMatchingColor(color, storyStyles, false)\n    ),\n  };\n}\n\nexport function areAllType(elType, selectedElements) {\n  return (\n    selectedElements.length > 0 &&\n    selectedElements.every(({ type }) => elType === type)\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/removeDupsFromArray.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Removes duplicates of any objects from an array of objects\n *\n * @param arr Array object[].\n * @param key Key on the basis of which duplicates can be identified string.\n * @return If the page is equivalent to the default page.\n */\nconst removeDupsFromArray = (arr: Record<string, unknown>[], key: string) => {\n  return arr.reduce(\n    (acc: Record<string, unknown>[], current: Record<string, unknown>) => {\n      const isCurrentTermAdded = acc.find(\n        (term: Record<string, unknown>) => term[key] === current[key]\n      );\n      if (!isCurrentTermAdded) {\n        return acc.concat([current]);\n      } else {\n        return acc;\n      }\n    },\n    []\n  );\n};\n\nexport default removeDupsFromArray;\n"
  },
  {
    "path": "packages/story-editor/src/utils/storyUpdates.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\n\n/**\n * Internal dependencies\n */\nimport type { ReducerState, UpdateStoryProps } from '../types';\nimport cleanForSlug from './cleanForSlug';\n\ninterface UpdateSlugProps {\n  currentSlug: string;\n  currentTitle: string;\n  updateStory: (props: UpdateStoryProps) => ReducerState;\n}\n\n/**\n * For use on blur of updating story title\n * that can impact what story slug is if\n * not set independently.\n *\n * @param args Necessary data for update.\n * @param args.currentSlug The currently assigned value to story's slug.\n * @param args.currentTitle The currently assigned value to story's title.\n * @param args.updateStory The callback to useStory's action for updating the story with new slug.\n */\nexport const updateSlug = ({\n  currentSlug,\n  currentTitle,\n  updateStory,\n}: UpdateSlugProps) => {\n  if (!currentSlug) {\n    const cleanSlug = encodeURIComponent(cleanForSlug(currentTitle));\n    updateStory({ properties: { slug: cleanSlug } });\n  }\n};\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/cleanForSlug.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport cleanForSlug from '../cleanForSlug';\n\ndescribe('cleanForSlug', () => {\n  it('should return string prepared for use as URL slug', () => {\n    expect(cleanForSlug(' /Déjà_vu. ')).toBe('deja-vu');\n  });\n\n  it('should return an empty string for missing argument', () => {\n    expect(cleanForSlug()).toBe('');\n  });\n\n  it('should return an empty string for falsy argument', () => {\n    expect(cleanForSlug(null)).toBe('');\n  });\n\n  it('should trim leading and ending whitespace and dashes', () => {\n    const result = cleanForSlug('- Hello-World- ');\n    expect(result).toBe('hello-world');\n  });\n\n  it('should not trim leading and ending whitespace and dashes if editing', () => {\n    const result = cleanForSlug('- Hello-World- ', true);\n    expect(result).toBe('--hello-world--');\n  });\n\n  it('should collapse multiple whitespace and dashes', () => {\n    const result = cleanForSlug('Hello   cruel- world');\n    expect(result).toBe('hello-cruel-world');\n  });\n\n  it('should not collapse multiple whitespace and dashes if editing', () => {\n    const result = cleanForSlug('Hello   cruel- world', true);\n    expect(result).toBe('hello---cruel--world');\n  });\n\n  it('should remove diacritics', () => {\n    const result = cleanForSlug('-Hello-World-');\n    expect(result).toBe('hello-world');\n  });\n\n  it('should remove all illegal characters', () => {\n    const result = cleanForSlug('Hello-?-,:;!\"World');\n    expect(result).toBe('hello-world');\n  });\n\n  it.each([\n    ['హల-వరలడ', 'హల-వరలడ'],\n    ['你好世界', '你好世界'],\n    ['Γειά σου Κόσμε', 'γειά-σου-κόσμε'],\n    ['سلام دنیا', 'سلام-دنیا'],\n  ])(\n    'should properly generate slug from %s and return %s',\n    (original, expected) => {\n      expect(cleanForSlug(original)).toBe(expected);\n    }\n  );\n\n  // eslint-disable-next-line jest/no-disabled-tests -- not implemented yet.\n  it.skip('should replace umlauts if locale is de-*', () => {\n    expect(cleanForSlug('Übergrössengeschäft')).toBe('uebergroessengeschaeft');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/contrastUtils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport * as contrastUtils from '../contrastUtils';\n\ndescribe('contrastUtils', () => {\n  describe('calculateLuminanceFromRGB', () => {\n    it('calculate from RGB object', () => {\n      const rgb = {\n        r: 255,\n        g: 255,\n        b: 255,\n      };\n      expect(contrastUtils.calculateLuminanceFromRGB(rgb)).toBe(1);\n    });\n    it('calculate from RGBA object', () => {\n      const rgb = {\n        r: 255,\n        g: 255,\n        b: 255,\n        a: 1.0,\n      };\n      expect(contrastUtils.calculateLuminanceFromRGB(rgb)).toBe(1);\n    });\n  });\n\n  describe('calculateLuminanceFromStyleColor', () => {\n    it('calculate from element rgb style.color string', () => {\n      const color = 'rgb(255, 255, 255)';\n      expect(contrastUtils.calculateLuminanceFromStyleColor(color)).toBe(1);\n    });\n    it('calculate from element rgba style.color string', () => {\n      const color = 'rgb(255, 255, 255, 1)';\n      expect(contrastUtils.calculateLuminanceFromStyleColor(color)).toBe(1);\n    });\n  });\n\n  describe('checkContrastFromLuminances', () => {\n    it('calculate successful contrast check from differing luminances', () => {\n      const luminanceA = 0;\n      const luminanceB = 1;\n      expect(\n        contrastUtils.checkContrastFromLuminances(luminanceA, luminanceB)\n          .WCAG_AA\n      ).toBeTrue();\n    });\n\n    it('calculate failed contrast check from similar luminances', () => {\n      const luminanceA = 0.3;\n      const luminanceB = 1;\n      expect(\n        contrastUtils.checkContrastFromLuminances(luminanceA, luminanceB)\n          .WCAG_AA\n      ).toBeFalse();\n    });\n\n    it('calculate successful contrast check from large font size', () => {\n      const luminanceA = 1;\n      const luminanceB = 0.3;\n      expect(\n        contrastUtils.checkContrastFromLuminances(luminanceA, luminanceB, 24)\n          .WCAG_AA\n      ).toBeTrue();\n    });\n    it('calculate failed contrast check from small font size', () => {\n      const luminanceA = 1;\n      const luminanceB = 0.3;\n      expect(\n        contrastUtils.checkContrastFromLuminances(luminanceA, luminanceB, 12)\n          .WCAG_AA\n      ).toBeFalse();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/copyPaste.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { PAGE_WIDTH } from '@googleforcreators/units';\nimport {\n  SHARED_DEFAULT_ATTRIBUTES,\n  MEDIA_DEFAULT_ATTRIBUTES,\n  elementTypes,\n} from '@googleforcreators/element-library';\nimport {\n  registerElementType,\n  TEXT_ELEMENT_DEFAULT_FONT,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { addElementsToClipboard, processPastedElements } from '../copyPaste';\n\nconst getDefinitionForType = (type) =>\n  elementTypes.find((element) => element.type === type);\n\ndescribe('copyPaste utils', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  const PAGE = {\n    backgroundColor: createSolid(255, 0, 0),\n  };\n  const TEXT_ELEMENT = {\n    ...getDefinitionForType('text').defaultAttributes,\n    ...SHARED_DEFAULT_ATTRIBUTES,\n    font: TEXT_ELEMENT_DEFAULT_FONT,\n    padding: {\n      horizontal: 0,\n      vertical: 0,\n    },\n    type: 'text',\n    content: 'Fill in some text',\n    x: 91,\n    y: 23,\n    width: 100,\n    height: 100,\n    color: createSolid(0, 0, 0),\n    id: '1',\n  };\n  const IMAGE_ELEMENT = {\n    ...getDefinitionForType('image').defaultAttributes,\n    ...SHARED_DEFAULT_ATTRIBUTES,\n    ...MEDIA_DEFAULT_ATTRIBUTES,\n    type: 'image',\n    x: PAGE_WIDTH,\n    y: 41,\n    width: 220,\n    height: 202,\n    resource: {\n      type: 'image',\n      mimeType: '',\n      src: '',\n      width: 1,\n      height: 1,\n    },\n    id: '2',\n  };\n\n  const SHAPE_ELEMENT = {\n    ...getDefinitionForType('shape').defaultAttributes,\n    ...SHARED_DEFAULT_ATTRIBUTES,\n    type: 'shape',\n    x: 10,\n    y: 10,\n    width: 10,\n    height: 10,\n    mask: {\n      type: 'rectangle',\n    },\n    isBackground: true,\n    backgroundColor: createSolid(1, 1, 1),\n    id: '3',\n  };\n\n  const ANIMATION = {\n    type: 'BOUNCE',\n    targets: ['3'],\n    duration: 1000,\n    delay: 0,\n  };\n\n  describe('processPastedElements', () => {\n    const DOUBLE_DASH_ESCAPE = '_DOUBLEDASH_';\n\n    let template;\n\n    beforeEach(() => {\n      template = document.createElement('template');\n      const payload = JSON.stringify({\n        sentinel: 'story-elements',\n        items: [TEXT_ELEMENT, IMAGE_ELEMENT, SHAPE_ELEMENT],\n        animations: [ANIMATION],\n      }).replace(/--/g, DOUBLE_DASH_ESCAPE);\n      const htmlContent = '<div>Foo</div>';\n      const innerHTML = `<!-- ${payload} -->${htmlContent}`;\n\n      template.innerHTML = innerHTML;\n    });\n\n    it('should detect elements as expected', () => {\n      const { elements: processedElements } = processPastedElements(\n        template.content,\n        {\n          elements: [],\n        }\n      );\n      expect(processedElements).toHaveLength(3);\n      expect(processedElements[0]).toStrictEqual({\n        ...TEXT_ELEMENT,\n        id: expect.any(String),\n      });\n      expect(processedElements[1]).toStrictEqual({\n        ...IMAGE_ELEMENT,\n        id: expect.any(String),\n      });\n      expect(processedElements[2]).toStrictEqual({\n        ...SHAPE_ELEMENT,\n        id: expect.any(String),\n      });\n    });\n\n    it('should detect animations as expected and update target to new element id', () => {\n      const { elements, animations } = processPastedElements(template.content, {\n        elements: [],\n        animations: [],\n      });\n      expect(animations).toHaveLength(1);\n      expect(animations[0]).toStrictEqual({\n        ...ANIMATION,\n        id: expect.any(String),\n        targets: [elements[2].id],\n      });\n    });\n\n    it('should set the position values based on the origin elements correctly', () => {\n      const currentPage = {\n        elements: [\n          {\n            id: '1',\n            x: 91,\n            y: 23,\n          },\n          {\n            id: '2',\n            x: PAGE_WIDTH,\n            y: 41,\n          },\n        ],\n      };\n      const { elements: processedElements } = processPastedElements(\n        template.content,\n        currentPage\n      );\n      expect(processedElements[0]).toStrictEqual({\n        ...TEXT_ELEMENT,\n        x: 121,\n        y: 53,\n        id: expect.any(String),\n      });\n      expect(processedElements[1]).toStrictEqual({\n        ...IMAGE_ELEMENT,\n        x: 30,\n        y: 71,\n        id: expect.any(String),\n      });\n    });\n\n    it('should ignore the elements comment if sentinel is not story-elements', () => {\n      const templateIncorrectSentinel = document.createElement('template');\n      const payload = JSON.stringify({\n        sentinel: 'foo',\n        items: [TEXT_ELEMENT, IMAGE_ELEMENT],\n      }).replace(/--/g, DOUBLE_DASH_ESCAPE);\n      templateIncorrectSentinel.innerHTML = `<!-- ${payload} -->`;\n\n      const { elements: processedElements } = processPastedElements(\n        templateIncorrectSentinel.content,\n        {\n          elements: [],\n        }\n      );\n      expect(processedElements).toStrictEqual([]);\n    });\n\n    it('should not find elements without a comment in document fragment', () => {\n      const templateWithoutComment = document.createElement('template');\n      const payload = JSON.stringify({\n        sentinel: 'story-elements',\n        items: [TEXT_ELEMENT, IMAGE_ELEMENT],\n      }).replace(/--/g, DOUBLE_DASH_ESCAPE);\n\n      templateWithoutComment.innerHTML = `${payload}`;\n      const { elements: processedElements } = processPastedElements(\n        templateWithoutComment.content,\n        {\n          elements: [],\n        }\n      );\n      expect(processedElements).toStrictEqual([]);\n    });\n  });\n\n  describe('addElementsToClipboard', () => {\n    it('should add elements correctly to clipboard', () => {\n      const setData = jest.fn();\n      const evt = {\n        clipboardData: {\n          setData,\n        },\n      };\n\n      const elements = [\n        {\n          ...TEXT_ELEMENT,\n          id: '1',\n        },\n      ];\n      addElementsToClipboard(PAGE, elements, [], {}, evt);\n\n      expect(setData).toHaveBeenCalledTimes(2);\n      expect(setData).toHaveBeenCalledWith('text/plain', 'Fill in some text');\n      expect(setData).toHaveBeenCalledWith('text/html', expect.any(String));\n    });\n\n    it('should add background color to any background shape to clipboard', () => {\n      const setData = jest.fn();\n      const evt = {\n        clipboardData: {\n          setData,\n        },\n      };\n\n      const elements = [\n        {\n          ...SHAPE_ELEMENT,\n          id: '1',\n          isDefaultBackground: true,\n        },\n      ];\n      addElementsToClipboard(PAGE, elements, [], {}, evt);\n\n      expect(setData).toHaveBeenCalledTimes(2);\n      expect(setData).toHaveBeenCalledWith('text/plain', 'shape');\n      expect(setData).toHaveBeenCalledWith(\n        'text/html',\n        expect.stringMatching(\n          /\"backgroundColor\":{\"color\":{\"r\":255,\"g\":0,\"b\":0}}/\n        )\n      );\n    });\n\n    it('should add elements not containing any text correctly to clipboard', () => {\n      const setData = jest.fn();\n      const evt = {\n        clipboardData: {\n          setData,\n        },\n      };\n\n      const elements = [\n        {\n          ...SHAPE_ELEMENT,\n          id: '1',\n        },\n      ];\n      addElementsToClipboard(PAGE, elements, [], {}, evt);\n\n      expect(setData).toHaveBeenCalledTimes(2);\n      expect(setData).toHaveBeenCalledWith('text/plain', 'shape');\n      expect(setData).toHaveBeenCalledWith('text/html', expect.any(String));\n    });\n\n    it('should add animations to clipboard', () => {\n      const setData = jest.fn();\n      const evt = {\n        clipboardData: {\n          setData,\n        },\n      };\n\n      const elements = [\n        {\n          ...SHAPE_ELEMENT,\n          id: '1',\n        },\n      ];\n      const animations = [\n        {\n          id: 'a',\n          targets: ['1'],\n          type: 'ANIMATION_TYPE',\n        },\n      ];\n      addElementsToClipboard(PAGE, elements, animations, {}, evt);\n\n      expect(setData).toHaveBeenCalledTimes(2);\n      expect(setData).toHaveBeenCalledWith('text/plain', 'shape');\n      expect(setData).toHaveBeenCalledWith(\n        'text/html',\n        expect.stringMatching(/\"type\":\"ANIMATION_TYPE\"/)\n      );\n    });\n\n    it('should not add anything if none are passed', () => {\n      const setData = jest.fn();\n      const evt = {\n        clipboardData: {\n          setData,\n        },\n      };\n      addElementsToClipboard(PAGE, [], [], {}, evt);\n      expect(setData).toHaveBeenCalledTimes(0);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/createError.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport createError from '../createError';\n\ndescribe('createError', () => {\n  it('should return an error', () => {\n    expect(() => {\n      throw createError('testing', 'test.jpg', 'hello there');\n    }).toThrow('hello there');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/generateGroupName.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport generateGroupName, { getNextGroupNumber } from '../generateGroupName';\n\ndescribe('getNextGroupNumber', () => {\n  it('should return next highest number from group name', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'mygroup',\n      },\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'my group',\n      },\n      '66f74a42-a5b2-4d05-91a2-5f82ac57dddb': {\n        name: 'Group 2',\n      },\n      '36f74a42-a5b2-4d05-91a2-5f82ac57dddb': {\n        name: 'Group 1',\n      },\n    };\n\n    expect(getNextGroupNumber(groups)).toBe(3);\n  });\n\n  it('should return 1 when no numbered groups exists', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'mygroup',\n      },\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'my group',\n      },\n    };\n\n    expect(getNextGroupNumber(groups)).toBe(1);\n  });\n\n  it('should return 1 when groups are empty', () => {\n    const groups = {};\n    expect(getNextGroupNumber(groups)).toBe(1);\n  });\n\n  it('should return 1 when groups is undefined', () => {\n    expect(getNextGroupNumber()).toBe(1);\n  });\n\n  it('should return 1 when bad data is passed', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {},\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': [],\n    };\n\n    expect(getNextGroupNumber(groups)).toBe(1);\n  });\n});\n\ndescribe('generateGroupName', () => {\n  it('should return next highest group name', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'mygroup',\n      },\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': {\n        name: 'my group',\n      },\n      '66f74a42-a5b2-4d05-91a2-5f82ac57dddb': {\n        name: 'Group 2',\n      },\n      '36f74a42-a5b2-4d05-91a2-5f82ac57dddb': {\n        name: 'Group 1',\n      },\n    };\n\n    expect(generateGroupName(groups)).toBe('Group 3');\n  });\n\n  it('should return default group name', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {},\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': {},\n    };\n\n    expect(generateGroupName(groups)).toBe('Group 1');\n  });\n\n  it('should return group name with \"copy\" appended', () => {\n    const groups = {\n      'b524f947-ce3f-4559-95ce-ac5538ed75dc': {},\n      'a524f947-ce3f-4559-95ce-ac5538ed75dc': {},\n    };\n\n    expect(generateGroupName(groups, 'My group')).toBe('My group Copy');\n  });\n\n  it('should append \"copy\" to copied group name', () => {\n    const groups = {};\n    expect(generateGroupName(groups, 'My group Copy')).toBe(\n      'My group Copy Copy'\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/getCropParams.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n/**\n * External dependencies\n */\nimport {\n  DANGER_ZONE_HEIGHT,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n} from '@googleforcreators/units';\nimport { getCropParams } from '../getCropParams';\n\n/**\n * External dependencies\n */\n\ndescribe('getCropParams', () => {\n  it('should update width when off canvas left', () => {\n    const element = {\n      x: -20,\n      y: 0,\n      width: 320,\n      height: 240,\n      resource: {\n        width: 640,\n        height: 480,\n      },\n    };\n    const { newWidth } = getCropParams(element);\n    expect(newWidth).toBe(300);\n  });\n\n  it('should update width when off canvas right', () => {\n    const element = {\n      x: 33 + (PAGE_WIDTH - 320),\n      y: 0,\n      width: 320,\n      height: 240,\n      resource: {\n        width: 640,\n        height: 480,\n      },\n    };\n    const { newWidth } = getCropParams(element);\n    expect(newWidth).toBe(287);\n  });\n\n  it('should update height when off canvas top', () => {\n    const element = {\n      x: 50,\n      y: -20 - DANGER_ZONE_HEIGHT,\n      width: 320,\n      height: 240,\n      resource: {\n        width: 640,\n        height: 480,\n      },\n    };\n    const { newHeight } = getCropParams(element);\n    expect(newHeight).toBe(220);\n  });\n\n  it('should update height when off canvas bottom', () => {\n    const element = {\n      x: 50,\n      y: 18 + (PAGE_HEIGHT + DANGER_ZONE_HEIGHT - 240),\n      width: 320,\n      height: 240,\n      resource: {\n        width: 640,\n        height: 480,\n      },\n    };\n    const { newHeight } = getCropParams(element);\n    expect(newHeight).toBe(222);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/getInUseFonts.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { getInUseFontsForPages, getTextSetsForFonts } from '../getInUseFonts';\n\ndescribe('getInUseFontsForPages', () => {\n  it('should return nothing for empty pages', () => {\n    expect(getInUseFontsForPages([])).toStrictEqual([]);\n  });\n\n  it('should return a list of fonts for the pages', () => {\n    expect(\n      getInUseFontsForPages([\n        {\n          elements: [\n            { type: 'text', font: { family: 'Roboto' } },\n            { type: 'shape' },\n            { type: 'text', font: { family: 'Google Sans' } },\n          ],\n        },\n      ])\n    ).toStrictEqual(['Roboto', 'Google Sans']);\n  });\n\n  it('should eliminate any duplicate fonts and list them only once', () => {\n    expect(\n      getInUseFontsForPages([\n        {\n          elements: [\n            { type: 'text', font: { family: 'Roboto' } },\n            { type: 'shape' },\n            { type: 'text', font: { family: 'Roboto' } },\n            { type: 'text', font: { family: 'Google Sans' } },\n          ],\n        },\n      ])\n    ).toStrictEqual(['Roboto', 'Google Sans']);\n  });\n\n  it('should eliminate any invalid data or missing font names', () => {\n    expect(\n      getInUseFontsForPages([\n        {\n          elements: [\n            { type: 'shape' },\n            { type: 'text', font: { family: null } },\n            { type: 'text', font: { family: 'Google Sans' } },\n          ],\n        },\n      ])\n    ).toStrictEqual(['Google Sans']);\n  });\n\n  it('should return text sets for the fonts.', () => {\n    expect(\n      getTextSetsForFonts({\n        fonts: ['Google Sans', 'Helvetica'],\n        textSets: [\n          { elements: [{ type: 'text', font: { family: 'Google Sans' } }] },\n          { elements: [{ type: 'text', font: { family: 'Helvetica' } }] },\n          { elements: [{ type: 'text', font: { family: 'Times New Roman' } }] },\n        ],\n      })\n    ).toStrictEqual([\n      { elements: [{ font: { family: 'Google Sans' }, type: 'text' }] },\n      { elements: [{ font: { family: 'Helvetica' }, type: 'text' }] },\n    ]);\n  });\n\n  it('should return an empty array if there are no matches.', () => {\n    expect(\n      getTextSetsForFonts({\n        fonts: ['New York', 'San Francisco'],\n        textSets: [\n          { elements: [{ type: 'text', font: { family: 'Google Sans' } }] },\n          { elements: [{ type: 'text', font: { family: 'Helvetica' } }] },\n          { elements: [{ type: 'text', font: { family: 'Times New Roman' } }] },\n        ],\n      })\n    ).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/getInsertedElementSize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport getInsertedElementSize from '../getInsertedElementSize';\n\ndescribe('getInsertedElementSize', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should return original size if set', () => {\n    const { width, height } = getInsertedElementSize('text', 100, 100, {\n      x: 10,\n      y: 10,\n      content: 'Hello, Stories',\n    });\n    expect(width).toBe(100);\n    expect(height).toBe(100);\n  });\n\n  it('should generate size if not set', () => {\n    const { width, height } = getInsertedElementSize('text', null, null, {\n      x: 10,\n      y: 10,\n      content: 'Hello, Stories',\n    });\n    expect(width).toBeNumber();\n    expect(height).toBeNumber();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/getUniquePresets.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getUniquePresets from '../getUniquePresets';\n\ndescribe('getUniquePresets', () => {\n  it('should return array of unique presets', () => {\n    const repeatingPresets = [\n      { color: { r: 181, g: 57, b: 57 } },\n      { color: { r: 181, g: 57, b: 57 } },\n      { color: { r: 0, g: 57, b: 57 } },\n      { color: { r: 0, g: 57, b: 57 } },\n      { color: { r: 181, g: 57, b: 0 } },\n      { color: { r: 181, g: 57, b: 0 } },\n      {\n        rotation: 0.5,\n        type: 'linear',\n        stops: [\n          { color: { r: 181, g: 57, b: 0 }, position: 0 },\n          { color: { r: 181, g: 57, b: 0 }, position: 1 },\n        ],\n      },\n      {\n        rotation: 0.5,\n        type: 'linear',\n        stops: [\n          { color: { r: 181, g: 57, b: 0 }, position: 0 },\n          { color: { r: 181, g: 57, b: 0 }, position: 1 },\n        ],\n      },\n    ];\n\n    const uniquePresets = [\n      { color: { r: 181, g: 57, b: 57 } },\n      { color: { r: 0, g: 57, b: 57 } },\n      { color: { r: 181, g: 57, b: 0 } },\n      {\n        rotation: 0.5,\n        type: 'linear',\n        stops: [\n          { color: { r: 181, g: 57, b: 0 }, position: 0 },\n          { color: { r: 181, g: 57, b: 0 }, position: 1 },\n        ],\n      },\n    ];\n    expect(getUniquePresets(repeatingPresets)).toStrictEqual(uniquePresets);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/isDefaultPage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createSolid } from '@googleforcreators/patterns';\nimport { createPage, registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * Internal dependencies\n */\nimport isDefaultPage from '../isDefaultPage';\n\ndescribe('isDefaultPage', () => {\n  beforeAll(() => {\n    elementTypes.forEach(registerElementType);\n  });\n\n  it('should return true with base page', () => {\n    const page = createPage();\n    expect(isDefaultPage(page)).toBeTrue();\n  });\n\n  it('should return false with custom background color', () => {\n    const page = createPage({\n      backgroundColor: createSolid(0, 0, 0),\n    });\n    expect(isDefaultPage(page)).toBeFalse();\n  });\n\n  it('should return false with additional elements', () => {\n    const page = createPage();\n    page.elements.push({});\n    expect(isDefaultPage(page)).toBeFalse();\n  });\n\n  it('should return false if background element is no longer default', () => {\n    const page = createPage();\n    delete page.elements[0].isDefaultBackground;\n    expect(isDefaultPage(page)).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/isOffCanvas.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  DANGER_ZONE_HEIGHT,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n} from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport { isOffCanvas } from '../isOffCanvas';\n\ndescribe('isOffCanvas', () => {\n  it('should return element as not off canvas', () => {\n    const { offCanvas } = isOffCanvas({ x: 0, y: 0, width: 320, height: 240 });\n    expect(offCanvas).toBeFalse();\n  });\n\n  it('should return element off canvas', () => {\n    const { offCanvas } = isOffCanvas({\n      x: -10,\n      y: 0,\n      width: 320,\n      height: 240,\n    });\n    expect(offCanvas).toBeTrue();\n  });\n\n  it('should return off canvas params as 0', () => {\n    const { offCanvasTop, offCanvasRight, offCanvasBottom, offCanvasLeft } =\n      isOffCanvas({ x: 50, y: 50, width: 320, height: 240 });\n\n    expect(offCanvasTop).toBe(0);\n    expect(offCanvasRight).toBe(0);\n    expect(offCanvasBottom).toBe(0);\n    expect(offCanvasLeft).toBe(0);\n  });\n\n  it('should be off canvas top', () => {\n    const { offCanvasTop } = isOffCanvas({\n      x: 50,\n      y: -10 - DANGER_ZONE_HEIGHT,\n      width: 320,\n      height: 240,\n    });\n\n    expect(offCanvasTop).toBe(10);\n  });\n\n  it('should be off canvas left', () => {\n    const { offCanvasLeft } = isOffCanvas({\n      x: -50,\n      y: 0,\n      width: 320,\n      height: 240,\n    });\n\n    expect(offCanvasLeft).toBe(50);\n  });\n\n  it('should be off canvas right', () => {\n    const { offCanvasRight } = isOffCanvas({\n      x: 33 + (PAGE_WIDTH - 320),\n      y: 0,\n      width: 320,\n      height: 240,\n    });\n\n    expect(offCanvasRight).toBe(33);\n  });\n\n  it('should be off canvas bottom', () => {\n    const { offCanvasBottom } = isOffCanvas({\n      x: 0,\n      y: 18 + (PAGE_HEIGHT + DANGER_ZONE_HEIGHT - 240),\n      width: 320,\n      height: 240,\n    });\n\n    expect(offCanvasBottom).toBe(18);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/nativeCopyPasteExpected.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport nativeCopyPasteExpected from '../nativeCopyPasteExpected';\n\ndescribe('nativeCopyPasteExpected', () => {\n  it('should detect selection correctly for textarea', () => {\n    const textArea = document.createElement('textarea');\n    document.body.appendChild(textArea);\n    textArea.focus();\n    expect(nativeCopyPasteExpected()).toBeTrue();\n  });\n\n  it('should detect selection correctly for text input', () => {\n    const textInput = document.createElement('input');\n    textInput.type = 'text';\n    document.body.appendChild(textInput);\n    textInput.focus();\n    expect(nativeCopyPasteExpected()).toBeTrue();\n  });\n\n  it('should detect selection correctly for number input', () => {\n    const numberInput = document.createElement('input');\n    numberInput.type = 'number';\n    document.body.appendChild(numberInput);\n    numberInput.focus();\n    expect(nativeCopyPasteExpected()).toBeTrue();\n  });\n\n  it('should detect selection correctly for search input', () => {\n    const searchInput = document.createElement('input');\n    searchInput.type = 'search';\n    document.body.appendChild(searchInput);\n    searchInput.focus();\n    expect(nativeCopyPasteExpected()).toBeTrue();\n  });\n\n  /* eslint-disable-next-line jest/no-disabled-tests --\n   * jsdom does not actually support checking for contenteditable.\n   * See https://github.com/jsdom/jsdom/issues/1670\n   **/\n  it.skip('should detect selection correctly for contenteditable element', () => {\n    const contentEditable = document.createElement('div');\n    contentEditable.setAttribute('contenteditable', 'true');\n    document.body.appendChild(contentEditable);\n    contentEditable.focus();\n    expect(nativeCopyPasteExpected()).toBeTrue();\n  });\n\n  it('should detect selection correctly for unsupported input', () => {\n    const windowSpy = jest\n      .spyOn(window, 'getSelection')\n      .mockImplementation(() => false);\n\n    const incorrectInput = document.createElement('input');\n    // Setting to something like \"invalid\" does not work, will be ignored by jsdom.\n    incorrectInput.type = 'file';\n    document.body.appendChild(incorrectInput);\n    incorrectInput.focus();\n\n    expect(nativeCopyPasteExpected()).toBeFalse();\n\n    windowSpy.mockRestore();\n  });\n\n  it('should use native copypaste if there is selection', () => {\n    const windowSpy = jest\n      .spyOn(window, 'getSelection')\n      .mockImplementation(() => ({\n        rangeCount: 1,\n        collapsed: false,\n        getRangeAt: () => true,\n      }));\n\n    expect(nativeCopyPasteExpected()).toBeTrue();\n\n    windowSpy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/objectPick.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport objectPick from '../objectPick';\n\ndescribe('objectPick', () => {\n  it('should pick only the specified properties and only if they exist', () => {\n    const setup = {\n      a: 1,\n      b: 2,\n      c: 3,\n    };\n    const result = objectPick(setup, ['a', 'b', 'd']);\n    const expected = {\n      a: 1,\n      b: 2,\n      // Note no \"c\" or \"d\" here\n    };\n    expect(result).toStrictEqual(expected);\n  });\n\n  it('should do nothing for non-objects and empty objects', () => {\n    expect(objectPick()).toStrictEqual({});\n    expect(objectPick(null)).toStrictEqual({});\n    expect(objectPick(1)).toStrictEqual({});\n    expect(objectPick(false)).toStrictEqual({});\n    expect(objectPick(true)).toStrictEqual({});\n    expect(objectPick('1')).toStrictEqual({});\n    expect(objectPick({})).toStrictEqual({});\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/presetUtils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  TEXT_ELEMENT_DEFAULT_FONT,\n  BACKGROUND_TEXT_MODE,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport {\n  findMatchingColor,\n  findMatchingStylePreset,\n  getShapePresets,\n  getTextPresets,\n} from '../presetUtils';\nimport { PRESET_TYPES } from '../../constants';\nimport objectWithout from '../objectWithout';\n\ndescribe('presetUtils', () => {\n  const TEST_COLOR = {\n    color: {\n      r: 1,\n      g: 1,\n      b: 1,\n    },\n  };\n  const TEST_COLOR_2 = {\n    color: {\n      r: 2,\n      g: 2,\n      b: 2,\n    },\n  };\n  const STYLE_PRESET = {\n    color: TEST_COLOR_2,\n    backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n    backgroundColor: TEST_COLOR,\n    font: TEXT_ELEMENT_DEFAULT_FONT,\n  };\n  it('should return matching color object', () => {\n    const globalStoryStyles = {\n      colors: [\n        TEST_COLOR,\n        {\n          color: {\n            r: 2,\n            g: 2,\n            b: 1,\n          },\n        },\n      ],\n    };\n    const color = {\n      color: {\n        r: 1,\n        g: 1,\n        b: 1,\n      },\n    };\n    expect(findMatchingColor(color, globalStoryStyles, true)).toStrictEqual(\n      color\n    );\n  });\n\n  it('should return undefined when not finding matching color', () => {\n    const globalStoryStyles = {\n      colors: [\n        {\n          color: {\n            r: 1,\n            g: 2,\n            b: 3,\n          },\n        },\n        {\n          color: {\n            r: 2,\n            g: 2,\n            b: 1,\n          },\n        },\n      ],\n    };\n    expect(\n      findMatchingColor(TEST_COLOR, globalStoryStyles, true)\n    ).toBeUndefined();\n  });\n\n  it('should return matching text style preset', () => {\n    const globalStoryStyles = {\n      textStyles: [STYLE_PRESET],\n    };\n    const stylePreset = {\n      color: {\n        color: {\n          r: 2,\n          g: 2,\n          b: 2,\n        },\n      },\n      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n      backgroundColor: {\n        color: {\n          r: 1,\n          g: 1,\n          b: 1,\n        },\n      },\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n    };\n    expect(\n      findMatchingStylePreset(stylePreset, globalStoryStyles)\n    ).toStrictEqual(stylePreset);\n  });\n\n  it('should return not return non-matching text style preset', () => {\n    const globalStoryStyles = {\n      textStyles: [STYLE_PRESET],\n    };\n    const stylePreset = {\n      color: {\n        color: {\n          r: 1,\n          g: 2,\n          b: 2,\n        },\n      },\n      backgroundTextMode: BACKGROUND_TEXT_MODE.FILL,\n      backgroundColor: {\n        color: {\n          r: 1,\n          g: 1,\n          b: 1,\n        },\n      },\n      font: TEXT_ELEMENT_DEFAULT_FONT,\n    };\n    expect(\n      findMatchingStylePreset(stylePreset, globalStoryStyles)\n    ).toBeUndefined();\n  });\n\n  it('should get correct text style presets from selected elements', () => {\n    const stylePreset = {\n      ...STYLE_PRESET,\n      font: {\n        family: 'Foo',\n        fallbacks: ['Bar'],\n      },\n    };\n    const elements = [\n      {\n        type: 'text',\n        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        foo: 'bar',\n        padding: {\n          vertical: 0,\n          horizontal: 0,\n        },\n        content: '<span style=\"color: rgb(1,1,1)\">Content</span>',\n      },\n      {\n        type: 'text',\n        x: 30,\n        content:\n          '<span style=\"font-weight: 700; font-style: italic; color: rgb(2,2,2)\">Content</span>',\n        ...objectWithout(stylePreset, ['color']),\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      colors: [],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [\n        {\n          backgroundTextMode: 'NONE',\n          color: TEST_COLOR,\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          fontWeight: 400,\n          isItalic: false,\n          isUnderline: false,\n          letterSpacing: 0,\n          padding: {\n            horizontal: 0,\n            vertical: 0,\n          },\n        },\n        {\n          backgroundColor: TEST_COLOR,\n          backgroundTextMode: 'FILL',\n          color: TEST_COLOR_2,\n          font: {\n            fallbacks: ['Bar'],\n            family: 'Foo',\n          },\n          fontWeight: 700,\n          isItalic: true,\n          isUnderline: false,\n          letterSpacing: 0,\n        },\n      ],\n    };\n    const presets = getTextPresets(\n      elements,\n      globalStoryStyles,\n      PRESET_TYPES.STYLE\n    );\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should ignore text color presets for multi-color text fields', () => {\n    const elements = [\n      {\n        type: 'text',\n        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content:\n          '<span style=\"color: rgb(1,1,1)\">O</span><span style=\"color: rgb(2,1,1)\">K</span>',\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      colors: [],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [],\n    };\n    const presets = getTextPresets(\n      elements,\n      globalStoryStyles,\n      PRESET_TYPES.COLOR\n    );\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should use black color when adding text style preset for multi-color text fields', () => {\n    const stylePreset = {\n      ...STYLE_PRESET,\n      fontWeight: 400,\n      isItalic: false,\n      isUnderline: false,\n      letterSpacing: 0,\n      font: {\n        family: 'Foo',\n        fallbacks: ['Bar'],\n      },\n    };\n    const elements = [\n      {\n        type: 'text',\n        x: 30,\n        content:\n          '<span style=\"color: rgb(1,1,1)\">O</span><span style=\"color: rgb(2,1,1)\">K</span>',\n        ...objectWithout(stylePreset, ['color']),\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      fillColors: [],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [\n        {\n          ...stylePreset,\n          color: { color: { r: 0, g: 0, b: 0 } },\n        },\n      ],\n    };\n    const presets = getTextPresets(\n      elements,\n      globalStoryStyles,\n      PRESET_TYPES.STYLE\n    );\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should get correct font weight for text preset', () => {\n    const elements = [\n      {\n        type: 'text',\n        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        content: '<span style=\"font-weight: 600\">Semi-bold</span>',\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      colors: [],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [\n        {\n          backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n          font: TEXT_ELEMENT_DEFAULT_FONT,\n          color: { color: { r: 0, g: 0, b: 0 } },\n          fontWeight: 600,\n          isItalic: false,\n          isUnderline: false,\n          letterSpacing: 0,\n        },\n      ],\n    };\n    const presets = getTextPresets(\n      elements,\n      globalStoryStyles,\n      PRESET_TYPES.STYLE\n    );\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should default to null/false when adding text style preset for mixed inline styles', () => {\n    const stylePreset = {\n      ...STYLE_PRESET,\n      fontWeight: null,\n      isItalic: false,\n      isUnderline: false,\n      letterSpacing: null,\n      font: {\n        family: 'Foo',\n        fallbacks: ['Bar'],\n      },\n    };\n    const elements = [\n      {\n        type: 'text',\n        x: 30,\n        content:\n          '<span style=\"letter-spacing: 2px; font-style: italic; font-weight: 700; text-decoration: underline; color: rgb(1,1,1)\">O</span><span style=\"text-decoration: none; color: rgb(2,1,1)\">K</span>',\n        ...objectWithout(stylePreset, ['color']),\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      fillColors: [],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [\n        {\n          ...stylePreset,\n          color: { color: { r: 0, g: 0, b: 0 } },\n        },\n      ],\n    };\n    const presets = getTextPresets(\n      elements,\n      globalStoryStyles,\n      PRESET_TYPES.STYLE\n    );\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should not consider existing presets as new', () => {\n    const stylePreset = {\n      ...STYLE_PRESET,\n      font: {\n        family: 'Foo',\n        fallbacks: ['Bar'],\n      },\n    };\n    const elements = [\n      {\n        type: 'text',\n        backgroundTextMode: BACKGROUND_TEXT_MODE.NONE,\n        font: TEXT_ELEMENT_DEFAULT_FONT,\n        foo: 'bar',\n        content: '<span style=\"color: rgb(1,1,1)\">Content</span>',\n        padding: {\n          vertical: 0,\n          horizontal: 0,\n        },\n      },\n      {\n        type: 'text',\n        x: 30,\n        content: '<span style=\"color: rgb(2,2,2)\">Content</span>',\n        ...objectWithout(stylePreset, ['color']),\n      },\n    ];\n    const colorPresets = {\n      colors: [TEST_COLOR, TEST_COLOR_2],\n    };\n    const expected = {\n      colors: [],\n      textStyles: [],\n    };\n    const presets = getTextPresets(elements, colorPresets, PRESET_TYPES.COLOR);\n    expect(presets).toStrictEqual(expected);\n  });\n\n  it('should get correct shape presets from selected elements', () => {\n    const elements = [\n      {\n        type: 'shape',\n        backgroundColor: TEST_COLOR,\n      },\n      {\n        type: 'shape',\n        backgroundColor: TEST_COLOR_2,\n      },\n    ];\n    const globalStoryStyles = {\n      textStyles: [],\n      colors: [],\n    };\n    const expected = {\n      colors: [TEST_COLOR, TEST_COLOR_2],\n    };\n    const presets = getShapePresets(elements, globalStoryStyles);\n    expect(presets).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/removeDupsFromArray.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport removeDupsFromArray from '../removeDupsFromArray';\n\ndescribe('removeDupsFromArray', () => {\n  it('should remove duplicates from an array of objects', () => {\n    const obj1 = {\n      key: '1',\n      foo1: 'foo1',\n      bar1: 'bar1',\n    };\n    const obj2 = {\n      key: '2',\n      foo2: 'foo2',\n      bar2: 'bar2',\n    };\n    const obj3 = {\n      key: '1',\n      foo3: 'foo3',\n      bar3: 'bar3',\n    };\n    const arr = [obj1, obj2, obj3];\n    expect(removeDupsFromArray(arr, 'key')).toStrictEqual([obj1, obj2]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/storyUpdates.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { updateSlug } from '../storyUpdates';\n\ndescribe('storyUpdates', () => {\n  describe('updateSlug', () => {\n    const updateStory = jest.fn();\n\n    afterEach(() => {\n      updateStory.mockReset();\n    });\n\n    it('should call updateStory with newly formed slug when a slug did not already exist', () => {\n      updateSlug({\n        currentSlug: '',\n        currentTitle: 'Top 10 Summer Sparkling Water Flavors',\n        updateStory,\n      });\n\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: { slug: 'top-10-summer-sparkling-water-flavors' },\n      });\n    });\n\n    it('should call fn with updated slug as story title when slug is empty and story title exists', () => {\n      updateSlug({\n        currentSlug: '',\n        currentTitle: 'Top 10 Summer Blockbusters',\n        updateStory,\n      });\n\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: { slug: 'top-10-summer-blockbusters' },\n      });\n    });\n\n    it('should call fn with empty slug when story title does not exist (fallback)', () => {\n      updateSlug({\n        currentSlug: '',\n        currentTitle: '',\n        updateStory,\n      });\n\n      expect(updateStory).toHaveBeenCalledWith({\n        properties: { slug: '' },\n      });\n    });\n\n    it('should not call fn with there is a slug present', () => {\n      updateSlug({\n        currentSlug: '10-reasons-to-go-for-a-walk',\n        currentTitle: '',\n        updateStory,\n      });\n\n      expect(updateStory).not.toHaveBeenCalled();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/textMeasurements.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { calculateTextHeight } from '@googleforcreators/element-library';\n\ndescribe('textMeasurements', () => {\n  let element;\n\n  beforeEach(() => {\n    element = {\n      id: '123',\n      content: 'Content 1',\n      backgroundColor: {\n        color: {\n          r: 255,\n          g: 0,\n          b: 0,\n          a: 0.3,\n        },\n      },\n      font: {\n        family: 'Roboto',\n        metrics: {\n          upm: 2048,\n          asc: 1900,\n          des: -500,\n          tAsc: 1536,\n          tDes: -512,\n          tLGap: 102,\n          wAsc: 1946,\n          wDes: 512,\n          xH: 1082,\n          capH: 1456,\n          yMin: -555,\n          yMax: 2163,\n          hAsc: 1900,\n          hDes: -500,\n          lGap: 0,\n        },\n      },\n      fontSize: 16,\n      textAlign: 'left',\n      type: 'text',\n      x: 10,\n      y: 10,\n      width: 50,\n      height: 50,\n      rotationAngle: 0,\n      padding: {\n        vertical: 0,\n        horizontal: 0,\n      },\n      box: { width: 1080 },\n    };\n  });\n\n  it('should create the measuring element', () => {\n    calculateTextHeight(element, 100);\n    const measurer = document.body['__WEB_STORIES_MEASURER__'];\n\n    // Text is output as an element.\n    expect(measurer.children).toHaveLength(1);\n    expect(measurer.children[0].tagName).toBe('P');\n    expect(measurer.children[0]).toHaveStyle({\n      fontSize: '16px',\n    });\n    expect(measurer).toHaveTextContent('Content 1');\n\n    // The \"web-stories-content\" class ensures that the editor markup and\n    // text output do not conflict with each other. For instance,\n    // `<b>` is styled with a regular `font-weight: bold`.\n    expect(measurer).toHaveClass('web-stories-content');\n\n    // The most important measurer styles.\n    expect(measurer).toHaveStyle({\n      boxSizing: 'border-box',\n      position: 'fixed',\n      zIndex: '-1',\n      visibility: 'hidden',\n    });\n  });\n\n  it('should re-render the measuring element', () => {\n    calculateTextHeight(element, 100);\n    const measurer = document.body['__WEB_STORIES_MEASURER__'];\n    expect(measurer.children[0]).toHaveStyle({\n      fontSize: '16px',\n    });\n\n    // Re-render.\n    const element2 = { ...element, fontSize: 20, content: 'Content 2' };\n    calculateTextHeight(element2, 100);\n\n    // Text is output as an element.\n    expect(measurer.children).toHaveLength(1);\n    expect(measurer.children[0].tagName).toBe('P');\n    expect(measurer.children[0]).toHaveStyle({\n      fontSize: '20px',\n    });\n    expect(measurer).toHaveTextContent('Content 2');\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useElementsWithLinks.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { DANGER_ZONE_HEIGHT, FULLBLEED_HEIGHT } from '@googleforcreators/units';\n\n/**\n * Internal dependencies\n */\nimport StoryContext from '../../app/story/context';\nimport CanvasContext from '../../app/canvas/context';\nimport useElementsWithLinks from '../useElementsWithLinks';\n\nconst ELEMENT_WITH_LINK = {\n  id: 'elementWithLink',\n  type: 'unknown',\n  link: {\n    url: 'https://example.com',\n  },\n  content: 'Example Link',\n  width: 40,\n  height: 40,\n  rotationAngle: 0,\n  x: 10,\n  y: 10,\n};\n\nconst ELEMENT_WITH_LINK_BELOW_LIMIT = {\n  id: 'elementWithLinkBelowLimit',\n  type: 'unknown',\n  link: {\n    url: 'https://example.com',\n  },\n  content: 'Example Link',\n  width: 40,\n  height: 40,\n  rotationAngle: 0,\n  x: 10,\n  y: FULLBLEED_HEIGHT * 0.8 + DANGER_ZONE_HEIGHT + 10,\n};\n\nconst ELEMENT = {\n  id: 'element',\n  type: 'unknown',\n  content: 'Example Link',\n  width: 40,\n  height: 40,\n  rotationAngle: 0,\n  x: 10,\n  y: 10,\n};\n\nconst ELEMENT_BELOW_LIMIT = {\n  id: 'elementBelowLimit',\n  type: 'unknown',\n  content: 'Example Link',\n  width: 40,\n  height: 40,\n  rotationAngle: 0,\n  x: 10,\n  y: FULLBLEED_HEIGHT * 0.8 + DANGER_ZONE_HEIGHT + 10,\n};\n\nfunction render({\n  pageAttachmentContainer = null,\n  pageAttachment = '',\n  elements = [],\n  selectedElements = [],\n}) {\n  const storyContextValue = {\n    state: {\n      currentPage: {\n        elements,\n        pageAttachment: {\n          url: pageAttachment,\n        },\n      },\n      selectedElements,\n    },\n  };\n\n  const canvasContext = {\n    state: {\n      pageAttachmentContainer,\n    },\n    actions: {},\n  };\n\n  const Wrapper = ({ children }) => (\n    <StoryContext.Provider value={storyContextValue}>\n      <CanvasContext.Provider value={canvasContext}>\n        {children}\n      </CanvasContext.Provider>\n    </StoryContext.Provider>\n  );\n\n  return renderHook(() => useElementsWithLinks(), {\n    wrapper: Wrapper,\n    initialProps: true,\n  });\n}\n\ndescribe('useElementsWithLinks', () => {\n  describe('hasLinksInAttachmentArea', () => {\n    it('returns true if there are links in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        elements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasLinksInAttachmentArea).toBeTrue();\n    });\n\n    it('returns true even if there is no page attachment', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: '',\n        elements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasLinksInAttachmentArea).toBeTrue();\n    });\n\n    it('returns false if links are not in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        elements: [ELEMENT_WITH_LINK],\n      });\n      expect(result.current.hasLinksInAttachmentArea).toBeFalse();\n    });\n\n    it('returns false if there is no page attachment container', () => {\n      const { result } = render({\n        pageAttachment: 'https://example.com',\n        elements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasLinksInAttachmentArea).toBeFalse();\n    });\n  });\n\n  describe('hasElementsInAttachmentArea', () => {\n    it('returns true if the selected elements are in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasElementsInAttachmentArea).toBeTrue();\n    });\n\n    it('returns true if the selected elements are in the page attachment area and do not have links', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_BELOW_LIMIT],\n      });\n      expect(result.current.hasElementsInAttachmentArea).toBeTrue();\n    });\n\n    it('returns false if there is no page attachment', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: '',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasElementsInAttachmentArea).toBeFalse();\n    });\n\n    it('returns false if the selected elements are not in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK],\n      });\n      expect(result.current.hasElementsInAttachmentArea).toBeFalse();\n    });\n\n    it('returns false if there is no page attachment container', () => {\n      const { result } = render({\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasElementsInAttachmentArea).toBeFalse();\n    });\n  });\n\n  describe('hasInvalidLinkSelected', () => {\n    it('returns true if the selected elements are in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasInvalidLinkSelected).toBeTrue();\n    });\n\n    it('returns false if there is no page attachment', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: '',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasInvalidLinkSelected).toBeFalse();\n    });\n\n    it('returns false if the selected elements are not in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK],\n      });\n      expect(result.current.hasInvalidLinkSelected).toBeFalse();\n    });\n\n    it('returns false if there is no page attachment container', () => {\n      const { result } = render({\n        pageAttachment: 'https://example.com',\n        selectedElements: [ELEMENT_WITH_LINK_BELOW_LIMIT],\n      });\n      expect(result.current.hasInvalidLinkSelected).toBeFalse();\n    });\n  });\n\n  describe('isElementInAttachmentArea', () => {\n    it('returns true if the given element is in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n      });\n      expect(\n        result.current.isElementInAttachmentArea(ELEMENT_BELOW_LIMIT)\n      ).toBeTrue();\n    });\n\n    it('returns false if there is no page attachment', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: '',\n      });\n      expect(\n        result.current.isElementInAttachmentArea(ELEMENT_BELOW_LIMIT)\n      ).toBeFalse();\n    });\n\n    it('returns false if the given element is not in the page attachment area', () => {\n      const { result } = render({\n        pageAttachmentContainer: document.body,\n        pageAttachment: 'https://example.com',\n      });\n      expect(result.current.isElementInAttachmentArea(ELEMENT)).toBeFalse();\n    });\n\n    it('returns false if there is no page attachment container', () => {\n      const { result } = render({\n        pageAttachment: 'https://example.com',\n      });\n      expect(\n        result.current.isElementInAttachmentArea(ELEMENT_BELOW_LIMIT)\n      ).toBeFalse();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useGlobalClipboardHandlers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent } from '@testing-library/react';\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useGlobalClipboardHandlers from '../useGlobalClipboardHandlers';\n\ndescribe('useGlobalClipboardHandlers', () => {\n  it('should call the set handlers as expected', () => {\n    const copyCutHandler = jest.fn();\n    const pasteHandler = jest.fn();\n\n    const windowSpy = jest\n      .spyOn(window, 'getSelection')\n      .mockImplementation(() => false);\n\n    renderHook(() => {\n      useGlobalClipboardHandlers(copyCutHandler, pasteHandler);\n    });\n\n    fireEvent.paste(document, '');\n    expect(pasteHandler).toHaveBeenCalledOnce();\n\n    fireEvent.copy(document);\n    fireEvent.cut(document);\n    expect(copyCutHandler).toHaveBeenCalledTimes(2);\n\n    windowSpy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useHandlers.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport useHandlers from '../useHandlers';\n\nconst handler1 = jest.fn();\nconst handler2 = jest.fn();\n\ndescribe('useHandlers', () => {\n  let handlers, registerHandler;\n\n  function Comp() {\n    const result = useHandlers();\n    handlers = result[0];\n    registerHandler = result[1];\n    return <div />;\n  }\n\n  it('should add/remove any number of handlers and remain invariant', () => {\n    render(<Comp />);\n\n    expect(handlers).toStrictEqual([]);\n\n    const cleanup1 = registerHandler(handler1);\n    expect(handlers).toStrictEqual([handler1]);\n\n    const cleanup2 = registerHandler(handler2);\n    expect(handlers).toStrictEqual([handler1, handler2]);\n\n    cleanup1();\n    expect(handlers).toStrictEqual([handler2]);\n\n    cleanup2();\n    expect(handlers).toStrictEqual([]);\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useIdleTaskQueue.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { renderHook, act } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport useIdleTaskQueue from '../useIdleTaskQueue';\nimport { requestIdleCallback, cancelIdleCallback } from '../idleCallback';\n\njest.mock('../idleCallback', () => {\n  return {\n    __esModule: true,\n    requestIdleCallback: jest.fn(),\n    cancelIdleCallback: jest.fn(),\n  };\n});\n\ndescribe('useIdleTaskQueue', () => {\n  let mockIdleCallbacks, runIdleCallbacks;\n\n  beforeEach(() => {\n    mockIdleCallbacks = [];\n    runIdleCallbacks = () => {\n      while (mockIdleCallbacks.length > 0) {\n        const { task } = mockIdleCallbacks.shift();\n        task();\n      }\n    };\n\n    requestIdleCallback.mockImplementation((callback) => {\n      const idleCallbackId = Symbol();\n      mockIdleCallbacks.push({ taskId: idleCallbackId, task: callback });\n      return idleCallbackId;\n    });\n    cancelIdleCallback.mockImplementation((idleCallbackId) => {\n      mockIdleCallbacks = mockIdleCallbacks.filter(\n        ({ taskId }) => taskId !== idleCallbackId\n      );\n    });\n  });\n\n  describe('queueIdleTask', () => {\n    it('calls idle tasks sequentially', async () => {\n      const runAllIdleCallbacks = async () => {\n        runIdleCallbacks();\n        await act(async () => {\n          await Promise.resolve();\n        });\n      };\n\n      const {\n        result: { current: queueIdleTask },\n      } = renderHook(() => useIdleTaskQueue());\n      const task1Tuple = { taskId: 1, task: jest.fn(() => Promise.resolve()) };\n      const task2Tuple = { taskId: 2, task: jest.fn(() => Promise.resolve()) };\n      const task3Tuple = { taskId: 3, task: jest.fn(() => Promise.resolve()) };\n\n      // queue all tasks\n      queueIdleTask(task1Tuple);\n      queueIdleTask(task2Tuple);\n      queueIdleTask(task3Tuple);\n\n      // see that no tasks have been run\n      expect(task1Tuple.task).toHaveBeenCalledTimes(0);\n      expect(task2Tuple.task).toHaveBeenCalledTimes(0);\n      expect(task3Tuple.task).toHaveBeenCalledTimes(0);\n\n      // See that task queue exhibits first out (FIFO) behavior.\n      await runAllIdleCallbacks();\n      expect(task1Tuple.task).toHaveBeenCalledOnce();\n      expect(task2Tuple.task).toHaveBeenCalledTimes(0);\n      expect(task3Tuple.task).toHaveBeenCalledTimes(0);\n\n      await runAllIdleCallbacks();\n      expect(task1Tuple.task).toHaveBeenCalledOnce();\n      expect(task2Tuple.task).toHaveBeenCalledOnce();\n      expect(task3Tuple.task).toHaveBeenCalledTimes(0);\n\n      await runAllIdleCallbacks();\n      expect(task1Tuple.task).toHaveBeenCalledOnce();\n      expect(task2Tuple.task).toHaveBeenCalledOnce();\n      expect(task3Tuple.task).toHaveBeenCalledOnce();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useIsUploadingToStory.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport MediaContext from '../../app/media/context';\nimport StoryContext from '../../app/story/context';\nimport useIsUploadingToStory from '../useIsUploadingToStory';\n\nconst isCurrentResourceUploading = jest.fn(() => false);\nconst isCurrentResourceProcessing = jest.fn(() => false);\n\nfunction render({ pages = [] }) {\n  const storyContextValue = {\n    state: {\n      pages,\n    },\n  };\n\n  const mediaContextValue = {\n    local: {\n      state: { isCurrentResourceUploading, isCurrentResourceProcessing },\n    },\n  };\n\n  const Wrapper = ({ children }) => (\n    <StoryContext.Provider value={storyContextValue}>\n      <MediaContext.Provider value={mediaContextValue}>\n        {children}\n      </MediaContext.Provider>\n    </StoryContext.Provider>\n  );\n\n  return renderHook(() => useIsUploadingToStory(), {\n    wrapper: Wrapper,\n    initialProps: true,\n  });\n}\n\ndescribe('useIsUploadingToStory', () => {\n  afterEach(() => {\n    isCurrentResourceUploading.mockReset();\n    isCurrentResourceProcessing.mockReset();\n  });\n\n  it('should return false if there are no elements', () => {\n    const pages = [\n      {\n        elements: [],\n      },\n      {\n        elements: [],\n      },\n    ];\n\n    const { result } = render({ pages });\n    expect(result.current).toBeFalse();\n  });\n\n  it('should return false if there are no media elements', () => {\n    const pages = [\n      {\n        elements: [{ id: '123', type: 'text' }],\n      },\n      {\n        elements: [{ id: '789', type: 'text' }],\n      },\n    ];\n\n    const { result } = render({ pages });\n    expect(result.current).toBeFalse();\n  });\n\n  it('should return false if there are no elements being uploaded', () => {\n    const pages = [\n      {\n        elements: [\n          { id: '123', type: 'video', resource: { type: 'video', id: '1' } },\n          { id: '456', type: 'video', resource: { type: 'video', id: '2' } },\n        ],\n      },\n      {\n        elements: [\n          { id: '789', type: 'video', resource: { type: 'video', id: '3' } },\n          { id: '147', type: 'image', resource: { type: 'image', id: '4' } },\n        ],\n      },\n    ];\n\n    isCurrentResourceUploading.mockReturnValue(false);\n    isCurrentResourceProcessing.mockReturnValue(false);\n\n    const { result } = render({ pages });\n    expect(result.current).toBeFalse();\n  });\n\n  it('should return true if resources are being uploaded', () => {\n    const pages = [\n      {\n        elements: [\n          {\n            id: '123',\n            type: 'video',\n            resource: { type: 'video', id: 'uploadingId' },\n          },\n          { id: '456', type: 'video', resource: { type: 'video', id: '2' } },\n        ],\n      },\n      {\n        elements: [\n          { id: '789', type: 'video', resource: { type: 'video', id: '3' } },\n          { id: '147', type: 'image', resource: { type: 'image', id: '4' } },\n        ],\n      },\n    ];\n\n    isCurrentResourceUploading.mockImplementation(\n      (resourceId) => 'uploadingId' === resourceId\n    );\n\n    const { result } = render({ pages });\n    expect(result.current).toBeTrue();\n  });\n\n  it('should return true if resources are being processed', () => {\n    const pages = [\n      {\n        elements: [\n          { id: '123', type: 'video', resource: { type: 'video', id: '1' } },\n          { id: '456', type: 'video', resource: { type: 'video', id: '2' } },\n        ],\n      },\n      {\n        elements: [\n          {\n            id: '789',\n            type: 'video',\n            resource: { type: 'video', id: 'processingId' },\n          },\n          { id: '147', type: 'image', resource: { type: 'image', id: '4' } },\n        ],\n      },\n    ];\n\n    isCurrentResourceProcessing.mockImplementation(\n      (resourceId) => 'processingId' === resourceId\n    );\n\n    const { result } = render({ pages });\n    expect(result.current).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/usePreventWindowUnload.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\n\n/**\n * Internal dependencies\n */\nimport usePreventWindowUnload from '../usePreventWindowUnload';\n\ndescribe('usePreventWindowUnload', () => {\n  it('should register beforeunload listener', () => {\n    jest.spyOn(window, 'addEventListener');\n    renderHook(() => {\n      const setPreventUnload = usePreventWindowUnload();\n      setPreventUnload('history', true);\n    });\n    expect(window.addEventListener).toHaveBeenCalledWith(\n      'beforeunload',\n      expect.any(Function)\n    );\n  });\n\n  it('should unregister beforeunload listener', () => {\n    jest.spyOn(window, 'removeEventListener');\n    renderHook(() => {\n      const setPreventUnload = usePreventWindowUnload();\n      setPreventUnload('history', false);\n    });\n\n    expect(window.removeEventListener).toHaveBeenCalledWith(\n      'beforeunload',\n      expect.any(Function)\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/test/useRovingTabIndex.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { getFocusableElementDirection } from '../useRovingTabIndex';\nimport { getNextEnabledSibling } from '../useRovingTabIndex/flatNavigation';\n\ndescribe('getNextEnabledSibling', () => {\n  it('should get next sibling', () => {\n    const wrapper = document.createElement('div');\n    const button1 = document.createElement('button');\n    wrapper.appendChild(button1);\n    const button2 = document.createElement('button');\n    wrapper.appendChild(button2);\n    const button3 = document.createElement('button3');\n    wrapper.appendChild(button3);\n\n    expect(getNextEnabledSibling(button2, 'previousSibling')).toBe(button1);\n    expect(getNextEnabledSibling(button2, 'nextSibling')).toBe(button3);\n  });\n\n  it('should skip disabled sibling', () => {\n    const wrapper = document.createElement('div');\n    const button1 = document.createElement('button');\n    wrapper.appendChild(button1);\n    const button2 = document.createElement('button');\n    button2.disabled = 'true';\n    wrapper.appendChild(button2);\n    const button3 = document.createElement('button3');\n    wrapper.appendChild(button3);\n\n    expect(getNextEnabledSibling(button3, 'previousSibling')).toBe(button1);\n    expect(getNextEnabledSibling(button1, 'nextSibling')).toBe(button3);\n  });\n});\n\ndescribe('getSiblingDirection', () => {\n  describe('RTL', () => {\n    it.each(['ArrowRight', 'ArrowUp', 'PageUp'])(\n      'given key: %s returns \"previousSibling\"',\n      (key) => {\n        const isRTL = true;\n        expect(getFocusableElementDirection(isRTL, key)).toBe(\n          'previousSibling'\n        );\n      }\n    );\n\n    it.each(['ArrowLeft', 'ArrowDown', 'PageDown'])(\n      'given key: %s returns \"nextSibling\"',\n      (key) => {\n        const isRTL = true;\n        expect(getFocusableElementDirection(isRTL, key)).toBe('nextSibling');\n      }\n    );\n  });\n\n  describe('LTR', () => {\n    it.each(['ArrowLeft', 'ArrowUp', 'PageUp'])(\n      'given key: %s returns \"previousSibling\"',\n      (key) => {\n        const isRTL = false;\n        expect(getFocusableElementDirection(isRTL, key)).toBe(\n          'previousSibling'\n        );\n      }\n    );\n\n    it.each(['ArrowRight', 'ArrowDown', 'PageDown'])(\n      'given key: %s returns \"nextSibling\"',\n      (key) => {\n        const isRTL = false;\n        expect(getFocusableElementDirection(isRTL, key)).toBe('nextSibling');\n      }\n    );\n  });\n});\n"
  },
  {
    "path": "packages/story-editor/src/utils/useAddPreset.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport { useStory } from '../app';\nimport getUniquePresets from './getUniquePresets';\nimport {\n  areAllType,\n  getPagePreset,\n  getShapePresets,\n  getTextPresets,\n} from './presetUtils';\n\nfunction useAddPreset({ presetType, isBackgroundColor }) {\n  const {\n    currentPage,\n    currentStoryStyles = { colors: [] },\n    selectedElements,\n    globalStoryStyles = { colors: [], textStyles: [] },\n    updateStory,\n  } = useStory(\n    ({\n      state: {\n        currentPage,\n        selectedElements,\n        story: { globalStoryStyles, currentStoryStyles },\n      },\n      actions: { updateStory },\n    }) => {\n      return {\n        currentPage,\n        currentStoryStyles,\n        selectedElements,\n        globalStoryStyles,\n        updateStory,\n      };\n    }\n  );\n  const { colors, textStyles } = globalStoryStyles;\n  const { colors: localColors } = currentStoryStyles;\n\n  const isText = areAllType('text', selectedElements);\n  const isBackground =\n    selectedElements?.[0]?.id === currentPage?.elements?.[0]?.id;\n\n  const getPresets = useCallback(\n    (addedPresets, currentPresets) => {\n      if (isText) {\n        return {\n          ...addedPresets,\n          ...getTextPresets(\n            selectedElements,\n            currentPresets,\n            presetType,\n            isBackgroundColor\n          ),\n        };\n      } else if (isBackground) {\n        return {\n          ...addedPresets,\n          ...getPagePreset(currentPage, currentPresets),\n        };\n      } else {\n        return {\n          ...addedPresets,\n          ...getShapePresets(selectedElements, currentPresets),\n        };\n      }\n    },\n    [\n      currentPage,\n      isBackground,\n      isText,\n      presetType,\n      selectedElements,\n      isBackgroundColor,\n    ]\n  );\n\n  const updateLocalPresets = useCallback(\n    (addedPresets) => {\n      updateStory({\n        properties: {\n          currentStoryStyles: {\n            colors: getUniquePresets([...localColors, ...addedPresets.colors]),\n          },\n        },\n      });\n    },\n    [localColors, updateStory]\n  );\n\n  const updateGlobalPresets = useCallback(\n    (addedPresets) => {\n      updateStory({\n        properties: {\n          globalStoryStyles: {\n            textStyles: getUniquePresets([\n              ...textStyles,\n              ...addedPresets.textStyles,\n            ]),\n            colors: getUniquePresets([...colors, ...addedPresets.colors]),\n          },\n        },\n      });\n    },\n    [colors, textStyles, updateStory]\n  );\n\n  const handleAddPreset = useCallback(\n    (addedPresets, isLocal = false) => {\n      const currentPresets = isLocal ? currentStoryStyles : globalStoryStyles;\n      addedPresets = getPresets(addedPresets, currentPresets);\n      if (\n        addedPresets.colors?.length > 0 ||\n        addedPresets.textStyles?.length > 0\n      ) {\n        if (isLocal) {\n          updateLocalPresets(addedPresets, currentPresets);\n        } else {\n          updateGlobalPresets(addedPresets, currentPresets);\n        }\n\n        return addedPresets;\n      }\n\n      return undefined;\n    },\n    [\n      getPresets,\n      currentStoryStyles,\n      globalStoryStyles,\n      updateGlobalPresets,\n      updateLocalPresets,\n    ]\n  );\n  const addGlobalPreset = (evt) => {\n    evt.stopPropagation();\n    return handleAddPreset({\n      textStyles: [],\n      colors: [],\n    });\n  };\n\n  const addLocalPreset = (evt) => {\n    evt.stopPropagation();\n    return handleAddPreset(\n      {\n        colors: [],\n      },\n      true /* isLocal */\n    );\n  };\n\n  return {\n    addGlobalPreset,\n    addLocalPreset,\n  };\n}\n\nexport default useAddPreset;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useApplyTextAutoStyle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getHTMLFormatters } from '@googleforcreators/rich-text';\nimport { BACKGROUND_TEXT_MODE } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useCalculateAccessibleTextColors } from '../app/pageCanvas';\nimport { applyHiddenPadding } from '../components/panels/design/textStyle/utils';\n\nfunction useApplyTextAutoStyle(element, updater) {\n  const htmlFormatters = getHTMLFormatters();\n  const { setColor } = htmlFormatters;\n  const calculateAccessibleTextColors = useCalculateAccessibleTextColors();\n\n  const applyTextAutoStyle = async () => {\n    const autoColor = await calculateAccessibleTextColors(element);\n    const { color: fgColor, backgroundColor } = autoColor;\n    if (backgroundColor || fgColor) {\n      const highlightProps = backgroundColor\n        ? {\n            backgroundColor: { color: backgroundColor },\n            backgroundTextMode: BACKGROUND_TEXT_MODE.HIGHLIGHT,\n            padding: applyHiddenPadding(element),\n          }\n        : null;\n      const content = fgColor\n        ? setColor(element.content, { color: fgColor })\n        : element.content;\n      updater({ ...highlightProps, content });\n    }\n  };\n\n  return applyTextAutoStyle;\n}\n\nexport default useApplyTextAutoStyle;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useCORSProxy.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport type { Resource } from '@googleforcreators/media';\n\n/**\n * Internal dependencies\n */\nimport { useAPI } from '../app/api';\n\nfunction useCORSProxy() {\n  const {\n    actions: { getProxyUrl },\n  } = useAPI();\n\n  /**\n   * Check if the resource can be accessed directly.\n   *\n   * Makes a HEAD request, which in turn triggers a CORS preflight request\n   * in the browser.\n   *\n   * If the request passes, we don't need to do anything.\n   * If it doesn't, it means we need to run the resource through our CORS proxy at all times.\n   *\n   * @type {function(string): Promise<boolean>}\n   */\n  const checkResourceAccess = useCallback(async (link: string) => {\n    let shouldProxy = false;\n    if (!link) {\n      return shouldProxy;\n    }\n    try {\n      await fetch(link, {\n        method: 'HEAD',\n      });\n    } catch {\n      shouldProxy = true;\n    }\n\n    return shouldProxy;\n  }, []);\n\n  /**\n   * Get proxied url.\n   *\n   * @param {Object} resource Resource object\n   * @param {string} src The thumbnail's url\n   * @return {null|string} Return proxied source or null.\n   */\n  const getProxiedUrl = useCallback(\n    (resource: Resource, src?: string) => {\n      const { needsProxy } = resource;\n      if (needsProxy && src && getProxyUrl) {\n        return getProxyUrl(src);\n      }\n      return src || null;\n    },\n    [getProxyUrl]\n  );\n\n  return {\n    getProxiedUrl,\n    checkResourceAccess,\n  };\n}\nexport default useCORSProxy;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useDoubleClick.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\n\ntype ClickCallback = (evt: MouseEvent, target: Element) => void;\n\n/**\n * This hook creates a handler to use for double click listening\n * on a node, where single clicks are also relevant. Default timeout\n * is 200 ms. If no subsequent click has been recorded in the given\n * time, single click will be assumed.\n *\n * This hook returns a handler retrieval function, not the handler\n * itself. This allows the component to use the same hook for multiple\n * children listening for events.\n *\n * For example:\n * ```\n * function SomeComponent() {\n *   const handleSingle = useCallback( ( evt, item ) => {\n *     // Handle single click on `item`\n *   }, [] );\n *   const handleDouble = useCallback( ( evt, item ) => {\n *     // Handle double click on `item`\n *   }, [] );\n *   const getHandler = useDoubleClick( handleSingle, handleDouble );\n *   const items = [\n *     // Some objects with `id` and `name` attributes.\n *   ];\n *   return items.map( ( item} ) => (\n *     <button key={ item.id } onClick={ getHandler( item ) }>\n *       { item.name }\n *     </button>\n *   ) );\n * }\n * ```\n *\n * @param onSingleClick  Handler to activate on single click.\n * @param onDoubleClick  Handler to activate on double click.\n * @param ms             Timeout in ms to wait - defaults to 200.\n * @return Handler retrieval function to get an onClick listener (invoke with unique value).\n */\nconst useDoubleClick = (\n  onSingleClick: ClickCallback,\n  onDoubleClick: ClickCallback,\n  ms = 200\n) => {\n  const [target, setTarget] = useState<Element | null>(null);\n  const [lastEvent, setLastEvent] = useState<MouseEvent | null>(null);\n  const getHandler = useCallback(\n    (newTarget: Element) => (evt: MouseEvent) => {\n      evt.stopPropagation();\n\n      if (target !== newTarget) {\n        if (target) {\n          onSingleClick(evt, target);\n        }\n        setTarget(newTarget);\n        setLastEvent(evt);\n        return;\n      }\n\n      onDoubleClick(evt, target);\n      setTarget(null);\n    },\n    [onSingleClick, onDoubleClick, target]\n  );\n  useEffect(() => {\n    if (!target) {\n      return undefined;\n    }\n    const int = setTimeout(() => {\n      setTarget(null);\n      if (lastEvent && target) {\n        onSingleClick(lastEvent, target);\n      }\n    }, ms);\n    return () => {\n      clearTimeout(int);\n    };\n  }, [target, lastEvent, onSingleClick, ms]);\n\n  return getHandler;\n};\n\nexport default useDoubleClick;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useElementPolygon.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport SAT from 'sat';\nimport { useUnits } from '@googleforcreators/units';\nimport { canSupportMultiBorder } from '@googleforcreators/masks';\n\n/**\n * Internal dependencies\n */\nimport useStory from '../app/story/useStory';\nimport useCanvas from '../app/canvas/useCanvas';\n\nfunction useElementPolygon() {\n  const nodesById = useCanvas(({ state: { nodesById } }) => nodesById);\n  const bgElement = useStory(({ state }) =>\n    state.currentPage?.elements?.find(({ isBackground }) => isBackground)\n  );\n\n  const { getBoxWithBorder, getBox } = useUnits(\n    ({ actions: { getBox, getBoxWithBorder } }) => ({\n      getBoxWithBorder,\n      getBox,\n    })\n  );\n\n  const getElementPolygon = (element) => {\n    const bgNode = nodesById[bgElement.id];\n    const {\n      x: bgX,\n      y: bgY,\n      width: bgWidth,\n      height: bgHeight,\n    } = bgNode.getBoundingClientRect();\n    const bgPolygon = new SAT.Box(\n      new SAT.Vector(bgX, bgY),\n      bgWidth,\n      bgHeight\n    ).toPolygon();\n    // The background element is offset by a certain amount, so add that back in for\n    // other elements when resolving their position relative to it.\n    const elementYOffset = -getBox(bgElement).y;\n    if (element.isBackground) {\n      return bgPolygon;\n    }\n    const { id, rotationAngle } = element;\n    const node = nodesById[id];\n    if (!node) {\n      return null;\n    }\n    const box = canSupportMultiBorder(element)\n      ? getBoxWithBorder(element)\n      : getBox(element);\n    // Note that we place the box at the center coordinate. We do this for the angle\n    // to apply correctly. We correct for this offset with `setOffset`` later.\n    const center = new SAT.Vector(\n      bgPolygon.pos.x + box.x + box.width / 2,\n      bgPolygon.pos.y + elementYOffset + box.y + box.height / 2\n    );\n    const elementBox = new SAT.Box(center, box.width, box.height);\n    const polygon = elementBox.toPolygon();\n    const offset = new SAT.Vector(-box.width / 2, -box.height / 2);\n    polygon.setOffset(offset);\n    polygon.setAngle((rotationAngle * Math.PI) / 180);\n    return polygon;\n  };\n\n  return getElementPolygon;\n}\n\nexport default useElementPolygon;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useElementsWithLinks.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport {\n  elementIs,\n  isElementBelowLimit,\n  type Element,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../app/story';\nimport { useCanvas } from '../app/canvas';\n\n/**\n * Custom hook to aid with detecting links conflicting with page attachments.\n *\n * @return Hook result.\n */\nfunction useElementsWithLinks() {\n  const { pageAttachmentContainer } = useCanvas((state) => ({\n    pageAttachmentContainer: state.state.pageAttachmentContainer,\n  }));\n  const {\n    hasLinksInAttachmentArea,\n    hasInvalidLinkSelected,\n    hasPageAttachment,\n    hasElementsInAttachmentArea,\n  } = useStory(({ state }) => {\n    const elementsWithLinks =\n      state.currentPage?.elements.filter(elementIs.linkable) || [];\n\n    const hasPageAttachment = Boolean(\n      state.currentPage?.pageAttachment?.url?.length\n    );\n\n    return {\n      hasInvalidLinkSelected: Boolean(\n        pageAttachmentContainer &&\n        hasPageAttachment &&\n        state.selectedElements\n          .filter(elementIs.linkable)\n          .some((element) => isElementBelowLimit(element))\n      ),\n      hasLinksInAttachmentArea: Boolean(\n        pageAttachmentContainer &&\n        elementsWithLinks.some((element) => isElementBelowLimit(element, true))\n      ),\n      hasElementsInAttachmentArea: Boolean(\n        pageAttachmentContainer &&\n        hasPageAttachment &&\n        state.selectedElements.some((element) =>\n          isElementBelowLimit(element, false)\n        )\n      ),\n      hasPageAttachment,\n    };\n  });\n\n  const isElementInAttachmentArea = useCallback(\n    (element: Element) => {\n      if (!pageAttachmentContainer) {\n        return false;\n      }\n\n      if (!hasPageAttachment) {\n        return false;\n      }\n\n      return isElementBelowLimit(element, false);\n    },\n    [pageAttachmentContainer, hasPageAttachment]\n  );\n\n  return {\n    hasLinksInAttachmentArea,\n    hasInvalidLinkSelected,\n    isElementInAttachmentArea,\n    hasElementsInAttachmentArea,\n  };\n}\n\nexport default useElementsWithLinks;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useFocusTrapping.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n\nconst getFocusableElements = (node) => {\n  if (!node) {\n    return [];\n  }\n  return [\n    ...node.querySelectorAll(\n      'a[href], button, textarea, input[type]:not([type=\"hidden\"]), select'\n    ),\n  ].filter(\n    (el) => !el.hasAttribute('disabled') && el.getAttribute('tabindex') !== '-1'\n  );\n};\n\nfunction useFocusTrapping({ ref }) {\n  const handleTab = (e) => {\n    const focusableElements = getFocusableElements(ref.current);\n    const firstEl = focusableElements[0];\n    const lastEl = focusableElements[focusableElements.length - 1];\n\n    if (!e.shiftKey && document.activeElement === lastEl) {\n      firstEl.focus();\n      e.preventDefault();\n    } else if (e.shiftKey && document.activeElement === firstEl) {\n      lastEl.focus();\n      e.preventDefault();\n    }\n  };\n\n  useKeyDownEffect(\n    ref,\n    { key: ['tab'], allowDefault: true, editable: true, shift: true },\n    handleTab\n  );\n  useKeyDownEffect(\n    ref,\n    { key: ['tab'], allowDefault: true, editable: true },\n    handleTab\n  );\n}\n\nexport default useFocusTrapping;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useGlobalClipboardHandlers.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport nativeCopyPasteExpected from './nativeCopyPasteExpected';\n\ntype HandlerCallback = (event: ClipboardEvent) => void;\n\n/**\n * @param copyCutHandler Copy & Cut handler.\n * @param pasteHandler Paste handler.\n */\nfunction useGlobalClipboardHandlers(\n  copyCutHandler: HandlerCallback,\n  pasteHandler: HandlerCallback\n) {\n  useEffect(() => {\n    const copyCutHandlerWrapper = (evt: ClipboardEvent) => {\n      const { clipboardData } = evt;\n\n      // Elements that either handle their own clipboard or have selection.\n      if (nativeCopyPasteExpected()) {\n        return;\n      }\n\n      // Someone has already put something in the clipboard. Do not override.\n      if (clipboardData?.types?.length) {\n        return;\n      }\n\n      copyCutHandler(evt);\n    };\n\n    // We always use global handler for pasting.\n    const pasteHandlerWrapper = (evt: ClipboardEvent) => {\n      if (!nativeCopyPasteExpected()) {\n        pasteHandler(evt);\n      }\n    };\n\n    document.addEventListener('copy', copyCutHandlerWrapper);\n    document.addEventListener('cut', copyCutHandlerWrapper);\n    document.addEventListener('paste', pasteHandlerWrapper);\n    return () => {\n      document.removeEventListener('copy', copyCutHandlerWrapper);\n      document.removeEventListener('cut', copyCutHandlerWrapper);\n      document.removeEventListener('paste', pasteHandlerWrapper);\n    };\n  }, [copyCutHandler, pasteHandler]);\n}\n\nexport default useGlobalClipboardHandlers;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useHandlers.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useMemo, useRef } from '@googleforcreators/react';\n\ntype HandleFn = () => void;\n\nfunction useHandlers() {\n  const handlersRef = useRef<HandleFn[]>([]);\n\n  const registerHandler = useCallback((handler: HandleFn) => {\n    const handlerList = handlersRef.current;\n    handlerList.push(handler);\n    return () => {\n      handlerList.splice(handlerList.indexOf(handler), 1);\n    };\n  }, []);\n\n  return useMemo(\n    () => [handlersRef.current, registerHandler],\n    [registerHandler]\n  );\n}\n\nexport default useHandlers;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useIdleTaskQueue.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useRef, useCallback } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { requestIdleCallback, cancelIdleCallback } from './idleCallback';\n\ninterface Task {\n  taskId: string | null;\n  task: number | null | (() => Promise<void>);\n}\n\n/**\n * Creates a FIFO idle task queue\n *\n * @return queueIdleTask\n */\nfunction useIdleTaskQueue() {\n  const taskQueueRef = useRef<Task[]>([]);\n  const isTaskQueueRunningRef = useRef(false);\n  const currentTaskRef = useRef<Task>({ taskId: null, task: null });\n\n  /**\n   * Recursively runs idle task queue sequentially\n   * until all queued tasks are run.\n   *\n   * @return {void}\n   */\n  const runTaskQueue = useCallback(() => {\n    isTaskQueueRunningRef.current = true;\n\n    if (!taskQueueRef.current.length) {\n      isTaskQueueRunningRef.current = false;\n      return;\n    }\n\n    const { taskId, task } = taskQueueRef.current.shift() as Task;\n    const idleCallbackId = requestIdleCallback(() => {\n      if (typeof task === 'function') {\n        void task().then(() => {\n          currentTaskRef.current = { taskId: null, task: null };\n          // eslint-disable-next-line react-hooks/immutability -- FIXME\n          runTaskQueue();\n        });\n      }\n    });\n    currentTaskRef.current = { taskId, task: idleCallbackId };\n  }, []);\n\n  /**\n   * Clears queue of any tasks associated with the\n   * given task id.\n   *\n   * @param id id of a task\n   * @return {void}\n   */\n  const clearQueuedTask = useCallback(\n    (id: string) => {\n      // Remove any queued tasks associated with this task Id\n      taskQueueRef.current = taskQueueRef.current.filter(\n        ({ taskId }: Task) => taskId !== id\n      );\n\n      // If the current requested task hasn't fired, clear it\n      // and restart the queue on the next task\n      const { taskId, task }: Task = currentTaskRef.current;\n      if (id === taskId && typeof task === 'number') {\n        cancelIdleCallback(task);\n        currentTaskRef.current = { taskId: null, task: null };\n        runTaskQueue();\n      }\n    },\n    [runTaskQueue]\n  );\n\n  /**\n   * Takes a task tuple consisting of a uid for your requested task,\n   * and the requested task, and adds that task to the idleQueue.\n   * Returns a cleanup function to cancel the task.\n   *\n   * Idle Task Queue is a FIFO queue (first in first out)\n   */\n  const queueIdleTask = useCallback(\n    ({ taskId, task }: Task) => {\n      if (taskId) {\n        // Clear queue of any stale tasks\n        clearQueuedTask(taskId);\n      }\n      // Add request to generate page image generation queue\n      taskQueueRef.current.push({ taskId, task });\n\n      // If the queue has stopped processing because\n      // it ran out of entries, restart it\n      if (!isTaskQueueRunningRef.current) {\n        runTaskQueue();\n      }\n\n      return () => {\n        if (taskId) {\n          clearQueuedTask(taskId);\n        }\n      };\n    },\n    [runTaskQueue, clearQueuedTask]\n  );\n\n  return queueIdleTask;\n}\n\nexport default useIdleTaskQueue;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useIsUploadingToStory.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { useLocalMedia, useStory } from '../app';\n\nfunction useIsUploadingToStory() {\n  const resourceIds = useStory(({ state: { pages = [] } }) =>\n    pages.reduce((acc, curr) => {\n      acc.push(\n        ...curr.elements\n          .filter(\n            ({ type, isExternal }) =>\n              ['image', 'video', 'gif'].includes(type) && !isExternal\n          )\n          .map(({ resource }) => resource.id)\n      );\n      return acc;\n    }, [])\n  );\n\n  const { isCurrentResourceUploading, isCurrentResourceProcessing } =\n    useLocalMedia(\n      ({\n        state: { isCurrentResourceUploading, isCurrentResourceProcessing },\n      }) => ({\n        isCurrentResourceUploading,\n        isCurrentResourceProcessing,\n      })\n    );\n\n  // TODO: What about video posters?\n  return useMemo(() => {\n    return Boolean(\n      resourceIds?.some(\n        (resourceId) =>\n          isCurrentResourceUploading(resourceId) ||\n          isCurrentResourceProcessing(resourceId)\n      )\n    );\n  }, [resourceIds, isCurrentResourceUploading, isCurrentResourceProcessing]);\n}\n\nexport default useIsUploadingToStory;\n"
  },
  {
    "path": "packages/story-editor/src/utils/usePerformanceTracking.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport { trackTiming } from '@googleforcreators/tracking';\n\ninterface TraceProps {\n  [key: string]: {\n    label: string;\n    category: string;\n    isReported?: boolean;\n    time?: number;\n  };\n}\n\nconst OBSERVED_EVENTS = ['click', 'pointerdown', 'pointerup'];\nconst OBSERVED_ENTRY_TYPE = 'event';\n\ninterface UsePerformanceTrackingProps {\n  node: Node;\n  eventData: { label: string; category: string };\n  eventType: string;\n}\n\nfunction usePerformanceTracking({\n  node,\n  eventData,\n  eventType = 'click',\n}: UsePerformanceTrackingProps) {\n  const performanceObserverRef = useRef<PerformanceObserver>();\n  const tracesRef = useRef<TraceProps>({});\n  const supportsPerformanceObserving =\n    typeof PerformanceObserver !== 'undefined' &&\n    PerformanceObserver.supportedEntryTypes.includes(OBSERVED_ENTRY_TYPE);\n\n  // Start observing all events if not doing so already.\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  if (!performanceObserverRef.current && supportsPerformanceObserving) {\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    performanceObserverRef.current = new PerformanceObserver((entries) => {\n      for (const entry of entries.getEntries()) {\n        if (\n          OBSERVED_EVENTS.includes(entry.name) &&\n          tracesRef.current[entry.startTime]?.category &&\n          !tracesRef.current[entry.startTime]?.isReported\n        ) {\n          tracesRef.current[entry.startTime].isReported = true;\n          trackTiming(\n            tracesRef.current[entry.startTime].category,\n            entry.duration,\n            tracesRef.current[entry.startTime].label,\n            entry.name\n          );\n        }\n      }\n    });\n    // eslint-disable-next-line react-hooks/refs -- FIXME\n    performanceObserverRef.current.observe({\n      entryTypes: [OBSERVED_ENTRY_TYPE],\n    });\n  }\n\n  useEffect(() => {\n    if (!node || !supportsPerformanceObserving) {\n      return undefined;\n    }\n    const { label = '', category } = eventData;\n    const el = node;\n    const traceEvent = (e: Event) => {\n      tracesRef.current[e.timeStamp] = { category, label, time: e.timeStamp };\n    };\n    el.addEventListener(eventType, traceEvent);\n\n    return () => {\n      el.removeEventListener(eventType, traceEvent);\n    };\n  }, [eventData, node, eventType, supportsPerformanceObserving]);\n}\n\nexport default usePerformanceTracking;\n"
  },
  {
    "path": "packages/story-editor/src/utils/usePreventWindowUnload.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  createContext,\n  useContext,\n} from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { noop } from './noop';\n\ntype EventListener = (event: BeforeUnloadEvent) => void;\ninterface PreventUnloadContextState {\n  listeners: Map<string, EventListener>;\n}\nconst PreventUnloadContext = createContext<PreventUnloadContextState>({\n  listeners: new Map(),\n});\n\n/**\n * This is a helper that to compliant the correct register/unregister system of `beforeunload` event\n */\nconst beforeUnloadListener = (event: BeforeUnloadEvent, id: string) => {\n  event.preventDefault();\n  event.returnValue = id;\n};\n\nfunction usePreventWindowUnload() {\n  const context = useContext(PreventUnloadContext);\n  const setPreventUnload = useCallback(\n    (id: string, value: boolean) => {\n      const listener = context.listeners.get(id);\n      if (value) {\n        // Register beforeunload by scope\n        if (!context.listeners.has(id)) {\n          context.listeners.set(id, (event: BeforeUnloadEvent) =>\n            beforeUnloadListener(event, id)\n          );\n        }\n        if (listener) {\n          window.addEventListener('beforeunload', listener);\n        }\n      } else {\n        // Unregister beforeunload by scope\n        if (listener) {\n          window.removeEventListener('beforeunload', listener);\n        }\n        context.listeners.delete(id);\n      }\n    },\n    [context]\n  );\n  return setPreventUnload;\n}\n\ndeclare const WEB_STORIES_DISABLE_PREVENT: string;\nconst shouldDisablePrevent =\n  typeof WEB_STORIES_DISABLE_PREVENT !== 'undefined' &&\n  WEB_STORIES_DISABLE_PREVENT === 'true';\nexport default shouldDisablePrevent ? () => noop : usePreventWindowUnload;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useRefreshPostEditURL.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\n\n/**\n * Update page URL in browser.\n */\nfunction useRefreshPostEditURL(postId: number, postEditURL: string) {\n  return useCallback(() => {\n    try {\n      const newUrl = new URL(postEditURL);\n      newUrl.hash = window.location.hash;\n      window.history.replaceState(\n        { id: postId },\n        sprintf(\n          /* translators: %d: current story id. */\n          __('Post %d', 'web-stories'),\n          postId\n        ),\n        newUrl.toString()\n      );\n    } catch {\n      // Do nothing for now.\n    }\n  }, [postId, postEditURL]);\n}\n\nexport default useRefreshPostEditURL;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useRovingTabIndex/flatNavigation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Given an element and a sibling direction, returns that media element's next enabled sibling.\n * Media elements are nested 1 level deep.\n *\n * @param {Element} e The element.\n * @param {string} siblingDirection The sibling direction (previousSibling or nextSibling).\n * @return {Element} The sibling.\n */\nexport function getNextEnabledSibling(e, siblingDirection) {\n  let sibling = e[siblingDirection];\n  while (sibling && sibling.disabled) {\n    sibling = sibling[siblingDirection];\n  }\n  return sibling;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/useRovingTabIndex/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { useKeyDownEffect } from '@googleforcreators/design-system';\n/**\n * Internal dependencies\n */\nimport { useConfig } from '../../app/config';\nimport {\n  getAncestorByDepth,\n  getFocusableChild,\n  getNextEnabledElement,\n} from './nestedNavigation';\nimport { getNextEnabledSibling } from './flatNavigation';\n\n/**\n * A point in 2D space.\n *\n * @typedef {Object} Point2D A point in 2D space.\n * @property {number} x The X coordinate.\n * @property {number} y The Y coordinate.\n */\n\n/**\n * Returns the center of a given element.\n *\n * @param {Element} e The element\n * @return {Point2D} The coordinates of the center as defined by\n * getBoundingClientRect's `top` and `left` fields.\n */\nfunction getCenter(e) {\n  const rect = e.getBoundingClientRect();\n  return {\n    x: rect.left + rect.width / 2,\n    y: rect.top + rect.height / 2,\n  };\n}\n\nfunction getNextElement(e, direction, depth) {\n  if (depth > 0) {\n    return getNextEnabledElement(e, direction, depth);\n  }\n  return getNextEnabledSibling(e, direction);\n}\n\n/**\n * Calculates the square of the distance between 2 points.\n *\n * @param {Point2D} p1 The first point.\n * @param {Point2D} p2 The second point.\n * @return {number} The square of the distance between the 2 points.\n */\nfunction getDistanceSq(p1, p2) {\n  return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);\n}\n\n/**\n * Returns either `previousSibling` or `nextSibling` depending on whether the\n * document is RTL and the user pressed the left or right key.\n *\n * @param {boolean} isRTL Whether the document is RTL.\n * @param {string} key The key pressed.\n * @return {string} Either `previousSibling` or `nextSibling`.\n */\nexport function getFocusableElementDirection(isRTL, key) {\n  const isPreviousDirection = isRTL\n    ? key === 'ArrowRight' || key === 'ArrowUp' || key === 'PageUp'\n    : key === 'ArrowLeft' || key === 'ArrowUp' || key === 'PageUp';\n  return isPreviousDirection ? 'previousSibling' : 'nextSibling';\n}\n\n/**\n * Given an element, returns the closest following (or previous) sibling in 2D\n * space that is in a different row.\n *\n * @param {Element} element The element.\n * @param {string} direction The next element direction.\n * @param {number} depth The nesting depth of the focusable element.\n * @return {?Element} The closest sibling in the following (or previous) row.\n */\nfunction getClosestValidElement(element, direction, depth) {\n  const elementCenter = getCenter(element);\n  // Iterate for the next elements and get the closest one in a different row.\n  let closestValidElement = null;\n  let closestValidElementCenter = null;\n  let closestValidElementDistanceSq = null;\n  for (\n    let nextElement = getNextElement(element, direction, depth);\n    nextElement;\n    nextElement = getNextElement(nextElement, direction, depth)\n  ) {\n    const nextElementCenter = getCenter(nextElement);\n    if (Math.floor(nextElementCenter.y) === Math.floor(elementCenter.y)) {\n      // Same row, not useful. Keep looking.\n      continue;\n    }\n    if (\n      closestValidElement &&\n      Math.floor(nextElementCenter.y) > Math.floor(closestValidElementCenter.y)\n    ) {\n      // We're past the next row, stop.\n      break;\n    }\n    const distanceSq = getDistanceSq(elementCenter, nextElementCenter);\n    if (\n      !closestValidElementDistanceSq ||\n      distanceSq < closestValidElementDistanceSq\n    ) {\n      closestValidElementDistanceSq = distanceSq;\n      closestValidElementCenter = nextElementCenter;\n      closestValidElement = nextElement;\n    }\n  }\n  return closestValidElement;\n}\n\n/**\n * Keyboard navigation for focusable elements.\n *\n * @param {Object} ref Ref object.\n * @param {Object} ref.ref Ref object or node.\n * @param {Array} keyEventDeps Array of dependencies.\n * @param {number} depth The nesting depth of the focusable element. By default (0) the focusable elements are siblings.\n */\nexport default function useRovingTabIndex(\n  { ref },\n  keyEventDeps = [],\n  depth = 0\n) {\n  const { isRTL } = useConfig();\n\n  /**\n   * Returns a callback for the keydown event raised by a MediaElement.\n   *\n   * @param {Event} event Keydown event.\n   */\n  const onKeyDown = useCallback(\n    ({ key, target }) => {\n      const element = target;\n      const elementDirection = getFocusableElementDirection(isRTL, key);\n      const switchFocusToElement = (e) => {\n        if (e) {\n          const elToScroll = depth > 0 ? getAncestorByDepth(e, depth) : e;\n          element.tabIndex = -1;\n          e.tabIndex = 0;\n          e.focus();\n          elToScroll.scrollIntoView(\n            /* alignToTop= */ elementDirection === 'previousSibling'\n          );\n        }\n      };\n      if (key === 'ArrowLeft' || key === 'ArrowRight') {\n        const nextElement = getNextElement(element, elementDirection, depth);\n        if (nextElement) {\n          switchFocusToElement(nextElement);\n        }\n      } else if (key === 'ArrowUp' || key === 'ArrowDown') {\n        const closestValidElement = getClosestValidElement(\n          element,\n          elementDirection,\n          depth\n        );\n        if (closestValidElement) {\n          element.tabIndex = -1;\n          closestValidElement.tabIndex = 0;\n          closestValidElement.focus();\n        } else if (key === 'ArrowUp') {\n          // First element.\n          const elToFocus =\n            depth > 0\n              ? getFocusableChild(element, depth)\n              : element.parentNode.firstChild;\n          switchFocusToElement(elToFocus);\n        } else {\n          // Last element.\n          const elToFocus =\n            depth > 0\n              ? getFocusableChild(element, depth, 'lastChild')\n              : element.parentNode.lastChild;\n          switchFocusToElement(elToFocus);\n        }\n      } else if (key === 'Home') {\n        // First element.\n        const elToFocus =\n          depth > 0\n            ? getFocusableChild(element, depth)\n            : element.parentNode.firstChild;\n        switchFocusToElement(elToFocus);\n      } else if (key === 'End') {\n        // Last element.\n        const elToFocus =\n          depth > 0\n            ? getFocusableChild(element, depth, 'lastChild')\n            : element.parentNode.lastChild;\n        switchFocusToElement(elToFocus);\n      } else if (key === 'PageDown' || key === 'PageUp') {\n        let sibling = element;\n        for (\n          let i = 0;\n          getNextElement(sibling, elementDirection, depth) && i < 5;\n          sibling = getNextElement(sibling, elementDirection, depth)\n        ) {\n          i++;\n        }\n        switchFocusToElement(sibling);\n      }\n    },\n    [isRTL, depth]\n  );\n\n  useKeyDownEffect(\n    ref,\n    {\n      key: ['up', 'down', 'left', 'right', 'pageup', 'pagedown', 'home', 'end'],\n    },\n    onKeyDown,\n    [ref, onKeyDown, ...keyEventDeps]\n  );\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/useRovingTabIndex/nestedNavigation.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst SELECTOR = '[tabIndex=\"-1\"]:not(:disabled)';\n\n/**\n * Gets the ancestor element of the active element based on given depth.\n *\n * @param {Object} e Original element to get the parent of.\n * @param {number} depth Nesting depth of the element to see how far up we have to look for the ancestor.\n * @return {Object} Found element.\n */\nexport function getAncestorByDepth(e, depth) {\n  let parentElement,\n    counter = depth;\n\n  while (counter > 0) {\n    if (!parentElement) {\n      parentElement = e.parentElement;\n    } else {\n      parentElement = parentElement?.parentElement;\n    }\n    counter--;\n  }\n  return parentElement;\n}\n\nexport function getFocusableChild(element, depth, childToGet = 'firstChild') {\n  const parentElement = getAncestorByDepth(element, depth);\n  const firstElementParent = parentElement.parentNode[childToGet];\n  // First non-disabled child with tabIndex -1.\n  return firstElementParent.querySelector(SELECTOR);\n}\n\n/**\n * Given an element, nesting depth and a direction, returns that element's next enabled active element.\n *\n * @param {Element} e The element.\n * @param {string} direction The sibling direction (previousSibling or nextSibling).\n * @param {number} depth Nesting depth.\n * @return {Element} The sibling.\n */\nexport function getNextEnabledElement(e, direction, depth) {\n  const parentElement = getAncestorByDepth(e, depth);\n  if (parentElement) {\n    const nextElementParent = parentElement[direction];\n    if (!nextElementParent) {\n      return null;\n    }\n    // Get the first child that is not disabled and has tabindex -1.\n    return nextElementParent.querySelector(SELECTOR);\n  }\n  return null;\n}\n"
  },
  {
    "path": "packages/story-editor/src/utils/useShapeMask.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { MaskTypes } from '@googleforcreators/masks';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../app';\nimport useInsertElement from '../components/canvas/useInsertElement';\nimport objectPick from './objectPick';\n\nconst useShapeMask = (element) => {\n  const { updateElementById } = useStory(({ actions }) => ({\n    updateElementById: actions.updateElementById,\n    combineElements: actions.combineElements,\n  }));\n\n  const insertElement = useInsertElement();\n  const { isMedia } = getDefinitionForType(element.type);\n  const hasShapeMask = isMedia && element?.mask?.type !== MaskTypes.RECTANGLE;\n\n  const removeShapeMask = useCallback(() => {\n    if (!element) {\n      return;\n    }\n\n    const SHAPE_PROPS = ['x', 'y', 'width', 'height', 'scale', 'rotationAngle'];\n    const shapeProps = objectPick(element, SHAPE_PROPS);\n    insertElement('shape', {\n      ...shapeProps,\n      mask: {\n        type: element.mask.type,\n      },\n    });\n\n    updateElementById({\n      elementId: element.id,\n      properties: { mask: { type: MaskTypes.RECTANGLE } },\n    });\n  }, [element, insertElement, updateElementById]);\n\n  return {\n    hasShapeMask,\n    removeShapeMask,\n  };\n};\n\nexport default useShapeMask;\n"
  },
  {
    "path": "packages/story-editor/src/utils/useShapeMaskElements.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useState, useEffect } from '@googleforcreators/react';\nimport { getDefinitionForType } from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { useStory } from '../app';\n\nconst useShapeMaskElements = () => {\n  const { selectedElements, combineElements } = useStory(\n    ({ state, actions }) => ({\n      selectedElements: state.selectedElements,\n      combineElements: actions.combineElements,\n    })\n  );\n\n  const [shapeMaskElements, setShapeMaskElements] = useState({});\n  const [canMergeIntoMask, setCanMergeIntoMask] = useState(false);\n\n  /**\n   * Get shape and image from selected elements.\n   */\n  useEffect(() => {\n    if (selectedElements?.length > 2) {\n      setCanMergeIntoMask(false);\n      return;\n    }\n\n    let target, shape;\n\n    selectedElements.forEach((element) => {\n      const { isMedia } = getDefinitionForType(element.type);\n      element.type === 'shape' && (shape = element);\n      isMedia && (target = element);\n    });\n\n    if (shape && target) {\n      setCanMergeIntoMask(true);\n      setShapeMaskElements({ shape, target });\n      return;\n    }\n\n    setCanMergeIntoMask(false);\n  }, [selectedElements]);\n\n  /**\n   * Apply shape mask to element.\n   */\n  const mergeIntoMask = () => {\n    const { target, shape } = shapeMaskElements;\n\n    if (target && shape) {\n      combineElements({\n        firstElement: target,\n        secondId: shape.id,\n      });\n    }\n  };\n\n  return {\n    canMergeIntoMask,\n    mergeIntoMask,\n  };\n};\n\nexport default useShapeMaskElements;\n"
  },
  {
    "path": "packages/story-editor/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../dom\" },\n    { \"path\": \"../design-system\" },\n    { \"path\": \"../elements\" },\n    { \"path\": \"../element-library\" },\n    { \"path\": \"../fonts\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../masks\" },\n    { \"path\": \"../migration\" },\n    { \"path\": \"../output\" },\n    { \"path\": \"../patterns\" },\n    { \"path\": \"../rich-text\" },\n    { \"path\": \"../react\" },\n    { \"path\": \"../text-sets\" },\n    { \"path\": \"../templates\" },\n    { \"path\": \"../tracking\" }\n  ],\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\n    \"src/**/test/**/*.ts\",\n    \"src/**/test/**/*.tsx\",\n    \"src/app/api\",\n    \"src/app/canvas\",\n    \"src/app/config\",\n    \"src/app/currentUser\",\n    \"src/app/helpCenter\",\n    \"src/components/library/paneIds.ts\",\n    \"src/components/sidebar/constants.ts\",\n    \"src/app/highlights/*.ts\",\n    \"src/app/highlights/*.tsx\",\n    \"src/app/history\",\n    \"src/app/font\",\n    \"src/app/layout\",\n    \"src/app/uploader\",\n    \"src/app/media/*.ts\",\n    \"src/app/media/media3p/*.ts\",\n    \"src/app/media/uploadQueue/*.ts\",\n    \"src/app/media/media3p/*.tsx\",\n    \"src/app/media/utils/**/*.ts\",\n    \"src/app/pageCanvas\",\n    \"src/app/pageDataUrls\",\n    \"src/app/story\",\n    \"src/app/taxonomy\",\n    \"src/components/hideOnError.tsx\",\n    \"src/components/library/panes/text/textPresets.ts\",\n    \"src/components/canvas/*.ts\",\n    \"src/components/canvas/utils/*.ts\",\n    \"src/components/floatingMenu/elements/shared/*.ts\",\n    \"src/components/footer/carousel/**/*.ts\",\n    \"src/components/footer/carousel/**/*.tsx\",\n    \"src/components/keyboardShortcutsMenu/keyboardShortcutsMenuContext\",\n    \"src/constants/*\",\n    \"src/utils/**/*.ts\",\n    \"src/utils/**/*.tsx\",\n    \"src/types/*\",\n    \"src/typings/*\"\n  ]\n}\n"
  },
  {
    "path": "packages/templates/.npmignore",
    "content": "scripts\nsrc\n"
  },
  {
    "path": "packages/templates/README.md",
    "content": "# Templates\n\nThis package contains the templates used by the dashboard and the editor (as part of page templates).\n\n## Template Creation\n\nSee [External Template Creation](../../docs/external-template-creation.md).\n\n## Generating images for templates\n\nRun `npm run workflow:render-template-posters` to generate and save each template page as an image in the `build/template-posters/` folder.\nThen move and commit the images to the [GoogleForCreators/wp.stories.google](https://github.com/GoogleForCreators/wp.stories.google) repo under `public/static/main/images/templates/<template-name>/posters`.\n\nYou will want to run the resulting images through [ImageOptim](https://imageoptim.com/howto.html) locally to optimize them before adding them to the repo.\n"
  },
  {
    "path": "packages/templates/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/templates\",\n  \"description\": \"A set of existing Web Stories templates for use in the editor\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/templates/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/templates\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/migration\": \"*\",\n    \"@googleforcreators/tracking\": \"*\"\n  },\n  \"devDependencies\": {\n    \"@googleforcreators/date\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/stickers\": \"*\",\n    \"puppeteer\": \"*\"\n  },\n  \"scripts\": {\n    \"render-template-posters\": \"node ./scripts/cli.js\"\n  }\n}\n"
  },
  {
    "path": "packages/templates/scripts/cli.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint-disable no-await-in-loop, no-console */\n\n/**\n * External dependencies\n */\nimport fs from 'fs';\nimport puppeteer from 'puppeteer';\n\nconst screenshotsPath = `build/template-posters/`;\n\nfs.mkdirSync(screenshotsPath, { recursive: true });\n\n(async () => {\n  const browser = await puppeteer.launch({\n    defaultViewport: null,\n    headless: true,\n    args: [`--window-size=1600,854`],\n  });\n  const page = await browser.newPage();\n  await page.setViewport({\n    width: 1600,\n    height: 854,\n    deviceScaleFactor: 2,\n  });\n  await page.goto(\n    'http://localhost:8899/wp-admin/edit.php?post_type=web-story&page=stories-dashboard#/templates-gallery'\n  );\n  await page.type('#user_login', 'admin');\n  await page.type('#user_pass', 'password');\n  await page.click('#wp-submit');\n  await page.waitForNavigation({ waitUntil: 'networkidle2' });\n\n  await page.waitForSelector('[aria-label^=\"Explore Templates\"]');\n  await page.click('[aria-label^=\"Explore Templates\"]');\n\n  // Wait for templates to be rendered\n  await page.waitForSelector('div.templateGridItem');\n\n  // total templates to generate screenshots from\n  const templateCount = await page.evaluate(() => {\n    return document.querySelectorAll('.templateGridItem').length;\n  });\n\n  // Now let's go through each template\n  for (\n    let currentTemplate = 1;\n    currentTemplate <= templateCount;\n    currentTemplate++\n  ) {\n    // Get the template name to use as build directory\n    const templateName = await page.evaluate((gridItemId) => {\n      return document\n        .querySelector(\n          `div#template-grid-item-${gridItemId} div[data-testid=\"card-action-container\"]`\n        )\n        .getAttribute('data-template-slug');\n    }, currentTemplate);\n    // Prep a directory for the template screenshots\n    fs.mkdirSync(`${screenshotsPath}${templateName}`, { recursive: true });\n\n    console.log(`Getting screenshots for ${templateName}`);\n\n    // Use the template, this will open up the editor\n    await page.click(`div#template-grid-item-${currentTemplate} button`);\n\n    // Load the template in the editor to get story id to render preview\n    await page.waitForNavigation({ waitUntil: 'networkidle2' });\n    const editorUrl = await page.url(); // 'http://localhost:8899/wp-admin/post.php?post=1163&action=edit#page=%252217fa9c85-89c7-47d0-a7a8-29f6ef56e161%2522'\n    const storyId = editorUrl.split('post=')[1].split('&')[0];\n\n    const previewUrl = `http://localhost:8899/?post_type=web-story&p=${storyId}&preview=true`;\n\n    // Need to click preview for the story to save and be loadable in a second window.\n    // This is because the \"Save\" button is disabled at this point.\n    // Also not using the tab opened by the preview button and instead assembling `pagePreview`\n    // ourselves so that we can emulate `prefers-reduced-motion` and don't have to deal with\n    // the story dev tools.\n    await page.waitForSelector('aria/Preview');\n    await page.click('aria/Preview');\n\n    // the viewport height decides the size of the preview, we're aiming to maintain our recommended 853px height, we get the closest to this by setting the viewport height to 1145\n    const pagePreview = await browser.newPage();\n    await pagePreview.setViewport({\n      width: 640,\n      height: 854, // 853 is a breakpoint and will shrink the preview to height of 630px\n      deviceScaleFactor: 1,\n    });\n    // set prefers-reduced-motion to get story without animations so screenshots are complete page views\n    await pagePreview.emulateMediaFeatures([\n      { name: 'prefers-reduced-motion', value: 'reduce' },\n    ]);\n    await pagePreview.evaluate(\n      () => matchMedia('(prefers-reduced-motion: reduce)').matches\n    );\n\n    await pagePreview.goto(previewUrl);\n    // Ensure that the page's ready before looping\n    await pagePreview.waitForSelector('aria/Next page');\n\n    const totalPages = await pagePreview.evaluate(() => {\n      return document.querySelectorAll('amp-story-page').length;\n    });\n\n    for (let currentPage = 1; currentPage <= totalPages; currentPage++) {\n      const templatePageSafeArea = await pagePreview.$(\n        `amp-story-page:nth-child(${currentPage}) .page-safe-area`\n      );\n      // Speed up animations, this in tandem with emulating reduced motion will account for fade in content\n      await pagePreview._client.send('Animation.setPlaybackRate', {\n        playbackRate: 2,\n      });\n\n      await templatePageSafeArea.screenshot({\n        path: `${screenshotsPath}${templateName}/${currentPage}.png`,\n      });\n\n      await templatePageSafeArea.screenshot({\n        path: `${screenshotsPath}${templateName}/${currentPage}.webp`,\n      });\n\n      if (currentPage < totalPages) {\n        await pagePreview.click('aria/Next page');\n      }\n    }\n\n    // Close the preview\n    await pagePreview.close();\n\n    // Use the original browser page to go back to the template gallery for the next template.\n    await page.goto(\n      'http://localhost:8899/wp-admin/edit.php?post_type=web-story&page=stories-dashboard#/templates-gallery'\n    );\n  }\n\n  await browser.close();\n  console.log(\n    `\\nTemplate images generated in ${screenshotsPath}, please move and commit them to the static-site branch`\n  );\n})();\n\n/* eslint-enable */\n"
  },
  {
    "path": "packages/templates/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// @todo Enable two quiz templates when the interactivity is added to the web story editor.\n// Assets and Stickers for these templates have already been added, to enable these template add them to\n// the TEMPLATE_NAMES array.\n// Templates need to be added:\n//   1. 'beauty-quiz',\n//   2. 'sports-quiz',\n// See https://github.com/googleforcreators/web-stories-wp/issues/8725 for more details.\n\nexport const TEMPLATE_NAMES = [\n  'fresh-and-bright',\n  'food-and-stuff',\n  'doers-get-more-done',\n  'weekly-entertainment',\n  'fashion-on-the-go',\n  'no-days-off',\n  'experience-thailand',\n  'sleep',\n  'baking-bread-guide',\n  'sangria-artichoke',\n  'ways-to-eat-avocado',\n  'kitchen-stories',\n  'album-releases',\n  'almodos-films',\n  'pizzas-in-nyc',\n  '12-hours-in-barcelona',\n  'ultimate-comparison',\n  'fitness-apps-ranked',\n  'street-style-on-the-go',\n  'plant-based-dyes',\n  'indoor-garden-oasis',\n  'belly-fat-workout',\n  'tv-show-recap',\n  'pride-month-watchlist',\n  'honeymooning-in-italy',\n  'ace-hotel-kyoto-review',\n  'how-video-calls-saved-the-day',\n  'laptop-buying-guide',\n  'diy-home-office',\n  'kitchen-makeover',\n  'self-care-guide',\n  'rock-music-festival',\n  'celebrity-q-and-a',\n  'los-angeles-city-guide',\n  'hawaii-travel-packing-list',\n  'google-music-studio-tour',\n  'how-contact-tracing-works',\n  'summer-fashion-collection',\n  'buying-art-on-the-internet',\n  'house-hunting',\n  'new-york-party-round-up',\n  'a-day-in-the-life',\n  'elegant-travel-itinerary',\n  'modernist-travel-guide',\n  'simple-tech-tutorial',\n  'magazine-article',\n  'fashion-inspiration',\n  'skin-care-at-home',\n  'art-books-gift-guide',\n  'vintage-chairs-buying-guide',\n  'celebrity-life-story',\n  'series-best-of',\n  'summer-adventure-guide',\n  'one-day-city-itinerary',\n  'technology-advice',\n  'sustainability-tips',\n  'an-artists-legacy',\n  'tips-for-throwing-an-outdoor-luau',\n  'all-about-cars',\n];\n"
  },
  {
    "path": "packages/templates/src/getMetaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { TEMPLATE_NAMES } from './constants';\nimport type { MetaData } from './types';\n\ntype Data = {\n  default: MetaData;\n};\n\nexport function getTemplateMetaData(): Promise<MetaData[]> {\n  return Promise.all(\n    TEMPLATE_NAMES.map((title) =>\n      import(\n        /* webpackChunkName: \"chunk-web-stories-template-[index]-metaData\" */ `./raw/${title}/metaData.ts`\n      ).then((data: Data) => data.default)\n    )\n  );\n}\n"
  },
  {
    "path": "packages/templates/src/getTemplates.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getTimeTracker } from '@googleforcreators/tracking';\nimport { DATA_VERSION, migrate } from '@googleforcreators/migration';\nimport type {\n  MediaElement,\n  Element,\n  SequenceMediaElement,\n} from '@googleforcreators/elements';\n\n/**\n * Internal dependencies\n */\nimport { TEMPLATE_NAMES } from './constants';\nimport type { RawTemplate, Template } from './types';\n\ntype Data = {\n  default: RawTemplate;\n};\n\nasync function loadTemplate(\n  title: string,\n  imageBaseUrl: string\n): Promise<Template> {\n  const data: Data = (await import(\n    /* webpackChunkName: \"chunk-web-stories-template-[index]\" */ `./raw/${title}/index.ts`\n  )) as Data;\n\n  function isMediaElement(e: Element): e is MediaElement {\n    return 'resource' in e;\n  }\n\n  function isSequenceMediaElement(e: MediaElement): e is SequenceMediaElement {\n    return 'poster' in e.resource;\n  }\n\n  const template = {\n    ...data.default,\n    pages: (data.default.pages || []).map((page) => ({\n      ...page,\n      elements: page.elements?.map((elem) => {\n        if (isMediaElement(elem) && elem.resource) {\n          if ('sizes' in elem.resource && elem.resource.sizes) {\n            elem.resource.sizes = {};\n          }\n          if (elem.resource.src) {\n            // imageBaseUrl (cdnURL) will always have a trailing slash,\n            // so make sure to avoid double slashes when replacing.\n            elem.resource.src = elem.resource.src.replace(\n              '__WEB_STORIES_TEMPLATE_BASE_URL__/',\n              imageBaseUrl\n            );\n          }\n\n          if (isSequenceMediaElement(elem) && elem.resource.poster) {\n            // imageBaseUrl (cdnURL) will always have a trailing slash,\n            // so make sure to avoid double slashes when replacing.\n            elem.resource.poster = elem.resource.poster.replace(\n              '__WEB_STORIES_TEMPLATE_BASE_URL__/',\n              imageBaseUrl\n            );\n          }\n        }\n        return elem;\n      }),\n    })),\n\n    postersByPage: data.default.pages.map((_, i) => {\n      const srcPath = `${imageBaseUrl}images/templates/${\n        data.default.slug\n      }/posters/${i + 1}`;\n      return {\n        webp: `${srcPath}.webp`,\n        png: `${srcPath}.png`,\n        type: data.default.pages[i].pageTemplateType,\n      };\n    }),\n  };\n\n  return {\n    ...(migrate(template, template.version) as unknown as Template),\n    version: DATA_VERSION,\n  } as Template;\n}\n\nasync function getTemplates(imageBaseUrl: string) {\n  const trackTiming = getTimeTracker('load_templates');\n\n  const templates = await Promise.all(\n    TEMPLATE_NAMES.map((title) => {\n      return loadTemplate(title, imageBaseUrl);\n    })\n  );\n\n  trackTiming();\n\n  return templates;\n}\n\nexport default getTemplates;\n"
  },
  {
    "path": "packages/templates/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport memoize from './utils/memoize';\nimport getTemplates from './getTemplates';\nimport type { Template } from './types';\n\nconst memoizedGetTemplates = memoize(getTemplates);\n\nexport async function getAllTemplates({\n  cdnURL,\n}: {\n  cdnURL: string;\n}): Promise<Template[]> {\n  const templates = await memoizedGetTemplates(cdnURL);\n\n  const globalConfig = {\n    createdBy: 'Google',\n    modified: '2020-04-21',\n  };\n\n  return templates.map((template, index) => {\n    return {\n      id: index + 1,\n      ...globalConfig,\n      ...template,\n    };\n  });\n}\n\nexport { getTemplateMetaData } from './getMetaData';\n\nexport * from './types';\n"
  },
  {
    "path": "packages/templates/src/raw/12-hours-in-barcelona/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\n// For some reason, the inferred TypeScript type is too narrow here and we have to use\n// file declaration instead of importing directly from `template.json`.\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/12-hours-in-barcelona/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: '12-hours-in-barcelona',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('12 Hours in Barcelona', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Magazine', 'template keyword', 'web-stories'),\n    _x('Destination', 'template keyword', 'web-stories'),\n    _x('Outdoor', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Winter Blue', 'color', 'web-stories'),\n      color: '#a4deff',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Blackcurrant Blue', 'color', 'web-stories'),\n      color: '#160236',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Sunset Yellow', 'color', 'web-stories'),\n      color: '#ffc700',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    '12 Hours in Barcelona’s classic magazine aesthetic will let you create engaging travel itineraries, bucket lists, and visual articles that will enthuse and motivate your audience.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/12-hours-in-barcelona/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/12-hours-in-barcelona/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 476,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"aa2fbbaa-670c-4f87-8349-954464b36b62\",\n          \"scale\": 114,\n          \"focalX\": 50,\n          \"focalY\": 51.64473684210527,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-11T02:48:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page1_img1.jpg\",\n            \"width\": 330,\n            \"height\": 476,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person surfing with high-rise building in background\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a0a1ab\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 145, \"g\": 143, \"b\": 164 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 72, \"g\": 71, \"b\": 84, \"a\": 0 },\n                \"position\": 0.49\n              }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"width\": 69,\n          \"height\": 103,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cfd2781a-77cb-470c-ad0e-3712913f04d0\",\n          \"x\": 0,\n          \"y\": 43,\n          \"type\": \"shape\",\n          \"groupId\": \"17166fdb-7768-407e-a9d4-8ae688ad252c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 140,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 35,\n          \"y\": 0,\n          \"width\": 186,\n          \"height\": 187,\n          \"id\": \"6952d29c-8ad5-410f-9982-eb8ca2f828a1\",\n          \"type\": \"text\",\n          \"groupId\": \"17166fdb-7768-407e-a9d4-8ae688ad252c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Hours</span><span style=\\\"font-weight: 700\\\"> </span><span style=\\\"font-weight: 700; color: #160236\\\">in</span>\\n<span style=\\\"font-weight: 700; color: #160236\\\">Barcelona</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 139,\n          \"id\": \"c153d6f9-3904-4c8a-bec6-2a7e84e0d7d9\",\n          \"x\": 48,\n          \"y\": 152,\n          \"type\": \"text\",\n          \"groupId\": \"17166fdb-7768-407e-a9d4-8ae688ad252c\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #080439; letter-spacing: 0.01em; text-transform: uppercase\\\">By </span><span style=\\\"font-weight: 700; color: #080439; letter-spacing: 0.01em; text-transform: uppercase\\\">Marco Christiansen</span><span style=\\\"color: #080439; letter-spacing: 0.01em; text-transform: uppercase\\\"> | Jun 21, 2021</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 601,\n          \"width\": 316,\n          \"height\": 17,\n          \"id\": \"9e6218c8-7223-4069-add8-ea3367dc9466\",\n          \"type\": \"text\",\n          \"groupId\": \"68836b5c-a442-4407-a938-a790f564d9de\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"width\": 14,\n          \"height\": 268,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"baf1f174-c8e9-43cc-be31-ddcd62be8207\",\n          \"x\": 398,\n          \"y\": 405,\n          \"type\": \"shape\",\n          \"groupId\": \"68836b5c-a442-4407-a938-a790f564d9de\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9c17b213-94a8-4da4-bb6f-20018ea8787d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"5b062014-b126-44a0-920b-5378359d60b9\"\n      },\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"17166fdb-7768-407e-a9d4-8ae688ad252c\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"68836b5c-a442-4407-a938-a790f564d9de\": {\n          \"name\": \"Footer\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 47.79829545454545,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page2_img1.jpg\",\n            \"width\": 330,\n            \"height\": 186,\n            \"id\": 0,\n            \"alt\": \"Man in black formal suit wearing eyeglasses\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#4d4d47\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 186,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"dc283215-6e21-4d7c-a245-994aba9ca38d\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 8, \"g\": 4, \"b\": 57, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 8, \"g\": 4, \"b\": 57 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"width\": 16,\n          \"height\": 126,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0b51116c-4383-4d84-b102-30665a0622f8\",\n          \"x\": 0,\n          \"y\": 0,\n          \"type\": \"shape\",\n          \"groupId\": \"e3454734-01f7-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">The writer</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 11,\n          \"width\": 186,\n          \"height\": 18,\n          \"id\": \"8f13b559-fa80-47ea-af5e-b701b4acf146\",\n          \"type\": \"text\",\n          \"groupId\": \"e3454734-01f7-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Marco</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">Christiansen</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 98,\n          \"id\": \"6ef1a8e1-da7b-4c8d-9240-9e6359bc1086\",\n          \"x\": 48,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"e3454734-01f7-11ed-b939-0242ac120002\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page2_route_1.png\",\n            \"width\": 330,\n            \"height\": 205,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"x\": 0,\n          \"y\": 265,\n          \"width\": 412,\n          \"height\": 256,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"23d2af7b-5d1d-4af3-be12-f1c6bb18524e\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 52,\n          \"y\": 455,\n          \"width\": 22,\n          \"height\": 27,\n          \"sticker\": { \"type\": \"travelList\" },\n          \"id\": \"02334556-1b8f-48e9-a9a8-6b6b96eb3e39\",\n          \"type\": \"sticker\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Author of “Barcelona</span>\\n<span style=\\\"color: #fff\\\">by Day and Night”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 275,\n          \"height\": 40,\n          \"id\": \"e09010ea-b97f-4d11-83e5-4c2901fc427d\",\n          \"x\": 89,\n          \"y\": 450,\n          \"type\": \"text\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 22,\n          \"height\": 27,\n          \"sticker\": { \"type\": \"travelList\" },\n          \"id\": \"363c5121-5877-454b-b831-29468b73d86e\",\n          \"x\": 52,\n          \"y\": 520,\n          \"type\": \"sticker\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Editor at Large for\\nConde Nast Traveler</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 275,\n          \"height\": 40,\n          \"id\": \"502d7135-c336-4d93-af50-88e37be12ae5\",\n          \"x\": 89,\n          \"y\": 515,\n          \"type\": \"text\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 22,\n          \"height\": 27,\n          \"sticker\": { \"type\": \"travelList\" },\n          \"id\": \"902d99ed-9236-41f5-a929-8c9d272ef7ee\",\n          \"x\": 52,\n          \"y\": 585,\n          \"type\": \"sticker\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Writer for NY Times\\nMagazine</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 275,\n          \"height\": 40,\n          \"id\": \"1f9a47ce-2654-4f29-9e45-cb8c4b1105a7\",\n          \"x\": 89,\n          \"y\": 580,\n          \"type\": \"text\",\n          \"groupId\": \"f469962e-01f6-11ed-b939-0242ac120002\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b9bade29-6db1-4832-b35f-4aea0121e143\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"23d2af7b-5d1d-4af3-be12-f1c6bb18524e\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"16311f22-ad92-4e20-b9e9-374284b8d4ce\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"02334556-1b8f-48e9-a9a8-6b6b96eb3e39\"],\n          \"duration\": 1600,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"7308fee9-5e89-4e9e-a079-180712eb7359\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"363c5121-5877-454b-b831-29468b73d86e\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"b4d688e0-13f5-4c6b-94c7-b4a9bff96234\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"902d99ed-9236-41f5-a929-8c9d272ef7ee\"],\n          \"duration\": 1600,\n          \"delay\": 900\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8f204b6d-38a1-4e2f-afba-8ea0d5b42c93\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"34d2009a-af78-44f3-9a2c-90351a0d93d8\"\n      },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"e3454734-01f7-11ed-b939-0242ac120002\": {\n          \"isCollapsed\": true,\n          \"isLocked\": false,\n          \"name\": \"Header\"\n        },\n        \"f469962e-01f6-11ed-b939-0242ac120002\": {\n          \"isCollapsed\": true,\n          \"isLocked\": false,\n          \"name\": \"List\"\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 412,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"f20dcbfa-0f72-479b-b2fe-5c3e299d1ec4\",\n          \"scale\": 100,\n          \"focalX\": 43.56250000000001,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page3_img1.jpg\",\n            \"width\": 330,\n            \"height\": 412,\n            \"id\": 0,\n            \"alt\": \"Aerial view of city\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c5ccd7\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 220,\n          \"height\": 25,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5cff9137-0b76-4f14-b6f1-3eebff20e48d\",\n          \"x\": 47,\n          \"y\": 40,\n          \"groupId\": \"985834ab-2f0c-40a9-8bdb-57b5d06eb24c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #080439\\\">Live the Journey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 37,\n          \"type\": \"text\",\n          \"id\": \"8810ec7c-291f-4dea-bd40-565bb3970bd5\",\n          \"x\": 52,\n          \"y\": 22,\n          \"groupId\": \"985834ab-2f0c-40a9-8bdb-57b5d06eb24c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 118,\n          \"width\": 24,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"yellowLocationPin\" },\n          \"id\": \"308e8e8f-09e8-48f0-8a5a-bb0e86c6ee07\",\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #080439\\\">Churches and</span>\\n<span style=\\\"color: #080439\\\">monasteries</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 267,\n          \"height\": 39,\n          \"type\": \"text\",\n          \"id\": \"63525e80-0249-4709-9ffd-217f5d7544da\",\n          \"x\": 85,\n          \"y\": 117,\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 24,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"yellowLocationPin\" },\n          \"id\": \"c4e0bb0e-876d-4539-90e1-0f1fe56ecc12\",\n          \"x\": 48,\n          \"y\": 182,\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #080439\\\">Most famous</span>\\n<span style=\\\"color: #080439\\\">shoping street</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 267,\n          \"height\": 39,\n          \"type\": \"text\",\n          \"id\": \"0b9b543c-0832-4994-bf6b-f5dcfe73bb49\",\n          \"x\": 86,\n          \"y\": 181,\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 24,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"yellowLocationPin\" },\n          \"id\": \"db397abd-79d6-4df1-8900-91499c45dc96\",\n          \"x\": 46,\n          \"y\": 252,\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #080439\\\">Authentic culinary</span>\\n<span style=\\\"color: #080439\\\">paradise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 267,\n          \"height\": 40,\n          \"type\": \"text\",\n          \"id\": \"60ed9ffe-24ef-488c-bd94-a96a4e88da3e\",\n          \"x\": 85,\n          \"y\": 247,\n          \"groupId\": \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page3_route_1.png\",\n            \"width\": 330,\n            \"height\": 167,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 0.5,\n          \"y\": 288,\n          \"width\": 411,\n          \"height\": 208,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"51c8c656-480f-484d-9118-08f868e7a97e\",\n          \"groupId\": \"94970fa5-54a1-4dfb-90d1-511804cd559e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 252,\n          \"y\": 378,\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"7eb4ea8c-36c4-4a83-84bd-35e06ef1fd00\",\n          \"groupId\": \"94970fa5-54a1-4dfb-90d1-511804cd559e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Start</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 252,\n          \"y\": 382,\n          \"width\": 80,\n          \"height\": 18,\n          \"id\": \"42a0aee5-4867-4bdd-9fcc-992d75a14eab\",\n          \"groupId\": \"94970fa5-54a1-4dfb-90d1-511804cd559e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 24,\n            \"vertical\": 10\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">A special walk through medieval streets and alleyways of the Gothic and Barceloneta neighborhoods.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 108,\n          \"type\": \"text\",\n          \"id\": \"c6de292a-421d-472b-9475-abfe7ead8219\",\n          \"x\": 48,\n          \"y\": 510\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"68b3e22e-344e-4351-86d6-c4f0372499b0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7eb4ea8c-36c4-4a83-84bd-35e06ef1fd00\"],\n          \"duration\": 1600,\n          \"delay\": 1600\n        },\n        {\n          \"id\": \"fbecb5f0-1771-4f17-9c23-3182e2c2cc85\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"42a0aee5-4867-4bdd-9fcc-992d75a14eab\"],\n          \"duration\": 1600,\n          \"delay\": 1600\n        },\n        {\n          \"id\": \"d328453c-96a0-494d-8d16-50387bc1e1e0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5cff9137-0b76-4f14-b6f1-3eebff20e48d\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"9c9c7ab5-6665-4773-822e-0d78e972e686\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"308e8e8f-09e8-48f0-8a5a-bb0e86c6ee07\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"08d0b02d-34ba-4a7c-88e1-d157ca27d4ef\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"c4e0bb0e-876d-4539-90e1-0f1fe56ecc12\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"f89429b7-5526-410f-98ce-77f1678a5081\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"db397abd-79d6-4df1-8900-91499c45dc96\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"b720dea9-967e-4a29-9af3-db719a5ea849\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"51c8c656-480f-484d-9118-08f868e7a97e\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0f83ba39-4463-47f2-b1dd-861be6cd77f7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b821d675-08df-4ea7-98d4-4e0fb4c088c7\"\n      },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"985834ab-2f0c-40a9-8bdb-57b5d06eb24c\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"001c8fc2-79cf-45f5-a4a3-a91efa7b9273\": {\n          \"name\": \"List\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"94970fa5-54a1-4dfb-90d1-511804cd559e\": {\n          \"name\": \"Start\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 106,\n          \"focalX\": 48.04117387998859,\n          \"focalY\": 49.88362710927139,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page4_img1.jpg\",\n            \"width\": 330,\n            \"height\": 412,\n            \"id\": 0,\n            \"alt\": \"Two gray and brown concrete bricks\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#835a34\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 412,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"68c038b1-c40b-4f77-a70a-eeb5e98ca99f\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.34 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Morning</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"7e996619-8518-4bd0-b521-9cdb4f318efe\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"4eb0f819-8cd8-44b7-891b-d473a0e9b3de\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Park</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">Güell</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 96,\n          \"id\": \"c6792456-6509-4487-a53c-b7c83b336044\",\n          \"x\": 48,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"4eb0f819-8cd8-44b7-891b-d473a0e9b3de\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page4_route_1.png\",\n            \"width\": 330,\n            \"height\": 32,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"x\": 0,\n          \"y\": 285,\n          \"width\": 412,\n          \"height\": 40,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2c7e17db-5838-4e8d-9727-37a08c00bcd4\",\n          \"type\": \"image\",\n          \"groupId\": \"82369769-f716-44e0-8ebf-cf5b82382418\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"f706b393-4a67-49fa-b973-b59cc793c3e6\",\n          \"x\": 92,\n          \"y\": 259,\n          \"groupId\": \"82369769-f716-44e0-8ebf-cf5b82382418\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">8:45 AM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 76,\n          \"height\": 18,\n          \"id\": \"b068cae7-1d0f-4650-a7ed-52e09deae130\",\n          \"x\": 93,\n          \"y\": 262,\n          \"groupId\": \"82369769-f716-44e0-8ebf-cf5b82382418\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 24,\n            \"vertical\": 23\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">Why Park Güell? It’s a public park system composed of gardens and architectural elements located on Carmel Hill. It's a must see for any traveler in Barcelona.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 157,\n          \"id\": \"bed3654d-9924-49df-ae65-2335fd4c897e\",\n          \"x\": 48,\n          \"y\": 462,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6b4ad9fa-0fa5-447d-bbcf-99a47f1330a9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b068cae7-1d0f-4650-a7ed-52e09deae130\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"886081f5-5594-46aa-a625-a034ce5e462a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f706b393-4a67-49fa-b973-b59cc793c3e6\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"983899df-234f-4ec2-a6e2-a9df4d1b71f9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2c7e17db-5838-4e8d-9727-37a08c00bcd4\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"targets\": [\"7e996619-8518-4bd0-b521-9cdb4f318efe\"],\n          \"id\": \"c1a55d54-54b5-4f5d-87a8-deeb2f696d48\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"77c8f37e-554b-4f77-af91-9bfd1ed1a483\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1da06749-7c4f-4f85-9197-4e207659e74b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4eb0f819-8cd8-44b7-891b-d473a0e9b3de\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"82369769-f716-44e0-8ebf-cf5b82382418\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1da06749-7c4f-4f85-9197-4e207659e74b\",\n          \"scale\": 118,\n          \"focalX\": 59.419675556708576,\n          \"focalY\": 52.3329416727721,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page5_img1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Brown concrete statue under blue sky during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#86b1d6\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.36 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Morning</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"1c683d7a-39cb-485b-b5a4-e8e39096c8e7\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"bb4c28dd-988d-44a0-8af8-430ba633138d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Gaudí</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">House</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">Museum</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 138,\n          \"id\": \"f3d132ca-c5ad-412d-ad8e-320a5e8b4059\",\n          \"x\": 47,\n          \"y\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"bb4c28dd-988d-44a0-8af8-430ba633138d\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-27T11:03:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page5_route_1.png\",\n            \"width\": 330,\n            \"height\": 216,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 222,\n          \"width\": 412,\n          \"height\": 270,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"052d183b-2d21-4ed4-8635-2e2e8835eb77\",\n          \"groupId\": \"763c6552-fbad-4a8b-bfa0-d078ea11523f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"9843703b-6315-4916-8d27-a871f5f63a1d\",\n          \"x\": 258,\n          \"y\": 324,\n          \"groupId\": \"763c6552-fbad-4a8b-bfa0-d078ea11523f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">11:30 AM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 18,\n          \"id\": \"937f7e2e-6a1e-484b-895e-c4e6f4b4817c\",\n          \"x\": 259,\n          \"y\": 331,\n          \"groupId\": \"763c6552-fbad-4a8b-bfa0-d078ea11523f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 19,\n            \"vertical\": 20\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">A historic home that houses all the personal treasures of Antoni Gaudi. You won't see them anywhere else.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 113,\n          \"id\": \"0407e214-bae3-487f-b3b8-3e90562ecf18\",\n          \"x\": 48,\n          \"y\": 505,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a5a1e8de-dba8-4f03-8ced-a22593e7d1ee\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"937f7e2e-6a1e-484b-895e-c4e6f4b4817c\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"adb973d4-6f66-47af-af3a-7378b839387e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"052d183b-2d21-4ed4-8635-2e2e8835eb77\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"de62c713-473e-4a1e-a272-0785b3c02661\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9843703b-6315-4916-8d27-a871f5f63a1d\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"291f361b-87c7-4337-8d67-6f7005a4a685\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"2c3f3035-aea0-460c-aba0-7ab8d2521135\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bb4c28dd-988d-44a0-8af8-430ba633138d\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"763c6552-fbad-4a8b-bfa0-d078ea11523f\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -46,\n          \"y\": 68,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"2c3f3035-aea0-460c-aba0-7ab8d2521135\",\n          \"scale\": 130,\n          \"focalX\": 48.2671024880688,\n          \"focalY\": 40.499666805551854,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page6_img1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Brown concrete building during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#28211d\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"alpha\": 0.4\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Afternoon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"30e73da3-a0de-4790-9db1-549450bd1e3a\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"8507db95-896c-4456-8be2-f867dd867528\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Art\\nNouveau\\nFor Days</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 138,\n          \"id\": \"2eb9913f-adb8-49c6-b6cd-f68efc8373b3\",\n          \"x\": 52,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"8507db95-896c-4456-8be2-f867dd867528\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-27T11:14:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page6_route_1.png\",\n            \"width\": 330,\n            \"height\": 168,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 235,\n          \"width\": 412,\n          \"height\": 210,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3f2955a6-dabe-4871-9a51-e9d4a8d08a15\",\n          \"groupId\": \"da97becf-20e8-4bb2-a4fb-b742581797f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"10e1baa9-dc97-41e8-82b8-70ab243a2ab4\",\n          \"x\": 299,\n          \"y\": 328,\n          \"groupId\": \"da97becf-20e8-4bb2-a4fb-b742581797f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">1:45 PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 18,\n          \"id\": \"a4d6302a-a910-47df-b202-58fa068c4a75\",\n          \"x\": 299,\n          \"y\": 332,\n          \"groupId\": \"da97becf-20e8-4bb2-a4fb-b742581797f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 20,\n            \"vertical\": 22\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">Spend the day exploring shops and restaurants. Stop in, take your time, grab lunch and a few gin &amp; tonics.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 110,\n          \"id\": \"c5364cb9-6b40-4a02-b65d-715b3c024d9c\",\n          \"x\": 48,\n          \"y\": 506,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"80c925b2-16e7-49cf-90e7-e62d35321e37\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"10e1baa9-dc97-41e8-82b8-70ab243a2ab4\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"9637c921-8147-448c-ad70-29b9902de52c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a4d6302a-a910-47df-b202-58fa068c4a75\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"30e73da3-a0de-4790-9db1-549450bd1e3a\"],\n          \"id\": \"3ac24b1d-2d65-40b6-961d-a367b46d7935\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4a5e4f40-d437-4af7-ab82-254a9a1b7e53\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3f2955a6-dabe-4871-9a51-e9d4a8d08a15\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5c0637ff-a17e-43cb-a8b2-79d6c4f1480f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"fa1d3671-ae25-449c-aa6d-7d8aef8a2db6\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"8507db95-896c-4456-8be2-f867dd867528\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"da97becf-20e8-4bb2-a4fb-b742581797f7\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 332,\n          \"height\": 544,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"fa1d3671-ae25-449c-aa6d-7d8aef8a2db6\",\n          \"scale\": 130,\n          \"focalX\": 47.922134032919075,\n          \"focalY\": 39.331896551724135,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page7_img1.jpg\",\n            \"width\": 330,\n            \"height\": 544,\n            \"id\": 0,\n            \"alt\": \"Brwon and black cathedrla\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#272422\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.44 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page7_route_1.png\",\n            \"width\": 330,\n            \"height\": 110,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 318,\n          \"width\": 412,\n          \"height\": 137,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a76df551-3d1c-47cb-adbd-f72ad28ec374\",\n          \"groupId\": \"349f764f-9f35-4935-83e0-243dcdf78f30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"564b12c5-cd1d-473c-863c-8e0ac570918a\",\n          \"x\": 279,\n          \"y\": 319,\n          \"groupId\": \"349f764f-9f35-4935-83e0-243dcdf78f30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">3:30 PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 18,\n          \"id\": \"272dfab6-46bf-40d9-b090-0a9efa7e5c09\",\n          \"x\": 279,\n          \"y\": 324,\n          \"groupId\": \"349f764f-9f35-4935-83e0-243dcdf78f30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Afternoon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"86ab6768-cbf2-45f3-a0f0-3e74da538c9f\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"9d24f16f-eaa8-4f13-8c68-65e3e26e9fa0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Casa</span>\\n<span style=\\\"color: #fff\\\">Batlló</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 96,\n          \"id\": \"e406dbd5-4c40-4aeb-8ec9-ff74bf275b94\",\n          \"x\": 46,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"9d24f16f-eaa8-4f13-8c68-65e3e26e9fa0\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 26,\n            \"vertical\": 22\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">Casa Batlló is identifiable as Modernism or Art Nouveau in the broadest sense. To locals, it’s a slice of Barcelona tradition.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 132,\n          \"id\": \"ec789224-25b4-440b-8ae4-9b7b1a7d7a99\",\n          \"x\": 46,\n          \"y\": 485,\n          \"type\": \"text\",\n          \"marginOffset\": -0.03399999999999892\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7ab95974-ad79-4f53-a0a3-8c1cd1119e88\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"564b12c5-cd1d-473c-863c-8e0ac570918a\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"e624478c-a1e7-4b51-80b1-83703aeffc68\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"272dfab6-46bf-40d9-b090-0a9efa7e5c09\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"3cc54e2d-f3e1-488f-bcab-2f6ccf646b31\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a76df551-3d1c-47cb-adbd-f72ad28ec374\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"da2e4f65-15a7-4e04-9cc1-32cb5db8e21e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e65879b8-1394-4055-b1e8-f22a4bf63447\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9d24f16f-eaa8-4f13-8c68-65e3e26e9fa0\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"324240e3-94d8-44da-b6e3-56d2a7f2a6fa\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"349f764f-9f35-4935-83e0-243dcdf78f30\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 118,\n          \"focalX\": 60.47367517504435,\n          \"focalY\": 49.905708991185875,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page8_img1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Interior of a railway station like building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1f1f1b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"68292eb5-7b8e-474d-ae67-ddb9bbbaac08\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Evening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"cae06000-380b-46a0-b4b1-539b676724f2\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"46a533c3-50eb-4908-9ffa-c25d56cb2d42\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Basílica</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 55,\n          \"id\": \"077eceeb-0615-4ba5-bc26-552a128bd803\",\n          \"x\": 47,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"46a533c3-50eb-4908-9ffa-c25d56cb2d42\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page8_route_1.png\",\n            \"width\": 330,\n            \"height\": 103,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"x\": 0,\n          \"y\": 256,\n          \"width\": 412,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"35c04a6f-123c-4d7e-a883-755198043315\",\n          \"type\": \"image\",\n          \"groupId\": \"1702b74a-44cf-49ae-8163-19e3f9148e27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"7d752bc2-9c20-4ea4-97b9-ea61b7a65b2d\",\n          \"x\": 282,\n          \"y\": 320,\n          \"groupId\": \"1702b74a-44cf-49ae-8163-19e3f9148e27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">7:00 PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 18,\n          \"id\": \"d37ce262-0dc4-46c0-a478-8eb12df52fe1\",\n          \"x\": 284,\n          \"y\": 325,\n          \"groupId\": \"1702b74a-44cf-49ae-8163-19e3f9148e27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 26,\n            \"vertical\": 24\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">Sagrada Familia, the symbol of Barcelona and the stunning masterpiece of Gaudi.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 114,\n          \"id\": \"fd200968-8ccd-4f68-907b-443262f35486\",\n          \"x\": 48,\n          \"y\": 505,\n          \"marginOffset\": -0.03399999999999892,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"aba1e5d0-5dc3-4ad4-8875-1ce6f69d78d4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7d752bc2-9c20-4ea4-97b9-ea61b7a65b2d\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"cf10baae-f3e0-45a9-a0d4-441a20bf09c2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d37ce262-0dc4-46c0-a478-8eb12df52fe1\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"cae06000-380b-46a0-b4b1-539b676724f2\"],\n          \"id\": \"bdfd07f8-d41b-4deb-a58c-0cbcc42fab26\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5a3ca3a3-4d0a-43b8-8a21-8e84f5b8006f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"35c04a6f-123c-4d7e-a883-755198043315\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"79fcde0c-b6d9-454a-919b-21e22498d077\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"2946e472-ae6e-4317-9661-913b0493e7b9\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bad5dba2-1ffa-40f4-a5d6-e5a4f5b1df66\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"1702b74a-44cf-49ae-8163-19e3f9148e27\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"46a533c3-50eb-4908-9ffa-c25d56cb2d42\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 439,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"2946e472-ae6e-4317-9661-913b0493e7b9\",\n          \"scale\": 130,\n          \"focalX\": 49.96400695264332,\n          \"focalY\": 51.041666666666664,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page9_img1.jpg\",\n            \"width\": 330,\n            \"height\": 439,\n            \"id\": 0,\n            \"alt\": \"Fried food with sauce\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8b5f49\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 22, \"g\": 22, \"b\": 22 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 22, \"g\": 22, \"b\": 22, \"a\": 0 },\n                \"position\": 0.39\n              }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Evening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"773970b2-e5d8-4061-953d-fb0e3e284735\",\n          \"x\": 48,\n          \"y\": 20,\n          \"groupId\": \"f3d63749-0118-476c-a183-47ef25360f7d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Bar\\nRamón</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 96,\n          \"id\": \"0c9c16a6-cd3e-4203-bc39-7174277be2a8\",\n          \"x\": 48,\n          \"y\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"f3d63749-0118-476c-a183-47ef25360f7d\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page9_route_1.png\",\n            \"width\": 330,\n            \"height\": 46,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 373,\n          \"width\": 412,\n          \"height\": 57,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"39ea5c84-bf0b-4a33-88f4-b1a0256954fb\",\n          \"groupId\": \"eeb19136-ea34-4a36-ae0a-8fa47a588959\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"9fb6ef2f-f6d0-4791-9c08-79804328b806\",\n          \"x\": 141,\n          \"y\": 340,\n          \"groupId\": \"eeb19136-ea34-4a36-ae0a-8fa47a588959\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">8:30 PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 18,\n          \"id\": \"4f733d66-2844-493b-9274-de6211700766\",\n          \"x\": 144,\n          \"y\": 345,\n          \"groupId\": \"eeb19136-ea34-4a36-ae0a-8fa47a588959\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 25,\n            \"vertical\": 24\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">Ready for some bites now, right? Grab pre-dinner snacks at this local's bar and restaurant.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 314,\n          \"height\": 114,\n          \"id\": \"27472069-5878-4a0e-8c5f-c9eee943a15d\",\n          \"x\": 48,\n          \"y\": 505,\n          \"marginOffset\": -0.03399999999999892,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4b390a59-87a0-47ef-8ad0-39d125a3381f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9fb6ef2f-f6d0-4791-9c08-79804328b806\"],\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"e55035ce-308c-4b6c-b100-1056b29cb86a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4f733d66-2844-493b-9274-de6211700766\"],\n          \"duration\": 1600,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"8aa4c1f6-a59a-47c5-a84d-d2b1e72ef304\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"39ea5c84-bf0b-4a33-88f4-b1a0256954fb\"],\n          \"duration\": 1600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"80ebdab5-4975-4a7e-ab74-49c95bd52a45\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"9ee6c38a-c279-47cd-a6a4-8aa32340aa2b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"eeb19136-ea34-4a36-ae0a-8fa47a588959\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f3d63749-0118-476c-a183-47ef25360f7d\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 247,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"9ee6c38a-c279-47cd-a6a4-8aa32340aa2b\",\n          \"scale\": 106,\n          \"focalX\": 51.62062552720009,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page10_img1.jpg\",\n            \"width\": 330,\n            \"height\": 247,\n            \"id\": 0,\n            \"alt\": \"People on beach during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cbd0de\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page10_route_1.png\",\n            \"width\": 330,\n            \"height\": 211,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 258,\n          \"width\": 412,\n          \"height\": 264,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3ab82064-9564-4fc0-a7d0-d16fa6a1fb63\",\n          \"groupId\": \"8ccea118-49f8-4978-989f-2e9329648e61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 80,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"travelToolTip\" },\n          \"id\": \"e7085bfe-9d76-45b0-b220-a7651e26cc3b\",\n          \"x\": 172,\n          \"y\": 381,\n          \"groupId\": \"8ccea118-49f8-4978-989f-2e9329648e61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">End</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 18,\n          \"id\": \"1f15ef40-5c58-455e-abd0-008f2de4c5a1\",\n          \"x\": 175,\n          \"y\": 386,\n          \"groupId\": \"8ccea118-49f8-4978-989f-2e9329648e61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 199, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 22,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"color: #160236\\\">The unique experiences in Barcelona belong to this city only, begging you to return here over and over again.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 117,\n          \"id\": \"fccd7415-af38-4f6b-b9b6-380a20f6e8b7\",\n          \"x\": 48,\n          \"y\": 500,\n          \"marginOffset\": -0.03399999999999892,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f0fea999-cbb9-42be-b939-07f0d0391294\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e7085bfe-9d76-45b0-b220-a7651e26cc3b\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"39e2bbd4-ea79-4717-9b5d-af17688fa195\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1f15ef40-5c58-455e-abd0-008f2de4c5a1\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"230dedaf-50e5-4007-8fd7-959964bc7066\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3ab82064-9564-4fc0-a7d0-d16fa6a1fb63\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"823c3d20-d001-4bc5-a07d-bf48d1fa2b0e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"a9562766-122d-4f05-b2db-8bb10b1647e4\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8ccea118-49f8-4978-989f-2e9329648e61\": {\n          \"name\": \"End\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c6b09dbe-27d4-4f6f-bfb1-2f9ab3f085fb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -50,\n          \"width\": 412,\n          \"height\": 725,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"df55c462-e535-4eaf-987c-774553354e74\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page11_route_1.png\",\n            \"width\": 330,\n            \"height\": 581,\n            \"id\": 0,\n            \"alt\": \"Dashed border line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Next steps</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 186,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"ffcbf0a0-8720-4d0c-9c48-904056bc6e98\",\n          \"x\": 52,\n          \"y\": 34,\n          \"groupId\": \"f8de7d40-258c-4d10-a0d4-713b57b13b6b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">More</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">Stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 96,\n          \"type\": \"text\",\n          \"id\": \"0fee495a-3b8c-4e00-9170-7b32c0a1a38b\",\n          \"x\": 52,\n          \"y\": 60,\n          \"groupId\": \"f8de7d40-258c-4d10-a0d4-713b57b13b6b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #ffc700\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 22,\n          \"height\": 67,\n          \"type\": \"text\",\n          \"id\": \"ef5cbd25-6d2e-4fc7-876f-5a11ac357010\",\n          \"x\": 197,\n          \"y\": 253,\n          \"groupId\": \"fc45fbb0-70df-4d3c-aa17-d660aa78b582\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">days in</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">East Berlin</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 99,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"id\": \"61390d07-3107-4db5-b90f-27b90e8b53ec\",\n          \"x\": 225,\n          \"y\": 280,\n          \"groupId\": \"fc45fbb0-70df-4d3c-aa17-d660aa78b582\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#ccd1db\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/polaroids_bg.png\",\n            \"width\": 121,\n            \"height\": 160,\n            \"id\": 0,\n            \"alt\": \"Polaroids photo frames\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 56,\n          \"y\": 216,\n          \"width\": 116,\n          \"height\": 155,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"295b719f-2a5c-4d13-9ae1-3396804c5b20\",\n          \"groupId\": \"fc45fbb0-70df-4d3c-aa17-d660aa78b582\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 88,\n          \"height\": 100,\n          \"scale\": 215,\n          \"focalX\": 61.84536881607784,\n          \"focalY\": 62.75964944835199,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"031713db-689e-4ebf-8779-6aeb3a31ae17\",\n          \"x\": 72,\n          \"y\": 237,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page11_img1.jpg\",\n            \"width\": 320,\n            \"height\": 427,\n            \"id\": 0,\n            \"alt\": \"low-angle photography of Berlin Cathedral, Berlin, Germany during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cdd9d3\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"fc45fbb0-70df-4d3c-aa17-d660aa78b582\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #ffc700\\\">A</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 22,\n          \"height\": 66,\n          \"type\": \"text\",\n          \"id\": \"9cc2576e-652e-4f03-8a3d-8463f3fc8ff7\",\n          \"x\": 55,\n          \"y\": 416,\n          \"groupId\": \"b3b8bf9f-8c6f-4b33-bc9e-2fe7076b18c8\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">dream week</span>\\n<span style=\\\"color: #fff\\\">in Amsterdam</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 133,\n          \"height\": 47,\n          \"type\": \"text\",\n          \"id\": \"59e236f3-2390-4349-8392-46b4d9e29d28\",\n          \"x\": 91,\n          \"y\": 447,\n          \"groupId\": \"b3b8bf9f-8c6f-4b33-bc9e-2fe7076b18c8\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#ccd1db\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/polaroids_bg.png\",\n            \"width\": 121,\n            \"height\": 160,\n            \"id\": 0,\n            \"alt\": \"Polaroids photo frames\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 116,\n          \"height\": 155,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fe7bdf60-e08b-460d-a12a-4864f80e232f\",\n          \"x\": 234,\n          \"y\": 412,\n          \"groupId\": \"b3b8bf9f-8c6f-4b33-bc9e-2fe7076b18c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 250,\n          \"y\": 431,\n          \"width\": 88,\n          \"height\": 100,\n          \"scale\": 155,\n          \"focalX\": 56.341193850562185,\n          \"focalY\": 48.81727203554218,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f429e54a-bd63-443c-ae14-f46a0f3963ab\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/12-hours-in-barcelona/page11_img2.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"id\": 0,\n            \"alt\": \"Boat docked near building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#babab6\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"b3b8bf9f-8c6f-4b33-bc9e-2fe7076b18c8\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f6c61a0a-ebbb-4abb-be9c-d76f9b143073\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"df55c462-e535-4eaf-987c-774553354e74\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dd76f91e-80ef-48dd-b813-74c406af18df\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ef5cbd25-6d2e-4fc7-876f-5a11ac357010\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"cae4095b-ad49-432a-930b-552507ae12a0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"61390d07-3107-4db5-b90f-27b90e8b53ec\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"52f44282-fd9c-4612-a60f-656829b5fd93\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9cc2576e-652e-4f03-8a3d-8463f3fc8ff7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"3cacb1d0-1968-4a78-b6d5-26de896db984\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"59e236f3-2390-4349-8392-46b4d9e29d28\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"ce20750d-45ce-47bc-8497-d55793cacdef\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"031713db-689e-4ebf-8779-6aeb3a31ae17\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"03762cd1-1dca-4ecc-bfc9-1ce209ca3199\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"295b719f-2a5c-4d13-9ae1-3396804c5b20\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5efa6f68-7933-4db4-ba3b-012269d8e45c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fe7bdf60-e08b-460d-a12a-4864f80e232f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"19afbfe0-6c9b-450b-b669-1ac033ddbacf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f429e54a-bd63-443c-ae14-f46a0f3963ab\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 39, \"g\": 66, \"b\": 81 } },\n      \"type\": \"page\",\n      \"id\": \"c004ed2c-65d3-400c-92b3-9d83f8850b26\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c6b09dbe-27d4-4f6f-bfb1-2f9ab3f085fb\"\n      },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"b3b8bf9f-8c6f-4b33-bc9e-2fe7076b18c8\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fc45fbb0-70df-4d3c-aa17-d660aa78b582\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f8de7d40-258c-4d10-a0d4-713b57b13b6b\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/a-day-in-the-life/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/a-day-in-the-life/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'a-day-in-the-life',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('A Day in the Life', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Routine', 'template keyword', 'web-stories'),\n    _x('Video', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Waterworld Blue', 'color', 'web-stories'),\n      color: '#061b38',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Arctic White', 'color', 'web-stories'),\n      color: '#fcfcfc',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Honey Pot Yellow', 'color', 'web-stories'),\n      color: '#ffc864',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This simple and minimalist template will let you create long format video stories that are highly engaging. Create day-in-the-life videos, workout routines, makeup tutorials and much more.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/a-day-in-the-life/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/a-day-in-the-life/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 625,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"da188790-4acd-4082-9701-74126b2cc568\",\n          \"scale\": 180,\n          \"focalX\": 54.93827160493827,\n          \"focalY\": 58.544921875,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-01T15:00:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page1_bg-vid.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page1_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A person wearing hat and olive green jacket\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#a59a89\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 1 }\n            ]\n          },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3); text-transform: uppercase\\\">A day in the life: Jordan Micheals</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 309,\n          \"width\": 282,\n          \"height\": 291,\n          \"id\": \"57828597-1338-4b6f-b2c7-60339643bc9f\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">By John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 160,\n          \"y\": 602,\n          \"width\": 92,\n          \"height\": 17,\n          \"id\": \"49b6135f-6f30-4c9e-a09d-818c46fbe77d\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"7b18ade0-d74d-41b9-81b6-50a65422db76\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"21510eba-e5e1-4c6e-b372-a157e48659d3\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 185,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"8f791733-8a73-4a48-a009-a1b2649d4279\",\n          \"type\": \"video\",\n          \"scale\": 120,\n          \"focalX\": 41.12274792729592,\n          \"focalY\": 43.96524234693879,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-01T10:21:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page2_bg-vid.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page2_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"alt\": \"Hand Washing\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#b8b8b9\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">7:00AM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 266,\n          \"width\": 316,\n          \"height\": 86,\n          \"id\": \"974ce9b6-7771-40fe-8046-9346ff2f66da\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Rise &amp; Shine</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 140,\n          \"y\": 359,\n          \"width\": 131,\n          \"height\": 28,\n          \"id\": \"16a0f85f-86e3-4840-8305-7004ae62146e\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"67a84fd1-16af-414b-8981-a527059933f9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"974ce9b6-7771-40fe-8046-9346ff2f66da\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"599cd1a6-dc8e-4744-9357-0b0c43c76958\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"16a0f85f-86e3-4840-8305-7004ae62146e\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"a7721c47-bf43-486d-bb39-182473d46c83\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"63b03a14-d4ca-443e-bb76-4fcde7e186fd\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"8eec9636-b09d-4d2e-94a5-6c0df73647ea\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:19:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"White soft-tube and brown brush in blue container beside pump bottle\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#4d575d\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 200, \"b\": 100 } },\n          \"x\": 48,\n          \"y\": 11,\n          \"width\": 50,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ba4478ab-2791-4d63-9b67-fd0491405cc1\",\n          \"type\": \"shape\",\n          \"groupId\": \"ccd8441d-1d26-4bf0-88bb-b3171d2811a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">My favorite morning products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 28,\n          \"id\": \"724858ef-097e-4b72-9ec2-105750f1c638\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"ccd8441d-1d26-4bf0-88bb-b3171d2811a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">“I love this facewash and toothpaste, the mint and rosemary always wake me up”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 86,\n          \"id\": \"5793290c-aabd-48d9-a4fe-3b39ae4c51e0\",\n          \"x\": 47,\n          \"y\": 55,\n          \"type\": \"text\",\n          \"groupId\": \"ccd8441d-1d26-4bf0-88bb-b3171d2811a4\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 27, \"b\": 56 } },\n          \"x\": 55,\n          \"y\": 195,\n          \"id\": \"f6deaf9c-23ef-4c55-aeb5-7aba4dd616dc\",\n          \"width\": 50,\n          \"height\": 50,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"fbc339bf-dd80-4039-8e88-e058900ba2f4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 70,\n          \"y\": 210,\n          \"width\": 20,\n          \"height\": 20,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"3ea648fa-dccf-435e-95d8-8cd217288f27\",\n          \"type\": \"shape\",\n          \"groupId\": \"fbc339bf-dd80-4039-8e88-e058900ba2f4\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 27, \"b\": 56 } },\n          \"x\": 330,\n          \"y\": 259,\n          \"id\": \"99003f39-617c-4a03-813b-e97da611d750\",\n          \"width\": 50,\n          \"height\": 50,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"e39453c3-885c-4d7f-af0a-75500ec26304\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 345,\n          \"y\": 274,\n          \"id\": \"10794479-1b6c-46a2-8576-948369ec3939\",\n          \"width\": 20,\n          \"height\": 20,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"e39453c3-885c-4d7f-af0a-75500ec26304\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 23,\n            \"vertical\": 15\n          },\n          \"x\": 124,\n          \"y\": 568,\n          \"id\": \"16df8a94-58d5-4d2b-bbdd-73c5678ca9c4\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View </span><span style=\\\"color: #fff\\\">Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 40,\n            \"topRight\": 40,\n            \"bottomRight\": 40,\n            \"bottomLeft\": 40\n          },\n          \"width\": 164,\n          \"height\": 49,\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" },\n          \"marginOffset\": 3.3999999999999986,\n          \"type\": \"text\",\n          \"groupId\": \"d5f7a406-4f76-4e50-beae-8b59fd4f8b2d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 145,\n          \"y\": 585,\n          \"width\": 12,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"dayInTheLifeBag\" },\n          \"id\": \"a6ee6890-154d-4c0f-8d5e-038bb3cd2783\",\n          \"type\": \"sticker\",\n          \"groupId\": \"d5f7a406-4f76-4e50-beae-8b59fd4f8b2d\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d2002a3e-49c9-4326-83e8-9abb5b63b11c\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"f6deaf9c-23ef-4c55-aeb5-7aba4dd616dc\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"633a6728-680e-4d39-92a5-82e21ad7cdb9\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"3ea648fa-dccf-435e-95d8-8cd217288f27\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b64fd4c0-dffe-4765-b96c-ebaba51876f8\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"99003f39-617c-4a03-813b-e97da611d750\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6c40724f-3702-4d73-9f11-16678dde9433\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"10794479-1b6c-46a2-8576-948369ec3939\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"0f8ab043-fa6f-4af4-9cf5-cff9b63e7701\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f5a8c3e4-03b2-4269-a0da-0b45dc704532\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"d5f7a406-4f76-4e50-beae-8b59fd4f8b2d\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ccd8441d-1d26-4bf0-88bb-b3171d2811a4\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"e39453c3-885c-4d7f-af0a-75500ec26304\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fbc339bf-dd80-4039-8e88-e058900ba2f4\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 579,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f5065299-4134-46a0-964b-1780dbccabb0\",\n          \"type\": \"video\",\n          \"scale\": 145,\n          \"focalX\": 50.000000000000014,\n          \"focalY\": 58.51293103448276,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:39:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page4_bg-vid.mp4\",\n            \"width\": 1080,\n            \"height\": 1896,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page4_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A man using a jump rope to warm up\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#383838\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">9:00AM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 262,\n          \"width\": 316,\n          \"height\": 86,\n          \"id\": \"fb4c4132-b648-4998-a5f8-bf529be048e6\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Workout</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 140,\n          \"y\": 348,\n          \"width\": 131,\n          \"height\": 28,\n          \"id\": \"a9ae198e-62be-4ec6-8df1-95679d12d3fc\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fe33f1e3-c73e-47a2-95f6-281dd743e19c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fb4c4132-b648-4998-a5f8-bf529be048e6\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"3357638e-926d-4f06-a678-47909daf4c65\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a9ae198e-62be-4ec6-8df1-95679d12d3fc\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"7c86b60b-cffa-4f2a-8f44-697945abc94d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"d15e8a32-e297-4a0d-b9cf-a60697039386\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d827eebd-99aa-4727-a364-a99e36f8cd29\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:41:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page5_bg-vid.mp4\",\n            \"width\": 1365,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page5_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"Two men doing cardio exercises\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#35363f\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 455,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3da8860d-2e1e-423c-85eb-8617348b98f8\",\n          \"type\": \"video\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 200, \"b\": 100 } },\n          \"width\": 50,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9f793930-5646-43d4-9f59-8ab1e4ccbe81\",\n          \"x\": 48,\n          \"y\": 436,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Jordan's Workout</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 28,\n          \"id\": \"4310b80c-ea1b-433c-bfeb-5bde5b82a6b7\",\n          \"x\": 48,\n          \"y\": 439,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 65,\n          \"y\": 500,\n          \"width\": 36,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"dayInTheLifeAlarmClock\" },\n          \"id\": \"46be44b4-5dc6-4cc5-8310-ec81ad624d97\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c676ab9f-ec5d-4ced-a0f9-298059af381d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 60,\n          \"y\": 553,\n          \"id\": \"5715d14d-e802-4e6b-b2cb-6e78a8ae26ba\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">20M</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 61,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"c676ab9f-ec5d-4ced-a0f9-298059af381d\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 595,\n          \"id\": \"3d7c4dfd-b784-4e40-b668-a5d9eaaebc5b\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Treadmill</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"c676ab9f-ec5d-4ced-a0f9-298059af381d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 186,\n          \"y\": 504,\n          \"width\": 44,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"dayInTheLifeJumpRope\" },\n          \"id\": \"f0298471-fa3a-4435-b86d-54c6b0b744ac\",\n          \"type\": \"sticker\",\n          \"groupId\": \"6f9c459b-e14e-49e4-90b4-b286ee43d5e1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 177,\n          \"y\": 553,\n          \"id\": \"6ec08767-f5a9-4a7c-b304-591bc4c75884\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">10X</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"6f9c459b-e14e-49e4-90b4-b286ee43d5e1\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 168,\n          \"y\": 595,\n          \"id\": \"ecd6f5a5-36e4-4f3c-b9ad-16971584f12e\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Jump Rope</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 85,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"6f9c459b-e14e-49e4-90b4-b286ee43d5e1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 304,\n          \"y\": 511,\n          \"width\": 52,\n          \"height\": 30,\n          \"sticker\": { \"type\": \"dayInTheLifeDumbells\" },\n          \"id\": \"7c217db2-ee8d-46d8-ae30-97633cc84e43\",\n          \"type\": \"sticker\",\n          \"groupId\": \"b8130953-0754-4800-801f-2507f890c612\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 315,\n          \"y\": 553,\n          \"id\": \"f66b9636-128b-4f3f-bc2f-ad70e4ee5f6c\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">5X</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 35,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"b8130953-0754-4800-801f-2507f890c612\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 294,\n          \"y\": 595,\n          \"id\": \"d72284c6-a9e2-48dc-992d-aec36bc8e5c0\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Lunges</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 72,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"b8130953-0754-4800-801f-2507f890c612\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3a8d54c6-f283-45c9-9614-c503e14a2900\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"46be44b4-5dc6-4cc5-8310-ec81ad624d97\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b7a2fe02-eff6-4967-b802-5c2a5e8a4bcc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5715d14d-e802-4e6b-b2cb-6e78a8ae26ba\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"45e68d75-c044-43a6-8d75-db61241fd5cc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3d7c4dfd-b784-4e40-b668-a5d9eaaebc5b\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dc97f28e-fc4a-4842-8b05-d79b1e9db826\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f0298471-fa3a-4435-b86d-54c6b0b744ac\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"46ef3334-a49a-4547-8ce8-b176504f75b7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6ec08767-f5a9-4a7c-b304-591bc4c75884\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"080a6f5f-fa91-43f9-8c4e-fcf0c949a6e0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ecd6f5a5-36e4-4f3c-b9ad-16971584f12e\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"09d3b875-f6ee-4f98-a2b0-912c0c6e72ba\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7c217db2-ee8d-46d8-ae30-97633cc84e43\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"9bdaabec-d787-4188-af26-ef614b07fced\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f66b9636-128b-4f3f-bc2f-ad70e4ee5f6c\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"ea72afff-8d6f-4984-b354-3947903404a6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d72284c6-a9e2-48dc-992d-aec36bc8e5c0\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 12, \"g\": 23, \"b\": 39 } },\n      \"type\": \"page\",\n      \"id\": \"f10eeeae-8d55-4d3f-a0e6-2fb7a38417b8\",\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"c676ab9f-ec5d-4ced-a0f9-298059af381d\": {\n          \"name\": \"Treadmill\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6f9c459b-e14e-49e4-90b4-b286ee43d5e1\": {\n          \"name\": \"Rope\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b8130953-0754-4800-801f-2507f890c612\": {\n          \"name\": \"Lunges\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 174,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3d001f82-1ae4-4a41-a454-3a3f0d998567\",\n          \"type\": \"video\",\n          \"scale\": 130,\n          \"focalX\": 48.54184277261201,\n          \"focalY\": 55.52884615384615,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:42:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page6_bg-vid.mp4\",\n            \"width\": 1365,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page6_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"Man having conversation with a woman at an outdoor restaurant\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#c4c4c4\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">11:00AM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 262,\n          \"width\": 316,\n          \"height\": 90,\n          \"id\": \"fbce8523-ab3f-4885-8005-55e840cce0a1\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Brunch</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 140,\n          \"y\": 352,\n          \"width\": 131,\n          \"height\": 28,\n          \"id\": \"f8c0a654-c9ae-464d-a6f3-5288cc544d32\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ed1b12fc-ea34-448d-9f99-5e764e45db49\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fbce8523-ab3f-4885-8005-55e840cce0a1\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"45c27fcc-6316-4fd2-b1d6-ff1c1b27d7a0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f8c0a654-c9ae-464d-a6f3-5288cc544d32\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"26d9eedb-ae2b-4991-85c1-c3c5645fcdd7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ac604717-7cd8-45ab-8fe9-e4fc11292331\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e67318a0-aad9-4812-9b0d-23f89dd450c9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 125,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:43:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page7_bg-vid.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page7_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"Plating presentation for a serving of mixed sushi\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#7d6c56\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 455,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4f41dfc8-0119-4157-9171-58051939a27e\",\n          \"type\": \"video\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 200, \"b\": 100 } },\n          \"width\": 50,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d9911d02-510d-4e02-a9f6-60271a2fd934\",\n          \"x\": 48,\n          \"y\": 436,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Jordan's Health Breakfast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 28,\n          \"id\": \"9fa5baa1-061e-4083-a3ae-ed1408d37631\",\n          \"x\": 48,\n          \"y\": 439,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 48,\n          \"y\": 507,\n          \"width\": 50,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"dayInTheLifeFish\" },\n          \"id\": \"d101b2f6-d85d-4683-9ded-528264aa6724\",\n          \"type\": \"sticker\",\n          \"groupId\": \"d558a302-5e68-47b1-b9b1-25503d452ecd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 60,\n          \"y\": 553,\n          \"id\": \"d28cf99e-ba51-4b57-a87b-8790e9e0231e\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"d558a302-5e68-47b1-b9b1-25503d452ecd\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 75,\n          \"y\": 557,\n          \"id\": \"f728e032-be7a-40c5-a5c0-c15645c9420c\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">OZ</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"groupId\": \"d558a302-5e68-47b1-b9b1-25503d452ecd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 595,\n          \"id\": \"bbc75e67-0972-441d-8161-2b3870d00ad6\",\n          \"content\": \"<span style=\\\"color: #fff\\\">FISH</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 48,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"d558a302-5e68-47b1-b9b1-25503d452ecd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 181,\n          \"y\": 499,\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"dayInTheLifeBrownRice\" },\n          \"id\": \"ad8127ae-7949-45f3-9976-d00f0bb76a2e\",\n          \"type\": \"sticker\",\n          \"groupId\": \"6c87c966-2031-4e97-9c16-4e21f9df69a2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 168,\n          \"y\": 595,\n          \"id\": \"6b5725a6-2c2f-4ef4-be30-c55530e5f37d\",\n          \"content\": \"<span style=\\\"color: #fff\\\">BROWN RICE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 85,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"6c87c966-2031-4e97-9c16-4e21f9df69a2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 177,\n          \"y\": 553,\n          \"id\": \"715f2995-b65b-4162-bc5d-dbf67207a8c8\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">1 CUP</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"6c87c966-2031-4e97-9c16-4e21f9df69a2\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 306,\n          \"y\": 496,\n          \"width\": 41,\n          \"height\": 49,\n          \"sticker\": { \"type\": \"dayInTheLifeLeaves\" },\n          \"id\": \"c2829191-981c-45fa-8908-3d2f5afbf25b\",\n          \"type\": \"sticker\",\n          \"groupId\": \"97e3a654-5784-42da-b660-d614aa307a54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 312,\n          \"y\": 553,\n          \"id\": \"5d34c5e5-520e-464f-abf8-11722f6d9b33\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"97e3a654-5784-42da-b660-d614aa307a54\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 327,\n          \"y\": 557,\n          \"id\": \"eb375931-651a-4160-88bd-964b5b4300b3\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em\\\">OZ</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"groupId\": \"97e3a654-5784-42da-b660-d614aa307a54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 291,\n          \"y\": 594,\n          \"id\": \"0985e096-cbee-4a47-a96a-12da843590a0\",\n          \"content\": \"<span style=\\\"color: #fff\\\">VEGGIES</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 72,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"97e3a654-5784-42da-b660-d614aa307a54\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1f7a1fca-7347-4fc4-a96b-2047f020bfd1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d101b2f6-d85d-4683-9ded-528264aa6724\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"59b5c50c-bb5c-47d2-b96e-c95133256426\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f728e032-be7a-40c5-a5c0-c15645c9420c\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2922de6f-fa33-4bf2-9205-90bbb566c6be\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d28cf99e-ba51-4b57-a87b-8790e9e0231e\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1e4bf26a-eea5-4ce7-82b0-24e9ee4ea185\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bbc75e67-0972-441d-8161-2b3870d00ad6\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d5699db5-b55d-4c6b-a26f-f85bfc57d481\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ad8127ae-7949-45f3-9976-d00f0bb76a2e\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"7579ac62-baea-471e-9623-2f849eb51169\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"715f2995-b65b-4162-bc5d-dbf67207a8c8\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"b75de085-5e44-4134-9689-199f55a240d2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6b5725a6-2c2f-4ef4-be30-c55530e5f37d\"],\n          \"duration\": 1200,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"a2f1e479-944e-4bc2-aa2e-5dfba078ebd8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c2829191-981c-45fa-8908-3d2f5afbf25b\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0809a30c-6a7c-452a-b3b6-2c29a646076f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5d34c5e5-520e-464f-abf8-11722f6d9b33\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5986971b-077f-4fcc-b898-8c2d653e7ead\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"eb375931-651a-4160-88bd-964b5b4300b3\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"1a97770c-14ba-4a61-b9a3-73e69dff0589\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0985e096-cbee-4a47-a96a-12da843590a0\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 12, \"g\": 23, \"b\": 39 } },\n      \"type\": \"page\",\n      \"id\": \"b99a433d-e8a9-41c7-ab8e-70605639b48d\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"d558a302-5e68-47b1-b9b1-25503d452ecd\": {\n          \"name\": \"Fish\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6c87c966-2031-4e97-9c16-4e21f9df69a2\": {\n          \"name\": \"Rice\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"97e3a654-5784-42da-b660-d614aa307a54\": {\n          \"name\": \"Veggies\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 185,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"1b738a5d-6663-4262-8ad3-f69adaaf3605\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 54.74609375,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-27T07:42:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page8_bg-vid.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page8_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 13,\n            \"lengthFormatted\": \"0:13\",\n            \"alt\": \"A woman walking at an airpot\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#727272\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">6:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 262,\n          \"width\": 316,\n          \"height\": 86,\n          \"id\": \"5ae9738d-9cb9-4142-b030-a7c2ac2f8f64\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Flying to Canada</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 95,\n          \"y\": 348,\n          \"width\": 223,\n          \"height\": 28,\n          \"id\": \"7f140385-a748-422d-89ab-953a112ab98e\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b0146edd-d9e6-44b1-a578-a413f9d888b8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5ae9738d-9cb9-4142-b030-a7c2ac2f8f64\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"dbb66bb7-7d3d-425b-843d-becdc2129a10\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7f140385-a748-422d-89ab-953a112ab98e\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"cc13cce5-326d-4a7f-a111-33d942140da0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8a07a137-852b-4c22-a86b-ab05ba2b4146\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 185,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"18138bd1-2454-4631-9326-4c3ebd5f0385\",\n          \"scale\": 120,\n          \"focalX\": 40.8447265625,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:45:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page9_bg-vid.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page9_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"Selective focus on a persons hand using a smartphone\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#2b241a\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1eee2fa1-e0dc-4660-bc0c-df6a0c3a4ab3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"42a9d371-6641-4f75-9ca3-b8f63c855114\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 625,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7cb7e231-50d8-4b0a-93fa-9a6d669e7352\",\n          \"type\": \"video\",\n          \"scale\": 150,\n          \"focalX\": 50,\n          \"focalY\": 35.05859375,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:46:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page10_bg-vid.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page10_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A person cutting a grilled steak into thin slices\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#2e2e2e\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">9:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 262,\n          \"width\": 316,\n          \"height\": 86,\n          \"id\": \"c073d458-33d4-4317-807c-9bd1549358cf\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Dinner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 95,\n          \"y\": 348,\n          \"width\": 223,\n          \"height\": 28,\n          \"id\": \"a7b18100-64ff-4a4d-ad22-2b4df4465b12\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2df2ff65-3c18-4abb-8fcf-b84e06b3a8f1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c073d458-33d4-4317-807c-9bd1549358cf\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"ea770106-1a5d-47fb-b690-c238af744f67\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a7b18100-64ff-4a4d-ad22-2b4df4465b12\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"7cc78168-03db-43fe-991e-8cafa9203b6e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e519b87d-1b07-4bbd-866a-35b604332d96\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cefd3789-4976-4074-9680-b611b7e16f92\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:20:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page11_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Grilled meat dish served on white plate\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c0b7b2\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 200, \"b\": 100 } },\n          \"x\": 48,\n          \"y\": 12,\n          \"width\": 50,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bfcbc709-e19b-45f5-8831-29454d20327d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">My Go-To Dinner Recipe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 28,\n          \"id\": \"0cde6bd1-1284-43e4-b292-813f40003e10\",\n          \"x\": 48,\n          \"y\": 15,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">“I have to watch my diet, but every now and then I splurge and have comfort food.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 87,\n          \"id\": \"b16d69e2-c15a-4cca-9e03-a63455396546\",\n          \"x\": 47,\n          \"y\": 56,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0a6ac25f-20f0-4b70-9500-3f44e47c0626\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"targets\": [\"cefd3789-4976-4074-9680-b611b7e16f92\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 12000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleOut\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"da1bbc20-9b29-4e2a-96b5-2612fce01286\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"GET THE RECIPE\",\n        \"theme\": \"light\"\n      },\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"62217bcb-8a8d-4149-8f92-86306d4432bd\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 185,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"711e2c47-3361-433f-bf8f-398c92801c54\",\n          \"type\": \"video\",\n          \"scale\": 205,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T07:47:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page12_bg-vid.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page12_bg-vid-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A man sleeping on his bed\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#676767\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: rgba(255,255,255,0.3)\\\">11:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 262,\n          \"width\": 316,\n          \"height\": 86,\n          \"id\": \"edb3053e-9fe2-4579-8331-8a30f845f872\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Bedtime</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 95,\n          \"y\": 348,\n          \"width\": 223,\n          \"height\": 28,\n          \"id\": \"17c5d678-36ff-421c-969a-f55124d4b0fb\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5cc9b890-6eae-4f1a-b8c6-3511c543c97a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"edb3053e-9fe2-4579-8331-8a30f845f872\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"c74c0ce6-3ca2-4547-8b9d-a9707931872b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"17c5d678-36ff-421c-969a-f55124d4b0fb\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 57, \"g\": 57, \"b\": 57 } },\n      \"type\": \"page\",\n      \"id\": \"ea59b139-3723-4f10-8de7-d9de0a02d21f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"1fea0a11-2bb9-437d-a313-d21ff5fb4074\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c0bf418b-19d0-422e-a0e5-00be8622e588\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.04em; text-transform: uppercase\\\">Read more stories:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 36,\n          \"id\": \"b99133c9-9989-40b0-bd13-de9f0ddd49a3\",\n          \"x\": 48,\n          \"y\": -6,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:22:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page13_img2.jpg\",\n            \"width\": 720,\n            \"height\": 1121,\n            \"id\": 0,\n            \"alt\": \"Woman in green, red, and floral plunging-neckline top\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#2b3935\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 77,\n          \"width\": 274,\n          \"height\": 189,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"17678571-5417-44a3-89ab-296eb55965c4\",\n          \"type\": \"image\",\n          \"groupId\": \"870bd98c-1033-475e-a2f4-288a02fe7f24\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">Mary Coppolla's Wild Life</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 192,\n          \"height\": 120,\n          \"id\": \"0315941d-7e80-44c4-8c2d-603947137752\",\n          \"x\": 187,\n          \"y\": 205,\n          \"type\": \"text\",\n          \"groupId\": \"870bd98c-1033-475e-a2f4-288a02fe7f24\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:22:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/a-day-in-the-life/page13_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Man wearing black crew-neck shirt\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#161817\",\n            \"isExternal\": true\n          },\n          \"x\": 170,\n          \"y\": 357,\n          \"id\": \"3bb0ef4b-92f9-4aef-9509-0db281673427\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 195,\n          \"height\": 295,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"groupId\": \"b8a12257-1cb9-4178-8119-50630afc8a32\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow Condensed\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1075,\n              \"wDes\": 274,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1074,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 517,\n          \"id\": \"45b30b77-d14b-4e81-b9ee-7c3cd3ed1708\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">Evan Chris: Downunder</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 246,\n          \"height\": 84,\n          \"type\": \"text\",\n          \"groupId\": \"b8a12257-1cb9-4178-8119-50630afc8a32\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"404b77d4-2792-41fd-a381-ee0ad4081673\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0315941d-7e80-44c4-8c2d-603947137752\"],\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"f9f02000-72a8-41e0-a43f-afa4bae76298\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"45b30b77-d14b-4e81-b9ee-7c3cd3ed1708\"],\n          \"duration\": 600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 12, \"g\": 23, \"b\": 39 } },\n      \"type\": \"page\",\n      \"id\": \"4441a44c-e958-4e1b-a717-cbc46c18e817\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"870bd98c-1033-475e-a2f4-288a02fe7f24\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b8a12257-1cb9-4178-8119-50630afc8a32\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ace-hotel-kyoto-review/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/ace-hotel-kyoto-review/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'ace-hotel-kyoto-review',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Ace Hotel Kyoto Review', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Reviews', 'template keyword', 'web-stories'),\n    _x('Hotel', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Plankton Green', 'color', 'web-stories'),\n      color: '#19584d',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Rhino Gray-Blue', 'color', 'web-stories'),\n      color: '#374456',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dawn Gray', 'color', 'web-stories'),\n      color: '#b7bfc9',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Blueberry Gray', 'color', 'web-stories'),\n      color: '#6f7f94',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its plain font and boxy design, this template has an industrial and authoritative look. Use photos and videos to create compelling hotel reviews that inspire trust and confidence.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/ace-hotel-kyoto-review/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ace-hotel-kyoto-review/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e0e9305e-c182-4cfe-b9fb-ba0f2ae796c5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100.20242914979758,\n          \"focalX\": 50,\n          \"focalY\": 57.73477995511082,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page01_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Black and Brown leather padded tub sofa\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dacdc3\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 287,\n          \"width\": 416,\n          \"height\": 527,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c426b239-b92c-4d75-b1f8-55963f6667cc\",\n          \"resizeWidth\": 193.86408,\n          \"resizeHeight\": 245.781\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -445,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ea97f8b4-5f3d-41a0-83a1-7088caf806c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.02em\\\">Sophia Jayden</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 69,\n          \"y\": 0,\n          \"width\": 200,\n          \"height\": 25,\n          \"id\": \"ea6badf3-5d35-4903-8593-e7154b48d5a4\"\n        },\n        {\n          \"x\": 69,\n          \"y\": 101,\n          \"id\": \"24fcde09-a421-4762-9a3f-9c8793df7f41\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">My Stay At The Ace Hotel Kyoto</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 95,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 57,\n          \"y\": 161,\n          \"id\": \"3ce61444-e401-490f-b9f1-f775b3d0244f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 180,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">K</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 94,\n          \"height\": 288,\n          \"marginOffset\": -107.25299999999999,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n      \"type\": \"page\",\n      \"id\": \"da3808b7-6397-435a-8a2d-93f756672665\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a31a8f4f-52f5-48a0-aec7-ce68fa7422c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n          \"type\": \"shape\",\n          \"x\": 18,\n          \"y\": -88,\n          \"width\": 460,\n          \"height\": 345,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"92661475-0b13-4b28-8bc9-129cfdd1dcc4\",\n          \"groupId\": \"4e88ac63-e02c-4436-92c4-935b22f0e871\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">While Kyoto itself is a historical center, the Ace Hotel drops itself right into a new era of young makers reimagining age-old traditions.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 256,\n          \"height\": 82,\n          \"id\": \"439926ff-ecf2-489d-9870-f740f2835572\",\n          \"x\": 79,\n          \"y\": 101,\n          \"marginOffset\": -3.9129999999999967,\n          \"groupId\": \"4e88ac63-e02c-4436-92c4-935b22f0e871\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:03:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page02_image01.png\",\n            \"width\": 330,\n            \"height\": 356,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Abstract shapes forming a map like layout\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b3bbcb\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -9,\n          \"y\": 228,\n          \"width\": 439,\n          \"height\": 474,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"81e59880-e5ef-4fcd-a408-ade6d9df31e4\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 213,\n          \"y\": 323.5,\n          \"width\": 102,\n          \"height\": 22,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bb39be65-63ed-4e55-8604-e44621f3a282\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 220,\n          \"y\": 323,\n          \"id\": \"63b7aeb9-0761-44f4-8412-ea1911828986\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #374456; text-transform: uppercase\\\">UMEYACHO</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 88,\n          \"height\": 26,\n          \"marginOffset\": -3.9129999999999967,\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 559,\n          \"id\": \"03641918-b334-4ab8-bf45-dd29b4e5ca62\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 225,\n          \"height\": 22,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 558,\n          \"id\": \"e97f2792-33c5-4fcf-8bc9-d2ca6493e259\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #374456; text-transform: uppercase\\\">LAWSON KARASUMA-SANJO</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 211,\n          \"height\": 26,\n          \"marginOffset\": -10.216999999999999,\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 181,\n          \"y\": 459,\n          \"id\": \"dc78e3e5-1195-4da9-967d-c57719c01048\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 127,\n          \"height\": 27,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 188,\n          \"y\": 460,\n          \"id\": \"ed7be9f2-e1ae-4196-9e1b-a10f3bdfa996\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #374456\\\">Ace Hotel Kyoto</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 113,\n          \"height\": 25,\n          \"marginOffset\": -9.015,\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 226,\n          \"y\": 414,\n          \"width\": 38,\n          \"height\": 38,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"797322a7-6134-41be-81c3-74643f4a80e9\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 240,\n          \"y\": 428,\n          \"id\": \"85dc98f6-314b-4b37-8ea7-a41d69b89bfb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n          \"type\": \"shape\",\n          \"width\": 10,\n          \"height\": 10,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 341,\n          \"y\": 395,\n          \"width\": 24,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"greenCup\" },\n          \"id\": \"fe229179-97dc-421e-844e-fa71747fe45c\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 64,\n          \"y\": 407,\n          \"width\": 24,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"greenCutlery\" },\n          \"id\": \"2584c174-47d2-4efd-bc86-228d4f3b628d\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 74,\n          \"y\": 513,\n          \"width\": 24,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"greenHandBag\" },\n          \"id\": \"ebf94677-3f2d-4128-b0f4-c7cf372f59fe\",\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        },\n        {\n          \"x\": 179,\n          \"y\": 605,\n          \"id\": \"1306def3-30cb-4412-bcd1-59a735454118\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 24,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"greenCup\" },\n          \"groupId\": \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2b8262fa-b89e-42f8-9d48-4e6e7e416ebc\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"797322a7-6134-41be-81c3-74643f4a80e9\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8aceac25-8b75-489a-a1c8-e139cdfc1ab2\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"85dc98f6-314b-4b37-8ea7-a41d69b89bfb\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ddaec139-a55c-4bfd-90d4-13d8c98a6320\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"fe229179-97dc-421e-844e-fa71747fe45c\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"5686e111-96f8-4b83-9a33-31dfa2657e84\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"1306def3-30cb-4412-bcd1-59a735454118\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"067ff6a5-5f51-41d9-a142-7358c97cd3af\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"ebf94677-3f2d-4128-b0f4-c7cf372f59fe\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"8c97e217-972f-4325-a81d-bc7229955772\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"2584c174-47d2-4efd-bc86-228d4f3b628d\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 111, \"g\": 127, \"b\": 148 } },\n      \"type\": \"page\",\n      \"id\": \"1914e9cd-0077-4a81-a7a9-fe4bdf5cd0d4\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"549c8bc9-bfbd-43a7-9ba6-0a7feb16951f\": {\n          \"name\": \"Map\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4e88ac63-e02c-4436-92c4-935b22f0e871\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"3108b6ac-d6a3-464c-b1f2-d853c25edafa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"62d6cdb7-2964-4bdb-bad8-4e2a2b4439f4\",\n          \"x\": 48,\n          \"y\": 6\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Minimal</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Bedrooms</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 70,\n          \"id\": \"810c35ee-8652-4cd2-95bc-8730d8623de1\",\n          \"x\": 48,\n          \"y\": 40\n        },\n        {\n          \"x\": 48,\n          \"y\": 106,\n          \"id\": \"066f7c7f-ba73-4976-8d46-b9fdee662241\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">The bedrooms are classic Ace Hotel meets traditional Japanese, with a twist.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 43,\n          \"marginOffset\": -17.525\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page03_video01.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page03_video01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 26,\n            \"lengthFormatted\": \"0:26\",\n            \"alt\": \"Man waking up in his bed with a great view outside the window.\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#b0aab1\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 46.5,\n          \"y\": 189,\n          \"width\": 319,\n          \"height\": 407,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0aa245e4-6e4c-45fd-a45b-743b4163acf7\"\n        },\n        {\n          \"x\": 182,\n          \"y\": 453,\n          \"id\": \"8bc06f95-963a-4340-9cb7-de463b091329\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 180,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">M</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 150,\n          \"height\": 288,\n          \"marginOffset\": -338.583,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"795eb092-c920-43e8-9577-484d021decce\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"066f7c7f-ba73-4976-8d46-b9fdee662241\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"42c96658-ec4e-414e-8330-63cb83b2e309\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8bc06f95-963a-4340-9cb7-de463b091329\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n      \"type\": \"page\",\n      \"id\": \"0d9f7bf0-6f57-4a60-ba0c-504ed28dc38f\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -7,\n          \"y\": -70,\n          \"width\": 426,\n          \"height\": 758,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a8d7d2f5-0a80-4172-b1c9-6bb123943f6b\",\n          \"scale\": 109,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:03:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page04_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Pillows On A Bed\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d9d7d2\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 0.5,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 18,\n            \"vertical\": 7\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #374456\\\">Turntables and a Japanese soaking tub. A+</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 231,\n          \"height\": 62,\n          \"marginOffset\": -9.015,\n          \"x\": 58,\n          \"y\": 551,\n          \"id\": \"1c545b91-68a9-43da-af81-5c63cc677722\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b6f0beb9-44c0-4dbf-8254-d7e5cd34e29a\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"a8d7d2f5-0a80-4172-b1c9-6bb123943f6b\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"3f68897c-b314-4dd4-a57a-9a977123a718\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"296ef295-f335-4ede-9dcb-59e6b73b1a3b\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d1fcfbd8-286a-4910-80fe-f5f34411dbb2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 418,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ea0f3e8b-cf60-4356-8aab-8cfd49f370d3\",\n          \"x\": 0,\n          \"y\": -58\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">The perfect use of traditional Kimono fabric, Japanese cypress and modern touches in every room.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 256,\n          \"height\": 63,\n          \"marginOffset\": -3.9129999999999967,\n          \"id\": \"38b57f0e-3e70-47d0-87d4-6c190d05079b\",\n          \"x\": 51,\n          \"y\": 536\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:03:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page05_image01.jpg\",\n            \"width\": 240,\n            \"height\": 255,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown stool below brown tabletop with green plant in white pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d6d5d0\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 1,\n          \"y\": 0,\n          \"width\": 205,\n          \"height\": 218,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"70c9bc40-0326-47a2-b18a-a4e682c110d5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:03:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page05_image02.jpg\",\n            \"width\": 240,\n            \"height\": 340,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Gray desk lamp mount on white wall under brown stool with white book on top near wall corner\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d2d4d6\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 208,\n          \"y\": 75,\n          \"width\": 204,\n          \"height\": 285,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"27c7d5d3-7969-46a2-b556-d67c30458cf6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page05_image03.jpg\",\n            \"width\": 330,\n            \"height\": 247,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White vanity sink\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b1aca6\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -115,\n          \"y\": 220,\n          \"width\": 321,\n          \"height\": 272,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"640b76da-8390-42d0-9ca3-6806a8306cb6\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"847d4baa-8b1e-41f1-ab1c-5c658aa7e82c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"27c7d5d3-7969-46a2-b556-d67c30458cf6\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"68ded932-fcf4-4536-8317-49bc5a8b1d4d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"640b76da-8390-42d0-9ca3-6806a8306cb6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f71ec6e6-6c49-4243-8fcf-90d0736cc37b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"70c9bc40-0326-47a2-b18a-a4e682c110d5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n      \"type\": \"page\",\n      \"id\": \"a008d97e-4739-4e43-8739-4b065132f44c\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e8af8f9a-d402-4ac6-8ae6-22ccf259383d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"402d3feb-2211-4453-b72b-d93ec9c6bb62\",\n          \"x\": 48,\n          \"y\": 6,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">THE Korimoto Pool</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 70,\n          \"id\": \"70398854-13bb-4abf-ace8-791209f63479\",\n          \"x\": 48,\n          \"y\": 40,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 106,\n          \"id\": \"61c674ba-d889-4a96-8183-d9fbf2f347ed\",\n          \"content\": \"<span style=\\\"color: #fff\\\">The pool is a modern take on a Japanese onsen meets infinity pool.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 43,\n          \"marginOffset\": -17.525,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-15T09:09:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page06_video01.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page06_video01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 24,\n            \"lengthFormatted\": \"0:24\",\n            \"alt\": \"Attractive man talking to camera - stock video\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#3c3534\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 47,\n          \"y\": 189,\n          \"width\": 319,\n          \"height\": 407,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a8a0aa06-6c9c-44d4-b971-523c4cb9f4af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 180,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 225,\n          \"y\": 454,\n          \"id\": \"ac3d04d8-e41a-46de-8ee6-c7cc0ae90aaf\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">K</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 150,\n          \"height\": 288,\n          \"marginOffset\": -338.583,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a6365348-27cc-425a-8243-9dafe967a272\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ac3d04d8-e41a-46de-8ee6-c7cc0ae90aaf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"0ad66694-8de1-42d8-bca9-d1e11b01b3e6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"61c674ba-d889-4a96-8183-d9fbf2f347ed\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n      \"type\": \"page\",\n      \"id\": \"4d0dd9f4-a221-497c-9265-afb2916dc082\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -86,\n          \"width\": 492,\n          \"height\": 814,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"225b9128-0081-4091-9a00-ed8f23b58d56\",\n          \"type\": \"image\",\n          \"scale\": 107,\n          \"focalX\": 39.980534413938166,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page07_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Swimming in an Infinity Pool\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cecec9\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 213,\n          \"height\": 36,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"519f6416-483c-4785-b928-927c7747984a\",\n          \"x\": 58,\n          \"y\": 551,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 58,\n          \"y\": 573,\n          \"id\": \"74dd496c-0d53-4c5c-b7b8-1d438d38c6e9\",\n          \"width\": 155,\n          \"height\": 36,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"content\": \"<span style=\\\"color: #374456\\\">The use of binchotan</span>\\n<span style=\\\"color: #374456\\\">instead of chlorine</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 46,\n          \"marginOffset\": -9.015,\n          \"id\": \"26a0a8aa-0fd3-40c1-8968-59ad1b526a47\",\n          \"x\": 71,\n          \"y\": 558,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ee13c4b2-81c3-498c-a5e5-6b78dfdff965\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"225b9128-0081-4091-9a00-ed8f23b58d56\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8ceca771-daff-44a4-9758-cd05e8ac8e9d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"847dba7c-d3f5-4a26-8a72-a9591b59cfdd\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8eb62411-9bfc-428e-9e08-babadca3d7f9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page08_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown Lounge Chair on Side of Swimming Pool\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#91a4d7\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 529,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e005bbfc-4971-45eb-95a5-fa68dd180077\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 468,\n          \"width\": 412,\n          \"height\": 219,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8a4db622-e27e-4c4c-9e03-f0ba43c70aa2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">The views of “new” Kyoto are unparalleled from the rooftop pool, where you can lounge, plan your day’s activities or grab a refreshing drink.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 295,\n          \"height\": 82,\n          \"marginOffset\": -3.9129999999999967,\n          \"id\": \"a005ce30-6798-4b35-b58c-de026b05c63b\",\n          \"x\": 51,\n          \"y\": 493,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 206,\n          \"y\": 596,\n          \"width\": 206,\n          \"height\": 79,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"630c4b1f-d936-4cdc-86b3-a061c7eb3102\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"889a05dc-7f8b-46cb-a659-01cc47cba23b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a005ce30-6798-4b35-b58c-de026b05c63b\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2a7b70a5-de9c-44e1-a2fc-0df9fbd41b4f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"630c4b1f-d936-4cdc-86b3-a061c7eb3102\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n      \"type\": \"page\",\n      \"id\": \"19705bc4-77cc-4137-b6c8-e83175cbe3e4\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"25ed3508-dda0-4563-822e-bfeccf5fd423\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em\\\">3.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"33fded58-58cf-414f-8a99-5e96902f3c83\",\n          \"x\": 48,\n          \"y\": 6,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Akurimei</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Gym</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 70,\n          \"id\": \"ca6faece-0ba9-44a6-bf36-71b0f2fda8a9\",\n          \"x\": 48,\n          \"y\": 40,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 106,\n          \"id\": \"56014d69-45f9-41d2-bdb6-8a26bff358ab\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Not your average hotel gym. </span>\\n<span style=\\\"color: #fff\\\">Not even close.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 43,\n          \"marginOffset\": -17.525,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-15T09:09:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page06_video01.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page06_video01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 24,\n            \"lengthFormatted\": \"0:24\",\n            \"alt\": \"Attractive man talking to camera - stock video\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#3c3534\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"x\": 47,\n          \"y\": 189,\n          \"width\": 319,\n          \"height\": 407,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"50543b0e-dc38-47ba-96b6-6b6390ba6084\",\n          \"type\": \"video\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 180,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 227,\n          \"y\": 454,\n          \"id\": \"b4257d95-bfec-4e61-ac95-212c3bb41ac4\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">A</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 150,\n          \"height\": 288,\n          \"marginOffset\": -338.583,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5abd4494-c9e7-471f-965e-11b4b4d765ca\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b4257d95-bfec-4e61-ac95-212c3bb41ac4\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"ea7e1576-3c57-470a-8b27-0d927174fd77\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"56014d69-45f9-41d2-bdb6-8a26bff358ab\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n      \"type\": \"page\",\n      \"id\": \"6fc8e3d7-8c40-4fec-9545-2658faf045ef\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -1,\n          \"y\": -58,\n          \"width\": 414,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cd052ba0-9221-4628-992c-97d336598045\",\n          \"type\": \"image\",\n          \"scale\": 106,\n          \"focalX\": 55.61990806866536,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page10_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown Wooden Shelf With Assorted Items\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#333331\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 0.5,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 18,\n            \"vertical\": 7\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #374456\\\">All the things you’d see in a Western gym plus</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 231,\n          \"height\": 61,\n          \"marginOffset\": -9.015,\n          \"x\": 58,\n          \"y\": 551,\n          \"id\": \"0e4a5d78-5ae1-4e9b-9bca-dcc1fb005264\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"decca973-80e3-4cad-ac8e-235aa790ae34\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"cd052ba0-9221-4628-992c-97d336598045\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"802ddf6d-1414-4b26-af96-68759313b435\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"3140c39b-0e4e-45a5-96df-725241536f3d\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2a905321-a75a-429b-b03b-7a91158fa600\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 88, \"b\": 77 } },\n          \"width\": 412,\n          \"height\": 418,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e927c316-13ba-40d7-a489-43ad1c5e2750\",\n          \"x\": 0,\n          \"y\": -58,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">You’ll see traditional weights and pilates balls, but this is intentionally mixed with more Japanese machinery and workout props meant to relax and strengthen.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 82,\n          \"marginOffset\": -3.9129999999999967,\n          \"id\": \"2cf1a0c7-cc8d-415f-af76-16a05ba2c198\",\n          \"x\": 51,\n          \"y\": 536,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page11_image01.jpg\",\n            \"width\": 240,\n            \"height\": 255,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"A Romantic Setting In The Bathroom\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a48975\",\n            \"isExternal\": true\n          },\n          \"x\": 1,\n          \"y\": -1,\n          \"width\": 205,\n          \"height\": 218,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f6ba7266-5f18-4ba0-9749-3bfb1e39bc83\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page11_image02.jpg\",\n            \"width\": 240,\n            \"height\": 340,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown Wooden Shelf With Assorted Items\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b2a28\",\n            \"isExternal\": true\n          },\n          \"x\": 209,\n          \"y\": 75,\n          \"width\": 204,\n          \"height\": 285,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"77afc476-cffc-48d7-8c03-4b5b9d95f1fc\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page11_image03.jpg\",\n            \"width\": 240,\n            \"height\": 340,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Doing Pull-Ups\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b1f1d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 221,\n          \"width\": 206,\n          \"height\": 282,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c13d2c85-a9fc-4cfb-9cf2-0d501cdc6dc1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a3137a60-02b2-4803-b559-79ce9a7bbfd5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"77afc476-cffc-48d7-8c03-4b5b9d95f1fc\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1104f0e9-ab94-42ea-aaa4-0ab95d7f0527\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c13d2c85-a9fc-4cfb-9cf2-0d501cdc6dc1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"121a283f-5a3d-41e4-b35a-b9daa4d2f627\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f6ba7266-5f18-4ba0-9749-3bfb1e39bc83\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n      \"type\": \"page\",\n      \"id\": \"9914352b-7eb7-4e16-abe5-8807b7d88317\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c0a438bd-a794-4bd7-8847-7cb5798eae0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Perfect use of traditional Kimono fabric.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 43,\n          \"marginOffset\": -3.9129999999999967,\n          \"id\": \"4647ea8a-684a-49b1-9812-14cadff005aa\",\n          \"x\": 69,\n          \"y\": 173,\n          \"groupId\": \"7c547b2d-3425-42ca-a2e2-9094d8e78aa4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #374456; text-transform: uppercase\\\">YOJIYA</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 71,\n          \"height\": 26,\n          \"marginOffset\": -3.9129999999999967,\n          \"id\": \"c99b1739-6393-4782-9ae9-1006a3bfa158\",\n          \"x\": 61,\n          \"y\": 142,\n          \"groupId\": \"7c547b2d-3425-42ca-a2e2-9094d8e78aa4\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">List Of Best Things To DO In The Area:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 215,\n          \"height\": 45,\n          \"type\": \"text\",\n          \"id\": \"55b0af73-b5d6-44e2-b88c-3fe3df0d9466\",\n          \"x\": 61,\n          \"y\": 3,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 6,\n            \"vertical\": 1\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #374456; text-transform: uppercase\\\">Kyoto distillery</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 153,\n          \"height\": 28,\n          \"marginOffset\": -10.216999999999999,\n          \"x\": 61,\n          \"y\": 275,\n          \"groupId\": \"ea188731-c024-4eb1-a52a-97cc326e1204\",\n          \"tagName\": \"h3\",\n          \"id\": \"8bac226e-2548-4c25-9c93-776fe61b5d39\"\n        },\n        {\n          \"x\": 69,\n          \"y\": 303,\n          \"id\": \"389e14ce-287b-44b6-9e92-de67fecc6c52\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Local whiskey as well as a few beers on tap.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 221,\n          \"height\": 45,\n          \"marginOffset\": -3.9129999999999967,\n          \"groupId\": \"ea188731-c024-4eb1-a52a-97cc326e1204\"\n        },\n        {\n          \"x\": 61,\n          \"y\": 402,\n          \"id\": \"b7ebec19-a9c6-495f-9a82-a6e15c84ca0f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 99,\n          \"height\": 27,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"59963d38-3472-45c2-8518-2afa53d82ca3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 6,\n            \"vertical\": 1\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #374456; text-transform: uppercase\\\">karakami</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 99,\n          \"height\": 28,\n          \"marginOffset\": -10.216999999999999,\n          \"x\": 60,\n          \"y\": 404,\n          \"groupId\": \"59963d38-3472-45c2-8518-2afa53d82ca3\",\n          \"tagName\": \"h3\",\n          \"id\": \"6a2f2fe0-bf86-49be-96e1-0d617b5480aa\"\n        },\n        {\n          \"x\": 69,\n          \"y\": 433,\n          \"id\": \"cf5994e4-ab40-4597-86de-ce177f3517b4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Traditional papers are great for wrapping all your gifts.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 221,\n          \"height\": 43,\n          \"marginOffset\": -3.9129999999999967,\n          \"groupId\": \"59963d38-3472-45c2-8518-2afa53d82ca3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c06536f6-0cd8-45ca-a26a-4dd6164223ac\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4647ea8a-684a-49b1-9812-14cadff005aa\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"90963eec-7c88-4f58-9ba2-151304f43715\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c99b1739-6393-4782-9ae9-1006a3bfa158\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"449d442a-c84c-4deb-8a63-17221b37cc8a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"389e14ce-287b-44b6-9e92-de67fecc6c52\"],\n          \"duration\": 1000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"c1a36b1d-f851-43c6-ab4c-26fd703d33d3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cf5994e4-ab40-4597-86de-ce177f3517b4\"],\n          \"duration\": 1000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"c95a00b2-17c8-4e16-8e85-c2e23bb718f5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b7ebec19-a9c6-495f-9a82-a6e15c84ca0f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"8bac226e-2548-4c25-9c93-776fe61b5d39\"],\n          \"id\": \"6f84ec42-874a-4f8b-a560-57adbbf51d79\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"6a2f2fe0-bf86-49be-96e1-0d617b5480aa\"],\n          \"id\": \"72ac8bbc-0bf1-4441-b001-6efc4fa1a14b\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 55, \"g\": 68, \"b\": 86 } },\n      \"type\": \"page\",\n      \"id\": \"29db91a3-3d12-48f3-9594-2da9d1b5d4e0\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"7c547b2d-3425-42ca-a2e2-9094d8e78aa4\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ea188731-c024-4eb1-a52a-97cc326e1204\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"59963d38-3472-45c2-8518-2afa53d82ca3\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a08dcd13-f73f-4305-a2ad-5f31445ebc80\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Next Review</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 215,\n          \"height\": 29,\n          \"id\": \"d3b8dc1d-4fbb-4444-87bd-63c3a468e1ed\",\n          \"x\": 68,\n          \"y\": 3,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 68,\n          \"y\": 84,\n          \"id\": \"011d843e-66a6-49c2-b00a-c20d7929f2f7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">Hotel</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">Las Arenas,</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.11em; text-transform: uppercase\\\">Valencia</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 215,\n          \"height\": 95,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T05:04:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ace-hotel-kyoto-review/page13_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Empty Balcony Near Beach\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#312925\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -75,\n          \"y\": 292,\n          \"width\": 493,\n          \"height\": 450,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a9fd462f-c2d7-41e6-b0ec-1f7d53c32d31\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 180,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">V</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 150,\n          \"height\": 288,\n          \"marginOffset\": -338.583,\n          \"type\": \"text\",\n          \"id\": \"dcb28936-1d06-4c08-9041-2bca836f784f\",\n          \"x\": 68,\n          \"y\": 169,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1a045f74-6319-4123-87d0-017609144b96\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dcb28936-1d06-4c08-9041-2bca836f784f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"97ff967b-16e7-4b39-8fe9-a2b41a9b4849\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"011d843e-66a6-49c2-b00a-c20d7929f2f7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"f2170217-9ff2-49d8-8c46-7717b5b5b428\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/album-releases/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/album-releases/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'album-releases',\n  creationDate: '2021-06-28T00:00:00.000Z',\n  title: _x('Album Releases', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Music', 'template keyword', 'web-stories'),\n    _x('Album', 'template keyword', 'web-stories'),\n    _x('Trending', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Hot Orange', 'color', 'web-stories'),\n      color: '#f7722f',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Peach Bisque', 'color', 'web-stories'),\n      color: '#fee2c6',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Champagne Yellow', 'color', 'web-stories'),\n      color: '#f4e6b0',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cola Brown', 'color', 'web-stories'),\n      color: '#3d3225',\n      family: _x('Brown', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its raw typography and mesmerizing visual elements, the Album Releases template will let you create listicles that engage. Switch the colors and make it your own.',\n    'web-stories'\n  ),\n  vertical: _x('Music', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/album-releases/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/album-releases/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a87a2024-2d96-4406-9abc-204da98b3f73\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 49,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #f7722f\\\">Top 5 most Anticipated Album Releases for Fall</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 198,\n          \"id\": \"15076563-0ade-484e-999a-aecabb0ec31e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">By: Marco Carola</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 205,\n          \"width\": 200,\n          \"height\": 24,\n          \"id\": \"2813cfb7-ec17-411f-963e-bd038b45d9c7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#101632\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page01_image1.jpg\",\n            \"width\": 330,\n            \"height\": 369,\n            \"id\": 0,\n            \"alt\": \"page01_image1\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 270,\n          \"width\": 366,\n          \"height\": 409,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8ce9bdf4-f6f1-4045-a288-eb90dd64aaf7\",\n          \"borderRadius\": {\n            \"topLeft\": 11,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 32, \"b\": 54 } },\n      \"type\": \"page\",\n      \"id\": \"eff1d1ce-14d8-454c-a770-2cdf0d3c154f\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"8f266374-7964-4f5f-b3b7-cf61f02c6df0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -185.5,\n          \"y\": -64,\n          \"width\": 783,\n          \"height\": 746,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"d8c4e07a-9722-4faf-8d28-6bb6e12f5fd8\",\n          \"scale\": 119,\n          \"focalX\": 48.92911710138601,\n          \"focalY\": 48.124249699879954,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">There is so much to look forward to this Fall, from the latest hip-hop release by United World Records to genres you didn't even know existed.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 203,\n          \"width\": 316,\n          \"height\": 186,\n          \"id\": \"a8e8b431-4927-4128-9fb1-9a236bf364b4\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 32, \"b\": 54 } },\n      \"type\": \"page\",\n      \"id\": \"ba8f61d1-d6d2-463f-9d02-cc95560a1a31\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"8f266374-7964-4f5f-b3b7-cf61f02c6df0\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"11ef0ff2-7ece-45b6-b2ff-64736e54ce84\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-26T07:13:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -27.5,\n          \"y\": -82,\n          \"width\": 467,\n          \"height\": 444,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0cc7a75b-97ea-4e05-8175-8619710e4711\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page03_image1.jpg\",\n            \"width\": 316,\n            \"height\": 316,\n            \"id\": 0,\n            \"alt\": \"page03_image1\",\n            \"isExternal\": true,\n            \"baseColor\": \"#0c0d14\",\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 46,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 316,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"936c6c02-fa80-41f2-9bf1-4ae9e38c56bc\",\n          \"borderRadius\": {\n            \"topLeft\": 11,\n            \"topRight\": 11,\n            \"bottomRight\": 11,\n            \"bottomLeft\": 11,\n            \"locked\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f7722f\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 30,\n          \"id\": \"48f1a8fc-827f-4bd7-ac0a-ed55096e7b78\",\n          \"x\": 194,\n          \"y\": 350\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #f7722f; text-transform: uppercase\\\">Travis</span>\\n<span style=\\\"font-weight: 900; color: #f7722f; text-transform: uppercase\\\">Travis</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 50,\n          \"y\": 359,\n          \"width\": 315,\n          \"height\": 152,\n          \"id\": \"21504a29-21d8-4674-80c4-156ee7dbbd13\",\n          \"marginOffset\": -33.45600000000001,\n          \"groupId\": \"c45c4c27-b9c6-4fb5-95e7-6292b90a8bd5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">The Travis</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 153,\n          \"y\": 519,\n          \"width\": 103,\n          \"height\": 35,\n          \"id\": \"530b11bf-555b-47bb-8d3c-cb2d72dc9169\",\n          \"groupId\": \"c45c4c27-b9c6-4fb5-95e7-6292b90a8bd5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 24,\n          \"id\": \"1259e77a-6aca-4f1e-b9b1-7538938e4f74\",\n          \"x\": 183,\n          \"y\": 550,\n          \"groupId\": \"c45c4c27-b9c6-4fb5-95e7-6292b90a8bd5\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"14c952b8-14a5-470c-8f43-327cf982a006\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"936c6c02-fa80-41f2-9bf1-4ae9e38c56bc\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 32, \"b\": 54 } },\n      \"type\": \"page\",\n      \"id\": \"d9dbb504-256d-4641-89e0-4912eacf3b68\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"c45c4c27-b9c6-4fb5-95e7-6292b90a8bd5\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 110,\n          \"y\": 5,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c5b51ca8-0299-4799-a96f-504df4c40e7d\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page04_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page04_image1\",\n            \"baseColor\": \"#1a3243\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\",\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"width\": 991,\n          \"height\": 943,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a99a598c-91af-4406-a409-2747b117bf12\",\n          \"x\": -290.5,\n          \"y\": 397.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f7722f\\\">Travis Travis' full length album will be released this November. Mixing hip-hop with lo-fi and ambient genres, this album is set to satisfy his original fanbase.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 348,\n          \"width\": 316,\n          \"height\": 211,\n          \"id\": \"aa0a3a83-2b78-4368-bb2d-2eba6ceb3cf7\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"585e770d-0484-4d54-a291-093f4956bfb9\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"c5b51ca8-0299-4799-a96f-504df4c40e7d\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 32, \"b\": 54 } },\n      \"type\": \"page\",\n      \"id\": \"d5582e2a-be27-4a3b-9182-0f60701ead66\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e0c5e1de-24fd-4ed5-bc2a-652901ef1cd3\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 119,\n          \"y\": 101,\n          \"width\": 131,\n          \"height\": 234,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"b0e39a74-727e-40d8-9222-c38a69a15b46\",\n          \"scale\": 109,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-19T10:28:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page05_image1.jpg\",\n            \"width\": 131,\n            \"height\": 234,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page05_image1\",\n            \"baseColor\": \"#2e3b4b\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Moongazing</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 57,\n          \"width\": 315,\n          \"height\": 68,\n          \"id\": \"b42d0c60-2d97-48b9-a2c2-c1590e06d308\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -11,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Permanent Marker\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 1136,\n              \"des\": -325,\n              \"tAsc\": 622,\n              \"tDes\": -61,\n              \"tLGap\": 61,\n              \"wAsc\": 1136,\n              \"wDes\": 325,\n              \"xH\": 625,\n              \"capH\": 758,\n              \"yMin\": -325,\n              \"yMax\": 1136,\n              \"hAsc\": 1136,\n              \"hDes\": -325,\n              \"lGap\": 31\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f7722f; letter-spacing: 0.1em; text-transform: uppercase\\\">Can't wait</span>\\n<span style=\\\"color: #f7722f; letter-spacing: 0.1em; text-transform: uppercase\\\">to listen to</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 43,\n          \"y\": 23,\n          \"width\": 237,\n          \"height\": 49,\n          \"id\": \"25fe8c57-ea9b-456a-8994-990fd995275f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">A single from the album conjures his grandmother's poetry, which he remembers from childhood trips traveling through Texas with her.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 51,\n          \"y\": 447,\n          \"width\": 321,\n          \"height\": 116,\n          \"id\": \"143d6b1d-a740-4553-91f1-59e43f1f5783\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ed8efb23-8b32-4751-8f03-7b28471364fe\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"25fe8c57-ea9b-456a-8994-990fd995275f\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8f6f4764-71a6-4fb9-a568-4a0a9e20baa6\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"b0e39a74-727e-40d8-9222-c38a69a15b46\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"31846961-c9bb-493a-bc80-c30a40188716\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e62fbb5e-574c-49f3-ba5b-287e40f79568\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"52792a53-0e06-4ad9-bdd1-1d6692b53b59\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-26T07:13:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"width\": 467,\n          \"height\": 444,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8b25f662-0591-4482-b901-feb11b07e6fb\",\n          \"x\": -27.5,\n          \"y\": -82,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 316,\n          \"scale\": 152,\n          \"focalX\": 54.39883258953343,\n          \"focalY\": 57.122253957995575,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5aad802a-b40d-4fc8-a917-928c3579a145\",\n          \"borderRadius\": {\n            \"topLeft\": 11,\n            \"topRight\": 11,\n            \"bottomRight\": 11,\n            \"bottomLeft\": 11,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-30T12:43:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page06_image1.jpg\",\n            \"width\": 374,\n            \"height\": 249,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page06_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#121319\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3d3225\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 30,\n          \"id\": \"4e4f1657-b3d1-482b-94a3-1ae032550d4f\",\n          \"x\": 196,\n          \"y\": 350,\n          \"type\": \"text\",\n          \"groupId\": \"ee199a09-f665-4161-a5f2-0592e8820fa1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #3d3225; text-transform: uppercase\\\">Ariana</span>\\n<span style=\\\"font-weight: 900; color: #3d3225; text-transform: uppercase\\\">Ariana</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 360,\n          \"width\": 317,\n          \"height\": 153,\n          \"id\": \"9e67906a-41c6-40a5-8f94-f24b64a7ff42\",\n          \"type\": \"text\",\n          \"groupId\": \"ee199a09-f665-4161-a5f2-0592e8820fa1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(61,50,37,0.8)\\\">Sweetener</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 151,\n          \"y\": 519,\n          \"width\": 109,\n          \"height\": 35,\n          \"id\": \"14568c79-34cb-434f-a704-183144026ea9\",\n          \"type\": \"text\",\n          \"groupId\": \"ee199a09-f665-4161-a5f2-0592e8820fa1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(61,50,37,0.8)\\\">2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 24,\n          \"id\": \"6a034b77-e600-49f2-8452-5093f4e43595\",\n          \"x\": 185,\n          \"y\": 550,\n          \"type\": \"text\",\n          \"groupId\": \"ee199a09-f665-4161-a5f2-0592e8820fa1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"292cf925-5c64-4d9a-927f-23f7bc7c89bd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5aad802a-b40d-4fc8-a917-928c3579a145\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 223, \"g\": 185, \"b\": 149 } },\n      \"type\": \"page\",\n      \"id\": \"0fe270f2-e036-4c0d-ba0d-fbaec4962362\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"ee199a09-f665-4161-a5f2-0592e8820fa1\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"93d3893d-4cb2-4acb-a244-c5b32ccfa9ed\",\n          \"scale\": 118,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-19T10:32:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page07_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page07_image1\",\n            \"baseColor\": \"#2f2125\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\",\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"width\": 991,\n          \"height\": 943,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e5cd5289-1c22-4e6a-a82e-36ac37c513d2\",\n          \"x\": -289.5,\n          \"y\": 411.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">Ariana's 6th album release is expected this October. Having leaked her last 2 albums, it's unclear what fans can expect from the artist and her next album release.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 211,\n          \"id\": \"beac2df8-847c-471a-be2b-5c28272047da\",\n          \"x\": 48,\n          \"y\": 354,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"22fa6207-4adf-4ee6-a70d-e3460d9df89a\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"93d3893d-4cb2-4acb-a244-c5b32ccfa9ed\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e3886fad-695f-43cc-989f-52556bb58cae\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"58b939dc-b59d-404e-9763-e4800104563f\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f14c3425-f459-4b1c-8b19-a78f1d266e75\",\n          \"type\": \"image\",\n          \"scale\": 109,\n          \"focalX\": 33.020833333333336,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page08_image1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"page08_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ae8f7d\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 50, \"g\": 37, \"b\": 24, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">5 Rings</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 67,\n          \"width\": 315,\n          \"height\": 68,\n          \"id\": \"87cc3529-72b2-4fa9-bb1f-f7da4e5edbed\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -11,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Permanent Marker\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 1136,\n              \"des\": -325,\n              \"tAsc\": 622,\n              \"tDes\": -61,\n              \"tLGap\": 61,\n              \"wAsc\": 1136,\n              \"wDes\": 325,\n              \"xH\": 625,\n              \"capH\": 758,\n              \"yMin\": -325,\n              \"yMax\": 1136,\n              \"hAsc\": 1136,\n              \"hDes\": -325,\n              \"lGap\": 31\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fee2c6; letter-spacing: 0.1em; text-transform: uppercase\\\">Can't wait</span>\\n<span style=\\\"color: #fee2c6; letter-spacing: 0.1em; text-transform: uppercase\\\">to listen to</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 37,\n          \"y\": 32,\n          \"width\": 218,\n          \"height\": 49,\n          \"id\": \"42ecd9a6-7d87-48ae-b4e5-c65b6d59429f\",\n          \"type\": \"text\",\n          \"marginOffset\": -8.53515625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">Already a single that has topped the charts from her latest album. More hits coming right up.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 491,\n          \"width\": 310,\n          \"height\": 74,\n          \"id\": \"7ec57319-100b-429e-ae11-fd0b97454698\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9343a994-cb5e-4acd-a72f-633070260b8f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"42ecd9a6-7d87-48ae-b4e5-c65b6d59429f\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"bf27647d-20da-478f-870b-cf55776f9504\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"f14c3425-f459-4b1c-8b19-a78f1d266e75\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"60ce8825-26f3-4422-a7a9-e70f78d837cc\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"1899b726-b36a-4990-86c8-9747fb2e5c08\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2919e860-b917-44a2-b381-1e5b3e9a24ef\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-26T07:13:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"width\": 467,\n          \"height\": 444,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0cbfcc06-9e54-4dc3-9f0b-4ba94bfb4e32\",\n          \"x\": -27.5,\n          \"y\": -82,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 316,\n          \"scale\": 179,\n          \"focalX\": 50,\n          \"focalY\": 49.97976726425704,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"584af732-596b-4f36-a8a6-775761af4472\",\n          \"borderRadius\": {\n            \"topLeft\": 11,\n            \"topRight\": 11,\n            \"bottomRight\": 11,\n            \"bottomLeft\": 11,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-30T12:43:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page09_image1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page09_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#292519\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f4e6b0\\\">3.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 30,\n          \"id\": \"55769b1d-a9a4-41b2-b59a-c26bb9542f0e\",\n          \"x\": 196,\n          \"y\": 350,\n          \"type\": \"text\",\n          \"groupId\": \"14ed837d-1653-4efa-bb7c-c777a1b57766\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #f4e6b0; text-transform: uppercase\\\">Teyana</span>\\n<span style=\\\"font-weight: 900; color: #f4e6b0; text-transform: uppercase\\\">Teyana</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 361,\n          \"width\": 317,\n          \"height\": 153,\n          \"id\": \"9cc25d56-e8f5-4568-8fcb-ae8a690f36bd\",\n          \"type\": \"text\",\n          \"groupId\": \"14ed837d-1653-4efa-bb7c-c777a1b57766\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">K.T.S.E</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 151,\n          \"y\": 519,\n          \"width\": 109,\n          \"height\": 35,\n          \"id\": \"57044f15-8f86-432a-8cd6-dbf808ce8a03\",\n          \"type\": \"text\",\n          \"groupId\": \"14ed837d-1653-4efa-bb7c-c777a1b57766\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 24,\n          \"id\": \"e8ce1801-48bb-4818-a733-dd68475c479a\",\n          \"x\": 185,\n          \"y\": 550,\n          \"type\": \"text\",\n          \"groupId\": \"14ed837d-1653-4efa-bb7c-c777a1b57766\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"55b31a08-c71a-4cd6-8f84-514d153a89a1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"584af732-596b-4f36-a8a6-775761af4472\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 25, \"g\": 43, \"b\": 49 } },\n      \"type\": \"page\",\n      \"id\": \"eb00917e-1f2f-40d0-a8d4-a78c4e6b1274\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"14ed837d-1653-4efa-bb7c-c777a1b57766\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"eaf548d4-6a37-4458-b9ba-17bc1e55fd35\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-19T15:07:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page10_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image1\",\n            \"baseColor\": \"#8e8981\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\",\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"width\": 991,\n          \"height\": 943,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d54e6eef-c8c8-46a8-b673-969920b7ed71\",\n          \"x\": -289.5,\n          \"y\": 412.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f4e6b0\\\">Teyana's music is made to move you. Influences from legendary R&amp;B singers of the 80s, her music sounds soothingly familiar but with a modern twist. &nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 211,\n          \"id\": \"30e0117e-0b3e-4f60-b564-4b6e059a341b\",\n          \"x\": 48,\n          \"y\": 354,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9670bdf5-0262-4baa-bb3f-86650fb40923\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"eaf548d4-6a37-4458-b9ba-17bc1e55fd35\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f4ec2dd8-2edc-47aa-97af-b884a62ad77a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"a05807ee-5090-4aa2-90f2-8e899d080aa9\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"2dfcbdeb-6d63-4650-88ec-27bfbbe32938\",\n          \"type\": \"image\",\n          \"scale\": 109,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page11_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page11_image1\",\n            \"baseColor\": \"#6b6a68\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Going</span>\\n<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">West</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 57,\n          \"width\": 315,\n          \"height\": 103,\n          \"id\": \"8e967863-0da9-4f8c-8f9d-8af0da14075b\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -11,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Permanent Marker\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 1136,\n              \"des\": -325,\n              \"tAsc\": 622,\n              \"tDes\": -61,\n              \"tLGap\": 61,\n              \"wAsc\": 1136,\n              \"wDes\": 325,\n              \"xH\": 625,\n              \"capH\": 758,\n              \"yMin\": -325,\n              \"yMax\": 1136,\n              \"hAsc\": 1136,\n              \"hDes\": -325,\n              \"lGap\": 31\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f4e6b0; letter-spacing: 0.1em; text-transform: uppercase\\\">Top 10</span>\\n<span style=\\\"color: #f4e6b0; letter-spacing: 0.1em; text-transform: uppercase\\\">Dancers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 38,\n          \"y\": 21,\n          \"width\": 227,\n          \"height\": 49,\n          \"id\": \"66019f08-0bf4-41c4-bbed-523bf3d88721\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f4e6b0\\\">She's been able to catch the attention of the right people in the music industry and this is her tribute.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 469,\n          \"width\": 316,\n          \"height\": 95,\n          \"id\": \"4d0bc3ad-7b91-4449-be8d-53f19f640fc4\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"582fee31-e323-468c-8d63-28774e5b52a2\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"66019f08-0bf4-41c4-bbed-523bf3d88721\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"51d32f0a-d8cf-4c21-acd9-d41167e0b45a\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"2dfcbdeb-6d63-4650-88ec-27bfbbe32938\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8d19a3ef-cec0-4741-be77-f7910ebfa51c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8ecdb58d-3192-47e7-b2e7-896b2d0af033\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"393d5a6d-ca62-4f1b-ac59-d9564abfe183\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-26T07:13:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"width\": 467,\n          \"height\": 444,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c0b46049-38f2-466c-b317-18df5b3d1ddf\",\n          \"x\": -27.5,\n          \"y\": -82,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">4.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 30,\n          \"id\": \"42e6fd19-b453-4cfb-a9ef-976c3f187c8c\",\n          \"x\": 196,\n          \"y\": 350,\n          \"type\": \"text\",\n          \"groupId\": \"a748016b-6b98-43e2-b85c-e21038ae39b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 75,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fee2c6; text-transform: uppercase\\\">Justin</span>\\n<span style=\\\"font-weight: 900; color: #fee2c6; text-transform: uppercase\\\">Barber</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 360,\n          \"width\": 317,\n          \"height\": 153,\n          \"id\": \"d6bbd44f-da8d-46aa-a719-6bf5cb6c3c6b\",\n          \"type\": \"text\",\n          \"groupId\": \"a748016b-6b98-43e2-b85c-e21038ae39b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Changes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 151,\n          \"y\": 519,\n          \"width\": 109,\n          \"height\": 35,\n          \"id\": \"07c86374-b042-4660-b212-b2627f845d6c\",\n          \"type\": \"text\",\n          \"groupId\": \"a748016b-6b98-43e2-b85c-e21038ae39b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 24,\n          \"id\": \"8a6b264d-f57d-4835-8084-d7c6ab904466\",\n          \"x\": 185,\n          \"y\": 550,\n          \"type\": \"text\",\n          \"groupId\": \"a748016b-6b98-43e2-b85c-e21038ae39b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 316,\n          \"scale\": 193,\n          \"focalX\": 59.919012034037976,\n          \"focalY\": 52.905438395217196,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1bab9ba1-224b-4c1b-b48f-8a90dc28b72a\",\n          \"borderRadius\": {\n            \"topLeft\": 11,\n            \"topRight\": 11,\n            \"bottomRight\": 11,\n            \"bottomLeft\": 11,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-30T12:43:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page15_image1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page15_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#663636\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e5a9473e-ce1c-41a9-b496-8c0192dd04e0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1bab9ba1-224b-4c1b-b48f-8a90dc28b72a\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 23, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"c0864782-cc25-4f04-bbd8-633e2b4ac38f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a748016b-6b98-43e2-b85c-e21038ae39b0\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7399fbc5-00b2-480a-a5e4-5975ada8c9d1\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page16_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page16_image1\",\n            \"baseColor\": \"#73707d\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/sticker_sound.png\",\n            \"width\": 330,\n            \"height\": 314,\n            \"id\": 0,\n            \"alt\": \"sticker_sound\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"width\": 991,\n          \"height\": 943,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e6b8257c-fc13-4af9-b899-78e002b6297d\",\n          \"x\": -289.5,\n          \"y\": 413.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">Always keeping things exciting, Barber opts for even more collaborations with established and rising artists on his forthcoming album.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 183,\n          \"id\": \"7295ae08-99ad-4121-8e2d-d3af5168b95f\",\n          \"x\": 48,\n          \"y\": 386,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8e001318-e10f-4b9a-9da2-a91290e4bac6\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"7399fbc5-00b2-480a-a5e4-5975ada8c9d1\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"55dfbb6b-afbd-4787-9ca8-1c90e6e40650\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"2f709f3f-4120-4fde-9068-983f77b8c753\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4e3bb4e5-d99c-449d-8c00-28566ecd3fdb\",\n          \"type\": \"image\",\n          \"scale\": 107,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page17_image1.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page17_image1\",\n            \"baseColor\": \"#6a364e\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Pink</span>\\n<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Sweater</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 61,\n          \"width\": 315,\n          \"height\": 103,\n          \"id\": \"a532098d-7c38-4a95-8acc-99b1aecfea76\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 345,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Permanent Marker\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 1136,\n              \"des\": -325,\n              \"tAsc\": 622,\n              \"tDes\": -61,\n              \"tLGap\": 61,\n              \"wAsc\": 1136,\n              \"wDes\": 325,\n              \"xH\": 625,\n              \"capH\": 758,\n              \"yMin\": -325,\n              \"yMax\": 1136,\n              \"hAsc\": 1136,\n              \"hDes\": -325,\n              \"lGap\": 31\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fee2c6; letter-spacing: 0.1em; text-transform: uppercase\\\">That's</span>\\n<span style=\\\"color: #fee2c6; letter-spacing: 0.1em; text-transform: uppercase\\\">Flow!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 34,\n          \"y\": 28,\n          \"width\": 172,\n          \"height\": 49,\n          \"id\": \"513899a1-21cc-44dc-8fa4-49f379d6e0e9\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">The song samples some of the greatest Jazz tracks of all time. Naturally, we see Barber collaborating on this track with the best and brightest hip hop newcomers.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 425,\n          \"width\": 316,\n          \"height\": 137,\n          \"id\": \"0d87c15d-0c0e-4806-a469-f72a57593bca\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c8ecf35e-8f70-4f69-a772-b8060d5f444b\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"513899a1-21cc-44dc-8fa4-49f379d6e0e9\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"022a5904-d6e9-44b6-95c5-84a302c35714\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"4e3bb4e5-d99c-449d-8c00-28566ecd3fdb\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"73a54749-45bb-4fab-80a3-c6aa4a9d164f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"aa014c03-c406-451b-8b18-0f2fce008b43\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c5bdf331-8cb4-49e8-ada0-2b72a16aec9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">What's</span>\\n<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Next?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 166,\n          \"height\": 103,\n          \"type\": \"text\",\n          \"id\": \"55b718d7-5953-4f81-adad-6c5b6cf3b87a\",\n          \"x\": 122,\n          \"y\": 10\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/album-releases/page19_image1.jpg\",\n            \"width\": 316,\n            \"height\": 255,\n            \"id\": 0,\n            \"alt\": \"page19_image1\",\n            \"isExternal\": true,\n            \"baseColor\": \"#3f3739\",\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 149,\n          \"width\": 316,\n          \"height\": 255,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9e8f0682-b345-4752-a6f1-f13eb2e98a26\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Darker Grotesque\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1060,\n              \"des\": -296,\n              \"tAsc\": 1060,\n              \"tDes\": -296,\n              \"tLGap\": 0,\n              \"wAsc\": 1060,\n              \"wDes\": 296,\n              \"xH\": 406,\n              \"capH\": 563,\n              \"yMin\": -296,\n              \"yMax\": 1060,\n              \"hAsc\": 1060,\n              \"hDes\": -296,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fee2c6\\\">Top 5 hip hop tracks of all time</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 166,\n          \"height\": 58,\n          \"type\": \"text\",\n          \"id\": \"35202050-6f6b-42c1-a6cb-5979366a58d3\",\n          \"x\": 123,\n          \"y\": 453\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 226, \"b\": 198 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 29,\n            \"vertical\": 17\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #3d3225\\\">Click to play story</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 7,\n            \"topRight\": 7,\n            \"bottomRight\": 7,\n            \"bottomLeft\": 7\n          },\n          \"x\": 112,\n          \"y\": 520,\n          \"width\": 185,\n          \"height\": 50,\n          \"id\": \"b9580080-aa79-486f-a97a-b06fc55f82d8\",\n          \"marginOffset\": -0.1738636363636381,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": null\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4275e77d-5fdc-4fac-879e-a7a44f6478d4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9e8f0682-b345-4752-a6f1-f13eb2e98a26\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"14990adf-66e0-4270-9147-096ae492c808\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"b9580080-aa79-486f-a97a-b06fc55f82d8\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 32, \"b\": 54 } },\n      \"type\": \"page\",\n      \"id\": \"ce1b993b-e400-429d-86c8-0236ff5cec5d\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/all-about-cars/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/all-about-cars/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'all-about-cars',\n  creationDate: '2021-09-01T00:00:00.000Z',\n  title: _x('All About Cars', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Cars', 'template keyword', 'web-stories'),\n    _x('Features', 'template keyword', 'web-stories'),\n    _x('Futuristic', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Neon Aqua Blue', 'color', 'web-stories'),\n      color: '#00f0ff',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Catalina Blue', 'color', 'web-stories'),\n      color: '#002e73',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Aqua Blue', 'color', 'web-stories'),\n      color: '#a2f6fc',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Celestial Blue', 'color', 'web-stories'),\n      color: '#152132',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Explain technical topics and talk about the latest in science and technology with this clean and futuristic template. Use the blue stickers to draw attention to objects of importance and clearly illustrate your point.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/all-about-cars/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/all-about-cars/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"723d48fb-ba99-4d15-bee5-2a2c7fc62f1b\",\n          \"scale\": 126,\n          \"focalX\": 47.02380952380952,\n          \"focalY\": 54.83630952380951,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:22:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page1_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Black and White city under white sky\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3f3e3b\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 132,\n          \"y\": 165,\n          \"width\": 362,\n          \"height\": 362,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"045aa174-4326-485e-ab49-061d5d7f517c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #a2f6fc\\\">John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 49,\n          \"y\": 364,\n          \"width\": 200,\n          \"height\": 24,\n          \"id\": \"49925035-6a2a-40dd-89c8-3b37174f7620\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">The ins and outs of self-driving cars</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 240,\n          \"height\": 213,\n          \"id\": \"6815fa2d-5446-4838-b840-c8ea6853a48f\",\n          \"x\": 49,\n          \"y\": 393,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e5a0040d-67df-47af-b227-f31db2882ec3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"5c022335-01a0-425b-ade6-af8c5f09c80d\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"3fe2b5f7-d3f7-4d4e-9e14-837b4a06dbbb\",\n          \"scale\": 102,\n          \"focalX\": 48.85110294117647,\n          \"focalY\": 49.080882352941174,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:23:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Vehicle on road with taillights on\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#bdb8b7\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">Soon, self-driving cars will be everywhere. But did you know there are varying degrees of automation?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 129,\n          \"id\": \"482ef501-2ac0-4fd0-99d9-5a3511d253c1\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #00f0ff\\\">Level 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 52,\n          \"y\": 452,\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"1610049f-9c71-4fb6-92fe-a8fca174275a\",\n          \"type\": \"text\",\n          \"groupId\": \"94fd4b8c-7a27-4ea2-80ea-bbd51e169dee\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 31,\n          \"y\": 371,\n          \"width\": 94,\n          \"height\": 94,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"a0047d9a-0aeb-4d88-8df8-02a099aafcba\",\n          \"groupId\": \"94fd4b8c-7a27-4ea2-80ea-bbd51e169dee\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #00f0ff\\\">Level 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"0172700e-9c1c-4eb9-a614-9cb96e865540\",\n          \"x\": 175,\n          \"y\": 494,\n          \"type\": \"text\",\n          \"groupId\": \"161dad7f-46c9-4578-a8d3-dc5c789f1564\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 160,\n          \"height\": 160,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"b679adf8-369f-4d89-b5a5-11d4f1f79f3b\",\n          \"x\": 119,\n          \"y\": 357,\n          \"groupId\": \"161dad7f-46c9-4578-a8d3-dc5c789f1564\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #00f0ff\\\">Level 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"c07ca576-5114-4eb4-a27e-0d9a1405a317\",\n          \"x\": 269,\n          \"y\": 368,\n          \"type\": \"text\",\n          \"groupId\": \"1609c38a-c682-4e86-89f8-4c38e65ed0a3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"0c141bd2-22ea-476e-aaec-72b14bd71531\",\n          \"x\": 266,\n          \"y\": 389,\n          \"groupId\": \"1609c38a-c682-4e86-89f8-4c38e65ed0a3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"215ba1a8-8892-478f-81e9-d304857c0ebe\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"b679adf8-369f-4d89-b5a5-11d4f1f79f3b\"]\n        },\n        {\n          \"id\": \"61704de9-de3d-4498-b1ba-975e25c8685c\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"a0047d9a-0aeb-4d88-8df8-02a099aafcba\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"47a794b9-9ce0-4f56-bf7c-b6e9527eb24b\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"0c141bd2-22ea-476e-aaec-72b14bd71531\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d46f4236-4c6c-4b17-9fb1-fe03d56b37cb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1610049f-9c71-4fb6-92fe-a8fca174275a\"],\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"8aee2164-3994-431e-9b22-5b2535612912\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c07ca576-5114-4eb4-a27e-0d9a1405a317\"],\n          \"duration\": 600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"98754efe-cae7-4513-94e6-59267bf1adc9\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"ce450633-fd8a-444c-a29e-45ea32b16a9d\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1609c38a-c682-4e86-89f8-4c38e65ed0a3\": {\n          \"name\": \"Level 4\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"161dad7f-46c9-4578-a8d3-dc5c789f1564\": {\n          \"name\": \"Level 1\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"94fd4b8c-7a27-4ea2-80ea-bbd51e169dee\": {\n          \"name\": \"Level 3\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"cda90cb3-d7b6-42d6-9868-6c763991efa0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #002e73\\\">2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 55,\n          \"height\": 27,\n          \"id\": \"4b7a6c25-b2df-40b0-9a2d-4875b9d32b77\",\n          \"x\": 178.5,\n          \"y\": 0,\n          \"groupId\": \"cf116d3a-332a-406f-b68e-b5d365bb1734\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #002e73\\\">2,4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 142,\n          \"height\": 137,\n          \"id\": \"e777a152-66f7-41be-90c5-b8310f8d049e\",\n          \"x\": 135,\n          \"y\": 5,\n          \"groupId\": \"cf116d3a-332a-406f-b68e-b5d365bb1734\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #002e73\\\">m</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 55,\n          \"height\": 61,\n          \"id\": \"0598f042-d8b3-44b9-933c-fcc10e03edca\",\n          \"x\": 255,\n          \"y\": 62,\n          \"groupId\": \"cf116d3a-332a-406f-b68e-b5d365bb1734\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 495,\n          \"height\": 494,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"0be7ded0-d3d7-46d4-a0c2-e48f00b51273\",\n          \"x\": -50,\n          \"y\": 56,\n          \"groupId\": \"15608c48-5e23-47ac-9420-ff2944bde348\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 76,\n          \"y\": 198,\n          \"width\": 234,\n          \"height\": 222,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0d64b9ad-4b91-4085-b9d8-cc786ca3e5c8\",\n          \"groupId\": \"15608c48-5e23-47ac-9420-ff2944bde348\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Currently there are 2.4m vehicles on the road with some level of automation.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 98,\n          \"id\": \"d6d72c7f-00ea-448f-82f5-cf085d903c8c\",\n          \"x\": 48,\n          \"y\": 494,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1d24f4c2-ed60-4d01-859f-101e2c6a3df3\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"0be7ded0-d3d7-46d4-a0c2-e48f00b51273\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5a5a5532-8738-4dae-96ee-b7cccda85223\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"15608c48-5e23-47ac-9420-ff2944bde348\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"cf116d3a-332a-406f-b68e-b5d365bb1734\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a3c2ccea-7fab-4d0d-94f6-f398ed3f2695\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #002e73\\\">2025</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 55,\n          \"height\": 27,\n          \"id\": \"b1fb8137-80f6-4279-8ce3-f36e3a487177\",\n          \"x\": 178.5,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"50ce0c1c-9b85-49bb-8603-6d7556a74403\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #002e73\\\">8,1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 142,\n          \"height\": 136,\n          \"id\": \"8401e2f6-fd99-43db-8e95-c957ef1520bc\",\n          \"x\": 135,\n          \"y\": 5,\n          \"type\": \"text\",\n          \"groupId\": \"50ce0c1c-9b85-49bb-8603-6d7556a74403\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #002e73\\\">m</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 55,\n          \"height\": 61,\n          \"id\": \"96de7370-c0e7-43f2-a54e-ffe6d05f3db1\",\n          \"x\": 255,\n          \"y\": 62,\n          \"type\": \"text\",\n          \"groupId\": \"50ce0c1c-9b85-49bb-8603-6d7556a74403\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 283,\n          \"height\": 282,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"849db591-181c-4cc5-baf4-f132373f0c84\",\n          \"x\": 279,\n          \"y\": 73,\n          \"groupId\": \"2ad115f4-812d-4816-919f-b050bb9d00e2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 133,\n          \"height\": 127,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4b180471-cd03-43e0-9242-aeb204d17df1\",\n          \"x\": 354,\n          \"y\": 151,\n          \"groupId\": \"2ad115f4-812d-4816-919f-b050bb9d00e2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 283,\n          \"height\": 282,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"7ecdaac6-2e52-4005-8e5d-5656a296e528\",\n          \"x\": 87,\n          \"y\": 168,\n          \"groupId\": \"a441d415-f1be-4f29-b8e5-fe56cb9554b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 133,\n          \"height\": 127,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"13c6da8a-5e16-4b48-b6f8-69c85c8647e6\",\n          \"x\": 162,\n          \"y\": 246,\n          \"groupId\": \"a441d415-f1be-4f29-b8e5-fe56cb9554b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 283,\n          \"height\": 282,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"42357ead-4f0c-476c-bc48-5c6e479c29ec\",\n          \"x\": -103,\n          \"y\": 261,\n          \"groupId\": \"b3cc05f2-41ad-40b7-99c1-4e540c01ed01\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 133,\n          \"height\": 127,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5800ab1e-6ff4-418b-94f3-a1551e9a6e3a\",\n          \"x\": -28,\n          \"y\": 339,\n          \"groupId\": \"b3cc05f2-41ad-40b7-99c1-4e540c01ed01\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"32492fe0-014d-4433-b201-89802a0e9877\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4b180471-cd03-43e0-9242-aeb204d17df1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9a8b6c9e-41aa-42dd-a31b-a910b58d4c47\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"849db591-181c-4cc5-baf4-f132373f0c84\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"bbbd343e-863c-4c29-94c7-268f3b022b07\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7ecdaac6-2e52-4005-8e5d-5656a296e528\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"3cd4ae30-e957-48a3-9e18-2c90a0207299\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"42357ead-4f0c-476c-bc48-5c6e479c29ec\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"acb5fbaa-8b29-42fc-a523-a31321669ecf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"13c6da8a-5e16-4b48-b6f8-69c85c8647e6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"0193722a-4c75-4fe7-9e75-e9a81ffb2484\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5800ab1e-6ff4-418b-94f3-a1551e9a6e3a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 1200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ad88c646-11c4-4f68-8a34-95853bd62472\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"b3cc05f2-41ad-40b7-99c1-4e540c01ed01\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a441d415-f1be-4f29-b8e5-fe56cb9554b9\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2ad115f4-812d-4816-919f-b050bb9d00e2\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"50ce0c1c-9b85-49bb-8603-6d7556a74403\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ce834425-4cd6-4131-9651-d45f5ccf5e23\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #002e73\\\">Safety</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 247,\n          \"height\": 136,\n          \"id\": \"2e3cf014-ce0d-44e9-989e-3c1eabc07ac3\",\n          \"x\": 82.5,\n          \"y\": 5,\n          \"type\": \"text\",\n          \"groupId\": \"78c4cdda-302c-4c3a-80d3-e345884b8ef5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #002e73\\\">2050</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 55,\n          \"height\": 27,\n          \"id\": \"0075819c-8770-41ed-aec8-41f6b1a76ede\",\n          \"x\": 178,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"78c4cdda-302c-4c3a-80d3-e345884b8ef5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"94796b51-6311-47b2-b33f-9f4f524ddf3b\",\n          \"x\": -97,\n          \"y\": 577\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"8722b660-d374-4954-ba74-3d4463c1982b\",\n          \"x\": 268,\n          \"y\": 577\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"167cac5c-f5f1-4127-ab4f-4eef672fc3f1\",\n          \"x\": -97,\n          \"y\": -142,\n          \"groupId\": \"1ec28ba2-9106-4d7d-9a85-1e142e1d4c75\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7c183417-6160-4a3d-99e5-37d6c56d0b7f\",\n          \"x\": -28,\n          \"y\": -72,\n          \"groupId\": \"1ec28ba2-9106-4d7d-9a85-1e142e1d4c75\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"d1f8d40a-0409-4886-ac2b-3d046c5ac7be\",\n          \"x\": 268,\n          \"y\": -142,\n          \"groupId\": \"8b3de13d-fead-4772-b05c-75de213ad00e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fe27aa44-d0dc-48e1-85f2-7130c24f353c\",\n          \"x\": 337,\n          \"y\": -72,\n          \"groupId\": \"8b3de13d-fead-4772-b05c-75de213ad00e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"8a5d41aa-8112-4643-bc8d-dde0ad2c5bab\",\n          \"x\": -97,\n          \"y\": 41,\n          \"groupId\": \"83642705-3da1-4018-9ccc-d947e7502b11\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0b372c4e-7395-4f86-b754-00e92e0a70f1\",\n          \"x\": -28,\n          \"y\": 111,\n          \"groupId\": \"83642705-3da1-4018-9ccc-d947e7502b11\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"b229f274-2ef4-4ccf-8e02-31153c9a91c5\",\n          \"x\": 268,\n          \"y\": 41,\n          \"groupId\": \"ba4fb876-7146-4078-b1d2-8fa777f73ec9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7e3b2ce3-f00c-4448-a77c-0c36daff3241\",\n          \"x\": 337,\n          \"y\": 111,\n          \"groupId\": \"ba4fb876-7146-4078-b1d2-8fa777f73ec9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"dba0f245-7515-4339-9647-ee981abb4b82\",\n          \"x\": 82,\n          \"y\": 121,\n          \"groupId\": \"85263dcf-ce9b-4a2c-b05e-e86eeb251327\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"704fedc6-fddd-49b0-856c-44604133fd70\",\n          \"x\": 151,\n          \"y\": 191,\n          \"groupId\": \"85263dcf-ce9b-4a2c-b05e-e86eeb251327\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"58855cc7-5bd5-40cc-bf20-d9e763c84d25\",\n          \"x\": -97,\n          \"y\": 220,\n          \"groupId\": \"2547cf1b-708b-49ee-af30-f733ee01cee4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"90cdbc8e-0aee-4f36-ae32-041cb8fb3bef\",\n          \"x\": -28,\n          \"y\": 290,\n          \"groupId\": \"2547cf1b-708b-49ee-af30-f733ee01cee4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"13431965-90e4-4ab8-84be-3fb52ef19ee0\",\n          \"x\": 268,\n          \"y\": 220,\n          \"groupId\": \"099f912a-b4c8-4cc9-b310-6bffbed1e7ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b699516d-4f80-4dd5-8ad5-2a20ee69abfc\",\n          \"x\": 337,\n          \"y\": 290,\n          \"groupId\": \"099f912a-b4c8-4cc9-b310-6bffbed1e7ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"19bb87ff-0c58-4501-a681-de0794128166\",\n          \"x\": 82,\n          \"y\": 304,\n          \"groupId\": \"aca8bc97-a418-4426-81b8-727510f9bab1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"86dbf62c-4ce2-4949-9390-298dc82ff8b3\",\n          \"x\": 151,\n          \"y\": 374,\n          \"groupId\": \"aca8bc97-a418-4426-81b8-727510f9bab1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"0b20a372-4f7b-478f-953d-e6daecf1fed0\",\n          \"x\": -97,\n          \"y\": 397,\n          \"groupId\": \"6283ca3f-f57d-4832-bc7c-cc30c0750cf1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e9988cc0-a672-4d90-9df6-3e7c44fcea29\",\n          \"x\": -28,\n          \"y\": 467,\n          \"groupId\": \"6283ca3f-f57d-4832-bc7c-cc30c0750cf1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"379fe051-74aa-427f-988a-c444831db902\",\n          \"x\": 268,\n          \"y\": 399,\n          \"groupId\": \"4594afc1-a596-4e5c-a069-4061b0f8fabb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"30353c58-3bdc-4572-9052-f1be972f98e5\",\n          \"x\": 337,\n          \"y\": 469,\n          \"groupId\": \"4594afc1-a596-4e5c-a069-4061b0f8fabb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 241,\n          \"height\": 241,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"06f3264f-758c-4673-a566-c5f50bf98daf\",\n          \"x\": 85,\n          \"y\": 483,\n          \"groupId\": \"750395af-fb6f-4c8f-b530-b841eb4f5462\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 103,\n          \"height\": 101,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"666446b0-35fb-4408-b76c-595b1331d58a\",\n          \"x\": 154,\n          \"y\": 553,\n          \"groupId\": \"750395af-fb6f-4c8f-b530-b841eb4f5462\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"de299bff-80ae-411e-ae34-0e8145ab0192\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"167cac5c-f5f1-4127-ab4f-4eef672fc3f1\"]\n        },\n        {\n          \"id\": \"8c2d5a65-51de-4e37-b67b-07e824d66fcc\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"d1f8d40a-0409-4886-ac2b-3d046c5ac7be\"]\n        },\n        {\n          \"id\": \"88860c1e-3b9c-4705-80f2-c15f155edba5\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"dba0f245-7515-4339-9647-ee981abb4b82\"]\n        },\n        {\n          \"id\": \"fb02ab52-d5a0-4a0d-980b-bc0bffbf5b6f\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"13431965-90e4-4ab8-84be-3fb52ef19ee0\"]\n        },\n        {\n          \"id\": \"b5eeb278-65e2-4966-a25a-648dc4d9f5dc\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"19bb87ff-0c58-4501-a681-de0794128166\"]\n        },\n        {\n          \"id\": \"7a88bea0-e2d4-47ca-950d-f8539f842d90\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"58855cc7-5bd5-40cc-bf20-d9e763c84d25\"]\n        },\n        {\n          \"id\": \"d7962354-5f14-4273-bff2-7057507c8716\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"8a5d41aa-8112-4643-bc8d-dde0ad2c5bab\"]\n        },\n        {\n          \"id\": \"ee6e5d74-a6da-426c-b685-43ad52ef537d\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"0b20a372-4f7b-478f-953d-e6daecf1fed0\"]\n        },\n        {\n          \"id\": \"8fc82053-7ad0-4f6c-b02b-5c00e0905f26\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"06f3264f-758c-4673-a566-c5f50bf98daf\"]\n        },\n        {\n          \"id\": \"377d0ba6-c346-47dd-81a5-da51d31ae8bc\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"379fe051-74aa-427f-988a-c444831db902\"]\n        },\n        {\n          \"id\": \"095939e3-8412-47fa-90d9-1bebe80f0c39\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"8722b660-d374-4954-ba74-3d4463c1982b\"]\n        },\n        {\n          \"id\": \"768175a6-2239-4ff9-9125-5240e638acc7\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"94796b51-6311-47b2-b33f-9f4f524ddf3b\"]\n        },\n        {\n          \"id\": \"5d8d29e5-4634-4696-a572-41100e2785b0\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"b229f274-2ef4-4ccf-8e02-31153c9a91c5\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b8a2bf75-253e-4ac8-ad66-102f0403c957\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1ec28ba2-9106-4d7d-9a85-1e142e1d4c75\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"83642705-3da1-4018-9ccc-d947e7502b11\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"85263dcf-ce9b-4a2c-b05e-e86eeb251327\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ba4fb876-7146-4078-b1d2-8fa777f73ec9\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8b3de13d-fead-4772-b05c-75de213ad00e\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"099f912a-b4c8-4cc9-b310-6bffbed1e7ed\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aca8bc97-a418-4426-81b8-727510f9bab1\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2547cf1b-708b-49ee-af30-f733ee01cee4\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6283ca3f-f57d-4832-bc7c-cc30c0750cf1\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"750395af-fb6f-4c8f-b530-b841eb4f5462\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4594afc1-a596-4e5c-a069-4061b0f8fabb\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"78c4cdda-302c-4c3a-80d3-e345884b8ef5\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"ffbac519-e2ed-4ce9-804e-234408b82ffe\",\n          \"scale\": 120,\n          \"focalX\": 30.920138888888886,\n          \"focalY\": 58.333333333333336,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:24:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page6_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Black car instrument panel cluster\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#202a2e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #00f0ff\\\">Level 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"147217cf-832a-4c94-b75f-7a0df885504a\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 4,\n          \"y\": 37,\n          \"width\": 405,\n          \"height\": 402,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"ffb33d6a-22d1-425e-b967-590ee01921d7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Monitoring speed</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 121,\n          \"id\": \"caf5297a-74df-4688-9a21-5702caf3ce5e\",\n          \"x\": 48,\n          \"y\": 447,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">Single automated system like adaptive cruise control features, e.g. monitoring speed</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 46,\n          \"id\": \"21180795-6fb7-46d6-916a-ceeb5ab42ef2\",\n          \"x\": 50,\n          \"y\": 566,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"56134ce6-85f6-4b1d-9f5c-d642d3709e44\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"ffb33d6a-22d1-425e-b967-590ee01921d7\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"651983a8-901b-4bc8-af2e-b3df0fd22007\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"3e425af5-09d1-4a91-a7cc-8c1263980d4a\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"d24bcc4a-8858-45fa-896d-31a643af8171\",\n          \"scale\": 217,\n          \"focalX\": 48.784606740337225,\n          \"focalY\": 42.8530655372032,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:25:58\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Time-lapse Photo Of Cars on Asphalt Road\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#393638\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #00f0ff\\\">Level 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"9af4f225-3e46-409e-8cad-591d0c94a536\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Acceleration control</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 121,\n          \"id\": \"88a91603-04dc-462f-934b-11ebdc139f62\",\n          \"x\": 48,\n          \"y\": 447,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">Advanced Driver Assistance Systems. The vehicle can control steering and acceleration.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 45,\n          \"id\": \"8c26348b-7c5c-4d59-8930-4f36c83084ab\",\n          \"x\": 50,\n          \"y\": 566,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 318,\n          \"height\": 317,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"2e7137f4-6067-4d92-90c2-ef20f09d388d\",\n          \"x\": 6,\n          \"y\": 20\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c6aaef84-339c-4b41-a5a3-81cab0f4e02d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9af4f225-3e46-409e-8cad-591d0c94a536\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6a5eebc5-7f56-4783-8cb7-cb0849a12fd6\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"2e7137f4-6067-4d92-90c2-ef20f09d388d\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a813b43a-5e97-438e-bce3-d81c1f8272f4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"285a5ee5-61a2-488e-9fd7-76708f889183\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"17734d1a-5e2d-40d6-9eca-3b093a9ccc5c\",\n          \"scale\": 151,\n          \"focalX\": 54.785738482384815,\n          \"focalY\": 66.62220528455285,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:28:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Landscape photo of a highway road\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b9c2d0\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #00f0ff\\\">Level 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"de227f53-2565-4f3c-a103-e3497f1c8fb5\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Environmental Detection</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 121,\n          \"id\": \"34f24416-a6c5-4445-9fc4-2fd95d2cbed0\",\n          \"x\": 48,\n          \"y\": 432,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">Conditional automation can alert to any vehicles nearby and make steering adjustments.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 67,\n          \"id\": \"e27baa44-e8b9-4a98-aae6-7e553ecb1122\",\n          \"x\": 50,\n          \"y\": 551,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 189,\n          \"height\": 189,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"339085c4-01f5-4913-917c-3be35f1ac156\",\n          \"x\": 215,\n          \"y\": 171\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b443523a-448d-4311-b5d3-5c625283429f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"de227f53-2565-4f3c-a103-e3497f1c8fb5\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f3953732-5c66-427d-9902-c08d0ba5d3d8\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"339085c4-01f5-4913-917c-3be35f1ac156\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"407453dc-605e-40e6-80e9-552102d95bdf\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e1a6819e-50f6-4681-a988-51c749c5bc7f\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"ffbac519-e2ed-4ce9-804e-234408b82ffe\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-16T06:54:53\",\n            \"baseColor\": \"#3f463f\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page9_vid1.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page9_vid1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 5,\n            \"lengthFormatted\": \"0:05\",\n            \"alt\": \"A Woman Being Careful In Crossing The Street\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0.85 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #00f0ff\\\">Level 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"abdfcac1-d6f9-45d5-9721-389e72c256d7\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Pedestrian</span>\\n<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Safety</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 121,\n          \"id\": \"c48fb36e-0fa0-4d2d-9b88-7baeded54cc6\",\n          \"x\": 48,\n          \"y\": 447,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">High-driving automation. Vehicles can intervene if things go wrong.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 45,\n          \"id\": \"e90a15c2-59ff-4df2-a714-a116d628b787\",\n          \"x\": 50,\n          \"y\": 566,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 189,\n          \"height\": 189,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"065a31fb-ce1d-464b-b831-3fb1d15a59e1\",\n          \"x\": 238,\n          \"y\": 278\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"af31f80f-788e-4157-b892-82c34a29b6a8\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"065a31fb-ce1d-464b-b831-3fb1d15a59e1\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"93babed8-8a04-4e27-87f8-486cfdb1f35a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"abdfcac1-d6f9-45d5-9721-389e72c256d7\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"88dea1a8-b8c7-47d3-abf7-35fe25ad3596\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e97d4b86-fa15-4f7b-b655-fb5f8b42818d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"ef1f539d-379e-4be7-b74d-98f4771a305d\",\n          \"scale\": 112,\n          \"focalX\": 53.80434782608696,\n          \"focalY\": 53.66847826086957,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:50:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man in White Dress Shirt Holding Smartphone\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#66564b\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #00f0ff\\\">Level 5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"d107a529-7d1b-4837-87c1-9fdcba27ef82\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Relax</span>\\n<span style=\\\"font-weight: 300; color: #a2f6fc\\\">and enjoy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 119,\n          \"id\": \"08ad927a-1d6e-4a77-aab7-239425d516a2\",\n          \"x\": 48,\n          \"y\": 432,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">Full driving automation. Does not require human attention. No pedals or steering wheels.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 67,\n          \"id\": \"4df4a4b9-77c2-449e-aac2-2677e61e8e85\",\n          \"x\": 50,\n          \"y\": 551,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 189,\n          \"height\": 189,\n          \"sticker\": { \"type\": \"selfDrivingCarsBlueRings\" },\n          \"id\": \"f3d6cb23-e721-4139-be11-1beccd400426\",\n          \"x\": 241,\n          \"y\": 352\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6a2ae12d-7146-42ad-a265-9dfbb4690699\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d107a529-7d1b-4837-87c1-9fdcba27ef82\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c7a2219b-1e20-4754-bbac-8533777a259a\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"f3d6cb23-e721-4139-be11-1beccd400426\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"3490b41e-e9b5-4057-ad4f-99b5c28c9a56\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"4d347524-ac7e-4345-b587-663e027ab020\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f486870e-ad80-4421-a82a-40a6c6cfe3cf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Levels of automation</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 7,\n          \"width\": 269,\n          \"height\": 46,\n          \"id\": \"2f0e0519-0864-4b30-ad14-f96ce0c941b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Automated monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 46,\n          \"id\": \"d79d9ae5-3538-4184-acd4-9052d8a602df\",\n          \"x\": 47,\n          \"y\": 148\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Human monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 45,\n          \"id\": \"609a8199-5525-458a-9d51-b6e57e4ade6f\",\n          \"x\": 47,\n          \"y\": 560,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 240, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 154,\n          \"y\": 509,\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8efa0bf9-bd79-407c-9d3b-8d440efe4c1a\",\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"type\": \"shape\",\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4bb4a2d5-696f-484f-af3d-3918ce46f59b\",\n          \"x\": 154,\n          \"y\": 406,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"type\": \"shape\",\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9cbc74d8-80ac-48a0-af9d-9e11082e3c85\",\n          \"x\": 154,\n          \"y\": 303,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"type\": \"shape\",\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"907c7910-2f46-4c38-9aff-78ddf3ba16b3\",\n          \"x\": 154,\n          \"y\": 200,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"type\": \"shape\",\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"24172698-6ba7-463d-9077-a7377f46c2a0\",\n          \"x\": 154,\n          \"y\": 98,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 40,\n          \"id\": \"ab20e044-7d71-4ca9-be26-16f2f1687482\",\n          \"x\": 124,\n          \"y\": 498,\n          \"groupId\": \"a6168861-25f0-4c38-bfba-fcf722af02f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 275,\n          \"height\": 274,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"02eb1747-08ee-4b70-87c7-fbbf519b284c\",\n          \"x\": 140,\n          \"y\": 383,\n          \"groupId\": \"0191a669-a433-446b-ba06-af000646e49b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 127,\n          \"height\": 125,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fdd4d13e-1b6c-4762-b724-bbeadd2d673f\",\n          \"x\": 214,\n          \"y\": 458,\n          \"groupId\": \"0191a669-a433-446b-ba06-af000646e49b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"087ef4a7-d65b-4797-8265-70c3564ce669\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"02eb1747-08ee-4b70-87c7-fbbf519b284c\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9431d792-419b-4489-be8e-8c53bb16ac10\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0191a669-a433-446b-ba06-af000646e49b\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a6168861-25f0-4c38-bfba-fcf722af02f8\": {\n          \"name\": \"Progress\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7159b1d9-8979-4035-98a9-4580143fb3b7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Levels of automation</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 7,\n          \"width\": 269,\n          \"height\": 46,\n          \"id\": \"0f250a52-5006-4b7a-b7b3-d2aa6af05bc2\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Automated monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 46,\n          \"id\": \"bf751abd-6ecd-4b35-9683-74d46d032ac7\",\n          \"x\": 47,\n          \"y\": 148,\n          \"type\": \"text\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Human monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 45,\n          \"id\": \"ef4edff3-ec72-4a99-8848-0c773ad4626e\",\n          \"x\": 47,\n          \"y\": 560,\n          \"type\": \"text\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 240, \"b\": 255 } },\n          \"x\": 154,\n          \"y\": 509,\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1a466056-fe84-4a4f-bc82-dc988861c30f\",\n          \"type\": \"shape\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 1 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d35b352b-e4a7-4dae-aa4b-26c11658f7b0\",\n          \"x\": 154,\n          \"y\": 406,\n          \"type\": \"shape\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f3a0d4f5-0cbe-4c18-beca-019f8f17dfb2\",\n          \"x\": 154,\n          \"y\": 303,\n          \"type\": \"shape\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2d8a5461-3642-4d46-a4b8-5d3e39e21107\",\n          \"x\": 154,\n          \"y\": 200,\n          \"type\": \"shape\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 0.2 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8077523d-f678-4e52-8258-2e775b6a8675\",\n          \"x\": 154,\n          \"y\": 98,\n          \"type\": \"shape\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 39,\n          \"id\": \"e9166c36-b575-4ed7-8ae1-e031148732af\",\n          \"x\": 124,\n          \"y\": 396,\n          \"type\": \"text\",\n          \"groupId\": \"8df61a11-0b13-44e1-a14b-f767226f5f9a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 275,\n          \"height\": 274,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"93711dbc-810e-4e61-ae1f-03411657903c\",\n          \"x\": 140,\n          \"y\": 253,\n          \"groupId\": \"1e35117c-55a5-4a96-9116-b856a634ad24\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 127,\n          \"height\": 125,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c469ffa6-eec5-4006-9efa-f60396525041\",\n          \"x\": 214,\n          \"y\": 328,\n          \"groupId\": \"1e35117c-55a5-4a96-9116-b856a634ad24\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a3b19a3e-d95e-47ff-98f3-312851287717\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"93711dbc-810e-4e61-ae1f-03411657903c\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fc55a6b7-25de-4696-b232-25d83b96bf40\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"1e35117c-55a5-4a96-9116-b856a634ad24\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8df61a11-0b13-44e1-a14b-f767226f5f9a\": {\n          \"name\": \"Progress\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0ce692d4-df09-46fe-8a4b-1904b20841c3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Levels of automation</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 7,\n          \"width\": 269,\n          \"height\": 46,\n          \"id\": \"48ddb27b-542a-4dd9-a1bb-59fda1792a6f\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Automated monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 46,\n          \"id\": \"34939693-fc32-4059-8045-f353b88b5367\",\n          \"x\": 47,\n          \"y\": 148,\n          \"type\": \"text\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">Human monitored</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 116,\n          \"height\": 47,\n          \"id\": \"f59a716d-5dff-4126-8297-3aec8582e757\",\n          \"x\": 47,\n          \"y\": 560,\n          \"type\": \"text\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 240, \"b\": 255 } },\n          \"x\": 154,\n          \"y\": 509,\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bd80bcd1-1fce-420e-ae8a-e9105074db3a\",\n          \"type\": \"shape\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 1 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a1539564-e077-4944-9bd7-509337411915\",\n          \"x\": 154,\n          \"y\": 406,\n          \"type\": \"shape\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 1 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2e272416-78e4-471f-9b69-35740542c15b\",\n          \"x\": 154,\n          \"y\": 303,\n          \"type\": \"shape\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 1 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"18e04ecc-c4af-4bae-b128-830fb03186f3\",\n          \"x\": 154,\n          \"y\": 200,\n          \"type\": \"shape\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 0, \"g\": 240, \"b\": 255, \"a\": 1 }\n          },\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"db529494-def0-4024-91d4-0883b15e1867\",\n          \"x\": 154,\n          \"y\": 98,\n          \"type\": \"shape\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0f2c59\\\">5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 39,\n          \"id\": \"14c5a37b-039a-4f21-b4d2-c961adcbc6fc\",\n          \"x\": 124,\n          \"y\": 87,\n          \"type\": \"text\",\n          \"groupId\": \"d4967b8e-8b35-492e-8972-263f7d40398f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 275,\n          \"height\": 274,\n          \"sticker\": { \"type\": \"selfDrivingCarsMultipleBlueRings\" },\n          \"id\": \"8372925d-dff2-4de1-8545-a4210bad328a\",\n          \"x\": 139,\n          \"y\": 53,\n          \"groupId\": \"83053063-a90b-4d4d-abea-dbba3df93d82\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T09:49:57\",\n            \"baseColor\": \"#343f42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page3_4_5_11_12_13_img1.png\",\n            \"width\": 468,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Selfdriving Smart Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 127,\n          \"height\": 125,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a68efc4d-d373-40b6-b5b3-f4a99d1c82b3\",\n          \"x\": 213,\n          \"y\": 126,\n          \"groupId\": \"83053063-a90b-4d4d-abea-dbba3df93d82\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9ab7474a-ccc1-4188-a6a0-77517cd740c6\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"8372925d-dff2-4de1-8545-a4210bad328a\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1b2dadc6-d054-46c2-904d-3b9a900bc7d2\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"83053063-a90b-4d4d-abea-dbba3df93d82\": {\n          \"name\": \"Graphic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d4967b8e-8b35-492e-8972-263f7d40398f\": {\n          \"name\": \"Progress\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f0c28e66-fa06-468a-abf2-b58701a1d704\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #a2f6fc\\\">Other Stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 119,\n          \"id\": \"51508948-08ab-4382-aa39-571326a74741\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #00f0ff\\\">Story 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"6819b5a8-2bb7-4c06-94ed-2f447cf88497\",\n          \"x\": 148,\n          \"y\": 351,\n          \"type\": \"text\",\n          \"groupId\": \"d85b35dc-4f71-4e07-8fe8-4e70bf0b00fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">How It’s Made: Autonomous Cars</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 183,\n          \"height\": 55,\n          \"id\": \"a97a3a00-d7c3-4786-9033-524993ffd119\",\n          \"x\": 148,\n          \"y\": 378,\n          \"type\": \"text\",\n          \"groupId\": \"d85b35dc-4f71-4e07-8fe8-4e70bf0b00fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:52:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page14_img1.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man in black jacket sitting on black chair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c7c7c1\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 356,\n          \"width\": 86,\n          \"height\": 70,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c0260618-082a-4a92-ab6a-e8dbe0bb0273\",\n          \"type\": \"image\",\n          \"groupId\": \"d85b35dc-4f71-4e07-8fe8-4e70bf0b00fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #00f0ff\\\">Story 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 70,\n          \"height\": 27,\n          \"id\": \"18b06e50-020c-4ae6-bc82-8ed21fa405fa\",\n          \"x\": 148,\n          \"y\": 502,\n          \"type\": \"text\",\n          \"groupId\": \"f53a69c3-293c-42be-b4e4-2da6a4f9b81d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dffdff\\\">The Interiors of\\nSelf-driving Vehicles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 206,\n          \"height\": 55,\n          \"id\": \"2d01a816-02c1-410b-9698-f617f452d6e1\",\n          \"x\": 148,\n          \"y\": 529,\n          \"type\": \"text\",\n          \"groupId\": \"f53a69c3-293c-42be-b4e4-2da6a4f9b81d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:53:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/all-about-cars/page14_img2.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Turned-On Monitor Inside a Tesla Car\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#ccd1cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 86,\n          \"height\": 70,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ca9db983-2e78-46d9-b589-dae645b4c836\",\n          \"x\": 47,\n          \"y\": 507,\n          \"type\": \"image\",\n          \"groupId\": \"f53a69c3-293c-42be-b4e4-2da6a4f9b81d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.25em\\\">..................................................</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 456,\n          \"width\": 313,\n          \"height\": 13,\n          \"id\": \"f1964199-53b7-4dca-8eb1-435a693f28c3\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6791cdae-dd45-4048-b79d-afff5156830c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"51508948-08ab-4382-aa39-571326a74741\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c0bfca89-54cc-440a-a090-1e5f6fa55288\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c0260618-082a-4a92-ab6a-e8dbe0bb0273\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1e766e24-daac-4ff8-bcea-69ff5efcc35c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a97a3a00-d7c3-4786-9033-524993ffd119\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"503da795-17c7-4e76-ab12-48d1a44e8d2d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6819b5a8-2bb7-4c06-94ed-2f447cf88497\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2d33e430-5c7f-4969-a6a1-2e84ee4f8033\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ca9db983-2e78-46d9-b589-dae645b4c836\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dff3eefa-695e-4756-8ee6-e55fcb8153b4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"18b06e50-020c-4ae6-bc82-8ed21fa405fa\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8ca0596c-754e-4ae8-813f-ae9fb66d7aaf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2d01a816-02c1-410b-9698-f617f452d6e1\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6582d22b-817f-4f90-a52a-43498a5de451\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f1964199-53b7-4dca-8eb1-435a693f28c3\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 33, \"b\": 50 } },\n      \"type\": \"page\",\n      \"id\": \"33c9d3cf-e900-457a-8bc3-a09452f6d8b6\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"f53a69c3-293c-42be-b4e4-2da6a4f9b81d\": {\n          \"name\": \"Story 2\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d85b35dc-4f71-4e07-8fe8-4e70bf0b00fa\": {\n          \"name\": \"Story 1\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/almodos-films/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/almodos-films/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'almodos-films',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Almodo’s Films', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Films', 'template keyword', 'web-stories'),\n    _x('Women', 'template keyword', 'web-stories'),\n    _x('Elegant', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Paris Daisy Yellow', 'color', 'web-stories'),\n      color: '#fbeb50',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Piedmont Green', 'color', 'web-stories'),\n      color: '#263524',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Soft curved shapes, elegant antique typography and cool colors with green undertones. This template is perfect for when you want your story to feel calm and tranquil but also look bold and vibrant.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/almodos-films/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/almodos-films/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 510,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"aa873b8f-d480-416b-9b89-118916439706\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:44:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page1_bg.jpg\",\n            \"width\": 330,\n            \"height\": 510,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Elderly man sketching on white cardboard\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#aea49d\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.25,\n            \"alpha\": 0.4\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 74,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Women in Almodo’s films</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": -128,\n          \"y\": 111,\n          \"width\": 561,\n          \"height\": 339,\n          \"id\": \"e91a76a0-c0c1-4d59-9b37-a86e14dec456\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">By </span><span style=\\\"font-weight: 700; color: #fff\\\">Nicole Newman</span><span style=\\\"color: #fff\\\"> | Jan 29, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 592,\n          \"width\": 254,\n          \"height\": 21,\n          \"id\": \"4838faa0-fb5d-49d4-9095-1b14feac4aba\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"957708f3-6565-46a3-9ef3-ca13ad24fbb6\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c084b1c7-913c-40b5-82f7-02e9b62bacb1\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"eb34fd22-fa04-4a70-aa0d-50ec8d0cb9e2\",\n          \"scale\": 112,\n          \"focalX\": 50,\n          \"focalY\": 55.73748707045168,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T07:59:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page2_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Three Women in Assorted-Color Tops\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#a1a2ab\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.33 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 309,\n          \"width\": 412,\n          \"height\": 372,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a7a0779c-491d-43bf-aea3-7c994c52f6a7\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"groupId\": \"0c3fe02d-557f-468c-baaa-1442b4efa843\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Strong female characters</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 190,\n          \"id\": \"7aa2fd5a-706a-4350-a96c-757447120b69\",\n          \"x\": 47,\n          \"y\": 341,\n          \"groupId\": \"0c3fe02d-557f-468c-baaa-1442b4efa843\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">With a filmography that spans nearly 40 years, Almodo has always been consistent with his memorable, outspoken, and nuanced female leads.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 91,\n          \"id\": \"2ca4f034-d08f-441d-b6d2-b0b81acc112f\",\n          \"x\": 49,\n          \"y\": 513,\n          \"groupId\": \"0c3fe02d-557f-468c-baaa-1442b4efa843\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"97040c08-d403-4f59-8f05-aaf6c0631975\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2ca4f034-d08f-441d-b6d2-b0b81acc112f\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"795b11a1-3d5c-4033-ba16-ca3a93084da8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a7a0779c-491d-43bf-aea3-7c994c52f6a7\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e35f8c9b-ca1e-409c-b8ac-5999a1dbd20a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"0c3fe02d-557f-468c-baaa-1442b4efa843\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"bf2a101e-8e1f-4f5d-a958-49feb7cf55ca\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#7b7878\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page3.png\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"id\": 0,\n            \"alt\": \"Woman in White and Brown Floral Dress\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"611f2840-0a22-4a0a-9ccd-3ac73bde73a3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Almodo's film \\\"Julieta\\\" poignantly explores female agency when one woman reconciles her present situation with her past decisions.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 93,\n          \"id\": \"2eee5b42-aed2-456c-b501-175c2f0f1349\",\n          \"x\": 57,\n          \"y\": 479,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Julieta</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 70,\n          \"id\": \"9a252096-7acd-41ce-9215-fe124771dc7c\",\n          \"x\": 45,\n          \"y\": 419,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 129,\n          \"y\": 34,\n          \"id\": \"81b9cbb1-fc48-4d5f-8bf8-9d8076ef71d7\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">A woman's journey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"d83642db-ae25-4f64-8bd4-fbc55904c30c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 108,\n          \"y\": 36.5,\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"id\": \"02a60ede-ff6a-4a10-a9df-15a0d116e37b\",\n          \"type\": \"sticker\",\n          \"groupId\": \"d83642db-ae25-4f64-8bd4-fbc55904c30c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 290,\n          \"y\": 36.5,\n          \"id\": \"e7f0c1ab-c6a8-49d0-83d1-f97577c16a01\",\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"type\": \"sticker\",\n          \"groupId\": \"d83642db-ae25-4f64-8bd4-fbc55904c30c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0c9fa8d2-df15-4571-9a17-f65e7455ba42\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"e7f0c1ab-c6a8-49d0-83d1-f97577c16a01\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"de24fe34-0996-4774-a41c-e8ee0dac13e5\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"02a60ede-ff6a-4a10-a9df-15a0d116e37b\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"3887d40d-0866-48ac-b811-83f822c7df44\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"d83642db-ae25-4f64-8bd4-fbc55904c30c\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -284,\n          \"y\": -301,\n          \"width\": 1080,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"373bfaa0-99cc-415f-87ab-cf2b576fac02\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:08:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page4_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in Gray Sweater Leaning Backward  Near White Window Curtain\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dddbda\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": false\n          },\n          \"id\": \"6303fb88-e618-4ff5-b70d-0bec786837c2\",\n          \"x\": 0,\n          \"y\": -62,\n          \"groupId\": \"9365df04-ba7d-45cb-ba7f-3d1f1f470427\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Originally intended for legendary actor Meryl Streep, Almodo ultimately decided to cast Adriana Ugarte back home in his native Spain.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 93,\n          \"id\": \"ebfa9763-2f94-41e4-98ca-cb1ca649ef16\",\n          \"x\": 49,\n          \"y\": 34,\n          \"groupId\": \"9365df04-ba7d-45cb-ba7f-3d1f1f470427\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Making Julieta</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 209,\n          \"height\": 51,\n          \"id\": \"5b7a158e-a4d4-4fff-8d30-57a83d356aa6\",\n          \"x\": 48,\n          \"y\": -13,\n          \"groupId\": \"9365df04-ba7d-45cb-ba7f-3d1f1f470427\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7c565990-1b2a-4296-bd12-3fc216af6978\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ebfa9763-2f94-41e4-98ca-cb1ca649ef16\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"e5996b58-1436-4f8c-bf63-e94e936e0a7e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6303fb88-e618-4ff5-b70d-0bec786837c2\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8d6df786-df0b-495d-a269-956114065985\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"9e57288b-42fd-40ef-8ea8-08b5e45f79c2\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9365df04-ba7d-45cb-ba7f-3d1f1f470427\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"588effb3-5f01-400f-a89c-fa73e544e1fa\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Adriana Ugarte was ultimately chosen to play Julieta for her nuanced portrayal of youth, independence, and female freedom.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 67,\n          \"id\": \"1c5fbc43-1fb1-47c5-b67e-80eba95da7bd\",\n          \"x\": 50,\n          \"y\": 540,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Ugarte as Julieta</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 312,\n          \"height\": 51,\n          \"id\": \"7ac7d85c-f623-41e0-a997-d41ee26e83e7\",\n          \"x\": 49,\n          \"y\": -13,\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:10:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page5_image1.jpg\",\n            \"width\": 240,\n            \"height\": 427,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in Under Garment Standing on The Platform\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#564d3d\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 48,\n          \"y\": 71,\n          \"width\": 193,\n          \"height\": 304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"85c8d43f-b488-45c5-a24b-445f63748e1c\",\n          \"borderRadius\": {\n            \"topLeft\": 90,\n            \"topRight\": 90,\n            \"bottomRight\": 90,\n            \"bottomLeft\": 90,\n            \"locked\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"x\": 172,\n          \"y\": 204,\n          \"id\": \"fc3c6ae0-fa0f-4c50-84f5-0e07c266e8bf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 49.78617270488902,\n          \"focalY\": 50.23806346521936,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:10:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page5_image2.jpg\",\n            \"width\": 480,\n            \"height\": 854,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in Brown Shirt Kissing Woman in White Tank Top\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#261e16\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 193,\n          \"height\": 304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 90,\n            \"topRight\": 90,\n            \"bottomRight\": 90,\n            \"bottomLeft\": 90,\n            \"locked\": true\n          },\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7d38872e-4316-47c4-986d-09e338658822\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fc3c6ae0-fa0f-4c50-84f5-0e07c266e8bf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"173e9809-2208-432b-b566-ed7be5b657f9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"85c8d43f-b488-45c5-a24b-445f63748e1c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"be528b0a-a60f-4d52-ae28-b7e76dfaf6a1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 118,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:11:55\",\n            \"baseColor\": \"#644838\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page6_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person Face in Close Up PhotoWoman Sitting on a Sofa Chair in a Room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -651,\n          \"width\": 1080,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"bc027675-b8b2-4d26-9512-80e48a750eea\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0.2 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 372,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"27cf2b7d-ac31-44d6-a076-35da17bb8034\",\n          \"x\": 0,\n          \"y\": 303,\n          \"groupId\": \"d15b4890-cdc7-4707-940b-2e56241574aa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">“ I wanted to portray a woman exploring life and making decisions on her own terms.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 236,\n          \"id\": \"d4449ab6-9590-4a16-8fe8-8c5df5e42c6e\",\n          \"x\": 48,\n          \"y\": 355,\n          \"type\": \"text\",\n          \"groupId\": \"d15b4890-cdc7-4707-940b-2e56241574aa\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Almodo on </span><span style=\\\"font-weight: 700; color: #fff\\\">Adriana Ugarte</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 20,\n          \"id\": \"e5d74804-c12d-44cb-8361-03c45d6cacf1\",\n          \"x\": 49,\n          \"y\": 590,\n          \"type\": \"text\",\n          \"groupId\": \"d15b4890-cdc7-4707-940b-2e56241574aa\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b8ef6cd9-eae0-4c5d-b8cd-fcae68ea7a33\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e5d74804-c12d-44cb-8361-03c45d6cacf1\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"f600362d-2755-4407-80e5-a58efd9890dc\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"bc027675-b8b2-4d26-9512-80e48a750eea\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f66754bc-4646-4e58-8831-c175b1c87abe\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n      },\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"d15b4890-cdc7-4707-940b-2e56241574aa\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c1e7631a-ad07-4833-8394-2b1383e0945c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#2f1310\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page7.png\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"id\": 0,\n            \"alt\": \"Woman Sitting on a Sofa Chair in a Room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1037c4fa-622a-4b39-99d8-0e9dc9581813\",\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">In Volver, we see Almodo explore female identity: the layers, the emotions, the influences on a woman's decision-making process.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 93,\n          \"id\": \"956c518f-30dd-43dc-83b1-60e136fc1a16\",\n          \"x\": 56,\n          \"y\": 479,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Volver</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 70,\n          \"id\": \"d2016699-8393-49ca-923b-aa21385d5161\",\n          \"x\": 49,\n          \"y\": 419,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 129,\n          \"y\": 34,\n          \"id\": \"217b8544-8ff2-4131-9a40-ca5ed2d27afd\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">Female Identity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"1da32414-b11d-4135-bb9b-d8d07718c034\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"id\": \"9f971c69-149e-477d-a8c3-b27b9fbce181\",\n          \"x\": 121,\n          \"y\": 36.5,\n          \"type\": \"sticker\",\n          \"groupId\": \"1da32414-b11d-4135-bb9b-d8d07718c034\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"id\": \"df20e5d2-fce7-4fb2-82bc-f891e3b4716a\",\n          \"x\": 280,\n          \"y\": 36.5,\n          \"type\": \"sticker\",\n          \"groupId\": \"1da32414-b11d-4135-bb9b-d8d07718c034\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b3bab013-578f-4461-9f1b-37515b55f3e4\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"df20e5d2-fce7-4fb2-82bc-f891e3b4716a\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"56a9f64a-184d-455a-9d88-423bd12376a2\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"9f971c69-149e-477d-a8c3-b27b9fbce181\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"6e6528b7-19b4-4fd1-bf4b-e4d6665af57a\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1da32414-b11d-4135-bb9b-d8d07718c034\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:21:34\",\n            \"baseColor\": \"#352b1d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page8_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in Brown T-shirt Standing Beside Woman in Brown Brassiere\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -651,\n          \"width\": 1080,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"ee04022a-afcb-4485-84a6-bc817870bef8\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0.2 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": false\n          },\n          \"id\": \"1ed5de75-8afd-42dd-8480-261cd15463fb\",\n          \"x\": 0,\n          \"y\": -62,\n          \"groupId\": \"c1ce1dcb-4693-4ea8-9799-27b6929b7512\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Almodo famously makes movies about movies as a way to explore the complexity of identity for women. Women have always been understood through someone else's lens or medium.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 117,\n          \"id\": \"2410871a-1ba7-4b29-b082-0d0ac6d4adad\",\n          \"x\": 49,\n          \"y\": 34,\n          \"type\": \"text\",\n          \"groupId\": \"c1ce1dcb-4693-4ea8-9799-27b6929b7512\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Why Identity?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 52,\n          \"id\": \"4c323030-2f1e-4044-9233-a17fca56353d\",\n          \"x\": 49,\n          \"y\": -13,\n          \"type\": \"text\",\n          \"groupId\": \"c1ce1dcb-4693-4ea8-9799-27b6929b7512\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5cc6fb32-98a8-42e2-b2cc-178fa7d9bede\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2410871a-1ba7-4b29-b082-0d0ac6d4adad\"],\n          \"duration\": 1700,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"0f2d7a56-5d70-4c63-9d33-b586cc07f009\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1ed5de75-8afd-42dd-8480-261cd15463fb\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d88d7fed-f444-4104-84c1-e21a0068aeca\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"9e57288b-42fd-40ef-8ea8-08b5e45f79c2\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c1ce1dcb-4693-4ea8-9799-27b6929b7512\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 111,\n          \"focalX\": 46.29355592632268,\n          \"focalY\": 49.90402334084169,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-19T21:36:11\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page9_bg.jpg\",\n            \"width\": 330,\n            \"height\": 531,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in Black Tank Top\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d59e76\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 531,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"747ae8c9-698b-4d39-984d-e35d9bc73eb4\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0.2 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 341,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"a29b0756-f9ef-4a77-ac28-dd0d9edf62d8\",\n          \"x\": 0,\n          \"y\": 336,\n          \"groupId\": \"075a59ee-96c4-4370-9971-324b829197ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">“His work is his love letter to women. It's his love letter to cinema.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 202,\n          \"id\": \"ec70578b-9c7a-4e22-a0d4-51734242c223\",\n          \"x\": 49,\n          \"y\": 386,\n          \"type\": \"text\",\n          \"groupId\": \"075a59ee-96c4-4370-9971-324b829197ed\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Almodo on </span><span style=\\\"font-weight: 700; color: #fff\\\">Penny Cruz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 21,\n          \"id\": \"2e688881-29ac-4534-8bc2-0b9c0e408386\",\n          \"x\": 49,\n          \"y\": 590,\n          \"type\": \"text\",\n          \"groupId\": \"075a59ee-96c4-4370-9971-324b829197ed\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b4a10039-4534-41ff-a7c1-23a23df8919d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2e688881-29ac-4534-8bc2-0b9c0e408386\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"6d0fb9b5-6942-4b8f-9c6a-801f31e0ec74\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"747ae8c9-698b-4d39-984d-e35d9bc73eb4\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"185f13ae-c58e-4308-9ac0-aebde90bb34b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"075a59ee-96c4-4370-9971-324b829197ed\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9a9b88ce-5a32-43f2-8aae-e9560983669b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#2f2924\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page10.png\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"id\": 0,\n            \"alt\": \"Girl in pinstriped shirt kissing the woman's forehead\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"07b8a1eb-5cb6-459e-8272-20864e0d2057\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">All About My Mother explores why women act, who they act for, and how they perform.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 69,\n          \"id\": \"4d86a05f-3c75-40a0-947c-3e04dc90058e\",\n          \"x\": 56,\n          \"y\": 479,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">All about my mother</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 105,\n          \"id\": \"972478a3-3890-4aba-a9e4-c775a8e8aa85\",\n          \"x\": 47,\n          \"y\": 388,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 130,\n          \"y\": 34,\n          \"id\": \"69a8da9c-eb98-4f4c-8f7f-c271d7ffcd47\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">Women Who Act</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"9fbc7892-ea16-4414-a16a-972975551a65\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"id\": \"3d0d4e6a-9ac8-445b-805f-73798142e6ae\",\n          \"x\": 124,\n          \"y\": 36.5,\n          \"type\": \"sticker\",\n          \"groupId\": \"9fbc7892-ea16-4414-a16a-972975551a65\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"heptagram\" },\n          \"id\": \"188a9280-5841-44f3-ad8d-b7051056efda\",\n          \"x\": 276,\n          \"y\": 36.5,\n          \"type\": \"sticker\",\n          \"groupId\": \"9fbc7892-ea16-4414-a16a-972975551a65\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b84282aa-1b7a-4b15-a4fa-5a5fc0a1d827\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"188a9280-5841-44f3-ad8d-b7051056efda\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2e9a2b10-f239-4458-bd93-804e7403c08a\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"3d0d4e6a-9ac8-445b-805f-73798142e6ae\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"8f868cda-a3fe-4685-b4e2-815d713ede88\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9fbc7892-ea16-4414-a16a-972975551a65\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 122,\n          \"focalX\": 50,\n          \"focalY\": 40.90383201275102,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:26:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in white shirt with blue eyes\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#222c2a\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9c4edb33-6bc6-4c64-97ea-84f5169a3bb6\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0 }, \"position\": 0.43 },\n              { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": false\n          },\n          \"id\": \"4b2ef586-6dd7-4e59-bc0d-4c8835c54d7d\",\n          \"x\": 0,\n          \"y\": -62,\n          \"groupId\": \"881047a9-509f-4a93-b650-32a1e54aab91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">The film moves around characters who are melodramatic. Their real hardships are punctuated by moments of seeming parody. Almodo examines the convention of acting in our daily lives.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 116,\n          \"id\": \"65b87c49-45e9-44d1-abff-be35deb096c8\",\n          \"x\": 49,\n          \"y\": 34,\n          \"type\": \"text\",\n          \"groupId\": \"881047a9-509f-4a93-b650-32a1e54aab91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Real vs. Unreal</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 51,\n          \"id\": \"994fc256-4f85-4be4-8410-084d07445365\",\n          \"x\": 48,\n          \"y\": -13,\n          \"type\": \"text\",\n          \"groupId\": \"881047a9-509f-4a93-b650-32a1e54aab91\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d4da8222-c7ee-45a7-abbd-2bdb71870ce5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"65b87c49-45e9-44d1-abff-be35deb096c8\"],\n          \"duration\": 1700,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"62208294-d168-4e27-930e-e45d3b232c43\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4b2ef586-6dd7-4e59-bc0d-4c8835c54d7d\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"eaceddda-c153-42e6-98cd-9bcb19cd2e2b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"9e57288b-42fd-40ef-8ea8-08b5e45f79c2\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"881047a9-509f-4a93-b650-32a1e54aab91\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 112,\n          \"focalX\": 50,\n          \"focalY\": 46.004971590909086,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:28:23\",\n            \"baseColor\": \"#3a3638\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Taking Video With Woman Standing Inside Room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -651,\n          \"width\": 1080,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9b631654-bc1f-4657-ad7c-4b913ae6e92a\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 1, \"g\": 1, \"b\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.4\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 374,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"ded20a6f-204f-46de-ad66-6970e082f9f1\",\n          \"x\": 0,\n          \"y\": 303,\n          \"groupId\": \"d8ec8e34-4304-41bc-ace1-f3c1868ce035\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">“The films he makes are a reflection of himself, and this is how he sees women.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 236,\n          \"id\": \"4edf29e6-9064-446a-a7f6-f14b9911ad19\",\n          \"x\": 49,\n          \"y\": 352,\n          \"type\": \"text\",\n          \"groupId\": \"d8ec8e34-4304-41bc-ace1-f3c1868ce035\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Almodo on </span><span style=\\\"font-weight: 700; color: #fff\\\">Cecilia Roth</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 21,\n          \"id\": \"02ab4eaf-379d-413a-8104-f7dac02d397b\",\n          \"x\": 49,\n          \"y\": 590,\n          \"type\": \"text\",\n          \"groupId\": \"d8ec8e34-4304-41bc-ace1-f3c1868ce035\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d3e7be7a-7522-4657-a3ba-ed8cfc2ea882\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"02ab4eaf-379d-413a-8104-f7dac02d397b\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a8f093fe-29e4-4e48-89da-01f9dd331d02\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"9b631654-bc1f-4657-ad7c-4b913ae6e92a\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f0ef7445-19db-4246-a731-c9d12c21a80e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"d8ec8e34-4304-41bc-ace1-f3c1868ce035\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">The observer of women</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 194,\n          \"height\": 74,\n          \"id\": \"0d842297-b498-4fee-8615-f707b13352a6\",\n          \"x\": 48,\n          \"y\": -13,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">La Frances Hui said: “Almodo is someone who is very beloved by female actresses. He has an unusual ability to observe women with a sense of empathy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 93,\n          \"id\": \"ffea6a83-e91a-4bae-bc67-d69bdbdc6d21\",\n          \"x\": 49,\n          \"y\": 516,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50.02467628993972,\n          \"focalY\": 49.61909845564901,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:28:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page13_image1.jpg\",\n            \"width\": 480,\n            \"height\": 854,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Holding on Railings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#312218\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 193,\n          \"height\": 304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 90,\n            \"topRight\": 90,\n            \"bottomRight\": 90,\n            \"bottomLeft\": 90,\n            \"locked\": true\n          },\n          \"type\": \"image\",\n          \"id\": \"e9097afb-5e54-4518-844c-39c949bcc1c9\",\n          \"x\": 49,\n          \"y\": 71\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 49.82729138369691,\n          \"focalY\": 50.142838079131614,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:29:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page13_image2.jpg\",\n            \"width\": 480,\n            \"height\": 854,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Holding on Railings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#302218\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 193,\n          \"height\": 304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 90,\n            \"topRight\": 90,\n            \"bottomRight\": 90,\n            \"bottomLeft\": 90,\n            \"locked\": true\n          },\n          \"type\": \"image\",\n          \"id\": \"764558dd-47aa-4027-837f-cfa7cbf53c70\",\n          \"x\": 172,\n          \"y\": 204\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"65a4cc37-be34-4252-b382-0541a82805ad\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e9097afb-5e54-4518-844c-39c949bcc1c9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"287a8ec9-482e-4501-aa26-aa8b57c5183f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"764558dd-47aa-4027-837f-cfa7cbf53c70\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"9224c10b-3726-433c-9000-1081fe1ae04c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"283187b0-23d3-4fe8-8189-c5fb55770aa0\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5c1ab3af-173c-422f-aead-41ea5f9973f4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">Other \\nstories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 140,\n          \"type\": \"text\",\n          \"id\": \"cc557f7d-b36e-4beb-99b8-b9ac9e8ee41d\",\n          \"x\": 48,\n          \"y\": -28,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 28, \"g\": 39, \"b\": 27 } },\n          \"type\": \"shape\",\n          \"x\": -112,\n          \"y\": 123,\n          \"width\": 202,\n          \"height\": 140,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8f98248e-e03b-4e4f-a1c0-04857b9ab1da\",\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"groupId\": \"77a8ba7f-2523-47ff-9031-521aec451a84\"\n        },\n        {\n          \"x\": 327,\n          \"y\": 124,\n          \"id\": \"d09e3b35-5ccc-468c-a7e8-10f7b9062221\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 28, \"g\": 39, \"b\": 27 } },\n          \"type\": \"shape\",\n          \"width\": 202,\n          \"height\": 140,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"groupId\": \"77a8ba7f-2523-47ff-9031-521aec451a84\"\n        },\n        {\n          \"x\": -112,\n          \"y\": 385,\n          \"id\": \"bc168ffd-841e-47af-b3e1-e7ec793854b3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 28, \"g\": 39, \"b\": 27 } },\n          \"type\": \"shape\",\n          \"width\": 202,\n          \"height\": 140,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"groupId\": \"77a8ba7f-2523-47ff-9031-521aec451a84\"\n        },\n        {\n          \"x\": 325,\n          \"y\": 385,\n          \"id\": \"1bbf68d0-4e83-424a-8935-ea7c64809dd1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 28, \"g\": 39, \"b\": 27 } },\n          \"type\": \"shape\",\n          \"width\": 202,\n          \"height\": 140,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"groupId\": \"77a8ba7f-2523-47ff-9031-521aec451a84\"\n        },\n        {\n          \"x\": 109,\n          \"y\": 124,\n          \"id\": \"2a6a2790-5d10-42e6-96e5-a37704ed2136\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 200,\n          \"height\": 140,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:32:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page14_image2.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in white off shoulder dress sitting on white floor\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dcbca1\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"a63ffb4c-9149-429a-b0d5-c0c21cd59f70\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16.2,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">In the Museum of Modern Art</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 108,\n          \"y\": 276,\n          \"width\": 201,\n          \"height\": 67,\n          \"id\": \"a0cad156-0467-42bb-a2c2-9c074999edf7\",\n          \"groupId\": \"a63ffb4c-9149-429a-b0d5-c0c21cd59f70\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 109,\n          \"y\": 386,\n          \"id\": \"80dbfb66-ca4b-4743-9e35-2ce531cb1102\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 200,\n          \"height\": 140,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 15,\n            \"topRight\": 15,\n            \"bottomRight\": 15,\n            \"bottomLeft\": 15,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:31:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/almodos-films/page14_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Wearing Brown Cardigan\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#533a2c\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"74b5e592-f094-4754-a09f-4e9b9fa82dcf\"\n        },\n        {\n          \"x\": 53,\n          \"y\": 538,\n          \"id\": \"203125f8-e726-4a2f-987b-0587191de874\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inknut Antiqua\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1703,\n              \"des\": -876,\n              \"tAsc\": 1703,\n              \"tDes\": -876,\n              \"tLGap\": 0,\n              \"wAsc\": 1703,\n              \"wDes\": 876,\n              \"xH\": 531,\n              \"capH\": 786,\n              \"yMin\": -846,\n              \"yMax\": 1566,\n              \"hAsc\": 1703,\n              \"hDes\": -876,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16.2,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbeb50; text-transform: uppercase\\\">The director that gives the most notes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 66,\n          \"groupId\": \"74b5e592-f094-4754-a09f-4e9b9fa82dcf\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7218025d-31be-4d95-ab4d-ce9fcf17287c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8f98248e-e03b-4e4f-a1c0-04857b9ab1da\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ccaba51d-52c2-4c6f-b528-0a8c2c0159e2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2a6a2790-5d10-42e6-96e5-a37704ed2136\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a1e32441-1552-4ca1-a561-1fb8f1773300\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d09e3b35-5ccc-468c-a7e8-10f7b9062221\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"373dfbfe-83fd-4c38-9012-e12c5b6baab7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1bbf68d0-4e83-424a-8935-ea7c64809dd1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"587b8776-6ac1-49de-a363-45b6dc880504\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"80dbfb66-ca4b-4743-9e35-2ce531cb1102\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"db447b54-1a3b-47e9-812c-59e9e094ab80\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bc168ffd-841e-47af-b3e1-e7ec793854b3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"7727f587-ccfb-430f-8e9c-8122d5d2f3d6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a0cad156-0467-42bb-a2c2-9c074999edf7\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"4b0d4831-a8ca-45ff-9a9c-8ba630aa8558\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"203125f8-e726-4a2f-987b-0587191de874\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 53, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"41e7ee5f-cc78-49bc-b99f-60b8bc7e512f\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"77a8ba7f-2523-47ff-9031-521aec451a84\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"74b5e592-f094-4754-a09f-4e9b9fa82dcf\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a63ffb4c-9149-429a-b0d5-c0c21cd59f70\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/an-artists-legacy/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/an-artists-legacy/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'an-artists-legacy',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('An Artist’s Legacy', 'template name', 'web-stories'),\n  tags: [\n    _x('Arts & Crafts', 'template keyword', 'web-stories'),\n    _x('Paint', 'template keyword', 'web-stories'),\n    _x('Artist', 'template keyword', 'web-stories'),\n    _x('Story', 'template keyword', 'web-stories'),\n    _x('Gray', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Lavender Gray', 'color', 'web-stories'),\n      color: '#eaeef4',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Baby Beluga Gray', 'color', 'web-stories'),\n      color: '#4d4c48',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pale Orange', 'color', 'web-stories'),\n      color: '#ffdcc0',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Meringue White', 'color', 'web-stories'),\n      color: '#fbf5f1',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its artistic brush strokes, white background, and art gallery-like arrangement of photos, this template will let you create beautiful stories around painting, sculpting and other arts and crafts.',\n    'web-stories'\n  ),\n  vertical: _x('Arts & Crafts', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/an-artists-legacy/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/an-artists-legacy/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"519e3414-c33d-4833-81cd-9672b9fa52d2\"\n        },\n        {\n          \"x\": 71,\n          \"y\": -58,\n          \"id\": \"55d8dd3d-34b0-47ab-a2fe-342cee96b734\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 342,\n          \"height\": 735,\n          \"scale\": 100,\n          \"focalX\": 58.46253698272626,\n          \"focalY\": 50.203001531865,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:33:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#0a60bf\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 313,\n          \"height\": 255,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"shape\",\n          \"id\": \"56b3420e-ee0a-472f-9b3a-23452b35ee20\",\n          \"x\": 71,\n          \"y\": 372\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -341,\n          \"y\": 446,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"fd4219e8-f495-48c7-9b72-f6538f71daa8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">Why Baquo’s Paintings Are His Most Sought After Works</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 89,\n          \"y\": 405,\n          \"width\": 247,\n          \"height\": 135,\n          \"id\": \"58c85b5a-60d0-4039-9738-692025552474\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2b2b2b; letter-spacing: 0.01em\\\">By: Mary Jones</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 89,\n          \"y\": 577,\n          \"width\": 165,\n          \"height\": 20,\n          \"id\": \"84a98cb9-3a36-4fbe-b7e7-2f77f58c9fab\"\n        },\n        {\n          \"x\": -58,\n          \"y\": 144,\n          \"id\": \"7e59b671-7185-4686-a937-a51913442919\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #2a2a2a; letter-spacing: 0.65em; text-transform: uppercase\\\">Artist Story</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 232,\n          \"height\": 18\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"58d5729f-4584-4416-8c59-938c142f4fe6\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e442e9a6-3816-417d-b0b1-954fa96a6dc7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": 31,\n          \"width\": 412,\n          \"height\": 645,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"512176ef-9821-4fff-9cb2-0d5c9b622cbf\",\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-08-05T11:07:18\",\n            \"baseColor\": \"#453e39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page2_bg.mp4\",\n            \"width\": 768,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 20,\n            \"lengthFormatted\": \"0:20\",\n            \"alt\": \"Video of two women talking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -28,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -120,\n          \"y\": -236,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"162dbae3-99c0-4cd5-b0a7-68e6e35a00dc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.27,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">Amy Hansson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 82.5,\n          \"y\": 6,\n          \"width\": 247,\n          \"height\": 25,\n          \"id\": \"42fb6d1e-aec6-4f02-8e8e-2f553feb2162\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2a2a2a\\\">Art Critic, Gagosian Gallery</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 89,\n          \"y\": 35,\n          \"width\": 232,\n          \"height\": 20,\n          \"id\": \"4f283010-af09-4bc0-b1bd-b3e0c8bbf4ca\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"18fe175a-ba16-4745-ad6e-42aad9ce77c2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"162dbae3-99c0-4cd5-b0a7-68e6e35a00dc\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"66677cc7-ea6d-4e53-8e98-1fc02e0af8b1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"42fb6d1e-aec6-4f02-8e8e-2f553feb2162\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"b072a13f-bdb2-43cb-8cb8-62bb7e253ddb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4f283010-af09-4bc0-b1bd-b3e0c8bbf4ca\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1e6c5855-8613-4cc7-9f53-ceb7db19bcf5\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1d1f95f4-9a99-4523-9454-49708764b009\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -321,\n          \"y\": 162,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"6ba0f089-8003-46c3-be8e-1203b29b05cd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 437,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"52f7a6bb-b25f-41ae-84ac-89655cd977da\",\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:34:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page3_image1.jpg\",\n            \"width\": 720,\n            \"height\": 693,\n            \"id\": 0,\n            \"alt\": \"Blue Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#063d81\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.27,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">Baquo’s Abs</span><span style=\\\"font-weight: 700; color: #2a2a2a\\\">tract Blues</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 78,\n          \"y\": 483,\n          \"width\": 247,\n          \"height\": 25,\n          \"id\": \"d2c10282-a056-4755-a4ed-d3f61b98f6e5\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2a2a2a; letter-spacing: 0.01em\\\">For Baquo, these blues are gestures toward cultural reclamation.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 78,\n          \"y\": 524,\n          \"width\": 232,\n          \"height\": 64,\n          \"id\": \"adf0c2be-e12c-44bb-92d3-19fbed164835\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"509df064-626b-4862-877c-4d60477a3db4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"52f7a6bb-b25f-41ae-84ac-89655cd977da\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2400,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c223180e-8f00-4ed2-af45-13a58b622458\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a51aadba-4d5c-477e-b168-86a82e7e0cd9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -105,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -53,\n          \"y\": 80,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"d3947d2e-879b-4079-8e16-f7d0479c4469\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 38,\n          \"y\": 7,\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 110,\n          \"focalX\": 50.68850267064677,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a014bb66-2837-4b53-92bb-c860100028f0\",\n          \"type\": \"image\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:34:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page4_image1.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#ccc5d8\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">“These paintings are t</span><span style=\\\"font-weight: 700; color: #2a2a2a\\\">he most raw in form, color, expression and have become icons in their own right.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 403,\n          \"width\": 258,\n          \"height\": 129,\n          \"id\": \"1095e103-e8a3-474a-8ecf-f171de5d5b46\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2a2a2a\\\">Emily Smith, Art Historian</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 568,\n          \"width\": 232,\n          \"height\": 20,\n          \"id\": \"fcbb196e-9ce4-466d-97d9-569671d3aafa\",\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 7,\n          \"id\": \"11836dc9-014d-43bc-8ba5-b11b8129bea1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 53.32859470519992,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:35:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page4_image2.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Blue Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#056edd\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8836eff1-0513-4ffc-92fa-ce5f6593b337\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d3947d2e-879b-4079-8e16-f7d0479c4469\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"af637476-c85e-4fa6-8630-8cd306c8acfa\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": -51,\n          \"width\": 720,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"0976b5a0-9c23-412d-a253-c9f85f2ffdd8\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-08-05T11:07:40\",\n            \"baseColor\": \"#393635\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page5_bg.mp4\",\n            \"width\": 720,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page5_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 20,\n            \"lengthFormatted\": \"0:20\",\n            \"alt\": \"Video of two women talking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7f6c6215-168f-45cc-849b-e72489c97c61\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"ff058f0e-fe37-4ae4-8638-b02676b27ea2\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f3d225e0-b95d-45d3-a896-d7fc5fb61118\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -193,\n          \"y\": 81,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"08962ab1-2548-4e58-9d5e-90eadd68276f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 49,\n          \"y\": 453,\n          \"width\": 363,\n          \"height\": 297,\n          \"scale\": 123,\n          \"focalX\": 56.05387665409452,\n          \"focalY\": 55.344511782929885,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1c88b0f5-223a-4fe5-a09d-1ead8409c1e2\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:44:21\",\n            \"baseColor\": \"#16252d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page6_image2.jpg\",\n            \"width\": 717,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": -1,\n          \"y\": -74,\n          \"id\": \"9f539e27-524a-4f0c-905d-9d3d7a4c661e\",\n          \"width\": 364,\n          \"height\": 269,\n          \"scale\": 179,\n          \"focalX\": 29.93402946298555,\n          \"focalY\": 39.692917607065375,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:41:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page6_image1.jpg\",\n            \"width\": 683,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#234b79\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2a2a2a; letter-spacing: 0.01em\\\">Most of his work is seen as largely autobiographical and personal work.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 68,\n          \"y\": 292,\n          \"width\": 243,\n          \"height\": 64,\n          \"id\": \"6b5e3870-dec7-4316-b14b-1f13aa423ac8\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">A personal take</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 68,\n          \"y\": 251,\n          \"width\": 258,\n          \"height\": 25,\n          \"id\": \"86418af7-9d5e-4ee6-94e5-c6f403108dbe\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1c7cc646-f850-4093-946c-02f369d7f669\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"9f539e27-524a-4f0c-905d-9d3d7a4c661e\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"abd097d5-0cbe-4379-b908-722e3da67c18\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"1c88b0f5-223a-4fe5-a09d-1ead8409c1e2\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2d7ff090-413a-4a18-9cca-0d422b004b59\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"963f13a2-8069-4114-9cb2-3ac42720a85e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 120,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -292,\n          \"y\": -245,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"3a5dffd4-75a3-4039-984c-493eb5dc2d9b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 38,\n          \"y\": 306,\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 42.454212633874036,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4eaaf4cd-7b60-4d44-a76e-edf357b37434\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:46:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page7_image1.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#dacdc5\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">“These paintings are the most raw in form, color, expression and have become icons in their own right.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 37,\n          \"width\": 258,\n          \"height\": 130,\n          \"id\": \"9821d4c7-518e-46f8-bfeb-154a15809934\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2a2a2a\\\">Paul Sons, Art Historian &nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 202,\n          \"width\": 232,\n          \"height\": 20,\n          \"id\": \"d6f91338-78d1-4c5f-bbb3-4eab30dc5360\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 223,\n          \"y\": 306,\n          \"id\": \"5d728e16-96e3-46f1-9f75-ed036c350109\",\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 106,\n          \"focalX\": 39.33070686013986,\n          \"focalY\": 47.50922803424667,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:47:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page7_image2.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#9eb0d1\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f320aeb7-8535-4568-9988-726e3920761d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3a5dffd4-75a3-4039-984c-493eb5dc2d9b\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e8bcbd70-cf90-4b65-b517-482c3ab09dc6\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"03d7d88e-3266-4533-a6d3-7a57e89771d3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 120,\n          \"y\": 600,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"3ba82cbc-c901-42e7-a3da-1b3e1bc35e54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2a2a2a\\\">He depicts himself as victim and victor,</span>\\n<span style=\\\"font-weight: 300\\\">a new concept for art of the time.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 567,\n          \"width\": 322,\n          \"height\": 42,\n          \"id\": \"bf183e1a-f2a3-4015-96d8-9b32c85f747f\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -60,\n          \"id\": \"c6b0da80-454c-42e5-ae27-0203c0689ea5\",\n          \"width\": 412,\n          \"height\": 584,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 44.441964285714306,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:49:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page8_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#cdd3d3\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d6476081-087f-4db0-9909-f7b2959000b4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3ba82cbc-c901-42e7-a3da-1b3e1bc35e54\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d5c9fb2a-994c-4ee3-93e0-6625757ec878\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8a64cef8-3d11-4002-a54b-d80ae96b80bc\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -154,\n          \"y\": -409,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"f7bbe32c-124c-4c3e-b66c-b263d6b23d9d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 91,\n          \"id\": \"aeb15097-42eb-4407-9f48-75fafbf35b73\",\n          \"width\": 412,\n          \"height\": 584,\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50.04177167641248,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:50:52\",\n            \"baseColor\": \"#e0c2a1\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page9_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1054,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2a2a2a\\\">His themes tackle, head-on, perceptions of what a Black artist can represent.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 50,\n          \"y\": 1,\n          \"width\": 322,\n          \"height\": 42,\n          \"id\": \"18018daf-65f2-4dc6-aabc-096c39afd655\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b0f88498-3842-4b6c-9ac7-86cf5fd87b41\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f7bbe32c-124c-4c3e-b66c-b263d6b23d9d\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"af58829b-e56d-4bf4-86c7-9604830d7814\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": -51,\n          \"width\": 720,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"aa6d2399-570e-49d7-91e9-79c3560611fc\",\n          \"scale\": 108,\n          \"focalX\": 50,\n          \"focalY\": 46.279761904761905,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-08-05T11:07:43\",\n            \"baseColor\": \"#433f3c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page10_bg.mp4\",\n            \"width\": 720,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page10_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 20,\n            \"lengthFormatted\": \"0:20\",\n            \"alt\": \"Video of a woman sitting with a book and talking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7ef150ba-e6c4-4dc8-9c93-87694725bda6\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"0b861cc1-6d8a-4fb1-8acc-2e67a36cfd03\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4b10dd30-d087-447e-b134-c765a50cd9ad\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 60,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -375,\n          \"y\": 91,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"df560e0d-8d0d-4a60-bb0e-f6538f8182a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 49,\n          \"y\": 453,\n          \"width\": 363,\n          \"height\": 222,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d648ffa0-6e43-46d8-b60d-f64f68af74c2\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:52:26\",\n            \"baseColor\": \"#cc9b92\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page11_image2.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Close-Up photo of multicolored abstract painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">Radical by Choice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 68,\n          \"y\": 251,\n          \"width\": 258,\n          \"height\": 25,\n          \"id\": \"645342e7-78b6-43cc-8896-fbe61c4d0d47\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2a2a2a; letter-spacing: 0.01em\\\">There’s an inherent rejection of the mainstream culture in favor of stories that are more raw, emotional and moving.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 68,\n          \"y\": 292,\n          \"width\": 258,\n          \"height\": 87,\n          \"id\": \"374546c6-e836-4891-a017-284c484dbedd\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": -1,\n          \"y\": -74,\n          \"id\": \"f8e9b469-5e50-4e41-9bee-9b81f5f6e6b9\",\n          \"width\": 364,\n          \"height\": 269,\n          \"scale\": 100,\n          \"focalX\": 50.08103695864728,\n          \"focalY\": 50.442559038564546,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:52:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page11_image1.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"yellow, brown, and green abstract painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#cab162\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f8be47b7-0aa5-481c-a15a-92072c3d7304\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"df560e0d-8d0d-4a60-bb0e-f6538f8182a9\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0895c1db-e538-4a4b-8247-2c22cc6dbb26\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9c9ab3d1-941a-4201-939c-8d8b735f107a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -30,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -193,\n          \"y\": -272,\n          \"width\": 799,\n          \"height\": 443,\n          \"sticker\": { \"type\": \"baquosBrushStroke\" },\n          \"id\": \"8cf07bd4-4672-44fa-a05f-58c725a39769\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 38,\n          \"y\": 306,\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c385ba2e-1fa0-42f7-ab06-c3d1753f7cfb\",\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:54:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page12_image1.jpg\",\n            \"width\": 480,\n            \"height\": 803,\n            \"id\": 0,\n            \"alt\": \"Blue, Orange, and White Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#11398b\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2a2a2a\\\">“These were groundbreaking when artists of the 1980s were largely white.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 36,\n          \"width\": 258,\n          \"height\": 103,\n          \"id\": \"f46e7209-c2ee-43f6-8fab-250187995c92\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2a2a2a\\\">James Doe, Art Historian</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 80,\n          \"y\": 177,\n          \"width\": 232,\n          \"height\": 20,\n          \"id\": \"80568020-8dc8-492c-8956-f5a6aef620b9\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 223,\n          \"y\": 306,\n          \"id\": \"f01dd2e3-4169-41a5-8dc0-077537ad6e81\",\n          \"width\": 142,\n          \"height\": 300,\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50.40885029089077,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 234, \"g\": 238, \"b\": 244 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:54:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page12_image2.jpg\",\n            \"width\": 480,\n            \"height\": 840,\n            \"id\": 0,\n            \"alt\": \"Multicolored Abstract Painting\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b5881\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2e410325-a6cb-4ca4-a92f-1c1ecab25991\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8cf07bd4-4672-44fa-a05f-58c725a39769\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0aba4a1d-6661-4a88-8f8c-1390df577c6f\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"41ff3c29-7ea1-45f5-8d90-527385631729\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff; letter-spacing: 0.01em\\\">Born in 1959 in New York City, Baquo was born to parents of Haitian and Dominican descent.</span>\\n\\n<span style=\\\"font-weight: 400; color: #fff; letter-spacing: 0.01em\\\">He enrolled as an apprentice at the BK Museum of Art.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 322,\n          \"height\": 132,\n          \"type\": \"text\",\n          \"id\": \"77e32ad0-40dc-4fbe-8e6c-75b7192e66fa\",\n          \"x\": 50,\n          \"y\": 308\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 339,\n          \"height\": 235,\n          \"scale\": 105,\n          \"focalX\": 48.72139615399921,\n          \"focalY\": 55.758233127535796,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 16,\n            \"right\": 16,\n            \"top\": 16,\n            \"bottom\": 16,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 85, \"g\": 85, \"b\": 85 } }\n          },\n          \"type\": \"image\",\n          \"id\": \"4054b2ae-3547-4110-b4d3-8615d805a2ae\",\n          \"x\": 50,\n          \"y\": -41,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:56:26\",\n            \"baseColor\": \"#7b6a60\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/an-artists-legacy/page13_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"A Serious Man Painting On a White Cardboard\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">About Baquo</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 247,\n          \"height\": 35,\n          \"id\": \"95c3589a-2f3b-42cc-bb5d-f8e8b361d092\",\n          \"x\": 50,\n          \"y\": 258\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0110d5ae-804c-4bbb-8acd-e85673b6614b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4054b2ae-3547-4110-b4d3-8615d805a2ae\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 30, \"g\": 32, \"b\": 31 } },\n      \"type\": \"page\",\n      \"id\": \"d17aab13-a4b3-4f06-9767-12a334a42c2e\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/art-books-gift-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/art-books-gift-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'art-books-gift-guide',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Art Books Gift Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Art', 'template keyword', 'web-stories'),\n    _x('Gift', 'template keyword', 'web-stories'),\n    _x('Recommendation', 'template keyword', 'web-stories'),\n    _x('Books', 'template keyword', 'web-stories'),\n    _x('Pink', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Petal Pink', 'color', 'web-stories'),\n      color: '#da9bb2',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Milano Red', 'color', 'web-stories'),\n      color: '#c01e00',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Voodoo Purple', 'color', 'web-stories'),\n      color: '#412c47',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its serene, comforting colors and beautiful illustrations, this template is great for creating stories about books and literature. Review books, talk about the newest releases in fiction, create reading lists and more.',\n    'web-stories'\n  ),\n  vertical: _x('Arts & Crafts', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/art-books-gift-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/art-books-gift-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7bbe1e43-0291-4e56-bc0d-d41506fa02fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Gift Guide: Art Books</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 67,\n          \"y\": 27,\n          \"width\": 250,\n          \"height\": 102,\n          \"id\": \"f6877772-87af-4046-95ba-76d84c6605fb\"\n        },\n        {\n          \"x\": 67,\n          \"y\": 148,\n          \"id\": \"f7759f78-a4c5-4b50-b234-2c6ec855e99a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Charlie Taylor</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 250,\n          \"height\": 20\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 20,\n          \"y\": 204,\n          \"width\": 406,\n          \"height\": 472,\n          \"sticker\": { \"type\": \"artWomanReading\" },\n          \"id\": \"81355f8c-39b0-42f9-b4b3-8bb3f67ba2fb\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 65, \"g\": 44, \"b\": 71 } },\n      \"type\": \"page\",\n      \"id\": \"c02e601a-0212-46d0-84d8-7b5c63e4523f\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a30970c0-6f57-4a61-951f-21d6be10ea0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">A book can often be the perfect gift, whether it’s specifically tailored to a friend’s tastes or something you personally loved.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 276,\n          \"height\": 144,\n          \"id\": \"a4162e76-7489-4258-8f6b-3cac147bf992\",\n          \"x\": 50,\n          \"y\": 77\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 66,\n          \"y\": 348,\n          \"width\": 296,\n          \"height\": 269,\n          \"sticker\": { \"type\": \"artBooks\" },\n          \"id\": \"9f6bdbef-2e18-4382-b3b5-eb50c19eb682\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 218, \"g\": 155, \"b\": 178 } },\n      \"type\": \"page\",\n      \"id\": \"0d4492e9-e0e1-4c5d-913c-bf32ef001186\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e8b1e60a-6daf-413e-8b6d-ca255916663d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #412c47; letter-spacing: 0.01em\\\">Perfect coffee table books for every art lover.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 250,\n          \"height\": 39,\n          \"id\": \"78f3930a-6395-45ea-9bf7-02b08bc76c8b\",\n          \"x\": 67,\n          \"y\": 174\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #412c47\\\">Coffee table art books</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 250,\n          \"height\": 79,\n          \"id\": \"840bb7c6-772c-4ab6-beb9-ccb415514d2d\",\n          \"x\": 67,\n          \"y\": 77\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -57,\n          \"y\": 262,\n          \"width\": 592,\n          \"height\": 510,\n          \"sticker\": { \"type\": \"artManReading\" },\n          \"id\": \"65af2559-eb01-481a-9601-12751f3cba53\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ee615b78-ac02-42c7-843e-9c1e9a78a6a6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"65af2559-eb01-481a-9601-12751f3cba53\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"40fd5d51-bcb6-4c0a-a69e-36f808ebc832\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"91ce90fc-a094-40ca-8865-6bce341b636d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T09:36:15\",\n            \"baseColor\": \"#0d188f\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page4_image1.jpg\",\n            \"width\": 480,\n            \"height\": 712,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: Peter Beard\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 42,\n          \"y\": -6,\n          \"width\": 172,\n          \"height\": 255,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a074a211-643e-4dae-94d6-0f2afaccecf5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 207,\n          \"y\": 28,\n          \"width\": 232,\n          \"height\": 328,\n          \"sticker\": { \"type\": \"artHandHeldSign\" },\n          \"id\": \"a7ff7705-466d-4145-9060-55e50fefd286\",\n          \"groupId\": \"8d2d5afc-e6f7-4c12-9103-4a3c9a5d45de\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$150</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 118,\n          \"height\": 20,\n          \"id\": \"598f304a-0826-4b36-8ce8-02adcf9fafc8\",\n          \"x\": 229,\n          \"y\": 44,\n          \"groupId\": \"8d2d5afc-e6f7-4c12-9103-4a3c9a5d45de\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 121,\n          \"id\": \"ca5afbb0-12d2-4015-9105-919fe53e918b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 5, \"vertical\": 5 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Peter Beard</span>\\n<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Taschen</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 128,\n          \"height\": 49,\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" },\n          \"groupId\": \"8d2d5afc-e6f7-4c12-9103-4a3c9a5d45de\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T09:40:24\",\n            \"baseColor\": \"#372622\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page4_image2.jpg\",\n            \"width\": 480,\n            \"height\": 607,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: Vogue and The Metropolitan Museum of Art Costume Institute: Parties,  Exhibitions, People by Hamish Bowles\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 200,\n          \"y\": 350,\n          \"width\": 172,\n          \"height\": 218,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e503d67d-7abf-4b7a-9f1e-03a3fdd96d7c\"\n        },\n        {\n          \"x\": -32,\n          \"y\": 399,\n          \"id\": \"d164f119-f0ce-4d2c-bf56-480c77b2a275\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 232,\n          \"height\": 328,\n          \"sticker\": { \"type\": \"artHandHeldSign\" },\n          \"groupId\": \"a4e09ccb-fe53-470c-9ee7-5f03f7694577\"\n        },\n        {\n          \"x\": 42,\n          \"y\": 414,\n          \"id\": \"d2157111-b18b-408c-9385-bb4a0dd58837\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$44</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 118,\n          \"height\": 20,\n          \"groupId\": \"a4e09ccb-fe53-470c-9ee7-5f03f7694577\"\n        },\n        {\n          \"x\": 42,\n          \"y\": 459,\n          \"id\": \"3b6ad9ec-a488-41ea-85f6-095878692006\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Vogue and the Met Costume Institute</span>\\n<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Amazon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 129,\n          \"height\": 77,\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" },\n          \"groupId\": \"a4e09ccb-fe53-470c-9ee7-5f03f7694577\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c22ec45c-030c-47c1-b705-5ccba0dfd7c3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a7ff7705-466d-4145-9060-55e50fefd286\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"15d89e2b-9568-4184-8dec-d5cf56829587\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ca5afbb0-12d2-4015-9105-919fe53e918b\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"747aef08-4223-4e95-831d-78be6acf06c1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"598f304a-0826-4b36-8ce8-02adcf9fafc8\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"d0954c38-54dc-47e0-9186-3b6f0b7dbf25\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d164f119-f0ce-4d2c-bf56-480c77b2a275\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"67ce3bb0-893d-4efe-b938-088f2d9ad872\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d2157111-b18b-408c-9385-bb4a0dd58837\"],\n          \"duration\": 1500,\n          \"delay\": 1750\n        },\n        {\n          \"id\": \"2b694115-bd79-470f-95e5-5f8df8e46735\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3b6ad9ec-a488-41ea-85f6-095878692006\"],\n          \"duration\": 1500,\n          \"delay\": 1750\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"41809ae0-f9ad-49aa-be25-8f02e793707a\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"8d2d5afc-e6f7-4c12-9103-4a3c9a5d45de\": {\n          \"name\": \"Sign\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a4e09ccb-fe53-470c-9ee7-5f03f7694577\": {\n          \"name\": \"Sign\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"96fdf79d-6e7a-402c-9eb7-c664697d7d6b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 232,\n          \"height\": 328,\n          \"sticker\": { \"type\": \"artHandHeldSign\" },\n          \"id\": \"77a97a80-7162-4814-96c6-e89594ec96a8\",\n          \"x\": 207,\n          \"y\": 28,\n          \"groupId\": \"c19a8f4c-52b5-498b-8483-df9f0b39505f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$40</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 118,\n          \"height\": 20,\n          \"id\": \"b3130e85-7bac-47a1-b1ec-be45dbbd6fa2\",\n          \"x\": 225,\n          \"y\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"c19a8f4c-52b5-498b-8483-df9f0b39505f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 225,\n          \"y\": 88,\n          \"id\": \"b6ced4b0-1bd5-424b-9954-cac6b2a54820\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Breaking Ground: Architecture by Women Amazon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 77,\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": null\n          },\n          \"groupId\": \"c19a8f4c-52b5-498b-8483-df9f0b39505f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 232,\n          \"height\": 328,\n          \"sticker\": { \"type\": \"artHandHeldSign\" },\n          \"id\": \"f7bc1f2c-f9e5-4a56-b6e5-1adbc8a32962\",\n          \"x\": -32,\n          \"y\": 399,\n          \"groupId\": \"452c11c2-9912-42f7-a571-a8da9f61b1c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 44,\n          \"y\": 412,\n          \"id\": \"3b395780-46aa-4406-b8c6-9fefe36a9609\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$44</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 118,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"groupId\": \"452c11c2-9912-42f7-a571-a8da9f61b1c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 44,\n          \"y\": 478,\n          \"id\": \"ea8abd53-2472-474f-b41f-c7fa2dd42be9\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">The New Black Vanguard</span>\\n<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Amazon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 129,\n          \"height\": 58,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" },\n          \"groupId\": \"452c11c2-9912-42f7-a571-a8da9f61b1c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T09:49:57\",\n            \"baseColor\": \"#fb6907\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page5_image1.png\",\n            \"width\": 480,\n            \"height\": 559,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: Breaking Ground: Architecture by Women: Hall, Jane\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 43,\n          \"y\": -6,\n          \"width\": 172,\n          \"height\": 201,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b6f492de-4a69-4cb7-81db-981d1ce06efe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T09:50:05\",\n            \"baseColor\": \"#8a5d5e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page5_image2.jpg\",\n            \"width\": 480,\n            \"height\": 651,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: The New Black Vanguard\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 200,\n          \"y\": 350,\n          \"width\": 172,\n          \"height\": 234,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"67b25a9a-bb5f-4fd7-b6d9-8fc6bd2e35bd\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cfd1cf99-243e-42de-a137-2ebf2367a44e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"77a97a80-7162-4814-96c6-e89594ec96a8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ce2571f1-da98-49fa-879d-f97d3a937003\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b6ced4b0-1bd5-424b-9954-cac6b2a54820\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"de080c78-c672-4c33-9edb-7fea51ed6dee\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b3130e85-7bac-47a1-b1ec-be45dbbd6fa2\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"3de6cd94-1882-4b22-879b-da447d59d056\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f7bc1f2c-f9e5-4a56-b6e5-1adbc8a32962\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"b64cd415-a5aa-4a9f-88de-758dbd3ba7aa\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3b395780-46aa-4406-b8c6-9fefe36a9609\"],\n          \"duration\": 1500,\n          \"delay\": 1750\n        },\n        {\n          \"id\": \"6da6ab89-0755-4e8c-8d85-960ec524d414\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ea8abd53-2472-474f-b41f-c7fa2dd42be9\"],\n          \"duration\": 1500,\n          \"delay\": 1750\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"1a932019-c548-4c31-8220-caec6987e58b\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c19a8f4c-52b5-498b-8483-df9f0b39505f\": {\n          \"name\": \"Sign\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"452c11c2-9912-42f7-a571-a8da9f61b1c2\": {\n          \"name\": \"Sign\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c0376cc7-6044-45cc-9764-070a5978b311\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #412c47\\\">Books that will make you feel like you are in the museum or an art gallery.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 58,\n          \"id\": \"31ae845b-2ca4-4b32-904a-6f8157c88c8d\",\n          \"x\": 67,\n          \"y\": 174,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #412c47\\\">Page Turning art books</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 250,\n          \"height\": 79,\n          \"id\": \"edcab60a-a58e-4f70-8d8c-0f29b59bed79\",\n          \"x\": 67,\n          \"y\": 77,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T06:42:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page6_image1.png\",\n            \"baseColor\": \"#ac3c3c\",\n            \"width\": 480,\n            \"height\": 348,\n            \"id\": 0,\n            \"alt\": \"Illustration of a photo frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -25,\n          \"y\": 292,\n          \"width\": 120,\n          \"height\": 87,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"49c80482-23c2-45de-bd5d-a418905e7312\",\n          \"groupId\": \"dbc97575-bb66-4a82-8c47-a12fcfa2de12\"\n        },\n        {\n          \"x\": 366,\n          \"y\": 304,\n          \"id\": \"da698ecc-cd48-40c5-a7b1-202284bfe55b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T06:42:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page6_image1.png\",\n            \"baseColor\": \"#ac3c3c\",\n            \"width\": 480,\n            \"height\": 348,\n            \"id\": 0,\n            \"alt\": \"Illustration of a photo frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 87,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"groupId\": \"dbc97575-bb66-4a82-8c47-a12fcfa2de12\"\n        },\n        {\n          \"x\": -14,\n          \"y\": 422,\n          \"id\": \"b9168a92-a459-4f5d-b9f2-8b60e54a1a19\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T06:42:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page6_image1.png\",\n            \"baseColor\": \"#ac3c3c\",\n            \"width\": 480,\n            \"height\": 348,\n            \"id\": 0,\n            \"alt\": \"Illustration of a photo frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 82,\n          \"height\": 59,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"groupId\": \"dbc97575-bb66-4a82-8c47-a12fcfa2de12\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 46,\n          \"y\": 256,\n          \"width\": 330,\n          \"height\": 589,\n          \"sticker\": { \"type\": \"artWomanReading02\" },\n          \"id\": \"e62ecad0-77a4-41fd-9a21-b10ae2018ebe\",\n          \"groupId\": \"dbc97575-bb66-4a82-8c47-a12fcfa2de12\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fdba78f3-6b67-4e27-99af-c1712d7edfd9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"31ae845b-2ca4-4b32-904a-6f8157c88c8d\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"025f6b9c-558f-4302-8913-4d98bc9f3577\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e62ecad0-77a4-41fd-9a21-b10ae2018ebe\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f862b177-27f8-4b11-8be2-91b9f8e2cf3c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"49c80482-23c2-45de-bd5d-a418905e7312\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5a97d19d-b31a-4384-b2e0-ddb595d6eb6a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b9168a92-a459-4f5d-b9f2-8b60e54a1a19\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"305fbdb8-c97a-4718-abd6-aa9e9f4e8ecd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"da698ecc-cd48-40c5-a7b1-202284bfe55b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 8000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"9c09ead0-3c92-4e42-8e20-17da6a6eecc8\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"dbc97575-bb66-4a82-8c47-a12fcfa2de12\": {\n          \"name\": \"Background Image\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a89ecd48-9e45-4d5b-8966-8c918f5b9d59\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 71,\n          \"y\": 458,\n          \"width\": 270,\n          \"height\": 80,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7bbe2ee2-f54e-4a81-b16b-09db2edbd897\"\n        },\n        {\n          \"x\": 71,\n          \"y\": 49,\n          \"id\": \"0ff7e277-3063-45e0-9a7a-124e064d0295\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 195, \"b\": 220 } },\n          \"type\": \"shape\",\n          \"width\": 270,\n          \"height\": 409,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 89,\n          \"y\": 66,\n          \"id\": \"2c3b2493-2951-4837-adea-0f02a30eb4b1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:03:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page7_image1.jpg\",\n            \"width\": 480,\n            \"height\": 765,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: Life with Picasso\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c87f61\",\n            \"isExternal\": true\n          },\n          \"width\": 235,\n          \"height\": 374,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$40</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 67,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"id\": \"d43c4892-2da1-453f-b3cb-0796b19e02a7\",\n          \"x\": 89,\n          \"y\": 472\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 5, \"vertical\": 5 },\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Life with PIcasso by Francois Gilot</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 153,\n          \"height\": 49,\n          \"type\": \"text\",\n          \"id\": \"671dd7d7-6455-400f-bd24-9ac377e1c793\",\n          \"x\": 150,\n          \"y\": 467,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": null\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 198,\n          \"height\": 107,\n          \"sticker\": { \"type\": \"artHands\" },\n          \"id\": \"d942d107-e000-4704-9c6d-b951b8443ea5\",\n          \"x\": 107,\n          \"y\": 592\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c4547c3b-5707-4607-9c4c-579c984da44a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2c3b2493-2951-4837-adea-0f02a30eb4b1\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"835daf1b-b6ab-46d8-8a5b-a71c952f4694\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d942d107-e000-4704-9c6d-b951b8443ea5\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"6870c42a-6aa3-46b7-83a8-53ef90ac7162\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6994e656-1ccf-4e7a-938d-c48bbf513679\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 195, \"b\": 220 } },\n          \"x\": 89,\n          \"y\": 0,\n          \"id\": \"8d9ffc82-820f-4866-b2d7-0088f89fa4ab\",\n          \"width\": 234,\n          \"height\": 355,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 72,\n          \"y\": 335,\n          \"width\": 270,\n          \"height\": 80,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0833bb21-791c-4f97-933b-3314290143f3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:05:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page8_image1.jpg\",\n            \"width\": 480,\n            \"height\": 737,\n            \"id\": 0,\n            \"alt\": \"Cover of the book: Walden\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#496733\",\n            \"isExternal\": true\n          },\n          \"x\": 104,\n          \"y\": 13,\n          \"id\": \"25485940-5d2e-498a-a936-5553ccc39e04\",\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 205,\n          \"height\": 322,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">$54</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 67,\n          \"height\": 20,\n          \"id\": \"5f27da0d-7e71-4973-b1d4-4c20b4e6c7f2\",\n          \"x\": 101,\n          \"y\": 345,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 5, \"vertical\": 5 },\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Walden by Henry David Thoreau</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 153,\n          \"height\": 49,\n          \"id\": \"287f4fb1-6f79-4d8a-9cc5-fcecf1cac6b4\",\n          \"x\": 160,\n          \"y\": 340,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 198,\n          \"height\": 107,\n          \"sticker\": { \"type\": \"artHands\" },\n          \"id\": \"fa62a01c-6375-4576-8491-a7be73526e74\",\n          \"x\": 107,\n          \"y\": 592\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #412c47; letter-spacing: 0.01em\\\">“I was surprised by the three distinct themes I found in this fascinating book.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 58,\n          \"type\": \"text\",\n          \"id\": \"2d41822e-5033-4d98-94a2-3fcdca3270ab\",\n          \"x\": 103,\n          \"y\": 446\n        },\n        {\n          \"x\": 103,\n          \"y\": 518,\n          \"id\": \"39d1b204-ddf8-4ece-89bb-ee0c561b6dc6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #412c47; letter-spacing: 0.01em\\\">Linda Newbery,</span>\\n<span style=\\\"color: #412c47; letter-spacing: 0.01em\\\">British writer</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 40,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e36fc235-ff2f-4f1f-be1b-c3f064ed32b1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fa62a01c-6375-4576-8491-a7be73526e74\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0f19e5b1-4d9e-4e97-8e75-5fd2ba24a818\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"25485940-5d2e-498a-a936-5553ccc39e04\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 184, \"g\": 184, \"b\": 207 } },\n      \"type\": \"page\",\n      \"id\": \"f4c22fc7-8bf5-41c8-a280-55d58802680a\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7935a43d-03d8-4762-b0de-e8b9e914558c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #412c47\\\">Whether it’s a page turner or something unique for your coffee table, you can’t go wrong with an art book.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 276,\n          \"height\": 97,\n          \"id\": \"2ec09536-06f3-4f5e-965a-03f13822fdbb\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 117,\n          \"id\": \"c2838699-b88f-4b38-936a-804f57775fa7\",\n          \"content\": \"<span style=\\\"color: #412c47\\\">Not to mention, holidays are just around the corner!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 276,\n          \"height\": 48,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 296,\n          \"height\": 269,\n          \"sticker\": { \"type\": \"artBooks\" },\n          \"id\": \"e608b6d2-0aa8-4f7a-b744-1b819cde4dc3\",\n          \"x\": 66,\n          \"y\": 348\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 218, \"g\": 155, \"b\": 178 } },\n      \"type\": \"page\",\n      \"id\": \"f55be543-f8e9-46cd-9b43-8b4463471b82\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e986f066-e518-496b-b6cf-36aa675b202c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 17,\n          \"width\": 307,\n          \"height\": 41,\n          \"id\": \"6b5e8d9d-ad87-42a7-ae5b-594ea8f1ee0c\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:18:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page10_image1.jpg\",\n            \"width\": 480,\n            \"height\": 673,\n            \"id\": 0,\n            \"alt\": \"Man on sofa\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#29333b\",\n            \"isExternal\": true\n          },\n          \"x\": 20,\n          \"y\": 119,\n          \"width\": 177,\n          \"height\": 248,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"840c4b09-46f1-4939-a795-52af1bff9e88\"\n        },\n        {\n          \"x\": 195,\n          \"y\": 119,\n          \"id\": \"be852c25-89f2-4ba3-8c56-d1b66af5a6c1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 217,\n          \"height\": 248,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 0,\n          \"y\": 367,\n          \"id\": \"8c74e67f-b16e-4e43-aad7-a2417d328323\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 196,\n          \"height\": 248,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 196,\n          \"y\": 367,\n          \"id\": \"2462790e-886f-41f5-b649-4126a8fe5340\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:18:33\",\n            \"baseColor\": \"#342c26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/art-books-gift-guide/page10_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman in black blazer using macbook pro\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 196,\n          \"height\": 248,\n          \"scale\": 100,\n          \"focalX\": 50.19435535332219,\n          \"focalY\": 47.29712804514386,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00; letter-spacing: 0.01em\\\">Inside the Studio with Christopher Wool</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 77,\n          \"type\": \"text\",\n          \"id\": \"bf227f0e-886f-490f-b7d4-2211c7418bf0\",\n          \"x\": 219,\n          \"y\": 214,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": null\n          },\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 462,\n          \"id\": \"33739323-584a-485a-be33-d2edbaaf2d71\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; text-decoration: underline; color: #c01e00\\\">Inside the Studio with Barbara Kruger</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 58,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" },\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4d59da0e-fa76-4100-bc5c-c445f1e02ecc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2462790e-886f-41f5-b649-4126a8fe5340\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ef22432f-0e5f-47d4-a6f1-035e1dd1a27f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"840c4b09-46f1-4939-a795-52af1bff9e88\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 65, \"g\": 44, \"b\": 71 } },\n      \"type\": \"page\",\n      \"id\": \"86c0e307-d8ad-4bbb-9829-a32fa5e7ba8a\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/baking-bread-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/baking-bread-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'baking-bread-guide',\n  creationDate: '2021-07-13T00:00:00.000Z',\n  title: _x('Baking Bread Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Food', 'template keyword', 'web-stories'),\n    _x('Cooking', 'template keyword', 'web-stories'),\n    _x('Recipe', 'template keyword', 'web-stories'),\n    _x('Bread', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n    _x('Violet', 'template keyword', 'web-stories'),\n    _x('Guide', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Hawaii Blue', 'color', 'web-stories'),\n      color: '#bcebee',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Earth Violet', 'color', 'web-stories'),\n      color: '#2d2a35',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Papaya Orange', 'color', 'web-stories'),\n      color: '#fff0d8',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its earthy tones and vintage elegance, this template is perfect for creating instructionals that are calm and soothing. Use it for recipes, woodworking tutorials, meditation guides, or anything that could use some rustic charm.',\n    'web-stories'\n  ),\n  vertical: _x('Cooking', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/baking-bread-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/baking-bread-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"de01aa50-cfbb-438d-a357-5d5e3fdac4a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 412,\n          \"height\": 484,\n          \"scale\": 118,\n          \"focalX\": 50,\n          \"focalY\": 33.01094072280514,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1d5e5fbc-5fc6-4707-8430-c96ee46482de\",\n          \"x\": 0,\n          \"y\": -57,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:02:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page01_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page01_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#b09b88\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"width\": 37,\n          \"height\": 35,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"058e4521-038d-4034-be16-f80248526262\",\n          \"x\": 57,\n          \"y\": 402\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #bcebee; letter-spacing: 0.4em; text-transform: uppercase\\\">Bak'n with Em</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 183,\n          \"height\": 16,\n          \"id\": \"01fa0fd7-aeb2-43f4-b52e-b1731b2290e3\",\n          \"x\": 114.5,\n          \"y\": 449\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.04em\\\">Beginner’s Guide</span>\\n<span style=\\\"color: #fff0d8; letter-spacing: 0.04em\\\">to Baking Bread</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 78,\n          \"id\": \"b77a2dd4-5b1f-4b65-ad07-0689182056df\",\n          \"x\": 48,\n          \"y\": 489,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #bcebee\\\">Emma Keys</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 19,\n          \"id\": \"a32f5187-3902-428f-94ba-9faa7555ef4b\",\n          \"x\": 38,\n          \"y\": 584\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"21cf9649-5574-4038-bd34-e297eca0a920\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ae80a8d5-0bc5-41dd-ad68-6c3637eb573d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": -16,\n          \"y\": 333,\n          \"width\": 446,\n          \"height\": 358,\n          \"scale\": 138,\n          \"focalX\": 39.07292385553255,\n          \"focalY\": 46.35764128517751,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cb08239a-51c6-48f6-a516-aea526bbb0e1\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:04:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page02_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page02_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#372e25\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 188, \"g\": 235, \"b\": 238 } },\n          \"type\": \"shape\",\n          \"width\": 46,\n          \"height\": 44,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"0e87fa78-9538-4fb6-beb2-5237d820da3d\",\n          \"x\": 36,\n          \"y\": 310\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"So, I hear you want to bake bread! You’ve come to the right place. Making bread is both easy and rewarding, especially if you learn these 6 fast rules for making bread.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 182,\n          \"id\": \"2a0e6c2d-2b10-4b9d-9efe-5bf60e3e3d3d\",\n          \"x\": 49,\n          \"y\": 39,\n          \"marginOffset\": 3.299999999999997,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"\\nLet’s get started!\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 55,\n          \"marginOffset\": 3.299999999999997,\n          \"id\": \"dccf045e-6b78-4db1-9447-e2583a5e93b2\",\n          \"x\": 50,\n          \"y\": 220,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7a815ce1-b866-4bd8-9e92-b4cb4a0d1bc1\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"dccf045e-6b78-4db1-9447-e2583a5e93b2\"],\n          \"scale\": 0.06,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 3000\n        },\n        {\n          \"id\": \"68aaabfa-3ded-4a86-aa87-b04c7eacd79f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"cb08239a-51c6-48f6-a516-aea526bbb0e1\"],\n          \"scale\": 0.01,\n          \"iterations\": 1,\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 188, \"g\": 235, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"a5371335-75d1-4360-828d-d8a0ec8b0485\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"5b16c66f-673d-4b95-84bd-587b329a825e\",\n          \"scale\": 102,\n          \"focalX\": 49.190187142565364,\n          \"focalY\": 50.10941876750701,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T11:36:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page03_bg_video.mp4\",\n            \"width\": 768,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page03_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 30,\n            \"lengthFormatted\": \"0:30\",\n            \"alt\": \"page03_bg_video\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#928e86\"\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.22 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">There is nothing mysterious about making bread! Practice makes perfect so bake, bake, bake!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 301,\n          \"height\": 235,\n          \"id\": \"afc1d24f-a73c-4375-9e78-198f71a7eeb8\",\n          \"x\": 64,\n          \"y\": 372,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">“</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 150,\n          \"height\": 44,\n          \"id\": \"9e47f0f8-d0c2-48ba-8436-f27f919a29e2\",\n          \"x\": 48,\n          \"y\": 362\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fa833674-57f8-4311-80bc-de1817acc6e7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"da50f3de-460e-4c42-bf3c-67dbe2d0ae77\"\n      },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5136483c-631b-4bde-bcea-c8246d639aca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">6 Fast Rules For Making Bread</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 88,\n          \"id\": \"16a1e440-3dca-42c6-abc1-d139939023e1\",\n          \"x\": 48,\n          \"y\": 0,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">01</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">Use fresh ingredients - especially yeast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 136,\n          \"height\": 116,\n          \"id\": \"00f94fef-2e30-4849-aeaa-e5d627e25006\",\n          \"x\": 59,\n          \"y\": 159,\n          \"groupId\": \"dd43b0fa-072f-4a02-8846-86b32ca0ca30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 97,\n          \"y\": 151,\n          \"width\": 33,\n          \"height\": 40,\n          \"sticker\": { \"type\": \"yeastPackage\" },\n          \"id\": \"3f1bc3f7-c9cf-44c0-8263-30f739d37db8\",\n          \"groupId\": \"dd43b0fa-072f-4a02-8846-86b32ca0ca30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">02</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">Storage: dry is nice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 108,\n          \"height\": 86,\n          \"id\": \"92b13dac-b7bf-4b20-8a30-c2440824eb99\",\n          \"x\": 237,\n          \"y\": 159,\n          \"groupId\": \"cf61d1d8-02fb-4d0d-af5e-ba7e7be08669\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 279,\n          \"y\": 140,\n          \"width\": 33,\n          \"height\": 52,\n          \"sticker\": { \"type\": \"thermometer\" },\n          \"id\": \"db3ce326-32cd-4a9c-9466-547b17186779\",\n          \"groupId\": \"cf61d1d8-02fb-4d0d-af5e-ba7e7be08669\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">03</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">Use the right flour</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 118,\n          \"height\": 92,\n          \"id\": \"11615f30-317c-4620-bcd1-4a95f73c1dbb\",\n          \"x\": 59,\n          \"y\": 339,\n          \"groupId\": \"f2346ced-a649-41c8-a9a4-f79c95cd05f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 100,\n          \"y\": 330,\n          \"width\": 27,\n          \"height\": 37,\n          \"sticker\": { \"type\": \"jar\" },\n          \"id\": \"f98bf842-45d7-4587-939f-1f0b7bd32723\",\n          \"groupId\": \"f2346ced-a649-41c8-a9a4-f79c95cd05f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">04</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">Temperature and yeast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 116,\n          \"height\": 91,\n          \"id\": \"e22cd567-66ac-425d-8611-f2d2f1fb21d1\",\n          \"x\": 237,\n          \"y\": 339,\n          \"groupId\": \"9bb74869-ce4c-43a1-9a46-c748b0a00d95\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 273,\n          \"y\": 337,\n          \"width\": 46,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"dough\" },\n          \"id\": \"a2e91787-181c-409d-a6f3-a449dc2698c3\",\n          \"groupId\": \"9bb74869-ce4c-43a1-9a46-c748b0a00d95\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">05</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">To knead or not to knead</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 136,\n          \"height\": 92,\n          \"id\": \"7c520025-e6f3-452e-94c5-c0d0ca0a8c82\",\n          \"x\": 59,\n          \"y\": 497,\n          \"groupId\": \"54e505b6-550c-4976-9e30-cf0b903ee9af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 94,\n          \"y\": 484,\n          \"width\": 36,\n          \"height\": 38,\n          \"sticker\": { \"type\": \"flourBag\" },\n          \"id\": \"2c9c36c0-13ce-41ae-a799-19eea39ffdff\",\n          \"groupId\": \"54e505b6-550c-4976-9e30-cf0b903ee9af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.01em\\\">06</span>\\n\\n<span style=\\\"color: #bcebee; letter-spacing: 0.01em\\\">Prescribed rising times</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 119,\n          \"height\": 92,\n          \"id\": \"3119b163-57ce-431e-96d7-569f2d462b56\",\n          \"x\": 237,\n          \"y\": 497,\n          \"groupId\": \"b8f993b0-d14c-4267-900c-33c2c2a5e814\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 277,\n          \"y\": 493,\n          \"width\": 41,\n          \"height\": 30,\n          \"sticker\": { \"type\": \"flourBowl\" },\n          \"id\": \"e818b9d9-cfd1-4f18-ab15-072f0adb3ec7\",\n          \"groupId\": \"b8f993b0-d14c-4267-900c-33c2c2a5e814\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"79e2585d-8701-4ddc-b016-36237b33e53f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"3f1bc3f7-c9cf-44c0-8263-30f739d37db8\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"54113d5e-ed2f-48e7-90e6-801e812df172\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"db3ce326-32cd-4a9c-9466-547b17186779\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"e6955f60-b6cf-4a08-8bab-fb084356e2c9\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"f98bf842-45d7-4587-939f-1f0b7bd32723\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"5ff59de1-48f8-42ac-b842-febd3d72cd61\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"a2e91787-181c-409d-a6f3-a449dc2698c3\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 2100\n        },\n        {\n          \"id\": \"e88fe987-c922-4491-bf95-364f586531e6\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"2c9c36c0-13ce-41ae-a799-19eea39ffdff\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 2700\n        },\n        {\n          \"id\": \"edcb666d-4127-40e8-9df2-0dceec837cb5\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e818b9d9-cfd1-4f18-ab15-072f0adb3ec7\"],\n          \"scale\": 0.2,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 3300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"3bebb81e-b6bf-4b85-92ef-27c958f7b3c2\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"dd43b0fa-072f-4a02-8846-86b32ca0ca30\": {\n          \"name\": \"Fresh\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"cf61d1d8-02fb-4d0d-af5e-ba7e7be08669\": {\n          \"name\": \"Storage\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f2346ced-a649-41c8-a9a4-f79c95cd05f8\": {\n          \"name\": \"Flour\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9bb74869-ce4c-43a1-9a46-c748b0a00d95\": {\n          \"name\": \"Yeast\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"54e505b6-550c-4976-9e30-cf0b903ee9af\": {\n          \"name\": \"Knead\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b8f993b0-d14c-4267-900c-33c2c2a5e814\": {\n          \"name\": \"Bowl\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"764c9a54-9130-4b1a-8ede-fa06d6a1d468\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 412,\n          \"height\": 452,\n          \"scale\": 115,\n          \"focalX\": 49.705845423943224,\n          \"focalY\": 56.52173913043478,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d40aed6a-b833-4f82-93c6-b65d2e2fc0f1\",\n          \"x\": 0,\n          \"y\": -59,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:05:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page05_image1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page05_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#9b8988\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"width\": 48,\n          \"height\": 46,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"53be6e2a-5359-4321-a0e3-db39db99126b\",\n          \"x\": 37,\n          \"y\": 365\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Use fresh ingredients - especially yeast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 64,\n          \"id\": \"71459ccb-fea5-45bd-b97f-d3305bbd1f06\",\n          \"x\": 101,\n          \"y\": 435\n        },\n        {\n          \"x\": 48,\n          \"y\": 435,\n          \"id\": \"2446c1cd-46e9-4392-bada-6b17973d3f4d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 37,\n          \"height\": 30,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 101,\n          \"y\": 518,\n          \"id\": \"c935d5f6-ca44-4263-b130-06b16f0876e5\",\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">To ensure a good lift and a beautiful outer crust, you’ll want to start with fresh yeast and baking powder/soda</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 99\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"dbcb59d0-1ecf-403b-8eef-5d9f0d595a3c\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"aa48759a-6296-4317-961c-f74e3b3b79fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 430,\n          \"height\": 452,\n          \"scale\": 143,\n          \"focalX\": 62.153903387331034,\n          \"focalY\": 68.67475141397557,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fc207625-f197-4ddb-980c-7b8cd535de9e\",\n          \"x\": -9,\n          \"y\": -58,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:17:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page06_image1.jpg\",\n            \"width\": 900,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page06_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#6e5f4f\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 45,\n          \"height\": 42,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"310a1d2d-9c15-4180-bab9-e82b5a68a71f\",\n          \"x\": 38,\n          \"y\": 371\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Storage: Dry is nice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 31,\n          \"id\": \"7f8d3dad-7463-4d82-9246-75dbce5a4670\",\n          \"x\": 102,\n          \"y\": 435\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 30,\n          \"height\": 30,\n          \"id\": \"4ad093bc-7a41-4ba5-8d92-c5257c1e9d4b\",\n          \"x\": 48,\n          \"y\": 435,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"Always store your baking ingredients in a dry place at room temperature. Never refrigerate.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 98,\n          \"id\": \"1db9ee9a-200d-4316-9721-acd1dc25eefd\",\n          \"x\": 102,\n          \"y\": 488\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"09e3254f-73d9-4e45-a888-510d39a554c0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"aa48759a-6296-4317-961c-f74e3b3b79fe\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"96332d53-9ec9-45ff-95c6-63fa71ce3069\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 412,\n          \"height\": 452,\n          \"scale\": 150,\n          \"focalX\": 51.32275132275132,\n          \"focalY\": 57.76014109347444,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d89a2156-a2b1-4dc8-9d65-41d4e8bb409e\",\n          \"x\": 0,\n          \"y\": -59,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:21:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page07_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page07_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#a09ea6\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"width\": 48,\n          \"height\": 46,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"c596ffca-5b22-4df1-8b7e-3e2a5592659f\",\n          \"x\": 37,\n          \"y\": 365,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Use the Right Flour</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 31,\n          \"id\": \"0e2903f7-5393-4897-bb17-64260280028a\",\n          \"x\": 101,\n          \"y\": 435,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 48,\n          \"y\": 435,\n          \"id\": \"1f4f5e00-54e2-4ce0-99ca-d1c6989a0362\",\n          \"content\": \"<span style=\\\"color: #fff\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 37,\n          \"height\": 31,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 101,\n          \"y\": 488,\n          \"id\": \"d8acea82-3fe0-403e-b330-aa5946dcb61a\",\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">Get good bread flour. It’s ground specifically for making bread!&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 73,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"2a131a9b-cf36-4961-86a9-9ccc8a7a6f64\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Learn About Flour\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"02869b8a-bc1c-40c7-b0ce-f0f649f51b32\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 412,\n          \"height\": 452,\n          \"scale\": 107,\n          \"focalX\": 47.120837613107994,\n          \"focalY\": 50.47567366063136,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a72425c1-32f5-459f-ad35-fb94eb7fe514\",\n          \"x\": 0,\n          \"y\": -59,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:23:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page08_image1.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page08_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ebe7dd\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 52,\n          \"height\": 46,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"d33cf65c-dac1-4f38-9a13-2402573e6010\",\n          \"x\": 37,\n          \"y\": 366,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Temperature and Yeast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 263,\n          \"height\": 30,\n          \"id\": \"b92e076a-8b69-400e-8d1a-4ece201afd76\",\n          \"x\": 101,\n          \"y\": 435,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 30,\n          \"height\": 31,\n          \"id\": \"33a33767-1230-485c-93eb-99d36f94bc1c\",\n          \"x\": 48,\n          \"y\": 435,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"Make sure your liquid is between 95 degrees F and 115 degrees F when adding to yeast.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 98,\n          \"id\": \"c3acbb73-11bc-4e08-a1c3-63b32deb8b9a\",\n          \"x\": 101,\n          \"y\": 490,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"eea9d5d5-8b17-4943-a1c6-3a56f040eccd\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"02869b8a-bc1c-40c7-b0ce-f0f649f51b32\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"56455d14-495c-408c-8e13-1a53975e7e48\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 412,\n          \"height\": 452,\n          \"scale\": 115,\n          \"focalX\": 51.048429287851604,\n          \"focalY\": 49.37094242728904,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2fbb2f16-e99e-4d0e-a7ae-be892480d711\",\n          \"x\": 0,\n          \"y\": -59,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:24:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page09_image1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page09_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#cec5bf\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"width\": 48,\n          \"height\": 46,\n          \"mask\": { \"type\": \"triangle\" },\n          \"type\": \"shape\",\n          \"id\": \"975f6314-92ae-40d8-a317-b875ba97f8ae\",\n          \"x\": 37,\n          \"y\": 365\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">To knead or not to knead</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 63,\n          \"id\": \"27daba3e-d36f-4819-a10d-54e63bd9b85c\",\n          \"x\": 101,\n          \"y\": 435,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 48,\n          \"y\": 435,\n          \"id\": \"be956d2e-177b-4263-bdf4-0662cbb725e0\",\n          \"content\": \"<span style=\\\"color: #fff\\\">05</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 37,\n          \"height\": 31,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 101,\n          \"y\": 518,\n          \"id\": \"2d86e11c-8491-4f94-9e09-e90bce600859\",\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">Quick breads usually don’t require kneading (think cake mix) while yeast bread requires some kneading.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 98,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"e9734daf-b847-40d4-8821-2a8b944381bf\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2e9270bd-9e9e-42de-995f-c1a11c408431\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 412,\n          \"height\": 452,\n          \"scale\": 113,\n          \"focalX\": 48.826315885723645,\n          \"focalY\": 45.84826594826905,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bef5e047-e2bb-4798-bdfd-4de3282c2b39\",\n          \"x\": 0,\n          \"y\": -59,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:26:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page10_image1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image1\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#c4c5c2\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 52,\n          \"height\": 46,\n          \"mask\": { \"type\": \"triangle\" },\n          \"type\": \"shape\",\n          \"id\": \"f55181ef-456d-4620-bac0-bea368f6d159\",\n          \"x\": 37,\n          \"y\": 366\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Prescribed rising times</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 275,\n          \"height\": 30,\n          \"id\": \"fda34afa-4e74-43e5-98af-84dce551bd8d\",\n          \"x\": 101,\n          \"y\": 435,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">06</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 30,\n          \"height\": 31,\n          \"id\": \"7479e9b3-a69d-49e4-a561-3998150c81aa\",\n          \"x\": 48,\n          \"y\": 435,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"Follow the prescribed rising time. Use a timer. Too long and you might have a sour-tasting loaf or a dry bread with abundance of holes!\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 261,\n          \"height\": 123,\n          \"id\": \"c8758f4c-0797-4a2d-b836-014c081660cf\",\n          \"x\": 101,\n          \"y\": 488,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c8b945df-3d70-47c6-9fec-66d98cea42ac\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"2e9270bd-9e9e-42de-995f-c1a11c408431\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bd8e099a-5ce9-4423-9e94-2ab1934a0557\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 191,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b694f1a5-c447-4572-be03-0abfcd19ae0e\",\n          \"x\": 0,\n          \"y\": 485,\n          \"groupId\": \"349da810-9017-4e1c-972b-99f4f335f79e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"width\": 26,\n          \"height\": 24,\n          \"mask\": { \"type\": \"triangle\" },\n          \"id\": \"f2bd63d3-1e19-4863-8743-a52d68cf0ead\",\n          \"x\": 65,\n          \"y\": 466,\n          \"groupId\": \"349da810-9017-4e1c-972b-99f4f335f79e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 65,\n          \"y\": 4,\n          \"width\": 92,\n          \"height\": 66,\n          \"sticker\": { \"type\": \"breadBun\" },\n          \"id\": \"4f62eec7-72aa-4c6e-b414-192925454393\",\n          \"groupId\": \"9d04824c-f1cb-439a-a908-4b6c69a6afca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">Beginner Bread Recipe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 199,\n          \"height\": 78,\n          \"id\": \"d25f125a-751f-453a-8b2b-82f91d1b8b9c\",\n          \"x\": 164,\n          \"y\": 0,\n          \"groupId\": \"9d04824c-f1cb-439a-a908-4b6c69a6afca\"\n        },\n        {\n          \"x\": 66,\n          \"y\": 294,\n          \"id\": \"8b105649-9015-4c21-90b2-9242f0dda07e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">White Homemade Bread</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 115,\n          \"height\": 68,\n          \"marginOffset\": 0.06000000000000005,\n          \"groupId\": \"689d34df-a852-421d-a8b0-eb0fbf057331\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 195,\n          \"y\": 281,\n          \"id\": \"3838e975-9f05-4195-9202-c9c3a2a11871\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 153,\n          \"height\": 96,\n          \"scale\": 149,\n          \"focalX\": 49.28283514955857,\n          \"focalY\": 49.043780199411444,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:28:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page11_image2.jpg\",\n            \"width\": 480,\n            \"height\": 360,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page11_image2\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#998d78\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"689d34df-a852-421d-a8b0-eb0fbf057331\"\n        },\n        {\n          \"x\": 66,\n          \"y\": 186,\n          \"id\": \"835c0875-e0c3-42aa-b2ca-a157c263498e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Sour French Baguette</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 115,\n          \"height\": 46,\n          \"marginOffset\": 0.06000000000000005,\n          \"groupId\": \"a28e72c2-599f-4fbd-b06a-48ed6b3b8481\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 195,\n          \"y\": 161,\n          \"width\": 153,\n          \"height\": 96,\n          \"scale\": 147,\n          \"focalX\": 58.723066344144655,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"95df0e77-bdab-4709-a33e-b43f1cc44349\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T11:27:57\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page11_image1.jpg\",\n            \"width\": 480,\n            \"height\": 360,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page13_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#694c3d\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"a28e72c2-599f-4fbd-b06a-48ed6b3b8481\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Emma Ray Keys</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 192,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"id\": \"27242169-2379-41c1-82b1-21bda1ab40b4\",\n          \"x\": 65,\n          \"y\": 549,\n          \"groupId\": \"890df759-960b-404e-a9c7-c0999dc07269\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 18\n          },\n          \"content\": \"<span style=\\\"color: rgba(255,240,216,0.6)\\\">Visit </span><span style=\\\"text-decoration: underline; color: #bcebee\\\">Bak’n With Em</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 212,\n          \"height\": 57,\n          \"type\": \"text\",\n          \"id\": \"d2036eb8-eaef-4054-b4c4-1b12cb5acba6\",\n          \"x\": 57,\n          \"y\": 575,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": \"\"\n          },\n          \"marginOffset\": 2.549999999999997,\n          \"groupId\": \"890df759-960b-404e-a9c7-c0999dc07269\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 265,\n          \"y\": 541,\n          \"width\": 84,\n          \"height\": 84,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9521ce09-9a52-404b-9b80-3471a0cf5561\",\n          \"borderRadius\": {\n            \"topLeft\": 44,\n            \"topRight\": 44,\n            \"bottomRight\": 44,\n            \"bottomLeft\": 44,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 4,\n            \"right\": 4,\n            \"top\": 4,\n            \"bottom\": 4,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 100, \"g\": 100, \"b\": 100 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:36:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/baking-bread-guide/page11_image3.jpg\",\n            \"width\": 87,\n            \"height\": 88,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page11_image3\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#916c52\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"890df759-960b-404e-a9c7-c0999dc07269\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e04e89fc-fb3d-49b4-8769-e9017bf3b4d8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4f62eec7-72aa-4c6e-b414-192925454393\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"944a066e-319a-4f03-9684-62e59ad704c6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f2bd63d3-1e19-4863-8743-a52d68cf0ead\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"b8cdc29a-014a-43d1-8c57-0c1e21bcf9d9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b694f1a5-c447-4572-be03-0abfcd19ae0e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f8bbfbc3-2a8b-4389-b8ae-61330527256b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9521ce09-9a52-404b-9b80-3471a0cf5561\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"cafbf116-952d-4b66-b685-c456dbf9deac\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d2036eb8-eaef-4054-b4c4-1b12cb5acba6\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1700,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"db42f161-c39a-4777-bfab-832bcceb90c9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"27242169-2379-41c1-82b1-21bda1ab40b4\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5e448bcd-223a-42af-bb53-b2b676948f32\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"bd8e099a-5ce9-4423-9e94-2ab1934a0557\"\n      },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"a28e72c2-599f-4fbd-b06a-48ed6b3b8481\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"689d34df-a852-421d-a8b0-eb0fbf057331\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"890df759-960b-404e-a9c7-c0999dc07269\": {\n          \"name\": \"Emma\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9d04824c-f1cb-439a-a908-4b6c69a6afca\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"349da810-9017-4e1c-972b-99f4f335f79e\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/beauty-quiz/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/beauty-quiz/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'beauty-quiz',\n  creationDate: '2021-06-28T00:00:00.000Z',\n  title: _x('Beauty Quiz', 'template name', 'web-stories'),\n  tags: [\n    _x('Fashion & Beauty', 'template keyword', 'web-stories'),\n    _x('Skin Care', 'template keyword', 'web-stories'),\n    _x('Personal Care', 'template keyword', 'web-stories'),\n    _x('Shapes', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Courtyard Green', 'color', 'web-stories'),\n      color: '#397165',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pink Wash', 'color', 'web-stories'),\n      color: '#f8dfdc',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Aquatic Green', 'color', 'web-stories'),\n      color: '#aec2bf',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its soft pink shade, lightweight typography and rounded shapes, this template is just right for creating stories in the beauty and personal care niche. Create questonnaires, skincare routines, product promotions and more that look pretty and feel pleasant.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion & Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/beauty-quiz/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/beauty-quiz/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -258,\n          \"y\": -193,\n          \"width\": 726,\n          \"height\": 889,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"d3c66373-d2ce-4295-bb5e-5e1ffe20aee9\",\n          \"scale\": 170,\n          \"focalX\": 63.41535688285285,\n          \"focalY\": 54.82062729983297,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page01_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Topless woman sitting on bathtub with yellow flowers\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#99684c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -156,\n          \"y\": 295,\n          \"width\": 571,\n          \"height\": 409,\n          \"sticker\": { \"type\": \"beautyQuizGreenBlob\" },\n          \"id\": \"380bdeec-030d-4b2b-b5ad-b3c921e16e23\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Beauty Quiz for Your Best Skin Ever</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 67,\n          \"y\": 367,\n          \"width\": 263,\n          \"height\": 132,\n          \"id\": \"45c9b8e5-68bc-4682-92c8-f45b1051296e\",\n          \"marginOffset\": -3.3062499999999986\n        },\n        {\n          \"x\": 238,\n          \"y\": 567,\n          \"id\": \"ff1d2f99-fec1-4935-833d-b36d66e0b1fa\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Ann Kv Atowich</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 16,\n          \"marginOffset\": 3.421875\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9182a7be-e7cb-4206-bee1-09ec8ecbba01\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1c04adad-e90d-47c7-b885-251c6a765211\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -47,\n          \"y\": -215,\n          \"width\": 523,\n          \"height\": 894,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"2035c185-344a-4a74-80f4-001552afa5ac\",\n          \"scale\": 128,\n          \"focalX\": 50.10471501347897,\n          \"focalY\": 53.471401897273175,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T07:43:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page02_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman washing her face\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#daa992\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -88,\n          \"y\": 196,\n          \"width\": 571,\n          \"height\": 391,\n          \"sticker\": { \"type\": \"beautyQuizPinkBlob\" },\n          \"id\": \"b7f2bc51-3992-4b74-9184-e4033f4adc3e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Trying to figure out the right set of products and building a beauty regimen can be confusing. Take our quiz for an easy serving of what steps to incorporate into your daily routine.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 53,\n          \"y\": 289,\n          \"width\": 280,\n          \"height\": 150,\n          \"id\": \"0f8418e7-2885-42c5-a2c9-b7fece4613b6\",\n          \"marginOffset\": 0.6187499999999986\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"451ac27e-3812-445c-bbd1-e8e8de50f7c0\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"targets\": [\"2035c185-344a-4a74-80f4-001552afa5ac\"],\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleIn\",\n          \"panDir\": \"topToBottom\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0788c382-d3f6-4b11-85e3-da77baf68b8e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e5606ca7-7efd-4acd-b98f-8aa91141ae00\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2c5353ad-e81e-4d4f-96cd-dd77c42d4aae\"\n        },\n        {\n          \"x\": 78,\n          \"y\": 0,\n          \"id\": \"f58ec61b-6b3f-46ab-8355-42e99abb92f1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #1e0404\\\">01 / 04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 70,\n          \"height\": 16,\n          \"marginOffset\": 8.896874999999994\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Let's start with the basics. What is your age range?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 89,\n          \"marginOffset\": 0.703125,\n          \"id\": \"0313916c-44be-44b1-b5de-f8dd2d8014ab\",\n          \"x\": 78,\n          \"y\": 140\n        },\n        {\n          \"x\": 78,\n          \"y\": 97,\n          \"id\": \"9afb766f-6742-49bd-816b-668b73389c56\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #1e0404; text-transform: uppercase\\\">QUESTION</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 16,\n          \"marginOffset\": 2.84659090909091\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 317,\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d87e7fe2-868f-4602-84d0-907bdebea91a\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          }\n        },\n        {\n          \"x\": 47,\n          \"y\": 416,\n          \"id\": \"e0808680-a000-4216-a5e7-2fb9d60d17b3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          }\n        },\n        {\n          \"x\": 47,\n          \"y\": 517,\n          \"id\": \"591728f6-f5a2-4162-b3dd-b2482325372b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          }\n        },\n        {\n          \"x\": 173.5,\n          \"y\": 348,\n          \"id\": \"c51e338a-436e-4f83-94be-ca644df3750c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">18-24</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 65,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986\n        },\n        {\n          \"x\": 166,\n          \"y\": 448,\n          \"id\": \"361e513b-a25c-48f1-a0be-599b3d88bbba\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">25-35</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986\n        },\n        {\n          \"x\": 170,\n          \"y\": 548,\n          \"id\": \"dd0d4345-1f24-4bf1-82b7-09116af2fb04\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">36-45</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 72,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d5757cb8-a08b-41c9-b3fc-228f684c3153\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"d87e7fe2-868f-4602-84d0-907bdebea91a\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d6c44880-5c2a-427c-9bb5-0434db5466cc\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e0808680-a000-4216-a5e7-2fb9d60d17b3\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"faeb19c1-f8d4-430e-9a54-f40eeb2d8613\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"591728f6-f5a2-4162-b3dd-b2482325372b\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 248, \"g\": 223, \"b\": 220 } },\n      \"type\": \"page\",\n      \"id\": \"f4ff91ec-9190-4f2e-a0f7-30606c615b39\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"944efad3-ae12-4638-b143-b48fa23c5c40\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 0,\n          \"id\": \"40db48cd-8787-460f-8f46-c225e188c91e\",\n          \"content\": \"<span style=\\\"color: #1e0404\\\">02 / 04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 49,\n          \"height\": 16,\n          \"marginOffset\": 3.421875,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Do you have any skin concerns?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 61,\n          \"marginOffset\": 0.703125,\n          \"id\": \"d74eb94c-1702-4dbb-8c41-cef2b6f52015\",\n          \"x\": 78,\n          \"y\": 140,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 97,\n          \"id\": \"f6857a9d-ffd3-46c4-beb4-a9c3a4bbd33f\",\n          \"content\": \"<span style=\\\"color: #1e0404; text-transform: uppercase\\\">QUESTION</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 16,\n          \"marginOffset\": 2.84659090909091,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 317,\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"75a306cd-9cad-4b82-b2d2-ae630630aea9\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 49,\n          \"y\": 417,\n          \"id\": \"14d6fdbc-36af-4d61-aa96-50174cbe8637\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 517,\n          \"id\": \"ea5b4f0d-8954-4a92-8398-7cadd15b8df9\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 158,\n          \"y\": 348,\n          \"id\": \"0d872af9-68a4-4bf2-a625-ad57c3b5b12b\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Pregnant</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 97,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 164,\n          \"y\": 448,\n          \"id\": \"964763e8-7cff-41f3-b2df-9b76625af59a\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Eczema</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 108.5,\n          \"y\": 548,\n          \"id\": \"f586254a-907d-445a-a64f-99308d0b6e9f\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Seasonal allergies</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 194,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 248, \"g\": 223, \"b\": 220 } },\n      \"type\": \"page\",\n      \"id\": \"43b31c51-4f14-48fc-bd83-4115cada9c88\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5231e51a-9245-4662-8169-40795cd1864b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 571,\n          \"height\": 409,\n          \"sticker\": { \"type\": \"beautyQuizGreenBlob\" },\n          \"id\": \"b137c337-7cc4-4a44-b325-9dc823f87234\",\n          \"x\": -43,\n          \"y\": 331,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page05_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Topless woman putting lipstick on her lips\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfcecc\",\n            \"isExternal\": true\n          },\n          \"x\": 86.5,\n          \"y\": 81,\n          \"width\": 223,\n          \"height\": 292,\n          \"scale\": 119,\n          \"focalX\": 54.803100864703936,\n          \"focalY\": 50.1152744207529,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"72044a70-0fe9-41c9-a4e5-a1ec4ed71abd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#bab19e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page05_07_frame.png\",\n            \"width\": 629,\n            \"height\": 772,\n            \"id\": 0,\n            \"alt\": \"Frame baguette creativity picture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 49,\n          \"y\": 34,\n          \"width\": 314,\n          \"height\": 385,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f07308f5-d530-402a-9582-4d4064066fcb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Great! Lets move onto your skin concerns</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 109,\n          \"marginOffset\": -2.9468749999999986,\n          \"id\": \"ed3fe49d-37e8-4f2b-be90-18efc60afb9b\",\n          \"x\": 65,\n          \"y\": 488,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 174, \"g\": 194, \"b\": 191 } },\n      \"type\": \"page\",\n      \"id\": \"e34d8064-5238-406b-8da8-7bae03252844\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"86bef967-4e35-40d1-a2de-81edd43de4e4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 0,\n          \"id\": \"84afa341-30d8-4508-9735-e9b959fc00c9\",\n          \"content\": \"<span style=\\\"color: #1e0404\\\">03 / 04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 46,\n          \"height\": 16,\n          \"marginOffset\": 3.421875,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">What's your ideal skin look like?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 59,\n          \"marginOffset\": 0.703125,\n          \"id\": \"a2a31a1c-00a8-4044-adcb-6befe1910e31\",\n          \"x\": 78,\n          \"y\": 140,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 97,\n          \"id\": \"a6e03012-b9f7-4f20-a56c-badc016a12be\",\n          \"content\": \"<span style=\\\"color: #1e0404; text-transform: uppercase\\\">QUESTION</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 16,\n          \"marginOffset\": 2.84659090909091,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 317,\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a579951c-7207-46d4-b5d6-edab44005fe5\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 417,\n          \"id\": \"5eb852cd-8837-4f6c-87a4-ea6b3a9014b9\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 517,\n          \"id\": \"526c5c01-5df7-47bc-909f-48d75189892b\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 158,\n          \"y\": 348,\n          \"id\": \"605e3181-c2e2-4af1-baae-e1f40e799f7a\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Bright</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 97,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 138.5,\n          \"y\": 448,\n          \"id\": \"896b41cf-0e4a-446f-abe5-88f9650ec21b\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Glowy, dewy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 135,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 109,\n          \"y\": 548,\n          \"id\": \"a48bd3a4-92fc-4a82-913d-9515874b9da3\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">Even, calm</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 194,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 248, \"g\": 223, \"b\": 220 } },\n      \"type\": \"page\",\n      \"id\": \"c09660a0-330e-451e-be8e-98c71faedb61\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"940fa4cb-8e5e-4c13-9334-1a5da89fc552\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 571,\n          \"height\": 409,\n          \"sticker\": { \"type\": \"beautyQuizGreenBlob\" },\n          \"id\": \"ffda7a52-2471-40fb-a607-87e788cbec45\",\n          \"x\": -43,\n          \"y\": 331,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page07_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman sitting and smiling\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c2b2a4\",\n            \"isExternal\": true\n          },\n          \"x\": 94.5,\n          \"y\": 81,\n          \"width\": 223,\n          \"height\": 292,\n          \"scale\": 123,\n          \"focalX\": 46.06736816461503,\n          \"focalY\": 50.055631846496865,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7c49ccc3-06da-4aa8-af9d-802d38f49696\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-28T13:34:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page05_07_frame.png\",\n            \"width\": 629,\n            \"height\": 772,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Frame baguette creativity picture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#405e50\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 49,\n          \"y\": 34,\n          \"width\": 314,\n          \"height\": 385,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1db40776-20ef-4c95-903d-10461113988a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Almost Done!</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Only one final question.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 109,\n          \"marginOffset\": -2.9468749999999986,\n          \"id\": \"b55ba81b-0dcf-48f7-962d-3771adae861a\",\n          \"x\": 65,\n          \"y\": 488,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 174, \"g\": 194, \"b\": 191 } },\n      \"type\": \"page\",\n      \"id\": \"c04e612f-31c6-4d99-b193-8a00bfe15406\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5877f68f-9b90-4f02-a97f-e2949fc44ba0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 0,\n          \"id\": \"7221c892-fa68-4bbd-99b6-1dc1139f00ca\",\n          \"content\": \"<span style=\\\"color: #1e0404\\\">04 / 04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 45,\n          \"height\": 16,\n          \"marginOffset\": 3.421875,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">How much time do you have each morning for skincare?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 266,\n          \"height\": 92,\n          \"marginOffset\": 0.703125,\n          \"id\": \"aa1fdf83-461a-49ed-8726-2f4ceb944202\",\n          \"x\": 78,\n          \"y\": 140,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 97,\n          \"id\": \"8c582e3a-6fd4-4f9f-9f9b-73c178b0e0b3\",\n          \"content\": \"<span style=\\\"color: #1e0404; text-transform: uppercase\\\">QUESTION</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 16,\n          \"marginOffset\": 2.84659090909091,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 317,\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f25d1bcb-9462-4d94-b6ce-6e54b547bbc4\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 417,\n          \"id\": \"374e9e8c-406f-429f-b9cd-40b371efc3de\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 47,\n          \"y\": 517,\n          \"id\": \"9f4d5214-e843-434c-8ea2-9868df5ecb44\",\n          \"width\": 317,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 84,\n          \"y\": 348,\n          \"id\": \"f3272c5d-c503-4dcf-8817-e22f6ed18c95\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">5 mins or less</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 139,\n          \"y\": 448,\n          \"id\": \"d609d546-692e-4ba7-8cdd-a5f5dc35adca\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">30 mins</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 135,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 109,\n          \"y\": 548,\n          \"id\": \"38933f56-29e5-4b64-a329-2373c73c456a\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #1e0404\\\">1 hour</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 194,\n          \"height\": 26,\n          \"marginOffset\": 0.3374999999999986,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 248, \"g\": 223, \"b\": 220 } },\n      \"type\": \"page\",\n      \"id\": \"f1f00788-891d-41a7-8c6b-ac5c6f7c348d\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8b981230-4f52-4e02-ab1b-27a969a1e92a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">You need a brightening and clarifying regimen.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 113,\n          \"marginOffset\": 0.703125,\n          \"id\": \"89054a81-950e-446e-8aca-6ddba66353a6\",\n          \"x\": 78,\n          \"y\": 77,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 78,\n          \"y\": 302,\n          \"id\": \"4ed6b780-7e96-4d6a-9532-a3f4dc985609\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Evenness</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 18,\n          \"marginOffset\": 2.4670454545454543,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 164,\n          \"y\": 415,\n          \"id\": \"41abd4ca-8158-4380-a40a-352e926d529c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Brightening dullness</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 98,\n          \"height\": 40,\n          \"marginOffset\": 3.2261363636363605,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 246,\n          \"y\": 544,\n          \"id\": \"cf396d80-f35e-4ce0-b294-16b4c18f3490\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Dewy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 98,\n          \"height\": 18,\n          \"marginOffset\": 3.2261363636363605,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 77,\n          \"y\": 249,\n          \"id\": \"dd4709f9-db6a-4219-81ba-92af9f20f51a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">10%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 90,\n          \"height\": 66,\n          \"marginOffset\": -3.3687500000000057,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 164,\n          \"y\": 360,\n          \"id\": \"12565a1e-7e46-4f62-bdb2-8934f0d69790\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">38%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 90,\n          \"height\": 64,\n          \"marginOffset\": -3.3687500000000057,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 246,\n          \"y\": 491,\n          \"id\": \"54282bed-a600-4d24-ac41-4aa714533e92\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">40%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 90,\n          \"height\": 64,\n          \"marginOffset\": -3.3687500000000057,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cc3b0375-fae1-4713-ac70-5814450d4b9a\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"dd4709f9-db6a-4219-81ba-92af9f20f51a\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"beb03753-0187-4609-b6de-1aaabe7e9bb8\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"12565a1e-7e46-4f62-bdb2-8934f0d69790\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"fd4d9158-e560-4aab-9deb-4615e930c97a\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"54282bed-a600-4d24-ac41-4aa714533e92\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1450,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 248, \"g\": 223, \"b\": 220 } },\n      \"type\": \"page\",\n      \"id\": \"e9381f9f-129e-4b03-b84f-b6f01e512df2\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a1acef79-d979-4df7-bca9-a01105bf9d17\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T07:48:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page10_image01.jpg\",\n            \"width\": 576,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding dropper\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a5765d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -17,\n          \"y\": -67,\n          \"width\": 446,\n          \"height\": 566,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8f0326d6-951f-46e9-b2f8-4b716c2159f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 571,\n          \"height\": 409,\n          \"sticker\": { \"type\": \"beautyQuizGreenBlob\" },\n          \"id\": \"20075941-d9c4-406b-b2e9-ec5b107f3e76\",\n          \"x\": -43,\n          \"y\": 331,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Kjaer Weis Beautiful Oil</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 30,\n          \"marginOffset\": -2.9468749999999986,\n          \"id\": \"02657fa3-2a3a-4fd3-85d4-d882f0e15e75\",\n          \"x\": 64,\n          \"y\": 426,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 64,\n          \"y\": 471,\n          \"id\": \"b6a35ee7-e424-4f42-9144-0fd647c8d860\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">It may sound counterintuitive to use an oil, but this one evens out skin tone and natural levels of hydration for an all over even skin tone.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 82,\n          \"marginOffset\": -2.9468749999999986,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"014c65f3-a00e-40c6-8853-dfa5904f25a0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8f0326d6-951f-46e9-b2f8-4b716c2159f8\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b38694ef-3332-4d80-a224-390b1d5e244f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"20075941-d9c4-406b-b2e9-ec5b107f3e76\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 174, \"g\": 194, \"b\": 191 } },\n      \"type\": \"page\",\n      \"id\": \"5a6b2c2c-83e5-46e6-8462-c89c7e8a84f6\",\n      \"pageAttachment\": {\n        \"url\": \"google.com\",\n        \"ctaText\": \"GET PRODUCT\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5b5ac72b-5816-4d68-b8b4-555396a164b0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T07:49:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page11_image01.jpg\",\n            \"width\": 733,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Drops of lotion on pink background\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#fbc7cb\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -6,\n          \"y\": -59,\n          \"width\": 521,\n          \"height\": 511,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"50ef34b8-b12d-4ece-b144-a97988def504\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 571,\n          \"height\": 409,\n          \"sticker\": { \"type\": \"beautyQuizGreenBlob\" },\n          \"id\": \"edb4959a-aad7-428d-9b1d-e187c8520e97\",\n          \"x\": -43,\n          \"y\": 331,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">La Mer's The Tonic</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 30,\n          \"marginOffset\": -2.9468749999999986,\n          \"id\": \"d6748315-85fb-441e-8ed5-13b8e4e2069e\",\n          \"x\": 64,\n          \"y\": 426,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 64,\n          \"y\": 469,\n          \"id\": \"4d89d11f-ca6e-40ac-b2ae-2ccc3eb9f2fc\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">A refreshing toner that balances and refreshes the complexion.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 40,\n          \"marginOffset\": -2.9468749999999986,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 174, \"g\": 194, \"b\": 191 } },\n      \"type\": \"page\",\n      \"id\": \"f8fca7e6-ed47-47e7-a9f7-5372278d2cad\",\n      \"pageAttachment\": {\n        \"url\": \"google.com\",\n        \"ctaText\": \"GET PRODUCT\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"38278aef-3754-4281-b3fe-18a3c38f537b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">More beauty tips for your skin type</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 75,\n          \"marginOffset\": -2.9468749999999986,\n          \"type\": \"text\",\n          \"id\": \"925e2838-c184-4740-944d-736e7874816e\",\n          \"x\": 53,\n          \"y\": 29\n        },\n        {\n          \"x\": 185,\n          \"y\": 203,\n          \"id\": \"a4e47588-1a7a-415b-8de5-efc836d8c90d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">5 steps to a brighter complexion</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 47,\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 349,\n          \"id\": \"1183e006-e4ed-4881-b105-f3dfba8eed5d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">When to exfoliate and how to do it</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 47,\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 185,\n          \"y\": 472,\n          \"id\": \"fb1b1001-5350-4893-a317-809f4cd98579\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1e0404\\\">Serums and oils for your nighttime routine</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 71,\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 239,\n          \"y\": 329,\n          \"width\": 122,\n          \"height\": 106,\n          \"sticker\": { \"type\": \"beautyQuizTiltedGreenBlob\" },\n          \"id\": \"47cae18d-3068-4772-907e-a103a60b3e11\"\n        },\n        {\n          \"x\": 37,\n          \"y\": 194,\n          \"id\": \"00b30c06-d0f2-42e2-b6a7-e77b6edf3011\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 122,\n          \"height\": 106,\n          \"sticker\": { \"type\": \"beautyQuizTiltedGreenBlob\" }\n        },\n        {\n          \"x\": 34,\n          \"y\": 464,\n          \"id\": \"b6bc201a-f6b2-41a2-aee8-70e493d480d0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 109,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 122,\n          \"height\": 106,\n          \"sticker\": { \"type\": \"beautyQuizTiltedGreenBlob\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T08:19:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page12_image02.png\",\n            \"width\": 476,\n            \"height\": 477,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman with red lipstick and blonde hair\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ebd1bf\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 226,\n          \"y\": 313,\n          \"width\": 116,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"09de8fdf-14ab-4940-9345-6b9c0c32e634\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T08:19:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page12_image03.png\",\n            \"width\": 476,\n            \"height\": 476,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in black and white floral shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e0ada2\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 53,\n          \"y\": 446,\n          \"width\": 116,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"25836408-6521-4282-8ce0-a6e6f55cf6e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-21T07:49:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/beauty-quiz/page12_image01.png\",\n            \"width\": 476,\n            \"height\": 477,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in gray monokini\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d5af91\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 53,\n          \"y\": 180,\n          \"width\": 116,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7b0d5dee-c22a-4c8a-9e53-b49f869aa9eb\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e5f9c98d-2631-4581-a861-dcb553b2c61d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a4e47588-1a7a-415b-8de5-efc836d8c90d\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"551b142d-d48d-44e1-9bae-490c038fe449\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7b0d5dee-c22a-4c8a-9e53-b49f869aa9eb\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"53faa28f-16f4-4650-94b4-a640e9281e37\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"47cae18d-3068-4772-907e-a103a60b3e11\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"8a14235f-af7d-40e7-b9c3-6056ef74e927\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"00b30c06-d0f2-42e2-b6a7-e77b6edf3011\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1699f5af-2732-44d9-b7c6-73dca8b9078a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"09de8fdf-14ab-4940-9345-6b9c0c32e634\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"ce87b27d-5574-4d5f-8071-38fd3a178d01\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1183e006-e4ed-4881-b105-f3dfba8eed5d\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"68d567e0-db26-4485-b301-30f5c7fc9588\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fb1b1001-5350-4893-a317-809f4cd98579\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"3a65d4e3-7d97-45a3-ac4a-c547b0257abf\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"25836408-6521-4282-8ce0-a6e6f55cf6e3\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"1e8e9660-8e29-46c7-a227-89f5d05caee5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b6bc201a-f6b2-41a2-aee8-70e493d480d0\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9f816b1c-2e08-434a-a6eb-9033cf5cd99b\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/belly-fat-workout/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/belly-fat-workout/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'belly-fat-workout',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Belly Fat Workout', 'template name', 'web-stories'),\n  tags: [\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Workout', 'template keyword', 'web-stories'),\n    _x('Tutorial', 'template keyword', 'web-stories'),\n    _x('Simple', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Lime Green', 'color', 'web-stories'),\n      color: '#e0ff8c',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Slime Green', 'color', 'web-stories'),\n      color: '#d6fd56',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Whitesmoke', 'color', 'web-stories'),\n      color: '#f9f9f9',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Flat design, bright colors, and bold typography. This template will let you keep text to a minimum and clearly demonstrate your workout routine with videos.',\n    'web-stories'\n  ),\n  vertical: _x('Health & Wellness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/belly-fat-workout/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/belly-fat-workout/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"23915bae-b34d-4929-a8e4-450d7c34e26a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#323943\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page01_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"Young Sportswoman Working Out With Battle Ropes In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -0.5,\n          \"y\": -58,\n          \"width\": 413,\n          \"height\": 734,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c84585dc-9218-4b14-b263-63d72fd72a33\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 214, \"g\": 253, \"b\": 86, \"a\": 0.6 }\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"86f89631-269e-4ec5-98e3-82478de2adc3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">KILL BELLY FAT IN </span><span style=\\\"color: #fff; text-transform: uppercase\\\">15</span><span style=\\\"text-transform: uppercase\\\"> MINUTES</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 43,\n          \"y\": 187,\n          \"width\": 324,\n          \"height\": 275,\n          \"id\": \"f5a69faf-517a-45a1-adc8-98ed77c0a323\",\n          \"marginOffset\": 0.8518749999999997\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"Written by Betty Doe\\nJuly 23, 2020\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 126,\n          \"y\": 473,\n          \"width\": 158,\n          \"height\": 41,\n          \"id\": \"c4cfe316-478a-4d58-9662-5916e1cde062\",\n          \"marginOffset\": 0.4781249999999986\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"f0d308dc-15f3-4959-ae9c-fc0c1ddb65c7\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"30a032e7-04e6-4f6a-a8db-c127cdd46e1f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:34:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page02_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Carries Dumbbells\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#adb1a8\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -37.5,\n          \"y\": -119.5,\n          \"width\": 487,\n          \"height\": 863,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ff9ba174-1598-4a23-a296-e4fde7f44703\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0e091abc-cc10-497e-9e38-f66b5fcbe9f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #d6fd56; letter-spacing: 0.01em; text-transform: uppercase\\\">elly jordan</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 68,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"id\": \"26858498-5688-45aa-b8db-7ee40c925d81\",\n          \"x\": 51,\n          \"y\": 459,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">A fitness guru when it comes to at-home workouts. She's trained celebrities and fitness teams with her methodical, guided approach.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 90,\n          \"marginOffset\": 5.69318181818182,\n          \"type\": \"text\",\n          \"id\": \"09d161b2-9e38-4b24-ad38-1dc8e19132b4\",\n          \"x\": 51,\n          \"y\": 522\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9c7138a7-f80f-4340-906c-9ddf15c93bfa\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"09d161b2-9e38-4b24-ad38-1dc8e19132b4\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"39436374-235b-4d36-a0d9-55ce03643162\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e9667391-1bbb-4608-8197-31929d3a2d68\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:56:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page03_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page03_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 12,\n            \"lengthFormatted\": \"0:12\",\n            \"alt\": \"Footage Of A Young Sportswoman Working Out With A Skipping Rope In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#c2c0c0\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -261,\n          \"y\": -59,\n          \"width\": 935,\n          \"height\": 521,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"cfec8136-1264-4ef6-8193-8478e0536da5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -17,\n          \"y\": 384,\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"bad04e66-3686-49a6-89dc-a673f2669b2b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">JUMP ROPE WARM UP</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 117,\n          \"marginOffset\": -18.9,\n          \"id\": \"b25c087d-5036-4bb0-9b3b-09ef24e20076\",\n          \"x\": 51,\n          \"y\": 465,\n          \"type\": \"text\",\n          \"groupId\": \"db97d712-7a5f-47ea-9953-92ccd56eb611\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"3d1aa735-2127-48d7-927a-4b54866b24e4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 8x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"db97d712-7a5f-47ea-9953-92ccd56eb611\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 392,\n          \"id\": \"f7370472-ec38-4b15-b9be-9545e4b27331\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"db97d712-7a5f-47ea-9953-92ccd56eb611\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"39aaf0c4-5d21-4669-bf52-ab078c26bff5\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"f7370472-ec38-4b15-b9be-9545e4b27331\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dea1d52d-1350-4c72-a3b3-84f0fb211f90\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"3d1aa735-2127-48d7-927a-4b54866b24e4\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"a489d228-c0e9-4d44-a6e3-25cef15b0c54\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"db97d712-7a5f-47ea-9953-92ccd56eb611\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e808f5ae-174b-4fa1-83f4-cd5b05faedd7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:56:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page04_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page04_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 6,\n            \"lengthFormatted\": \"0:06\",\n            \"alt\": \"Footage Of A Young Sportswoman Doing Sit Ups While Working Out In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#293241\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -237,\n          \"y\": -59,\n          \"width\": 958,\n          \"height\": 539,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"59aee87c-9cac-41a7-a649-82184af4e2c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"1e67f834-8a69-441f-a640-d8d963982e75\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">AB CRUNCHES</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 68,\n          \"marginOffset\": -18.9,\n          \"id\": \"892648f8-1887-4623-a5ba-d125d4563c1a\",\n          \"x\": 51,\n          \"y\": 514,\n          \"type\": \"text\",\n          \"groupId\": \"5ee257c1-8f55-4251-9f7c-99d8eaf3fac9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"e5a3ba83-9e64-4978-8d61-540895ce8f62\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 8x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"5ee257c1-8f55-4251-9f7c-99d8eaf3fac9\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 391,\n          \"id\": \"6f3d0683-411d-461e-88b6-4660ca29c6d8\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"5ee257c1-8f55-4251-9f7c-99d8eaf3fac9\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a9c997b2-3171-4237-a9e7-84a224a62b7d\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"6f3d0683-411d-461e-88b6-4660ca29c6d8\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"37657f8a-1b25-4ef0-a217-17095c82058f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e5a3ba83-9e64-4978-8d61-540895ce8f62\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"e4060b3c-f59d-441c-bb62-acc4244a51e0\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5ee257c1-8f55-4251-9f7c-99d8eaf3fac9\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"993c02b0-c80d-4b6b-921b-32f7f2dc58bd\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page05_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page05_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 11,\n            \"lengthFormatted\": \"0:11\",\n            \"alt\": \"Footage Of A Young Sportswoman Working Out With Battle Ropes In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#353b46\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -222,\n          \"y\": -61,\n          \"width\": 943,\n          \"height\": 534,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b8850130-fb9d-40d2-81ad-ccf98d834a4b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"4891ce42-8347-452f-afcb-9e16d9572940\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">BATTLE </span>\\n<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">ROPE WAVE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 117,\n          \"marginOffset\": -18.9,\n          \"id\": \"26862c80-fc12-4ad0-91c2-b727f6857a44\",\n          \"x\": 51,\n          \"y\": 465,\n          \"type\": \"text\",\n          \"groupId\": \"870782ef-3d17-407d-b6cb-2d471e02f792\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"31803504-4ba8-4cca-9b39-67caaebff486\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 16x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"870782ef-3d17-407d-b6cb-2d471e02f792\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 392,\n          \"id\": \"fcd0d318-243a-472b-a24f-69afa50b25d1\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"870782ef-3d17-407d-b6cb-2d471e02f792\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a1aec702-33ec-4857-9dc9-02ec006781b9\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"fcd0d318-243a-472b-a24f-69afa50b25d1\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7a5fdba1-6a9b-4bfc-9743-2acc0614e812\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"31803504-4ba8-4cca-9b39-67caaebff486\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"625eed82-64bc-463d-9de0-c794f14a2beb\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"870782ef-3d17-407d-b6cb-2d471e02f792\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1f925140-bf93-4e0c-8ba5-93b280cc540b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page06_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page06_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 14,\n            \"lengthFormatted\": \"0:14\",\n            \"alt\": \"Footage Of A Young Sportswoman Working Out With Kettle Bells In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#283036\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -262,\n          \"y\": -58,\n          \"width\": 937,\n          \"height\": 527,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"faf0ee54-7d46-4bee-a34a-398ded701cd9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"80c4d764-ca75-4959-987d-3eb02b2729b8\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">KETTLEBELL</span>\\n<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">LUNGE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 117,\n          \"marginOffset\": -18.9,\n          \"id\": \"b0261658-f0f5-464e-a555-8d40395706ea\",\n          \"x\": 51,\n          \"y\": 465,\n          \"type\": \"text\",\n          \"groupId\": \"c4326598-ebda-45a4-af40-c728b1d0cb44\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"9af14d2b-7061-4c72-a67e-64ee4906533b\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 8x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"c4326598-ebda-45a4-af40-c728b1d0cb44\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 392,\n          \"id\": \"c9054608-a576-469c-9172-ffe0883f5211\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"c4326598-ebda-45a4-af40-c728b1d0cb44\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c7ca2128-9414-4e2c-8177-03ed82b69992\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"c9054608-a576-469c-9172-ffe0883f5211\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"71961ca9-ca04-4a03-bf95-f909dc4965fc\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"9af14d2b-7061-4c72-a67e-64ee4906533b\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"5acce07d-999b-4d1e-8fcb-e1b632f6147f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c4326598-ebda-45a4-af40-c728b1d0cb44\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"44807a0e-fef7-4920-ae64-31cdb996b362\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page07_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page07_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 7,\n            \"lengthFormatted\": \"0:07\",\n            \"alt\": \"Footage Of A Young Sportswoman Doing Push Ups While Working Out In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#363a46\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -362,\n          \"y\": -59,\n          \"width\": 934,\n          \"height\": 527,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7211cea1-3c98-46e6-addf-366d876e0378\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"3b65c35e-f567-486d-9726-924b8ec7f548\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">PUSH-UPS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 68,\n          \"marginOffset\": -18.9,\n          \"id\": \"c1c133cc-284f-4467-964a-3e4740427276\",\n          \"x\": 51,\n          \"y\": 514,\n          \"type\": \"text\",\n          \"groupId\": \"7bbc3e62-830c-4af7-aacb-2e6c3b7db0e6\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"6784c4ae-6f96-423e-bbab-fad7982f870b\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 8x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"7bbc3e62-830c-4af7-aacb-2e6c3b7db0e6\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 392,\n          \"id\": \"804b84ce-167f-4dde-a0bc-0806b41c5832\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"7bbc3e62-830c-4af7-aacb-2e6c3b7db0e6\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fb0a32aa-df8d-47b2-86f1-6de171e74466\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"804b84ce-167f-4dde-a0bc-0806b41c5832\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f5f8052f-37c5-4efd-8bc6-a2f22459374e\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"6784c4ae-6f96-423e-bbab-fad7982f870b\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"2ff689e5-3d4b-4f5a-9b4b-02ecd54e06ff\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7bbc3e62-830c-4af7-aacb-2e6c3b7db0e6\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b4e26505-7991-4055-949e-ff95b7c31e90\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page08_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page08_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 10,\n            \"lengthFormatted\": \"0:10\",\n            \"alt\": \"Footage Of A Young Sportswoman Working Out With A Kettle Bell In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#212b32\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -385,\n          \"y\": -62,\n          \"width\": 943,\n          \"height\": 531,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"946153a4-1b2a-4e16-821f-d887c303fa9b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"ae169475-d791-45bb-8d10-8644248f957e\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">KETTLEBELL</span>\\n<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">SWINGS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 117,\n          \"marginOffset\": -18.9,\n          \"id\": \"19820766-a470-451b-bf66-08b40c53bbe7\",\n          \"x\": 51,\n          \"y\": 465,\n          \"type\": \"text\",\n          \"groupId\": \"3ce287fb-164f-40e6-ace4-4d2fb3bddb56\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"fd4f4ceb-ff05-4e0e-bfbb-7c956beac753\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 16x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"3ce287fb-164f-40e6-ace4-4d2fb3bddb56\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 392,\n          \"id\": \"6096276e-9e15-434c-af8e-6b2658837382\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"3ce287fb-164f-40e6-ace4-4d2fb3bddb56\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9452fac9-53ad-497e-a885-569b9f3fc2d1\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"6096276e-9e15-434c-af8e-6b2658837382\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"366e1a6b-579c-4ed6-81f1-fe18c529dd10\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"fd4f4ceb-ff05-4e0e-bfbb-7c956beac753\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"4fc62051-3f22-4cbc-b081-5188d9f1df42\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"3ce287fb-164f-40e6-ace4-4d2fb3bddb56\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d1c82eea-e913-4ac0-94b4-c0271f82dbcd\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page09_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page09_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 7,\n            \"lengthFormatted\": \"0:07\",\n            \"alt\": \"Footage Of A Young Sportswoman Working Out With A Weight Plate In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#292b32\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -403,\n          \"y\": -60,\n          \"width\": 936,\n          \"height\": 528,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d641feec-6663-4ada-9ad1-d4c559b4383a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 446,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"homeWorkoutSectionSeparator\" },\n          \"id\": \"5c7a909d-ab2e-4810-b5c5-e05ed9d8b5b7\",\n          \"x\": -17,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f9f9f9; letter-spacing: 0.01em; text-transform: uppercase\\\">LATERAL CRUNCH FINISH</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 117,\n          \"marginOffset\": -18.9,\n          \"id\": \"e32e2a3b-f55d-47d0-8061-e2423b2d2ce8\",\n          \"x\": 51,\n          \"y\": 465,\n          \"type\": \"text\",\n          \"groupId\": \"dc15a953-de68-45c9-a4d2-fe4afbaf7daf\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 583,\n          \"id\": \"c45bac82-3050-4cb0-9d5c-098f3a085cb9\",\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">repeat: 10x</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 28,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"dc15a953-de68-45c9-a4d2-fe4afbaf7daf\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 55,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 393,\n          \"id\": \"e379e224-fcf6-402d-8c6a-75ceb3ccfcc4\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #d6fd56\\\">7</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 67,\n          \"marginOffset\": -18.9,\n          \"type\": \"text\",\n          \"groupId\": \"dc15a953-de68-45c9-a4d2-fe4afbaf7daf\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cc9649ef-bdf6-49e8-8701-61cf478fc134\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e379e224-fcf6-402d-8c6a-75ceb3ccfcc4\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"71744d88-5a43-4746-81f3-4f92f9154826\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"c45bac82-3050-4cb0-9d5c-098f3a085cb9\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"6566be53-d1fe-45f7-b8f3-8225d70d1184\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"dc15a953-de68-45c9-a4d2-fe4afbaf7daf\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2b851710-373c-44fe-b75b-a9f9b93ec69c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:57:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page10_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page10_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"Footage Of A Young Sportswoman Taking A Break While Working Out In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#28333a\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -446,\n          \"y\": -60,\n          \"width\": 1398,\n          \"height\": 782,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"686be377-803d-46ec-a6b1-1a2020b17260\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"bd0986c3-00b8-44df-ad93-03927c5809e1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3d0f17fc-9db8-4196-b5f2-355df710cea4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T10:58:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page11_bgvideo.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page11_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 5,\n            \"lengthFormatted\": \"0:05\",\n            \"alt\": \"Footage Of An Unrecognizable Young Sportswoman Applying Talcum Powder To Her Hands In A Gym\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#d8dde2\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": -494,\n          \"y\": -91,\n          \"width\": 1401,\n          \"height\": 798,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"07a525ed-f231-4cec-a488-e6371229368f\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"629e63fc-7bc3-4557-bfbb-f767f3f40e3d\",\n      \"pageAttachment\": {\n        \"url\": \"google.com\",\n        \"ctaText\": \"Watch the full video\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"11295a10-e76b-4286-b8c0-d977ed79d855\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:34:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page12_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman In Black Tank Top And Black Shorts Sitting On Floor\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#383534\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -56,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f4029ba3-e3b3-4545-be48-c4d9affcab78\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #d6fd56; text-transform: uppercase\\\">OTHER WORKOUTS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 129,\n          \"marginOffset\": -18.9,\n          \"id\": \"b81a0d70-c939-4d77-80c9-37f0b0eb35b1\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 238,\n          \"y\": 220,\n          \"id\": \"df2e9106-0be7-491c-884e-3fd4aadcf9e0\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Full Body Workout for Beach Body</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 120,\n          \"height\": 73,\n          \"marginOffset\": -5.5,\n          \"type\": \"text\",\n          \"groupId\": \"00c35a38-8d4c-4a2e-99c8-c30bfdd9fb4c\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:34:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page12_image01.png\",\n            \"width\": 289,\n            \"height\": 232,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman In Black Sports Bra And Black Leggings Wearing Black Boxing Gloves\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfcfd2\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 66,\n          \"y\": 171,\n          \"width\": 145,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"640a75e9-138a-4d1e-bdf4-4b39f6a13282\",\n          \"groupId\": \"00c35a38-8d4c-4a2e-99c8-c30bfdd9fb4c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:34:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page12_image02.png\",\n            \"width\": 289,\n            \"height\": 232,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman In Black Tank Top And Leggings Doing Exercise\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3d7db\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 66,\n          \"y\": 306,\n          \"width\": 145,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"987bbbde-cd36-486b-9fc1-a1ec637acc8f\",\n          \"groupId\": \"d5b52bcf-ff85-4e32-9d38-b119ab2943bb\"\n        },\n        {\n          \"x\": 241,\n          \"y\": 358,\n          \"id\": \"a6aee34c-b1a4-4baf-bc56-3f5f196a63ef\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">The 9-Minute Daily Strength Workout</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 120,\n          \"height\": 73,\n          \"marginOffset\": -5.5,\n          \"type\": \"text\",\n          \"groupId\": \"d5b52bcf-ff85-4e32-9d38-b119ab2943bb\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:34:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/belly-fat-workout/page12_image03.png\",\n            \"width\": 289,\n            \"height\": 232,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Performing Yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfcac6\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 66,\n          \"y\": 447,\n          \"width\": 145,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ff3734c4-2d2a-4a51-bb55-d4fb536c8514\",\n          \"groupId\": \"e7ed1138-5631-42ea-87b5-702ea39e36a9\"\n        },\n        {\n          \"x\": 238,\n          \"y\": 496,\n          \"id\": \"620c1daa-49d1-4552-b2b6-ff7a1aa2259e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Staatliches\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 950,\n              \"des\": -300,\n              \"tAsc\": 950,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 306,\n              \"xH\": 500,\n              \"capH\": 696,\n              \"yMin\": -306,\n              \"yMax\": 1006,\n              \"hAsc\": 950,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Leg &amp; yoga Workouts for Women</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 120,\n          \"height\": 72,\n          \"marginOffset\": -5.5,\n          \"type\": \"text\",\n          \"groupId\": \"e7ed1138-5631-42ea-87b5-702ea39e36a9\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -15,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 214, \"g\": 253, \"b\": 86 } },\n          \"type\": \"shape\",\n          \"x\": -22,\n          \"y\": 652,\n          \"width\": 520,\n          \"height\": 199,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"93b3b7e5-3fb3-4525-ad61-6b2dc0d61b6b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5495e22b-9fcc-4c3d-bb48-b18b0a161d72\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"640a75e9-138a-4d1e-bdf4-4b39f6a13282\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"8306c4fa-da9e-45ba-8815-d8f567c023a8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"987bbbde-cd36-486b-9fc1-a1ec637acc8f\"],\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"7e4ed338-b085-4758-bf5c-cb96fb8bedb5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ff3734c4-2d2a-4a51-bb55-d4fb536c8514\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"b75d93c6-9ec9-4ce9-a049-c42f753cc40f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"93b3b7e5-3fb3-4525-ad61-6b2dc0d61b6b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7108ee72-3576-4172-9f3a-494f1af95177\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"df2e9106-0be7-491c-884e-3fd4aadcf9e0\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"46171fc0-0559-46cd-a2fb-5cfa74277ec4\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"a6aee34c-b1a4-4baf-bc56-3f5f196a63ef\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"c2a4543c-b460-4c5e-b41e-905df79462ce\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"620c1daa-49d1-4552-b2b6-ff7a1aa2259e\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"8b101a2d-ba6c-441b-b853-8294ec6a1e4b\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"e7ed1138-5631-42ea-87b5-702ea39e36a9\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d5b52bcf-ff85-4e32-9d38-b119ab2943bb\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"00c35a38-8d4c-4a2e-99c8-c30bfdd9fb4c\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/buying-art-on-the-internet/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/buying-art-on-the-internet/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'buying-art-on-the-internet',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Buying Art on the Internet', 'template name', 'web-stories'),\n  tags: [\n    _x('Arts & Craft', 'template keyword', 'web-stories'),\n    _x('Paint', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Clean', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('International Klein Blue', 'color', 'web-stories'),\n      color: '#002fa7',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Inkwell Blue', 'color', 'web-stories'),\n      color: '#252a3a',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template will let you create informative stories and guides that look clean, classy and artsy. Use photos as well as videos and add links to online stores, websites and other resources.',\n    'web-stories'\n  ),\n  vertical: _x('Arts & Crafts', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/buying-art-on-the-internet/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/buying-art-on-the-internet/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"96c25aad-abd1-492e-981e-ef6ceececaed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:21:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page1_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1140,\n            \"id\": 0,\n            \"alt\": \"Multicolored abstract painting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1783b5\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 422,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 62.531328320802004,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1315da4c-38be-4b30-88d9-2688609b1a70\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">Purchase Guide</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 411,\n          \"width\": 214,\n          \"height\": 18,\n          \"id\": \"0f6e85db-9be0-4d0c-b999-241a8413bda5\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 441,\n          \"id\": \"67154d5e-32dd-48b6-89a9-566130a3e6ed\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Where to buy affordable art on The internet?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 137\n        },\n        {\n          \"x\": 48,\n          \"y\": 600,\n          \"id\": \"0a5abdef-b0eb-4e67-b0fb-d7fb4f036e5d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"By <span style=\\\"font-weight: 700\\\">Marshal Deck</span> 8.10.20\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 214,\n          \"height\": 20\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e505d4f4-6f7d-4ab1-9a49-8fc96c4156d2\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 69,\n          \"width\": 720,\n          \"height\": 480,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"49b2c36d-8f56-4b04-b9db-91beeb8475f7\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-09T09:44:31\",\n            \"baseColor\": \"#907a6d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_bg.mp4\",\n            \"width\": 720,\n            \"height\": 480,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"Man Explaining His Self\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Marshall Deck</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 53,\n          \"id\": \"10d1cc5c-019a-47fb-993b-7e26ff16c512\",\n          \"x\": 50,\n          \"y\": 542,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.16,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Art Critic, </span><span style=\\\"font-style: italic; color: #fff\\\">NYartsmag</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 214,\n          \"height\": 19,\n          \"id\": \"ef0a218c-5fa9-4363-97db-19de60547325\",\n          \"x\": 48,\n          \"y\": 600\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 83, \"g\": 83, \"b\": 83 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"e4a3ba1e-5e8d-472a-8505-074e5d86f2fc\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"dc7cb486-74bc-4b71-8e85-5238a7cbad96\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"bda2f04b-d420-4aab-9615-82392520d603\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:22:10\",\n            \"baseColor\": \"#20415d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Abstract painting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.25em; text-transform: uppercase\\\">Tip One:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 165,\n          \"height\": 18,\n          \"id\": \"ebcdb784-b88d-4433-8c57-fcb2d0f328c0\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 33,\n          \"id\": \"da8f17ab-640d-473c-a1c7-60792a758cb6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Abstract art doesn’t have to be expensive.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 137\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"video\",\n          \"x\": 47,\n          \"y\": 204,\n          \"width\": 318,\n          \"height\": 365,\n          \"scale\": 100,\n          \"focalX\": 50.38435031311559,\n          \"focalY\": 42.19171141490816,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"71a7a66d-a7ae-44fc-bdce-076b90bb3fe5\",\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-09T09:45:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1.mp4\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"Man Talking with His Friends\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#e5e3e0\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 139, \"g\": 139, \"b\": 139 } },\n      \"type\": \"page\",\n      \"id\": \"cf875a7d-17df-4be8-baae-85dddd021d73\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b9ae2e3a-40d8-4599-b98e-001b83173395\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"642337b8-fae8-4a62-b539-e169da9da841\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T12:10:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page4_bg.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Square pattern\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#fcfcfc\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Russe Tyler</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 18,\n          \"width\": 314,\n          \"height\": 63,\n          \"id\": \"3ce7db4d-0723-41cd-a90b-3830227a7817\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"American,<span style=\\\"font-style: italic\\\"> b. 1981</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 123,\n          \"y\": 78,\n          \"width\": 165,\n          \"height\": 20,\n          \"id\": \"7005e203-6f47-4dc0-a147-9eb1c0edfb53\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 571,\n          \"id\": \"77b51f76-619d-4ff4-b7bb-96f94fca91b4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 63,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Available at Taparts - </span><span style=\\\"color: #002fa7; text-transform: uppercase\\\">$500</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 49,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"marginOffset\": 4.1337890625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:22:52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page4_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1020,\n            \"id\": 0,\n            \"alt\": \"Closeup photo of torn papers\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#182424\",\n            \"isExternal\": true\n          },\n          \"x\": 75,\n          \"y\": 165,\n          \"width\": 262,\n          \"height\": 302,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"aac3071a-740f-456b-a762-cf2b35759788\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8e6b1578-7804-4deb-91be-42e47da083cc\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"afc62c9c-2f34-47dd-b44c-eb2da028bd4c\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f046f343-d108-45f8-910c-cce7522b8480\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T12:10:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page4_bg.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Square pattern\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#fcfcfc\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Luke Hage</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 18,\n          \"width\": 314,\n          \"height\": 63,\n          \"id\": \"6be7a6a0-2b17-4a12-b66f-3c74b75284d3\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"American,<span style=\\\"font-style: italic\\\"> b. 1972</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 123,\n          \"y\": 78,\n          \"width\": 165,\n          \"height\": 20,\n          \"id\": \"bdd6e8b5-39a8-466e-b4d9-cb1a8a12aea1\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 53,\n            \"vertical\": 14\n          },\n          \"x\": 49,\n          \"y\": 569,\n          \"id\": \"eb7733e8-2085-48c3-83eb-b9e3229f8b55\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Available at Artonline - </span><span style=\\\"color: #002fa7; text-transform: uppercase\\\">$1000</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 236,\n          \"height\": 365,\n          \"scale\": 100,\n          \"focalX\": 50.121067262368946,\n          \"focalY\": 45.60251011448475,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d6f667b5-35c7-4cde-b55f-e4b4a4e5ba2c\",\n          \"x\": 88,\n          \"y\": 137,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:23:22\",\n            \"baseColor\": \"#7b5b54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page5_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1225,\n            \"id\": 0,\n            \"alt\": \"Multicolored abstract painting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f5ae9d85-e4f5-43db-bf95-1470ffac7e9a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"9fd1d379-8712-465f-871d-4b92c83263ed\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"bdad90da-948e-4df4-a95f-33d74c4fa4a4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:24:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page6_image1.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Woman in black long sleeve shirt sitting on floor\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#413d3c\",\n            \"isExternal\": true\n          },\n          \"x\": 47,\n          \"y\": 36,\n          \"width\": 318,\n          \"height\": 108,\n          \"scale\": 100,\n          \"focalX\": 50.38435031311559,\n          \"focalY\": 36.838374467269055,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"46f36d48-2334-4cc5-81d9-b527c0cc3f82\",\n          \"type\": \"image\",\n          \"borderRadius\": {\n            \"topLeft\": 4,\n            \"topRight\": 4,\n            \"bottomRight\": 4,\n            \"bottomLeft\": 4,\n            \"locked\": true\n          },\n          \"groupId\": \"fd8a3f60-c3a7-4acc-8e8f-ab0aa64d98c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 154,\n          \"id\": \"44e7d881-bfd2-4872-997f-352fb472f529\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Taparts</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 32,\n          \"type\": \"text\",\n          \"groupId\": \"fd8a3f60-c3a7-4acc-8e8f-ab0aa64d98c2\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 189,\n          \"id\": \"7a7fbdbd-ad53-48fa-bb36-9f5349cb9d99\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.5)\\\">Discover and collect contemporary art.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 319,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"groupId\": \"fd8a3f60-c3a7-4acc-8e8f-ab0aa64d98c2\"\n        },\n        {\n          \"x\": 137,\n          \"y\": 157,\n          \"id\": \"997ff382-00d0-46ee-b6a9-d92308115e5b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"01\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"fd8a3f60-c3a7-4acc-8e8f-ab0aa64d98c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">Where to look:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 0,\n          \"width\": 214,\n          \"height\": 15,\n          \"id\": \"2e6b6761-9cb7-4bba-b532-a04659992d1e\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 241,\n          \"id\": \"9049ad56-906f-4fdf-84e5-5e8fad764897\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:25:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page6_image2.jpg\",\n            \"width\": 719,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Art Gallery\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#181c1c\",\n            \"isExternal\": true\n          },\n          \"width\": 318,\n          \"height\": 108,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"borderRadius\": {\n            \"topLeft\": 4,\n            \"topRight\": 4,\n            \"bottomRight\": 4,\n            \"bottomLeft\": 4,\n            \"locked\": true\n          },\n          \"groupId\": \"faa41c99-c034-4726-92b4-382e8382c22b\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 358,\n          \"id\": \"0f0fd3dc-aae3-4daf-bdc6-ba125dec61f7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">2x2x2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 32,\n          \"type\": \"text\",\n          \"groupId\": \"faa41c99-c034-4726-92b4-382e8382c22b\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 394,\n          \"id\": \"5a86946a-bd37-47f9-9611-4abd0fa765ae\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.5)\\\">Modern and classic artworks.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"groupId\": \"faa41c99-c034-4726-92b4-382e8382c22b\"\n        },\n        {\n          \"x\": 113,\n          \"y\": 362,\n          \"id\": \"ffdb8987-9466-46dd-a58b-96e2d7d12ae2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"02\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"faa41c99-c034-4726-92b4-382e8382c22b\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 446,\n          \"id\": \"ecaf5cd2-e1ee-4c42-b251-ebbe32fce55d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:25:48\",\n            \"baseColor\": \"#c0bdba\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page6_image3.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Art gallery interior\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 318,\n          \"height\": 108,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"borderRadius\": {\n            \"topLeft\": 4,\n            \"topRight\": 4,\n            \"bottomRight\": 4,\n            \"bottomLeft\": 4,\n            \"locked\": true\n          },\n          \"groupId\": \"34816601-c6fa-4388-8b1d-49fc1e5ea2d3\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 564,\n          \"id\": \"dd52a2a0-e8f6-40a0-99c0-f8bb0fd89232\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Savvy Art</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 32,\n          \"type\": \"text\",\n          \"groupId\": \"34816601-c6fa-4388-8b1d-49fc1e5ea2d3\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 599,\n          \"id\": \"831ca3df-c0d2-4c54-9ef8-f7abb7d20270\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.5)\\\">Young and upcoming art talent.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"groupId\": \"34816601-c6fa-4388-8b1d-49fc1e5ea2d3\"\n        },\n        {\n          \"x\": 158,\n          \"y\": 567,\n          \"id\": \"4c974f1a-5b2f-4e51-bbac-f6c976db5307\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"03\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"34816601-c6fa-4388-8b1d-49fc1e5ea2d3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"669b9a28-0169-4a96-a767-402ef0e56a04\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"997ff382-00d0-46ee-b6a9-d92308115e5b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1b9e5fca-6b79-4bbf-92d1-0796142742aa\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ffdb8987-9466-46dd-a58b-96e2d7d12ae2\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"2a6ec89d-29a1-45e0-985c-cd9257f62a1a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4c974f1a-5b2f-4e51-bbac-f6c976db5307\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"28457fb3-139a-4b07-9e3e-9e5e75ccee7a\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"fd8a3f60-c3a7-4acc-8e8f-ab0aa64d98c2\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"faa41c99-c034-4726-92b4-382e8382c22b\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"34816601-c6fa-4388-8b1d-49fc1e5ea2d3\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3b1672c9-cbdf-4e8a-b69c-aa0c35bf9452\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:26:24\",\n            \"baseColor\": \"#1e5e5c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Multicolored abstract painting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.25em; text-transform: uppercase\\\">Tip Two:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 165,\n          \"height\": 18,\n          \"id\": \"888cfeda-24a0-4087-acb2-212cfc92af8f\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 33,\n          \"id\": \"4d34ba88-23c8-4312-a4a4-b978ec8b12b9\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Listen to your gut when it comes to independent art</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 319,\n          \"height\": 137,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 204,\n          \"width\": 318,\n          \"height\": 365,\n          \"scale\": 100,\n          \"focalX\": 50.12978082551669,\n          \"focalY\": 42.48090728843008,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"86b7c2f7-77fe-4301-90ff-5e03c9540540\",\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"type\": \"video\",\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-09T09:45:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1.mp4\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"Man Talking with His Friends\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#e5e3e0\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 139, \"g\": 139, \"b\": 139 } },\n      \"type\": \"page\",\n      \"id\": \"c23b7aa6-9599-4d11-82d6-a08ff55f9cad\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"5775d9d1-9a51-4b7b-ba79-1841e31529c1\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"edfc6818-cd2c-4b26-b417-99baafb2092f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">(HAHA) experiments with new spaces by renting temporary venues.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 441,\n          \"width\": 321,\n          \"height\": 42,\n          \"id\": \"866391b6-9d21-44ff-9181-047aedced10c\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 53,\n            \"vertical\": 14\n          },\n          \"x\": 49,\n          \"y\": 569,\n          \"id\": \"edea597f-25af-4b96-a222-17c5cbc834e1\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 253,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1fce66fc-6c8b-4775-926d-ce5dec5f1ff9\",\n          \"x\": 47,\n          \"y\": 162,\n          \"type\": \"image\",\n          \"borderRadius\": {\n            \"topLeft\": 4,\n            \"topRight\": 4,\n            \"bottomRight\": 4,\n            \"bottomLeft\": 4,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:31:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page8_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Woman in blue denim jeans standing in front of white wall with 3 black wooden picture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#f8e8e0\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">Where to Look:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 18,\n          \"id\": \"36cb8504-44b2-4348-8e0c-28bc268bf7d9\",\n          \"x\": 47,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 25,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f37b30f4-9bb5-4a65-997e-5a1455e7b149\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 57,\n          \"id\": \"e533d9b2-89e3-4349-a6f5-ea85c8050a70\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #040404\\\">1/3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"c637751c-0392-4c81-a214-2a43f986b2bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Haha Fine Art</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 95,\n          \"width\": 314,\n          \"height\": 53,\n          \"id\": \"aa54cb88-2eba-44ae-8836-a923fd5ef45c\",\n          \"type\": \"text\",\n          \"groupId\": \"c637751c-0392-4c81-a214-2a43f986b2bd\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"071c48b7-3994-4e4c-9b45-1232bf37325d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"edea597f-25af-4b96-a222-17c5cbc834e1\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"07a07efc-ee14-46a5-a3f1-868d4bb31d53\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"c637751c-0392-4c81-a214-2a43f986b2bd\": {\n          \"name\": \"Header\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4eb45b0c-210d-4589-9532-13a8bd20929f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Minting makes printed art easy to frame</span> and enjoy on the walls of your own home.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 441,\n          \"width\": 321,\n          \"height\": 64,\n          \"id\": \"c73c6bd7-1b33-4712-b8eb-7d17d27080f7\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 53,\n            \"vertical\": 14\n          },\n          \"x\": 49,\n          \"y\": 569,\n          \"id\": \"588c7a52-6a4a-4b38-96d7-90fbd8521898\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 253,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8ee994c2-994a-4d50-9afc-74bd5bba9f7f\",\n          \"x\": 47,\n          \"y\": 162,\n          \"type\": \"image\",\n          \"borderRadius\": {\n            \"topLeft\": 4,\n            \"topRight\": 4,\n            \"bottomRight\": 4,\n            \"bottomLeft\": 4,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:32:44\",\n            \"baseColor\": \"#cfd3ce\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page9_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Assorted-color wall arts\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 48,\n          \"y\": 25,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"234864f9-ee51-42ca-9d39-25ee93f388e0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 51,\n          \"y\": 57,\n          \"id\": \"4a767a31-7875-4b6c-86b9-04499fa9ace9\",\n          \"content\": \"<span style=\\\"color: #040404\\\">2/3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"43badbc5-7f1c-47ff-ad2d-dad879c92539\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Minting</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 95,\n          \"width\": 314,\n          \"height\": 53,\n          \"id\": \"036977ba-8c3b-4423-ba3c-31580cdd9adf\",\n          \"type\": \"text\",\n          \"groupId\": \"43badbc5-7f1c-47ff-ad2d-dad879c92539\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">Where to Look:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 18,\n          \"id\": \"57499dc2-34e9-486d-8841-603e854865b5\",\n          \"x\": 47,\n          \"y\": 0\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7975c0b1-7521-4f92-8203-ee29411f5b5c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"588c7a52-6a4a-4b38-96d7-90fbd8521898\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"23c3ac5e-86cc-404f-9abe-c763974d32c0\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"43badbc5-7f1c-47ff-ad2d-dad879c92539\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"14beb08b-b50a-481c-abc8-7ce3af90a93b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Papier Collective is a collection of paper art from artists around the world.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 441,\n          \"width\": 321,\n          \"height\": 64,\n          \"id\": \"c999c7a5-cfaf-45f8-b7c7-8b67dd306176\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 53,\n            \"vertical\": 14\n          },\n          \"x\": 49,\n          \"y\": 569,\n          \"id\": \"1caf13b8-416f-48af-94b6-8f2d54f0e6d4\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 253,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0f8a1666-4930-4bd6-a075-18d2686508d5\",\n          \"x\": 47,\n          \"y\": 162,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:33:52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page10_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Two abstract paintings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#f8e8e0\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 48,\n          \"y\": 25,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a54c3699-8b45-424b-9b56-d86f9fa2f8da\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 51,\n          \"y\": 57,\n          \"id\": \"cd2d0a0a-5f5f-451e-a998-a12d889d7559\",\n          \"content\": \"<span style=\\\"color: #040404\\\">3/3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"147ba536-9f14-46f8-8e59-2ae2e1bb3622\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Papier Collective</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 95,\n          \"width\": 314,\n          \"height\": 53,\n          \"id\": \"eb419f36-3951-400f-8ef8-03dd0babc3cc\",\n          \"type\": \"text\",\n          \"groupId\": \"147ba536-9f14-46f8-8e59-2ae2e1bb3622\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">Where to Look:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 18,\n          \"id\": \"ce2cb624-7701-4bc2-a0db-93a4998d5bb8\",\n          \"x\": 47,\n          \"y\": 0\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3c100015-0a01-4b4e-aa85-9850d1361e04\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1caf13b8-416f-48af-94b6-8f2d54f0e6d4\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d5ec9964-6bba-4c88-9915-a6e6ae8a9554\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"147ba536-9f14-46f8-8e59-2ae2e1bb3622\": {\n          \"name\": \"Header\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"2b8e3670-26d4-42a2-a73c-85914496f8eb\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-09T09:34:18\",\n            \"baseColor\": \"#2f434f\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Multicolored abstract painting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; text-decoration: underline; color: #fff; letter-spacing: 0.25em; text-transform: uppercase\\\">Final Thoughts</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 314,\n          \"height\": 18,\n          \"id\": \"e154eaf4-0da1-48e6-9c6e-ee9a63bfafda\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 118,\n          \"id\": \"83deae4a-41e1-4c8e-8336-08e2599ed185\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Affordable art is out there, just waiting to be snatched up and added to your collection. Trust your taste!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 325,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 139, \"g\": 139, \"b\": 139 } },\n      \"type\": \"page\",\n      \"id\": \"21f76f2c-51bd-47d1-8573-403b12a10ed3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"43facbfe-203d-438d-8bfd-e4820cfe2c1f\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1d16bc4c-efc5-4507-9dc4-0e31c09c03b9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">My handy internet list</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 81,\n          \"width\": 314,\n          \"height\": 18,\n          \"id\": \"3a2476e7-bdba-45d8-8858-bf249a0be25f\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 183,\n          \"id\": \"92b62c6b-b70a-4ba0-a983-6b580abeeaae\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">TapArts</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"124d8c7c-94c3-48b2-901e-4381aa45baf1\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 167,\n          \"y\": 186,\n          \"id\": \"1e22903e-aa18-46cf-9d1b-881f03d24fd9\",\n          \"content\": \"04\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"124d8c7c-94c3-48b2-901e-4381aa45baf1\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 247,\n          \"id\": \"d5236a44-9c35-48a7-96aa-871625d8e0b7\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">2x2x2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"f8f2dc70-029b-487e-a283-77aafc2396ae\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 138,\n          \"y\": 249,\n          \"id\": \"f1faef6f-7540-4a1e-bff3-34c910cea87b\",\n          \"content\": \"05\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"f8f2dc70-029b-487e-a283-77aafc2396ae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 311,\n          \"id\": \"63405bca-3b45-49bb-8a26-4d869c9cc0b5\",\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Savvy Art</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"9b1d1137-d341-4b37-80a3-1ee8ea53e106\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 195,\n          \"y\": 314,\n          \"id\": \"e24855b6-c913-468c-ad2e-5922b6c9a111\",\n          \"content\": \"06\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"9b1d1137-d341-4b37-80a3-1ee8ea53e106\"\n        },\n        {\n          \"x\": 57,\n          \"y\": 375,\n          \"id\": \"4c5db39e-d57a-49ce-9dad-a8045de51e7b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Haha</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"5eaa1698-1eed-4d6d-ace3-4fe0ae001a33\"\n        },\n        {\n          \"x\": 136,\n          \"y\": 377,\n          \"id\": \"8ae7a228-3dcc-4f04-a3c7-51ae1762da58\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"07\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"5eaa1698-1eed-4d6d-ace3-4fe0ae001a33\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 439,\n          \"id\": \"ba854802-d549-460f-b372-6110092f7285\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Minting</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"fc0b53d4-b4ae-4ccd-a9d3-726fbe9223ac\"\n        },\n        {\n          \"x\": 171,\n          \"y\": 442,\n          \"id\": \"ac3b08ec-875d-43c4-a830-32f118d97502\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"08\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"fc0b53d4-b4ae-4ccd-a9d3-726fbe9223ac\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 503,\n          \"id\": \"1673dcc8-1fca-4e15-8f0b-faacedb3f00d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">Papier Collective</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"c0c10ac0-b63a-4d62-8f27-fa5f6d89b57b\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 304,\n          \"y\": 504,\n          \"id\": \"99dae96e-f595-4649-92da-7b4c58ae1aec\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"09\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"groupId\": \"c0c10ac0-b63a-4d62-8f27-fa5f6d89b57b\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"114b498e-6134-4cc4-b9f9-f29ad4ff1969\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1e22903e-aa18-46cf-9d1b-881f03d24fd9\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9d429ca5-3f9e-41ae-b082-d85fdac43b7a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f1faef6f-7540-4a1e-bff3-34c910cea87b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"f49c6f34-0746-4237-99a5-3f4264910871\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e24855b6-c913-468c-ad2e-5922b6c9a111\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"caf479c5-d932-4489-8e0a-6ed7fba7fafc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8ae7a228-3dcc-4f04-a3c7-51ae1762da58\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"e2bea39e-4eb6-4a35-b0bd-5d55b0c50903\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ac3b08ec-875d-43c4-a830-32f118d97502\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"75df1d44-5f11-4e73-843a-b38c0024aec6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"99dae96e-f595-4649-92da-7b4c58ae1aec\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 1000\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"108e1b6f-4ba0-46b1-994a-ed907c9a5323\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"124d8c7c-94c3-48b2-901e-4381aa45baf1\": {\n          \"name\": \"Taparts\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f8f2dc70-029b-487e-a283-77aafc2396ae\": {\n          \"name\": \"2x2x2\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9b1d1137-d341-4b37-80a3-1ee8ea53e106\": {\n          \"name\": \"Savvy Art\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"5eaa1698-1eed-4d6d-ace3-4fe0ae001a33\": {\n          \"name\": \"Haha\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fc0b53d4-b4ae-4ccd-a9d3-726fbe9223ac\": {\n          \"name\": \"Minting\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c0c10ac0-b63a-4d62-8f27-fa5f6d89b57b\": {\n          \"name\": \"Papier Collective\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"af9a7c4c-62ec-4654-9f83-57e32378780f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 365,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"39c80752-6536-4959-b444-051cf144a5c7\",\n          \"x\": 47,\n          \"y\": 17,\n          \"type\": \"video\",\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-09T09:45:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1.mp4\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/buying-art-on-the-internet/page2_video1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"Man Talking with His Friends\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#e5e3e0\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.08,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #002fa7; text-transform: uppercase\\\">@Marshalldeck</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 497,\n          \"width\": 314,\n          \"height\": 53,\n          \"id\": \"f4508d18-4573-4dc2-94c9-9fb3c930571e\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Baskerville\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 970,\n              \"des\": -270,\n              \"tAsc\": 970,\n              \"tDes\": -270,\n              \"tLGap\": 0,\n              \"wAsc\": 970,\n              \"wDes\": 270,\n              \"xH\": 530,\n              \"capH\": 770,\n              \"yMin\": -260,\n              \"yMax\": 970,\n              \"hAsc\": 970,\n              \"hDes\": -270,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.25em; text-transform: uppercase\\\">For more art pics</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 460,\n          \"width\": 312,\n          \"height\": 18,\n          \"id\": \"e5f6d5f0-8311-48ec-a742-a07bf2221e82\",\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 53,\n            \"vertical\": 14\n          },\n          \"x\": 49,\n          \"y\": 571,\n          \"id\": \"2329882a-8007-4b63-8212-5c561dc1420f\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Instagram</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n          },\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 70,\n          \"y\": 584,\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"artOnTheInternetInstagramBlack\" },\n          \"id\": \"f73fc5eb-44cc-453e-942d-7c28729e1db5\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6a170e45-4f45-4549-9157-6380423cae69\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2329882a-8007-4b63-8212-5c561dc1420f\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"22975696-7537-4e1b-869d-dda3a2d40cb6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f73fc5eb-44cc-453e-942d-7c28729e1db5\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"543334ac-dbbc-4dc7-a744-f65ae1ccf8dc\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-life-story/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-life-story/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'celebrity-life-story',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Celebrity Life Story', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Celebrity', 'template keyword', 'web-stories'),\n    _x('Pop', 'template keyword', 'web-stories'),\n    _x('Bright', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Phantom Black', 'color', 'web-stories'),\n      color: '#020202',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gecko Green', 'color', 'web-stories'),\n      color: '#80FF44',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With an upbeat neon green color and a powerful headings font, this template is great for creating stories around pop culture, music and the show business.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-life-story/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-life-story/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"ccd9700f-2c08-4926-b532-1e1b12dd2400\",\n          \"scale\": 135,\n          \"focalX\": 38.888888888888886,\n          \"focalY\": 38.54166666666667,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:02:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page1_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Grayscale photography of woman's face\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#222325\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T06:44:55\",\n            \"baseColor\": \"#84fc44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page1_2_3_star_img1.png\",\n            \"width\": 1509,\n            \"height\": 1443,\n            \"id\": 0,\n            \"alt\": \"Green star on transparent background\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": -128,\n          \"y\": 191,\n          \"width\": 754,\n          \"height\": 720,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"bdfdf929-1824-4baa-abdb-9e8bf1d4a825\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Marcellus\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1995,\n              \"des\": -573,\n              \"tAsc\": 1995,\n              \"tDes\": -573,\n              \"tLGap\": 0,\n              \"wAsc\": 1995,\n              \"wDes\": 573,\n              \"xH\": 1024,\n              \"capH\": 1434,\n              \"yMin\": -573,\n              \"yMax\": 1995,\n              \"hAsc\": 1995,\n              \"hDes\": -573,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Logo</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 316,\n          \"height\": 50,\n          \"id\": \"8d2500b3-eec0-4f85-9896-8092d04d8cf8\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">Rise to Fame:</span>\\n<span style=\\\"font-weight: 700; color: #020202\\\">Meet Jane Popular</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 56,\n          \"y\": 343,\n          \"width\": 309,\n          \"height\": 197,\n          \"id\": \"99377bf6-8aaa-4faa-b639-386bf4e72eb5\",\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #020202; text-transform: uppercase\\\">By Michaela Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 56,\n          \"y\": 559,\n          \"width\": 228,\n          \"height\": 18,\n          \"id\": \"e8b8be9b-825e-4ba3-9204-9020e01f9c28\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #020202\\\">July 22, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 228,\n          \"height\": 18,\n          \"id\": \"c8e63fad-0c15-41f2-8fe5-51fcdce97f0c\",\n          \"x\": 56,\n          \"y\": 579,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0b2ff5e9-0446-48c0-be8c-61adf75ba2fc\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"41c0202a-b78d-467b-a80d-daeba1687dec\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 498,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"e4940d0a-9074-44de-9414-5d3dc3c77eff\",\n          \"scale\": 105,\n          \"focalX\": 52.92148919753087,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:03:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1631,\n            \"id\": 0,\n            \"alt\": \"woman in black and white scarf and black and white scarf photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b7ad9e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #80ff44\\\">Ever wonder how Jane Popular rose to astronomical fame? Let’s take a walk down memory lane.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 48,\n          \"y\": 456,\n          \"width\": 278,\n          \"height\": 144,\n          \"id\": \"283fd96e-b294-462e-8a8c-129f3e9053f8\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"265063ed-47cf-421e-a6fe-7bf2d1d42c84\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"e4940d0a-9074-44de-9414-5d3dc3c77eff\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f9a50b97-97aa-4dd4-9ac0-229be8963bf0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"2493b5f5-432c-437f-89a7-55a3f7e9679f\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 230,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0a6892f5-959a-4e6f-9eb0-d0fb41171886\",\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:04:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 755,\n            \"id\": 0,\n            \"alt\": \"Woman performing on stage with closed eyes and holding a microphone photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0e0e0e\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 5,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T06:44:55\",\n            \"baseColor\": \"#84fc44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page1_2_3_star_img1.png\",\n            \"width\": 1509,\n            \"height\": 1443,\n            \"id\": 0,\n            \"alt\": \"Green star on transparent background\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 754,\n          \"height\": 720,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2982684c-0a66-46e0-8766-e5d181530e3c\",\n          \"x\": -152,\n          \"y\": 204,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #282828; text-transform: uppercase\\\">The early years</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 228,\n          \"height\": 20,\n          \"id\": \"75185f3c-da05-4442-aada-ae0399f4beee\",\n          \"x\": 51,\n          \"y\": 425,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">1985.-1995.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 309,\n          \"height\": 62,\n          \"id\": \"3b62ed05-299e-4eef-a86f-ee1e64126a89\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #1e1e1e\\\">The beginning of her ascent to fame started early and young.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 313,\n          \"height\": 88,\n          \"id\": \"ff194c12-adb7-43a8-a1a4-00227c631b12\",\n          \"x\": 51,\n          \"y\": 512,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f8cb8082-447d-41f4-9399-64245c4463ce\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"5c814c90-c975-4b44-9d85-608275c0880c\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"b78218a0-382e-4fb6-96de-dab04278ea17\",\n          \"scale\": 105,\n          \"focalX\": 33.82936507936508,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:05:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page4_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Woman in White Short-sleeved Top\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#17130e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"x\": 0,\n          \"y\": 21,\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ecd514d3-7360-4496-bce4-9cee8a371335\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 63,\n          \"y\": 8,\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"0ef7e769-b89f-40b3-9ee9-74e65e1136e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1985</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"5a220006-60a0-4e13-a386-b0194547c2e8\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Her career started as a childhood singer.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 278,\n          \"height\": 46,\n          \"id\": \"e30b24f6-8714-408e-8471-dcab59896856\",\n          \"x\": 54,\n          \"y\": 550,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e5c3058b-a8af-4f8d-a1cd-11531e96f816\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5a220006-60a0-4e13-a386-b0194547c2e8\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1a2dff49-6cde-4109-bbfc-3e365cfa3227\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ecd514d3-7360-4496-bce4-9cee8a371335\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5080c5b7-dc6e-4cb0-93fa-ac3c0fb02429\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"0ef7e769-b89f-40b3-9ee9-74e65e1136e3\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"59fd257b-e31f-4e08-b8ee-c2b80f8929c4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1eb5316c-d14e-41a6-8c12-a93ba906ce6d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"89e27450-3440-422f-940d-faa4ef667cfd\",\n          \"scale\": 133,\n          \"focalX\": 39.25710543720412,\n          \"focalY\": 38.839285714285715,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:06:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page5_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1619,\n            \"id\": 0,\n            \"alt\": \"Woman holding microphone on stage\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#362334\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2f00885d-d894-41aa-b27d-1004c24e2faa\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"0cede45b-d159-4b3e-8e7d-7dfa1b877d5e\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1989</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"110fea93-813e-4b6c-840e-5f749b45c432\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">By age 16, she had already sung backup vocals for 5 Grammy winning singers.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 312,\n          \"height\": 47,\n          \"id\": \"16d66303-88b5-4f3f-943a-f7517fea6afd\",\n          \"x\": 54,\n          \"y\": 550,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0b871b36-af1d-41f9-bcc7-453df792f9d6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"110fea93-813e-4b6c-840e-5f749b45c432\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f2db7eb5-cae8-4734-8f0c-a72a2b63558a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0cede45b-d159-4b3e-8e7d-7dfa1b877d5e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"704ef7fe-f3f7-456f-a32f-f779ff01a1d9\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b328bbcc-8241-4656-94ba-1f7fe9843e49\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"f0c63796-c7ab-437a-a59e-9419813d72f4\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:07:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page6_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1619,\n            \"id\": 0,\n            \"alt\": \"Woman wearing orange button collared top near red and yellow flowers\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c87a63\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a2960f26-a76c-4284-879e-2720662a4e82\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"16695198-0936-4d94-9f69-0f7e86fc3c6b\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1992</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"d5344787-8eea-4c7d-8f1b-115a324b5fef\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">But a sudden career pivot to the silver screen catapulted her early fame. She soon starred in 5 TV shows, and 4 major motion pictures.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 312,\n          \"height\": 97,\n          \"id\": \"6e8ee380-c283-4c81-b19a-70876f9345de\",\n          \"x\": 54,\n          \"y\": 500,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0cc9717b-96c2-4357-82d6-0c85cdd86950\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16695198-0936-4d94-9f69-0f7e86fc3c6b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4c934316-8bf9-41ff-b264-f617f441defd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d5344787-8eea-4c7d-8f1b-115a324b5fef\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d8aa32bf-a0f2-47bb-8561-87222ff5e233\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"53511d18-f5df-4208-a2ad-1eb0d6047fd1\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"01ab9f01-0094-468a-880d-2b0a8b8fe298\",\n          \"scale\": 130,\n          \"focalX\": 53.96634615384615,\n          \"focalY\": 43.62980769230769,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:07:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Grayscale photo of a woman wearing white off-shoulder shirt photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0e0e0e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbfd3b86-b20c-4bb9-ba24-f1842825aca4\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"3fc5c956-ec03-44cd-8b47-b075c8a70316\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1995</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"dbd10921-96cf-4c7e-a33b-f3bcbd14aabd\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">First TV appearance with an all-star cast on the show “All Right With Us.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 312,\n          \"height\": 47,\n          \"id\": \"ac1d8aac-91f9-4e23-8bf9-36d49682b848\",\n          \"x\": 54,\n          \"y\": 546,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c80b1ee5-dc45-4085-b827-7dda48c48fb9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3fc5c956-ec03-44cd-8b47-b075c8a70316\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"25d8edc2-099f-4219-b992-38dfc8b093b4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dbd10921-96cf-4c7e-a33b-f3bcbd14aabd\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7093ba5b-f1b9-4b22-b317-9480e91acb81\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"cf3611df-ee9a-4bcd-a8aa-ea8daf9b1692\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"f69efdd0-5a24-46ec-94df-6299d3314f88\",\n          \"scale\": 138,\n          \"focalX\": 62.73777173913042,\n          \"focalY\": 62.81702898550725,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:08:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Woman singing on focus photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c2c2c2\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 5,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T06:44:55\",\n            \"baseColor\": \"#84fc44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page1_2_3_star_img1.png\",\n            \"width\": 1509,\n            \"height\": 1443,\n            \"id\": 0,\n            \"alt\": \"Green star on transparent background\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 754,\n          \"height\": 720,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"140a5e4a-bd90-4052-a542-58330b327445\",\n          \"x\": -152,\n          \"y\": 204,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #282828; text-transform: uppercase\\\">The change</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 228,\n          \"height\": 19,\n          \"id\": \"b0cdcf12-dcdf-46bb-a444-2f760562097a\",\n          \"x\": 51,\n          \"y\": 425,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">1996.-2001.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 309,\n          \"height\": 62,\n          \"id\": \"edcf6a81-8c7d-4fc0-b607-a9929f448555\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #1e1e1e\\\">Hitting her stride and making her own brand of fame.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 265,\n          \"height\": 88,\n          \"id\": \"76fccd9c-757e-4372-ade9-106c3efd66c9\",\n          \"x\": 51,\n          \"y\": 512,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"970ce1c5-554f-43e1-8eed-47d345efc6a0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"94c22cf9-bb96-4887-8e2f-8d9f64fd5d4b\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"87bae174-bea5-4a0a-9a5a-f882c0d21bd3\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:09:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page9_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Close-Up Photo of Person Wearing Brown Bonnet\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d1cecd\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"582f611f-c3a7-4f12-9e28-e9b66eca6e29\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"a8c3e8ee-6435-4488-b300-9fd842e64eeb\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1996</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"9aa84b2d-09bc-4c6a-9080-effc174b70b5\",\n          \"x\": 7,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">She met Quinn Darandino on the set of Kill Will, which set her movie trajectory into acceleration.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 302,\n          \"height\": 71,\n          \"id\": \"bc70ab47-145c-475f-86aa-895ae68c3d4f\",\n          \"x\": 54,\n          \"y\": 519,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ca056e5c-64e7-4f27-b8f6-b544c2fb4f34\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9aa84b2d-09bc-4c6a-9080-effc174b70b5\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"96724b12-c0d1-4718-b4a2-d7da054761d6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"582f611f-c3a7-4f12-9e28-e9b66eca6e29\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"a8c3e8ee-6435-4488-b300-9fd842e64eeb\"],\n          \"id\": \"08fc94fa-8880-4346-9a19-32e2b62d82cf\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a919525f-3876-4aaf-a89d-7ca6bd92f99e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"d822bc82-84fd-4e06-8c61-9458faece9a1\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 493,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"d306f8b4-9890-466a-aee2-e592c2a15922\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:10:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1617,\n            \"id\": 0,\n            \"alt\": \"Woman Posing While A Person Is Operating a Camera\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#313431\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8053f009-ff17-44d0-8616-0a567093b0d9\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"f13e5742-46e5-430c-9d01-a9ee2c44c434\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1996</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"9eff3941-3007-4ca2-9c1e-407218579013\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Starred in 4 consecutive blockbusters by 2012.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 302,\n          \"height\": 47,\n          \"id\": \"54706f73-92be-429e-a581-b0687dbef0b7\",\n          \"x\": 55,\n          \"y\": 546,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8c1f7398-5897-4b68-9899-1433d778446d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f13e5742-46e5-430c-9d01-a9ee2c44c434\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"befb7918-9599-4014-821e-e0af1e5acfe6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9eff3941-3007-4ca2-9c1e-407218579013\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ac71de99-5beb-4d24-ab5b-ef0afd6e8235\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"84439991-ee2b-4334-a03a-3bda9a923d90\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c7fe7e1f-64d6-4c8f-8140-5c1edb873691\",\n          \"scale\": 134,\n          \"focalX\": 34.95802238805969,\n          \"focalY\": 57.34608208955226,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:10:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Monochrome Photo of Woman Sitting in Vehicle\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#252525\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fa5bc7fd-b61c-4ca0-9212-c2d7f7910466\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"ff0c5898-c719-4c7e-8304-c321e88a0e4c\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">1997</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"f60de09f-b334-49a8-a273-d6cf2d2a4866\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">But a real movie star was made when she starred as Lucy Ohio in “Gone By Day.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 302,\n          \"height\": 72,\n          \"id\": \"4a26f345-fe20-46e2-b286-1086c8772bf4\",\n          \"x\": 54,\n          \"y\": 519,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"176f6589-4159-4a2c-a566-35ba087918c2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ff0c5898-c719-4c7e-8304-c321e88a0e4c\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e3637784-f5c0-42c9-967b-41e108c80b76\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f60de09f-b334-49a8-a273-d6cf2d2a4866\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e9d912bb-1b7f-4758-bc21-b66c3eaa630b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"22eeef49-9d4a-45f3-810d-e77a7d5db550\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 554,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"7dd2a7cb-49f3-480e-99fc-c10eb8f4240e\",\n          \"scale\": 130,\n          \"focalX\": 49.99999999999999,\n          \"focalY\": 51.80288461538463,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:11:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page12_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1815,\n            \"id\": 0,\n            \"alt\": \"Two Women Sitting on Ottoman\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#483a1a\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"26cf6ebf-6fec-4fb5-b2a9-8216bf12d6db\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"d44e43d8-7bc8-49dd-a0b1-b13edcb562ef\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">2003</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"219e916e-8947-424d-991a-054b8d730494\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Her first Oscar Nomination as Best Supporting Actress in a foreign film.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 302,\n          \"height\": 47,\n          \"id\": \"4bb4d70f-4078-4be6-b2cc-ffadf01ea162\",\n          \"x\": 54,\n          \"y\": 546,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f35a7e0b-ce9b-45c2-8511-f5c297b36b0d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d44e43d8-7bc8-49dd-a0b1-b13edcb562ef\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"db83b48d-4cee-44f3-abab-86ac670be294\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"219e916e-8947-424d-991a-054b8d730494\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7ddb32b0-6ef3-48b6-af7f-e319311dab37\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1d66b0a1-0da6-478c-a7bb-31dfa1a8ec74\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1860a7d9-d621-4653-832f-59985d0ca6b0\",\n          \"scale\": 100,\n          \"focalX\": 23.125,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:13:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page13_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man Holding Camera and Woman Playing Violin\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#41342b\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b858db76-9aa0-4ea4-adcf-a8f7efefe2f3\",\n          \"x\": 0,\n          \"y\": 21,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularGreenStar\" },\n          \"id\": \"66179b44-e939-4d35-8b41-319b8c88b35e\",\n          \"x\": 63,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #80ff44\\\">2012</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 141,\n          \"height\": 62,\n          \"id\": \"6a1c589b-dfcf-4855-9189-a882a58be4b8\",\n          \"x\": 8,\n          \"y\": 81,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Back to back blockbusters and Grammy nominations really made 2012 her year.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 302,\n          \"height\": 72,\n          \"id\": \"b4e6d607-8ec2-4e92-912c-f00daecaa356\",\n          \"x\": 54,\n          \"y\": 519,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4e44704e-2689-4f21-9194-56ca5e111d17\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"66179b44-e939-4d35-8b41-319b8c88b35e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"956a4203-1811-4b0d-a37a-d66f10a5aa9b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6a1c589b-dfcf-4855-9189-a882a58be4b8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1800,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c86d9ef2-d4d5-4675-a32c-5ec451a6fc20\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1703fcfc-e49d-406b-809b-40fca8a1fbc4\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"55281726-8ca6-4d46-bad1-ffe114cf1e09\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 5,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T07:17:05\",\n            \"baseColor\": \"#040404\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page14_star_img1.png\",\n            \"width\": 1509,\n            \"height\": 1443,\n            \"id\": 0,\n            \"alt\": \"Black star shape\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 52,\n          \"y\": 57,\n          \"width\": 718,\n          \"height\": 685,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"012ff1f9-6e7a-4b92-96b7-3a8d8495e1a5\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">Read</span>\\n<span style=\\\"font-weight: 700; color: #020202\\\">more</span>\\n<span style=\\\"font-weight: 700; color: #020202\\\">stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 152,\n          \"id\": \"80e72f7f-1338-409f-a43c-50fe913ab37a\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 2, \"g\": 2, \"b\": 2, \"a\": 0.2 } },\n          \"x\": 0,\n          \"y\": 183,\n          \"width\": 412,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6da669c6-1f0a-4b13-b8c1-b0fbc87bf084\",\n          \"type\": \"shape\",\n          \"groupId\": \"ba446afe-2ae4-4765-ac02-f84fb67c7531\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 169,\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularBlackStar\" },\n          \"id\": \"65d900a8-4ee1-4490-96d1-5fc93648af13\",\n          \"groupId\": \"ba446afe-2ae4-4765-ac02-f84fb67c7531\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">Music</span>\\n<span style=\\\"font-weight: 700; color: #020202\\\">Legacy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 115,\n          \"height\": 60,\n          \"id\": \"ac767d4c-3130-4b09-94b3-44837191cb0e\",\n          \"x\": 51,\n          \"y\": 207,\n          \"type\": \"text\",\n          \"groupId\": \"fca2a702-a868-4e99-bf69-4745f35ff4be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #020202\\\">The life of Johnny Dash</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 212,\n          \"height\": 22,\n          \"id\": \"b192731b-c6f9-4820-99dd-a7460775654f\",\n          \"x\": 51,\n          \"y\": 274,\n          \"type\": \"text\",\n          \"groupId\": \"fca2a702-a868-4e99-bf69-4745f35ff4be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:14:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page14_img1.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man Playing Jazz Guitar\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#323c3e\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 281,\n          \"y\": 228,\n          \"width\": 84,\n          \"height\": 126,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"97cf5c8a-d18b-426f-bf88-ab42eb7b24a6\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Red Rose\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 937,\n              \"des\": -312,\n              \"tAsc\": 937,\n              \"tDes\": -312,\n              \"tLGap\": 0,\n              \"wAsc\": 1110,\n              \"wDes\": 690,\n              \"xH\": 468,\n              \"capH\": 600,\n              \"yMin\": -680,\n              \"yMax\": 1086,\n              \"hAsc\": 937,\n              \"hDes\": -312,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #020202\\\">Hollywood</span>\\n<span style=\\\"font-weight: 700; color: #020202\\\">Couples</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 156,\n          \"height\": 60,\n          \"id\": \"3f44114e-19a7-4997-87ad-f96598d5dd44\",\n          \"x\": 166,\n          \"y\": 414,\n          \"type\": \"text\",\n          \"groupId\": \"f85d0f28-d921-4576-998f-cde53117843a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #020202\\\">The Ups and Downs</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 198,\n          \"height\": 22,\n          \"id\": \"e1cc4281-7e28-4ffc-aeec-197a36e044fd\",\n          \"x\": 166,\n          \"y\": 480,\n          \"type\": \"text\",\n          \"groupId\": \"f85d0f28-d921-4576-998f-cde53117843a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 2, \"g\": 2, \"b\": 2, \"a\": 0.2 } },\n          \"width\": 412,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"96922fed-d760-45e2-9c9a-87ed30097d8a\",\n          \"x\": 0,\n          \"y\": 390,\n          \"type\": \"shape\",\n          \"groupId\": \"20a9ee22-2312-4d5f-8ef7-8bdb36d8b06e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"popularBlackStar\" },\n          \"id\": \"407315d7-7316-4657-a82e-06f1a206c57b\",\n          \"x\": 166,\n          \"y\": 377,\n          \"groupId\": \"20a9ee22-2312-4d5f-8ef7-8bdb36d8b06e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T05:15:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-life-story/page14_img2.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Two Women Laying On Bed\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#1e1908\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 48,\n          \"y\": 531,\n          \"width\": 130,\n          \"height\": 87,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3680e80f-3356-49d5-b975-8107a0cf67fd\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cb189374-11b0-4356-9c4c-a4a99c972f18\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"80e72f7f-1338-409f-a43c-50fe913ab37a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ae2575f9-7f41-4345-a60d-649ded64db30\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6da669c6-1f0a-4b13-b8c1-b0fbc87bf084\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7d8b5f7b-fa26-4f75-98f7-73f948c0d05b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"97cf5c8a-d18b-426f-bf88-ab42eb7b24a6\"],\n          \"duration\": 1200,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"379cd67a-19f9-4dee-bb96-61d0510f755d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ac767d4c-3130-4b09-94b3-44837191cb0e\"],\n          \"duration\": 1200,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"04332104-d8ce-4ebd-80e2-13c50f8dcf75\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b192731b-c6f9-4820-99dd-a7460775654f\"],\n          \"duration\": 1200,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"0f6ebb0a-ca10-4c5f-8042-c185e366b26a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"96922fed-d760-45e2-9c9a-87ed30097d8a\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"5f36c8b9-d42a-4139-9b44-4486cc16e837\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3f44114e-19a7-4997-87ad-f96598d5dd44\"],\n          \"duration\": 1200,\n          \"delay\": 2400\n        },\n        {\n          \"id\": \"9f1a01a8-d826-4d9e-9ff0-396d176d855e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e1cc4281-7e28-4ffc-aeec-197a36e044fd\"],\n          \"duration\": 1200,\n          \"delay\": 2400\n        },\n        {\n          \"id\": \"6b459851-fe39-4db8-a4da-dc1cb0839390\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3680e80f-3356-49d5-b975-8107a0cf67fd\"],\n          \"duration\": 1200,\n          \"delay\": 2400\n        },\n        {\n          \"id\": \"2230f53a-d815-49fc-a33a-64a1e4ab14a7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"65d900a8-4ee1-4490-96d1-5fc93648af13\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7f7e9d58-595e-46d6-b8c8-5728d504a990\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"407315d7-7316-4657-a82e-06f1a206c57b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 1100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 128, \"g\": 255, \"b\": 68 } },\n      \"type\": \"page\",\n      \"id\": \"88e3ec73-3672-4e03-9e49-3c94ce60ee5a\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"ba446afe-2ae4-4765-ac02-f84fb67c7531\": {\n          \"name\": \"Divider\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"20a9ee22-2312-4d5f-8ef7-8bdb36d8b06e\": {\n          \"name\": \"Divider\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f85d0f28-d921-4576-998f-cde53117843a\": {\n          \"name\": \"Heading\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fca2a702-a868-4e99-bf69-4745f35ff4be\": {\n          \"name\": \"Heading\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-q-and-a/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-q-and-a/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'celebrity-q-and-a',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Celebrity Q & A', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Interview', 'template keyword', 'web-stories'),\n    _x('Questions', 'template keyword', 'web-stories'),\n    _x('Modern', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black Bean', 'color', 'web-stories'),\n      color: '#131313',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Bright Coral Red', 'color', 'web-stories'),\n      color: '#fe3131',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s magazine look and stylish modern design will let you present video interviews and Q&A’s in a way that is fun, engaging, and entertaining.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-q-and-a/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/celebrity-q-and-a/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8292711e-a84b-46fc-9a01-06d14c221166\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 400,\n          \"focalX\": 37.20155166760863,\n          \"focalY\": 47.866127866823724,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T10:59:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page1_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1350,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of a woman with afro in an apartment\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#28221c\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"x\": 210,\n          \"y\": -57,\n          \"width\": 202,\n          \"height\": 299,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"34f04d90-ba21-4036-abc6-363af1d12bc7\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 230,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Zoe</span>\\n<span style=\\\"text-transform: uppercase\\\">Travis</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": -13,\n          \"width\": 299,\n          \"height\": 504,\n          \"id\": \"18d5d604-babb-4348-9987-8e4d6a1da97c\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 18,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 160,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">Q&amp;A</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 167,\n          \"y\": 356,\n          \"width\": 217,\n          \"height\": 215,\n          \"id\": \"5e174cb2-a3f1-4a21-a08d-de3b1af4b54a\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"By <span style=\\\"font-weight: 700\\\">Nicole Newman</span> 9/13/20\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 599,\n          \"width\": 274,\n          \"height\": 20,\n          \"id\": \"c99005c7-776e-46db-8bbf-53099c00b6ee\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"911c9de4-8b85-4779-aa58-321b4b7e3388\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"d7149945-c3b3-4672-a1e4-1101caf606df\",\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:00:52\",\n            \"baseColor\": \"#ceb4b5\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Woman in white tank top lying on bed\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.31 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.31 },\n                \"position\": 0.7\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Style icon and actress best known for her roles in Big Lies and Lo-Fidelity joins us for an edition of our rapid-fire Q &amp; A.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 79,\n          \"y\": 484,\n          \"width\": 256,\n          \"height\": 135,\n          \"id\": \"e472d3eb-4679-46ab-882d-bc3c50bccca0\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"af9baedc-0d75-4340-ad6c-ade749699558\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"d7149945-c3b3-4672-a1e4-1101caf606df\"],\n          \"panDir\": \"topToBottom\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f9324df0-5145-4972-b8a2-fea346d97858\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"bdb388e5-37e3-4e3e-9389-197ec24f9b87\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1774bba0-9b0d-4a74-b200-90533c54da09\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 160,\n          \"focalX\": 49.947406045107094,\n          \"focalY\": 27.735225762005765,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:02:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page3_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of a woman with afro in an apartment\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#33251e\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 272,\n          \"height\": 253,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"decfcaeb-a56a-46a7-bae6-48c0d86fa253\",\n          \"x\": 140,\n          \"y\": 422,\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"alpha\": 0.28\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 154,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Where</span>\\n<span style=\\\"text-transform: uppercase\\\">did you</span>\\n<span style=\\\"text-transform: uppercase\\\">grow up</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 478,\n          \"id\": \"cbcde42e-1c7f-45da-99f1-6f5569e3c9f5\",\n          \"x\": 47,\n          \"y\": -2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 269,\n          \"id\": \"c3941ca7-3cfe-4fd9-8409-096a20f70785\",\n          \"x\": 12,\n          \"y\": -64,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 26,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 218,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 293,\n          \"id\": \"ee1d45cd-54d0-44a2-b651-09ebe1812154\",\n          \"x\": 271,\n          \"y\": 253,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e7579782-eeb3-41b0-9737-8b6d57f6bc3b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"decfcaeb-a56a-46a7-bae6-48c0d86fa253\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"117e9a48-d7a6-48bf-8980-997cfcda6362\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 625,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"abc7c465-20d3-45f6-acc6-d5fa9303f1a8\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T09:42:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page4_vid1.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page4_vid1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A woman checking her clothes fit in front of a mirror\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#5f5f60\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"376eaf69-859a-4911-b177-e9527ae4f44e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f484a700-b391-44ff-9471-65a980cae7b7\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"84e8f574-948f-4337-a7d1-6c48a0f3b24f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 400,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f2f2f2; text-transform: uppercase\\\">Brooklyn</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 759,\n          \"height\": 526,\n          \"id\": \"8aec9776-cdcf-44d3-b68c-ce981dca68dc\",\n          \"x\": -123,\n          \"y\": 42,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 150,\n          \"focalX\": 53.68888888888888,\n          \"focalY\": 41.7037037037037,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:03:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page5_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of a woman sitting on a chair with a dog\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cfc2be\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 315,\n          \"height\": 515,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"27ae4af9-cf9d-424e-81fe-872391371fac\",\n          \"x\": 97,\n          \"y\": -57,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"It feels like Travis, 30, has always been famous — an indelible screen presence and iconic parents will do that.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 223,\n          \"height\": 85,\n          \"id\": \"c8c7c040-9a15-4729-8e33-5a768c1cef2f\",\n          \"x\": 97,\n          \"y\": 513,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c3fd3bad-e53d-4177-be24-b6ed7a2f9919\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8aec9776-cdcf-44d3-b68c-ce981dca68dc\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9d76fa95-d6d3-4e1b-acc9-7c6b6bc5bbd1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"53c94040-b94c-4c29-9bb2-0d3f3aa78dba\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 269,\n          \"id\": \"cd89deb5-663b-452a-81a5-c5a05bcd6c4f\",\n          \"x\": 11,\n          \"y\": 243,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 268,\n          \"id\": \"6b459de4-a092-4a90-ac45-7bd6acc30aed\",\n          \"x\": 279,\n          \"y\": 449,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">That was what I liked growing up. And also, that was what I thought I was suited for. I didn’t see a lot of people who looked like me in big movies.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 217,\n          \"id\": \"3f010d5c-2816-473f-8bd3-5c66b2fac1d9\",\n          \"x\": 47,\n          \"y\": 330,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 200,\n          \"focalX\": 55.81163195453408,\n          \"focalY\": 45.67853008509004,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:03:58\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page6_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman's Face\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3a2113\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 256,\n          \"height\": 366,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d89ed844-8f84-4c6f-aab6-d4c5d76bd533\",\n          \"x\": 157,\n          \"y\": -57,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3bfd391f-c305-44d6-adf8-41efd93c182c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d89ed844-8f84-4c6f-aab6-d4c5d76bd533\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"88c0b37e-4509-44ce-90b9-8cb95aee74a6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6b459de4-a092-4a90-ac45-7bd6acc30aed\"],\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"9e646ba3-8e9c-49c1-bf69-e6b14de6f2e4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cd89deb5-663b-452a-81a5-c5a05bcd6c4f\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"83de9e27-6ff8-46cc-8555-5a61aa1f64e0\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"428cb4ac-7928-4315-96a9-b1917ecd38a0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 230,\n          \"focalX\": 52.523750996858595,\n          \"focalY\": 71.64356837044049,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:04:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page7_img1.jpg\",\n            \"width\": 1086,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"People walking on bridge during daytime\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d8d9d4\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 265,\n          \"height\": 183,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4a6f6ac1-7a58-466e-b972-c0ee339808bf\",\n          \"x\": 147,\n          \"y\": -57,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 180,\n          \"focalX\": 48.616985560983515,\n          \"focalY\": 33.736774652306025,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:05:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page7_img2.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"City Street\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3c3336\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 331,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"685975e0-431f-4c4b-8e93-5a829d15b08b\",\n          \"x\": 0,\n          \"y\": 455,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 159,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Brooklyn</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 344,\n          \"height\": 208,\n          \"id\": \"b64babea-33f3-4264-8af4-3fdeadaab637\",\n          \"x\": 35,\n          \"y\": 142,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 159,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Manhattan</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 344,\n          \"height\": 208,\n          \"id\": \"99ed2b90-9c62-4155-9b62-c80eda6ac022\",\n          \"x\": 35,\n          \"y\": 295,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 116,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">or</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 137,\n          \"height\": 156,\n          \"id\": \"ca68969a-9b92-4ef2-bea4-e04d195b2b2c\",\n          \"x\": 14,\n          \"y\": 235,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 160,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 63,\n          \"height\": 215,\n          \"id\": \"27029d5c-cb10-4400-92b6-6f3aa651b30d\",\n          \"x\": 341,\n          \"y\": 254,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"31a49106-2f25-45e6-ab5e-baa112fcac8d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4a6f6ac1-7a58-466e-b972-c0ee339808bf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"33867d52-f3e4-4638-a2d5-229d00ca1a7c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b64babea-33f3-4264-8af4-3fdeadaab637\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c2ae724d-d845-4503-9b58-0be2343ef098\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ca68969a-9b92-4ef2-bea4-e04d195b2b2c\"],\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"b699e121-7b13-4759-8f19-474fe71c7704\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"99ed2b90-9c62-4155-9b62-c80eda6ac022\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"3e575c80-91bd-43b8-b67b-c2800d4ffd24\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"685975e0-431f-4c4b-8e93-5a829d15b08b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"7e03bc23-59a5-4a41-9c2f-1affa9f92606\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"27029d5c-cb10-4400-92b6-6f3aa651b30d\"],\n          \"duration\": 600,\n          \"delay\": 800\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0e0e880b-1817-4bae-892d-3d49fe25b34d\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 625,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"6fdcc6c8-1d7d-4749-9469-658bd3b5ea7a\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-02T10:57:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page8_vid1.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page8_vid1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"alt\": \"A Woman Lying On Bed\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#393939\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c5d0dc2a-59bc-4fe5-82c5-4e2dd8ea2373\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b3631c7e-3b25-4581-8301-07019c59001d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"06a5fd42-8759-4527-839d-e6db322ba611\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 400,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f2f2f2; text-transform: uppercase\\\">Brooklyn</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 759,\n          \"height\": 526,\n          \"id\": \"5a747c42-7d9b-4e26-9adb-29f86fccddcf\",\n          \"x\": -123,\n          \"y\": 42,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 156,\n          \"focalX\": 57.963618922231554,\n          \"focalY\": 50.016088119034805,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:06:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page9_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of a woman reading newspaper\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c0b8b3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 304,\n          \"height\": 448,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c499efe0-85f5-45b7-adc5-8b958ae32ca6\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"There is so much diverse energy in Brooklyn. You can take a turn down a lovely neighborhood street, or get that lively nightlife if you want.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 223,\n          \"height\": 129,\n          \"id\": \"032c2609-dcf6-4f9e-b5ba-e68180af13f0\",\n          \"x\": 97,\n          \"y\": 479,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7208af67-7511-4d09-a42e-f3bab2c5dd0a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5a747c42-7d9b-4e26-9adb-29f86fccddcf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"36b691c7-6c88-4af4-a2d4-8e8fafe57659\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9bd1ce1d-a481-4bf1-addb-d5db72633a8f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 269,\n          \"id\": \"71853bb0-e683-4df4-afc9-6378607039e3\",\n          \"x\": 11,\n          \"y\": 243,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 85,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 269,\n          \"id\": \"b209ce60-b077-4423-bdbe-bbaf46e74cbf\",\n          \"x\": 279,\n          \"y\": 449,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">A lot of what inspires me is rooted in Brooklyn. I love to be at home whenever I can and I really fill my place with treasures from people near and dear to me.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 216,\n          \"id\": \"33558267-f6af-4466-9933-6b4673dd6b26\",\n          \"x\": 47,\n          \"y\": 330,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 160,\n          \"focalX\": 48.827413496495666,\n          \"focalY\": 35.928961957948054,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:07:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of a woman in an apartment\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#342420\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 256,\n          \"height\": 366,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbf1acf8-1862-4b25-8730-f18c60359851\",\n          \"x\": 157,\n          \"y\": -57,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5cb72c19-8b4d-4334-8266-4fcadf162a06\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cbf1acf8-1862-4b25-8730-f18c60359851\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9cb9da9d-490b-4276-adbb-0858bf95db3c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"71853bb0-e683-4df4-afc9-6378607039e3\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"970c6e97-8507-42a4-bbfe-48b28ed1b575\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b209ce60-b077-4423-bdbe-bbaf46e74cbf\"],\n          \"duration\": 600,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"8763dc13-eb60-4ff7-b17f-f8f8388d0978\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 625,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"378e5de8-25ed-4f1a-8f0c-9a90240fcd43\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T09:42:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page11_vid1.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page11_vid1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A woman embracing her pet dog in bed\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#727273\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"00330383-ed24-4e3a-96c9-9fb40d7c0eb5\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Watch the full interview\",\n        \"theme\": \"light\"\n      },\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"26e4fb31-8acb-4229-bed1-14034c956fce\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c36f0cfe-d15f-4b37-8c02-de3bf7b7c8e5\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 271,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f2f2f2; text-transform: uppercase\\\">More videos</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 759,\n          \"height\": 356,\n          \"id\": \"bb66915e-fbea-4a6a-b883-31fcc3476910\",\n          \"x\": -115,\n          \"y\": 122,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 120,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Javier</span>\\n<span style=\\\"text-transform: uppercase\\\">Dardem</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 265,\n          \"id\": \"2184c995-419b-4bbc-b56f-e7736ad376eb\",\n          \"x\": 56,\n          \"y\": 21,\n          \"type\": \"text\",\n          \"groupId\": \"3ebd0057-d737-46f7-8c87-e6ff33636366\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:07:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page12_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Man in White Shirt Taking Selfie\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#33211f\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 200,\n          \"height\": 250,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1e0f3868-24d5-4f1b-aab3-dd539ce372bf\",\n          \"x\": 212,\n          \"y\": -57,\n          \"type\": \"image\",\n          \"groupId\": \"3ebd0057-d737-46f7-8c87-e6ff33636366\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 16,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 66,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">Q&amp;A</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 89,\n          \"id\": \"03d45231-d0e1-4389-b51f-d7457f38d448\",\n          \"x\": 27,\n          \"y\": -2,\n          \"type\": \"text\",\n          \"groupId\": \"3ebd0057-d737-46f7-8c87-e6ff33636366\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 238,\n          \"focalX\": 44.35726663090819,\n          \"focalY\": 35.77049846055113,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:08:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/celebrity-q-and-a/page12_img2.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman in Black Double Breasted Long-sleeved Dress\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#dac4ae\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 49, \"b\": 49 } },\n          \"width\": 168,\n          \"height\": 294,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4b3c1c28-6607-4fc2-a4b5-ab606572f279\",\n          \"x\": 0,\n          \"y\": 381,\n          \"type\": \"image\",\n          \"groupId\": \"0d44408c-9f4e-4d01-bdd8-073a8dcd419b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Six Caps\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2263,\n              \"des\": -432,\n              \"tAsc\": 2263,\n              \"tDes\": -432,\n              \"tLGap\": 0,\n              \"wAsc\": 2263,\n              \"wDes\": 432,\n              \"yMin\": -506,\n              \"yMax\": 2281,\n              \"hAsc\": 2263,\n              \"hDes\": -432,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 120,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Dree</span>\\n<span style=\\\"text-transform: uppercase\\\">Larson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 266,\n          \"id\": \"b0c805a0-3f15-4fe8-aff9-140d6a1d7def\",\n          \"x\": 181,\n          \"y\": 346,\n          \"type\": \"text\",\n          \"groupId\": \"0d44408c-9f4e-4d01-bdd8-073a8dcd419b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Covered By Your Grace\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 995,\n              \"des\": -384,\n              \"tAsc\": 995,\n              \"tDes\": -384,\n              \"tLGap\": 0,\n              \"wAsc\": 995,\n              \"wDes\": 384,\n              \"xH\": 500,\n              \"capH\": 795,\n              \"yMin\": -384,\n              \"yMax\": 1021,\n              \"hAsc\": 995,\n              \"hDes\": -384,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 66,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ff2d2d\\\">Q&amp;A</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 92,\n          \"height\": 89,\n          \"id\": \"c6d5c39d-d54a-4748-b071-603b17e88bf7\",\n          \"x\": 275,\n          \"y\": 543,\n          \"type\": \"text\",\n          \"groupId\": \"0d44408c-9f4e-4d01-bdd8-073a8dcd419b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a30ff780-af50-41bb-8a2a-586d586a8150\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1e0f3868-24d5-4f1b-aab3-dd539ce372bf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"03ef823c-b842-4814-9419-8adfabd45c30\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2184c995-419b-4bbc-b56f-e7736ad376eb\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6b718c7e-99f5-49f1-8b5b-9633818d879d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"03d45231-d0e1-4389-b51f-d7457f38d448\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"00fdcc6d-22b5-4179-bcd7-a05c226dd79c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4b3c1c28-6607-4fc2-a4b5-ab606572f279\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"bb6aa27c-9627-4ea2-a697-b64c77711d37\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b0c805a0-3f15-4fe8-aff9-140d6a1d7def\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"2becce85-c134-4c91-9414-3da6ecbc53e4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c6d5c39d-d54a-4748-b071-603b17e88bf7\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2a32f8e5-db1b-4e1c-95b9-534caadfdbe1\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"0d44408c-9f4e-4d01-bdd8-073a8dcd419b\": {\n          \"name\": \"QA\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3ebd0057-d737-46f7-8c87-e6ff33636366\": {\n          \"name\": \"QA\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/diy-home-office/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/diy-home-office/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'diy-home-office',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('DIY Home Office', 'template name', 'web-stories'),\n  tags: [\n    _x('Arts & Craft', 'template keyword', 'web-stories'),\n    _x('Home Office', 'template keyword', 'web-stories'),\n    _x('Interior', 'template keyword', 'web-stories'),\n    _x('Vintage', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black Pepper', 'color', 'web-stories'),\n      color: '#3d3730',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cannon Black', 'color', 'web-stories'),\n      color: '#373737',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pastel Orange', 'color', 'web-stories'),\n      color: '#ffb555',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White Linen', 'color', 'web-stories'),\n      color: '#f6f2ed',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gray Beige', 'color', 'web-stories'),\n      color: '#c7bbaf',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s balanced layout and warm, pastel color palette will let you create stories about home decor, arts and crafts, and other DIY guides that are detailed and inspiring.',\n    'web-stories'\n  ),\n  vertical: _x('Arts & Crafts', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/diy-home-office/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/diy-home-office/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"022ce6ae-e8ef-4c37-a65a-512cdbd2fa39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -9,\n          \"y\": -248,\n          \"width\": 421,\n          \"height\": 632,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"616582fc-2bd7-46e5-b273-4afb28c63750\",\n          \"scale\": 100,\n          \"focalX\": 51.40597539543058,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page01_12_image01.jpg\",\n            \"width\": 1707,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"White steel chair in front round table on white rug\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c8c7c4\",\n            \"isExternal\": true\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#3c3434\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page01_image02.png\",\n            \"width\": 133,\n            \"height\": 132,\n            \"id\": 0,\n            \"alt\": \"House Symbol in circle.\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": 3,\n          \"width\": 66,\n          \"height\": 65,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"280440cd-40d8-429a-aa23-e895710955d8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 61, \"g\": 55, \"b\": 48 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 224,\n          \"width\": 412,\n          \"height\": 450,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"caf5d5c5-55ac-4ff8-9c13-740c5e2b4cbc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f6f2ed\\\">DIY</span>\\n<span style=\\\"color: #f6f2ed\\\">Budget</span>\\n<span style=\\\"color: #f6f2ed\\\">Friendly</span>\\n<span style=\\\"color: #ffb555\\\">at-home</span>\\n<span style=\\\"color: #ffb555\\\">office</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 270,\n          \"width\": 246,\n          \"height\": 320,\n          \"id\": \"e0dcbf6e-c26f-4509-bb08-8aacfc57fa40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ffb555\\\">Sylvia Tribel · 31 Aug, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 598,\n          \"width\": 203,\n          \"height\": 19,\n          \"id\": \"e1df29f5-2ec4-4bcc-85aa-d136b15122e6\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a2ac85f3-e76c-4d6d-9664-2b9311857b1e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"022ce6ae-e8ef-4c37-a65a-512cdbd2fa39\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5f3803d2-5a26-481b-b698-af6e286ce27c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#c8c3c0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page02_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Female Remote Worker Typing On Laptop At Home\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 263,\n          \"y\": 0,\n          \"width\": 102,\n          \"height\": 153,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"10ceb109-edf0-4ecb-8a74-77034ce61db9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 181, \"b\": 85 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 263,\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c9814697-7f72-45d1-a9f0-a956c6e16bc5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #373737\\\">What \\nwe need</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 246,\n          \"height\": 111,\n          \"id\": \"fb36525e-6494-4ed9-8868-60a27afeb4c1\",\n          \"x\": 47,\n          \"y\": 256,\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"893722cb-2a8d-4e59-b3e2-3ff40d2793ed\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c9814697-7f72-45d1-a9f0-a956c6e16bc5\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fb76032f-ee0d-4499-ae06-39b54e7e71d5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"10ceb109-edf0-4ecb-8a74-77034ce61db9\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"b1ffaed7-d622-45bd-9225-67205ffccb1d\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"756e2128-0d13-4e13-95a4-402cc9cb0bb1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page03_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1265,\n            \"id\": 0,\n            \"alt\": \"Photo Of White Couch On Wooden Floor\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4c2c1\",\n            \"isExternal\": true\n          },\n          \"x\": 48,\n          \"y\": 44,\n          \"width\": 365,\n          \"height\": 350,\n          \"scale\": 100,\n          \"focalX\": 34.46301279401976,\n          \"focalY\": 50.05714374653969,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c7b61b8e-e74a-4df5-99e0-0951fdd9ec23\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-26T15:04:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page03_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White ceramic vase in creative shape of ring placed on white marble stand against beige wall as home decoration element or art object\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ccc2ba\",\n            \"isExternal\": true\n          },\n          \"x\": 245,\n          \"y\": 359,\n          \"width\": 120,\n          \"height\": 155,\n          \"scale\": 100,\n          \"focalX\": 50.16666925756169,\n          \"focalY\": 57.01851847789784,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a5f80da0-02c5-40dd-9364-0f365c2168f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Look for a vintage, statement sofa for your seating area. Scour Ebay, or go to garage sales in your town!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 189,\n          \"height\": 107,\n          \"id\": \"7a4c91ce-8adc-40bd-8846-9b56a3934c5e\",\n          \"x\": 48,\n          \"y\": 499,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fbf3df4b-d044-4202-ae98-de1f50b13352\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a5f80da0-02c5-40dd-9364-0f365c2168f3\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"34800717-cf07-4188-9507-776d4f039b8f\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"64f2d500-f5b6-40c9-a7ad-dc3c7c9c49c9\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page04_image01.jpg\",\n            \"width\": 805,\n            \"height\": 1207,\n            \"id\": 0,\n            \"alt\": \"Beige Wooden Bar Stool\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#acb9b8\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 389,\n          \"width\": 218,\n          \"height\": 138,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e0f8be22-180e-45b6-ae73-426cacf61c6a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Also consider unusual or minimalistic stools. Overstock sites are a great place to find affordable versions.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 175,\n          \"height\": 107,\n          \"type\": \"text\",\n          \"id\": \"c58c7605-2ce3-4023-9f7b-f69857b6acd7\",\n          \"x\": 66,\n          \"y\": 402\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9bee326d-f612-407d-85b8-7a970119396d\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"64f2d500-f5b6-40c9-a7ad-dc3c7c9c49c9\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d61744e3-eac7-4f14-8ebb-74ffc667b202\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f0f5fc6e-1f9c-4d7c-bb76-243f67c77948\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"14c6800e-98ba-4d9d-829e-8717d5703754\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Vintage chairs are also a great choice. They usually become a focal piece of the office, not just a comfy place to sit.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 268,\n          \"height\": 63,\n          \"type\": \"text\",\n          \"id\": \"4232e1c5-431d-4e22-8bc7-b9f013f8b519\",\n          \"x\": 51,\n          \"y\": 10\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 368,\n          \"height\": 350,\n          \"scale\": 100,\n          \"focalX\": 50.14118961267398,\n          \"focalY\": 62.062626018231846,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"66ded9ac-538f-4f36-b87c-d620c3f3ab2d\",\n          \"x\": 0,\n          \"y\": 325,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-26T15:12:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page05_image02.jpg\",\n            \"width\": 1704,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Armless Chair Near White Wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d2d5d6\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page05_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1746,\n            \"id\": 0,\n            \"alt\": \"Two White Flower Vases\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e1e0dc\",\n            \"isExternal\": true\n          },\n          \"x\": 51,\n          \"y\": 138,\n          \"width\": 204,\n          \"height\": 228,\n          \"scale\": 100,\n          \"focalX\": 50.1034824602391,\n          \"focalY\": 59.172916458484195,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8dfb4a66-1c4c-4967-9c52-6856c055307c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e08e18b3-a206-48f1-a2f2-0f25f691f453\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8dfb4a66-1c4c-4967-9c52-6856c055307c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"68080c3e-35ee-49aa-9e18-63e277dab649\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fea02842-08b8-481e-8c68-8f5d671d5071\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 181, \"b\": 85 } },\n          \"x\": 0,\n          \"y\": 267,\n          \"width\": 6,\n          \"height\": 91,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cb51538e-bb28-41cf-9061-636c15b98e4f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Do it in just</span>\\n<span style=\\\"color: #373737\\\">five steps</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 246,\n          \"height\": 111,\n          \"id\": \"c49bbb0a-72ba-4388-bf64-94165b4b9164\",\n          \"x\": 47,\n          \"y\": 256,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#c3c1c0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page06_08_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Positive Young Woman Using Laptop In Modern Living Room With Wooden Staircase\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": 463,\n          \"width\": 103,\n          \"height\": 154,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9fac00ef-227e-466a-a500-dc22e235ea5e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e8879055-6166-459a-b3b8-d3a8d042ab3e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cb51538e-bb28-41cf-9061-636c15b98e4f\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e6ffed00-9e6a-4396-b73c-bced413bf82b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9fac00ef-227e-466a-a500-dc22e235ea5e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2500,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"ef9b90a1-634e-412b-b26b-4b0541cfd938\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b3dd6be7-61ba-41e5-ae72-528b23cadde9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page07_image01.jpg\",\n            \"width\": 1710,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Person Holding White Ceramic Mug\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d4d2cc\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 562,\n          \"scale\": 110,\n          \"focalX\": 47.16732542819499,\n          \"focalY\": 57.23414754971591,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"228d2958-3614-4842-ab36-60b075813ddb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 94,\n          \"backgroundColor\": { \"color\": { \"r\": 199, \"g\": 187, \"b\": 175 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #373737\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 137,\n          \"height\": 136,\n          \"type\": \"text\",\n          \"id\": \"8ed9f9db-812b-4a82-8244-0cf7e5a9a76a\",\n          \"x\": 48,\n          \"y\": 397,\n          \"tagName\": \"p\",\n          \"marginOffset\": -24.872558593749986\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Since all 3 of our design inspiration leans more minimal, we can gracefully incorporate all styles.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"type\": \"text\",\n          \"id\": \"4a91612c-4a90-4912-9e47-4bbd0642e7de\",\n          \"x\": 48,\n          \"y\": 555\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c505d065-e893-4a8e-9a83-5c376213ac85\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8ed9f9db-812b-4a82-8244-0cf7e5a9a76a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"2a5a97de-b4c8-467b-998d-8738614e45b4\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8abc1bd7-7349-4a27-8a63-67653eccaff4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">You can even incorporate comfortable seating. Who says a workspace has to be all work and no play?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"id\": \"5caf6a6a-a8e6-4a23-8530-01d824fee4a4\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 125,\n          \"focalX\": 50.06766381766382,\n          \"focalY\": 62.15839660493826,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-26T15:14:32\",\n            \"baseColor\": \"#bfbdb9\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page06_08_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Positive Young Woman Using Laptop In Modern Living Room With Wooden Staircase\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 114,\n          \"width\": 412,\n          \"height\": 562,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"338075b0-fcbd-4902-b5f8-000e38b86fa2\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 94,\n          \"backgroundColor\": { \"color\": { \"r\": 199, \"g\": 187, \"b\": 175 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #373737\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 137,\n          \"height\": 136,\n          \"type\": \"text\",\n          \"x\": 228,\n          \"y\": 80,\n          \"tagName\": \"p\",\n          \"marginOffset\": -24.872558593749986,\n          \"id\": \"85701ccb-a47a-41c1-9937-9b974d1039bf\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"85701ccb-a47a-41c1-9937-9b974d1039bf\"],\n          \"id\": \"426d2f33-3daa-450b-8096-5406bb547886\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"9b0da8f6-4d20-4038-90eb-cb6e1a848297\",\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"797d4998-9272-41cf-be3c-b8e249415c5e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 132,\n          \"focalX\": 51.255829489041346,\n          \"focalY\": 38.82981210824519,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page09_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1706,\n            \"id\": 0,\n            \"alt\": \"Wooden Bench And Stools In A Cozy Room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#988f85\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 562,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f4ab886d-30d8-4f0b-9fd1-d196b17331bf\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Incorporate materials that are complementary. That can be woods, metals, or colors that are neutral.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"id\": \"2b92d8b3-1992-4277-b533-79437eafc19c\",\n          \"x\": 48,\n          \"y\": 555,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 94,\n          \"backgroundColor\": { \"color\": { \"r\": 199, \"g\": 187, \"b\": 175 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #373737\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 137,\n          \"height\": 136,\n          \"type\": \"text\",\n          \"x\": 48,\n          \"y\": 397,\n          \"tagName\": \"p\",\n          \"marginOffset\": -24.872558593749986,\n          \"id\": \"229841db-fecf-4e5c-9e43-bd33b7a1e342\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"229841db-fecf-4e5c-9e43-bd33b7a1e342\"],\n          \"id\": \"e50c01ea-f7ca-4087-9920-6777a8014ee2\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"cc74ccfa-71fb-4aaf-9703-cdcecbd0cd83\",\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e93135a8-e67e-40f8-bc6c-0c2396e40ce9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">You can create your own desk with two sawhorse legs and simple plank of wood, or purchase a minimal wooden desk.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"id\": \"cd02ebfb-ebad-413f-b6e4-e17b4350d0dd\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 123,\n          \"focalX\": 50,\n          \"focalY\": 58.74597513146059,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page10_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1917,\n            \"id\": 0,\n            \"alt\": \"Brown Wooden Table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bfc8c9\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 114,\n          \"width\": 412,\n          \"height\": 562,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"85115cb6-75c3-4a66-ad3b-0ded6aa57836\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 94,\n          \"backgroundColor\": { \"color\": { \"r\": 199, \"g\": 187, \"b\": 175 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #373737\\\">4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 137,\n          \"height\": 136,\n          \"type\": \"text\",\n          \"x\": 228,\n          \"y\": 80,\n          \"tagName\": \"p\",\n          \"marginOffset\": -24.872558593749986,\n          \"id\": \"66e68c40-bae0-4832-920a-39fed633261a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"66e68c40-bae0-4832-920a-39fed633261a\"],\n          \"id\": \"8cea9f2d-6c1d-41b7-8606-66498dd0300e\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"aff9c463-5644-4118-a447-39d726d06172\",\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ca884449-d7e3-41cf-8840-b655d62703c3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 140,\n          \"focalX\": 45.78924162257497,\n          \"focalY\": 47.16195512617261,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page11_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Decorative golden leaves in unique formed white vase placed on marble table against beige background\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cac2bb\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 562,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"324004ab-f0f0-4ea7-8309-87fab679ae8c\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">Lastly, put the finishing touches on your workspace once all the furniture is assembled and put into place.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"id\": \"64fc0a48-d0b4-41cb-8235-1518e3319c15\",\n          \"x\": 48,\n          \"y\": 555,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 94,\n          \"backgroundColor\": { \"color\": { \"r\": 199, \"g\": 187, \"b\": 175 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #373737\\\">5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 137,\n          \"height\": 136,\n          \"type\": \"text\",\n          \"x\": 48,\n          \"y\": 397,\n          \"tagName\": \"p\",\n          \"marginOffset\": -24.872558593749986,\n          \"id\": \"8a74a479-1658-42ce-919c-922fe49b2a15\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"8a74a479-1658-42ce-919c-922fe49b2a15\"],\n          \"id\": \"fd442031-28a9-49e4-9b40-f0b245f1a5cf\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 246, \"g\": 242, \"b\": 237 } },\n      \"type\": \"page\",\n      \"id\": \"71103bca-aa69-48a7-aa42-6bebcb12b0d8\",\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"6b50fd48-cbee-4b05-a963-63f7d1f08028\",\n          \"scale\": 118,\n          \"focalX\": 42.05663618400802,\n          \"focalY\": 46.6896186440678,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-26T14:55:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page01_12_image01.jpg\",\n            \"width\": 1707,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White steel chair in front round table on white rug\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c9c9c7\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">The Result</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 32,\n          \"type\": \"text\",\n          \"id\": \"68d6f3c3-7390-4122-9604-da058bc13a39\",\n          \"x\": 225,\n          \"y\": 164\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #373737\\\">A well-rounded, minimal chic office space!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 62,\n          \"type\": \"text\",\n          \"id\": \"ae40221d-36f7-41aa-8762-22b5f8c00794\",\n          \"x\": 226,\n          \"y\": 201\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 61, \"g\": 55, \"b\": 48 } },\n          \"type\": \"shape\",\n          \"x\": 226,\n          \"y\": 280,\n          \"width\": 128,\n          \"height\": 58,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b63d1755-32ee-436b-aef0-5cae6d0db50b\",\n          \"groupId\": \"7e1e3b93-5644-4a34-9b24-338e9c9a9906\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f6f2ed\\\">Voilá !</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 53,\n          \"type\": \"text\",\n          \"id\": \"b282552a-c253-4393-a17f-f9689ec7fb7f\",\n          \"x\": 234,\n          \"y\": 280,\n          \"groupId\": \"7e1e3b93-5644-4a34-9b24-338e9c9a9906\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 181, \"b\": 85 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 667,\n          \"width\": 412,\n          \"height\": 8,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"16bc4f8d-28dd-4793-9c0b-784078204ce1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"83b11778-a27c-4634-bf67-a7b844a15dc9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b282552a-c253-4393-a17f-f9689ec7fb7f\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"583a1769-306a-488f-b5ab-54165fdfdb1a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16bc4f8d-28dd-4793-9c0b-784078204ce1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"34ff8fa6-6779-4404-8741-bdef70a62909\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"aa302879-fe46-4d1c-8a4c-d31f7ef5c45b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7e1e3b93-5644-4a34-9b24-338e9c9a9906\": {\n          \"name\": \"Voila\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"0d11c8da-20db-4fd0-a503-5b413092cbe5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Serif\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f6f2ed\\\">Next up</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 165,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"id\": \"c89a1406-36c6-4fff-a53e-1afb70e4e056\",\n          \"x\": 47,\n          \"y\": 32\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page13_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"A Romantic Setting In The Bathroom\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#7c6f60\",\n            \"isExternal\": true\n          },\n          \"x\": 44,\n          \"y\": 138,\n          \"width\": 368,\n          \"height\": 350,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b3ecdca4-ddaf-4d99-9796-9ae032783b86\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 134,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"74c63c75-03d6-4156-89d0-bf0d6ae37ba9\",\n          \"x\": 245,\n          \"y\": 403,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/diy-home-office/page13_image02.jpg\",\n            \"width\": 1707,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Green cactus plant near wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4beb8\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f6f2ed\\\">Build a budget home spa in your bathroom</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 184,\n          \"height\": 40,\n          \"type\": \"text\",\n          \"id\": \"ab29bebd-17cd-409c-ab71-523ad8e04569\",\n          \"x\": 47,\n          \"y\": 563,\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 251,\n          \"y\": 588,\n          \"width\": 107,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"atHomeOfficeArrow\" },\n          \"id\": \"7102a86e-52d0-4ca2-a85c-6670406c2ea7\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6319fd8e-382a-456b-8dab-1f46d5dc0678\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"74c63c75-03d6-4156-89d0-bf0d6ae37ba9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"56a1693e-a365-4a09-b213-41bdfc8d861a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7102a86e-52d0-4ca2-a85c-6670406c2ea7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 61, \"g\": 55, \"b\": 48 } },\n      \"type\": \"page\",\n      \"id\": \"5c8c6848-3cb2-4e4d-8897-36870c4c3c83\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/doers-get-more-done/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/doers-get-more-done/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'doers-get-more-done',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Doers Get More Done', 'template name', 'web-stories'),\n  tags: [\n    _x('Doers', 'template keyword', 'web-stories'),\n    _x('Expand', 'template keyword', 'web-stories'),\n    _x('Start', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#211f1e',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Orange', 'color', 'web-stories'),\n      color: '#ff630b',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cream', 'color', 'web-stories'),\n      color: '#faf4ea',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Gray', 'color', 'web-stories'),\n      color: '#858280',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Motivate your audience to get out there and make something with the bold DIY template. Use it for DIY, crafting, 3D printing, woodworking or any other content targeting makers.',\n    'web-stories'\n  ),\n  vertical: _x('DIY', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/doers-get-more-done/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/doers-get-more-done/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 90,\n          \"y\": 79,\n          \"width\": 128,\n          \"height\": 128,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"acc2f8e0-b819-4adf-9b9f-7bf7c878d7b9\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"type\": \"image\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"36358de8-eac2-4a37-b86c-6d18eae1187c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#ccc7c3\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page1_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page1_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 41,\n          \"y\": 233,\n          \"width\": 330,\n          \"height\": 267,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"id\": \"4e256c35-5e30-45f5-9095-d8ce0a230b21\",\n          \"content\": \"<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">Doers&nbsp;</span>\\n<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">Get </span><span style=\\\"color: #ff630b; text-transform: uppercase\\\">More Done</span>\",\n          \"fontSize\": 90,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 145,\n          \"y\": 86,\n          \"width\": 123,\n          \"height\": 18,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"id\": \"b8f9eb9a-5007-4642-aca3-750cdb7c7463\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Issue No. 2</span>\",\n          \"fontSize\": 14,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 197,\n          \"y\": 119,\n          \"width\": 17,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"diyOrangeCross\" },\n          \"id\": \"4baca404-e3f5-41d6-b4b0-36e2ecaee696\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"d47afc22-71b7-4303-9917-96f9a31ad38a\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 81,\n          \"y\": 44,\n          \"width\": 128,\n          \"height\": 128,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"6d60fa52-25c3-4207-acea-45c2c9680fcf\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -56,\n          \"width\": 412,\n          \"height\": 730,\n          \"type\": \"image\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 41.681999964185515,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"00210dfd-2813-4a6c-9182-df2071c28e1f\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#bbb7b5\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page2_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page2_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": -70,\n          \"y\": 284,\n          \"width\": 476,\n          \"height\": 154,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"8e053a88-17a5-4162-8ae0-214e5a84e33c\",\n          \"content\": \"<span style=\\\"color: #fafae4; text-transform: uppercase\\\">Expand Your</span>\\n<span style=\\\"color: #fafae4; text-transform: uppercase\\\">Living Space To</span>\",\n          \"fontSize\": 77,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 72,\n          \"y\": 185,\n          \"width\": 422,\n          \"height\": 77,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"id\": \"9b8df2db-2f35-4aa6-a48c-f7bc71afc6de\",\n          \"content\": \"<span style=\\\"color: #ff630b; text-transform: uppercase\\\">The Outdoors</span>\",\n          \"fontSize\": 77,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"80de7e7c-5cb8-44fb-9451-f12c0064d4f0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8e053a88-17a5-4162-8ae0-214e5a84e33c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c375f60a-4618-414e-ae02-012669b24b05\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9b8df2db-2f35-4aa6-a48c-f7bc71afc6de\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"6a6ddf2d-7f98-405a-8c95-76b0440f9b30\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"a848ae15-78c1-488a-9c2f-befbc69a1fb3\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 167.5,\n          \"y\": 445,\n          \"width\": 77,\n          \"height\": 77,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 140,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"7a20f7e7-fe90-46b3-9382-7204473f2724\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#413d3c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page3_image1.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 145,\n          \"y\": 547,\n          \"width\": 123,\n          \"height\": 18,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"id\": \"b767306b-6b92-4b2a-935d-00954a502681\",\n          \"content\": \"<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">Anonymous</span>\",\n          \"fontSize\": 14,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 164,\n          \"y\": 38,\n          \"width\": 84,\n          \"height\": 65,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"id\": \"ec867712-86cf-4681-a2f9-48fe633cfb4c\",\n          \"content\": \"<span style=\\\"color: #faf4ea\\\">“”</span>\",\n          \"fontSize\": 66,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 164,\n          \"y\": 231,\n          \"width\": 170,\n          \"height\": 13,\n          \"type\": \"shape\",\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 133, \"g\": 130, \"b\": 128 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7d8bae39-0d48-4424-b7ac-f95231a7c688\"\n        },\n        {\n          \"x\": 108,\n          \"y\": 266,\n          \"width\": 188,\n          \"height\": 13,\n          \"type\": \"shape\",\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 133, \"g\": 130, \"b\": 128 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a9bf183b-8951-4fdc-8bfd-fa6a71736a28\"\n        },\n        {\n          \"x\": 68.5,\n          \"y\": 139,\n          \"width\": 275,\n          \"height\": 212,\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"id\": \"1788ced3-50fc-495e-9944-9f7a205b3107\",\n          \"content\": \"<span style=\\\"color: #faf4ea\\\">Always pay particular attention to the </span><span style=\\\"color: #faf4ea\\\">terrain, soil and weather</span><span style=\\\"color: #faf4ea\\\"> influences of your landscape.</span>\",\n          \"fontSize\": 30,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fa5f6052-f8ce-4e58-9163-186e2769cb13\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ec867712-86cf-4681-a2f9-48fe633cfb4c\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7b9857a3-6c57-4952-9c1b-141f8fefbd2f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1788ced3-50fc-495e-9944-9f7a205b3107\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"8d61e0c1-7264-4311-ab7f-280224e497fb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a9bf183b-8951-4fdc-8bfd-fa6a71736a28\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"17668082-c754-491e-89b9-3dfbf68b880f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7d8bae39-0d48-4424-b7ac-f95231a7c688\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 100\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"6a5fbd97-2e43-4f7a-a672-6b1b90f8a625\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 21,\n          \"y\": 64,\n          \"width\": 128,\n          \"height\": 128,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"5249418e-8fb7-46d7-8af1-835671d52f2b\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -1,\n          \"y\": -57,\n          \"width\": 413,\n          \"height\": 732,\n          \"type\": \"image\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 140,\n          \"focalX\": 30.027943808528523,\n          \"focalY\": 55.266039046623774,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"21c8f992-9285-486b-955d-89212dc3435c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#141513\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page4_page5_bg.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_page5_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 44,\n          \"y\": 37,\n          \"width\": 246,\n          \"height\": 220,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"457c0ed6-69da-43c4-ac59-1d1359d980b9\",\n          \"content\": \"<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">Start</span>\\n<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">With</span>\",\n          \"fontSize\": 110,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 54,\n          \"y\": 257,\n          \"width\": 324,\n          \"height\": 330,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"id\": \"b0b134b8-2aae-4da8-83be-a0f5a811f082\",\n          \"content\": \"<span style=\\\"color: #ff630b; text-transform: uppercase\\\">The</span>\\n<span style=\\\"color: #ff630b; text-transform: uppercase\\\">Founda</span>\\n<span style=\\\"color: #ff630b; text-transform: uppercase\\\">tion</span>\",\n          \"fontSize\": 110,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1944db3a-5915-4a89-94b4-17269f59322d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"457c0ed6-69da-43c4-ac59-1d1359d980b9\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"88dbe4e0-b177-4155-b856-23817f533121\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b0b134b8-2aae-4da8-83be-a0f5a811f082\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 200\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"3164a2b3-10c7-42b8-bcea-38292c8427f5\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"type\": \"shape\",\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0f06a768-d7d7-48c3-94fd-0d200978ef7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 567,\n          \"scale\": 180,\n          \"focalX\": 35.035015096158986,\n          \"focalY\": 48.43441973450807,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f7404703-d0bd-418d-8df5-5db492686c59\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#141513\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page4_page5_bg.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_page5_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 0,\n          \"y\": 342,\n          \"width\": 386,\n          \"height\": 216,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 250, \"g\": 244, \"b\": 234 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4496cff1-60d7-4f33-9231-9fb423308319\"\n        },\n        {\n          \"x\": 37,\n          \"y\": 384,\n          \"width\": 223,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"67f45a53-bf09-4235-95f0-680ad1bc9e66\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Getting Started</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 37,\n          \"y\": 418,\n          \"width\": 310,\n          \"height\": 120,\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1069,\n              \"des\": -293,\n              \"tAsc\": 1069,\n              \"tDes\": -293,\n              \"tLGap\": 0,\n              \"wAsc\": 1347,\n              \"wDes\": 395,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -394,\n              \"yMax\": 1347,\n              \"hAsc\": 1069,\n              \"hDes\": -293,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"id\": \"566dcf70-af92-4ee1-8a03-e07dab4556b8\",\n          \"content\": \"<span style=\\\"color: #211f1e\\\">Every deck starts with a solid foundation. There are a few ways that a foundation system for a deck can be constructed and we’ll highlight three of them: footing, pier, and pier/footing.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 37,\n          \"y\": 571,\n          \"width\": 92,\n          \"height\": 14,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"88038fd9-5e4e-41f2-a831-a79e990695ce\",\n          \"content\": \"<span style=\\\"color: #f9f3e9; letter-spacing: 0.15em; text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 14,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 129,\n          \"y\": 571,\n          \"width\": 16,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"diyRightArrow\" },\n          \"id\": \"5352f504-967c-4164-a048-c26176120773\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dcb2a902-3c03-4b69-a967-b52afdb9d469\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"67f45a53-bf09-4235-95f0-680ad1bc9e66\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 390\n        },\n        {\n          \"id\": \"3c92b85f-4082-4dae-817d-ffb112c50a64\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"566dcf70-af92-4ee1-8a03-e07dab4556b8\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"a2054244-e6cd-4b6a-a668-507fc00f63ef\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f7404703-d0bd-418d-8df5-5db492686c59\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9ca86ca1-2c59-4bd7-b6b1-b7e120c4bd89\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4496cff1-60d7-4f33-9231-9fb423308319\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"cb4d4a6b-5b3c-4513-8732-96e6e86751b2\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"0f06a768-d7d7-48c3-94fd-0d200978ef7c\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 81,\n          \"y\": 117,\n          \"width\": 193,\n          \"height\": 129,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 33.29545454545455,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#292524\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page6_bg.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"86db87f7-47d4-49e3-b714-8e28bf6c64e1\",\n          \"isBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 66,\n          \"height\": 732,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fba88016-92e6-4f7b-9f52-08c870f9ce0a\"\n        },\n        {\n          \"x\": 81,\n          \"y\": 41,\n          \"width\": 281,\n          \"height\": 439,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"id\": \"2af301c7-7cdf-4afc-bd9c-86309ec7cc80\",\n          \"content\": \"<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">Hem-fir</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">Brown</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">Stain</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">Ground</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">Contact</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">pressure-t</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">reated</span>\\n<span style=\\\"color: #f9f3e9; text-transform: uppercase\\\">lumber</span>\",\n          \"fontSize\": 55,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 5,\n          \"y\": 538,\n          \"width\": 55,\n          \"height\": 17,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"id\": \"e754bfb7-0132-4515-80c2-5c20b2b1475b\",\n          \"content\": \"<span style=\\\"color: #faf4ea; text-transform: uppercase\\\">Natural</span>\",\n          \"fontSize\": 14,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": -62.5,\n          \"y\": 355,\n          \"width\": 191,\n          \"height\": 16,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"id\": \"e3de1f4e-c47e-439b-97cd-50c779650b6d\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.001em\\\"><span style=\\\"color: rgba(250, 244, 234, 1)\\\">1.5 in. x 5.5 in. x 96 in</span></span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 307.5,\n          \"y\": 511,\n          \"width\": 55,\n          \"height\": 55,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 99, \"b\": 11 } },\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e7d91e07-214b-4718-9b8a-32f13e0e0d01\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 325,\n          \"y\": 527,\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"diyPlus\" },\n          \"id\": \"bba481a4-e128-4b73-8f1a-8ddc09609a88\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"14040395-9bd8-4d12-b201-d6c6d00dda4e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2af301c7-7cdf-4afc-bd9c-86309ec7cc80\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"bf7b9bc5-d238-4843-a80f-43473f5dcca1\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e7d91e07-214b-4718-9b8a-32f13e0e0d01\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"8f462228-45f9-459c-a091-da058c60bd62\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f903e641-0485-4da0-be58-66e0cc614467\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 12,\n          \"y\": 20,\n          \"width\": 128,\n          \"height\": 128,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d4d8e43d-57ff-401c-b525-fabfebb77af4\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 413,\n          \"height\": 554,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 58.97434159500363,\n          \"focalY\": 48.75313812608893,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6994410a-4350-4d7e-bb52-1efe7a952e3c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#c8bfb5\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page7_bg.jpg\",\n            \"width\": 330,\n            \"height\": 442,\n            \"id\": 0,\n            \"alt\": \"page7_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": -1,\n          \"y\": 344,\n          \"width\": 386,\n          \"height\": 274,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 250, \"g\": 244, \"b\": 234 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"92f6281c-d00a-4207-a95c-9a6bd40da7d9\"\n        },\n        {\n          \"x\": 37,\n          \"y\": 398,\n          \"width\": 223,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"9c0db82d-9759-4a90-8c97-3d1eb8f370e3\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">TD-1M Circular Saw</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 37,\n          \"y\": 433,\n          \"width\": 271,\n          \"height\": 144,\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1069,\n              \"des\": -293,\n              \"tAsc\": 1069,\n              \"tDes\": -293,\n              \"tLGap\": 0,\n              \"wAsc\": 1347,\n              \"wDes\": 395,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -394,\n              \"yMax\": 1347,\n              \"hAsc\": 1069,\n              \"hDes\": -293,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"id\": \"112e77ab-1cec-4679-b501-b9085d5f5d79\",\n          \"content\": \"<span style=\\\"color: #211f1e\\\">The TD-1M Cordless Circular Saw features 3,700 rpm for fast rip and cross cuts, carbide tip blade to maintain sharpness, and high strength shoe and upper guard for increased durability.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9299670e-b785-4db1-8fbd-7cf601af326a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9c0db82d-9759-4a90-8c97-3d1eb8f370e3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"3eeff24c-aae6-43cf-879b-6aba105a6408\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"112e77ab-1cec-4679-b501-b9085d5f5d79\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"669c1986-7470-4736-aec7-db0fa19e93d3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6994410a-4350-4d7e-bb52-1efe7a952e3c\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dd0f09ff-d555-4117-a2e6-330198d20f4a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"92f6281c-d00a-4207-a95c-9a6bd40da7d9\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"eb4fdaf0-52c9-46bb-acb7-91408e671880\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"defaultBackgroundElement\": {\n        \"x\": 12,\n        \"y\": 20,\n        \"width\": 128,\n        \"height\": 128,\n        \"type\": \"shape\",\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"id\": \"d4d8e43d-57ff-401c-b525-fabfebb77af4\",\n        \"isDefaultBackground\": true\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4ee0756d-c9b1-4914-a3cf-e0b41a442367\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 2,\n          \"y\": -57,\n          \"width\": 372,\n          \"height\": 612,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 250, \"g\": 244, \"b\": 234 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4b5a41ea-1f3c-4f52-8ee7-6e314d66e9f2\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 6,\n          \"width\": 258,\n          \"height\": 130,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"5fe94c96-3a59-4b24-bb76-1a2a24795c23\",\n          \"content\": \"<span style=\\\"color: #ff630b; text-transform: uppercase\\\">The best tools</span>\\n<span style=\\\"color: #211f1e; text-transform: uppercase\\\">for your DIY</span>\\n<span style=\\\"color: #211f1e; text-transform: uppercase\\\">project.</span>\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 299,\n          \"width\": 99,\n          \"height\": 99,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 140,\n          \"focalX\": 35.38461608058604,\n          \"focalY\": 57.751613096774726,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#8d7565\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page8_image2.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"ad72e216-61e5-474b-b187-9f06a613a4d5\",\n          \"groupId\": \"d1387b40-30ae-4a2c-ab0c-856cdfc7be3f\"\n        },\n        {\n          \"x\": 192,\n          \"y\": 337,\n          \"width\": 112,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"bc9330a4-a5c1-4711-842c-9f6c2a577bd0\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Jet Screws</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d1387b40-30ae-4a2c-ab0c-856cdfc7be3f\"\n        },\n        {\n          \"x\": 168,\n          \"y\": 337,\n          \"width\": 26,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"db606b2b-1199-4a93-885e-8e1be559c256\",\n          \"content\": \"<span style=\\\"color: #ff630b\\\">2.</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d1387b40-30ae-4a2c-ab0c-856cdfc7be3f\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 434,\n          \"width\": 99,\n          \"height\": 99,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 39.50000049999998,\n          \"focalY\": 50.15873173847311,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"33d1b36e-8dae-4501-b295-05b68654e8dd\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#3b3635\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page8_image3.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"aa00d502-7b6c-4fc7-a420-ca3748f8a6f7\"\n        },\n        {\n          \"x\": 192,\n          \"y\": 473,\n          \"width\": 120,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"b29b6af7-1fd0-4f84-a9c5-8e33c4623865\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Clamp Meter</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"aa00d502-7b6c-4fc7-a420-ca3748f8a6f7\"\n        },\n        {\n          \"x\": 168,\n          \"y\": 473,\n          \"width\": 26,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"7b1484d1-e0d5-4d8c-8c03-d28ecf193b4f\",\n          \"content\": \"<span style=\\\"color: #ff630b\\\">3.</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"aa00d502-7b6c-4fc7-a420-ca3748f8a6f7\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 164,\n          \"width\": 99,\n          \"height\": 99,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 120,\n          \"focalX\": 56.06481452601413,\n          \"focalY\": 57.85714248299318,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ae3014b3-9828-4285-991d-4b0aa1fc83a6\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#a29594\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page8_image1.jpg\",\n            \"width\": 220,\n            \"height\": 131,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"afa5baf1-7022-402d-8528-f9eded74849c\"\n        },\n        {\n          \"x\": 192,\n          \"y\": 193,\n          \"width\": 110,\n          \"height\": 43,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"ac28f1fa-0509-49e2-82d2-4607c9e2cc23\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Cordless</span>\\n<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Power Drill</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"afa5baf1-7022-402d-8528-f9eded74849c\"\n        },\n        {\n          \"x\": 168,\n          \"y\": 193,\n          \"width\": 26,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"9b59aecd-69c2-45c3-8f8e-b12aa586e99b\",\n          \"content\": \"<span style=\\\"color: #ff630b\\\">1.</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"afa5baf1-7022-402d-8528-f9eded74849c\"\n        },\n        {\n          \"x\": 45,\n          \"y\": 578.5,\n          \"width\": 148,\n          \"height\": 14,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"1f552208-c803-40aa-8eaf-8c7356196a87\",\n          \"content\": \"<span style=\\\"color: #faf4ea; letter-spacing: 0.15em; text-transform: uppercase\\\">View All Products</span>\",\n          \"fontSize\": 14,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 188,\n          \"y\": 577,\n          \"width\": 16,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"diyRightArrow\" },\n          \"id\": \"9c424d4b-b135-429e-b880-2815f72a4093\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e90c415c-a655-4a33-9111-f69c6ed9508b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4b5a41ea-1f3c-4f52-8ee7-6e314d66e9f2\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8519830d-3ea3-4466-bcc4-7fdfb86c0b06\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ae3014b3-9828-4285-991d-4b0aa1fc83a6\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"e5f38178-253d-44a0-aaf5-30ae4abef6a7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ac28f1fa-0509-49e2-82d2-4607c9e2cc23\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"2caa17e2-0ec9-48b6-86b3-14992db0a195\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9b59aecd-69c2-45c3-8f8e-b12aa586e99b\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"1937794a-314f-4af7-a8dc-4f169e9e79e0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5fe94c96-3a59-4b24-bb76-1a2a24795c23\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"feeb2116-c698-4bd7-a435-543c179190b8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ad72e216-61e5-474b-b187-9f06a613a4d5\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"6c9074bc-426c-42d3-b025-4aae1dfdf62e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"db606b2b-1199-4a93-885e-8e1be559c256\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"18d82024-7668-4f43-8f52-118660ea91b7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bc9330a4-a5c1-4711-842c-9f6c2a577bd0\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"61aa1861-e04e-4c6d-8434-45c63bcfa08f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"33d1b36e-8dae-4501-b295-05b68654e8dd\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"099db14b-0309-4802-b03a-26132d738e5b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7b1484d1-e0d5-4d8c-8c03-d28ecf193b4f\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"ee27b3c0-1a23-4749-b76d-9c0d8a543f29\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b29b6af7-1fd0-4f84-a9c5-8e33c4623865\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 300\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"7dc22ed5-579e-4988-9f9c-97b2cd2ff068\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"afa5baf1-7022-402d-8528-f9eded74849c\": {\n          \"name\": \"Drill\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d1387b40-30ae-4a2c-ab0c-856cdfc7be3f\": {\n          \"name\": \"Screws\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aa00d502-7b6c-4fc7-a420-ca3748f8a6f7\": {\n          \"name\": \"Meter\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 81,\n          \"y\": 187,\n          \"width\": 330,\n          \"height\": 442,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 47.18877202262253,\n          \"focalY\": 49.953358674938045,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-22T16:42:02\",\n            \"baseColor\": \"#c8bfb5\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page7_bg.jpg\",\n            \"width\": 330,\n            \"height\": 442,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"1b7b64ba-ee71-4edf-be38-d30753ac39ef\",\n          \"isBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 372,\n          \"height\": 181,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 250, \"g\": 244, \"b\": 234 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d38b12e9-ba7a-4a62-9e65-b03305beae30\"\n        },\n        {\n          \"x\": 61,\n          \"y\": 22,\n          \"width\": 277,\n          \"height\": 87,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"7b86d9a0-7674-4172-8abb-ddd27f241376\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">The Right Tools </span><span style=\\\"color: #ff630b; text-transform: uppercase\\\">For The Job.</span>\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 282,\n          \"y\": 253,\n          \"width\": 56,\n          \"height\": 56,\n          \"sticker\": { \"type\": \"diyOrangeDot\" },\n          \"id\": \"7ad8800a-9b13-4856-b5b9-52ecf10388ef\",\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 56,\n          \"height\": 56,\n          \"sticker\": { \"type\": \"diyOrangeDot\" },\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          },\n          \"id\": \"13b9e040-b2f7-4376-ab05-2e790ac4f906\",\n          \"x\": 99,\n          \"y\": 438\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 56,\n          \"height\": 56,\n          \"sticker\": { \"type\": \"diyOrangeDot\" },\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          },\n          \"id\": \"ed0b7813-6d43-4e9e-9818-d9f8b52e178f\",\n          \"x\": 81,\n          \"y\": 240\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"054bb91f-0bf5-49b2-8cfa-21261d675868\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7b86d9a0-7674-4172-8abb-ddd27f241376\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 800,\n          \"delay\": 650\n        },\n        {\n          \"id\": \"7af6017c-f9c9-4d3d-9762-d8254586954d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d38b12e9-ba7a-4a62-9e65-b03305beae30\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"d25a2dd8-b784-4818-81d3-cc70a6aad6ab\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e982349a-5439-458d-937e-5a72701cfbad\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 31, \"b\": 30, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"82dea0d1-dbc5-41e5-9ed7-409bcb672830\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -62,\n          \"width\": 372,\n          \"height\": 612,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 250, \"g\": 244, \"b\": 234 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f92aa000-0cfa-40ea-a9dd-dfee946477ab\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 14,\n          \"width\": 142,\n          \"height\": 87,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"3d4ecfbb-db87-4575-95f3-ad04b65645c9\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">More</span>\\n<span style=\\\"color: #ff630b; text-transform: uppercase\\\">Stories</span><span style=\\\"color: #ff7224\\\">.</span>\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 174,\n          \"y\": 157,\n          \"width\": 186,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"57cb521c-1572-490b-96aa-daa9ae4b45a9\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Kitchen Remodeling</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"050c8b2d-c0e3-48bd-95eb-89050f977637\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"type\": \"image\",\n          \"x\": 49,\n          \"y\": 139,\n          \"width\": 99,\n          \"height\": 99,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"261f4295-b4c7-40b3-8195-53181ea2380b\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-22T17:12:23\",\n            \"baseColor\": \"#eee1e3\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page10_image1.jpg\",\n            \"width\": 330,\n            \"height\": 235,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"050c8b2d-c0e3-48bd-95eb-89050f977637\"\n        },\n        {\n          \"x\": 173,\n          \"y\": 183,\n          \"width\": 184,\n          \"height\": 48,\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1069,\n              \"des\": -293,\n              \"tAsc\": 1069,\n              \"tDes\": -293,\n              \"tLGap\": 0,\n              \"wAsc\": 1347,\n              \"wDes\": 395,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -394,\n              \"yMax\": 1347,\n              \"hAsc\": 1069,\n              \"hDes\": -293,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"id\": \"e68025e7-bea3-47fc-ba92-466cdd5fbaf5\",\n          \"content\": \"<span style=\\\"color: #211f1e\\\">Learn how to remodel your kitchen in 10 steps</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"050c8b2d-c0e3-48bd-95eb-89050f977637\"\n        },\n        {\n          \"width\": 186,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">The Right Tools</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"bf4d94b8-f717-4ed1-a09d-f0d4cb4f7801\",\n          \"x\": 173,\n          \"y\": 291,\n          \"groupId\": \"5fb50c20-881b-458f-8e35-220d75eec380\"\n        },\n        {\n          \"width\": 176,\n          \"height\": 48,\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1069,\n              \"des\": -293,\n              \"tAsc\": 1069,\n              \"tDes\": -293,\n              \"tLGap\": 0,\n              \"wAsc\": 1347,\n              \"wDes\": 395,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -394,\n              \"yMax\": 1347,\n              \"hAsc\": 1069,\n              \"hDes\": -293,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"content\": \"<span style=\\\"color: #211f1e\\\">Finding the right tools for every home project</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"9a04e762-70f6-45bb-b265-a78a04253b5c\",\n          \"x\": 173,\n          \"y\": 318,\n          \"groupId\": \"5fb50c20-881b-458f-8e35-220d75eec380\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"type\": \"image\",\n          \"width\": 99,\n          \"height\": 99,\n          \"scale\": 130,\n          \"focalX\": 61.70024257061352,\n          \"focalY\": 62.66451151162751,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"222b994c-3782-4970-8a0c-05bdc0c78cb8\",\n          \"x\": 49,\n          \"y\": 276,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-22T17:12:21\",\n            \"baseColor\": \"#303944\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page10_image2.jpg\",\n            \"width\": 330,\n            \"height\": 498,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"5fb50c20-881b-458f-8e35-220d75eec380\"\n        },\n        {\n          \"width\": 186,\n          \"height\": 22,\n          \"font\": {\n            \"family\": \"Anton\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2409,\n              \"des\": -674,\n              \"tAsc\": 2409,\n              \"tDes\": -674,\n              \"tLGap\": 0,\n              \"wAsc\": 2876,\n              \"wDes\": 674,\n              \"xH\": 1500,\n              \"capH\": 1760,\n              \"yMin\": -667,\n              \"yMax\": 2874,\n              \"hAsc\": 2409,\n              \"hDes\": -674,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"content\": \"<span style=\\\"color: #211f1e; text-transform: uppercase\\\">Cabinetry</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"aa346ca1-cce7-4e30-b0e3-7f11462bf2e4\",\n          \"x\": 172,\n          \"y\": 425,\n          \"groupId\": \"a2c0faaa-75f1-47ff-9b52-b04a1e356546\"\n        },\n        {\n          \"width\": 151,\n          \"height\": 48,\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1069,\n              \"des\": -293,\n              \"tAsc\": 1069,\n              \"tDes\": -293,\n              \"tLGap\": 0,\n              \"wAsc\": 1347,\n              \"wDes\": 395,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -394,\n              \"yMax\": 1347,\n              \"hAsc\": 1069,\n              \"hDes\": -293,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"content\": \"<span style=\\\"color: #211f1e\\\">Learn the basics of cabinetry</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"221fddb4-180f-4239-bb83-76d6e25bd38c\",\n          \"x\": 172,\n          \"y\": 452,\n          \"groupId\": \"a2c0faaa-75f1-47ff-9b52-b04a1e356546\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"type\": \"image\",\n          \"width\": 99,\n          \"height\": 99,\n          \"scale\": 130,\n          \"focalX\": 50,\n          \"focalY\": 38.41341111589627,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dfe5ba2a-fbb4-4739-b42c-b28b28fe3e44\",\n          \"x\": 50,\n          \"y\": 413,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-22T17:12:19\",\n            \"baseColor\": \"#e3dcdc\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/doers-get-more-done/page10_image3.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"a2c0faaa-75f1-47ff-9b52-b04a1e356546\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 59,\n          \"y\": 571,\n          \"width\": 26,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"diyTwitterIcon\" },\n          \"id\": \"b3313c8a-776c-44f2-a3ee-fd4d27cc74f1\",\n          \"groupId\": \"2e7050a7-3bca-4d6b-8987-1751cd315d59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 148,\n          \"y\": 571,\n          \"width\": 27,\n          \"height\": 18,\n          \"sticker\": { \"type\": \"diyYouTubeIcon\" },\n          \"id\": \"06861f8b-4684-4204-8500-892a85c70abc\",\n          \"groupId\": \"2e7050a7-3bca-4d6b-8987-1751cd315d59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 235,\n          \"y\": 569,\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"diyInstagramIcon\" },\n          \"id\": \"e69ad458-2707-41ac-91d4-99aa820a211c\",\n          \"groupId\": \"2e7050a7-3bca-4d6b-8987-1751cd315d59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 317,\n          \"y\": 568,\n          \"width\": 13,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"diyFacebookIcon\" },\n          \"id\": \"7427d556-c992-447b-9c66-222ba6224d25\",\n          \"groupId\": \"2e7050a7-3bca-4d6b-8987-1751cd315d59\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0b51f17f-3fd6-4ece-a2ae-88e0cc847743\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3d4ecfbb-db87-4575-95f3-ad04b65645c9\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"3ffc8efb-3b09-4bbc-8249-34c17ae98718\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"261f4295-b4c7-40b3-8195-53181ea2380b\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"3d82c6f8-b868-4f14-a768-85ff39ea664d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"57cb521c-1572-490b-96aa-daa9ae4b45a9\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"1c919eab-f74e-4e53-b876-1467ae231fed\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e68025e7-bea3-47fc-ba92-466cdd5fbaf5\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"0ead1aac-3f85-433a-98e4-d07176cd2ed4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bf4d94b8-f717-4ed1-a09d-f0d4cb4f7801\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"0096585f-4fbb-4291-9a73-3d6221484136\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9a04e762-70f6-45bb-b265-a78a04253b5c\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"00df9efb-ed13-44b6-81d3-a0dc63c29df8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"222b994c-3782-4970-8a0c-05bdc0c78cb8\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"17815df7-0efb-4202-9989-48b922103dd2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"aa346ca1-cce7-4e30-b0e3-7f11462bf2e4\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"11f4533f-dec8-4377-a6aa-e5470d01d527\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"221fddb4-180f-4239-bb83-76d6e25bd38c\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"a9644d0b-05d9-422d-a323-fa3d3f304c76\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dfe5ba2a-fbb4-4739-b42c-b28b28fe3e44\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"ac758432-e1e9-4ec1-93e1-7a128f06c463\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f92aa000-0cfa-40ea-a9dd-dfee946477ab\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"5c295574-87a0-4ae7-b548-699e0bd47fdf\",\n      \"backgroundColor\": { \"color\": { \"r\": 53, \"g\": 51, \"b\": 50 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"050c8b2d-c0e3-48bd-95eb-89050f977637\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"5fb50c20-881b-458f-8e35-220d75eec380\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a2c0faaa-75f1-47ff-9b52-b04a1e356546\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2e7050a7-3bca-4d6b-8987-1751cd315d59\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/elegant-travel-itinerary/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/elegant-travel-itinerary/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'elegant-travel-itinerary',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Elegant Travel Itinerary', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Trip', 'template keyword', 'web-stories'),\n    _x('Heritage', 'template keyword', 'web-stories'),\n    _x('Frame', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Night Blue', 'color', 'web-stories'),\n      color: '#151c23',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Porcelain White', 'color', 'web-stories'),\n      color: '#eef0f2',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Aztec Gold', 'color', 'web-stories'),\n      color: '#c89d4f',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Bright Sky Blue', 'color', 'web-stories'),\n      color: '#61a0ff',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s ornate shapes and design elements inspired by olden architecture will let you travel stories that are beautiful and elegant. Create reviews, tour guides and itineraries for cultural and heritage tourism, luxury travel and more.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/elegant-travel-itinerary/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/elegant-travel-itinerary/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5adeeccf-0687-4d46-9640-0be8e9ba4857\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#2f353b\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page01_image01.jpg\",\n            \"width\": 636,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Locomotive engine\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 208,\n          \"width\": 412,\n          \"height\": 467,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8eb648a6-165f-4e84-9824-2ee5cbe9c153\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 155.5,\n          \"y\": 5,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"dc7e3e81-8767-4749-8e04-e32eed42fa2e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #eef0f2\\\">The Venice Simplon Orient Express</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 44,\n          \"y\": 63,\n          \"width\": 324,\n          \"height\": 86,\n          \"id\": \"488359ff-1e82-46b4-a74b-1b6593450c80\",\n          \"marginOffset\": -38.564\n        },\n        {\n          \"x\": 44,\n          \"y\": 151,\n          \"id\": \"3b0d63b8-6a9d-420a-a172-c7ec19ca3754\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.15em; text-transform: uppercase\\\">By John Doe 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 20,\n          \"marginOffset\": -38.564\n        },\n        {\n          \"x\": 44,\n          \"y\": 32,\n          \"id\": \"bded7bda-df15-412c-9d0a-e27415cd0412\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.3em; text-transform: uppercase\\\">All aboard</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 19,\n          \"marginOffset\": -38.564\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"32902389-0b53-4c6f-84db-96cfab05c0fc\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -82.5,\n          \"y\": -113,\n          \"width\": 577,\n          \"height\": 1026,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"11557cfe-99ad-45cc-839a-9bce5a5d577d\",\n          \"scale\": 137,\n          \"focalX\": 50,\n          \"focalY\": 40.501358244857336,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page02_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Train on bridge surrounded with trees at daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#363830\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"48c07057-0d09-471a-92dc-024a666d8523\"\n        },\n        {\n          \"x\": -6.5,\n          \"y\": -57,\n          \"id\": \"ce6dcc37-b3f6-4549-952a-0799856a433d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.46 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 425,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Looking to travel from Venice to </span><span style=\\\"color: #fff\\\">London</span><span style=\\\"font-weight: 300; color: #fff\\\">?&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 79,\n          \"y\": 30,\n          \"width\": 254,\n          \"height\": 54,\n          \"id\": \"fe083ef7-9105-4ca3-9872-3f6fa2c365aa\",\n          \"marginOffset\": -8.694000000000003\n        },\n        {\n          \"x\": 71,\n          \"y\": 102,\n          \"id\": \"57b4bac8-9f59-4564-b55c-2e7dadc21038\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Enter the most authentic, vintage, and luxury way to ride</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">by train.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 271,\n          \"height\": 75,\n          \"marginOffset\": -8.694000000000003\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"49d5bca3-ef73-44ef-881c-80174f984a96\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"11557cfe-99ad-45cc-839a-9bce5a5d577d\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7de94e75-e022-4ab7-839a-8198df60a9e7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"57b4bac8-9f59-4564-b55c-2e7dadc21038\"],\n          \"duration\": 1000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"ddf0fc23-e2d3-42b2-ab59-d8ec5e459892\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fe083ef7-9105-4ca3-9872-3f6fa2c365aa\"],\n          \"duration\": 1000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"25c8be74-ee08-4dde-a86e-da4f7efc259c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c5b1370c-eed7-4e22-ab5f-922678b7fefc\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0cfe6335-e35b-41b4-b1e5-127c3d4e8174\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Fine dining inside train\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dae1df\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 } },\n          \"type\": \"shape\",\n          \"width\": 429,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fb17e1a1-01c2-464a-806a-56c270d99ed4\",\n          \"x\": -8.5,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 21,\n          \"y\": -33.5,\n          \"width\": 370,\n          \"height\": 685,\n          \"sticker\": { \"type\": \"elegantTravelFloralFrame\" },\n          \"id\": \"9f8b83fe-87ff-4307-adb1-d229544d8b5f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">A perfectly restored, vintage train from the Golden Era </span>\\n<span style=\\\"color: #fff\\\">of travel.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 82,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"cb1d1884-6f57-464c-a6c9-f126faba3c28\",\n          \"x\": 71,\n          \"y\": 498\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"513e2d13-f8a5-48e8-a9d0-a08c11f7df54\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"0cfe6335-e35b-41b4-b1e5-127c3d4e8174\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8f08102e-3336-469b-9e72-bfb0ec1f1896\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9f8b83fe-87ff-4307-adb1-d229544d8b5f\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fba50a93-0a9a-400a-80fb-30a7a75ca6bc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cb1d1884-6f57-464c-a6c9-f126faba3c28\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"44a6850f-bfb3-4a61-b681-8825f8b87f8b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"eaecdbda-5112-40eb-8ccd-22c211c8c6d3\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"40524471-e9c6-464f-ba3f-6546de285418\",\n          \"scale\": 111,\n          \"focalX\": 55.01126126126127,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Gray table lamp beside white bed pillow\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1b262c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.35 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 429,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"393b366e-6c83-4322-bcaf-6fc63963d7d9\",\n          \"x\": -8.5,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Handmade textiles from the south of </span><span style=\\\"font-style: italic; color: #fff\\\">France</span><span style=\\\"color: #fff\\\">.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 222,\n          \"height\": 54,\n          \"marginOffset\": -5.796000000000003,\n          \"id\": \"13be2b01-1780-4c97-adb5-e92d52f5592a\",\n          \"x\": 95,\n          \"y\": 46\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"d1cd8a15-46b8-4f85-bb94-079d0a939fbe\",\n          \"x\": 155.5,\n          \"y\": 5\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"142a7fb3-7381-49a7-899a-5bc94b952a2d\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"40524471-e9c6-464f-ba3f-6546de285418\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0d865475-9baa-4044-92fa-69f68f2a4bc0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"03b8981e-4819-43c1-92da-f3a4af6adbad\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"230d95d0-e71c-4760-a7ac-30f9a8f8f363\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page05_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Clear glass bowls on table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c3a27d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.34 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 429,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0664c49a-0c52-457d-868f-e6b1f2ffa5fc\",\n          \"x\": -8.5,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Blown glass from </span>\\n<span style=\\\"color: #fff\\\">the canals of </span><span style=\\\"font-style: italic; color: #fff\\\">Venice</span><span style=\\\"color: #fff\\\">.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 248,\n          \"height\": 54,\n          \"marginOffset\": -5.796000000000003,\n          \"id\": \"b1bd827b-1c84-49b9-8b58-627cbfc20743\",\n          \"x\": 82,\n          \"y\": 571,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"cef81440-c106-46e8-8329-3d9a9093b7c2\",\n          \"x\": 155.5,\n          \"y\": 530,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9e2de28d-a2ea-48f2-9d1a-6bf7335abe88\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"230d95d0-e71c-4760-a7ac-30f9a8f8f363\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b19c77b3-b7f9-4cc7-97bf-150d8c86f8bb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"5dac7052-e417-438d-b377-c0b54be04633\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"30612af7-a936-4ba7-b223-da3a229270a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page06_bg.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Map of Europe highlighting London, Paris and Venice\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c6a5b94a-affa-4368-a2c4-cfb81c0f811f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"type\": \"sticker\",\n          \"id\": \"c32ec50e-daf1-4e8b-a1c5-5bf795878f99\",\n          \"x\": 155.5,\n          \"y\": 5,\n          \"groupId\": \"804859cc-4d6d-4587-abb9-2eb61803b774\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Depart Venice for a romantic journey to London.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 54,\n          \"marginOffset\": -7.084000000000003,\n          \"type\": \"text\",\n          \"id\": \"6f21120f-99c0-43b0-9864-e5d0c7f0cd40\",\n          \"x\": 74,\n          \"y\": 46,\n          \"groupId\": \"804859cc-4d6d-4587-abb9-2eb61803b774\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page06_image01.png\",\n            \"width\": 224,\n            \"height\": 160,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dotted weavy line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 101.5,\n          \"y\": 224,\n          \"width\": 224,\n          \"height\": 167,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3bf10ebf-b810-4ffa-85fd-3204f1a12de2\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } },\n          \"type\": \"shape\",\n          \"x\": 317.5,\n          \"y\": 382.5,\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"1db3e8b6-0630-4e74-b6ed-977af47e128a\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"x\": 309,\n          \"y\": 374,\n          \"width\": 32,\n          \"height\": 32,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"616459a3-b2c1-4fbb-bfc4-4c4e843cb735\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } }\n          },\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 93,\n          \"y\": 223,\n          \"id\": \"578b455b-7be6-4be7-89b9-21b623e02f13\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 138,\n          \"y\": 288,\n          \"id\": \"c2647c9f-aee5-407c-aec8-b700aa255cbf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 97, \"g\": 160, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 278,\n          \"y\": 384,\n          \"id\": \"175f9e72-686c-4223-b55b-9c75c45d5722\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 97, \"g\": 160, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 60,\n          \"y\": 197,\n          \"id\": \"af2979b7-14e5-4cd7-94d2-98bb23e6f23f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">London</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 81,\n          \"height\": 20,\n          \"marginOffset\": -3.330000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 103,\n          \"y\": 304,\n          \"id\": \"3c4361c1-2eb3-4975-9462-fa24d25cfbab\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Paris</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 81,\n          \"height\": 20,\n          \"marginOffset\": -3.330000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 192,\n          \"y\": 378,\n          \"id\": \"1e462206-8fa5-4347-83fe-420759a624d4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Verona</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 81,\n          \"height\": 20,\n          \"marginOffset\": -3.330000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"x\": 283,\n          \"y\": 411,\n          \"id\": \"bffcdd32-cc3f-4016-a873-d9fa85f4909e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Venice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 81,\n          \"height\": 20,\n          \"marginOffset\": -3.330000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"d3a38361-fd7f-4785-9bed-bff4984c46b2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 67,\n          \"y\": 526,\n          \"width\": 30,\n          \"height\": 35,\n          \"sticker\": { \"type\": \"elegantTravelTrainTracks\" },\n          \"id\": \"7fa4e0a8-8a0f-46d2-b0a0-848fbc1a3024\",\n          \"groupId\": \"719e7099-fce8-49c9-9451-821fa7d83acf\"\n        },\n        {\n          \"x\": 60,\n          \"y\": 572.5,\n          \"id\": \"ef5edc33-08cb-4749-b2b7-efbffd449e19\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em\\\">1,700</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 46,\n          \"height\": 30,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"719e7099-fce8-49c9-9451-821fa7d83acf\"\n        },\n        {\n          \"x\": 57,\n          \"y\": 603,\n          \"id\": \"a453fbe5-2310-4073-a3bf-3340bc73bda2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.5); letter-spacing: 0.1em; text-transform: uppercase\\\">Miles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 19,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"719e7099-fce8-49c9-9451-821fa7d83acf\"\n        },\n        {\n          \"x\": 177,\n          \"y\": 603,\n          \"id\": \"a31b94f8-cdfb-41d2-bb25-676b62cdde62\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.5); letter-spacing: 0.1em; text-transform: uppercase\\\">Hours</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 59,\n          \"height\": 19,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"694ef937-19e2-41f6-92d7-a8f0c002fa78\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 194,\n          \"y\": 530,\n          \"width\": 24,\n          \"height\": 30,\n          \"sticker\": { \"type\": \"elegantTravelStationClock\" },\n          \"id\": \"d1d4316e-e846-47d9-b12a-480df3d7e06f\",\n          \"groupId\": \"694ef937-19e2-41f6-92d7-a8f0c002fa78\"\n        },\n        {\n          \"x\": 184,\n          \"y\": 572.5,\n          \"id\": \"25cc0c04-b8cd-4901-af41-a6ebe7ceb0e8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em\\\">54</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 46,\n          \"height\": 30,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"694ef937-19e2-41f6-92d7-a8f0c002fa78\"\n        },\n        {\n          \"x\": 286,\n          \"y\": 603,\n          \"id\": \"d9232c45-1bbb-4e9f-b679-369826461a63\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.5); letter-spacing: 0.1em; text-transform: uppercase\\\">Bridges</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 70,\n          \"height\": 19,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"b9bed110-dde8-4901-a570-7e437e3cff5b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 301,\n          \"y\": 535,\n          \"width\": 37,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"elegantTravelBridge\" },\n          \"id\": \"16316614-0f96-44c8-a7ea-46f00114c36d\",\n          \"groupId\": \"b9bed110-dde8-4901-a570-7e437e3cff5b\"\n        },\n        {\n          \"x\": 298,\n          \"y\": 572.5,\n          \"id\": \"57766d0f-00b2-498c-8d8c-abe7bbe336a7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em\\\">12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 46,\n          \"height\": 30,\n          \"marginOffset\": -6.263999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"b9bed110-dde8-4901-a570-7e437e3cff5b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"544f8516-1aad-4183-884a-1e5c1d571a3d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3bf10ebf-b810-4ffa-85fd-3204f1a12de2\"],\n          \"duration\": 1000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"2aad6ee8-7caf-448b-8273-c64493c5b486\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"af2979b7-14e5-4cd7-94d2-98bb23e6f23f\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"c664a214-a5c1-4771-82b5-48eb6304864f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"578b455b-7be6-4be7-89b9-21b623e02f13\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"b031ded3-0ab8-4fcf-9bd6-72b3692ef4d7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c2647c9f-aee5-407c-aec8-b700aa255cbf\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"c42babd7-aff8-40a6-95a8-4a60a4a61510\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3c4361c1-2eb3-4975-9462-fa24d25cfbab\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"de3774fe-b541-4133-a0c3-59c1e2f8054e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1e462206-8fa5-4347-83fe-420759a624d4\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"eece8ab9-eaaf-4854-991e-60fd591d2c39\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"175f9e72-686c-4223-b55b-9c75c45d5722\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"9f949cdd-dba3-4c0c-91e7-1bbb5e64ff7e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bffcdd32-cc3f-4016-a873-d9fa85f4909e\"],\n          \"duration\": 2000,\n          \"delay\": 2000\n        },\n        {\n          \"id\": \"876c7d63-f3c4-477d-8de5-c672bf168656\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1db3e8b6-0630-4e74-b6ed-977af47e128a\"],\n          \"duration\": 2000,\n          \"delay\": 2000\n        },\n        {\n          \"id\": \"0eb88713-bb62-4116-a5b5-33eb22328e5a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"616459a3-b2c1-4fbb-bfc4-4c4e843cb735\"],\n          \"duration\": 2000,\n          \"delay\": 2000\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"895018dc-c155-412b-9ad2-600fe543ca1f\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"719e7099-fce8-49c9-9451-821fa7d83acf\": {\n          \"name\": \"Miles\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"694ef937-19e2-41f6-92d7-a8f0c002fa78\": {\n          \"name\": \"Hours\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b9bed110-dde8-4901-a570-7e437e3cff5b\": {\n          \"name\": \"Bridges\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d3a38361-fd7f-4785-9bed-bff4984c46b2\": {\n          \"name\": \"Trip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"804859cc-4d6d-4587-abb9-2eb61803b774\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"43be9212-e84d-4155-8982-5a216076faab\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page07_image01.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"A map of somewhere in Europe\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5530c714-1be3-4dd2-971b-a1628c40617d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page07_image02.jpg\",\n            \"width\": 717,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Aerial view of village on mountain cliff during orange sunset\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3a363f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 261,\n          \"width\": 412,\n          \"height\": 414,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"033b38aa-fef7-40bb-b088-4c18e373c74e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"af8a748a-23cc-4c37-b1cb-4efe601071d2\",\n          \"x\": 155.5,\n          \"y\": 5,\n          \"type\": \"sticker\",\n          \"groupId\": \"42be86c1-e433-4aa8-84f9-b5eea0f50bcc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">The first stop</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 30,\n          \"marginOffset\": -7.084000000000003,\n          \"id\": \"7614ccd1-001c-43fb-bd04-75e6be01fcd2\",\n          \"x\": 74,\n          \"y\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"42be86c1-e433-4aa8-84f9-b5eea0f50bcc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:29:58\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page07_image03.png\",\n            \"width\": 344,\n            \"height\": 272,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dotted line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 336,\n          \"height\": 265,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"64eb7718-13b6-4d4f-99b0-2f59e3712389\",\n          \"groupId\": \"956b5d4f-bf98-4b64-b7f9-9d9d5340a8b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } },\n          \"x\": 191,\n          \"y\": 177.5,\n          \"width\": 23,\n          \"height\": 23,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"66b385e8-ea99-4828-88c5-8188a00653ae\",\n          \"type\": \"shape\",\n          \"groupId\": \"956b5d4f-bf98-4b64-b7f9-9d9d5340a8b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": 179,\n          \"y\": 165.5,\n          \"width\": 47,\n          \"height\": 47,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"404808f4-8428-4cee-9f78-85047e7d127e\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"956b5d4f-bf98-4b64-b7f9-9d9d5340a8b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 97, \"g\": 160, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"4586c430-8745-4edb-9997-55e6dab9bc7b\",\n          \"x\": 273,\n          \"y\": 158,\n          \"groupId\": \"956b5d4f-bf98-4b64-b7f9-9d9d5340a8b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 222,\n          \"id\": \"c5150c32-105e-422a-b52e-8f5765129ccb\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Verona</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 91,\n          \"marginOffset\": -38.85000000000002,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4920e3cd-83a3-4fc9-9b12-ad9a1cd4912f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"404808f4-8428-4cee-9f78-85047e7d127e\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1ade76a0-0425-414b-86f8-a676ddf9c043\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"66b385e8-ea99-4828-88c5-8188a00653ae\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7e24790b-9d5d-4d1f-8caf-5528a3af20a9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c5150c32-105e-422a-b52e-8f5765129ccb\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"229ff8e6-51f4-41e7-b24d-2b4a60667265\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"956b5d4f-bf98-4b64-b7f9-9d9d5340a8b1\": {\n          \"name\": \"Trip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"42be86c1-e433-4aa8-84f9-b5eea0f50bcc\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -273,\n          \"y\": -687,\n          \"width\": 768,\n          \"height\": 1369,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"1dbfb013-3428-426f-8d9e-84bc80f2a7cb\",\n          \"type\": \"image\",\n          \"scale\": 177,\n          \"focalX\": 62.40122701768692,\n          \"focalY\": 71.66755081435382,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"House surrounded by plants and grass field\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dbbcaa\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.34 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 425,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"feb47bf8-9265-4aef-aeaf-f1096d9e13f9\",\n          \"x\": -6.5,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Visit famed Winery Menegolli, near Verona.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 248,\n          \"height\": 54,\n          \"marginOffset\": -5.796000000000003,\n          \"id\": \"7691274f-25dd-49d7-907e-663e7835f375\",\n          \"x\": 82,\n          \"y\": 571,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"fc8dc765-5609-4f22-8fae-b8d6bedc097e\",\n          \"x\": 155.5,\n          \"y\": 530,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"00e61c1f-aa53-4165-b669-3d13c57ef0cb\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"1dbfb013-3428-426f-8d9e-84bc80f2a7cb\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 6000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"3b9473d5-50fe-4bcd-a4a3-0b67b606ab73\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f655e45a-6f83-443a-b822-e10e999265f8\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2f6a16b5-146d-4dca-b08c-3efddb1d04b8\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page09_image01.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Map of Paris illustration\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -53,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"858b7989-ff99-4807-b5d0-aae03c8fe4e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page09_image02.jpg\",\n            \"width\": 720,\n            \"height\": 689,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Bridge during night time\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9281a1\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -10,\n          \"y\": 262,\n          \"width\": 432,\n          \"height\": 413,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"52ca5c29-c3bd-4f0c-ad89-b56cade14b2b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"05780628-ce8e-4949-914a-228286aad847\",\n          \"x\": 155.5,\n          \"y\": 5,\n          \"type\": \"sticker\",\n          \"groupId\": \"41f7b790-df82-4456-b8bb-2398f318959f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">The next stop</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 30,\n          \"marginOffset\": -7.084000000000003,\n          \"id\": \"88b09b12-96c3-49f4-856b-83ade487bb96\",\n          \"x\": 74,\n          \"y\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"41f7b790-df82-4456-b8bb-2398f318959f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page09_image03.png\",\n            \"width\": 412,\n            \"height\": 454,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dotted line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -21,\n          \"width\": 413,\n          \"height\": 394,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6d77678e-af6c-4dd9-bf25-8be73fc6ca20\",\n          \"groupId\": \"7f1ba731-3cd2-4f3a-a787-59f979699fdf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } },\n          \"x\": 191,\n          \"y\": 177.5,\n          \"width\": 23,\n          \"height\": 23,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"5dc3d148-55e9-4d7e-8fe6-c01ce534d1a0\",\n          \"type\": \"shape\",\n          \"groupId\": \"7f1ba731-3cd2-4f3a-a787-59f979699fdf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": 179,\n          \"y\": 165.5,\n          \"width\": 47,\n          \"height\": 47,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ea35379d-b144-46ad-a16f-f84d1f9431cd\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"7f1ba731-3cd2-4f3a-a787-59f979699fdf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 97, \"g\": 160, \"b\": 255 } },\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"2821aed5-b46a-472c-b321-960674119b05\",\n          \"x\": 314,\n          \"y\": 220,\n          \"type\": \"shape\",\n          \"groupId\": \"7f1ba731-3cd2-4f3a-a787-59f979699fdf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 225,\n          \"id\": \"c95c19dd-06f0-4b66-b568-34ec541dfaab\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Paris</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 91,\n          \"marginOffset\": -38.85000000000002,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d7bb42a5-a427-484e-a1da-e01855edfc21\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"ea35379d-b144-46ad-a16f-f84d1f9431cd\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b50667ec-f346-4043-97da-64e6d2b8f0f5\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"5dc3d148-55e9-4d7e-8fe6-c01ce534d1a0\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e09015ae-8c21-413f-8e24-f59bca268e92\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c95c19dd-06f0-4b66-b568-34ec541dfaab\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"713e70f1-286c-4b56-834f-a54399866785\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7f1ba731-3cd2-4f3a-a787-59f979699fdf\": {\n          \"name\": \"Trip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"41f7b790-df82-4456-b8bb-2398f318959f\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a2fd292d-a94c-469b-aeec-b9d960d09f3a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"aa33c666-ce57-463a-aa9b-7fddd50a4afb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page10_image01.jpg\",\n            \"width\": 630,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Armchair Books store\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#586364\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 471,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"944f6665-42ee-4eb7-ac01-30ada5211a5b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 108.38663423092481,\n          \"focalX\": 50,\n          \"focalY\": 72.83611525783694,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page10_image02.png\",\n            \"width\": 1080,\n            \"height\": 838,\n            \"id\": 0,\n            \"alt\": \"Illustration of city lanes in a map\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#141c24\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -207,\n          \"y\": 425,\n          \"width\": 1000,\n          \"height\": 457,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"64f6fe2a-cab3-4108-949a-07e62426a256\",\n          \"resizeWidth\": 466.01942,\n          \"resizeHeight\": 212.92200000000003\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } },\n          \"x\": 198,\n          \"y\": 471,\n          \"width\": 23,\n          \"height\": 23,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e312a53b-c58d-480d-af3c-39c1be6d7b0a\",\n          \"type\": \"shape\",\n          \"groupId\": \"14d55607-e623-4274-ab8c-70f404dd2002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": 186,\n          \"y\": 459,\n          \"width\": 47,\n          \"height\": 47,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6c1cd852-d976-465d-87a5-0c95b3adc67b\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"14d55607-e623-4274-ab8c-70f404dd2002\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">12 Rue de Lancry, 75010 Paris, France</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 56,\n          \"marginOffset\": -7.084000000000003,\n          \"id\": \"0b19f04e-d24a-4f9c-8b18-39af051cce2e\",\n          \"x\": 74,\n          \"y\": 517,\n          \"type\": \"text\",\n          \"groupId\": \"14d55607-e623-4274-ab8c-70f404dd2002\"\n        },\n        {\n          \"x\": -5.5,\n          \"y\": -58,\n          \"id\": \"37d7f4c5-876e-4bf7-a4d5-9964a3d98925\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 } },\n          \"type\": \"shape\",\n          \"width\": 423,\n          \"height\": 471,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 34,\n          \"y\": 380,\n          \"id\": \"637d773b-8e7e-43ea-8ffe-922a0e2cbb78\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Le Marais</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 344,\n          \"height\": 75,\n          \"marginOffset\": -38.85000000000002,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9ffd2e61-9a83-4255-9a66-a4faf8c2350c\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"6c1cd852-d976-465d-87a5-0c95b3adc67b\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d64cdc95-4034-4b45-8e74-d55f7ef96b87\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e312a53b-c58d-480d-af3c-39c1be6d7b0a\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"97dc71fd-7932-4898-9eaa-57d376348642\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"637d773b-8e7e-43ea-8ffe-922a0e2cbb78\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"2dacc2ce-a98b-4df3-aab9-c3a7e564f94b\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"14d55607-e623-4274-ab8c-70f404dd2002\": {\n          \"name\": \"Trip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"96120aaa-d6ec-483d-a82a-46d02bb9113e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page11_image01.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Plain overview map of London\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6b50c314-fa16-48a9-bd0a-710fb3160278\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page11_image02.jpg\",\n            \"width\": 720,\n            \"height\": 689,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo of Elizabeth Tower, London\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d4d3d1\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -10,\n          \"y\": 262,\n          \"width\": 432,\n          \"height\": 413,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1a563c31-7e04-42af-91ea-2c42843ea820\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } },\n          \"type\": \"shape\",\n          \"width\": 432,\n          \"height\": 413,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"379275ad-f90e-44c9-a2c6-98d411e907af\",\n          \"x\": -10,\n          \"y\": 262\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 43,\n          \"y\": 218,\n          \"id\": \"0c5dcee6-e8d1-4e16-98d0-ac1060d0d025\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">London</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 91,\n          \"marginOffset\": -38.85000000000002,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } },\n          \"x\": 191,\n          \"y\": 177.5,\n          \"width\": 23,\n          \"height\": 23,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"350fc10f-fcab-4d3d-aedf-a8da1318e19a\",\n          \"type\": \"shape\",\n          \"groupId\": \"afec97de-4d6a-4a77-aee2-ce53508d1b4a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": 179,\n          \"y\": 165.5,\n          \"width\": 47,\n          \"height\": 47,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"96d034dc-f60a-41eb-a551-1d8a09020c1d\",\n          \"borderRadius\": {\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 200, \"g\": 157, \"b\": 79 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"afec97de-4d6a-4a77-aee2-ce53508d1b4a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 97, \"g\": 160, \"b\": 255 } },\n          \"width\": 8,\n          \"height\": 8,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"8c0e631a-884b-4f45-81e2-589ac8091c1b\",\n          \"x\": 263,\n          \"y\": 234,\n          \"type\": \"shape\",\n          \"groupId\": \"afec97de-4d6a-4a77-aee2-ce53508d1b4a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 30,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page09_image03.png\",\n            \"width\": 412,\n            \"height\": 454,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dotted line\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 337,\n          \"height\": 321,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ecb9a927-2049-4022-a486-3ca6c83903c1\",\n          \"x\": 132,\n          \"y\": 190,\n          \"groupId\": \"afec97de-4d6a-4a77-aee2-ce53508d1b4a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"id\": \"0ea311b8-4133-401a-9721-ac3c574f8047\",\n          \"x\": 155.5,\n          \"y\": 5,\n          \"type\": \"sticker\",\n          \"groupId\": \"dccdb7b9-67b0-40bc-85b6-cc4e79bf9b95\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Final stop</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 30,\n          \"marginOffset\": -7.084000000000003,\n          \"id\": \"8c368da4-d6dd-4efb-96d2-057e7f10ce06\",\n          \"x\": 74,\n          \"y\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"dccdb7b9-67b0-40bc-85b6-cc4e79bf9b95\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6cecde86-7803-4160-b11c-6d72d6eaec64\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"96d034dc-f60a-41eb-a551-1d8a09020c1d\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3c621b84-f1d0-45a5-901a-9b8f688de68f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"350fc10f-fcab-4d3d-aedf-a8da1318e19a\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fb323e5a-3b15-40bf-97c3-6bf118fdf933\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0c5dcee6-e8d1-4e16-98d0-ac1060d0d025\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"58767793-d6a8-46ae-abdd-811177f4b68b\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"dccdb7b9-67b0-40bc-85b6-cc4e79bf9b95\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"afec97de-4d6a-4a77-aee2-ce53508d1b4a\": {\n          \"name\": \"Trip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9f43db5a-ba94-4636-9dcf-c531c176bb2c\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 54.356060606060616,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:30:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Beige concrete structure\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2d2727\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 } },\n          \"width\": 425,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7365ed90-3a05-479a-a85b-473fd5893619\",\n          \"x\": -6.5,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Leadenhall is a thriving Victorian covered retail centre with a wide range of goods </span>\\n<span style=\\\"color: #fff\\\">on sale.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 107,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"3082c247-35c5-4a42-8964-4a98959408d3\",\n          \"x\": 69,\n          \"y\": 307,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 21,\n          \"y\": -33.5,\n          \"width\": 370,\n          \"height\": 685,\n          \"sticker\": { \"type\": \"elegantTravelFloralFrame\" },\n          \"id\": \"c33c74bc-ddb6-4cf4-acab-baffbf6a5307\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"x\": 69,\n          \"y\": 271,\n          \"id\": \"80a7bb2e-435a-42ee-b105-51302427c2b7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Leadenhall market</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 101,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"elegantTravelFloralSeparator\" },\n          \"type\": \"sticker\",\n          \"id\": \"3c4487b8-925d-4a70-8cc1-6af849d71a87\",\n          \"x\": 155.5,\n          \"y\": 238\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c91be718-924b-49af-9aff-ec4ec25258a3\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"9f43db5a-ba94-4636-9dcf-c531c176bb2c\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"967bf3c7-8255-49b3-9f26-5438e1dd36b4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ec7f01f3-e88f-4921-81a1-7478f3bd65b8\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e3929097-4842-4cde-92e3-1a44f6571b62\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 370,\n          \"height\": 685,\n          \"sticker\": { \"type\": \"elegantTravelFloralFrame\" },\n          \"type\": \"sticker\",\n          \"id\": \"ffc651fc-c67a-4ead-9595-a9c03a260223\",\n          \"x\": 21,\n          \"y\": -33.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.3em; text-transform: uppercase\\\">More from John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 19,\n          \"marginOffset\": -38.564,\n          \"id\": \"94e874ee-edff-46b0-afeb-bbf6ea8d8270\",\n          \"x\": 44,\n          \"y\": 34,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T10:31:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page13_image01.jpg\",\n            \"width\": 720,\n            \"height\": 498,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Bare tress and mountain\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d7d5d2\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 57,\n          \"y\": 77,\n          \"width\": 301,\n          \"height\": 208,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8857ac4d-d641-45ef-b3c2-1dfab3b069d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#3b4335\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/elegant-travel-itinerary/page13_image02.jpg\",\n            \"width\": 720,\n            \"height\": 498,\n            \"id\": 0,\n            \"alt\": \"Photo of house near cliff and body of water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 57,\n          \"y\": 344,\n          \"width\": 301,\n          \"height\": 208,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fc83929c-683d-4fa1-9c1c-433cbd7a8fda\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 294,\n          \"id\": \"280b404b-49f7-4483-8e52-d2ac0a94ae34\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Top Five Fall Road Trips</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 26,\n          \"marginOffset\": -38.564\n        },\n        {\n          \"x\": 44,\n          \"y\": 561,\n          \"id\": \"fb5db080-b238-435f-b1b1-d84b29be7e10\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Spend a Week in Tuscany</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 324,\n          \"height\": 25,\n          \"marginOffset\": -38.564\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3aba2b10-6e04-49fc-94fa-845d88bd8584\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ffc651fc-c67a-4ead-9595-a9c03a260223\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"12fa4b32-3fda-42c6-bbaf-37b9c787f421\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8857ac4d-d641-45ef-b3c2-1dfab3b069d3\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"79f68006-b46e-46ac-be2d-89be61bce045\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"280b404b-49f7-4483-8e52-d2ac0a94ae34\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"74f9a1bc-d03d-484e-a414-baf0685d60e6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fc83929c-683d-4fa1-9c1c-433cbd7a8fda\"],\n          \"duration\": 2000,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"cbc891ec-03e5-4839-a53b-b93c3a03b9ac\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fb5db080-b238-435f-b1b1-d84b29be7e10\"],\n          \"duration\": 2000,\n          \"delay\": 750\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 21, \"g\": 28, \"b\": 35 } },\n      \"type\": \"page\",\n      \"id\": \"4af8e3b1-7d59-42b8-9441-efeb85e86b93\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/experience-thailand/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/experience-thailand/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'experience-thailand',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Experience Thailand', 'template name', 'web-stories'),\n  tags: [\n    _x('Explore', 'template keyword', 'web-stories'),\n    _x('Adventure', 'template keyword', 'web-stories'),\n    _x('Taste', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Green', 'color', 'web-stories'),\n      color: '#094228',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Yellow', 'color', 'web-stories'),\n      color: '#fec85a',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Blue', 'color', 'web-stories'),\n      color: '#0648ad',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Designed to instil a sense of wanderlust & wonder, the Travel template can be a great foundation for travel inspiration, travel itineraries, restaurant hopping guides, Best-of attraction listicles and other types of travel content.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/experience-thailand/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/experience-thailand/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 19,\n          \"y\": 117,\n          \"width\": 206,\n          \"height\": 138,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"scale\": 140,\n          \"focalX\": 51.403743315508024,\n          \"focalY\": 50.84033613445378,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#867068\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page1_bg.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"ca140433-52d1-4423-896f-2e5c856cb22f\",\n          \"isBackground\": true,\n          \"overlay\": null,\n          \"alt\": \"Close up of elephant's face\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 263,\n          \"width\": 412,\n          \"height\": 42,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"d5ca2488-668b-4e21-a7d8-05c17084742b\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Experience</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": -2,\n          \"y\": 309,\n          \"width\": 413,\n          \"height\": 98,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"3c00f665-e2ff-4393-aef4-6ca790f599fd\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Thailand</span>\",\n          \"fontSize\": 99,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 20,\n          \"y\": 545,\n          \"width\": 128,\n          \"height\": 56,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 9, \"g\": 66, \"b\": 40 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7de325ef-2490-4e19-9c9c-7031bffa4b05\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-06-17T21:30:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/icon_logo.png\",\n            \"width\": 32,\n            \"height\": 10,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"icon_logo\",\n            \"sizes\": [],\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 563.5,\n          \"width\": 60,\n          \"height\": 19,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"a6b25c2c-a676-404b-ab44-5bd5b49598f5\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"fca5c47a-e26f-4feb-b2a3-f6d8b6c68996\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e36e376f-3cdb-43f8-b1c7-cdf3a0098132\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 43,\n          \"y\": 0,\n          \"width\": 137,\n          \"height\": 137,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"143182cf-804b-4d71-93d8-d4a53c9e6ed6\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -4,\n          \"y\": -61,\n          \"width\": 417,\n          \"height\": 468,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 9, \"g\": 66, \"b\": 40 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a81f2dcc-b5a3-4be6-8a06-bb42ac828ed0\"\n        },\n        {\n          \"x\": 57,\n          \"y\": 17,\n          \"width\": 265,\n          \"height\": 265,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"bfd53cf2-f8e8-41f0-8449-48772b5194bb\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">I travel to find myself in the eyes and hearts of others”</span>\",\n          \"fontSize\": 53,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 16,\n          \"width\": 19,\n          \"height\": 51,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"90e3970e-a7be-4ecb-91a6-4f6065f28de1\",\n          \"content\": \"<span style=\\\"color: #fff\\\">“</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 58,\n          \"y\": 351,\n          \"width\": 206,\n          \"height\": 23,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"88df74ed-7334-4e91-957c-c48b8da344e4\",\n          \"content\": \"<span style=\\\"color: #fff\\\">– Anonymous</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 70,\n          \"y\": 333,\n          \"width\": 272,\n          \"height\": 416,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 120,\n          \"focalX\": 49.958297992927974,\n          \"focalY\": 47.911921059829645,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8a21c4e7-4e9b-4811-9b8b-f36d0297a9e4\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#11242e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page2_image1.jpg\",\n            \"width\": 220,\n            \"height\": 331,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Variety of prepared food dishes\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d51e578e-e103-4e72-8f32-2c00e36d4f26\",\n          \"targets\": [\"90e3970e-a7be-4ecb-91a6-4f6065f28de1\"],\n          \"type\": \"move\",\n          \"overflowHidden\": false,\n          \"offsetX\": 0,\n          \"offsetY\": \"35%\",\n          \"duration\": 600,\n          \"delay\": 500,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"inOutCubic\",\n          \"fill\": \"both\"\n        },\n        {\n          \"id\": \"64648979-ec76-4ab0-abf5-874b238d948c\",\n          \"targets\": [\"90e3970e-a7be-4ecb-91a6-4f6065f28de1\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 300,\n          \"delay\": 800,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"inOutCubic\",\n          \"fill\": \"both\"\n        },\n        {\n          \"id\": \"2428c2b8-e3fb-4a52-837d-fa877a4fdd25\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bfd53cf2-f8e8-41f0-8449-48772b5194bb\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"a3383e56-c185-406e-b848-fbbf5de39a2a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"88df74ed-7334-4e91-957c-c48b8da344e4\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 500,\n          \"delay\": 800\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"3cdf0fde-f515-477d-8688-472c4cc5a8b3\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 90,\n          \"y\": 86,\n          \"width\": 137,\n          \"height\": 137,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"b39e1373-e1d4-40ee-bd0c-298924b61a3e\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": 284,\n          \"width\": 324,\n          \"height\": 392,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 49.81801455703381,\n          \"focalY\": 44.55730329866608,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4c694857-df14-4ba9-8791-9b13935dbbbe\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#46382a\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page3_image1.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Preparing a street food dish\"\n        },\n        {\n          \"x\": 236,\n          \"y\": 284,\n          \"width\": 88,\n          \"height\": 88,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"FILL\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"id\": \"3cf17fb8-a5ae-4f32-8e5f-d3a0513215de\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">Learn</span>\\n<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 20,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"locked\": false,\n            \"horizontal\": 18,\n            \"vertical\": 19\n          },\n          \"lockAspectRatio\": true,\n          \"marginOffset\": 0\n        },\n        {\n          \"x\": 41,\n          \"y\": 140,\n          \"width\": 247,\n          \"height\": 92,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"883808f1-b87b-4b35-b0f1-0945e0faef2e\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">The cheapest and most authentic way to experience Thai life. Prepare yourself, some like it hot!</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 41,\n          \"y\": 15,\n          \"width\": 143,\n          \"height\": 104,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"6258d646-a291-498f-81ab-3095f352bb26\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Street</span>\\n<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Food</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a182062e-4c57-41c8-83cb-c44813cc025c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6258d646-a291-498f-81ab-3095f352bb26\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"a0a9acaf-40d0-424f-b614-5754f613c979\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"883808f1-b87b-4b35-b0f1-0945e0faef2e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"a5e7c238-bf50-45b8-a4c4-eafc15e03fbc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3cf17fb8-a5ae-4f32-8e5f-d3a0513215de\"],\n          \"duration\": 600,\n          \"delay\": 600\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"80b4f7b3-c54a-4e40-9a75-c937cedfed4b\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 91,\n          \"y\": 69,\n          \"width\": 206,\n          \"height\": 138,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#2f342d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page4_bg.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"a920881d-6fab-4d96-8884-0df9f0b6a8fd\",\n          \"isBackground\": true,\n          \"alt\": \"Aerial view of floating market boats\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 0,\n          \"width\": 334,\n          \"height\": 168,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3d3b38a3-d8db-4a86-a4e2-0be30e92b177\"\n        },\n        {\n          \"x\": 67,\n          \"y\": 30,\n          \"width\": 139,\n          \"height\": 26,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"1b892512-7510-4c09-a750-7dfd21ece74a\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Floating Market</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 68,\n          \"y\": 66,\n          \"width\": 267,\n          \"height\": 69,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"d773e2ce-05a7-4195-a815-cfd66e93f66a\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">Experience the unique floating market, where all goods are sold from boats.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fd0a257e-a082-4e9f-a0b9-28bacb8b8e5f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d773e2ce-05a7-4195-a815-cfd66e93f66a\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 600,\n          \"delay\": 475\n        },\n        {\n          \"id\": \"48ba141a-41f7-43e7-ac32-9368af23ecfe\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1b892512-7510-4c09-a750-7dfd21ece74a\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 600,\n          \"delay\": 450\n        },\n        {\n          \"id\": \"818b510f-3eb7-413d-829d-8cdb6a2cdfd9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3d3b38a3-d8db-4a86-a4e2-0be30e92b177\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 600,\n          \"delay\": 500\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"6302fb0d-8f99-4498-91eb-bca15d67ae84\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"3769638a-e9e5-4ff0-96dc-9b3df5d78215\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 53,\n          \"y\": 17,\n          \"width\": 206,\n          \"height\": 140,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"scale\": 100,\n          \"focalX\": 49.18364448416392,\n          \"focalY\": 49.97767879474251,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#797a6e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page5_bg.jpg\",\n            \"width\": 220,\n            \"height\": 149,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"3b0ede46-334e-4bc5-abb7-f09dec3d6d48\",\n          \"isBackground\": true,\n          \"alt\": \"Tourist taking a photo\"\n        },\n        {\n          \"x\": 103,\n          \"y\": 13,\n          \"width\": 206,\n          \"height\": 42,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"65283dae-40f2-4ace-8b0a-0d9f2066a38a\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Capture</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 55,\n          \"width\": 411,\n          \"height\": 97,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"95c08a42-48cd-4112-b0e2-f24362adc7bc\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Bangkok</span>\",\n          \"fontSize\": 98,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 74,\n          \"y\": 558,\n          \"width\": 264,\n          \"height\": 46,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"7dae1bd9-9f88-4ae8-93eb-f3d908cace09\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Tips and tricks for capturing this iconic city in a day.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3bcb7063-d1cf-4a1f-925f-572eab6f3238\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 1000,\n          \"delay\": 0,\n          \"targets\": [\"3b0ede46-334e-4bc5-abb7-f09dec3d6d48\"]\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"22081c00-a02f-4085-84de-0f4a31253222\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"4d03120b-e736-4b71-b5bc-81159357f030\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 44,\n          \"y\": 57,\n          \"width\": 206,\n          \"height\": 116,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"scale\": 130,\n          \"focalX\": 31.508137400282983,\n          \"focalY\": 50.08072617756131,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#523c30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page6_bg.jpg\",\n            \"width\": 220,\n            \"height\": 124,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"117a9caa-d0cc-47d0-b00e-ee623bbcd5fc\",\n          \"isBackground\": true,\n          \"alt\": \"Temples surrounded by greenery\"\n        },\n        {\n          \"x\": 45,\n          \"y\": 404,\n          \"width\": 246,\n          \"height\": 108,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"c40c8eae-e683-4fa6-a632-e1d652279a37\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Top 5</span>\\n<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Chiang Mai</span>\",\n          \"fontSize\": 54,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 521,\n          \"width\": 303,\n          \"height\": 84,\n          \"font\": {\n            \"family\": \"Arial\",\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1854,\n              \"des\": -434,\n              \"tAsc\": 1491,\n              \"tDes\": -431,\n              \"tLGap\": 307,\n              \"wAsc\": 1854,\n              \"wDes\": 1854,\n              \"xH\": 1062,\n              \"capH\": 1467,\n              \"yMin\": -665,\n              \"yMax\": 2060,\n              \"hAsc\": 1854,\n              \"hDes\": -434,\n              \"lGap\": 67\n            },\n            \"weights\": [400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"service\": \"system\"\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"ca20176a-3245-4735-9b1c-66017aa9e528\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\">If you only have one day to see as many sights as you can, we’ve compiled a list of walkable must-see destinations.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 136,\n          \"y\": -56,\n          \"width\": 268,\n          \"height\": 451,\n          \"sticker\": { \"type\": \"travelMap\" },\n          \"id\": \"a26880a7-7949-4522-8006-71a3be643a06\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"13a823a5-2e21-4a9d-80ca-36100b3b161e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c40c8eae-e683-4fa6-a632-e1d652279a37\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"3b27a58f-ec23-4be9-bb5b-8557f0309e0b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ca20176a-3245-4735-9b1c-66017aa9e528\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"c706ce0e-80f8-4676-96f0-95fc3090022f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a26880a7-7949-4522-8006-71a3be643a06\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"c2d56aca-cb1a-41eb-bbdc-41dc2c4f597c\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"64ea1430-5f03-4155-be5d-16faaa4b098e\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 7,\n          \"y\": 62,\n          \"width\": 137,\n          \"height\": 137,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9012bef0-e5e3-4910-8412-a10ce18e23a6\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 42,\n          \"y\": 381,\n          \"width\": 152,\n          \"height\": 104,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"3932eb5c-e456-43d8-988d-4aa01dd4a8bd\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Temple</span>\\n<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Name</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 42,\n          \"y\": 501,\n          \"width\": 300,\n          \"height\": 92,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"bc7d8800-b421-4a19-9db0-f594e9b0bd8d\",\n          \"content\": \"<span style=\\\"color: #094228\\\">The courtyard around the 3 Kings Monument is the best place to give early morning Alms to the Monks in Central Chiang Mai.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 327,\n          \"height\": 402,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.000000000000014,\n          \"focalY\": 57.36776812717045,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"37a09535-568f-4dc6-a07d-57f3ac1c9d39\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#3f463e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page7_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Close up of statue in 3 Kings Monument\"\n        },\n        {\n          \"x\": 239,\n          \"y\": 257,\n          \"width\": 88,\n          \"height\": 88,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"FILL\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">No. 3</span>\",\n          \"fontSize\": 20,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"locked\": false,\n            \"horizontal\": 18,\n            \"vertical\": 29\n          },\n          \"lockAspectRatio\": true,\n          \"marginOffset\": 0,\n          \"id\": \"b6dd7e92-0951-4581-9436-29393593c5d3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6cef7b08-36b0-47d2-b1e7-ac1212a09080\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3932eb5c-e456-43d8-988d-4aa01dd4a8bd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 650\n        },\n        {\n          \"id\": \"5623af7f-e8ff-42f8-b823-f19e7e88f80b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bc7d8800-b421-4a19-9db0-f594e9b0bd8d\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 700\n        },\n        {\n          \"targets\": [\"b6dd7e92-0951-4581-9436-29393593c5d3\"],\n          \"id\": \"6c6db6d4-c0e6-479e-8442-e227a734af37\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 600\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"7b7d7662-fb1f-46b5-94e0-b01029a666a5\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 12,\n          \"y\": 130,\n          \"width\": 206,\n          \"height\": 138,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#37474e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page8_bg.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"3f23fce9-2fb5-4f17-acec-f0f6f524967d\",\n          \"isBackground\": true,\n          \"alt\": \"Boat with many passengers near island mountains\"\n        },\n        {\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 324,\n          \"height\": 436,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 159, \"g\": 208, \"b\": 255, \"a\": 0.5 }\n          },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f60ae332-db13-481f-ace7-107885b1c202\"\n        },\n        {\n          \"x\": 40,\n          \"y\": 29,\n          \"width\": 195,\n          \"height\": 101,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"30716193-c4ff-4619-b485-8108d250c8b8\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Island</span>\\n<span style=\\\"text-transform: uppercase\\\">Hopping</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 41,\n          \"y\": 152,\n          \"width\": 250,\n          \"height\": 138,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"41d3069f-61de-4998-8487-036ea86917a6\",\n          \"content\": \"The main island hopping hubs are Phuket, Krabi, Koh Phi Phi, and Koh Lipe. Other favorites include Ko Tao, Ko Pha-Ngan, Ko Samui and Surat Thani.\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 236,\n          \"y\": 290,\n          \"width\": 88,\n          \"height\": 88,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"FILL\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">Learn</span>\\n<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 20,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"locked\": false,\n            \"horizontal\": 18,\n            \"vertical\": 19\n          },\n          \"lockAspectRatio\": true,\n          \"marginOffset\": 0,\n          \"id\": \"88d486d7-a957-4c41-b4e9-11280585f13f\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"75b03916-f227-421c-957e-1681ff729d77\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"30716193-c4ff-4619-b485-8108d250c8b8\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"d3c032d2-af08-4fa9-9997-e5e9cccb9e93\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"41d3069f-61de-4998-8487-036ea86917a6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"88d486d7-a957-4c41-b4e9-11280585f13f\"],\n          \"id\": \"c3ab8ee7-6ac1-4e73-b042-5ef7d43685a2\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 600\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"1659f169-eb29-498a-bd00-6aea80d7ace7\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6f8d6dec-a10b-43d5-a74f-0bac45722dab\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 33,\n          \"y\": 97,\n          \"width\": 137,\n          \"height\": 137,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"55fcd4fb-1af4-4540-ac57-a783f94f6864\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -2.5,\n          \"y\": 162,\n          \"width\": 417,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d90985a8-8ba6-45b1-8e8a-ef2fa073dac9\"\n        },\n        {\n          \"x\": -2.5,\n          \"y\": 309,\n          \"width\": 417,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"359fca2c-a5ab-448c-b9e6-11dd47517650\"\n        },\n        {\n          \"x\": -1,\n          \"y\": 454,\n          \"width\": 417,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2a391259-057a-4976-b90d-2c6140e2a222\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 59,\n          \"width\": 206,\n          \"height\": 20,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"5cb07f8c-750f-437b-981f-cc3228cdeffd\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">1. Phuket</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"13341c17-f694-4c40-95d8-5058fa620c4e\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 89,\n          \"width\": 207,\n          \"height\": 23,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"adc642e3-a739-4349-9646-cb06d88f51a4\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">Start your journey here</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"13341c17-f694-4c40-95d8-5058fa620c4e\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 17,\n          \"width\": 140,\n          \"height\": 146,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 210,\n          \"focalX\": 71.09866593641652,\n          \"focalY\": 42.12316471707116,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"43b28f35-fdc3-4b59-b3da-ad9581cbeb8c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#dbe1e0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page9_image1.jpg\",\n            \"width\": 220,\n            \"height\": 165,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Boat near beach in Phuket\",\n          \"groupId\": \"13341c17-f694-4c40-95d8-5058fa620c4e\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 205,\n          \"width\": 206,\n          \"height\": 20,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"840cd415-bf08-4186-9649-932beb2e6778\",\n          \"content\": \"<span style=\\\"color: #094228; text-transform: uppercase\\\">2. Koh Phi Phi</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"6b41cd4a-107a-4648-a53a-ec4d1eda23cc\"\n        },\n        {\n          \"x\": 169,\n          \"y\": 235,\n          \"width\": 207,\n          \"height\": 23,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"919e9a80-e851-49fe-9660-c67937a14e13\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">Scoot around the island</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"6b41cd4a-107a-4648-a53a-ec4d1eda23cc\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 164,\n          \"width\": 140,\n          \"height\": 146,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 38.57638552918454,\n          \"focalY\": 50.00000000000002,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d16ef169-d80c-4e70-817a-9e3bf66d1428\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#091514\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page9_image2.jpg\",\n            \"width\": 220,\n            \"height\": 124,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Person riding a scooter on a road\",\n          \"groupId\": \"6b41cd4a-107a-4648-a53a-ec4d1eda23cc\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 351,\n          \"width\": 206,\n          \"height\": 20,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"bbe6302e-87c0-49d2-b16b-ff787059c187\",\n          \"content\": \"<span style=\\\"color: #094228; text-transform: uppercase\\\">3. Koh Lipe</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"09a92979-ba20-4a80-af42-f970ee2d2be1\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 381,\n          \"width\": 187,\n          \"height\": 23,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"63b0bbbf-6ef4-42c1-b017-d7db0db07039\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">Best red curry</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"09a92979-ba20-4a80-af42-f970ee2d2be1\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 308,\n          \"width\": 140,\n          \"height\": 146,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 37.799042537992264,\n          \"focalY\": 54.72610116975728,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a7ca1ee4-5f88-45e3-aa3d-ea3cfda6b027\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#314a47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page9_image4.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Close up of red curry dish\",\n          \"groupId\": \"09a92979-ba20-4a80-af42-f970ee2d2be1\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 497,\n          \"width\": 195,\n          \"height\": 20,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"44db08e2-0900-40a6-9e52-3ab2325aeab2\",\n          \"content\": \"<span style=\\\"color: #094228; text-transform: uppercase\\\">4. Ko Samui</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"5b9a504d-46ff-4058-83e5-bbf6f78f648b\"\n        },\n        {\n          \"x\": 171,\n          \"y\": 528,\n          \"width\": 187,\n          \"height\": 23,\n          \"font\": {\n            \"family\": \"Lora\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"300c43cc-b0b0-45de-97ba-1775028d50bb\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1)\\\">Semi-secluded island</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"5b9a504d-46ff-4058-83e5-bbf6f78f648b\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 454,\n          \"width\": 140,\n          \"height\": 146,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 160,\n          \"focalX\": 68.9811217492273,\n          \"focalY\": 60.54933296820826,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"07155f07-19d8-4eca-8817-9b512fd3303f\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#242c17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page9_image5.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Close up of palm branch\",\n          \"groupId\": \"5b9a504d-46ff-4058-83e5-bbf6f78f648b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d4d4da64-b099-4201-aaa6-1164ae19a0c8\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"43b28f35-fdc3-4b59-b3da-ad9581cbeb8c\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"dc8b9d52-23ea-4a6e-8f19-8810dc8e6a96\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"5cb07f8c-750f-437b-981f-cc3228cdeffd\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1ccd4b89-b8a1-4379-ab33-0187c889a3b2\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"adc642e3-a739-4349-9646-cb06d88f51a4\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5f70813d-1ac8-4a05-8b18-248bb2386b02\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"d16ef169-d80c-4e70-817a-9e3bf66d1428\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"451a8798-e690-46a7-8d3e-77d0c4a3b093\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"840cd415-bf08-4186-9649-932beb2e6778\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0dfe9906-9e95-4b5f-81ee-6989b9f27167\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"919e9a80-e851-49fe-9660-c67937a14e13\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"81df1d47-03a1-4fe2-94ae-d73d526f26bf\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"a7ca1ee4-5f88-45e3-aa3d-ea3cfda6b027\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"4b99e1fc-dfb3-4c0c-ba24-3d1d13be9550\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"bbe6302e-87c0-49d2-b16b-ff787059c187\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"0d0b8e35-ce1f-4755-8729-6f15f34ebf79\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"63b0bbbf-6ef4-42c1-b017-d7db0db07039\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"22490f0c-fcfa-49be-ad9b-b2980db6013a\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"07155f07-19d8-4eca-8817-9b512fd3303f\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"60a1a95e-c800-4aa7-b62b-30255c4b9a21\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"44db08e2-0900-40a6-9e52-3ab2325aeab2\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"97bc4870-6bae-4498-aa1e-19a1820e8b47\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"300c43cc-b0b0-45de-97ba-1775028d50bb\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"78da0e6c-6bc7-4680-90a8-2b6bf6e98aaa\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"13341c17-f694-4c40-95d8-5058fa620c4e\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6b41cd4a-107a-4648-a53a-ec4d1eda23cc\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"09a92979-ba20-4a80-af42-f970ee2d2be1\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"5b9a504d-46ff-4058-83e5-bbf6f78f648b\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 82,\n          \"y\": 63,\n          \"width\": 137,\n          \"height\": 137,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"282588c3-fbc2-4b63-8260-2e58d0e63294\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 252,\n          \"y\": 158,\n          \"width\": 160,\n          \"height\": 120,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b542beff-39c1-4787-a8ad-a2a061c51a60\",\n          \"lockAspectRatio\": true,\n          \"groupId\": \"af2d1be9-be5a-4f80-8d7f-508fb15ea9b2\"\n        },\n        {\n          \"x\": 277,\n          \"y\": 199,\n          \"width\": 81,\n          \"height\": 40,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"7ea7ab1b-9bcd-45d6-941d-2c1143cadf0f\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">5 Spiciest</span>\\n<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Dishes</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"af2d1be9-be5a-4f80-8d7f-508fb15ea9b2\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 158,\n          \"width\": 252,\n          \"height\": 120,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 230,\n          \"focalX\": 46.28668252718276,\n          \"focalY\": 67.71403998512304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"85439d79-2100-4dc8-9b20-e6e51d2064af\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#868247\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page10_image1.jpg\",\n            \"width\": 220,\n            \"height\": 112,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"alt\": \"Variety of peppers\",\n          \"groupId\": \"af2d1be9-be5a-4f80-8d7f-508fb15ea9b2\"\n        },\n        {\n          \"x\": 252,\n          \"y\": 396,\n          \"width\": 160,\n          \"height\": 120,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 236, \"g\": 236, \"b\": 236 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"12b82d84-167c-49b1-8efd-afae77b857f0\",\n          \"lockAspectRatio\": true,\n          \"groupId\": \"84a09ec9-f5b8-4fd9-9095-4f5dec1a5db2\"\n        },\n        {\n          \"x\": 277,\n          \"y\": 428,\n          \"width\": 88,\n          \"height\": 60,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"fcdc8182-cfb1-4010-82cd-91b5f235f0fc\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Catch The Swimming Monkeys</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"84a09ec9-f5b8-4fd9-9095-4f5dec1a5db2\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 397,\n          \"width\": 252,\n          \"height\": 120,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 54.65421808442616,\n          \"focalY\": 38.31609851544505,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#0e8484\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page10_image3.jpg\",\n            \"width\": 220,\n            \"height\": 124,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"098c9143-7ca0-4b04-866f-02c5c48339d2\",\n          \"alt\": \"Two monkeys swimming\",\n          \"groupId\": \"84a09ec9-f5b8-4fd9-9095-4f5dec1a5db2\"\n        },\n        {\n          \"x\": 41,\n          \"y\": 18,\n          \"width\": 195,\n          \"height\": 104,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 99,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"e5272870-2b37-4bba-abcf-eab0ffc222a4\",\n          \"content\": \"<span style=\\\"color: #094228; text-transform: uppercase\\\">More</span>\\n<span style=\\\"color: #094228; text-transform: uppercase\\\">Stories</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 278,\n          \"y\": 308,\n          \"width\": 89,\n          \"height\": 60,\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundTextMode\": \"NONE\",\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"id\": \"cb201d61-faec-476e-9d72-14caf813197b\",\n          \"content\": \"<span style=\\\"color: rgba(9, 66, 40, 1); text-transform: uppercase\\\">Hikes Off The Beaten\\nTrail</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"b4c42e7f-223e-4460-a534-f464437321b0\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 278,\n          \"width\": 252,\n          \"height\": 120,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 120,\n          \"focalX\": 45.07590551296434,\n          \"focalY\": 41.80970621298839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#cd7963\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/experience-thailand/page10_image2.jpg\",\n            \"width\": 220,\n            \"height\": 83,\n            \"poster\": \"\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"19fd443d-f580-436b-82b4-ef2938c55e89\",\n          \"alt\": \"Person hiking during sunset\",\n          \"groupId\": \"b4c42e7f-223e-4460-a534-f464437321b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 77,\n          \"y\": 576,\n          \"width\": 13,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"travelFacebookIcon\" },\n          \"id\": \"c6a706c8-7f36-4b04-bb5c-3d3d9d30498a\",\n          \"groupId\": \"dc6f0dc5-613f-46b7-ad00-0c5e7e736f98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 147,\n          \"y\": 576,\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"travelInstagramIcon\" },\n          \"id\": \"3e52ff79-b15b-4f2c-ba7d-daba7f967904\",\n          \"groupId\": \"dc6f0dc5-613f-46b7-ad00-0c5e7e736f98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 229,\n          \"y\": 578,\n          \"width\": 30,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"travelYouTubeIcon\" },\n          \"id\": \"276d0d4c-e1d1-47c9-99bf-fe3ebc86615d\",\n          \"groupId\": \"dc6f0dc5-613f-46b7-ad00-0c5e7e736f98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 309,\n          \"y\": 579,\n          \"width\": 26,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"travelTwitterIcon\" },\n          \"id\": \"ce560b5f-13b9-4a5e-85ff-cbc41ea982e8\",\n          \"groupId\": \"dc6f0dc5-613f-46b7-ad00-0c5e7e736f98\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3bd3503e-3962-4b3e-ae11-571796156bf8\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"e5272870-2b37-4bba-abcf-eab0ffc222a4\"]\n        },\n        {\n          \"id\": \"47272274-438e-465e-964c-f8f4cd7a6888\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"85439d79-2100-4dc8-9b20-e6e51d2064af\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c8ce65ee-7290-427a-921c-663281aaa49d\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"7ea7ab1b-9bcd-45d6-941d-2c1143cadf0f\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"536d05b0-1c32-4152-ab73-299afce57a2f\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"b542beff-39c1-4787-a8ad-a2a061c51a60\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"58be93c8-f73c-4c69-ac9b-d0f0c7f669e6\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"19fd443d-f580-436b-82b4-ef2938c55e89\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"eeaa124d-1fa5-40b5-af48-4730f5f59185\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"cb201d61-faec-476e-9d72-14caf813197b\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"087fd1bc-10d2-4053-a742-402be6e8c059\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"098c9143-7ca0-4b04-866f-02c5c48339d2\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"46e98909-59fd-409e-a716-52342550e277\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"fcdc8182-cfb1-4010-82cd-91b5f235f0fc\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"ce871997-549f-4166-96fe-49855a5200d0\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"12b82d84-167c-49b1-8efd-afae77b857f0\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 900\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"9a45a0b2-0261-4298-aef7-c08b99771787\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"dc6f0dc5-613f-46b7-ad00-0c5e7e736f98\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"84a09ec9-f5b8-4fd9-9095-4f5dec1a5db2\": {\n          \"name\": \"Monkeys\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"af2d1be9-be5a-4f80-8d7f-508fb15ea9b2\": {\n          \"name\": \"Dishes\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b4c42e7f-223e-4460-a534-f464437321b0\": {\n          \"name\": \"Hikes\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-inspiration/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-inspiration/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'fashion-inspiration',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Fashion Inspiration', 'template name', 'web-stories'),\n  tags: [\n    _x('Fashion', 'template keyword', 'web-stories'),\n    _x('Inspiration', 'template keyword', 'web-stories'),\n    _x('Clothes', 'template keyword', 'web-stories'),\n    _x('Classy', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Faded Rose Red', 'color', 'web-stories'),\n      color: '#c16351',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Winter Mist White', 'color', 'web-stories'),\n      color: '#f2f2f2',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Prairie Gold', 'color', 'web-stories'),\n      color: '#b18c54',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its clean, classy look and full-screen photos, this template will let you effectively present fashion and outfit ideas. You can use large-scale close up shots to showcase products, along with individual purchase pages and a short description.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion & Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-inspiration/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-inspiration/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ac0ad0ca-5d24-40c4-90bd-e20385e6584e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 64,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; font-style: italic; color: rgba(177,140,84,0.12)\\\">Inside look</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 71,\n          \"id\": \"3cccfd70-c5ed-4e0a-84f8-8356b205e519\",\n          \"x\": -25,\n          \"y\": 54,\n          \"type\": \"text\",\n          \"groupId\": \"c535c1c2-117b-4047-8efe-e9ea57a69324\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 64,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; font-style: italic; color: rgba(177,140,84,0.12)\\\">Inside look</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 71,\n          \"id\": \"50548434-d1d7-4699-b5f7-9cf582a6eccd\",\n          \"x\": -25,\n          \"y\": 99,\n          \"type\": \"text\",\n          \"groupId\": \"c535c1c2-117b-4047-8efe-e9ea57a69324\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 64,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; font-style: italic; color: rgba(177,140,84,0.12)\\\">Inside look</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 71,\n          \"id\": \"5516447e-18cd-4ecd-a76c-140029547b89\",\n          \"x\": -25,\n          \"y\": 146,\n          \"type\": \"text\",\n          \"groupId\": \"c535c1c2-117b-4047-8efe-e9ea57a69324\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 64,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; font-style: italic; color: rgba(177,140,84,0.12)\\\">Inside look</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 317,\n          \"height\": 71,\n          \"id\": \"64b35e74-ddac-484f-affb-60c2ca646824\",\n          \"x\": -25,\n          \"y\": 193,\n          \"type\": \"text\",\n          \"groupId\": \"c535c1c2-117b-4047-8efe-e9ea57a69324\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Fashion Inspiration</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 238,\n          \"height\": 17,\n          \"id\": \"71847b2f-57b4-4a06-9a2d-471ee92eb0fe\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"x\": 70,\n          \"y\": 102,\n          \"width\": 382,\n          \"height\": 254,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"be6b55fc-a396-4cfb-8e1b-4e5eb8c963cd\",\n          \"type\": \"shape\",\n          \"groupId\": \"581825a0-be14-4515-b819-4bfacec3bf38\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 110,\n          \"focalX\": 47.86749479899753,\n          \"focalY\": 65.91779387283562,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:42:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page1_img1.jpg\",\n            \"width\": 810,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Folded clothes above hanged clothes\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#413a33\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 90,\n          \"y\": 45,\n          \"width\": 322,\n          \"height\": 293,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e6faaf99-9591-482a-90f6-c89ee6f7850b\",\n          \"type\": \"image\",\n          \"groupId\": \"581825a0-be14-4515-b819-4bfacec3bf38\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 51,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Inside</span>\\n<span style=\\\"font-weight: 200\\\">Jean Legere's</span>\\n<span style=\\\"font-weight: 200\\\">Closet</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 429,\n          \"width\": 317,\n          \"height\": 159,\n          \"id\": \"fdd58d7f-a517-4b39-b1d2-293d57ada467\",\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"12b85089-b491-41fa-8762-0286f2d49f05\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"c535c1c2-117b-4047-8efe-e9ea57a69324\": {\n          \"name\": \"Background Text\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"581825a0-be14-4515-b819-4bfacec3bf38\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 493,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"62eab021-4297-46ca-b72d-334498841944\",\n          \"scale\": 121,\n          \"focalX\": 37.23958333333334,\n          \"focalY\": 58.65185950413222,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:43:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1617,\n            \"id\": 0,\n            \"alt\": \"Man in brown coat\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#7e9598\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">Ah, Jean Legere.</span>\\n<span style=\\\"font-weight: 200; color: #fff\\\">A legendary man of song and style. Let’s step inside his closet shall we?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 459,\n          \"width\": 326,\n          \"height\": 130,\n          \"id\": \"5d6d6259-cf27-4cb5-b934-ed50adf330c1\",\n          \"type\": \"text\",\n          \"groupId\": \"22cda22d-e604-4ca5-8a96-fa3fb601246c\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e608ed67-86a8-4ceb-ac10-eb277154251e\",\n          \"x\": 47,\n          \"y\": 452,\n          \"type\": \"shape\",\n          \"groupId\": \"22cda22d-e604-4ca5-8a96-fa3fb601246c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"e608ed67-86a8-4ceb-ac10-eb277154251e\"],\n          \"id\": \"ed871294-1cd0-46e9-96b6-9523d852f29e\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5c820aef-95ec-4f15-be9a-4abb4d2d71bb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"36957881-3929-4947-8a6a-c9c99e9dd608\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"22cda22d-e604-4ca5-8a96-fa3fb601246c\": {\n          \"name\": \"Text\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7b938a42-b7a6-4cfa-bdfd-7022be2615e0\",\n          \"type\": \"image\",\n          \"scale\": 155,\n          \"focalX\": 38.508064516129025,\n          \"focalY\": 36.693548387096776,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:45:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man in black 2-piece suit near swimming pool\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c5c1c1\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 375,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c890d939-144b-4018-879c-2fd2b9251a10\",\n          \"type\": \"shape\",\n          \"groupId\": \"35ee72cc-f74d-4519-9f53-19df9b825898\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.28em; text-transform: uppercase\\\">Alexander McQueen Suit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 385,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"38980eef-41dc-4f4c-8cef-96e0c64b4e52\",\n          \"type\": \"text\",\n          \"groupId\": \"35ee72cc-f74d-4519-9f53-19df9b825898\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">I absolutely love this suit, I wore it during the</span>\\n<span style=\\\"font-weight: 200; color: #fff\\\">Grammys last year. It is sharp, sharp, sharp.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 416,\n          \"width\": 318,\n          \"height\": 130,\n          \"id\": \"07c8ab5e-bb74-426e-b1da-e2311eccf468\",\n          \"type\": \"text\",\n          \"groupId\": \"35ee72cc-f74d-4519-9f53-19df9b825898\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 25,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 15,\n          \"lockAspectRatio\": true,\n          \"x\": 247,\n          \"y\": -276,\n          \"width\": 420,\n          \"height\": 437,\n          \"sticker\": { \"type\": \"fashionInspirationCutout\" },\n          \"id\": \"608f5fa1-f8a3-433a-8db4-e8c7773e477a\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"36bcf4b1-43ec-4826-b2c0-198d310fd512\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c890d939-144b-4018-879c-2fd2b9251a10\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"40467ff8-3cb0-4acb-a48f-67015af41ba7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"1e689663-4c00-4ba7-b097-c3cd8962a6cb\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"35ee72cc-f74d-4519-9f53-19df9b825898\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 218,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4c8d6e32-e5b9-409a-9f1b-0c3342fbb57c\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 43.17136725935009,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:46:08\",\n            \"baseColor\": \"#2b363e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page4_img1.jpg\",\n            \"width\": 1631,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Closeup photo of man in black suit jacket\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.5\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">It’s probably the softest and most comfortable piece I own too.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 133,\n          \"y\": 33,\n          \"width\": 229,\n          \"height\": 130,\n          \"id\": \"8216055c-75c9-4840-93a3-f82b141f42ac\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 135,\n          \"y\": 182,\n          \"width\": 118,\n          \"height\": 293,\n          \"sticker\": { \"type\": \"fashionInspirationCurvedArrow\" },\n          \"id\": \"3516128e-5c41-4714-af52-8a413910ac5f\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9bdb1a9f-83bc-46aa-93be-095e434f011e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3516128e-5c41-4714-af52-8a413910ac5f\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0dd58d27-0c5b-4971-99e3-df719d00d01c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e793daec-aa72-4fb3-bdd8-4901acbdc5e3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 219,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4601a3dc-5728-4387-bff3-82d434387b7a\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 55.66433566433566,\n          \"focalY\": 45.45454545454545,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:47:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page5_img1.jpg\",\n            \"width\": 1625,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Silver colored m lapel pin\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0f1522\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.5\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">I love the small notch above the pocket.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 84,\n          \"y\": 526,\n          \"width\": 254,\n          \"height\": 64,\n          \"id\": \"fa91373f-948b-43bd-87ba-d604553ff52e\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 165,\n          \"lockAspectRatio\": true,\n          \"x\": 247,\n          \"y\": 340,\n          \"width\": 81,\n          \"height\": 200,\n          \"sticker\": { \"type\": \"fashionInspirationCurvedArrow\" },\n          \"id\": \"44ec12e8-6519-4cbe-b34d-0ca38b0cc479\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"75c6170e-c1e2-4074-8a45-50b2ab7a0484\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"44ec12e8-6519-4cbe-b34d-0ca38b0cc479\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f0b64737-b83c-402f-903e-73fc372fd629\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ec19f79d-0c1c-41da-ac2b-3ecac1e08241\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4e60d4d6-cc5b-4269-b231-54bf43efcd3d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"x\": -8,\n          \"y\": 139,\n          \"width\": 428,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"225b0d4a-6cbb-4322-bea6-f7ad6b1d7b9b\",\n          \"type\": \"shape\",\n          \"groupId\": \"a77dbd2a-c5fe-46a5-bc6a-539eadc581b6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:48:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page6_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Black suit jacket hanged on wall\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#1b1b1b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 427,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"db8bda6a-d0c6-40cb-a6ea-5e77d535e3ad\",\n          \"type\": \"image\",\n          \"groupId\": \"a77dbd2a-c5fe-46a5-bc6a-539eadc581b6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 424,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ed473526-b6b1-4786-8232-12056c713093\",\n          \"type\": \"shape\",\n          \"groupId\": \"6117164f-004c-439e-a6dc-8c09b554cc52\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Alexander McQueen Suit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 434,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"62c397f1-a799-42b7-9c14-798e251f6ce5\",\n          \"type\": \"text\",\n          \"groupId\": \"6117164f-004c-439e-a6dc-8c09b554cc52\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Single-breasted wool mohair jacket in navy with a signature Alexander McQueen shoulder.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 466,\n          \"width\": 326,\n          \"height\": 70,\n          \"id\": \"3dfd5caa-7d3d-467d-b9aa-68592f942cfb\",\n          \"type\": \"text\",\n          \"groupId\": \"6117164f-004c-439e-a6dc-8c09b554cc52\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 23,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">View Product</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 40,\n            \"topRight\": 40,\n            \"bottomRight\": 40,\n            \"bottomLeft\": 40\n          },\n          \"width\": 164,\n          \"height\": 49,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": \"\",\n            \"desc\": \"https://www.google.com/\"\n          },\n          \"id\": \"8f710eb8-e301-4ea3-95f9-6fded111b4d4\",\n          \"x\": 124,\n          \"y\": 567,\n          \"type\": \"text\",\n          \"groupId\": \"b8b334b7-4e00-4169-a229-8e8ee5094f13\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 14,\n          \"height\": 18,\n          \"sticker\": { \"type\": \"dayInTheLifeBag\" },\n          \"id\": \"c3c59637-b5e6-4f00-9add-08ea41390357\",\n          \"x\": 152,\n          \"y\": 581,\n          \"type\": \"sticker\",\n          \"groupId\": \"b8b334b7-4e00-4169-a229-8e8ee5094f13\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"8f710eb8-e301-4ea3-95f9-6fded111b4d4\"],\n          \"id\": \"46f0cf76-9af0-4ca7-9d2d-320216b62c9b\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"c3c59637-b5e6-4f00-9add-08ea41390357\"],\n          \"id\": \"4e626d6c-e408-42e5-a521-a436c75d9bd9\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"08020a59-6d51-436d-a5b1-7013ed256d72\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a77dbd2a-c5fe-46a5-bc6a-539eadc581b6\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6117164f-004c-439e-a6dc-8c09b554cc52\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"b8b334b7-4e00-4169-a229-8e8ee5094f13\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"392046b2-ead8-463a-93bb-b16a7b5a337b\",\n          \"type\": \"image\",\n          \"scale\": 138,\n          \"focalX\": 50,\n          \"focalY\": 62.45471014492754,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:48:57\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page7_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Person wearing black suit jacket and silver-colored watch\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3f302e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 375,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"46539db6-d898-4c96-9764-9d967fe27144\",\n          \"type\": \"shape\",\n          \"groupId\": \"42bb8c26-9d32-42de-beb0-f266bffb4633\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.28em; text-transform: uppercase\\\">Audemars Piguet Royal</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 385,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"d22bc26b-3bbc-4941-9ce4-c02863b2c065\",\n          \"type\": \"text\",\n          \"groupId\": \"42bb8c26-9d32-42de-beb0-f266bffb4633\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">This was one of the first big purchases I made back in the day.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 416,\n          \"width\": 280,\n          \"height\": 97,\n          \"id\": \"0a96aff9-ef00-4302-8751-14a6047d0622\",\n          \"marginOffset\": 2.216796875,\n          \"type\": \"text\",\n          \"groupId\": \"42bb8c26-9d32-42de-beb0-f266bffb4633\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 25,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 15,\n          \"lockAspectRatio\": true,\n          \"width\": 420,\n          \"height\": 437,\n          \"sticker\": { \"type\": \"fashionInspirationCutout\" },\n          \"id\": \"9b3370d0-1194-4a3d-9463-b45810b8b34e\",\n          \"x\": 247,\n          \"y\": -276,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4ee89875-c33d-43c0-8c58-a66fad5cfc5e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"46539db6-d898-4c96-9764-9d967fe27144\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"083cdca7-d69d-4202-956d-fb606201ec38\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b11bd56f-35fc-4937-8454-b4f91977d005\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"42bb8c26-9d32-42de-beb0-f266bffb4633\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 439,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"172f68ce-4141-4e83-ad49-4de7e691a522\",\n          \"type\": \"image\",\n          \"scale\": 159,\n          \"focalX\": 54.60659515809424,\n          \"focalY\": 67.8385080124063,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-21T07:50:01\",\n            \"baseColor\": \"#0d0d0d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1440,\n            \"id\": 0,\n            \"alt\": \"Silver round watch\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">The half skeleton rear is such a beautiful touch.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 74,\n          \"y\": 526,\n          \"width\": 275,\n          \"height\": 64,\n          \"id\": \"5814edb6-ff32-4272-9338-cd0f78489007\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"x\": 223,\n          \"y\": 208,\n          \"width\": 118,\n          \"height\": 293,\n          \"sticker\": { \"type\": \"fashionInspirationCurvedArrow\" },\n          \"id\": \"c5f37608-5f96-4ace-8537-dd2466b88afd\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"355688da-0ab9-4668-9501-80f40b606f6d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c5f37608-5f96-4ace-8537-dd2466b88afd\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"cd0a78de-abd5-49f6-b824-9437bb3294f7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b5479eab-8fde-46f1-8051-2121a3564e90\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"931f583f-a7f1-47b9-bf30-325dbe7b00ec\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"x\": -8,\n          \"y\": 139,\n          \"width\": 428,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"186b0051-3a56-4b26-bd98-cc0a611870cd\",\n          \"type\": \"shape\",\n          \"groupId\": \"ce2fd4a4-d937-4046-ae91-7a6fd18d3eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:51:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page9_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Round silver-colored Fossil chronograph watch at 9:22 with brown leather band\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c3c0c3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 427,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5429e517-c1d1-403d-97e8-9f83ae0011b0\",\n          \"type\": \"image\",\n          \"groupId\": \"ce2fd4a4-d937-4046-ae91-7a6fd18d3eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 424,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b1759895-587a-4e1e-ba46-02ad306efbb2\",\n          \"type\": \"shape\",\n          \"groupId\": \"1fcf46dd-793d-4182-a813-52b35ebac09a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Audemars Piguet Royal</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 434,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"aa257efc-2303-44c8-af72-be3660a213e1\",\n          \"type\": \"text\",\n          \"groupId\": \"1fcf46dd-793d-4182-a813-52b35ebac09a\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Steel case, octagonal bezel, &amp; integrated bracelet. The Royal Oak overturned the prevailing codes in 1972 and took its rightful place as a true modern icon.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 466,\n          \"width\": 326,\n          \"height\": 90,\n          \"id\": \"b9886cb2-caa8-45c9-9aa7-62245adb5947\",\n          \"type\": \"text\",\n          \"groupId\": \"1fcf46dd-793d-4182-a813-52b35ebac09a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 23,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">View Product</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 40,\n            \"topRight\": 40,\n            \"bottomRight\": 40,\n            \"bottomLeft\": 40\n          },\n          \"width\": 164,\n          \"height\": 49,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": \"\",\n            \"desc\": \"https://www.google.com/\"\n          },\n          \"id\": \"a025b957-94e1-4c43-b05b-e621764e4506\",\n          \"x\": 124,\n          \"y\": 567,\n          \"type\": \"text\",\n          \"groupId\": \"1f3a3691-ee30-4811-912f-34edfb8a2391\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 14,\n          \"height\": 18,\n          \"sticker\": { \"type\": \"dayInTheLifeBag\" },\n          \"id\": \"65e6c375-bb46-48d0-9384-303c013b13aa\",\n          \"x\": 152,\n          \"y\": 581,\n          \"type\": \"sticker\",\n          \"groupId\": \"1f3a3691-ee30-4811-912f-34edfb8a2391\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"a025b957-94e1-4c43-b05b-e621764e4506\"],\n          \"id\": \"74c1784b-e272-484a-80f2-80521c175c07\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"65e6c375-bb46-48d0-9384-303c013b13aa\"],\n          \"id\": \"88549632-c010-4c5b-91b5-870f33ba532c\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"48f07468-6de4-4641-a0c9-ce1c61ad8007\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"1fcf46dd-793d-4182-a813-52b35ebac09a\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ce2fd4a4-d937-4046-ae91-7a6fd18d3eeb\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1f3a3691-ee30-4811-912f-34edfb8a2391\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"bfe4880d-8c11-44c2-97dd-666a51c5cc38\",\n          \"type\": \"image\",\n          \"scale\": 165,\n          \"focalX\": 45.02840909090908,\n          \"focalY\": 67.23484848484848,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:52:16\",\n            \"baseColor\": \"#1f2014\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man carrying bag outdoors\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 375,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"18a13d6c-d42c-425d-ae61-a97bde88d00c\",\n          \"type\": \"shape\",\n          \"groupId\": \"e0b53217-5919-4086-8d25-603b0515e2eb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.28em; text-transform: uppercase\\\">Drake's Classic Scarf</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 385,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"9a940f3f-ea92-4809-8bb7-8c225f8eba7f\",\n          \"type\": \"text\",\n          \"groupId\": \"e0b53217-5919-4086-8d25-603b0515e2eb\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">This is something of a Drake's classic - great with almost any outfit, dressy or casual.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 416,\n          \"width\": 272,\n          \"height\": 130,\n          \"id\": \"22eb5b33-5c83-40b7-8e9f-67d9d7689e3f\",\n          \"type\": \"text\",\n          \"groupId\": \"e0b53217-5919-4086-8d25-603b0515e2eb\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 276,\n          \"y\": 309,\n          \"width\": 50,\n          \"height\": 50,\n          \"sticker\": { \"type\": \"fitnessCTA\" },\n          \"id\": \"8dddd564-8c46-461c-b170-f9d354b577c2\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"47ec07e1-0d59-4cbd-9d60-b158d3be5362\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"18a13d6c-d42c-425d-ae61-a97bde88d00c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"294789d9-c836-4b4c-a9eb-3fc746eb59dd\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"8dddd564-8c46-461c-b170-f9d354b577c2\"],\n          \"scale\": 0.2,\n          \"iterations\": 7,\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"bc660620-3f74-44a2-9156-0a9a544a2359\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6635d043-f443-4468-99cd-06a9069b3eb2\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"e0b53217-5919-4086-8d25-603b0515e2eb\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"a866bf19-9011-49c3-89dc-806235c5d35d\",\n          \"type\": \"image\",\n          \"scale\": 138,\n          \"focalX\": 32.846467391304344,\n          \"focalY\": 48.75452898550725,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:53:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Person in black suit holding brown leather bag\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#43332d\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -150,\n          \"lockAspectRatio\": true,\n          \"x\": 281,\n          \"y\": 341,\n          \"width\": 81,\n          \"height\": 192,\n          \"sticker\": { \"type\": \"fashionInspirationCurvedArrow\" },\n          \"id\": \"985654d2-5cc9-4f77-9d44-33036d1493f7\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">Tom Deitch, makes these scarves by hand in Poland.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 57,\n          \"y\": 499,\n          \"width\": 231,\n          \"height\": 97,\n          \"id\": \"7b28a0de-a67e-470e-bde6-ff116dce396d\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"073f64c3-2722-4677-b649-8db2d0c3d778\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"985654d2-5cc9-4f77-9d44-33036d1493f7\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c91c6cc8-cb05-4044-974a-b0929b93641e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"84d80c14-69fe-4cfd-9cd2-f7b9eae01195\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"71a62f1b-57f0-4dba-8951-6f2947628faf\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"x\": -8,\n          \"y\": 139,\n          \"width\": 428,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbfad111-2910-48bd-b775-09e99eeeeec0\",\n          \"type\": \"shape\",\n          \"groupId\": \"e8b018f2-a0d9-4aff-bf49-a9de6101fcf2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 249, \"b\": 249 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 427,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"243bafa7-b28c-4180-8d76-f8b34beed44b\",\n          \"type\": \"shape\",\n          \"groupId\": \"e8b018f2-a0d9-4aff-bf49-a9de6101fcf2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:54:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page12_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1512,\n            \"id\": 0,\n            \"alt\": \"Black Scarf\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#343737\",\n            \"isExternal\": true\n          },\n          \"x\": 63,\n          \"y\": -43,\n          \"width\": 286,\n          \"height\": 399,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e60a4817-bfc8-44b3-b8a3-7a9535f39927\",\n          \"type\": \"image\",\n          \"groupId\": \"e8b018f2-a0d9-4aff-bf49-a9de6101fcf2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 424,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f1871700-0e62-4afa-8276-f217e1d31769\",\n          \"type\": \"shape\",\n          \"groupId\": \"1c4fb96c-1253-4c91-9142-9bf9bd28814a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Drake's Classic Scarf</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 434,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"caff37ab-e626-4a4c-be33-7a7fdb126585\",\n          \"type\": \"text\",\n          \"groupId\": \"1c4fb96c-1253-4c91-9142-9bf9bd28814a\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">The beautiful, printed spot wool and silk 70% wool 30% silk, printed in Italy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 466,\n          \"width\": 303,\n          \"height\": 46,\n          \"id\": \"89296d0a-8b33-490e-bd8d-b2c063311175\",\n          \"type\": \"text\",\n          \"groupId\": \"1c4fb96c-1253-4c91-9142-9bf9bd28814a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 23,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 200; color: #fff\\\">View Product</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 40,\n            \"topRight\": 40,\n            \"bottomRight\": 40,\n            \"bottomLeft\": 40\n          },\n          \"width\": 164,\n          \"height\": 49,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": \"\",\n            \"desc\": \"https://www.google.com/\"\n          },\n          \"id\": \"e81ccabd-d745-4faa-afc8-36bb402755a0\",\n          \"x\": 124,\n          \"y\": 567,\n          \"type\": \"text\",\n          \"groupId\": \"b0ff9971-6a9c-4929-aee9-57af73bf12db\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 14,\n          \"height\": 18,\n          \"sticker\": { \"type\": \"dayInTheLifeBag\" },\n          \"id\": \"0c6e3167-bed0-4a8c-ba3e-b9ec910ebaf6\",\n          \"x\": 152,\n          \"y\": 581,\n          \"type\": \"sticker\",\n          \"groupId\": \"b0ff9971-6a9c-4929-aee9-57af73bf12db\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"e81ccabd-d745-4faa-afc8-36bb402755a0\"],\n          \"id\": \"a5a1c9d6-3c34-4fa2-9287-698cb990fed7\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"0c6e3167-bed0-4a8c-ba3e-b9ec910ebaf6\"],\n          \"id\": \"9ce85d7f-95cb-4377-8d21-da9693d0c51c\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"e4ce06eb-05e9-4564-800d-ac932df854e6\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e8b018f2-a0d9-4aff-bf49-a9de6101fcf2\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b0ff9971-6a9c-4929-aee9-57af73bf12db\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1c4fb96c-1253-4c91-9142-9bf9bd28814a\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"34dfed8e-1350-4ec7-8d51-a281cf27939b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 154, \"g\": 74, \"b\": 59 } },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fe06f6dd-cad2-4698-9922-06beb7df2d18\",\n          \"type\": \"shape\",\n          \"groupId\": \"ca603a55-597c-4703-beb0-9b3b9871ffd2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">More style round ups</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 14,\n          \"width\": 318,\n          \"height\": 17,\n          \"id\": \"97878cc7-aa56-40f9-ac92-e8df33daa905\",\n          \"type\": \"text\",\n          \"groupId\": \"ca603a55-597c-4703-beb0-9b3b9871ffd2\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fb813a40-d366-42ac-915d-bdb07abfa09a\",\n          \"x\": 56,\n          \"y\": 102,\n          \"type\": \"shape\",\n          \"groupId\": \"4f40115e-bafa-4f02-8818-0f9164b1b786\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Marky Park from Hypebeast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 192,\n          \"y\": 159,\n          \"width\": 147,\n          \"height\": 46,\n          \"id\": \"24618714-2491-426d-bd02-6adbcdc7f917\",\n          \"type\": \"text\",\n          \"groupId\": \"4f40115e-bafa-4f02-8818-0f9164b1b786\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:55:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page13_img1.jpg\",\n            \"width\": 576,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man walking on road while holding bag during daytime\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c9c3be\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 93,\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3ece57ed-0dc2-4a83-9259-9c39a8400931\",\n          \"type\": \"image\",\n          \"groupId\": \"4f40115e-bafa-4f02-8818-0f9164b1b786\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; letter-spacing: 0.28em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 17,\n          \"id\": \"26241101-e136-4646-b0f9-f60a1657e10d\",\n          \"x\": 192,\n          \"y\": 138,\n          \"type\": \"text\",\n          \"groupId\": \"4f40115e-bafa-4f02-8818-0f9164b1b786\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a649b052-f7ef-4cf1-96f5-ae81bbe9814e\",\n          \"x\": 271,\n          \"y\": 280,\n          \"type\": \"shape\",\n          \"groupId\": \"31a4a804-7624-492e-9632-cc880e35e988\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:55:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page13_img2.jpg\",\n            \"width\": 520,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Woman in yellow tracksuit standing on basketball court side\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#a9d9d8\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5ae1181e-7f2d-4dc7-9c5f-1f9c7b1c92e6\",\n          \"x\": 261,\n          \"y\": 271,\n          \"type\": \"image\",\n          \"groupId\": \"31a4a804-7624-492e-9632-cc880e35e988\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; letter-spacing: 0.28em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 16,\n          \"id\": \"f010b1f4-de52-4231-80af-152a3746ba0b\",\n          \"x\": 110,\n          \"y\": 315,\n          \"type\": \"text\",\n          \"groupId\": \"31a4a804-7624-492e-9632-cc880e35e988\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Zenraya’s Summer Looks</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 121,\n          \"height\": 46,\n          \"id\": \"51dceca8-dac3-440b-ac74-e0293f535484\",\n          \"x\": 110,\n          \"y\": 336,\n          \"type\": \"text\",\n          \"groupId\": \"31a4a804-7624-492e-9632-cc880e35e988\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 99, \"b\": 81 } },\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b3b735d1-b218-4249-84ae-820a3721d799\",\n          \"x\": 57,\n          \"y\": 459,\n          \"type\": \"shape\",\n          \"groupId\": \"4cfab88f-ce4c-4c2a-b56d-09fcf15b73b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:55:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-inspiration/page13_img3.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Pair of brown leather dress shoes with box\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c5b7b0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 104,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"26d690b7-14f1-4ee1-9779-2a9b1f829345\",\n          \"x\": 47,\n          \"y\": 449,\n          \"type\": \"image\",\n          \"groupId\": \"4cfab88f-ce4c-4c2a-b56d-09fcf15b73b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200; letter-spacing: 0.28em\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 16,\n          \"id\": \"661f8451-8212-4cdd-b4cc-42a6d6f538e5\",\n          \"x\": 192,\n          \"y\": 493,\n          \"type\": \"text\",\n          \"groupId\": \"4cfab88f-ce4c-4c2a-b56d-09fcf15b73b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Seven Work from Home Looks</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 147,\n          \"height\": 46,\n          \"id\": \"3266dd8d-7b77-4c72-afd3-599d2b7b9813\",\n          \"x\": 192,\n          \"y\": 514,\n          \"type\": \"text\",\n          \"groupId\": \"4cfab88f-ce4c-4c2a-b56d-09fcf15b73b5\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"712c197d-7176-40b8-8246-1df32be6204d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3ece57ed-0dc2-4a83-9259-9c39a8400931\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e612f797-1a08-4184-b3f1-a05a030d16b2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5ae1181e-7f2d-4dc7-9c5f-1f9c7b1c92e6\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"c76b85d6-ca39-4b6c-bcc2-0789eb1767bc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"26d690b7-14f1-4ee1-9779-2a9b1f829345\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"a693562d-91fc-4b2b-b162-3755bff421f9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fb813a40-d366-42ac-915d-bdb07abfa09a\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"43009803-a932-4ed1-875e-c95cc0396325\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"24618714-2491-426d-bd02-6adbcdc7f917\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8d8457e9-5da8-4362-9331-3cdb16e0fb09\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"26241101-e136-4646-b0f9-f60a1657e10d\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9470288e-a535-49b2-b7eb-f974c6226962\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a649b052-f7ef-4cf1-96f5-ae81bbe9814e\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"4dd0e39d-8a78-41cc-984a-8b1b1efb1ebb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f010b1f4-de52-4231-80af-152a3746ba0b\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"8938c785-1b37-4d7d-abad-1c4ec7b5d281\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"51dceca8-dac3-440b-ac74-e0293f535484\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"64847aba-0953-495a-b95c-b510b92458c5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b3b735d1-b218-4249-84ae-820a3721d799\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"4093a4ad-ebd5-47ba-8228-8f22d874d149\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"661f8451-8212-4cdd-b4cc-42a6d6f538e5\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"2a9363ac-0bed-4ba2-86d9-4ee0f842dee4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3266dd8d-7b77-4c72-afd3-599d2b7b9813\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"2580a9b9-9b95-405d-9e45-a820260f327e\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"4f40115e-bafa-4f02-8818-0f9164b1b786\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"31a4a804-7624-492e-9632-cc880e35e988\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4cfab88f-ce4c-4c2a-b56d-09fcf15b73b5\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ca603a55-597c-4703-beb0-9b3b9871ffd2\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-on-the-go/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-on-the-go/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'fashion-on-the-go',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Fashion On The Go', 'template name', 'web-stories'),\n  tags: [\n    _x('Clothing', 'template keyword', 'web-stories'),\n    _x('Sparkle', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Cream', 'color', 'web-stories'),\n      color: '#ffece3',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Orange', 'color', 'web-stories'),\n      color: '#ff3000',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#212121',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gray', 'color', 'web-stories'),\n      color: '#858280',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'The elegant serif Fashion template works well for New York Fashion Week highlights, high fashion shopping guides and accessory trends.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-on-the-go/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fashion-on-the-go/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"95a99f3f-ccbd-4b61-b676-25a8dec8577b\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 65,\n          \"y\": 69,\n          \"width\": 347,\n          \"height\": 456,\n          \"type\": \"image\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51, \"a\": 0 } },\n          \"scale\": 170,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6978fba6-59ce-46bc-b862-92ce2b9795bb\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#252521\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page1_hero.jpg\",\n            \"width\": 220,\n            \"height\": 297,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page1_hero\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": -180,\n          \"y\": 216,\n          \"width\": 580,\n          \"height\": 192,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.96,\n          \"textAlign\": \"left\",\n          \"id\": \"a32c17e0-a46b-4821-bbdb-8dc064ac097d\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: -0.01em; text-transform: uppercase\\\">Fashion</span>\\n<span style=\\\"color: #ff3000; letter-spacing: -0.01em; text-transform: uppercase\\\">on the go</span>\",\n          \"fontSize\": 100,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#040404\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page1_logo-generic.png\",\n            \"width\": 32,\n            \"height\": 10,\n            \"id\": 0,\n            \"alt\": \"page1_logo-generic\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 27,\n          \"y\": 30,\n          \"width\": 75,\n          \"height\": 22,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"f18e9cbe-088b-4366-99a7-3eec4b8d4c66\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"1f51fc35-c1d6-46ea-9580-b38672124162\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"6a6e5101-6d92-4c64-b1b6-124cf9cce0b1\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 18,\n          \"y\": 520,\n          \"width\": 229,\n          \"height\": 28,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"61d23551-31e3-4aad-ac15-b8fc5e4be2ec\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">— Anonymous</span>\",\n          \"fontSize\": 28,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 18,\n          \"y\": 11,\n          \"width\": 371,\n          \"height\": 250,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"id\": \"d773925c-2f95-44c0-9b0e-0743d45476f2\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">“When we dress well, we naturally boost our confidence”</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 216,\n          \"y\": 278,\n          \"width\": 204,\n          \"height\": 270,\n          \"sticker\": { \"type\": \"fashionStarburstWithArrow\" },\n          \"id\": \"9c4ccb62-0860-456c-b949-af0ffd4eedfa\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9ffb6b02-a02b-4135-95a5-1a44b2d1dfbe\",\n          \"targets\": [\"9c4ccb62-0860-456c-b949-af0ffd4eedfa\"],\n          \"type\": \"zoom\",\n          \"zoomFrom\": 2,\n          \"zoomTo\": 1,\n          \"duration\": 1000,\n          \"delay\": 0,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"outQuint\",\n          \"fill\": \"forwards\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"c0ee0297-3fb3-4410-92d2-1b50a6caea2f\",\n          \"targets\": [\"9c4ccb62-0860-456c-b949-af0ffd4eedfa\"],\n          \"type\": \"move\",\n          \"overflowHidden\": false,\n          \"offsetX\": \"-35\",\n          \"offsetY\": \"160\",\n          \"duration\": 1000,\n          \"delay\": 0,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"inOutSine\",\n          \"fill\": \"forwards\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"c9dc2105-28d2-45eb-9c2a-c0e071c8260e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d773925c-2f95-44c0-9b0e-0743d45476f2\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fbbcd2a3-7b99-406c-8297-f1ef1334e0eb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"61d23551-31e3-4aad-ac15-b8fc5e4be2ec\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"25e55ea8-2912-4471-af46-d278da177382\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9c4ccb62-0860-456c-b949-af0ffd4eedfa\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"cda99980-6722-4141-9616-25e523a98722\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"589a577a-fcac-49cf-964e-96e092ecf511\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -55,\n          \"y\": -60,\n          \"width\": 442,\n          \"height\": 678,\n          \"type\": \"image\",\n          \"opacity\": 95,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 170,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6cca5fcd-80d5-4181-b9e6-2979b80c2b99\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#6e472e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page3_bg.jpg\",\n            \"width\": 220,\n            \"height\": 261,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 0,\n          \"y\": 330,\n          \"width\": 412,\n          \"height\": 290,\n          \"type\": \"shape\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 33, \"g\": 33, \"b\": 33, \"a\": 0.75 },\n                \"position\": 0\n              },\n              { \"color\": { \"r\": 33, \"g\": 33, \"b\": 33, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6fc327a4-8e5d-48e8-8285-899267ec1183\"\n        },\n        {\n          \"x\": 8,\n          \"y\": -13,\n          \"width\": 441,\n          \"height\": 510,\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.96,\n          \"textAlign\": \"left\",\n          \"id\": \"792955f1-699b-499a-bf65-d88b60d613af\",\n          \"content\": \"<span style=\\\"color: #ffece3; text-transform: uppercase\\\">s/s prev</span>\\n<span style=\\\"color: #ffece3; text-transform: uppercase\\\">iew</span>\",\n          \"fontSize\": 178,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 16,\n          \"y\": 531,\n          \"width\": 239,\n          \"height\": 48,\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"type\": \"text\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"id\": \"9bd1600f-5d9d-4beb-bdfb-817b118a8852\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.0002em\\\"><span style=\\\"color: rgba(255, 236, 227, 1); text-transform: uppercase\\\">Preview the latest looks of the season</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"af78ffa4-4115-4ac7-8d16-495af9919922\",\n          \"targets\": [\"6cca5fcd-80d5-4181-b9e6-2979b80c2b99\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 1000,\n          \"delay\": 800,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"6b927fd7-198e-4567-8903-90d81e409cad\",\n          \"targets\": [\"792955f1-699b-499a-bf65-d88b60d613af\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 1000,\n          \"delay\": 800,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"26a2ee53-e78a-4e39-844c-e14be610b8ea\",\n          \"targets\": [\"9bd1600f-5d9d-4beb-bdfb-817b118a8852\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 1000,\n          \"delay\": 800,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"3ebbefbe-89af-4773-80aa-480b4501af58\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"792955f1-699b-499a-bf65-d88b60d613af\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"392f4102-2fee-49e3-8247-2913f06aabb9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9bd1600f-5d9d-4beb-bdfb-817b118a8852\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 700\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"99ae5466-855b-4d84-9379-c401969ade38\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 33, \"b\": 33 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"178de0c9-6a64-450e-bc47-5f38e6884665\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 17,\n          \"y\": 13,\n          \"width\": 143,\n          \"height\": 74,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"64b41c08-0817-4b98-aa55-0aaa9ea205e8\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">MJ</span>\\n<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">Kepler</span>\",\n          \"fontSize\": 37,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"8bb349c8-ad53-4610-bee5-f5146f5c95f7\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 17,\n          \"y\": 97,\n          \"width\": 143,\n          \"height\": 18,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a2a90d9e-2bce-44d3-95cd-77f33c55e144\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.02em; text-transform: uppercase\\\">A Rich History</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"8bb349c8-ad53-4610-bee5-f5146f5c95f7\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 122,\n          \"y\": 225,\n          \"width\": 273,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"8c45242f-9941-4fdc-b5de-3339a36585bf\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">Monogram Canvas</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"b96485e7-6ed3-493e-adfd-61a35b9e40f7\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 132,\n          \"y\": 66,\n          \"width\": 263,\n          \"height\": 171,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"acb2ccae-1faf-4192-bf28-19614324ed25\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: -0.01em\\\">1896</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"b96485e7-6ed3-493e-adfd-61a35b9e40f7\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 18,\n          \"y\": 251,\n          \"width\": 131,\n          \"height\": 85,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e6ee6ead-43e0-45a4-aeef-1bcb7c914fcd\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: -0.01em\\\">1901</span>\",\n          \"fontSize\": 66,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"4ed447fb-ab58-4857-af1f-1ff3633793c0\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 19,\n          \"y\": 329,\n          \"width\": 195,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"2c548d81-abe2-4f74-9292-9910382fb293\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">The Hobo Bag</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"4ed447fb-ab58-4857-af1f-1ff3633793c0\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 264,\n          \"y\": 353,\n          \"width\": 131,\n          \"height\": 85,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"9156bf8e-3cdd-41fb-99c2-f6206f95ec1b\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: -0.01em\\\">1930</span>\",\n          \"fontSize\": 66,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"cc808f1a-5fa4-4c81-a1bb-fd6219b32ee9\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 160,\n          \"y\": 433,\n          \"width\": 230,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"78ef1efb-0ca7-4067-9a38-a646987fd096\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">The Kepler Bag</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"cc808f1a-5fa4-4c81-a1bb-fd6219b32ee9\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 20,\n          \"y\": 563,\n          \"width\": 272,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"f5593520-3bb3-49d6-bfbd-c9fe2af7ee51\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">The Stargaze Bag</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"10e11545-6cef-4cdb-8693-f851c5d575cb\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 18,\n          \"y\": 451,\n          \"width\": 195,\n          \"height\": 130,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a10cc4c5-ee6f-43dd-a391-ce72a14a43b7\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">1966</span>\",\n          \"fontSize\": 100,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"10e11545-6cef-4cdb-8693-f851c5d575cb\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f819040c-2f1e-49d3-9462-fcec73f81eda\",\n          \"targets\": [\"a2a90d9e-2bce-44d3-95cd-77f33c55e144\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 400,\n          \"delay\": 1100,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"91628b90-9245-48ab-90d6-fa552967379b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"64b41c08-0817-4b98-aa55-0aaa9ea205e8\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0824703c-eaac-4ef8-ac17-66fcaa02fe06\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a2a90d9e-2bce-44d3-95cd-77f33c55e144\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"af25ea7f-6392-44df-ab3f-6a447a33f753\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"acb2ccae-1faf-4192-bf28-19614324ed25\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1300,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"20fd999a-92df-4fb9-9812-07fdc6b5e7f4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8c45242f-9941-4fdc-b5de-3339a36585bf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1300,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"8f2f0381-8218-4c4f-878f-05808d329f68\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e6ee6ead-43e0-45a4-aeef-1bcb7c914fcd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"950808a8-3247-430f-883a-cca0b80e08cb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2c548d81-abe2-4f74-9292-9910382fb293\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"1b464ec7-5803-4a9c-8da9-768467523e6e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9156bf8e-3cdd-41fb-99c2-f6206f95ec1b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1300,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"6a2bddee-5d43-4039-99e0-7fe0e6480bbd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"78ef1efb-0ca7-4067-9a38-a646987fd096\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1300,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"e5aa4d19-0282-45c0-8fea-0eb548764137\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a10cc4c5-ee6f-43dd-a391-ce72a14a43b7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1050\n        },\n        {\n          \"id\": \"71bd6195-6d9f-42d6-8745-5762a7324a76\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f5593520-3bb3-49d6-bfbd-c9fe2af7ee51\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1050\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"22e2ed54-fa70-43c5-81e8-81ad672bd6ad\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"b96485e7-6ed3-493e-adfd-61a35b9e40f7\": {\n          \"name\": \"1896\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4ed447fb-ab58-4857-af1f-1ff3633793c0\": {\n          \"name\": \"1901\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"cc808f1a-5fa4-4c81-a1bb-fd6219b32ee9\": {\n          \"name\": \"1930\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"10e11545-6cef-4cdb-8693-f851c5d575cb\": {\n          \"name\": \"1966\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8bb349c8-ad53-4610-bee5-f5146f5c95f7\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"db53e416-f618-4f22-9043-0e05f05094e1\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -190,\n          \"y\": 396,\n          \"width\": 512,\n          \"height\": 171,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"bad4432f-b82b-4579-bb2d-d9858f7feec2\",\n          \"content\": \"<span style=\\\"color: #ffece3; letter-spacing: -0.01em; text-transform: uppercase\\\">Kepler</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": -395,\n          \"y\": -425,\n          \"width\": 924,\n          \"height\": 171,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"875e2b60-1738-425a-8d7d-95f648bb3af6\",\n          \"content\": \"<span style=\\\"color: rgba(255,236,227,0.35); letter-spacing: -0.01em; text-transform: uppercase\\\">The Handbag</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 176,\n          \"y\": 464,\n          \"width\": 131,\n          \"height\": 27,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"f19846b4-b351-4607-a8f9-c7e69ff7a6f3\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: 0.02em; text-transform: uppercase\\\">MJ Kepler</span>\",\n          \"fontSize\": 21,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 176,\n          \"y\": 493,\n          \"width\": 216,\n          \"height\": 50,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"61b42950-25ca-46cf-83bf-1e04cdc0cd94\",\n          \"content\": \"<span style=\\\"color: #ffece3; letter-spacing: 0.02em; text-transform: uppercase\\\">The Kepler Handbag $450</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 177,\n          \"y\": 578,\n          \"width\": 131,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"67777589-1517-4a00-9e95-11e262bf02dd\",\n          \"content\": \"<span style=\\\"color: #ffece3; letter-spacing: 0.01em; text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#dd4546\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page5_handbag-alt.png\",\n            \"width\": 272,\n            \"height\": 251,\n            \"id\": 0,\n            \"alt\": \"page5_handbag-alt\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 164,\n          \"y\": 15,\n          \"width\": 439,\n          \"height\": 405,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"f7d6b29f-d15e-4ac3-8372-bd389741dd92\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 288,\n          \"y\": 582,\n          \"width\": 25,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"fashionArrowLight\" },\n          \"id\": \"999215b6-48b8-4396-88fc-60d44301d244\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9299f52a-5cd7-42d7-a917-adec6d7d04c9\",\n          \"targets\": [\"f19846b4-b351-4607-a8f9-c7e69ff7a6f3\"],\n          \"type\": \"move\",\n          \"overflowHidden\": false,\n          \"offsetX\": 0,\n          \"offsetY\": \"40px\",\n          \"duration\": 1200,\n          \"delay\": 600,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"outQuint\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"7a895ca2-b447-4533-9b09-99baaf156878\",\n          \"targets\": [\"61b42950-25ca-46cf-83bf-1e04cdc0cd94\"],\n          \"type\": \"move\",\n          \"overflowHidden\": false,\n          \"offsetX\": 0,\n          \"offsetY\": \"40px\",\n          \"duration\": 1200,\n          \"delay\": 600,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"outQuint\",\n          \"fill\": \"both\",\n          \"iterations\": 1\n        },\n        {\n          \"id\": \"44c0d3d9-2783-43e2-a4af-d76df046bd12\",\n          \"targets\": [\"f19846b4-b351-4607-a8f9-c7e69ff7a6f3\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 600,\n          \"delay\": 700,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\"\n        },\n        {\n          \"id\": \"284fcc81-c5f5-48bc-ad32-64827270508e\",\n          \"targets\": [\"61b42950-25ca-46cf-83bf-1e04cdc0cd94\"],\n          \"type\": \"fade\",\n          \"fadeFrom\": 0,\n          \"fadeTo\": 1,\n          \"duration\": 600,\n          \"delay\": 700,\n          \"direction\": \"normal\",\n          \"easingPreset\": \"linear\",\n          \"fill\": \"both\"\n        },\n        {\n          \"id\": \"6a38d93d-4298-47f2-8682-4c5142803dde\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"67777589-1517-4a00-9e95-11e262bf02dd\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 1650\n        },\n        {\n          \"id\": \"00b49281-be7f-4fab-afa6-a8f7f61b7ee8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"999215b6-48b8-4396-88fc-60d44301d244\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 1650\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"06f93f32-41a9-4fcd-9d03-08ea29f591e4\",\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 33, \"b\": 33 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"dc3c80d7-8757-4231-826a-0d0c34f6e15e\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 15,\n          \"y\": -1,\n          \"width\": 381,\n          \"height\": 153,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"735394cc-0da6-479c-951d-14579f0766ef\",\n          \"content\": \"<span style=\\\"color: #ff3000; letter-spacing: -0.01em; text-transform: uppercase\\\">Top 5</span>\\n<span style=\\\"color: #ff3000; letter-spacing: -0.01em; text-transform: uppercase\\\">Collections</span>\\n<span style=\\\"color: #ff3000; letter-spacing: -0.01em; text-transform: uppercase\\\">this Season</span>\",\n          \"fontSize\": 51,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 204,\n          \"width\": 254,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ecfb31af-00a8-4533-b86a-e268e7b2a573\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">MJ Kepler</span>\",\n          \"fontSize\": 48,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"39871719-16d5-4d12-8eb2-f24044c9ff90\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 255,\n          \"y\": 182,\n          \"width\": 35,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"3873fcaf-3c89-43dd-ba61-47bfed747b3e\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">1</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"39871719-16d5-4d12-8eb2-f24044c9ff90\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 242,\n          \"y\": 175,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"fdc527dd-e6f2-4524-a9d2-3310a15372c7\",\n          \"groupId\": \"39871719-16d5-4d12-8eb2-f24044c9ff90\"\n        },\n        {\n          \"x\": 180,\n          \"y\": 294,\n          \"width\": 170,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"f40e6fac-12c9-4259-a5af-8de9d1fd1c64\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">Jardin</span>\",\n          \"fontSize\": 48,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"c94d8d78-fa72-4857-bc29-845b17b529b4\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 164,\n          \"y\": 271,\n          \"width\": 32,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"e614554a-4201-4bdd-9ced-c5fe97c758c8\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">2</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"c94d8d78-fa72-4857-bc29-845b17b529b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 150,\n          \"y\": 263,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"1c4e8466-f929-4200-820a-26881a9b613e\",\n          \"groupId\": \"c94d8d78-fa72-4857-bc29-845b17b529b4\"\n        },\n        {\n          \"x\": 15,\n          \"y\": 382,\n          \"width\": 296,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"dc565020-6358-44d9-9aac-a8eb90e76415\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">Rick Marks</span>\",\n          \"fontSize\": 48,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"f8582406-83b5-49e1-9c02-e3ae3ac5cacd\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 289,\n          \"y\": 360,\n          \"width\": 43,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"53f8e685-93b5-4971-bb76-03d52602eb47\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">3</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"f8582406-83b5-49e1-9c02-e3ae3ac5cacd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 280,\n          \"y\": 353,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"d54dbea3-9271-4b1f-84cc-9d6611d2e105\",\n          \"groupId\": \"f8582406-83b5-49e1-9c02-e3ae3ac5cacd\"\n        },\n        {\n          \"x\": 107,\n          \"y\": 464,\n          \"width\": 136,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"d6fea8bd-8f0a-414b-a845-722d436a6d43\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">Prag</span>\",\n          \"fontSize\": 48,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"fb573ce0-4aee-46a6-ab7b-acfeb578b2c2\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 82,\n          \"y\": 440,\n          \"width\": 51,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c8f479d6-429d-4ea4-93e8-ce8dfb37a5d5\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">4</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"fb573ce0-4aee-46a6-ab7b-acfeb578b2c2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 77,\n          \"y\": 434,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"8e3a20f9-294c-4030-ab03-930f372372f5\",\n          \"groupId\": \"fb573ce0-4aee-46a6-ab7b-acfeb578b2c2\"\n        },\n        {\n          \"x\": 71,\n          \"y\": 554,\n          \"width\": 251,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7726e175-d97f-42ed-bb2e-a581f4135332\",\n          \"content\": \"<span style=\\\"color: #212121; text-transform: uppercase\\\">Rag’n Tag</span>\",\n          \"fontSize\": 48,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"1df9f87e-137c-4f60-a4d7-1c0a2da19247\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 311,\n          \"y\": 530,\n          \"width\": 42,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"175d2727-d683-4601-8405-f0a2ee56a654\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">5</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"1df9f87e-137c-4f60-a4d7-1c0a2da19247\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 302,\n          \"y\": 524,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"9945ab8f-4235-4ced-a414-aed99e981653\",\n          \"groupId\": \"1df9f87e-137c-4f60-a4d7-1c0a2da19247\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"57a3b17c-3964-4fcc-81af-8d1d3f7d3d62\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"735394cc-0da6-479c-951d-14579f0766ef\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"feec9889-01ac-4c59-91c7-c621270645ec\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ecfb31af-00a8-4533-b86a-e268e7b2a573\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"0a4f538d-2958-46de-9dcb-eb812178c40f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3873fcaf-3c89-43dd-ba61-47bfed747b3e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"423a4e2f-38f1-4ef1-a378-8c6286cb5831\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e614554a-4201-4bdd-9ced-c5fe97c758c8\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"c2348094-71a9-4964-84bf-8b9ed4fd494a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f40e6fac-12c9-4259-a5af-8de9d1fd1c64\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"bc13080e-fee7-4163-80d9-9a417db47443\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"53f8e685-93b5-4971-bb76-03d52602eb47\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"9038c797-9630-4edc-98f8-145a75c35231\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dc565020-6358-44d9-9aac-a8eb90e76415\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"8af0df0d-5396-430a-bb75-10af9c2852c0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c8f479d6-429d-4ea4-93e8-ce8dfb37a5d5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1050\n        },\n        {\n          \"id\": \"ffccc4f5-a45a-481c-813b-8184c3b892b4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d6fea8bd-8f0a-414b-a845-722d436a6d43\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1050\n        },\n        {\n          \"id\": \"b5c12702-959b-4955-a345-3464e38cc700\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7726e175-d97f-42ed-bb2e-a581f4135332\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"2f810f07-bd81-4454-9a91-466d9ab27e98\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"175d2727-d683-4601-8405-f0a2ee56a654\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"ec69d6fc-df3b-4c11-8242-934a314d442b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9945ab8f-4235-4ced-a414-aed99e981653\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"1e78b49e-c62a-4be8-90c3-df0d24a68745\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8e3a20f9-294c-4030-ab03-930f372372f5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1050\n        },\n        {\n          \"id\": \"b9e245b4-4ee4-4d03-bf36-dd23e3aa73fc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d54dbea3-9271-4b1f-84cc-9d6611d2e105\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"d8a3ac42-611e-4e1c-a5bd-5269129339c2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1c4e8466-f929-4200-820a-26881a9b613e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"c9ff1ff6-dd62-4dc7-a2fb-cb5424f1d0b8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fdc527dd-e6f2-4524-a9d2-3310a15372c7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 900\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e39c480a-e017-4c6e-b48c-4dc1ef00f6ab\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"39871719-16d5-4d12-8eb2-f24044c9ff90\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c94d8d78-fa72-4857-bc29-845b17b529b4\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f8582406-83b5-49e1-9c02-e3ae3ac5cacd\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fb573ce0-4aee-46a6-ab7b-acfeb578b2c2\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1df9f87e-137c-4f60-a4d7-1c0a2da19247\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"68541aa4-d532-4f23-b89e-7dc34882f49b\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 386,\n          \"height\": 426,\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 250,\n          \"focalX\": 46.86957537007236,\n          \"focalY\": 44.74151693332471,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"7ecf93c5-2286-495d-86e9-30cdf0bf32b3\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#b38c81\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page7_hero.jpg\",\n            \"width\": 220,\n            \"height\": 274,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_hero\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 19,\n          \"y\": 400,\n          \"width\": 135,\n          \"height\": 51,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9ce78e9e-7568-45de-bef3-1f9438a11568\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">Prag</span>\",\n          \"fontSize\": 51,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 37,\n          \"y\": 315,\n          \"width\": 75,\n          \"height\": 78,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"8c86903b-0df0-4c1e-a75a-23f1e79522b3\",\n          \"content\": \"<span style=\\\"color: #ff3000\\\">1</span>\",\n          \"fontSize\": 78,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 22,\n          \"y\": 468,\n          \"width\": 363,\n          \"height\": 88,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"43b205d1-376b-4eaf-b493-e55d70f8703e\",\n          \"content\": \"<span style=\\\"color: #212121\\\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam vel dui erat. Curabitur sit amet venenatis felis. In ac ornare lacus. Integer vitae lacus a lectus eleifend finibus.&nbsp;</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 22,\n          \"y\": 616,\n          \"width\": 131,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"46ec18b4-8061-467f-88a0-fb2abd494061\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: 0.01em; text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 9,\n          \"y\": 302,\n          \"width\": 134,\n          \"height\": 134,\n          \"sticker\": { \"type\": \"fashionStarburst\" },\n          \"id\": \"a6cfa456-0bf9-4b93-9e67-c985317b2c46\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 137,\n          \"y\": 620,\n          \"width\": 25,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"fashionArrowDark\" },\n          \"id\": \"bd8f2e42-09cd-4c82-a2fd-a414f6f230e7\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2fa6bf69-df37-4614-aeae-ae96f6912cf7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9ce78e9e-7568-45de-bef3-1f9438a11568\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"88a75cc6-7249-4aed-b16d-f1417797117d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"43b205d1-376b-4eaf-b493-e55d70f8703e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1300,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"050444c7-6097-410f-8147-0c195b051a27\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a879eb64-3b0f-49f7-93de-e63359e6fb1a\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#dbd4cd\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page8_bg.jpg\",\n            \"width\": 220,\n            \"height\": 291,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"scale\": 120,\n          \"focalX\": 54.19913419913419,\n          \"focalY\": 58.333333333333336\n        },\n        {\n          \"x\": -378,\n          \"y\": 182,\n          \"width\": 875,\n          \"height\": 143,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"faf0a8bb-fa80-40b7-b423-80b8bd4cd7a5\",\n          \"content\": \"<span style=\\\"letter-spacing: -0.0001em\\\"><span style=\\\"color: rgba(33, 33, 33, 1); text-transform: uppercase\\\">Get The Look</span></span>\",\n          \"fontSize\": 110,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 157,\n          \"y\": 542,\n          \"width\": 32,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"fashionStarburstSolid\" },\n          \"id\": \"bafc748f-0169-477f-9f44-0281f11c80cc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 32,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"fashionStarburstSolid\" },\n          \"id\": \"67c81c32-d417-42e4-ba62-9254fbffc6cb\",\n          \"x\": 291,\n          \"y\": 381\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 32,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"fashionStarburstSolid\" },\n          \"id\": \"26ca74b2-e9f8-4e5e-a3af-e4e0f8e814f5\",\n          \"x\": 131,\n          \"y\": 110\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f8ddc45f-6216-4e8d-9f09-05f9e01b70c2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"faf0a8bb-fa80-40b7-b423-80b8bd4cd7a5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"838f7a86-70d4-4b42-a708-beabfa1df808\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"bafc748f-0169-477f-9f44-0281f11c80cc\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"67c81c32-d417-42e4-ba62-9254fbffc6cb\"],\n          \"id\": \"91239624-c82a-4cce-b29f-ddf4cbfa7bb5\",\n          \"type\": \"effect-twirl-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"26ca74b2-e9f8-4e5e-a3af-e4e0f8e814f5\"],\n          \"id\": \"9392f400-0fc9-4b01-9daa-88643d2e83b4\",\n          \"type\": \"effect-twirl-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"9e35d123-c307-4474-abd6-bb80a265bb2a\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"452a4add-0155-44fd-8521-042dcbf88594\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"55d761b2-f2ae-4878-8c07-57908d3ab5ca\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 29,\n          \"y\": 5,\n          \"width\": 213,\n          \"height\": 129,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"421f76ac-4c4d-4a44-ad77-622facf57db5\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">More</span>\\n<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">Stories</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 148,\n          \"y\": 188,\n          \"width\": 217,\n          \"height\": 44,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"1043803d-625c-4b7a-a5ad-1cdecfbb1c62\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">How to pull off the</span>\\n<span style=\\\"letter-spacing: -0.01em; text-transform: uppercase\\\">all denim look</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"72c25e55-9c1e-484d-a9a8-7ccf770d91d7\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 30,\n          \"y\": 164,\n          \"width\": 94,\n          \"height\": 94,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"d01ae69c-43cc-455e-bb63-250642795201\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#4b5c68\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page9_item1-cropped.jpg\",\n            \"width\": 43,\n            \"height\": 43,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_item1-cropped\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"72c25e55-9c1e-484d-a9a8-7ccf770d91d7\"\n        },\n        {\n          \"x\": 148,\n          \"y\": 299,\n          \"width\": 249,\n          \"height\": 43,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"87b77bd3-8bc3-44ca-af6f-661e45522a7c\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">The Best Street </span><span style=\\\"letter-spacing: -0.01em; text-transform: uppercase\\\">Styles From NYFW</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"c625b6ba-90fc-4e5a-8a85-a7140b8cdddc\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 30,\n          \"y\": 274,\n          \"width\": 94,\n          \"height\": 94,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 41.611295124593894,\n          \"focalY\": 35.212817670108095,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"c77c788b-cba9-421d-8a9a-2e8b604e99b8\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#bbb8b7\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page9_item2.jpg\",\n            \"width\": 220,\n            \"height\": 331,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_item2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"c625b6ba-90fc-4e5a-8a85-a7140b8cdddc\"\n        },\n        {\n          \"x\": 148,\n          \"y\": 416,\n          \"width\": 227,\n          \"height\": 44,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"44e7aa5c-3fe0-43db-8d46-c0a4425eeb18\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">The Latest Trends </span><span style=\\\"letter-spacing: -0.01em; text-transform: uppercase\\\">In Sneaker Land</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d1542e9f-6499-44ed-b51e-421787ecebbd\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 29,\n          \"y\": 385,\n          \"width\": 94,\n          \"height\": 94,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 220,\n          \"focalX\": 53.074903314458275,\n          \"focalY\": 63.289037207094864,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"ba68ba92-edcd-4c5c-a4fe-5263fc994e2b\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#959188\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page9_item3.jpg\",\n            \"width\": 229,\n            \"height\": 157,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_item3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"d1542e9f-6499-44ed-b51e-421787ecebbd\"\n        },\n        {\n          \"width\": 94,\n          \"height\": 94,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 210,\n          \"focalX\": 50.23363426439001,\n          \"focalY\": 56.7630971270795,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-29T20:54:29\",\n            \"baseColor\": \"#bdb8af\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fashion-on-the-go/page9_item4.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_item4\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"40d8eaeb-1fad-4346-b56b-eef002fcb4db\",\n          \"x\": 29,\n          \"y\": 496,\n          \"groupId\": \"fa78fb07-2fd6-4be8-ad25-25741ca99d0e\"\n        },\n        {\n          \"width\": 195,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #212121; letter-spacing: -0.01em; text-transform: uppercase\\\">The 90’s Back!</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"0785511b-324d-4a52-90bc-1fa6d5a8a0e6\",\n          \"x\": 148,\n          \"y\": 535,\n          \"groupId\": \"fa78fb07-2fd6-4be8-ad25-25741ca99d0e\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2fcd65e4-fad5-4443-828d-06b3250e0f6d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"421f76ac-4c4d-4a44-ad77-622facf57db5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d3b1c430-0462-4961-aaac-e6bc160a9f98\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1043803d-625c-4b7a-a5ad-1cdecfbb1c62\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"061f2737-dc6a-48e0-a62d-21049d3eb26c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d01ae69c-43cc-455e-bb63-250642795201\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c6659c98-8e14-4341-8342-fdfe68046ae0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c77c788b-cba9-421d-8a9a-2e8b604e99b8\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"06f3d6b9-6eef-40a2-bd33-b3b6a005b842\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"87b77bd3-8bc3-44ca-af6f-661e45522a7c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"e8fa7bdc-c342-4ab8-b91e-14930342b388\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ba68ba92-edcd-4c5c-a4fe-5263fc994e2b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"aa9afffb-66b9-413f-9115-bd50690d9c3a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"44e7aa5c-3fe0-43db-8d46-c0a4425eeb18\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"6fae8139-8021-4456-917c-7963744d3df8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"40d8eaeb-1fad-4346-b56b-eef002fcb4db\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"6a7e10d6-04f5-4d70-91f2-7c7cf5726428\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0785511b-324d-4a52-90bc-1fa6d5a8a0e6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 350\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"a9ed1626-720d-4b66-bfbd-40441c83390c\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 236, \"b\": 227 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"72c25e55-9c1e-484d-a9a8-7ccf770d91d7\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c625b6ba-90fc-4e5a-8a85-a7140b8cdddc\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d1542e9f-6499-44ed-b51e-421787ecebbd\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fa78fb07-2fd6-4be8-ad25-25741ca99d0e\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fitness-apps-ranked/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/fitness-apps-ranked/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'fitness-apps-ranked',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Fitness Apps Ranked', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Fitness', 'template keyword', 'web-stories'),\n    _x('App', 'template keyword', 'web-stories'),\n    _x('Reviews', 'template keyword', 'web-stories'),\n    _x('Yellow', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Space Blue', 'color', 'web-stories'),\n      color: '#222b49',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Watermelon Yellow', 'color', 'web-stories'),\n      color: '#f1ff51',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pastel Blue', 'color', 'web-stories'),\n      color: '#e0edf8',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its bright neon colors and modern design, this template is perfect for talking about what’s hot. Create vivid and energetic tech reviews, DIY tutorials, fitness guides and more.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/fitness-apps-ranked/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fitness-apps-ranked/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 352,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c8f41de6-8425-4b0d-8c8b-39e2cd6c0c82\",\n          \"scale\": 130,\n          \"focalX\": 62.89473684376997,\n          \"focalY\": 58.91953439734877,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-30T07:31:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page1_img1.jpg\",\n            \"width\": 330,\n            \"height\": 352,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"space gray aluminum case Apple watch\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d6cdb4\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.4\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"type\": \"shape\",\n          \"x\": -160,\n          \"y\": -108,\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b75958ad-f27d-4a49-a159-034521643cbd\",\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #f1ff51\\\">The best fitness apps, ranked</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 383,\n          \"width\": 341,\n          \"height\": 180,\n          \"id\": \"256ed426-a1b3-4507-a6a0-4aa0d3dcbe78\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f1ff51; letter-spacing: 0.01em; text-transform: uppercase\\\">Written By</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 587,\n          \"width\": 97,\n          \"height\": 16,\n          \"id\": \"87486d08-73e9-4ed8-8d18-3fdc0c7bd51b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.01em\\\">Martin Hansson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 21,\n          \"id\": \"33a1ce8a-1602-41d0-abf3-99c96e9a58d7\",\n          \"x\": 47,\n          \"y\": 607\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d8301b17-ccb5-4929-9c1a-071ebc5b722d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"5edb73ba-001a-4a24-aad0-c791a64088e6\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 447,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c8f41de6-8425-4b0d-8c8b-39e2cd6c0c82\",\n          \"scale\": 111,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-11T22:15:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page2_img1.jpg\",\n            \"width\": 330,\n            \"height\": 447,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman holding brown ropes\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b4b8be\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.1 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 224, \"g\": 237, \"b\": 248 } },\n          \"x\": 243,\n          \"y\": 577,\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bd0dbca0-32cd-41ec-8c69-d8a8550d51fd\",\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">Our gym days are over for now. So what are the best apps to get a good sweat in at home?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 343,\n          \"width\": 272,\n          \"height\": 172,\n          \"id\": \"34808ef3-2eae-4266-96c3-023358397520\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c236039a-83bd-42c8-9c5e-ab0c30f7fdf3\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"c8f41de6-8425-4b0d-8c8b-39e2cd6c0c82\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d5af44b3-6273-4e60-81c0-306f3d73b246\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"517647c0-62ed-476c-ae9e-85d76992732e\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 105,\n          \"focalX\": 35.101299694189606,\n          \"focalY\": 50.50103757099171,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page357_bg_img1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"woman tying her right shoe\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8095b3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9a70b555-4111-4215-9dd9-a7fc31daa382\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.7 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"x\": -158,\n          \"y\": 264,\n          \"width\": 1000,\n          \"height\": 540,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7f1c4d3c-d527-4b6e-bd5d-51e43c282c4b\",\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">The best app if cost is no concern</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 79,\n          \"y\": 0,\n          \"width\": 254,\n          \"height\": 56,\n          \"id\": \"efaaf1b7-e827-4539-96c1-c61b8b552bfb\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-29T06:08:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page3_img2.png\",\n            \"width\": 184,\n            \"height\": 383,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"mobile app showing woman doing cardio\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#333239\",\n            \"isExternal\": true\n          },\n          \"x\": 114,\n          \"y\": 92,\n          \"width\": 184,\n          \"height\": 383,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"568f15f0-dffe-4f65-ab34-c31e12d23135\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#0d0d0d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/mobile_frame.png\",\n            \"width\": 213,\n            \"height\": 413,\n            \"id\": 0,\n            \"alt\": \"smart phone frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 99.5,\n          \"y\": 77,\n          \"width\": 213,\n          \"height\": 413,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b9ba21ba-306b-4501-91b5-d177c831853a\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 214, \"g\": 68, \"b\": 36 } },\n          \"type\": \"shape\",\n          \"x\": 108,\n          \"y\": 533,\n          \"width\": 69,\n          \"height\": 69,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"d20092e4-0de3-4f5e-ac2a-74f1ee93bbb5\",\n          \"groupId\": \"c509118f-a795-489e-8c16-38fd25df02fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 127.5,\n          \"y\": 551.5,\n          \"width\": 32,\n          \"height\": 32,\n          \"sticker\": { \"type\": \"technologyPieChart\" },\n          \"id\": \"52c8c3bf-06e9-40d0-98aa-af0487e36896\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c509118f-a795-489e-8c16-38fd25df02fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #222b49\\\">FitFrame</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 86,\n          \"height\": 24,\n          \"id\": \"6ad918bb-886c-4dad-b1d9-b610a5d0b952\",\n          \"x\": 197,\n          \"y\": 538,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #222b49\\\">Advanced&nbsp;</span>\\n<span style=\\\"color: #222b49\\\">Fitness App</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 142,\n          \"height\": 30,\n          \"id\": \"3e345ce0-9c02-46fd-a38b-1df95c555957\",\n          \"x\": 197,\n          \"y\": 567,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6a237812-9843-4b57-a697-84f11517ea8f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7f1c4d3c-d527-4b6e-bd5d-51e43c282c4b\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"75b40f21-fffd-43cd-aec7-7d88704a40ba\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"9a70b555-4111-4215-9dd9-a7fc31daa382\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"08f40272-20fc-4da3-b15b-1a1ed50fac14\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"d20092e4-0de3-4f5e-ac2a-74f1ee93bbb5\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"c6a0d897-70c2-4f8e-92f0-76d35e1e64a3\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"52c8c3bf-06e9-40d0-98aa-af0487e36896\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"394d5c5c-7812-4adb-8a63-40f764f7a7fb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"fd289893-c627-46ab-aa5d-8ec4f7005780\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c509118f-a795-489e-8c16-38fd25df02fe\": {\n          \"name\": \"Badge\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 352,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"db632cc9-b5ae-4aa4-89d5-5b41da9a545f\",\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 52.473958333333336,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page4_img1.jpg\",\n            \"width\": 330,\n            \"height\": 352,\n            \"id\": 0,\n            \"alt\": \"person using smartphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1b1210\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.3 },\n                \"position\": 0\n              },\n              { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"type\": \"shape\",\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"id\": \"e5e8ace3-c6f2-4dce-9956-e20fd2b1b617\",\n          \"x\": -150,\n          \"y\": -114\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">For someone who’s just getting into a daily workout, FitFrame is a solid-and-free choice.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 269,\n          \"width\": 280,\n          \"height\": 152,\n          \"id\": \"a1f6f156-1307-4cd6-ac34-d6b722da8952\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9e2ec82d-1f84-4d85-9f3b-1e9c8b0dbb9f\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"db632cc9-b5ae-4aa4-89d5-5b41da9a545f\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a35115bf-f81e-4a9e-8b22-03e6719a8c2b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"cebac410-c75a-4094-b856-fafa49d8382a\"\n      },\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Download the app\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 105,\n          \"focalX\": 35.101299694189606,\n          \"focalY\": 50.50103757099171,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page357_bg_img1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"woman tying her right shoe\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8095b3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"09574b38-9580-4bfe-b353-d0d602f342da\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.7 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"x\": -160,\n          \"y\": 263,\n          \"width\": 1000,\n          \"height\": 540,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cf0badad-7c91-44ff-b1b6-8cae49a33e16\",\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Best app which comes with lighweight gear</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 79,\n          \"y\": 0,\n          \"width\": 254,\n          \"height\": 56,\n          \"id\": \"14b10594-bfd9-41ab-b6be-0188d0587a6b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#b49b7c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page5_img2.png\",\n            \"width\": 177,\n            \"height\": 381,\n            \"id\": 0,\n            \"alt\": \"fitness app screen showing 3 jump series with woman jumping above gray sand\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 117.5,\n          \"y\": 94,\n          \"width\": 177,\n          \"height\": 381,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0ae85159-8b43-4c2c-9d91-063a875b5740\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#0d0d0d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/mobile_frame.png\",\n            \"width\": 213,\n            \"height\": 413,\n            \"id\": 0,\n            \"alt\": \"smart phone frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 99.5,\n          \"y\": 77,\n          \"width\": 213,\n          \"height\": 413,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2fa03e34-5ac3-456f-a155-f4f76e666e6e\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 49, \"g\": 86, \"b\": 209 } },\n          \"type\": \"shape\",\n          \"x\": 108,\n          \"y\": 533,\n          \"width\": 69,\n          \"height\": 69,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"ae657fdf-9c17-478c-998f-d2ff6b79751e\",\n          \"groupId\": \"ffc5d036-c2cc-4793-8876-67d165efac0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 126.5,\n          \"y\": 551,\n          \"width\": 32,\n          \"height\": 33,\n          \"sticker\": { \"type\": \"technologyRunningFigure\" },\n          \"id\": \"d20ca0b1-89f6-44a9-9302-38d1f681945e\",\n          \"type\": \"sticker\",\n          \"groupId\": \"ffc5d036-c2cc-4793-8876-67d165efac0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #222b49\\\">Jetfit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 86,\n          \"height\": 24,\n          \"id\": \"1f161ac6-656f-40c6-ab44-2fbe7f517405\",\n          \"x\": 197,\n          \"y\": 538,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #222b49\\\">App +</span>\\n<span style=\\\"color: #222b49\\\">Lightweight Gear</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 142,\n          \"height\": 31,\n          \"id\": \"b6a2777a-cd6c-4a74-8977-d89d956a342d\",\n          \"x\": 197,\n          \"y\": 567,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e69a3200-d81b-4791-80d9-284a95adfdf9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cf0badad-7c91-44ff-b1b6-8cae49a33e16\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"06c10ffc-9eba-4cfa-b2a8-7ad9eebd9c86\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"09574b38-9580-4bfe-b353-d0d602f342da\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"98bfb5fe-96ec-4853-aad5-50f4f29ea261\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"ae657fdf-9c17-478c-998f-d2ff6b79751e\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"b93944e0-d92d-4d20-8f8e-9dffcb4eedd1\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"d20ca0b1-89f6-44a9-9302-38d1f681945e\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7b2fb002-505f-4d04-acf3-e6ed71182f39\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"fd289893-c627-46ab-aa5d-8ec4f7005780\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"ffc5d036-c2cc-4793-8876-67d165efac0a\": {\n          \"name\": \"Badge\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 352,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a44837e6-c1f3-4134-aef4-1b47f8b84d60\",\n          \"scale\": 109,\n          \"focalX\": 42.201834862385326,\n          \"focalY\": 50.86009174311926,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page6_img1.jpg\",\n            \"width\": 330,\n            \"height\": 352,\n            \"id\": 0,\n            \"alt\": \"person using iPhone X\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b19e8f\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">To see maximum results with this app, you will need a few pieces of gear: weights, a tension band, a pilates ball and a jumprope.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 371,\n          \"width\": 280,\n          \"height\": 168,\n          \"id\": \"f0cb9305-2017-49ba-8ffb-5350d3be5686\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"type\": \"shape\",\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"id\": \"858585e5-669a-4054-bf91-e71f8cc6c399\",\n          \"x\": -150,\n          \"y\": -114\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6648f1fd-a9a7-49ef-9067-840645b7893e\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"a44837e6-c1f3-4134-aef4-1b47f8b84d60\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"68ce9003-5fb1-496b-9415-56a637585be1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"29b86b58-3158-4734-b043-3229aebba4be\"\n      },\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Download the app\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 105,\n          \"focalX\": 35.101299694189606,\n          \"focalY\": 50.50103757099171,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page357_bg_img1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"woman tying her right shoe\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8095b3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"0f8001fa-ae7a-4368-9356-d82d2e76c317\",\n          \"type\": \"image\",\n          \"overlay\": { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.7 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"x\": -167,\n          \"y\": 268,\n          \"width\": 1000,\n          \"height\": 540,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b80d87ce-d3a3-4582-9a68-a8ccf92ed015\",\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Best app for runners building their strength</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 79,\n          \"y\": 0,\n          \"width\": 254,\n          \"height\": 56,\n          \"id\": \"c4b9149d-affe-44f5-b2a3-ef1baa94f7df\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#212121\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page7_img2.png\",\n            \"width\": 184,\n            \"height\": 383,\n            \"id\": 0,\n            \"alt\": \"fitness app screen to start the weekly routine\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 114,\n          \"y\": 94,\n          \"width\": 184,\n          \"height\": 383,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d5cab2a9-9e86-4d44-9b40-942aee009338\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#0d0d0d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/mobile_frame.png\",\n            \"width\": 213,\n            \"height\": 413,\n            \"id\": 0,\n            \"alt\": \"smart phone frame\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 99.5,\n          \"y\": 77,\n          \"width\": 213,\n          \"height\": 413,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9e30c6df-c08e-47bc-a7ef-2ac62bb7fa5a\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73 } },\n          \"type\": \"shape\",\n          \"x\": 108,\n          \"y\": 533,\n          \"width\": 69,\n          \"height\": 69,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"a1612d1b-cb9a-4807-a101-cdc8bc949db8\",\n          \"groupId\": \"4ce7115e-2de9-468c-a0cc-fbb20acc8853\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 121.5,\n          \"y\": 555.5,\n          \"width\": 42,\n          \"height\": 24,\n          \"sticker\": { \"type\": \"technologyDumbbells\" },\n          \"id\": \"43c1a7d7-4f77-4b31-b5ce-3718eda3f214\",\n          \"type\": \"sticker\",\n          \"groupId\": \"4ce7115e-2de9-468c-a0cc-fbb20acc8853\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #222b49\\\">RunStrong</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 96,\n          \"height\": 24,\n          \"id\": \"e60f1beb-5a0e-479b-9412-52aefa868e8f\",\n          \"x\": 197,\n          \"y\": 538,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #222b49\\\">Strength Training</span>\\n<span style=\\\"color: #222b49\\\">for Runners </span>Free\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 181,\n          \"height\": 30,\n          \"id\": \"4a2ae072-fcc5-44ba-a8e4-58cdfad212e1\",\n          \"x\": 197,\n          \"y\": 567,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"211d6aff-92dc-4d7e-a0a0-956503c4dc0f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b80d87ce-d3a3-4582-9a68-a8ccf92ed015\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"02aa8426-731b-4fb4-bcb5-2b92ef357733\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"43c1a7d7-4f77-4b31-b5ce-3718eda3f214\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"d80cc227-b238-498d-abcc-40bc99cfab0a\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"a1612d1b-cb9a-4807-a101-cdc8bc949db8\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"929c383d-dde2-452b-bb32-5142eaa675b7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"fd289893-c627-46ab-aa5d-8ec4f7005780\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4ce7115e-2de9-468c-a0cc-fbb20acc8853\": {\n          \"name\": \"Badge\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 288,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"5c1cd06c-6dcd-4892-a1a7-802147702950\",\n          \"scale\": 114,\n          \"focalX\": 41.14077254015334,\n          \"focalY\": 44.82737173816895,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page8_img1.jpg\",\n            \"width\": 330,\n            \"height\": 288,\n            \"id\": 0,\n            \"alt\": \"man in black crew-neck top using smartphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d8e1e1\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 34, \"g\": 43, \"b\": 73, \"a\": 0.4 },\n                \"position\": 0\n              },\n              { \"color\": { \"r\": 34, \"g\": 43, \"b\": 73 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">The app is personalized, creating strength training regiments mixed with your run goals in mind.</span>\\n\\n<span style=\\\"font-weight: 700; color: #f1ff51\\\">The overall goal is to build endurance and to help you achieve time goals.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 269,\n          \"width\": 280,\n          \"height\": 224,\n          \"id\": \"9cfeae02-6a5b-46e5-b4c9-9f6db08759d2\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"type\": \"shape\",\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"id\": \"652d9673-d5ca-4db6-831e-d8fe40160ad2\",\n          \"x\": -150,\n          \"y\": -114\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"99279686-f50d-4d17-9145-466ae0d33451\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"5c1cd06c-6dcd-4892-a1a7-802147702950\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"752c9060-8425-4134-af13-7268b17256ae\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"376785c5-f44a-4b63-915c-f012f96bc9dd\"\n      },\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Download the app\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"797fe61d-66fa-407a-bb3a-b7347a38d3a7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\",\n          \"id\": \"d0f9a832-6edd-404d-b901-fbd26bd133b0\",\n          \"x\": -137,\n          \"y\": 649,\n          \"groupId\": \"111d68da-2a22-4b15-af6a-32f43056b491\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 49, \"g\": 83, \"b\": 108 } },\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\",\n          \"id\": \"f6dba06f-74c8-47e3-b2b9-1daa894954e5\",\n          \"x\": 202,\n          \"y\": -130,\n          \"groupId\": \"111d68da-2a22-4b15-af6a-32f43056b491\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #f1ff51\\\">Other apps</span>\\n<span style=\\\"font-weight: 600; color: #f1ff51\\\">we love</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 341,\n          \"height\": 126,\n          \"id\": \"c5c1927a-a461-4655-abcf-558d60946e60\",\n          \"x\": 47,\n          \"y\": 70,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 134, \"g\": 57, \"b\": 233 }, \"position\": 0 },\n              { \"color\": { \"r\": 57, \"g\": 127, \"b\": 233 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 71,\n          \"y\": 242,\n          \"width\": 90,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7eeb17d7-d26e-4476-b2ec-52e2e6a42447\",\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"groupId\": \"7f0c3f83-9298-4b80-bb5d-e7c471761eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 83.5,\n          \"y\": 265,\n          \"width\": 65,\n          \"height\": 44,\n          \"sticker\": { \"type\": \"technologyShoe\" },\n          \"id\": \"e0d7e496-d352-4d0f-ba5d-632b879dc8b8\",\n          \"groupId\": \"7f0c3f83-9298-4b80-bb5d-e7c471761eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">Fit For All</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 31,\n          \"id\": \"3517ae98-6e41-466f-b4b7-1450e61662df\",\n          \"x\": 189,\n          \"y\": 242,\n          \"groupId\": \"7f0c3f83-9298-4b80-bb5d-e7c471761eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f1ff51\\\">The reference app for runners</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 144,\n          \"height\": 38,\n          \"id\": \"ca30a640-6708-42d0-a226-9daa57069a88\",\n          \"x\": 189,\n          \"y\": 275,\n          \"groupId\": \"7f0c3f83-9298-4b80-bb5d-e7c471761eeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 49, \"g\": 86, \"b\": 209 } },\n          \"type\": \"shape\",\n          \"width\": 90,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"id\": \"17ffcd54-b88d-4307-8fd8-e8759f3f7915\",\n          \"x\": 71,\n          \"y\": 362,\n          \"groupId\": \"d83c519e-827c-4412-ab6c-d62db9b56271\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 86,\n          \"y\": 381.5,\n          \"width\": 60,\n          \"height\": 51,\n          \"sticker\": { \"type\": \"technologyMuscle\" },\n          \"id\": \"2eb0121e-b4f1-422f-a1ba-02b934034b3e\",\n          \"groupId\": \"d83c519e-827c-4412-ab6c-d62db9b56271\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">Gymmy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 31,\n          \"id\": \"de3a2c4e-0e2c-4806-8c0a-482ebf71c625\",\n          \"x\": 189,\n          \"y\": 354,\n          \"groupId\": \"d83c519e-827c-4412-ab6c-d62db9b56271\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f1ff51\\\">Dozens of tailor-made workouts</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 57,\n          \"id\": \"6db24f9a-c2c9-40ba-a6d4-255015e1e9cb\",\n          \"x\": 189,\n          \"y\": 391,\n          \"groupId\": \"d83c519e-827c-4412-ab6c-d62db9b56271\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 32, \"g\": 95, \"b\": 140 } },\n          \"type\": \"shape\",\n          \"width\": 90,\n          \"height\": 90,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"id\": \"1299e382-b9b7-4cc5-b4c3-283c1cd22dcf\",\n          \"x\": 71,\n          \"y\": 482,\n          \"groupId\": \"b493ca28-f3a4-4a39-b251-b07af4563067\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 81.5,\n          \"y\": 508,\n          \"width\": 69,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"technologySwimmer\" },\n          \"id\": \"1e3b0b01-f908-4b79-abef-8e873fba73b1\",\n          \"groupId\": \"b493ca28-f3a4-4a39-b251-b07af4563067\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f1ff51\\\">42K Push</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 31,\n          \"id\": \"2d97fc7c-c3a8-4a95-bfe4-bac6cc74e7af\",\n          \"x\": 188,\n          \"y\": 482,\n          \"groupId\": \"b493ca28-f3a4-4a39-b251-b07af4563067\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f1ff51\\\">10-week program to run long and strong</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 135,\n          \"height\": 57,\n          \"id\": \"e2ff0591-7b07-4312-a4d2-03b29372d003\",\n          \"x\": 187,\n          \"y\": 517,\n          \"groupId\": \"b493ca28-f3a4-4a39-b251-b07af4563067\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fd8cc6ab-5496-4393-a1b6-0f7d75b8f697\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"f6dba06f-74c8-47e3-b2b9-1daa894954e5\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"91da9553-4c3b-4240-9a17-587ed184d3e6\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"d0f9a832-6edd-404d-b901-fbd26bd133b0\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a26f291c-977e-4b45-9299-acc596083b9f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3517ae98-6e41-466f-b4b7-1450e61662df\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"660fe840-1a0c-4f28-a50f-58b6556792f5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ca30a640-6708-42d0-a226-9daa57069a88\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"afab4868-6498-413d-810c-e02418d7bea2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"de3a2c4e-0e2c-4806-8c0a-482ebf71c625\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"722ee78d-2a53-4494-95a7-98545dd781bc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6db24f9a-c2c9-40ba-a6d4-255015e1e9cb\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"47c7883d-80d4-491a-8cc6-b655abcf3fdd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2d97fc7c-c3a8-4a95-bfe4-bac6cc74e7af\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 1400\n        },\n        {\n          \"id\": \"e54ea6f6-8dc0-4dbb-b196-78d3b88caff6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e2ff0591-7b07-4312-a4d2-03b29372d003\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"bc6cb30c-f945-4d1a-90bf-a9afdf60b772\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"e0d7e496-d352-4d0f-ba5d-632b879dc8b8\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"e0ef6ec7-f68f-441c-a59c-78c9deba1f88\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"7eeb17d7-d26e-4476-b2ec-52e2e6a42447\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"ef52e5f8-fab2-414a-b17c-9ad4241107f3\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"17ffcd54-b88d-4307-8fd8-e8759f3f7915\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"cdfe2688-cf44-4d60-b214-89f602f5d926\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"2eb0121e-b4f1-422f-a1ba-02b934034b3e\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"a6709f85-88f0-43f6-a383-ca5e6eb1735f\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"1299e382-b9b7-4cc5-b4c3-283c1cd22dcf\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1400\n        },\n        {\n          \"id\": \"58c1ac42-062e-4424-90d1-a51f0140d602\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"1e3b0b01-f908-4b79-abef-8e873fba73b1\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 15, \"g\": 44, \"b\": 65 } },\n      \"type\": \"page\",\n      \"id\": \"50e7be7c-88e7-4a28-920e-547fbfe9886d\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"7f0c3f83-9298-4b80-bb5d-e7c471761eeb\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d83c519e-827c-4412-ab6c-d62db9b56271\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b493ca28-f3a4-4a39-b251-b07af4563067\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"111d68da-2a22-4b15-af6a-32f43056b491\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"31b8d43d-b4b7-4e18-bcf7-1710a4b1d2b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 15, \"g\": 44, \"b\": 65 } },\n          \"width\": 300,\n          \"height\": 128,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 120,\n            \"topRight\": 120,\n            \"bottomRight\": 120,\n            \"bottomLeft\": 120,\n            \"locked\": true\n          },\n          \"type\": \"shape\",\n          \"id\": \"384412ef-2fba-466a-b867-ff0aeb243fe8\",\n          \"x\": 279,\n          \"y\": -141\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #0f2c41\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 140,\n          \"height\": 28,\n          \"id\": \"0ce7cd0e-c641-4ea3-9df8-1ff400fcd1f4\",\n          \"x\": 136,\n          \"y\": 14\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 63,\n          \"y\": 84,\n          \"width\": 130,\n          \"height\": 150,\n          \"scale\": 180,\n          \"focalX\": 45.813081752906406,\n          \"focalY\": 36.605761197812534,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"824ed88e-636d-4bb0-921e-c7169f43ed6c\",\n          \"borderRadius\": {\n            \"topLeft\": 7,\n            \"topRight\": 7,\n            \"bottomRight\": 7,\n            \"bottomLeft\": 7,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page10_img1.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"id\": 0,\n            \"alt\": \"woman wearing gray shirt and orange leggings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1d120b\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"b2a5f85c-0025-40f7-b384-37098f282c3f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0f2c41\\\">Best apps for power lifters</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 38,\n          \"id\": \"cad091f8-9d55-4101-a087-d311f81ee04e\",\n          \"x\": 63,\n          \"y\": 242,\n          \"groupId\": \"b2a5f85c-0025-40f7-b384-37098f282c3f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 130,\n          \"height\": 150,\n          \"scale\": 130,\n          \"focalX\": 53.281474388143025,\n          \"focalY\": 42.95726489466286,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 7,\n            \"topRight\": 7,\n            \"bottomRight\": 7,\n            \"bottomLeft\": 7,\n            \"locked\": true\n          },\n          \"id\": \"48b1d0dd-1982-4d62-bbe4-a2dae9d6347e\",\n          \"x\": 218,\n          \"y\": 206,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-29T07:37:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page10_img2.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman wearing black sports bra and white legging lifting dumbbells\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d1d9d6\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"964030c5-9acd-4414-af12-fc459a8d08f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0f2c41\\\">Learn how to do a squat correctly</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 38,\n          \"id\": \"783bcbab-9cf3-4023-89ae-b251e1e33168\",\n          \"x\": 219,\n          \"y\": 370,\n          \"groupId\": \"964030c5-9acd-4414-af12-fc459a8d08f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 130,\n          \"height\": 150,\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 46.12160490379697,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 7,\n            \"topRight\": 7,\n            \"bottomRight\": 7,\n            \"bottomLeft\": 7,\n            \"locked\": true\n          },\n          \"id\": \"a5731d92-fe49-4742-a696-f92d9094c56f\",\n          \"x\": 63,\n          \"y\": 340,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-29T07:37:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fitness-apps-ranked/page10_img3.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"topless man in black shorts carrying black dumbbell\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#beaaa4\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"2474450c-c1fc-47a2-bc62-2380be88516a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Barlow\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1000,\n              \"des\": -200,\n              \"tAsc\": 1000,\n              \"tDes\": -200,\n              \"tLGap\": 0,\n              \"wAsc\": 1112,\n              \"wDes\": 249,\n              \"xH\": 506,\n              \"capH\": 700,\n              \"yMin\": -209,\n              \"yMax\": 1084,\n              \"hAsc\": 1000,\n              \"hDes\": -200,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0f2c41\\\">Top 5 muscle building apps</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 38,\n          \"id\": \"f39454d6-f499-4d27-96a8-6bce103371d5\",\n          \"x\": 63,\n          \"y\": 498,\n          \"groupId\": \"2474450c-c1fc-47a2-bc62-2380be88516a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ebc7be78-44cd-4431-acdc-8969e6814cb8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"824ed88e-636d-4bb0-921e-c7169f43ed6c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"0a2c9878-834e-4283-9859-49c1258616d6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"48b1d0dd-1982-4d62-bbe4-a2dae9d6347e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"7e0ff75b-9800-4a91-bfb0-ab38f72312b3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a5731d92-fe49-4742-a696-f92d9094c56f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"5080c499-f24a-41c3-9a67-1fd5fa8ab2a3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cad091f8-9d55-4101-a087-d311f81ee04e\"],\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"fcf772e4-e1ad-4419-8f7f-9178734d13a0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"783bcbab-9cf3-4023-89ae-b251e1e33168\"],\n          \"duration\": 1000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"ad8de5ee-29d1-4b59-a128-0832e5d21ad3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f39454d6-f499-4d27-96a8-6bce103371d5\"],\n          \"duration\": 1000,\n          \"delay\": 1300\n        },\n        {\n          \"id\": \"40d90e54-f67d-4c8c-9075-50a63260a36e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"384412ef-2fba-466a-b867-ff0aeb243fe8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 255, \"b\": 81 } },\n      \"type\": \"page\",\n      \"id\": \"cc6675e4-0919-424f-9909-45b5d89451d9\",\n      \"pageAttachment\": { \"url\": \"\", \"ctaText\": \"\", \"theme\": \"light\" },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"b2a5f85c-0025-40f7-b384-37098f282c3f\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"964030c5-9acd-4414-af12-fc459a8d08f5\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2474450c-c1fc-47a2-bc62-2380be88516a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/food-and-stuff/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/food-and-stuff/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'food-and-stuff',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Food & Stuff', 'template name', 'web-stories'),\n  tags: [\n    _x('Delicious', 'template keyword', 'web-stories'),\n    _x('Baker', 'template keyword', 'web-stories'),\n    _x('Cooking', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Yellow', 'color', 'web-stories'),\n      color: '#fff933',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Orange', 'color', 'web-stories'),\n      color: '#ff922e',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gray', 'color', 'web-stories'),\n      color: '#676461',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Blue', 'color', 'web-stories'),\n      color: '#3a566e',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cream', 'color', 'web-stories'),\n      color: '#fff9ee',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Make your audience salivate by using the Cooking template to create web stories about ingredients, food recipes, how-to’s, restaurant guides and kitchen inspiration.',\n    'web-stories'\n  ),\n  vertical: _x('Cooking', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/food-and-stuff/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/food-and-stuff/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"900a850f-fb71-4262-84f0-d6b803224ac7\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#ffffff\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/icon_logo.png\",\n            \"width\": 75,\n            \"height\": 23,\n            \"id\": 0,\n            \"alt\": \"icon_logo\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 168.5,\n          \"y\": 22,\n          \"width\": 75,\n          \"height\": 24,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"779cea6f-ac5b-41d1-9bb1-75511614c04d\"\n        },\n        {\n          \"x\": -1,\n          \"y\": 235,\n          \"width\": 413,\n          \"height\": 441,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 180,\n          \"focalX\": 49.92453232830327,\n          \"focalY\": 44.16425931048792,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"8f4fcc58-2834-46af-a2cb-64e139f333d5\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#0d2c2b\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page1_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page1_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 66,\n          \"y\": 137,\n          \"width\": 280,\n          \"height\": 130,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"be108bc9-3a51-48c4-b495-24be6163e44c\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff9ee\\\">Food &amp; Stuff</span>\",\n          \"fontSize\": 74,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"dd6a669f-ff4b-4633-8eb4-c601e98b40f1\",\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 86, \"b\": 110 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"b8ea29e5-ce25-4204-8660-afe56bb6b952\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 73.5,\n          \"y\": 184,\n          \"width\": 265,\n          \"height\": 156,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"5ad5b20a-e1ef-4341-a9ea-afc442cca079\",\n          \"content\": \"<span style=\\\"color: #fff9ee\\\">“Take a moment out of the day to enjoy what's on your plate.”</span>\",\n          \"fontSize\": 36,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 75.5,\n          \"y\": 379,\n          \"width\": 261,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"d3bb1cdf-9ab7-4444-a71b-e4a5bfd27410\",\n          \"content\": \"<span style=\\\"color: #fff9ee\\\">- Anonymous</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 75,\n          \"y\": -62,\n          \"width\": 371,\n          \"height\": 792,\n          \"sticker\": { \"type\": \"cookingRadishLarge\" },\n          \"id\": \"5f7724b1-43dc-4e3f-bf37-eaec61cb1788\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"478b8923-6e57-4c78-a5ae-4f5216448e86\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5ad5b20a-e1ef-4341-a9ea-afc442cca079\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"86efecb1-126e-465d-8628-489ee26f9252\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d3bb1cdf-9ab7-4444-a71b-e4a5bfd27410\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 400\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"434c112e-3463-4dc6-aa8e-cb97f13a4e8e\",\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 86, \"b\": 110 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"268f9f40-cce2-4d37-899e-ea2422f8df7b\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -66,\n          \"width\": 412,\n          \"height\": 436,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 160,\n          \"focalX\": 50.94203518720969,\n          \"focalY\": 40.15889802797264,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"4b496f17-b72e-4ead-aaa9-92936156e01f\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page3_image1.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 123,\n          \"y\": 403,\n          \"width\": 245,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"6c29ba73-482b-4759-bbc0-2a503f075b61\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Dan Williams</span>\",\n          \"fontSize\": 32,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 47,\n          \"y\": 480,\n          \"width\": 241,\n          \"height\": 105,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"31272720-81e0-416c-b7e6-870d7c68bf81\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">We go behind the scene of his famous Soho restaurant, where Dan will show us what inspires him this season and how he plans his menu accordingly.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 310,\n          \"y\": 508,\n          \"width\": 59,\n          \"height\": 30,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"d189d8f5-809a-4775-8043-4f1ff432a932\",\n          \"content\": \"<span style=\\\"color: #3a566e; text-transform: uppercase\\\">View</span>\\n<span style=\\\"color: #3a566e; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 12,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 47,\n          \"y\": 393,\n          \"width\": 40,\n          \"height\": 41,\n          \"sticker\": { \"type\": \"cookingPersimmon\" },\n          \"id\": \"195514c6-04e5-4f4e-8791-dbb85f9b4d53\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 328,\n          \"y\": 549,\n          \"width\": 22,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"cookingArrow\" },\n          \"id\": \"b836b3b3-3030-4f5e-a998-77cd464ad80f\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e087ba53-961a-4bef-81e7-079c54264751\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"31272720-81e0-416c-b7e6-870d7c68bf81\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"76911023-5376-4bf1-8b3c-3a892bea167e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6c29ba73-482b-4759-bbc0-2a503f075b61\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"51ce0813-345b-4fc4-948e-496e0650b529\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4b496f17-b72e-4ead-aaa9-92936156e01f\"],\n          \"duration\": 1700,\n          \"delay\": 100\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"a378f919-785d-4ff2-8f8c-e7922a221cbf\",\n      \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 249, \"b\": 239 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"10cd0ef0-78ac-41f8-9e90-810376fb7a0e\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 30,\n          \"y\": 18,\n          \"width\": 353,\n          \"height\": 28,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"b4b4b005-1524-4a37-ba21-0ef518581240\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Currently in season</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 194,\n          \"y\": 215,\n          \"width\": 26,\n          \"height\": 2,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 146, \"b\": 46 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"d3799e22-bfe3-4d56-8bb4-5f5603ecaeae\"\n        },\n        {\n          \"x\": 194,\n          \"y\": 342,\n          \"width\": 26,\n          \"height\": 2,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 146, \"b\": 46 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"ea9de973-d615-466a-bf7e-7f6539688a63\"\n        },\n        {\n          \"x\": 194,\n          \"y\": 468,\n          \"width\": 26,\n          \"height\": 2,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 146, \"b\": 46 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"2645174d-c03f-4e45-b801-a92cf39cccfb\"\n        },\n        {\n          \"x\": 84,\n          \"y\": 120,\n          \"width\": 244,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"30276475-9eaf-4f66-824b-4619e28b788f\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Radishes</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"5a5e54c0-b438-4241-9f02-20d837bb735c\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 275,\n          \"y\": 76,\n          \"width\": 107,\n          \"height\": 168,\n          \"sticker\": { \"type\": \"cookingRadish\" },\n          \"id\": \"cabe6f42-c5d0-4944-8d0d-411b52803c80\",\n          \"groupId\": \"5a5e54c0-b438-4241-9f02-20d837bb735c\"\n        },\n        {\n          \"x\": 96,\n          \"y\": 247,\n          \"width\": 220,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"2312c664-2f6e-4aa7-a179-2d76900b7ab1\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Carrots</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"2e30ad9b-71db-4a56-8e15-07bf474771ae\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 96,\n          \"y\": 182,\n          \"width\": 133,\n          \"height\": 183,\n          \"sticker\": { \"type\": \"cookingCarrot\" },\n          \"id\": \"7fa4fe54-aeb8-45d0-a45c-acef91f0a3ac\",\n          \"groupId\": \"2e30ad9b-71db-4a56-8e15-07bf474771ae\"\n        },\n        {\n          \"x\": 32,\n          \"y\": 376,\n          \"width\": 350,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"1ea46b67-82b6-43dc-9b68-761f60b23367\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Persimmons</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"4ad5f4a4-0399-43ce-9551-7c2f55c32da3\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 285,\n          \"y\": 383,\n          \"width\": 90,\n          \"height\": 94,\n          \"sticker\": { \"type\": \"cookingPersimmon\" },\n          \"id\": \"c7788d92-d48c-45c5-b58f-41db7c6878c5\",\n          \"groupId\": \"4ad5f4a4-0399-43ce-9551-7c2f55c32da3\"\n        },\n        {\n          \"x\": 31,\n          \"y\": 506,\n          \"width\": 350,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"429d7f44-4a17-4bbe-af08-6786b3b122f2\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Artichokes</span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"43055330-ed3d-4940-9836-a2ad980f2790\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 47,\n          \"y\": 498,\n          \"width\": 103,\n          \"height\": 108,\n          \"sticker\": { \"type\": \"cookingArtichoke\" },\n          \"id\": \"8d30661a-2cb7-4ba0-bbfc-49d37b51a1bc\",\n          \"groupId\": \"43055330-ed3d-4940-9836-a2ad980f2790\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"44ba9771-f034-41dc-b4ae-bc1f20b3d176\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b4b4b005-1524-4a37-ba21-0ef518581240\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"da0cd83f-7d71-4a08-a964-a9d2a2ec41d1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"30276475-9eaf-4f66-824b-4619e28b788f\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 700,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"b202db79-f121-4236-87a8-c325db85ba30\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2312c664-2f6e-4aa7-a179-2d76900b7ab1\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 700,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a11ccb5e-8304-46df-b685-01e4b1afe336\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1ea46b67-82b6-43dc-9b68-761f60b23367\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 700,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"25891349-30f3-48ba-9108-880464020557\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"429d7f44-4a17-4bbe-af08-6786b3b122f2\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 700,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"127d027d-15cc-4be1-8169-945298214a6b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2645174d-c03f-4e45-b801-a92cf39cccfb\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 701,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"a2353dfd-5439-40e2-883c-109af74d158a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ea9de973-d615-466a-bf7e-7f6539688a63\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 701,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f82c5dc3-caf9-4b2d-be69-413fce434a14\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d3799e22-bfe3-4d56-8bb4-5f5603ecaeae\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 701,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e6314f4e-5a59-425c-a6a3-b0a3ecff301c\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 249, \"b\": 238 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"5a5e54c0-b438-4241-9f02-20d837bb735c\": {\n          \"name\": \"Radish\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2e30ad9b-71db-4a56-8e15-07bf474771ae\": {\n          \"name\": \"Carrot\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4ad5f4a4-0399-43ce-9551-7c2f55c32da3\": {\n          \"name\": \"Persimmon\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"43055330-ed3d-4940-9836-a2ad980f2790\": {\n          \"name\": \"Artichoke\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 43,\n          \"y\": 72,\n          \"width\": 206,\n          \"height\": 366,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 130,\n          \"focalX\": 49.93933316207369,\n          \"focalY\": 54.07044367178359,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#cd5c20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page5_bg.jpg\",\n            \"width\": 220,\n            \"height\": 391,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page5_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"85bf1bf4-8ef0-4408-9fd1-755769555106\",\n          \"isBackground\": true\n        },\n        {\n          \"x\": 24,\n          \"y\": 186.5,\n          \"width\": 364,\n          \"height\": 346,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.84,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"b93db3ac-4bbd-4189-90fa-c509f358a954\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff9ee\\\">Pers</span>\\n<span style=\\\"font-weight: 700; color: #fff9ee\\\">imm</span>\\n<span style=\\\"font-weight: 700; color: #fff9ee\\\">on</span>\",\n          \"fontSize\": 138,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 100,\n          \"y\": 18,\n          \"width\": 212,\n          \"height\": 56,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"a6b673a3-db8d-48a2-9469-1892e6266eb3\",\n          \"content\": \"<span style=\\\"color: rgba(255, 249, 238, 1)\\\"><span style=\\\"font-weight: 700\\\">The ultimate recipe guide on</span></span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a706e47a-7be1-4d68-8afd-37b161483fec\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b93db3ac-4bbd-4189-90fa-c509f358a954\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"39b567b9-bb24-459b-a19f-637e4917a863\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a6b673a3-db8d-48a2-9469-1892e6266eb3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"b08e5e3d-08c8-4865-b82f-20a04e8f6fc7\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e59627e9-eb83-4ce5-bf83-17f22851ed1c\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"353201ca-58e7-487f-b6f7-6360c5b72aa9\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 111,\n          \"y\": -169,\n          \"width\": 189,\n          \"height\": 414,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 46.3086913086913,\n          \"focalY\": 38.18681318681318,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"15c7cc7e-e144-43db-bb67-1a8d4b6a561e\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#cd5c20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page5_bg.jpg\",\n            \"width\": 220,\n            \"height\": 391,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page5_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 88,\n          \"y\": 580,\n          \"width\": 136,\n          \"height\": 13,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"7979d059-fcdd-4a43-b92c-a9700cab7519\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Discover them</span>\",\n          \"fontSize\": 12,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"marginOffset\": 0\n        },\n        {\n          \"x\": 104,\n          \"y\": 184.5,\n          \"width\": 259,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"38be890d-5627-4041-b008-2f24707bf749\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Persimmon Salsa Tacos</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 104,\n          \"y\": 242.5,\n          \"width\": 259,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"127f9ed4-f754-45f1-9bc5-60fee6cbc90c\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Steamed Persimmon Pudding</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"width\": 259,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #676461\\\">Frozen Persimmon Custard</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"1e5d493d-dbfa-40b9-afa2-6b0c4312cb25\",\n          \"x\": 104,\n          \"y\": 425.5,\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 104,\n          \"y\": 305.5,\n          \"width\": 259,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"260c32cf-161f-4d2c-9b0b-f9d04cbf57f9\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Persimmon and Brie Crostini</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 104,\n          \"y\": 364.5,\n          \"width\": 282,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9aa100d8-d095-4c1a-8430-1b3a5bbbc5b4\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Persimmon, Beet, and Citrus Salad</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 104,\n          \"y\": 484.5,\n          \"width\": 259,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e3681a5a-e2a2-4754-b9d2-5a466a46c218\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Persimmon and Bresaola Bites</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 180,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c65251ab-3347-4658-a18a-1425b12b7081\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">1</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 240,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"3d65fd5b-fc80-4b1a-90ba-d866036d934a\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">2</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 300,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"87a59266-ad7d-43cd-a626-0d2a0126828d\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">3</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 360,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"050e9d9e-6b37-44ef-9f9c-a516ea88c8a4\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">4</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 422,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"86a51872-f144-4332-8b93-13b189f1d30b\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">5</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 486,\n          \"width\": 23,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"ac878a4a-4cf7-41be-8269-c1f317f3fef6\",\n          \"content\": \"<span style=\\\"color: #3a566e\\\">6</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 38.5,\n          \"width\": 161,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c0040186-618e-4b75-bbda-ec1803464e6e\",\n          \"content\": \"<span style=\\\"color: rgba(255, 249, 238, 1)\\\"><span style=\\\"font-weight: 700\\\">Top 8</span></span>\",\n          \"fontSize\": 50,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 49.5,\n          \"width\": 155,\n          \"height\": 43,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"88dd72fa-b6d4-4749-85f7-a5430f7e51c2\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff9ee\\\">recipes with</span>\\n<span style=\\\"font-weight: 700; color: #fff9ee\\\">persimmon</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 237,\n          \"y\": 580,\n          \"width\": 22,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"cookingArrow\" },\n          \"id\": \"76fc4a93-22cd-492c-8081-96f52259a907\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a09cda34-471e-4a02-92f0-5440760cc058\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e3681a5a-e2a2-4754-b9d2-5a466a46c218\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"e57a8b53-a484-4c90-bcf9-08afffaba694\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3d65fd5b-fc80-4b1a-90ba-d866036d934a\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1baa685e-11eb-4fdb-a012-f63aa7fca3df\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"87a59266-ad7d-43cd-a626-0d2a0126828d\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"66ae6fb1-fa17-480c-9313-35b508f22224\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"050e9d9e-6b37-44ef-9f9c-a516ea88c8a4\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c09a1c2f-c891-4b42-ad1e-0dc4bd310650\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"86a51872-f144-4332-8b93-13b189f1d30b\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"598ce217-814c-4518-88b4-eecf7cd597d6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ac878a4a-4cf7-41be-8269-c1f317f3fef6\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"564a3db7-1e16-4bde-a838-cb0c571952b8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"38be890d-5627-4041-b008-2f24707bf749\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"1d6708e8-85fa-47e8-b5f2-a842f0a7f5d0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"127f9ed4-f754-45f1-9bc5-60fee6cbc90c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"db18e43b-6945-45f1-875f-9656f9be7522\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"260c32cf-161f-4d2c-9b0b-f9d04cbf57f9\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"2fdbd002-752a-43e5-94f5-0ffa1a8b5f98\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9aa100d8-d095-4c1a-8430-1b3a5bbbc5b4\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a3dbcd32-50bd-4961-904d-b5a1584bece7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1e5d493d-dbfa-40b9-afa2-6b0c4312cb25\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"2fc44d58-5d5c-41bf-b2e8-2b497263bda6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c0040186-618e-4b75-bbda-ec1803464e6e\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d42a0368-016d-402c-bb10-dc23061ab408\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"88dd72fa-b6d4-4749-85f7-a5430f7e51c2\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a3a68672-be31-45a4-91ed-85f17216ecda\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c65251ab-3347-4658-a18a-1425b12b7081\"],\n          \"duration\": 1400,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"4ce57acc-c58e-40ab-8a3d-87f6dc5fb106\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 249, \"b\": 238 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"94c76f20-7f3d-4f8b-9a2a-bec75d120607\": {\n          \"name\": \"List\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9b628714-3fa2-490a-b766-4cf019ebe394\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 394,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 53.015125503173735,\n          \"focalY\": 37.93949798730505,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#d3d0ce\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page7_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"6f97df5b-14e7-4b83-be99-b82cd767f0ff\"\n        },\n        {\n          \"x\": 300,\n          \"y\": 511,\n          \"width\": 81,\n          \"height\": 30,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"962ba57a-da00-4ea0-8ac9-649c7996768d\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Learn</span>\\n<span style=\\\"font-weight: 500; color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 12,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 44,\n          \"y\": 366,\n          \"width\": 302,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"f4b2e739-5428-4639-8b71-b25630dac775\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Squash Soup&nbsp;</span>\\n<span style=\\\"font-weight: 700; color: #3a566e\\\">with Persimmon</span>\",\n          \"fontSize\": 33,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 44,\n          \"y\": 476,\n          \"width\": 73,\n          \"height\": 11,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"33d395dd-462d-4457-97c0-7b82f8c7c5d8\",\n          \"content\": \"<span style=\\\"color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Yield</span>\",\n          \"fontSize\": 11,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"a8093f87-4887-43e1-95f0-c65a4ac22dba\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 496,\n          \"width\": 88,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"6eff8e7e-7799-456b-9bd3-5abe4fffac5d\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">4-6 people</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"a8093f87-4887-43e1-95f0-c65a4ac22dba\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 556,\n          \"width\": 73,\n          \"height\": 11,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a5f5f1d9-015f-4f74-8bb7-a92e3ec3ea9a\",\n          \"content\": \"<span style=\\\"color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Type</span>\",\n          \"fontSize\": 11,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"6c3f4a0a-ebb5-499d-8770-2cf7686ee69d\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 573.5,\n          \"width\": 93,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"5ac12eaa-a7f3-4ded-8273-ba0d9f73955e\",\n          \"content\": \"<span style=\\\"color: #676461\\\">Vegetarian</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"6c3f4a0a-ebb5-499d-8770-2cf7686ee69d\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 479,\n          \"width\": 73,\n          \"height\": 11,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"296554e7-af85-41ab-8f40-44b091a1b3a8\",\n          \"content\": \"<span style=\\\"color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Time</span>\",\n          \"fontSize\": 11,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"58ae596f-c4c6-430d-984a-2a9cd32d4832\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 497,\n          \"width\": 92,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"b6d08619-ca6a-4466-8f40-e4845ec26eda\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">40 minutes</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"58ae596f-c4c6-430d-984a-2a9cd32d4832\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 555,\n          \"width\": 73,\n          \"height\": 11,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"36968290-c6c8-4de1-bb7b-b8faf7a5872e\",\n          \"content\": \"<span style=\\\"color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">Level</span>\",\n          \"fontSize\": 11,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"503f27dc-41ad-4022-90eb-2d8b9a60274b\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 573,\n          \"width\": 73,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a3d09960-be5c-4ce2-b6ef-669d2efa927b\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Beginner</span>\",\n          \"fontSize\": 17,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"503f27dc-41ad-4022-90eb-2d8b9a60274b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 329,\n          \"y\": 557,\n          \"width\": 22,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"cookingArrow\" },\n          \"id\": \"d360e57c-0318-4a5b-816f-9f89cefad82b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7b74fe49-d216-4258-b554-9a8f79ea85c1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a3d09960-be5c-4ce2-b6ef-669d2efa927b\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"adffc634-0fb0-40ad-a4a9-9371f8eefc21\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f4b2e739-5428-4639-8b71-b25630dac775\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"77350e31-6fbf-47d1-b64b-e31b00482df1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6eff8e7e-7799-456b-9bd3-5abe4fffac5d\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"991edd30-b817-4b0f-9be4-7c16f9c440ea\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"33d395dd-462d-4457-97c0-7b82f8c7c5d8\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ceb964f7-6d39-411e-b567-fe2267cb8226\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"296554e7-af85-41ab-8f40-44b091a1b3a8\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f01fe031-c41f-4e2c-8755-23070bb14326\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b6d08619-ca6a-4466-8f40-e4845ec26eda\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"55e7f462-4ace-4dda-808a-b43d5b9ff886\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a5f5f1d9-015f-4f74-8bb7-a92e3ec3ea9a\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3b6a228f-af0e-4e26-b810-c29843239078\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5ac12eaa-a7f3-4ded-8273-ba0d9f73955e\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b73637ee-72a9-4e27-8e5e-15d4db81e212\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"36968290-c6c8-4de1-bb7b-b8faf7a5872e\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c808e4d2-cb1f-4c7e-b5a3-568038e15c6c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6f97df5b-14e7-4b83-be99-b82cd767f0ff\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"c0a40237-d827-4aa3-b3ca-01e668dc90aa\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 249, \"b\": 238 } },\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"a8093f87-4887-43e1-95f0-c65a4ac22dba\": {\n          \"name\": \"Yield\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"58ae596f-c4c6-430d-984a-2a9cd32d4832\": {\n          \"name\": \"Time\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6c3f4a0a-ebb5-499d-8770-2cf7686ee69d\": {\n          \"name\": \"Type\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"503f27dc-41ad-4022-90eb-2d8b9a60274b\": {\n          \"name\": \"Level\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7805eaf2-f323-4b3e-8c2b-a328f3e95056\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 436,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 57.60565118552531,\n          \"focalY\": 38.56528948869127,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#ec8f13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page8_image1.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"page8_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"c9526803-1a13-4a9e-93ca-9f6d9b14cc61\"\n        },\n        {\n          \"x\": -2,\n          \"y\": -21,\n          \"width\": 413,\n          \"height\": 274,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"4377060a-594e-4d7d-a544-d6ab79b91c99\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff9ee\\\">3</span>\",\n          \"fontSize\": 274,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"marginOffset\": 0,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 481,\n          \"width\": 235,\n          \"height\": 105,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e474a0ae-051d-4788-8578-b5888531dac8\",\n          \"content\": \"<span style=\\\"color: #676461\\\">Rinse and dry your squash. Slice off the stem and bottom ends of the squash, so that both ends are flat. Slice the squash in half and lightly salt.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"width\": 66,\n          \"height\": 30,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">View</span>\\n<span style=\\\"font-weight: 500; color: #3a566e; letter-spacing: 0.25em; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 12,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"e0681907-a6fa-4d61-a7b1-ad71fc8b6335\",\n          \"x\": 307,\n          \"y\": 510\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.19,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">Prep the Squash</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 409,\n          \"width\": 303,\n          \"height\": 44,\n          \"id\": \"7781e785-f40d-440e-a76d-f6ae7c75f7a1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 329,\n          \"y\": 556,\n          \"width\": 22,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"cookingArrow\" },\n          \"id\": \"362aebb0-27dd-452a-9f21-db3a5c6dd59e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"90267d2d-16c5-4bf9-83bc-5da170d5ffde\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e474a0ae-051d-4788-8578-b5888531dac8\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1df1d4af-0db4-47b2-9c92-8949d1660096\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c9526803-1a13-4a9e-93ca-9f6d9b14cc61\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b05f3990-1931-4eca-b121-9284de483ce6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7781e785-f40d-440e-a76d-f6ae7c75f7a1\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1400,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"11f60c54-4345-4979-8f10-edf4b43c7f44\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 249, \"b\": 238 } },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"25cbd8d2-adac-46e7-8cbb-24ef7536a9f5\",\n          \"type\": \"shape\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 90,\n          \"y\": 31,\n          \"width\": 232,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Gelasio\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -700,\n              \"tAsc\": 1900,\n              \"tDes\": -700,\n              \"tLGap\": 0,\n              \"wAsc\": 2600,\n              \"wDes\": 800,\n              \"xH\": 986,\n              \"capH\": 1419,\n              \"yMin\": -635,\n              \"yMax\": 2593,\n              \"hAsc\": 1900,\n              \"hDes\": -700,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"a2be26e3-7314-4fc5-aa65-c69d390a173f\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #3a566e\\\">More stories</span>\",\n          \"fontSize\": 33,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 27,\n          \"y\": 96,\n          \"width\": 104,\n          \"height\": 104,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 150,\n          \"focalX\": 66.39097470744551,\n          \"focalY\": 64.85345906426349,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"f5d57c6a-fc29-4136-ba9d-08d3119d1cd2\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#b8a581\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page9_image1.jpg\",\n            \"width\": 220,\n            \"height\": 294,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"0aeeb417-3c72-4a82-942e-dca962375a60\"\n        },\n        {\n          \"x\": 147,\n          \"y\": 137.5,\n          \"width\": 234,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"c4a34697-400c-4b45-8646-b81c1ada574f\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Our best taco recipes to date</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"0aeeb417-3c72-4a82-942e-dca962375a60\"\n        },\n        {\n          \"x\": 27,\n          \"y\": 199,\n          \"width\": 104,\n          \"height\": 104,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 50,\n          \"focalY\": 57.634470218345214,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#cdc3b9\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page9_image2.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"90256502-5ed3-4354-90f3-16ef1e0d1d3a\",\n          \"groupId\": \"a3b03eae-2040-4198-a68b-458c5f6ad925\"\n        },\n        {\n          \"x\": 147,\n          \"y\": 240.5,\n          \"width\": 234,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"8b2ad361-4db2-41ef-9f96-142b4f150556\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Comfort food for all occasions</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"a3b03eae-2040-4198-a68b-458c5f6ad925\"\n        },\n        {\n          \"x\": 27,\n          \"y\": 302,\n          \"width\": 104,\n          \"height\": 104,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#d7ced6\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page9_image3.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"73ba04c5-2f32-44c3-9c96-a9300e9c4e89\",\n          \"groupId\": \"31ad6d42-0256-4c0c-ab1e-04082d4383c1\"\n        },\n        {\n          \"x\": 147,\n          \"y\": 344.5,\n          \"width\": 234,\n          \"height\": 21,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"55aae5bd-87d3-4ecb-add2-ed214ce75805\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Desserts you can’t live without</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"31ad6d42-0256-4c0c-ab1e-04082d4383c1\"\n        },\n        {\n          \"x\": 27,\n          \"y\": 405,\n          \"width\": 104,\n          \"height\": 104,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#2c2622\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page9_image4.jpg\",\n            \"width\": 220,\n            \"height\": 284,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image4\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"2729ff59-dfa0-4d0d-9023-de6d26f812ac\",\n          \"groupId\": \"0cb22084-123b-45d1-a397-969199f9cfef\"\n        },\n        {\n          \"x\": 147,\n          \"y\": 438,\n          \"width\": 180,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"21aed5d1-b061-4a20-87e8-3e9c9b804d41\",\n          \"content\": \"<span style=\\\"color: rgba(103, 100, 97, 1)\\\">Easy brunch recipes that will impress your guests</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"0cb22084-123b-45d1-a397-969199f9cfef\"\n        },\n        {\n          \"width\": 104,\n          \"height\": 104,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 150,\n          \"focalX\": 66.39097470744551,\n          \"focalY\": 64.85345906426349,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#b8a581\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/food-and-stuff/page9_image1.jpg\",\n            \"width\": 220,\n            \"height\": 294,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"3e2b3e2f-40a7-4301-9dae-4a8772ecad92\",\n          \"x\": 27,\n          \"y\": 509,\n          \"groupId\": \"e7acd16b-2976-4547-9da0-94dc8bed00fa\"\n        },\n        {\n          \"width\": 174,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Andada Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 942,\n              \"des\": -235,\n              \"tAsc\": 942,\n              \"tDes\": -235,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 390,\n              \"xH\": 494,\n              \"capH\": 705,\n              \"yMin\": -382,\n              \"yMax\": 1068,\n              \"hAsc\": 942,\n              \"hDes\": -235,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #676461\\\">Easy steak tacos</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"cf0ee6ac-7b90-4c56-b5d4-0062726c42e1\",\n          \"x\": 148,\n          \"y\": 551,\n          \"groupId\": \"e7acd16b-2976-4547-9da0-94dc8bed00fa\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ae17c7f8-43a6-44d5-9bcc-0031581bd5bf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"55aae5bd-87d3-4ecb-add2-ed214ce75805\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0f81ea24-0ea8-4278-b65e-d35ee5ac35e5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"21aed5d1-b061-4a20-87e8-3e9c9b804d41\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"4bf00d38-ea58-4f10-875a-823ee78c5813\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a2be26e3-7314-4fc5-aa65-c69d390a173f\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"745d0f25-de58-48d2-a0bc-8065b9ebabf3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c4a34697-400c-4b45-8646-b81c1ada574f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"7af36104-93cd-4157-8e25-a50e33c0702b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8b2ad361-4db2-41ef-9f96-142b4f150556\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"1513a478-27d9-48cb-ae2d-3e47601bcfd9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cf0ee6ac-7b90-4c56-b5d4-0062726c42e1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c0bb905e-339f-46ad-abf3-434b79093685\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"f5d57c6a-fc29-4136-ba9d-08d3119d1cd2\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"d924781c-0e25-4ee8-966c-8378816d8f95\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"90256502-5ed3-4354-90f3-16ef1e0d1d3a\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"95fbb7e8-5cd4-4854-811f-b4c41c5878cb\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"73ba04c5-2f32-44c3-9c96-a9300e9c4e89\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"82e48d2a-7bbb-4681-b3f2-531f4815227c\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"2729ff59-dfa0-4d0d-9023-de6d26f812ac\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"f272fbab-249d-47b0-bc2f-117acf646adf\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"3e2b3e2f-40a7-4301-9dae-4a8772ecad92\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 400\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e8a21c0b-1db7-4777-b25d-b7d9a51b10fe\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 249, \"b\": 238 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"0aeeb417-3c72-4a82-942e-dca962375a60\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a3b03eae-2040-4198-a68b-458c5f6ad925\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"31ad6d42-0256-4c0c-ab1e-04082d4383c1\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0cb22084-123b-45d1-a397-969199f9cfef\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e7acd16b-2976-4547-9da0-94dc8bed00fa\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fresh-and-bright/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/fresh-and-bright/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'fresh-and-bright',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Fresh & Bright', 'template name', 'web-stories'),\n  tags: [\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Bold', 'template keyword', 'web-stories'),\n    _x('Joy', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Pink', 'color', 'web-stories'),\n      color: '#f3d9e1',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Green', 'color', 'web-stories'),\n      color: '#d8ddcc',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#28292b',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Brown', 'color', 'web-stories'),\n      color: '#eadfd6',\n      family: _x('Brown', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'The modern and bright Beauty template lends itself well as a foundation for stories covering makeup, beauty products, shopping guides, instructions & tutorials and more.',\n    'web-stories'\n  ),\n  vertical: _x('Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/fresh-and-bright/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/fresh-and-bright/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 234,\n          \"y\": -160,\n          \"width\": 206,\n          \"height\": 366,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"9ecb248e-2adc-4834-a270-01325263a30e\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page1_bg-alt.png\",\n            \"width\": 206,\n            \"height\": 366,\n            \"id\": 0,\n            \"alt\": \"page1_bg-alt\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#35312f\"\n          },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 217, \"b\": 225 } },\n          \"type\": \"shape\",\n          \"x\": -6,\n          \"y\": 415,\n          \"width\": 798,\n          \"height\": 382,\n          \"mask\": { \"type\": \"brush-stroke-1\" },\n          \"id\": \"c2cb4adc-8209-4441-83f3-94fb5dba59eb\",\n          \"groupId\": \"f183f9bc-8bcd-4fa9-8530-425af0f604bd\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 442,\n          \"width\": 337,\n          \"height\": 165,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"25b6f99b-3f69-4351-9e18-31b8ef1d1a61\",\n          \"content\": \"<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">Fresh</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">&amp;&nbsp;</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">Bright</span>\",\n          \"fontSize\": 55,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"f183f9bc-8bcd-4fa9-8530-425af0f604bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page1_logo-generic.png\",\n            \"width\": 32,\n            \"height\": 10,\n            \"id\": 0,\n            \"alt\": \"page1_logo-generic\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 42,\n          \"y\": 22,\n          \"width\": 60,\n          \"height\": 19,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"9f187764-e909-416f-8820-9d24ac15f192\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"17fa9c85-89c7-47d0-a7a8-29f6ef56e161\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"eaf6765f-8506-48c9-a526-15917b431464\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"f183f9bc-8bcd-4fa9-8530-425af0f604bd\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ef056bde-fdc3-4f71-809a-e69c62ae914d\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 118.5,\n          \"y\": 554,\n          \"width\": 175,\n          \"height\": 36,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"96e93ceb-accb-4c38-b603-7d616174e5d3\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #28292b\\\">Anonymous</span>\",\n          \"fontSize\": 28,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 40,\n          \"y\": 3,\n          \"width\": 66,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"beautyHeart\" },\n          \"id\": \"bd8f9376-7962-44a0-b2b7-175ab75b9d58\",\n          \"groupId\": \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 66,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"beautyHeart\" },\n          \"id\": \"254ac1ec-228e-424f-ab2f-392364e08947\",\n          \"x\": 316,\n          \"y\": 45,\n          \"groupId\": \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 66,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"beautyHeart\" },\n          \"id\": \"3797ec08-e931-4774-a4bd-9f91af2439f5\",\n          \"x\": 30,\n          \"y\": 235,\n          \"groupId\": \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 66,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"beautyHeart\" },\n          \"id\": \"98375f28-5877-481d-a08d-a0b525af943c\",\n          \"x\": 337,\n          \"y\": 540,\n          \"groupId\": \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 66,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"beautyHeart\" },\n          \"id\": \"19df8224-87e4-4d81-a452-43b6d0a218f5\",\n          \"x\": 6,\n          \"y\": 590,\n          \"groupId\": \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\"\n        },\n        {\n          \"x\": 61,\n          \"y\": 26,\n          \"width\": 309,\n          \"height\": 539,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.02,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"51e3dfb3-fe95-4132-ade1-cd226982cf68\",\n          \"content\": \"<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">I</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">woke</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">up</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">like</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">this</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">”</span>\",\n          \"fontSize\": 88,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"808d6cd9-2a3b-4194-9c0c-d92f1e9c0198\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"51e3dfb3-fe95-4132-ade1-cd226982cf68\"],\n          \"scale\": 0.15,\n          \"iterations\": 1,\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b933a01b-f276-4da4-8c6a-47593c332fdb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"96e93ceb-accb-4c38-b603-7d616174e5d3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 900,\n          \"delay\": 1000\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"65359a38-f1fa-4048-9b99-9415147b74d3\",\n      \"backgroundColor\": { \"color\": { \"r\": 233, \"g\": 213, \"b\": 197 } },\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"dc20376a-95ab-4347-9ea4-5b6864a83a7a\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f20aa1b3-6e99-4b87-9088-8fafd8d1f2b0\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 125,\n          \"y\": -17,\n          \"width\": 216,\n          \"height\": 324,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 221, \"b\": 204 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"9f1b4f10-f779-4a36-9833-baef0c4530a4\"\n        },\n        {\n          \"x\": 97,\n          \"y\": 12,\n          \"width\": 216,\n          \"height\": 324,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 221, \"b\": 204 } },\n          \"scale\": 120,\n          \"focalX\": 60.636029423263835,\n          \"focalY\": 58.06001706624724,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"254e9e10-3f62-4e5a-8184-35f7aa9f15b8\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page3_figure.jpg\",\n            \"width\": 220,\n            \"height\": 258,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_figure\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#89adb7\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 221, \"b\": 204 } },\n          \"type\": \"shape\",\n          \"x\": -31,\n          \"y\": 353,\n          \"width\": 895,\n          \"height\": 312,\n          \"mask\": { \"type\": \"brush-stroke-1\" },\n          \"id\": \"9b89eb4a-f9fa-408f-b5df-8d7f9324309c\",\n          \"groupId\": \"327c1303-ef75-4ea2-97da-7fdc57adb40c\"\n        },\n        {\n          \"x\": 20,\n          \"y\": 411,\n          \"width\": 371,\n          \"height\": 88,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"8922e664-91d5-422d-86a8-8dda035c39d8\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #28292b\\\">Sun Protection</span>\\nDone Right\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"327c1303-ef75-4ea2-97da-7fdc57adb40c\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 52,\n          \"y\": 512,\n          \"width\": 308,\n          \"height\": 88,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.375,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"b93fdb3d-22a9-4f54-bcdc-5c9c0aa7117c\",\n          \"content\": \"<span style=\\\"color: #28292b\\\">We’ve done our research so you don’t have to. These sheer sun screens protect your skin from UVA and UVBs while also posing no harm to the environment.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"327c1303-ef75-4ea2-97da-7fdc57adb40c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"06fe7228-c6e8-48b0-b725-18e8dc95793d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8922e664-91d5-422d-86a8-8dda035c39d8\"],\n          \"duration\": 3000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"082939f3-6f5b-48fe-9100-8cbaa2194e1f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b93fdb3d-22a9-4f54-bcdc-5c9c0aa7117c\"],\n          \"duration\": 3500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"724a4956-c962-4f0c-b2cb-cab9f268e49f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"254e9e10-3f62-4e5a-8184-35f7aa9f15b8\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"d61b5acc-03ab-42f9-893d-aa7a1765f607\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9f1b4f10-f779-4a36-9833-baef0c4530a4\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1400,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e71288c8-1c09-4abd-8e59-db479c97cef2\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"327c1303-ef75-4ea2-97da-7fdc57adb40c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"98d7eb94-0a2d-4dff-b1bc-83b1487d37ee\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page4_bg.png\",\n            \"width\": 220,\n            \"height\": 391,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_bg\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#252110\"\n          },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"beautyCta\" },\n          \"id\": \"6e2c6c31-800c-40b4-8b4c-423e875fa897\",\n          \"x\": 164,\n          \"y\": 125,\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"beautyCta\" },\n          \"id\": \"44e92a2d-e8ce-47fb-a081-5d84792272ce\",\n          \"x\": 102,\n          \"y\": 302,\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 71,\n          \"y\": 416,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"beautyCta\" },\n          \"id\": \"ba504f4a-7eee-4e86-add7-6fb6c15166c7\",\n          \"link\": {\n            \"url\": \"http://example.com\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"17e6fcb3-d3e9-43b8-9e10-67b386af4912\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"ba504f4a-7eee-4e86-add7-6fb6c15166c7\"],\n          \"scale\": 0.3,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"0239d43e-460f-4b5e-9924-59557ffd97c9\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"44e92a2d-e8ce-47fb-a081-5d84792272ce\"],\n          \"scale\": 0.3,\n          \"iterations\": 1,\n          \"duration\": 1601,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"c884fc80-6cb0-444f-89b5-482ccb4bb350\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"6e2c6c31-800c-40b4-8b4c-423e875fa897\"],\n          \"scale\": 0.3,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"31982a98-dcce-44b0-8280-15614e2b67f2\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b9d953bb-b69e-4d97-a5b8-61136fe83c0f\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"73511558-2879-461f-a983-d872d0436048\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": 235,\n          \"width\": 413,\n          \"height\": 440,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.09652605991262,\n          \"focalY\": 57.52895834886181,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"91a4a6fc-9c99-49dd-a70b-cd31d0f8ad11\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page5_figure.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page5_figure\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#c9a3ab\"\n          }\n        },\n        {\n          \"x\": 47,\n          \"y\": 19,\n          \"width\": 337,\n          \"height\": 165,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"65b49662-1ad8-4478-8fe9-98a7b60b2ea4\",\n          \"content\": \"<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">Gifts</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">for</span>\\n<span style=\\\"color: #28292b; letter-spacing: 0.09em; text-transform: uppercase\\\">under</span>\",\n          \"fontSize\": 55,\n          \"padding\": {\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 89,\n          \"y\": 185,\n          \"width\": 235,\n          \"height\": 92,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"e4be23ed-5219-4df3-8cde-5a9a2e571f8f\",\n          \"content\": \"<span style=\\\"color: #28292b; letter-spacing: 0.09em\\\">$20</span>\",\n          \"fontSize\": 92,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"082c66f8-545c-428a-99f1-0b23e392155a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"91a4a6fc-9c99-49dd-a70b-cd31d0f8ad11\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1400,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"d7012c1e-a1aa-422a-b101-a3fc935d1c17\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e4be23ed-5219-4df3-8cde-5a9a2e571f8f\"],\n          \"scale\": 0.3,\n          \"iterations\": 1,\n          \"duration\": 1601,\n          \"delay\": 50\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"a31f98d0-13a5-4904-860b-61a6ce35d36c\",\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 217, \"b\": 225 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"fe20d9ff-158b-4948-adae-cba1d9a2b25b\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 140,\n          \"y\": -2,\n          \"width\": 131,\n          \"height\": 100,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"53c22575-7ab2-4c00-931d-b0a8b68b7464\",\n          \"content\": \"<span style=\\\"color: #28292b\\\">1</span>\",\n          \"fontSize\": 100,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"87d2a5bd-e2c5-4722-8b2e-909f1dd4abc2\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 25,\n          \"y\": 101,\n          \"width\": 362,\n          \"height\": 57,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"6db599ec-da49-4694-ad37-9384644b0f8d\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">Natural Beauty</span></span>\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"87d2a5bd-e2c5-4722-8b2e-909f1dd4abc2\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 157,\n          \"width\": 334,\n          \"height\": 43,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.375,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c7cb3455-9a2e-4af4-8098-e5f04567b377\",\n          \"content\": \"<span style=\\\"color: #28292b\\\">For that friend who barely wears makeup</span>\\n<span style=\\\"color: #28292b\\\">but likes to add a little sparkle.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"87d2a5bd-e2c5-4722-8b2e-909f1dd4abc2\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 356,\n          \"width\": 280,\n          \"height\": 204,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 217, \"b\": 225 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"2c9f4240-6d4e-4c26-a62b-bb628a0ae34e\"\n        },\n        {\n          \"x\": 74,\n          \"y\": 263,\n          \"width\": 251,\n          \"height\": 185,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page6_figure.jpg\",\n            \"width\": 220,\n            \"height\": 174,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_figure\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#dac5b5\"\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"9fe9caa0-d046-40d2-8e22-a8a88fbbdbfd\"\n        },\n        {\n          \"x\": 255,\n          \"y\": 505,\n          \"width\": 115,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"b21c003f-d5ad-4829-8ebd-4fe39746ec36\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 500\\\">Buy Now</span></span>\",\n          \"fontSize\": 15,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          }\n        },\n        {\n          \"x\": 25,\n          \"y\": 489,\n          \"width\": 189,\n          \"height\": 52,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ef299f55-6f0c-4a50-80e4-254eb5d0e633\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #28292b\\\">Lid Shimmer $12</span>\\n<span style=\\\"color: #28292b\\\">website.com</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5478b348-c58c-4944-b6b1-f1ebe08762a4\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"53c22575-7ab2-4c00-931d-b0a8b68b7464\"],\n          \"scale\": 0.3,\n          \"iterations\": 1,\n          \"duration\": 1800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0960a8ea-8b31-4111-b4c3-e4f8b24db058\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6db599ec-da49-4694-ad37-9384644b0f8d\"],\n          \"duration\": 3000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"2f5fdba2-ff33-44d6-8ace-e9aaf5f723c3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c7cb3455-9a2e-4af4-8098-e5f04567b377\"],\n          \"duration\": 3000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"a3eec247-1d15-4260-b01d-0dd451e4dc01\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9fe9caa0-d046-40d2-8e22-a8a88fbbdbfd\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"173b610b-392d-4bd1-a3c4-747c7535ba5c\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"87d2a5bd-e2c5-4722-8b2e-909f1dd4abc2\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"17f22a0e-aae4-4eff-9cee-5020ca545950\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -1,\n          \"y\": 392,\n          \"width\": 296,\n          \"height\": 225,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 221, \"b\": 204 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"66c7e85f-72de-4dda-93cd-c3d114332275\",\n          \"groupId\": \"af5acc97-c15f-4d25-ae68-49e2a4cfb9d5\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 358,\n          \"width\": 285,\n          \"height\": 179,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 140,\n          \"focalX\": 46.14708413831984,\n          \"focalY\": 62.898892232581424,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"8e829ac4-0b1a-42b5-b519-a7941b98b768\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page7_product2.jpg\",\n            \"width\": 220,\n            \"height\": 184,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_product2\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#a87155\"\n          },\n          \"groupId\": \"af5acc97-c15f-4d25-ae68-49e2a4cfb9d5\"\n        },\n        {\n          \"x\": 53,\n          \"y\": 555,\n          \"width\": 189,\n          \"height\": 26,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ac0add24-bf97-46a4-abe0-1241f0e91a20\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">Lid Shimmer $12</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"af5acc97-c15f-4d25-ae68-49e2a4cfb9d5\"\n        },\n        {\n          \"x\": 53,\n          \"y\": 576,\n          \"width\": 239,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"479bdbea-1369-40c8-bcb7-96d82fb8b36c\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\">website.com</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"af5acc97-c15f-4d25-ae68-49e2a4cfb9d5\"\n        },\n        {\n          \"x\": 135,\n          \"y\": 74,\n          \"width\": 277,\n          \"height\": 243,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 221, \"b\": 204 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"6b601d9d-0aa0-4c11-8077-19881fb1f744\",\n          \"groupId\": \"76b1a926-7a44-4dba-8a75-668acfb884e4\"\n        },\n        {\n          \"x\": 167,\n          \"y\": -57,\n          \"width\": 212,\n          \"height\": 264,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"ca75cd7a-c9d1-48ac-8d4a-1268023e88d3\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page7_product1.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_product1\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#cfb1aa\"\n          },\n          \"groupId\": \"76b1a926-7a44-4dba-8a75-668acfb884e4\"\n        },\n        {\n          \"x\": 236,\n          \"y\": 231,\n          \"width\": 189,\n          \"height\": 26,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"d07cf4f9-46d9-420c-aa06-ad4e406b7a42\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">Lip Tattoo $18</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"76b1a926-7a44-4dba-8a75-668acfb884e4\"\n        },\n        {\n          \"x\": 236,\n          \"y\": 253,\n          \"width\": 239,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"6017e32e-c0fb-4ea3-8876-aaaa1b2bbef5\",\n          \"content\": \"<span style=\\\"color: #28292b\\\">website.com</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"76b1a926-7a44-4dba-8a75-668acfb884e4\"\n        },\n        {\n          \"x\": 71,\n          \"y\": 233,\n          \"width\": 123,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 500\\\">Buy Now</span></span>\",\n          \"fontSize\": 15,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"id\": \"fc58f262-ffa0-4d0c-a233-a95aa62d27ad\"\n        },\n        {\n          \"x\": 252,\n          \"y\": 557,\n          \"width\": 123,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 500\\\">Buy Now</span></span>\",\n          \"fontSize\": 15,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"id\": \"04968afa-8979-49ea-a445-43865ea4099e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dcd834e8-23ae-4725-bbdb-bf81276e0f9a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ca75cd7a-c9d1-48ac-8d4a-1268023e88d3\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d0778698-92fd-40a0-a2a4-a047ae014cea\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8e829ac4-0b1a-42b5-b519-a7941b98b768\"],\n          \"duration\": 3000,\n          \"delay\": 200\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"9845d2e8-8afe-448b-b7c7-ed1b5e30ab69\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"af5acc97-c15f-4d25-ae68-49e2a4cfb9d5\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"76b1a926-7a44-4dba-8a75-668acfb884e4\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 5,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bc3bdf9d-3f6d-428c-be02-82e004339ab4\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 52,\n          \"y\": 19,\n          \"width\": 308,\n          \"height\": 88,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"7ad20266-6a32-4038-8ed7-d84b8f697532\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">TV Inspired\\nMake-up</span></span>\",\n          \"fontSize\": 44,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 64,\n          \"y\": 129,\n          \"width\": 284,\n          \"height\": 67,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.37,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"3eafb106-5681-4bba-9eef-b162d3364486\",\n          \"content\": \"<span style=\\\"color: #28292b\\\">Want to look like Hunter Schafer from “Euphoria”? We got’chyu, plus looks from the rest of the cast.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 103,\n          \"y\": 255,\n          \"width\": 204,\n          \"height\": 272,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"1fd9e47b-c054-4966-8b5e-8288726a1463\"\n        },\n        {\n          \"x\": 145,\n          \"y\": 554,\n          \"width\": 125,\n          \"height\": 43,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Get The Look</span>\",\n          \"fontSize\": 16,\n          \"padding\": {\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"id\": \"0ab67d94-4d3a-423d-acfb-444d1c8359e4\"\n        },\n        {\n          \"x\": 135,\n          \"y\": 225,\n          \"width\": 204,\n          \"height\": 272,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"7d267050-70a4-4fdb-849e-f91092d8fda4\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page8_figure.jpg\",\n            \"width\": 370,\n            \"height\": 492,\n            \"id\": 0,\n            \"alt\": \"page8_figure\",\n            \"isExternal\": true,\n            \"baseColor\": \"#e1d3c9\",\n            \"sizes\": []\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"37f59a5b-2a14-459d-977b-03c6c4fac785\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7ad20266-6a32-4038-8ed7-d84b8f697532\"],\n          \"duration\": 3000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"b5afd6f6-6762-48ee-98bd-278d76e55974\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7d267050-70a4-4fdb-849e-f91092d8fda4\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"491a005e-b439-401a-aae3-41fda4460fd4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3eafb106-5681-4bba-9eef-b162d3364486\"],\n          \"duration\": 3500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"cd55eb72-dbab-49e8-a079-bd6ee00302e8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1fd9e47b-c054-4966-8b5e-8288726a1463\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1400,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"d605aece-b940-4ae4-8917-562ffba57c53\",\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 217, \"b\": 225 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d07dfc60-f3b6-4295-b687-012dd2cfdf8c\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 37,\n          \"y\": 19,\n          \"width\": 337,\n          \"height\": 111,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"2d2d9987-93c3-4c06-83c4-8e59dff41e48\",\n          \"content\": \"<span style=\\\"color: #28292b; text-transform: uppercase\\\">More</span>\\n<span style=\\\"color: #28292b; text-transform: uppercase\\\">Stories</span>\",\n          \"fontSize\": 55,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 234, \"g\": 223, \"b\": 214 } },\n          \"type\": \"shape\",\n          \"x\": -15,\n          \"y\": 157,\n          \"width\": 496,\n          \"height\": 134,\n          \"mask\": { \"type\": \"brush-stroke-2\" },\n          \"id\": \"6ec575af-42c7-4b91-b0ed-49780a002117\",\n          \"groupId\": \"e6a435ef-5381-4ded-9ef6-dd0a231aa17a\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 165,\n          \"width\": 116,\n          \"height\": 116,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 220,\n          \"focalX\": 29.72407681721303,\n          \"focalY\": 49.98987897855799,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"7fc72830-25a5-47a0-8228-d1adee50581e\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page9_story1.jpg\",\n            \"width\": 220,\n            \"height\": 124,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_story1\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#dbdbdc\"\n          },\n          \"groupId\": \"e6a435ef-5381-4ded-9ef6-dd0a231aa17a\"\n        },\n        {\n          \"x\": 205,\n          \"y\": 203,\n          \"width\": 187,\n          \"height\": 40,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e5f86bbb-dd3e-431a-aae3-5a8e00cf6d0f\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">Top 10 Bronzing\\nKits for Summer</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"e6a435ef-5381-4ded-9ef6-dd0a231aa17a\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 220, \"g\": 196, \"b\": 178 } },\n          \"type\": \"shape\",\n          \"width\": 704,\n          \"height\": 152,\n          \"mask\": { \"type\": \"brush-stroke-2\" },\n          \"id\": \"95bffcec-5323-4f5d-9eea-8402d676bd2e\",\n          \"x\": -15,\n          \"y\": 454,\n          \"groupId\": \"593a20fa-0ca6-4353-a11b-48abe8cd4227\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 463,\n          \"width\": 116,\n          \"height\": 116,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.133512681795544,\n          \"focalY\": 41.18825111898196,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"f36a0781-1fa1-4cf5-9d88-c5a4140f9e77\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#3b2220\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page9_story3.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_story3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"593a20fa-0ca6-4353-a11b-48abe8cd4227\"\n        },\n        {\n          \"x\": 205,\n          \"y\": 501,\n          \"width\": 187,\n          \"height\": 40,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"6405d5d0-89ec-4f1e-976e-48eed941608d\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">Use the Fenty\\nShade Finder</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"593a20fa-0ca6-4353-a11b-48abe8cd4227\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 233, \"g\": 213, \"b\": 197 } },\n          \"type\": \"shape\",\n          \"width\": 569,\n          \"height\": 127,\n          \"mask\": { \"type\": \"brush-stroke-2\" },\n          \"id\": \"c83e126a-96a0-4131-8906-6ed69881877e\",\n          \"x\": -166,\n          \"y\": 310,\n          \"groupId\": \"d5380682-3183-4269-ae52-e8835dcd4070\"\n        },\n        {\n          \"x\": 248,\n          \"y\": 318,\n          \"width\": 116,\n          \"height\": 116,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.133512681795565,\n          \"focalY\": 55.87449925401202,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"eb703bda-f03c-44b1-8df7-a7970252e4ea\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#e24e51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/fresh-and-bright/page9_story2.jpg\",\n            \"width\": 352,\n            \"height\": 528,\n            \"id\": 0,\n            \"alt\": \"page9_story2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"d5380682-3183-4269-ae52-e8835dcd4070\"\n        },\n        {\n          \"x\": 40,\n          \"y\": 356,\n          \"width\": 187,\n          \"height\": 40,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Chivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -250,\n              \"tAsc\": 940,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 250,\n              \"xH\": 511,\n              \"capH\": 686,\n              \"yMin\": -250,\n              \"yMax\": 926,\n              \"hAsc\": 940,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"41f71d08-27df-4137-94b7-eaf0aec0d16c\",\n          \"content\": \"<span style=\\\"color: rgba(40, 41, 43, 1)\\\"><span style=\\\"font-weight: 900\\\">This Year’s\\nK-Beauty Trends</span></span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d5380682-3183-4269-ae52-e8835dcd4070\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2033faa2-f3b7-480f-8490-7db526a29d88\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"2d2d9987-93c3-4c06-83c4-8e59dff41e48\"],\n          \"scale\": 0.15,\n          \"iterations\": 1,\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"343fd1f3-125e-429c-8dd6-48788c170092\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7fc72830-25a5-47a0-8228-d1adee50581e\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"822b830e-4e8b-4a21-93c7-943a36070bd5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"eb703bda-f03c-44b1-8df7-a7970252e4ea\"],\n          \"duration\": 1201,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"def20f5c-9cf8-43e7-9133-92af7e44de94\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f36a0781-1fa1-4cf5-9d88-c5a4140f9e77\"],\n          \"duration\": 1200,\n          \"delay\": 200\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"edf299b1-e35a-4049-9e66-a08dcee8b936\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"e6a435ef-5381-4ded-9ef6-dd0a231aa17a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d5380682-3183-4269-ae52-e8835dcd4070\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"593a20fa-0ca6-4353-a11b-48abe8cd4227\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/google-music-studio-tour/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/google-music-studio-tour/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'google-music-studio-tour',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Google Music Studio Tour', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Interior', 'template keyword', 'web-stories'),\n    _x('Office', 'template keyword', 'web-stories'),\n    _x('Informational', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black Timber', 'color', 'web-stories'),\n      color: '#2f2f37',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Whole Wheat Brown', 'color', 'web-stories'),\n      color: '#ddc69e',\n      family: _x('Brown', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s formal yet friendly appearance will let you create stories that are informational but also fun to watch. Present office and studio tours, showcase desk setups, inspire your audience with interior ideas, or do something else entirely. The possibilities are endless.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/google-music-studio-tour/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/google-music-studio-tour/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0ad8c5be-2d34-4cc7-89f4-008bad44c14e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.15,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #ddc69e\\\">Sneak Peek: Google Music’s Brand New</span>\\n<span style=\\\"font-weight: 500; color: #ddc69e\\\">Studio</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 50,\n          \"y\": 23,\n          \"width\": 288,\n          \"height\": 169,\n          \"id\": \"125ececa-af85-43bc-8cde-5c03adb0404c\",\n          \"type\": \"text\",\n          \"groupId\": \"ec78ff49-e4f8-4921-8aca-4dfeeeb59be9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff8ed; letter-spacing: 0.12em; text-transform: uppercase\\\">Brooklyn Simmons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 49,\n          \"y\": 232,\n          \"width\": 179,\n          \"height\": 13,\n          \"id\": \"3439c68e-202a-4873-a310-c39b4264c8c2\",\n          \"type\": \"text\",\n          \"groupId\": \"ec78ff49-e4f8-4921-8aca-4dfeeeb59be9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 49,\n          \"y\": 264,\n          \"width\": 315,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ee0e83dd-a941-4ea7-a298-b325f98b1c63\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 150,\n          \"focalX\": 54.57777773115227,\n          \"focalY\": 51.90740738798011,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:42:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page1_img3.jpg\",\n            \"width\": 1080,\n            \"height\": 864,\n            \"id\": 0,\n            \"alt\": \"Beige wooden conference table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b4a99b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 294,\n          \"width\": 198,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a2998fed-80ac-44b7-aabe-dade59949ce1\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:42:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page1_img2.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Black floor lamp on living room sofa\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cac8c6\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 202,\n          \"height\": 322,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8f0263c1-0944-408f-8d4d-5d38e9316efe\",\n          \"x\": 210,\n          \"y\": 294,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 120,\n          \"focalX\": 47.109988797738595,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:41:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page1_7_11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Photo of dining table and chairs inside room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#4d4836\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 198,\n          \"height\": 130,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"633c9283-8ef8-41eb-b3a7-9373c86e4fc3\",\n          \"x\": 0,\n          \"y\": 545,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"444c59da-134a-4945-b8aa-f0e59aae33b7\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"ec78ff49-e4f8-4921-8aca-4dfeeeb59be9\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"10b90d09-8349-4c22-a121-5000a7a09e07\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 170,\n          \"focalX\": 33.02370466171847,\n          \"focalY\": 43.84347505361102,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:43:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Woman walking on staircase during daytim\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cca68f\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 402,\n          \"height\": 503,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"40d6fec1-0a32-4f5d-873e-1be45ecd7693\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 18,\n          \"id\": \"de77e334-66ff-40fc-a26a-2453c2a25f82\",\n          \"type\": \"text\",\n          \"groupId\": \"fc1d6a7d-f651-46ef-a379-360f36720afc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Entrance</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 25,\n          \"id\": \"84872cde-2bc2-45d4-b318-22445a71f266\",\n          \"type\": \"text\",\n          \"groupId\": \"fc1d6a7d-f651-46ef-a379-360f36720afc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">An unassuming building entrance feels like any other workspace, yet it’s private. And it’s a decoy for our famous artists.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 58,\n          \"id\": \"36ef2da0-0f0b-4eac-8496-2e57116293b0\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"fc1d6a7d-f651-46ef-a379-360f36720afc\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"56eaa91d-423e-427a-b9de-213d0c29d31c\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"fc1d6a7d-f651-46ef-a379-360f36720afc\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"692e5293-73a5-4bb4-86d1-87e8fb2b2f8c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:44:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Square white wooden tables and chairs\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#bdb4b0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 371,\n          \"height\": 238,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"02061991-6dd9-4e42-b44a-1509d4919579\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 125,\n          \"focalX\": 54.04491103333794,\n          \"focalY\": 46.755905547288876,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:44:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page3_7_img2.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"White living room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d3ccc3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 366,\n          \"height\": 254,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a16488af-5fe8-48f5-a0d5-d08d0e465b3c\",\n          \"x\": 46,\n          \"y\": 190,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 17,\n          \"id\": \"5d14df3a-4f1e-4c21-86be-08c4ccff261e\",\n          \"type\": \"text\",\n          \"groupId\": \"0148e1b6-a50c-4e34-bc3a-0b70854778f6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">1st Floor</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"ce15f1ea-9ccd-4afe-a5e9-6d155377ba0f\",\n          \"type\": \"text\",\n          \"groupId\": \"0148e1b6-a50c-4e34-bc3a-0b70854778f6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Gateways to individual recording studios with their own private lounges and concierges are the special touches.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"47b388e1-e39e-414d-afa3-d4dbb71a1ddf\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"0148e1b6-a50c-4e34-bc3a-0b70854778f6\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"76adfebf-ad05-4c57-9dea-860499dcd9c5\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0148e1b6-a50c-4e34-bc3a-0b70854778f6\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9875cce5-2c49-4f43-aacd-7b38811e85b7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:44:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page4_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 715,\n            \"id\": 0,\n            \"alt\": \"Floor plan of a house\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#f3f1ef\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 46,\n          \"y\": 0,\n          \"width\": 365,\n          \"height\": 437,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7dab73f7-9a04-4b68-9790-83db99739bf5\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 17,\n          \"id\": \"2970ce17-8640-485c-841f-cab4f05662f1\",\n          \"type\": \"text\",\n          \"groupId\": \"b40bca61-abae-40ef-9aa7-1511f57da051\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Blueprint of the building</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"ab2a16d2-a06e-4b1c-9a6f-5a0c954ecfad\",\n          \"type\": \"text\",\n          \"groupId\": \"b40bca61-abae-40ef-9aa7-1511f57da051\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">We’ve been intentional about each floor and who gets the most benefit out of each area of the building.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"48266e4a-ed7d-402c-8c45-43c65cd9798e\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"b40bca61-abae-40ef-9aa7-1511f57da051\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"b235c3a6-2002-4b08-a5dc-70c1dbb8a7ec\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"b40bca61-abae-40ef-9aa7-1511f57da051\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 174,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"e2935f43-0835-4602-a8d2-3b3b2b7b3e44\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-22T09:46:52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page5_vid1.mp4\",\n            \"width\": 1365,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page5_vid1-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"Video footage of a table and chairs in a modern office\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#b2aaae\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"loop\": true\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"25b9da52-47da-4438-b519-b4748e7548c3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"36c146f8-b44b-4f32-b7ff-d5b8878b57f1\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8e639a1d-6e09-41d7-b102-4ff37c84cc3c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:44:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page6_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Empty wooden table and chairs\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d2cac5\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 502,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9f7ff128-8895-461f-81ef-429dabc0a9d1\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 18,\n          \"id\": \"b8c0b095-6f92-4759-914e-e296be075b6a\",\n          \"type\": \"text\",\n          \"groupId\": \"00db687b-e3d1-4be0-9a61-2fca3bee0f39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">2nd Floor</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"d1d719c9-113b-4fc4-a4f7-d027e51899f9\",\n          \"type\": \"text\",\n          \"groupId\": \"00db687b-e3d1-4be0-9a61-2fca3bee0f39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">The second floor is dedicated to marketing, design and technology. It’s a more traditional work floor.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"22aecd03-3ebb-4b81-a680-a94753d9825b\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"00db687b-e3d1-4be0-9a61-2fca3bee0f39\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"0b2752a8-b820-43c7-affe-29575fe18cfb\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"00db687b-e3d1-4be0-9a61-2fca3bee0f39\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fbed2117-c7be-4fcd-80cf-2663c0395ea4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 190,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:41:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page1_7_11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Photo of dining table and chairs inside room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#3f3824\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 365,\n          \"height\": 238,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ce52ecfe-3b61-448c-af6c-0dba77405538\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 184,\n          \"focalX\": 37.59303651338337,\n          \"focalY\": 60.77446829100918,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:44:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page3_7_img2.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"White living room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#af9a86\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 366,\n          \"height\": 254,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"642f69ce-b64d-47b5-b1ff-862eeb31d6e2\",\n          \"x\": 46,\n          \"y\": 189,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 17,\n          \"id\": \"b6d4cda2-1b0c-4b88-a3be-477a1537bf19\",\n          \"type\": \"text\",\n          \"groupId\": \"4b37efd1-45d9-4db7-85de-9d17afd5dde3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">2nd Floor Cafe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"1e1629eb-9ed9-4e38-8172-240532b58a78\",\n          \"type\": \"text\",\n          \"groupId\": \"4b37efd1-45d9-4db7-85de-9d17afd5dde3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">The cafe on the 2nd floor comes equipped with smart tech so employees never have to pay by touch.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"cdc7bc24-a9ce-4aed-9724-483d8042731f\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"4b37efd1-45d9-4db7-85de-9d17afd5dde3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6eafd6cb-12d8-469d-ad65-dcaa259eee31\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ce52ecfe-3b61-448c-af6c-0dba77405538\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7a257f1c-c6bb-49d7-be13-d443748b555e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"642f69ce-b64d-47b5-b1ff-862eeb31d6e2\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"e0a49f0f-4792-4db6-9530-defc5123d1cc\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4b37efd1-45d9-4db7-85de-9d17afd5dde3\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9d237531-ea50-4dd5-825a-9b9c0c686690\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #ddc69e\\\">“Even in the cafe every element of productivity and smart tech moments are accounted for.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 183,\n          \"id\": \"e8ac7200-c7fc-4a2f-a574-d0160e0ab872\",\n          \"x\": 50,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:46:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page8_img2.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man in gray sweatshirt sitting on chair in front of iMac\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c8cbcd\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 197,\n          \"y\": 321,\n          \"width\": 215,\n          \"height\": 153,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7c0b9313-ca97-4b42-bddc-3593d8238c6e\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 110,\n          \"focalX\": 77.73212486239709,\n          \"focalY\": 54.72709403331476,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:46:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page8_img1.jpg\",\n            \"width\": 853,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Woman in front of laptop computer editing photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3e3433\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 186,\n          \"height\": 228,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"53e7a3d9-8db7-400f-8c13-a0a12eca257b\",\n          \"x\": 0,\n          \"y\": 360,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"38595816-6064-4b86-8929-6022dbe47d8c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7c0b9313-ca97-4b42-bddc-3593d8238c6e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b376514d-2b5c-4a51-b655-e5afe62b4ecf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"53e7a3d9-8db7-400f-8c13-a0a12eca257b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"12fdc64d-a3f5-42f6-91a4-d020240b833b\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"72558121-5715-4166-ace3-f1eec0e79d10\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:46:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page9_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 719,\n            \"id\": 0,\n            \"alt\": \"Brown wooden 9-piece office table and chairs\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#484745\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 412,\n          \"height\": 502,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"37fbd9c3-9b17-460e-95de-2ab3dc7e41dd\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 18,\n          \"id\": \"46c76151-d1f1-4ff5-842f-4335952dffb6\",\n          \"type\": \"text\",\n          \"groupId\": \"13175eb6-d6ec-45ad-b22f-b5a69442a136\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">3rd Floor Meeting Room</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"7889a208-6fc2-4c45-bb1d-a94178ddfc22\",\n          \"type\": \"text\",\n          \"groupId\": \"13175eb6-d6ec-45ad-b22f-b5a69442a136\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">This is dedicated to our executives to hold board meetings or host celebrity clients and musicians.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"0bbc746f-9d00-4aee-b3a3-839c313d9575\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"13175eb6-d6ec-45ad-b22f-b5a69442a136\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"5f1f528c-debc-40e8-9624-8d6c989afe8e\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"13175eb6-d6ec-45ad-b22f-b5a69442a136\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7eb798b4-6f9f-4c7a-8c3f-da5a76d72db2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Workspaces are open to executives and their entire teams. It’s an opportunity to be collaborative with the C-suite.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 56,\n          \"id\": \"8092efd0-0461-4ab8-b408-454851eecfc4\",\n          \"x\": 46,\n          \"y\": 562,\n          \"type\": \"text\",\n          \"groupId\": \"194d89cc-e5c1-4b42-b438-464a8fb42aa2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">3rd Floor Workspace</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 510,\n          \"width\": 288,\n          \"height\": 26,\n          \"id\": \"76780feb-5574-4b54-b6cc-801ffc17d84f\",\n          \"type\": \"text\",\n          \"groupId\": \"194d89cc-e5c1-4b42-b438-464a8fb42aa2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #cdcbc8; letter-spacing: 0.12em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 484,\n          \"width\": 38,\n          \"height\": 17,\n          \"id\": \"eb27f8bb-37e5-4b53-8f81-f41f77f4ff51\",\n          \"type\": \"text\",\n          \"groupId\": \"194d89cc-e5c1-4b42-b438-464a8fb42aa2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:47:52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page10_img2.jpg\",\n            \"width\": 1080,\n            \"height\": 711,\n            \"id\": 0,\n            \"alt\": \"Black flat screen computer monitor on brown wooden table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b8a194\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 366,\n          \"height\": 254,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f4bcb3e3-1541-481b-b7cf-7383125b5a6a\",\n          \"x\": 46,\n          \"y\": 190,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 146,\n          \"focalX\": 65.69087395031293,\n          \"focalY\": 49.942731247125096,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:47:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 810,\n            \"id\": 0,\n            \"alt\": \"Man in blue dress shirt sitting on rolling chair inside room with monitors\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#beb6b3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 365,\n          \"height\": 238,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0e2607cf-90a9-49c9-ba24-669dd8f581d6\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 55 } },\n      \"type\": \"page\",\n      \"id\": \"ab30407b-fc64-4101-8200-0e5e5da1bd14\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"194d89cc-e5c1-4b42-b438-464a8fb42aa2\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8baef72e-a38d-4511-a270-6419c7af343a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f37\\\">More stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 288,\n          \"height\": 25,\n          \"id\": \"86b132f1-3869-45a5-a5f3-9f17ba1083ec\",\n          \"x\": 62,\n          \"y\": -7,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37; letter-spacing: 0.12em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 18,\n          \"id\": \"4e5598b1-45a4-43c2-ae65-2eb0703115f4\",\n          \"x\": 47,\n          \"y\": 51,\n          \"type\": \"text\",\n          \"groupId\": \"cf4a7800-f3d8-44fb-ba02-16f72c370001\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37\\\">The secrets of Orange’s AI Team</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 257,\n          \"height\": 18,\n          \"id\": \"26bf1a5f-564c-485f-9048-344a936f1e10\",\n          \"x\": 77,\n          \"y\": 51,\n          \"type\": \"text\",\n          \"groupId\": \"cf4a7800-f3d8-44fb-ba02-16f72c370001\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:48:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page11_img1.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man and woman sitting on table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#474949\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 86,\n          \"width\": 318,\n          \"height\": 136,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fe70d82a-e9dc-4049-b77b-28f2292576c9\",\n          \"type\": \"image\",\n          \"groupId\": \"cf4a7800-f3d8-44fb-ba02-16f72c370001\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37; letter-spacing: 0.12em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 17,\n          \"id\": \"a36c3297-13d2-4333-aa2f-9338d83f3bef\",\n          \"x\": 47,\n          \"y\": 250,\n          \"type\": \"text\",\n          \"groupId\": \"d321aaa4-05eb-4fc0-bbba-99024da40c50\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37\\\">A look into Proper’s HQ</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 257,\n          \"height\": 18,\n          \"id\": \"49939af7-773d-405c-8d6c-70d4878b1f93\",\n          \"x\": 77,\n          \"y\": 250,\n          \"type\": \"text\",\n          \"groupId\": \"d321aaa4-05eb-4fc0-bbba-99024da40c50\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:41:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page1_7_11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Photo of dining table and chairs inside room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#bfb9b2\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 136,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5102a5cb-5788-44b6-8c30-b55051963daf\",\n          \"x\": 47,\n          \"y\": 285,\n          \"type\": \"image\",\n          \"groupId\": \"d321aaa4-05eb-4fc0-bbba-99024da40c50\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37; letter-spacing: 0.12em\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 17,\n          \"id\": \"ef9a7645-885a-4e5d-9049-57ff221a7208\",\n          \"x\": 47,\n          \"y\": 449,\n          \"type\": \"text\",\n          \"groupId\": \"dadc06d2-f557-4028-99af-1ad066cd095a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #2f2f37\\\">Orange’s very orange loop</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 257,\n          \"height\": 18,\n          \"id\": \"1bc94b34-b669-4fe4-8e5b-c7b34d598fe8\",\n          \"x\": 77,\n          \"y\": 449,\n          \"type\": \"text\",\n          \"groupId\": \"dadc06d2-f557-4028-99af-1ad066cd095a\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:48:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/google-music-studio-tour/page11_img3.jpg\",\n            \"width\": 720,\n            \"height\": 405,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of round building\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3e352e\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 318,\n          \"height\": 136,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bd08f395-85b1-4e5e-9c77-8739e6d81492\",\n          \"x\": 47,\n          \"y\": 484,\n          \"type\": \"image\",\n          \"groupId\": \"dadc06d2-f557-4028-99af-1ad066cd095a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"576dc23c-e74e-43b7-ad29-e6437039e07b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fe70d82a-e9dc-4049-b77b-28f2292576c9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"23a9f376-9ecd-4cb2-8101-542232b69ab9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5102a5cb-5788-44b6-8c30-b55051963daf\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"632c3f20-19d7-4e73-9d20-5f7b08b0cfe3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bd08f395-85b1-4e5e-9c77-8739e6d81492\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 221, \"g\": 198, \"b\": 158 } },\n      \"type\": \"page\",\n      \"id\": \"89f61bfd-b699-4b2e-a35a-aa11c825c399\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"cf4a7800-f3d8-44fb-ba02-16f72c370001\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d321aaa4-05eb-4fc0-bbba-99024da40c50\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"dadc06d2-f557-4028-99af-1ad066cd095a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/hawaii-travel-packing-list/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/hawaii-travel-packing-list/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'hawaii-travel-packing-list',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Hawaii Travel Packing List', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Island', 'template keyword', 'web-stories'),\n    _x('List', 'template keyword', 'web-stories'),\n    _x('Nature', 'template keyword', 'web-stories'),\n    _x('Teal', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Cool Teal', 'color', 'web-stories'),\n      color: '#EFFAF6',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s beautiful blue-green palette will let you create helpful travel and backpacking stories such as tourist guides, packing lists, and more, with the ability to add product links.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/hawaii-travel-packing-list/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/hawaii-travel-packing-list/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"20c39481-3891-4324-babb-cf72e1a40121\"\n        },\n        {\n          \"x\": 0,\n          \"y\": -547,\n          \"id\": \"015d0097-ce2d-4a51-b191-b7b86fba1466\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 239, \"g\": 250, \"b\": 246 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 735,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"fadcc168-9650-473f-a28c-01725e984ad7\"\n        },\n        {\n          \"x\": 291,\n          \"y\": -4,\n          \"id\": \"ec570a8b-f907-4cfd-9e5a-cc75ca90f911\",\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -22,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 305,\n          \"height\": 518,\n          \"sticker\": { \"type\": \"palmTree\" },\n          \"groupId\": \"fadcc168-9650-473f-a28c-01725e984ad7\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 86,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -187,\n          \"y\": -307,\n          \"width\": 271,\n          \"height\": 460,\n          \"sticker\": { \"type\": \"palmTree\" },\n          \"id\": \"6b545f60-6744-4023-9246-799504b66352\",\n          \"groupId\": \"fadcc168-9650-473f-a28c-01725e984ad7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#35554f\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page01_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of green mountain beside body of water under white sky\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -0.5,\n          \"y\": 190,\n          \"width\": 413,\n          \"height\": 485,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0478d4ff-98e0-4c3f-bc8d-d3850f0593bc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"What to pack for Hawaii’s Main Islands\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 43,\n          \"width\": 318,\n          \"height\": 77,\n          \"id\": \"55010409-03f7-412c-a1f4-57f52e26dce7\",\n          \"marginOffset\": -17.92800000000001,\n          \"groupId\": \"b33049ca-8a1a-40de-9c4f-c7cf80709897\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 121,\n          \"id\": \"6db574ef-4f1e-455e-92c6-e4ade991687a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">By</span> <span style=\\\"font-weight: 600\\\">Emily Kawamoto</span> <span style=\\\"font-weight: 300\\\">8/11/20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 23,\n          \"marginOffset\": -17.92800000000001,\n          \"groupId\": \"b33049ca-8a1a-40de-9c4f-c7cf80709897\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 239, \"g\": 250, \"b\": 246 } },\n      \"type\": \"page\",\n      \"id\": \"c11f2e39-4f1d-43ed-9353-4bf3d49f2c15\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"b33049ca-8a1a-40de-9c4f-c7cf80709897\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fadcc168-9650-473f-a28c-01725e984ad7\": {\n          \"name\": \"Header background image\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -74,\n          \"width\": 412,\n          \"height\": 766,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0d6c78af-e2c5-4d15-9b3b-37c19d125134\",\n          \"scale\": 108,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page02_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Satellite view of hawaiian islands\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1c2c5c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">The Hawaiian Islands</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 461,\n          \"width\": 318,\n          \"height\": 44,\n          \"id\": \"a485b5b6-9547-41d3-9f40-81e828d73722\",\n          \"marginOffset\": 0.6343749999999986,\n          \"groupId\": \"4059b06a-672f-4b10-85c4-504c2f131482\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 504,\n          \"id\": \"c5432395-652c-4926-a1a9-5f5329268beb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Made up of eight islands: Maui, Kauai, Oahu, Lanai, Molokai, Kahoolawe, Niihau, the Big Island Hawaii.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 114,\n          \"marginOffset\": 0.6343749999999986,\n          \"groupId\": \"4059b06a-672f-4b10-85c4-504c2f131482\"\n        },\n        {\n          \"x\": 230,\n          \"y\": 299,\n          \"id\": \"d1626a8f-0eb3-4ef4-847e-34957857b08c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Kahoolawe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 331,\n          \"y\": 399,\n          \"id\": \"4890d03b-5aee-4406-9a9e-cca55aeedabf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Hawaii</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 197,\n          \"y\": 258,\n          \"id\": \"8172abd1-875d-447f-b034-a11e29f394aa\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Lanai</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 238,\n          \"y\": 204,\n          \"id\": \"8adddbb7-e6cb-4201-9f7c-74fc654903eb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Molokai</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 312,\n          \"y\": 240,\n          \"id\": \"095a51f7-549b-49ec-ab8a-a55393745d76\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Maui</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 132,\n          \"y\": 190,\n          \"id\": \"1d361452-7794-4f50-9d2f-6403db8cbe7f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Oahu</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 99,\n          \"y\": 143,\n          \"id\": \"82d51f5a-6685-4b9b-aa32-8a8f08dc9bfb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Kauai</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        },\n        {\n          \"x\": 32,\n          \"y\": 208,\n          \"id\": \"f4723c53-f0e5-4eff-bc65-31a7a8123aa0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Niihau</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 21,\n          \"marginOffset\": -1.2200000000000006\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c1cdd9fb-43ca-4614-9e81-b8c1aff16980\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f4723c53-f0e5-4eff-bc65-31a7a8123aa0\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"aa7f8954-f5c6-43d8-8ba0-f38fb938b5f8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"82d51f5a-6685-4b9b-aa32-8a8f08dc9bfb\"],\n          \"duration\": 1600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"169fb2e7-a48c-4a68-80a3-8010732625fb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1d361452-7794-4f50-9d2f-6403db8cbe7f\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"96a2611a-3736-4f37-bd60-5dddd12eb2f7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8adddbb7-e6cb-4201-9f7c-74fc654903eb\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"1f859c84-2b10-4e90-9ce2-cce197e43240\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8172abd1-875d-447f-b034-a11e29f394aa\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"955981a3-5263-4f45-8fec-278d18cf950e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"095a51f7-549b-49ec-ab8a-a55393745d76\"],\n          \"duration\": 1600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"6504ac1d-9542-4b0d-b77c-f40c8f99fb89\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d1626a8f-0eb3-4ef4-847e-34957857b08c\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"176a2556-c77f-4b24-ac83-85261cdd152c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4890d03b-5aee-4406-9a9e-cca55aeedabf\"],\n          \"duration\": 1600,\n          \"delay\": 700\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"39eff02a-063b-4ca3-9cae-ca13b83475fa\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"4e37750d-b059-4aa2-a72f-3c5070985eab\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4059b06a-672f-4b10-85c4-504c2f131482\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -115.5,\n          \"y\": -57,\n          \"width\": 643,\n          \"height\": 1146,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"71e3c39f-017c-4d0a-9b9e-22a2c4e50806\",\n          \"scale\": 160,\n          \"focalX\": 50,\n          \"focalY\": 33.62329202523783,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man standing on hill\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#353521\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.65 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d3fc6375-792f-4bf3-99de-ac8e955fabf0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Hike the Big Island</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 49,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"67618dc9-78d0-4981-b9a6-d204f905c67c\",\n          \"x\": 47,\n          \"y\": 28\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Must Do:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 30,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"2847b4de-c487-42c2-ba38-fd8a7d12a96e\",\n          \"x\": 47,\n          \"y\": 0\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"49a2b6a2-8baf-4df8-b951-eef9450b5d42\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"71e3c39f-017c-4d0a-9b9e-22a2c4e50806\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e596c981-5972-4c7f-b8f6-acb54274266f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b3610dda-4498-4726-95d7-ed97b354ebc9\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"051b10ff-88bf-4104-b461-8e95c9aacfc9\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 86,\n          \"y\": -182,\n          \"width\": 291,\n          \"height\": 412,\n          \"sticker\": { \"type\": \"travelPalmLeaf\" },\n          \"id\": \"0bf34d1e-6f7f-4a6f-86bd-d87d5e23a6dd\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 368,\n          \"y\": 451,\n          \"width\": 69,\n          \"height\": 125,\n          \"sticker\": { \"type\": \"travelGreenLeaf\" },\n          \"id\": \"6833495e-7add-4721-9f7b-918ac3b5bd21\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"Be sure to pack\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"81970e87-bdf8-44e2-b6d8-3930ed995b31\",\n          \"x\": 48,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">01.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 197,\n          \"y\": 112,\n          \"width\": 168,\n          \"height\": 85,\n          \"id\": \"6b6fb17c-80d5-4c2a-b6ed-a3351f311adb\",\n          \"marginOffset\": 0.5799999999999983,\n          \"groupId\": \"dc183cea-abc7-4a3f-8770-5960475889e8\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 197,\n          \"y\": 241,\n          \"id\": \"9ff216a4-051b-4f96-abfb-3ca0c64931d8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Hiking Boots</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"groupId\": \"dc183cea-abc7-4a3f-8770-5960475889e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:39\",\n            \"baseColor\": \"#4a4634\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page04_image01.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person sitting on rocky mountain during day\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 131,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a16013c7-2077-4736-86d6-dfc1039687e0\",\n          \"groupId\": \"dc183cea-abc7-4a3f-8770-5960475889e8\"\n        },\n        {\n          \"x\": 197,\n          \"y\": 424,\n          \"id\": \"cb0b4ab6-42cc-40d9-9fef-b799efb67e3c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">A Good Camera</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"groupId\": \"b43ef346-87f3-420b-8cee-c971d07b9e08\"\n        },\n        {\n          \"x\": 197,\n          \"y\": 293,\n          \"id\": \"d9d3084f-7a34-4c17-852b-c86122d8a804\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">02.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 84,\n          \"marginOffset\": 0.5799999999999983,\n          \"groupId\": \"b43ef346-87f3-420b-8cee-c971d07b9e08\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:42\",\n            \"baseColor\": \"#332d31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page04_image02.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding Canon DSLR camera\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 49,\n          \"y\": 314,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f821aa2b-a43f-462f-b4c0-aa3004802f27\",\n          \"groupId\": \"b43ef346-87f3-420b-8cee-c971d07b9e08\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page04_image03.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man facing mountain covered with snow\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#353933\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 49,\n          \"y\": 489,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d57a6c17-bb21-4a8f-9b22-f434a6ab2e10\",\n          \"groupId\": \"21e2de5b-f89d-4d65-8c91-1cfcc1092e4d\"\n        },\n        {\n          \"x\": 197,\n          \"y\": 596,\n          \"id\": \"02f02e19-7948-4b33-94db-cfedb4204398\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Warm Clothes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"groupId\": \"21e2de5b-f89d-4d65-8c91-1cfcc1092e4d\"\n        },\n        {\n          \"x\": 198,\n          \"y\": 468,\n          \"id\": \"41640a1f-1053-4101-bfa3-1225b8d689ff\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">03.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 84,\n          \"marginOffset\": 0.5799999999999983,\n          \"groupId\": \"21e2de5b-f89d-4d65-8c91-1cfcc1092e4d\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 239, \"g\": 250, \"b\": 246 } },\n      \"type\": \"page\",\n      \"id\": \"3514e901-2f15-4b10-b93d-993d1381dd47\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"dc183cea-abc7-4a3f-8770-5960475889e8\": {\n          \"name\": \"Section 1\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"b43ef346-87f3-420b-8cee-c971d07b9e08\": {\n          \"name\": \"Section 2\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"21e2de5b-f89d-4d65-8c91-1cfcc1092e4d\": {\n          \"name\": \"Section 3\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7cf6974e-a6c0-46da-9286-0b801af2f25f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page05_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person sitting on rocky mountain during day\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#35332c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -30,\n          \"y\": -198.5,\n          \"width\": 526,\n          \"height\": 936,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5a5477c9-2577-44b1-b6ed-c83b45ccde4c\",\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.06 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"961ddba8-0374-4c71-8195-393a30f49fed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Hiking Boots</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 48,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"d2749f0d-66cf-4f7f-8dda-eb8b08f4eb5f\",\n          \"x\": 47,\n          \"y\": 22,\n          \"groupId\": \"2cb620af-1d36-4d66-a597-0a93a7803f0c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">01.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 27,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"9edc054d-2841-45cc-b836-404987ea4f4b\",\n          \"x\": 47,\n          \"y\": 0,\n          \"groupId\": \"2cb620af-1d36-4d66-a597-0a93a7803f0c\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 78,\n          \"id\": \"f404b1ef-78c6-424f-93e1-79cb30117a20\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">If you really want to hike and adventure to see the real sights of the Big Island, you will want to be prepared.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 251,\n          \"height\": 130,\n          \"marginOffset\": -15.660000000000004,\n          \"groupId\": \"2cb620af-1d36-4d66-a597-0a93a7803f0c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"type\": \"shape\",\n          \"x\": 170,\n          \"y\": 445,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"a5d67eda-ba29-47f6-8406-b04e16d86def\",\n          \"groupId\": \"ef091571-24eb-4135-bb40-ffaa99c92c13\"\n        },\n        {\n          \"x\": 191,\n          \"y\": 466,\n          \"id\": \"490495b8-88c3-48b6-974d-13993bbd234a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"ef091571-24eb-4135-bb40-ffaa99c92c13\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"id\": \"1cc96554-113c-4f54-b5f4-7df3dc7e6653\",\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"groupId\": \"ab183ada-08b2-41cc-8050-4c4af57ba531\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 23,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"41b11a78-af4d-4ad8-9496-975e0a5d8261\",\n          \"groupId\": \"ab183ada-08b2-41cc-8050-4c4af57ba531\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bdb49244-4184-4f77-94b3-a2612f3e7986\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"a5d67eda-ba29-47f6-8406-b04e16d86def\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8bc4c053-87ac-45c8-ae1a-7a8c03de1c04\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"490495b8-88c3-48b6-974d-13993bbd234a\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"31178cc6-3fd4-4f11-a8fa-3d4c98200c38\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2cb620af-1d36-4d66-a597-0a93a7803f0c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ab183ada-08b2-41cc-8050-4c4af57ba531\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ef091571-24eb-4135-bb40-ffaa99c92c13\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4fe010dc-ecf5-4a12-bb1e-6e169f6e3f6c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:18:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding Canon DSLR camera\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#322e37\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -77,\n          \"width\": 446,\n          \"height\": 792,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"50369499-2d1e-49ce-a486-b64f0af354dd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c9598f14-dab1-4460-b8ae-5dcd5b1ce7b1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">A Good Camera</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"efdec576-b782-496c-a4cc-c33f16899360\",\n          \"x\": 47,\n          \"y\": 315,\n          \"type\": \"text\",\n          \"groupId\": \"aa639ff6-17c9-441a-9218-d7eff663d82d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">02.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 25,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"afe90b5c-b712-4a89-b525-b0edd3e98371\",\n          \"x\": 47,\n          \"y\": 293,\n          \"type\": \"text\",\n          \"groupId\": \"aa639ff6-17c9-441a-9218-d7eff663d82d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 371,\n          \"id\": \"5c2a2df4-a9cf-405e-a185-ac3e8c6746cc\",\n          \"content\": \"<span style=\\\"color: #fff\\\">You’re going to want more than what your average phone camera can capture. These are going to be photos of a lifetime.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 251,\n          \"height\": 134,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"aa639ff6-17c9-441a-9218-d7eff663d82d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"x\": 163,\n          \"y\": 204,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"5fa3738a-ba12-4573-b324-5307cb523969\",\n          \"type\": \"shape\",\n          \"groupId\": \"d17d5895-8ead-4c70-bac4-3b69decf7965\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 184,\n          \"y\": 226,\n          \"id\": \"47a47418-5a8a-4551-9d6e-d8249a47ab68\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"d17d5895-8ead-4c70-bac4-3b69decf7965\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"id\": \"071f4bfc-2abe-4ac6-85a1-4e011e5b7a5a\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"groupId\": \"2ae58dce-ca1a-4258-8a64-38b623826133\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 23,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"b8495237-4d1f-4a9d-9032-365f51bed2b0\",\n          \"groupId\": \"2ae58dce-ca1a-4258-8a64-38b623826133\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e836f760-53a9-46dd-b6b1-1f0dc6b7665c\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"47a47418-5a8a-4551-9d6e-d8249a47ab68\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"770e676a-44bc-4b15-abe6-d8a0152af1c6\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"5fa3738a-ba12-4573-b324-5307cb523969\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"de6c04ec-3f96-4a08-a5d6-870b3772d53c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"aa639ff6-17c9-441a-9218-d7eff663d82d\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2ae58dce-ca1a-4258-8a64-38b623826133\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d17d5895-8ead-4c70-bac4-3b69decf7965\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5a9503f0-d0a7-4ba5-b5e7-6dbeec78014d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page07_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man facing mountain covered with snow\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#202722\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -5,\n          \"y\": -208,\n          \"width\": 508,\n          \"height\": 898,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b00fe09a-26aa-4248-99eb-8c97f9590097\",\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.17 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f97ee79f-e811-4801-9519-a0dad8538073\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Warm Clothes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"a66f0e2d-c496-4189-96d4-c95c53e13d22\",\n          \"x\": 47,\n          \"y\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"05e2c13b-9089-4841-9d67-613308aba160\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">03.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 25,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"5e255d7a-6c59-402f-99d9-1fd5c0716ae8\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"05e2c13b-9089-4841-9d67-613308aba160\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 78,\n          \"id\": \"62ebe965-c9f2-4575-9c95-43b3f118904d\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Weather can be fickle here. If you plan to hike all day, make sure to be prepared with a set of warmer layers in a backpack.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 251,\n          \"height\": 130,\n          \"marginOffset\": -15.660000000000004,\n          \"type\": \"text\",\n          \"groupId\": \"05e2c13b-9089-4841-9d67-613308aba160\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"x\": 281,\n          \"y\": 361,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"57185897-4c0d-4a04-a157-ecee661f0630\",\n          \"type\": \"shape\",\n          \"groupId\": \"7c1ad448-25cd-4705-be7b-a3991f5f6f74\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 302,\n          \"y\": 383,\n          \"id\": \"9010c573-4dd5-4f33-bb5d-1cdd3107c4e7\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"7c1ad448-25cd-4705-be7b-a3991f5f6f74\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"id\": \"d7e5c2c5-6028-481f-8abb-c43a6ad05741\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"groupId\": \"d380642e-e38f-48a5-8bde-c4e6ab8ff25b\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 23,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"0b716870-e949-4507-98c0-4ddbdafa844b\",\n          \"groupId\": \"d380642e-e38f-48a5-8bde-c4e6ab8ff25b\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"08b9a004-ca54-4029-96f2-ee854727aa8f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"9010c573-4dd5-4f33-bb5d-1cdd3107c4e7\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d8231bc9-b36f-4198-ac7a-526363bd2111\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"57185897-4c0d-4a04-a157-ecee661f0630\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9cdb64c7-57ba-4ba5-becd-d1fd802d78b7\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"d380642e-e38f-48a5-8bde-c4e6ab8ff25b\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7c1ad448-25cd-4705-be7b-a3991f5f6f74\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"05e2c13b-9089-4841-9d67-613308aba160\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -5,\n          \"y\": -56,\n          \"width\": 516,\n          \"height\": 918,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"894e8f89-1db3-49cd-bbb4-7e71661bccd2\",\n          \"type\": \"image\",\n          \"scale\": 135,\n          \"focalX\": 43.977828913726356,\n          \"focalY\": 40.07523111979167,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman snorkeling underwater\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#4781a1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.65 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.6\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ff67c4b4-9262-4a67-998b-24a581ced3b9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Snorkeling in Maui</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"e5bf4b20-707d-4be0-a6b7-fe0c899432d0\",\n          \"x\": 48,\n          \"y\": 28,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Must Do:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 30,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"728beedc-20b0-4799-a72c-6a99619e8206\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dda719cc-5f18-4741-903a-a35efa589648\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"894e8f89-1db3-49cd-bbb4-7e71661bccd2\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7c25285e-d05a-4943-a6d4-982b63c72dd2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"778d5bbc-9b72-4064-9e64-fe14dce58dfc\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6e0f47d0-6d32-4e14-9ae7-6704778419ad\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 86,\n          \"y\": -182,\n          \"width\": 291,\n          \"height\": 412,\n          \"sticker\": { \"type\": \"travelPalmLeaf\" },\n          \"id\": \"db522d77-d361-4b7d-8b1b-c50f867693e1\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 378,\n          \"y\": 451,\n          \"width\": 69,\n          \"height\": 125,\n          \"sticker\": { \"type\": \"travelGreenLeaf\" },\n          \"id\": \"a90ea1cf-691a-47b3-af93-7c063e1a3898\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"What to pack\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"75835290-acf7-4719-be83-b141fa50955e\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 200\\\">01.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 197,\n          \"y\": 112,\n          \"width\": 168,\n          \"height\": 85,\n          \"id\": \"4f63a0d2-86a5-477b-bcf1-edfac1bf9532\",\n          \"marginOffset\": 0.5799999999999983,\n          \"type\": \"text\",\n          \"groupId\": \"4f34177c-4d4f-4031-a237-eafd1dab0c00\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 197,\n          \"y\": 239,\n          \"id\": \"bebdc562-d78a-4929-aa27-9345af67fca4\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Snorkel Mask</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"4f34177c-4d4f-4031-a237-eafd1dab0c00\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page09_image01.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Underwater photography of person diving\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#90afa5\",\n            \"isExternal\": true\n          },\n          \"x\": 48,\n          \"y\": 131,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"67a9b65f-4314-46bc-95b2-adb355ebb47b\",\n          \"type\": \"image\",\n          \"groupId\": \"f71cc780-a13b-42fa-a1c2-41c003ea7e02\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 197,\n          \"y\": 424,\n          \"id\": \"90a60cf8-deab-4f43-a632-3a268583cf02\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Sunglasses</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 30,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"f71cc780-a13b-42fa-a1c2-41c003ea7e02\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 197,\n          \"y\": 293,\n          \"id\": \"937f563a-fded-40c9-992a-b1807dc576ca\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">02.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 84,\n          \"marginOffset\": 0.5799999999999983,\n          \"type\": \"text\",\n          \"groupId\": \"f71cc780-a13b-42fa-a1c2-41c003ea7e02\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page09_image02.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black Ray-Ban Wayfarer sunglasses on beach sand\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c8cbc6\",\n            \"isExternal\": true\n          },\n          \"x\": 49,\n          \"y\": 314,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5de54fc1-6d6f-4c5a-b779-e3256dc46426\",\n          \"type\": \"image\",\n          \"groupId\": \"f71cc780-a13b-42fa-a1c2-41c003ea7e02\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page09_image03.jpg\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding action camera in underwater\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#059fae\",\n            \"isExternal\": true\n          },\n          \"x\": 49,\n          \"y\": 489,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"304c4179-2146-4c57-a7d8-15b78907a10b\",\n          \"type\": \"image\",\n          \"groupId\": \"77fa89f1-d8d4-4c31-9c86-db37305cb722\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 198,\n          \"y\": 468,\n          \"id\": \"08447e7e-6d78-4f39-8fe1-77ce92f3d487\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">03.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 84,\n          \"marginOffset\": 0.5799999999999983,\n          \"type\": \"text\",\n          \"groupId\": \"77fa89f1-d8d4-4c31-9c86-db37305cb722\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 197,\n          \"y\": 570,\n          \"id\": \"168149ee-3c87-4c52-a75b-44120eb5fd68\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Waterproof Pro-Cam</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 140,\n          \"height\": 56,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"77fa89f1-d8d4-4c31-9c86-db37305cb722\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 239, \"g\": 250, \"b\": 246 } },\n      \"type\": \"page\",\n      \"id\": \"6951e10e-26d7-4b83-aa1c-a5089d22fc10\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4f34177c-4d4f-4031-a237-eafd1dab0c00\": {\n          \"name\": \"Section 1\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f71cc780-a13b-42fa-a1c2-41c003ea7e02\": {\n          \"name\": \"Section 2\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"77fa89f1-d8d4-4c31-9c86-db37305cb722\": {\n          \"name\": \"Section 3\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3cce2610-f9df-481a-8b9e-8288862520cb\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:19:58\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Underwater photography of person diving\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8aa294\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"01229ffb-0bd2-46eb-9909-b323c1aee9e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a23f5dea-1520-4f83-99e2-031a97b1766c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Snorkel Mask</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"e2a8d30f-7073-4bc0-88e0-b04f3e1f5550\",\n          \"x\": 47,\n          \"y\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"1d2b3c77-1282-4fbc-81e1-2de9114fcfc8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">01.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 27,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"3f242762-f6d4-4b84-b9ce-c4bd403de7fb\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"1d2b3c77-1282-4fbc-81e1-2de9114fcfc8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 78,\n          \"id\": \"36565544-69be-4c43-bb88-5241b78942b3\",\n          \"content\": \"<span style=\\\"color: #fff\\\">If you can, why not pack your own snorkel mask? Especially these days, you want something that is custom for your face and your face only.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 251,\n          \"height\": 159,\n          \"marginOffset\": -15.660000000000004,\n          \"type\": \"text\",\n          \"groupId\": \"1d2b3c77-1282-4fbc-81e1-2de9114fcfc8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"x\": 225,\n          \"y\": 453,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"dd704ef6-e749-46ab-ba99-c58624f452d0\",\n          \"type\": \"shape\",\n          \"groupId\": \"24bde573-cbf9-44a3-923a-d86bddd51b40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 246,\n          \"y\": 475,\n          \"id\": \"9ba05243-911c-4567-a5af-0e9cb60fcc6d\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"24bde573-cbf9-44a3-923a-d86bddd51b40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"id\": \"3ce64b2f-c6fe-4e17-82aa-0ec2085bf45f\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"groupId\": \"c7b8e772-d320-4739-a9ff-11e0e444f978\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 19,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 162,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"groupId\": \"c7b8e772-d320-4739-a9ff-11e0e444f978\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"f6f8325e-6e5a-4730-9803-5552933d824e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ca2a4b38-2f5e-4642-8f53-e546fe7cbd92\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"dd704ef6-e749-46ab-ba99-c58624f452d0\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9766cbbe-01cd-43f6-8cb8-941033ec2ca9\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"9ba05243-911c-4567-a5af-0e9cb60fcc6d\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ec688592-858a-47a0-8a13-b03672f5dac9\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1d2b3c77-1282-4fbc-81e1-2de9114fcfc8\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"24bde573-cbf9-44a3-923a-d86bddd51b40\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c7b8e772-d320-4739-a9ff-11e0e444f978\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ef42ead7-5b55-47a9-ae83-2cfd45e2a199\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:20:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black Ray-Ban Wayfarer sunglasses on beach sand\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1c9c9\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -53,\n          \"y\": -305,\n          \"width\": 553,\n          \"height\": 986,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"99b30770-6836-405f-822a-566c74a61946\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5a5a3dab-a950-4ac2-9974-95d0f191ce41\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Sunglasses</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"53c30df8-ca0b-4223-8baf-cbbb2b99b4d0\",\n          \"x\": 46,\n          \"y\": 313,\n          \"type\": \"text\",\n          \"groupId\": \"c7c2dfbb-4407-46e7-a6d4-f53e506a8b43\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">02.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 25,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"820aed53-1fdc-4a32-8404-0bc2d6428bd0\",\n          \"x\": 47,\n          \"y\": 294,\n          \"type\": \"text\",\n          \"groupId\": \"c7c2dfbb-4407-46e7-a6d4-f53e506a8b43\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 367,\n          \"id\": \"c67bb80e-024e-4818-96f1-a8028f59405b\",\n          \"content\": \"<span style=\\\"color: #fff\\\">If you’re going to be on a boat en route to your snorkel destination, be sure to pack a pair of sunnies.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 251,\n          \"height\": 108,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"c7c2dfbb-4407-46e7-a6d4-f53e506a8b43\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"x\": 177,\n          \"y\": 131,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"026fb8fe-b58b-4a3d-907a-eacc00115050\",\n          \"type\": \"shape\",\n          \"groupId\": \"9a2be0d3-dcbe-4956-a56e-366791d8a3dc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 198,\n          \"y\": 153,\n          \"id\": \"e2117b5d-4447-4c58-a9b7-a1ca0ba3e2e4\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"9a2be0d3-dcbe-4956-a56e-366791d8a3dc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"id\": \"7261bb4b-a1d5-4def-80dd-27550c4ef4f2\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"groupId\": \"50c374f9-9a5f-4a83-864c-10175f9d3024\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 23,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"6b1f4017-01cc-4775-adf7-7808ca543fd8\",\n          \"groupId\": \"50c374f9-9a5f-4a83-864c-10175f9d3024\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"60f48661-f9e8-4057-b226-4ce584285d55\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"026fb8fe-b58b-4a3d-907a-eacc00115050\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a3a4da01-89f7-4a65-843c-977cb8c6d8ca\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e2117b5d-4447-4c58-a9b7-a1ca0ba3e2e4\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f9eeeb1d-d420-4ed0-a7c9-77c741ef37c8\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c7c2dfbb-4407-46e7-a6d4-f53e506a8b43\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9a2be0d3-dcbe-4956-a56e-366791d8a3dc\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"50c374f9-9a5f-4a83-864c-10175f9d3024\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"85516cab-7312-437c-be73-33ef6f636672\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T05:20:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding action camera in underwater\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0b8f9d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -38,\n          \"y\": -58.5,\n          \"width\": 488,\n          \"height\": 866,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"00c759ef-85b0-4663-9347-655ea9d0b035\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7e57b7f2-d069-4efe-8762-fdbc36affeaa\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Waterproof Pro-Cam</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 47,\n          \"marginOffset\": 0.6343749999999986,\n          \"id\": \"1c834543-3dd0-4f47-b10b-9ce2a6a5b301\",\n          \"x\": 47,\n          \"y\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"e2128bbc-faf4-4276-a4d2-02a87c6a99b7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">03.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 24,\n          \"height\": 25,\n          \"marginOffset\": -4.440000000000001,\n          \"id\": \"3f8aacdf-a7ef-42e6-b66d-2e0143ebe038\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"e2128bbc-faf4-4276-a4d2-02a87c6a99b7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 78,\n          \"id\": \"5676cfac-4771-4047-b5ff-a22b59357bda\",\n          \"content\": \"<span style=\\\"color: #fff\\\">My rule of thumb is to capture everything. And underwater views are so special. They’re definitely worth savoring again and again.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 159,\n          \"marginOffset\": -4.440000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"e2128bbc-faf4-4276-a4d2-02a87c6a99b7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 }\n          },\n          \"x\": 252,\n          \"y\": 309,\n          \"width\": 58,\n          \"height\": 58,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"21f6737e-42fe-4b01-8a53-7a16d140ca66\",\n          \"type\": \"shape\",\n          \"groupId\": \"42bca55a-cf57-47a0-a2fe-2df2a5d972af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 273,\n          \"y\": 331,\n          \"id\": \"0d6a4985-f3bd-496f-932a-0b868ef5ee16\",\n          \"width\": 15,\n          \"height\": 15,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"42bca55a-cf57-47a0-a2fe-2df2a5d972af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 16,\n          \"height\": 17,\n          \"sticker\": { \"type\": \"travelBag\" },\n          \"link\": { \"url\": \"google.com\", \"icon\": null, \"desc\": \"google.com\" },\n          \"id\": \"92a00e30-ef31-4b31-bbbe-01a8973ac441\",\n          \"x\": 144,\n          \"y\": 585.5,\n          \"groupId\": \"7292f956-f14c-4d8f-8ff4-3b1110538d5a\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 571,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 23,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">View Products</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": -2.663999999999998,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"ec980d3e-5e00-46f9-b7bf-3b58eae77f67\",\n          \"groupId\": \"7292f956-f14c-4d8f-8ff4-3b1110538d5a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1a20922d-104a-473e-842a-4bbaa18b6000\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"0d6a4985-f3bd-496f-932a-0b868ef5ee16\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a979c5f8-2441-49b9-8cd5-731a3c954184\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"21f6737e-42fe-4b01-8a53-7a16d140ca66\"],\n          \"scale\": 0.5,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"84b1e35d-63df-4984-bfc1-3d82ff37bfe6\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"e2128bbc-faf4-4276-a4d2-02a87c6a99b7\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"42bca55a-cf57-47a0-a2fe-2df2a5d972af\": {\n          \"name\": \"Focus\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7292f956-f14c-4d8f-8ff4-3b1110538d5a\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"1e4a30b3-33e1-48da-bd25-e88dc01298a6\"\n        },\n        {\n          \"opacity\": 5,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 26,\n          \"y\": -329,\n          \"width\": 532,\n          \"height\": 753,\n          \"sticker\": { \"type\": \"travelPalmLeaf\" },\n          \"id\": \"e21cca17-7aeb-4e3a-896b-a1ca723f6259\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Curious about the \\nother islands?\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 77,\n          \"marginOffset\": 0.6343749999999986,\n          \"type\": \"text\",\n          \"id\": \"ef63944e-00b1-47b9-be06-dbb4c31557ec\",\n          \"x\": 49,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page13_image01.jpg\",\n            \"width\": 720,\n            \"height\": 563,\n            \"id\": 0,\n            \"alt\": \"Woman swimming underwater\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1d715b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 158,\n          \"width\": 220,\n          \"height\": 172,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"127db0dd-e66e-41ca-8d79-b69985457a5f\"\n        },\n        {\n          \"x\": 140,\n          \"y\": 81,\n          \"id\": \"0d90785f-0ab6-49bc-8088-aa516321f46f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Kauai\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 232,\n          \"height\": 137,\n          \"marginOffset\": -15.660000000000004,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/hawaii-travel-packing-list/page13_image02.jpg\",\n            \"width\": 720,\n            \"height\": 563,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of mountain range\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#394f3b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 192,\n          \"y\": 296,\n          \"width\": 220,\n          \"height\": 172,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"627abd9f-5447-4df3-8c27-3971d0892e7b\"\n        },\n        {\n          \"x\": 36,\n          \"y\": 417,\n          \"id\": \"023aa8f1-92b6-4e82-8697-ca7e152b2e1d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 90,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Molokai\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 332,\n          \"height\": 136,\n          \"marginOffset\": -19.97999999999999,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 43,\n            \"vertical\": 14\n          },\n          \"content\": \"See More\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 159,\n          \"height\": 46,\n          \"marginOffset\": 1.4699999999999989,\n          \"type\": \"text\",\n          \"id\": \"165e5f3e-1282-4cc3-a649-b70a53acbceb\",\n          \"x\": 127,\n          \"y\": 571,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4b5db9ce-a2c4-42b9-9878-41b5dc767c33\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0d90785f-0ab6-49bc-8088-aa516321f46f\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"fbaa5943-efb8-41d8-8000-ba3ff1290275\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"023aa8f1-92b6-4e82-8697-ca7e152b2e1d\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"cbc7522a-e474-474f-a3a7-ad7291f6c764\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"165e5f3e-1282-4cc3-a649-b70a53acbceb\"],\n          \"duration\": 2000,\n          \"delay\": 1250\n        },\n        {\n          \"id\": \"2c902e55-b664-4eee-b8aa-e0a86f77f501\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"627abd9f-5447-4df3-8c27-3971d0892e7b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"3469b52c-5d8c-41c2-b784-bdb041ba8594\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"127db0dd-e66e-41ca-8d79-b69985457a5f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 239, \"g\": 250, \"b\": 246 } },\n      \"type\": \"page\",\n      \"id\": \"24ac301d-7e81-4578-979a-7aaeccd409e3\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/honeymooning-in-italy/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/honeymooning-in-italy/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'honeymooning-in-italy',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Honeymooning in Italy', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Outdoor', 'template keyword', 'web-stories'),\n    _x('Floral', 'template keyword', 'web-stories'),\n    _x('Collage', 'template keyword', 'web-stories'),\n    _x('Brown', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Night Green', 'color', 'web-stories'),\n      color: '#232c27',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Brownish Pink', 'color', 'web-stories'),\n      color: '#f2e5d6',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Parchment White', 'color', 'web-stories'),\n      color: '#fef6df',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its elegant typography, charming colors and exquisite floral design pattern, this template will let you create lush travel guides, itineraries, bucket lists, travelogues and more.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/honeymooning-in-italy/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/honeymooning-in-italy/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6c2aa2fa-7a2c-41da-8c75-dbca68b95a27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -194,\n          \"y\": -245,\n          \"width\": 388,\n          \"height\": 373,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"f2201a06-f489-4521-8b8f-07b57ad7161f\"\n        },\n        {\n          \"x\": 225,\n          \"y\": 453,\n          \"id\": \"810c630a-5b70-4ffc-9425-7430abe1db92\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 371,\n          \"height\": 356,\n          \"sticker\": { \"type\": \"floralPattern\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 46,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Honeymooning in Italy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 64,\n          \"y\": -2,\n          \"width\": 283,\n          \"height\": 106,\n          \"id\": \"40063a65-2c7a-4bc3-81dc-d240befed7bb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Martina Hansson &amp; Mike Smith</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 64,\n          \"y\": 119,\n          \"width\": 240,\n          \"height\": 21,\n          \"id\": \"88973f2a-66da-4907-8014-dc6e57c926d0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:45:58\",\n            \"baseColor\": \"#d4d5d0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page01_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man and woman sitting on concrete surface\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 23,\n          \"y\": 174,\n          \"width\": 365,\n          \"height\": 479,\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 55.06967911533227,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ef9cffa6-0c32-431d-b4b5-21fb9d71c54d\",\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 229, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"93ec2ce2-944b-41d9-a329-255003bbf5f2\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6344cf3c-5263-4d84-9790-f8d40bc91e42\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 45,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"f0e871c2-3cda-404d-9180-ed53d6150c8f\",\n          \"x\": -133,\n          \"y\": 172\n        },\n        {\n          \"x\": 137,\n          \"y\": 172,\n          \"id\": \"6412e96d-09bd-400e-abda-245c23cde7ac\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -45,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 449,\n          \"height\": 435,\n          \"scale\": 153,\n          \"focalX\": 52.37990104776502,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 300,\n            \"topRight\": 300,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"f8dc27fc-9573-4739-8d64-63431f380c8e\",\n          \"x\": -19.5,\n          \"y\": 247,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:01:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page02_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown concrete building under evening sky\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#101111\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Fondazione Prada</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 42,\n          \"id\": \"3db25d37-118f-4fa4-96d3-ba8cd849d286\",\n          \"x\": 76,\n          \"y\": 35\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">A major center for all things contemporary art and culture. Created by Rem Koolhaas.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 240,\n          \"height\": 66,\n          \"id\": \"ded1eb29-9fd8-4219-b406-1505edcf0191\",\n          \"x\": 76,\n          \"y\": 90\n        },\n        {\n          \"x\": 79,\n          \"y\": 4,\n          \"id\": \"97be1561-f8ff-4119-90e8-060fcc90e134\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #232c27\\\">MY FAVOURITE PLACES OF TUSCANY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 17\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"560404e3-24eb-4c4a-b981-a4950af16aaa\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f8dc27fc-9573-4739-8d64-63431f380c8e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"9d8d78d0-36f6-40d6-b64a-84e4cf0adfb8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3db25d37-118f-4fa4-96d3-ba8cd849d286\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"06e737cc-7100-450c-a397-c3ff9abb1490\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ded1eb29-9fd8-4219-b406-1505edcf0191\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 246, \"b\": 223 } },\n      \"type\": \"page\",\n      \"id\": \"d61fe28e-60c0-4822-ace8-82bbbb2a1888\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"See the location\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9798646d-0a3e-4226-a00b-b406e822512b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 45,\n          \"lockAspectRatio\": true,\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"599eee86-ae04-4824-8b5d-268454107eb8\",\n          \"x\": -134,\n          \"y\": -40,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -45,\n          \"lockAspectRatio\": true,\n          \"x\": 142,\n          \"y\": -40,\n          \"id\": \"7e0ea2d2-4466-45f9-a5c0-de20d79dfadf\",\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 449,\n          \"height\": 403,\n          \"scale\": 115,\n          \"focalX\": 52.20104584932508,\n          \"focalY\": 56.464714461398394,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 300,\n            \"bottomLeft\": 300,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"id\": \"fc59ebdf-d016-4e0e-9089-8edbe91f5527\",\n          \"x\": -18.5,\n          \"y\": -57,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:52:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page03_image01.jpg\",\n            \"width\": 960,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown concrete building under blue sky during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a8b0b6\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Accademia di Belle Arti di Brera</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 81,\n          \"id\": \"145c032f-3a8c-4834-88ed-838087d08131\",\n          \"x\": 65,\n          \"y\": 381\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">A beautiful 17th century building that used to be a convent, but now houses the most beautiful collection of paintings.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 88,\n          \"id\": \"583c8c77-a7d5-40b0-80a8-f43e0e008365\",\n          \"x\": 64,\n          \"y\": 472\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"57bc6e89-a628-4057-abf4-0b9826ff19e2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fc59ebdf-d016-4e0e-9089-8edbe91f5527\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 246, \"b\": 223 } },\n      \"type\": \"page\",\n      \"id\": \"b2d0baf3-7abb-4faf-9844-05b74c629cfd\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"See the location\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"174072df-bc7a-4832-b4cd-6d43e57839e2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"x\": -194,\n          \"y\": -245,\n          \"width\": 388,\n          \"height\": 373,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"1fee32e4-057c-421c-93dc-a31cccf741fb\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 225,\n          \"y\": 453,\n          \"id\": \"a704e766-b7b4-40f2-a8e8-b98423de89b0\",\n          \"width\": 371,\n          \"height\": 356,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:45:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page04_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown Painted Buildings Across Body of Water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#43454b\",\n            \"isExternal\": true\n          },\n          \"x\": 68,\n          \"y\": -3,\n          \"width\": 275,\n          \"height\": 365,\n          \"scale\": 122,\n          \"focalX\": 50,\n          \"focalY\": 53.65481520616918,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3b8773d2-3e20-4d2f-ab58-295be1aed390\",\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">“We did not miss Raphael's \\\"Marriage of the Virgin.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 70,\n          \"y\": 415,\n          \"width\": 283,\n          \"height\": 112,\n          \"id\": \"5ef7785c-7fb5-4aa4-8b2f-7fa0dcb40cf9\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">Martin Hansson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 70,\n          \"y\": 590,\n          \"width\": 240,\n          \"height\": 21,\n          \"id\": \"b3efd744-437b-4a7a-b453-045039dd563e\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"efccef3c-074b-4fb0-baa6-9f6c3eba34fd\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"3b8773d2-3e20-4d2f-ab58-295be1aed390\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"41811441-2887-4b48-9c23-d27c61e2824d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5ef7785c-7fb5-4aa4-8b2f-7fa0dcb40cf9\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"879e8fd8-6fe6-4967-a597-ffd7a3fd2321\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b3efd744-437b-4a7a-b453-045039dd563e\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 229, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"d98925cd-b891-40f1-9e10-a7149234972f\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"685edeed-6a1d-491c-bd72-1f404debb56c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 45,\n          \"lockAspectRatio\": true,\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"29c6278f-7aee-4cae-99ff-cde88f9569c7\",\n          \"x\": -133,\n          \"y\": 172,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -45,\n          \"lockAspectRatio\": true,\n          \"x\": 137,\n          \"y\": 172,\n          \"id\": \"76f59dc5-e7fd-4cff-8dd4-5d2b1c0510e4\",\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 449,\n          \"height\": 435,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 54.85499813744066,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 300,\n            \"topRight\": 300,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"9f9f9945-de51-468d-8680-5fa9d0e8a475\",\n          \"x\": -18.5,\n          \"y\": 247,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:47:50\",\n            \"baseColor\": \"#d7b6a8\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page05_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black pendant lamp turned on near glass window\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">Latteria San Marco</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 43,\n          \"id\": \"c42f74e8-a9bf-4cdc-a94b-7fdfcc89e59b\",\n          \"x\": 76,\n          \"y\": 35,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">A local's spot for the best caprese salad. MMM!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 253,\n          \"height\": 43,\n          \"id\": \"c63f0fa6-2594-4af9-95d8-22e8c8c7b104\",\n          \"x\": 76,\n          \"y\": 90,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1f78efdb-6b1a-4c61-92c8-5790e6c212af\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9f9f9945-de51-468d-8680-5fa9d0e8a475\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 246, \"b\": 223 } },\n      \"type\": \"page\",\n      \"id\": \"7ff02613-ccfa-4dcb-adc0-fe90c9a299cd\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"See the location\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4fbb96f2-ab06-4755-b944-2e15db2dc278\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 45,\n          \"lockAspectRatio\": true,\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"d580b6fc-47d0-4f59-8130-d87ea334a95d\",\n          \"x\": -134,\n          \"y\": -40,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -45,\n          \"lockAspectRatio\": true,\n          \"x\": 142,\n          \"y\": -40,\n          \"id\": \"2a9f8c11-0c79-4d0f-b857-00f7bbb5e769\",\n          \"width\": 382,\n          \"height\": 367,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">Pasticcheria Marchesi</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 42,\n          \"id\": \"da32686c-63c4-461c-be70-e6829c7effea\",\n          \"x\": 57,\n          \"y\": 415,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">A historic bakery that is just as opulent as its pastries are decadent.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 240,\n          \"height\": 65,\n          \"id\": \"2c7c697d-cafc-4930-a9ec-05d9a64fc6ad\",\n          \"x\": 57,\n          \"y\": 470,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 449,\n          \"height\": 467,\n          \"scale\": 135,\n          \"focalX\": 58.97404020801529,\n          \"focalY\": 48.161313949436554,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 300,\n            \"bottomLeft\": 300,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T08:19:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page06_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Clean Coffee Shop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#232d2f\",\n            \"isExternal\": true\n          },\n          \"id\": \"a3581225-02ac-448b-8ef0-5ef40b26bf5d\",\n          \"x\": -18.5,\n          \"y\": -121\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"414eef6e-98c5-4175-8b2a-f9b3441f2e9c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a3581225-02ac-448b-8ef0-5ef40b26bf5d\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 246, \"b\": 223 } },\n      \"type\": \"page\",\n      \"id\": \"962d65aa-de14-45bf-a9d3-c1a72e9920fb\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"See the location\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1f67ab40-22bd-46ea-84fe-df022e8b8b4e\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T08:43:52\",\n            \"baseColor\": \"#f0e0cb\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page07_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representation of a map\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Find the\\nplaces below</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 78,\n          \"id\": \"4fe0fb5d-ae85-49c9-a706-68a3bd73971c\",\n          \"x\": 55,\n          \"y\": 35\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Fundazione</span>\\nPrada\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 88,\n          \"height\": 43,\n          \"id\": \"c2fabfa0-d161-47e6-afd2-455b438d849f\",\n          \"x\": 51,\n          \"y\": 307\n        },\n        {\n          \"x\": 274,\n          \"y\": 271,\n          \"id\": \"344535e2-478b-4c70-bfc5-a6b7fa47628d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T08:19:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page06_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Clean Coffee Shop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#fce3e0\",\n            \"isExternal\": true\n          },\n          \"width\": 77,\n          \"height\": 103,\n          \"scale\": 210,\n          \"focalX\": 52.44324923741566,\n          \"focalY\": 51.660178973851515,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          }\n        },\n        {\n          \"x\": 264,\n          \"y\": 389,\n          \"id\": \"9304e89e-22b4-40ae-bad3-52df88e6d838\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Pasticcheria\\nMarchesi</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 95,\n          \"height\": 43\n        },\n        {\n          \"x\": 134,\n          \"y\": 551,\n          \"id\": \"8615e7e7-a5fa-45e9-ab9f-ea539079e04c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Letteria \\nSan Marco</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 88,\n          \"height\": 43\n        },\n        {\n          \"x\": 57,\n          \"y\": 188,\n          \"id\": \"f8a8b086-c45d-45de-80d9-b9ea15e44f2f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:01:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page02_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown concrete building under evening sky\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#2fa5d2\",\n            \"isExternal\": true\n          },\n          \"width\": 77,\n          \"height\": 103,\n          \"scale\": 200,\n          \"focalX\": 60.58201058201058,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          }\n        },\n        {\n          \"x\": 140,\n          \"y\": 432,\n          \"id\": \"ac376bb1-44ee-484c-aa17-8c3013585b17\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:47:50\",\n            \"baseColor\": \"#050505\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page05_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black pendant lamp turned on near glass window\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"isExternal\": true\n          },\n          \"width\": 77,\n          \"height\": 103,\n          \"scale\": 133,\n          \"focalX\": 53.19289238145338,\n          \"focalY\": 55.831655389894955,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2b2a00f1-8b54-4577-9f10-47124cc35d4d\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"f8a8b086-c45d-45de-80d9-b9ea15e44f2f\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f09f16c9-67c2-49c3-9761-72d03c9a5311\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"344535e2-478b-4c70-bfc5-a6b7fa47628d\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"3a47ec72-1cc1-420a-b122-47a2bcb4b245\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"ac376bb1-44ee-484c-aa17-8c3013585b17\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"1979246b-a84a-452b-82cd-b73cc092f5e2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c2fabfa0-d161-47e6-afd2-455b438d849f\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6b5405ce-d891-4724-9ac0-256e92bd9d0e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9304e89e-22b4-40ae-bad3-52df88e6d838\"],\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"04f3caae-1428-4553-8a0d-b466a76d913f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8615e7e7-a5fa-45e9-ab9f-ea539079e04c\"],\n          \"duration\": 1000,\n          \"delay\": 1000\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 229, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"e83483f4-4610-43c1-9fa8-b9543b47fcda\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e6f71327-37c4-4dd4-983f-482fc8c4ea0d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"051a2737-2a99-4435-b3f0-3fa14578699d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"x\": -194,\n          \"y\": -245,\n          \"width\": 388,\n          \"height\": 373,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"id\": \"8d557a70-608c-4322-a840-bbc774586389\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 225,\n          \"y\": 453,\n          \"id\": \"89ef9084-9e75-455e-a7d6-0fc5b07ac60b\",\n          \"width\": 371,\n          \"height\": 356,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:50:01\",\n            \"baseColor\": \"#cac8c2\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page08_image01.jpg\",\n            \"width\": 1096,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"From above of appetizing piece of cake decorated chocolate powder and mint leaves served near ceramic creamer and forks with light pink chrysanthemum on top placed on wooden board\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 68,\n          \"y\": -3,\n          \"width\": 275,\n          \"height\": 365,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3dd1bc4f-5b24-464a-89ac-d371fce80c3c\",\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">\\\"The tarts here are displayed like jewelry behind glass casings.\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 417,\n          \"width\": 294,\n          \"height\": 112,\n          \"id\": \"d0aa49f8-1d85-4f25-8a0b-db00060adb36\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #232c27\\\">Martin Hansson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 590,\n          \"width\": 240,\n          \"height\": 21,\n          \"id\": \"5b2443bd-2ca2-45c7-9a8e-5529ae95cbd8\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f3e8fc01-3844-413c-88be-93e9f1d66580\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"3dd1bc4f-5b24-464a-89ac-d371fce80c3c\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"267ed9a6-8879-4789-868f-503775b6cb03\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d0aa49f8-1d85-4f25-8a0b-db00060adb36\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"45cc1ddc-90bc-49be-b960-d29c00bacc6e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5b2443bd-2ca2-45c7-9a8e-5529ae95cbd8\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 229, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"7aa51ed5-fd22-444c-89c3-9c420d4d4122\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4111e375-f233-4a65-acb0-3bc70ed708a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"width\": 388,\n          \"height\": 373,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\",\n          \"id\": \"a03cdc6a-ee6a-4f5f-a9f2-6d35e6ba7726\",\n          \"x\": -194,\n          \"y\": -245\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 371,\n          \"height\": 356,\n          \"sticker\": { \"type\": \"floralPattern\" },\n          \"type\": \"sticker\",\n          \"id\": \"eeb6cb89-2349-4b57-a798-92b9443d911f\",\n          \"x\": 225,\n          \"y\": 453\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cormorant Garamond\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 924,\n              \"des\": -287,\n              \"tAsc\": 924,\n              \"tDes\": -287,\n              \"tLGap\": 0,\n              \"wAsc\": 937,\n              \"wDes\": 283,\n              \"xH\": 386,\n              \"capH\": 625,\n              \"yMin\": -283,\n              \"yMax\": 927,\n              \"hAsc\": 924,\n              \"hDes\": -287,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 42,\n          \"id\": \"1eabe3b5-cf96-470a-b9dd-883a2e183111\",\n          \"x\": 55,\n          \"y\": 35\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 61,\n          \"y\": 134,\n          \"width\": 152,\n          \"height\": 203,\n          \"scale\": 160,\n          \"focalX\": 53.22920253247898,\n          \"focalY\": 40.7806609582163,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3385bf43-19c8-4c6a-adc1-b54aa44b443c\",\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:03:51\",\n            \"baseColor\": \"#3c3124\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page09_image01.jpg\",\n            \"width\": 1081,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Aerial view of city buildings near body of water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 62,\n          \"y\": 359,\n          \"id\": \"129d39ec-ae37-4e9f-9f09-f3a0c2b586f4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 152,\n          \"height\": 203,\n          \"scale\": 160,\n          \"focalX\": 49.929873285367215,\n          \"focalY\": 34.54427893673837,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 188,\n            \"topRight\": 188,\n            \"bottomRight\": 188,\n            \"bottomLeft\": 188,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T05:10:21\",\n            \"baseColor\": \"#bab19e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/honeymooning-in-italy/page09_image02.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Trevi Fountain\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">A wedding on Lake Garda, Italy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 108,\n          \"height\": 66,\n          \"id\": \"96a88451-5c7f-4f26-8883-3a77501e2c82\",\n          \"x\": 239,\n          \"y\": 209,\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 238,\n          \"y\": 439,\n          \"id\": \"c7655bcf-fb73-40b2-a639-2e4cc7565ba8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #232c27\\\">See Rome in 36 hours.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 108,\n          \"height\": 43,\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5b1f17a7-630d-430e-9a73-b141584d0027\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"3385bf43-19c8-4c6a-adc1-b54aa44b443c\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9b1ffd03-d6dc-4513-9ecd-81926e8a95d5\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"129d39ec-ae37-4e9f-9f09-f3a0c2b586f4\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 1500,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"8b0b5f0c-8567-4f02-a2bf-945ce35cafec\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"96a88451-5c7f-4f26-8883-3a77501e2c82\"],\n          \"duration\": 2500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f8165c0d-eb01-40ec-bd70-ece5d46b9cf4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c7655bcf-fb73-40b2-a639-2e4cc7565ba8\"],\n          \"duration\": 2500,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 229, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"ea962a18-b3b9-42b7-b82a-5711c26062bb\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/house-hunting/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/house-hunting/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'house-hunting',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('House Hunting', 'template name', 'web-stories'),\n  tags: [\n    _x('Home', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Decor', 'template keyword', 'web-stories'),\n    _x('Budget', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Pastel Toffee Pink', 'color', 'web-stories'),\n      color: '#eec2bc',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black Violet', 'color', 'web-stories'),\n      color: '#2d2a35',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Marshmallow Yellow', 'color', 'web-stories'),\n      color: '#fff0d8',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Grape Purple', 'color', 'web-stories'),\n      color: '#464152',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its earthly colors and charming typography, this template will let you create guides and tutorials with a pinch of old-fashioned elegence. Present fresh new ideas for topics like home renovation, interior, architecture, gardening and more.',\n    'web-stories'\n  ),\n  vertical: _x('Home & Garden', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/house-hunting/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/house-hunting/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"89aaefa1-b2cb-4222-9809-60637b1c39f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 457,\n          \"scale\": 150,\n          \"focalX\": 52.07105064247922,\n          \"focalY\": 41.57092466616276,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"168933f8-16c7-41ae-94a0-d339ec226611\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page1_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Brown wooden bench near green plants\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#272823\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #eec2bc; letter-spacing: 1em; text-transform: uppercase\\\">Louisiana</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 94,\n          \"y\": 436,\n          \"width\": 224,\n          \"height\": 15,\n          \"id\": \"2adc4970-9823-4adb-aebe-eda406140022\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #eec2bc; letter-spacing: 0.04em\\\">House hunting</span>\\n<span style=\\\"color: #eec2bc; letter-spacing: 0.04em\\\">in New Orleans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 78,\n          \"id\": \"c4e87553-11d8-4d27-9c85-2591336413d2\",\n          \"x\": 71,\n          \"y\": 476,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #eec2bc\\\">Billy Rogers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 18,\n          \"id\": \"43fd8e6e-0e69-44fd-81f0-20303ebdf3eb\",\n          \"x\": 71,\n          \"y\": 572\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"53ece471-d87a-4e9d-9d33-908102e5c322\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"19fd0111-6b00-47ca-9a5f-608e886acc75\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 373,\n          \"height\": 365,\n          \"scale\": 115,\n          \"focalX\": 50,\n          \"focalY\": 47.59878773678326,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c8cdea4e-0fb6-4202-bbbe-ae544843a8e2\",\n          \"x\": 19.5,\n          \"y\": 310,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Brown and gray 3-story building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#4d4749\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Ever wondered how far you can stretch your dollar in a city like New Orleans?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 239,\n          \"height\": 73,\n          \"id\": \"2868430e-9026-4cde-b1f0-0eb54cd14531\",\n          \"x\": 84,\n          \"y\": 101\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Well, look no further.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 239,\n          \"height\": 22,\n          \"id\": \"889809e7-36d1-4c27-83e8-cf0d0d26316c\",\n          \"x\": 84,\n          \"y\": 206\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 238, \"g\": 194, \"b\": 188 } },\n      \"type\": \"page\",\n      \"id\": \"70a3cd58-9d7b-4d3c-bdd4-1df98654559f\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a83c7c89-f4ee-483b-9727-8a4343cf7aaf\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.02em\\\">Garden Style Home</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 39,\n          \"id\": \"affef821-e5f5-4d18-9960-ad7b0c8263dd\",\n          \"x\": 48,\n          \"y\": 480,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">If this is your budget, you’re really sitting pretty in a city like NoLa.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 47,\n          \"id\": \"e3fdc126-7223-4795-8f9b-06cf7e17c3f9\",\n          \"x\": 48,\n          \"y\": 530,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 105,\n          \"focalX\": 47.61904761904761,\n          \"focalY\": 48.05996472663139,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:17:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page3_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Photo of a living room\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c2c2ba\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 481,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ffc42125-e50a-410b-be33-155740e47e12\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 70, \"g\": 65, \"b\": 82 } },\n          \"x\": 0,\n          \"y\": 322,\n          \"width\": 180,\n          \"height\": 102,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d9f4f2fb-a927-4719-a066-8b7a0d1335bd\",\n          \"type\": \"shape\",\n          \"groupId\": \"7fb0e541-e1e3-4b09-b926-b51f241b5320\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #eec2bc; letter-spacing: 0.3em; text-transform: uppercase\\\">Budget</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 344,\n          \"width\": 101,\n          \"height\": 15,\n          \"id\": \"75b81328-8a6f-4549-9844-d32021ac8014\",\n          \"type\": \"text\",\n          \"groupId\": \"7fb0e541-e1e3-4b09-b926-b51f241b5320\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.03em\\\">$5000</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 124,\n          \"height\": 39,\n          \"id\": \"6ff14e23-da5a-4a8c-b272-e074b463e8ac\",\n          \"x\": 47,\n          \"y\": 363,\n          \"type\": \"text\",\n          \"groupId\": \"7fb0e541-e1e3-4b09-b926-b51f241b5320\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e99570e7-9ba8-46d6-9b2a-8135860e3ecb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d9f4f2fb-a927-4719-a066-8b7a0d1335bd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3ed1d903-aa98-4b5c-80c9-71116c64422d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"75b81328-8a6f-4549-9844-d32021ac8014\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c2f32b8c-901a-4682-a326-9e0835eab15a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6ff14e23-da5a-4a8c-b272-e074b463e8ac\"],\n          \"duration\": 2000,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"6c7b8c88-1b38-4e7d-9011-ed855b55b49a\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"7fb0e541-e1e3-4b09-b926-b51f241b5320\": {\n          \"name\": \"Budget\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 82,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"0194a0d4-9846-473c-a3bd-9f7b245199e1\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:18:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Black round plate on brown wooden table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#dad6c9\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ba6aabee-47d5-47ec-8522-eaf3b176a8a7\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"354e4319-d1bf-45a8-ac64-fa61f084f81b\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 40,\n          \"height\": 29,\n          \"id\": \"84e2ac5e-aff5-42be-a818-e69182e559b3\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"a5c0da69-3fc6-4c96-b134-93bd53db56ed\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Dining room</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 29,\n          \"id\": \"b23bab8b-8300-4ed6-b39e-70ee547fb372\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"a5c0da69-3fc6-4c96-b134-93bd53db56ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">Spacious open air dining rooms are indicative of the style.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 72,\n          \"id\": \"ee1f242d-2a3d-4745-9809-fb7eab60f5b5\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"a5c0da69-3fc6-4c96-b134-93bd53db56ed\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"69af32e2-091a-4b45-ad74-6a606d343007\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"68eb8ab8-e3f5-4798-ad91-5f89286753a3\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a5c0da69-3fc6-4c96-b134-93bd53db56ed\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T11:24:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"ab5ac926-ccff-4c98-b091-6322ba2dc17c\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 148,\n          \"focalX\": 28.3407487351915,\n          \"focalY\": 46.96010508564091,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:18:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page5_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"White concrete building\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#3e3624\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0568014c-b4e9-4827-b164-0d0bc42d7006\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"13928a79-39f2-41ef-b284-88a1d7d27793\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 42,\n          \"height\": 29,\n          \"id\": \"d2905692-f7f4-43b7-9193-8e22525f0507\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"7ffedb82-711e-49a7-b00e-85f8f83e8c99\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Courtyard</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 30,\n          \"id\": \"1c7d9329-8b65-4c3f-a43e-d991210cea9f\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"7ffedb82-711e-49a7-b00e-85f8f83e8c99\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">A courtyard, often even inside the center of a home is a classic.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 73,\n          \"id\": \"4dbf3584-34a1-481e-904a-b1221ebab7c4\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"7ffedb82-711e-49a7-b00e-85f8f83e8c99\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2cf09698-ee0a-44b1-97fa-6a5cebf3b0e4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e135fc75-153b-4571-8653-497b84f9ce4f\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7ffedb82-711e-49a7-b00e-85f8f83e8c99\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T11:24:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"44cac24c-82ba-47da-a921-afd0c30d5fb6\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 47.18603439291297,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:19:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page6_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Brown stairs\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cb8757\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbaf252a-e3d6-4603-8a07-b736bf48e2f8\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"f15270ec-1fac-41a0-bac8-2ffe2949c897\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 41,\n          \"height\": 29,\n          \"id\": \"cd224c31-de17-41c1-b96c-66f57f59345c\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"5f83f323-95ce-461b-aa6e-38baf8ea199a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Staircase</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 30,\n          \"id\": \"d2880695-59a2-43cd-8c47-3026bbed798e\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"5f83f323-95ce-461b-aa6e-38baf8ea199a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">Unique staircases are common in homes of this stature.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 73,\n          \"id\": \"6ac417ae-e6f6-4b98-8ea0-ccf302afa224\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"5f83f323-95ce-461b-aa6e-38baf8ea199a\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"43b73531-448a-44ee-bbd2-f4acf1ff5b27\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6d9fdcc7-b1e2-40b3-8a21-74e0c6f670b8\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5f83f323-95ce-461b-aa6e-38baf8ea199a\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8e0022da-7d1f-4e5a-a943-7a537235a3ae\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">Double Gallery</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 40,\n          \"id\": \"92dc0937-0487-4fd6-a6e3-ae9cf648db07\",\n          \"x\": 48,\n          \"y\": 454,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">You still have your pick of the litter at this price point. Personally, I’d go for something classic.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 73,\n          \"id\": \"53d35ae6-3846-4b01-9604-b24d57863088\",\n          \"x\": 48,\n          \"y\": 504,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 105,\n          \"focalX\": 56.73002676422878,\n          \"focalY\": 49.9538010854663,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:21:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page7_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Brown fabric sofa set\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d5d4d4\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 481,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"da259bf2-99c8-421e-bd21-3a2ce7cc4815\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 70, \"g\": 65, \"b\": 82 } },\n          \"x\": 0,\n          \"y\": 322,\n          \"width\": 180,\n          \"height\": 102,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"84be1653-7ad6-4b31-bc86-650190229482\",\n          \"type\": \"shape\",\n          \"groupId\": \"a3c24400-19d9-4e8f-aad8-ecdf648458c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #eec2bc; letter-spacing: 0.3em; text-transform: uppercase\\\">Budget</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 344,\n          \"width\": 101,\n          \"height\": 15,\n          \"id\": \"c369c457-8302-4bed-9762-1324e2856aca\",\n          \"type\": \"text\",\n          \"groupId\": \"a3c24400-19d9-4e8f-aad8-ecdf648458c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8; letter-spacing: 0.03em\\\">$3000</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 124,\n          \"height\": 39,\n          \"id\": \"a9189649-c7d6-4921-8840-ba2c1e909dd1\",\n          \"x\": 47,\n          \"y\": 363,\n          \"type\": \"text\",\n          \"groupId\": \"a3c24400-19d9-4e8f-aad8-ecdf648458c8\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a1d628b1-0ba6-4eb6-ab51-c44d7aaf407b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"84be1653-7ad6-4b31-bc86-650190229482\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"bfc2b1e5-a9b3-48d1-af4c-33fe8c9873f1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c369c457-8302-4bed-9762-1324e2856aca\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"125065c3-2732-4aaf-932c-1da082686cc4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a9189649-c7d6-4921-8840-ba2c1e909dd1\"],\n          \"duration\": 2000,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"bc33cae7-d386-4abd-888b-a24f97636890\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a3c24400-19d9-4e8f-aad8-ecdf648458c8\": {\n          \"name\": \"Budget\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T11:24:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"352494f0-831c-4ff5-87c6-d85c5be28bb8\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:22:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page8_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"White sofa set near window\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#afa18b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c806e095-f6b4-4376-ad58-5eabf7f7eec0\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"2a9d28dd-cb18-4f3f-bf27-605ba3a01ee4\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 29,\n          \"id\": \"7041c27e-9046-459d-bf0b-b8ae2eff0a3a\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"00a3c284-100d-4944-b8cd-472382dcbeef\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Top floor access</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 30,\n          \"id\": \"7d12d05d-1970-48ca-9eb3-bc63ff4b2064\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"00a3c284-100d-4944-b8cd-472382dcbeef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">There is typically a visible route to get to the top of this home.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 73,\n          \"id\": \"0b4d942c-3ffe-4674-90a2-413f1c87240b\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"00a3c284-100d-4944-b8cd-472382dcbeef\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"70354c98-7f97-4e04-b8fa-94bda7aa236c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"bab02cd5-9f1f-42bd-b402-02b46ab0891b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"00a3c284-100d-4944-b8cd-472382dcbeef\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T11:24:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3032254f-fc9e-4155-8323-e3fa0849f2ba\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:22:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page9_img1.jpg\",\n            \"width\": 1630,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Brown wooden armchair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#4f4e3c\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d5331a3b-a8c8-4145-95f6-a6614c7cb9e0\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"19a9b0d4-7824-4f00-bd81-e63e4e4d5534\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 44,\n          \"height\": 29,\n          \"id\": \"b38972d1-414e-41e6-be15-119b79a68da5\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"5a6287d7-7a46-46e5-8f1e-60e5f988f4fa\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Patio</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 30,\n          \"id\": \"51de8a00-107b-4783-95b3-c4904cce424c\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"5a6287d7-7a46-46e5-8f1e-60e5f988f4fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">On the roof, you’ll find hidden spaces or patios to enjoy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 195,\n          \"height\": 72,\n          \"id\": \"26f9001e-c33a-4eb8-ab78-d6d091ed003b\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"5a6287d7-7a46-46e5-8f1e-60e5f988f4fa\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c531314a-1c88-4f2a-90b2-464aa6cda094\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ea8fce46-64c3-448c-85ef-71f4c335e9b3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5a6287d7-7a46-46e5-8f1e-60e5f988f4fa\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T11:24:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page4_5_6_8_9_10_img2.png\",\n            \"width\": 756,\n            \"height\": 756,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Square pattern image\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 330,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"1195ed04-6863-4285-b0c5-b1e1d537ce26\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 183,\n          \"focalX\": 50,\n          \"focalY\": 63.67537425271104,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:22:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page10_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Brown-and-black wooden 5-piece dining set\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b09a87\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 62,\n          \"width\": 412,\n          \"height\": 407,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c545a0cf-2db3-4342-8add-e32a37062e31\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35; letter-spacing: 0.02em\\\">What to look for:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 22,\n          \"id\": \"fcc630a6-92ff-4c25-b53b-2878a1389843\",\n          \"x\": 47,\n          \"y\": 2,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 45,\n          \"height\": 29,\n          \"id\": \"9d3995ab-41c2-45f0-8e57-4a606902f6b8\",\n          \"x\": 47,\n          \"y\": 495,\n          \"type\": \"text\",\n          \"groupId\": \"8c559ef8-8a9f-45e3-94fa-7c6222612aa7\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2d2a35\\\">Gallery floor</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 204,\n          \"height\": 30,\n          \"id\": \"c2103ef1-6bb6-4545-ba03-3241276b0829\",\n          \"x\": 161,\n          \"y\": 499,\n          \"type\": \"text\",\n          \"groupId\": \"8c559ef8-8a9f-45e3-94fa-7c6222612aa7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(0,0,0,0.6)\\\">These days, gallery floors are used for formal dining.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 73,\n          \"id\": \"c22cbe3e-30a4-4196-8374-8fb6c5d4d83e\",\n          \"x\": 161,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"8c559ef8-8a9f-45e3-94fa-7c6222612aa7\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1fd64413-993c-4a0f-a882-213b67baa8e3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"03f3b088-ebe7-4f6f-bce1-1072607a5932\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8c559ef8-8a9f-45e3-94fa-7c6222612aa7\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b9be8428-2b84-49f9-87e3-6fa9a74a14c2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #eec2bc; letter-spacing: 0.02em\\\">More about New Orleans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 28,\n          \"id\": \"6d1088aa-a9db-46b2-bc86-3e1a37574a05\",\n          \"x\": 48,\n          \"y\": -3,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50.02453515608796,\n          \"focalY\": 54.24804301503373,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:23:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page11_img1.jpg\",\n            \"width\": 1059,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Gray sedan parked near multicolored building during daytime\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d8dee0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 48,\n          \"y\": 71,\n          \"width\": 317,\n          \"height\": 179,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5d906bbe-707b-4d0c-89c5-41e5e939b82f\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">What neighborhood is right for you?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 45,\n          \"id\": \"137dc11c-8d6f-42ab-982b-83d5c9e20fa4\",\n          \"x\": 48,\n          \"y\": 265,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50.02453515608796,\n          \"focalY\": 54.86930426333717,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T11:23:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/house-hunting/page11_img2.jpg\",\n            \"width\": 1079,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Trees beside white house\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#4b4634\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 317,\n          \"height\": 179,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a74ee8ca-33ad-43f4-ad82-a4252431e1e9\",\n          \"x\": 48,\n          \"y\": 344,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Trykker\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2022,\n              \"des\": -538,\n              \"tAsc\": 2022,\n              \"tDes\": -538,\n              \"tLGap\": 0,\n              \"wAsc\": 2022,\n              \"wDes\": 538,\n              \"xH\": 1013,\n              \"capH\": 1492,\n              \"yMin\": -539,\n              \"yMax\": 2027,\n              \"hAsc\": 2022,\n              \"hDes\": -538,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff0d8\\\">Managing the upkeep of an older home</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 45,\n          \"id\": \"c382aeb5-f3a0-427b-bd72-46c893b47bab\",\n          \"x\": 48,\n          \"y\": 538,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0a5bbac6-5d92-4f20-af19-91238026a264\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"137dc11c-8d6f-42ab-982b-83d5c9e20fa4\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"bf0d9c3c-37c1-4c8e-892e-9451ebecbffc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c382aeb5-f3a0-427b-bd72-46c893b47bab\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"973a57db-b313-49d6-bb08-5bee83721cb0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a74ee8ca-33ad-43f4-ad82-a4252431e1e9\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"14bfcf29-03ce-41b2-84bd-0c510b8546e4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5d906bbe-707b-4d0c-89c5-41e5e939b82f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 45, \"g\": 42, \"b\": 53 } },\n      \"type\": \"page\",\n      \"id\": \"c7c905cc-80d8-4f00-b8b5-6563dc2fcea5\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/how-contact-tracing-works/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/how-contact-tracing-works/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'how-contact-tracing-works',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('How Contact Tracing Works', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Network', 'template keyword', 'web-stories'),\n    _x('Insights', 'template keyword', 'web-stories'),\n    _x('Steps', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Blazing Red', 'color', 'web-stories'),\n      color: '#fe0002',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Tropical Blue', 'color', 'web-stories'),\n      color: '#94e1de',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gunmetal Blue', 'color', 'web-stories'),\n      color: '#252a3a',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its readability-focused design, this template is great for breaking down concepts and easily explaining technical topics with the help of photos, videos, and text.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/how-contact-tracing-works/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/how-contact-tracing-works/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b9330f4e-2a40-4cc8-9ff3-1a73511f949d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#ffffff\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page01_image05.png\",\n            \"width\": 1237,\n            \"height\": 294,\n            \"id\": 0,\n            \"alt\": \"Abstract pattern with circles\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -26,\n          \"y\": 598,\n          \"width\": 464,\n          \"height\": 78,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fa93e8b6-8ff1-4b9d-a5c3-8e94837d8b75\",\n          \"groupId\": \"7e51a0e1-1959-4dc3-9637-2237c352c4a2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-11T08:10:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page01_image04.png\",\n            \"width\": 1237,\n            \"height\": 1009,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Abstract pattern with circles\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -26,\n          \"y\": 210,\n          \"width\": 464,\n          \"height\": 269,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"58f3a434-e215-4522-84ea-1a28b33eeded\",\n          \"groupId\": \"7e51a0e1-1959-4dc3-9637-2237c352c4a2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 129,\n          \"focalX\": 61.00014544472795,\n          \"focalY\": 40.589955536258444,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#3ec3bc\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page01_image01.png\",\n            \"width\": 180,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man in black leather jacket and black pants walking on street during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 320,\n          \"width\": 124,\n          \"height\": 297,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e21e5054-939f-4fbd-8f50-66407a76ca2a\",\n          \"resizeWidth\": 57.78641,\n          \"resizeHeight\": 120.125,\n          \"groupId\": \"bab34a77-e091-451e-8329-072180fbf1d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page01_image02.jpg\",\n            \"width\": 181,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in black and white shirt wearing white mask\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2f0809\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 129,\n          \"y\": 266,\n          \"width\": 153,\n          \"height\": 409,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6fefb92d-01c8-4864-bcc5-3672c2a4dbd5\",\n          \"groupId\": \"bab34a77-e091-451e-8329-072180fbf1d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page01_image03.png\",\n            \"width\": 181,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in black leather jacket standing beside yellow car\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#68caca\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 288,\n          \"y\": 320,\n          \"width\": 124,\n          \"height\": 296,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b04c0272-848d-460b-b5b5-4147eb0e7d9f\",\n          \"groupId\": \"bab34a77-e091-451e-8329-072180fbf1d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 29,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.05,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">How it works:</span>\\n<span style=\\\"color: #fff\\\">Contact Tracing</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 73,\n          \"y\": 27,\n          \"width\": 274,\n          \"height\": 61,\n          \"id\": \"90a5e51a-13a2-44f8-8468-ac65afadeb1d\",\n          \"marginOffset\": 0.6343749999999986,\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 73,\n          \"y\": 140,\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"f3a16675-1450-4499-88d7-44a94c089a19\",\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\"\n        },\n        {\n          \"x\": 76,\n          \"y\": 140,\n          \"id\": \"33bc0ba3-8cb5-4caa-be61-8ead46a2b7f6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\"\n        },\n        {\n          \"x\": 79,\n          \"y\": 140,\n          \"id\": \"1fa37f0f-9d6b-4889-ab5a-cff421340ba3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\"\n        },\n        {\n          \"x\": 82,\n          \"y\": 140,\n          \"id\": \"27b5b56f-ec86-495d-a190-faeb2cc36879\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\"\n        },\n        {\n          \"x\": 73,\n          \"y\": 154,\n          \"id\": \"3ce384ee-0f05-4a8e-8aef-f7c2f4401086\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Billy Rogers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 80,\n          \"height\": 16,\n          \"marginOffset\": -0.5700000000000003,\n          \"groupId\": \"1f16b646-e901-476d-b503-34631e08cc78\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"acef1172-8528-42e0-b0da-e88f8a946feb\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"1f16b646-e901-476d-b503-34631e08cc78\": {\n          \"name\": \"Title\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"bab34a77-e091-451e-8329-072180fbf1d3\": {\n          \"name\": \"Images\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7e51a0e1-1959-4dc3-9637-2237c352c4a2\": {\n          \"name\": \"Background\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7428d0b2-a929-4668-bb3f-8f6b41d355ec\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page02_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representation of global network connections\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -0.5,\n          \"y\": -58,\n          \"width\": 413,\n          \"height\": 734,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a2a7861f-3f15-4d6d-888f-070bd04cd5ff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d303c\\\">In a world where contact tracing is slowly becoming utilized in everyday life, have you ever wondered “how exactly does it work?”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 65,\n          \"y\": 267,\n          \"width\": 282,\n          \"height\": 85,\n          \"id\": \"bb7291db-95c7-41e6-bbfa-691cb4f3ff97\",\n          \"marginOffset\": 0.703125\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0d117a47-1d57-4743-9b12-9e70e4a72eab\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"718d0a4c-6d61-4032-8184-5bf76b4bda41\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-04T06:56:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page03_bgvideo.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page03_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 11,\n            \"lengthFormatted\": \"0:11\",\n            \"alt\": \"Person Texting on Her Phone\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#322e30\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 736,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6688060e-f126-474b-9a59-12945c68441a\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"72a61171-0f0e-4b9b-9759-e4df2565ec87\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"9989b264-4ada-4b48-8308-3cac4cdc0eea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">First, a user must pick up a phone call from a contact tracing server.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 39,\n          \"marginOffset\": 0.703125,\n          \"id\": \"8b60fcc3-a7ce-4fa8-a2f2-7c84b2ff0695\",\n          \"x\": 65,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -19,\n          \"y\": 174,\n          \"width\": 374,\n          \"height\": 530,\n          \"sticker\": { \"type\": \"contactTracingPhone\" },\n          \"id\": \"3c12ddd1-a7f8-4095-8a68-02149412c1a2\",\n          \"groupId\": \"c9220a64-1778-4c5d-8379-43bf77e706cd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -85,\n          \"y\": 42,\n          \"width\": 592,\n          \"height\": 581,\n          \"sticker\": { \"type\": \"contactTracingRings\" },\n          \"id\": \"47c8a613-4a9d-4c32-8780-ddfc4052ec5f\",\n          \"groupId\": \"c9220a64-1778-4c5d-8379-43bf77e706cd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Contact Tracer</span>\\n<span style=\\\"color: #fff\\\">+ 1 (555) xxx-xxxx</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 31,\n          \"marginOffset\": 0.703125,\n          \"type\": \"text\",\n          \"id\": \"e0745ebe-9335-4dbc-9139-54d2b633dc4c\",\n          \"x\": 65,\n          \"y\": 252,\n          \"groupId\": \"c9220a64-1778-4c5d-8379-43bf77e706cd\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1cfd34d8-3d46-4536-bc6c-fe5f70fda807\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3c12ddd1-a7f8-4095-8a68-02149412c1a2\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"92867399-95ac-42d7-94db-fa985ff4e3a5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e0745ebe-9335-4dbc-9139-54d2b633dc4c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1657bdce-c366-4970-b835-80b4b183ff5a\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"47c8a613-4a9d-4c32-8780-ddfc4052ec5f\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"04629cd7-2843-4cf4-9a61-24b1eb9c416f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c9220a64-1778-4c5d-8379-43bf77e706cd\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b6b8c35f-137f-4fe1-bfa3-91ebb43ed1ac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page05_image01.png\",\n            \"width\": 480,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representation of a cloud\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -41,\n          \"y\": 102,\n          \"width\": 230,\n          \"height\": 150,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"cbfeb59b-ce76-4994-a049-dc2058b113be\",\n          \"groupId\": \"6191d443-18e6-43b0-b441-afd6138907ed\"\n        },\n        {\n          \"x\": 209,\n          \"y\": 16,\n          \"id\": \"59c25376-5094-46ce-a4c1-ae1ccb081b79\",\n          \"opacity\": 76,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page05_image01.png\",\n            \"width\": 480,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representation of a cloud\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 178,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"groupId\": \"6191d443-18e6-43b0-b441-afd6138907ed\"\n        },\n        {\n          \"x\": 93,\n          \"y\": 16,\n          \"id\": \"2b54870e-ac37-49f8-9c6b-58a30ade78aa\",\n          \"opacity\": 76,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page05_image01.png\",\n            \"width\": 480,\n            \"height\": 314,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representation of a cloud\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 96,\n          \"height\": 62,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"groupId\": \"6191d443-18e6-43b0-b441-afd6138907ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -301,\n          \"y\": 250,\n          \"width\": 1000,\n          \"height\": 991,\n          \"sticker\": { \"type\": \"contactTracingRings\" },\n          \"id\": \"6626e656-44c3-4cfa-a222-183ced30d615\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">A wireless signal is then sent to its cloud database.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 39,\n          \"marginOffset\": 0.703125,\n          \"id\": \"d8a9e4c7-a061-4ca4-9e74-b267cba91e70\",\n          \"x\": 65,\n          \"y\": 340\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"087ff6a8-e2d7-4b9a-8c96-6a26adc092ea\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"59c25376-5094-46ce-a4c1-ae1ccb081b79\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 5000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"49b824a6-fce1-4704-a3fe-967b331bc124\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cbfeb59b-ce76-4994-a049-dc2058b113be\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1294a636-dcbe-4273-a257-7297f55b0050\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"6626e656-44c3-4cfa-a222-183ced30d615\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"7609cb70-f9af-4656-ad87-9ffd2735fa5e\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"6191d443-18e6-43b0-b441-afd6138907ed\": {\n          \"name\": \"Clouds\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"37df1eb8-f0bb-4d48-b250-92fce749013c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#317171\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Timelapse photo of people passing the street\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"014c5d2b-2539-4e82-865b-14e1d1f607c0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">While contact tracing may feel cold and impersonal to some, it’s meant to ensure ultimate privacy &amp; data security.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 76.5,\n          \"y\": 267,\n          \"width\": 259,\n          \"height\": 85,\n          \"id\": \"719de5d8-1a9e-4b38-a774-bdfd875ef763\",\n          \"marginOffset\": 8.859375\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e4c12e7c-be31-4117-a8ad-3f63ab5cf8f1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7e06172d-3a90-4a2a-b7e5-3cbbd3c7f4bd\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:57:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page07_image04.png\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Illustrations of network connections\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#5363c2\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 545,\n          \"width\": 412,\n          \"height\": 220,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"18ad3f80-0386-45cf-a8a7-cac37236fa5e\",\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d303c\\\">Instead of actual phone numbers or names, the encrypted data of your phone is logged into the contact tracing system.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 279,\n          \"height\": 85,\n          \"marginOffset\": 3.603999999999999,\n          \"id\": \"4dcf770c-5afd-4476-b0bd-95160c4e5073\",\n          \"x\": 76,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page07_image03.png\",\n            \"width\": 153,\n            \"height\": 369,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person sitting in a public transport\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d8fbfb\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 311,\n          \"y\": 172,\n          \"width\": 124,\n          \"height\": 320,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0d0c922d-ff88-48be-b05d-ad179e3e9e3f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:57\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page07_image02.jpg\",\n            \"width\": 180,\n            \"height\": 411,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in green sweater holding black mask\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0c5250\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 138,\n          \"y\": 135,\n          \"width\": 157,\n          \"height\": 312,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ce068b4b-31dc-4ddc-a4cb-f294d1be4f4c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:56:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page07_image01.png\",\n            \"width\": 180,\n            \"height\": 411,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Timelapse photo of people passing the street\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -23,\n          \"y\": 244,\n          \"width\": 145,\n          \"height\": 272,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c8d96452-855f-4f6a-9c99-90faf673fba3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c2b2f3e8-5430-40b3-b759-2053c2269c92\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0d0c922d-ff88-48be-b05d-ad179e3e9e3f\"],\n          \"duration\": 2000,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"998f89be-7753-4ee1-8b0c-293c9861e015\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ce068b4b-31dc-4ddc-a4cb-f294d1be4f4c\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"30e9d0ad-1439-4092-b416-ec7a3bde131d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c8d96452-855f-4f6a-9c99-90faf673fba3\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 231, \"g\": 231, \"b\": 231 } },\n      \"type\": \"page\",\n      \"id\": \"fd56b36a-574b-4a93-80b3-25e2322130be\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d1f50101-9500-4097-89a0-c45506a5e32f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-22T10:33:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing face mask\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2d5d5d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f857818f-ebc2-42b0-b7df-8fce869644b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Intimate personal details are kept anonymous and logged only as a series of numbers and letters.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 76,\n          \"y\": 278.5,\n          \"width\": 260,\n          \"height\": 61,\n          \"id\": \"4e905f90-ba43-4871-a72a-8f33ffe4b45c\",\n          \"marginOffset\": 8.859375,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fa64f7ba-2f25-41ff-b555-adf796b72011\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1ee6d74a-c547-4600-ada3-e2c3487fa232\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:57:21\",\n            \"baseColor\": \"#204f56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page09_image01.png\",\n            \"width\": 617,\n            \"height\": 833,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Illustrations of a man with digital avatars around him\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 22,\n          \"y\": 171,\n          \"width\": 309,\n          \"height\": 417,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7e3d1529-c648-461a-bfe3-2fe224f94f8f\",\n          \"groupId\": \"e5c1f9ee-9451-4497-be1f-d88a2ad7039e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -90,\n          \"y\": 47,\n          \"width\": 590,\n          \"height\": 579,\n          \"sticker\": { \"type\": \"contactTracingRings\" },\n          \"id\": \"7db345de-6d4b-48f6-b045-fd982f5590cb\",\n          \"groupId\": \"e5c1f9ee-9451-4497-be1f-d88a2ad7039e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">The code scrapes inventory of who you have been in contact with over the last 30 days.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 56,\n          \"marginOffset\": 0.703125,\n          \"id\": \"1f2631b6-355c-4e29-9e81-8c8d1178975a\",\n          \"x\": 65,\n          \"y\": 0,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"621f8d2a-83ba-4f2e-99bb-db8f7bbcece6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7e3d1529-c648-461a-bfe3-2fe224f94f8f\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"a71afc65-aa68-49ac-8d26-e59edcc3e1b3\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"7db345de-6d4b-48f6-b045-fd982f5590cb\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"ea634391-b948-4b76-ba76-57d1a855c6c1\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e5c1f9ee-9451-4497-be1f-d88a2ad7039e\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a3264c15-a916-49e0-a628-d8015ab7f7a3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:57:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page10_image01.png\",\n            \"width\": 689,\n            \"height\": 820,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Illustrations of a man with connected digital avatars\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3a2c35\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -3,\n          \"y\": 158,\n          \"width\": 341,\n          \"height\": 407,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1a9f58c6-c666-44f3-a5ff-9e5ec85e7d1f\",\n          \"groupId\": \"848639c5-4984-4549-bfeb-81f55e05dba5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 590,\n          \"height\": 579,\n          \"sticker\": { \"type\": \"contactTracingRings\" },\n          \"id\": \"79e3f304-520f-48e4-9b6e-b48a52f13200\",\n          \"x\": -89,\n          \"y\": 49,\n          \"groupId\": \"848639c5-4984-4549-bfeb-81f55e05dba5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">It makes connections based on proximity to these other cellular devices and networks and starts to create a visual map of its own.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 75,\n          \"marginOffset\": 0.703125,\n          \"id\": \"5e9c2a56-fba1-4c5f-9599-bfdc66547d12\",\n          \"x\": 65,\n          \"y\": 0,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"051dff32-2014-4f8a-bae6-f25f025e17b8\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"848639c5-4984-4549-bfeb-81f55e05dba5\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0274de46-4280-4d80-9159-42d7c0991ed0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Only if you’ve tested positive and activated your contact tracing network will other users be notified.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 56,\n          \"marginOffset\": 0.703125,\n          \"id\": \"b423c51f-2157-48d5-8ea6-afcb4a9c19c4\",\n          \"x\": 65,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 592,\n          \"height\": 581,\n          \"sticker\": { \"type\": \"contactTracingRings\" },\n          \"id\": \"d0d3a306-c447-4107-8c81-db81c84ed03b\",\n          \"x\": -85,\n          \"y\": 42,\n          \"groupId\": \"1142e96b-0956-4c2d-b474-3ba13a77fb52\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 374,\n          \"height\": 530,\n          \"sticker\": { \"type\": \"contactTracingPhone\" },\n          \"id\": \"a6ab5c47-7dbf-4ab5-b091-714476e1f689\",\n          \"x\": -19,\n          \"y\": 174,\n          \"groupId\": \"1142e96b-0956-4c2d-b474-3ba13a77fb52\"\n        },\n        {\n          \"x\": 65,\n          \"y\": 252,\n          \"id\": \"ada5bd6e-9804-415c-99b0-9113c0918c63\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Contract Tracer</span>\\n<span style=\\\"color: #d00\\\">Possible Contact</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 282,\n          \"height\": 30,\n          \"marginOffset\": 0.703125,\n          \"type\": \"text\",\n          \"groupId\": \"1142e96b-0956-4c2d-b474-3ba13a77fb52\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"41f3362c-933b-4efc-b647-1d8c725aecf9\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"d0d3a306-c447-4107-8c81-db81c84ed03b\"]\n        },\n        {\n          \"id\": \"5c9f453e-1315-420a-9566-fd07ae70a5b3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ada5bd6e-9804-415c-99b0-9113c0918c63\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"d6e5ccf4-c83d-44f0-9701-8461f911386e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a6ab5c47-7dbf-4ab5-b091-714476e1f689\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 37, \"g\": 42, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"d61093dd-447a-4448-a0f4-bcec733712c0\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1142e96b-0956-4c2d-b474-3ba13a77fb52\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d9682d27-0a49-4b92-9bb7-cb818dff2b60\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-04T06:57:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page12_bgvideo.mp4\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page12_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A Man Writing On Paper His Observation Of A Subject Under The Microscope\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#c7cbc7\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 736,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"470b3ecc-4fba-4e49-81ae-fe84b21f8b6e\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b1e92d2b-d18c-4cb8-8774-6e0a54872a2c\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"9d82faa8-c32a-462c-9a74-db4a389501ee\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.05,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2d303c\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 74,\n          \"y\": 13,\n          \"width\": 186,\n          \"height\": 26,\n          \"id\": \"d771187d-91ba-4d58-abb5-c581ef048f00\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 146,\n          \"y\": 544,\n          \"id\": \"694fa31d-e994-4feb-a0cd-6efb60b31d3d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #22242e\\\">The science of AR maps</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 189,\n          \"height\": 18,\n          \"marginOffset\": 1.3439999999999976,\n          \"type\": \"text\",\n          \"groupId\": \"a0c3d60d-d61a-4dbb-9544-b94550e693f0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:57:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page13_image02.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Bokeh photography of person holding turned on iphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b3e34\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 74,\n          \"y\": 356,\n          \"width\": 261,\n          \"height\": 175,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6e318344-60c7-4bba-943e-1e4160dd7d9c\",\n          \"groupId\": \"a0c3d60d-d61a-4dbb-9544-b94550e693f0\"\n        },\n        {\n          \"x\": 76,\n          \"y\": 544,\n          \"id\": \"fa70bb42-6888-4263-a5ed-23542a818cce\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #22242e\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 17,\n          \"height\": 33,\n          \"marginOffset\": 3.1799999999999997,\n          \"type\": \"text\",\n          \"groupId\": \"a0c3d60d-d61a-4dbb-9544-b94550e693f0\"\n        },\n        {\n          \"x\": 76,\n          \"y\": 272,\n          \"id\": \"cd88ed81-c6e0-4603-8f3f-8f72f33cf319\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #22242e\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 17,\n          \"height\": 15,\n          \"marginOffset\": 3.1799999999999997,\n          \"type\": \"text\",\n          \"groupId\": \"b7fa09ba-1ec2-4d9d-b281-6e595a55d426\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #22242e\\\">How to build your own quantum computer</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 189,\n          \"height\": 40,\n          \"marginOffset\": 1.3439999999999976,\n          \"type\": \"text\",\n          \"id\": \"302714cf-49af-4528-a9a0-66b33fcdce68\",\n          \"x\": 146,\n          \"y\": 272,\n          \"groupId\": \"b7fa09ba-1ec2-4d9d-b281-6e595a55d426\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-04T06:57:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-contact-tracing-works/page13_image01.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White and green hard disk drive\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dacfbd\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 74,\n          \"y\": 87,\n          \"width\": 261,\n          \"height\": 175,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4431e12d-b0bf-4eea-bfac-206af0cf687f\",\n          \"groupId\": \"b7fa09ba-1ec2-4d9d-b281-6e595a55d426\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b02c3fac-edc1-4ff2-9890-a816d1494edc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"302714cf-49af-4528-a9a0-66b33fcdce68\"],\n          \"duration\": 1000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"e00de235-0055-4cac-b4a4-f05355779aea\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"694fa31d-e994-4feb-a0cd-6efb60b31d3d\"],\n          \"duration\": 1000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 225, \"g\": 225, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"9d746bcc-90f6-4f61-8100-70c6ff4cf2e2\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"b7fa09ba-1ec2-4d9d-b281-6e595a55d426\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a0c3d60d-d61a-4dbb-9544-b94550e693f0\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/how-video-calls-saved-the-day/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\n// For some reason, the inferred TypeScript type is too narrow here and we have to use\n// file declaration instead of importing directly from `template.json`.\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/how-video-calls-saved-the-day/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'how-video-calls-saved-the-day',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('How Video Calls Saved the Day', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Remote', 'template keyword', 'web-stories'),\n    _x('Video', 'template keyword', 'web-stories'),\n    _x('Bright', 'template keyword', 'web-stories'),\n    _x('Yellow', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Eclipse Black', 'color', 'web-stories'),\n      color: '#3a3a3a',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Amber Yellow', 'color', 'web-stories'),\n      color: '#ffbf0b',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template has a quirky font and a lively color palette that will let you create cool tech stories and turn boring content into narratives that are fun and entertaining.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/how-video-calls-saved-the-day/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/how-video-calls-saved-the-day/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6cc03e12-1bed-4f82-baf0-15b98948b15c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">How</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">Video Calls</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">Saved the Day</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 43,\n          \"y\": 10,\n          \"width\": 317,\n          \"height\": 236,\n          \"id\": \"fa12a7c8-c985-459f-9c8e-401a76007576\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -231,\n          \"y\": 295,\n          \"width\": 287,\n          \"height\": 204,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"aecd13c7-4abe-420c-bff8-1723d0adb3e0\",\n          \"groupId\": \"f3f8ba78-47a0-4c12-8e45-a55263db974d\"\n        },\n        {\n          \"x\": -224,\n          \"y\": 322,\n          \"id\": \"323e1d16-d1b6-4256-beb8-facf11a6a2df\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T10:30:56\",\n            \"baseColor\": \"#c3b4b4\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page01_image02.jpg\",\n            \"width\": 677,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman using macbook\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 278,\n          \"height\": 175,\n          \"scale\": 100,\n          \"focalX\": 49.94290127731412,\n          \"focalY\": 43.36426077894482,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"f3f8ba78-47a0-4c12-8e45-a55263db974d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 194,\n          \"y\": 295,\n          \"width\": 280,\n          \"height\": 204,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"35934601-79e9-450b-94f2-72a239dee8ff\",\n          \"groupId\": \"6af439e2-d568-4f3a-b21a-ac7bf4b1a0d2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T10:27:52\",\n            \"baseColor\": \"#d4d0cf\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page01_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Happy ethnic woman sitting at table with laptop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 196,\n          \"y\": 322,\n          \"width\": 278,\n          \"height\": 175,\n          \"scale\": 142,\n          \"focalX\": 51.87177988223175,\n          \"focalY\": 45.341347848667645,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d10b538c-f14a-4c98-81c1-29a7d82e687c\",\n          \"groupId\": \"6af439e2-d568-4f3a-b21a-ac7bf4b1a0d2\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 559,\n          \"id\": \"46740eba-44b0-4afb-96d3-d8c645de91b6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Written by Betty Doe</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">23 July, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 58\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 139,\n          \"y\": 352,\n          \"width\": 112,\n          \"height\": 50,\n          \"sticker\": { \"type\": \"videoCallsTooltip\" },\n          \"id\": \"40a6f116-13f9-4091-b364-9ae673d43f60\",\n          \"groupId\": \"a75a32db-67d1-4071-b7da-7d39b8f28830\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Hey!!!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 151,\n          \"y\": 365,\n          \"width\": 44,\n          \"height\": 19,\n          \"id\": \"e8c24d48-b29d-4948-9cbd-dbc0c9b3fbc3\",\n          \"groupId\": \"a75a32db-67d1-4071-b7da-7d39b8f28830\"\n        },\n        {\n          \"x\": 216,\n          \"y\": 363,\n          \"id\": \"587f4a17-7803-45a3-8edf-eb12dd3a704b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"🙂\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 23,\n          \"marginOffset\": 6.5625,\n          \"groupId\": \"a75a32db-67d1-4071-b7da-7d39b8f28830\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 191, \"b\": 11 } },\n      \"type\": \"page\",\n      \"id\": \"a2b16ddc-2786-458a-a8e3-8ad0cd34aa31\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"a75a32db-67d1-4071-b7da-7d39b8f28830\": {\n          \"name\": \"Chat\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f3f8ba78-47a0-4c12-8e45-a55263db974d\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6af439e2-d568-4f3a-b21a-ac7bf4b1a0d2\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"942c92a1-2a24-49a9-9db6-5f4ad6c90dfb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">We asked our friends and staff here at </span><span style=\\\"font-weight: 500; font-style: italic; color: #fff\\\">Connected</span><span style=\\\"font-weight: 500; color: #fff\\\"> to write videocall reviews so we could see just how effective virtual communication has been during quarantine.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 212,\n          \"id\": \"67c004c2-88a9-40d3-9273-d6b32a77559e\",\n          \"x\": 50,\n          \"y\": 10,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 178,\n          \"y\": 414,\n          \"id\": \"89645e1e-02df-4a6a-9534-8194a0ddcf3e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -8,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">See</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 97,\n          \"height\": 51,\n          \"groupId\": \"d9144810-2fe1-4198-98cc-e27ed5b5a51f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 225,\n          \"y\": 463,\n          \"id\": \"fc0ef842-cf31-4532-8c72-fec00cc8e938\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">the</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 94,\n          \"height\": 51,\n          \"groupId\": \"d9144810-2fe1-4198-98cc-e27ed5b5a51f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 156,\n          \"y\": 520,\n          \"id\": \"18861eb7-26b1-4d67-a28f-6660e0b2718a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -8,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 191, \"b\": 11 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">experiences</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 191,\n          \"height\": 51,\n          \"groupId\": \"d9144810-2fe1-4198-98cc-e27ed5b5a51f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T12:13:29\",\n            \"baseColor\": \"#ffffff\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page02_image01.png\",\n            \"width\": 88,\n            \"height\": 46,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White arrow\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 321,\n          \"y\": 592,\n          \"width\": 44,\n          \"height\": 23,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"00c0c07e-ce38-41ec-88b7-5bb7c62a2dab\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"10be46a9-c9c3-4fed-81b2-cf74dfb14b73\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"89645e1e-02df-4a6a-9534-8194a0ddcf3e\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"a897580a-1cf2-449b-a4b6-17c4184ccc6f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fc0ef842-cf31-4532-8c72-fec00cc8e938\"],\n          \"duration\": 1600,\n          \"delay\": 450\n        },\n        {\n          \"id\": \"bfa5a820-9da6-4c26-bef8-475460bf598d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"18861eb7-26b1-4d67-a28f-6660e0b2718a\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"940c266f-43d5-4ef1-991e-6dd681bf5e27\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"00c0c07e-ce38-41ec-88b7-5bb7c62a2dab\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"eafd228f-ca60-4d9a-a0d8-621a0c64f000\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"d9144810-2fe1-4198-98cc-e27ed5b5a51f\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6ef7d527-f05d-41ae-b6d4-48605a1f8f39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">Miss the</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">real thing:</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">68</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 180,\n          \"id\": \"cd4fb90a-54b2-4fa6-83fd-865e13fbdbfa\",\n          \"x\": 53,\n          \"y\": 119,\n          \"groupId\": \"4320a8bc-318d-4567-999f-50d5d8e8b9f6\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 125,\n          \"y\": 254,\n          \"id\": \"c897e972-cb32-476a-8748-18871821aaab\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 36,\n          \"height\": 37,\n          \"groupId\": \"4320a8bc-318d-4567-999f-50d5d8e8b9f6\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -3,\n          \"y\": 393,\n          \"width\": 419,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"1020e519-5e8f-4dbc-98c6-2d6cc2ba5b3b\",\n          \"groupId\": \"aba13638-ddf4-4ee3-ace9-c6784a3beb62\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T10:32:20\",\n            \"baseColor\": \"#dad3d0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page03_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Boy In White Polo Shirt Crying\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": 433,\n          \"width\": 412,\n          \"height\": 247,\n          \"scale\": 104,\n          \"focalX\": 50,\n          \"focalY\": 40.23199023199023,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9209a9f3-71ec-4f2e-b5fa-80b1a10a56b3\",\n          \"groupId\": \"aba13638-ddf4-4ee3-ace9-c6784a3beb62\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 112,\n          \"height\": 50,\n          \"sticker\": { \"type\": \"videoCallsTooltip\" },\n          \"id\": \"a01f052e-152a-4f8b-a47b-64142265abff\",\n          \"x\": 224,\n          \"y\": 410,\n          \"groupId\": \"993bd94e-33f1-4407-a78c-d601f60d4040\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Nooo!!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 55,\n          \"height\": 19,\n          \"id\": \"4a218b08-a654-42d7-9a0d-b54c57c531c1\",\n          \"x\": 237,\n          \"y\": 423,\n          \"groupId\": \"993bd94e-33f1-4407-a78c-d601f60d4040\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 21,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"🙁\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 299,\n          \"y\": 420,\n          \"width\": 27,\n          \"height\": 25,\n          \"id\": \"10df4f4e-1153-4106-963d-1d13ce047dc7\",\n          \"marginOffset\": 7.21875,\n          \"groupId\": \"993bd94e-33f1-4407-a78c-d601f60d4040\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ae0f38d3-cbcf-4ea9-936b-004f027f302e\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"9209a9f3-71ec-4f2e-b5fa-80b1a10a56b3\"]\n        },\n        {\n          \"id\": \"c58b6986-7aac-412b-9d24-224d21f719e2\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"1020e519-5e8f-4dbc-98c6-2d6cc2ba5b3b\"]\n        },\n        {\n          \"id\": \"9bfbb48c-5ae9-49ca-9825-7a3d4995070b\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"4a218b08-a654-42d7-9a0d-b54c57c531c1\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"e63de2d8-4195-48a7-a361-49d25e26eef1\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"a01f052e-152a-4f8b-a47b-64142265abff\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"106861ac-ab8e-4616-b2a6-0e8fd32c63b5\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"10df4f4e-1153-4106-963d-1d13ce047dc7\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 191, \"b\": 11 } },\n      \"type\": \"page\",\n      \"id\": \"8ce91ead-121e-4e39-a8dd-a0302b660873\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"993bd94e-33f1-4407-a78c-d601f60d4040\": {\n          \"name\": \"Chat\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4320a8bc-318d-4567-999f-50d5d8e8b9f6\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aba13638-ddf4-4ee3-ace9-c6784a3beb62\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2d8b482e-5624-46fb-b3ac-51efc1b2eea9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 438,\n          \"width\": 79,\n          \"height\": 30,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7c280353-ec99-4412-96fe-92a2c8e49bae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">“I hate</span><span style=\\\"font-weight: 500; color: #fff\\\"> commuting. 😩😩😩</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">Now it takes me 5 seconds from the bedroom to my office. 😀😀😀”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 113,\n          \"id\": \"42d44268-ecf9-4285-b6a3-b700eb086d1b\",\n          \"x\": 50,\n          \"y\": 438,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 302,\n          \"y\": 600,\n          \"id\": \"960fd66e-51f8-470c-a4ae-b91f55e1c91c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">John L.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 20\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:22:57\",\n            \"baseColor\": \"#f7bf26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page04_image02.png\",\n            \"width\": 1080,\n            \"height\": 973,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cartoon figure of a person riding a scooter\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 3,\n          \"width\": 412,\n          \"height\": 371,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9e862542-9498-4e41-840b-4b528e39ab7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 95,\n          \"y\": 33,\n          \"width\": 158,\n          \"height\": 112,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"8aeb3479-a7c1-4fd4-9d35-516208f07f59\",\n          \"groupId\": \"21f64464-a4ba-4dd7-b8f9-8f98e75c0c92\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:13:31\",\n            \"baseColor\": \"#b7b4b0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page04_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in gray tank top\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 156,\n          \"height\": 97,\n          \"scale\": 137,\n          \"focalX\": 49.844271414312914,\n          \"focalY\": 37.216274150177156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"262d7bbe-7dcf-4776-aef6-d5138c612d8e\",\n          \"x\": 96,\n          \"y\": 47,\n          \"groupId\": \"21f64464-a4ba-4dd7-b8f9-8f98e75c0c92\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"caecc005-5805-4cde-8782-4548bfe53830\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"960fd66e-51f8-470c-a4ae-b91f55e1c91c\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"fe31b57a-485e-4584-b7e7-1a0108e865e3\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"21f64464-a4ba-4dd7-b8f9-8f98e75c0c92\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"38f9046f-73ad-4669-933c-5d6e0de0607e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 268,\n          \"height\": 30,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f6009e6a-abcc-4be4-8896-2a1dcd250781\",\n          \"x\": 48,\n          \"y\": 438\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 302,\n          \"y\": 600,\n          \"id\": \"f9cb1694-8c47-480b-81e5-bffaa16f2c8f\",\n          \"content\": \"<span style=\\\"color: #fff\\\">John L.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 20,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:23:52\",\n            \"baseColor\": \"#1d1515\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page05_image02.png\",\n            \"width\": 724,\n            \"height\": 1029,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cartoon figure parachuting\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 68,\n          \"y\": 0,\n          \"width\": 276,\n          \"height\": 391,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"84c56f81-98f3-4ee1-911d-a207fb7a4bd1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 127,\n          \"y\": 143,\n          \"width\": 158,\n          \"height\": 112,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"4e7397b4-8b9d-409b-9ff2-619c7483d5fc\",\n          \"groupId\": \"f4d9f51a-0d82-4f3d-9993-3b4252075da8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:12:27\",\n            \"baseColor\": \"#c1cfcb\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page05_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing black eyeglasses\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 156,\n          \"height\": 97,\n          \"scale\": 155,\n          \"focalX\": 46.554028628380415,\n          \"focalY\": 55.324648535062806,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d7a6a69f-f2d4-4596-bceb-dad85a9cba8d\",\n          \"x\": 128,\n          \"y\": 157,\n          \"groupId\": \"f4d9f51a-0d82-4f3d-9993-3b4252075da8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">“Enabling remote work. </span><span style=\\\"font-weight: 500; color: #fff\\\">One minute I could be in NY, one minute in Italy. </span><span style=\\\"color: #fff\\\">✈️✈️✈️ </span><span style=\\\"font-weight: 500; color: #fff\\\">Theoretically, anyway.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 439,\n          \"width\": 312,\n          \"height\": 117,\n          \"id\": \"5e5712fb-53ae-4f87-b882-28d86929fb73\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"51f7b690-52a9-446d-9ee4-a94660b7084e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f9cb1694-8c47-480b-81e5-bffaa16f2c8f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"e67b0451-5a65-4802-8308-1341c1bc9a9e\",\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"f4d9f51a-0d82-4f3d-9993-3b4252075da8\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3554988d-224d-4e73-83e6-58c7d1dd381e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">People</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">use plants</span>\\n<span style=\\\"font-weight: 500; color: #3a3a3a\\\">89</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 180,\n          \"id\": \"cb9cdccc-75a4-42e9-b374-434741e4e136\",\n          \"x\": 53,\n          \"y\": 119,\n          \"type\": \"text\",\n          \"groupId\": \"0818554c-bcab-414c-ab5c-7dae86c15717\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 125,\n          \"y\": 254,\n          \"id\": \"b6b7be67-5810-4210-b2fd-1daa0c2a010d\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 36,\n          \"height\": 37,\n          \"type\": \"text\",\n          \"groupId\": \"0818554c-bcab-414c-ab5c-7dae86c15717\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 112,\n          \"height\": 50,\n          \"sticker\": { \"type\": \"videoCallsTooltip\" },\n          \"id\": \"c7952817-a99a-4022-b60d-2d63a640939e\",\n          \"x\": 224,\n          \"y\": 410,\n          \"groupId\": \"2a4108b1-14db-4fc2-9a60-1a9069aed787\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Aloha!!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 61,\n          \"height\": 19,\n          \"id\": \"914656ba-28ae-411c-aa0e-439fb2b3aea9\",\n          \"x\": 237,\n          \"y\": 423,\n          \"groupId\": \"2a4108b1-14db-4fc2-9a60-1a9069aed787\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"😃\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 304,\n          \"y\": 420,\n          \"width\": 20,\n          \"height\": 23,\n          \"id\": \"14eb0c30-651b-4dfa-aea1-794c3d8df75f\",\n          \"marginOffset\": 6.5625,\n          \"groupId\": \"2a4108b1-14db-4fc2-9a60-1a9069aed787\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -4.5,\n          \"y\": 392,\n          \"width\": 419,\n          \"height\": 306,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"7ba63f7e-1ada-4388-9d2d-f599c1e77d21\",\n          \"type\": \"sticker\",\n          \"groupId\": \"198c77cb-26f1-41cf-a54f-f4a55521eeae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T10:39:17\",\n            \"baseColor\": \"#e6e6ed\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page06_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo Of Woman Wearing White Shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 412,\n          \"height\": 250,\n          \"scale\": 130,\n          \"focalX\": 40.51069703243616,\n          \"focalY\": 47.412008281573506,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5e8ed5b0-173f-4c71-ade7-fc3c0d0b358e\",\n          \"x\": 0,\n          \"y\": 433,\n          \"groupId\": \"198c77cb-26f1-41cf-a54f-f4a55521eeae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:20:06\",\n            \"baseColor\": \"#fab911\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page06_image02.png\",\n            \"width\": 152,\n            \"height\": 195,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Orchid plant in a pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 18,\n          \"y\": 577,\n          \"width\": 76,\n          \"height\": 98,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4cb28cb9-618b-47d2-bcf8-96b5409e5af6\",\n          \"groupId\": \"198c77cb-26f1-41cf-a54f-f4a55521eeae\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3523d305-e8fc-41d0-9bb7-9800781cdfda\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5e8ed5b0-173f-4c71-ade7-fc3c0d0b358e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c22f74d3-b1d7-4b82-82c7-1f4b33e41628\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7ba63f7e-1ada-4388-9d2d-f599c1e77d21\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"572188c7-8e3a-4167-b40d-c940529f8ec1\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"c7952817-a99a-4022-b60d-2d63a640939e\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"e6e78946-8758-4952-a475-3d4bb06e22ee\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"914656ba-28ae-411c-aa0e-439fb2b3aea9\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"76d132de-aca4-4747-b29c-cc384cc7bdcb\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"14eb0c30-651b-4dfa-aea1-794c3d8df75f\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c0362077-befd-42f2-bc99-49c84f554624\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4cb28cb9-618b-47d2-bcf8-96b5409e5af6\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1300,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 191, \"b\": 11 } },\n      \"type\": \"page\",\n      \"id\": \"962fdc9c-994a-4368-afdc-b526e6c4cf5c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0818554c-bcab-414c-ab5c-7dae86c15717\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2a4108b1-14db-4fc2-9a60-1a9069aed787\": {\n          \"name\": \"Chat\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"198c77cb-26f1-41cf-a54f-f4a55521eeae\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"dc205837-f6f5-46df-84bc-205e74d63e60\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 79,\n          \"height\": 30,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a37f8a3e-a953-45d0-9cb1-e00335c66657\",\n          \"x\": 47,\n          \"y\": 436\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">“Video</span><span style=\\\"font-weight: 500; color: #fff\\\"> allows me to have meetings from the sofa. My ass is very happy 👌👌👌.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 84,\n          \"id\": \"79adf470-d2c9-4fa9-bffb-06581df0d3d6\",\n          \"x\": 48,\n          \"y\": 437,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 302,\n          \"y\": 600,\n          \"id\": \"0eedd59f-eef0-485b-a10e-615123c184eb\",\n          \"content\": \"<span style=\\\"color: #fff\\\">John L.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 20,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:28:10\",\n            \"baseColor\": \"#fab911\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page07_image02.png\",\n            \"width\": 944,\n            \"height\": 528,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cartoon figure of a woman using laptop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 26,\n          \"y\": 164,\n          \"width\": 360,\n          \"height\": 201,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"aa81639d-2331-4148-90ab-0e7806898404\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 68,\n          \"y\": 112,\n          \"width\": 158,\n          \"height\": 112,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"5e1ff880-11f0-4fd1-b04d-2d1ebd6af7cd\",\n          \"groupId\": \"c1a168fa-f682-44f8-8eb1-02d3a7e80279\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:10:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page07_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in brown knit top\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#646f6f\",\n            \"isExternal\": true\n          },\n          \"width\": 156,\n          \"height\": 97,\n          \"scale\": 170,\n          \"focalX\": 55.77992130255349,\n          \"focalY\": 50.127591590182355,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"188df79a-bb3a-4c94-9faa-4200fe2e5dfe\",\n          \"x\": 69,\n          \"y\": 126,\n          \"groupId\": \"c1a168fa-f682-44f8-8eb1-02d3a7e80279\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ad12b20a-a287-4a2b-98f3-45b7368b03be\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0eedd59f-eef0-485b-a10e-615123c184eb\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"b593ab98-1efc-4567-9fcc-2e14fc1e10d6\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c1a168fa-f682-44f8-8eb1-02d3a7e80279\": {\n          \"name\": \"Image\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6d96520f-8d5f-458e-a168-017bcc515ef4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 30,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"73c5174a-1816-4e3b-abe3-1b0434901d1b\",\n          \"x\": 48,\n          \"y\": 438\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 302,\n          \"y\": 600,\n          \"id\": \"f09bd595-d63d-4474-b173-e74fc7d5df9a\",\n          \"content\": \"<span style=\\\"color: #fff\\\">John L.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 69,\n          \"height\": 20,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">“Sometimes,</span><span style=\\\"font-weight: 500; color: #fff\\\"> I use video calls as a virtual bar to reunite with my friends 🍺🍺🍺.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 439,\n          \"width\": 286,\n          \"height\": 116,\n          \"id\": \"ef5f8776-7ec3-45ca-8745-ba312d632244\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 0,\n          \"y\": 33,\n          \"width\": 412,\n          \"height\": 293,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"df124319-286a-4426-bd31-76a1a2058dd2\",\n          \"groupId\": \"bfc16459-4693-4003-8d25-30d83ba69471\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T10:55:49\",\n            \"baseColor\": \"#c7b7a8\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page08_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cheerful girlfriends eating pizza and drinking beer in kitchen\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 3,\n          \"y\": 72,\n          \"width\": 206,\n          \"height\": 125,\n          \"scale\": 115,\n          \"focalX\": 53.252667549161046,\n          \"focalY\": 48.23597487592704,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0363b1f6-4874-4ce8-93fc-8c049b692f37\",\n          \"groupId\": \"bfc16459-4693-4003-8d25-30d83ba69471\"\n        },\n        {\n          \"x\": 3,\n          \"y\": 197,\n          \"id\": \"9a077340-22b0-48ef-b837-35e3a0cfc3c4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T10:59:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page08_image03.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Happy woman smiling during remote chat\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bcad9f\",\n            \"isExternal\": true\n          },\n          \"width\": 206,\n          \"height\": 126,\n          \"scale\": 170,\n          \"focalX\": 40.315526285558704,\n          \"focalY\": 53.99585425836172,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"bfc16459-4693-4003-8d25-30d83ba69471\"\n        },\n        {\n          \"x\": 208,\n          \"y\": 72,\n          \"id\": \"afe56b0a-19a4-4b3a-8994-56b34f1cb4a2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T10:57:56\",\n            \"baseColor\": \"#c9ad95\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page08_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cheerful woman smiling while sitting at table with laptop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 201,\n          \"height\": 125,\n          \"scale\": 150,\n          \"focalX\": 54.5441175650865,\n          \"focalY\": 56.07565348517123,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"bfc16459-4693-4003-8d25-30d83ba69471\"\n        },\n        {\n          \"x\": 208,\n          \"y\": 197,\n          \"id\": \"7d9642a4-0f1e-4b10-baba-d45517d0a35f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:00:35\",\n            \"baseColor\": \"#bf9979\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page08_image04.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman sitting on sofa while looking at phone with laptop on lap\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 201,\n          \"height\": 126,\n          \"scale\": 230,\n          \"focalX\": 49.975499710944504,\n          \"focalY\": 48.60620577817605,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"bfc16459-4693-4003-8d25-30d83ba69471\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e002dfcc-1be2-4ace-a7c8-f2de3ae9a61d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f09bd595-d63d-4474-b173-e74fc7d5df9a\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 58, \"g\": 58, \"b\": 58 } },\n      \"type\": \"page\",\n      \"id\": \"a7fcb1b4-6ddc-4a2c-94b6-43df3674422d\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bfc16459-4693-4003-8d25-30d83ba69471\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"897975dc-47d5-457a-964f-adfa87a337e1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 56,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #3a3a3a\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 125,\n          \"id\": \"8856d246-2f4b-456f-9e65-381c402385bb\",\n          \"x\": 47,\n          \"y\": 13,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 160,\n          \"y\": 546,\n          \"id\": \"762e82bf-a5b7-499f-96ba-0163bd782b36\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #3a3a3a\\\">Filter Trends</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 193,\n          \"height\": 51\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #3a3a3a\\\">Tech Trends</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 189,\n          \"height\": 51,\n          \"id\": \"95830244-e5c6-46ec-aeab-c07ae0f8679f\",\n          \"x\": 160,\n          \"y\": 356\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T13:37:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page09_image03.png\",\n            \"width\": 478,\n            \"height\": 479,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Heart shape with 'Love it.' text around it\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3c3c3c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 250,\n          \"y\": 123,\n          \"width\": 120,\n          \"height\": 120,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f2fd77e4-6129-40b2-9af7-6857975153ae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 49,\n          \"y\": 244,\n          \"width\": 158,\n          \"height\": 112,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"id\": \"d0d37097-15ae-4a55-b377-60d87b617440\",\n          \"groupId\": \"d57fa946-aff5-4b21-852a-d13fba941faf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:23:50\",\n            \"baseColor\": \"#4f4b42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page09_image01.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black woman messaging on modern cellphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 50,\n          \"y\": 258,\n          \"width\": 156,\n          \"height\": 97,\n          \"scale\": 110,\n          \"focalX\": 50.14806509174784,\n          \"focalY\": 42.448680320860255,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"de91ce5b-8a1b-4603-ad3e-350cb916fc17\",\n          \"groupId\": \"d57fa946-aff5-4b21-852a-d13fba941faf\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 434,\n          \"id\": \"fbd645f5-bac7-40e6-8c24-14af1220eafd\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 158,\n          \"height\": 112,\n          \"sticker\": { \"type\": \"videoCallsBrowserIcon\" },\n          \"groupId\": \"db10a96c-253b-4b41-be0d-33524c304eef\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 449,\n          \"id\": \"16c995f7-1bdb-4e70-8ac9-d6fa4a60cb18\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-26T11:06:37\",\n            \"baseColor\": \"#e0e5e4\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/how-video-calls-saved-the-day/page09_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman lying on bed with two cats\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"width\": 155,\n          \"height\": 96,\n          \"scale\": 135,\n          \"focalX\": 47.49654155128561,\n          \"focalY\": 55.08018645780306,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"db10a96c-253b-4b41-be0d-33524c304eef\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"da4ca752-c834-4374-bacd-0082f8252840\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"f2fd77e4-6129-40b2-9af7-6857975153ae\"],\n          \"duration\": 2500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7420f15d-939d-407f-a034-2b8e1b5ef38a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"de91ce5b-8a1b-4603-ad3e-350cb916fc17\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"bc2f2deb-6339-4434-ab25-4d660bd107a6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d0d37097-15ae-4a55-b377-60d87b617440\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"56821d7d-c2c0-43d2-b7ef-533d41e2cf3e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16c995f7-1bdb-4e70-8ac9-d6fa4a60cb18\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"73b8711d-c3a3-41b7-9ecf-80f60c174352\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fbd645f5-bac7-40e6-8c24-14af1220eafd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"496de04c-e2e7-4e95-89b7-12172b4ac6e6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"762e82bf-a5b7-499f-96ba-0163bd782b36\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"6e8cb3fb-3527-4e70-a27e-cdfcb1e605d4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"95830244-e5c6-46ec-aeab-c07ae0f8679f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 191, \"b\": 11 } },\n      \"type\": \"page\",\n      \"id\": \"4f916886-a771-4cf4-a294-62678347399d\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"d57fa946-aff5-4b21-852a-d13fba941faf\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"db10a96c-253b-4b41-be0d-33524c304eef\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/indoor-garden-oasis/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/indoor-garden-oasis/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'indoor-garden-oasis',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Indoor Garden Oasis DIY', 'template name', 'web-stories'),\n  tags: [\n    _x('Home', 'template keyword', 'web-stories'),\n    _x('Garden', 'template keyword', 'web-stories'),\n    _x('How To', 'template keyword', 'web-stories'),\n    _x('Plant', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Everglades Green', 'color', 'web-stories'),\n      color: '#235524',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mint Green', 'color', 'web-stories'),\n      color: '#c2e3c3',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Banana Cream Yellow', 'color', 'web-stories'),\n      color: '#fcefab',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mineral Green', 'color', 'web-stories'),\n      color: '#65a867',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template has a perfect balance of green, earthly colors and simple but playful typography. Create stories about gardening, nature crafts, cooking recipes, and more.',\n    'web-stories'\n  ),\n  vertical: _x('Home & Garden', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/indoor-garden-oasis/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/indoor-garden-oasis/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f6892538-fb4b-4334-8c62-65876e964a2d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Create Your Indoor Garden Oasis</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 70,\n          \"y\": 19,\n          \"width\": 294,\n          \"height\": 128,\n          \"id\": \"b535f835-a8ac-4626-8874-33f8575feb6d\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Home gardening guide</span>\\n<span style=\\\"color: #235524\\\">Maria Contelo</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 42,\n          \"id\": \"caa82a15-5242-43ff-8d6c-f8b16e6151ae\",\n          \"x\": 70,\n          \"y\": 155,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 214,\n          \"y\": 107,\n          \"width\": 147,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"homeGardenGreenCurvedLine\" },\n          \"id\": \"36ffb7eb-0030-4891-8a40-872d80d06bcc\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 70,\n          \"y\": 272,\n          \"width\": 342,\n          \"height\": 403,\n          \"scale\": 136,\n          \"focalX\": 43.53230567828931,\n          \"focalY\": 43.07677403503722,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a8ee899f-6303-482f-a48d-8c56e2800f69\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page1_img1.jpg\",\n            \"width\": 330,\n            \"height\": 444,\n            \"id\": 0,\n            \"alt\": \"Green Indoor Plants\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#252313\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n      \"type\": \"page\",\n      \"id\": \"922cb2db-3900-4f14-adfe-18d804ba73a2\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a12d712a-78d4-472f-bb2f-d1032c992fca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 278,\n          \"y\": -92,\n          \"width\": 170,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"homeGardenFloral\" },\n          \"id\": \"ee4193b8-ff82-431e-8c5c-e34b8b8d2da2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fcefab\\\">Ever wanted a little garden or jungle oasis of your own?</span>\\n<span style=\\\"font-weight: 700; color: #fcefab\\\">Bring the outside in with our DIY guide to making your apartment as green as can be.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 303,\n          \"height\": 286,\n          \"id\": \"7b178d50-8276-4635-8143-50b327621dd4\",\n          \"x\": 48,\n          \"y\": 161,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Start the</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">tutorial</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 114,\n          \"height\": 65,\n          \"id\": \"e690e05a-80a3-4d9a-8093-c98223c8fbbf\",\n          \"x\": 203,\n          \"y\": 537,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 313,\n          \"y\": 575,\n          \"width\": 50,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"homeGardenLightYellowArrow\" },\n          \"id\": \"21028a0a-0f9e-41e2-894c-9fa0c5d271d4\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"717de74c-9d44-4b06-8c6a-f196461d3da6\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e690e05a-80a3-4d9a-8093-c98223c8fbbf\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"4b5533ee-c99e-4cdd-a107-1d1671639482\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"21028a0a-0f9e-41e2-894c-9fa0c5d271d4\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 35, \"g\": 85, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"5d627c7b-7b9f-4edb-a687-79932fbedfcd\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"738d1596-b055-4034-8d7e-f22f139663d0\",\n          \"scale\": 133,\n          \"focalX\": 49.079410173160205,\n          \"focalY\": 58.64571283979178,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page3_img1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Green Plants on Brown Clay Pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dadad9\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"type\": \"shape\",\n          \"x\": 50,\n          \"y\": 520,\n          \"width\": 362,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a6f107f0-8240-4659-9426-53d487426882\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"groupId\": \"08ea09d4-97e9-414e-8165-99bd0083025a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 26,\n          \"id\": \"504e4fcd-40b1-4fff-9a9c-9ce8b8dc566f\",\n          \"x\": 117,\n          \"y\": 555,\n          \"groupId\": \"08ea09d4-97e9-414e-8165-99bd0083025a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524; text-transform: uppercase\\\">Lighting</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 24,\n          \"id\": \"6f4f2111-fa5c-438e-9dec-e35e790e7a6c\",\n          \"x\": 171,\n          \"y\": 555,\n          \"groupId\": \"08ea09d4-97e9-414e-8165-99bd0083025a\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #235524\\\">Adjustable LED lights help your plants grow.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 40,\n          \"id\": \"8ccc12f5-3846-4d96-a1df-72c7947994dc\",\n          \"x\": 171,\n          \"y\": 590,\n          \"groupId\": \"08ea09d4-97e9-414e-8165-99bd0083025a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Here's What You Need</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 88,\n          \"id\": \"823ef878-bce5-4b20-9042-43627cd963b2\",\n          \"x\": 60,\n          \"y\": 10,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 110,\n          \"height\": 7,\n          \"sticker\": { \"type\": \"homeGardenGreenCurvedLine\" },\n          \"id\": \"5d34b15e-1c4b-4571-8bf7-7ba08eabd846\",\n          \"x\": 142,\n          \"y\": 92\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"303fc544-8bb3-41cb-b151-45979d36ea6c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5d34b15e-1c4b-4571-8bf7-7ba08eabd846\"],\n          \"duration\": 600,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8fd8f72f-866b-407c-b5fa-71d9b8979eb6\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"4508a287-6291-481e-8165-e648fd8d2505\"\n      },\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"08ea09d4-97e9-414e-8165-99bd0083025a\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"4508a287-6291-481e-8165-e648fd8d2505\",\n          \"scale\": 122,\n          \"focalX\": 45.390278361506184,\n          \"focalY\": 54.45893228580137,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page4_img1.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Top View Photo of Gardening Tools\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3d362c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"type\": \"shape\",\n          \"width\": 362,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"7aced4c7-1069-482f-8c3f-60c6db9672d0\",\n          \"x\": 50,\n          \"y\": 520,\n          \"groupId\": \"bec97c62-440e-4b17-8dea-b046aca32f8c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 25,\n          \"id\": \"3f8a2113-98b9-48a0-be78-70325ed9aae4\",\n          \"x\": 117,\n          \"y\": 555,\n          \"type\": \"text\",\n          \"groupId\": \"bec97c62-440e-4b17-8dea-b046aca32f8c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524; text-transform: uppercase\\\">Tools / Shear</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 193,\n          \"height\": 24,\n          \"id\": \"9f870da1-0183-48f4-aa7c-cc09169cd949\",\n          \"x\": 171,\n          \"y\": 555,\n          \"type\": \"text\",\n          \"groupId\": \"bec97c62-440e-4b17-8dea-b046aca32f8c\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #235524\\\">The right tools to trim, weed, and maintain.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 38,\n          \"id\": \"3f78c080-30be-4e29-bc1e-2446887fc011\",\n          \"x\": 171,\n          \"y\": 590,\n          \"type\": \"text\",\n          \"groupId\": \"bec97c62-440e-4b17-8dea-b046aca32f8c\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ec792364-e2d5-40b9-aa60-5db0c09d8ac6\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"3f4a4f74-b76e-4499-ba8f-b8c9079407a9\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bec97c62-440e-4b17-8dea-b046aca32f8c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"e4908e6a-5944-443b-a919-c205944024dc\",\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page5_img1.jpg\",\n            \"width\": 1707,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Person Arranging Pot Plant\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bab19f\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"x\": 50,\n          \"y\": 520,\n          \"width\": 362,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"81df0afc-8bf0-4219-9111-71544bd81f33\",\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"396ae62e-701d-4481-975c-f6b8c5f27659\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 27,\n          \"height\": 25,\n          \"id\": \"9e7aafdf-a11e-45e9-aeeb-79f0eb51b685\",\n          \"x\": 117,\n          \"y\": 555,\n          \"type\": \"text\",\n          \"groupId\": \"396ae62e-701d-4481-975c-f6b8c5f27659\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524; text-transform: uppercase\\\">Kit / Containers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 193,\n          \"height\": 24,\n          \"id\": \"8a552d5e-e826-42ff-8b0e-cc720947b9bf\",\n          \"x\": 171,\n          \"y\": 555,\n          \"type\": \"text\",\n          \"groupId\": \"396ae62e-701d-4481-975c-f6b8c5f27659\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #235524\\\">From very basic to self-watering.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 163,\n          \"height\": 38,\n          \"id\": \"9f6cddd9-fb02-4c1c-9e5c-46a7ba0f8fe3\",\n          \"x\": 171,\n          \"y\": 590,\n          \"type\": \"text\",\n          \"groupId\": \"396ae62e-701d-4481-975c-f6b8c5f27659\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ead36123-a0dd-4ad9-b191-63fdc3295398\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8a552d5e-e826-42ff-8b0e-cc720947b9bf\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"db831e72-efa8-4a99-866c-90fd4f1f5d59\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9f6cddd9-fb02-4c1c-9e5c-46a7ba0f8fe3\"],\n          \"duration\": 1800,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"154707cb-ee9e-4e1e-8a7a-d98f7f94cdc0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"95c725ea-5fd3-4152-841a-6feb6ae0b0c6\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"396ae62e-701d-4481-975c-f6b8c5f27659\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"80b664ed-f4b1-430c-83a3-291e0063754e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 250,\n          \"scale\": 158,\n          \"focalX\": 54.07696341385476,\n          \"focalY\": 43.91295004501316,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1c5c2846-6764-478f-88e1-0251aa853078\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-29T11:41:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page69_img1.jpg\",\n            \"width\": 193,\n            \"height\": 257,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo of Plants On White Pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dddee3\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 21,\n          \"id\": \"63496cee-5d3a-447a-b61b-6c4c45505837\",\n          \"x\": 128,\n          \"y\": 361,\n          \"groupId\": \"ad195e87-b039-4d96-b8ff-1bbfb2ab6dc9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Warm Light</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"9a97dcd7-a430-4e44-ac18-0c4addfbbabb\",\n          \"x\": 165,\n          \"y\": 360,\n          \"groupId\": \"ad195e87-b039-4d96-b8ff-1bbfb2ab6dc9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 50,\n          \"y\": 343,\n          \"width\": 53,\n          \"height\": 53,\n          \"sticker\": { \"type\": \"homeGardenGreenSun\" },\n          \"id\": \"c7dafcd4-aaa3-47d1-bdc4-fef044506328\",\n          \"groupId\": \"ad195e87-b039-4d96-b8ff-1bbfb2ab6dc9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"8b30efe8-3e05-4760-958f-49459adefb36\",\n          \"x\": 128,\n          \"y\": 448,\n          \"groupId\": \"150165ee-5a35-4090-9311-231a96b61d38\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Fluorescent Bulbs</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 159,\n          \"height\": 21,\n          \"id\": \"8e47e485-1dd7-4dc4-b626-ec533400df6e\",\n          \"x\": 165,\n          \"y\": 447,\n          \"groupId\": \"150165ee-5a35-4090-9311-231a96b61d38\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 64,\n          \"y\": 427,\n          \"width\": 24,\n          \"height\": 35,\n          \"sticker\": { \"type\": \"homeGardenGreenBulb\" },\n          \"id\": \"0ada4bf7-ba5a-4e04-83dc-2fe6076c5686\",\n          \"groupId\": \"150165ee-5a35-4090-9311-231a96b61d38\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"93562e17-12f6-4080-a6d9-e43879fcc3ef\",\n          \"x\": 128,\n          \"y\": 528,\n          \"groupId\": \"45ec8ec2-3ebb-4dd6-97e0-1328dd50111b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Indirect Light</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"b58a82c3-ef3c-4cb7-a8b4-685c5d630465\",\n          \"x\": 165,\n          \"y\": 528,\n          \"groupId\": \"45ec8ec2-3ebb-4dd6-97e0-1328dd50111b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 58,\n          \"y\": 517,\n          \"width\": 40,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"homeGardenGreenSunLight\" },\n          \"id\": \"f0e7f4f3-7999-4c9e-883d-7a66668798c6\",\n          \"groupId\": \"45ec8ec2-3ebb-4dd6-97e0-1328dd50111b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">First things first: Choose Your Light</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 76,\n          \"id\": \"45002d21-5703-4197-aea8-80748fe4bf6a\",\n          \"x\": 48,\n          \"y\": 227,\n          \"groupId\": \"4338d9be-1da7-4877-af11-4a1fcda72827\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 250,\n          \"y\": 300,\n          \"width\": 75,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"homeGardenGreenCurvedLine\" },\n          \"id\": \"039c0046-dd34-442c-a084-abe00e14d682\",\n          \"groupId\": \"4338d9be-1da7-4877-af11-4a1fcda72827\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c5020848-d191-4973-aed1-f7709d05fbfe\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"039c0046-dd34-442c-a084-abe00e14d682\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1d849f77-5708-4bca-a035-fea852dbf6b6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c7dafcd4-aaa3-47d1-bdc4-fef044506328\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"cdc7174e-353f-459e-ad3b-1b5e5886175a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0ada4bf7-ba5a-4e04-83dc-2fe6076c5686\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"454a32be-ef4f-4777-a29e-4354f83f771c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f0e7f4f3-7999-4c9e-883d-7a66668798c6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n      \"type\": \"page\",\n      \"id\": \"ed7e71ef-0a89-4e9c-a433-bb5fb7d0d08b\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"ad195e87-b039-4d96-b8ff-1bbfb2ab6dc9\": {\n          \"name\": \"Warm\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"150165ee-5a35-4090-9311-231a96b61d38\": {\n          \"name\": \"Bulbs\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"45ec8ec2-3ebb-4dd6-97e0-1328dd50111b\": {\n          \"name\": \"Indirect\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4338d9be-1da7-4877-af11-4a1fcda72827\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1c3990e9-0950-4a7d-8ce3-9e1f81eb9cd2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 228,\n          \"scale\": 103,\n          \"focalX\": 50.08243267997803,\n          \"focalY\": 46.656495766873604,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"308de66e-34e2-4092-85b5-4f6767cd9900\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page7_img1.jpg\",\n            \"width\": 330,\n            \"height\": 247,\n            \"id\": 0,\n            \"alt\": \"black pruning shears beside green gloves\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d4d4c7\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 21,\n          \"id\": \"f6a2098d-7d32-4dfd-a982-108646809a56\",\n          \"x\": 112,\n          \"y\": 364,\n          \"type\": \"text\",\n          \"groupId\": \"71e56ad5-0ce0-4e6b-8579-a0aae38211e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Length</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"52ab8831-c71e-43b2-a348-8470fe9d23db\",\n          \"x\": 149,\n          \"y\": 363,\n          \"type\": \"text\",\n          \"groupId\": \"71e56ad5-0ce0-4e6b-8579-a0aae38211e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 51,\n          \"y\": 342,\n          \"width\": 42,\n          \"height\": 57,\n          \"sticker\": { \"type\": \"homeGardenLengthComparison\" },\n          \"id\": \"82209229-9d69-49e1-9ecf-740615f522fe\",\n          \"groupId\": \"71e56ad5-0ce0-4e6b-8579-a0aae38211e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"81dad450-7fb6-47c7-8376-b6ec665f07c0\",\n          \"x\": 112,\n          \"y\": 467,\n          \"type\": \"text\",\n          \"groupId\": \"e4446643-c21f-4001-86a4-efe7323cb1a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Size</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 159,\n          \"height\": 22,\n          \"id\": \"e61606d4-e7aa-47fe-a583-00035a799160\",\n          \"x\": 149,\n          \"y\": 466,\n          \"type\": \"text\",\n          \"groupId\": \"e4446643-c21f-4001-86a4-efe7323cb1a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 53,\n          \"y\": 446,\n          \"width\": 35,\n          \"height\": 54,\n          \"sticker\": { \"type\": \"homeGardenScissor\" },\n          \"id\": \"4489f34e-3f21-420f-b572-09f7da562a27\",\n          \"groupId\": \"e4446643-c21f-4001-86a4-efe7323cb1a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"e5f3315f-1531-4d65-98fa-bbf401b79a0e\",\n          \"x\": 112,\n          \"y\": 572,\n          \"type\": \"text\",\n          \"groupId\": \"47c18454-a2fc-40ab-887c-9cbb670c53b3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Weight</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"5a4683e0-4006-46b3-9a1b-46626f4e4d47\",\n          \"x\": 149,\n          \"y\": 572,\n          \"type\": \"text\",\n          \"groupId\": \"47c18454-a2fc-40ab-887c-9cbb670c53b3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 50,\n          \"y\": 547,\n          \"width\": 31,\n          \"height\": 59,\n          \"sticker\": { \"type\": \"homeGardenCurvedScissor\" },\n          \"id\": \"a2ce4245-ec6a-4a92-98d7-ff3428fced51\",\n          \"groupId\": \"47c18454-a2fc-40ab-887c-9cbb670c53b3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Tools and Shears</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 173,\n          \"height\": 76,\n          \"id\": \"f8eb9a6f-2f70-434d-a688-82a64c1d4c28\",\n          \"x\": 48,\n          \"y\": 217,\n          \"type\": \"text\",\n          \"groupId\": \"788749db-17ca-4a39-8d6b-18a17a7044ec\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 50,\n          \"y\": 287,\n          \"width\": 102,\n          \"height\": 7,\n          \"sticker\": { \"type\": \"homeGardenGreenCurvedLine\" },\n          \"id\": \"0c1e671d-e9f9-4f3c-a41b-8ead9eeef381\",\n          \"groupId\": \"788749db-17ca-4a39-8d6b-18a17a7044ec\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9598b6ec-f45d-4a16-a357-3b18e3e1227d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0c1e671d-e9f9-4f3c-a41b-8ead9eeef381\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n      \"type\": \"page\",\n      \"id\": \"e7f8be07-172e-4325-a77e-a2075252c88b\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"788749db-17ca-4a39-8d6b-18a17a7044ec\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"71e56ad5-0ce0-4e6b-8579-a0aae38211e0\": {\n          \"name\": \"Length\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e4446643-c21f-4001-86a4-efe7323cb1a0\": {\n          \"name\": \"Size\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"47c18454-a2fc-40ab-887c-9cbb670c53b3\": {\n          \"name\": \"Weight\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ba12cf06-1f0c-49f0-b588-8ee554f78fea\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 228,\n          \"scale\": 160,\n          \"focalX\": 50,\n          \"focalY\": 41.71065859600383,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ff242b44-dbbe-456c-93e6-e9c404b01791\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page8_img1.jpg\",\n            \"width\": 330,\n            \"height\": 461,\n            \"id\": 0,\n            \"alt\": \"Photo of Green Leafed Plant in Bottle With Water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e2e8f5\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 21,\n          \"id\": \"1410ff5b-c18b-4200-b4c5-11eb83796065\",\n          \"x\": 116,\n          \"y\": 393,\n          \"type\": \"text\",\n          \"groupId\": \"3b0633a4-ac97-4d1f-861f-a9acb8653161\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Watering</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"021a9f9f-f796-4f9e-8bc0-b42d999c8e8f\",\n          \"x\": 150,\n          \"y\": 394,\n          \"type\": \"text\",\n          \"groupId\": \"3b0633a4-ac97-4d1f-861f-a9acb8653161\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 56,\n          \"y\": 374,\n          \"width\": 36,\n          \"height\": 48,\n          \"sticker\": { \"type\": \"homeGardenWaterDroplet\" },\n          \"id\": \"2ef4fdde-c9b4-475d-b4e6-682df6d9401e\",\n          \"groupId\": \"3b0633a4-ac97-4d1f-861f-a9acb8653161\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"49a9429d-aef8-409f-bcd7-3dc25e141345\",\n          \"x\": 116,\n          \"y\": 479,\n          \"type\": \"text\",\n          \"groupId\": \"437c878e-30f4-49b4-b8ff-cfae9141861b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Lighting Requirements</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 192,\n          \"height\": 22,\n          \"id\": \"96aa0e6b-471f-4f7c-98c2-e961ddca48c8\",\n          \"x\": 155,\n          \"y\": 477,\n          \"type\": \"text\",\n          \"groupId\": \"437c878e-30f4-49b4-b8ff-cfae9141861b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 456,\n          \"width\": 54,\n          \"height\": 58,\n          \"sticker\": { \"type\": \"homeGardenGreenLightning\" },\n          \"id\": \"4e258291-7312-43a4-9564-f42814187f4a\",\n          \"groupId\": \"437c878e-30f4-49b4-b8ff-cfae9141861b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 22,\n          \"id\": \"bb8f9e13-dadf-4163-bc4d-9c93d271a5cb\",\n          \"x\": 116,\n          \"y\": 566,\n          \"type\": \"text\",\n          \"groupId\": \"914a6ac0-daec-411a-8bfa-1edc2579134a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Simplicity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"d7943297-ed62-4126-b51b-8ef53c2d295d\",\n          \"x\": 153,\n          \"y\": 566,\n          \"type\": \"text\",\n          \"groupId\": \"914a6ac0-daec-411a-8bfa-1edc2579134a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 56,\n          \"y\": 547,\n          \"width\": 41,\n          \"height\": 52,\n          \"sticker\": { \"type\": \"homeGardenGreenBag\" },\n          \"id\": \"8e4792a4-f44d-42a2-a4f1-21c050a2eb43\",\n          \"groupId\": \"914a6ac0-daec-411a-8bfa-1edc2579134a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">So you want an all-in-one kit</span>\\n<span style=\\\"font-weight: 700; color: #235524\\\">you say?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 288,\n          \"height\": 111,\n          \"id\": \"75250deb-1eca-4181-ae65-c7c46278b5e0\",\n          \"x\": 48,\n          \"y\": 217,\n          \"type\": \"text\",\n          \"groupId\": \"712f6cc1-ca5e-48b7-9c15-380701241327\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 284,\n          \"width\": 204,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"homeGardenGreenCurvedLine\" },\n          \"id\": \"23bb0d9d-539a-47cd-b186-78239d694f40\",\n          \"groupId\": \"712f6cc1-ca5e-48b7-9c15-380701241327\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8f63b72e-0572-41dc-9131-347f1baf284a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"23bb0d9d-539a-47cd-b186-78239d694f40\"],\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n      \"type\": \"page\",\n      \"id\": \"eed5040e-dd69-4b40-833a-adf77506ee9f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"712f6cc1-ca5e-48b7-9c15-380701241327\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"914a6ac0-daec-411a-8bfa-1edc2579134a\": {\n          \"name\": \"Simple\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"437c878e-30f4-49b4-b8ff-cfae9141861b\": {\n          \"name\": \"Light\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3b0633a4-ac97-4d1f-861f-a9acb8653161\": {\n          \"name\": \"Water\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6993c5e7-f701-4994-b34f-c1404508513d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 86,\n          \"y\": 10,\n          \"width\": 180,\n          \"height\": 230,\n          \"scale\": 369,\n          \"focalX\": 50.01695907439964,\n          \"focalY\": 46.22446964354175,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"73bf1afa-a890-4a94-beb0-59081c84d03a\",\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-29T11:41:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page69_img1.jpg\",\n            \"width\": 330,\n            \"height\": 439,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo of Plants On White Pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dedee4\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 162,\n          \"y\": 195,\n          \"width\": 138,\n          \"height\": 105,\n          \"scale\": 123,\n          \"focalX\": 45.95715939368512,\n          \"focalY\": 43.34383436094533,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"24ffa1af-87c7-461d-97e0-318bf1ab8b1f\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page9_img2.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"id\": 0,\n            \"alt\": \"shallow focus photography of potted plants\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#beb1a4\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fcefab\\\">Once you've gotten the basics and foundation down, there's no limit to what you can build.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 303,\n          \"height\": 181,\n          \"id\": \"299fef66-21d1-473d-a135-034a6bf2b475\",\n          \"x\": 48,\n          \"y\": 331,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Look at other</span>\\n<span style=\\\"color: #fff\\\">stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 156,\n          \"height\": 65,\n          \"id\": \"10a539b3-dd5b-4d0e-8e3f-b68896fe53d3\",\n          \"x\": 203,\n          \"y\": 531,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 170,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"homeGardenFloral\" },\n          \"id\": \"edcea37c-78d8-406b-b501-2bcb1110a3e9\",\n          \"x\": 307,\n          \"y\": -92\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 50,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"homeGardenLightYellowArrow\" },\n          \"id\": \"ec6aa0ad-a013-445e-ae02-a19d4fde7f41\",\n          \"x\": 313,\n          \"y\": 575\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d285f24e-edb5-4d45-b5bd-13e2e8567dc6\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"10a539b3-dd5b-4d0e-8e3f-b68896fe53d3\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"d2a4dd34-3659-4f53-8f2a-c0f8b1e83fad\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ec6aa0ad-a013-445e-ae02-a19d4fde7f41\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 35, \"g\": 85, \"b\": 36 } },\n      \"type\": \"page\",\n      \"id\": \"493618e4-cd40-415e-8a53-3140875a239b\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6aa50920-2043-40ac-8ef0-8986981d87e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 47,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Other Stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 185,\n          \"height\": 103,\n          \"type\": \"text\",\n          \"id\": \"193e1f0a-dddd-4a12-954e-324a15c69ed5\",\n          \"x\": 48,\n          \"y\": 0,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 132,\n          \"width\": 155,\n          \"height\": 130,\n          \"scale\": 110,\n          \"focalX\": 53.3621664404912,\n          \"focalY\": 52.83886399378774,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"54133c92-9e73-43f3-a799-0e81098a9cbc\",\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page10_img1.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"id\": 0,\n            \"alt\": \"green vegetable\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1b443f\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"1805e4b6-f565-4e4b-8c82-583bf9db00d6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 253,\n          \"width\": 155,\n          \"height\": 10,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"78b2cf98-5e85-4ce9-b593-a4fe81e2db9a\",\n          \"groupId\": \"1805e4b6-f565-4e4b-8c82-583bf9db00d6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">10 tips</span>\\n<span style=\\\"font-weight: 700; color: #235524\\\">for growing lettuce</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 70,\n          \"type\": \"text\",\n          \"id\": \"00078d7f-9192-4398-a3a1-0b28517249d8\",\n          \"x\": 223,\n          \"y\": 130,\n          \"groupId\": \"1805e4b6-f565-4e4b-8c82-583bf9db00d6\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 155,\n          \"height\": 130,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"16bc3d6f-c9ac-464a-9e39-b1b3adca0786\",\n          \"x\": 48,\n          \"y\": 290,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page10_img2.jpg\",\n            \"width\": 320,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Person Holding Green Plant in Brown Pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#5e4833\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"151590ca-988a-4ee8-b308-749b0f6e247d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"type\": \"shape\",\n          \"width\": 155,\n          \"height\": 10,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8eb40fa0-0a10-4b69-8621-346219fed3a9\",\n          \"x\": 48,\n          \"y\": 410,\n          \"groupId\": \"151590ca-988a-4ee8-b308-749b0f6e247d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">Natural nutrients for house plants</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 70,\n          \"type\": \"text\",\n          \"id\": \"fcef8b1e-e7c0-44ba-a520-d8f12991ab96\",\n          \"x\": 223,\n          \"y\": 288,\n          \"groupId\": \"151590ca-988a-4ee8-b308-749b0f6e247d\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 155,\n          \"height\": 130,\n          \"scale\": 134,\n          \"focalX\": 49.91254065975694,\n          \"focalY\": 60.05868088457559,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"e5c8f7ce-0ea7-4c82-bce9-b6a5dd335de1\",\n          \"x\": 48,\n          \"y\": 446,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/indoor-garden-oasis/page10_img3.jpg\",\n            \"width\": 320,\n            \"height\": 213,\n            \"id\": 0,\n            \"alt\": \"plant in gray pot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e7e6e8\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"61b634c2-277f-4dc6-a85f-c5971260162b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n          \"type\": \"shape\",\n          \"width\": 155,\n          \"height\": 10,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f711df59-b953-4b58-89e2-f30296af74fe\",\n          \"x\": 48,\n          \"y\": 566,\n          \"groupId\": \"61b634c2-277f-4dc6-a85f-c5971260162b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"DM Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 500, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 992,\n              \"des\": -310,\n              \"tAsc\": 992,\n              \"tDes\": -310,\n              \"tLGap\": 0,\n              \"wAsc\": 992,\n              \"wDes\": 310,\n              \"xH\": 496,\n              \"capH\": 700,\n              \"yMin\": -261,\n              \"yMax\": 967,\n              \"hAsc\": 992,\n              \"hDes\": -310,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #235524\\\">How to strengthen</span>\\n<span style=\\\"font-weight: 700; color: #235524\\\">up your</span>\\n<span style=\\\"font-weight: 700; color: #235524\\\">plant game</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 92,\n          \"type\": \"text\",\n          \"id\": \"2b603ba6-8707-4d53-96a1-78b0f781bd10\",\n          \"x\": 223,\n          \"y\": 445,\n          \"groupId\": \"61b634c2-277f-4dc6-a85f-c5971260162b\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 276,\n          \"y\": -86,\n          \"width\": 170,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"homeGardenFloral\" },\n          \"id\": \"092ca1c1-fa0c-4b2f-aead-83f135d2aecf\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8b4cc0a1-958b-431c-a062-18b1ce3609ba\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"54133c92-9e73-43f3-a799-0e81098a9cbc\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f0a0b113-7ee4-44ca-9bdf-81576565c07d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"78b2cf98-5e85-4ce9-b593-a4fe81e2db9a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ebf260af-b057-4834-84eb-d0edd76b4282\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16bc3d6f-c9ac-464a-9e39-b1b3adca0786\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5c97f999-8911-4496-8ad2-90c5921ebae1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8eb40fa0-0a10-4b69-8621-346219fed3a9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"8a8f1efb-c453-4804-8c4d-610b2eb080f2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e5c8f7ce-0ea7-4c82-bce9-b6a5dd335de1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"71f6815a-4aa6-4003-9791-95c8b6abaf42\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f711df59-b953-4b58-89e2-f30296af74fe\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"7a520f7c-294a-4961-b3e1-499411d7b60a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"00078d7f-9192-4398-a3a1-0b28517249d8\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"51fe7899-4de5-421b-9901-88fe467fea79\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fcef8b1e-e7c0-44ba-a520-d8f12991ab96\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5c52122a-4e29-404d-9cb4-c08a874ea91c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2b603ba6-8707-4d53-96a1-78b0f781bd10\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 227, \"b\": 195 } },\n      \"type\": \"page\",\n      \"id\": \"441766b4-a0b8-496f-8ba1-25bbf645572c\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"1805e4b6-f565-4e4b-8c82-583bf9db00d6\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"151590ca-988a-4ee8-b308-749b0f6e247d\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"61b634c2-277f-4dc6-a85f-c5971260162b\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-makeover/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-makeover/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'kitchen-makeover',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Kitchen Makeover', 'template name', 'web-stories'),\n  tags: [\n    _x('Home & Garden', 'template keyword', 'web-stories'),\n    _x('Interior Design', 'template keyword', 'web-stories'),\n    _x('Interior Decoration', 'template keyword', 'web-stories'),\n    _x('Modern', 'template keyword', 'web-stories'),\n    _x('Brown', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Crater Brown', 'color', 'web-stories'),\n      color: '#44272b',\n      family: _x('Brown', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Flour White', 'color', 'web-stories'),\n      color: '#f3f3f1',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Frost Gray', 'color', 'web-stories'),\n      color: '#eeece5',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Quill Gray', 'color', 'web-stories'),\n      color: '#d7d6d2',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#ffffff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s gray color palette is the perfect neutral that goes well with everything. Use photos and videos to create contemporary as well as old-school interior design and home inspiration stories.',\n    'web-stories'\n  ),\n  vertical: _x('Home & Garden', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-makeover/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-makeover/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d13f5499-688b-4196-835f-7dd28dd7c8bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 214,\n          \"width\": 461,\n          \"height\": 461,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"a8b3704d-45b9-474a-ba49-d7adfac599cf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Kitchen Makeover Interior</span>\\n<span style=\\\"font-weight: 300; color: #44272b\\\">Decor with:</span>\\n<span style=\\\"color: #44272b\\\">Athene Calder</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 52,\n          \"width\": 316,\n          \"height\": 100,\n          \"id\": \"d3c75e42-8c60-4e48-ab1c-d06db485cd6b\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Ann Katowich</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 95,\n          \"height\": 22,\n          \"id\": \"fc61968e-d3aa-434f-9ca0-986356222fa7\",\n          \"x\": 48,\n          \"y\": 360\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 357,\n          \"width\": 15,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4897583c-59bf-4a34-85a5-e89dd3bb169b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 170,\n          \"height\": 308,\n          \"scale\": 170,\n          \"focalX\": 37.32043071100478,\n          \"focalY\": 43.3444053310398,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"897f1bd0-56c7-4aa1-a133-3b6dd335bdbc\",\n          \"x\": 240,\n          \"y\": 214,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:23:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page01_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 2400,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Blue ceramic dinnerware on rack\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e5e4e3\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 240,\n          \"height\": 270,\n          \"scale\": 120,\n          \"focalX\": 47.94498928241905,\n          \"focalY\": 47.951303154163725,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b2e89c85-d830-4faf-ba7e-8032c8486727\",\n          \"x\": 0,\n          \"y\": 406,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:25:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page01_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1281,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Four brown wooden chairs\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1bab5\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"d1e88875-a140-4f6e-a778-537641ac1638\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b618d207-7423-44f3-866b-ae59109ce231\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"type\": \"shape\",\n          \"x\": -313,\n          \"y\": 309,\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"84f09c6d-3ebd-4f6d-a93a-22dd1b3e0c4a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"video\",\n          \"width\": 383,\n          \"height\": 557,\n          \"scale\": 132,\n          \"focalX\": 59.83404577305309,\n          \"focalY\": 39.48527681315171,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"648358a9-6642-47bd-a930-a6c0240d7c37\",\n          \"x\": 29,\n          \"y\": -35,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-28T07:11:14\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page02_vid01.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page02_vid01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"alt\": \"Portrait Of A Woman Self Isolating At Home\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#887a73\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #44272b\\\">Athene Calder</span>\\n<span style=\\\"font-weight: 300\\\">of I-Swoon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 51,\n          \"id\": \"c74a9059-8f6c-4948-8f7c-0bd3cb381f6e\",\n          \"x\": 75,\n          \"y\": 544\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #44272b\\\">•</span><span style=\\\"font-weight: 300; color: #44272b\\\"> Designer, Decorator</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 191,\n          \"height\": 28,\n          \"id\": \"fb6d2745-771d-46c7-b57a-0512f39c2896\",\n          \"x\": 59,\n          \"y\": 607\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d8f38c1e-f5c5-4563-90e7-532747523367\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"84f09c6d-3ebd-4f6d-a93a-22dd1b3e0c4a\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 215, \"g\": 214, \"b\": 210 } },\n      \"type\": \"page\",\n      \"id\": \"74255039-175f-4b22-ae4d-2010eeb481a9\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"0933ae46-d909-474f-a94d-2a4a9ed9431d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 238, \"g\": 236, \"b\": 229 } },\n          \"type\": \"shape\",\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"4509a51a-6dc5-4881-bb26-839c1ac8f7fb\",\n          \"x\": -313,\n          \"y\": 309\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f3f3f1\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 49,\n          \"height\": 49,\n          \"id\": \"b2efed50-966e-4dcd-b5ae-8f036e491008\",\n          \"x\": 48,\n          \"y\": 14,\n          \"groupId\": \"912be636-5156-429f-9a56-d2b815dc91e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Modern Farmhouse I</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 51,\n          \"id\": \"e716c7d7-9da7-4675-bcbb-5c269d49def2\",\n          \"x\": 132,\n          \"y\": 16,\n          \"groupId\": \"912be636-5156-429f-9a56-d2b815dc91e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 110,\n          \"focalX\": 49.898721729679885,\n          \"focalY\": 52.53195675800284,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b69e01fd-0a6e-448e-a5ad-864696203ca2\",\n          \"x\": 46,\n          \"y\": 123,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:27:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page03_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown wooden rack\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cccecd\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 196,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"715ad185-c00f-4df1-9712-aa6bcdb9edf8\",\n          \"x\": 254,\n          \"y\": 169,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:27:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page03_image03.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Green Leafed Plants On Kitchen Island\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#cbcdcc\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 49.89107020869228,\n          \"focalY\": 44.724096000636116,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"497736d8-2239-4fad-b967-29274035de2d\",\n          \"x\": 46,\n          \"y\": 325,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:27:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page03_image02.jpg\",\n            \"width\": 1876,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Closeup photo of turned on iPad with rack on table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#beb8b2\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 130,\n          \"focalX\": 46.33190876742058,\n          \"focalY\": 54.59672192437167,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6fd40bcd-90da-4070-8d87-d751a14f23bd\",\n          \"x\": 254,\n          \"y\": 326,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-27T14:28:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page03_image04.jpg\",\n            \"width\": 1920,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Two clear glass jars on brown wooden floating shelf\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dcdad9\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"d1a7e1b9-fb50-439d-860e-371994771e4d\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"912be636-5156-429f-9a56-d2b815dc91e3\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f047374d-5b37-47a9-9c16-74b0bd2e6301\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 238, \"g\": 236, \"b\": 229 } },\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"0d846a3c-5235-4350-823d-ea695d16b640\",\n          \"x\": -416,\n          \"y\": -111,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f3f3f1\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 49,\n          \"height\": 48,\n          \"x\": 48,\n          \"y\": 14,\n          \"id\": \"6cbfc854-5e7a-43e0-a618-4ebd4cb5ee81\",\n          \"groupId\": \"15bead46-5056-413b-a0cb-4621c722c9da\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Modern Farmhouse II</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 51,\n          \"id\": \"26c6f04b-dcf6-44c2-8ba9-ee8643e46779\",\n          \"x\": 132,\n          \"y\": 16,\n          \"type\": \"text\",\n          \"groupId\": \"15bead46-5056-413b-a0cb-4621c722c9da\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 140,\n          \"focalX\": 24.577855257841495,\n          \"focalY\": 64.21644107221897,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c51dbf66-6784-4a08-b0a9-5d1ca00f5298\",\n          \"x\": 46,\n          \"y\": 169,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:22:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page04_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1284,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Grey pendant lamp with kitchen island\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfd2d6\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 214,\n          \"focalX\": 51.233213547220124,\n          \"focalY\": 49.92892359106439,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"be77f861-d492-4ba2-b537-cf93158fe3bd\",\n          \"x\": 208,\n          \"y\": 123,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:23:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page04_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1265,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Four brown stools\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3cbc4\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 240,\n          \"focalX\": 33.46779185581632,\n          \"focalY\": 65.24828581661892,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3bdcaac7-6144-46c2-b0a7-ccf3626e53fd\",\n          \"x\": 46,\n          \"y\": 327,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:23:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page04_image03.jpg\",\n            \"width\": 1920,\n            \"height\": 1281,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Chopping Boards Near Oven Under Hood\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cac2bc\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 330,\n          \"focalX\": 36.88833434067644,\n          \"focalY\": 83.66479277486994,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"980c698d-8dc7-4b05-a4ff-e8aa6a50e2de\",\n          \"x\": 254,\n          \"y\": 327,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:22:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page04_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1284,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Grey pendant lamp with kitchen island\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#d1d0ce\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ca28b0ef-696f-461b-b84a-8aee912e753f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0d846a3c-5235-4350-823d-ea695d16b640\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"62c5c755-6a79-4140-85f8-374e07cbc4ff\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"15bead46-5056-413b-a0cb-4621c722c9da\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b539828d-5c49-4b4c-9c86-4bc48acfeee2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 238, \"g\": 236, \"b\": 229 } },\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e944b25b-ef92-41b3-9e45-824f2e9f9ff7\",\n          \"x\": -26,\n          \"y\": 325,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f3f3f1\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 49,\n          \"height\": 48,\n          \"x\": 48,\n          \"y\": 14,\n          \"groupId\": \"35da833a-19f5-47ac-9641-603e73e3d361\",\n          \"id\": \"61ef8b7c-bc81-4538-ad74-6ba95fb49142\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Modern Farmhouse III</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 51,\n          \"id\": \"d6f5e716-84cf-4c5a-893f-053f387fa85f\",\n          \"x\": 132,\n          \"y\": 16,\n          \"type\": \"text\",\n          \"groupId\": \"35da833a-19f5-47ac-9641-603e73e3d361\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 120,\n          \"focalX\": 47.50254305380953,\n          \"focalY\": 57.984607247360245,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7cb95f84-d52c-4f87-814f-68c641ef7166\",\n          \"x\": 46,\n          \"y\": 123,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:27:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page05_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White and brown wooden kitchen cabinet\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c6c5c8\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 140,\n          \"focalX\": 48.42862296544557,\n          \"focalY\": 40.86440872451797,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"12f57da9-57fb-403e-a898-09933cfb8268\",\n          \"x\": 207,\n          \"y\": 123,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:27:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page05_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1279,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Ceramic Bowls on Brown Wooden Shelf\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c0b9b4\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 158,\n          \"height\": 154,\n          \"scale\": 400,\n          \"focalX\": 29.866991979751017,\n          \"focalY\": 60.99485599074943,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f3cd5d4c-c5d9-4ecc-be2e-dfa486dc30a3\",\n          \"x\": 46,\n          \"y\": 323,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:27:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page05_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White and brown wooden kitchen cabinet\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#c3c3c1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 204,\n          \"height\": 200,\n          \"scale\": 135,\n          \"focalX\": 50,\n          \"focalY\": 68.22136995395923,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a2550d26-5a9b-41dc-bf49-64b96b3fc71f\",\n          \"x\": 207,\n          \"y\": 325,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:28:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page05_image03.jpg\",\n            \"width\": 1581,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown wooden dining table with white chairs near kitchen\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d0d2d2\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"a24a18b4-68a3-4d02-aac2-f747a75a6c17\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"35da833a-19f5-47ac-9641-603e73e3d361\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"441d691f-71fc-4fda-bbe5-7eef2f42e657\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"x\": -119.5,\n          \"y\": 376,\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"ca51a66d-5cd1-4a86-a623-0deca0e5262e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"video\",\n          \"width\": 361,\n          \"height\": 658,\n          \"scale\": 105,\n          \"focalX\": 54.996844720429806,\n          \"focalY\": 50.08105379887199,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9997aa0e-4ba4-4a5f-ac2c-85d79090aa47\",\n          \"x\": 0,\n          \"y\": -28,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-28T07:13:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page06_vid01.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page06_vid01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 10,\n            \"lengthFormatted\": \"0:10\",\n            \"alt\": \"A Woman Instructor Giving On Line Yoga Exercise At Home\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#c8bba9\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"341e3e17-e096-479a-86ec-13780ede8cf1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ca51a66d-5cd1-4a86-a623-0deca0e5262e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 215, \"g\": 214, \"b\": 210 } },\n      \"type\": \"page\",\n      \"id\": \"38f4a398-b6e0-4b1a-bacd-40d7840d7fe4\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1a2e47b9-8ce0-47f7-ac09-6c2a3476176d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"x\": -167.5,\n          \"y\": 360,\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e68ba31e-52fc-44ca-8d4a-c29ca371a0e4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Before we had a rustic stove that we really wanted to keep but needed more room.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 87,\n          \"id\": \"d126bfa1-0cd1-4df7-b7df-79d01f0b7953\",\n          \"x\": 57,\n          \"y\": 16,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 357,\n          \"height\": 493,\n          \"scale\": 114,\n          \"focalX\": 46.390485999276834,\n          \"focalY\": 55.66018570591489,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9fbca181-3982-4b18-a97a-d875f9450f4d\",\n          \"x\": 0,\n          \"y\": 136,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:32:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page07_10_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1919,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Kitchen Room Design \",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b2afac\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 215, \"g\": 214, \"b\": 210 } },\n      \"type\": \"page\",\n      \"id\": \"af310d7b-7315-45de-9d2b-3a87556538f1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"7709c106-ccb4-4cb5-b7d2-1939deda4292\",\n          \"scale\": 100,\n          \"focalX\": 40.83680555555556,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-28T07:18:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page08_vid01.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page08_vid01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 7,\n            \"lengthFormatted\": \"0:07\",\n            \"alt\": \"Woman Standing in the Kitchen\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#c9c5ba\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a42e4322-a030-4ceb-b42a-63db1bf31a17\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"69ca0638-db76-4db3-a567-7c0692dd1e93\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d89b6ef3-054b-494f-b05d-004dc84ab3e9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"x\": -167.5,\n          \"y\": 360,\n          \"width\": 653,\n          \"height\": 653,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"2d59e91c-a372-48c2-9926-e81682393a1e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">At long last ... new shelves</span>\\n<span style=\\\"font-weight: 300; color: #44272b\\\">going in!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 60,\n          \"id\": \"a662bea9-4b74-48a9-b1ee-d56e9badda1b\",\n          \"x\": 57,\n          \"y\": 16,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 357,\n          \"height\": 493,\n          \"scale\": 200,\n          \"focalX\": 45.33712478517077,\n          \"focalY\": 70.33531690911636,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b23000d4-b2c0-434b-8ff5-86f3a4474fc0\",\n          \"x\": 0,\n          \"y\": 137,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:33:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page09_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Wooden Shelves With Kitchen Utensils\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cbc9cc\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8d0f8880-25d4-46b4-b659-526605edf26d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2d59e91c-a372-48c2-9926-e81682393a1e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 215, \"g\": 214, \"b\": 210 } },\n      \"type\": \"page\",\n      \"id\": \"7c5d7a91-0830-4670-8b16-43d2750ac7b1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a26d1598-169c-4603-a84a-b6f339337740\",\n          \"scale\": 105,\n          \"focalX\": 47.444513494318194,\n          \"focalY\": 54.54545454545454,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:32:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page07_10_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1919,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Kitchen Room Design \",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#c3c3c1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 7\n          },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Before</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 142,\n          \"height\": 61,\n          \"type\": \"text\",\n          \"id\": \"db6a956a-dfa5-4e8a-aeb5-021ea59b7094\",\n          \"x\": 37,\n          \"y\": 12\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"type\": \"shape\",\n          \"width\": 234,\n          \"height\": 117,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ab09e79f-870c-4372-a747-e91627794d07\",\n          \"x\": 37,\n          \"y\": 504\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Rustic, but definitely lacking in modern charm and space.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 180,\n          \"height\": 77,\n          \"type\": \"text\",\n          \"id\": \"1c7d25d7-127d-45d1-a6b5-3ca97db27426\",\n          \"x\": 63,\n          \"y\": 529\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d0a6bb96-3dca-453d-a5e4-245f59564c57\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"a26d1598-169c-4603-a84a-b6f339337740\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5a8b02a7-6b3e-4976-98a3-563b355744fe\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"161d812b-65f8-4a55-b53b-1078da989f58\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d234fc02-6faf-4c66-b267-208aa0078851\",\n          \"type\": \"image\",\n          \"scale\": 115,\n          \"focalX\": 62.09390096618359,\n          \"focalY\": 50.80887681159422,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:35:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page11_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White wooden kitchen cabinet with white wooden kitchen cabinet\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c9c3c3\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"width\": 234,\n          \"height\": 117,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d670df46-914b-4cc0-be75-888d69cf478f\",\n          \"x\": 37,\n          \"y\": 504,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">And there you have it. A modern farmhouse kitchen.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 189,\n          \"height\": 77,\n          \"id\": \"06d2fa6f-0519-4118-a2cf-411de755d280\",\n          \"x\": 58,\n          \"y\": 529,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 243, \"b\": 241 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 7\n          },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">After</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 117,\n          \"height\": 61,\n          \"type\": \"text\",\n          \"x\": 38,\n          \"y\": 12,\n          \"id\": \"bef4a0ca-bc85-4f8d-92fa-b344fc572ae6\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"60f8ea30-a969-4f10-b5b1-3ceb098494fd\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"decf0e89-7063-475a-bc44-328685ec2720\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b4f2589e-b3a8-4db9-8dd4-11df39331f0d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -150.5,\n          \"y\": -327,\n          \"width\": 461,\n          \"height\": 461,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"8e17e971-49f7-417b-9bab-e5a004835627\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 461,\n          \"height\": 461,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"id\": \"c0f4a2c8-706d-46ab-81ca-815aa916869c\",\n          \"x\": 100,\n          \"y\": 375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 47,\n          \"id\": \"147d337d-acb2-412f-9e82-dd93b90c5dd3\",\n          \"x\": 59,\n          \"y\": 26,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 137,\n          \"height\": 157,\n          \"scale\": 110,\n          \"focalX\": 39.93516805245057,\n          \"focalY\": 45.29112217227715,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dba2683d-752b-42b2-91d2-57747b4ccc18\",\n          \"x\": 59,\n          \"y\": 103,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:36:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page12_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1279,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Bedspread Beside Nightstand With White and Copper Table Lamp\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d6d8d8\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"727dee3b-555d-4049-927b-4914435302dd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Bedroom Makeover with Athene</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"id\": \"70a8342f-64c9-44c4-b907-586991aed329\",\n          \"x\": 213,\n          \"y\": 151,\n          \"groupId\": \"727dee3b-555d-4049-927b-4914435302dd\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"width\": 137,\n          \"height\": 157,\n          \"scale\": 100,\n          \"focalX\": 49.90268045591324,\n          \"focalY\": 59.00987597062672,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4eceaf60-868d-45e4-b4c0-697edb15fc84\",\n          \"x\": 213,\n          \"y\": 279,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:37:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page12_image02.jpg\",\n            \"width\": 1847,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White and brown chairs beside wicker basket near white wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e5e4e4\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"838758d7-af1c-4f38-9782-ac74102d6d46\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">Inspiration for a living room upgrade</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"id\": \"03239ccd-b74e-4175-8769-de9bab13c743\",\n          \"x\": 59,\n          \"y\": 325,\n          \"groupId\": \"838758d7-af1c-4f38-9782-ac74102d6d46\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 39, \"b\": 43 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-28T06:37:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-makeover/page12_image03.jpg\",\n            \"width\": 1816,\n            \"height\": 2560,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Shade Table Lamp Near Bed\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#dedddc\",\n            \"isExternal\": true\n          },\n          \"x\": 58,\n          \"y\": 449,\n          \"width\": 137,\n          \"height\": 157,\n          \"scale\": 109,\n          \"focalX\": 50.38319307038924,\n          \"focalY\": 37.34902157581301,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8ac1380f-739e-4a16-8ab1-78d4da62526c\",\n          \"groupId\": \"37150d31-d3c3-48ad-a9f5-ce2cac327a83\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Heebo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -862,\n              \"tAsc\": 2146,\n              \"tDes\": -862,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 862,\n              \"xH\": 1178,\n              \"capH\": 1456,\n              \"yMin\": -687,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -862,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #44272b\\\">How to get the lighting right</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 131,\n          \"height\": 45,\n          \"type\": \"text\",\n          \"id\": \"45e8c88c-df17-43e2-a914-925d82d23a6f\",\n          \"x\": 213,\n          \"y\": 507,\n          \"groupId\": \"37150d31-d3c3-48ad-a9f5-ce2cac327a83\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bf2a138a-acd7-4eb7-9487-336710ab58e0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8e17e971-49f7-417b-9bab-e5a004835627\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"897fe375-5e5c-4cd8-b990-4d793c2d0672\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c0f4a2c8-706d-46ab-81ca-815aa916869c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 215, \"g\": 214, \"b\": 210 } },\n      \"type\": \"page\",\n      \"id\": \"428ebaf6-b787-49c4-aca6-9cc616d4f00c\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"727dee3b-555d-4049-927b-4914435302dd\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"838758d7-af1c-4f38-9782-ac74102d6d46\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"37150d31-d3c3-48ad-a9f5-ce2cac327a83\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-stories/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-stories/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'kitchen-stories',\n  creationDate: '2021-06-28T00:00:00.000Z',\n  title: _x('Kitchen Stories', 'template name', 'web-stories'),\n  tags: [\n    _x('Cooking', 'template keyword', 'web-stories'),\n    _x('DIY', 'template keyword', 'web-stories'),\n    _x('Protein', 'template keyword', 'web-stories'),\n    _x('Homemade', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Mariner Blue', 'color', 'web-stories'),\n      color: '#d4e3fc',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Hawkes Blue', 'color', 'web-stories'),\n      color: '#215fce',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'The Kitchen Stories template puts the spotlight on you by keeping the text minimal and letting you tell your story through video. Increase your audience by linking your social profile and website at the end.',\n    'web-stories'\n  ),\n  vertical: _x('Cooking', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-stories/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/kitchen-stories/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -206,\n          \"y\": -423,\n          \"width\": 824,\n          \"height\": 1464,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"17b64623-dacf-4d03-9357-2e277b97e11c\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-10T13:12:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page01_bg.jpg\",\n            \"width\": 824,\n            \"height\": 1464,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page01_bg\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#292e39\",\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.3em; text-transform: uppercase\\\">Recipe For Beginners</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 89,\n          \"y\": 469,\n          \"width\": 234,\n          \"height\": 18,\n          \"id\": \"ebab2ec8-98de-4766-9aa1-79f21f942dbe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Crispy Chicken Thigh With Vegetables</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 25,\n          \"y\": 493,\n          \"width\": 363,\n          \"height\": 94,\n          \"id\": \"4f4d5944-8dee-471f-ad9c-6e81c9a03e3b\"\n        },\n        {\n          \"x\": 89,\n          \"y\": 603,\n          \"id\": \"78e7271d-a523-4873-9481-aeb7eaa6da91\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.3em; text-transform: uppercase\\\">By Jamie Leach</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 234,\n          \"height\": 18\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-20T10:23:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page01_logo.png\",\n            \"width\": 302,\n            \"height\": 162,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page01_logo\",\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 130.5,\n          \"y\": 0,\n          \"width\": 151,\n          \"height\": 81,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7fef7ce3-34c1-4536-acd0-a875de006c01\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"dafd5c10-3f8b-4476-bd6a-6bb1620addd3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e0ad34a8-c0a4-4888-853b-b708485b61d4\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 304,\n          \"height\": 540,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"0edc5b8b-a567-48c5-b988-e5b14d4cefc1\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:24:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page02_bg_video.mp4\",\n            \"width\": 304,\n            \"height\": 540,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page02_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 26,\n            \"lengthFormatted\": \"0:26\",\n            \"alt\": \"page02_bg_video\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"provider\": \"local\",\n            \"isMuted\": true,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page02_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page02_bg_video_subtitle.vtt\",\n              \"id\": \"3b3be6d7-994b-4400-8513-60d5461856e3\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ]\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 523,\n          \"width\": 412,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3ed1ff54-1eea-43bc-8c96-f199bfd35eb8\",\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"groupId\": \"638bc0e1-4220-4785-872a-fc71f8f953f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 95, \"b\": 206 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Dish Info</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 50,\n            \"topRight\": 50,\n            \"bottomRight\": 50,\n            \"bottomLeft\": 50\n          },\n          \"width\": 162,\n          \"height\": 42,\n          \"id\": \"2bf6d528-33ae-426e-bd76-5300df70e2a9\",\n          \"x\": 125,\n          \"y\": 502,\n          \"groupId\": \"638bc0e1-4220-4785-872a-fc71f8f953f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"type\": \"shape\",\n          \"x\": 144,\n          \"y\": 565,\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b0df6175-c872-4ca1-bbd0-0231d9670a90\"\n        },\n        {\n          \"x\": 20,\n          \"y\": 610,\n          \"id\": \"d78c6352-773b-4bcb-bea6-337f6985be73\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 114,\n          \"height\": 20,\n          \"groupId\": \"31efc009-9111-4424-bbcd-1938a742be61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">8</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 23,\n          \"height\": 53,\n          \"id\": \"688d8eaa-0fe1-422d-9421-d3cb19fabcf6\",\n          \"x\": 65,\n          \"y\": 557,\n          \"groupId\": \"31efc009-9111-4424-bbcd-1938a742be61\"\n        },\n        {\n          \"x\": 169,\n          \"y\": 610,\n          \"id\": \"2e08ccc8-cd8d-4cb6-a0f9-1d81ed351599\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Calories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 82,\n          \"height\": 20,\n          \"groupId\": \"4977409e-cabf-4ac8-8e63-0822c7f14378\"\n        },\n        {\n          \"x\": 177,\n          \"y\": 557,\n          \"id\": \"9e928779-97a5-44b3-8685-b360c02fac1a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce; letter-spacing: 0.06em\\\">624</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 67,\n          \"height\": 53,\n          \"groupId\": \"4977409e-cabf-4ac8-8e63-0822c7f14378\"\n        },\n        {\n          \"x\": 269,\n          \"y\": 565,\n          \"id\": \"bdc66397-bac8-4278-a567-cebca8c41cc0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 303,\n          \"y\": 610,\n          \"id\": \"6392a731-c499-43a6-9202-da0281eb36c1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Minutes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 74,\n          \"height\": 20,\n          \"groupId\": \"0211b650-6f32-4b4f-924e-d73057472020\"\n        },\n        {\n          \"x\": 318,\n          \"y\": 557,\n          \"id\": \"d5ef1659-f247-4c7e-b840-7075306efb88\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce; letter-spacing: 0.06em\\\">45</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 44,\n          \"height\": 53,\n          \"groupId\": \"0211b650-6f32-4b4f-924e-d73057472020\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"40c84d05-2e0b-4a6b-bfc4-f1311cded47e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3ed1ff54-1eea-43bc-8c96-f199bfd35eb8\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"25aa0f02-3eec-4875-a35a-b46ddfb450b4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"688d8eaa-0fe1-422d-9421-d3cb19fabcf6\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d89b70b0-4d17-4ca9-b730-9826ababad28\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9e928779-97a5-44b3-8685-b360c02fac1a\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ec3b41c7-98fc-48c1-a3b9-9f3d25599253\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d5ef1659-f247-4c7e-b840-7075306efb88\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d2e78446-975d-4045-81cf-bbd213a09c7f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d78c6352-773b-4bcb-bea6-337f6985be73\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"61864e95-abb7-4b73-883e-62910b8f5d29\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2e08ccc8-cd8d-4cb6-a0f9-1d81ed351599\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"5818884f-18ca-4a35-a63d-269037a9282e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6392a731-c499-43a6-9202-da0281eb36c1\"],\n          \"duration\": 1000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"58dc6258-25bb-4a35-bcfe-9ab085ecd175\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b0df6175-c872-4ca1-bbd0-0231d9670a90\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"71456342-6c15-4065-a5a8-aa2e4d7e678b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bdc66397-bac8-4278-a567-cebca8c41cc0\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8872a70b-a576-4500-b450-1f8416e8951a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1da63b04-9fdb-4b94-b4bd-71b3b89578a9\"\n      },\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"638bc0e1-4220-4785-872a-fc71f8f953f8\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"31efc009-9111-4424-bbcd-1938a742be61\": {\n          \"name\": \"Ingredients\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4977409e-cabf-4ac8-8e63-0822c7f14378\": {\n          \"name\": \"Calories\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0211b650-6f32-4b4f-924e-d73057472020\": {\n          \"name\": \"Minutes\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4f10fb5a-c6fc-4dcf-b8a3-a272f589c368\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:37:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page03_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 958,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page03_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 11,\n            \"lengthFormatted\": \"0:11\",\n            \"alt\": \"page03_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#a88582\"\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"9f8d380f-ba21-4359-b1cf-67e8f93f4a53\",\n          \"x\": 0,\n          \"y\": 523,\n          \"groupId\": \"3a518b12-7c8e-44d9-8433-5eec24e2c0ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 95, \"b\": 206 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 50,\n            \"topRight\": 50,\n            \"bottomRight\": 50,\n            \"bottomLeft\": 50\n          },\n          \"width\": 162,\n          \"height\": 42,\n          \"x\": 125,\n          \"y\": 502,\n          \"id\": \"84e6d6ba-4926-4c98-8035-3f9e6224b608\",\n          \"groupId\": \"3a518b12-7c8e-44d9-8433-5eec24e2c0ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"x\": 101,\n          \"y\": 569,\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"868e3296-caf9-40fc-9af9-1496df730d65\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 22,\n          \"y\": 597,\n          \"id\": \"e43ec6dc-a72f-4778-ab06-5b58e3b67acd\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Red Potato</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 68,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"groupId\": \"97c05d8e-50ce-46f8-8405-0a2bcc31ae7d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 43,\n          \"id\": \"8b8d5d32-f8ae-409b-8eb0-8840772d24e8\",\n          \"x\": 21,\n          \"y\": 555,\n          \"type\": \"text\",\n          \"groupId\": \"97c05d8e-50ce-46f8-8405-0a2bcc31ae7d\"\n        },\n        {\n          \"x\": 45,\n          \"y\": 566,\n          \"id\": \"640cd251-a5f1-4920-82b6-59b23da90e03\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #215fce\\\">lb</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 26,\n          \"type\": \"text\",\n          \"groupId\": \"97c05d8e-50ce-46f8-8405-0a2bcc31ae7d\"\n        },\n        {\n          \"x\": 124,\n          \"y\": 555,\n          \"id\": \"313018be-de2a-4b12-8d0b-9c879110d45d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"groupId\": \"082578ef-77b0-438e-8611-51797fe2659c\"\n        },\n        {\n          \"x\": 149,\n          \"y\": 566,\n          \"id\": \"ee6ed327-647b-4515-a8f2-714208a45265\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #215fce\\\">lb</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 26,\n          \"type\": \"text\",\n          \"groupId\": \"082578ef-77b0-438e-8611-51797fe2659c\"\n        },\n        {\n          \"x\": 125,\n          \"y\": 597,\n          \"id\": \"d7d989ff-6659-4f75-bdc6-d7566ba0ef19\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Green Beans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 55,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"groupId\": \"082578ef-77b0-438e-8611-51797fe2659c\"\n        },\n        {\n          \"x\": 198,\n          \"y\": 569,\n          \"id\": \"cd92a965-9cce-420f-8429-c99f108788a7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"x\": 301,\n          \"y\": 569,\n          \"id\": \"bf66e3b6-d398-4817-8595-7edbe40bef8e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"x\": 228,\n          \"y\": 597,\n          \"id\": \"f243930d-9b42-49dc-8d0f-8dcff1dfa906\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Fresh Lemon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 57,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"groupId\": \"b7bf5d7a-f96a-4a3b-bb5f-77bad2a22b56\"\n        },\n        {\n          \"x\": 227,\n          \"y\": 555,\n          \"id\": \"4f281cb2-bc89-416c-908a-84421a82a482\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"groupId\": \"b7bf5d7a-f96a-4a3b-bb5f-77bad2a22b56\"\n        },\n        {\n          \"x\": 317,\n          \"y\": 597,\n          \"id\": \"7636d707-3247-4c58-a5b5-7b69de5aab02\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Cloves Garlic</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 68,\n          \"height\": 39,\n          \"type\": \"text\",\n          \"groupId\": \"c7dad8ad-bf3d-495e-a8c0-7db915f6501c\"\n        },\n        {\n          \"x\": 317,\n          \"y\": 555,\n          \"id\": \"79f0484a-a883-4b15-91cb-2591c2e82023\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">3 - 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 60,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"groupId\": \"c7dad8ad-bf3d-495e-a8c0-7db915f6501c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"9f8d380f-ba21-4359-b1cf-67e8f93f4a53\"],\n          \"id\": \"51c53422-cd9a-4a38-a6a6-c047f1e883a8\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ff432ee3-9f6d-4a82-a967-0bb3b226872d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8b8d5d32-f8ae-409b-8eb0-8840772d24e8\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b86e7141-bda0-4725-9a77-7e1d5fa43d00\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"313018be-de2a-4b12-8d0b-9c879110d45d\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"199ca73d-f169-4b4c-8291-cda52584d7c8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4f281cb2-bc89-416c-908a-84421a82a482\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"02f29a4d-1ca9-4756-b9fd-2eec41050b13\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"79f0484a-a883-4b15-91cb-2591c2e82023\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8e7bdca6-9a35-4f3e-be8b-ce86348148a4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"640cd251-a5f1-4920-82b6-59b23da90e03\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"753ea96d-44a9-4da4-9bc7-6ca41a613222\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ee6ed327-647b-4515-a8f2-714208a45265\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c6d2d3be-abb9-418e-a4e7-8013dd6c82d0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e43ec6dc-a72f-4778-ab06-5b58e3b67acd\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"8290d5b4-1621-4bd2-8fcf-0290838f3466\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d7d989ff-6659-4f75-bdc6-d7566ba0ef19\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"8036cde0-09db-45ad-b132-f3ee18c3006e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f243930d-9b42-49dc-8d0f-8dcff1dfa906\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"174d9b05-614c-4d6c-81e0-3c39ec932cfc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7636d707-3247-4c58-a5b5-7b69de5aab02\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"b45558fc-8ded-4dd7-940b-c754831afa86\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"868e3296-caf9-40fc-9af9-1496df730d65\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fb4dacce-8d54-4a6b-897e-0425d9b8398b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cd92a965-9cce-420f-8429-c99f108788a7\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"73a31b20-79c0-4c5e-a863-3f335fd7dd55\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bf66e3b6-d398-4817-8595-7edbe40bef8e\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ef9955a0-3031-4cb5-9d98-c5e59fb26ed5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"cfccb851-db11-4633-8cbb-acfee2e393a2\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"3a518b12-7c8e-44d9-8433-5eec24e2c0ef\": {\n          \"name\": \"Section\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"c7dad8ad-bf3d-495e-a8c0-7db915f6501c\": {\n          \"name\": \"Garlic\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b7bf5d7a-f96a-4a3b-bb5f-77bad2a22b56\": {\n          \"name\": \"Lemon\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"082578ef-77b0-438e-8611-51797fe2659c\": {\n          \"name\": \"Bean\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"97c05d8e-50ce-46f8-8405-0a2bcc31ae7d\": {\n          \"name\": \"Potato\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"54fbae0a-704f-40a7-b0fa-03d80b6ab550\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:38:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page04_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 886,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page04_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"page04_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#b5afac\"\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"d58b9350-fcf1-48e7-a42b-4c0a1bee0efc\",\n          \"x\": 0,\n          \"y\": 523,\n          \"groupId\": \"9da33eb2-6e4c-43f7-8fc2-44f00e1981d1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 95, \"b\": 206 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 50,\n            \"topRight\": 50,\n            \"bottomRight\": 50,\n            \"bottomLeft\": 50\n          },\n          \"width\": 162,\n          \"height\": 42,\n          \"x\": 125,\n          \"y\": 502,\n          \"groupId\": \"9da33eb2-6e4c-43f7-8fc2-44f00e1981d1\",\n          \"id\": \"0f1758c9-40ae-4d1c-b070-d0245d7e3412\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"e6a713ca-bfa2-4dfd-a361-7076efc874eb\",\n          \"x\": 211,\n          \"y\": 569\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Chicken Thighs (Bone-In, Skin-On)</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 182,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"id\": \"8c84d348-91b0-4662-8ab9-126d85517ee6\",\n          \"x\": 21,\n          \"y\": 597,\n          \"groupId\": \"21bc3c21-aa6c-41d6-b620-cd34aeac35a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"id\": \"a0292b07-938a-4e79-916a-1b6a39c84611\",\n          \"x\": 21,\n          \"y\": 555,\n          \"groupId\": \"21bc3c21-aa6c-41d6-b620-cd34aeac35a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #215fce\\\">lb</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 20,\n          \"height\": 26,\n          \"type\": \"text\",\n          \"id\": \"fe794fbb-3c47-42a6-81c7-959a1d0f1833\",\n          \"x\": 42,\n          \"y\": 566,\n          \"groupId\": \"21bc3c21-aa6c-41d6-b620-cd34aeac35a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">To Taste</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 111,\n          \"height\": 43,\n          \"type\": \"text\",\n          \"id\": \"b8219ef6-7c04-46d5-99e4-132c601e72cf\",\n          \"x\": 246,\n          \"y\": 555,\n          \"groupId\": \"283b6814-35b8-4dfd-a7b3-7202768aaf3c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Salt, Pepper, Gochujang</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 127,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"id\": \"22d4b2bb-c214-48bb-9304-d3e2bb0cd574\",\n          \"x\": 246,\n          \"y\": 597,\n          \"groupId\": \"283b6814-35b8-4dfd-a7b3-7202768aaf3c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"d58b9350-fcf1-48e7-a42b-4c0a1bee0efc\"],\n          \"id\": \"b41b381e-ee2c-4415-a0bc-53e0a1d1fb1a\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"66490e05-641e-469e-9d37-d48cb22ae7a5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8c84d348-91b0-4662-8ab9-126d85517ee6\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"8b2612f7-c07c-4942-9d4c-44d42969fa62\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"22d4b2bb-c214-48bb-9304-d3e2bb0cd574\"],\n          \"duration\": 1000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"c76217ab-d5b8-47dd-9995-321c4349958d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a0292b07-938a-4e79-916a-1b6a39c84611\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6de8b592-ac5c-48a4-83fd-39c105599e84\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fe794fbb-3c47-42a6-81c7-959a1d0f1833\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7fefd3c0-bf92-4276-9fed-057f18d8cfc5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b8219ef6-7c04-46d5-99e4-132c601e72cf\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1f8c5638-ccdb-41fc-bed6-85c36adcc663\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e6a713ca-bfa2-4dfd-a361-7076efc874eb\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9e4f06a3-8570-4fa9-aae8-a317dc3904b5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"984e182e-601a-4a25-add2-de86f32f4da1\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9da33eb2-6e4c-43f7-8fc2-44f00e1981d1\": {\n          \"name\": \"Section\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"21bc3c21-aa6c-41d6-b620-cd34aeac35a5\": {\n          \"name\": \"Chicken\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"283b6814-35b8-4dfd-a7b3-7202768aaf3c\": {\n          \"name\": \"Taste\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"02397bf8-1926-4636-8039-b5c556866917\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 173,\n          \"y\": 261,\n          \"width\": 66,\n          \"height\": 65,\n          \"sticker\": { \"type\": \"oven\" },\n          \"id\": \"ff7752e9-2b63-4cab-a40e-19fb3900a7ca\",\n          \"groupId\": \"44f6a675-b3a2-4104-949f-6ed1b9531019\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 341,\n          \"id\": \"88c02233-a617-4708-9e12-081919794aed\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.16,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">Preheat a cast iron skillet in the oven to 425°F</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 318,\n          \"height\": 60,\n          \"groupId\": \"44f6a675-b3a2-4104-949f-6ed1b9531019\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 164,\n          \"y\": 85,\n          \"width\": 86,\n          \"height\": 72,\n          \"sticker\": { \"type\": \"potatoes\" },\n          \"id\": \"083cb159-2665-47df-ba89-7bce08de9d9b\",\n          \"groupId\": \"ea01336d-49c4-4eba-9823-0e5c7a96b4ab\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">Wash the vegetables</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 32,\n          \"id\": \"d9e02efb-411c-4e80-8c30-4eb9afeeb3ce\",\n          \"x\": 91.5,\n          \"y\": 169,\n          \"groupId\": \"ea01336d-49c4-4eba-9823-0e5c7a96b4ab\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase\\\">Pre-Preparation</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 234,\n          \"height\": 20,\n          \"id\": \"f5d43adb-c7de-45a8-a2cc-20720161643d\",\n          \"x\": 89,\n          \"y\": 8\n        },\n        {\n          \"x\": 47,\n          \"y\": 546,\n          \"id\": \"568da739-c0b4-4277-8430-04e8daa141ba\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.16,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce\\\">Add oil to the skillet before cooking the chicken</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 318,\n          \"height\": 60,\n          \"groupId\": \"3b0b775c-1024-47f7-be3f-eaf2f754a414\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 78,\n          \"height\": 76,\n          \"sticker\": { \"type\": \"castIron\" },\n          \"id\": \"bef0da7c-6f94-4a1d-8adf-323b90d1a7b9\",\n          \"x\": 171,\n          \"y\": 455,\n          \"groupId\": \"3b0b775c-1024-47f7-be3f-eaf2f754a414\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 227, \"b\": 252 } },\n      \"type\": \"page\",\n      \"id\": \"dc934228-1e50-41fc-af25-b1a2d4321d46\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"ea01336d-49c4-4eba-9823-0e5c7a96b4ab\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"44f6a675-b3a2-4104-949f-6ed1b9531019\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3b0b775c-1024-47f7-be3f-eaf2f754a414\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"d2c9d996-96a1-4b2c-a02d-644bcf5bb585\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:40:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page06_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1040,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page06_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 43,\n            \"lengthFormatted\": \"0:43\",\n            \"alt\": \"page06_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#c1b4a8\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page06_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page06_bg_video_subtitle.vtt\",\n              \"id\": \"b49a71c4-99a3-444b-b9b3-45fe19ce0abe\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.48 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"id\": \"7f47519a-c35e-4489-8e8c-2992beab67a4\",\n          \"x\": 146,\n          \"y\": -3\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Prep the chicken</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 35,\n          \"id\": \"9f193540-3d0d-4cf9-b30d-8e82939aeb40\",\n          \"x\": 91.5,\n          \"y\": 19\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"17f46ebe-2fda-41f4-adda-51af45a3bc6d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"813eb70f-efb3-446a-aa11-5b27e7efe980\"\n      },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"90616074-948f-45ee-978a-b068c12be53b\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:40:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page07_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1052,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page07_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 22,\n            \"lengthFormatted\": \"0:22\",\n            \"alt\": \"page07_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#cfc0ad\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page07_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page07_bg_video_subtitle.vtt\",\n              \"id\": \"482eae12-a620-4851-8dfb-3dddb9e84653\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.52 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"id\": \"a76107dc-def8-4687-b646-1b9f859cc4aa\",\n          \"x\": 146,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Prep the veggies</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 35,\n          \"id\": \"034c9bb8-af6a-4d73-88a1-509598209d36\",\n          \"x\": 92,\n          \"y\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"48af2b80-73c6-488f-ba7d-090d71171fd5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"abc02b45-c348-4ad0-93c3-d62728b1e3bf\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"5653408f-8f4e-4451-8e65-80a45f060729\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:42:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page08_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1080,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page08_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 35,\n            \"lengthFormatted\": \"0:35\",\n            \"alt\": \"page08_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#c6ced1\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page08_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page08_bg_video_subtitle.vtt\",\n              \"id\": \"0cb93880-3435-4c62-a70d-8d767bb31c39\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.52 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"id\": \"19bc9c9d-184e-4c8d-84e9-ed726823ab69\",\n          \"x\": 146,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Cook the chicken</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 34,\n          \"id\": \"f7d1cdca-c3f3-4e2b-8382-2c399cf841dd\",\n          \"x\": 91.5,\n          \"y\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2db4bcb3-8491-4b28-8972-21c5032613af\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"faa06289-1ab3-49f2-bbbe-6adf3ba9deba\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"54270e2b-1006-4fbc-8387-2cea5fb67e46\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:54:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page09_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1080,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page09_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 57,\n            \"lengthFormatted\": \"0:57\",\n            \"alt\": \"page09_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#cdb08f\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page09_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page09_bg_video_subtitle.vtt\",\n              \"id\": \"201b67b8-6f11-4c9a-a694-09bc73a2130e\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.49 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"id\": \"50a86785-9c0a-4e37-8181-40e989b1e7d3\",\n          \"x\": 146,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Add the potatoes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 35,\n          \"id\": \"71b066d8-7f15-46af-8efd-2a7515fdead4\",\n          \"x\": 92,\n          \"y\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5f3d3dae-b24d-4eb9-89e1-c819142177c7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"aceb7b5a-e2a8-43ce-b0d0-9231d04c32d5\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"5cdfc722-3231-4c35-8de3-0dc813883952\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:54:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page10_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1080,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page10_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 55,\n            \"lengthFormatted\": \"0:55\",\n            \"alt\": \"page10_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#0f0d0e\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page010_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page010_bg_video_subtitle.vtt\",\n              \"id\": \"f655fe38-9dac-47d4-8d0a-26a8a0d7713e\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.52 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"id\": \"bddd6320-52c7-490f-8469-c9378f663b8f\",\n          \"x\": 146,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Add the beans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 35,\n          \"id\": \"e2d64143-9607-4e62-8dce-c394ec3d38e0\",\n          \"x\": 92,\n          \"y\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7a1236ce-eeb5-468b-94ff-63491ddea1f8\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ab1771cd-eb71-43b1-ab77-4e5dddba90d7\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"52bac944-215a-4df7-a193-d358702a4bdd\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:53:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page11_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1044,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page11_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 37,\n            \"lengthFormatted\": \"0:37\",\n            \"alt\": \"page11_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true,\n            \"baseColor\": \"#c9b9a9\"\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page011_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page011_bg_video_subtitle.vtt\",\n              \"id\": \"6d53fbc4-2eb6-4a07-b3e1-3a3eebadaa86\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.54 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.24em; text-transform: uppercase\\\">Step 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 120,\n          \"height\": 19,\n          \"id\": \"3d1a9647-44d3-47c7-af32-d47b62c02ebc\",\n          \"x\": 146,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Toss the beans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 229,\n          \"height\": 35,\n          \"id\": \"77f9f48c-0113-4fcc-b57b-510c55562362\",\n          \"x\": 92,\n          \"y\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a7682eaa-dfda-4142-b7f1-1ee36f528f62\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"2a1e95e2-ba80-4e73-987b-e26a99ef9f3f\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -98,\n          \"y\": -51,\n          \"width\": 608,\n          \"height\": 720,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"51914ccd-eb44-4235-a92c-d5998ef398db\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-10T12:51:22\",\n            \"baseColor\": \"#c5bbab\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page12_bg_video.mp4\",\n            \"width\": 608,\n            \"height\": 1038,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page12_bg_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 11,\n            \"lengthFormatted\": \"0:11\",\n            \"alt\": \"page12_bg_video\",\n            \"sizes\": [],\n            \"isMuted\": false,\n            \"isOptimized\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [\n            {\n              \"track\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page012_bg_video_subtitle.vtt\",\n              \"trackId\": 0,\n              \"trackName\": \"page012_bg_video_subtitle.vtt\",\n              \"id\": \"d49aeba0-c1ef-4675-a57a-957ae12b76e9\",\n              \"kind\": \"captions\",\n              \"srclang\": \"\",\n              \"label\": \"\"\n            }\n          ]\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"bca484e3-90eb-43d8-a41a-31920df37c8f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"53c31bf9-8bea-4a71-a6b2-6dcacb2bef36\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d549d391-16d9-404e-ba3d-3ec8825e9602\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-04-20T12:25:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page14_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page14_bg\",\n            \"baseColor\": \"#255dcb\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f38a761e-bc6e-430c-8441-457ba9c1ac79\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.29,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Jamie’s </span><span style=\\\"color: #fff\\\">style is Californian since the technique is rooted in traditional French cooking, but the flavors are inspired by Latin and Asian food and locally sourced ingredients.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 53,\n          \"y\": 18,\n          \"width\": 314,\n          \"height\": 111,\n          \"id\": \"74485bad-69e4-4a1e-9afa-916819fa3160\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 155,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"type\": \"shape\",\n          \"id\": \"edf1cf50-5dd4-4fd2-bf23-2954408c2021\",\n          \"x\": 0,\n          \"y\": 523,\n          \"groupId\": \"158c36cc-9c80-45b1-925c-c9f283d65c0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 227, \"b\": 252 } },\n          \"lineHeight\": 1.36,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 12\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #215fce; letter-spacing: 0.24em; text-transform: uppercase\\\">More Info</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 50,\n            \"topRight\": 50,\n            \"bottomRight\": 50,\n            \"bottomLeft\": 50\n          },\n          \"width\": 162,\n          \"height\": 42,\n          \"x\": 124,\n          \"y\": 501,\n          \"groupId\": \"158c36cc-9c80-45b1-925c-c9f283d65c0a\",\n          \"id\": \"54b64192-07f5-4893-aaa3-ba2f35a94219\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 227, \"b\": 252 } },\n          \"width\": 1,\n          \"height\": 63,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"78ad5ffc-0c41-41d5-93c4-b5c2ec9438c0\",\n          \"x\": 205.5,\n          \"y\": 569\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 15\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em\\\">Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 71,\n          \"height\": 50,\n          \"type\": \"text\",\n          \"id\": \"619b94cd-0a00-4098-8f77-11f505568453\",\n          \"x\": 288,\n          \"y\": 589,\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": \"Google\"\n          },\n          \"groupId\": \"a63a8cc1-3617-49d8-8a4a-a38908f2c7f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 227, \"b\": 252 } },\n          \"type\": \"shape\",\n          \"x\": 299,\n          \"y\": 549,\n          \"width\": 48,\n          \"height\": 48,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cfb78a1f-2c9e-4813-be4e-9dd4cabdb9e7\",\n          \"borderRadius\": {\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 2,\n            \"right\": 2,\n            \"top\": 2,\n            \"bottom\": 2,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 38, \"g\": 94, \"b\": 205 } }\n          },\n          \"link\": {\n            \"url\": \"https://www.google.com/\",\n            \"icon\": null,\n            \"desc\": null\n          },\n          \"groupId\": \"a63a8cc1-3617-49d8-8a4a-a38908f2c7f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 306,\n          \"y\": 562,\n          \"width\": 34,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"hotDish\" },\n          \"id\": \"ed35c3f9-507f-4e48-9968-575ce6441035\",\n          \"groupId\": \"a63a8cc1-3617-49d8-8a4a-a38908f2c7f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 74,\n          \"y\": 549,\n          \"width\": 48,\n          \"height\": 48,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a13e1945-ddbc-4cbf-a3b8-4656145d3429\",\n          \"borderRadius\": {\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 2,\n            \"right\": 2,\n            \"top\": 2,\n            \"bottom\": 2,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 38, \"g\": 94, \"b\": 205 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-04-20T06:39:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/kitchen-stories/page14_profileimage.jpg\",\n            \"width\": 46,\n            \"height\": 46,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page14_profileimage\",\n            \"sizes\": [],\n            \"baseColor\": \"#c2c2c2\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"00cfa981-a3f5-476e-8545-8d1d7c5a1c9c\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 589,\n          \"id\": \"80b32681-e900-4008-aa8f-08a27c1b344d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"lineHeight\": 1.32,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 15\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em\\\">Jamiekleach</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 115,\n          \"height\": 50,\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://stories.google/\",\n            \"icon\": \"https://lh3.googleusercontent.com/jkRCEaBKzyVNijg12zycgjObWmQucwktNiscALqOZp5GL-0ZFG-I3AENfYXpHr8h_jrjng1sGbbrfX63O_Yg7-YToMejArZVUki8zw\",\n            \"desc\": \"Web Stories on Google\"\n          },\n          \"groupId\": \"00cfa981-a3f5-476e-8545-8d1d7c5a1c9c\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"15394bb1-c0aa-4a29-a312-5394be11be6f\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"158c36cc-9c80-45b1-925c-c9f283d65c0a\": {\n          \"name\": \"Section\",\n          \"isLocked\": true,\n          \"isCollapsed\": false\n        },\n        \"00cfa981-a3f5-476e-8545-8d1d7c5a1c9c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a63a8cc1-3617-49d8-8a4a-a38908f2c7f3\": {\n          \"name\": \"Site\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/laptop-buying-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/laptop-buying-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'laptop-buying-guide',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Laptop Buying Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Products', 'template keyword', 'web-stories'),\n    _x('Laptop', 'template keyword', 'web-stories'),\n    _x('Simple', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Brilliant Blue', 'color', 'web-stories'),\n      color: '#0057ff',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gentle Gray', 'color', 'web-stories'),\n      color: '#c4c4c4',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mineshaft Black', 'color', 'web-stories'),\n      color: '#3d3d3d',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s clean design and structure will let you create uncomplicated long-form product reviews, comparisons and more. Adapt it to your style by changing the colors.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/laptop-buying-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/laptop-buying-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"aaaba7a6-7fe9-4df6-a97b-9c1416c9d472\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e3747b1b-f148-4e8f-9eb0-689a6eee8098\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 61,\n          \"width\": 317,\n          \"height\": 317,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"519657d8-7d6d-4e93-aaf3-73be9fb3a9b5\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } }\n          },\n          \"borderRadius\": {\n            \"topLeft\": 8,\n            \"topRight\": 8,\n            \"bottomRight\": 8,\n            \"bottomLeft\": 8,\n            \"locked\": true\n          },\n          \"groupId\": \"9cec2110-856a-4b49-8046-7443dd3762fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 317,\n          \"height\": 317,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } }\n          },\n          \"borderRadius\": {\n            \"topLeft\": 8,\n            \"topRight\": 8,\n            \"bottomRight\": 8,\n            \"bottomLeft\": 8,\n            \"locked\": true\n          },\n          \"id\": \"d608d1c1-5b34-4bf0-aa42-22e09f9a5d31\",\n          \"x\": 379,\n          \"y\": 25,\n          \"groupId\": \"9cec2110-856a-4b49-8046-7443dd3762fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 317,\n          \"height\": 317,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } }\n          },\n          \"borderRadius\": {\n            \"topLeft\": 8,\n            \"topRight\": 8,\n            \"bottomRight\": 8,\n            \"bottomLeft\": 8,\n            \"locked\": true\n          },\n          \"id\": \"ff0031c3-fedd-4506-b443-401a8cb59c45\",\n          \"x\": -286,\n          \"y\": 96,\n          \"groupId\": \"9cec2110-856a-4b49-8046-7443dd3762fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page01_04_14_image01.png\",\n            \"width\": 1920,\n            \"height\": 1329,\n            \"id\": 0,\n            \"alt\": \"Macbook pro 16 inch mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#040404\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 13,\n          \"y\": 80,\n          \"width\": 392,\n          \"height\": 270,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8ea78e0d-d479-4079-96a0-980e10930b0e\",\n          \"groupId\": \"9cec2110-856a-4b49-8046-7443dd3762fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-31T07:41:44\",\n            \"baseColor\": \"#090909\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page01_image02.png\",\n            \"width\": 61,\n            \"height\": 74,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Pointer hand icon\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 317,\n          \"y\": 359,\n          \"width\": 30,\n          \"height\": 36,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b828e719-9522-422e-9bf8-0582e922f76f\",\n          \"groupId\": \"9cec2110-856a-4b49-8046-7443dd3762fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2f2f2f; letter-spacing: 0.1em; text-transform: uppercase\\\">Sylvia Tribel</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 139,\n          \"y\": 443,\n          \"width\": 134,\n          \"height\": 17,\n          \"id\": \"77148140-9bce-4227-9459-037099c7ba4e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Pick the right laptop for your creative needs</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 77,\n          \"y\": 474,\n          \"width\": 258,\n          \"height\": 127,\n          \"id\": \"051de424-1038-46a1-aba8-b2da9e81736a\",\n          \"tagName\": \"h1\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1cc6d76a-3b98-40d7-958f-7bab37485254\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"9cec2110-856a-4b49-8046-7443dd3762fd\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7edff1f8-bf91-49bf-9d20-7c8606bcb57c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page02_image01.jpg\",\n            \"width\": 1695,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Man tapping on laptop computer\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#141417\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 412,\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50.875806051587304,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"080fde21-44bf-4560-8b9c-0ffd598df505\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 25,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Being a creative requires patience, an eye for details.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 322,\n          \"height\": 64,\n          \"id\": \"eba8bf59-5bb4-460a-a81f-afab25b2efef\",\n          \"x\": 49,\n          \"y\": 401,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">We compiled a list of laptops for your specific creative needs. Read on for our picks.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 64,\n          \"id\": \"c15011a8-1687-44a2-b97c-7bdeacd7a8c0\",\n          \"x\": 50,\n          \"y\": 474\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"03648b35-3582-487b-a0c8-3d541fcb58bf\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"080fde21-44bf-4560-8b9c-0ffd598df505\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ffc8e95c-666a-4427-8c71-f9594093a1fa\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 327,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7be58764-53a1-4173-9c4b-f527ba2d83af\",\n          \"type\": \"image\",\n          \"scale\": 120,\n          \"focalX\": 43.12716069918219,\n          \"focalY\": 57.008833180708166,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page03_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1905,\n            \"id\": 0,\n            \"alt\": \"Illustration, Digital, Woman, Water, Sol, Landscape\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b28c47\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 1, \"g\": 86, \"b\": 252 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em\\\">01/03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 60,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"723702f6-aae8-4ed6-9783-f27788dc41b8\",\n          \"x\": 176,\n          \"y\": 229,\n          \"marginOffset\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">For animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 39,\n          \"id\": \"27b36872-63d2-44d3-808e-55376672da3a\",\n          \"x\": 49,\n          \"y\": 257,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Animators need RAM and processing speed. Period.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"id\": \"ee2b5264-6cc9-4088-a134-108885e4b57e\",\n          \"x\": 50,\n          \"y\": 298,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e58e6cb7-f631-497c-a94b-a41175946951\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"targets\": [\"7be58764-53a1-4173-9c4b-f527ba2d83af\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleIn\"\n        },\n        {\n          \"id\": \"f9a354f0-3bf4-4ded-9c21-41bf6b34dd2f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ee2b5264-6cc9-4088-a134-108885e4b57e\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fa6f135d-e207-4181-934a-c91f955be24f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"51c2605d-592e-4f36-9809-5960224c48f5\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"777b3c98-62c1-4a62-81bf-eb3ae277f155\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"225e39a4-b0d0-4c0b-b5ea-893fb5e01216\",\n          \"x\": 0,\n          \"y\": -57,\n          \"groupId\": \"8f7420b5-bed5-4aed-9973-9da1b622a354\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 01 for Animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"ac7059af-1e18-4b7e-91d7-0bb7c2e918b3\",\n          \"x\": 48,\n          \"y\": 14,\n          \"groupId\": \"8f7420b5-bed5-4aed-9973-9da1b622a354\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:45:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page01_04_14_image01.png\",\n            \"width\": 1920,\n            \"height\": 1329,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Macbook pro 16 inch mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#040404\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 17,\n          \"y\": 101,\n          \"width\": 378,\n          \"height\": 262,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a0fa3f52-a7ec-4896-836f-7ea4faca8c1a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Google Pixelbook</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"bbf5d2af-0c07-421f-9647-17f16bed549c\",\n          \"x\": 49,\n          \"y\": 451\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">Powerful processing speed and infinite cloud storage.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 42,\n          \"id\": \"99007627-849b-4b94-a6af-f0960282c250\",\n          \"x\": 49,\n          \"y\": 487\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:95/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"12b23d02-f578-478e-a2ce-68b8ef4c3eb8\",\n          \"x\": 49,\n          \"y\": 596\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ea8facb2-b00c-4c76-8804-2a4f8b4b43f5\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8f7420b5-bed5-4aed-9973-9da1b622a354\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8498f709-48fb-4d4b-8e53-b20fadc9ec4c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1b59b14b-9282-479b-bba9-709966e3e734\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"a13797e6-134f-4b9a-992c-efe92ae91f73\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 01 for Animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"051fed88-ad4a-4a8d-b8ff-3962154bab50\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"a13797e6-134f-4b9a-992c-efe92ae91f73\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T12:03:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page05_image01.png\",\n            \"width\": 1920,\n            \"height\": 1200,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Macbook pro from side view mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#050505\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -49,\n          \"y\": 64,\n          \"width\": 510,\n          \"height\": 318,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2d1ec41e-8c66-4ee1-804d-f085f9f2ee79\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Google Pixelbook Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"415079a4-5d64-4552-9ac6-79f210b2272e\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">A larger magic screen + processing speed but lacks the infinite cloud storage capability.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 64,\n          \"id\": \"cb55e28d-7347-421d-9310-ad2f7fb36373\",\n          \"x\": 49,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:92/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"e1060dec-1e31-4fe5-b485-66a6ebc0f20b\",\n          \"x\": 49,\n          \"y\": 598,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e3ec8238-6ab7-43fa-9e5e-c4e58057ef06\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a13797e6-134f-4b9a-992c-efe92ae91f73\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9a968210-5519-4b2c-8663-bc885174cde1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9ff7f8f0-39f6-4ec8-b62e-1eb61c44298d\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"9b54b799-e84e-410f-9b86-45ca40212108\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 01 for Animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"7398926b-aede-49f2-8dbd-edfba83b9ef9\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"9b54b799-e84e-410f-9b86-45ca40212108\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Performance graph</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"3d6ef8bf-c78f-4d34-a607-a74fdfcb7bae\",\n          \"x\": 47,\n          \"y\": 101,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 151,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ef66981b-56de-43cf-8fdd-32a2db646e55\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Performance graph</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"id\": \"0d24ffe0-2eb9-4622-9285-1cb68c2dc148\",\n          \"x\": 47,\n          \"y\": 175,\n          \"groupId\": \"0f253d47-80d9-409a-a8e5-25f657a5b8b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 20,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"41998f9a-1160-4e76-9913-8a193bd3379f\",\n          \"x\": 47,\n          \"y\": 208,\n          \"groupId\": \"0f253d47-80d9-409a-a8e5-25f657a5b8b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"image\",\n          \"width\": 277,\n          \"height\": 12,\n          \"scale\": 92.02368800531443,\n          \"focalX\": 43.6459724582783,\n          \"focalY\": 54.33383630214046,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5dacdbec-201a-420b-b4bf-3a51d977fa54\",\n          \"x\": 47,\n          \"y\": 212,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page06_image01.png\",\n            \"width\": 628,\n            \"height\": 24,\n            \"id\": 0,\n            \"alt\": \"Blue diagonal bars\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0454fc\",\n            \"isExternal\": true\n          },\n          \"resizeWidth\": 242.328,\n          \"resizeHeight\": 12.3438,\n          \"groupId\": \"0f253d47-80d9-409a-a8e5-25f657a5b8b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">95/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 51,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"afb201d0-0c4c-434b-9659-591422d5d9ed\",\n          \"x\": 47,\n          \"y\": 233,\n          \"groupId\": \"0f253d47-80d9-409a-a8e5-25f657a5b8b0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"77a0f2db-d968-4abc-a7f5-52790199bdda\",\n          \"x\": 47,\n          \"y\": 261\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Google Pixelbook Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 20,\n          \"type\": \"text\",\n          \"id\": \"60726046-5037-4ef2-a770-92d191d2c3a3\",\n          \"x\": 47,\n          \"y\": 287,\n          \"groupId\": \"6a4dd488-aa2d-41b0-8d6b-cda6eb75b3aa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 20,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"516cb438-7cce-4fa4-8ed0-cd521a859614\",\n          \"x\": 48,\n          \"y\": 320,\n          \"groupId\": \"6a4dd488-aa2d-41b0-8d6b-cda6eb75b3aa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"image\",\n          \"width\": 243,\n          \"height\": 12,\n          \"scale\": 92.54251520561625,\n          \"focalX\": 38.958671250499464,\n          \"focalY\": 54.02922093581219,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page06_image01.png\",\n            \"width\": 628,\n            \"height\": 24,\n            \"id\": 0,\n            \"alt\": \"Blue diagonal bars\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0454fc\",\n            \"isExternal\": true\n          },\n          \"resizeWidth\": 212.031,\n          \"resizeHeight\": 13.2188,\n          \"id\": \"aee50420-ba8f-487c-b586-6de0385c1a6e\",\n          \"x\": 47,\n          \"y\": 324,\n          \"groupId\": \"6a4dd488-aa2d-41b0-8d6b-cda6eb75b3aa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">92/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 57,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"7c111531-e067-4de2-aa99-b4b31b4ab563\",\n          \"x\": 47,\n          \"y\": 345,\n          \"groupId\": \"6a4dd488-aa2d-41b0-8d6b-cda6eb75b3aa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2189e638-7457-44f3-a712-197dea44b4b2\",\n          \"x\": 47,\n          \"y\": 373\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Average</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 21,\n          \"type\": \"text\",\n          \"id\": \"984b1e3e-91f2-4ae7-aa0e-ec4188950fdc\",\n          \"x\": 50,\n          \"y\": 399,\n          \"groupId\": \"b045d2f3-d3b7-49ef-a7e6-f595cab821ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 20,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2fe5f79c-cf9b-4e3c-baad-f500d4386183\",\n          \"x\": 47,\n          \"y\": 432,\n          \"groupId\": \"b045d2f3-d3b7-49ef-a7e6-f595cab821ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"type\": \"image\",\n          \"width\": 151,\n          \"height\": 12,\n          \"scale\": 91.30159172442617,\n          \"focalX\": 24.3793827535866,\n          \"focalY\": 54.76355784783471,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page06_image01.png\",\n            \"width\": 628,\n            \"height\": 24,\n            \"id\": 0,\n            \"alt\": \"Blue diagonal bars\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0454fc\",\n            \"isExternal\": true\n          },\n          \"resizeWidth\": 132.328,\n          \"resizeHeight\": 11.4844,\n          \"id\": \"88ea99a5-eaec-4b80-9de2-0732b534f78f\",\n          \"x\": 47,\n          \"y\": 436,\n          \"groupId\": \"b045d2f3-d3b7-49ef-a7e6-f595cab821ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">51/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 54,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"b147e772-2e53-4b16-a6f9-ec62736f437e\",\n          \"x\": 50,\n          \"y\": 457,\n          \"groupId\": \"b045d2f3-d3b7-49ef-a7e6-f595cab821ea\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c8198913-7853-4607-8933-6490eceae3b4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5dacdbec-201a-420b-b4bf-3a51d977fa54\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a72e8a69-75df-4500-8903-446e93977e95\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"aee50420-ba8f-487c-b586-6de0385c1a6e\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"4af7b589-28e7-4ecf-a8c1-936d7d7bcc8d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"88ea99a5-eaec-4b80-9de2-0732b534f78f\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"00b812ca-d325-46ad-ad69-346a03a76840\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"afb201d0-0c4c-434b-9659-591422d5d9ed\"],\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"fa59a43a-6788-475a-89e9-c3372002458f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7c111531-e067-4de2-aa99-b4b31b4ab563\"],\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"c81f9514-a488-411a-9291-e8135fe601b8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b147e772-2e53-4b16-a6f9-ec62736f437e\"],\n          \"duration\": 600,\n          \"delay\": 900\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5644a1c5-a513-4905-8753-e73bb88e07a5\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9b54b799-e84e-410f-9b86-45ca40212108\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"0f253d47-80d9-409a-a8e5-25f657a5b8b0\": {\n          \"name\": \"Performance\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6a4dd488-aa2d-41b0-8d6b-cda6eb75b3aa\": {\n          \"name\": \"Go\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b045d2f3-d3b7-49ef-a7e6-f595cab821ea\": {\n          \"name\": \"Average\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 444,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"875b7b7d-298f-4f5e-a5a1-15babed0a855\",\n          \"type\": \"image\",\n          \"scale\": 134,\n          \"focalX\": 56.56449899015199,\n          \"focalY\": 46.53213338658963,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page07_image01.jpg\",\n            \"width\": 1426,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Illustration of hands on keyboard\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a07145\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 1, \"g\": 86, \"b\": 252 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em\\\">02/03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 60,\n          \"height\": 23,\n          \"id\": \"b85181a5-9df0-42c6-baaf-1b98c10bc34f\",\n          \"x\": 176,\n          \"y\": 229,\n          \"type\": \"text\",\n          \"marginOffset\": -1.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">For writers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 39,\n          \"id\": \"4ac8fedb-d51d-4d2b-bf0b-279a1057d2c5\",\n          \"x\": 49,\n          \"y\": 257,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Really all you need is a digital writing pad and a place to access your thoughts online and off.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 73,\n          \"id\": \"d39c16e3-8d57-4573-aa4a-1156d9828d90\",\n          \"x\": 50,\n          \"y\": 298,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3171f627-0b7c-4515-8cda-77d9c60b9955\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"targets\": [\"875b7b7d-298f-4f5e-a5a1-15babed0a855\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleIn\"\n        },\n        {\n          \"id\": \"ec03e84d-b782-4d03-a146-e7aad87b64d9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d39c16e3-8d57-4573-aa4a-1156d9828d90\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"16cfd36f-e0cf-4012-8a0f-de28d1001e7d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"828e54e0-ebb4-4d47-a3f6-4a135ed7a13c\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e90d4a37-6d10-4a11-9057-ae648b8682d4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8e29caf4-6e8b-46d8-aab4-39a0da1e9544\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"653317dc-d9a9-4785-b36c-3cf347f09b9c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 02 for Writers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"ad3c24ac-139b-4524-b53f-91f266965e3e\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"653317dc-d9a9-4785-b36c-3cf347f09b9c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-26T09:30:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page08_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1440,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Close-Up Of Laptop Against White Background\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c7c7c7\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 384,\n          \"height\": 287,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"60eea6ef-d78f-4966-ab89-ffbeaf1b21ad\",\n          \"x\": 14,\n          \"y\": 86\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Lenovo Ideapad S340</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"e0615041-2c93-4727-848c-dba09903953a\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">With the ability to write your free-form thoughts like a notepad and switch to editing mode. You're all set</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 64,\n          \"id\": \"a524c320-22c3-4d2f-ba0b-c4bdc5e6a71b\",\n          \"x\": 49,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:97/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"96824fe1-b113-4fe5-8367-f1f875db9644\",\n          \"x\": 49,\n          \"y\": 598,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"953c7bb7-5fb5-48c0-904a-498eb4094572\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"653317dc-d9a9-4785-b36c-3cf347f09b9c\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"813dcd4d-ae80-4899-927e-2b0c1653badf\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cf425fab-2e5a-484c-8dab-381b362bc933\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"7d280577-9c01-4e88-88e2-27a02a49c4fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 02 for Writers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"44cc3a4f-f2a7-434e-8b08-3e766198ffde\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"7d280577-9c01-4e88-88e2-27a02a49c4fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#acdbea\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page09_image01.png\",\n            \"width\": 1920,\n            \"height\": 1329,\n            \"id\": 0,\n            \"alt\": \"Macbook Pro 16\\\" mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 17,\n          \"y\": 101,\n          \"width\": 378,\n          \"height\": 261,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fbe6a491-ef56-4fb6-9e51-f3a1d81b86fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Lenovo Ideapad S145</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 30,\n          \"id\": \"e7cfc9f5-6bd3-46db-bffb-9be004f272dc\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">The latest and greatest, now in a collapsible version so you can carry with you anywhere</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 42,\n          \"id\": \"abde8104-c001-413d-b394-c913e8375958\",\n          \"x\": 49,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:98/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"28791da5-3d77-4b7a-9222-e26f45790d10\",\n          \"x\": 49,\n          \"y\": 598,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"4a8a37fb-2cc7-404e-8265-99dab1fd9268\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7d280577-9c01-4e88-88e2-27a02a49c4fd\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"729065c7-62b6-4db3-8448-8f874173f455\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"19e017a9-f61f-43e6-811c-05197b542e5c\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"504fb351-2ce9-44a4-adff-46647cf3fbae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 01 for Animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"cb04be07-d1cc-4328-af2b-07f3b246fc58\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"504fb351-2ce9-44a4-adff-46647cf3fbae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Lightweight graph</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 30,\n          \"id\": \"1c091636-92a2-48df-b27f-13969241dc3a\",\n          \"x\": 47,\n          \"y\": 101,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"x\": 47,\n          \"y\": 156,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a3296562-ece7-455c-a912-fc10ec5c2a0c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Lenovo Ideapad S340</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 21,\n          \"id\": \"6f56acdb-9f0a-496d-8ca0-f08d014b2655\",\n          \"x\": 47,\n          \"y\": 182,\n          \"type\": \"text\",\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 224,\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"d2ca3724-95bb-4e22-8fe0-ad114322122b\",\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"5dea2216-2aa0-4d50-810d-b7cddb1eaea5\",\n          \"x\": 100,\n          \"y\": 224,\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"2657bbb7-eec7-4df1-8964-46ed178204dd\",\n          \"x\": 153,\n          \"y\": 224,\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 202,\n          \"y\": 224,\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsHalf\" },\n          \"id\": \"06a19893-9eda-44e7-bae8-63473b66ac07\",\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">3.4 LB</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 56,\n          \"height\": 15,\n          \"id\": \"fed1ca37-b08b-4c11-a252-80ea40cb527b\",\n          \"x\": 47,\n          \"y\": 266,\n          \"type\": \"text\",\n          \"groupId\": \"5eadc781-e130-4bff-bd64-0a9cf917e607\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bb40468c-e378-48e8-8ead-09aa827f5c44\",\n          \"x\": 48,\n          \"y\": 300,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Lenovo Ideapad S145</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 20,\n          \"id\": \"9190b4cc-bb94-4e25-baed-6870cd1c05df\",\n          \"x\": 47,\n          \"y\": 321,\n          \"type\": \"text\",\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"97f9c448-7481-45df-9263-789f80810252\",\n          \"x\": 48,\n          \"y\": 363,\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsHalf\" },\n          \"id\": \"363e940a-7c23-4df9-8c46-ad92936d6591\",\n          \"x\": 100,\n          \"y\": 363,\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 152,\n          \"y\": 363,\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopOff\" },\n          \"id\": \"2769a9b5-d436-411f-843d-31f5ed3104c8\",\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopOff\" },\n          \"id\": \"5bef79b0-b43b-4b7e-8eee-69dda28f31d3\",\n          \"x\": 203,\n          \"y\": 363,\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">1.45 LB</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 67,\n          \"height\": 15,\n          \"id\": \"3d361dd0-0046-420f-a0ca-9f28257154af\",\n          \"x\": 47,\n          \"y\": 405,\n          \"type\": \"text\",\n          \"groupId\": \"3ac15074-2cea-482c-bccb-0fe34886d97a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } },\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"437d1dd5-2369-475f-b3b4-4fd701bbf148\",\n          \"x\": 48,\n          \"y\": 439,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Average</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 21,\n          \"id\": \"6a26355f-894a-4da4-a584-8a229a177f5c\",\n          \"x\": 47,\n          \"y\": 460,\n          \"type\": \"text\",\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"0ce2603b-9b30-4018-b180-41dea946f5f2\",\n          \"x\": 48,\n          \"y\": 502,\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsFull\" },\n          \"id\": \"e4df9a01-789c-4b41-8f51-211e176e2182\",\n          \"x\": 101,\n          \"y\": 502,\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 152,\n          \"y\": 502,\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopRatingsThreeFourth\" },\n          \"id\": \"2a223fbc-9362-4fbf-8c47-7dad48aa2939\",\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"laptopOff\" },\n          \"id\": \"031e9649-d2ef-40ce-9fc3-6fcde92447fd\",\n          \"x\": 203,\n          \"y\": 502,\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em\\\">2.95 LB</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 67,\n          \"height\": 15,\n          \"id\": \"516cbe00-dbc5-42fb-805f-4f577d4211b3\",\n          \"x\": 47,\n          \"y\": 544,\n          \"type\": \"text\",\n          \"groupId\": \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"88407aef-d969-4e4c-8169-7f61ccd5434a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d2ca3724-95bb-4e22-8fe0-ad114322122b\"],\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"04699f2b-dcf9-43d9-93d8-4cb378df219a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5dea2216-2aa0-4d50-810d-b7cddb1eaea5\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c1e0143f-3006-4bc3-a0b0-9186d92e8d1e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2657bbb7-eec7-4df1-8964-46ed178204dd\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"cb40ab23-0769-41af-8d53-91301eb46358\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"06a19893-9eda-44e7-bae8-63473b66ac07\"],\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"96d56862-962b-48c1-a739-8b9caac38d59\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"97f9c448-7481-45df-9263-789f80810252\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"38bd6b9f-708e-4979-8aca-af09e6f69e82\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"363e940a-7c23-4df9-8c46-ad92936d6591\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"97a06185-ea38-4bc1-98b7-f22486360b5e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2769a9b5-d436-411f-843d-31f5ed3104c8\"],\n          \"duration\": 2000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"567e8677-af87-45a9-b50d-62c5b11e093f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5bef79b0-b43b-4b7e-8eee-69dda28f31d3\"],\n          \"duration\": 2000,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"e80ae7e1-87a0-4c2d-ab1e-21857bd885f1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0ce2603b-9b30-4018-b180-41dea946f5f2\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"8733ac60-d577-433c-b418-f57434b32a7e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e4df9a01-789c-4b41-8f51-211e176e2182\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"10240622-90e7-4b37-8c26-b03c80979944\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2a223fbc-9362-4fbf-8c47-7dad48aa2939\"],\n          \"duration\": 2000,\n          \"delay\": 1100\n        },\n        {\n          \"id\": \"b751c08d-0878-48d3-b6bf-ca9598e42a4f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"031e9649-d2ef-40ce-9fc3-6fcde92447fd\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"2f62238c-04b8-4d4f-a837-38e30bd4e19b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fed1ca37-b08b-4c11-a252-80ea40cb527b\"],\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"e19be5af-36a6-472d-b6a7-4c7704ef48e2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3d361dd0-0046-420f-a0ca-9f28257154af\"],\n          \"duration\": 600,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"18520a46-a83e-4fad-889f-9d6fa8b7cb09\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"516cbe00-dbc5-42fb-805f-4f577d4211b3\"],\n          \"duration\": 600,\n          \"delay\": 1200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ddc239ba-d5b6-497e-a3d3-fc88cf2ba3d7\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"5eadc781-e130-4bff-bd64-0a9cf917e607\": {\n          \"name\": \"S340\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3ac15074-2cea-482c-bccb-0fe34886d97a\": {\n          \"name\": \"S145\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"097cef7a-0ede-4fda-a863-7d18c1ef22cb\": {\n          \"name\": \"Average\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"504fb351-2ce9-44a4-adff-46647cf3fbae\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 339,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"a63bc44a-fba1-4db2-9613-51c32c14f579\",\n          \"type\": \"image\",\n          \"scale\": 212,\n          \"focalX\": 62.141403679427235,\n          \"focalY\": 41.25095577371671,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page11_image01.png\",\n            \"width\": 960,\n            \"height\": 986,\n            \"id\": 0,\n            \"alt\": \"Remote work office home office\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e6d3c3\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 1, \"g\": 86, \"b\": 252 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em\\\">02/03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 60,\n          \"height\": 23,\n          \"id\": \"971c948f-7529-4680-9b16-6061ac9a9534\",\n          \"x\": 180,\n          \"y\": 229,\n          \"type\": \"text\",\n          \"marginOffset\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">For designers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 39,\n          \"id\": \"c85b20ff-b78d-4cf1-a7f6-ef2f187d192a\",\n          \"x\": 49,\n          \"y\": 257,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Processing speed, screen clarity and transportability.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 48,\n          \"id\": \"cc993193-6917-4dbd-8c00-2fc024548383\",\n          \"x\": 50,\n          \"y\": 298,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b27ee23b-a407-4cd3-8296-b03b8b9a6b04\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"targets\": [\"a63bc44a-fba1-4db2-9613-51c32c14f579\"],\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleIn\"\n        },\n        {\n          \"id\": \"d92c2e4c-0b0c-4762-bdfa-7675018a7953\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cc993193-6917-4dbd-8c00-2fc024548383\"],\n          \"duration\": 1600,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"45d8da1d-4548-42ae-be55-33237dedc77c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"14c143ea-71d9-4245-80b4-343b91aa11f2\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c4bca965-0200-4a97-88ea-a1ca28eb6171\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a7e2f6ac-474b-4e13-8545-881928e13d5d\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"22251922-75c7-42b1-a69e-555e0bbb3152\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 03 for Designers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"b1322908-9a17-4466-be51-0e96cc9ad2b9\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"22251922-75c7-42b1-a69e-555e0bbb3152\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#d9d9da\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page12_14_image01.png\",\n            \"width\": 1920,\n            \"height\": 1440,\n            \"id\": 0,\n            \"alt\": \"Clean Macbook Air mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 378,\n          \"height\": 283,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7f6b3857-abc8-4d9b-aea2-e4dbfd907ad8\",\n          \"x\": 17,\n          \"y\": 86\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">DELL Inspiron 3593</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"1405adbe-8968-430c-9127-423a13055cb7\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">With an edge to edge screen with Google's clarity pixelation(TM) you'll see every detail of your design.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 64,\n          \"id\": \"aedeb6af-cf95-44aa-b154-c36fa7e7f360\",\n          \"x\": 49,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:94/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"676478ba-7e99-431d-8d83-5869661d9e04\",\n          \"x\": 49,\n          \"y\": 598,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0a97c7ab-456b-477f-bcc1-807bbd4b911d\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"22251922-75c7-42b1-a69e-555e0bbb3152\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"760fcf27-2dde-4805-a117-e9e10ec0f370\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1130c10c-4f86-4beb-8bb4-bc9320a947dc\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"0fa9961c-671b-4b56-a37d-415bf1858d25\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; 03 for Designers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 15,\n          \"id\": \"7b6f8422-1162-4365-bca7-a564ae4dd48d\",\n          \"x\": 48,\n          \"y\": 14,\n          \"type\": \"text\",\n          \"groupId\": \"0fa9961c-671b-4b56-a37d-415bf1858d25\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#28a6d6\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page13_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1440,\n            \"id\": 0,\n            \"alt\": \"Laptop floating angled Open\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 74,\n          \"width\": 412,\n          \"height\": 308,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a980a935-17ce-46bf-a72c-1181c0a2532c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff\\\">Lenovo Ideapad Slim 3i</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 29,\n          \"id\": \"f8312782-1fd3-408f-b7bc-3cd3848b5989\",\n          \"x\": 49,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2f\\\">More for transportability between meetings or for traveling. Quickly access and download the files you need.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 64,\n          \"id\": \"213e55f5-2766-43d5-a5d2-a70860582871\",\n          \"x\": 49,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; text-transform: uppercase\\\">&gt;&gt;&gt; Score:96/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 21,\n          \"id\": \"f7ab7618-0010-438b-b471-2acfa3e1b4db\",\n          \"x\": 48,\n          \"y\": 598,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"cd654836-98d6-41bc-9c1a-a68776723945\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0fa9961c-671b-4b56-a37d-415bf1858d25\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"bd9db634-536b-46e7-a390-a9028d4d9fb3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n          \"width\": 412,\n          \"height\": 108,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"69bdef22-cb17-4e2a-8de4-e9f483a5c6b4\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"fec71870-c8e9-4e36-b40c-6b254b1002cd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Best laptop...&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 29,\n          \"id\": \"ee2e993f-455e-42dd-8644-a22cb96f73db\",\n          \"x\": 48,\n          \"y\": -8,\n          \"type\": \"text\",\n          \"groupId\": \"fec71870-c8e9-4e36-b40c-6b254b1002cd\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 102,\n          \"width\": 145,\n          \"height\": 126,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"aaccf5a7-cff1-4556-9c7b-4813c1a97b8d\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } }\n          },\n          \"groupId\": \"70de3059-e166-44b8-9dc7-c4afe7466790\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:45:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page01_04_14_image01.png\",\n            \"width\": 1920,\n            \"height\": 1329,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Macbook pro 16 inch mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#040404\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 45,\n          \"y\": 106,\n          \"width\": 151,\n          \"height\": 104,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"bd943a6d-5f96-4a00-be96-9f5141195ad0\",\n          \"groupId\": \"70de3059-e166-44b8-9dc7-c4afe7466790\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f; letter-spacing: 0.1em; text-transform: uppercase\\\">For Animators</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 152,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"9f07b4e1-125f-43a6-8750-3b9e51bc2715\",\n          \"x\": 209,\n          \"y\": 131,\n          \"groupId\": \"70de3059-e166-44b8-9dc7-c4afe7466790\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Google Pixelbook</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 159,\n          \"height\": 23,\n          \"id\": \"d8f51bfe-d8a9-4ad6-9948-a020ffef89fd\",\n          \"x\": 206,\n          \"y\": 158,\n          \"type\": \"text\",\n          \"groupId\": \"70de3059-e166-44b8-9dc7-c4afe7466790\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; Score:95/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 15,\n          \"id\": \"79db26bd-67a9-41de-acf1-f8a8c4bedb03\",\n          \"x\": 209,\n          \"y\": 190,\n          \"type\": \"text\",\n          \"groupId\": \"70de3059-e166-44b8-9dc7-c4afe7466790\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 126,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } }\n          },\n          \"id\": \"9550a0b5-3b0f-4669-abc4-365940ee713f\",\n          \"x\": 48,\n          \"y\": 248,\n          \"groupId\": \"f9d579a7-91bf-4fae-a376-5b23125c5712\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T11:58:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page12_14_image01.png\",\n            \"width\": 1920,\n            \"height\": 1440,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Clean Macbook Air mockup\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d8d9da\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 54,\n          \"y\": 260,\n          \"width\": 133,\n          \"height\": 99,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b9643217-424a-4626-9a72-711c27220b8b\",\n          \"groupId\": \"f9d579a7-91bf-4fae-a376-5b23125c5712\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f; letter-spacing: 0.1em; text-transform: uppercase\\\">For Writers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"884cbbcb-e8b0-4b30-a34c-5c9ef57640bd\",\n          \"x\": 209,\n          \"y\": 263,\n          \"groupId\": \"f9d579a7-91bf-4fae-a376-5b23125c5712\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Lenovo Ideapad S340</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 156,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"id\": \"1f7468ff-010c-481d-b203-3fe327bd6f24\",\n          \"x\": 209,\n          \"y\": 290,\n          \"groupId\": \"f9d579a7-91bf-4fae-a376-5b23125c5712\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; Score:95/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"2c3c05c9-4a8f-4fcf-85a4-561b7ee646b2\",\n          \"x\": 209,\n          \"y\": 345,\n          \"groupId\": \"f9d579a7-91bf-4fae-a376-5b23125c5712\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 126,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 228, \"g\": 228, \"b\": 228 } }\n          },\n          \"id\": \"81d11d17-df5a-4125-bb9f-cf679ce4e70c\",\n          \"x\": 48,\n          \"y\": 395,\n          \"groupId\": \"45f859e0-dab0-460d-bced-9b683eb07e34\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#28a6d6\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page13_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1440,\n            \"id\": 0,\n            \"alt\": \"Laptop floating angled Open\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 131,\n          \"height\": 97,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4d1facf7-e3b2-499f-922c-e45e30db598e\",\n          \"x\": 56,\n          \"y\": 408,\n          \"groupId\": \"45f859e0-dab0-460d-bced-9b683eb07e34\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f; letter-spacing: 0.1em; text-transform: uppercase\\\">For Designers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"57586933-8964-4d79-aca6-8b1d7f179b35\",\n          \"x\": 209,\n          \"y\": 408,\n          \"groupId\": \"45f859e0-dab0-460d-bced-9b683eb07e34\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #2f2f2f\\\">Lenovo Ideapad Slim 3i</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"id\": \"a95c6bb2-08fb-4bb7-8b31-aa84acab473e\",\n          \"x\": 209,\n          \"y\": 435,\n          \"groupId\": \"45f859e0-dab0-460d-bced-9b683eb07e34\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #0057ff; letter-spacing: 0.1em; text-transform: uppercase\\\">&gt;&gt;&gt; Score:95/100</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"bbc2afa1-c745-46bc-8e33-2464a0f0bc4e\",\n          \"x\": 209,\n          \"y\": 491,\n          \"groupId\": \"45f859e0-dab0-460d-bced-9b683eb07e34\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3203d62e-7d1d-4ec0-ba09-894278348d28\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"79db26bd-67a9-41de-acf1-f8a8c4bedb03\"],\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"30c00a63-229e-4187-ac65-fc506f973989\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2c3c05c9-4a8f-4fcf-85a4-561b7ee646b2\"],\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"ef41bf4f-b9db-442b-bca5-4ccb5244f852\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bbc2afa1-c745-46bc-8e33-2464a0f0bc4e\"],\n          \"duration\": 600,\n          \"delay\": 900\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f2b65c55-6303-43c1-94bf-b95985117afa\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"fec71870-c8e9-4e36-b40c-6b254b1002cd\": {\n          \"name\": \"Header\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"70de3059-e166-44b8-9dc7-c4afe7466790\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f9d579a7-91bf-4fae-a376-5b23125c5712\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"45f859e0-dab0-460d-bced-9b683eb07e34\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"1adf168b-3d7a-43e3-ab74-4830853ad75c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 29,\n          \"type\": \"text\",\n          \"id\": \"ad8b4e80-08d5-4bb9-ba1f-de41d8c241c5\",\n          \"x\": 120.5,\n          \"y\": 23,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.1em\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"523c0db6-b686-42ca-906c-51b0bd7ee141\",\n          \"x\": 76,\n          \"y\": 129,\n          \"marginOffset\": -1.2000000000000028,\n          \"groupId\": \"0190afbb-fab7-49fd-b1d7-49c8a36ad32a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page15_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1422,\n            \"id\": 0,\n            \"alt\": \"Person holding turned-on black iPad\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d8dbdc\",\n            \"isExternal\": true\n          },\n          \"x\": 76,\n          \"y\": 153,\n          \"width\": 260,\n          \"height\": 150,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cc940bbd-d9fd-4188-a789-69332de002e5\",\n          \"groupId\": \"0190afbb-fab7-49fd-b1d7-49c8a36ad32a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Find the right tablet</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 232,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"eea77c70-7e10-4d58-b784-b758fa91b819\",\n          \"x\": 108,\n          \"y\": 315,\n          \"groupId\": \"0190afbb-fab7-49fd-b1d7-49c8a36ad32a\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em\\\">&gt;&gt;&gt;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 31,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"abf6785d-9cb1-421e-8638-8391f2d4645f\",\n          \"x\": 76,\n          \"y\": 319,\n          \"groupId\": \"0190afbb-fab7-49fd-b1d7-49c8a36ad32a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.1em\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"marginOffset\": -1.2000000000000028,\n          \"id\": \"ce128187-c794-4d2d-b9fb-d93960c64d55\",\n          \"x\": 76,\n          \"y\": 360,\n          \"groupId\": \"10eb0ab1-2ec5-455e-9187-5719368baea1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 260,\n          \"height\": 150,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6194c4c1-88fd-4bfd-8ba0-02fd5589b846\",\n          \"x\": 76,\n          \"y\": 384,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/laptop-buying-guide/page15_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"MacBook Pro on top of brown table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d5cfc5\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"10eb0ab1-2ec5-455e-9187-5719368baea1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Get savvy on Sketch</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 232,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"2303f2cb-8ecc-4ae8-9e54-e716fd02e43d\",\n          \"x\": 108,\n          \"y\": 546,\n          \"groupId\": \"10eb0ab1-2ec5-455e-9187-5719368baea1\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Mono\",\n            \"fallbacks\": [\"monospace\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -251,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.1em\\\">&gt;&gt;&gt;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 31,\n          \"height\": 15,\n          \"type\": \"text\",\n          \"id\": \"d975b68b-ae15-4f58-93d0-87782ac8ae37\",\n          \"x\": 76,\n          \"y\": 551,\n          \"groupId\": \"10eb0ab1-2ec5-455e-9187-5719368baea1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6524fe1a-01cb-40c5-a150-734a4d39c5ed\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2303f2cb-8ecc-4ae8-9e54-e716fd02e43d\"],\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"46bcd5d5-2dbb-4a14-9730-69a0e90d3520\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d975b68b-ae15-4f58-93d0-87782ac8ae37\"],\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"1a84b8a0-926a-4479-b243-92d0e02d6410\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"abf6785d-9cb1-421e-8638-8391f2d4645f\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2b0c39dc-9951-4aac-8020-b19705348644\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"eea77c70-7e10-4d58-b784-b758fa91b819\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b8289d55-26db-4b14-9099-6636c9278675\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cc940bbd-d9fd-4188-a789-69332de002e5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"2a8bc6e4-30b0-452d-9761-6b40cb0f4df3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6194c4c1-88fd-4bfd-8ba0-02fd5589b846\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 87, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2cdd54a4-58a1-4f76-99a0-b740f41f3feb\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0190afbb-fab7-49fd-b1d7-49c8a36ad32a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"10eb0ab1-2ec5-455e-9187-5719368baea1\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/los-angeles-city-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/los-angeles-city-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'los-angeles-city-guide',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Los Angeles City Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('City', 'template keyword', 'web-stories'),\n    _x('Visit', 'template keyword', 'web-stories'),\n    _x('Dark', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Dusk Black', 'color', 'web-stories'),\n      color: '#212426',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Alpine Green', 'color', 'web-stories'),\n      color: '#c2cda3',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its serene black-and-green color palette, this template will let you create city guides, travelogues and other travel stories that are moody and atmospheric.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/los-angeles-city-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/los-angeles-city-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c75d8432-050f-4b0c-8ccc-5fffe814bf03\",\n          \"scale\": 113,\n          \"focalX\": 44.469026548672566,\n          \"focalY\": 54.271785769842374,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page01_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Vehicles on road\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#6f727d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e2a4d092-c1b7-450f-b6b6-15e8b09b52e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">Everything You Didn't Know About Los Angeles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 162,\n          \"width\": 309,\n          \"height\": 166,\n          \"id\": \"5307bdc0-6dd8-48ac-9158-63f1e4e56835\",\n          \"marginOffset\": 0.8881249999999952\n        },\n        {\n          \"x\": 47,\n          \"y\": 601,\n          \"id\": \"98663352-5c1c-4d3a-bc1a-f93c00d30ca2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">By </span><span style=\\\"font-weight: 900; color: #c2cda3\\\">Billy Rogers</span><span style=\\\"color: #c2cda3\\\"> 08/11/20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 182,\n          \"height\": 19,\n          \"marginOffset\": -24.779999999999994\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c359b3cd-b99d-47be-8d46-57b14b735477\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"cff73925-1ba0-41f4-a3ae-2ed3c2f54292\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7d783119-0cb3-45a9-bb0d-f877f80929b8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 75.48828124999999,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:16:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page02_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1280,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Cars parked on gray concrete near trees\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1f2f2a\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 394,\n          \"width\": 412,\n          \"height\": 279,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e4f054b7-72d7-4653-b5b5-790cdecb39ae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3\\\">Los Angeles, one of the most traveled cities in the world</span><span style=\\\"color: #c2cda3\\\">. </span><span style=\\\"font-weight: 300; color: #c2cda3\\\">But just when you thought you knew it all.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 290,\n          \"height\": 92,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"15a512ab-1fc9-46fc-a25f-b80d055329ef\",\n          \"x\": 47,\n          \"y\": 151\n        },\n        {\n          \"x\": 47,\n          \"y\": 278,\n          \"id\": \"0d89a999-8616-4888-ac6f-543d83fcddcc\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #c2cda3\\\">Here are 6 things you (probably) didn’t know.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 290,\n          \"height\": 45,\n          \"marginOffset\": 3.288999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 132,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2c46ae1f-9a06-4017-a1f2-ac54ef251f9f\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ca74840c-7add-4c7e-ab54-1c69ceb4b408\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2c46ae1f-9a06-4017-a1f2-ac54ef251f9f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"bd8cc584-3b14-416c-87aa-55fdb89ca4fe\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"9bb5c89b-aefb-48c4-a430-1a334105da09\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page03_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"People crossing the street\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3d2d0\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -338.5,\n          \"y\": -230,\n          \"width\": 1049,\n          \"height\": 774,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8de05f92-5a1f-4152-80d7-0325a9b24173\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 496,\n          \"width\": 412,\n          \"height\": 177,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbd40219-f56a-4419-ab2b-b6b37f8d8738\",\n          \"groupId\": \"18078796-061e-4f77-a0a5-55c19544b98b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">BUNKER HILL</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 532,\n          \"width\": 191,\n          \"height\": 48,\n          \"id\": \"0078d19f-a03e-491e-9c1d-ab59b33e6a94\",\n          \"marginOffset\": 0.6706250000000011,\n          \"groupId\": \"18078796-061e-4f77-a0a5-55c19544b98b\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 573,\n          \"id\": \"458ce963-1fb6-4142-8398-22039c2e9861\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">Downtown used to be the infamous </span><span style=\\\"font-weight: 700; color: #c2cda3\\\">Bunker Hill.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 45,\n          \"marginOffset\": 5.637500000000003,\n          \"groupId\": \"18078796-061e-4f77-a0a5-55c19544b98b\"\n        },\n        {\n          \"x\": 11,\n          \"y\": 454,\n          \"id\": \"176c402a-1019-4e10-8e8a-fc84c5d11124\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 34,\n            \"vertical\": 9\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #212426\\\">01.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 89,\n          \"height\": 43,\n          \"marginOffset\": -0.9299999999999997,\n          \"groupId\": \"18078796-061e-4f77-a0a5-55c19544b98b\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"c83559fd-1ec2-4def-b9fc-1bdbfe0ad2b6\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"18078796-061e-4f77-a0a5-55c19544b98b\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1c6e0b63-3297-4b0a-945d-ada96c80ae68\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 118,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:16:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Palace building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#211618\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -7,\n          \"y\": -70,\n          \"width\": 426,\n          \"height\": 758,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0a5b62f8-9290-4cd5-9fcf-454adab9e5fd\"\n        },\n        {\n          \"opacity\": 64,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.43 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8f39ff01-7774-466b-b502-1fca9c346c81\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">The historic home of</span>\\n<span style=\\\"color: #c2cda3\\\">Los Angeles mobsters &amp; the underground elite.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 73,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"230b15ae-17c4-4fec-8cb0-ab3e372339cf\",\n          \"x\": 98,\n          \"y\": 34,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"x\": 98,\n          \"y\": 21,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"86803053-e41e-4859-88b6-257b190851c4\",\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"df0e32d6-e0f6-4a05-83eb-ecf6e0bb489b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"86803053-e41e-4859-88b6-257b190851c4\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"2023769d-d737-4487-babc-c8b2685d90d0\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"603f58ef-ca08-4b17-83ed-c8dc22a9e4c4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:16:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page05_image01.jpg\",\n            \"width\": 1079,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Landscape of road near city buildings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d1c3ba\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -96,\n          \"y\": -60,\n          \"width\": 592,\n          \"height\": 369,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4b7c4571-ae77-493d-9fe3-06e5907c2f40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 153,\n          \"focalX\": 50.04963294768095,\n          \"focalY\": 57.38240893849314,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:16:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page05_image02.jpg\",\n            \"width\": 1079,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Hollywood, California\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3d3a3b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -48,\n          \"y\": 308,\n          \"width\": 508,\n          \"height\": 366,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"10ede671-d5ef-4d55-8528-94b7aac99f00\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"df45ecf9-d04a-43ed-8541-efd5690a4bc1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">An area of the city with roots in Hollywood film noir and beyond.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 68,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"b47e2f4c-5737-4938-a860-ed8a4abeccb4\",\n          \"x\": 109,\n          \"y\": 498,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"x\": 109,\n          \"y\": 485,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4d102492-bca5-4cf7-8759-740f97e71d0c\",\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3cf150bd-9eb4-42fd-942b-2dd136c19db9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4d102492-bca5-4cf7-8759-740f97e71d0c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"49dc6308-3e04-4e3a-9da7-ed8458d63638\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -7,\n          \"y\": -70,\n          \"width\": 426,\n          \"height\": 758,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"80ae3bc2-5fb5-426d-ab33-6eacfd68b937\",\n          \"type\": \"image\",\n          \"scale\": 131,\n          \"focalX\": 49.98012086513996,\n          \"focalY\": 40.43337223964013,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Birds eye view of buildings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1c1c1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"38ecaa27-4703-4666-bca5-45dae7fc4323\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">“Bunker Hill was purchased for $51 and re-architected for a then-whopping $95,000.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 81,\n          \"marginOffset\": 3.146000000000001,\n          \"id\": \"d3a45f6b-7dd6-48b1-af35-ba01a3c0372c\",\n          \"x\": 47,\n          \"y\": 280,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 89,\n          \"y\": 387,\n          \"id\": \"73f59b57-24a2-4b82-b9dc-25f4b0a01c40\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.88,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3; letter-spacing: 0.1em; text-transform: uppercase\\\">KEN KENNY, LA MAYOR</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19,\n          \"marginOffset\": -5.654999999999998,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"45f3ade8-2f54-414f-938b-01e9ccad05bd\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"80ae3bc2-5fb5-426d-ab33-6eacfd68b937\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"73d66cdc-d172-4ffa-92b8-dc352e855c85\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"73f59b57-24a2-4b82-b9dc-25f4b0a01c40\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"8b265362-cdee-4f18-b3e1-981338f03e78\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"29015d0b-5266-4d5c-88d6-466c06150528\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"083c7e37-ea68-485f-a336-720e0a647915\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">Bunker Hill Value</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 17,\n          \"marginOffset\": 3.146000000000001,\n          \"id\": \"15d310cb-be57-44cb-85da-f7eea18b7cd0\",\n          \"x\": 47,\n          \"y\": 31,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 131,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"049f1eb9-c1fe-4698-97bb-45c0289580bf\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 263,\n          \"id\": \"42a248b4-9218-467b-9529-b3187417ea8a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 47,\n          \"y\": 395,\n          \"id\": \"48b4e14b-c157-46b0-811a-919691b7b50e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 47,\n          \"y\": 526,\n          \"id\": \"ae851434-42f4-4e48-bd47-2f11041018a1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 163,\n          \"id\": \"539554c7-2730-41f4-b560-449f9367deee\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">PRICE PAID</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 73,\n          \"height\": 20,\n          \"marginOffset\": -6.1949999999999985,\n          \"type\": \"text\",\n          \"groupId\": \"c56acbc9-44ae-49e0-81af-f8f78efe7ae3\"\n        },\n        {\n          \"x\": 193,\n          \"y\": 137,\n          \"id\": \"2d59d5e4-0b8d-433f-bfbb-841bb3a00fb8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #c2cda3\\\">$51</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 173,\n          \"height\": 90,\n          \"marginOffset\": 10.296000000000006,\n          \"type\": \"text\",\n          \"groupId\": \"c56acbc9-44ae-49e0-81af-f8f78efe7ae3\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 293,\n          \"id\": \"c95dec3e-321a-4c4f-80e5-d2315b0e9c26\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">DEVELOPED</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 20,\n          \"marginOffset\": -6.205000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"b34814a7-ff26-41f2-96cd-d9f93e432867\"\n        },\n        {\n          \"x\": 168,\n          \"y\": 277,\n          \"id\": \"16535e27-ca83-4081-a561-659da1c81ede\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #c2cda3\\\">$95K</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 198,\n          \"height\": 90,\n          \"marginOffset\": 10.296000000000006,\n          \"type\": \"text\",\n          \"groupId\": \"b34814a7-ff26-41f2-96cd-d9f93e432867\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 435,\n          \"id\": \"928bc426-93d8-4dea-879a-5464a19b8bf4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">CURRENT VALUE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 112,\n          \"height\": 20,\n          \"marginOffset\": -6.205000000000002,\n          \"type\": \"text\",\n          \"groupId\": \"c9b76bd8-2edc-4620-838f-26bc1847c7c3\"\n        },\n        {\n          \"x\": 166,\n          \"y\": 423,\n          \"id\": \"45c93f87-8ca6-4d07-ae97-59c7a037ea50\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #c2cda3\\\">$2.1B</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 198,\n          \"height\": 90,\n          \"marginOffset\": 10.296000000000006,\n          \"type\": \"text\",\n          \"groupId\": \"c9b76bd8-2edc-4620-838f-26bc1847c7c3\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"35837952-ae90-4deb-9e96-16b5fc960c18\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"539554c7-2730-41f4-b560-449f9367deee\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"afe8e732-19c6-4fd1-872f-3f7625575053\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c95dec3e-321a-4c4f-80e5-d2315b0e9c26\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"0782628d-01ad-4d09-b4c7-4e5942111815\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"928bc426-93d8-4dea-879a-5464a19b8bf4\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"09bfaf4c-1764-475e-9f62-531c3c6e664f\",\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"c56acbc9-44ae-49e0-81af-f8f78efe7ae3\": {\n          \"name\": \"Price\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b34814a7-ff26-41f2-96cd-d9f93e432867\": {\n          \"name\": \"Developed\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c9b76bd8-2edc-4620-838f-26bc1847c7c3\": {\n          \"name\": \"Value\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"998ffee2-a741-44d9-ac9c-2646e4e2f4c9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 141,\n          \"focalX\": 41.084522128870596,\n          \"focalY\": 64.74866081986856,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page08_image01.jpg\",\n            \"width\": 720,\n            \"height\": 960,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Turned-on filament bulb lights at bar counter\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1a0d08\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -10.5,\n          \"y\": -69,\n          \"width\": 433,\n          \"height\": 574,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d133ec87-270b-43d5-aa64-03535ceb74a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n          \"x\": 0,\n          \"y\": 496,\n          \"width\": 412,\n          \"height\": 177,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"68a5fc00-7b16-4be4-b040-d09c38e52856\",\n          \"type\": \"shape\",\n          \"groupId\": \"542bf51c-d2c9-4869-98cd-bff24ded23ff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">THE EDISON</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 524,\n          \"width\": 191,\n          \"height\": 48,\n          \"id\": \"da0525f9-3f7b-43a8-95a2-c7f5d9a2ad91\",\n          \"marginOffset\": 0.6706250000000011,\n          \"type\": \"text\",\n          \"groupId\": \"542bf51c-d2c9-4869-98cd-bff24ded23ff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 564,\n          \"id\": \"740671e3-99ec-4eb4-aa98-710cd5abcb78\",\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">You can drink in a Prohibition-era power plant.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 47,\n          \"marginOffset\": 5.637500000000003,\n          \"type\": \"text\",\n          \"groupId\": \"542bf51c-d2c9-4869-98cd-bff24ded23ff\"\n        },\n        {\n          \"x\": 11,\n          \"y\": 454,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 34,\n            \"vertical\": 9\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #212426\\\">02.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 89,\n          \"height\": 43,\n          \"marginOffset\": -0.9299999999999997,\n          \"groupId\": \"542bf51c-d2c9-4869-98cd-bff24ded23ff\",\n          \"id\": \"f479f3a1-edbd-48c4-bc3d-b720dd6e8362\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"d906deb5-07a1-4c81-acef-ae9668e431ac\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"542bf51c-d2c9-4869-98cd-bff24ded23ff\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"48b8e7b2-af13-48df-987d-609715bff9a0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People talking near building on road\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b292d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -0.5,\n          \"y\": -57.5,\n          \"width\": 413,\n          \"height\": 733,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c5740509-ce00-4843-be73-66e9f1598249\"\n        },\n        {\n          \"opacity\": 64,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.5 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1f9c3d22-4c82-4d75-97e1-1da7ffe1358e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">Now a beloved 1920s bar and club in what seems like decor, but is a true relic.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 92,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"a37f18db-dc92-46a2-9451-ce3c191c6aac\",\n          \"x\": 92,\n          \"y\": 498,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"x\": 92,\n          \"y\": 485,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"055af4d5-b873-44a6-8aa9-8cad16cefb7b\",\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1d648dfc-4946-41fc-be71-bf4dc8b1252f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"055af4d5-b873-44a6-8aa9-8cad16cefb7b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"3d418efe-e50d-41f2-a714-58feef1c0868\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3152b3a1-edce-423a-b83c-a160ead701bb\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page10_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1050,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Representational map of Los Angeles\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#272727\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -13,\n          \"y\": -86,\n          \"width\": 438,\n          \"height\": 633,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d0dc1dcc-2734-46a5-bc64-a454db8b4d2d\",\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 134,\n          \"focalX\": 51.584690762762044,\n          \"focalY\": 42.086233339419934,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page10_image02.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Bartender standing beside table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#272012\",\n            \"isExternal\": true\n          },\n          \"x\": -8,\n          \"y\": 299,\n          \"width\": 508,\n          \"height\": 375,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"35d3d4c7-e3c0-43b1-97ca-754fbd1d5043\",\n          \"type\": \"image\",\n          \"resizeWidth\": 236.73786,\n          \"resizeHeight\": 174.562\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3\\\">The Edison</span>\\n<span style=\\\"color: #c2cda3\\\">108 W 2nd Street</span>\\n<span style=\\\"color: #c2cda3\\\">Los Angeles, CA 90012</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 68,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"45128a01-03b9-4f0b-9a7f-ab387fcd80aa\",\n          \"x\": 166,\n          \"y\": 98,\n          \"type\": \"text\",\n          \"groupId\": \"30422657-3c15-4251-ac79-06a02597b17c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 135,\n          \"y\": 98,\n          \"width\": 24,\n          \"height\": 28,\n          \"sticker\": { \"type\": \"greenLocationPin\" },\n          \"id\": \"75d37d1f-8f8a-48ca-ae53-cc67b6015492\",\n          \"groupId\": \"30422657-3c15-4251-ac79-06a02597b17c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0235988d-ebec-4184-bde3-dae3d25a2a02\",\n          \"type\": \"effect-drop\",\n          \"targets\": [\"75d37d1f-8f8a-48ca-ae53-cc67b6015492\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c254b73e-be4d-4800-8079-50b35f4109e7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"45128a01-03b9-4f0b-9a7f-ab387fcd80aa\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"923f19aa-7356-49af-aa94-5615f92adb76\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"30422657-3c15-4251-ac79-06a02597b17c\": {\n          \"name\": \"Location\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d2ec1682-4983-4fe1-b649-77376bdfc8d1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 110,\n          \"focalX\": 50.068772511783756,\n          \"focalY\": 43.2064432829339,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page11_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1151,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People sitting on stadium chairs during golden hour\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#212730\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -24.5,\n          \"y\": -146,\n          \"width\": 461,\n          \"height\": 733,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"91a0f7ca-dc51-48ff-985b-136ab928d69c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n          \"x\": 0,\n          \"y\": 496,\n          \"width\": 412,\n          \"height\": 177,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f8939fe1-dcc3-4c30-a823-08d7b38542a6\",\n          \"type\": \"shape\",\n          \"groupId\": \"5edce6ce-6b75-40d0-92b3-56367439263b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">DODGER STADIUM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 532,\n          \"width\": 267,\n          \"height\": 48,\n          \"id\": \"78ad7e23-de8a-4584-8d8d-6172a730091a\",\n          \"marginOffset\": -17.20499999999999,\n          \"type\": \"text\",\n          \"groupId\": \"5edce6ce-6b75-40d0-92b3-56367439263b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 574,\n          \"id\": \"c8dddf2e-442d-4157-9987-b70f83a2b7d1\",\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">Dodger stadium is built on land teeming with Mexican history.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 308,\n          \"height\": 45,\n          \"marginOffset\": 5.637500000000003,\n          \"type\": \"text\",\n          \"groupId\": \"5edce6ce-6b75-40d0-92b3-56367439263b\"\n        },\n        {\n          \"x\": 11,\n          \"y\": 454,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 34,\n            \"vertical\": 9\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #212426\\\">03.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 89,\n          \"height\": 43,\n          \"marginOffset\": -0.9299999999999997,\n          \"groupId\": \"5edce6ce-6b75-40d0-92b3-56367439263b\",\n          \"id\": \"c70ff82b-2e24-4eb1-8adb-5260b8d07b6a\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"80c879ad-c817-4179-8201-17dda83fada3\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5edce6ce-6b75-40d0-92b3-56367439263b\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -10,\n          \"y\": -58,\n          \"width\": 413,\n          \"height\": 736,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"8b0daa5f-0b59-42f1-bfdf-5b388cf83aea\",\n          \"type\": \"image\",\n          \"scale\": 116,\n          \"focalX\": 53.591954022988496,\n          \"focalY\": 50.000000000000014,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:17:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Free stock photo of vintage photograph\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#636446\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 64,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.63 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"434407d5-7f17-4343-8f6b-cdeb27a1ae82\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">The area was once home to the most populous Mexican community in the city.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 92,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"a43a66b7-cc66-45d5-ab3f-8f163b77cb2d\",\n          \"x\": 98,\n          \"y\": 518,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"x\": 98,\n          \"y\": 505,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6db287ba-ad99-4955-a7a2-eedf438dd421\",\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"befc86b6-5d6d-4d91-9af5-fe6a8eacad55\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6db287ba-ad99-4955-a7a2-eedf438dd421\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"07bfde5c-b03f-43d6-994a-25ab968ea961\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"8b0daa5f-0b59-42f1-bfdf-5b388cf83aea\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"ecff7060-38c0-4e4c-8b05-a10b78fc935d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"a368083a-a94c-4e37-8543-64f9269e065b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"76ad546c-3a2f-4caa-82de-d73a4f94f6fd\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"baseColor\": \"#4c4c4c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page13_videobg.mp4\",\n            \"width\": 1364,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page13_videobg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 13,\n            \"lengthFormatted\": \"0:13\",\n            \"alt\": \"AERIAL Downtown Los Angeles with Dodger Stadium in the front - stock video\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"width\": 437,\n          \"height\": 1181,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"fcb9429b-ed44-435c-a3e1-f7baaf88095f\",\n          \"x\": -11.5,\n          \"y\": -281.5\n        },\n        {\n          \"opacity\": 64,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.63 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": 0,\n          \"y\": -57.5,\n          \"width\": 412,\n          \"height\": 733,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"552bd07c-6ee7-47b3-8638-5036552e7f45\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">It’s hard to imagine Los Angeles without the stadium, which now plays neighbor to bustling and diverse Eastside neighborhoods and families.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 163,\n          \"marginOffset\": 3.288999999999998,\n          \"id\": \"14adcf65-e231-4d2c-b472-98263fa75d51\",\n          \"x\": 98,\n          \"y\": 21,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"x\": 98,\n          \"y\": 8,\n          \"width\": 61,\n          \"height\": 3,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"68deaf59-a892-4c08-9ff6-1169b1e56faf\",\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a8ff0399-05a0-4290-be5c-3c1a4f7bc390\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"68deaf59-a892-4c08-9ff6-1169b1e56faf\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"a3804d63-15bf-4954-8374-69d9ac0e5041\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b7c2c8d7-bd86-44e5-a591-6afd93e830a0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Biryani\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1109,\n              \"des\": -656,\n              \"tAsc\": 1109,\n              \"tDes\": -656,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 656,\n              \"xH\": 563,\n              \"capH\": 758,\n              \"yMin\": -592,\n              \"yMax\": 1109,\n              \"hAsc\": 1109,\n              \"hDes\": -656,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #c2cda3; text-transform: uppercase\\\">READ MORE ABOUT LA</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 0,\n          \"width\": 292,\n          \"height\": 42,\n          \"id\": \"d6f2683c-c385-4afe-a38a-858d04286861\",\n          \"marginOffset\": -12.554999999999993,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"x\": 70,\n          \"y\": 529,\n          \"content\": \"<span style=\\\"font-weight: 900; color: #212426\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 50,\n          \"height\": 25,\n          \"marginOffset\": 1.34659090909091,\n          \"type\": \"text\",\n          \"groupId\": \"8da7acb9-c6a2-4187-9ea1-1f7d3dfdc604\",\n          \"id\": \"ada5063e-d952-489d-9f75-4b7a90f77089\"\n        },\n        {\n          \"x\": 138,\n          \"y\": 551,\n          \"id\": \"a635585b-7f9d-407a-abf3-496582e271de\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">Best Hotel pools in Los Angeles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 45,\n          \"marginOffset\": 1.4300000000000015,\n          \"type\": \"text\",\n          \"groupId\": \"8da7acb9-c6a2-4187-9ea1-1f7d3dfdc604\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:18:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page14_image02.jpg\",\n            \"width\": 720,\n            \"height\": 405,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Green palm tree near swimming pool during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#45493b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 70,\n          \"y\": 372,\n          \"width\": 271,\n          \"height\": 157,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3512c987-68f7-493c-ab8d-359d35d40f47\",\n          \"groupId\": \"8da7acb9-c6a2-4187-9ea1-1f7d3dfdc604\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-03T05:18:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/los-angeles-city-guide/page14_image01.jpg\",\n            \"width\": 720,\n            \"height\": 405,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Silhouette of airplane flying during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c69e99\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 70,\n          \"y\": 82,\n          \"width\": 271,\n          \"height\": 157,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9cfc5b4f-2595-4c27-a5fb-87fb21376fa2\",\n          \"groupId\": \"6a3832da-11ee-4b0b-a484-6e2737f3324e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 194, \"g\": 205, \"b\": 163 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"x\": 70,\n          \"y\": 238,\n          \"id\": \"bd1b08a8-515a-4e8c-9809-f252945c7f3f\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #212426\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 50,\n          \"height\": 25,\n          \"marginOffset\": 1.34659090909091,\n          \"type\": \"text\",\n          \"groupId\": \"6a3832da-11ee-4b0b-a484-6e2737f3324e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 138,\n          \"y\": 259,\n          \"id\": \"2567e4e4-cf19-4014-adf4-9df5a9ee6bb7\",\n          \"content\": \"<span style=\\\"color: #c2cda3\\\">What to Pack for Los Angeles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 47,\n          \"marginOffset\": 1.4300000000000015,\n          \"type\": \"text\",\n          \"tagName\": \"h3\",\n          \"groupId\": \"6a3832da-11ee-4b0b-a484-6e2737f3324e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"11a28c0b-446b-4588-8311-420e8511f58e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2567e4e4-cf19-4014-adf4-9df5a9ee6bb7\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"98ddc55e-f3b1-4ba3-a93d-e7a34775408e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a635585b-7f9d-407a-abf3-496582e271de\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 33, \"g\": 36, \"b\": 38 } },\n      \"type\": \"page\",\n      \"id\": \"88b39507-b25b-4119-870f-1c2371cbbded\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"6a3832da-11ee-4b0b-a484-6e2737f3324e\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8da7acb9-c6a2-4187-9ea1-1f7d3dfdc604\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/magazine-article/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/magazine-article/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'magazine-article',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Magazine Article', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Future', 'template keyword', 'web-stories'),\n    _x('Presentation', 'template keyword', 'web-stories'),\n    _x('Magazine', 'template keyword', 'web-stories'),\n    _x('Gray', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('School Bus Yellow', 'color', 'web-stories'),\n      color: '#ffdb00',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gentle Gray', 'color', 'web-stories'),\n      color: '#c4c4c4',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its rounded font, boxy images and yellow accents, this template is just like your good old tech magazine, but in a visual story format. Share the latest news, write opinionated pieces, explainers, product reviews and much more.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/magazine-article/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/magazine-article/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"17192280-65fc-4228-bef6-bf4267f7c111\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"23744c49-09d3-48aa-994e-7f8f1309c2df\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#1e3e50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image01.jpg\",\n            \"width\": 540,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Airplane wing towards clouds\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -15,\n          \"y\": -124,\n          \"width\": 380,\n          \"height\": 582,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b6649c89-30bc-4a98-8fda-aca16cbe9789\"\n        },\n        {\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -172,\n          \"y\": -69,\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9041cb86-bedc-4205-88d6-1ee2b9f8f4c0\"\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"id\": \"1aafefb6-a378-4de6-9c06-5366f8c4d53d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } },\n          \"type\": \"shape\",\n          \"width\": 366,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.29 },\n                \"position\": 0.34\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 366,\n          \"height\": 515,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bddf496a-8bb8-4fe4-bd60-0d29624cc059\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 364,\n          \"y\": 458,\n          \"width\": 412,\n          \"height\": 217,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e39615c4-be0a-45e8-abb1-77a17312c38e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em\\\">Matt Johnson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 394,\n          \"width\": 200,\n          \"height\": 19,\n          \"id\": \"eb0caa01-f3f2-4732-ba5e-c443975f14eb\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 69,\n          \"y\": -80,\n          \"width\": 333,\n          \"height\": 475,\n          \"sticker\": { \"type\": \"flightPath\" },\n          \"id\": \"e402376a-138c-4ba7-8093-d4cd607d1b80\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 447,\n          \"id\": \"3178fe32-e693-4ac6-bd35-76543bf19ded\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Inside the future of aviation technology</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 295,\n          \"height\": 169,\n          \"marginOffset\": 3.6549999999999976\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"0ae62c1d-aeb1-4308-a532-dc00885410d2\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4ad3b752-13eb-4ddf-921e-26ccab6774ac\"\n        },\n        {\n          \"x\": -172,\n          \"y\": -69,\n          \"id\": \"5b9ca7af-b39b-432d-83ce-0860ad26e2b4\",\n          \"opacity\": 5,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 272,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7a752561-e177-4b00-ac38-8f35773a2ce4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 63.86975827924803,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page02_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Scenic view of sea against sky during sunset\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#112242\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": -65,\n          \"width\": 366,\n          \"height\": 392,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e360b567-81f3-4ce1-a96b-642f70a30cff\",\n          \"resizeWidth\": 153.78641,\n          \"resizeHeight\": 166.203\n        },\n        {\n          \"opacity\": 2,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0da85227-1992-4345-becd-0a1eee5bc1b1\",\n          \"x\": -172,\n          \"y\": -69\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Step inside what the future of air travel could entail as we design </span><span style=\\\"font-weight: 300\\\">smarter and more comfortable </span><span style=\\\"font-weight: 300\\\">experiences for the everyday traveler. Welcome to the Overture.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 437,\n          \"width\": 327,\n          \"height\": 128,\n          \"id\": \"7bc86bd3-6677-48ff-a233-e9fed282a812\",\n          \"marginOffset\": 0.84375\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"7c52ab9e-0b07-487c-8f22-4c15c478687b\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"f1e2f2e2-dd79-4ecd-8866-8c0e24fe1388\",\n          \"scale\": 116,\n          \"focalX\": 46.40804597701149,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Grey textile\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#21242f\",\n            \"isExternal\": true\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 204, \"g\": 204, \"b\": 204, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": -6.5,\n          \"y\": -57,\n          \"width\": 425,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"31cd45b4-2ef8-432e-8fe0-016b8de056fb\"\n        },\n        {\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"26c5428d-7c06-4b09-bff4-a2cb52716308\",\n          \"x\": -172,\n          \"y\": -69\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Special materials help prevent bacterial buildup. This is especially useful in saving time between flight cleanups.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 108,\n          \"marginOffset\": 4.299999999999997,\n          \"id\": \"2b9d8f99-69fe-45e2-95eb-84c0e1044fb9\",\n          \"x\": 47,\n          \"y\": 494\n        },\n        {\n          \"x\": 47,\n          \"y\": 399,\n          \"id\": \"8acb5e60-f288-46fd-8ddd-593b2de57bd1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 39,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Antimicrobial finishes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 85,\n          \"marginOffset\": -3.144999999999996\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 219, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 46.5,\n          \"y\": 380,\n          \"width\": 319,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9f7d6608-b941-40fb-8fb1-b61e0c8f84f4\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 72,\n          \"y\": -375,\n          \"width\": 417,\n          \"height\": 595,\n          \"sticker\": { \"type\": \"flightPath\" },\n          \"id\": \"371e6077-5535-49d0-89ba-ac60672cc6b3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"953d94aa-b632-4beb-bddc-030988d12d82\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9f7d6608-b941-40fb-8fb1-b61e0c8f84f4\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e3612676-abc3-4808-bee0-82110dac8984\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"371e6077-5535-49d0-89ba-ac60672cc6b3\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 6000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f2129a5e-d9ed-4c27-b41c-b33752fb760c\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"f1e2f2e2-dd79-4ecd-8866-8c0e24fe1388\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"1550d2e0-77cb-4fdf-b7e6-174fec5272d0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"0102ac7c-7d8b-4837-962c-948181dde864\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"0c866aa2-42dd-40d0-aff2-1ce363849103\",\n          \"type\": \"image\",\n          \"scale\": 119,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black and gray laptop computer\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#242423\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": -6.5,\n          \"y\": -58,\n          \"width\": 425,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dbee76b3-4b16-4a14-ba62-3539856ba761\",\n          \"type\": \"shape\"\n        },\n        {\n          \"x\": -172,\n          \"y\": -69,\n          \"id\": \"ff7714d7-5094-48c7-83d6-7d9b71cfdb76\",\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">From NASA to the interiors of government official vehicles, these fabrics will become </span><span style=\\\"font-weight: 300; color: #fff\\\">the </span><span style=\\\"font-weight: 300; color: #fff\\\">industry standard.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 102,\n          \"marginOffset\": 4.299999999999997,\n          \"id\": \"82c58c80-002c-4a5d-a050-12d7337f6aef\",\n          \"x\": 47,\n          \"y\": 515,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9c786381-ffd9-4a19-85d9-a547d65f514d\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"0c866aa2-42dd-40d0-aff2-1ce363849103\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 6000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d765d573-5728-4e9a-ad6f-63d2e26af727\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"2b9ab38b-70c2-4c35-9fb4-f91753c15c5c\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f8aead57-8349-49f5-bad5-ed380cc2cdbf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page05_image02.jpg\",\n            \"width\": 720,\n            \"height\": 647,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Dark photo of metal mesh screen\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#0d0d0d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 280,\n          \"width\": 412,\n          \"height\": 395,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9546cc42-0561-4ea9-87c2-5f8dfe680c2a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": -4.5,\n          \"y\": 280,\n          \"width\": 421,\n          \"height\": 395,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"de32848d-53df-4723-8b98-8cf69c2b23ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page05_image01.jpg\",\n            \"width\": 720,\n            \"height\": 575,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Close up colors detail fabric\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#525252\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 341,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9b9205cd-3f5e-4b8f-9b49-203df3515fdc\"\n        },\n        {\n          \"x\": -7.5,\n          \"y\": -57,\n          \"id\": \"318a9c13-6893-4d4f-a02c-9814f672f10c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 427,\n          \"height\": 341,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">They are often made of</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">microfibers (synthetic fibers</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">up to 60 times finer than</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">human hair).</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 102,\n          \"marginOffset\": 4.299999999999997,\n          \"type\": \"text\",\n          \"id\": \"7687c5fa-9ed9-4eaa-97b8-859b26f0b1ae\",\n          \"x\": 47,\n          \"y\": 520\n        },\n        {\n          \"x\": 47,\n          \"y\": 160,\n          \"id\": \"4650e416-ead9-4d42-b97e-85d952a1e87b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Elastic but strong, spider silk is equal to steel in tensile strength and much tougher than carbon fiber.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 327,\n          \"height\": 102,\n          \"marginOffset\": 2.299999999999997,\n          \"type\": \"text\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"a77e1bb0-0924-422c-82f3-dc25e8ed4710\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f3d1eb1f-c93a-4c94-9456-9bbf0de9c539\",\n          \"type\": \"image\",\n          \"scale\": 111,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding smartphone riding airplane\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2e2f2d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": -6.5,\n          \"y\": -57,\n          \"width\": 425,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cc0b5576-1442-4601-bc31-b7b6c954b154\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a6c27e0c-d1a5-4265-b8a7-50e0bad0eb0f\",\n          \"x\": -172,\n          \"y\": -69,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">We could make air travel more comfortable and a better experience for all.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 80,\n          \"marginOffset\": 4.299999999999997,\n          \"id\": \"bff428c7-9dd2-47f5-a56d-eeff5ece7a2e\",\n          \"x\": 47,\n          \"y\": 494,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 39,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 399,\n          \"id\": \"e0dd66a2-ecc7-4478-b669-07da11b371e6\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Restructured Seating</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 85,\n          \"marginOffset\": -3.144999999999996,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 219, \"b\": 0 } },\n          \"x\": 46.5,\n          \"y\": 380,\n          \"width\": 319,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"da6036aa-ab9d-4db6-944d-8df3cf4fdd15\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 11,\n          \"y\": -160,\n          \"width\": 288,\n          \"height\": 411,\n          \"sticker\": { \"type\": \"flightPath\" },\n          \"id\": \"7bfb15b9-715d-4524-90bf-b61c2b613082\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5ee537f6-d157-4ab7-ab86-e3e17f90e221\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"f3d1eb1f-c93a-4c94-9456-9bbf0de9c539\"]\n        },\n        {\n          \"id\": \"a1be1667-75c2-49ee-9335-6525c358193f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"da6036aa-ab9d-4db6-944d-8df3cf4fdd15\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9380293e-058e-4063-9f9f-bc45ade6be67\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8df77fe2-ca3a-4e65-958d-1205ecb74b9d\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bc92519b-c122-410a-807e-e0259a3379f9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 26,\n          \"width\": 329,\n          \"height\": 46,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"427ea69f-cd46-4377-9bff-4cc498b923bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page07_image01.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People inside commercial air plane\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c2c8d1\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 72,\n          \"width\": 392,\n          \"height\": 254,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a3f2d751-83b5-4a3a-b39c-8cc26c2d5a83\"\n        },\n        {\n          \"opacity\": 2,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"type\": \"image\",\n          \"id\": \"f3e1b71f-eda2-4d37-8e62-94a0e9eb2b4f\",\n          \"x\": -172,\n          \"y\": -69\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Spacious cabin design also contributes to easy maintenance, not just safety. Comfortable seats enable window view and aisle access for better convenience on longer flights.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 394,\n          \"width\": 310,\n          \"height\": 153,\n          \"id\": \"1dba92e9-a7a4-4fa8-84b8-1ddfd6e4a0d2\",\n          \"marginOffset\": 0.7593749999999986\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e0ee0137-5860-4c8a-bf79-73956394ec1c\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e737a225-9236-4e70-88ec-8d0977eaebd5\",\n          \"type\": \"image\",\n          \"scale\": 119,\n          \"focalX\": 38.26335877862595,\n          \"focalY\": 49.888179866412216,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:13:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man looking on his sitting on plane seat\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#231f1e\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": -7.5,\n          \"y\": -57,\n          \"width\": 427,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"10a746a2-5977-4a25-905f-57fa553bb7a3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"x\": -172,\n          \"y\": -69,\n          \"id\": \"41f7b56c-4794-4178-b2fa-ea12e54553f2\",\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Comfort and safety will become the standard expectations of modern travel.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 76,\n          \"marginOffset\": 4.299999999999997,\n          \"id\": \"c7749f15-f6cd-4d6e-9007-fcd1b14997c0\",\n          \"x\": 45,\n          \"y\": 517,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"32d99779-43ca-4527-92b2-cc5cf4765058\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"e737a225-9236-4e70-88ec-8d0977eaebd5\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 6000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"ff0ab1ea-7bea-4443-bafc-744307feacdd\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"0dbb1f34-f4b6-49fa-a928-9fc7244fb3d7\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"697d48f7-1b05-4cd3-ba36-d3954f312d5b\",\n          \"type\": \"image\",\n          \"scale\": 174,\n          \"focalX\": 50,\n          \"focalY\": 62.122844827586185,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:14:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Inside view of building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#452d38\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": -9.5,\n          \"y\": -57,\n          \"width\": 431,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b100334c-3616-4a8f-b81d-fac5749c0c6f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 6,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"78c2cfed-6c1a-4174-93a1-eee6c9c9d120\",\n          \"x\": -172,\n          \"y\": -71,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">En-route to destination features within airports and shuttles will steer clear of anything high-touch.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 289,\n          \"height\": 108,\n          \"marginOffset\": 3.8699999999999974,\n          \"id\": \"8473fb01-5ac0-4658-ad01-aec4bd6cea0b\",\n          \"x\": 47,\n          \"y\": 497,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 39,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 315,\n          \"id\": \"0bc8aea9-693f-47c3-8a21-98ded332dc6e\",\n          \"content\": \"<span style=\\\"color: #fff\\\">High-tech,&nbsp;</span>\\n<span style=\\\"color: #fff\\\">low-touch airport architecture</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 166,\n          \"marginOffset\": -3.144999999999996,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 219, \"b\": 0 } },\n          \"x\": 46.5,\n          \"y\": 303,\n          \"width\": 319,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"25923877-e6ef-49c9-8787-42348d5e0809\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -17,\n          \"y\": -50,\n          \"width\": 288,\n          \"height\": 411,\n          \"sticker\": { \"type\": \"flightPath\" },\n          \"id\": \"2c2a0de2-4fa0-4e6b-869d-ea18f3d7df8c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5a3a26fe-beb5-4c17-861f-a1ecb5dea107\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"697d48f7-1b05-4cd3-ba36-d3954f312d5b\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 6000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d95e288d-2b57-4f8d-aef4-43a4826f6f0c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2c2a0de2-4fa0-4e6b-869d-ea18f3d7df8c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 6000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1711b5e6-c124-477b-bf00-73df70ed005a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"25923877-e6ef-49c9-8787-42348d5e0809\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"40e398c6-7f71-4ea7-9a30-5c414ecbaec2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"abd99b05-dfda-4b36-9fed-87787675f9ff\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4f319d85-0384-4fb5-9184-93ec475d4f06\",\n          \"type\": \"image\",\n          \"scale\": 117,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:14:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People on hallway\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d2d3d0\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 2,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2a6ea89a-73af-411e-a50f-ef0f39328b94\",\n          \"x\": -172,\n          \"y\": -69,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300\\\">It all contributes to a greater sense of ease and freedom as travelers move about space en route to different cultural spaces.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 327,\n          \"height\": 102,\n          \"marginOffset\": 4.729999999999997,\n          \"id\": \"a506f0e0-2f63-461a-bbd5-047b9942c24e\",\n          \"x\": 48,\n          \"y\": 517,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"087fc2e6-d4a9-421e-a6e3-5712931f084e\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"4f319d85-0384-4fb5-9184-93ec475d4f06\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 6000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2e77f5f5-f77f-45a7-9adc-8b2d6eac66d1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"3faf3803-cb97-477a-9b00-7c9bfece7f39\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"427100f5-f6a3-4b6f-897d-8a6a95af38a7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 50,\n          \"height\": 534,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e1c2f091-dd10-4a1c-83d5-ffccefc42485\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 51.75759190177656,\n          \"focalY\": 49.91485947120967,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:14:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page11_image01.jpg\",\n            \"width\": 720,\n            \"height\": 481,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People in station\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3a2b20\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 316,\n          \"height\": 261,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e2e27e8c-8675-46a4-b37d-93e6dd975e71\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:14:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page11_image02.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People walking on white tiled floor\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b1aca8\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 204,\n          \"width\": 365,\n          \"height\": 273,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a570018d-bc0a-468e-a33d-2bfd85c143aa\"\n        },\n        {\n          \"opacity\": 2,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:12:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page01_image02.png\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White noise texture\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e4\",\n            \"isExternal\": true\n          },\n          \"width\": 756,\n          \"height\": 756,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"type\": \"image\",\n          \"id\": \"a97a35d2-66d3-4193-9f7c-7e9773206859\",\n          \"x\": -172,\n          \"y\": -69\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Safety, comfort, and autonomy work together in the future of air travel. It’s technology working in harmony with its environment.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 327,\n          \"height\": 101,\n          \"marginOffset\": 4.729999999999997,\n          \"type\": \"text\",\n          \"id\": \"86bb7ebb-0047-429f-a9f4-f5d9144ec79c\",\n          \"x\": 48,\n          \"y\": 517\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"22674c47-4f84-40cb-9f41-587cb8d6afd2\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"aeb47068-18a2-44ce-9c16-f7d903aa4071\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": -7.5,\n          \"y\": -57,\n          \"width\": 427,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5630d2ef-742a-421f-8177-f19a0a07d349\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T15:14:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/magazine-article/page12_image01.jpg\",\n            \"width\": 540,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black and white business computer connection\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4c3c4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 20,\n          \"y\": 0,\n          \"width\": 372,\n          \"height\": 459,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3d203536-39ea-4000-b149-86cb6ad7c222\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ffdb00; letter-spacing: 0.01em; text-transform: uppercase\\\">More Stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 489,\n          \"width\": 107,\n          \"height\": 17,\n          \"id\": \"13749516-1650-4bbd-93c7-d7120175250f\",\n          \"marginOffset\": 3.224999999999998,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Tech gadgets for modern air travel</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 64,\n          \"marginOffset\": 2.299999999999997,\n          \"type\": \"text\",\n          \"id\": \"c5aba7cf-ef50-4594-a3ff-a643a5776d07\",\n          \"x\": 47,\n          \"y\": 520,\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"cede7b34-0a4c-4205-90cc-8f9411c96d01\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/modernist-travel-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/modernist-travel-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'modernist-travel-guide',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Modernist Travel Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Rounded', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Tomato Sauce Red', 'color', 'web-stories'),\n      color: '#B51006',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White Smoke', 'color', 'web-stories'),\n      color: '#f1f1f1',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Graphite Gray', 'color', 'web-stories'),\n      color: '#2e2e2e',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Inspired by the clean and minimalistic look of modern architecture, this template is great for creating stories about urban and city tourism. Create sightseeing guides, give out information about local buildings and attractions and more.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/modernist-travel-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/modernist-travel-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7ba32155-8890-41dc-9274-00c12b98ba50\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#d3cdc7\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page01_image01.png\",\n            \"width\": 720,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Rover near road and buildings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -104,\n          \"y\": 247,\n          \"width\": 469,\n          \"height\": 469,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"080cbd42-c365-40b9-b18c-b3a66c01571a\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"type\": \"shape\",\n          \"x\": 201,\n          \"y\": 413,\n          \"width\": 343,\n          \"height\": 343,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e318f391-b0a8-402c-8a12-200e1c3b6c83\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #2e2e2e; text-transform: uppercase\\\">The creative boss guide to travel</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 23,\n          \"width\": 293,\n          \"height\": 159,\n          \"id\": \"ff0f3ff9-40aa-4f4e-b47a-b5a3e4815d37\",\n          \"marginOffset\": -22.874999999999993\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #292929\\\">John Deck</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 190,\n          \"width\": 200,\n          \"height\": 19,\n          \"id\": \"3e5526ca-7072-4b35-b576-b40026c28fed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 206,\n          \"y\": 250,\n          \"width\": 195,\n          \"height\": 195,\n          \"sticker\": { \"type\": \"linedCircle\" },\n          \"id\": \"992268d0-90a5-45ea-80de-35dbb4bd00e3\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"4dc45791-28b8-416a-b74a-da6ddc409a14\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"0c195c6a-8d92-44ae-88e6-be8b70f0e607\"\n        },\n        {\n          \"x\": 231,\n          \"y\": -76,\n          \"id\": \"00e1f6ba-47f6-430e-aaba-d57d3e48f6e3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 293,\n          \"height\": 293,\n          \"mask\": { \"type\": \"circle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": -94,\n          \"y\": 138,\n          \"width\": 283,\n          \"height\": 283,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"9be5bc00-7f84-49c4-ba2a-10c434e48279\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 218,\n          \"height\": 218,\n          \"sticker\": { \"type\": \"linedCircle\" },\n          \"id\": \"a7a1826f-8bed-4890-9b02-ffbbcbba0a27\",\n          \"x\": 253,\n          \"y\": 199\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image03.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man wearing green polo shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4b5ac\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 56,\n          \"y\": 247,\n          \"width\": 143,\n          \"height\": 143,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4ab90559-c52a-4975-90a9-4fecb8f07ac6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image01.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Men's gray crew-neck long-sleeve shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#605553\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 86,\n          \"y\": 31,\n          \"width\": 133,\n          \"height\": 133,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1d8dafd0-e622-48ec-875b-7549d55aef94\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image02.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing black shirt standing in front of red wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#da9688\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 232,\n          \"y\": 179,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4eb87c16-eb0f-4d26-8d7b-1e1068653c7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">The Crew</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 468,\n          \"width\": 145,\n          \"height\": 33,\n          \"id\": \"e22da101-952c-4c7f-b51f-0744cfc57cd1\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 503,\n          \"id\": \"5aadc105-735c-471a-954f-26aa30f31c9a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #292929\\\">Meet our 3 favorite bosses, brand owners and creatives. These insiders let us in on their favorite places to go in the world.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 90,\n          \"marginOffset\": -18.91000000000001\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1ca3fea9-483f-4121-b81f-6cc3fe31e78c\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"00e1f6ba-47f6-430e-aaba-d57d3e48f6e3\"]\n        },\n        {\n          \"id\": \"785104b7-5420-43d1-8b92-1456bf961aa9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9be5bc00-7f84-49c4-ba2a-10c434e48279\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5aaa3f62-7b12-4fe9-955d-537ffb5c8d67\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a7a1826f-8bed-4890-9b02-ffbbcbba0a27\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"606df260-8e5f-47c0-9a8d-01f4b3d8797d\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"2fd050ff-3949-4327-8511-d20857e02378\",\n          \"scale\": 104,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People inside building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c3c3c3\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 425,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"eacac07c-e1b5-443b-b8d7-32e0c3601400\",\n          \"x\": -6.5,\n          \"y\": 481,\n          \"groupId\": \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d055a309-d0a1-47d7-a5cb-0ea3c695af43\",\n          \"x\": -4.5,\n          \"y\": 481,\n          \"groupId\": \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\"\n        },\n        {\n          \"x\": -79,\n          \"y\": 474,\n          \"id\": \"e3dd68eb-97a8-48df-9809-7daf889c698d\",\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"type\": \"shape\",\n          \"width\": 374,\n          \"height\": 374,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Claire W.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 145,\n          \"height\": 20,\n          \"id\": \"7fade586-09fa-4467-a911-2f9aab170755\",\n          \"x\": 47,\n          \"y\": 577,\n          \"groupId\": \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.94); letter-spacing: 0.02em; text-transform: uppercase\\\">Senior Brand Strategist</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 15,\n          \"marginOffset\": -18.91000000000001,\n          \"id\": \"1aebd39f-0965-4161-9dcc-5e6708a6ac51\",\n          \"x\": 47,\n          \"y\": 600,\n          \"groupId\": \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image02.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing black shirt standing in front of red wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#da9688\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": 437,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3b5c5069-ec14-430c-9f6a-83719ac8fe1d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"type\": \"shape\",\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2a1c335c-39ca-4e06-b697-0654ecf1ff45\",\n          \"x\": -4.5,\n          \"y\": -57,\n          \"groupId\": \"ce9914e2-da16-4f01-b40a-9a6682c9e462\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"type\": \"shape\",\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4477159a-81fb-410c-9b53-23487b42c9ad\",\n          \"x\": -4.5,\n          \"y\": -57,\n          \"groupId\": \"ce9914e2-da16-4f01-b40a-9a6682c9e462\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"type\": \"shape\",\n          \"width\": 427,\n          \"height\": 427,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"96896c17-84dc-4655-9070-a1e8f3a2bf1b\",\n          \"x\": -62,\n          \"y\": -227,\n          \"groupId\": \"ce9914e2-da16-4f01-b40a-9a6682c9e462\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 0,\n          \"id\": \"89f48602-1fd4-490e-88b9-2714ebc39ec5\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Louisiana Art Museum</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 61,\n          \"marginOffset\": -4.899999999999999,\n          \"groupId\": \"ce9914e2-da16-4f01-b40a-9a6682c9e462\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 79,\n          \"id\": \"43bcc68b-e4ef-48ae-9545-0f2d7e907406\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Copenhagen</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 20,\n          \"marginOffset\": -18.91000000000001,\n          \"groupId\": \"ce9914e2-da16-4f01-b40a-9a6682c9e462\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"125a2999-95da-4cdc-9c2d-152cb0323b1d\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"2fd050ff-3949-4327-8511-d20857e02378\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c7ba8f18-4a75-4175-a6b4-efaab898de64\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f7e9a9fe-bd08-4d78-8258-187bc4b050ec\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"a2581183-0eb2-4baa-a44a-e0a8d7897b20\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ce9914e2-da16-4f01-b40a-9a6682c9e462\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c01223b4-b2a8-4133-b4f9-76270773a391\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page04_image01.jpg\",\n            \"width\": 361,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Low angle photography of a building at daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#22819d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 34,\n          \"y\": 33,\n          \"width\": 169,\n          \"height\": 226,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"aeb63a1f-ee1a-4bf6-8f66-3acf50601328\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page04_image02.jpg\",\n            \"width\": 320,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White concrete building during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#78acce\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 210,\n          \"y\": 0,\n          \"width\": 173,\n          \"height\": 259,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0e348d12-6a35-4660-a6ed-94618b8266ae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page04_image03.jpg\",\n            \"width\": 480,\n            \"height\": 310,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White concrete building with chairs\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bdc1c4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 104,\n          \"y\": 267,\n          \"width\": 278,\n          \"height\": 179,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f35632fd-95e0-4d0c-83e9-b6be9da732e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #292929\\\">This place challenges the notions about what art should be. It’s a great place for inspiration and to introduce something fresh to your creative mind.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 280,\n          \"height\": 122,\n          \"marginOffset\": 3.375,\n          \"id\": \"9f0dcb16-c292-4289-bb31-88941eb19904\",\n          \"x\": 67,\n          \"y\": 487\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"dca61177-1921-44a6-8347-4c88b991394d\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"22745ce6-2c53-454d-9de7-4e89c544983a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page05_image01.png\",\n            \"width\": 587,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of cityscape during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#afb7b7\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -41,\n          \"y\": -195,\n          \"width\": 471,\n          \"height\": 578,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d732c627-01af-43f2-9639-742bf03cbd28\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Louisiana Art Museum</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 33,\n          \"marginOffset\": -5.25,\n          \"id\": \"7034f05b-4c44-4f96-8178-56c787e85513\",\n          \"x\": 47,\n          \"y\": 420\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #292929\\\">Gl. Strandvej 13</span>\\n<span style=\\\"color: #292929\\\">3050 Humlebæk</span>\\n<span style=\\\"color: #292929\\\">Denmark</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 75,\n          \"marginOffset\": 3.8249999999999957,\n          \"id\": \"273aed33-5276-4d3f-9675-42aa560cca86\",\n          \"x\": 47,\n          \"y\": 466\n        },\n        {\n          \"x\": 48,\n          \"y\": 572,\n          \"id\": \"414d9609-a339-40e3-8b13-537531b8addf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 107,\n            \"vertical\": 15\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"width\": 316,\n          \"height\": 48,\n          \"marginOffset\": 4.225,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 41, \"g\": 41, \"b\": 41 } }\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"feb887c6-b277-4dfe-81d8-07b202fad804\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"414d9609-a339-40e3-8b13-537531b8addf\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"4d233f88-21b3-4859-a478-b7140b212d93\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"43786611-2f24-4c21-a826-7fb0926a1b9c\",\n          \"type\": \"image\",\n          \"scale\": 107,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of city buildings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#342c27\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": -6.5,\n          \"y\": 481,\n          \"id\": \"67e051f9-9d52-47bb-87bf-84b9e4c2a165\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 425,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"x\": -9.5,\n          \"y\": 481,\n          \"width\": 431,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"eb3869c4-16c2-4afa-97a8-a734a30f29cb\",\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"x\": -79,\n          \"y\": 474,\n          \"id\": \"b6177518-38a2-4169-ae85-1302fe7d701c\",\n          \"width\": 374,\n          \"height\": 374,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image03.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man wearing green polo shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4b5ac\",\n            \"isExternal\": true\n          },\n          \"x\": 47,\n          \"y\": 437,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b34e7bf4-12fb-4a12-b666-56dba47c7f60\",\n          \"type\": \"image\",\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Matt F.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 145,\n          \"height\": 21,\n          \"id\": \"c1a1a58f-deb6-482f-9d80-fca45ad17b40\",\n          \"x\": 47,\n          \"y\": 577,\n          \"type\": \"text\",\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.94); letter-spacing: 0.02em; text-transform: uppercase\\\">Chief Creative Officer</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 15,\n          \"marginOffset\": -18.91000000000001,\n          \"id\": \"96d3c326-c129-4798-99ff-c8282a7d1d8e\",\n          \"x\": 47,\n          \"y\": 600,\n          \"type\": \"text\",\n          \"groupId\": \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\"\n        },\n        {\n          \"x\": -5.5,\n          \"y\": -57,\n          \"id\": \"7b271df4-15c4-451c-8586-4e41aca5b525\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"type\": \"shape\",\n          \"width\": 423,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"69f2a91f-4839-44cd-9073-05d3ed863326\"\n        },\n        {\n          \"x\": -5.5,\n          \"y\": -57,\n          \"id\": \"2a8911c7-ddc4-4159-83aa-70b3ea75f513\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"type\": \"shape\",\n          \"width\": 423,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"69f2a91f-4839-44cd-9073-05d3ed863326\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"width\": 427,\n          \"height\": 427,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"3a25f42d-b4e0-4d20-81a9-87d86ff36165\",\n          \"x\": -62,\n          \"y\": -227,\n          \"type\": \"shape\",\n          \"groupId\": \"69f2a91f-4839-44cd-9073-05d3ed863326\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 0,\n          \"id\": \"9d8a9206-b76c-4f93-b9db-a67bfb2146c7\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Gramercy </span>\\n<span style=\\\"font-weight: 800; color: #fff\\\">Park Hotel</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 61,\n          \"marginOffset\": -4.899999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"69f2a91f-4839-44cd-9073-05d3ed863326\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 79,\n          \"id\": \"e3380b21-4b64-406c-84ea-1c9266e3dc8c\",\n          \"content\": \"<span style=\\\"color: #fff\\\">New York City</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 20,\n          \"marginOffset\": -18.91000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"69f2a91f-4839-44cd-9073-05d3ed863326\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bede0a0c-86c3-454c-9b4d-fbbe250926b6\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"43786611-2f24-4c21-a826-7fb0926a1b9c\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b75999ab-bdb8-4bcd-a6f7-be30a81f3f13\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e01312a7-e412-4d17-9efe-a3067532eb26\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"4afecb17-f9e6-4eb5-9982-046a9a3282e8\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"69f2a91f-4839-44cd-9073-05d3ed863326\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8a73cc62-8cfc-4e9a-bcb7-6385aa087b59\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #292929\\\">The NY Hotel's creative flair can be found in each of its 190 guest rooms and suites, which offer a unique composition of colors, textures and a rare collection of art, photographs and objects.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 277,\n          \"height\": 138,\n          \"marginOffset\": 3.375,\n          \"id\": \"fa848205-c5e5-41cb-8a8e-1d4b9129c66d\",\n          \"x\": 48,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page07_image02.jpg\",\n            \"width\": 402,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Lighted brown and black uplight chandelier\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#34190d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 210,\n          \"y\": 224,\n          \"width\": 173,\n          \"height\": 207,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1d1f7c77-fe49-4486-bef5-0b9546061e0b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page07_image01.jpg\",\n            \"width\": 319,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman holding candelabra statue\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#492513\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 35,\n          \"y\": 175,\n          \"width\": 170,\n          \"height\": 256,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b60de5c4-fbbf-4afb-9dce-0fbdc979ef29\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page07_image03.jpg\",\n            \"width\": 480,\n            \"height\": 249,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding candlelabara statue\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cb723d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 33,\n          \"y\": 436,\n          \"width\": 348,\n          \"height\": 180,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6ea197b2-c57c-4818-8178-4a8e62d4bca6\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"ff41af54-caa6-43c7-aafe-14f1711b8c2b\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c626f116-d61c-4bcb-9921-b1e6583011e7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Gramercy Park Hotel</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 33,\n          \"marginOffset\": -5.25,\n          \"id\": \"5a4c47c0-797e-409c-a7b9-c21d036c2138\",\n          \"x\": 47,\n          \"y\": 420,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #292929\\\">2 Lexington Ave,&nbsp;</span>\\n<span style=\\\"color: #292929\\\">New York,&nbsp;NY&nbsp;</span>\\n<span style=\\\"color: #292929\\\">10010</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 71,\n          \"marginOffset\": 3.8249999999999957,\n          \"id\": \"a52af929-77c4-4e49-8683-cb182ed61dae\",\n          \"x\": 47,\n          \"y\": 466,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page08_image01.png\",\n            \"width\": 546,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Aerial photography of city buildings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#322822\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -17,\n          \"y\": -206,\n          \"width\": 446,\n          \"height\": 589,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8f411f1e-9797-464f-bc1e-08ff9e89d0ad\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 572,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 107,\n            \"vertical\": 15\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"width\": 316,\n          \"height\": 48,\n          \"marginOffset\": 4.225,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 41, \"g\": 41, \"b\": 41 } }\n          },\n          \"id\": \"eedced71-7d76-4098-b51c-9668088b982c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"eedced71-7d76-4098-b51c-9668088b982c\"],\n          \"id\": \"d91ca061-ffbb-470b-b12f-3a16812417db\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"1ce9d4e6-af5b-49a8-adf7-c331c0409581\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e3432f82-1587-4858-bbc4-54deb2974c90\",\n          \"type\": \"image\",\n          \"scale\": 104,\n          \"focalX\": 50,\n          \"focalY\": 47.937951660156266,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photography of bike near store facade\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#533b30\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"x\": -6.5,\n          \"y\": 481,\n          \"id\": \"5fcefa37-e724-4d9b-8acc-05826a7420bd\",\n          \"width\": 425,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"x\": -4.5,\n          \"y\": 481,\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"48f17403-1dd0-4a4d-997f-45d7e9db5556\",\n          \"type\": \"shape\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"x\": -79,\n          \"y\": 474,\n          \"id\": \"5b8e1ab1-363e-4bb5-878c-e045ed9aeb76\",\n          \"width\": 374,\n          \"height\": 374,\n          \"mask\": { \"type\": \"circle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:27:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page02_image01.png\",\n            \"width\": 480,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Men's gray crew-neck long-sleeve shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#605553\",\n            \"isExternal\": true\n          },\n          \"x\": 47,\n          \"y\": 437,\n          \"width\": 129,\n          \"height\": 129,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d85f2873-fe06-4be9-b890-20583ec6c1a9\",\n          \"type\": \"image\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Marvin S.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 145,\n          \"height\": 20,\n          \"id\": \"836e587d-e6ec-43fe-a7df-9390229bfd5e\",\n          \"x\": 47,\n          \"y\": 577,\n          \"type\": \"text\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: rgba(255,255,255,0.94); letter-spacing: 0.02em; text-transform: uppercase\\\">Editor at Dwell</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 15,\n          \"marginOffset\": -18.91000000000001,\n          \"id\": \"c42709f7-1e47-49fa-a4df-258966cbbc92\",\n          \"x\": 47,\n          \"y\": 603,\n          \"type\": \"text\",\n          \"groupId\": \"94df2aab-534c-46ba-8997-7351622dcd7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 120, \"g\": 120, \"b\": 120 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 120, \"g\": 120, \"b\": 120, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"x\": -4.5,\n          \"y\": -57,\n          \"id\": \"03b46ea1-00f8-4986-8aee-910f630dae07\",\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"d3909409-c9e4-48fe-8aed-4a54de02fd59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.4\n          },\n          \"x\": -4.5,\n          \"y\": -57,\n          \"id\": \"dd902f21-2961-4bd7-ab04-7f2164228e50\",\n          \"width\": 421,\n          \"height\": 194,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"d3909409-c9e4-48fe-8aed-4a54de02fd59\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n          \"width\": 427,\n          \"height\": 427,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"cd949a65-7b5a-40bd-b4c9-382acc1c7ece\",\n          \"x\": -62,\n          \"y\": -227,\n          \"type\": \"shape\",\n          \"groupId\": \"d3909409-c9e4-48fe-8aed-4a54de02fd59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 0,\n          \"id\": \"3f7b8e5e-8f1d-4002-ad8f-8f8848ef95cd\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Thanks Books</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 261,\n          \"height\": 33,\n          \"marginOffset\": -4.899999999999999,\n          \"type\": \"text\",\n          \"groupId\": \"d3909409-c9e4-48fe-8aed-4a54de02fd59\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 50,\n          \"id\": \"7e27cc14-5c39-44f2-978e-5cd7e06c36df\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Seoul</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 20,\n          \"marginOffset\": -18.91000000000001,\n          \"type\": \"text\",\n          \"groupId\": \"d3909409-c9e4-48fe-8aed-4a54de02fd59\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"654b2dd9-bd49-4fd2-b346-9ffe79cdfa8f\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"e3432f82-1587-4858-bbc4-54deb2974c90\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"51ad002f-941b-451f-b6c7-b373d8e6a790\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"9236191f-554a-4355-b211-b454fdec93a3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"94df2aab-534c-46ba-8997-7351622dcd7a\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d3909409-c9e4-48fe-8aed-4a54de02fd59\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e80018cb-2a00-4e2d-91d1-7a92aaa9d82f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #292929\\\">Founded by a professor and a local design figure, Thanks Books features expertly curated picks.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 277,\n          \"height\": 97,\n          \"marginOffset\": 3.375,\n          \"id\": \"b40ba0e7-1c5f-46de-89a3-30c7d5244a7a\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:28:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page10_image01.jpg\",\n            \"width\": 319,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in white off shoulder dress standing near glass wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c7c9c0\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 35,\n          \"y\": 175,\n          \"width\": 170,\n          \"height\": 256,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2e83bfb7-ba44-4f67-8e72-5203bd1248e9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:28:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page10_image02.jpg\",\n            \"width\": 402,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Assorted title book lot on table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#806953\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 210,\n          \"y\": 224,\n          \"width\": 173,\n          \"height\": 207,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"721c4804-2905-4d21-a5c9-d0f552645c09\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:28:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page10_image03.jpg\",\n            \"width\": 480,\n            \"height\": 249,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman inside library looking at books\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#755c47\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 35,\n          \"y\": 436,\n          \"width\": 348,\n          \"height\": 180,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a85e2d83-7f28-4ced-88ca-3477132db351\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"a75ccef0-141e-44d6-aa7c-5dbf64174706\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"195b6ac3-a242-4220-b26a-adc2fdb78291\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:28:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page11_image01.png\",\n            \"width\": 546,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photography of bike near store facade\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#493329\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -17,\n          \"y\": -206,\n          \"width\": 446,\n          \"height\": 588,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"faceb486-6cc5-43a3-b0c3-b0d95f32257d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Thanks Books</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 33,\n          \"marginOffset\": -5.25,\n          \"id\": \"201807b3-c4cf-44fd-acc6-a1c1a96bf330\",\n          \"x\": 47,\n          \"y\": 420,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #292929\\\">28, Jandari-ro, </span>\\n<span style=\\\"color: #292929\\\">Mapo-gu, Seoul&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 46,\n          \"marginOffset\": 3.8249999999999957,\n          \"id\": \"db8f459d-5f18-4692-b092-ebd044d026da\",\n          \"x\": 47,\n          \"y\": 466,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 572,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 107,\n            \"vertical\": 15\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #292929\\\">Visit Website</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"width\": 316,\n          \"height\": 48,\n          \"marginOffset\": 4.225,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"google.com\"\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 41, \"g\": 41, \"b\": 41 } }\n          },\n          \"id\": \"2cea4858-7d4e-47e3-b67b-64273bee5bb8\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"2cea4858-7d4e-47e3-b67b-64273bee5bb8\"],\n          \"id\": \"446180ad-2652-4d57-8209-1917eb4dc45a\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 241, \"g\": 241, \"b\": 241 } },\n      \"type\": \"page\",\n      \"id\": \"bcb0daf1-17db-4aae-b8ea-bca4a1cbd982\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e2003575-764c-4fa0-a146-416b13e4f1ff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">Read More</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 33,\n          \"marginOffset\": -5.25,\n          \"type\": \"text\",\n          \"id\": \"b6df198f-3730-465c-8269-150de5f4353b\",\n          \"x\": 47,\n          \"y\": 5\n        },\n        {\n          \"x\": 48,\n          \"y\": 74,\n          \"id\": \"3b23f135-b6ee-4ffc-9925-29646451e669\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 20,\n          \"height\": 21,\n          \"marginOffset\": -2.9750000000000014,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 283,\n          \"id\": \"a6dcefe0-83e2-4ab0-9710-14c6548a7802\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">An Insider’s Guide to Copenhagen</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 281,\n          \"height\": 20,\n          \"marginOffset\": 5.524999999999999,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 343,\n          \"id\": \"b658c331-b6d6-4fb0-9ada-707a74a99083\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 25,\n          \"height\": 21,\n          \"marginOffset\": -2.9750000000000014,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 559,\n          \"id\": \"357f2775-7f48-4241-9dfe-d9711791b16b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Everything </span><span style=\\\"color: #fff\\\">Entrepreneurial</span><span style=\\\"color: #fff\\\"> in Stockholm</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 45,\n          \"marginOffset\": 3.375,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:28:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page12_image01.jpg\",\n            \"width\": 720,\n            \"height\": 369,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Red and white concrete building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4b7ac\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": 109,\n          \"width\": 317,\n          \"height\": 162,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5e6de8c8-9b83-4e70-bd09-55ef45b4b53d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-21T10:44:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/modernist-travel-guide/page12_image02.jpg\",\n            \"width\": 720,\n            \"height\": 368,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"People inside building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#302e2d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": 376,\n          \"width\": 317,\n          \"height\": 162,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a0963597-bf13-4117-91be-1db1833f7aa3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0f3b82c8-0432-49e4-958a-b229f7895173\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a6dcefe0-83e2-4ab0-9710-14c6548a7802\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"fe03c3d0-8017-4aa7-bfca-56f12f95267d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"357f2775-7f48-4241-9dfe-d9711791b16b\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"171f8c38-1b30-4125-92e4-8e2c3f31e2bc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5e6de8c8-9b83-4e70-bd09-55ef45b4b53d\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"52eecf44-36a6-477e-b1ef-bfc20fec35b5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a0963597-bf13-4117-91be-1db1833f7aa3\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"bd028f1b-3852-4086-8a75-efb0f8166e54\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3b23f135-b6ee-4ffc-9925-29646451e669\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"5f46f860-e228-461d-9c49-1ee3a54b5688\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b658c331-b6d6-4fb0-9ada-707a74a99083\"],\n          \"duration\": 1500,\n          \"delay\": 750\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 16, \"b\": 6 } },\n      \"type\": \"page\",\n      \"id\": \"27f5c03c-4a36-4269-8d27-966b911dfc57\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/new-york-party-round-up/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/new-york-party-round-up/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'new-york-party-round-up',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('New York Party Round-up', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Club', 'template keyword', 'web-stories'),\n    _x('Event', 'template keyword', 'web-stories'),\n    _x('Banner', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s large black and white banners and full-screen visuals will let you create simple yet attractive stories in the entertainment niche. Create buzzy listicles, announce events and show times, give out info about music festivals and more. Use the social share buttons to reach a wider audience.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/new-york-party-round-up/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/new-york-party-round-up/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"2f814d52-6421-4c20-8ce8-e8d7b39ef30f\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:43:20\",\n            \"baseColor\": \"#131618\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Wrinkle texture on dark color\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 336,\n          \"y\": 494,\n          \"width\": 144,\n          \"height\": 138,\n          \"sticker\": { \"type\": \"nycPartyCircleIcon\" },\n          \"id\": \"daf179c2-c3f3-4157-b088-b090abb51780\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:43:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page1_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1023,\n            \"id\": 0,\n            \"alt\": \"Man in blue denim jacket\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2f2423\",\n            \"isExternal\": true\n          },\n          \"x\": 84,\n          \"y\": -57,\n          \"width\": 328,\n          \"height\": 438,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cc93ee81-bd40-4d9d-96ef-6428c5e756c3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 43,\n          \"y\": 361,\n          \"width\": 307,\n          \"height\": 209,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"428fbbc8-3611-417c-bdf1-972ff17841ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; text-transform: uppercase\\\">New York Party Round-up</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 364,\n          \"width\": 313,\n          \"height\": 132,\n          \"id\": \"68fb4e17-c785-40a4-b11d-f145fdd82c30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"Simon Romanov\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 68,\n          \"y\": 537,\n          \"width\": 200,\n          \"height\": 18,\n          \"id\": \"638f49c3-4d5d-49e1-afc9-5ecaebcd3f60\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"520c23bb-543d-4be2-bf92-af506e19a57e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"bfce4d10-0344-400a-af65-36d474c79205\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"b0af3c0b-832f-4f42-bf37-4435d6a783d1\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:43:47\",\n            \"baseColor\": \"#1927d5\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page2_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Group of people standing inside dome watching concert\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">Here is a round-up of the events and goings-on that we are anxiously awaiting this week.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 290,\n          \"height\": 195,\n          \"id\": \"f569e972-ff30-4069-a979-cd49c1e93da8\",\n          \"x\": 47,\n          \"y\": 343,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"09add21a-e5ac-4f54-8473-a1929210fd13\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"b0af3c0b-832f-4f42-bf37-4435d6a783d1\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"419b9060-9050-419d-8d2f-396256292c90\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"07b07e9a-7812-4545-9b23-f0b74d87b3f3\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"af0677e7-0fd2-4119-bb1d-cb3d26f3bd50\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:46:26\",\n            \"baseColor\": \"#141414\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White distributed particles on black backdrop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">Sept 7-9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 164,\n          \"height\": 48,\n          \"id\": \"5c8416a2-60a0-4f6b-8cd0-9edd58aaa750\",\n          \"x\": 48,\n          \"y\": 3,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:44:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page3_image1.jpg\",\n            \"width\": 780,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man in blue denim jacket\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#312423\",\n            \"isExternal\": true\n          },\n          \"x\": 35,\n          \"y\": 70,\n          \"width\": 325,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"822d351e-7cef-4da7-9b6f-3cb3722bbc76\",\n          \"groupId\": \"603d19e4-8ed7-44c3-bfab-293d78a0b171\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.6)\\\">9/7</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 82,\n          \"id\": \"1a514e92-2d60-4989-94d2-19e8ec033d3d\",\n          \"x\": 38,\n          \"y\": 243,\n          \"groupId\": \"603d19e4-8ed7-44c3-bfab-293d78a0b171\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Village Fête — &nbsp;10:30PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 17,\n          \"id\": \"dd50c7a4-0e4a-491e-9a81-8ec4e04a8754\",\n          \"x\": 172,\n          \"y\": 284,\n          \"groupId\": \"603d19e4-8ed7-44c3-bfab-293d78a0b171\"\n        },\n        {\n          \"x\": 35,\n          \"y\": 362,\n          \"id\": \"eb1c3f99-5f49-4f59-a23c-a59375b5f77e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 3,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:44:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page3_image2.jpg\",\n            \"width\": 776,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man in black crew neck t-shirt holding white ceramic mug\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dbaf8d\",\n            \"isExternal\": true\n          },\n          \"width\": 325,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"96129e5d-f78e-4f49-9901-5fb1c3fd1315\"\n        },\n        {\n          \"x\": 42,\n          \"y\": 538,\n          \"id\": \"c776de48-d44e-4c91-87bc-381544c387e8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.6)\\\">9/9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 82,\n          \"groupId\": \"96129e5d-f78e-4f49-9901-5fb1c3fd1315\"\n        },\n        {\n          \"x\": 176,\n          \"y\": 578,\n          \"id\": \"4cc215fd-77a4-4850-a9ba-3319048b6569\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Defected: NYD — 11:30PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 17,\n          \"groupId\": \"96129e5d-f78e-4f49-9901-5fb1c3fd1315\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"e8b15fdf-cd87-4dc0-aef7-f8b6f4dca8d9\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"7e8ad10a-4c7a-4079-851e-62b191e6a10b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"603d19e4-8ed7-44c3-bfab-293d78a0b171\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"96129e5d-f78e-4f49-9901-5fb1c3fd1315\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7b62bb81-cfef-4ca9-91c7-691982b9eea0\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:46:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White distributed particles on black backdrop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#ac3c3c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 500\\\">Sept 10-12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 254,\n          \"height\": 48,\n          \"id\": \"168b955f-3766-4567-90be-f771f3bb3d4a\",\n          \"x\": 50,\n          \"y\": 2,\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:46:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page4_image1.jpg\",\n            \"width\": 746,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Photo of a selective focus on DJ booth in a club\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d31d78\",\n            \"isExternal\": true\n          },\n          \"x\": 35,\n          \"y\": 68,\n          \"width\": 325,\n          \"height\": 209,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6af257fd-eb11-476e-a1b3-66117c2fed76\",\n          \"type\": \"image\",\n          \"groupId\": \"e2c8a297-c656-4285-ac41-f7f8d203e4b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.6)\\\">9/10</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 202,\n          \"height\": 82,\n          \"id\": \"1eb72045-c5cd-4859-9d15-719be275853e\",\n          \"x\": 38,\n          \"y\": 243,\n          \"type\": \"text\",\n          \"groupId\": \"e2c8a297-c656-4285-ac41-f7f8d203e4b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">KANO — 9:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 17,\n          \"id\": \"cf2a98f0-7f67-44f7-b750-68d54fcffe1b\",\n          \"x\": 202,\n          \"y\": 284,\n          \"type\": \"text\",\n          \"groupId\": \"e2c8a297-c656-4285-ac41-f7f8d203e4b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 3,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 35,\n          \"y\": 362,\n          \"id\": \"f5973388-ba65-4223-8eb6-0e68cb049253\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:47:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page4_image2.jpg\",\n            \"width\": 780,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Ouf light signage\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#fa6ad0\",\n            \"isExternal\": true\n          },\n          \"width\": 325,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"groupId\": \"b3e4b106-8d19-465d-b5a3-651cc515cacf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 42,\n          \"y\": 538,\n          \"id\": \"c6cf349f-74c6-403c-ae56-90618d52c788\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.6)\\\">9/12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 171,\n          \"height\": 82,\n          \"type\": \"text\",\n          \"groupId\": \"b3e4b106-8d19-465d-b5a3-651cc515cacf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 202,\n          \"y\": 578,\n          \"id\": \"c91619f9-96eb-4a37-b09d-fa12f2a76214\",\n          \"content\": \"<span style=\\\"color: #fff\\\">OUF! Cringe party\\n—11:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"groupId\": \"b3e4b106-8d19-465d-b5a3-651cc515cacf\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"2208700b-3a0f-4eea-9ea3-c9b1eae35e9f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"727b7e7b-484b-4cd3-afa3-041444f2a67b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e2c8a297-c656-4285-ac41-f7f8d203e4b9\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b3e4b106-8d19-465d-b5a3-651cc515cacf\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e75af52c-57ee-4ef2-af1c-41d2a06dec5f\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T13:30:12\",\n            \"baseColor\": \"#1f1817\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page5_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man wearing a cap in a\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"Village Fête\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 364,\n          \"height\": 78,\n          \"id\": \"d16389af-9567-4596-b119-96e142c10f4d\",\n          \"x\": 31,\n          \"y\": 280,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.4)\\\">9/7</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 346,\n          \"height\": 235,\n          \"id\": \"73ce87ad-8503-487d-93c0-4276fb91fbc0\",\n          \"x\": -28,\n          \"y\": -74,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 30,\n          \"y\": 391,\n          \"id\": \"2b33139a-3051-47bf-b359-63b14a92dca5\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 500\\\">September 7 — 10:30PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 364,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 144,\n          \"height\": 138,\n          \"sticker\": { \"type\": \"nycPartyCircleIcon\" },\n          \"id\": \"986ad9a0-9815-44fa-ab8d-b87710245832\",\n          \"x\": 336,\n          \"y\": 494\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b059d5d0-9a84-44c0-bf21-b7abc03a6b84\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"73ce87ad-8503-487d-93c0-4276fb91fbc0\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e18904e3-9346-487e-9ca7-7f0ca3ca60c9\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleOut\",\n          \"targets\": [\"e75af52c-57ee-4ef2-af1c-41d2a06dec5f\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"0ce39005-e596-4b16-be27-fd819977beb1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ff84a5b7-2bce-4b85-b380-8baf4cb31c8c\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"76cbb697-d32b-4921-8c3f-b96218200fe9\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-25T08:01:05\",\n            \"baseColor\": \"#de0949\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page6_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"People partying inside room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.45 } }\n        },\n        {\n          \"x\": 48,\n          \"y\": 543,\n          \"id\": \"b1e3dacf-dc75-440c-95aa-4760a3b4624b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">SHARE:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 18,\n          \"groupId\": \"fa5e7328-6880-41c4-9cf0-02391670d1ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 104,\n          \"y\": 582,\n          \"width\": 28,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitterIcon\" },\n          \"id\": \"2f8146ab-3017-43ef-b832-34df3f5e13de\",\n          \"groupId\": \"fa5e7328-6880-41c4-9cf0-02391670d1ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 49,\n          \"y\": 582,\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyInstagramIcon\" },\n          \"id\": \"79e781c3-8d3e-4659-a9c9-5053632fa5c3\",\n          \"groupId\": \"fa5e7328-6880-41c4-9cf0-02391670d1ea\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 166,\n          \"y\": 582,\n          \"width\": 20,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitchIcon\" },\n          \"id\": \"2f880bba-4e53-42d2-bf4e-88e9d7c38167\",\n          \"groupId\": \"fa5e7328-6880-41c4-9cf0-02391670d1ea\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Venue</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"a5133442-8f67-4976-9e06-2ef5a82912d4\",\n          \"x\": 49,\n          \"y\": 11,\n          \"groupId\": \"c1ff5c76-454b-45ed-a640-bd6784d4541f\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 36,\n          \"id\": \"f63371b6-3beb-46e8-95ac-12fc112a3226\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Pagework</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"groupId\": \"c1ff5c76-454b-45ed-a640-bd6784d4541f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 49,\n          \"y\": 83,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"209ea68e-0a75-4c9f-846a-04d3888fc2a2\",\n          \"groupId\": \"c1ff5c76-454b-45ed-a640-bd6784d4541f\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Date</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"dff941f4-8d7f-4268-825f-e7bc0fbac4ef\",\n          \"x\": 49,\n          \"y\": 98,\n          \"groupId\": \"98b935dc-c913-40bf-9faa-8ccd3bae6aad\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 170,\n          \"id\": \"6d6de56a-5b4a-41fc-b5ab-9786be6b21e6\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"98b935dc-c913-40bf-9faa-8ccd3bae6aad\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 124,\n          \"id\": \"d5a974db-cc2b-42bf-b597-076481c2cdfc\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Mon 09.07.20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"groupId\": \"98b935dc-c913-40bf-9faa-8ccd3bae6aad\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Showtime</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"a8aa600c-5cf0-4afc-8d0c-c4d3556dddd1\",\n          \"x\": 49,\n          \"y\": 187,\n          \"groupId\": \"62391972-efab-4fcb-9025-f845cc7c3822\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 213,\n          \"id\": \"1ec6c0ac-f9bf-438b-a83d-680c8ade0c19\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">12:00 - 3:00</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"groupId\": \"62391972-efab-4fcb-9025-f845cc7c3822\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 257,\n          \"id\": \"37182dab-597c-4006-90bc-85ea20760834\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"62391972-efab-4fcb-9025-f845cc7c3822\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Age Range</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"95f7d545-cdc0-4b00-bc89-4a7c619c7d8b\",\n          \"x\": 49,\n          \"y\": 276,\n          \"groupId\": \"e56a28ff-4048-404f-88e8-02bc3dafa8ff\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 344,\n          \"id\": \"cc25e651-a299-498a-ace6-10e0c199cec9\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"e56a28ff-4048-404f-88e8-02bc3dafa8ff\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 302,\n          \"id\": \"0c7e492e-fd6c-4b55-8ad8-9d18cb9ec89d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">18+</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"groupId\": \"e56a28ff-4048-404f-88e8-02bc3dafa8ff\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bf0dac1f-d019-4a4e-afaf-4db705eb1424\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2f880bba-4e53-42d2-bf4e-88e9d7c38167\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ca4064a2-fd15-46ce-8706-7eb9a99235e6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2f8146ab-3017-43ef-b832-34df3f5e13de\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c2b29272-5877-426b-89cb-49f6209b8e6c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"79e781c3-8d3e-4659-a9c9-5053632fa5c3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fd7667bc-75fe-4a57-9109-bea39dab551c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cc25e651-a299-498a-ace6-10e0c199cec9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"c77a21d2-7ca7-4f00-8471-6cdcf7405e29\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"37182dab-597c-4006-90bc-85ea20760834\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"8afadc44-4f91-4395-87f3-c71202b62998\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6d6de56a-5b4a-41fc-b5ab-9786be6b21e6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"822b8c16-4e34-453e-bcba-7b28a80e4ffe\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"209ea68e-0a75-4c9f-846a-04d3888fc2a2\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ad4cc025-e621-4072-8f0f-167f502514c2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a5133442-8f67-4976-9e06-2ef5a82912d4\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fd1a30b7-f5f7-4c76-8dca-f48a7a7fe933\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f63371b6-3beb-46e8-95ac-12fc112a3226\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"8b2e6d01-2a9e-4fc3-948c-e1eb98575d13\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dff941f4-8d7f-4268-825f-e7bc0fbac4ef\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"dcf0e1ba-bc3e-41c8-b579-7fe02a51a69b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d5a974db-cc2b-42bf-b597-076481c2cdfc\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"2379a2b4-cdd9-4a26-96eb-a9b653ff6d7b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a8aa600c-5cf0-4afc-8d0c-c4d3556dddd1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"a93e93c6-ad49-4a4f-9459-53f52a48c381\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1ec6c0ac-f9bf-438b-a83d-680c8ade0c19\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"6b26df79-59fa-430f-ba9c-496bd9066295\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"95f7d545-cdc0-4b00-bc89-4a7c619c7d8b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"e2b077b9-e054-44b0-9756-eac035ad73fd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0c7e492e-fd6c-4b55-8ad8-9d18cb9ec89d\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"223eb73e-b383-460a-a6b7-d53d8115f768\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"4e4fbc38-e914-4384-bbac-c8d552991d1a\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c1ff5c76-454b-45ed-a640-bd6784d4541f\": {\n          \"name\": \"Venue\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"98b935dc-c913-40bf-9faa-8ccd3bae6aad\": {\n          \"name\": \"Date\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"62391972-efab-4fcb-9025-f845cc7c3822\": {\n          \"name\": \"Showtime\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e56a28ff-4048-404f-88e8-02bc3dafa8ff\": {\n          \"name\": \"Age\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fa5e7328-6880-41c4-9cf0-02391670d1ea\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"bd3ee200-a9cd-4e41-9d03-1e4fa9bdef2c\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-25T07:59:37\",\n            \"baseColor\": \"#19110d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Women in club\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 500\\\">Defected: </span><span style=\\\"font-weight: 500; text-transform: uppercase\\\">Nyd</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 364,\n          \"height\": 144,\n          \"id\": \"e70f49a1-9fde-44c4-b2de-0a7c4e89b3cd\",\n          \"x\": 30,\n          \"y\": 249,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.4)\\\">9/9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 346,\n          \"height\": 235,\n          \"id\": \"7bddadc1-f7f3-4bb8-b0a9-6efd15bd86cc\",\n          \"x\": -28,\n          \"y\": -74,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"x\": 39,\n          \"y\": 430,\n          \"id\": \"cffdaab7-40b5-4f14-b83d-b5066b8e3c78\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">September 9 — 11:30PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 35,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 144,\n          \"height\": 138,\n          \"sticker\": { \"type\": \"nycPartyCircleIcon\" },\n          \"id\": \"2053db0f-9910-42a2-8c36-3b9ae108f582\",\n          \"x\": 336,\n          \"y\": 494,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0f9552e7-ec84-4386-a0b4-6d888f13cb95\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleOut\",\n          \"targets\": [\"bd3ee200-a9cd-4e41-9d03-1e4fa9bdef2c\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"6e48abc8-0fa3-49a5-b2eb-9116ebb8c720\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"77a60ee3-cc7a-4003-9e9f-31de55a3ae32\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"51513c42-363d-480d-8dfc-b02587c1d997\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:48:11\",\n            \"baseColor\": \"#041425\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page8_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White metal frame in grayscale photography\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 543,\n          \"id\": \"19ddd6f1-710b-4b42-a72e-2c1da984f882\",\n          \"content\": \"<span style=\\\"color: #fff\\\">SHARE:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"212cc920-3ff2-4dbb-9541-4253359601f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitterIcon\" },\n          \"id\": \"555deaf9-39b3-424a-973f-4b6cac4bc5b1\",\n          \"x\": 104,\n          \"y\": 582,\n          \"groupId\": \"212cc920-3ff2-4dbb-9541-4253359601f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyInstagramIcon\" },\n          \"id\": \"32ae64c0-c876-4831-9e5b-d6f6cc15cd0b\",\n          \"x\": 49,\n          \"y\": 582,\n          \"groupId\": \"212cc920-3ff2-4dbb-9541-4253359601f5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 20,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitchIcon\" },\n          \"id\": \"15c3677d-f663-4893-8bfd-6d66d51d89b7\",\n          \"x\": 166,\n          \"y\": 582,\n          \"groupId\": \"212cc920-3ff2-4dbb-9541-4253359601f5\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Venue</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"435fcd35-01cc-4ada-94ce-8cced98c591c\",\n          \"x\": 49,\n          \"y\": 11,\n          \"groupId\": \"3483e291-f8ef-47b8-9539-5621f397ddca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Queensland</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"5b9288d9-5d5d-4128-ab9a-fab8f04f9513\",\n          \"x\": 50,\n          \"y\": 36,\n          \"groupId\": \"3483e291-f8ef-47b8-9539-5621f397ddca\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"73c64fc2-ab9e-4a0a-8903-cf6e1d40259d\",\n          \"x\": 49,\n          \"y\": 83,\n          \"groupId\": \"3483e291-f8ef-47b8-9539-5621f397ddca\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Date</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"35bb8574-e028-4022-920d-900c9131c861\",\n          \"x\": 50,\n          \"y\": 98,\n          \"groupId\": \"1090c0b6-8213-4f2d-aff8-4028d39e1336\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bb12ed7e-bbcd-4cca-a8fb-972eba53a4ea\",\n          \"x\": 49,\n          \"y\": 170,\n          \"groupId\": \"1090c0b6-8213-4f2d-aff8-4028d39e1336\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 124,\n          \"id\": \"db52484b-afe0-47ee-aacf-b6ff35747d64\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Wed 09.07.20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"1090c0b6-8213-4f2d-aff8-4028d39e1336\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Showtime</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"c7a0fd4d-fd75-467a-854e-034c295ff8fd\",\n          \"x\": 49,\n          \"y\": 187,\n          \"groupId\": \"b97e756c-2fab-4333-a3f5-4f0ad4dd35f6\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"254ef480-5acb-4075-ae8c-c90da0b1d471\",\n          \"x\": 49,\n          \"y\": 257,\n          \"groupId\": \"b97e756c-2fab-4333-a3f5-4f0ad4dd35f6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 213,\n          \"id\": \"7699a04e-c136-40f8-882f-e25bbd1c4d10\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">12:00 - 3:00</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"b97e756c-2fab-4333-a3f5-4f0ad4dd35f6\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d88f3324-8907-4ffc-ad44-ab519709b36f\",\n          \"x\": 49,\n          \"y\": 344,\n          \"groupId\": \"ed0664a1-fe1a-4f46-8685-3c80411ff4e7\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Age Range</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"d466b4fc-0c89-4f15-aa52-704af739f2ac\",\n          \"x\": 49,\n          \"y\": 276,\n          \"groupId\": \"ed0664a1-fe1a-4f46-8685-3c80411ff4e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">18+</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"571979fa-09ba-45d4-8cd5-34485ca37150\",\n          \"x\": 48,\n          \"y\": 302,\n          \"groupId\": \"ed0664a1-fe1a-4f46-8685-3c80411ff4e7\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"abb1d4e2-b6a6-4ace-adfa-a70cb2333ca3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"73c64fc2-ab9e-4a0a-8903-cf6e1d40259d\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c9937645-11d1-4ffb-a65d-54796a803030\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"bb12ed7e-bbcd-4cca-a8fb-972eba53a4ea\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0010b830-f8ea-43fa-a67c-b93f78d3af14\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"254ef480-5acb-4075-ae8c-c90da0b1d471\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"fe902a91-fe6a-4407-9f7b-a8af07672ca0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d88f3324-8907-4ffc-ad44-ab519709b36f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"555deaf9-39b3-424a-973f-4b6cac4bc5b1\"],\n          \"id\": \"cc166c72-dea2-4f06-846e-ccd2d3bc4dcc\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"32ae64c0-c876-4831-9e5b-d6f6cc15cd0b\"],\n          \"id\": \"8bd66bbb-9ddf-4f47-8259-d08f1167d8dc\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"15c3677d-f663-4893-8bfd-6d66d51d89b7\"],\n          \"id\": \"d5957bf5-45be-4d51-a94f-eff994221d3a\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"661afc6b-27e5-4d1a-b600-c0d68c1235a5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"435fcd35-01cc-4ada-94ce-8cced98c591c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ecd4c839-a41a-4570-9b58-bf400e73940a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5b9288d9-5d5d-4128-ab9a-fab8f04f9513\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"bfe82b62-3b85-4049-863c-15c070fbca69\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"db52484b-afe0-47ee-aacf-b6ff35747d64\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"80ef070c-00da-46a0-a6b9-42e377c88187\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"35bb8574-e028-4022-920d-900c9131c861\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"bc8e8076-849b-4552-8fc9-9cadf72a8371\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c7a0fd4d-fd75-467a-854e-034c295ff8fd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"130195c9-85c8-4e4f-b139-64e39c43c7db\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7699a04e-c136-40f8-882f-e25bbd1c4d10\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d072e0af-337c-48a0-be9b-cb95084f822f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d466b4fc-0c89-4f15-aa52-704af739f2ac\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"571979fa-09ba-45d4-8cd5-34485ca37150\"],\n          \"id\": \"6932559f-c719-42a4-bf7d-1a15507e30d3\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"dcb9b873-f592-4838-83e6-094536049ace\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"191e072e-711f-4b46-9532-f614fd246a1c\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"3483e291-f8ef-47b8-9539-5621f397ddca\": {\n          \"name\": \"Venue\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1090c0b6-8213-4f2d-aff8-4028d39e1336\": {\n          \"name\": \"Date\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b97e756c-2fab-4333-a3f5-4f0ad4dd35f6\": {\n          \"name\": \"Showtime\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ed0664a1-fe1a-4f46-8685-3c80411ff4e7\": {\n          \"name\": \"Age\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"212cc920-3ff2-4dbb-9541-4253359601f5\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"313d548e-357e-456e-9a9f-750ef60bb453\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:48:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page9_bg.jpg\",\n            \"baseColor\": \"#28051d\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"DJ booth in a club\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 12,\n            \"vertical\": 8\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Kano</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 372,\n          \"height\": 87,\n          \"id\": \"cf9968cf-5f45-4523-89c8-dfd6d7c33054\",\n          \"x\": 29,\n          \"y\": 278,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.4)\\\">9/10</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 436,\n          \"height\": 235,\n          \"id\": \"f8238f2f-5d36-41d4-9558-de0fdd890173\",\n          \"x\": -28,\n          \"y\": -72,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"x\": 32,\n          \"y\": 391,\n          \"id\": \"8a45d0f5-d0e0-407d-9046-24b4e5f3e544\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">September 10 — 9:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 364,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 144,\n          \"height\": 138,\n          \"sticker\": { \"type\": \"nycPartyCircleIcon\" },\n          \"id\": \"47cd761f-d3b2-4d34-9ac6-c72459e42897\",\n          \"x\": 336,\n          \"y\": 494,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4bc233cc-9552-4785-ad08-1530e7e15691\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleOut\",\n          \"targets\": [\"313d548e-357e-456e-9a9f-750ef60bb453\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"ca9c3996-5897-4c55-858c-975daefe3be0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8737f47b-5d87-45bc-9cae-ff7a878feeaa\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"dfc878ec-0e36-462f-9ac0-bd01aed3e702\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-25T08:00:21\",\n            \"baseColor\": \"#775756\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man singing on stage white wearing brown crew-neck shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 543,\n          \"id\": \"e1f9efab-fbb6-4870-bdff-9f390292fbc7\",\n          \"content\": \"<span style=\\\"color: #fff\\\">SHARE:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"c4be6791-f4cd-46a8-ae1a-074b365477c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitterIcon\" },\n          \"id\": \"98ae1512-77f3-4e63-a8bb-5e70f543683f\",\n          \"x\": 104,\n          \"y\": 582,\n          \"groupId\": \"c4be6791-f4cd-46a8-ae1a-074b365477c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyInstagramIcon\" },\n          \"id\": \"2d9679fa-370b-46d2-b3e9-2438d17b81f4\",\n          \"x\": 49,\n          \"y\": 582,\n          \"groupId\": \"c4be6791-f4cd-46a8-ae1a-074b365477c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 20,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitchIcon\" },\n          \"id\": \"9e78cf91-76a0-41e3-99b2-1aa5ab3350e0\",\n          \"x\": 166,\n          \"y\": 582,\n          \"groupId\": \"c4be6791-f4cd-46a8-ae1a-074b365477c6\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Venue</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"9c92b6d6-1b73-417a-adbb-52cf94edfa55\",\n          \"x\": 49,\n          \"y\": 11,\n          \"groupId\": \"d7ad1e80-23f6-44c3-ae9f-cb816d5a0062\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 35,\n          \"id\": \"5a0fc61d-c757-4c39-bdb1-7b57c57d0e4e\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Drumsheds</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"d7ad1e80-23f6-44c3-ae9f-cb816d5a0062\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3acb3c9f-16d1-4c34-a3cf-e384b7653310\",\n          \"x\": 49,\n          \"y\": 83,\n          \"groupId\": \"d7ad1e80-23f6-44c3-ae9f-cb816d5a0062\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Date</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"1488487f-6de3-451a-9724-05253197ae30\",\n          \"x\": 50,\n          \"y\": 98,\n          \"groupId\": \"14bc625a-a7d8-4959-99e7-1864db692727\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 124,\n          \"id\": \"d812be02-e23e-4bcc-ae2a-5e8edc05fb37\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Thu 09.10.20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"14bc625a-a7d8-4959-99e7-1864db692727\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d35e59ba-59d5-4e7e-8455-521397863074\",\n          \"x\": 49,\n          \"y\": 170,\n          \"groupId\": \"14bc625a-a7d8-4959-99e7-1864db692727\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Showtime</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"0c4bad30-28e8-4639-9a3e-498dfa210eb8\",\n          \"x\": 49,\n          \"y\": 187,\n          \"groupId\": \"8badf9ae-1cb8-4fa1-82d1-47a2d730f312\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 213,\n          \"id\": \"145397e8-a032-422b-9413-f52aaba69767\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">9:00 - 2:00</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"8badf9ae-1cb8-4fa1-82d1-47a2d730f312\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"558f837c-857d-4b0a-8ad7-f9fd272215fe\",\n          \"x\": 49,\n          \"y\": 257,\n          \"groupId\": \"8badf9ae-1cb8-4fa1-82d1-47a2d730f312\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Age Range</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"52682620-1cf8-4a3e-abe7-74fbc93a6f79\",\n          \"x\": 49,\n          \"y\": 276,\n          \"groupId\": \"c4c1b2f3-a52f-4396-afa2-abd48273c807\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"eeee21ff-4a78-4ec4-b8c8-77b10762c785\",\n          \"x\": 49,\n          \"y\": 344,\n          \"groupId\": \"c4c1b2f3-a52f-4396-afa2-abd48273c807\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">18+</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"abe25859-f66f-404b-91ca-a38a63387ef8\",\n          \"x\": 48,\n          \"y\": 302,\n          \"groupId\": \"c4c1b2f3-a52f-4396-afa2-abd48273c807\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"98ae1512-77f3-4e63-a8bb-5e70f543683f\"],\n          \"id\": \"e105ad11-59f2-4b7e-b52b-570145239b1d\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"2d9679fa-370b-46d2-b3e9-2438d17b81f4\"],\n          \"id\": \"d3aec322-934f-4268-be0c-2868d6909570\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"9e78cf91-76a0-41e3-99b2-1aa5ab3350e0\"],\n          \"id\": \"81c42e0c-0726-4f0d-8d37-121a4df1673a\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"3acb3c9f-16d1-4c34-a3cf-e384b7653310\"],\n          \"id\": \"cdee77b2-520d-4b25-9c50-4b43a03d1dd8\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"d35e59ba-59d5-4e7e-8455-521397863074\"],\n          \"id\": \"75ec2615-58ad-44f8-9310-26ff4bb8a01a\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"558f837c-857d-4b0a-8ad7-f9fd272215fe\"],\n          \"id\": \"73b02fa3-f375-4fcf-87b2-7a63978adbdd\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"eeee21ff-4a78-4ec4-b8c8-77b10762c785\"],\n          \"id\": \"a27ddec7-9c08-45da-a1d5-4592d3145216\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"9c92b6d6-1b73-417a-adbb-52cf94edfa55\"],\n          \"id\": \"b1bb40ec-eb02-4c1e-bb67-e5159d3bb31f\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"1488487f-6de3-451a-9724-05253197ae30\"],\n          \"id\": \"a3c4afda-908b-463d-bcbc-d7c9fae1d68b\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"0c4bad30-28e8-4639-9a3e-498dfa210eb8\"],\n          \"id\": \"fb576b12-b1d4-41d1-acb0-931216e9575a\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"52682620-1cf8-4a3e-abe7-74fbc93a6f79\"],\n          \"id\": \"31957d25-a5b2-470a-a05e-30a01502617c\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"abe25859-f66f-404b-91ca-a38a63387ef8\"],\n          \"id\": \"61fa8ffb-3464-417f-8497-49767de16437\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"e35befd6-be27-4957-bb88-407c2de36a65\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"145397e8-a032-422b-9413-f52aaba69767\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"fe6fbd17-03fc-4929-b69a-987bded7e2ea\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d812be02-e23e-4bcc-ae2a-5e8edc05fb37\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"8a33f777-c3c1-46fb-bf89-ec870ba03906\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5a0fc61d-c757-4c39-bdb1-7b57c57d0e4e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"0a728a37-b4ca-4c65-b681-9ebacfaf77e8\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b79c177b-c135-4f3f-b342-efd3f615497a\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"d7ad1e80-23f6-44c3-ae9f-cb816d5a0062\": {\n          \"name\": \"Venue\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"14bc625a-a7d8-4959-99e7-1864db692727\": {\n          \"name\": \"Date\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8badf9ae-1cb8-4fa1-82d1-47a2d730f312\": {\n          \"name\": \"Showtime\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c4c1b2f3-a52f-4396-afa2-abd48273c807\": {\n          \"name\": \"Age\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c4be6791-f4cd-46a8-ae1a-074b365477c6\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"032fe00b-09c4-4ac6-a902-c9c954e043fa\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:49:21\",\n            \"baseColor\": \"#a0295d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Ouf light signage\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 200,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(255,255,255,0.4)\\\">9/12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 439,\n          \"height\": 234,\n          \"id\": \"5fb7a7ff-8e44-416d-8c82-84693542c5e8\",\n          \"x\": -28,\n          \"y\": -74,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 144,\n          \"height\": 138,\n          \"sticker\": { \"type\": \"nycPartyCircleIcon\" },\n          \"id\": \"78b9ace8-8055-4bec-9753-5dc6670760d0\",\n          \"x\": 336,\n          \"y\": 494,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 12,\n            \"vertical\": 8\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Ouf</span><span style=\\\"font-weight: 500\\\">! Cringe party</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 372,\n          \"height\": 152,\n          \"type\": \"text\",\n          \"id\": \"0a7d8cfe-9828-4472-a0bf-7e7761ebd0f8\",\n          \"x\": 26,\n          \"y\": 245,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 500\\\">September 12 — 11:00PM</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 315,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"id\": \"b3f194e7-6ae5-4ab6-9eb6-d67bd05d2da2\",\n          \"x\": 39,\n          \"y\": 430,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6a76995b-bc28-492d-84bb-e7b23d410382\",\n          \"type\": \"effect-background-pan-and-zoom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"zoomDirection\": \"scaleOut\",\n          \"targets\": [\"032fe00b-09c4-4ac6-a902-c9c954e043fa\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"cb4ef0e9-cf52-4a50-8bea-9207b0a3192d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"7beeb408-2591-4821-8627-55944e27d884\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"4c1d3bca-1d06-4b0c-b1ed-e1aae4c57edf\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:49:38\",\n            \"baseColor\": \"#4c623f\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"People dancing inside room with green lights\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 543,\n          \"id\": \"40d727a9-8f5c-40e0-adf9-4b63b70ef3d4\",\n          \"content\": \"<span style=\\\"color: #fff\\\">SHARE:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"6c69de29-c841-4b13-bf94-ff38ad8efcc7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 28,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitterIcon\" },\n          \"id\": \"67df62f6-c055-4a5e-b469-73196d0cd1ad\",\n          \"x\": 104,\n          \"y\": 582,\n          \"groupId\": \"6c69de29-c841-4b13-bf94-ff38ad8efcc7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 22,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyInstagramIcon\" },\n          \"id\": \"f700f569-7f02-4095-a11e-7cc4c646d580\",\n          \"x\": 49,\n          \"y\": 582,\n          \"groupId\": \"6c69de29-c841-4b13-bf94-ff38ad8efcc7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 20,\n          \"height\": 22,\n          \"sticker\": { \"type\": \"nycPartyTwitchIcon\" },\n          \"id\": \"6a89fa03-8c35-447e-97de-06505b68ade6\",\n          \"x\": 166,\n          \"y\": 582,\n          \"groupId\": \"6c69de29-c841-4b13-bf94-ff38ad8efcc7\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Venue</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"bea347c7-f003-4a22-9d35-46a06cfc26b0\",\n          \"x\": 49,\n          \"y\": 11,\n          \"groupId\": \"65c27a80-9505-4587-ab6f-8b0e4c5cd0fd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 35,\n          \"id\": \"106fc2c7-7d31-41ab-968b-e6047b1c20f7\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Happy Endings</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"65c27a80-9505-4587-ab6f-8b0e4c5cd0fd\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1d0a5e5f-3d0a-4240-81ed-1a3f20c5e650\",\n          \"x\": 49,\n          \"y\": 83,\n          \"groupId\": \"65c27a80-9505-4587-ab6f-8b0e4c5cd0fd\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Date</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"1ad4ebfe-246a-490b-aef4-9b14c209d0da\",\n          \"x\": 50,\n          \"y\": 98,\n          \"groupId\": \"2d55153e-230e-4851-a457-b2fb7b9d0e68\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"55bbab18-af70-45ef-b6fb-9e63047a95ec\",\n          \"x\": 49,\n          \"y\": 170,\n          \"groupId\": \"2d55153e-230e-4851-a457-b2fb7b9d0e68\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 124,\n          \"id\": \"5cae9bae-9534-45d6-b76d-4761fe8634b0\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Sat 09.12.20</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"2d55153e-230e-4851-a457-b2fb7b9d0e68\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Showtime</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"8b3ab1a7-fe74-450d-a941-620b5cb3d640\",\n          \"x\": 49,\n          \"y\": 187,\n          \"groupId\": \"ded72301-f80b-4a39-a726-d1bd0027935a\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9055c5bf-3c21-4bcf-8f9e-385c97eadcd3\",\n          \"x\": 49,\n          \"y\": 257,\n          \"groupId\": \"ded72301-f80b-4a39-a726-d1bd0027935a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 212,\n          \"id\": \"af4c00bc-6fc6-475f-9868-72805d8a6a85\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">12:00 - 3:00</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"ded72301-f80b-4a39-a726-d1bd0027935a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Age Range</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 16,\n          \"type\": \"text\",\n          \"id\": \"5648ecdd-8c6d-4a1d-a998-399e06efa300\",\n          \"x\": 49,\n          \"y\": 276,\n          \"groupId\": \"a2065c2a-7fd8-454d-a28b-d1fd6bf1a558\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7d971b82-b5fb-4824-a71a-13ca149778fd\",\n          \"x\": 49,\n          \"y\": 344,\n          \"groupId\": \"a2065c2a-7fd8-454d-a28b-d1fd6bf1a558\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">18+</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 200,\n          \"height\": 28,\n          \"id\": \"f2b32ce2-6f83-46e3-bfcb-1b6c44517d8f\",\n          \"x\": 48,\n          \"y\": 302,\n          \"groupId\": \"a2065c2a-7fd8-454d-a28b-d1fd6bf1a558\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"67df62f6-c055-4a5e-b469-73196d0cd1ad\"],\n          \"id\": \"370e30ab-171d-41fc-8d85-3e59248bae8c\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"f700f569-7f02-4095-a11e-7cc4c646d580\"],\n          \"id\": \"0b9ec7e1-bf0d-44d3-a545-ec91d0197ef1\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"6a89fa03-8c35-447e-97de-06505b68ade6\"],\n          \"id\": \"8cf6055e-381d-49e1-8895-e680bfbe534c\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"1d0a5e5f-3d0a-4240-81ed-1a3f20c5e650\"],\n          \"id\": \"d2ab89a4-5ff5-4f4c-9d06-93537334ff99\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"55bbab18-af70-45ef-b6fb-9e63047a95ec\"],\n          \"id\": \"9314f0f1-b54c-4e6c-b3f5-b2b856c90f23\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"9055c5bf-3c21-4bcf-8f9e-385c97eadcd3\"],\n          \"id\": \"2abd3b14-2aa5-4493-abe6-3c7bfddf2f07\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"7d971b82-b5fb-4824-a71a-13ca149778fd\"],\n          \"id\": \"96eb7d28-1994-49af-9969-ad712de97a27\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"bea347c7-f003-4a22-9d35-46a06cfc26b0\"],\n          \"id\": \"f15061ed-4ed3-4096-b5be-cca2966f8612\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"1ad4ebfe-246a-490b-aef4-9b14c209d0da\"],\n          \"id\": \"12df2e12-b20f-45b9-b37a-49d87a03b660\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"8b3ab1a7-fe74-450d-a941-620b5cb3d640\"],\n          \"id\": \"d047a9e7-ad99-4a03-9878-1782cbba58d0\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"5648ecdd-8c6d-4a1d-a998-399e06efa300\"],\n          \"id\": \"8514d57e-c8e7-43cc-9710-aefd8d43fbe7\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"f2b32ce2-6f83-46e3-bfcb-1b6c44517d8f\"],\n          \"id\": \"45164e4a-d611-4e29-b459-99d5de744682\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"de7f2512-0e84-4e3d-a1bf-c31f983a24f9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"106fc2c7-7d31-41ab-968b-e6047b1c20f7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"028c2dec-abc6-4aff-9c93-877b1b12cc17\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5cae9bae-9534-45d6-b76d-4761fe8634b0\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"55fe8275-024e-4971-a9eb-d0f55a89c237\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"af4c00bc-6fc6-475f-9868-72805d8a6a85\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 400,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 18, \"g\": 18, \"b\": 18 } },\n      \"type\": \"page\",\n      \"id\": \"0dad6441-df61-4869-a687-d9a56a082046\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"d322a8ce-765a-4050-b7a7-86ddecf4b937\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"65c27a80-9505-4587-ab6f-8b0e4c5cd0fd\": {\n          \"name\": \"Venue\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2d55153e-230e-4851-a457-b2fb7b9d0e68\": {\n          \"name\": \"Date\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ded72301-f80b-4a39-a726-d1bd0027935a\": {\n          \"name\": \"Showtime\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a2065c2a-7fd8-454d-a28b-d1fd6bf1a558\": {\n          \"name\": \"Age\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6c69de29-c841-4b13-bf94-ff38ad8efcc7\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"76d046ff-2573-4dc6-8451-e24f24d7d319\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:46:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White distributed particles on black backdrop\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#ac3c3c\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.09,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 500\\\">More Events</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 288,\n          \"height\": 48,\n          \"id\": \"2d3c8f89-2efb-4a6a-98bd-0363655bae0f\",\n          \"x\": 48,\n          \"y\": -1,\n          \"type\": \"text\",\n          \"tagName\": \"auto\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:49:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page13_image1.jpg\",\n            \"width\": 780,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"People gathering on concert field\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#12150f\",\n            \"isExternal\": true\n          },\n          \"x\": 35,\n          \"y\": 68,\n          \"width\": 325,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"41d92af7-fe49-4453-906f-b7eccf26b4ef\",\n          \"type\": \"image\",\n          \"groupId\": \"caf28278-b654-4345-8139-80127981e025\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Hybrid Minds</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 110,\n          \"height\": 18,\n          \"id\": \"e8447e1b-24f3-40da-a8dc-fee9898923e3\",\n          \"x\": 261,\n          \"y\": 280,\n          \"type\": \"text\",\n          \"groupId\": \"caf28278-b654-4345-8139-80127981e025\"\n        },\n        {\n          \"opacity\": 30,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 108,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">9/30</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 256,\n          \"height\": 127,\n          \"id\": \"8c4a7012-bd08-43e4-ae06-f57c07cdea99\",\n          \"x\": 9,\n          \"y\": 213,\n          \"type\": \"text\",\n          \"groupId\": \"caf28278-b654-4345-8139-80127981e025\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -1,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 35,\n          \"y\": 362,\n          \"id\": \"41ab9d9c-49a4-4d02-959d-cd656f3d3cf7\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-23T12:50:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/new-york-party-round-up/page13_image2.jpg\",\n            \"width\": 780,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Selective focus silhouette photography of man playing red-lighted DJ terminal\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#110427\",\n            \"isExternal\": true\n          },\n          \"width\": 325,\n          \"height\": 200,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"groupId\": \"4a3c19d2-089e-4598-94ac-844853a91361\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.34,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 288,\n          \"y\": 580,\n          \"id\": \"750a88ea-7448-418c-829b-c15bf671d459\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Subfocus</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 97,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"4a3c19d2-089e-4598-94ac-844853a91361\"\n        },\n        {\n          \"opacity\": 30,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 108,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.73,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": -1,\n          \"y\": 523,\n          \"id\": \"19e0c202-deae-42f4-89d2-d127b1d536e9\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">10/12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 290,\n          \"height\": 127,\n          \"type\": \"text\",\n          \"groupId\": \"4a3c19d2-089e-4598-94ac-844853a91361\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"26b84ef9-a614-4c34-b879-27526d00f834\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"0c895083-d433-4f42-af00-f680c3f9fa49\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"caf28278-b654-4345-8139-80127981e025\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4a3c19d2-089e-4598-94ac-844853a91361\": {\n          \"name\": \"Event\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/no-days-off/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/no-days-off/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'no-days-off',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('No Days Off', 'template name', 'web-stories'),\n  tags: [\n    _x('Exercise', 'template keyword', 'web-stories'),\n    _x('Fitness', 'template keyword', 'web-stories'),\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Workout', 'template keyword', 'web-stories'),\n    _x('Bold', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#1a1a1a',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Red', 'color', 'web-stories'),\n      color: '#cf1323',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This modern, bold theme lends itself well for workout routines, fitness gear shopping lists, but also tech, internet and gadget news, reviews, recommendations and coverage, due to its timeless, simple look.',\n    'web-stories'\n  ),\n  vertical: _x('Fitness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/no-days-off/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/no-days-off/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 97,\n          \"y\": -319,\n          \"width\": 330,\n          \"height\": 586,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"40b3440b-fdf1-4969-8469-4af6e9d49cb2\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#a9141c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page1_bg-red.png\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page1_bg-red\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 21,\n          \"y\": 227,\n          \"width\": 390,\n          \"height\": 392,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.74,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9fc66e49-85dd-477d-8bb9-30ae259bc7fe\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.03em; text-transform: uppercase\\\">No</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.03em; text-transform: uppercase\\\">Days</span>\\n<span style=\\\"font-weight: 600; color: rgba(255,255,255,0.4); letter-spacing: -0.03em; text-transform: uppercase\\\">Off</span>\",\n          \"fontSize\": 178,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page1_logo-generic.png\",\n            \"width\": 79,\n            \"height\": 22,\n            \"id\": 0,\n            \"alt\": \"page1_logo-generic\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 20,\n          \"y\": 24,\n          \"width\": 81,\n          \"height\": 23,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"898ed4f5-c704-459c-be51-be8daeaab737\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"2572f4a4-bb11-47e2-9f77-b8371aeabe49\",\n      \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n        \"x\": 10.73767307309668,\n        \"y\": 73.81953888501366,\n        \"width\": 146.66666666666666,\n        \"height\": 146.66666666666666,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"5e0a9de6-0c71-42fb-8d26-7beb33ce55c0\",\n        \"isDefaultBackground\": true\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"65bb259e-6b72-4009-af27-3c19ee9d34e7\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": 0,\n          \"width\": 412,\n          \"height\": 598,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page2_figure-formatted.png\",\n            \"width\": 220,\n            \"height\": 350,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page2_figure-formatted\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#ab141c\"\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"f7bd8df7-6f90-47c8-8c88-9c9db3183eea\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 397,\n          \"width\": 319,\n          \"height\": 178,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"e44d4b12-221b-4fbf-96be-8a3c81e26f7c\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: -0.03em; text-transform: uppercase\\\">“To get to greatness, you have to be willing to get out of your comfort zone.”</span>\",\n          \"fontSize\": 46,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 117,\n          \"y\": 587,\n          \"width\": 284,\n          \"height\": 22,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"7fc0fd6e-ce7e-4be9-925c-c30a39d7cfeb\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: -0.03em; text-transform: uppercase\\\">-Anonymous</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6b163eb5-6d90-4aa4-b90b-fdfcfafad296\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7fc0fd6e-ce7e-4be9-925c-c30a39d7cfeb\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 600,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"1375c821-23f1-468c-ac6a-391ea691d60c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e44d4b12-221b-4fbf-96be-8a3c81e26f7c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 600\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"708fbc22-f0ca-40ec-9a57-21d9eb0be6b7\",\n      \"backgroundColor\": { \"color\": { \"r\": 26, \"g\": 26, \"b\": 26 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"dd764483-9e29-4aab-bb58-445d1f043d1a\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page3_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_bg\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#1c1c1c\"\n          },\n          \"scale\": 150,\n          \"focalX\": 50,\n          \"focalY\": 46.89484126984126\n        },\n        {\n          \"x\": 65,\n          \"y\": 19,\n          \"width\": 282,\n          \"height\": 154,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.74,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"8e351291-f603-459c-883b-66ba0d036694\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: rgba(207,19,35,0.4); letter-spacing: -0.03em; text-transform: uppercase\\\">Run</span>\",\n          \"fontSize\": 209,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 12,\n          \"y\": 136,\n          \"width\": 400,\n          \"height\": 112,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.72,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"b4571f66-24f3-4908-8c18-8ac378735fb9\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Like You</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Mean It</span>\",\n          \"fontSize\": 79,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 88,\n          \"y\": 267,\n          \"width\": 235,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"002f9bfc-2f7a-45b0-b900-78251f2746f1\",\n          \"content\": \"<span style=\\\"color: rgba(136, 136, 136, 1)\\\">Our lead editor shares tips on how to best start running</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cb6bb07b-8b73-462e-a19f-ac1fe9d52680\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"8e351291-f603-459c-883b-66ba0d036694\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1b305aa1-cbc1-4f46-9b6c-822951e0d21c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b4571f66-24f3-4908-8c18-8ac378735fb9\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4b9623a7-3e35-4d5d-984a-26399b93b92c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"002f9bfc-2f7a-45b0-b900-78251f2746f1\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 800,\n          \"delay\": 1100\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"2dbd86ab-dab1-4142-996a-5932a57797b3\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"c324efb7-dd3a-4cce-b780-f3fde3cc94f2\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 16, \"g\": 16, \"b\": 16, \"a\": 1 } },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": -95,\n          \"y\": -160,\n          \"width\": 330,\n          \"height\": 308,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0ed58ad7-eed6-4f1a-80a5-7ce92991677f\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#c01323\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page4_bg-red.png\",\n            \"width\": 330,\n            \"height\": 308,\n            \"id\": 0,\n            \"alt\": \"page4_bg-red\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": false,\n          \"type\": \"image\",\n          \"id\": \"13b1c45d-c6e8-4e59-acde-67f4b2b6ef0c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#e0dde2\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page4_bg.jpg\",\n            \"width\": 220,\n            \"height\": 288,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"scale\": 100,\n          \"focalX\": 49.97721576668946,\n          \"focalY\": 33.03397382344752\n        },\n        {\n          \"x\": 164,\n          \"y\": -129,\n          \"width\": 235,\n          \"height\": 702,\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"37864aea-dc9e-42c6-bcf2-c1fbc93de1b1\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 600\\\">5</span></span>\",\n          \"fontSize\": 540,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 326,\n          \"width\": 311,\n          \"height\": 204,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7470ab2a-4a73-49aa-aaf5-74cfafb51adb\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Top</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Distance</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Running</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Shoes</span>\",\n          \"fontSize\": 74,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 52,\n          \"y\": 534,\n          \"width\": 276,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9832faa6-2c7e-43eb-b75a-b68051da626a\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Hit the trails with the latest and greatest lightweight mid-distance shoes for the season.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"18d5cbd3-17bf-49ef-992f-90a12be3ea42\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"37864aea-dc9e-42c6-bcf2-c1fbc93de1b1\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"502c8040-a29f-40a8-9cf5-c44325fb8442\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7470ab2a-4a73-49aa-aaf5-74cfafb51adb\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 800,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"1ed97725-0146-409e-afe5-b3ca52f6819e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9832faa6-2c7e-43eb-b75a-b68051da626a\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 900,\n          \"delay\": 1000\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"97a844aa-4ff5-4875-aac0-682bd51b087e\",\n      \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n      \"defaultBackgroundElement\": {\n        \"x\": 37,\n        \"y\": 2,\n        \"width\": 137,\n        \"height\": 137,\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"aef43d55-bf5e-4175-8975-1637ce53d9ca\",\n        \"isDefaultBackground\": true\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": -46,\n          \"y\": 475,\n          \"width\": 330,\n          \"height\": 295,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"19e74314-7e11-49dd-ab9f-42155fb93091\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page5_bg-no-logo.png\",\n            \"width\": 330,\n            \"height\": 295,\n            \"id\": 0,\n            \"alt\": \"page5_bg-no-logo\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#ca0c20\"\n          },\n          \"scale\": 100,\n          \"focalX\": 38.367113188634875,\n          \"focalY\": 49.953358674938045\n        },\n        {\n          \"x\": 22,\n          \"y\": 16,\n          \"width\": 311,\n          \"height\": 102,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"09d35ab8-76f0-4252-838d-4eb54a99c2b3\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">The Woven</span>\\n<span style=\\\"font-weight: 600; color: #fff; letter-spacing: -0.01em; text-transform: uppercase\\\">Runner</span>\",\n          \"fontSize\": 74,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 22,\n          \"y\": 145,\n          \"width\": 154,\n          \"height\": 147,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"73bdf015-c3f1-41fb-bc24-79a1b881d914\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Ideal for runs up to 3 miles, the Woven Runner delivers a lightweight design &amp; breathable slip so you can get in and hit your stride.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 225,\n          \"y\": 310,\n          \"width\": 235,\n          \"height\": 367,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a849f15a-ed9b-4589-abe0-c19da7abfcf4\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: rgba(255,255,255,0.4)\\\">3</span>\",\n          \"fontSize\": 408,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 21,\n          \"y\": 319,\n          \"width\": 100,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 26, \"g\": 26, \"b\": 26 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"5ae621aa-0b73-4f4f-888b-ba3787156bf0\"\n        },\n        {\n          \"x\": 33.5,\n          \"y\": 327,\n          \"width\": 75,\n          \"height\": 20,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"d4bdc028-59aa-4adc-8762-570676202dc3\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Buy Now</span>\",\n          \"fontSize\": 20,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e1c4d78b-a7f1-409c-ba16-d4c21b3714f6\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"a849f15a-ed9b-4589-abe0-c19da7abfcf4\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a68fdb58-c34b-4888-b1ca-294d36ed9d49\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5ae621aa-0b73-4f4f-888b-ba3787156bf0\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7932f21e-c310-46c6-8668-259fc7236668\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d4bdc028-59aa-4adc-8762-570676202dc3\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"00b17b67-2789-46b6-ac1b-0509ec00542f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"09d35ab8-76f0-4252-838d-4eb54a99c2b3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 900,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"c431803a-7a5f-4a44-be03-2e0c3bfd97d4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"73bdf015-c3f1-41fb-bc24-79a1b881d914\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 900,\n          \"delay\": 900\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"52b7935e-e379-4596-bfbc-3b1ea5ca3503\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ff86e4bb-4a5c-446d-81c5-0bcd77bd8086\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"05e35040-f294-42da-b67d-dfd39327b2d8\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#e0ddde\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page6_bg.jpg\",\n            \"width\": 220,\n            \"height\": 165,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 130,\n          \"focalX\": 52.684313245208656,\n          \"focalY\": 47.775163796764,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-06-30T20:40:21\",\n            \"baseColor\": \"#292929\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page6_watch.png\",\n            \"width\": 330,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_watch\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 69,\n          \"y\": 122,\n          \"width\": 273,\n          \"height\": 326,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"ca5cbef2-1ef0-435d-a6e5-4b46e985fb0a\"\n        },\n        {\n          \"x\": 40,\n          \"y\": 21,\n          \"width\": 252,\n          \"height\": 313,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"885a6a97-1fb8-4303-a27c-151395801c5b\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #cf1323; text-transform: uppercase\\\">The Best</span>\\n<span style=\\\"font-weight: 600; color: #1a1a1a; text-transform: uppercase\\\">Running</span>\\n<span style=\\\"font-weight: 600; color: #cf1323; text-transform: uppercase\\\">Tech</span>\",\n          \"fontSize\": 74,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 5,\n          \"y\": 462,\n          \"width\": 402,\n          \"height\": 46,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c432d288-5b66-4c40-8141-060cc29f9ee6\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #1a1a1a; letter-spacing: -0.01em; text-transform: uppercase\\\">The Perfect Mate</span>\",\n          \"fontSize\": 46,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 52,\n          \"y\": 504,\n          \"width\": 307,\n          \"height\": 84,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Hind\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1055,\n              \"des\": -546,\n              \"tAsc\": 1055,\n              \"tDes\": -546,\n              \"tLGap\": 0,\n              \"wAsc\": 1055,\n              \"wDes\": 546,\n              \"xH\": 505,\n              \"capH\": 679,\n              \"yMin\": -440,\n              \"yMax\": 1003,\n              \"hAsc\": 1055,\n              \"hDes\": -546,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.22,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ae9a760a-a4e8-4759-8407-001b3eb243f3\",\n          \"content\": \"<span style=\\\"color: rgba(26, 26, 26, 1)\\\">Whether you’re an elite athlete or you just want to track your daily activity, Apple Watch Series 5 helps you train smarter to get results faster.</span>\",\n          \"fontSize\": 18,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4151af3a-aeff-4e12-994c-055d8651fba7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"885a6a97-1fb8-4303-a27c-151395801c5b\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"74f6aa85-dc53-4219-9d54-f2fddfa5ffa7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ca5cbef2-1ef0-435d-a6e5-4b46e985fb0a\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9c4b43d2-8617-4ed9-a8f7-78f6fac6271f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c432d288-5b66-4c40-8141-060cc29f9ee6\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"bad0a4f5-7ce1-4043-aeb8-8a13e58590df\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ae9a760a-a4e8-4759-8407-001b3eb243f3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 600,\n          \"delay\": 700\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"95ae824a-7060-46cb-a8d2-8d6a721ad1ff\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"506b7e72-d072-474a-9fd7-289c1ba8b707\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 87,\n          \"y\": -221,\n          \"width\": 330,\n          \"height\": 239,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1613baad-b2a9-42e7-b0a6-d2f4c6941f65\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#22131c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page7_bg-red.png\",\n            \"width\": 330,\n            \"height\": 239,\n            \"id\": 0,\n            \"alt\": \"page7_bg-red\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 17,\n          \"y\": 28,\n          \"width\": 311,\n          \"height\": 151,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.76,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"5d25ecb0-3056-4597-ba08-44e958de6069\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Gear</span>\\n<span style=\\\"font-weight: 600; color: rgba(255,255,255,0.4); text-transform: uppercase\\\">Up</span>\",\n          \"fontSize\": 100,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 226,\n          \"y\": 140,\n          \"width\": 40,\n          \"height\": 40,\n          \"sticker\": { \"type\": \"fitnessCTA\" },\n          \"id\": \"c4da9212-236c-4fcf-b3ae-5029b03ff5cc\",\n          \"link\": {\n            \"url\": \"https://example.com/\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 40,\n          \"height\": 40,\n          \"sticker\": { \"type\": \"fitnessCTA\" },\n          \"id\": \"eb560c41-66a8-4b87-8447-aa42601cc960\",\n          \"x\": 129,\n          \"y\": 356,\n          \"link\": {\n            \"url\": \"https://example.com/\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f5c7034e-c6bb-4a7b-8165-b4cd097d0e79\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5d25ecb0-3056-4597-ba08-44e958de6069\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 450\n        },\n        {\n          \"id\": \"d12716ac-9cf2-45d5-99d9-3f4b00bcb739\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"c4da9212-236c-4fcf-b3ae-5029b03ff5cc\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"69138ccb-0d11-4bbc-b6ae-d6850d6dba55\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"eb560c41-66a8-4b87-8447-aa42601cc960\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"a30a33fc-d687-4e94-8a2c-0f9546a21efe\",\n      \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n      \"defaultBackgroundElement\": {\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 180, \"g\": 17, \"b\": 31 } },\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"6b7a12c9-81f2-4cf8-8868-6f5d741646e1\",\n        \"isDefaultBackground\": true\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"641d6b05-3e8c-4c1e-8e57-b1d1a528c119\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": 447,\n          \"width\": 207,\n          \"height\": 210,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#a2b7cb\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page8_story3-formatted.png\",\n            \"width\": 95,\n            \"height\": 97,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_story3-formatted\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"ffd4e077-5c4c-4baa-bc7f-56f09b29d0d6\"\n        },\n        {\n          \"x\": 2,\n          \"y\": 178,\n          \"width\": 204,\n          \"height\": 209,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#d5d1cf\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page8_story1-formatted.png\",\n            \"width\": 95,\n            \"height\": 97,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_story1-formatted\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"90f9d543-7728-49f6-a241-965847b7b4ab\"\n        },\n        {\n          \"x\": -1,\n          \"y\": 283,\n          \"width\": 413,\n          \"height\": 213,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#ddc7b4\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/no-days-off/page8_story2-formatted.png\",\n            \"width\": 188,\n            \"height\": 97,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_story2-formatted\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"f8f33b69-fab8-40e2-ac67-e1dc8bb5f8ca\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 11,\n          \"width\": 311,\n          \"height\": 151,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.76,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7447a2ba-a336-4618-beb2-8423ebc1ddc3\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #cf1323; letter-spacing: -0.01em; text-transform: uppercase\\\">More</span>\\n<span style=\\\"font-weight: 600; color: rgba(255,255,255,0.4); letter-spacing: -0.01em; text-transform: uppercase\\\">Stories</span>\",\n          \"fontSize\": 100,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 243,\n          \"y\": 207,\n          \"width\": 137,\n          \"height\": 66,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"96fea994-b71e-442f-b611-16d73f520016\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Sweat</span>\\n<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Resistant</span>\\n<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Earbuds</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 49,\n          \"y\": 359,\n          \"width\": 137,\n          \"height\": 66,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9b117b87-0269-4c4b-9e0d-8cdbcb0df89a\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 600; text-transform: uppercase\\\">10 Best Coretraining Exercises</span></span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 242,\n          \"y\": 488,\n          \"width\": 157,\n          \"height\": 66,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"03c44ea1-7ec8-4bdf-8e49-bb43ba83b2f3\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Triathlon</span>\\n<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">Training</span>\\n<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">in The Summer</span>\",\n          \"fontSize\": 22,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f60d21a4-8b2b-48b3-9109-d31a3a782e11\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"7447a2ba-a336-4618-beb2-8423ebc1ddc3\"],\n          \"scale\": 0.05,\n          \"iterations\": 3,\n          \"duration\": 600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c58db8b5-626b-401f-a10e-76f81147bf90\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"96fea994-b71e-442f-b611-16d73f520016\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 550\n        },\n        {\n          \"id\": \"8eda0f74-b81b-4f45-8c16-7d708165b666\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"90f9d543-7728-49f6-a241-965847b7b4ab\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"dd8d001d-6548-4278-8237-d158f610b92e\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"9b117b87-0269-4c4b-9e0d-8cdbcb0df89a\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 650\n        },\n        {\n          \"id\": \"c3fcdcec-8b65-40dd-a977-ac149e178707\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"f8f33b69-fab8-40e2-ac67-e1dc8bb5f8ca\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"43e9b58e-88f9-4501-adf2-0849a63319b3\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"ffd4e077-5c4c-4baa-bc7f-56f09b29d0d6\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 700\n        },\n        {\n          \"id\": \"a3b296ea-166e-414d-8ae7-6218193e4be4\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"03c44ea1-7ec8-4bdf-8e49-bb43ba83b2f3\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 750\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"d65c11a1-5f71-48ff-8579-85d53f18d461\",\n      \"backgroundColor\": { \"color\": { \"r\": 26, \"g\": 26, \"b\": 26 } },\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/one-day-city-itinerary/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/one-day-city-itinerary/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'one-day-city-itinerary',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('One Day City Itinerary', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Brochure', 'template keyword', 'web-stories'),\n    _x('Guide', 'template keyword', 'web-stories'),\n    _x('Aesthetic', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Berry Red', 'color', 'web-stories'),\n      color: '#e0193e',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Havana White', 'color', 'web-stories'),\n      color: '#f7ece3',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its combination of 3 beautiful fonts, curved sections and bright colors, this template is equipped with the liveliness of an elegant travel magazine. Create one-day itineraries, sight-seeing guides and other stories for urban travel. Change the colors to suit your style.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/one-day-city-itinerary/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/one-day-city-itinerary/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -67,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"eb99f440-ff97-40f9-89ce-8f3a34f494b2\",\n          \"scale\": 106,\n          \"focalX\": 53.271028037383175,\n          \"focalY\": 49.877766709779706,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page01_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Photo of architecture, coin operated binoculars, downtown\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#5e4e45\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8de39806-d64c-4a4b-968c-faac7a578a09\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -435,\n          \"y\": -127.5,\n          \"width\": 1000,\n          \"height\": 710,\n          \"sticker\": { \"type\": \"soloSundayRedSectionSeparator\" },\n          \"id\": \"cde01e69-55d1-4c98-afc6-6931200ec709\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.1em; text-transform: uppercase\\\">By Betty Doe / July 23, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 590,\n          \"width\": 290,\n          \"height\": 18,\n          \"id\": \"a6eae420-bfcf-449f-a435-a66045ab7bd6\",\n          \"marginOffset\": 0.703125\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 100,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Solo Sunday in Your City</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": -6,\n          \"width\": 310,\n          \"height\": 436,\n          \"id\": \"9d29ef73-b53f-47b2-8ecd-c3a088e97f24\",\n          \"marginOffset\": -48.90899999999999\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9f4f55f2-969a-4027-875f-1a67fb1e2548\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"3e997ccb-11df-4886-af13-49736e79b954\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 174,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"6941fbad-3390-47e7-be73-f867ba4f3234\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-08-03T06:38:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page02_05_bgvideo.mp4\",\n            \"width\": 1365,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page02_05_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"alt\": \"Stock video of a woman speaking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#b7b1b0\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 328,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -302,\n          \"y\": 392,\n          \"width\": 934,\n          \"height\": 514,\n          \"sticker\": { \"type\": \"soloSundayCreamSectionSeparator\" },\n          \"id\": \"e4f54f5d-1fe1-4baa-8f26-c297b970e767\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #e0193e\\\">Betty Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 71,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"afd470c6-f92b-4c3e-9e9a-b0199d4a90fa\",\n          \"x\": 55,\n          \"y\": 518,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 55,\n          \"y\": 583,\n          \"id\": \"bfe53929-c226-4a63-a952-e871aa77f7e0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #e0193e; letter-spacing: 0.01em\\\">@BettysBigCity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 20,\n          \"marginOffset\": -48.90899999999999\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2c6e8501-d399-45fe-a92b-ffacced265c3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"9287ab9c-ebb5-43f0-85cd-5b265569a2d6\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"fb4b2b79-0692-4c3f-8428-a77852c8a32e\",\n          \"scale\": 108,\n          \"focalX\": 46.13455603038935,\n          \"focalY\": 53.623162320128856,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:39:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Person touching a cup of coffee and a plate with food\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#c0a077\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.3\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"94cf3a2e-dcb4-4ef5-bd7d-4cc8ad532af2\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 208,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -51,\n          \"y\": -231,\n          \"width\": 610,\n          \"height\": 485,\n          \"sticker\": { \"type\": \"soloSundayRedSectionSeparator\" },\n          \"id\": \"755ecf83-5b3b-4df7-a2f8-217da4e6922a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f7ece3; letter-spacing: 0.01em\\\">Morning</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 88,\n          \"height\": 24,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"253afcbd-78ba-4865-9560-ad8ad50a582e\",\n          \"x\": 51,\n          \"y\": 9\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Treat yourself</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 85,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"d82fc575-69b6-4a88-919c-db015e6665b7\",\n          \"x\": 51,\n          \"y\": 38\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8d5c5b9d-148d-4ae4-9041-704c4a2f92de\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"fb4b2b79-0692-4c3f-8428-a77852c8a32e\"]\n        },\n        {\n          \"id\": \"81f14d6a-45fa-4a81-92a4-9ed37dce5bce\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d82fc575-69b6-4a88-919c-db015e6665b7\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2b09ba7c-c688-4e5d-b7ba-ed06896ae1a5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"6aaff808-c6f5-49d1-b9d5-942350f7a58d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 107,\n          \"focalX\": 46.59267912772586,\n          \"focalY\": 49.86309871495326,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:39:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Open brown wooden french door\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#b1a39c\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"b2318fb1-d4eb-463b-a293-20c3343f7db2\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.21 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Freemans</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 71,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"3f24b7a4-052e-4c65-bc25-5fef0687a9fb\",\n          \"x\": 51,\n          \"y\": 450,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.01em\\\">Freeman Alley, NYC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 194,\n          \"height\": 20,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"970ef88d-e5ca-43c2-975b-7f70e3553f24\",\n          \"x\": 74,\n          \"y\": 511,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 547,\n          \"id\": \"d6c86be7-ee2a-4bad-b96b-e3ea14a5269c\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">Hidden-away spot with amazing craft cocktails &amp; colonial tavern decor.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 43,\n          \"marginOffset\": -3.285,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -1,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 204,\n          \"y\": 375,\n          \"id\": \"36c8886c-cfa4-4193-8cb2-91b38b621f5b\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Top Coffee</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 43,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 204,\n          \"y\": 416,\n          \"width\": 129,\n          \"height\": 7,\n          \"sticker\": { \"type\": \"soloSundayWhiteLine\" },\n          \"id\": \"76286d5f-5788-43ac-a007-456afd6cc3cf\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 56,\n          \"y\": 513,\n          \"width\": 13,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"soloSundayOffWhiteLocation\" },\n          \"id\": \"b3f7d62e-b5ee-4a57-92a5-4ed9d553d0ec\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0aa8f0fb-3edb-4567-9c74-35d980a0d4fe\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"b2318fb1-d4eb-463b-a293-20c3343f7db2\"]\n        },\n        {\n          \"id\": \"67f392f2-2216-44cc-b30d-cdbee0a21acf\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"36c8886c-cfa4-4193-8cb2-91b38b621f5b\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"b50143dc-d0ff-48a8-b057-3909043764bf\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"76286d5f-5788-43ac-a007-456afd6cc3cf\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d2b392eb-a10a-4ffe-9e3b-a462ba6b4a43\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"61ccf886-a095-4e67-a531-5e75a52b50b8\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 174,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c80008ce-1249-41a8-a68c-edb0094b41fd\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-08-03T06:38:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page02_05_bgvideo.mp4\",\n            \"width\": 1365,\n            \"height\": 720,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page02_05_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 9,\n            \"lengthFormatted\": \"0:09\",\n            \"alt\": \"Stock video of a woman speaking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#b7b1b0\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.3\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8ec93b33-9234-4fca-adf6-ae7752dbaa22\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 208,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 610,\n          \"height\": 485,\n          \"sticker\": { \"type\": \"soloSundayRedSectionSeparator\" },\n          \"id\": \"e1d01635-e673-47ba-b962-f7a2657615ad\",\n          \"x\": -51,\n          \"y\": -231\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f7ece3; letter-spacing: 0.01em\\\">Afternoon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 120,\n          \"height\": 24,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"a1bb7bd9-4c45-4884-8586-681935b3b403\",\n          \"x\": 51,\n          \"y\": 9,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Explore</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 83,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"51d6a217-bc2a-48c8-9f71-fe7555b76b88\",\n          \"x\": 51,\n          \"y\": 38,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"81f7d5a0-dd10-4773-aca4-0cc5d4ac2680\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"51d6a217-bc2a-48c8-9f71-fe7555b76b88\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9262aae9-2879-4a06-98a5-1261f64bf320\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"c9dbb706-044e-4bbd-a5f9-dfaef4664406\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 107,\n          \"focalX\": 53.13473520249221,\n          \"focalY\": 49.86309871495327,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:40:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Gray concrete buildings beside trees at daytime photo in Central Park, NYC\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#473222\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d797d393-5397-43b3-aefd-45b5763c7d59\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.23 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Central Park</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 71,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"44337e92-e554-414e-b88c-d50f80649dd2\",\n          \"x\": 51,\n          \"y\": 450,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.01em\\\">Central Park Deli - New York, NY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 287,\n          \"height\": 20,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"bf9195b3-150c-4833-a552-01881229213f\",\n          \"x\": 74,\n          \"y\": 511,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 547,\n          \"id\": \"cac33b6d-700b-4549-85ba-d59e1495065e\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">The best greenery, sights, and smells to take in and take an aimless stroll to.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 44,\n          \"marginOffset\": -3.285,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 49,\n          \"y\": 364,\n          \"id\": \"80a6e2b3-af35-4ecc-88e0-943a3d1ad450\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Love running here...</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 41,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"soloSundayOffWhiteLocation\" },\n          \"id\": \"4ce14ff4-42ab-4d3d-aea0-ea7129ece010\",\n          \"x\": 56,\n          \"y\": 513,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 356,\n          \"lockAspectRatio\": true,\n          \"x\": 51,\n          \"y\": 403,\n          \"width\": 240,\n          \"height\": 13,\n          \"sticker\": { \"type\": \"soloSundayWhiteLine\" },\n          \"id\": \"7f65daeb-7ac4-450a-82c1-dd715eff305b\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5b44d55a-1df4-4e5e-8986-805712926d28\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"80a6e2b3-af35-4ecc-88e0-943a3d1ad450\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"a15be4c0-04a5-4ce5-88bf-27a77c7c60bf\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"d797d393-5397-43b3-aefd-45b5763c7d59\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"90e78c41-3286-4ae8-9c44-fbe6b6d24acc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7f65daeb-7ac4-450a-82c1-dd715eff305b\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"774ff109-de04-41a5-941b-04b384608e92\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"d8fbb296-d38f-461f-87b1-77cad986f827\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 107,\n          \"focalX\": 50,\n          \"focalY\": 46.71437189690422,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:40:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page07_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"New York City Cityscape Photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#94a2ca\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"5d6669c1-92f3-41ef-b3e9-4b194fef2851\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.23 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Empire State</span>\\n<span style=\\\"color: #f7ece3\\\">Building</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 119,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"2b901966-2731-4cbe-87e9-3fc1d1fdecab\",\n          \"x\": 51,\n          \"y\": 399,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.01em\\\">Empire State - New York, NY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 257,\n          \"height\": 20,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"3eb53c87-0f9e-44c7-9bbe-5f6e1406cbb0\",\n          \"x\": 74,\n          \"y\": 511,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 547,\n          \"id\": \"9a78a949-2415-4a95-a641-fef70273f017\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">One of my favorite restaurants is on the bottom floor.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 44,\n          \"marginOffset\": -3.285,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 122,\n          \"y\": 290,\n          \"id\": \"7452ff3d-d9d5-4d98-9ea7-17570bbe639b\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Nice views</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 41,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 359,\n          \"lockAspectRatio\": true,\n          \"width\": 126,\n          \"height\": 7,\n          \"sticker\": { \"type\": \"soloSundayWhiteLine\" },\n          \"id\": \"ed23d342-0726-4c43-b08d-435b20d92447\",\n          \"x\": 121,\n          \"y\": 334,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 13,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"soloSundayOffWhiteLocation\" },\n          \"id\": \"fc8f276a-a564-42bd-ac43-1ad2a3cb8504\",\n          \"x\": 56,\n          \"y\": 513,\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3bbde680-7180-4f34-ba83-6720ceef5d80\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"5d6669c1-92f3-41ef-b3e9-4b194fef2851\"],\n          \"panDir\": \"topToBottom\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b1ededf6-f942-4326-ac28-017eaeb481fd\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"a6fe8f26-55bf-49f4-be04-d80bc4491ef2\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d65b7380-8060-4861-b34e-cca0fe6e1687\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:40:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in black jacket carrying backpack with tousled hair walking on the street at night\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#121d23\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2f470366-41f6-4786-8495-e85d3067d926\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 208,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 610,\n          \"height\": 485,\n          \"sticker\": { \"type\": \"soloSundayRedSectionSeparator\" },\n          \"id\": \"d01be94a-dea6-40dd-9d48-b6d9306a8f7f\",\n          \"x\": -51,\n          \"y\": -231\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #f7ece3; letter-spacing: 0.01em\\\">Evening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 120,\n          \"height\": 24,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"6edf6f64-ed81-4731-8d2a-a71c62542450\",\n          \"x\": 51,\n          \"y\": 9,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Enjoy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 83,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"d23c372c-a99c-47c3-9be9-aebb4fafacdd\",\n          \"x\": 51,\n          \"y\": 38,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 56,\n          \"y\": 527,\n          \"id\": \"b63992c6-7a61-4586-95b8-5236f3df7aad\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">I can spend hours at Central Park, but come nighttime...</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 43,\n          \"marginOffset\": -4.380000000000003,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"481f6fc3-07df-4907-9f68-466dc414f9c1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d23c372c-a99c-47c3-9be9-aebb4fafacdd\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7cce7ef0-6de5-4903-8e8f-d9f2cd02a1ea\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"eb4a45f7-73f4-4b96-9a06-87e297890dfa\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:40:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Skyline Photography of Buildings\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#0f1c1f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"16dbedb4-d658-4987-a2d7-dde89da29b8a\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.45 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0.79 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Skyline</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 70,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"34cec1be-cd06-41e2-8cbd-3f13ad10a086\",\n          \"x\": 51,\n          \"y\": 449,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.01em\\\">Central Park Deli - New York, NY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 20,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"53863afc-574c-4df7-bc35-a15bafb4a8e3\",\n          \"x\": 74,\n          \"y\": 511,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 547,\n          \"id\": \"766c61f7-05bd-4318-b885-a000a3906fc7\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">Reveling in your city a little is one way to remember why you moved here.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 40,\n          \"marginOffset\": -3.285,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 50,\n          \"y\": 10,\n          \"id\": \"6207d60a-f752-4ddd-b0f4-830b25c698d9\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">I just need</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">someone to share</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">this moment...</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 102,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 13,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"soloSundayOffWhiteLocation\" },\n          \"id\": \"01541df7-e276-491e-81d7-914e10b9d3a6\",\n          \"x\": 56,\n          \"y\": 513\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 357,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 178,\n          \"height\": 9,\n          \"sticker\": { \"type\": \"soloSundayWhiteLine\" },\n          \"id\": \"50f4a161-35cc-4e43-9cf5-6fd7ca9617b0\",\n          \"x\": 55,\n          \"y\": 113\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"496d883d-373d-4971-bb94-47593630f8f8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6207d60a-f752-4ddd-b0f4-830b25c698d9\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"38563609-72ec-4e05-ae27-306e1c598bab\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"50f4a161-35cc-4e43-9cf5-6fd7ca9617b0\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"6a7c404a-1dd3-40d9-9177-1ffb3926a3bb\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"56e946ca-35c9-4295-947b-1848ba129fef\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T07:40:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Two People on Chair Under Ceiling\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#2e2c2c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c23dd2a6-6f4a-4e82-a261-65ee0bcd0bae\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.38 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0.84 }\n            ],\n            \"alpha\": 0.9\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">Bool</span>\\n<span style=\\\"color: #f7ece3\\\">Restaurant</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 119,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"d6fa66ad-e587-4065-82da-951ef6ee1f41\",\n          \"x\": 51,\n          \"y\": 399,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3; letter-spacing: 0.01em\\\">5th Avenue - New York, NY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 19,\n          \"marginOffset\": -4.380000000000003,\n          \"id\": \"f69a064f-c54e-47f3-a0ee-d562f3629dab\",\n          \"x\": 74,\n          \"y\": 511,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 51,\n          \"y\": 547,\n          \"id\": \"7c84efd4-d925-4556-b897-99e783a4d6c7\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f6f0e8\\\">This Turkish-Mediterranean restaurant is one of my secret spots.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 44,\n          \"marginOffset\": -3.285,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 222,\n          \"y\": 5,\n          \"id\": \"8e964f92-2a01-44dd-bb97-781a7e3a3204\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">Best pasta</span>\\n<span style=\\\"font-weight: 700; color: #fff\\\">of NYC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 77,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 359,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 90,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"soloSundayWhiteLine\" },\n          \"id\": \"fd7680f7-8ae9-474e-b4ca-8e88014a8162\",\n          \"x\": 227,\n          \"y\": 86\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 13,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"soloSundayOffWhiteLocation\" },\n          \"id\": \"75cb08aa-c1bc-46a6-a67b-633d89d494a1\",\n          \"x\": 56,\n          \"y\": 513\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5381dbae-da78-40fa-95fe-8055266bf280\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8e964f92-2a01-44dd-bb97-781a7e3a3204\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"1db638e8-66ef-4f48-a81a-d19af4dfd586\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fd7680f7-8ae9-474e-b4ca-8e88014a8162\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"6368e64d-4dc4-4153-bf0c-bd3c4d845b8f\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"45624d06-dad1-4c0c-9f0b-60197fb9b954\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Viaoda Libre\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1051,\n              \"des\": -360,\n              \"tAsc\": 1051,\n              \"tDes\": -360,\n              \"tLGap\": 0,\n              \"wAsc\": 1051,\n              \"wDes\": 360,\n              \"xH\": 467,\n              \"capH\": 740,\n              \"yMin\": -360,\n              \"yMax\": 1051,\n              \"hAsc\": 1051,\n              \"hDes\": -360,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 80,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #f7ece3\\\">About Betty</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 193,\n          \"marginOffset\": -48.90899999999999,\n          \"id\": \"5a986aac-8c74-45c3-a6bf-2a2cd379c043\",\n          \"x\": 62,\n          \"y\": 198,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 62,\n          \"y\": 387,\n          \"id\": \"5000fd0f-727f-42e8-9b7a-51990ae7b8ca\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Betty has lived in NYC for 14 years and has written numerous articles for The Cut.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 255,\n          \"height\": 116,\n          \"marginOffset\": 3.9819999999999958,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 62,\n          \"y\": 528,\n          \"id\": \"c296c12d-7575-4f44-8609-ac882f55cb5f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 517,\n              \"capH\": 700,\n              \"yMin\": -259,\n              \"yMax\": 1021,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f7ece3\\\">Read more about her</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 20,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Caveat\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 960,\n              \"des\": -300,\n              \"tAsc\": 960,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 974,\n              \"wDes\": 315,\n              \"xH\": 400,\n              \"capH\": 610,\n              \"yMin\": -299,\n              \"yMax\": 960,\n              \"hAsc\": 960,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Betty Simons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 32,\n          \"marginOffset\": -48.90899999999999,\n          \"type\": \"text\",\n          \"id\": \"da4c515c-45ea-4ee2-a2b6-dc4661547908\",\n          \"x\": 62,\n          \"y\": 580,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 208,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 610,\n          \"height\": 488,\n          \"sticker\": { \"type\": \"soloSundayCreamSectionSeparator\" },\n          \"id\": \"f2852804-0e49-4035-8457-2369e834296b\",\n          \"x\": -51,\n          \"y\": -232\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-08-03T05:52:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/one-day-city-itinerary/page11_img01.jpg\",\n            \"width\": 932,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Woman standing wearing blue denim jacket\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#91857b\",\n            \"isExternal\": true\n          },\n          \"x\": 62,\n          \"y\": -4,\n          \"width\": 167,\n          \"height\": 167,\n          \"scale\": 100,\n          \"focalX\": 44.70586723196373,\n          \"focalY\": 50.39255129766638,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"9ec2ee0f-9b0a-4c9d-b0e4-40edf5b387a9\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"040d1806-bab7-4d5e-a6aa-439c65091c4e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"da4c515c-45ea-4ee2-a2b6-dc4661547908\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 224, \"g\": 25, \"b\": 62 } },\n      \"type\": \"page\",\n      \"id\": \"46126af3-a79c-47cc-8aba-7fdd15d9f64f\",\n      \"pageTemplateType\": \"editorial\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/pizzas-in-nyc/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/pizzas-in-nyc/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'pizzas-in-nyc',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Pizzas in NYC', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Food', 'template keyword', 'web-stories'),\n    _x('Restaurant', 'template keyword', 'web-stories'),\n    _x('Pizza', 'template keyword', 'web-stories'),\n    _x('Orange', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Canyon Orange', 'color', 'web-stories'),\n      color: '#a36431',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Warm Yellow', 'color', 'web-stories'),\n      color: '#f8bc63',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Raisin Black', 'color', 'web-stories'),\n      color: '#262626',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Magnolia White', 'color', 'web-stories'),\n      color: '#fef9f1',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Use the neutral typography, layout, and brush strokes of this template to your advantage and turn it into your own beautiful travel story, tutorial, or even a cooking recipe. Mix, match and reuse the pages, and change the colors to fit your style.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/pizzas-in-nyc/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/pizzas-in-nyc/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -501,\n          \"width\": 1080,\n          \"height\": 1620,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"e1ad4031-41f3-46c8-8dfd-ff7cc349f27f\",\n          \"scale\": 114,\n          \"focalX\": 54.37712224108658,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:44:07\",\n            \"baseColor\": \"#523c34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person standing and about to slice pizza\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.5 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f8bc63\\\">I ate 30 pizzas to find the best pizza in NYC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 58,\n          \"y\": -2,\n          \"width\": 292,\n          \"height\": 123,\n          \"id\": \"6384cc8c-0cac-4709-9dfb-661f571a3328\"\n        },\n        {\n          \"x\": 59,\n          \"y\": 144,\n          \"id\": \"3c6c91e1-8bb6-4934-830d-1d2e09ae22f0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f8bc63\\\">By: Chris Don</span>\\n<span style=\\\"color: #f8bc63\\\">Internet Celebrity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 292,\n          \"height\": 44\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"622df19a-39be-43de-9b02-e94449d0988d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"bbdc08c8-4ad8-4ed6-8040-f87a30b56f16\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"acb48bd0-f108-475f-bc8d-9ba658749b0f\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-19T10:50:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page2_bg.mp4\",\n            \"width\": 720,\n            \"height\": 1283,\n            \"baseColor\": \"#9a7453\",\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 18,\n            \"lengthFormatted\": \"0:18\",\n            \"alt\": \"Friends filming / doing a video chat on barbecue party at beach house\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.08 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -7,\n          \"y\": 433,\n          \"width\": 426,\n          \"height\": 198,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"id\": \"5abdcde8-f807-494e-9b67-05d2ce6fe69e\",\n          \"groupId\": \"9ec8f4c2-5acd-4485-87b1-8a83b9d10e30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">Chris Don</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 174,\n          \"height\": 41,\n          \"id\": \"f090cc50-af7f-4bb3-aae7-4a3635278181\",\n          \"x\": 119,\n          \"y\": 495,\n          \"groupId\": \"9ec8f4c2-5acd-4485-87b1-8a83b9d10e30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #262626\\\">Internet Celebrity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 155,\n          \"height\": 23,\n          \"id\": \"bb1dd937-9734-4d5e-8b60-68e45a56cc1f\",\n          \"x\": 130,\n          \"y\": 537,\n          \"groupId\": \"9ec8f4c2-5acd-4485-87b1-8a83b9d10e30\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"341259c4-cf2c-46fa-b608-31570784981a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bb1dd937-9734-4d5e-8b60-68e45a56cc1f\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"cd007a53-4d9d-4363-82ec-8f334f64ac6f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"8f9e6993-c98f-4fc7-90bc-212fa10036bd\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9ec8f4c2-5acd-4485-87b1-8a83b9d10e30\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ce6c1d76-6671-4d38-b311-8b4f195db5a7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f8bc63\\\">So what makes a really good pizza?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 277,\n          \"height\": 74,\n          \"id\": \"93ab7171-4cea-407c-b67e-d6a9f0807b1c\",\n          \"x\": 59,\n          \"y\": 174\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f8bc63\\\">It's a simple formula, really. A perfectly crispy crust, a good red or white base, and fresh toppings.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 100,\n          \"id\": \"3e78f1a7-1047-46ca-9841-16520b2a1922\",\n          \"x\": 59,\n          \"y\": 292\n        },\n        {\n          \"x\": 59,\n          \"y\": 417,\n          \"id\": \"172b812a-c744-4885-822a-b01e31cfca64\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f8bc63\\\">Don't forget about the ambience!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 50\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 28,\n          \"y\": 501,\n          \"width\": 195,\n          \"height\": 195,\n          \"sticker\": { \"type\": \"nycTomatoes\" },\n          \"id\": \"0fdbd60e-58c7-40e0-b2d6-e4411e43d075\",\n          \"groupId\": \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 150,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 8,\n          \"y\": -128,\n          \"width\": 190,\n          \"height\": 206,\n          \"sticker\": { \"type\": \"nycVeggies\" },\n          \"id\": \"6ad3b8d4-6173-4ac9-aafd-1ac50538501d\",\n          \"groupId\": \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 326,\n          \"y\": -33,\n          \"width\": 139,\n          \"height\": 108,\n          \"sticker\": { \"type\": \"nycOnion\" },\n          \"id\": \"a045a19f-414c-43de-b055-f88332181481\",\n          \"groupId\": \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 229,\n          \"y\": 53,\n          \"width\": 63,\n          \"height\": 68,\n          \"sticker\": { \"type\": \"nycChili\" },\n          \"id\": \"370ab2af-ecea-438b-be40-44406adeaa4e\",\n          \"groupId\": \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 325,\n          \"y\": 461,\n          \"width\": 106,\n          \"height\": 80,\n          \"sticker\": { \"type\": \"nycCheese\" },\n          \"id\": \"d5ae66ef-593c-4cee-a2f6-11530804990b\",\n          \"groupId\": \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"19bcb726-8666-4323-8c64-c684699d0a41\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"1573a2c0-1bf1-4d21-8a69-15a355dccfef\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -501,\n          \"width\": 1080,\n          \"height\": 1620,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"86afccec-f4b8-451f-b6bc-6bddeb877cb1\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 52.371162231670745,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:45:36\",\n            \"baseColor\": \"#cc9568\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page4_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Pizza on brown wooden table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -80,\n          \"y\": 385,\n          \"width\": 563,\n          \"height\": 445,\n          \"sticker\": { \"type\": \"nycTiltedBrush\" },\n          \"id\": \"302bdac3-fa06-494e-b7b5-a8406aef1c77\",\n          \"type\": \"sticker\",\n          \"groupId\": \"9e50a2ee-593f-4ea6-a122-a65449c5a64a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The crust</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 174,\n          \"height\": 41,\n          \"id\": \"ed117c88-8375-41e1-b767-cd64cd0cbaaa\",\n          \"x\": 119,\n          \"y\": 496,\n          \"type\": \"text\",\n          \"groupId\": \"9e50a2ee-593f-4ea6-a122-a65449c5a64a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #262626\\\">The last satisfying mouthful of slightly crunchy, doughy goodness.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 75,\n          \"id\": \"e6df3ee2-a880-4378-84b6-a3f32f7c9232\",\n          \"x\": 75,\n          \"y\": 537,\n          \"type\": \"text\",\n          \"groupId\": \"9e50a2ee-593f-4ea6-a122-a65449c5a64a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"453dd7f4-34df-4dee-8999-4fec9939797e\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"86afccec-f4b8-451f-b6bc-6bddeb877cb1\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"16d6b837-81e8-4c33-9441-7e0ecc7d3a37\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6e157aba-a731-4a10-9930-508c49cba4d3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9e50a2ee-593f-4ea6-a122-a65449c5a64a\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -506.5,\n          \"width\": 1080,\n          \"height\": 1631,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"96134eee-b383-4fde-869f-53c57ce6c307\",\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 49.91477272674006,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:47:00\",\n            \"baseColor\": \"#ccb0a8\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page5_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1631,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding dough\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -76,\n          \"y\": -83,\n          \"width\": 538,\n          \"height\": 269,\n          \"sticker\": { \"type\": \"nycMediumBrush\" },\n          \"id\": \"286d00f9-3c42-406f-910c-055a307d5b36\",\n          \"groupId\": \"1bbe0d93-915e-4b8a-80dd-e90112fabe6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The base</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 174,\n          \"height\": 41,\n          \"type\": \"text\",\n          \"id\": \"7f1c95fe-7584-450a-a89a-369d21de63e2\",\n          \"x\": 119,\n          \"y\": 1,\n          \"groupId\": \"1bbe0d93-915e-4b8a-80dd-e90112fabe6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #262626\\\">A homemade base is a must. A secret recipe? Even better!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 50,\n          \"type\": \"text\",\n          \"id\": \"15d5f0a0-6550-4191-b682-836656cbdb9e\",\n          \"x\": 76,\n          \"y\": 44,\n          \"groupId\": \"1bbe0d93-915e-4b8a-80dd-e90112fabe6c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dc8a2e9f-dcd2-4009-b1b2-6c248e0e8f79\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"96134eee-b383-4fde-869f-53c57ce6c307\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b047a2c1-00bb-4421-9e63-381b6dc23ad6\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"65f27998-4542-4af5-9793-80a0fab0b074\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"1bbe0d93-915e-4b8a-80dd-e90112fabe6c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 468,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"65f27998-4542-4af5-9793-80a0fab0b074\",\n          \"scale\": 107,\n          \"focalX\": 47.049072266635605,\n          \"focalY\": 47.78037383834696,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-05-18T01:23:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page6_bg.jpg\",\n            \"width\": 330,\n            \"height\": 468,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man adding  pizza topings\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3c383a\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 5,\n          \"lockAspectRatio\": true,\n          \"x\": -86,\n          \"y\": 155,\n          \"width\": 541,\n          \"height\": 270,\n          \"sticker\": { \"type\": \"nycMediumBrush\" },\n          \"id\": \"e993190f-f960-4251-88a7-4b4812dc8722\",\n          \"type\": \"sticker\",\n          \"groupId\": \"a366a44b-ab3d-4547-86cb-d98481e7530c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The toppings</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 218,\n          \"height\": 41,\n          \"id\": \"d75e3812-8de5-4549-8b62-c56c5e83b2d8\",\n          \"x\": 97,\n          \"y\": 224,\n          \"type\": \"text\",\n          \"groupId\": \"a366a44b-ab3d-4547-86cb-d98481e7530c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #262626\\\">They say keep it simple for a reason. A few fresh ingredients go a long way.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 75,\n          \"id\": \"c570dc78-a9d6-450a-9e75-62b5b515cea4\",\n          \"x\": 71,\n          \"y\": 267,\n          \"type\": \"text\",\n          \"groupId\": \"a366a44b-ab3d-4547-86cb-d98481e7530c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ecf1743d-3d67-4577-9756-00d0ef8bfa4f\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"65f27998-4542-4af5-9793-80a0fab0b074\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a00ae530-ca51-4c5c-b4b3-79d9f6f84106\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"a78d233c-2f13-417e-baf2-0869cf5abb90\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a366a44b-ab3d-4547-86cb-d98481e7530c\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 117,\n          \"focalX\": 48.420227464416925,\n          \"focalY\": 51.17984692621972,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:48:19\",\n            \"baseColor\": \"#3e281a\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Pizzeria with Black fabric stool\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -501,\n          \"width\": 1080,\n          \"height\": 1620,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cdf2d077-deb0-416d-b8bf-c84cf2ce715f\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"x\": -16,\n          \"y\": 427,\n          \"width\": 499,\n          \"height\": 249,\n          \"sticker\": { \"type\": \"nycMediumBrush\" },\n          \"id\": \"54476660-3aa7-4472-af49-63b9ccafa96c\",\n          \"type\": \"sticker\",\n          \"groupId\": \"7866007b-b710-4c7f-92c3-6fcea78a3193\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The environment</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 41,\n          \"id\": \"b98989c6-593e-4c61-8777-ffa12fece779\",\n          \"x\": 76,\n          \"y\": 494,\n          \"type\": \"text\",\n          \"groupId\": \"7866007b-b710-4c7f-92c3-6fcea78a3193\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #262626\\\">The restaurant's vibe should match your soaring spirits.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 50,\n          \"id\": \"3f654768-f856-4e3d-981e-c8f88f19bb2c\",\n          \"x\": 71,\n          \"y\": 537,\n          \"type\": \"text\",\n          \"groupId\": \"7866007b-b710-4c7f-92c3-6fcea78a3193\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"76128b71-f2a3-4379-9963-d5b79a32ea81\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"cdf2d077-deb0-416d-b8bf-c84cf2ce715f\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8aaa0e15-4e11-4965-92f1-72727089dbcd\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"a78d233c-2f13-417e-baf2-0869cf5abb90\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"7866007b-b710-4c7f-92c3-6fcea78a3193\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -411,\n          \"width\": 1080,\n          \"height\": 1440,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"69fc7d58-253e-4765-a1bc-3d47dabdccdd\",\n          \"scale\": 108,\n          \"focalX\": 39.737274220032845,\n          \"focalY\": 50.96213054187193,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:48:58\",\n            \"baseColor\": \"#b5c7cc\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page8_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1440,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Group of people inside the restaurant\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.4 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -6,\n          \"y\": 58,\n          \"width\": 426,\n          \"height\": 198,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"id\": \"c3d5dbfa-8686-4444-981c-35de73796b92\",\n          \"groupId\": \"3cf7b9b0-4373-4675-bfdd-90c9774d7e7d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The best pizza\\ncrust winner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 73,\n          \"type\": \"text\",\n          \"id\": \"7e8aef49-21f8-422b-8158-5b6762d52aed\",\n          \"x\": 76,\n          \"y\": 96,\n          \"groupId\": \"3cf7b9b0-4373-4675-bfdd-90c9774d7e7d\"\n        },\n        {\n          \"x\": 76,\n          \"y\": 187,\n          \"id\": \"407bf12a-cb90-40d9-8682-1f631cd7e592\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">Joe’s Pizza</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 28,\n          \"type\": \"text\",\n          \"groupId\": \"3cf7b9b0-4373-4675-bfdd-90c9774d7e7d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 20,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"nycArrowRight\" },\n          \"type\": \"sticker\",\n          \"id\": \"755bf31d-5ecd-47f0-abce-95938e285635\",\n          \"x\": 132,\n          \"y\": 586,\n          \"groupId\": \"c27a215d-d7b5-4d87-9d46-c5f877506125\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": false, \"horizontal\": 22, \"vertical\": 8 },\n          \"content\": \"<span style=\\\"color: #fff\\\">Get Directions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"x\": 116,\n          \"y\": 579,\n          \"groupId\": \"c27a215d-d7b5-4d87-9d46-c5f877506125\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"d53839a4-51b4-4e0c-9aae-19f7b9b8f061\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b5f32c5b-85bc-43e7-aa87-daeac1c80ddc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"755bf31d-5ecd-47f0-abce-95938e285635\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"d53839a4-51b4-4e0c-9aae-19f7b9b8f061\"],\n          \"id\": \"93876a65-3343-491d-99d9-9681711c55f1\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"15071bca-99eb-4d5d-b978-5942860fdf69\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"47621367-6c30-4f3d-89e5-240c6e0cd13b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"3cf7b9b0-4373-4675-bfdd-90c9774d7e7d\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c27a215d-d7b5-4d87-9d46-c5f877506125\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e36f6d0d-fcdf-41fd-8fe5-ffac1e173589\": {\n          \"name\": \"Action Copy\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 142,\n          \"focalX\": 40.498546836575,\n          \"focalY\": 48.270875251509054,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:49:33\",\n            \"baseColor\": \"#1e1a15\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page9_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Group of people inside cafeteria\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -651,\n          \"width\": 1080,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"740d0f75-3140-49bf-958f-69583015dbd3\",\n          \"type\": \"image\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.53 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -14,\n          \"y\": 23,\n          \"width\": 426,\n          \"height\": 198,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"id\": \"619a4653-c867-4bfa-9dcc-12d71f2f21f3\",\n          \"type\": \"sticker\",\n          \"groupId\": \"7d123ae5-fef6-4186-9098-af0434204212\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The best red sauce</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 73,\n          \"id\": \"b4d74646-c7aa-46a4-ae0d-931372c5a306\",\n          \"x\": 76,\n          \"y\": 61,\n          \"type\": \"text\",\n          \"groupId\": \"7d123ae5-fef6-4186-9098-af0434204212\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 76,\n          \"y\": 151,\n          \"id\": \"f6854320-08b8-4ce7-a6fe-7cb48b0598ce\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">Artichoke’s Pizza</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"7d123ae5-fef6-4186-9098-af0434204212\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 20,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"nycArrowRight\" },\n          \"type\": \"sticker\",\n          \"id\": \"4e4e3e92-d4bf-408e-a1a2-9bad3f41d189\",\n          \"x\": 132,\n          \"y\": 586,\n          \"groupId\": \"a900af27-4a6e-479f-ae08-d71ce869dc6d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": false, \"horizontal\": 22, \"vertical\": 8 },\n          \"content\": \"<span style=\\\"color: #fff\\\">Get Directions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"x\": 116,\n          \"y\": 579,\n          \"groupId\": \"a900af27-4a6e-479f-ae08-d71ce869dc6d\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"57149a11-36a9-4612-9bfb-e1d6fca70aa2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"24a71109-3b25-49c4-816a-719d4bf8c269\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4e4e3e92-d4bf-408e-a1a2-9bad3f41d189\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"57149a11-36a9-4612-9bfb-e1d6fca70aa2\"],\n          \"id\": \"789fe504-62cc-4735-8fcc-1c18d493045a\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"82bb3486-640b-46c9-8a84-1ce438a53c3c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"47621367-6c30-4f3d-89e5-240c6e0cd13b\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a900af27-4a6e-479f-ae08-d71ce869dc6d\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7d123ae5-fef6-4186-9098-af0434204212\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -501,\n          \"width\": 1080,\n          \"height\": 1620,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"47621367-6c30-4f3d-89e5-240c6e0cd13b\",\n          \"scale\": 135,\n          \"focalX\": 55.45634920634921,\n          \"focalY\": 45.370370370370374,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:50:42\",\n            \"baseColor\": \"#cc8d52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Standing Outside Trattoria Pizzeria Store\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.43 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -14,\n          \"y\": 181,\n          \"width\": 426,\n          \"height\": 198,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"id\": \"c81a5ffa-27e8-4b4b-9a0d-e33747310f1e\",\n          \"type\": \"sticker\",\n          \"groupId\": \"ca4c057e-321c-44e8-ab3b-af0ad98da8e5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The best topping winner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 73,\n          \"id\": \"dc318dfc-6f02-4890-8f93-f6f031debff9\",\n          \"x\": 76,\n          \"y\": 219,\n          \"type\": \"text\",\n          \"groupId\": \"ca4c057e-321c-44e8-ab3b-af0ad98da8e5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 76,\n          \"y\": 309,\n          \"id\": \"7ca69d71-2970-461d-97c9-82ace04043d8\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">Trattoria</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"ca4c057e-321c-44e8-ab3b-af0ad98da8e5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 20,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"nycArrowRight\" },\n          \"type\": \"sticker\",\n          \"id\": \"7155f312-5345-4c81-877d-b155d8962c97\",\n          \"x\": 132,\n          \"y\": 586,\n          \"groupId\": \"ea319746-4536-4240-96ac-febdf13e5e49\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": false, \"horizontal\": 22, \"vertical\": 8 },\n          \"content\": \"<span style=\\\"color: #fff\\\">Get Directions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"x\": 116,\n          \"y\": 579,\n          \"groupId\": \"ea319746-4536-4240-96ac-febdf13e5e49\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"d3e34964-ce81-4418-9308-aae32194d4b1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e970ea99-896d-4036-8c7e-c913df657260\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7155f312-5345-4c81-877d-b155d8962c97\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"d3e34964-ce81-4418-9308-aae32194d4b1\"],\n          \"id\": \"fc9325dd-767d-42ef-8d97-3f787837d905\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"93126d0c-c037-494a-bcd2-b80f9a823d1f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"2f156d35-c735-464e-9ac6-df4ae6654b71\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"ca4c057e-321c-44e8-ab3b-af0ad98da8e5\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ea319746-4536-4240-96ac-febdf13e5e49\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -501,\n          \"width\": 1080,\n          \"height\": 1620,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"47621367-6c30-4f3d-89e5-240c6e0cd13b\",\n          \"scale\": 110,\n          \"focalX\": 46.95616883116883,\n          \"focalY\": 51.42045454545454,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:52:15\",\n            \"baseColor\": \"#bea787\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man near pizza\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.47 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -14,\n          \"y\": 228,\n          \"width\": 426,\n          \"height\": 198,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"id\": \"36be4aec-f421-44fe-a4f9-3e8a711f205e\",\n          \"type\": \"sticker\",\n          \"groupId\": \"47d0a7c3-f739-4979-ba88-47ec1ed53446\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">The best place to\\neat pizza winner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 73,\n          \"id\": \"3c3ee984-c4ac-45ea-99c3-6b1da119fc4c\",\n          \"x\": 76,\n          \"y\": 270,\n          \"type\": \"text\",\n          \"groupId\": \"47d0a7c3-f739-4979-ba88-47ec1ed53446\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 76,\n          \"y\": 360,\n          \"id\": \"7d799651-a5d5-4520-819d-0ab32348bac4\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262626\\\">Di Fara Pizza</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 260,\n          \"height\": 30,\n          \"type\": \"text\",\n          \"groupId\": \"47d0a7c3-f739-4979-ba88-47ec1ed53446\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 20,\n          \"height\": 20,\n          \"sticker\": { \"type\": \"nycArrowRight\" },\n          \"type\": \"sticker\",\n          \"id\": \"d979e4d6-52e0-4f77-90f3-2e5a55b45eae\",\n          \"x\": 132,\n          \"y\": 586,\n          \"groupId\": \"b4fa7401-2904-444e-8f7b-d8d54e6af73f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.28,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": false, \"horizontal\": 22, \"vertical\": 8 },\n          \"content\": \"<span style=\\\"color: #fff\\\">Get Directions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 38,\n          \"type\": \"text\",\n          \"x\": 116,\n          \"y\": 579,\n          \"groupId\": \"b4fa7401-2904-444e-8f7b-d8d54e6af73f\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"id\": \"fa1cad59-5395-4264-97a6-7878c98abfde\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a05185a3-462c-452e-953a-dc93ee5731bc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d979e4d6-52e0-4f77-90f3-2e5a55b45eae\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"fa1cad59-5395-4264-97a6-7878c98abfde\"],\n          \"id\": \"59b549e4-6b40-4f19-bb4e-287c5f0ab5a7\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"adb9041d-188d-4bd7-a457-e93544be0b4e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"8cf01df7-0149-492b-b86e-edf53955f7bb\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"47d0a7c3-f739-4979-ba88-47ec1ed53446\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b4fa7401-2904-444e-8f7b-d8d54e6af73f\": {\n          \"name\": \"Action\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0bc85caf-a774-4d5e-b69a-e40ba1cce02a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 177,\n          \"y\": 543,\n          \"width\": 175,\n          \"height\": 175,\n          \"sticker\": { \"type\": \"nycTomatoes\" },\n          \"id\": \"7e1fbdf4-e3fa-48e1-aa99-425ba6c602c5\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c2eca49f-eaaf-43a1-b699-eab439e06f7c\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 335,\n          \"y\": 119,\n          \"width\": 104,\n          \"height\": 113,\n          \"sticker\": { \"type\": \"nycVeggies\" },\n          \"id\": \"c1396685-2622-4ff3-ab15-b5c16b7c2a7f\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c2eca49f-eaaf-43a1-b699-eab439e06f7c\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 105,\n          \"lockAspectRatio\": true,\n          \"x\": 32,\n          \"y\": -79,\n          \"width\": 151,\n          \"height\": 164,\n          \"sticker\": { \"type\": \"nycChili\" },\n          \"id\": \"8ac3218e-27dc-4eef-a005-fcb81f585b21\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c2eca49f-eaaf-43a1-b699-eab439e06f7c\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -49,\n          \"y\": 504,\n          \"width\": 82,\n          \"height\": 62,\n          \"sticker\": { \"type\": \"nycCheese\" },\n          \"id\": \"c0762083-ebdc-44d2-81f8-90c908063332\",\n          \"type\": \"sticker\",\n          \"groupId\": \"c2eca49f-eaaf-43a1-b699-eab439e06f7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 55,\n          \"y\": 179,\n          \"width\": 298,\n          \"height\": 298,\n          \"scale\": 129,\n          \"focalX\": 62.76459430110698,\n          \"focalY\": 60.80117477280089,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"1749e90c-3a88-48ef-b753-ed2c785eed61\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T12:53:08\",\n            \"baseColor\": \"#312d2d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pizzas-in-nyc/page12_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Group of people sitting inside a cafeteria\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f8bc63\\\">More stories like this</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 240,\n          \"height\": 74,\n          \"type\": \"text\",\n          \"id\": \"e31ab540-e2cc-4779-ab41-67afc7210336\",\n          \"x\": 86,\n          \"y\": 67\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": true,\n          \"width\": 289,\n          \"height\": 134,\n          \"sticker\": { \"type\": \"nycThickBrush\" },\n          \"type\": \"sticker\",\n          \"id\": \"e9847403-aa9f-4cdb-b1dd-bea51f9d76c6\",\n          \"x\": 61.5,\n          \"y\": 387,\n          \"groupId\": \"0e53105d-437f-4522-b3c3-2554fecd0bac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Noto Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1098,\n              \"capH\": 1462,\n              \"yMin\": -806,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #202325\\\">7 Best Restaurants in Brooklyn</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 154,\n          \"height\": 78,\n          \"type\": \"text\",\n          \"id\": \"5fae2cab-6229-424d-801f-7a019fc65f87\",\n          \"x\": 129,\n          \"y\": 415,\n          \"groupId\": \"0e53105d-437f-4522-b3c3-2554fecd0bac\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0dd9b324-c010-4808-aaa0-e5392804dae1\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"7e1fbdf4-e3fa-48e1-aa99-425ba6c602c5\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"382947db-b7a2-445e-8b8b-6c2d881297d8\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"c1396685-2622-4ff3-ab15-b5c16b7c2a7f\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f9535eb8-d1f4-48f3-9e29-86fec7d44c5e\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"8ac3218e-27dc-4eef-a005-fcb81f585b21\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"098b165f-5b98-4fa8-8c56-1478b0120d19\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"c0762083-ebdc-44d2-81f8-90c908063332\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"8cb30a3a-7dc1-4705-8a77-63edee73555c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c2eca49f-eaaf-43a1-b699-eab439e06f7c\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"0e53105d-437f-4522-b3c3-2554fecd0bac\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/plant-based-dyes/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\n// For some reason, the inferred TypeScript type is too narrow here and we have to use\n// file declaration instead of importing directly from `template.json`.\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/plant-based-dyes/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'plant-based-dyes',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Plant Based Dyes DIY', 'template name', 'web-stories'),\n  tags: [\n    _x('Crafts', 'template keyword', 'web-stories'),\n    _x('Plant', 'template keyword', 'web-stories'),\n    _x('DIY', 'template keyword', 'web-stories'),\n    _x('Calm', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Sweet Corn Yellow', 'color', 'web-stories'),\n      color: '#f9e46c',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Rainforest Green', 'color', 'web-stories'),\n      color: '#4a6747',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Herbal Green', 'color', 'web-stories'),\n      color: '#a7aa2d',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Leaf Green', 'color', 'web-stories'),\n      color: '#414c40',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Almond Milk', 'color', 'web-stories'),\n      color: '#f3e9d4',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its gentle shapes, modest font and soothing pastel tones, this template will let you create nature-inspired DIY guides that feel relaxed and serene.',\n    'web-stories'\n  ),\n  vertical: _x('Arts & Crafts', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/plant-based-dyes/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/plant-based-dyes/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6c7f42f5-9dfa-4dfe-b0cb-1add55305962\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #393d28\\\">How to make your own plant based dyes: DIY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 6,\n          \"width\": 283,\n          \"height\": 126,\n          \"id\": \"dc8465af-6580-418b-bc0b-70a061683a74\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 166,\n          \"id\": \"8762d1df-b171-4594-b8e4-6ec9eaca6955\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #393d28; letter-spacing: 0.12em; text-transform: uppercase\\\">SASHA DUERR</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 283,\n          \"height\": 18\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:15:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page01_image01.png\",\n            \"width\": 475,\n            \"height\": 374,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sliced avocado on brown wooden chopping board\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#252019\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -47,\n          \"y\": 218,\n          \"width\": 448,\n          \"height\": 353,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"15303abe-739f-410a-b286-8fd3055d8364\",\n          \"groupId\": \"834fb54d-5190-4b25-8f50-999700a71f2c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 210,\n          \"y\": 211,\n          \"width\": 148,\n          \"height\": 95,\n          \"sticker\": { \"type\": \"makerYellowDots\" },\n          \"id\": \"6a0e3a93-ec70-487b-85f5-f5f2d7a7d03f\",\n          \"groupId\": \"834fb54d-5190-4b25-8f50-999700a71f2c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 205,\n          \"y\": 482,\n          \"width\": 137,\n          \"height\": 137,\n          \"sticker\": { \"type\": \"makerGreenLeafShape\" },\n          \"id\": \"7351c173-5bcb-40c3-b733-762701f3b1be\",\n          \"groupId\": \"834fb54d-5190-4b25-8f50-999700a71f2c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 121,\n          \"y\": 483,\n          \"width\": 137,\n          \"height\": 147,\n          \"sticker\": { \"type\": \"makerYellowLeaf\" },\n          \"id\": \"4a207c5a-6b29-449f-89a4-872b1e90b6ed\",\n          \"groupId\": \"834fb54d-5190-4b25-8f50-999700a71f2c\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 233, \"b\": 212 } },\n      \"type\": \"page\",\n      \"id\": \"c4b1095e-77fa-4627-8459-e61d9168d6d8\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"834fb54d-5190-4b25-8f50-999700a71f2c\": {\n          \"name\": \"Image\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -2,\n          \"y\": -61,\n          \"width\": 416,\n          \"height\": 740,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"9c60f078-1830-4c35-af6d-e4a8bd180295\",\n          \"scale\": 116,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:15:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page02_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman holding leafed plant\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9a765a\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4d0487b3-8879-444c-9043-633fe2e13394\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 60,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #f9e46c\\\">Sasha Duerr</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 129,\n          \"id\": \"88c4ea44-30c9-4413-8a66-473756a894d1\",\n          \"x\": 48,\n          \"y\": 395,\n          \"marginOffset\": -3.6850000000000023\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f6f6f6\\\">Professor of Plant Dyes and author of “Living Color”, Duerr takes us through the beauty of using plant-based dyes to create vibrant color at home.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 51,\n          \"y\": 519,\n          \"width\": 310,\n          \"height\": 92,\n          \"id\": \"bf4f7a21-b8ba-4f95-ab01-1ada0467bdd3\",\n          \"marginOffset\": 0.7593749999999986\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 137.5,\n          \"y\": -22,\n          \"width\": 137,\n          \"height\": 95,\n          \"sticker\": { \"type\": \"makerBannerWithDots\" },\n          \"id\": \"a73c7d51-ed09-48f4-bef6-fc8d8350ff8a\",\n          \"groupId\": \"d6431164-4f9c-45d6-a8ac-301c9233f836\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.12em; text-transform: uppercase\\\">YOUR GUIDE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 111,\n          \"height\": 18,\n          \"id\": \"ec24d629-03f7-4951-8f45-e684110c5019\",\n          \"x\": 150,\n          \"y\": 9,\n          \"marginOffset\": -3.3149999999999977,\n          \"groupId\": \"d6431164-4f9c-45d6-a8ac-301c9233f836\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2538fa11-7102-4d3a-b9a5-c10b8755cc4d\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"9c60f078-1830-4c35-af6d-e4a8bd180295\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"812ab657-5b0c-4684-ade9-2de408dd021d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bf4f7a21-b8ba-4f95-ab01-1ada0467bdd3\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"365e2dfe-b28f-4417-b808-a14ce1153cad\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"a73c7d51-ed09-48f4-bef6-fc8d8350ff8a\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f75b650a-53d7-40a1-8c2b-36f6211e8d20\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"69358c68-0fd3-46b6-a4c4-34f2b4d1bb07\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"d6431164-4f9c-45d6-a8ac-301c9233f836\": {\n          \"name\": \"Text\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"64f456bd-299a-4010-bd20-15c2f2461a0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f9e46c\\\">Plant based dyes are&nbsp;</span>\\n<span style=\\\"color: #f9e46c\\\">eco-friendly, organic and gentle enough for everyday wear.</span>\\n\\n<span style=\\\"color: #f9e46c\\\">The best part? It's all cost effective and sustainable at its best.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 288,\n          \"height\": 207,\n          \"marginOffset\": -1.3749999999999964,\n          \"id\": \"52330206-e62d-4b73-ab4b-45007c92d184\",\n          \"x\": 48,\n          \"y\": 344,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 10,\n          \"id\": \"1398d39a-7410-4cf4-8539-26dfdb37deeb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9e46c\\\">Do you know...</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 29,\n          \"marginOffset\": 0.7593749999999986,\n          \"groupId\": \"97ee6113-8c21-4119-8320-fe78b06b3083\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 43,\n          \"width\": 153,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"makerWavyLine\" },\n          \"id\": \"2d556a12-9e1d-4ed7-afe7-8063ab7fd20f\",\n          \"groupId\": \"97ee6113-8c21-4119-8320-fe78b06b3083\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 195,\n          \"y\": 120,\n          \"width\": 163,\n          \"height\": 264,\n          \"sticker\": { \"type\": \"makerPlant\" },\n          \"id\": \"4deeb064-9324-4dc2-aafe-b8880356dff1\",\n          \"groupId\": \"3d3cf946-8e76-4eca-862b-edb8719354f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 298,\n          \"y\": -87,\n          \"width\": 137,\n          \"height\": 147,\n          \"sticker\": { \"type\": \"makerYellowLeaf\" },\n          \"id\": \"d7846485-e100-4eea-a348-bc8e1fcd6c7d\",\n          \"groupId\": \"3d3cf946-8e76-4eca-862b-edb8719354f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -41,\n          \"y\": 104,\n          \"width\": 137,\n          \"height\": 128,\n          \"sticker\": { \"type\": \"makerGreenLeaf\" },\n          \"id\": \"23ff3ef0-1167-447f-8f83-af423a6d7962\",\n          \"groupId\": \"3d3cf946-8e76-4eca-862b-edb8719354f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 165,\n          \"y\": 573,\n          \"width\": 145,\n          \"height\": 53,\n          \"sticker\": { \"type\": \"makerSquigglyLine\" },\n          \"id\": \"658a22ff-79bb-4aac-9e46-7ece108fd899\",\n          \"groupId\": \"3d3cf946-8e76-4eca-862b-edb8719354f3\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 65, \"g\": 76, \"b\": 64 } },\n      \"type\": \"page\",\n      \"id\": \"bb652455-d882-47c5-acf8-b0c438511638\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"97ee6113-8c21-4119-8320-fe78b06b3083\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3d3cf946-8e76-4eca-862b-edb8719354f3\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -4,\n          \"y\": -63.5,\n          \"width\": 420,\n          \"height\": 745,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"3bb2919b-92f1-473c-84ef-654409f90146\",\n          \"scale\": 112,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:15:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page04_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"sliced avocado on plate\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b1afa7\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2c3babd9-8de5-4bc5-b301-2f0c8da39eef\",\n          \"x\": 0,\n          \"y\": -58,\n          \"groupId\": \"fa51342f-94c8-4e59-aa23-cca44e346091\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -3,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 55,\n          \"y\": 615,\n          \"width\": 531,\n          \"height\": 254,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"9675c36c-59f6-4ba4-992c-d3d7ce9b620f\",\n          \"groupId\": \"fa51342f-94c8-4e59-aa23-cca44e346091\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 188,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 478,\n          \"height\": 508,\n          \"sticker\": { \"type\": \"makerYellowLeaf\" },\n          \"id\": \"d50c5007-7110-4385-b348-07142bcee0b4\",\n          \"x\": -242,\n          \"y\": 538,\n          \"groupId\": \"fa51342f-94c8-4e59-aa23-cca44e346091\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #ffee96; letter-spacing: 0.12em; text-transform: uppercase\\\">TUTORIAL</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 18,\n          \"marginOffset\": -3.0599999999999987,\n          \"id\": \"759570a9-218e-42e4-b15b-83c3c4fdc81e\",\n          \"x\": 48,\n          \"y\": 9\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #f9e46c\\\">Avocado Pit</span>\\n<span style=\\\"font-weight: 600; color: #f9e46c\\\">Dye 101</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 75,\n          \"marginOffset\": -1.6499999999999986,\n          \"id\": \"99e7abb1-1a88-419b-bc0a-9a1fbadbff8b\",\n          \"x\": 56,\n          \"y\": 30\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"074bbac5-8fa2-41e3-82b4-f3c8c9a9945b\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"3bb2919b-92f1-473c-84ef-654409f90146\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"81040084-7ea2-4ea6-af5d-56ce803eac0b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c54400dc-188d-4394-b9e2-db18b7f3c817\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"fa51342f-94c8-4e59-aa23-cca44e346091\": {\n          \"name\": \"Background\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"658dbbaf-8062-447b-8c4f-92a8586bf510\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:16:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page05_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person in Brown Long Sleeve Shirt Holding White Paper\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b8b5ad\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -14.5,\n          \"y\": -81,\n          \"width\": 441,\n          \"height\": 661,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"05419731-14da-4c35-aee7-9a3c57a758d5\",\n          \"groupId\": \"b5675fb1-06e6-45ab-ac93-c063b2d466e2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 675,\n          \"height\": 323,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"9e230c41-803a-4699-b749-1b0e132792cb\",\n          \"x\": -158,\n          \"y\": 420,\n          \"groupId\": \"b5675fb1-06e6-45ab-ac93-c063b2d466e2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">Prepare your</span>\\n<span style=\\\"font-weight: 600; color: #414c40\\\">fabric</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 479,\n          \"width\": 300,\n          \"height\": 60,\n          \"id\": \"69b45dd0-1b8a-4a0d-a83e-1d65fdd8738e\",\n          \"marginOffset\": 0.5625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #414c40\\\">I wash the fabric with Synthrapol detergent, which is perfect to prep fabric for dyeing.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 62,\n          \"marginOffset\": 2.465,\n          \"id\": \"d798cb9b-9728-4c0e-9273-a1d4e7dcadd9\",\n          \"x\": 71,\n          \"y\": 549\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 134,\n          \"y\": 366,\n          \"width\": 142,\n          \"height\": 97,\n          \"sticker\": { \"type\": \"makerRoundedBannerWithDots\" },\n          \"id\": \"bd6b5ffa-95ac-4494-af6f-30381d7d1a33\",\n          \"groupId\": \"95d9b47d-79e1-4edf-b1ff-d759faa74bdf\"\n        },\n        {\n          \"x\": 185,\n          \"y\": 387,\n          \"id\": \"8fd756d0-f349-4c93-9311-df6c2ec5bc35\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 50,\n          \"marginOffset\": -1.0999999999999979,\n          \"groupId\": \"95d9b47d-79e1-4edf-b1ff-d759faa74bdf\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"76239a74-0194-4b6d-927f-51852a093f1f\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"95d9b47d-79e1-4edf-b1ff-d759faa74bdf\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"b5675fb1-06e6-45ab-ac93-c063b2d466e2\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"82011504-bef3-47e3-b30b-de34f2a33870\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:16:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page06_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Top view of halved tasty avocado with seed placed on white marble table\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d9d3c8\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -7,\n          \"y\": -89,\n          \"width\": 418,\n          \"height\": 639,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"bb91d2c2-7b47-4912-8b7e-6e1c27169948\",\n          \"groupId\": \"2df8766d-86fa-49f0-93a1-6368bc46b88f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 675,\n          \"height\": 323,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"0bd8ec6d-2d22-4004-a8cc-445508a9b9d8\",\n          \"x\": -158,\n          \"y\": 420,\n          \"groupId\": \"2df8766d-86fa-49f0-93a1-6368bc46b88f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 142,\n          \"height\": 97,\n          \"sticker\": { \"type\": \"makerRoundedBannerWithDots\" },\n          \"id\": \"964aaa5b-80c9-4e28-80e0-84b6df4d464d\",\n          \"x\": 134,\n          \"y\": 366,\n          \"groupId\": \"c3dba45e-b94e-423a-8a5d-0235adfa2fc1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 49,\n          \"marginOffset\": -1.0999999999999979,\n          \"id\": \"dd8e4a7f-b0bf-4cf0-bb04-e64a84d7aa1d\",\n          \"x\": 184,\n          \"y\": 387,\n          \"groupId\": \"c3dba45e-b94e-423a-8a5d-0235adfa2fc1\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">Prepare the</span>\\n<span style=\\\"font-weight: 600; color: #414c40\\\">avocado pits</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 479,\n          \"width\": 300,\n          \"height\": 60,\n          \"id\": \"a59c4534-311e-4a86-8bfb-e233afffd57f\",\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #414c40\\\">Wash avocado pits completely to\\nremove any flesh. You would need 3-4 avocado pits per 1/2 lb of fabric.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 62,\n          \"marginOffset\": 2.465,\n          \"id\": \"1e1becb6-3295-4257-aaee-acdff63bf932\",\n          \"x\": 71,\n          \"y\": 549,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"de677507-4bac-4efb-8660-8b31b99704bf\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"c3dba45e-b94e-423a-8a5d-0235adfa2fc1\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"2df8766d-86fa-49f0-93a1-6368bc46b88f\": {\n          \"name\": \"Background\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"72764d27-f827-4320-ad83-8dc807c4c9bc\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:16:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page07_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in White and Red Floral Shirt Holding Stainless Steel Bowl and Whisk\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b19476\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -2,\n          \"y\": -61,\n          \"width\": 428,\n          \"height\": 640,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ab57a96e-ef0f-47bf-82fc-4156b0a1e7e6\",\n          \"groupId\": \"871704f9-a71c-4e14-8d2a-b49215565531\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 675,\n          \"height\": 323,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"e82da8ca-7629-4f9f-8a5d-c0c261820e88\",\n          \"x\": -158,\n          \"y\": 420,\n          \"groupId\": \"871704f9-a71c-4e14-8d2a-b49215565531\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 142,\n          \"height\": 97,\n          \"sticker\": { \"type\": \"makerRoundedBannerWithDots\" },\n          \"id\": \"fbdc390e-f95d-4906-a8d5-326db351cf94\",\n          \"x\": 134,\n          \"y\": 366,\n          \"groupId\": \"ea426cc4-055b-4237-8d29-b3ea317c008c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 49,\n          \"marginOffset\": -1.0999999999999979,\n          \"id\": \"e4955a10-955f-413b-9aa5-aa23744a222b\",\n          \"x\": 184,\n          \"y\": 387,\n          \"groupId\": \"ea426cc4-055b-4237-8d29-b3ea317c008c\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">Mix everything</span>\\n<span style=\\\"font-weight: 600; color: #414c40\\\">together</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 479,\n          \"width\": 300,\n          \"height\": 60,\n          \"id\": \"f0896114-0a43-4193-ae6d-ac836b2fe488\",\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #414c40\\\">Put your whole pits into the bottom of the pot. Add enough water to cover the fabric that will be dyed.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 62,\n          \"marginOffset\": 2.465,\n          \"id\": \"0e41564f-9a14-46c1-a918-b437aa2ced6e\",\n          \"x\": 71,\n          \"y\": 549,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"1087c9d2-1002-4391-b9f9-7e1d19945cc7\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"ea426cc4-055b-4237-8d29-b3ea317c008c\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"871704f9-a71c-4e14-8d2a-b49215565531\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"02ae1519-d11e-4438-8d09-e5f6f8c44333\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:16:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page08_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"vegetable grind in mortar and pestle\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#57605c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -0.5,\n          \"y\": -57,\n          \"width\": 413,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c4e65e0b-fee5-447a-b23d-8de517917da4\",\n          \"groupId\": \"09af9f79-ae4d-42ba-b17a-82c9e3f9bbad\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 65, \"g\": 76, \"b\": 64, \"a\": 0.3 }\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"660d1512-b88f-4a69-b655-aa9d286d466d\",\n          \"x\": 0,\n          \"y\": -57,\n          \"groupId\": \"09af9f79-ae4d-42ba-b17a-82c9e3f9bbad\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 140,\n          \"y\": -22,\n          \"width\": 137,\n          \"height\": 95,\n          \"sticker\": { \"type\": \"makerBannerWithDots\" },\n          \"id\": \"ccec74a0-8a26-401c-aff6-233181923dca\",\n          \"groupId\": \"9608a8ed-6130-46cd-ac05-5ef48e4e5b7f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.12em; text-transform: uppercase\\\">ADVICE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 111,\n          \"height\": 18,\n          \"id\": \"de075d18-e33b-418c-91f2-ce961854c1c9\",\n          \"x\": 151,\n          \"y\": 9,\n          \"marginOffset\": -3.3149999999999977,\n          \"type\": \"text\",\n          \"groupId\": \"9608a8ed-6130-46cd-ac05-5ef48e4e5b7f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9e46c\\\">“ Slow food has taught us that sustainability is as equally rooted in social connection and care as it is in environmental stewardship. “</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 269,\n          \"marginOffset\": -4.649999999999999,\n          \"id\": \"c5a6502a-bc4f-4e31-a71d-8a1ef7d026e0\",\n          \"x\": 48,\n          \"y\": 298,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 147,\n          \"y\": 598,\n          \"id\": \"2db9aaee-d52c-4bab-9c67-c8505a66de35\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.12em; text-transform: uppercase\\\">SASHA DUERR</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 122,\n          \"height\": 18,\n          \"marginOffset\": -3.3149999999999977,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"558253e0-1adb-4cdf-81ab-53c566662cab\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2db9aaee-d52c-4bab-9c67-c8505a66de35\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"9658e894-4fc6-4e4d-8108-1d04787b8f1e\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"ccec74a0-8a26-401c-aff6-233181923dca\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"03b0fe6f-9c80-48ec-bc11-a0f3ad8a31fc\",\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"9608a8ed-6130-46cd-ac05-5ef48e4e5b7f\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"09af9f79-ae4d-42ba-b17a-82c9e3f9bbad\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fcaf5ec6-5f2a-49c3-9300-332e806fbe1c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:16:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page09_image01.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Stainless Steel Cookware on Stove\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfb19e\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 412,\n          \"height\": 539,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2e60ace3-2414-45c5-809a-ba52c70a291f\",\n          \"groupId\": \"929c751c-97a6-4449-a061-c0a7956eaf0c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 675,\n          \"height\": 323,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"327d176c-c140-44a2-bdfa-5367d3b42891\",\n          \"x\": -158,\n          \"y\": 420,\n          \"groupId\": \"929c751c-97a6-4449-a061-c0a7956eaf0c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 142,\n          \"height\": 97,\n          \"sticker\": { \"type\": \"makerRoundedBannerWithDots\" },\n          \"id\": \"0d3189c5-49d8-4a6f-a6b2-61449592ce03\",\n          \"x\": 134,\n          \"y\": 366,\n          \"groupId\": \"ee4e5597-17d4-4466-9a24-cf8054c893e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 49,\n          \"marginOffset\": -1.0999999999999979,\n          \"id\": \"1a0f7cf5-e99a-41fa-bcf9-012ac5d1679a\",\n          \"x\": 184,\n          \"y\": 387,\n          \"groupId\": \"ee4e5597-17d4-4466-9a24-cf8054c893e0\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">Give it</span>\\n<span style=\\\"font-weight: 600; color: #414c40\\\">time</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 479,\n          \"width\": 300,\n          \"height\": 60,\n          \"id\": \"7e94eea5-a8ec-4c35-a24c-24ec839aa3ca\",\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #414c40\\\">Remember not to boil the pigment for too long, it's the time not the heat that produces the richest hues.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 270,\n          \"height\": 62,\n          \"marginOffset\": 2.465,\n          \"id\": \"c915fc8d-e450-44da-b67f-4d9069ae7ce0\",\n          \"x\": 71,\n          \"y\": 549,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"cdf79071-15a4-4e55-ae21-c7145827c7a5\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"ee4e5597-17d4-4466-9a24-cf8054c893e0\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"929c751c-97a6-4449-a061-c0a7956eaf0c\": {\n          \"name\": \"Background\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8aaa5816-b914-42fa-8225-902e116009a0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:17:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page10_image01.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Gray Textile Closeup Photo\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e7ccc4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -58,\n          \"y\": -82,\n          \"width\": 800,\n          \"height\": 534,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c105f679-46cd-4de6-bccb-344ffefc49a6\",\n          \"groupId\": \"507168b8-9480-4229-b25d-fcc86b8310f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 1,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 675,\n          \"height\": 323,\n          \"sticker\": { \"type\": \"makerOffWhiteSectionSeparator\" },\n          \"id\": \"512a716c-0c7e-4c8a-b169-d4b316476d71\",\n          \"x\": -158,\n          \"y\": 420,\n          \"groupId\": \"507168b8-9480-4229-b25d-fcc86b8310f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 142,\n          \"height\": 97,\n          \"sticker\": { \"type\": \"makerRoundedBannerWithDots\" },\n          \"id\": \"63363320-828f-49bc-a457-a972b5a446a5\",\n          \"x\": 134,\n          \"y\": 366,\n          \"groupId\": \"5cce8fa9-4f82-4ac9-b3c8-ff4d0d2c013c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 49,\n          \"marginOffset\": -1.0999999999999979,\n          \"id\": \"e42f5caa-4510-4b24-87af-c753e99d5242\",\n          \"x\": 184,\n          \"y\": 387,\n          \"groupId\": \"5cce8fa9-4f82-4ac9-b3c8-ff4d0d2c013c\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">Let it dry</span>\\n<span style=\\\"font-weight: 600; color: #414c40\\\">overnight</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 479,\n          \"width\": 300,\n          \"height\": 60,\n          \"id\": \"45b55ca4-1d6a-4d22-8419-f10bc649943c\",\n          \"marginOffset\": 0.5625,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #414c40\\\">Remove the fabric from the dye bath and rinse gently in the sink and hang the dyed fabric to dry overnight.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 64,\n          \"marginOffset\": 2.465,\n          \"id\": \"3067bb2a-5b21-4ca2-b3bd-fb33271ceb37\",\n          \"x\": 56,\n          \"y\": 549,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"9b374799-1152-4923-9697-389eed8ebc0f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5cce8fa9-4f82-4ac9-b3c8-ff4d0d2c013c\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"507168b8-9480-4229-b25d-fcc86b8310f8\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"354a5ba1-eb8b-4536-8706-ee06fbc4f2ae\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:17:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page11_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White and Pink Striped Textile\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9f9b98\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"59354419-ca4f-4e76-9663-4ff211160cfe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 35,\n          \"y\": 20,\n          \"width\": 143,\n          \"height\": 92,\n          \"sticker\": { \"type\": \"makerYellowDots\" },\n          \"id\": \"19ae9804-ad75-4120-9c86-5ab4fd2e751a\",\n          \"groupId\": \"1edcf074-dffe-428e-981f-034083cff888\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 103,\n          \"y\": 28,\n          \"width\": 211,\n          \"height\": 188,\n          \"sticker\": { \"type\": \"makerGreenRoundBanner\" },\n          \"id\": \"81065f9e-8275-4b82-9f63-66d07c35fe4b\",\n          \"groupId\": \"1edcf074-dffe-428e-981f-034083cff888\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #f9e46c\\\">Your plant dyed fabrics are now ready for use!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 143,\n          \"y\": 72,\n          \"width\": 157,\n          \"height\": 99,\n          \"id\": \"c8ce6639-0c2d-4c03-9dc6-2dd48c80f43b\",\n          \"marginOffset\": -0.8249999999999993,\n          \"type\": \"text\",\n          \"groupId\": \"1edcf074-dffe-428e-981f-034083cff888\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 32,\n          \"y\": 562,\n          \"width\": 190,\n          \"height\": 44,\n          \"sticker\": { \"type\": \"makerOffWhiteBanner\" },\n          \"id\": \"5bfc563e-1ece-4079-b308-ce0e865e787f\",\n          \"groupId\": \"b3bb33ae-ef7d-4f59-83a7-90078d506530\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #414c40; letter-spacing: 0.12em; text-transform: uppercase\\\">WELL DONE!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 18,\n          \"marginOffset\": -3.0599999999999987,\n          \"type\": \"text\",\n          \"id\": \"c89e0355-28e4-448a-be7b-df28a0eebdce\",\n          \"x\": -32,\n          \"y\": 577,\n          \"groupId\": \"b3bb33ae-ef7d-4f59-83a7-90078d506530\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4215114c-2a64-4a2b-8be7-2a2ea62c54d0\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"5bfc563e-1ece-4079-b308-ce0e865e787f\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 228, \"g\": 213, \"b\": 184 } },\n      \"type\": \"page\",\n      \"id\": \"b04076b2-627d-4b68-961a-311ecd1d15a3\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"b3bb33ae-ef7d-4f59-83a7-90078d506530\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1edcf074-dffe-428e-981f-034083cff888\": {\n          \"name\": \"Text\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c5b82a83-89e9-4b6c-9010-547ed132a105\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:17:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page12_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo of Woman Wearing Pink Dress\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ebc5b4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"cb5319e6-0f8f-4e38-a89f-ecf6a3afb3f7\",\n          \"groupId\": \"9b8b9956-7a4e-4658-87b3-4e82de5f4642\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.7 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"48c68933-6f88-462b-8ecb-fcb0dcaec25a\",\n          \"x\": 0,\n          \"y\": -57,\n          \"groupId\": \"9b8b9956-7a4e-4658-87b3-4e82de5f4642\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 188,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -242,\n          \"y\": 547,\n          \"width\": 478,\n          \"height\": 508,\n          \"sticker\": { \"type\": \"makerYellowLeaf\" },\n          \"id\": \"b8e2d22e-9d3d-437a-a7d3-30c1f7beb050\",\n          \"groupId\": \"9b8b9956-7a4e-4658-87b3-4e82de5f4642\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 140,\n          \"y\": -22,\n          \"width\": 137,\n          \"height\": 95,\n          \"sticker\": { \"type\": \"makerBannerWithDots\" },\n          \"id\": \"7cb1be8b-2ad4-4e0d-8c89-e91a316ae5b3\",\n          \"groupId\": \"09f41c81-7684-4510-bf2c-71f8982f2f18\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.12em; text-transform: uppercase\\\">ENJOY</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 111,\n          \"height\": 18,\n          \"id\": \"c532cbe6-252a-4aaa-ac35-1ac9d5f13d36\",\n          \"x\": 150,\n          \"y\": 9,\n          \"marginOffset\": -3.3149999999999977,\n          \"type\": \"text\",\n          \"groupId\": \"09f41c81-7684-4510-bf2c-71f8982f2f18\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9e46c\\\">I mean, can you believe how easy that is? Water + Avocado + Fabric + Heat = the most gorgeous pink. The popular &nbsp;millennial pink!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 230,\n          \"marginOffset\": -4.649999999999999,\n          \"id\": \"a402030a-c04a-42f9-81e2-ca4a8abf541e\",\n          \"x\": 47,\n          \"y\": 331,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 147,\n          \"y\": 598,\n          \"id\": \"0987803c-2b09-4418-b7ca-98609ca450c3\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; letter-spacing: 0.12em; text-transform: uppercase\\\">SASHA DUERR</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 122,\n          \"height\": 18,\n          \"marginOffset\": -3.3149999999999977,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2599514c-8d50-4d35-a70d-0a484a526d4b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0987803c-2b09-4418-b7ca-98609ca450c3\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"b1958954-7a3b-4897-a463-7e419b446209\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"7cb1be8b-2ad4-4e0d-8c89-e91a316ae5b3\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"30d73acb-c84c-4193-8741-80eba533a661\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"09f41c81-7684-4510-bf2c-71f8982f2f18\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9b8b9956-7a4e-4658-87b3-4e82de5f4642\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"bf05ab8c-3f32-48d6-a3ba-aa78ce999548\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:17:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page13_image01.png\",\n            \"width\": 267,\n            \"height\": 246,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"cookware set on floating shelves\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#335668\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 172,\n          \"y\": 91,\n          \"width\": 178,\n          \"height\": 164,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d71698fe-e4d8-45cb-b3ff-5b0a29aef1c9\",\n          \"groupId\": \"923b3a9f-d5c7-4f52-aab8-41c38403f95a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 140,\n          \"y\": 188,\n          \"width\": 126,\n          \"height\": 86,\n          \"sticker\": { \"type\": \"makerYellowRoundBanner\" },\n          \"id\": \"c50daee2-0574-4325-b169-fbaac6104b37\",\n          \"groupId\": \"923b3a9f-d5c7-4f52-aab8-41c38403f95a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #e5e5e5\\\">7 DIY Ways to Organize Pots and Pans in Your Kitchen Cabinets</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 203,\n          \"height\": 58,\n          \"marginOffset\": 1.7399999999999984,\n          \"type\": \"text\",\n          \"id\": \"7bdfa090-6a40-4b73-b67a-591b2c148482\",\n          \"x\": 180,\n          \"y\": 279,\n          \"groupId\": \"923b3a9f-d5c7-4f52-aab8-41c38403f95a\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 29,\n          \"marginOffset\": -1.0999999999999979,\n          \"type\": \"text\",\n          \"id\": \"ea6bfbad-e6f5-4f09-a232-2578197a0d78\",\n          \"x\": 180,\n          \"y\": 216,\n          \"groupId\": \"923b3a9f-d5c7-4f52-aab8-41c38403f95a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T14:17:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/plant-based-dyes/page13_image02.png\",\n            \"width\": 178,\n            \"height\": 164,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photography of a Woman Holding Green Leaves\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d6c9bd\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 72,\n          \"y\": 384,\n          \"width\": 178,\n          \"height\": 164,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6173211e-ea40-42a1-89b4-6fb1f9958e30\",\n          \"groupId\": \"e800ab8c-4866-40d0-a0de-e77329e6a1d0\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 490,\n          \"id\": \"66350784-9414-4772-8e82-c2cd21bec99a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 126,\n          \"height\": 86,\n          \"sticker\": { \"type\": \"makerYellowRoundBanner\" },\n          \"groupId\": \"e800ab8c-4866-40d0-a0de-e77329e6a1d0\"\n        },\n        {\n          \"x\": 80,\n          \"y\": 575,\n          \"id\": \"92b02ce0-fd6e-4958-9d13-95b3cde88829\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #e5e5e5\\\">Slow fashion and regenerative design</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 203,\n          \"height\": 39,\n          \"marginOffset\": 1.7399999999999984,\n          \"type\": \"text\",\n          \"groupId\": \"e800ab8c-4866-40d0-a0de-e77329e6a1d0\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 80,\n          \"y\": 521,\n          \"id\": \"e660456d-4de2-4851-8b7e-27df340c0f51\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #414c40\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 53,\n          \"height\": 29,\n          \"marginOffset\": -1.0999999999999979,\n          \"type\": \"text\",\n          \"groupId\": \"e800ab8c-4866-40d0-a0de-e77329e6a1d0\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -60,\n          \"y\": 103,\n          \"width\": 186,\n          \"height\": 173,\n          \"sticker\": { \"type\": \"makerGreenLeaf\" },\n          \"id\": \"7bf924db-c2cb-49be-b5b2-abd58f68a685\",\n          \"groupId\": \"f2fd51c8-8826-4316-80b5-d68ce5e24c22\"\n        },\n        {\n          \"x\": 274,\n          \"y\": 476,\n          \"id\": \"bc7c0591-9088-44bc-99c6-c9503e52abb1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 186,\n          \"height\": 173,\n          \"sticker\": { \"type\": \"makerGreenLeaf\" },\n          \"groupId\": \"f2fd51c8-8826-4316-80b5-d68ce5e24c22\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 10,\n          \"id\": \"d5850110-f792-4ef7-b144-71026ac02498\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9e46c\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 29,\n          \"marginOffset\": 0.7593749999999986,\n          \"type\": \"text\",\n          \"groupId\": \"43ee0819-fede-4817-996d-0ba1de825a37\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 43,\n          \"width\": 153,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"makerWavyLine\" },\n          \"id\": \"7650709d-23d0-4bc5-9d28-1b9bf86a45eb\",\n          \"groupId\": \"43ee0819-fede-4817-996d-0ba1de825a37\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"eb173176-7330-418f-aa93-6d2be2a334d0\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"7650709d-23d0-4bc5-9d28-1b9bf86a45eb\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7d1e5c84-2bda-4ccf-ac84-2554c515d87e\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"c50daee2-0574-4325-b169-fbaac6104b37\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"94f1255d-5e23-4b5d-9eca-c794adea40bb\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"66350784-9414-4772-8e82-c2cd21bec99a\"],\n          \"scale\": 0.08,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 65, \"g\": 76, \"b\": 64 } },\n      \"type\": \"page\",\n      \"id\": \"5694fe54-b2af-4fd3-bcc2-8eaaea9f67aa\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"43ee0819-fede-4817-996d-0ba1de825a37\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f2fd51c8-8826-4316-80b5-d68ce5e24c22\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"923b3a9f-d5c7-4f52-aab8-41c38403f95a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e800ab8c-4866-40d0-a0de-e77329e6a1d0\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/pride-month-watchlist/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/pride-month-watchlist/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'pride-month-watchlist',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Pride Month Watchlist', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Watchlist', 'template keyword', 'web-stories'),\n    _x('Favourite', 'template keyword', 'web-stories'),\n    _x('Colourful', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Emerald Green', 'color', 'web-stories'),\n      color: '#006110',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Venice Red', 'color', 'web-stories'),\n      color: '#b50021',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Raspberry Pink', 'color', 'web-stories'),\n      color: '#9e005f',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Daring Violet', 'color', 'web-stories'),\n      color: '#5c0094',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Sassy and bold with no distractions, this template will let you create watchlists, summaries, synopses and more with personality and character.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/pride-month-watchlist/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/pride-month-watchlist/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e04b9fce-cbde-4d51-afd0-739e8b4c10c5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 16,\n          \"y\": -41,\n          \"width\": 120,\n          \"height\": 443,\n          \"scale\": 180,\n          \"focalX\": 46.37826101842547,\n          \"focalY\": 50.01528636702987,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8b097584-d872-4e06-b105-f47cb20afb54\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page01_image01.jpg\",\n            \"width\": 1709,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Dancing Man in White Room\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#aeb4bb\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 443,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"68ad66b4-73dd-42af-a7b2-788d497715b6\",\n          \"x\": 146,\n          \"y\": -41,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page01_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in White Crew Neck T-shirt Holding Teal Ceramic Bowl\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bbb3bb\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 443,\n          \"scale\": 150,\n          \"focalX\": 46.09509754221782,\n          \"focalY\": 38.593312922305515,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e2bd22c7-c501-4bf7-b70c-56529bf2aa12\",\n          \"x\": 276,\n          \"y\": -41,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page01_image03.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man in White Long Sleeve Shirt Sitting on Brown Chair\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#433429\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 106,\n          \"y\": 608,\n          \"width\": 200,\n          \"height\": 16,\n          \"id\": \"13e030de-ce98-401e-a506-703fa6222294\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">What to watch during pride month</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 444,\n          \"width\": 316,\n          \"height\": 155,\n          \"id\": \"46770d7c-7dd1-47ed-900a-6e94d96613d5\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 97, \"b\": 16 } },\n      \"type\": \"page\",\n      \"id\": \"bbccbe21-c824-4760-a4bb-a24296c45abd\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"36da58e0-24ca-401d-a7bd-e2740c98209f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Since June is synonymous with Pride month, we compiled a few must watch LGBTQI movies to see in the weeks ahead.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 310,\n          \"height\": 193,\n          \"id\": \"4c7354f1-dd91-4f62-97a5-749c71014a29\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 412,\n          \"height\": 273,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 36.851851851851855,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5294bc6f-8e55-4ab9-a15a-c9cd66f69377\",\n          \"x\": 0,\n          \"y\": 402,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page02_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man in White Button Up Shirt Sitting on White Couch\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#241c16\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 97, \"b\": 16 } },\n      \"type\": \"page\",\n      \"id\": \"73b6974d-70dd-4829-afee-c77f094fd0e1\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"09ec63ac-78f4-4404-9cca-9cd10c98e7c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page03_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1568,\n            \"id\": 0,\n            \"alt\": \"Grayscale Photo of Boy Standing Behind Wooden Fence\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#868686\",\n            \"isExternal\": true\n          },\n          \"x\": 116,\n          \"y\": 0,\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 100,\n          \"focalX\": 55.809859875562196,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fe0beabc-15fd-47f1-8ee9-bd1435094386\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 165,\n          \"focalX\": 47.65866050947544,\n          \"focalY\": 64.84761203059782,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"af589b5c-56cc-48bd-a128-17f1e8c95b03\",\n          \"x\": 245,\n          \"y\": 0,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page03_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Blue haired woman on window on white concrete building during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#f1f0ee\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Watch with friends&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 67,\n          \"id\": \"5f4960f4-2aef-4dfd-ad1c-f07418aafa74\",\n          \"x\": 59,\n          \"y\": 406,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Meaty movies worthy of good recap conversation over bowls of popcorn and ice cream.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 288,\n          \"height\": 74,\n          \"type\": \"text\",\n          \"id\": \"990a67d8-aa6c-4a76-8d13-5413d7de8367\",\n          \"x\": 48,\n          \"y\": 541\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"05b17473-6c62-4e98-8dd1-38b150f7cdba\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fe0beabc-15fd-47f1-8ee9-bd1435094386\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"81953fc8-bf89-47e4-8469-669a0a06e259\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"af589b5c-56cc-48bd-a128-17f1e8c95b03\"],\n          \"duration\": 3000,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 181, \"g\": 0, \"b\": 33 } },\n      \"type\": \"page\",\n      \"id\": \"7cd72777-83f1-4bf3-9dc5-5fb6aaec7240\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"3ce4fe6e-6fad-477f-9fc5-4191fef06dff\",\n          \"scale\": 112,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page04_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Grayscale Photo of Boy Sitting on Stair\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#5f6565\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 },\n                \"position\": 0.56\n              },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 },\n                \"position\": 0.83\n              }\n            ],\n            \"alpha\": 0.4\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 2,\n          \"width\": 26,\n          \"height\": 16,\n          \"id\": \"a4f7b221-79be-43b2-a44c-d55209950151\",\n          \"marginOffset\": 3.9375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Moon Night</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 35,\n          \"id\": \"b2e2d092-0fb7-4f91-9119-4f25ae140168\",\n          \"x\": 73,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">A classic bildungsroman of Charles, a young Black man from a tough Miami neighborhood, as he navigates his identity.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 85,\n          \"type\": \"text\",\n          \"id\": \"aabc53ef-8ad8-44f8-9847-dec873d1c2f2\",\n          \"x\": 47,\n          \"y\": 530\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c4a3852f-216c-47b4-94e4-3e1e45ca39f4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"73eb1435-661c-46df-b781-2f53ab0af86d\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"73eb1435-661c-46df-b781-2f53ab0af86d\",\n          \"scale\": 139,\n          \"focalX\": 50.2248201438849,\n          \"focalY\": 49.10071942446043,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page05_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Woman in white long sleeve shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a5a49f\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 },\n                \"position\": 0.02\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.49 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 2,\n          \"width\": 26,\n          \"height\": 17,\n          \"id\": \"94fa6b8e-33f1-4068-a102-406f9eb20b79\",\n          \"marginOffset\": 3.9375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Blue is the coldest color</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 99,\n          \"id\": \"b514a18a-a050-464e-9157-bc1cf6bcd79f\",\n          \"x\": 73,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">An ambiguous friendship between Adele and Emma, two teenagers trying to understand their feelings for one another.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"id\": \"b99a38b7-afa1-45f4-9cd8-37f6da8cd804\",\n          \"x\": 47,\n          \"y\": 552,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"4f027682-4c20-4fed-8a26-d2cf1c5f6619\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"10dce7c6-8e00-425a-bcf7-d9b3828ebf53\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"0243a703-3f7d-4f35-917f-2a9ed64a7b1f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 100,\n          \"focalX\": 46.91415633550373,\n          \"focalY\": 50.07807894915997,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"60560392-fb01-49e2-aed2-6853093c3dac\",\n          \"x\": 116,\n          \"y\": 2,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page06_image01.jpg\",\n            \"width\": 1920,\n            \"height\": 1277,\n            \"id\": 0,\n            \"alt\": \"Woman in white long sleeve shirt with pink manicure\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b3b2b4\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 270,\n          \"focalX\": 70.22338421108417,\n          \"focalY\": 45.92409822919098,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c467a303-2129-432b-8981-0bd66055766a\",\n          \"x\": 245,\n          \"y\": 2,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page06_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in Blue Denim Jeans Standing\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#645f5a\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Watch alone and cry</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 67,\n          \"id\": \"a0062be3-99ee-4d16-a4ae-72efeae71ef4\",\n          \"x\": 59,\n          \"y\": 406,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Sometimes you just want to feel all the feelings, alone. We get it.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 302,\n          \"height\": 48,\n          \"type\": \"text\",\n          \"id\": \"0bb7eb89-89ee-424d-afee-90f5435d926c\",\n          \"x\": 48,\n          \"y\": 566\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3caa1365-b466-40f4-84d1-8314cd452837\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"60560392-fb01-49e2-aed2-6853093c3dac\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c177db18-147d-41b5-8073-51a1d186a568\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c467a303-2129-432b-8981-0bd66055766a\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 158, \"g\": 0, \"b\": 95 } },\n      \"type\": \"page\",\n      \"id\": \"963b3076-2c74-48e3-84cd-2353f6ce6c2e\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 545,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"e4082697-ee44-4757-a36e-beb8747fadec\",\n          \"scale\": 115,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page07_image01.jpg\",\n            \"width\": 1548,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Man Standing in the Middle of Road\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#262921\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 },\n                \"position\": 0.01\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.39 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 26,\n          \"height\": 16,\n          \"marginOffset\": 3.9375,\n          \"id\": \"ae99cc69-ba6e-4ccc-8344-e366c3d154d4\",\n          \"x\": 47,\n          \"y\": 2\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Billy Alles</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 35,\n          \"id\": \"34227a5c-95bf-4f51-8029-c5c2975e0ea8\",\n          \"x\": 73,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">An 11 year old boy discovers his love for ballet.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 40,\n          \"type\": \"text\",\n          \"id\": \"ca542a10-381d-4da0-b23f-90a5b6ba56d5\",\n          \"x\": 47,\n          \"y\": 574\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7529f122-4e94-4bca-b817-838c9da696b3\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"8bf27660-d58f-4a25-8d1c-3a1d019a7ec9\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"7d921249-e940-4798-ae33-15d18eee245a\",\n          \"scale\": 127,\n          \"focalX\": 46.6798797367126,\n          \"focalY\": 59.59645669291339,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page08_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Woman in White Crew Neck T-shirt Sitting on Brown Wooden Chair\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d5c8c2\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.25 },\n                \"position\": 0.02\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.44 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 26,\n          \"height\": 17,\n          \"marginOffset\": 3.9375,\n          \"type\": \"text\",\n          \"id\": \"593cd0f5-ca4b-4996-bdd7-e21d339fea23\",\n          \"x\": 47,\n          \"y\": 2\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Carole</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 35,\n          \"type\": \"text\",\n          \"id\": \"7f17809e-d78a-46f6-a14a-27e554e7a226\",\n          \"x\": 73,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">A compelling love story set in 1950s New York, Carole’s narrative weaves through forbidden desire, compromise, and lives that could have been.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 84,\n          \"type\": \"text\",\n          \"id\": \"80b59767-1d71-435a-972c-1b068da01329\",\n          \"x\": 47,\n          \"y\": 552\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8eef080d-9ad8-4523-9c98-7afd82074d30\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"7577a8d2-0ded-4fe6-b9c6-30110eaf6083\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"436bfb1f-3049-49c5-8789-28b87ac6b0e5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"video\",\n          \"width\": 412,\n          \"height\": 273,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8608de5a-0391-4467-818e-84fd52a6505c\",\n          \"x\": 0,\n          \"y\": -57,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page09_vid01.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page09_vid01-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"lengthFormatted\": \"0:20\",\n            \"alt\": \"A Woman Having Coffee On A Veranda\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"length\": 20,\n            \"baseColor\": \"#c9c3c1\",\n            \"isExternal\": true\n          },\n          \"tracks\": []\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Carol, directed by New Queer Cinema Director Todd Haynes, has received a ten-minute standing ovation at its Cannes Film Festival international press screening and premiere.\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 309,\n          \"height\": 259,\n          \"type\": \"text\",\n          \"id\": \"eb8aedab-d7b9-4bd7-be31-39c2c33591d9\",\n          \"x\": 48,\n          \"y\": 273\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 158, \"g\": 0, \"b\": 95 } },\n      \"type\": \"page\",\n      \"id\": \"787df553-c506-4767-b61f-2b944fbabea1\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"WATCH THE TRAILER\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"78982ce2-88d4-421e-afe1-8e8ed763a60b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 120,\n          \"focalX\": 62.71604941708372,\n          \"focalY\": 56.31464877471317,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"863fc5be-dc84-4e09-a833-9647924518ea\",\n          \"x\": 116,\n          \"y\": 2,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page10_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in Red Jacket Standing Near Glass Door\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#50291b\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 370,\n          \"scale\": 100,\n          \"focalX\": 32.692210914183164,\n          \"focalY\": 50.07807894915997,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e1a254ab-7664-4f67-a944-1b5c85266491\",\n          \"x\": 245,\n          \"y\": 2,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page10_image02.jpg\",\n            \"width\": 1920,\n            \"height\": 1279,\n            \"id\": 0,\n            \"alt\": \"Man With Raised Fist in a Protest\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c4bdba\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Watch too feel a surge of pride</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 99,\n          \"id\": \"7d51bd62-a5ff-4993-b9aa-59e5ac30b45b\",\n          \"x\": 48,\n          \"y\": 406,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">When you need to feel your spirits soar.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 48,\n          \"type\": \"text\",\n          \"id\": \"fc64ee2d-fabc-44f8-891d-757cc471def0\",\n          \"x\": 48,\n          \"y\": 567\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"edc9dbc3-3ab2-484c-9005-cbb8bb2d7cab\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"863fc5be-dc84-4e09-a833-9647924518ea\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0da2ec52-08b7-43ca-aa2c-007fc7a2042c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e1a254ab-7664-4f67-a944-1b5c85266491\"],\n          \"duration\": 3000,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 92, \"g\": 0, \"b\": 148 } },\n      \"type\": \"page\",\n      \"id\": \"c0262900-6070-4da8-b493-1f2a05a9f622\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"0a82e607-7e3c-49bc-ae75-8e599296ad00\",\n          \"type\": \"image\",\n          \"scale\": 128,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page11_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in Red Crew Neck Shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#342626\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 },\n                \"position\": 0.02\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.5 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 26,\n          \"height\": 16,\n          \"marginOffset\": 3.9375,\n          \"id\": \"9b8f0f29-5ed7-43e3-9fa1-d41edcba0bf4\",\n          \"x\": 47,\n          \"y\": 2\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Rockets</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 35,\n          \"id\": \"0b17e829-a14a-41dd-b817-38459aceff55\",\n          \"x\": 73,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">You know who's story retold through fantastical &nbsp;narrative, song and dance.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 310,\n          \"height\": 40,\n          \"type\": \"text\",\n          \"id\": \"91475c79-52d8-48d1-8037-ea66f3b7cd39\",\n          \"x\": 47,\n          \"y\": 574\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"6ac6026a-2f60-44a6-a50f-6fcc96109489\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"ee6c5d0c-3a32-4eb9-9b9a-2f2c72ac0c35\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 495,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9713b6a7-43f8-4fb9-a447-e19e67d49f01\",\n          \"type\": \"image\",\n          \"scale\": 160,\n          \"focalX\": 50,\n          \"focalY\": 51.32378472222222,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page12_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 1921,\n            \"id\": 0,\n            \"alt\": \"Photo of Woman Raising Her Right Hand\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9f9895\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 },\n                \"position\": 0.02\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.45 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 26,\n          \"height\": 17,\n          \"marginOffset\": 3.9375,\n          \"type\": \"text\",\n          \"id\": \"3c9f8bdf-af22-4224-9449-6250cf03625a\",\n          \"x\": 47,\n          \"y\": 2\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">How to survive a memory</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 99,\n          \"type\": \"text\",\n          \"id\": \"60ea80dc-8e71-442e-9288-90e0939f6f0c\",\n          \"x\": 73,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Centered around ACT UP, this movie focuses on AIDS in New York in the 80s and 90s.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 62,\n          \"type\": \"text\",\n          \"id\": \"b9183775-1286-4d24-9d4b-7203cbfc70f5\",\n          \"x\": 47,\n          \"y\": 552\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"f2ac6def-15b4-490b-97f3-d45d4c59c7ff\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8c44506b-4b16-41cb-bb82-da6e19e82725\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"98b6c9c6-ce6a-4f1d-b564-6fb3b502587d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 35,\n          \"id\": \"4dbdec34-61d6-4926-aaed-cb70458c6aac\",\n          \"x\": 48,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 218,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4866035a-b5d7-4943-93a9-d80e93f0d713\",\n          \"x\": 48,\n          \"y\": 61,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page13_image01.jpg\",\n            \"width\": 1707,\n            \"height\": 2560,\n            \"id\": 0,\n            \"alt\": \"Man holding pistol wearing black bulletproof vest\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#101b1f\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">In action</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 101,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"id\": \"3e5704c9-5ae7-41ee-86a5-6145515356c6\",\n          \"x\": 48,\n          \"y\": 297\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Greatest Protest Movies of</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">All Time</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 101,\n          \"height\": 100,\n          \"type\": \"text\",\n          \"id\": \"0b56a1ba-e87a-49b5-8642-30fcf5b597e3\",\n          \"x\": 48,\n          \"y\": 353\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 218,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"061fdd0d-ce29-4f92-8fc4-b0b8022442c5\",\n          \"x\": 225,\n          \"y\": 234,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/pride-month-watchlist/page13_image02.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Two women smiling during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#271510\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo Black\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1035,\n              \"wDes\": 312,\n              \"xH\": 528,\n              \"capH\": 688,\n              \"yMin\": -267,\n              \"yMax\": 957,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">A love history</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 111,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"id\": \"530b0fcb-1cc8-4450-a80f-3ed3766b8eaa\",\n          \"x\": 223,\n          \"y\": 472\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Archivo\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 878,\n              \"des\": -210,\n              \"tAsc\": 878,\n              \"tDes\": -210,\n              \"tLGap\": 0,\n              \"wAsc\": 1100,\n              \"wDes\": 410,\n              \"xH\": 526,\n              \"capH\": 686,\n              \"yMin\": -406,\n              \"yMax\": 1092,\n              \"hAsc\": 878,\n              \"hDes\": -210,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">One of the best stories of love</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 114,\n          \"height\": 74,\n          \"type\": \"text\",\n          \"id\": \"6085d84b-f864-453a-9eb5-4f815a5232d8\",\n          \"x\": 223,\n          \"y\": 529\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c37cbe50-1989-4e51-b1a2-ceee5454b692\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4866035a-b5d7-4943-93a9-d80e93f0d713\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a01de88c-d55c-463e-b090-afd80e3dbd94\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"061fdd0d-ce29-4f92-8fc4-b0b8022442c5\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"1dc3f7e2-6690-48f8-bda5-8d14c604ef6d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3e5704c9-5ae7-41ee-86a5-6145515356c6\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"7e54768f-69d7-4ca2-8a04-f5fd8910b477\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0b56a1ba-e87a-49b5-8642-30fcf5b597e3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"342ff606-4bff-4b5a-9040-acd29a40fb96\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"530b0fcb-1cc8-4450-a80f-3ed3766b8eaa\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"e2322884-3698-4b00-afec-b92964c6b0f2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6085d84b-f864-453a-9eb5-4f815a5232d8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 150\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"76a17872-128b-4f38-af96-2525ef6ef367\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/rock-music-festival/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/rock-music-festival/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'rock-music-festival',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Rock Music Festival', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Concert', 'template keyword', 'web-stories'),\n    _x('Music', 'template keyword', 'web-stories'),\n    _x('Festival', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mercury Gray', 'color', 'web-stories'),\n      color: '#e3e3e3',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Festive Orange', 'color', 'web-stories'),\n      color: '#f8754c',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its powerful headlines and tantalizing visuals, this template is great for creating energetic stories about rock concerts, music festivals, concert tours and more.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/rock-music-festival/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/rock-music-festival/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1c0117fb-a1b6-47fd-8247-19768859690a\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:38:48\",\n            \"baseColor\": \"#e6c092\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"People watching band on the stage\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.11,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">By John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 473,\n          \"width\": 165,\n          \"height\": 19,\n          \"id\": \"080b6375-2871-41d7-9ca3-3c7e6cb1c3df\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 203,\n          \"id\": \"8ed77bbc-1fd0-45ad-9eb3-0987ffd86016\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.11,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Behind the scenes:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 209,\n          \"height\": 28\n        },\n        {\n          \"x\": 45,\n          \"y\": 276,\n          \"id\": \"bb82bfe7-21df-41fb-931e-0ae8360a0588\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bebas Neue\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 900,\n              \"des\": -300,\n              \"tAsc\": 900,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 950,\n              \"wDes\": 350,\n              \"xH\": 700,\n              \"capH\": 700,\n              \"yMin\": -200,\n              \"yMax\": 912,\n              \"hAsc\": 900,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 88,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Rock in</span>\\n<span style=\\\"color: #fff; text-transform: uppercase\\\">Rotterdam</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 176\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 0,\n          \"y\": 553,\n          \"width\": 245,\n          \"height\": 122,\n          \"sticker\": { \"type\": \"rockInRotterdamFlames\" },\n          \"id\": \"7cff4dc0-6d11-4c1c-9feb-65772e3c0353\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"0ba91e48-1b84-49ed-b080-0361a070c365\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f35e71dc-82b5-4b6c-b34a-96b614e20921\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"42f94cf9-371b-4782-9bac-00c5a2fd220e\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-10T12:06:15\",\n            \"baseColor\": \"#131115\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page2_bg.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 36,\n            \"lengthFormatted\": \"0:36\",\n            \"alt\": \"Aerial view of people watching a concert\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.42 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">One of the most popular rock festivals of all time, Rock in Rotterdam has won the hearts of so many rock fans from all over the world.</span>\\n\\n<span style=\\\"color: #fff\\\">But how is the festival created each year?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 395,\n          \"width\": 317,\n          \"height\": 219,\n          \"id\": \"86498944-f4b2-4f8f-9e42-8400a30707bf\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 368,\n          \"y\": 395,\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"7eac8e45-87eb-4a40-a073-fef321319f35\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -18,\n          \"y\": 394,\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"82c325e0-52b2-4f29-acc1-5e38c0bc26cc\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"ea18b268-dbc9-445b-9c02-18c5153c3d95\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f4a5d856-3d77-43b4-b889-3514abb2a7e4\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"bf9e18a2-8d7b-424d-bafc-818656cbe34b\",\n          \"type\": \"video\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-06-10T11:55:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page3_bg.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page3_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 18,\n            \"lengthFormatted\": \"0:18\",\n            \"alt\": \"Rock Band Concert\",\n            \"sizes\": [],\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#1c111d\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.45 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">One of the first things that gets nailed down is the roster of performing artists. The headliner last year were The Bools.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 507,\n          \"width\": 317,\n          \"height\": 108,\n          \"id\": \"42866736-232b-473e-b886-029ad6e2e4c6\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 12,\n          \"y\": 469,\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"3e839cf5-bf3e-455b-8c99-b56c7bc116aa\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2bf9f71f-0c70-4d5e-8eb1-e063da7a9c17\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3e839cf5-bf3e-455b-8c99-b56c7bc116aa\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"2e301795-7350-4960-ae45-278bd62c852b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f8fb5413-f1ab-4321-b666-54a013c17af9\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"915817c6-e107-4c4c-b713-a067b456f6cf\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-25T08:13:43\",\n            \"baseColor\": \"#111417\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page4_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Black metal guitar stand with turned-on stage light\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -49,\n          \"y\": -129,\n          \"width\": 401,\n          \"height\": 329,\n          \"sticker\": { \"type\": \"rockInRotterdamLightning\" },\n          \"id\": \"778ec7fd-1bd3-4362-89b6-47b096a06ee9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Curation of stages and set times take months to plan and develop. There is a lot of back and forth between artists and agents about preferences and availabilities.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 483,\n          \"width\": 317,\n          \"height\": 136,\n          \"id\": \"103c2125-f9c7-4293-8bcf-a6440a05e80a\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bebas Neue\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 900,\n              \"des\": -300,\n              \"tAsc\": 900,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 950,\n              \"wDes\": 350,\n              \"xH\": 700,\n              \"capH\": 700,\n              \"yMin\": -200,\n              \"yMax\": 912,\n              \"hAsc\": 900,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 88,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Setting the Stage</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 176,\n          \"id\": \"c3359848-855e-4070-aa52-151466088fb0\",\n          \"x\": 47,\n          \"y\": 275\n        },\n        {\n          \"x\": 50,\n          \"y\": 203,\n          \"id\": \"4aec4a45-f4d6-411b-b2ac-3a48eaeac9e1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.11,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f8754c; letter-spacing: 0.03em; text-transform: uppercase\\\">Time to Prep</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 19,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"616f57c7-6617-4141-b6f4-4e166671d226\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"778ec7fd-1bd3-4362-89b6-47b096a06ee9\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"cffa36b9-86d8-4757-b746-177bb61a7a30\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"869d2ae2-5789-4109-9a47-9e407b1f36c5\",\n        \"type\": \"shape\"\n      },\n      \"pageAttachment\": { \"theme\": \"light\" },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d49d5124-17e9-480c-b38a-64afe4d4fdc0\",\n          \"type\": \"image\",\n          \"scale\": 106,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:39:40\",\n            \"baseColor\": \"#1b1616\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page5_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"People in a concert\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">There are usually 6 stages, 2 main, and 4 smaller. Once artists are locked in, stage and set design can start planning the equipment, sound, and lighting appropriate for each artist.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 449,\n          \"width\": 317,\n          \"height\": 164,\n          \"id\": \"ca3900cf-42b8-4a34-90e9-82549d4d4ab6\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 2,\n          \"y\": 423,\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"b2d81107-865d-4ee7-a1cd-60d26ef94770\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a54481e4-c88f-4371-838d-6e0e228b6afd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b2d81107-865d-4ee7-a1cd-60d26ef94770\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5af7d1b4-6c3e-474a-af92-36f6d40bb0b7\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"d49d5124-17e9-480c-b38a-64afe4d4fdc0\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"9cb6e92f-2e06-482b-8385-2fcef15dd550\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"509743ae-90b1-4163-ae8e-2da0c61c42d0\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"23d41ffe-df40-4a45-a801-239d0fd33d7c\",\n          \"type\": \"image\",\n          \"scale\": 111,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:40:03\",\n            \"baseColor\": \"#1d181c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page6_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"People having a concert\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Most main stage acts take 6 months or more to plan, depending on the level of theatrics and sophistication.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 496,\n          \"width\": 268,\n          \"height\": 107,\n          \"id\": \"d8669465-fc29-4a21-bde8-03f0e498f700\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"40065e6f-71ff-487c-8bbc-94179806f09e\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"23d41ffe-df40-4a45-a801-239d0fd33d7c\"],\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"44375129-089c-4716-9500-368d1d841778\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"9aac0519-6b18-4bee-a02e-a12b240cfa3d\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"f7a57f1f-afbf-4004-9fa2-309ef208f4e8\",\n          \"type\": \"image\",\n          \"scale\": 111,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-11T11:46:51\",\n            \"baseColor\": \"#0a0b0c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Gray roll up door opened\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Professional grade equipment and power systems are flown in from all over Europe to prepare for the festival.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 108,\n          \"type\": \"text\",\n          \"id\": \"e6797678-86e7-46d5-b1d3-f166c0032f1b\",\n          \"x\": 48,\n          \"y\": 496\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"517bca34-1b00-4011-8e4b-72bbe2273d52\",\n          \"x\": 374,\n          \"y\": 496\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 56,\n          \"height\": 46,\n          \"sticker\": { \"type\": \"rockInRotterdamWhiteLightning\" },\n          \"id\": \"30ab0e6f-14ab-4958-a0fd-44bea1d84cd0\",\n          \"x\": -18,\n          \"y\": 494\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5078dcb0-32c7-4d05-988b-931d84e97c26\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"f7a57f1f-afbf-4004-9fa2-309ef208f4e8\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"7427f8f7-5e9e-483a-9498-f7b0299f60e8\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"77e2e659-d0f2-4d32-b143-5a412a3caa98\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cc41c2d3-8626-4b88-8491-035f2261722f\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-14T10:05:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page8_bg.png\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Black background with white dusty corners\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ffffff\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Each of the 3 stages acts as its own little city in terms of a power system, equipment and the sound engineers that keep the stage operating at its best.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 136,\n          \"id\": \"0d782601-12da-4fcf-b7a8-b5f6f25cc0f6\",\n          \"x\": 47,\n          \"y\": 4,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:40:30\",\n            \"baseColor\": \"#210f0b\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page8_image1.png\",\n            \"width\": 781,\n            \"height\": 1012,\n            \"id\": 0,\n            \"alt\": \"Labels with three stages, stage 1 at the top, stage 2 and 3 at the bottom\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 57,\n          \"y\": 200,\n          \"width\": 298,\n          \"height\": 386,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"499abe87-777e-4666-a288-29cd64810dfc\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"042b51bf-f633-4d29-9719-184029d0d1fe\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"499abe87-777e-4666-a288-29cd64810dfc\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 20, \"g\": 20, \"b\": 20 } },\n      \"type\": \"page\",\n      \"id\": \"db98510e-aadf-4cb9-8644-6e82df92c23c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"53c569ec-5a0d-4995-a356-83f831dbcb8f\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3aec6bb2-c85d-4247-a190-7562ad461a51\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 48.107047032828284,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:41:17\",\n            \"baseColor\": \"#170d0c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page9_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Person holding drinking glass\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">With all the prep work on sound, we can’t forget about food and beverage for the festival.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 535,\n          \"width\": 317,\n          \"height\": 79,\n          \"id\": \"4e43f1ad-93c9-4387-a0a3-9731d2811674\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bebas Neue\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 900,\n              \"des\": -300,\n              \"tAsc\": 900,\n              \"tDes\": -300,\n              \"tLGap\": 0,\n              \"wAsc\": 950,\n              \"wDes\": 350,\n              \"xH\": 700,\n              \"capH\": 700,\n              \"yMin\": -200,\n              \"yMax\": 912,\n              \"hAsc\": 900,\n              \"hDes\": -300,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 88,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">The Experience</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 176,\n          \"id\": \"4af4aaa1-6ae7-4ede-985c-8e4ff2e4c891\",\n          \"x\": 47,\n          \"y\": 0,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 136,\n          \"y\": 160,\n          \"width\": 401,\n          \"height\": 329,\n          \"sticker\": { \"type\": \"rockInRotterdamLightning\" },\n          \"id\": \"cb2310ff-403e-4afd-8948-418903054cbf\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b375725f-3444-4812-a13a-da7d3a5e22d9\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"cb2310ff-403e-4afd-8948-418903054cbf\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9ed807a9-b08c-45e0-a348-c40802b72ded\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"3aec6bb2-c85d-4247-a190-7562ad461a51\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"b5ce2a17-051f-40f9-b21b-743078815857\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8d71d082-025d-4044-8e12-f34dc9347626\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d4889792-ec43-4004-a5d3-5309ca266e65\",\n          \"type\": \"image\",\n          \"scale\": 109,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:41:22\",\n            \"baseColor\": \"#1c150e\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Burger with stick\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">A team of 20 festival planners coordinate with food and drink vendors to keep variety high and \\ncosts low.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 108,\n          \"id\": \"be2f47ca-876d-480d-a96f-15a3262ad695\",\n          \"x\": 47,\n          \"y\": 4,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"67c3030e-a3bd-42ff-a76a-78a4702ba9fe\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"d4889792-ec43-4004-a5d3-5309ca266e65\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 20, \"g\": 20, \"b\": 20 } },\n      \"type\": \"page\",\n      \"id\": \"1fe3324a-f76d-4e7e-9697-8fb7a3bc89bb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"bd3f7b22-0556-40e7-809e-8ad2297b0b40\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"2759ba7b-91f3-4eac-88f1-cbf93657cb88\",\n          \"type\": \"image\",\n          \"scale\": 110,\n          \"focalX\": 52.208445128366996,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:41:41\",\n            \"baseColor\": \"#141d1c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Woman touching head of topless man holding cup with beer\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">The festival grounds are architected to account for the food stalls, rest areas, VIP areas, and of course restrooms.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 108,\n          \"id\": \"7bd6b7f0-f7de-4144-8cfb-126fcfc437f7\",\n          \"x\": 47,\n          \"y\": 4,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e62b3524-c47c-484f-8ea1-ab898d83630f\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"2759ba7b-91f3-4eac-88f1-cbf93657cb88\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 20, \"g\": 20, \"b\": 20 } },\n      \"type\": \"page\",\n      \"id\": \"46289385-1bff-40b9-8256-40a0fc82ca78\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"44207339-c6ae-4f85-a2ae-dc666afebf0a\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"c08e63e2-1b3d-42ad-ad9d-c06e822dda6e\",\n          \"type\": \"image\",\n          \"scale\": 115,\n          \"focalX\": 53.31952621779388,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:41:50\",\n            \"baseColor\": \"#352325\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page12_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1919,\n            \"id\": 0,\n            \"alt\": \"Selective focus photography of man playing drum\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">After a full year of planning, rock fans get to enjoy a 3-day festival of a lifetime.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 79,\n          \"id\": \"ef019b4d-19e3-4e3c-bf19-275948b160eb\",\n          \"x\": 47,\n          \"y\": 4,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"88e7dcaf-d49f-45ba-91e3-f1f07a4659fb\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"c08e63e2-1b3d-42ad-ad9d-c06e822dda6e\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 20, \"g\": 20, \"b\": 20 } },\n      \"type\": \"page\",\n      \"id\": \"304bb021-2e82-43f0-9426-af79c3b61304\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"23adf013-9449-4ca8-8ab9-a5a64f92f9dd\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2572d086-b016-4e3d-8c63-480b1c5ee6c2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-10T11:42:01\",\n            \"baseColor\": \"#c5bbb7\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/rock-music-festival/page13_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Man in gray zip up jacket holding red and black smartphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"x\": 112,\n          \"y\": 81,\n          \"width\": 300,\n          \"height\": 326,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"af563aaa-09d3-405f-8da5-f4d30612e06c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -32,\n          \"y\": -53,\n          \"width\": 396,\n          \"height\": 329,\n          \"sticker\": { \"type\": \"rockInRotterdamLightning\" },\n          \"id\": \"1df87336-c087-4d5f-a6be-82657dbc7173\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #141414; text-transform: uppercase\\\">Next Story</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 37,\n          \"id\": \"9ba68eec-c8d6-4e5d-a61e-58adfc207bbf\",\n          \"x\": 58,\n          \"y\": 3,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 58,\n          \"y\": 476,\n          \"id\": \"c39a94a1-97f0-4793-a66e-3bcb289e1df0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fjalla One\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -508,\n              \"tAsc\": 1810,\n              \"tDes\": -458,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 508,\n              \"xH\": 1377,\n              \"capH\": 1708,\n              \"yMin\": -458,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -508,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #141414; text-transform: uppercase\\\">Rob la Miro</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 63,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #141414\\\">An Actor With A Thousand Faces</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 276,\n          \"height\": 51,\n          \"type\": \"text\",\n          \"id\": \"a90d2d23-1339-49d8-93a8-396a3515b05b\",\n          \"x\": 58,\n          \"y\": 535\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"785cc57a-677b-4ddb-9ca7-45918386fff4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1df87336-c087-4d5f-a6be-82657dbc7173\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6462279c-56f4-4988-be15-e5387d151c0a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"af563aaa-09d3-405f-8da5-f4d30612e06c\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b77ce411-935c-4e99-856f-3e24e7f2a744\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sangria-artichoke/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/sangria-artichoke/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'sangria-artichoke',\n  creationDate: '2021-06-28T00:00:00.000Z',\n  title: _x('Trendy Winter Veggie', 'template name', 'web-stories'),\n  tags: [\n    _x('Food', 'template keyword', 'web-stories'),\n    _x('Healthy', 'template keyword', 'web-stories'),\n    _x('Recipe', 'template keyword', 'web-stories'),\n    _x('How-To', 'template keyword', 'web-stories'),\n    _x('Earthy', 'template keyword', 'web-stories'),\n    _x('Vegan', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Jewel Green', 'color', 'web-stories'),\n      color: '#0e662a',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Tabasco Red', 'color', 'web-stories'),\n      color: '#9f240f',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Yukon Sky Gray', 'color', 'web-stories'),\n      color: '#dfe3e4',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'From veggies, with love. This template’s natural green color palette and lively typography will inspire your audience to cook a healthy meal today.',\n    'web-stories'\n  ),\n  vertical: _x('Cooking', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/sangria-artichoke/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sangria-artichoke/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e2df66d3-fd43-4003-901d-8c4f2f3dd217\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 223, \"g\": 227, \"b\": 228 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 224, \"g\": 229, \"b\": 232, \"a\": 0 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -64.5,\n          \"width\": 412,\n          \"height\": 747,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"23498e51-3ddf-4b01-8c82-d10495733ae8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#183a15\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page01_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page01_bg\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -5,\n          \"y\": 198,\n          \"width\": 422,\n          \"height\": 749,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2e6f0229-1e25-4fdb-823d-e8e443d14a6e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Sangria Artichoke</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 48,\n          \"y\": 16,\n          \"width\": 298,\n          \"height\": 132,\n          \"id\": \"2987c930-d96f-4c50-b23c-0192e97413bc\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 136,\n          \"id\": \"4726ca5d-9ab0-4cf9-8d7b-210c3da4c2d9\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">The Trendy Winter Veggie</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 298,\n          \"height\": 100,\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 264,\n          \"id\": \"44ee3a4b-ac3b-4c39-adbf-58554f991b59\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #9f240f; letter-spacing: 0.04em; text-transform: uppercase\\\">Billy Rogers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 298,\n          \"height\": 22\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 225,\n          \"width\": 182,\n          \"height\": 11,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"b08b7a4a-51d3-4c28-ac19-c25865620ceb\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 223, \"g\": 227, \"b\": 228 } },\n      \"type\": \"page\",\n      \"id\": \"dad018db-27b9-4813-9821-3e5bcba833f5\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c68c0246-0102-4823-91a1-99eba95a3e01\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -533,\n          \"y\": -69,\n          \"width\": 1458,\n          \"height\": 834,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"video\",\n          \"id\": \"efd264b4-7318-4218-9d2d-3152e1714d24\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-05-14T11:04:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page02_bg_video.mp4\",\n            \"width\": 330,\n            \"height\": 185,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page02_bg_video_poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 21,\n            \"lengthFormatted\": \"0:21\",\n            \"alt\": \"page02_bg_video\",\n            \"isMuted\": true,\n            \"isOptimized\": true,\n            \"baseColor\": \"#b5b2b3\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": null,\n          \"loop\": false\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 231,\n          \"width\": 412,\n          \"height\": 444,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d4d24bc1-ed0c-432f-a216-243433a8a200\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f9fcf4\\\">One of the biggest winter veggie trends this year has been the Sangria artichoke. Let’s see why...</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 364,\n          \"width\": 337,\n          \"height\": 252,\n          \"id\": \"b6332c5b-6b1b-408e-89a5-0914d25d2fe2\",\n          \"marginOffset\": -7,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 324,\n          \"id\": \"57eee62e-33cf-45fe-b1ed-f74d7a2f89d0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9fcf4\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 337,\n          \"height\": 50,\n          \"marginOffset\": -7\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 28, \"g\": 98, \"b\": 50 } },\n      \"type\": \"page\",\n      \"id\": \"cf5733d2-959d-4e81-bcc3-9e4e32e111a8\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c68c0246-0102-4823-91a1-99eba95a3e01\"\n      },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -18,\n          \"y\": -279,\n          \"width\": 540,\n          \"height\": 959,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"f880b5e6-a894-4fa0-8832-94182a7a77a2\",\n          \"scale\": 117,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:43:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page03_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page03_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e0da\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 342,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e1303605-ab23-4842-a012-2714bcdebbd8\",\n          \"x\": 0,\n          \"y\": 333\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 249, \"g\": 252, \"b\": 244, \"a\": 0.9 }\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 247,\n          \"width\": 412,\n          \"height\": 114,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e6911ff4-a061-4254-b2c0-33ad3875a99b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #117932\\\">The Sangria Artichoke</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 266,\n          \"height\": 32,\n          \"marginOffset\": -7,\n          \"id\": \"b3ca9afa-94ae-43ee-8910-ceccc59be427\",\n          \"x\": 73,\n          \"y\": 292\n        },\n        {\n          \"x\": 48,\n          \"y\": 452,\n          \"id\": \"3c6aad2b-c150-47c6-b124-edaebc1f9d43\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Sangria artichokes have deep purple meaty leaves. It has a nutty flavor and is perfect when steamed!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 320,\n          \"height\": 112,\n          \"marginOffset\": -7\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9e692bf4-4600-4449-86bd-a231a4e4bbec\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"f880b5e6-a894-4fa0-8832-94182a7a77a2\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 220, \"g\": 236, \"b\": 195 } },\n      \"type\": \"page\",\n      \"id\": \"aac6d458-24d5-4d3a-94bf-40c9f079e3ac\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"3fb2b819-948c-4b59-8dd8-9c54173aa4af\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c1d5a1f8-3b3d-45d9-a701-b523deae57ad\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"baseColor\": \"#ffffff\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page04_bg.png\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page04_bg\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -15,\n          \"y\": -59,\n          \"width\": 442,\n          \"height\": 783,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"abfdaba8-fd9c-40d4-a87b-ee6c0c73cb1d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #f9fcf4\\\">100% yummy and healthy without the calories to weigh you down.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 337,\n          \"height\": 179,\n          \"marginOffset\": -7,\n          \"id\": \"e3785666-3eaf-4e35-9035-eee296fb5512\",\n          \"x\": 48,\n          \"y\": 204,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #f9fcf4\\\">\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 337,\n          \"height\": 50,\n          \"marginOffset\": -7,\n          \"id\": \"07e6b9d0-c174-444d-be0a-159a9e03fc22\",\n          \"x\": 48,\n          \"y\": 164\n        },\n        {\n          \"x\": 208,\n          \"y\": 538,\n          \"id\": \"b82ee0fe-d790-43b7-bcdd-62b4b432ef96\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #f9fcf4\\\">Health benefits</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 136,\n          \"height\": 25,\n          \"marginOffset\": -7\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 260,\n          \"y\": 559,\n          \"width\": 100,\n          \"height\": 26,\n          \"sticker\": { \"type\": \"scribbledArrow\" },\n          \"id\": \"fb6c5e85-f9c2-4a76-a92f-f4681d21e96a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7a417151-21f5-4fc2-a4a9-00a8299f2f69\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b82ee0fe-d790-43b7-bcdd-62b4b432ef96\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a1ef1794-16b0-4bc8-ad20-5cfbe77c3da3\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"fb6c5e85-f9c2-4a76-a92f-f4681d21e96a\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 17, \"g\": 121, \"b\": 50 } },\n      \"type\": \"page\",\n      \"id\": \"38e2963d-c2cb-43ee-82cf-42e10bdf1917\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"825768f3-a4fb-4135-bc4f-dcbe35485830\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Veggie Facts:</span>\\n<span style=\\\"font-weight: 700; color: #9f240f\\\">Sangria Artichoke</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 61,\n          \"marginOffset\": -7,\n          \"id\": \"8bdc65c6-aac5-4cf2-9953-e95370f5ddd7\",\n          \"x\": 48,\n          \"y\": 21,\n          \"groupId\": \"0c7587e4-b29a-4248-99b4-fab31b028b27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 51,\n          \"y\": 79,\n          \"width\": 240,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"scribbledUnderline2\" },\n          \"id\": \"b64c7a0d-8143-430f-be51-6d4e5cf31270\",\n          \"groupId\": \"0c7587e4-b29a-4248-99b4-fab31b028b27\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 88,\n          \"y\": 179,\n          \"width\": 60,\n          \"height\": 59,\n          \"sticker\": { \"type\": \"pills\" },\n          \"id\": \"d6808d8c-7294-45c1-8e17-24f7c1911a85\",\n          \"groupId\": \"e8ba7b50-b96d-47d1-853d-8a72b1f12ade\"\n        },\n        {\n          \"x\": 222,\n          \"y\": 159,\n          \"id\": \"0e49bca8-9230-4120-a899-3bc9c5c6646d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">01</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">25% daily serving of Vitamin C</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 98,\n          \"marginOffset\": -7,\n          \"groupId\": \"e8ba7b50-b96d-47d1-853d-8a72b1f12ade\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 90,\n          \"y\": 363,\n          \"width\": 60,\n          \"height\": 39,\n          \"sticker\": { \"type\": \"openPill\" },\n          \"id\": \"85d298dc-bc94-4123-a3a6-9d39cc173cda\",\n          \"groupId\": \"245b1fb9-bff9-4c1c-9fc5-3bab19d7be63\"\n        },\n        {\n          \"x\": 222,\n          \"y\": 342,\n          \"id\": \"c773c4df-e7cc-4ffa-873b-39f567edc037\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">02</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">Chock full of iron</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 91,\n          \"height\": 79,\n          \"marginOffset\": -7,\n          \"groupId\": \"245b1fb9-bff9-4c1c-9fc5-3bab19d7be63\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 97,\n          \"y\": 515,\n          \"width\": 54,\n          \"height\": 61,\n          \"sticker\": { \"type\": \"pillBox\" },\n          \"id\": \"f1605c9e-b541-4c77-8747-69a01adbc6d2\",\n          \"groupId\": \"cbe20a8f-4f95-4896-8db1-7f47c603f35e\"\n        },\n        {\n          \"x\": 222,\n          \"y\": 508,\n          \"id\": \"a7f6d2e7-0b40-40b5-a8ef-4372f1ed0ed5\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">03</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">Loaded with B12</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 93,\n          \"height\": 72,\n          \"marginOffset\": -7,\n          \"groupId\": \"cbe20a8f-4f95-4896-8db1-7f47c603f35e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fd22d612-2240-496a-b782-9d140582c592\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b64c7a0d-8143-430f-be51-6d4e5cf31270\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"998ac4ad-cf27-4798-ae33-6018d856e73e\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"d6808d8c-7294-45c1-8e17-24f7c1911a85\"],\n          \"scale\": 0.1,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"807b07e2-0088-458f-a7ec-0497a2333103\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"85d298dc-bc94-4123-a3a6-9d39cc173cda\"],\n          \"scale\": 0.1,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"ed451ef2-2c81-4c3c-babe-5ba6627ceeaf\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"f1605c9e-b541-4c77-8747-69a01adbc6d2\"],\n          \"scale\": 0.1,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"850e73eb-1f10-4273-a865-45bf67e1012d\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"e8ba7b50-b96d-47d1-853d-8a72b1f12ade\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"245b1fb9-bff9-4c1c-9fc5-3bab19d7be63\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"cbe20a8f-4f95-4896-8db1-7f47c603f35e\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0c7587e4-b29a-4248-99b4-fab31b028b27\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -51,\n          \"y\": -180,\n          \"width\": 517,\n          \"height\": 920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"561fcf03-a366-4365-bf93-d96db733f440\",\n          \"scale\": 121,\n          \"focalX\": 52.4077291322039,\n          \"focalY\": 52.324380147130036,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:42:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page06_07_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page06_07_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#373a31\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 243, \"g\": 244, \"b\": 236, \"a\": 0.9 }\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 235,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c0dca19c-899b-481c-88c2-e474e68c2881\",\n          \"x\": 0,\n          \"y\": 107\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Sangria Artichoke, Mint, Lemon and Rice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 245,\n          \"height\": 96,\n          \"marginOffset\": -7,\n          \"id\": \"7f7945bb-7f5c-479f-a409-a07361bd24eb\",\n          \"x\": 87,\n          \"y\": 132\n        },\n        {\n          \"x\": 87,\n          \"y\": 245,\n          \"id\": \"ae9f6d78-6474-4ba3-97e3-020bbf4b041e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0e662a\\\">A fresh summer salad but for winter. Comfort food at its best.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 245,\n          \"height\": 71,\n          \"marginOffset\": -7\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 24,\n          \"y\": 183,\n          \"width\": 80,\n          \"height\": 294,\n          \"sticker\": { \"type\": \"curvedArrow\" },\n          \"id\": \"5daa82b0-3e7e-407c-95a8-dabc4151fa46\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 156,\n          \"height\": 9,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"4f0b88fd-3e83-4faf-878e-a356187b1ac3\",\n          \"x\": 84,\n          \"y\": 223\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7a263d6e-531a-4228-af60-3752f7b7cfcb\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"561fcf03-a366-4365-bf93-d96db733f440\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6a4411d5-77fe-4b3b-a53c-126453312518\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5daa82b0-3e7e-407c-95a8-dabc4151fa46\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"046c764c-5f2d-46b5-a6ae-9620f716c565\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c6bd2a09-64be-4cec-8302-f8b0fd89f3fc\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -51,\n          \"y\": -182,\n          \"width\": 517,\n          \"height\": 920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"561fcf03-a366-4365-bf93-d96db733f440\",\n          \"scale\": 112,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:42:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page06_07_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page06_07_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#373a31\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"width\": 436,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3aedbe49-6d7f-47f7-8c12-9314b76dc583\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 149,\n          \"id\": \"6913fc44-6059-4c20-89db-37a67bb247fe\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 19, \"g\": 28, \"b\": 29 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 412,\n          \"height\": 526,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Prep Time: </span><span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">20 Min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 141,\n          \"height\": 18,\n          \"marginOffset\": -2.3999999999999986,\n          \"id\": \"22c34e70-ba26-403c-b50a-9ed378497cac\",\n          \"x\": 48,\n          \"y\": 72,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 210,\n          \"id\": \"59bb33e9-b835-4479-97e9-33def6d23982\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">1 ½ cups chicken stock</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">2 tsp olive oil</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">1 onion</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">2 garlic cloves</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">1 cup rice</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">2 tsp salt</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">1/4 tsp curry powder</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">12 olives</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">2 artichoke hearts</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">1 celery stalk</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 315,\n          \"marginOffset\": -7,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 219,\n          \"y\": 72,\n          \"id\": \"d4d7f45d-bb18-44d4-92f3-94f486df9c7f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Cook Time: </span><span style=\\\"font-weight: 800; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">20 Min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 18,\n          \"marginOffset\": -2.5999999999999996,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 161,\n          \"id\": \"56b330c1-57cd-46df-8c1b-ba179193030d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.28em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 20,\n          \"marginOffset\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 181,\n          \"width\": 156,\n          \"height\": 9,\n          \"sticker\": { \"type\": \"scribbledUnderlineWhite\" },\n          \"id\": \"66b0b5e3-1b7d-4f20-9520-a91e91c0d9d9\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8ec39960-052c-4b46-87ca-75a5e71552a8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"66b0b5e3-1b7d-4f20-9520-a91e91c0d9d9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"d389ae98-2ea8-4a3c-af2b-c5f72a926aae\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"561fcf03-a366-4365-bf93-d96db733f440\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"4ae768a5-c989-481d-9bb9-90882cb3b25f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"1c7cd6f4-2198-4583-a226-90450a94ced1\"\n      },\n      \"pageTemplateType\": \"list\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 11,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c5072c40-b884-4cff-9544-4c830a6b8f68\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:43:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page08_image01.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page08_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#b49e81\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -147,\n          \"y\": -90,\n          \"width\": 598,\n          \"height\": 392,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d64bc29e-ebbc-4a03-8e27-4557583388b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Step 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 42,\n          \"marginOffset\": -3,\n          \"type\": \"text\",\n          \"id\": \"4ec71f7a-5ebf-494a-b518-bbf7085a32ef\",\n          \"x\": 48,\n          \"y\": 352,\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Make the rice. </span><span style=\\\"font-weight: 400; color: #0e662a\\\">Bring stock to a simmer. Heat oil in a saucepan over medium heat. Add onion and garlic. Cook until onion is translucent. Add rice, salt, and curry powder. Cook, stirring, 1 minute.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 152,\n          \"marginOffset\": -7,\n          \"id\": \"2370e8d3-fb8a-4ee6-89d6-403d8ec53c7c\",\n          \"x\": 48,\n          \"y\": 420\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 84,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"86b2efc2-8920-4bb5-b657-a8b8658a6c32\",\n          \"x\": 48,\n          \"y\": 393\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f6bd1448-00e5-4f0d-a324-2da0e232c622\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"86b2efc2-8920-4bb5-b657-a8b8658a6c32\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a98aeb61-da6e-4a8c-a464-a263035df156\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"4ec71f7a-5ebf-494a-b518-bbf7085a32ef\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"d5efd352-ad61-42d8-8dc2-7f942d429e76\",\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b9728f3f-3507-4f16-b3e4-5d5996609e07\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Step 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 42,\n          \"marginOffset\": -3,\n          \"id\": \"80e39c41-9a4a-4e8b-a46d-03ec93db09c6\",\n          \"x\": 48,\n          \"y\": 352,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Make the artichoke. </span><span style=\\\"font-weight: 400; color: #0e662a\\\">Prepare a large pot with an inch of water. Add garlic and bay leaf. Cut off and discard the top 1/2 inch and bottom 2 inches of the artichokes. Place in pot and cook for 20 min.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 131,\n          \"marginOffset\": -7,\n          \"id\": \"90d35d01-f4b8-458e-bf9b-2f9db9383518\",\n          \"x\": 48,\n          \"y\": 420,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:42:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page09_image01.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page09_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#4c5338\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -60,\n          \"y\": -60,\n          \"width\": 537,\n          \"height\": 362,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5610564a-425f-468f-a28f-e34c94fcc105\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 84,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"69c35143-88ea-4398-8ed5-a2e11767ab7d\",\n          \"x\": 48,\n          \"y\": 393\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6351f05d-a357-47a3-a314-5975b55dc739\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"80e39c41-9a4a-4e8b-a46d-03ec93db09c6\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"69c35143-88ea-4398-8ed5-a2e11767ab7d\"],\n          \"id\": \"44bc9464-ebe5-4c01-8259-dd728f9c2252\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"063b89c5-2c8a-496a-a091-e8ad604cf903\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3ea5da83-32db-46ad-a072-ed115a26f985\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Step 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 42,\n          \"marginOffset\": -3,\n          \"id\": \"61f1a668-4b5f-494f-b81e-685b613f4c3f\",\n          \"x\": 48,\n          \"y\": 352,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0e662a\\\">Drain and let cool. Trim off the exterior leaves, leaving the tender artichoke heart.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 71,\n          \"marginOffset\": -7,\n          \"id\": \"8134ea36-de52-45a3-96d5-923c117e18a6\",\n          \"x\": 48,\n          \"y\": 420,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 120,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#dcd3c6\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page10_image01.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"id\": 0,\n            \"alt\": \"page10_image01\",\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -65,\n          \"y\": -80,\n          \"width\": 528,\n          \"height\": 383,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"50fca2f2-21e5-45ce-ba28-e56dc4078ad6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 84,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"327bb2d0-2106-45d8-b0d3-c17e242f3b52\",\n          \"x\": 48,\n          \"y\": 393\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"15c74038-1812-4644-ad87-37169694f44c\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"61f1a668-4b5f-494f-b81e-685b613f4c3f\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"327bb2d0-2106-45d8-b0d3-c17e242f3b52\"],\n          \"id\": \"28c47b96-8387-4d6a-9fa3-bf978334745e\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"687277fc-3cdc-434a-bbe7-f2d7b26af4e7\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"409d290b-6ef9-4965-8e2e-ff8a92878490\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Step 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 146,\n          \"height\": 42,\n          \"marginOffset\": -3,\n          \"id\": \"e2f39dba-9816-4fde-b636-86a0b45bc035\",\n          \"x\": 48,\n          \"y\": 352,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #0e662a\\\">Mix artichoke heart with top and top with apricot and dill. Serve cold or at room temperature.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 71,\n          \"marginOffset\": -7,\n          \"id\": \"d01ce0b5-9f28-4cb7-b8e5-02ceaaf13cdb\",\n          \"x\": 48,\n          \"y\": 420,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:42:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page11_image01.jpg\",\n            \"width\": 330,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"apage11_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#c9c4b6\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -128,\n          \"y\": -60,\n          \"width\": 604,\n          \"height\": 359,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"933e429d-f969-438b-be3a-d888234d7c07\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 84,\n          \"height\": 5,\n          \"sticker\": { \"type\": \"scribbledUnderline\" },\n          \"id\": \"f83260cc-17af-4de7-a5cd-a8343e4fe574\",\n          \"x\": 48,\n          \"y\": 393\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"75a190c7-24ab-4004-b6b4-1f180706c37d\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e2f39dba-9816-4fde-b636-86a0b45bc035\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"targets\": [\"f83260cc-17af-4de7-a5cd-a8343e4fe574\"],\n          \"id\": \"ba2a07bd-33f5-44f6-bfbf-4848ae206f20\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 249, \"g\": 252, \"b\": 244 } },\n      \"type\": \"page\",\n      \"id\": \"941853ce-be33-4db1-853b-44ec764b2033\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"70fb4757-3714-460e-b409-980c98b72249\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a\\\">Recipes for other</span>\\n<span style=\\\"font-weight: 700; color: #9f240f\\\">Trendy Veggies</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 61,\n          \"marginOffset\": -7,\n          \"id\": \"8d7b9fcf-ee06-4e59-9d57-ca5f5b53c24b\",\n          \"x\": 48,\n          \"y\": 21,\n          \"groupId\": \"069d6c4e-0eb1-40dd-855c-c333faa316cf\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 240,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"scribbledUnderline2\" },\n          \"id\": \"f8aaf895-1334-4a6a-a05c-e95d00cf229b\",\n          \"x\": 51,\n          \"y\": 79,\n          \"groupId\": \"069d6c4e-0eb1-40dd-855c-c333faa316cf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">01</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">Sunchoke Salad with Raisins</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 109,\n          \"marginOffset\": -7,\n          \"id\": \"6f355aac-02a4-4976-b3bd-8cff973f3ca0\",\n          \"x\": 48,\n          \"y\": 138,\n          \"groupId\": \"5020d16e-2d35-4d34-a6ce-5873262402f4\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 207,\n          \"y\": 135,\n          \"width\": 154,\n          \"height\": 115,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"19a471db-914b-48f9-a5d1-e468d1a7f8e1\",\n          \"borderRadius\": {\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:44:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page12_image01.jpg\",\n            \"width\": 231,\n            \"height\": 173,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page12_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#464037\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"5020d16e-2d35-4d34-a6ce-5873262402f4\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 311,\n          \"id\": \"40fc78ba-48ee-41a3-ad49-1466ce5d0f2c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">02</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">Fall Squash Stew</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 125,\n          \"height\": 88,\n          \"marginOffset\": -7,\n          \"groupId\": \"ee4d1f7f-3b00-413f-8942-301b7a005675\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 297,\n          \"id\": \"5a5f82ce-f26d-4bf5-9bd3-bcaf7fadd647\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 154,\n          \"height\": 115,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:44:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page12_image02.jpg\",\n            \"width\": 231,\n            \"height\": 173,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page12_image02\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#d5cfc3\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"ee4d1f7f-3b00-413f-8942-301b7a005675\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 462,\n          \"id\": \"633bbd5a-6ddc-41bb-81ab-e5d4012b719b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #0e662a; letter-spacing: 0.01em\\\">03</span>\\n\\n<span style=\\\"color: #0e662a; letter-spacing: 0.01em\\\">Steamed Okra with Tiger Bite Sauce</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 109,\n          \"marginOffset\": -7,\n          \"groupId\": \"b954269c-3d83-45d4-a0d9-0654e5db52b0\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 459,\n          \"id\": \"58060017-8a7b-4c83-a1f3-eda72fabab3e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 154,\n          \"height\": 115,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2,\n            \"locked\": true\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T11:44:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sangria-artichoke/page12_image03.jpg\",\n            \"width\": 231,\n            \"height\": 173,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page12_image03\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#c3ccaf\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"b954269c-3d83-45d4-a0d9-0654e5db52b0\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"83e28a9a-4705-472f-b8a0-be4fdbc6f50c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f8aaf895-1334-4a6a-a05c-e95d00cf229b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3ad8a7a6-fdf3-4c2a-855b-b0f17709a806\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"19a471db-914b-48f9-a5d1-e468d1a7f8e1\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"32358c02-94b7-460d-8e57-291a64f2db4e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5a5f82ce-f26d-4bf5-9bd3-bcaf7fadd647\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d1ba44cd-69e7-4bb1-b088-4a6f7c376c63\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"58060017-8a7b-4c83-a1f3-eda72fabab3e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 252, \"g\": 239, \"b\": 171 } },\n      \"type\": \"page\",\n      \"id\": \"cdd23b86-3e0e-4926-9f81-02ec4e74898d\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"5020d16e-2d35-4d34-a6ce-5873262402f4\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ee4d1f7f-3b00-413f-8942-301b7a005675\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b954269c-3d83-45d4-a0d9-0654e5db52b0\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"069d6c4e-0eb1-40dd-855c-c333faa316cf\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/self-care-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\n// For some reason, the inferred TypeScript type is too narrow here and we have to use\n// file declaration instead of importing directly from `template.json`.\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/self-care-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'self-care-guide',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('Self-care Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Health & Wellness', 'template keyword', 'web-stories'),\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Self Care', 'template keyword', 'web-stories'),\n    _x('Informative', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Studio White', 'color', 'web-stories'),\n      color: '#f5f4ee',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cavernous Gray', 'color', 'web-stories'),\n      color: '#535353',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gold Ochre', 'color', 'web-stories'),\n      color: '#b17417',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cove Blue', 'color', 'web-stories'),\n      color: '#7a87a8',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Velvet Green', 'color', 'web-stories'),\n      color: '#588061',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Olive Garden Green', 'color', 'web-stories'),\n      color: '#878c52',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#ffffff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its natural color palette, this template will let you create uplifting and informative stories about self-care, health and nutrition, meditation, and more.',\n    'web-stories'\n  ),\n  vertical: _x('Health & Wellness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/self-care-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/self-care-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6d9cbd2f-6802-49eb-abd4-dbb3706fe792\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"x\": -177,\n          \"y\": 131,\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"270cd27c-03e7-4f73-82b5-5e72204452e2\",\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"groupId\": \"62bceaac-53fc-435d-bde6-2522f980695c\"\n        },\n        {\n          \"x\": 117,\n          \"y\": -250,\n          \"id\": \"9c7df34e-1209-4a82-a973-20154a455d87\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"groupId\": \"62bceaac-53fc-435d-bde6-2522f980695c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 102, \"g\": 138, \"b\": 110 } },\n          \"type\": \"shape\",\n          \"x\": 160,\n          \"y\": 609,\n          \"width\": 57,\n          \"height\": 9,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0e2c1625-4aac-4476-8b1d-84c9fbfd90b7\",\n          \"groupId\": \"73e659e8-f68a-40fb-8a60-23d007df1b31\"\n        },\n        {\n          \"x\": 216,\n          \"y\": 609,\n          \"id\": \"62fca869-b824-4364-ae38-21932b519f27\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 144, \"g\": 149, \"b\": 97 } },\n          \"type\": \"shape\",\n          \"width\": 57,\n          \"height\": 9,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"73e659e8-f68a-40fb-8a60-23d007df1b31\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 133, \"g\": 144, \"b\": 174 } },\n          \"type\": \"shape\",\n          \"width\": 57,\n          \"height\": 9,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7e7f69f3-472e-42cf-863f-989c27ece528\",\n          \"x\": 104,\n          \"y\": 609,\n          \"groupId\": \"73e659e8-f68a-40fb-8a60-23d007df1b31\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 182, \"g\": 127, \"b\": 44 } },\n          \"type\": \"shape\",\n          \"width\": 57,\n          \"height\": 9,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e13185ca-4f74-4957-b149-6a0939ee4950\",\n          \"x\": 47,\n          \"y\": 609,\n          \"groupId\": \"73e659e8-f68a-40fb-8a60-23d007df1b31\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 246,\n          \"y\": 259,\n          \"width\": 119,\n          \"height\": 94,\n          \"scale\": 106,\n          \"focalX\": 52.63598381784652,\n          \"focalY\": 58.13282970752775,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"31dab9ec-0e5f-4d20-a77a-e883fc2e74d1\",\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:17:32\",\n            \"baseColor\": \"#ccc5bf\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page01_image02.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Set of natural toiletries on marble table in bathroom\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 188,\n          \"height\": 299,\n          \"scale\": 100,\n          \"focalX\": 48.35961144663132,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 60,\n            \"topRight\": 40,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"a4ceb8ab-764a-4611-8c2a-1585fde0329b\",\n          \"x\": 47,\n          \"y\": -10,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:16:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page01_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Women Doing Yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#cbc5be\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 48,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">Taking Care</span>\\n<span style=\\\"font-weight: 300; color: #272727\\\">Of Yourself</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 404,\n          \"width\": 294,\n          \"height\": 131,\n          \"id\": \"eaf87cb8-e9e2-4bfc-8880-dcecd7fd1ddf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">With Monique Robbins</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 536,\n          \"width\": 175,\n          \"height\": 19,\n          \"id\": \"73929614-83f4-446e-883c-376f0fbdb2be\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"e2d8f340-b4d4-4fd9-9858-6db7e5a90ad8\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"62bceaac-53fc-435d-bde6-2522f980695c\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"73e659e8-f68a-40fb-8a60-23d007df1b31\": {\n          \"name\": \"Bar\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"591a4915-cda1-4c4a-b51d-d293dd21ebae\",\n          \"scale\": 120,\n          \"focalX\": 38.46405480295566,\n          \"focalY\": 41.67692939244662,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:19:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page02_bg.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman doing yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true,\n            \"baseColor\": \"#dcd4d5\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 457,\n          \"height\": 666,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 } }\n          },\n          \"id\": \"3869addd-d01a-41d8-a631-36ed17b0fd34\",\n          \"x\": -177,\n          \"y\": 39,\n          \"groupId\": \"6c26938c-3d28-4658-afca-2ac6da8df519\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 151,\n          \"height\": 151,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.2 } }\n          },\n          \"id\": \"01881a70-d4c4-4bb6-8714-1cdb19159ad1\",\n          \"x\": 29,\n          \"y\": -36,\n          \"groupId\": \"6c26938c-3d28-4658-afca-2ac6da8df519\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 83, \"g\": 83, \"b\": 83 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 43,\n            \"vertical\": 50\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">We’re probably working longer hours from home now, which means we’re tied to our kitchen tables and home offices. Here are some tips to keeping that pep in your step.</span>\",\n          \"borderRadius\": {\n            \"locked\": false,\n            \"topLeft\": 40,\n            \"topRight\": 80,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 60\n          },\n          \"width\": 353,\n          \"height\": 222,\n          \"id\": \"c2d0f8f7-b86a-4e92-b421-635887ec7869\",\n          \"x\": 29,\n          \"y\": 414\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5092e3ec-27fd-4715-b07f-7db0ed247ea5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3869addd-d01a-41d8-a631-36ed17b0fd34\"],\n          \"duration\": 4000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"996491f9-641a-4d16-ba77-41f132bfa756\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"01881a70-d4c4-4bb6-8714-1cdb19159ad1\"],\n          \"duration\": 4000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"44838b6e-f895-492b-9094-7dfecb26417c\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"591a4915-cda1-4c4a-b51d-d293dd21ebae\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 6000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"be6ace0d-7343-4c74-ac9f-20bd185a9e25\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c67a5af1-7680-462a-884e-06d337d31515\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"6c26938c-3d28-4658-afca-2ac6da8df519\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b6b5d62e-4bd8-4ea7-83b8-911e93c4e38c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"8b4eb9cf-865f-441b-9e4d-8a3111d7b552\",\n          \"x\": -153,\n          \"y\": 131,\n          \"groupId\": \"16b6fef8-ad77-48a6-a98f-2e898b1aaff1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 151,\n          \"height\": 151,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"85ec672f-cc6d-48f5-9198-dddee8abd4fb\",\n          \"x\": 229,\n          \"y\": 448,\n          \"groupId\": \"16b6fef8-ad77-48a6-a98f-2e898b1aaff1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 177, \"g\": 116, \"b\": 23 } },\n          \"type\": \"shape\",\n          \"x\": 47,\n          \"y\": 354,\n          \"width\": 43,\n          \"height\": 7,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ee50414e-7e2c-4518-9899-85d4d2b8c2d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 305,\n          \"height\": 485,\n          \"scale\": 114,\n          \"focalX\": 54.5806486773076,\n          \"focalY\": 52.64222727812253,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 60,\n            \"topRight\": 40,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"74e1254b-bc03-4b9d-a351-44972f1f5324\",\n          \"x\": 47,\n          \"y\": -130,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:20:30\",\n            \"baseColor\": \"#979082\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page03_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman doing yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #272727\\\">Exercise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 43,\n          \"id\": \"0fd3cc0e-a22b-49cb-94ae-101d68438d57\",\n          \"x\": 47,\n          \"y\": 439\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">Even a light yoga session will counteract a lot of sitting during your work day.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 79,\n          \"id\": \"08cf8b1d-35e8-412a-8db9-c657d0ccf92e\",\n          \"x\": 47,\n          \"y\": 489\n        },\n        {\n          \"x\": 47,\n          \"y\": 401,\n          \"id\": \"c694ec71-8620-4c06-991c-5868ba576dbd\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #272727; text-transform: uppercase\\\">Tip 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 165,\n          \"height\": 17\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"89a7bbe2-803b-45b4-89ce-d5ec01205fab\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ee50414e-7e2c-4518-9899-85d4d2b8c2d3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5df909af-366e-4831-8696-d7bf27d5e06b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"74e1254b-bc03-4b9d-a351-44972f1f5324\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"39c1fbdf-fef8-4e48-bdf9-393c2a2d8e8a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8b4eb9cf-865f-441b-9e4d-8a3111d7b552\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a50d1562-569a-421b-bbe2-2f592d64fbcd\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"85ec672f-cc6d-48f5-9198-dddee8abd4fb\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"f30d7b9f-80f0-43b3-82ec-4ca9efe39f0c\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"16b6fef8-ad77-48a6-a98f-2e898b1aaff1\": {\n          \"name\": \"Background\",\n          \"isLocked\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"3a36dfd2-3442-4f70-82e1-7f383b0a791f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"f29059fe-cbf9-49bb-90de-c58f85326dc9\",\n          \"x\": 110,\n          \"y\": 131,\n          \"groupId\": \"beb7e768-d23a-48b2-9780-300e2b6bdfeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"c01b6a06-08f3-4381-be34-f42db440d26c\",\n          \"x\": 117,\n          \"y\": -250,\n          \"groupId\": \"beb7e768-d23a-48b2-9780-300e2b6bdfeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 177, \"g\": 116, \"b\": 23 } },\n          \"type\": \"shape\",\n          \"width\": 353,\n          \"height\": 144,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 80,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 60,\n            \"locked\": false\n          },\n          \"id\": \"64d31899-54e8-4e0d-bcb3-9469a6283a48\",\n          \"x\": 29,\n          \"y\": -183,\n          \"groupId\": \"beb7e768-d23a-48b2-9780-300e2b6bdfeb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 57,\n          \"y\": 290,\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 100,\n          \"focalX\": 50.039649654465144,\n          \"focalY\": 38.4735272468917,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c9107a3c-b492-41be-ac0d-758504fd36ad\",\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:19:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page02_bg.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman doing yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#9a9692\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"a9f1ec9d-9ba6-4e10-8e0a-4eafc385d937\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Splurge</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 17,\n          \"id\": \"7d978541-31ae-49b6-9da9-80bce2fbbccd\",\n          \"x\": 223,\n          \"y\": 317,\n          \"groupId\": \"a9f1ec9d-9ba6-4e10-8e0a-4eafc385d937\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 342,\n          \"id\": \"bd127e29-8544-4966-9c46-abccfdf8ea6a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Equinox</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 19,\n          \"groupId\": \"a9f1ec9d-9ba6-4e10-8e0a-4eafc385d937\"\n        },\n        {\n          \"x\": 57,\n          \"y\": 446,\n          \"id\": \"604134a1-d8e8-4f30-b4e0-19febd833791\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 105,\n          \"focalX\": 52.5841722405033,\n          \"focalY\": 53.21674389808967,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:21:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page04_image02.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman doing yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#cbc5be\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"04546939-096c-4eab-8b75-be91b5743753\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 455,\n          \"id\": \"33778ea4-a7d6-4885-afd0-e378049b1a9e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Save</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 17,\n          \"groupId\": \"04546939-096c-4eab-8b75-be91b5743753\"\n        },\n        {\n          \"x\": 222,\n          \"y\": 481,\n          \"id\": \"d0946301-9eea-4de3-8e32-61cf1b5ecb9d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Jumprope at your local park or try a Youtube series</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 64,\n          \"groupId\": \"04546939-096c-4eab-8b75-be91b5743753\"\n        },\n        {\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"cae57128-b8d9-4f3c-a0a1-cb93d7f3c9de\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Best</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Exercise</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Options</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">In NYC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 218,\n          \"height\": 164\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"333bbe00-9273-48b4-882f-501b9ff8a4c9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bd127e29-8544-4966-9c46-abccfdf8ea6a\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3f0ee10c-5641-4431-8ef6-b11d4ed28f6f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d0946301-9eea-4de3-8e32-61cf1b5ecb9d\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 94, \"g\": 86, \"b\": 74 } },\n      \"type\": \"page\",\n      \"id\": \"dd8e448d-2525-43a2-a4b8-3e481eab3e8a\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"beb7e768-d23a-48b2-9780-300e2b6bdfeb\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"a9f1ec9d-9ba6-4e10-8e0a-4eafc385d937\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"04546939-096c-4eab-8b75-be91b5743753\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a83fcad0-cf02-49cb-acee-d9f74b28dd99\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"6fa5bcc1-f3d8-4ef1-aab6-31d3daff5e06\",\n          \"x\": -153,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"e0c4d7e9-5997-4826-a740-144a39ad5cb6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 151,\n          \"height\": 151,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"39655dcb-c49f-4428-a1b7-b6b55a89a0ee\",\n          \"x\": 229,\n          \"y\": 448,\n          \"type\": \"shape\",\n          \"groupId\": \"e0c4d7e9-5997-4826-a740-144a39ad5cb6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 122, \"g\": 135, \"b\": 168 } },\n          \"x\": 47,\n          \"y\": 355,\n          \"width\": 43,\n          \"height\": 7,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f5dae377-1d10-48f8-8b70-8a7f9dbea6d9\",\n          \"type\": \"shape\",\n          \"groupId\": \"e0c4d7e9-5997-4826-a740-144a39ad5cb6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 305,\n          \"height\": 485,\n          \"scale\": 183,\n          \"focalX\": 50,\n          \"focalY\": 50.36841205786088,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 60,\n            \"topRight\": 40,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"32c61414-e9cc-45ca-8a1b-b6c4903d474e\",\n          \"x\": 47,\n          \"y\": -130,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:23:49\",\n            \"baseColor\": \"#484944\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page05_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman with afro hair, at home\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #272727\\\">Sleep More</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 43,\n          \"id\": \"a6c52001-a70d-4d54-9fd5-5a2a4d29a676\",\n          \"x\": 47,\n          \"y\": 439,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">Are you getting at least 8 hours (or more) of sleep a night? Tracking sleep can definitely help you figure out.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 108,\n          \"id\": \"a946962e-b0ae-4b08-9cf6-28547453f3cc\",\n          \"x\": 47,\n          \"y\": 489,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 401,\n          \"id\": \"faa16b91-1010-403e-a964-a1ea9cfc8070\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #272727; text-transform: uppercase\\\">Tip 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 165,\n          \"height\": 17,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8b2b13bc-6d7b-4102-a791-4ca487be30dc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"32c61414-e9cc-45ca-8a1b-b6c4903d474e\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6a315e76-b184-485f-9c7a-237db72a78d0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f5dae377-1d10-48f8-8b70-8a7f9dbea6d9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3a81484c-1708-4aa0-a162-e3c239c2fd39\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6fa5bcc1-f3d8-4ef1-aab6-31d3daff5e06\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"80cb1584-55d5-4515-8ec7-e5248cc97ca5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"39655dcb-c49f-4428-a1b7-b6b55a89a0ee\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"d896de97-47c6-4509-8358-eba27f168b06\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e0c4d7e9-5997-4826-a740-144a39ad5cb6\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ee8d2260-9509-4e24-83f8-72d35ae1a7b2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"dcedd70c-ee4e-490c-90b1-07ca6a17a714\",\n          \"x\": 110,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"02334812-5f7b-4956-a4a1-14739124592a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"5f69e607-0710-4fee-b098-d1041d363a8d\",\n          \"x\": 117,\n          \"y\": -250,\n          \"type\": \"shape\",\n          \"groupId\": \"02334812-5f7b-4956-a4a1-14739124592a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 122, \"g\": 135, \"b\": 168 } },\n          \"width\": 353,\n          \"height\": 144,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 80,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 60,\n            \"locked\": false\n          },\n          \"id\": \"1655cf00-79c7-407b-a8b7-69fa5df30ded\",\n          \"x\": 29,\n          \"y\": -183,\n          \"type\": \"shape\",\n          \"groupId\": \"02334812-5f7b-4956-a4a1-14739124592a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 290,\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 130,\n          \"focalX\": 38.26742500210641,\n          \"focalY\": 50.72760155025695,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1d071fce-9521-4a03-bd4c-8e7f8665acd5\",\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:24:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page06_image02.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Black smartwatch\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#abacaf\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"bb04fb07-bbf4-4ec6-8387-be22d1469465\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Sleep Control</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 37,\n          \"id\": \"87ba7d25-84a3-4a49-a9cc-cb4b5d835e7f\",\n          \"x\": 223,\n          \"y\": 290,\n          \"type\": \"text\",\n          \"groupId\": \"bb04fb07-bbf4-4ec6-8387-be22d1469465\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 225,\n          \"y\": 335,\n          \"id\": \"a26f74d2-d0ce-4415-831f-cb89121a17d8\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Track your sleep and monitor your movement.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 122,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"bb04fb07-bbf4-4ec6-8387-be22d1469465\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 446,\n          \"id\": \"7a353b4d-69be-4127-ab3b-1388223380f9\",\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 115,\n          \"focalX\": 44.38658546428824,\n          \"focalY\": 55.25286176300853,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:26:38\",\n            \"baseColor\": \"#c4ccca\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page06_image01.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Sleeping\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"groupId\": \"f129f23c-2ced-4b86-a615-07e02d99e73b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 455,\n          \"id\": \"100f8d9c-97e4-4e40-ab0a-a44675606f11\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Auto Ring</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 111,\n          \"height\": 17,\n          \"type\": \"text\",\n          \"groupId\": \"f129f23c-2ced-4b86-a615-07e02d99e73b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 222,\n          \"y\": 481,\n          \"id\": \"0a96264e-c16d-46ad-8d31-32078648a8d1\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Track your sleep and your waking productivity.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"f129f23c-2ced-4b86-a615-07e02d99e73b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"eca5be61-27ff-42fa-a2aa-5c65d11491aa\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #f5f4ee\\\">Best</span>\\n<span style=\\\"font-weight: 300; color: #f5f4ee\\\">Mindfulness</span>\\n<span style=\\\"font-weight: 300; color: #f5f4ee\\\">Apps</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 218,\n          \"height\": 126,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"37bd28d3-f9bc-4845-a01b-8f39757253e5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a26f74d2-d0ce-4415-831f-cb89121a17d8\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"fac61333-8b5c-4a59-a390-f9174fe69ed4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0a96264e-c16d-46ad-8d31-32078648a8d1\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 70, \"g\": 76, \"b\": 90 } },\n      \"type\": \"page\",\n      \"id\": \"4edd4335-d94c-4b29-85e0-0b419ec1746c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"02334812-5f7b-4956-a4a1-14739124592a\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"bb04fb07-bbf4-4ec6-8387-be22d1469465\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f129f23c-2ced-4b86-a615-07e02d99e73b\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1009fff2-9375-4627-8fd8-2479d8d0c6f8\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"0dcdf7f8-1c67-4927-b639-1d315728a3d8\",\n          \"x\": -153,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"b2c7d6b8-4d4d-400a-926a-2178760f92f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 151,\n          \"height\": 151,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"21873cb8-7195-4b34-acc9-d150e0fd53da\",\n          \"x\": 229,\n          \"y\": 448,\n          \"type\": \"shape\",\n          \"groupId\": \"b2c7d6b8-4d4d-400a-926a-2178760f92f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 88, \"g\": 128, \"b\": 97 } },\n          \"x\": 47,\n          \"y\": 355,\n          \"width\": 43,\n          \"height\": 7,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7b8cc4d9-0ce8-4132-b1f2-a769b4d174cd\",\n          \"type\": \"shape\",\n          \"groupId\": \"b2c7d6b8-4d4d-400a-926a-2178760f92f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 305,\n          \"height\": 485,\n          \"scale\": 110,\n          \"focalX\": 46.36088430345942,\n          \"focalY\": 54.31472219899403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 60,\n            \"topRight\": 40,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"f9eec32d-0546-4985-aca9-1c5a693b8e15\",\n          \"x\": 47,\n          \"y\": -130,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:28:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page07_image01.jpg\",\n            \"width\": 720,\n            \"height\": 900,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Green and white drink with straw in clear drinking glass\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dddddd\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #272727\\\">Get Your Daily&nbsp;</span>\\n<span style=\\\"color: #272727\\\">Dose Of Vitamins</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 76,\n          \"id\": \"a5d9ab76-e2de-48c9-9278-c816e7de19b9\",\n          \"x\": 47,\n          \"y\": 439,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">B12 and iron are your best friends for energy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 243,\n          \"height\": 51,\n          \"id\": \"cee59c11-98af-4b62-b994-26c835f7261f\",\n          \"x\": 47,\n          \"y\": 523,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 401,\n          \"id\": \"4cac393e-db45-4d98-8d69-148218f4d990\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #272727; text-transform: uppercase\\\">Tip 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 165,\n          \"height\": 17,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9d517124-6748-44ca-9d74-4a62088053f0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f9eec32d-0546-4985-aca9-1c5a693b8e15\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b80f8971-390d-4b59-8c91-c0254d52492c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7b8cc4d9-0ce8-4132-b1f2-a769b4d174cd\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d9a57be7-911d-4bfc-9a9b-6afd64b67b0d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0dcdf7f8-1c67-4927-b639-1d315728a3d8\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"18b4e1d4-6de7-46fd-a906-dbcabac661a3\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"21873cb8-7195-4b34-acc9-d150e0fd53da\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"0df5cf42-08b1-420c-ac21-64d370c404a4\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"b2c7d6b8-4d4d-400a-926a-2178760f92f1\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1097a42c-fd70-4a51-af30-4a0abd529e35\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"f72e3cab-d2e8-41d9-abb0-9ebcad4668e6\",\n          \"x\": 110,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"9ca0d2ac-8785-480f-b68f-9b1f5a66e83f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"24b8f1c4-dc6a-4ad1-8e46-b0d838136d30\",\n          \"x\": 117,\n          \"y\": -250,\n          \"type\": \"shape\",\n          \"groupId\": \"9ca0d2ac-8785-480f-b68f-9b1f5a66e83f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 88, \"g\": 128, \"b\": 97 } },\n          \"width\": 353,\n          \"height\": 144,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 80,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 60,\n            \"locked\": false\n          },\n          \"id\": \"b5e4bf11-878b-4639-acec-9dd17ca50714\",\n          \"x\": 29,\n          \"y\": -183,\n          \"type\": \"shape\",\n          \"groupId\": \"9ca0d2ac-8785-480f-b68f-9b1f5a66e83f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 290,\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 110,\n          \"focalX\": 53.04706375739108,\n          \"focalY\": 52.63235649880511,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c1eff610-cff5-41fb-ab1d-8468d9c8e372\",\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:32:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page08_image01.jpg\",\n            \"width\": 480,\n            \"height\": 464,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Green broccoli\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d9e8e8\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"2dbfbeb5-5d4a-4c0e-8870-368dd3c6a325\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Kale and Broccoli</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 87,\n          \"height\": 37,\n          \"id\": \"703c5e62-ccf4-4942-ada6-f4d073642914\",\n          \"x\": 223,\n          \"y\": 290,\n          \"type\": \"text\",\n          \"groupId\": \"2dbfbeb5-5d4a-4c0e-8870-368dd3c6a325\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 335,\n          \"id\": \"e6cfd7b3-a0b2-4e1a-adaf-8dc35d608181\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">These are your #1 powerhouse greens.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 115,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"2dbfbeb5-5d4a-4c0e-8870-368dd3c6a325\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 446,\n          \"id\": \"0fa903a4-8f1e-4cc3-977b-690bf103b210\",\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 132,\n          \"focalX\": 50,\n          \"focalY\": 48.03530546573858,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:33:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page08_image02.jpg\",\n            \"width\": 480,\n            \"height\": 445,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Tomato Slice \",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b6473f\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"d101ba21-6c8c-40f8-aef1-5c73bfa120d7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 455,\n          \"id\": \"8858ce0a-1566-44ef-a136-8230812ed6ad\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Tomatoes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 97,\n          \"height\": 17,\n          \"type\": \"text\",\n          \"groupId\": \"d101ba21-6c8c-40f8-aef1-5c73bfa120d7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 222,\n          \"y\": 481,\n          \"id\": \"911a0d6f-a200-462c-a692-fa61fce57f21\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Eat them raw or cooked. They’re great for energy.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"d101ba21-6c8c-40f8-aef1-5c73bfa120d7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"b14d1d3b-ffef-4f72-bc91-97f78984d651\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Best</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Vitamin-Loaded</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Food</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">Options</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 240,\n          \"height\": 164,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"80893fdc-ba84-4d88-8236-5ebd61573202\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e6cfd7b3-a0b2-4e1a-adaf-8dc35d608181\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"eafd02c7-0f47-4503-a020-12c2d7a31259\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"911a0d6f-a200-462c-a692-fa61fce57f21\"],\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 66, \"g\": 78, \"b\": 68 } },\n      \"type\": \"page\",\n      \"id\": \"141b9a5e-a39a-44b8-b1f8-3ae52bce927f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9ca0d2ac-8785-480f-b68f-9b1f5a66e83f\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"2dbfbeb5-5d4a-4c0e-8870-368dd3c6a325\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d101ba21-6c8c-40f8-aef1-5c73bfa120d7\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"79eebd97-cfdb-41f7-b5fe-fb6b15bbb481\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"95fdd935-299a-4975-9e56-031d98bceab9\",\n          \"x\": -153,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"2044dc02-f340-4853-95b6-fb981b434a66\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 151,\n          \"height\": 151,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"id\": \"2e72f5a3-4f8d-48a7-a72c-3d8abe0cd969\",\n          \"x\": 229,\n          \"y\": 448,\n          \"type\": \"shape\",\n          \"groupId\": \"2044dc02-f340-4853-95b6-fb981b434a66\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 135, \"g\": 140, \"b\": 82 } },\n          \"x\": 47,\n          \"y\": 355,\n          \"width\": 43,\n          \"height\": 7,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"29050045-f073-4127-9e2d-957e8f7674e2\",\n          \"type\": \"shape\",\n          \"groupId\": \"2044dc02-f340-4853-95b6-fb981b434a66\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 305,\n          \"height\": 413,\n          \"scale\": 106,\n          \"focalX\": 49.929334221855676,\n          \"focalY\": 44.40589361879173,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"68eea36b-c563-43f3-9109-b68b513f2ee7\",\n          \"x\": 47,\n          \"y\": -58,\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:34:39\",\n            \"baseColor\": \"#d4d5d0\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page09_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Clear Glass Bowl with Herbs and Tea\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #272727\\\">Skip the coffee</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 294,\n          \"height\": 43,\n          \"id\": \"bcdda95e-4253-45e2-b2f6-4edf1725a92f\",\n          \"x\": 47,\n          \"y\": 439,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">Coffee is a really short term solution for more energy. Try playing the long game instead.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 256,\n          \"height\": 80,\n          \"id\": \"7e26dfe0-3594-45de-87e7-15da45884e37\",\n          \"x\": 47,\n          \"y\": 489,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": 401,\n          \"id\": \"6d000e40-1624-4ebe-82bc-ee5772773d11\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #272727; text-transform: uppercase\\\">Tip 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 165,\n          \"height\": 17,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b464f992-fcb5-49ef-8dcf-a3c072caaf05\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"68eea36b-c563-43f3-9109-b68b513f2ee7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3eff553e-42f7-4bfb-9f61-beddc6068cb6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"29050045-f073-4127-9e2d-957e8f7674e2\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"153012ef-37f1-41cb-beff-66bf4ca58313\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"95fdd935-299a-4975-9e56-031d98bceab9\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"457ddd67-792b-4f44-b43d-c2ccd089a89c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2e72f5a3-4f8d-48a7-a72c-3d8abe0cd969\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"de3c610c-ae10-49b7-ba37-95a3320d68a7\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2044dc02-f340-4853-95b6-fb981b434a66\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"966395ca-8762-4acd-a6a7-f43656c430e8\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 457,\n          \"height\": 616,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"9355719e-eeaa-4d7e-95e2-5e053b0389a8\",\n          \"x\": 110,\n          \"y\": 131,\n          \"type\": \"shape\",\n          \"groupId\": \"2ef4008b-8b60-4300-90a1-8654d3fc428b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0.1 } }\n          },\n          \"id\": \"311f5ee9-6176-4e02-af0e-d4d1a23d884b\",\n          \"x\": 117,\n          \"y\": -250,\n          \"type\": \"shape\",\n          \"groupId\": \"2ef4008b-8b60-4300-90a1-8654d3fc428b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 135, \"g\": 140, \"b\": 82 } },\n          \"width\": 353,\n          \"height\": 144,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 40,\n            \"topRight\": 80,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 60,\n            \"locked\": false\n          },\n          \"id\": \"e10cd290-a090-440e-9fe3-d5ec15a5f611\",\n          \"x\": 29,\n          \"y\": -183,\n          \"type\": \"shape\",\n          \"groupId\": \"2ef4008b-8b60-4300-90a1-8654d3fc428b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 290,\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a5499c7a-17e6-4073-9780-7ec60ffdd449\",\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:37:55\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page10_image01.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown teapot on black surface\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e4e4e5\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"ad3f83e7-2118-42ec-8056-3c3dd577b031\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Tea and Sympathy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 117,\n          \"height\": 37,\n          \"id\": \"2c6c86d3-f394-4de8-8a82-6303134e8d03\",\n          \"x\": 223,\n          \"y\": 290,\n          \"type\": \"text\",\n          \"groupId\": \"ad3f83e7-2118-42ec-8056-3c3dd577b031\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 224,\n          \"y\": 334,\n          \"id\": \"533013ae-d961-4d45-b416-4bc74a688835\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">A classic NY tea shop that never goes out of style.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"ad3f83e7-2118-42ec-8056-3c3dd577b031\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 57,\n          \"y\": 446,\n          \"id\": \"87b1d4ce-b4fe-4543-bca9-6f9e54d3776c\",\n          \"width\": 136,\n          \"height\": 107,\n          \"scale\": 153,\n          \"focalX\": 50.092523723843804,\n          \"focalY\": 54.31777377937739,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 30,\n            \"topRight\": 30,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 30,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:38:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page10_image02.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person holding white ceramic cup with hot coffee\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#6b564f\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"fb446e2c-b395-472c-8f1f-6b5ff827ac81\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 225,\n          \"y\": 455,\n          \"id\": \"be43cfd2-77d6-402a-b727-eaa974cbfcef\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.1em; text-transform: uppercase\\\">Cha An</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 17,\n          \"type\": \"text\",\n          \"groupId\": \"fb446e2c-b395-472c-8f1f-6b5ff827ac81\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 222,\n          \"y\": 481,\n          \"id\": \"036397e6-36ce-41a6-b381-c9c47c3eb0fb\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Take a trip to Japan in NY and explore unique teas.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"fb446e2c-b395-472c-8f1f-6b5ff827ac81\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"3beb3cc9-a05c-44db-aab6-72e1ea9e9c4d\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Best</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">exercise</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">options</span>\\n<span style=\\\"font-weight: 300; color: #fff\\\">in NYC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 218,\n          \"height\": 164,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"333ac16f-afb9-44c8-b5bd-dc578b4651a4\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"533013ae-d961-4d45-b416-4bc74a688835\"]\n        },\n        {\n          \"id\": \"c36532cd-cd31-49e6-a864-6d3ec2df1b5f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"036397e6-36ce-41a6-b381-c9c47c3eb0fb\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 99, \"g\": 101, \"b\": 79 } },\n      \"type\": \"page\",\n      \"id\": \"995c748f-da00-4449-afe2-e0bb26720198\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2ef4008b-8b60-4300-90a1-8654d3fc428b\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"ad3f83e7-2118-42ec-8056-3c3dd577b031\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fb446e2c-b395-472c-8f1f-6b5ff827ac81\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"73a5d5ce-ac55-4050-bbc9-c27d3cd3b28a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": -177,\n          \"y\": 107,\n          \"width\": 457,\n          \"height\": 654,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9ab45f9e-d1dd-4354-94a6-2c0a3d8351c5\",\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"1370028e-0753-4db2-a4a7-69a259ef8554\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"x\": 117,\n          \"y\": -250,\n          \"id\": \"90b1a60b-9621-42ed-a244-c6f715144457\",\n          \"width\": 265,\n          \"height\": 357,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 200,\n            \"topRight\": 200,\n            \"bottomRight\": 200,\n            \"bottomLeft\": 200,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n          },\n          \"type\": \"shape\",\n          \"groupId\": \"1370028e-0753-4db2-a4a7-69a259ef8554\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Spectral\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1059,\n              \"des\": -463,\n              \"tAsc\": 1059,\n              \"tDes\": -463,\n              \"tLGap\": 0,\n              \"wAsc\": 1059,\n              \"wDes\": 463,\n              \"xH\": 450,\n              \"capH\": 660,\n              \"yMin\": -250,\n              \"yMax\": 1057,\n              \"hAsc\": 1059,\n              \"hDes\": -463,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #272727\\\">Let’s</span>\\n<span style=\\\"font-weight: 300; color: #272727\\\">Recap</span>\\n<span style=\\\"font-weight: 300; color: #272727\\\">What We</span>\\n<span style=\\\"font-weight: 300; color: #272727\\\">Learned</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 218,\n          \"height\": 164,\n          \"id\": \"003a97fd-898a-4c6b-955f-40ad905be703\",\n          \"x\": 47,\n          \"y\": -4\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 220,\n          \"y\": 200,\n          \"width\": 88,\n          \"height\": 70,\n          \"scale\": 100,\n          \"focalX\": 51.1363627918798,\n          \"focalY\": 36.37566068756343,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"23e38af0-2e54-4f7f-bf69-719b840d5855\",\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 20,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:19:49\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page02_bg.png\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman doing yoga\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#dbd4d3\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"6b5d68ab-33ff-460e-a411-deea98123782\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #272727; letter-spacing: 0.1em; text-transform: uppercase\\\">Exercise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 84,\n          \"height\": 17,\n          \"id\": \"b9b2aa64-41af-4b5a-96bf-e966d11eef1b\",\n          \"x\": 51,\n          \"y\": 226,\n          \"groupId\": \"6b5d68ab-33ff-460e-a411-deea98123782\"\n        },\n        {\n          \"x\": 221,\n          \"y\": 300,\n          \"id\": \"ee483ac1-a82d-4de8-83c6-105db178f697\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 88,\n          \"height\": 70,\n          \"scale\": 240,\n          \"focalX\": 50.16464844146129,\n          \"focalY\": 53.29917955808827,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 20,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:23:49\",\n            \"baseColor\": \"#484944\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page05_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman with afro hair, at home\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"25258554-a2fb-4a8c-b22a-ffe3de09551c\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 326,\n          \"id\": \"6983adf5-845c-46a0-a135-dd92fd3eca9a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #272727; letter-spacing: 0.1em; text-transform: uppercase\\\">Sleep More</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 115,\n          \"height\": 17,\n          \"groupId\": \"25258554-a2fb-4a8c-b22a-ffe3de09551c\"\n        },\n        {\n          \"x\": 221,\n          \"y\": 400,\n          \"id\": \"f32bb246-4fc5-4ead-ac50-9e6d5d015a99\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 88,\n          \"height\": 70,\n          \"scale\": 120,\n          \"focalX\": 50.08563466196947,\n          \"focalY\": 55.1380797181666,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 20,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:28:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page07_image01.jpg\",\n            \"width\": 720,\n            \"height\": 900,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Green and white drink with straw in clear drinking glass\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#47261a\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"28b266c2-f8b6-48cf-93a5-e52705452e96\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 416,\n          \"id\": \"4fc4880d-2486-4097-9ff8-5c8644dcc1d2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #272727; letter-spacing: 0.1em; text-transform: uppercase\\\">Get your vitamins</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 115,\n          \"height\": 37,\n          \"groupId\": \"28b266c2-f8b6-48cf-93a5-e52705452e96\"\n        },\n        {\n          \"x\": 221,\n          \"y\": 500,\n          \"id\": \"c2b1b798-b8a4-489b-a6a6-3b20d9efd03c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 88,\n          \"height\": 70,\n          \"scale\": 100,\n          \"focalX\": 47.457458043729964,\n          \"focalY\": 50.04901876633995,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 20,\n            \"locked\": false\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-25T07:44:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/self-care-guide/page11_image03.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Brown teapot\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b3b7b9\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"74c6bc9a-cee5-4732-9c4c-930ac27e0bfa\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 517,\n          \"id\": \"dc828d32-d0de-405a-a4ba-414bdb727d5b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Libre Franklin\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 966,\n              \"des\": -246,\n              \"tAsc\": 966,\n              \"tDes\": -246,\n              \"tLGap\": 0,\n              \"wAsc\": 1177,\n              \"wDes\": 246,\n              \"xH\": 530,\n              \"capH\": 742,\n              \"yMin\": -236,\n              \"yMax\": 1147,\n              \"hAsc\": 966,\n              \"hDes\": -246,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #272727; letter-spacing: 0.1em; text-transform: uppercase\\\">Skip the coffee</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 115,\n          \"height\": 37,\n          \"groupId\": \"74c6bc9a-cee5-4732-9c4c-930ac27e0bfa\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c2ee574f-14dc-4d1f-88f9-1b3c7ae9595a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b9b2aa64-41af-4b5a-96bf-e966d11eef1b\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4d4eb3fc-0531-4754-b763-26670e1edcaf\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6983adf5-845c-46a0-a135-dd92fd3eca9a\"],\n          \"duration\": 1500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5dd5437e-63b9-4051-8438-bef9348d488e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4fc4880d-2486-4097-9ff8-5c8644dcc1d2\"],\n          \"duration\": 1500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"71827f3b-3e2e-4eac-830a-28b22ee3cd67\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"dc828d32-d0de-405a-a4ba-414bdb727d5b\"],\n          \"duration\": 1500,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 244, \"b\": 238 } },\n      \"type\": \"page\",\n      \"id\": \"61a81226-95e0-47c7-92b1-071477f13da2\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"1370028e-0753-4db2-a4a7-69a259ef8554\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"6b5d68ab-33ff-460e-a411-deea98123782\": {\n          \"name\": \"Exercise\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"25258554-a2fb-4a8c-b22a-ffe3de09551c\": {\n          \"name\": \"Sleep\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"28b266c2-f8b6-48cf-93a5-e52705452e96\": {\n          \"name\": \"Vitamins\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"74c6bc9a-cee5-4732-9c4c-930ac27e0bfa\": {\n          \"name\": \"Coffee\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/series-best-of/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/series-best-of/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'series-best-of',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Series - Best Of', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('Roundup', 'template keyword', 'web-stories'),\n    _x('Banners', 'template keyword', 'web-stories'),\n    _x('Classic', 'template keyword', 'web-stories'),\n    _x('Yellow', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Zinc Yellow', 'color', 'web-stories'),\n      color: '#ffe145',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mercury Gray', 'color', 'web-stories'),\n      color: '#e3e3e3',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s simple banners and classic font make it great for creating bite-sized informational stories. Easily change the colors and use it to create stories for a variety of different topics like technology, entertainment, arts and crafts and more.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/series-best-of/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/series-best-of/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8ac0f39e-4b55-4d86-8b80-1958b23a6c50\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 29,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 206,\n          \"y\": -110,\n          \"width\": 1,\n          \"height\": 839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"80360831-2db7-421e-ad11-6a8087e5795d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">The best of</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 37,\n          \"width\": 200,\n          \"height\": 21,\n          \"id\": \"00578a6d-34de-4729-8b3d-78b247265b5b\",\n          \"type\": \"text\",\n          \"groupId\": \"76bb4db9-9822-4f0b-a61b-8a81e54e3879\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 207,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"32e1702e-a169-4d15-a663-f9465cef031e\",\n          \"x\": 47,\n          \"y\": 103,\n          \"type\": \"shape\",\n          \"groupId\": \"76bb4db9-9822-4f0b-a61b-8a81e54e3879\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 300,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"16bdf445-a6ce-46e5-be42-1515eac296ec\",\n          \"x\": 47,\n          \"y\": 150,\n          \"type\": \"shape\",\n          \"groupId\": \"76bb4db9-9822-4f0b-a61b-8a81e54e3879\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 46,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Celebrity</span>\\n<span style=\\\"font-weight: 700\\\">Philanthropy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 333,\n          \"height\": 113,\n          \"id\": \"5b3d69cd-6080-445a-b521-2b6f8eceb567\",\n          \"x\": 47,\n          \"y\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"76bb4db9-9822-4f0b-a61b-8a81e54e3879\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(0,0,0,0.37); text-transform: uppercase\\\">A roundup</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 93,\n          \"height\": 19,\n          \"id\": \"d82e7b14-14f2-4f9f-ba2b-1d469ba9a91f\",\n          \"x\": 10,\n          \"y\": 340,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:36:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page1_img1.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Woman Wearing Gray Notch Lapel Suit Jacket\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cbcbcd\",\n            \"isExternal\": true\n          },\n          \"x\": 99,\n          \"y\": 302,\n          \"width\": 140,\n          \"height\": 170,\n          \"scale\": 105,\n          \"focalX\": 54.509388920130306,\n          \"focalY\": 50.38561718777822,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b62d2bc4-9f14-4ca5-8f73-e84de2b5617b\",\n          \"groupId\": \"95fdddad-bed5-4bd0-9996-5da24ccdc2a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 120,\n          \"height\": 170,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e66522ab-e55b-4e68-8e26-9e7325835a8d\",\n          \"x\": 244,\n          \"y\": 302,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:37:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page1_img2.jpg\",\n            \"width\": 720,\n            \"height\": 494,\n            \"id\": 0,\n            \"alt\": \"Photo Of Man Wearing Black Eyeglasses\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c7c8ca\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"95fdddad-bed5-4bd0-9996-5da24ccdc2a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 266,\n          \"height\": 141,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"07c3aabe-8229-4537-b145-67f4bc980c46\",\n          \"x\": 99,\n          \"y\": 477,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:37:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page1_img3.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Man Standing Near Building White Black Turtleneck Shirt\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#887062\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"95fdddad-bed5-4bd0-9996-5da24ccdc2a5\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"32383cca-37ff-48b9-9a63-ea76afdbe272\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"76bb4db9-9822-4f0b-a61b-8a81e54e3879\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"95fdddad-bed5-4bd0-9996-5da24ccdc2a5\": {\n          \"name\": \"Head Shots\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"972e1032-12aa-4e7a-b252-6a13832119c7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 29,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 206,\n          \"y\": -110,\n          \"width\": 1,\n          \"height\": 839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"48e4096f-f549-474c-947e-6ace300de4be\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300\\\">It’s great to see so many celebrities we know and love put their money where their heart is.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 90,\n          \"width\": 285,\n          \"height\": 113,\n          \"id\": \"d42d9e78-578a-43ec-9a11-e7bf1d2a4474\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 412,\n          \"height\": 121,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1ccd12fa-5de5-4abf-b3a5-c45420e49a63\",\n          \"x\": 0,\n          \"y\": 342,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:37:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page2_img1.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Selective Focus Photography of Child's Hand\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#282320\",\n            \"isExternal\": true\n          },\n          \"x\": 32,\n          \"y\": 372,\n          \"width\": 380,\n          \"height\": 303,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a60dfcfc-8cbf-4d6f-92e7-5f9711eeca87\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1a95960f-2b5e-4b3b-a264-6acbc3ef29dc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a60dfcfc-8cbf-4d6f-92e7-5f9711eeca87\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"a48afcc0-f0f0-4254-bb45-ebb2673a5c23\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 226,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"ac68880d-3564-441b-91a4-2f58ac2f0d72\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 49.356770833333336,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:38:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 741,\n            \"id\": 0,\n            \"alt\": \"Photo Of Man Wearing Black Eyeglasses\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c8c8c8\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.6\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffe145\\\">\\\"It was important for me to start this foundation because it’s rooted in caring for others.\\\"</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 105,\n          \"y\": 413,\n          \"width\": 209,\n          \"height\": 116,\n          \"id\": \"25e42cea-d4b2-4d69-b201-2d73b5f4a39b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffe145\\\">Bill Dates</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 20,\n          \"id\": \"baef07cc-9454-449c-9bd2-ec486ddd10c4\",\n          \"x\": 105,\n          \"y\": 546,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"776b0ec3-fee4-4e51-ac40-0bb0b9c17d85\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"ac68880d-3564-441b-91a4-2f58ac2f0d72\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"ba958870-e15d-4a57-9706-eb7c61670622\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"1cdb95db-ebcd-4ffc-a7af-75ca4565979a\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"8ba56096-78a9-4554-bce8-1ac623532139\",\n          \"type\": \"image\",\n          \"scale\": 142,\n          \"focalX\": 51.9806338028169,\n          \"focalY\": 56.16197183098591,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:39:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page4_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Girl sitting using smartphone photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#29291d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 324,\n          \"height\": 197,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"98d52617-070a-4b29-9b94-a906ce914f3e\",\n          \"x\": 44,\n          \"y\": 442,\n          \"type\": \"shape\",\n          \"groupId\": \"85afa4b6-472f-4888-bcd9-d6d5fc926612\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Bill Dates's\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 21,\n          \"id\": \"cb41760b-3fef-48d0-beb4-85dca6f8d605\",\n          \"x\": 67,\n          \"y\": 457,\n          \"type\": \"text\",\n          \"groupId\": \"85afa4b6-472f-4888-bcd9-d6d5fc926612\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">The Plant School</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 67,\n          \"y\": 510,\n          \"width\": 209,\n          \"height\": 32,\n          \"id\": \"ef709aa7-84d5-410f-85f9-b5504ce6129b\",\n          \"type\": \"text\",\n          \"groupId\": \"85afa4b6-472f-4888-bcd9-d6d5fc926612\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Bringing plants to urban, underserved environments.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 268,\n          \"height\": 47,\n          \"id\": \"eb068da4-381d-4610-994a-1f5cb4542812\",\n          \"x\": 67,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"85afa4b6-472f-4888-bcd9-d6d5fc926612\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4293fe58-164e-4172-abea-7b7cc51e7b96\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"8ba56096-78a9-4554-bce8-1ac623532139\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"8e79860c-7081-490f-ac41-c2f9a38a7588\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"eca8914e-d94f-4ef6-be97-4cd0255c34b3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"85afa4b6-472f-4888-bcd9-d6d5fc926612\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"870fa7f0-2744-4797-8944-ec7d9c9a3bca\",\n          \"type\": \"image\",\n          \"scale\": 182,\n          \"focalX\": 39.56902472527473,\n          \"focalY\": 48.71222527472527,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:40:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page5_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Woman in white robe sitting on black office rolling chair photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c3c6bf\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 324,\n          \"height\": 197,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6e54db47-f8a2-4eb6-a92e-ab6edd704ca8\",\n          \"x\": 44,\n          \"y\": 442,\n          \"type\": \"shape\",\n          \"groupId\": \"fa25dbe8-a759-4b39-a46f-f20cfc36f6f2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Bill Dates's\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 21,\n          \"id\": \"7f03639a-e52e-4c14-b399-cf786b51b94d\",\n          \"x\": 67,\n          \"y\": 457,\n          \"type\": \"text\",\n          \"groupId\": \"fa25dbe8-a759-4b39-a46f-f20cfc36f6f2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Cancer Cures</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 66,\n          \"y\": 510,\n          \"width\": 209,\n          \"height\": 32,\n          \"id\": \"f00a47ee-c3b6-49e8-b489-260492d320bc\",\n          \"type\": \"text\",\n          \"groupId\": \"fa25dbe8-a759-4b39-a46f-f20cfc36f6f2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Giving cancer research a much-needed push through donations.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 268,\n          \"height\": 70,\n          \"id\": \"1f82ec22-8de6-450d-8309-4b791b392154\",\n          \"x\": 67,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"fa25dbe8-a759-4b39-a46f-f20cfc36f6f2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"826ea8cc-4a18-42ec-833d-89d9df40278d\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"870fa7f0-2744-4797-8944-ec7d9c9a3bca\"],\n          \"panDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"26edfadc-74c9-4ca5-85ea-5cb24d5d8bc0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"436cdf32-be49-40c8-bd05-a24b2d12c243\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"fa25dbe8-a759-4b39-a46f-f20cfc36f6f2\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d5658fca-7234-409d-92ad-b32c7cbca538\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 29,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 206,\n          \"y\": -110,\n          \"width\": 1,\n          \"height\": 839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2ed3d555-e283-4a11-a8b2-7196468df4d1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:41:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page6_img1.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Green leaf plants beside white house photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cfd9d7\",\n            \"isExternal\": true\n          },\n          \"x\": 46,\n          \"y\": -57,\n          \"width\": 366,\n          \"height\": 293,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f61735a1-7892-4b2b-bfb3-783002aca563\",\n          \"groupId\": \"5d539645-cb44-4278-8aaa-093964422cc0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 400\\\">The Plant School</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 169,\n          \"height\": 49,\n          \"id\": \"cc2e5712-9778-4a17-878f-97852b1d2783\",\n          \"x\": 46,\n          \"y\": 187,\n          \"type\": \"text\",\n          \"groupId\": \"5d539645-cb44-4278-8aaa-093964422cc0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Find Your Celebrity Cause:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 105,\n          \"y\": 277,\n          \"width\": 205,\n          \"height\": 63,\n          \"id\": \"64cb2116-3c92-477c-97fe-2bc58023364b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 365,\n          \"height\": 280,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b2c335d7-4a6a-43b3-b0e7-8197a5029515\",\n          \"x\": 0,\n          \"y\": 395,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:42:11\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page6_img2.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Silver microscope photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#bfc0c0\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"8e8d3ace-916a-4183-8529-3447389050b2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"content\": \"Cancer Cures\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 161,\n          \"height\": 50,\n          \"id\": \"011227c8-c24e-4c78-bbbc-4010c0b61ca1\",\n          \"x\": 204,\n          \"y\": 394,\n          \"type\": \"text\",\n          \"groupId\": \"8e8d3ace-916a-4183-8529-3447389050b2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6158b60f-c8b2-47bf-b7d1-fabca2dd2033\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"64cb2116-3c92-477c-97fe-2bc58023364b\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"a1c9b635-196b-4a37-9c4e-81036d6cf5af\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Donate Now\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5d539645-cb44-4278-8aaa-093964422cc0\": {\n          \"name\": \"School Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"8e8d3ace-916a-4183-8529-3447389050b2\": {\n          \"name\": \"Cures Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 412,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cf390b2f-c773-4ccb-9d08-e9f743cfa27d\",\n          \"type\": \"image\",\n          \"scale\": 136,\n          \"focalX\": 50,\n          \"focalY\": 59.65073529411765,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:42:38\",\n            \"baseColor\": \"#c7c7c7\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1350,\n            \"id\": 0,\n            \"alt\": \"Photo of Woman Wearing Headscarf\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.6 }, \"position\": 1 }\n            ],\n            \"alpha\": 1\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffe145\\\">“Many things in life inspire philanthropy, such as your faith in humanity and your belief in the human spirit to overcome.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 105,\n          \"y\": 390,\n          \"width\": 209,\n          \"height\": 138,\n          \"id\": \"4cc689e8-b7ab-47c4-9167-2423ef7a874b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffe145\\\">Wanda Winfrey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 20,\n          \"id\": \"6d6f8328-457a-498d-8951-8ccdf871e76e\",\n          \"x\": 105,\n          \"y\": 546,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dd21f4e4-ecc1-441b-9b27-2ce2c4f3aa2f\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"cf390b2f-c773-4ccb-9d08-e9f743cfa27d\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"617c66bd-1263-41f8-95bc-eb31d7ed4a8d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"3f7536e8-aecd-4a22-b00f-ceacd18c0c39\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e6de7dff-cca4-4d04-8fbc-8aa6cc24179a\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 38.125,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:45:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Children holding hands standing on grasses photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#afbb74\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 324,\n          \"height\": 197,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cb593444-068e-4d1d-a437-7123203cc37c\",\n          \"x\": 44,\n          \"y\": 442,\n          \"type\": \"shape\",\n          \"groupId\": \"6487be1a-2378-473f-94af-a2599abe9e98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Wanda Winfrey’s\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 21,\n          \"id\": \"5a6e8d4d-b159-48b0-b9ba-0128401ce88c\",\n          \"x\": 67,\n          \"y\": 457,\n          \"type\": \"text\",\n          \"groupId\": \"6487be1a-2378-473f-94af-a2599abe9e98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Little Big Moves</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 67,\n          \"y\": 510,\n          \"width\": 209,\n          \"height\": 32,\n          \"id\": \"63d4ef69-33fa-4f4d-b0af-4e98081e643a\",\n          \"type\": \"text\",\n          \"groupId\": \"6487be1a-2378-473f-94af-a2599abe9e98\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Encouraging exercise in children across all public and private schools in the US.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 276,\n          \"height\": 70,\n          \"id\": \"7516f9cd-e4dc-4559-93c5-0842f14678f9\",\n          \"x\": 67,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"6487be1a-2378-473f-94af-a2599abe9e98\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"d0701238-58b1-45ce-a143-78a5df69e930\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"52ff2913-2605-4c19-928b-6de74f273c0b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"6487be1a-2378-473f-94af-a2599abe9e98\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"fb2a7c88-371e-4e1c-be81-238502ce71bb\",\n          \"type\": \"image\",\n          \"scale\": 120,\n          \"focalX\": 40.78583140432099,\n          \"focalY\": 54.947916666666664,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:46:03\",\n            \"baseColor\": \"#353e42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page9_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Man in beige blazer holding tablet computer\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"width\": 324,\n          \"height\": 197,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b7f8ab1d-8f5c-4f82-b3a2-7ca9c4cdf8d4\",\n          \"x\": 44,\n          \"y\": 442,\n          \"type\": \"shape\",\n          \"groupId\": \"308754ee-f33e-460d-a1a9-aeafe48b8f84\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Wanda Winfrey’s\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 209,\n          \"height\": 21,\n          \"id\": \"dd60c1b4-7874-4911-ac2d-c27bbc4510f2\",\n          \"x\": 67,\n          \"y\": 457,\n          \"type\": \"text\",\n          \"groupId\": \"308754ee-f33e-460d-a1a9-aeafe48b8f84\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Heart To Heart</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 67,\n          \"y\": 510,\n          \"width\": 209,\n          \"height\": 33,\n          \"id\": \"400697cf-ee57-4dbf-af96-f425f6fe6865\",\n          \"type\": \"text\",\n          \"groupId\": \"308754ee-f33e-460d-a1a9-aeafe48b8f84\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Tools, methods, and therapists to chat anytime about anything.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 281,\n          \"height\": 47,\n          \"id\": \"5c979f3a-c7c6-4fd2-898d-6b28bfe3546c\",\n          \"x\": 67,\n          \"y\": 547,\n          \"type\": \"text\",\n          \"groupId\": \"308754ee-f33e-460d-a1a9-aeafe48b8f84\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"79af651a-76a2-4259-90f9-7c65df58b14e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f86a11fa-86aa-4da2-b0f2-a0a7be4ebf13\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"308754ee-f33e-460d-a1a9-aeafe48b8f84\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d32bc21a-22fb-42bb-a69d-addc1375e45a\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 29,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 206,\n          \"y\": -110,\n          \"width\": 1,\n          \"height\": 839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"afd4f25f-b90f-4206-8086-bc4b829fb4c5\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:46:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page10_img1.jpg\",\n            \"width\": 720,\n            \"height\": 479,\n            \"id\": 0,\n            \"alt\": \"Boy in green shirt\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c7beb7\",\n            \"isExternal\": true\n          },\n          \"x\": 46,\n          \"y\": -57,\n          \"width\": 366,\n          \"height\": 293,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"26129273-e19a-493a-bcdf-4185049d4293\",\n          \"groupId\": \"0dc011a4-13d5-4f29-897d-ba1e6f4c76a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"content\": \"Little Big Moves\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 169,\n          \"height\": 50,\n          \"id\": \"c41d949f-03f3-415a-90b5-79b7b8cea242\",\n          \"x\": 46,\n          \"y\": 187,\n          \"type\": \"text\",\n          \"groupId\": \"0dc011a4-13d5-4f29-897d-ba1e6f4c76a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Find Your Celebrity Cause:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 105,\n          \"y\": 277,\n          \"width\": 205,\n          \"height\": 63,\n          \"id\": \"fd0353ed-1c8a-409b-ad11-aee0a9aa414b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 365,\n          \"height\": 280,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4cf632ff-4a0d-4233-acdb-9e47cb507c8f\",\n          \"x\": 0,\n          \"y\": 395,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:47:03\",\n            \"baseColor\": \"#1a1e1d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page10_img2.jpg\",\n            \"width\": 720,\n            \"height\": 1078,\n            \"id\": 0,\n            \"alt\": \"Man and Woman Sitting Beside Table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"isExternal\": true\n          },\n          \"groupId\": \"265104c7-7932-4205-9c60-098ac4047268\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 14\n          },\n          \"content\": \"Heart to Heart\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 161,\n          \"height\": 50,\n          \"id\": \"92770873-2420-44ec-ac8e-7d3d31d0a404\",\n          \"x\": 205,\n          \"y\": 394,\n          \"type\": \"text\",\n          \"groupId\": \"265104c7-7932-4205-9c60-098ac4047268\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f744a5bf-2b0c-4b9d-9c0c-17ca5056056b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fd0353ed-1c8a-409b-ad11-aee0a9aa414b\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 227, \"g\": 227, \"b\": 227 } },\n      \"type\": \"page\",\n      \"id\": \"2f00e698-d9bd-4238-b43d-4bfbdd7aabf0\",\n      \"pageAttachment\": {\n        \"url\": \"https://www.google.com/\",\n        \"ctaText\": \"Donate Now\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"265104c7-7932-4205-9c60-098ac4047268\": {\n          \"name\": \"Heart Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0dc011a4-13d5-4f29-897d-ba1e6f4c76a4\": {\n          \"name\": \"Big Moves Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3990c1fb-5a39-489c-a3ea-b05b0f7766a4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 29,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"x\": 206,\n          \"y\": -110,\n          \"width\": 1,\n          \"height\": 839,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"34dcb6bc-e23d-439f-acc9-6a2b2d703d31\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Read More Causes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 73,\n          \"y\": 41,\n          \"width\": 205,\n          \"height\": 63,\n          \"id\": \"edf3aa1d-2533-45d1-a2e8-406cda612b80\",\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:47:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page11_img1.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Group of people taking photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b77751\",\n            \"isExternal\": true\n          },\n          \"x\": 47,\n          \"y\": 143,\n          \"width\": 220,\n          \"height\": 125,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2010fb72-1586-46d2-a385-b50a014d23cb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 10\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">Million dollar</span>\\n<span style=\\\"color: #fff\\\">celebrity foundations</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 245,\n          \"height\": 68,\n          \"id\": \"209587bd-800a-422e-ab03-67ca13591b09\",\n          \"x\": 47,\n          \"y\": 267,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 220,\n          \"height\": 125,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e55118f0-fc99-4f8c-b555-6c7584a3bc4d\",\n          \"x\": 145,\n          \"y\": 414,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-20T15:47:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/series-best-of/page11_img2.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Woman sitting on gray chair while writing on table\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b59d83\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 22,\n            \"vertical\": 10\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">Hollywood turns retail:</span>\\n<span style=\\\"color: #fff\\\">Celebrity brands</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 243,\n          \"height\": 68,\n          \"id\": \"6ae3571e-f7b8-40c7-a2b6-5f7a0120522b\",\n          \"x\": 122,\n          \"y\": 539,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"128b2528-636f-45a9-9524-ac15276cde85\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2010fb72-1586-46d2-a385-b50a014d23cb\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6a7337f9-89f0-4d0b-ad40-195426608e96\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e55118f0-fc99-4f8c-b555-6c7584a3bc4d\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 225, \"b\": 69 } },\n      \"type\": \"page\",\n      \"id\": \"ba8a5f35-bb6c-4f27-bdc8-74c8f77845dc\",\n      \"pageAttachment\": {\n        \"url\": \"\",\n        \"ctaText\": \"Learn more\",\n        \"theme\": \"light\"\n      },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {}\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/simple-tech-tutorial/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/simple-tech-tutorial/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'simple-tech-tutorial',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Simple Tech Tutorial', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Network', 'template keyword', 'web-stories'),\n    _x('How-To', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('Blue', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Boston Blue', 'color', 'web-stories'),\n      color: '#4899bf',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Liquid Blue', 'color', 'web-stories'),\n      color: '#c1ddeb',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Teal', 'color', 'web-stories'),\n      color: '#264156',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This clean and simple template will let you create structured and easy to understand tech tutorials and how-to guides. Just add your own screenshots, text, and illustrations.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/simple-tech-tutorial/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/simple-tech-tutorial/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0f8f7aa5-f27f-4e4c-b7d5-9cb2dc6e7f5f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #264156\\\">How to get Safari’s privacy features in Chrome.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 323,\n          \"height\": 144,\n          \"id\": \"52d76a59-0387-4a92-89a7-2ce936c82717\",\n          \"type\": \"text\",\n          \"groupId\": \"e0c23ee6-4dd2-48c8-be9c-f942ef6b64db\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #264156\\\">By</span><span style=\\\"color: #264156\\\"> </span><span style=\\\"font-weight: 500; color: #264156\\\">John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 144,\n          \"width\": 126,\n          \"height\": 29,\n          \"id\": \"b3c9036c-5394-4ded-aed0-6abe5e1adb96\",\n          \"type\": \"text\",\n          \"groupId\": \"e0c23ee6-4dd2-48c8-be9c-f942ef6b64db\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 109,\n          \"focalX\": 50.0236418498007,\n          \"focalY\": 45.993051656729946,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:28:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page1_img1.jpg\",\n            \"width\": 1527,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Network services and network security\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0691cc\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 185,\n          \"width\": 412,\n          \"height\": 490,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d4a05a81-32bd-4590-98f9-bd0a02bbdce7\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 145, \"b\": 202 } },\n      \"type\": \"page\",\n      \"id\": \"0277a411-0108-4e6b-8e52-6341a77c7851\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"e0c23ee6-4dd2-48c8-be9c-f942ef6b64db\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5120650b-3c64-494c-95f7-b4362df91a98\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 140,\n          \"focalX\": 47.09388228418253,\n          \"focalY\": 62.093727301689526,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:29:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page2_8_img1.jpg\",\n            \"width\": 1527,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Smart device and web data cloud savings and analysis\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0f93cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 378,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"63c9453f-5691-4234-b610-c3a54ad8aee9\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #264156\\\">Keeping your web browser private is more important than ever these days. Here’s how to get Safari’s privacy features on Chrome.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 418,\n          \"width\": 323,\n          \"height\": 172,\n          \"id\": \"b7bd7a02-da3e-444f-af04-ef6f4544bd4f\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a85d59db-d3ee-4953-a200-1a9004be2eaa\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"63c9453f-5691-4234-b610-c3a54ad8aee9\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 145, \"b\": 202 } },\n      \"type\": \"page\",\n      \"id\": \"14f1d556-ba3e-4304-9c2c-5c3f370e6afc\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bfffa10b-6e01-4eac-bc59-79fe7bb08044\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 65, \"b\": 86 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">01/04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 60,\n          \"height\": 24,\n          \"id\": \"587c063f-d247-47b5-892e-0b3a2209088b\",\n          \"groupId\": \"1d1b6c99-ad82-4fa0-8fa7-6f213ef06c6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #264156\\\">Check your passwords</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 35,\n          \"width\": 307,\n          \"height\": 28,\n          \"id\": \"9d908d43-23c1-4335-bd81-4214a215c366\",\n          \"groupId\": \"1d1b6c99-ad82-4fa0-8fa7-6f213ef06c6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #264156\\\">Run an audit on your existing passwords in Chrome.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 46,\n          \"id\": \"842d6797-de9f-4b78-8c0d-e600f52d4d56\",\n          \"x\": 47,\n          \"y\": 67,\n          \"groupId\": \"1d1b6c99-ad82-4fa0-8fa7-6f213ef06c6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 221, \"b\": 235 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 164,\n          \"width\": 412,\n          \"height\": 511,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4557045d-1916-4af3-b97f-7861c20780ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#dfe0e1\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page3_img1.png\",\n            \"width\": 824,\n            \"height\": 976,\n            \"id\": 0,\n            \"alt\": \"Screenshot of chrome browser settings with a pointer on Passwords menu\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 187,\n          \"width\": 412,\n          \"height\": 488,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"28a6be75-a899-4de3-ba72-29fa5f6bca5f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #264156\\\">Go to Chrome </span><span style=\\\"font-weight: 500; color: #264156\\\">Settings</span><span style=\\\"font-weight: 300; color: #264156\\\"> and click </span><span style=\\\"font-weight: 500; color: #264156\\\">Passwords.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 18,\n          \"id\": \"735f6324-26c7-408d-98db-f2a1350e04be\",\n          \"x\": 43.5,\n          \"y\": 600\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c1609c53-1a9b-4a11-ad2b-2d834080923c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"735f6324-26c7-408d-98db-f2a1350e04be\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"66f978ae-cd61-476f-8c06-fbe79179c2d6\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"1d1b6c99-ad82-4fa0-8fa7-6f213ef06c6c\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6a674787-5b9b-401a-9851-c6d7dc2fcc31\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 65, \"b\": 86 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">02/04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 60,\n          \"height\": 24,\n          \"id\": \"31f17f12-62ea-4857-9844-06afa8f7a4f8\",\n          \"type\": \"text\",\n          \"groupId\": \"9a478c57-4e21-4079-9964-3d05bc47e72b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #264156\\\">Install Noblockers.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 35,\n          \"width\": 307,\n          \"height\": 28,\n          \"id\": \"d55478f3-ec15-445d-bc13-e7aebafa689e\",\n          \"type\": \"text\",\n          \"groupId\": \"9a478c57-4e21-4079-9964-3d05bc47e72b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #264156\\\">To get even more tracking data about a URL, or to block it, Safari-style, use an extension like </span><span style=\\\"text-decoration: underline; color: #264156\\\">Noblockers</span><span style=\\\"color: #264156\\\">.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 314,\n          \"height\": 71,\n          \"id\": \"b7784902-43cb-44f3-8d3d-6d17baabe22a\",\n          \"x\": 47,\n          \"y\": 67,\n          \"type\": \"text\",\n          \"groupId\": \"9a478c57-4e21-4079-9964-3d05bc47e72b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 221, \"b\": 235 } },\n          \"x\": 0,\n          \"y\": 164,\n          \"width\": 412,\n          \"height\": 511,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"12418f13-157d-45c1-90a6-625681a693a2\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#cecece\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page4_img1.png\",\n            \"width\": 824,\n            \"height\": 976,\n            \"id\": 0,\n            \"alt\": \"Screenshot of a browser extension with information on blocked URLs\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 187,\n          \"width\": 413,\n          \"height\": 488,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0ed66ad0-8909-4f77-83a0-ae979314e130\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"beef1d38-9fbf-45f4-808d-6f28734df2df\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0ed66ad0-8909-4f77-83a0-ae979314e130\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2973fe6c-4414-433f-ba04-6b7bbf28eb0f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9a478c57-4e21-4079-9964-3d05bc47e72b\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f64f41b1-82e8-4bea-a48e-50e1407e9aa3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 105,\n          \"focalX\": 53.28640858498307,\n          \"focalY\": 52.27958890692411,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:29:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page5_8_img1.jpg\",\n            \"width\": 1527,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Businessman standing on magnifying glass analyzing data\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#0893cc\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 475,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1c36dafd-7b30-4b12-a943-ef820ba12bbe\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #264156\\\">Almost there! You are more than halfway through.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 516,\n          \"width\": 323,\n          \"height\": 70,\n          \"id\": \"95f908c6-c8d7-4cc9-8601-01d56b78985b\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 145, \"b\": 202 } },\n      \"type\": \"page\",\n      \"id\": \"61bb1b9f-676a-474e-abca-547972322766\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"12d9dfdd-da32-4f62-a536-da9d0d931bf9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 65, \"b\": 86 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">03/04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 60,\n          \"height\": 24,\n          \"id\": \"e556e80b-a5f3-4f19-81db-d04c4352fd8c\",\n          \"type\": \"text\",\n          \"groupId\": \"e37a5058-676c-457e-a2ce-ef6f8a3423a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #264156\\\">Police Extensions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 35,\n          \"width\": 307,\n          \"height\": 28,\n          \"id\": \"06e87cee-3dc6-4ddb-950c-aba2f9d681b7\",\n          \"type\": \"text\",\n          \"groupId\": \"e37a5058-676c-457e-a2ce-ef6f8a3423a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #264156\\\">To police extension permissions, go to Choose More Tools &gt; Extensions from the Chrome menu.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 297,\n          \"height\": 71,\n          \"id\": \"22dcb0b9-cb26-4e3b-8725-2641b90462f4\",\n          \"x\": 47,\n          \"y\": 67,\n          \"type\": \"text\",\n          \"groupId\": \"e37a5058-676c-457e-a2ce-ef6f8a3423a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 221, \"b\": 235 } },\n          \"x\": 0,\n          \"y\": 164,\n          \"width\": 412,\n          \"height\": 511,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"50dc7ba9-6749-418f-9812-c51563c5e9d9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#c8c9c9\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page6_img1.png\",\n            \"width\": 824,\n            \"height\": 1098,\n            \"id\": 0,\n            \"alt\": \"More tools menu in Chrome browser\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 125,\n          \"width\": 412,\n          \"height\": 550,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"abc11c00-c872-458a-b012-646d6940cf8d\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6645af93-c1e4-439b-9802-f5394551237f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"abc11c00-c872-458a-b012-646d6940cf8d\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"b86af1ff-3f9f-4fb4-9197-85e6293793aa\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e37a5058-676c-457e-a2ce-ef6f8a3423a9\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fe7075c0-e8b0-44da-8390-201949879185\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"HIGHLIGHT\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 38, \"g\": 65, \"b\": 86 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">04/04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 5,\n            \"topRight\": 5,\n            \"bottomRight\": 5,\n            \"bottomLeft\": 5\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 60,\n          \"height\": 24,\n          \"id\": \"01b45803-c895-4215-bd5a-7c0aeb2c976a\",\n          \"type\": \"text\",\n          \"groupId\": \"63e58e45-d402-482b-838f-c585fdf249ac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #264156\\\">Detailed Extensions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 35,\n          \"width\": 307,\n          \"height\": 28,\n          \"id\": \"3712e806-1a36-4218-b468-291de608300e\",\n          \"type\": \"text\",\n          \"groupId\": \"63e58e45-d402-482b-838f-c585fdf249ac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #264156\\\">Then click Details next to the extension you need.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 297,\n          \"height\": 46,\n          \"id\": \"75063df8-9faf-4d81-8c3a-97429db94993\",\n          \"x\": 47,\n          \"y\": 67,\n          \"type\": \"text\",\n          \"groupId\": \"63e58e45-d402-482b-838f-c585fdf249ac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 193, \"g\": 221, \"b\": 235 } },\n          \"x\": 0,\n          \"y\": 164,\n          \"width\": 412,\n          \"height\": 511,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"59b49cc7-8bdf-4fb0-b796-3c3651ee4828\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"baseColor\": \"#c9cacc\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page7_img1.png\",\n            \"width\": 824,\n            \"height\": 952,\n            \"id\": 0,\n            \"alt\": \"Browser extension details modal with buttons to see more details and to remove the extension\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 199,\n          \"width\": 412,\n          \"height\": 476,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e780b7d9-a159-438e-9786-914bc441e3bf\",\n          \"alt\": \"page7_img1\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bdded0ff-a181-4ea4-bdc5-34a5639f3752\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e780b7d9-a159-438e-9786-914bc441e3bf\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"3c15156c-96a3-40d1-9cd8-112085061b9b\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"63e58e45-d402-482b-838f-c585fdf249ac\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fd6421af-47c1-4d10-9cc2-91c8ff0e575e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #264156\\\">Other Stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 307,\n          \"height\": 28,\n          \"id\": \"d072cd32-7c56-4916-83aa-25815020f744\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #264156\\\">How to use breakout rooms in Vroom</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 21,\n          \"id\": \"eaf23b08-a8a2-44a8-9f90-42739a5f83d5\",\n          \"x\": 47,\n          \"y\": 283,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #264156\\\">How to use the Together App for video calls</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 321,\n          \"height\": 46,\n          \"id\": \"b1096a32-5933-4b19-8b7f-ea3c8aceb788\",\n          \"x\": 47,\n          \"y\": 575,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 49.97546484391203,\n          \"focalY\": 45.66771817163699,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:32:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page9_img1.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"id\": 0,\n            \"alt\": \"Illustration of workspace with video call on desktop computer\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#e37c4d\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 47,\n          \"y\": 76,\n          \"width\": 317,\n          \"height\": 196,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"90e22932-afa9-48c0-b663-ffee4001cbca\",\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:32:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/simple-tech-tutorial/page9_img2.jpg\",\n            \"width\": 720,\n            \"height\": 540,\n            \"id\": 0,\n            \"alt\": \"Illustration of a diverse group of friends or colleagues in a video conference on laptop computer screen\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#04b2a2\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 320,\n          \"height\": 206,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"borderRadius\": {\n            \"topLeft\": 10,\n            \"topRight\": 10,\n            \"bottomRight\": 10,\n            \"bottomLeft\": 10,\n            \"locked\": true\n          },\n          \"id\": \"ce43c2cd-b69b-484a-954f-6743b82fa41e\",\n          \"x\": 47,\n          \"y\": 358,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e2f7e4d9-8c82-47c5-b6e3-233bba763c80\",\n      \"pageTemplateType\": \"list\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/skin-care-at-home/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/skin-care-at-home/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'skin-care-at-home',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Skin Care at Home', 'template name', 'web-stories'),\n  tags: [\n    _x('Beauty', 'template keyword', 'web-stories'),\n    _x('Care', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Pastel', 'template keyword', 'web-stories'),\n    _x('Pink', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Playful Purple', 'color', 'web-stories'),\n      color: '#380e63',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Rose Pink', 'color', 'web-stories'),\n      color: '#f3cce5',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Lavender Potpourri', 'color', 'web-stories'),\n      color: '#cdccf3',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Blue Denim', 'color', 'web-stories'),\n      color: '#cce0f3',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Green Teal', 'color', 'web-stories'),\n      color: '#ccf3df',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cream Fizz Yellow', 'color', 'web-stories'),\n      color: '#f3e5cc',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its light background colors, pink shades and structured format, this template will let you create beautiful and informative makeup and skincare tutorials.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion & Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/skin-care-at-home/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/skin-care-at-home/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7a231af0-0e9a-4198-879c-ba0bce572945\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 57.132045045498934,\n          \"focalY\": 50.03381584520643,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:17:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page1_img1.jpg\",\n            \"width\": 1620,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Selective focus portrait photo of smiling woman with a towel on head looking in the mirror\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c2c1c0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 215,\n          \"width\": 412,\n          \"height\": 460,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fdde237e-c595-42ec-af1a-ad4a4e1fe6e9\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.19,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63; text-transform: uppercase\\\">3 facials</span><span style=\\\"color: #380e63; text-transform: uppercase\\\"> </span><span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">you can try at home</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 250,\n          \"height\": 125,\n          \"id\": \"ad252272-e26a-4c31-b182-5d5fc160091c\",\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">JOHN DOE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 149,\n          \"width\": 85,\n          \"height\": 17,\n          \"id\": \"0398ea4e-be1d-40ac-bfb2-7399acfdbb9a\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 204, \"b\": 229 } },\n      \"type\": \"page\",\n      \"id\": \"685a549b-28db-43dd-a80d-8631eaba429c\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a6219a13-2986-4bae-823b-a0b02b6b6872\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 185,\n          \"focalX\": 47.89789789789789,\n          \"focalY\": 45.5955955955956,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:18:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Woman lying on brown textile\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#ba8069\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 139,\n          \"width\": 412,\n          \"height\": 536,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d1d3b78f-c804-40d5-9fdc-41dc83e5a4ea\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">The </span><span style=\\\"font-weight: 700; color: #380e63; text-transform: uppercase\\\">Brightening </span><span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">Facial</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 36,\n          \"width\": 332,\n          \"height\": 74,\n          \"id\": \"ffdd918f-df93-48aa-bae6-a9e5f2b3d0a0\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 85,\n          \"height\": 17,\n          \"id\": \"14dce690-1c20-4836-b03f-1189a91920e6\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5fae2da4-8382-4178-b97f-8a3562f34234\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d1d3b78f-c804-40d5-9fdc-41dc83e5a4ea\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 205, \"g\": 204, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"d0a807e8-7fd0-4b8a-9451-dda1532bc036\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0c741193-4a83-48ee-a3e4-53fa52959455\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:20:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page3_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1440,\n            \"id\": 0,\n            \"alt\": \"Foundation bottle beside pink rose petals\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b19da0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"db6c1d8d-edce-44ec-9104-4d7f7d85270e\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Lapis Facial Oil</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 385,\n          \"width\": 316,\n          \"height\": 30,\n          \"id\": \"ebe2c6c7-5673-4422-991a-e280bf2c1911\",\n          \"type\": \"text\",\n          \"groupId\": \"39ff0e14-b6a7-4232-a3e6-80a65351c61d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">An inflammation-reducing facial oil that we recommend for even the most sensitive skin.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 73,\n          \"id\": \"09d4225a-4f54-40cd-86e0-6f52fcd2d1b1\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"39ff0e14-b6a7-4232-a3e6-80a65351c61d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"08094aec-703d-4a5a-8e70-8bf0fc2425f5\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 63,\n          \"y\": 562,\n          \"width\": 47,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"skinCareFlower\" },\n          \"id\": \"370a1e52-c08c-444e-a8a0-7722a4e17d53\",\n          \"type\": \"sticker\",\n          \"groupId\": \"4f8dc467-7f9d-431b-8ae9-84327c18f689\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Floral</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 41,\n          \"height\": 17,\n          \"id\": \"6bff3a0b-7663-4320-830a-be09408e9a45\",\n          \"x\": 69,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"4f8dc467-7f9d-431b-8ae9-84327c18f689\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 170,\n          \"y\": 567,\n          \"width\": 54,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"skinCareSleepMask\" },\n          \"id\": \"adcf48ee-e573-4132-9d4c-1d347484111a\",\n          \"type\": \"sticker\",\n          \"groupId\": \"ea1cb809-8164-4a9d-b33c-aad859631cdb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Fine Line</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 62,\n          \"height\": 17,\n          \"id\": \"c8dc89c4-a487-4b69-b348-b4c9da229f15\",\n          \"x\": 170,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"ea1cb809-8164-4a9d-b33c-aad859631cdb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 301,\n          \"y\": 560,\n          \"width\": 30,\n          \"height\": 34,\n          \"sticker\": { \"type\": \"skinCareFaceWashBottles\" },\n          \"id\": \"e8977e77-d102-4262-a7cd-9a75a3ee53a3\",\n          \"type\": \"sticker\",\n          \"groupId\": \"07b4e87d-7d98-4839-b77a-0e8771e923ad\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Brightening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"14f6f698-b49a-42df-b0b8-9e3b7cac6abe\",\n          \"x\": 278,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"07b4e87d-7d98-4839-b77a-0e8771e923ad\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5f034ea4-1341-4363-a47e-a41c94e22221\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"370a1e52-c08c-444e-a8a0-7722a4e17d53\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f862ff5d-3a30-4d2a-b08f-745181973a9e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6bff3a0b-7663-4320-830a-be09408e9a45\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ea688456-bb6c-46bd-ad22-2bc2b437cecb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"adcf48ee-e573-4132-9d4c-1d347484111a\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"b6416257-028c-4479-9f0e-ec64d764c434\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c8dc89c4-a487-4b69-b348-b4c9da229f15\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"16e9017a-2c02-486b-b62d-63ebfd1de21b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e8977e77-d102-4262-a7cd-9a75a3ee53a3\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"79ed971a-b4a1-4287-90be-18223c462f7b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"14f6f698-b49a-42df-b0b8-9e3b7cac6abe\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"a5b9d1df-b38b-437f-942c-75b5186604db\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"db6c1d8d-edce-44ec-9104-4d7f7d85270e\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 205, \"g\": 204, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"19bb36d6-a1b9-4050-b25b-4e3448aa5238\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"39ff0e14-b6a7-4232-a3e6-80a65351c61d\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"4f8dc467-7f9d-431b-8ae9-84327c18f689\": {\n          \"name\": \"Floral\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ea1cb809-8164-4a9d-b33c-aad859631cdb\": {\n          \"name\": \"Fine\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"07b4e87d-7d98-4839-b77a-0e8771e923ad\": {\n          \"name\": \"Bright\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"47c5c9e8-62a4-4d5d-82e5-cd8d31d85e22\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:20:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page4_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"white and brown plastic tube bottle on white textile photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#b4a087\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e37ccb07-36b3-4feb-a64b-7f90cc5d25d6\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Rosehip BioRegenerate Oil</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 384,\n          \"width\": 316,\n          \"height\": 30,\n          \"id\": \"75ddef40-8b20-49de-8b27-d31aca22972f\",\n          \"type\": \"text\",\n          \"groupId\": \"47734154-b827-401e-a029-d7035ec3e5fb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">Streamline your routine with this multitasking oil that does it all: conditions &amp; firms.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 72,\n          \"id\": \"0a09e4ff-8dfe-4611-ba67-8cc5d427a0d1\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"47734154-b827-401e-a029-d7035ec3e5fb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8899fc93-f98b-4619-bcc8-7eb877809d89\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Hair Friendly</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 87,\n          \"height\": 17,\n          \"id\": \"aeaacb7c-b025-4c98-848d-36d485a2b102\",\n          \"x\": 47,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"8701c6e5-0348-4da4-949e-203edaf029d0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 73,\n          \"y\": 555,\n          \"width\": 31,\n          \"height\": 32,\n          \"sticker\": { \"type\": \"skinCareCombAndScissors\" },\n          \"id\": \"978989fd-7e0a-4b34-b138-e9dd089c7a8e\",\n          \"type\": \"sticker\",\n          \"groupId\": \"8701c6e5-0348-4da4-949e-203edaf029d0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Night Cream</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 86,\n          \"height\": 17,\n          \"id\": \"f830d245-8818-4f9b-b1af-348c53cba8e1\",\n          \"x\": 169,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"16de95b7-85b5-44ba-bea7-39fe77f7ff40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 199,\n          \"y\": 556,\n          \"width\": 22,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"skinCareFaceIcon\" },\n          \"id\": \"de52b375-b0f0-47fb-9020-f607a1ca4bfd\",\n          \"type\": \"sticker\",\n          \"groupId\": \"16de95b7-85b5-44ba-bea7-39fe77f7ff40\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">No Grease</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"03ebbda3-8fd9-4faf-86ce-f496c2db0e36\",\n          \"x\": 289,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"3017fbbd-cc27-44e9-86b2-242e36ad0df9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 308,\n          \"y\": 556,\n          \"width\": 24,\n          \"height\": 37,\n          \"sticker\": { \"type\": \"skinCarePalmIcon\" },\n          \"id\": \"df2cf7f8-5451-462a-8620-37dc2a81c2ec\",\n          \"type\": \"sticker\",\n          \"groupId\": \"3017fbbd-cc27-44e9-86b2-242e36ad0df9\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8e888b71-236c-4d66-add4-a75733c089fb\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"978989fd-7e0a-4b34-b138-e9dd089c7a8e\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f6af2070-5df4-4c87-8f36-70253b70607e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"aeaacb7c-b025-4c98-848d-36d485a2b102\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0836cf70-f178-407e-ad12-392259b8818e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"de52b375-b0f0-47fb-9020-f607a1ca4bfd\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"b63e351f-4bb4-4b74-9c86-b4d1734993e4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f830d245-8818-4f9b-b1af-348c53cba8e1\"],\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"3a272761-dddd-485e-8f63-5a2729fe2395\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"df2cf7f8-5451-462a-8620-37dc2a81c2ec\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"237034ff-26c7-480f-9dcd-428b5177df33\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"03ebbda3-8fd9-4faf-86ce-f496c2db0e36\"],\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"ec8a8b3d-136a-4b65-9df3-4bf939cf27fd\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e37ccb07-36b3-4feb-a64b-7f90cc5d25d6\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 205, \"g\": 204, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"d3d1cfdd-f4bb-4f74-8130-becc36a103c9\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8701c6e5-0348-4da4-949e-203edaf029d0\": {\n          \"name\": \"Comb\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"16de95b7-85b5-44ba-bea7-39fe77f7ff40\": {\n          \"name\": \"Towel\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3017fbbd-cc27-44e9-86b2-242e36ad0df9\": {\n          \"name\": \"Palm\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"47734154-b827-401e-a029-d7035ec3e5fb\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"c398b032-fea3-4dc4-9ebe-537ef635962b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 174,\n          \"focalX\": 29.853128991060025,\n          \"focalY\": 41.07253086419752,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:20:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page5_img1.jpg\",\n            \"width\": 754,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman with pink lipstick\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#ebb79b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 139,\n          \"width\": 412,\n          \"height\": 536,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"aa4538da-d4dc-4f02-a221-e6215bbeac0c\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">The </span><span style=\\\"font-weight: 700; color: #380e63; text-transform: uppercase\\\">Clarifying </span><span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">Facial</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 36,\n          \"width\": 332,\n          \"height\": 74,\n          \"id\": \"30f16ec0-db2c-4adb-b846-a3920099c08d\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 85,\n          \"height\": 17,\n          \"id\": \"f52ac2b0-f68d-4a1f-bf2a-8bef820eb161\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f182bae7-7f64-411b-8c01-a5d38bf0147c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"aa4538da-d4dc-4f02-a221-e6215bbeac0c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 224, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"30930adf-03dc-4b6a-8fef-60445bdfef71\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6af2abfd-3e9d-4859-bbb4-7e14f95dc830\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:21:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page6_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 810,\n            \"id\": 0,\n            \"alt\": \"Person holding pink rose flowers and perfume bottle\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c0b0ad\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"051a386b-30bb-4db3-bf9e-40830e1000fb\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Carrot Seed Facial Oil</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 385,\n          \"width\": 316,\n          \"height\": 30,\n          \"id\": \"5968e701-5359-4a87-b8a7-3f4ef4d25705\",\n          \"type\": \"text\",\n          \"groupId\": \"e0e86fe6-3c8d-4137-9503-225519ff84af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">A lightweight, healing vitamin boost that deeply nourishes and reinforces the skin's barrier.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 72,\n          \"id\": \"386d793e-6748-430a-a247-06a0b85cd84a\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"e0e86fe6-3c8d-4137-9503-225519ff84af\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"599a5d85-ad8b-45cc-98a3-bf95462fed35\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 47,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"skinCareFlower\" },\n          \"id\": \"8e615ea4-3113-4abe-a1bc-46ecd1c51c2a\",\n          \"x\": 63,\n          \"y\": 562,\n          \"type\": \"sticker\",\n          \"groupId\": \"f4a089fe-b89d-4d3d-9cc7-5f425bef388d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Floral</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 41,\n          \"height\": 17,\n          \"id\": \"c0a0292e-f21d-4b57-bc74-13ebd9f0257a\",\n          \"x\": 69,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"f4a089fe-b89d-4d3d-9cc7-5f425bef388d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 54,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"skinCareSleepMask\" },\n          \"id\": \"f5ce94a5-d36f-46d1-96ee-218dd72b39cc\",\n          \"x\": 170,\n          \"y\": 567,\n          \"type\": \"sticker\",\n          \"groupId\": \"fa87c9f1-aac8-430d-89e0-7ce96e061470\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Fine Line</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 62,\n          \"height\": 17,\n          \"id\": \"ea499eb0-4ee0-4547-a1e4-8b9face6d5f3\",\n          \"x\": 170,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"fa87c9f1-aac8-430d-89e0-7ce96e061470\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 30,\n          \"height\": 34,\n          \"sticker\": { \"type\": \"skinCareFaceWashBottles\" },\n          \"id\": \"48848644-9ca4-4685-9d41-964c079e8a42\",\n          \"x\": 301,\n          \"y\": 560,\n          \"type\": \"sticker\",\n          \"groupId\": \"65b34c51-fad9-4f98-be3f-c2fa3c35655a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Brightening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"32e700c0-59b2-47fa-bd72-110c8950c3b9\",\n          \"x\": 278,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"65b34c51-fad9-4f98-be3f-c2fa3c35655a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"8e615ea4-3113-4abe-a1bc-46ecd1c51c2a\"],\n          \"id\": \"3d49ed0a-91ed-44ac-86b8-680f8fc8228e\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"c0a0292e-f21d-4b57-bc74-13ebd9f0257a\"],\n          \"id\": \"9bd4ab4c-0b9d-4255-ac96-b7d7d4643454\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"f5ce94a5-d36f-46d1-96ee-218dd72b39cc\"],\n          \"id\": \"f31bf83d-4ea7-4d1b-a48b-944245cd7765\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"ea499eb0-4ee0-4547-a1e4-8b9face6d5f3\"],\n          \"id\": \"3c590950-829d-4513-99e8-1a71f71819c2\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"48848644-9ca4-4685-9d41-964c079e8a42\"],\n          \"id\": \"03cc193e-a379-4c98-86a0-65bc1e7d5f0f\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"32e700c0-59b2-47fa-bd72-110c8950c3b9\"],\n          \"id\": \"0eb41c2d-5834-4b3c-aaf9-204602b699ee\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"ea0dae5a-2545-44a6-bd87-fe3635882d9b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"051a386b-30bb-4db3-bf9e-40830e1000fb\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 224, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"b0a17975-50ed-4942-a231-fac486b74e4c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e0e86fe6-3c8d-4137-9503-225519ff84af\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f4a089fe-b89d-4d3d-9cc7-5f425bef388d\": {\n          \"name\": \"Floral\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"fa87c9f1-aac8-430d-89e0-7ce96e061470\": {\n          \"name\": \"Fine\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"65b34c51-fad9-4f98-be3f-c2fa3c35655a\": {\n          \"name\": \"Bright\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"ec4153a3-82f6-40b8-b6ef-76684f94986d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:21:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Bottle of beauty oil and big green leaf\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#486b19\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"370b22bc-c88d-4347-861b-0de14fc61e81\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Avocado, Poppy Seed Oil</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 385,\n          \"width\": 316,\n          \"height\": 30,\n          \"id\": \"ade4fb0a-ae1e-4810-b0c4-d6df7be0e768\",\n          \"type\": \"text\",\n          \"groupId\": \"0886179e-b185-4e7e-8842-b773484993df\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">Look for a seed oil that is targeted at clearing out impurities in the skin, especially when used with a clarifying cleanser.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 316,\n          \"height\": 97,\n          \"id\": \"32890e1e-7df2-4a8e-b7c9-3f637f1a5dc4\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"0886179e-b185-4e7e-8842-b773484993df\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1337c3bb-be57-4909-85a0-edd39af32cb8\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Hair Friendly</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 87,\n          \"height\": 17,\n          \"id\": \"b3700257-de62-4a6c-9628-c0a710d09194\",\n          \"x\": 47,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"ab49d554-690a-4328-84db-781ca9da9730\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 31,\n          \"height\": 32,\n          \"sticker\": { \"type\": \"skinCareCombAndScissors\" },\n          \"id\": \"151343f1-87de-4d35-b899-e04ac77250ca\",\n          \"x\": 73,\n          \"y\": 555,\n          \"type\": \"sticker\",\n          \"groupId\": \"ab49d554-690a-4328-84db-781ca9da9730\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Night Cream</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 86,\n          \"height\": 17,\n          \"id\": \"783ed25c-fa78-4955-9a32-60e4644b31e0\",\n          \"x\": 169,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"aeaaeaeb-9b0a-4756-93a6-c14109f23e54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 22,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"skinCareFaceIcon\" },\n          \"id\": \"11ff418c-29d0-4829-8519-517a7af5b8ff\",\n          \"x\": 199,\n          \"y\": 556,\n          \"type\": \"sticker\",\n          \"groupId\": \"aeaaeaeb-9b0a-4756-93a6-c14109f23e54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">No Grease</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"053dc788-623e-460c-a83c-0dd6389b76b7\",\n          \"x\": 289,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"b17a3386-b3fd-49f2-8396-6bad6e54cf52\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 24,\n          \"height\": 37,\n          \"sticker\": { \"type\": \"skinCarePalmIcon\" },\n          \"id\": \"b19c86d0-db83-4c49-9392-cc240d8ba2d9\",\n          \"x\": 308,\n          \"y\": 556,\n          \"type\": \"sticker\",\n          \"groupId\": \"b17a3386-b3fd-49f2-8396-6bad6e54cf52\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"b3700257-de62-4a6c-9628-c0a710d09194\"],\n          \"id\": \"ac693e6e-1777-43e5-adce-a6e3a346a84e\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"783ed25c-fa78-4955-9a32-60e4644b31e0\"],\n          \"id\": \"6195fc10-377f-4937-bd30-b13472b8ac9d\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"053dc788-623e-460c-a83c-0dd6389b76b7\"],\n          \"id\": \"90372ad4-7dcb-4f16-bb65-5c2eab75fdcc\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"151343f1-87de-4d35-b899-e04ac77250ca\"],\n          \"id\": \"a9369602-a194-4fd4-ac62-ae0039578cac\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"11ff418c-29d0-4829-8519-517a7af5b8ff\"],\n          \"id\": \"3b24f38d-3c7f-4318-97d9-313051b34b1e\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"b19c86d0-db83-4c49-9392-cc240d8ba2d9\"],\n          \"id\": \"9a3a601c-651f-4aa7-8737-02eb0eec76f5\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"84b177b0-37e3-4005-b359-955b452b5cf0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"370b22bc-c88d-4347-861b-0de14fc61e81\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 224, \"b\": 243 } },\n      \"type\": \"page\",\n      \"id\": \"7244f52a-0b7c-41ec-8d53-c22ff9f74794\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0886179e-b185-4e7e-8842-b773484993df\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ab49d554-690a-4328-84db-781ca9da9730\": {\n          \"name\": \"Comb\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aeaaeaeb-9b0a-4756-93a6-c14109f23e54\": {\n          \"name\": \"Towel\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b17a3386-b3fd-49f2-8396-6bad6e54cf52\": {\n          \"name\": \"Palm\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"788bfd80-4a2d-455c-a2a8-7d8eb4312cea\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:22:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page8_img1.jpg\",\n            \"width\": 721,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman's face\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#e0b3a3\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 139,\n          \"width\": 412,\n          \"height\": 536,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e36de93b-45c2-40f7-ac58-db67fcdca986\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">THE </span><span style=\\\"font-weight: 700; color: #380e63\\\">CALMING </span><span style=\\\"font-weight: 300; color: #380e63\\\">FACIAL</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 36,\n          \"width\": 308,\n          \"height\": 73,\n          \"id\": \"d1e84cd8-8339-4b14-8e6b-c6e1e40ff020\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 85,\n          \"height\": 17,\n          \"id\": \"0a0083ec-730a-4d3d-8890-a3a1dd8853cb\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5566de09-d1b5-4f5f-9947-bde98a4b0d0b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e36de93b-45c2-40f7-ac58-db67fcdca986\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 229, \"b\": 204 } },\n      \"type\": \"page\",\n      \"id\": \"98f2de84-f6c6-4a7b-a7a3-6f2f2005c075\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"5ede7937-6b71-4e0c-b5a5-366e3dc71369\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 145,\n          \"focalX\": 51.04452874888204,\n          \"focalY\": 48.824905157507715,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:22:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page9_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Cosmetic bottle placed near fresh green leaves\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#ced1b6\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"551a54fb-7068-4f57-99aa-72f80e98d056\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Water-Lock Moisturizer</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 385,\n          \"width\": 316,\n          \"height\": 30,\n          \"id\": \"79c362e0-f8a4-408d-a277-e3c782993bda\",\n          \"type\": \"text\",\n          \"groupId\": \"2ca2151c-0c47-4df6-96d1-cc0139b3ffc3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">Hydrate more and waste less with this refillable, lightweight daily moisturizer.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 322,\n          \"height\": 47,\n          \"id\": \"433e728d-112c-410f-a705-0265af338161\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"2ca2151c-0c47-4df6-96d1-cc0139b3ffc3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d6bcb9d6-ee73-4dce-94d0-b34bff00c976\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 47,\n          \"height\": 31,\n          \"sticker\": { \"type\": \"skinCareFlower\" },\n          \"id\": \"0b58a842-52f4-4dbe-bfc0-4b4fe3739ed9\",\n          \"x\": 63,\n          \"y\": 562,\n          \"type\": \"sticker\",\n          \"groupId\": \"7578ba09-70a0-406b-984a-122903c11edd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Floral</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 41,\n          \"height\": 17,\n          \"id\": \"72851118-d2c2-4b1d-ac7d-0f956e9001c9\",\n          \"x\": 69,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"7578ba09-70a0-406b-984a-122903c11edd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 54,\n          \"height\": 21,\n          \"sticker\": { \"type\": \"skinCareSleepMask\" },\n          \"id\": \"3e3c7f42-3053-4084-a5c0-a73cacc39b22\",\n          \"x\": 170,\n          \"y\": 567,\n          \"type\": \"sticker\",\n          \"groupId\": \"48ba3f9b-382d-4c77-a036-0f41572dbef1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Fine Line</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 62,\n          \"height\": 17,\n          \"id\": \"51f893c5-3ce2-4bcc-aad7-1c10705c37c5\",\n          \"x\": 170,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"48ba3f9b-382d-4c77-a036-0f41572dbef1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 30,\n          \"height\": 34,\n          \"sticker\": { \"type\": \"skinCareFaceWashBottles\" },\n          \"id\": \"5d7a968b-62a3-48e7-9d0f-3e19fff25541\",\n          \"x\": 301,\n          \"y\": 560,\n          \"type\": \"sticker\",\n          \"groupId\": \"48ca823d-ce07-4d2a-8bc8-83993e0ee8ed\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Brightening</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"4d2d5842-69cc-4f40-b687-5ad4090c56d3\",\n          \"x\": 278,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"48ca823d-ce07-4d2a-8bc8-83993e0ee8ed\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"0b58a842-52f4-4dbe-bfc0-4b4fe3739ed9\"],\n          \"id\": \"6b704103-e4a0-4b50-9842-8dc65fbedc4f\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"72851118-d2c2-4b1d-ac7d-0f956e9001c9\"],\n          \"id\": \"1bcc92bd-50c7-49c2-81d4-1b47371364cb\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"3e3c7f42-3053-4084-a5c0-a73cacc39b22\"],\n          \"id\": \"e0f3aa9b-7c7b-4e54-9fb5-f816f55429c5\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"51f893c5-3ce2-4bcc-aad7-1c10705c37c5\"],\n          \"id\": \"7c6bad01-40e8-452b-af0e-4a9b1b73489d\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"5d7a968b-62a3-48e7-9d0f-3e19fff25541\"],\n          \"id\": \"7f67d161-b53d-477b-b961-3b2cae50d905\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"4d2d5842-69cc-4f40-b687-5ad4090c56d3\"],\n          \"id\": \"8068a005-cc67-48a3-99f6-95259e71fe3f\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"832a516b-e5d5-451b-8455-bcaeb909e5d8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"551a54fb-7068-4f57-99aa-72f80e98d056\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 229, \"b\": 204 } },\n      \"type\": \"page\",\n      \"id\": \"f7d33660-69b0-4840-806b-264519f8aee6\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2ca2151c-0c47-4df6-96d1-cc0139b3ffc3\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7578ba09-70a0-406b-984a-122903c11edd\": {\n          \"name\": \"Floral\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"48ba3f9b-382d-4c77-a036-0f41572dbef1\": {\n          \"name\": \"Fine\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"48ca823d-ce07-4d2a-8bc8-83993e0ee8ed\": {\n          \"name\": \"Bright\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"a0e8124f-2bd6-46df-9d98-02cf24c313d7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:23:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page10_img1.jpg\",\n            \"width\": 734,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Venus all mat bottle\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#9f7784\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 403,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8af3062d-a2a2-44e9-87a2-8cfb551b3d24\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Calendula Hydrating Cream</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 385,\n          \"width\": 326,\n          \"height\": 30,\n          \"id\": \"cc19b7f1-3da2-4fa5-8bd9-56e04744a29e\",\n          \"type\": \"text\",\n          \"groupId\": \"9f68a921-792f-4d8a-bbb6-2d7431e44678\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63\\\">Like a panic button for cranky skin, this moisturizer instantly soothes irritation.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 326,\n          \"height\": 47,\n          \"id\": \"dec7ecbb-2b02-4bcd-b450-2d63744f0748\",\n          \"x\": 48,\n          \"y\": 426,\n          \"type\": \"text\",\n          \"groupId\": \"9f68a921-792f-4d8a-bbb6-2d7431e44678\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 56, \"g\": 14, \"b\": 99 } },\n          \"x\": 48,\n          \"y\": 533,\n          \"width\": 318,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"13c6ad3f-553f-411d-b7dd-4f81fdc307e3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Hair Friendly</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 87,\n          \"height\": 17,\n          \"id\": \"1b074b86-3434-431e-ba1d-061d16340eb5\",\n          \"x\": 47,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"0dff1010-c026-44d1-aced-c89935385385\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 31,\n          \"height\": 32,\n          \"sticker\": { \"type\": \"skinCareCombAndScissors\" },\n          \"id\": \"7007c4c0-eea7-4370-9a30-4b6f2bd497a6\",\n          \"x\": 73,\n          \"y\": 555,\n          \"type\": \"sticker\",\n          \"groupId\": \"0dff1010-c026-44d1-aced-c89935385385\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">Night Cream</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 86,\n          \"height\": 17,\n          \"id\": \"9ebfd0c8-ba93-4558-ac18-7aff09d04b08\",\n          \"x\": 169,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"92312010-b686-460e-9487-4671b5eb46b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 22,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"skinCareFaceIcon\" },\n          \"id\": \"c69c154e-02ad-435b-9747-81a6e0a5b386\",\n          \"x\": 199,\n          \"y\": 556,\n          \"type\": \"sticker\",\n          \"groupId\": \"92312010-b686-460e-9487-4671b5eb46b4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63\\\">No Grease</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 79,\n          \"height\": 17,\n          \"id\": \"1db0e777-5220-4e03-a975-423727136da2\",\n          \"x\": 289,\n          \"y\": 602,\n          \"type\": \"text\",\n          \"groupId\": \"9f6a79e4-d42e-4c22-8a20-c4acad9dfde7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 24,\n          \"height\": 37,\n          \"sticker\": { \"type\": \"skinCarePalmIcon\" },\n          \"id\": \"3419470a-78a1-42fc-a49f-7f31ce3d6ef4\",\n          \"x\": 308,\n          \"y\": 556,\n          \"type\": \"sticker\",\n          \"groupId\": \"9f6a79e4-d42e-4c22-8a20-c4acad9dfde7\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"1b074b86-3434-431e-ba1d-061d16340eb5\"],\n          \"id\": \"2e228ceb-3d13-4b23-8ffc-2e36f06d2283\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"9ebfd0c8-ba93-4558-ac18-7aff09d04b08\"],\n          \"id\": \"f4c97203-ff22-4557-8dcc-617d53387aad\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"1db0e777-5220-4e03-a975-423727136da2\"],\n          \"id\": \"8ff4463a-8f7d-4003-984b-d89b1bdf1854\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"targets\": [\"7007c4c0-eea7-4370-9a30-4b6f2bd497a6\"],\n          \"id\": \"d19c807b-06c3-410a-99a0-fe09ad6789ae\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"targets\": [\"c69c154e-02ad-435b-9747-81a6e0a5b386\"],\n          \"id\": \"8e94a242-3720-4765-b459-51aa6614a38f\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"targets\": [\"3419470a-78a1-42fc-a49f-7f31ce3d6ef4\"],\n          \"id\": \"a02c7464-ec04-4745-b17f-3fca3df5acb4\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"519239fd-3b4e-42e1-8ef7-f0c4e586a8f1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8af3062d-a2a2-44e9-87a2-8cfb551b3d24\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 229, \"b\": 204 } },\n      \"type\": \"page\",\n      \"id\": \"ba660036-2d65-40ab-9a27-6fadd6d6f92f\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9f68a921-792f-4d8a-bbb6-2d7431e44678\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0dff1010-c026-44d1-aced-c89935385385\": {\n          \"name\": \"Comb\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"92312010-b686-460e-9487-4671b5eb46b4\": {\n          \"name\": \"Towel\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"9f6a79e4-d42e-4c22-8a20-c4acad9dfde7\": {\n          \"name\": \"Palm\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"eeeaf33f-4e6a-4355-b4e9-15e1646446e8\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 135,\n          \"focalX\": 48.35390946502058,\n          \"focalY\": 36.28257887517147,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T07:23:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/skin-care-at-home/page12_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman wearing white and red floral top across body of water photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#7e9599\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 468,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ae61164f-32c0-4a5a-b3c9-8970c9f3a66f\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 300; color: #380e63; text-transform: uppercase\\\">The Author:</span>\\n<span style=\\\"font-weight: 700; color: #380e63; text-transform: uppercase\\\">Sandra Lanshin</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 482,\n          \"width\": 323,\n          \"height\": 74,\n          \"id\": \"5dd7c73b-15ce-4c90-8060-f75345a74fba\",\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Mulish\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1005,\n              \"des\": -250,\n              \"tAsc\": 1005,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 297,\n              \"xH\": 500,\n              \"capH\": 705,\n              \"yMin\": -270,\n              \"yMax\": 1036,\n              \"hAsc\": 1005,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #380e63; text-transform: uppercase\\\">Watch next</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 443,\n          \"width\": 161,\n          \"height\": 22,\n          \"id\": \"f6139cf8-c16c-4349-b6e3-ee2318def212\",\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e158e7ca-6bf1-4d3d-9f36-b5829fbcd391\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ae61164f-32c0-4a5a-b3c9-8970c9f3a66f\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 204, \"b\": 229 } },\n      \"type\": \"page\",\n      \"id\": \"99061b91-2b6c-4ecb-9e72-4c5dcb1bfe2c\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sleep/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/sleep/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'sleep',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Sleep', 'template name', 'web-stories'),\n  tags: [\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Happiness', 'template keyword', 'web-stories'),\n    _x('Joy', 'template keyword', 'web-stories'),\n    _x('Mindfulness', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Blue', 'color', 'web-stories'),\n      color: '#1f2a2e',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Green', 'color', 'web-stories'),\n      color: '#4b5c54',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Yellow', 'color', 'web-stories'),\n      color: '#FDF5DC',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gray', 'color', 'web-stories'),\n      color: '#858280',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Gray', 'color', 'web-stories'),\n      color: '#d8d8d8',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With a warm color palette and soothing shapes, the Wellbeing template works best for web stories covering mindfulness, lifestyle health and related exercise and activities like Yoga, Spa treatments and the like.',\n    'web-stories'\n  ),\n  vertical: _x('Wellbeing', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/sleep/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sleep/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"df765066-cd07-49bf-8ef7-02ae6f2b3330\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 91,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 75, \"g\": 92, \"b\": 84 } },\n          \"type\": \"shape\",\n          \"x\": -128,\n          \"y\": 305,\n          \"width\": 540,\n          \"height\": 618,\n          \"mask\": { \"type\": \"blob-3\" },\n          \"id\": \"a413ec38-e047-4458-927f-14364d513d52\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 200,\n          \"width\": 360,\n          \"height\": 475,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 55.691190320099714,\n          \"focalY\": 45.601822039491275,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#1b1c19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page1_image1.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page1_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"8dbfe563-a930-4de7-90d7-e9681be1e98e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"shape\",\n          \"x\": -156,\n          \"y\": -81,\n          \"width\": 641,\n          \"height\": 781,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"d1783451-12c7-4e47-99a7-baebb0a45541\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 14, \"g\": 22, \"b\": 26 } },\n          \"type\": \"shape\",\n          \"x\": 164.5,\n          \"y\": 24,\n          \"width\": 83,\n          \"height\": 37,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a6c0478f-00b6-4b8a-87e1-681a29605708\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/icon_logo.png\",\n            \"width\": 38,\n            \"height\": 12,\n            \"id\": 0,\n            \"alt\": \"icon_logo\",\n            \"sizes\": [],\n            \"isExternal\": true,\n            \"baseColor\": \"#ffffff\"\n          },\n          \"type\": \"image\",\n          \"x\": 170.5,\n          \"y\": 30.5,\n          \"width\": 75,\n          \"height\": 24,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"id\": \"8b9f4705-fd93-41ad-bb6e-a47cfee940c4\"\n        },\n        {\n          \"x\": 50,\n          \"y\": 133,\n          \"width\": 313,\n          \"height\": 109,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"dd32270f-eb83-45ff-917b-edf80e86b024\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fdf5dc\\\">Sleep</span>\",\n          \"fontSize\": 110,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"80cd76d6-6c52-4892-98d7-f414dbb7619e\",\n      \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"56248b21-6e15-48fa-bc4b-ebd2163c4b6c\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n          \"type\": \"shape\",\n          \"x\": -185,\n          \"y\": 523,\n          \"width\": 679,\n          \"height\": 409,\n          \"mask\": { \"type\": \"blob-3\" },\n          \"id\": \"8d31d477-7e91-4214-b263-c72d0a726be1\",\n          \"groupId\": \"88ff01d9-2cd0-4f93-bc6b-c49dc66164f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 251, \"g\": 235, \"b\": 186, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": -220,\n          \"y\": 31,\n          \"width\": 639,\n          \"height\": 667,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"ec40785b-35e7-4572-8fd5-3bce5b898d50\",\n          \"groupId\": \"88ff01d9-2cd0-4f93-bc6b-c49dc66164f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 216, \"g\": 216, \"b\": 216 } },\n          \"type\": \"shape\",\n          \"x\": -121,\n          \"y\": -71,\n          \"width\": 685,\n          \"height\": 687,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"741aeabf-40d3-4f1b-8ff0-0e9d72639718\",\n          \"groupId\": \"88ff01d9-2cd0-4f93-bc6b-c49dc66164f1\"\n        },\n        {\n          \"x\": 187,\n          \"y\": 83,\n          \"width\": 38,\n          \"height\": 117,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"6977e93f-f8f3-40ee-ba03-40a671211636\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2b393e\\\">“</span>\",\n          \"fontSize\": 90,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 131,\n          \"y\": 383,\n          \"width\": 150,\n          \"height\": 38,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"643dd508-0499-4c8e-adab-b48039c98296\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1); text-transform: uppercase\\\">-</span>\\n<span style=\\\"color: rgba(43, 57, 62, 1); text-transform: uppercase\\\">Dalai Lama</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 72,\n          \"y\": 183,\n          \"width\": 269,\n          \"height\": 171,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"fbe0221c-732c-40ac-83e9-3c982aef987a\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #2b393e\\\">Sleep</span>\\n<span style=\\\"font-weight: 300\\\">is the best</span>\\n<span style=\\\"font-weight: 300\\\">meditation</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7a2f3891-9118-408c-b00e-f5d4592119e7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6977e93f-f8f3-40ee-ba03-40a671211636\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e1e21b15-9a11-4758-aa57-1cad12353da2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fbe0221c-732c-40ac-83e9-3c982aef987a\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"27ee3963-f352-4a8c-b9f7-b46192165497\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"643dd508-0499-4c8e-adab-b48039c98296\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 200\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e96638f8-1f19-4f34-b7e6-963329aa12fd\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"88ff01d9-2cd0-4f93-bc6b-c49dc66164f1\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 89,\n          \"y\": 84,\n          \"width\": 137,\n          \"height\": 137,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c6e37b7e-ddb8-4028-a66f-dd280351af00\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 413,\n          \"height\": 453,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 36.16674990819293,\n          \"focalY\": 57.85050694492415,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"65e8ce0b-d522-4ca2-89e1-d2cca7752934\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#ac9e90\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page3_bg.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page3_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 63,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 75, \"g\": 92, \"b\": 84 } },\n          \"type\": \"shape\",\n          \"x\": -45,\n          \"y\": 231,\n          \"width\": 532,\n          \"height\": 521,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"89b87d99-5afb-46bd-a3aa-14225f858bac\",\n          \"groupId\": \"7fda65e6-f078-4d1a-bc06-31d689917f9f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 251, \"g\": 235, \"b\": 186, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": 264,\n          \"y\": 255,\n          \"width\": 403,\n          \"height\": 283,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"f48c6b69-fb61-4c9f-aee3-2155a28eda0b\",\n          \"groupId\": \"7fda65e6-f078-4d1a-bc06-31d689917f9f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 287,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": -217,\n          \"y\": 178,\n          \"width\": 621,\n          \"height\": 723,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"1d881f00-3727-4531-ba0a-3d6d3459dc8e\",\n          \"groupId\": \"7fda65e6-f078-4d1a-bc06-31d689917f9f\"\n        },\n        {\n          \"x\": 38,\n          \"y\": 444,\n          \"width\": 319,\n          \"height\": 76,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e4b371be-6204-493b-be2d-a94a93a0649b\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\">1 in 3 adults don’t get enough sleep. This trend poses many health risks. Studies and reports link lack of sleep to depression, ADHD and more.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 38,\n          \"y\": 581,\n          \"width\": 94,\n          \"height\": 16,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a05c550f-a6fd-453c-a498-7c0840c74e80\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 38,\n          \"y\": 386,\n          \"width\": 226,\n          \"height\": 54,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"16874f25-165a-4633-90b6-61c465d9b868\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fdf5dc\\\">Can't sleep?</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 135,\n          \"y\": 582,\n          \"width\": 240,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"wellbeingArrowLight\" },\n          \"id\": \"f3e299f2-dbf8-41ae-8163-6288e0e38cec\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a5c3616f-a4ba-416a-a770-d811ab5b6a28\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16874f25-165a-4633-90b6-61c465d9b868\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"f2abb87c-4a4a-4244-9e89-6942bc736ae5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e4b371be-6204-493b-be2d-a94a93a0649b\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 100\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"e6b3eacb-1032-4965-8e57-efe5dbe8b1b7\",\n      \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"7fda65e6-f078-4d1a-bc06-31d689917f9f\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 71,\n          \"y\": 77,\n          \"width\": 206,\n          \"height\": 366,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 130,\n          \"focalX\": 50.01420476860542,\n          \"focalY\": 49.97767879474251,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#22201c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page4_bg.jpg\",\n            \"width\": 220,\n            \"height\": 391,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"7744e075-8030-462f-bdd5-15dc4f1ab97d\",\n          \"isBackground\": true,\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 57,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n          \"type\": \"shape\",\n          \"x\": -16,\n          \"y\": -292,\n          \"width\": 478,\n          \"height\": 467,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"414d5315-c8a7-40d3-aebb-1d0362eeea9b\"\n        },\n        {\n          \"x\": 58,\n          \"y\": 0,\n          \"width\": 297,\n          \"height\": 158,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"c9c064f6-310e-4d41-b85d-0be6fedc9ea4\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fdf5dc\\\">Aroma Therapy</span>\",\n          \"fontSize\": 79,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 247,\n          \"y\": 286,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"wellbeingCTA\" },\n          \"id\": \"92fe983c-5bfc-45ab-9044-0649ca535a34\",\n          \"link\": {\n            \"url\": \"https://example.com/\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 295,\n          \"y\": 428,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"wellbeingCTA\" },\n          \"id\": \"d3b28784-2312-46d3-93a5-b79af788fd1f\",\n          \"link\": {\n            \"url\": \"https://example.com/\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 56,\n          \"y\": 460,\n          \"width\": 60,\n          \"height\": 60,\n          \"sticker\": { \"type\": \"wellbeingCTA\" },\n          \"id\": \"44f8688f-7588-4c4c-9599-7fdf77cbe010\",\n          \"link\": {\n            \"url\": \"https://example.com/\",\n            \"icon\": null,\n            \"desc\": \"Example Domain\"\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4b159c79-36b7-462a-88b7-b6d61d338c40\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"d3b28784-2312-46d3-93a5-b79af788fd1f\"],\n          \"scale\": 0.05,\n          \"iterations\": 2,\n          \"duration\": 2000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"9de702c5-1445-43d4-9f17-f1856e393ad1\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"92fe983c-5bfc-45ab-9044-0649ca535a34\"],\n          \"scale\": 0.05,\n          \"iterations\": 2,\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"94bec456-cebf-4b72-bb75-61c6fca05a62\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"44f8688f-7588-4c4c-9599-7fdf77cbe010\"],\n          \"scale\": 0.05,\n          \"iterations\": 2,\n          \"duration\": 2000,\n          \"delay\": 50\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"0fd64689-3e15-4e91-b9b3-d991204703b1\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"e4224ca8-e130-44df-a647-57d7a6dba4f4\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"970e7f88-c07d-4a78-81f9-e66bd4b2bebe\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 115,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 251, \"g\": 235, \"b\": 186, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": -75,\n          \"y\": 21,\n          \"width\": 615,\n          \"height\": 585,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"08a9f14d-e04a-4e73-8c33-ba3baba83813\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 238,\n          \"width\": 360,\n          \"height\": 437,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#262d2d\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page5_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page5_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"e5936b3b-e398-4cdd-a2f5-91128b4c10b9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 306,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"shape\",\n          \"x\": -69,\n          \"y\": 115,\n          \"width\": 512,\n          \"height\": 658,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"83bb4834-fe9a-4cd9-9b51-4a2b33d42f13\"\n        },\n        {\n          \"x\": 35,\n          \"y\": 128,\n          \"width\": 338,\n          \"height\": 57,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7db74862-4e63-4403-b085-eced23113392\",\n          \"content\": \"<span style=\\\"color: rgba(31, 42, 46, 1)\\\">Put your phone down and put this smart eye mask on. Heat regulating and soothing, this mask will put you right to sleep.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 35,\n          \"y\": 71,\n          \"width\": 201,\n          \"height\": 54,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"456cb303-7b53-4844-8ecf-7a07e8c267b9\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">Sleep Tech</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 38,\n          \"y\": 20,\n          \"width\": 94,\n          \"height\": 16,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"4a6f10ee-b868-4ec8-80c3-7968bede7d8d\",\n          \"content\": \"<span style=\\\"color: rgba(31, 42, 46, 1); text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 133,\n          \"y\": 20,\n          \"width\": 240,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"wellbeingArrowDark\" },\n          \"id\": \"b1686168-2d10-467f-aa35-911a79c2bae2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ed7f87e1-1ad7-45fa-bb11-2f253e1203b5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"456cb303-7b53-4844-8ecf-7a07e8c267b9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"4ff90627-f9c7-407e-af2a-f6d7b22e72f9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7db74862-4e63-4403-b085-eced23113392\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"1a57cf2b-d1d0-432c-8b97-3794c41e2098\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 95,\n          \"y\": 110,\n          \"width\": 206,\n          \"height\": 309,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#5b6361\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page6_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"4aac4002-7c41-434c-ab44-7bc43f6e863c\",\n          \"isBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 354,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 75, \"g\": 92, \"b\": 84 } },\n          \"type\": \"shape\",\n          \"x\": 36,\n          \"y\": 379,\n          \"width\": 530,\n          \"height\": 495,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"dc2f00ab-bacf-4593-a6a0-e24b777c116b\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 445,\n          \"width\": 360,\n          \"height\": 155,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"2dd45145-0aa5-442c-b900-9b49e454c0a2\"\n        },\n        {\n          \"x\": 53,\n          \"y\": 469,\n          \"width\": 250,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"561628d6-e00a-473d-8fe8-bc7fea38b5ff\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">Relax in a bath</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 53,\n          \"y\": 513,\n          \"width\": 286,\n          \"height\": 57,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"f496cd2f-5ffc-400c-b567-18478e0d1e89\",\n          \"content\": \"<span style=\\\"color: rgba(31, 42, 46, 1)\\\">A study found that taking a hot bath about 90 minutes before bed could help people fall asleep more quickly.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 245,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 22,\n          \"y\": 394,\n          \"width\": 373,\n          \"height\": 475,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"0aa52870-b073-41b1-888a-accd81a375e2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fcae05ab-a71a-4fa9-a09d-06d5d88f82a6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"561628d6-e00a-473d-8fe8-bc7fea38b5ff\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"08304ce2-ed9d-4d80-b523-4f6362adbc87\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f496cd2f-5ffc-400c-b567-18478e0d1e89\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 450\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"41d961c4-f7af-4d93-a9a1-94bc28287078\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"aceee55e-9440-4b53-90b7-4480bb1722ee\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 70,\n          \"y\": 2,\n          \"width\": 206,\n          \"height\": 274,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 140,\n          \"focalX\": 73.25925470564026,\n          \"focalY\": 58.0575453206811,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#484543\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page7_bg.jpg\",\n            \"width\": 220,\n            \"height\": 293,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_bg\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1\n          },\n          \"type\": \"image\",\n          \"id\": \"f8dca448-520e-4b47-a0ee-f3aea1cd2e3d\",\n          \"isBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 75, \"g\": 92, \"b\": 84 } },\n          \"type\": \"shape\",\n          \"x\": -211,\n          \"y\": -130,\n          \"width\": 577,\n          \"height\": 577,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"9b7290b8-f166-4e38-8213-97abb1c96ad6\",\n          \"groupId\": \"074e2685-7611-45fb-9e1c-0341fe20581a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 314,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": -52,\n          \"y\": -139,\n          \"width\": 569,\n          \"height\": 733,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"85a31443-3c26-4c04-9123-c4d86b83e1f0\",\n          \"groupId\": \"074e2685-7611-45fb-9e1c-0341fe20581a\"\n        },\n        {\n          \"x\": 144,\n          \"y\": 20,\n          \"width\": 150,\n          \"height\": 249,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.83,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"58899538-5ad3-4697-9fb5-bf32e92a4d0a\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fbebba\\\">5</span>\",\n          \"fontSize\": 300,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 64,\n          \"y\": 287,\n          \"width\": 284,\n          \"height\": 108,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"ceda6811-72ee-421e-9778-5711edabdfc3\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fbebba\\\">Bedtime</span>\\n<span style=\\\"font-weight: 300; color: #fbebba\\\">Routine Tips</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8aabf9fa-b7e5-4c40-a0b2-5e470d3b8ee9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ceda6811-72ee-421e-9778-5711edabdfc3\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"a7e203f2-0540-4ee6-8e0d-3640d39114a7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"58899538-5ad3-4697-9fb5-bf32e92a4d0a\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"b96f282e-4b4e-465d-a2ec-a7c904c3e5d8\",\n      \"defaultBackgroundElement\": {\n        \"type\": \"shape\",\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"rotationAngle\": 0,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"backgroundColor\": {\n          \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 }\n        },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"fadc0093-2969-4c68-a93a-443622c08d81\"\n      },\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 1 } },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"074e2685-7611-45fb-9e1c-0341fe20581a\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"18d986e5-e023-466d-b8fc-fce0393071b0\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 99,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 75, \"g\": 92, \"b\": 84 } },\n          \"type\": \"shape\",\n          \"x\": 55,\n          \"y\": -296,\n          \"width\": 443,\n          \"height\": 653,\n          \"mask\": { \"type\": \"blob-3\" },\n          \"id\": \"2694e032-b61e-4adc-97a2-a97f128c88e6\"\n        },\n        {\n          \"x\": 26,\n          \"y\": -57,\n          \"width\": 360,\n          \"height\": 452,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 57.1386688259285,\n          \"focalY\": 47.773251549578646,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#d7d4d9\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page8_image1.jpg\",\n            \"width\": 220,\n            \"height\": 220,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"a406280f-9a0b-4140-83fb-e9cac472886f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 263,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 251, \"g\": 235, \"b\": 186, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": 242,\n          \"y\": 170,\n          \"width\": 230,\n          \"height\": 249,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"f6ced1c2-1877-4093-a039-a8deacce21ea\",\n          \"groupId\": \"5594783d-8cb4-4ca3-b6e1-ba6a2f3550e1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 27,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": -128,\n          \"y\": -296,\n          \"width\": 524,\n          \"height\": 650,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"4fe9f1f6-d2dd-491a-90a1-a0ff485c735f\",\n          \"groupId\": \"5594783d-8cb4-4ca3-b6e1-ba6a2f3550e1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 6,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"width\": 315,\n          \"height\": 331,\n          \"mask\": { \"type\": \"blob-6\" },\n          \"id\": \"fed8726d-5c7d-4110-ba07-c436be00523b\",\n          \"x\": 208,\n          \"y\": 545,\n          \"groupId\": \"5594783d-8cb4-4ca3-b6e1-ba6a2f3550e1\"\n        },\n        {\n          \"x\": 38,\n          \"y\": 581,\n          \"width\": 94,\n          \"height\": 16,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"91d4d005-9a56-49d2-8e72-053ef3fa83c3\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1); text-transform: uppercase\\\">Learn More</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 112,\n          \"y\": 484,\n          \"width\": 274,\n          \"height\": 57,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"c832531d-efa9-455f-9cb3-6d9669392c02\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Improved flexibility, more strength, better concentration, improved posture are all benefits of yoga.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 112,\n          \"y\": 427,\n          \"width\": 124,\n          \"height\": 54,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"d9ed4ad5-3559-413c-a7b4-c9e264111621\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fbebba\\\">Yoga</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 26,\n          \"y\": 418,\n          \"width\": 69,\n          \"height\": 132,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"4438e06a-84e8-4ff5-95a5-60979c6f5f49\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fbebba\\\">3</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 135,\n          \"y\": 582,\n          \"width\": 240,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"wellbeingArrowLight\" },\n          \"id\": \"9e36fe4f-00c1-42eb-b613-9e8c31be8eca\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"db99202c-384e-4ba0-9638-2514b362f9fc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d9ed4ad5-3559-413c-a7b4-c9e264111621\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"f60d31e6-df15-46b8-92cd-61c5534ca72c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c832531d-efa9-455f-9cb3-6d9669392c02\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 100\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"a3dd6d21-4f75-4d8a-bacb-ef9d14f61503\",\n      \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"5594783d-8cb4-4ca3-b6e1-ba6a2f3550e1\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d982e67d-6773-46a8-81db-fb99f0ee69a1\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 69,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 245, \"b\": 220 } },\n          \"type\": \"shape\",\n          \"x\": -244,\n          \"y\": 63,\n          \"width\": 842,\n          \"height\": 842,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"1156e7c9-c922-46f0-b484-65e141757c02\",\n          \"groupId\": \"652808df-22da-4c3d-a3e0-ee34fe2bbd25\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 7,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 31, \"g\": 42, \"b\": 46 } },\n          \"type\": \"shape\",\n          \"x\": 205,\n          \"y\": 571,\n          \"width\": 261,\n          \"height\": 261,\n          \"mask\": { \"type\": \"blob-2\" },\n          \"id\": \"ca831afb-f22f-491a-aaf1-ace1e3423d64\",\n          \"groupId\": \"652808df-22da-4c3d-a3e0-ee34fe2bbd25\"\n        },\n        {\n          \"x\": 45,\n          \"y\": 14,\n          \"width\": 322,\n          \"height\": 138,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"e34fa932-2407-4d18-8586-e08e1f0d360f\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">Top 4</span>\\n<span style=\\\"font-weight: 300\\\">wellness retreats</span>\\n<span style=\\\"font-weight: 300\\\">in the world</span>\",\n          \"fontSize\": 42,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 315,\n          \"y\": 449,\n          \"width\": 65,\n          \"height\": 132,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"7404bfb0-bd86-4b76-8dbb-37fa50a28dfe\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">4</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"24a6583e-5002-42ed-aa76-40bea8cc6a18\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 485,\n          \"width\": 169,\n          \"height\": 34,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"6398137c-148c-4469-b521-f3db9fd40b5d\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Six Senses Douro Valley,\\nPortugal</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"24a6583e-5002-42ed-aa76-40bea8cc6a18\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 314,\n          \"y\": 255,\n          \"width\": 63,\n          \"height\": 132,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"e02c6ab4-de7d-437d-b2b9-271b7de9b64b\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">2</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"311afe47-563f-4e56-94e9-5f932fd8d018\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 126,\n          \"y\": 292,\n          \"width\": 169,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"e33ab4b1-8411-42c7-a407-b2d85756ff6f\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Aro Ha, Glenorchy,\\nNew Zealand</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"311afe47-563f-4e56-94e9-5f932fd8d018\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 158,\n          \"width\": 66,\n          \"height\": 132,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"7d7706a3-01b2-4bcd-8799-e18119b4c17d\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">1</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d2e4a7ff-a799-4fe0-9b90-d78d40e0a754\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 120,\n          \"y\": 202,\n          \"width\": 169,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"8d0b43ae-5979-4cb2-8b12-524929fe7d9a\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Kamalaya, Koh Samui,\\nThailand</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"d2e4a7ff-a799-4fe0-9b90-d78d40e0a754\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 352,\n          \"width\": 66,\n          \"height\": 132,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"4038789a-8b44-4d77-b5dd-592a1e247933\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">3</span>\",\n          \"fontSize\": 132,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"909d6039-a44d-47ed-95b7-778d84ff13fc\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 121,\n          \"y\": 387,\n          \"width\": 169,\n          \"height\": 33,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a314d206-0252-40f6-84f4-75b84138df1b\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Amanpuri, Phuket,\\nThailand</span>\",\n          \"fontSize\": 13,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"909d6039-a44d-47ed-95b7-778d84ff13fc\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8fecadf1-9687-437b-a612-7e983ba5a4c6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"8d0b43ae-5979-4cb2-8b12-524929fe7d9a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"fc1cf68b-978b-4198-8e35-4ca311e3bfe4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e33ab4b1-8411-42c7-a407-b2d85756ff6f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"28af5653-66d0-4c34-b972-8b20b6d3507f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a314d206-0252-40f6-84f4-75b84138df1b\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"b5408ced-6361-4897-ae2c-f22289fd8b18\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6398137c-148c-4469-b521-f3db9fd40b5d\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 800\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"d17e5002-9a42-41ea-a7fc-c2fddc7b58e6\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"652808df-22da-4c3d-a3e0-ee34fe2bbd25\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"d2e4a7ff-a799-4fe0-9b90-d78d40e0a754\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"311afe47-563f-4e56-94e9-5f932fd8d018\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"909d6039-a44d-47ed-95b7-778d84ff13fc\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"24a6583e-5002-42ed-aa76-40bea8cc6a18\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"fd455062-8efd-4332-ab36-5b66742ce5a1\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 221,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 245, \"b\": 220 } },\n          \"type\": \"shape\",\n          \"x\": -24,\n          \"y\": -163,\n          \"width\": 563,\n          \"height\": 397,\n          \"mask\": { \"type\": \"blob-4\" },\n          \"id\": \"909339b8-8ec5-4997-a7e6-688504be7f23\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 115,\n          \"width\": 108,\n          \"height\": 108,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.728870219890965,\n          \"focalY\": 43.5860062048976,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"20ab13c0-b782-40f7-8700-a99d9b56008c\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#e2e2e1\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page10_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image1\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"17085809-a0db-4a0b-9a11-967585ca39ea\"\n        },\n        {\n          \"x\": 169,\n          \"y\": 150,\n          \"width\": 169,\n          \"height\": 38,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e59766e5-94cd-4a5d-92c3-010f9b5f85ff\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">10 Ways to bring the outdoors inside.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"17085809-a0db-4a0b-9a11-967585ca39ea\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 242,\n          \"width\": 108,\n          \"height\": 108,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-30T20:23:34\",\n            \"baseColor\": \"#bbada7\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page10_image2.jpg\",\n            \"width\": 330,\n            \"height\": 494,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image2\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"70006d51-6f37-47b4-9074-b193a473caab\",\n          \"groupId\": \"767f9281-3430-4d09-b4d3-9c09805ae0e6\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 278,\n          \"width\": 206,\n          \"height\": 38,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7ac7ca60-c164-4860-8ea5-837ee07d47b0\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Is snoozing with your pets bad for your health?</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"767f9281-3430-4d09-b4d3-9c09805ae0e6\"\n        },\n        {\n          \"x\": 33,\n          \"y\": 369,\n          \"width\": 108,\n          \"height\": 108,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 220,\n          \"focalX\": 73.03206862786772,\n          \"focalY\": 44.169096549906904,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"baseColor\": \"#c9a68c\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page10_image3.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image3\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"id\": \"46172f61-dfd3-4105-a3b3-9e6b95e32a4c\",\n          \"groupId\": \"93f58f04-66fa-4777-8e70-e161b749fd1f\"\n        },\n        {\n          \"x\": 170,\n          \"y\": 406,\n          \"width\": 191,\n          \"height\": 38,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ad0ab4b9-9b87-4624-bfa8-45779fe6cf78\",\n          \"content\": \"<span style=\\\"color: rgba(43, 57, 62, 1)\\\">Perfect supplement for home-made granola.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"93f58f04-66fa-4777-8e70-e161b749fd1f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"type\": \"image\",\n          \"x\": 33,\n          \"y\": 497,\n          \"width\": 108,\n          \"height\": 108,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b35fc13c-9f8c-4ad5-8e35-839fa4d59a50\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2020-06-23T00:45:25\",\n            \"baseColor\": \"#d6c3b8\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sleep/page10_image4.jpg\",\n            \"width\": 54,\n            \"height\": 55,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_image4\",\n            \"sizes\": [],\n            \"isExternal\": true\n          },\n          \"groupId\": \"f47e9a75-46c0-41de-84a2-d0f384aacf3d\"\n        },\n        {\n          \"width\": 191,\n          \"height\": 37,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #2b393e\\\">10 yummy snack foods that are good for you.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"64006e3b-b381-4321-90f5-b8c5e9efffe9\",\n          \"x\": 169,\n          \"y\": 533,\n          \"groupId\": \"f47e9a75-46c0-41de-84a2-d0f384aacf3d\"\n        },\n        {\n          \"x\": 50,\n          \"y\": 9,\n          \"width\": 311,\n          \"height\": 67,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"d9a1df8f-5d8a-4c1f-90ba-d63b2f720ae0\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #1f2a2e\\\">More stories</span>\",\n          \"fontSize\": 52,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8d51e968-91ae-472d-8961-6b92128a4397\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e59766e5-94cd-4a5d-92c3-010f9b5f85ff\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"96646721-8645-47d4-a2ec-3a6969aad237\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"20ab13c0-b782-40f7-8700-a99d9b56008c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"26cf4c60-7602-4f1f-89b5-0f9e6d7c4c4d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"70006d51-6f37-47b4-9074-b193a473caab\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"461bf5fa-6430-4387-9cef-9008c20ae262\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7ac7ca60-c164-4860-8ea5-837ee07d47b0\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 645\n        },\n        {\n          \"id\": \"a73fc53f-7337-4536-9b76-59dccb7843fe\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"46172f61-dfd3-4105-a3b3-9e6b95e32a4c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"5feb7845-4e60-4bc4-a5cc-077456a10586\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ad0ab4b9-9b87-4624-bfa8-45779fe6cf78\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 950\n        },\n        {\n          \"id\": \"a31308e0-ca66-44aa-a4c9-1c778b2fd8fe\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b35fc13c-9f8c-4ad5-8e35-839fa4d59a50\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1105\n        },\n        {\n          \"id\": \"3b1b9807-5665-45c3-ba88-f79123f732bb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"64006e3b-b381-4321-90f5-b8c5e9efffe9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1250\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"47783f6c-471c-427c-804e-532ace8261d1\",\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"17085809-a0db-4a0b-9a11-967585ca39ea\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"767f9281-3430-4d09-b4d3-9c09805ae0e6\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"93f58f04-66fa-4777-8e70-e161b749fd1f\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f47e9a75-46c0-41de-84a2-d0f384aacf3d\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sports-quiz/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/sports-quiz/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'sports-quiz',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Sports Quiz', 'template name', 'web-stories'),\n  tags: [\n    _x('Health & Wellness', 'template keyword', 'web-stories'),\n    _x('Quiz', 'template keyword', 'web-stories'),\n    _x('Sports', 'template keyword', 'web-stories'),\n    _x('Bold', 'template keyword', 'web-stories'),\n    _x('Violet', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Amethyst Violet', 'color', 'web-stories'),\n      color: '#442383',\n      family: _x('Purple', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mango', 'color', 'web-stories'),\n      color: '#ffcd48',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Create interactive quizzes for sports and a variety of other topics with this bold and energetic template. Just change the photos and colors to suit your style.',\n    'web-stories'\n  ),\n  vertical: _x('Health & Wellness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/sports-quiz/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sports-quiz/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"bd26e9cb-d85b-4d02-867b-8eecd9b2f145\",\n          \"scale\": 131,\n          \"focalX\": 34.792461832061065,\n          \"focalY\": 57.87213740458015,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:03:31\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page1_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Two Men Playing Basketball\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#2a2a2a\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131, \"a\": 0.7 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 110,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">The</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Bools</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"x\": 47,\n          \"y\": 146,\n          \"width\": 316,\n          \"height\": 228,\n          \"id\": \"60afc5ad-d6cd-435f-a1e1-e73404a58dcd\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 110,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: rgba(255,205,72,0.5); text-transform: uppercase\\\">Quiz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 129,\n          \"id\": \"eba1ce7d-a9c6-4909-8fe5-b6eb1c8b4999\",\n          \"x\": 47,\n          \"y\": 346,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": 520,\n          \"width\": 291,\n          \"height\": 68,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9e6c1333-5fe1-4561-b08f-550f3fa74593\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 700],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #462486; text-transform: uppercase\\\">How much do you know about the BOOLS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 534,\n          \"width\": 217,\n          \"height\": 38,\n          \"id\": \"1ac4e0a4-88ad-4fa3-81f8-7ef7dbf0c003\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131 } },\n      \"type\": \"page\",\n      \"id\": \"d16d2719-b94a-46d4-94c1-f3f863bc5b3d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"6f39febc-9740-4eef-b245-61220d8dd24f\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 338,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"7e5cdd4e-0828-4a56-a7a3-abf351443044\",\n          \"scale\": 144,\n          \"focalX\": 60.88967656893005,\n          \"focalY\": 56.94444444444443,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:04:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1106,\n            \"id\": 0,\n            \"alt\": \"People watching live NBA game at Bankers life Fieldhouse\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#201e1d\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">The Bools</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 45,\n          \"id\": \"3909d447-5608-46b0-b3dd-46903f9f93e0\",\n          \"x\": 40,\n          \"y\": 29,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffcd48\\\">One of the all time famous teams in the NBA.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 258,\n          \"height\": 49,\n          \"id\": \"30c23223-f9c6-4df9-b1b3-e7e893bba68a\",\n          \"x\": 77,\n          \"y\": 81,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 204,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: rgba(255,205,72,0.5); text-transform: uppercase\\\">Bools</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 623,\n          \"height\": 238,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"id\": \"7f053a03-f901-48ea-92f4-27cb907b929c\",\n          \"x\": -72.5,\n          \"y\": 356,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f2cd944f-9dc0-4576-b2c7-4d2c359ee41d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7f053a03-f901-48ea-92f4-27cb907b929c\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 7000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"6da0c375-68dd-455b-8872-871cf1e912e5\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"d7642b5d-8078-4300-8209-2851ee55404f\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a4941a5d-f04b-4cde-9d94-78112506f8e5\",\n          \"scale\": 150,\n          \"focalX\": 33.75,\n          \"focalY\": 34.479166666666664,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:06:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page3_11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man in Gray Sleeveless Shirt Carrying White and Brown Spalding Basketball\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#2d3536\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"rotation\": 0,\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 44,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">But how well do</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">you really know them?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 259,\n          \"height\": 182,\n          \"id\": \"079bcb76-ac3e-4ee6-a496-fcf7f2c28576\",\n          \"x\": 76,\n          \"y\": 358,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e3a4e4a0-8bd3-4acd-b9bc-5f5cf58b7a23\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"80053e48-dac4-4189-b135-b77d68038f92\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"fa525350-d6df-492f-9efc-e5da843508f4\",\n          \"type\": \"image\",\n          \"scale\": 228,\n          \"focalX\": 44.34621710526316,\n          \"focalY\": 52.604166666666664,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:07:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page4_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Men's Green and White Basketball Jersey Shirt\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c3bcb0\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffcd48\\\">Question</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 19,\n          \"id\": \"de899c0e-32af-4764-b45d-42469d746fa0\",\n          \"x\": 48,\n          \"y\": 8,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Before they were the NBA team of LA, what city did they play for?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 159,\n          \"id\": \"0b2bd510-1f52-44b8-8951-c1d94279df6c\",\n          \"x\": 48,\n          \"y\": 208,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">Dallas</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 124,\n          \"height\": 51,\n          \"id\": \"109abc6f-fb7f-4d34-8c30-c1be82012c7e\",\n          \"x\": 48,\n          \"y\": 409,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">Minneapolis</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 174,\n          \"height\": 53,\n          \"id\": \"b1637d0a-80e1-455f-bc90-59a441cf0273\",\n          \"x\": 48,\n          \"y\": 468,\n          \"type\": \"text\",\n          \"marginOffset\": -3.4375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">Kansas City</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 168,\n          \"height\": 52,\n          \"id\": \"a4da577c-f9d2-4649-94af-f59c42669aa4\",\n          \"x\": 48,\n          \"y\": 528,\n          \"type\": \"text\",\n          \"marginOffset\": -3.4375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">1 / 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 19,\n          \"id\": \"3010dda3-4dc7-4166-8f2e-fe7e23bb0d1f\",\n          \"x\": 48,\n          \"y\": 28,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"104a548b-4b45-434a-ab40-b93b39ed6f9f\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"109abc6f-fb7f-4d34-8c30-c1be82012c7e\"]\n        },\n        {\n          \"id\": \"63fefcae-e5f1-4004-a008-90f347aada5b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b1637d0a-80e1-455f-bc90-59a441cf0273\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"8cf18e32-db0b-44e2-a704-f0ef54f018e8\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a4da577c-f9d2-4649-94af-f59c42669aa4\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"89a6b466-6f0c-4d6c-8501-83759407d809\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"94e49dc9-9c6c-45b1-8484-e5132c904931\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 265,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"e1205308-24a2-4406-9875-b80ef08d4261\",\n          \"scale\": 124,\n          \"focalX\": 41.38186510603346,\n          \"focalY\": 47.22782258064516,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:08:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page5_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 869,\n            \"id\": 0,\n            \"alt\": \"North Texas Agricultural College basketball team;\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#383838\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131, \"a\": 0.6 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Minneapolis. Where the legend was born.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 305,\n          \"height\": 120,\n          \"id\": \"8eaaead2-424c-45a6-8aa5-b1d1355ca7de\",\n          \"x\": 47,\n          \"y\": 10,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffcd48\\\">The Bools got their name from the Great Bools after their move to Minnesota. It was the making of legends and legacies from then on.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 271,\n          \"height\": 127,\n          \"id\": \"b0d4c549-d150-4e0e-92eb-1c7e1e0eca3b\",\n          \"x\": 47,\n          \"y\": 487,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 115,\n          \"focalX\": 42.75939781864528,\n          \"focalY\": 50.1502141998159,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:08:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page5_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 869,\n            \"id\": 0,\n            \"alt\": \"North Texas Agricultural College basketball team;\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#ccd1cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 87,\n          \"y\": 176,\n          \"width\": 325,\n          \"height\": 265,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"59708f0e-975f-4942-91f5-9af42c159ee0\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"81380f20-5ab9-4fa6-9c00-dea13762f561\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"59708f0e-975f-4942-91f5-9af42c159ee0\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8786f381-6a72-4bae-b368-0e283b27eb9e\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"eb70964d-0a66-49dd-bf3a-807424489a58\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1d38d16c-dc8d-46ee-89ce-4a86c7bb5cba\",\n          \"scale\": 208,\n          \"focalX\": 57.32421875,\n          \"focalY\": 69.38100961538461,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:09:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page6_7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Basketball court arena photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#231c1f\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffcd48\\\">Question</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 19,\n          \"id\": \"e7dad47e-ae5b-4cc6-88b6-eff57699d47e\",\n          \"x\": 48,\n          \"y\": 8,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">How many NBA championships have the BOOLS won?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 158,\n          \"id\": \"07268b4d-940c-4609-ba1b-4581952bc124\",\n          \"x\": 48,\n          \"y\": 208,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 51,\n          \"id\": \"169e41ba-bdb0-499e-9132-6f3b1618c133\",\n          \"x\": 48,\n          \"y\": 409,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 50,\n          \"id\": \"74a1ee13-d408-4ffe-a1bd-99d5094f1f70\",\n          \"x\": 48,\n          \"y\": 468,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">16</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 79,\n          \"height\": 51,\n          \"id\": \"c4a84a65-ba6b-4fee-b197-ad80a6351bb3\",\n          \"x\": 48,\n          \"y\": 528,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">2 / 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 18,\n          \"id\": \"abbb047a-cf3f-45e8-8652-99017da2c286\",\n          \"x\": 48,\n          \"y\": 31,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6265ccfc-37a4-4b53-9d61-580a15833cef\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"169e41ba-bdb0-499e-9132-6f3b1618c133\"]\n        },\n        {\n          \"id\": \"6e2329de-4d46-4774-a125-2341d38fae56\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"74a1ee13-d408-4ffe-a1bd-99d5094f1f70\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"ad5784d2-4872-4bca-bb1b-3a6a143f4817\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c4a84a65-ba6b-4fee-b197-ad80a6351bb3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"50d4d7e5-ac2c-46a6-9696-c5b051c10074\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"d91ed00b-42d2-42ce-821a-5eafd6b1d77b\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 208,\n          \"focalX\": 57.32421875,\n          \"focalY\": 69.38100961538461,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:09:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page6_7_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Basketball court arena photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#231c1f\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"a29c3576-6207-42c2-ab34-7176210e244a\",\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffcd48\\\">Question</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"id\": \"cb24c740-22ca-4fd3-9693-7b91999d5535\",\n          \"x\": 48,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">2 / 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"id\": \"6f6f0e48-9f00-436f-a245-5e24296b9a50\",\n          \"x\": 48,\n          \"y\": 31\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">How many NBA championships have the BOOLS won?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 158,\n          \"type\": \"text\",\n          \"id\": \"a7d56cf7-687f-43f0-8477-8b5767c18fbe\",\n          \"x\": 48,\n          \"y\": 208\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 51,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\",\n          \"id\": \"069af516-193d-4543-a7d5-de0bad845f5d\",\n          \"x\": 48,\n          \"y\": 409\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 252,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"74342ad2-806c-491b-91a5-49e8f2cb0a51\",\n          \"x\": 114,\n          \"y\": 409\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 96,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3d471bdf-3e7d-4c31-a6db-e6511563c516\",\n          \"x\": 113,\n          \"y\": 409\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #fff; text-transform: uppercase\\\">32%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"c681169a-292e-4b68-8da7-f2a1f6b70d79\",\n          \"x\": 318,\n          \"y\": 423\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 67,\n          \"height\": 51,\n          \"marginOffset\": -3.09375,\n          \"type\": \"text\",\n          \"id\": \"46dd9626-f2ab-49ab-9fe6-dd8f66f255dc\",\n          \"x\": 48,\n          \"y\": 468\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 252,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4c15e90d-747e-4e2f-b953-089150551535\",\n          \"x\": 114,\n          \"y\": 468\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 173,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8ae179f6-dae3-4c7a-be93-5a1ea8b257b2\",\n          \"x\": 114,\n          \"y\": 468\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #fff; text-transform: uppercase\\\">46%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"e4ffa3dc-1dfc-49a5-8639-b96161fda792\",\n          \"x\": 318,\n          \"y\": 481\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">16</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 79,\n          \"height\": 51,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\",\n          \"id\": \"a16bef19-d176-4c86-bb4c-0be94c5a26db\",\n          \"x\": 48,\n          \"y\": 528\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 239,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e4b588b6-993d-4143-acd9-88dd9e965580\",\n          \"x\": 127,\n          \"y\": 528\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n          \"type\": \"shape\",\n          \"width\": 98,\n          \"height\": 51,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"80b3f743-fc21-41ae-870b-944f6a546a8e\",\n          \"x\": 126,\n          \"y\": 528\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #fff; text-transform: uppercase\\\">12%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 39,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"0937be1b-3ac2-42ae-a1e4-afe35119f8ba\",\n          \"x\": 318,\n          \"y\": 542\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a2a5bc9f-ae08-4064-ac41-805d001541f9\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"74342ad2-806c-491b-91a5-49e8f2cb0a51\"]\n        },\n        {\n          \"id\": \"64e41670-1c1d-42ec-bfd7-d5662e68ea23\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"4c15e90d-747e-4e2f-b953-089150551535\"]\n        },\n        {\n          \"id\": \"5e249417-85da-4bff-a66e-420f079c10ac\",\n          \"type\": \"effect-fade-in\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"e4b588b6-993d-4143-acd9-88dd9e965580\"]\n        },\n        {\n          \"id\": \"8b495b71-b00e-4ac8-bafd-181265810629\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3d471bdf-3e7d-4c31-a6db-e6511563c516\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"eabfcd06-56df-4411-8cd6-47681162b51c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8ae179f6-dae3-4c7a-be93-5a1ea8b257b2\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"8b88ee4a-ceb7-4961-b9be-690b75410365\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"80b3f743-fc21-41ae-870b-944f6a546a8e\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"a180815d-75bc-4b13-af27-bc3afb4de837\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c681169a-292e-4b68-8da7-f2a1f6b70d79\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"855a97d1-f282-4b9e-85b4-1e0ca6d74f50\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e4ffa3dc-1dfc-49a5-8639-b96161fda792\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"2994adea-17b8-4eea-8005-22f812625536\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0937be1b-3ac2-42ae-a1e4-afe35119f8ba\"],\n          \"duration\": 1200,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"654e580d-3d40-485f-b73c-12cf2206aad1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"d91ed00b-42d2-42ce-821a-5eafd6b1d77b\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"3a2f873f-6b7b-4f62-995c-42f5d1e36789\",\n          \"scale\": 280,\n          \"focalX\": 48.49330357142857,\n          \"focalY\": 49.609375,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:13:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man Playing Basketball\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#34292b\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131, \"a\": 0.6 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">The Bools</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">have won</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">16 rINGS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 120,\n          \"id\": \"320e8a95-c42f-4e0a-901b-d43ebb2e19e7\",\n          \"x\": 47,\n          \"y\": 352,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffcd48\\\">In their 52 seasons of championships in the making, they have won 16 rings in total.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 287,\n          \"height\": 75,\n          \"id\": \"422642b1-ada4-4e63-9925-f142f223d69c\",\n          \"x\": 47,\n          \"y\": 488,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 49.96227572068208,\n          \"focalY\": 33.516232507779165,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:13:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man Playing Basketball\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#ccd1cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 44,\n          \"width\": 324,\n          \"height\": 265,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b46d87ce-78a5-433e-a386-91c133344ec0\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7fc3b17c-b342-4fcc-9b16-0aa25d4b6066\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b46d87ce-78a5-433e-a386-91c133344ec0\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e79744a3-d351-480a-befe-63092e9913e0\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c8b5df99-5aac-4f95-b30c-c1c68d188882\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d0d7d39a-5c8d-47ba-b3f1-fe8ac2241a64\",\n          \"type\": \"image\",\n          \"scale\": 105,\n          \"focalX\": 46.651785714285715,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:14:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page9_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Photo Of Man Doing A Dunk\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#dcdacd\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.4 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffcd48\\\">Question</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 19,\n          \"id\": \"3a5c11a8-4757-4692-a1aa-323b1ac43ce8\",\n          \"x\": 48,\n          \"y\": 8,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Can you name the all-time leading BOOLS scorer in NBA history?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 158,\n          \"id\": \"b4cf9a8d-1c9c-4bba-b217-07033c72de94\",\n          \"x\": 48,\n          \"y\": 208,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">Kobe Brians</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 171,\n          \"height\": 50,\n          \"id\": \"4781481c-7492-45bf-8247-d1e554c5335c\",\n          \"x\": 48,\n          \"y\": 409,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">Lawrence O'Neal</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 214,\n          \"height\": 50,\n          \"id\": \"61747274-af93-4b62-b0f1-8a8020afe3aa\",\n          \"x\": 48,\n          \"y\": 468,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 28,\n            \"vertical\": 14\n          },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #462486; text-transform: uppercase\\\">K.Abdil-Japaar</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 195,\n          \"height\": 50,\n          \"id\": \"22224d01-6eb7-4459-8cfc-3f1f644c636f\",\n          \"x\": 48,\n          \"y\": 528,\n          \"marginOffset\": -3.4375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">3 / 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 18,\n          \"id\": \"cead7f52-7b89-4947-8fcc-e6d7b066f42a\",\n          \"x\": 48,\n          \"y\": 31,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"568e08b0-0e16-4cac-bb87-e9d81dc6eb40\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 0,\n          \"targets\": [\"4781481c-7492-45bf-8247-d1e554c5335c\"]\n        },\n        {\n          \"id\": \"00e8877b-0e11-4846-9acf-6a21309b66e5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"61747274-af93-4b62-b0f1-8a8020afe3aa\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"dc81dcd6-0440-4ca0-aeea-f7019883d5c9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"22224d01-6eb7-4459-8cfc-3f1f644c636f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c3cc330c-61a7-48ad-b606-fb32237e4e9c\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"76b087bc-fefd-4fd2-b80a-acb6bb496174\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"5322f68c-f626-456a-8de1-e6089bb96476\",\n          \"scale\": 152,\n          \"focalX\": 43.52384868421053,\n          \"focalY\": 51.74753289473685,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:15:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Photo Of Man Doing Dunk\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#9faca0\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131, \"a\": 0.7 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Kareem</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">Japaar</span>\\n<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48; text-transform: uppercase\\\">38,387 points</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 243,\n          \"height\": 120,\n          \"id\": \"f64b9139-1064-47d3-9bb5-6c8746a6ae41\",\n          \"x\": 47,\n          \"y\": 27,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffcd48\\\">The highest scoring player of all time is Kareem Japaar with over 38,000 points from 1982 to 2012.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 266,\n          \"height\": 101,\n          \"id\": \"1c20d41d-f922-41c2-b0e6-170d70e6a955\",\n          \"x\": 47,\n          \"y\": 183,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:15:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page10_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Photo Of Man Doing Dunk\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#ccd1cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 50,\n          \"y\": 368,\n          \"width\": 312,\n          \"height\": 307,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4d57a573-0d19-4eb7-acc3-29b6efcba562\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"112b6147-a6f1-430a-bbd0-e190d53a5f14\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4d57a573-0d19-4eb7-acc3-29b6efcba562\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e7476046-ab18-4107-8f80-67923c69dc26\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b9a458b1-326e-484b-801e-98e3729869c2\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8e7e411d-0ab9-4705-beed-056f0bab2f6f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:17:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page11_img2.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Black Haired Man Wearing Black Sleeveless Shirt and Black Shorts\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#333221\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 237,\n          \"y\": -57,\n          \"width\": 104,\n          \"height\": 103,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2878f4c9-2655-46a7-a0fb-53c60ce38e73\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 59.34240340567975,\n          \"focalY\": 50.317454867725,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:17:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page11_img3.jpg\",\n            \"width\": 480,\n            \"height\": 320,\n            \"id\": 0,\n            \"alt\": \"Basketball court photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#2c363d\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 97,\n          \"height\": 98,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ef11fa81-271a-4da8-adce-e81a0be7cd73\",\n          \"x\": 0,\n          \"y\": 126,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 115,\n          \"focalX\": 31.607310541878338,\n          \"focalY\": 50.05000849519312,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:06:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page3_11_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Man in Gray Sleeveless Shirt Carrying White and Brown Spalding Basketball\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#3d3d3b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 98,\n          \"height\": 199,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e8379b0f-a9a3-4b19-ac3e-c669ac869eb5\",\n          \"x\": 314,\n          \"y\": 103,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ffcd48\\\">Correct</span>\\n<span style=\\\"font-weight: 700; color: #ffcd48\\\">Answers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 36,\n          \"id\": \"2c266922-1967-4a23-9bad-70725ba32d61\",\n          \"x\": 47,\n          \"y\": 8,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">5 / 6</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 75,\n          \"height\": 18,\n          \"id\": \"8cc28eac-a921-45c3-83af-7e149b4a6b0b\",\n          \"x\": 47,\n          \"y\": 48,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 300,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #ffcd48\\\">5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 179,\n          \"height\": 352,\n          \"id\": \"1fad4d72-9b5f-47db-bdba-367f593f2f6d\",\n          \"x\": 110,\n          \"y\": 37,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; color: #fff; text-transform: uppercase\\\">Someone knows their team. Congratulations!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 330,\n          \"height\": 121,\n          \"id\": \"8e36ffab-d05b-4088-bd43-3d1303ab3d37\",\n          \"x\": 47,\n          \"y\": 352,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #ffcd48\\\">Most Bools fans average a score of 3/5. Not you though my friend. You really know your stuff.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 266,\n          \"height\": 98,\n          \"id\": \"cf46cdb4-5904-4f06-a97a-1d84f29decce\",\n          \"x\": 47,\n          \"y\": 481,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fc54b07b-fa3f-4e04-abf0-e75ab6901658\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1fad4d72-9b5f-47db-bdba-367f593f2f6d\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"969cbb88-c7ad-414b-9597-4ed0c21a4b4a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ef11fa81-271a-4da8-adce-e81a0be7cd73\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"51a07173-6e8e-4be3-ad26-4cd77b80759f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2878f4c9-2655-46a7-a0fb-53c60ce38e73\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"95a09d85-6856-4176-acda-bd0675ada035\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e8379b0f-a9a3-4b19-ac3e-c669ac869eb5\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 35, \"b\": 131 } },\n      \"type\": \"page\",\n      \"id\": \"6992edac-d28c-4193-a001-044f004dbdad\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1a1229a3-c37d-44f3-85b1-5e6a5737d31f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; text-transform: uppercase\\\">Enjoyed this sport quiz?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 316,\n          \"height\": 82,\n          \"id\": \"186715fb-b684-4941-aefb-80d28fe6f712\",\n          \"x\": 47,\n          \"y\": 42,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"Test your NFL trivia knowledge at: triviaonline.com/sport\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 252,\n          \"height\": 42,\n          \"id\": \"abf1b87d-e3b3-4176-9861-f54358d3f77a\",\n          \"x\": 47,\n          \"y\": 138,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T06:18:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sports-quiz/page12_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Football Player Holding Football\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#1d2b1e\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 95,\n          \"y\": 237,\n          \"width\": 274,\n          \"height\": 379,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cc4675fd-c954-4669-8a03-1df7eae31acf\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"width\": 214,\n          \"height\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b7dd7a10-7969-425e-9b31-c76ad85453f7\",\n          \"x\": 0,\n          \"y\": 502,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; font-style: italic; text-transform: uppercase\\\">Click to play</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 134,\n          \"height\": 23,\n          \"id\": \"728e4af7-b63c-4dd1-ae36-bdc917f7ea28\",\n          \"x\": 47,\n          \"y\": 516,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7ed8d243-0bbd-4097-a174-357a5a54cd7f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cc4675fd-c954-4669-8a03-1df7eae31acf\"],\n          \"duration\": 1200,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c662f8a5-b67e-4ef4-a709-c9a0cf68ca69\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b7dd7a10-7969-425e-9b31-c76ad85453f7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"f5c83a30-2390-4619-8336-b53f059f9991\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"728e4af7-b63c-4dd1-ae36-bdc917f7ea28\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 205, \"b\": 72 } },\n      \"type\": \"page\",\n      \"id\": \"136cca74-5131-4053-a4e2-003b582a3306\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/street-style-on-the-go/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\n// For some reason, the inferred TypeScript type is too narrow here and we have to use\n// file declaration instead of importing directly from `template.json`.\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/street-style-on-the-go/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'street-style-on-the-go',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Street Style On The Go', 'template name', 'web-stories'),\n  tags: [\n    _x('Fashion', 'template keyword', 'web-stories'),\n    _x('Lifestyle', 'template keyword', 'web-stories'),\n    _x('Trend', 'template keyword', 'web-stories'),\n    _x('Stylish', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Voguish Green', 'color', 'web-stories'),\n      color: '#74e3a3',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#ffffff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Beautiful bright colors, full-scale photos, and an elegant font. Street Style On The Go will let you create stories that look chic and stylish.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion & Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/street-style-on-the-go/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/street-style-on-the-go/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"8fe4f619-7591-4389-b43e-d196bd3f5eb1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page01_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in white shirt and black pants standing on sidewalk during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#344043\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -34,\n          \"y\": -392,\n          \"width\": 500,\n          \"height\": 1067,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4b032487-ccb7-49fb-92d8-f4f0db1fde8b\",\n          \"groupId\": \"43822f2d-e2ce-445d-ac82-13372d91db61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9292a0ed-9f5a-4bf2-ba3b-fa83eb341f53\",\n          \"groupId\": \"43822f2d-e2ce-445d-ac82-13372d91db61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": -84,\n          \"y\": 245,\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cbefdc72-f3c8-4385-b57f-4488f40c4521\",\n          \"groupId\": \"fa398ffe-eb70-4024-afe6-76e604dfeabe\"\n        },\n        {\n          \"x\": -77,\n          \"y\": 245,\n          \"id\": \"88d3dc35-863b-4eec-aaae-5a19f0911c0f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"fa398ffe-eb70-4024-afe6-76e604dfeabe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 85,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Street Style On The Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 44,\n          \"y\": 275,\n          \"width\": 324,\n          \"height\": 250,\n          \"id\": \"42d3cd2a-11b2-4f13-9d0c-67510cce933d\",\n          \"marginOffset\": 2.1700000000000017,\n          \"groupId\": \"fa398ffe-eb70-4024-afe6-76e604dfeabe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Written by Betty D</span>\\n<span style=\\\"color: #fff\\\">July 23, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 139,\n          \"y\": 552,\n          \"width\": 132,\n          \"height\": 46,\n          \"id\": \"a177f788-1834-4a25-838b-4977b3a71265\",\n          \"marginOffset\": 0.4781249999999986\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"0a63bedc-b774-47f4-8702-e2f97d0df862\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"43822f2d-e2ce-445d-ac82-13372d91db61\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        },\n        \"fa398ffe-eb70-4024-afe6-76e604dfeabe\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2dcfc6c2-4d52-48e8-99ec-18f92d4c27a8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page01_image01.jpg\",\n            \"width\": 498,\n            \"height\": 332,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man and woman standing in front of building wearing jackets\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#212f3f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"width\": 674,\n          \"height\": 498,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7baa1438-ff66-4cd5-b6b4-cacf6e41e9b0\",\n          \"x\": -180,\n          \"y\": -61\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": -67,\n          \"y\": 394,\n          \"width\": 511,\n          \"height\": 335,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"48830afb-9f96-4465-be04-b96194b22d11\",\n          \"groupId\": \"69941a5e-88a5-4c8c-8cfa-19cb195da1b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">There is so much to see and be seen wearing this Fall. We take a detailed look at the shoes, the bags, the accessories and of course the overall looks when you're busy going from point A to point Z.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 300,\n          \"height\": 162,\n          \"marginOffset\": 4.41,\n          \"id\": \"52f3d09e-d5d5-4fba-848b-57c0f16487f8\",\n          \"x\": 56,\n          \"y\": 440,\n          \"groupId\": \"69941a5e-88a5-4c8c-8cfa-19cb195da1b5\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"044acf92-f5dc-41a5-b1d6-1171880d0c23\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"69941a5e-88a5-4c8c-8cfa-19cb195da1b5\": {\n          \"name\": \"Info\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0bb4ba23-a797-4b1b-929d-bd94d16b5b53\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page03_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman wearing green top standing near Flatiron building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#4e4c47\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -5.5,\n          \"y\": -64.5,\n          \"width\": 423,\n          \"height\": 747,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"272c2f66-df4b-4103-8fdf-04fd181772b3\",\n          \"groupId\": \"63bf92a8-58bd-4e60-bf59-b06f84f2fabc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bfe69af4-9705-402c-b7ce-44913da92145\",\n          \"type\": \"shape\",\n          \"groupId\": \"63bf92a8-58bd-4e60-bf59-b06f84f2fabc\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -89,\n          \"y\": -129,\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b13513fe-f747-439d-8fad-709f54119341\",\n          \"type\": \"shape\",\n          \"groupId\": \"eac270eb-6d68-41a3-9da6-82e447fea7fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -82,\n          \"y\": -129,\n          \"id\": \"5c296bd7-e68d-4639-a983-2db4e573cd80\",\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"eac270eb-6d68-41a3-9da6-82e447fea7fe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 65,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">New York On The Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 51,\n          \"y\": 0,\n          \"width\": 310,\n          \"height\": 133,\n          \"id\": \"1ffeff5b-a218-4f7d-8809-ef545820b0c1\",\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"eac270eb-6d68-41a3-9da6-82e447fea7fe\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">New York, no stranger to being on the go, makes it minimal this time.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 533,\n          \"width\": 300,\n          \"height\": 71,\n          \"id\": \"182d73ad-141c-4d59-bd3d-3035a002603e\",\n          \"marginOffset\": 4.41,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7b745a93-1ec5-44aa-bfb0-2a9c017c2c7d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"182d73ad-141c-4d59-bd3d-3035a002603e\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d20e69b6-2ce2-493b-a930-49adfe3b619b\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"eac270eb-6d68-41a3-9da6-82e447fea7fe\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"63bf92a8-58bd-4e60-bf59-b06f84f2fabc\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"79c61116-a0d0-4e64-917d-89fa5077abe7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page04_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man in white long sleeve shirt and black pants standing on road during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9d8b7f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -63.5,\n          \"width\": 412,\n          \"height\": 745,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7ef4154b-3fa1-452f-8ad1-6b27e2c74989\",\n          \"groupId\": \"9e02919f-ac5c-40ba-bb58-e90081c93011\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"e737e6a6-c4ef-438c-9d56-752cb07fe85a\",\n          \"x\": 0,\n          \"y\": -57,\n          \"groupId\": \"9e02919f-ac5c-40ba-bb58-e90081c93011\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 171,\n          \"y\": 43,\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"id\": \"2618ee74-b460-41bc-bf79-ab03945bb7de\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"9e02919f-ac5c-40ba-bb58-e90081c93011\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 167,\n          \"id\": \"e961ad3d-4583-4668-a61a-270dee386a3b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"9e02919f-ac5c-40ba-bb58-e90081c93011\"\n        },\n        {\n          \"x\": 149,\n          \"y\": 404,\n          \"id\": \"19750fef-2288-45b5-a636-8442c8384399\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"9e02919f-ac5c-40ba-bb58-e90081c93011\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Black &amp; White</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"id\": \"79f0f310-892a-4e22-b960-97f33bf98df2\",\n          \"x\": 48,\n          \"y\": 524,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">New York Look 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 132,\n          \"y\": 498,\n          \"width\": 151,\n          \"height\": 18,\n          \"id\": \"043e48d6-10c5-41f0-a985-6e59b34069e1\",\n          \"marginOffset\": 0.42499999999999716\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"72fff2a9-09b9-441c-8648-62200b42d877\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"2618ee74-b460-41bc-bf79-ab03945bb7de\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ff0ec755-a198-4978-bef8-57cc5c01fec8\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e961ad3d-4583-4668-a61a-270dee386a3b\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"1068c93d-aa09-40b9-83ef-4d6181c682bf\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"19750fef-2288-45b5-a636-8442c8384399\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"717f9e7a-fb90-4630-90fc-6981f0963a7d\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9e02919f-ac5c-40ba-bb58-e90081c93011\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"cfc770f4-b235-4416-a04d-78f63aa9d91b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"76ec54d0-a8e4-4f79-8804-01f3cf394ca8\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page05_image02.png\",\n            \"width\": 330,\n            \"height\": 298,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in blue and white polka dot shirt and white skirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ceccd3\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -4,\n          \"y\": 287,\n          \"width\": 420,\n          \"height\": 408,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"33e2cbff-61eb-46a4-be40-c610f32e9f9e\",\n          \"groupId\": \"936a023d-b437-40dc-bfb7-b045082e0adf\"\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"id\": \"9aa548af-ba86-4f93-a58c-55d80e3e8895\",\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"936a023d-b437-40dc-bfb7-b045082e0adf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">White Bag</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"id\": \"ce205980-e306-4717-9215-4bb30bca8b9c\",\n          \"x\": 48,\n          \"y\": 524,\n          \"type\": \"text\",\n          \"groupId\": \"936a023d-b437-40dc-bfb7-b045082e0adf\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; text-transform: uppercase\\\">SIMPLE BUT BOLD</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 132,\n          \"y\": 498,\n          \"width\": 151,\n          \"height\": 18,\n          \"id\": \"1082f19d-bc15-496b-ae62-fce0b86404f6\",\n          \"marginOffset\": 0.42499999999999716,\n          \"type\": \"text\",\n          \"groupId\": \"936a023d-b437-40dc-bfb7-b045082e0adf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 149,\n          \"y\": 368,\n          \"id\": \"68d96cfa-c217-4e09-8f9f-3b4e30d8a190\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"936a023d-b437-40dc-bfb7-b045082e0adf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page05_image01.png\",\n            \"width\": 330,\n            \"height\": 298,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"two women in teal romper pants\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1b6b9\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -13.5,\n          \"y\": -173,\n          \"width\": 451,\n          \"height\": 524,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e91883e6-167f-4423-b564-1ce98fb792da\",\n          \"groupId\": \"7c934704-3be5-41fb-98d7-717306e3c36a\"\n        },\n        {\n          \"opacity\": 60,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": -6,\n          \"y\": -61,\n          \"width\": 424,\n          \"height\": 342,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a5b9e0c2-ccd3-4e60-9ef3-49394ff77859\",\n          \"groupId\": \"7c934704-3be5-41fb-98d7-717306e3c36a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 310,\n          \"y\": 113,\n          \"id\": \"e6535291-ee64-43a6-bd4d-88153aef3f86\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"7c934704-3be5-41fb-98d7-717306e3c36a\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 34,\n          \"id\": \"8841b290-6ce1-40cb-8760-563c905c1e47\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Nude Heels</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"7c934704-3be5-41fb-98d7-717306e3c36a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 131,\n          \"y\": 8,\n          \"id\": \"8ec6c081-8c01-4461-9182-4bb50dd9f97d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; text-transform: uppercase\\\">EVERYDAY CLASSIC</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 151,\n          \"height\": 18,\n          \"marginOffset\": 0.42499999999999716,\n          \"type\": \"text\",\n          \"groupId\": \"7c934704-3be5-41fb-98d7-717306e3c36a\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"950391ee-2bf8-4443-856e-94c9dcb81e14\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e6535291-ee64-43a6-bd4d-88153aef3f86\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"24f2c379-e3ec-47b4-829b-4e7847974343\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"68d96cfa-c217-4e09-8f9f-3b4e30d8a190\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 50\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"40aedb26-f5c7-4389-b1f9-b5abe8671d9e\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"7c934704-3be5-41fb-98d7-717306e3c36a\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"936a023d-b437-40dc-bfb7-b045082e0adf\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4fc4bce6-4d26-43ad-bf24-5d7b4f37fbe4\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:51:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page06_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man and woman walking on street\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bbc5be\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -43,\n          \"y\": -62,\n          \"width\": 530,\n          \"height\": 889,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8b90b36a-ecf8-47e0-9cb0-63218931cdbc\",\n          \"groupId\": \"df1a5998-b880-4157-aae7-cef113648f5d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.51 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"482664d3-7f20-4dcc-afb7-8887d99a52d3\",\n          \"type\": \"shape\",\n          \"groupId\": \"df1a5998-b880-4157-aae7-cef113648f5d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -89,\n          \"y\": -129,\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2e907df2-759c-4173-bcf6-fdb29dbda261\",\n          \"type\": \"shape\",\n          \"groupId\": \"81ba1fe2-ca86-4ce1-8590-8cd49e79b7c7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -82,\n          \"y\": -129,\n          \"id\": \"45bcd259-fb9a-4c21-8c6e-e7ef3a0c50bc\",\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"81ba1fe2-ca86-4ce1-8590-8cd49e79b7c7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 65,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Barcelona On The Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 51,\n          \"y\": 0,\n          \"width\": 310,\n          \"height\": 133,\n          \"id\": \"592e9a85-cfeb-4b23-85ee-2be306fb698c\",\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"81ba1fe2-ca86-4ce1-8590-8cd49e79b7c7\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Accessories that are bold and statement making are ways to lean into fashion while busy on the go.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 533,\n          \"width\": 300,\n          \"height\": 66,\n          \"id\": \"161444e7-0c6f-4f41-8ef5-587d4dfaa05f\",\n          \"marginOffset\": 4.41,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"4fc88e3c-770b-4ff6-8458-a5080f7338c7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"161444e7-0c6f-4f41-8ef5-587d4dfaa05f\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"67f8cefb-7c27-4d8d-a705-943380b1de89\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"81ba1fe2-ca86-4ce1-8590-8cd49e79b7c7\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"df1a5998-b880-4157-aae7-cef113648f5d\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"102a3c91-4e16-4fc4-8d7c-745cd1ba3c3c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:52:15\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page07_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in red and white sweater wearing pink knit cap\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#163741\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -56,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b3caf96f-8f2c-44c7-9d44-9b1de6bef28e\",\n          \"groupId\": \"374fa7aa-59fc-4407-babb-59569bb35d91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.49 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2c9ba44e-c4b3-4d8d-beca-2357013fdffb\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"374fa7aa-59fc-4407-babb-59569bb35d91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 148,\n          \"y\": 176,\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"id\": \"8c6204fb-504d-4a36-bcb6-8158640c8aa8\",\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"374fa7aa-59fc-4407-babb-59569bb35d91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 206,\n          \"y\": 367,\n          \"id\": \"03d6f4c6-71f5-4f52-a71c-abf2873eefdd\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"374fa7aa-59fc-4407-babb-59569bb35d91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 118,\n          \"y\": 565,\n          \"id\": \"766fd6c5-d038-4dfa-b2cf-ab2b869a27a8\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"374fa7aa-59fc-4407-babb-59569bb35d91\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Bright &amp; Bold</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"id\": \"1c0e5058-3388-46ed-8a4c-d25e912f3781\",\n          \"x\": 48,\n          \"y\": 34,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">BARCELONA LOOK 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 121,\n          \"y\": 8,\n          \"width\": 170,\n          \"height\": 18,\n          \"id\": \"daf40241-7590-4dea-bbfa-54517191b1cc\",\n          \"marginOffset\": -4.125,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"563b7b99-01a1-44d8-9f61-32b4801eb27d\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"8c6204fb-504d-4a36-bcb6-8158640c8aa8\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d90946ae-88fd-4fbf-af88-93a0ad177636\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"03d6f4c6-71f5-4f52-a71c-abf2873eefdd\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"4dd3f30f-42ed-4dc7-adda-1a387c3c674c\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"766fd6c5-d038-4dfa-b2cf-ab2b869a27a8\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"cd82cda9-2c39-4204-8df1-f5575e42647e\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"374fa7aa-59fc-4407-babb-59569bb35d91\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0db47ff9-1342-403f-ba66-3c6b4100732f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:52:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page08_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man walking on the street while carrying bag\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#26393d\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -135.5,\n          \"y\": -414,\n          \"width\": 683,\n          \"height\": 1217,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6520c853-510e-41c4-80c0-617dda47e5c1\",\n          \"groupId\": \"5ff05d6a-4844-4834-a14a-5eeec2ad7268\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.45 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f9ba124d-a4f3-46bc-a910-72c97b817bd9\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"5ff05d6a-4844-4834-a14a-5eeec2ad7268\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 99,\n          \"y\": 424,\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"id\": \"d4c31f52-6dbd-486d-b0ac-e771141d336e\",\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"5ff05d6a-4844-4834-a14a-5eeec2ad7268\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 206,\n          \"y\": 200,\n          \"id\": \"20b13191-5fee-4d5d-b2a4-d15790e7f414\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"5ff05d6a-4844-4834-a14a-5eeec2ad7268\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Leather First</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"id\": \"ad473584-ec9c-4ea6-b32c-68379d38660c\",\n          \"x\": 48,\n          \"y\": 34,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">BARCELONA LOOK 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 121,\n          \"y\": 8,\n          \"width\": 170,\n          \"height\": 18,\n          \"id\": \"8cf1cdb6-eb51-425d-a4bd-ff41bf4808dd\",\n          \"marginOffset\": -4.125,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b90cf0e2-5891-40b2-b754-20e9328458b4\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"d4c31f52-6dbd-486d-b0ac-e771141d336e\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"05afdc92-5b19-43ea-b4b0-da75eb786a4d\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"20b13191-5fee-4d5d-b2a4-d15790e7f414\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"82970939-a60b-4543-81fb-f9edeed3d243\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5ff05d6a-4844-4834-a14a-5eeec2ad7268\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"3b189d48-b906-4c12-9c1c-a73f7c721a5b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:52:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page09_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman looking at Eiffel Tower\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#bbc5da\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"5464d837-558a-493f-baf9-24a55dd6b59b\",\n          \"groupId\": \"f548d5f5-9b03-4a3f-8876-421956f623ae\"\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.55 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 1\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"24ecb791-f40b-4405-8dcb-8fd6e79f0167\",\n          \"type\": \"shape\",\n          \"groupId\": \"f548d5f5-9b03-4a3f-8876-421956f623ae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -89,\n          \"y\": -129,\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"272183e6-c572-4fbe-9e54-4ae57b19626c\",\n          \"type\": \"shape\",\n          \"groupId\": \"e827c319-3b85-4fe5-b103-1865bd1fbbae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 112, \"g\": 255, \"b\": 169, \"a\": 0.5 }\n          },\n          \"x\": -82,\n          \"y\": -129,\n          \"id\": \"2f8ac7bc-499c-4e97-8959-463c8e20c16d\",\n          \"width\": 581,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"groupId\": \"e827c319-3b85-4fe5-b103-1865bd1fbbae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 65,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Paris</span>\\n<span style=\\\"text-transform: uppercase\\\">&nbsp;On The Go</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 51,\n          \"y\": 0,\n          \"width\": 310,\n          \"height\": 133,\n          \"id\": \"a22422ad-f9d7-49e4-93a9-307bf2180fbf\",\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"e827c319-3b85-4fe5-b103-1865bd1fbbae\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">You'll want to sparkle and dazzle your way through the streets of Paris with elevated eye-catching statements.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 56,\n          \"y\": 533,\n          \"width\": 300,\n          \"height\": 66,\n          \"id\": \"4e426846-152a-449f-b79e-fcbf05eb7688\",\n          \"marginOffset\": 4.41,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0954d91f-46b6-4a4d-ba37-935e813e5c13\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4e426846-152a-449f-b79e-fcbf05eb7688\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e59e8a55-ebe7-48cc-b5c5-69ba91ab7297\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e827c319-3b85-4fe5-b103-1865bd1fbbae\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"f548d5f5-9b03-4a3f-8876-421956f623ae\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"d5499d1e-e9e7-4544-a21e-b928f92bf124\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:53:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page10_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman in black leather jacket standing on sidewalk during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#807f7e\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -3,\n          \"y\": -105.5,\n          \"width\": 418,\n          \"height\": 782,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e850c642-b414-4283-a2c5-e0c50a1c8a95\",\n          \"groupId\": \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.5 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"378b6f2c-b8c5-462b-a5b2-7f878a335304\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 257,\n          \"y\": 232,\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"id\": \"0e4df1c9-fcc8-4ec2-81cf-83f43800011f\",\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 157,\n          \"y\": 299,\n          \"id\": \"e47bcf2b-70f8-48dc-a648-caa16e579732\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 257,\n          \"y\": 505,\n          \"id\": \"43dfe5b4-2b0c-4231-af65-85eecb988c18\",\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Elegant Style</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 58,\n          \"marginOffset\": -16.32,\n          \"id\": \"b9683800-cf47-4386-96d5-fccc9bbd8677\",\n          \"x\": 48,\n          \"y\": 34,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">PARIS LOOK 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 121,\n          \"y\": 8,\n          \"width\": 170,\n          \"height\": 18,\n          \"id\": \"34e75c51-6a39-4e0c-9f7c-c0a112f95de5\",\n          \"marginOffset\": -4.125,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e33b7cfc-7b92-449d-bd33-f2ed4b1af11b\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"0e4df1c9-fcc8-4ec2-81cf-83f43800011f\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d164d506-17a6-428a-9403-57c9771ac23f\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"e47bcf2b-70f8-48dc-a648-caa16e579732\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"511ba7eb-467f-4208-a5db-d9c9a94915ce\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"43dfe5b4-2b0c-4231-af65-85eecb988c18\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"a3030e08-6462-4246-bda4-530a477aec31\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"520fbcd1-de3e-40ae-8c54-cbe352b4dc04\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"30c1f5cb-7f91-411b-b2b4-05f2801b5741\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:53:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page11_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman sitting on brown concrete surface wearing brown boots beside brown leather handbag\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#534441\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -134,\n          \"y\": -245,\n          \"width\": 583,\n          \"height\": 1037,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ea88354c-57ea-43df-9bad-432380f0e314\",\n          \"groupId\": \"dccf59cf-db53-4885-afd2-44041e844611\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.5 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.7\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"41ea520c-94a0-4a47-a0df-522df64387f6\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\",\n          \"groupId\": \"dccf59cf-db53-4885-afd2-44041e844611\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 294,\n          \"y\": 301,\n          \"width\": 42,\n          \"height\": 42,\n          \"sticker\": { \"type\": \"fashionTap\" },\n          \"id\": \"34986906-17c7-4662-bc99-7dec99cb099e\",\n          \"type\": \"sticker\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"Product Domain\"\n          },\n          \"groupId\": \"dccf59cf-db53-4885-afd2-44041e844611\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Statement Black Clutch</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 108,\n          \"marginOffset\": -16.32,\n          \"id\": \"cd9a9891-e73f-4fad-9587-2a7eb4a86339\",\n          \"x\": 48,\n          \"y\": 474,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">PARIS MUST HAVE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 121,\n          \"y\": 446,\n          \"width\": 170,\n          \"height\": 18,\n          \"id\": \"57bb1bc8-e907-4ab1-a109-b588ed8c5dd6\",\n          \"marginOffset\": -4.125,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0311b6b5-b628-42e7-a091-5975a80735af\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"34986906-17c7-4662-bc99-7dec99cb099e\"],\n          \"scale\": 0.25,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"e046e6d1-0633-4298-9726-763c408bbce4\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"dccf59cf-db53-4885-afd2-44041e844611\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"3be27294-cc7d-4987-8bfb-d3852c67e9ff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 78, \"g\": 78, \"b\": 78, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"x\": -57,\n          \"y\": -92,\n          \"width\": 531,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2ae36a17-0bcd-4e10-84cd-a999fe945bc0\",\n          \"groupId\": \"98a0c007-f3c1-49e2-8620-6be1e0817dbd\"\n        },\n        {\n          \"x\": -57,\n          \"y\": 402,\n          \"id\": \"0cb9e18e-08fd-4b1a-8066-2d723d04fbf3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 78, \"g\": 78, \"b\": 78, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"width\": 531,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"98a0c007-f3c1-49e2-8620-6be1e0817dbd\"\n        },\n        {\n          \"x\": -56,\n          \"y\": 124,\n          \"id\": \"8d3c7497-0b84-4a78-9075-400ccf6ae068\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -15,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 78, \"g\": 78, \"b\": 78, \"a\": 0.5 }\n          },\n          \"type\": \"shape\",\n          \"width\": 531,\n          \"height\": 249,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"98a0c007-f3c1-49e2-8620-6be1e0817dbd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">View More</span>\\n<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Cities</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 65,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"id\": \"25426855-7f3e-4455-9ccb-62fd2b494b17\",\n          \"x\": 48,\n          \"y\": 34\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; letter-spacing: 0.05em; text-transform: uppercase\\\">NEXT STEPs</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 170,\n          \"height\": 17,\n          \"marginOffset\": -4.125,\n          \"type\": \"text\",\n          \"id\": \"5677ed71-cf50-4586-8103-47de6f0402ad\",\n          \"x\": 121,\n          \"y\": 8\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:53:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page12_image01.jpg\",\n            \"width\": 156,\n            \"height\": 238,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman standing in the middle of the road\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2f312e\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 252,\n          \"y\": 134,\n          \"width\": 101,\n          \"height\": 153,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8d1b8d81-e005-4418-b941-687cee87ef72\",\n          \"groupId\": \"0447b865-badc-49fe-a1b9-63fea133a862\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 198,\n          \"id\": \"3971568f-b6c2-4898-b7f1-4f07717d9c54\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Sao Paulo</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 81,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"0447b865-badc-49fe-a1b9-63fea133a862\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:53:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page12_image02.jpg\",\n            \"width\": 156,\n            \"height\": 239,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman wearing white spaghetti strap jumpsuit\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#acb9bb\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 34,\n          \"y\": 309,\n          \"width\": 90,\n          \"height\": 136,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"20329871-c688-4e18-a2dd-971704196fc6\",\n          \"groupId\": \"d6a16c60-f9c1-49d4-ad5d-9f8d5fc773d2\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 334,\n          \"id\": \"5d066331-741c-469b-b93a-95449cf636a8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Berlin</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 81,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"d6a16c60-f9c1-49d4-ad5d-9f8d5fc773d2\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-13T13:53:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/street-style-on-the-go/page03_bg.jpg\",\n            \"width\": 156,\n            \"height\": 238,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"woman wearing green top standing near Flatiron building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d0cdce\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 221,\n          \"y\": 499,\n          \"width\": 77,\n          \"height\": 116,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d2501a37-076f-4e57-99d9-0f4c28b7a5f4\",\n          \"groupId\": \"606fedc5-320c-4c8b-ab63-f6e591aa8ab8\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 470,\n          \"id\": \"4aa4ce21-2df6-4171-8d1e-b216ce01178e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oranienbaum\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 895,\n              \"des\": -260,\n              \"tAsc\": 895,\n              \"tDes\": -260,\n              \"tLGap\": 0,\n              \"wAsc\": 895,\n              \"wDes\": 260,\n              \"xH\": 475,\n              \"capH\": 700,\n              \"yMin\": -260,\n              \"yMax\": 895,\n              \"hAsc\": 895,\n              \"hDes\": -260,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #70ffa9; text-transform: uppercase\\\">Chicago</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 81,\n          \"marginOffset\": -16.32,\n          \"type\": \"text\",\n          \"groupId\": \"606fedc5-320c-4c8b-ab63-f6e591aa8ab8\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fb64b5f4-cdb5-4ef2-83c4-194b0b2e04f4\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"8d1b8d81-e005-4418-b941-687cee87ef72\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4cfdddaf-053a-4a46-a912-ec1a39a0ea6a\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"20329871-c688-4e18-a2dd-971704196fc6\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e4b03884-fe91-4664-bc3c-b0097b994a90\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"d2501a37-076f-4e57-99d9-0f4c28b7a5f4\"],\n          \"whooshInDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"7c6f0de3-850b-4263-95e9-732206f937a9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3971568f-b6c2-4898-b7f1-4f07717d9c54\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"3adfa5a2-d40b-4df4-9469-8c3e64679761\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5d066331-741c-469b-b93a-95449cf636a8\"],\n          \"duration\": 2000,\n          \"delay\": 750\n        },\n        {\n          \"id\": \"71817139-da13-43ee-b50f-33bbde4a18ef\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4aa4ce21-2df6-4171-8d1e-b216ce01178e\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"type\": \"page\",\n      \"id\": \"78887218-eb63-4166-9e99-5101d819d218\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"0447b865-badc-49fe-a1b9-63fea133a862\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d6a16c60-f9c1-49d4-ad5d-9f8d5fc773d2\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"606fedc5-320c-4c8b-ab63-f6e591aa8ab8\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"98a0c007-f3c1-49e2-8620-6be1e0817dbd\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/summer-adventure-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/summer-adventure-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'summer-adventure-guide',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Summer Adventure Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Travel', 'template keyword', 'web-stories'),\n    _x('Adventure', 'template keyword', 'web-stories'),\n    _x('Trip', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Golden Yellow', 'color', 'web-stories'),\n      color: '#fec85a',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Olive Green', 'color', 'web-stories'),\n      color: '#556C28',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s green-yellow color palette and map-like stickers will let you create fun and exciting stories for adventure travel, ecotourism, hiking, camping, wildlife and more.',\n    'web-stories'\n  ),\n  vertical: _x('Travel', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/summer-adventure-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/summer-adventure-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"06176914-a5cb-44c9-a5ee-a84e2350b52b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 123,\n          \"focalX\": 55.043712536879056,\n          \"focalY\": 57.13812399836735,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page01_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man riding on vehicle looking for map photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#5a4d3a\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d9915953-acca-414f-b17a-4cd44dea17f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b4f13f93-d5fa-4b2c-a49b-507122907ab8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 68,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">Plan an</span>\\n<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">RV Summer Adventure</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 44,\n          \"y\": 239,\n          \"width\": 321,\n          \"height\": 205,\n          \"id\": \"75b36af4-815e-41f2-b339-43e2fc8eb6c7\",\n          \"marginOffset\": -65.97\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Preparation tips by:</span>\\n<span style=\\\"color: #fec85a\\\">Charlie Smith</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 44,\n          \"y\": 434,\n          \"width\": 200,\n          \"height\": 43,\n          \"id\": \"44fd3a82-199b-45a5-8745-7049e9d6f09a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 113,\n          \"y\": 129,\n          \"width\": 339,\n          \"height\": 386,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" },\n          \"id\": \"cf23a0d6-fd4b-4195-90d8-d7d491a2eac6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 267,\n          \"y\": 474,\n          \"width\": 32,\n          \"height\": 32,\n          \"sticker\": { \"type\": \"SummerAdventurePlus\" },\n          \"id\": \"7e70bd8d-cc67-4470-aec2-8e64755c6f6d\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fb9e9e6b-998e-430b-b965-eaf3f3d0c1f8\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ea3d1391-9f38-4560-85f5-223dba3d33ba\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Everything you’ll need to prepare a perfect RV summer adventure.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 129,\n          \"marginOffset\": -15.990000000000002,\n          \"id\": \"e2a8cf60-104f-4aa3-b537-97b3af2166ab\",\n          \"x\": 84,\n          \"y\": 149\n        },\n        {\n          \"x\": 84,\n          \"y\": 371,\n          \"id\": \"216a29ce-76a5-4514-8454-964f68ceb72e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 72,\n          \"marginOffset\": -27.183,\n          \"groupId\": \"d5fdf9d7-6dfa-48ca-96fb-49c8b33d8695\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 134,\n          \"y\": 381.5,\n          \"id\": \"69eff7ac-175d-4f76-b0e8-06b4b1df892f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Choose the camper</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 43,\n          \"marginOffset\": -12.259000000000004,\n          \"groupId\": \"d5fdf9d7-6dfa-48ca-96fb-49c8b33d8695\"\n        },\n        {\n          \"x\": 134,\n          \"y\": 468.5,\n          \"id\": \"86f0684d-7a0a-47f1-b8a0-1caa68043508\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Plan your budget</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 41,\n          \"marginOffset\": -12.259000000000004,\n          \"groupId\": \"033e20b5-fb47-4eed-8cc9-57b893016ad7\"\n        },\n        {\n          \"x\": 84,\n          \"y\": 543,\n          \"id\": \"a1e12eb8-207b-4922-a4a2-27aacd73f27d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">3.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 49,\n          \"height\": 72,\n          \"marginOffset\": -31.016999999999996,\n          \"groupId\": \"4bfe752f-e883-40b3-a900-b3235cfb5a7b\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 84,\n          \"y\": 458,\n          \"id\": \"6c958a27-e2f1-491d-9d9e-cbcdce3a2cc6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 51,\n          \"height\": 72,\n          \"marginOffset\": -31.016999999999996,\n          \"groupId\": \"4bfe752f-e883-40b3-a900-b3235cfb5a7b\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 135,\n          \"y\": 552.5,\n          \"id\": \"6ed0bebb-5aae-4ff2-ac23-3208cd18e959\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Map the&nbsp;</span>\\n<span style=\\\"color: #fec85a\\\">route</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 109,\n          \"height\": 43,\n          \"marginOffset\": 1.5261363636363647,\n          \"groupId\": \"4bfe752f-e883-40b3-a900-b3235cfb5a7b\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 339,\n          \"height\": 386,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" },\n          \"id\": \"50b56ef4-da70-4df8-a4d1-d93e3828124b\",\n          \"x\": -195,\n          \"y\": -90\n        },\n        {\n          \"x\": 186,\n          \"y\": 339,\n          \"id\": \"d10b4c4a-3593-4ac3-88ac-e84d59202f18\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 165,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 339,\n          \"height\": 386,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d6467f65-254a-43ce-a829-a61239558356\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"69eff7ac-175d-4f76-b0e8-06b4b1df892f\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"82a0bc01-ca33-476a-9054-1881f7ba24a8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"216a29ce-76a5-4514-8454-964f68ceb72e\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"6647313f-6e4a-49a3-9710-d77eac6cba6c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"86f0684d-7a0a-47f1-b8a0-1caa68043508\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"4edee6eb-0837-44bb-9655-fb8f06d85737\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6c958a27-e2f1-491d-9d9e-cbcdce3a2cc6\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"98bd2f26-bf57-4dca-ac70-7a5bc5a8121a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6ed0bebb-5aae-4ff2-ac23-3208cd18e959\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"aac4a935-3e5c-492b-88d1-89a33f5bc6e6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a1e12eb8-207b-4922-a4a2-27aacd73f27d\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 74, \"g\": 98, \"b\": 24 } },\n      \"type\": \"page\",\n      \"id\": \"e56de283-7b57-4559-8610-c9509c489c0e\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"d5fdf9d7-6dfa-48ca-96fb-49c8b33d8695\": {\n          \"name\": \"First\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"033e20b5-fb47-4eed-8cc9-57b893016ad7\": {\n          \"name\": \"Second\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"4bfe752f-e883-40b3-a900-b3235cfb5a7b\": {\n          \"name\": \"Third\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"786bae58-0701-4ab6-a6a3-6ff5e300161f\",\n          \"scale\": 104,\n          \"focalX\": 56.341374269005854,\n          \"focalY\": 49.87150493421053,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"No vehicles at the road during daytime photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#443f32\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6bceb606-f566-4c51-987f-cbd1d050c359\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">choose the right camper</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 100,\n          \"marginOffset\": -39.246,\n          \"id\": \"1b1a6957-746c-4dc2-aa1a-3ac148596f6f\",\n          \"x\": 63,\n          \"y\": 451\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">If you know where the open roads are going to take you, choosing an RV will be a little easier.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 63,\n          \"id\": \"79b22ce6-0d3b-4ac5-884d-fdf88381277a\",\n          \"x\": 54,\n          \"y\": 552,\n          \"marginOffset\": 2.4238636363636417\n        },\n        {\n          \"x\": 183,\n          \"y\": 399,\n          \"id\": \"084b0d48-8990-436b-b996-551ac4aecd6f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262525; text-transform: uppercase\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 47,\n          \"height\": 45,\n          \"marginOffset\": -17.091,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 45,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 339,\n          \"height\": 386,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" },\n          \"id\": \"20b7b72d-6738-4ad4-a5ab-f329d92c5f86\",\n          \"x\": 32,\n          \"y\": -215\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"70331b93-5e86-4246-a6fc-4658eab4ccde\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"79b22ce6-0d3b-4ac5-884d-fdf88381277a\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"75e27d11-4b43-4fcb-97dd-48b777b3b15e\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"786bae58-0701-4ab6-a6a3-6ff5e300161f\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2024f354-b683-4695-aa27-45bb7cf00ffe\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e49c3605-3a1b-497c-a21a-579f0acdcfa4\"\n      },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0413e3d1-d075-4400-922c-3e0288badaf1\",\n          \"scale\": 128,\n          \"focalX\": 50,\n          \"focalY\": 59.475708007812514,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:11\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White van beside road photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#392f19\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1664ded3-116e-44b8-a38b-f9b0009c044d\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Truck Camper</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 45,\n          \"marginOffset\": -39.246,\n          \"id\": \"80489898-7fd3-46b8-b313-b8b04854dc19\",\n          \"x\": 74,\n          \"y\": 508\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Compact RV camper with similar experience to a larger RV at a much cheaper pricepoint.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 274,\n          \"height\": 65,\n          \"marginOffset\": 2.4238636363636417,\n          \"id\": \"b6d8e3d1-3398-4d8a-a9b8-36b2dbe4c499\",\n          \"x\": 74,\n          \"y\": 552\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"140fa7f3-6721-4c06-971b-1b485b9bdea9\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"0413e3d1-d075-4400-922c-3e0288badaf1\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f606d759-0a00-4305-af53-323c42f1506a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"a14380b4-1d31-496e-8f77-eb0479d94ae2\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6c90b994-36fa-41ea-b684-e328291fb554\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -224.5,\n          \"y\": -100.5,\n          \"width\": 861,\n          \"height\": 819,\n          \"sticker\": { \"type\": \"SummerAdventureTerrainMap\" },\n          \"id\": \"745b0901-5d57-4731-9f0a-d064954d07d9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 70,\n          \"y\": 536,\n          \"id\": \"7abe682d-140e-4cfa-b03d-ba3687bc3b02\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">A captivating RV camper with spacious interiors is suitable for making yourself at home or working on the road.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 273,\n          \"height\": 84,\n          \"marginOffset\": 1.5261363636363647,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"type\": \"shape\",\n          \"x\": 56,\n          \"y\": 9,\n          \"width\": 300,\n          \"height\": 420,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c13c3594-cd4d-4408-ae03-540a4b8fe098\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page05_image01.jpg\",\n            \"width\": 504,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"White wooden storage bed and table photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#93836c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 66,\n          \"y\": 19,\n          \"width\": 280,\n          \"height\": 400,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3cc1c551-4ea1-431f-809c-e0b0bee668df\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 74, \"g\": 98, \"b\": 24 } },\n      \"type\": \"page\",\n      \"id\": \"db2b3d1c-3d0c-437e-afec-5d270f97b956\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"fc678314-7865-4709-b1ef-140dd3714b07\",\n          \"type\": \"image\",\n          \"scale\": 104,\n          \"focalX\": 48.15705128205128,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page06_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Crop man getting dollars from wallet\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3ccc5\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 412,\n          \"height\": 735,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e8999a18-5cbb-4b88-a498-22f8885616ea\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">Plan the BUDGET</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 97,\n          \"marginOffset\": -39.246,\n          \"id\": \"fe4f0a22-e9ec-44bc-a455-9c114e279e9a\",\n          \"x\": 63,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Set a budget. You will thank yourself later. Especially if it’s an extended adventure.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 63,\n          \"id\": \"d45497f9-9449-45d5-bedf-8a60724b2f73\",\n          \"x\": 54,\n          \"y\": 552,\n          \"marginOffset\": 2.4238636363636417,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 183,\n          \"y\": 399,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262525; text-transform: uppercase\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 47,\n          \"height\": 46,\n          \"marginOffset\": -17.091,\n          \"tagName\": \"p\",\n          \"id\": \"9d8e9afd-a771-4416-887a-692a4206a844\"\n        },\n        {\n          \"opacity\": 50,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 339,\n          \"height\": 386,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" },\n          \"id\": \"7c60ec3c-ab98-46ce-8c9a-73b65c006215\",\n          \"x\": 103,\n          \"y\": -157\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"74222a16-63ce-4dad-ad01-694e0fd3bace\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d45497f9-9449-45d5-bedf-8a60724b2f73\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"82ef1e4f-d2ad-4444-879a-ab69e34798ca\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"fc678314-7865-4709-b1ef-140dd3714b07\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"5a0673c5-5cea-42c4-8707-d901aa2423b2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"066ac186-4450-42f6-b5ef-d7c7468fe7fa\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"bbc849e7-de5e-43b4-a032-4cc9803e7025\",\n          \"type\": \"image\",\n          \"scale\": 104,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page07_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Crop anonymous person calculating profit on smartphone calculator near banknotes\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#d1cfd1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 412,\n          \"height\": 735,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9212dd92-1547-445e-8508-1438f37f4684\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Analyze all expenses</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 45,\n          \"marginOffset\": -39.246,\n          \"id\": \"3fed3621-6a88-481f-9cba-6d150b5e8834\",\n          \"x\": 74,\n          \"y\": 508,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Consider all your stops, your meals and any extra sites you want to stop at.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 65,\n          \"marginOffset\": 1.5261363636363647,\n          \"id\": \"a98a1ac2-be8c-4116-93de-75aca7d19c15\",\n          \"x\": 74,\n          \"y\": 552,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c8746a1d-fd8d-48b9-a4c2-2440dc9f3059\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"bbc849e7-de5e-43b4-a032-4cc9803e7025\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"3181fd90-98c9-4ee6-a648-b3bd233dfcab\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"f1f67da1-eeca-4e41-8448-09cf170ba53b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"765ca066-8b3b-42ff-a03f-4a47c4f69b9e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 861,\n          \"height\": 819,\n          \"sticker\": { \"type\": \"SummerAdventureTerrainMap\" },\n          \"id\": \"d05ae35a-0c29-4311-8032-ca3db939cf40\",\n          \"x\": -224.5,\n          \"y\": -100.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 70,\n          \"y\": 536,\n          \"id\": \"bde025b6-589a-43b3-876d-e8f357dbc3e8\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">No one wants to set a budget for travel, but even on the road, you should know what your expenses are.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 273,\n          \"height\": 84,\n          \"marginOffset\": 1.5261363636363647,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"x\": 56,\n          \"y\": 9,\n          \"width\": 300,\n          \"height\": 420,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"702d0714-f948-4056-855c-55ced617b352\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:57:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page08_image01.jpg\",\n            \"width\": 504,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Gold Iphone 7 Beside Space Gray Macbook Pro\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3d0d6\",\n            \"isExternal\": true\n          },\n          \"x\": 66,\n          \"y\": 19,\n          \"width\": 280,\n          \"height\": 400,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"69ac5502-79da-4a0a-a242-a41b1b7fae68\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 74, \"g\": 98, \"b\": 24 } },\n      \"type\": \"page\",\n      \"id\": \"41706c10-98cd-4756-8646-7f414f478de8\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"daad9226-a174-4c93-a168-44e4c514be3d\",\n          \"type\": \"image\",\n          \"scale\": 155,\n          \"focalX\": 50.000000000000014,\n          \"focalY\": 49.905493951612904,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"White vehicle photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#2c2a24\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 412,\n          \"height\": 735,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0a12a896-d9e6-4f6c-bcfc-50ab4ae655f4\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">plan</span>\\n<span style=\\\"font-weight: 700; color: #fec85a; text-transform: uppercase\\\">the route</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 100,\n          \"marginOffset\": -39.246,\n          \"id\": \"90e1de80-6674-4024-9265-45b1d5843225\",\n          \"x\": 63,\n          \"y\": 451,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fec85a\\\">When you are on the road a proper mapped plan will shine and keep you on the right track.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 63,\n          \"id\": \"1a12689b-378b-4686-96e6-969115fd5496\",\n          \"x\": 54,\n          \"y\": 552,\n          \"marginOffset\": 2.4238636363636417,\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 183,\n          \"y\": 399,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": true,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 8,\n            \"vertical\": 4\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #262525; text-transform: uppercase\\\">3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 100,\n            \"topRight\": 100,\n            \"bottomRight\": 100,\n            \"bottomLeft\": 100\n          },\n          \"width\": 47,\n          \"height\": 46,\n          \"marginOffset\": -17.091,\n          \"tagName\": \"p\",\n          \"id\": \"af755602-80d9-4d50-8d35-4b4274a7bf2e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9c7b1746-3e1b-4dca-8b57-ff6c4d17b0b5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1a12689b-378b-4686-96e6-969115fd5496\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"e8fcbd02-b5b4-4f28-9c95-1cf1e64661e5\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"daad9226-a174-4c93-a168-44e4c514be3d\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2d196e5d-736b-4852-aa99-31da88087270\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"4bdbd529-21fc-415a-b553-9aa8d85d380a\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {}\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3f9d6eac-460f-4944-b488-7bfb558baf80\",\n          \"type\": \"image\",\n          \"scale\": 104,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:11\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Photo of bonfire\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#241e1f\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"width\": 412,\n          \"height\": 735,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0d293a00-5116-46b9-a077-57ac0eb8ebd7\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Do it together</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 285,\n          \"height\": 45,\n          \"marginOffset\": -39.246,\n          \"id\": \"7d50f523-f7ee-4fa6-8eee-d794a3ddcd62\",\n          \"x\": 74,\n          \"y\": 485,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fec85a\\\">When it comes to route planning, the more the merrier. You’ll have a bunch of different ideas to choose from.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 264,\n          \"height\": 84,\n          \"marginOffset\": 1.5261363636363647,\n          \"id\": \"fa59c220-5a7d-4e27-afe7-862cc418dd64\",\n          \"x\": 74,\n          \"y\": 529,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1dea70f9-2ce6-4d45-b820-fcf5c16653d3\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"3f9d6eac-460f-4944-b488-7bfb558baf80\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"df444820-505b-4fbd-93f5-17f214fb10db\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6cb1e9c5-1636-41b3-ab03-747c726b7d90\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"37a5f6e4-ce39-42b7-90eb-b769ebc1156e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 861,\n          \"height\": 819,\n          \"sticker\": { \"type\": \"SummerAdventureTerrainMap\" },\n          \"id\": \"2dc27a8e-04c9-48c5-b16e-01c309686e09\",\n          \"x\": -224.5,\n          \"y\": -100.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 70,\n          \"y\": 536,\n          \"id\": \"5c83bca3-a2e9-4dd5-826f-7e00c3c1ccf3\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">There’s a whole subculture related to using physical maps, which is super fun and can be collected or framed later on.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 273,\n          \"height\": 84,\n          \"marginOffset\": 1.5261363636363647,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"x\": 56,\n          \"y\": 9,\n          \"width\": 300,\n          \"height\": 420,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2991d2ae-92fd-450b-b718-6c1e88471b6c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page11_image01.jpg\",\n            \"width\": 504,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Photo of Woman Sitting While Pointing on World Map\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1b096\",\n            \"isExternal\": true\n          },\n          \"x\": 66,\n          \"y\": 19,\n          \"width\": 280,\n          \"height\": 400,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2cc4777a-1bcf-4bc4-a87b-4bac5e4ad758\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 74, \"g\": 98, \"b\": 24 } },\n      \"type\": \"page\",\n      \"id\": \"4b501951-7fc4-4a54-97f0-035b728f705e\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"14d2245c-5615-4536-89db-3879fa01dfe9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Let’s recap</span>\\n<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">what we</span>\\n<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">learned</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 101,\n          \"marginOffset\": -15.990000000000002,\n          \"id\": \"70881c8f-7681-4f11-a4dc-0f7d5245c39d\",\n          \"x\": 188,\n          \"y\": 28,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 183,\n          \"y\": 174,\n          \"id\": \"4499c215-0509-4c8a-ab95-9ac7bf00f010\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">1.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 63,\n          \"marginOffset\": -27.183,\n          \"type\": \"text\",\n          \"groupId\": \"3922acf1-e470-4a68-a610-da8361786a3a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 183,\n          \"y\": 231,\n          \"id\": \"1180a7f4-c339-44e9-941a-6aea7d4da000\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Choose the right camper</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 41,\n          \"marginOffset\": -12.259000000000004,\n          \"type\": \"text\",\n          \"groupId\": \"3922acf1-e470-4a68-a610-da8361786a3a\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 117,\n          \"y\": 330,\n          \"id\": \"183d771f-bcc7-4918-af1a-b4e7083124f6\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">2.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 36,\n          \"height\": 64,\n          \"marginOffset\": -31.016999999999996,\n          \"type\": \"text\",\n          \"groupId\": \"dfbba1cf-c77c-4a54-a231-d7562892a139\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 117,\n          \"y\": 387,\n          \"id\": \"ee28c61e-d0c9-4ce2-ae23-e287c251412c\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Plan your budget</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 130,\n          \"height\": 41,\n          \"marginOffset\": -12.259000000000004,\n          \"type\": \"text\",\n          \"groupId\": \"dfbba1cf-c77c-4a54-a231-d7562892a139\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 188,\n          \"y\": 486,\n          \"id\": \"94326373-cbf7-42c1-9a63-f595d056a3ef\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a\\\">3.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 36,\n          \"height\": 64,\n          \"marginOffset\": -31.016999999999996,\n          \"type\": \"text\",\n          \"groupId\": \"6b76798b-2f81-485e-bb84-9264c6d9fbc4\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 188,\n          \"y\": 541,\n          \"id\": \"6593319f-6e62-4587-b39f-c7a041b0b4b8\",\n          \"content\": \"<span style=\\\"color: #fec85a\\\">Map the&nbsp;</span>\\n<span style=\\\"color: #fec85a\\\">route</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 109,\n          \"height\": 43,\n          \"marginOffset\": 1.5261363636363647,\n          \"type\": \"text\",\n          \"groupId\": \"6b76798b-2f81-485e-bb84-9264c6d9fbc4\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 239,\n          \"y\": 322,\n          \"id\": \"54396ce6-07fe-455e-8443-13cc7f3e0bda\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"type\": \"shape\",\n          \"width\": 85,\n          \"height\": 115,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"016d7792-3776-473b-841a-eac3949b11a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:30\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page12_image02.jpg\",\n            \"width\": 348,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Crop man getting dollars from wallet\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#37403c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 245.5,\n          \"y\": 329.5,\n          \"width\": 72,\n          \"height\": 100,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"945273b5-ff86-4ab2-8e56-b6898ba1edea\",\n          \"groupId\": \"016d7792-3776-473b-841a-eac3949b11a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"x\": 277,\n          \"y\": 325,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"f58d171a-abf6-43b7-8f52-6865a94bf0d8\",\n          \"groupId\": \"016d7792-3776-473b-841a-eac3949b11a0\"\n        },\n        {\n          \"x\": 286,\n          \"y\": 325,\n          \"id\": \"27ed2a38-3686-4ce8-b179-1642a09b1303\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"016d7792-3776-473b-841a-eac3949b11a0\"\n        },\n        {\n          \"x\": 245,\n          \"y\": 431,\n          \"id\": \"b9f4197e-f76a-4bd2-bbe0-ce8a4d3312f0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"016d7792-3776-473b-841a-eac3949b11a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"type\": \"shape\",\n          \"x\": 74,\n          \"y\": 158,\n          \"width\": 85,\n          \"height\": 115,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1339ed11-662a-42c9-a935-9dcf32f881df\",\n          \"groupId\": \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page12_image01.jpg\",\n            \"width\": 348,\n            \"height\": 481,\n            \"id\": 0,\n            \"alt\": \"White wooden storage bed and table photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#8b7b63\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 80.5,\n          \"y\": 165.5,\n          \"width\": 72,\n          \"height\": 100,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2a2fb6f8-7f65-4104-bef4-5534a0965829\",\n          \"groupId\": \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\"\n        },\n        {\n          \"x\": 113,\n          \"y\": 162,\n          \"id\": \"8624c105-0fb6-41a0-afc8-d54d8f502ace\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\"\n        },\n        {\n          \"x\": 122,\n          \"y\": 162,\n          \"id\": \"dc33bc40-890e-495d-8976-57182731f284\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\"\n        },\n        {\n          \"x\": 81,\n          \"y\": 268,\n          \"id\": \"3c44d228-c738-4f11-b187-d9a6bc42813d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\"\n        },\n        {\n          \"x\": 67,\n          \"y\": 487,\n          \"id\": \"e0554316-62bd-4bc7-bf5e-b3e04dbe8f63\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"type\": \"shape\",\n          \"width\": 85,\n          \"height\": 115,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"e006855a-54d3-4f31-bb37-282931b6cb9c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page12_image03.jpg\",\n            \"width\": 348,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"White vehicle photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#b0bcc5\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 73.5,\n          \"y\": 494.5,\n          \"width\": 72,\n          \"height\": 100,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"4df5b0ae-9f8d-4cbc-b072-4b63a590af9a\",\n          \"groupId\": \"e006855a-54d3-4f31-bb37-282931b6cb9c\"\n        },\n        {\n          \"x\": 106,\n          \"y\": 491,\n          \"id\": \"bb70c490-1bb4-40b1-a4f2-8a97979fd7de\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"e006855a-54d3-4f31-bb37-282931b6cb9c\"\n        },\n        {\n          \"x\": 115,\n          \"y\": 491,\n          \"id\": \"01d7adaa-25be-4a87-9102-b8ac0f6797e4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"e006855a-54d3-4f31-bb37-282931b6cb9c\"\n        },\n        {\n          \"x\": 74,\n          \"y\": 597,\n          \"id\": \"f23c4602-fa5b-466f-8086-6c20739a178f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 195, \"g\": 149, \"b\": 54 } },\n          \"type\": \"shape\",\n          \"width\": 2,\n          \"height\": 2,\n          \"mask\": { \"type\": \"circle\" },\n          \"groupId\": \"e006855a-54d3-4f31-bb37-282931b6cb9c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6ecd68eb-97e5-4547-9436-dc2a2f1309ec\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"70881c8f-7681-4f11-a4dc-0f7d5245c39d\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"864210de-e151-4314-87e1-adb8f743e1e8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4499c215-0509-4c8a-ab95-9ac7bf00f010\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"e8904a96-d10b-46a1-8d16-bb78b7feb282\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1180a7f4-c339-44e9-941a-6aea7d4da000\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"d9afb4a8-ad95-47c7-8740-c9a6297853c0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2a2fb6f8-7f65-4104-bef4-5534a0965829\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"44984c6f-0b01-4363-a1f2-d53fa2e7123f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1339ed11-662a-42c9-a935-9dcf32f881df\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"a2c70dec-dba5-422b-b51e-832e9c843dbd\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"945273b5-ff86-4ab2-8e56-b6898ba1edea\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"91c796c9-e59a-42da-8e37-58a2e62dbfca\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ee28c61e-d0c9-4ce2-ae23-e287c251412c\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"ad551be6-4451-4b58-8119-399d0dd41be1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"183d771f-bcc7-4918-af1a-b4e7083124f6\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"181d9a30-9e76-4530-ba02-a38e2bef176a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"54396ce6-07fe-455e-8443-13cc7f3e0bda\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"fb5f5bb8-112d-4d09-9b12-91882ef73e3e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4df5b0ae-9f8d-4cbc-b072-4b63a590af9a\"],\n          \"duration\": 1500,\n          \"delay\": 2100\n        },\n        {\n          \"id\": \"eb3759ee-f1b5-4354-bd98-0ae0795ffb71\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e0554316-62bd-4bc7-bf5e-b3e04dbe8f63\"],\n          \"duration\": 1500,\n          \"delay\": 2100\n        },\n        {\n          \"id\": \"139cdb7a-d875-4c51-82bf-0c8bfdfe19f0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6593319f-6e62-4587-b39f-c7a041b0b4b8\"],\n          \"duration\": 2000,\n          \"delay\": 2100\n        },\n        {\n          \"id\": \"936b4bb8-093e-4da6-a29c-faf3470bdd86\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"94326373-cbf7-42c1-9a63-f595d056a3ef\"],\n          \"duration\": 2000,\n          \"delay\": 2100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 41, \"g\": 50, \"b\": 21 } },\n      \"type\": \"page\",\n      \"id\": \"d1ba0eff-b1ae-4ab8-910a-16db3ea377fc\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"b1c5efdd-7cac-48ea-9e3a-158410e3dc6c\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"016d7792-3776-473b-841a-eac3949b11a0\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"e006855a-54d3-4f31-bb37-282931b6cb9c\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6b76798b-2f81-485e-bb84-9264c6d9fbc4\": {\n          \"name\": \"Third\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"dfbba1cf-c77c-4a54-a231-d7562892a139\": {\n          \"name\": \"Second\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3922acf1-e470-4a68-a610-da8361786a3a\": {\n          \"name\": \"First\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0f236654-3da0-4b66-af35-0e36ae55aad9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -97,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 461,\n          \"height\": 487,\n          \"sticker\": { \"type\": \"SummerAdventureDashedTrail\" },\n          \"id\": \"827aa426-9b01-403c-82dd-9d309757bef0\",\n          \"x\": 16,\n          \"y\": 210\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em; text-transform: uppercase\\\">Liked this story?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 96,\n          \"marginOffset\": -15.990000000000002,\n          \"id\": \"6efe5422-4c50-4514-9dc2-43b5967dbf0f\",\n          \"x\": 67,\n          \"y\": 30,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 34,\n            \"vertical\": 15\n          },\n          \"x\": 109,\n          \"y\": 556,\n          \"id\": \"fcdc29dc-6e07-4e72-a320-055fd4d2f56d\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.01em\\\">Click &nbsp;to explore</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80\n          },\n          \"width\": 195,\n          \"height\": 47,\n          \"marginOffset\": 1.5261363636363647,\n          \"type\": \"text\",\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": \"\",\n            \"desc\": \"https://google.com\"\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 254, \"g\": 200, \"b\": 90 } },\n          \"x\": 48.5,\n          \"y\": 309,\n          \"width\": 315,\n          \"height\": 178,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0e66280c-2f82-4603-9e8e-aa9a4a00a067\",\n          \"type\": \"shape\",\n          \"groupId\": \"642f35b3-7274-4159-bae1-5d246295825e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T05:58:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-adventure-guide/page13_image01.jpg\",\n            \"width\": 720,\n            \"height\": 382,\n            \"id\": 0,\n            \"alt\": \"Photo of people on seashore\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#413325\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 60.5,\n          \"y\": 321,\n          \"width\": 291,\n          \"height\": 154,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"99e3be02-8d83-4fed-a80e-a561f0fc63ef\",\n          \"groupId\": \"642f35b3-7274-4159-bae1-5d246295825e\"\n        },\n        {\n          \"x\": 67,\n          \"y\": 251,\n          \"id\": \"3cac3e7e-e7a7-47c0-9fbd-750906bd986e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; letter-spacing: 0.01em\\\">Next</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 45,\n          \"marginOffset\": -15.990000000000002,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 67,\n          \"y\": 500,\n          \"id\": \"908e0a86-6376-4f32-b954-ebb4a35c56a1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Teko\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 958,\n              \"des\": -475,\n              \"tAsc\": 958,\n              \"tDes\": -475,\n              \"tLGap\": 0,\n              \"wAsc\": 958,\n              \"wDes\": 475,\n              \"xH\": 488,\n              \"capH\": 626,\n              \"yMin\": -394,\n              \"yMax\": 866,\n              \"hAsc\": 958,\n              \"hDes\": -475,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fec85a; letter-spacing: 0.01em\\\">Why I Live Outdoors</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 278,\n          \"height\": 45,\n          \"marginOffset\": -15.990000000000002,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 196, \"g\": 196, \"b\": 196, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"x\": 141.5,\n          \"y\": 131,\n          \"width\": 129,\n          \"height\": 38,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"63010d0d-26b3-468f-b5e5-c4688d54a035\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"borderRadius\": {\n            \"topLeft\": 80,\n            \"topRight\": 80,\n            \"bottomRight\": 80,\n            \"bottomLeft\": 80,\n            \"locked\": false\n          },\n          \"link\": { \"url\": \"https://google.com\", \"icon\": null, \"desc\": null },\n          \"groupId\": \"aa8c2007-1cb7-4dbe-860d-fc9e0241924e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Inter\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2816,\n              \"asc\": 2728,\n              \"des\": -680,\n              \"tAsc\": 2728,\n              \"tDes\": -680,\n              \"tLGap\": 0,\n              \"wAsc\": 2728,\n              \"wDes\": 680,\n              \"xH\": 1536,\n              \"capH\": 2048,\n              \"yMin\": -900,\n              \"yMax\": 3072,\n              \"hAsc\": 2728,\n              \"hDes\": -680,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Share it</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 60,\n          \"height\": 17,\n          \"marginOffset\": -1.65340909090909,\n          \"type\": \"text\",\n          \"id\": \"b71ab8f8-08dd-482d-bad3-f66253cce1de\",\n          \"x\": 173,\n          \"y\": 142,\n          \"link\": {\n            \"url\": \"https://google.com\",\n            \"icon\": null,\n            \"desc\": \"https://google.com\"\n          },\n          \"groupId\": \"aa8c2007-1cb7-4dbe-860d-fc9e0241924e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 236,\n          \"y\": 143.5,\n          \"width\": 13,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"SummerAdventureShare\" },\n          \"id\": \"bfab27f8-6fff-47dc-a220-fa3a919db3ad\",\n          \"groupId\": \"aa8c2007-1cb7-4dbe-860d-fc9e0241924e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fdb8fe2f-ba9e-4f27-8dd0-0be32b188df1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6efe5422-4c50-4514-9dc2-43b5967dbf0f\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"27115c25-9f17-46dc-b591-2fa75c23ce82\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"63010d0d-26b3-468f-b5e5-c4688d54a035\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"45c21e88-483d-4594-9de7-b4d69a90ab5a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b71ab8f8-08dd-482d-bad3-f66253cce1de\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"3626a27e-73eb-4fb2-b983-5f48749fd171\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3cac3e7e-e7a7-47c0-9fbd-750906bd986e\"],\n          \"duration\": 2000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"ab402c4a-1d8a-4942-b3f5-0634e7e4d5a5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"99e3be02-8d83-4fed-a80e-a561f0fc63ef\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"f1c69719-3176-4da4-b110-61047d4032f5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0e66280c-2f82-4603-9e8e-aa9a4a00a067\"],\n          \"duration\": 2000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"9678d287-d612-4553-afc7-aa7131d7891e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"908e0a86-6376-4f32-b954-ebb4a35c56a1\"],\n          \"duration\": 2000,\n          \"delay\": 1250\n        },\n        {\n          \"id\": \"5606f234-c36f-4465-a251-7b913396266b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fcdc29dc-6e07-4e72-a320-055fd4d2f56d\"],\n          \"duration\": 2000,\n          \"delay\": 1250\n        },\n        {\n          \"id\": \"2cdc75d7-79d0-4246-a863-d0153f7f8273\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bfab27f8-6fff-47dc-a220-fa3a919db3ad\"],\n          \"duration\": 2000,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 41, \"g\": 50, \"b\": 21 } },\n      \"type\": \"page\",\n      \"id\": \"80d4fc14-2f06-48e1-a35f-90f1e3421632\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"642f35b3-7274-4159-bae1-5d246295825e\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aa8c2007-1cb7-4dbe-860d-fc9e0241924e\": {\n          \"name\": \"Share\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/summer-fashion-collection/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/summer-fashion-collection/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'summer-fashion-collection',\n  creationDate: '2021-08-03T00:00:00.000Z',\n  title: _x('Summer Fashion Collection', 'template name', 'web-stories'),\n  tags: [\n    _x('Fashion', 'template keyword', 'web-stories'),\n    _x('Clothing', 'template keyword', 'web-stories'),\n    _x('Summer', 'template keyword', 'web-stories'),\n    _x('Trendy', 'template keyword', 'web-stories'),\n    _x('Pink', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Sunset Pink', 'color', 'web-stories'),\n      color: '#FFC6DA',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Sunset Blue', 'color', 'web-stories'),\n      color: '#9BB0F0',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pearl Yellow', 'color', 'web-stories'),\n      color: '#FFF7CE',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Rubber Ducky Yellow', 'color', 'web-stories'),\n      color: '#FFE55C',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Show the latest styles and outfits with this template’s social media-inspired layout. The vibrant colors and popping font will let you create cool and trendy fashion stories, and you can add purchase links to showcased products.',\n    'web-stories'\n  ),\n  vertical: _x('Fashion & Beauty', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/summer-fashion-collection/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/summer-fashion-collection/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"dd6558cb-93a2-40f5-934d-6364f6953216\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -149,\n          \"y\": 465,\n          \"width\": 370,\n          \"height\": 370,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"d25b20c4-8bfc-4921-bfe9-d4ca436363c1\"\n        },\n        {\n          \"x\": 209,\n          \"y\": -94,\n          \"id\": \"7e876422-321b-4621-9778-49bf8163be65\",\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 370,\n          \"height\": 370,\n          \"sticker\": { \"type\": \"summerTrendStar\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Summer Trend Round-up</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": -8,\n          \"width\": 317,\n          \"height\": 129,\n          \"id\": \"29887750-6257-4680-82ff-f671a6c33506\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">by Vague’s </span><span style=\\\"font-weight: 500; text-transform: uppercase\\\">Mary Thompson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 129,\n          \"width\": 255,\n          \"height\": 17,\n          \"id\": \"d1476bd5-3d2c-4264-bd7a-e8106906fae2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"image\",\n          \"x\": 60,\n          \"y\": 224,\n          \"width\": 325,\n          \"height\": 512,\n          \"scale\": 110,\n          \"focalX\": 47.77063571649618,\n          \"focalY\": 51.40559171311535,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fccee789-2c8d-40ed-9cc9-bffa91784bcb\",\n          \"border\": {\n            \"left\": 9,\n            \"right\": 9,\n            \"top\": 9,\n            \"bottom\": 9,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:02:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page1_image1.jpg\",\n            \"width\": 720,\n            \"height\": 900,\n            \"id\": 0,\n            \"alt\": \"Woman holding her black hat\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#647285\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 225, \"g\": 129, \"b\": 65 }, \"position\": 0 },\n          { \"color\": { \"r\": 235, \"g\": 174, \"b\": 192 }, \"position\": 0.54 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"a108edbc-92be-4cba-807e-5bdbf551945f\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4cd4761f-7b2f-4581-b451-b344f875e5ae\"\n        },\n        {\n          \"x\": 114,\n          \"y\": 30,\n          \"id\": \"b3aed77b-f3d5-4fab-bef4-3dfbe761e59d\",\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" }\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 370,\n          \"height\": 370,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"6cb05af8-1568-47ef-9bcf-7428ec4cbaf9\",\n          \"x\": -146,\n          \"y\": -261\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.17,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Get Ready for Summer Days!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 58,\n          \"id\": \"d70dffda-e5dc-4ce5-a1da-a9855fa1002f\",\n          \"x\": 49,\n          \"y\": 434\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"Summer, the long-awaited season where we can be a little more casual with what we wear.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 76,\n          \"id\": \"b30305ca-241f-4d24-9b1c-e08ae72bb24a\",\n          \"x\": 48,\n          \"y\": 503\n        },\n        {\n          \"x\": 169,\n          \"y\": -66,\n          \"id\": \"0086bbe1-cd79-4900-93da-f36cc16f592c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"image\",\n          \"width\": 260,\n          \"height\": 332,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:03:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page2_image1.jpg\",\n            \"width\": 720,\n            \"height\": 921,\n            \"id\": 0,\n            \"alt\": \"Woman in yellow crew-neck t-shirt and blue denim bottoms\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#786b59\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"image\",\n          \"x\": -16,\n          \"y\": 38,\n          \"width\": 260,\n          \"height\": 332,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"249fc6ec-5a22-408a-ae49-36499d790be9\",\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:03:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page2_image2.jpg\",\n            \"width\": 722,\n            \"height\": 908,\n            \"id\": 0,\n            \"alt\": \"Woman in black off-shoulder shirt sitting on brown wooden stairs\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#978b83\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"faeb3537-5fde-496b-956c-ae57eea025c1\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"6cb05af8-1568-47ef-9bcf-7428ec4cbaf9\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1138d576-d0c8-4f98-bd6d-c93a9f5c828c\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"b3aed77b-f3d5-4fab-bef4-3dfbe761e59d\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 225, \"g\": 129, \"b\": 65 }, \"position\": 0 },\n          { \"color\": { \"r\": 235, \"g\": 174, \"b\": 192 }, \"position\": 0.54 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"ffe48325-d8c8-4aa9-b71a-769e698fac4f\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7ecefe2c-055a-46af-abf9-98f8145bc6c1\"\n        },\n        {\n          \"x\": -132,\n          \"y\": 391,\n          \"id\": \"1dc8ff59-73dc-401a-a72d-83f09c4b4ff8\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"ab8d481a-68dd-4a38-8441-31ae919a6a57\",\n          \"x\": 93,\n          \"y\": -188\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } },\n          \"type\": \"shape\",\n          \"x\": 33,\n          \"y\": 93,\n          \"width\": 346,\n          \"height\": 531,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"98f235f0-6612-4880-9b68-e4a4ac5f73a2\",\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">• The crop top • The crop top</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 886,\n          \"height\": 54,\n          \"id\": \"a58ea7fb-681c-4400-b658-9791b9ae2c58\",\n          \"x\": -172,\n          \"y\": 0,\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"x\": 45,\n          \"y\": 101,\n          \"id\": \"a3e1be48-e83c-42bc-9673-90bc673fde90\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 204, \"b\": 204 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:03:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page3_image1.jpg\",\n            \"width\": 720,\n            \"height\": 843,\n            \"id\": 0,\n            \"alt\": \"Woman in blue bralette holding sunglasses putting on her eyes\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#aa8e53\",\n            \"isExternal\": true\n          },\n          \"width\": 328,\n          \"height\": 400,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">@TuckerNYC123</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"x\": 103,\n          \"y\": 559,\n          \"width\": 194,\n          \"height\": 49,\n          \"id\": \"6e6d04b7-eac8-43cd-9823-0ec6be2f5ec0\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 521,\n          \"id\": \"4dd53764-0c12-41ba-a556-689bf50dbf5c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"This is 100% the craziest season ever\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 317,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 3,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 339,\n          \"y\": 483,\n          \"width\": 16,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"summerTrendInstragramIcon\" },\n          \"id\": \"19e056c8-2b48-469a-ac2f-ad89fb36f8a0\",\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 48,\n          \"y\": 472,\n          \"width\": 16,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"summerTrendHeart\" },\n          \"id\": \"fed92a3a-0fb4-426e-a15a-2ff46b630f22\",\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        },\n        {\n          \"x\": 69,\n          \"y\": 472,\n          \"id\": \"49b16344-c109-416a-add2-78ce9d942ddf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff7ce\\\">54,234 likes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 91,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"groupId\": \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 161, \"g\": 176, \"b\": 243 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.51 },\n          { \"color\": { \"r\": 169, \"g\": 219, \"b\": 236 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"9bddedee-ad4f-4abe-a391-76909650d68c\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"1b94a3aa-7de5-4cdd-a86e-b3e9f7d6be39\": {\n          \"name\": \"Card\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"a5507610-cde7-43e7-a14b-9d4f274068b4\",\n          \"scale\": 114,\n          \"focalX\": 50,\n          \"focalY\": 51.88459429824561,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:05:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page4_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in white and black crop top and blue denim shorts standing near red car\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#7f7873\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.33 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.5\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-style: italic; color: #fff7ce\\\">“The crop top is the quintessential summer staple. The right amount of bare summer skin”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 421,\n          \"width\": 317,\n          \"height\": 124,\n          \"id\": \"7bc35638-d9e9-4b2c-866c-7b8d34febdc0\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 566,\n          \"id\": \"7e934bba-68f0-49c4-a7ec-d4d87080b93c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">- Elizabeth F., Stylist</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 16\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"435a3a57-9843-48d4-8ee0-dbb2432be34f\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"a5507610-cde7-43e7-a14b-9d4f274068b4\"],\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"dfed90e0-f0fd-42bd-b4c7-e6855952d2cc\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"ff914cfc-c429-4983-a8f5-e4e3e82a9098\"\n      },\n      \"pageAttachment\": { \"theme\": \"light\" },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"59672ee4-cebe-44a3-9022-7757ef81b7dc\"\n        },\n        {\n          \"x\": 204,\n          \"y\": 451,\n          \"id\": \"73e06fa6-c3a6-4f98-9a35-5dc722a0cfc2\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" }\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -168,\n          \"y\": -331,\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"3792a30a-bb85-44ce-9377-7a89ccb5fe92\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:07:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page5_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman in black crew neck t-shirt wearing brown framed sunglasses standing on beach during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cfb7ab\",\n            \"isExternal\": true\n          },\n          \"x\": 180,\n          \"y\": 98,\n          \"width\": 241,\n          \"height\": 240,\n          \"scale\": 100,\n          \"focalX\": 50.103735354779225,\n          \"focalY\": 46.97417979114806,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f98aae9b-d7bd-4274-92e8-df26c0797b98\",\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          }\n        },\n        {\n          \"x\": 0,\n          \"y\": 98,\n          \"id\": \"1967cb4c-8d62-4663-b2af-e1dae9a85168\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:06:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page5_image1.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman in beige jacket wearing black sunglasses standing on beach during day\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a07f69\",\n            \"isExternal\": true\n          },\n          \"width\": 160,\n          \"height\": 240,\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          }\n        },\n        {\n          \"x\": 225,\n          \"y\": 358,\n          \"id\": \"864793a8-78f8-4664-a2f9-2be0e84ec271\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:09:01\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page5_image4.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman leaning beside orange wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b95d36\",\n            \"isExternal\": true\n          },\n          \"width\": 187,\n          \"height\": 205,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          }\n        },\n        {\n          \"x\": 0,\n          \"y\": 358,\n          \"id\": \"0cfeb16c-e1aa-4d21-b4a2-53f6d7af2d0f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:08:18\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page5_image3.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman raising right hand\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e07c62\",\n            \"isExternal\": true\n          },\n          \"width\": 205,\n          \"height\": 205,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Crop tops we love</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 217,\n          \"height\": 64,\n          \"id\": \"515aa5bc-73e6-4ea8-b185-617c0f33e405\",\n          \"x\": 97,\n          \"y\": -3\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">Shop the Items</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"width\": 194,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"id\": \"fe85f9c1-a78c-4aab-aa78-d9d9e0200945\",\n          \"x\": 108,\n          \"y\": 587,\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 161, \"g\": 176, \"b\": 243 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.51 },\n          { \"color\": { \"r\": 169, \"g\": 219, \"b\": 236 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"7d3625fb-7c89-4cae-b49f-b908f665edb2\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"9bf4d5e1-b696-40a5-b868-ee7f36ac5c1f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -132,\n          \"y\": 391,\n          \"id\": \"cbe9c697-bda5-47b5-a692-7c9324b8a85e\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"6eb9e99c-0415-4d3d-a5e1-8bfac11dd08c\",\n          \"x\": 93,\n          \"y\": -188,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } },\n          \"x\": 33,\n          \"y\": 77,\n          \"width\": 346,\n          \"height\": 531,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"22a12da3-3feb-46a5-a6f4-9a38aa6bcbaa\",\n          \"type\": \"shape\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 204, \"b\": 204 } },\n          \"x\": 41,\n          \"y\": 87,\n          \"id\": \"6268f158-d73d-4535-933f-fe08e30a826e\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:10:04\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page6_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Woman in pink suit walking near garden\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#756e74\",\n            \"isExternal\": true\n          },\n          \"width\": 328,\n          \"height\": 400,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">@Peacepenny</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"x\": 109,\n          \"y\": 536,\n          \"width\": 194,\n          \"height\": 49,\n          \"id\": \"cb951a34-b959-48b7-b6c5-6d9fa31f1f54\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 54.5,\n          \"y\": 498,\n          \"id\": \"8235fb7f-c898-469b-a185-5fa8f3dcc205\",\n          \"content\": \"Felt cute, definitely not deleting later.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 317,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": true,\n          \"x\": 348,\n          \"y\": 445,\n          \"width\": 16,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"summerTrendInstragramIcon\" },\n          \"id\": \"3b2103a9-46e4-437f-9f2f-6f3eaf6b1de2\",\n          \"type\": \"sticker\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": true,\n          \"x\": 60,\n          \"y\": 454,\n          \"width\": 16,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"summerTrendHeart\" },\n          \"id\": \"54f09a1b-fb4f-45c9-bee6-419c88737428\",\n          \"type\": \"sticker\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 81,\n          \"y\": 450,\n          \"id\": \"c1cf8322-4549-4b2b-a9bd-282aa72cc763\",\n          \"content\": \"<span style=\\\"color: #fff7ce\\\">54,234 likes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 91,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"groupId\": \"9947d792-9ca1-436f-b709-3ad80374431a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"letter-spacing: 0.05em; text-transform: uppercase\\\">The Matching Set•The Matching Set&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 1000,\n          \"height\": 54,\n          \"id\": \"4eb840ff-1576-4877-b895-2330c04e4a39\",\n          \"x\": -465,\n          \"y\": -4,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 255, \"g\": 198, \"b\": 218 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.51 },\n          { \"color\": { \"r\": 199, \"g\": 174, \"b\": 206 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"5b4f4c90-fb37-4406-b7ae-aee2b3a77429\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"9947d792-9ca1-436f-b709-3ad80374431a\": {\n          \"name\": \"Card\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 109,\n          \"focalX\": 54.11569826707442,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:15:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman wearing orange v-neck overall dress sitting on chair\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9a8177\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"85eb9e18-c706-4561-85db-af88e0365161\",\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 1\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-style: italic; color: #fff7ce\\\">“There is nothing cuter and more pulled together than a matching set for summer”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 421,\n          \"width\": 317,\n          \"height\": 124,\n          \"id\": \"cff9eb3f-21fc-4aa5-942f-2fc4b73a295b\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 566,\n          \"id\": \"332eb4be-1a2d-43d8-b2fc-dd727c896891\",\n          \"content\": \"<span style=\\\"color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">- </span><span style=\\\"color: #fff7ce; text-transform: uppercase\\\">Jane K., Editor at Belle</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 17,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"341b0972-28f1-43ff-af62-755860e18fbf\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"85eb9e18-c706-4561-85db-af88e0365161\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"f3f53115-2328-4e5a-b685-81132e70692a\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"ff914cfc-c429-4983-a8f5-e4e3e82a9098\"\n      },\n      \"pageAttachment\": { \"theme\": \"light\" },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"69b18303-c37a-4347-8e1c-d56b8596f1ef\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 85,\n          \"y\": 240,\n          \"id\": \"b804bf2f-4ae8-4a2d-8c16-bf9b1a94b271\",\n          \"width\": 465,\n          \"height\": 465,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -169,\n          \"y\": -301,\n          \"width\": 465,\n          \"height\": 465,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"4c215ac8-c7f2-4354-bf18-0aa49c6849d8\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:17:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page8_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman in white crew neck t-shirt wearing red and white floral headdress standing beside blue\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2c3a38\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 180,\n          \"y\": 98,\n          \"width\": 241,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c2e9c25f-c412-44b9-b923-bb5643367b62\",\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:17:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page8_image1.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Photo of woman standing on seashore\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ddd4d0\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": 98,\n          \"id\": \"9b851ad7-bbca-4d77-bfb0-01fb4151338f\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 160,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50.65571683664013,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:18:57\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page8_image4.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Celebrity sitting beside yellow flower fields\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#977350\",\n            \"isExternal\": true\n          },\n          \"x\": 225,\n          \"y\": 358,\n          \"id\": \"be146af2-86b4-4adc-8db8-6ab712791b67\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 187,\n          \"height\": 205,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50.000000000000014,\n          \"focalY\": 46.2915215010007,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:18:02\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page8_image3.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"id\": 0,\n            \"alt\": \"Woman wearing black and white polka dot shirt with black shorts holding black leather tote bag\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c6b8ad\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": 358,\n          \"id\": \"0de9d534-454f-45a1-ba3b-004d8c281d38\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 205,\n          \"height\": 205,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"letter-spacing: 0.05em; text-transform: uppercase\\\">Matching sets we love</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 308,\n          \"height\": 64,\n          \"id\": \"2c54cfc7-0a80-4cd8-9bd9-8976e83bd440\",\n          \"x\": 52,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff7ce; letter-spacing: 0.05em; text-transform: uppercase\\\">Shop the Items</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"width\": 194,\n          \"height\": 48,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"id\": \"39f6a377-b6ab-45ec-961a-021f4d893e6e\",\n          \"x\": 108,\n          \"y\": 587,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"081ecd5b-dd35-48a1-baba-3da060a9d085\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"4c215ac8-c7f2-4354-bf18-0aa49c6849d8\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"08364da1-3c86-44d5-9809-66823dce67ca\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"b804bf2f-4ae8-4a2d-8c16-bf9b1a94b271\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 255, \"g\": 198, \"b\": 218 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.51 },\n          { \"color\": { \"r\": 199, \"g\": 174, \"b\": 206 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"83c75c16-629a-406e-9e61-e3771d1ca481\",\n      \"pageTemplateType\": \"list\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2f20fdbc-8d60-4f4b-8e84-3d15de0aa018\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"9635ca81-80a0-4935-8cd2-037bead54946\",\n          \"x\": 88,\n          \"y\": -290,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } },\n          \"x\": 33,\n          \"y\": 93,\n          \"width\": 346,\n          \"height\": 531,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e8bc1283-4c3a-4b24-ba33-332d0d37b1ee\",\n          \"type\": \"shape\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": false,\n          \"scale\": 104,\n          \"focalX\": 49.03548348299196,\n          \"focalY\": 60.399734715241685,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:24:56\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page9_image1.jpg\",\n            \"width\": 720,\n            \"height\": 1066,\n            \"id\": 0,\n            \"alt\": \"Walking woman wearing red and white floral half-sleeved dress near the building during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#9a9595\",\n            \"isExternal\": true\n          },\n          \"x\": 45,\n          \"y\": 102,\n          \"id\": \"f08185d0-9bcb-460e-bd7e-8143c2d5e35e\",\n          \"backgroundColor\": { \"color\": { \"r\": 204, \"g\": 204, \"b\": 204 } },\n          \"width\": 328,\n          \"height\": 400,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"color: #fff7ce\\\">@EDITORATLARGE82</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"x\": 103,\n          \"y\": 559,\n          \"width\": 189,\n          \"height\": 47,\n          \"id\": \"048f8bf3-a755-4193-a942-2c27aa35744e\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"marginOffset\": 1.495000000000001,\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 40,\n          \"y\": 521,\n          \"id\": \"7caaf2c0-3422-48ab-b15f-cc9989fa20cc\",\n          \"content\": \"Never not wearing a one-piece romper\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 319,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 3,\n          \"lockAspectRatio\": true,\n          \"x\": 339,\n          \"y\": 483,\n          \"width\": 16,\n          \"height\": 16,\n          \"sticker\": { \"type\": \"summerTrendInstragramIcon\" },\n          \"id\": \"f167306c-72bb-4d09-9634-b08e7e22d143\",\n          \"type\": \"sticker\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"x\": 48,\n          \"y\": 472,\n          \"width\": 16,\n          \"height\": 14,\n          \"sticker\": { \"type\": \"summerTrendHeart\" },\n          \"id\": \"695bb9cc-9af6-4a61-b1fe-391c3a9fba0d\",\n          \"type\": \"sticker\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 2,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": false,\n            \"horizontal\": 0,\n            \"vertical\": 0\n          },\n          \"x\": 69,\n          \"y\": 472,\n          \"id\": \"140f6f93-2b28-4084-b9fc-a63ac61f2903\",\n          \"content\": \"<span style=\\\"color: #fff7ce\\\">54,234 likes</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 25,\n            \"topRight\": 25,\n            \"bottomRight\": 25,\n            \"bottomLeft\": 25\n          },\n          \"width\": 91,\n          \"height\": 19,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"type\": \"text\",\n          \"groupId\": \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"letter-spacing: 0.05em\\\">THE ONE PIECE • THE ONE PIECE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 886,\n          \"height\": 54,\n          \"id\": \"e81d6077-7563-405f-8c18-9029bbf17eea\",\n          \"x\": -349,\n          \"y\": -3,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 234, \"g\": 218, \"b\": 212 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.51 },\n          { \"color\": { \"r\": 200, \"g\": 201, \"b\": 244 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"019b8706-705a-4145-8dd5-0554a306b9b0\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8f209e48-e15a-4082-9dfe-76749ea2d7f8\": {\n          \"name\": \"Card\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"ff914cfc-c429-4983-a8f5-e4e3e82a9098\",\n          \"scale\": 107,\n          \"focalX\": 50,\n          \"focalY\": 48.174649532710276,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:28:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman with surfboard\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#96886e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ]\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-style: italic; color: #fff7ce\\\">“Lounging poolside or being active? Enter the chic one piece.”</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 452,\n          \"width\": 317,\n          \"height\": 93,\n          \"id\": \"086d6284-a73d-4bf2-88f9-2464336f1f80\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 578,\n          \"id\": \"e34918ab-fdea-4b2c-9788-c2686043c0e2\",\n          \"content\": \"<span style=\\\"color: #fff7ce; letter-spacing: 0.05em\\\">- PARKER N., BLOGGER</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 17,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"979f3b8c-3104-4c77-967d-b5f8c5eb91bd\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"ff914cfc-c429-4983-a8f5-e4e3e82a9098\"],\n          \"panDir\": \"topToBottom\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n          { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"a48f0bd7-b4df-4126-bbc4-8513a805c5a2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"883d76ed-eb06-4963-ac97-28db7b45c570\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b7a8238e-af68-4a1c-b6a2-2c5bbf07bd6b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 85,\n          \"y\": 240,\n          \"id\": \"d8723fa9-b30e-4142-9f92-4ed3da541b7b\",\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -169,\n          \"y\": -301,\n          \"width\": 417,\n          \"height\": 417,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"6606921d-176c-46ea-b188-dc397ef08c6c\",\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 49.657507877637656,\n          \"focalY\": 58.64947621146429,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:17:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page8_image1.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Photo of woman standing on seashore\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ded4cf\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 180,\n          \"y\": 98,\n          \"width\": 233,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ae294630-e72b-474c-a664-af2ce2b27362\",\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:29:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page11_image1.jpg\",\n            \"width\": 480,\n            \"height\": 722,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in red and white floral dress standing on water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c3bcaa\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": 98,\n          \"id\": \"fff87ebe-6de8-4433-b0c1-dc1215bd3009\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 160,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:30:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page11_image4.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing sun hat and yellow dress in front of brown concrete building\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c0a890\",\n            \"isExternal\": true\n          },\n          \"x\": 225,\n          \"y\": 358,\n          \"id\": \"dc0a21e2-7874-4f12-ad79-1e2fa3602890\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 187,\n          \"height\": 205,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:30:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page11_image3.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in white dress sitting on blue car during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d1c2ab\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": 358,\n          \"id\": \"377cb828-99d6-423b-b3d9-0416898d5a3e\",\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 205,\n          \"height\": 205,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"letter-spacing: 0.05em\\\">MATCHING SETS WE LOVE</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 308,\n          \"height\": 64,\n          \"id\": \"5d5ca571-93ee-4ff7-87f2-3536c01764a4\",\n          \"x\": 52,\n          \"y\": -3,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 30,\n            \"vertical\": 16\n          },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff7ce; letter-spacing: 0.05em\\\">SHOP THE ITEMS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 20,\n            \"topRight\": 20,\n            \"bottomRight\": 20,\n            \"bottomLeft\": 20\n          },\n          \"width\": 194,\n          \"height\": 49,\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          },\n          \"id\": \"0c44dd32-f034-4669-9350-b380310a9e5b\",\n          \"x\": 108,\n          \"y\": 587,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://www.google.com/\", \"icon\": \"\", \"desc\": \"\" }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"97d3a81f-3ae4-4a6a-85e1-73ab5ac5724e\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"6606921d-176c-46ea-b188-dc397ef08c6c\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e0463e81-832c-420f-a874-215fe8958da5\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"d8723fa9-b30e-4142-9f92-4ed3da541b7b\"],\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 234, \"g\": 218, \"b\": 212 }, \"position\": 0 },\n          { \"color\": { \"r\": 155, \"g\": 176, \"b\": 240 }, \"position\": 0.52 },\n          { \"color\": { \"r\": 200, \"g\": 201, \"b\": 244 }, \"position\": 1 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"c88b3a9a-3607-4191-a252-470e03b9f641\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"91b77b5f-747c-45dc-8d73-32bf217ae0ca\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": -139,\n          \"y\": -96,\n          \"id\": \"ea441a89-146a-42c8-a902-ef5c4a38cb2d\",\n          \"width\": 465,\n          \"height\": 465,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"width\": 370,\n          \"height\": 370,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"9cdeba2e-ef98-4a34-94b1-c579f22102d2\",\n          \"x\": -148,\n          \"y\": -261,\n          \"type\": \"sticker\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"So yes these are trends, but they are really timeless at the end of the day. \\n\\nEven the crop top can be worn year after year. Rule of thumb: just keep the style current.\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 315,\n          \"height\": 182,\n          \"id\": \"75a20a13-104b-4e44-b5db-a39b0843a2ce\",\n          \"x\": 48,\n          \"y\": 390,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -4,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -49,\n          \"y\": -75,\n          \"width\": 260,\n          \"height\": 333,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6bdcc2a9-7599-4b02-b0f8-601429ae4f13\",\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:31:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page12_image1.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in red spaghetti strap top standing beside brown concrete wall during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dfd6cb\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 5,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 177,\n          \"y\": -3,\n          \"id\": \"77d86782-951b-45de-b80b-a7379b994628\",\n          \"width\": 253,\n          \"height\": 338,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 5,\n            \"right\": 5,\n            \"top\": 5,\n            \"bottom\": 5,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:32:33\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page12_image2.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in green and blue tube dress holding blue textile\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2f3028\",\n            \"isExternal\": true\n          }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c4694f54-248e-423f-9954-ce40fd5a2a01\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"77d86782-951b-45de-b80b-a7379b994628\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6b82512b-dc08-4a76-a73f-5916c51a9ffb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6bdcc2a9-7599-4b02-b0f8-601429ae4f13\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0d47ee74-880e-471c-85d5-58cd76808cbe\",\n          \"type\": \"effect-twirl-in\",\n          \"targets\": [\"ea441a89-146a-42c8-a902-ef5c4a38cb2d\"],\n          \"duration\": 2500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 225, \"g\": 129, \"b\": 65 }, \"position\": 0 },\n          { \"color\": { \"r\": 235, \"g\": 174, \"b\": 192 }, \"position\": 0.54 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"614c5001-ed97-46a0-9d97-9168011d5d19\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bf1623ae-6d5a-4ada-b40f-cde451366f97\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 465,\n          \"height\": 465,\n          \"sticker\": { \"type\": \"summerTrendStar\" },\n          \"id\": \"daaa41df-36b5-43eb-97cd-626c7cec8558\",\n          \"x\": 156,\n          \"y\": 53\n        },\n        {\n          \"x\": -125,\n          \"y\": 447,\n          \"id\": \"9f2f003b-72bb-48ba-99c5-8f51821417e5\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 313,\n          \"height\": 313,\n          \"sticker\": { \"type\": \"summerTrendStar\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Ultra\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2066,\n              \"des\": -561,\n              \"tAsc\": 2066,\n              \"tDes\": -561,\n              \"tLGap\": 0,\n              \"wAsc\": 2066,\n              \"wDes\": 561,\n              \"xH\": 1102,\n              \"capH\": 1473,\n              \"yMin\": -561,\n              \"yMax\": 2066,\n              \"hAsc\": 2066,\n              \"hDes\": -561,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"MORE STYLE ROUND-UPS\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 224,\n          \"height\": 64,\n          \"id\": \"7a68d516-00a7-4efd-a2d7-b57ab83f23e2\",\n          \"x\": 94,\n          \"y\": -3\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"Michelle Yan from Hypebeast\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 152,\n          \"height\": 49,\n          \"type\": \"text\",\n          \"id\": \"b88f9de5-4b17-4ea6-9bf1-541e36cd00ae\",\n          \"x\": 210,\n          \"y\": 141,\n          \"groupId\": \"6e6bda5a-ba8d-4d39-a64f-9f1671d43608\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 3,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 50,\n          \"y\": 103,\n          \"width\": 136,\n          \"height\": 149,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"792798d4-cb3e-42bb-bf1b-6bb3a05fbd44\",\n          \"border\": {\n            \"left\": 4,\n            \"right\": 4,\n            \"top\": 4,\n            \"bottom\": 4,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:38:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page13_image1.jpg\",\n            \"width\": 480,\n            \"height\": 527,\n            \"id\": 0,\n            \"alt\": \"Selective focus photography of woman standing beside rail during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a6a4a0\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"6e6bda5a-ba8d-4d39-a64f-9f1671d43608\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 505,\n          \"id\": \"cbc39705-f444-46af-950e-ad4092c5d95d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"Seven work from home looks\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 152,\n          \"height\": 50,\n          \"type\": \"text\",\n          \"groupId\": \"90972d0d-c9d9-454f-b0fe-22e80cdc2374\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 455,\n          \"id\": \"ea6c10d5-19b9-46d2-be95-39bfa5f7bece\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 5,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 136,\n          \"height\": 149,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 4,\n            \"right\": 4,\n            \"top\": 4,\n            \"bottom\": 4,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:39:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page13_image3.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Woman wearing black shirt standing in front of wall\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c1b5ad\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"90972d0d-c9d9-454f-b0fe-22e80cdc2374\"\n        },\n        {\n          \"x\": 71,\n          \"y\": 318,\n          \"id\": \"14157845-3d99-4d8a-99f7-5fc7137b4b7a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"Zenraya’s Summer Looks\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 152,\n          \"height\": 50,\n          \"type\": \"text\",\n          \"groupId\": \"687c1444-b285-4137-8f69-250a3d622e50\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 228,\n          \"y\": 244,\n          \"id\": \"92ac4060-73c3-4141-ba05-1cc0f7c7b114\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -6,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 136,\n          \"height\": 194,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 4,\n            \"right\": 4,\n            \"top\": 4,\n            \"bottom\": 4,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 247, \"b\": 206 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-06-07T14:38:54\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/summer-fashion-collection/page13_image2.jpg\",\n            \"width\": 480,\n            \"height\": 687,\n            \"id\": 0,\n            \"alt\": \"Woman in yellow dress sitting on sand during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a89087\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"687c1444-b285-4137-8f69-250a3d622e50\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"765fe380-38f2-4ca6-bc5a-8f55c999c536\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b88f9de5-4b17-4ea6-9bf1-541e36cd00ae\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"25842c14-d9bf-4b44-8fba-36753f6496e0\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"14157845-3d99-4d8a-99f7-5fc7137b4b7a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"2c44f612-6bf0-46c1-9f96-58861a157dd3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cbc39705-f444-46af-950e-ad4092c5d95d\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": {\n        \"type\": \"linear\",\n        \"stops\": [\n          { \"color\": { \"r\": 225, \"g\": 129, \"b\": 65 }, \"position\": 0 },\n          { \"color\": { \"r\": 235, \"g\": 174, \"b\": 192 }, \"position\": 0.54 }\n        ],\n        \"rotation\": 0.5\n      },\n      \"type\": \"page\",\n      \"id\": \"17f1455e-5e7e-434d-a408-c5dc395e9db2\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"6e6bda5a-ba8d-4d39-a64f-9f1671d43608\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"687c1444-b285-4137-8f69-250a3d622e50\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"90972d0d-c9d9-454f-b0fe-22e80cdc2374\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sustainability-tips/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/sustainability-tips/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'sustainability-tips',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Sustainability Tips', 'template name', 'web-stories'),\n  tags: [\n    _x('Health & Wellness', 'template keyword', 'web-stories'),\n    _x('Sustainability', 'template keyword', 'web-stories'),\n    _x('Environment', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Eco Green', 'color', 'web-stories'),\n      color: '#134f3c',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Acorn Orange', 'color', 'web-stories'),\n      color: '#bb7c48',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Light Dutch White', 'color', 'web-stories'),\n      color: '#fdf0d6',\n      family: _x('White', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template’s soft earthly colors and readable font will let you create beautiful and calming stories for nature topics. Add your own illustrations and create infographics, how-to guides and more.',\n    'web-stories'\n  ),\n  vertical: _x('Health & Wellness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/sustainability-tips/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/sustainability-tips/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"77a513d7-5f7b-4795-9525-10ff2378cfc4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T13:51:07\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page1_image1.png\",\n            \"width\": 1260,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Vector Illustration Of Save The Planet Concept\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#ede6cc\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -173,\n          \"y\": 242,\n          \"width\": 759,\n          \"height\": 432,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f0b5ace2-b25c-41e6-9755-e75d84eeb4b2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Sustainability Tips for Living Green Daily</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 43.5,\n          \"y\": 4,\n          \"width\": 325,\n          \"height\": 167,\n          \"id\": \"a95e0ba7-ccc1-462e-879b-d705947194ec\"\n        },\n        {\n          \"x\": 44,\n          \"y\": 180,\n          \"id\": \"428f9e6b-3dc3-4221-aa36-9241bfd2c6bb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Written by John Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 23\n        },\n        {\n          \"x\": 44,\n          \"y\": 201,\n          \"id\": \"53fb1d2d-1abe-40a8-84b8-b32bacf81c70\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48\\\">July 22, 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 23\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"53d519bc-2c93-4301-8e8e-30bac768ad46\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"144c49cc-b861-4ed5-8b3c-0758c9de6770\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T13:53:43\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page2_image1.png\",\n            \"width\": 967,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Woman Cycling High-Res Vector Graphic\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#dfd2ae\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 239,\n          \"width\": 464,\n          \"height\": 344,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"0f42aee8-bb4e-41f0-a0de-ff27488a9509\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Travel slow if you can</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 52.5,\n          \"y\": 103,\n          \"width\": 307,\n          \"height\": 93,\n          \"id\": \"f1e453af-9648-48fa-98f7-f71096f8575d\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 44,\n          \"y\": 70,\n          \"id\": \"61c44b93-02eb-4a20-b21a-cb4c259c7348\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Tip 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 33,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5ab46562-2596-4347-a22c-e80b075f7bf3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0f42aee8-bb4e-41f0-a0de-ff27488a9509\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e35169e6-6a2b-48b3-b4c6-1de766500d5b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f1e453af-9648-48fa-98f7-f71096f8575d\"],\n          \"duration\": 750,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"654b0843-b6d8-4c5d-a870-a87b70bd2d69\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 678,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e24583da-3ee1-483e-b5c0-32dbdd8e5df9\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T08:05:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 2220,\n            \"id\": 0,\n            \"alt\": \"Train During Golden Hour\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#5d6063\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -58,\n          \"y\": 466,\n          \"width\": 586,\n          \"height\": 351,\n          \"sticker\": { \"type\": \"cloudBanner\" },\n          \"id\": \"8222f5cf-0c35-4a2c-86b5-de59899d4efd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #134f3c\\\">If you have the luxury of time, try traveling by train or by boat to offset carbon emissions</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 61,\n          \"y\": 553,\n          \"width\": 307,\n          \"height\": 71,\n          \"id\": \"9048c820-4244-4373-8947-b185ef5b178c\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"62050b21-7029-42be-b960-5afaa5dde21f\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"e24583da-3ee1-483e-b5c0-32dbdd8e5df9\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"f8050e79-c2e7-457f-9b3f-fac8f1417122\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"cb2331ce-0fac-45e2-bd55-d5cc88f31811\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0651d9ca-fc05-4602-8726-fec7ee361682\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T13:56:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page4_image1.png\",\n            \"width\": 562,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"People Traveling Set High-Res Vector Graphic\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#efd0b5\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 42,\n          \"y\": 229,\n          \"width\": 286,\n          \"height\": 367,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a60da82f-faa9-4946-93ed-c3df4b8fa2c9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Choose your airlines w</span><span style=\\\"font-weight: 700; color: #134f3c\\\">isely</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 52,\n          \"y\": 103,\n          \"width\": 307,\n          \"height\": 93,\n          \"id\": \"053df1fd-98b1-4a8b-b291-8848d3d794e4\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 44,\n          \"y\": 70,\n          \"id\": \"49253ce9-7504-4c5e-acc7-b1e5b951fc51\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Tip 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 34,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e4f90b6a-549b-45ee-873e-b0af7cd5faf9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a60da82f-faa9-4946-93ed-c3df4b8fa2c9\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"cd20d7dd-ca9e-4da6-8dcd-85495343eb65\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"053df1fd-98b1-4a8b-b291-8848d3d794e4\"],\n          \"duration\": 750,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"fcf0af06-9f6e-48a7-ad17-b16860e9b8ff\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 678,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"233ab831-f310-46de-83f7-7d15add09574\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 51.93050193050194,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T08:08:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page5_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 2220,\n            \"id\": 0,\n            \"alt\": \"Man standing holding luggage during daytime\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#9ea199\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 586,\n          \"height\": 351,\n          \"sticker\": { \"type\": \"cloudBanner\" },\n          \"id\": \"c651a97a-27ce-453d-809b-c71dff8cc029\",\n          \"x\": -58,\n          \"y\": 466\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #134f3c\\\">Pick an airline that lets you offset your travel emissions when you purchase your ticket.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 61,\n          \"y\": 553,\n          \"width\": 307,\n          \"height\": 71,\n          \"id\": \"24f0ed91-58d9-4703-8f5a-ea6d84adc4cd\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0812c0f3-f23a-4e18-93ff-9ce4e07e77af\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"233ab831-f310-46de-83f7-7d15add09574\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"63a3ee29-7301-4ccd-8dcc-5651a061e0a7\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"94811709-ad86-4f81-9e04-b32045d80f29\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"1bc45fd1-5875-4793-a46f-561db93d7934\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 99.91658481210044,\n          \"focalX\": 50,\n          \"focalY\": 50.04174241346241,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T13:58:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page6_image1.png\",\n            \"width\": 612,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Vector Illustration Of Recycling Concept Flat Modern Design\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#c5c69b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -16.5,\n          \"y\": 146,\n          \"width\": 445,\n          \"height\": 524,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b0330b84-6899-41ee-9276-5fbe56ca7bc3\",\n          \"resizeWidth\": 252,\n          \"resizeHeight\": 320.65\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Reduce your waste</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 52,\n          \"y\": 103,\n          \"width\": 307,\n          \"height\": 93,\n          \"id\": \"4c651159-e6cc-47fc-ba54-292432f8b185\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 44,\n          \"y\": 70,\n          \"id\": \"dc633e84-886f-48a3-963e-bd5241f94461\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Tip 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 34,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1894d1f3-52d7-4a23-a11e-c073c8d762c5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b0330b84-6899-41ee-9276-5fbe56ca7bc3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"69b83d53-b3d2-4cb9-bddb-2c9a611c5786\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4c651159-e6cc-47fc-ba54-292432f8b185\"],\n          \"duration\": 750,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"5da19e79-ac72-4f2e-82b4-24fdcee54b39\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 678,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"b5282b0c-df23-4f3e-9c66-c2ca8c3c0adf\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 56.75675675675676,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T08:10:06\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 2220,\n            \"id\": 0,\n            \"alt\": \"Person holding white plastic bag\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#a4998d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 586,\n          \"height\": 351,\n          \"sticker\": { \"type\": \"cloudBanner\" },\n          \"id\": \"8de3373e-8c7f-4308-aaa6-0bf2f66cc061\",\n          \"x\": -58,\n          \"y\": 422\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #134f3c\\\">The amount of trash we generate personally on a daily and annual basis is staggering. Whenever possible, bring your own utensils and bags.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 61,\n          \"y\": 508,\n          \"width\": 307,\n          \"height\": 115,\n          \"id\": \"6e413a4d-5546-4537-baf7-66c68b814714\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"0b4bbffc-2e18-4247-9c2a-aeab8a9a434b\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"b5282b0c-df23-4f3e-9c66-c2ca8c3c0adf\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"73b83700-bb97-4894-8b9e-4db94205815d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"978e2840-02fd-4725-8520-b30a35bf023b\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b32caf0c-8597-4079-a670-f8e1b8b04944\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T14:02:28\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page8_image1.png\",\n            \"width\": 610,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Paper Bag Full Of Grocery High-Res Vector Graphic\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#e7cda3\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 29,\n          \"y\": 215,\n          \"width\": 337,\n          \"height\": 398,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"057159f3-746c-4118-8d33-32843193e17c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Buy in bulk</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 52,\n          \"y\": 103,\n          \"width\": 307,\n          \"height\": 57,\n          \"id\": \"f4331b26-3fad-49ba-af63-170baad95e93\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 44,\n          \"y\": 70,\n          \"id\": \"7798aae7-f9a7-458e-833d-1c28ba12176b\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Tip 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 34,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cf573c8b-ce44-4dbb-9fab-3ab153b77400\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"057159f3-746c-4118-8d33-32843193e17c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 7000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a8d3d3ff-9cbb-4a69-9a8f-176b7a403e34\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f4331b26-3fad-49ba-af63-170baad95e93\"],\n          \"duration\": 750,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"8819482e-8301-404d-92bd-9e73c96eee99\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 678,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"ebfadcf7-a4be-4e0a-a91d-db1b45c42145\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 56.75675675675676,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T08:10:29\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page9_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 2220,\n            \"id\": 0,\n            \"alt\": \"Person Holding Almonds\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#bfb3b1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 586,\n          \"height\": 351,\n          \"sticker\": { \"type\": \"cloudBanner\" },\n          \"id\": \"c6a55251-32a4-455b-b41d-69cdca45e161\",\n          \"x\": -58,\n          \"y\": 422\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #134f3c\\\">Not only is it cheaper to buy in bulk, you reduce the amount of product packaging going into landfills.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 61,\n          \"y\": 530,\n          \"width\": 307,\n          \"height\": 71,\n          \"id\": \"fca968a9-935c-4160-98c6-618c2ca8c2d4\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9511eaa3-fad8-43ca-acf5-29bb00308bf0\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"ebfadcf7-a4be-4e0a-a91d-db1b45c42145\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"fe04cd4d-2aad-40f0-99f9-79da3e038a03\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6d7ef52d-2479-4327-aad2-d8ece81b733c\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"dc04e36c-de8c-4a66-aed4-59ea2a8f828f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T14:04:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page10_image1.png\",\n            \"width\": 648,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Fast Food Flat Icons Set High-Res Vector Graphic\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#ebd6b4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 54,\n          \"y\": 194,\n          \"width\": 317,\n          \"height\": 354,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6db250a1-8212-4f2d-8da5-d80ef5f82e23\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #134f3c\\\">Reduce food</span>\\n<span style=\\\"font-weight: 700; color: #134f3c\\\">waste</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 52,\n          \"y\": 103,\n          \"width\": 307,\n          \"height\": 93,\n          \"id\": \"6d328bb3-8463-4622-9682-87713ffbcb2b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 44,\n          \"y\": 70,\n          \"id\": \"c97ef15e-0806-497e-9612-eaed8e22bba8\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #bb7c48; text-transform: uppercase\\\">Tip 5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 34,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"c3f5bf18-e044-4c25-8ed0-caba66202213\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6d328bb3-8463-4622-9682-87713ffbcb2b\"],\n          \"duration\": 750,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"662fae1c-7626-4a30-9b52-ffc9fd4c1bc4\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 678,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"7bc4c9d5-ba29-4fd3-9b15-2a3ccaaca2ce\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 56.75675675675676,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-22T08:11:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 2220,\n            \"id\": 0,\n            \"alt\": \"Person holding yellow and green gardening shovel\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#6e5a46\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 586,\n          \"height\": 351,\n          \"sticker\": { \"type\": \"cloudBanner\" },\n          \"id\": \"bc26b204-0a5f-4fba-8072-0024b53e5a33\",\n          \"x\": -58,\n          \"y\": 422\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #134f3c\\\">Reducing food waste and composting are great ways to offset your footprint. Find a community compost station near you.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 61,\n          \"y\": 508,\n          \"width\": 307,\n          \"height\": 92,\n          \"id\": \"6e4137cb-093e-4a67-b8cd-52334cec3cba\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"dc5026a1-c80a-471b-a7df-ccdb83083040\",\n          \"type\": \"effect-background-pan\",\n          \"panDir\": \"bottomToTop\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"7bc4c9d5-ba29-4fd3-9b15-2a3ccaaca2ce\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 253, \"g\": 240, \"b\": 214 } },\n      \"type\": \"page\",\n      \"id\": \"2704872a-f238-43b4-b28a-1b98d9abee74\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b8844bfb-2f10-4e10-a160-2812c895d5aa\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"fb6f1381-ba7e-4cf8-8809-e4a476fe97a1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fdf0d6\\\">Energy saving tips that will save the world</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 111,\n          \"type\": \"text\",\n          \"id\": \"0225d77f-d1d1-4e77-b334-0fb8888c9c01\",\n          \"x\": 47,\n          \"y\": 486\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">From Jane Dow</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 307,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"id\": \"18137c6a-cded-4510-abfc-833ff59855de\",\n          \"x\": 47,\n          \"y\": 66\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Prompt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1090,\n              \"des\": -422,\n              \"tAsc\": 750,\n              \"tDes\": -250,\n              \"tLGap\": 200,\n              \"wAsc\": 1090,\n              \"wDes\": 422,\n              \"xH\": 536,\n              \"capH\": 714,\n              \"yMin\": -368,\n              \"yMax\": 1061,\n              \"hAsc\": 1090,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.05,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fdf0d6; text-transform: uppercase\\\">Up Next</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 325,\n          \"height\": 33,\n          \"type\": \"text\",\n          \"id\": \"ecacbfe0-4372-4eba-b804-28c5e8e83b88\",\n          \"x\": 47,\n          \"y\": 28\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T14:06:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/sustainability-tips/page12_image1.png\",\n            \"width\": 690,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Illustration of Windmills\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#47443f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 36,\n          \"y\": 111,\n          \"width\": 350,\n          \"height\": 365,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"32159c7e-a95f-406d-8bb2-a6fbd56ba3bb\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e8d6ffb3-21c3-4eb9-b162-562b6dabc1f7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0225d77f-d1d1-4e77-b334-0fb8888c9c01\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 73, \"g\": 69, \"b\": 61 } },\n      \"type\": \"page\",\n      \"id\": \"49a34cbc-7b00-447b-992d-bd60c5d10636\",\n      \"pageTemplateType\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/technology-advice/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/technology-advice/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'technology-advice',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x('Technology Advice', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Studio', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Modern', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cod Black', 'color', 'web-stories'),\n      color: '#444849',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Cosmonaut Gray', 'color', 'web-stories'),\n      color: '#dedede',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its smooth gray shades and corner frame accents, this template is like your very own professional tech review studio. Use photos and videos and create informative, sleek-looking product reviews, comparisons and buying guides for your audience.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/technology-advice/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/technology-advice/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"167a9bd6-cd10-41ab-afaa-661e4f44ac81\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:21\",\n            \"baseColor\": \"#161716\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page01_image02.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Black folding chair on canvas photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -59,\n          \"y\": 260,\n          \"width\": 628,\n          \"height\": 419,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"2032887d-219a-4a9a-9121-0877c2787825\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 473,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"af56fe17-5bf9-4d4d-af77-79c7ff22337e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page01_image01.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Black camera photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#3f4040\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 243,\n          \"y\": 24,\n          \"width\": 99,\n          \"height\": 149,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"87df7b4a-377f-47f4-9748-548355b978be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #1a1a1a\\\">Everything You Need For A Home Video Studio</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 207,\n          \"width\": 304,\n          \"height\": 123,\n          \"id\": \"93d8d962-f3c4-4d52-9301-cc609c08083c\",\n          \"marginOffset\": 9.84375\n        },\n        {\n          \"x\": 47,\n          \"y\": 132,\n          \"id\": \"4c188b55-5c84-423a-8ba8-c3aeae17c101\",\n          \"opacity\": 75,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #1a1a1a; letter-spacing: 0.02em; text-transform: uppercase\\\">Technology advice</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 19,\n          \"marginOffset\": 9.84375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 47,\n          \"y\": 0,\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioGrayFrameCorner\" },\n          \"id\": \"a81c8218-6495-4111-b088-b56753263e5c\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"7739dc34-fa9c-4527-8556-56a3d20b255a\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c386e333-c25e-4753-932b-becdee0151d8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-13T11:59:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page02_bgvideo.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page02_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 24,\n            \"lengthFormatted\": \"0:24\",\n            \"alt\": \"Video Footage Of A Male Photographer In Action\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#826e55\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"633ed51c-a46a-43c6-93c4-cb69a116062a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.8\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7aeec725-cd40-4045-b189-95c50df58f9f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 25,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Matthew Donner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 34,\n          \"marginOffset\": 9.84375,\n          \"id\": \"d0d7b713-8deb-4bfd-aaf2-1330979b1b41\",\n          \"x\": 54,\n          \"y\": 491\n        },\n        {\n          \"x\": 54,\n          \"y\": 534,\n          \"id\": \"caa32409-4e2b-42ed-a6a3-8396f9f8d5ff\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Founder, Sky High Videos</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 21,\n          \"marginOffset\": 9.84375\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"4a96c637-97fc-49b8-93bc-693d24b3ed17\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"1b4ade05-ef35-4340-aff0-d65cb581a505\",\n          \"scale\": 107,\n          \"focalX\": 50,\n          \"focalY\": 53.105420793064994,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man standing on brown field carrying black recording camera during daytime photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#a1a1a0\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.13 },\n                \"position\": 0.27\n              },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.26 },\n                \"position\": 0.51\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.64\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3929da7d-33d4-4d67-a0ab-510f1a01411c\",\n          \"x\": 0,\n          \"y\": -60\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 25,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">What are you going to be filming? Will you be on the go? Or static in the studio?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 96,\n          \"marginOffset\": 0,\n          \"id\": \"75cfcda7-af7d-40dd-825f-5e6964ca40bd\",\n          \"x\": 47,\n          \"y\": 0,\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 47,\n          \"y\": 598,\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioWhiteFrameCorner\" },\n          \"id\": \"80795641-48c8-4095-b28c-cc7c4beba29e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"74843fe2-f1ed-482f-ac9c-faf29a4cc865\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"1b4ade05-ef35-4340-aff0-d65cb581a505\"],\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c546c742-c032-4cce-8f21-764b3a9c2ea2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e6c25952-24f2-4508-8b50-a5fb4b34f03e\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"8fe1f528-32d9-418d-b834-a54f353ab756\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:45\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page04_image01.jpg\",\n            \"width\": 576,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Flat lay photography of black Red TV camcorder set photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#bfc0c2\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 537,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"27740faa-0211-4168-8f69-142660333a6c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.13 },\n                \"position\": 0.27\n              },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.26 },\n                \"position\": 0.51\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.64\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 537,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5f8b7c67-929d-4020-b89a-e2f8145ee478\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 480,\n          \"width\": 412,\n          \"height\": 195,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2d7caaa6-8c4c-4ea6-9d9c-1b651d76952c\",\n          \"groupId\": \"4a6f46b0-177c-4c44-9e5d-cd16f3f94826\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">As a preferred choice, RED Camera offers unprecedented configurability and quality for outdoor and indoor shooting.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 522,\n          \"width\": 299,\n          \"height\": 90,\n          \"id\": \"e42a76a2-a293-4bac-bf2e-4e9e74b2abeb\",\n          \"marginOffset\": 9.84375,\n          \"groupId\": \"4a6f46b0-177c-4c44-9e5d-cd16f3f94826\"\n        },\n        {\n          \"x\": 344,\n          \"y\": 586,\n          \"id\": \"161fc8d3-d042-461a-aae6-538368ba9287\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(171,171,171,0.5); letter-spacing: 0.01em\\\">0218</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 16,\n          \"marginOffset\": 0.19999999999999973,\n          \"groupId\": \"4a6f46b0-177c-4c44-9e5d-cd16f3f94826\"\n        },\n        {\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"b1045094-f7d9-4926-8762-cdf600551d7c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">My choice for best camera:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 20,\n          \"marginOffset\": 9.84375,\n          \"groupId\": \"1416f63c-6823-4f69-a8f7-38c3929526b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">RED</span><span style=\\\"font-weight: 600; color: #fff\\\"> Camera</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 39,\n          \"marginOffset\": 0,\n          \"id\": \"cca05235-7415-4377-9c94-cb45ec8cfe16\",\n          \"x\": 47,\n          \"y\": 23,\n          \"groupId\": \"1416f63c-6823-4f69-a8f7-38c3929526b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 340,\n          \"y\": 0,\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioWhiteFrameCorner\" },\n          \"id\": \"384456cc-8695-47e0-ad9d-e833470b228b\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 424,\n          \"id\": \"cdeef913-10aa-452c-871f-64d0a5004ae3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioWhiteFrameCorner\" }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"177efa9c-e483-4d33-8c93-3f58f8d91dd0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cca05235-7415-4377-9c94-cb45ec8cfe16\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"c3bbb8f8-45b0-404a-afad-44e4a7b1fcd7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b1045094-f7d9-4926-8762-cdf600551d7c\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"07f42d63-64ea-4a75-97f2-747de3c7993c\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0,\n          \"targets\": [\"5f8b7c67-929d-4020-b89a-e2f8145ee478\"]\n        },\n        {\n          \"id\": \"38436653-e547-467c-ae11-9541d2004aad\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"27740faa-0211-4168-8f69-142660333a6c\"],\n          \"scaleDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5e975c9b-2b41-421c-ae69-0bd1d88a6a4c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"384456cc-8695-47e0-ad9d-e833470b228b\"],\n          \"duration\": 1500,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"0d58df1a-c52c-4757-94ff-3b3d654d7939\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cdeef913-10aa-452c-871f-64d0a5004ae3\"],\n          \"duration\": 1500,\n          \"delay\": 350\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2a7ca89f-f3b8-4db3-9dd3-c87e6dc80ab8\",\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"4a6f46b0-177c-4c44-9e5d-cd16f3f94826\": {\n          \"name\": \"Info\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"1416f63c-6823-4f69-a8f7-38c3929526b5\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"51907be0-9a08-471d-ba74-f6ae9641618a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-13T11:59:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page05_bgvideo.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page05_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 5,\n            \"lengthFormatted\": \"0:05\",\n            \"alt\": \"A Man With A Camera On Hand Spinning The Chair He Is Sitting On\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#85725b\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d12e2f40-8ecd-4ead-8706-de24c77f792e\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7060ff56-39f1-4790-80c2-06cb249369f3\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bd3e0933-b231-4c1e-ba8e-1beb2f89f923\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 460,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"59aed3b0-368a-4c68-9238-e4bb34000f8a\",\n          \"x\": 0,\n          \"y\": 220\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">With the right base camera, you can experiment with more low-fi attachments like your phone.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 69,\n          \"marginOffset\": 9.84375,\n          \"id\": \"6c1f57f0-a45d-4b1b-8a00-97e11c3e8ff5\",\n          \"x\": 47,\n          \"y\": 546\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page06_image01.jpg\",\n            \"width\": 720,\n            \"height\": 481,\n            \"id\": 0,\n            \"alt\": \"Close-up photo of black video camera photo – Free Camera Image on Unsplash\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#2a2c2b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": -87,\n          \"width\": 713,\n          \"height\": 587,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f721c06b-077d-4471-a8e2-da9e30db2051\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bb6f6288-23b7-4d84-87d3-aa29200d7c1b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f721c06b-077d-4471-a8e2-da9e30db2051\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"66fd2353-9565-4854-bbcd-bfe21e7f0c3c\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7382f577-e6c1-40e1-80fc-2c84905d8cfa\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"width\": 412,\n          \"height\": 460,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"87d4460b-69fd-4326-bdc4-770a0f2d4561\",\n          \"x\": 0,\n          \"y\": 220,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">For more details check out specs and compare cameras at </span><span style=\\\"color: #fff\\\">Camera Culture</span><span style=\\\"color: #fff\\\">.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 46,\n          \"marginOffset\": 9.84375,\n          \"id\": \"e44ba583-e67e-41ac-a293-6cc6b2b71673\",\n          \"x\": 47,\n          \"y\": 570,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page01_image01.jpg\",\n            \"width\": 480,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Black camera photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#262828\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": -57,\n          \"width\": 228,\n          \"height\": 342,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"255f30a2-5fdb-48fa-af78-7294f82e738f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:53\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page06_image01.jpg\",\n            \"width\": 720,\n            \"height\": 481,\n            \"id\": 0,\n            \"alt\": \"Close-Up photo of black video camera photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#2a2c2b\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 133,\n          \"y\": 347,\n          \"width\": 232,\n          \"height\": 154,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"391690f9-a982-4b25-ab58-c5727e4354f2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(171,171,171,0.75); letter-spacing: 0.01em\\\">0218</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 16,\n          \"marginOffset\": 0.19999999999999973,\n          \"id\": \"3b746604-bbe3-41c8-aeac-554739f6f151\",\n          \"x\": 335,\n          \"y\": 187\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 347,\n          \"y\": 0,\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioGrayFrameCorner\" },\n          \"id\": \"05cb2254-ea62-455b-933c-aaf8008518b7\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 500,\n          \"id\": \"4a7d5042-7310-4287-9197-76b88123b4f5\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioGrayFrameCorner\" }\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"135b6ea2-25f1-42fd-87a2-72c84d5181e4\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"0bb87a54-45fa-4faa-800b-1d400617947c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T11:59:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page08_image01.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Person holding black macro lens photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#d8cfcd\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -222,\n          \"y\": -57,\n          \"width\": 858,\n          \"height\": 537,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"9314f495-b5dd-40c1-bc09-05d9ac9b8e17\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.13 },\n                \"position\": 0.27\n              },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.26 },\n                \"position\": 0.51\n              },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5,\n            \"alpha\": 0.64\n          },\n          \"width\": 412,\n          \"height\": 270,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ce4e63f4-e7a5-4782-8d9d-6a154d2f1fdd\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"x\": 0,\n          \"y\": 480,\n          \"width\": 412,\n          \"height\": 195,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7ef9f439-332b-4ab4-8745-d24381a4b1e3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">A good lens is likely to outlive your camera body because good optics are not prone to obsolescence like your fast advancing electronic hardware.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 522,\n          \"width\": 299,\n          \"height\": 93,\n          \"id\": \"65519768-c923-4437-b950-fa74c9691aef\",\n          \"marginOffset\": 9.84375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": -4,\n          \"id\": \"9f62b4a4-a397-4329-8019-83d1c0dcdaab\",\n          \"content\": \"<span style=\\\"color: #fff\\\">My go to lenses:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 299,\n          \"height\": 20,\n          \"marginOffset\": 9.84375,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 25,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Nikon </span><span style=\\\"font-weight: 600; color: #fff; text-transform: uppercase\\\">HB</span><span style=\\\"font-weight: 600; color: #fff\\\">-47 50mm lens</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 32,\n          \"marginOffset\": 0,\n          \"id\": \"1bb35d70-a29d-40c0-ad08-1ece8faad539\",\n          \"x\": 47,\n          \"y\": 23,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioWhiteFrameCorner\" },\n          \"id\": \"1622f4ff-ce5f-4f3f-8820-d2161b844cc4\",\n          \"x\": 340,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioWhiteFrameCorner\" },\n          \"id\": \"a40f82f4-b994-4a62-9984-0e4aad859e02\",\n          \"x\": 47,\n          \"y\": 424\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"cd561412-4d8e-41f6-b49a-e29622bc2e1c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1bb35d70-a29d-40c0-ad08-1ece8faad539\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"0cb53a7e-d5a7-4b79-9e32-e027475aa51f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9f62b4a4-a397-4329-8019-83d1c0dcdaab\"],\n          \"duration\": 1500,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"6a8c455e-9d33-4d40-99d9-b959c9cf41d0\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"9314f495-b5dd-40c1-bc09-05d9ac9b8e17\"],\n          \"scaleDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"be4223fa-adb7-43d3-817c-785d14643f30\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"ce4e63f4-e7a5-4782-8d9d-6a154d2f1fdd\"],\n          \"scaleDirection\": \"scaleOut\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"811efee0-05a8-459e-a6d5-4a819c6f9202\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1622f4ff-ce5f-4f3f-8820-d2161b844cc4\"],\n          \"duration\": 1500,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"153abd28-e2d9-407d-8f86-446b70ef9f33\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a40f82f4-b994-4a62-9984-0e4aad859e02\"],\n          \"duration\": 1500,\n          \"delay\": 350\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"84f3b909-152c-478a-b545-64d3fa55e86d\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fc06767a-6144-46c2-91d7-34d429083aea\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-13T12:00:09\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page09_bgvideo.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page09_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 8,\n            \"lengthFormatted\": \"0:08\",\n            \"alt\": \"A Male Model Goofing Around With A Spinning Chair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#7c6850\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"86642aff-f227-4c18-b7c4-0ddc6aa2dfdc\",\n          \"type\": \"video\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"49b56d4c-d55c-40d6-b5f6-9749e034fa55\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"12c13f1b-73ea-41cc-b9db-bb299ae853f1\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"width\": 412,\n          \"height\": 460,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"77f4691b-ba18-4b12-9cfb-36ceb24e61b1\",\n          \"x\": 0,\n          \"y\": 220,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">Depending on your subject matter and your location, you may want to consider at least 2 lenses.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 67,\n          \"marginOffset\": 9.84375,\n          \"id\": \"8e574d10-cce1-4e7d-8e59-fedea3fe53a6\",\n          \"x\": 47,\n          \"y\": 546,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 155,\n          \"focalX\": 50.14080377243331,\n          \"focalY\": 58.357189424167046,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T12:00:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page10_image01.jpg\",\n            \"width\": 720,\n            \"height\": 1280,\n            \"id\": 0,\n            \"alt\": \"Person holding camera lens photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#0a1415\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 364,\n          \"height\": 557,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"7db3309e-4d03-42ab-8400-4b4917588fa0\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"26049170-c61f-4677-8693-432f8bc4a742\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7db3309e-4d03-42ab-8400-4b4917588fa0\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"0462c838-d0dd-4e51-a0f3-d034bfb26f62\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"215ddab3-8c1c-423a-b2de-2f3454ddb560\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"width\": 412,\n          \"height\": 460,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bb9b4977-31f6-461e-b758-046acc42002b\",\n          \"x\": 0,\n          \"y\": 220,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">For more details check out lenses and compare at </span><span style=\\\"color: #fff\\\">Lens Louis</span><span style=\\\"color: #fff\\\">.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 318,\n          \"height\": 46,\n          \"marginOffset\": 9.84375,\n          \"id\": \"78f0ec9b-9306-4765-940c-b133e2be200e\",\n          \"x\": 47,\n          \"y\": 570,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T12:00:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page11_image02.jpg\",\n            \"width\": 720,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Black Canon DSLR camera photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#ccd6d7\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 260,\n          \"width\": 318,\n          \"height\": 242,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"3aa1f58b-132f-45a2-a081-ba0ed70a6bc3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-13T12:00:16\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page11_image01.jpg\",\n            \"width\": 721,\n            \"height\": 488,\n            \"id\": 0,\n            \"alt\": \"Person holding camera lens photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#0d1a1c\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 94,\n          \"y\": 0,\n          \"width\": 272,\n          \"height\": 184,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"cdc240cf-4e88-4cad-acb0-9750785c57bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(171,171,171,0.75); letter-spacing: 0.01em\\\">0218</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 16,\n          \"marginOffset\": 0.19999999999999973,\n          \"id\": \"43eb7433-d734-4c06-a8c3-ae02a2eba248\",\n          \"x\": 47,\n          \"y\": 176\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioGrayFrameCorner\" },\n          \"id\": \"e6ee7254-584c-45e1-85e9-d1f1df2c74db\",\n          \"x\": 47,\n          \"y\": 0\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"fb04d360-0102-4043-a029-60bbc3785e6e\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"521fdf1c-953b-4b38-a71d-38b723c6dca0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-13T12:00:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page12_bgvideo.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page12_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 15,\n            \"lengthFormatted\": \"0:15\",\n            \"alt\": \"A Male Photographer Checking And Testing His Camera\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#847056\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": true,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"def0eed6-6da1-40e2-83fb-d7647d257037\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"4e1d84fa-97e1-4ecb-9697-74d3b6ab8cac\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d1f89005-0dbd-4d4c-bab7-35184f65d8b8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 68, \"g\": 72, \"b\": 73 } },\n          \"width\": 412,\n          \"height\": 309,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"3e5372a9-096a-4f3b-a30a-6415a88f225f\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 25,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Book a tutorial</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">with Matt</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": -6,\n          \"width\": 277,\n          \"height\": 64,\n          \"id\": \"3b2403d6-25f2-4ca8-8b96-9137f83f968d\",\n          \"marginOffset\": 0,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #1a1a1a\\\">Book a video tutorial</span><span style=\\\"color: #1a1a1a\\\"> class with Matthew Donner.&nbsp;</span>\\n\\n<span style=\\\"color: #1a1a1a\\\">You’ll cover the basics in more depth with 1:1 time.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 252,\n          \"height\": 98,\n          \"marginOffset\": -1.7000000000000028,\n          \"type\": \"text\",\n          \"id\": \"22dd9901-8656-4a30-8230-6cb4cdb1b263\",\n          \"x\": 47,\n          \"y\": 518\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-13T11:59:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page02_bgvideo.mp4\",\n            \"width\": 1080,\n            \"height\": 2048,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/technology-advice/page02_bgvideo-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 24,\n            \"lengthFormatted\": \"0:24\",\n            \"alt\": \"Video Footage Of A Male Photographer In Action\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"provider\": \"local\",\n            \"baseColor\": \"#826e55\",\n            \"isExternal\": true\n          },\n          \"controls\": false,\n          \"loop\": false,\n          \"autoPlay\": true,\n          \"tracks\": [],\n          \"type\": \"video\",\n          \"x\": 47,\n          \"y\": 89,\n          \"width\": 277,\n          \"height\": 398,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"bbd186e7-3f6f-4243-9e08-6125aaf7d5e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 25,\n          \"height\": 25,\n          \"sticker\": { \"type\": \"studioGrayFrameCorner\" },\n          \"id\": \"9d2acdcb-7d37-4272-a8fb-895ca8340668\",\n          \"x\": 339,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 270,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: rgba(171,171,171,0.75); letter-spacing: 0.01em\\\">0218</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 30,\n          \"height\": 16,\n          \"marginOffset\": 0.19999999999999973,\n          \"id\": \"5c1510c7-a939-478a-8539-9b77683bf30b\",\n          \"x\": 353,\n          \"y\": 454\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 222, \"b\": 222 } },\n      \"type\": \"page\",\n      \"id\": \"9568115b-d78e-4e46-b279-904672989a96\",\n      \"pageTemplateType\": \"editorial\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/tips-for-throwing-an-outdoor-luau/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/tips-for-throwing-an-outdoor-luau/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'tips-for-throwing-an-outdoor-luau',\n  creationDate: '2021-08-25T00:00:00.000Z',\n  title: _x(\n    'Tips for Throwing an Outdoor Luau',\n    'template name',\n    'web-stories'\n  ),\n  tags: [\n    _x('Home & Garden', 'template keyword', 'web-stories'),\n    _x('Tips', 'template keyword', 'web-stories'),\n    _x('Party', 'template keyword', 'web-stories'),\n    _x('Planning', 'template keyword', 'web-stories'),\n    _x('Yellow', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Dry Yellow', 'color', 'web-stories'),\n      color: '#ece7bd',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Banff Green', 'color', 'web-stories'),\n      color: '#3f4f3e',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its nature-inspired banners and stickers, this template will let you create lively and playful stories for topics involving nature. Announce events and retreats, give out travel tips and recommendations, share recipes and so much more.',\n    'web-stories'\n  ),\n  vertical: _x('Home & Garden', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/tips-for-throwing-an-outdoor-luau/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/tips-for-throwing-an-outdoor-luau/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"0f69f03c-1479-46b7-bd97-fb43a60f361c\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:21:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman in gray tank top sitting on chair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#d9c4bc\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.1 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -8,\n          \"y\": -81,\n          \"width\": 458,\n          \"height\": 352,\n          \"sticker\": { \"type\": \"luauYellowFlowerBanner\" },\n          \"id\": \"71a34778-58f1-4f26-afb0-4e8f502df2bf\",\n          \"groupId\": \"d01f0aa9-b191-4101-aba5-fccd5ad14642\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.12,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #3f4f3e\\\">How to throw</span>\\n<span style=\\\"font-weight: 600; color: #3f4f3e\\\">a safe and fun outdoor luau</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 96,\n          \"y\": 38,\n          \"width\": 263,\n          \"height\": 116,\n          \"id\": \"0a5f0ed4-e8f9-4fd2-add8-177d89e97b15\",\n          \"groupId\": \"d01f0aa9-b191-4101-aba5-fccd5ad14642\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 68,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -43,\n          \"y\": 482,\n          \"width\": 277,\n          \"height\": 264,\n          \"sticker\": { \"type\": \"luauGreenFlower\" },\n          \"id\": \"298312ec-78a8-4abf-af99-29f217fc4cb8\",\n          \"groupId\": \"006edb2f-afe4-4187-96de-c36072e9c665\"\n        },\n        {\n          \"x\": 46,\n          \"y\": 537,\n          \"id\": \"3e8cbf15-8932-4912-bcc4-26e5c0186dbf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">by:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 29,\n          \"height\": 20,\n          \"groupId\": \"006edb2f-afe4-4187-96de-c36072e9c665\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 563,\n          \"id\": \"c753ede0-0d43-4a37-979f-555026dfd008\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Joshua</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">Goldsmith</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 183,\n          \"height\": 51,\n          \"groupId\": \"006edb2f-afe4-4187-96de-c36072e9c665\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 275,\n          \"y\": 399,\n          \"width\": 175,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"9d6198b0-aae1-4d69-b480-52202b511192\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"bd7c5157-9295-4c70-9455-5e6bebe2183d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c0bb0984-50ae-493e-a0f6-3ce9cc00dfcd\"\n      },\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"006edb2f-afe4-4187-96de-c36072e9c665\": {\n          \"name\": \"Author\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"d01f0aa9-b191-4101-aba5-fccd5ad14642\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"2816ff3d-3786-4955-a866-dbfaa4f8786b\",\n          \"type\": \"video\",\n          \"scale\": 120,\n          \"focalX\": 38.30820596246973,\n          \"focalY\": 42.50151331719129,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-14T14:17:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page2_bg.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 16,\n            \"lengthFormatted\": \"0:16\",\n            \"alt\": \"Smiling man reporting by the sea\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#776064\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 32,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Joshua</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">Goldsmith</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": -5,\n          \"width\": 263,\n          \"height\": 77,\n          \"id\": \"9888386b-5e83-4c0b-9eda-af7a9a32da11\",\n          \"type\": \"text\",\n          \"groupId\": \"368b85a1-41b3-4e6d-93f3-42e47867dd88\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 76,\n          \"id\": \"a4afe50e-e806-42c6-bc8d-72ab9d478cec\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em\\\">Founder, Hawaiian Events</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"368b85a1-41b3-4e6d-93f3-42e47867dd88\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 120,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -29,\n          \"y\": 394,\n          \"width\": 102,\n          \"height\": 107,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"1170401f-1778-4dc7-94ce-277f243de245\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 302,\n          \"y\": 27,\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"df0f6f5f-5546-470c-aef6-22486e76d6f2\",\n          \"groupId\": \"073a017b-60ff-4006-89a3-157e8d5fe6ec\"\n        },\n        {\n          \"x\": 302,\n          \"y\": 46,\n          \"id\": \"9d25cd3c-dba0-4d0d-8c6d-ee0577686973\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"groupId\": \"073a017b-60ff-4006-89a3-157e8d5fe6ec\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"908894c8-0108-488d-921f-939fbb03cfba\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"581e926d-fb91-433e-a8d4-bb19f48c010f\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"368b85a1-41b3-4e6d-93f3-42e47867dd88\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"073a017b-60ff-4006-89a3-157e8d5fe6ec\": {\n          \"name\": \"Lines\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"9e3e87c9-247d-4414-8d6c-8f73415164d5\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:22:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page3_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Group of people setting up campfire photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#777479\",\n            \"isExternal\": true\n          },\n          \"overlay\": null\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -120,\n          \"y\": 364,\n          \"width\": 487,\n          \"height\": 374,\n          \"sticker\": { \"type\": \"luauYellowFlowerBanner\" },\n          \"id\": \"96a19e6c-afaf-40ec-a8a2-97d6df809f98\",\n          \"groupId\": \"bdb11a1e-0a8d-4797-939f-8b302bae9284\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #3f4f3e\\\">Limit guest</span>\\n<span style=\\\"font-weight: 600; color: #3f4f3e\\\">invitations</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 516,\n          \"width\": 263,\n          \"height\": 73,\n          \"id\": \"a7a3d447-e302-452e-af4b-af5fc57f59ae\",\n          \"type\": \"text\",\n          \"groupId\": \"bdb11a1e-0a8d-4797-939f-8b302bae9284\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 480,\n          \"id\": \"2ff73b92-e0f0-4455-9d52-44f25a61d526\",\n          \"content\": \"<span style=\\\"color: #3f4f3e; letter-spacing: 0.01em; text-transform: uppercase\\\">Tip 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"bdb11a1e-0a8d-4797-939f-8b302bae9284\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"eed23703-9d04-4043-bbb4-062286d11314\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"c4d30e8f-b89c-4bac-b006-110083a14673\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bdb11a1e-0a8d-4797-939f-8b302bae9284\": {\n          \"name\": \"Tip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"3ea03b48-d58e-4196-bcb0-57c1217da610\",\n          \"type\": \"image\",\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:23:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page4_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Group of women in forest drinking\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#766b4e\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.75 },\n                \"position\": 0.78\n              }\n            ],\n            \"alpha\": 0.7\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 483,\n          \"id\": \"0d31c315-4e1a-48ab-9e30-4e6facfec496\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">Keeping your guests safe is your priority! This means that everybody can relax properly and focus on what is important: having a good time!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 290,\n          \"height\": 133,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"58187665-53d1-4862-b407-8f4bfdce9bbb\",\n          \"x\": -47,\n          \"y\": 410,\n          \"groupId\": \"0e492f6d-900d-4be6-ae37-252896142884\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"2e4dd6cf-aaeb-4736-bbc7-d2cce3932a48\",\n          \"x\": -47,\n          \"y\": 429,\n          \"groupId\": \"0e492f6d-900d-4be6-ae37-252896142884\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a3e6105a-29c5-4d6d-a87c-afc5f6628ed1\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"3ea03b48-d58e-4196-bcb0-57c1217da610\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f808c1b4-9ef2-488c-aecb-03cfa716817b\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"728c69de-5b58-42a9-88cd-7f64b4ccb7b3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"0e492f6d-900d-4be6-ae37-252896142884\": {\n          \"name\": \"Lines\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"cf8560ca-98de-495f-abbe-baf3635490af\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:24:41\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page5_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Brown wooden fork, spoon, and knife on textile\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#9a9797\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": -63,\n          \"y\": -170,\n          \"width\": 466,\n          \"height\": 411,\n          \"sticker\": { \"type\": \"luauGreenLeafBanner\" },\n          \"id\": \"d3b9d317-1599-47e7-9027-57759f62cab9\",\n          \"groupId\": \"cc2d4127-0244-4752-a071-4ce6e5f60dd2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Provide masks, hand sanitizer &amp; personalized utensils</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 36,\n          \"width\": 227,\n          \"height\": 140,\n          \"id\": \"39a14482-1b50-4772-8ceb-909c50e6060a\",\n          \"type\": \"text\",\n          \"groupId\": \"cc2d4127-0244-4752-a071-4ce6e5f60dd2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 0,\n          \"id\": \"19ca5381-9c07-4b91-9e0f-57d5c88bc62a\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Tip 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"cc2d4127-0244-4752-a071-4ce6e5f60dd2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 275,\n          \"y\": 530,\n          \"width\": 185,\n          \"height\": 194,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"2d18d6db-196d-437e-b6c0-5796008dca95\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"30cd053f-5ece-4fae-8872-d26d4dff8fd4\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"0bd6c15a-71cc-4b30-9308-6889dfc90b00\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"cc2d4127-0244-4752-a071-4ce6e5f60dd2\": {\n          \"name\": \"Tip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"d7973fde-8cfc-4669-96ad-2a5535bc6e15\",\n          \"type\": \"image\",\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:25:11\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page6_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Brown wooden cross with rope\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#8e8a88\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 490,\n          \"height\": 376,\n          \"sticker\": { \"type\": \"luauYellowFlowerBanner\" },\n          \"id\": \"d1e5e216-4a52-415f-81cb-4b0f21cb0db0\",\n          \"x\": -96,\n          \"y\": 356,\n          \"groupId\": \"657e201a-7720-45e1-b484-66023653ce3e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #3f4f3e\\\">Decorate with Luau props&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 516,\n          \"width\": 263,\n          \"height\": 73,\n          \"id\": \"6d48778f-b92c-4ae6-a257-59abce59b0c7\",\n          \"type\": \"text\",\n          \"groupId\": \"657e201a-7720-45e1-b484-66023653ce3e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 480,\n          \"id\": \"35c1962b-4497-4317-a79d-4f60044acbe9\",\n          \"content\": \"<span style=\\\"color: #3f4f3e; letter-spacing: 0.01em; text-transform: uppercase\\\">Tip 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"657e201a-7720-45e1-b484-66023653ce3e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 175,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"dabaf908-3e2a-4f27-b8e6-aa80512ed3d9\",\n          \"x\": 283,\n          \"y\": -119\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"413dc340-9e40-471d-a513-66416d25035b\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"d7973fde-8cfc-4669-96ad-2a5535bc6e15\"],\n          \"panDir\": \"rightToLeft\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"2b3ddbea-1f95-4574-8b9b-1beb9a2a775f\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"6234ea30-f145-46c6-802f-ffaf74922b62\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"657e201a-7720-45e1-b484-66023653ce3e\": {\n          \"name\": \"Tip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"82e263a1-f83d-4fd7-8ea2-25b9beee1401\",\n          \"type\": \"image\",\n          \"scale\": 105,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:25:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page7_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Orange and green food in clear plastic container\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#6d5f53\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 487,\n          \"height\": 374,\n          \"sticker\": { \"type\": \"luauYellowFlowerBanner\" },\n          \"id\": \"e5f6a202-c4f6-4184-add8-60e0c6a77672\",\n          \"x\": -120,\n          \"y\": 364,\n          \"groupId\": \"8aef4b56-9ab7-4518-8513-b374f6bbf1ca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #3f4f3e\\\">Try single \\nserve snacks and drinks</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 516,\n          \"width\": 235,\n          \"height\": 106,\n          \"id\": \"9b43aa4c-1ec5-464e-bcce-48dc7bb8905c\",\n          \"type\": \"text\",\n          \"groupId\": \"8aef4b56-9ab7-4518-8513-b374f6bbf1ca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 480,\n          \"id\": \"99fb8e7e-e7f0-4df2-815f-7e01a2077e82\",\n          \"content\": \"<span style=\\\"color: #3f4f3e; letter-spacing: 0.01em; text-transform: uppercase\\\">Tip 4</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 23,\n          \"type\": \"text\",\n          \"groupId\": \"8aef4b56-9ab7-4518-8513-b374f6bbf1ca\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 175,\n          \"height\": 184,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"3c55b132-0a29-4b2c-a376-f5186f190056\",\n          \"x\": 289,\n          \"y\": -119\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"01bf3391-b0ec-4ba6-9fc9-8d6aa4c26fef\",\n          \"type\": \"effect-background-pan\",\n          \"targets\": [\"82e263a1-f83d-4fd7-8ea2-25b9beee1401\"],\n          \"panDir\": \"leftToRight\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"d8acf3bb-8e72-4668-b9a7-8c5c44011282\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"b1e4d0c9-6953-42e6-a350-a22a31894668\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"8aef4b56-9ab7-4518-8513-b374f6bbf1ca\": {\n          \"name\": \"Tip\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"26b86fa3-5aee-4395-96ab-25942edeed71\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:26:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page8_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Clear Glass Jar on Block\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#6a6842\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 185,\n          \"height\": 194,\n          \"sticker\": { \"type\": \"luauYellowFlower\" },\n          \"id\": \"b5768d71-6ad0-48fb-b4c3-ec43972e2c1b\",\n          \"x\": 275,\n          \"y\": 530\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 426,\n          \"height\": 376,\n          \"sticker\": { \"type\": \"luauGreenLeafBanner\" },\n          \"id\": \"c3a2b32a-09bd-40b1-8bf0-6d98fb9b0da8\",\n          \"x\": -90,\n          \"y\": -152,\n          \"groupId\": \"ce31f7e3-7ce4-437a-9c55-efcb22969bee\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Best</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">Hawaiian</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">Juices</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 36,\n          \"width\": 227,\n          \"height\": 106,\n          \"id\": \"015b29c2-c7f8-48d6-864c-7222f1265220\",\n          \"type\": \"text\",\n          \"groupId\": \"ce31f7e3-7ce4-437a-9c55-efcb22969bee\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 47,\n          \"y\": 0,\n          \"id\": \"7c50ca8f-3058-49a0-892f-bb10f4503648\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.01em; text-transform: uppercase\\\">Tip 5</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 216,\n          \"height\": 22,\n          \"type\": \"text\",\n          \"groupId\": \"ce31f7e3-7ce4-437a-9c55-efcb22969bee\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"9fc148e7-dec6-4c8e-99f0-969a955037eb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"4eea3ee4-729d-47b0-833e-312b418257d0\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"ce31f7e3-7ce4-437a-9c55-efcb22969bee\": {\n          \"name\": \"Tip\",\n          \"isLocked\": false\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -154,\n          \"y\": 106,\n          \"width\": 720,\n          \"height\": 406,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"video\",\n          \"id\": \"7d7a080e-0152-40ff-8b0a-b56397019105\",\n          \"scale\": 120,\n          \"focalX\": 38.30820596246973,\n          \"focalY\": 42.50151331719129,\n          \"resource\": {\n            \"type\": \"video\",\n            \"mimeType\": \"video/mp4\",\n            \"creationDate\": \"2021-07-14T14:17:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page2_bg.mp4\",\n            \"width\": 720,\n            \"height\": 406,\n            \"poster\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page2_bg-poster.jpg\",\n            \"posterId\": 0,\n            \"id\": 0,\n            \"length\": 16,\n            \"lengthFormatted\": \"0:16\",\n            \"alt\": \"Smiling man reporting by the sea\",\n            \"isPlaceholder\": false,\n            \"isOptimized\": true,\n            \"isMuted\": true,\n            \"baseColor\": \"#776064\",\n            \"isExternal\": true\n          },\n          \"tracks\": [],\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.15 } },\n          \"loop\": true\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"3a5cd35c-3b81-4292-9a41-147558c6c430\",\n          \"x\": -20,\n          \"y\": 7\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"556fe8c2-07b7-4ab7-bbc8-1719ddf54b8e\",\n          \"x\": -20,\n          \"y\": 26\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2d0f79f2-4e2f-4f9f-9053-1e4a8664db3c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3a5cd35c-3b81-4292-9a41-147558c6c430\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"71a34e85-f32b-4bc2-a3e3-bb0337dd6a63\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"556fe8c2-07b7-4ab7-bbc8-1719ddf54b8e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"8bc2f54e-e886-4c8c-8baf-0f52cd462767\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"c5e2d360-0176-42b8-a25f-959aa571de48\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 586,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"297b3b0e-c167-41d1-9438-18161cf9eef6\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:26:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page10_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Woman Soaking on the Swimming Pool\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#42584e\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.3 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Have a</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">safe and</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">happy</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">summer</span>\\n<span style=\\\"font-weight: 600; color: #fff\\\">luau!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 235,\n          \"width\": 227,\n          \"height\": 270,\n          \"id\": \"c4ca66ab-1731-415d-8de3-bcc6c72bc8db\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"c3dac545-7e7c-475b-84d6-33e6461e7d22\",\n          \"x\": 47,\n          \"y\": 520,\n          \"groupId\": \"e7ef3ca5-51ba-4957-8552-d4f6b362029f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"b9f28adb-4061-4097-b11a-4db20e9b54b5\",\n          \"x\": 47,\n          \"y\": 539,\n          \"groupId\": \"e7ef3ca5-51ba-4957-8552-d4f6b362029f\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"bafd51f3-8f19-4cb0-a7d5-429ce00dc256\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c3dac545-7e7c-475b-84d6-33e6461e7d22\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"25641fda-bc9c-477a-ac09-72472332fa76\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b9f28adb-4061-4097-b11a-4db20e9b54b5\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1500,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"fd981f68-922c-496c-915f-dd023a6a2907\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"5001b3b0-56ae-4ae0-8951-2dbf479c0541\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"e7ef3ca5-51ba-4957-8552-d4f6b362029f\": {\n          \"name\": \"Lines\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"03ab5547-440a-4cf8-a658-fab756136f9c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">Julie’s Party Guides</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 42,\n          \"y\": 23,\n          \"width\": 227,\n          \"height\": 73,\n          \"id\": \"9ba9b775-dcfa-460e-bd88-840f49462f05\",\n          \"type\": \"text\"\n        },\n        {\n          \"x\": 226,\n          \"y\": 548,\n          \"id\": \"4c846890-3003-4d2b-a19e-71fd97a939d0\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">How I became a</span>\\n<span style=\\\"font-weight: 500; color: #fff\\\">Party Planner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 46,\n          \"type\": \"text\",\n          \"groupId\": \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 226,\n          \"y\": 367,\n          \"id\": \"4a2e33b9-7e4f-4cb7-a093-b1b4c7a6aab3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 139,\n          \"height\": 173,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:27:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page11_image2.jpg\",\n            \"width\": 480,\n            \"height\": 598,\n            \"id\": 0,\n            \"alt\": \"Laughing Women\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#4d4033\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 100,\n          \"y\": 548,\n          \"width\": 96,\n          \"height\": 35,\n          \"sticker\": { \"type\": \"luauWhiteDottedArrow\" },\n          \"id\": \"6ce1e0f0-dd09-4d56-9d02-0ab8ff788fe1\",\n          \"groupId\": \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\"\n        },\n        {\n          \"x\": 127,\n          \"y\": 469,\n          \"id\": \"5e460268-bfa2-4e5b-9abc-30a8ff6cfa10\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"groupId\": \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\"\n        },\n        {\n          \"x\": 127,\n          \"y\": 488,\n          \"id\": \"682a9ba8-dc87-4e3b-b41b-cfaf39f71b42\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"groupId\": \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff\\\">A paper-themed children’s birthday party</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 162,\n          \"height\": 65,\n          \"type\": \"text\",\n          \"id\": \"cfbb9340-d11b-455a-9665-9cdd6e786f3d\",\n          \"x\": 42,\n          \"y\": 314,\n          \"groupId\": \"a7413651-9329-41e0-a291-2d3ef7290eb8\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 42,\n          \"y\": 126,\n          \"width\": 139,\n          \"height\": 173,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7374361e-f20e-4968-80c5-77533773b90d\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-07-14T11:27:26\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tips-for-throwing-an-outdoor-luau/page11_image1.jpg\",\n            \"width\": 480,\n            \"height\": 598,\n            \"id\": 0,\n            \"alt\": \"Cozy light room with children party or game decoration\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"baseColor\": \"#b2b9ac\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"a7413651-9329-41e0-a291-2d3ef7290eb8\"\n        },\n        {\n          \"x\": 213,\n          \"y\": 143,\n          \"id\": \"f54a1e47-0a15-40aa-acbe-b5d88a96a1e2\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 162,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 100,\n          \"height\": 36,\n          \"sticker\": { \"type\": \"luauWhiteDottedArrow\" },\n          \"groupId\": \"a7413651-9329-41e0-a291-2d3ef7290eb8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"18beb40c-c393-48e2-8f95-473b6167276c\",\n          \"x\": 158,\n          \"y\": 237,\n          \"groupId\": \"a7413651-9329-41e0-a291-2d3ef7290eb8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 135,\n          \"height\": 10,\n          \"sticker\": { \"type\": \"luauYellowWavyLine\" },\n          \"id\": \"4b778d7f-ca8a-4a2d-a342-3a9ec317d956\",\n          \"x\": 158,\n          \"y\": 256,\n          \"groupId\": \"a7413651-9329-41e0-a291-2d3ef7290eb8\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f8cc11a1-2875-47d2-8006-65eeb65f58fc\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cfbb9340-d11b-455a-9665-9cdd6e786f3d\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"6b734470-3468-41ac-8f19-9ddae4204f13\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4c846890-3003-4d2b-a19e-71fd97a939d0\"],\n          \"duration\": 1500,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"39bd239b-0a42-49b1-b1f2-d841734dd1e8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f54a1e47-0a15-40aa-acbe-b5d88a96a1e2\"],\n          \"duration\": 1500,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"b3fad8bb-3dab-4387-aa5d-6b6dda191f15\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6ce1e0f0-dd09-4d56-9d02-0ab8ff788fe1\"],\n          \"duration\": 1500,\n          \"delay\": 1000\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 63, \"g\": 79, \"b\": 62 } },\n      \"type\": \"page\",\n      \"id\": \"47246645-2015-49a3-96ff-e8f35420e654\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"a7413651-9329-41e0-a291-2d3ef7290eb8\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"778b3a3d-396e-4bc4-9cff-221ab556ba3c\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/tv-show-recap/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/tv-show-recap/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'tv-show-recap',\n  creationDate: '2021-07-29T00:00:00.000Z',\n  title: _x('TV Show Recap', 'template name', 'web-stories'),\n  tags: [\n    _x('Entertainment', 'template keyword', 'web-stories'),\n    _x('TV Show', 'template keyword', 'web-stories'),\n    _x('Explanation', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('Black', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black Walnut', 'color', 'web-stories'),\n      color: '#2f2f2b',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Mimosa Yellow', 'color', 'web-stories'),\n      color: '#fff172',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Clear Sky Blue', 'color', 'web-stories'),\n      color: '#72aaff',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its clean design and minimal visual elements, this template puts the focus on what you have to say. Create film and TV reviews, summaries, analyses, visual essays and more.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/tv-show-recap/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/tv-show-recap/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4b30d479-14a2-460d-bbd1-25a4f658c337\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-20T05:52:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page01_image01.jpg\",\n            \"width\": 720,\n            \"height\": 631,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman wearing off-shoulder dress\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#211715\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -10,\n          \"y\": -149,\n          \"width\": 333,\n          \"height\": 293,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d7cdc911-1371-4221-94c4-a36ed0e3e44c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page01_image02.jpg\",\n            \"width\": 640,\n            \"height\": 959,\n            \"id\": 0,\n            \"alt\": \"Photograph of Man in White Shirt With Round Black Analog Watch\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3c5c4\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 61,\n          \"y\": 307,\n          \"width\": 364,\n          \"height\": 544,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"85ec950f-9fc3-460d-97fb-9f9dd193191d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 43 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 130,\n          \"width\": 412,\n          \"height\": 295,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c8b2ada3-08c1-4999-b3c2-ba8ec28e77ad\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">Every Season OF The Crown: Recapped</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 149,\n          \"width\": 269,\n          \"height\": 248,\n          \"id\": \"b6abb09e-0b46-4aea-865f-762a715f110b\"\n        },\n        {\n          \"x\": 63,\n          \"y\": 391,\n          \"id\": \"246aa970-42af-4caf-9ad6-e3959e9311bf\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff\\\">By Jon Doe</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 269,\n          \"height\": 16\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 43 } },\n      \"type\": \"page\",\n      \"id\": \"5f694a18-687b-4c78-91af-22552d6dc2ef\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2628f629-aa32-4fb9-9d11-11f3f078524d\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:24:27\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page02_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man wearing brown blazer\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e8e1df\",\n            \"isExternal\": true\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"8ea685fe-9ae5-4378-b452-da3a43e1294a\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": -1,\n          \"y\": -58,\n          \"width\": 414,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"73ddb81b-90a7-4ff4-b7cf-aab99124595e\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 114, \"g\": 170, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": 393,\n          \"width\": 9,\n          \"height\": 61,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"45cdee25-4969-44f1-b84e-26abf427cc15\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">The Crown gives its American audience a glimpse and retelling of one of the most famous monarchies alive today. With 5 seasons slated for the entirety of the show, catch up with us on seasons 1-3.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 393,\n          \"width\": 304,\n          \"height\": 225,\n          \"id\": \"8fd6bb72-3ceb-42ba-8ff9-4bebd467b909\",\n          \"marginOffset\": -1.7308593750000014,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3530bee5-8e9d-46fe-87bc-b0b5a4e7e246\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"45cdee25-4969-44f1-b84e-26abf427cc15\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"435b2bd9-fb12-4783-9111-93c9b2aa5d80\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -0.5,\n          \"y\": -71,\n          \"width\": 413,\n          \"height\": 747,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"25ec0d61-57cd-4a11-abf8-5e037fbb4452\",\n          \"scale\": 108,\n          \"focalX\": 55.888976966188174,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-20T08:32:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page03_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in yellow off-shoulder dress sitting on bench\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c5b7a6\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 401,\n          \"width\": 412,\n          \"height\": 276,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d5149b1e-a42b-4834-ac66-8321618eda67\"\n        },\n        {\n          \"x\": 0,\n          \"y\": -58,\n          \"id\": \"b06890f0-9fa7-4336-b530-642296292c86\",\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 195,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">Elizabeth Assumes The Crown</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 247,\n          \"height\": 96,\n          \"id\": \"d1f36c03-83a0-41e9-bedd-6d7c562afa02\",\n          \"x\": 82,\n          \"y\": 535,\n          \"marginOffset\": -12.3544921875\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; text-transform: uppercase\\\">SE01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 269,\n          \"height\": 16,\n          \"id\": \"eb848008-d837-416d-8789-41ad8742e864\",\n          \"x\": 63,\n          \"y\": 510\n        },\n        {\n          \"x\": -212,\n          \"y\": 0,\n          \"id\": \"c096f6e1-89dd-4093-ad49-6957b81b81c9\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">SEASON 01 / SEASON 01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 837,\n          \"height\": 95,\n          \"marginOffset\": -21.002636718750004\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3212aa29-c7fa-4fe2-bfcc-03b3929aa6a5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"c096f6e1-89dd-4093-ad49-6957b81b81c9\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 8000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 70, \"g\": 56, \"b\": 56 } },\n      \"type\": \"page\",\n      \"id\": \"fd4c8ec0-dc10-4251-a465-3a7dd4d67c25\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"18ded946-4fd2-4771-a20a-9fdfbd490dfc\"\n      },\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"10a54f28-c45b-4d50-88fd-d3ef42344720\",\n          \"scale\": 117,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page04_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"id\": 0,\n            \"alt\": \"Man in black shirt kissing woman in white shirt\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d4c0b1\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7c1de8ab-f486-4600-a23e-4a033aa9f31c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">In Season 1, we can already see a young Elizabeth and Margaret engaged in a feisty sibling rivalry that will play out in wildly entertaining fashion in later seasons.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 107,\n          \"marginOffset\": -1.7308593750000014,\n          \"id\": \"3c8346fa-01b0-46c0-b54d-66621932cb9b\",\n          \"x\": 50,\n          \"y\": 516\n        },\n        {\n          \"x\": 50,\n          \"y\": 488,\n          \"id\": \"19893201-46e4-4c4f-b5ad-42814e3fb72b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172\\\">Young Elizabeth</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 24,\n          \"marginOffset\": -1.7308593750000014\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5e435c69-2b35-4b1d-b3df-45bdc4676e18\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"10a54f28-c45b-4d50-88fd-d3ef42344720\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 3000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"818a21ca-377a-42a1-b3c0-204be65c40e9\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"cef2c3b1-16ba-4d10-9d9b-f0a64c8299de\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -94,\n          \"y\": -166,\n          \"width\": 524,\n          \"height\": 911,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"12c56584-b954-4dae-8474-8947cdab9ca7\",\n          \"scale\": 133,\n          \"focalX\": 52.74122807017544,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:25:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page05_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in black leather jacket riding brown horse during daytime\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#3a241b\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 80,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.49 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d955db8d-0119-44a9-aea6-417a71964dcb\",\n          \"x\": 0,\n          \"y\": -57\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"id\": \"175fb3e0-b5c4-406e-bfb0-31568be99033\",\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.2 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.65 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">All Eyes On Princess Margaret</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 305,\n          \"height\": 96,\n          \"id\": \"d6c52cae-0272-4e3c-9871-60e12a34954e\",\n          \"x\": 53,\n          \"y\": 535,\n          \"marginOffset\": -12.3544921875\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; text-transform: uppercase\\\">SE02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 269,\n          \"height\": 16,\n          \"id\": \"05b40b4e-0afd-45b7-b2ea-f0e9da724635\",\n          \"x\": 54,\n          \"y\": 510\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">SEASON 02 / SEASON 02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 837,\n          \"height\": 95,\n          \"marginOffset\": -21.002636718750004,\n          \"id\": \"3f823322-dd8e-4c8a-9453-e245415ab8c0\",\n          \"x\": -212,\n          \"y\": 0\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"659adadc-fbc4-4db7-8d38-e6f36408b213\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3f823322-dd8e-4c8a-9453-e245415ab8c0\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 8000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"232069d6-206e-4e8e-aa0e-1754655756e1\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"f48af029-0523-4f66-9f81-9ee7de93a7da\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d0dc6675-e8f0-4c11-8649-9a725d7a988a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">The percentage of scenes with Princess Margo having too good a time in </span><span style=\\\"color: #fff172\\\">Season 2:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 85,\n          \"marginOffset\": -1.7308593750000014,\n          \"id\": \"f2c0dfa3-ec5a-4e10-8afd-9865d1fc87be\",\n          \"x\": 50,\n          \"y\": 20,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 59,\n          \"y\": 200,\n          \"id\": \"3f4c2397-d040-44c1-b96b-94a3a0418b9a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">19%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 96,\n          \"height\": 59,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 256,\n          \"y\": 189,\n          \"id\": \"4288876c-d65a-4e14-bc05-6c041629a7cc\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">47%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 96,\n          \"height\": 59,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 59,\n          \"y\": 470,\n          \"id\": \"cc10f86b-83f7-48e1-9578-cda07245287c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">10%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 96,\n          \"height\": 59,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 256,\n          \"y\": 459,\n          \"id\": \"65370cf9-4bd8-440a-a192-d5dd73687841\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 45,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff\\\">24%</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 96,\n          \"height\": 59,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 47,\n          \"y\": 255,\n          \"id\": \"3b8c1ccf-5e07-4c7d-add7-74f2c0d25449\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff172\\\">Smoking</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 121,\n          \"height\": 21,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 244,\n          \"y\": 244,\n          \"id\": \"af21ae00-e471-492a-801f-4e5e63ef6bc8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff172\\\">Drinking</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 121,\n          \"height\": 21,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 38,\n          \"y\": 525,\n          \"id\": \"88264ad0-b7fd-4603-b28d-270848eec241\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff172\\\">Missing in action</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 138,\n          \"height\": 21,\n          \"marginOffset\": 0.6491210937499972,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 244,\n          \"y\": 514,\n          \"id\": \"f79ca836-e96b-4e01-900b-0a36cf2c4315\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff172\\\">Partying</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 121,\n          \"height\": 21,\n          \"marginOffset\": -1.3599609374999986,\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 257,\n          \"y\": 277,\n          \"width\": 49,\n          \"height\": 58,\n          \"sticker\": { \"type\": \"curvedDottedLine\" },\n          \"id\": \"1669633e-9538-4655-921b-e8321da797ab\",\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 111,\n          \"y\": 280,\n          \"id\": \"8d6b79c2-182a-4e6d-9ed6-f25e48edb5d1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 49,\n          \"height\": 58,\n          \"sticker\": { \"type\": \"curvedDottedLine\" },\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 111,\n          \"y\": 406,\n          \"id\": \"81aae77b-d221-47bf-9a91-d059fa00c037\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": true },\n          \"rotationAngle\": 356,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 49,\n          \"height\": 58,\n          \"sticker\": { \"type\": \"curvedDottedLine\" },\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"x\": 200,\n          \"y\": 426,\n          \"id\": \"510b7ae6-da82-4cb4-bc0c-6d4e37f0721c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 49,\n          \"height\": 58,\n          \"sticker\": { \"type\": \"curvedDottedLine\" },\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 131,\n          \"y\": 288,\n          \"width\": 150,\n          \"height\": 150,\n          \"sticker\": { \"type\": \"discPieChart\" },\n          \"id\": \"4af10ce6-acc2-4320-8a8a-dfa3c6121799\",\n          \"groupId\": \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9c349c37-e9bd-4fc3-bd57-38a7140397d7\",\n          \"type\": \"effect-zoom\",\n          \"targets\": [\"4af10ce6-acc2-4320-8a8a-dfa3c6121799\"],\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 700,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"9cd84bf0-4b32-4bb8-b4f3-bb0e8873599b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4288876c-d65a-4e14-bc05-6c041629a7cc\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"9b9b3e0e-a099-473c-903d-12944e5ae4da\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"af21ae00-e471-492a-801f-4e5e63ef6bc8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"579b57e1-602f-41af-a502-475d5205bbc7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"1669633e-9538-4655-921b-e8321da797ab\"],\n          \"duration\": 1000,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"f51c013d-3559-48de-8a3a-9492f6937fcb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3f4c2397-d040-44c1-b96b-94a3a0418b9a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"5d66e927-0293-4c29-a34e-262014a0223b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3b8c1ccf-5e07-4c7d-add7-74f2c0d25449\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"07c2b5e9-b6bd-4ce3-b5d1-e567b702e17f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8d6b79c2-182a-4e6d-9ed6-f25e48edb5d1\"],\n          \"duration\": 1000,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"dcbdff95-e54c-4ac9-91a1-fc46f6da6454\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"65370cf9-4bd8-440a-a192-d5dd73687841\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 1800\n        },\n        {\n          \"id\": \"02e3a878-c559-4cf4-b409-f586f19c8554\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f79ca836-e96b-4e01-900b-0a36cf2c4315\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1200,\n          \"delay\": 1800\n        },\n        {\n          \"id\": \"71632520-1f06-4612-a2af-c8b0a1fb3a02\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"510b7ae6-da82-4cb4-bc0c-6d4e37f0721c\"],\n          \"duration\": 1000,\n          \"delay\": 1800\n        },\n        {\n          \"id\": \"6401323f-81a7-44a0-b400-b394de5eeca1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"81aae77b-d221-47bf-9a91-d059fa00c037\"],\n          \"duration\": 1000,\n          \"delay\": 1400\n        },\n        {\n          \"id\": \"a116a5f4-4f84-432c-ae28-61a08cbd2eee\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cc10f86b-83f7-48e1-9578-cda07245287c\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 1400\n        },\n        {\n          \"id\": \"5fbc0136-c947-4b2e-b6e3-3c9585735ec3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"88264ad0-b7fd-4603-b28d-270848eec241\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1200,\n          \"delay\": 1400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 43 } },\n      \"type\": \"page\",\n      \"id\": \"6bd4c107-6aca-4725-8620-bca0ba949fa7\",\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"17d5ac73-a738-479e-a21d-6c5f1b2d95c8\": {\n          \"name\": \"Graph\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"69dd7c0c-4128-4e7f-a4bc-b7ccd5528a5e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:25:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page07_image01.jpg\",\n            \"width\": 941,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in White Crew Neck Shirt Holding His Face\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#271514\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": -7,\n          \"y\": 7,\n          \"width\": 330,\n          \"height\": 252,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d626e8c2-4184-4985-86bb-a9e47d63f84e\",\n          \"groupId\": \"84862453-b36e-47d5-a3d1-2004000facff\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">John Williams</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 74,\n          \"y\": 174,\n          \"width\": 410,\n          \"height\": 68,\n          \"id\": \"ffdab448-f66d-4e43-8268-a674b6880325\",\n          \"marginOffset\": -18.850781249999997,\n          \"groupId\": \"84862453-b36e-47d5-a3d1-2004000facff\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:25:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page07_image02.jpg\",\n            \"width\": 941,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Businessman in his Office Looking at the Camera\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#191614\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 78,\n          \"y\": 284,\n          \"width\": 285,\n          \"height\": 244,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"6b631433-de49-40a4-8aa0-26f225c6f938\",\n          \"groupId\": \"fde919fc-86ba-416d-8b57-ce61b813d380\"\n        },\n        {\n          \"x\": -84,\n          \"y\": 421,\n          \"id\": \"2b94d219-2ba4-4afe-be2e-a1fb1897c6f6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">Alex Fergurson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 450,\n          \"height\": 68,\n          \"marginOffset\": -12.829003906249994,\n          \"groupId\": \"fde919fc-86ba-416d-8b57-ce61b813d380\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Margaret is vivacious, intelligent, talented with all eyes on her.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 43,\n          \"marginOffset\": -1.7308593750000014,\n          \"id\": \"0e538904-fb85-4107-9c02-b85c9f7ca7bb\",\n          \"x\": 50,\n          \"y\": 578\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">POTENTIAL SUITORS</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 30,\n          \"marginOffset\": -1.7308593750000014,\n          \"id\": \"f10d9581-e62f-4824-ae04-bbeb99240ca1\",\n          \"x\": 50,\n          \"y\": 550\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"fd0c1c82-24a2-4a14-bd4c-c9710a741608\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ffdab448-f66d-4e43-8268-a674b6880325\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 4000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"79bc4686-fa26-4282-8621-1e3436532271\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2b94d219-2ba4-4afe-be2e-a1fb1897c6f6\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 4000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 43 } },\n      \"type\": \"page\",\n      \"id\": \"188e533b-1a32-49f6-82aa-a4a037ab93a6\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"fde919fc-86ba-416d-8b57-ce61b813d380\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"84862453-b36e-47d5-a3d1-2004000facff\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"61519e97-0563-4fde-8eeb-2065564d7fe7\",\n          \"type\": \"image\",\n          \"scale\": 108,\n          \"focalX\": 53.54938271604939,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:25:48\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page08_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man lying on brown dried grass\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#412a1e\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 70,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.49 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"50bf3490-6824-4b81-a1e2-5bd94a65e7f8\",\n          \"x\": 0,\n          \"y\": -57,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 40,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.46 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.5 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"x\": 0,\n          \"y\": -57,\n          \"id\": \"6d4b6c05-0f66-4bc8-9fde-a7ec288fe56a\",\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">Elizabeth V.&nbsp;</span>\\n<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">The World</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 305,\n          \"height\": 68,\n          \"id\": \"ba32b3dd-14dc-44a1-9c07-f9811395f04e\",\n          \"x\": 53,\n          \"y\": 562,\n          \"marginOffset\": -12.3544921875,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Public Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1900,\n              \"des\": -450,\n              \"tAsc\": 1900,\n              \"tDes\": -450,\n              \"tLGap\": 0,\n              \"wAsc\": 2315,\n              \"wDes\": 495,\n              \"xH\": 1034,\n              \"capH\": 1446,\n              \"yMin\": -480,\n              \"yMax\": 2050,\n              \"hAsc\": 1900,\n              \"hDes\": -450,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 100; color: #fff; text-transform: uppercase\\\">SE03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 269,\n          \"height\": 16,\n          \"id\": \"bfc86da5-69f5-43ae-a511-e63426ef59aa\",\n          \"x\": 71,\n          \"y\": 544,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 70,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">SEASON 03 / SEASON 03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 837,\n          \"height\": 95,\n          \"marginOffset\": -21.002636718750004,\n          \"id\": \"84e9e47b-4d4f-4f1c-b02d-92aa05fab964\",\n          \"x\": -212,\n          \"y\": 0,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b4715976-7165-44ce-8f41-ccde7e388f9c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"84e9e47b-4d4f-4f1c-b02d-92aa05fab964\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 8000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"50b2f98e-4d17-451b-91ff-14039cccc7f2\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"dda0f84f-7fb6-4eae-8e89-6f641253b6fb\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"b500c059-0990-4c00-9cc1-9153a94fa7af\",\n          \"type\": \"image\",\n          \"scale\": 114,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:00\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page09_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Business People Talking\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#1b1919\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">This season pulls outside the walls of Buckingham Palace to give us a glimpse of Elizabeth's global literacy. She relies on her revolving door of Prime Ministers.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 309,\n          \"height\": 107,\n          \"marginOffset\": 0.6491210937499972,\n          \"id\": \"3049b5b0-8b09-4164-acc8-b9802ceff98e\",\n          \"x\": 50,\n          \"y\": 534,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 53,\n          \"y\": 506,\n          \"id\": \"d826aa97-6cb4-44a7-a301-34767eff38be\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172\\\">Global Literacy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 24,\n          \"marginOffset\": -1.7308593750000014,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"651004a9-ec90-4d83-8d1d-3c7cade49a85\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"af91cddf-01ad-4147-80e4-1a67b1070ade\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"aab48ed2-41e8-43d0-a15f-54766643d4c3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 78,\n          \"y\": 260,\n          \"width\": 256,\n          \"height\": 256,\n          \"sticker\": { \"type\": \"dottedDiamond\" },\n          \"id\": \"1f20c5f9-944d-49a0-a8ba-36948a73cd35\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.95,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff172; text-transform: uppercase\\\">The Love Quadrangle</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 305,\n          \"height\": 29,\n          \"marginOffset\": -12.3544921875,\n          \"type\": \"text\",\n          \"id\": \"096ff41c-cbd4-4886-8579-217ff6601da3\",\n          \"x\": 50,\n          \"y\": 20\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #fff\\\">We also get to see the love quadrangle that is Camilla Shand, Prince Charles, Andrew Bowles and Princess Anne.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 64,\n          \"marginOffset\": -1.7308593750000014,\n          \"type\": \"text\",\n          \"id\": \"3a8a667f-28b6-4d14-a57f-e506abf39e5f\",\n          \"x\": 50,\n          \"y\": 52\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:15\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page10_image01.jpg\",\n            \"width\": 478,\n            \"height\": 369,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in red tube top in swimming in water\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#374049\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 131.5,\n          \"y\": 178,\n          \"width\": 149,\n          \"height\": 115,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"b4610e37-5584-4544-948c-0c5d068597f3\",\n          \"groupId\": \"2943a234-98e3-426d-8098-4cf9602f8873\"\n        },\n        {\n          \"x\": 167,\n          \"y\": 153,\n          \"id\": \"0a0e562c-3211-40e6-ad27-94826819acca\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">CAMILLA</span>\\n<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">SHAND</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 78,\n          \"height\": 38,\n          \"marginOffset\": -4.941796875000001,\n          \"type\": \"text\",\n          \"groupId\": \"2943a234-98e3-426d-8098-4cf9602f8873\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page10_image03.jpg\",\n            \"width\": 473,\n            \"height\": 407,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in brown overcoat\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#c0b39f\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 264,\n          \"y\": 321,\n          \"width\": 131,\n          \"height\": 113,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"e9209d14-7676-420d-809e-d273813deef6\",\n          \"groupId\": \"aa3a7df9-e8ce-480a-989d-85039b7350d2\"\n        },\n        {\n          \"x\": 290,\n          \"y\": 424,\n          \"id\": \"3b1ba4dc-3e32-40f8-8b5d-fdd3d3aba726\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">PRINCE</span>\\n<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">CHARLES</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 78,\n          \"height\": 38,\n          \"marginOffset\": -4.941796875000001,\n          \"type\": \"text\",\n          \"groupId\": \"aa3a7df9-e8ce-480a-989d-85039b7350d2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page10_image02.jpg\",\n            \"width\": 473,\n            \"height\": 407,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man wearing black notched lapel blazer\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#716864\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 28,\n          \"y\": 321,\n          \"width\": 131,\n          \"height\": 113,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"722d1c6e-c0a0-4211-9efd-40334ededf63\",\n          \"groupId\": \"ea031cf9-f50f-4dbb-be84-13ff7b4057ab\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 424,\n          \"id\": \"26c667a6-b674-4d80-8907-d1d047f22d10\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">ANDREW BOWLES</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 78,\n          \"height\": 38,\n          \"marginOffset\": -4.941796875000001,\n          \"type\": \"text\",\n          \"groupId\": \"ea031cf9-f50f-4dbb-be84-13ff7b4057ab\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page10_image04.jpg\",\n            \"width\": 478,\n            \"height\": 369,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in black tank top and blue denim jeans sitting on white bed\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#8e8681\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 131.5,\n          \"y\": 478,\n          \"width\": 149,\n          \"height\": 115,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f6623450-3956-4063-a755-3c5f867f7f6e\",\n          \"groupId\": \"ba3dd8b0-9a1f-4cf1-94ab-6823d31ed036\"\n        },\n        {\n          \"x\": 167,\n          \"y\": 584,\n          \"id\": \"3e596e81-7191-4877-8f4b-d75edca34b15\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #fff; text-transform: uppercase\\\">PRINCESSANN</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 78,\n          \"height\": 38,\n          \"marginOffset\": -4.941796875000001,\n          \"type\": \"text\",\n          \"groupId\": \"ba3dd8b0-9a1f-4cf1-94ab-6823d31ed036\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"9dc286a3-d751-41b2-8977-d23fed62e098\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0a0e562c-3211-40e6-ad27-94826819acca\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5faee369-d16b-4b74-b0c9-eddb6870d437\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3b1ba4dc-3e32-40f8-8b5d-fdd3d3aba726\"],\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"4de83bcc-31eb-4b27-bb85-4f458537fe54\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"26c667a6-b674-4d80-8907-d1d047f22d10\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"35429be3-df12-4fd1-9b44-f76d83c89ee4\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3e596e81-7191-4877-8f4b-d75edca34b15\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 47, \"g\": 47, \"b\": 43 } },\n      \"type\": \"page\",\n      \"id\": \"8627c4ea-221a-415b-b6e7-57595e14453c\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2943a234-98e3-426d-8098-4cf9602f8873\": {\n          \"name\": \"Camilla\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ea031cf9-f50f-4dbb-be84-13ff7b4057ab\": {\n          \"name\": \"Andrew\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"aa3a7df9-e8ce-480a-989d-85039b7350d2\": {\n          \"name\": \"Prince\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ba3dd8b0-9a1f-4cf1-94ab-6823d31ed036\": {\n          \"name\": \"Princes\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"014b7cc1-8c92-41f5-a183-5030c30d2b66\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:24\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page11_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White clouds hovering above grey castle\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dfe2dd\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"36814207-dd05-4ef0-beee-8292c34eccd6\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.8 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 734,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ddefd847-49af-484d-81fe-38570fe2d33c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 114, \"g\": 170, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 451,\n          \"width\": 9,\n          \"height\": 61,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cc80373e-ddfc-4e42-af68-afd65350a00e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">If past seasons have been any indication, we should be graced with the presence of Season 4 by November or December 2020. Fingers crossed!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 50,\n          \"y\": 451,\n          \"width\": 318,\n          \"height\": 169,\n          \"id\": \"af365144-8e9c-49bd-bcae-3753b6ec2af4\",\n          \"marginOffset\": -1.3599609374999986\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b2805925-34c8-4930-b176-c505ef4d61a4\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"cc80373e-ddfc-4e42-af68-afd65350a00e\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"786d97ce-5a5d-4695-a350-bd8943038baf\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"94c154b4-e1c1-4a75-8a7c-24edac281431\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #2f2f2b; text-transform: uppercase\\\">Coming Soon</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 305,\n          \"height\": 30,\n          \"marginOffset\": -12.3544921875,\n          \"type\": \"text\",\n          \"id\": \"bb5d3a30-958b-41b0-bcaf-8babb286dcfd\",\n          \"x\": 50,\n          \"y\": 20,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #2f2f2b\\\">Every binge-worthy series to watch on Netflix</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 304,\n          \"height\": 42,\n          \"marginOffset\": -1.7308593750000014,\n          \"type\": \"text\",\n          \"id\": \"124e320d-b858-4089-a316-837c5f682bf5\",\n          \"x\": 50,\n          \"y\": 52\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page12_image01.jpg\",\n            \"width\": 477,\n            \"height\": 318,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man standing on white snow covered ground beside mountain\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#e3e5e7\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 53,\n          \"y\": 220,\n          \"width\": 207,\n          \"height\": 138,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"72ebcf6e-cf8b-43d6-9376-b4146cc86442\",\n          \"groupId\": \"3c708bae-ecf1-4617-bf79-6853423ba859\"\n        },\n        {\n          \"x\": 77,\n          \"y\": 137,\n          \"id\": \"50008343-bd15-4944-9749-8c0824b42820\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #2f2f2b; text-transform: uppercase\\\">The Mountain</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 293,\n          \"height\": 123,\n          \"marginOffset\": -7.9599609375,\n          \"type\": \"text\",\n          \"groupId\": \"3c708bae-ecf1-4617-bf79-6853423ba859\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-19T17:26:37\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/tv-show-recap/page12_image02.jpg\",\n            \"width\": 457,\n            \"height\": 450,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man holding basketball\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#b8b8b8\",\n            \"isExternal\": true\n          },\n          \"type\": \"image\",\n          \"x\": 212,\n          \"y\": 441,\n          \"width\": 152,\n          \"height\": 150,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"f8cecf79-f041-4e47-9d2d-0b9e8aaf1e58\",\n          \"groupId\": \"a3c504a4-0eee-4b68-ab70-fc8e4d011ae7\"\n        },\n        {\n          \"x\": 50,\n          \"y\": 420,\n          \"id\": \"f689648d-cba9-4bbf-92d5-2812b79ea84b\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 2189,\n              \"tDes\": -600,\n              \"tLGap\": 0,\n              \"wAsc\": 2302,\n              \"wDes\": 651,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -557,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 50,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #2f2f2b; text-transform: uppercase\\\">Nba Addicts</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 293,\n          \"height\": 123,\n          \"marginOffset\": -7.9599609375,\n          \"type\": \"text\",\n          \"groupId\": \"a3c504a4-0eee-4b68-ab70-fc8e4d011ae7\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"96418cd8-e262-4448-95c6-d1b2ff03f9a6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f8cecf79-f041-4e47-9d2d-0b9e8aaf1e58\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2500,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"384b135f-c975-4939-9f53-813e7973ab18\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"72ebcf6e-cf8b-43d6-9376-b4146cc86442\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 241, \"b\": 114 } },\n      \"type\": \"page\",\n      \"id\": \"483fa3cd-07b9-483a-87ea-b6d169ce2e1e\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"3c708bae-ecf1-4617-bf79-6853423ba859\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a3c504a4-0eee-4b68-ab70-fc8e4d011ae7\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ultimate-comparison/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/ultimate-comparison/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'ultimate-comparison',\n  creationDate: '2021-07-12T00:00:00.000Z',\n  title: _x('Ultimate Comparison', 'template name', 'web-stories'),\n  tags: [\n    _x('Technology', 'template keyword', 'web-stories'),\n    _x('Products', 'template keyword', 'web-stories'),\n    _x('Comparison', 'template keyword', 'web-stories'),\n    _x('Minimal', 'template keyword', 'web-stories'),\n    _x('White', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Rose White', 'color', 'web-stories'),\n      color: '#fff8f2',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Coal Black', 'color', 'web-stories'),\n      color: '#060607',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Ember Orange', 'color', 'web-stories'),\n      color: '#de7032',\n      family: _x('Orange', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'With its ultra-modern typography, minimalistic layout and fresh, contrasty color palette, this template will let you create product guides that are clear, attractive and effective.',\n    'web-stories'\n  ),\n  vertical: _x('Technology', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/ultimate-comparison/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ultimate-comparison/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -334,\n          \"y\": -331.5,\n          \"width\": 1080,\n          \"height\": 1281,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"c7f24a7c-dca3-40d8-b1ba-57b2cdda81bb\",\n          \"scale\": 138,\n          \"focalX\": 60.77390837071543,\n          \"focalY\": 48.73142191659272,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:04:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page1_bg.jpg\",\n            \"width\": 1080,\n            \"height\": 1281,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man in white dress shirt holding smartphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a2a7ac\",\n            \"isExternal\": true\n          },\n          \"overlay\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 0.26 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 }, \"position\": 1 }\n            ],\n            \"alpha\": 0.8\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 38,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">The battle of noise cancelling headphones</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 385,\n          \"width\": 317,\n          \"height\": 153,\n          \"id\": \"409d1f48-430b-4661-a45c-d216ffae3359\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">The ultimate comparison</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 358,\n          \"width\": 234,\n          \"height\": 19,\n          \"id\": \"26fa841d-4fc4-4eff-b272-e655d15b76e9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 359,\n          \"width\": 6,\n          \"height\": 170,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5e9bbca5-9939-4fb0-a107-68d39f263084\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 591,\n          \"id\": \"82d2cab0-eaaf-45c4-96d2-d174c4634a0e\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fbe6d7; letter-spacing: 0.02em; text-transform: uppercase\\\">By: John Derric</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"f1bd71af-ab18-4da6-ac5b-5cda241c9ccb\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"b4a79d54-2076-43d1-a954-5e2e74a5c148\"\n      },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -434,\n          \"y\": -651,\n          \"width\": 1280,\n          \"height\": 1920,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"image\",\n          \"id\": \"68f166d4-de2b-4a4b-ae13-5c58dfa5803b\",\n          \"scale\": 108,\n          \"focalX\": 51.86011904761906,\n          \"focalY\": 47.726521164021165,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:04:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page2_bg.jpg\",\n            \"width\": 1280,\n            \"height\": 1920,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man in black hoodie wearing black headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#45403d\",\n            \"isExternal\": true\n          },\n          \"overlay\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2; letter-spacing: 0.02em\\\">We demand a premium listening experience that doesn't skimp on the bells and whistles. Read on to see which headphones rise to the occasion.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 172,\n          \"id\": \"46f08b51-2ddd-4408-a6c7-ce72b673dc85\",\n          \"x\": 48,\n          \"y\": 425,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e7991fd3-5be8-4c13-ba7c-339902b74d22\",\n          \"type\": \"effect-background-zoom\",\n          \"targets\": [\"68f166d4-de2b-4a4b-ae13-5c58dfa5803b\"],\n          \"zoomDirection\": \"scaleIn\",\n          \"duration\": 5000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"af404a13-9c10-415a-9df4-129656b2fb6d\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"type\": \"shape\",\n        \"id\": \"e0737409-ce16-4f47-a511-8a4b4da96c84\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"8082ab1e-340c-479a-8d1a-e7bdbf97acc8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 216, \"b\": 217 } },\n          \"type\": \"image\",\n          \"x\": 47,\n          \"y\": -60,\n          \"width\": 365,\n          \"height\": 414,\n          \"scale\": 100,\n          \"focalX\": 50.888543826733155,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"732b09ad-605e-42e9-874b-4a74ba138a29\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:05:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page3.png\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black wireless headset\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3dbdb\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 47,\n          \"y\": 349,\n          \"id\": \"340bc823-a3fe-4a5f-91f6-22631bf3424d\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"width\": 365,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 25,\n            \"vertical\": 23\n          },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">01</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 65,\n          \"id\": \"dc1a8c40-1df3-448a-ba5a-6465c8bf1c2c\",\n          \"x\": 347,\n          \"y\": 354,\n          \"marginOffset\": -2.873000000000001\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #3e3939\\\">These headphones not only look incredibly sophisticated, they're comfortable and block out noise completely.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 72,\n          \"id\": \"dab89972-4f2d-415b-93ea-f7ff4fa71519\",\n          \"x\": 140,\n          \"y\": 546\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #0c0b0b; text-transform: uppercase\\\">TeoLAB X9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 36,\n          \"id\": \"21f43598-56b7-43d9-8112-8713d004d822\",\n          \"x\": 48,\n          \"y\": 468\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"246f47ba-1b5d-446c-ba48-549913ccea2d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"340bc823-a3fe-4a5f-91f6-22631bf3424d\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"d8b3594d-032b-4262-8159-61bf9960ed56\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"732b09ad-605e-42e9-874b-4a74ba138a29\"],\n          \"duration\": 2500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"4e0c2b3c-d2a6-48e8-9c98-71dab1b753e1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"dc1a8c40-1df3-448a-ba5a-6465c8bf1c2c\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"d636baa1-3fcc-4418-87c3-3b6c8cc49623\",\n      \"pageTemplateType\": \"list\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"137d2294-1e4b-4e90-b577-59deee8af6f9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2; letter-spacing: 0.02em; text-transform: uppercase\\\">$399 USD</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19,\n          \"id\": \"1d7a5db6-9046-4f36-ba99-e0b3ad88c427\",\n          \"x\": 85,\n          \"y\": 39,\n          \"groupId\": \"ee8e8a36-7bad-43b8-8159-132b07f4f82b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">TeoLAB X9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 36,\n          \"id\": \"4ce813d2-6a07-4a87-935a-cd71f538f996\",\n          \"x\": 85,\n          \"y\": 0,\n          \"groupId\": \"ee8e8a36-7bad-43b8-8159-132b07f4f82b\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 96,\n          \"width\": 266,\n          \"height\": 258,\n          \"scale\": 120,\n          \"focalX\": 40.1976055003798,\n          \"focalY\": 44.13836611739884,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4478889d-8cac-4e32-8c89-d56d8a28e3b8\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:05:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page4_image1.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in Black Sweater Wearing Black Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2b2d33\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 267,\n          \"y\": 96,\n          \"id\": \"3d709325-743c-47fd-a27f-5abf15cafa83\",\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 145,\n          \"height\": 258,\n          \"scale\": 137,\n          \"focalX\": 44.634448369447725,\n          \"focalY\": 53.70038043486364,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:07:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page4_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Wearing Black Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#cac6c2\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"type\": \"shape\",\n          \"x\": 49,\n          \"y\": 413,\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2f224bc7-225d-4ec3-9529-fea1fb09b255\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 451,\n          \"id\": \"e530f07c-bad3-4367-95be-724e86739066\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"type\": \"shape\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 49,\n          \"y\": 524,\n          \"id\": \"36362b98-a242-42b6-858e-45df2b225e40\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"type\": \"shape\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"x\": 48,\n          \"y\": 387,\n          \"id\": \"edf1779b-4505-4f81-a425-21f04356e16c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Pros</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 34,\n          \"height\": 17,\n          \"groupId\": \"0a18f55e-2e2c-4ea4-89b4-48508bf53ac9\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 426,\n          \"id\": \"a1f84f55-01c2-4502-b703-cd41ea83a723\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Nice headphone fit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"groupId\": \"0a18f55e-2e2c-4ea4-89b4-48508bf53ac9\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 464,\n          \"id\": \"a55067d4-bc22-449e-8bf4-fb2ee3e1f61a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Spacious soundstage</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"groupId\": \"0a18f55e-2e2c-4ea4-89b4-48508bf53ac9\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 537,\n          \"id\": \"e2e5902a-c8e7-4be3-8432-1ce2df1be4b4\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Blocks out background noise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"groupId\": \"0a18f55e-2e2c-4ea4-89b4-48508bf53ac9\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 387,\n          \"id\": \"3e0dce9d-118f-4365-bf42-d95d1b9f08ad\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Cons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 43,\n          \"height\": 19,\n          \"groupId\": \"845ad86c-e09b-4412-b7d1-98eb17607aef\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 426,\n          \"id\": \"8b90c646-3c22-4c74-bdc8-449dfc338628\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Can be a large fit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"groupId\": \"845ad86c-e09b-4412-b7d1-98eb17607aef\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 464,\n          \"id\": \"410dc217-a73a-4ca2-a58f-911a5a5ad9ef\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Clarity of sound overcorrects for high pitches</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 54,\n          \"groupId\": \"845ad86c-e09b-4412-b7d1-98eb17607aef\"\n        },\n        {\n          \"x\": 223,\n          \"y\": 537,\n          \"id\": \"c74cd2ff-e9a1-4bd8-8b91-1dd369373091\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Can be pricey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"groupId\": \"845ad86c-e09b-4412-b7d1-98eb17607aef\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"757e71e4-965d-4c02-b927-7d5de244ed39\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"edf1779b-4505-4f81-a425-21f04356e16c\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"5347bdd9-9d2b-485a-a239-0fe4bc9a1d96\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3e0dce9d-118f-4365-bf42-d95d1b9f08ad\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"715fa325-5899-41d2-b05b-08a14f7b50a5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a1f84f55-01c2-4502-b703-cd41ea83a723\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"2913059c-09ea-46fa-8da5-b4f95dc9c832\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8b90c646-3c22-4c74-bdc8-449dfc338628\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"c5d3c90f-3833-4960-b49e-4adb3de3ad54\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e530f07c-bad3-4367-95be-724e86739066\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"a834aec2-c0aa-4d8f-b9d2-0d1e103ab3a9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a55067d4-bc22-449e-8bf4-fb2ee3e1f61a\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"9a2c6f45-a9e1-4e31-8370-4604f4fa3107\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"410dc217-a73a-4ca2-a58f-911a5a5ad9ef\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d72c9393-0a1c-4184-8a67-bfce4c81cbf3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"36362b98-a242-42b6-858e-45df2b225e40\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"63b9f160-d609-4357-8063-ae67e2946f26\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e2e5902a-c8e7-4be3-8432-1ce2df1be4b4\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"27a15a1f-4b5a-45e0-af2f-c8d42793c13e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c74cd2ff-e9a1-4bd8-8b91-1dd369373091\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"09a765dd-a2d4-4e53-8343-0bdac33897eb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2f224bc7-225d-4ec3-9529-fea1fb09b255\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 100\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n      \"type\": \"page\",\n      \"id\": \"9b4a6651-8a12-4055-9e20-c33b027bdb23\",\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"0a18f55e-2e2c-4ea4-89b4-48508bf53ac9\": {\n          \"name\": \"Pros\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"845ad86c-e09b-4412-b7d1-98eb17607aef\": {\n          \"name\": \"Cons\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ee8e8a36-7bad-43b8-8159-132b07f4f82b\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f6e529c4-dbe7-457c-985c-6ebf84f8810f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 216, \"b\": 217 } },\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 365,\n          \"height\": 414,\n          \"scale\": 105,\n          \"focalX\": 49.53457228123499,\n          \"focalY\": 52.286379349015355,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7761bc63-d69f-4920-9140-e13d344bc07f\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:08:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page5.png\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black and silver headphones on white surface\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#d3dbdb\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"x\": 0,\n          \"y\": 349,\n          \"id\": \"2243d4b1-ec78-4234-afd2-ae9b7cd6ee6a\",\n          \"width\": 365,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 20,\n            \"vertical\": 23\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">02</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 65,\n          \"id\": \"af14575b-fe88-4b59-af6d-06aaa56eca6f\",\n          \"x\": 299,\n          \"y\": 355,\n          \"marginOffset\": -2.873000000000001,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #3e3939\\\">Superior sound with a pure voice assistant.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 37,\n          \"id\": \"a85d23b2-d423-440c-82e6-44b87d37af0d\",\n          \"x\": 140,\n          \"y\": 546,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #0c0b0b; text-transform: uppercase\\\">KROX WH-1000XM3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 36,\n          \"id\": \"e1c6f95f-7edb-44f8-9b1d-bf5a62d3de09\",\n          \"x\": 48,\n          \"y\": 468,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"b74880bd-e86c-4d50-8886-ffd02af125f7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7761bc63-d69f-4920-9140-e13d344bc07f\"],\n          \"duration\": 2500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"7df825d9-6d2b-4d51-9a34-f68ff6a7d99e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2243d4b1-ec78-4234-afd2-ae9b7cd6ee6a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"57d4ff3f-2964-417a-8f14-b1e71dc16e08\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"af14575b-fe88-4b59-af6d-06aaa56eca6f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"61b8b7dd-4fe4-452a-8965-4e79fcda8f69\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"23602568-add0-48c4-a76c-b550bb7da0e0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2; letter-spacing: 0.02em\\\">$378 USD</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19,\n          \"id\": \"2b10a841-466b-4f5d-b352-0151690194ea\",\n          \"x\": 85,\n          \"y\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"98888942-501c-473f-887e-ed76af7e833a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">KROX WH-1000XM3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 62,\n          \"id\": \"5b67b8df-f9e3-4eda-98d3-19f3a7f8216e\",\n          \"x\": 85,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"98888942-501c-473f-887e-ed76af7e833a\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 96,\n          \"width\": 266,\n          \"height\": 258,\n          \"scale\": 129,\n          \"focalX\": 40.881493488725404,\n          \"focalY\": 40.81394899604929,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"82972bdd-0a23-4370-be81-338340816b90\",\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:09:10\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page6_image1.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Looking Up While Wearing Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#979fa2\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 267,\n          \"y\": 96,\n          \"id\": \"9291815a-caf4-4c23-a8ad-b3d200fba313\",\n          \"width\": 146,\n          \"height\": 258,\n          \"scale\": 190,\n          \"focalX\": 47.776525791331935,\n          \"focalY\": 51.667605656501046,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:09:44\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page6_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in Black Shirt Wearing Black Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#454533\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 424,\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"56887a35-7289-4962-aa88-f68adf9bf46f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 480,\n          \"id\": \"83b4e4cf-d211-49ad-aea6-b6e668b28b7d\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 553,\n          \"id\": \"4dd0da63-68d7-4441-aafd-372af1509a44\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 398,\n          \"id\": \"45cf6bdf-b001-4cc8-9346-90ff2e8dac30\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Pros</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 34,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"bfe9a8e6-7035-488b-8999-0ca4dfdb2ef0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 437,\n          \"id\": \"94b87c82-6ef8-4e1f-b334-8bb710022f6b\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Voice assistant</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"bfe9a8e6-7035-488b-8999-0ca4dfdb2ef0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 493,\n          \"id\": \"a3a9934e-5f87-4f18-b595-5482a403e47c\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Spacious soundstage</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"bfe9a8e6-7035-488b-8999-0ca4dfdb2ef0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 566,\n          \"id\": \"33159e88-340f-48d8-a6c4-65dabc9c3251\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Blocks out background noise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"bfe9a8e6-7035-488b-8999-0ca4dfdb2ef0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 398,\n          \"id\": \"fe9d7f5b-bf27-40c0-b063-ecb77aec1bfe\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Cons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 43,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"7c53b632-dbfe-4b1b-98dd-f8c3f7f827bb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 437,\n          \"id\": \"9f39e42a-f838-4ca9-9b4a-e73e6bb67ac1\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Speaking but not hearing yourself</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"7c53b632-dbfe-4b1b-98dd-f8c3f7f827bb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 224,\n          \"y\": 493,\n          \"id\": \"8e17920d-d6a1-47ac-a01b-03f8f7101785\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">More bass and depth of sound vs. higher pitches</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 53,\n          \"type\": \"text\",\n          \"groupId\": \"7c53b632-dbfe-4b1b-98dd-f8c3f7f827bb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 225,\n          \"y\": 566,\n          \"id\": \"3e5cbbf6-8ea5-48af-bcb7-ff688528b60c\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Can be pricey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"7c53b632-dbfe-4b1b-98dd-f8c3f7f827bb\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"a70652f3-b422-4919-b049-d0eeb91b9226\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"45cf6bdf-b001-4cc8-9346-90ff2e8dac30\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"c9f115e1-d2cf-4d0a-a900-60e35048892a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fe9d7f5b-bf27-40c0-b063-ecb77aec1bfe\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ab278920-8b64-4b1d-bbe4-ba320b377b71\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"83b4e4cf-d211-49ad-aea6-b6e668b28b7d\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"f3b83385-fda9-47db-818f-6cea362cbce5\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a3a9934e-5f87-4f18-b595-5482a403e47c\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"a586b2b1-ae51-4537-87e0-5b3da2b8c2a1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8e17920d-d6a1-47ac-a01b-03f8f7101785\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d0d8bebe-9808-4afb-8b6f-ff820f5d843b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"56887a35-7289-4962-aa88-f68adf9bf46f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"2565345b-f98b-485f-9248-1e929f43624d\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"94b87c82-6ef8-4e1f-b334-8bb710022f6b\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"ccf014ad-d9bf-40b6-a11b-0d64f3bcd367\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9f39e42a-f838-4ca9-9b4a-e73e6bb67ac1\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"229a59cb-00f7-46a7-bb7c-027b8b5adceb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4dd0da63-68d7-4441-aafd-372af1509a44\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"012e4128-ce97-410e-8bff-af7f03224162\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"33159e88-340f-48d8-a6c4-65dabc9c3251\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"febb7e8a-01fb-4617-a58b-071181116cd2\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"3e5cbbf6-8ea5-48af-bcb7-ff688528b60c\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n      \"type\": \"page\",\n      \"id\": \"ec643a90-770d-435b-a6fb-a435405301a4\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"bfe9a8e6-7035-488b-8999-0ca4dfdb2ef0\": {\n          \"name\": \"Pros\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"7c53b632-dbfe-4b1b-98dd-f8c3f7f827bb\": {\n          \"name\": \"Cons\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"98888942-501c-473f-887e-ed76af7e833a\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"12a28ef9-9a03-4d3b-aed8-4fe56ced4e06\",\n          \"type\": \"shape\"\n        },\n        {\n          \"x\": 47,\n          \"y\": -59,\n          \"id\": \"bc8ab70e-e1b1-4c2c-a6f9-d87458ae1ece\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"width\": 365,\n          \"height\": 415,\n          \"scale\": 100,\n          \"focalX\": 52.21600689739534,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:10:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page7.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"gray and black wireless headphones on desk\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#2d2f32\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"x\": 47,\n          \"y\": 351,\n          \"id\": \"58f8250e-a4b1-4062-80e2-15630f8a1641\",\n          \"width\": 365,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 20,\n            \"vertical\": 23\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">03</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 64,\n          \"height\": 65,\n          \"id\": \"0c867697-07b0-44e9-8238-483973e6e4b6\",\n          \"x\": 348,\n          \"y\": 356,\n          \"marginOffset\": -2.873000000000001,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #3e3939\\\">Premium on-ear&nbsp;</span>\\n<span style=\\\"color: #3e3939\\\">noise-cancellers for a less&nbsp;</span>\\n<span style=\\\"color: #3e3939\\\">than premium price.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 53,\n          \"id\": \"b2b120f7-837b-4c13-a059-67621c905308\",\n          \"x\": 140,\n          \"y\": 546,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #0c0b0b; text-transform: uppercase\\\">MAAB PH805</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 36,\n          \"id\": \"9badd786-0ef6-4f90-90d5-a2d963301c9f\",\n          \"x\": 48,\n          \"y\": 468,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"7306de21-b153-423e-912a-1f344a17c7b0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bc8ab70e-e1b1-4c2c-a6f9-d87458ae1ece\"],\n          \"duration\": 2500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5e6b92a2-6dfb-4911-adc0-1b6753a252fa\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"58f8250e-a4b1-4062-80e2-15630f8a1641\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"ae7e39d2-973b-4019-bf51-f6f0154a8f58\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0c867697-07b0-44e9-8238-483973e6e4b6\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"0b0a26c1-4b43-48cc-9b10-5ec80c9849e6\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"4257f684-a4a7-429c-865f-3c3cccab0625\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2; letter-spacing: 0.02em\\\">$289 USD</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19,\n          \"id\": \"7f4f523b-a22d-43ca-8678-3e77854b140c\",\n          \"x\": 85,\n          \"y\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"84f01347-fbf9-41e4-a972-3897d9bf43a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">MAAB</span>\\n<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">PH805</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 62,\n          \"id\": \"2569e09d-f521-4cbf-a47c-505771c26fe9\",\n          \"x\": 85,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"84f01347-fbf9-41e4-a972-3897d9bf43a9\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:11:39\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page8_image1.jpg\",\n            \"width\": 1280,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man in Blue Crew Neck T-shirt Wearing Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#938d8c\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": -1,\n          \"y\": 96,\n          \"width\": 266,\n          \"height\": 258,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"99363490-078c-4d81-b93c-b5d8e4c53f1c\",\n          \"type\": \"image\",\n          \"groupId\": \"058bf694-0585-469a-b1dc-2af4cc0209cc\"\n        },\n        {\n          \"opacity\": 15,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"type\": \"shape\",\n          \"x\": -1,\n          \"y\": 96,\n          \"width\": 266,\n          \"height\": 258,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b810c43c-219d-469e-bfc0-8184724da67e\",\n          \"groupId\": \"058bf694-0585-469a-b1dc-2af4cc0209cc\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 61.32193067053774,\n          \"focalY\": 50.301459077906074,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:12:12\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page8_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"man in black jacket wearing black headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#7a7a84\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 267,\n          \"y\": 96,\n          \"id\": \"d18132ab-00d8-4faa-aecd-09074ede27f0\",\n          \"width\": 146,\n          \"height\": 258,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 424,\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a621eceb-75ae-41a1-b0c6-a94f414cf0de\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 461,\n          \"id\": \"1ae04737-1d43-43f7-badd-02d65c90288f\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 516,\n          \"id\": \"4c7690a2-d7ab-44db-afeb-f704f42964aa\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 398,\n          \"id\": \"2d99f757-dff8-4b1a-8605-722e239100a4\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Pros</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 34,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"5084dd49-d705-49e4-92d7-328b84857ac2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 437,\n          \"id\": \"9fbc20f8-e2b8-4f73-bf52-0a509616cd99\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Minimal look</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"5084dd49-d705-49e4-92d7-328b84857ac2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 474,\n          \"id\": \"eee81c42-0d89-41ac-9166-29d6a60f09d2\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Balanced sound</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"5084dd49-d705-49e4-92d7-328b84857ac2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 529,\n          \"id\": \"43d23b6e-8645-430f-943b-cbe797394b1e\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Blocks out background noise</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"5084dd49-d705-49e4-92d7-328b84857ac2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 224,\n          \"y\": 398,\n          \"id\": \"8ff8c32e-2aba-4f39-9b53-188e6f4b9988\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Cons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 43,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"edd168c4-9e02-4ce6-bc12-4e6cda22c8be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 225,\n          \"y\": 437,\n          \"id\": \"fa37253f-576c-4fd4-8de5-1a82bcf0240d\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Tight headphone fit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 142,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"edd168c4-9e02-4ce6-bc12-4e6cda22c8be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 474,\n          \"id\": \"40a6914a-d145-41c6-a302-6074cb16af4c\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Loose fit over the \\near</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"edd168c4-9e02-4ce6-bc12-4e6cda22c8be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 529,\n          \"id\": \"bd41c6ef-113f-4de9-a88a-2f424544243e\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Proper fit over ear is difficult to achieve</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 141,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"edd168c4-9e02-4ce6-bc12-4e6cda22c8be\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"abe047e7-931e-4a8a-bf1d-7d14fda9e605\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"2d99f757-dff8-4b1a-8605-722e239100a4\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"a88241d9-aa53-4f9a-8d36-b7f3b94b182c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"8ff8c32e-2aba-4f39-9b53-188e6f4b9988\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0450b080-a104-49b7-bd2b-553cd59b9007\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a621eceb-75ae-41a1-b0c6-a94f414cf0de\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"6883ecc6-826c-4958-80cb-4b5b0f90e332\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9fbc20f8-e2b8-4f73-bf52-0a509616cd99\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5cb17bcf-f07d-4171-ab82-6dabb8debe88\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fa37253f-576c-4fd4-8de5-1a82bcf0240d\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"570826b5-d45a-49fc-ae8e-20705568d32f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1ae04737-1d43-43f7-badd-02d65c90288f\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"7d56f739-1d6a-4b7f-94ce-c1b3ec56021c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4c7690a2-d7ab-44db-afeb-f704f42964aa\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"69f8b089-9cd5-4a2a-bfd6-86fa3a0022fd\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"eee81c42-0d89-41ac-9166-29d6a60f09d2\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"51c2831c-2061-4c0c-ac38-a82c2d589286\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"40a6914a-d145-41c6-a302-6074cb16af4c\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"d7a94be0-116e-4418-b179-2ad88813d585\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"43d23b6e-8645-430f-943b-cbe797394b1e\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"090c65ae-787d-4d4d-b9e8-e69e0781cd5b\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"bd41c6ef-113f-4de9-a88a-2f424544243e\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n      \"type\": \"page\",\n      \"id\": \"ec8a2052-1146-4399-ad06-d15180749c4e\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"5084dd49-d705-49e4-92d7-328b84857ac2\": {\n          \"name\": \"Pros\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"edd168c4-9e02-4ce6-bc12-4e6cda22c8be\": {\n          \"name\": \"Cons\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"84f01347-fbf9-41e4-a972-3897d9bf43a9\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"058bf694-0585-469a-b1dc-2af4cc0209cc\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"774d703d-f06b-4bc1-b090-ccb5bf9531bc\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 216, \"b\": 217 } },\n          \"x\": 0,\n          \"y\": -59,\n          \"width\": 365,\n          \"height\": 414,\n          \"scale\": 105,\n          \"focalX\": 48.517036807697664,\n          \"focalY\": 52.286379349015355,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"33962ba8-ee88-4654-afc7-4a6f3e00e843\",\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:13:20\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page9.png\",\n            \"width\": 1280,\n            \"height\": 721,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"White Cordless Headphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#ebeaea\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"x\": 0,\n          \"y\": 349,\n          \"id\": \"1720e776-6b6b-4c42-a20c-7b055f713814\",\n          \"width\": 365,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"border\": {\n            \"left\": 0,\n            \"right\": 0,\n            \"top\": 0,\n            \"bottom\": 0,\n            \"lockedWidth\": false,\n            \"color\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } }\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"lineHeight\": 1.14,\n          \"textAlign\": \"center\",\n          \"padding\": {\n            \"locked\": false,\n            \"hasHiddenPadding\": true,\n            \"horizontal\": 20,\n            \"vertical\": 23\n          },\n          \"content\": \"<span style=\\\"color: #fff\\\">04</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0\n          },\n          \"width\": 66,\n          \"height\": 65,\n          \"id\": \"475ffc44-499d-4ba8-87ea-fb5a9e792bed\",\n          \"x\": 299,\n          \"y\": 355,\n          \"marginOffset\": -2.873000000000001,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #3e3939\\\">The Beats Solo Pro takes sound and design seriously.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 224,\n          \"height\": 36,\n          \"id\": \"6d1a8019-7b6e-4b2b-80a0-79477648774e\",\n          \"x\": 140,\n          \"y\": 546,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #0c0b0b; text-transform: uppercase\\\">Bool solo pro</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 36,\n          \"id\": \"3614f35f-be79-46dc-800e-c77a6e6520b4\",\n          \"x\": 48,\n          \"y\": 468,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"19bdc0fa-7631-462b-a7b7-4cc3eb9bc0d0\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"33962ba8-ee88-4654-afc7-4a6f3e00e843\"],\n          \"duration\": 2500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"f51168af-b09a-4c83-b9f5-854cbefed2a2\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1720e776-6b6b-4c42-a20c-7b055f713814\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"a80cda7d-24a4-41b8-931f-3ce4bbdf3bcc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"475ffc44-499d-4ba8-87ea-fb5a9e792bed\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 250\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"83187b22-480b-49c5-afa5-dd8342a85a8d\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"94e4bf8c-486c-43b1-870b-5cdf227b0dc9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2; letter-spacing: 0.02em\\\">$399 USD</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 19,\n          \"id\": \"9337d6e7-9163-4368-84ce-b0048fd620aa\",\n          \"x\": 85,\n          \"y\": 64,\n          \"type\": \"text\",\n          \"groupId\": \"881dec1c-3683-4bbc-b435-9cb78c412719\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">Bool&nbsp;</span>\\n<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">solo pro</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 272,\n          \"height\": 62,\n          \"id\": \"86df2622-7854-42d1-a941-cbd7b70c7d77\",\n          \"x\": 85,\n          \"y\": 0,\n          \"type\": \"text\",\n          \"groupId\": \"881dec1c-3683-4bbc-b435-9cb78c412719\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 51.854702876498706,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:14:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page10_image1.jpg\",\n            \"width\": 984,\n            \"height\": 720,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Wearing White Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#beaca5\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": -1,\n          \"y\": 96,\n          \"width\": 266,\n          \"height\": 258,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f7b43e55-fe65-4e05-9f8d-98bd19e80aa2\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 90,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:14:34\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page10_image2.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman in Gray Sweatshirt Wearing Headphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#a59385\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 266,\n          \"y\": 96,\n          \"id\": \"87b25fef-82de-4413-9a0a-5b76a3a90533\",\n          \"width\": 146,\n          \"height\": 258,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 424,\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"660d35e1-cfb7-4af3-99ec-21a8c88eaeae\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 480,\n          \"id\": \"3f50c302-ecd6-45ab-b215-a8e3c42b2daa\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 248, \"b\": 242, \"a\": 0.3 }\n          },\n          \"x\": 49,\n          \"y\": 536,\n          \"id\": \"2f139a7d-0d2b-4f3d-9690-774604e2e1de\",\n          \"width\": 363,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 398,\n          \"id\": \"52e639fa-90de-4caf-8bb8-811bcb481e68\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Pros</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 34,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"da6258c7-43c9-4d30-bfb4-20a86424e917\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 437,\n          \"id\": \"4ba4d009-59ba-4450-aa0d-62608de9677b\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">More accurate sound</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"da6258c7-43c9-4d30-bfb4-20a86424e917\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 493,\n          \"id\": \"b0f5027d-a530-435c-a744-054be8e21aa0\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Best-sounding Beats headphones</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"da6258c7-43c9-4d30-bfb4-20a86424e917\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 49,\n          \"y\": 549,\n          \"id\": \"e94ac728-94a4-43f1-abe8-ca34eeab6e6a\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Effective noise cancelling</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"da6258c7-43c9-4d30-bfb4-20a86424e917\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 398,\n          \"id\": \"9924c9b2-7480-43ba-b0f0-2538e9476f98\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff8f2\\\">Cons</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 43,\n          \"height\": 19,\n          \"type\": \"text\",\n          \"groupId\": \"5de0f1c9-99a4-46c9-8f64-9b035a0d4a9e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 437,\n          \"id\": \"66a9af56-e98a-4839-a333-6bc53e616446\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Tight headphone fit</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 142,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"5de0f1c9-99a4-46c9-8f64-9b035a0d4a9e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 493,\n          \"id\": \"139b2e14-c7c6-4909-a03c-df4bb37b2641\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">A bit large and unwieldy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 36,\n          \"type\": \"text\",\n          \"groupId\": \"5de0f1c9-99a4-46c9-8f64-9b035a0d4a9e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 223,\n          \"y\": 549,\n          \"id\": \"de9fff52-0ed6-4500-b84e-5bb83f31f1e0\",\n          \"content\": \"<span style=\\\"color: #fff8f2\\\">Can be pricey</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 134,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"groupId\": \"5de0f1c9-99a4-46c9-8f64-9b035a0d4a9e\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"3abb7d16-ec51-485c-8d3c-8eab07d49470\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"52e639fa-90de-4caf-8bb8-811bcb481e68\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"1570b94d-7deb-4f5f-bfe3-7abbb207682c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9924c9b2-7480-43ba-b0f0-2538e9476f98\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"ce54a330-5e8c-4d06-94a9-df1f870b3241\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"660d35e1-cfb7-4af3-99ec-21a8c88eaeae\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"41153606-206a-4277-b1d4-1a7d2c0e93b6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4ba4d009-59ba-4450-aa0d-62608de9677b\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"8d4bfde1-b6b5-4298-8604-197dcd75a15e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"66a9af56-e98a-4839-a333-6bc53e616446\"],\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"5490636e-a651-4dac-80fe-7530e638a40c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3f50c302-ecd6-45ab-b215-a8e3c42b2daa\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"f50118e7-ce75-44f0-b5d6-0a6da3ae05e9\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"b0f5027d-a530-435c-a744-054be8e21aa0\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"ffc7e98a-e832-4239-a7a0-d4706df2bdf7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"139b2e14-c7c6-4909-a03c-df4bb37b2641\"],\n          \"duration\": 1600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"42b9f3d6-78cb-4f7a-83c3-e2bd739bb52d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2f139a7d-0d2b-4f3d-9690-774604e2e1de\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"4eb26d4b-4202-41e6-90de-ac63066ffb00\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e94ac728-94a4-43f1-abe8-ca34eeab6e6a\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"7afb58fd-60ee-4288-8c66-d14b1ff33a11\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"de9fff52-0ed6-4500-b84e-5bb83f31f1e0\"],\n          \"duration\": 1600,\n          \"delay\": 600\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n      \"type\": \"page\",\n      \"id\": \"fe2623ee-7d43-4d5c-b6cd-f8defc375dd1\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"da6258c7-43c9-4d30-bfb4-20a86424e917\": {\n          \"name\": \"Pros\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"5de0f1c9-99a4-46c9-8f64-9b035a0d4a9e\": {\n          \"name\": \"Cons\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"881dec1c-3683-4bbc-b435-9cb78c412719\": {\n          \"name\": \"Header\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"601e82ad-a3ae-4d1d-8b6c-5c80f04e3e30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": 218,\n          \"width\": 412,\n          \"height\": 458,\n          \"scale\": 100,\n          \"focalX\": 51.60095445269871,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3f5df7ab-4ff0-43e1-8313-cbd064b3788e\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:05:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page3.png\",\n            \"width\": 330,\n            \"height\": 185,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black wireless headset\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#171717\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 295,\n          \"y\": 63,\n          \"width\": 118,\n          \"height\": 156,\n          \"scale\": 140,\n          \"focalX\": 56.92762954805808,\n          \"focalY\": 38.12406363190044,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3143a8cf-8c52-419f-9ba9-135ab2f928c3\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:16:23\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page11_image1.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Man Holding Smartphone\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#6b6662\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 295,\n          \"y\": 213,\n          \"id\": \"3932e4d5-cacd-4e3d-9fb3-a1a6cc5e0f27\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"width\": 118,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #3e3939\\\">Superior sound with a sophisticated look to match.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 36,\n          \"id\": \"3616e6cf-4a95-41d0-aeea-477432a76b9c\",\n          \"x\": 46,\n          \"y\": 162\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #060607; text-transform: uppercase\\\">TeoLAB X9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 235,\n          \"height\": 26,\n          \"id\": \"2329b36d-1672-4df9-a66e-ca381883194e\",\n          \"x\": 46,\n          \"y\": 78\n        },\n        {\n          \"x\": 57,\n          \"y\": 0,\n          \"id\": \"31928933-f3ff-4700-a1ee-f7f95722a4bb\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"center\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #060607; text-transform: uppercase\\\">The Winner</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 308,\n          \"height\": 45\n        },\n        {\n          \"x\": 0,\n          \"y\": 63,\n          \"id\": \"0653137b-7b3c-49db-af8a-cddf0a2ef09b\",\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"1e68906f-2e93-419b-aa9a-8c9e67046af9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"0653137b-7b3c-49db-af8a-cddf0a2ef09b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"6abf49cb-89ad-4513-84e6-64386b6e860f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3932e4d5-cacd-4e3d-9fb3-a1a6cc5e0f27\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"8d9a4fb8-6774-48d9-a501-2fa1d4e49b2e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"3f5df7ab-4ff0-43e1-8313-cbd064b3788e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"b3d720f6-7a30-48d0-90ca-12563e788039\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6dbf8e53-6b59-45a9-8f4e-ba9997bc226c\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 218,\n          \"width\": 412,\n          \"height\": 458,\n          \"scale\": 105,\n          \"focalX\": 50.09529490789873,\n          \"focalY\": 52.20981164803007,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"17349aef-d259-4387-b25a-c5834aa50cf3\",\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:08:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page5.png\",\n            \"width\": 330,\n            \"height\": 185,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black and silver headphones on white surface\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#cd9668\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 148,\n          \"focalX\": 54.105605736857534,\n          \"focalY\": 37.464874422630515,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:16:59\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page12_image1.jpg\",\n            \"width\": 480,\n            \"height\": 640,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Woman Wearing Black Headphones\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#dcd5d0\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 295,\n          \"y\": 63,\n          \"width\": 118,\n          \"height\": 156,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1e4871c8-4d1a-4c61-9c89-6560557de40e\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"x\": 295,\n          \"y\": 213,\n          \"id\": \"364ceeb5-7922-4905-99cc-0ed8a0fced67\",\n          \"width\": 118,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #3e3939\\\">The longest battery life and the highest frequency range.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 234,\n          \"height\": 36,\n          \"id\": \"9a20dfbf-f0fd-4cae-9e95-0e874e6e3720\",\n          \"x\": 46,\n          \"y\": 162,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #060607; letter-spacing: 0.01em\\\">KROX WH-1000XM3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 196,\n          \"height\": 46,\n          \"id\": \"27505f24-a7c3-47ce-8d5e-f68d219cf71c\",\n          \"x\": 46,\n          \"y\": 78,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 34,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"right\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"x\": 48,\n          \"y\": 0,\n          \"id\": \"6cb55866-bb54-4af6-8508-f28d87d7de0f\",\n          \"content\": \"<span style=\\\"color: #060607; text-transform: uppercase\\\">The Contender</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 45,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n          \"x\": 0,\n          \"y\": 63,\n          \"id\": \"50edac92-c9cd-4e3f-8b56-7948e0519ce8\",\n          \"width\": 412,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"e43030b1-fb2e-4b3a-9c0d-94bafef7bbbb\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"17349aef-d259-4387-b25a-c5834aa50cf3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2500,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"564a02c0-f150-4ba1-97f8-2b27f9dbf363\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"50edac92-c9cd-4e3f-8b56-7948e0519ce8\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"e4b661d8-6e91-4606-ba49-1966dc047a1b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"364ceeb5-7922-4905-99cc-0ed8a0fced67\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1000,\n          \"delay\": 400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"e353672c-5b08-4f7f-9b6e-dba3d7e45076\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c92c3fd1-4f08-4613-881d-fa9a71989956\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #060607; text-transform: uppercase\\\">How do they compare</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 223,\n          \"height\": 62,\n          \"id\": \"7ff70c7d-22e1-4a26-8bc3-6661226daed7\",\n          \"x\": 95,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 48,\n          \"y\": 116,\n          \"width\": 150,\n          \"height\": 114,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"01eddcff-d596-49cf-99cd-3ba558b49b85\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:05:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page3.png\",\n            \"width\": 330,\n            \"height\": 185,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black wireless headset\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#171717\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #181617; text-transform: uppercase\\\">TeoLAB X9</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 17,\n          \"id\": \"86ae8463-8b3a-4bd6-ae7a-34323459dc76\",\n          \"x\": 49,\n          \"y\": 97,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 261,\n          \"id\": \"fa3da0c2-fdf2-4829-bdef-d922289a4851\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Frequency</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 280,\n          \"id\": \"32a4105c-9768-42d0-9af7-bba04b8fcd13\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">20 – 25.000 Hz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 49,\n          \"y\": 314,\n          \"id\": \"3356890c-edd8-4b34-8061-5d7123a2a264\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Microphone</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 332,\n          \"id\": \"2196a6d7-f25a-415a-afac-8e7295ce0554\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">One electret type</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 373,\n          \"id\": \"9cb81c72-03f8-4a33-8cee-6e1c38be4ab1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Sensitivity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 392,\n          \"id\": \"b5efe4a2-8723-4112-9515-94486f15666a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">85 dB/mW @ 1kHz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 433,\n          \"id\": \"807871ca-88d0-4fbd-8a48-b6469f814615\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Battery</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 453,\n          \"id\": \"13583b50-067d-4a7a-8147-d06179a47fae\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">Up to 19 hours</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 495,\n          \"id\": \"04fb3d4f-d685-4967-8dde-f5c22b2b3498\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Impedance</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"x\": 48,\n          \"y\": 514,\n          \"id\": \"b5237dec-49c4-474f-bf0c-f5e8df449b76\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">28 Ohm</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"86c547b4-f610-4fa5-be12-1ce54d2003f1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 212, \"g\": 216, \"b\": 217 } },\n          \"type\": \"image\",\n          \"width\": 150,\n          \"height\": 114,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0b0f1e2f-e4cd-4cc5-a1c4-946fc95aed77\",\n          \"x\": 214,\n          \"y\": 116,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:08:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page5.png\",\n            \"width\": 330,\n            \"height\": 185,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"black and silver headphones on white surface\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"provider\": \"local\",\n            \"baseColor\": \"#cd9668\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 215,\n          \"y\": 97,\n          \"id\": \"40f2ee94-88dc-4396-9a55-cf39885bf358\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #181617; letter-spacing: 0.01em\\\">KROX WH-1000XM3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 16,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 261,\n          \"id\": \"52d5f3a9-3581-47ed-8ff6-1698590ed4ba\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Frequency</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 280,\n          \"id\": \"626eb2ab-9453-4a85-9eef-9d3b074ca361\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">20 – 25.000 Hz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 215,\n          \"y\": 314,\n          \"id\": \"b2e7f45d-c94c-4356-807e-6c47bad5f439\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Microphone</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 332,\n          \"id\": \"807d0910-3d71-499a-a318-142baddd0763\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">Omnidirectional</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 373,\n          \"id\": \"7f1c0ab4-f316-47e4-be55-faef47f692e8\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Sensitivity</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 392,\n          \"id\": \"35324db5-5a10-4abb-86cb-408e84eaf034\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">91 dB/mW @ 1kHz</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 433,\n          \"id\": \"abe479e6-9389-4888-9f95-ab87c6c08a02\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Battery</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 453,\n          \"id\": \"65229104-a2b4-4bbb-ac04-850ddcf44fd5\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">Up to 24 hours</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 495,\n          \"id\": \"4dd27d61-114e-415d-87b6-6ea8aacef40a\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #161415\\\">Impedance</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        },\n        {\n          \"x\": 214,\n          \"y\": 514,\n          \"id\": \"72424921-73f5-45a3-9d55-340437b6193c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.18,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #161415\\\">25 Ohm</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 149,\n          \"height\": 18,\n          \"groupId\": \"a972dfec-5fe8-4f03-a5e7-47500398a717\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 248, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"1b0c21fe-d7f9-4406-ab6f-38aee909c546\",\n      \"pageTemplateType\": \"table\",\n      \"groups\": {\n        \"86c547b4-f610-4fa5-be12-1ce54d2003f1\": {\n          \"name\": \"X9\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"a972dfec-5fe8-4f03-a5e7-47500398a717\": {\n          \"name\": \"WH-1000XM3\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ffd50eff-26a3-49a1-9449-8d777ad7053b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Fahkwang\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1008,\n              \"des\": -292,\n              \"tAsc\": 1008,\n              \"tDes\": -292,\n              \"tLGap\": 0,\n              \"wAsc\": 1258,\n              \"wDes\": 456,\n              \"xH\": 490,\n              \"capH\": 700,\n              \"yMin\": -452,\n              \"yMax\": 1203,\n              \"hAsc\": 1008,\n              \"hDes\": -292,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.9,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff8f2; text-transform: uppercase\\\">Other stories</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 246,\n          \"height\": 62,\n          \"id\": \"a37f3de2-c49b-492e-852e-d43435badf57\",\n          \"x\": 96,\n          \"y\": 0\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 145,\n          \"height\": 110,\n          \"scale\": 130,\n          \"focalX\": 56.00233130547906,\n          \"focalY\": 50.91464096083488,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"23510da7-ee9f-4ab8-951f-2315601110c1\",\n          \"x\": 8,\n          \"y\": 242,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:18:08\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page14_image1.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Joyful millennial woman in headphones listening to music in park\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#807b77\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"0e9deeb5-de18-4368-a1c2-e67b39b448c1\"\n        },\n        {\n          \"x\": 8,\n          \"y\": 346,\n          \"id\": \"e03163b7-6f7e-44f5-9add-dced0fd59322\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"0e9deeb5-de18-4368-a1c2-e67b39b448c1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Hottest bluetooth headphones</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 164,\n          \"height\": 64,\n          \"id\": \"cd8af3fa-a10d-4f6b-8036-ef67fd1dbd7d\",\n          \"x\": 161,\n          \"y\": 240,\n          \"groupId\": \"0e9deeb5-de18-4368-a1c2-e67b39b448c1\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 161,\n          \"y\": 351,\n          \"id\": \"1facff90-3339-4675-9e70-b55ea9726b53\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 81, \"g\": 79, \"b\": 77 } },\n          \"type\": \"shape\",\n          \"width\": 201,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"0e9deeb5-de18-4368-a1c2-e67b39b448c1\"\n        },\n        {\n          \"x\": 8,\n          \"y\": 374,\n          \"id\": \"468147c4-759a-4877-9972-b5eef91d951f\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 145,\n          \"height\": 110,\n          \"scale\": 114,\n          \"focalX\": 42.99765412344801,\n          \"focalY\": 50.130376452750546,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:18:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page14_image2.png\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Macbook Pro\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#171717\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"b2020f0a-e409-4b59-a5a5-ed40cd44d2fb\"\n        },\n        {\n          \"x\": 8,\n          \"y\": 478,\n          \"id\": \"2b33fe58-e795-41ca-9c03-b4870e9f70e3\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"b2020f0a-e409-4b59-a5a5-ed40cd44d2fb\"\n        },\n        {\n          \"x\": 161,\n          \"y\": 372,\n          \"id\": \"0883a59c-74e1-4acb-b656-bbe5edbd743c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">The best laptops for 2020</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 150,\n          \"height\": 64,\n          \"groupId\": \"b2020f0a-e409-4b59-a5a5-ed40cd44d2fb\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 161,\n          \"y\": 483,\n          \"id\": \"6c6b20af-dfc3-44ea-bfac-eaf95eec4767\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 81, \"g\": 79, \"b\": 77 } },\n          \"type\": \"shape\",\n          \"width\": 201,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"b2020f0a-e409-4b59-a5a5-ed40cd44d2fb\"\n        },\n        {\n          \"x\": 8,\n          \"y\": 506,\n          \"id\": \"95a83083-4629-4970-8457-65da3768d752\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"width\": 145,\n          \"height\": 110,\n          \"scale\": 137,\n          \"focalX\": 57.32296937164805,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-12T13:19:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ultimate-comparison/page14_image3.jpg\",\n            \"width\": 640,\n            \"height\": 480,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"Person Wearing White Silicone Strap Black Smart Watch\",\n            \"sizes\": [],\n            \"isOptimized\": false,\n            \"baseColor\": \"#6b655a\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"10b7fbec-26a1-4d97-ad6e-9a9db8fdcf0c\"\n        },\n        {\n          \"x\": 8,\n          \"y\": 609,\n          \"id\": \"56645d09-0785-47f8-b5da-cee8fa9206e7\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 222, \"g\": 112, \"b\": 50 } },\n          \"type\": \"shape\",\n          \"width\": 145,\n          \"height\": 6,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"10b7fbec-26a1-4d97-ad6e-9a9db8fdcf0c\"\n        },\n        {\n          \"x\": 161,\n          \"y\": 504,\n          \"id\": \"747ed5e6-c012-496e-a9f9-df79c5b5764c\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1834,\n              \"des\": -504,\n              \"tAsc\": 1834,\n              \"tDes\": -504,\n              \"tLGap\": 0,\n              \"wAsc\": 2062,\n              \"wDes\": 545,\n              \"xH\": 956,\n              \"capH\": 1256,\n              \"yMin\": -492,\n              \"yMax\": 1952,\n              \"hAsc\": 1834,\n              \"hDes\": -504,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Digital Trends: smartwatch review</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 168,\n          \"height\": 64,\n          \"groupId\": \"10b7fbec-26a1-4d97-ad6e-9a9db8fdcf0c\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"x\": 161,\n          \"y\": 614,\n          \"id\": \"414ec340-6aa0-47bb-a35a-bb54334d0e91\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 81, \"g\": 79, \"b\": 77 } },\n          \"type\": \"shape\",\n          \"width\": 201,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"10b7fbec-26a1-4d97-ad6e-9a9db8fdcf0c\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"48850b21-5009-40ea-90ae-672722b222e6\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"23510da7-ee9f-4ab8-951f-2315601110c1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"3eab2eb5-90d4-4adf-84cc-8d74e425f1a5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"1facff90-3339-4675-9e70-b55ea9726b53\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"e7aadfb5-3339-4fa1-b0ca-d348f6975b96\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"468147c4-759a-4877-9972-b5eef91d951f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 600\n        },\n        {\n          \"id\": \"1cc0ba94-959d-484e-8bd0-ec323f52209e\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"6c6b20af-dfc3-44ea-bfac-eaf95eec4767\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 1000\n        },\n        {\n          \"id\": \"3e9394a3-de10-440d-83fb-fb0db9a655df\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"95a83083-4629-4970-8457-65da3768d752\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 1200\n        },\n        {\n          \"id\": \"2f3e4f2d-e04c-408c-8ae7-9e1f675ad5a3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"414ec340-6aa0-47bb-a35a-bb54334d0e91\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 1700\n        },\n        {\n          \"id\": \"9643d81c-9d13-4885-b241-7e58b2d82c13\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"cd8af3fa-a10d-4f6b-8036-ef67fd1dbd7d\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"a9304bae-c388-49af-880f-41fbcb9d139a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0883a59c-74e1-4acb-b656-bbe5edbd743c\"],\n          \"duration\": 2000,\n          \"delay\": 900\n        },\n        {\n          \"id\": \"5846c16a-e4d4-4e1b-9d92-af70a2774d67\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"747ed5e6-c012-496e-a9f9-df79c5b5764c\"],\n          \"duration\": 2000,\n          \"delay\": 1500\n        },\n        {\n          \"id\": \"6b4c75c4-e896-4bc3-b897-f9d935ff5a93\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e03163b7-6f7e-44f5-9add-dced0fd59322\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"067a8718-915d-4f39-aebb-4bd93b8e24b1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2b33fe58-e795-41ca-9c03-b4870e9f70e3\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 800\n        },\n        {\n          \"id\": \"24a430cf-dd67-4308-b789-328080dbe823\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"56645d09-0785-47f8-b5da-cee8fa9206e7\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 1400\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 6, \"g\": 6, \"b\": 7 } },\n      \"type\": \"page\",\n      \"id\": \"d3884429-7d9c-4434-b74d-cfcbee66bbf1\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"24ffb333-72ce-4e2b-b126-6cf749257434\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": false\n        },\n        \"10b7fbec-26a1-4d97-ad6e-9a9db8fdcf0c\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"0e9deeb5-de18-4368-a1c2-e67b39b448c1\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"b2020f0a-e409-4b59-a5a5-ed40cd44d2fb\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/vintage-chairs-buying-guide/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/vintage-chairs-buying-guide/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'vintage-chairs-buying-guide',\n  creationDate: '2021-08-09T00:00:00.000Z',\n  title: _x('Vintage Chair Buying Guide', 'template name', 'web-stories'),\n  tags: [\n    _x('Home', 'template keyword', 'web-stories'),\n    _x('Decor', 'template keyword', 'web-stories'),\n    _x('Guide', 'template keyword', 'web-stories'),\n    _x('Modern', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Snowfall White', 'color', 'web-stories'),\n      color: '#f3f2f0',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Metal Green', 'color', 'web-stories'),\n      color: '#313831',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Platinum Blue', 'color', 'web-stories'),\n      color: '#dbe2e7',\n      family: _x('Blue', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Present fresh and innovative ideas about home decor and renovation with this clean and modern-looking template. Create furniture buying guides, stories about interior design, garden inspiration and more.',\n    'web-stories'\n  ),\n  vertical: _x('Home & Garden', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/vintage-chairs-buying-guide/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/vintage-chairs-buying-guide/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7a0b814a-e76a-4ffa-8ab3-ff5712d0423b\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #dbe2e7\\\">Vintage Chairs: What to look for and how to buy</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 74,\n          \"y\": 7,\n          \"width\": 259,\n          \"height\": 103,\n          \"id\": \"10c12b78-df3a-4a93-b387-8ec6d0fe72e9\",\n          \"type\": \"text\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dbe2e7\\\">Billy Rogers</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 15,\n          \"id\": \"2c255ab5-4add-444f-a350-4ab163df674b\",\n          \"x\": 74,\n          \"y\": 142,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:09:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page1_img1.jpg\",\n            \"width\": 1079,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Chair comfort contemporary daylight\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d8d3cc\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": 220,\n          \"width\": 412,\n          \"height\": 455,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0bfeec41-0b6e-4426-81cf-9b2089ab5fb2\",\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 49, \"g\": 56, \"b\": 49 } },\n      \"type\": \"page\",\n      \"id\": \"e9a82cb4-df90-48d7-be12-bf3a9a6a353d\",\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"eafdb137-f761-4943-aa70-1ffa5d6737ae\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n          \"x\": 0,\n          \"y\": 220,\n          \"width\": 412,\n          \"height\": 455,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6f2519e8-97e8-4dcc-b705-c7c1675e68e9\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">The duo behind Brooklyn’s hip antique furniture store, Lichen, clue us in on what to look for when it comes to vintage seating.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 99,\n          \"width\": 304,\n          \"height\": 81,\n          \"id\": \"8b776c23-9126-4446-8a16-0155b6c426a0\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:09:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page2_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 720,\n            \"id\": 0,\n            \"alt\": \"Man in blue crew neck shirt beside man in blue crew neck shirt photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#242c2c\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 50,\n          \"y\": 317,\n          \"width\": 221,\n          \"height\": 289,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fcc934f7-41f0-483a-8996-017b5da170b5\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 178,\n          \"focalX\": 56.497571961428115,\n          \"focalY\": 64.1666139200949,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:09:32\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page2_img2.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Standing lamp near window photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d9e1d5\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 136,\n          \"height\": 236,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f7dc7e79-e2db-43ae-8ee1-901e6953095e\",\n          \"x\": 276,\n          \"y\": 439,\n          \"type\": \"image\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 219, \"g\": 226, \"b\": 231 } },\n      \"type\": \"page\",\n      \"id\": \"e5631fd5-26ed-4243-b7fc-4b155c220dbd\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"b34e4d00-ebc2-4b69-aa94-eab86f0ee682\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 44.44444444444444,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:10:21\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page3_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Blue chair by the beige wall\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#d1c6ba\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 512,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d02da367-47d3-4663-afd3-d5ed52ab31b3\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">If you don’t know what era, what style and who it’s made by, don’t sweat it.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 491,\n          \"width\": 251,\n          \"height\": 61,\n          \"id\": \"8a3c9fcd-d3d8-4d98-b40a-f68947d76d72\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"82ef6115-b75e-4bec-899e-92a7e33c337d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d02da367-47d3-4663-afd3-d5ed52ab31b3\"],\n          \"flyInDir\": \"topToBottom\",\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n      \"type\": \"page\",\n      \"id\": \"64637ae6-949b-49bc-b75d-5107b99e0a2a\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"81664493-6dd0-4100-b46f-804fd73880ac\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 237,\n          \"focalX\": 44.146812754913576,\n          \"focalY\": 61.95025729205147,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:10:46\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page4_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Yellow Chair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#42362b\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 83.5,\n          \"y\": 175,\n          \"width\": 245,\n          \"height\": 396,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"81c30c2c-8fb2-4492-a06a-df660e0edc22\",\n          \"border\": {\n            \"left\": 18,\n            \"right\": 18,\n            \"top\": 18,\n            \"bottom\": 18,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">If you like it,</span>\\n<span style=\\\"color: #313831\\\">You like it.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 146.5,\n          \"y\": 76,\n          \"width\": 119,\n          \"height\": 39,\n          \"id\": \"7c4302c2-8b5c-4eac-8d4f-a33e5f13df5b\",\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 188,\n          \"y\": 7,\n          \"width\": 36,\n          \"height\": 54,\n          \"sticker\": { \"type\": \"vintageChairsIcon01\" },\n          \"id\": \"8b2c5851-3b10-4640-ada6-1f4d7a46ae66\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"91343945-f431-4992-b40b-d2ecff5d7812\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"81c30c2c-8fb2-4492-a06a-df660e0edc22\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 219, \"g\": 226, \"b\": 231 } },\n      \"type\": \"page\",\n      \"id\": \"05a9b66a-1b7b-4b36-b3cb-f7b7067fd30e\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 494,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"8ef7ea3b-6750-457b-b89b-29f4be1bbc93\",\n          \"type\": \"image\",\n          \"scale\": 296,\n          \"focalX\": 18.723606418918923,\n          \"focalY\": 55.12035472972974,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:11:42\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page5_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1620,\n            \"id\": 0,\n            \"alt\": \"Wooden chair and table with vase and flower\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#ddcec5\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 243, \"g\": 242, \"b\": 240, \"a\": 0 }\n          },\n          \"width\": 313,\n          \"height\": 452,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"991b8871-3c99-41bc-94d7-7def3faed1c4\",\n          \"x\": 49.5,\n          \"y\": 0,\n          \"border\": {\n            \"left\": 2,\n            \"right\": 2,\n            \"top\": 2,\n            \"bottom\": 2,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } }\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n          \"x\": 47,\n          \"y\": 452,\n          \"width\": 318,\n          \"height\": 166,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2592965f-4074-427e-a3fe-8c8673882dcb\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">Carefully examine the surface of each chair. Examine every part and look for authenticity marks.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 75,\n          \"y\": 491,\n          \"width\": 256,\n          \"height\": 82,\n          \"id\": \"428c0360-27b3-4d2c-b3d3-e52bba20c9c2\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"51e2bb0c-fad2-4a05-ac09-7b392f8422f1\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"8ef7ea3b-6750-457b-b89b-29f4be1bbc93\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n      \"type\": \"page\",\n      \"id\": \"2b0c1bf8-0acc-4f24-9996-e5c6b47afa40\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"0b4ac6ea-6c4d-44ba-9641-de83ed21ae86\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e69e0a10-3a83-49dc-b32f-502c7f451b26\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:12:57\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page6_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Photo of black chair\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#cac4bc\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 510,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"30d1e12a-80da-4e85-b967-265a557ff634\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">When you find an interesting chair, do you like the curvature? The angles? The lines?</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 60,\n          \"y\": 491,\n          \"width\": 268,\n          \"height\": 61,\n          \"id\": \"8aa2db37-43e6-4d25-b3e6-2dd40994887a\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"8d7538d8-1dee-4e27-9597-f613fc09c943\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"30d1e12a-80da-4e85-b967-265a557ff634\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n      \"type\": \"page\",\n      \"id\": \"62ae21f2-86a5-43bc-b4a1-560e8cfeb4ab\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fde97a56-1328-4b52-b81b-5ca62fc91cb3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">Find an element that draws you in.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 105,\n          \"y\": 76,\n          \"width\": 203,\n          \"height\": 39,\n          \"id\": \"0d21e0db-cc7e-473b-bef2-fd619bcdb628\",\n          \"marginOffset\": 4.675000000000004,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:13:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page7_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Brown wooden framed gray padded chair photo\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#e8e7e6\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 83.5,\n          \"y\": 175,\n          \"width\": 245,\n          \"height\": 396,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"849b30cb-f70e-43a0-92c3-0817cf3264b4\",\n          \"border\": {\n            \"left\": 18,\n            \"right\": 18,\n            \"top\": 18,\n            \"bottom\": 18,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } }\n          },\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 181,\n          \"y\": 4,\n          \"width\": 50,\n          \"height\": 55,\n          \"sticker\": { \"type\": \"vintageChairsIcon02\" },\n          \"id\": \"e10fc08c-b48e-461b-b0cc-20ef1a3d07f7\",\n          \"type\": \"sticker\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5591c74c-c1e4-45b7-8995-b7dc519e1900\",\n          \"type\": \"effect-zoom\",\n          \"scaleDirection\": \"scaleIn\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"849b30cb-f70e-43a0-92c3-0817cf3264b4\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 219, \"g\": 226, \"b\": 231 } },\n      \"type\": \"page\",\n      \"id\": \"0c2f43a3-1099-480b-907f-d40f39daf5dc\",\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": 48,\n          \"y\": 0,\n          \"width\": 330,\n          \"height\": 220,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"1baa4a14-6a42-46c8-905f-437a46cbd5fa\",\n          \"type\": \"image\",\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:13:47\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page8_img1.jpg\",\n            \"width\": 1080,\n            \"height\": 721,\n            \"id\": 0,\n            \"alt\": \"Abstract art background brown\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#c67a4b\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 243, \"g\": 242, \"b\": 240, \"a\": 0 }\n          },\n          \"width\": 313,\n          \"height\": 452,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7a182ed7-b007-4420-9e0a-5d6dfb6a9f18\",\n          \"x\": 49.5,\n          \"y\": 0,\n          \"border\": {\n            \"left\": 2,\n            \"right\": 2,\n            \"top\": 2,\n            \"bottom\": 2,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } }\n          },\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n          \"x\": 47,\n          \"y\": 452,\n          \"width\": 318,\n          \"height\": 166,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"62452434-bf75-47d6-986a-616ce1f4605f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">Check foundational details to make sure it’s sturdy and it hasn’t lost any structural integrity.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 75,\n          \"y\": 491,\n          \"width\": 256,\n          \"height\": 82,\n          \"id\": \"19623e9e-a4c4-4276-8cc8-ba98552c2eed\",\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"f010ebce-b6b1-429f-a8aa-672bbd94b365\",\n          \"type\": \"effect-background-zoom\",\n          \"zoomDirection\": \"scaleOut\",\n          \"duration\": 2000,\n          \"delay\": 0,\n          \"targets\": [\"1baa4a14-6a42-46c8-905f-437a46cbd5fa\"]\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n      \"type\": \"page\",\n      \"id\": \"dd67e19a-af30-4218-b615-a2bc5a74b477\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"4bb61167-dd01-49c8-8df5-874d735d39bd\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"6bd6e063-6549-4e62-9887-35b1774d0be6\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 115,\n          \"focalX\": 47.58454106280193,\n          \"focalY\": 56.60225442834138,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:14:13\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page9_img1.jpg\",\n            \"width\": 720,\n            \"height\": 1080,\n            \"id\": 0,\n            \"alt\": \"Man sitting on a chair and reading a magazine\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#333e2e\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 424,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c2d228af-53fc-4d90-8ef0-61ad983369e3\",\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 21,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">“Try before you buy. See it, smell it, sit on it. And - bargain for it.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 59,\n          \"y\": 405,\n          \"width\": 268,\n          \"height\": 75,\n          \"id\": \"9a2e05c4-db9d-42d9-ba09-4d89d555de11\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">Mark Jackson</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 132,\n          \"height\": 15,\n          \"id\": \"3905f74b-f53d-4b09-9050-52f8f527c5d8\",\n          \"x\": 60,\n          \"y\": 519,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 219, \"g\": 226, \"b\": 231 } },\n      \"type\": \"page\",\n      \"id\": \"7729b890-8486-44b9-a309-182b1cce85c2\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"f0533bc8-23cc-4599-9379-5c9a548da45f\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 21,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #dbe2e7\\\">Read More:</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 268,\n          \"height\": 21,\n          \"id\": \"4d905c2c-ead1-4f2a-a788-6402e78eb8d8\",\n          \"x\": 50,\n          \"y\": 39,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:14:51\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page10_img1.jpg\",\n            \"width\": 665,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Brown, White, and Blue Wooden Board\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#e7ddd5\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 150,\n          \"height\": 228,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"24ef8218-89e0-4842-a881-0c20118cab26\",\n          \"x\": 50,\n          \"y\": 126,\n          \"type\": \"image\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n          \"width\": 163,\n          \"height\": 228,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"89393419-7cf5-47b9-956c-acf46b8827e4\",\n          \"x\": 200,\n          \"y\": 126,\n          \"type\": \"shape\",\n          \"groupId\": \"0b685419-996b-492a-bffd-0986a9c2e438\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">Make it&nbsp;</span>\\n<span style=\\\"color: #313831\\\">Mid-Century</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 95,\n          \"height\": 35,\n          \"id\": \"d808b9e7-ba2d-45d6-8f09-1b7096fb2550\",\n          \"x\": 218,\n          \"y\": 221,\n          \"type\": \"text\",\n          \"groupId\": \"0b685419-996b-492a-bffd-0986a9c2e438\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2021-07-21T08:15:03\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/vintage-chairs-buying-guide/page10_img2.jpg\",\n            \"width\": 320,\n            \"height\": 480,\n            \"id\": 0,\n            \"alt\": \"Green leafed plant on brown pot\",\n            \"sizes\": [],\n            \"isPlaceholder\": false,\n            \"isOptimized\": false,\n            \"isMuted\": false,\n            \"baseColor\": \"#584f46\",\n            \"isExternal\": true\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"width\": 150,\n          \"height\": 228,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9c2eef7b-236d-49ed-9157-23ef20108444\",\n          \"x\": 50,\n          \"y\": 374,\n          \"type\": \"image\",\n          \"groupId\": \"ebcc586b-bc9c-4d87-9c90-4519eef3c210\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 243, \"g\": 242, \"b\": 240 } },\n          \"width\": 163,\n          \"height\": 228,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e5565584-23aa-47ae-83ed-aba693bbd37c\",\n          \"x\": 200,\n          \"y\": 374,\n          \"type\": \"shape\",\n          \"groupId\": \"ebcc586b-bc9c-4d87-9c90-4519eef3c210\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Epilogue\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1580,\n              \"des\": -470,\n              \"tAsc\": 1580,\n              \"tDes\": -470,\n              \"tLGap\": 0,\n              \"wAsc\": 2310,\n              \"wDes\": 520,\n              \"xH\": 1062,\n              \"capH\": 1475,\n              \"yMin\": -467,\n              \"yMax\": 2133,\n              \"hAsc\": 1580,\n              \"hDes\": -470,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"color: #313831\\\">How to</span>\\n<span style=\\\"color: #313831\\\">Re-decorate Your Bathroom on a Budget</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 110,\n          \"height\": 74,\n          \"id\": \"bc62e2f5-543f-4a0b-8a99-aba9f41d1cee\",\n          \"x\": 218,\n          \"y\": 454,\n          \"type\": \"text\",\n          \"groupId\": \"ebcc586b-bc9c-4d87-9c90-4519eef3c210\",\n          \"tagName\": \"h3\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"86c4453b-661f-44b3-9302-2e76c6133f23\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"24ef8218-89e0-4842-a881-0c20118cab26\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d89a20e7-7e72-4546-a4cb-1ef051024450\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"9c2eef7b-236d-49ed-9157-23ef20108444\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 2000,\n          \"delay\": 300\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 49, \"g\": 56, \"b\": 49 } },\n      \"type\": \"page\",\n      \"id\": \"ee9c0096-fa8c-4866-bf3d-ed2f0f046e11\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"0b685419-996b-492a-bffd-0986a9c2e438\": {\n          \"name\": \"Card\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ebcc586b-bc9c-4d87-9c90-4519eef3c210\": {\n          \"name\": \"Card\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ways-to-eat-avocado/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/ways-to-eat-avocado/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'ways-to-eat-avocado',\n  creationDate: '2021-06-28T00:00:00.000Z',\n  title: _x('Ways to Eat Avocado', 'template name', 'web-stories'),\n  tags: [\n    _x('Nutrition', 'template keyword', 'web-stories'),\n    _x('Health', 'template keyword', 'web-stories'),\n    _x('Fitness', 'template keyword', 'web-stories'),\n    _x('Organic', 'template keyword', 'web-stories'),\n    _x('Diet', 'template keyword', 'web-stories'),\n    _x('Green', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Swamp Green', 'color', 'web-stories'),\n      color: '#a7b27e',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Saffron Yellow', 'color', 'web-stories'),\n      color: '#f5b435',\n      family: _x('Yellow', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Moss Green', 'color', 'web-stories'),\n      color: '#51611c',\n      family: _x('Green', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Rose Bud Pink', 'color', 'web-stories'),\n      color: '#ffa797',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Dark Coral', 'color', 'web-stories'),\n      color: '#a35445',\n      family: _x('Red', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'This template is on a diet. With its to-the-point structure and neutral typography, it will let you keep things simple and focus on getting your recipe to your followers.',\n    'web-stories'\n  ),\n  vertical: _x('Health & Wellness', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/ways-to-eat-avocado/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/ways-to-eat-avocado/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c4b728dd-2c80-4a6d-9ef6-21640548709f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.28em; text-transform: uppercase\\\">Recipe Inspiration</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": -2,\n          \"width\": 310,\n          \"height\": 17,\n          \"id\": \"73d87048-2ac9-44c8-b4fa-0a9f004caf7e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -7,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"x\": -58,\n          \"y\": 198,\n          \"width\": 428,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"872240f2-2e0b-48ab-88a4-11acfb93c817\",\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"x\": 34,\n          \"y\": 89,\n          \"id\": \"5b467e75-c0e6-4170-81bc-40da76fd44ba\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 9,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 167, \"g\": 178, \"b\": 126 } },\n          \"type\": \"shape\",\n          \"width\": 520,\n          \"height\": 278,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -20,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 77,\n          \"y\": 64,\n          \"width\": 243,\n          \"height\": 313,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ccd3c484-df39-40c5-b016-420a743613c4\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page01_image02.jpg\",\n            \"width\": 193,\n            \"height\": 249,\n            \"id\": 0,\n            \"alt\": \"page01_image02\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#cbb492\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 109,\n          \"y\": 65,\n          \"width\": 256,\n          \"height\": 330,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7ccd9289-481b-40fb-abd0-9c359b3a66ab\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page01_image01.jpg\",\n            \"width\": 193,\n            \"height\": 248,\n            \"id\": 0,\n            \"alt\": \"page01_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#e5e5d8\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"x\": 165,\n          \"y\": 87,\n          \"id\": \"79fa8adc-0125-42ae-8b51-2778da2be497\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 12,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #51611c; letter-spacing: 0.2em; text-transform: uppercase\\\">Avocado&nbsp;</span>\\n<span style=\\\"font-weight: 900; color: #51611c; letter-spacing: 0.2em; text-transform: uppercase\\\">Shake</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 87,\n          \"height\": 30,\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"x\": 134,\n          \"y\": 78,\n          \"id\": \"74a2ddbf-c69d-42b7-a3c8-d1e8139f1af6\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #51611c; letter-spacing: 0.2em\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 16,\n          \"height\": 56,\n          \"marginOffset\": -8.200000000000003,\n          \"groupId\": \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 51,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Ways to Eat Avocado</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 29,\n          \"y\": 498,\n          \"width\": 269,\n          \"height\": 108,\n          \"id\": \"52d376d6-2fbd-47f8-b2ce-ce7ab854926e\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 81, \"g\": 97, \"b\": 28 } },\n          \"type\": \"shape\",\n          \"x\": 163,\n          \"y\": 119,\n          \"width\": 19,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d82f1093-bc73-465b-913d-061deb133a12\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"8ab426f5-d4a4-4347-94d0-35e946676428\",\n      \"pageTemplateType\": \"cover\",\n      \"groups\": {\n        \"903cc0be-bc9f-4062-b4d0-a6c813745c0f\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"899fac4a-ecd0-4f40-a712-544fc45d29b6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:12:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page02_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page02_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#19161f\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -39.5,\n          \"y\": -244,\n          \"width\": 519,\n          \"height\": 918,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"11b1b62e-e149-4e02-b2ad-ef33e202934b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3b18e3da-2444-4fd6-bdb4-1c383e2bb6e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #a7b27e; letter-spacing: 0.2em; text-transform: uppercase\\\">Health Benefits Of Avocado</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 334,\n          \"width\": 324,\n          \"height\": 20,\n          \"id\": \"d6c5b9d2-ba5b-4225-97b9-e30f2157f3fb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 167, \"g\": 178, \"b\": 126 } },\n          \"type\": \"shape\",\n          \"x\": 48,\n          \"y\": 324,\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a3e96b4c-22fe-492e-a5ba-c27f174dc733\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Avocados are incredibly nutritious. They contain more potassium than bananas, are loaded with heart-healthy monounsaturated fatty acids and fiber.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 48,\n          \"y\": 365,\n          \"width\": 313,\n          \"height\": 235,\n          \"id\": \"b60a1d6f-7acb-4d2e-b011-4bd6d9ebfe7d\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"90bb1c1d-967f-41f6-96f3-a80914693d56\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a3e96b4c-22fe-492e-a5ba-c27f174dc733\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"21c1ef65-6c22-46bf-b1ec-391b0eb6add9\",\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"15c6b46d-16fb-4fc7-8085-1ceb582ec714\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:12:22\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page03_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page03_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#9e8e63\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -63.5,\n          \"y\": -71,\n          \"width\": 544,\n          \"height\": 967,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"a685b3ed-44b8-461f-ab33-aff9151deae3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 60, \"g\": 64, \"b\": 46, \"a\": 0 }, \"position\": 0 },\n              {\n                \"color\": { \"r\": 60, \"g\": 64, \"b\": 46, \"a\": 0.78 },\n                \"position\": 1\n              }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 412,\n          \"height\": 732,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a0215bc0-5675-4da8-b4e9-8b556ffcaf75\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">These are just a few of my favorite ways to eat avocados. Enjoy!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 317,\n          \"height\": 131,\n          \"id\": \"01725e1b-0655-49f5-be24-6d1409f736e6\",\n          \"x\": 47,\n          \"y\": 36,\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 41,\n          \"y\": -23,\n          \"id\": \"716a193d-67a8-433c-a526-15a7dcf567d9\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 77,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f5b435\\\">“</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 28,\n          \"height\": 84,\n          \"marginOffset\": 20.657812500000006\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"53d6eb8e-da9b-478b-9c5b-d478abfe87bb\",\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c1de619e-3807-46c6-91ac-3a0817918276\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page04_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"id\": 0,\n            \"alt\": \"page04_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#322a22\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -53.5,\n          \"y\": -192,\n          \"width\": 551,\n          \"height\": 975,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ba21857e-2b70-4265-9e37-cbea0d60a6fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"type\": \"shape\",\n          \"width\": 427,\n          \"height\": 443,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"596ba5e9-be99-47a2-b177-33dc2850e203\",\n          \"x\": -7.5,\n          \"y\": 241\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #ffa797; letter-spacing: 0.2em\\\">1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 46,\n          \"y\": 322,\n          \"width\": 30,\n          \"height\": 56,\n          \"id\": \"ddd7925a-f13f-4889-9b93-2da70c2cf62e\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 167, \"b\": 151 } },\n          \"type\": \"shape\",\n          \"width\": 19,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"47b2389e-8ea7-4217-bed3-e56a7f95bdfb\",\n          \"x\": 47,\n          \"y\": 368\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #ffa797; letter-spacing: 0.2em; text-transform: uppercase\\\">Avocado Shake</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 20,\n          \"id\": \"ef95490a-990d-4d7b-93b0-c271509d0bf4\",\n          \"x\": 46,\n          \"y\": 378,\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Don’t knock it till you’ve tried it! Avocado shakes are super creamy and good for you.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 330,\n          \"height\": 139,\n          \"id\": \"3a5c98ea-0411-461e-b3aa-b728a28d6502\",\n          \"x\": 48,\n          \"y\": 415,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"889e5fea-9fa3-4e9d-a0e4-67b4a3123d2a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"ddd7925a-f13f-4889-9b93-2da70c2cf62e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"4f684d55-2b8e-460d-a871-a4241955e2d7\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"47b2389e-8ea7-4217-bed3-e56a7f95bdfb\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 50\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"2103e5d5-a865-46a5-9533-e52d10bad635\",\n      \"pageTemplateType\": \"section\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c3efe6cc-0bc9-4d45-b0a6-0dd532c9fb50\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"x\": -51,\n          \"y\": 83,\n          \"width\": 426,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"850278ac-d800-4d6b-8235-e4d2a93784aa\",\n          \"groupId\": \"885d5a17-8172-4fb5-a6ca-cafbbe421bac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:12:36\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page05_image01.jpg\",\n            \"width\": 289,\n            \"height\": 360,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page05_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#736d66\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -40,\n          \"y\": -76,\n          \"width\": 467,\n          \"height\": 382,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1405b095-d009-473f-bbb9-934588a308bd\",\n          \"groupId\": \"885d5a17-8172-4fb5-a6ca-cafbbe421bac\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #a35445; letter-spacing: 0.1em; text-transform: uppercase\\\">Prep Time: 5 Min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"id\": \"7c1234e4-cae8-496a-b06d-5ac814ccc944\",\n          \"x\": 48,\n          \"y\": 361,\n          \"marginOffset\": 1.330078125\n        },\n        {\n          \"x\": 222,\n          \"y\": 361,\n          \"id\": \"87e6323b-88ba-41ec-8cbb-17f437cf55bc\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #a35445; letter-spacing: 0.1em; text-transform: uppercase\\\">Cook Time: 3 Min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 143,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 163, \"g\": 84, \"b\": 69 } },\n          \"type\": \"shape\",\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"16f2ce92-905b-44ad-8b66-d076947a9d30\",\n          \"x\": 48,\n          \"y\": 424\n        },\n        {\n          \"x\": 48,\n          \"y\": 434,\n          \"id\": \"06e6c09d-718a-4168-b1f9-85646b6430e1\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">1 cup ice cubes</span>\\n<span style=\\\"font-weight: 300\\\">1 ripe avocado cubed</span>\\n<span style=\\\"font-weight: 300\\\">1/2 cup milk</span>\\n<span style=\\\"font-weight: 300\\\">1/2 cup condensed milk</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 110,\n          \"id\": \"ebc0d53d-87a8-43b1-9c33-aac61b7ff6ae\",\n          \"x\": 48,\n          \"y\": 466,\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"74e5227b-7284-4a26-b8f0-7fff38ff9847\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"16f2ce92-905b-44ad-8b66-d076947a9d30\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"45ed4a43-210e-46b1-bfde-e86c58e981cd\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"7c1234e4-cae8-496a-b06d-5ac814ccc944\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"44e0fd61-46c2-4714-9c8c-03ce097ebdd1\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"87e6323b-88ba-41ec-8cbb-17f437cf55bc\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"9639c764-6d23-4ad6-a950-a9ac51fae9f5\",\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"885d5a17-8172-4fb5-a6ca-cafbbe421bac\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7e445ebc-0fbe-4b62-87ae-774bff1103d6\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:10:38\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page06_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page06_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#cdceca\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -48,\n          \"y\": -149,\n          \"width\": 508,\n          \"height\": 904,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"ceb184da-b879-426e-864e-6d2f0a44973b\",\n          \"groupId\": \"a0ef7a20-ba91-463e-98f5-bbd8689a0b63\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 528,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"31cddfb2-12ff-47ec-b4b5-0eaca2bdd62e\",\n          \"x\": -8.5,\n          \"y\": 152,\n          \"type\": \"shape\",\n          \"groupId\": \"a0ef7a20-ba91-463e-98f5-bbd8689a0b63\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 64,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d96215da-a722-48ef-ac79-578fc9c27eba\",\n          \"x\": 69,\n          \"y\": 368,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Add ice cubes, avocado cubes, milk and condensed milk to the blender. Blend till creamy. Approximately 3 min.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 297,\n          \"height\": 175,\n          \"id\": \"e5a13822-3d08-494e-a824-f7d9bbd9ba16\",\n          \"x\": 65,\n          \"y\": 415,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.28em; text-transform: uppercase\\\">Step 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"id\": \"b7ef7277-a652-45b8-ba12-59b4d4f2d5cd\",\n          \"x\": 69,\n          \"y\": 378\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"47231fe1-3e99-4fea-880b-25a57bd61bb9\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"d96215da-a722-48ef-ac79-578fc9c27eba\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"ac80c678-e24e-4fb6-9f1e-b4c19bcbf32b\",\n      \"pageTemplateType\": \"steps\",\n      \"groups\": {\n        \"a0ef7a20-ba91-463e-98f5-bbd8689a0b63\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"2cb0844c-96c9-45b1-bbc4-61c37f325f84\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:11:19\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page07_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page07_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#e7e6da\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -55.5,\n          \"y\": -60,\n          \"width\": 523,\n          \"height\": 929,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"c2faa68c-7d0c-4ab1-a94c-7a636c55450e\",\n          \"groupId\": \"cceb5cbc-899a-408f-9a71-83a070b25447\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 528,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fb561763-b0e8-4d63-808d-63732454d247\",\n          \"x\": -8.5,\n          \"y\": 152,\n          \"type\": \"shape\",\n          \"groupId\": \"cceb5cbc-899a-408f-9a71-83a070b25447\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Top with fruits or nuts. I like to add a tiny bit of lemon drizzle and crushed nuts. Enjoy!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 297,\n          \"height\": 139,\n          \"id\": \"4c1b176a-c242-49a8-88f7-5fd5a90c693e\",\n          \"x\": 65,\n          \"y\": 415,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.28em; text-transform: uppercase\\\">Step 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"id\": \"2c20187f-4673-487f-86cb-cd1dff713101\",\n          \"x\": 70,\n          \"y\": 378,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 64,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"03c192c4-1287-4265-b8ab-f5e4beeb8eb0\",\n          \"x\": 69,\n          \"y\": 368\n        }\n      ],\n      \"animations\": [\n        {\n          \"targets\": [\"03c192c4-1287-4265-b8ab-f5e4beeb8eb0\"],\n          \"id\": \"f40a242c-1dc4-4d3f-81ef-8d3a7e4e7ffc\",\n          \"type\": \"effect-fly-in\",\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"bc3e5021-fa2b-49d0-9ac4-3d714a81f86a\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"cceb5cbc-899a-408f-9a71-83a070b25447\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"e33c8a99-40d9-43b4-ad23-4074a3207984\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:11:40\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page08_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page08_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#989e3e\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -25,\n          \"y\": -183,\n          \"width\": 493,\n          \"height\": 875,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"58221ed8-7697-4f63-9e98-73779bd533ff\",\n          \"groupId\": \"351dce1c-79a1-44a5-889b-afbc1891fd7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 528,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"51a110c3-a040-400b-98e5-31f37c710458\",\n          \"x\": -7.5,\n          \"y\": 158,\n          \"type\": \"shape\",\n          \"groupId\": \"351dce1c-79a1-44a5-889b-afbc1891fd7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 40,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.2em\\\">2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"x\": 47,\n          \"y\": 322,\n          \"width\": 30,\n          \"height\": 55,\n          \"id\": \"2e583876-f776-4fbd-aa3e-2609f8c0a483\",\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 23,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"81717bc4-8e8e-4716-a1d0-fa604faf9107\",\n          \"x\": 47,\n          \"y\": 368,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 900; color: #f5b435; letter-spacing: 0.2em; text-transform: uppercase\\\">Avocado Toast</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 178,\n          \"height\": 20,\n          \"id\": \"f27a9b3f-fc16-4c0b-9bc9-6e9a370d77b2\",\n          \"x\": 47,\n          \"y\": 378,\n          \"type\": \"text\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">What’s not to love! It’s super easy to make, it’s healthy and satisfying!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 330,\n          \"height\": 103,\n          \"id\": \"cd93b09e-d187-4368-9229-85a7a088252b\",\n          \"x\": 48,\n          \"y\": 415,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"6307fd31-3583-4480-b74b-78994ff700a5\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2e583876-f776-4fbd-aa3e-2609f8c0a483\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1600,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"99db9086-205e-4acf-9b30-117f3ca58095\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"81717bc4-8e8e-4716-a1d0-fa604faf9107\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"1e3c4674-fd94-4232-83d4-eb8ea67236f7\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"351dce1c-79a1-44a5-889b-afbc1891fd7c\": {\n          \"name\": \"Background\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"11da1190-6665-4f7f-b656-2f210a28b1d7\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"x\": -51,\n          \"y\": 83,\n          \"width\": 426,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8fb2c41b-778a-4582-86ba-23430c48b71a\",\n          \"type\": \"shape\",\n          \"groupId\": \"a9515cd8-8212-4b5c-bd1b-37af3728ce70\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:12:17\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page09_image01.jpg\",\n            \"width\": 330,\n            \"height\": 274,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page09_image01\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#c5ab8c\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"x\": 0,\n          \"y\": -74,\n          \"width\": 429,\n          \"height\": 382,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"60040bd1-f869-4f2d-84cb-23c4c5be5993\",\n          \"type\": \"image\",\n          \"groupId\": \"a9515cd8-8212-4b5c-bd1b-37af3728ce70\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 500; color: #a35445; letter-spacing: 0.1em; text-transform: uppercase\\\">Prep Time: 2min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"id\": \"c3a97ff3-ac68-4ff8-9094-a256731c13a9\",\n          \"x\": 48,\n          \"y\": 361,\n          \"marginOffset\": 1.330078125,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 222,\n          \"y\": 361,\n          \"id\": \"8e380a36-fe02-497f-83ab-55a8c6f2cd6f\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #a35445; letter-spacing: 0.1em; text-transform: uppercase\\\">Cook Time: 2min</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 141,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"type\": \"text\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 163, \"g\": 84, \"b\": 69 } },\n          \"width\": 56,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a3cbea2c-bdc6-4e6f-8251-b5111ea6db05\",\n          \"x\": 48,\n          \"y\": 424,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"x\": 48,\n          \"y\": 434,\n          \"id\": \"75a5e7da-4094-45ca-83d4-4c14b2fa59f4\",\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.28em; text-transform: uppercase\\\">Ingredients</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"type\": \"text\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 300\\\">1 ripe avocado</span>\\n<span style=\\\"font-weight: 300\\\">Lemon, for squeezing</span>\\n<span style=\\\"font-weight: 300\\\">Sea salt</span>\\n<span style=\\\"font-weight: 300\\\">2 to 4 slices toasted bread</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 313,\n          \"height\": 109,\n          \"id\": \"065b33dd-4d57-410e-9e1f-64369383d7bc\",\n          \"x\": 48,\n          \"y\": 466,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ddec8b6e-17f6-44c1-8d20-872ead5b1277\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"c3a97ff3-ac68-4ff8-9094-a256731c13a9\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"0b52dc6c-7f97-49c9-b2d4-9df32b5f9c46\",\n          \"type\": \"effect-pulse\",\n          \"targets\": [\"8e380a36-fe02-497f-83ab-55a8c6f2cd6f\"],\n          \"scale\": 0.05,\n          \"iterations\": 1,\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"76d4bdeb-8628-4506-a7f0-b70abf9e2f55\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"a3cbea2c-bdc6-4e6f-8251-b5111ea6db05\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 200\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"7b0a862a-2483-4df0-bc1d-39d5915dc3c3\",\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"a9515cd8-8212-4b5c-bd1b-37af3728ce70\": {\n          \"name\": \"Image\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"fb96f769-4e1f-4cdb-8cc3-a2ff4795b4f3\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:10:25\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page10_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page10_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#c49e6a\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": -101,\n          \"y\": -236,\n          \"width\": 513,\n          \"height\": 908,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"d8649c4d-3ba3-4d64-9b7c-b3a985008133\",\n          \"groupId\": \"2c997a34-be0b-4812-9e84-230b67dc2e6f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 528,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"462a2944-152e-4057-82e8-ea6ee9cc483f\",\n          \"x\": -8.5,\n          \"y\": 152,\n          \"type\": \"shape\",\n          \"groupId\": \"2c997a34-be0b-4812-9e84-230b67dc2e6f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 64,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"87da2470-dda0-4bcb-ad4b-f5652666153b\",\n          \"x\": 69,\n          \"y\": 306,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">Halve the avocado vertically and remove the pit. Dice the avocado flesh while it's still inside the skin. Squeeze lemon juice and sprinkle it with sea salt.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 291,\n          \"height\": 235,\n          \"id\": \"6a104b8c-3475-4049-9ec4-c248eecc399a\",\n          \"x\": 65,\n          \"y\": 346,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.28em; text-transform: uppercase\\\">Step 1</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"id\": \"4a00826f-b43a-4279-aae0-832dccefdb70\",\n          \"x\": 69,\n          \"y\": 316,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"11440cb1-31d3-470a-9bea-4c193fd71a9d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"87da2470-dda0-4bcb-ad4b-f5652666153b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"69293770-23c7-4ab1-8afb-601fc46f8d05\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"fb96f769-4e1f-4cdb-8cc3-a2ff4795b4f3\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"2c997a34-be0b-4812-9e84-230b67dc2e6f\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"x\": -236,\n          \"y\": -85,\n          \"width\": 648,\n          \"height\": 1150,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"id\": \"e54ec2f3-5fe3-4930-a2ee-3b948a054ced\",\n          \"type\": \"image\",\n          \"scale\": 144,\n          \"focalX\": 62.66196188071188,\n          \"focalY\": 38.99429563492063,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:11:52\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page11_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page11_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#ccd0cf\",\n            \"isExternal\": true,\n            \"sizes\": []\n          }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": true, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 528,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4b861e06-ffe3-4ae5-872c-31142504a0e0\",\n          \"x\": -14.5,\n          \"y\": -81,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 64,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b82f6153-3829-4efa-b03a-7c83883d9f42\",\n          \"x\": 69,\n          \"y\": 55,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Scoop the diced avocado flesh out of the skin and onto the toasted bread. Mash the avocado with the back of a fork.&nbsp;</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 295,\n          \"height\": 175,\n          \"id\": \"202aae74-f4a4-419c-ae28-6ac5e9271af3\",\n          \"x\": 65,\n          \"y\": 95,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.28em; text-transform: uppercase\\\">Step 2</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 17,\n          \"marginOffset\": 1.330078125,\n          \"id\": \"b747f125-c17a-4180-a47a-342787a06973\",\n          \"x\": 69,\n          \"y\": 65,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"ff47c5d9-db58-4d77-a9f0-abc7c4680978\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b82f6153-3829-4efa-b03a-7c83883d9f42\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"64504e99-b47f-4bf0-b62f-b8d620a6acba\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"60dfdbfb-d4dc-4665-bdfc-c66d33bb4cd5\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": \"steps\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"8333de3f-cbc3-48cd-86cf-04b5313ac7d0\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"creationDate\": \"2021-05-11T08:10:05\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page12_bg.jpg\",\n            \"width\": 330,\n            \"height\": 586,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page12_bg\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#dcd9cd\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"type\": \"image\",\n          \"x\": 0,\n          \"y\": -72.5,\n          \"width\": 444,\n          \"height\": 745,\n          \"mask\": {\n            \"type\": \"rectangle\",\n            \"showInLibrary\": true,\n            \"name\": \"Rectangle\",\n            \"path\": \"M 0,0 1,0 1,1 0,1 0,0 Z\",\n            \"ratio\": 1,\n            \"supportsBorder\": true\n          },\n          \"id\": \"1349d311-ed5c-48ec-8f91-bdec7d5e879f\",\n          \"groupId\": \"08dd757a-5b6b-4346-bfd5-ec263dcc40a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"type\": \"linear\",\n            \"stops\": [\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.9 }, \"position\": 0 },\n              { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 }, \"position\": 1 }\n            ],\n            \"rotation\": 0.5\n          },\n          \"width\": 427,\n          \"height\": 480,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9fab792c-71aa-4fa8-8b55-fc9a9d1c7afc\",\n          \"x\": -7.5,\n          \"y\": 200,\n          \"type\": \"shape\",\n          \"groupId\": \"08dd757a-5b6b-4346-bfd5-ec263dcc40a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"width\": 64,\n          \"height\": 2,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"327f1fa6-cafd-4d7a-bf2d-31b39653371b\",\n          \"x\": 69,\n          \"y\": 438,\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 28,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 400; color: #fff\\\">Top with your desired toppings. I like adding something with a crunch!</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 306,\n          \"height\": 103,\n          \"id\": \"68cd1a10-3464-47c8-8133-97c0a879fb0a\",\n          \"x\": 65,\n          \"y\": 478,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"hasHiddenPadding\": false },\n          \"content\": \"<span style=\\\"font-weight: 800; color: #f5b435; letter-spacing: 0.28em; text-transform: uppercase\\\">Step 3</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 139,\n          \"height\": 16,\n          \"marginOffset\": 1.330078125,\n          \"id\": \"9c6b4d79-e41f-4d3b-8294-aa1955a13830\",\n          \"x\": 69,\n          \"y\": 448,\n          \"type\": \"text\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"54713841-1b20-418c-bb25-8096ce85618b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"327f1fa6-cafd-4d7a-bf2d-31b39653371b\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 1600,\n          \"delay\": 0\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 242, \"g\": 242, \"b\": 242 } },\n      \"type\": \"page\",\n      \"id\": \"ccf853fc-f266-476c-b10c-70d541e81a67\",\n      \"defaultBackgroundElement\": {\n        \"opacity\": 100,\n        \"flip\": { \"vertical\": false, \"horizontal\": false },\n        \"rotationAngle\": 0,\n        \"lockAspectRatio\": true,\n        \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n        \"x\": 1,\n        \"y\": 1,\n        \"width\": 1,\n        \"height\": 1,\n        \"mask\": { \"type\": \"rectangle\" },\n        \"isBackground\": true,\n        \"isDefaultBackground\": true,\n        \"id\": \"8333de3f-cbc3-48cd-86cf-04b5313ac7d0\",\n        \"type\": \"shape\"\n      },\n      \"pageTemplateType\": null,\n      \"groups\": {\n        \"08dd757a-5b6b-4346-bfd5-ec263dcc40a5\": {\n          \"name\": \"Background\",\n          \"isLocked\": true,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"id\": \"7ee691b8-dfa5-46bf-a4cb-b58ded0fd692\",\n          \"type\": \"shape\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 133, \"g\": 144, \"b\": 96, \"a\": 1 }\n          },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": -58,\n          \"width\": 412,\n          \"height\": 736,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ee2c9bf8-fbed-4e25-a1e7-c6c17253f2ec\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"color: #fff\\\">I’ve spent the last decade teaching my followers how to prepare delicious, nutritious recipes. </span><span style=\\\"font-weight: 800; color: #fff\\\">Healthy</span><span style=\\\"font-weight: 800; color: #fff\\\"> cooking</span><span style=\\\"color: #fff\\\"> doesn't always mean using low-fat products.</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 339,\n          \"height\": 340,\n          \"id\": \"fe5275da-58d0-42e7-9d2a-680d6badff66\",\n          \"x\": 48,\n          \"y\": 52,\n          \"type\": \"text\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 8,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 245, \"g\": 180, \"b\": 53 } },\n          \"type\": \"shape\",\n          \"x\": 54,\n          \"y\": 491,\n          \"width\": 428,\n          \"height\": 237,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e14d4519-63df-4f69-af11-d6484c3b1de0\",\n          \"groupId\": \"9333e446-d197-41ba-9a1e-84c91b2ef042\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 523,\n          \"width\": 412,\n          \"height\": 152,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fe43a795-fce8-488f-8e5e-f6a492014e5d\",\n          \"groupId\": \"9333e446-d197-41ba-9a1e-84c91b2ef042\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"type\": \"image\",\n          \"x\": 146,\n          \"y\": 435,\n          \"width\": 120,\n          \"height\": 120,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dda23273-4a95-4473-a0bc-57f063aa1637\",\n          \"borderRadius\": {\n            \"topLeft\": 1000,\n            \"topRight\": 1000,\n            \"bottomRight\": 1000,\n            \"bottomLeft\": 1000,\n            \"locked\": true\n          },\n          \"border\": {\n            \"left\": 3,\n            \"right\": 3,\n            \"top\": 3,\n            \"bottom\": 3,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } }\n          },\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/png\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/ways-to-eat-avocado/page13_image01.jpg\",\n            \"width\": 241,\n            \"height\": 240,\n            \"id\": 0,\n            \"alt\": \"page13_image1\",\n            \"isOptimized\": false,\n            \"baseColor\": \"#a97756\",\n            \"isExternal\": true,\n            \"sizes\": []\n          },\n          \"groupId\": \"9333e446-d197-41ba-9a1e-84c91b2ef042\"\n        },\n        {\n          \"x\": 128,\n          \"y\": 583,\n          \"id\": \"883e22e0-2b36-404c-99b8-288e968af548\",\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"content\": \"<span style=\\\"font-weight: 500; letter-spacing: 0.14em\\\">Visit Em’s Kitchen</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 339,\n          \"height\": 18,\n          \"type\": \"text\",\n          \"link\": { \"url\": \"https://google.com\", \"icon\": null, \"desc\": null },\n          \"groupId\": \"9333e446-d197-41ba-9a1e-84c91b2ef042\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Crimson Pro\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 918,\n              \"des\": -220,\n              \"tAsc\": 918,\n              \"tDes\": -220,\n              \"tLGap\": 0,\n              \"wAsc\": 1006,\n              \"wDes\": 295,\n              \"xH\": 430,\n              \"capH\": 587,\n              \"yMin\": -286,\n              \"yMax\": 984,\n              \"hAsc\": 918,\n              \"hDes\": -220,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 77,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f5b435\\\">“</span>\",\n          \"borderRadius\": {\n            \"locked\": true,\n            \"topLeft\": 2,\n            \"topRight\": 2,\n            \"bottomRight\": 2,\n            \"bottomLeft\": 2\n          },\n          \"width\": 28,\n          \"height\": 84,\n          \"marginOffset\": 20.657812500000006,\n          \"id\": \"59664198-2ecc-4a4e-80e5-cce50742d894\",\n          \"x\": 41,\n          \"y\": -23\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 65, \"g\": 120, \"b\": 118 } },\n      \"type\": \"page\",\n      \"id\": \"577871d9-a09e-405d-a1ad-2e5049a26ddc\",\n      \"pageTemplateType\": \"quote\",\n      \"groups\": {\n        \"9333e446-d197-41ba-9a1e-84c91b2ef042\": {\n          \"name\": \"Footer\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/raw/weekly-entertainment/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { RawTemplate } from '../../types';\nimport { default as template } from './template';\nimport { default as metaData } from './metaData';\n\nexport default {\n  ...metaData,\n  ...template,\n} as RawTemplate;\n"
  },
  {
    "path": "packages/templates/src/raw/weekly-entertainment/metaData.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, _x } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport type { MetaData } from '../../types';\n\nexport default {\n  slug: 'weekly-entertainment',\n  creationDate: '2021-05-29T00:00:00.000Z',\n  title: _x('Weekly Entertainment', 'template name', 'web-stories'),\n  tags: [\n    _x('Funny', 'template keyword', 'web-stories'),\n    _x('Action', 'template keyword', 'web-stories'),\n    _x('Hip', 'template keyword', 'web-stories'),\n  ],\n  colors: [\n    {\n      label: _x('Black', 'color', 'web-stories'),\n      color: '#000',\n      family: _x('Black', 'color', 'web-stories'),\n    },\n    {\n      label: _x('White', 'color', 'web-stories'),\n      color: '#fff',\n      family: _x('White', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Pink', 'color', 'web-stories'),\n      color: '#ff00d6',\n      family: _x('Pink', 'color', 'web-stories'),\n    },\n    {\n      label: _x('Gray', 'color', 'web-stories'),\n      color: '#525252',\n      family: _x('Gray', 'color', 'web-stories'),\n    },\n  ],\n  description: __(\n    'Cover the world of entertainment with this template that comes with an edgy, interesting look. Works well as foundation for celebrity, movie, TV and music coverage, insights and inspiration.',\n    'web-stories'\n  ),\n  vertical: _x('Entertainment', 'template vertical', 'web-stories'),\n} as MetaData;\n"
  },
  {
    "path": "packages/templates/src/raw/weekly-entertainment/template.d.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TemplateData } from '../../types';\n\ndeclare module 'template.json' {\n  const templateStory: TemplateData;\n  export default templateStory;\n}\n"
  },
  {
    "path": "packages/templates/src/raw/weekly-entertainment/template.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"17bad711-de31-4f09-8d30-f83ade1d6f2a\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 52,\n          \"y\": 27,\n          \"width\": 360,\n          \"height\": 648,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 270,\n          \"focalX\": 41.91473010440877,\n          \"focalY\": 20.55378631524039,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"ce3de6dc-492d-47ab-aa0b-aa86cf1363cd\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page1_bg.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page1_bg\",\n            \"sizes\": [],\n            \"baseColor\": \"#311901\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 85,\n          \"y\": 0,\n          \"width\": 273,\n          \"height\": 47,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"c7a5dbe5-43f8-4510-8741-7e3900e3d487\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Weekly</span>\",\n          \"fontSize\": 68,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": -269,\n          \"y\": 304,\n          \"width\": 586,\n          \"height\": 54,\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"3970117d-3e7f-4eb0-94c6-a90873ba11c5\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Entertainment</span></span>\",\n          \"fontSize\": 68,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 94,\n          \"y\": 260,\n          \"width\": 586,\n          \"height\": 54,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"d3c1350e-1e2f-4f43-ae55-7fac7fd59932\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Entertainment</span></span>\",\n          \"fontSize\": 68,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h1\"\n        },\n        {\n          \"x\": 51,\n          \"y\": 572,\n          \"width\": 273,\n          \"height\": 47,\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 180,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"0b0ba715-00b7-4b12-8c51-2fa4035bca6b\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Weekly</span></span>\",\n          \"fontSize\": 68,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 92,\n          \"y\": 374,\n          \"width\": 154,\n          \"height\": 150,\n          \"sticker\": { \"type\": \"entertainmentMusicNote\" },\n          \"id\": \"075de066-f066-4076-bb4b-f96816afb6d2\"\n        }\n      ],\n      \"animations\": [],\n      \"type\": \"page\",\n      \"id\": \"04df622c-0d7f-4760-a06c-e88d9d9ac435\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"cover\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7a27a752-537d-4dcd-9677-5926437c0e19\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 55,\n          \"y\": 16,\n          \"width\": 209,\n          \"height\": 34,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"74ea4aa6-1165-42cf-9849-90ab25e6b76e\",\n          \"content\": \"<span style=\\\"color: #fff\\\">New Artists</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 55,\n          \"y\": 70,\n          \"width\": 357,\n          \"height\": 606,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 41.49743929933975,\n          \"focalY\": 54.586814873401416,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"816de043-a84a-43af-af61-9a4d00a04e9b\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page2_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page2_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#4f4e3f\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": -20,\n          \"y\": 535,\n          \"width\": 452,\n          \"height\": 64,\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"26df8c19-b913-441a-bff1-bf1b677cb159\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">The Top 10</span>\",\n          \"fontSize\": 81,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"00fb5f95-5464-40af-a3a5-d59c615c36e9\"\n        },\n        {\n          \"x\": -20,\n          \"y\": 503,\n          \"width\": 452,\n          \"height\": 65,\n          \"opacity\": 30,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"5bfb51c9-3d47-4a78-be2c-776db5143bc9\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">The Top 10</span>\",\n          \"fontSize\": 81,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"00fb5f95-5464-40af-a3a5-d59c615c36e9\"\n        },\n        {\n          \"x\": -20,\n          \"y\": 470,\n          \"width\": 452,\n          \"height\": 65,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"5efefa69-c1d0-4331-905b-3936d866f0eb\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">The Top 10</span>\",\n          \"fontSize\": 81,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"00fb5f95-5464-40af-a3a5-d59c615c36e9\",\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"2eb4d2d7-a0d9-436a-92b7-aec84408ee6b\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5efefa69-c1d0-4331-905b-3936d866f0eb\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"198fef51-d45a-408a-8152-44001820366a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"5bfb51c9-3d47-4a78-be2c-776db5143bc9\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"5d93159b-7873-4191-a396-6997f8301760\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"26df8c19-b913-441a-bff1-bf1b677cb159\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"21c3e6ee-e034-43f2-8941-9f288a65aab6\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"816de043-a84a-43af-af61-9a4d00a04e9b\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"9670b092-e11b-433e-aa8a-659e4ee982c9\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"section\",\n      \"groups\": {\n        \"00fb5f95-5464-40af-a3a5-d59c615c36e9\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"03d49bf5-7b5e-4d7c-b09e-7c3ebde20c94\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": -32,\n          \"y\": 272,\n          \"width\": 937,\n          \"height\": 257,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.7,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"741cf9c1-5c4e-400a-88d1-f8d85988d103\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: rgba(78,20,80,0.5); text-transform: uppercase\\\">Pink</span>\",\n          \"fontSize\": 367,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 1,\n          \"y\": 43,\n          \"width\": 81,\n          \"height\": 202,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"a8a8df4d-5750-4508-9698-69226f88a94f\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">“</span>\",\n          \"fontSize\": 202,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 45,\n          \"y\": 160,\n          \"width\": 335,\n          \"height\": 318,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.83,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"37fa4bdd-2898-4b95-bf2a-ae0d4e474f47\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ff00d6; text-transform: uppercase\\\">Pink</span>\\n<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">is not</span>\\n<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">just a</span>\\n<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">color,</span>\\n<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">it's an</span>\\n<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">attitude!</span>\",\n          \"fontSize\": 64,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 251,\n          \"y\": 555,\n          \"width\": 100,\n          \"height\": 26,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"right\",\n          \"type\": \"text\",\n          \"id\": \"8bef4ffe-0a36-4444-ac4c-48b548217cb9\",\n          \"content\": \"<span style=\\\"color: #fff\\\">– Artist</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"89717445-e01f-44aa-b06b-5574bbb57b59\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"741cf9c1-5c4e-400a-88d1-f8d85988d103\"],\n          \"flyInDir\": \"rightToLeft\",\n          \"duration\": 600,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"a06ec228-0ba9-4ce0-b5c5-afa4ebaf60a1\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"37fa4bdd-2898-4b95-bf2a-ae0d4e474f47\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 1000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"73e07f65-ae5a-4a85-8802-7ea5cfaa45b2\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"quote\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"87fe44ec-dfa5-450c-8250-1859f8e4fe07\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 48,\n          \"y\": -57,\n          \"width\": 364,\n          \"height\": 425,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": true },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50.193135557679454,\n          \"focalY\": 58.677063671635366,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"7f6f6565-2e46-4ef5-964c-d6c44350416d\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page4_image1.jpg\",\n            \"width\": 220,\n            \"height\": 329,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page4_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#725a5d\",\n            \"isExternal\": true\n          }\n        },\n        {\n          \"x\": 77,\n          \"y\": 341,\n          \"width\": 595,\n          \"height\": 80,\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.75,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"2ed3fa60-d97a-4641-b858-a024163090aa\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Spotlight</span>\",\n          \"fontSize\": 108,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 49,\n          \"y\": 408,\n          \"width\": 272,\n          \"height\": 70,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"e23cd5e4-d0c9-436d-a1b1-b91dcf909373\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Toronto-based singer D7</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 50,\n          \"y\": 493,\n          \"width\": 343,\n          \"height\": 84,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.43,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"fc016a73-3d6f-43a3-8542-6de6651a2829\",\n          \"content\": \"<span style=\\\"color: #fff\\\">D7 first gained media attention in 2020 when a video of her singing \\\"Nowhere to Go\\\" was shared over a million times. Her deput album was well received.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": -149,\n          \"y\": 150,\n          \"width\": 352,\n          \"height\": 53,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": -90,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.83,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"17fff8ec-3742-4837-bbcb-6f547744c46a\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Spotlight</span></span>\",\n          \"fontSize\": 64,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"tagName\": \"h2\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5c64625a-ff69-407b-8e56-1b6b0168d209\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"17fff8ec-3742-4837-bbcb-6f547744c46a\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 3500,\n          \"delay\": 50\n        },\n        {\n          \"id\": \"aeb98b0a-9d15-4d38-9964-f0a9da66998a\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"e23cd5e4-d0c9-436d-a1b1-b91dcf909373\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"96d581df-2dc7-4a93-94eb-af857f071088\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"fc016a73-3d6f-43a3-8542-6de6651a2829\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"8fd85b65-56bc-4b67-9a77-318d7ecc7780\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"7f6f6565-2e46-4ef5-964c-d6c44350416d\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"582c5a25-6f17-4107-8e60-6ae4721c932f\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"923c69d0-84f6-4223-8f7e-8fd7f0d0363f\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 0,\n          \"y\": -57,\n          \"width\": 30,\n          \"height\": 286,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 214 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"07ca71a9-b60e-4373-8ee1-65be94c152f0\"\n        },\n        {\n          \"x\": 19,\n          \"y\": -57,\n          \"width\": 392,\n          \"height\": 372,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-15T20:53:50\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page5_image1.jpg\",\n            \"width\": 330,\n            \"height\": 199,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page5_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#384d64\",\n            \"isExternal\": true\n          },\n          \"id\": \"46058255-8bf6-4302-88eb-f9bd71304225\"\n        },\n        {\n          \"x\": 37,\n          \"y\": 346,\n          \"width\": 272,\n          \"height\": 70,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"fd434caf-7752-47d3-b41b-0a1048f116a8\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\">New Album Review</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 37,\n          \"y\": 433,\n          \"width\": 332,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.43,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ff9a77cf-c942-4a04-84ea-d7134d97f360\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Trevor and Inband explores electronic sounds with haunting vocals.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 264,\n          \"y\": 564,\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 82, \"g\": 82, \"b\": 82 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"76c34633-deca-4d3b-ad89-9f8f787aabf3\",\n          \"groupId\": \"c8d3e119-de8d-4b40-bf9a-18d5ba0f91d4\"\n        },\n        {\n          \"x\": 254,\n          \"y\": 553,\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"837db927-1ee6-4419-ace6-c59f83f0ca49\",\n          \"groupId\": \"c8d3e119-de8d-4b40-bf9a-18d5ba0f91d4\"\n        },\n        {\n          \"x\": 257.5,\n          \"y\": 555,\n          \"width\": 101,\n          \"height\": 28,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"d61d1f44-9af9-4cdc-8912-caf2aa0c4993\",\n          \"content\": \"<span style=\\\"color: #fff\\\">See More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 11, \"vertical\": 6 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"groupId\": \"c8d3e119-de8d-4b40-bf9a-18d5ba0f91d4\"\n        },\n        {\n          \"x\": 136,\n          \"y\": 563,\n          \"width\": 75,\n          \"height\": 11,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"ed850d1c-3f8f-4154-ad72-a90d30dc836d\",\n          \"content\": \"<span style=\\\"font-style: italic; color: #fff\\\">5 out of 5</span>\",\n          \"fontSize\": 12,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"x\": 98,\n          \"y\": 560,\n          \"width\": 17,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"entertainmentStar\" },\n          \"id\": \"fbd2640e-0f63-49fb-9573-172a8e77b166\",\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 17,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"entertainmentStar\" },\n          \"id\": \"502676dd-9ed2-4bb1-a899-4f43733ae6ae\",\n          \"x\": 83,\n          \"y\": 560,\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 17,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"entertainmentStar\" },\n          \"id\": \"049e569d-4f5a-473f-ad05-0a00f4ccb802\",\n          \"x\": 67,\n          \"y\": 560,\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 17,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"entertainmentStar\" },\n          \"id\": \"c136d4e4-a956-4d96-87c2-febec1c39ca0\",\n          \"x\": 52,\n          \"y\": 560,\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"type\": \"sticker\",\n          \"width\": 17,\n          \"height\": 15,\n          \"sticker\": { \"type\": \"entertainmentStar\" },\n          \"id\": \"1d5e6344-dba8-4aec-8865-9c60b35e8ed2\",\n          \"x\": 37,\n          \"y\": 560,\n          \"groupId\": \"ab61d7c9-c230-4372-abd0-27d88e95b225\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"16b7e31d-8cbb-4cbc-9063-74267c3dde2e\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"ed850d1c-3f8f-4154-ad72-a90d30dc836d\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"e7a07582-0c95-471c-9d12-c119a357404c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"ff9a77cf-c942-4a04-84ea-d7134d97f360\"],\n          \"duration\": 3000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"53a394d6-86de-45a0-8357-444417d42b26\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"fd434caf-7752-47d3-b41b-0a1048f116a8\"],\n          \"duration\": 3000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"df79f0fc-7e24-4b3a-8f7c-a8fc2c571343\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"d61d1f44-9af9-4cdc-8912-caf2aa0c4993\"],\n          \"duration\": 600,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"66c47e20-dbed-4a85-b5bf-f69e43751aa8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"837db927-1ee6-4419-ace6-c59f83f0ca49\"],\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"4a0c96d3-b601-48c8-9144-1d83ee52aa72\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"76c34633-deca-4d3b-ad89-9f8f787aabf3\"],\n          \"duration\": 600,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"af3d530d-f26e-47c0-bc17-b138fb525bdd\",\n          \"type\": \"effect-whoosh-in\",\n          \"targets\": [\"fbd2640e-0f63-49fb-9573-172a8e77b166\"],\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"502676dd-9ed2-4bb1-a899-4f43733ae6ae\"],\n          \"id\": \"235b5175-75bd-4171-93ee-3e8a93253c8d\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"049e569d-4f5a-473f-ad05-0a00f4ccb802\"],\n          \"id\": \"4d9560fa-fb94-4a73-8ba1-af7dc2f83a53\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"c136d4e4-a956-4d96-87c2-febec1c39ca0\"],\n          \"id\": \"0101c08d-e8d8-4d03-888e-429ae079b6a2\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"targets\": [\"1d5e6344-dba8-4aec-8865-9c60b35e8ed2\"],\n          \"id\": \"9239308d-3772-4b31-9acc-8807732baf11\",\n          \"type\": \"effect-whoosh-in\",\n          \"whooshInDir\": \"leftToRight\",\n          \"duration\": 600,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"1a55ad42-1807-4e35-b65b-77428949cbd1\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"46058255-8bf6-4302-88eb-f9bd71304225\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"7494b712-c8d0-4189-a85c-32aa52a22032\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"c8d3e119-de8d-4b40-bf9a-18d5ba0f91d4\": {\n          \"name\": \"See More\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"ab61d7c9-c230-4372-abd0-27d88e95b225\": {\n          \"name\": \"Rating\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"3fb75a52-ac04-4979-9a26-c28e725c3ed3\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 41,\n          \"y\": 53,\n          \"width\": 349,\n          \"height\": 42,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.43,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7807179c-ca03-44f5-b164-de59858ed73b\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Summer’s here and so are the great hits! Let’s check out the scenes with Trevor and Inband.</span>\",\n          \"fontSize\": 15,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"x\": 41,\n          \"y\": 10,\n          \"width\": 272,\n          \"height\": 34,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"883294a7-1863-4ef1-b3b3-05f4e99f027c\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Summer Hits</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 414,\n          \"height\": 579,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3ed28508-6e62-4bb6-9057-0263ed615cba\",\n          \"x\": 0,\n          \"y\": 96\n        },\n        {\n          \"x\": 39,\n          \"y\": 451,\n          \"width\": 386,\n          \"height\": 63,\n          \"opacity\": 10,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"99964f56-048a-4e9c-bc0c-79ff8f9e32d5\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Out Now</span>\",\n          \"fontSize\": 79,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"e41dada8-d72e-40ec-8657-30222347907f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 481,\n          \"width\": 386,\n          \"height\": 63,\n          \"opacity\": 30,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"7134bc0d-5c49-40fb-ac4a-dac7dc45dccf\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Out Now</span>\",\n          \"fontSize\": 79,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"e41dada8-d72e-40ec-8657-30222347907f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 516,\n          \"width\": 386,\n          \"height\": 63,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.8,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"id\": \"842c2576-5887-4eb2-a9ba-93a6eea67b7d\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Out Now</span>\",\n          \"fontSize\": 79,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"e41dada8-d72e-40ec-8657-30222347907f\",\n          \"tagName\": \"p\"\n        },\n        {\n          \"x\": 39,\n          \"y\": 114,\n          \"width\": 375,\n          \"height\": 305,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 200,\n          \"focalX\": 50.079165168465856,\n          \"focalY\": 43.117469706013374,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page6_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page6_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#7572d1\",\n            \"isExternal\": true\n          },\n          \"id\": \"9bcf8de4-b888-486b-93cb-f27bc58c637d\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"5e637d83-95ba-450e-8a8b-06e120ced464\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"842c2576-5887-4eb2-a9ba-93a6eea67b7d\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"d0fa0ef7-2b4b-40a7-889c-612ac6c3d1f3\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"7134bc0d-5c49-40fb-ac4a-dac7dc45dccf\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 450\n        },\n        {\n          \"id\": \"9fbf0c52-d234-48cc-878b-62c8ecdaba03\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"99964f56-048a-4e9c-bc0c-79ff8f9e32d5\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1000,\n          \"delay\": 550\n        },\n        {\n          \"id\": \"d963d40c-f91e-47d2-956f-b82654680648\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9bcf8de4-b888-486b-93cb-f27bc58c637d\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"fd60f532-b619-4162-8df9-d8241cc88e45\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"editorial\",\n      \"groups\": {\n        \"e41dada8-d72e-40ec-8657-30222347907f\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f1d3853d-aa0a-4bfc-8b40-d09c94153814\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 36,\n          \"y\": 420,\n          \"width\": 272,\n          \"height\": 70,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"0fdf2c26-3138-41cf-ae7c-e508635ae6fe\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\">Behind the Scenes</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 490,\n          \"width\": 413,\n          \"height\": 185,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7ad806d6-4023-4c41-a3e8-7142fe7c3361\"\n        },\n        {\n          \"x\": 36,\n          \"y\": 0,\n          \"width\": 376,\n          \"height\": 392,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 49.89204749754657,\n          \"focalY\": 62.22262102275575,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page7_image1.jpg\",\n            \"width\": 220,\n            \"height\": 330,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page7_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#3a626a\",\n            \"isExternal\": true\n          },\n          \"id\": \"6314a691-d449-4d99-9f12-64a9c7e5b477\"\n        },\n        {\n          \"x\": 36,\n          \"y\": 509,\n          \"width\": 340,\n          \"height\": 92,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"b0d4ee54-76eb-4050-821d-5d11181b6a2c\",\n          \"content\": \"<span style=\\\"color: #fff\\\">It’s one thing to listen to music; it’s another to learn how it’s made! We’ll take you through the production process of one of our favorite songs.</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"55cc5974-9853-43ad-b5f2-82e8f61d6a80\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b0d4ee54-76eb-4050-821d-5d11181b6a2c\"],\n          \"flyInDir\": \"bottomToTop\",\n          \"duration\": 1001,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"65b41981-b9ac-4612-840b-bedf218e3e49\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6314a691-d449-4d99-9f12-64a9c7e5b477\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"877c2ef2-1faa-4a7b-9f5b-364dcfa3d856\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"editorial\"\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"777737d1-e79e-4f4e-9708-cf5a41962d77\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"x\": 40,\n          \"y\": 25,\n          \"width\": 251,\n          \"height\": 105,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"97bead85-66e2-4ea0-af98-8b1305d41884\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\">This summer’s must-see blockbusters</span>\",\n          \"fontSize\": 35,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 }\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 0,\n          \"y\": 130,\n          \"width\": 412,\n          \"height\": 579,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"90ca1407-45ab-4dd5-b34f-eede73e091ef\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 158,\n          \"width\": 309,\n          \"height\": 10,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 214 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"4e907f06-b5e0-4254-b469-8f0a505cd915\",\n          \"groupId\": \"9ffe05c9-14f6-414c-a007-e15aaf5614c9\"\n        },\n        {\n          \"x\": -2,\n          \"y\": 167,\n          \"width\": 352,\n          \"height\": 110,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 130,\n          \"focalX\": 55.59746548940643,\n          \"focalY\": 37.583736990182935,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"24deb6f3-2a32-4638-8702-7fc1157b9956\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page8_image1.jpg\",\n            \"width\": 220,\n            \"height\": 90,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#3b4345\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"9ffe05c9-14f6-414c-a007-e15aaf5614c9\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 248,\n          \"width\": 268,\n          \"height\": 46,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"2942198b-fcac-4d56-bc37-b5a16de50651\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Murder Mystery</span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 10, \"vertical\": 10 },\n          \"groupId\": \"9ffe05c9-14f6-414c-a007-e15aaf5614c9\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 313,\n          \"width\": 309,\n          \"height\": 10,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 214 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"016efcac-89dc-4123-bec4-f7422f8babd6\",\n          \"groupId\": \"17e0c840-10d9-4b9c-94be-9a79d9db55dc\"\n        },\n        {\n          \"x\": -2,\n          \"y\": 323,\n          \"width\": 352,\n          \"height\": 110,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 160,\n          \"focalX\": 31.375571576243427,\n          \"focalY\": 57.36004155908421,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"e53c70ed-d9e7-442b-ab62-0c236111e1db\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page8_image2.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image2\",\n            \"sizes\": [],\n            \"baseColor\": \"#93967e\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"17e0c840-10d9-4b9c-94be-9a79d9db55dc\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 408,\n          \"width\": 268,\n          \"height\": 46,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"787be6c3-3d2d-4d08-9db1-801e2f1bf7f1\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Documentary</span></span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 10, \"vertical\": 10 },\n          \"groupId\": \"17e0c840-10d9-4b9c-94be-9a79d9db55dc\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 471,\n          \"width\": 309,\n          \"height\": 10,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 214 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"6403aa20-a02a-499d-832a-0982518395f5\",\n          \"groupId\": \"c67adb69-b6e9-4df0-920a-bfc33ef11e82\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 480,\n          \"width\": 352,\n          \"height\": 110,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 110,\n          \"focalX\": 50,\n          \"focalY\": 35.61736883198913,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"84d3c738-e445-460d-96cc-e04f1184a554\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"creationDate\": \"2020-06-26T17:40:35\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page8_image3.jpg\",\n            \"width\": 176,\n            \"height\": 70,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page8_image3\",\n            \"sizes\": [],\n            \"baseColor\": \"#664e4a\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"c67adb69-b6e9-4df0-920a-bfc33ef11e82\"\n        },\n        {\n          \"x\": 0,\n          \"y\": 566,\n          \"width\": 268,\n          \"height\": 48,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"b2b65d7c-5689-4c40-a40e-5a9a628bc04e\",\n          \"content\": \"<span style=\\\"color: rgba(255, 255, 255, 1)\\\"><span style=\\\"font-weight: 700; text-transform: uppercase\\\">Political Biopic</span></span>\",\n          \"fontSize\": 26,\n          \"padding\": { \"horizontal\": 10, \"vertical\": 11 },\n          \"groupId\": \"c67adb69-b6e9-4df0-920a-bfc33ef11e82\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"d8ce2a5f-21e2-4c80-9a28-88c825cdf437\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"4e907f06-b5e0-4254-b469-8f0a505cd915\"],\n          \"duration\": 3000,\n          \"delay\": 150\n        },\n        {\n          \"id\": \"26b907f4-f957-4c18-9af4-a30a9bed1cc7\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"24deb6f3-2a32-4638-8702-7fc1157b9956\"],\n          \"duration\": 2000,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"c5781e03-4e6e-48ca-8721-a90ecb386703\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e53c70ed-d9e7-442b-ab62-0c236111e1db\"],\n          \"duration\": 2000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"7be88b0d-d250-41e9-b4ac-d063b731017f\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"016efcac-89dc-4123-bec4-f7422f8babd6\"],\n          \"duration\": 3000,\n          \"delay\": 250\n        },\n        {\n          \"id\": \"8c53d221-aea2-4263-8069-de0103b23d93\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"6403aa20-a02a-499d-832a-0982518395f5\"],\n          \"duration\": 3000,\n          \"delay\": 350\n        },\n        {\n          \"id\": \"a1f0a214-d65d-4819-bd4b-c1d85e874b99\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"84d3c738-e445-460d-96cc-e04f1184a554\"],\n          \"duration\": 2000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"250e22f3-abf7-4b69-b27b-0509fd449804\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"2942198b-fcac-4d56-bc37-b5a16de50651\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"0e026746-75eb-462d-98d7-d1368f7cef4f\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"787be6c3-3d2d-4d08-9db1-801e2f1bf7f1\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 405\n        },\n        {\n          \"id\": \"f5483d63-2044-4d33-b9d9-1046aa29d32c\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"b2b65d7c-5689-4c40-a40e-5a9a628bc04e\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 500\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"3d0dbbd3-70c0-4376-b1bf-c8015def1050\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"9ffe05c9-14f6-414c-a007-e15aaf5614c9\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"17e0c840-10d9-4b9c-94be-9a79d9db55dc\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"c67adb69-b6e9-4df0-920a-bfc33ef11e82\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    },\n    {\n      \"elements\": [\n        {\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ffce028c-042d-4b3c-a489-3cc31162ed10\",\n          \"isDefaultBackground\": true\n        },\n        {\n          \"width\": 338,\n          \"height\": 66,\n          \"opacity\": 30,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.83,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Stories</span>\",\n          \"fontSize\": 80,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"id\": \"f449ade2-50c9-4495-9887-2e906e1e925f\",\n          \"x\": -1,\n          \"y\": 57,\n          \"groupId\": \"fe5dd611-9a17-4f04-b007-539cddb1fc08\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": -1,\n          \"y\": 19,\n          \"width\": 234,\n          \"height\": 66,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 0.83,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"4f12d40d-d1c9-488f-a4f8-48e81f141c27\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">More</span>\",\n          \"fontSize\": 80,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"fe5dd611-9a17-4f04-b007-539cddb1fc08\",\n          \"tagName\": \"h2\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 175,\n          \"width\": 162,\n          \"height\": 31,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"c6c185a6-32d1-42ed-b376-5733abe06f55\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Our Top Picks&nbsp;For The Grammys</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 82, \"g\": 82, \"b\": 82 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"9b070f80-9ba0-4358-bc37-5da9fc2a9697\",\n          \"x\": 220,\n          \"y\": 240,\n          \"groupId\": \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"a5460d7e-4e85-41c9-b55f-a6ca14c0df8e\",\n          \"x\": 210,\n          \"y\": 229,\n          \"groupId\": \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\"\n        },\n        {\n          \"width\": 101,\n          \"height\": 28,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">See More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 11, \"vertical\": 6 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"72fa1c93-fbac-460f-a06a-9c539d1f55c0\",\n          \"x\": 213.5,\n          \"y\": 231,\n          \"groupId\": \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 154,\n          \"width\": 160,\n          \"height\": 124,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"77770ec0-6e97-40bc-813b-1e0500033fc3\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page9_image1.jpg\",\n            \"width\": 220,\n            \"height\": 165,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image1\",\n            \"sizes\": [],\n            \"baseColor\": \"#453248\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 331,\n          \"width\": 113,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9379053f-520a-4138-9720-dd14e3115431\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Trending Superhero</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"3a76f47c-6334-4091-80cd-964169685c97\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 82, \"g\": 82, \"b\": 82 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"5930c7f2-9203-4a8a-b183-4d42a8c78850\",\n          \"x\": 219,\n          \"y\": 385,\n          \"groupId\": \"3a76f47c-6334-4091-80cd-964169685c97\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"19f39586-3daa-4b78-8561-7a2f1beafb37\",\n          \"x\": 209,\n          \"y\": 374,\n          \"groupId\": \"3a76f47c-6334-4091-80cd-964169685c97\"\n        },\n        {\n          \"width\": 101,\n          \"height\": 28,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">See More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 11, \"vertical\": 6 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"0f9d3b1c-6f29-4dce-a4fb-7a9a66715ad9\",\n          \"x\": 212.5,\n          \"y\": 376,\n          \"groupId\": \"3a76f47c-6334-4091-80cd-964169685c97\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 312,\n          \"width\": 160,\n          \"height\": 124,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 49.851188990309694,\n          \"focalY\": 34.28571451955782,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"e279e4c7-f45a-4642-86ce-8c86644f7198\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page9_image2.jpg\",\n            \"width\": 220,\n            \"height\": 275,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image2\",\n            \"sizes\": [],\n            \"baseColor\": \"#92a6a3\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"3a76f47c-6334-4091-80cd-964169685c97\"\n        },\n        {\n          \"x\": 210,\n          \"y\": 488,\n          \"width\": 145,\n          \"height\": 31,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"type\": \"text\",\n          \"id\": \"9300db37-ac48-4bfc-b91b-0ffb4da5f8d0\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">New Summer Movies</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 0, \"vertical\": 0 },\n          \"groupId\": \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\",\n          \"tagName\": \"h3\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 82, \"g\": 82, \"b\": 82 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"a83e16c9-6c65-4c65-bdca-30f2a1616e01\",\n          \"x\": 220,\n          \"y\": 542,\n          \"groupId\": \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\"\n        },\n        {\n          \"width\": 108,\n          \"height\": 32,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"shape\",\n          \"id\": \"f8241cd9-c24e-44aa-8556-4bde9758fee4\",\n          \"x\": 210,\n          \"y\": 531,\n          \"groupId\": \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\"\n        },\n        {\n          \"width\": 101,\n          \"height\": 28,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">See More</span>\",\n          \"fontSize\": 16,\n          \"padding\": { \"horizontal\": 11, \"vertical\": 6 },\n          \"borderRadius\": {\n            \"topLeft\": 0,\n            \"topRight\": 0,\n            \"bottomRight\": 0,\n            \"bottomLeft\": 0,\n            \"locked\": false\n          },\n          \"id\": \"a82b3d64-8a58-4b16-9faa-88051a2d246a\",\n          \"x\": 213.5,\n          \"y\": 533,\n          \"groupId\": \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\"\n        },\n        {\n          \"x\": 26,\n          \"y\": 470,\n          \"width\": 160,\n          \"height\": 124,\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 51, \"g\": 51, \"b\": 51 } },\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"type\": \"image\",\n          \"id\": \"78953cce-d23a-4bef-97e5-dec04f6a45a9\",\n          \"resource\": {\n            \"type\": \"image\",\n            \"mimeType\": \"image/jpeg\",\n            \"src\": \"__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/weekly-entertainment/page9_image3.jpg\",\n            \"width\": 220,\n            \"height\": 147,\n            \"posterId\": 0,\n            \"id\": 0,\n            \"alt\": \"page9_image3\",\n            \"sizes\": [],\n            \"baseColor\": \"#5c5a4f\",\n            \"isExternal\": true\n          },\n          \"groupId\": \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\"\n        }\n      ],\n      \"animations\": [\n        {\n          \"id\": \"704ed23f-82b9-4cae-a96c-f2cf148102ed\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9b070f80-9ba0-4358-bc37-5da9fc2a9697\"],\n          \"duration\": 1200,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"f49e4183-364c-4032-8bab-3007b7492518\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a5460d7e-4e85-41c9-b55f-a6ca14c0df8e\"],\n          \"duration\": 1200,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"9e88c647-420a-4e26-9cdf-f1be13209d27\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"72fa1c93-fbac-460f-a06a-9c539d1f55c0\"],\n          \"duration\": 1200,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"55d16e8a-4fe6-494e-9d48-3ff5566a1ade\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"5930c7f2-9203-4a8a-b183-4d42a8c78850\"],\n          \"duration\": 1200,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"2144a782-06cf-4af0-84cd-bda9587ccd82\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"19f39586-3daa-4b78-8561-7a2f1beafb37\"],\n          \"duration\": 1200,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"3d418f55-1d15-4fd4-994b-4ef1280d187c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"0f9d3b1c-6f29-4dce-a4fb-7a9a66715ad9\"],\n          \"duration\": 1200,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"1c13e343-3b6a-4d10-8378-8b78f20e0325\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a83e16c9-6c65-4c65-bdca-30f2a1616e01\"],\n          \"duration\": 1200,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"602a40d5-ba5d-4524-8d0e-dd760e36e123\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"f8241cd9-c24e-44aa-8556-4bde9758fee4\"],\n          \"duration\": 1200,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"f6053183-2480-4ad7-b2db-5f5277be5f56\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"a82b3d64-8a58-4b16-9faa-88051a2d246a\"],\n          \"duration\": 1200,\n          \"delay\": 500\n        },\n        {\n          \"id\": \"d7ad4d72-7615-4999-be97-15babc0b1a17\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"c6c185a6-32d1-42ed-b376-5733abe06f55\"],\n          \"duration\": 3000,\n          \"delay\": 200\n        },\n        {\n          \"id\": \"0eb0924e-ac39-4213-bb3a-a2610d881e8a\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9379053f-520a-4138-9720-dd14e3115431\"],\n          \"duration\": 3000,\n          \"delay\": 300\n        },\n        {\n          \"id\": \"99387892-5b48-4939-95de-e186921e16fa\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"9300db37-ac48-4bfc-b91b-0ffb4da5f8d0\"],\n          \"duration\": 3000,\n          \"delay\": 400\n        },\n        {\n          \"id\": \"7eec743d-1153-4f7d-9982-262273c1140d\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"4f12d40d-d1c9-488f-a4f8-48e81f141c27\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"e64342ee-4c3d-482e-a3b6-158152098dbc\",\n          \"type\": \"effect-fly-in\",\n          \"targets\": [\"f449ade2-50c9-4495-9887-2e906e1e925f\"],\n          \"flyInDir\": \"leftToRight\",\n          \"duration\": 800,\n          \"delay\": 100\n        },\n        {\n          \"id\": \"eb8dc4ce-cc4e-44d0-8038-6ee862ce943c\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"77770ec0-6e97-40bc-813b-1e0500033fc3\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"d0c20ed8-6d6e-4bb7-a3d4-c25e8c5d0ed8\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"e279e4c7-f45a-4642-86ce-8c86644f7198\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        },\n        {\n          \"id\": \"11f620b7-7e1e-4319-b14c-cf5bf7fb948e\",\n          \"type\": \"effect-fade-in\",\n          \"targets\": [\"78953cce-d23a-4bef-97e5-dec04f6a45a9\"],\n          \"duration\": 2000,\n          \"delay\": 0\n        }\n      ],\n      \"type\": \"page\",\n      \"id\": \"f4ea7828-e328-47e6-bf9d-a786ab192ee1\",\n      \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n      \"pageTemplateType\": \"list\",\n      \"groups\": {\n        \"fe5dd611-9a17-4f04-b007-539cddb1fc08\": {\n          \"name\": \"Text\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"42f48f90-d1d9-4b0a-a2dc-7b0c09c93a1f\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"3a76f47c-6334-4091-80cd-964169685c97\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        },\n        \"6ae7d757-be0e-40ef-95e4-41609ab2e6c6\": {\n          \"name\": \"Section\",\n          \"isLocked\": false,\n          \"isCollapsed\": true\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/templates/src/test/getTemplates.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport getTemplates from '../getTemplates';\n\ndescribe('getTemplate', () => {\n  it('should return png and webp urls for each page', async () => {\n    const templates = await getTemplates('example.com/');\n\n    templates.forEach((template) => {\n      template.postersByPage.forEach((page, i) => {\n        expect(page).toStrictEqual(\n          expect.objectContaining({\n            png: expect.stringContaining(\n              `example.com/images/templates/${template.slug}/posters/${\n                i + 1\n              }.png`\n            ),\n            webp: expect.stringContaining(\n              `example.com/images/templates/${template.slug}/posters/${\n                i + 1\n              }.webp`\n            ),\n            type: expect.toBeOneOf([\n              null,\n              'cover',\n              'editorial',\n              'list',\n              'quote',\n              'section',\n              'table',\n              'steps',\n            ]),\n          })\n        );\n      });\n    });\n  });\n\n  it('should match postersByPage.type with pages.pageTemplateType', async () => {\n    const templates = await getTemplates('example.com/');\n\n    templates.forEach((template) => {\n      template.postersByPage.forEach((page, i) => {\n        expect(page.type).toStrictEqual(template.pages[i].pageTemplateType);\n      });\n    });\n  });\n\n  it('should replace __WEB_STORIES_TEMPLATE_BASE_URL__/ with imageUrl for each page', async () => {\n    const templates = await getTemplates('example.com/');\n\n    templates.forEach((template) => {\n      template.pages.forEach((page) => {\n        page.elements.forEach((element) => {\n          expect(element.resource?.src).toStrictEqual(\n            expect.not.stringContaining('__WEB_STORIES_TEMPLATE_BASE_URL__/')\n          );\n          expect(element.resource?.poster).toStrictEqual(\n            expect.not.stringContaining('__WEB_STORIES_TEMPLATE_BASE_URL__/')\n          );\n        });\n      });\n    });\n  });\n\n  it('should have keys for color, label, and family for each template color', async () => {\n    const templates = await getTemplates('example.com/');\n\n    templates.forEach((template) => {\n      template.colors.forEach((color) => {\n        expect(color).toStrictEqual(\n          expect.objectContaining({\n            label: expect.toBeString(),\n            color: expect.stringContaining('#'),\n            family: expect.toBeString(),\n          })\n        );\n      });\n    });\n  });\n\n  it('should only list valid elements as animation targets', async () => {\n    const templates = await getTemplates('example.com/');\n    for (const template of templates) {\n      for (const { id, elements, animations = [] } of template.pages) {\n        const elementIds = elements.map((e) => e.id);\n        for (const animation of animations) {\n          try {\n            expect(elementIds).toIncludeAllMembers(animation.targets);\n          } catch {\n            throw new Error(\n              `Animation target failure in: '${template.slug}', page ${id}, animation ${animation.id}`\n            );\n          }\n        }\n      }\n    }\n  });\n\n  it('should list elements in the same group sequentially without gaps', async () => {\n    const templates = await getTemplates('example.com/');\n    let i = 0;\n    for (const template of templates) {\n      i++;\n      for (const { id, elements, groups = {} } of template.pages) {\n        const existingGroupIds = Object.keys(groups);\n\n        const seenGroupIds = [];\n\n        let lastGroupId = null;\n        const elementGroups = elements.map(({ groupId }) => groupId);\n        for (const groupId of elementGroups) {\n          try {\n            expect(\n              // eslint-disable-next-line jest/no-conditional-in-test\n              lastGroupId &&\n                groupId &&\n                lastGroupId !== groupId &&\n                seenGroupIds.includes(groupId)\n            ).toBeFalsy();\n          } catch {\n            throw new Error(\n              `Group order failure in: '${template.slug} (${i}/${\n                templates.length\n              })', page ${id}, group ${groupId}.\\nGroups are:\\n* ${elementGroups\n                // eslint-disable-next-line jest/no-conditional-in-test\n                .map((g) => (g === undefined ? 'none' : g))\n                .join('\\n* ')}`\n            );\n          }\n\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (groupId) {\n            seenGroupIds.push(groupId);\n\n            // eslint-disable-next-line jest/no-conditional-expect\n            expect(existingGroupIds).toContain(groupId);\n          }\n\n          lastGroupId = groupId;\n        }\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "packages/templates/src/test/raw.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readdirSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\nimport stickers from '@googleforcreators/stickers';\nimport { isValid } from '@googleforcreators/date';\n\ndescribe('raw template files', () => {\n  const templates = readdirSync(\n    resolve(process.cwd(), 'packages/templates/src/raw')\n  );\n\n  describe.each(templates)('%s template', (template) => {\n    let templateData;\n\n    beforeAll(async () => {\n      const { default: _templateData } = await import(\n        /* webpackChunkName: \"chunk-web-stories-template-[index]\" */ `../raw/${template}`\n      );\n\n      templateData = _templateData;\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/issues/2473#issuecomment-651509687\n    it('should not contain invisible characters', () => {\n      const templateContent = readFileSync(\n        resolve(\n          process.cwd(),\n          `packages/templates/src/raw/${template}/template.json`\n        ),\n        'utf8'\n      );\n\n      expect(templateContent).not.toContain('\\u2028');\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/issues/11648\n    it('should not contain first page animations', () => {\n      const { pages } = templateData;\n      const firstPage = pages[0];\n      const { animations = [] } = firstPage;\n      expect(animations).toHaveLength(0);\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/pull/4516\n    // @see https://github.com/googleforcreators/web-stories-wp/pull/6159\n    it('should contain replaceable URLs', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (!element?.resource?.src) {\n            continue;\n          }\n\n          expect(element?.resource?.src).toStartWith(\n            `__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/${template}`\n          );\n        }\n      }\n    });\n\n    it('should contain replaceable poster URLs', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (element?.type !== 'video') {\n            continue;\n          }\n\n          expect(element?.resource?.poster).toStartWith(\n            `__WEB_STORIES_TEMPLATE_BASE_URL__/images/templates/${template}`\n          );\n        }\n      }\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/pull/7944#pullrequestreview-686071526\n    it('images and video ids should default to 0', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (!['image', 'video', 'gif'].includes(element?.type)) {\n            continue;\n          }\n\n          expect(element?.resource?.id).toBe(0);\n\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if ('image' === element?.type) {\n            continue;\n          }\n\n          expect(element?.resource?.posterId).toBe(0);\n        }\n      }\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/pull/5889\n    it('should contain pageTemplateType', () => {\n      for (const page of templateData.pages) {\n        expect(page).toStrictEqual(\n          expect.objectContaining({\n            pageTemplateType: expect.toBeOneOf([\n              null,\n              'cover',\n              'editorial',\n              'list',\n              'quote',\n              'section',\n              'table',\n              'steps',\n            ]),\n          })\n        );\n      }\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/issues/7227\n    it('should not contain extraneous properties', () => {\n      expect(templateData.current).toBeUndefined();\n      expect(templateData.selection).toBeUndefined();\n      expect(templateData.story).toBeUndefined();\n    });\n\n    it('should only contain videos marked as optimized', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (element?.type !== 'video' || !element?.resource?.src) {\n            continue;\n          }\n\n          expect(element?.resource?.isOptimized).toBeTrue();\n        }\n      }\n    });\n\n    it('should only contain videos have isMuted attribute', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (element?.type !== 'video' || !element?.resource?.src) {\n            continue;\n          }\n\n          expect(element?.resource?.isMuted).toBeDefined();\n          expect(element?.resource?.isMuted).toBeBoolean();\n        }\n      }\n    });\n\n    it('images and videos should have baseColor', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (!['image', 'video', 'gif'].includes(element?.type)) {\n            continue;\n          }\n\n          expect(element?.resource?.baseColor).toStrictEqual(\n            expect.stringMatching(/^#(?:[0-9a-fA-F]{3}){1,2}$/)\n          );\n        }\n      }\n    });\n\n    it('should contain only valid stickers', () => {\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (element?.type !== 'sticker' || !element?.sticker?.type) {\n            continue;\n          }\n\n          expect(stickers).toStrictEqual(\n            expect.objectContaining({\n              [element?.sticker?.type]: expect.any(Object),\n            })\n          );\n        }\n      }\n    });\n\n    // @see https://github.com/googleforcreators/web-stories-wp/pull/8692\n    it('should contain a slug for screenshot referencing', () => {\n      expect(templateData.slug).toBeString();\n    });\n\n    it('should contain a valid createdDate', async () => {\n      const { default: metaData } = await import(\n        /* webpackChunkName: \"chunk-web-stories-template-[index]-metaData\" */ `../raw/${template}/metaData`\n      );\n\n      expect(isValid(new Date(metaData.creationDate))).toBeTrue();\n      expect(isValid(new Date(templateData.creationDate))).toBeTrue();\n    });\n\n    it('should contain fonts from global fonts list', () => {\n      const fonts = JSON.parse(\n        readFileSync(\n          resolve(process.cwd(), 'packages/fonts/src/fonts.json'),\n          'utf8'\n        )\n      );\n      const fontNames = fonts.map(({ family }) => family);\n\n      for (const { elements } of templateData.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (!['text'].includes(element?.type)) {\n            continue;\n          }\n\n          expect(fontNames).toContain(element.font.family);\n        }\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "packages/templates/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { StoryData, Page, Element } from '@googleforcreators/elements';\n\nexport interface Color {\n  label: string;\n  color: string;\n  family: string;\n}\n\nexport interface MetaData {\n  slug: string;\n  creationDate: string;\n  title: string;\n  tags: string[];\n  colors: Color[];\n  description: string;\n  vertical: string;\n  createdBy?: string;\n  modified?: string;\n}\n\nexport interface TemplateData extends Omit<StoryData, 'pages'> {\n  current: null;\n  selection: never[];\n  story: Record<string, never>;\n  version: number;\n  pages: TemplatePage[];\n}\n\ninterface TemplatePage extends Omit<\n  Page,\n  'autoAdvance' | 'defaultPageDuration' | 'elements'\n> {\n  pageTemplateType: string | null;\n  elements: Element[];\n}\n\nexport type RawTemplate = MetaData & TemplateData;\n\ntype Poster = {\n  webp: string;\n  png: string;\n  type: string;\n};\n\nexport interface Template extends RawTemplate {\n  postersByPage: Poster[];\n}\n"
  },
  {
    "path": "packages/templates/src/utils/memoize.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype ArgHash<K> = (args: K[]) => string;\nexport default function memoize<K, T>(\n  func: (...args: K[]) => T,\n  argsHash: ArgHash<K> = (args) => args.join('-')\n) {\n  const memoized = new Map<string, T>();\n  return (...args: K[]) => {\n    const key = argsHash(args);\n    if (!memoized.has(key)) {\n      const result = func(...args);\n      memoized.set(key, result);\n      return result;\n    }\n    // Here get() has signature `T | undefined` but because of has() above,\n    // it must be T (which can technically still include undefined, but that's\n    // besides the point).\n    return memoized.get(key) as T;\n  };\n}\n"
  },
  {
    "path": "packages/templates/src/utils/test/memoize.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport memoize from '../memoize';\n\ndescribe('memoize(func, argumentsHash)', () => {\n  it('memoizes based off arguments', () => {\n    const memoized = memoize((a, b, c) => ({\n      a,\n      b,\n      c,\n    }));\n\n    const funcArg = () => {};\n    const objArg = {};\n\n    expect(memoized(1, 'prop', true)).toStrictEqual(memoized(1, 'prop', true));\n    expect(memoized(2, 'other-prop', false)).toStrictEqual(\n      memoized(2, 'other-prop', false)\n    );\n    expect(memoized(funcArg, objArg, 5)).toStrictEqual(\n      memoized(funcArg, objArg, 5)\n    );\n  });\n\n  it('allows for a custom hashing function', () => {\n    const memoized = memoize(\n      (v) => v,\n      () => 'hashKey'\n    );\n    const value = { prop: 23 };\n    expect(memoized(value)).toStrictEqual(value);\n    expect(memoized({ prop: 'otherInput' })).toStrictEqual(value);\n  });\n\n  it('only calls the given function once per memoized param', () => {\n    const func = jest.fn();\n    const memoized = memoize(func);\n\n    memoized(1, 2, 3);\n    memoized(1, 2, 3);\n    memoized(1, 2, 3);\n\n    expect(func).toHaveBeenCalledOnce();\n    expect(func).toHaveBeenCalledWith(1, 2, 3);\n  });\n});\n"
  },
  {
    "path": "packages/templates/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [\n    { \"path\": \"../date\" },\n    { \"path\": \"../elements\" },\n    { \"path\": \"../i18n\" },\n    { \"path\": \"../migration\" },\n    { \"path\": \"../stickers\" },\n    { \"path\": \"../tracking\" }\n  ],\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\n    \"packages/*/dist-*/**\",\n    \"packages/*/dist/**\",\n    \"**/karma/**\",\n    \"**/stories/**\",\n    \"**/test/**\",\n    \"**/testUtils/**\",\n    \"src/raw/**/template.json\"\n  ]\n}\n"
  },
  {
    "path": "packages/test-utils/README.md",
    "content": "# Test Utils\n\nPackage for Web Stories test utilities\n"
  },
  {
    "path": "packages/test-utils/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/test-utils\",\n  \"description\": \"Package for Web Stories test utilities\",\n  \"private\": true,\n  \"version\": \"0.1.202203150806\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/test-utils/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/test-utils\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n     \"default\": \"./src/index.js\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"@googleforcreators/design-system\": \"*\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"prop-types\": \"^15.8.1\",\n    \"styled-components\": \"^5.3.11\"\n  }\n}\n"
  },
  {
    "path": "packages/test-utils/src/firePointerEvent.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent } from '@testing-library/react';\n\nfunction _firePointerEvent(\n  node: Element | Node | Document | Window,\n  eventType: string,\n  properties: MouseEventInit\n) {\n  fireEvent(node, new window.MouseEvent(eventType, properties));\n}\n\nconst pointerEventTypes = [\n  'pointerOver',\n  'pointerEnter',\n  'pointerDown',\n  'pointerMove',\n  'pointerUp',\n  'pointerCancel',\n  'pointerOut',\n  'pointerLeave',\n  'gotPointerCapture',\n  'lostPointerCapture',\n];\n\nconst firePointerEvent: Record<\n  string,\n  (node: Element | Node | Document | Window, properties: MouseEventInit) => void\n> = {};\n\npointerEventTypes.forEach((type) => {\n  firePointerEvent[type] = (\n    node: Element | Node | Document | Window,\n    properties: MouseEventInit\n  ) =>\n    _firePointerEvent(node, type.toLowerCase(), {\n      bubbles: true,\n      ...properties,\n    });\n});\n\nexport default firePointerEvent;\n"
  },
  {
    "path": "packages/test-utils/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as firePointerEvent } from './firePointerEvent';\nexport { default as renderWithTheme } from './renderWithTheme';\nexport * from './queryByAriaLabel';\nexport * from './queryByAutoAdvanceAfter';\nexport * from './queryById';\n"
  },
  {
    "path": "packages/test-utils/src/queryByAriaLabel.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  queryAllByAttribute,\n  buildQueries,\n  type GetErrorFunction,\n  type Matcher,\n} from '@testing-library/react';\n\nconst queryAllByAriaLabel = (container: HTMLElement, id: Matcher) =>\n  queryAllByAttribute('aria-label', container, id);\n\nconst getMultipleError: GetErrorFunction = (_c: Element | null, value) =>\n  `Found multiple elements with the aria-label attribute of: ${value}`;\nconst getMissingError: GetErrorFunction = (_c: Element | null, value) =>\n  `Unable to find an element with the aria-label attribute of: ${value}`;\n\nconst [\n  queryByAriaLabel,\n  getAllByAriaLabel,\n  getByAriaLabel,\n  findAllByAriaLabel,\n  findByAriaLabel,\n] = buildQueries(queryAllByAriaLabel, getMultipleError, getMissingError);\n\nexport {\n  queryByAriaLabel,\n  queryAllByAriaLabel,\n  getByAriaLabel,\n  getAllByAriaLabel,\n  findAllByAriaLabel,\n  findByAriaLabel,\n};\n"
  },
  {
    "path": "packages/test-utils/src/queryByAutoAdvanceAfter.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  queryAllByAttribute,\n  buildQueries,\n  type GetErrorFunction,\n  type Matcher,\n} from '@testing-library/react';\n\nconst queryAllByAutoAdvanceAfter = (container: HTMLElement, id: Matcher) =>\n  queryAllByAttribute('auto-advance-after', container, id);\n\nconst getMultipleError: GetErrorFunction = (_c: Element | null, value) =>\n  `Found multiple elements with the auto-advance-after attribute of: ${value}`;\nconst getMissingError: GetErrorFunction = (_c: Element | null, value) =>\n  `Unable to find an element with the auto-advance-after attribute of: ${value}`;\n\nconst [\n  queryByAutoAdvanceAfter,\n  getAllByAutoAdvanceAfter,\n  getByAutoAdvanceAfter,\n  findAllByAutoAdvanceAfter,\n  findByAutoAdvanceAfter,\n] = buildQueries(queryAllByAutoAdvanceAfter, getMultipleError, getMissingError);\n\nexport {\n  queryByAutoAdvanceAfter,\n  queryAllByAutoAdvanceAfter,\n  getByAutoAdvanceAfter,\n  getAllByAutoAdvanceAfter,\n  findAllByAutoAdvanceAfter,\n  findByAutoAdvanceAfter,\n};\n"
  },
  {
    "path": "packages/test-utils/src/queryById.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  queryAllByAttribute,\n  buildQueries,\n  type GetErrorFunction,\n  type Matcher,\n} from '@testing-library/react';\n\nconst queryAllById = (container: HTMLElement, id: Matcher) =>\n  queryAllByAttribute('id', container, id);\n\nconst getMultipleError: GetErrorFunction = (_c: Element | null, value) =>\n  `Found multiple elements with the id attribute of: ${value}`;\nconst getMissingError: GetErrorFunction = (_c: Element | null, value) =>\n  `Unable to find an element with the id attribute of: ${value}`;\n\nconst [queryById, getAllById, getById, findAllById, findById] = buildQueries(\n  queryAllById,\n  getMultipleError,\n  getMissingError\n);\n\nexport { queryById, queryAllById, getById, getAllById, findAllById, findById };\n"
  },
  {
    "path": "packages/test-utils/src/renderWithTheme.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, queries, type RenderOptions } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { theme } from '@googleforcreators/design-system';\nimport type { PropsWithChildren, ReactElement } from 'react';\n\n/**\n * Internal dependencies\n */\nimport * as ariaLabelQueries from './queryByAriaLabel';\nimport * as autoAdvanceAfterQueries from './queryByAutoAdvanceAfter';\nimport * as idQueries from './queryById';\n\nconst WithThemeProvider = ({ children }: PropsWithChildren<unknown>) => {\n  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;\n};\n\nfunction renderWithTheme(\n  ui: ReactElement,\n  options: Partial<Omit<RenderOptions, 'queries'>>\n) {\n  return render(ui, {\n    wrapper: WithThemeProvider,\n    queries: {\n      ...queries,\n      ...ariaLabelQueries,\n      ...autoAdvanceAfterQueries,\n      ...idQueries,\n    },\n    ...options,\n  });\n}\n\nexport default renderWithTheme;\n"
  },
  {
    "path": "packages/test-utils/src/typings/svg.d.ts",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare module '*.svg' {\n  import type { FunctionComponent, SVGProps } from 'react';\n  const ReactComponent: FunctionComponent<\n    SVGProps<SVGElement> & { title?: string }\n  >;\n  export default ReactComponent;\n}\n"
  },
  {
    "path": "packages/test-utils/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/text-sets/.npmignore",
    "content": "scripts\nsrc\n"
  },
  {
    "path": "packages/text-sets/README.md",
    "content": "# Text sets\n\nThis package contains the text sets used by the editor.\n\n## Generating images for text sets\n\n_Note: This script requires the development environment to be running with `WEB_STORIES_DISABLE_OPTIMIZED_RENDERING` so the text sets are rendered as components not images._\n\nRun `npm run workflow:render-text-sets` to generate and save text sets images in the `build/text-sets/` folder.\nThen move and commit the images to the [GoogleForCreators/wp.stories.google](https://github.com/GoogleForCreators/wp.stories.google) repo.\n"
  },
  {
    "path": "packages/text-sets/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/text-sets\",\n  \"description\": \"A set of predefined text combinations for use in the Web Stories editor.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/text-sets/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/text-sets\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/migration\": \"*\"\n  },\n  \"devDependencies\": {\n    \"puppeteer\": \"*\"\n  },\n  \"scripts\": {\n    \"render-text-sets\": \"node ./scripts/cli.js\"\n  }\n}\n"
  },
  {
    "path": "packages/text-sets/scripts/cli.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* eslint-disable no-await-in-loop, no-console */\n\n/**\n * External dependencies\n */\nimport fs from 'fs';\nimport puppeteer from 'puppeteer';\n\nconst screenshotsPath = `build/text-sets/`;\nfs.mkdirSync(screenshotsPath, { recursive: true });\n\n(async () => {\n  const browser = await puppeteer.launch({\n    defaultViewport: null,\n    headless: true,\n    args: [`--window-size=1600,800`],\n  });\n  const page = await browser.newPage();\n  await page.setViewport({\n    width: 1600,\n    height: 800,\n    deviceScaleFactor: 2,\n  });\n  await page.goto(\n    'http://localhost:8899/wp-admin/post-new.php?post_type=web-story'\n  );\n  await page.type('#user_login', 'admin');\n  await page.type('#user_pass', 'password');\n  await page.click('#wp-submit');\n  await page.waitForNavigation({ waitUntil: 'networkidle2' });\n  await page.waitForSelector('aria/Text library');\n  await page.click('aria/Text library');\n  await page.waitForSelector('aria/Text Set Options');\n  // Wait for fonts to load\n  await page.waitForTimeout(1000);\n\n  // Change BG of all TextSets container parents to transparent\n  await page.evaluateHandle(() => {\n    const el = document.querySelector(`[aria-label=\"Text Set Options\"]`);\n    let tempParent = el;\n    while (tempParent.parentNode) {\n      tempParent.style.transition = 'none';\n      tempParent.style.background = 'transparent';\n      tempParent = tempParent.parentNode;\n    }\n    return el;\n  });\n\n  // Focus on first TextSet\n  await page.focus(`[aria-label=\"Text Set Options\"] button:nth-child(1)`);\n\n  let lastTextSetId = null;\n  let textSetId;\n  while (lastTextSetId !== textSetId) {\n    lastTextSetId = textSetId;\n    // Generate PNG with transparent BG\n    const textSet = await page.evaluateHandle(() => {\n      const el = document.activeElement;\n      el.style.transition = 'none';\n      el.style.background = 'transparent';\n      el.style.borderRadius = 0;\n      el.parentNode.style.transition = 'none';\n      el.parentNode.style.background = 'transparent';\n      return el;\n    });\n    textSetId = (\n      await page.evaluate((obj) => {\n        return obj.getAttribute('data-testid');\n      }, textSet)\n    ).replace('text_set_', '');\n\n    if (lastTextSetId === textSetId) {\n      break;\n    }\n\n    await textSet.screenshot({\n      path: `${screenshotsPath}${textSetId}.png`,\n      omitBackground: true,\n    });\n    process.stdout.write('.');\n    await page.keyboard.press('ArrowRight');\n    await page.waitForTimeout(500);\n  }\n\n  await browser.close();\n  console.log(\n    `\\nText sets images generated in ${screenshotsPath}, please move and commit them to the GoogleForCreators/wp.stories.google repo.`\n  );\n})();\n\n/* eslint-enable */\n"
  },
  {
    "path": "packages/text-sets/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as loadTextSets } from './loadTextSets';\nexport * from './types';\n"
  },
  {
    "path": "packages/text-sets/src/loadTextSets.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { migrate } from '@googleforcreators/migration';\nimport type { Element } from '@googleforcreators/elements';\nimport { ElementType } from '@googleforcreators/elements';\n/**\n * Internal dependencies\n */\nimport type { MinMax, TextSet, TextSetData, TextSets } from './types';\nimport { TextSetType } from './types';\n\nfunction updateMinMax(minMax: MinMax, element: Element): MinMax {\n  // Purposely mutating object so passed\n  // in minMax is modified\n  minMax.minX = Math.min(minMax.minX, element.x);\n  minMax.maxX = Math.max(minMax.maxX, element.x + element.width);\n\n  minMax.minY = Math.min(minMax.minY, element.y);\n  minMax.maxY = Math.max(minMax.maxY, element.y + element.height);\n\n  return minMax;\n}\n\nasync function loadTextSet(name: string) {\n  const data: TextSetData = (await import(\n    /* webpackChunkName: \"chunk-web-stories-textset-[index]\" */ `./raw/${name}.json`\n  )) as TextSetData;\n  const migrated = migrate(data, data.version) as TextSetData;\n  return migrated.pages.reduce((sets: TextSet[], page) => {\n    const minMax = {\n      minX: Number.POSITIVE_INFINITY,\n      maxX: 0,\n      minY: Number.POSITIVE_INFINITY,\n      maxY: 0,\n    };\n\n    const textElements = page.elements.filter(\n      ({ type }) => type === ElementType.Text\n    );\n    textElements.forEach((element) => updateMinMax(minMax, element));\n\n    return [\n      ...sets,\n      {\n        textSetFonts: page.fonts,\n        id: page.id,\n        textSetCategory: name,\n        elements: textElements.map((e) => ({\n          ...e,\n          // Offset elements so the text set's\n          // default position is (0,0)\n          normalizedOffsetX: e.x - minMax.minX,\n          normalizedOffsetY: e.y - minMax.minY,\n          // The overall text set width & height\n          // is the delta between the max/mins\n          textSetWidth: minMax.maxX - minMax.minX,\n          textSetHeight: minMax.maxY - minMax.minY,\n        })),\n      },\n    ];\n  }, []);\n}\n\nexport default async function loadTextSets() {\n  const textSets: TextSets = {} as TextSets;\n\n  await Promise.all(\n    Object.values(TextSetType).map(async (name) => {\n      textSets[name] = await loadTextSet(name);\n    })\n  );\n\n  return textSets;\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/contact.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6011dfe7-3af2-4210-bf24-b4b507b32bae\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Contact us</span>\",\n          \"marginOffset\": 2.8187500000000014,\n          \"x\": 40,\n          \"y\": 399,\n          \"width\": 332,\n          \"height\": 25,\n          \"id\": \"09647017-4ea7-4ccd-978b-6c23de4e04a3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 1, \"vertical\": 1 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">example@google.com</span>\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 40,\n          \"y\": 429,\n          \"width\": 332,\n          \"height\": 23,\n          \"id\": \"4604b8b1-3d3a-467f-a24b-48a642dfe8f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Visit us</span>\",\n          \"marginOffset\": 2.8187500000000014,\n          \"x\": 40,\n          \"y\": 486,\n          \"width\": 332,\n          \"height\": 25,\n          \"id\": \"edad0881-bf20-49c7-a202-ea9305112608\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 1, \"vertical\": 1 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">example@google.com</span>\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 40,\n          \"y\": 516,\n          \"width\": 332,\n          \"height\": 23,\n          \"id\": \"737b0d7c-1bf9-40ed-8bd0-c394f72ceba2\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"4aa11112-fc48-41f6-a760-7b402af17bcd\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"707908a6-ae23-44de-b161-a7b866d5201a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Contact us</span>\",\n          \"marginOffset\": 4.4460000000000015,\n          \"x\": 40,\n          \"y\": 434,\n          \"width\": 165,\n          \"height\": 23,\n          \"id\": \"ad6afbe7-6971-4362-a05a-26707272852f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"mailaddress@google.com\",\n          \"marginOffset\": 3.211000000000002,\n          \"x\": 167,\n          \"y\": 434,\n          \"width\": 205,\n          \"height\": 23,\n          \"id\": \"37bf07b3-4fc3-406a-ada0-6be3b7162cb5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Visit us</span>\",\n          \"marginOffset\": 4.4460000000000015,\n          \"x\": 40,\n          \"y\": 477,\n          \"width\": 61,\n          \"height\": 23,\n          \"id\": \"99e6ff9e-f7f9-40c0-8960-2a49893e67a9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"example@google.com\",\n          \"marginOffset\": 0.799000000000003,\n          \"x\": 192,\n          \"y\": 477,\n          \"width\": 180,\n          \"height\": 22,\n          \"id\": \"6330c524-34c0-4ee9-9e68-ce63eba8c5e0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 425,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"af088132-0712-460f-a124-d1cf91009e51\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 512,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e85b401d-f25d-4464-85f6-5fec535fc77f\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"0c6be4c9-bcbc-415a-b0d8-d9ed9bb49aa1\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7bb33ef8-6a63-4f4c-a520-01f08581cf32\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">example.google.com</span>\",\n          \"marginOffset\": 0,\n          \"x\": 40,\n          \"y\": 429,\n          \"width\": 332,\n          \"height\": 23,\n          \"id\": \"174e8726-e67e-48dd-a27e-2a16a29cbc11\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">Visit our website</span>\",\n          \"marginOffset\": 1.5,\n          \"x\": 40,\n          \"y\": 398,\n          \"width\": 332,\n          \"height\": 26,\n          \"id\": \"f523bd67-d78c-42a0-a81b-630b5022f480\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 16, \"vertical\": 16 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff; text-transform: uppercase\\\">Contact Us</span>\",\n          \"marginOffset\": -3,\n          \"x\": 127,\n          \"y\": 477,\n          \"width\": 158,\n          \"height\": 58,\n          \"id\": \"728642af-987d-43c2-875e-e181adc073c3\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"IBM Plex Sans\", \"Poppins\"],\n      \"id\": \"0801b50a-1fa2-426b-9763-c1e43615906e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"06f2376c-5c38-4768-bacd-b0b74abe87c8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 231, \"g\": 231, \"b\": 231 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 10, \"vertical\": 10 },\n          \"type\": \"text\",\n          \"content\": \"Contact us\",\n          \"marginOffset\": 6.847000000000001,\n          \"x\": 109,\n          \"y\": 482,\n          \"width\": 200,\n          \"height\": 46,\n          \"id\": \"48fe75c3-e1da-4ee0-87e7-68c84e5283e9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 10, \"vertical\": 10 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">Subscribe</span>\",\n          \"marginOffset\": 6.179000000000002,\n          \"x\": 109,\n          \"y\": 418,\n          \"width\": 200,\n          \"height\": 47,\n          \"id\": \"32da77d9-6f7e-4867-989e-8eba96ed1572\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\"],\n      \"id\": \"ae7116bf-67ac-4ceb-b7f4-16bee1f79b55\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7cea1657-52d1-4ecc-9a63-c51be8832e58\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 24,\n          \"y\": 373,\n          \"width\": 364,\n          \"height\": 189,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"28749f86-aaf3-45b2-914a-2ac3d88d907d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">Contact</span>\",\n          \"x\": 41,\n          \"y\": 388,\n          \"width\": 160,\n          \"height\": 40,\n          \"id\": \"9246e079-47a7-448b-b195-14e11793171a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">111 8th Avenue New York, NY 10011</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 41,\n          \"y\": 437,\n          \"width\": 332,\n          \"height\": 21,\n          \"id\": \"ef8ce9a1-e268-4a70-89fc-19e39dfd5116\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">+1 212-565-0000</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 41,\n          \"y\": 464,\n          \"width\": 332,\n          \"height\": 21,\n          \"id\": \"30fb1555-837d-4c5c-8f06-bdd7cf460a51\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline; color: #fff\\\">mailaddress@google.com</span>\\n<span style=\\\"text-decoration: underline; color: #fff\\\">example.google.com</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 41,\n          \"y\": 491,\n          \"width\": 332,\n          \"height\": 48,\n          \"id\": \"ee329a7c-ba7e-49fa-962f-d2179695bb93\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 428,\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"364c6804-6760-48ca-9ffc-f820d5aec1d4\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"f8c296f8-5ede-4048-befd-5b7b1b86a19f\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a1e761b8-15b3-4238-ab8b-ade718751408\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase\\\">Contact Us</span>\",\n          \"marginOffset\": 4.068000000000001,\n          \"x\": 40,\n          \"y\": 382,\n          \"width\": 332,\n          \"height\": 21,\n          \"id\": \"66168e46-7eb1-45e6-9981-8611ca0859a3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 3, \"vertical\": 3 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">twitter.com/accountname</span>\\n<span style=\\\"text-decoration: underline\\\">example.google.com</span>\",\n          \"marginOffset\": 6.860000000000003,\n          \"x\": 40,\n          \"y\": 501,\n          \"width\": 331,\n          \"height\": 54,\n          \"id\": \"92b59e67-9b7f-476a-97d0-9c14867874ec\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"111 8th Avenue New York, NY 10011\",\n          \"marginOffset\": 9.963000000000001,\n          \"x\": 40,\n          \"y\": 415,\n          \"width\": 331,\n          \"height\": 73,\n          \"id\": \"b6096634-8012-4044-b512-8254561d961f\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\"],\n      \"id\": \"9dad0a18-20ba-4a8f-9505-bdaa3d4b69bc\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"356fa714-e8cc-4fe6-9394-7d7bb64ec640\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">example.google.com</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 40,\n          \"y\": 533,\n          \"width\": 332,\n          \"height\": 41,\n          \"id\": \"c6e94562-0e47-4ef4-8990-563f5cc70d77\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"or visit us at\",\n          \"marginOffset\": 7.193999999999999,\n          \"x\": 40,\n          \"y\": 506,\n          \"width\": 332,\n          \"height\": 19,\n          \"id\": \"f71dec9a-e771-4587-96e2-927c836a336e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 18, \"vertical\": 18 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Like &amp; Subscribe!</span>\",\n          \"marginOffset\": -11.235,\n          \"x\": 75,\n          \"y\": 413,\n          \"width\": 262,\n          \"height\": 76,\n          \"id\": \"3c52b35a-f5f2-4e90-a29d-fc6d371a1869\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\"],\n      \"id\": \"4bb3f3b4-8312-4faa-993c-4f538bcef9b0\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c43443c6-384a-4870-b603-484ed394bc76\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Follow us</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 65,\n          \"y\": 410,\n          \"width\": 283,\n          \"height\": 21,\n          \"id\": \"ccad6ee1-1243-4ed4-8e6f-3eb91a62f5e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">twitter.com/accountname</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 65,\n          \"y\": 437,\n          \"width\": 283,\n          \"height\": 21,\n          \"id\": \"a272fb1d-4b6d-45d5-b067-222b93f98030\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Visit us</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 65,\n          \"y\": 480,\n          \"width\": 283,\n          \"height\": 21,\n          \"id\": \"ad12f628-ec59-45ff-ac73-0a43a7dadbc4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-decoration: underline\\\">example.google.com</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 65,\n          \"y\": 507,\n          \"width\": 283,\n          \"height\": 21,\n          \"id\": \"f6615a8e-5957-468e-8769-6cfab5355a59\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Karla\"],\n      \"id\": \"b85c3d39-f7c5-4805-a353-022e9198f216\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6edd9495-ba69-4832-96cb-1abccb583f6e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 232, \"b\": 113, \"a\": 0.75 }\n          },\n          \"type\": \"shape\",\n          \"width\": 132,\n          \"height\": 132,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"8c2e5518-1e64-4f15-903b-a6d48eb2e7d0\",\n          \"x\": 93,\n          \"y\": 319\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 185, \"g\": 239, \"b\": 229, \"a\": 0.75 }\n          },\n          \"type\": \"shape\",\n          \"width\": 88,\n          \"height\": 88,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"3891a08e-5f02-4389-a3bf-11511a2f7cb1\",\n          \"x\": 198,\n          \"y\": 427\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 135, \"b\": 135, \"a\": 0.75 }\n          },\n          \"type\": \"shape\",\n          \"width\": 76,\n          \"height\": 76,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"06ebadf6-1c6f-422c-9d34-8cd390650ff9\",\n          \"x\": 242,\n          \"y\": 347\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #434343; letter-spacing: 0.02em; text-transform: uppercase\\\">Kids Summer</span>\",\n          \"width\": 174,\n          \"height\": 28,\n          \"id\": \"e87eb600-80ca-4009-b6db-23e84d343dd7\",\n          \"x\": 119,\n          \"y\": 287\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Henny Penny\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2324,\n              \"des\": -1305,\n              \"tAsc\": 2324,\n              \"tDes\": -1305,\n              \"tLGap\": 0,\n              \"wAsc\": 2324,\n              \"wDes\": 1305,\n              \"xH\": 1264,\n              \"capH\": 1794,\n              \"yMin\": -1305,\n              \"yMax\": 2324,\n              \"hAsc\": 2324,\n              \"hDes\": -1305,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #434343; letter-spacing: 0.02em\\\">Outdoor</span>\\n<span style=\\\"color: #434343; letter-spacing: 0.02em\\\">Camp Party</span>\",\n          \"width\": 296,\n          \"height\": 155,\n          \"id\": \"22964fd7-dbf9-4ea3-a6fe-30b50af98a34\",\n          \"x\": 58,\n          \"y\": 347\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #434343\\\">April 4th, 2020 09:00 AM</span>\",\n          \"width\": 225,\n          \"height\": 21,\n          \"id\": \"7bc67a04-426e-4920-a017-0e4b6fb58514\",\n          \"x\": 94,\n          \"y\": 534\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #434343\\\">2118 Thornridge Cir. Syracuse, Connecticut 35624</span>\",\n          \"width\": 192,\n          \"height\": 35,\n          \"marginOffset\": 4.921875,\n          \"id\": \"afedc7ea-2f7c-4932-849d-241beaa8ba6d\",\n          \"x\": 110,\n          \"y\": 562\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Rubik\", \"Henny Penny\"],\n      \"id\": \"098967a3-f72e-4236-92e9-ec239467696f\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/cover.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"cd465622-1638-4bfe-80f1-4ef75ec289a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 1 } },\n          \"lineHeight\": 1.8,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": false, \"horizontal\": 3, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff; text-transform: uppercase\\\">Category</span>\",\n          \"marginOffset\": 11.306249999999999,\n          \"x\": 41,\n          \"y\": 348,\n          \"width\": 114,\n          \"height\": 21,\n          \"id\": \"fe03f64e-2976-45a0-a9fb-a477523ddf54\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Robots, Humanity's New Best Friend</span>\",\n          \"x\": 41,\n          \"y\": 385,\n          \"width\": 313,\n          \"height\": 144,\n          \"id\": \"fec4e47a-0f6d-48c3-9e3b-35f4ccd12d84\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">By Agatha Android</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 41,\n          \"y\": 545,\n          \"width\": 156,\n          \"height\": 21,\n          \"id\": \"3fc4426c-ef7b-4149-b420-4bf835697885\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">January 16, 2020</span>\",\n          \"x\": 41,\n          \"y\": 572,\n          \"width\": 160,\n          \"height\": 21,\n          \"id\": \"3fdad7d5-2aba-4901-b893-835253a11674\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"755f1d9e-aeb4-4c4d-ba7f-fac834434243\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"eaf76058-26a2-4c86-91ab-fc083041c971\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 33,\n          \"y\": 360,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"79d6bb35-390b-4ab1-9440-23bcb5a12cbd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase\\\">Category</span>\",\n          \"x\": 33,\n          \"y\": 373,\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"0ca88179-4c8a-40eb-a425-335aea48c82e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">The Local's Guide to San Francisco</span>\",\n          \"x\": 33,\n          \"y\": 399,\n          \"width\": 313,\n          \"height\": 84,\n          \"id\": \"747ea170-3d1b-4652-ac15-bbee4a882d86\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"By Cali Crystal &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;May 19, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 33,\n          \"y\": 499,\n          \"width\": 342,\n          \"height\": 17,\n          \"id\": \"3c0a2d83-d1bd-452a-834b-7de3c02a7788\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 33,\n          \"y\": 491,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"533a6377-3383-469f-8a16-bf8839619a7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 33,\n          \"y\": 523,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"845bb3db-26fc-4c8f-b3ab-0749479a1ae1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 144,\n          \"y\": 500,\n          \"width\": 1,\n          \"height\": 14,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"481812b5-b3b5-4c8c-acd5-49ab3c58ad9c\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\", \"Lato\"],\n      \"id\": \"04a57b5d-b702-48a2-9c30-53ab7efe2691\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"04fe3198-81fb-4832-a006-3da5526919a0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase\\\">Category</span>\",\n          \"x\": 33,\n          \"y\": 504,\n          \"width\": 140,\n          \"height\": 33,\n          \"id\": \"195687ca-1dfd-4829-b08b-33d0724cddde\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em\\\">Plants!</span>\\n<span style=\\\"font-weight: 700; letter-spacing: 0.03em\\\">Fresh Decor For Modern Homes</span>\",\n          \"x\": 33,\n          \"y\": 308,\n          \"width\": 313,\n          \"height\": 201,\n          \"id\": \"467bdf56-0df2-42c5-97eb-9e6eeb3440d5\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"By Fern Greenthumb\\nJanuary 31, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 33,\n          \"y\": 541,\n          \"width\": 146,\n          \"height\": 38,\n          \"id\": \"d07705f6-d260-4b59-95b9-2867be8ec7c3\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\"],\n      \"id\": \"d96cfe7f-359f-4916-b7c1-933da0b8e0df\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b2fc6127-8e85-47f5-8486-37897347a51b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 107,\n          \"y\": 380,\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6faa1e81-41ed-4525-b2f4-ee94b8feb5b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase\\\">Category</span>\",\n          \"x\": 151,\n          \"y\": 370,\n          \"width\": 112,\n          \"height\": 23,\n          \"id\": \"ec521544-fad3-47e2-a986-f6d7786de123\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 273,\n          \"y\": 380,\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ba000ba1-9ebb-4583-b388-a0e16dcbe9c0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"February 14, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 146,\n          \"y\": 545,\n          \"width\": 122,\n          \"height\": 19,\n          \"id\": \"a2c9de84-83e8-43d2-a26f-8c2f4002ca67\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase\\\">Healthy habits to find your authentic self</span>\",\n          \"x\": 48,\n          \"y\": 398,\n          \"width\": 313,\n          \"height\": 115,\n          \"id\": \"269d472f-976d-4207-90f0-4a8309f16861\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"By Dr. Lora Poppins\",\n          \"marginOffset\": 5.578125,\n          \"x\": 139,\n          \"y\": 525,\n          \"width\": 140,\n          \"height\": 19,\n          \"id\": \"c3ec2f27-c240-4496-812a-eb9e82b6a949\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Poppins\"],\n      \"id\": \"870a951e-c4d3-454e-970f-c1acd564ebbf\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"20b485df-e817-4791-bafa-8036e7b4e92e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 25,\n          \"y\": 335,\n          \"width\": 363,\n          \"height\": 266,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fa13ba90-e095-4508-a8a6-a83f5bebcf29\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #fff\\\">Category</span>\",\n          \"marginOffset\": -7.049999999999997,\n          \"x\": 40,\n          \"y\": 350,\n          \"width\": 112,\n          \"height\": 35,\n          \"id\": \"e8d26428-e5fc-4fe7-a1fc-e6e005bf4037\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 387,\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"51221f90-7fb2-4f31-9ca6-59893c45983c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; color: #fff; text-transform: uppercase\\\">A condensed guide to minimalism</span>\",\n          \"marginOffset\": -16.043999999999997,\n          \"x\": 41,\n          \"y\": 388,\n          \"width\": 287,\n          \"height\": 154,\n          \"id\": \"2375a3d4-4f13-4510-9612-893af7c538be\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 548,\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7ef733fc-9ee8-463f-9304-39737161db36\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">By Mary Apartment</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 41,\n          \"y\": 557,\n          \"width\": 163,\n          \"height\": 21,\n          \"id\": \"b5b6fa73-47d2-47b7-a8e8-4d4568999294\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">June 29, 2020</span>\",\n          \"marginOffset\": 5.578125,\n          \"x\": 272,\n          \"y\": 557,\n          \"width\": 122,\n          \"height\": 21,\n          \"id\": \"71dbc521-fca3-43dd-b35d-ad1d07947e84\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"92858448-5995-4490-9c7d-ae1a4cd66739\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ab5e7bb6-884d-451d-b1e1-cc0cbdb24464\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase\\\">Category</span>\",\n          \"marginOffset\": 4.068000000000001,\n          \"x\": 40,\n          \"y\": 385,\n          \"width\": 112,\n          \"height\": 21,\n          \"id\": \"35c2a188-b282-4493-bc73-5dcf73a78e77\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Coffee saved the world</span>\",\n          \"x\": 40,\n          \"y\": 418,\n          \"width\": 313,\n          \"height\": 90,\n          \"id\": \"267ef5db-ebee-4830-a7b2-a8b0afd85619\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caffeinated Historians\",\n          \"marginOffset\": 5.578125,\n          \"x\": 40,\n          \"y\": 528,\n          \"width\": 164,\n          \"height\": 18,\n          \"id\": \"42556cb4-5e8f-42e3-b186-7893405180c6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 219,\n          \"y\": 532,\n          \"width\": 1,\n          \"height\": 14,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9a3e70bb-45e1-465d-922b-06a9d0cf16c9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"January 31, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 232,\n          \"y\": 528,\n          \"width\": 164,\n          \"height\": 18,\n          \"id\": \"8eb89dc5-ef0c-4167-8204-42c8b0ba62c8\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\"],\n      \"id\": \"970f0745-cd88-4500-a663-4331a97d1b4e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"72f7af44-2551-43ba-a467-99d02bab7b9c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: rgba(0,0,0,0.15)\\\">All Work Should Be Play</span>\",\n          \"x\": 44,\n          \"y\": 363,\n          \"width\": 313,\n          \"height\": 112,\n          \"id\": \"a08bb658-d031-4dd4-9770-79cfcb13d600\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900\\\">All Work Should Be Play</span>\",\n          \"x\": 41,\n          \"y\": 359,\n          \"width\": 313,\n          \"height\": 112,\n          \"id\": \"e861676a-0d4d-498c-a68d-06ad5cd702ee\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"By Industry Standard\\nJanuary 31, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 121,\n          \"y\": 478,\n          \"width\": 176,\n          \"height\": 44,\n          \"id\": \"5de75e6e-b0ca-454c-9a6f-0efb44758caf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 525,\n              \"capH\": 700,\n              \"yMin\": -262,\n              \"yMax\": 1043,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 2, \"vertical\": 2 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.01em; text-transform: uppercase\\\">Category</span>\",\n          \"x\": 129,\n          \"y\": 543,\n          \"width\": 149,\n          \"height\": 28,\n          \"id\": \"55b2ecb8-a727-4799-ae32-2e07fd832540\",\n          \"border\": {\n            \"left\": 4,\n            \"right\": 4,\n            \"top\": 4,\n            \"bottom\": 4,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } }\n          }\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\", \"Montserrat\"],\n      \"id\": \"f9edfdfb-84c5-48eb-8a55-8377d634102e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f072f639-3c0d-4394-acde-744edf74043d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": {\n            \"color\": { \"r\": 255, \"g\": 255, \"b\": 255, \"a\": 0 }\n          },\n          \"type\": \"shape\",\n          \"border\": {\n            \"left\": 1,\n            \"right\": 1,\n            \"top\": 1,\n            \"bottom\": 1,\n            \"lockedWidth\": true,\n            \"color\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n            \"position\": \"inside\"\n          },\n          \"x\": 17,\n          \"y\": 331,\n          \"width\": 380,\n          \"height\": 273,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"aca88807-e0f2-46ed-81ef-9a8ddd330a2e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">Hairstyle Hacks for Lazy Ladies</span>\",\n          \"marginOffset\": -6.068000000000005,\n          \"x\": 41,\n          \"y\": 375,\n          \"width\": 331,\n          \"height\": 92,\n          \"id\": \"b8546fb4-62be-4d60-b344-f3b8bf416a0d\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 109,\n          \"y\": 487,\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bc0bd49b-26b1-48e7-ab7f-8f930d6692bf\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.2em; text-transform: uppercase\\\">Category</span>\",\n          \"x\": 151,\n          \"y\": 477,\n          \"width\": 112,\n          \"height\": 22,\n          \"id\": \"3bea13e4-f64f-4830-9078-3bf88169f1d5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 271,\n          \"y\": 487,\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2db26456-cef4-4a3d-a16b-b4e797cd7573\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 15,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"By Style-ish Mag October 12, 2020\",\n          \"marginOffset\": 5.578125,\n          \"x\": 125,\n          \"y\": 518,\n          \"width\": 159,\n          \"height\": 39,\n          \"id\": \"66588fa9-1271-483c-b6b5-6376d33409bc\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"206d1872-6bb1-48e0-bf90-349595c84825\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"199de043-4703-40b7-a87f-bcdc65715e51\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Anton\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1138,\n              \"des\": -329,\n              \"tAsc\": 1138,\n              \"tDes\": -329,\n              \"tLGap\": 0,\n              \"wAsc\": 1176,\n              \"wDes\": 329,\n              \"xH\": 732,\n              \"capH\": 859,\n              \"yMin\": -326,\n              \"yMax\": 1404,\n              \"hAsc\": 1138,\n              \"hDes\": -329,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 153 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 4, \"vertical\": 4 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.02em; text-transform: uppercase\\\">Hot Gossip Article</span>\",\n          \"marginOffset\": -9.340000000000003,\n          \"x\": 40,\n          \"y\": 328,\n          \"width\": 159,\n          \"height\": 35,\n          \"id\": \"e840bda8-086c-4074-9254-9e027872adfe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Anton\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1138,\n              \"des\": -329,\n              \"tAsc\": 1138,\n              \"tDes\": -329,\n              \"tLGap\": 0,\n              \"wAsc\": 1176,\n              \"wDes\": 329,\n              \"xH\": 732,\n              \"capH\": 859,\n              \"yMin\": -326,\n              \"yMax\": 1404,\n              \"hAsc\": 1138,\n              \"hDes\": -329,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #f09; letter-spacing: 0.02em; text-transform: uppercase\\\">Celebrities Who Love Pizza</span>\",\n          \"x\": 40,\n          \"y\": 371,\n          \"width\": 332,\n          \"height\": 186,\n          \"id\": \"8e4f558d-688a-4b35-8e09-e68b3f0c2174\",\n          \"tagName\": \"h1\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Anton\"],\n      \"id\": \"f99ae41b-b824-4b19-873e-ce5b9b5d68c8\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d7a2fc7b-6127-4e58-8286-e9793dce4840\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 308,\n          \"width\": 332,\n          \"height\": 272,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"642f946d-8680-4cc9-b27b-5eb3020e555b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 58,\n          \"y\": 376,\n          \"width\": 298,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"41ace95f-a644-4bd8-b37e-2d070d785583\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 57,\n          \"y\": 506,\n          \"width\": 298,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"059839ab-6d9d-4863-82c0-9b73eefb307b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 58,\n          \"y\": 403,\n          \"width\": 139,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dbd0d68a-0248-400e-aeed-278c68e3b6b3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 217,\n          \"y\": 403,\n          \"width\": 139,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3bbc2a0b-b250-4f96-a546-74db9fb64cda\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 205,\n          \"y\": 401,\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"42309eaf-cfb9-44e8-bdc2-def12ffac619\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Open Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 600, 700, 800],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 1567,\n              \"tDes\": -492,\n              \"tLGap\": 132,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1096,\n              \"capH\": 1462,\n              \"yMin\": -555,\n              \"yMax\": 2146,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.08em; text-transform: uppercase\\\">Team Presents</span>\",\n          \"x\": 149,\n          \"y\": 383,\n          \"width\": 114,\n          \"height\": 17,\n          \"id\": \"5d086af1-18da-4534-a717-202bee670b61\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"UnifrakturMaguntia\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1607,\n              \"des\": -513,\n              \"tAsc\": 1607,\n              \"tDes\": -514,\n              \"tLGap\": 0,\n              \"wAsc\": 1607,\n              \"wDes\": 512,\n              \"xH\": 1095,\n              \"capH\": 1409,\n              \"yMin\": -496,\n              \"yMax\": 1906,\n              \"hAsc\": 1607,\n              \"hDes\": -513,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #d9b24d\\\">Rock Festival</span>\",\n          \"x\": 55,\n          \"y\": 419,\n          \"width\": 302,\n          \"height\": 55,\n          \"id\": \"15688993-939f-4cb6-a1bf-82bbf63a0041\",\n          \"tagName\": \"h1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; text-transform: uppercase\\\">Marvin Mckinney</span>\",\n          \"marginOffset\": 2.504999999999999,\n          \"x\": 40,\n          \"y\": 474,\n          \"width\": 332,\n          \"height\": 24,\n          \"id\": \"f29a5c72-1f88-45d0-af15-7803a1fd8a0b\"\n        }\n      ],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Open Sans\", \"UnifrakturMaguntia\", \"Playfair Display\"],\n      \"id\": \"56e39edb-0d25-4186-b950-76d5c1536651\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/editorial.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5af75aa3-94b9-42a5-8786-fbcf9649c568\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"We've always dreamed of autonomous friends and helpers. The idea of non-human servants and companions date at least as far back as ancient mythologies. One being mechanical handmaidens built by the Greek god Hephaestus.\",\n          \"x\": 40,\n          \"y\": 409,\n          \"width\": 332,\n          \"height\": 156,\n          \"id\": \"b16d8411-cf94-4bb8-92ac-e7a800763005\",\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 37,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Artificial Love?</span>\",\n          \"x\": 40,\n          \"y\": 350,\n          \"width\": 332,\n          \"height\": 43,\n          \"id\": \"dff0913d-9a7a-4a40-b3b2-efb2d35a6a1b\",\n          \"marginOffset\": 1.0406249999999986\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"8de5a540-9aa2-4532-b1de-87f071ccdd1a\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e3f68470-4155-4e9b-8121-5f744b23e76d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">Left my heart</span>\",\n          \"x\": 40,\n          \"y\": 353,\n          \"width\": 332,\n          \"height\": 39,\n          \"id\": \"5866ef82-08bf-40fa-87b2-89e2270aeda6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The City by the Bay captures the love of over 25 million visitors each year! Charming, chilly and creative, there's no other place like it. Ensure you're making the most of your travels by following this local's guide to fun, food and bus fare.\",\n          \"x\": 40,\n          \"y\": 423,\n          \"width\": 332,\n          \"height\": 158,\n          \"id\": \"0706b1b6-fc33-4e21-a9a2-64ba4507ff30\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 146,\n          \"y\": 406,\n          \"width\": 120,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6596c712-bc3a-4e5b-8438-74ee1b941b65\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"7ec0f8c7-5226-4fac-bef5-82755b0d72cc\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"fec7c152-8198-4bc3-aba1-6acffd8e1ca6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; text-transform: uppercase\\\">Find Your Roots</span>\",\n          \"width\": 332,\n          \"height\": 43,\n          \"id\": \"6fd28db6-2c6b-46c0-ae0b-707af1d36f3f\",\n          \"x\": 40,\n          \"y\": 359,\n          \"marginOffset\": -6.399999999999999\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Have you ever felt like you're living in a house but not a home? If yes, you're not alone! Creating a space that looks as good as it feels isn't easy, and it's often not just about what you put in it. Introducing plants not only brightens a space, they form a ritual of care.\",\n          \"width\": 332,\n          \"height\": 172,\n          \"id\": \"d93c3f60-5073-4e36-9c0f-aeffe4205266\",\n          \"x\": 40,\n          \"y\": 412,\n          \"marginOffset\": 3.3999999999999986\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"87936ffe-2e44-44d5-8f4a-93f28a4e5cfc\",\n          \"x\": 40,\n          \"y\": 339\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"IBM Plex Sans\"],\n      \"id\": \"2ce3fbcf-b0ec-4ae9-9e37-e46b94b4856e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f4bd63eb-47f0-454c-8734-7d8d4b5461fa\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.04em\\\">Change Focus</span>\",\n          \"width\": 331,\n          \"height\": 36,\n          \"id\": \"ad27512c-2018-404f-9cdd-007a89cb8288\",\n          \"x\": 40,\n          \"y\": 362,\n          \"marginOffset\": -3.591000000000001\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"We all have goals, but keeping your attention only on the destination means you miss the journey. Instead of seeing your daily life as a means to an end, take a step back and identify the place you've already arrived. Gratefulness practices help you focus in on what's important.\",\n          \"width\": 332,\n          \"height\": 171,\n          \"id\": \"dba6a0b2-7487-4ee4-bd05-6c6aeb6b246e\",\n          \"x\": 40,\n          \"y\": 410,\n          \"marginOffset\": 3.7399999999999984\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Lora\"],\n      \"id\": \"64fde279-f5b3-4501-88c1-88e9ae28c698\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2e117f4a-9267-407b-bd02-08203dbc960c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Start Simple</span>\",\n          \"width\": 332,\n          \"height\": 38,\n          \"id\": \"598702ed-bbd1-4744-8e8d-4a1f00ba41b5\",\n          \"x\": 40,\n          \"y\": 372,\n          \"marginOffset\": -7.614000000000004\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Getting started with minimalism is easy; if you don't love it and you don't use it, let it go. There isn't a science, you don't need a style, you just need to start noticing. Keep track of what stands out and if it leaves you wit positive or negative feelings.\",\n          \"width\": 332,\n          \"height\": 156,\n          \"id\": \"b72f7521-ac44-48be-857b-92c41b4c959d\",\n          \"x\": 40,\n          \"y\": 420\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5708edac-534f-4341-9870-33a7688d0d5a\",\n          \"x\": 40,\n          \"y\": 355\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"0249900f-0801-4cf2-904b-9eb505784148\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"733af034-220b-4232-894c-2550379f11a1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Before the bean\",\n          \"width\": 332,\n          \"height\": 34,\n          \"id\": \"2bbf9a2d-cc99-4c08-b6d2-0662761f12bc\",\n          \"x\": 40,\n          \"y\": 354\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Humans need water! Before coffee the most common way to drink water safely was by fermenting it, usually by brewing beer. Humanity spent most of it's early industry years a little tipsy. Introducing coffee morphed the type of buzz we began our day with.\",\n          \"width\": 332,\n          \"height\": 170,\n          \"id\": \"02a14cfc-5936-462f-a79e-ffca46c2dd7f\",\n          \"x\": 40,\n          \"y\": 405,\n          \"marginOffset\": 5.831000000000003\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Merriweather\"],\n      \"id\": \"7193ad78-832b-470b-90fd-c856334ee56a\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d34c4e1a-4ef0-4f15-8620-f842858e1a3a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: rgba(0,0,0,0.15)\\\">Always recess</span>\",\n          \"width\": 332,\n          \"height\": 54,\n          \"id\": \"c05092f4-7822-416c-98a6-44858a1a9069\",\n          \"x\": 44,\n          \"y\": 357\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900\\\">Always recess</span>\",\n          \"width\": 332,\n          \"height\": 54,\n          \"id\": \"ae3d8b77-a89a-441e-a735-24d256ab1e3d\",\n          \"x\": 40,\n          \"y\": 353\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Every kid's favorite subject in school is recess! Why shouldn't it be? Who doesn't like designated time to hang with your friends, meet new ones, and play fun games? Read on to find out how bring the benefits recess brings to students into your office.\",\n          \"width\": 332,\n          \"height\": 163,\n          \"id\": \"1cbbe1a0-99b7-4fac-9eb5-18dbfc50272d\",\n          \"x\": 40,\n          \"y\": 409,\n          \"marginOffset\": 5.5589999999999975\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\"],\n      \"id\": \"f6204eaa-9008-45ca-9559-17a6e43efc33\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"1391f8a5-7162-4ac7-bdb0-7ad1832b93d6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Breezy beauty</span>\",\n          \"width\": 332,\n          \"height\": 41,\n          \"id\": \"ee1c31cf-c782-4cd7-9bd9-7ebc08f01fed\",\n          \"x\": 40,\n          \"y\": 363,\n          \"marginOffset\": -7.920000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The lazy life is all about maximum reward with minimum effort. But when it comes to hair, where's the balance between effortless style and no style effort? Well, we've done the work for you! Read on for our best hairstyle hacks.\",\n          \"width\": 332,\n          \"height\": 144,\n          \"id\": \"f2d01d29-e755-4634-b346-e0a2682f159d\",\n          \"x\": 40,\n          \"y\": 413,\n          \"marginOffset\": 5.626999999999999\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"ea7b0add-02a4-4746-8c5c-d9422f096533\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b5cd1ddc-ca45-4f21-808f-404048eaf877\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 288,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"da5457e6-a055-402e-bf12-7ad0b482c2fd\",\n          \"x\": 61.5,\n          \"y\": 373\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 230, \"g\": 204, \"b\": 71 } },\n          \"type\": \"shape\",\n          \"width\": 288,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1a697864-c11c-47c3-8ac8-c2d032530544\",\n          \"x\": 61.5,\n          \"y\": 382\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 288,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c48a35bf-0386-4138-b065-24831d69b92d\",\n          \"x\": 60,\n          \"y\": 507\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 230, \"g\": 204, \"b\": 71 } },\n          \"type\": \"shape\",\n          \"width\": 288,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"da49cb47-73d1-4830-993e-f7aa9d51e2ac\",\n          \"x\": 60,\n          \"y\": 498\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">10</span>\",\n          \"width\": 66,\n          \"height\": 99,\n          \"id\": \"bce65336-1bbb-40d6-bb61-7d19c9bbd777\",\n          \"x\": 61,\n          \"y\": 393\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Parisienne\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1875,\n              \"des\": -915,\n              \"tAsc\": 1875,\n              \"tDes\": -915,\n              \"tLGap\": 0,\n              \"wAsc\": 1875,\n              \"wDes\": 915,\n              \"xH\": 723,\n              \"capH\": 1558,\n              \"yMin\": -915,\n              \"yMax\": 1875,\n              \"hAsc\": 1875,\n              \"hDes\": -915,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #e6cc47\\\">Christmas</span>\",\n          \"width\": 187,\n          \"height\": 74,\n          \"id\": \"a4153098-8497-4247-ba31-a3283e244183\",\n          \"x\": 151,\n          \"y\": 401\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"letter-spacing: 0.04em; text-transform: uppercase\\\">Recommended Gifts</span>\",\n          \"width\": 190,\n          \"height\": 24,\n          \"id\": \"dc744d4c-1e81-420b-a596-dbc4b489d9b2\",\n          \"x\": 151,\n          \"y\": 462\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"Parisienne\"],\n      \"id\": \"b8a0da89-3304-4da6-a6f4-8208c39465f1\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c1ff35cb-5069-4685-a96a-ba26e1ce0573\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 278,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1902e4f1-5d9c-4d14-9e6a-718a1a3b6797\",\n          \"x\": 39,\n          \"y\": 304\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rock Salt\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 1623,\n              \"des\": -788,\n              \"tAsc\": 824,\n              \"tDes\": -240,\n              \"tLGap\": 63,\n              \"wAsc\": 1623,\n              \"wDes\": 788,\n              \"xH\": 833,\n              \"capH\": 1154,\n              \"yMin\": -787,\n              \"yMax\": 1623,\n              \"hAsc\": 1623,\n              \"hDes\": -788,\n              \"lGap\": 32\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff\\\">black friday</span>\",\n          \"width\": 332,\n          \"height\": 180,\n          \"id\": \"7704e046-0510-47ac-aabe-c65908a5e879\",\n          \"x\": 40,\n          \"y\": 328\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #ff5858; letter-spacing: 0.02em; text-transform: uppercase\\\">Sale</span>\",\n          \"width\": 160,\n          \"height\": 64,\n          \"id\": \"b13c515e-8d27-4bfe-bc2b-06ab72d27d34\",\n          \"x\": 121,\n          \"y\": 508\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Rock Salt\", \"Oswald\"],\n      \"id\": \"bfddf7b1-ea3a-4283-943f-7aa5340a3758\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"96b3c828-f0ec-439f-af7d-68a4cca261bd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #00c2ff; letter-spacing: 0.04em; text-transform: uppercase\\\">TV Show</span>\",\n          \"width\": 180,\n          \"height\": 50,\n          \"id\": \"31551cfe-d34a-465b-bd2d-1395c0916edc\",\n          \"x\": 116,\n          \"y\": 294\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Monoton\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2366,\n              \"des\": -822,\n              \"tAsc\": 2366,\n              \"tDes\": -822,\n              \"tLGap\": 0,\n              \"wAsc\": 2366,\n              \"wDes\": 822,\n              \"xH\": 1440,\n              \"capH\": 1656,\n              \"yMin\": -822,\n              \"yMax\": 2366,\n              \"hAsc\": 2366,\n              \"hDes\": -822,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #00c2ff; letter-spacing: 0.04em; text-transform: uppercase\\\">Pop</span>\\n<span style=\\\"color: #00c2ff; letter-spacing: 0.04em; text-transform: uppercase\\\">Quiz</span>\",\n          \"width\": 332,\n          \"height\": 180,\n          \"id\": \"b27aae73-7930-462a-a725-d5298785fcf1\",\n          \"x\": 40,\n          \"y\": 352\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #00c2ff\\\">How many of them</span>\\n<span style=\\\"color: #00c2ff\\\">can you guess correctly?</span>\",\n          \"width\": 332,\n          \"height\": 51,\n          \"marginOffset\": 5.578125,\n          \"id\": \"efaa436a-2d3b-4695-a966-90a6faae1878\",\n          \"x\": 40,\n          \"y\": 540\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"Monoton\"],\n      \"id\": \"43ef8035-151e-4a80-81d9-8ed746a2d2be\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"cf00f32a-0bb9-4746-8c80-a24e32fb8166\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #ffd600\\\">Week Trip </span><span style=\\\"font-weight: 900; color: #f69e4c\\\">to Hawaii</span>\",\n          \"width\": 322,\n          \"height\": 131,\n          \"id\": \"24d77029-a48d-4e60-8c5e-7c94d7333f86\",\n          \"x\": 45,\n          \"y\": 366\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nothing You Could Do\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1024,\n              \"asc\": 959,\n              \"des\": -407,\n              \"tAsc\": 962,\n              \"tDes\": -407,\n              \"tLGap\": 0,\n              \"wAsc\": 959,\n              \"wDes\": 407,\n              \"xH\": 462,\n              \"capH\": 758,\n              \"yMin\": -407,\n              \"yMax\": 959,\n              \"hAsc\": 959,\n              \"hDes\": -407,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #39999f\\\">Surf all day!</span>\",\n          \"width\": 322,\n          \"height\": 47,\n          \"id\": \"beeac3d7-6f8e-48bf-920d-2fa25861fb54\",\n          \"x\": 45,\n          \"y\": 505\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #4dbd58; letter-spacing: 0.02em; text-transform: uppercase\\\">A Quick Recap to Our</span>\",\n          \"width\": 322,\n          \"height\": 24,\n          \"id\": \"de3317df-e660-4d45-80aa-942e2a30d1b2\",\n          \"x\": 45,\n          \"y\": 334\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Nothing You Could Do\", \"Nunito\"],\n      \"id\": \"6825bee0-5867-4aee-8230-f3b73a6979c2\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4206e30c-64e1-463a-af93-602e54b57d14\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"BioRhyme\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 700, 800],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 800]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1127,\n              \"des\": -422,\n              \"tAsc\": 1127,\n              \"tDes\": -422,\n              \"tLGap\": 0,\n              \"wAsc\": 1127,\n              \"wDes\": 422,\n              \"xH\": 471,\n              \"capH\": 686,\n              \"yMin\": -369,\n              \"yMax\": 1117,\n              \"hAsc\": 1127,\n              \"hDes\": -422,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 43,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 800; letter-spacing: 0.04em\\\">Build an IoT System</span>\",\n          \"width\": 332,\n          \"height\": 114,\n          \"id\": \"413baa21-b89b-4df8-9756-1ade6e8e268b\",\n          \"x\": 40,\n          \"y\": 354\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Slab\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2146,\n              \"des\": -555,\n              \"tAsc\": 2146,\n              \"tDes\": -555,\n              \"tLGap\": 0,\n              \"wAsc\": 2146,\n              \"wDes\": 618,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2146,\n              \"hAsc\": 2146,\n              \"hDes\": -555,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Make your life easier</span>\\n<span style=\\\"font-weight: 700\\\">with automations</span>\",\n          \"width\": 332,\n          \"height\": 52,\n          \"id\": \"baddeb36-483e-442f-aab0-d3b8076c4ba9\",\n          \"x\": 40,\n          \"y\": 480\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"c5df890e-44e6-4ff1-bd3e-62aeb2862c5e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2827c4d2-8029-45e2-9e2d-e936fccb2221\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"highlights of\",\n          \"width\": 266,\n          \"height\": 30,\n          \"id\": \"7472564d-c9a0-475f-b23b-cecf0629c7b0\",\n          \"x\": 73,\n          \"y\": 344\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee Shade\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ff5c00; letter-spacing: 0.04em\\\">pc game night</span>\",\n          \"width\": 332,\n          \"height\": 113,\n          \"marginOffset\": 8.300000000000011,\n          \"id\": \"e5a66644-3349-4c9b-a076-710f9dd6c404\",\n          \"x\": 40,\n          \"y\": 382\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.04em\\\">july 20th, 2020</span>\",\n          \"width\": 191,\n          \"height\": 31,\n          \"marginOffset\": 8.5,\n          \"id\": \"caf051db-232a-4a3d-8fac-210178b958bd\",\n          \"x\": 111,\n          \"y\": 511\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"BioRhyme\", \"Roboto Slab\", \"Bungee\", \"Bungee Shade\"],\n      \"id\": \"52e8bbd5-0994-4fbc-a129-52e51fdbc831\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d367ac7b-3ea3-4405-8cfa-99404da93f26\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 412,\n          \"height\": 412,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"19b1fe3c-dd3e-4272-a2e2-04d6d18e6051\",\n          \"x\": 0,\n          \"y\": 236\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ffe600\\\">highlights of</span>\",\n          \"width\": 266,\n          \"height\": 31,\n          \"id\": \"b36ef221-ee84-431c-95a5-aa291bac6001\",\n          \"x\": 73,\n          \"y\": 344\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.04em\\\">pc game night</span>\",\n          \"width\": 332,\n          \"height\": 113,\n          \"marginOffset\": 8.300000000000011,\n          \"id\": \"2645f9cb-7054-437c-86ed-f979ffaeeeb8\",\n          \"x\": 40,\n          \"y\": 382\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Bungee\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 860,\n              \"des\": -140,\n              \"tAsc\": 860,\n              \"tDes\": -140,\n              \"tLGap\": 200,\n              \"wAsc\": 1634,\n              \"wDes\": 914,\n              \"xH\": 500,\n              \"capH\": 720,\n              \"yMin\": -916,\n              \"yMax\": 1636,\n              \"hAsc\": 860,\n              \"hDes\": -140,\n              \"lGap\": 200\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #fff; letter-spacing: 0.04em\\\">july 20th, 2020</span>\",\n          \"width\": 191,\n          \"height\": 32,\n          \"marginOffset\": 8.5,\n          \"id\": \"565d5249-cdfb-4ac2-942d-a892ea08cedd\",\n          \"x\": 110.5,\n          \"y\": 511\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Bungee\"],\n      \"id\": \"95970834-7a29-4066-9a8f-54f682868d64\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/list.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"ba73aa7d-ba78-4184-91b8-856b5bad57b8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"id\": \"a1621ecf-3b3f-4072-8e44-6bf2892eb0a6\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Robots in Film</span>\",\n          \"x\": 41,\n          \"y\": 214,\n          \"width\": 331,\n          \"height\": 30,\n          \"marginOffset\": 3.84375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"R2-D2, Star Wars\",\n          \"x\": 59,\n          \"y\": 261,\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"6dbe785d-0d5f-4a74-a796-3ba20950acbc\",\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The Terminator, The Terminator\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"23bf647b-1367-4703-b5e3-2be7cb857281\",\n          \"x\": 59,\n          \"y\": 292,\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Optimus Prime, Transformers\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"b21e7e88-2b19-4c1a-991d-43e3cb017f6c\",\n          \"x\": 59,\n          \"y\": 354\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"HAL, 2001: A Space Odyssey\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"df4f466a-320a-42c7-a460-7fab1a788c66\",\n          \"x\": 59,\n          \"y\": 323,\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Sonny, I. Robot\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"ab60497a-5f5c-4073-83e9-7b56df31c71f\",\n          \"x\": 59,\n          \"y\": 385\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 42,\n          \"y\": 269.5,\n          \"width\": 4,\n          \"height\": 4,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"a41f331f-29b5-40ca-b13f-eb02ae2634d4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 4,\n          \"height\": 4,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"3487e6a4-35e6-4158-ac09-74ffdbf06f05\",\n          \"x\": 42,\n          \"y\": 300.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 4,\n          \"height\": 4,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"822ccb27-1692-4d54-9cd7-8114202d440f\",\n          \"x\": 42,\n          \"y\": 331.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 4,\n          \"height\": 4,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"0bf25e9e-c30c-4513-a6b3-600984b89c08\",\n          \"x\": 42,\n          \"y\": 362.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 4,\n          \"height\": 4,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"083cd063-ec51-48f0-8553-23b244b1f2fa\",\n          \"x\": 42,\n          \"y\": 393.5\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"36f525c9-7d62-4f90-a663-35f475d63ea0\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f48c1fe1-7a9e-4449-a407-ed88e83e38e7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">Robots in Film</span>\",\n          \"width\": 331,\n          \"height\": 33,\n          \"marginOffset\": 3.84375,\n          \"id\": \"25cdb4d5-9a90-47fd-9dc0-e42adf6cf46d\",\n          \"x\": 41,\n          \"y\": 206\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"R2-D2, Star Wars\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"506b1f2a-64cf-4f8d-ad2e-0d585db3de84\",\n          \"x\": 59,\n          \"y\": 254\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The Terminator, The Terminator\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"069d0034-9e43-4305-8c19-6a91ec2007f2\",\n          \"x\": 59,\n          \"y\": 291\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Optimus Prime, Transformers\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"3d3a2a32-4a26-4231-9365-b8b03b34482e\",\n          \"x\": 59,\n          \"y\": 360\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"HAL, 2001: A Space Odyssey\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"550f7450-1280-4bf0-a5be-791adeb2e39b\",\n          \"x\": 59,\n          \"y\": 325\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Sonny, I. Robot\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"afa0aaf9-c202-4ed1-bc72-a89ad7cb1d05\",\n          \"x\": 59,\n          \"y\": 394\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"0964be69-8ad0-4823-b6cf-98a5885e32b6\",\n          \"x\": 42,\n          \"y\": 261.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"403a4895-6d52-47f6-9d91-708e6cfd39e9\",\n          \"x\": 42,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"bf08a5a1-a064-4e61-8581-564eecfeaca9\",\n          \"x\": 42,\n          \"y\": 369\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"14473a90-f95f-45ef-96f7-18103948af83\",\n          \"x\": 42,\n          \"y\": 334\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"ffb2856e-9edf-4827-8aa2-08b77283c868\",\n          \"x\": 42,\n          \"y\": 299\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"ff4c2b11-8d86-41f4-823c-9e8b40bec163\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6a9e01ad-5227-44b1-8aed-4abc8b00aa43\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 198,\n          \"width\": 32,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6522a49f-ceba-421a-9900-b9f265cd63f3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase\\\">Plant Care Apps</span>\",\n          \"x\": 41,\n          \"y\": 218,\n          \"width\": 331,\n          \"height\": 43,\n          \"id\": \"a7d0b1de-d0d4-4fa6-8970-9dca2c40f3b5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"PlantMi\",\n          \"width\": 313,\n          \"height\": 23,\n          \"id\": \"a91708d3-d694-4ee8-a970-614f89cc03b8\",\n          \"x\": 59,\n          \"y\": 277\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"GreenTime\",\n          \"width\": 313,\n          \"height\": 23,\n          \"id\": \"c5e3dba4-d89a-4c1a-b825-59bb5ce2de63\",\n          \"x\": 59,\n          \"y\": 308\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Wet Dyrt\",\n          \"width\": 313,\n          \"height\": 23,\n          \"id\": \"2a5ca2e1-7f72-4051-ba5f-3b9c3b1acdaa\",\n          \"x\": 59,\n          \"y\": 370\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Branch &amp; Leaf\",\n          \"width\": 313,\n          \"height\": 23,\n          \"id\": \"e6e625c5-0bd8-487f-9f42-23df549ede83\",\n          \"x\": 59,\n          \"y\": 339\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Rooted\",\n          \"width\": 313,\n          \"height\": 23,\n          \"id\": \"a23d31ee-6b31-4947-a9f3-0f8526b83d29\",\n          \"x\": 59,\n          \"y\": 401\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e198bccf-09f7-4dbb-8c9f-770865247239\",\n          \"x\": 42,\n          \"y\": 288\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f07e0d64-5372-4e51-86a6-0c3da7607dd4\",\n          \"x\": 42,\n          \"y\": 319\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"077d4e05-7c75-4d9c-9feb-f191deea147f\",\n          \"x\": 42,\n          \"y\": 350\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a94e39bf-2c23-4e6d-b409-9647b5f8bd98\",\n          \"x\": 42,\n          \"y\": 381\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fd9e9ae6-2d67-4973-8783-2128787a59a6\",\n          \"x\": 42,\n          \"y\": 412\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"IBM Plex Sans\"],\n      \"id\": \"2735a7bd-a814-45f9-b103-233eff39c478\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e6c264f2-1e4d-4c0e-a888-2e11370786a5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Know thyself\",\n          \"width\": 313,\n          \"height\": 21,\n          \"id\": \"5ee0db06-85f4-4ba9-94e8-7cdcd73fbfc8\",\n          \"x\": 59,\n          \"y\": 260,\n          \"marginOffset\": 3.7399999999999984\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Be kind\",\n          \"width\": 313,\n          \"height\": 21,\n          \"id\": \"9cf80e40-7ea6-437c-a0e6-72370e0463ee\",\n          \"x\": 59,\n          \"y\": 291,\n          \"marginOffset\": 3.7399999999999984\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Trust your gut\",\n          \"width\": 313,\n          \"height\": 21,\n          \"id\": \"2a306a0d-afc5-419a-b28c-d6bb3dbc100c\",\n          \"x\": 59,\n          \"y\": 353,\n          \"marginOffset\": 3.7399999999999984\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Bring your whole self\",\n          \"width\": 313,\n          \"height\": 21,\n          \"id\": \"bea9fcf7-ccc9-45f6-b3b3-607eeeb07c31\",\n          \"x\": 59,\n          \"y\": 322,\n          \"marginOffset\": 3.7399999999999984\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Practice Reflection\",\n          \"width\": 313,\n          \"height\": 21,\n          \"id\": \"6decd8bd-7f19-43cd-a035-7029629e9a22\",\n          \"x\": 59,\n          \"y\": 384,\n          \"marginOffset\": 3.7399999999999984\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase\\\">Essentials</span>\",\n          \"width\": 177,\n          \"height\": 31,\n          \"id\": \"a1b69a5a-0d61-49b9-8ba4-44daa7581e86\",\n          \"x\": 118,\n          \"y\": 209\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"71bc3869-8369-449e-b577-507e044b1eb3\",\n          \"x\": 304,\n          \"y\": 224.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7e373de9-463f-4f8d-b496-f37b6fba4ab4\",\n          \"x\": 74,\n          \"y\": 224.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e9380652-0931-43b3-b9cf-0119bb879e3d\",\n          \"x\": 42,\n          \"y\": 268.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"67090ebe-b763-4a7c-b6ed-fb515f82dc46\",\n          \"x\": 42,\n          \"y\": 392.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"519ad94e-4b2d-45d1-a6cb-dc469a986ffd\",\n          \"x\": 42,\n          \"y\": 361.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"9eb352a6-9245-46fc-881e-225dbae11c73\",\n          \"x\": 42,\n          \"y\": 330.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"1da2f2f4-26ce-4a4c-9c9a-af090d99b757\",\n          \"x\": 42,\n          \"y\": 299.5\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Lora\"],\n      \"id\": \"df215279-3127-47fa-a711-e6f24c48fc7e\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"acb87d14-27cb-46d6-a789-20584f61cab0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Declutter first\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"857cd7a6-8d25-433b-bf16-df9a0d9689d3\",\n          \"x\": 59,\n          \"y\": 265\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Organize second\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"47987511-94e3-4057-8741-6a333d5510df\",\n          \"x\": 59,\n          \"y\": 296\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Minimize distractions\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"8a36bc28-894b-43a7-a3e0-74f81c439233\",\n          \"x\": 59,\n          \"y\": 358\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Detach self-worth\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"9b20ab27-a660-491f-951b-232f6e095405\",\n          \"x\": 59,\n          \"y\": 327\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Practice patience\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"0f939067-5ee0-4fcf-9c42-bf5ec90b3896\",\n          \"x\": 59,\n          \"y\": 389\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; text-transform: uppercase\\\">The Principles</span>\",\n          \"width\": 331,\n          \"height\": 39,\n          \"id\": \"d7666a19-5643-406b-bc02-f5d9fd4b06a1\",\n          \"x\": 41,\n          \"y\": 210\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"9ae7cf81-c809-442a-b187-c7b6fef2c6a2\",\n          \"x\": 42,\n          \"y\": 273.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e61a76a3-dc95-4dc4-be65-b5fa98447ebd\",\n          \"x\": 42,\n          \"y\": 397.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"c0adee60-3c32-4cbc-9f77-5a6cdc0caaa5\",\n          \"x\": 42,\n          \"y\": 366.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"672d5a3a-1d48-427d-932b-4867b104c0f8\",\n          \"x\": 42,\n          \"y\": 335.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"c953b818-f7ff-4555-8caa-5faec28e800d\",\n          \"x\": 42,\n          \"y\": 304.5\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"91a206b8-1fc2-418f-89fa-faf0fa63f2b0\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"e73ad4f4-939f-4692-be69-6b011d372d71\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Drip coffee\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"b0d4bec7-761e-49e4-9287-9b0ebed6a8bc\",\n          \"x\": 59,\n          \"y\": 259,\n          \"marginOffset\": 4.374000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Espresso\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"d7cc69d2-833e-4fcb-9a18-e4ccc143b2b3\",\n          \"x\": 59,\n          \"y\": 290,\n          \"marginOffset\": 4.131\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Cappuccino\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"7b51d5a2-9a71-4335-b366-eb5a32080022\",\n          \"x\": 59,\n          \"y\": 352,\n          \"marginOffset\": 4.374000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Latte\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"3c6710e1-9212-4d0c-b2fb-dc69ce227cfd\",\n          \"x\": 59,\n          \"y\": 321,\n          \"marginOffset\": 4.374000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Americano\",\n          \"width\": 313,\n          \"height\": 22,\n          \"id\": \"0c94bdfd-fd68-464d-b26a-33b2bc8f3c85\",\n          \"x\": 59,\n          \"y\": 383,\n          \"marginOffset\": 4.374000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Coffee drinks\",\n          \"width\": 331,\n          \"height\": 34,\n          \"id\": \"b5b41d0f-51fe-477c-8dab-761c066762d4\",\n          \"x\": 41,\n          \"y\": 210\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"0a5df081-89db-4e49-87fe-95c3d841011d\",\n          \"x\": 42,\n          \"y\": 267.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"6cc27d85-0735-4d11-bcc1-958f9d046ec9\",\n          \"x\": 42,\n          \"y\": 391.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"55901f15-39ac-4a22-adf5-063e23158c9a\",\n          \"x\": 42,\n          \"y\": 360.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"3decaf02-890b-49ef-b433-8ceddd32434a\",\n          \"x\": 42,\n          \"y\": 329.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 5,\n          \"height\": 5,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"e44c5bd9-5c39-4602-ae60-4e2c67bef3f5\",\n          \"x\": 42,\n          \"y\": 298.5\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Merriweather\"],\n      \"id\": \"35d5cfbd-ec8f-4cd2-803f-c7f70c12aca4\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"48b4df6b-1a5a-44d4-a10f-0e5dc8dc1e8d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Stress relief\",\n          \"width\": 313,\n          \"height\": 19,\n          \"id\": \"6f6367c6-438a-4398-880d-28b474d5fd4f\",\n          \"x\": 59,\n          \"y\": 263,\n          \"marginOffset\": 5.5589999999999975\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Brain function\",\n          \"width\": 313,\n          \"height\": 19,\n          \"id\": \"5eca2380-50ff-4075-a511-7af1e968a8d9\",\n          \"x\": 59,\n          \"y\": 294,\n          \"marginOffset\": 5.5589999999999975\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Flourish relationships\",\n          \"width\": 313,\n          \"height\": 19,\n          \"id\": \"0a67dc94-8db8-4b0c-bfb1-0d0172f2cd1c\",\n          \"x\": 59,\n          \"y\": 356,\n          \"marginOffset\": 5.5589999999999975\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Creative boost\",\n          \"width\": 313,\n          \"height\": 19,\n          \"id\": \"90adf5cc-d567-428f-9bcb-b16a17fb52dc\",\n          \"x\": 59,\n          \"y\": 325,\n          \"marginOffset\": 5.5589999999999975\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Energized feelings\",\n          \"width\": 313,\n          \"height\": 19,\n          \"id\": \"440d1bf0-37d6-4638-a095-e74bbc6c00a2\",\n          \"x\": 59,\n          \"y\": 387,\n          \"marginOffset\": 5.5589999999999975\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Benefits of play</span>\",\n          \"width\": 331,\n          \"height\": 41,\n          \"id\": \"23a2eebf-b6e0-4b03-adb8-4a9a4e015a6d\",\n          \"x\": 41,\n          \"y\": 208,\n          \"marginOffset\": -11.366999999999997\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">+</span>\",\n          \"width\": 25,\n          \"height\": 23,\n          \"id\": \"5f66f577-5ba3-45e1-ae3c-6d0581a5e644\",\n          \"x\": 46,\n          \"y\": 258\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">+</span>\",\n          \"width\": 25,\n          \"height\": 23,\n          \"id\": \"98381e2f-b4b0-43dd-9b51-fa073ba77610\",\n          \"x\": 46,\n          \"y\": 290\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">+</span>\",\n          \"width\": 25,\n          \"height\": 23,\n          \"id\": \"02cd45b1-c37b-4da2-a326-161947df271f\",\n          \"x\": 46,\n          \"y\": 321\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">+</span>\",\n          \"width\": 25,\n          \"height\": 23,\n          \"id\": \"3bb4786e-ceac-44e5-8b4b-e716bf6fb349\",\n          \"x\": 46,\n          \"y\": 352\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">+</span>\",\n          \"width\": 25,\n          \"height\": 23,\n          \"id\": \"af90d4a8-fc72-4035-b4ce-2351b7c981d7\",\n          \"x\": 46,\n          \"y\": 382\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\"],\n      \"id\": \"e21ff914-108e-4f32-9dbd-b3c8a276aa13\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"50e5bff1-79c2-46a5-823a-057c1876d582\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Headband\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"25ea0169-cbc3-4777-bdfd-4036ce372057\",\n          \"x\": 59,\n          \"y\": 266,\n          \"marginOffset\": 5.957999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Bobby pins\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"23f270b7-9614-4444-aa3b-58e46bd8aaea\",\n          \"x\": 59,\n          \"y\": 297,\n          \"marginOffset\": 5.957999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Clips\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"89a797e9-dc77-4003-ad93-5e0f34250e5f\",\n          \"x\": 59,\n          \"y\": 359,\n          \"marginOffset\": 5.957999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Ties\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"7b3c9d38-2000-48cb-b3bd-dcb64b76a5d8\",\n          \"x\": 59,\n          \"y\": 328,\n          \"marginOffset\": 5.957999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Scarf\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"a899dfcc-41d8-470c-9575-fa6d1e2f4e84\",\n          \"x\": 59,\n          \"y\": 390,\n          \"marginOffset\": 5.957999999999998\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Accessory necessities</span>\",\n          \"width\": 331,\n          \"height\": 42,\n          \"id\": \"dd313427-1c45-4a93-a82f-555d1701d7b6\",\n          \"x\": 41,\n          \"y\": 209,\n          \"marginOffset\": -7.920000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"eb045b80-4896-49c8-8535-0dd29e70d960\",\n          \"x\": 41,\n          \"y\": 275\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fd781603-76a2-43a3-8737-ec42188eef40\",\n          \"x\": 41,\n          \"y\": 306\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"756d51fe-7610-408e-8c12-49f666bfd820\",\n          \"x\": 41,\n          \"y\": 337\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dc3c9237-a672-454b-8899-94e15402cc2d\",\n          \"x\": 41,\n          \"y\": 368\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 11,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"703aeb65-ae9e-4c5a-9874-81566b3bc712\",\n          \"x\": 41,\n          \"y\": 399\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"ecb7bee3-9672-46a3-897e-64a92de65f94\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"3c7bde90-d663-4a58-8599-f3b39a00366f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Categories of Robots</span>\",\n          \"width\": 331,\n          \"height\": 30,\n          \"marginOffset\": 3.84375,\n          \"id\": \"d44aa256-41f4-4eac-b844-069791aa00de\",\n          \"x\": 41,\n          \"y\": 214\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Locomotion\",\n          \"width\": 313,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"911a54be-15e5-4465-b52c-473b53aa5f46\",\n          \"x\": 59,\n          \"y\": 261\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Industrial\",\n          \"width\": 313,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"d9fd9d7a-5ef7-40d8-93e6-b7ebe3b2f5af\",\n          \"x\": 59,\n          \"y\": 292\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Medical\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"c122f5fe-ae28-4ca7-98b5-c194af864b85\",\n          \"x\": 59,\n          \"y\": 354\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Consumer\",\n          \"width\": 313,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"684b381f-4117-4236-a264-42949b39533a\",\n          \"x\": 59,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Aerospace\",\n          \"width\": 313,\n          \"height\": 20,\n          \"id\": \"d2e33049-7bad-4365-9663-7a842bb330bc\",\n          \"x\": 59,\n          \"y\": 385\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">1.</span>\",\n          \"width\": 27,\n          \"height\": 21,\n          \"marginOffset\": 5.90625,\n          \"id\": \"d5026284-7421-43ee-a390-dcec8578110e\",\n          \"x\": 40,\n          \"y\": 261\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">2.</span>\",\n          \"width\": 27,\n          \"height\": 22,\n          \"marginOffset\": 5.90625,\n          \"id\": \"0214d5a9-d4b4-4637-ba4d-6258a1106074\",\n          \"x\": 40,\n          \"y\": 292\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">3.</span>\",\n          \"width\": 27,\n          \"height\": 22,\n          \"marginOffset\": 5.90625,\n          \"id\": \"6da68881-e64c-4916-ac88-6b4da4220be5\",\n          \"x\": 40,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">4.</span>\",\n          \"width\": 27,\n          \"height\": 22,\n          \"marginOffset\": 5.90625,\n          \"id\": \"bc0fd919-f3ba-4d47-851b-f8ba8c161157\",\n          \"x\": 40,\n          \"y\": 354\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">5.</span>\",\n          \"width\": 27,\n          \"height\": 22,\n          \"marginOffset\": 5.90625,\n          \"id\": \"40769abb-8b59-47c7-94ed-7cda39cfa894\",\n          \"x\": 40,\n          \"y\": 385\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"bd18c333-b565-460a-9ab3-53003ba7e156\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"7810244e-da4f-495d-9606-8ebd41e566e8\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Bike the Golden\\nGate Bridge\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"7e887951-6b78-434a-9381-77c1e93e9471\",\n          \"x\": 64,\n          \"y\": 159\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Stroll through&nbsp;\\nFisherman's Warf\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"c3acfdf8-caf1-4fe8-8bec-8b06028c7f5b\",\n          \"x\": 64,\n          \"y\": 213\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Chill in Mission\\nDolores Park\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"9b59be2e-45e1-4721-b058-866b39b0ff5d\",\n          \"x\": 64,\n          \"y\": 267\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Go surfing on\\nOcean Beach\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"8dce2eb8-bec4-4b84-83d9-dad0a1c07128\",\n          \"x\": 64,\n          \"y\": 321\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Buy speciality\\ncheese and bread at\\nThe Ferry Building\",\n          \"width\": 130,\n          \"height\": 50,\n          \"id\": \"aaa353f9-f553-4344-9cd2-bdc8bad73399\",\n          \"x\": 64,\n          \"y\": 375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Try some local dim\\nsum in Chinatown\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"1f3f9fe4-9855-4083-986a-afdf51f0f7b4\",\n          \"x\": 242,\n          \"y\": 159\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Explore the Presidio&nbsp;\\nand Golden Gate Parks\",\n          \"width\": 130,\n          \"height\": 50,\n          \"id\": \"da0957d9-2ca1-4ee4-83cc-a23404c98eb8\",\n          \"x\": 242,\n          \"y\": 213\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"See a game in the&nbsp;\\nOracle Park\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"ae39e734-025b-4c43-8601-fcbb4d944b6e\",\n          \"x\": 242,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Dine outdoors in\\nNorth Beach\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"a353d4d0-cbfa-44e1-a8bd-213ed70ed145\",\n          \"x\": 242,\n          \"y\": 338\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Take a Ferry to&nbsp;\\nSausalito\",\n          \"width\": 130,\n          \"height\": 33,\n          \"id\": \"6a3a063d-59d4-43db-b7d1-027fa2bd8ec7\",\n          \"x\": 242,\n          \"y\": 392\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">01.</span>\",\n          \"width\": 24,\n          \"height\": 17,\n          \"id\": \"b69f96c0-bc39-42a5-ad82-3b631dca68af\",\n          \"x\": 40,\n          \"y\": 159\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">02.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"45e51018-320b-4957-8e9d-16105c9a2d5c\",\n          \"x\": 40,\n          \"y\": 213\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">03.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"935ea9a2-24dd-45f1-a590-662a082d8e34\",\n          \"x\": 40,\n          \"y\": 267\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">04.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"c77ae14d-5e53-4253-ac0e-36b935cdfca8\",\n          \"x\": 39,\n          \"y\": 321\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">05.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"bc9d0c23-68fa-4541-858b-262f19b6a05e\",\n          \"x\": 40,\n          \"y\": 375\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">06.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"e7f645b9-3f90-49bf-8042-da032d5cca16\",\n          \"x\": 218,\n          \"y\": 159\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">07.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"4a81bb81-2862-4bd1-8fc1-04bb6c8e8d1c\",\n          \"x\": 218,\n          \"y\": 213\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">08.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"af6c6f67-7e2a-4d3d-b428-c54b9a32fac4\",\n          \"x\": 218,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 918,\n              \"des\": -335,\n              \"tAsc\": 918,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1036,\n              \"wDes\": 335,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -335,\n              \"yMax\": 1002,\n              \"hAsc\": 918,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">09.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"774bfc23-e512-423a-971a-8e815ae01ecc\",\n          \"x\": 218,\n          \"y\": 338\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">10.</span>\",\n          \"width\": 24,\n          \"height\": 16,\n          \"id\": \"1f95effd-af8f-4890-835a-7e17ec2e2fe4\",\n          \"x\": 218,\n          \"y\": 392\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 200,\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"6a677a18-8799-4d4b-8f04-3fc55d994ec0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"980a5f9b-7a2f-4199-970a-38abbde832f6\",\n          \"x\": 40,\n          \"y\": 254\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ae972090-9f91-4c90-b859-9bc03af55197\",\n          \"x\": 40,\n          \"y\": 308\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"cff34a8c-6e08-4e15-9e1f-8ef62dbb0e07\",\n          \"x\": 218,\n          \"y\": 325\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bec793f4-a509-4b30-929a-fb9604d98991\",\n          \"x\": 218,\n          \"y\": 270\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"77200e78-f860-41dc-8da8-beb917920f75\",\n          \"x\": 218,\n          \"y\": 200\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d5371343-b3a7-4403-8ab1-790b61ebade1\",\n          \"x\": 40,\n          \"y\": 362\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2f06affc-b522-4f7d-8cb8-bd0855e899e8\",\n          \"x\": 218,\n          \"y\": 379\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"3029c0e6-384a-43f3-90f2-1d5d84e752d6\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"37cde38f-6a78-485d-ac98-0369918dc2e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Snake Plant\",\n          \"width\": 292,\n          \"height\": 18,\n          \"marginOffset\": 5.90625,\n          \"id\": \"587f6698-9762-440a-9375-753c68b6b702\",\n          \"x\": 80,\n          \"y\": 195\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Succulent\",\n          \"width\": 292,\n          \"height\": 18,\n          \"marginOffset\": 5.578125,\n          \"id\": \"b340f622-144b-48c5-bb74-abbbd123c312\",\n          \"x\": 80,\n          \"y\": 252\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Spider Plant\",\n          \"width\": 292,\n          \"height\": 18,\n          \"id\": \"28185704-c253-4fae-8621-5bc141e28482\",\n          \"x\": 80,\n          \"y\": 364,\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Aloe Vera\",\n          \"width\": 292,\n          \"height\": 18,\n          \"marginOffset\": 5.90625,\n          \"id\": \"dd8a2c00-2a23-4301-ae99-9ade0ebe3de9\",\n          \"x\": 80,\n          \"y\": 307\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Fiddle Leaf Fig\",\n          \"width\": 292,\n          \"height\": 18,\n          \"id\": \"cb75aad4-9abe-4592-9f0c-e4fd5755bf54\",\n          \"x\": 80,\n          \"y\": 419,\n          \"marginOffset\": 5.90625\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400\\\">1.</span>\",\n          \"width\": 40,\n          \"height\": 28,\n          \"marginOffset\": 5.90625,\n          \"id\": \"0b17058d-3678-43f4-b716-13067e4fa39c\",\n          \"x\": 40,\n          \"y\": 191\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400\\\">2.</span>\",\n          \"width\": 40,\n          \"height\": 28,\n          \"marginOffset\": 5.90625,\n          \"id\": \"fbcef0d5-2da5-4b5d-b43a-60bb533e28c3\",\n          \"x\": 40,\n          \"y\": 247\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400\\\">3.</span>\",\n          \"width\": 40,\n          \"height\": 28,\n          \"marginOffset\": 5.90625,\n          \"id\": \"9a6a87f2-1b4f-4f96-9a2b-29ba82d96433\",\n          \"x\": 40,\n          \"y\": 303\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400\\\">4.</span>\",\n          \"width\": 40,\n          \"height\": 28,\n          \"marginOffset\": 5.90625,\n          \"id\": \"4e7917dc-709d-4bd6-8a02-3ed53811b394\",\n          \"x\": 40,\n          \"y\": 359\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400\\\">5.</span>\",\n          \"width\": 40,\n          \"height\": 28,\n          \"marginOffset\": 5.90625,\n          \"id\": \"b70a050e-3ed8-44ad-94c8-89ad528ff3ee\",\n          \"x\": 40,\n          \"y\": 415\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 398,\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0b67a85e-5716-40ee-8c0a-719630d5fb0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"038b05b4-2383-4bf3-a8fa-dce5b1df9b95\",\n          \"x\": 40,\n          \"y\": 342\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ebc794da-9006-48da-9eab-25130949ccbc\",\n          \"x\": 40,\n          \"y\": 286\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3a498220-cf66-4731-8270-a0821f45dc97\",\n          \"x\": 40,\n          \"y\": 230\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\", \"Rubik\"],\n      \"id\": \"9773923a-d36c-4037-ad25-78a2a62fd668\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"701520ee-28a2-4bdf-9752-96b3b1d97858\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Self care is meditation.\",\n          \"width\": 332,\n          \"height\": 26,\n          \"marginOffset\": 5.90625,\n          \"id\": \"2e513127-a6e7-439e-9e9c-9d24b1c55bd2\",\n          \"x\": 40,\n          \"y\": 221\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Self care is journaling.\",\n          \"width\": 332,\n          \"height\": 26,\n          \"marginOffset\": 5.578125,\n          \"id\": \"859e00a8-bfc3-437f-a068-6b1b23fe0c03\",\n          \"x\": 40,\n          \"y\": 259\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Self care is eating healthy.\",\n          \"width\": 332,\n          \"height\": 26,\n          \"marginOffset\": 5.90625,\n          \"id\": \"87dca9c5-67ac-4297-98ed-917e34970534\",\n          \"x\": 40,\n          \"y\": 335\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Self care is exercising.\",\n          \"width\": 332,\n          \"height\": 26,\n          \"marginOffset\": 5.90625,\n          \"id\": \"d760191c-c367-4e05-a7d4-6abface2e73e\",\n          \"x\": 40,\n          \"y\": 297\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Self care is socializing.\",\n          \"width\": 332,\n          \"height\": 26,\n          \"marginOffset\": 5.90625,\n          \"id\": \"e5b0b416-cfd2-413a-830b-db40861d530d\",\n          \"x\": 40,\n          \"y\": 373\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\"],\n      \"id\": \"6ebe649d-39dc-4fbf-a1bb-ebe272d5fc94\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d10e54e7-1457-47c3-9c83-5eb048603270\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"CDs/DVDs/VHSs\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"ddc9d799-d597-4f43-b139-6b51293f1397\",\n          \"x\": 40,\n          \"y\": 228\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Books\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"adbcbd91-2815-48e0-9d84-50821702e21b\",\n          \"x\": 40,\n          \"y\": 284\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Seasonal Decor\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"faee2c09-ca9a-4f84-be5a-e23ed401f4f8\",\n          \"x\": 40,\n          \"y\": 347\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Broken Appliances\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"f3476350-c727-4b05-a2ec-c834bcc18a9b\",\n          \"x\": 218,\n          \"y\": 228\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Anything that doesn't bring\\nyou joy\",\n          \"width\": 154,\n          \"height\": 35,\n          \"id\": \"9be290e8-3171-4080-9030-e0dfc08eb7be\",\n          \"x\": 218,\n          \"y\": 383\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Stuffed Animals\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"bef35e47-956e-4992-a73e-cb6917fc69e0\",\n          \"x\": 40,\n          \"y\": 407\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Stuff you saved in a box that you haven't opened for\\na year\",\n          \"width\": 154,\n          \"height\": 55,\n          \"id\": \"a097f00a-6680-4b5f-bdef-05c48a1f3316\",\n          \"x\": 218,\n          \"y\": 285\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Rinse and repeat\",\n          \"width\": 154,\n          \"height\": 15,\n          \"id\": \"d8e76066-fb80-489c-932b-ab8d7e61e2b8\",\n          \"x\": 218,\n          \"y\": 463\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">1.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"2cdb8991-c28c-43e3-a208-239781dd628c\",\n          \"x\": 40,\n          \"y\": 203\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">2.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"60294892-2d16-414e-9372-99a10838456b\",\n          \"x\": 40,\n          \"y\": 259\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">3.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"80850e0d-f962-4897-bf5d-843b08caaae8\",\n          \"x\": 40,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">4.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"94cb0125-8ce9-4717-ad92-c8f084962877\",\n          \"x\": 39,\n          \"y\": 382\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">5.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"f964d388-bad9-443c-8f80-4e360294cd4e\",\n          \"x\": 218,\n          \"y\": 203\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">6.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"9c0d3922-3194-48d8-ad95-cb02037d2284\",\n          \"x\": 218,\n          \"y\": 260\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">7.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"4f6153f1-f4ca-4fd6-b356-da3f0b7e2de5\",\n          \"x\": 218,\n          \"y\": 358\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">8.</span>\",\n          \"width\": 13,\n          \"height\": 25,\n          \"id\": \"b8a76540-9b19-445b-b1d2-f460a0173be0\",\n          \"x\": 218,\n          \"y\": 436\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4e129269-1bbd-4de7-a5f7-104de5027e88\",\n          \"x\": 40,\n          \"y\": 252\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5dea57ca-db08-485d-b12e-cf7e9f845553\",\n          \"x\": 40,\n          \"y\": 310\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"15306dfc-17da-4d45-9ece-ebf9611c2003\",\n          \"x\": 40,\n          \"y\": 373\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e858248a-4dc4-47f9-b750-1a374514fdd0\",\n          \"x\": 40,\n          \"y\": 431\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2ed00db8-e88a-461c-954e-c13951f98deb\",\n          \"x\": 218,\n          \"y\": 252\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"62d4953e-e441-44ba-b17f-c452c7c8f5a9\",\n          \"x\": 218,\n          \"y\": 351\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 154,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f8244d91-759f-4a82-b931-e9e021e0df81\",\n          \"x\": 218,\n          \"y\": 429\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto Condensed\", \"Oswald\"],\n      \"id\": \"4ba2d2c7-5283-4e18-a673-04724a3bd93a\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d5d8b4b3-536b-49bf-8f1e-22ef8f7ca105\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Brazil\",\n          \"width\": 307,\n          \"height\": 20,\n          \"marginOffset\": 5.957999999999998,\n          \"id\": \"9d56473c-6f8a-4cd1-bf13-f4556cc86a0a\",\n          \"x\": 65,\n          \"y\": 258\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Vietnam\",\n          \"width\": 307,\n          \"height\": 20,\n          \"marginOffset\": 5.957999999999998,\n          \"id\": \"03ce9cfd-bd5a-425f-bead-99e34dae3bdc\",\n          \"x\": 65,\n          \"y\": 284\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Indonesia\",\n          \"width\": 307,\n          \"height\": 20,\n          \"marginOffset\": 5.957999999999998,\n          \"id\": \"bc83ad9d-4a34-4107-a9d3-407cd8ded2d8\",\n          \"x\": 65,\n          \"y\": 336\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Colombia\",\n          \"width\": 307,\n          \"height\": 20,\n          \"marginOffset\": 5.957999999999998,\n          \"id\": \"7c83dc35-daea-40f5-a2b7-548187310657\",\n          \"x\": 65,\n          \"y\": 310\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Ethiopia\",\n          \"width\": 307,\n          \"height\": 20,\n          \"marginOffset\": 5.957999999999998,\n          \"id\": \"b01599d9-549b-4c8f-a2bf-80d68df00956\",\n          \"x\": 65,\n          \"y\": 362\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Top coffee exporters\",\n          \"width\": 331,\n          \"height\": 34,\n          \"marginOffset\": -7.920000000000002,\n          \"id\": \"0f009c00-6705-443c-be2f-e2a553209391\",\n          \"x\": 41,\n          \"y\": 209\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 16,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"15a07370-f01a-4db9-85ad-3c6b9e4298cc\",\n          \"x\": 41,\n          \"y\": 260.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 16,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"740431de-71d9-4f12-89cd-a2395be8743c\",\n          \"x\": 41,\n          \"y\": 286\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 16,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8e8f383c-1f89-4c41-ac76-48b0d0a6f4d8\",\n          \"x\": 41,\n          \"y\": 312\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 16,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9e48b1b3-e3cb-4d29-bab3-8f4ee805b3fc\",\n          \"x\": 41,\n          \"y\": 338\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 16,\n          \"height\": 16,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"73a14ced-21d4-40c7-b18a-98823b49e5c5\",\n          \"x\": 41,\n          \"y\": 364\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n          \"type\": \"shape\",\n          \"x\": 44.5,\n          \"y\": 265,\n          \"width\": 10,\n          \"height\": 8,\n          \"mask\": { \"type\": \"check-mark\" },\n          \"id\": \"2d75dced-7e08-4096-bef9-6183bfe56546\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"id\": \"7fee5f83-94b7-40ed-ad0b-a503bab0e1de\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5d202228-bd29-4c86-8030-b8e54f0334b1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">1. &nbsp;Ice breakers</span>\",\n          \"width\": 316,\n          \"height\": 43,\n          \"marginOffset\": -0.3780000000000001,\n          \"id\": \"42bfa787-5d92-467c-9317-12c1567b4638\",\n          \"x\": 48,\n          \"y\": 185\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">2. &nbsp;Business focused</span>\",\n          \"width\": 316,\n          \"height\": 43,\n          \"marginOffset\": -0.3780000000000001,\n          \"id\": \"bb39a121-bc3a-49c6-8880-2afe0a964e62\",\n          \"x\": 48,\n          \"y\": 236\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">4. &nbsp;Active games</span>\",\n          \"width\": 316,\n          \"height\": 43,\n          \"marginOffset\": -0.3780000000000001,\n          \"id\": \"75962323-124b-40c4-8f48-361f31b39316\",\n          \"x\": 48,\n          \"y\": 338\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">3. &nbsp;Guessing games</span>\",\n          \"width\": 316,\n          \"height\": 43,\n          \"marginOffset\": -0.3780000000000001,\n          \"id\": \"3dbe1aa3-a8ca-4313-8170-83958567437d\",\n          \"x\": 48,\n          \"y\": 287\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">5. &nbsp;Relaxing activities</span>\",\n          \"width\": 316,\n          \"height\": 43,\n          \"marginOffset\": -0.3780000000000001,\n          \"id\": \"a0fbe4da-4624-4a5c-b46d-4318558b9194\",\n          \"x\": 48,\n          \"y\": 389\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Merriweather\", \"Titillium Web\"],\n      \"id\": \"e4331b1e-a2cf-42fc-ace6-c3f4dda22808\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"816d4486-7125-4f1c-a5a4-94ee0e1e123e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Cleanse\",\n          \"width\": 332,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"6a4b2a15-dcb8-4674-8311-b0d8165f4a1e\",\n          \"x\": 40,\n          \"y\": 215\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Condition\",\n          \"width\": 332,\n          \"height\": 20,\n          \"marginOffset\": 5.578125,\n          \"id\": \"b2d9f1f9-a7b2-49c2-b154-5a6756633ff1\",\n          \"x\": 40,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Detangle\",\n          \"width\": 332,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"97aabcc5-03e2-47db-85fe-2ed0ffe3b78f\",\n          \"x\": 40,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Moisturise and seal\",\n          \"width\": 332,\n          \"height\": 20,\n          \"marginOffset\": 5.90625,\n          \"id\": \"1b53244c-4993-411b-a5e7-58845c12d95c\",\n          \"x\": 40,\n          \"y\": 341\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"01\",\n          \"width\": 18,\n          \"height\": 16,\n          \"marginOffset\": -4.732000000000003,\n          \"id\": \"a96bda21-5aaa-4352-bd58-e1286b535950\",\n          \"x\": 197,\n          \"y\": 195\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 179,\n          \"y\": 201.5,\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"756040e3-c569-47b3-98cf-e61ad9cc74f2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ee8989ed-441c-4442-8cbe-2a5aca4dd4b4\",\n          \"x\": 226,\n          \"y\": 201.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"02\",\n          \"width\": 18,\n          \"height\": 16,\n          \"marginOffset\": -4.732000000000003,\n          \"id\": \"633c0021-ea6d-4b18-9f3b-80f1869f2f01\",\n          \"x\": 197,\n          \"y\": 255\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1c2ef0db-ecb3-4b57-9650-f582784f6862\",\n          \"x\": 179,\n          \"y\": 266\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dd6c59c4-50a2-4f55-96d9-163d376e0c40\",\n          \"x\": 226,\n          \"y\": 266\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"03\",\n          \"width\": 18,\n          \"height\": 16,\n          \"marginOffset\": -4.732000000000003,\n          \"id\": \"486278fa-f9c3-498f-a535-d38014013556\",\n          \"x\": 197,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ab037ba1-e534-469a-9c9b-eca9290e9141\",\n          \"x\": 179,\n          \"y\": 329\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b6cb61e8-49c9-44fc-bcba-a53b30e65eb0\",\n          \"x\": 226,\n          \"y\": 329\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 800],\n              [1, 800],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 13,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"04\",\n          \"width\": 18,\n          \"height\": 16,\n          \"marginOffset\": -4.732000000000003,\n          \"id\": \"c3d5d88d-8bed-4513-b6c8-dc2ab841a53b\",\n          \"x\": 195,\n          \"y\": 384\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"af667001-d6c7-48f6-b5e9-41a387912f59\",\n          \"x\": 177,\n          \"y\": 391\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 8,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9087c5c4-ac99-44a7-a4b6-a17a54347d68\",\n          \"x\": 224,\n          \"y\": 391\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"e5746627-7cb7-4249-9129-32ac0e614176\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4259217b-228c-44bc-80b4-9eb2855c02e3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #ff8e25; letter-spacing: 0.08em; text-transform: uppercase\\\">Quick Recipe</span>\",\n          \"width\": 332,\n          \"height\": 38,\n          \"marginOffset\": -7.614000000000004,\n          \"id\": \"917f87d6-a606-4f82-80aa-8ec8fb345d17\",\n          \"x\": 40,\n          \"y\": 199\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Cookie\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400],\n            \"styles\": [\"regular\"],\n            \"variants\": [[0, 400]],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 789,\n              \"des\": -320,\n              \"tAsc\": 789,\n              \"tDes\": -320,\n              \"tLGap\": 0,\n              \"wAsc\": 789,\n              \"wDes\": 320,\n              \"xH\": 115,\n              \"capH\": 312,\n              \"yMin\": -320,\n              \"yMax\": 789,\n              \"hAsc\": 789,\n              \"hDes\": -320,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 72,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ff8e25\\\">Apple Pie</span>\",\n          \"width\": 332,\n          \"height\": 80,\n          \"id\": \"ed560175-6684-4c8b-8379-64690b9d6e01\",\n          \"x\": 40,\n          \"y\": 249\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #666\\\">Easy to follow, this guide will get you to bake a delicious crusty apple pie right off the bat.</span>\",\n          \"width\": 250,\n          \"height\": 74,\n          \"id\": \"3341605e-2bad-4827-87fa-e65797d198b6\",\n          \"x\": 81,\n          \"y\": 343\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Cookie\", \"Roboto Condensed\"],\n      \"id\": \"2c847372-cd79-456e-a6e0-fb837487fa0d\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/quote.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d3931551-599c-4f56-9fc4-0d840cb2abbd\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; font-style: italic\\\">The best humans are kind to everyone, even artificial someones.</span>\",\n          \"marginOffset\": 9.84375,\n          \"x\": 41,\n          \"y\": 208,\n          \"width\": 330,\n          \"height\": 171,\n          \"id\": \"3ba10c6c-92e9-41f6-8bb2-9fa271f4c999\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"— Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 41,\n          \"y\": 396,\n          \"width\": 147,\n          \"height\": 21,\n          \"id\": \"7f0b5ab5-e076-47c4-843d-1960734980a9\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"28518eb9-7c09-4e5a-9c80-87d61cba8622\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f1d6b05b-2e30-4c1f-a4b9-ede74455a306\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"San Francisco is a city that sleeps. It's full of dreamers.\",\n          \"marginOffset\": 9.84375,\n          \"x\": 40,\n          \"y\": 233,\n          \"width\": 330,\n          \"height\": 123,\n          \"id\": \"773e33c5-e58b-45c3-ba2f-a11ecac17e4d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"— Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 132,\n          \"y\": 386,\n          \"width\": 149,\n          \"height\": 23,\n          \"id\": \"30512f4c-15e6-4da5-bd28-02bc101ca768\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 146,\n          \"y\": 369,\n          \"width\": 120,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"71b5b0da-5d94-401d-b188-e2db311c9cba\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 146,\n          \"y\": 216,\n          \"width\": 120,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"d2f56f7c-b011-4282-aa3f-97658fd61527\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"8d36c287-78bb-4825-beb3-1427f30523bd\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"c75c14ae-de70-40ee-a284-8b088c5a4e8b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">Everyone thinks I'm talking to myself, but I promise my plants are listening</span>\",\n          \"marginOffset\": -10.5,\n          \"x\": 70,\n          \"y\": 169,\n          \"width\": 309,\n          \"height\": 245,\n          \"id\": \"b96c283b-0608-4b23-b050-a096508cdf41\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"— Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 207,\n          \"y\": 425,\n          \"width\": 184,\n          \"height\": 26,\n          \"id\": \"fb736e78-7220-427f-9792-3ac6bc133ca2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 49,\n          \"y\": 169,\n          \"width\": 4,\n          \"height\": 240,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ff09eeab-8607-4bf3-b657-8db968d40a1c\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\"],\n      \"id\": \"95e1a6a4-7e60-4d6d-84fc-921e76dee243\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"bd6e5771-a62b-469e-8da2-ab6caa53899f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-style: italic\\\">If you don't like yourself, no one else will.</span>\",\n          \"marginOffset\": -4.920999999999999,\n          \"x\": 40,\n          \"y\": 229,\n          \"width\": 332,\n          \"height\": 134,\n          \"id\": \"96783563-d957-4a76-b7ba-e045001a1601\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"— Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 130,\n          \"y\": 374,\n          \"width\": 152,\n          \"height\": 24,\n          \"id\": \"f2e8f4cc-ac67-49ef-b9d7-0dda9fc672ee\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\"],\n      \"id\": \"21619959-7a77-42f2-a84d-71c958b254c6\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"90cc863f-92fd-4266-b238-5b18e4ee0a20\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 42,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Minimalism maximizes what you care about.</span>\",\n          \"marginOffset\": -16.043999999999997,\n          \"x\": 41,\n          \"y\": 226,\n          \"width\": 332,\n          \"height\": 157,\n          \"id\": \"177372d5-853d-45b6-8760-f334a5d641f7\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"text-transform: uppercase\\\">— Crystal Lambert</span>\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 124,\n          \"y\": 386,\n          \"width\": 147,\n          \"height\": 27,\n          \"id\": \"81fe5f78-3b28-4e09-8777-115619be7e7b\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\"],\n      \"id\": \"34cd2863-6711-48d0-a28a-d5ad7fa61700\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"81b87a79-dac6-4d11-9089-be45ddc5af7c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">I take my coffee black. I need it as strong as I am.</span>\",\n          \"marginOffset\": -4.920999999999999,\n          \"x\": 40,\n          \"y\": 252,\n          \"width\": 332,\n          \"height\": 131,\n          \"id\": \"46c02eae-19bf-4ecd-a9e1-3276c64d1abb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.25,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"— Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 124,\n          \"y\": 397,\n          \"width\": 165,\n          \"height\": 22,\n          \"id\": \"765b2982-21f0-4b59-a379-32caa230f497\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 187,\n          \"y\": 197,\n          \"width\": 40,\n          \"height\": 40,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"32e21adc-45f0-4b0b-b9ba-c1c7697d5481\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 47,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">“</span>\",\n          \"marginOffset\": -11.890999999999998,\n          \"x\": 197,\n          \"y\": 202,\n          \"width\": 18,\n          \"height\": 58,\n          \"id\": \"b645062a-a2f6-46c1-9fca-6265614494c8\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\", \"Source Serif 4\"],\n      \"id\": \"35854c63-b7f5-4637-99dc-f26dec385321\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"1db60d3b-edf9-47da-b87f-676e41179958\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #d2d2d2; text-transform: uppercase\\\">Crystal Lambert</span>\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 74,\n          \"y\": 389,\n          \"width\": 324,\n          \"height\": 54,\n          \"id\": \"42f83867-682c-4547-9011-a606e55d9b0a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; text-transform: uppercase\\\">Crystal Lambert</span>\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 71,\n          \"y\": 386,\n          \"width\": 301,\n          \"height\": 54,\n          \"id\": \"8304683d-4da5-471a-90b7-0146592286a3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 175,\n          \"width\": 332,\n          \"height\": 205,\n          \"mask\": { \"type\": \"chat-bubble\" },\n          \"id\": \"1362a62e-5729-4fcc-b05f-38bd4a6f991f\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.2 } },\n          \"type\": \"shape\",\n          \"x\": 44,\n          \"y\": 179,\n          \"width\": 332,\n          \"height\": 205,\n          \"mask\": { \"type\": \"chat-bubble\" },\n          \"id\": \"dca26230-09aa-4b84-9cec-33b6ce885588\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">I didn't work this hard to keep working this hard.</span>\",\n          \"marginOffset\": -4.920999999999999,\n          \"x\": 64,\n          \"y\": 192,\n          \"width\": 284,\n          \"height\": 141,\n          \"id\": \"a6de316b-e55c-4aa7-9e16-a5b9f351e88e\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\"],\n      \"id\": \"60dfcbbd-6bc2-4535-9f3d-1770db7e4147\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"74d5cfba-edc0-4db6-9a8b-729623c64aab\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 118,\n          \"y\": 365,\n          \"width\": 16,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2c09cf58-9287-4e54-b2d5-658db44212e2\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 281,\n          \"y\": 365,\n          \"width\": 16,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"feca60f0-b3d3-4afe-8de0-3a553849557e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 200\\\">My hair matches my life, it's all a mess.</span>\",\n          \"marginOffset\": 9.84375,\n          \"x\": 40,\n          \"y\": 253,\n          \"width\": 330,\n          \"height\": 92,\n          \"id\": \"5526674b-2f67-4ec8-b34e-611965f4a090\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Crystal Lambert\",\n          \"marginOffset\": 2.306250000000002,\n          \"x\": 142,\n          \"y\": 355,\n          \"width\": 131,\n          \"height\": 21,\n          \"id\": \"6b96ea1d-a465-4800-bb26-35258a0fa0f9\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 23,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"002f7939-e342-488c-8c9b-c4743160a34d\",\n          \"x\": 372,\n          \"y\": 214\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 214,\n          \"width\": 1,\n          \"height\": 23,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a8f9dde5-cfd6-4504-a41a-41590f25a2eb\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 23,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"864b0d4c-ee8a-486e-b801-4fcf8b5ef2d3\",\n          \"x\": 41,\n          \"y\": 214\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 23,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e28fb39d-b1ab-4417-98f8-2a071ddd0498\",\n          \"x\": 350,\n          \"y\": 214\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 23,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"5b825540-99a5-410d-b52a-a8284223e727\",\n          \"x\": 41,\n          \"y\": 381\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 23,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"05f4dd37-e2a6-42f9-9f55-250dea0b0112\",\n          \"x\": 41,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 23,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"be47d78c-2b75-4a8e-998e-22154c96f22b\",\n          \"x\": 350,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 23,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"97307ebd-da1e-4575-afa7-8fb0739c52fe\",\n          \"x\": 372,\n          \"y\": 381\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"7da9face-3152-4482-aba2-82fce4114901\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/section_header.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"01322aae-3e57-4f47-8d15-1afc290c30d6\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">From fiction to fact</span>\",\n          \"x\": 40,\n          \"y\": 373,\n          \"width\": 315,\n          \"height\": 42,\n          \"id\": \"1cd520e5-caa2-4640-931e-23970ccf59c3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 309,\n          \"width\": 48,\n          \"height\": 48,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bf4a0323-a2cf-4fc8-a859-4ee1ba2defd0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">2</span>\",\n          \"width\": 32,\n          \"height\": 27,\n          \"id\": \"e085c108-3710-46ec-bb53-7579ede7591f\",\n          \"x\": 48,\n          \"y\": 320\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The word \\\"Robot\\\" comes from a 1920's play titled R.U.R., by Karel Čapek, a Czech writer. The story centers around living creatures made of artificial flesh, rather than machinery, assembled in a factory. \\\"Robot\\\" quickly replaced older words, like \\\"automaton\\\", in science fiction.\",\n          \"x\": 40,\n          \"y\": 432,\n          \"width\": 330,\n          \"height\": 183,\n          \"id\": \"58240b4d-fc89-4b8c-8d0a-d1dc22885597\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"8f7d5b98-666f-4d23-bd5f-9af695c406e0\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"5002e0f4-c595-4326-a04a-c7b9d1e9aa7a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">Unique on every block</span>\",\n          \"width\": 315,\n          \"height\": 39,\n          \"id\": \"e5c59a1e-6343-40f3-a436-10233b2257fb\",\n          \"x\": 41,\n          \"y\": 359\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 120,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b7e67855-dfd6-4da2-a3b6-dd086fbc9eec\",\n          \"x\": 146,\n          \"y\": 412\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase\\\">Section 2</span>\",\n          \"width\": 98,\n          \"height\": 23,\n          \"id\": \"7a413d47-c361-4628-a3ff-1275d55b3040\",\n          \"x\": 159,\n          \"y\": 321\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"San Francisco is only seven by seven miles, but it's packed of distinct neighborhoods. Stay in the Haight Asbury to taste the Summer of Love, or book off Columbus street for a culinary collision between Little Italy and Chinatown. \",\n          \"width\": 321,\n          \"height\": 185,\n          \"id\": \"bfd32375-080a-49d7-9c57-20aa77e627fc\",\n          \"x\": 46,\n          \"y\": 429\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"1abbc5b2-3682-4fbd-a697-22204c8f7df7\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"528109cf-0865-4108-8abd-def9f0fb65a4\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 30,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase\\\">Learn The Language</span>\",\n          \"width\": 324,\n          \"height\": 78,\n          \"id\": \"0268df76-4bc2-4501-a443-92c2e82b18f8\",\n          \"x\": 40,\n          \"y\": 374,\n          \"marginOffset\": -6\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">02.</span>\",\n          \"width\": 93,\n          \"height\": 64,\n          \"id\": \"1349ca02-3e09-4701-9f0f-9cb95168260e\",\n          \"x\": 40,\n          \"y\": 312\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Tending to plants teaches patience and it requires careful attention. Learning to communicate with your little green friends takes time! When done right, you'll be rewarded with beautiful accent pieces and fresher air.\",\n          \"width\": 325,\n          \"height\": 158,\n          \"id\": \"9cde7138-1466-465e-b74c-76c5c3675e32\",\n          \"x\": 40,\n          \"y\": 464\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"IBM Plex Sans\", \"Rubik\"],\n      \"id\": \"4fb31852-a1ba-4f9d-a94d-e62b14818f07\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d8e90ad9-14b1-4d3c-abee-c390cc2b6fa0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase\\\">Embrace Emotions</span>\",\n          \"width\": 331,\n          \"height\": 36,\n          \"id\": \"895ba9ab-fae1-4ec3-ac09-48eaf119b5db\",\n          \"x\": 41,\n          \"y\": 408,\n          \"marginOffset\": -3.591000000000001\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 400; letter-spacing: 0.04em; text-transform: uppercase\\\">ii</span>\",\n          \"width\": 331,\n          \"height\": 47,\n          \"id\": \"19220de8-e6d3-4236-81b8-f20fd17134b2\",\n          \"x\": 41,\n          \"y\": 332,\n          \"marginOffset\": -11.655000000000001\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Stop telling yourself things should or shouldn't be a certain way. Sit with your feelings instead and try to name them and understand where they're coming from. Have compassion for negative feelings and celebrate good ones.\",\n          \"width\": 332,\n          \"height\": 146,\n          \"id\": \"92d43528-fa2a-4f52-8e8d-98fc81ff213a\",\n          \"x\": 41,\n          \"y\": 456,\n          \"marginOffset\": 3.7399999999999984\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Lora\"],\n      \"id\": \"71f21b73-f7fc-41b2-b61a-a35d0bcff633\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"45fe1f64-0ba8-40bc-ac0a-b7937239b103\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Digitize Everything</span>\",\n          \"width\": 331,\n          \"height\": 40,\n          \"id\": \"f626b97c-2bf4-4299-a04d-3975d4e787da\",\n          \"x\": 41,\n          \"y\": 427,\n          \"marginOffset\": -7.614000000000004\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 35,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500\\\">02</span>\",\n          \"width\": 38,\n          \"height\": 53,\n          \"id\": \"bc7d401f-3f80-4c66-9116-bfe4efae16bd\",\n          \"x\": 187,\n          \"y\": 327,\n          \"marginOffset\": -16.869999999999997\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"If you don't need to keep a physical copy of something, don't! Virtual space is limitless. It's worth the upfront cost of converting from physical to digital. You'll be surprised how much these little things build up.\",\n          \"width\": 332,\n          \"height\": 129,\n          \"id\": \"4ea9d2da-f875-45aa-8ba1-d8032ed9df0b\",\n          \"x\": 41,\n          \"y\": 475,\n          \"marginOffset\": 5.578125\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 189,\n          \"y\": 378,\n          \"width\": 38,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1026e4b9-721b-4d41-86f8-db853af66e04\"\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"e1d2a549-46ca-4f67-babc-efbfe8901406\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a7fd86d3-8084-4712-a658-e4c82568e557\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Ready for a revolution\",\n          \"width\": 332,\n          \"height\": 34,\n          \"id\": \"d1500eb2-89b5-4be4-ad74-3a07eead97dd\",\n          \"x\": 40,\n          \"y\": 388,\n          \"marginOffset\": -1.5390000000000015\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">02.</span>\",\n          \"width\": 93,\n          \"height\": 28,\n          \"id\": \"05e6c69b-83d7-458c-85be-864bc1de9b3c\",\n          \"x\": 40,\n          \"y\": 346\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Coffee changed everything! Humans began thinking and gathering. It's said that the French and American revolutions were planned in coffeehouses. It also gave great thinkers fuel to kick off the industrial revolution.\",\n          \"width\": 338,\n          \"height\": 136,\n          \"id\": \"167bb93b-0a13-42ce-8e8d-10ef76bff9ff\",\n          \"x\": 40,\n          \"y\": 439,\n          \"marginOffset\": 2.4309999999999974\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\"],\n      \"id\": \"c9dd26dd-c76c-47a1-aeed-2ad60eda048f\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"19c6ca5b-5db2-4e30-960f-382845085f89\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Making time for fun at work brings teams closer, increases creative collaborations, and reduces stress. Use personality tools to understand your teams dynamic and research related activities, such as a paint night for creatives or playing kickball with sport lovers.\",\n          \"width\": 338,\n          \"height\": 194,\n          \"id\": \"08a826e3-fa5a-47c9-818b-a93c65e7afc6\",\n          \"x\": 40,\n          \"y\": 433\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.15 } },\n          \"type\": \"shape\",\n          \"width\": 56,\n          \"height\": 56,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"0d3c3171-1d98-43a1-97e8-cfa5d2920441\",\n          \"x\": 320,\n          \"y\": 309\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 316,\n          \"y\": 305,\n          \"width\": 56,\n          \"height\": 56,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"89cb319a-33a7-44ef-afb2-e4860a3c256a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 525,\n              \"capH\": 700,\n              \"yMin\": -262,\n              \"yMax\": 1043,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600; color: #fff\\\">2</span>\",\n          \"width\": 22,\n          \"height\": 44,\n          \"id\": \"fb434971-6710-47fe-93c1-04cc624842f2\",\n          \"x\": 333,\n          \"y\": 311,\n          \"marginOffset\": -8.103000000000002\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: rgba(0,0,0,0.15)\\\">Learn your team</span>\",\n          \"width\": 337,\n          \"height\": 54,\n          \"id\": \"6bb18ef8-aa4e-4ac0-8eb4-67505e38c150\",\n          \"x\": 44,\n          \"y\": 381\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 36,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900\\\">Learn your team</span>\",\n          \"width\": 337,\n          \"height\": 54,\n          \"id\": \"616622fc-f2de-4f1a-b919-a37764baa73a\",\n          \"x\": 40,\n          \"y\": 377\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\", \"Montserrat\"],\n      \"id\": \"902b7a10-0a66-4f92-998d-6c2b0a92b2b5\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"18a0059e-28e0-4144-baf1-6d1fc4d527ef\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Hair care comes first</span>\",\n          \"width\": 331,\n          \"height\": 42,\n          \"id\": \"ddb38426-a6de-47b9-b783-24187c869f5a\",\n          \"x\": 41,\n          \"y\": 393,\n          \"marginOffset\": -8.448\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Healthy hair looks good, period. Decide how much time you're willing to spend on your look and dedicate the bulk of it to hair care. Make sure you're using the right products and tools for your hair type!\",\n          \"width\": 330,\n          \"height\": 156,\n          \"id\": \"a0263a3c-9cf5-49e7-b4aa-5fc91cdb3411\",\n          \"x\": 41,\n          \"y\": 443\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4704e3f0-20b0-4d93-9ea0-7563a626097b\",\n          \"x\": 136,\n          \"y\": 346\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"bea8eabf-4121-48c3-8359-960520198da9\",\n          \"x\": 244,\n          \"y\": 346\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1087,\n              \"wDes\": 275,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -259,\n              \"yMax\": 1077,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 26,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">02</span>\",\n          \"width\": 56,\n          \"height\": 35,\n          \"id\": \"aad45546-79bf-4a85-9ffc-392e53286c6d\",\n          \"x\": 178,\n          \"y\": 331,\n          \"marginOffset\": -9.828000000000003\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Nunito Sans\", \"Karla\"],\n      \"id\": \"9c5a3d04-66eb-4ff3-a5fa-440b1ca4c9cf\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/step.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"a9dd2ec8-c668-45c2-b3c3-61701c7d4afe\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Make a man of tin</span>\",\n          \"x\": 90,\n          \"y\": 360,\n          \"width\": 254,\n          \"height\": 25,\n          \"id\": \"19240e57-e3d3-4974-80a5-c45381f162de\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The first British robot, Eric, was exhibited&nbsp;\\nin 1928 at the Model Engineers Society in London. Eric could sit, stand, and&nbsp;\\ndelivered a speech via radio signal.\",\n          \"x\": 40,\n          \"y\": 405,\n          \"width\": 332,\n          \"height\": 93,\n          \"id\": \"25dc99de-cd5f-4589-a654-80a1d4ae9fcb\",\n          \"marginOffset\": 5.578125\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 5, \"vertical\": 5 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 900; color: #fff\\\">2</span>\",\n          \"width\": 35,\n          \"height\": 34,\n          \"marginOffset\": 10.5,\n          \"id\": \"e38c860f-ac6a-430b-a615-43be6d2ccbdb\",\n          \"x\": 40,\n          \"y\": 355\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"db308a1e-9fbd-48a0-b7ee-4ac232f23459\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"579bf3ee-378d-4732-8f96-980a7ac23b84\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">Know before you go</span>\",\n          \"width\": 284,\n          \"height\": 27,\n          \"id\": \"da1954aa-db03-473d-92a9-87c906083942\",\n          \"x\": 88,\n          \"y\": 359\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 22,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">02.</span>\",\n          \"width\": 39,\n          \"height\": 27,\n          \"marginOffset\": 10.5,\n          \"id\": \"973e1776-967c-4be9-8c40-67ea0a7073ce\",\n          \"x\": 40,\n          \"y\": 358\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"San Francisco is America's most walkable city with wide weather forecast. Come prepared with layers and comfortable shoes.\",\n          \"width\": 284,\n          \"height\": 100,\n          \"id\": \"2c3dd807-05dd-432c-9c91-cecee9b175d1\",\n          \"x\": 88,\n          \"y\": 392\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"05c03e47-aa32-46c9-8324-3d1c89e40720\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b5238b09-5e76-4e1c-973b-9e12fb0f2083\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">Green Soul Mates</span>\",\n          \"width\": 276,\n          \"height\": 26,\n          \"id\": \"8909982a-9b45-435d-b833-c5d865b19ca5\",\n          \"x\": 96,\n          \"y\": 347\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Rubik\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 935,\n              \"des\": -250,\n              \"tAsc\": 935,\n              \"tDes\": -250,\n              \"tLGap\": 0,\n              \"wAsc\": 945,\n              \"wDes\": 307,\n              \"xH\": 520,\n              \"capH\": 700,\n              \"yMin\": -264,\n              \"yMax\": 905,\n              \"hAsc\": 935,\n              \"hDes\": -250,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 54,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">2</span>\",\n          \"width\": 39,\n          \"height\": 64,\n          \"marginOffset\": 10.5,\n          \"id\": \"1f559bf2-dc73-466c-9884-f2d2f5d10b6a\",\n          \"x\": 40,\n          \"y\": 347\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Before you adopt a plant, identify places in your home you'd like to keep one. Balancing light, air flow, and water needs are essential to keeping a happy and healthy plant.\",\n          \"width\": 276,\n          \"height\": 153,\n          \"id\": \"21723eac-86c9-40e8-8fdc-67d9e30c893c\",\n          \"x\": 96,\n          \"y\": 382,\n          \"marginOffset\": 3.599999999999998\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"IBM Plex Sans\", \"Rubik\"],\n      \"id\": \"b30adc33-602f-463c-8a01-3407a8ca5ab1\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"f1006bb9-bc4e-4296-b538-1151cef86940\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Keep a journal</span>\",\n          \"width\": 284,\n          \"height\": 26,\n          \"id\": \"7fc212fd-8dca-4e45-8f2c-1bd4b7d3402d\",\n          \"x\": 88,\n          \"y\": 366\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">ii</span>\",\n          \"width\": 32,\n          \"height\": 25,\n          \"marginOffset\": 3.34,\n          \"id\": \"8b20a587-4c93-4910-acc3-bc5dc061e94f\",\n          \"x\": 40,\n          \"y\": 366\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Start writing your thoughts down. Studies have found that regular journaling increases happiness and helps manage stressful situations.\",\n          \"width\": 284,\n          \"height\": 94,\n          \"id\": \"c26327a3-7df0-4d77-afa3-5cd3ef6ea069\",\n          \"x\": 88,\n          \"y\": 392,\n          \"marginOffset\": 4.199000000000002\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Source Serif 4\"],\n      \"id\": \"3762e203-e4e5-4a70-83a5-a45f832c5c6a\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"577ff93a-fd76-4cd2-806e-2c1186266563\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">02</span>\",\n          \"width\": 28,\n          \"height\": 39,\n          \"marginOffset\": 10.5,\n          \"id\": \"449e1d3f-e38d-483a-af21-c8843ff10ee4\",\n          \"x\": 40,\n          \"y\": 355\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"No more impulse buys! Everything you want goes into a tracking sheet. Set a date to go over your wish list and decide if you still feel strongly about a potential purchase.\",\n          \"width\": 284,\n          \"height\": 125,\n          \"id\": \"317fba41-6497-4a49-a31e-4160cb8492fa\",\n          \"x\": 88,\n          \"y\": 403\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; text-transform: uppercase\\\">Set Rules</span>\",\n          \"width\": 284,\n          \"height\": 40,\n          \"id\": \"f6a78147-8b58-4236-a7e3-4e1fe1737fb2\",\n          \"x\": 88,\n          \"y\": 355\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"23e0dfcc-a5f8-4333-b130-34c6c09790eb\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"49f684c5-4616-4b4e-b74b-9d2e0c3ec5be\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 20,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Tiny but mighty</span>\",\n          \"width\": 290,\n          \"height\": 24,\n          \"id\": \"bbbf66b2-75e8-4e0f-96bf-ed06a1c0c6f9\",\n          \"x\": 82,\n          \"y\": 362\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 600\\\">02.</span>\",\n          \"width\": 34,\n          \"height\": 28,\n          \"marginOffset\": 10.5,\n          \"id\": \"8be77026-0a06-4a30-a392-3c272589d477\",\n          \"x\": 40,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"The coffee bean is a humble plant, but it created big waves. Trade routes and tourist destinations followed the brew all over the world!\",\n          \"width\": 332,\n          \"height\": 99,\n          \"id\": \"aaa3dbb0-9520-4446-8273-e07b705dc311\",\n          \"x\": 40,\n          \"y\": 397\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\"],\n      \"id\": \"27b30409-0757-47cd-b66b-95404b18bbd4\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d5edf05d-96a9-4e8f-bc7d-34a5c4ceed6d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Avoid forced fun</span>\",\n          \"width\": 284,\n          \"height\": 41,\n          \"id\": \"12573e26-0ff2-426a-9244-810b189786b2\",\n          \"x\": 88,\n          \"y\": 349\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.15 } },\n          \"type\": \"shape\",\n          \"width\": 40,\n          \"height\": 40,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"ea30dc49-eda0-49b2-a0b5-eed876a6a8f6\",\n          \"x\": 36,\n          \"y\": 349\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 32,\n          \"y\": 345,\n          \"width\": 40,\n          \"height\": 40,\n          \"mask\": { \"type\": \"circle\" },\n          \"id\": \"518ab49d-c5ec-426e-bbd2-e06feb8d6755\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Montserrat\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 968,\n              \"des\": -251,\n              \"tAsc\": 968,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1109,\n              \"wDes\": 270,\n              \"xH\": 525,\n              \"capH\": 700,\n              \"yMin\": -262,\n              \"yMax\": 1043,\n              \"hAsc\": 968,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; color: #fff\\\">2</span>\",\n          \"width\": 26,\n          \"height\": 29,\n          \"marginOffset\": 10.5,\n          \"id\": \"41dad828-61eb-42a3-b2c5-9b77ff8c34c7\",\n          \"x\": 39,\n          \"y\": 351\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Be careful about mandatory outings or activities. Instead, look where fun is happening naturally and try to grow it! Is your team gathering in the break room? Make sure there's enough chairs for everyone!\",\n          \"width\": 284,\n          \"height\": 167,\n          \"id\": \"db4af893-534a-49ee-8f07-5ff834627bcf\",\n          \"x\": 88,\n          \"y\": 392\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\", \"Montserrat\"],\n      \"id\": \"3c30606b-4f07-47ff-9fdc-f3161a69108b\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"4f55007a-c651-4929-900a-1a8696d453d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 40,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"e2d89223-1625-4e60-913b-49f1f6e3222f\",\n          \"x\": 39.5,\n          \"y\": 379.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 40,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8bff60f7-0b7b-4725-9d55-73746f44543b\",\n          \"x\": 39.5,\n          \"y\": 340.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 40,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b1218f3f-b7d9-41bc-b803-b36452cb3dd9\",\n          \"x\": 39.5,\n          \"y\": 340.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 40,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b77923f6-920e-4134-bb5f-3bd3d124532d\",\n          \"x\": 78.5,\n          \"y\": 340.5\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">2</span>\",\n          \"x\": 40,\n          \"y\": 349,\n          \"width\": 40,\n          \"height\": 24,\n          \"id\": \"1452f140-20f5-4303-a535-5c053ed0f7ab\",\n          \"marginOffset\": 10.828125\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Nunito\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1011,\n              \"des\": -353,\n              \"tAsc\": 1011,\n              \"tDes\": -353,\n              \"tLGap\": 0,\n              \"wAsc\": 1092,\n              \"wDes\": 281,\n              \"xH\": 487,\n              \"capH\": 705,\n              \"yMin\": -275,\n              \"yMax\": 1081,\n              \"hAsc\": 1011,\n              \"hDes\": -353,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300\\\">Braids and bobby pins</span>\",\n          \"width\": 276,\n          \"height\": 32,\n          \"id\": \"78190b80-771a-443b-a30e-744e8ceb500a\",\n          \"x\": 96,\n          \"y\": 346\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"A quick fishtail braid or fringe twist transforms your look in seconds! Pulling hair away from your face and into a plait embraces the mood and transforms a bad hair day into an effortless style.\",\n          \"width\": 276,\n          \"height\": 177,\n          \"id\": \"019520da-e6c9-4a42-ab0d-eb3a81e5d4e4\",\n          \"x\": 96,\n          \"y\": 392,\n          \"marginOffset\": 5.957999999999998\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Nunito\", \"Karla\"],\n      \"id\": \"6074e40e-c120-498b-81d4-dc6337166914\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"6ce84846-af53-42c0-af00-a60dce067cd0\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Dancing Script\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"cursive\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 920,\n              \"des\": -280,\n              \"tAsc\": 920,\n              \"tDes\": -280,\n              \"tLGap\": 0,\n              \"wAsc\": 1096,\n              \"wDes\": 306,\n              \"xH\": 332,\n              \"capH\": 720,\n              \"yMin\": -284,\n              \"yMax\": 1095,\n              \"hAsc\": 920,\n              \"hDes\": -280,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 65,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"color: #ff96b5\\\">Eyeshadow</span>\\n<span style=\\\"color: #ff96b5\\\">Makeup</span>\",\n          \"width\": 332,\n          \"height\": 155,\n          \"marginOffset\": 21.65625,\n          \"id\": \"a4c10384-278e-48a5-a16c-ccb9a2002dba\",\n          \"x\": 40,\n          \"y\": 342\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 700],\n            \"styles\": [\"italic\"],\n            \"variants\": [\n              [0, 300],\n              [0, 700],\n              [1, 300]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 2189,\n              \"des\": -600,\n              \"tAsc\": 1567,\n              \"tDes\": -492,\n              \"tLGap\": 132,\n              \"wAsc\": 2189,\n              \"wDes\": 600,\n              \"xH\": 1085,\n              \"capH\": 1462,\n              \"yMin\": -512,\n              \"yMax\": 2132,\n              \"hAsc\": 2189,\n              \"hDes\": -600,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 23,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 300; color: #444; letter-spacing: 0.02em\\\">Quick Tutorial for Beginners</span>\",\n          \"width\": 332,\n          \"height\": 33,\n          \"id\": \"c6758347-f6c5-4225-a276-e1853ecff8eb\",\n          \"x\": 40,\n          \"y\": 518\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Dancing Script\", \"Roboto Condensed\"],\n      \"id\": \"f3ff9526-189a-4eb5-8e5b-1b38228a562b\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/raw/table.json",
    "content": "{\n  \"version\": 47,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"27703533-bcd6-4ddf-80c0-0f7573645d8c\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"vertical\": 0, \"horizontal\": 0, \"locked\": true },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Most Expensive Robots</span>\",\n          \"x\": 41,\n          \"y\": 183,\n          \"width\": 331,\n          \"height\": 31,\n          \"id\": \"6cfb2f63-bb73-426f-a8cc-aadb2b5d4ad5\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 41,\n          \"y\": 231,\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"7e480110-14ff-4ac7-92ee-b23f6a8d1366\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Asimo\",\n          \"x\": 41,\n          \"y\": 240,\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"f1c8f5eb-244b-410a-b889-b1941ab8b05d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Valkyrie\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"fd1ccbd1-2281-41a1-b2fe-898c19c5210a\",\n          \"x\": 41,\n          \"y\": 275\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Atlas\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"94e7dbf3-9258-46b5-b9de-c582ac68460b\",\n          \"x\": 41,\n          \"y\": 310\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Kuratas\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"3e205a8e-8fb1-4aa0-8078-51993882297a\",\n          \"x\": 41,\n          \"y\": 345\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Hubo II\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"5fcab657-f470-414f-83eb-45e6975542ba\",\n          \"x\": 41,\n          \"y\": 380\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4ad591d3-f5a8-4ee8-b514-fd5130944c18\",\n          \"x\": 41,\n          \"y\": 415\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$2.5 Million</span>\",\n          \"x\": 272,\n          \"y\": 240,\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"11b6e3dc-5de2-4989-9d5e-5bd7fd8971d3\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$2 Million</span>\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"b26ebb98-47cc-4431-b70e-9eb65acd50fd\",\n          \"x\": 272,\n          \"y\": 275\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$2 Million</span>\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"67020819-fffb-4983-a689-1d8503dcfcf1\",\n          \"x\": 272,\n          \"y\": 310\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$1.3 Million</span>\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"93fba19b-2d49-465e-99d4-b32f436d45e2\",\n          \"x\": 272,\n          \"y\": 345\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$400,000</span>\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"b2725bf6-8f39-4515-96b4-8023af950b05\",\n          \"x\": 272,\n          \"y\": 380\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Roboto\"],\n      \"id\": \"64a7810a-b11c-48ae-b8f9-4820af17bf84\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"fbc49dce-2eea-4214-b8d9-134bd15d4942\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Local Transportation</span>\",\n          \"width\": 331,\n          \"height\": 33,\n          \"id\": \"285e5007-d535-4b3d-acd6-cc745dd1e011\",\n          \"x\": 41,\n          \"y\": 196\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"45996c9d-a162-4fb0-9b1f-afe80221df49\",\n          \"x\": 41,\n          \"y\": 314\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8fa19274-3cf7-4379-a178-c697ca11aa6c\",\n          \"x\": 41,\n          \"y\": 275\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Muni\",\n          \"width\": 231,\n          \"height\": 22,\n          \"id\": \"5dcf1716-5ca4-4467-9efd-97180dd6bfa2\",\n          \"x\": 41,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Muni\",\n          \"width\": 231,\n          \"height\": 22,\n          \"id\": \"16d8ea91-c4ed-4f1d-80d6-26861d3408ed\",\n          \"x\": 41,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"BART\",\n          \"width\": 231,\n          \"height\": 22,\n          \"id\": \"1441935b-5b8b-427c-9518-1be5e77b24c7\",\n          \"x\": 42,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"AC Transit\",\n          \"width\": 231,\n          \"height\": 22,\n          \"id\": \"e847e1bd-6156-407e-917b-4b4946c72bfe\",\n          \"x\": 42,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"CalTran\",\n          \"width\": 231,\n          \"height\": 22,\n          \"id\": \"2fbcfe82-26f4-4369-b2bc-49a2bb945c09\",\n          \"x\": 42,\n          \"y\": 400\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Bus</span>\",\n          \"width\": 100,\n          \"height\": 22,\n          \"id\": \"5ab3c137-a155-4895-acb9-4b6861e4fde9\",\n          \"x\": 272,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 918,\n              \"des\": -335,\n              \"tAsc\": 918,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1036,\n              \"wDes\": 335,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -335,\n              \"yMax\": 1002,\n              \"hAsc\": 918,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Rail</span>\",\n          \"width\": 100,\n          \"height\": 22,\n          \"id\": \"88f625cb-de28-4b06-b428-d37118075162\",\n          \"x\": 272,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Train</span>\",\n          \"width\": 100,\n          \"height\": 22,\n          \"id\": \"3416ef7b-05ea-47db-b53a-5ff21fb313d3\",\n          \"x\": 273,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Bus</span>\",\n          \"width\": 100,\n          \"height\": 22,\n          \"id\": \"26225f34-2d96-468c-9730-5bc55775d532\",\n          \"x\": 273,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Train</span>\",\n          \"width\": 100,\n          \"height\": 22,\n          \"id\": \"cb1a4cfe-48a2-4633-b7ee-eaac27e20cf3\",\n          \"x\": 273,\n          \"y\": 400\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"25c860ab-51db-419f-9b35-09a5cc90d5e5\",\n          \"x\": 41,\n          \"y\": 353\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b50a8880-19d1-4ba1-99cc-d22d9bc0073d\",\n          \"x\": 41,\n          \"y\": 392\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\"],\n      \"id\": \"2f0bbc9f-65d8-4da8-bc87-6be32e970243\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"343a8b28-3932-4e0f-847e-aa69ce34e375\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Poppins\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1050,\n              \"des\": -350,\n              \"tAsc\": 1050,\n              \"tDes\": -350,\n              \"tLGap\": 100,\n              \"wAsc\": 1135,\n              \"wDes\": 627,\n              \"xH\": 548,\n              \"capH\": 698,\n              \"yMin\": -572,\n              \"yMax\": 1065,\n              \"hAsc\": 1050,\n              \"hDes\": -350,\n              \"lGap\": 100\n            }\n          },\n          \"fontSize\": 31,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.03em\\\">Light Needs</span>\",\n          \"width\": 331,\n          \"height\": 43,\n          \"id\": \"2b95ebb6-f095-4501-a0b9-540c78efdb76\",\n          \"x\": 41,\n          \"y\": 221\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 4,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"dfb4c355-e101-47d7-b6f6-66fa128106a7\",\n          \"x\": 41,\n          \"y\": 201\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Palms\",\n          \"width\": 231,\n          \"height\": 23,\n          \"id\": \"1d9c3ea3-c165-4f31-b018-8e01afde53e6\",\n          \"x\": 41,\n          \"y\": 271\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Ferns\",\n          \"width\": 231,\n          \"height\": 23,\n          \"id\": \"acc90a9d-ba38-4052-b03c-7f382f6d1acd\",\n          \"x\": 41,\n          \"y\": 302\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Succulents\",\n          \"width\": 231,\n          \"height\": 23,\n          \"id\": \"696ecc2a-9806-47b1-911f-1f64d52d7be5\",\n          \"x\": 41,\n          \"y\": 333\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Herbs\",\n          \"width\": 231,\n          \"height\": 23,\n          \"id\": \"33118e89-5f05-4c87-9292-f715660e55aa\",\n          \"x\": 41,\n          \"y\": 364\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Flowers\",\n          \"width\": 231,\n          \"height\": 23,\n          \"id\": \"7379c302-0225-484d-acb0-1e48b2b0d82f\",\n          \"x\": 41,\n          \"y\": 395\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Indirect\",\n          \"width\": 100,\n          \"height\": 23,\n          \"id\": \"8eb0169f-2ce6-4bb0-bc52-60ab0d2ecaad\",\n          \"x\": 272,\n          \"y\": 271\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Partial\",\n          \"width\": 100,\n          \"height\": 23,\n          \"id\": \"d1a33bdd-edde-4bb1-9dce-d61681638581\",\n          \"x\": 272,\n          \"y\": 302\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Medium\",\n          \"width\": 100,\n          \"height\": 23,\n          \"id\": \"217defea-1605-4b13-a5bc-0a7df4cf37aa\",\n          \"x\": 272,\n          \"y\": 333\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"High\",\n          \"width\": 100,\n          \"height\": 23,\n          \"id\": \"b4bdf110-6cb9-419d-9957-e1fc4531c1bb\",\n          \"x\": 272,\n          \"y\": 364\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"IBM Plex Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1025,\n              \"des\": -275,\n              \"tAsc\": 780,\n              \"tDes\": -220,\n              \"tLGap\": 300,\n              \"wAsc\": 1025,\n              \"wDes\": 275,\n              \"xH\": 516,\n              \"capH\": 698,\n              \"yMin\": -245,\n              \"yMax\": 1119,\n              \"hAsc\": 1025,\n              \"hDes\": -275,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Maximum\",\n          \"width\": 100,\n          \"height\": 23,\n          \"id\": \"882f55cb-6f30-4846-ad14-3a35ac3a910e\",\n          \"x\": 272,\n          \"y\": 395\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Poppins\", \"IBM Plex Sans\"],\n      \"id\": \"f90daf3c-f7ef-4b25-b31c-5edbdf61c517\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2b57bbe2-dbb7-4ac8-91ab-9553a83431c1\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Source Serif 4\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1036,\n              \"des\": -335,\n              \"tAsc\": 1036,\n              \"tDes\": -335,\n              \"tLGap\": 0,\n              \"wAsc\": 1009,\n              \"wDes\": 324,\n              \"xH\": 475,\n              \"capH\": 670,\n              \"yMin\": -321,\n              \"yMax\": 1003,\n              \"hAsc\": 1036,\n              \"hDes\": -335,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase\\\">Self Care Gifts</span>\",\n          \"width\": 238,\n          \"height\": 29,\n          \"id\": \"8d0739f1-537e-4ce4-bc5e-0e6ded648670\",\n          \"x\": 88,\n          \"y\": 189\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"8dd2e805-d729-412d-a40d-29c55d17a2eb\",\n          \"x\": 41,\n          \"y\": 314\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"50f100d5-4481-433e-8e08-abe1e1452ff8\",\n          \"x\": 41,\n          \"y\": 270\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Meditation Bench\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"fd063d64-6bde-4214-b75c-0743d6e835b3\",\n          \"x\": 41,\n          \"y\": 235\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Yoga Mat\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"4a682269-3ba8-4f7c-9f37-a42cb0cb74b4\",\n          \"x\": 41,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Journal\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"a494161b-a715-4e6b-a318-439db3299028\",\n          \"x\": 42,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Gym Membership\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"cbb00b75-84e5-4489-9e5f-70bbba2edb26\",\n          \"x\": 42,\n          \"y\": 367\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Hugs\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"836156b8-0f13-4fc1-abb8-560c8006e244\",\n          \"x\": 42,\n          \"y\": 411\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$100\",\n          \"width\": 100,\n          \"height\": 24,\n          \"id\": \"af54ad2c-0711-4028-931a-f9d872fa61cb\",\n          \"x\": 272,\n          \"y\": 235\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$60\",\n          \"width\": 100,\n          \"height\": 24,\n          \"id\": \"74cc4e82-f838-4581-9351-ae99e0fbc485\",\n          \"x\": 272,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$5 - $25\",\n          \"width\": 100,\n          \"height\": 24,\n          \"id\": \"919bbfb1-755f-440c-83d2-4c0726ce3af0\",\n          \"x\": 273,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$30/month\",\n          \"width\": 100,\n          \"height\": 24,\n          \"id\": \"eca735fc-fc7f-478c-aa0c-6438d03ceb49\",\n          \"x\": 273,\n          \"y\": 367\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Free\",\n          \"width\": 100,\n          \"height\": 24,\n          \"id\": \"fe0227e8-1077-4e80-8a74-9c230be11642\",\n          \"x\": 273,\n          \"y\": 411\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"758a4943-8039-494b-b97b-da55da993a5f\",\n          \"x\": 41,\n          \"y\": 358\n        },\n        {\n          \"opacity\": 20,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"24590da6-c538-4c4f-a09d-afa2e55e6d44\",\n          \"x\": 41,\n          \"y\": 402\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"x\": 40,\n          \"y\": 203,\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"2a9dfe8b-af99-4dbd-90f0-c71bfeaee950\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"541d992e-9ad7-4e1f-9568-23af5a7a17a5\",\n          \"x\": 342,\n          \"y\": 203\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Source Serif 4\", \"Lora\", \"Playfair Display\"],\n      \"id\": \"c867f325-0f47-4d8b-8e3f-6eaa1c59030f\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"2137b448-cc23-4b1e-8ca1-58f83bf79b58\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 19,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Minimalist Types</span>\",\n          \"width\": 331,\n          \"height\": 27,\n          \"id\": \"f73e0297-1e74-4df6-903c-265df1481a88\",\n          \"x\": 41,\n          \"y\": 185\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0cccce3a-7ea2-428c-a04b-c6cb2bf73e26\",\n          \"x\": 41,\n          \"y\": 311\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"b6c57d67-11f5-4a05-b6c9-f1861bcd0b74\",\n          \"x\": 41,\n          \"y\": 267\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [1, 300],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Frugal\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"b3d5f68c-da1d-4a6a-808d-812c01c5aa5d\",\n          \"x\": 41,\n          \"y\": 235\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Green\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"292c632a-edae-4e44-a31e-49119f5b9281\",\n          \"x\": 41,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Nomad\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"910acfbf-59da-4b59-9a77-6fd20473db7d\",\n          \"x\": 42,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Aesthetic\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"16515d79-a2e5-4012-8423-96ee7c495cd4\",\n          \"x\": 42,\n          \"y\": 367\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Challenge\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"464f9c6b-943a-4172-9400-3e51376b90fb\",\n          \"x\": 42,\n          \"y\": 408\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Reduce &amp; reuse\",\n          \"width\": 113,\n          \"height\": 21,\n          \"id\": \"b878731a-d488-4cbc-b6e7-b930eae92b79\",\n          \"x\": 259,\n          \"y\": 235\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Eco-friendly\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"d00b14c8-bfe8-48e3-bef7-84e5ed7f5851\",\n          \"x\": 272,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Travel essentials\",\n          \"width\": 122,\n          \"height\": 21,\n          \"id\": \"64be7770-c026-456d-836e-6fd307111b15\",\n          \"x\": 251,\n          \"y\": 323\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Beautifully blank\",\n          \"width\": 131,\n          \"height\": 21,\n          \"id\": \"ddd2161e-1f4d-41ba-b581-21af64648304\",\n          \"x\": 242,\n          \"y\": 367\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto Condensed\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [300, 400, 700],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Less is more\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"c084242d-80ff-44f3-ac3e-640ebbc1656b\",\n          \"x\": 273,\n          \"y\": 408\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"824dce32-7243-4eb3-9bd8-333e55a332cd\",\n          \"x\": 41,\n          \"y\": 355\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"793ab90f-35d8-46d1-b5c7-b15de318dc86\",\n          \"x\": 42,\n          \"y\": 399\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"197f2dcb-ec81-43b9-a128-6b453afa5f95\",\n          \"x\": 41,\n          \"y\": 223\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9e69cd18-8235-4d63-8187-d943575079f9\",\n          \"x\": 41,\n          \"y\": 175\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Roboto Condensed\"],\n      \"id\": \"46255a97-3e9e-444a-acb4-59be70044ac6\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"b22af226-96b3-4230-8f8d-ce065636a91d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Brew times\",\n          \"width\": 331,\n          \"height\": 34,\n          \"id\": \"ceb8a5d7-83ab-4d3d-8c40-4eb86d263f94\",\n          \"x\": 41,\n          \"y\": 193\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"86eb0bc9-3ef7-4fc4-904e-236bf8e0a589\",\n          \"x\": 41,\n          \"y\": 315\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"1b680c8e-0245-4793-9f06-c2eefd563d05\",\n          \"x\": 41,\n          \"y\": 275\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Drip\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"d458932f-0ab1-4083-ad3d-7f130ea3e1c0\",\n          \"x\": 41,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Pour Over\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"00029122-4425-433e-8119-f5ff79cf6f9f\",\n          \"x\": 41,\n          \"y\": 284\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"French Press\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"8f8f033e-3b88-4552-a0fb-e47f7c5a242c\",\n          \"x\": 42,\n          \"y\": 324\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Espresso\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"00a0da6d-af0f-419b-afb4-8ecf3e2c7133\",\n          \"x\": 42,\n          \"y\": 364\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Merriweather\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 984,\n              \"des\": -273,\n              \"tAsc\": 984,\n              \"tDes\": -273,\n              \"tLGap\": 0,\n              \"wAsc\": 1065,\n              \"wDes\": 273,\n              \"xH\": 555,\n              \"capH\": 743,\n              \"yMin\": -272,\n              \"yMax\": 1055,\n              \"hAsc\": 984,\n              \"hDes\": -273,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.6,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Cold brew\",\n          \"width\": 231,\n          \"height\": 21,\n          \"id\": \"969d0159-7f68-41b7-98f3-5f944f11e670\",\n          \"x\": 42,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"5 minutes\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"9712a3e6-dcd9-4c33-b1b6-e8a696ba9f01\",\n          \"x\": 272,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"5 minutes\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"1c98b558-dbea-46c8-b2cd-2e8a4bebb3eb\",\n          \"x\": 272,\n          \"y\": 284\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"6 minutes\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"e4befb0b-cfa2-402c-a43d-4ec28e3e37b7\",\n          \"x\": 273,\n          \"y\": 324\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"30 seconds\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"7db2ff6c-720f-4ff1-bc70-5ff4c8c648f6\",\n          \"x\": 273,\n          \"y\": 364\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Raleway\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 940,\n              \"des\": -234,\n              \"tAsc\": 940,\n              \"tDes\": -234,\n              \"tLGap\": 0,\n              \"wAsc\": 1154,\n              \"wDes\": 234,\n              \"xH\": 519,\n              \"capH\": 710,\n              \"yMin\": -223,\n              \"yMax\": 1151,\n              \"hAsc\": 940,\n              \"hDes\": -234,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Overnight\",\n          \"width\": 100,\n          \"height\": 21,\n          \"id\": \"4bc228fa-cb39-4101-9007-84e4705ec1d8\",\n          \"x\": 273,\n          \"y\": 404\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"0468061b-09db-4701-9e75-8c87de7152a3\",\n          \"x\": 42,\n          \"y\": 355\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 331,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"3c424294-d6c5-44e4-9af1-c9233540d504\",\n          \"x\": 41,\n          \"y\": 395\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Raleway\", \"Merriweather\"],\n      \"id\": \"85dbd7cd-ba41-4248-9487-a6b7f5dc4da1\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"60c99225-838c-4d69-9405-007d103c403a\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 600],\n              [0, 700],\n              [0, 900],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.1,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Team personality quizzes</span>\",\n          \"width\": 331,\n          \"height\": 40,\n          \"id\": \"0bbbbe21-4d2b-4fac-a074-742765b4514d\",\n          \"x\": 39,\n          \"y\": 184\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"Color Soul\",\n          \"width\": 332,\n          \"height\": 35,\n          \"id\": \"e061f22f-29b5-40c8-b961-7f77b4e30ab4\",\n          \"x\": 39,\n          \"y\": 233\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"Teamality\",\n          \"width\": 332,\n          \"height\": 35,\n          \"id\": \"d3414a40-4c98-4de1-b2b7-af067c1ea863\",\n          \"x\": 39,\n          \"y\": 272\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"Together Who\",\n          \"width\": 332,\n          \"height\": 35,\n          \"id\": \"54efc1f3-9d0d-4b88-a3b0-dd684e8404dc\",\n          \"x\": 39,\n          \"y\": 315\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"Group by numbers\",\n          \"width\": 332,\n          \"height\": 35,\n          \"id\": \"4286a076-f3f9-49d5-91da-7565d78e8805\",\n          \"x\": 39,\n          \"y\": 356\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"FILL\",\n          \"font\": {\n            \"family\": \"Work Sans\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 200, 300, 400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 100],\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 100],\n              [1, 200],\n              [1, 300],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 930,\n              \"des\": -243,\n              \"tAsc\": 930,\n              \"tDes\": -243,\n              \"tLGap\": 0,\n              \"wAsc\": 1105,\n              \"wDes\": 343,\n              \"xH\": 500,\n              \"capH\": 660,\n              \"yMin\": -337,\n              \"yMax\": 1100,\n              \"hAsc\": 930,\n              \"hDes\": -243,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0, \"a\": 0.05 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 8, \"vertical\": 8 },\n          \"type\": \"text\",\n          \"content\": \"Pieced Together\",\n          \"width\": 332,\n          \"height\": 35,\n          \"id\": \"53f32005-a806-48b1-8156-209d5c15e213\",\n          \"x\": 39,\n          \"y\": 397\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$5.00</span>\",\n          \"width\": 100,\n          \"height\": 26,\n          \"id\": \"7986ea38-8c10-45b3-95df-d830470642f1\",\n          \"x\": 263,\n          \"y\": 238\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$30.00</span>\",\n          \"width\": 100,\n          \"height\": 25,\n          \"id\": \"9374f87c-1778-4823-9ad0-83feb6b2c5e5\",\n          \"x\": 263,\n          \"y\": 279\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$45.00</span>\",\n          \"width\": 100,\n          \"height\": 25,\n          \"id\": \"ca632159-bae4-4159-a0dd-6ca16e1a266c\",\n          \"x\": 263,\n          \"y\": 320\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$80.00</span>\",\n          \"width\": 100,\n          \"height\": 25,\n          \"id\": \"1286e388-91c3-4cf6-8b6f-afbc89d75eb4\",\n          \"x\": 263,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Titillium Web\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 600, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 200],\n              [1, 200],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 600],\n              [1, 600],\n              [0, 700],\n              [1, 700],\n              [0, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1133,\n              \"des\": -388,\n              \"tAsc\": 1133,\n              \"tDes\": -388,\n              \"tLGap\": 0,\n              \"wAsc\": 1133,\n              \"wDes\": 388,\n              \"xH\": 500,\n              \"capH\": 692,\n              \"yMin\": -285,\n              \"yMax\": 1082,\n              \"hAsc\": 1133,\n              \"hDes\": -388,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">$120.00</span>\",\n          \"width\": 100,\n          \"height\": 25,\n          \"id\": \"e0430522-1729-4e89-9a26-abe10e8091c8\",\n          \"x\": 263,\n          \"y\": 402\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Titillium Web\", \"Work Sans\"],\n      \"id\": \"6f0273f6-31b1-48a9-b6a7-2ecba9098751\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"288baf91-d4c6-41e9-be40-5afdd06fa84d\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 267,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"11d0934e-dbd9-4977-9041-5da02269c7df\",\n          \"x\": 372,\n          \"y\": 176\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 267,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"9b6fe019-ac7d-46a4-b616-c9f129d5797b\",\n          \"x\": 41,\n          \"y\": 176\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"51ea243e-9186-469c-873a-1c3aac942e50\",\n          \"x\": 41,\n          \"y\": 443\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"72f1cb41-bfae-4327-9de7-4d91433277c5\",\n          \"x\": 41,\n          \"y\": 231\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"38acf74f-94c2-42f4-b796-2b65bd23ae13\",\n          \"x\": 41,\n          \"y\": 176\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 700],\n              [1, 400],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"All types\",\n          \"width\": 76,\n          \"height\": 21,\n          \"id\": \"14419bd4-8841-471a-aafd-a4666950ea55\",\n          \"x\": 285,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"All types\",\n          \"width\": 76,\n          \"height\": 21,\n          \"id\": \"8294b7a2-ff36-4135-97da-a44cef0b1dbc\",\n          \"x\": 285,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Fine\",\n          \"width\": 76,\n          \"height\": 21,\n          \"id\": \"ab194138-9aa6-4bf6-a3fd-cd9561937237\",\n          \"x\": 285,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Medium\",\n          \"width\": 76,\n          \"height\": 21,\n          \"id\": \"aad0c773-a12a-49bf-836c-b3f09f246774\",\n          \"x\": 285,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Curly\",\n          \"width\": 76,\n          \"height\": 21,\n          \"id\": \"8af1b892-6ced-45d6-a765-4811fc40f26d\",\n          \"x\": 285,\n          \"y\": 400\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Cream\",\n          \"width\": 207,\n          \"height\": 21,\n          \"id\": \"9c269db9-b63c-4da9-8933-c2f7447b73c4\",\n          \"x\": 57,\n          \"y\": 400\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Texturizer\",\n          \"width\": 207,\n          \"height\": 21,\n          \"id\": \"4f686cec-a322-4dd3-be07-9764bf56b121\",\n          \"x\": 57,\n          \"y\": 361\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Volumizer\",\n          \"width\": 207,\n          \"height\": 21,\n          \"id\": \"1c24a1dd-48af-4cec-a63b-171510492401\",\n          \"x\": 57,\n          \"y\": 322\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Mousse\",\n          \"width\": 207,\n          \"height\": 21,\n          \"id\": \"13f20b28-4ed4-4b66-bd23-590c110005af\",\n          \"x\": 57,\n          \"y\": 283\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Dry Shampoo\",\n          \"width\": 207,\n          \"height\": 21,\n          \"id\": \"6c0cd099-a2b9-47f2-9b3c-b812a0c02667\",\n          \"x\": 57,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Karla\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [400, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 917,\n              \"des\": -252,\n              \"tAsc\": 917,\n              \"tDes\": -252,\n              \"tLGap\": 0,\n              \"wAsc\": 917,\n              \"wDes\": 252,\n              \"xH\": 478,\n              \"capH\": 629,\n              \"yMin\": -246,\n              \"yMax\": 879,\n              \"hAsc\": 917,\n              \"hDes\": -252,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 18,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Best Products</span>\",\n          \"width\": 306,\n          \"height\": 21,\n          \"id\": \"b3f38031-b2a8-4933-9800-c830946af4f2\",\n          \"x\": 57,\n          \"y\": 192\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Karla\"],\n      \"id\": \"a2150663-53dc-4475-91b0-80ab58f2b2fb\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"369c5cf1-b3ee-4487-836f-f564e24e6994\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Playfair Display\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700, 800, 900],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [0, 800],\n              [0, 900],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700],\n              [1, 800],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1082,\n              \"des\": -251,\n              \"tAsc\": 1082,\n              \"tDes\": -251,\n              \"tLGap\": 0,\n              \"wAsc\": 1159,\n              \"wDes\": 251,\n              \"xH\": 514,\n              \"capH\": 708,\n              \"yMin\": -241,\n              \"yMax\": 1159,\n              \"hAsc\": 1082,\n              \"hDes\": -251,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 24,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"center\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase\\\">Menu Title</span>\",\n          \"width\": 172,\n          \"height\": 31,\n          \"id\": \"1154a9bb-09d5-4050-ab79-83d3b22eb0f8\",\n          \"x\": 120,\n          \"y\": 151\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"a77a4d5d-f2c8-49d9-86d8-c5a759caa08e\",\n          \"x\": 72,\n          \"y\": 166\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 32,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"f14195f1-40a5-42d0-ace9-2b5963a3a554\",\n          \"x\": 308,\n          \"y\": 166\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">List item</span>\",\n          \"width\": 73,\n          \"height\": 22,\n          \"id\": \"0fd9c2d5-f3ee-4d77-93af-5e21333ff62c\",\n          \"x\": 40,\n          \"y\": 206\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 41,\n          \"id\": \"7843f10c-b4a9-490a-a63e-87939c68838b\",\n          \"x\": 40,\n          \"y\": 236\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-style: italic\\\">$5.00</span>\",\n          \"width\": 44,\n          \"height\": 22,\n          \"id\": \"b310e54d-b91f-47d5-9877-26ab4d7687aa\",\n          \"x\": 328,\n          \"y\": 206\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">List item</span>\",\n          \"width\": 73,\n          \"height\": 22,\n          \"id\": \"4aaea416-7d2a-4e44-92b1-781f4b5ee950\",\n          \"x\": 40,\n          \"y\": 301\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 41,\n          \"id\": \"ffab1e28-686e-4c67-bd9c-a25450166b6b\",\n          \"x\": 40,\n          \"y\": 331\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-style: italic\\\">$5.00</span>\",\n          \"width\": 44,\n          \"height\": 22,\n          \"id\": \"4c80f92d-33fe-42d3-9e70-9cfe8f52dbc7\",\n          \"x\": 328,\n          \"y\": 301\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">List item</span>\",\n          \"width\": 73,\n          \"height\": 22,\n          \"id\": \"cfefbb8b-8f2a-454c-9291-782a0b77f7f4\",\n          \"x\": 40,\n          \"y\": 396\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\",\n            \"metrics\": {\n              \"upm\": 2048,\n              \"asc\": 1900,\n              \"des\": -500,\n              \"tAsc\": 1536,\n              \"tDes\": -512,\n              \"tLGap\": 102,\n              \"wAsc\": 1946,\n              \"wDes\": 512,\n              \"xH\": 1082,\n              \"capH\": 1456,\n              \"yMin\": -555,\n              \"yMax\": 2163,\n              \"hAsc\": 1900,\n              \"hDes\": -500,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 16,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 41,\n          \"id\": \"2679a442-aaec-448a-936c-85da286dab9e\",\n          \"x\": 40,\n          \"y\": 426\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lora\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"serif\"],\n            \"weights\": [400, 500, 600, 700],\n            \"styles\": [\"regular\", \"italic\"],\n            \"variants\": [\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700],\n              [1, 400],\n              [1, 500],\n              [1, 600],\n              [1, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1006,\n              \"des\": -274,\n              \"tAsc\": 1006,\n              \"tDes\": -274,\n              \"tLGap\": 0,\n              \"wAsc\": 1206,\n              \"wDes\": 294,\n              \"xH\": 500,\n              \"capH\": 700,\n              \"yMin\": -271,\n              \"yMax\": 1114,\n              \"hAsc\": 1006,\n              \"hDes\": -274,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"right\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-style: italic\\\">$5.00</span>\",\n          \"width\": 44,\n          \"height\": 22,\n          \"id\": \"91b604b2-c113-44f9-a13b-a40e5243b6b2\",\n          \"x\": 328,\n          \"y\": 396\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Playfair Display\", \"Lora\", \"Roboto\"],\n      \"id\": \"aca0d2aa-cd54-455f-aee6-eba7ffa3b226\"\n    },\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"55ad5d21-4fba-48fb-b5e3-244ed045c92e\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 332,\n          \"height\": 1,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"4a97f45a-d45f-46dd-bc9e-60d030145e35\",\n          \"x\": 40,\n          \"y\": 152\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 27,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.2,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 500; text-transform: uppercase\\\">Menu Title</span>\",\n          \"width\": 332,\n          \"height\": 39,\n          \"id\": \"13014c4f-15b3-4768-ac5c-d8a4b4c71d24\",\n          \"x\": 40,\n          \"y\": 177\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [0, 300],\n              [0, 400],\n              [0, 700],\n              [0, 900],\n              [1, 100],\n              [1, 300],\n              [1, 400],\n              [1, 700],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 34,\n          \"id\": \"824b92b2-8efc-484f-9ac0-94b49bb37d56\",\n          \"x\": 40,\n          \"y\": 274\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$5.00\",\n          \"width\": 44,\n          \"height\": 25,\n          \"id\": \"18585253-eb18-4b16-b1df-6bd7ad284eda\",\n          \"x\": 131,\n          \"y\": 240\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">List Item</span>\",\n          \"width\": 66,\n          \"height\": 26,\n          \"id\": \"0ad1b759-52b8-4509-9ebe-c980286b4ad6\",\n          \"x\": 40,\n          \"y\": 240\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 18,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"ee7ff455-be0f-40d3-81d9-9e6d66d7d6ca\",\n          \"x\": 118,\n          \"y\": 244\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 34,\n          \"id\": \"c09e2e28-2ac5-45cb-987f-dedd25e78a5c\",\n          \"x\": 40,\n          \"y\": 366\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$5.00\",\n          \"width\": 44,\n          \"height\": 25,\n          \"id\": \"07966784-5fee-4faf-a9f2-f5b806b1afc9\",\n          \"x\": 131,\n          \"y\": 332\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">List Item</span>\",\n          \"width\": 66,\n          \"height\": 26,\n          \"id\": \"27511f18-fdab-4af0-86c9-596d40bc83f1\",\n          \"x\": 40,\n          \"y\": 332\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 18,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"c560cae9-d49e-43d6-8dc8-d7323169995b\",\n          \"x\": 118,\n          \"y\": 336\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Lato\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [100, 300, 400, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"metrics\": {\n              \"upm\": 2000,\n              \"asc\": 1974,\n              \"des\": -426,\n              \"tAsc\": 1610,\n              \"tDes\": -390,\n              \"tLGap\": 400,\n              \"wAsc\": 1974,\n              \"wDes\": 426,\n              \"xH\": 1013,\n              \"capH\": 1433,\n              \"yMin\": -365,\n              \"yMax\": 1837,\n              \"hAsc\": 1974,\n              \"hDes\": -426,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.4,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"Caption: Web Stories immerse your readers in fast-loading full-screen experiences.\",\n          \"width\": 332,\n          \"height\": 34,\n          \"id\": \"91e9c338-5e93-4e04-ae2f-926915d4e9f6\",\n          \"x\": 40,\n          \"y\": 458\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"$5.00\",\n          \"width\": 44,\n          \"height\": 25,\n          \"id\": \"73fcca5f-9b69-4e4f-8632-67ca9a5446bc\",\n          \"x\": 131,\n          \"y\": 424\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Oswald\",\n            \"service\": \"fonts.google.com\",\n            \"fallbacks\": [\"sans-serif\"],\n            \"weights\": [200, 300, 400, 500, 600, 700],\n            \"styles\": [\"regular\"],\n            \"variants\": [\n              [0, 200],\n              [0, 300],\n              [0, 400],\n              [0, 500],\n              [0, 600],\n              [0, 700]\n            ],\n            \"metrics\": {\n              \"upm\": 1000,\n              \"asc\": 1193,\n              \"des\": -289,\n              \"tAsc\": 1193,\n              \"tDes\": -289,\n              \"tLGap\": 0,\n              \"wAsc\": 1325,\n              \"wDes\": 377,\n              \"xH\": 578,\n              \"capH\": 810,\n              \"yMin\": -287,\n              \"yMax\": 1297,\n              \"hAsc\": 1193,\n              \"hDes\": -289,\n              \"lGap\": 0\n            }\n          },\n          \"fontSize\": 17,\n          \"backgroundColor\": { \"color\": { \"r\": 196, \"g\": 196, \"b\": 196 } },\n          \"lineHeight\": 1.5,\n          \"textAlign\": \"left\",\n          \"padding\": { \"locked\": true, \"horizontal\": 0, \"vertical\": 0 },\n          \"type\": \"text\",\n          \"content\": \"<span style=\\\"font-weight: 700; text-transform: uppercase\\\">List Item</span>\",\n          \"width\": 66,\n          \"height\": 26,\n          \"id\": \"4d2c9e2b-17a6-4271-b505-671cf2ada8b5\",\n          \"x\": 40,\n          \"y\": 424\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": { \"vertical\": false, \"horizontal\": false },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": false,\n          \"backgroundColor\": { \"color\": { \"r\": 0, \"g\": 0, \"b\": 0 } },\n          \"type\": \"shape\",\n          \"width\": 1,\n          \"height\": 18,\n          \"mask\": { \"type\": \"rectangle\" },\n          \"id\": \"fb272342-dfb8-4eb8-9498-189121f50b08\",\n          \"x\": 118,\n          \"y\": 428\n        }\n      ],\n      \"animations\": [],\n      \"backgroundColor\": { \"color\": { \"r\": 255, \"g\": 255, \"b\": 255 } },\n      \"type\": \"page\",\n      \"fonts\": [\"Oswald\", \"Lato\"],\n      \"id\": \"07f4168e-3c83-4319-aefe-9cfd8ab39624\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/text-sets/src/test/raw.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { readdirSync, readFileSync } from 'fs';\nimport { resolve, basename } from 'path';\n\ndescribe('Raw text set files', () => {\n  const textSets = readdirSync(\n    resolve(process.cwd(), 'packages/text-sets/src/raw')\n  );\n\n  describe.each(textSets)('%s text set', (textSet) => {\n    const category = basename(textSet, '.json');\n    const rawData = readFileSync(\n      resolve(process.cwd(), `packages/text-sets/src/raw/${category}.json`),\n      'utf8'\n    );\n    const data = JSON.parse(rawData);\n\n    it('should contain at least two non-background elements', () => {\n      for (const { elements } of data.pages) {\n        // 3 since one is background element.\n        expect(elements.length >= 3).toBeTrue();\n      }\n    });\n\n    it('should contain fonts from global fonts list', () => {\n      const fonts = JSON.parse(\n        readFileSync(\n          resolve(process.cwd(), 'packages/fonts/src/fonts.json'),\n          'utf8'\n        )\n      );\n      const fontNames = fonts.map(({ family }) => family);\n\n      for (const { elements } of data.pages) {\n        for (const element of elements) {\n          // eslint-disable-next-line jest/no-conditional-in-test\n          if (!['text'].includes(element?.type)) {\n            continue;\n          }\n\n          expect(fontNames).toContain(element.font.family);\n        }\n      }\n    });\n\n    // @see https://github.com/GoogleForCreators/web-stories-wp/issues/10727\n    it('should not contain extraneous properties', () => {\n      const textSetData = JSON.parse(\n        readFileSync(\n          resolve(process.cwd(), `packages/text-sets/src/raw/${textSet}`),\n          'utf8'\n        )\n      );\n\n      expect(textSetData.current).toBeUndefined();\n      expect(textSetData.selection).toBeUndefined();\n      expect(textSetData.story).toBeUndefined();\n    });\n\n    it('should not contain invisible characters', () => {\n      const textSetData = JSON.parse(\n        readFileSync(\n          resolve(process.cwd(), `packages/text-sets/src/raw/${textSet}`),\n          'utf8'\n        )\n      );\n\n      expect(textSetData).not.toContain('\\u2028');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/text-sets/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport type { Page, StoryData, Element } from '@googleforcreators/elements';\n\nexport interface TextSetData extends Omit<StoryData, 'pages'> {\n  current: null;\n  selection: never[];\n  story: Record<string, never>;\n  version: number;\n  pages: TextSetPage[];\n}\n\nexport interface TextSetPage extends Page {\n  fonts: string[];\n  id: string;\n}\n\nexport interface MinMax {\n  minX: number;\n  maxX: number;\n  minY: number;\n  maxY: number;\n}\n\nexport interface TextSetElement extends Element {\n  normalizedOffsetX: number;\n  normalizedOffsetY: number;\n  textSetWidth: number;\n  textSetHeight: number;\n}\n\nexport interface TextSet {\n  id: string;\n  elements: TextSetElement[];\n  textSetCategory: string;\n  textSetFonts: string[];\n}\n\nexport interface TextSets {\n  cover: TextSet[];\n  step: TextSet[];\n  section_header: TextSet[];\n  editorial: TextSet[];\n  contact: TextSet[];\n  table: TextSet[];\n  list: TextSet[];\n  quote: TextSet[];\n}\n\nexport enum TextSetType {\n  Cover = 'cover',\n  Step = 'step',\n  SectionHeader = 'section_header',\n  Editorial = 'editorial',\n  Contact = 'contact',\n  Table = 'table',\n  List = 'list',\n  Quote = 'quote',\n}\n"
  },
  {
    "path": "packages/text-sets/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../elements\" }, { \"path\": \"../migration\" }],\n  /* Excludes the raw JSON files */\n  \"include\": [\"src/*\"]\n}\n"
  },
  {
    "path": "packages/tinymce-button/README.md",
    "content": "# TinyMCE Button\n\nAdds a button to WordPress's TinyMCE interface.\n"
  },
  {
    "path": "packages/tinymce-button/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/tinymce-button\",\n  \"description\": \"Web Stories TinyMCE integration for  the WordPress classic editor\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/tinymce-button/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/tinymce-button\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@wordpress/components\": \"^32.5.0\",\n    \"@wordpress/compose\": \"^7.22.0\",\n    \"@wordpress/data\": \"^10.22.0\",\n    \"@wordpress/dom-ready\": \"^4.22.0\",\n    \"@wordpress/element\": \"^6.32.0\",\n    \"@wordpress/i18n\": \"^6.16.0\",\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^16.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/tinymce-button/src/components/Modal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport {\n  Modal,\n  RangeControl,\n  SelectControl,\n  Button,\n  TextControl,\n  RadioControl,\n} from '@wordpress/components';\nimport { dispatch, select } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { updateViewSettings } from '../utils';\nimport store from '../store';\n\nimport TinyMceToggle from './controls/Toggle';\n\nconst WebStoriesModal = (props) => {\n  const { modalOpen, settings = {}, prepareShortCode } = props;\n  const {\n    author,\n    date,\n    title,\n    number_of_stories,\n    order,\n    orderby,\n    view,\n    excerpt,\n    image_alignment,\n    archive_link,\n    circle_size,\n    number_of_columns,\n    sharp_corners,\n    archive_link_label,\n  } = settings;\n  const { views = [], fields } = window.webStoriesData || {};\n\n  const displayField = (fieldName) =>\n    fields?.[view][fieldName].show && !fields?.[view][fieldName].hidden;\n\n  if (!modalOpen) {\n    return null;\n  }\n\n  return (\n    <Modal\n      onRequestClose={() => {\n        dispatch(store).toggleModal(false);\n      }}\n      closeButtonLabel={__('Close', 'web-stories')}\n      title={__('Web Stories', 'web-stories')}\n      className={'component_web_stories_mce_model'}\n      shouldCloseOnClickOutside={false}\n    >\n      <SelectControl\n        label={__('Select Layout', 'web-stories')}\n        value={view}\n        options={views}\n        onChange={(view_type) => {\n          dispatch(store).setCurrentView(view_type);\n        }}\n        __nextHasNoMarginBottom\n        __next40pxDefaultSize\n      />\n\n      <RangeControl\n        label={__('Number of Stories', 'web-stories')}\n        value={number_of_stories}\n        min={1}\n        max={20}\n        onChange={(value) => {\n          updateViewSettings({\n            fieldObj: Number(value),\n            field: 'number_of_stories',\n          });\n        }}\n        __nextHasNoMarginBottom\n        __next40pxDefaultSize\n      />\n\n      <SelectControl\n        label={__('Order By', 'web-stories')}\n        value={orderby}\n        options={[\n          {\n            value: 'post_date',\n            label: __('Date', 'web-stories'),\n          },\n          {\n            value: 'post_title',\n            label: __('Title', 'web-stories'),\n          },\n        ]}\n        onChange={(value) => {\n          updateViewSettings({ fieldObj: value, field: 'orderby' });\n        }}\n        __nextHasNoMarginBottom\n        __next40pxDefaultSize\n      />\n\n      <SelectControl\n        label={__('Order', 'web-stories')}\n        value={order}\n        options={[\n          {\n            value: 'ASC',\n            label: __('Ascending', 'web-stories'),\n          },\n          {\n            value: 'DESC',\n            label: __('Descending', 'web-stories'),\n          },\n        ]}\n        onChange={(value) => {\n          updateViewSettings({ fieldObj: value, field: 'order' });\n        }}\n        __nextHasNoMarginBottom\n        __next40pxDefaultSize\n      />\n\n      <TinyMceToggle field=\"title\" fieldObj={title} />\n\n      <TinyMceToggle field=\"excerpt\" fieldObj={excerpt} />\n\n      <TinyMceToggle field=\"author\" fieldObj={author} />\n\n      <TinyMceToggle field=\"date\" fieldObj={date} />\n\n      {displayField('image_alignment') && (\n        <div style={{ margin: '0 0 10px 0' }}>\n          <RadioControl\n            label={__('Image Alignment', 'web-stories')}\n            selected={image_alignment}\n            options={[\n              {\n                value: 'left',\n                label: __('Left', 'web-stories'),\n              },\n              {\n                value: 'right',\n                label: __('Right', 'web-stories'),\n              },\n            ]}\n            onChange={(value) => {\n              updateViewSettings({\n                fieldObj: value,\n                field: 'image_alignment',\n              });\n            }}\n            __nextHasNoMarginBottom\n          />\n        </div>\n      )}\n\n      <TinyMceToggle field=\"sharp_corners\" fieldObj={sharp_corners} />\n\n      <TinyMceToggle field=\"archive_link\" fieldObj={archive_link} />\n\n      {archive_link?.show && (\n        <TextControl\n          label={__('Archive Link Label', 'web-stories')}\n          value={archive_link_label}\n          onChange={(value) => {\n            updateViewSettings({\n              fieldObj: value,\n              field: 'archive_link_label',\n            });\n          }}\n          __nextHasNoMarginBottom\n          __next40pxDefaultSize\n        />\n      )}\n\n      {circle_size?.show && (\n        <RangeControl\n          label={__('Circle Size', 'web-stories')}\n          value={circle_size}\n          min={80}\n          max={200}\n          step={5}\n          onChange={(size) =>\n            updateViewSettings({\n              fieldObj: Number(size),\n              field: 'circle_size',\n            })\n          }\n          __nextHasNoMarginBottom\n          __next40pxDefaultSize\n        />\n      )}\n\n      {displayField('number_of_columns') && (\n        <RangeControl\n          label={__('Number of Columns', 'web-stories')}\n          value={number_of_columns}\n          min={1}\n          max={4}\n          onChange={(value) =>\n            updateViewSettings({\n              fieldObj: Number(value),\n              field: 'number_of_columns',\n            })\n          }\n          __nextHasNoMarginBottom\n          __next40pxDefaultSize\n        />\n      )}\n\n      <div style={{ padding: '20px 0' }} className=\"alignright\">\n        <Button\n          isPrimary\n          onClick={() => {\n            const editorInstance = select(store).getEditor();\n            if (editorInstance) {\n              const shortcode = prepareShortCode();\n              editorInstance.insertContent(shortcode);\n            }\n\n            dispatch(store).toggleModal(false);\n          }}\n        >\n          {__('Insert', 'web-stories')}\n        </Button>\n        <Button onClick={() => dispatch(store).toggleModal(false)}>\n          {__('Cancel', 'web-stories')}\n        </Button>\n      </div>\n    </Modal>\n  );\n};\n\nconst StateFulFieldShape = PropTypes.shape({\n  show: PropTypes.bool,\n  label: PropTypes.string,\n  hidden: PropTypes.bool,\n});\n\nWebStoriesModal.propTypes = {\n  modalOpen: PropTypes.bool,\n  settings: PropTypes.shape({\n    author: StateFulFieldShape,\n    title: StateFulFieldShape,\n    excerpt: StateFulFieldShape,\n    image_alignment: StateFulFieldShape,\n    archive_link: StateFulFieldShape,\n    archive_link_label: PropTypes.string,\n    sharp_corners: StateFulFieldShape,\n    date: StateFulFieldShape,\n    number_of_columns: PropTypes.number,\n    number_of_stories: PropTypes.number,\n    orderby: PropTypes.string,\n    order: PropTypes.string,\n    view: PropTypes.string,\n    circle_size: PropTypes.number,\n  }),\n  prepareShortCode: PropTypes.func,\n};\n\nexport default WebStoriesModal;\n"
  },
  {
    "path": "packages/tinymce-button/src/components/controls/Toggle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * WordPress dependencies\n */\nimport { ToggleControl } from '@wordpress/components';\n\n/**\n * Internal dependencies\n */\nimport { updateViewSettings } from '../../utils';\n\n/**\n * Toggle component for TinyMCE popup.\n *\n * @param {Object} props Component props.\n * @return {*} React component.\n */\nconst TinyMceToggle = (props) => {\n  const { fieldObj = {}, field } = props;\n  const { show, hidden, label } = fieldObj;\n\n  if (hidden) {\n    return null;\n  }\n\n  return (\n    <ToggleControl\n      label={label}\n      checked={show}\n      onChange={() => {\n        updateViewSettings({\n          fieldObj: fieldObj,\n          field: field,\n          hidden,\n        });\n      }}\n      __nextHasNoMarginBottom\n    />\n  );\n};\n\nTinyMceToggle.propTypes = {\n  fieldObj: PropTypes.shape({\n    show: PropTypes.bool,\n    label: PropTypes.string,\n    hidden: PropTypes.bool,\n  }),\n  field: PropTypes.string,\n};\n\nexport default TinyMceToggle;\n"
  },
  {
    "path": "packages/tinymce-button/src/components/controls/test/Toggle.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport TinyMceToggle from '../Toggle';\n\ndescribe('Toggle', () => {\n  it('should render nothing if hidden', () => {\n    const props = {\n      fieldObj: {\n        show: true,\n        hidden: true,\n        label: 'Test Control',\n      },\n      field: '',\n    };\n\n    render(<TinyMceToggle {...props} />);\n\n    expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();\n  });\n\n  it('should render toggle control', () => {\n    const props = {\n      fieldObj: {\n        show: true,\n        hidden: false,\n        label: 'Test Control',\n      },\n      field: '',\n    };\n\n    render(<TinyMceToggle {...props} />);\n\n    expect(screen.getByRole('checkbox')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/tinymce-button/src/components/test/Modal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport WebStoriesModal from '../Modal';\n\njest.mock('@wordpress/data', () => ({\n  select: jest.fn(() => ({\n    getCurrentView: () => 'grid',\n  })),\n  createReduxStore: jest.fn(),\n  combineReducers: jest.fn(),\n  register: jest.fn(),\n  createSelector: jest.fn(),\n}));\n\njest.mock('@wordpress/i18n', () => ({\n  ...jest.requireActual('@wordpress/i18n'),\n  // eslint-disable-next-line no-unused-vars -- Negligible.\n  __: (val, domain) => val,\n}));\n\njest.mock('../../utils', () => ({\n  updateViewSettings: jest.fn((settings) => settings),\n}));\n\ndescribe('Modal', () => {\n  it('renders modal with toggles', () => {\n    const props = {\n      modalOpen: true,\n      settings: {\n        archive_link: {\n          show: true,\n        },\n        title: {},\n        excerpt: {},\n        author: {},\n        date: {},\n      },\n      prepareShortCode: jest.fn(),\n    };\n\n    render(<WebStoriesModal {...props} />);\n    expect(screen.getByText(/Archive Link Label/i)).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/tinymce-button/src/containers/Modal.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { withSelect } from '@wordpress/data';\nimport { compose } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport WebStoriesModal from '../components/Modal';\nimport { prepareShortCode } from '../utils';\nimport store from '../store';\n\n/**\n *\n * Pass extended props to the Modal component.\n *\n * @param {Function} select Store selector.\n * @return {Object} Injected props.\n */\nconst mapSelectToProps = (select) => {\n  return {\n    modalOpen: select(store).getModal(),\n    settings: select(store).getCurrentViewSettings(),\n    prepareShortCode: prepareShortCode,\n  };\n};\n\n/**\n * Higher-order component.\n */\nexport default compose([withSelect(mapSelectToProps)])(WebStoriesModal);\n"
  },
  {
    "path": "packages/tinymce-button/src/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { render } from '@wordpress/element';\nimport { dispatch } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\nimport domReady from '@wordpress/dom-ready';\n\n/**\n * Internal dependencies\n */\nimport store from './store';\nimport WebStoriesModal from './containers/Modal';\n\nconst { _ } = window;\n\n/**\n * This is a patch for TinyMCE editor to insert content\n * using `insertContent` method.\n *\n * WP still uses `_.pluck` method\n * https://github.com/WordPress/WordPress/blob/master/wp-includes/js/mce-view.js#L145\n * lodash (which WP uses now) does not have this method, so there will be JS error in console.\n */\n// eslint-disable-next-line no-prototype-builtins -- False positive because this is Lodash.\nif (!_.hasOwnProperty('pluck')) {\n  _.pluck = _.map;\n}\n\n// eslint-disable-next-line prefer-arrow-callback -- Must not be an arrow function.\ntinymce.PluginManager.add('web_stories', function (editor) {\n  editor.addButton('web_stories', {\n    text: __('Web Stories', 'web-stories'),\n    classes: 'web-stories',\n    image:\n      'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjA4IiBoZWlnaHQ9IjIwOCIgdmlld0JveD0iMCAwIDIwOCAyMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjEwMCIgY3k9IjEwMCIgcj0iMTAwIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNMTM1LjIgNjIuNDAwNUMxNDAuOTQ0IDYyLjQwMDUgMTQ1LjYgNjcuMDU2NyAxNDUuNiA3Mi44MDA1VjEzNS4yQzE0NS42IDE0MC45NDQgMTQwLjk0NCAxNDUuNiAxMzUuMiAxNDUuNlY2Mi40MDA1WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTU3LjIgNjIuNDAwNUM1Ny4yIDU2LjY1NjcgNjEuODU2MiA1Mi4wMDA1IDY3LjYgNTIuMDAwNUgxMTQuNEMxMjAuMTQ0IDUyLjAwMDUgMTI0LjggNTYuNjU2NyAxMjQuOCA2Mi40MDA1VjE0NS42QzEyNC44IDE1MS4zNDQgMTIwLjE0NCAxNTYgMTE0LjQgMTU2SDY3LjZDNjEuODU2MiAxNTYgNTcuMiAxNTEuMzQ0IDU3LjIgMTQ1LjZWNjIuNDAwNVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0xNTYgNzIuODAwNUMxNjAuMzA4IDcyLjgwMDUgMTYzLjggNzYuMjkyNyAxNjMuOCA4MC42MDA1VjEyNy40QzE2My44IDEzMS43MDggMTYwLjMwOCAxMzUuMiAxNTYgMTM1LjJWNzIuODAwNVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPg==',\n    onClick: function () {\n      dispatch(store).setEditor(editor);\n      dispatch(store).toggleModal(true);\n    },\n  });\n});\n\ndomReady(() => {\n  const target = document.getElementById('web-stories-tinymce');\n\n  if (target) {\n    render(<WebStoriesModal />, target);\n  }\n});\n"
  },
  {
    "path": "packages/tinymce-button/src/store/actions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function setSettings(settings) {\n  return {\n    type: 'SET_SETTINGS',\n    settings: settings,\n  };\n}\n\nexport function toggleModal(open) {\n  return {\n    type: 'TOGGLE_MODAL',\n    modalOpen: open,\n  };\n}\n\nexport function setEditor(editor) {\n  return {\n    type: 'SET_EDITOR',\n    editor: editor,\n  };\n}\n\n/**\n * Set current view.\n *\n * @param {string} view Current view.\n * @return {Object} Current view action object.\n */\nexport function setCurrentView(view) {\n  return {\n    type: 'SET_CURRENT_VIEW',\n    currentView: view,\n  };\n}\n\n/**\n * Set view settings.\n *\n * @param {Array} view Views list.\n * @param {Object} settings Settings object.\n * @return {Object} View settings object.\n */\nexport function setViewSettings(view, settings) {\n  return {\n    type: 'SET_VIEW_SETTINGS',\n    view: view,\n    settings: settings,\n  };\n}\n"
  },
  {
    "path": "packages/tinymce-button/src/store/default.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Set default setting state per se view type.\n *\n * @return {Object} Settings.\n */\nconst setDefaultStateSetting = () => {\n  const state = [];\n  const { views = [], fields } = window.webStoriesData || {};\n\n  views.forEach((value) => {\n    const { value: viewType } = value;\n    const { title, author, date, excerpt, archive_link, sharp_corners } =\n      fields[viewType];\n\n    state[viewType] = {\n      title,\n      excerpt,\n      author,\n      date,\n      archive_link,\n      archive_link_label: '',\n      circle_size: 150,\n      sharp_corners,\n      image_alignment: 'left',\n      number_of_columns: 1,\n      number_of_stories: 5,\n      order: 'DESC',\n      orderby: 'post_title',\n      view: viewType,\n    };\n  });\n\n  return state;\n};\n\nconst DEFAULT_STATE = {\n  settings: setDefaultStateSetting(),\n  modalOpen: false,\n  editor: false,\n  currentView: 'circles',\n};\n\nexport default DEFAULT_STATE;\n"
  },
  {
    "path": "packages/tinymce-button/src/store/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as actions from './actions';\nimport reducer from './reducers';\nimport * as selectors from './selectors';\n\nconst name = 'web-stories-mce';\n\nconst store = createReduxStore(name, {\n  actions,\n  reducer,\n  selectors,\n});\n\nregister(store);\n\nexport default store;\n"
  },
  {
    "path": "packages/tinymce-button/src/store/reducers.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport DEFAULT_STATE from './default';\n\n/**\n * Store reducer.\n *\n * @param {Object} state Current state for the data store.\n * @param {Object} action Action object for manipulating state.\n * @return {Object} New Manipulated state for the store.\n */\nfunction reducer(state = DEFAULT_STATE, action) {\n  switch (action.type) {\n    case 'SET_SETTINGS':\n      return {\n        ...state,\n        settings: action.settings,\n      };\n\n    case 'TOGGLE_MODAL':\n      return {\n        ...state,\n        modalOpen: action.modalOpen,\n      };\n\n    case 'SET_EDITOR':\n      return {\n        ...state,\n        editor: action.editor,\n      };\n\n    case 'SET_CURRENT_VIEW':\n      return {\n        ...state,\n        currentView: action.currentView,\n      };\n\n    case 'SET_VIEW_SETTINGS':\n      return {\n        ...state,\n        settings: {\n          ...state.settings,\n          [action.view]: action.settings,\n        },\n      };\n\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "packages/tinymce-button/src/store/selectors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Retrieve settings.\n *\n * @param {Object} state State of store.\n * @return {Object} Settings object.\n */\nexport function getSettings(state) {\n  return state.settings;\n}\n\n/**\n * Get Modal state.\n *\n * @param  {Object} state State of the store.\n * @return {boolean} Flag for open state of modal.\n */\nexport function getModal(state) {\n  return state.modalOpen;\n}\n\n/**\n * Get editor instance.\n *\n * @param {Object} state State for the store.\n * @return {string} Editor ID.\n */\nexport function getEditor(state) {\n  return state.editor;\n}\n\n/**\n * Get current view for the store.\n *\n * @param {Object} state State object.\n * @return {string} Current view name.\n */\nexport function getCurrentView(state) {\n  return state.currentView;\n}\n\n/**\n *Get settings for current view.\n *\n * @param {Object} state State object.\n * @return {Object} Settings object for current view.\n */\nexport function getCurrentViewSettings(state) {\n  const currentView = getCurrentView(state);\n\n  return state.settings[currentView];\n}\n\nexport function getState(state) {\n  return state;\n}\n"
  },
  {
    "path": "packages/tinymce-button/src/store/test/actions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport * as actions from '../actions';\n\ndescribe(\"Test actions' returned object\", () => {\n  describe('Test set settings actions', () => {\n    it('pass empty setting', () => {\n      const expected = {\n        type: 'SET_SETTINGS',\n        settings: {},\n      };\n\n      const settingsActionObject = actions.setSettings({});\n      expect(settingsActionObject).toStrictEqual(expected);\n    });\n  });\n\n  describe('Test toggle Modal action', () => {\n    it('pass true', () => {\n      const expected = {\n        type: 'TOGGLE_MODAL',\n        modalOpen: true,\n      };\n\n      const toggleModal = actions.toggleModal(true);\n      expect(toggleModal).toStrictEqual(expected);\n    });\n\n    it('pass false', () => {\n      const expected = {\n        type: 'TOGGLE_MODAL',\n        modalOpen: false,\n      };\n\n      const toggleModal = actions.toggleModal(false);\n      expect(toggleModal).toStrictEqual(expected);\n    });\n  });\n\n  describe('Test setting editor via action object', () => {\n    it('set editor instance', () => {\n      const expected = {\n        type: 'SET_EDITOR',\n        editor: 'test_editor',\n      };\n\n      const Editor = actions.setEditor('test_editor');\n      expect(Editor).toStrictEqual(expected);\n    });\n  });\n\n  describe('Set current view', () => {\n    it('set current view to list', () => {\n      const expected = {\n        type: 'SET_CURRENT_VIEW',\n        currentView: 'list',\n      };\n\n      const View = actions.setCurrentView('list');\n      expect(View).toStrictEqual(expected);\n    });\n  });\n\n  describe('Set view settings', () => {\n    it('set view related settings', () => {\n      const expected = {\n        type: 'SET_VIEW_SETTINGS',\n        view: 'list',\n        settings: {\n          test: 'test',\n        },\n      };\n\n      const ViewSettings = actions.setViewSettings('list', { test: 'test' });\n      expect(ViewSettings).toStrictEqual(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/tinymce-button/src/store/test/selectors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport * as selector from '../selectors';\n\njest.mock('@wordpress/data', () => ({\n  select: jest.fn(() => ({\n    getCurrentView: () => 'round',\n  })),\n}));\n\ndescribe('Test Store Selectors', () => {\n  it('get settings', () => {\n    const expected = {\n      test: 'dummy',\n    };\n\n    const state = {\n      settings: expected,\n    };\n\n    const Settings = selector.getSettings(state);\n    expect(Settings).toStrictEqual(expected);\n  });\n\n  it('get modal open state', () => {\n    const state = {\n      modalOpen: true,\n    };\n\n    const ModalOpen = selector.getModal(state);\n    expect(ModalOpen).toBeTrue();\n  });\n\n  it('get editor', () => {\n    const state = {\n      editor: 'test',\n    };\n\n    const Editor = selector.getEditor(state);\n    expect(Editor).toBe('test');\n  });\n\n  it('get current view as `round`', () => {\n    const state = {\n      currentView: 'round',\n    };\n\n    const CurrentView = selector.getCurrentView(state);\n    expect(CurrentView).toBe('round');\n  });\n\n  it('get current view settings for round', () => {\n    const state = {\n      currentView: 'round',\n      settings: {\n        round: {\n          test: 'dummy',\n        },\n      },\n    };\n\n    const CurrentView = selector.getCurrentViewSettings(state);\n    expect(CurrentView).toStrictEqual({ test: 'dummy' });\n  });\n});\n"
  },
  {
    "path": "packages/tinymce-button/src/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { dispatch, select } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport store from '../store';\n\n/**\n * Update the view wide settings.\n *\n * @param {Object} args Arguments.\n * @param {Object} args.fieldObj Field object.\n * @param {Object} args.field Field.\n * @param {boolean} [args.hidden] Whether the field is hidden.\n * @return {void}\n */\nexport const updateViewSettings = ({ fieldObj, field, hidden = false }) => {\n  const currentViewSettings = select(store).getCurrentViewSettings();\n  let updatedSettings = currentViewSettings;\n\n  switch (typeof fieldObj) {\n    case 'object':\n      if (!hidden) {\n        const { show } = fieldObj;\n        updatedSettings = {\n          ...currentViewSettings,\n          [field]: { ...fieldObj, show: !show },\n        };\n      }\n      break;\n\n    default:\n      updatedSettings = {\n        ...currentViewSettings,\n        [field]: fieldObj,\n      };\n      break;\n  }\n\n  dispatch(store).setViewSettings(\n    select(store).getCurrentView(),\n    updatedSettings\n  );\n};\n\n/**\n * Build the shortcode tag based on the selected attributes.\n *\n * @return {string} Shortcode.\n */\nexport const prepareShortCode = () => {\n  let shortCode = `[web_stories`;\n  const editorInstance = select(store).getEditor();\n  const settings = select(store).getCurrentViewSettings();\n\n  if (editorInstance) {\n    Object.keys(settings).forEach((value) => {\n      const ValueObject = settings[value];\n      const Value =\n        'object' === typeof ValueObject\n          ? ValueObject.show.toString()\n          : ValueObject.toString();\n      shortCode += ` ${value.toString()}=\"${Value}\"`;\n    });\n  }\n\n  shortCode += ' /]';\n\n  return shortCode;\n};\n"
  },
  {
    "path": "packages/tinymce-button/src/utils/test/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport { dispatch } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as Utils from '..';\nimport store from '../../store';\n\n/**\n * Test shortcode build function.\n */\ndescribe('Test shortcode is preparation', () => {\n  beforeAll(() => {\n    dispatch(store).setViewSettings('circles', {\n      order: 'latest',\n      dummy: {\n        show: true,\n        label: 'Dummy Text',\n        hidden: true,\n      },\n    });\n  });\n\n  it('editor instance not set', () => {\n    const shortCode = Utils.prepareShortCode();\n    expect(shortCode).toBe('[web_stories /]');\n  });\n\n  it('editor instance set', () => {\n    dispatch(store).setEditor('test_editor');\n    const shortCode = Utils.prepareShortCode();\n    expect(shortCode).toBe('[web_stories order=\"latest\" dummy=\"true\" /]');\n  });\n});\n"
  },
  {
    "path": "packages/tracking/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/tracking/README.md",
    "content": "# Tracking\n\nHelper library for interacting with Google Events to track page/screen views and events.\n\nSupports only Google Analytics 4\n\n## Usage\n\n### Initialize Tracking\n\nInitialize tracking in the module's entry point.\n\nIf the user has opted in to telemetry, this will enable tracking by loading the Google Analytics `gtag.js` script.\n\nBy default this will result in a page view being tracked, unless turned off using the second boolean argument.\n\n```js\ninitializeTracking('Awesome App', false);\n```\n\n### Enable/Disable Tracking\n\nUse the `disableTracking` and `enableTracking` functions to initialize tracking after the initial page view.\n\nUseful when the user changes his telemetry preferences at a later point.\n\nThe `isTrackingEnabled()` function provides the current opt-in/out status.\n\n### Tracking Screen Views\n\n[Screen views](https://developers.google.com/analytics/devguides/collection/ga4/screen-view) are like page views, but for web apps. To send `screen_view` events when users navigate to different screens within an app,\nuse the `trackScreenView()` function.\n\n```js\ntrackScreenView('Settings');\n```\n\n### Tracking Clicks\n\nUse the `trackClick` function in your `onClick` handler.\n\nIf links are to open in the same tab, they will only do so after the tracking event has already been sent.\nThis ensures no tracking calls are missed.\n\n```js\ntrackClick(event, 'contact_support');\n```\n\n### Tracking Errors (Exceptions)\n\nYou can use `trackError` to send [exception events](https://developers.google.com/analytics/devguides/collection/ga4/exceptions) to measure the number and type of crashes or errors that occur on a web page.\n\nThe first parameter is the prefix, the second one the error description, and the third one indicates whether the error was fatal or not.\n\n```js\ntrackError('demo', 'Division by zero', false);\n```\n\n### Tracking Events\n\nAt the core of this package is the `trackEvent` function.\n\nAll you need to provide is the event name and as many optional event parameters as you want:\n\n```js\ntrackEvent('insert_template', {\n  template_name: 'Awesome Template',\n});\n```\n\n### User Timings\n\nUse the following helper function to start a timer and return a callback to stop it:\n\n```js\nconst trackTiming = getTimeTracker('video_transcoding'); // Start timer.\n// Perform some long task...\ntrackTiming(); // Stop timer and send event.\n```\n"
  },
  {
    "path": "packages/tracking/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/tracking\",\n  \"description\": \"Utility package for telemetry in the Web Stories editor, powered by Google Analytics.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"analytics\",\n    \"google analytics\",\n    \"telemetry\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/tracking/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/tracking\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/tracking/src/constants.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const DATA_LAYER = 'webStoriesTrackingDataLayer';\n"
  },
  {
    "path": "packages/tracking/src/disableTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { config } from './shared';\n\nfunction disableTracking(): void {\n  config.trackingEnabled = false;\n}\n\nexport default disableTracking;\n"
  },
  {
    "path": "packages/tracking/src/enableTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { DATA_LAYER } from './constants';\nimport { config, gtag } from './shared';\n\nconst SCRIPT_IDENTIFIER = 'data-web-stories-tracking';\n\nfunction loadScriptTag(url: string): Promise<Event> {\n  return new Promise((resolve, reject) => {\n    const script = document.createElement('script');\n    script.setAttribute(SCRIPT_IDENTIFIER, '');\n    script.async = true;\n    script.src = url;\n    script.addEventListener('load', resolve);\n    script.addEventListener('error', reject);\n    document.head.appendChild(script);\n  });\n}\n\n/**\n * Loads the Analytics tracking script.\n *\n * @param [sendPageView] Whether to send a page view event or not upon loading.\n * @return Promise.\n */\nasync function loadTrackingScript(sendPageView = true): Promise<void> {\n  if (document.querySelector(`script[${SCRIPT_IDENTIFIER}]`)) {\n    return;\n  }\n\n  try {\n    await loadScriptTag(\n      `https://www.googletagmanager.com/gtag/js?id=${config.trackingIdGA4}&l=${DATA_LAYER}`\n    );\n  } catch {\n    // Loading was not possible, probably because of an ad blocker.\n    return;\n  }\n\n  // This way we'll get \"Editor\" and \"Dashboard\" instead of \"Edit Story ‹ Web Stories Dev — WordPress\".\n  const pageTitle = config.appName;\n\n  // 'Plugin Activation' -> '/plugin-activation'\n  // This way we get nicer looking paths like '/editor' instead of 'wp-admin/post-new.php?post_type=web-story'.\n  const pagePath = '/' + config.appName.replace(/ /g, '-').toLowerCase();\n\n  gtag('js', new Date());\n\n  // Note: `set` commands need to be placed before `config` commands to ensure\n  // those values are passed along with the initial config.\n\n  // Google Analytics 4 user properties.\n  // See https://developers.google.com/analytics/devguides/collection/ga4/persistent-values\n  // See https://developers.google.com/analytics/devguides/collection/ga4/user-properties\n  gtag('set', 'user_properties', {\n    ...config.userProperties,\n    app_version: config.appVersion,\n    page_title: pageTitle,\n    page_path: pagePath,\n  });\n\n  gtag('config', config.trackingIdGA4, {\n    app_name: config.appName,\n    // Not really supported for web properties, but passed for completeness.\n    // See https://support.google.com/analytics/answer/9268042\n    app_version: config.appVersion,\n    send_page_view: sendPageView,\n    // Setting the transport method to 'beacon' lets the hit be sent\n    // using 'navigator.sendBeacon' in browsers that support it.\n    transport_type: 'beacon',\n  });\n}\n\nasync function enableTracking(sendPageView = true): Promise<void> {\n  if (!config.trackingAllowed || config.trackingEnabled) {\n    return;\n  }\n\n  await loadTrackingScript(sendPageView);\n  config.trackingEnabled = true;\n}\n\nexport default enableTracking;\n"
  },
  {
    "path": "packages/tracking/src/getTimeTracker.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport trackEvent from './trackEvent';\n\n/**\n * Starts a timer and returns a callback to stop it and send an analytics timing_complete event.\n *\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/user-timings\n * @param eventName The event nae (e.g. 'load_items').\n * @return Callback to stop timer and send tracking event.\n */\nfunction getTimeTracker(eventName: string): () => void {\n  const before = window.performance.now();\n  return () => {\n    const after = window.performance.now();\n    const value = after - before;\n\n    void trackEvent(eventName, {\n      value,\n    });\n  };\n}\n\nexport default getTimeTracker;\n"
  },
  {
    "path": "packages/tracking/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport initializeTracking from './initializeTracking';\nimport enableTracking from './enableTracking';\nimport disableTracking from './disableTracking';\nimport isTrackingEnabled from './isTrackingEnabled';\nimport trackClick from './trackClick';\nimport trackError from './trackError';\nimport trackEvent from './trackEvent';\nimport trackTiming from './trackTiming';\nimport trackScreenView from './trackScreenView';\nimport getTimeTracker from './getTimeTracker';\n\nexport {\n  initializeTracking,\n  enableTracking,\n  disableTracking,\n  isTrackingEnabled,\n  trackScreenView,\n  trackClick,\n  trackError,\n  trackEvent,\n  trackTiming,\n  getTimeTracker,\n};\n"
  },
  {
    "path": "packages/tracking/src/initializeErrorReporting.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport trackError from './trackError';\n\nconst IGNORED_ERROR_MESSAGES = ['ResizeObserver loop limit exceeded'];\n\n/**\n *\n * @param event Error event.\n */\nfunction handleErrors(event: ErrorEvent): void {\n  if (event.filename && !event.filename.includes('web-stories')) {\n    return;\n  }\n\n  if (IGNORED_ERROR_MESSAGES.includes(event.message)) {\n    return;\n  }\n\n  const errorMessage = `${event.message} (${event.lineno}:${event.colno})`;\n  void trackError('uncaught_error', errorMessage, true);\n}\n\n/**\n *\n * @param event Promise rejection event.\n */\nfunction handleUncaughtPromises(event: PromiseRejectionEvent): void {\n  const errorMessage = (event.reason as string) || 'Promise rejection';\n  void trackError('uncaught_promise', errorMessage);\n}\n\nfunction initializeErrorReporting(): void {\n  window.addEventListener('error', handleErrors);\n  window.addEventListener('unhandledrejection', handleUncaughtPromises);\n}\n\nexport default initializeErrorReporting;\n"
  },
  {
    "path": "packages/tracking/src/initializeTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { config } from './shared';\nimport enableTracking from './enableTracking';\nimport initializeErrorReporting from './initializeErrorReporting';\n\n/**\n * Initializes tracking.\n *\n * @param appName Name of the application, e.g. 'Dashboard' or 'Editor'.\n * @param [sendPageView] Whether to send an initial page view event upon loading.\n * @return Promise.\n */\nasync function initializeTracking(appName: string, sendPageView = true) {\n  config.appName = appName;\n  await enableTracking(sendPageView);\n  initializeErrorReporting();\n}\n\nexport default initializeTracking;\n"
  },
  {
    "path": "packages/tracking/src/isTrackingEnabled.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { config } from './shared';\nimport enableTracking from './enableTracking';\n\n/**\n * Determines whether tracking is enabled or not.\n *\n * @return Whether tracking is enabled\n */\nasync function isTrackingEnabled() {\n  await enableTracking();\n  return Boolean(config.trackingEnabled);\n}\n\nexport default isTrackingEnabled;\n"
  },
  {
    "path": "packages/tracking/src/shared.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { DATA_LAYER } from './constants';\n\ninterface ConfigParams {\n  anonymize_ip?: boolean;\n  app_name?: string;\n  app_version?: string;\n  send_page_view?: boolean;\n  transport_type?: 'beacon' | 'image' | 'xhr';\n  page_title?: string;\n  page_path?: string;\n  custom_map?: Record<string, string | number>;\n}\n\nexport interface ControlParams {\n  groups?: string | string[] | undefined;\n  event_callback?: (() => void) | undefined;\n  event_timeout?: number | undefined;\n}\n\nexport interface EventParameters {\n  name?: string;\n  value?: string | number;\n  search_type?: string;\n  duration?: number;\n  title_length?: number;\n  unread_count?: number;\n  event_label?: string;\n  event_category?: string;\n  status?: string;\n  original_length?: number;\n  new_length?: number;\n  start_offset?: number | null;\n  end_offset?: number | null;\n  result?: boolean;\n  file_size?: number;\n  file_type?: string;\n  width?: number;\n  height?: number;\n  element?: string;\n}\n\ninterface Gtag {\n  (command: 'config', targetId: string, config?: ConfigParams): void;\n  (command: 'set', targetId: string, config: ConfigParams): void;\n  (command: 'set', config: ConfigParams): void;\n  (command: 'js', config: Date): void;\n  (\n    command: 'event',\n    eventName: string,\n    eventParams?: ControlParams | EventParameters\n  ): void;\n}\n\ninterface TrackingConfig {\n  /**\n   * Whether tracking is allowed in the current context.\n   *\n   * @default false\n   */\n  trackingAllowed?: boolean;\n  /**\n   * Whether tracking is currently enabled.\n   *\n   * @default false\n   */\n  trackingEnabled?: boolean;\n  /**\n   * GA4 measurement ID.\n   */\n  trackingIdGA4: string;\n  /**\n   * Application name.\n   */\n  appName: string;\n  /**\n   * Application version.\n   */\n  appVersion: string;\n  /**\n   * User properties.\n   */\n  userProperties: Record<string, string | number>;\n}\n\ndeclare global {\n  interface Window {\n    [DATA_LAYER]: object[];\n    webStoriesTrackingSettings: TrackingConfig;\n  }\n}\n\n/**\n * Pushes data onto the data layer.\n *\n * MUST push an instance of Arguments to the target.\n * Using an ES6 spread operator (i.e. `...args`) will cause tracking events to _silently_ fail.\n *\n * @see https://developers.google.com/tag-platform/devguides/datalayer#rename_the_data_layer\n */\nexport const gtag: Gtag = function (): void {\n  window[DATA_LAYER] = window[DATA_LAYER] || [];\n  //eslint-disable-next-line prefer-rest-params -- Must push instead of using spread to prevent tracking failures.\n  window[DATA_LAYER].push(arguments);\n};\n\nconst DEFAULT_CONFIG = {\n  trackingAllowed: false,\n  trackingEnabled: false,\n  trackingIdGA4: '',\n  userProperties: {},\n  appName: '',\n};\n\nconst { trackingAllowed, trackingIdGA4, appVersion, userProperties } =\n  window.webStoriesTrackingSettings || {};\n\nexport const config: TrackingConfig = {\n  ...DEFAULT_CONFIG,\n  trackingAllowed,\n  trackingIdGA4,\n  appVersion,\n  userProperties,\n};\n"
  },
  {
    "path": "packages/tracking/src/test/disableTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { config } from '../shared';\nimport disableTracking from '../disableTracking';\n\ndescribe('disableTracking', () => {\n  afterEach(() => {\n    config.trackingEnabled = undefined;\n  });\n\n  it('should return a boolean', () => {\n    config.trackingEnabled = true;\n    disableTracking();\n    expect(config.trackingEnabled).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/enableTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\njest.mock('../shared');\n\n/**\n * Internal dependencies\n */\nimport { config } from '../shared';\nimport enableTracking from '../enableTracking';\n\n//eslint-disable-next-line jest/no-disabled-tests -- Not yet testable due to the Promise in loadTrackingScript().\ndescribe.skip('enableTracking', () => {\n  afterEach(() => {\n    config.trackingAllowed = undefined;\n    config.trackingEnabled = undefined;\n  });\n\n  it('does nothing if tracking is not allowed', async () => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n\n    await enableTracking();\n    expect(config.trackingEnabled).toBeFalse();\n  });\n\n  it('enqueues tracking script if tracking is allowed', async () => {\n    config.trackingAllowed = true;\n    config.trackingEnabled = false;\n\n    await enableTracking();\n\n    expect(config.trackingEnabled).toBeTrue();\n    const result = document.querySelector(`script[data-web-stories-tracking]`);\n    expect(result).not.toBeNull();\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/getTimeTracker.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getTimeTracker from '../getTimeTracker';\nimport { config } from '../shared';\nimport trackEvent from '../trackEvent';\n\njest.mock('../trackEvent');\n\njest\n  .spyOn(performance, 'now')\n  .mockImplementationOnce(() => 150)\n  .mockImplementationOnce(() => 200);\n\ndescribe('getTimeTracker', () => {\n  afterEach(() => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n    config.appName = '';\n\n    jest.clearAllMocks();\n  });\n\n  it('sends two separate tracking events', () => {\n    config.appName = 'Foo App';\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n    config.trackingIdGA4 = 'G-ABC1234567';\n\n    const trackTime = getTimeTracker('load_dependencies');\n    trackTime();\n\n    expect(trackEvent).toHaveBeenCalledOnce();\n    expect(trackEvent).toHaveBeenNthCalledWith(1, 'load_dependencies', {\n      value: 50,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/gtag.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { gtag } from '../shared';\nimport { DATA_LAYER } from '../constants';\n\ndescribe('gtag', () => {\n  it('should push data to the data layer', () => {\n    gtag('event', 'Bar');\n    gtag('event', 'Baz');\n    expect(window[DATA_LAYER]).toHaveLength(2);\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/initializeTracking.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\njest.mock('../shared');\n\n/**\n * Internal dependencies\n */\nimport { config } from '../shared';\nimport initializeTracking from '../initializeTracking';\n\ndescribe('initializeTracking', () => {\n  afterEach(() => {\n    config.trackingIdGA4 = '';\n  });\n\n  it('sets app name in config', async () => {\n    config.trackingIdGA4 = '1234567';\n    await initializeTracking('Foo App');\n\n    expect(config.appName).toBe('Foo App');\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/isTrackingEnabled.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { config } from '../shared';\nimport isTrackingEnabled from '../isTrackingEnabled';\n\ndescribe('isTrackingEnabled', () => {\n  afterEach(() => {\n    config.trackingEnabled = undefined;\n  });\n\n  it('should return a boolean', async () => {\n    await expect(isTrackingEnabled()).resolves.toBeFalse();\n    config.trackingEnabled = true;\n    await expect(isTrackingEnabled()).resolves.toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/trackError.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\njest.mock('../shared');\n\n/**\n * Internal dependencies\n */\nimport trackError from '../trackError';\nimport { config, gtag } from '../shared';\nimport type { ControlParams } from '../shared';\n\ndescribe('trackError', () => {\n  afterEach(() => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n\n    jest.clearAllMocks();\n  });\n\n  it('adds a tracking event to the dataLayer', async () => {\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n    const error = new Error('mock error');\n\n    jest.mocked(gtag).mockImplementation((_type, _eventName, eventData) => {\n      (eventData as ControlParams).event_callback?.();\n    });\n    await trackError('test_error', error.message, true);\n    expect(gtag).toHaveBeenCalledWith('event', 'exception', {\n      description: 'test_error: mock error',\n      fatal: true,\n      event_callback: expect.any(Function) as () => void,\n    });\n  });\n\n  it('does not push to dataLayer when tracking is disabled', async () => {\n    config.trackingEnabled = false;\n    const error = new Error('mock error');\n    await trackError('test_error', error.message);\n    expect(gtag).not.toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/trackEvent.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\njest.mock('../shared');\n\n/**\n * Internal dependencies\n */\nimport trackEvent from '../trackEvent';\nimport { config, gtag } from '../shared';\nimport type { ControlParams } from '../shared';\n\ndescribe('trackEvent', () => {\n  afterEach(() => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n\n    jest.clearAllMocks();\n  });\n\n  it('adds a tracking event to the dataLayer', async () => {\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n\n    jest.mocked(gtag).mockImplementation((_type, _eventName, eventData) => {\n      (eventData as ControlParams).event_callback?.();\n    });\n\n    await trackEvent('name', { name: 'abc', value: 'def', event_label: 'ghi' });\n    expect(gtag).toHaveBeenCalledWith('event', 'name', {\n      event_callback: expect.any(Function) as () => void,\n      name: 'abc',\n      value: 'def',\n      event_label: 'ghi',\n    });\n  });\n\n  it('does not push to dataLayer when tracking is disabled', async () => {\n    config.trackingEnabled = false;\n\n    await trackEvent('name', { name: 'abc', value: 'def', event_label: 'ghi' });\n    expect(gtag).not.toHaveBeenCalled();\n  });\n\n  it('sends two different tracking events for backwards compatibility', async () => {\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n    config.trackingIdGA4 = 'G-ABC1234567';\n\n    jest.mocked(gtag).mockImplementation((_type, _eventName, eventData) => {\n      (eventData as ControlParams).event_callback?.();\n    });\n\n    await trackEvent('name', {\n      search_type: 'abc',\n    });\n    await trackEvent('name', {\n      duration: 123,\n    });\n    await trackEvent('name', {\n      title_length: 123,\n    });\n    await trackEvent('name', {\n      unread_count: 123,\n    });\n    expect(gtag).toHaveBeenNthCalledWith(1, 'event', 'name', {\n      event_callback: expect.any(Function) as () => void,\n      search_type: 'abc',\n    });\n    expect(gtag).toHaveBeenNthCalledWith(2, 'event', 'name', {\n      event_callback: expect.any(Function) as () => void,\n      duration: 123,\n    });\n    expect(gtag).toHaveBeenNthCalledWith(3, 'event', 'name', {\n      event_callback: expect.any(Function) as () => void,\n      title_length: 123,\n    });\n    expect(gtag).toHaveBeenNthCalledWith(4, 'event', 'name', {\n      event_callback: expect.any(Function) as () => void,\n      unread_count: 123,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/trackScreenView.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\njest.mock('../shared');\n\n/**\n * Internal dependencies\n */\nimport trackScreenView from '../trackScreenView';\nimport { config, gtag } from '../shared';\nimport type { ControlParams } from '../shared';\n\ndescribe('trackScreenView', () => {\n  afterEach(() => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n\n    jest.clearAllMocks();\n  });\n\n  it('adds a tracking event to the dataLayer', async () => {\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n\n    jest.mocked(gtag).mockImplementation((_type, _eventName, eventData) => {\n      (eventData as ControlParams).event_callback?.();\n    });\n\n    await trackScreenView('Explore Templates');\n    expect(gtag).toHaveBeenCalledWith('event', 'screen_view', {\n      event_callback: expect.any(Function) as () => void,\n      screen_name: 'Explore Templates',\n    });\n  });\n\n  it('does not push to dataLayer when tracking is disabled', async () => {\n    config.trackingEnabled = false;\n\n    await trackScreenView('Explore Templates');\n    expect(gtag).not.toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/test/trackTiming.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport trackTiming from '../trackTiming';\nimport { config } from '../shared';\nimport trackEvent from '../trackEvent';\n\njest.mock('../trackEvent');\n\njest\n  .spyOn(performance, 'now')\n  .mockImplementationOnce(() => 150)\n  .mockImplementationOnce(() => 200);\n\ndescribe('trackTiming', () => {\n  afterEach(() => {\n    config.trackingAllowed = false;\n    config.trackingEnabled = false;\n    config.appName = '';\n\n    jest.clearAllMocks();\n  });\n\n  it('sends two separate tracking events', () => {\n    config.appName = 'Foo App';\n    config.trackingAllowed = true;\n    config.trackingEnabled = true;\n    config.trackingIdGA4 = 'G-ABC1234567';\n\n    trackTiming('page', 50, 'carousel_navigate', 'click');\n\n    expect(trackEvent).toHaveBeenCalledOnce();\n    expect(trackEvent).toHaveBeenNthCalledWith(1, 'click', {\n      event_category: 'page',\n      event_label: 'carousel_navigate',\n      value: 50,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/tracking/src/track.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { gtag } from './shared';\n\n/**\n * Send an Analytics tracking event.\n *\n * @param eventName Event name, either 'screen_view', 'timing_complete', or something custom.\n * @param [eventData] The event data to send.\n * @return Promise that always resolves.\n */\nfunction track(eventName: string, eventData = {}): Promise<void> {\n  return new Promise<void>((resolve) => {\n    // This timeout ensures a tracking event does not block the user\n    // event if it is not sent (in time).\n    // If this fails, it shouldn't reject the promise since event\n    // tracking should not result in user-facing errors. It will just\n    // trigger a console warning.\n    // See https://developers.google.com/analytics/devguides/collection/gtagjs/sending-data\n    const failTimeout = setTimeout(() => {\n      window.console.warn(\n        `[Web Stories] Tracking event \"${eventName}\" took too long to fire.`\n      );\n      resolve();\n    }, 1000);\n\n    gtag('event', eventName, {\n      ...eventData,\n      event_callback: () => {\n        clearTimeout(failTimeout);\n        resolve();\n      },\n    });\n  });\n}\n\nexport default track;\n"
  },
  {
    "path": "packages/tracking/src/trackClick.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { MouseEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport isTrackingEnabled from './isTrackingEnabled';\nimport track from './track';\n\n/**\n * Send an Analytics tracking event for clicks.\n *\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/events\n * @param event The actual click event.\n * @param eventName The event name (e.g. 'search').\n * @return Promise that always resolves.\n */\nasync function trackClick(event: MouseEvent, eventName: string): Promise<void> {\n  // currentTarget becomes null after event bubbles up, so we\n  // grab it for reference before any async operations occur.\n  // https://github.com/facebook/react/issues/2857#issuecomment-70006324\n  const { currentTarget } = event || {};\n\n  // Handle cases where trackClick is used in places where the event is not passed and thus undefined.\n  if (!currentTarget) {\n    return Promise.resolve();\n  }\n\n  if (!(await isTrackingEnabled())) {\n    return Promise.resolve();\n  }\n\n  const openLinkInNewTab =\n    (currentTarget as HTMLAnchorElement)?.target === '_blank' ||\n    event.ctrlKey ||\n    event.shiftKey ||\n    event.metaKey ||\n    event.button === 1;\n\n  if (openLinkInNewTab) {\n    return track(eventName);\n  }\n\n  event.preventDefault();\n\n  return track(eventName).finally(() => {\n    document.location = (currentTarget as HTMLAnchorElement).href;\n  });\n}\n\nexport default trackClick;\n"
  },
  {
    "path": "packages/tracking/src/trackError.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport isTrackingEnabled from './isTrackingEnabled';\nimport track from './track';\n\n/**\n * Send an Analytics tracking event for exceptions.\n *\n * @see https://developers.google.com/analytics/devguides/collection/ga4/exceptions\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/exceptions\n * @param prefix Error prefixed. Concatenated with description.\n * @param description The error description.\n * @param [fatal] Report whether there is a fatal error.\n * @return Promise that always resolves.\n */\nasync function trackError(\n  prefix: string,\n  description: string,\n  fatal = false\n): Promise<void> {\n  if (!(await isTrackingEnabled())) {\n    return Promise.resolve();\n  }\n\n  const eventData = {\n    description: `${prefix}: ${description}`,\n    fatal,\n  };\n\n  return track('exception', eventData);\n}\n\nexport default trackError;\n"
  },
  {
    "path": "packages/tracking/src/trackEvent.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { EventParameters } from './shared';\nimport isTrackingEnabled from './isTrackingEnabled';\nimport track from './track';\n\n/**\n * Send an Analytics tracking event.\n *\n * Note: Only use custom events if the existing events don't handle your use case.\n *\n * @see https://developers.google.com/analytics/devguides/collection/ga4/events\n * @see https://support.google.com/analytics/answer/9267735\n * @see https://support.google.com/analytics/answer/9310895?hl=en\n * @param eventName The event name (e.g. 'search'). The value that will appear as the event action in Google Analytics Event reports.\n * @param [eventParameters] Event parameters.\n * @return Promise that always resolves.\n */\nasync function trackEvent(\n  eventName: string,\n  eventParameters: EventParameters = {}\n): Promise<void> {\n  if (!(await isTrackingEnabled())) {\n    return Promise.resolve();\n  }\n\n  return track(eventName, eventParameters);\n}\n\nexport default trackEvent;\n"
  },
  {
    "path": "packages/tracking/src/trackScreenView.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport track from './track';\nimport isTrackingEnabled from './isTrackingEnabled';\n\n/**\n * Send an Analytics screen_view event.\n *\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/screens\n * @see https://developers.google.com/analytics/devguides/collection/ga4/screen-view\n * @param screenName Screen name. Example: 'Explore Templates'.\n * @return Promise that always resolves.\n */\nasync function trackScreenView(screenName: string): Promise<void> {\n  if (!(await isTrackingEnabled())) {\n    return Promise.resolve();\n  }\n\n  const eventData = {\n    screen_name: screenName,\n  };\n\n  return track('screen_view', eventData);\n}\n\nexport default trackScreenView;\n"
  },
  {
    "path": "packages/tracking/src/trackTiming.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport trackEvent from './trackEvent';\n\n/**\n * Track event timing for performance measuring.\n *\n * @param category Category for categorizing the user timing variables into groups.\n * @param time Duration in milliseconds.\n * @param label Label that allows extra flexibility in reports.\n * @param eventName Event name, e.g. click or mousedown.\n */\nfunction trackTiming(\n  category: string,\n  time: number,\n  label = '',\n  eventName = 'click'\n): void {\n  void trackEvent(eventName, {\n    value: time,\n    event_category: category,\n    event_label: label,\n  });\n}\n\nexport default trackTiming;\n"
  },
  {
    "path": "packages/tracking/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/transform/README.md",
    "content": "# Transform\n\nUtility package for element transformations.\n"
  },
  {
    "path": "packages/transform/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/transform\",\n  \"description\": \"Utility package for element transformations.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/transform/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/transform\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {\n    \"@googleforcreators/react\": \"*\"\n  }\n}\n"
  },
  {
    "path": "packages/transform/src/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { State } from './types';\nexport default createContext<State>({ actions: {}, state: {} });\n"
  },
  {
    "path": "packages/transform/src/index.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as TransformProvider } from './transformProvider';\nexport { default as useTransform } from './useTransform';\nexport { default as useTransformHandler } from './useTransformHandler';\nexport { default as TransformContext } from './context';\n"
  },
  {
    "path": "packages/transform/src/transformProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type {\n  HandlersList,\n  TransformsList,\n  Transform,\n  TransformHandler,\n} from './types';\n\nfunction TransformProvider({ children }: { children: ReactNode }) {\n  const transformHandlersRef = useRef<HandlersList>({});\n  const lastTransformsRef = useRef<TransformsList>({});\n  const [isAnythingTransforming, setIsAnythingTransforming] = useState(false);\n\n  const registerTransformHandler = useCallback(\n    (id: string, handler: TransformHandler) => {\n      const handlerListMap = transformHandlersRef.current;\n      const handlerList = handlerListMap[id] || (handlerListMap[id] = []);\n      handlerList.push(handler);\n      return () => {\n        handlerList.splice(handlerList.indexOf(handler), 1);\n      };\n    },\n    []\n  );\n\n  const pushTransform = useCallback(\n    (id: string, transform: Transform | null) => {\n      const handlerListMap = transformHandlersRef.current;\n      const lastTransforms = lastTransformsRef.current;\n      const handlerList = handlerListMap[id];\n\n      if (handlerList) {\n        handlerList.forEach((handler) => handler(transform));\n      }\n\n      if (transform === null) {\n        lastTransforms[id] = null;\n      } else {\n        lastTransforms[id] = { ...lastTransforms[id], ...transform };\n      }\n\n      if (isDoneTransform(lastTransforms[id])) {\n        const allTransformsDone =\n          Object.values(lastTransforms).every(isDoneTransform);\n        if (allTransformsDone) {\n          lastTransformsRef.current = {};\n          setIsAnythingTransforming(false);\n        }\n        // isAnythingTransforming is relevant for transformations relevant to Moveable.\n        // Suppress communicating static transformations to the world.\n      } else if (transform && !transform.staticTransformation) {\n        setIsAnythingTransforming(true);\n      }\n    },\n    []\n  );\n\n  const clearTransforms = useCallback(() => {\n    lastTransformsRef.current = {};\n    setIsAnythingTransforming(false);\n  }, [setIsAnythingTransforming]);\n\n  const state = {\n    state: {\n      isAnythingTransforming,\n    },\n    actions: {\n      registerTransformHandler,\n      pushTransform,\n      clearTransforms,\n    },\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nconst isDoneTransform = (transform: null | object) => {\n  if (transform === null) {\n    return true;\n  }\n  const transformKeys = Object.keys(transform);\n  return transformKeys.length === 1 && 'dropTargets' in transform;\n};\n\nexport default TransformProvider;\n"
  },
  {
    "path": "packages/transform/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport type TransformHandler = (frame: Transform | null) => void;\nexport type HandlerRegister = (\n  id: string,\n  handler: TransformHandler\n) => () => void;\n\nexport type HandlersList = Record<string, TransformHandler[]>;\n\nexport type TransformsList = Record<string, Record<string, unknown> | null>;\n\nexport interface Transform {\n  staticTransformation: boolean;\n  color?: unknown;\n  style?: string;\n  resize?: [number, number];\n  dropTargets?: { hover: boolean; active: boolean };\n  updates?: Record<string, unknown>;\n}\n\nexport type PushTransform = (id: string, transform: Transform | null) => void;\nexport type ClearTransform = () => void;\n\nexport interface State {\n  actions: {\n    registerTransformHandler?: HandlerRegister;\n    pushTransform?: PushTransform;\n    clearTransforms?: ClearTransform;\n  };\n  state: {\n    isAnythingTransforming?: boolean;\n  };\n}\n"
  },
  {
    "path": "packages/transform/src/useTransform.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { State } from './types';\n\nfunction useTransform<T>(selector: (state: State) => T) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useTransform;\n"
  },
  {
    "path": "packages/transform/src/useTransformHandler.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect } from '@googleforcreators/react';\nimport type { DependencyList } from 'react';\n\n/**\n * Internal dependencies\n */\nimport useTransform from './useTransform';\nimport type { TransformHandler } from './types';\n\n/**\n * @param id Target element's id.\n * @param handler The transform handler. The argument is\n * the frame object. The `null` value resets the transform.\n * @param [deps] The effect's dependencies.\n */\nfunction useTransformHandler(\n  id: string,\n  handler: TransformHandler,\n  deps: DependencyList | undefined = undefined\n) {\n  const registerTransformHandler = useTransform(\n    ({ actions }) => actions.registerTransformHandler\n  );\n\n  useEffect(\n    () => registerTransformHandler?.(id, handler),\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- We want to pass through provided deps.\n    deps\n  );\n}\n\nexport default useTransformHandler;\n"
  },
  {
    "path": "packages/transform/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../react\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/units/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/units/README.md",
    "content": "# Units\n\nUtility package to deal with editor units.\n"
  },
  {
    "path": "packages/units/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/units\",\n  \"description\": \"A collection of utility functions as well as a React context provider for dealing with \\\"data\\\" and \\\"editor\\\" pixels in the Web Stories editor.\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/units/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/units\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@googleforcreators/react\": \"*\",\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/units/src/calcRotatedObjectPositionAndSize.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getCorners from './getCorners';\n\nexport default function calcRotatedObjectPositionAndSize(\n  angle = 0,\n  x: number,\n  y: number,\n  width: number,\n  height: number\n) {\n  if (!angle) {\n    return { x, y, width, height };\n  }\n\n  const { topLeftPoint, topRightPoint, bottomRightPoint, bottomLeftPoint } =\n    getCorners(angle, x, y, width, height);\n  /// get bounding box\n  const boundTopLeftX = Math.min(\n    topLeftPoint.x,\n    topRightPoint.x,\n    bottomRightPoint.x,\n    bottomLeftPoint.x\n  );\n  const boundTopLeftY = Math.min(\n    topLeftPoint.y,\n    topRightPoint.y,\n    bottomRightPoint.y,\n    bottomLeftPoint.y\n  );\n  const boundBottomRightX = Math.max(\n    topLeftPoint.x,\n    topRightPoint.x,\n    bottomRightPoint.x,\n    bottomLeftPoint.x\n  );\n  const boundBottomRightY = Math.max(\n    topLeftPoint.y,\n    topRightPoint.y,\n    bottomRightPoint.y,\n    bottomLeftPoint.y\n  );\n\n  return {\n    x: boundTopLeftX,\n    y: boundTopLeftY,\n    width: boundBottomRightX - boundTopLeftX,\n    height: boundBottomRightY - boundTopLeftY,\n  };\n}\n"
  },
  {
    "path": "packages/units/src/calcRotatedResizeOffset.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Calculates the position offset [dx, dy] for a resized rotated shape.\n * The resizing can be done on four sides: left, right, top, and bottom.\n *\n * @param degree The rotation angle in degrees.\n * @param left The resize delta on the left.\n * @param right The resize delta on the right.\n * @param top The resize delta on the top.\n * @param bottom The resize delta on the bottom.\n * @return The offsets in a [dx, dy] array.\n */\nfunction calcRotatedResizeOffset(\n  degree: number,\n  left: number,\n  right: number,\n  top: number,\n  bottom: number\n): [number, number] {\n  const rad = (degree * Math.PI) / 180.0;\n  const cos = Math.cos(rad);\n  const sin = Math.sin(rad);\n\n  const dcx = ((right - left) * cos + (top - bottom) * sin) / 2;\n  const dcy = ((bottom - top) * cos + (right - left) * sin) / 2;\n\n  const dx = dcx - (right + left) / 2;\n  const dy = dcy - (bottom + top) / 2;\n\n  return [dx, dy];\n}\n\nexport default calcRotatedResizeOffset;\n"
  },
  {
    "path": "packages/units/src/constants.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const PAGE_RATIO: number = 2 / 3;\nexport const PAGE_WIDTH = 412;\nexport const PAGE_HEIGHT = 618;\n\nexport const FULLBLEED_RATIO: number = 9 / 16;\n\nexport const FULLBLEED_HEIGHT: number = PAGE_WIDTH / FULLBLEED_RATIO;\nexport const DANGER_ZONE_HEIGHT: number = (FULLBLEED_HEIGHT - PAGE_HEIGHT) / 2;\n\n// Default 1em value for font size.\nexport const DEFAULT_EM: number = PAGE_HEIGHT * 0.02186;\n\n// Default device pixel ratio.\nexport const DEFAULT_DPR = 0.5;\n"
  },
  {
    "path": "packages/units/src/context.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport type { State } from './types';\n\nconst INITIAL_STATE = {\n  state: {},\n  actions: {},\n};\n\nexport default createContext<State>(INITIAL_STATE as State);\n"
  },
  {
    "path": "packages/units/src/dimensions.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport calcRotatedResizeOffset from './calcRotatedResizeOffset';\nimport {\n  DANGER_ZONE_HEIGHT,\n  DEFAULT_EM,\n  FULLBLEED_HEIGHT,\n  PAGE_HEIGHT,\n  PAGE_WIDTH,\n} from './constants';\nimport type { DimensionableElement, ElementBox } from './types';\n\n/**\n * Rounds the pixel value to the max allowed precision in the \"data\" space.\n *\n * @param v The value to be rounded.\n * @return The value rounded to the \"data\" space precision.\n */\nexport function dataPixels(v: number): number {\n  return Number(v.toFixed(0));\n}\n\n/**\n * Returns the font size in the \"data\" space for the specified \"em\" value.\n *\n * @param v The \"em\" value. E.g. 2 for \"2em\".\n * @return The font size for the specified \"em\" value.\n */\nexport function dataFontEm(v: number): number {\n  return Number((v * DEFAULT_EM).toFixed(1));\n}\n\n/**\n * Rounds the pixel value to the max allowed precision in the \"editor\" space.\n *\n * @param v The value to be rounded.\n * @return The value rounded to the \"editor\" space precision.\n */\nexport function editorPixels(v: number): number {\n  return Number(v.toFixed(5));\n}\n\n/**\n * Converts a \"data\" pixel value to the value in the \"editor\" space along\n * the horizontal (X) dimension.\n *\n * @param x The value to be converted.\n * @param pageWidth The basis value for the page's width in the \"editor\" space.\n * @return The value in the \"editor\" space.\n */\nexport function dataToEditorX(x: number, pageWidth: number): number {\n  return editorPixels((x * pageWidth) / PAGE_WIDTH);\n}\n\n/**\n * Converts a \"data\" pixel value to the value in the \"editor\" space along\n * the vertical (Y) dimension.\n *\n * @param y The value to be converted.\n * @param pageHeight The basis value for the page's height in the \"editor\" space.\n * @return The value in the \"editor\" space.\n */\nexport function dataToEditorY(y: number, pageHeight: number): number {\n  return editorPixels((y * pageHeight) / PAGE_HEIGHT);\n}\n\nexport function dataToFontSizeY(v: number, pageHeight: number): string {\n  return (dataToEditorY(v, pageHeight) / 10).toFixed(6);\n}\n\n/**\n * Converts a \"editor\" pixel value to the value in the \"data\" space along\n * the horizontal (X) dimension.\n *\n * @param x The value to be converted.\n * @param pageWidth The basis value for the page's width in the \"editor\" space.\n * @param [withRounding] Whether the dataPixels rounding should occur.\n * @return The value in the \"data\" space.\n */\nexport function editorToDataX(\n  x: number,\n  pageWidth: number,\n  withRounding = true\n): number {\n  const v = (x * PAGE_WIDTH) / pageWidth;\n  if (!withRounding) {\n    return v;\n  }\n  return dataPixels(v);\n}\n\n/**\n * Converts a \"editor\" pixel value to the value in the \"data\" space along\n * the vertical (Y) dimension.\n *\n * @param y The value to be converted.\n * @param pageHeight The basis value for the page's height in the \"editor\" space.\n * @param [withRounding] Whether the dataPixels rounding should occur.\n * @return The value in the \"data\" space.\n */\nexport function editorToDataY(\n  y: number,\n  pageHeight: number,\n  withRounding = true\n): number {\n  const v = (y * PAGE_HEIGHT) / pageHeight;\n  if (!withRounding) {\n    return v;\n  }\n  return dataPixels(v);\n}\n\n/**\n * Converts the element's position, width, and rotation to the \"box\" in the\n * \"editor\" coordinate space.\n *\n * @param element The element's position, width, and rotation. See `StoryPropTypes.element`.\n * @param pageWidth The basis value for the page's width in the \"editor\" space.\n * @param pageHeight The basis value for the page's height in the \"editor\" space.\n * @return The \"box\" in the editor space.\n */\nexport function getBox(\n  { x, y, width, height, rotationAngle, isBackground }: DimensionableElement,\n  pageWidth: number,\n  pageHeight: number\n): ElementBox {\n  return {\n    x: dataToEditorX(isBackground ? 0 : x, pageWidth),\n    y: dataToEditorY(isBackground ? -DANGER_ZONE_HEIGHT : y, pageHeight),\n    width: dataToEditorX(isBackground ? PAGE_WIDTH : width, pageWidth),\n    height: dataToEditorY(isBackground ? FULLBLEED_HEIGHT : height, pageHeight),\n    rotationAngle: isBackground ? 0 : rotationAngle,\n  };\n}\n\n/**\n * Converts the element's position, width, border, and rotation) to the \"box\" in the\n * \"editor\" coordinate space for an element with border.\n *\n * @param element The element object. See `StoryPropTypes.element`.\n * @param pageWidth The basis value for the page's width in the \"editor\" space.\n * @param pageHeight The basis value for the page's height in the \"editor\" space.\n * @return The \"box\" in the editor space.\n */\nexport function getBoxWithBorder(\n  element: DimensionableElement,\n  pageWidth: number,\n  pageHeight: number\n): ElementBox {\n  const { rotationAngle, border } = element;\n  const box = getBox(element, pageWidth, pageHeight);\n  if (!border) {\n    return box;\n  }\n  const { left = 0, right = 0, top = 0, bottom = 0 } = border;\n  const [diffX, diffY] = calcRotatedResizeOffset(\n    rotationAngle,\n    left,\n    right,\n    top,\n    bottom\n  );\n\n  // Since CSS border is used and the border width is not responsive,\n  // the border is not included in the element's width and height,\n  // and we're adding the border to the box in pixels directly.\n  return {\n    ...box,\n    x: box.x + diffX,\n    y: box.y + diffY,\n    width: box.width + left + right,\n    height: box.height + top + bottom,\n  };\n}\n"
  },
  {
    "path": "packages/units/src/getBoundRect.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport calcRotatedObjectPositionAndSize from './calcRotatedObjectPositionAndSize';\nimport type { ElementBox } from './types';\n\n/**\n * Get the outer frame values for all objects in `list`,\n * returns { startX, startY, endX, endY, width, height };\n * Example usage:\n```\ngetBoundRect( [ { x: 10, y: 10, width: 100, height: 50 }, { x: 30, y: 20, width: 100, height: 50 } ] );\n// returns { startX: 10, startY: 10, endX: 130, endY: 70, width: 120, height: 60 };\ngetBoundRect( [ { x: 10, y: 10, width: 100, height: 50 }, { x: 30, y: 20, width: 100, height: 50, rotationAngle: 45 } ] );\n// returns { startX: 10, startY: -8, endX: 133, endY: 98, width: 123, height: 106 };\n```\n *\n * @param list List of elements with size and position properties\n * @return Returns outer frame of all list objects\n */\nfunction getBoundRect(list: ElementBox[]) {\n  const updatedList = list.map((el) =>\n    calcRotatedObjectPositionAndSize(\n      el.rotationAngle,\n      el.x,\n      el.y,\n      el.width,\n      el.height\n    )\n  );\n  const firstElement = updatedList[0];\n  let startX = firstElement.x;\n  let startY = firstElement.y;\n  let endX = startX + firstElement.width;\n  let endY = startY + firstElement.height;\n\n  updatedList.slice(1).forEach((el) => {\n    startX = Math.min(el.x, startX);\n    startY = Math.min(el.y, startY);\n    endX = Math.max(el.x + el.width, endX);\n    endY = Math.max(el.y + el.height, endY);\n  });\n  return {\n    startX,\n    startY,\n    endX,\n    endY,\n    width: endX - startX,\n    height: endY - startY,\n  };\n}\n\nexport default getBoundRect;\n"
  },
  {
    "path": "packages/units/src/getCorner.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport type { Coordinates } from './types';\nimport { dataPixels } from './dimensions';\n\nfunction getCorner(\n  pivotX: number,\n  pivotY: number,\n  cornerX: number,\n  cornerY: number,\n  angle: number\n): Coordinates {\n  /// get distance from center to point\n  const diffX = cornerX - pivotX;\n  const diffY = cornerY - pivotY;\n  const distance = Math.sqrt(diffX * diffX + diffY * diffY);\n\n  /// find angle from pivot to corner\n  angle += Math.atan2(diffY, diffX);\n\n  /// get new x and y and round it off to integer\n  const x = dataPixels(pivotX + distance * Math.cos(angle));\n  const y = dataPixels(pivotY + distance * Math.sin(angle));\n\n  return { x, y };\n}\n\nexport default getCorner;\n"
  },
  {
    "path": "packages/units/src/getCorners.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getCorner from './getCorner';\nimport { Corner, type Corners } from './types';\n\nfunction getCorners(\n  angle: number,\n  x: number,\n  y: number,\n  width: number,\n  height: number\n): Corners {\n  /// variables\n  const centerX = x + width * 0.5;\n  const centerY = y + height * 0.5;\n  const radian = (angle * Math.PI) / 180;\n  /// get corner coordinates\n  const topLeftPoint = getCorner(centerX, centerY, x, y, radian);\n  const topRightPoint = getCorner(centerX, centerY, x + width, y, radian);\n  const bottomRightPoint = getCorner(\n    centerX,\n    centerY,\n    x + width,\n    y + height,\n    radian\n  );\n  const bottomLeftPoint = getCorner(centerX, centerY, x, y + height, radian);\n  return {\n    [Corner.TopLeft]: topLeftPoint,\n    [Corner.TopRight]: topRightPoint,\n    [Corner.BottomRight]: bottomRightPoint,\n    [Corner.BottomLeft]: bottomLeftPoint,\n  };\n}\n\nexport default getCorners;\n"
  },
  {
    "path": "packages/units/src/index.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './constants';\nexport * from './dimensions';\nexport * from './types';\n\nexport { default as UnitsProvider } from './unitsProvider';\nexport { default as useUnits } from './useUnits';\nexport { default as calcRotatedResizeOffset } from './calcRotatedResizeOffset';\nexport * from './range';\nexport { default as calcRotatedObjectPositionAndSize } from './calcRotatedObjectPositionAndSize';\nexport { default as getBoundRect } from './getBoundRect';\nexport { default as getCorners } from './getCorners';\n"
  },
  {
    "path": "packages/units/src/range.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ninterface Range {\n  MIN: number;\n  MAX: number;\n}\n\n/**\n * Linear interpolation function.\n *\n * Takes a normalized progress value and a range in the form of a tuple\n * and returns the interpolated progress within the given range.\n *\n * @param progress Value between 0 and 1.\n * @param range Range.\n * @return value within given range\n */\nexport const lerp = (progress: number, range: Range) =>\n  (1 - progress) * range.MIN + progress * range.MAX;\n\n/**\n * Takes a value and a range in the form of the tuple and returns\n * a normalized progress value of that value within the range.\n *\n * ```js\n * const p = progress(25, {MIN: 0, MAX: 50});\n * console.log(p) // .5\n * ```\n *\n * @param v Value in range\n * @param range Range.\n * @return Progress value in the range [0, 1]\n */\nexport const progress = (v: number, range: Range) => {\n  const clamped = clamp(v, range);\n  const delta = clamped - range.MIN;\n  const difference = range.MAX - range.MIN;\n\n  return Math.abs(delta / difference);\n};\n\n/**\n * Takes a value and a range in the form of a tuple and clamps the value to that range.\n *\n * @param value Value to be clamped.\n * @param range Range.\n * @return Number within range.\n */\nexport const clamp = (value: number, { MIN, MAX }: Range) => {\n  return Math.min(Math.max(value, MIN), MAX);\n};\n"
  },
  {
    "path": "packages/units/src/test/getBoundRect.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getBoundRect from '../getBoundRect';\n\ndescribe('getBoundRect', () => {\n  it('should return correct outer frame values for 2 unrotated objects', () => {\n    const elements = [\n      {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        rotationAngle: 0,\n      },\n      {\n        x: 30,\n        y: 20,\n        width: 100,\n        height: 50,\n        rotationAngle: 0,\n      },\n    ];\n\n    const expectedResult = {\n      startX: 10,\n      startY: 10,\n      endX: 130,\n      endY: 70,\n      width: 120,\n      height: 60,\n    };\n    const boundRect = getBoundRect(elements);\n    expect(boundRect).toStrictEqual(expectedResult);\n  });\n\n  it('should return correct outer frame values for 2+ unrotated objects', () => {\n    const elements = [\n      {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        rotationAngle: 0,\n      },\n      {\n        x: 30,\n        y: 20,\n        width: 100,\n        height: 50,\n        rotationAngle: 0,\n      },\n      {\n        x: 75,\n        y: 84,\n        width: 50,\n        height: 32,\n        rotationAngle: 0,\n      },\n    ];\n\n    const expectedResult = {\n      startX: 10,\n      startY: 10,\n      endX: 130,\n      endY: 116,\n      width: 120,\n      height: 106,\n    };\n    const boundRect = getBoundRect(elements);\n    expect(boundRect).toStrictEqual(expectedResult);\n  });\n\n  it('should return correct outer frame values for 2 rotated objects', () => {\n    const elements = [\n      {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        rotationAngle: 45,\n      },\n      {\n        x: 30,\n        y: 20,\n        width: 100,\n        height: 50,\n        rotationAngle: 120,\n      },\n    ];\n\n    const expectedResult = {\n      startX: 7,\n      startY: -18,\n      endX: 127,\n      endY: 101,\n      width: 120,\n      height: 119,\n    };\n    const boundRect = getBoundRect(elements);\n    expect(boundRect).toStrictEqual(expectedResult);\n  });\n\n  it('should return correct outer frame values for 2+ rotated and unrotated objects', () => {\n    const elements = [\n      {\n        x: 10,\n        y: 10,\n        width: 100,\n        height: 50,\n        rotationAngle: 45,\n      },\n      {\n        x: 30,\n        y: 20,\n        width: 100,\n        height: 50,\n        rotationAngle: 120,\n      },\n      {\n        x: 57,\n        y: 83,\n        width: 250,\n        height: 12,\n        rotationAngle: 0,\n      },\n      {\n        x: 18,\n        y: 5,\n        width: 100,\n        height: 100,\n        rotationAngle: 90,\n      },\n    ];\n\n    const expectedResult = {\n      startX: 7,\n      startY: -18,\n      endX: 307,\n      endY: 105,\n      width: 300,\n      height: 123,\n    };\n    const boundRect = getBoundRect(elements);\n    expect(boundRect).toStrictEqual(expectedResult);\n  });\n});\n"
  },
  {
    "path": "packages/units/src/test/range.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { clamp, lerp, progress } from '../range';\n\ndescribe('lerp', () => {\n  it('equals `target` when `progress === 1`', () => {\n    const target = 60;\n    expect(lerp(1, { MIN: 0, MAX: target })).toStrictEqual(target);\n  });\n\n  it('equals `initial` when `progress === 0`', () => {\n    const initial = 60;\n    expect(lerp(0, { MIN: initial, MAX: 0 })).toStrictEqual(initial);\n  });\n\n  it('calculates normal range properly', () => {\n    const range = { MIN: 0, MAX: 100 };\n    expect(lerp(0.25, range)).toBe(25);\n    expect(lerp(0.5, range)).toBe(50);\n    expect(lerp(0.75, range)).toBe(75);\n  });\n\n  it('calculates reverse range properly', () => {\n    const range = { MIN: 100, MAX: 0 };\n    expect(lerp(0.25, range)).toBe(75);\n    expect(lerp(0.5, range)).toBe(50);\n    expect(lerp(0.75, range)).toBe(25);\n  });\n});\n\ndescribe('clamp', () => {\n  it('should return 2 when range is [1, 6] and value is 2', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(2, range);\n\n    expect(clampedNumber).toBe(2);\n  });\n\n  it('should return 1 when range is [1, 6] and value is 8', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(8, range);\n\n    expect(clampedNumber).toBe(6);\n  });\n\n  it('should return 6 when range is [1, 6] and value is 0', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(0, range);\n\n    expect(clampedNumber).toBe(1);\n  });\n\n  it('should return 1 when range is [1, 6] and value is -1', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(-1, range);\n\n    expect(clampedNumber).toBe(1);\n  });\n\n  it('should return 5.4 when range is [1, 6] and value is 5.4', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(5.4, range);\n\n    expect(clampedNumber).toBe(5.4);\n  });\n\n  it('should return 6 when range is [1, 6] and value is 6.4', () => {\n    const range = { MIN: 1, MAX: 6 };\n    const clampedNumber = clamp(6.4, range);\n\n    expect(clampedNumber).toBe(6);\n  });\n});\n\ndescribe('progress', () => {\n  it('calculates progress in standard range', () => {\n    const standard = { MIN: 0, MAX: 100 };\n    expect(progress(0, standard)).toBe(0);\n    expect(progress(25, standard)).toBe(0.25);\n    expect(progress(50, standard)).toBe(0.5);\n    expect(progress(75, standard)).toBe(0.75);\n    expect(progress(100, standard)).toBe(1);\n  });\n\n  it('calculates progress in negative range', () => {\n    const negative = { MIN: -100, MAX: 0 };\n    expect(progress(-100, negative)).toBe(0);\n    expect(progress(-75, negative)).toBe(0.25);\n    expect(progress(-50, negative)).toBe(0.5);\n    expect(progress(-25, negative)).toBe(0.75);\n    expect(progress(0, negative)).toBe(1);\n  });\n});\n"
  },
  {
    "path": "packages/units/src/types.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport interface ElementBox {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n  rotationAngle: number;\n}\n\ninterface Border {\n  top: number;\n  right: number;\n  bottom: number;\n  left: number;\n}\n\nexport interface DimensionableElement extends ElementBox {\n  isBackground?: boolean;\n  border?: Border;\n}\n\nexport interface State {\n  state: {\n    pageSize: {\n      width: number;\n      height: number;\n    };\n  };\n  actions: {\n    dataToEditorX: (x: number) => number;\n    dataToEditorY: (y: number) => number;\n    editorToDataX: (x: number, withRounding?: boolean) => number;\n    editorToDataY: (y: number, withRounding?: boolean) => number;\n    getBox: (element: DimensionableElement) => ElementBox;\n    getBoxWithBorder: (element: DimensionableElement) => ElementBox;\n  };\n}\n\nexport interface Coordinates {\n  x: number;\n  y: number;\n}\n\nexport enum Corner {\n  TopLeft = 'topLeftPoint',\n  TopRight = 'topRightPoint',\n  BottomRight = 'bottomRightPoint',\n  BottomLeft = 'bottomLeftPoint',\n}\n\nexport type Corners = {\n  [key in Corner]: Coordinates;\n};\n"
  },
  {
    "path": "packages/units/src/unitsProvider.tsx",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\nimport { useMemo } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { State, DimensionableElement } from './types';\nimport {\n  dataToEditorX,\n  dataToEditorY,\n  editorToDataX,\n  editorToDataY,\n  getBox,\n  getBoxWithBorder,\n} from './dimensions';\n\ninterface PageSize {\n  width: number;\n  height: number;\n}\n\ninterface UnitsProviderProps {\n  pageSize: PageSize;\n  children: ReactNode;\n}\n\nfunction UnitsProvider({ pageSize, children }: UnitsProviderProps) {\n  const { width: pageWidth, height: pageHeight } = pageSize;\n  const state: State = useMemo(\n    () => ({\n      state: {\n        pageSize: { width: pageWidth, height: pageHeight },\n      },\n      actions: {\n        dataToEditorX: (x: number) => dataToEditorX(x, pageWidth),\n        dataToEditorY: (y: number) => dataToEditorY(y, pageHeight),\n        editorToDataX: (x: number, withRounding?: boolean) =>\n          editorToDataX(x, pageWidth, withRounding),\n        editorToDataY: (y: number, withRounding?: boolean) =>\n          editorToDataY(y, pageHeight, withRounding),\n        getBox: (element: DimensionableElement) =>\n          getBox(element, pageWidth, pageHeight),\n        getBoxWithBorder: (element: DimensionableElement) =>\n          getBoxWithBorder(element, pageWidth, pageHeight),\n      },\n    }),\n    [pageWidth, pageHeight]\n  );\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nexport default UnitsProvider;\n"
  },
  {
    "path": "packages/units/src/useUnits.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\nimport type { State } from './types';\n\nfunction useUnits(): State;\nfunction useUnits<T>(selector: (state: State) => T): T;\nfunction useUnits<T>(selector: (state: State) => T | State = identity) {\n  return useContextSelector(Context, selector);\n}\n\nexport default useUnits;\n"
  },
  {
    "path": "packages/units/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"references\": [{ \"path\": \"../react\" }],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/url/.npmignore",
    "content": "src\n"
  },
  {
    "path": "packages/url/README.md",
    "content": "# Url\n\nURL utility package for Web Stories editor.\n"
  },
  {
    "path": "packages/url/package.json",
    "content": "{\n  \"name\": \"@googleforcreators/url\",\n  \"description\": \"URL utility package for Web Stories editor\",\n  \"private\": false,\n  \"version\": \"0.1.202410011217\",\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/url/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/url\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"customExports\": {\n    \".\": {\n      \"default\": \"./src/index.ts\"\n    }\n  },\n  \"main\": \"dist/index.js\",\n  \"module\": \"dist-module/index.js\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/url/src/addQueryArgs.ts",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Appends search params to the provided URL.\n *\n * @param url URL to be modified.\n * @param args Query arguments to apply to URL.\n * @example\n * ```js\n * const newURL = addQueryArgs( 'https://google.com', { q: 'test' } ); // https://google.com/?q=test\n * ```\n * @return URL with arguments applied.\n */\nexport default function addQueryArgs(\n  url: string,\n  args: Record<string, null | string | undefined>\n): string {\n  let isRelativeUrl = false;\n  let parsedURL;\n\n  try {\n    parsedURL = new URL(url);\n  } catch {\n    parsedURL = new URL(url, document.location.href);\n    isRelativeUrl = true;\n  }\n\n  for (const key in args) {\n    if (!Object.prototype.hasOwnProperty.call(args, key)) {\n      continue;\n    }\n\n    const value = args[key];\n\n    if (typeof value !== 'undefined' && value !== null) {\n      parsedURL.searchParams.set(key, value);\n    }\n  }\n\n  return isRelativeUrl ? parsedURL.pathname + parsedURL.search : parsedURL.href;\n}\n"
  },
  {
    "path": "packages/url/src/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * from './url';\nexport { default as addQueryArgs } from './addQueryArgs';\nexport { default as safeDecodeURIComponent } from './safeDecodeUriComponent';\n"
  },
  {
    "path": "packages/url/src/safeDecodeUriComponent.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Safely decodes a URI component with `decodeURIComponent`. Returns the URI component unmodified if\n * `decodeURIComponent` throws an error.\n *\n * @param uriComponent URI component to decode.\n * @return Decoded URI component if possible.\n */\nexport default function safeDecodeURIComponent(uriComponent: string) {\n  try {\n    return decodeURIComponent(uriComponent);\n  } catch {\n    return uriComponent;\n  }\n}\n"
  },
  {
    "path": "packages/url/src/test/addQueryArgs.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport addQueryArgs from '../addQueryArgs';\n\ndescribe('addQueryArgs', () => {\n  it('should leave URL unaffected if no args passed', () => {\n    const url = 'https://google.com/';\n    const args = {};\n\n    expect(addQueryArgs(url, args)).toBe(url);\n  });\n\n  it('should append args', () => {\n    const url = 'https://google.com/';\n    const args = { q: 'test' };\n\n    expect(addQueryArgs(url, args)).toBe('https://google.com/?q=test');\n  });\n\n  it('should append args to existing ones', () => {\n    const url = 'https://google.com/?foo=bar';\n    const args = { q: 'test' };\n\n    expect(addQueryArgs(url, args)).toBe('https://google.com/?foo=bar&q=test');\n  });\n\n  it('should replace existing args', () => {\n    const url = 'https://google.com/?foo=bar';\n    const args = { foo: 'baz' };\n\n    expect(addQueryArgs(url, args)).toBe('https://google.com/?foo=baz');\n  });\n\n  it('should append args to relative URL', () => {\n    const url = '/foo/bar';\n    const args = { q: 'test' };\n\n    expect(addQueryArgs(url, args)).toBe('/foo/bar?q=test');\n  });\n\n  it('should disregard keys with undefined or null values', () => {\n    const url = 'https://google.com/';\n    const args = { foo: 'true', bar: undefined, baz: null };\n\n    expect(addQueryArgs(url, args)).toBe('https://google.com/?foo=true');\n  });\n});\n"
  },
  {
    "path": "packages/url/src/test/safeDecodeUriComponent.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport safeDecodeURIComponent from '../safeDecodeUriComponent';\n\ndescribe('safeDecodeURIComponent', () => {\n  it.each([\n    ['kanji-%e6%bc%a2%e5%ad%97', 'kanji-漢字'],\n    ['%CE%A7%CE%B1%CE%AF%CF%81%CE%B5%CF%84%CE%B5', 'Χαίρετε'],\n    ['%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C', '你好世界'],\n  ])(\n    'should decode the URI %s correctly and return %s',\n    (original, expected) => {\n      expect(safeDecodeURIComponent(original)).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/url/src/test/url.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { withProtocol, isValidUrl, withoutProtocol } from '..';\n\ndescribe('isValidUrl', () => {\n  it('should return correct results for valid URL', () => {\n    expect(isValidUrl('foo-bar')).toBeFalse();\n    expect(isValidUrl('foo-bar.jpg')).toBeFalse();\n    expect(isValidUrl('//foo-bar')).toBeFalse();\n    expect(isValidUrl('http://foo-bar')).toBeTrue();\n    expect(isValidUrl('https://foo-bar.com')).toBeTrue();\n    expect(isValidUrl('https://foo-bar.com/test.jpg')).toBeTrue();\n    expect(isValidUrl('https://foo-bar.com/example.html')).toBeTrue();\n    expect(isValidUrl('https://foo-bar.com/font.ttf')).toBeTrue();\n    expect(isValidUrl('tel:1234567')).toBeTrue();\n    expect(isValidUrl('mailto:example@example.com')).toBeTrue();\n  });\n});\n\ndescribe('withProtocol', () => {\n  it('should add protocol correctly if applicable', () => {\n    expect(withProtocol('https://foo.com/test')).toBe('https://foo.com/test');\n    expect(withProtocol('http://foo.com/test')).toBe('http://foo.com/test');\n    expect(withProtocol('foo.com/test')).toBe('https://foo.com/test');\n  });\n});\n\ndescribe('withoutProtocol', () => {\n  it('should remove protocol correctly if applicable', () => {\n    expect(withoutProtocol('https://foo.com/test')).toBe('foo.com/test');\n    expect(withoutProtocol('http://foo.com/test')).toBe('foo.com/test');\n    expect(withoutProtocol('foo.com/test')).toBe('foo.com/test');\n  });\n});\n"
  },
  {
    "path": "packages/url/src/url.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport function toAbsoluteUrl(base: string, path: string): string {\n  try {\n    return new URL(path, base).href;\n  } catch {\n    return path;\n  }\n}\n\nexport function isValidUrl(url: string): boolean {\n  try {\n    // eslint-disable-next-line no-new -- Needed here just to catch errors.\n    new URL(url);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Prepends a protocol (default https) to a URL that doesn't have one\n *\n * @param url URL.\n * @param [protocol] default protocol to prepend\n * @return the url with the protocol prepended to it\n */\nexport function withProtocol(\n  url: string,\n  protocol: 'http' | 'https' | 'tel' | 'mailto' = 'https'\n): string {\n  return /^(http:\\/\\/|https:\\/\\/|tel:|mailto:)/.test(url)\n    ? url\n    : `${protocol}://${url}`;\n}\n\nexport function withoutProtocol(url: string): string {\n  return url.replace(/^(http:\\/\\/|https:\\/\\/|tel:|mailto:)/, '');\n}\n"
  },
  {
    "path": "packages/url/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"files\": [\"../../node_modules/jest-extended/types/index.d.ts\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "packages/widget/README.md",
    "content": "# Widget\n\nWordPress widget javascript.\n"
  },
  {
    "path": "packages/widget/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/widget\",\n  \"description\": \"Web Stories widget\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/widget/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/widget\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@wordpress/dom-ready\": \"^4.22.0\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "packages/widget/src/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport domReady from '@wordpress/dom-ready';\n\n/**\n * Internal dependencies\n */\nimport './style.css';\n\n/**\n * Store field states in local variable.\n *\n * @type {Object}\n */\nconst fieldState = window.webStoriesData || {};\n\n/**\n * Closure for making inputs reactive\n * on view type selection change.\n *\n * @param {Object}  target Event object.\n * @param {boolean} reset Flag to reset fields value.\n */\nconst reactiveWidget = (target, reset = false) => {\n  const currentView = target.value;\n  const widget = target.closest('.widget');\n  const state = fieldState.fields[currentView];\n\n  for (const [key, fieldObj] of Object.entries(state)) {\n    const field = widget.querySelector(`.${key}.stories-widget-field`);\n    const fieldWrapper = widget.querySelector(`.${key}_wrapper`);\n\n    if (field && fieldWrapper) {\n      const field_type = field.getAttribute('type');\n\n      if ('checkbox' === field_type) {\n        if (reset) {\n          field.checked = false;\n        }\n        /**\n         * If this is readonly field.\n         * Assign the value automatically and hide it afterward.\n         */\n        if (fieldObj.hidden) {\n          field.checked = fieldObj.show;\n        }\n\n        fieldWrapper.style.display = fieldObj.hidden ? 'none' : 'block';\n      } else {\n        fieldWrapper.style.display = fieldObj.show ? 'block' : 'none';\n      }\n    }\n  }\n};\n\n/**\n * Returns the HTML Collection of view type selectors.\n *\n * @return {HTMLCollection} Array of elements.\n */\nconst viewSelectors = () =>\n  document.getElementsByClassName('view_type stories-widget-field');\n\n/**\n * Bind event on view type selection change.\n */\nconst bindEvent = () => {\n  const dropdowns = viewSelectors();\n\n  if (dropdowns.length) {\n    for (let i = 0; i < dropdowns.length; i++) {\n      dropdowns[i].addEventListener('change', (event) => {\n        reactiveWidget(event.target, false);\n      });\n    }\n  }\n};\n\n/**\n * Fire event manually once.\n */\nconst fireEvent = () => {\n  const dropdowns = viewSelectors();\n  const evt = document.createEvent('HTMLEvents');\n  evt.initEvent('change', false, true);\n  for (let l = 0; l < dropdowns.length; l++) {\n    dropdowns[l].dispatchEvent(evt);\n  }\n};\n\n/**\n * Wait till document is ready and then bind the event.\n */\ndomReady(() => {\n  bindEvent();\n  fireEvent();\n});\n\n/**\n * Called when widget is updated or added.\n *\n * @param {Object} event Event object.\n * @param {Object} widget Widget jQuery object.\n */\nconst widgetChange = (event, widget) => {\n  if (!widget[0]) {\n    return;\n  }\n\n  const target = widget[0].querySelectorAll('.stories-widget-field.view_type');\n\n  if (target.length) {\n    reactiveWidget(target[0], false);\n    bindEvent();\n  }\n};\n\nconst $ = window.jQuery;\n\n/**\n * Listen to widget updated event and update the widget.\n */\n$(document).on('widget-updated', widgetChange);\n$(document).on('widget-added', widgetChange);\n"
  },
  {
    "path": "packages/widget/src/style.css",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#available-widgets [class*='web_stories'] .widget-title:before {\n  content: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMDggMjA4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8Y2lyY2xlIGN4PSIxMDAiIGN5PSIxMDAiIHI9IjEwMCIgZmlsbD0iYmxhY2siLz4KPHBhdGggZD0iTTEzNS4yIDYyLjQwMDVDMTQwLjk0NCA2Mi40MDA1IDE0NS42IDY3LjA1NjcgMTQ1LjYgNzIuODAwNVYxMzUuMkMxNDUuNiAxNDAuOTQ0IDE0MC45NDQgMTQ1LjYgMTM1LjIgMTQ1LjZWNjIuNDAwNVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik01Ny4yIDYyLjQwMDVDNTcuMiA1Ni42NTY3IDYxLjg1NjIgNTIuMDAwNSA2Ny42IDUyLjAwMDVIMTE0LjRDMTIwLjE0NCA1Mi4wMDA1IDEyNC44IDU2LjY1NjcgMTI0LjggNjIuNDAwNVYxNDUuNkMxMjQuOCAxNTEuMzQ0IDEyMC4xNDQgMTU2IDExNC40IDE1Nkg2Ny42QzYxLjg1NjIgMTU2IDU3LjIgMTUxLjM0NCA1Ny4yIDE0NS42VjYyLjQwMDVaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMTU2IDcyLjgwMDVDMTYwLjMwOCA3Mi44MDA1IDE2My44IDc2LjI5MjcgMTYzLjggODAuNjAwNVYxMjcuNEMxNjMuOCAxMzEuNzA4IDE2MC4zMDggMTM1LjIgMTU2IDEzNS4yVjcyLjgwMDVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=');\n}\n"
  },
  {
    "path": "packages/wp-dashboard/README.md",
    "content": "# WP Dashboard\n\nContains WordPress integration of dashboard.\n"
  },
  {
    "path": "packages/wp-dashboard/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/wp-dashboard\",\n  \"description\": \"WordPress Web Stories dashboard\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/wp-dashboard/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/wp-dashboard\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@googleforcreators/dashboard\": \"*\",\n    \"@googleforcreators/date\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/dom\": \"*\",\n    \"@googleforcreators/fonts\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/patterns\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@googleforcreators/url\": \"*\",\n    \"@web-stories-wp/wp-utils\": \"*\",\n    \"@wordpress/api-fetch\": \"^7.43.0\",\n    \"@wordpress/dom-ready\": \"^4.22.0\",\n    \"flagged\": \"^2.0.10\",\n    \"opentype.js\": \"^1.3.4\",\n    \"prop-types\": \"^15.8.1\",\n    \"styled-components\": \"^5.3.11\",\n    \"uuid\": \"^11.1.0\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"@testing-library/user-event\": \"^14.6.1\"\n  }\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/authors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\nexport function getAuthors(config, search) {\n  return apiFetch({\n    path: addQueryArgs(config.api.users, {\n      per_page: '100',\n      capabilities: config.editPostsCapabilityName,\n      search,\n    }),\n  });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/constants/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const STORY_FIELDS = [\n  'id',\n  'title',\n  'status',\n  'date',\n  'date_gmt',\n  'modified',\n  'modified_gmt',\n  'story_poster',\n  'link',\n  'preview_link',\n  'edit_link',\n  '_links', // Needed for WP 6.1+\n  '_embedded',\n  // _web_stories_envelope will add these fields, we need them too.\n  'body',\n  'status',\n  'headers',\n].join(',');\n\nexport const SEARCH_PAGES_FIELDS = ['id', 'title'];\nexport const GET_PAGE_FIELDS = ['title', 'link'];\n\nexport const STORY_EMBED = 'wp:lock,author';\n\nexport const REST_LINKS = {\n  EDIT: 'wp:action-edit',\n  DELETE: 'wp:action-delete',\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/fonts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Gets custom fonts added by the user.\n * Used for \"Custom Fonts\" list on settings page.\n *\n * @param {string} apiPath API path.\n * @return {Promise} Request promise.\n */\nexport function getCustomFonts(apiPath) {\n  const path = addQueryArgs(apiPath, {\n    per_page: 100,\n    service: 'custom',\n  });\n\n  return apiFetch({ path });\n}\n\n/**\n * Delete a font by ID.\n *\n * @param {string} apiPath API path.\n * @param {number|string} id Font Id.\n * @return {Promise} Request promise.\n */\nexport function deleteCustomFont(apiPath, id) {\n  const path = addQueryArgs(`${apiPath}${id}/`, {\n    _method: 'DELETE',\n  });\n\n  return apiFetch({\n    path,\n    method: 'POST',\n  });\n}\n\n/**\n * Add new custom font.\n *\n * @param {string} apiPath API path.\n * @param {Object} font Font data.\n * @return {Promise} Request promise.\n */\nexport function addCustomFont(apiPath, font) {\n  return apiFetch({\n    path: apiPath,\n    data: font,\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/useApiAlerts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useDebouncedCallback } from '@googleforcreators/react';\nimport { useSnackbar } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SUCCESS } from '../../constants';\nimport useEditorSettings from '../../components/editorSettings/useEditorSettings';\n\nfunction useApiAlerts() {\n  const { settingsError, mediaError, settingSaved, publisherLogosError } =\n    useEditorSettings(\n      ({\n        state: {\n          settings: { error: settingsError, settingSaved },\n          media: { error: mediaError },\n          publisherLogos: {\n            error: publisherLogosError,\n            settingSaved: publisherLogosSaved,\n          },\n        },\n      }) => ({\n        settingsError,\n        mediaError,\n        settingSaved: settingSaved || publisherLogosSaved,\n        publisherLogosError,\n      })\n    );\n  const { showSnackbar } = useSnackbar();\n\n  const debouncedShowSnackbar = useDebouncedCallback((message) => {\n    return showSnackbar({ 'aria-label': message, message, dismissible: true });\n  }, 200);\n\n  // if there is an API error, display a snackbar\n  useEffect(() => {\n    if (settingsError?.id) {\n      debouncedShowSnackbar(settingsError.message);\n    }\n  }, [settingsError, debouncedShowSnackbar]);\n\n  useEffect(() => {\n    if (settingSaved) {\n      debouncedShowSnackbar(SUCCESS.SETTINGS.UPDATED);\n    }\n  }, [debouncedShowSnackbar, settingSaved]);\n\n  useEffect(() => {\n    if (mediaError?.id) {\n      debouncedShowSnackbar(mediaError.message);\n    }\n  }, [mediaError, debouncedShowSnackbar]);\n\n  useEffect(() => {\n    if (publisherLogosError?.id) {\n      debouncedShowSnackbar(publisherLogosError.message);\n    }\n  }, [publisherLogosError, debouncedShowSnackbar]);\n}\nexport default useApiAlerts;\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/useFontsApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  addCustomFont as addCustomFontCallback,\n  getCustomFonts as getCustomFontsCallback,\n  deleteCustomFont as deleteCustomFontCallback,\n} from '../fonts';\n\nexport default function useFontsApi() {\n  const {\n    api: { fonts: fontsApiPath },\n  } = useConfig();\n  const [customFonts, setCustomFonts] = useState(null);\n\n  const fetchCustomFonts = useCallback(async () => {\n    try {\n      const response = await getCustomFontsCallback(fontsApiPath);\n      const filteredFonts = response.map(({ id, family, url }) => ({\n        id,\n        family,\n        url,\n      }));\n      setCustomFonts(filteredFonts);\n      return filteredFonts;\n    } catch {\n      return null;\n    }\n  }, [fontsApiPath]);\n\n  const deleteCustomFont = useCallback(\n    async (id) => {\n      const response = await deleteCustomFontCallback(fontsApiPath, id);\n      const newCustomFonts = customFonts.filter((font) => font.id !== id);\n      setCustomFonts(newCustomFonts);\n      return response;\n    },\n    [customFonts, fontsApiPath]\n  );\n\n  const addCustomFont = useCallback(\n    async (font) => {\n      const response = await addCustomFontCallback(fontsApiPath, font);\n      const { id, family, url } = response;\n      const newFont = { id, family, url };\n      setCustomFonts([newFont, ...customFonts]);\n      return newFont;\n    },\n    [customFonts, fontsApiPath]\n  );\n\n  return {\n    customFonts,\n    api: { addCustomFont, deleteCustomFont, fetchCustomFonts },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/useMediaApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReducer } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport mediaReducer, {\n  defaultMediaState,\n  ACTION_TYPES as MEDIA_ACTION_TYPES,\n} from '../reducers/media';\nimport { ERRORS } from '../../constants';\nimport { uploadMedia as uploadMediaCallback } from '../media';\n\nexport default function useMediaApi() {\n  const [state, dispatch] = useReducer(mediaReducer, defaultMediaState);\n  const {\n    api: { media: mediaApiPath },\n  } = useConfig();\n\n  const uploadMedia = useCallback(\n    async (files) => {\n      dispatch({\n        type: MEDIA_ACTION_TYPES.LOADING_MEDIA,\n      });\n\n      try {\n        // each file needs to be uploaded separately\n        const mediaResponse = await uploadMediaCallback(mediaApiPath, files);\n\n        dispatch({\n          type: MEDIA_ACTION_TYPES.ADD_MEDIA_SUCCESS,\n          payload: {\n            media: mediaResponse,\n            newlyCreatedMediaIds: mediaResponse.map(({ id }) => id),\n          },\n        });\n      } catch {\n        dispatch({\n          type: MEDIA_ACTION_TYPES.ADD_MEDIA_FAILURE,\n          payload: {\n            message:\n              ERRORS.UPLOAD_PUBLISHER_LOGO[\n                files.length > 1 ? 'MESSAGE_PLURAL' : 'MESSAGE'\n              ],\n          },\n        });\n      }\n    },\n    [mediaApiPath]\n  );\n\n  return {\n    media: state,\n    api: {\n      uploadMedia,\n    },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/usePagesApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { stripHTML } from '@googleforcreators/dom';\nimport { useCallback } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  getPageById as getPageByIdCallback,\n  searchPages as searchPagesCallback,\n} from '../pages';\n\nexport default function usePagesApi() {\n  const {\n    api: { pages: pagesApiPath },\n  } = useConfig();\n\n  const getPageById = useCallback(\n    async (id) => {\n      try {\n        const { title, link } = await getPageByIdCallback(pagesApiPath, id);\n\n        return {\n          title: stripHTML(title.rendered),\n          link,\n        };\n      } catch {\n        return null;\n      }\n    },\n    [pagesApiPath]\n  );\n\n  const searchPages = useCallback(\n    async (searchTerm) => {\n      try {\n        const response = await searchPagesCallback(pagesApiPath, searchTerm);\n\n        return response.map(({ id, title }) => ({\n          value: id,\n          label: stripHTML(title.rendered),\n        }));\n      } catch {\n        return [];\n      }\n    },\n    [pagesApiPath]\n  );\n\n  return {\n    api: { searchPages, getPageById },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/usePublisherLogosApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReducer } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport publisherLogosReducer, {\n  defaultPublisherLogosState,\n  ACTION_TYPES,\n} from '../reducers/publisherLogos';\nimport { ERRORS } from '../../constants';\n\nimport {\n  fetchPublisherLogos as fetchPublisherLogosCallback,\n  addPublisherLogo as addPublisherLogoCallback,\n  removePublisherLogo as removePublisherLogoCallback,\n  setPublisherLogoAsDefault as setPublisherLogoAsDefaultCallback,\n} from '../publisherLogo';\n\nexport default function usePublisherLogosApi() {\n  const [state, dispatch] = useReducer(\n    publisherLogosReducer,\n    defaultPublisherLogosState\n  );\n  const {\n    api: { publisherLogos: publisherLogosApiPath },\n  } = useConfig();\n\n  const fetchPublisherLogos = useCallback(async () => {\n    dispatch({\n      type: ACTION_TYPES.LOADING,\n    });\n\n    try {\n      const response = await fetchPublisherLogosCallback(publisherLogosApiPath);\n\n      if (!Array.isArray(response)) {\n        dispatch({\n          type: ACTION_TYPES.FETCH_FAILURE,\n          payload: {\n            message: ERRORS.LOAD_PUBLISHER_LOGOS.MESSAGE,\n          },\n        });\n      } else {\n        dispatch({\n          type: ACTION_TYPES.FETCH_SUCCESS,\n          payload: {\n            publisherLogos: response,\n          },\n        });\n      }\n    } catch {\n      dispatch({\n        type: ACTION_TYPES.FETCH_FAILURE,\n        payload: {\n          message: ERRORS.LOAD_PUBLISHER_LOGOS.MESSAGE,\n        },\n      });\n    }\n  }, [publisherLogosApiPath]);\n\n  const removePublisherLogo = useCallback(\n    async (publisherLogoId) => {\n      dispatch({\n        type: ACTION_TYPES.LOADING,\n      });\n\n      try {\n        await removePublisherLogoCallback(\n          publisherLogosApiPath,\n          publisherLogoId\n        );\n\n        dispatch({\n          type: ACTION_TYPES.REMOVE_SUCCESS,\n          payload: {\n            id: publisherLogoId,\n          },\n        });\n      } catch {\n        dispatch({\n          type: ACTION_TYPES.FETCH_FAILURE,\n          payload: {\n            message: ERRORS.REMOVE_PUBLISHER_LOGO.MESSAGE,\n          },\n        });\n      }\n    },\n    [publisherLogosApiPath]\n  );\n\n  const addPublisherLogo = useCallback(\n    async (publisherLogoIds) => {\n      dispatch({\n        type: ACTION_TYPES.LOADING,\n      });\n\n      try {\n        const response = await addPublisherLogoCallback(\n          publisherLogosApiPath,\n          publisherLogoIds\n        );\n\n        const publisherLogos = Array.isArray(response) ? response : [response];\n\n        for (const publisherLogo of publisherLogos) {\n          dispatch({\n            type: ACTION_TYPES.ADD_SUCCESS,\n            payload: {\n              publisherLogo,\n            },\n          });\n        }\n      } catch {\n        dispatch({\n          type: ACTION_TYPES.ADD_FAILURE,\n          payload: {\n            message: ERRORS.UPLOAD_PUBLISHER_LOGO.MESSAGE,\n          },\n        });\n      }\n    },\n    [publisherLogosApiPath]\n  );\n\n  const setPublisherLogoAsDefault = useCallback(\n    async (publisherLogoId) => {\n      dispatch({\n        type: ACTION_TYPES.LOADING,\n      });\n\n      try {\n        const response = await setPublisherLogoAsDefaultCallback(\n          publisherLogosApiPath,\n          publisherLogoId\n        );\n\n        dispatch({\n          type: ACTION_TYPES.UPDATE_SUCCESS,\n          payload: {\n            publisherLogo: response,\n          },\n        });\n      } catch {\n        dispatch({\n          type: ACTION_TYPES.FETCH_FAILURE,\n          payload: {\n            message: ERRORS.UPDATE_PUBLISHER_LOGO.MESSAGE,\n          },\n        });\n      }\n    },\n    [publisherLogosApiPath]\n  );\n\n  return {\n    publisherLogos: state,\n    api: {\n      fetchPublisherLogos,\n      addPublisherLogo,\n      removePublisherLogo,\n      setPublisherLogoAsDefault,\n    },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/useSettingsApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useReducer } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport settingsReducer, {\n  defaultSettingsState,\n  ACTION_TYPES as SETTINGS_ACTION_TYPES,\n} from '../reducers/settings';\nimport { ERRORS } from '../../constants';\nimport {\n  fetchSettings as fetchSettingsCallback,\n  updateSettings as updateSettingsCallback,\n} from '../settings';\n\nexport default function useSettingsApi() {\n  const [state, dispatch] = useReducer(settingsReducer, defaultSettingsState);\n  const {\n    api: { settings: settingsApiPath },\n  } = useConfig();\n\n  const fetchSettings = useCallback(async () => {\n    try {\n      const response = await fetchSettingsCallback(settingsApiPath);\n\n      dispatch({\n        type: SETTINGS_ACTION_TYPES.FETCH_SETTINGS_SUCCESS,\n        payload: response,\n      });\n    } catch {\n      dispatch({\n        type: SETTINGS_ACTION_TYPES.FETCH_SETTINGS_FAILURE,\n        payload: {\n          message: ERRORS.LOAD_SETTINGS.MESSAGE,\n        },\n      });\n    }\n  }, [settingsApiPath]);\n\n  const updateSettings = useCallback(\n    async (queryParams) => {\n      dispatch({ type: SETTINGS_ACTION_TYPES.SETTING_SAVED });\n      try {\n        const response = await updateSettingsCallback(\n          settingsApiPath,\n          queryParams\n        );\n\n        dispatch({\n          type: SETTINGS_ACTION_TYPES.UPDATE_SETTINGS_SUCCESS,\n          payload: response,\n        });\n        dispatch({ type: SETTINGS_ACTION_TYPES.SETTING_SAVED, payload: true });\n      } catch {\n        dispatch({\n          type: SETTINGS_ACTION_TYPES.UPDATE_SETTINGS_FAILURE,\n          payload: {\n            message: ERRORS.UPDATE_EDITOR_SETTINGS.MESSAGE,\n          },\n        });\n      }\n    },\n    [settingsApiPath]\n  );\n\n  return {\n    settings: state,\n    api: {\n      fetchSettings,\n      updateSettings,\n    },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/hooks/useUserApi.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  getUser,\n  toggleWebStoriesTrackingOptIn as toggleWebStoriesTrackingOptInCallback,\n  toggleWebStoriesMediaOptimization as toggleWebStoriesMediaOptimizationCallback,\n} from '../user';\n\nexport default function useUserApi() {\n  const [currentUser, setCurrentUser] = useState({});\n  const [isUpdating, setIsUpdating] = useState(false);\n\n  const {\n    api: { currentUser: currentUserApiPath },\n  } = useConfig();\n\n  useEffect(() => {\n    if (!Object.keys(currentUser).length) {\n      getUser(currentUserApiPath).then(setCurrentUser);\n    }\n  }, [currentUserApiPath, currentUser]);\n\n  const toggleWebStoriesTrackingOptIn = useCallback(async () => {\n    setIsUpdating(true);\n    try {\n      setCurrentUser(\n        await toggleWebStoriesTrackingOptInCallback(\n          currentUserApiPath,\n          currentUser\n        )\n      );\n    } finally {\n      setIsUpdating(false);\n    }\n  }, [currentUserApiPath, currentUser]);\n\n  const toggleWebStoriesMediaOptimization = useCallback(async () => {\n    setIsUpdating(true);\n    try {\n      setCurrentUser(\n        await toggleWebStoriesMediaOptimizationCallback(\n          currentUserApiPath,\n          currentUser\n        )\n      );\n    } finally {\n      setIsUpdating(false);\n    }\n  }, [currentUserApiPath, currentUser]);\n\n  return {\n    api: {\n      toggleWebStoriesTrackingOptIn,\n      toggleWebStoriesMediaOptimization,\n    },\n    currentUser: {\n      data: currentUser,\n      isUpdating,\n    },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './story';\nexport * from './authors';\nexport * from './taxonomies';\nexport * from './shopping';\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/media.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * Upload media\n * Used on settings page for upload button.\n *\n * @param {string} apiPath API path.\n * @param {Object} files Uploaded files.\n * @return {Promise} Request promise.\n */\nexport function uploadMedia(apiPath, files) {\n  return Promise.all(\n    Object.values(files).map((file) => {\n      const data = new window.FormData();\n\n      data.append('file', file, file.name || file.type.replace('/', '.'));\n\n      return apiFetch({\n        path: apiPath,\n        body: data,\n        method: 'POST',\n      }).then(snakeToCamelCaseObjectKeys);\n    })\n  );\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/pages.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { SEARCH_PAGES_FIELDS, GET_PAGE_FIELDS } from './constants';\n\n/**\n * Search pages by search term.\n * Used for \"Stories Archive\" custom page selection on settings page.\n *\n * @param {string} apiPath API path.\n * @param {string} searchTerm Search term.\n * @return {Promise} Request promise.\n */\nexport function searchPages(apiPath, searchTerm) {\n  const path = addQueryArgs(apiPath, {\n    per_page: 100,\n    search: searchTerm,\n    _fields: SEARCH_PAGES_FIELDS,\n  });\n\n  return apiFetch({ path });\n}\n\n/**\n * Get page by id.\n * Used for getting the custom page by id after selection is saved on settings page\n *\n * @param {string} apiPath API path.\n * @param {number} id page id.\n * @return {Promise} Request promise.\n */\nexport function getPageById(apiPath, id) {\n  const path = addQueryArgs(`${apiPath}${id}/`, {\n    _fields: GET_PAGE_FIELDS,\n  });\n\n  return apiFetch({ path });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/publisherLogo.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * Fetch publisher logos.\n * Used for \"Publisher Logo\" field under editor settings page\n *\n * @param {string} apiPath API path.\n * @return {Promise} Request promise.\n */\nexport function fetchPublisherLogos(apiPath) {\n  return apiFetch({ path: apiPath });\n}\n\n/**\n * Remove publisher logo.\n *\n * @param {string} apiPath API path.\n * @param {number|string} logoId Logo id.\n * @return {Promise} Request promise.\n */\nexport function removePublisherLogo(apiPath, logoId) {\n  const path = addQueryArgs(`${apiPath}${logoId}/`, {\n    _method: 'DELETE',\n  });\n\n  return apiFetch({\n    path,\n    method: 'POST',\n  });\n}\n\n/**\n * Add publisher logo.\n *\n * @param {string} apiPath API path.\n * @param {number|Array<number>} logoId Single logo ID or array of logo IDs.\n * @return {Promise} Request promise.\n */\nexport function addPublisherLogo(apiPath, logoId) {\n  return apiFetch({\n    path: apiPath,\n    data: {\n      id: logoId,\n    },\n    method: 'POST',\n  });\n}\n\n/**\n * Set publisher logo as default.\n *\n * @param {string} apiPath API path.\n * @param {number|string} logoId Logo id.\n * @return {Promise} Request promise.\n */\nexport function setPublisherLogoAsDefault(apiPath, logoId) {\n  return apiFetch({\n    path: `${apiPath}${logoId}/`,\n    data: {\n      active: true,\n    },\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/media.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ACTION_TYPES = {\n  LOADING_MEDIA: 'loading_media',\n  ADD_MEDIA_SUCCESS: 'add_media_success',\n  ADD_MEDIA_FAILURE: 'add_media_failure',\n};\n\nexport const defaultMediaState = {\n  error: {},\n  isLoading: false,\n  newlyCreatedMediaIds: [],\n};\n\nfunction mediaReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.LOADING_MEDIA: {\n      return {\n        ...state,\n        isLoading: true,\n        newlyCreatedMediaIds: [],\n      };\n    }\n\n    case ACTION_TYPES.ADD_MEDIA_FAILURE: {\n      return {\n        ...state,\n        error: { ...action.payload, id: Date.now() },\n        isLoading: false,\n      };\n    }\n\n    case ACTION_TYPES.ADD_MEDIA_SUCCESS: {\n      return {\n        ...state,\n        error: {},\n        isLoading: false,\n        newlyCreatedMediaIds:\n          action.payload.newlyCreatedMediaIds || state.newlyCreatedMediaIds,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default mediaReducer;\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/publisherLogos.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ACTION_TYPES = {\n  LOADING: 'loading',\n  UPDATE_FAILURE: 'update_failure',\n  UPDATE_SUCCESS: 'update_success',\n  FETCH_FAILURE: 'fetch_failure',\n  FETCH_SUCCESS: 'fetch_success',\n  REMOVE_FAILURE: 'remove_failure',\n  REMOVE_SUCCESS: 'remove_success',\n  ADD_FAILURE: 'add_failure',\n  ADD_SUCCESS: 'add_success',\n};\n\nexport const defaultPublisherLogosState = {\n  error: {},\n  isLoading: false,\n  publisherLogos: [],\n  settingSaved: false,\n};\n\nfunction publisherLogoReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.LOADING: {\n      return {\n        ...state,\n        isLoading: true,\n        settingSaved: false,\n      };\n    }\n\n    case ACTION_TYPES.ADD_FAILURE:\n    case ACTION_TYPES.UPDATE_FAILURE:\n    case ACTION_TYPES.REMOVE_FAILURE:\n    case ACTION_TYPES.FETCH_FAILURE: {\n      return {\n        ...state,\n        error: { ...action.payload, id: Date.now() },\n        isLoading: false,\n        settingSaved: false,\n      };\n    }\n\n    case ACTION_TYPES.FETCH_SUCCESS: {\n      return {\n        ...state,\n        error: {},\n        isLoading: false,\n        publisherLogos: [...action.payload.publisherLogos],\n      };\n    }\n\n    case ACTION_TYPES.ADD_SUCCESS: {\n      const newPublisherLogos = [\n        ...state.publisherLogos,\n        action.payload.publisherLogo,\n      ];\n\n      return {\n        ...state,\n        error: {},\n        isLoading: false,\n        settingSaved: true,\n        publisherLogos: newPublisherLogos,\n      };\n    }\n\n    case ACTION_TYPES.UPDATE_SUCCESS: {\n      const newPublisherLogos = [...state.publisherLogos].map(\n        (publisherLogo) => {\n          publisherLogo.active =\n            publisherLogo.id === action.payload.publisherLogo.id;\n          return publisherLogo;\n        }\n      );\n\n      return {\n        ...state,\n        error: {},\n        isLoading: false,\n        settingSaved: true,\n        publisherLogos: newPublisherLogos,\n      };\n    }\n\n    case ACTION_TYPES.REMOVE_SUCCESS: {\n      const wasDefault = state.publisherLogos.some(\n        ({ id, active }) => id === action.payload.id && active\n      );\n\n      const newPublisherLogos = [...state.publisherLogos]\n        .filter(({ id }) => id !== action.payload.id)\n        .map((publisherLogo, index) => {\n          publisherLogo.active = wasDefault\n            ? 0 === index\n            : publisherLogo.active;\n          return publisherLogo;\n        });\n\n      return {\n        ...state,\n        error: {},\n        isLoading: false,\n        settingSaved: true,\n        publisherLogos: newPublisherLogos,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default publisherLogoReducer;\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/settings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  AD_NETWORK_TYPE,\n  ARCHIVE_TYPE,\n  SHOPPING_PROVIDER_TYPE,\n  GOOGLE_ANALYTICS_HANDLER_TYPE,\n} from '../../constants';\n\nexport const ACTION_TYPES = {\n  UPDATE_SETTINGS_SUCCESS: 'update_settings_success',\n  UPDATE_SETTINGS_FAILURE: 'update_settings_failure',\n  SETTING_SAVED: 'setting_saved',\n  FETCH_SETTINGS_SUCCESS: 'fetch_settings_success',\n  FETCH_SETTINGS_FAILURE: 'fetch_settings_failure',\n};\n\nexport const defaultSettingsState = {\n  error: {},\n  googleAnalyticsId: '',\n  usingLegacyAnalytics: false,\n  adSensePublisherId: '',\n  adSenseSlotId: '',\n  adManagerSlotId: '',\n  mgidWidgetId: '',\n  adNetwork: AD_NETWORK_TYPE.NONE,\n  archive: ARCHIVE_TYPE.DEFAULT,\n  archivePageId: 0,\n  videoCache: false,\n  dataRemoval: false,\n  settingSaved: false,\n  shoppingProvider: SHOPPING_PROVIDER_TYPE.NONE,\n  shopifyHost: '',\n  shopifyAccessToken: '',\n  autoAdvance: true,\n  defaultPageDuration: 7,\n  googleAnalyticsHandler: GOOGLE_ANALYTICS_HANDLER_TYPE.SITE_KIT,\n};\n\nfunction settingsReducer(state, action) {\n  switch (action.type) {\n    case ACTION_TYPES.SETTING_SAVED: {\n      return {\n        ...state,\n        settingSaved: action.payload,\n      };\n    }\n\n    case ACTION_TYPES.UPDATE_SETTINGS_FAILURE:\n    case ACTION_TYPES.FETCH_SETTINGS_FAILURE: {\n      return {\n        ...state,\n        error: { ...action.payload, id: Date.now() },\n      };\n    }\n\n    case ACTION_TYPES.FETCH_SETTINGS_SUCCESS:\n    case ACTION_TYPES.UPDATE_SETTINGS_SUCCESS: {\n      return {\n        ...state,\n        error: {},\n        googleAnalyticsId: action.payload.googleAnalyticsId,\n        usingLegacyAnalytics: action.payload.usingLegacyAnalytics,\n        adSensePublisherId: action.payload.adSensePublisherId,\n        adSenseSlotId: action.payload.adSenseSlotId,\n        adManagerSlotId: action.payload.adManagerSlotId,\n        mgidWidgetId: action.payload.mgidWidgetId,\n        adNetwork: action.payload.adNetwork,\n        videoCache: action.payload.videoCache,\n        dataRemoval: action.payload.dataRemoval,\n        archive: action.payload.archive,\n        archivePageId: action.payload.archivePageId,\n        shoppingProvider: action.payload.shoppingProvider,\n        shopifyHost: action.payload.shopifyHost,\n        shopifyAccessToken: action.payload.shopifyAccessToken,\n        autoAdvance: action.payload.autoAdvance,\n        defaultPageDuration: action.payload.defaultPageDuration,\n        googleAnalyticsHandler: action.payload.googleAnalyticsHandler,\n      };\n    }\n\n    default:\n      return state;\n  }\n}\n\nexport default settingsReducer;\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/test/media.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ERRORS } from '../../../constants';\nimport mediaReducer, { ACTION_TYPES } from '../media';\n\ndescribe('mediaReducer', () => {\n  const initialState = {\n    error: {},\n    isLoading: false,\n    newlyCreatedMediaIds: [],\n  };\n\n  const MOCK_ERROR_ID = Date.now();\n\n  beforeAll(() => {\n    jest.spyOn(Date, 'now').mockImplementation(() => MOCK_ERROR_ID);\n  });\n\n  it(`should update media state of isLoading and reset newlyCreatedMediaIds to an empty array when ${ACTION_TYPES.LOADING_MEDIA} is called`, () => {\n    const result = mediaReducer(\n      { ...initialState, newlyCreatedMediaIds: [9, 8] },\n      {\n        type: ACTION_TYPES.LOADING_MEDIA,\n      }\n    );\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: true,\n      newlyCreatedMediaIds: [],\n    });\n  });\n\n  it(`should update media state of error when ${ACTION_TYPES.ADD_MEDIA_FAILURE} is called`, () => {\n    const result = mediaReducer(initialState, {\n      type: ACTION_TYPES.ADD_MEDIA_FAILURE,\n      payload: {\n        message: ERRORS.UPLOAD_PUBLISHER_LOGO.MESSAGE,\n        code: 'my_error_code',\n      },\n    });\n\n    expect(result).toMatchObject({\n      error: {\n        message: ERRORS.UPLOAD_PUBLISHER_LOGO.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n      isLoading: false,\n      newlyCreatedMediaIds: [],\n    });\n  });\n\n  it(`should update media state of newlyCreatedMediaIds and mediaById when ${ACTION_TYPES.ADD_MEDIA_SUCCESS} is called`, () => {\n    const result = mediaReducer(initialState, {\n      type: ACTION_TYPES.ADD_MEDIA_SUCCESS,\n      payload: {\n        newlyCreatedMediaIds: [1, 2],\n      },\n    });\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: false,\n      newlyCreatedMediaIds: [1, 2],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/test/publisherLogos.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ERRORS } from '../../../constants';\nimport publisherLogoReducer, { ACTION_TYPES } from '../publisherLogos';\n\ndescribe('publisherLogoReducer', () => {\n  const initialState = {\n    error: {},\n    isLoading: false,\n    publisherLogos: [],\n    settingSaved: false,\n  };\n\n  const MOCK_ERROR_ID = Date.now();\n\n  beforeAll(() => {\n    jest.spyOn(Date, 'now').mockImplementation(() => MOCK_ERROR_ID);\n  });\n\n  it(`should update isLoading state when ${ACTION_TYPES.LOADING} is called`, () => {\n    const result = publisherLogoReducer(\n      { ...initialState },\n      {\n        type: ACTION_TYPES.LOADING,\n      }\n    );\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: true,\n    });\n  });\n\n  it(`should update error state when ${ACTION_TYPES.ADD_FAILURE} is called`, () => {\n    const result = publisherLogoReducer(initialState, {\n      type: ACTION_TYPES.ADD_FAILURE,\n      payload: {\n        message: ERRORS.UPLOAD_PUBLISHER_LOGO.MESSAGE,\n        code: 'my_error_code',\n      },\n    });\n\n    expect(result).toMatchObject({\n      error: {\n        message: ERRORS.UPLOAD_PUBLISHER_LOGO.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n      isLoading: false,\n    });\n  });\n\n  it(`should update publisherLogos state when ${ACTION_TYPES.FETCH_SUCCESS} is called`, () => {\n    const result = publisherLogoReducer(initialState, {\n      type: ACTION_TYPES.FETCH_SUCCESS,\n      payload: {\n        publisherLogos: [\n          {\n            id: 123,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: true,\n          },\n          {\n            id: 456,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: false,\n          },\n        ],\n      },\n    });\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: false,\n      publisherLogos: [\n        {\n          id: 123,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: true,\n        },\n        {\n          id: 456,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: false,\n        },\n      ],\n    });\n  });\n\n  it(`should update publisherLogos state when ${ACTION_TYPES.ADD_SUCCESS} is called`, () => {\n    const result = publisherLogoReducer(\n      {\n        ...initialState,\n        publisherLogos: [\n          {\n            id: 123,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: true,\n          },\n        ],\n      },\n      {\n        type: ACTION_TYPES.ADD_SUCCESS,\n        payload: {\n          publisherLogo: {\n            id: 456,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: false,\n          },\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: false,\n      publisherLogos: [\n        {\n          id: 123,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: true,\n        },\n        {\n          id: 456,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: false,\n        },\n      ],\n    });\n  });\n\n  it(`should update publisherLogos state when ${ACTION_TYPES.UPDATE_SUCCESS} is called`, () => {\n    const result = publisherLogoReducer(\n      {\n        ...initialState,\n        publisherLogos: [\n          {\n            id: 123,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: true,\n          },\n          {\n            id: 456,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: false,\n          },\n        ],\n      },\n      {\n        type: ACTION_TYPES.UPDATE_SUCCESS,\n        payload: {\n          publisherLogo: {\n            id: 456,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: true,\n          },\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: false,\n      publisherLogos: [\n        {\n          id: 123,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: false,\n        },\n        {\n          id: 456,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: true,\n        },\n      ],\n    });\n  });\n\n  it(`should update publisherLogos state when ${ACTION_TYPES.REMOVE_SUCCESS} is called`, () => {\n    const result = publisherLogoReducer(\n      {\n        ...initialState,\n        publisherLogos: [\n          {\n            id: 123,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: true,\n          },\n          {\n            id: 456,\n            url: 'https://example.com',\n            title: 'Logo A',\n            active: false,\n          },\n        ],\n      },\n      {\n        type: ACTION_TYPES.REMOVE_SUCCESS,\n        payload: {\n          id: 456,\n        },\n      }\n    );\n\n    expect(result).toMatchObject({\n      error: {},\n      isLoading: false,\n      publisherLogos: [\n        {\n          id: 123,\n          url: 'https://example.com',\n          title: 'Logo A',\n          active: true,\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/reducers/test/settings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { ERRORS } from '../../../constants';\nimport settingsReducer, {\n  ACTION_TYPES,\n  defaultSettingsState as initialState,\n} from '../settings';\n\ndescribe('settingsReducer', () => {\n  const MOCK_ERROR_ID = Date.now();\n\n  beforeAll(() => {\n    jest.spyOn(Date, 'now').mockImplementation(() => MOCK_ERROR_ID);\n  });\n\n  it(`should update settings state when ${ACTION_TYPES.FETCH_SETTINGS_SUCCESS} is called`, () => {\n    const result = settingsReducer(initialState, {\n      type: ACTION_TYPES.FETCH_SETTINGS_SUCCESS,\n      payload: {\n        googleAnalyticsId: 'fakeId12345',\n        usingLegacyAnalytics: false,\n      },\n    });\n    expect(result).toMatchObject({\n      error: {},\n      googleAnalyticsId: 'fakeId12345',\n      usingLegacyAnalytics: false,\n    });\n  });\n\n  it(`should update settings state when ${ACTION_TYPES.FETCH_SETTINGS_FAILURE} is called`, () => {\n    const result = settingsReducer(initialState, {\n      type: ACTION_TYPES.FETCH_SETTINGS_FAILURE,\n      payload: {\n        message: ERRORS.LOAD_SETTINGS.MESSAGE,\n        code: 'my_error_code',\n      },\n    });\n    expect(result).toMatchObject({\n      googleAnalyticsId: '',\n      usingLegacyAnalytics: false,\n      error: {\n        message: ERRORS.LOAD_SETTINGS.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update settings state when ${ACTION_TYPES.UPDATE_SETTINGS_FAILURE} is called`, () => {\n    const result = settingsReducer(initialState, {\n      type: ACTION_TYPES.UPDATE_SETTINGS_FAILURE,\n      payload: {\n        message: ERRORS.UPDATE_EDITOR_SETTINGS.MESSAGE,\n        code: 'my_error_code',\n      },\n    });\n    expect(result).toMatchObject({\n      googleAnalyticsId: '',\n      usingLegacyAnalytics: false,\n      error: {\n        message: ERRORS.UPDATE_EDITOR_SETTINGS.MESSAGE,\n        id: MOCK_ERROR_ID,\n        code: 'my_error_code',\n      },\n    });\n  });\n\n  it(`should update settings state when ${ACTION_TYPES.UPDATE_SETTINGS_SUCCESS} is called`, () => {\n    const result = settingsReducer(initialState, {\n      type: ACTION_TYPES.UPDATE_SETTINGS_SUCCESS,\n      payload: {\n        googleAnalyticsId: 'fakeId12345NEW',\n        usingLegacyAnalytics: false,\n      },\n    });\n    expect(result).toMatchObject({\n      error: {},\n      googleAnalyticsId: 'fakeId12345NEW',\n      usingLegacyAnalytics: false,\n    });\n  });\n\n  it(`should update settingSaved boolean when ${ACTION_TYPES.SETTING_SAVED} is called`, () => {\n    const result = settingsReducer(initialState, {\n      type: ACTION_TYPES.SETTING_SAVED,\n      payload: true,\n    });\n    expect(result).toMatchObject({\n      settingSaved: true,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/settings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Transform settings api response.\n *\n * @param {Object} response API response.\n * @return {Object} Transformed object.\n */\nconst transformSettingResponse = (response) => ({\n  googleAnalyticsId: response.web_stories_ga_tracking_id,\n  usingLegacyAnalytics: response.web_stories_using_legacy_analytics,\n  adSensePublisherId: response.web_stories_adsense_publisher_id,\n  adSenseSlotId: response.web_stories_adsense_slot_id,\n  adManagerSlotId: response.web_stories_ad_manager_slot_id,\n  mgidWidgetId: response.web_stories_mgid_widget_id,\n  adNetwork: response.web_stories_ad_network,\n  videoCache: response.web_stories_video_cache,\n  dataRemoval: response.web_stories_data_removal,\n  archive: response.web_stories_archive,\n  archivePageId: response.web_stories_archive_page_id,\n  shoppingProvider: response.web_stories_shopping_provider,\n  shopifyHost: response.web_stories_shopify_host,\n  shopifyAccessToken: response.web_stories_shopify_access_token,\n  autoAdvance: Boolean(response.web_stories_auto_advance),\n  defaultPageDuration: response.web_stories_default_page_duration,\n  googleAnalyticsHandler: response.web_stories_ga_tracking_handler,\n});\n\n/**\n * Fetch settings.\n * Used on settings page.\n *\n * @param {string} apiPath API path.\n * @return {Promise} Request promise.\n */\nexport function fetchSettings(apiPath) {\n  return apiFetch({\n    path: apiPath,\n  }).then(transformSettingResponse);\n}\n\n/**\n * Update settings.\n *\n * @param {string} apiPath API path.\n * @param {Object} settingsParams Settings to update.\n * @return {Promise} Request promise.\n */\nexport function updateSettings(apiPath, settingsParams) {\n  const {\n    googleAnalyticsId,\n    usingLegacyAnalytics,\n    adSensePublisherId,\n    adSenseSlotId,\n    adManagerSlotId,\n    mgidWidgetId,\n    adNetwork,\n    videoCache,\n    dataRemoval,\n    archive,\n    archivePageId,\n    shoppingProvider,\n    shopifyHost,\n    shopifyAccessToken,\n    autoAdvance,\n    defaultPageDuration,\n    googleAnalyticsHandler,\n  } = settingsParams;\n\n  const settings = {};\n\n  if (googleAnalyticsId !== undefined) {\n    settings.web_stories_ga_tracking_id = googleAnalyticsId;\n  }\n\n  if (usingLegacyAnalytics !== undefined) {\n    settings.web_stories_using_legacy_analytics = usingLegacyAnalytics;\n  }\n\n  if (adSensePublisherId !== undefined) {\n    settings.web_stories_adsense_publisher_id = adSensePublisherId;\n  }\n\n  if (adSenseSlotId !== undefined) {\n    settings.web_stories_adsense_slot_id = adSenseSlotId;\n  }\n\n  if (adManagerSlotId !== undefined) {\n    settings.web_stories_ad_manager_slot_id = adManagerSlotId;\n  }\n\n  if (mgidWidgetId !== undefined) {\n    settings.web_stories_mgid_widget_id = mgidWidgetId;\n  }\n\n  if (adNetwork !== undefined) {\n    settings.web_stories_ad_network = adNetwork;\n  }\n\n  if (videoCache !== undefined) {\n    settings.web_stories_video_cache = Boolean(videoCache);\n  }\n\n  if (dataRemoval !== undefined) {\n    settings.web_stories_data_removal = Boolean(dataRemoval);\n  }\n\n  if (archive !== undefined) {\n    settings.web_stories_archive = archive;\n  }\n\n  if (archivePageId !== undefined) {\n    settings.web_stories_archive_page_id = archivePageId;\n  }\n\n  if (shoppingProvider !== undefined) {\n    settings.web_stories_shopping_provider = shoppingProvider;\n  }\n\n  if (shopifyHost !== undefined) {\n    settings.web_stories_shopify_host = shopifyHost;\n  }\n\n  if (shopifyAccessToken !== undefined) {\n    settings.web_stories_shopify_access_token = shopifyAccessToken;\n  }\n\n  if (autoAdvance !== undefined) {\n    settings.web_stories_auto_advance = Boolean(autoAdvance);\n  }\n\n  if (defaultPageDuration !== undefined) {\n    settings.web_stories_default_page_duration = defaultPageDuration;\n  }\n\n  if (googleAnalyticsHandler !== undefined) {\n    settings.web_stories_ga_tracking_handler = googleAnalyticsHandler;\n  }\n\n  return apiFetch({\n    path: apiPath,\n    method: 'POST',\n    data: settings,\n  }).then(transformSettingResponse);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/shopping.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * Get products.\n *\n * @param {Object} config Configuration object.\n * @param {string} search Search term.\n * @return {Promise} Request promise.\n */\nexport function getProducts(config, search) {\n  return apiFetch({\n    path: addQueryArgs(config.api.products, {\n      per_page: 1,\n      search,\n    }),\n  });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/story.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport {\n  STORIES_PER_REQUEST,\n  DEFAULT_FILTERS,\n} from '@googleforcreators/dashboard';\nimport { createSolidFromString } from '@googleforcreators/patterns';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORY_FIELDS, STORY_EMBED } from './constants';\nimport { reshapeStoryObject } from './utils';\n\n/**\n * Fetch stories ( When dashboard link is clicked. )\n *\n * @param {Object} config Configuration object.\n * @param {Object} queryParams Query params.\n * @return {Promise} Request promise.\n */\nexport function fetchStories(config, queryParams) {\n  const {\n    page = 1,\n    perPage = STORIES_PER_REQUEST,\n    filters = {},\n    sort = {},\n  } = queryParams;\n\n  // Important: Keep in sync with REST API preloading definition.\n  const _defaultPreload = {\n    _embed: STORY_EMBED,\n    context: 'edit',\n    _web_stories_envelope: true,\n    _fields: STORY_FIELDS,\n    ...DEFAULT_FILTERS.filters,\n    ...DEFAULT_FILTERS.sort,\n  };\n\n  const query = {\n    ..._defaultPreload,\n    page,\n    per_page: perPage,\n    ...filters,\n    ...sort,\n  };\n\n  return apiFetch({\n    path: addQueryArgs(config.api.stories, query),\n  }).then(({ body: stories, headers }) => {\n    const totalPages = headers && Number.parseInt(headers['X-WP-TotalPages']);\n    const totalStoriesByStatus =\n      headers && JSON.parse(headers['X-WP-TotalByStatus']);\n\n    const fetchedStoryIds = [];\n    const reshapedStories = stories.reduce((acc, current) => {\n      if (!current) {\n        return acc;\n      }\n      fetchedStoryIds.push(current.id);\n      acc[current.id] = reshapeStoryObject(current);\n      return acc;\n    }, {});\n\n    return {\n      stories: reshapedStories,\n      fetchedStoryIds,\n      totalPages,\n      totalStoriesByStatus,\n    };\n  });\n}\n\n/**\n * Trash stories.\n *\n * @param {Object} config Configuration object.\n * @param {number|string} storyId Story Id.\n * @return {Promise} Request promise.\n */\nexport function trashStory(config, storyId) {\n  const path = addQueryArgs(`${config.api.stories}${storyId}`, {\n    _method: 'DELETE',\n  });\n\n  return apiFetch({\n    path,\n    method: 'POST',\n  });\n}\n\n/**\n * Update story.\n *\n * @param {Object} config Configuration object.\n * @param {Object} story Story object.\n * @return {Promise} Request promise.\n */\nexport function updateStory(config, story) {\n  const path = addQueryArgs(`${config.api.stories}${story.id}/`, {\n    _embed: STORY_EMBED,\n  });\n\n  const data = {\n    id: story.id,\n    author: story.author.id,\n    title: story.title?.raw || story.title,\n  };\n\n  return apiFetch({\n    path,\n    data,\n    method: 'POST',\n  }).then(reshapeStoryObject);\n}\n\n/**\n * Create story from template\n *\n * @param {Object} config Configuration object.\n * @param {Object} template Template object.\n * @return {Promise} Request promise.\n */\nexport const createStoryFromTemplate = (config, template) => {\n  const path = addQueryArgs(config.api.stories, {\n    _fields: 'edit_link',\n  });\n\n  const { pages, version, colors } = template;\n\n  const story = {\n    featuredMedia: {\n      id: 0,\n      url: '',\n    },\n    publisherLogo: {\n      url: '',\n    },\n    title: '',\n  };\n\n  const storyPropsToSave = {\n    pages,\n    featuredMedia: story.featuredMedia,\n    title: story.title,\n    status: 'auto-draft',\n    meta: {\n      web_stories_publisher_logo: story.publisherLogo.id,\n    },\n  };\n\n  const convertedColors = colors.map(({ color }) =>\n    createSolidFromString(color)\n  );\n\n  // If available, take the global values.\n  const { globalPageDuration = 7, globalAutoAdvance = true } = config;\n  const storyData = {\n    pages,\n    version,\n    autoAdvance: globalAutoAdvance,\n    defaultPageDuration: globalPageDuration,\n    currentStoryStyles: {\n      colors: convertedColors,\n    },\n  };\n\n  return apiFetch({\n    path,\n    data: {\n      ...storyPropsToSave,\n      story_data: storyData,\n    },\n    method: 'POST',\n  }).then(snakeToCamelCaseObjectKeys);\n};\n\n/**\n * Duplicate story.\n *\n * @param {Object} config Configuration object.\n * @param {Object} story Story object.\n * @return {Promise} Request promise.\n */\nexport function duplicateStory(config, story) {\n  const path = addQueryArgs(config.api.stories, {\n    _embed: STORY_EMBED,\n    _fields: STORY_FIELDS,\n  });\n\n  return apiFetch({\n    path,\n    data: {\n      original_id: story.id,\n      status: 'draft',\n    },\n    method: 'POST',\n  }).then(reshapeStoryObject);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/taxonomies.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * Get all taxonomies.\n *\n * @param {Object} config Configuration object.\n * @return {Promise} Taxonomies promise.\n */\n\nexport async function getTaxonomies(config, args = {}) {\n  const result = await apiFetch({\n    path: addQueryArgs(config.api.taxonomies, {\n      type: 'web-story',\n      context: 'edit',\n      ...args,\n    }),\n  });\n\n  return Object.values(result).map((taxonomy) => {\n    taxonomy.restPath = taxonomy['_links']?.['wp:items']?.[0]?.href;\n    delete taxonomy['_links'];\n\n    return snakeToCamelCaseObjectKeys(taxonomy, ['capabilities', 'visibility']);\n  });\n}\n\n/**\n * Get a taxonomy term.\n *\n * @param {Object} config configuration object.\n * @param {string} endpoint absolute url to interact with taxonomy\n * @param {Object} args Additional args.\n * @return {Promise} Term promise.\n */\nexport function getTaxonomyTerms(config, endpoint, args = {}) {\n  return apiFetch({\n    url: addQueryArgs(endpoint, args),\n  });\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/test/editorSettingsApi.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\nimport { ConfigProvider } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport { ERRORS } from '../../constants';\nimport {\n  useEditorSettings,\n  EditorSettingsProvider,\n} from '../../components/editorSettings';\n\njest.mock('../settings', () => ({\n  fetchSettings: () => Promise.reject(new Error()),\n  updateSettings: () => Promise.reject(new Error()),\n}));\n\njest.mock('../user', () => ({\n  getUser: () => {\n    return Promise.resolve({\n      id: 1,\n      name: 'dev',\n      url: 'https://www.story-link.com',\n      description: '',\n      link: 'https://www.story-link.com/author/dev/',\n      slug: 'dev',\n      avatar_urls: {},\n      meta: {\n        web_stories_tracking_optin: false,\n        web_stories_media_optimization: true,\n        web_stories_onboarding: {\n          safeZone: true,\n        },\n      },\n    });\n  },\n}));\n\ndescribe('useSettingsApi', () => {\n  it('should return an error when fetching settings API request fails', async () => {\n    const { result } = renderHook(() => useEditorSettings(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            api: { settings: 'wordpress' },\n          }}\n        >\n          <EditorSettingsProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.settingsApi.fetchSettings();\n    });\n\n    expect(result.current.state.settings.error.message).toStrictEqual(\n      ERRORS.LOAD_SETTINGS.MESSAGE\n    );\n  });\n\n  it('should return an error when updating settings API request fails', async () => {\n    const { result } = renderHook(() => useEditorSettings(), {\n      wrapper: (props) => (\n        <ConfigProvider\n          config={{\n            api: { settings: 'wordpress' },\n          }}\n        >\n          <EditorSettingsProvider {...props} />\n        </ConfigProvider>\n      ),\n    });\n\n    await act(async () => {\n      await result.current.actions.settingsApi.updateSettings('2738237892739');\n    });\n\n    expect(result.current.state.settings.error.message).toStrictEqual(\n      ERRORS.UPDATE_EDITOR_SETTINGS.MESSAGE\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/test/user.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport {\n  toggleWebStoriesTrackingOptIn,\n  toggleWebStoriesMediaOptimization,\n} from '../user';\n\njest.mock('@wordpress/api-fetch', () => ({\n  __esModule: true,\n  default: jest.fn(() => Promise.resolve({})),\n}));\n\ndescribe('User API Callbacks', () => {\n  const currentUserPath = '/web-stories/v1/users/me';\n\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  // Payload `__PAYLOAD_DATA__.meta.web_stories_tracking_optin` must be flipped value\n  it('toggleWebStoriesTrackingOptIn: validate request payload & path', () => {\n    const currentUser = {\n      meta: {\n        webStoriesMediaOptimization: false,\n      },\n    };\n    toggleWebStoriesTrackingOptIn(currentUserPath, currentUser);\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: currentUserPath,\n        data: {\n          meta: {\n            web_stories_tracking_optin: true,\n          },\n        },\n      })\n    );\n  });\n\n  // Payload `__PAYLOAD_DATA__.meta.webStoriesMediaOptimization` must be flipped value\n  it('toggleWebStoriesMediaOptimization: validate request payload & path', () => {\n    const currentUser = {\n      meta: {\n        webStoriesMediaOptimization: false,\n      },\n    };\n    toggleWebStoriesMediaOptimization(currentUserPath, currentUser);\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: currentUserPath,\n        data: {\n          meta: {\n            web_stories_media_optimization: true,\n          },\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/user.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * Get user.\n *\n * @param {string} apiPath API path.\n * @return {Promise} Request promise.\n */\nexport function getUser(apiPath) {\n  return apiFetch({\n    path: apiPath,\n  }).then(snakeToCamelCaseObjectKeys);\n}\n\n/**\n * Toggle web stories media optimization on settings page.\n *\n * @param {string} apiPath API path.\n * @param {Object} currentUser Current user.\n * @return {Promise} Request promise.\n */\nexport function toggleWebStoriesMediaOptimization(apiPath, currentUser) {\n  return apiFetch({\n    path: apiPath,\n    data: {\n      meta: {\n        web_stories_media_optimization:\n          !currentUser.meta.webStoriesMediaOptimization,\n      },\n    },\n    method: 'POST',\n  }).then(snakeToCamelCaseObjectKeys);\n}\n\n/**\n * Handles the toggle web stories tracking opt in on settings page.\n *\n * @param {string} apiPath API path.\n * @param {Object} currentUser Current user object.\n * @return {Promise} Request promise.\n */\nexport function toggleWebStoriesTrackingOptIn(apiPath, currentUser) {\n  return apiFetch({\n    path: apiPath,\n    data: {\n      meta: {\n        web_stories_tracking_optin: !currentUser.meta.webStoriesTrackingOptin,\n      },\n    },\n    method: 'POST',\n  }).then(snakeToCamelCaseObjectKeys);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as reshapeStoryObject } from './reshapeStoryObject';\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/utils/reshapeStoryObject.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { REST_LINKS } from '../constants';\n\nexport default function reshapeStoryObject(originalStoryData) {\n  const {\n    id,\n    title,\n    status,\n    date,\n    date_gmt,\n    modified,\n    modified_gmt,\n    link,\n    preview_link: previewLink,\n    edit_link: editStoryLink,\n    story_poster: storyPoster,\n    _embedded: { author, 'wp:lock': lock } = {},\n    _links: links = {},\n  } = originalStoryData;\n  if (!id) {\n    return null;\n  }\n\n  const { locked = false, user: lockUser = { id: 0, name: '' } } =\n    lock?.[0] || {};\n  const storyAuthor = author?.[0] || { id: 0, name: '' };\n  const capabilities = {\n    hasEditAction: Object.prototype.hasOwnProperty.call(links, REST_LINKS.EDIT),\n    hasDeleteAction: Object.prototype.hasOwnProperty.call(\n      links,\n      REST_LINKS.DELETE\n    ),\n  };\n\n  return {\n    id,\n    status,\n    title: title.raw,\n    created: date,\n    createdGmt: `${date_gmt}Z`,\n    modified,\n    modifiedGmt: `${modified_gmt}Z`,\n    author: {\n      id: storyAuthor.id,\n      name: storyAuthor.name,\n    },\n    locked,\n    lockUser: {\n      ...lockUser,\n      avatar: lockUser?.avatar?.['96'] || null,\n    },\n    bottomTargetAction: editStoryLink,\n    featuredMediaUrl: storyPoster?.url,\n    editStoryLink,\n    previewLink,\n    link,\n    capabilities,\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/api/utils/test/reshapeStoryObject.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { REST_LINKS } from '../../constants';\nimport reshapeStoryObject from '../reshapeStoryObject';\n\ndescribe('reshapeStoryObject', () => {\n  it('should return object', () => {\n    const responseObj = {\n      id: 27,\n      date: '2020-03-26T20:57:24',\n      guid: {\n        rendered: 'http://localhost:8899/?post_type=web-story&#038;p=27',\n      },\n      modified: '2020-03-26T21:42:14',\n      slug: '',\n      status: 'draft',\n      type: 'web-story',\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      title: { raw: 'Carlos Draft' },\n      excerpt: { rendered: '', protected: false },\n      author: 1,\n      featured_media: 33,\n      preview_link: 'http://localhost:8899/preview/27',\n      edit_link: 'http://localhost:8899/edit/27',\n      template: '',\n      categories: [],\n      tags: [],\n      story_poster: {\n        id: 33,\n        url: 'http://localhost:8899/wp-content/uploads/poster.jpg',\n        width: 640,\n        height: 853,\n        needsProxy: false,\n      },\n      _embedded: {\n        author: [{ id: 1, name: 'admin' }],\n        'wp:lock': [\n          {\n            locked: true,\n            time: '1628506372',\n            user: {\n              id: 1,\n              name: 'admin',\n              avatar: {\n                24: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=24&d=mm&r=g',\n                48: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=48&d=mm&r=g',\n                96: 'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=96&d=mm&r=g',\n              },\n            },\n          },\n        ],\n      },\n    };\n\n    const reshapedObj = reshapeStoryObject(responseObj);\n    expect(reshapedObj).toMatchObject({\n      author: {\n        name: 'admin',\n        id: 1,\n      },\n      bottomTargetAction: 'http://localhost:8899/edit/27',\n      created: '2020-03-26T20:57:24',\n      createdGmt: 'undefinedZ',\n      editStoryLink: 'http://localhost:8899/edit/27',\n      featuredMediaUrl: 'http://localhost:8899/wp-content/uploads/poster.jpg',\n      id: 27,\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      lockUser: {\n        avatar:\n          'http://2.gravatar.com/avatar/b642b4217b34b1e8d3bd915fc65c4452?s=96&d=mm&r=g',\n        id: 1,\n        name: 'admin',\n      },\n      locked: true,\n      modified: '2020-03-26T21:42:14',\n      modifiedGmt: 'undefinedZ',\n      previewLink: 'http://localhost:8899/preview/27',\n      status: 'draft',\n      title: 'Carlos Draft',\n    });\n  });\n\n  it('should return object without avatar', () => {\n    const responseObj = {\n      id: 27,\n      date: '2020-03-26T20:57:24',\n      guid: {\n        rendered: 'http://localhost:8899/?post_type=web-story&#038;p=27',\n      },\n      modified: '2020-03-26T21:42:14',\n      slug: '',\n      status: 'draft',\n      type: 'web-story',\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      title: { raw: 'Carlos Draft' },\n      excerpt: { rendered: '', protected: false },\n      author: 1,\n      featured_media: 0,\n      preview_link: 'http://localhost:8899/preview/27',\n      edit_link: 'http://localhost:8899/edit/27',\n      template: '',\n      categories: [],\n      tags: [],\n      story_poster: {\n        id: 33,\n        url: 'http://localhost:8899/wp-content/uploads/poster.jpg',\n        width: 640,\n        height: 853,\n        needsProxy: false,\n      },\n      _embedded: {\n        author: [{ id: 1, name: 'admin' }],\n        'wp:lock': [\n          {\n            locked: true,\n            time: '1628506372',\n            user: {\n              id: 1,\n              name: 'admin',\n            },\n          },\n        ],\n      },\n    };\n\n    const reshapedObj = reshapeStoryObject(responseObj);\n    expect(reshapedObj).toMatchObject({\n      author: {\n        name: 'admin',\n        id: 1,\n      },\n      bottomTargetAction: 'http://localhost:8899/edit/27',\n      created: '2020-03-26T20:57:24',\n      createdGmt: 'undefinedZ',\n      editStoryLink: 'http://localhost:8899/edit/27',\n      featuredMediaUrl: 'http://localhost:8899/wp-content/uploads/poster.jpg',\n      id: 27,\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      lockUser: {\n        avatar: null,\n        id: 1,\n        name: 'admin',\n      },\n      locked: true,\n      modified: '2020-03-26T21:42:14',\n      modifiedGmt: 'undefinedZ',\n      previewLink: 'http://localhost:8899/preview/27',\n      status: 'draft',\n      title: 'Carlos Draft',\n    });\n  });\n\n  it('should return null if the ID is missing', () => {\n    const responseObj = {\n      date: '2020-03-26T20:57:24',\n      guid: {\n        rendered: 'http://localhost:8899/?post_type=web-story&#038;p=27',\n      },\n      modified: '2020-03-26T21:42:14',\n      slug: '',\n      status: 'draft',\n      type: 'web-story',\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      title: { raw: 'Carlos Draft' },\n      excerpt: { rendered: '', protected: false },\n      author: 1,\n      featured_media: 0,\n      template: '',\n      categories: [],\n      tags: [],\n      meta: {\n        web_stories_poster: {},\n      },\n      _embedded: {\n        'wp:featuredmedia': [{ id: 0, source_url: '' }],\n        author: [{ id: 1, name: 'admin' }],\n      },\n    };\n\n    const reshapedObj = reshapeStoryObject(responseObj);\n    expect(reshapedObj).toBeNull();\n  });\n\n  it('should return capabilities', () => {\n    const responseObj = {\n      id: 27,\n      date: '2020-03-26T20:57:24',\n      guid: {\n        rendered: 'http://localhost:8899/?post_type=web-story&#038;p=27',\n      },\n      modified: '2020-03-26T21:42:14',\n      slug: '',\n      status: 'draft',\n      type: 'web-story',\n      link: 'http://localhost:8899/?post_type=web-story&p=27',\n      title: { raw: 'Carlos Draft' },\n      excerpt: { rendered: '', protected: false },\n      author: 1,\n      featured_media: 0,\n      template: '',\n      categories: [],\n      tags: [],\n      meta: {\n        web_stories_poster: {},\n      },\n      _embedded: {\n        'wp:featuredmedia': [{ id: 0, source_url: '' }],\n        author: [{ id: 1, name: 'admin' }],\n      },\n      _links: {\n        [REST_LINKS.EDIT]: [\n          {\n            href: 'http://localhost:8899/wp-json/web-stories/v1/web-story/163',\n          },\n        ],\n        [REST_LINKS.DELETE]: [\n          {\n            href: 'http://localhost:8899/wp-json/web-stories/v1/web-story/163',\n          },\n        ],\n      },\n    };\n\n    const reshapedObj = reshapeStoryObject(responseObj);\n    expect(reshapedObj.capabilities.hasDeleteAction).toBeTrue();\n    expect(reshapedObj.capabilities.hasEditAction).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/adNetwork/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useEffect,\n  useCallback,\n  useMemo,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, _x, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { TextSize, DropDown } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { InlineLink, TextInputHelperText } from '../../components';\nimport { AD_NETWORK_TYPE } from '../../../../constants';\n\nexport const TEXT = {\n  SLOT_ID_LABEL: __('Monetization type', 'web-stories'),\n\n  HELPER_MESSAGE_ADSENSE: __(\n    'Learn more about <a>how to monetize your Web Stories</a> using AdSense. Once configured, AdSense will determine where and how to insert ads into the story. Consult <help>AdSense Help</help> for any further assistance.',\n    'web-stories'\n  ),\n  HELPER_MESSAGE_ADMANAGER: __(\n    'Learn how to <a>enable programmatic demand in Web Stories</a> through Ad Manager.',\n    'web-stories'\n  ),\n  HELPER_MESSAGE_MGID: __(\n    'Learn how to start <a>monetizing Web Stories with MGID Native Solution</a>',\n    'web-stories'\n  ),\n  HELPER_LINK_ADSENSE: __(\n    'https://support.google.com/adsense/answer/10175505',\n    'web-stories'\n  ),\n  HELPER_LINK_ADSENSE_HELP: __(\n    'https://support.google.com/adsense/',\n    'web-stories'\n  ),\n  HELPER_LINK_ADMANAGER: __(\n    'https://support.google.com/admanager/answer/9416436',\n    'web-stories'\n  ),\n  HELPER_LINK_MGID: __(\n    'https://help.mgid.com/generate-revenue-with-amp-web-stories?utm_source=wp-plugin&utm_medium=web-stories-by-google',\n    'web-stories'\n  ),\n};\n\nconst OPTIONS = [\n  {\n    label: _x('None', 'ad network', 'web-stories'),\n    value: AD_NETWORK_TYPE.NONE,\n  },\n  {\n    label: __('Google AdSense', 'web-stories'),\n    value: AD_NETWORK_TYPE.ADSENSE,\n  },\n  {\n    label: __('Google Ad Manager', 'web-stories'),\n    value: AD_NETWORK_TYPE.ADMANAGER,\n  },\n  {\n    label: __('MGID', 'web-stories'),\n    value: AD_NETWORK_TYPE.MGID,\n  },\n];\n\nfunction AdNetworkSettings({ adNetwork: adNetworkRaw, handleUpdate }) {\n  const [adNetwork, setAdNetwork] = useState(adNetworkRaw);\n\n  useEffect(() => setAdNetwork(adNetworkRaw), [adNetworkRaw]);\n\n  const message = useMemo(() => {\n    if (AD_NETWORK_TYPE.ADMANAGER === adNetwork) {\n      return TEXT.HELPER_MESSAGE_ADMANAGER;\n    }\n\n    if (AD_NETWORK_TYPE.ADSENSE === adNetwork) {\n      return TEXT.HELPER_MESSAGE_ADSENSE;\n    }\n\n    if (AD_NETWORK_TYPE.MGID === adNetwork) {\n      return TEXT.HELPER_MESSAGE_MGID;\n    }\n\n    return null;\n  }, [adNetwork]);\n\n  const link = useMemo(() => {\n    if (AD_NETWORK_TYPE.ADMANAGER === adNetwork) {\n      return TEXT.HELPER_LINK_ADMANAGER;\n    }\n\n    if (AD_NETWORK_TYPE.ADSENSE === adNetwork) {\n      return TEXT.HELPER_LINK_ADSENSE;\n    }\n\n    if (AD_NETWORK_TYPE.MGID === adNetwork) {\n      return TEXT.HELPER_LINK_MGID;\n    }\n\n    return null;\n  }, [adNetwork]);\n\n  const handleMonetizationClick = useCallback(\n    (evt) => trackClick(evt, 'click_monetization_docs'),\n    []\n  );\n\n  return (\n    <>\n      <DropDown\n        ariaLabel={TEXT.SLOT_ID_LABEL}\n        options={OPTIONS}\n        selectedValue={adNetwork}\n        onMenuItemClick={(_, newAdNetwork) => handleUpdate(newAdNetwork)}\n        fillWidth\n      />\n\n      {message && (\n        <TextInputHelperText size={TextSize.Small}>\n          <TranslateWithMarkup\n            mapping={{\n              a: (\n                <InlineLink\n                  href={link}\n                  rel=\"noreferrer\"\n                  target=\"_blank\"\n                  onClick={handleMonetizationClick}\n                  size={TextSize.Small}\n                />\n              ),\n              help: (\n                <InlineLink\n                  href={TEXT.HELPER_LINK_ADSENSE_HELP}\n                  rel=\"noreferrer\"\n                  target=\"_blank\"\n                  size={TextSize.Small}\n                />\n              ),\n            }}\n          >\n            {message}\n          </TranslateWithMarkup>\n        </TextInputHelperText>\n      )}\n    </>\n  );\n}\nAdNetworkSettings.propTypes = {\n  handleUpdate: PropTypes.func,\n  adNetwork: PropTypes.oneOf(Object.values(AD_NETWORK_TYPE)),\n};\n\nexport default AdNetworkSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/adNetwork/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport AdNetwork from '..';\nimport { AD_NETWORK_TYPE } from '../../../../../constants';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/AdManagement/AdNetwork',\n  component: AdNetwork,\n  args: {\n    adNetwork: AD_NETWORK_TYPE.NONE,\n  },\n  argTypes: {\n    adNetwork: {\n      options: Object.values(AD_NETWORK_TYPE),\n      control: 'select',\n    },\n    handleUpdate: { action: 'update ad network' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <AdNetwork {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/adNetwork/test/adNetwork.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport AdNetworkSettings from '..';\nimport { AD_NETWORK_TYPE } from '../../../../../constants';\nimport { renderWithProviders } from '../../../../../testUtils';\n\ndescribe('Editor Settings: Ad network settings <AdNetworkSettings />', () => {\n  let adNetwork;\n  let mockUpdate;\n\n  beforeEach(() => {\n    adNetwork = AD_NETWORK_TYPE.NONE;\n    mockUpdate = jest.fn((id) => {\n      adNetwork = id;\n    });\n  });\n\n  afterEach(() => {\n    adNetwork = AD_NETWORK_TYPE.NONE;\n  });\n\n  it('should render ad network settings dropdown button', () => {\n    renderWithProviders(\n      <AdNetworkSettings adNetwork={adNetwork} handleUpdate={mockUpdate} />\n    );\n\n    const networkDropdown = screen.getByRole('button');\n    expect(networkDropdown).toHaveTextContent('None');\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdManager/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  ButtonSize,\n  ButtonType,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { validateAdManagerSlotIdFormat } from '../../utils';\nimport {\n  InlineForm,\n  SaveButton,\n  SettingsTextInput,\n  TextInputHelperText,\n  VisuallyHiddenLabel,\n} from '../../components';\n\nexport const TEXT = {\n  SLOT_ID_CONTEXT: sprintf(\n    /* translators: %s: example value. */\n    __('Example: %s', 'web-stories'),\n    '/123456789/a4a/amp_story_dfp_example'\n  ),\n  SLOT_ID_PLACEHOLDER: __('Enter your Slot ID', 'web-stories'),\n  SLOT_ID_LABEL: __('Google Ad Manager Slot ID', 'web-stories'),\n  INPUT_ERROR: __('Invalid ID format', 'web-stories'),\n  SUBMIT_BUTTON: __('Save', 'web-stories'),\n};\n\nfunction GoogleAdManagerSettings({ slotId: adManagerSlotId, handleUpdate }) {\n  const [slotId, setSlotId] = useState(adManagerSlotId);\n  const [slotIdInputError, setSlotIdInputError] = useState('');\n  const canSaveSlotId = slotId !== adManagerSlotId && !slotIdInputError;\n  const disableSlotIdSaveButton = !canSaveSlotId;\n\n  useEffect(() => {\n    setSlotId(adManagerSlotId);\n  }, [adManagerSlotId]);\n\n  const onUpdateSlotId = useCallback((event) => {\n    const { value } = event.target;\n    setSlotId(value);\n\n    if (value.length === 0 || validateAdManagerSlotIdFormat(value)) {\n      setSlotIdInputError('');\n\n      return;\n    }\n\n    setSlotIdInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onSaveSlotId = useCallback(() => {\n    if (canSaveSlotId) {\n      handleUpdate(slotId);\n    }\n  }, [canSaveSlotId, slotId, handleUpdate]);\n\n  const onKeyDownSlotId = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSaveSlotId();\n      }\n    },\n    [onSaveSlotId]\n  );\n\n  return (\n    <>\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"adManagerSlotId\">\n          {TEXT.SLOT_ID_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          id=\"adManagerSlotId\"\n          aria-label={TEXT.SLOT_ID_LABEL}\n          value={slotId}\n          onChange={onUpdateSlotId}\n          onKeyDown={onKeyDownSlotId}\n          placeholder={TEXT.SLOT_ID_PLACEHOLDER}\n          hasError={Boolean(slotIdInputError)}\n          hint={slotIdInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disableSlotIdSaveButton}\n          onClick={onSaveSlotId}\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        {TEXT.SLOT_ID_CONTEXT}\n      </TextInputHelperText>\n    </>\n  );\n}\nGoogleAdManagerSettings.propTypes = {\n  handleUpdate: PropTypes.func,\n  slotId: PropTypes.string,\n};\n\nexport default GoogleAdManagerSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdManager/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport GoogleAdManager from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/AdManagement/GoogleAdManager',\n  component: GoogleAdManager,\n  args: {\n    slotId: '',\n  },\n  argTypes: {\n    handleUpdate: { action: 'update google ad manager' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <GoogleAdManager {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdManager/test/googleAdManager.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport GoogleAdManagerSettings, { TEXT } from '..';\nimport { renderWithProviders } from '../../../../../testUtils';\n\ndescribe('Editor Settings: Google Analytics <GoogleAdManager />', () => {\n  let adManagerSlotId;\n  let mockUpdate;\n\n  beforeEach(() => {\n    adManagerSlotId = '';\n    mockUpdate = jest.fn((id) => {\n      adManagerSlotId = id;\n    });\n  });\n\n  afterEach(() => {\n    adManagerSlotId = '';\n  });\n\n  it('should render a visually hidden label for Google Ad Manager input', () => {\n    renderWithProviders(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    const label = screen.getByLabelText(TEXT.SLOT_ID_LABEL);\n    expect(label).toBeInTheDocument();\n  });\n\n  it('should call mockUpdate when enter is keyed on input', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n\n    fireEvent.change(input, {\n      target: { value: '/123456789/a4a/amp_story_dfp_example' },\n    });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated adManagerSlotId prop\n    rerender(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated adManagerSlotId prop\n    rerender(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdate when the save button is clicked', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    const button = screen.getByRole('button');\n\n    fireEvent.change(input, {\n      target: { value: '/123456789/a4a/amp_story_dfp_example' },\n    });\n\n    fireEvent.click(button);\n\n    // rerender to get updated adManagerSlotId prop\n    rerender(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated adManagerSlotId prop\n    rerender(\n      <GoogleAdManagerSettings\n        slotId={adManagerSlotId}\n        handleUpdate={mockUpdate}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.click(button);\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdSense/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, sprintf, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport {\n  ButtonSize,\n  ButtonType,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  validateAdSensePublisherIdFormat,\n  validateAdSenseSlotIdFormat,\n} from '../../utils';\nimport {\n  InlineForm,\n  InlineLink,\n  SaveButton,\n  SettingsTextInput,\n  TextInputHelperText,\n  VisuallyHiddenLabel,\n} from '../../components';\n\nexport const TEXT = {\n  PUBLISHER_ID_CONTEXT: sprintf(\n    /* translators: 1: first example. 2: second example. */\n    __(\n      'Example: %1$s or %2$s. <a>Find your AdSense Publisher ID</a>.',\n      'web-stories'\n    ),\n    'pub-1234567891234567',\n    'ca-pub-1234567891234567'\n  ),\n  PUBLISHER_ID_CONTEXT_LINK: __(\n    'https://support.google.com/adsense/answer/105516',\n    'web-stories'\n  ),\n  PUBLISHER_ID_PLACEHOLDER: __('Enter your Publisher ID', 'web-stories'),\n  PUBLISHER_ID_LABEL: __('Google AdSense Publisher ID', 'web-stories'),\n  SLOT_ID_CONTEXT: sprintf(\n    /* translators: %s: example value. */\n    __(\n      'Example: %s. Copy the slot ID from <a>your ad unit’s code</a>. The same ad unit will be used for all of your Web Stories.',\n      'web-stories'\n    ),\n    '1234567890'\n  ),\n  SLOT_ID_CONTEXT_LINK: __(\n    'https://support.google.com/adsense/answer/9274019',\n    'web-stories'\n  ),\n  SLOT_ID_PLACEHOLDER: __('Enter your Slot ID', 'web-stories'),\n  SLOT_ID_LABEL: __('Google AdSense Slot ID', 'web-stories'),\n  INPUT_ERROR: __('Invalid ID format', 'web-stories'),\n  SUBMIT_BUTTON: __('Save', 'web-stories'),\n};\n\nfunction GoogleAdSenseSettings({\n  publisherId: adSensePublisherId,\n  slotId: adSenseSlotId,\n  handleUpdatePublisherId,\n  handleUpdateSlotId,\n}) {\n  const [publisherId, setPublisherId] = useState(adSensePublisherId);\n  const [publisherIdInputError, setPublisherIdInputError] = useState('');\n  const canSavePublisherId =\n    publisherId !== adSensePublisherId && !publisherIdInputError;\n  const disablePublisherIdSaveButton = !canSavePublisherId;\n\n  const [slotId, setSlotId] = useState(adSenseSlotId);\n  const [slotIdInputError, setSlotIdInputError] = useState('');\n  const canSaveSlotId = slotId !== adSenseSlotId && !slotIdInputError;\n  const disableSlotIdSaveButton = !canSaveSlotId;\n\n  useEffect(() => {\n    setPublisherId(adSensePublisherId);\n  }, [adSensePublisherId]);\n\n  const onUpdatePublisherId = useCallback((event) => {\n    const { value } = event.target;\n    setPublisherId(value);\n\n    if (value.length === 0 || validateAdSensePublisherIdFormat(value)) {\n      setPublisherIdInputError('');\n\n      return;\n    }\n\n    setPublisherIdInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onSavePublisherId = useCallback(() => {\n    if (canSavePublisherId) {\n      handleUpdatePublisherId(publisherId);\n    }\n  }, [canSavePublisherId, publisherId, handleUpdatePublisherId]);\n\n  const onKeyDownPublisherId = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSavePublisherId();\n      }\n    },\n    [onSavePublisherId]\n  );\n\n  useEffect(() => {\n    setSlotId(adSenseSlotId);\n  }, [adSenseSlotId]);\n\n  const onUpdateSlotId = useCallback((event) => {\n    const { value } = event.target;\n    setSlotId(value);\n\n    if (value.length === 0 || validateAdSenseSlotIdFormat(value)) {\n      setSlotIdInputError('');\n\n      return;\n    }\n\n    setSlotIdInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onSaveSlotId = useCallback(() => {\n    if (canSaveSlotId) {\n      handleUpdateSlotId(slotId);\n    }\n  }, [canSaveSlotId, slotId, handleUpdateSlotId]);\n\n  const onKeyDownSlotId = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSaveSlotId();\n      }\n    },\n    [onSaveSlotId]\n  );\n\n  const handleClick = useCallback(\n    (evt) => trackClick(evt, 'click_adsense_publisher_id_docs'),\n    []\n  );\n\n  return (\n    <>\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"adSensePublisherId\">\n          {TEXT.PUBLISHER_ID_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          aria-label={TEXT.PUBLISHER_ID_LABEL}\n          id=\"adSensePublisherId\"\n          name=\"adSensePublisherId\"\n          data-testid=\"adSensePublisherId\"\n          value={publisherId}\n          onChange={onUpdatePublisherId}\n          onKeyDown={onKeyDownPublisherId}\n          placeholder={TEXT.PUBLISHER_ID_PLACEHOLDER}\n          hasError={Boolean(publisherIdInputError)}\n          hint={publisherIdInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disablePublisherIdSaveButton}\n          onClick={onSavePublisherId}\n          data-testid=\"adSensePublisherIdButton\"\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <InlineLink\n                href={TEXT.PUBLISHER_ID_CONTEXT_LINK}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                onClick={handleClick}\n                size={TextSize.Small}\n              />\n            ),\n          }}\n        >\n          {TEXT.PUBLISHER_ID_CONTEXT}\n        </TranslateWithMarkup>\n      </TextInputHelperText>\n\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"adSenseSlotId\">\n          {TEXT.SLOT_ID_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          id=\"adSenseSlotId\"\n          aria-label={TEXT.SLOT_ID_LABEL}\n          name=\"adSenseSlotId\"\n          data-testid=\"adSenseSlotId\"\n          value={slotId}\n          onChange={onUpdateSlotId}\n          onKeyDown={onKeyDownSlotId}\n          placeholder={TEXT.SLOT_ID_PLACEHOLDER}\n          hasError={Boolean(slotIdInputError)}\n          hint={slotIdInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disableSlotIdSaveButton}\n          onClick={onSaveSlotId}\n          data-testid=\"adSenseSlotIdButton\"\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <InlineLink\n                href={TEXT.SLOT_ID_CONTEXT_LINK}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                size={TextSize.Small}\n              />\n            ),\n          }}\n        >\n          {TEXT.SLOT_ID_CONTEXT}\n        </TranslateWithMarkup>\n      </TextInputHelperText>\n    </>\n  );\n}\nGoogleAdSenseSettings.propTypes = {\n  handleUpdatePublisherId: PropTypes.func,\n  handleUpdateSlotId: PropTypes.func,\n  publisherId: PropTypes.string,\n  slotId: PropTypes.string,\n};\n\nexport default GoogleAdSenseSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdSense/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport GoogleAdSense from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/AdManagement/GoogleAdSense',\n  component: GoogleAdSense,\n  args: {\n    slotId: '',\n    publisherId: '',\n  },\n  argTypes: {\n    handleUpdateSlotId: { action: 'update slot id' },\n    handleUpdatePublisherId: { action: 'update publisher id' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <GoogleAdSense {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/googleAdSense/test/googleAdSense.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport GoogleAdSenseSettings, { TEXT } from '..';\nimport { renderWithProviders } from '../../../../../testUtils';\n\ndescribe('Editor Settings: Google AdSense <GoogleAdSense />', () => {\n  let publisherId;\n  let slotId;\n  let mockUpdatePublisherId;\n  let mockUpdateSlotId;\n\n  beforeEach(() => {\n    publisherId = '';\n    slotId = '';\n    mockUpdatePublisherId = jest.fn((id) => {\n      publisherId = id;\n    });\n    mockUpdateSlotId = jest.fn((id) => {\n      slotId = id;\n    });\n  });\n\n  afterEach(() => {\n    publisherId = '';\n    slotId = '';\n  });\n\n  it('should render google AdSense input and helper text by default', () => {\n    renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const adSensePublisherIdInput = screen.getByTestId('adSensePublisherId');\n    expect(adSensePublisherIdInput).toBeInTheDocument();\n\n    const adSenseSlotIdInput = screen.getByTestId('adSenseSlotId');\n    expect(adSenseSlotIdInput).toBeInTheDocument();\n\n    const idLabel = screen.getByText(TEXT.PUBLISHER_ID_LABEL);\n    expect(idLabel).toBeInTheDocument();\n\n    const slotIdLabel = screen.getByText(TEXT.SLOT_ID_LABEL);\n    expect(slotIdLabel).toBeInTheDocument();\n  });\n\n  it('should render a visually hidden label for inputs', () => {\n    renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const label1 = screen.getByLabelText(TEXT.SLOT_ID_LABEL);\n    expect(label1).toBeInTheDocument();\n\n    const label2 = screen.getByLabelText(TEXT.PUBLISHER_ID_LABEL);\n    expect(label2).toBeInTheDocument();\n  });\n\n  it('should call mockUpdatePublisherId when enter is keyed on input', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const input = screen.getByTestId('adSensePublisherId');\n\n    fireEvent.change(input, { target: { value: 'pub-1234567891234567' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdatePublisherId when the save button is clicked', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const input = screen.getByTestId('adSensePublisherId');\n    const button = screen.getByTestId('adSensePublisherIdButton');\n\n    fireEvent.change(input, { target: { value: 'pub-1234567891234567' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.click(button);\n\n    expect(mockUpdatePublisherId).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdateSlotId when enter is keyed on input', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const input = screen.getByTestId('adSenseSlotId');\n\n    fireEvent.change(input, { target: { value: '0123456789' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdateSlotId).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdateSlotId).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(mockUpdateSlotId).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdateSlotId when the save button is clicked', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    const input = screen.getByTestId('adSenseSlotId');\n    const button = screen.getByTestId('adSenseSlotIdButton');\n\n    fireEvent.change(input, { target: { value: '0123456789' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdateSlotId).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated publisherId prop\n    rerender(\n      <GoogleAdSenseSettings\n        publisherId={publisherId}\n        slotId={slotId}\n        handleUpdatePublisherId={mockUpdatePublisherId}\n        handleUpdateSlotId={mockUpdateSlotId}\n      />\n    );\n\n    expect(mockUpdateSlotId).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.click(button);\n\n    expect(mockUpdateSlotId).toHaveBeenCalledTimes(2);\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\nimport { TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineLink,\n  MultilineForm,\n  SettingHeading,\n  SettingSubheading,\n  TextInputHelperText,\n} from '../components';\nimport { AD_NETWORK_TYPE } from '../../../constants';\nimport AdNetworkSettings from './adNetwork';\nimport GoogleAdManagerSettings from './googleAdManager';\nimport GoogleAdSenseSettings from './googleAdSense';\nimport MgidSettings from './mgid';\n\nexport const TEXT = {\n  SECTION_HEADING: __('Monetization', 'web-stories'),\n  HELPER_MESSAGE_NONE: __(\n    'Monetize your content by showing ads in your Web Stories. <a>Learn more</a>.',\n    'web-stories'\n  ),\n  HELPER_LINK_NONE: __(\n    'https://amp.dev/documentation/guides-and-tutorials/develop/advertise_amp_stories/',\n    'web-stories'\n  ),\n  SITE_KIT_NOT_INSTALLED: __(\n    'Install <a>Site Kit by Google</a> to easily enable Google AdSense for Web Stories.',\n    'web-stories'\n  ),\n  SITE_KIT_INSTALLED: __(\n    'Use Site Kit by Google to easily<a>activate Google AdSense</a> for Web Stories.',\n    'web-stories'\n  ),\n  SITE_KIT_IN_USE: __(\n    'Site Kit by Google has already enabled Google AdSense for your Web Stories, all changes to your ad configuration should occur there.',\n    'web-stories'\n  ),\n};\n\nfunction AdManagement({\n  updateSettings,\n  adNetwork,\n  publisherId,\n  adSenseSlotId,\n  adManagerSlotId,\n  mgidWidgetId,\n  siteKitStatus,\n}) {\n  const { adsenseActive, installed, adsenseLink } = siteKitStatus;\n\n  const handleMonetizationClick = useCallback(\n    (evt) =>\n      trackClick(evt, 'monetization', 'dashboard', TEXT.HELPER_LINK_NONE),\n    []\n  );\n\n  const handleUpdateAdSensePublisherId = useCallback(\n    (newAdSensePublisherId) =>\n      updateSettings({ adSensePublisherId: newAdSensePublisherId }),\n    [updateSettings]\n  );\n\n  const handleUpdateAdSenseSlotId = useCallback(\n    (newAdSenseSlotId) => updateSettings({ adSenseSlotId: newAdSenseSlotId }),\n    [updateSettings]\n  );\n\n  const handleUpdateAdManagerSlotId = useCallback(\n    (newAdManagerSlotId) =>\n      updateSettings({ adManagerSlotId: newAdManagerSlotId }),\n    [updateSettings]\n  );\n\n  const handleUpdateMgidWidgetId = useCallback(\n    (newMgidWidgetId) => updateSettings({ mgidWidgetId: newMgidWidgetId }),\n    [updateSettings]\n  );\n\n  const handleUpdateAdNetwork = useCallback(\n    (newAdNetwork) => {\n      updateSettings({ adNetwork: newAdNetwork });\n      trackEvent('change_ad_network', {\n        name: newAdNetwork,\n      });\n    },\n    [updateSettings]\n  );\n\n  const onSiteKitClick = useCallback(\n    (evt) => trackClick(evt, 'click_site_kit_link'),\n    []\n  );\n\n  const siteKitDisplayText = useMemo(() => {\n    if (adsenseActive) {\n      return null;\n    }\n\n    return (\n      <TranslateWithMarkup\n        mapping={{\n          a: (\n            <InlineLink\n              href={adsenseLink}\n              rel=\"noreferrer\"\n              target=\"_blank\"\n              size={TextSize.Small}\n              onClick={onSiteKitClick}\n            />\n          ),\n        }}\n      >\n        {installed ? TEXT.SITE_KIT_INSTALLED : TEXT.SITE_KIT_NOT_INSTALLED}\n      </TranslateWithMarkup>\n    );\n  }, [adsenseActive, installed, adsenseLink, onSiteKitClick]);\n\n  return (\n    <MultilineForm onSubmit={(e) => e.preventDefault()}>\n      <div>\n        <SettingHeading>{TEXT.SECTION_HEADING}</SettingHeading>\n\n        <TextInputHelperText size={TextSize.Small}>\n          <TranslateWithMarkup\n            mapping={{\n              a: (\n                <InlineLink\n                  href={TEXT.HELPER_LINK_NONE}\n                  rel=\"noreferrer\"\n                  target=\"_blank\"\n                  onClick={handleMonetizationClick}\n                  size={TextSize.Small}\n                />\n              ),\n            }}\n          >\n            {TEXT.HELPER_MESSAGE_NONE}\n          </TranslateWithMarkup>\n        </TextInputHelperText>\n        <SettingSubheading size={TextSize.Small}>\n          {siteKitDisplayText}\n        </SettingSubheading>\n      </div>\n\n      {adsenseActive ? (\n        <div>\n          <TextInputHelperText size={TextSize.Small}>\n            {TEXT.SITE_KIT_IN_USE}\n          </TextInputHelperText>\n        </div>\n      ) : (\n        <div>\n          <AdNetworkSettings\n            handleUpdate={handleUpdateAdNetwork}\n            adNetwork={adNetwork}\n          />\n          {AD_NETWORK_TYPE.ADSENSE === adNetwork && (\n            <GoogleAdSenseSettings\n              handleUpdatePublisherId={handleUpdateAdSensePublisherId}\n              handleUpdateSlotId={handleUpdateAdSenseSlotId}\n              publisherId={publisherId}\n              slotId={adSenseSlotId}\n              siteKitStatus={siteKitStatus}\n            />\n          )}\n          {AD_NETWORK_TYPE.ADMANAGER === adNetwork && (\n            <GoogleAdManagerSettings\n              handleUpdate={handleUpdateAdManagerSlotId}\n              slotId={adManagerSlotId}\n            />\n          )}\n          {AD_NETWORK_TYPE.MGID === adNetwork && (\n            <MgidSettings\n              handleUpdate={handleUpdateMgidWidgetId}\n              widgetId={mgidWidgetId}\n            />\n          )}\n        </div>\n      )}\n    </MultilineForm>\n  );\n}\n\nAdManagement.propTypes = {\n  updateSettings: PropTypes.func.isRequired,\n  adNetwork: PropTypes.string.isRequired,\n  publisherId: PropTypes.string,\n  adSenseSlotId: PropTypes.string,\n  adManagerSlotId: PropTypes.string,\n  mgidWidgetId: PropTypes.string,\n  siteKitStatus: PropTypes.shape({\n    installed: PropTypes.bool,\n    active: PropTypes.bool,\n    adsenseActive: PropTypes.bool,\n    analyticsActive: PropTypes.bool,\n    adsenseLink: PropTypes.string,\n  }),\n};\n\nexport default AdManagement;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/mgid/index.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  ButtonSize,\n  ButtonType,\n  TextSize,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { validateMgidWidgetIdFormat } from '../../utils';\nimport {\n  InlineForm,\n  SaveButton,\n  SettingsTextInput,\n  TextInputHelperText,\n  VisuallyHiddenLabel,\n} from '../../components';\n\nexport const TEXT = {\n  WIDGET_ID_CONTEXT: sprintf(\n    /* translators: %s: example value. */\n    __('Example: %s', 'web-stories'),\n    '1234567'\n  ),\n  WIDGET_ID_PLACEHOLDER: __('Enter your MGID Widget ID', 'web-stories'),\n  WIDGET_ID_LABEL: __('Widget ID', 'web-stories'),\n  INPUT_ERROR: __('Invalid ID format', 'web-stories'),\n  SUBMIT_BUTTON: __('Save', 'web-stories'),\n};\n\nfunction MgidSettings({ widgetId: mgidWidgetId, handleUpdate }) {\n  const [widgetId, setWidgetId] = useState(mgidWidgetId);\n  const [widgetIdInputError, setWidgetIdInputError] = useState('');\n  const canSaveWidgetId = widgetId !== mgidWidgetId && !widgetIdInputError;\n  const disableWidgetIdSaveButton = !canSaveWidgetId;\n\n  useEffect(() => {\n    setWidgetId(mgidWidgetId);\n  }, [mgidWidgetId]);\n\n  const onUpdateWidgetId = useCallback((event) => {\n    const { value } = event.target;\n    setWidgetId(value);\n\n    if (value.length === 0 || validateMgidWidgetIdFormat(value)) {\n      setWidgetIdInputError('');\n\n      return;\n    }\n\n    setWidgetIdInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onSaveWidgetId = useCallback(() => {\n    if (canSaveWidgetId) {\n      handleUpdate(widgetId);\n    }\n  }, [canSaveWidgetId, widgetId, handleUpdate]);\n\n  const onKeyDownWidgetId = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSaveWidgetId();\n      }\n    },\n    [onSaveWidgetId]\n  );\n\n  return (\n    <>\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"mgidWidgetId\">\n          {TEXT.WIDGET_ID_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          id=\"mgidWidgetId\"\n          aria-label={TEXT.WIDGET_ID_LABEL}\n          value={widgetId}\n          onChange={onUpdateWidgetId}\n          onKeyDown={onKeyDownWidgetId}\n          placeholder={TEXT.WIDGET_ID_PLACEHOLDER}\n          hasError={Boolean(widgetIdInputError)}\n          hint={widgetIdInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disableWidgetIdSaveButton}\n          onClick={onSaveWidgetId}\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        {TEXT.WIDGET_ID_CONTEXT}\n      </TextInputHelperText>\n    </>\n  );\n}\nMgidSettings.propTypes = {\n  handleUpdate: PropTypes.func,\n  widgetId: PropTypes.string,\n};\n\nexport default MgidSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/mgid/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport Mgid from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/AdManagement/Mgid',\n  component: Mgid,\n  args: {\n    widgetId: '',\n  },\n  argTypes: {\n    handleUpdate: { action: 'update mgid' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <Mgid {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/mgid/test/mgid.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport MgidSettings, { TEXT } from '..';\nimport { renderWithProviders } from '../../../../../testUtils';\n\ndescribe('Editor Settings: MGID <Mgid />', () => {\n  let mgidWidgetIdtId;\n  let mockUpdate;\n\n  beforeEach(() => {\n    mgidWidgetIdtId = '';\n    mockUpdate = jest.fn((id) => {\n      mgidWidgetIdtId = id;\n    });\n  });\n\n  afterEach(() => {\n    mgidWidgetIdtId = '';\n  });\n\n  it('should render a visually hidden label for MGID input', () => {\n    renderWithProviders(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    const label = screen.getByLabelText(TEXT.WIDGET_ID_LABEL);\n    expect(label).toBeInTheDocument();\n  });\n\n  it('should call mockUpdate when enter is keyed on input', () => {\n    const { rerender } = renderWithProviders(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    const input = screen.getByRole('textbox');\n\n    fireEvent.change(input, {\n      target: { value: '1234567890' },\n    });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated mgidWidgetIdtId prop\n    rerender(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated mgidWidgetId prop\n    rerender(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdate when the save button is clicked', () => {\n    const { rerender } = renderWithProviders(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    const input = screen.getByRole('textbox');\n    const button = screen.getByRole('button');\n\n    fireEvent.change(input, {\n      target: { value: '1234567890' },\n    });\n\n    fireEvent.click(button);\n\n    // rerender to get updated mgidWidgetId prop\n    rerender(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated mgidWidgetId prop\n    rerender(\n      <MgidSettings widgetId={mgidWidgetIdtId} handleUpdate={mockUpdate} />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.click(button);\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport AdManagement from '..';\nimport { AD_NETWORK_TYPE } from '../../../../constants';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/AdManagement',\n  component: AdManagement,\n  args: {\n    publisherId: 'publisher Id',\n    adSenseSlotId: 'ad sense slot id',\n    adManagerSlotId: 'ad manager slot id',\n    mgidWidgetId: 'mgid widget id',\n    installed: false,\n    active: false,\n    adsenseActive: false,\n    adsenseLink: '',\n  },\n  argTypes: {\n    updateSettings: { action: 'trigger ad update' },\n    adNetwork: {\n      options: Object.values(AD_NETWORK_TYPE),\n      control: 'radio',\n    },\n  },\n  parameters: {\n    controls: {\n      exclude: ['siteKitStatus'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <AdManagement\n        siteKitStatus={{\n          installed: args.installed,\n          active: args.active,\n          adsenseActive: args.adsenseActive,\n          adsenseLink: args.adsenseLink,\n        }}\n        {...args}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/adManagement/test/adManagement.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport AdManagement, { TEXT } from '..';\nimport { AD_NETWORK_TYPE } from '../../../../constants';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: Ad Management group settings <AdManagement />', () => {\n  let adNetwork;\n  let mockUpdate;\n  const defaultSiteKitStatus = {\n    installed: false,\n    adsenseActive: false,\n    active: false,\n  };\n\n  beforeEach(() => {\n    adNetwork = AD_NETWORK_TYPE.NONE;\n    mockUpdate = jest.fn();\n  });\n\n  afterEach(() => {\n    adNetwork = AD_NETWORK_TYPE.NONE;\n  });\n\n  it('should render ad management settings area with ad network dropdown button and helper text by default', () => {\n    renderWithProviders(\n      <AdManagement\n        adNetwork={adNetwork}\n        updateSettings={mockUpdate}\n        publisherId=\"\"\n        adSenseSlotId=\"\"\n        adManagerSlotId=\"\"\n        mgidWidgetId=\"\"\n        siteKitStatus={defaultSiteKitStatus}\n      />\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helperLink = screen.getByText(\n      (_, node) => node.textContent === 'Learn more',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n\n    const networkDropdown = screen.getByRole('button');\n    expect(networkDropdown).toHaveTextContent('None');\n  });\n\n  it('should render ad network settings and link adsense', () => {\n    renderWithProviders(\n      <AdManagement\n        adNetwork={AD_NETWORK_TYPE.ADSENSE}\n        updateSettings={mockUpdate}\n        publisherId=\"\"\n        adSenseSlotId=\"\"\n        adManagerSlotId=\"\"\n        mgidWidgetId=\"\"\n        siteKitStatus={defaultSiteKitStatus}\n      />\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helperLink = screen.getByText(\n      (_, node) => node.textContent === 'how to monetize your Web Stories',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n  });\n\n  it('should render ad network settings and link Ad Manager', () => {\n    renderWithProviders(\n      <AdManagement\n        adNetwork={AD_NETWORK_TYPE.ADMANAGER}\n        updateSettings={mockUpdate}\n        publisherId=\"\"\n        adSenseSlotId=\"\"\n        adManagerSlotId=\"\"\n        mgidWidgetId=\"\"\n        siteKitStatus={defaultSiteKitStatus}\n      />\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helperLink = screen.getByText(\n      (_, node) =>\n        node.textContent === 'enable programmatic demand in Web Stories',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n  });\n\n  it('should render ad network settings and link MGID', () => {\n    renderWithProviders(\n      <AdManagement\n        adNetwork={AD_NETWORK_TYPE.MGID}\n        updateSettings={mockUpdate}\n        publisherId=\"\"\n        adSenseSlotId=\"\"\n        adManagerSlotId=\"\"\n        mgidWidgetId=\"\"\n        siteKitStatus={defaultSiteKitStatus}\n      />\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helperLink = screen.getByText(\n      (_, node) =>\n        node.textContent === 'monetizing Web Stories with MGID Native Solution',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n  });\n\n  it('should render adsense message when site kit is installed', () => {\n    renderWithProviders(\n      <AdManagement\n        adNetwork={AD_NETWORK_TYPE.ADMANAGER}\n        updateSettings={mockUpdate}\n        publisherId=\"\"\n        adSenseSlotId=\"\"\n        adManagerSlotId=\"\"\n        mgidWidgetId=\"\"\n        siteKitStatus={{\n          ...defaultSiteKitStatus,\n          active: true,\n          installed: true,\n          adsenseActive: true,\n        }}\n      />\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const siteKitMessage = screen.getByText(TEXT.SITE_KIT_IN_USE);\n    expect(siteKitMessage).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/archive/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useDebouncedCallback,\n  useEffect,\n  useState,\n} from '@googleforcreators/react';\nimport { __, _x, TranslateWithMarkup, sprintf } from '@googleforcreators/i18n';\nimport { DropDown, Search, TextSize } from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport { TEXT_INPUT_DEBOUNCE } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineLink,\n  SettingForm,\n  SettingHeading,\n  TextInputHelperText,\n} from '../components';\nimport { ARCHIVE_TYPE } from '../../../constants';\n\nexport const TEXT = {\n  LABEL: __('Stories Archives', 'web-stories'),\n  SECTION_HEADING: __('Stories Archives', 'web-stories'),\n  ARCHIVE_CONTENT: __(\n    \"By default WordPress automatically creates an archive page, displaying your latest stories in your theme's layout.\",\n    'web-stories'\n  ),\n  ARCHIVE_CONTENT_2: __(\n    'You can customize or disable this behavior.',\n    'web-stories'\n  ),\n  SUB_TEXT_CUSTOM: __(\n    'Choose a page to serve as your Web Stories archive. Use the Web Stories block to add stories to this page.',\n    'web-stories'\n  ),\n};\n\nconst OPTIONS = [\n  {\n    label: _x('Default', 'archive type', 'web-stories'),\n    value: ARCHIVE_TYPE.DEFAULT,\n  },\n  {\n    label: __('Disabled', 'web-stories'),\n    value: ARCHIVE_TYPE.DISABLED,\n  },\n  {\n    label: __('Create your own', 'web-stories'),\n    value: ARCHIVE_TYPE.CUSTOM,\n  },\n];\n\nconst SearchWrapper = styled.div`\n  padding-top: 12px;\n`;\n\nexport default function ArchiveSettings({\n  archive = ARCHIVE_TYPE.DEFAULT,\n  archiveURL: _archiveURL,\n  defaultArchiveURL,\n  archivePageId,\n  updateSettings,\n  searchPages,\n  getPageById,\n}) {\n  const [archiveURL, setArchiveURL] = useState(_archiveURL);\n  const [selectedPage, setSelectedPage] = useState(\n    archivePageId ? { value: archivePageId } : undefined\n  );\n  const [searchOptions, setSearchOptions] = useState([]);\n\n  const onChangeArchive = useCallback(\n    (_, newArchive) => {\n      // TODO: Get archive URL from REST API instead of config.\n      // This way, when changing from \"Custom\" to \"Default\", we can display\n      // the default \"/web-stories/\" URL again. Otherwise that's not possible.\n      setArchiveURL(_archiveURL);\n      const newArchivePageId =\n        newArchive === ARCHIVE_TYPE.CUSTOM ? archivePageId : 0;\n      setSelectedPage(newArchivePageId);\n      updateSettings({\n        archive: newArchive,\n        archivePageId: newArchivePageId,\n      });\n    },\n    [updateSettings, archivePageId, _archiveURL]\n  );\n\n  const onChangeArchivePageId = useCallback(\n    (_, newArchivePage) => {\n      const newValue = Number(newArchivePage.value);\n      if (newValue !== archivePageId) {\n        setSelectedPage(newValue ? { value: newValue } : undefined);\n        updateSettings({ archivePageId: newValue });\n      }\n    },\n    [archivePageId, updateSettings]\n  );\n\n  useEffect(() => {\n    let mounted = true;\n\n    if (archivePageId && ARCHIVE_TYPE.CUSTOM === archive) {\n      (async () => {\n        const { title, link } = await getPageById(archivePageId);\n        if (mounted && title) {\n          const newOption = { value: archivePageId, label: title };\n          setSearchOptions((options) => [newOption, ...options]);\n          setSelectedPage(newOption);\n          setArchiveURL(link);\n        }\n      })();\n    }\n\n    return () => {\n      mounted = false;\n    };\n  }, [archive, archivePageId, getPageById]);\n\n  const handleSearchChange = useDebouncedCallback(async (value) => {\n    await trackEvent('archive_page_search', {\n      search_type: 'dashboard',\n      search_term: value,\n    });\n    setSearchOptions(await searchPages(value));\n  }, TEXT_INPUT_DEBOUNCE);\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>{TEXT.SECTION_HEADING}</SettingHeading>\n        <TextInputHelperText size={TextSize.Small}>\n          {TEXT.ARCHIVE_CONTENT}\n        </TextInputHelperText>\n        <TextInputHelperText size={TextSize.Small}>\n          {TEXT.ARCHIVE_CONTENT_2}\n        </TextInputHelperText>\n      </div>\n      <div>\n        <DropDown\n          ariaLabel={TEXT.LABEL}\n          options={OPTIONS}\n          selectedValue={archive}\n          onMenuItemClick={onChangeArchive}\n          fillWidth\n        />\n        {ARCHIVE_TYPE.DISABLED === archive && (\n          <TextInputHelperText size={TextSize.Small}>\n            <TranslateWithMarkup\n              mapping={{\n                code: <code />,\n              }}\n            >\n              {sprintf(\n                /* translators: %s: archive url. */\n                __(\n                  'Turn off the default archive page at <code>%s</code>. Users will see a 404 Not Found page when trying to access the default archive page.',\n                  'web-stories'\n                ),\n                defaultArchiveURL\n              )}\n            </TranslateWithMarkup>\n          </TextInputHelperText>\n        )}\n        {ARCHIVE_TYPE.CUSTOM === archive && (\n          <TextInputHelperText size={TextSize.Small}>\n            {TEXT.SUB_TEXT_CUSTOM}\n          </TextInputHelperText>\n        )}\n        {ARCHIVE_TYPE.CUSTOM === archive && (\n          <SearchWrapper>\n            <Search\n              placeholder={__('Select page', 'web-stories')}\n              selectedValue={selectedPage}\n              options={searchOptions}\n              handleSearchValueChange={handleSearchChange}\n              emptyText={__('No pages available', 'web-stories')}\n              onMenuItemClick={onChangeArchivePageId}\n            />\n          </SearchWrapper>\n        )}\n        {ARCHIVE_TYPE.DISABLED !== archive && (\n          <TextInputHelperText size={TextSize.Small}>\n            <TranslateWithMarkup\n              mapping={{\n                a: (\n                  <InlineLink\n                    href={archiveURL}\n                    rel=\"noreferrer\"\n                    target=\"_blank\"\n                    size={TextSize.Small}\n                  />\n                ),\n                code: <code />,\n              }}\n            >\n              {archivePageId && archiveURL !== defaultArchiveURL\n                ? sprintf(\n                    /* translators: 1. current archive url, 2. default archive url. */\n                    __(\n                      'Visit archive page at <a>%1$s</a>. <code>%2$s</code> will automatically redirect to this page.',\n                      'web-stories'\n                    ),\n                    archiveURL,\n                    defaultArchiveURL\n                  )\n                : sprintf(\n                    /* translators: %s: archive url. */\n                    __('Visit archive page at <a>%s</a>.', 'web-stories'),\n                    defaultArchiveURL\n                  )}\n            </TranslateWithMarkup>\n          </TextInputHelperText>\n        )}\n      </div>\n    </SettingForm>\n  );\n}\n\nArchiveSettings.propTypes = {\n  archive: PropTypes.string.isRequired,\n  archiveURL: PropTypes.string.isRequired,\n  defaultArchiveURL: PropTypes.string.isRequired,\n  updateSettings: PropTypes.func.isRequired,\n  searchPages: PropTypes.func.isRequired,\n  archivePageId: PropTypes.number.isRequired,\n  getPageById: PropTypes.func.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/archive/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FlagsProvider } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport ArchiveSettings from '..';\nimport { ARCHIVE_TYPE } from '../../../../constants';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/Archive',\n  component: ArchiveSettings,\n  argTypes: {\n    archive: {\n      options: Object.values(ARCHIVE_TYPE),\n      control: 'radio',\n    },\n    updateSettings: { action: 'updateSettings fired' },\n  },\n  parameters: {\n    controls: {\n      include: ['updateSettings', 'archive'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <FlagsProvider>\n        <ArchiveSettings\n          archiveURL={'http://www.example.com/web-stories'}\n          defaultArchiveURL={'http://www.example.com/web-stories'}\n          archivePageId={0}\n          getPageById={() => ({ value: 1, label: 'Page 1' })}\n          searchPages={() => [\n            { value: 1, label: 'Page 1' },\n            { value: 1, label: 'Page 2' },\n            { value: 1, label: 'Page 3' },\n          ]}\n          {...args}\n        />\n      </FlagsProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/archive/test/archive.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\nimport { FlagsProvider } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport ArchiveSetting, { TEXT } from '..';\nimport { ARCHIVE_TYPE } from '../../../../constants';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: Archive page settings <ArchiveSetting />', () => {\n  let archive;\n  let mockUpdate;\n\n  beforeEach(() => {\n    archive = ARCHIVE_TYPE.DEFAULT;\n    mockUpdate = jest.fn();\n  });\n\n  afterEach(() => {\n    archive = ARCHIVE_TYPE.DEFAULT;\n  });\n\n  it('should render archive dropdown button and helper text for default', () => {\n    const archiveURL = 'http://www.example.com/custom-archive/';\n    const defaultArchiveURL = 'http://www.example.com/web-stories/';\n    renderWithProviders(\n      <FlagsProvider>\n        <ArchiveSetting\n          archive={archive}\n          updateSettings={mockUpdate}\n          archiveURL={archiveURL}\n          defaultArchiveURL={defaultArchiveURL}\n          archivePageId={0}\n          searchPages={jest.fn()}\n          getPageById={jest.fn()}\n        />\n      </FlagsProvider>\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helperLink = screen.getByText(\n      (_, node) => node.textContent === defaultArchiveURL,\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n\n    const archiveDropdown = screen.getByRole('button');\n    expect(archiveDropdown).toHaveTextContent('Default');\n  });\n\n  it('should render archive dropdown button and helper text for disabled', () => {\n    const archiveURL = 'http://www.example.com/custom-archive/';\n    const defaultArchiveURL = 'http://www.example.com/web-stories/';\n    renderWithProviders(\n      <FlagsProvider>\n        <ArchiveSetting\n          archive={ARCHIVE_TYPE.DISABLED}\n          updateSettings={mockUpdate}\n          archiveURL={archiveURL}\n          defaultArchiveURL={defaultArchiveURL}\n          archivePageId={0}\n          searchPages={jest.fn()}\n          getPageById={jest.fn()}\n        />\n      </FlagsProvider>\n    );\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n\n    const helpText = screen.getByText(TEXT.ARCHIVE_CONTENT);\n    expect(helpText).toBeInTheDocument();\n\n    const archiveDropdown = screen.getByRole('button');\n    expect(archiveDropdown).toHaveTextContent('Disabled');\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/components.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled, { css } from 'styled-components';\nimport {\n  Button,\n  ButtonType,\n  ButtonSize,\n  ButtonVariant,\n  Headline,\n  Input,\n  Link,\n  Text,\n  TextSize,\n  themeHelpers,\n} from '@googleforcreators/design-system';\nimport { StandardViewContentGutter } from '@googleforcreators/dashboard';\n\nexport const Wrapper = styled.div``;\n\nexport const Main = styled(StandardViewContentGutter)`\n  display: flex;\n  flex-direction: column;\n  padding-top: 36px;\n  margin-top: 20px;\n  margin-bottom: 56px;\n  max-width: 945px;\n`;\n\nexport const SettingForm = styled.form`\n  display: grid;\n  grid-template-columns: 27% minmax(400px, 1fr);\n  column-gap: 6.56%;\n  padding-bottom: 52px;\n\n  @media ${({ theme }) => theme.breakpoint.mobile} {\n    grid-template-columns: 100%;\n    row-gap: 20px;\n  }\n`;\n\nexport const SettingHeading = styled(Headline).attrs({\n  as: 'h3',\n})`\n  ${({ theme }) =>\n    themeHelpers.expandPresetStyles({\n      preset: {\n        ...theme.typography.presets.label[TextSize.Large],\n      },\n      theme,\n    })};\n  margin: 8px 0;\n`;\n\nexport const InlineLink = styled(Link)`\n  display: inline-block;\n`;\n\nexport const HelperText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nexport const ConnectionHelperText = styled(Text.Paragraph)`\n  padding-top: 12px;\n  color: ${({ hasError, theme }) =>\n    hasError ? theme.colors.fg.negative : theme.colors.fg.tertiary};\n`;\n\nexport const CenterMutedText = styled(Text.Paragraph)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  text-align: center;\n`;\n\nexport const SettingSubheading = styled(HelperText)`\n  padding: 8px 0;\n`;\n\nexport const TextInputHelperText = styled(HelperText)`\n  padding-top: 12px;\n`;\n\nexport const CheckboxLabel = styled(Text.Label)`\n  display: flex;\n  justify-content: flex-start;\n  margin-top: 8px;\n  cursor: pointer;\n`;\n\nexport const CheckboxLabelText = styled(HelperText)`\n  margin-left: 8px;\n`;\n\nexport const Error = styled(CenterMutedText)`\n  padding-bottom: 10px;\n  color: ${({ theme }) => theme.colors.fg.negative};\n`;\n\nexport const UploadedContainer = styled.div`\n  display: grid;\n  grid-template-columns: repeat(auto-fill, 102px);\n  grid-auto-rows: 102px;\n  grid-column-gap: 12px;\n  grid-row-gap: 20px;\n  padding-bottom: 20px;\n  margin-bottom: 4px;\n  border: 1px solid transparent;\n\n  ${themeHelpers.focusableOutlineCSS};\n`;\n\nexport const GridItemContainer = styled.div`\n  position: relative;\n  ${({ active, theme }) =>\n    active &&\n    css`\n      border: 1px solid ${theme.colors.border.defaultActive};\n      border-radius: ${theme.borders.radius.small};\n    `};\n\n  &:hover,\n  &:focus-within {\n    button {\n      opacity: 1 !important;\n    }\n  }\n`;\n\nexport const GridItemButton = styled.button`\n  display: block;\n  background-color: transparent;\n  border: 2px solid transparent;\n  width: 100%;\n  height: 100%;\n  border-radius: 4px;\n  padding: 0;\n\n  ${themeHelpers.focusableOutlineCSS};\n`;\n\nexport const Logo = styled.img`\n  object-fit: cover;\n  width: 100%;\n  height: 100%;\n  border-radius: 4px;\n`;\n\nexport const MenuContainer = styled.div`\n  position: absolute;\n  top: 0;\n  width: 100%;\n  height: 100%;\n`;\n\nexport const LogoMenuButton = styled(Button).attrs({\n  size: ButtonSize.Small,\n  type: ButtonType.Secondary,\n  variant: ButtonVariant.Circle,\n})`\n  opacity: ${({ isActive, menuOpen }) => (menuOpen || isActive ? 1 : 0)};\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n`;\n\nexport const SaveButton = styled(Button)`\n  height: 36px;\n`;\n\nexport const TestConnectionButton = styled(Button)`\n  height: 36px;\n  margin-top: 12px;\n`;\n\nexport const InlineForm = styled.div`\n  display: flex;\n  align-items: flex-start;\n`;\n\nexport const VisuallyHiddenLabel = styled.label(themeHelpers.visuallyHidden);\n\nexport const SettingsTextInput = styled(Input)`\n  margin-right: 8px;\n`;\n\nexport const VisuallyHiddenDescription = styled.span(\n  themeHelpers.visuallyHidden\n);\n\nexport const MultilineForm = styled(SettingForm)`\n  margin-bottom: 28px;\n\n  ${InlineForm} {\n    margin-top: 20px;\n  }\n`;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {} });\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/customFonts/confirmationDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport { ThemeProvider } from 'styled-components';\nimport {\n  Text,\n  TextSize,\n  Dialog,\n  ButtonType,\n  ButtonSize,\n  Button,\n  theme,\n} from '@googleforcreators/design-system';\n\nfunction ConfirmationDialog({ onClose, onPrimary }) {\n  return (\n    <ThemeProvider theme={theme}>\n      <Dialog\n        isOpen\n        onClose={onClose}\n        title={__('Delete Font', 'web-stories')}\n        actions={\n          <>\n            <Button\n              type={ButtonType.Tertiary}\n              size={ButtonSize.Small}\n              onClick={() => onClose()}\n            >\n              {__('Cancel', 'web-stories')}\n            </Button>\n            <Button\n              type={ButtonType.Primary}\n              size={ButtonSize.Small}\n              onClick={() => onPrimary()}\n            >\n              {__('Delete Font', 'web-stories')}\n            </Button>\n          </>\n        }\n      >\n        <Text.Paragraph size={TextSize.Small}>\n          {__(\n            'Deleting a font will delete it from every previous story it’s in. Would you like to proceed?',\n            'web-stories'\n          )}\n        </Text.Paragraph>\n      </Dialog>\n    </ThemeProvider>\n  );\n}\n\nConfirmationDialog.propTypes = {\n  onClose: PropTypes.func.isRequired,\n  onPrimary: PropTypes.func.isRequired,\n};\n\nexport default ConfirmationDialog;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/customFonts/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\nimport { __, sprintf, translateToExclusiveList } from '@googleforcreators/i18n';\nimport { isValidUrl, withProtocol } from '@googleforcreators/url';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  Text,\n  TextSize,\n  themeHelpers,\n  useSnackbar,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\n\nimport styled from 'styled-components';\nimport { trackEvent, trackError } from '@googleforcreators/tracking';\nimport { Tooltip } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  InlineForm,\n  SaveButton,\n  SettingForm,\n  SettingHeading,\n  SettingsTextInput,\n  SettingSubheading,\n  TextInputHelperText,\n} from '../components';\nimport { ERRORS } from '../../../constants';\nimport ConfirmationDialog from './confirmationDialog';\nimport getFontDataFromUrl from './utils/getFontDataFromUrl';\n\nexport const TEXT = {\n  ADD_CONTEXT: __(\n    'Add and manage your custom and brand fonts via link here. They’ll appear in your font list in the editor.',\n    'web-stories'\n  ),\n  REMOVAL: __(\n    'Removing a font from this settings page will remove it from your font list in all stories.',\n    'web-stories'\n  ),\n  SECTION_HEADING: __('Custom Fonts', 'web-stories'),\n  LABEL: __('Insert Font URL', 'web-stories'),\n  INPUT_CONTEXT: __(\n    'Insert a public URL to a font file. Allowed formats are .otf, .ttf, .woff.',\n    'web-stories'\n  ),\n  INPUT_ERROR: __('Invalid URL format', 'web-stories'),\n  SUBMIT_BUTTON: __('Add Font', 'web-stories'),\n  FONTS_HEADING: __('Current Fonts', 'web-stories'),\n  FONTS_CONTEXT: __(\n    'Deleting fonts will delete them from your in-editor font list and all previous stories.',\n    'web-stories'\n  ),\n};\n\nconst AddButton = styled(SaveButton)`\n  min-width: 90px;\n  margin-top: 32px;\n`;\n\nconst InputsWrapper = styled.div`\n  margin-top: 8px;\n`;\n\nconst FontsWrapper = styled.div`\n  margin-top: 34px;\n`;\n\nconst ListHeading = styled(Text.Span)`\n  margin-bottom: 10px;\n  display: inline-block;\n`;\n\nconst FontsList = styled.div`\n  padding: 12px 0;\n  border: ${({ theme }) => `1px solid ${theme.colors.divider.primary}`};\n  :focus-within {\n    ${({ theme }) => themeHelpers.focusCSS(theme.colors.border.focus)}\n  }\n`;\n\n// Hidden by default.\nconst DeleteButton = styled(Button)`\n  visibility: hidden;\n  opacity: 0;\n  transition:\n    visibility 0s,\n    opacity ease-in-out 300ms;\n  &:focus {\n    ${({ theme }) => themeHelpers.focusCSS(theme.colors.border.focus)}\n  }\n`;\n\nconst FontRow = styled.div`\n  padding: 0 12px;\n  display: flex;\n  height: 32px;\n  width: 100%;\n  justify-content: space-between;\n  transition: background-color ease-in-out 300ms;\n  &[aria-selected='true'],\n  &:hover,\n  &:focus {\n    background-color: ${({ theme }) => theme.colors.bg.secondary};\n\n    button {\n      visibility: visible;\n      opacity: 1;\n    }\n  }\n`;\n\n// 32px is the button width.\nconst FontData = styled.div`\n  line-height: 32px;\n  white-space: nowrap;\n  display: flex;\n  font-size: 14px;\n  max-width: calc(100% - 32px);\n  align-items: center;\n`;\n\nconst StyledText = styled(Text.Paragraph).attrs({\n  as: 'span',\n})``;\n\nconst FontUrl = styled(StyledText)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n`;\n\nconst Divider = styled.div`\n  width: 4px;\n  height: 4px;\n  background-color: ${({ theme }) => theme.colors.standard.black};\n  border-radius: ${({ theme }) => theme.borders.radius.round};\n  margin: 0 6px;\n  align-self: center;\n`;\n\nconst ALLOWED_FONT_TYPES = ['.otf', '.ttf', '.woff'];\nfunction CustomFontsSettings({\n  customFonts = [],\n  addCustomFont,\n  deleteCustomFont,\n}) {\n  const speak = useLiveRegion();\n  const [fontUrl, setFontUrl] = useState('');\n  const [inputError, setInputError] = useState('');\n  const [showDialog, setShowDialog] = useState(false);\n  const [toDelete, setToDelete] = useState(null);\n  const canSave = !inputError && fontUrl;\n  const currentFontsContainerRef = useRef(null);\n  const currentFontsRowsRef = useRef([]);\n  const [currentFontsFocusIndex, setCurrentFontsFocusIndex] = useState(0);\n  const [currentFontsActiveId, setCurrentFontsActiveId] = useState();\n  const { showSnackbar } = useSnackbar();\n\n  const handleUpdateFontUrl = useCallback((event) => {\n    const { value } = event.target;\n    setFontUrl(value);\n\n    if (value.length === 0 || isValidUrl(withProtocol(value))) {\n      setInputError('');\n\n      return;\n    }\n\n    setInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const handleDelete = useCallback(async () => {\n    try {\n      await deleteCustomFont(toDelete);\n      speak(__('Font deleted', 'web-stories'));\n    } catch (err) {\n      trackError('remove_custom_font', err?.message);\n      showSnackbar({\n        'aria-label': ERRORS.REMOVE_FONT.MESSAGE,\n        message: ERRORS.REMOVE_FONT.MESSAGE,\n        dismissible: true,\n      });\n    } finally {\n      setToDelete(null);\n      setShowDialog(false);\n      setInputError('');\n    }\n  }, [deleteCustomFont, toDelete, showSnackbar, speak]);\n\n  const handleOnSave = useCallback(async () => {\n    if (canSave) {\n      const urlWithProtocol = withProtocol(fontUrl);\n      try {\n        await fetch(urlWithProtocol, {\n          method: 'HEAD',\n        });\n      } catch (err) {\n        trackError('add_custom_font', err?.message);\n        setInputError(\n          __(\n            'Please ensure correct CORS settings for allowing font usage on this site.',\n            'web-stories'\n          )\n        );\n        return;\n      }\n      let fontData;\n      try {\n        trackEvent('add_custom_font', {\n          url: urlWithProtocol,\n        });\n        fontData = await getFontDataFromUrl(urlWithProtocol);\n        if (!fontData.family) {\n          setInputError(\n            __('Something went wrong, please try again.', 'web-stories')\n          );\n          return;\n        }\n      } catch (err) {\n        trackError('add_custom_font', err?.message);\n        setInputError(\n          sprintf(\n            /* translators: %s: list of allowed font types. */\n            __(\n              'Getting font data failed, please ensure the URL points directly to a %s file.',\n              'web-stories'\n            ),\n            translateToExclusiveList(ALLOWED_FONT_TYPES)\n          )\n        );\n        return;\n      }\n\n      try {\n        await addCustomFont({ ...fontData, url: urlWithProtocol });\n        setFontUrl('');\n      } catch (err) {\n        trackError('add_custom_font', err?.message);\n        setInputError(\n          sprintf(\n            /* translators: %s: font name. */\n            __('A font with the name %s already exists.', 'web-stories'),\n            fontData.family\n          )\n        );\n      }\n    }\n  }, [addCustomFont, canSave, fontUrl]);\n\n  const handleOnKeyDown = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        handleOnSave();\n      }\n    },\n    [handleOnSave]\n  );\n\n  useEffect(() => {\n    const el = currentFontsRowsRef.current[`row-${currentFontsFocusIndex}`];\n    if (el) {\n      el.focus();\n      setCurrentFontsActiveId(el.id);\n    }\n  }, [currentFontsFocusIndex]);\n\n  const isListBoxActiveRow = (index) => currentFontsFocusIndex === index;\n\n  // Handles managing the which `font row` index has focus\n  // Arrows move the index up or down by 1\n  // unless we're at the start or the end\n  // after we update the index using setCurrentFontsFocusIndex\n  // the element will get focus via the useEffect above el.focus();\n  const handleListBoxNav = useCallback(\n    (evt) => {\n      const { key } = evt;\n      if (key === 'ArrowUp') {\n        evt.preventDefault();\n        setCurrentFontsFocusIndex((index) => Math.max(0, index - 1));\n      } else if (key === 'ArrowDown') {\n        evt.preventDefault();\n        setCurrentFontsFocusIndex((index) =>\n          Math.min(customFonts.length - 1, index + 1)\n        );\n      }\n    },\n    [customFonts]\n  );\n\n  return (\n    <SettingForm onSubmit={(e) => e.preventDefault()}>\n      <div>\n        <SettingHeading as=\"h3\">{TEXT.SECTION_HEADING}</SettingHeading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.ADD_CONTEXT}\n        </SettingSubheading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.REMOVAL}\n        </SettingSubheading>\n      </div>\n      <InputsWrapper>\n        <InlineForm>\n          <SettingsTextInput\n            value={fontUrl}\n            onChange={handleUpdateFontUrl}\n            onKeyDown={handleOnKeyDown}\n            hasError={Boolean(inputError)}\n            hint={inputError}\n            label={TEXT.LABEL}\n          />\n          <AddButton\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            disabled={!canSave}\n            onClick={handleOnSave}\n          >\n            {TEXT.SUBMIT_BUTTON}\n          </AddButton>\n        </InlineForm>\n        <TextInputHelperText size={TextSize.Small}>\n          {TEXT.INPUT_CONTEXT}\n        </TextInputHelperText>\n        {customFonts?.length > 0 && (\n          <FontsWrapper>\n            <ListHeading>{TEXT.FONTS_HEADING}</ListHeading>\n            <FontsList\n              ref={currentFontsContainerRef}\n              role=\"listbox\"\n              tabIndex={0}\n              onKeyDown={handleListBoxNav}\n              aria-activedescendant={\n                // sets the active descendant for the listbox to font-${id}\n                // if a font \"row\" is selected\n                // defaults to the 1st font in the array which 'will' get focus by default\n                currentFontsActiveId ? currentFontsActiveId : customFonts[0]?.id\n              }\n            >\n              {customFonts.map(({ id, family, url }, index) => (\n                // eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/interactive-supports-focus -- keyboard handling is via the parent\n                <FontRow\n                  id={`font-${id}`}\n                  ref={\n                    (el) => (currentFontsRowsRef.current[`row-${index}`] = el) // track the active font row\n                  }\n                  key={family}\n                  role=\"option\"\n                  onClick={() => {\n                    setCurrentFontsFocusIndex(index);\n                  }}\n                  aria-selected={isListBoxActiveRow(index)}\n                >\n                  <FontData>\n                    <StyledText>{family}</StyledText>\n                    <Divider />\n                    <FontUrl>{url}</FontUrl>\n                  </FontData>\n                  <Tooltip hasTail title={__('Delete font', 'web-stories')}>\n                    <DeleteButton\n                      aria-label={sprintf(\n                        /*translators: %s: font family. */\n                        __('Delete %s', 'web-stories'),\n                        family\n                      )}\n                      type={ButtonType.Tertiary}\n                      size={ButtonSize.Small}\n                      variant={ButtonVariant.Square}\n                      onClick={() => {\n                        setToDelete(id);\n                        setShowDialog(true);\n                      }}\n                    >\n                      <Icons.Trash />\n                    </DeleteButton>\n                  </Tooltip>\n                </FontRow>\n              ))}\n            </FontsList>\n            <TextInputHelperText size={TextSize.Small}>\n              {TEXT.FONTS_CONTEXT}\n            </TextInputHelperText>\n          </FontsWrapper>\n        )}\n      </InputsWrapper>\n      {showDialog && (\n        <ConfirmationDialog\n          onClose={() => setShowDialog(false)}\n          onPrimary={handleDelete}\n        />\n      )}\n    </SettingForm>\n  );\n}\n\nCustomFontsSettings.propTypes = {\n  customFonts: PropTypes.array,\n  addCustomFont: PropTypes.func.isRequired,\n  deleteCustomFont: PropTypes.func.isRequired,\n};\n\nexport default CustomFontsSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/customFonts/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useRef, useState } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport { rawCustomFonts } from '../../dataUtils/formattedCustomFonts';\nimport CustomFontsSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/CustomFonts',\n  component: CustomFontsSettings,\n  argTypes: {\n    onSubmit: { action: 'onSubmitFired' },\n    onDelete: { action: 'onDelete fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const [addedFonts, setAddedFonts] = useState(rawCustomFonts);\n    const demoId = useRef(4);\n\n    const handleAddFont = useCallback(\n      ({ url }) => {\n        args.onSubmit(url);\n\n        // For storybook demo only.\n        const fontData = {\n          id: demoId,\n          family: `Demo font ${demoId.current}`,\n          url,\n        };\n        setAddedFonts([fontData, ...addedFonts]);\n        demoId.current = demoId.current + 1;\n      },\n      [addedFonts, args]\n    );\n\n    const deleteFont = useCallback(\n      (toDelete) => {\n        args.onDelete(toDelete);\n\n        setAddedFonts((currentFonts) => {\n          return currentFonts.filter(({ id }) => id !== toDelete);\n        });\n      },\n      [args]\n    );\n\n    return (\n      <CustomFontsSettings\n        addCustomFont={handleAddFont}\n        customFonts={addedFonts}\n        deleteCustomFont={deleteFont}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/customFonts/test/customFonts.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport CustomFontsSettings, { TEXT } from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <CustomFontsSettings />', () => {\n  it('should select font when clicked', () => {\n    renderWithProviders(\n      <CustomFontsSettings\n        customFonts={[\n          {\n            id: 609,\n            family: 'Overpass ExtraBold Italic',\n            url: 'https://example.com/overpass-extrabold-italic.ttf',\n          },\n          {\n            id: 610,\n            family: 'Overpass Regular',\n            url: 'https://example.com/overpass-regular.ttf',\n          },\n          {\n            id: 611,\n            family: 'Overpass SemiBold Italic',\n            url: 'https://example.com/overpass-semibold-italic.ttf',\n          },\n        ]}\n        addCustomFont={jest.fn}\n        deleteCustomFont={jest.fn}\n      />\n    );\n\n    const heading = screen.getByText(TEXT.SECTION_HEADING);\n    expect(heading).toBeInTheDocument();\n\n    const textContext = screen.getByText(TEXT.ADD_CONTEXT);\n    expect(textContext).toBeInTheDocument();\n\n    fireEvent.click(screen.getByText('Overpass Regular'));\n\n    const selected = screen.getByRole('option', { selected: true });\n    expect(selected.id).toBe('font-610');\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/customFonts/utils/getFontDataFromUrl.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {Object} FontMetrics font metrics.\n * @property {number} upm units per em.\n * @property {number} asc ascender.\n * @property {number} desc descender.\n * @property {number} tAsc sTypoAscender\n * @property {number} tDesc sTypoDescender.\n * @property {number} tLGap sTypoLineGap.\n * @property {number} wAsc usWinAscent.\n * @property {number} wDes usWinDescent.\n * @property {?number} xH sxHeight.\n * @property {?number} capH sCapHeight.\n * @property {number} yMin yMin.\n * @property {number} yMax yMax.\n * @property {number} hAsc ascender.\n * @property {number} hDes descender.\n * @property {number} lGap line gap.\n */\n\n/**\n * Returns font metrics for a given public font URL.\n *\n * @param {string} fontURL Public font URL.\n * @return {Object} Font data, including metrics, name.\n */\nasync function getFontDataFromUrl(fontURL) {\n  const { load } = await import(\n    /* webpackChunkName: \"chunk-opentype\" */ 'opentype.js'\n  );\n  const fontInfo = await load(fontURL);\n\n  return {\n    name: fontInfo.names.fullName.en,\n    family: fontInfo.names.fullName.en,\n    weights: [400],\n    styles: ['regular'],\n    variants: [[0, 400]],\n    service: 'custom',\n    fallbacks: ['sans-serif'],\n    metrics: {\n      upm: fontInfo.unitsPerEm,\n      asc: fontInfo.ascender,\n      des: fontInfo.descender,\n      tAsc: fontInfo.tables.os2.sTypoAscender,\n      tDes: fontInfo.tables.os2.sTypoDescender,\n      tLGap: fontInfo.tables.os2.sTypoLineGap,\n      wAsc: fontInfo.tables.os2.usWinAscent,\n      wDes: fontInfo.tables.os2.usWinDescent,\n      xH: fontInfo.tables.os2.sxHeight,\n      capH: fontInfo.tables.os2.sCapHeight,\n      yMin: fontInfo.tables.head.yMin,\n      yMax: fontInfo.tables.head.yMax,\n      hAsc: fontInfo.tables.hhea.ascender,\n      hDes: fontInfo.tables.hhea.descender,\n      lGap: fontInfo.tables.hhea.lineGap,\n    },\n  };\n}\n\nexport default getFontDataFromUrl;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/dataRemoval/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Checkbox, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  SettingForm,\n  SettingHeading,\n  CheckboxLabel,\n  CheckboxLabelText,\n} from '../components';\n\nexport default function DataRemovalSettings({\n  isEnabled = false,\n  updateSettings,\n}) {\n  const onChange = useCallback(\n    () => updateSettings({ dataRemoval: !isEnabled }),\n    [updateSettings, isEnabled]\n  );\n\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>{__('Plugin Uninstall', 'web-stories')}</SettingHeading>\n      </div>\n      <div>\n        <CheckboxLabel htmlFor=\"data-removal-settings\">\n          <Checkbox\n            id=\"data-removal-settings\"\n            data-testid=\"data-removal-settings-checkbox\"\n            onChange={onChange}\n            checked={Boolean(isEnabled)}\n          />\n          <CheckboxLabelText\n            size={TextSize.Small}\n            aria-checked={Boolean(isEnabled)}\n          >\n            {__(\n              'Remove all data including stories and saved templates when uninstalling the Web Stories plugin.',\n              'web-stories'\n            )}\n          </CheckboxLabelText>\n        </CheckboxLabel>\n      </div>\n    </SettingForm>\n  );\n}\n\nDataRemovalSettings.propTypes = {\n  isEnabled: PropTypes.bool,\n  updateSettings: PropTypes.func.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/dataRemoval/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport DataRemovalSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/DataRemovalSettings',\n  component: DataRemovalSettings,\n  args: {\n    isEnabled: true,\n  },\n  argTypes: {\n    updateSettings: { action: 'updateSettings fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <DataRemovalSettings {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/dataRemoval/test/DataRemovalSettings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport DataRemovalSettings from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <DataRemovalSettings />', () => {\n  it('should render the data removal setting as checked when isEnabled', () => {\n    renderWithProviders(\n      <DataRemovalSettings updateSettings={jest.fn()} isEnabled />\n    );\n\n    expect(screen.getByRole('checkbox')).toBeChecked();\n  });\n\n  it('should not render the data removal setting as checked when not isEnabled', () => {\n    renderWithProviders(<DataRemovalSettings updateSettings={jest.fn()} />);\n\n    expect(screen.getByRole('checkbox')).not.toBeChecked();\n  });\n\n  it('should update settings when the checkbox is clicked.', () => {\n    const onChange = jest.fn();\n    renderWithProviders(<DataRemovalSettings updateSettings={onChange} />);\n\n    const checkbox = screen.getByRole('checkbox');\n    fireEvent.click(checkbox);\n\n    expect(onChange).toHaveBeenCalledOnce();\n    expect(onChange).toHaveBeenCalledWith({ dataRemoval: true });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/dataUtils/formattedCustomFonts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const rawCustomFonts = [\n  {\n    id: 1,\n    url: 'https://font.test/font-url-1.ttf',\n    family: 'Dummy Font 1',\n  },\n  {\n    id: 2,\n    url: 'https://font.test/font-url-2.otf',\n    family: 'Dummy Font 2',\n  },\n  {\n    id: 3,\n    url: 'https://font.test/font-url-3.woff',\n    family: 'Dummy Font 3',\n  },\n];\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/dataUtils/formattedPublisherLogos.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const rawPublisherLogos = [\n  {\n    id: 577,\n    src: 'https://picsum.photos/96',\n    title: 'dummy image 1',\n    active: true,\n  },\n  {\n    id: 584,\n    src: 'https://picsum.photos/97',\n    title: 'dummy image 2',\n    active: false,\n  },\n  {\n    id: 582,\n    src: 'https://picsum.photos/98',\n    title: 'dummy image 3',\n    active: false,\n  },\n  {\n    id: 581,\n    src: 'https://picsum.photos/99',\n    title: 'dummy image 4',\n    active: false,\n  },\n];\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/editorSettings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  PageHeading,\n  Layout,\n  MIN_IMG_WIDTH,\n  MIN_IMG_HEIGHT,\n  useConfig,\n  StandardViewContentGutter,\n} from '@googleforcreators/dashboard';\nimport { preloadImage } from '@googleforcreators/media';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { useTelemetryOptIn, useMediaOptimization } from '../../effects';\nimport useApiAlerts from '../../api/hooks/useApiAlerts';\nimport AdManagement from './adManagement';\nimport PublisherLogoSettings from './publisherLogo';\nimport TelemetrySettings from './telemetry';\nimport MediaOptimizationSettings from './mediaOptimization';\nimport VideoCacheSettings from './videoCache';\nimport DataRemovalSettings from './dataRemoval';\nimport ArchiveSettings from './archive';\nimport GoogleAnalyticsSettings from './googleAnalytics';\nimport { Wrapper, Main } from './components';\nimport useEditorSettings from './useEditorSettings';\nimport CustomFontsSettings from './customFonts';\nimport Shopping from './shopping';\nimport PageAdvancement from './pageAdvancement';\n\nconst BodyViewOptionsHeader = styled.div``;\n\nfunction EditorSettings() {\n  const {\n    fetchSettings,\n    updateSettings,\n    googleAnalyticsId,\n    usingLegacyAnalytics,\n    adSensePublisherId,\n    adSenseSlotId,\n    adManagerSlotId,\n    mgidWidgetId,\n    adNetwork,\n    uploadMedia,\n    newlyCreatedMediaIds,\n    isMediaLoading,\n    videoCache,\n    dataRemoval,\n    archive,\n    archivePageId,\n    searchPages,\n    getPageById,\n    customFonts,\n    addCustomFont,\n    deleteCustomFont,\n    fetchCustomFonts,\n    publisherLogos,\n    addPublisherLogo,\n    fetchPublisherLogos,\n    removePublisherLogo,\n    setPublisherLogoAsDefault,\n    shoppingProvider,\n    shopifyHost,\n    shopifyAccessToken,\n    autoAdvance,\n    defaultPageDuration,\n    googleAnalyticsHandler,\n  } = useEditorSettings(\n    ({\n      actions: {\n        fontsApi: { addCustomFont, deleteCustomFont, fetchCustomFonts },\n        settingsApi: { fetchSettings, updateSettings },\n        pagesApi: { searchPages, getPageById },\n        mediaApi: { uploadMedia },\n        publisherLogosApi: {\n          fetchPublisherLogos,\n          addPublisherLogo,\n          removePublisherLogo,\n          setPublisherLogoAsDefault,\n        },\n      },\n      state: {\n        settings: {\n          googleAnalyticsId,\n          usingLegacyAnalytics,\n          adSensePublisherId,\n          adSenseSlotId,\n          adManagerSlotId,\n          mgidWidgetId,\n          adNetwork,\n          videoCache,\n          dataRemoval,\n          archive,\n          archivePageId,\n          shoppingProvider,\n          shopifyHost,\n          shopifyAccessToken,\n          autoAdvance,\n          defaultPageDuration,\n          googleAnalyticsHandler,\n        },\n        media: { isLoading: isMediaLoading, newlyCreatedMediaIds },\n        publisherLogos: { publisherLogos },\n        customFonts,\n      },\n    }) => ({\n      fetchSettings,\n      updateSettings,\n      googleAnalyticsId,\n      usingLegacyAnalytics,\n      adSensePublisherId,\n      adSenseSlotId,\n      adManagerSlotId,\n      mgidWidgetId,\n      adNetwork,\n      uploadMedia,\n      isMediaLoading,\n      newlyCreatedMediaIds,\n      videoCache,\n      dataRemoval,\n      archive,\n      archivePageId,\n      searchPages,\n      getPageById,\n      customFonts,\n      addCustomFont,\n      deleteCustomFont,\n      fetchCustomFonts,\n      fetchPublisherLogos,\n      addPublisherLogo,\n      removePublisherLogo,\n      setPublisherLogoAsDefault,\n      publisherLogos,\n      shoppingProvider,\n      shopifyHost,\n      shopifyAccessToken,\n      autoAdvance,\n      defaultPageDuration,\n      googleAnalyticsHandler,\n    })\n  );\n\n  const {\n    capabilities: { canUploadFiles, canManageSettings } = {},\n    plugins: { siteKit = {}, woocommerce = {} },\n    maxUpload,\n    maxUploadFormatted,\n    allowedImageMimeTypes,\n    archiveURL,\n    defaultArchiveURL,\n    vendors,\n  } = useConfig();\n\n  const {\n    disabled: disableOptedIn,\n    toggleWebStoriesTrackingOptIn,\n    optedIn,\n  } = useTelemetryOptIn();\n\n  const {\n    disabled: disableMediaOptimization,\n    toggleWebStoriesMediaOptimization,\n    mediaOptimization,\n  } = useMediaOptimization();\n\n  const [mediaError, setMediaError] = useState('');\n\n  useEffect(() => {\n    if (canManageSettings) {\n      fetchSettings();\n      fetchPublisherLogos();\n      fetchCustomFonts();\n    }\n  }, [fetchSettings, fetchPublisherLogos, canManageSettings, fetchCustomFonts]);\n\n  useEffect(() => {\n    if (newlyCreatedMediaIds.length > 0) {\n      addPublisherLogo(newlyCreatedMediaIds);\n    }\n  }, [newlyCreatedMediaIds, addPublisherLogo]);\n\n  useApiAlerts();\n\n  const handleUpdateGoogleAnalyticsId = useCallback(\n    (newGoogleAnalyticsId) =>\n      updateSettings({ googleAnalyticsId: newGoogleAnalyticsId }),\n    [updateSettings]\n  );\n\n  const handleMigrateLegacyAnalytics = useCallback(\n    () => updateSettings({ usingLegacyAnalytics: false }),\n    [updateSettings]\n  );\n\n  const handleAddLogos = useCallback(\n    async (files) => {\n      let allFileSizesWithinMaxUpload = true;\n      let allFileTypeSupported = true;\n      let errorProcessingImages = false;\n      const imagePromises = [];\n\n      files.forEach((file) => {\n        allFileSizesWithinMaxUpload =\n          allFileSizesWithinMaxUpload && file.size <= maxUpload;\n        const fileTypeSupported = allowedImageMimeTypes.includes(file.type);\n        allFileTypeSupported = allFileTypeSupported && fileTypeSupported;\n\n        if (fileTypeSupported) {\n          return;\n        }\n\n        imagePromises.push(preloadImage({ src: URL.createObjectURL(file) }));\n      });\n\n      if (!allFileSizesWithinMaxUpload) {\n        const errorText =\n          files.length === 1\n            ? sprintf(\n                /* translators: %s: max upload size for media */\n                __(\n                  'Sorry, this file is too big. Make sure your logo is under %s.',\n                  'web-stories'\n                ),\n                maxUploadFormatted\n              )\n            : sprintf(\n                /* translators: %s: max upload size for media */\n                __(\n                  'Sorry, one or more of these files are too big. Make sure your logos are all under %s.',\n                  'web-stories'\n                ),\n                maxUploadFormatted\n              );\n        return setMediaError(errorText);\n      }\n\n      if (!allFileTypeSupported) {\n        const errorText =\n          files.length === 1\n            ? __(\n                'Sorry, this file type is not supported. Only jpg, png, and static gifs are supported for publisher logos.',\n                'web-stories'\n              )\n            : __(\n                'Sorry, one or more of these files are of an unsupported file type. Only jpg, png, and static gifs are supported for publisher logos.',\n                'web-stories'\n              );\n        return setMediaError(errorText);\n      }\n\n      const images = await Promise.all(imagePromises).catch(() => {\n        errorProcessingImages = true;\n      });\n\n      if (errorProcessingImages) {\n        const errorText =\n          files.length === 1\n            ? __(\n                'Sorry, there was an error processing your upload. Please try again.',\n                'web-stories'\n              )\n            : __(\n                'Sorry, there was an error processing one or more of your uploads. Please try again.',\n                'web-stories'\n              );\n        return setMediaError(errorText);\n      }\n\n      const allFileDimensionsValid = images.every(\n        ({ height, width }) =>\n          height >= MIN_IMG_HEIGHT && width >= MIN_IMG_WIDTH\n      );\n\n      if (!allFileDimensionsValid) {\n        const errorText =\n          files.length === 1\n            ? sprintf(\n                /* translators: %s: image dimensions in pixels. */\n                __(\n                  'Sorry, this file is too small. Make sure your logo is larger than %s.',\n                  'web-stories'\n                ),\n                sprintf('%1$dx%2$dpx', MIN_IMG_WIDTH, MIN_IMG_HEIGHT)\n              )\n            : sprintf(\n                /* translators: %s: image dimensions in pixels. */\n                __(\n                  'Sorry, one or more files are too small. Make sure your logos are all larger than %s.',\n                  'web-stories'\n                ),\n                sprintf('%1$dx%2$dpx', MIN_IMG_WIDTH, MIN_IMG_HEIGHT)\n              );\n        return setMediaError(errorText);\n      }\n\n      setMediaError('');\n      return uploadMedia(files);\n    },\n    [maxUpload, maxUploadFormatted, uploadMedia, allowedImageMimeTypes]\n  );\n\n  const handleRemoveLogo = useCallback(\n    (publisherLogo) => {\n      removePublisherLogo(publisherLogo.id);\n    },\n    [removePublisherLogo]\n  );\n\n  const handleUpdateDefaultLogo = useCallback(\n    (newDefaultLogo) => setPublisherLogoAsDefault(newDefaultLogo.id),\n    [setPublisherLogoAsDefault]\n  );\n\n  const handleUpdateGoogleAnalyticsHandler = useCallback(\n    (newGoogleAnalyticsHandler) =>\n      updateSettings({ googleAnalyticsHandler: newGoogleAnalyticsHandler }),\n    [updateSettings]\n  );\n\n  return (\n    <Layout.Provider>\n      <Wrapper data-testid=\"editor-settings\">\n        <PageHeading heading={__('Settings', 'web-stories')} />\n        <StandardViewContentGutter>\n          <BodyViewOptionsHeader id=\"body-view-options-header\" />\n        </StandardViewContentGutter>\n        <Layout.Scrollable>\n          <Main>\n            {canManageSettings && (\n              <>\n                <GoogleAnalyticsSettings\n                  googleAnalyticsId={googleAnalyticsId}\n                  handleUpdateAnalyticsId={handleUpdateGoogleAnalyticsId}\n                  usingLegacyAnalytics={usingLegacyAnalytics}\n                  handleMigrateLegacyAnalytics={handleMigrateLegacyAnalytics}\n                  siteKitStatus={siteKit}\n                  googleAnalyticsHandler={googleAnalyticsHandler}\n                  handleUpdateGoogleAnalyticsHandler={\n                    handleUpdateGoogleAnalyticsHandler\n                  }\n                />\n                <PublisherLogoSettings\n                  onAddLogos={handleAddLogos}\n                  onRemoveLogo={handleRemoveLogo}\n                  onUpdateDefaultLogo={handleUpdateDefaultLogo}\n                  publisherLogos={publisherLogos}\n                  canUploadFiles={canUploadFiles}\n                  isLoading={isMediaLoading}\n                  uploadError={mediaError}\n                />\n              </>\n            )}\n            <CustomFontsSettings\n              customFonts={customFonts}\n              addCustomFont={addCustomFont}\n              deleteCustomFont={deleteCustomFont}\n            />\n            <TelemetrySettings\n              disabled={disableOptedIn}\n              onCheckboxSelected={toggleWebStoriesTrackingOptIn}\n              selected={optedIn}\n            />\n            {canUploadFiles && (\n              <MediaOptimizationSettings\n                disabled={disableMediaOptimization}\n                onCheckboxSelected={toggleWebStoriesMediaOptimization}\n                selected={mediaOptimization}\n              />\n            )}\n            {canManageSettings && (\n              <>\n                <VideoCacheSettings\n                  isEnabled={videoCache}\n                  updateSettings={updateSettings}\n                />\n                <DataRemovalSettings\n                  isEnabled={dataRemoval}\n                  updateSettings={updateSettings}\n                />\n                <ArchiveSettings\n                  archive={archive}\n                  archiveURL={archiveURL}\n                  defaultArchiveURL={defaultArchiveURL}\n                  updateSettings={updateSettings}\n                  searchPages={searchPages}\n                  archivePageId={archivePageId}\n                  getPageById={getPageById}\n                />\n                <AdManagement\n                  updateSettings={updateSettings}\n                  adNetwork={adNetwork}\n                  publisherId={adSensePublisherId}\n                  adSenseSlotId={adSenseSlotId}\n                  adManagerSlotId={adManagerSlotId}\n                  mgidWidgetId={mgidWidgetId}\n                  siteKitStatus={siteKit}\n                />\n                <Shopping\n                  updateSettings={updateSettings}\n                  shoppingProvider={shoppingProvider}\n                  shopifyHost={shopifyHost}\n                  shopifyAccessToken={shopifyAccessToken}\n                  vendors={vendors}\n                  woocommerce={woocommerce}\n                />\n                <PageAdvancement\n                  updateSettings={updateSettings}\n                  autoAdvance={autoAdvance}\n                  defaultPageDuration={defaultPageDuration}\n                />\n              </>\n            )}\n          </Main>\n        </Layout.Scrollable>\n      </Wrapper>\n    </Layout.Provider>\n  );\n}\n\nexport default EditorSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/editorSettingsProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport useUsersApi from '../../api/hooks/useUserApi';\nimport useMediaApi from '../../api/hooks/useMediaApi';\nimport useSettingsApi from '../../api/hooks/useSettingsApi';\nimport usePagesApi from '../../api/hooks/usePagesApi';\nimport usePublisherLogosApi from '../../api/hooks/usePublisherLogosApi';\nimport useFontsApi from '../../api/hooks/useFontsApi';\nimport Context from './context';\n\nfunction EditorSettingsProvider({ children }) {\n  const { customFonts, api: fontsApi } = useFontsApi();\n  const { currentUser, api: usersApi } = useUsersApi();\n  const { media, api: mediaApi } = useMediaApi();\n  const { settings, api: settingsApi } = useSettingsApi();\n  const { api: pagesApi } = usePagesApi();\n  const { publisherLogos, api: publisherLogosApi } = usePublisherLogosApi();\n\n  const state = {\n    state: {\n      media,\n      settings,\n      currentUser,\n      customFonts,\n      publisherLogos,\n    },\n    actions: {\n      fontsApi,\n      mediaApi,\n      settingsApi,\n      usersApi,\n      pagesApi,\n      publisherLogosApi,\n    },\n  };\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nEditorSettingsProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default EditorSettingsProvider;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/googleAnalytics/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useState,\n  useCallback,\n  useEffect,\n  useMemo,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\nimport {\n  ButtonSize,\n  ButtonType,\n  TextSize,\n  NotificationBubble,\n  Icons,\n  Text,\n  Link,\n  DropDown,\n} from '@googleforcreators/design-system';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport { validateGoogleAnalyticsIdFormat } from '../utils';\nimport {\n  InlineForm,\n  InlineLink,\n  SaveButton,\n  SettingForm,\n  SettingHeading,\n  SettingsTextInput,\n  SettingSubheading,\n  TextInputHelperText,\n  VisuallyHiddenLabel,\n} from '../components';\nimport { GOOGLE_ANALYTICS_HANDLER_TYPE } from '../../../constants/settings';\n\nconst StyledNotificationBubble = styled(NotificationBubble)`\n  display: inline-block;\n  margin-left: 10px;\n`;\n\nexport const TEXT = {\n  CONTEXT: __(\n    'The story editor will append a default, configurable AMP analytics configuration to your story. If you’re interested in going beyond what the default configuration, read this <a>article</a>.',\n    'web-stories'\n  ),\n  CONTEXT_LINK:\n    'https://blog.amp.dev/2019/08/28/analytics-for-your-amp-stories/',\n  SECTION_HEADING: __('Google Analytics', 'web-stories'),\n  PLACEHOLDER: __('Enter your Google Analytics Measurement ID', 'web-stories'),\n  ARIA_LABEL: __('Enter your Google Analytics Measurement ID', 'web-stories'),\n  INPUT_ERROR: __('Invalid ID format', 'web-stories'),\n  SUBMIT_BUTTON: __('Save', 'web-stories'),\n  SITE_KIT_NOT_INSTALLED: __(\n    'Install <a>Site Kit by Google</a> to easily enable Google Analytics for Web Stories.',\n    'web-stories'\n  ),\n  SITE_KIT_INSTALLED: __(\n    'Use Site Kit by Google to easily<a>activate Google Analytics</a> for Web Stories.',\n    'web-stories'\n  ),\n  SITE_KIT_IN_USE: __(\n    '<b>Note: </b>If Site Kit is active, it will be used to set up Google Analytics by default. However, you can customize the behavior in case you need more flexibility.',\n    'web-stories'\n  ),\n  ANALYTICS_DROPDOWN_LABEL: __('Analytics Type', 'web-stories'),\n  ANALYTICS_DROPDOWN_PLACEHOLDER: __('Select Analytics Type', 'web-stories'),\n};\n\nexport const ANALYTICS_DROPDOWN_OPTIONS = [\n  {\n    value: GOOGLE_ANALYTICS_HANDLER_TYPE.SITE_KIT,\n    label: __('Use Site Kit for analytics (default)', 'web-stories'),\n  },\n  {\n    value: GOOGLE_ANALYTICS_HANDLER_TYPE.WEB_STORIES,\n    label: __('Use only Web Stories for analytics', 'web-stories'),\n  },\n  {\n    value: GOOGLE_ANALYTICS_HANDLER_TYPE.BOTH,\n    label: __('Use both', 'web-stories'),\n  },\n];\n\nconst DropdownContainer = styled.div`\n  padding-top: 12px;\n`;\n\nconst WarningContainer = styled.div`\n  display: flex;\n  gap: 8px;\n  margin: 14px auto;\n  border: 1px solid ${({ theme }) => theme.colors.border.defaultNormal};\n  border-radius: ${({ theme }) => theme.borders.radius.small};\n  padding: 8px;\n`;\n\nconst WarningIcon = styled(Icons.ExclamationOutline)`\n  width: 32px;\n  height: 100%;\n  color: ${({ theme }) => theme.colors.status.warning};\n`;\n\nconst Message = styled(Text.Paragraph).attrs({\n  size: TextSize.Small,\n})`\n  max-width: calc(100% - 40px);\n`;\n\nfunction GoogleAnalyticsSettings({\n  googleAnalyticsId,\n  handleUpdateAnalyticsId,\n  usingLegacyAnalytics,\n  handleMigrateLegacyAnalytics,\n  siteKitStatus = {},\n  googleAnalyticsHandler,\n  handleUpdateGoogleAnalyticsHandler,\n}) {\n  const [analyticsId, setAnalyticsId] = useState(googleAnalyticsId);\n  const [analyticsHandler, setAnalyticsHandler] = useState(\n    googleAnalyticsHandler\n  );\n  const [inputError, setInputError] = useState('');\n  const canSave = analyticsId !== googleAnalyticsId && !inputError;\n  const disableSaveButton = !canSave;\n\n  const { analyticsActive, installed, analyticsLink } = siteKitStatus;\n\n  useEffect(() => {\n    setAnalyticsId(googleAnalyticsId);\n  }, [googleAnalyticsId]);\n\n  useEffect(() => {\n    setAnalyticsHandler(googleAnalyticsHandler);\n  }, [googleAnalyticsHandler]);\n\n  const onUpdateAnalyticsId = useCallback((event) => {\n    const { value } = event.target;\n    setAnalyticsId(value);\n\n    if (value.length === 0 || validateGoogleAnalyticsIdFormat(value)) {\n      setInputError('');\n\n      return;\n    }\n\n    setInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onUpdateAnalyticsHandler = useCallback(\n    (value) => {\n      setAnalyticsHandler(value);\n      handleUpdateGoogleAnalyticsHandler(value);\n    },\n    [handleUpdateGoogleAnalyticsHandler]\n  );\n\n  const handleOnSave = useCallback(() => {\n    if (canSave) {\n      handleUpdateAnalyticsId(analyticsId);\n    }\n  }, [canSave, analyticsId, handleUpdateAnalyticsId]);\n\n  const handleOnKeyDown = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        handleOnSave();\n      }\n    },\n    [handleOnSave]\n  );\n\n  const handleAnalyticsMigration = useCallback(\n    (evt) => {\n      evt.preventDefault();\n      handleMigrateLegacyAnalytics();\n      trackEvent('migrate_story_auto_analytics');\n    },\n    [handleMigrateLegacyAnalytics]\n  );\n\n  const onAutoAnalyticsClick = useCallback(\n    (evt) => trackClick(evt, 'click_auto_analytics_link'),\n    []\n  );\n\n  const onSiteKitClick = useCallback(\n    (evt) => trackClick(evt, 'click_site_kit_link'),\n    []\n  );\n\n  const onContextClick = useCallback(\n    (evt) => trackClick(evt, 'click_analytics_docs'),\n    []\n  );\n\n  const siteKitDisplayText = useMemo(() => {\n    if (analyticsActive) {\n      return null;\n    }\n\n    return (\n      <TranslateWithMarkup\n        mapping={{\n          a: (\n            <InlineLink\n              href={analyticsLink}\n              rel=\"noreferrer\"\n              target=\"_blank\"\n              size={TextSize.Small}\n              onClick={onSiteKitClick}\n            />\n          ),\n        }}\n      >\n        {installed ? TEXT.SITE_KIT_INSTALLED : TEXT.SITE_KIT_NOT_INSTALLED}\n      </TranslateWithMarkup>\n    );\n  }, [analyticsActive, installed, analyticsLink, onSiteKitClick]);\n\n  return (\n    <SettingForm onSubmit={(e) => e.preventDefault()}>\n      <div>\n        <SettingHeading htmlFor=\"gaTrackingID\" as=\"h3\">\n          {TEXT.SECTION_HEADING}\n          {usingLegacyAnalytics && (\n            <StyledNotificationBubble notificationCount={1} isSmall />\n          )}\n        </SettingHeading>\n        <SettingSubheading size={TextSize.Small}>\n          {siteKitDisplayText}\n        </SettingSubheading>\n        {usingLegacyAnalytics && (\n          <>\n            <SettingSubheading size={TextSize.Small}>\n              <TranslateWithMarkup\n                mapping={{\n                  a: (\n                    <InlineLink\n                      href=\"https://wp.stories.google/docs/seo/\"\n                      rel=\"noreferrer\"\n                      target=\"_blank\"\n                      size={TextSize.Small}\n                      onClick={onAutoAnalyticsClick}\n                    />\n                  ),\n                }}\n              >\n                {__(\n                  'An improved analytics configuration is now available. <a>Learn more</a>.',\n                  'web-stories'\n                )}\n              </TranslateWithMarkup>\n            </SettingSubheading>\n            <SettingSubheading size={TextSize.Small}>\n              <SaveButton\n                type={ButtonType.Secondary}\n                size={ButtonSize.Small}\n                onClick={handleAnalyticsMigration}\n              >\n                {__('Migrate', 'web-stories')}\n              </SaveButton>\n            </SettingSubheading>\n          </>\n        )}\n      </div>\n      <div>\n        <InlineForm>\n          <VisuallyHiddenLabel htmlFor=\"gaTrackingId\">\n            {TEXT.ARIA_LABEL}\n          </VisuallyHiddenLabel>\n          <SettingsTextInput\n            aria-label={TEXT.ARIA_LABEL}\n            id=\"gaTrackingId\"\n            value={analyticsId}\n            onChange={onUpdateAnalyticsId}\n            onKeyDown={handleOnKeyDown}\n            placeholder={TEXT.PLACEHOLDER}\n            hasError={Boolean(inputError)}\n            hint={inputError}\n          />\n          <SaveButton\n            type={ButtonType.Secondary}\n            size={ButtonSize.Small}\n            disabled={disableSaveButton}\n            onClick={handleOnSave}\n          >\n            {TEXT.SUBMIT_BUTTON}\n          </SaveButton>\n        </InlineForm>\n        <TextInputHelperText size={TextSize.Small}>\n          <TranslateWithMarkup\n            mapping={{\n              a: (\n                <InlineLink\n                  href={TEXT.CONTEXT_LINK}\n                  rel=\"noreferrer\"\n                  target=\"_blank\"\n                  size={TextSize.Small}\n                  onClick={onContextClick}\n                />\n              ),\n            }}\n          >\n            {TEXT.CONTEXT}\n          </TranslateWithMarkup>\n        </TextInputHelperText>\n        {analyticsActive && (\n          <>\n            <TextInputHelperText size={TextSize.Small}>\n              <TranslateWithMarkup>{TEXT.SITE_KIT_IN_USE}</TranslateWithMarkup>\n            </TextInputHelperText>\n            <DropdownContainer>\n              <DropDown\n                id=\"analyticsType\"\n                ariaLabel={TEXT.ANALYTICS_DROPDOWN_LABEL}\n                placeholder={TEXT.ANALYTICS_DROPDOWN_PLACEHOLDER}\n                options={ANALYTICS_DROPDOWN_OPTIONS}\n                onMenuItemClick={(_, newValue) => {\n                  onUpdateAnalyticsHandler(newValue);\n                }}\n                selectedValue={analyticsHandler}\n              />\n            </DropdownContainer>\n          </>\n        )}\n        {googleAnalyticsId.startsWith('UA-') ? (\n          <WarningContainer>\n            <WarningIcon aria-hidden />\n            <Message>\n              <TranslateWithMarkup\n                mapping={{\n                  a: (\n                    <Link\n                      href={__(\n                        'https://support.google.com/analytics/answer/11583528?hl=en',\n                        'web-stories'\n                      )}\n                      rel=\"noreferrer\"\n                      target=\"_blank\"\n                      size={TextSize.Small}\n                      onClick={(evt) =>\n                        trackClick(evt, 'click_ua_deprecation_docs')\n                      }\n                    />\n                  ),\n                  a2: (\n                    <Link\n                      href={__(\n                        'https://support.google.com/analytics/answer/10089681?hl=en',\n                        'web-stories'\n                      )}\n                      rel=\"noreferrer\"\n                      target=\"_blank\"\n                      size={TextSize.Small}\n                      onClick={(evt) => trackClick(evt, 'click_ga4_docs')}\n                    />\n                  ),\n                }}\n              >\n                {__(\n                  'Universal Analytics <a>stopped processing new visits</a> starting <b>July 1, 2023</b>. We recommend switching to <a2>Google Analytics 4</a2> (GA4).',\n                  'web-stories'\n                )}\n              </TranslateWithMarkup>\n            </Message>\n          </WarningContainer>\n        ) : null}\n      </div>\n    </SettingForm>\n  );\n}\n\nGoogleAnalyticsSettings.propTypes = {\n  googleAnalyticsId: PropTypes.string,\n  handleUpdateAnalyticsId: PropTypes.func,\n  usingLegacyAnalytics: PropTypes.bool,\n  handleMigrateLegacyAnalytics: PropTypes.func,\n  siteKitStatus: PropTypes.shape({\n    installed: PropTypes.bool,\n    active: PropTypes.bool,\n    adsenseActive: PropTypes.bool,\n    analyticsActive: PropTypes.bool,\n    analyticsLink: PropTypes.string,\n  }),\n  googleAnalyticsHandler: PropTypes.string,\n  handleUpdateGoogleAnalyticsHandler: PropTypes.func,\n};\n\nexport default GoogleAnalyticsSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/googleAnalytics/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport GoogleAnalyticsSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/GoogleAnalytics',\n  component: GoogleAnalyticsSettings,\n  args: {\n    googleAnalyticsId: 'UA-000000-98',\n    installed: false,\n    active: false,\n    analyticsActive: false,\n    analyticsLink: '',\n  },\n  argTypes: {\n    onUpdateGoogleAnalyticsId: {\n      action: 'update google analytics id submitted',\n    },\n    handleUpdateAnalyticsId: { action: 'handleUpdateAnalyticsId' },\n  },\n  parameters: {\n    controls: {\n      exclude: [\n        'siteKitStatus',\n        'usingLegacyAnalytics',\n        'handleMigrateLegacyAnalytics',\n      ],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return (\n      <GoogleAnalyticsSettings\n        siteKitStatus={{\n          installed: args.installed,\n          active: args.active,\n          analyticsActive: args.analyticsActive,\n          analyticsLink: args.analyticsLink,\n        }}\n        {...args}\n      />\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/googleAnalytics/test/googleAnalytics.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport GoogleAnalyticsSettings, { TEXT, ANALYTICS_DROPDOWN_OPTIONS } from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\nconst SITE_KIT_MESSAGE = TEXT.SITE_KIT_IN_USE.replace('<b>Note: </b>', '');\n\ndescribe('Editor Settings: Google Analytics <GoogleAnalytics />', () => {\n  let googleAnalyticsId;\n  let mockUpdate;\n  let mockHandleUpdateGoogleAnalyticsHandler;\n  const defaultSiteKitStatus = {\n    installed: false,\n    analyticsActive: false,\n    active: false,\n  };\n\n  beforeEach(() => {\n    googleAnalyticsId = '';\n    mockUpdate = jest.fn((id) => {\n      googleAnalyticsId = id;\n    });\n    mockHandleUpdateGoogleAnalyticsHandler = jest.fn();\n  });\n\n  afterEach(() => {\n    googleAnalyticsId = '';\n  });\n\n  it('should render Google Analytics input and helper text by default', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    expect(input).toBeInTheDocument();\n    expect(input).toBeEnabled();\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n  });\n\n  it('should render a visually hidden label for Google Analytics input', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const label = screen.getByLabelText(TEXT.ARIA_LABEL);\n    expect(label).toBeInTheDocument();\n  });\n\n  it('should display input field when analytics module is active', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={{\n          ...defaultSiteKitStatus,\n          active: true,\n          analyticsActive: true,\n        }}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const input = screen.queryByRole('textbox');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should display analytics type dropdown when analytics module is active', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={{\n          ...defaultSiteKitStatus,\n          active: true,\n          analyticsActive: true,\n        }}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const dropdown = screen.getByLabelText(TEXT.ANALYTICS_DROPDOWN_LABEL);\n    expect(dropdown).toBeInTheDocument();\n  });\n\n  it('should call mockUpdate when enter is keyed on input', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n\n    fireEvent.change(input, { target: { value: 'UA-098754-33' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated googleAnalyticsId prop\n    rerender(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    // rerender to get updated googleAnalyticsId prop\n    rerender(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n\n  it('should call mockUpdate when the save button is clicked', () => {\n    const { rerender } = renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    const input = screen.getByRole('textbox');\n    const button = screen.getByRole('button');\n\n    fireEvent.change(input, { target: { value: 'UA-098754-33' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated googleAnalyticsId prop\n    rerender(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledOnce();\n\n    fireEvent.change(input, { target: { value: '' } });\n\n    fireEvent.click(button);\n\n    // rerender to get updated googleAnalyticsId prop\n    rerender(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={defaultSiteKitStatus}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n\n    fireEvent.change(input, { target: { value: 'NOT A VALID ID!!!' } });\n\n    fireEvent.click(button);\n\n    expect(mockUpdate).toHaveBeenCalledTimes(2);\n  });\n\n  it('should display Site Kit message when analytics module is active', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={{\n          ...defaultSiteKitStatus,\n          active: true,\n          analyticsActive: true,\n        }}\n        usingLegacyAnalytics={false}\n      />\n    );\n\n    expect(screen.getByText(SITE_KIT_MESSAGE)).toBeInTheDocument();\n  });\n\n  it('should call handleUpdateGoogleAnalyticsHandler when the dropdown value changes', () => {\n    renderWithProviders(\n      <GoogleAnalyticsSettings\n        googleAnalyticsId={googleAnalyticsId}\n        handleUpdateAnalyticsId={mockUpdate}\n        siteKitStatus={{\n          ...defaultSiteKitStatus,\n          analyticsActive: true,\n        }}\n        usingLegacyAnalytics={false}\n        handleUpdateGoogleAnalyticsHandler={\n          mockHandleUpdateGoogleAnalyticsHandler\n        }\n      />\n    );\n\n    const dropdown = screen.getByLabelText(TEXT.ANALYTICS_DROPDOWN_LABEL);\n    fireEvent.click(dropdown);\n\n    ANALYTICS_DROPDOWN_OPTIONS.forEach((option) => {\n      const optionElement = screen.getByText(option.label);\n      fireEvent.click(optionElement);\n      expect(mockHandleUpdateGoogleAnalyticsHandler).toHaveBeenCalledWith(\n        option.value\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as EditorSettings } from './editorSettings';\nexport { default as EditorSettingsProvider } from './editorSettingsProvider';\nexport { default as useEditorSettings } from './useEditorSettings';\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/mediaOptimization/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport propTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport { Checkbox, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  SettingForm,\n  SettingHeading,\n  CheckboxLabel,\n  CheckboxLabelText,\n} from '../components';\n\nexport default function MediaOptimizationSettings({\n  selected,\n  onCheckboxSelected,\n  disabled,\n}) {\n  const mediaOptimizationId = useMemo(\n    () => `media-optimization-${uuidv4()}`,\n    []\n  );\n\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>\n          {__('Video Optimization', 'web-stories')}\n        </SettingHeading>\n      </div>\n      <div>\n        <CheckboxLabel htmlFor={mediaOptimizationId}>\n          <Checkbox\n            id={mediaOptimizationId}\n            data-testid=\"media-optimization-settings-checkbox\"\n            disabled={disabled}\n            onChange={onCheckboxSelected}\n            checked={Boolean(selected)}\n          />\n          <CheckboxLabelText\n            size={TextSize.Small}\n            aria-checked={Boolean(selected)}\n          >\n            {__(\n              'Automatically optimize videos used in Web Stories. We recommend enabling this feature. Video files that are too large or have an unsupported format (like .mov) will otherwise not display properly.',\n              'web-stories'\n            )}\n          </CheckboxLabelText>\n        </CheckboxLabel>\n      </div>\n    </SettingForm>\n  );\n}\n\nMediaOptimizationSettings.propTypes = {\n  disabled: propTypes.bool.isRequired,\n  selected: propTypes.bool.isRequired,\n  onCheckboxSelected: propTypes.func.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/mediaOptimization/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport MediaOptimizationSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/MediaOptimization',\n  component: MediaOptimizationSettings,\n  args: {\n    disabled: false,\n    selected: true,\n  },\n  argTypes: {\n    onCheckboxSelected: { action: 'onCheckboxSelected fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <MediaOptimizationSettings {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/mediaOptimization/test/mediaOptimizationSettings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport MediaOptimizationSettings from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <MediaOptimizationSettings />', () => {\n  it('should render the media optimization as checked when selected is true.', () => {\n    renderWithProviders(\n      <MediaOptimizationSettings\n        disabled={false}\n        onCheckboxSelected={jest.fn()}\n        selected\n      />\n    );\n\n    expect(screen.getByRole('checkbox')).toBeChecked();\n  });\n\n  it('should render the media optimization as not checked when selected is false.', () => {\n    renderWithProviders(\n      <MediaOptimizationSettings\n        disabled={false}\n        onCheckboxSelected={jest.fn()}\n        selected={false}\n      />\n    );\n\n    expect(screen.getByRole('checkbox')).not.toBeChecked();\n  });\n\n  it('should call the change function when the checkbox is clicked.', () => {\n    const changeFn = jest.fn();\n    renderWithProviders(\n      <MediaOptimizationSettings\n        disabled={false}\n        onCheckboxSelected={changeFn}\n        selected={false}\n      />\n    );\n\n    const checkbox = screen.getByRole('checkbox');\n    fireEvent.click(checkbox);\n\n    expect(changeFn).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/pageAdvancement/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __, _n, sprintf } from '@googleforcreators/i18n';\nimport {\n  TextSize,\n  NumericInput,\n  Switch,\n} from '@googleforcreators/design-system';\nimport PropTypes from 'prop-types';\n\nimport styled from 'styled-components';\nimport { trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineForm,\n  MultilineForm,\n  SettingHeading,\n  SettingSubheading,\n  TextInputHelperText,\n} from '../components';\n\nconst MIN_MAX = {\n  PAGE_DURATION: {\n    MIN: 1,\n    MAX: 20,\n  },\n};\n\nexport const TEXT = {\n  CONTEXT: __(\n    'All new stories will be set to this page advancement setting. Control whether a story auto-advances between pages, or whether the reader has to manually tap to advance.',\n    'web-stories'\n  ),\n  SECTION_HEADING: __('Default Page Advancement', 'web-stories'),\n  LABEL_AUTO: __('Auto', 'web-stories'),\n  LABEL_MANUAL: __('Manual', 'web-stories'),\n  SWITCH_LABEL: __('Page Advancement', 'web-stories'),\n  INPUT_LABEL: __('Default page duration in seconds', 'web-stories'),\n  INPUT_SUFFIX: __('Duration', 'web-stories'),\n  INPUT_HELPER: sprintf(\n    /* translators: 1: minimum duration. 2: maximum duration. */\n    _n(\n      'Duration between %1$d and %2$d second.',\n      'Duration between %1$d and %2$d seconds.',\n      MIN_MAX.PAGE_DURATION.MAX,\n      'web-stories'\n    ),\n    MIN_MAX.PAGE_DURATION.MIN,\n    MIN_MAX.PAGE_DURATION.MAX\n  ),\n};\n\nconst InputsWrapper = styled.div`\n  margin-top: 8px;\n`;\n\nconst StyledSwitch = styled(Switch)`\n  width: 186px;\n`;\n\nfunction PageAdvancementSettings({\n  updateSettings,\n  autoAdvance,\n  defaultPageDuration,\n}) {\n  // Track the value locally to display it to the user visually right away, otherwise it looks broken.\n  const [_autoAdvance, _setAutoAdvance] = useState(autoAdvance);\n\n  const onAdvanceChange = useCallback(() => {\n    trackEvent('change_auto_advance', {\n      value: !autoAdvance,\n    });\n    _setAutoAdvance(!autoAdvance);\n    updateSettings({ autoAdvance: !autoAdvance });\n  }, [autoAdvance, updateSettings]);\n\n  useEffect(() => {\n    _setAutoAdvance(autoAdvance);\n  }, [autoAdvance]);\n\n  const onDurationChange = useCallback(\n    (_, newDuration) => {\n      updateSettings({ defaultPageDuration: newDuration });\n      trackEvent('change_default_page_duration', {\n        value: newDuration,\n      });\n    },\n    [updateSettings]\n  );\n\n  return (\n    <MultilineForm onSubmit={(e) => e.preventDefault()}>\n      <div>\n        <SettingHeading as=\"h3\">{TEXT.SECTION_HEADING}</SettingHeading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.CONTEXT}\n        </SettingSubheading>\n      </div>\n      <InputsWrapper>\n        <InlineForm>\n          <StyledSwitch\n            groupLabel={TEXT.SWITCH_LABEL}\n            name=\"page-advancement-switch\"\n            value={_autoAdvance}\n            onLabel={TEXT.LABEL_AUTO}\n            offLabel={TEXT.LABEL_MANUAL}\n            onChange={onAdvanceChange}\n            darkTheme={false}\n          />\n        </InlineForm>\n        {_autoAdvance && (\n          <>\n            <InlineForm>\n              <NumericInput\n                unit={` ${__('seconds', 'web-stories')}`}\n                suffix={TEXT.INPUT_SUFFIX}\n                value={defaultPageDuration}\n                onChange={onDurationChange}\n                aria-label={TEXT.INPUT_SUFFIX}\n                min={MIN_MAX.PAGE_DURATION.MIN}\n                max={MIN_MAX.PAGE_DURATION.MAX}\n              />\n            </InlineForm>\n            <TextInputHelperText size={TextSize.Small}>\n              {TEXT.INPUT_HELPER}\n            </TextInputHelperText>\n          </>\n        )}\n      </InputsWrapper>\n    </MultilineForm>\n  );\n}\n\nPageAdvancementSettings.propTypes = {\n  updateSettings: PropTypes.func.isRequired,\n  autoAdvance: PropTypes.bool.isRequired,\n  defaultPageDuration: PropTypes.number.isRequired,\n};\n\nexport default PageAdvancementSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/pageAdvancement/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PageAdvancementSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/PageAdvancementSettings',\n  component: PageAdvancementSettings,\n  args: {\n    autoAdvance: true,\n    defaultPageDuration: 15,\n  },\n  argTypes: {\n    updateSettings: { action: 'updateSettings fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <PageAdvancementSettings {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/pageAdvancement/test/pageAdvancement.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport PageAdvancementSetting from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <PageAdvancementSetting />', () => {\n  it('should render the only the advancement setting when auto-advance is false', () => {\n    renderWithProviders(\n      <PageAdvancementSetting\n        updateSettings={jest.fn()}\n        autoAdvance={false}\n        defaultPageDuration={1}\n      />\n    );\n\n    const radioGroup = screen.queryByRole('radiogroup');\n    expect(radioGroup).toBeInTheDocument();\n\n    const input = screen.queryByRole('textbox');\n    expect(input).not.toBeInTheDocument();\n  });\n\n  it('should not render the page duration setting when auto-advance is true', () => {\n    renderWithProviders(\n      <PageAdvancementSetting\n        updateSettings={jest.fn()}\n        autoAdvance\n        defaultPageDuration={1}\n      />\n    );\n\n    const input = screen.queryByRole('textbox');\n    expect(input).toBeInTheDocument();\n  });\n\n  it('should update auto-advance setting', () => {\n    const onChange = jest.fn();\n    renderWithProviders(\n      <PageAdvancementSetting\n        updateSettings={onChange}\n        autoAdvance\n        defaultPageDuration={1}\n      />\n    );\n\n    const switchButton = screen.queryByLabelText('Manual');\n    fireEvent.click(switchButton);\n\n    expect(onChange).toHaveBeenCalledExactlyOnceWith({ autoAdvance: false });\n  });\n\n  it('should update page duration setting', () => {\n    const onChange = jest.fn();\n    renderWithProviders(\n      <PageAdvancementSetting\n        updateSettings={onChange}\n        autoAdvance\n        defaultPageDuration={1}\n      />\n    );\n\n    const input = screen.getByLabelText('Duration');\n    fireEvent.click(input);\n    fireEvent.change(input, { target: { value: '5' } });\n    fireEvent.blur(input);\n\n    expect(onChange).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/publisherLogo/gridItem.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { forwardRef } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport { TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  CenterMutedText,\n  GridItemButton,\n  GridItemContainer,\n  Logo,\n} from '../components';\nimport PopoverLogoContextMenu, {\n  PopoverLogoContextMenuPropTypes,\n} from './popoverLogoContextMenu';\n\nexport const GridItem = forwardRef(\n  (\n    {\n      contextMenuId,\n      index,\n      onMenuItemToggle,\n      onRemoveLogo,\n      onUpdateDefaultLogo,\n      publisherLogo,\n      setFocusedPublisherLogoId,\n      showLogoContextMenu,\n      isFocused,\n    },\n    ref\n  ) => {\n    const items = [\n      {\n        label: __('Set as Default', 'web-stories'),\n        onClick: (ev) => {\n          ev.preventDefault();\n          onUpdateDefaultLogo(publisherLogo);\n        },\n        disabled: publisherLogo.active,\n      },\n      {\n        label: __('Delete', 'web-stories'),\n        onClick: (ev) => {\n          ev.preventDefault();\n          onRemoveLogo(publisherLogo, index);\n        },\n      },\n    ];\n\n    return (\n      <GridItemContainer\n        ref={ref}\n        role=\"listitem\"\n        active={publisherLogo.active}\n        data-testid={`publisher-logo-${index}`}\n      >\n        <GridItemButton\n          onFocus={() => {\n            setFocusedPublisherLogoId(publisherLogo.id);\n          }}\n          data-testid={`uploaded-publisher-logo-${index}`}\n          isSelected={isFocused}\n          tabIndex={isFocused ? 0 : -1}\n          onClick={(e) => {\n            e.preventDefault();\n            setFocusedPublisherLogoId(publisherLogo.id);\n          }}\n          aria-label={sprintf(\n            /* translators: %s: logo title.*/\n            __('Publisher Logo %s', 'web-stories'),\n            publisherLogo.title\n          )}\n        >\n          <Logo src={publisherLogo.url} alt={publisherLogo.title} />\n        </GridItemButton>\n        {publisherLogo.active && (\n          <CenterMutedText size={TextSize.XSmall}>\n            {__('Default', 'web-stories')}\n          </CenterMutedText>\n        )}\n        {showLogoContextMenu && (\n          <PopoverLogoContextMenu\n            isActive={isFocused}\n            idx={index}\n            items={items}\n            publisherLogo={publisherLogo}\n            onMenuItemToggle={onMenuItemToggle}\n            contextMenuId={contextMenuId}\n          />\n        )}\n      </GridItemContainer>\n    );\n  }\n);\nGridItem.propTypes = {\n  contextMenuId: PopoverLogoContextMenuPropTypes.contextMenuId,\n  index: PopoverLogoContextMenuPropTypes.idx,\n  onMenuItemToggle: PopoverLogoContextMenuPropTypes.onMenuItemToggle,\n  onRemoveLogo: PropTypes.func.isRequired,\n  onUpdateDefaultLogo: PropTypes.func.isRequired,\n  publisherLogo: PopoverLogoContextMenuPropTypes.publisherLogo,\n  setFocusedPublisherLogoId: PropTypes.func.isRequired,\n  showLogoContextMenu: PropTypes.bool,\n  isFocused: PropTypes.bool,\n};\nGridItem.displayName = 'GridItem';\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/publisherLogo/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { useGridViewKeys, TextSize } from '@googleforcreators/design-system';\nimport { FileUpload, useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  Error,\n  SettingForm,\n  SettingSubheading,\n  UploadedContainer,\n  SettingHeading,\n} from '../components';\nimport { GridItem } from './gridItem';\nimport { PopoverLogoContextMenuPropTypes } from './popoverLogoContextMenu';\n\nexport const TEXT = {\n  SECTION_HEADING: __('Publisher Logo', 'web-stories'),\n  UPLOAD_CONTEXT: __(\n    'Upload your logos here and they will become available to any stories you create.',\n    'web-stories'\n  ),\n  CLICK_CONTEXT: __(\n    'Click on logo to set as default if you want that logo to be used on default logo for all your stories.',\n    'web-stories'\n  ),\n  REMOVAL: __(\n    \"Removing a logo from your settings won't remove it from any stories using that logo.\",\n    'web-stories'\n  ),\n  INSTRUCTIONS: __(\n    'Avoid vector files, such as svg or eps. Logos should be at least 96x96 pixels and a perfect square. The background should not be transparent.',\n    'web-stories'\n  ),\n  SUBMIT: __('Upload logo', 'web-stories'),\n  ARIA_LABEL: __('Click to upload a new logo', 'web-stories'),\n  HELPER_UPLOAD: __(\n    'Drag a jpg, png, or static gif in this box. Or click “Upload logo” below.',\n    'web-stories'\n  ),\n};\n\nfunction PublisherLogoSettings({\n  canUploadFiles,\n  onAddLogos,\n  onRemoveLogo,\n  onUpdateDefaultLogo,\n  isLoading,\n  publisherLogos,\n  uploadError,\n}) {\n  const { isRTL, allowedImageMimeTypes } = useConfig();\n\n  const containerRef = useRef();\n  const gridRef = useRef();\n  const itemsRef = useRef({});\n\n  const [focusedPublisherLogoId, setFocusedPublisherLogoId] = useState(null);\n\n  const [indexRemoved, setIndexRemoved] = useState(null);\n\n  const [contextMenuId, setContextMenuId] = useState(null);\n\n  const hasOnlyOneLogo = publisherLogos.length === 1;\n\n  const publisherLogoCountRef = useRef(publisherLogos.length);\n\n  const handleRemoveLogoClick = useCallback(\n    (publisherLogo, idx) => {\n      setContextMenuId(-1);\n      onRemoveLogo?.(publisherLogo);\n      setIndexRemoved(idx);\n      publisherLogoCountRef.current = publisherLogos.length;\n    },\n    [onRemoveLogo, publisherLogos.length]\n  );\n\n  const handleUpdateDefaultLogo = useCallback(\n    (publisherLogo) => {\n      setContextMenuId(-1);\n      onUpdateDefaultLogo?.(publisherLogo);\n    },\n    [onUpdateDefaultLogo]\n  );\n\n  // Update publisher logo focus when logo is removed\n  useEffect(() => {\n    if (\n      Boolean(indexRemoved?.toString()) &&\n      publisherLogos.length !== publisherLogoCountRef.current\n    ) {\n      if (publisherLogos.length === 0) {\n        // if the user has removed their last publisher logo, the logo grid will not render\n        // the first element child of containerRef becomes the input upload\n        // upload will always be present unless upload is not enabled.\n        // currently only admin can get to settings, which means they have upload ability\n        // checking for current and firstElementChild are safeguards\n        return containerRef.current?.getElementsByTagName('input')[0].focus();\n      }\n\n      const moveItemFocusByIndex =\n        indexRemoved > 0 ? publisherLogos[indexRemoved - 1] : publisherLogos[0];\n\n      setFocusedPublisherLogoId(moveItemFocusByIndex.id);\n      itemsRef.current[moveItemFocusByIndex.id].firstChild.focus();\n      return setIndexRemoved(null);\n    }\n    return undefined;\n  }, [indexRemoved, publisherLogos, setFocusedPublisherLogoId]);\n\n  useGridViewKeys({\n    containerRef,\n    gridRef,\n    itemRefs: itemsRef,\n    isRTL,\n    currentItemId: focusedPublisherLogoId,\n    items: publisherLogos,\n  });\n\n  const onMenuItemToggle = useCallback((newMenuId) => {\n    setFocusedPublisherLogoId(newMenuId);\n  }, []);\n\n  useFocusOut(containerRef, () => {\n    setFocusedPublisherLogoId(null);\n    setContextMenuId(null);\n  }, []);\n\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>{TEXT.SECTION_HEADING}</SettingHeading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.UPLOAD_CONTEXT}\n        </SettingSubheading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.CLICK_CONTEXT}\n        </SettingSubheading>\n        <SettingSubheading size={TextSize.Small}>\n          {TEXT.REMOVAL}\n        </SettingSubheading>\n      </div>\n      <div ref={containerRef} data-testid=\"publisher-logos-container\">\n        {publisherLogos.length > 0 && (\n          <UploadedContainer\n            tabIndex={0}\n            ref={gridRef}\n            role=\"list\"\n            aria-label={__('Viewing existing publisher logos', 'web-stories')}\n          >\n            {publisherLogos.map((publisherLogo, idx) => (\n              <GridItem\n                key={publisherLogo.id}\n                ref={(el) => {\n                  itemsRef.current[publisherLogo.id] = el;\n                }}\n                contextMenuId={{\n                  set: setContextMenuId,\n                  value: contextMenuId,\n                }}\n                index={idx}\n                isFocused={focusedPublisherLogoId === publisherLogo.id}\n                onMenuItemToggle={onMenuItemToggle}\n                onRemoveLogo={handleRemoveLogoClick}\n                onUpdateDefaultLogo={handleUpdateDefaultLogo}\n                publisherLogo={publisherLogo}\n                setFocusedPublisherLogoId={setFocusedPublisherLogoId}\n                showLogoContextMenu={!hasOnlyOneLogo}\n              />\n            ))}\n          </UploadedContainer>\n        )}\n        {uploadError && <Error role=\"alert\">{uploadError}</Error>}\n        {canUploadFiles && (\n          <>\n            <FileUpload\n              onSubmit={onAddLogos}\n              id=\"settings_publisher_logos\"\n              isLoading={isLoading}\n              label={TEXT.SUBMIT}\n              isMultiple\n              ariaLabel={TEXT.ARIA_LABEL}\n              instructionalText={TEXT.HELPER_UPLOAD}\n              acceptableFormats={Object.values(allowedImageMimeTypes)}\n            />\n            <SettingSubheading size={TextSize.Small}>\n              {TEXT.INSTRUCTIONS}\n            </SettingSubheading>\n          </>\n        )}\n      </div>\n    </SettingForm>\n  );\n}\n\nPublisherLogoSettings.propTypes = {\n  canUploadFiles: PropTypes.bool,\n  onAddLogos: PropTypes.func,\n  onRemoveLogo: PropTypes.func,\n  onUpdateDefaultLogo: PropTypes.func,\n  isLoading: PropTypes.bool,\n  publisherLogos: PropTypes.arrayOf(\n    PropTypes.shape(PopoverLogoContextMenuPropTypes.publisherLogos)\n  ),\n  uploadError: PropTypes.string,\n};\nexport default PublisherLogoSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/publisherLogo/popoverLogoContextMenu.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { Fragment, useCallback } from '@googleforcreators/react';\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport {\n  Icons,\n  ContextMenu,\n  ContextMenuComponents,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { MenuContainer, LogoMenuButton } from '../components';\n\nfunction PopoverLogoContextMenu({\n  isActive,\n  idx,\n  publisherLogo,\n  contextMenuId,\n  onMenuItemToggle,\n  items,\n}) {\n  const isPopoverMenuOpen = contextMenuId.value === publisherLogo.id;\n  const tabIndex = isActive ? 0 : -1;\n\n  const onMoreButtonSelected = useCallback(\n    (openMenuLogoId) => contextMenuId.set(openMenuLogoId),\n    [contextMenuId]\n  );\n\n  const handleDismiss = useCallback(\n    () => onMoreButtonSelected(-1),\n    [onMoreButtonSelected]\n  );\n\n  return (\n    <MenuContainer>\n      <LogoMenuButton\n        tabIndex={tabIndex}\n        isActive={isActive}\n        menuOpen={isPopoverMenuOpen}\n        data-testid={`publisher-logo-context-menu-button-${idx}`}\n        aria-label={sprintf(\n          /* translators: %s: logo title */\n          __('Publisher logo menu for %s', 'web-stories'),\n          publisherLogo.title\n        )}\n        onClick={(e) => {\n          e.preventDefault();\n          onMenuItemToggle(isPopoverMenuOpen ? null : publisherLogo.id);\n          onMoreButtonSelected(isPopoverMenuOpen ? -1 : publisherLogo.id);\n        }}\n        onFocus={() => {\n          onMenuItemToggle(isPopoverMenuOpen ? null : publisherLogo.id);\n        }}\n      >\n        <Icons.Pencil aria-hidden=\"true\" />\n      </LogoMenuButton>\n      <ContextMenu\n        animate\n        isOpen={isPopoverMenuOpen}\n        data-testid={`publisher-logo-context-menu-${idx}`}\n        onDismiss={handleDismiss}\n      >\n        {items.map(({ label, separator, ...props }) => {\n          // eslint-disable-next-line react/prop-types -- map is not picking up definition from StoryMenu proptypes.\n          const MenuItem = props.href\n            ? ContextMenuComponents.MenuLink\n            : ContextMenuComponents.MenuButton;\n\n          return (\n            <Fragment key={label}>\n              {separator === 'top' && <ContextMenuComponents.MenuSeparator />}\n              <MenuItem {...props}>{label}</MenuItem>\n              {separator === 'bottom' && (\n                <ContextMenuComponents.MenuSeparator />\n              )}\n            </Fragment>\n          );\n        })}\n      </ContextMenu>\n    </MenuContainer>\n  );\n}\n\nexport const PopoverLogoContextMenuPropTypes = {\n  contextMenuId: PropTypes.shape({\n    value: PropTypes.number,\n    set: PropTypes.func,\n  }).isRequired,\n  idx: PropTypes.number,\n  isActive: PropTypes.bool,\n  items: PropTypes.arrayOf(\n    PropTypes.shape({\n      disabled: PropTypes.bool,\n      href: PropTypes.string,\n      label: PropTypes.string.isRequired,\n      openNewTab: PropTypes.bool,\n      onClick: PropTypes.func,\n      onFocus: PropTypes.func,\n    })\n  ).isRequired,\n  onMenuItemToggle: PropTypes.func.isRequired,\n  publisherLogo: PropTypes.shape({\n    url: PropTypes.string,\n    title: PropTypes.string,\n    id: PropTypes.number,\n    active: PropTypes.bool,\n  }).isRequired,\n};\n\nPopoverLogoContextMenu.propTypes = PopoverLogoContextMenuPropTypes;\n\nexport default PopoverLogoContextMenu;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/publisherLogo/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useState } from '@googleforcreators/react';\nimport { createBlob, readFile } from '@googleforcreators/media';\nimport { ConfigProvider } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport { rawPublisherLogos } from '../../dataUtils/formattedPublisherLogos';\nimport PublisherLogoSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/PublisherLogo',\n  component: PublisherLogoSettings,\n  args: {\n    canUploadFiles: true,\n    isLoading: false,\n    uploadError: '',\n  },\n  argTypes: {\n    onAddLogos: { action: 'onSubmit fired' },\n    onRemoveLogo: { action: 'onDelete fired' },\n  },\n  parameters: {\n    controls: {\n      exclude: ['publisherLogos'],\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    const [uploadedContent, setUploadedContent] = useState(rawPublisherLogos);\n\n    const handleAddLogos = useCallback(\n      async (newPublisherLogos) => {\n        args.onAddLogos(newPublisherLogos);\n\n        // this is purely for the sake of storybook demoing\n        const newUploads = await Promise.all(\n          newPublisherLogos.map(async (file) => {\n            const arr = await readFile(file);\n            const src = createBlob(new Blob([arr], { type: file.type }));\n            return {\n              id: src,\n              url: src,\n              title: file.name,\n            };\n          })\n        );\n        setUploadedContent((existingUploads) => [\n          ...existingUploads,\n          ...newUploads,\n        ]);\n      },\n      [args]\n    );\n\n    const handleRemoveLogo = useCallback(\n      (deleteLogo) => {\n        args.onRemoveLogo(deleteLogo);\n\n        setUploadedContent((existingUploadedContent) => {\n          return existingUploadedContent.filter(\n            (uploadedLogo) => uploadedLogo.id !== deleteLogo.id\n          );\n        });\n      },\n      [args]\n    );\n\n    return (\n      <ConfigProvider config={{ allowedImageMimeTypes: {} }}>\n        <PublisherLogoSettings\n          onAddLogos={handleAddLogos}\n          onRemoveLogo={handleRemoveLogo}\n          publisherLogos={uploadedContent}\n          {...args}\n        />\n      </ConfigProvider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/publisherLogo/test/publisherLogo.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { within, screen } from '@testing-library/react';\nimport { noop } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport PublisherLogoSettings, { TEXT } from '..';\nimport { rawPublisherLogos } from '../../dataUtils/formattedPublisherLogos';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('PublisherLogo', () => {\n  const mockHandleAddLogos = jest.fn();\n\n  it('should render a fileUpload container and helper text by default when canUploadFiles is true', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={[]}\n        canUploadFiles\n      />\n    );\n\n    expect(screen.getByTestId('upload-file-input')).toBeInTheDocument();\n    expect(screen.getByText(TEXT.SECTION_HEADING)).toBeInTheDocument();\n  });\n\n  it('should not render fileUpload container when canUploadFiles is false', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={[]}\n      />\n    );\n\n    expect(screen.queryByTestId('upload-file-input')).not.toBeInTheDocument();\n  });\n\n  it('should render an image for each publisherLogo in the array', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={rawPublisherLogos}\n      />\n    );\n\n    expect(screen.queryAllByRole('img')).toHaveLength(rawPublisherLogos.length);\n  });\n\n  it('should specify the first logo displayed as default', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={rawPublisherLogos}\n      />\n    );\n\n    const FirstGridItem = screen.getAllByRole('listitem')[0];\n    const Default = within(FirstGridItem).getByText('Default');\n    expect(Default).toBeInTheDocument();\n  });\n\n  it('should render a context menu button for each uploaded logo', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={rawPublisherLogos}\n      />\n    );\n\n    expect(\n      screen.queryAllByTestId(/^publisher-logo-context-menu-button-/)\n    ).toHaveLength(rawPublisherLogos.length);\n  });\n\n  it('should render an error message if uploadError is present', () => {\n    renderWithProviders(\n      <PublisherLogoSettings\n        onAddLogos={mockHandleAddLogos}\n        onRemoveLogo={noop}\n        onUpdateDefaultLogo={noop}\n        isLoading={false}\n        publisherLogos={rawPublisherLogos}\n        uploadError={'Something went wrong.'}\n        canUploadFiles\n      />\n    );\n\n    expect(screen.getByText('Something went wrong.')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { TextSize } from '@googleforcreators/design-system';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineLink,\n  MultilineForm,\n  SettingHeading,\n  TextInputHelperText,\n} from '../components';\nimport { SHOPPING_PROVIDER_TYPE } from '../../../constants';\nimport ShopifySettings from './shopify';\nimport ShoppingProviderDropDown from './shoppingProviderDropDown';\n\nexport const TEXT = {\n  SECTION_HEADING: __('Shopping', 'web-stories'),\n  SHOPPING_PROVIDER_HELPER_MESSAGE: __(\n    'Once configured you can add products from this provider.',\n    'web-stories'\n  ),\n  HELPER_MESSAGE: __(\n    'Connect your store so you can easily add products to your stories.',\n    'web-stories'\n  ),\n  WOOCOMMERCE_INSTALL: __(\n    'Install <a>WooCommerce</a> to easily add shoppable products to Web Stories.',\n    'web-stories'\n  ),\n  WOOCOMMERCE_ACTIVE: __(\n    'Activate <a>WooCommerce</a> to easily add shoppable products to Web Stories.',\n    'web-stories'\n  ),\n  WOOCOMMERCE_MANAGE: __(\n    'Manage products in <a>WooCommerce</a> to make them available in Web Stories.',\n    'web-stories'\n  ),\n};\n\nfunction Shopping({\n  updateSettings,\n  shoppingProvider,\n  shopifyHost,\n  shopifyAccessToken,\n  vendors,\n  woocommerce,\n}) {\n  const handleUpdateShoppingProvider = useCallback(\n    (newValue) => {\n      updateSettings({ shoppingProvider: newValue });\n      trackEvent('change_shopping_provider', {\n        name: newValue,\n      });\n    },\n    [updateSettings]\n  );\n\n  const handleUpdateShopifyHost = useCallback(\n    (newValue) => updateSettings({ shopifyHost: newValue }),\n    [updateSettings]\n  );\n\n  const handleUpdateShopifyAccessToken = useCallback(\n    (newValue) => updateSettings({ shopifyAccessToken: newValue }),\n    [updateSettings]\n  );\n\n  const onWoocommerceClick = useCallback(\n    (evt) => trackClick(evt, 'click_woocommerce_link'),\n    []\n  );\n\n  const { canManage, installed, active, link } = woocommerce;\n\n  let woocommerceMessage;\n  if (installed === false) {\n    woocommerceMessage = TEXT.WOOCOMMERCE_INSTALL;\n  } else if (active === false) {\n    woocommerceMessage = TEXT.WOOCOMMERCE_ACTIVE;\n  } else if (canManage === true) {\n    woocommerceMessage = TEXT.WOOCOMMERCE_MANAGE;\n  }\n\n  return (\n    <MultilineForm onSubmit={(e) => e.preventDefault()}>\n      <div>\n        <SettingHeading>{TEXT.SECTION_HEADING}</SettingHeading>\n\n        <TextInputHelperText size={TextSize.Small}>\n          {TEXT.HELPER_MESSAGE}\n        </TextInputHelperText>\n        {shoppingProvider === SHOPPING_PROVIDER_TYPE.WOOCOMMERCE &&\n          woocommerceMessage &&\n          link && (\n            <TextInputHelperText\n              data-testid=\"woocommerceMessage\"\n              size={TextSize.Small}\n            >\n              <TranslateWithMarkup\n                mapping={{\n                  a: (\n                    <InlineLink\n                      href={link}\n                      rel=\"noreferrer\"\n                      target=\"_blank\"\n                      size={TextSize.Small}\n                      onClick={onWoocommerceClick}\n                    />\n                  ),\n                }}\n              >\n                {woocommerceMessage}\n              </TranslateWithMarkup>\n            </TextInputHelperText>\n          )}\n      </div>\n\n      <div>\n        <ShoppingProviderDropDown\n          vendors={vendors}\n          shoppingProvider={shoppingProvider}\n          handleUpdate={handleUpdateShoppingProvider}\n        />\n\n        <TextInputHelperText size={TextSize.Small}>\n          {TEXT.SHOPPING_PROVIDER_HELPER_MESSAGE}\n        </TextInputHelperText>\n\n        {shoppingProvider === SHOPPING_PROVIDER_TYPE.SHOPIFY && (\n          <ShopifySettings\n            handleUpdateHost={handleUpdateShopifyHost}\n            handleUpdateAccessToken={handleUpdateShopifyAccessToken}\n            host={shopifyHost}\n            accessToken={shopifyAccessToken}\n          />\n        )}\n      </div>\n    </MultilineForm>\n  );\n}\n\nShopping.propTypes = {\n  vendors: PropTypes.object.isRequired,\n  woocommerce: PropTypes.object,\n  updateSettings: PropTypes.func.isRequired,\n  shoppingProvider: PropTypes.string,\n  shopifyHost: PropTypes.string,\n  shopifyAccessToken: PropTypes.string,\n};\n\nexport default Shopping;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/shopify/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { useState, useCallback, useEffect } from '@googleforcreators/react';\nimport { __, sprintf, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport {\n  trackClick,\n  trackError,\n  trackEvent,\n} from '@googleforcreators/tracking';\nimport {\n  ButtonSize,\n  ButtonType,\n  TextSize,\n  CircularProgress,\n  useLiveRegion,\n} from '@googleforcreators/design-system';\nimport { useConfig } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport {\n  InlineForm,\n  InlineLink,\n  SaveButton,\n  TestConnectionButton,\n  SettingsTextInput,\n  TextInputHelperText,\n  VisuallyHiddenLabel,\n  ConnectionHelperText,\n} from '../../components';\n\nimport { isValidShopifyHost, hostPattern } from '../../utils';\n\nconst Loading = styled.div`\n  position: relative;\n  margin-top: 10px;\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  top: 0;\n`;\n\nexport const TEXT = {\n  HOST_CONTEXT: sprintf(\n    /* translators: 1: \"https://\". 2: \"www.\". 3: \"yourstore.myshopify.com\". */\n    __(\n      'Without <code>%1$s</code> or <code>%2$s</code>. Example: %3$s. <a>Find your URL</a>.',\n      'web-stories'\n    ),\n    'https://',\n    'www.',\n    'yourstore.myshopify.com'\n  ),\n  HOST_CONTEXT_LINK: __(\n    'https://help.shopify.com/en/manual/domains',\n    'web-stories'\n  ),\n  HOST_PLACEHOLDER: __('Enter your .myshopify.com domain', 'web-stories'),\n  HOST_LABEL: __('Shopify Domain', 'web-stories'),\n  ACCESS_TOKEN_CONTEXT: __('<a>Learn how to get one</a>.', 'web-stories'),\n  ACCESS_TOKEN_CONTEXT_LINK: __(\n    'https://help.shopify.com/en/manual/apps/custom-apps#get-the-api-credentials-for-a-custom-app',\n    'web-stories'\n  ),\n  ACCESS_TOKEN_PLACEHOLDER: __('Enter your API access token', 'web-stories'),\n  ACCESS_TOKEN_LABEL: __('Storefront API Access Token', 'web-stories'),\n  INPUT_ERROR: __('Invalid format', 'web-stories'),\n  SUBMIT_BUTTON: __('Save', 'web-stories'),\n  CONNECTION_TEST_BUTTON: __('Test connection', 'web-stories'),\n  CONNECTION_CHECKING: __('Testing connection…', 'web-stories'),\n  CONNECTION_SUCCESS: __('Connection successful', 'web-stories'),\n  CONNECTION_ERROR_DEFAULT: __(\n    'Connection failed. Please try again.',\n    'web-stories'\n  ),\n};\nfunction ShopifySettings({\n  host: shopifyHost,\n  accessToken: shopifyAccessToken,\n  handleUpdateHost,\n  handleUpdateAccessToken,\n}) {\n  const speak = useLiveRegion();\n  const [host, setHost] = useState(shopifyHost);\n  const [hostInputError, setHostInputError] = useState('');\n  const canSaveHost = host !== shopifyHost && !hostInputError;\n  const disableHostSaveButton = !canSaveHost;\n\n  const [accessToken, setAccessToken] = useState(shopifyAccessToken);\n  const [accessTokenInputError, setAccessTokenInputError] = useState('');\n  const canSaveAccessToken =\n    accessToken !== shopifyAccessToken && !accessTokenInputError;\n  const disableAccessTokenSaveButton = !canSaveAccessToken;\n\n  const {\n    apiCallbacks: { getProducts },\n  } = useConfig();\n\n  const [isTestingConnection, setIsTestingConnection] = useState(false);\n  const [testConnectionStatus, setTestConnectionStatus] = useState('');\n  const [hasConnectionError, setHasConnectionError] = useState(false);\n\n  useEffect(() => {\n    setHost(shopifyHost);\n  }, [shopifyHost]);\n\n  useEffect(() => {\n    setAccessToken(shopifyAccessToken);\n  }, [shopifyAccessToken]);\n\n  const onUpdateHost = useCallback((event) => {\n    const { value } = event.target;\n    setHost(value);\n    if (value.length === 0 || isValidShopifyHost(value)) {\n      setHostInputError('');\n      return;\n    }\n    setHostInputError(TEXT.INPUT_ERROR);\n  }, []);\n\n  const onHostBlur = useCallback((event) => {\n    const { value } = event.target;\n    if (!isValidShopifyHost(value)) {\n      return;\n    }\n    setHost(value.match(hostPattern)[0]);\n  }, []);\n\n  const onSaveHost = useCallback(() => {\n    if (canSaveHost) {\n      handleUpdateHost(host);\n    }\n  }, [canSaveHost, host, handleUpdateHost]);\n\n  const onKeyDownHost = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSaveHost();\n      }\n    },\n    [onSaveHost]\n  );\n\n  const onUpdateAccessToken = useCallback((event) => {\n    // @todo token verification see https://github.com/GoogleForCreators/web-stories-wp/pull/11218#discussion_r847495571\n    const { value } = event.target;\n    setAccessTokenInputError('');\n    setAccessToken(value);\n  }, []);\n\n  const onSaveAccessToken = useCallback(() => {\n    if (canSaveAccessToken) {\n      handleUpdateAccessToken(accessToken);\n    }\n  }, [canSaveAccessToken, accessToken, handleUpdateAccessToken]);\n\n  const onKeyDownAccessToken = useCallback(\n    (e) => {\n      if (e.key === 'Enter') {\n        e.preventDefault();\n        onSaveAccessToken();\n      }\n    },\n    [onSaveAccessToken]\n  );\n\n  const onTestConnection = useCallback(async () => {\n    setHasConnectionError(false);\n    setIsTestingConnection(true);\n    speak(TEXT.CONNECTION_CHECKING);\n\n    trackEvent('test_shopping_connection');\n\n    try {\n      await getProducts(new Date().getTime()); // @todo temp fix for cache busting the product query\n      setTestConnectionStatus(TEXT.CONNECTION_SUCCESS);\n      speak(TEXT.CONNECTION_SUCCESS);\n    } catch (e) {\n      trackError('test_shopping_connection', e?.message);\n      setHasConnectionError(true);\n      setTestConnectionStatus(TEXT.CONNECTION_ERROR_DEFAULT);\n      speak(TEXT.CONNECTION_ERROR_DEFAULT);\n    } finally {\n      setIsTestingConnection(false);\n    }\n  }, [getProducts, speak]);\n\n  const canTestConnection =\n    host &&\n    !hostInputError &&\n    accessToken &&\n    !accessTokenInputError &&\n    !isTestingConnection;\n\n  const handleClick = useCallback(\n    (evt) => trackClick(evt, 'click_shopify_docs'),\n    []\n  );\n\n  return (\n    <>\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"shopifyHost\">\n          {TEXT.HOST_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          aria-label={TEXT.HOST_LABEL}\n          id=\"shopifyHost\"\n          name=\"shopifyHost\"\n          data-testid=\"shopifyHost\"\n          value={host}\n          onChange={onUpdateHost}\n          onKeyDown={onKeyDownHost}\n          onBlur={onHostBlur}\n          placeholder={TEXT.HOST_PLACEHOLDER}\n          hasError={Boolean(hostInputError)}\n          hint={hostInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disableHostSaveButton}\n          onClick={onSaveHost}\n          data-testid=\"shopifyHostButton\"\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <InlineLink\n                href={TEXT.HOST_CONTEXT_LINK}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                onClick={handleClick}\n                size={TextSize.Small}\n              />\n            ),\n          }}\n        >\n          {TEXT.HOST_CONTEXT}\n        </TranslateWithMarkup>\n      </TextInputHelperText>\n\n      <InlineForm>\n        <VisuallyHiddenLabel htmlFor=\"shopifyAccessToken\">\n          {TEXT.ACCESS_TOKEN_LABEL}\n        </VisuallyHiddenLabel>\n        <SettingsTextInput\n          id=\"shopifyAccessToken\"\n          aria-label={TEXT.ACCESS_TOKEN_LABEL}\n          name=\"shopifyAccessToken\"\n          data-testid=\"shopifyAccessToken\"\n          value={accessToken}\n          onChange={onUpdateAccessToken}\n          onKeyDown={onKeyDownAccessToken}\n          placeholder={TEXT.ACCESS_TOKEN_PLACEHOLDER}\n          hasError={Boolean(accessTokenInputError)}\n          hint={accessTokenInputError}\n        />\n        <SaveButton\n          type={ButtonType.Secondary}\n          size={ButtonSize.Small}\n          disabled={disableAccessTokenSaveButton}\n          onClick={onSaveAccessToken}\n          data-testid=\"shopifyAccessTokenButton\"\n        >\n          {TEXT.SUBMIT_BUTTON}\n        </SaveButton>\n      </InlineForm>\n      <TextInputHelperText size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <InlineLink\n                href={TEXT.ACCESS_TOKEN_CONTEXT_LINK}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                size={TextSize.Small}\n              />\n            ),\n          }}\n        >\n          {TEXT.ACCESS_TOKEN_CONTEXT}\n        </TranslateWithMarkup>\n      </TextInputHelperText>\n\n      <TestConnectionButton\n        onFocus={() => setTestConnectionStatus('')}\n        type={ButtonType.Secondary}\n        size={ButtonSize.Small}\n        disabled={!canTestConnection}\n        onClick={onTestConnection}\n      >\n        {isTestingConnection\n          ? TEXT.CONNECTION_CHECKING\n          : TEXT.CONNECTION_TEST_BUTTON}\n      </TestConnectionButton>\n\n      {isTestingConnection && (\n        <Loading>\n          <Spinner>\n            <CircularProgress size={24} />\n          </Spinner>\n        </Loading>\n      )}\n      {testConnectionStatus && (\n        <ConnectionHelperText\n          data-testid=\"api-status\"\n          aria-label={__('API connection status', 'web-stories')}\n          hasError={hasConnectionError}\n          size={TextSize.Small}\n        >\n          {testConnectionStatus}\n        </ConnectionHelperText>\n      )}\n    </>\n  );\n}\nShopifySettings.propTypes = {\n  handleUpdateAccessToken: PropTypes.func,\n  handleUpdateHost: PropTypes.func,\n  host: PropTypes.string,\n  accessToken: PropTypes.string,\n};\n\nexport default ShopifySettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/shoppingProviderDropDown.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { __ } from '@googleforcreators/i18n';\nimport { DropDown } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SHOPPING_PROVIDER_TYPE } from '../../../constants';\n\nexport const TEXT = {\n  SLOT_ID_LABEL: __('Shopping provider', 'web-stories'),\n};\n\nfunction ShoppingProviderDropDown({ vendors, shoppingProvider, handleUpdate }) {\n  const OPTIONS = [];\n  Object.entries(vendors).forEach(([value, label]) =>\n    OPTIONS.push({ label, value })\n  );\n  return (\n    <DropDown\n      ariaLabel={TEXT.SLOT_ID_LABEL}\n      options={OPTIONS}\n      selectedValue={shoppingProvider}\n      onMenuItemClick={(_, newShoppingProvider) =>\n        handleUpdate(newShoppingProvider)\n      }\n      fillWidth\n    />\n  );\n}\nShoppingProviderDropDown.propTypes = {\n  vendors: PropTypes.object,\n  handleUpdate: PropTypes.func,\n  shoppingProvider: PropTypes.oneOf(Object.values(SHOPPING_PROVIDER_TYPE)),\n};\n\nexport default ShoppingProviderDropDown;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/stories/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport Shopping from '..';\nimport { SHOPPING_PROVIDER_TYPE } from '../../../../constants';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/Shopping',\n  component: Shopping,\n  args: {\n    shoppingProvider: SHOPPING_PROVIDER_TYPE.NONE,\n    shopifyHost: 'yourstore.myshopify.com',\n    shopifyAccessToken: '',\n    vendors: {\n      none: 'None',\n      shopify: 'Shopify',\n      woocommerce: 'WooCommerce',\n    },\n  },\n  argTypes: {\n    updateSettings: {\n      action: 'update settings',\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <Shopping {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/test/shopping.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, waitFor } from '@testing-library/react';\nimport { ConfigProvider } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\n\nimport ShoppingSettings, { TEXT } from '..';\nimport { TEXT as SETTINGS_TEXT } from '../shopify';\nimport { renderWithProviders } from '../../../../testUtils';\nimport { SHOPPING_PROVIDER_TYPE } from '../../../../constants';\n\nconst updateSettings = jest.fn();\n\nconst vendors = {\n  none: 'None',\n  shopify: 'Shopify',\n  woocommerce: 'WooCommerce',\n};\n\nconst woocommerceDefault = {\n  installed: true,\n  active: true,\n  canManage: true,\n  link: 'http://www.example.com',\n};\n\nconst mockGetProducts = jest.fn();\n\nconst config = {\n  apiCallbacks: {\n    getProducts: mockGetProducts,\n  },\n};\n\ndescribe('Editor Settings: Shopping <Shopping />', () => {\n  beforeEach(() => {\n    updateSettings.mockReset();\n  });\n\n  it('should render Shopify inputs and helper texts', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.SHOPIFY}\n          shopifyHost=\"yourstore.myshopify.com\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={woocommerceDefault}\n        />\n      </ConfigProvider>\n    );\n\n    const input = screen.getByLabelText('Shopify Domain');\n    expect(input).toBeInTheDocument();\n    expect(input).toBeEnabled();\n\n    const sectionHeader = screen.getByText(TEXT.SECTION_HEADING);\n    expect(sectionHeader).toBeInTheDocument();\n  });\n\n  it('should render WooCommerce inputs and helper texts', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.WOOCOMMERCE}\n          shopifyHost=\"\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={woocommerceDefault}\n        />\n      </ConfigProvider>\n    );\n\n    const element = screen.getByTestId('woocommerceMessage');\n    expect(element).toBeInTheDocument();\n    expect(element).toHaveTextContent(\n      'Manage products in WooCommerce to make them available in Web Stories.'\n    );\n  });\n\n  it('should render WooCommerce inputs and activation message', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.WOOCOMMERCE}\n          shopifyHost=\"\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={{\n            ...woocommerceDefault,\n            active: false,\n            canManage: false,\n          }}\n        />\n      </ConfigProvider>\n    );\n\n    const element = screen.getByTestId('woocommerceMessage');\n    expect(element).toBeInTheDocument();\n    expect(element).toHaveTextContent(\n      'Activate WooCommerce to easily add shoppable products to Web Stories.'\n    );\n  });\n\n  it('should render WooCommerce  inputs and install message', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.WOOCOMMERCE}\n          shopifyHost=\"\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={{\n            installed: false,\n            active: false,\n            canManage: false,\n            link: 'http://www.example.com',\n          }}\n        />\n      </ConfigProvider>\n    );\n\n    const element = screen.getByTestId('woocommerceMessage');\n    expect(element).toBeInTheDocument();\n    expect(element).toHaveTextContent(\n      'Install WooCommerce to easily add shoppable products to Web Stories.'\n    );\n  });\n\n  it('should update settings when pressing enter', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.SHOPIFY}\n          shopifyHost=\"yourstore.myshopify.com\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={woocommerceDefault}\n        />\n      </ConfigProvider>\n    );\n\n    const input = screen.getByLabelText('Shopify Domain');\n\n    fireEvent.change(input, { target: { value: 'mynewstore.myshopify.com' } });\n    fireEvent.keyDown(input, { key: 'Enter', keyCode: 13 });\n\n    expect(updateSettings).toHaveBeenCalledWith({\n      shopifyHost: 'mynewstore.myshopify.com',\n    });\n  });\n\n  it('should update settings when clicking save button', () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.SHOPIFY}\n          shopifyHost=\"yourstore.myshopify.com\"\n          shopifyAccessToken=\"\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={woocommerceDefault}\n        />\n      </ConfigProvider>\n    );\n\n    const input = screen.getByLabelText('Shopify Domain');\n    const button = screen.getByTestId('shopifyHostButton');\n\n    fireEvent.change(input, {\n      target: { value: 'https://mynewstore.myshopify.ca' },\n    });\n    fireEvent.click(button);\n    const errorMessage = screen.getByText(SETTINGS_TEXT.INPUT_ERROR);\n    expect(errorMessage).toBeInTheDocument();\n\n    fireEvent.change(input, { target: { value: 'mynewstore.myshopify.com' } });\n    fireEvent.click(button);\n    expect(updateSettings).toHaveBeenCalledWith({\n      shopifyHost: 'mynewstore.myshopify.com',\n    });\n  });\n\n  it('should render test api connection button', async () => {\n    renderWithProviders(\n      <ConfigProvider config={config}>\n        <ShoppingSettings\n          shoppingProvider={SHOPPING_PROVIDER_TYPE.SHOPIFY}\n          shopifyHost=\"yourstore.myshopify.com\"\n          shopifyAccessToken=\"123\"\n          updateSettings={updateSettings}\n          vendors={vendors}\n          woocommerce={woocommerceDefault}\n        />\n      </ConfigProvider>\n    );\n\n    const input = screen.getByRole('button', { name: 'Test connection' });\n\n    expect(input).toBeInTheDocument();\n\n    fireEvent.click(input);\n\n    await waitFor(() => {\n      expect(screen.getByTestId('api-status')).toHaveTextContent(\n        'Connection successful'\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/shopping/test/shoppingProvider.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport ShoppingProviderDropDown from '../shoppingProviderDropDown';\nimport { SHOPPING_PROVIDER_TYPE } from '../../../../constants';\nimport { renderWithProviders } from '../../../../testUtils';\n\nconst vendors = {\n  none: 'None',\n  shopify: 'Shopify',\n  woocommerce: 'WooCommerce',\n};\n\ndescribe('Editor Settings: Shopping provider settings <ShoppingProviderDropDown />', () => {\n  let provider;\n  let mockUpdate;\n\n  beforeEach(() => {\n    provider = SHOPPING_PROVIDER_TYPE.NONE;\n    mockUpdate = jest.fn((id) => {\n      provider = id;\n    });\n  });\n\n  afterEach(() => {\n    provider = SHOPPING_PROVIDER_TYPE.NONE;\n  });\n\n  it('should render shopping provider settings dropdown button', () => {\n    renderWithProviders(\n      <ShoppingProviderDropDown\n        shoppingProvider={provider}\n        handleUpdate={mockUpdate}\n        vendors={vendors}\n      />\n    );\n\n    const shoppingProviderDropdown = screen.getByRole('button');\n    expect(shoppingProviderDropdown).toHaveTextContent('None');\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/telemetry/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport propTypes from 'prop-types';\nimport { useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { Checkbox, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  SettingForm,\n  SettingHeading,\n  CheckboxLabel,\n  CheckboxLabelText,\n} from '../components';\n\nexport default function TelemetrySettings({\n  selected,\n  onCheckboxSelected,\n  disabled,\n}) {\n  const telemetryOptInId = useMemo(() => `telemetry-opt-in-${uuidv4()}`, []);\n\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>\n          {__('Data Sharing Opt-in', 'web-stories')}\n        </SettingHeading>\n      </div>\n      <div>\n        <CheckboxLabel htmlFor={telemetryOptInId}>\n          <Checkbox\n            id={telemetryOptInId}\n            data-testid=\"telemetry-settings-checkbox\"\n            disabled={disabled}\n            onChange={onCheckboxSelected}\n            checked={Boolean(selected)}\n          />\n          <CheckboxLabelText\n            size={TextSize.Small}\n            aria-checked={Boolean(selected)}\n          >\n            <TranslateWithMarkup\n              mapping={{\n                a: (\n                  <a\n                    href={__(\n                      'https://policies.google.com/privacy',\n                      'web-stories'\n                    )}\n                    rel=\"noreferrer\"\n                    target=\"_blank\"\n                    aria-label={__(\n                      'Learn more by visiting Google Privacy Policy',\n                      'web-stories'\n                    )}\n                  />\n                ),\n              }}\n            >\n              {__(\n                'Check the box to help us improve the Web Stories plugin by allowing tracking of product usage stats. All data are treated in accordance with <a>Google Privacy Policy</a>.',\n                'web-stories'\n              )}\n            </TranslateWithMarkup>\n          </CheckboxLabelText>\n        </CheckboxLabel>\n      </div>\n    </SettingForm>\n  );\n}\n\nTelemetrySettings.propTypes = {\n  disabled: propTypes.bool.isRequired,\n  selected: propTypes.bool.isRequired,\n  onCheckboxSelected: propTypes.func.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/telemetry/stories/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport TelemetrySettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/Telemetry',\n  component: TelemetrySettings,\n  args: {\n    disabled: false,\n    selected: true,\n  },\n  argTypes: {\n    onCheckboxSelected: { action: 'onCheckboxSelected fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <TelemetrySettings {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/telemetry/test/telemetrySettings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport TelemetrySettings from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <TelemetrySettings />', () => {\n  it('should render the telemetry as checked when selected is true.', () => {\n    renderWithProviders(\n      <TelemetrySettings\n        disabled={false}\n        onCheckboxSelected={jest.fn()}\n        selected\n      />\n    );\n\n    expect(screen.getByRole('checkbox')).toBeChecked();\n  });\n\n  it('should render the telemetry as not checked when selected is false.', () => {\n    renderWithProviders(\n      <TelemetrySettings\n        disabled={false}\n        onCheckboxSelected={jest.fn()}\n        selected={false}\n      />\n    );\n\n    expect(screen.getByRole('checkbox')).not.toBeChecked();\n  });\n\n  it('should call the change function when the checkbox is clicked.', () => {\n    const changeFn = jest.fn();\n    renderWithProviders(\n      <TelemetrySettings\n        disabled={false}\n        onCheckboxSelected={changeFn}\n        selected={false}\n      />\n    );\n\n    const checkbox = screen.getByRole('checkbox');\n    fireEvent.click(checkbox);\n\n    expect(changeFn).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/test/editorSettings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, within, screen } from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport EditorSettings from '../editorSettings';\nimport { rawPublisherLogos } from '../dataUtils/formattedPublisherLogos';\nimport { TEXT as AD_NETWORK_TEXT } from '../adManagement';\nimport { TEXT as GA_TEXT } from '../googleAnalytics';\nimport { TEXT as PUBLISHER_LOGO_TEXT } from '../publisherLogo';\nimport MockEditorProvider from '../../../testUtils/mockEditorProvider';\nimport { AD_NETWORK_TYPE } from '../../../constants';\nimport { renderWithProviders } from '../../../testUtils';\n\nconst mockedPromise = Promise.resolve({});\n\njest.mock('../../../api/settings', () => ({\n  fetchSettings: () => mockedPromise,\n  updateSettings: () => mockedPromise,\n}));\n\njest.mock('../../../api/media', () => ({\n  uploadMedia: () => mockedPromise,\n}));\n\njest.mock('../../../api/pages', () => ({\n  searchPages: () => mockedPromise,\n  getPageById: () => mockedPromise,\n}));\n\njest.mock('../../../api/publisherLogo', () => ({\n  fetchPublisherLogos: () => mockedPromise,\n  removePublisherLogo: () => mockedPromise,\n  addPublisherLogo: () => mockedPromise,\n  setPublisherLogoAsDefault: () => mockedPromise,\n}));\n\njest.mock('../../../api/fonts', () => ({\n  addCustomFont: () => mockedPromise,\n  deleteCustomFont: () => mockedPromise,\n}));\n\njest.mock('../../../api/user', () => ({\n  getUser: () => {\n    return Promise.resolve({\n      id: 1,\n      name: 'dev',\n      url: 'https://www.story-link.com',\n      description: '',\n      link: 'https://www.story-link.com/author/dev/',\n      slug: 'dev',\n      avatar_urls: {},\n      meta: {\n        web_stories_tracking_optin: false,\n        web_stories_media_optimization: true,\n        web_stories_onboarding: {\n          safeZone: true,\n        },\n      },\n    });\n  },\n}));\n\nconst mockFetchSettings = jest.fn();\nconst mockUploadMedia = jest.fn();\nconst mockUpdateSettings = jest.fn();\nconst mockSearch = jest.fn();\nconst mockGetPageById = jest.fn();\nconst mockFetchPublisherLogos = jest.fn();\nconst mockAddPublisherLogo = jest.fn();\nconst mockRemovePublisherLogo = jest.fn();\nconst mockSetPublisherLogoAsDefault = jest.fn();\nconst mockAddCustomFont = jest.fn();\nconst mockDeleteCustomFont = jest.fn();\nconst mockFetchCustomFonts = jest.fn();\n\nfunction createProviderValues({\n  canUploadFiles,\n  canManageSettings,\n  isLoading,\n  googleAnalyticsId,\n  adSensePublisherId = '',\n  adSenseSlotId = '',\n  adManagerSlotId = '',\n  mgidWidgetId = '',\n  adNetwork = AD_NETWORK_TYPE.NONE,\n  publisherLogos,\n}) {\n  return {\n    config: {\n      allowedImageMimeTypes: ['image/png', 'image/jpeg', 'image/gif'],\n      capabilities: {\n        canUploadFiles: canUploadFiles,\n        canManageSettings: canManageSettings,\n      },\n      maxUpload: 104857600,\n      maxUploadFormatted: '100 MB',\n      archiveURL: 'https://example.com/custom-archive/',\n      defaultArchiveURL: 'https://example.com/web-stories/',\n      api: {\n        currentUser: '/web-stories/v1/users/me/',\n        fonts: 'web-stories/v1/fonts',\n        users: '/web-stories/v1/users/',\n        settings: '/web-stories/v1/settings/',\n        pages: '/wp/v2/pages/',\n        publisherLogos: '/web-stories/v1/publisher-logos/',\n      },\n      vendors: { none: 'None', shopify: 'Shopify', woocommerce: 'WooCommerce' },\n      plugins: { siteKit: {}, woocommerce: {} },\n    },\n    api: {\n      state: {\n        settings: {\n          googleAnalyticsId,\n          adSensePublisherId,\n          adSenseSlotId,\n          adManagerSlotId,\n          mgidWidgetId,\n          adNetwork,\n          error: {},\n          archive: 'default',\n          archivePageId: 0,\n          autoAdvance: true,\n          defaultPageDuration: 20,\n        },\n        media: {\n          isLoading,\n          newlyCreatedMediaIds: [],\n          error: {},\n        },\n        currentUser: {\n          isUpdating: false,\n          data: {\n            id: 1,\n            meta: {\n              webStoriesTrackingOptin: true,\n              webStoriesMediaOptimization: true,\n            },\n          },\n        },\n        publisherLogos: {\n          publisherLogos,\n        },\n        customFonts: [],\n      },\n      actions: {\n        settingsApi: {\n          fetchSettings: mockFetchSettings,\n          updateSettings: mockUpdateSettings,\n        },\n        mediaApi: {\n          uploadMedia: mockUploadMedia,\n        },\n        usersApi: {},\n        pagesApi: {\n          searchPages: mockSearch,\n          getPageById: mockGetPageById,\n        },\n        publisherLogosApi: {\n          fetchPublisherLogos: mockFetchPublisherLogos,\n          addPublisherLogo: mockAddPublisherLogo,\n          removePublisherLogo: mockRemovePublisherLogo,\n          setPublisherLogoAsDefault: mockSetPublisherLogoAsDefault,\n        },\n        fontsApi: {\n          addCustomFont: mockAddCustomFont,\n          deleteCustomFont: mockDeleteCustomFont,\n          fetchCustomFonts: mockFetchCustomFonts,\n        },\n      },\n    },\n  };\n}\n\nconst renderEditorSettings = (values) => {\n  return renderWithProviders(\n    <EditorSettings />,\n    createProviderValues(values),\n    {},\n    ({ children }) => children,\n    MockEditorProvider\n  );\n};\n\ndescribe('Editor Settings: <Editor Settings />', () => {\n  afterEach(() => {\n    mockFetchSettings.mockReset();\n    mockRemovePublisherLogo.mockReset();\n  });\n\n  it('should render settings page with google analytics and publisher logo sections', () => {\n    const { container } = renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: true,\n      canManageSettings: true,\n      isLoading: false,\n      logoIds: [],\n      publisherLogos: [],\n    });\n\n    setAppElement(container);\n\n    const googleAnalyticsHeading = screen.getByText(GA_TEXT.SECTION_HEADING);\n    expect(googleAnalyticsHeading).toBeInTheDocument();\n\n    const input = screen.getByRole('textbox', {\n      name: 'Enter your Google Analytics Measurement ID',\n    });\n    expect(input).toBeInTheDocument();\n\n    expect(input).toHaveValue('UA-098909-05');\n\n    expect(\n      screen.getByText(PUBLISHER_LOGO_TEXT.SECTION_HEADING)\n    ).toBeInTheDocument();\n    expect(screen.getByTestId('upload-file-input')).toBeInTheDocument();\n    expect(mockFetchSettings).toHaveBeenCalledOnce();\n\n    expect(\n      screen.getByText(AD_NETWORK_TEXT.SECTION_HEADING)\n    ).toBeInTheDocument();\n  });\n\n  it('should render settings page with publisher logos', () => {\n    const { container } = renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: true,\n      canManageSettings: true,\n      isLoading: false,\n      publisherLogos: rawPublisherLogos,\n    });\n\n    setAppElement(container);\n\n    expect(screen.queryAllByTestId(/^uploaded-publisher-logo-/)).toHaveLength(\n      rawPublisherLogos.length\n    );\n  });\n\n  it('should call mockRemovePublisherLogo when a logo is removed', () => {\n    renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: true,\n      canManageSettings: true,\n      isLoading: false,\n      publisherLogos: rawPublisherLogos,\n    });\n\n    const ContextMenuButton = screen.getByTestId(\n      'publisher-logo-context-menu-button-1'\n    );\n\n    fireEvent.click(ContextMenuButton);\n\n    const ContextMenu = screen.getByTestId('publisher-logo-context-menu-1');\n    expect(ContextMenu).toBeInTheDocument();\n\n    const DeleteFileButton = within(ContextMenu).getByText('Delete');\n    expect(DeleteFileButton).toBeInTheDocument();\n\n    fireEvent.click(DeleteFileButton);\n\n    expect(mockRemovePublisherLogo).toHaveBeenCalledOnce();\n  });\n\n  it('should render settings page without file upload section when canUploadFiles is false', () => {\n    const { container } = renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: false,\n      canManageSettings: true,\n      isLoading: false,\n      publisherLogos: [],\n    });\n    setAppElement(container);\n\n    expect(screen.queryByTestId('upload-file-input')).not.toBeInTheDocument();\n  });\n\n  it('should render settings page with AdSense', () => {\n    const { container } = renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: true,\n      canManageSettings: true,\n      isLoading: false,\n      adSensePublisherId: '123',\n      adSenseSlotId: '456',\n      adManagerSlotId: '',\n      adNetwork: AD_NETWORK_TYPE.ADSENSE,\n      publisherLogos: [],\n    });\n\n    setAppElement(container);\n\n    const helperLink = screen.getByText(\n      (_, node) => node.textContent === 'how to monetize your Web Stories',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n  });\n\n  it('should render settings page with MGID', () => {\n    const { container } = renderEditorSettings({\n      googleAnalyticsId: 'UA-098909-05',\n      usingLegacyAnalytics: false,\n      canUploadFiles: true,\n      canManageSettings: true,\n      isLoading: false,\n      adSensePublisherId: '123',\n      adSenseSlotId: '456',\n      adManagerSlotId: '',\n      mgidWidgetId: '1234567890',\n      adNetwork: AD_NETWORK_TYPE.MGID,\n      publisherLogos: [],\n    });\n\n    setAppElement(container);\n\n    const helperLink = screen.getByText(\n      (_, node) =>\n        node.textContent === 'monetizing Web Stories with MGID Native Solution',\n      {\n        selector: 'a',\n      }\n    );\n    expect(helperLink).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/useEditorSettings.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useEditorSettings(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useEditorSettings;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as validateAdManagerSlotIdFormat } from './validateAdManagerSlotIdFormat';\nexport { default as validateAdSensePublisherIdFormat } from './validateAdSensePublisherIdFormat';\nexport { default as validateAdSenseSlotIdFormat } from './validateAdSenseSlotIdFormat';\nexport { default as validateGoogleAnalyticsIdFormat } from './validateGoogleAnalyticsIdFormat';\nexport { default as validateMgidWidgetIdFormat } from './validateMgidWidgetIdFormat';\nexport {\n  default as isValidShopifyHost,\n  hostPattern,\n} from './validateShopifyHost';\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateAdManagerSlotIdFormat.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { validateAdManagerSlotIdFormat } from '..';\n\nconst one_hundred_chars = 'abcde'.repeat(20);\n\nconst idsToValidate = [\n  ['123456789/amp_story_dfp_example', false],\n  ['/123456789/amp_story_dfp_example', true],\n  ['/123456789/a4a/amp_story_dfp_example', true],\n  ['/123456789/a4a/trailing-slash/', false],\n  ['/not/numeric/start', false],\n  ['clearly wrong', false],\n  ['/1234567,1234/Travel', true],\n  ['/123456789/post.mobileamp/webstory', true],\n  ['/123456789/abc_123-.*/\\\\!<:()', true],\n  [`/123456789/${one_hundred_chars}/${one_hundred_chars}`, true],\n  [`/123456789/${one_hundred_chars}f/${one_hundred_chars}`, false],\n  [`/123456789/${one_hundred_chars}/${one_hundred_chars}a`, false],\n];\n\ndescribe('validateAdManagerSlotIdFormat', () => {\n  it.each(idsToValidate)(\n    'should take \"%s\" and return as %p Ad Manager slot id format',\n    (slotId, expected) => {\n      const bool = validateAdManagerSlotIdFormat(slotId);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateAdSensePublisherIdFormat.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { validateAdSensePublisherIdFormat } from '..';\n\nconst idsToValidate = [\n  ['pub-1234567891234567', true],\n  ['ca-pub-1234567891234567', true],\n  ['ca-pub', false],\n  ['ca-1234567891234567', false],\n  ['clearly wrong', false],\n];\n\ndescribe('validateAdSensePublisherIdFormat', () => {\n  it.each(idsToValidate)(\n    'should take \" %s \" and return as %p AdSense publisher id format',\n    (publisherId, expected) => {\n      const bool = validateAdSensePublisherIdFormat(publisherId);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateAdSenseSlotIdFormat.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { validateAdSenseSlotIdFormat } from '..';\n\nconst idsToValidate = [\n  ['1234567890', true],\n  ['123456789', false],\n  ['12345678911', false],\n];\n\ndescribe('validateAdSenseSlotIdFormat', () => {\n  it.each(idsToValidate)(\n    'should take \" %s \" and return as %p AdSense slot id format',\n    (slotId, expected) => {\n      const bool = validateAdSenseSlotIdFormat(slotId);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateGoogleAnalyticsIdFormat.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { validateGoogleAnalyticsIdFormat } from '..';\n\n// GA4 measurement ID format is not yet supported in AMP.\n// See https://github.com/googleforcreators/web-stories-wp/issues/6479\nconst idsToValidate = [\n  ['UA-000000-56', true],\n  ['ua-098765432-9875', true],\n  ['78787878', false],\n  ['ua--123448-0', false],\n  ['clearly wrong', false],\n  ['G-9878987', true],\n  ['g-9878987', true],\n  ['G-1A2BCD345E', true],\n  ['X-8888888', false],\n  ['G-123456', true],\n  ['G-12345678', true],\n  ['G-abcdefg8910', true],\n];\n\ndescribe('validateGoogleAnalyticsIdFormat', () => {\n  it.each(idsToValidate)(\n    'should take \" %s \" and return as %p google analytic id format',\n    (validId, expected) => {\n      const bool = validateGoogleAnalyticsIdFormat(validId);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateMgidWidgetIdFormat.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { validateMgidWidgetIdFormat } from '..';\n\nconst idsToValidate = [\n  ['1234567890', true],\n  ['123456', false],\n  ['123456789012345678901', false],\n  ['widgetId12345', false],\n];\n\ndescribe('validateMgidWidgetIdFormat', () => {\n  it.each(idsToValidate)(\n    'should take \" %s \" and return as %p MGID widget id format',\n    (slotId, expected) => {\n      const bool = validateMgidWidgetIdFormat(slotId);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/test/validateShopifyHost.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport { isValidShopifyHost } from '..';\n\nconst hostToValidate = [\n  ['example.com', false],\n  ['https://webstories.myshopify.com', true],\n  ['webstories.myyshopify.com', false],\n  ['webstories.myshopify.com', true],\n];\n\ndescribe('isValidShopifyHost', () => {\n  it.each(hostToValidate)(\n    'should take \" %s \" and return as %p for shopify host',\n    (host, expected) => {\n      const bool = isValidShopifyHost(host);\n      expect(bool).toBe(expected);\n    }\n  );\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateAdManagerSlotIdFormat.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Example: /123456789/a4a/amp_story_dfp_example\n// Ad unit codes  (the \"amp_story_dfp_example\" part) can be up to 100 characters in length.\n// Only letters, numbers, underscores, hyphens, periods, asterisks, forward slashes, backslashes, exclamations, left angle brackets, colons and parentheses are allowed.\nconst adManagerSlotIdFormatRegex =\n  /^\\/\\d+(,\\d+)?(\\/[\\w\\d_\\-.*\\\\!<:()]{1,99}[^/])*$/;\n\nexport default function validateAdManagerSlotIdFormat(value = '') {\n  return Boolean(value.toLowerCase().match(adManagerSlotIdFormatRegex));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateAdSensePublisherIdFormat.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst adSensePublisherIdFormatRegex = /^(ca-)?pub-\\d{16}$/;\n\nexport default function validateAdSensePublisherIdFormat(value = '') {\n  return Boolean(value.toLowerCase().match(adSensePublisherIdFormatRegex));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateAdSenseSlotIdFormat.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst adSenseSlotIdFormatRegex = /^\\d{10}$/;\n\nexport default function validateAdSenseSlotIdFormat(value = '') {\n  return Boolean(value.toLowerCase().match(adSenseSlotIdFormatRegex));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateGoogleAnalyticsIdFormat.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst idFormatRegex = /^ua-\\d+-\\d+|g-\\w+$/;\n\nexport default function validateGoogleAnalyticsIdFormat(value = '') {\n  return Boolean(value.toLowerCase().match(idFormatRegex));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateMgidWidgetIdFormat.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Example: 1234567\nconst mgidWidgetIdFormatRegex = /^\\d{7,20}$/;\n\nexport default function validateMgidWidgetIdFormat(value = '') {\n  return Boolean(value.toLowerCase().match(mgidWidgetIdFormatRegex));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/utils/validateShopifyHost.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const hostPattern = /[\\w-]+\\.myshopify\\.com/i;\n\nexport default function isValidShopifyHost(value = '') {\n  return Boolean(value.toLowerCase().match(hostPattern));\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/videoCache/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo } from '@googleforcreators/react';\nimport { v4 as uuidv4 } from 'uuid';\nimport { __ } from '@googleforcreators/i18n';\nimport { Checkbox, TextSize } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport {\n  SettingForm,\n  SettingHeading,\n  CheckboxLabel,\n  CheckboxLabelText,\n} from '../components';\n\nexport default function VideoCacheSettings({\n  isEnabled = false,\n  updateSettings,\n}) {\n  const videoCacheId = useMemo(() => `video-cache-${uuidv4()}`, []);\n\n  const onChange = useCallback(\n    () => updateSettings({ videoCache: !isEnabled }),\n    [updateSettings, isEnabled]\n  );\n\n  return (\n    <SettingForm>\n      <div>\n        <SettingHeading>{__('Video Cache', 'web-stories')}</SettingHeading>\n      </div>\n      <div>\n        <CheckboxLabel htmlFor={videoCacheId}>\n          <Checkbox\n            id={videoCacheId}\n            data-testid=\"video-cache-settings-checkbox\"\n            onChange={onChange}\n            checked={Boolean(isEnabled)}\n          />\n          <CheckboxLabelText\n            size={TextSize.Small}\n            aria-checked={Boolean(isEnabled)}\n          >\n            {__(\n              'Reduce hosting costs and improve user experience by serving videos from the Google cache.',\n              'web-stories'\n            )}\n          </CheckboxLabelText>\n        </CheckboxLabel>\n      </div>\n    </SettingForm>\n  );\n}\n\nVideoCacheSettings.propTypes = {\n  isEnabled: PropTypes.bool,\n  updateSettings: PropTypes.func.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/videoCache/stories/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport VideoCacheSettings from '..';\n\nexport default {\n  title: 'Dashboard/Views/EditorSettings/VideoCache',\n  component: VideoCacheSettings,\n  args: {\n    isEnabled: true,\n  },\n  argTypes: {\n    updateSettings: { action: 'updateSettings fired' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <VideoCacheSettings {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/editorSettings/videoCache/test/videoCache.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\n\n/**\n * Internal dependencies\n */\nimport VideoCache from '..';\nimport { renderWithProviders } from '../../../../testUtils';\n\ndescribe('Editor Settings: <VideoCache />', () => {\n  it('should render the video cache setting as checked when isEnabled', () => {\n    renderWithProviders(<VideoCache updateSettings={jest.fn()} isEnabled />);\n\n    expect(screen.getByRole('checkbox')).toBeChecked();\n  });\n\n  it('should not render the video cache setting as checked when not isEnabled', () => {\n    renderWithProviders(<VideoCache updateSettings={jest.fn()} />);\n\n    expect(screen.getByRole('checkbox')).not.toBeChecked();\n  });\n\n  it('should update settings when the checkbox is clicked.', () => {\n    const onChange = jest.fn();\n    renderWithProviders(<VideoCache updateSettings={onChange} />);\n\n    const checkbox = screen.getByRole('checkbox');\n    fireEvent.click(checkbox);\n\n    expect(onChange).toHaveBeenCalledOnce();\n    expect(onChange).toHaveBeenCalledWith({ videoCache: true });\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/ga4Banner/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useRef,\n  useEffect,\n  createPortal,\n  useState,\n} from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { Banner, Link, Text } from '@googleforcreators/design-system';\nimport {\n  APP_ROUTES,\n  resolveRoute,\n  useConfig,\n  useRouteHistory,\n} from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport { trackClick } from '@googleforcreators/tracking';\nimport { EDITOR_SETTINGS_ROUTE } from '../../constants';\nimport useEditorSettings from '../editorSettings/useEditorSettings.js';\n\nconst StyledBanner = styled(Banner)`\n  background: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n`;\n\nconst StyledLink = styled(Link)`\n  color: ${({ theme }) => theme.colors.interactiveFg.brandNormal};\n  text-decoration: underline;\n\n  &:hover {\n    color: ${({ theme }) => theme.colors.interactiveFg.brandHover};\n  }\n\n  &:focus {\n    color: ${({ theme }) => theme.colors.interactiveFg.brandPress};\n  }\n`;\n\nfunction GoogleAnalytics4BannerContainer() {\n  const {\n    capabilities: { canManageSettings } = {},\n    plugins: { siteKit = {} },\n  } = useConfig();\n\n  const fetchSettings = useEditorSettings(\n    ({\n      actions: {\n        settingsApi: { fetchSettings },\n      },\n    }) => fetchSettings\n  );\n\n  useEffect(() => {\n    if (canManageSettings) {\n      fetchSettings();\n    }\n  }, [canManageSettings, fetchSettings]);\n\n  const isUsingUniversalAnalytics = useEditorSettings(\n    ({\n      state: {\n        settings: { googleAnalyticsId },\n      },\n    }) => googleAnalyticsId?.toLowerCase().startsWith('ua-')\n  );\n\n  const { currentPath } = useRouteHistory(({ state: { currentPath } }) => ({\n    currentPath,\n  }));\n\n  const ref = useRef();\n\n  if (siteKit.analyticsActive) {\n    return null;\n  }\n\n  if (!isUsingUniversalAnalytics) {\n    return null;\n  }\n\n  if (currentPath === EDITOR_SETTINGS_ROUTE) {\n    return null;\n  }\n\n  return (\n    <StyledBanner\n      title={__('Update your Google Analytics configuration.', 'web-stories')}\n      ref={ref}\n    >\n      <Text.Paragraph>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                href={__(\n                  'https://support.google.com/analytics/answer/11583528?hl=en',\n                  'web-stories'\n                )}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                onClick={(evt) => trackClick(evt, 'click_ua_deprecation_docs')}\n              />\n            ),\n            a2: (\n              <Link\n                href={__(\n                  'https://support.google.com/analytics/answer/10089681?hl=en',\n                  'web-stories'\n                )}\n                rel=\"noreferrer\"\n                target=\"_blank\"\n                onClick={(evt) => trackClick(evt, 'click_ga4_docs')}\n              />\n            ),\n          }}\n        >\n          {__(\n            'Universal Analytics <a>stopped processing new visits</a> starting <b>July 1, 2023</b>. We recommend switching to <a2>Google Analytics 4</a2> (GA4).',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n      <Text.Paragraph>\n        <TranslateWithMarkup\n          mapping={{\n            a: <StyledLink href={resolveRoute(EDITOR_SETTINGS_ROUTE)} />,\n          }}\n        >\n          {__('<a>Update your settings now</a>.', 'web-stories')}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </StyledBanner>\n  );\n}\n\nexport default function GoogleAnalytics4Banner() {\n  const { currentPath, hasAvailableRoutes } = useRouteHistory(({ state }) => ({\n    currentPath: state.currentPath,\n    hasAvailableRoutes: state.availableRoutes.length > 0,\n  }));\n  const headerRef = useRef(null);\n  const [, forceUpdate] = useState(false);\n\n  useEffect(() => {\n    if (!hasAvailableRoutes) {\n      return;\n    }\n\n    if (\n      [\n        APP_ROUTES.DASHBOARD,\n        APP_ROUTES.TEMPLATES_GALLERY,\n        EDITOR_SETTINGS_ROUTE,\n      ].includes(currentPath)\n    ) {\n      headerRef.current = document.getElementById('body-view-options-header');\n      forceUpdate((value) => !value);\n    }\n  }, [currentPath, hasAvailableRoutes]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  if (!headerRef.current) {\n    return null;\n  }\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  return createPortal(<GoogleAnalytics4BannerContainer />, headerRef.current);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Layout } from './layout';\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/layout/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { InterfaceSkeleton } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport { useSyncAdminMenu } from '../../effects';\nimport { EditorSettingsProvider, EditorSettings } from '../editorSettings';\nimport TelemetryBanner from '../telemetryBanner';\nimport UpdateBanner from '../updateBanner';\nimport GoogleAnalytics4Banner from '../ga4Banner';\nimport { EDITOR_SETTINGS_ROUTE } from '../../constants';\n\nfunction Layout() {\n  useSyncAdminMenu();\n\n  return (\n    <EditorSettingsProvider>\n      <InterfaceSkeleton\n        additionalRoutes={[\n          {\n            path: EDITOR_SETTINGS_ROUTE,\n            component: <EditorSettings />,\n          },\n        ]}\n      />\n      <TelemetryBanner />\n      <UpdateBanner />\n      <GoogleAnalytics4Banner />\n    </EditorSettingsProvider>\n  );\n}\n\nexport default Layout;\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/telemetryBanner/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useLayoutEffect,\n  useRef,\n  forwardRef,\n  useEffect,\n  createPortal,\n  useState,\n} from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport {\n  Banner,\n  Checkbox,\n  Link,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport {\n  resolveRoute,\n  APP_ROUTES,\n  useRouteHistory,\n} from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport useTelemetryOptIn from '../../effects/useTelemetryOptIn';\nimport { EDITOR_SETTINGS_ROUTE } from '../../constants';\n\nconst Label = styled.label.attrs({ htmlFor: 'telemetry-banner-opt-in' })`\n  display: flex;\n  cursor: pointer;\n`;\n\nconst LabelText = styled(Text.Span)`\n  margin-bottom: 16px;\n  margin-left: 8px;\n  color: ${({ theme }) => theme.colors.fg.secondary};\n`;\n\nconst VisitSettingsText = styled(Text.Span)`\n  color: ${({ theme }) => theme.colors.fg.tertiary};\n`;\n\nconst NavLink = styled(Link)`\n  display: inline-block;\n  margin: 0;\n`;\n\nexport const TelemetryOptInBanner = forwardRef(\n  (\n    {\n      visible = true,\n      disabled = false,\n      onChange = () => {},\n      onClose = () => {},\n      checked = false,\n    },\n    ref\n  ) => {\n    const checkboxRef = useRef();\n    const focusedCheckboxRef = useRef(false);\n    const title = checked\n      ? __(\n          'Your selection has been updated. Thank you for helping to improve the editor!',\n          'web-stories'\n        )\n      : __('Help improve the editor!', 'web-stories');\n\n    useEffect(() => {\n      if (focusedCheckboxRef.current) {\n        checkboxRef.current.focus();\n      }\n    });\n\n    return visible ? (\n      <Banner\n        closeButtonLabel={__('Dismiss telemetry banner', 'web-stories')}\n        onClose={onClose}\n        title={title}\n        ref={ref}\n      >\n        <Label>\n          <Checkbox\n            id=\"telemetry-banner-opt-in\"\n            checked={checked}\n            disabled={disabled}\n            onChange={() => {\n              onChange();\n              focusedCheckboxRef.current = true;\n            }}\n            onBlur={() => {\n              focusedCheckboxRef.current = false;\n            }}\n            ref={checkboxRef}\n          />\n          <LabelText aria-checked={checked} size={TextSize.Small}>\n            <TranslateWithMarkup\n              mapping={{\n                a: (\n                  <NavLink\n                    size={TextSize.Small}\n                    href={__(\n                      'https://policies.google.com/privacy',\n                      'web-stories'\n                    )}\n                    rel=\"noreferrer\"\n                    target=\"_blank\"\n                    aria-label={__(\n                      'Learn more by visiting Google Privacy Policy',\n                      'web-stories'\n                    )}\n                  />\n                ),\n              }}\n            >\n              {__(\n                'Check the box to help us improve the Web Stories plugin by allowing tracking of product usage stats. All data are treated in accordance with <a>Google Privacy Policy</a>.',\n                'web-stories'\n              )}\n            </TranslateWithMarkup>\n          </LabelText>\n        </Label>\n        <VisitSettingsText size={TextSize.XSmall}>\n          <TranslateWithMarkup\n            mapping={{\n              a: (\n                <NavLink\n                  size={TextSize.XSmall}\n                  href={resolveRoute(EDITOR_SETTINGS_ROUTE)}\n                  aria-label={__('Settings', 'web-stories')}\n                />\n              ),\n            }}\n          >\n            {__(\n              'You can update your selection later by visiting <a>Settings</a>.',\n              'web-stories'\n            )}\n          </TranslateWithMarkup>\n        </VisitSettingsText>\n      </Banner>\n    ) : null;\n  }\n);\n\nTelemetryOptInBanner.displayName = 'TelemetryOptInBanner';\n\nTelemetryOptInBanner.propTypes = {\n  visible: PropTypes.bool.isRequired,\n  checked: PropTypes.bool.isRequired,\n  disabled: PropTypes.bool.isRequired,\n  onChange: PropTypes.func.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport function TelemetryBannerContainer(props) {\n  const {\n    bannerVisible,\n    closeBanner,\n    optedIn,\n    disabled,\n    toggleWebStoriesTrackingOptIn,\n  } = useTelemetryOptIn();\n  const ref = useRef();\n\n  const previousBannerVisibleRef = useRef(bannerVisible);\n\n  useLayoutEffect(() => {\n    if (\n      bannerVisible &&\n      previousBannerVisibleRef.current === false &&\n      ref.current\n    ) {\n      previousBannerVisibleRef.current = true;\n    } else if (!bannerVisible && previousBannerVisibleRef.current) {\n      previousBannerVisibleRef.current = false;\n    }\n  }, [bannerVisible]);\n\n  return (\n    <TelemetryOptInBanner\n      ref={ref}\n      visible={bannerVisible}\n      checked={optedIn}\n      disabled={disabled}\n      onChange={toggleWebStoriesTrackingOptIn}\n      onClose={closeBanner}\n      {...props}\n    />\n  );\n}\n\nexport default function TelemetryBanner() {\n  const { currentPath, hasAvailableRoutes } = useRouteHistory(({ state }) => ({\n    currentPath: state.currentPath,\n    hasAvailableRoutes: state.availableRoutes.length > 0,\n  }));\n  const headerRef = useRef(null);\n  const [, forceUpdate] = useState(false);\n\n  useEffect(() => {\n    if (!hasAvailableRoutes) {\n      return;\n    }\n\n    if (\n      [APP_ROUTES.DASHBOARD, APP_ROUTES.TEMPLATES_GALLERY].includes(currentPath)\n    ) {\n      headerRef.current = document.getElementById('body-view-options-header');\n      forceUpdate((value) => !value);\n    }\n  }, [currentPath, hasAvailableRoutes]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  if (!headerRef.current) {\n    return null;\n  }\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  return createPortal(<TelemetryBannerContainer />, headerRef.current);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/telemetryBanner/stories/telemetryBanner.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport { TelemetryOptInBanner } from '..';\n\nexport default {\n  title: 'Dashboard/Views/Shared/TelemetryBanner',\n  component: TelemetryOptInBanner,\n  args: {\n    visible: true,\n    checked: false,\n    disabled: false,\n  },\n  argTypes: {\n    onChange: { action: 'onChange' },\n    onClose: { action: 'onClose' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <TelemetryOptInBanner {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/telemetryBanner/test/telemetryBanner.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useState } from '@googleforcreators/react';\nimport { screen } from '@testing-library/react';\nimport { userEvent } from '@testing-library/user-event';\n\n/**\n * Internal dependencies\n */\nimport { TelemetryOptInBanner } from '..';\nimport { renderWithProviders } from '../../../testUtils';\n\nfunction TelemetryBannerTestContainer(props) {\n  const [state, setState] = useState({\n    visible: true,\n    checked: false,\n    disabled: false,\n    ...props,\n  });\n\n  const onClose = () =>\n    setState((prevState) => ({ ...prevState, visible: false }));\n\n  const onChange = () => {\n    setState((prevState) => ({\n      ...prevState,\n      checked: true,\n    }));\n  };\n\n  return (\n    <TelemetryOptInBanner\n      visible={state.visible}\n      checked={state.checked}\n      disabled={state.disabled}\n      onChange={onChange}\n      onClose={onClose}\n    />\n  );\n}\n\ndescribe('TelemetryBanner', () => {\n  it('should render visible with the checkbox unchecked', () => {\n    renderWithProviders(<TelemetryBannerTestContainer />);\n\n    const checkbox = screen.getByRole('checkbox');\n\n    expect(checkbox).not.toBeChecked();\n  });\n\n  it('should change the checkbox to checked and update the header when clicked', async () => {\n    renderWithProviders(<TelemetryBannerTestContainer />);\n\n    const checkbox = screen.getByRole('checkbox');\n\n    expect(checkbox).not.toBeChecked();\n\n    let bannerHeader = screen.getByText(/Help improve the editor!/);\n\n    expect(bannerHeader).toBeInTheDocument();\n\n    await userEvent.click(checkbox);\n\n    expect(checkbox).toBeChecked();\n\n    bannerHeader = screen.getByText(/Your selection has been updated./);\n    expect(bannerHeader).toBeInTheDocument();\n  });\n\n  it('should close and not be visible when the close icon is clicked', async () => {\n    renderWithProviders(<TelemetryBannerTestContainer />);\n\n    const closeButton = screen.getByRole('button');\n\n    expect(closeButton).toBeInTheDocument();\n\n    await userEvent.click(closeButton);\n\n    expect(closeButton).not.toBeInTheDocument();\n  });\n\n  it('should not be able to be checked when disabled', async () => {\n    renderWithProviders(<TelemetryBannerTestContainer disabled />);\n\n    const checkbox = screen.getByRole('checkbox');\n\n    expect(checkbox).not.toBeChecked();\n\n    await userEvent.click(checkbox);\n\n    expect(checkbox).not.toBeChecked();\n  });\n\n  it('should keep focus on the checkbox when checking/unchecking via', async () => {\n    renderWithProviders(<TelemetryBannerTestContainer />);\n\n    const checkbox = screen.getByRole('checkbox');\n\n    // Tab to Dismiss button\n    await userEvent.tab();\n\n    // Tab to checkbox\n    await userEvent.tab();\n\n    expect(checkbox).toHaveFocus();\n\n    expect(checkbox).not.toBeChecked();\n\n    // Check the checkbox via keyboard\n    await userEvent.type(checkbox, '{space}');\n\n    expect(checkbox).toHaveFocus();\n\n    expect(checkbox).toBeChecked();\n  });\n});\n"
  },
  {
    "path": "packages/wp-dashboard/src/components/updateBanner/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useRef,\n  useEffect,\n  createPortal,\n  useState,\n  useCallback,\n} from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport {\n  Banner,\n  Link,\n  localStore,\n  Text,\n} from '@googleforcreators/design-system';\nimport {\n  APP_ROUTES,\n  useRouteHistory,\n  useConfig,\n} from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport useTelemetryOptIn from '../../effects/useTelemetryOptIn';\nimport { EDITOR_SETTINGS_ROUTE } from '../../constants';\n\nconst StyledBanner = styled(Banner)`\n  background: ${({ theme }) => theme.colors.interactiveBg.brandNormal};\n`;\n\nconst StyledLink = styled(Link)`\n  color: ${({ theme }) => theme.colors.interactiveFg.brandNormal};\n  text-decoration: underline;\n\n  &:hover {\n    color: ${({ theme }) => theme.colors.interactiveFg.brandHover};\n  }\n\n  &:focus {\n    color: ${({ theme }) => theme.colors.interactiveFg.brandPress};\n  }\n`;\n\nfunction NoLink({ children }) {\n  return children;\n}\n\n// The value associated with this key indicates if the user has interacted with\n// the banner previously. If they have, we do not show the banner again for 2 days.\nconst LOCAL_STORAGE_KEY = 'web_stories_update_banner_closed';\n\nfunction getStateFromLocalStorage() {\n  const storageValue = localStore.getItemByKey(LOCAL_STORAGE_KEY);\n\n  if (!storageValue) {\n    return true;\n  }\n\n  if (new Date().getTime() > storageValue) {\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, null);\n    return true;\n  }\n\n  return false;\n}\n\nfunction UpdateBannerContainer() {\n  const { bannerVisible: hasTelemetryBanner } = useTelemetryOptIn();\n  const {\n    plugins: { 'web-stories': webStories = {} },\n  } = useConfig();\n  const { needsUpdate, updateLink } = webStories;\n\n  const ref = useRef();\n  const [isVisible, setIsVisible] = useState(false);\n\n  useEffect(() => {\n    setIsVisible(getStateFromLocalStorage() && needsUpdate);\n  }, [needsUpdate]);\n\n  const onClose = useCallback(() => {\n    const dayInMs = 8.64e7;\n    const expiry = new Date().getTime() + 2 * dayInMs;\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, expiry);\n    setIsVisible(false);\n  }, []);\n\n  if (!isVisible) {\n    return null;\n  }\n\n  if (hasTelemetryBanner) {\n    return null;\n  }\n\n  const UpdateLink = updateLink ? StyledLink : NoLink;\n\n  return (\n    <StyledBanner\n      closeButtonLabel={__('Dismiss update notification', 'web-stories')}\n      onClose={onClose}\n      title={__('Update available.', 'web-stories')}\n      ref={ref}\n    >\n      <Text.Paragraph>\n        <TranslateWithMarkup\n          mapping={{\n            a: <UpdateLink href={updateLink} />,\n          }}\n        >\n          {__(\n            'A new version of the plugin is available. <a>Please update now</a>.',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </StyledBanner>\n  );\n}\n\nexport default function UpdateBanner() {\n  const { currentPath, hasAvailableRoutes } = useRouteHistory(({ state }) => ({\n    currentPath: state.currentPath,\n    hasAvailableRoutes: state.availableRoutes.length > 0,\n  }));\n  const headerRef = useRef(null);\n  const [, forceUpdate] = useState(false);\n\n  useEffect(() => {\n    if (!hasAvailableRoutes) {\n      return;\n    }\n\n    if (\n      [\n        APP_ROUTES.DASHBOARD,\n        APP_ROUTES.TEMPLATES_GALLERY,\n        EDITOR_SETTINGS_ROUTE,\n      ].includes(currentPath)\n    ) {\n      headerRef.current = document.getElementById('body-view-options-header');\n      forceUpdate((value) => !value);\n    }\n  }, [currentPath, hasAvailableRoutes]);\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  if (!headerRef.current) {\n    return null;\n  }\n\n  // eslint-disable-next-line react-hooks/refs -- FIXME\n  return createPortal(<UpdateBannerContainer />, headerRef.current);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/constants/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './textConstants';\nexport * from './settings';\nexport * from './wpAdmin';\n"
  },
  {
    "path": "packages/wp-dashboard/src/constants/settings.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const EDITOR_SETTINGS_ROUTE = '/editor-settings';\n\nexport const LEFT_RAIL_SECONDARY_NAVIGATION = [\n  {\n    value: EDITOR_SETTINGS_ROUTE,\n    label: __('Settings', 'web-stories'),\n  },\n  {\n    value: __(\n      'https://wordpress.org/support/plugin/web-stories/',\n      'web-stories'\n    ),\n    label: __('Support', 'web-stories'),\n    isExternal: true,\n    trackingEvent: 'click_support_page',\n  },\n];\n\nexport const AD_NETWORK_TYPE = {\n  NONE: 'none',\n  ADSENSE: 'adsense',\n  ADMANAGER: 'admanager',\n  MGID: 'mgid',\n};\n\nexport const ARCHIVE_TYPE = {\n  DEFAULT: 'default',\n  DISABLED: 'disabled',\n  CUSTOM: 'custom',\n};\n\nexport const SHOPPING_PROVIDER_TYPE = {\n  NONE: 'none',\n  WOOCOMMERCE: 'woocommerce',\n  SHOPIFY: 'shopify',\n};\n\nexport const GOOGLE_ANALYTICS_HANDLER_TYPE = {\n  SITE_KIT: 'site-kit',\n  WEB_STORIES: 'web-stories',\n  BOTH: 'both',\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/constants/textConstants.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nexport const SUCCESS = {\n  SETTINGS: {\n    UPDATED: __('Setting saved.', 'web-stories'),\n  },\n};\n\nexport const ERRORS = {\n  UPLOAD_PUBLISHER_LOGO: {\n    MESSAGE: __('Unable to add publisher logo', 'web-stories'),\n    MESSAGE_PLURAL: __('Unable to add publisher logos', 'web-stories'),\n  },\n  REMOVE_PUBLISHER_LOGO: {\n    MESSAGE: __('Unable to remove publisher logo', 'web-stories'),\n  },\n  REMOVE_FONT: {\n    MESSAGE: __('Unable to remove font', 'web-stories'),\n  },\n  UPDATE_PUBLISHER_LOGO: {\n    MESSAGE: __('Unable to update publisher logo', 'web-stories'),\n  },\n  LOAD_PUBLISHER_LOGOS: {\n    MESSAGE: __('Unable to load publisher logos', 'web-stories'),\n  },\n  LOAD_SETTINGS: {\n    MESSAGE: __('Unable to load settings', 'web-stories'),\n  },\n  UPDATE_EDITOR_SETTINGS: {\n    MESSAGE: __('Unable to update settings data', 'web-stories'),\n  },\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/constants/wpAdmin.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TOOLBAR_HEIGHT = 32;\nexport const MENU_WIDTH = 160;\nexport const MENU_FOLDED_WIDTH = 36;\n"
  },
  {
    "path": "packages/wp-dashboard/src/effects/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as useSyncAdminMenu } from './useSyncAdminMenu.js';\nexport { default as useMediaOptimization } from './useMediaOptimization';\nexport { default as useTelemetryOptIn } from './useTelemetryOptIn';\n"
  },
  {
    "path": "packages/wp-dashboard/src/effects/useMediaOptimization.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useSnackbar } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { SUCCESS } from '../constants';\nimport useEditorSettings from '../components/editorSettings/useEditorSettings';\n\nexport default function useMediaOptimization() {\n  const { showSnackbar } = useSnackbar();\n\n  const { currentUser, toggleWebStoriesMediaOptimization } = useEditorSettings(\n    ({\n      state: { currentUser },\n      actions: {\n        usersApi: { toggleWebStoriesMediaOptimization },\n      },\n    }) => ({\n      currentUser,\n      toggleWebStoriesMediaOptimization,\n    })\n  );\n\n  const mediaOptimization = Boolean(\n    currentUser.data.meta?.webStoriesMediaOptimization\n  );\n\n  const _toggleWebStoriesMediaOptimization = useCallback(() => {\n    toggleWebStoriesMediaOptimization();\n    trackEvent('video_optimization_optin', {\n      status: mediaOptimization ? 'off' : 'on',\n    });\n    showSnackbar({\n      'aria-label': SUCCESS.SETTINGS.UPDATED,\n      message: SUCCESS.SETTINGS.UPDATED,\n      dismissible: true,\n    });\n  }, [mediaOptimization, showSnackbar, toggleWebStoriesMediaOptimization]);\n\n  return {\n    mediaOptimization,\n    disabled: currentUser.isUpdating,\n    toggleWebStoriesMediaOptimization: _toggleWebStoriesMediaOptimization,\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/effects/useSyncAdminMenu.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useRouteHistory } from '@googleforcreators/dashboard';\nimport { useEffect } from '@googleforcreators/react';\n\nfunction useSyncAdminMenu() {\n  const { currentPath } = useRouteHistory(({ state: { currentPath } }) => ({\n    currentPath,\n  }));\n\n  // Add hash location to \"Dashboard\" link on load.\n  useEffect(() => {\n    document\n      .querySelectorAll(\n        '#menu-posts-web-story ul.wp-submenu li a[href$=\"page=stories-dashboard\"]'\n      )\n      ?.forEach((el) => {\n        el.setAttribute('href', el.getAttribute('href') + '#/');\n      });\n  }, []);\n\n  // Sync up WP navigation bar with our hash location.\n  useEffect(() => {\n    document\n      .querySelectorAll('#menu-posts-web-story ul.wp-submenu li')\n      ?.forEach((el) => {\n        el.classList.remove('current');\n        el.querySelector('a')?.classList.remove('current');\n        el.querySelector('a')?.removeAttribute('aria-current');\n\n        if (el.querySelector(`a[href$=\"#${currentPath}\"]`)) {\n          el.classList.add('current');\n          el.querySelector('a')?.classList.add('current');\n          el.querySelector('a')?.setAttribute('aria-current', 'page');\n        }\n      });\n  }, [currentPath]);\n}\n\nexport default useSyncAdminMenu;\n"
  },
  {
    "path": "packages/wp-dashboard/src/effects/useTelemetryOptIn.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useCallback, useState, useEffect } from '@googleforcreators/react';\nimport { enableTracking, disableTracking } from '@googleforcreators/tracking';\nimport { useSnackbar, localStore } from '@googleforcreators/design-system';\nimport { useRouteHistory } from '@googleforcreators/dashboard';\n/**\n * Internal dependencies\n */\nimport useEditorSettings from '../components/editorSettings/useEditorSettings';\n\n/**\n * Internal dependencies\n */\nimport { SUCCESS, EDITOR_SETTINGS_ROUTE } from '../constants';\n\n// The value associated with this key indicates if the user has interacted with\n// the banner previously. If they have, we do not show the banner again.\nconst LOCAL_STORAGE_KEY = 'web_stories_tracking_optin_banner_closed';\n\nfunction setInitialBannerPreviouslyClosed() {\n  const storageValue = localStorage.getItem(LOCAL_STORAGE_KEY);\n\n  return Boolean(JSON.parse(storageValue));\n}\n\nexport default function useTelemetryOptIn() {\n  const { showSnackbar } = useSnackbar();\n\n  const [bannerPreviouslyClosed, setBannerPreviouslyClosed] = useState(\n    setInitialBannerPreviouslyClosed\n  );\n  const [optInCheckboxClicked, setOptInCheckboxClicked] = useState(false);\n  const { currentUser, toggleWebStoriesTrackingOptIn } = useEditorSettings(\n    ({\n      state: { currentUser },\n      actions: {\n        usersApi: { toggleWebStoriesTrackingOptIn },\n      },\n    }) => ({ currentUser, toggleWebStoriesTrackingOptIn })\n  );\n  const { currentPath } = useRouteHistory(({ state: { currentPath } }) => ({\n    currentPath,\n  }));\n\n  const dataIsLoaded =\n    currentUser.data.meta?.webStoriesTrackingOptin !== undefined;\n\n  const optedIn = Boolean(currentUser.data.meta?.webStoriesTrackingOptin);\n\n  useEffect(() => {\n    if (optedIn) {\n      enableTracking();\n    } else {\n      disableTracking();\n    }\n  }, [optedIn]);\n\n  const _toggleWebStoriesTrackingOptIn = useCallback(() => {\n    toggleWebStoriesTrackingOptIn();\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, true);\n    setOptInCheckboxClicked(true);\n    showSnackbar({\n      'aria-label': SUCCESS.SETTINGS.UPDATED,\n      message: SUCCESS.SETTINGS.UPDATED,\n      dismissible: true,\n    });\n  }, [showSnackbar, toggleWebStoriesTrackingOptIn]);\n\n  const closeBanner = useCallback(() => {\n    setBannerPreviouslyClosed(true);\n    localStore.setItemByKey(LOCAL_STORAGE_KEY, true);\n  }, []);\n\n  let bannerVisible = true;\n\n  if (\n    bannerPreviouslyClosed || // The banner has been closed before\n    currentPath === EDITOR_SETTINGS_ROUTE || // The user is on the settings page\n    !dataIsLoaded || // currentUser is not loaded yet\n    (!optInCheckboxClicked && optedIn) // currentUser is loaded and optedIn is true but the user has not checked the opt in checkbox\n  ) {\n    bannerVisible = false;\n  }\n\n  return {\n    bannerVisible,\n    optedIn,\n    disabled: currentUser.isUpdating,\n    closeBanner,\n    toggleWebStoriesTrackingOptIn: _toggleWebStoriesTrackingOptIn,\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n// The __webpack_public_path__ assignment will be done after the imports.\n// That's why the public path assignment is in its own dedicated module and imported here at the very top.\n// See https://webpack.js.org/guides/public-path/#on-the-fly\nimport './publicPath';\nimport './style.css'; // This way the general dashboard styles are loaded before all the component styles.\n\n// We need to load translations before any other imports happen.\n// That's why this is in its own dedicated module imported here at the very top.\nimport './setLocaleData';\n\n/**\n * External dependencies\n */\nimport { Dashboard } from '@googleforcreators/dashboard';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { StrictMode, render } from '@googleforcreators/react';\nimport { updateSettings } from '@googleforcreators/date';\nimport { initializeTracking } from '@googleforcreators/tracking';\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * WordPress dependencies\n */\nimport '@wordpress/dom-ready'; // Just imported here so it's part of the bundle. Usage is in inline scripts.\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from './api';\nimport { GlobalStyle } from './theme';\nimport {\n  LEFT_RAIL_SECONDARY_NAVIGATION,\n  TOOLBAR_HEIGHT,\n  MENU_FOLDED_WIDTH,\n} from './constants';\nimport { Layout } from './components';\n\nwindow.webStories = window.webStories || {};\n\n/**\n * Initializes the Web Stories dashboard screen.\n *\n * @param {string} id       ID of the root element to render the screen in.\n * @param {Object} config   Story editor settings.\n */\nwindow.webStories.initializeStoryDashboard = (id, config) => {\n  const appElement = document.getElementById(id);\n\n  // see http://reactcommunity.org/react-modal/accessibility/\n  setAppElement(appElement);\n\n  updateSettings(config.locale);\n\n  // Already tracking screen views in AppContent, no need to send page views as well.\n  initializeTracking('Dashboard', false);\n\n  const dashboardConfig = {\n    ...config,\n    apiCallbacks: bindToCallbacks(apiCallbacks, config),\n    leftRailSecondaryNavigation: LEFT_RAIL_SECONDARY_NAVIGATION,\n    documentTitleSuffix: __('Web Stories \\u2212 WordPress', 'web-stories'),\n    styleConstants: {\n      topOffset: TOOLBAR_HEIGHT,\n      leftOffset: MENU_FOLDED_WIDTH,\n    },\n    containerId: 'wpbody',\n  };\n\n  render(\n    <StrictMode>\n      <Dashboard config={dashboardConfig}>\n        <GlobalStyle />\n        <Layout />\n      </Dashboard>\n    </StrictMode>,\n    appElement\n  );\n};\n"
  },
  {
    "path": "packages/wp-dashboard/src/publicPath.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n__webpack_public_path__ = window.webStories.publicPath;\n"
  },
  {
    "path": "packages/wp-dashboard/src/setLocaleData.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { setLocaleData } from '@googleforcreators/i18n';\n\nfor (const localeData of window?.webStories?.localeData || []) {\n  setLocaleData(localeData);\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/style.css",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * WordPress admin page integration\n *\n * Hides all controls that interfere with the dashboard UI.\n */\n\nbody.js {\n  background: #fff;\n  color: #1a1d1f; /* theme.colors.gray900 */\n}\n\n#screen-meta,\n#screen-meta ~ :not(.web-stories-wp):not(.clear) {\n  display: none;\n}\n\nbody.web-story_page_stories-dashboard {\n  position: relative;\n  overflow: scroll;\n}\n\n#adminmenuback {\n  z-index: 4;\n}\n\n#menu-posts-web-story .wp-menu-image::before {\n  box-sizing: content-box;\n}\n\nbody.js.web-story_page_stories-dashboard #wpcontent,\nbody.js.web-story_page_stories-dashboard #wpbody-content {\n  padding: 0;\n}\n\nbody.web-story_page_stories-dashboard #wpbody {\n  position: relative;\n  width: 100%;\n  height: 100%;\n}\n\nbody.web-story_page_stories-dashboard #web-stories-dashboard .loading-message {\n  position: absolute;\n  left: 0;\n  top: 0;\n  right: 0;\n  height: 100%;\n  width: 100%;\n  text-align: center;\n  color: #131516;\n  margin: 0;\n  padding-top: 50px;\n  font-size: 36px;\n  font-family: 'Google Sans', sans-serif;\n}\n\n@keyframes spin-progress {\n  0%,\n  100% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  12.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  37.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  50% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  62.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  75% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #dfcdfe;\n  }\n  87.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #dfcdfe,\n      0.8em -0.8em 0 0em #dfcdfe,\n      1.14em 0em 0 0em #dfcdfe,\n      0.8em 0.8em 0 0em #dfcdfe,\n      0em 1.14em 0 0em #dfcdfe,\n      -0.8em 0.8em 0 0em #dfcdfe,\n      -1.14em 0em 0 0em #dfcdfe,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n}\nbody.web-story_page_stories-dashboard\n  #web-stories-dashboard\n  .loading-message:after {\n  content: '';\n  display: block;\n  position: absolute;\n  left: 0;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  margin: 140px auto auto;\n  width: 0.4em;\n  height: 0.4em;\n  border-radius: 50%;\n\n  animation: spin-progress 0.85s infinite\n    cubic-bezier(0.455, 0.03, 0.515, 0.955);\n}\n\nbody.web-story_page_stories-dashboard #wpfooter {\n  display: none;\n}\n\n/* Copied from forms.css in WordPress, avoids issues with \"Collapse menu\" button */\n\nbutton {\n  font-size: inherit;\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/testUtils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as renderWithProviders } from './renderWithProviders';\n"
  },
  {
    "path": "packages/wp-dashboard/src/testUtils/mockEditorProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useMemo, useState } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport Context from '../components/editorSettings/context';\n\nexport default function MockEditorProvider({ children, value }) {\n  const [currentUser, setCurrentUser] = useState(getCurrentUserState());\n\n  const usersApi = useMemo(\n    () => ({\n      toggleWebStoriesTrackingOptIn: () =>\n        setCurrentUser(toggleOptInTracking(currentUser)),\n    }),\n    [currentUser]\n  );\n\n  const mergedValue = useMemo(\n    () => ({\n      state: { currentUser },\n      actions: { usersApi },\n      ...value,\n    }),\n    [currentUser, usersApi, value]\n  );\n  return <Context.Provider value={mergedValue}>{children}</Context.Provider>;\n}\n\nMockEditorProvider.propTypes = {\n  children: PropTypes.node,\n  value: PropTypes.object,\n};\n\nfunction getCurrentUserState() {\n  return {\n    data: {\n      id: 1,\n      meta: {\n        web_stories_tracking_optin: false,\n        web_stories_onboarding: {},\n        web_stories_media_optimization: true,\n      },\n    },\n    isUpdating: false,\n  };\n}\n\nfunction toggleOptInTracking(currentUser) {\n  return {\n    ...currentUser,\n    data: {\n      ...currentUser.data,\n      meta: {\n        web_stories_tracking_optin:\n          !currentUser.data.meta.web_stories_tracking_optin,\n      },\n    },\n  };\n}\n"
  },
  {
    "path": "packages/wp-dashboard/src/testUtils/renderWithProviders.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { render } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { FlagsProvider } from 'flagged';\nimport {\n  theme as externalDesignSystemTheme,\n  lightMode,\n  SnackbarProvider,\n} from '@googleforcreators/design-system';\nimport { ConfigProvider } from '@googleforcreators/dashboard';\n\n/**\n * Internal dependencies\n */\nimport MockEditorProvider from './mockEditorProvider';\n\nconst defaultProviderValues = {\n  features: {},\n  theme: {\n    ...externalDesignSystemTheme,\n    colors: lightMode,\n  },\n  config: {\n    userId: 8675301,\n    allowedImageMimeTypes: ['image/png', 'image/jpeg', 'image/gif'],\n  },\n  api: {},\n};\n\nconst DefaultWrapper = ({ children }) => children;\n\nexport const renderWithProviders = (\n  ui,\n  providerValues = {},\n  renderOptions = {},\n  wrapper = DefaultWrapper\n) => {\n  const mergedProviderValues = { ...defaultProviderValues, ...providerValues };\n\n  const ProvidedWrapper = wrapper;\n\n  const Wrapper = ({ children }) => (\n    <ProvidedWrapper>\n      <FlagsProvider features={mergedProviderValues.features}>\n        <ThemeProvider theme={mergedProviderValues.theme}>\n          <ConfigProvider config={mergedProviderValues.config}>\n            <MockEditorProvider value={mergedProviderValues.api}>\n              <SnackbarProvider value={mergedProviderValues.snackbar}>\n                {children}\n              </SnackbarProvider>\n            </MockEditorProvider>\n          </ConfigProvider>\n        </ThemeProvider>\n      </FlagsProvider>\n    </ProvidedWrapper>\n  );\n\n  const mergedRenderOptions = { wrapper: Wrapper, ...renderOptions };\n\n  return render(ui, mergedRenderOptions);\n};\n\nexport default renderWithProviders;\n"
  },
  {
    "path": "packages/wp-dashboard/src/theme.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\nimport {\n  themeHelpers,\n  OVERLAY_CLASS,\n  BODY_CLASS,\n} from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { TOOLBAR_HEIGHT, MENU_WIDTH, MENU_FOLDED_WIDTH } from './constants';\n\nexport const GlobalStyle = createGlobalStyle`\n  body.web-story_page_stories-dashboard #wpbody {\n    ${themeHelpers.scrollbarCSS};\n  }\n\n  .${OVERLAY_CLASS} {\n    top: ${TOOLBAR_HEIGHT}px !important;\n    left: ${MENU_WIDTH}px !important;\n  }\n\n  body.folded .${OVERLAY_CLASS} {\n    left: ${MENU_FOLDED_WIDTH}px !important;\n  }\n\n  /*\n    Increase submenu z-index from 3 to 15 so it's above the modal overlay (z-index 10).\n    See https://github.com/GoogleForCreators/web-stories-wp/pull/12443\n  */\n  body.${BODY_CLASS} {\n    #adminmenuwrap, #adminmenuback {\n      z-index: 15;\n    }\n  }\n`;\n"
  },
  {
    "path": "packages/wp-story-editor/README.md",
    "content": "# WP Story Editor\n\nWeb stories editor for WordPress\n"
  },
  {
    "path": "packages/wp-story-editor/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/wp-story-editor\",\n  \"description\": \"WordPress Web Stories editor\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/wp-story-editor/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/wp-story-editor\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.js\",\n  \"dependencies\": {\n    \"@googleforcreators/date\": \"*\",\n    \"@googleforcreators/design-system\": \"*\",\n    \"@googleforcreators/element-library\": \"*\",\n    \"@googleforcreators/elements\": \"*\",\n    \"@googleforcreators/i18n\": \"*\",\n    \"@googleforcreators/media\": \"*\",\n    \"@googleforcreators/migration\": \"*\",\n    \"@googleforcreators/output\": \"*\",\n    \"@googleforcreators/react\": \"*\",\n    \"@googleforcreators/story-editor\": \"*\",\n    \"@googleforcreators/tracking\": \"*\",\n    \"@googleforcreators/url\": \"*\",\n    \"@web-stories-wp/wp-utils\": \"*\",\n    \"@wordpress/api-fetch\": \"^7.43.0\",\n    \"@wordpress/dom-ready\": \"^4.22.0\",\n    \"flagged\": \"^2.0.10\",\n    \"polished\": \"^4.3.1\",\n    \"react-calendar\": \"^4.3.0\",\n    \"styled-components\": \"^5.3.11\"\n  },\n  \"devDependencies\": {\n    \"@googleforcreators/test-utils\": \"*\",\n    \"@testing-library/react\": \"^12.1.5\",\n    \"@testing-library/react-hooks\": \"^8.0.1\",\n    \"mockdate\": \"^3.0.5\",\n    \"prop-types\": \"^15.8.1\"\n  }\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/authors.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\nexport function getAuthors(config, search) {\n  return apiFetch({\n    path: addQueryArgs(config.api.users, {\n      per_page: '100',\n      capabilities: config.editPostsCapabilityName,\n      search,\n    }),\n  }).then((resp) => {\n    return resp.map((author) => {\n      delete author._links;\n      return snakeToCamelCaseObjectKeys(author);\n    });\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/constants/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Important: Keep in sync with REST API preloading definition.\nexport const STORY_FIELDS = [\n  'id',\n  'title',\n  'status',\n  'slug',\n  'date',\n  'modified',\n  'excerpt',\n  'link',\n  'story_poster',\n  'story_data',\n  'preview_link',\n  'edit_link',\n  'embed_post_link',\n  'permalink_template',\n  'style_presets',\n  'password',\n  '_links',\n  '_embedded',\n].join(',');\n\nexport const STORY_EMBED = 'wp:lock,author,wp:publisherlogo,wp:term';\n\nexport const MEDIA_FIELDS = [\n  'id',\n  'date_gmt',\n  'media_details',\n  'mime_type',\n  'featured_media',\n  'featured_media_src',\n  'alt_text',\n  'source_url',\n  'meta',\n  'web_stories_media_source',\n  'web_stories_is_muted',\n  // _web_stories_envelope will add these fields, we need them too.\n  'body',\n  'status',\n  'headers',\n].join(',');\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/fonts.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Assembles the `&include` query parameter.\n *\n * Works around a bug in WordPress.\n *\n * @see https://github.com/GoogleForCreators/web-stories-wp/issues/10710\n * @param {string} include Comma-separated list of fonts to include.\n * @return {string} include query parameter with bracket notation.\n */\nfunction getIncludeQueryArgs(include = '') {\n  return include\n    .split(',')\n    .filter(Boolean)\n    .map((item) => `include[]=${encodeURI(item)}`)\n    .join('&');\n}\n\nexport function getFonts(config, { include: _include, search, service }) {\n  let path = addQueryArgs(`${config.api.fonts}`, {\n    search,\n    service,\n    per_page: 100,\n  });\n  const include = getIncludeQueryArgs(_include);\n  if (include.length > 0) {\n    path += path.includes('?') ? `&${include}` : `?${include}`;\n  }\n  return apiFetch({\n    path,\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/hotlinkInfo.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\nexport function getHotlinkInfo(config, url) {\n  const path = addQueryArgs(config.api.hotlink, { url });\n  return apiFetch({\n    path,\n  }).then(snakeToCamelCaseObjectKeys);\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './authors';\nexport * from './story';\nexport * from './media';\nexport * from './metadata';\nexport * from './pageTemplate';\nexport * from './user';\nexport * from './hotlinkInfo';\nexport * from './proxy';\nexport * from './taxonomy';\nexport * from './fonts';\nexport * from './shopping';\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/media.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { flattenFormData, getResourceFromAttachment } from './utils';\nimport { MEDIA_FIELDS } from './constants';\n\n// Important: Keep in sync with REST API preloading definition.\nexport function getMedia(config, { mediaType, searchTerm, pagingNum }) {\n  let path = addQueryArgs(config.api.media, {\n    context: 'view',\n    per_page: 50,\n    page: pagingNum,\n    _web_stories_envelope: true,\n    _fields: MEDIA_FIELDS,\n  });\n\n  if (mediaType) {\n    path = addQueryArgs(path, { media_type: mediaType });\n  }\n\n  if (searchTerm) {\n    path = addQueryArgs(path, { search: searchTerm });\n  }\n\n  return apiFetch({ path }).then(({ body: attachments, headers }) => ({\n    data: attachments.map(getResourceFromAttachment),\n    headers: {\n      ...headers,\n      totalItems: headers['X-WP-Total'],\n      totalPages: headers['X-WP-TotalPages'],\n    },\n  }));\n}\n\n// Important: Keep in sync with REST API preloading definition.\nexport function getMediaForCorsCheck(config) {\n  const path = addQueryArgs(config.api.media, {\n    context: 'view',\n    per_page: 10,\n    _fields: 'source_url',\n  });\n\n  return apiFetch({ path }).then((attachments) =>\n    attachments.map((attachment) => attachment.source_url)\n  );\n}\n\n/**\n * Get media by ID.\n *\n * @param {Object} config Configuration object.\n * @param {number} mediaId Media ID.\n * @return {Promise<import('@googleforcreators/media').Resource>} Media object promise.\n */\nexport function getMediaById(config, mediaId) {\n  const path = addQueryArgs(`${config.api.media}${mediaId}/`, {\n    context: 'view',\n    _fields: MEDIA_FIELDS,\n  });\n\n  return apiFetch({ path }).then(getResourceFromAttachment);\n}\n\n/**\n * Get the muted variant of a given media resource.\n *\n * @param {Object} config Configuration object.\n * @param {number} mediaId Media ID.\n * @return {Promise<import('@googleforcreators/media').Resource>} Media resource if found, null otherwise.\n */\nexport async function getMutedMediaById(config, mediaId) {\n  const path = addQueryArgs(`${config.api.media}${mediaId}/`, {\n    context: 'view',\n    _fields: 'meta.web_stories_muted_id',\n  });\n\n  const result = await apiFetch({ path });\n\n  if (result?.meta?.web_stories_muted_id) {\n    return getMediaById(config, result.meta.web_stories_muted_id);\n  }\n\n  return null;\n}\n\n/**\n * Get the optimized variant of a given media resource.\n *\n * @param {Object} config Configuration object.\n * @param {number} mediaId Media ID.\n * @return {Promise<import('@googleforcreators/media').Resource>} Media resource if found, null otherwise.\n */\nexport async function getOptimizedMediaById(config, mediaId) {\n  const path = addQueryArgs(`${config.api.media}${mediaId}/`, {\n    context: 'view',\n    _fields: 'meta.web_stories_optimized_id',\n  });\n\n  const result = await apiFetch({ path });\n\n  if (result?.meta?.web_stories_optimized_id) {\n    return getMediaById(config, result.meta.web_stories_optimized_id);\n  }\n\n  return null;\n}\n\n/**\n * Get the poster of a given media resource.\n *\n * @param {Object} config Configuration object.\n * @param {number} mediaId Media ID.\n * @return {Promise<import('@googleforcreators/media').Resource>} Media resource if found, null otherwise.\n */\nexport async function getPosterMediaById(config, mediaId) {\n  const path = addQueryArgs(`${config.api.media}${mediaId}/`, {\n    context: 'view',\n    _fields: 'featured_media',\n  });\n\n  const result = await apiFetch({ path });\n\n  if (result?.featured_media) {\n    return getMediaById(config, result.featured_media);\n  }\n\n  return null;\n}\n\n/**\n * Upload file to via REST API.\n *\n * @param {Object} config Configuration object.\n * @param {File} file Media File to Save.\n * @param {?Object} additionalData Additional data to include in the request.\n * @return {Promise<import('@googleforcreators/media').Resource>} Media resource.\n */\nexport function uploadMedia(config, file, additionalData) {\n  const {\n    originalId,\n    mediaId,\n    storyId,\n    templateId,\n    optimizedId,\n    cropOriginId,\n    mutedId,\n    posterId,\n    isMuted,\n    mediaSource,\n    trimData,\n    baseColor,\n    blurHash,\n    isGif,\n    altText,\n  } = additionalData;\n\n  const wpKeysMapping = {\n    web_stories_media_source: mediaSource,\n    web_stories_is_muted: isMuted,\n    post: templateId || storyId || mediaId,\n    original_id: originalId,\n    meta: {\n      web_stories_base_color: baseColor,\n      web_stories_blurhash: blurHash,\n      web_stories_cropped_origin_id: cropOriginId,\n      web_stories_optimized_id: optimizedId,\n      web_stories_muted_id: mutedId,\n      web_stories_poster_id: posterId,\n      web_stories_trim_data: trimData,\n      web_stories_is_gif: isGif,\n    },\n    alt_text: altText,\n  };\n\n  Object.entries(wpKeysMapping.meta).forEach(([key, value]) => {\n    if (value === undefined) {\n      delete wpKeysMapping.meta[key];\n    }\n  });\n\n  Object.entries(wpKeysMapping).forEach(([key, value]) => {\n    if (value === undefined) {\n      delete wpKeysMapping[key];\n    }\n  });\n\n  // Create upload payload\n  const data = new window.FormData();\n  data.append('file', file, file.name || file.type.replace('/', '.'));\n  Object.entries(wpKeysMapping).forEach(([key, value]) =>\n    flattenFormData(data, key, value)\n  );\n\n  // TODO: Intercept window.fetch here to support progressive upload indicator when uploading\n  return apiFetch({\n    path: config.api.media,\n    body: data,\n    method: 'POST',\n  }).then((attachment) => getResourceFromAttachment(attachment));\n}\n\n/**\n * Update Existing media.\n *\n * @param  {Object} config API path.\n * @param  {number} mediaId Media id\n * @param  {Object} data Object of properties to update on attachment.\n * @return {Promise} Media Object Promise.\n */\nexport function updateMedia(config, mediaId, data) {\n  const {\n    baseColor,\n    blurHash,\n    isMuted,\n    mediaSource,\n    optimizedId,\n    cropOriginId,\n    mutedId,\n    posterId,\n    storyId,\n    altText,\n  } = data;\n\n  const wpKeysMapping = {\n    meta: {\n      web_stories_base_color: baseColor,\n      web_stories_blurhash: blurHash,\n      web_stories_optimized_id: optimizedId,\n      web_stories_muted_id: mutedId,\n      web_stories_cropped_origin_id: cropOriginId,\n      web_stories_poster_id: posterId,\n    },\n    web_stories_is_muted: isMuted,\n    web_stories_media_source: mediaSource,\n    featured_media: posterId,\n    post: storyId,\n    alt_text: altText,\n  };\n\n  Object.entries(wpKeysMapping.meta).forEach(([key, value]) => {\n    if (value === undefined) {\n      delete wpKeysMapping.meta[key];\n    }\n  });\n\n  Object.entries(wpKeysMapping).forEach(([key, value]) => {\n    if (value === undefined) {\n      delete wpKeysMapping[key];\n    }\n  });\n  return apiFetch({\n    path: `${config.api.media}${mediaId}/`,\n    data: wpKeysMapping,\n    method: 'POST',\n  }).then(getResourceFromAttachment);\n}\n\n/**\n * Delete existing media.\n *\n * @param {Object} config Configuration object.\n * @param  {number} mediaId Media id\n * @return {void}\n */\nexport function deleteMedia(config, mediaId) {\n  // `apiFetch` by default turns `DELETE` requests into `POST` requests\n  // with `X-HTTP-Method-Override: DELETE` headers.\n  // However, some Web Application Firewall (WAF) solutions prevent this.\n  // `?_method=DELETE` is an alternative solution to override the request method.\n  // See https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/#_method-or-x-http-method-override-header\n  apiFetch({\n    path: addQueryArgs(`${config.api.media}${mediaId}/`, { _method: 'DELETE' }),\n    data: { force: true },\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/metaboxes.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n// See https://github.com/WordPress/gutenberg/blob/148e2b28d4cdd4465c4fe68d97fcee154a6b209a/packages/edit-post/src/store/effects.js#L72-L126\nexport function saveMetaBoxes(story, formData, apiUrl) {\n  // Additional data needed for backward compatibility.\n  // If we do not provide this data, the post will be overridden with the default values.\n  const additionalData = [\n    story.comment_status ? ['comment_status', story.comment_status] : false,\n    story.ping_status ? ['ping_status', story.ping_status] : false,\n    story.sticky ? ['sticky', story.sticky] : false,\n    story.author ? ['post_author', story.author.id] : false,\n  ].filter(Boolean);\n\n  additionalData.forEach(([key, value]) => formData.append(key, value));\n\n  return apiFetch({\n    url: apiUrl,\n    method: 'POST',\n    body: formData,\n    parse: false,\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/metadata.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Gets metadata (title, favicon, etc.) from\n * a provided URL.\n *\n * @param {Object} config API path.\n * @param {string} url Url\n * @return {Promise} Result promise\n */\nexport function getLinkMetadata(config, url) {\n  const path = addQueryArgs(config.api.link, { url });\n  return apiFetch({\n    path,\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/pageTemplate.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\nconst TEMPLATE_FIELDS = [\n  'id',\n  'story_data',\n  'title',\n  // _web_stories_envelope will add these fields, we need them too.\n  'body',\n  'headers',\n  '_embedded',\n];\n\nconst TEMPLATE_EMBED = 'wp:featuredmedia';\n\nfunction transformResponse(template) {\n  const {\n    _embedded: embedded = {},\n    id: templateId,\n    story_data = {},\n    title,\n  } = template;\n  const image = {\n    id: embedded?.['wp:featuredmedia']?.[0].id || 0,\n    height: embedded?.['wp:featuredmedia']?.[0]?.media_details?.height || 0,\n    width: embedded?.['wp:featuredmedia']?.[0]?.media_details?.width || 0,\n    url: embedded?.['wp:featuredmedia']?.[0]?.source_url || '',\n    needsProxy: false,\n    isExternal: false,\n  };\n  return {\n    id: templateId,\n    elements: [],\n    ...story_data,\n    templateId,\n    image,\n    title,\n  };\n}\n\nexport function getCustomPageTemplates(config, page = 1, search) {\n  const perPage = 100;\n  const path = addQueryArgs(config.api.pageTemplates, {\n    context: 'edit',\n    per_page: perPage,\n    page,\n    search,\n    _web_stories_envelope: true,\n    _fields: TEMPLATE_FIELDS,\n    _embed: TEMPLATE_EMBED,\n  });\n  return apiFetch({ path }).then(({ headers, body }) => {\n    const totalPages = Number.parseInt(headers['X-WP-TotalPages']);\n    const templates = body.map(transformResponse);\n    return {\n      templates,\n      hasMore: totalPages > page,\n    };\n  });\n}\n\n/**\n * Add a new page template.\n *\n * @param {Object} config Config object.\n * @param {Object} data Page template data.\n * @return {Promise<*>} Saved page template.\n */\nexport function addPageTemplate(config, data) {\n  return apiFetch({\n    path: config.api.pageTemplates,\n    data: {\n      ...data,\n      status: 'publish',\n    },\n    method: 'POST',\n  }).then(transformResponse);\n}\n\n/**\n * Update an existing page template.\n *\n * @param {Object} config Config object.\n * @param {number} id Page template ID.\n * @param {Object} data Page template data.\n * @return {Promise<*>} Saved page template.\n */\nexport function updatePageTemplate(config, id, data) {\n  return apiFetch({\n    path: `${config.api.pageTemplates}${id}/`,\n    data: {\n      ...data,\n    },\n    method: 'POST',\n  }).then(transformResponse);\n}\n\nexport function deletePageTemplate(config, id) {\n  // `?_method=DELETE` is an alternative solution to override the request method.\n  // See https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/#_method-or-x-http-method-override-header\n  return apiFetch({\n    path: addQueryArgs(`${config.api.pageTemplates}${id}/`, {\n      _method: 'DELETE',\n    }),\n    data: { force: true },\n    method: 'POST',\n  }); // Response is not being used in core editor.\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/proxy.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\nexport function getProxyUrl(config, url) {\n  return addQueryArgs(config.api.proxy, { url, _wpnonce: config.nonce });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/publisherLogos.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Get publisher logos.\n *\n * @param {string} apiPath API path.\n * @return {Promise} Response.\n */\nexport function getPublisherLogos(apiPath) {\n  return apiFetch({\n    path: apiPath,\n  });\n}\n\n/**\n * Add publisher logo.\n *\n * @param {string} apiPath API path.\n * @param {string} id Logo media id.\n * @return {Promise} Response.\n */\nexport function addPublisherLogo(apiPath, id) {\n  return apiFetch({\n    path: apiPath,\n    data: { id },\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/shopping.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Get products\n *\n * @param {Object} config Configuration object.\n * @param {string} search Search term.\n * @param {number} page Page number.\n * @param {string} orderby Order collection by product attribute.\n * @param {string} order Sort attribute ascending or descending.\n * @return {Promise} The response from the API.\n */\nexport async function getProducts(config, search, page, orderby, order) {\n  const response = await apiFetch({\n    path: addQueryArgs(config.api.products, {\n      per_page: 50,\n      page,\n      search,\n      orderby,\n      order,\n      _web_stories_envelope: true,\n    }),\n  });\n\n  return {\n    products: response?.body,\n    hasNextPage: response?.headers['X-WP-HasNextPage'] === 'true',\n  };\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/statusCheck.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { base64Encode } from './utils';\n\n/**\n * Status check, submit html string.\n *\n * @param {string} content Content string.\n * @param {string} statusCheck Status check\n * @param {string} encodeMarkup Encode markup\n * @return {Promise} Result promise\n */\nexport function getStatusCheck(content, statusCheck, encodeMarkup) {\n  return apiFetch({\n    path: statusCheck,\n    data: { content: encodeMarkup ? base64Encode(content) : content },\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/story.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport { DATA_VERSION } from '@googleforcreators/migration';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORY_EMBED, STORY_FIELDS } from './constants';\nimport { base64Encode, transformStoryResponse } from './utils';\n\nexport function getStoryById(config, storyId) {\n  const path = addQueryArgs(`${config.api.stories}${storyId}/`, {\n    context: 'edit',\n    _embed: STORY_EMBED,\n    _fields: STORY_FIELDS,\n  });\n\n  return apiFetch({ path }).then(transformStoryResponse);\n}\n\nconst getStorySaveData = (\n  {\n    pages,\n    fonts,\n    featuredMedia,\n    globalStoryStyles,\n    publisherLogo,\n    autoAdvance,\n    defaultPageDuration,\n    currentStoryStyles,\n    backgroundAudio,\n    content,\n    author,\n    products,\n    ...rest\n  },\n  encodeMarkup\n) => {\n  return {\n    story_data: {\n      version: DATA_VERSION,\n      pages,\n      fonts,\n      autoAdvance,\n      defaultPageDuration,\n      currentStoryStyles,\n      backgroundAudio,\n    },\n    featured_media: !featuredMedia.isExternal ? featuredMedia.id : null,\n    style_presets: globalStoryStyles,\n    meta: {\n      web_stories_publisher_logo: publisherLogo?.id,\n      web_stories_products: products,\n      web_stories_poster: featuredMedia.isExternal\n        ? {\n            url: featuredMedia.url,\n            width: featuredMedia.width,\n            height: featuredMedia.height,\n            needsProxy: featuredMedia.needsProxy,\n          }\n        : null, // null ensures the meta value will be deleted.\n    },\n    publisher_logo: publisherLogo,\n    content: encodeMarkup ? base64Encode(content) : content,\n    author: author.id,\n    ...rest,\n  };\n};\n\n/**\n * Fire REST API call to save story.\n *\n * @param {Object} config Configuration object.\n * @param {import('@googleforcreators/elements').Story} story Story object.\n * @return {Promise} Return apiFetch promise.\n */\nexport function saveStoryById(config, story) {\n  const { storyId } = story;\n  const storySaveData = getStorySaveData(story, config.encodeMarkup);\n\n  // Only require these fields in the response as used by useSaveStory()\n  // to reduce response size.\n  const path = addQueryArgs(`${config.api.stories}${storyId}/`, {\n    _fields: [\n      'status',\n      'slug',\n      'link',\n      'preview_link',\n      'edit_link',\n      '_links',\n      'embed_post_link',\n      'story_poster',\n      'date',\n      'modified',\n    ].join(','),\n    _embed: STORY_EMBED,\n  });\n\n  return apiFetch({\n    path,\n    data: storySaveData,\n    method: 'POST',\n  }).then((data) => {\n    const { story_poster: storyPoster, _links: links = {}, ...rest } = data;\n\n    const revisions = {\n      count: links?.['version-history']?.[0]?.count,\n      id: links?.['predecessor-version']?.[0]?.id,\n    };\n\n    const featuredMedia = storyPoster\n      ? {\n          ...storyPoster,\n          isExternal: !storyPoster.id,\n        }\n      : {\n          id: 0,\n          height: 0,\n          width: 0,\n          url: '',\n          needsProxy: false,\n          isExternal: false,\n        };\n\n    return {\n      ...snakeToCamelCaseObjectKeys(rest),\n      featuredMedia,\n      revisions,\n    };\n  });\n}\n\n/**\n * Fire REST API call to auto-save story.\n *\n * @param {Object} config API path.\n * @param {import('@googleforcreators/elements').Story} story Story object.\n * @return {Promise} Return apiFetch promise.\n */\nexport function autoSaveById(config, story) {\n  const { storyId } = story;\n  const storySaveData = getStorySaveData(story, config.encodeMarkup);\n\n  return apiFetch({\n    path: `${config.api.stories}${storyId}/autosaves/`,\n    data: storySaveData,\n    method: 'POST',\n  }).then((resp) => snakeToCamelCaseObjectKeys(resp, ['story_data']));\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/storyLock.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\nexport function getStoryLockById(storyId, stories) {\n  return apiFetch({ path: `${stories}${storyId}/lock/` });\n}\n\nexport function setStoryLockById(storyId, stories) {\n  const path = `${stories}${storyId}/lock/`;\n  return apiFetch({ path, method: 'POST' });\n}\n\nexport function deleteStoryLockById(storyId, nonce, storyLocking) {\n  const data = new window.FormData();\n  data.append('_wpnonce', nonce);\n\n  const url = addQueryArgs(storyLocking, { _method: 'DELETE' });\n\n  window.navigator.sendBeacon?.(url, data);\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/taxonomy.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { addQueryArgs } from '@googleforcreators/url';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Get all taxonomies.\n *\n * @param {Object} config Configuration object.\n * @return {Promise} Taxonomies promise.\n */\nexport async function getTaxonomies(config) {\n  const result = await apiFetch({\n    path: addQueryArgs(config.api.taxonomies, {\n      type: config.postType,\n      context: 'edit',\n      show_ui: 'true',\n    }),\n  });\n\n  return Object.values(result).map((taxonomy) => {\n    taxonomy.restPath = taxonomy['_links']?.['wp:items']?.[0]?.href;\n    delete taxonomy['_links'];\n\n    return snakeToCamelCaseObjectKeys(taxonomy, ['capabilities', 'visibility']);\n  });\n}\n\n/**\n * Get a taxonomy term.\n *\n * @param {Object} config configuration object.\n * @param {string} endpoint absolute url to interact with taxonomy\n * @param {Object} args Additional args.\n * @return {Promise} Term promise.\n */\nexport function getTaxonomyTerm(config, endpoint, args = {}) {\n  return apiFetch({\n    url: addQueryArgs(endpoint, args),\n  });\n}\n\n/**\n * Create a new taxonomy term.\n *\n * @param {Object} config configuration object.\n * @param {string} endpoint absolute url to interact with taxonomy\n * @param {Object} args The args being sent.\n * @param {string} args.name The name.\n * @param {number|string} args.parent The parent id.\n * @return {Promise} Term promise.\n */\nexport function createTaxonomyTerm(config, endpoint, args) {\n  return apiFetch({\n    url: addQueryArgs(endpoint, args),\n    method: 'POST',\n  });\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/_utils.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const GET_MEDIA_RESPONSE_HEADER = {\n  'X-WP-Total': 1,\n  'X-WP-TotalPages': 1,\n};\n\nexport const GET_MEDIA_RESPONSE_BODY = [\n  {\n    id: 274,\n    date: '2020-09-01T05:33:54',\n    date_gmt: '2020-09-01T05:33:54',\n    guid: {\n      rendered: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n      raw: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n    },\n    modified: '2020-09-01T05:33:54',\n    modified_gmt: '2020-09-01T05:33:54',\n    slug: 'IMAGE',\n    status: 'inherit',\n    type: 'attachment',\n    link: 'http://wp.local/IMAGE/',\n    title: {\n      raw: 'IMAGE',\n      rendered: 'IMAGE',\n    },\n    author: { id: 1, name: 'John Doe' },\n    featured_media: 0,\n    comment_status: 'open',\n    ping_status: 'closed',\n    template: '',\n    meta: {\n      web_stories_is_poster: false,\n      web_stories_poster_id: 0,\n    },\n    web_stories_is_muted: false,\n    web_story_media_source: [2],\n    permalinkTemplate: 'http://wp.local/?attachment_id=274',\n    generated_slug: 'IMAGE',\n    web_stories_media_source: 'editor',\n    featured_media_src: [],\n    description: {\n      raw: '',\n      rendered: '<p class=\"attachment\">link</p>\\n',\n    },\n    caption: { raw: '', rendered: '' },\n    alt_text: 'IMAGE',\n    media_type: 'image',\n    mime_type: 'image/jpeg',\n    media_details: {\n      width: 1080,\n      height: 2220,\n      file: '2020/09/IMAGE.jpg',\n      sizes: {\n        medium: {\n          file: 'IMAGE-146x300.jpg',\n          width: 146,\n          height: 300,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-146x300.jpg',\n        },\n        large: {\n          file: 'IMAGE-498x1024.jpg',\n          width: 498,\n          height: 1024,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-498x1024.jpg',\n        },\n        thumbnail: {\n          file: 'IMAGE-150x150.jpg',\n          width: 150,\n          height: 150,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x150.jpg',\n        },\n        medium_large: {\n          file: 'IMAGE-768x1579.jpg',\n          width: 768,\n          height: 1579,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-768x1579.jpg',\n        },\n        '1536x1536': {\n          file: 'IMAGE-747x1536.jpg',\n          width: 747,\n          height: 1536,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-747x1536.jpg',\n        },\n        '2048x2048': {\n          file: 'IMAGE-996x2048.jpg',\n          width: 996,\n          height: 2048,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-996x2048.jpg',\n        },\n        'web-stories-poster-portrait': {\n          file: 'IMAGE-640x853.jpg',\n          width: 640,\n          height: 853,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-640x853.jpg',\n        },\n        'web-stories-publisher-logo': {\n          file: 'IMAGE-96x96.jpg',\n          width: 96,\n          height: 96,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-96x96.jpg',\n        },\n        'web-stories-thumbnail': {\n          file: 'IMAGE-150x308.jpg',\n          width: 150,\n          height: 308,\n          mime_type: 'image/jpeg',\n          source_url:\n            'http://wp.local/wp-content/uploads/2020/09/IMAGE-150x308.jpg',\n        },\n        full: {\n          file: 'IMAGE.jpg',\n          width: 1080,\n          height: 2220,\n          mime_type: 'image/jpeg',\n          source_url: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n        },\n      },\n      image_meta: {\n        aperture: '0',\n        credit: '',\n        camera: '',\n        caption: '',\n        created_timestamp: '0',\n        copyright: '',\n        focal_length: '0',\n        iso: '0',\n        shutter_speed: '0',\n        title: '',\n        orientation: '0',\n        keywords: [],\n      },\n    },\n    post: null,\n    source_url: 'http://wp.local/wp-content/uploads/2020/09/IMAGE.jpg',\n    missing_image_sizes: [],\n    _links: {\n      self: [{ href: 'http://wp.local/wp-json/web-stories/v1/media/274' }],\n      collection: [{ href: 'http://wp.local/wp-json/web-stories/v1/media' }],\n      about: [{ href: 'http://wp.local/wp-json/wp/v2/types/attachment' }],\n      author: [\n        { embeddable: true, href: 'http://wp.local/wp-json/wp/v2/users/1' },\n      ],\n      replies: [\n        {\n          embeddable: true,\n          href: 'http://wp.local/wp-json/wp/v2/comments?post=274',\n        },\n      ],\n      'wp:term': [\n        {\n          taxonomy: 'web_story_media_source',\n          embeddable: true,\n          href: 'http://wp.local/wp-json/wp/v2/web_story_media_source?post=274',\n        },\n      ],\n      'wp:action-unfiltered-html': [\n        { href: 'http://wp.local/wp-json/web-stories/v1/media/274' },\n      ],\n      'wp:action-assign-author': [\n        { href: 'http://wp.local/wp-json/web-stories/v1/media/274' },\n      ],\n      'wp:action-create-web_story_media_source': [\n        { href: 'http://wp.local/wp-json/web-stories/v1/media/274' },\n      ],\n      'wp:action-assign-web_story_media_source': [\n        { href: 'http://wp.local/wp-json/web-stories/v1/media/274' },\n      ],\n      curies: [\n        { name: 'wp', href: 'https://api.w.org/{rel}', templated: true },\n      ],\n    },\n  },\n];\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/fonts.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '..';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('Fonts API Callbacks', () => {\n  afterEach(() => {\n    apiFetch.mockReset();\n  });\n\n  it('should not add include param if not provided', () => {\n    const { getFonts } = bindToCallbacks(apiCallbacks, {\n      api: { fonts: '/web-stories/v1/fonts/' },\n    });\n\n    getFonts({\n      service: 'fonts.google.com',\n    });\n\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: expect.not.stringContaining('include[]='),\n      })\n    );\n  });\n\n  it('should include fonts with square bracket notation', () => {\n    const { getFonts } = bindToCallbacks(apiCallbacks, {\n      api: { fonts: '/web-stories/v1/fonts/' },\n    });\n\n    getFonts({\n      include: ['Roboto Mono', 'Roboto Serif'].join(','),\n    });\n\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: expect.stringContaining(\n          'include[]=Roboto%20Mono&include[]=Roboto%20Serif'\n        ),\n      })\n    );\n  });\n\n  it('should include fonts with square bracket notation after other query params', () => {\n    const { getFonts } = bindToCallbacks(apiCallbacks, {\n      api: { fonts: '/web-stories/v1/fonts/' },\n    });\n\n    getFonts({\n      service: 'fonts.google.com',\n      include: ['Roboto Mono', 'Roboto Serif'].join(','),\n    });\n\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: expect.stringContaining(\n          '&include[]=Roboto%20Mono&include[]=Roboto%20Serif'\n        ),\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/media.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '..';\nimport { flattenFormData } from '../utils';\nimport { GET_MEDIA_RESPONSE_BODY } from './_utils';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('Media API Callbacks', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n  const MEDIA_PATH = `/web-stories/v1/media/`;\n\n  it('updateMedia maps arguments to expected format', () => {\n    apiFetch.mockReturnValue(Promise.resolve(GET_MEDIA_RESPONSE_BODY[0]));\n    const { updateMedia } = bindToCallbacks(apiCallbacks, {\n      api: { media: MEDIA_PATH },\n    });\n\n    const mediaId = 1;\n    const mockData = {\n      baseColor: '#123456',\n      blurHash: 'asdafd-dsfgh',\n      isMuted: false,\n      mediaSource: 'source-video',\n      optimizedId: 12,\n      mutedId: 13,\n      altText: 'New Alt Text',\n      storyId: 11,\n      posterId: 14,\n    };\n    const expectedWpKeysMapping = {\n      meta: {\n        web_stories_base_color: mockData.baseColor,\n        web_stories_blurhash: mockData.blurHash,\n        web_stories_optimized_id: mockData.optimizedId,\n        web_stories_muted_id: mockData.mutedId,\n        web_stories_poster_id: mockData.posterId,\n      },\n      web_stories_is_muted: mockData.isMuted,\n      web_stories_media_source: mockData.mediaSource,\n      post: mockData.storyId,\n      featured_media: mockData.posterId,\n      alt_text: mockData.altText,\n    };\n\n    updateMedia(mediaId, mockData);\n\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: MEDIA_PATH + `${mediaId}/`,\n        method: 'POST',\n        data: expectedWpKeysMapping,\n      })\n    );\n  });\n\n  it('uploadMedia maps arguments to expected format', () => {\n    apiFetch.mockReturnValue(Promise.resolve(GET_MEDIA_RESPONSE_BODY[0]));\n    const { uploadMedia } = bindToCallbacks(apiCallbacks, {\n      api: { media: MEDIA_PATH },\n    });\n\n    const file = new File([''], 'filename');\n\n    const mockData = {\n      originalId: 11,\n      templateId: 12,\n      isMuted: false,\n      mediaSource: 'source-video',\n      trimData: { data: 'trimData' },\n      baseColor: '#123456',\n      blurHash: 'asdafd-dsfgh',\n    };\n    const expectedWpKeysMapping = {\n      web_stories_media_source: mockData.mediaSource,\n      web_stories_is_muted: mockData.isMuted,\n      post: mockData.templateId,\n      original_id: mockData.originalId,\n      web_stories_trim_data: mockData.trimData,\n      web_stories_base_color: mockData.baseColor,\n      web_stories_blurhash: mockData.blurHash,\n    };\n\n    const expectedDataArgument = new window.FormData();\n    expectedDataArgument.append(\n      'file',\n      file,\n      // eslint-disable-next-line jest/no-conditional-in-test\n      file.name || file.type.replace('/', '.')\n    );\n\n    Object.entries(expectedWpKeysMapping).forEach(([key, value]) =>\n      flattenFormData(expectedDataArgument, key, value)\n    );\n\n    uploadMedia(file, mockData);\n\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: MEDIA_PATH,\n        method: 'POST',\n        body: expectedDataArgument,\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/metaboxes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { saveMetaBoxes } from '../metaboxes';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('Meta Boxes API Callbacks', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n\n    apiFetch.mockReturnValue(Promise.resolve({}));\n  });\n\n  describe('saveMetaBoxes', () => {\n    it('sends the correct form data', () => {\n      const story = {\n        author: {\n          id: 123,\n          name: 'John Doe',\n        },\n      };\n\n      const formData = new window.FormData();\n      const apiUrl = 'wp-admin/post.php?action=edit&meta-box-loader=1';\n\n      saveMetaBoxes(story, formData, apiUrl);\n\n      expect(apiFetch).toHaveBeenCalledWith(\n        expect.objectContaining({\n          body: formData,\n        })\n      );\n      expect(formData.getAll('post_author')).toStrictEqual(\n        expect.arrayContaining(['123'])\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/pageTemplates.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '..';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('pageTemplates', () => {\n  afterEach(() => {\n    apiFetch.mockReset();\n  });\n\n  describe('getCustomPageTemplates', () => {\n    it('should always provide id and elements', async () => {\n      apiFetch.mockReturnValue(\n        Promise.resolve({\n          headers: {\n            'X-WP-TotalPages': 20,\n          },\n          body: [\n            {\n              id: 123,\n              story_data: { id: 'page-id', elements: [{ id: 'foo' }] },\n              title: { raw: 'abc', rendered: 'abc' },\n            },\n            {\n              id: 456,\n              story_data: [],\n              title: { raw: 'abc-1', rendered: 'abc-1' },\n            },\n          ],\n        })\n      );\n\n      const { getCustomPageTemplates } = bindToCallbacks(apiCallbacks, {\n        api: { pageTemplates: '/web-stories/v1/web-story-page/' },\n      });\n\n      await expect(getCustomPageTemplates(1)).resolves.toStrictEqual({\n        hasMore: true,\n        templates: [\n          {\n            elements: [{ id: 'foo' }],\n            id: 'page-id',\n            image: {\n              height: 0,\n              id: 0,\n              url: '',\n              width: 0,\n              needsProxy: false,\n              isExternal: false,\n            },\n            templateId: 123,\n            title: { raw: 'abc', rendered: 'abc' },\n          },\n          {\n            elements: [],\n            id: 456,\n            image: {\n              height: 0,\n              id: 0,\n              url: '',\n              width: 0,\n              needsProxy: false,\n              isExternal: false,\n            },\n            templateId: 456,\n            title: { raw: 'abc-1', rendered: 'abc-1' },\n          },\n        ],\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/story.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '..';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('Story API Callbacks', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  describe('saveStoryById', () => {\n    it('uses provided story poster', async () => {\n      apiFetch.mockReturnValue(\n        Promise.resolve({\n          id: 123,\n          meta: {},\n          story_poster: {\n            id: 567,\n            url: 'https://example.com/featuredimage.jpg',\n            width: 640,\n            height: 853,\n            needsProxy: false,\n          },\n        })\n      );\n      const { saveStoryById } = bindToCallbacks(apiCallbacks, {\n        api: { stories: '/web-stories/v1/web-story/' },\n      });\n\n      await expect(\n        saveStoryById({\n          storyId: 123,\n          featuredMedia: {},\n          author: {},\n        })\n      ).resolves.toStrictEqual(\n        expect.objectContaining({\n          id: 123,\n          featuredMedia: {\n            id: 567,\n            url: 'https://example.com/featuredimage.jpg',\n            width: 640,\n            height: 853,\n            needsProxy: false,\n            isExternal: false,\n          },\n        })\n      );\n    });\n\n    it('sets isExternal for hotlinked poster', async () => {\n      apiFetch.mockReturnValue(\n        Promise.resolve({\n          id: 123,\n          story_poster: {\n            url: 'https://example.com/hotlinked.jpg',\n            width: 640,\n            height: 853,\n            needsProxy: true,\n          },\n        })\n      );\n      const { saveStoryById } = bindToCallbacks(apiCallbacks, {\n        api: { stories: '/web-stories/v1/web-story/' },\n      });\n\n      await expect(\n        saveStoryById({\n          storyId: 123,\n          featuredMedia: {},\n          author: {},\n        })\n      ).resolves.toStrictEqual(\n        expect.objectContaining({\n          id: 123,\n          featuredMedia: {\n            width: 640,\n            height: 853,\n            isExternal: true,\n            needsProxy: true,\n            url: 'https://example.com/hotlinked.jpg',\n          },\n        })\n      );\n    });\n\n    it('returns \"empty\" object when there is no featured image', async () => {\n      apiFetch.mockReturnValue(\n        Promise.resolve({\n          id: 123,\n          story_poster: null,\n        })\n      );\n      const { saveStoryById } = bindToCallbacks(apiCallbacks, {\n        api: { stories: '/web-stories/v1/web-story/' },\n      });\n\n      await expect(\n        saveStoryById({\n          storyId: 123,\n          featuredMedia: {},\n          author: {},\n        })\n      ).resolves.toStrictEqual(\n        expect.objectContaining({\n          id: 123,\n          featuredMedia: {\n            id: 0,\n            width: 0,\n            height: 0,\n            isExternal: false,\n            needsProxy: false,\n            url: '',\n          },\n        })\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/test/user.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * External dependencies\n */\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\n\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '..';\n\njest.mock('@wordpress/api-fetch');\n\ndescribe('User API Callbacks', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  const API_PATH = '/web-stories/v1/users/me/';\n\n  it('getCurrentUser maps arguments to expected format', async () => {\n    apiFetch.mockReturnValue(\n      Promise.resolve({\n        id: 1234,\n        meta: {\n          web_stories_tracking_optin: true,\n          web_stories_onboarding: 'foobar',\n          web_stories_media_optimization: false,\n        },\n      })\n    );\n    const { getCurrentUser } = bindToCallbacks(apiCallbacks, {\n      api: { currentUser: API_PATH },\n    });\n\n    await expect(getCurrentUser()).resolves.toStrictEqual(\n      expect.objectContaining({\n        id: 1234,\n        trackingOptin: true,\n        onboarding: 'foobar',\n        mediaOptimization: false,\n      })\n    );\n  });\n\n  it('updateCurrentUser maps arguments to expected format', async () => {\n    apiFetch.mockReturnValue(\n      Promise.resolve({\n        id: 1234,\n        meta: {\n          web_stories_tracking_optin: true,\n          web_stories_onboarding: 'foobar',\n          web_stories_media_optimization: false,\n        },\n      })\n    );\n\n    const { updateCurrentUser } = bindToCallbacks(apiCallbacks, {\n      api: { currentUser: API_PATH },\n    });\n\n    await expect(\n      updateCurrentUser({\n        trackingOptin: false,\n        onboarding: 'baz',\n        mediaOptimization: true,\n      })\n    ).resolves.toStrictEqual(\n      expect.objectContaining({\n        id: 1234,\n        trackingOptin: true,\n        onboarding: 'foobar',\n        mediaOptimization: false,\n      })\n    );\n    expect(apiFetch).toHaveBeenCalledWith(\n      expect.objectContaining({\n        path: API_PATH,\n        method: 'POST',\n        data: {\n          meta: {\n            web_stories_tracking_optin: false,\n            web_stories_onboarding: 'baz',\n            web_stories_media_optimization: true,\n          },\n        },\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/user.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * WordPress dependencies\n */\nimport apiFetch from '@wordpress/api-fetch';\n\nfunction transformResponse(response) {\n  return {\n    id: response.id,\n    trackingOptin: response.meta.web_stories_tracking_optin,\n    onboarding: response.meta.web_stories_onboarding,\n    mediaOptimization: response.meta.web_stories_media_optimization,\n  };\n}\n\nexport function getCurrentUser(config) {\n  return apiFetch({\n    path: config.api.currentUser,\n  }).then(transformResponse);\n}\n\nexport function updateCurrentUser(config, data) {\n  const { trackingOptin, onboarding, mediaOptimization } = data;\n\n  const wpKeysMapping = {\n    meta: {\n      web_stories_tracking_optin: trackingOptin,\n      web_stories_onboarding: onboarding,\n      web_stories_media_optimization: mediaOptimization,\n    },\n  };\n\n  Object.entries(wpKeysMapping.meta).forEach(([key, value]) => {\n    if (value === undefined) {\n      delete wpKeysMapping.meta[key];\n    }\n  });\n\n  return apiFetch({\n    path: config.api.currentUser,\n    method: 'POST',\n    data: wpKeysMapping,\n  }).then(transformResponse);\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/base64Encode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Base64-encodes a string with Unicode support.\n *\n * Prefixes the encoded result so it can be easily identified\n * and treated accordingly.\n *\n * @param {string} string string to encode.\n * @return {string} Encoded string.\n */\nfunction base64Encode(string) {\n  return '__WEB_STORIES_ENCODED__' + btoa(encodeURIComponent(string));\n}\n\nexport default base64Encode;\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/flattenFormData.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Flatten data passed to form data, to allow using multi-level objects.\n *\n * @param {FormData} formData Form data object.\n * @param {string} key Key to amend to to form data object\n * @param {string|Object} data Data to be amended to form data.\n */\nconst flattenFormData = (formData, key, data) => {\n  if (typeof data === 'object') {\n    for (const name in data) {\n      if (Object.prototype.hasOwnProperty.call(data, name)) {\n        flattenFormData(formData, `${key}[${name}]`, data[name]);\n      }\n    }\n  } else {\n    formData.append(key, data);\n  }\n};\n\nexport default flattenFormData;\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/getResourceFromAttachment.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  createResource,\n  getTypeFromMime,\n  getResourceSize,\n} from '@googleforcreators/media';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * Internal dependencies\n */\nimport normalizeResourceSizes from './normalizeResourceSizes';\n\n/**\n * @typedef {import('@googleforcreators/media').Resource} Resource\n */\n\n/**\n * MediaDetails object.\n *\n * @typedef {Object} MediaDetails Media details object.\n * @property {number} width Media width.\n * @property {number} height Media height.\n * @property {number} length Video duration.\n * @property {string} length_formatted Formatted video duration.\n */\n\n/**\n * WPAttachment object.\n *\n * @typedef {Object} WPAttachment WordPress media object.\n * @property {number} id Numeric attachment ID.\n * @property {string} date_gmt Creation date in GMT.\n * @property {string} mime_type Media mime type.\n * @property {number} featured_media ID of the media item's poster ID.\n * @property {string} alt_text Alt text.\n * @property {string} source_url Media URL.\n * @property {string} web_stories_media_source Media source.\n * @property {MediaDetails} media_details Media details.\n */\n\nfunction getImageResourceFromAttachment(attachment) {\n  const {\n    id,\n    date_gmt,\n    media_details: { width, height, sizes: _sizes = {} } = {},\n    mime_type: mimeType,\n    alt_text: alt,\n    source_url: src,\n    meta: { web_stories_base_color: baseColor, web_stories_blurhash: blurHash },\n  } = attachment;\n\n  const sizes = Object.entries(_sizes).reduce((sizes, [key, value]) => {\n    sizes[key] = snakeToCamelCaseObjectKeys(value);\n    return sizes;\n  }, {});\n\n  return createResource({\n    baseColor,\n    blurHash,\n    mimeType,\n    creationDate: date_gmt,\n    src,\n    width,\n    height,\n    id,\n    alt,\n    sizes: normalizeResourceSizes(sizes),\n    local: false,\n    isExternal: false,\n  });\n}\n\nfunction getVideoResourceFromAttachment(attachment) {\n  const {\n    id,\n    date_gmt,\n    media_details: { width, height, length, length_formatted: lengthFormatted },\n    mime_type: mimeType,\n    featured_media: posterId,\n    featured_media_src: {\n      src: poster,\n      width: posterWidth,\n      height: posterHeight,\n      generated: posterGenerated,\n    },\n    web_stories_is_muted: isMuted,\n    alt_text: alt,\n    source_url: src,\n    web_stories_media_source: mediaSource,\n    meta: {\n      web_stories_trim_data: trimData,\n      web_stories_base_color: baseColor,\n      web_stories_blurhash: blurHash,\n    },\n  } = attachment;\n\n  return createResource({\n    baseColor,\n    blurHash,\n    mimeType,\n    creationDate: date_gmt,\n    src,\n    ...getResourceSize({\n      width,\n      height,\n      posterGenerated,\n      posterWidth,\n      posterHeight,\n    }),\n    poster,\n    posterId,\n    id,\n    length,\n    lengthFormatted,\n    alt,\n    local: false,\n    isExternal: false,\n    isOptimized: ['video-optimization', 'recording'].includes(mediaSource),\n    isMuted,\n    trimData,\n  });\n}\n\nfunction getGifResourceFromAttachment(attachment) {\n  const {\n    id,\n    date_gmt,\n    media_details: { width, height },\n    mime_type: mimeType,\n    featured_media: posterId,\n    featured_media_src: {\n      src: poster,\n      width: posterWidth,\n      height: posterHeight,\n      generated: posterGenerated,\n    },\n    alt_text: alt,\n    source_url: src,\n    meta: { web_stories_base_color: baseColor, web_stories_blurhash: blurHash },\n  } = attachment;\n\n  return createResource({\n    baseColor,\n    blurHash,\n    type: 'gif',\n    mimeType: 'image/gif',\n    creationDate: date_gmt,\n    src,\n    ...getResourceSize({\n      width,\n      height,\n      posterGenerated,\n      posterWidth,\n      posterHeight,\n    }),\n    posterId,\n    poster,\n    id,\n    alt,\n    local: false,\n    isOptimized: true,\n    isExternal: false,\n    output: {\n      mimeType: mimeType,\n      src: src,\n    },\n  });\n}\n\n/**\n * Generates a resource object from a WordPress attachment.\n *\n * @param {WPAttachment} attachment WP Attachment object.\n * @return {Resource} Resource object.\n */\nfunction getResourceFromAttachment(attachment) {\n  const {\n    mime_type: mimeType,\n    web_stories_media_source: mediaSource,\n    meta: { web_stories_is_gif: isGif = false } = {},\n  } = attachment;\n\n  if ('gif-conversion' === mediaSource || isGif) {\n    return getGifResourceFromAttachment(attachment);\n  }\n\n  const type = getTypeFromMime(mimeType);\n\n  if (type === 'image') {\n    return getImageResourceFromAttachment(attachment);\n  } else {\n    return getVideoResourceFromAttachment(attachment);\n  }\n}\n\nexport default getResourceFromAttachment;\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as flattenFormData } from './flattenFormData';\nexport { default as base64Encode } from './base64Encode';\nexport { default as getResourceFromAttachment } from './getResourceFromAttachment';\nexport { default as transformStoryResponse } from './transformStoryResponse';\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/normalizeResourceSizes.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @typedef {import('@googleforcreators/media').ResourceSize} ResourceSize\n */\n\n/**\n * @typedef {Object} PartialResourceSize\n * @property {string|number} [width] Resource width.\n * @property {string|number} [height] Resource height.\n * @property {string} mimeType Mime type.\n * @property {string} [sourceUrl] URL.\n */\n\n/**\n * Normalize resource sizes to ensure numerical values for dimensions.\n *\n * Skips invalid sizes lacking either width or height.\n *\n * @param {Object.<string, PartialResourceSize>} sizes Sizes.\n * @return {Object.<string, ResourceSize>} Normalized sizes.\n */\nfunction normalizeResourceSizes(sizes) {\n  const normalizedSizes = {};\n\n  if (!sizes) {\n    return normalizedSizes;\n  }\n\n  for (const size of Object.keys(sizes)) {\n    const data = sizes[size];\n\n    if (!data.width || !data.height || !data.sourceUrl) {\n      continue;\n    }\n\n    const width = Number(data.width);\n    const height = Number(data.height);\n\n    if (Number.isNaN(width) || Number.isNaN(height)) {\n      continue;\n    }\n\n    normalizedSizes[size] = {\n      ...data,\n      width,\n      height,\n    };\n  }\n\n  return normalizedSizes;\n}\n\nexport default normalizeResourceSizes;\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/test/base64Encode.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport base64Encode from '../base64Encode';\n\nfunction base64Decode(str) {\n  return decodeURIComponent(atob(str.replace('__WEB_STORIES_ENCODED__', '')));\n}\n\ndescribe('base64Encode', () => {\n  it('prefixes encoded content', () => {\n    expect(base64Encode('Hello World')).toStartWith('__WEB_STORIES_ENCODED__');\n  });\n\n  it('converts Unicode characters', () => {\n    const string = 'Hello 🌍 - これはサンプルです。';\n    const actual = base64Encode(string);\n    expect(actual).toBe(\n      '__WEB_STORIES_ENCODED__SGVsbG8lMjAlRjAlOUYlOEMlOEQlMjAtJTIwJUUzJTgxJTkzJUUzJTgyJThDJUUzJTgxJUFGJUUzJTgyJUI1JUUzJTgzJUIzJUUzJTgzJTk3JUUzJTgzJUFCJUUzJTgxJUE3JUUzJTgxJTk5JUUzJTgwJTgy'\n    ); // Hello 🌍 - これはサンプルです。\n    expect(base64Decode(actual)).toStrictEqual(string);\n  });\n\n  it('converts html', () => {\n    const string = 'Hello <a href=\"#\">world</a>';\n    const actual = base64Encode(string);\n    expect(actual).toBe(\n      '__WEB_STORIES_ENCODED__SGVsbG8lMjAlM0NhJTIwaHJlZiUzRCUyMiUyMyUyMiUzRXdvcmxkJTNDJTJGYSUzRQ=='\n    ); // Hello <a href=\"#\">world</a>\n    expect(base64Decode(actual)).toStrictEqual(string);\n  });\n\n  it('converts html characters', () => {\n    const string = 'Hello &copy;&dollar;&pound;';\n    const actual = base64Encode(string);\n    expect(actual).toBe(\n      '__WEB_STORIES_ENCODED__SGVsbG8lMjAlMjZjb3B5JTNCJTI2ZG9sbGFyJTNCJTI2cG91bmQlM0I='\n    ); // Hello &copy;&dollar;&pound;\n    expect(base64Decode(actual)).toStrictEqual(string);\n  });\n\n  it('converts UTF 16', () => {\n    const string = 'Hello world - ØÙßæĄŒƕƜǄǆɷ';\n    const actual = base64Encode(string);\n    expect(actual).toBe(\n      '__WEB_STORIES_ENCODED__SGVsbG8lMjB3b3JsZCUyMC0lMjAlQzMlOTglQzMlOTklQzMlOUYlQzMlQTYlQzQlODQlQzUlOTIlQzYlOTUlQzYlOUMlQzclODQlQzclODYlQzklQjc='\n    ); // Hello world - ØÙßæĄŒƕƜǄǆɷ\n    expect(base64Decode(actual)).toStrictEqual(string);\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/test/flatternFormData.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport flattenFormData from '../flattenFormData';\n\nconst append = jest.fn();\nconst FormData = {\n  append,\n};\n\ndescribe('flattenFormData', () => {\n  afterEach(() => {\n    append.mockClear();\n  });\n  it('should call append for string', () => {\n    flattenFormData(FormData, 'test', 'value');\n    expect(append).toHaveBeenCalledWith('test', 'value');\n  });\n\n  it('should call append for object', () => {\n    flattenFormData(FormData, 'test', {\n      meta: 'test',\n    });\n    expect(append).toHaveBeenCalledWith('test[meta]', 'test');\n  });\n\n  it('should call append for multiple levels object', () => {\n    flattenFormData(FormData, 'test', {\n      level1: {\n        level2: {\n          level3: 'test',\n        },\n      },\n    });\n    expect(append).toHaveBeenCalledWith('test[level1][level2][level3]', 'test');\n  });\n\n  it('should call append for null', () => {\n    flattenFormData(FormData, 'test', null);\n    expect(append).not.toHaveBeenCalledWith('test', null);\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/test/normalizeResourceSizes.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport normalizeResourceSizes from '../normalizeResourceSizes';\n\ndescribe('normalizeResourceSizes', () => {\n  it('normalizes resource sizes to numeric width and height', () => {\n    const sizes = {\n      size1: {\n        mimeType: 'image/jpeg',\n        width: '300',\n        height: '300',\n        sourceUrl: 'image-300x300.jpg',\n      },\n      size2: {\n        mimeType: 'image/jpeg',\n        width: '600',\n        height: '600',\n        sourceUrl: 'image-600x600.jpg',\n      },\n      size3: {\n        mimeType: 'image/jpeg',\n        width: '900',\n        height: '900',\n        sourceUrl: 'image-900x900.jpg',\n      },\n    };\n    const expected = {\n      size1: {\n        mimeType: 'image/jpeg',\n        width: 300,\n        height: 300,\n        sourceUrl: 'image-300x300.jpg',\n      },\n      size2: {\n        mimeType: 'image/jpeg',\n        width: 600,\n        height: 600,\n        sourceUrl: 'image-600x600.jpg',\n      },\n      size3: {\n        mimeType: 'image/jpeg',\n        width: 900,\n        height: 900,\n        sourceUrl: 'image-900x900.jpg',\n      },\n    };\n\n    expect(normalizeResourceSizes(sizes)).toStrictEqual(expected);\n  });\n\n  it('should skip sizes that are invalid', () => {\n    const sizes = {\n      img1: { mimeType: 'image/jpeg', height: 100, sourceUrl: 'small-url' },\n      img2: {\n        mimeType: 'image/jpeg',\n        width: 300,\n        height: 150,\n        sourceUrl: '',\n      },\n      img3: {\n        mimeType: 'image/jpeg',\n        width: 400,\n        height: 200,\n        sourceUrl: 'medium-url',\n      },\n      img4: {\n        mimeType: 'image/jpeg',\n        width: 800,\n        height: 400,\n        sourceUrl: 'large-url',\n      },\n      img5: {\n        mimeType: 'image/jpeg',\n        width: 300,\n        height: 150,\n      },\n      img6: { mimeType: 'image/jpeg', width: 100, sourceUrl: 'small-url' },\n    };\n\n    const expected = {\n      img3: {\n        mimeType: 'image/jpeg',\n        width: 400,\n        height: 200,\n        sourceUrl: 'medium-url',\n      },\n      img4: {\n        mimeType: 'image/jpeg',\n        width: 800,\n        height: 400,\n        sourceUrl: 'large-url',\n      },\n    };\n\n    expect(normalizeResourceSizes(sizes)).toStrictEqual(expected);\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/api/utils/transformStoryResponse.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\nfunction transformStoryResponse(post) {\n  const {\n    _embedded: embedded = {},\n    story_poster: storyPoster,\n    _links: links = {},\n    ...rest\n  } = post;\n\n  const terms = (embedded?.['wp:term'] || []).flat();\n\n  // TODO: Make author, lockUser, etc. null if absent, instead of these \"empty\" objects.\n  const story = {\n    ...snakeToCamelCaseObjectKeys(rest, ['story_data']),\n    author: {\n      id: embedded?.author?.[0].id || 0,\n      name: embedded?.author?.[0].name || '',\n    },\n    capabilities: {},\n    extras: {\n      lockUser: {\n        id: embedded?.['wp:lock']?.[0].user.id || 0,\n        name: embedded?.['wp:lock']?.[0].user.name || '',\n        avatar: embedded?.['wp:lock']?.[0].user.avatar?.['96'] || '',\n      },\n    },\n    featuredMedia: storyPoster\n      ? {\n          ...storyPoster,\n          isExternal: !storyPoster.id,\n        }\n      : {\n          id: 0,\n          height: 0,\n          width: 0,\n          url: '',\n          needsProxy: false,\n          isExternal: false,\n        },\n    publisherLogo: {\n      id: embedded?.['wp:publisherlogo']?.[0].id || 0,\n      height: embedded?.['wp:publisherlogo']?.[0]?.media_details?.height || 0,\n      width: embedded?.['wp:publisherlogo']?.[0]?.media_details?.width || 0,\n      url: embedded?.['wp:publisherlogo']?.[0]?.source_url || '',\n    },\n    terms,\n    revisions: {\n      count: links?.['version-history']?.[0]?.count,\n      id: links?.['predecessor-version']?.[0]?.id,\n    },\n  };\n\n  for (const link of Object.keys(links)) {\n    if (!link.startsWith('wp:action-')) {\n      continue;\n    }\n\n    // Turn 'wp:action-assign-author' into 'assign-author'\n    const capability = link.replace('wp:action-', '');\n    story.capabilities[capability] = true;\n  }\n\n  return story;\n}\n\nexport default transformStoryResponse;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/accessibility/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useConfig,\n  ElementLinkTappableRegionTooSmall,\n  ElementLinkTappableRegionTooBig,\n  ImageElementMissingAlt,\n  PageBackgroundTextLowContrast,\n  TextElementFontSizeTooSmall,\n  VideoElementMissingCaptions,\n  VideoElementMissingDescription,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport VideoOptimizationCheckbox from './videoOptimizationCheckbox';\n\nfunction Accessibility() {\n  const { hasUploadMediaAction } = useConfig(({ capabilities }) => ({\n    hasUploadMediaAction: capabilities.hasUploadMediaAction,\n  }));\n  return (\n    <>\n      <PageBackgroundTextLowContrast />\n      <TextElementFontSizeTooSmall />\n      <VideoElementMissingDescription />\n      {hasUploadMediaAction && <VideoElementMissingCaptions />}\n      <ElementLinkTappableRegionTooSmall />\n      <ElementLinkTappableRegionTooBig />\n      <ImageElementMissingAlt />\n      <VideoOptimizationCheckbox />\n    </>\n  );\n}\n\nexport default Accessibility;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/accessibility/videoOptimizationCheckbox/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useState,\n  useRef,\n  useEffect,\n} from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  Checkbox,\n  Link,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { TranslateWithMarkup, __ } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport {\n  useConfig,\n  useCurrentUser,\n  useIsChecklistMounted,\n  useStory,\n  ChecklistCard,\n  DefaultFooterText,\n} from '@googleforcreators/story-editor';\n\nconst CheckboxContainer = styled.div`\n  display: flex;\n  align-items: flex-start;\n`;\n\nconst ButtonContainer = styled.div`\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  margin-top: 16px;\n`;\n\nconst BoldText = styled(Text.Span).attrs({ isBold: true })`\n  color: ${({ theme }) => theme.colors.standard.white};\n`;\n\nconst CheckboxLabel = styled(Text.Label).attrs({\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.secondary};\n  margin-left: 8px;\n  margin-bottom: 0;\n  line-height: 20px;\n  cursor: pointer;\n`;\n\nfunction VideoOptimizationCheckbox() {\n  const isChecklistMounted = useIsChecklistMounted();\n  const { capabilities: { hasUploadMediaAction } = {}, dashboardSettingsLink } =\n    useConfig();\n  const [hasOptedIn, setHasOptedIn] = useState(false);\n  const saveButtonRef = useRef();\n  const { currentUser, toggleWebStoriesMediaOptimization } = useCurrentUser(\n    ({ state, actions }) => ({\n      currentUser: state.currentUser,\n      toggleWebStoriesMediaOptimization:\n        actions.toggleWebStoriesMediaOptimization,\n    })\n  );\n\n  const checked = currentUser?.mediaOptimization;\n  const showCheckbox = !checked && hasUploadMediaAction;\n\n  const handleToggle = useCallback(() => {\n    setHasOptedIn(true);\n    toggleWebStoriesMediaOptimization();\n  }, [toggleWebStoriesMediaOptimization]);\n\n  const { isSaving, saveStory } = useStory(({ state, actions }) => ({\n    isSaving: state.meta.isSaving,\n    saveStory: actions.saveStory,\n  }));\n  const handleSave = async () => {\n    await saveStory();\n    window.location.reload(true);\n  };\n\n  useEffect(() => {\n    hasOptedIn && saveButtonRef.current.focus();\n  }, [hasOptedIn]);\n\n  return (showCheckbox || hasOptedIn) && isChecklistMounted ? (\n    <ChecklistCard\n      title={__(\n        'Optimize all videos in the Story to ensure smooth playback.',\n        'web-stories'\n      )}\n      footer={\n        hasOptedIn ? (\n          <>\n            <DefaultFooterText>\n              <TranslateWithMarkup\n                mapping={{\n                  b: <BoldText />,\n                }}\n              >\n                {__(\n                  'Automatic video optimization enabled. <b>Reload the page</b> to apply changes.',\n                  'web-stories'\n                )}\n              </TranslateWithMarkup>\n            </DefaultFooterText>\n            <ButtonContainer>\n              <Button\n                type={ButtonType.Secondary}\n                size={ButtonSize.Small}\n                onClick={handleSave}\n                disabled={isSaving}\n                ref={saveButtonRef}\n              >\n                {__('Save & Reload', 'web-stories')}\n              </Button>\n            </ButtonContainer>\n          </>\n        ) : (\n          <CheckboxContainer>\n            <Checkbox\n              id=\"automatic-video-optimization-toggle\"\n              checked={currentUser?.mediaOptimization}\n              onChange={handleToggle}\n            />\n            <CheckboxLabel htmlFor=\"automatic-video-optimization-toggle\">\n              <TranslateWithMarkup\n                mapping={{\n                  a: (\n                    <Link\n                      size={TextSize.Small}\n                      onClick={(evt) =>\n                        trackClick(evt, 'click_video_optimization_settings')\n                      }\n                      href={dashboardSettingsLink}\n                      isBold\n                    />\n                  ),\n                }}\n              >\n                {__(\n                  'Enable automatic optimization. Change this any time in <a>Settings</a>.',\n                  'web-stories'\n                )}\n              </TranslateWithMarkup>\n            </CheckboxLabel>\n          </CheckboxContainer>\n        )\n      }\n    />\n  ) : null;\n}\n\nexport default VideoOptimizationCheckbox;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/accessibility/videoOptimizationCheckbox/test/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { render, screen } from '@testing-library/react';\nimport { ThemeProvider } from 'styled-components';\nimport { theme } from '@googleforcreators/design-system';\nimport {\n  useConfig,\n  useCurrentUser,\n  useStory,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport VideoOptimizationCheckbox from '..';\n\njest.mock('@googleforcreators/story-editor', () => ({\n  ...jest.requireActual('@googleforcreators/story-editor'),\n  useConfig: jest.fn(),\n  useCurrentUser: jest.fn(),\n  useStory: jest.fn(),\n  useIsChecklistMounted: jest.fn(() => true),\n}));\n\nconst mockUseConfig = useConfig;\nconst mockUseCurrentUser = useCurrentUser;\nconst mockUseStory = useStory;\nconst mockToggleWebStoriesMediaOptimization = jest.fn();\nconst mockUser = {\n  mediaOptimization: false,\n};\n\nconst mockStory = {\n  state: {\n    meta: {\n      isSaving: false,\n    },\n  },\n  actions: {\n    saveStory: jest.fn(),\n  },\n};\n\nconst Wrapper = (props) => <ThemeProvider theme={theme} {...props} />;\n\ndescribe('VideoOptimizationCheckbox', () => {\n  beforeEach(() => {\n    mockUseConfig.mockReturnValue({\n      capabilities: { hasUploadMediaAction: true },\n      dashboardSettingsLink: '/',\n    });\n    mockUseCurrentUser.mockReturnValue({\n      currentUser: mockUser,\n      toggleWebStoriesMediaOptimization: mockToggleWebStoriesMediaOptimization,\n    });\n    mockUseStory.mockReturnValue(mockStory);\n  });\n\n  it('should render `null` if auto video optimization is enabled', () => {\n    mockUseCurrentUser.mockReturnValue({\n      currentUser: {\n        ...mockUser,\n        mediaOptimization: true,\n      },\n      toggleWebStoriesMediaOptimization: mockToggleWebStoriesMediaOptimization,\n    });\n    render(<VideoOptimizationCheckbox />, { wrapper: Wrapper });\n\n    expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();\n  });\n\n  it('should render `null` if the user does not have the permission to upload media and auto video optimization is disabled', () => {\n    mockUseConfig.mockReturnValue({\n      capabilities: { hasUploadMediaAction: false },\n      dashboardSettingsLink: '/',\n    });\n    mockUseCurrentUser.mockReturnValue({\n      currentUser: {\n        ...mockUser,\n        mediaOptimization: false,\n      },\n      toggleWebStoriesMediaOptimization: mockToggleWebStoriesMediaOptimization,\n    });\n\n    render(<VideoOptimizationCheckbox />, { wrapper: Wrapper });\n\n    expect(screen.queryByRole('checkbox')).not.toBeInTheDocument();\n  });\n\n  it('should render the checkbox if auto video optimization is disabled and the user is able to upload media', () => {\n    render(<VideoOptimizationCheckbox />, { wrapper: Wrapper });\n\n    expect(screen.getByRole('checkbox')).toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/design/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useConfig,\n  PageTooManyLinks,\n  PageTooMuchText,\n  PageTooLittleText,\n  VideoElementResolution,\n  ImageElementResolution,\n  StoryPagesCount,\n  FirstPageAnimation,\n} from '@googleforcreators/story-editor';\n\nfunction Design() {\n  const { hasUploadMediaAction } = useConfig(({ capabilities }) => ({\n    hasUploadMediaAction: capabilities.hasUploadMediaAction,\n  }));\n  return (\n    <>\n      <StoryPagesCount />\n      <PageTooMuchText />\n      <PageTooLittleText />\n      <PageTooManyLinks />\n      <FirstPageAnimation />\n      {hasUploadMediaAction && <VideoElementResolution />}\n      {hasUploadMediaAction && <ImageElementResolution />}\n    </>\n  );\n}\n\nexport default Design;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Accessibility } from './accessibility';\nexport { default as Design } from './design';\nexport { default as Priority } from './priority';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/priority/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useConfig,\n  PublisherLogoSize,\n  StoryMissingExcerpt,\n  StoryMissingTitle,\n  StoryPosterSize,\n  StoryPosterAttached,\n  StoryTitleLength,\n  VideoElementMissingPoster,\n  VideoOptimization,\n  StoryAmpValidationErrors,\n  PublisherLogoMissing,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport StoryMissingPublisherName from './storyMissingPublisherName';\n\nfunction Priority() {\n  const { canManageSettings, hasUploadMediaAction } = useConfig(\n    ({ capabilities }) => ({\n      canManageSettings: capabilities.canManageSettings,\n      hasUploadMediaAction: capabilities.hasUploadMediaAction,\n    })\n  );\n\n  return (\n    <>\n      <StoryMissingTitle />\n      {canManageSettings && <StoryMissingPublisherName />}\n      <StoryTitleLength />\n      <StoryMissingExcerpt />\n      {hasUploadMediaAction && <StoryPosterAttached />}\n      {hasUploadMediaAction && <StoryPosterSize />}\n      {hasUploadMediaAction && <PublisherLogoMissing />}\n      {hasUploadMediaAction && <PublisherLogoSize />}\n      {hasUploadMediaAction && <VideoElementMissingPoster />}\n      <VideoOptimization />\n      <StoryAmpValidationErrors />\n    </>\n  );\n}\n\nexport default Priority;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/checklist/priority/storyMissingPublisherName.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { TranslateWithMarkup, __ } from '@googleforcreators/i18n';\nimport {\n  useConfig,\n  ChecklistCard,\n  DefaultFooterText,\n  CHECKLIST_PRIORITY_COPY,\n  useRegisterCheck,\n  useIsChecklistMounted,\n} from '@googleforcreators/story-editor';\nimport { Link, TextSize } from '@googleforcreators/design-system';\n\nconst StoryMissingPublisherName = () => {\n  const isChecklistMounted = useIsChecklistMounted();\n  const { generalSettingsLink, publisherName } = useConfig(\n    ({ metadata, generalSettingsLink }) => ({\n      publisherName: metadata?.publisher,\n      generalSettingsLink,\n    })\n  );\n  const hasPublisherName = publisherName?.trim().length > 0;\n\n  const { title } = CHECKLIST_PRIORITY_COPY.storyMissingPublisherName;\n\n  useRegisterCheck('StoryMissingPublisherName', !hasPublisherName);\n\n  return (\n    !hasPublisherName &&\n    isChecklistMounted && (\n      <ChecklistCard\n        title={title}\n        footer={\n          <DefaultFooterText>\n            <TranslateWithMarkup\n              mapping={{\n                a: (\n                  <Link\n                    href={generalSettingsLink}\n                    rel=\"noreferrer\"\n                    target=\"_blank\"\n                    size={TextSize.XSmall}\n                  />\n                ),\n              }}\n            >\n              {__(\n                'Your site title is used when your Story appears on Google. You can set your site title by going to <a>General Settings</a>.',\n                'web-stories'\n              )}\n            </TranslateWithMarkup>\n          </DefaultFooterText>\n        }\n      />\n    )\n  );\n};\n\nexport default StoryMissingPublisherName;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/corsCheck/corsCheck.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, useCallback, useState } from '@googleforcreators/react';\nimport { useAPI } from '@googleforcreators/story-editor';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n} from '@googleforcreators/design-system';\nimport { trackError } from '@googleforcreators/tracking';\n\n/**\n * Internal dependencies\n */\nimport CorsCheckFailed from './corsCheckFailed';\n\nconst storageKey = LOCAL_STORAGE_PREFIX.CORS_CHECK_DIALOG_DISMISSED;\n\nfunction CorsCheck() {\n  const [showDialog, setShowDialog] = useState(false);\n  const {\n    actions: { getMediaForCorsCheck },\n  } = useAPI();\n\n  const closeDialog = useCallback(() => {\n    setShowDialog(false);\n    localStore.setItemByKey(storageKey, true);\n  }, []);\n\n  const isDialogDismissed = Boolean(localStore.getItemByKey(storageKey));\n  useEffect(() => {\n    (async () => {\n      if (isDialogDismissed) {\n        return;\n      }\n      let mediaItems;\n      try {\n        mediaItems = await getMediaForCorsCheck();\n      } catch {\n        return;\n      }\n      if (!mediaItems?.length) {\n        return;\n      }\n      try {\n        await Promise.all(\n          [\n            ...new Set(\n              mediaItems.filter((url) => !url.startsWith(location.origin))\n            ),\n          ].map((url) => fetch(url, { method: 'HEAD' }))\n        );\n      } catch (err) {\n        setShowDialog(true);\n        trackError('cors_check', err.message);\n      }\n    })();\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- Only run this effect once, so do not pass dependencies.\n  }, []);\n\n  return <CorsCheckFailed isOpen={showDialog} onClose={closeDialog} />;\n}\n\nexport default CorsCheck;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/corsCheck/corsCheckFailed.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { Link, Text, TextSize } from '@googleforcreators/design-system';\nimport { Dialog } from '@googleforcreators/story-editor';\n\nconst DOCS_URL =\n  'https://wp.stories.google/docs/troubleshooting/common-issues/';\n\nfunction CorsCheckFailed({ isOpen, onClose }) {\n  const onDocsClick = useCallback((evt) => {\n    trackClick(evt, 'click_cors_check_docs');\n  }, []);\n\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      title={__('Unable to load media', 'web-stories')}\n      contentLabel={__('Unable to load media', 'web-stories')}\n      onPrimary={onClose}\n      primaryText={__('Dismiss', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                size={TextSize.Small}\n                href={DOCS_URL}\n                target=\"_blank\"\n                rel=\"noreferrer\"\n                onClick={onDocsClick}\n              />\n            ),\n          }}\n        >\n          {__(\n            'We detected a potential misconfiguration that prevents media items from loading correctly. This may be due to media being hosted on an external CDN. <a>Learn how to address this</a>.',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nCorsCheckFailed.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default CorsCheckFailed;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/corsCheck/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './corsCheck';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/corsCheck/stories/corsCheckFailed.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport CorsCheckFailed from '../corsCheckFailed';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/CORS Check Failed',\n  component: CorsCheckFailed,\n  args: {\n    isOpen: true,\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <CorsCheckFailed {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/corsCheck/test/corsCheck.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  fireEvent,\n  screen,\n  waitFor,\n  waitForElementToBeRemoved,\n} from '@testing-library/react';\nimport {\n  LOCAL_STORAGE_PREFIX,\n  localStore,\n  setAppElement,\n} from '@googleforcreators/design-system';\nimport { APIContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport CorsCheck from '../corsCheck.js';\n\nconst getMediaForCorsCheck = jest.fn();\n\njest.mock('@googleforcreators/design-system', () => ({\n  __esModule: true,\n  ...jest.requireActual('@googleforcreators/design-system'),\n  localStore: {\n    setItemByKey: jest.fn(),\n    getItemByKey: jest.fn(() => false),\n  },\n}));\n\nfunction setup() {\n  const apiData = {\n    actions: {\n      getMediaForCorsCheck,\n    },\n  };\n\n  return renderWithTheme(\n    <APIContext.Provider value={apiData}>\n      <CorsCheck />\n    </APIContext.Provider>\n  );\n}\n\ndescribe('corsCheck', () => {\n  let modalWrapper;\n\n  const fetchSpy = jest.spyOn(window, 'fetch');\n\n  beforeAll(() => {\n    fetchSpy.mockResolvedValue({\n      text: () => ({\n        status: 200,\n      }),\n    });\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n    fetchSpy.mockClear();\n  });\n\n  it('should do nothing if rest api returns nothing', async () => {\n    getMediaForCorsCheck.mockResolvedValue([]);\n    setup();\n\n    // This seems to be the best way to validate, that a certain\n    // element does *not* appear. Not very elegant, though.\n    await expect(screen.findByRole('dialog')).rejects.toThrow(\n      /Unable to find role=\"dialog\"/\n    );\n  });\n\n  it('should do nothing if successful', async () => {\n    getMediaForCorsCheck.mockResolvedValue(['https://example.com/logo.png']);\n    setup();\n\n    // This seems to be the best way to validate, that a certain\n    // element does *not* appear. Not very elegant, though.\n    await expect(screen.findByRole('dialog')).rejects.toThrow(\n      /Unable to find role=\"dialog\"/\n    );\n  });\n\n  it('should do nothing if same origin', async () => {\n    getMediaForCorsCheck.mockResolvedValue(['http://localhost/logo.png']);\n    setup();\n\n    // This seems to be the best way to validate, that a certain\n    // element does *not* appear. Not very elegant, though.\n    await expect(screen.findByRole('dialog')).rejects.toThrow(\n      /Unable to find role=\"dialog\"/\n    );\n  });\n\n  it('should do nothing if rest api returns error', async () => {\n    getMediaForCorsCheck.mockRejectedValue(() => new Error('api failed'));\n    setup();\n\n    // This seems to be the best way to validate, that a certain\n    // element does *not* appear. Not very elegant, though.\n    await expect(screen.findByRole('dialog')).rejects.toThrow(\n      /Unable to find role=\"dialog\"/\n    );\n  });\n\n  it('should display dismissible dialog if failed', async () => {\n    getMediaForCorsCheck.mockResolvedValue(['https://example.com/logo.png']);\n    fetchSpy.mockRejectedValue(() => new Error('request failed'));\n\n    setup();\n    expect(localStore.getItemByKey).toHaveBeenCalledWith(\n      LOCAL_STORAGE_PREFIX.CORS_CHECK_DIALOG_DISMISSED\n    );\n\n    const dialog = await screen.findByRole('dialog');\n    expect(dialog).toBeInTheDocument();\n\n    const dismiss = screen.getByRole('button', { name: /Dismiss/i });\n    expect(dismiss).toBeInTheDocument();\n    fireEvent.click(dismiss);\n\n    await waitForElementToBeRemoved(dialog);\n\n    await waitFor(() =>\n      expect(localStore.setItemByKey).toHaveBeenCalledWith(\n        LOCAL_STORAGE_PREFIX.CORS_CHECK_DIALOG_DISMISSED,\n        true\n      )\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/crossOriginIsolation/index.js",
    "content": "/*\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useLayoutEffect } from '@googleforcreators/react';\n\n/**\n * Internal dependencies\n */\nimport useMetaBoxes from '../metaBoxes/useMetaBoxes';\n\n/**\n * Complementary component to the Cross_Origin_Isolation PHP class\n * that detects dynamically added DOM nodes that are missing the crossorigin attribute.\n * These are typically found in custom meta boxes and the WordPress admin bar.\n *\n * @return {null} Rendered component\n */\nfunction CrossOriginIsolation() {\n  const { metaBoxesVisible, hasMetaBoxes } = useMetaBoxes(({ state }) => ({\n    hasMetaBoxes: state.hasMetaBoxes,\n    metaBoxesVisible: state.metaBoxesVisible,\n  }));\n\n  useLayoutEffect(() => {\n    if (!window.crossOriginIsolated) {\n      return () => undefined;\n    }\n\n    const observer = new MutationObserver((mutations) => {\n      mutations.forEach((mutation) => {\n        [mutation.addedNodes, mutation.target].forEach((node) => {\n          if (!node.querySelectorAll) {\n            return;\n          }\n\n          const elements = node.querySelectorAll('img');\n          elements.forEach((el) => {\n            if (el.hasAttribute('crossorigin')) {\n              return;\n            }\n\n            const imgSrc = new URL(el.src);\n\n            if (imgSrc.origin !== location.origin) {\n              el.setAttribute('crossorigin', 'anonymous');\n            }\n          });\n        });\n      });\n    });\n\n    const subTrees = document.querySelectorAll(\n      '#wpadminbar, .web-stories-meta-boxes-area'\n    );\n    subTrees.forEach((subTree) => {\n      observer.observe(subTree, {\n        attributes: true,\n        subtree: true,\n      });\n    });\n\n    return () => observer.disconnect();\n  }, [hasMetaBoxes, metaBoxesVisible]);\n\n  return null;\n}\n\nexport default CrossOriginIsolation;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  ExcerptPanel,\n  SlugPanel,\n  PageAdvancementPanel,\n  BackgroundAudioPanel,\n  TaxonomiesPanel,\n} from '@googleforcreators/story-editor';\nimport styled from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport PublishPanel from './publish';\nimport StatusPanel from './status';\n\nfunction DocumentPane() {\n  return (\n    <>\n      <StatusPanel />\n      <PublishPanel />\n      <ExcerptPanel />\n      <SlugPanel />\n      <PageAdvancementPanel />\n      <BackgroundAudioPanel />\n      <TaxonomiesPanel />\n    </>\n  );\n}\n\n// Panels require a name override to have their own local storage set for panel collapse\nexport function PublishModalDocumentPane() {\n  return (\n    <>\n      <PublishPanel nameOverride=\"storyDetailsPublishing\" />\n      <SlugPanel nameOverride=\"storyDetailsExcerpt\" />\n      <PageAdvancementPanel nameOverride=\"storyDetailsPageAdvancement\" />\n      <BackgroundAudioPanel nameOverride=\"storyDetailsBackgroundAudio\" />\n      <TaxonomiesPanel nameOverride=\"storyDetailsTaxonomies\" />\n    </>\n  );\n}\n\n// Isolated Status Panel should not collapse and\n// should have its own name to prevent collapse\n// based on other implementations that have default name\n\nconst IsolatedPanel = styled(StatusPanel)`\n  padding: 4px 4px 8px;\n`;\n\nexport function IsolatedStatusPanel() {\n  return (\n    <IsolatedPanel\n      nameOverride=\"storyDetailsStatus\"\n      canCollapse={false}\n      isPersistable={false}\n      popupZIndex={11}\n    />\n  );\n}\n\nexport default DocumentPane;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/publish/author.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { DatalistDropdown } from '@googleforcreators/design-system';\nimport {\n  Row,\n  useStory,\n  useAPI,\n  useSidebar,\n} from '@googleforcreators/story-editor';\n\nfunction Author() {\n  const {\n    actions: { getAuthors },\n  } = useAPI();\n  const {\n    state: { users, usersLoadingState },\n    actions: { loadUsers },\n  } = useSidebar();\n  const { isSaving, author, updateStory } = useStory(\n    ({\n      state: {\n        meta: { isSaving },\n        story: { author = {} },\n      },\n      actions: { updateStory },\n    }) => {\n      return {\n        isSaving,\n        author,\n        updateStory,\n      };\n    }\n  );\n\n  const [queriedUsers, setQueriedUsers] = useState(null);\n  const [visibleOptions, setVisibleOptions] = useState(null);\n\n  useEffect(() => {\n    loadUsers();\n  }, [loadUsers]);\n\n  const getAuthorsBySearch = useCallback(\n    (search) => {\n      return getAuthors(search)\n        .then((data) => {\n          const userData = data.map(({ id, name }) => ({\n            id,\n            name,\n          }));\n          setQueriedUsers(userData);\n        })\n        .catch(() => {\n          // Do nothing for now.\n        });\n    },\n    [getAuthors]\n  );\n\n  useEffect(() => {\n    if (users?.length) {\n      const currentAuthor = users.find(({ id }) => author.id === id);\n      if (!currentAuthor) {\n        setVisibleOptions([author, ...users]);\n      } else {\n        setVisibleOptions(users);\n      }\n    }\n  }, [author, users]);\n\n  const handleChangeAuthor = useCallback(\n    ({ id, name }) => {\n      updateStory({\n        properties: { author: { id, name } },\n      });\n    },\n    [updateStory]\n  );\n\n  const hasError = usersLoadingState === 'errored';\n  const isLoadingUsers = usersLoadingState !== 'finished' && !hasError;\n  const isLoading = isLoadingUsers || !visibleOptions;\n  const dropDownParams = {\n    hasSearch: true,\n    lightMode: true,\n    onChange: handleChangeAuthor,\n    getOptionsByQuery: getAuthorsBySearch,\n    selectedId: author.id,\n    dropDownLabel: __('Author', 'web-stories'),\n    placeholder: hasError\n      ? __('Could not load users', 'web-stories')\n      : isLoading\n        ? __('Loading…', 'web-stories')\n        : '',\n    disabled: isLoading || hasError || isSaving,\n    primaryOptions: isLoading ? [] : visibleOptions,\n    zIndex: 10,\n  };\n\n  return (\n    <Row>\n      <DatalistDropdown\n        options={queriedUsers}\n        searchResultsLabel={__('Search results', 'web-stories')}\n        dropdownButtonLabel={__('Author', 'web-stories')}\n        title={__('Available authors', 'web-stories')}\n        {...dropDownParams}\n      />\n    </Row>\n  );\n}\n\nexport default Author;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/publish/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './publish';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/publish/publish.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useState,\n  useEffect,\n  useMemo,\n  useCallback,\n  forwardRef,\n} from '@googleforcreators/react';\nimport styled from 'styled-components';\nimport { getExtensionsFromMimeType } from '@googleforcreators/media';\nimport {\n  __,\n  _n,\n  sprintf,\n  translateToExclusiveList,\n} from '@googleforcreators/i18n';\nimport {\n  Link,\n  Text,\n  TextSize,\n  Icons,\n  DatalistDropdown,\n  DatalistOption,\n} from '@googleforcreators/design-system';\nimport {\n  highlightStates as states,\n  highlightStyles as styles,\n  Row,\n  Media,\n  Panel,\n  Required,\n  PanelTitle,\n  PanelContent,\n  useStory,\n  useConfig,\n  useHighlights,\n  useSidebar,\n} from '@googleforcreators/story-editor';\nimport { addQueryArgs } from '@googleforcreators/url';\n/**\n * Internal dependencies\n */\nimport * as apiCallbacks from '../../../api/publisherLogos';\nimport PublishTime from './publishTime';\nimport Author from './author';\n\nconst LabelWrapper = styled.div`\n  height: 40px;\n`;\n\nconst Label = styled(Text.Paragraph).attrs({\n  as: 'label',\n  size: TextSize.Small,\n})`\n  color: ${({ theme }) => theme.colors.fg.primary};\n  font-size: 14px;\n`;\n\nconst MediaWrapper = styled.div`\n  display: flex;\n  align-items: center;\n  margin-bottom: 20px;\n  margin-top: 4px;\n  height: 96px;\n`;\n\nconst StyledMedia = styled(Media)`\n  width: ${({ $width }) => $width}px;\n  height: ${({ $height }) => $height}px;\n`;\n\nconst HighlightRow = styled(Row).attrs({\n  spaceBetween: false,\n})`\n  position: relative;\n  &::after {\n    content: '';\n    position: absolute;\n    top: -10px;\n    bottom: -10px;\n    left: -20px;\n    right: -10px;\n    ${({ isHighlighted }) => isHighlighted && styles.FLASH}\n    pointer-events: none;\n  }\n`;\n\nconst MediaInputWrapper = styled.div`\n  height: 160px;\n`;\n\nconst DropdownWrapper = styled.div`\n  position: relative;\n  width: 138px;\n  margin-left: 30px;\n  margin-top: 3px;\n`;\n\nconst LogoImg = styled.img`\n  object-fit: cover;\n  width: 100%;\n  height: 100%;\n  max-width: 96px;\n  max-height: 96px;\n`;\n\nconst RevisionsWrapper = styled.div`\n  width: 100%;\n  margin-bottom: 16px;\n  margin-top: 20px;\n`;\n\nconst RevisionsLabel = styled.div`\n  display: inline-block;\n  margin-left: 20px;\n  margin-right: 20px;\n`;\n\nconst LabelIconWrapper = styled.div`\n  position: absolute;\n  display: inline-block;\n  margin-left: -5px;\n`;\n\nfunction PublishPanel({ nameOverride }) {\n  const {\n    state: { users },\n  } = useSidebar();\n  const {\n    api: { publisherLogos: publisherLogosPath },\n  } = useConfig();\n\n  const { getPublisherLogos, addPublisherLogo } = apiCallbacks;\n\n  const {\n    allowedMimeTypes: { image: allowedImageMimeTypes },\n    dashboardSettingsLink,\n    capabilities: { hasUploadMediaAction, canManageSettings },\n    MediaUpload,\n    revisionLink,\n  } = useConfig();\n\n  const allowedImageFileTypes = useMemo(\n    () =>\n      allowedImageMimeTypes.flatMap((type) => getExtensionsFromMimeType(type)),\n    [allowedImageMimeTypes]\n  );\n\n  const [publisherLogos, setPublisherLogos] = useState([]);\n\n  useEffect(() => {\n    getPublisherLogos(publisherLogosPath).then(setPublisherLogos);\n  }, [getPublisherLogos, publisherLogosPath]);\n\n  const { highlightPoster, highlightLogo, resetHighlight } = useHighlights(\n    (state) => ({\n      highlightPoster: state[states.Poster],\n      highlightLogo: state[states.PublisherLogo],\n      resetHighlight: state.onFocusOut,\n      cancelHighlight: state.cancelEffect,\n    })\n  );\n\n  const { featuredMedia, publisherLogo, updateStory, capabilities, revisions } =\n    useStory(\n      ({\n        state: {\n          story: {\n            featuredMedia = { id: 0, url: '', height: 0, width: 0 },\n            publisherLogo = { id: 0, url: '', height: 0, width: 0 },\n            revisions,\n          },\n          capabilities,\n        },\n        actions: { updateStory },\n      }) => {\n        return {\n          featuredMedia,\n          publisherLogo,\n          updateStory,\n          capabilities,\n          revisions,\n        };\n      }\n    );\n\n  const revisionCount = revisions?.count ? revisions?.count : 0;\n  const revisionId = revisions?.id ? revisions?.id : 0;\n\n  const handleChangePoster = useCallback(\n    /**\n     * Handle story poster change.\n     *\n     * @param {import('@googleforcreators/media').Resource} newPoster The new image.\n     * @return {void}\n     */\n    (newPoster) => {\n      return updateStory({\n        properties: {\n          featuredMedia: {\n            id: newPoster.id,\n            url: newPoster.src,\n            height: newPoster.height,\n            width: newPoster.width,\n            isExternal: newPoster.isExternal,\n            needsProxy: newPoster.needsProxy,\n          },\n        },\n      });\n    },\n    [updateStory]\n  );\n\n  const onNewPublisherLogoSelected = ({ id, src }) => {\n    const newLogo = { id, url: src };\n    addPublisherLogo(publisherLogosPath, id);\n    setPublisherLogos((logos) => [...logos, newLogo]);\n    onPublisherLogoChange(newLogo);\n  };\n\n  const onPublisherLogoChange = (option) => {\n    updateStory({\n      properties: {\n        publisherLogo: {\n          id: option.id,\n          url: option.url,\n        },\n      },\n    });\n  };\n\n  const getErrorMessage = (message) => {\n    let returnedMessage = __(\n      'No file types are currently supported.',\n      'web-stories'\n    );\n\n    if (allowedImageFileTypes.length) {\n      returnedMessage = sprintf(\n        message,\n        translateToExclusiveList(allowedImageFileTypes)\n      );\n    }\n\n    return returnedMessage;\n  };\n\n  const publisherLogoErrorMessage = getErrorMessage(\n    /* translators: %s: list of allowed file types. */\n    __('Please choose only %s as publisher logo.', 'web-stories')\n  );\n  const posterErrorMessage = getErrorMessage(\n    /* translators: %s: list of allowed file types. */\n    __('Please choose only %s as a poster.', 'web-stories')\n  );\n\n  const publisherLogoOptionRenderer = forwardRef(({ option, ...rest }, ref) => {\n    if (option.props) {\n      return option;\n    }\n    return (\n      <DatalistOption value={option.id} ref={ref} {...rest}>\n        <LogoImg\n          src={option.url}\n          alt=\"\"\n          decoding=\"async\"\n          crossOrigin=\"anonymous\"\n        />\n      </DatalistOption>\n    );\n  });\n  const activeItemRenderer = () => {\n    const displayText = publisherLogos.length\n      ? __('Select logo', 'web-stories')\n      : __('No logo', 'web-stories');\n    return publisherLogo.id ? (\n      <LogoImg\n        src={publisherLogo.url}\n        alt=\"\"\n        decoding=\"async\"\n        crossOrigin=\"anonymous\"\n      />\n    ) : (\n      <Text.Span size={TextSize.Small}>{displayText}</Text.Span>\n    );\n  };\n\n  const renderUploadButton = (open) => (\n    <DatalistOption onClick={open} aria-label={__('Add new', 'web-stories')}>\n      <Icons.ArrowCloud height={32} width={32} />\n      <Text.Span size={TextSize.XSmall}>\n        {__('Add new', 'web-stories')}\n      </Text.Span>\n    </DatalistOption>\n  );\n  const publisherLogosWithUploadOption = [...publisherLogos];\n  if (hasUploadMediaAction) {\n    const cropParams = {\n      width: 96,\n      height: 96,\n    };\n    publisherLogosWithUploadOption.unshift(\n      <MediaUpload\n        onSelect={onNewPublisherLogoSelected}\n        onSelectErrorMessage={publisherLogoErrorMessage}\n        type={allowedImageMimeTypes}\n        render={renderUploadButton}\n        title={__('Select as publisher logo', 'web-stories')}\n        buttonInsertText={__('Select as publisher logo', 'web-stories')}\n        cropParams={cropParams}\n      />\n    );\n  }\n\n  const menuOptions = [hasUploadMediaAction && 'upload', 'hotlink'].filter(\n    Boolean\n  );\n\n  return (\n    <Panel\n      name={nameOverride || 'publishing'}\n      collapsedByDefault={false}\n      isPersistable={!(highlightLogo || highlightPoster)}\n    >\n      <PanelTitle>{__('Publishing', 'web-stories')}</PanelTitle>\n      <PanelContent>\n        {capabilities?.publish && <PublishTime />}\n        {capabilities?.['assign-author'] && users && <Author />}\n        <HighlightRow\n          isHighlighted={\n            highlightPoster?.showEffect || highlightLogo?.showEffect\n          }\n          onAnimationEnd={() => resetHighlight()}\n        >\n          <MediaInputWrapper>\n            <MediaWrapper>\n              <StyledMedia\n                ref={(node) => {\n                  if (\n                    node &&\n                    highlightPoster?.focus &&\n                    highlightPoster?.showEffect\n                  ) {\n                    node.focus();\n                  }\n                }}\n                $width={72}\n                $height={96}\n                cropParams={{\n                  width: 640,\n                  height: 853,\n                }}\n                value={featuredMedia?.url}\n                onChange={handleChangePoster}\n                title={__('Select as poster image', 'web-stories')}\n                hotlinkTitle={__(\n                  'Use external image as poster image',\n                  'web-stories'\n                )}\n                hotlinkInsertText={__(\n                  'Use image as poster image',\n                  'web-stories'\n                )}\n                hotlinkInsertingText={__(\n                  'Using image as poster image',\n                  'web-stories'\n                )}\n                buttonInsertText={__('Select as poster image', 'web-stories')}\n                type={allowedImageMimeTypes}\n                ariaLabel={__('Poster image', 'web-stories')}\n                onChangeErrorText={posterErrorMessage}\n                imgProps={featuredMedia}\n                canUpload\n                menuOptions={menuOptions}\n              />\n            </MediaWrapper>\n            <LabelWrapper>\n              <Label>{__('Poster image', 'web-stories')}</Label>\n              <Required />\n            </LabelWrapper>\n          </MediaInputWrapper>\n          <DropdownWrapper>\n            <MediaWrapper>\n              <DatalistDropdown\n                options={publisherLogosWithUploadOption}\n                primaryOptions={publisherLogosWithUploadOption}\n                onChange={onPublisherLogoChange}\n                title={__('Available publisher logos', 'web-stories')}\n                dropdownButtonLabel={__('Publisher Logo', 'web-stories')}\n                renderer={publisherLogoOptionRenderer}\n                activeItemRenderer={activeItemRenderer}\n                selectedId={publisherLogo.id}\n                zIndex={10}\n                disabled={!publisherLogosWithUploadOption.length}\n                ref={(node) => {\n                  if (\n                    node &&\n                    highlightLogo?.focus &&\n                    highlightLogo?.showEffect\n                  ) {\n                    node.focus();\n                  }\n                }}\n              />\n            </MediaWrapper>\n            <LabelWrapper>\n              <Label>{__('Publisher Logo', 'web-stories')}</Label>\n              <Row>\n                <Required />\n                {canManageSettings && (\n                  <Link\n                    rel=\"noreferrer\"\n                    target=\"_blank\"\n                    href={dashboardSettingsLink}\n                    size={TextSize.XSmall}\n                  >\n                    {__('Manage', 'web-stories')}\n                  </Link>\n                )}\n              </Row>\n            </LabelWrapper>\n          </DropdownWrapper>\n        </HighlightRow>\n        {revisionCount > 1 ? (\n          <RevisionsWrapper>\n            <Label>\n              <LabelIconWrapper>\n                <Icons.History width={24} height={24} aria-hidden />\n              </LabelIconWrapper>\n              <RevisionsLabel>\n                {sprintf(\n                  /* translators: %d: number of revisions. */\n                  _n(\n                    '%d Revision',\n                    '%d Revisions',\n                    revisionCount,\n                    'web-stories'\n                  ),\n                  revisionCount\n                )}\n              </RevisionsLabel>\n              {revisionLink && revisionId ? (\n                <Link\n                  rel=\"noreferrer\"\n                  target=\"_blank\"\n                  href={addQueryArgs(revisionLink, { revision: revisionId })}\n                  size={TextSize.XSmall}\n                >\n                  {__('Browse', 'web-stories')}\n                </Link>\n              ) : null}\n            </Label>\n          </RevisionsWrapper>\n        ) : null}\n      </PanelContent>\n    </Panel>\n  );\n}\n\nexport default PublishPanel;\n\nPublishPanel.propTypes = {\n  nameOverride: PropTypes.string,\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/publish/publishTime.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useRef,\n  useState,\n  useFocusOut,\n} from '@googleforcreators/react';\nimport {\n  format,\n  formatTime,\n  is12Hour,\n  hasLeadingZeros,\n} from '@googleforcreators/date';\nimport { __ } from '@googleforcreators/i18n';\nimport {\n  DropDownSelect,\n  useKeyDownEffect,\n  Popup,\n} from '@googleforcreators/design-system';\nimport {\n  DateTime,\n  Row,\n  useStory,\n  focusStyle,\n} from '@googleforcreators/story-editor';\n\n// date-fns format without timezone.\nconst TIMEZONELESS_FORMAT = 'Y-m-d\\\\TH:i:s';\n\nconst loadCalendar = () =>\n  import(/* webpackChunkName: \"chunk-react-calendar\" */ 'react-calendar');\n\nfunction PublishTime() {\n  const { date, origDate, modified, status, updateStory } = useStory(\n    ({\n      state: {\n        story: { date, origDate, modified, status },\n      },\n      actions: { updateStory },\n    }) => ({\n      date,\n      origDate,\n      modified,\n      status,\n      updateStory,\n    })\n  );\n  const use12HourFormat = is12Hour();\n  const useLeadingZeros = hasLeadingZeros();\n\n  /* translators: Date format, see https://www.php.net/manual/en/datetime.format.php */\n  const shortDateFormat = __('d/m/Y', 'web-stories');\n\n  const [showDatePicker, setShowDatePicker] = useState(false);\n  const dateTimeNode = useRef();\n  const dateFieldRef = useRef();\n\n  useKeyDownEffect(\n    dateFieldRef,\n    { key: ['space', 'enter'] },\n    () => {\n      setShowDatePicker((val) => !val);\n    },\n    []\n  );\n\n  useFocusOut(dateTimeNode, () => setShowDatePicker(false), [showDatePicker]);\n\n  const handleDateChange = useCallback(\n    (value, close = false) => {\n      if (close && showDatePicker) {\n        setShowDatePicker(false);\n      }\n      // Format the date only if the value exists.\n      const newDate = value\n        ? format(new Date(value), TIMEZONELESS_FORMAT)\n        : value;\n      updateStory({\n        properties: { date: newDate },\n      });\n    },\n    [showDatePicker, updateStory]\n  );\n\n  // Floating date means an unset date so that the story publish date will match the time it will get published.\n  const floatingDate =\n    ['draft', 'pending', 'auto-draft', 'future'].includes(status) &&\n    (date === modified || date === null);\n\n  const displayLabel = !floatingDate\n    ? format(date || origDate, shortDateFormat) +\n      ' ' +\n      formatTime(date || origDate)\n    : __('Immediately', 'web-stories');\n\n  return (\n    <>\n      <Row>\n        <DropDownSelect\n          dropDownLabel={__('Publish', 'web-stories')}\n          aria-pressed={showDatePicker}\n          aria-haspopup\n          aria-expanded={showDatePicker}\n          aria-label={__('Story publish time', 'web-stories')}\n          onSelectClick={(e) => {\n            e.preventDefault();\n            if (!showDatePicker) {\n              // Handle only opening the datepicker since onFocusOut deals with closing.\n              setShowDatePicker(true);\n            }\n          }}\n          ref={dateFieldRef}\n          activeItemLabel={displayLabel}\n          selectButtonStylesOverride={focusStyle}\n          onPointerEnter={() => loadCalendar()}\n          onFocus={() => loadCalendar()}\n          isOpen={showDatePicker}\n        />\n      </Row>\n      <Popup\n        anchor={dateFieldRef}\n        isOpen={showDatePicker}\n        zIndex={10}\n        renderContents={({ propagateDimensionChange }) => (\n          <DateTime\n            value={floatingDate ? origDate : date}\n            onChange={(value, close = false) => {\n              handleDateChange(value, close);\n            }}\n            onViewChange={() => propagateDimensionChange()}\n            is12Hour={use12HourFormat}\n            hasLeadingZeros={useLeadingZeros}\n            forwardedRef={dateTimeNode}\n            onClose={() => setShowDatePicker(false)}\n            canReset={\n              ['draft', 'pending', 'auto-draft', 'future'].includes(status) &&\n              !floatingDate\n            }\n          />\n        )}\n      />\n    </>\n  );\n}\n\nexport default PublishTime;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/publish/test/publish.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, waitFor, screen } from '@testing-library/react';\nimport MockDate from 'mockdate';\nimport {\n  APIContext,\n  ConfigContext,\n  StoryContext,\n  SidebarContext,\n} from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\nimport { useFeature } from 'flagged';\n\n/**\n * Internal dependencies\n */\nimport PublishPanel from '../publish';\n\njest.mock('./../../../../api/publisherLogos', () => ({\n  getPublisherLogos: jest.fn().mockResolvedValue([]),\n  addPublisherLogo: jest.fn().mockResolvedValue([]),\n}));\n\njest.mock('flagged');\n\nfunction MediaUpload({ render }) {\n  const open = jest.fn();\n  return render(open);\n}\n\nfunction arrange(\n  capabilities = {\n    'assign-author': true,\n    publish: true,\n    hasUploadMediaAction: true,\n  }\n) {\n  const updateStory = jest.fn();\n  const storyContextValue = {\n    state: {\n      capabilities,\n      meta: { isSaving: false },\n      story: {\n        author: { id: 1, name: 'John Doe' },\n        date: '2020-01-01T20:20:20',\n        modified: '2020-01-01T20:20:19',\n        featuredMedia: { id: 0, url: '', height: 0, width: 0 },\n        revisions: { count: 8, id: 189 },\n        publisherLogo: { id: 0, url: '', height: 0, width: 0 },\n        status: 'draft',\n      },\n    },\n    actions: { updateStory },\n  };\n\n  const config = {\n    capabilities,\n    allowedMimeTypes: {\n      image: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'],\n    },\n    revisionLink: 'http://example.com',\n    apiCallbacks: {\n      getAuthors: jest.fn().mockResolvedValue({}),\n    },\n    api: {\n      publisherLogos: '/web-stories/v1/publisher-logos/',\n    },\n    MediaUpload,\n  };\n  const loadUsers = jest.fn();\n\n  const sidebarContextValue = {\n    actions: { loadUsers },\n    state: {\n      users: [{ value: 'foo' }, { value: 'bar' }],\n    },\n  };\n\n  const actions = config.apiCallbacks;\n\n  const view = renderWithTheme(\n    <ConfigContext.Provider value={config}>\n      <APIContext.Provider value={{ actions }}>\n        <StoryContext.Provider value={storyContextValue}>\n          <SidebarContext.Provider value={sidebarContextValue}>\n            <PublishPanel />\n          </SidebarContext.Provider>\n        </StoryContext.Provider>\n      </APIContext.Provider>\n    </ConfigContext.Provider>\n  );\n  return {\n    ...view,\n    updateStory,\n  };\n}\n\ndescribe('PublishPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:publishing',\n      JSON.stringify({ isCollapsed: false })\n    );\n    MockDate.set('2020-07-15T12:00:00+00:00');\n    useFeature.mockImplementation(() => true);\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n    MockDate.reset();\n  });\n\n  it('should render PublishPanel', async () => {\n    arrange();\n    const publishPanel = screen.getByText('Publishing');\n    const publisherLogo = screen.getByText('Publisher Logo');\n    const revisionsText = screen.getByText('8 Revisions');\n    const revisionsLink = screen.getByRole('link', { name: 'Browse' });\n    await waitFor(() => expect(publishPanel).toBeDefined());\n    await waitFor(() => expect(publisherLogo).toBeDefined());\n    await waitFor(() => expect(revisionsText).toBeDefined());\n    expect(revisionsLink).toHaveAttribute(\n      'href',\n      'http://example.com/?revision=189'\n    );\n  });\n\n  it('should display Author field if authors available', async () => {\n    arrange();\n    const element = screen.getByRole('button', { name: 'Author' });\n    await waitFor(() => expect(element).toBeDefined());\n  });\n\n  it('should not display Author field without correct permissions', async () => {\n    arrange({\n      'assign-author': false,\n    });\n    const element = screen.queryByText('Author');\n    await waitFor(() => expect(element).toBeNull());\n  });\n\n  it('should open Date picker when clicking on date', async () => {\n    arrange();\n    const element = screen.getByRole('button', { name: 'Story publish time' });\n\n    fireEvent.click(element);\n    await expect(\n      screen.findByRole('button', { name: 'January 2020' })\n    ).resolves.toBeInTheDocument();\n  });\n\n  it('should update the story when choosing a date from the calendar', async () => {\n    const { updateStory } = arrange();\n    const element = screen.getByRole('button', { name: 'Story publish time' });\n\n    fireEvent.click(element);\n    const firstOfJanuary = screen.getByRole('button', {\n      name: 'January 1, 2020',\n    });\n    await waitFor(() => expect(firstOfJanuary).toBeDefined());\n\n    fireEvent.click(firstOfJanuary);\n    expect(updateStory).toHaveBeenCalledOnce();\n    const calledArg = updateStory.mock.calls[0][0];\n    const date = new Date(calledArg.properties.date);\n    expect(date.getMonth()).toBe(0);\n    expect(date.getDate()).toBe(1);\n    expect(date.getFullYear()).toBe(2020);\n  });\n\n  it('should allow resetting the publish time', async () => {\n    const { updateStory } = arrange();\n    const dateButton = screen.getByRole('button', {\n      name: 'Story publish time',\n    });\n\n    fireEvent.click(dateButton);\n    const resetButton = screen.getByRole('button', {\n      name: 'Reset publish time',\n    });\n    await waitFor(() => expect(resetButton).toBeDefined());\n    fireEvent.click(resetButton);\n\n    const calledArg = updateStory.mock.calls[0][0];\n    expect(calledArg.properties.date).toBeNull();\n  });\n\n  it('should not update the date with incorrect hour', async () => {\n    const { updateStory } = arrange();\n    const element = screen.getByRole('button', { name: 'Story publish time' });\n\n    fireEvent.click(element);\n    const hours = screen.getByLabelText('Hours');\n\n    // With PR#13339, Valid value for hour is from 1 to 12.\n    // Value 30 is invalid for hour and will be discarded which resulted in 0 hour.\n    // 0 is an invalid hour and won't fire onChange thus hour remains unchanged.\n    fireEvent.change(hours, { target: { value: '30' } });\n    fireEvent.blur(hours);\n\n    await waitFor(() => {\n      expect(updateStory).not.toHaveBeenCalled();\n    });\n  });\n\n  it('should update the date with incorrect minutes by resetting to zero', async () => {\n    const { updateStory } = arrange();\n    const element = screen.getByRole('button', { name: 'Story publish time' });\n\n    fireEvent.click(element);\n    const minutes = screen.getByLabelText('Minutes');\n\n    // With PR#13339, Valid value for minute is from 0 to 59.\n    // Value 130 is invalid for minute and will be discarded which resulted in 0 minute.\n    // 0 is a valid minute and will trigger fire onChange; thus updateStory will be called once.\n    fireEvent.change(minutes, { target: { value: '130' } });\n    fireEvent.blur(minutes);\n\n    await waitFor(() => {\n      expect(updateStory).toHaveBeenCalledOnce();\n    });\n\n    await waitFor(() => {\n      const calledArg = updateStory.mock.calls[0][0];\n      const updatedDate = new Date(calledArg.properties.date);\n      expect(updatedDate.getMinutes()).toBe(0); // Should be updated to the zero.\n    });\n  });\n\n  it('should open the calendar via keyboard events', async () => {\n    arrange();\n\n    let dateInCalendar = screen.queryByLabelText('January 1, 2020');\n    expect(dateInCalendar).not.toBeInTheDocument();\n\n    const element = screen.getByRole('button', { name: 'Story publish time' });\n\n    fireEvent.keyDown(element, {\n      key: 'Enter',\n      which: 13,\n    });\n\n    await waitFor(() => {\n      dateInCalendar = screen.getByRole('button', { name: 'January 1, 2020' });\n      expect(dateInCalendar).toBeDefined();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/status/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default } from './status';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/status/status.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport {\n  useCallback,\n  useEffect,\n  forwardRef,\n  useState,\n} from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport styled from 'styled-components';\nimport {\n  Input,\n  DropDown,\n  themeHelpers,\n  theme,\n  Text,\n} from '@googleforcreators/design-system';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport {\n  Row,\n  SimplePanel,\n  useStory,\n  useRefreshPostEditURL,\n  useIsUploadingToStory,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport { VISIBILITY, STATUS } from '../../../constants';\n\nconst StyledListItem = styled.li`\n  position: relative;\n  padding: 6px 8px;\n  margin: 4px 8px;\n  align-items: center;\n  border-radius: 4px;\n  cursor: pointer;\n  ${themeHelpers.focusableOutlineCSS}\n  &:hover {\n    background-color: ${theme.colors.border.defaultNormal};\n  }\n`;\nconst LabelText = styled(Text.Span)`\n  font-size: 14px;\n  color: ${theme.colors.fg.primary};\n`;\n\nconst HelperText = styled(Text.Span)`\n  color: ${theme.colors.fg.tertiary};\n`;\n\nconst RenderItemOverride = forwardRef(\n  ({ option, isSelected, ...rest }, ref) => (\n    <StyledListItem ref={ref} active={isSelected} {...rest}>\n      <LabelText>{option.label}</LabelText>\n      <br />\n      <HelperText>{option.helper}</HelperText>\n    </StyledListItem>\n  )\n);\n\nfunction StatusPanel({\n  nameOverride,\n  popupZIndex,\n  canCollapse,\n  isPersistable,\n  ...rest\n}) {\n  const {\n    status = '',\n    password,\n    updateStory,\n    saveStory,\n    capabilities,\n    editLink,\n    title,\n    storyId,\n  } = useStory(\n    ({\n      state: {\n        story: { status, password, editLink, title, storyId },\n        capabilities,\n      },\n      actions: { updateStory, saveStory },\n    }) => ({\n      status,\n      password,\n      updateStory,\n      saveStory,\n      capabilities,\n      editLink,\n      title,\n      storyId,\n    })\n  );\n\n  const [visibility, setVisibility] = useState(VISIBILITY.PUBLIC);\n\n  const isUploading = useIsUploadingToStory();\n\n  useEffect(() => {\n    if (password) {\n      setVisibility(VISIBILITY.PASSWORD_PROTECTED);\n      return;\n    }\n\n    if (status === STATUS.PRIVATE) {\n      setVisibility(VISIBILITY.PRIVATE);\n      updateStory({\n        properties: { visibility: VISIBILITY.PRIVATE },\n      });\n      return;\n    }\n  }, [password, status, updateStory, visibility]);\n\n  const visibilityOptions = [\n    {\n      value: VISIBILITY.PUBLIC,\n      label: __('Public', 'web-stories'),\n      helper: __('Visible to everyone', 'web-stories'),\n    },\n  ];\n\n  if (capabilities?.publish) {\n    visibilityOptions.push({\n      value: VISIBILITY.PRIVATE,\n      label: __('Private', 'web-stories'),\n      helper: __('Visible to site admins & editors only', 'web-stories'),\n      disabled: isUploading && visibility !== VISIBILITY.PRIVATE,\n    });\n    visibilityOptions.push({\n      value: VISIBILITY.PASSWORD_PROTECTED,\n      label: __('Password Protected', 'web-stories'),\n      helper: __('Visible only to those with the password.', 'web-stories'),\n    });\n  }\n\n  const handleChangePassword = useCallback(\n    (evt) => {\n      updateStory({\n        properties: { password: evt.target.value },\n      });\n    },\n    [updateStory]\n  );\n\n  const refreshPostEditURL = useRefreshPostEditURL(storyId, editLink);\n\n  const publishPrivately = useCallback(() => {\n    const properties = {\n      status: STATUS.PRIVATE,\n      password: '',\n    };\n\n    trackEvent('publish_story', {\n      status: STATUS.PRIVATE,\n      title_length: title.length,\n    });\n    refreshPostEditURL();\n\n    setVisibility(VISIBILITY.PRIVATE);\n    saveStory(properties);\n  }, [title.length, refreshPostEditURL, saveStory]);\n\n  const isAlreadyPublished = [\n    STATUS.PUBLISH,\n    STATUS.FUTURE,\n    STATUS.PRIVATE,\n  ].includes(status);\n\n  const handleChangeVisibility = useCallback(\n    (_, value) => {\n      const newVisibility = value;\n\n      if (VISIBILITY.PRIVATE === newVisibility && !isAlreadyPublished) {\n        if (\n          !window.confirm(\n            __(\n              'Would you like to privately publish this story now?',\n              'web-stories'\n            )\n          )\n        ) {\n          return;\n        }\n      }\n\n      const properties = {};\n\n      switch (newVisibility) {\n        case VISIBILITY.PUBLIC:\n          properties.status =\n            visibility === VISIBILITY.PRIVATE ? STATUS.DRAFT : status;\n          properties.password = '';\n          setVisibility(VISIBILITY.PUBLIC);\n          break;\n\n        case VISIBILITY.PRIVATE:\n          publishPrivately();\n          return;\n\n        case VISIBILITY.PASSWORD_PROTECTED:\n          properties.status =\n            visibility === VISIBILITY.PRIVATE ? STATUS.DRAFT : status;\n          properties.password = password || '';\n          setVisibility(VISIBILITY.PASSWORD_PROTECTED);\n          break;\n\n        default:\n          break;\n      }\n\n      updateStory({ properties });\n    },\n    [\n      status,\n      visibility,\n      password,\n      updateStory,\n      publishPrivately,\n      isAlreadyPublished,\n    ]\n  );\n\n  return (\n    <SimplePanel\n      name={nameOverride || 'status'}\n      title={__('Visibility', 'web-stories')}\n      canCollapse={canCollapse}\n      isPersistable={isPersistable}\n      collapsedByDefault={false}\n      {...rest}\n    >\n      <>\n        <Row>\n          <DropDown\n            options={visibilityOptions}\n            selectedValue={visibility}\n            onMenuItemClick={handleChangeVisibility}\n            popupZIndex={popupZIndex}\n            disabled={visibilityOptions.length <= 1}\n            renderItem={RenderItemOverride}\n            hint={\n              visibilityOptions.find((option) => visibility === option.value)\n                ?.helper\n            }\n          />\n        </Row>\n        {visibility === VISIBILITY.PASSWORD_PROTECTED && (\n          <Row>\n            <Input\n              aria-label={__('Password', 'web-stories')}\n              value={password}\n              onChange={handleChangePassword}\n              placeholder={__('Enter a password', 'web-stories')}\n            />\n          </Row>\n        )}\n      </>\n    </SimplePanel>\n  );\n}\n\nexport default StatusPanel;\n\nStatusPanel.propTypes = {\n  nameOverride: PropTypes.string,\n  popupZIndex: PropTypes.number,\n  canCollapse: PropTypes.bool,\n  isPersistable: PropTypes.bool,\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/documentPane/status/test/status.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen } from '@testing-library/react';\nimport { StoryContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StatusPanel from '../status';\nimport { STATUS, VISIBILITY } from '../../../../constants';\n\nfunction arrange(\n  capabilities = {\n    publish: true,\n  },\n  password = '',\n  visibility = VISIBILITY.PUBLIC\n) {\n  const updateStory = jest.fn();\n  const saveStory = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      story: {\n        status: STATUS.DRAFT,\n        password,\n        title: '',\n        storyId: 123,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        visibility,\n      },\n      capabilities,\n    },\n    actions: { updateStory, saveStory },\n  };\n  const view = renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <StatusPanel />\n    </StoryContext.Provider>\n  );\n  return {\n    ...view,\n    updateStory,\n    saveStory,\n  };\n}\n\nconst windowConfirm = jest.fn(() => true);\n\nconst clickDropdown = () => {\n  const dropdownBtn = screen.getByRole('button', {\n    name: 'Public',\n  });\n  fireEvent.click(dropdownBtn);\n};\n\ndescribe('statusPanel', () => {\n  beforeAll(() => {\n    localStorage.setItem(\n      'web_stories_ui_panel_settings:status',\n      JSON.stringify({ isCollapsed: false })\n    );\n\n    // Mock window.confirm()\n    Object.defineProperty(window, 'confirm', {\n      writable: true,\n      value: windowConfirm,\n    });\n  });\n\n  afterEach(() => {\n    jest.clearAllMocks();\n  });\n\n  afterAll(() => {\n    localStorage.clear();\n  });\n\n  it('should render Status Panel', () => {\n    arrange();\n    clickDropdown();\n\n    expect(screen.getAllByRole('option')).toHaveLength(3);\n    expect(\n      screen.getByRole('option', {\n        name: 'Public Visible to everyone',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('option', {\n        name: 'Private Visible to site admins & editors only',\n      })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('option', {\n        name: 'Password Protected Visible only to those with the password.',\n      })\n    ).toBeInTheDocument();\n  });\n\n  it('should always render the \"Public\" visibility option', () => {\n    arrange({\n      publish: false,\n    });\n    clickDropdown();\n\n    expect(\n      screen.getByRole('button', {\n        name: 'Public',\n      })\n    ).toBeInTheDocument();\n  });\n\n  it('should not render other visibility options if lacking permissions', () => {\n    arrange({\n      publish: false,\n    });\n    clickDropdown();\n\n    expect(\n      screen.queryByRole('option', {\n        name: 'Private Visible to site admins & editors only',\n      })\n    ).not.toBeInTheDocument();\n    expect(\n      screen.queryByRole('option', {\n        name: 'Password Protected Visible only to those with the password.',\n      })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should update the status when marking a story private', () => {\n    const { saveStory } = arrange();\n    clickDropdown();\n\n    fireEvent.click(\n      screen.getByRole('option', {\n        name: 'Private Visible to site admins & editors only',\n      })\n    );\n    expect(windowConfirm).toHaveBeenCalledWith(expect.any(String));\n    expect(saveStory).toHaveBeenCalledWith({\n      status: STATUS.PRIVATE,\n      password: '',\n    });\n  });\n\n  it('should display password field', () => {\n    arrange(\n      {\n        publish: true,\n      },\n      'password',\n      'protected'\n    );\n\n    expect(screen.getByLabelText('Password')).toBeInTheDocument();\n  });\n\n  it('should update properties changing visibility', () => {\n    const { updateStory } = arrange(\n      {\n        publish: true,\n      },\n      'password',\n      VISIBILITY.PASSWORD_PROTECTED\n    );\n    expect(screen.getByLabelText('Password')).toBeInTheDocument();\n\n    const dropdownBtn = screen.getByRole('button', {\n      name: 'Password Protected',\n    });\n    fireEvent.click(dropdownBtn);\n\n    fireEvent.click(\n      screen.getByRole('option', {\n        name: 'Public Visible to everyone',\n      })\n    );\n    expect(updateStory).toHaveBeenCalledWith({\n      properties: {\n        status: 'draft',\n        password: '',\n      },\n    });\n  });\n  it('should hide password when public visibility', () => {\n    arrange(\n      {\n        publish: true,\n      },\n      undefined,\n      VISIBILITY.PUBLIC\n    );\n    expect(screen.queryByLabelText('Password')).not.toBeInTheDocument();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/fontCheck/fontCheckDialog.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { TranslateWithMarkup, __ } from '@googleforcreators/i18n';\nimport { trackClick, trackEvent } from '@googleforcreators/tracking';\nimport styled from 'styled-components';\nimport { useState, useCallback } from '@googleforcreators/react';\nimport {\n  Button,\n  ButtonSize,\n  ButtonType,\n  Text,\n  TextSize,\n  Icons,\n  Link,\n} from '@googleforcreators/design-system';\n\nimport {\n  useStory,\n  useConfig,\n  Dialog,\n  FontPicker,\n} from '@googleforcreators/story-editor';\nimport { TEXT_ELEMENT_DEFAULT_FONT } from '@googleforcreators/elements';\n\nconst DialogContent = styled.div`\n  display: grid;\n  row-gap: 20px;\n`;\n\nconst ChevronRight = styled(Icons.ChevronRightSmall)`\n  width: 32px;\n  height: 32px;\n`;\n\nconst ChevronLeft = styled(ChevronRight)`\n  transform: rotate(180deg);\n`;\n\nconst StyledLink = styled(Link)`\n  display: flex;\n  color: ${({ theme }) => theme.colors.standard.black};\n  align-items: center;\n  font-weight: normal;\n  margin: 0 auto 0 0; /* auto forces left-alignment */\n`;\n\nconst StyledButton = styled(Button)`\n  margin-left: 16px;\n`;\n\n// Override the DialogActions default styling\n// so that the dashboard link aligns to the left,\n// while the other actions align to the right.\nconst ActionsWrap = styled.div`\n  display: flex;\n  align-self: flex-end;\n  width: 100%;\n`;\n\nexport const FontCheckDialog = ({\n  isOpen,\n  defaultCloseAction,\n  missingFont,\n  closeDialog,\n}) => {\n  const { dashboardLink, dashboardSettingsLink, isRTL } = useConfig();\n  const [suggestedFont, setSuggestedFont] = useState(TEXT_ELEMENT_DEFAULT_FONT);\n  const { updateElementsByFontFamily } = useStory(({ actions }) => ({\n    updateElementsByFontFamily: actions.updateElementsByFontFamily,\n  }));\n\n  const onClose = useCallback(\n    (evt) => {\n      trackEvent('font_check_cancel');\n\n      defaultCloseAction(evt);\n    },\n    [defaultCloseAction]\n  );\n\n  const onSettingsClick = useCallback((evt) => {\n    trackClick(evt, 'click_font_check_settings');\n  }, []);\n\n  const updateMissingFontWithDefault = useCallback(() => {\n    trackEvent('font_check_replace_default');\n\n    updateElementsByFontFamily({\n      family: missingFont,\n      properties: { font: TEXT_ELEMENT_DEFAULT_FONT },\n    });\n    closeDialog();\n  }, [closeDialog, missingFont, updateElementsByFontFamily]);\n\n  const updateMissingFontWithSelected = useCallback(() => {\n    trackEvent('font_check_replace_selected');\n\n    updateElementsByFontFamily({\n      family: missingFont,\n      properties: { font: suggestedFont },\n    });\n    closeDialog();\n  }, [suggestedFont, closeDialog, missingFont, updateElementsByFontFamily]);\n\n  const Chevron = isRTL ? ChevronRight : ChevronLeft;\n\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      title={__('Missing Fonts', 'web-stories')}\n      contentLabel={__('Missing Fonts', 'web-stories')}\n      actions={\n        <ActionsWrap>\n          <StyledLink href={dashboardLink}>\n            <Chevron />\n            {__('Back to dashboard', 'web-stories')}\n          </StyledLink>\n          <StyledButton\n            type={ButtonType.Secondary}\n            size={ButtonSize.Small}\n            onClick={updateMissingFontWithDefault}\n          >\n            {__('Open anyway', 'web-stories')}\n          </StyledButton>\n          <StyledButton\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            onClick={updateMissingFontWithSelected}\n          >\n            {__('Replace font', 'web-stories')}\n          </StyledButton>\n        </ActionsWrap>\n      }\n    >\n      <DialogContent>\n        <Text.Paragraph size={TextSize.Small}>\n          {__(\n            'This story contains the following font that is no longer available:',\n            'web-stories'\n          )}\n        </Text.Paragraph>\n        <Text.Paragraph size={TextSize.Small} isBold>\n          {missingFont}\n        </Text.Paragraph>\n        <div>\n          <TranslateWithMarkup\n            mapping={{\n              a: (\n                <Link\n                  size={TextSize.Small}\n                  onClick={onSettingsClick}\n                  href={dashboardSettingsLink}\n                  isBold\n                />\n              ),\n            }}\n          >\n            {__(\n              'To replace this font with your own or re-add it, go to <a>Settings</a>. To replace this font with a default, open the story.',\n              'web-stories'\n            )}\n          </TranslateWithMarkup>\n        </div>\n        <Text.Paragraph size={TextSize.Small}>\n          {__('Or, choose replacement font below:', 'web-stories')}\n        </Text.Paragraph>\n        <FontPicker\n          zIndex={10}\n          currentValue={suggestedFont.family}\n          onChange={setSuggestedFont}\n        />\n      </DialogContent>\n    </Dialog>\n  );\n};\n\nFontCheckDialog.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  defaultCloseAction: PropTypes.func,\n  closeDialog: PropTypes.func.isRequired,\n  missingFont: PropTypes.string.isRequired,\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/fontCheck/index.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { useEffect, useCallback, useState } from '@googleforcreators/react';\nimport {\n  useStory,\n  useConfig,\n  useAPI,\n  getInUseFontsForPages,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport { FontCheckDialog } from './fontCheckDialog';\n\nexport const FontCheck = () => {\n  const { dashboardLink } = useConfig();\n  const { isStoryLoaded, storyPages, updateElementsByFontFamily } = useStory(\n    ({ state: { pages }, actions }) => ({\n      storyPages: pages,\n      updateElementsByFontFamily: actions.updateElementsByFontFamily,\n      isStoryLoaded: pages.length > 0,\n    })\n  );\n  const {\n    actions: { getFonts },\n  } = useAPI();\n\n  const [missingFont, setMissingFont] = useState(null);\n  const [showDialog, setShowDialog] = useState(false);\n\n  const closeAndRedirect = useCallback(() => {\n    window.location = dashboardLink;\n  }, [dashboardLink]);\n\n  const closeDialog = () => setShowDialog(false);\n\n  useEffect(\n    () => {\n      (async () => {\n        if (!isStoryLoaded) {\n          return;\n        }\n\n        const inUseFonts = getInUseFontsForPages(storyPages);\n\n        if (!inUseFonts.length) {\n          return;\n        }\n\n        const allFonts = await getFonts({ include: inUseFonts.join(',') });\n        for (const fontFamily of inUseFonts) {\n          const matchedFont = allFonts.find(\n            (font) => font?.family === fontFamily\n          );\n          if (matchedFont) {\n            // ensure `in use` font element uses the latest metrics, weights etc...\n            updateElementsByFontFamily({\n              family: fontFamily,\n              properties: { font: matchedFont },\n            });\n          }\n        }\n\n        const diff = inUseFonts.filter(\n          (x) => !new Set(allFonts.map((font) => font.family)).has(x)\n        );\n\n        if (diff && diff.length >= 1) {\n          setShowDialog(true);\n          setMissingFont(diff[0]);\n        }\n      })();\n    },\n    // eslint-disable-next-line react-hooks/exhaustive-deps -- we only want to run this once after the story is loaded\n    [isStoryLoaded, updateElementsByFontFamily]\n  );\n\n  return (\n    <FontCheckDialog\n      isOpen={showDialog}\n      missingFont={missingFont || ''}\n      defaultCloseAction={closeAndRedirect}\n      closeDialog={closeDialog}\n    />\n  );\n};\n\nexport default FontCheck;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/fontCheck/test/fontCheck.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  useAPI,\n  useConfig,\n  StoryContext,\n  HistoryProvider,\n} from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\njest.mock('@googleforcreators/story-editor', () => ({\n  ...jest.requireActual('@googleforcreators/story-editor'),\n  useConfig: jest.fn(),\n  useAPI: jest.fn(),\n}));\n\nconst mockUseConfig = useConfig;\nconst mockUseAPI = useAPI;\nconst mockAllFonts = [\n  {\n    family: 'Rock Salt',\n    fallbacks: ['cursive'],\n    weights: [400, 500], // add weight\n    styles: ['regular'],\n    variants: [[0, 400]],\n    service: 'fonts.google.com',\n    metrics: {\n      upm: 1028, // modify upm\n      asc: 1623,\n      des: -788,\n      tAsc: 824,\n      tDes: -240,\n      tLGap: 63,\n      wAsc: 1623,\n      wDes: 788,\n      xH: 833,\n      capH: 1154,\n      yMin: -787,\n      yMax: 1623,\n      hAsc: 1623,\n      hDes: -788,\n      lGap: 32,\n    },\n  },\n];\n\nconst storyContext = {\n  state: {\n    version: 1,\n    pages: [\n      {\n        elements: [\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            x: 1,\n            y: 1,\n            width: 1,\n            height: 1,\n            mask: {\n              type: 'rectangle',\n            },\n            isBackground: true,\n            isDefaultBackground: true,\n            type: 'shape',\n            id: '637058d7-6ab3-47e8-addb-eb9ae56bd540',\n          },\n          {\n            opacity: 100,\n            flip: {\n              vertical: false,\n              horizontal: false,\n            },\n            rotationAngle: 0,\n            lockAspectRatio: true,\n            backgroundTextMode: 'NONE',\n            font: {\n              family: 'Rock Salt',\n              fallbacks: ['cursive'],\n              weights: [400],\n              styles: ['regular'],\n              variants: [[0, 400]],\n              service: 'fonts.google.com',\n              metrics: {\n                upm: 1024,\n                asc: 1623,\n                des: -788,\n                tAsc: 824,\n                tDes: -240,\n                tLGap: 63,\n                wAsc: 1623,\n                wDes: 788,\n                xH: 833,\n                capH: 1154,\n                yMin: -787,\n                yMax: 1623,\n                hAsc: 1623,\n                hDes: -788,\n                lGap: 32,\n              },\n            },\n            fontSize: 36,\n            backgroundColor: {\n              color: {\n                r: 196,\n                g: 196,\n                b: 196,\n              },\n            },\n            lineHeight: 1.19,\n            textAlign: 'left',\n            padding: {\n              locked: true,\n              hasHiddenPadding: false,\n              horizontal: 0,\n              vertical: 0,\n            },\n            type: 'text',\n            content: 'My Test Story',\n            borderRadius: {\n              locked: true,\n              topLeft: 2,\n              topRight: 2,\n              bottomRight: 2,\n              bottomLeft: 2,\n            },\n            x: 40,\n            y: 312,\n            width: 307,\n            height: 85,\n            scale: 100,\n            focalX: 50,\n            focalY: 50,\n            id: '8c6f0de5-c622-4a7e-9902-2a2d0f20eb61',\n            tagName: 'h1',\n          },\n        ],\n        backgroundColor: {\n          color: {\n            r: 255,\n            g: 255,\n            b: 255,\n          },\n        },\n        type: 'page',\n        id: '0cbeb527-cb8b-4316-ae5b-c0db7f81159f',\n      },\n    ],\n  },\n};\n\n/**\n * Internal dependencies\n */\nimport { FontCheck } from '..';\n\njest.mock('../fontCheckDialog', () => {\n  return {\n    __esModule: true,\n    FontCheckDialog: () => {\n      return <div>{'Font Check Dialog'}</div>;\n    },\n  };\n});\n\ndescribe('fontCheck metrics', () => {\n  beforeEach(() => {\n    mockUseConfig.mockReturnValue({\n      dashboardSettingsLink: '/',\n    });\n    mockUseAPI.mockReturnValue({ actions: { getFonts: () => mockAllFonts } });\n  });\n\n  it('should call updateElementsByFontFamily when font metrics update', async () => {\n    const mockUpdateByFontFamily = jest.fn();\n    const context = {\n      ...storyContext,\n      actions: { updateElementsByFontFamily: mockUpdateByFontFamily },\n    };\n    await renderWithTheme(\n      <HistoryProvider size={50}>\n        <StoryContext.Provider value={context}>\n          <FontCheck />\n        </StoryContext.Provider>\n      </HistoryProvider>\n    );\n    expect(mockUpdateByFontFamily).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/header/buttons/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useStory,\n  RedoButton,\n  PreviewButton,\n  SwitchToDraftButton,\n  UndoButton,\n  UpdateButton,\n  PublishButton,\n} from '@googleforcreators/story-editor';\nimport { CircularProgress } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport PropTypes from 'prop-types';\nimport useMetaBoxes from '../../metaBoxes/useMetaBoxes';\n\nconst ButtonList = styled.nav`\n  display: flex;\n  justify-content: flex-end;\n  padding: 1em;\n  height: 100%;\n`;\n\nconst List = styled.div`\n  display: flex;\n  align-items: center;\n  gap: 8px;\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  top: 0;\n`;\n\nconst IconWithSpinner = styled.div`\n  position: relative;\n`;\n\nfunction Loading() {\n  return (\n    <Spinner>\n      <CircularProgress size={32} />\n    </Spinner>\n  );\n}\n\nfunction DraftButtons({ forceIsSaving, hasUpdates }) {\n  return (\n    <>\n      <UpdateButton hasUpdates={hasUpdates} forceIsSaving={forceIsSaving} />\n      <PublishButton forceIsSaving={forceIsSaving} />\n    </>\n  );\n}\n\nDraftButtons.propTypes = {\n  forceIsSaving: PropTypes.bool.isRequired,\n  hasUpdates: PropTypes.bool.isRequired,\n};\n\nfunction PendingButtons({ forceIsSaving, hasUpdates, canPublish }) {\n  return (\n    <>\n      <SwitchToDraftButton forceIsSaving={forceIsSaving} />\n      {canPublish && (\n        <UpdateButton hasUpdates={hasUpdates} forceIsSaving={forceIsSaving} />\n      )}\n      <PublishButton forceIsSaving={forceIsSaving} />\n    </>\n  );\n}\n\nPendingButtons.propTypes = {\n  forceIsSaving: PropTypes.bool.isRequired,\n  hasUpdates: PropTypes.bool.isRequired,\n  canPublish: PropTypes.bool.isRequired,\n};\n\nfunction PublishedButtons({ forceIsSaving, hasUpdates }) {\n  return (\n    <>\n      <SwitchToDraftButton forceIsSaving={forceIsSaving} />\n      <UpdateButton hasUpdates={hasUpdates} forceIsSaving={forceIsSaving} />\n    </>\n  );\n}\n\nPublishedButtons.propTypes = {\n  forceIsSaving: PropTypes.bool.isRequired,\n  hasUpdates: PropTypes.bool.isRequired,\n};\n\nfunction Buttons() {\n  const { status, canPublish, isSaving } = useStory(\n    ({\n      state: {\n        story: { status },\n        meta: { isSaving },\n        capabilities,\n      },\n    }) => ({\n      status,\n      isSaving,\n      canPublish: Boolean(capabilities?.publish),\n    })\n  );\n\n  const isPending = 'pending' === status;\n  const isDraft = ['draft', 'auto-draft'].includes(status) || !status;\n  const isDraftOrPending = isDraft || isPending;\n\n  const { hasMetaBoxes, isSavingMetaBoxes } = useMetaBoxes(\n    ({ state: { hasMetaBoxes, isSavingMetaBoxes } }) => ({\n      hasMetaBoxes,\n      isSavingMetaBoxes,\n    })\n  );\n\n  return (\n    <ButtonList>\n      <List>\n        <UndoButton />\n        <RedoButton />\n        <IconWithSpinner>\n          <PreviewButton forceIsSaving={isSavingMetaBoxes} />\n          {isSaving && <Loading />}\n        </IconWithSpinner>\n        {isDraft && (\n          <DraftButtons\n            forceIsSaving={isSavingMetaBoxes}\n            hasUpdates={hasMetaBoxes}\n          />\n        )}\n        {isPending && (\n          <PendingButtons\n            forceIsSaving={isSavingMetaBoxes}\n            hasUpdates={hasMetaBoxes}\n            canPublish={canPublish}\n          />\n        )}\n        {!isDraftOrPending && (\n          <PublishedButtons\n            forceIsSaving={isSavingMetaBoxes}\n            hasUpdates={hasMetaBoxes}\n          />\n        )}\n      </List>\n    </ButtonList>\n  );\n}\n\nexport default Buttons;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/header/buttons/test/buttons.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { fireEvent, screen, within } from '@testing-library/react';\nimport MockDate from 'mockdate';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport {\n  StoryContext,\n  CheckpointContext,\n  ChecklistCountProvider,\n  ConfigContext,\n} from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport MetaBoxesContext from '../../../metaBoxes/context';\nimport Buttons from '..';\n\nconst newPoster = {\n  id: 'new-poster',\n  src: 'new-poster-url',\n  height: '36px',\n  width: '100000px',\n};\n\nfunction arrange({\n  story: extraStoryProps,\n  storyState: extraStoryStateProps,\n  meta: extraMetaProps,\n  metaBoxes: extraMetaBoxesProps,\n  config: extraConfigProps,\n} = {}) {\n  const saveStory = jest.fn();\n  const autoSave = jest.fn();\n  const focusChecklistTab = jest.fn();\n\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        publish: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        title: '',\n        excerpt: '',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n        ...extraStoryProps,\n      },\n      ...extraStoryStateProps,\n    },\n    actions: { saveStory, autoSave },\n  };\n  const metaBoxesValue = {\n    state: {\n      hasMetaBoxes: false,\n      isSavingMetaBoxes: false,\n      ...extraMetaBoxesProps,\n    },\n  };\n  const configValue = {\n    allowedMimeTypes: {},\n    capabilities: {},\n    metadata: {\n      publisher: 'publisher title',\n    },\n    MediaUpload: ({ onSelect }) => (\n      <button\n        data-testid=\"media-upload-button\"\n        onClick={() => onSelect(newPoster)}\n      >\n        {'Media Upload Button!'}\n      </button>\n    ),\n    ...extraConfigProps,\n  };\n\n  renderWithTheme(\n    <MetaBoxesContext.Provider value={metaBoxesValue}>\n      <ConfigContext.Provider value={configValue}>\n        <StoryContext.Provider value={storyContextValue}>\n          <ChecklistCountProvider>\n            <CheckpointContext.Provider\n              value={{\n                actions: {\n                  showPriorityIssues: () => {},\n                },\n                state: { hasHighPriorityIssues: false, checkpoint: 'all' },\n              }}\n            >\n              <Buttons />\n            </CheckpointContext.Provider>\n          </ChecklistCountProvider>\n        </StoryContext.Provider>\n      </ConfigContext.Provider>\n    </MetaBoxesContext.Provider>\n  );\n  return {\n    autoSave,\n    saveStory,\n    focusChecklistTab,\n  };\n}\n\ndescribe('Buttons', () => {\n  const FUTURE_DATE = '2022-01-01T20:20:20Z';\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n    MockDate.set('2020-07-15T12:00:00+00:00');\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n    MockDate.reset();\n    jest.clearAllMocks();\n  });\n\n  it('should always display history and preview buttons', () => {\n    arrange();\n    expect(\n      screen.getByRole('button', { name: 'Undo Changes' })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', { name: 'Redo Changes' })\n    ).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: 'Preview' })).toBeInTheDocument();\n  });\n\n  it('should display Publish button for draft stories', () => {\n    arrange();\n    expect(\n      screen.getByRole('button', { name: 'Save draft' })\n    ).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: 'Publish' })).toBeInTheDocument();\n  });\n\n  it('should display Update button for published stories', () => {\n    arrange({\n      story: { status: 'publish' },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Switch to Draft' })\n    ).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: 'Update' })).toBeInTheDocument();\n  });\n\n  it('should display Submit for Review button for draft stories if lacking capabilities', () => {\n    arrange({\n      storyState: { capabilities: { publish: false } },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Save draft' })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', { name: 'Submit for review' })\n    ).toBeInTheDocument();\n    expect(\n      screen.queryByRole('button', { name: 'Publish' })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should display three buttons for pending stories', () => {\n    arrange({\n      story: { status: 'pending' },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Switch to Draft' })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', { name: 'Save as pending' })\n    ).toBeInTheDocument();\n    expect(screen.getByRole('button', { name: 'Publish' })).toBeInTheDocument();\n  });\n\n  it('should display two buttons for pending stories if lacking capabilities', () => {\n    arrange({\n      story: { status: 'pending' },\n      storyState: { capabilities: { publish: false } },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Switch to Draft' })\n    ).toBeInTheDocument();\n    expect(\n      screen.getByRole('button', { name: 'Submit for review' })\n    ).toBeInTheDocument();\n    expect(\n      screen.queryByRole('button', { name: 'Publish' })\n    ).not.toBeInTheDocument();\n  });\n\n  it('should display Switch to draft button when published', () => {\n    const { saveStory } = arrange({\n      story: { status: 'publish' },\n    });\n    const draftButton = screen.getByRole('button', { name: 'Switch to Draft' });\n\n    fireEvent.click(draftButton);\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should display Schedule button when future date is set', () => {\n    const { saveStory } = arrange({\n      story: {\n        title: 'Some title',\n        status: 'draft',\n        date: FUTURE_DATE,\n      },\n    });\n    const scheduleButton = screen.getByRole('button', { name: 'Schedule' });\n\n    fireEvent.click(scheduleButton);\n    expect(saveStory).not.toHaveBeenCalled();\n\n    const publishModal = screen.getByRole('dialog');\n\n    const publishModalButton = within(publishModal).getByRole('button', {\n      name: 'Schedule',\n    });\n\n    fireEvent.click(publishModalButton);\n    expect(saveStory).toHaveBeenCalledOnce();\n  });\n\n  it('should display Schedule button with future status', () => {\n    arrange({\n      story: {\n        status: 'future',\n        date: FUTURE_DATE,\n      },\n    });\n    expect(\n      screen.getByRole('button', { name: 'Schedule' })\n    ).toBeInTheDocument();\n  });\n\n  it('should display loading indicator while the story is updating', () => {\n    arrange({ meta: { isSaving: true } });\n    expect(screen.getByRole('progressbar')).toBeInTheDocument();\n    expect(screen.queryByRole('button', { name: 'Save draft' })).toBeDisabled();\n    expect(screen.queryByRole('button', { name: 'Preview' })).toBeDisabled();\n    expect(screen.queryByRole('button', { name: 'Publish' })).toBeDisabled();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/header/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { memo } from '@googleforcreators/react';\nimport { HeaderTitle } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport Buttons from './buttons';\n\nconst Background = styled.header.attrs({\n  role: 'group',\n  'aria-label': __('Story canvas header', 'web-stories'),\n})`\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  background-color: ${({ theme }) => theme.colors.bg.primary};\n`;\n\nconst Head = styled.div`\n  flex: 1 1 auto;\n  padding: 1em;\n`;\n\nconst ButtonCell = styled.div`\n  grid-area: buttons;\n`;\n\nfunction HeaderLayout() {\n  return (\n    <Background>\n      <Head>\n        <HeaderTitle />\n      </Head>\n      <ButtonCell>\n        <Buttons />\n      </ButtonCell>\n    </Background>\n  );\n}\n\n// Don't rerender the header needlessly e.g. on element selection change.\nexport default memo(HeaderLayout);\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/helpCenter/footer/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackClick } from '@googleforcreators/tracking';\nimport {\n  themeHelpers,\n  Link as DsLink,\n  TextSize,\n  Text,\n} from '@googleforcreators/design-system';\n\nconst Panel = styled.div`\n  padding: 16px 0 24px 0;\n  border-top: 1px solid ${({ theme }) => theme.colors.bg.tertiary};\n`;\n\nconst Links = styled.ul`\n  margin: 8px 0 0 0;\n  padding: 0;\n  list-style-position: inside;\n  list-style-type: none;\n`;\n\nconst ListItem = styled.li`\n  ${themeHelpers.expandTextPreset(\n    ({ paragraph }, { XSmall }) => paragraph[XSmall]\n  )}\n  &::before {\n    content: '- ';\n  }\n  &,\n  & > * {\n    font-weight: 700;\n  }\n`;\n\nfunction Link({ children, ...props }) {\n  return (\n    <ListItem>\n      <DsLink {...props} size={TextSize.XSmall}>\n        {children}\n      </DsLink>\n    </ListItem>\n  );\n}\n\nLink.propTypes = {\n  children: PropTypes.node,\n};\n\nconst SUPPORT_URL = __(\n  'https://wordpress.org/support/plugin/web-stories/',\n  'web-stories'\n);\n\nconst YOUTUBE_URL = __(\n  'https://youtube.com/playlist?list=PLfVPq9A6B0RNoQ3HTE9LQzgAdVzcb7tmt',\n  'web-stories'\n);\n\nconst DOCS_URL = 'https://wp.stories.google/docs/getting-started/';\n\nexport default function Footer() {\n  const onSupportClick = useCallback((evt) => {\n    trackClick(evt, 'click_support_page');\n  }, []);\n\n  const onDocsClick = useCallback((evt) => {\n    trackClick(evt, 'click_website_docs');\n  }, []);\n\n  const onYouTubeClick = useCallback((evt) => {\n    trackClick(evt, 'click_storytime_channel');\n  }, []);\n\n  return (\n    <Panel>\n      <Text.Paragraph size={TextSize.XSmall}>\n        {__(\n          'Discover more resources to get the most out of Web Stories. Read our start guide or visit our support forum to get answers to your questions.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n      <Links>\n        <Link\n          href={DOCS_URL}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n          onClick={onDocsClick}\n        >\n          {__('Read Documentation', 'web-stories')}\n        </Link>\n        <Link\n          href={SUPPORT_URL}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n          onClick={onSupportClick}\n        >\n          {__('Visit Support Forums', 'web-stories')}\n        </Link>\n        <Link\n          href={YOUTUBE_URL}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n          onClick={onYouTubeClick}\n        >\n          {__('Storytime YouTube Series', 'web-stories')}\n        </Link>\n      </Links>\n    </Panel>\n  );\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/helpCenter/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as Footer } from './footer';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as PostPublishDialog } from './postPublishDialog';\nexport { default as PostReviewDialog } from './postReviewDialog';\nexport { default as Layout } from './layout';\nexport { default as MediaUpload } from './mediaUpload';\nexport { default as PostLock } from './postLock';\nexport { default as StatusCheck } from './statusCheck';\nexport { default as CorsCheck } from './corsCheck';\nexport { default as RevisionMessage } from './revisionMessage';\nexport { default as FontCheck } from './fontCheck';\nexport { default as CrossOriginIsolation } from './crossOriginIsolation';\nexport * from './metaBoxes';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/layout/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { InterfaceSkeleton } from '@googleforcreators/story-editor';\nimport { __ } from '@googleforcreators/i18n';\n\n/**\n * Internal dependencies\n */\nimport { default as Header } from '../header';\nimport { MetaBoxes, MetaBoxesProvider } from '../metaBoxes';\nimport DocumentPane, {\n  PublishModalDocumentPane,\n  IsolatedStatusPanel,\n} from '../documentPane';\nimport { Priority, Design, Accessibility } from '../checklist';\nimport { Footer } from '../helpCenter';\nimport CrossOriginIsolation from '../crossOriginIsolation';\n\nfunction Layout() {\n  return (\n    <MetaBoxesProvider>\n      <InterfaceSkeleton\n        header={<Header />}\n        footer={{\n          secondaryMenu: {\n            helpCenter: {\n              Footer,\n            },\n            checklist: {\n              Priority,\n              Design,\n              Accessibility,\n            },\n          },\n        }}\n        sidebarTabs={{\n          document: {\n            title: __('Document', 'web-stories'),\n            Pane: DocumentPane,\n          },\n          publishModal: {\n            DocumentPane: PublishModalDocumentPane,\n            IsolatedStatusPanel: IsolatedStatusPanel,\n          },\n        }}\n      >\n        <MetaBoxes />\n      </InterfaceSkeleton>\n      <CrossOriginIsolation />\n    </MetaBoxesProvider>\n  );\n}\n\nexport default Layout;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport { useMediaPicker } from './mediaPicker';\n\nfunction MediaUpload({ render, ...rest }) {\n  const open = useMediaPicker(rest);\n\n  return render(open);\n}\n\nMediaUpload.propTypes = {\n  render: PropTypes.func.isRequired,\n  ...useMediaPicker.propTypes,\n};\n\nexport default MediaUpload;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/WordPressImageCropper.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * A state for cropping an image\n *\n * Like CustomizeImageCropper in WordPress core,\n * but without setting the wp_customize parameter\n * which requires the 'customize' capability.\n *\n * @see https://github.com/WordPress/wordpress-develop/blob/baa5ba32d8698f6a6a5928bcbd4fea35bd47a8c1/src/js/media/controllers/customize-image-cropper.js\n */\nconst WordPressImageCropper = window.wp?.media?.controller?.Cropper?.extend?.({\n  /**\n   * Posts the crop details to the admin.\n   *\n   * Uses crop measurements when flexible in both directions.\n   * Constrains flexible side based on image ratio and size of the fixed side.\n   *\n   * @param {Object} attachment The attachment to crop.\n   * @return {Object} A jQuery promise that represents the crop image request.\n   */\n  doCrop: function (attachment) {\n    const cropDetails = attachment.get('cropDetails'),\n      control = this.get('control'),\n      ratio = cropDetails.width / cropDetails.height;\n\n    // Use crop measurements when flexible in both directions.\n    if (control.params.flex_width && control.params.flex_height) {\n      cropDetails.dst_width = cropDetails.width;\n      cropDetails.dst_height = cropDetails.height;\n\n      // Constrain flexible side based on image ratio and size of the fixed side.\n    } else {\n      cropDetails.dst_width = control.params.flex_width\n        ? control.params.height * ratio\n        : control.params.width;\n      cropDetails.dst_height = control.params.flex_height\n        ? control.params.width / ratio\n        : control.params.height;\n    }\n\n    return window.wp.ajax.post('crop-image', {\n      nonce: attachment.get('nonces').edit,\n      id: attachment.get('id'),\n      context: control.id,\n      cropDetails: cropDetails,\n    });\n  },\n});\n\nexport default WordPressImageCropper;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as useMediaPicker } from './useMediaPicker';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/test/useMediaPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { act, renderHook } from '@testing-library/react-hooks';\nimport { SnackbarContext } from '@googleforcreators/design-system';\nimport { ConfigContext } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport useMediaPicker from '../useMediaPicker';\n\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: () => {\n    return {\n      showSnackbar: jest.fn(),\n    };\n  },\n}));\n\nfunction setup({ args, cropParams }) {\n  const configValue = {\n    capabilities: {\n      hasUploadMediaAction: true,\n    },\n    ...args,\n  };\n\n  const wrapper = ({ children }) => (\n    <ConfigContext.Provider value={configValue}>\n      <SnackbarContext.Provider>{children}</SnackbarContext.Provider>\n    </ConfigContext.Provider>\n  );\n  const onSelect = jest.fn();\n  const onClose = jest.fn();\n  const onPermissionError = jest.fn();\n  const { result } = renderHook(\n    () => useMediaPicker({ onSelect, onClose, onPermissionError, cropParams }),\n    {\n      wrapper,\n    }\n  );\n  return {\n    openMediaPicker: result.current,\n    onPermissionError,\n  };\n}\n\ndescribe('useMediaPicker', () => {\n  it('user unable to upload', () => {\n    const { openMediaPicker, onPermissionError } = setup({\n      args: {\n        capabilities: {\n          hasUploadMediaAction: false,\n        },\n      },\n    });\n    act(() => {\n      openMediaPicker(new Event('click'));\n    });\n    expect(onPermissionError).toHaveBeenCalledOnce();\n  });\n\n  it('user unable to upload with cropped', () => {\n    const { openMediaPicker, onPermissionError } = setup({\n      args: {\n        capabilities: {\n          hasUploadMediaAction: false,\n        },\n      },\n      cropParams: {\n        height: 500,\n        width: 500,\n        flex_width: false,\n        flex_height: false,\n      },\n    });\n    act(() => {\n      openMediaPicker(new Event('click'));\n    });\n    expect(onPermissionError).toHaveBeenCalledOnce();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/useMediaPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useMemo } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { useConfig, useAPI } from '@googleforcreators/story-editor';\nimport PropTypes from 'prop-types';\n\n/**\n * Internal dependencies\n */\nimport {\n  calculateImageSelectOptions,\n  mustBeCropped,\n  getResourceFromMediaPicker,\n} from './utils';\nimport WordPressImageCropper from './WordPressImageCropper';\n\nconst defaultCropParams = {\n  height: 0,\n  width: 0,\n  flex_width: false,\n  flex_height: false,\n};\n\n/**\n * Custom hook to open the WordPress media modal.\n *\n * @param {Object} props Props.\n * @param {string} [props.title] Media modal title.\n * @param {string} [props.buttonInsertText] Text to use for the \"Insert\" button.\n * @param {Function} props.onSelect Selection callback. Used to process the inserted image.\n * @param {string} props.onSelectErrorMessage Text displayed when incorrect file type is selected.\n * @param {Function?} props.onClose Close Callback.\n * @param {Function?} props.onPermissionError Callback for when user does not have upload permissions.\n * @param {string|string[]} props.type Media type(s).\n * @param {boolean} props.multiple Whether multi-selection should be allowed.\n * @param {Object} props.cropParams Object params for cropped images.\n * @return {Function} Callback to open the media picker.\n */\nfunction useMediaPicker({\n  title = __('Upload to Story', 'web-stories'),\n  buttonInsertText = __('Insert into page', 'web-stories'),\n  onSelect,\n  onSelectErrorMessage = __('Unable to use this file type.', 'web-stories'),\n  onClose,\n  onPermissionError,\n  type = '',\n  multiple = false,\n  cropParams,\n}) {\n  const {\n    actions: { updateMedia },\n  } = useAPI();\n  const {\n    capabilities: { hasUploadMediaAction },\n  } = useConfig();\n  const { showSnackbar } = useSnackbar();\n\n  useEffect(() => {\n    try {\n      // The Uploader.success callback is invoked when a user uploads a file.\n      // This is used to mark files as \"uploaded to the story editor\"\n      // in case we eventually want to allow filtering such files.\n      // Note: at this point the video has not yet been inserted into the canvas,\n      // it's just in the WP media modal.\n      // Video poster generation for newly added videos is done in <MediaPane>.\n      window.wp.Uploader.prototype.success = ({ attributes }) => {\n        updateMedia(attributes.id, {\n          mediaSource: 'editor',\n          altText: attributes.alt || attributes.title,\n        });\n      };\n    } catch {\n      // Silence.\n    }\n  }, [updateMedia]);\n\n  const openMediaDialog = useCallback(\n    (evt) => {\n      trackEvent('open_media_modal');\n\n      // If a user does not have the rights to upload to the media library, do not show the media picker.\n      if (!hasUploadMediaAction) {\n        if (onPermissionError) {\n          onPermissionError();\n        }\n        evt.preventDefault();\n        return;\n      }\n\n      // Create the media frame.\n      const fileFrame = window.wp.media({\n        title,\n        library: {\n          type,\n        },\n        multiple,\n      });\n\n      fileFrame.on('toolbar:create:select', (toolbar) => {\n        fileFrame.createSelectToolbar(toolbar, {\n          text: buttonInsertText,\n        });\n      });\n\n      // When an image is selected, run a callback.\n      fileFrame.once('select', () => {\n        const mediaPickerEl = fileFrame\n          .state()\n          .get('selection')\n          .first()\n          .toJSON();\n\n        // Only allow user to select a mime type from allowed list.\n        if (Array.isArray(type) && !type.includes(mediaPickerEl.mime)) {\n          showSnackbar({ message: onSelectErrorMessage });\n\n          return;\n        }\n        mediaPickerEl.alt = mediaPickerEl.alt || mediaPickerEl.title;\n        onSelect(getResourceFromMediaPicker(mediaPickerEl));\n      });\n\n      fileFrame.once('close', () => {\n        if (onClose) {\n          onClose();\n        }\n        fileFrame.remove();\n      });\n\n      // Finally, open the modal\n      fileFrame.open();\n\n      evt.preventDefault();\n    },\n    [\n      buttonInsertText,\n      hasUploadMediaAction,\n      multiple,\n      onClose,\n      onPermissionError,\n      onSelect,\n      onSelectErrorMessage,\n      showSnackbar,\n      title,\n      type,\n    ]\n  );\n\n  const openCropper = useCallback(\n    (evt) => {\n      trackEvent('open_media_crop_modal');\n      // If a user does not have the rights to upload to the media library, do not show the media picker.\n      if (!hasUploadMediaAction) {\n        if (onPermissionError) {\n          onPermissionError();\n        }\n        evt.preventDefault();\n        return;\n      }\n\n      const params = {\n        ...defaultCropParams,\n        ...cropParams,\n      };\n\n      const control = {\n        id: 'control-id',\n        params,\n        mustBeCropped,\n      };\n\n      // Create the media frame.\n      const fileFrame = window.wp.media({\n        button: {\n          text: buttonInsertText,\n          close: false,\n        },\n        states: [\n          new window.wp.media.controller.Library({\n            title,\n            library: window.wp.media.query({ type }),\n            multiple,\n            suggestedWidth: params.width,\n            suggestedHeight: params.height,\n          }),\n          // In a Karma context `wp.media.controller.Cropper.extend` will not exist yet\n          // during time of import, despite mocking, so WordPressImageCropper won't be\n          // a class with a proper constructor.\n          // This safeguard below prevents errors in tests while retaining full functionality\n          // in the actual app at runtime.\n          WordPressImageCropper &&\n            new WordPressImageCropper({\n              imgSelectOptions: calculateImageSelectOptions,\n              control,\n            }),\n        ],\n      });\n\n      fileFrame.once('cropped', (attachment) => {\n        if (attachment?.id) {\n          const altText = attachment.alt || attachment.title;\n          updateMedia(attachment.id, {\n            mediaSource: 'editor',\n            altText,\n          });\n          attachment.alt = altText;\n        }\n        onSelect(getResourceFromMediaPicker(attachment));\n      });\n\n      fileFrame.once('skippedcrop', () => {\n        const mediaPickerEl = fileFrame\n          .state()\n          .get('selection')\n          .first()\n          .toJSON();\n        mediaPickerEl.alt = mediaPickerEl.alt || mediaPickerEl.title;\n        onSelect(getResourceFromMediaPicker(mediaPickerEl));\n      });\n\n      fileFrame.once('select', () => {\n        const mediaPickerEl = fileFrame\n          .state()\n          .get('selection')\n          .first()\n          .toJSON();\n\n        // Only allow user to select a mime type from allowed list.\n        if (Array.isArray(type) && !type.includes(mediaPickerEl.mime)) {\n          fileFrame.close();\n          showSnackbar({ message: onSelectErrorMessage });\n\n          return;\n        }\n\n        if (\n          control.params.width === mediaPickerEl.width &&\n          control.params.height === mediaPickerEl.height &&\n          !control.params.flex_width &&\n          !control.params.flex_height\n        ) {\n          mediaPickerEl.alt = mediaPickerEl.alt || mediaPickerEl.title;\n          onSelect(getResourceFromMediaPicker(mediaPickerEl));\n          fileFrame.close();\n        } else {\n          fileFrame.setState('cropper');\n        }\n      });\n\n      fileFrame.once('close', () => {\n        if (onClose) {\n          onClose();\n        }\n        fileFrame.remove();\n      });\n\n      // Finally, open the modal\n      fileFrame.open();\n\n      evt.preventDefault();\n    },\n    [\n      hasUploadMediaAction,\n      cropParams,\n      buttonInsertText,\n      title,\n      type,\n      multiple,\n      onSelect,\n      onClose,\n      onPermissionError,\n      updateMedia,\n      showSnackbar,\n      onSelectErrorMessage,\n    ]\n  );\n\n  return useMemo(() => {\n    return cropParams ? openCropper : openMediaDialog;\n  }, [cropParams, openCropper, openMediaDialog]);\n}\n\nuseMediaPicker.propTypes = {\n  title: PropTypes.string,\n  buttonInsertText: PropTypes.string,\n  onSelect: PropTypes.func.isRequired,\n  onSelectErrorMessage: PropTypes.string,\n  onClose: PropTypes.func,\n  onPermissionError: PropTypes.func,\n  type: PropTypes.oneOfType([\n    PropTypes.string,\n    PropTypes.arrayOf(PropTypes.string),\n  ]),\n  cropParams: PropTypes.object,\n  multiple: PropTypes.bool,\n};\n\nexport default useMediaPicker;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/calculateImageSelectOptions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns a set of options, computed from the attached image data and\n * control-specific data, to be fed to the imgAreaSelect plugin in\n * wp.media.view.Cropper.\n *\n * @param {window.wp.media.model.Attachment} attachment Attachment object.\n * @param {window.wp.media.controller.Cropper} controller wp.media controller object.\n * @return {Object} Options\n */\nconst calculateImageSelectOptions = (attachment, controller) => {\n  const control = controller.get('control');\n\n  const flexWidth = Boolean(Number.parseInt(control.params.flex_width));\n  const flexHeight = Boolean(Number.parseInt(control.params.flex_height));\n  const realWidth = attachment.get('width');\n  const realHeight = attachment.get('height');\n  let xInit = Number.parseInt(control.params.width);\n  let yInit = Number.parseInt(control.params.height);\n  const ratio = xInit / yInit;\n  const xImg = xInit;\n  const yImg = yInit;\n\n  controller.set(\n    'canSkipCrop',\n    !control.mustBeCropped(\n      flexWidth,\n      flexHeight,\n      xInit,\n      yInit,\n      realWidth,\n      realHeight\n    )\n  );\n\n  if (realWidth / realHeight > ratio) {\n    yInit = realHeight;\n    xInit = yInit * ratio;\n  } else {\n    xInit = realWidth;\n    yInit = xInit / ratio;\n  }\n\n  const x1 = (realWidth - xInit) / 2;\n  const y1 = (realHeight - yInit) / 2;\n\n  const imgSelectOptions = {\n    handles: true,\n    keys: true,\n    instance: true,\n    persistent: true,\n    imageWidth: realWidth,\n    imageHeight: realHeight,\n    minWidth: xImg > xInit ? xInit : xImg,\n    minHeight: yImg > yInit ? yInit : yImg,\n    x1: x1,\n    y1: y1,\n    x2: xInit + x1,\n    y2: yInit + y1,\n  };\n\n  if (flexHeight === false && flexWidth === false) {\n    imgSelectOptions.aspectRatio = xInit + ':' + yInit;\n  }\n\n  if (true === flexHeight) {\n    delete imgSelectOptions.minHeight;\n    imgSelectOptions.maxWidth = realWidth;\n  }\n\n  if (true === flexWidth) {\n    delete imgSelectOptions.minWidth;\n    imgSelectOptions.maxHeight = realHeight;\n  }\n\n  return imgSelectOptions;\n};\n\nexport default calculateImageSelectOptions;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/getResourceFromMediaPicker.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createResource, getResourceSize } from '@googleforcreators/media';\nimport { snakeToCamelCaseObjectKeys } from '@web-stories-wp/wp-utils';\n\n/**\n * Generates a resource object from a WordPress media picker object.\n *\n * @param {Object} mediaPickerEl WP Media Picker object.\n * @return {import('@googleforcreators/media').Resource} Resource object.\n */\nconst getResourceFromMediaPicker = (mediaPickerEl) => {\n  const {\n    src,\n    url,\n    mime: mimeType,\n    alt,\n    date,\n    id,\n    featured_media: posterId,\n    featured_media_src: {\n      src: poster,\n      width: posterWidth,\n      height: posterHeight,\n      generated: posterGenerated,\n    } = '',\n    media_details: {\n      width,\n      height,\n      length,\n      length_formatted: lengthFormatted,\n      sizes: _sizes = {},\n    } = {},\n    web_stories_media_source: mediaSource,\n    web_stories_is_muted: isMuted,\n    web_stories_base_color: baseColor,\n    web_stories_blurhash: blurHash,\n    trim_data: trimData,\n  } = mediaPickerEl;\n\n  const sizes = Object.entries(_sizes).reduce((sizes, [key, value]) => {\n    sizes[key] = snakeToCamelCaseObjectKeys(value);\n    return sizes;\n  }, {});\n\n  return createResource({\n    baseColor,\n    blurHash,\n    mimeType,\n    creationDate: date,\n    src: url || src,\n    ...getResourceSize({\n      width,\n      height,\n      posterGenerated,\n      posterWidth,\n      posterHeight,\n    }),\n    poster,\n    posterId,\n    id,\n    length,\n    lengthFormatted,\n    alt,\n    sizes,\n    local: false,\n    isExternal: false,\n    isOptimized: ['video-optimization', 'recording'].includes(mediaSource),\n    isMuted,\n    trimData,\n  });\n};\n\nexport default getResourceFromMediaPicker;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default as calculateImageSelectOptions } from './calculateImageSelectOptions';\nexport { default as getResourceFromMediaPicker } from './getResourceFromMediaPicker';\nexport { default as mustBeCropped } from './mustBeCropped';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/mustBeCropped.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Return whether the image must be cropped, based on required dimensions.\n *\n * @param {boolean} flexW Flexible width.\n * @param {boolean} flexH Flexible height.\n * @param {number}  dstW Destination width.\n * @param {number}  dstH Destination height.\n * @param {number}  imgW Image Width.\n * @param {number}  imgH Image height.\n * @return {boolean} Whether or not an image must be cropped or not.\n */\nconst mustBeCropped = (flexW, flexH, dstW, dstH, imgW, imgH) => {\n  if (true === flexW && true === flexH) {\n    return false;\n  }\n\n  if (true === flexW && dstH === imgH) {\n    return false;\n  }\n\n  if (true === flexH && dstW === imgW) {\n    return false;\n  }\n\n  if (dstW === imgW && dstH === imgH) {\n    return false;\n  }\n\n  // Skip cropping of the image's aspect ratio is the same as the required aspect ratio.\n  if (Math.abs(dstW / dstH - imgW / imgH) < Number.EPSILON) {\n    return false;\n  }\n\n  return true;\n};\nexport default mustBeCropped;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/test/calculateImageSelectOptions.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport calculateImageSelectOptions from '../calculateImageSelectOptions';\n\nconst attachment = {\n  get: () => {\n    return 300;\n  },\n};\n\ndescribe('calculateImageSelectOptions', () => {\n  it('pass some default values', () => {\n    const controller = {\n      get: () => {\n        return {\n          mustBeCropped: () => {},\n          params: {\n            flex_width: 0,\n            flex_height: 0,\n            width: 300,\n            height: 300,\n          },\n        };\n      },\n      set: () => {},\n    };\n    const result = calculateImageSelectOptions(attachment, controller);\n    const expectedCalculateImageSelectOptions = {\n      aspectRatio: '300:300',\n      handles: true,\n      imageHeight: 300,\n      imageWidth: 300,\n      instance: true,\n      keys: true,\n      minHeight: 300,\n      minWidth: 300,\n      persistent: true,\n      x1: 0,\n      x2: 300,\n      y1: 0,\n      y2: 300,\n    };\n    expect(result).toStrictEqual(expectedCalculateImageSelectOptions);\n  });\n\n  it('flex height and widget', () => {\n    const controller = {\n      get: () => {\n        return {\n          mustBeCropped: () => {},\n          params: {\n            flex_width: 1,\n            flex_height: 1,\n            width: 300,\n            height: 300,\n          },\n        };\n      },\n      set: () => {},\n    };\n    const result = calculateImageSelectOptions(attachment, controller);\n    const expectedCalculateImageSelectOptions = {\n      handles: true,\n      imageHeight: 300,\n      imageWidth: 300,\n      instance: true,\n      keys: true,\n      maxHeight: 300,\n      maxWidth: 300,\n      persistent: true,\n      x1: 0,\n      x2: 300,\n      y1: 0,\n      y2: 300,\n    };\n    expect(result).toStrictEqual(expectedCalculateImageSelectOptions);\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/test/getResourceFromMediaPicker.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport getResourceFromMediaPicker from '../getResourceFromMediaPicker';\n\ndescribe('getResourceFromMediaPicker', () => {\n  it('should transform media picker element into resource', () => {\n    const mediaPickerEl = {\n      id: 1234,\n      title: 'example.jpg',\n      filename: 'example.jpg',\n      url: 'https://example.com/wp-content/uploads/example.jpg',\n      link: 'https://example.com/example-jpg/',\n      alt: 'example.jpg',\n      author: '1',\n      description: 'https://example.com/wp-content/uploads/example.jpg',\n      caption: '',\n      name: 'example-jpg',\n      status: 'inherit',\n      uploadedTo: 0,\n      date: '2022-02-10T15:03:03.000Z',\n      modified: '2022-02-10T15:05:07.000Z',\n      menuOrder: 0,\n      mime: 'image/jpeg',\n      type: 'image',\n      subtype: 'jpeg',\n      icon: 'https://example.com/wp-includes/images/media/default.png',\n      dateFormatted: 'February 10, 2022',\n      nonces: {\n        update: 'db1fb0b017',\n        delete: '52880b1870',\n        edit: '5a9af214ea',\n      },\n      editLink: 'https://example.com/wp-admin/post.php?post=1234&action=edit',\n      meta: false,\n      authorName: 'Pascal',\n      authorLink: 'https://example.com/wp-admin/profile.php',\n      filesizeInBytes: 64588,\n      filesizeHumanReadable: '63 KB',\n      context: 'control-id',\n      height: 853,\n      width: 640,\n      orientation: 'portrait',\n      sizes: {\n        thumbnail: {\n          height: 150,\n          width: 150,\n          url: 'https://example.com/wp-content/uploads/example-150x150.jpg',\n          orientation: 'landscape',\n        },\n        medium: {\n          height: 300,\n          width: 225,\n          url: 'https://example.com/wp-content/uploads/example-225x300.jpg',\n          orientation: 'portrait',\n        },\n        full: {\n          url: 'https://example.com/wp-content/uploads/example.jpg',\n          height: 853,\n          width: 640,\n          orientation: 'portrait',\n        },\n      },\n      compat: {\n        item: '',\n        meta: '',\n      },\n      web_stories_base_color: '#bb9470',\n      web_stories_blurhash: 'UdJ%aptlo}S#~AX9WD$%NGbHRkn%wIxaS#R+',\n      media_details: {\n        width: 640,\n        height: 853,\n        file: '2021/12/example.jpg',\n        sizes: {\n          medium: {\n            file: 'example-225x300.jpg',\n            width: 225,\n            height: 300,\n            mime_type: 'image/jpeg',\n            source_url:\n              'https://example.com/wp-content/uploads/example-225x300.jpg',\n          },\n          thumbnail: {\n            file: 'example-150x150.jpg',\n            width: 150,\n            height: 150,\n            mime_type: 'image/jpeg',\n            source_url:\n              'https://example.com/wp-content/uploads/example-150x150.jpg',\n          },\n          'web-stories-poster-portrait': {\n            file: 'example-640x853.jpg',\n            width: 640,\n            height: 853,\n            mime_type: 'image/jpeg',\n            source_url:\n              'https://example.com/wp-content/uploads/example-640x853.jpg',\n          },\n          'web-stories-publisher-logo': {\n            file: 'example-96x96.jpg',\n            width: 96,\n            height: 96,\n            mime_type: 'image/jpeg',\n            source_url:\n              'https://example.com/wp-content/uploads/example-96x96.jpg',\n          },\n          'web-stories-thumbnail': {\n            file: 'example-150x200.jpg',\n            width: 150,\n            height: 200,\n            mime_type: 'image/jpeg',\n            source_url:\n              'https://example.com/wp-content/uploads/example-150x200.jpg',\n          },\n          full: {\n            file: 'example.jpg',\n            width: 640,\n            height: 853,\n            mime_type: 'image/jpeg',\n            source_url: 'https://example.com/wp-content/uploads/example.jpg',\n          },\n        },\n      },\n      web_stories_media_source: 'editor',\n    };\n\n    expect(getResourceFromMediaPicker(mediaPickerEl)).toStrictEqual(\n      expect.objectContaining({\n        alt: 'example.jpg',\n        baseColor: '#bb9470',\n        blurHash: 'UdJ%aptlo}S#~AX9WD$%NGbHRkn%wIxaS#R+',\n        creationDate: '2022-02-10T15:03:03.000Z',\n        height: 853,\n        id: 1234,\n        isExternal: false,\n        isPlaceholder: false,\n        mimeType: 'image/jpeg',\n        needsProxy: false,\n        src: 'https://example.com/wp-content/uploads/example.jpg',\n        type: 'image',\n        width: 640,\n        sizes: {\n          medium: {\n            file: 'example-225x300.jpg',\n            width: 225,\n            height: 300,\n            mimeType: 'image/jpeg',\n            sourceUrl:\n              'https://example.com/wp-content/uploads/example-225x300.jpg',\n          },\n          thumbnail: {\n            file: 'example-150x150.jpg',\n            width: 150,\n            height: 150,\n            mimeType: 'image/jpeg',\n            sourceUrl:\n              'https://example.com/wp-content/uploads/example-150x150.jpg',\n          },\n          'web-stories-poster-portrait': {\n            file: 'example-640x853.jpg',\n            width: 640,\n            height: 853,\n            mimeType: 'image/jpeg',\n            sourceUrl:\n              'https://example.com/wp-content/uploads/example-640x853.jpg',\n          },\n          'web-stories-publisher-logo': {\n            file: 'example-96x96.jpg',\n            width: 96,\n            height: 96,\n            mimeType: 'image/jpeg',\n            sourceUrl:\n              'https://example.com/wp-content/uploads/example-96x96.jpg',\n          },\n          'web-stories-thumbnail': {\n            file: 'example-150x200.jpg',\n            width: 150,\n            height: 200,\n            mimeType: 'image/jpeg',\n            sourceUrl:\n              'https://example.com/wp-content/uploads/example-150x200.jpg',\n          },\n          full: {\n            file: 'example.jpg',\n            width: 640,\n            height: 853,\n            mimeType: 'image/jpeg',\n            sourceUrl: 'https://example.com/wp-content/uploads/example.jpg',\n          },\n        },\n      })\n    );\n  });\n\n  it('should return resource for VTT file', () => {\n    const mediaPickerEl = {\n      id: 1234,\n      title: 'captions',\n      filename: 'captions.vtt',\n      url: 'https://example.com/wp-content/uploads/captions.vtt',\n      link: 'https://example.com/captions/',\n      alt: 'captions',\n      author: '1',\n      description: '',\n      caption: '',\n      name: 'captions',\n      status: 'inherit',\n      uploadedTo: 0,\n      date: '2021-11-12T11:15:56.000Z',\n      modified: '2021-11-12T11:15:56.000Z',\n      menuOrder: 0,\n      mime: 'text/vtt',\n      type: 'text',\n      subtype: 'vtt',\n      icon: 'https://example.com/wp-includes/images/media/text.png',\n      dateFormatted: 'November 12, 2021',\n      nonces: {\n        update: 'a43563250f',\n        delete: '813aa798e6',\n        edit: '2a2853a1b9',\n      },\n      editLink: 'https://example.com/wp-admin/post.php?post=1234&action=edit',\n      meta: false,\n      authorName: 'Pascal',\n      authorLink: 'https://example.com/wp-admin/profile.php',\n      filesizeInBytes: 17551,\n      filesizeHumanReadable: '17 KB',\n      context: '',\n      compat: {\n        item: '',\n        meta: '',\n      },\n      web_stories_base_color: '',\n      web_stories_blurhash: '',\n      media_details: [],\n      web_stories_media_source: 'editor',\n    };\n\n    expect(getResourceFromMediaPicker(mediaPickerEl)).toStrictEqual(\n      expect.objectContaining({\n        alt: 'captions',\n        baseColor: '',\n        blurHash: '',\n        creationDate: '2021-11-12T11:15:56.000Z',\n        id: 1234,\n        isExternal: false,\n        isPlaceholder: false,\n        mimeType: 'text/vtt',\n        needsProxy: false,\n        src: 'https://example.com/wp-content/uploads/captions.vtt',\n        type: 'text',\n        sizes: {},\n      })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/mediaUpload/mediaPicker/utils/test/mustBeCropped.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport mustBeCropped from '../mustBeCropped';\n\ndescribe('mustBeCropped', () => {\n  it('flexible height / width false, and height and with 0', () => {\n    const result = mustBeCropped(false, false, 0, 0, 0, 0);\n    expect(result).toBeFalse();\n  });\n\n  it('flexible height / width', () => {\n    const result = mustBeCropped(true, true, 300, 300, 300, 300);\n    expect(result).toBeFalse();\n  });\n\n  it('matching values', () => {\n    const result = mustBeCropped(false, false, 300, 300, 300, 300);\n    expect(result).toBeFalse();\n  });\n\n  it('larger height and width', () => {\n    const result = mustBeCropped(false, false, 300, 300, 500, 505);\n    expect(result).toBeTrue();\n  });\n\n  it('same aspect ratio', () => {\n    const result = mustBeCropped(false, false, 300, 300, 500, 500);\n    expect(result).toBeFalse();\n  });\n\n  it('smaller values', () => {\n    const result = mustBeCropped(false, false, 680, 853, 300, 300);\n    expect(result).toBeTrue();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/context.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { createContext } from '@googleforcreators/react';\n\nexport default createContext({ state: {}, actions: {} });\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport { default as MetaBoxes } from './metaBoxes';\nexport { default as MetaBoxesProvider } from './metaBoxesProvider';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/menuItem/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\nimport { useCallback } from '@googleforcreators/react';\nimport { trackEvent } from '@googleforcreators/tracking';\nimport { Tooltip } from '@googleforcreators/story-editor';\nimport {\n  Button as DesignSystemButton,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  Icons,\n  Placement,\n  THEME_CONSTANTS,\n} from '@googleforcreators/design-system';\nimport styled, { css } from 'styled-components';\n\n/**\n * Internal dependencies\n */\nimport useMetaBoxes from '../useMetaBoxes';\n\nconst Box = styled.div`\n  width: 32px;\n  height: 32px;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n`;\n\nconst Button = styled(DesignSystemButton)`\n  border-width: 1px;\n  border-style: solid;\n  padding: 0 10px;\n  white-space: nowrap;\n  height: 36px;\n  min-width: 36px;\n  /* Handle props-dependent styling in one place */\n  ${({ isOpen, theme }) => css`\n    color: ${theme.colors.fg.primary};\n    border-color: ${isOpen\n      ? theme.colors.bg.secondary\n      : theme.colors.border.defaultNormal};\n    background-color: ${isOpen\n      ? theme.colors.bg.secondary\n      : theme.colors.bg.primary};\n  `}\n\n  /* This should be sufficient to ensure proper spacing of button content */\n  > :not(svg):last-child {\n    margin-right: 0;\n  }\n\n  /*\n   Margin is set to -8px to compensate for empty space\n   around the actual icon graphic in the svg\n  */\n  svg {\n    height: ${THEME_CONSTANTS.ICON_SIZE}px;\n    width: auto;\n    margin: -8px;\n    display: block;\n  }\n`;\n\nconst Item = styled.div``;\n\nfunction MenuItem() {\n  const { metaBoxesVisible, toggleMetaBoxesVisible, hasMetaBoxes } =\n    useMetaBoxes(({ state, actions }) => ({\n      hasMetaBoxes: state.hasMetaBoxes,\n      metaBoxesVisible: state.metaBoxesVisible,\n      toggleMetaBoxesVisible: actions.toggleMetaBoxesVisible,\n    }));\n\n  const handleMetaBoxesClick = useCallback(() => {\n    toggleMetaBoxesVisible();\n    trackEvent('meta_boxes_toggled', {\n      status: metaBoxesVisible ? 'visible' : 'hidden',\n    });\n  }, [metaBoxesVisible, toggleMetaBoxesVisible]);\n\n  if (!hasMetaBoxes) {\n    return null;\n  }\n\n  return (\n    <Item>\n      <Box>\n        <Tooltip\n          title={__('Third-Party Meta Boxes', 'web-stories')}\n          placement={Placement.Top}\n          hasTail\n        >\n          <Button\n            aria-haspopup\n            aria-pressed={metaBoxesVisible}\n            aria-expanded={metaBoxesVisible}\n            isOpen={metaBoxesVisible}\n            type={ButtonType.Tertiary}\n            variant={ButtonVariant.Rectangle}\n            size={ButtonSize.Medium}\n            onClick={handleMetaBoxesClick}\n            aria-label={__('Third-Party Meta Boxes', 'web-stories')}\n          >\n            <Icons.LetterMOutline />\n          </Button>\n        </Tooltip>\n      </Box>\n    </Item>\n  );\n}\n\nexport default MenuItem;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/metaBoxes.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport {\n  useEffect,\n  useRef,\n  useState,\n  createPortal,\n} from '@googleforcreators/react';\nimport { useConfig, useStory } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport MenuItem from './menuItem';\nimport MetaBoxesArea from './metaBoxesArea';\nimport useMetaBoxes from './useMetaBoxes';\nimport useSaveMetaBoxes from './useSaveMetaBoxes';\n\nconst Wrapper = styled.div``;\n\nconst Area = styled.div`\n  grid-area: ${({ area }) => area};\n  position: relative;\n  overflow: hidden;\n  z-index: 2;\n`;\n\nconst MetaBoxesContainer = styled(Area).attrs({\n  area: 'supplementary',\n})`\n  overflow-y: auto;\n`;\n\nfunction MetaBoxes() {\n  const { metaBoxesVisible, hasMetaBoxes } = useMetaBoxes(({ state }) => ({\n    hasMetaBoxes: state.hasMetaBoxes,\n    metaBoxesVisible: state.metaBoxesVisible,\n  }));\n  const [showMenuButton, updateMenuButtonState] = useState(false);\n  const menuButtonContainerRef = useRef(null);\n  const { postType, metaBoxes = {} } = useConfig();\n  const { pages, isSavingStory, isAutoSavingStory, story } = useStory(\n    ({\n      state: {\n        meta: { isSavingStory, isAutoSavingStory },\n        story,\n        pages,\n      },\n    }) => ({ pages, isSavingStory, isAutoSavingStory, story })\n  );\n\n  useSaveMetaBoxes({ isSavingStory, isAutoSavingStory, story });\n\n  useEffect(() => {\n    let timeout;\n\n    if (!showMenuButton && hasMetaBoxes && pages.length > 0) {\n      timeout = setTimeout(() => {\n        menuButtonContainerRef.current =\n          document.getElementById('primary-menu-items');\n        updateMenuButtonState(null !== menuButtonContainerRef.current);\n      });\n    }\n\n    return () => {\n      clearTimeout(timeout);\n    };\n  }, [pages, hasMetaBoxes, showMenuButton]);\n\n  useEffect(() => {\n    // Allow toggling metaboxes panels.\n    // We need to wait for all scripts to load.\n    // If the meta box loads the post script, it will already trigger this.\n    // See https://github.com/WordPress/gutenberg/blob/148e2b28d4cdd4465c4fe68d97fcee154a6b209a/packages/edit-post/src/store/effects.js#L25-L35\n    const timeout = setTimeout(() => {\n      if (window.postboxes?.page !== postType) {\n        window.postboxes?.add_postbox_toggles(postType);\n      }\n    });\n\n    return () => {\n      clearTimeout(timeout);\n    };\n  }, [postType]);\n\n  if (!hasMetaBoxes) {\n    return null;\n  }\n\n  const locations = Object.keys(metaBoxes);\n\n  return (\n    <MetaBoxesContainer>\n      {metaBoxesVisible && (\n        <Wrapper>\n          {locations.map((location) => {\n            return <MetaBoxesArea key={location} location={location} />;\n          })}\n        </Wrapper>\n      )}\n      {showMenuButton /* eslint-disable-next-line react-hooks/refs -- FIXME */ &&\n        createPortal(<MenuItem />, menuButtonContainerRef.current)}\n    </MetaBoxesContainer>\n  );\n}\n\nexport default MetaBoxes;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/metaBoxesArea.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useRef } from '@googleforcreators/react';\nimport PropTypes from 'prop-types';\nimport styled from 'styled-components';\nimport { rgba } from 'polished';\nimport { useStory } from '@googleforcreators/story-editor';\nimport { CircularProgress } from '@googleforcreators/design-system';\n\nconst Wrapper = styled.div`\n  position: relative;\n\n  /**\n   * The wordpress default for most meta-box elements is content-box. Some\n   * elements such as textarea and input are set to border-box in forms.css.\n   * These elements therefore specifically set back to border-box here, while\n   * other elements (such as .button) are unaffected by Gutenberg's style\n   * because of their higher specificity.\n   */\n  &__container,\n  .inside {\n    box-sizing: content-box;\n  }\n\n  /* Match width and positioning of the meta boxes. Override default styles. */\n  #poststuff {\n    margin: 0 auto;\n    padding-top: 0;\n    min-width: auto;\n  }\n\n  /* Override Default meta box styling */\n  #poststuff h3.hndle,\n  #poststuff .stuffbox > h3,\n  #poststuff h2.hndle {\n    color: ${({ theme }) => rgba(theme.colors.standard.white, 0.84)};\n    font-size: 14px;\n    font-weight: 500;\n    outline: none;\n    padding: 15px;\n    width: 100%;\n  }\n\n  .postbox {\n    border: 0;\n    color: inherit;\n    margin-bottom: 0;\n  }\n\n  .postbox > .hndle,\n  .postbox .postbox-header {\n    background: ${({ theme }) => theme.colors.bg.secondary};\n    color: ${({ theme }) => rgba(theme.colors.standard.white, 0.84)};\n    border-bottom: 1px solid\n      ${({ theme }) => rgba(theme.colors.standard.white, 0.04)};\n  }\n\n  .postbox .handlediv {\n    height: 44px;\n    width: 44px;\n  }\n\n  .postbox .handlediv .toggle-indicator {\n    color: ${({ theme }) => rgba(theme.colors.standard.white, 0.84)};\n  }\n\n  .postbox .handle-order-higher,\n  .postbox .handle-order-lower {\n    color: ${({ theme }) => rgba(theme.colors.standard.white, 0.84)};\n\n    &[aria-disabled='true'] {\n      color: ${({ theme }) => rgba(theme.colors.standard.white, 0.3)};\n    }\n  }\n\n  /**\n   * Hide disabled meta boxes using CSS so that we don't interfere with plugins\n   * that modify 'element.style.display' on the meta box.\n   */\n  .is-hidden {\n    display: none;\n  }\n`;\n\nconst Spinner = styled.div`\n  position: absolute;\n  top: 10px;\n  right: 100px;\n  z-index: 1;\n`;\n\n/**\n * Component for displaying a single meta box.\n *\n * @see https://github.com/WordPress/gutenberg/blob/78585d6935fee9020017d17383cef597b67c5703/packages/edit-post/src/components/meta-boxes/meta-boxes-area/index.js\n * @param {Object} props Component props.\n * @param {string} props.location Location name.\n * @return {*} Element.\n */\nfunction MetaBoxesArea({ location }) {\n  const formRef = useRef();\n  const containerRef = useRef();\n\n  const { isSaving } = useStory(({ state }) => ({\n    isSaving: state.meta.isSaving,\n  }));\n\n  useEffect(() => {\n    const form = document.querySelector(`.metabox-location-${location}`);\n    formRef.current = form;\n    if (formRef.current && containerRef.current) {\n      containerRef.current.appendChild(formRef.current);\n    }\n\n    return () => {\n      document.querySelector('#metaboxes').appendChild(form);\n    };\n  });\n\n  return (\n    <Wrapper\n      className={`web-stories-meta-boxes-area web-stories-meta-boxes-area-${location}`}\n    >\n      {isSaving && (\n        <Spinner>\n          <CircularProgress size={30} />\n        </Spinner>\n      )}\n      <div ref={containerRef} />\n    </Wrapper>\n  );\n}\n\nMetaBoxesArea.propTypes = {\n  location: PropTypes.string.isRequired,\n};\n\nexport default MetaBoxesArea;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/metaBoxesProvider.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback, useMemo, useState } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction MetaBoxesProvider({ children }) {\n  const { metaBoxes = {} } = useConfig();\n\n  const [metaBoxesVisible, setMetaBoxesVisible] = useState(false);\n  const [isSavingMetaBoxes, setIsSavingMetaBoxes] = useState(false);\n  const toggleMetaBoxesVisible = useCallback(\n    () => setMetaBoxesVisible((visible) => !visible),\n    [setMetaBoxesVisible]\n  );\n\n  const hasMetaBoxes = Object.keys(metaBoxes).some((location) =>\n    Boolean(metaBoxes[location]?.length)\n  );\n\n  const locations = Object.keys(metaBoxes);\n\n  const state = useMemo(\n    () => ({\n      state: {\n        isSavingMetaBoxes,\n        metaBoxesVisible,\n        metaBoxes,\n        locations,\n        hasMetaBoxes,\n      },\n      actions: {\n        toggleMetaBoxesVisible,\n        setIsSavingMetaBoxes,\n      },\n    }),\n    [\n      isSavingMetaBoxes,\n      metaBoxesVisible,\n      setIsSavingMetaBoxes,\n      toggleMetaBoxesVisible,\n      metaBoxes,\n      locations,\n      hasMetaBoxes,\n    ]\n  );\n\n  return <Context.Provider value={state}>{children}</Context.Provider>;\n}\n\nMetaBoxesProvider.propTypes = {\n  children: PropTypes.node,\n};\n\nexport default MetaBoxesProvider;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/test/useSaveMetaBoxes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { renderHook } from '@testing-library/react-hooks';\nimport { ConfigContext } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport useSaveMetaBoxes from '../useSaveMetaBoxes';\nimport MetaBoxesProvider from '../metaBoxesProvider';\nimport useMetaBoxes from '../useMetaBoxes';\n\nconst render = ({ configValue, isEnabled, ...initialProps }) => {\n  return renderHook(\n    ({ story, isSavingStory, isAutoSavingStory }) => {\n      useSaveMetaBoxes({ story, isSavingStory, isAutoSavingStory });\n      return useMetaBoxes();\n    },\n    {\n      initialProps: { ...initialProps },\n      wrapper: ({ children }) => (\n        <ConfigContext.Provider value={configValue}>\n          <MetaBoxesProvider>{children}</MetaBoxesProvider>\n        </ConfigContext.Provider>\n      ),\n    }\n  );\n};\n\ndescribe('useSaveMetaBoxes', () => {\n  it('saves meta box form data', async () => {\n    const baseFormElement = document.createElement('form');\n    baseFormElement.className = 'metabox-base-form';\n\n    // \"Normal\" meta box area with 1 meta box.\n\n    const normalWrapper = document.createElement('div');\n    normalWrapper.className = 'web-stories-meta-boxes-area-normal';\n\n    const normalLocation = document.createElement('form');\n    normalLocation.className = 'metabox-location-normal';\n    normalWrapper.appendChild(normalLocation);\n\n    const normalMetaBoxInput = document.createElement('input');\n    normalMetaBoxInput.name = 'normal-metabox-input-value';\n    normalMetaBoxInput.value = 'Normal Data';\n    normalLocation.appendChild(normalMetaBoxInput);\n\n    // \"Advanced\" meta box area with 1 meta box.\n\n    const advancedWrapper = document.createElement('div');\n    advancedWrapper.className = 'web-stories-meta-boxes-area-advanced';\n\n    const advancedLocation = document.createElement('form');\n    advancedLocation.className = 'metabox-location-advanced';\n    advancedWrapper.appendChild(advancedLocation);\n\n    const advancedMetaBoxInput = document.createElement('input');\n    advancedMetaBoxInput.name = 'advanced-metabox-input-value';\n    advancedMetaBoxInput.value = 'Advanced Data';\n    advancedLocation.appendChild(advancedMetaBoxInput);\n\n    document.body.appendChild(baseFormElement);\n    document.body.appendChild(normalWrapper);\n    document.body.appendChild(advancedWrapper);\n\n    const configValue = {\n      metaBoxes: {\n        normal: [{}],\n        advanced: [{}],\n      },\n      api: {\n        metaBoxes:\n          'http://localhost:10003/wp-admin/post.php?post=5&action=edit&meta-box-loader=1&meta-box-loader-nonce=d19ae41860',\n      },\n    };\n\n    const story = { id: 123 };\n\n    const hookProps = {\n      story,\n      isSavingStory: true,\n      isAutoSavingStory: false,\n    };\n\n    const { rerender, waitForNextUpdate, result } = render({\n      configValue,\n      isEnabled: true,\n      ...hookProps,\n    });\n\n    expect(result.current.state.isSavingMetaBoxes).toBeFalse();\n    rerender({ ...hookProps, isSavingStory: false });\n\n    expect(result.current.state.isSavingMetaBoxes).toBeTrue();\n    await waitForNextUpdate();\n    expect(result.current.state.isSavingMetaBoxes).toBeFalse();\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/useMetaBoxes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { identity, useContextSelector } from '@googleforcreators/react';\n/**\n * Internal dependencies\n */\nimport Context from './context';\n\nfunction useMetaBoxes(selector) {\n  return useContextSelector(Context, selector ?? identity);\n}\n\nexport default useMetaBoxes;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/metaBoxes/useSaveMetaBoxes.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, usePrevious } from '@googleforcreators/react';\nimport { useConfig } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport { saveMetaBoxes } from '../../api/metaboxes';\nimport useMetaBoxes from './useMetaBoxes';\n\n/**\n * Effect to save meta boxes for a story.\n *\n * @see https://github.com/WordPress/gutenberg/blob/148e2b28d4cdd4465c4fe68d97fcee154a6b209a/packages/edit-post/src/store/effects.js#L24-L126\n * @param {Object} props Hook props.\n * @param {Object} props.story Story object.\n * @param {boolean} props.isSavingStory Whether saving is in progress.\n * @param {boolean} props.isAutoSavingStory Whether autosaving is in progress.\n */\nfunction useSaveMetaBoxes({ story, isSavingStory, isAutoSavingStory }) {\n  const { hasMetaBoxes, locations, isSavingMetaBoxes, setIsSavingMetaBoxes } =\n    useMetaBoxes(({ state, actions }) => ({\n      hasMetaBoxes: state.hasMetaBoxes,\n      locations: state.locations,\n      isSavingMetaBoxes: state.isSavingMetaBoxes,\n      setIsSavingMetaBoxes: actions.setIsSavingMetaBoxes,\n    }));\n\n  const {\n    api: { metaBoxes: apiUrl },\n  } = useConfig();\n\n  const wasSaving = usePrevious(isSavingStory);\n  const wasAutoSaving = usePrevious(isAutoSavingStory);\n\n  // Save metaboxes when performing a full save on the post.\n  useEffect(() => {\n    if (\n      !hasMetaBoxes ||\n      isSavingStory ||\n      isAutoSavingStory ||\n      isSavingMetaBoxes ||\n      !wasSaving ||\n      wasAutoSaving\n    ) {\n      return;\n    }\n\n    async function save() {\n      // Saves the wp_editor fields.\n      window.tinyMCE?.triggerSave();\n\n      // We gather all the metaboxes locations data and the base form data.\n      const baseFormElement = document.querySelector('.metabox-base-form');\n      const baseFormData = new window.FormData(baseFormElement || undefined);\n\n      const formDataToMerge = [\n        baseFormData,\n        ...locations.map(\n          (location) =>\n            new window.FormData(\n              document.querySelector(`.metabox-location-${location}`) ||\n                undefined\n            )\n        ),\n      ];\n\n      // Merge all form data objects into a single one.\n      const formData = formDataToMerge.reduce((acc, currentFormData) => {\n        for (const [key, value] of currentFormData) {\n          acc.append(key, value);\n        }\n        return acc;\n      }, new window.FormData());\n\n      setIsSavingMetaBoxes(true);\n      await saveMetaBoxes(story, formData, apiUrl);\n      setIsSavingMetaBoxes(false);\n    }\n\n    save();\n  }, [\n    hasMetaBoxes,\n    story,\n    isSavingStory,\n    wasSaving,\n    isAutoSavingStory,\n    wasAutoSaving,\n    isSavingMetaBoxes,\n    setIsSavingMetaBoxes,\n    locations,\n    apiUrl,\n  ]);\n}\n\nexport default useSaveMetaBoxes;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './postLock';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/postLock.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from '@googleforcreators/react';\nimport { trackError } from '@googleforcreators/tracking';\nimport {\n  useStory,\n  useConfig,\n  useCurrentUser,\n  useHistory,\n} from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport {\n  getStoryLockById,\n  setStoryLockById,\n  deleteStoryLockById,\n} from '../../api/storyLock';\nimport PostLockDialog from './postLockDialog';\nimport PostTakeOverDialog from './postTakeOverDialog';\n\nfunction PostLock() {\n  const { currentUser } = useCurrentUser(({ state }) => ({\n    currentUser: state.currentUser,\n  }));\n  const {\n    storyId,\n    dashboardLink,\n    nonce: firstNonce,\n    postLock: { interval: postLockInterval, showLockedDialog },\n    api: { stories, storyLocking },\n  } = useConfig();\n\n  const {\n    state: { hasNewChanges },\n  } = useHistory();\n\n  const { previewLink, lockUser, autoSave } = useStory(\n    ({\n      state: {\n        story: { previewLink, extras: { lockUser = {} } = {} },\n      },\n      actions: { autoSave },\n    }) => ({\n      previewLink,\n      lockUser,\n      autoSave,\n    })\n  );\n  const [currentOwner, setCurrentOwner] = useState(null);\n  const [initialOwner, setInitialOwner] = useState(null);\n  const [autoSaveDoneWhenTakenOver, setAutoSaveDoneWhenTakenOver] =\n    useState(false);\n  const [nonce, setNonce] = useState(firstNonce);\n\n  // When dialog is closed, then set current user to lock owner.\n  const closeDialog = useCallback(() => {\n    setCurrentOwner(null);\n    setStoryLockById(storyId, stories);\n  }, [storyId, stories]);\n\n  const currentUserLoaded = useMemo(\n    () => currentUser && Boolean(Object.keys(currentUser).length),\n    [currentUser]\n  );\n\n  // When async call only if dialog is true, current user is loaded and post locking is enabled.\n  const doGetStoryLock = useCallback(() => {\n    (async () => {\n      if (showLockedDialog && currentUserLoaded) {\n        try {\n          const {\n            locked,\n            nonce: newNonce,\n            user,\n          } = await getStoryLockById(storyId, stories);\n          const lockAuthor = {\n            ...user,\n            avatar: user?.avatar?.['96'] || '',\n          };\n          if (locked && initialOwner === null) {\n            setInitialOwner(lockAuthor);\n          }\n          if (locked && lockAuthor?.id && lockAuthor?.id !== currentUser.id) {\n            setCurrentOwner(lockAuthor);\n          } else {\n            setStoryLockById(storyId, stories);\n          }\n          // Refresh nonce on every request.\n          setNonce(newNonce);\n        } catch (err) {\n          trackError('post_lock', err.message);\n        }\n      }\n    })();\n  }, [\n    setCurrentOwner,\n    storyId,\n    stories,\n    currentUser,\n    initialOwner,\n    setInitialOwner,\n    showLockedDialog,\n    currentUserLoaded,\n  ]);\n\n  // Cache it to make it stable in terms of the below timeout\n  const cachedDoGetStoryLockRef = useRef(doGetStoryLock);\n  useEffect(() => {\n    cachedDoGetStoryLockRef.current = doGetStoryLock;\n  }, [doGetStoryLock, currentUserLoaded]);\n\n  useEffect(() => {\n    if (showLockedDialog && currentUserLoaded) {\n      if (lockUser?.id && lockUser?.id !== currentUser.id) {\n        setCurrentOwner(lockUser);\n      }\n    }\n  }, [lockUser, currentUser, currentUserLoaded, showLockedDialog]);\n\n  // Register an event on user navigating away from current tab to release / delete lock.\n  useEffect(() => {\n    function releasePostLock() {\n      if (showLockedDialog && currentOwner?.id && nonce) {\n        deleteStoryLockById(storyId, nonce, storyLocking);\n      }\n    }\n\n    window.addEventListener('beforeunload', releasePostLock);\n\n    return () => {\n      window.removeEventListener('beforeunload', releasePostLock);\n    };\n  }, [storyId, showLockedDialog, currentOwner, nonce, storyLocking]);\n\n  // Register repeating callback to check lock every 150 seconds.\n  useEffect(() => {\n    const timeout = setInterval(() => {\n      if (!postLockInterval) {\n        return;\n      }\n      if (currentUserLoaded) {\n        cachedDoGetStoryLockRef.current();\n      }\n    }, postLockInterval * 1000);\n\n    return () => clearInterval(timeout);\n  }, [postLockInterval, currentUserLoaded]);\n\n  useEffect(() => {\n    if (\n      showLockedDialog &&\n      hasNewChanges &&\n      currentUser?.id === initialOwner?.id &&\n      currentOwner &&\n      currentOwner?.id !== currentUser?.id &&\n      !autoSaveDoneWhenTakenOver\n    ) {\n      autoSave();\n      setAutoSaveDoneWhenTakenOver(true);\n    }\n  }, [\n    hasNewChanges,\n    showLockedDialog,\n    currentOwner,\n    initialOwner,\n    currentUser,\n    autoSave,\n    autoSaveDoneWhenTakenOver,\n    setAutoSaveDoneWhenTakenOver,\n  ]);\n\n  if (!showLockedDialog || !currentOwner) {\n    return null;\n  }\n\n  // On first load, display dialog with option to take over.\n  if (initialOwner?.id !== currentUser?.id) {\n    return (\n      <PostLockDialog\n        isOpen={Boolean(currentOwner?.id)}\n        owner={currentOwner}\n        onClose={closeDialog}\n        previewLink={previewLink}\n        dashboardLink={dashboardLink}\n      />\n    );\n  }\n\n  // Second time around, show message that story was taken over.\n  if (\n    currentUser?.id === initialOwner?.id &&\n    currentOwner?.id !== currentUser?.id\n  ) {\n    return (\n      <PostTakeOverDialog\n        isOpen={Boolean(currentOwner?.id)}\n        owner={currentOwner}\n        dashboardLink={dashboardLink}\n        previewLink={previewLink}\n        onClose={closeDialog}\n      />\n    );\n  }\n\n  return null;\n}\n\nexport default PostLock;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/postLockDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport {\n  Button,\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { Dialog } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport {\n  DialogWrapper,\n  DialogText,\n  DialogImageWrapper,\n  DialogContent,\n  Avatar,\n} from './shared';\n\n/**\n * @param {Object} props Component props.\n * @param {boolean} props.isOpen If open or not.\n * @param {Object} props.owner Lock owner's user data as a object.\n * @param {string} props.dashboardLink Link to dashboard.\n * @param {string} props.previewLink Preview link.\n * @param {Function} props.onClose Function when dialog is closed.\n * @return {*} Render.\n */\nfunction PostLockDialog({\n  isOpen,\n  onClose,\n  owner,\n  dashboardLink,\n  previewLink,\n}) {\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      shouldCloseOnEsc={false}\n      shouldCloseOnOverlayClick={false}\n      title={__('This story is already being edited', 'web-stories')}\n      actions={\n        <>\n          <ButtonAsLink\n            type={ButtonType.Tertiary}\n            size={ButtonSize.Small}\n            href={previewLink}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n          >\n            {__('Preview', 'web-stories')}\n          </ButtonAsLink>\n          <Button\n            type={ButtonType.Tertiary}\n            size={ButtonSize.Small}\n            onClick={onClose}\n          >\n            {__('Take over', 'web-stories')}\n          </Button>\n          <ButtonAsLink\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            href={dashboardLink}\n          >\n            {__('Back to dashboard', 'web-stories')}\n          </ButtonAsLink>\n        </>\n      }\n    >\n      <DialogWrapper>\n        {owner?.avatar && (\n          <DialogImageWrapper>\n            <Avatar\n              src={owner.avatar}\n              alt={owner.name}\n              height={48}\n              width={48}\n              crossOrigin=\"anonymous\"\n              decoding=\"async\"\n            />\n          </DialogImageWrapper>\n        )}\n        <DialogContent>\n          <DialogText size={TextSize.Small}>\n            <>\n              {sprintf(\n                /* translators: %s: owner's name */\n                __(\n                  '%s is currently working on this story, which means you cannot make changes, unless you take over.',\n                  'web-stories'\n                ),\n                owner?.name\n              )}\n            </>\n          </DialogText>\n          <DialogText size={TextSize.Small}>\n            {sprintf(\n              /* translators: %s: owner's name */ __(\n                'If you take over, %s will lose editing control to the story, but their changes will be saved.',\n                'web-stories'\n              ),\n              owner?.name\n            )}\n          </DialogText>\n        </DialogContent>\n      </DialogWrapper>\n    </Dialog>\n  );\n}\n\nPostLockDialog.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  owner: PropTypes.object,\n  dashboardLink: PropTypes.string.isRequired,\n  previewLink: PropTypes.string,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default PostLockDialog;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/postTakeOverDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { __, sprintf } from '@googleforcreators/i18n';\nimport PropTypes from 'prop-types';\nimport {\n  ButtonAsLink,\n  ButtonSize,\n  ButtonType,\n  ButtonVariant,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { Dialog } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport {\n  DialogWrapper,\n  DialogText,\n  DialogImageWrapper,\n  DialogContent,\n  Avatar,\n} from './shared';\n\n/**\n * @param {Object} props Component props.\n * @param {boolean} props.isOpen If open or not.\n * @param {Object} props.owner Lock owner's user data as a object.\n * @param {string} props.dashboardLink Link to dashboard.\n * @param {string} props.previewLink Preview link.\n * @param {Function} props.onClose Function when dialog is closed.\n * @return {*} Render.\n */\nfunction PostTakeOverDialog({\n  isOpen,\n  owner,\n  dashboardLink,\n  previewLink,\n  onClose,\n}) {\n  return (\n    <Dialog\n      isOpen={isOpen}\n      title={__('Someone else has taken over this story', 'web-stories')}\n      onClose={onClose}\n      shouldCloseOnEsc={false}\n      shouldCloseOnOverlayClick={false}\n      actions={\n        <>\n          <ButtonAsLink\n            type={ButtonType.Tertiary}\n            size={ButtonSize.Small}\n            href={previewLink}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n          >\n            {__('Preview', 'web-stories')}\n          </ButtonAsLink>\n          <ButtonAsLink\n            type={ButtonType.Primary}\n            size={ButtonSize.Small}\n            variant={ButtonVariant.Rectangle}\n            href={dashboardLink}\n          >\n            {__('Back to dashboard', 'web-stories')}\n          </ButtonAsLink>\n        </>\n      }\n    >\n      <DialogWrapper>\n        {owner?.avatar && (\n          <DialogImageWrapper>\n            <Avatar\n              src={owner.avatar}\n              alt={owner.name}\n              height={48}\n              width={48}\n              crossOrigin=\"anonymous\"\n              decoding=\"async\"\n            />\n          </DialogImageWrapper>\n        )}\n\n        <DialogContent>\n          <DialogText size={TextSize.Small}>\n            {sprintf(\n              /* translators: %s: owner's name */\n              __('%s now has editing control of this story.', 'web-stories'),\n              owner?.name\n            )}\n          </DialogText>\n\n          <DialogText size={TextSize.Small}>\n            {__(\n              \"Don't worry, your changes up to this moment have been saved\",\n              'web-stories'\n            )}\n          </DialogText>\n        </DialogContent>\n      </DialogWrapper>\n    </Dialog>\n  );\n}\n\nPostTakeOverDialog.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  owner: PropTypes.object,\n  dashboardLink: PropTypes.string.isRequired,\n  previewLink: PropTypes.string.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default PostTakeOverDialog;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/shared.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport styled from 'styled-components';\nimport { Text } from '@googleforcreators/design-system';\n\nexport const DialogWrapper = styled.div`\n  display: grid;\n  grid-template-columns: auto 1fr;\n`;\n\nexport const DialogImageWrapper = styled.div``;\n\nexport const DialogContent = styled.div``;\n\nexport const DialogText = styled(Text.Paragraph)`\n  margin-bottom: 12px;\n`;\n\nexport const Avatar = styled.img`\n  margin: 0 12px 0 0;\n`;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/stories/postLockDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PostLockDialog from '../postLockDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Post Lock Dialog',\n  component: PostLockDialog,\n  args: {\n    user: {\n      name: 'Matt Mullenweg',\n      avatar:\n        'http://1.gravatar.com/avatar/767fc9c115a1b989744c755db47feb60?size=48',\n    },\n    dashboardLink: 'http://www.example.com/dashboard',\n    previewLink: 'http://www.example.com/preview',\n    isOpen: true,\n  },\n  argTypes: {\n    onClose: { action: 'onClose' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <PostLockDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/stories/postTakeOverDialog.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport PostTakeOverDialog from '../postTakeOverDialog';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Post Take Over Dialog',\n  component: PostTakeOverDialog,\n  args: {\n    isOpen: true,\n    user: {\n      name: 'Matt Mullenweg',\n      avatar:\n        'http://1.gravatar.com/avatar/767fc9c115a1b989744c755db47feb60?size=48',\n    },\n    dashboardLink: 'http://www.example.com/dashboard',\n    previewLink: 'http://www.example.com/preview',\n  },\n  argTypes: {\n    onClose: { action: 'onClose' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <PostTakeOverDialog {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postLock/test/postLock.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { FlagsProvider } from 'flagged';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { screen, act, waitFor } from '@testing-library/react';\nimport {\n  ConfigContext,\n  StoryContext,\n  CurrentUserContext,\n  HistoryContext,\n} from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport {\n  getStoryLockById,\n  setStoryLockById,\n  deleteStoryLockById,\n} from '../../../api/storyLock';\nimport PostLock from '../postLock';\n\njest.mock('../../../api/storyLock');\n\nconst autoSave = jest.fn();\n\nfunction setup({\n  extraStoryContextValue = {},\n  extraConfigValue = {},\n  extraHistoryProps = {},\n}) {\n  const configValue = {\n    storyId: 123,\n    dashboardLink: 'http://www.example.com/dashboard',\n    nonce: '12345',\n    postLock: {\n      interval: 150,\n      showLockedDialog: true,\n    },\n    api: {\n      stories: '',\n      storyLocking: '',\n    },\n    ...extraConfigValue,\n  };\n\n  const storyContextValue = {\n    state: {\n      story: {\n        previewLink: 'http://www.example.com/preview',\n        extras: {\n          lockUser: {\n            id: 150,\n            name: 'John Doe',\n          },\n        },\n      },\n    },\n    actions: {\n      autoSave,\n    },\n    ...extraStoryContextValue,\n  };\n\n  const userContextValue = {\n    state: {\n      currentUser: {\n        id: 150,\n        name: 'John Doe',\n      },\n    },\n  };\n\n  const historyContextValue = {\n    state: { ...extraHistoryProps },\n  };\n\n  return renderWithTheme(\n    <FlagsProvider features={configValue.flags}>\n      <HistoryContext.Provider value={historyContextValue}>\n        <ConfigContext.Provider value={configValue}>\n          <StoryContext.Provider value={storyContextValue}>\n            <CurrentUserContext.Provider value={userContextValue}>\n              <PostLock />\n            </CurrentUserContext.Provider>\n          </StoryContext.Provider>\n        </ConfigContext.Provider>\n      </HistoryContext.Provider>\n    </FlagsProvider>\n  );\n}\ndescribe('PostLock', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    jest.useFakeTimers();\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n\n    setStoryLockById.mockReturnValue(Promise.resolve());\n    deleteStoryLockById.mockReturnValue(Promise.resolve());\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n    jest.runAllTimers();\n  });\n\n  it('should display take over dialog', async () => {\n    const extraStoryContextValue = {\n      state: {\n        story: {\n          previewLink: 'http://www.example.com/preview',\n          extras: {\n            lockUser: {\n              id: 123,\n              name: 'John Doe',\n            },\n          },\n        },\n      },\n    };\n\n    getStoryLockById.mockReturnValue(\n      Promise.resolve({\n        locked: true,\n        user: 123,\n        nonce: 'fsdfds',\n        _embedded: { author: [{ id: 123, name: 'John Doe' }] },\n      })\n    );\n\n    setup({ extraStoryContextValue });\n\n    const dialog = await screen.findByRole('dialog');\n    expect(dialog).toBeInTheDocument();\n\n    const dashboardButton = screen.getByRole('link', { name: /Dashboard/i });\n    expect(dashboardButton).toBeInTheDocument();\n\n    const takeOverButton = screen.getByRole('button', { name: 'Take over' });\n    expect(takeOverButton).toBeInTheDocument();\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- Investigate issues with timer in test.\n  it.skip('should display dialog', async () => {\n    jest.spyOn(window, 'setInterval');\n\n    getStoryLockById.mockReturnValue(\n      Promise.resolve({\n        locked: true,\n        user: 123,\n        nonce: 'fsdfds',\n        _embedded: { author: [{ id: 123, name: 'John Doe' }] },\n      })\n    );\n\n    setup();\n\n    expect(setInterval).toHaveBeenCalledOnce();\n\n    act(() => {\n      jest.advanceTimersByTime(160 * 1000);\n    });\n\n    await waitFor(() => {\n      const dialog = screen.getByRole('dialog');\n      expect(dialog).toBeInTheDocument();\n    });\n\n    await waitFor(() => {\n      expect(\n        screen.getByRole('link', { name: 'Dashboard' })\n      ).toBeInTheDocument();\n    });\n\n    expect(\n      screen.getByText('John Doe now has editing control of this story.')\n    ).toBeInTheDocument();\n  });\n\n  // eslint-disable-next-line jest/no-disabled-tests -- With bug this test was easy, it needs overhaul for the current version.\n  it.skip('should autosave', async () => {\n    jest.spyOn(window, 'setInterval');\n\n    getStoryLockById.mockReturnValue(\n      Promise.resolve({\n        locked: true,\n        user: 123,\n        nonce: 'fsdfds',\n        _embedded: { author: [{ id: 123, name: 'John Doe' }] },\n      })\n    );\n\n    const extraHistoryProps = { hasNewChanges: true };\n\n    setup({ extraHistoryProps });\n\n    expect(setInterval).toHaveBeenCalledOnce();\n\n    act(() => {\n      jest.advanceTimersByTime(160 * 1000);\n    });\n\n    await waitFor(() => {\n      expect(autoSave).toHaveBeenCalledWith();\n    });\n  });\n\n  it('should not display dialog', () => {\n    getStoryLockById.mockReturnValue(\n      Promise.resolve({\n        locked: true,\n        user: 150,\n        nonce: 'fsdfds',\n        _embedded: { author: [{ id: 150, name: 'John Doe' }] },\n      })\n    );\n\n    setup({});\n\n    expect(screen.queryByRole('dialog')).not.toBeInTheDocument();\n  });\n\n  it('should register beforeunload listener', () => {\n    jest.spyOn(window, 'addEventListener');\n\n    getStoryLockById.mockReturnValue(\n      Promise.resolve({\n        locked: true,\n        user: 150,\n        nonce: 'fsdfds',\n        _embedded: { author: [{ id: 150, name: 'John Doe' }] },\n      })\n    );\n    setup({});\n\n    expect(window.addEventListener).toHaveBeenCalledWith(\n      'beforeunload',\n      expect.any(Function)\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postPublishDialog/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport {\n  ButtonAsLink,\n  Link,\n  Text,\n  TextSize,\n} from '@googleforcreators/design-system';\nimport { Dialog, useStory } from '@googleforcreators/story-editor';\n\nfunction PostPublishDialog() {\n  const {\n    embedPostLink: confirmURL,\n    link: storyURL,\n    isFreshlyPublished,\n    status,\n  } = useStory(\n    ({\n      state: {\n        story: { embedPostLink, link, status },\n        meta: { isFreshlyPublished },\n      },\n    }) => ({\n      embedPostLink,\n      link,\n      isFreshlyPublished,\n      status,\n    })\n  );\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  useEffect(() => setIsOpen(Boolean(isFreshlyPublished)), [isFreshlyPublished]);\n\n  const onAddToPostClick = useCallback((evt) => {\n    trackClick(evt, 'add_story_to_new_post');\n  }, []);\n\n  const onViewStoryClick = useCallback((evt) => {\n    trackClick(evt, 'view_story');\n  }, []);\n  const onClose = useCallback(() => setIsOpen(false), []);\n\n  const primaryText = confirmURL ? __('Add to new post', 'web-stories') : '';\n\n  const dialogTitle =\n    status === 'private'\n      ? __('Story published privately.', 'web-stories')\n      : status === 'future'\n        ? __('Story scheduled.', 'web-stories')\n        : __('Story published.', 'web-stories');\n\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      // Same as item_published post type label.\n      title={dialogTitle}\n      secondaryText={__('Dismiss', 'web-stories')}\n      primaryText={primaryText}\n      onPrimary={onAddToPostClick}\n      PrimaryComponent={ButtonAsLink}\n      primaryRest={{ href: confirmURL }}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                size={TextSize.Small}\n                href={storyURL}\n                target=\"_blank\"\n                rel=\"noreferrer\"\n                onClick={onViewStoryClick}\n              />\n            ),\n          }}\n        >\n          {status === 'future'\n            ? __(\n                'Your story has been successfully scheduled! <a>View story</a>.',\n                'web-stories'\n              )\n            : __(\n                'Your story has been successfully published! <a>View story</a>.',\n                'web-stories'\n              )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n      {confirmURL && (\n        <Text.Paragraph size={TextSize.Small}>\n          {\n            /* translators: 'it' refers to a web story. */\n            __('Would you like to include it on a new post?', 'web-stories')\n          }\n        </Text.Paragraph>\n      )}\n    </Dialog>\n  );\n}\n\nexport default PostPublishDialog;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postPublishDialog/stories/postPublishDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryContext } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport PostPublishDialog from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Post-Publish',\n  component: PostPublishDialog,\n};\n\nconst storyContext = {\n  state: {\n    story: {\n      embedPostLink:\n        'https://example.com/wp-admin/post-new.php?from-web-story=123',\n      link: '',\n    },\n    meta: {\n      isFreshlyPublished: true,\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryContext.Provider value={storyContext}>\n        <PostPublishDialog />\n      </StoryContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postPublishDialog/test/postPublishDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  fireEvent,\n  screen,\n  waitForElementToBeRemoved,\n} from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { StoryContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport PostPublishDialog from '..';\n\nfunction setupButtons({ meta: extraMetaProps } = {}) {\n  const storyContextValue = {\n    state: {\n      capabilities: {\n        hasPublishAction: true,\n      },\n      meta: { isSaving: false, isFreshlyPublished: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n        embedPostLink:\n          'https://example.com/wp-admin/post-new.php?from-web-story=123',\n        previewLink:\n          'http://localhost?preview_id=1679&preview_nonce=b5ea827939&preview=true',\n      },\n    },\n    actions: { saveStory: jest.fn(), autoSave: jest.fn() },\n  };\n\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <PostPublishDialog />\n    </StoryContext.Provider>\n  );\n}\n\ndescribe('buttons', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n  });\n\n  it('should display post-publish dialog if recently published', async () => {\n    setupButtons({ meta: { isFreshlyPublished: true } });\n\n    const dismissButton = screen.getByRole('button', { name: 'Dismiss' });\n    expect(dismissButton).toBeInTheDocument();\n    fireEvent.click(dismissButton);\n\n    await waitForElementToBeRemoved(() =>\n      screen.queryByRole('button', { name: 'Dismiss' })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postReviewDialog/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useCallback, useEffect, useState } from '@googleforcreators/react';\nimport { __ } from '@googleforcreators/i18n';\nimport { Text, TextSize } from '@googleforcreators/design-system';\nimport { Dialog, useStory } from '@googleforcreators/story-editor';\n\nfunction PostReviewDialog() {\n  const { isFreshlyPending } = useStory(\n    ({\n      state: {\n        meta: { isFreshlyPending },\n      },\n    }) => ({\n      isFreshlyPending,\n    })\n  );\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  useEffect(() => setIsOpen(isFreshlyPending), [isFreshlyPending]);\n\n  const onClose = useCallback(() => setIsOpen(false), []);\n\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      title={__('Submitted for Review.', 'web-stories')}\n      primaryText={__('Dismiss', 'web-stories')}\n      onPrimary={onClose}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        {__(\n          'Your Story has been successfully submitted for review.',\n          'web-stories'\n        )}\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nexport default PostReviewDialog;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postReviewDialog/stories/postReviewDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { StoryContext } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport PostReviewDialog from '..';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Post-Review Submitted',\n  component: PostReviewDialog,\n};\n\nconst storyContext = {\n  state: {\n    meta: {\n      isFreshlyPublished: true,\n    },\n  },\n};\n\nexport const _default = {\n  render: function Render() {\n    return (\n      <StoryContext.Provider value={storyContext}>\n        <PostReviewDialog />\n      </StoryContext.Provider>\n    );\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/postReviewDialog/test/postReviewDialog.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport {\n  fireEvent,\n  screen,\n  waitForElementToBeRemoved,\n} from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { StoryContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport PostReviewDialog from '..';\n\nfunction setupButtons({ meta: extraMetaProps } = {}) {\n  const storyContextValue = {\n    state: {\n      meta: { isSaving: false, isFreshlyPending: false, ...extraMetaProps },\n      story: {\n        status: 'draft',\n        storyId: 123,\n        date: null,\n        editLink: 'http://localhost/wp-admin/post.php?post=123&action=edit',\n      },\n    },\n    actions: { saveStory: jest.fn(), autoSave: jest.fn() },\n  };\n\n  renderWithTheme(\n    <StoryContext.Provider value={storyContextValue}>\n      <PostReviewDialog />\n    </StoryContext.Provider>\n  );\n}\n\ndescribe('buttons', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n  });\n\n  it('should display post-review dialog if recently published and in review', async () => {\n    setupButtons({ meta: { isFreshlyPending: true } });\n\n    const dismissButton = screen.getByRole('button', { name: 'Dismiss' });\n    expect(dismissButton).toBeInTheDocument();\n    fireEvent.click(dismissButton);\n\n    await waitForElementToBeRemoved(() =>\n      screen.queryByRole('button', { name: 'Dismiss' })\n    );\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/revisionMessage/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './revisionMessage';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/revisionMessage/revisionMessage.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useConfig } from '@googleforcreators/story-editor';\nimport { useSnackbar } from '@googleforcreators/design-system';\nimport { useEffect } from '@googleforcreators/react';\n\nfunction RevisionMessage() {\n  const { revisionMessage } = useConfig();\n  const { showSnackbar } = useSnackbar();\n  useEffect(() => {\n    if (revisionMessage) {\n      showSnackbar({\n        message: revisionMessage,\n        dismissible: true,\n      });\n    }\n  }, [showSnackbar, revisionMessage]);\n\n  return null;\n}\n\nexport default RevisionMessage;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/revisionMessage/test/revisionMessage.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { ConfigContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport RevisionMessage from '../revisionMessage';\n\nconst mockShowSnackbar = jest.fn();\njest.mock('@googleforcreators/design-system', () => ({\n  ...jest.requireActual('@googleforcreators/design-system'),\n  useSnackbar: () => ({ showSnackbar: mockShowSnackbar }),\n}));\n\nfunction setup({ extraConfigValue = {} }) {\n  const configValue = {\n    revisionMessage: '',\n    ...extraConfigValue,\n  };\n\n  return renderWithTheme(\n    <ConfigContext.Provider value={configValue}>\n      <RevisionMessage />\n    </ConfigContext.Provider>\n  );\n}\ndescribe('RevisionMessage.', () => {\n  beforeEach(() => {\n    mockShowSnackbar.mockReset();\n  });\n\n  it('should not display snackbar', () => {\n    setup({});\n\n    expect(mockShowSnackbar).not.toHaveBeenCalled();\n  });\n\n  it('should display snackbar', () => {\n    setup({\n      extraConfigValue: {\n        revisionMessage: 'Foobar',\n      },\n    });\n\n    expect(mockShowSnackbar).toHaveBeenCalledWith({\n      dismissible: true,\n      message: 'Foobar',\n    });\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport { default } from './statusCheck';\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/statusCheck.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { useEffect, useCallback, useState } from '@googleforcreators/react';\nimport { trackError } from '@googleforcreators/tracking';\nimport { useConfig } from '@googleforcreators/story-editor';\n\n/**\n * Internal dependencies\n */\nimport { getStatusCheck } from '../../api/statusCheck';\nimport { getContent } from './utils';\nimport StatusCheckFailed from './statusCheckFailed';\n\nfunction StatusCheck() {\n  const [showDialog, setShowDialog] = useState(false);\n  const closeDialog = useCallback(() => setShowDialog(false), []);\n  const {\n    api: { statusCheck },\n    encodeMarkup,\n  } = useConfig();\n\n  useEffect(() => {\n    // If it succeeds, do nothing.\n    // Only in case of failure do we want to alert the user and track the error.\n    getStatusCheck(getContent(), statusCheck, encodeMarkup)\n      .then((result) => {\n        if (result && result?.success === true) {\n          return;\n        }\n\n        try {\n          JSON.parse(result);\n        } catch {\n          throw new Error('Invalid JSON');\n        }\n      })\n      .catch((err) => {\n        setShowDialog(true);\n        trackError('status_check', err.message);\n      });\n  }, [encodeMarkup, statusCheck]);\n\n  return <StatusCheckFailed isOpen={showDialog} onClose={closeDialog} />;\n}\nexport default StatusCheck;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/statusCheckFailed.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport PropTypes from 'prop-types';\nimport { useCallback } from '@googleforcreators/react';\nimport { __, TranslateWithMarkup } from '@googleforcreators/i18n';\nimport { trackClick } from '@googleforcreators/tracking';\nimport { Link, Text, TextSize } from '@googleforcreators/design-system';\nimport { Dialog } from '@googleforcreators/story-editor';\n\nconst SUPPORT_URL = __(\n  'https://wordpress.org/support/plugin/web-stories/',\n  'web-stories'\n);\n\nfunction StatusCheckFailed({ isOpen, onClose }) {\n  const onSupportClick = useCallback((evt) => {\n    trackClick(evt, 'click_support_page');\n  }, []);\n\n  return (\n    <Dialog\n      isOpen={isOpen}\n      onClose={onClose}\n      title={__('Unable to save your story', 'web-stories')}\n      contentLabel={__('Unable to save your story', 'web-stories')}\n      onPrimary={onClose}\n      primaryText={__('Dismiss', 'web-stories')}\n    >\n      <Text.Paragraph size={TextSize.Small}>\n        <TranslateWithMarkup\n          mapping={{\n            a: (\n              <Link\n                size={TextSize.Small}\n                href={SUPPORT_URL}\n                target=\"_blank\"\n                rel=\"noreferrer\"\n                onClick={onSupportClick}\n              />\n            ),\n          }}\n        >\n          {__(\n            'We are currently unable to save your story, any changes you make may be lost. This may be due to temporary issues connecting to WordPress. <a>Submit a new support topic</a> for additional help.',\n            'web-stories'\n          )}\n        </TranslateWithMarkup>\n      </Text.Paragraph>\n    </Dialog>\n  );\n}\n\nStatusCheckFailed.propTypes = {\n  isOpen: PropTypes.bool.isRequired,\n  onClose: PropTypes.func.isRequired,\n};\n\nexport default StatusCheckFailed;\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/stories/statusCheckFailed.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\nimport StatusCheckFailed from '../statusCheckFailed';\n\nexport default {\n  title: 'Stories Editor/Components/Dialog/Status Check Failed',\n  component: StatusCheckFailed,\n  args: {\n    isOpen: true,\n  },\n  argTypes: {\n    onClose: { action: 'closed' },\n  },\n};\n\nexport const _default = {\n  render: function Render(args) {\n    return <StatusCheckFailed {...args} />;\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/test/statusCheck.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport {\n  fireEvent,\n  screen,\n  waitForElementToBeRemoved,\n} from '@testing-library/react';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { ConfigContext } from '@googleforcreators/story-editor';\nimport { renderWithTheme } from '@googleforcreators/test-utils';\n\n/**\n * Internal dependencies\n */\nimport StatusCheck from '../statusCheck';\n\njest.mock('../../../api/statusCheck');\nimport { getStatusCheck } from '../../../api/statusCheck';\n\nfunction setup() {\n  const configValue = { api: { statusCheck: '' }, metadata: { publisher: '' } };\n\n  return renderWithTheme(\n    <ConfigContext.Provider value={configValue}>\n      <StatusCheck />\n    </ConfigContext.Provider>\n  );\n}\n\ndescribe('statusCheck', () => {\n  let modalWrapper;\n\n  beforeAll(() => {\n    modalWrapper = document.createElement('aside');\n    document.documentElement.appendChild(modalWrapper);\n    setAppElement(modalWrapper);\n  });\n\n  afterAll(() => {\n    document.documentElement.removeChild(modalWrapper);\n  });\n\n  it('should do nothing if successful', async () => {\n    getStatusCheck.mockReturnValue(Promise.resolve({ success: true }));\n\n    setup();\n\n    // This seems to be the best way to validate, that a certain\n    // element does *not* appear. Not very elegant, though.\n    await expect(screen.findByRole('dialog')).rejects.toThrow(\n      /Unable to find role=\"dialog\"/\n    );\n  });\n\n  it('should display dismissible dialog if failed', async () => {\n    getStatusCheck.mockReturnValue(Promise.reject(new Error('api failed')));\n\n    setup();\n\n    const dialog = await screen.findByRole('dialog');\n    expect(dialog).toBeInTheDocument();\n\n    const dismiss = screen.getByRole('button', { name: /Dismiss/i });\n    expect(dismiss).toBeInTheDocument();\n    fireEvent.click(dismiss);\n\n    await waitForElementToBeRemoved(dialog);\n  });\n});\n"
  },
  {
    "path": "packages/wp-story-editor/src/components/statusCheck/utils.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { getStoryMarkup } from '@googleforcreators/output';\n\nexport function getContent() {\n  const story = {\n    storyId: 1,\n    title: 'Story!',\n    author: {\n      id: 1,\n      name: 'John Doe',\n    },\n    fonts: {},\n    slug: 'story',\n    publisherLogo: {\n      id: 1,\n      url: 'https://example.com/logo.png',\n      height: 0,\n      width: 0,\n    },\n    defaultPageDuration: 7,\n    status: 'publish',\n    date: '2020-04-10T07:06:26',\n    modified: '',\n    excerpt: '',\n    featuredMedia: {\n      id: 123,\n      url: 'https://example.com/image.png',\n      width: 123,\n      height: 456,\n    },\n    password: '',\n    globalStoryStyles: '',\n  };\n  const pages = [\n    {\n      type: 'page',\n      id: '2',\n      elements: [],\n    },\n  ];\n  const metadata = {\n    publisher: 'Web Stories',\n  };\n\n  return getStoryMarkup(story, pages, metadata);\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/constants/index.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './tips';\nexport * from './wpAdmin.js';\nexport * from './status.js';\n"
  },
  {
    "path": "packages/wp-story-editor/src/constants/status.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const VISIBILITY = {\n  PUBLIC: 'public',\n  PRIVATE: 'private',\n  PASSWORD_PROTECTED: 'protected',\n};\n\nexport const STATUS = {\n  PUBLISH: 'publish',\n  FUTURE: 'future',\n  PRIVATE: 'private',\n  DRAFT: 'draft',\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/constants/tips.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { __ } from '@googleforcreators/i18n';\n\nconst DOCS_URL = 'https://wp.stories.google/docs/best-practices/';\n\nconst KEYS = {\n  EMBED_WEB_STORIES: 'embedWebStories',\n};\n\nexport const TIPS = {\n  [KEYS.EMBED_WEB_STORIES]: {\n    title: __('Embed Web Stories', 'web-stories'),\n    /* TODO #7212 `figureSrcImg` and `figureAlt` are temporary until\n    we get an animation. Once we have the animation then these\n    attributes should be removed. */\n    figureSrcImg: 'images/help-center/story_embed_module_1',\n    figureAlt: __('Graphic showing embed functionality', 'web-stories'),\n    description: [\n      __(\n        'When you create a new post in WordPress, you can embed any of your Stories. <a>Learn more</a>',\n        'web-stories'\n      ),\n    ],\n    href: DOCS_URL,\n  },\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/constants/wpAdmin.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TOOLBAR_HEIGHT = 32;\nexport const MENU_WIDTH = 160;\nexport const MENU_FOLDED_WIDTH = 36;\n"
  },
  {
    "path": "packages/wp-story-editor/src/index.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Internal dependencies\n */\n// The __webpack_public_path__ assignment will be done after the imports.\n// That's why the public path assignment is in its own dedicated module and imported here at the very top.\n// See https://webpack.js.org/guides/public-path/#on-the-fly\nimport './publicPath';\nimport './style.css'; // This way the general editor styles are loaded before all the component styles.\n\n// We need to load translations before any other imports happen.\n// That's why this is in its own dedicated module imported here at the very top.\nimport './setLocaleData';\n\n/**\n * External dependencies\n */\nimport { StoryEditor, AutoSaveCheck } from '@googleforcreators/story-editor';\nimport { setAppElement } from '@googleforcreators/design-system';\nimport { StrictMode, render } from '@googleforcreators/react';\nimport { updateSettings } from '@googleforcreators/date';\nimport { initializeTracking } from '@googleforcreators/tracking';\nimport { bindToCallbacks } from '@web-stories-wp/wp-utils';\nimport { registerElementType } from '@googleforcreators/elements';\nimport { elementTypes } from '@googleforcreators/element-library';\n\n/**\n * WordPress dependencies\n */\nimport '@wordpress/dom-ready'; // Just imported here so it's part of the bundle. Usage is in inline scripts.\n\n/**\n * Internal dependencies\n */\nimport {\n  Layout,\n  PostPublishDialog,\n  PostReviewDialog,\n  StatusCheck,\n  CorsCheck,\n  FontCheck,\n  PostLock,\n  MediaUpload,\n  RevisionMessage,\n} from './components';\nimport * as apiCallbacks from './api';\nimport { transformStoryResponse } from './api/utils';\nimport { TIPS, TOOLBAR_HEIGHT, MENU_FOLDED_WIDTH } from './constants';\nimport { GlobalStyle } from './theme.js';\n\nwindow.webStories = window.webStories || {};\n\n/**\n * Initializes the web stories editor.\n *\n * @param {string} id           ID of the root element to render the screen in.\n * @param {Object} config       Story editor settings.\n * @param {Object} initialEdits Initial edits.\n */\nwindow.webStories.initializeStoryEditor = (id, config, initialEdits) => {\n  const appElement = document.getElementById(id);\n\n  // see http://reactcommunity.org/react-modal/accessibility/\n  setAppElement(appElement);\n\n  updateSettings(config.locale);\n\n  initializeTracking('Editor');\n\n  elementTypes.forEach(registerElementType);\n\n  initialEdits.story = initialEdits.story\n    ? transformStoryResponse(initialEdits.story)\n    : null;\n\n  const editorConfig = {\n    ...config,\n    apiCallbacks: bindToCallbacks(apiCallbacks, config),\n    additionalTips: TIPS,\n    MediaUpload,\n    styleConstants: {\n      topOffset: TOOLBAR_HEIGHT,\n      leftOffset: MENU_FOLDED_WIDTH,\n    },\n  };\n\n  render(\n    <StrictMode>\n      <StoryEditor config={editorConfig} initialEdits={initialEdits}>\n        <GlobalStyle />\n        <Layout />\n        <PostPublishDialog />\n        <PostReviewDialog />\n        <StatusCheck />\n        <CorsCheck />\n        <RevisionMessage />\n        <FontCheck />\n        <AutoSaveCheck />\n        <PostLock />\n      </StoryEditor>\n    </StrictMode>,\n    appElement\n  );\n};\n"
  },
  {
    "path": "packages/wp-story-editor/src/publicPath.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n__webpack_public_path__ = window.webStories.publicPath;\n"
  },
  {
    "path": "packages/wp-story-editor/src/setLocaleData.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { setLocaleData } from '@googleforcreators/i18n';\n\nfor (const localeData of window?.webStories?.localeData || []) {\n  setLocaleData(localeData);\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/style.css",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * WordPress admin page integration\n *\n * Hides all controls that interfere with the editor UI.\n */\n\n#screen-meta,\n#screen-meta-links,\n#screen-meta-links ~ :not(.web-stories-wp):not(.clear) {\n  display: none;\n}\n\nbody.js.edit-story #wpcontent {\n  position: fixed;\n  width: calc(100% - 160px);\n}\n\nbody.js.edit-story.folded #adminmenuback {\n  top: 32px;\n}\n\nbody.js.edit-story #wpcontent,\nbody.js.edit-story #wpbody-content {\n  padding: 0;\n}\n\n/* issue #12545 */\nbody.js.edit-story.WebStories_ReactModal__Body--open #wpcontent {\n  position: relative;\n}\n\nbody.edit-story .web-stories-wp {\n  position: relative;\n}\n\nbody.js.edit-story #web-stories-editor {\n  background-color: #131516; /* theme.colors.bg.primary */\n  position: relative;\n  height: calc(100vh - 32px); /* ADMIN_TOOLBAR_HEIGHT = 32 */\n  overflow: hidden;\n}\n\nbody.js.edit-story #web-stories-editor .loading-message {\n  position: absolute;\n  left: 0;\n  top: 0;\n  right: 0;\n  height: 100%;\n  width: 100%;\n  text-align: center;\n  color: #fff;\n  margin: 0;\n  padding-top: 50px;\n  font-size: 36px;\n  font-family: 'Google Sans', sans-serif;\n}\n\n@keyframes spin-progress {\n  0%,\n  100% {\n    box-shadow:\n      0em -1.14em 0em 0em #b488fc,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  12.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #b488fc,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  37.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #b488fc,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  50% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #b488fc,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  62.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #b488fc,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  75% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #b488fc,\n      -0.8em -0.8em 0 0em #cbacff;\n  }\n  87.5% {\n    box-shadow:\n      0em -1.14em 0em 0em #cbacff,\n      0.8em -0.8em 0 0em #cbacff,\n      1.14em 0em 0 0em #cbacff,\n      0.8em 0.8em 0 0em #cbacff,\n      0em 1.14em 0 0em #cbacff,\n      -0.8em 0.8em 0 0em #cbacff,\n      -1.14em 0em 0 0em #cbacff,\n      -0.8em -0.8em 0 0em #b488fc;\n  }\n}\nbody.js.edit-story #web-stories-editor .loading-message:after {\n  content: '';\n  display: block;\n  position: absolute;\n  left: 0;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  margin: 140px auto auto;\n  width: 0.4em;\n  height: 0.4em;\n  border-radius: 50%;\n\n  animation: spin-progress 0.85s infinite\n    cubic-bezier(0.455, 0.03, 0.515, 0.955);\n}\n\nbody.edit-story #wpfooter {\n  display: none;\n}\n\n/* Copied from forms.css in WordPress, avoids issues with \"Collapse menu\" button */\n\nbutton {\n  font-size: inherit;\n}\n\n@media screen and (max-width: 783px) {\n  body.js.edit-story #wpcontent {\n    position: relative;\n    width: 100%;\n  }\n  ul#adminmenu {\n    overflow-y: scroll;\n    height: 100vh;\n  }\n}\n\n@media screen and (min-width: 783px) {\n  #adminmenuwrap,\n  #adminmenuback {\n    z-index: 0;\n  }\n  #adminmenuwrap:hover {\n    z-index: 1;\n  }\n  body.js.edit-story.folded #wpcontent {\n    width: calc(100% - 36px);\n  }\n}\n"
  },
  {
    "path": "packages/wp-story-editor/src/theme.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * External dependencies\n */\nimport { createGlobalStyle } from 'styled-components';\nimport { OVERLAY_CLASS, BODY_CLASS } from '@googleforcreators/design-system';\n\n/**\n * Internal dependencies\n */\nimport { TOOLBAR_HEIGHT, MENU_WIDTH, MENU_FOLDED_WIDTH } from './constants';\n\nexport const GlobalStyle = createGlobalStyle`\n  .${OVERLAY_CLASS} {\n    top: ${TOOLBAR_HEIGHT}px !important;\n    left: ${MENU_WIDTH}px !important;\n  }\n\n  body.folded .${OVERLAY_CLASS} {\n    left: ${MENU_FOLDED_WIDTH}px !important;\n  }\n\n  /*\n    Increase submenu z-index from 3 to 15 so it's above the modal overlay (z-index 10).\n    See https://github.com/GoogleForCreators/web-stories-wp/pull/12443\n  */\n  body.${BODY_CLASS} {\n    #adminmenuwrap, #adminmenuback {\n      z-index: 15;\n    }\n  }\n`;\n"
  },
  {
    "path": "packages/wp-utils/README.md",
    "content": "# wp-utils\n\nUtilities for WordPress integration packages.\n"
  },
  {
    "path": "packages/wp-utils/package.json",
    "content": "{\n  \"name\": \"@web-stories-wp/wp-utils\",\n  \"description\": \"Utilities for WordPress integration packages\",\n  \"private\": true,\n  \"author\": {\n    \"name\": \"Google\",\n    \"url\": \"https://creators.google/\"\n  },\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"web stories\",\n    \"wordpress\"\n  ],\n  \"homepage\": \"https://github.com/GoogleForCreators/web-stories-wp/blob/main/packages/wp-utils/README.md\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/GoogleForCreators/web-stories-wp.git\",\n    \"directory\": \"packages/wp-utils\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/googleforcreators/web-stories-wp/issues\"\n  },\n  \"engines\": {\n    \"node\": \">= 20 || >= 22 || >= 24\",\n    \"npm\": \">= 7.3\"\n  },\n  \"type\": \"module\",\n  \"main\": \"./src/index.ts\",\n  \"types\": \"dist-types/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "packages/wp-utils/src/bindToCallbacks.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nfunction bindToCallbacks<T>(\n  callbacks: Record<string, (config: T) => unknown>,\n  config: T\n): Record<string, unknown> {\n  return Object.fromEntries(\n    Object.entries(callbacks).map(([name, callback]) => [\n      name,\n      callback.bind(null, config),\n    ])\n  );\n}\n\nexport default bindToCallbacks;\n"
  },
  {
    "path": "packages/wp-utils/src/index.ts",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport * from './snakeToCamelCase';\nexport { default as bindToCallbacks } from './bindToCallbacks';\n"
  },
  {
    "path": "packages/wp-utils/src/snakeToCamelCase.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Takes a string that is in snake case and returns the same\n * term in camel case.\n *\n * @param string The key in snake case\n * @return The key in camel case\n */\nexport function snakeToCamelCase(string = ''): string {\n  if (!string.includes('_') && !string.includes('-')) {\n    return string;\n  }\n\n  return string\n    .toLowerCase()\n    .replace(\n      /([a-z])([_|-][a-z])/g,\n      (_match, group1: string, group2: string) =>\n        group1 + group2.toUpperCase().replace('_', '').replace('-', '')\n    );\n}\n\ntype ObjectOrPrimitive = unknown;\n\ninterface SnakeOrCamelCaseObject {\n  [key: string]: ObjectOrPrimitive;\n}\n\nfunction isObject(obj: unknown) {\n  return obj && 'object' === typeof obj && !Array.isArray(obj);\n}\n\n/**\n * Transform a given object keys from snake case to camel case recursively.\n *\n * @param obj Object to be transformed.\n * @param ignore Array of keys to be ignored for camelcase.\n * @return Transformed object.\n */\nexport function snakeToCamelCaseObjectKeys(\n  obj: ObjectOrPrimitive,\n  ignore: string[] = []\n): ObjectOrPrimitive {\n  if (!isObject(obj)) {\n    return obj;\n  }\n\n  return Object.fromEntries(\n    Object.entries(obj as SnakeOrCamelCaseObject).map(\n      ([key, value]: [string, ObjectOrPrimitive]) => {\n        return [\n          snakeToCamelCase(key),\n          isObject(value) && !ignore.includes(key)\n            ? snakeToCamelCaseObjectKeys(value)\n            : value,\n        ] as [string, SnakeOrCamelCaseObject];\n      }\n    )\n  );\n}\n"
  },
  {
    "path": "packages/wp-utils/src/test/snakeToCamelCase.ts",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Internal dependencies\n */\nimport {\n  snakeToCamelCase,\n  snakeToCamelCaseObjectKeys,\n} from '../snakeToCamelCase';\n\ndescribe('snakeToCamelCase', () => {\n  it.each([\n    ['', ''],\n    [undefined, ''],\n    ['test', 'test'],\n    ['rest_base', 'restBase'],\n    ['rest-base', 'restBase'],\n    ['rest-base_test', 'restBaseTest'],\n    ['_links', '_links'],\n    ['links_', 'links_'],\n    ['a_l', 'aL'],\n  ])('should return the expected string for $key', (key, result) => {\n    expect(snakeToCamelCase(key)).toStrictEqual(result);\n  });\n});\n\ndescribe('snakeToCamelCaseObjectKeys', () => {\n  it.each([\n    [{}, {}],\n    [\n      [1, 2],\n      [1, 2],\n    ],\n    [undefined, undefined],\n    ['', ''],\n    [{ item_one: 'two' }, { itemOne: 'two' }],\n  ])('should return the expected value for $key', (key, result) => {\n    expect(snakeToCamelCaseObjectKeys(key)).toStrictEqual(result);\n  });\n\n  it('should return camelcase keys for nested objects', () => {\n    const transformedObject = snakeToCamelCaseObjectKeys({\n      item_one: 'string',\n      itemTwo: 'string',\n      item_three: {\n        level_one_item_one: {\n          level_two_item_one: {\n            level_three_item_one: 22,\n          },\n          levelTwoItemTwo: 'string',\n        },\n        random: 'string',\n      },\n    });\n\n    const expectedResult = {\n      itemOne: 'string',\n      itemTwo: 'string',\n      itemThree: {\n        levelOneItemOne: {\n          levelTwoItemOne: {\n            levelThreeItemOne: 22,\n          },\n          levelTwoItemTwo: 'string',\n        },\n        random: 'string',\n      },\n    };\n\n    expect(transformedObject).toStrictEqual(expectedResult);\n  });\n});\n"
  },
  {
    "path": "packages/wp-utils/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.shared.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"declarationDir\": \"dist-types\"\n  },\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "patches/@types+draft-js+0.11.9.patch",
    "content": "diff --git a/node_modules/@types/draft-js/index.d.ts b/node_modules/@types/draft-js/index.d.ts\nindex ac2e584..3aa03ed 100755\n--- a/node_modules/@types/draft-js/index.d.ts\n+++ b/node_modules/@types/draft-js/index.d.ts\n@@ -419,7 +419,21 @@ declare namespace Draft {\n             /**\n              * Valid inline styles.\n              */\n-            type DraftInlineStyleType = 'BOLD' | 'CODE' | 'ITALIC' | 'STRIKETHROUGH' | 'UNDERLINE';\n+            type DraftInlineStyleType =\n+              | 'BOLD'\n+              | 'CODE'\n+              | 'ITALIC'\n+              | 'STRIKETHROUGH'\n+              | 'UNDERLINE'\n+              | 'NONE'\n+              | 'CUSTOM-ITALIC'\n+              | 'CUSTOM-UNDERLINE'\n+              | 'CUSTOM-WEIGHT'\n+              | 'CUSTOM-WEIGHT-700'\n+              | 'CUSTOM-WEIGHT-900'\n+              | 'CUSTOM-COLOR'\n+              | 'CUSTOM-LETTERSPACING'\n+              | 'CUSTOM-UPPERCASE';\n\n             /**\n              * Default entity types.\n"
  },
  {
    "path": "patches/@types+glider-js+1.7.12.patch",
    "content": "diff --git a/node_modules/@types/glider-js/index.d.ts b/node_modules/@types/glider-js/index.d.ts\nindex 2be4c56..1b838c6 100644\n--- a/node_modules/@types/glider-js/index.d.ts\n+++ b/node_modules/@types/glider-js/index.d.ts\n@@ -97,7 +97,7 @@ declare namespace Glider {\n         /**\n          * An aggravator used to control animation speed. Higher is slower!\n          */\n-        duration?: number | undefined;\n+        duration: number;\n \n         /**\n          * This prevents resizing items to fit when `slidesToShow` is set to\n@@ -247,13 +247,13 @@ declare class Glider<T extends HTMLElement = HTMLDivElement> {\n      * @param slideIndexs string | number\n      * @param isActuallyDotIndex boolean\n      */\n-    scrollItem(slideIndex: string | number, isActuallyDotIndex: boolean): void;\n+    scrollItem(slideIndex: string | number, isActuallyDotIndex: boolean, evt: Event): void;\n \n     /**\n      * Scroll directly to supplied scroll position in pixels\n      * @param pixelOffset number\n      */\n-    scrollTo(pixelOffset: number): void;\n+    scrollTo(pixelOffset: number, scrollDuration?: number, callback?: () => void): void;\n \n     /**\n      * Overrides options set during initialization. If called when a\n@@ -276,6 +276,10 @@ declare class Glider<T extends HTMLElement = HTMLDivElement> {\n     resize(): void;\n \n     init(): void;\n+\n+    emit(name: string, arg: unknown): void;\n+\n+    getCurrentSlide(): number;\n }\n \n declare function Glider<T extends HTMLElement = HTMLDivElement>(element: T): Glider<T>;\n"
  },
  {
    "path": "patches/eslint-plugin-react-hooks+7.0.1.patch",
    "content": "diff --git a/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js b/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js\nindex ec5280f..9844d96 100644\n--- a/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js\n+++ b/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js\n@@ -50,7 +50,26 @@ const rule$1 = {\n                 enableDangerousAutofixThisMayCauseInfiniteLoops: false,\n                 properties: {\n                     additionalHooks: {\n-                        type: 'string',\n+                        anyOf: [\n+                           // An abbreviated form with a single RegExp with the implicit\n+                           // callback index == 0.\n+                           { type: 'string' },\n+                           // An expanded form: an array with RegExp and callback index\n+                           // values.\n+                           {\n+                               type: 'array',\n+                               items: {\n+                                   type: 'object',\n+                                       additionalProperties: false,\n+                                       properties: {\n+                                           // The RegExp string.\n+                                           test: {type: 'string'},\n+                                           // The callback index.\n+                                           callbackIndex: {type: 'number'},\n+                                       },\n+                               },\n+                           },\n+                       ],\n                     },\n                     enableDangerousAutofixThisMayCauseInfiniteLoops: {\n                         type: 'boolean',\n@@ -72,7 +91,7 @@ const rule$1 = {\n         const rawOptions = context.options && context.options[0];\n         const settings = context.settings || {};\n         const additionalHooks = rawOptions && rawOptions.additionalHooks\n-            ? new RegExp(rawOptions.additionalHooks)\n+            ? parseAdditionalHooks(rawOptions.additionalHooks)\n             : getAdditionalEffectHooksFromSettings(settings);\n         const enableDangerousAutofixThisMayCauseInfiniteLoops = (rawOptions &&\n             rawOptions.enableDangerousAutofixThisMayCauseInfiniteLoops) ||\n@@ -1374,13 +1393,44 @@ function getReactiveHookCallbackIndex(calleeNode, options) {\n                         throw error;\n                     }\n                 }\n-                return options.additionalHooks.test(name) ? 0 : -1;\n+                const found = options.additionalHooks.find(({test}) => test.test(name));\n+                return found ? found.callbackIndex : -1;\n             }\n             else {\n                 return -1;\n             }\n     }\n }\n+/**\n+ * Parses the `additionalHooks` configuration. It can be in one of the two\n+ * formats:\n+ * - a single string that indicates the RegExp and implicit callback index of 0;\n+ * - an array of `{ test: string, callbackIndex: number }` objects.\n+ *\n+ * Returns the normalized form of this configuration object in the shape of\n+ * `{  test: RegExp, callbackIndex: number }`.\n+ *\n+ * See `additionalHooks` schema definition for more info.\n+*/\n+function parseAdditionalHooks(additionalHooksConfig) {\n+  if (!additionalHooksConfig) {\n+    return undefined;\n+  }\n+\n+  // A single string format.\n+  if (typeof additionalHooksConfig === 'string') {\n+    return [{test: new RegExp(additionalHooksConfig), callbackIndex: 0}];\n+  }\n+\n+  // An array format.\n+  if (Array.isArray(additionalHooksConfig)) {\n+    return additionalHooksConfig.map(({test, callbackIndex}) => ({\n+        test: new RegExp(test),\n+        callbackIndex,\n+      }));\n+  }\n+  throw new Error('Unknown format of additionalHooks');\n+}\n function fastFindReferenceWithParent(start, target) {\n     const queue = [start];\n     let item;\n"
  },
  {
    "path": "patches/html-to-image+1.10.8.patch",
    "content": "diff --git a/node_modules/html-to-image/es/embed-images.js b/node_modules/html-to-image/es/embed-images.js\nindex 70e8468..e04eb19 100644\n--- a/node_modules/html-to-image/es/util.js\n+++ b/node_modules/html-to-image/es/util.js\n@@ -136,11 +136,11 @@ export function canvasToBlob(canvas, options = {}) {\n export function createImage(url) {\n     return new Promise((resolve, reject) => {\n         const img = new Image();\n-        img.onload = () => resolve(img);\n         img.onerror = reject;\n         img.crossOrigin = 'anonymous';\n         img.decoding = 'sync';\n         img.src = url;\n+        img.decode().then(() => resolve(img)).catch(reject);\n     });\n }\n export async function svgToDataURL(svg) {\n"
  },
  {
    "path": "patches/humbug-php-scoper-php85.diff",
    "content": "diff --git a/src/PhpParser/NodeVisitor/UseStmt/UseStmtCollection.php b/src/PhpParser/NodeVisitor/UseStmt/UseStmtCollection.php\nindex ec64786..74e40d3 100644\n--- a/src/PhpParser/NodeVisitor/UseStmt/UseStmtCollection.php\n+++ b/src/PhpParser/NodeVisitor/UseStmt/UseStmtCollection.php\n@@ -53,7 +53,7 @@ final class UseStmtCollection implements IteratorAggregate\n      * @var array<string, list<Use_>>\n      */\n     private array $nodes = [\n-        null => [],\n+        '' => [],\n     ];\n \n     public function add(?Name $namespaceName, Use_ $use): void"
  },
  {
    "path": "patches/karma-parallel+0.3.1.dev.patch",
    "content": "diff --git a/node_modules/karma-parallel/lib/karma-parallelizer.js b/node_modules/karma-parallel/lib/karma-parallelizer.js\nindex 81ac9df..2989063 100644\n--- a/node_modules/karma-parallel/lib/karma-parallelizer.js\n+++ b/node_modules/karma-parallel/lib/karma-parallelizer.js\n@@ -120,9 +120,11 @@ function createFakeTestContext(ctx, shouldUseDescription) {\n       hasFocusedWithoutFaking =\n         hasFocusedWithoutFaking || (isFocus && !isFaking);\n \n+      const isTopLevelSetupOrTeardown = typeof name === 'function' && !isFocus && !isDescription && !isSpec && depth === 0;\n+\n       if (isDescription) def = wrapDescription(def);\n \n-      if (!isFaking || forceDescribe) {\n+      if (!isFaking || forceDescribe || isTopLevelSetupOrTeardown) {\n         // Call through to framework and return the result\n         return fn.call(this, name, def);\n       } else if (isDescription) {\n"
  },
  {
    "path": "patches/react-moveable+0.56.0.patch",
    "content": "diff --git a/node_modules/react-moveable/declaration/makeMoveable.d.ts b/node_modules/react-moveable/declaration/makeMoveable.d.ts\nindex 9948a7f..a28c4ab 100644\n--- a/node_modules/react-moveable/declaration/makeMoveable.d.ts\n+++ b/node_modules/react-moveable/declaration/makeMoveable.d.ts\n@@ -1,3 +1,4 @@\n+import { IObject } from \"@daybrush/utils\";\n import { Able } from \"./types\";\n import { InitialMoveable } from \"./InitialMoveable\";\n-export declare function makeMoveable<T extends Record<string, any> = {}>(ables: Array<Able<T>>): typeof InitialMoveable & (new (...args: any[]) => InitialMoveable<T>);\n+export declare function makeMoveable<T extends IObject<any> = {}>(ables: Array<Able<T>>): typeof InitialMoveable & (new (...args: any[]) => InitialMoveable<T>);\n"
  },
  {
    "path": "patches/thecodingmachine-safe-nullable.diff",
    "content": "diff --git a/deprecated/mssql.php b/deprecated/mssql.php\nindex 234ef56..aa44ad0 100644\n--- a/deprecated/mssql.php\n+++ b/deprecated/mssql.php\n@@ -97,7 +97,7 @@ function mssql_close($link_identifier = null): void\n  * @throws MssqlException\n  *\n  */\n-function mssql_connect(string $servername = null, string $username = null, string $password = null, bool $new_link = false)\n+function mssql_connect(?string $servername = null, ?string $username = null, ?string $password = null, bool $new_link = false)\n {\n     error_clear_last();\n     if ($new_link !== false) {\n@@ -330,7 +330,7 @@ function mssql_init(string $sp_name, $link_identifier = null)\n  * @throws MssqlException\n  *\n  */\n-function mssql_pconnect(string $servername = null, string $username = null, string $password = null, bool $new_link = false)\n+function mssql_pconnect(?string $servername = null, ?string $username = null, ?string $password = null, bool $new_link = false)\n {\n     error_clear_last();\n     if ($new_link !== false) {\ndiff --git a/generated/bzip2.php b/generated/bzip2.php\nindex 77302aa..95e52e0 100644\n--- a/generated/bzip2.php\n+++ b/generated/bzip2.php\n@@ -81,7 +81,7 @@ function bzread($bz, int $length = 1024): string\n  * @throws Bzip2Exception\n  *\n  */\n-function bzwrite($bz, string $data, int $length = null): int\n+function bzwrite($bz, string $data, ?int $length = null): int\n {\n     error_clear_last();\n     if ($length !== null) {\ndiff --git a/generated/com.php b/generated/com.php\nindex 53643f9..62fc2e2 100644\n--- a/generated/com.php\n+++ b/generated/com.php\n@@ -117,7 +117,7 @@ function com_load_typelib(string $typelib_name, bool $case_sensitive = true): vo\n  * @throws ComException\n  *\n  */\n-function com_print_typeinfo(object $comobject, string $dispinterface = null, bool $wantsink = false): void\n+function com_print_typeinfo(object $comobject, ?string $dispinterface = null, bool $wantsink = false): void\n {\n     error_clear_last();\n     $result = \\com_print_typeinfo($comobject, $dispinterface, $wantsink);\ndiff --git a/generated/curl.php b/generated/curl.php\nindex 53f9255..1b48fc5 100644\n--- a/generated/curl.php\n+++ b/generated/curl.php\n@@ -512,7 +512,7 @@ function curl_exec($ch)\n  * @throws CurlException\n  *\n  */\n-function curl_getinfo($ch, int $opt = null)\n+function curl_getinfo($ch, ?int $opt = null)\n {\n     error_clear_last();\n     if ($opt !== null) {\n@@ -542,7 +542,7 @@ function curl_getinfo($ch, int $opt = null)\n  * @throws CurlException\n  *\n  */\n-function curl_init(string $url = null)\n+function curl_init(?string $url = null)\n {\n     error_clear_last();\n     $result = \\curl_init($url);\ndiff --git a/generated/datetime.php b/generated/datetime.php\nindex 01bfa93..9467652 100644\n--- a/generated/datetime.php\n+++ b/generated/datetime.php\n@@ -233,7 +233,7 @@ function date_sun_info(int $timestamp, float $latitude, float $longitude): array\n  * @throws DatetimeException\n  *\n  */\n-function date_sunrise(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, float $latitude = null, float $longitude = null, float $zenith = null, float $utcOffset = 0)\n+function date_sunrise(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, ?float $latitude = null, ?float $longitude = null, ?float $zenith = null, ?float $utcOffset = 0)\n {\n     error_clear_last();\n     if ($utcOffset !== 0) {\n@@ -336,7 +336,7 @@ function date_sunrise(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, f\n  * @throws DatetimeException\n  *\n  */\n-function date_sunset(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, float $latitude = null, float $longitude = null, float $zenith = null, float $utcOffset = 0)\n+function date_sunset(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, ?float $latitude = null, ?float $longitude = null, ?float $zenith = null, float $utcOffset = 0)\n {\n     error_clear_last();\n     if ($utcOffset !== 0) {\n@@ -374,7 +374,7 @@ function date_sunset(int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING, fl\n  * @throws DatetimeException\n  *\n  */\n-function date(string $format, int $timestamp = null): string\n+function date(string $format, ?int $timestamp = null): string\n {\n     error_clear_last();\n     if ($timestamp !== null) {\n@@ -405,7 +405,7 @@ function date(string $format, int $timestamp = null): string\n  * @throws DatetimeException\n  *\n  */\n-function gmdate(string $format, int $timestamp = null): string\n+function gmdate(string $format, ?int $timestamp = null): string\n {\n     error_clear_last();\n     if ($timestamp !== null) {\n@@ -461,7 +461,7 @@ function gmdate(string $format, int $timestamp = null): string\n  * @throws DatetimeException\n  *\n  */\n-function mktime(int $hour = null, int $minute = null, int $second = null, int $month = null, int $day = null, int $year = null): int\n+function mktime(?int $hour = null, ?int $minute = null, ?int $second = null, ?int $month = null, ?int $day = null, ?int $year = null): int\n {\n     error_clear_last();\n     if ($year !== null) {\n@@ -584,7 +584,7 @@ function strptime(string $date, string $format): array\n  * @throws DatetimeException\n  *\n  */\n-function strtotime(string $datetime, int $now = null): int\n+function strtotime(string $datetime, ?int $now = null): int\n {\n     error_clear_last();\n     if ($now !== null) {\ndiff --git a/generated/eio.php b/generated/eio.php\nindex 8d2f538..2224d52 100644\n--- a/generated/eio.php\n+++ b/generated/eio.php\n@@ -19,7 +19,7 @@ use Safe\\Exceptions\\EioException;\n  * @throws EioException\n  *\n  */\n-function eio_busy(int $delay, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_busy(int $delay, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_busy($delay, $pri, $callback, $data);\n@@ -71,7 +71,7 @@ function eio_busy(int $delay, int $pri = EIO_PRI_DEFAULT, callable $callback = n\n  * @throws EioException\n  *\n  */\n-function eio_chmod(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_chmod(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_chmod($path, $mode, $pri, $callback, $data);\n@@ -123,7 +123,7 @@ function eio_chmod(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, callable\n  * @throws EioException\n  *\n  */\n-function eio_chown(string $path, int $uid, int $gid = -1, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_chown(string $path, int $uid, int $gid = -1, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_chown($path, $uid, $gid, $pri, $callback, $data);\n@@ -172,7 +172,7 @@ function eio_chown(string $path, int $uid, int $gid = -1, int $pri = EIO_PRI_DEF\n  * @throws EioException\n  *\n  */\n-function eio_close($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_close($fd, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_close($fd, $pri, $callback, $data);\n@@ -231,7 +231,7 @@ function eio_close($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $\n  * @throws EioException\n  *\n  */\n-function eio_custom(callable $execute, int $pri, callable $callback, $data = null)\n+function eio_custom(callable $execute, int $pri, ?callable $callback, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_custom($execute, $pri, $callback, $data);\n@@ -280,7 +280,7 @@ function eio_custom(callable $execute, int $pri, callable $callback, $data = nul\n  * @throws EioException\n  *\n  */\n-function eio_dup2($fd, $fd2, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_dup2($fd, $fd2, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_dup2($fd, $fd2, $pri, $callback, $data);\n@@ -352,7 +352,7 @@ function eio_event_loop(): void\n  * @throws EioException\n  *\n  */\n-function eio_fallocate($fd, int $mode, int $offset, int $length, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_fallocate($fd, int $mode, int $offset, int $length, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_fallocate($fd, $mode, $offset, $length, $pri, $callback, $data);\n@@ -402,7 +402,7 @@ function eio_fallocate($fd, int $mode, int $offset, int $length, int $pri = EIO_\n  * @throws EioException\n  *\n  */\n-function eio_fchmod($fd, int $mode, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_fchmod($fd, int $mode, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_fchmod($fd, $mode, $pri, $callback, $data);\n@@ -450,7 +450,7 @@ function eio_fchmod($fd, int $mode, int $pri = EIO_PRI_DEFAULT, callable $callba\n  * @throws EioException\n  *\n  */\n-function eio_fdatasync($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_fdatasync($fd, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_fdatasync($fd, $pri, $callback, $data);\n@@ -604,7 +604,7 @@ function eio_fstatvfs($fd, int $pri, callable $callback, $data = null)\n  * @throws EioException\n  *\n  */\n-function eio_fsync($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_fsync($fd, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_fsync($fd, $pri, $callback, $data);\n@@ -655,7 +655,7 @@ function eio_fsync($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $\n  * @throws EioException\n  *\n  */\n-function eio_ftruncate($fd, int $offset = 0, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_ftruncate($fd, int $offset = 0, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_ftruncate($fd, $offset, $pri, $callback, $data);\n@@ -706,7 +706,7 @@ function eio_ftruncate($fd, int $offset = 0, int $pri = EIO_PRI_DEFAULT, callabl\n  * @throws EioException\n  *\n  */\n-function eio_futime($fd, float $atime, float $mtime, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_futime($fd, float $atime, float $mtime, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_futime($fd, $atime, $mtime, $pri, $callback, $data);\n@@ -750,7 +750,7 @@ function eio_futime($fd, float $atime, float $mtime, int $pri = EIO_PRI_DEFAULT,\n  * @throws EioException\n  *\n  */\n-function eio_grp(callable $callback, string $data = null)\n+function eio_grp(?callable $callback, ?string $data = null)\n {\n     error_clear_last();\n     $result = \\eio_grp($callback, $data);\n@@ -849,7 +849,7 @@ function eio_lstat(string $path, int $pri, callable $callback, $data = null)\n  * @throws EioException\n  *\n  */\n-function eio_mkdir(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_mkdir(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_mkdir($path, $mode, $pri, $callback, $data);\n@@ -914,7 +914,7 @@ function eio_mkdir(string $path, int $mode, int $pri = EIO_PRI_DEFAULT, callable\n  * @throws EioException\n  *\n  */\n-function eio_mknod(string $path, int $mode, int $dev, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_mknod(string $path, int $mode, int $dev, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_mknod($path, $mode, $dev, $pri, $callback, $data);\n@@ -962,7 +962,7 @@ function eio_mknod(string $path, int $mode, int $dev, int $pri = EIO_PRI_DEFAULT\n  * @throws EioException\n  *\n  */\n-function eio_nop(int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_nop(int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_nop($pri, $callback, $data);\n@@ -1013,7 +1013,7 @@ function eio_nop(int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data =\n  * @throws EioException\n  *\n  */\n-function eio_readahead($fd, int $offset, int $length, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_readahead($fd, int $offset, int $length, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_readahead($fd, $offset, $length, $pri, $callback, $data);\n@@ -1316,7 +1316,7 @@ function eio_readahead($fd, int $offset, int $length, int $pri = EIO_PRI_DEFAULT\n  * @throws EioException\n  *\n  */\n-function eio_readdir(string $path, int $flags, int $pri, callable $callback, string $data = null)\n+function eio_readdir(string $path, int $flags, int $pri, callable $callback, ?string $data = null)\n {\n     error_clear_last();\n     $result = \\eio_readdir($path, $flags, $pri, $callback, $data);\n@@ -1364,7 +1364,7 @@ function eio_readdir(string $path, int $flags, int $pri, callable $callback, str\n  * @throws EioException\n  *\n  */\n-function eio_readlink(string $path, int $pri, callable $callback, string $data = null)\n+function eio_readlink(string $path, int $pri, callable $callback, ?string $data = null)\n {\n     error_clear_last();\n     $result = \\eio_readlink($path, $pri, $callback, $data);\n@@ -1413,7 +1413,7 @@ function eio_readlink(string $path, int $pri, callable $callback, string $data =\n  * @throws EioException\n  *\n  */\n-function eio_rename(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_rename(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_rename($path, $new_path, $pri, $callback, $data);\n@@ -1461,7 +1461,7 @@ function eio_rename(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT,\n  * @throws EioException\n  *\n  */\n-function eio_rmdir(string $path, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_rmdir(string $path, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_rmdir($path, $pri, $callback, $data);\n@@ -1517,7 +1517,7 @@ function eio_rmdir(string $path, int $pri = EIO_PRI_DEFAULT, callable $callback\n  * @throws EioException\n  *\n  */\n-function eio_seek($fd, int $offset, int $whence, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_seek($fd, int $offset, int $whence, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_seek($fd, $offset, $whence, $pri, $callback, $data);\n@@ -1569,7 +1569,7 @@ function eio_seek($fd, int $offset, int $whence, int $pri = EIO_PRI_DEFAULT, cal\n  * @throws EioException\n  *\n  */\n-function eio_sendfile($out_fd, $in_fd, int $offset, int $length, int $pri = null, callable $callback = null, string $data = null)\n+function eio_sendfile($out_fd, $in_fd, int $offset, int $length, ?int $pri = null, ?callable $callback = null, ?string $data = null)\n {\n     error_clear_last();\n     if ($data !== null) {\n@@ -1731,7 +1731,7 @@ function eio_statvfs(string $path, int $pri, callable $callback, $data = null)\n  * @throws EioException\n  *\n  */\n-function eio_symlink(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_symlink(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_symlink($path, $new_path, $pri, $callback, $data);\n@@ -1790,7 +1790,7 @@ function eio_symlink(string $path, string $new_path, int $pri = EIO_PRI_DEFAULT,\n  * @throws EioException\n  *\n  */\n-function eio_sync_file_range($fd, int $offset, int $nbytes, int $flags, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_sync_file_range($fd, int $offset, int $nbytes, int $flags, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_sync_file_range($fd, $offset, $nbytes, $flags, $pri, $callback, $data);\n@@ -1811,7 +1811,7 @@ function eio_sync_file_range($fd, int $offset, int $nbytes, int $flags, int $pri\n  * @throws EioException\n  *\n  */\n-function eio_sync(int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_sync(int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_sync($pri, $callback, $data);\n@@ -1859,7 +1859,7 @@ function eio_sync(int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data =\n  * @throws EioException\n  *\n  */\n-function eio_syncfs($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_syncfs($fd, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_syncfs($fd, $pri, $callback, $data);\n@@ -1909,7 +1909,7 @@ function eio_syncfs($fd, int $pri = EIO_PRI_DEFAULT, callable $callback = null,\n  * @throws EioException\n  *\n  */\n-function eio_truncate(string $path, int $offset = 0, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_truncate(string $path, int $offset = 0, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_truncate($path, $offset, $pri, $callback, $data);\n@@ -1957,7 +1957,7 @@ function eio_truncate(string $path, int $offset = 0, int $pri = EIO_PRI_DEFAULT,\n  * @throws EioException\n  *\n  */\n-function eio_unlink(string $path, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_unlink(string $path, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_unlink($path, $pri, $callback, $data);\n@@ -2007,7 +2007,7 @@ function eio_unlink(string $path, int $pri = EIO_PRI_DEFAULT, callable $callback\n  * @throws EioException\n  *\n  */\n-function eio_utime(string $path, float $atime, float $mtime, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_utime(string $path, float $atime, float $mtime, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_utime($path, $atime, $mtime, $pri, $callback, $data);\n@@ -2060,7 +2060,7 @@ function eio_utime(string $path, float $atime, float $mtime, int $pri = EIO_PRI_\n  * @throws EioException\n  *\n  */\n-function eio_write($fd, string $str, int $length = 0, int $offset = 0, int $pri = EIO_PRI_DEFAULT, callable $callback = null, $data = null)\n+function eio_write($fd, string $str, int $length = 0, int $offset = 0, int $pri = EIO_PRI_DEFAULT, ?callable $callback = null, $data = null)\n {\n     error_clear_last();\n     $result = \\eio_write($fd, $str, $length, $offset, $pri, $callback, $data);\ndiff --git a/generated/errorfunc.php b/generated/errorfunc.php\nindex ac64a7d..c5ff97a 100644\n--- a/generated/errorfunc.php\n+++ b/generated/errorfunc.php\n@@ -66,7 +66,7 @@ use Safe\\Exceptions\\ErrorfuncException;\n  * @throws ErrorfuncException\n  *\n  */\n-function error_log(string $message, int $message_type = 0, string $destination = null, string $extra_headers = null): void\n+function error_log(string $message, int $message_type = 0, ?string $destination = null, ?string $extra_headers = null): void\n {\n     error_clear_last();\n     if ($extra_headers !== null) {\ndiff --git a/generated/exec.php b/generated/exec.php\nindex e9a40e0..00699de 100644\n--- a/generated/exec.php\n+++ b/generated/exec.php\n@@ -148,7 +148,7 @@ function proc_nice(int $increment): void\n  * @throws ExecException\n  *\n  */\n-function system(string $command, int &$return_var = null): string\n+function system(string $command, ?int &$return_var = null): string\n {\n     error_clear_last();\n     $result = \\system($command, $return_var);\ndiff --git a/generated/filesystem.php b/generated/filesystem.php\nindex ee0a4bd..20ed535 100644\n--- a/generated/filesystem.php\n+++ b/generated/filesystem.php\n@@ -237,7 +237,7 @@ function fflush($handle): void\n  * @throws FilesystemException\n  *\n  */\n-function file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, int $maxlen = null): string\n+function file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, ?int $maxlen = null): string\n {\n     error_clear_last();\n     if ($maxlen !== null) {\n@@ -922,7 +922,7 @@ function ftruncate($handle, int $size): void\n  * @throws FilesystemException\n  *\n  */\n-function fwrite($handle, string $string, int $length = null): int\n+function fwrite($handle, string $string, ?int $length = null): int\n {\n     error_clear_last();\n     if ($length !== null) {\n@@ -1448,7 +1448,7 @@ function tmpfile()\n  * @throws FilesystemException\n  *\n  */\n-function touch(string $filename, int $time = null, int $atime = null): void\n+function touch(string $filename, ?int $time = null, ?int $atime = null): void\n {\n     error_clear_last();\n     if ($atime !== null) {\ndiff --git a/generated/ftp.php b/generated/ftp.php\nindex 1748826..1f63c6e 100644\n--- a/generated/ftp.php\n+++ b/generated/ftp.php\n@@ -15,7 +15,7 @@ use Safe\\Exceptions\\FtpException;\n  * @throws FtpException\n  *\n  */\n-function ftp_alloc($ftp_stream, int $filesize, string &$result = null): void\n+function ftp_alloc($ftp_stream, int $filesize, ?string &$result = null): void\n {\n     error_clear_last();\n     $result = \\ftp_alloc($ftp_stream, $filesize, $result);\ndiff --git a/generated/gnupg.php b/generated/gnupg.php\nindex b5d85ca..84c8968 100644\n--- a/generated/gnupg.php\n+++ b/generated/gnupg.php\n@@ -53,7 +53,7 @@ function gnupg_addencryptkey($identifier, string $fingerprint): void\n  * @throws GnupgException\n  *\n  */\n-function gnupg_addsignkey($identifier, string $fingerprint, string $passphrase = null): void\n+function gnupg_addsignkey($identifier, string $fingerprint, ?string $passphrase = null): void\n {\n     error_clear_last();\n     if ($passphrase !== null) {\ndiff --git a/generated/ibase.php b/generated/ibase.php\nindex 4969740..db14f1d 100644\n--- a/generated/ibase.php\n+++ b/generated/ibase.php\n@@ -34,7 +34,7 @@ function fbird_blob_cancel($blob_handle): void\n  * @throws IbaseException\n  *\n  */\n-function ibase_add_user($service_handle, string $user_name, string $password, string $first_name = null, string $middle_name = null, string $last_name = null): void\n+function ibase_add_user($service_handle, string $user_name, string $password, ?string $first_name = null, ?string $middle_name = null, ?string $last_name = null): void\n {\n     error_clear_last();\n     if ($last_name !== null) {\n@@ -250,7 +250,7 @@ function ibase_commit($link_or_trans_identifier = null): void\n  * @throws IbaseException\n  *\n  */\n-function ibase_connect(string $database = null, string $username = null, string $password = null, string $charset = null, int $buffers = null, int $dialect = null, string $role = null, int $sync = null)\n+function ibase_connect (?string $database = null, ?string $username = null, ?string $password = null, ?string $charset = null, ?int $buffers = null, ?int $dialect = null, ?string $role = null, ?int $sync = null)\n {\n     error_clear_last();\n     if ($sync !== null) {\n@@ -403,7 +403,7 @@ function ibase_maintain_db($service_handle, string $db, int $action, int $argume\n  * @throws IbaseException\n  *\n  */\n-function ibase_modify_user($service_handle, string $user_name, string $password, string $first_name = null, string $middle_name = null, string $last_name = null): void\n+function ibase_modify_user($service_handle, string $user_name, string $password, ?string $first_name = null, ?string $middle_name = null, ?string $last_name = null): void\n {\n     error_clear_last();\n     if ($last_name !== null) {\n@@ -480,7 +480,7 @@ function ibase_name_result($result, string $name): void\n  * @throws IbaseException\n  *\n  */\n-function ibase_pconnect(string $database = null, string $username = null, string $password = null, string $charset = null, int $buffers = null, int $dialect = null, string $role = null, int $sync = null)\n+function ibase_pconnect (?string $database = null, ?string $username = null, ?string $password = null, ?string $charset = null, ?int $buffers = null, ?int $dialect = null, ?string $role = null, ?int $sync = null)\n {\n     error_clear_last();\n     if ($sync !== null) {\ndiff --git a/generated/ibmDb2.php b/generated/ibmDb2.php\nindex f97e7b0..7336f9d 100644\n--- a/generated/ibmDb2.php\n+++ b/generated/ibmDb2.php\n@@ -46,7 +46,7 @@ use Safe\\Exceptions\\IbmDb2Exception;\n  * @throws IbmDb2Exception\n  *\n  */\n-function db2_autocommit($connection, int $value = null)\n+function db2_autocommit($connection, ?int $value = null)\n {\n     error_clear_last();\n     if ($value !== null) {\n@@ -96,7 +96,7 @@ function db2_autocommit($connection, int $value = null)\n  * @throws IbmDb2Exception\n  *\n  */\n-function db2_bind_param($stmt, int $parameter_number, string $variable_name, int $parameter_type = null, int $data_type = 0, int $precision = -1, int $scale = 0): void\n+function db2_bind_param($stmt, int $parameter_number, string $variable_name, ?int $parameter_type = null, int $data_type = 0, int $precision = -1, int $scale = 0): void\n {\n     error_clear_last();\n     if ($scale !== 0) {\n@@ -304,7 +304,7 @@ function db2_commit($connection): void\n  * @throws IbmDb2Exception\n  *\n  */\n-function db2_execute($stmt, array $parameters = null): void\n+function db2_execute($stmt, ?array $parameters = null): void\n {\n     error_clear_last();\n     if ($parameters !== null) {\ndiff --git a/generated/image.php b/generated/image.php\nindex f1dc218..0729365 100644\n--- a/generated/image.php\n+++ b/generated/image.php\n@@ -66,7 +66,7 @@ use Safe\\Exceptions\\ImageException;\n  * @throws ImageException\n  *\n  */\n-function getimagesize(string $filename, array &$imageinfo = null): array\n+function getimagesize(string $filename, ?array &$imageinfo = null): array\n {\n     error_clear_last();\n     $result = \\getimagesize($filename, $imageinfo);\n@@ -91,7 +91,7 @@ function getimagesize(string $filename, array &$imageinfo = null): array\n  * @throws ImageException\n  *\n  */\n-function image2wbmp($image, ?string $filename = null, int $foreground = null): void\n+function image2wbmp($image, ?string $filename = null, ?int $foreground = null): void\n {\n     error_clear_last();\n     if ($foreground !== null) {\n@@ -118,7 +118,7 @@ function image2wbmp($image, ?string $filename = null, int $foreground = null): v\n  * @throws ImageException\n  *\n  */\n-function imageaffine($image, array $affine, array $clip = null)\n+function imageaffine($image, array $affine, ?array $clip = null)\n {\n     error_clear_last();\n     if ($clip !== null) {\n@@ -1367,7 +1367,7 @@ function imagefilltoborder($image, int $x, int $y, int $border, int $color): voi\n  * @throws ImageException\n  *\n  */\n-function imagefilter($image, int $filtertype, int $arg1 = null, int $arg2 = null, int $arg3 = null, int $arg4 = null): void\n+function imagefilter($image, int $filtertype, ?int $arg1 = null, ?int $arg2 = null, ?int $arg3 = null, ?int $arg4 = null): void\n {\n     error_clear_last();\n     if ($arg4 !== null) {\n@@ -2551,7 +2551,7 @@ function imagettftext($image, float $size, float $angle, int $x, int $y, int $co\n  * @throws ImageException\n  *\n  */\n-function imagewbmp($image, $to = null, int $foreground = null): void\n+function imagewbmp($image, $to = null, ?int $foreground = null): void\n {\n     error_clear_last();\n     if ($foreground !== null) {\n@@ -2606,7 +2606,7 @@ function imagewebp($image, $to = null, int $quality = 80): void\n  * @throws ImageException\n  *\n  */\n-function imagexbm($image, ?string $filename, int $foreground = null): void\n+function imagexbm($image, ?string $filename, ?int $foreground = null): void\n {\n     error_clear_last();\n     if ($foreground !== null) {\ndiff --git a/generated/imap.php b/generated/imap.php\nindex acd8672..3611898 100644\n--- a/generated/imap.php\n+++ b/generated/imap.php\n@@ -22,7 +22,7 @@ use Safe\\Exceptions\\ImapException;\n  * @throws ImapException\n  *\n  */\n-function imap_append($imap_stream, string $mailbox, string $message, string $options = null, string $internal_date = null): void\n+function imap_append($imap_stream, string $mailbox, string $message, ?string $options = null, ?string $internal_date = null): void\n {\n     error_clear_last();\n     $result = \\imap_append($imap_stream, $mailbox, $message, $options, $internal_date);\n@@ -567,7 +567,7 @@ function imap_gc($imap_stream, int $caches): void\n  * @throws ImapException\n  *\n  */\n-function imap_headerinfo($imap_stream, int $msg_number, int $fromlength = 0, int $subjectlength = 0, string $defaulthost = null): \\stdClass\n+function imap_headerinfo($imap_stream, int $msg_number, int $fromlength = 0, int $subjectlength = 0, ?string $defaulthost = null): \\stdClass\n {\n     error_clear_last();\n     $result = \\imap_headerinfo($imap_stream, $msg_number, $fromlength, $subjectlength, $defaulthost);\n@@ -784,7 +784,7 @@ function imap_mail_move($imap_stream, string $msglist, string $mailbox, int $opt\n  * @throws ImapException\n  *\n  */\n-function imap_mail(string $to, string $subject, string $message, string $additional_headers = null, string $cc = null, string $bcc = null, string $rpath = null): void\n+function imap_mail(string $to, string $subject, string $message, ?string $additional_headers = null, ?string $cc = null, ?string $bcc = null, ?string $rpath = null): void\n {\n     error_clear_last();\n     $result = \\imap_mail($to, $subject, $message, $additional_headers, $cc, $bcc, $rpath);\n@@ -1325,7 +1325,7 @@ function imap_setflag_full($imap_stream, string $sequence, string $flag, int $op\n  * @throws ImapException\n  *\n  */\n-function imap_sort($imap_stream, int $criteria, int $reverse, int $options = 0, string $search_criteria = null, string $charset = null): array\n+function imap_sort($imap_stream, int $criteria, int $reverse, int $options = 0, ?string $search_criteria = null, ?string $charset = null): array\n {\n     error_clear_last();\n     $result = \\imap_sort($imap_stream, $criteria, $reverse, $options, $search_criteria, $charset);\ndiff --git a/generated/info.php b/generated/info.php\nindex 1a76b40..a26fa39 100644\n--- a/generated/info.php\n+++ b/generated/info.php\n@@ -192,7 +192,7 @@ function getmyuid(): int\n  * @throws InfoException\n  *\n  */\n-function getopt(string $options, array $longopts = null, ?int &$optind = null): array\n+function getopt(string $options, ?array $longopts = null, ?int &$optind = null): array\n {\n     error_clear_last();\n     if ($optind !== null) {\ndiff --git a/generated/ingres-ii.php b/generated/ingres-ii.php\nindex 9ea8b5f..414433f 100644\n--- a/generated/ingres-ii.php\n+++ b/generated/ingres-ii.php\n@@ -332,7 +332,7 @@ function ingres_commit($link): void\n  * @throws IngresiiException\n  *\n  */\n-function ingres_connect(string $database = null, string $username = null, string $password = null, array $options = null)\n+function ingres_connect (?string $database = null, ?string $username = null, ?string $password = null, ?array $options = null)\n {\n     error_clear_last();\n     if ($options !== null) {\n@@ -364,7 +364,7 @@ function ingres_connect(string $database = null, string $username = null, string\n  * @throws IngresiiException\n  *\n  */\n-function ingres_execute($result, array $params = null, string $types = null): void\n+function ingres_execute($result, ?array $params = null, ?string $types = null): void\n {\n     error_clear_last();\n     if ($types !== null) {\n@@ -503,7 +503,7 @@ function ingres_free_result($result): void\n  * @throws IngresiiException\n  *\n  */\n-function ingres_pconnect(string $database = null, string $username = null, string $password = null, array $options = null)\n+function ingres_pconnect (?string $database = null, ?string $username = null, ?string $password = null, ?array $options = null)\n {\n     error_clear_last();\n     if ($options !== null) {\ndiff --git a/generated/ldap.php b/generated/ldap.php\nindex 871f295..2136e42 100644\n--- a/generated/ldap.php\n+++ b/generated/ldap.php\n@@ -15,7 +15,7 @@ use Safe\\Exceptions\\LdapException;\n  * @throws LdapException\n  *\n  */\n-function ldap_add_ext($link_identifier, string $dn, array $entry, array $serverctrls = null)\n+function ldap_add_ext($link_identifier, string $dn, array $entry, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_add_ext($link_identifier, $dn, $entry, $serverctrls);\n@@ -45,7 +45,7 @@ function ldap_add_ext($link_identifier, string $dn, array $entry, array $serverc\n  * @throws LdapException\n  *\n  */\n-function ldap_add($link_identifier, string $dn, array $entry, array $serverctrls = null): void\n+function ldap_add($link_identifier, string $dn, array $entry, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_add($link_identifier, $dn, $entry, $serverctrls);\n@@ -66,7 +66,7 @@ function ldap_add($link_identifier, string $dn, array $entry, array $serverctrls\n  * @throws LdapException\n  *\n  */\n-function ldap_bind_ext($link_identifier, ?string $bind_rdn = null, ?string $bind_password = null, array $serverctrls = null)\n+function ldap_bind_ext($link_identifier, ?string $bind_rdn = null, ?string $bind_password = null, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_bind_ext($link_identifier, $bind_rdn, $bind_password, $serverctrls);\n@@ -170,7 +170,7 @@ function ldap_count_entries($link_identifier, $result_identifier): int\n  * @throws LdapException\n  *\n  */\n-function ldap_delete_ext($link_identifier, string $dn, array $serverctrls = null)\n+function ldap_delete_ext($link_identifier, string $dn, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_delete_ext($link_identifier, $dn, $serverctrls);\n@@ -190,7 +190,7 @@ function ldap_delete_ext($link_identifier, string $dn, array $serverctrls = null\n  * @throws LdapException\n  *\n  */\n-function ldap_delete($link_identifier, string $dn, array $serverctrls = null): void\n+function ldap_delete($link_identifier, string $dn, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_delete($link_identifier, $dn, $serverctrls);\n@@ -215,7 +215,7 @@ function ldap_delete($link_identifier, string $dn, array $serverctrls = null): v\n  * @throws LdapException\n  *\n  */\n-function ldap_exop_passwd($link, string $user = \"\", string $oldpw = \"\", string $newpw = \"\", array &$serverctrls = null)\n+function ldap_exop_passwd($link, string $user = \"\", string $oldpw = \"\", string $newpw = \"\", ?array &$serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_exop_passwd($link, $user, $oldpw, $newpw, $serverctrls);\n@@ -263,7 +263,7 @@ function ldap_exop_whoami($link): string\n  * @throws LdapException\n  *\n  */\n-function ldap_exop($link, string $reqoid, string $reqdata = null, ?array $serverctrls = null, ?string &$retdata = null, ?string &$retoid = null)\n+function ldap_exop($link, string $reqoid, ?string $reqdata = null, ?array $serverctrls = null, ?string &$retdata = null, ?string &$retoid = null)\n {\n     error_clear_last();\n     $result = \\ldap_exop($link, $reqoid, $reqdata, $serverctrls, $retdata, $retoid);\n@@ -798,7 +798,7 @@ function ldap_get_values($link_identifier, $result_entry_identifier, string $att\n  * @throws LdapException\n  *\n  */\n-function ldap_list($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null)\n+function ldap_list($link_identifier, string $base_dn, string $filter, ?array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, ?array $serverctrls = null)\n {\n     error_clear_last();\n     if ($serverctrls !== null) {\n@@ -834,7 +834,7 @@ function ldap_list($link_identifier, string $base_dn, string $filter, array $att\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_add_ext($link_identifier, string $dn, array $entry, array $serverctrls = null)\n+function ldap_mod_add_ext($link_identifier, string $dn, array $entry, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_mod_add_ext($link_identifier, $dn, $entry, $serverctrls);\n@@ -856,7 +856,7 @@ function ldap_mod_add_ext($link_identifier, string $dn, array $entry, array $ser\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_add($link_identifier, string $dn, array $entry, array $serverctrls = null): void\n+function ldap_mod_add($link_identifier, string $dn, array $entry, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_mod_add($link_identifier, $dn, $entry, $serverctrls);\n@@ -877,7 +877,7 @@ function ldap_mod_add($link_identifier, string $dn, array $entry, array $serverc\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_del_ext($link_identifier, string $dn, array $entry, array $serverctrls = null)\n+function ldap_mod_del_ext($link_identifier, string $dn, array $entry, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_mod_del_ext($link_identifier, $dn, $entry, $serverctrls);\n@@ -900,7 +900,7 @@ function ldap_mod_del_ext($link_identifier, string $dn, array $entry, array $ser\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_del($link_identifier, string $dn, array $entry, array $serverctrls = null): void\n+function ldap_mod_del($link_identifier, string $dn, array $entry, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_mod_del($link_identifier, $dn, $entry, $serverctrls);\n@@ -921,7 +921,7 @@ function ldap_mod_del($link_identifier, string $dn, array $entry, array $serverc\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_replace_ext($link_identifier, string $dn, array $entry, array $serverctrls = null)\n+function ldap_mod_replace_ext($link_identifier, string $dn, array $entry, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_mod_replace_ext($link_identifier, $dn, $entry, $serverctrls);\n@@ -943,7 +943,7 @@ function ldap_mod_replace_ext($link_identifier, string $dn, array $entry, array\n  * @throws LdapException\n  *\n  */\n-function ldap_mod_replace($link_identifier, string $dn, array $entry, array $serverctrls = null): void\n+function ldap_mod_replace($link_identifier, string $dn, array $entry, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_mod_replace($link_identifier, $dn, $entry, $serverctrls);\n@@ -1038,7 +1038,7 @@ function ldap_mod_replace($link_identifier, string $dn, array $entry, array $ser\n  * @throws LdapException\n  *\n  */\n-function ldap_modify_batch($link_identifier, string $dn, array $entry, array $serverctrls = null): void\n+function ldap_modify_batch($link_identifier, string $dn, array $entry, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_modify_batch($link_identifier, $dn, $entry, $serverctrls);\n@@ -1193,7 +1193,7 @@ function ldap_parse_result($link, $result, ?int &$errcode, ?string &$matcheddn =\n  * @throws LdapException\n  *\n  */\n-function ldap_read($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null)\n+function ldap_read($link_identifier, string $base_dn, string $filter, ?array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, ?array $serverctrls = null)\n {\n     error_clear_last();\n     if ($serverctrls !== null) {\n@@ -1231,7 +1231,7 @@ function ldap_read($link_identifier, string $base_dn, string $filter, array $att\n  * @throws LdapException\n  *\n  */\n-function ldap_rename_ext($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, array $serverctrls = null)\n+function ldap_rename_ext($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, ?array $serverctrls = null)\n {\n     error_clear_last();\n     $result = \\ldap_rename_ext($link_identifier, $dn, $newrdn, $newparent, $deleteoldrdn, $serverctrls);\n@@ -1255,7 +1255,7 @@ function ldap_rename_ext($link_identifier, string $dn, string $newrdn, string $n\n  * @throws LdapException\n  *\n  */\n-function ldap_rename($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, array $serverctrls = null): void\n+function ldap_rename($link_identifier, string $dn, string $newrdn, string $newparent, bool $deleteoldrdn, ?array $serverctrls = null): void\n {\n     error_clear_last();\n     $result = \\ldap_rename($link_identifier, $dn, $newrdn, $newparent, $deleteoldrdn, $serverctrls);\n@@ -1279,7 +1279,7 @@ function ldap_rename($link_identifier, string $dn, string $newrdn, string $newpa\n  * @throws LdapException\n  *\n  */\n-function ldap_sasl_bind($link, string $binddn = null, string $password = null, string $sasl_mech = null, string $sasl_realm = null, string $sasl_authc_id = null, string $sasl_authz_id = null, string $props = null): void\n+function ldap_sasl_bind($link, ?string $binddn = null, ?string $password = null, ?string $sasl_mech = null, ?string $sasl_realm = null, ?string $sasl_authc_id = null, ?string $sasl_authz_id = null, ?string $props = null): void\n {\n     error_clear_last();\n     $result = \\ldap_sasl_bind($link, $binddn, $password, $sasl_mech, $sasl_realm, $sasl_authc_id, $sasl_authz_id, $props);\n@@ -1375,7 +1375,7 @@ function ldap_sasl_bind($link, string $binddn = null, string $password = null, s\n  * @throws LdapException\n  *\n  */\n-function ldap_search($link_identifier, string $base_dn, string $filter, array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $serverctrls = null)\n+function ldap_search($link_identifier, string $base_dn, string $filter, ?array $attributes = null, int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, ?array $serverctrls = null)\n {\n     error_clear_last();\n     if ($serverctrls !== null) {\ndiff --git a/generated/mailparse.php b/generated/mailparse.php\nindex 1bae182..35242df 100644\n--- a/generated/mailparse.php\n+++ b/generated/mailparse.php\n@@ -26,7 +26,7 @@ use Safe\\Exceptions\\MailparseException;\n  * @throws MailparseException\n  *\n  */\n-function mailparse_msg_extract_part_file($mimemail, $filename, callable $callbackfunc = null): string\n+function mailparse_msg_extract_part_file($mimemail, $filename, ?callable $callbackfunc = null): string\n {\n     error_clear_last();\n     if ($callbackfunc !== null) {\ndiff --git a/generated/mbstring.php b/generated/mbstring.php\nindex fa08294..b9d22c1 100644\n--- a/generated/mbstring.php\n+++ b/generated/mbstring.php\n@@ -13,7 +13,7 @@ use Safe\\Exceptions\\MbstringException;\n  * @throws MbstringException\n  *\n  */\n-function mb_chr(int $cp, string $encoding = null): string\n+function mb_chr(int $cp, ?string $encoding = null): string\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -190,7 +190,7 @@ function mb_ereg_search_getregs(): array\n  * @throws MbstringException\n  *\n  */\n-function mb_ereg_search_init(string $string, string $pattern = null, string $option = \"msr\"): void\n+function mb_ereg_search_init(string $string, ?string $pattern = null, string $option = \"msr\"): void\n {\n     error_clear_last();\n     if ($option !== \"msr\") {\n@@ -215,7 +215,7 @@ function mb_ereg_search_init(string $string, string $pattern = null, string $opt\n  * @throws MbstringException\n  *\n  */\n-function mb_ereg_search_regs(string $pattern = null, string $option = \"ms\"): array\n+function mb_ereg_search_regs (?string $pattern = null, string $option = \"ms\"): array\n {\n     error_clear_last();\n     if ($option !== \"ms\") {\n@@ -289,7 +289,7 @@ function mb_eregi_replace(string $pattern, string $replace, string $string, stri\n  * @throws MbstringException\n  *\n  */\n-function mb_http_output(string $encoding = null)\n+function mb_http_output (?string $encoding = null)\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -320,7 +320,7 @@ function mb_http_output(string $encoding = null)\n  * @throws MbstringException\n  *\n  */\n-function mb_internal_encoding(string $encoding = null)\n+function mb_internal_encoding (?string $encoding = null)\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -344,7 +344,7 @@ function mb_internal_encoding(string $encoding = null)\n  * @throws MbstringException\n  *\n  */\n-function mb_ord(string $str, string $encoding = null): int\n+function mb_ord(string $str, ?string $encoding = null): int\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -392,7 +392,7 @@ function mb_parse_str(string $encoded_string, ?array &$result): void\n  * @throws MbstringException\n  *\n  */\n-function mb_regex_encoding(string $encoding = null)\n+function mb_regex_encoding (?string $encoding = null)\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -464,7 +464,7 @@ function mb_regex_encoding(string $encoding = null)\n  * @throws MbstringException\n  *\n  */\n-function mb_send_mail(string $to, string $subject, string $message, $additional_headers = null, string $additional_parameter = null): void\n+function mb_send_mail(string $to, string $subject, string $message, $additional_headers = null, ?string $additional_parameter = null): void\n {\n     error_clear_last();\n     $result = \\mb_send_mail($to, $subject, $message, $additional_headers, $additional_parameter);\n@@ -511,7 +511,7 @@ function mb_split(string $pattern, string $string, int $limit = -1): array\n  * @throws MbstringException\n  *\n  */\n-function mb_str_split(string $string, int $split_length = 1, string $encoding = null): array\n+function mb_str_split(string $string, int $split_length = 1, ?string $encoding = null): array\n {\n     error_clear_last();\n     if ($encoding !== null) {\ndiff --git a/generated/misc.php b/generated/misc.php\nindex ff636fd..a59d974 100644\n--- a/generated/misc.php\n+++ b/generated/misc.php\n@@ -339,7 +339,7 @@ function sapi_windows_generate_ctrl_event(int $event, int $pid = 0): void\n  * @throws MiscException\n  *\n  */\n-function sapi_windows_vt100_support($stream, bool $enable = null): void\n+function sapi_windows_vt100_support($stream, ?bool $enable = null): void\n {\n     error_clear_last();\n     if ($enable !== null) {\ndiff --git a/generated/msql.php b/generated/msql.php\nindex 331c1b6..c380047 100644\n--- a/generated/msql.php\n+++ b/generated/msql.php\n@@ -81,7 +81,7 @@ function msql_close($link_identifier = null): void\n  * @throws MsqlException\n  *\n  */\n-function msql_connect(string $hostname = null)\n+function msql_connect (?string $hostname = null)\n {\n     error_clear_last();\n     if ($hostname !== null) {\n@@ -369,7 +369,7 @@ function msql_free_result($result): void\n  * @throws MsqlException\n  *\n  */\n-function msql_pconnect(string $hostname = null)\n+function msql_pconnect (?string $hostname = null)\n {\n     error_clear_last();\n     if ($hostname !== null) {\ndiff --git a/generated/mysql.php b/generated/mysql.php\nindex 475c609..6c5880f 100644\n--- a/generated/mysql.php\n+++ b/generated/mysql.php\n@@ -73,7 +73,7 @@ function mysql_close($link_identifier = null): void\n  * @throws MysqlException\n  *\n  */\n-function mysql_connect(string $server = null, string $username = null, string $password = null, bool $new_link = false, int $client_flags = 0)\n+function mysql_connect (?string $server = null, ?string $username = null, ?string $password = null, bool $new_link = false, int $client_flags = 0)\n {\n     error_clear_last();\n     if ($client_flags !== 0) {\ndiff --git a/generated/network.php b/generated/network.php\nindex 6d46b6c..5550340 100644\n--- a/generated/network.php\n+++ b/generated/network.php\n@@ -304,7 +304,7 @@ function dns_get_record(string $hostname, int $type = DNS_ANY, ?array &$authns =\n  * @throws NetworkException\n  *\n  */\n-function fsockopen(string $hostname, int $port = -1, ?int &$errno = null, ?string &$errstr = null, float $timeout = null)\n+function fsockopen(string $hostname, int $port = -1, ?int &$errno = null, ?string &$errstr = null, ?float $timeout = null)\n {\n     error_clear_last();\n     if ($timeout !== null) {\ndiff --git a/generated/oci8.php b/generated/oci8.php\nindex f2bac27..305d706 100644\n--- a/generated/oci8.php\n+++ b/generated/oci8.php\n@@ -489,7 +489,7 @@ function oci_commit($connection): void\n  * @throws Oci8Exception\n  *\n  */\n-function oci_connect(string $username, string $password, string $connection_string = null, string $character_set = null, int $session_mode = null)\n+function oci_connect(string $username, string $password, ?string $connection_string = null, ?string $character_set = null, ?int $session_mode = null)\n {\n     error_clear_last();\n     if ($session_mode !== null) {\n@@ -912,7 +912,7 @@ function oci_free_statement($statement): void\n  * @throws Oci8Exception\n  *\n  */\n-function oci_new_collection($connection, string $tdo, string $schema = null)\n+function oci_new_collection($connection, string $tdo, ?string $schema = null)\n {\n     error_clear_last();\n     $result = \\oci_new_collection($connection, $tdo, $schema);\n@@ -1011,7 +1011,7 @@ function oci_new_collection($connection, string $tdo, string $schema = null)\n  * @throws Oci8Exception\n  *\n  */\n-function oci_new_connect(string $username, string $password, string $connection_string = null, string $character_set = null, int $session_mode = null)\n+function oci_new_connect(string $username, string $password, ?string $connection_string = null, ?string $character_set = null, ?int $session_mode = null)\n {\n     error_clear_last();\n     if ($session_mode !== null) {\n@@ -1232,7 +1232,7 @@ function oci_parse($connection, string $sql_text)\n  * @throws Oci8Exception\n  *\n  */\n-function oci_pconnect(string $username, string $password, string $connection_string = null, string $character_set = null, int $session_mode = null)\n+function oci_pconnect(string $username, string $password, ?string $connection_string = null, ?string $character_set = null, ?int $session_mode = null)\n {\n     error_clear_last();\n     if ($session_mode !== null) {\ndiff --git a/generated/openssl.php b/generated/openssl.php\nindex 117b53d..4dddb03 100644\n--- a/generated/openssl.php\n+++ b/generated/openssl.php\n@@ -209,7 +209,7 @@ function openssl_csr_get_subject($csr, bool $use_shortnames = true): array\n  * @throws OpensslException\n  *\n  */\n-function openssl_csr_new(array $dn, &$privkey, array $configargs = null, array $extraattribs = null)\n+function openssl_csr_new(array $dn, &$privkey, ?array $configargs = null, ?array $extraattribs = null)\n {\n     error_clear_last();\n     if ($extraattribs !== null) {\n@@ -250,7 +250,7 @@ function openssl_csr_new(array $dn, &$privkey, array $configargs = null, array $\n  * @throws OpensslException\n  *\n  */\n-function openssl_csr_sign($csr, $cacert, $priv_key, int $days, array $configargs = null, int $serial = 0)\n+function openssl_csr_sign($csr, $cacert, $priv_key, int $days, ?array $configargs = null, int $serial = 0)\n {\n     error_clear_last();\n     if ($serial !== 0) {\n@@ -360,7 +360,7 @@ function openssl_digest(string $data, string $method, bool $raw_output = false):\n  * @throws OpensslException\n  *\n  */\n-function openssl_open(string $sealed_data, ?string &$open_data, string $env_key, $priv_key_id, string $method = \"RC4\", string $iv = null): void\n+function openssl_open(string $sealed_data, ?string &$open_data, string $env_key, $priv_key_id, string $method = \"RC4\", ?string $iv = null): void\n {\n     error_clear_last();\n     if ($iv !== null) {\n@@ -433,7 +433,7 @@ function openssl_pbkdf2(string $password, string $salt, int $key_length, int $it\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkcs12_export_to_file($x509, string $filename, $priv_key, string $pass, array $args = null): void\n+function openssl_pkcs12_export_to_file($x509, string $filename, $priv_key, string $pass, ?array $args = null): void\n {\n     error_clear_last();\n     if ($args !== null) {\n@@ -481,7 +481,7 @@ function openssl_pkcs12_export_to_file($x509, string $filename, $priv_key, strin\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkcs12_export($x509, ?string &$out, $priv_key, string $pass, array $args = null): void\n+function openssl_pkcs12_export($x509, ?string &$out, $priv_key, string $pass, ?array $args = null): void\n {\n     error_clear_last();\n     if ($args !== null) {\n@@ -618,7 +618,7 @@ function openssl_pkcs7_read(string $infilename, ?array &$certs): void\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkcs7_sign(string $infilename, string $outfilename, $signcert, $privkey, array $headers, int $flags = PKCS7_DETACHED, string $extracerts = null): void\n+function openssl_pkcs7_sign(string $infilename, string $outfilename, $signcert, $privkey, array $headers, int $flags = PKCS7_DETACHED, ?string $extracerts = null): void\n {\n     error_clear_last();\n     if ($extracerts !== null) {\n@@ -648,7 +648,7 @@ function openssl_pkcs7_sign(string $infilename, string $outfilename, $signcert,\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkey_export_to_file($key, string $outfilename, string $passphrase = null, array $configargs = null): void\n+function openssl_pkey_export_to_file($key, string $outfilename, ?string $passphrase = null, ?array $configargs = null): void\n {\n     error_clear_last();\n     if ($configargs !== null) {\n@@ -679,7 +679,7 @@ function openssl_pkey_export_to_file($key, string $outfilename, string $passphra\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkey_export($key, ?string &$out, string $passphrase = null, array $configargs = null): void\n+function openssl_pkey_export($key, ?string &$out, ?string $passphrase = null, ?array $configargs = null): void\n {\n     error_clear_last();\n     if ($configargs !== null) {\n@@ -768,7 +768,7 @@ function openssl_pkey_get_public($certificate)\n  * @throws OpensslException\n  *\n  */\n-function openssl_pkey_new(array $configargs = null)\n+function openssl_pkey_new (?array $configargs = null)\n {\n     error_clear_last();\n     if ($configargs !== null) {\n@@ -953,7 +953,7 @@ function openssl_random_pseudo_bytes(int $length, ?bool &$crypto_strong = null):\n  * @throws OpensslException\n  *\n  */\n-function openssl_seal(string $data, ?string &$sealed_data, array &$env_keys, array $pub_key_ids, string $method = \"RC4\", string &$iv = null): int\n+function openssl_seal(string $data, ?string &$sealed_data, array &$env_keys, array $pub_key_ids, string $method = \"RC4\", ?string &$iv = null): int\n {\n     error_clear_last();\n     $result = \\openssl_seal($data, $sealed_data, $env_keys, $pub_key_ids, $method, $iv);\ndiff --git a/generated/password.php b/generated/password.php\nindex 3808e02..d0d1455 100644\n--- a/generated/password.php\n+++ b/generated/password.php\n@@ -111,7 +111,7 @@ use Safe\\Exceptions\\PasswordException;\n  * @throws PasswordException\n  *\n  */\n-function password_hash(string $password, $algo, array $options = null): string\n+function password_hash(string $password, $algo, ?array $options = null): string\n {\n     error_clear_last();\n     if ($options !== null) {\ndiff --git a/generated/pcntl.php b/generated/pcntl.php\nindex 1cb721e..1a182d2 100644\n--- a/generated/pcntl.php\n+++ b/generated/pcntl.php\n@@ -20,7 +20,7 @@ use Safe\\Exceptions\\PcntlException;\n  * @throws PcntlException\n  *\n  */\n-function pcntl_exec(string $path, array $args = null, array $envs = null): void\n+function pcntl_exec(string $path, ?array $args = null, ?array $envs = null): void\n {\n     error_clear_last();\n     if ($envs !== null) {\n@@ -50,7 +50,7 @@ function pcntl_exec(string $path, array $args = null, array $envs = null): void\n  * @throws PcntlException\n  *\n  */\n-function pcntl_getpriority(int $pid = null, int $process_identifier = PRIO_PROCESS): int\n+function pcntl_getpriority (?int $pid = null, int $process_identifier = PRIO_PROCESS): int\n {\n     error_clear_last();\n     if ($process_identifier !== PRIO_PROCESS) {\n@@ -83,7 +83,7 @@ function pcntl_getpriority(int $pid = null, int $process_identifier = PRIO_PROCE\n  * @throws PcntlException\n  *\n  */\n-function pcntl_setpriority(int $priority, int $pid = null, int $process_identifier = PRIO_PROCESS): void\n+function pcntl_setpriority(int $priority, ?int $pid = null, int $process_identifier = PRIO_PROCESS): void\n {\n     error_clear_last();\n     if ($process_identifier !== PRIO_PROCESS) {\ndiff --git a/generated/pcre.php b/generated/pcre.php\nindex c40f14c..baad8cf 100644\n--- a/generated/pcre.php\n+++ b/generated/pcre.php\n@@ -347,7 +347,7 @@ use Safe\\Exceptions\\PcreException;\n  * @throws PcreException\n  *\n  */\n-function preg_match_all(string $pattern, string $subject, array &$matches = null, int $flags = PREG_PATTERN_ORDER, int $offset = 0): int\n+function preg_match_all(string $pattern, string $subject, ?array &$matches = null, int $flags = PREG_PATTERN_ORDER, int $offset = 0): int\n {\n     error_clear_last();\n     $result = \\preg_match_all($pattern, $subject, $matches, $flags, $offset);\n@@ -584,7 +584,7 @@ function preg_match_all(string $pattern, string $subject, array &$matches = null\n  * @throws PcreException\n  *\n  */\n-function preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int\n+function preg_match(string $pattern, string $subject, ?array &$matches = null, int $flags = 0, int $offset = 0): int\n {\n     error_clear_last();\n     $result = \\preg_match($pattern, $subject, $matches, $flags, $offset);\ndiff --git a/generated/pgsql.php b/generated/pgsql.php\nindex 007faac..95bba95 100644\n--- a/generated/pgsql.php\n+++ b/generated/pgsql.php\n@@ -130,7 +130,7 @@ function pg_close($connection = null): void\n  * @throws PgsqlException\n  *\n  */\n-function pg_connect(string $connection_string, int $connect_type = null)\n+function pg_connect(string $connection_string, ?int $connect_type = null)\n {\n     error_clear_last();\n     if ($connect_type !== null) {\n@@ -213,7 +213,7 @@ function pg_convert($connection, string $table_name, array $assoc_array, int $op\n  * @throws PgsqlException\n  *\n  */\n-function pg_copy_from($connection, string $table_name, array $rows, string $delimiter = null, string $null_as = null): void\n+function pg_copy_from($connection, string $table_name, array $rows, ?string $delimiter = null, ?string $null_as = null): void\n {\n     error_clear_last();\n     if ($null_as !== null) {\n@@ -245,7 +245,7 @@ function pg_copy_from($connection, string $table_name, array $rows, string $deli\n  * @throws PgsqlException\n  *\n  */\n-function pg_copy_to($connection, string $table_name, string $delimiter = null, string $null_as = null): array\n+function pg_copy_to($connection, string $table_name, ?string $delimiter = null, ?string $null_as = null): array\n {\n     error_clear_last();\n     if ($null_as !== null) {\n@@ -403,7 +403,7 @@ function pg_end_copy($connection = null): void\n  * @throws PgsqlException\n  *\n  */\n-function pg_execute($connection = null, string $stmtname = null, array $params = null)\n+function pg_execute($connection = null, ?string $stmtname = null, ?array $params = null)\n {\n     error_clear_last();\n     if ($params !== null) {\n@@ -779,7 +779,7 @@ function pg_lo_close($large_object): void\n  * @throws PgsqlException\n  *\n  */\n-function pg_lo_export($connection = null, int $oid = null, string $pathname = null): void\n+function pg_lo_export($connection = null, ?int $oid = null, ?string $pathname = null): void\n {\n     error_clear_last();\n     if ($pathname !== null) {\n@@ -820,7 +820,7 @@ function pg_lo_export($connection = null, int $oid = null, string $pathname = nu\n  * @throws PgsqlException\n  *\n  */\n-function pg_lo_import($connection = null, string $pathname = null, $object_id = null): int\n+function pg_lo_import($connection = null, ?string $pathname = null, $object_id = null): int\n {\n     error_clear_last();\n     if ($object_id !== null) {\n@@ -1009,7 +1009,7 @@ function pg_lo_unlink($connection, int $oid): void\n  * @throws PgsqlException\n  *\n  */\n-function pg_lo_write($large_object, string $data, int $len = null): int\n+function pg_lo_write($large_object, string $data, ?int $len = null): int\n {\n     error_clear_last();\n     if ($len !== null) {\n@@ -1113,7 +1113,7 @@ function pg_options($connection = null): string\n  * @throws PgsqlException\n  *\n  */\n-function pg_parameter_status($connection = null, string $param_name = null): string\n+function pg_parameter_status($connection = null, ?string $param_name = null): string\n {\n     error_clear_last();\n     if ($param_name !== null) {\n@@ -1174,7 +1174,7 @@ function pg_parameter_status($connection = null, string $param_name = null): str\n  * @throws PgsqlException\n  *\n  */\n-function pg_pconnect(string $connection_string, int $connect_type = null)\n+function pg_pconnect(string $connection_string, ?int $connect_type = null)\n {\n     error_clear_last();\n     if ($connect_type !== null) {\n@@ -1278,7 +1278,7 @@ function pg_port($connection = null): int\n  * @throws PgsqlException\n  *\n  */\n-function pg_prepare($connection = null, string $stmtname = null, string $query = null)\n+function pg_prepare($connection = null, ?string $stmtname = null, ?string $query = null)\n {\n     error_clear_last();\n     if ($query !== null) {\n@@ -1319,7 +1319,7 @@ function pg_prepare($connection = null, string $stmtname = null, string $query =\n  * @throws PgsqlException\n  *\n  */\n-function pg_put_line($connection = null, string $data = null): void\n+function pg_put_line($connection = null, ?string $data = null): void\n {\n     error_clear_last();\n     if ($data !== null) {\n@@ -1385,7 +1385,7 @@ function pg_put_line($connection = null, string $data = null): void\n  * @throws PgsqlException\n  *\n  */\n-function pg_query_params($connection = null, string $query = null, array $params = null)\n+function pg_query_params($connection = null, ?string $query = null, ?array $params = null)\n {\n     error_clear_last();\n     if ($params !== null) {\n@@ -1443,7 +1443,7 @@ function pg_query_params($connection = null, string $query = null, array $params\n  * @throws PgsqlException\n  *\n  */\n-function pg_query($connection = null, string $query = null)\n+function pg_query($connection = null, ?string $query = null)\n {\n     error_clear_last();\n     if ($query !== null) {\ndiff --git a/generated/ps.php b/generated/ps.php\nindex a66667a..5224fb1 100644\n--- a/generated/ps.php\n+++ b/generated/ps.php\n@@ -778,7 +778,7 @@ function ps_fill($psdoc): void\n  * @throws PsException\n  *\n  */\n-function ps_get_parameter($psdoc, string $name, float $modifier = null): string\n+function ps_get_parameter($psdoc, string $name, ?float $modifier = null): string\n {\n     error_clear_last();\n     if ($modifier !== null) {\n@@ -925,7 +925,7 @@ function ps_new()\n  * @throws PsException\n  *\n  */\n-function ps_open_file($psdoc, string $filename = null): void\n+function ps_open_file($psdoc, ?string $filename = null): void\n {\n     error_clear_last();\n     if ($filename !== null) {\ndiff --git a/generated/pspell.php b/generated/pspell.php\nindex 4cf4c36..afcff73 100644\n--- a/generated/pspell.php\n+++ b/generated/pspell.php\n@@ -90,7 +90,7 @@ function pspell_clear_session(int $dictionary_link): void\n  * @throws PspellException\n  *\n  */\n-function pspell_config_create(string $language, string $spelling = null, string $jargon = null, string $encoding = null): int\n+function pspell_config_create(string $language, ?string $spelling = null, ?string $jargon = null, ?string $encoding = null): int\n {\n     error_clear_last();\n     if ($encoding !== null) {\n@@ -392,7 +392,7 @@ function pspell_new_config(int $config): int\n  * @throws PspellException\n  *\n  */\n-function pspell_new(string $language, string $spelling = null, string $jargon = null, string $encoding = null, int $mode = 0): int\n+function pspell_new(string $language, ?string $spelling = null, ?string $jargon = null, ?string $encoding = null, int $mode = 0): int\n {\n     error_clear_last();\n     if ($mode !== 0) {\ndiff --git a/generated/readline.php b/generated/readline.php\nindex a1c52c7..b4e4e66 100644\n--- a/generated/readline.php\n+++ b/generated/readline.php\n@@ -122,7 +122,7 @@ function readline_completion_function(callable $function): void\n  * @throws ReadlineException\n  *\n  */\n-function readline_read_history(string $filename = null): void\n+function readline_read_history (?string $filename = null): void\n {\n     error_clear_last();\n     if ($filename !== null) {\n@@ -143,7 +143,7 @@ function readline_read_history(string $filename = null): void\n  * @throws ReadlineException\n  *\n  */\n-function readline_write_history(string $filename = null): void\n+function readline_write_history (?string $filename = null): void\n {\n     error_clear_last();\n     if ($filename !== null) {\ndiff --git a/generated/sodium.php b/generated/sodium.php\nindex 6cb378a..d0ebc6e 100644\n--- a/generated/sodium.php\n+++ b/generated/sodium.php\n@@ -43,7 +43,7 @@ function sodium_crypto_pwhash_str(string $password, int $opslimit, int $memlimit\n  * @throws SodiumException\n  *\n  */\n-function sodium_crypto_pwhash(int $length, string $password, string $salt, int $opslimit, int $memlimit, int $alg = null): string\n+function sodium_crypto_pwhash(int $length, string $password, string $salt, int $opslimit, int $memlimit, ?int $alg = null): string\n {\n     error_clear_last();\n     if ($alg !== null) {\ndiff --git a/generated/spl.php b/generated/spl.php\nindex 679e689..0e0afda 100644\n--- a/generated/spl.php\n+++ b/generated/spl.php\n@@ -99,7 +99,7 @@ function class_uses($class, bool $autoload = true): array\n  * @throws SplException\n  *\n  */\n-function spl_autoload_register(callable $autoload_function = null, bool $throw = true, bool $prepend = false): void\n+function spl_autoload_register (?callable $autoload_function = null, bool $throw = true, bool $prepend = false): void\n {\n     error_clear_last();\n     if ($prepend !== false) {\ndiff --git a/generated/sqlsrv.php b/generated/sqlsrv.php\nindex e93aa37..7dc312b 100644\n--- a/generated/sqlsrv.php\n+++ b/generated/sqlsrv.php\n@@ -251,7 +251,7 @@ function sqlsrv_free_stmt($stmt): void\n  * @throws SqlsrvException\n  *\n  */\n-function sqlsrv_get_field($stmt, int $fieldIndex, int $getAsType = null)\n+function sqlsrv_get_field($stmt, int $fieldIndex, ?int $getAsType = null)\n {\n     error_clear_last();\n     if ($getAsType !== null) {\n@@ -357,7 +357,7 @@ function sqlsrv_num_rows($stmt): int\n  * @throws SqlsrvException\n  *\n  */\n-function sqlsrv_prepare($conn, string $sql, array $params = null, array $options = null)\n+function sqlsrv_prepare($conn, string $sql, ?array $params = null, ?array $options = null)\n {\n     error_clear_last();\n     if ($options !== null) {\n@@ -394,7 +394,7 @@ function sqlsrv_prepare($conn, string $sql, array $params = null, array $options\n  * @throws SqlsrvException\n  *\n  */\n-function sqlsrv_query($conn, string $sql, array $params = null, array $options = null)\n+function sqlsrv_query($conn, string $sql, ?array $params = null, ?array $options = null)\n {\n     error_clear_last();\n     if ($options !== null) {\ndiff --git a/generated/ssh2.php b/generated/ssh2.php\nindex 96af9df..3117cb9 100644\n--- a/generated/ssh2.php\n+++ b/generated/ssh2.php\n@@ -39,7 +39,7 @@ function ssh2_auth_agent($session, string $username): void\n  * @throws Ssh2Exception\n  *\n  */\n-function ssh2_auth_hostbased_file($session, string $username, string $hostname, string $pubkeyfile, string $privkeyfile, string $passphrase = null, string $local_username = null): void\n+function ssh2_auth_hostbased_file($session, string $username, string $hostname, string $pubkeyfile, string $privkeyfile, ?string $passphrase = null, ?string $local_username = null): void\n {\n     error_clear_last();\n     if ($local_username !== null) {\n@@ -91,7 +91,7 @@ function ssh2_auth_password($session, string $username, string $password): void\n  * @throws Ssh2Exception\n  *\n  */\n-function ssh2_auth_pubkey_file($session, string $username, string $pubkeyfile, string $privkeyfile, string $passphrase = null): void\n+function ssh2_auth_pubkey_file($session, string $username, string $pubkeyfile, string $privkeyfile, ?string $passphrase = null): void\n {\n     error_clear_last();\n     if ($passphrase !== null) {\n@@ -304,7 +304,7 @@ function ssh2_auth_pubkey_file($session, string $username, string $pubkeyfile, s\n  * @throws Ssh2Exception\n  *\n  */\n-function ssh2_connect(string $host, int $port = 22, array $methods = null, array $callbacks = null)\n+function ssh2_connect(string $host, int $port = 22, ?array $methods = null, ?array $callbacks = null)\n {\n     error_clear_last();\n     if ($callbacks !== null) {\n@@ -357,7 +357,7 @@ function ssh2_disconnect($session): void\n  * @throws Ssh2Exception\n  *\n  */\n-function ssh2_exec($session, string $command, string $pty = null, array $env = null, int $width = 80, int $height = 25, int $width_height_type = SSH2_TERM_UNIT_CHARS)\n+function ssh2_exec($session, string $command, ?string $pty = null, ?array $env = null, int $width = 80, int $height = 25, int $width_height_type = SSH2_TERM_UNIT_CHARS)\n {\n     error_clear_last();\n     if ($width_height_type !== SSH2_TERM_UNIT_CHARS) {\n@@ -395,7 +395,7 @@ function ssh2_exec($session, string $command, string $pty = null, array $env = n\n  * @throws Ssh2Exception\n  *\n  */\n-function ssh2_publickey_add($pkey, string $algoname, string $blob, bool $overwrite = false, array $attributes = null): void\n+function ssh2_publickey_add($pkey, string $algoname, string $blob, bool $overwrite = false, ?array $attributes = null): void\n {\n     error_clear_last();\n     if ($attributes !== null) {\ndiff --git a/generated/stream.php b/generated/stream.php\nindex 573d029..d858ec8 100644\n--- a/generated/stream.php\n+++ b/generated/stream.php\n@@ -83,7 +83,7 @@ function stream_copy_to_stream($source, $dest, int $maxlength = -1, int $offset\n  * @throws StreamException\n  *\n  */\n-function stream_filter_append($stream, string $filtername, int $read_write = null, $params = null)\n+function stream_filter_append($stream, string $filtername, ?int $read_write = null, $params = null)\n {\n     error_clear_last();\n     if ($params !== null) {\n@@ -132,7 +132,7 @@ function stream_filter_append($stream, string $filtername, int $read_write = nul\n  * @throws StreamException\n  *\n  */\n-function stream_filter_prepend($stream, string $filtername, int $read_write = null, $params = null)\n+function stream_filter_prepend($stream, string $filtername, ?int $read_write = null, $params = null)\n {\n     error_clear_last();\n     if ($params !== null) {\n@@ -331,7 +331,7 @@ function stream_set_timeout($stream, int $seconds, int $microseconds = 0): void\n  * @throws StreamException\n  *\n  */\n-function stream_socket_accept($server_socket, float $timeout = null, ?string &$peername = null)\n+function stream_socket_accept($server_socket, ?float $timeout = null, ?string &$peername = null)\n {\n     error_clear_last();\n     if ($peername !== null) {\n@@ -397,7 +397,7 @@ function stream_socket_accept($server_socket, float $timeout = null, ?string &$p\n  * @throws StreamException\n  *\n  */\n-function stream_socket_client(string $remote_socket, int &$errno = null, string &$errstr = null, float $timeout = null, int $flags = STREAM_CLIENT_CONNECT, $context = null)\n+function stream_socket_client(string $remote_socket, ?int &$errno = null, ?string &$errstr = null, ?float $timeout = null, int $flags = STREAM_CLIENT_CONNECT, $context = null)\n {\n     error_clear_last();\n     if ($context !== null) {\n@@ -492,7 +492,7 @@ function stream_socket_pair(int $domain, int $type, int $protocol): iterable\n  * @throws StreamException\n  *\n  */\n-function stream_socket_server(string $local_socket, int &$errno = null, string &$errstr = null, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context = null)\n+function stream_socket_server(string $local_socket, ?int &$errno = null, ?string &$errstr = null, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context = null)\n {\n     error_clear_last();\n     if ($context !== null) {\ndiff --git a/generated/strings.php b/generated/strings.php\nindex 9bc7284..67a49ce 100644\n--- a/generated/strings.php\n+++ b/generated/strings.php\n@@ -529,7 +529,7 @@ function sprintf(string $format, ...$params): string\n  * @throws StringsException\n  *\n  */\n-function substr(string $string, int $start, int $length = null): string\n+function substr(string $string, int $start, ?int $length = null): string\n {\n     error_clear_last();\n     if ($length !== null) {\ndiff --git a/generated/swoole.php b/generated/swoole.php\nindex 334d96b..f65ab48 100644\n--- a/generated/swoole.php\n+++ b/generated/swoole.php\n@@ -14,7 +14,7 @@ use Safe\\Exceptions\\SwooleException;\n  * @throws SwooleException\n  *\n  */\n-function swoole_async_write(string $filename, string $content, int $offset = null, callable $callback = null): void\n+function swoole_async_write(string $filename, string $content, ?int $offset = null, ?callable $callback = null): void\n {\n     error_clear_last();\n     if ($callback !== null) {\n@@ -40,7 +40,7 @@ function swoole_async_write(string $filename, string $content, int $offset = nul\n  * @throws SwooleException\n  *\n  */\n-function swoole_async_writefile(string $filename, string $content, callable $callback = null, int $flags = 0): void\n+function swoole_async_writefile(string $filename, string $content, ?callable $callback = null, int $flags = 0): void\n {\n     error_clear_last();\n     if ($flags !== 0) {\ndiff --git a/generated/uodbc.php b/generated/uodbc.php\nindex 89775c8..a401d6f 100644\n--- a/generated/uodbc.php\n+++ b/generated/uodbc.php\n@@ -237,7 +237,7 @@ function odbc_columnprivileges($connection_id, string $catalog, string $schema,\n  * @throws UodbcException\n  *\n  */\n-function odbc_columns($connection_id, string $catalog = null, string $schema = null, string $table_name = null, string $column_name = null)\n+function odbc_columns($connection_id, ?string $catalog = null, ?string $schema = null, ?string $table_name = null, ?string $column_name = null)\n {\n     error_clear_last();\n     if ($column_name !== null) {\n@@ -314,7 +314,7 @@ function odbc_data_source($connection_id, int $fetch_type): array\n  * @throws UodbcException\n  *\n  */\n-function odbc_exec($connection_id, string $query_string, int $flags = null)\n+function odbc_exec($connection_id, string $query_string, ?int $flags = null)\n {\n     error_clear_last();\n     if ($flags !== null) {\n@@ -345,7 +345,7 @@ function odbc_exec($connection_id, string $query_string, int $flags = null)\n  * @throws UodbcException\n  *\n  */\n-function odbc_execute($result_id, array $parameters_array = null): void\n+function odbc_execute($result_id, ?array $parameters_array = null): void\n {\n     error_clear_last();\n     if ($parameters_array !== null) {\n@@ -373,7 +373,7 @@ function odbc_execute($result_id, array $parameters_array = null): void\n  * @throws UodbcException\n  *\n  */\n-function odbc_fetch_into($result_id, ?array &$result_array, int $rownumber = null): int\n+function odbc_fetch_into($result_id, ?array &$result_array, ?int $rownumber = null): int\n {\n     error_clear_last();\n     if ($rownumber !== null) {\n@@ -573,7 +573,7 @@ function odbc_foreignkeys($connection_id, string $pk_catalog, string $pk_schema,\n  * @throws UodbcException\n  *\n  */\n-function odbc_gettypeinfo($connection_id, int $data_type = null)\n+function odbc_gettypeinfo($connection_id, ?int $data_type = null)\n {\n     error_clear_last();\n     if ($data_type !== null) {\n@@ -687,7 +687,7 @@ function odbc_primarykeys($connection_id, string $catalog, string $schema, strin\n  * @throws UodbcException\n  *\n  */\n-function odbc_result_all($result_id, string $format = null): int\n+function odbc_result_all($result_id, ?string $format = null): int\n {\n     error_clear_last();\n     if ($format !== null) {\n@@ -988,7 +988,7 @@ function odbc_tableprivileges($connection_id, string $catalog, string $schema, s\n  * @throws UodbcException\n  *\n  */\n-function odbc_tables($connection_id, string $catalog = null, string $schema = null, string $name = null, string $types = null)\n+function odbc_tables($connection_id, ?string $catalog = null, ?string $schema = null, ?string $name = null, ?string $types = null)\n {\n     error_clear_last();\n     if ($types !== null) {\ndiff --git a/generated/xdiff.php b/generated/xdiff.php\nindex 27feef3..4719332 100644\n--- a/generated/xdiff.php\n+++ b/generated/xdiff.php\n@@ -219,7 +219,7 @@ function xdiff_string_patch_binary(string $str, string $patch): string\n  * @throws XdiffException\n  *\n  */\n-function xdiff_string_patch(string $str, string $patch, int $flags = null, ?string &$error = null): string\n+function xdiff_string_patch(string $str, string $patch, ?int $flags = null, ?string &$error = null): string\n {\n     error_clear_last();\n     if ($error !== null) {\ndiff --git a/generated/xml.php b/generated/xml.php\nindex 4f9f660..33a4c2d 100644\n--- a/generated/xml.php\n+++ b/generated/xml.php\n@@ -22,7 +22,7 @@ use Safe\\Exceptions\\XmlException;\n  * @throws XmlException\n  *\n  */\n-function xml_parser_create_ns(string $encoding = null, string $separator = \":\")\n+function xml_parser_create_ns (?string $encoding = null, string $separator = \":\")\n {\n     error_clear_last();\n     if ($separator !== \":\") {\n@@ -59,7 +59,7 @@ function xml_parser_create_ns(string $encoding = null, string $separator = \":\")\n  * @throws XmlException\n  *\n  */\n-function xml_parser_create(string $encoding = null)\n+function xml_parser_create (?string $encoding = null)\n {\n     error_clear_last();\n     if ($encoding !== null) {\ndiff --git a/generated/yaml.php b/generated/yaml.php\nindex 38daaf7..eaab6a7 100644\n--- a/generated/yaml.php\n+++ b/generated/yaml.php\n@@ -23,7 +23,7 @@ use Safe\\Exceptions\\YamlException;\n  * @throws YamlException\n  *\n  */\n-function yaml_parse_file(string $filename, int $pos = 0, ?int &$ndocs = null, array $callbacks = null)\n+function yaml_parse_file(string $filename, int $pos = 0, ?int &$ndocs = null, ?array $callbacks = null)\n {\n     error_clear_last();\n     $result = \\yaml_parse_file($filename, $pos, $ndocs, $callbacks);\n@@ -56,7 +56,7 @@ function yaml_parse_file(string $filename, int $pos = 0, ?int &$ndocs = null, ar\n  * @throws YamlException\n  *\n  */\n-function yaml_parse_url(string $url, int $pos = 0, ?int &$ndocs = null, array $callbacks = null)\n+function yaml_parse_url(string $url, int $pos = 0, ?int &$ndocs = null, ?array $callbacks = null)\n {\n     error_clear_last();\n     $result = \\yaml_parse_url($url, $pos, $ndocs, $callbacks);\n@@ -86,7 +86,7 @@ function yaml_parse_url(string $url, int $pos = 0, ?int &$ndocs = null, array $c\n  * @throws YamlException\n  *\n  */\n-function yaml_parse(string $input, int $pos = 0, ?int &$ndocs = null, array $callbacks = null)\n+function yaml_parse(string $input, int $pos = 0, ?int &$ndocs = null, ?array $callbacks = null)\n {\n     error_clear_last();\n     $result = \\yaml_parse($input, $pos, $ndocs, $callbacks);\ndiff --git a/generated/yaz.php b/generated/yaz.php\nindex 29c1d33..dab539f 100644\n--- a/generated/yaz.php\n+++ b/generated/yaz.php\n@@ -427,7 +427,7 @@ function yaz_search($id, string $type, string $query): void\n  * @throws YazException\n  *\n  */\n-function yaz_wait(array &$options = null)\n+function yaz_wait (?array &$options = null)\n {\n     error_clear_last();\n     $result = \\yaz_wait($options);\ndiff --git a/generated/zip.php b/generated/zip.php\nindex 8fd22bb..f8579f1 100644\n--- a/generated/zip.php\n+++ b/generated/zip.php\n@@ -35,7 +35,7 @@ function zip_entry_close($zip_entry): void\n  * @throws ZipException\n  *\n  */\n-function zip_entry_open($zip, $zip_entry, string $mode = null): void\n+function zip_entry_open($zip, $zip_entry, ?string $mode = null): void\n {\n     error_clear_last();\n     if ($mode !== null) {\ndiff --git a/generated/zlib.php b/generated/zlib.php\nindex 4dc3ca9..a3ec860 100644\n--- a/generated/zlib.php\n+++ b/generated/zlib.php\n@@ -115,7 +115,7 @@ function deflate_add($context, string $data, int $flush_mode = ZLIB_SYNC_FLUSH):\n  * @throws ZlibException\n  *\n  */\n-function deflate_init(int $encoding, array $options = null)\n+function deflate_init(int $encoding, ?array $options = null)\n {\n     error_clear_last();\n     $result = \\deflate_init($encoding, $options);\n@@ -183,7 +183,7 @@ function gzcompress(string $data, int $level = -1, int $encoding = ZLIB_ENCODING\n  * @throws ZlibException\n  *\n  */\n-function gzdecode(string $data, int $length = null): string\n+function gzdecode(string $data, ?int $length = null): string\n {\n     error_clear_last();\n     if ($length !== null) {\n@@ -276,7 +276,7 @@ function gzencode(string $data, int $level = -1, int $encoding_mode = FORCE_GZIP\n  * @throws ZlibException\n  *\n  */\n-function gzgets($zp, int $length = null): string\n+function gzgets($zp, ?int $length = null): string\n {\n     error_clear_last();\n     if ($length !== null) {\n@@ -305,7 +305,7 @@ function gzgets($zp, int $length = null): string\n  * @throws ZlibException\n  *\n  */\n-function gzgetss($zp, int $length, string $allowable_tags = null): string\n+function gzgetss($zp, int $length, ?string $allowable_tags = null): string\n {\n     error_clear_last();\n     if ($allowable_tags !== null) {\n@@ -550,7 +550,7 @@ function inflate_add($context, string $encoded_data, int $flush_mode = ZLIB_SYNC\n  * @throws ZlibException\n  *\n  */\n-function inflate_init(int $encoding, array $options = null)\n+function inflate_init(int $encoding, ?array $options = null)\n {\n     error_clear_last();\n     $result = \\inflate_init($encoding, $options);\n@@ -596,7 +596,7 @@ function readgzfile(string $filename, int $use_include_path = 0): int\n  * @throws ZlibException\n  *\n  */\n-function zlib_decode(string $data, int $max_decoded_len = null): string\n+function zlib_decode(string $data, ?int $max_decoded_len = null): string\n {\n     error_clear_last();\n     if ($max_decoded_len !== null) {\ndiff --git a/lib/special_cases.php b/lib/special_cases.php\nindex d18e211..ee0192e 100644\n--- a/lib/special_cases.php\n+++ b/lib/special_cases.php\n@@ -152,7 +152,7 @@ function apcu_fetch($key)\n  * @throws PcreException\n  *\n  */\n-function preg_replace($pattern, $replacement, $subject, int $limit = -1, int &$count = null)\n+function preg_replace($pattern, $replacement, $subject, int $limit = -1, ?int &$count = null)\n {\n     error_clear_last();\n     $result = \\preg_replace($pattern, $replacement, $subject, $limit, $count);\n"
  },
  {
    "path": "percy.config.karma.yml",
    "content": "version: 2\nsnapshot:\n  widths:\n    - 1600\n  min-height: 1000\n  percy-css: >\n    body {\n      margin: 0;\n      width: 100vw;\n      height: 100vh;\n    }\n    .i__karma__snapshot__hide {\n      display: none !important;\n    }\n\n    .story-media-display-element {\n      background-color: transparent !important;\n    }\n\n    video::-webkit-media-controls {\n      display: none;\n    }\n"
  },
  {
    "path": "percy.config.yml",
    "content": "version: 2\nsnapshot:\n  widths:\n    - 1600\n  min-height: 1000\n  percy-css: >\n    .toplevel_page_amp-options, #footer-upgrade, #wpadminbar\n    #wp-admin-bar-updates {\n      display: none;\n    }\n\n    span.update-plugins {\n      display: none !important;\n    }\n\n    .story-media-display-element {\n      background-color: transparent !important;\n    }\n\n    video::-webkit-media-controls {\n      display: none;\n    }\n"
  },
  {
    "path": "phpcs.xml.dist",
    "content": "<?xml version=\"1.0\" ?>\n<ruleset name=\"Web Stories PHP Coding Standards Rules\">\n  <config name=\"minimum_supported_wp_version\" value=\"6.6\" />\n\n  <rule ref=\"WordPress-Core\">\n    <type>error</type>\n    <exclude name=\"Universal.Arrays.DisallowShortArraySyntax\" />\n    <exclude name=\"Universal.Operators.DisallowShortTernary\" />\n    <exclude\n      name=\"WordPress.NamingConventions.ValidPostTypeSlug.NotStringLiteral\"\n    />\n  </rule>\n\n  <rule ref=\"PSR12.Files.FileHeader.IncorrectOrder\">\n    <exclude-pattern>*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress-Docs\">\n    <type>error</type>\n    <exclude-pattern>tests/*</exclude-pattern>\n    <!-- Documentation is organized with the use of namespaces. -->\n    <exclude name=\"Squiz.Commenting.FileComment.MissingPackageTag\" />\n    <exclude name=\"Squiz.Commenting.VariableComment.MissingVar\" />\n  </rule>\n\n  <rule ref=\"WordPress-Extra\">\n    <type>error</type>\n    <exclude name=\"WordPress.Files.FileName\" />\n    <exclude name=\"WordPress.Files.FileName.NotHyphenatedLowercase\" />\n  </rule>\n\n  <rule ref=\"WordPress-VIP-Go\">\n    <type>error</type>\n    <exclude-pattern>tests/*</exclude-pattern>\n    <exclude\n      name=\"WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules\"\n    />\n  </rule>\n\n  <rule ref=\"WordPress.Security.NonceVerification\">\n    <exclude-pattern>tests/*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.Security.EscapeOutput.OutputNotEscaped\">\n    <exclude-pattern\n    >includes/Infrastructure/Injector/SimpleInjector.php</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.WP.AlternativeFunctions\">\n     <exclude-pattern>tests/*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.WP.GlobalVariablesOverride.Prohibited\">\n    <exclude-pattern>tests/*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.WP.EnqueuedResources\">\n    <type>error</type>\n    <exclude-pattern>tests/*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.WP.I18n\">\n    <properties>\n      <property name=\"text_domain\" type=\"array\">\n        <element value=\"web-stories\" />\n      </property>\n    </properties>\n  </rule>\n\n  <rule ref=\"WordPress.NamingConventions.ValidVariableName\">\n    <properties>\n      <property name=\"allowed_custom_properties\" type=\"array\">\n        <element value=\"childNodes\" />\n        <element value=\"tagName\" />\n        <element value=\"textContent\" />\n        <element value=\"parentNode\" />\n        <element value=\"nodeType\" />\n        <element value=\"nodeName\" />\n        <element value=\"nextSibling\" />\n        <element value=\"previousSibling\" />\n        <element value=\"firstChild\" />\n        <element value=\"lastChild\" />\n        <element value=\"nodeValue\" />\n        <element value=\"ownerElement\" />\n        <element value=\"documentElement\" />\n        <element value=\"removeChild\" />\n        <element value=\"ownerDocument\" />\n        <element value=\"strictErrorChecking\" />\n        <element value=\"preserveWhiteSpace\" />\n      </property>\n    </properties>\n  </rule>\n\n  <rule ref=\"VariableAnalysis.CodeAnalysis.VariableAnalysis\" />\n\n  <!-- Check for cross-version support for PHP 7.4 and higher. -->\n  <config name=\"testVersion\" value=\"7.4-\" />\n  <rule ref=\"PHPCompatibilityWP\" />\n\n  <!-- The main plugin file should be parsable by PHP 5.6. -->\n  <rule ref=\"Generic.Arrays.DisallowLongArraySyntax.Found\">\n    <exclude-pattern>web-stories.php</exclude-pattern>\n    <exclude-pattern\n    >includes/compat/Web_Stories_Compatibility.php</exclude-pattern>\n  </rule>\n\n  <rule ref=\"WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid\">\n    <exclude-pattern\n    >tests/phpunit/integration/includes/REST_Setup.php</exclude-pattern>\n  </rule>\n\n  <rule ref=\"SlevomatCodingStandard.TypeHints.ReturnTypeHint\">\n    <properties>\n      <property name=\"enableStaticTypeHint\" value=\"false\" />\n      <property name=\"enableMixedTypeHint\" value=\"false\" />\n      <property name=\"enableUnionTypeHint\" value=\"false\" />\n      <property name=\"enableIntersectionTypeHint\" value=\"false\" />\n      <property name=\"enableStandaloneNullTrueFalseTypeHints\" value=\"false\" />\n      <property name=\"enableNeverTypeHint\" value=\"false\" />\n    </properties>\n\n    <exclude\n      name=\"SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification\"\n    />\n\n    <!-- The main plugin file should be parsable by PHP 5.6. -->\n    <exclude-pattern>web-stories.php</exclude-pattern>\n    <exclude-pattern\n    >includes/compat/Web_Stories_Compatibility.php</exclude-pattern>\n\n    <!-- To ensure backward compatibility for developers using these. -->\n    <exclude-pattern>includes/Interfaces/FieldState.php</exclude-pattern>\n    <exclude-pattern>includes/Interfaces/FieldStateFactory.php</exclude-pattern>\n    <exclude-pattern>includes/Renderer/Stories/*</exclude-pattern>\n  </rule>\n\n  <!-- Requires parameter typehints and reports useless @param annotations. -->\n  <rule ref=\"SlevomatCodingStandard.TypeHints.ParameterTypeHint\">\n    <properties>\n      <property name=\"enableMixedTypeHint\" value=\"false\" />\n      <property name=\"enableUnionTypeHint\" value=\"false\" />\n      <property name=\"enableIntersectionTypeHint\" value=\"false\" />\n      <property name=\"enableStandaloneNullTrueFalseTypeHints\" value=\"false\" />\n    </properties>\n\n    <exclude\n      name=\"SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification\"\n    />\n\n    <!-- The main plugin file should be parsable by PHP 5.6. -->\n    <exclude-pattern>web-stories.php</exclude-pattern>\n    <exclude-pattern\n    >includes/compat/Web_Stories_Compatibility.php</exclude-pattern>\n\n    <!-- To ensure backward compatibility for developers using these. -->\n    <exclude-pattern>includes/Interfaces/FieldState.php</exclude-pattern>\n    <exclude-pattern>includes/Interfaces/FieldStateFactory.php</exclude-pattern>\n    <exclude-pattern>includes/Renderer/Stories/*</exclude-pattern>\n\n    <!-- Parent REST API controller classes in WP don't use parameter type hints, need to match their signature -->\n    <exclude-pattern>includes/REST_API</exclude-pattern>\n\n    <!-- Parent widget classes in WP don't use parameter type hints, need to match their signature -->\n    <exclude-pattern>includes/Widgets</exclude-pattern>\n  </rule>\n\n  <!-- Checks whether the nullablity ? symbol is present before each nullable and optional parameter. -->\n  <rule\n    ref=\"SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue\"\n  />\n  <!-- Enforce no space between closing brace and colon of return typehint. -->\n  <rule ref=\"SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing\">\n    <properties>\n      <property name=\"spacesCountBeforeColon\" value=\"0\" />\n    </properties>\n  </rule>\n  <!-- Checks that there's no whitespace between a nullability symbol and a typehint. -->\n  <rule ref=\"SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing\" />\n  <!-- Enforces using shorthand scalar typehint variants in phpDocs. -->\n  <rule ref=\"SlevomatCodingStandard.TypeHints.LongTypeHints\" />\n  <!-- Reports useless @var annotation for constants because the type of constant is always clear. -->\n  <rule ref=\"SlevomatCodingStandard.TypeHints.UselessConstantTypeHint\" />\n\n  <rule ref=\"SlevomatCodingStandard.TypeHints.DeclareStrictTypes\">\n      <exclude-pattern>web-stories.php</exclude-pattern>\n      <exclude-pattern>includes/compat/*</exclude-pattern>\n      <exclude-pattern>includes/templates/*</exclude-pattern>\n  </rule>\n\n  <rule ref=\"SlevomatCodingStandard.TypeHints.PropertyTypeHint\">\n      <exclude-pattern>web-stories.php</exclude-pattern>\n      <exclude-pattern>includes/compat/*</exclude-pattern>\n       <properties>\n        <property name=\"enableMixedTypeHint\" value=\"false\" />\n        <property name=\"enableUnionTypeHint\" value=\"false\" />\n        <property name=\"enableIntersectionTypeHint\" value=\"false\" />\n        <property name=\"enableStandaloneNullTrueFalseTypeHints\" value=\"false\" />\n      </properties>\n  </rule>\n\n  <rule ref=\"SlevomatCodingStandard.Numbers.RequireNumericLiteralSeparator\">\n      <properties>\n        <property name=\"minDigitsAfterDecimalPoint\" value=\"3\" />\n        <property name=\"minDigitsBeforeDecimalPoint\" value=\"6\" />\n      </properties>\n  </rule>\n  <!-- Disallows grouped use declarations. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.DisallowGroupUse\" />\n  <!-- Disallows leading backslash in use statement. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash\" />\n  <!-- Checks whether uses at the top of a file are alphabetically sorted. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses\" />\n  <!-- Enforces one space after namespace, disallows content between namespace name and semicolon and disallows use of bracketed syntax. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.NamespaceDeclaration\" />\n  <!-- Prohibits multiple uses separated by commas. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.MultipleUsesPerLine\" />\n  <!-- Enforces one blank line before and after namespace. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.NamespaceSpacing\">\n    <properties>\n      <property name=\"linesCountBeforeNamespace\" value=\"1\" />\n      <property name=\"linesCountAfterNamespace\" value=\"1\" />\n    </properties>\n  </rule>\n  <!-- Enforces one blank before first use, after last use and none between two different types of use. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.UseSpacing\">\n    <properties>\n      <property name=\"linesCountBeforeFirstUse\" value=\"1\" />\n      <property name=\"linesCountBetweenUseTypes\" value=\"0\" />\n      <property name=\"linesCountAfterLastUse\" value=\"1\" />\n    </properties>\n  </rule>\n  <!-- All references to functions, classes and constants should import using a use statement. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly\">\n     <properties>\n        <property name=\"allowFullyQualifiedGlobalFunctions\" value=\"true\" />\n        <property name=\"allowFullyQualifiedGlobalClasses\" value=\"true\" />\n        <property name=\"allowFullyQualifiedGlobalConstants\" value=\"true\" />\n        <property name=\"allowFallbackGlobalFunctions\" value=\"true\" />\n        <property name=\"allowFallbackGlobalConstants\" value=\"true\" />\n        <property\n        name=\"allowFullyQualifiedNameForCollidingClasses\"\n        value=\"true\"\n      />\n    </properties>\n  </rule>\n  <!-- Prohibits uses from the same namespace. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.UseFromSameNamespace\" />\n  <!-- Looks for unused imports from other namespaces. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.UnusedUses\">\n    <properties>\n      <property name=\"searchAnnotations\" value=\"true\" />\n    </properties>\n  </rule>\n  <!-- Require root namespace for special compiled PHP functions. -->\n  <rule ref=\"SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions\">\n    <properties>\n      <property name=\"includeSpecialFunctions\" value=\"true\" />\n    </properties>\n  </rule>\n\n  <!-- Requires arrow functions if possible. -->\n  <rule ref=\"SlevomatCodingStandard.Functions.RequireArrowFunction\" />\n  <!-- Enforces correct space usage in array functions. -->\n  <rule ref=\"SlevomatCodingStandard.Functions.ArrowFunctionDeclaration\">\n    <properties>\n      <property name=\"spacesCountAfterKeyword\" value=\"0\" />\n      <property name=\"spacesCountBeforeArrow\" value=\"1\" />\n      <property name=\"spacesCountAfterArrow\" value=\"1\" />\n      <property name=\"allowMultiLine\" value=\"true\" />\n    </properties>\n  </rule>\n  <rule ref=\"SlevomatCodingStandard.Functions.StaticClosure\" />\n\n  <rule ref=\"SlevomatCodingStandard.PHP\">\n    <exclude name=\"SlevomatCodingStandard.PHP.RequireExplicitAssertion\" />\n    <exclude name=\"SlevomatCodingStandard.PHP.DisallowReference\" />\n  </rule>\n\n  <!-- Class names should be referenced via ::class constant when possible. -->\n  <rule ref=\"SlevomatCodingStandard.Classes.ModernClassNameReference\">\n    <properties>\n      <property name=\"enableOnObjects\" value=\"false\" />\n    </properties>\n  </rule>\n\n  <!-- Requires declaring visibility for class constants. -->\n  <rule ref=\"SlevomatCodingStandard.Classes.ClassConstantVisibility\" />\n\n  <rule ref=\"SlevomatCodingStandard.Classes.ClassStructure\">\n    <properties>\n      <property name=\"groups\" type=\"array\">\n        <element value=\"uses\" />\n\n        <element value=\"enum cases\" />\n\n        <!-- Public constants are first but you don't care about the order of protected or private constants -->\n        <element value=\"public constants\" />\n        <element value=\"constants\" />\n\n        <!-- You don't care about the order among the properties. The same can be done with \"properties\" shortcut -->\n        <element\n          value=\"public static properties, protected static properties, private static properties\"\n        />\n        <element\n          value=\"public properties, protected properties, private properties\"\n        />\n\n        <!-- Constructor is first, then all public methods, then protected/private methods and magic methods are last -->\n        <element value=\"constructor\" />\n        <element value=\"all public methods\" />\n        <element value=\"methods\" />\n        <element value=\"magic methods\" />\n      </property>\n    </properties>\n  </rule>\n\n  <rule ref=\"SlevomatCodingStandard.Variables\">\n    <exclude\n      name=\"SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable\"\n    />\n  </rule>\n\n  <!-- Enforces maximum cognitive complexity for functions.. -->\n  <rule ref=\"SlevomatCodingStandard.Complexity.Cognitive\">\n    <properties>\n      <property name=\"maxComplexity\" value=\"25\" />\n    </properties>\n  </rule>\n\n  <!-- Requires use of null coalesce operator (??) when possible. -->\n  <rule\n    ref=\"SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator\"\n  />\n\n  <!-- Reports forbidden annotations. -->\n  <rule ref=\"SlevomatCodingStandard.Commenting.ForbiddenAnnotations\">\n    <properties>\n      <property name=\"forbiddenAnnotations\" type=\"array\">\n        <element value=\"@package\" />\n        <element value=\"@subpackage\" />\n        <element value=\"@author\" />\n        <element value=\"@created\" />\n        <element value=\"@access\" />\n        <element value=\"@version\" />\n      </property>\n    </properties>\n  </rule>\n  <!-- Require specific order of PHPDoc annotations with empty newline between specific groups. -->\n  <rule ref=\"SlevomatCodingStandard.Commenting.DocCommentSpacing\">\n    <properties>\n      <property name=\"linesCountBeforeFirstContent\" value=\"0\" />\n      <property name=\"linesCountAfterLastContent\" value=\"0\" />\n      <property name=\"linesCountBetweenDescriptionAndAnnotations\" value=\"1\" />\n      <property name=\"linesCountBetweenAnnotationsGroups\" value=\"1\" />\n      <property name=\"annotationsGroups\" type=\"array\">\n        <element\n          value=\"\n          @SuppressWarnings,\n          @codeCoverageIgnore\n        \"\n        />\n        <element value=\"@internal\" />\n        <element value=\"\n\t\t\t\t\t@since,\n\t\t\t\t\t@deprecated,\n\t\t\t\t\" />\n        <element value=\"\n\t\t\t\t\t@link,\n\t\t\t\t\t@see,\n\t\t\t\t\t@uses,\n\t\t\t\t\" />\n        <element value=\"\n\t\t\t\t\t@global,\n\t\t\t\t\" />\n        <element value=\"\n\t\t\t\t\t@throws,\n\t\t\t\t\" />\n        <element value=\"\n\t\t\t\t\t@param,\n\t\t\t\t\t@return,\n\t\t\t\t\" />\n      </property>\n    </properties>\n\n    <!-- Prevent false positives for WordPress-style array annotations. -->\n    <exclude\n      name=\"SlevomatCodingStandard.Commenting.DocCommentSpacing.IncorrectAnnotationsGroup\"\n    />\n  </rule>\n\n  <!-- Show details about violated sniffs -->\n  <arg value=\"s\" />\n\n  <!-- Iterate over all PHP files by default -->\n  <arg name=\"extensions\" value=\"php\" />\n  <file>.</file>\n\n  <!-- Strip the filepaths down to the relevant bit. -->\n  <arg name=\"basepath\" value=\"./\" />\n\n  <!-- Check up to 20 files simultaneously. -->\n  <arg name=\"parallel\" value=\"20\" />\n\n  <!-- Third-party or auto-generated code -->\n  <exclude-pattern>*/build/*</exclude-pattern>\n  <exclude-pattern>*/data/*</exclude-pattern>\n  <exclude-pattern>packages/e2e-tests/src/plugins/*</exclude-pattern>\n  <exclude-pattern>*/node_modules/*</exclude-pattern>\n  <exclude-pattern>*/third-party/*</exclude-pattern>\n  <exclude-pattern>*/vendor/*</exclude-pattern>\n  <exclude-pattern>assets/js/*.asset.php</exclude-pattern>\n  <exclude-pattern>assets/js/*.chunks.php</exclude-pattern>\n  <exclude-pattern>includes/polyfills/mbstring.php</exclude-pattern>\n  <exclude-pattern>tests/phpstan/*</exclude-pattern>\n  <exclude-pattern\n  >tests/phpunit/unit/includes/MarkupComparison.php</exclude-pattern>\n</ruleset>\n"
  },
  {
    "path": "phpmd.xml",
    "content": "<?xml version=\"1.0\" ?>\n<ruleset\n  name=\"Web Stories PHPMD rule set\"\n  xmlns=\"http://pmd.sf.net/ruleset/1.0.0\"\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://pmd.sf.net/ruleset/1.0.0\n                       http://pmd.sf.net/ruleset_xml_schema.xsd\"\n  xsi:noNamespaceSchemaLocation=\"\n                       http://pmd.sf.net/ruleset_xml_schema.xsd\"\n>\n\n  <rule ref=\"rulesets/codesize.xml\">\n    <exclude name=\"CyclomaticComplexity\" />\n  </rule>\n\n  <rule ref=\"rulesets/codesize.xml/CyclomaticComplexity\">\n    <properties>\n      <property name=\"reportLevel\" value=\"20\" />\n    </properties>\n  </rule>\n\n  <rule ref=\"rulesets/cleancode.xml\">\n    <exclude name=\"ElseExpression\" />\n    <exclude name=\"StaticAccess\" />\n    <exclude name=\"MissingImport\" />\n  </rule>\n\n  <rule ref=\"rulesets/cleancode.xml/MissingImport\">\n    <properties>\n      <property name=\"ignore-global\" value=\"true\" />\n    </properties>\n  </rule>\n\n  <rule ref=\"rulesets/unusedcode.xml\">\n    <exclude name=\"UnusedFormalParameter\" />\n  </rule>\n\n  <!-- Temporary workaround for https://github.com/phpmd/phpmd/issues/337 -->\n  <exclude-pattern>includes/namespace.php</exclude-pattern>\n\n  <!-- Third-party or auto-generated code -->\n  <exclude-pattern>*/build/*</exclude-pattern>\n  <exclude-pattern>*/data/*</exclude-pattern>\n  <exclude-pattern>*/node_modules/*</exclude-pattern>\n  <exclude-pattern>*/tests/*</exclude-pattern>\n  <exclude-pattern>*/third-party/*</exclude-pattern>\n  <exclude-pattern>*/vendor/*</exclude-pattern>\n  <exclude-pattern>assets/js/*.asset.php</exclude-pattern>\n  <exclude-pattern>includes/polyfills/mbstring.php</exclude-pattern>\n</ruleset>\n"
  },
  {
    "path": "phpstan.neon.dist",
    "content": "services:\n  -\n    class: Google\\Web_Stories\\PHPStan\\ServiceContainerDynamicReturnTypeExtension\n    tags:\n      - phpstan.broker.dynamicMethodReturnTypeExtension\n  -\n    class: Google\\Web_Stories\\PHPStan\\ServicesDynamicReturnTypeExtension\n    tags:\n      - phpstan.broker.dynamicStaticMethodReturnTypeExtension\n\nincludes:\n\t- vendor/phpstan/phpstan/conf/bleedingEdge.neon\n\nparameters:\n  level: 9\n  inferPrivatePropertyTypeFromConstructor: true\n  ignoreErrors:\n    -\n      identifier: missingType.generics\n    -\n      identifier: requireOnce.fileNotFound\n    -\n      identifier: require.fileNotFound\n    -\n      identifier: staticMethod.internalClass\n      path: tests/phpunit/unit/tests\n    -\n      message: '/^Parameter #2 \\$args of method WP_Customize_Manager::add_setting\\(\\)/'\n      path: includes/Admin/Customizer.php\n    -\n      message: '/\\(int\\) does not accept int\\|WP_Error\\.$/'\n      path: tests/phpunit/integration/tests\n    -\n      message: '/^Call to deprecated method _get_first_available_transport\\(\\)/'\n      path: includes/REST_API/Hotlinking_Controller.php\n    -\n      message: '/apply_filters expects non-empty-string, string given/'\n      identifier: argument.type\n  paths:\n    - includes/\n    - tests/phpunit/integration/includes\n    - tests/phpunit/integration/tests\n    - tests/phpunit/unit/includes/\n    - tests/phpunit/unit/tests/\n    - uninstall.php\n  excludePaths:\n    - includes/vendor/*\n    - includes/polyfills/*\n  scanDirectories:\n    - third-party/\n  scanFiles:\n    - web-stories.php\n    - vendor/php-stubs/wordpress-tests-stubs/wordpress-tests-stubs.php\n    - tests/phpstan/stubs/amp.php\n    - tests/phpstan/stubs/wordpress-seo.php\n    - tests/phpstan/stubs/wp-cli.php\n    - tests/phpstan/stubs/wpdotcom.php\n  stubFiles:\n    - tests/phpstan/stubs/wordpress-override.php\n  bootstrapFiles:\n    - tests/phpstan/bootstrap.php\n    - third-party/vendor/ampproject/amp-wp/includes/sanitizers/class-amp-base-sanitizer.php\n    - third-party/vendor/ampproject/amp-wp/includes/sanitizers/class-amp-meta-sanitizer.php\n    - vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php\n  dynamicConstantNames:\n    - WEBSTORIES_DEV_MODE\n    - WPCOM_IS_VIP_ENV\n    - IS_WPCOM\n    - GOOGLESITEKIT_VERSION\n    - AMP__VERSION\n"
  },
  {
    "path": "phpunit-integration-multisite.xml.dist",
    "content": "<?xml version=\"1.0\" ?>\n<phpunit\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  bootstrap=\"tests/phpunit/integration/bootstrap.php\"\n  backupGlobals=\"false\"\n  colors=\"true\"\n  failOnRisky=\"true\"\n  convertErrorsToExceptions=\"true\"\n  convertNoticesToExceptions=\"true\"\n  convertWarningsToExceptions=\"true\"\n  xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/9.2/phpunit.xsd\"\n>\n\t<php>\n\t\t<ini name=\"error_reporting\" value=\"32767\" />\n\t\t<ini name=\"display_errors\" value=\"1\" />\n\t\t<ini name=\"display_startup_errors\" value=\"1\" />\n\t\t<const name=\"WP_TESTS_MULTISITE\" value=\"1\" />\n\t</php>\n\n\t<testsuites>\n\t\t<testsuite name=\"Web Stories Multisite Integration Test Suite\">\n\t\t\t<directory suffix=\".php\">./tests/phpunit/integration/tests</directory>\n\t\t</testsuite>\n\t</testsuites>\n\n\t<groups>\n\t\t<exclude>\n\t\t\t<group>ms-excluded</group>\n\t\t</exclude>\n\t</groups>\n\n\t<filter>\n\t\t<whitelist processUncoveredFilesFromWhitelist=\"false\">\n\t\t\t<directory suffix=\".php\">./</directory>\n\t\t\t<exclude>\n\t\t\t\t<directory suffix=\".php\">assets</directory>\n\t\t\t\t<directory suffix=\".php\">bin</directory>\n\t\t\t\t<directory suffix=\".php\">build</directory>\n\t\t\t\t<directory suffix=\".php\">node_modules</directory>\n\t\t\t\t<directory suffix=\".php\">tests</directory>\n\t\t\t\t<directory suffix=\".php\">vendor</directory>\n\t\t\t</exclude>\n\t\t</whitelist>\n\t</filter>\n</phpunit>\n"
  },
  {
    "path": "phpunit-integration.xml.dist",
    "content": "<?xml version=\"1.0\" ?>\n<phpunit\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  bootstrap=\"tests/phpunit/integration/bootstrap.php\"\n  backupGlobals=\"false\"\n  colors=\"true\"\n  failOnRisky=\"true\"\n  convertErrorsToExceptions=\"true\"\n  convertNoticesToExceptions=\"true\"\n  convertWarningsToExceptions=\"true\"\n  xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/9.2/phpunit.xsd\"\n>\n\t<php>\n\t\t<ini name=\"error_reporting\" value=\"32767\" />\n\t\t<ini name=\"display_errors\" value=\"1\" />\n\t\t<ini name=\"display_startup_errors\" value=\"1\" />\n\t</php>\n\n\t<testsuites>\n\t\t<testsuite name=\"Web Stories Integration Test Suite\">\n\t\t\t<directory suffix=\".php\">./tests/phpunit/integration/tests</directory>\n\t\t</testsuite>\n\t</testsuites>\n\n\t<groups>\n\t\t<exclude>\n\t\t\t<group>ms-required</group>\n\t\t</exclude>\n\t</groups>\n\n\t<filter>\n\t\t<whitelist processUncoveredFilesFromWhitelist=\"false\">\n\t\t\t<directory suffix=\".php\">./</directory>\n\t\t\t<exclude>\n\t\t\t\t<directory suffix=\".php\">assets</directory>\n\t\t\t\t<directory suffix=\".php\">bin</directory>\n\t\t\t\t<directory suffix=\".php\">build</directory>\n\t\t\t\t<directory suffix=\".php\">node_modules</directory>\n\t\t\t\t<directory suffix=\".php\">tests</directory>\n\t\t\t\t<directory suffix=\".php\">vendor</directory>\n\t\t\t\t<file>scoper.inc.php</file>\n\t\t\t\t<file>web-stories.php</file>\n\t\t\t\t<file>uninstall.php</file>\n\t\t\t\t<file>includes/namespace.php</file>\n\t\t\t\t<directory suffix=\".php\">includes/templates</directory>\n\t\t\t</exclude>\n\t\t</whitelist>\n\t</filter>\n</phpunit>\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" ?>\n<phpunit\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  bootstrap=\"tests/phpunit/unit/bootstrap.php\"\n  backupGlobals=\"false\"\n  colors=\"true\"\n  failOnRisky=\"true\"\n  convertErrorsToExceptions=\"true\"\n  convertNoticesToExceptions=\"true\"\n  convertWarningsToExceptions=\"true\"\n  xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/9.3/phpunit.xsd\"\n>\n  <coverage processUncoveredFiles=\"false\">\n    <include>\n      <directory suffix=\".php\">./</directory>\n    </include>\n    <exclude>\n      <directory suffix=\".php\">assets</directory>\n      <directory suffix=\".php\">bin</directory>\n      <directory suffix=\".php\">build</directory>\n      <directory suffix=\".php\">node_modules</directory>\n      <directory suffix=\".php\">tests</directory>\n      <directory suffix=\".php\">vendor</directory>\n      <file>scoper.inc.php</file>\n      <file>web-stories.php</file>\n      <file>uninstall.php</file>\n      <file>includes/namespace.php</file>\n      <directory suffix=\".php\">includes/templates</directory>\n    </exclude>\n  </coverage>\n  <php>\n    <ini name=\"error_reporting\" value=\"32767\" />\n    <ini name=\"display_errors\" value=\"1\" />\n    <ini name=\"display_startup_errors\" value=\"1\" />\n  </php>\n  <testsuites>\n    <testsuite name=\"Web Stories Unit Test Suite\">\n      <directory suffix=\".php\">./tests/phpunit/unit/tests</directory>\n    </testsuite>\n  </testsuites>\n  <groups>\n    <exclude>\n      <group>ms-required</group>\n    </exclude>\n  </groups>\n</phpunit>\n"
  },
  {
    "path": "readme.txt",
    "content": "=== Web Stories ===\n\nContributors:      google\nTested up to:      6.9\nRequires at least: 6.6\nStable tag:        V.V.V\nLicense:           Apache-2.0\nLicense URI:       https://www.apache.org/licenses/LICENSE-2.0\nTags:              web stories, stories, amp, storytelling, google\n\nWeb Stories are a visual storytelling format for the open web which immerses your readers in fast-loading, full-screen, and visually rich experiences.\n\n== Description ==\n\n[Web Stories](https://amp.dev/about/stories/) are a free, open-web, visual storytelling format for the web, enabling you to easily create visual narratives with engaging animations and tappable interactions, and  immerse your readers in great and fast-loading full-screen experiences.\n\n=== Benefits of Web Stories ===\n\nThe Web Stories format puts features and capabilities at your fingertips to engage with your audience via the power of storytelling on the open web. Specifically, you can:\n\n* **Create beautiful and engaging content easily:** Web Stories make the production of stories as easy as possible from a technical perspective.\n* **Enjoy creative flexibility for editorial freedom and branding:** The Web Stories format comes with preset but flexible layout templates, standardized UI controls, and components for sharing and adding follow-on content.\n* **Share and link your stories on the open web:** Web Stories are part of the open web and can be shared and embedded across sites and apps without being confined to a single ecosystem.\n* **Track and measure your stories:** Supports analytics and bookend capabilities for viral sharing and monetization.\n* **Capture the attention of your readers by offering fast loading times to your stories:** Web Stories are lightning fast so that your audience stays engaged and entertained.\n* **Engage with your readers via immersive storytelling:** Web Stories are a new and modern way to reach existing readers.\n* **Monetize effectively the beautiful and engaging stories you create:** Web Stories enable monetization capability for publishers using affiliate links. For advertisers, Stories is a way to reach a unique audience within a new storytelling experience.\n\n=== Web Stories Editor ===\n\nThe Web Stories editor for WordPress brings together a robust set of story creation capabilities in a user-friendly, WYSIWYG creation tool. Some of the key features you can leverage out of the box are:\n\n* **A visually rich and intuitive dashboard**, allowing you to easily navigate the story creation process\n* **Beautiful and expressive page templates** to you get your story creation process started quickly and smoothly\n* **Easy drag-and-drop capabilities**, making it easy to compose beautiful stories\n* **Convenient access to WordPress’ media library**, enabling you to grab your media assets right from the plugin dashboard as you create your stories\n* **Customizable color and text style presets**, making it easy to tailor the style of your stories to the needs of your content strategy\n* **And much more!**\n\nUsing the Web Stories editor for WordPress, you can easily create visual narratives with tappable interactions, and share freely across the web, or embed them on your existing content strategies. The Stories you create are yours in every way, as Web Stories belong to the open web, instead of being confined to any specific closed ecosystem or platform.\n\n=== Audience: Everyone ===\n\nWeb Stories are for everyone! If you are a site owner, content creator, or publisher on the web, embracing the Web Stories format would be great as a way to enhance the quality of your content strategy, the value you bring to your readers, and consequently your chances of achieving sustainable success.\n\n=== Terms of Service ===\n\nBy using this plugin, you agree to [Google's Terms of Service](https://policies.google.com/terms). By using third-party imagery and video provided by [Unsplash](https://unsplash.com/terms), [Coverr](https://coverr.co/license) and [Tenor](https://tenor.com/legal-terms), you agree to adhere to the respective Terms of Service.\n\n== Installation ==\n\n= Installation from within WordPress =\n\n1. Visit **Plugins > Add New**.\n2. Search for **Web Stories**.\n3. Install and activate the Web Stories plugin.\n\n= Manual installation =\n\n1. Upload the entire `web-stories` folder to the `/wp-content/plugins/` directory.\n2. Visit **Plugins**.\n3. Activate the Web Stories plugin.\n\n== Screenshots ==\n\n1. Web Stories for WordPress brings a powerful editor right into your WordPress admin.\n2. Easily create Web Stories with our drag-and-drop editor.\n3. Explore our WYSIWYG editor with easy access to many editing tools (shown here: zooming and cropping media)\n4. Get started building your first story by editing one of our expressive, fully built template stories included with the editor.\n\n== Frequently Asked Questions ==\n\nThank you for being an early adopter of Web Stories for WordPress! We're working around the clock to improve your experience and add editing capabilities. If you find any issues, please reach out by visiting the [support forum](https://wordpress.org/support/plugin/web-stories/) to ask any questions or file feature requests.\n\n= What browsers are supported? =\n\n**For an optimal Web Story creation experience**, we recommend using the latest version of commonly popular web browsers (Chrome, Firefox, Safari, Edge).\n\n= Is Web Stories for WordPress compatible with other WordPress plugins? =\n\nBecause the Web Story format is new to the web ecosystem, some WordPress plugins may need extra support. We are working to improve compatibility with the Web Story editor and encourage you to file any bugs and requests in the [support forum](https://wordpress.org/support/plugin/web-stories/).\n\n= Can I use Web Stories for WordPress on a touch screen? =\n\nThe Web Story editor is not currently supported on touch screen devices, such as a smartphone or tablet.\n\n= How do I make Web Stories appear in Google and other search engines? =\n\nFor better chances of being discovered, after publishing your Web Story, we encourage you to embed it into a regular article or post on your site by using the Web Stories Gutenberg block.\n\nWhile the default sitemaps in WordPress and most popular plugins handle it automatically, we encourage you to check that your Web Stories are included in your XML sitemaps.\n\n= How can I optimize Web Stories to show up on search engines? =\n\nWeb Stories created using Web Stories for WordPress use what’s provided in the Document tab inside the editor to generate schema.org and social meta-data automatically. Ensure you review and update all requested metadata, including cover image, excerpt and publisher logo. Please see [SEO for Web Stories](https://blog.amp.dev/2020/02/12/seo-for-amp-stories/) for further SEO guidance.\n\n= How do I implement Analytics in my Web Stories? =\n\nThere are two ways to include analytics in your Web Stories:\n\n* Add your Google Analytics ID in the \"Settings”.\n* If you use the [Site Kit by Google](https://wordpress.org/plugins/google-site-kit/) WordPress plugin, you can set up Google Analytics there.\n\n= What do I do about an AMP validation issue in Search Console? =\n\nWeb Stories are powered by [AMP](https://amp.dev/), which adds some restrictions on a page's allowed markup. In some cases, other WordPress plugins use disallowed markup. We recommend temporarily disabling these plugins and reaching out to our [support forum](https://wordpress.org/plugins/web-stories/).\n\n= Where can I report bugs? =\n\nFor help requests, support questions, or general feedback, please reach out via the [support forum](https://wordpress.org/plugins/web-stories/).\n\nReproducible bug reports can be filed [on GitHub](https://github.com/googleforcreators/web-stories-wp/).\n\nTo report a vulnerability in this plugin, please contact the Google Security Team at [g.co/vulnz](https://g.co/vulnz).\n\n== Changelog ==\n\nFor the plugin's full changelog, please see [the Releases page on GitHub](https://github.com/googleforcreators/web-stories-wp/releases).\n\n= 1.42.0 =\n\n* Enhancement: raises minimum WordPress version to 6.6.\n* Enhancement: updated list of available Google Fonts.\n* Fixed: resolved issue with lightbox when using shortcode.\n\n= 1.41.0 =\n\n* Fixed: resolved issue with carousel on right-to-left languages.\n* Fixed: resolved issue with lightbox when using shortcode.\n\n= 1.40.0 =\n\n* Enhancement: performance and UX improvements for the Web Stories block.\n* Enhancement: several performance improvements in the admin due to more lightweight bundles.\n* Enhancement: compatibility with WordPress 6.8.\n* Enhancement: updated list of available Google Fonts.\n* Fixed: Minor code quality improvements and bug fixes.\n\n= 1.39.0 =\n\n* Enhancement: new experimental performance improvements in the dashboard and editor.\n* Fixed: resolved translation warning on WordPress 6.7.\n* Fixed: improved Google Analytics 4 banner.\n* Fixed: resolved edge case where the media library might crash.\n\n== Upgrade Notice ==\n\n= 1.42.0 =\n\nThis release fixes a minor issues with the Web Stories shortcode. Now requires at least WordPress 6.6.\n"
  },
  {
    "path": "rollup.config.js",
    "content": "/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { resolve as resolvePath, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport resolve from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport { babel } from '@rollup/plugin-babel';\nimport url from '@rollup/plugin-url';\nimport json from '@rollup/plugin-json';\nimport dynamicImportVars from '@rollup/plugin-dynamic-import-vars';\nimport svgr from '@svgr/rollup';\nimport terser from '@rollup/plugin-terser';\nimport del from 'rollup-plugin-delete';\nimport copy from 'rollup-plugin-copy';\nimport webWorkerLoader from 'rollup-plugin-web-worker-loader';\nimport { getPackages } from '@manypkg/get-packages';\n\nconst __dirname = fileURLToPath(dirname(import.meta.url));\n\nconst plugins = [\n  resolve({\n    browser: true, // To correctly import browser version of @ffmpeg/ffmpeg for example.\n    preferBuiltins: true,\n    extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json'],\n  }),\n  babel({\n    babelrc: false,\n    extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs'],\n    babelHelpers: 'inline',\n    exclude: 'node_modules/**',\n    presets: ['@babel/env', '@babel/preset-react', '@babel/preset-typescript'],\n    plugins: [\n      'babel-plugin-styled-components',\n      [\n        'babel-plugin-transform-react-remove-prop-types',\n        {\n          removeImport: true,\n        },\n      ],\n    ],\n  }),\n  url({\n    include: '**/inline-icons/*.svg',\n  }),\n  svgr({\n    include: '**/icons/*.svg',\n    titleProp: true,\n    svgo: true,\n    memo: true,\n    svgoConfig: {\n      plugins: [\n        {\n          name: 'preset-default',\n          params: {\n            overrides: {\n              removeViewBox: false,\n              convertColors: {\n                currentColor: /^(?!url|none)/i,\n              },\n            },\n          },\n        },\n        'removeDimensions',\n      ],\n    },\n  }),\n  svgr({\n    include: '**/images/*.svg',\n    titleProp: true,\n    svgo: true,\n    memo: true,\n    svgoConfig: {\n      plugins: [\n        {\n          name: 'preset-default',\n          params: {\n            overrides: {\n              removeViewBox: false,\n              convertColors: {\n                // See https://github.com/googleforcreators/web-stories-wp/pull/6361\n                currentColor: false,\n              },\n            },\n          },\n        },\n        'removeDimensions',\n      ],\n    },\n  }),\n  commonjs(),\n  json({\n    compact: true,\n  }),\n  dynamicImportVars(),\n  webWorkerLoader({\n    inline: true,\n    preserveSource: true,\n    'web-worker': /\\.worker\\.js$/,\n  }),\n  terser({\n    // We preserve function names that start with capital letters as\n    // they're _likely_ component names, and these are useful to have\n    // in tracebacks and error messages.\n    keep_fnames: /__|_x|_n|_nx|sprintf|^[A-Z].+$/,\n    output: {\n      comments: /translators:/i,\n    },\n    mangle: {\n      reserved: ['__', '_x', '_n', '_nx', 'sprintf'],\n    },\n  }),\n];\n\n/**\n * @typedef {Object} CustomInputOptions\n * @property {string} configPackages Comma-separated list of package names to include.\n * @property {string} configEntries Comma-separated list of entries to build. Supports \"es\" and \"cjs\".\n * @typedef {import('rollup').RollupOptions & CustomInputOptions} CustomInputOptions\n */\n\n/**\n * Main rollup configuration for building npm packages.\n *\n * To build only a subset of all public packages, run:\n *\n * `npx rollup -c --configPackages=i18n,fonts`\n *\n * @param {CustomInputOptions} cliArgs CLI arguments.\n * @return {import('rollup').RollupOptions} Rollup configuration.\n */\nasync function config(cliArgs) {\n  const entries = [];\n\n  const { packages } = await getPackages(__dirname);\n\n  const allPublicPackageNames = packages\n    .filter((pkg) => !pkg.packageJson.private)\n    .map((pkg) => pkg.packageJson.name.split('/')[1]);\n  const packagesToBuild = cliArgs?.configPackages\n    ? cliArgs.configPackages.split(',')\n    : allPublicPackageNames;\n  const entriesToBuild = cliArgs?.configEntries\n    ? cliArgs.configEntries.split(',')\n    : ['es', 'cjs'];\n\n  for (const pkg of packages) {\n    if (!packagesToBuild.includes(pkg.packageJson.name.split('/')[1])) {\n      continue;\n    }\n\n    if (!pkg.packageJson.source) {\n      // This shouldn't happen for public packages.\n      continue;\n    }\n\n    const input = resolvePath(pkg.dir, pkg.packageJson.source);\n\n    const external = [\n      ...new Set([\n        ...Object.keys(pkg.packageJson.dependencies || {}),\n        ...Object.keys(pkg.packageJson.peerDependencies || {}),\n        'react',\n        'react-dom',\n        'react-dom/server',\n        /@babel\\/runtime/,\n        /node_modules/,\n      ]),\n    ];\n\n    const output = {\n      sourcemap: true,\n      exports: 'auto',\n      preserveModules: true,\n      banner: `/*\n * Copyright ${new Date().getFullYear()} Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */`,\n    };\n\n    const sourceDir = dirname(resolvePath(pkg.dir, pkg.packageJson.source));\n\n    if (entriesToBuild.includes('es')) {\n      const _plugins = [];\n\n      const moduleDir = dirname(resolvePath(pkg.dir, pkg.packageJson.module));\n      _plugins.push(\n        del({\n          targets: [moduleDir],\n          runOnce: false !== cliArgs.watch,\n        })\n      );\n\n      if ('@googleforcreators/fonts' === pkg.packageJson.name) {\n        _plugins.push(\n          copy({\n            targets: [{ src: `${sourceDir}/fonts.json`, dest: moduleDir }],\n          })\n        );\n      }\n\n      entries.push({\n        input,\n        output: {\n          ...output,\n          dir: moduleDir,\n          format: 'es',\n        },\n        plugins: [...plugins, ..._plugins],\n        external,\n        context: 'window',\n      });\n    }\n\n    if (entriesToBuild.includes('cjs')) {\n      const _plugins = [];\n\n      const mainDir = dirname(resolvePath(pkg.dir, pkg.packageJson.main));\n      _plugins.push(\n        del({\n          targets: [mainDir],\n          runOnce: false !== cliArgs.watch,\n        })\n      );\n\n      if ('@googleforcreators/fonts' === pkg.name) {\n        _plugins.push(\n          copy({\n            targets: [{ src: `${sourceDir}/fonts.json`, dest: mainDir }],\n          })\n        );\n      }\n\n      entries.push({\n        input,\n        output: {\n          ...output,\n          dir: mainDir,\n          format: 'cjs',\n        },\n        plugins: [...plugins, ..._plugins],\n        external,\n        context: 'window',\n      });\n    }\n  }\n\n  return entries;\n}\n\nexport default config;\n"
  },
  {
    "path": "scoper.inc.php",
    "content": "<?php\n/**\n * PHP-Scoper configuration file.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\ndeclare(strict_types = 1);\n\nuse Isolated\\Symfony\\Component\\Finder\\Finder;\n\n$wp_classes   = json_decode( file_get_contents( 'vendor/sniccowp/php-scoper-wordpress-excludes/generated/exclude-wordpress-classes.json' ), true );\n$wp_functions = json_decode( file_get_contents( 'vendor/sniccowp/php-scoper-wordpress-excludes/generated/exclude-wordpress-functions.json' ), true );\n$wp_constants = json_decode( file_get_contents( 'vendor/sniccowp/php-scoper-wordpress-excludes/generated/exclude-wordpress-constants.json' ), true );\n\nreturn [\n\t'prefix'            => 'Google\\\\Web_Stories_Dependencies',\n\n\t// See: https://github.com/humbug/php-scoper#finders-and-paths.\n\t'finders'           => [\n\t\t// Main AMP PHP Library.\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->name( '*.php' )\n\t\t\t->name( 'class-amp-base-sanitizer.php' )\n\t\t\t->notName(\n\t\t\t\t[\n\t\t\t\t\t'amp.php',\n\t\t\t\t\t'amp-enabled-classic-editor-toggle.php',\n\t\t\t\t\t'amp-frontend-actions.php',\n\t\t\t\t\t'amp-helper-functions.php',\n\t\t\t\t\t'amp-paired-browsing.php',\n\t\t\t\t\t'amp-post-template-functions.php',\n\t\t\t\t\t'class-amp-autoloader.php',\n\t\t\t\t\t'class-amp-comment-walker.php',\n\t\t\t\t\t'class-amp-content.php',\n\t\t\t\t\t'class-amp-html-utils.php',\n\t\t\t\t\t'class-amp-http.php',\n\t\t\t\t\t'class-amp-post-template.php',\n\t\t\t\t\t'class-amp-post-type-support.php',\n\t\t\t\t\t'class-amp-service-worker.php',\n\t\t\t\t\t'class-amp-theme-support.php',\n\t\t\t\t\t'class-amp-validated-url-post-type.php',\n\t\t\t\t\t'class-amp-validation-callback-wrapper.php',\n\t\t\t\t\t'deprecated.php',\n\t\t\t\t\t'reader-template-loader.php',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->exclude(\n\t\t\t\t[\n\t\t\t\t\t'admin',\n\t\t\t\t\t'assets',\n\t\t\t\t\t'back-compat',\n\t\t\t\t\t'bin',\n\t\t\t\t\t'cli',\n\t\t\t\t\t'docs',\n\t\t\t\t\t'embeds',\n\t\t\t\t\t'includes/admin',\n\t\t\t\t\t'includes/cli',\n\t\t\t\t\t'includes/embeds',\n\t\t\t\t\t'includes/options',\n\t\t\t\t\t'includes/settings',\n\t\t\t\t\t'includes/validation',\n\t\t\t\t\t'includes/widgets',\n\t\t\t\t\t'options',\n\t\t\t\t\t'patches',\n\t\t\t\t\t'sanitizers',\n\t\t\t\t\t'settings',\n\t\t\t\t\t'src',\n\t\t\t\t\t'templates',\n\t\t\t\t\t'tests',\n\t\t\t\t\t'vendor',\n\t\t\t\t\t'widgets',\n\t\t\t\t\t'wp-assets',\n\t\t\t\t\t'tests',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->in(\n\t\t\t\t[\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes',\n\t\t\t\t\t'vendor/ampproject/amp-wp/src/RemoteRequest',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->append(\n\t\t\t\t[\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-allowed-tags-generated.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-base-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-dev-mode-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-layout-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-meta-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-rule-spec.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-script-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-style-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/class-amp-tag-and-attribute-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/sanitizers/trait-amp-noscript-fallback.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/includes/templates/class-amp-content-sanitizer.php',\n\t\t\t\t\t'vendor/ampproject/amp-wp/src/ValidationExemption.php',\n\t\t\t\t]\n\t\t\t)\n\t\t\t\t->append( [ 'vendor/ampproject/amp-wp/composer.json' ] ),\n\n\t\t// AMP PHP Toolbox (Common + Optimizer).\n\t\t// Not just including /src folder because we also need the /resources folder.\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->in(\n\t\t\t\t[\n\t\t\t\t\t'vendor/ampproject/amp-toolbox/src',\n\t\t\t\t\t'vendor/ampproject/amp-toolbox/resources',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->append( [ 'vendor/ampproject/amp-toolbox/composer.json' ] ),\n\n\t\t// FasterImage (used by AMP_Img_Sanitizer).\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->name( '*.php' )\n\t\t\t->exclude(\n\t\t\t\t[\n\t\t\t\t\t'tests',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->in( 'vendor/fasterimage/fasterimage' )\n\t\t\t->append( [ 'vendor/fasterimage/fasterimage/composer.json' ] ),\n\n\t\t// PHP-CSS-Parser (used by AMP_Style_Sanitizer).\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->name( '*.php' )\n\t\t\t->exclude(\n\t\t\t\t[\n\t\t\t\t\t'tests',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->in( 'vendor/sabberworm/php-css-parser' )\n\t\t\t->append( [ 'vendor/sabberworm/php-css-parser/composer.json' ] ),\n\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->name( '*.php' )\n\t\t\t->exclude(\n\t\t\t\t[\n\t\t\t\t\t'tests',\n\t\t\t\t]\n\t\t\t)\n\t\t\t->in( 'vendor/enshrined/svg-sanitize/src' )\n\t\t\t->append( [ 'vendor/enshrined/svg-sanitize/composer.json' ] ),\n\n\t\t// Symfony mbstring polyfill.\n\t\tFinder::create()\n\t\t\t->files()\n\t\t\t->ignoreVCS( true )\n\t\t\t->ignoreDotFiles( true )\n\t\t\t->name( '/\\.*.php8?/' )\n\t\t\t->in( 'vendor/symfony/polyfill-mbstring/Resources' )\n\t\t\t->append(\n\t\t\t\t[\n\t\t\t\t\t'vendor/symfony/polyfill-mbstring/Mbstring.php',\n\t\t\t\t\t'vendor/symfony/polyfill-mbstring/composer.json',\n\t\t\t\t]\n\t\t\t),\n\n\t\t// Main composer.json file so that we can build a classmap.\n\t\tFinder::create()\n\t\t\t->append( [ 'composer.json' ] ),\n\t],\n\n\t// See: https://github.com/humbug/php-scoper#patchers.\n\t'patchers'          => [],\n\n\t// See https://github.com/humbug/php-scoper#whitelist.\n\t'whitelist'         => [],\n\n\t'exclude-classes'   => $wp_classes,\n\n\t'exclude-functions' => $wp_functions,\n\n\t'exclude-constants' => array_merge(\n\t\t$wp_constants,\n\t\t[\n\t\t\t'AMP__FILE__',\n\t\t\t'AMP__DIR__',\n\t\t\t'AMP__VERSION',\n\t\t]\n\t),\n];\n"
  },
  {
    "path": "tests/js/imageMock.js",
    "content": "/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default 'https://example.com/path/to/image.png';\n"
  },
  {
    "path": "tests/js/jest.config.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { dirname, join } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/** @type {import('@jest/types').Config} */\nconst sharedConfig = {\n  rootDir: '.',\n  resolver: '@web-stories-wp/jest-resolver',\n  moduleNameMapper: {\n    '\\\\.svg': join(__dirname, '/svgrMock.js'),\n    '\\\\.css': join(__dirname, '/styleMock.js'),\n    '\\\\.png': join(__dirname, '/imageMock.js'),\n  },\n  setupFiles: ['core-js'],\n  // Do not transform any node_modules except use-reduction\n  // See https://jestjs.io/docs/configuration#transformignorepatterns-arraystring\n  transformIgnorePatterns: [\n    '/node_modules/(?!(use-reduction|lib0|parsel-js)/)',\n  ],\n  testEnvironment: 'jsdom',\n  testMatch: ['**/test/**/*.{js,jsx,ts,tsx}'],\n  globals: {\n    WEB_STORIES_ENV: 'development',\n    WEB_STORIES_DISABLE_ERROR_BOUNDARIES: true,\n    WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: true,\n    WEB_STORIES_DISABLE_PREVENT: true,\n    WEB_STORIES_DISABLE_QUICK_TIPS: true,\n  },\n  setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/tests/js/jest.setup'],\n  testPathIgnorePatterns: [\n    '<rootDir>/.git',\n    '<rootDir>/build',\n    '<rootDir>/node_modules',\n    '<rootDir>/vendor',\n    'testUtils',\n    '_utils',\n  ],\n  coveragePathIgnorePatterns: [\n    '<rootDir>/node_modules',\n    '<rootDir>/build',\n    'testUtils',\n    '_utils',\n    'types.js',\n    'rollup.config.js',\n  ],\n  modulePathIgnorePatterns: [\n    '<rootDir>/build',\n    '<rootDir>/vendor',\n    '/dist-types/',\n  ],\n};\n\nexport default {\n  coverageReporters: ['lcov'],\n  coverageDirectory: '<rootDir>/build/logs',\n  collectCoverageFrom: [\n    '<rootDir>/packages/**/*.js',\n    '<rootDir>/bin/**/*.js',\n    '!<rootDir>/packages/fonts/**',\n    '!**/karma/**',\n    '!**/test/**',\n    '!**/testUtils/**',\n    '!**/stories/**',\n  ],\n  reporters: [\n    [\n      'jest-silent-reporter',\n      { useDots: true, showWarnings: true, showPaths: true },\n    ],\n  ],\n  projects: [\n    {\n      ...sharedConfig,\n      displayName: 'Core (jsdom)',\n      transform: {\n        '^.+\\\\.[jt]sx?$': 'babel-jest',\n      },\n      setupFiles: [\n        ...sharedConfig.setupFiles,\n        '<rootDir>/tests/js/setup-globals',\n        '<rootDir>/tests/js/setup-mocks',\n        'jest-canvas-mock',\n      ],\n      testMatch: ['<rootDir>/packages/**/test/**/*.{js,jsx,ts,tsx}'],\n      testPathIgnorePatterns: [\n        ...sharedConfig.testPathIgnorePatterns,\n        '<rootDir>/packages/*/scripts',\n        '<rootDir>/packages/activation-notice',\n        '<rootDir>/packages/stories-block',\n        '<rootDir>/packages/tinymce-button',\n        '<rootDir>/packages/widget',\n        '<rootDir>/packages/e2e-test-utils',\n        '<rootDir>/packages/e2e-tests',\n      ],\n    },\n    {\n      ...sharedConfig,\n      displayName: 'Core (node)',\n      testEnvironment: 'node',\n      testMatch: ['<rootDir>/packages/*/scripts/**/test/**/*.{js,ts}'],\n    },\n    {\n      ...sharedConfig,\n      displayName: 'WP (jsdom)',\n      transform: {\n        '^.+\\\\.[jt]sx?$': 'babel-jest',\n      },\n      setupFiles: [\n        ...sharedConfig.setupFiles,\n        '<rootDir>/tests/js/setup-globals',\n      ],\n      moduleNameMapper: {\n        ...sharedConfig.moduleNameMapper,\n        // Hacky way to grab a version of React 18 we know is installed.\n        '^react$':\n          '<rootDir>/packages/stories-block/node_modules/react/index.js',\n        '^react-dom(/.*)$':\n          '<rootDir>/packages/stories-block/node_modules/react-dom/$1',\n        // Ditto for React Testing Library.\n        '^@testing-library/react$':\n          '<rootDir>/packages/stories-block/node_modules/@testing-library/react/dist/index.js',\n      },\n      testMatch: [\n        '<rootDir>/packages/activation-notice/**/test/**/*.{js,jsx,ts,tsx}',\n        '<rootDir>/packages/stories-block/**/test/**/*.{js,jsx,ts,tsx}',\n        '<rootDir>/packages/tinymce-button/**/test/**/*.{js,jsx,ts,tsx}',\n        '<rootDir>/packages/widget/**/test/**/*.{js,jsx,ts,tsx}',\n      ],\n    },\n    {\n      ...sharedConfig,\n      displayName: 'WP (node)',\n      testEnvironment: 'node',\n      testMatch: ['<rootDir>/packages/commander/**/test/**/*.[jt]s'],\n    },\n  ],\n};\n"
  },
  {
    "path": "tests/js/jest.setup.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\n\n// Extend Jest matchers.\n// See https://github.com/testing-library/jest-dom.\nimport '@testing-library/jest-dom';\nimport 'jest-axe/extend-expect';\n\n// Improve snapshot testing for styled components.\n// Also provides a `toHaveStyleRule()` matcher.\nimport 'jest-styled-components';\n\nimport {\n  toBeValidAMP,\n  toBeValidAMPStoryElement,\n  toBeValidAMPStoryPage,\n} from '@web-stories-wp/jest-amp';\n\nexpect.extend({\n  toBeValidAMP,\n  toBeValidAMPStoryElement,\n  toBeValidAMPStoryPage,\n});\n\n// Retry flaky tests  on CI.\nif ('true' === process.env.CI) {\n  jest.retryTimes(2);\n}\n"
  },
  {
    "path": "tests/js/setup-globals.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nglobal.webStories = {};\nglobal.webStoriesBlockSettings = {\n  config: {\n    api: {},\n  },\n};\n\nglobal.wp = {};\n// eslint-disable-next-line jest/prefer-spy-on  -- test setup\nglobal.wp.media = jest.fn(() => ({\n  state: () => ({\n    get: () => ({\n      first: () => ({\n        toJSON: () => ({ url: 'http://dummy:url/' }),\n      }),\n    }),\n  }),\n  on: (type, callback) => callback(),\n  once: (type, callback) => callback(),\n  open: () => {},\n}));\n\nglobal.wp.media.controller = {\n  Library: {\n    prototype: {\n      defaults: {\n        contentUserSetting: jest.fn(),\n      },\n    },\n  },\n  Cropper: {\n    extend: jest.fn(),\n  },\n};\n\nglobal.IntersectionObserver = class IntersectionObserver {\n  observe() {}\n  unobserve() {}\n  disconnect() {}\n};\n\nglobal.ResizeObserver = class ResizeObserver {\n  observe() {}\n  unobserve() {}\n  disconnect() {}\n};\n\n// eslint-disable-next-line jest/prefer-spy-on -- test-setup\nglobal.matchMedia = jest.fn().mockImplementation((query) => ({\n  matches: false,\n  media: query,\n  onchange: null,\n  addListener: jest.fn(), // deprecated\n  removeListener: jest.fn(), // deprecated\n  addEventListener: jest.fn(),\n  removeEventListener: jest.fn(),\n  dispatchEvent: jest.fn(),\n}));\n\n// jsdom doesn't support these, so we stub them to make tests work as expected.\nif (typeof window !== 'undefined') {\n  window.HTMLMediaElement.prototype.load = () => undefined;\n  window.HTMLMediaElement.prototype.play = () => Promise.resolve();\n  window.HTMLMediaElement.prototype.pause = () => undefined;\n  File.prototype.arrayBuffer = () =>\n    new Promise((resolve) => resolve(new ArrayBuffer(0)));\n\n  window.KeyframeEffect = class KeyframeEffect {};\n  window.Animation = class Animation {\n    cancel() {}\n    play() {}\n  };\n  window.AnimationPlaybackEvent = class AnimationPlaybackEvent {};\n\n  // Prevent React warnings when setting the `muted` attribute on `<video>` elements.\n  // See https://github.com/testing-library/react-testing-library/issues/470\n  // See https://github.com/facebook/react/issues/10389\n  Object.defineProperty(HTMLMediaElement.prototype, 'muted', {\n    set: () => {},\n  });\n\n  class Worker {\n    constructor(stringUrl) {\n      this.url = stringUrl;\n      this.onmessage = () => {};\n    }\n\n    postMessage(msg) {\n      this.onmessage(msg);\n    }\n  }\n\n  window.Worker = Worker;\n}\n"
  },
  {
    "path": "tests/js/setup-mocks.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nimport { enableFetchMocks } from 'jest-fetch-mock';\n\n// eslint-disable-next-line jest/require-hook -- test setup\nenableFetchMocks();\n\njest.mock('react', () => ({\n  ...jest.requireActual('react'),\n  useLayoutEffect: jest.requireActual('react').useEffect,\n}));\n\njest.mock('@googleforcreators/story-editor/src/utils/getBlurHashFromImage');\n"
  },
  {
    "path": "tests/js/styleMock.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default {};\n"
  },
  {
    "path": "tests/js/svgrMock.js",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default 'span';\n"
  },
  {
    "path": "tests/phpstan/bootstrap.php",
    "content": "<?php\n/*\n * Global constants used in the analysed code need to be defined in bootstrap files.\n */\n\ndefine( 'WEBSTORIES_VERSION', '0.0.0' );\ndefine( 'WEBSTORIES_DB_VERSION', '0.0.0' );\ndefine( 'WEBSTORIES_AMP_VERSION', '0.0.0' );\ndefine( 'WEBSTORIES_PLUGIN_FILE', dirname( __DIR__, 2 ) . '/web-stories.php' ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.dirname_levelsFound\ndefine( 'WEBSTORIES_PLUGIN_DIR_PATH', dirname( WEBSTORIES_PLUGIN_FILE ) );\ndefine( 'WEBSTORIES_PLUGIN_DIR_URL', 'https://example.com/wp-content/plugins/web-stories/' );\ndefine( 'WEBSTORIES_CDN_URL', 'https://wp.stories.google/static/main/' );\ndefine( 'WEBSTORIES_MINIMUM_PHP_VERSION', '0.0' );\ndefine( 'WEBSTORIES_MINIMUM_WP_VERSION', '0.0' );\ndefine( 'WEBSTORIES_DEV_MODE', true );\n\ndefine( 'WPCOM_IS_VIP_ENV', true );\n\ndefine( 'AMP__VERSION', '1.2.3' );\n\n\n// Used only in tests:\n\ndefine( 'WPINC', '' );\ndefine( 'DIR_TESTDATA', '' );\ndefine( 'WEB_STORIES_TEST_DATA_DIR', '' );\n"
  },
  {
    "path": "tests/phpstan/src/ServiceContainerDynamicReturnTypeExtension.php",
    "content": "<?php\n/**\n * Class ServiceContainerDynamicReturnTypeExtension\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\PHPStan;\n\nuse Google\\Web_Stories\\Plugin;\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer;\nuse PhpParser\\Node\\Expr\\MethodCall;\nuse PhpParser\\Node\\Expr\\Variable;\nuse PhpParser\\Node\\Scalar\\String_;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Reflection\\MethodReflection;\nuse PHPStan\\Reflection\\ParametersAcceptorSelector;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Type\\DynamicMethodReturnTypeExtension;\nuse PHPStan\\Type\\ObjectType;\nuse PHPStan\\Type\\Type;\n\n/**\n * PHPStan extension class that provides the type for services returned via the\n * static service locator.\n *\n * phpcs:disable WordPress.NamingConventions.ValidVariableName\n * phpcs:disable PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations\n * phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable\n */\nfinal class ServiceContainerDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension {\n\n\tpublic function getClass(): string {\n\t\treturn ServiceContainer::class;\n\t}\n\n\tpublic function isMethodSupported(\n\t\tMethodReflection $methodReflection\n\t): bool {\n\t\treturn 'get' === $methodReflection->getName();\n\t}\n\n\tpublic function getTypeFromMethodCall(\n\t\tMethodReflection $methodReflection,\n\t\tMethodCall $methodCall,\n\t\tScope $scope\n\t): Type {\n\t\tswitch ( $methodReflection->getName() ) {\n\t\t\tcase 'get':\n\t\t\t\treturn $this->getGetTypeFromMethodCall(\n\t\t\t\t\t$methodReflection,\n\t\t\t\t\t$methodCall,\n\t\t\t\t\t$scope,\n\t\t\t\t);\n\n\t\t\tcase 'has':\n\t\t\t\treturn $this->getHasTypeFromMethodCall(\n\t\t\t\t\t$methodReflection,\n\t\t\t\t\t$methodCall\n\t\t\t\t);\n\t\t}\n\n\t\tthrow new ShouldNotHappenException();\n\t}\n\n\tprivate function getGetTypeFromMethodCall(\n\t\tMethodReflection $methodReflection,\n\t\tMethodCall $methodCall,\n\t\tScope $scope\n\t): Type {\n\t\t$return_type = ParametersAcceptorSelector::selectFromArgs(\n\t\t\t$scope,\n\t\t\t$methodCall->getArgs(),\n\t\t\t$methodReflection->getVariants()\n\t\t)->getReturnType();\n\n\t\tif (\n\t\t\t! isset( $methodCall->args[0] )\n\t\t\t||\n\t\t\tempty( $methodCall->args[0]->value )\n\t\t) {\n\t\t\treturn $return_type;\n\t\t}\n\n\t\t$service_id = $methodCall->args[0]->value;\n\t\tif ( $service_id instanceof String_ ) {\n\t\t\t$service_id = $service_id->value;\n\t\t}\n\n\t\t$services = array_merge(\n\t\t\t[ 'injector' => Injector::class ],\n\t\t\tPlugin::SERVICES\n\t\t);\n\n\t\tif ( $service_id instanceof Variable ) {\n\t\t\treturn new ObjectType( Service::class );\n\t\t}\n\n\t\tif ( array_key_exists( (string) $service_id, $services ) ) {\n\t\t\treturn new ObjectType( $services[ (string) $service_id ] );\n\t\t}\n\n\t\treturn $return_type;\n\t}\n}\n"
  },
  {
    "path": "tests/phpstan/src/ServicesDynamicReturnTypeExtension.php",
    "content": "<?php\n/**\n * Class ServicesDynamicReturnTypeExtension\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\PHPStan;\n\nuse Google\\Web_Stories\\Plugin;\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Services;\nuse PhpParser\\Node\\Expr\\StaticCall;\nuse PhpParser\\Node\\Expr\\Variable;\nuse PhpParser\\Node\\Scalar\\String_;\nuse PHPStan\\Analyser\\Scope;\nuse PHPStan\\Reflection\\MethodReflection;\nuse PHPStan\\Reflection\\ParametersAcceptorSelector;\nuse PHPStan\\ShouldNotHappenException;\nuse PHPStan\\Type\\Constant\\ConstantBooleanType;\nuse PHPStan\\Type\\DynamicStaticMethodReturnTypeExtension;\nuse PHPStan\\Type\\ObjectType;\nuse PHPStan\\Type\\Type;\n\n/**\n * PHPStan extension class that provides the type for services returned via the\n * static service locator.\n *\n * phpcs:disable WordPress.NamingConventions.ValidVariableName\n * phpcs:disable PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations\n * phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable\n */\nfinal class ServicesDynamicReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension {\n\n\tpublic function getClass(): string {\n\t\treturn Services::class;\n\t}\n\n\tpublic function isStaticMethodSupported(\n\t\tMethodReflection $methodReflection\n\t): bool {\n\t\treturn in_array( $methodReflection->getName(), [ 'get' ], true );\n\t}\n\n\tpublic function getTypeFromStaticMethodCall(\n\t\tMethodReflection $methodReflection,\n\t\tStaticCall $methodCall,\n\t\tScope $scope\n\t): Type {\n\t\tswitch ( $methodReflection->getName() ) {\n\t\t\tcase 'get':\n\t\t\t\treturn $this->getGetTypeFromStaticMethodCall(\n\t\t\t\t\t$methodReflection,\n\t\t\t\t\t$methodCall,\n\t\t\t\t\t$scope\n\t\t\t\t);\n\t\t}\n\n\t\tthrow new ShouldNotHappenException();\n\t}\n\n\tprivate function getGetTypeFromStaticMethodCall(\n\t\tMethodReflection $methodReflection,\n\t\tStaticCall $methodCall,\n\t\tScope $scope\n\t): Type {\n\t\t$return_type = ParametersAcceptorSelector::selectFromArgs(\n\t\t\t$scope,\n\t\t\t$methodCall->getArgs(),\n\t\t\t$methodReflection->getVariants()\n\t\t)->getReturnType();\n\n\t\tif (\n\t\t\t! isset( $methodCall->args[0] )\n\t\t\t||\n\t\t\tempty( $methodCall->args[0]->value )\n\t\t) {\n\t\t\treturn $return_type;\n\t\t}\n\n\t\t$service_id = $methodCall->args[0]->value;\n\t\tif ( $service_id instanceof String_ ) {\n\t\t\t$service_id = $service_id->value;\n\t\t}\n\n\t\t$services = array_merge(\n\t\t\t[ 'injector' => Injector::class ],\n\t\t\tPlugin::SERVICES\n\t\t);\n\n\t\tif ( $service_id instanceof Variable ) {\n\t\t\treturn new ObjectType( Service::class );\n\t\t}\n\n\t\tif ( array_key_exists( (string) $service_id, $services ) ) {\n\t\t\treturn new ObjectType( $services[ (string) $service_id ] );\n\t\t}\n\n\t\treturn $return_type;\n\t}\n}\n"
  },
  {
    "path": "tests/phpstan/stubs/amp.php",
    "content": "<?php\n\n/**\n * @return bool\n */\nfunction is_amp_endpoint() {\n}\n\nclass AMP_Base_Sanitizer {\n\t/**\n\t * @var AmpProject\\Dom\\Document\n\t */\n\tprotected $dom;\n\n\t/**\n\t * @var array\n\t */\n\tprotected $args;\n}\n"
  },
  {
    "path": "tests/phpstan/stubs/wordpress-override.php",
    "content": "<?php\n\n// See https://github.com/szepeviktor/phpstan-wordpress/issues/42\n\n/**\n * Determines whether current WordPress query has posts to loop over.\n *\n * @phpstan-impure\n *\n * @since 1.5.0\n *\n * @global WP_Query $wp_query WordPress Query object.\n *\n * @return bool True if posts are available, false if end of the loop.\n */\nfunction have_posts() {}\n"
  },
  {
    "path": "tests/phpstan/stubs/wordpress-seo.php",
    "content": "<?php\n/*\n * @todo: Use php-stubs/wordpress-seo-stubs once stable.\n */\n\nnamespace {\n\tfunction YoastSEO() {}\n}\n\nnamespace Yoast\\WP\\SEO {\n\n\tuse Yoast\\WP\\SEO\\Surfaces\\Classes_Surface;\n\n\tclass Main {\n\t\t/**\n\t\t * @var Classes_Surface\n\t\t */\n\t\tpublic $classes;\n\t}\n}\n\nnamespace Yoast\\WP\\SEO\\Surfaces {\n\tclass Classes_Surface {\n\t\t/**\n\t\t * Returns the instance of a class. Handy for unhooking things.\n\t\t *\n\t\t * @param string $class The class to get the instance of.\n\t\t *\n\t\t * @return mixed The instance of the class.\n\t\t */\n\t\tpublic function get( $class ) {}\n\t}\n}\n\nnamespace Yoast\\WP\\SEO\\Models {\n\tclass Indexable {\n\t\t/**\n\t\t * @var string\n\t\t */\n\t\tpublic $permalink;\n\t}\n}\n\nnamespace Yoast\\WP\\SEO\\Repositories {\n\n\tuse Yoast\\WP\\SEO\\Models\\Indexable;\n\n\tclass Indexable_Repository {\n\t\t/**\n\t\t * Retrieves an indexable for a post type archive.\n\t\t *\n\t\t * @param string $post_type   The post type.\n\t\t * @param bool   $auto_create Optional. Create the indexable if it does not exist.\n\t\t *\n\t\t * @return false|Indexable The indexable, false if none could be found.\n\t\t */\n\t\tpublic function find_for_post_type_archive( $post_type, $auto_create = true ) {}\n\n\t\t/**\n\t\t * Retrieves an indexable by its ID and type.\n\t\t *\n\t\t * @param int    $object_id   The indexable object ID.\n\t\t * @param string $object_type The indexable object type.\n\t\t * @param bool   $auto_create Optional. Create the indexable if it does not exist.\n\t\t *\n\t\t * @return false|Indexable Instance of indexable.\n\t\t */\n\t\tpublic function find_by_id_and_type( $object_id, $object_type, $auto_create = true ) {}\n\t}\n}\n\nnamespace Yoast\\WP\\SEO\\Builders {\n\n\tuse Yoast\\WP\\SEO\\Models\\Indexable;\n\n\tclass Indexable_Builder {\n\t\t/**\n\t\t * Creates an indexable for a post type archive.\n\t\t *\n\t\t * @param string         $post_type The post type.\n\t\t * @param Indexable|bool $indexable Optional. An existing indexable to overwrite.\n\t\t *\n\t\t * @return Indexable The post type archive indexable.\n\t\t */\n\t\tpublic function build_for_post_type_archive( $post_type, $indexable = false ) {}\n\n\t\t/**\n\t\t * Creates an indexable by its ID and type.\n\t\t *\n\t\t * @param int            $object_id   The indexable object ID.\n\t\t * @param string         $object_type The indexable object type.\n\t\t * @param Indexable|bool $indexable   Optional. An existing indexable to overwrite.\n\t\t *\n\t\t * @return bool|Indexable Instance of indexable. False when unable to build.\n\t\t */\n\t\tpublic function build_for_id_and_type( $object_id, $object_type, $indexable = false ) {}\n\t}\n}\n"
  },
  {
    "path": "tests/phpstan/stubs/wp-cli.php",
    "content": "<?php\n\nclass WP_CLI {\n\tpublic static function line( $text ) {\n\t}\n\n\tpublic static function warning( $text ) {\n\t}\n}\n"
  },
  {
    "path": "tests/phpstan/stubs/wpdotcom.php",
    "content": "<?php\n\n/**\n * @param mixed $url\n * @return int\n */\nfunction wpcom_vip_url_to_postid( $url ) {\n}\n\n/**\n * @param string       $page_path Page path.\n * @param string       $output    Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which\n *                                correspond to a WP_Post object, an associative array, or a numeric array,\n *                                respectively. Default OBJECT.\n * @param string|array $post_type Optional. Post type or array of post types. Default 'page'.\n * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.\n */\nfunction wpcom_vip_get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {\n}\n"
  },
  {
    "path": "tests/phpunit/integration/bootstrap.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nuse function Yoast\\WPTestUtils\\WPIntegration\\bootstrap_it;\nuse function Yoast\\WPTestUtils\\WPIntegration\\get_path_to_wp_test_dir;\n\n/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * PHPUnit bootstrap file.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nrequire_once dirname( __DIR__, 3 ) . '/vendor/yoast/wp-test-utils/src/WPIntegration/bootstrap-functions.php';\n\n$_tests_dir = get_path_to_wp_test_dir();\n\ndefine( 'WP_TESTS_PHPUNIT_POLYFILLS_PATH', dirname( __DIR__, 2 ) . '/vendor/yoast/phpunit-polyfills' );\n\n// Give access to tests_add_filter() function.\nrequire_once $_tests_dir . '/includes/functions.php';\n\n/**\n * Manually load the plugin being tested.\n */\nfunction _manually_load_plugin(): void {\n\trequire dirname( __DIR__, 3 ) . '/web-stories.php';\n}\n\ntests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );\n\nbootstrap_it();\n\ndefine( 'WEB_STORIES_TEST_DATA_DIR', __DIR__ . '/data' );\n\n/*\n * The mocks in ServiceBasedPluginTest require the WP_Site class\n * (as required by SiteInitializationAware::on_site_initialization)\n * to exist so that it can be mocked.\n * Since this class only exists on Multisite, it is stubbed here conditionally\n * for the sole purpose of making the mocking work.\n */\nif ( ! defined( 'WP_TESTS_MULTISITE' ) || ! WP_TESTS_MULTISITE ) {\n\trequire_once __DIR__ . '/stubs/WP_Site.php';\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/amp.dev.html",
    "content": "<!--\n  ~ Copyright 2020 Google LLC\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~     https://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<!DOCTYPE HTML><html amp lang=\"en\" i-amphtml-layout i-amphtml-no-boilerplate transformed=\"self;v=1\"><head><meta charset=\"utf-8\"><style amp-runtime i-amphtml-version=\"012002192257490\">html{overflow-x:hidden!important}html.i-amphtml-fie{height:100%!important;width:100%!important}html:not([amp4ads]),html:not([amp4ads]) body{height:auto!important}html:not([amp4ads]) body{margin:0!important}body{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}html.i-amphtml-singledoc.i-amphtml-embedded{-ms-touch-action:pan-y;touch-action:pan-y}html.i-amphtml-fie>body,html.i-amphtml-singledoc>body{overflow:visible!important}html.i-amphtml-fie:not(.i-amphtml-inabox)>body,html.i-amphtml-singledoc:not(.i-amphtml-inabox)>body{position:relative!important}html.i-amphtml-webview>body{overflow-x:hidden!important;overflow-y:visible!important;min-height:100vh!important}html.i-amphtml-ios-embed-legacy>body{overflow-x:hidden!important;overflow-y:auto!important;position:absolute!important}html.i-amphtml-ios-embed{overflow-y:auto!important;position:static}#i-amphtml-wrapper{overflow-x:hidden!important;overflow-y:auto!important;position:absolute!important;top:0!important;left:0!important;right:0!important;bottom:0!important;margin:0!important;display:block!important}html.i-amphtml-ios-embed.i-amphtml-ios-overscroll,html.i-amphtml-ios-embed.i-amphtml-ios-overscroll>#i-amphtml-wrapper{-webkit-overflow-scrolling:touch!important}#i-amphtml-wrapper>body{position:relative!important;border-top:1px solid transparent!important}#i-amphtml-wrapper+body{visibility:visible}#i-amphtml-wrapper+body .i-amphtml-lightbox-element,#i-amphtml-wrapper+body[i-amphtml-lightbox]{visibility:hidden}#i-amphtml-wrapper+body[i-amphtml-lightbox] .i-amphtml-lightbox-element{visibility:visible}#i-amphtml-wrapper.i-amphtml-scroll-disabled,.i-amphtml-scroll-disabled{overflow-x:hidden!important;overflow-y:hidden!important}amp-instagram{padding:54px 0px 0px!important;background-color:#fff}amp-iframe iframe{box-sizing:border-box!important}[amp-access][amp-access-hide]{display:none}[subscriptions-dialog],body:not(.i-amphtml-subs-ready) [subscriptions-action],body:not(.i-amphtml-subs-ready) [subscriptions-section]{display:none!important}amp-experiment,amp-live-list>[update],amp-share-tracking{display:none}.i-amphtml-jank-meter{position:fixed;background-color:rgba(232,72,95,0.5);bottom:0;right:0;color:#fff;font-size:16px;z-index:1000;padding:5px}amp-list[resizable-children]>.i-amphtml-loading-container.amp-hidden{display:none!important}amp-list[load-more] [load-more-button],amp-list[load-more] [load-more-end],amp-list[load-more] [load-more-failed],amp-list[load-more] [load-more-loading]{display:none}amp-story-page,amp-story[standalone]{min-height:1px!important;display:block!important;height:100%!important;margin:0!important;padding:0!important;overflow:hidden!important;width:100%!important}amp-story[standalone]{background-color:#202125!important;position:relative!important}amp-story-page{background-color:#757575}amp-story .amp-active>div{display:none!important}amp-story-page:not(:first-of-type):not([distance]):not([active]){transform:translateY(1000vh)!important}amp-autocomplete{position:relative!important;display:inline-block!important}amp-autocomplete>input,amp-autocomplete>textarea{padding:0.5rem;border:1px solid rgba(0,0,0,0.33)}.i-amphtml-autocomplete-results,amp-autocomplete>input,amp-autocomplete>textarea{font-size:1rem;line-height:1.5rem}[amp-fx^=fly-in]{visibility:hidden}\n/*# sourceURL=/css/ampdoc.css*/[hidden]{display:none!important}.i-amphtml-element{display:inline-block}.i-amphtml-blurry-placeholder{transition:opacity 0.3s cubic-bezier(0.0,0.0,0.2,1)!important}[layout=nodisplay]:not(.i-amphtml-element){display:none!important}.i-amphtml-layout-fixed,[layout=fixed][width][height]:not(.i-amphtml-layout-fixed){display:inline-block;position:relative}.i-amphtml-layout-responsive,[layout=responsive][width][height]:not(.i-amphtml-layout-responsive),[width][height][sizes]:not(.i-amphtml-layout-responsive){display:block;position:relative}.i-amphtml-layout-intrinsic{display:inline-block;position:relative;max-width:100%}.i-amphtml-intrinsic-sizer{max-width:100%;display:block!important}.i-amphtml-layout-container,.i-amphtml-layout-fixed-height,[layout=container],[layout=fixed-height][height]{display:block;position:relative}.i-amphtml-layout-fill,[layout=fill]:not(.i-amphtml-layout-fill){display:block;overflow:hidden!important;position:absolute;top:0;left:0;bottom:0;right:0}.i-amphtml-layout-flex-item,[layout=flex-item]:not(.i-amphtml-layout-flex-item){display:block;position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.i-amphtml-layout-fluid{position:relative}.i-amphtml-layout-size-defined{overflow:hidden!important}.i-amphtml-layout-awaiting-size{position:absolute!important;top:auto!important;bottom:auto!important}i-amphtml-sizer{display:block!important}.i-amphtml-blurry-placeholder,.i-amphtml-fill-content{display:block;height:0;max-height:100%;max-width:100%;min-height:100%;min-width:100%;width:0;margin:auto}.i-amphtml-layout-size-defined .i-amphtml-fill-content{position:absolute;top:0;left:0;bottom:0;right:0}.i-amphtml-layout-intrinsic .i-amphtml-sizer{max-width:100%}.i-amphtml-replaced-content,.i-amphtml-screen-reader{padding:0!important;border:none!important}.i-amphtml-screen-reader{position:fixed!important;top:0px!important;left:0px!important;width:4px!important;height:4px!important;opacity:0!important;overflow:hidden!important;margin:0!important;display:block!important;visibility:visible!important}.i-amphtml-screen-reader~.i-amphtml-screen-reader{left:8px!important}.i-amphtml-screen-reader~.i-amphtml-screen-reader~.i-amphtml-screen-reader{left:12px!important}.i-amphtml-screen-reader~.i-amphtml-screen-reader~.i-amphtml-screen-reader~.i-amphtml-screen-reader{left:16px!important}.i-amphtml-unresolved{position:relative;overflow:hidden!important}.i-amphtml-select-disabled{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.i-amphtml-notbuilt,[layout]:not(.i-amphtml-element){position:relative;overflow:hidden!important;color:transparent!important}.i-amphtml-notbuilt:not(.i-amphtml-layout-container)>*,[layout]:not([layout=container]):not(.i-amphtml-element)>*{display:none}.i-amphtml-ghost{visibility:hidden!important}.i-amphtml-element>[placeholder],[layout]:not(.i-amphtml-element)>[placeholder]{display:block}.i-amphtml-element>[placeholder].amp-hidden,.i-amphtml-element>[placeholder].hidden{visibility:hidden}.i-amphtml-element:not(.amp-notsupported)>[fallback],.i-amphtml-layout-container>[placeholder].amp-hidden,.i-amphtml-layout-container>[placeholder].hidden{display:none}.i-amphtml-layout-size-defined>[fallback],.i-amphtml-layout-size-defined>[placeholder]{position:absolute!important;top:0!important;left:0!important;right:0!important;bottom:0!important;z-index:1}.i-amphtml-notbuilt>[placeholder]{display:block!important}.i-amphtml-hidden-by-media-query{display:none!important}.i-amphtml-element-error{background:red!important;color:#fff!important;position:relative!important}.i-amphtml-element-error:before{content:attr(error-message)}i-amp-scroll-container,i-amphtml-scroll-container{position:absolute;top:0;left:0;right:0;bottom:0;display:block}i-amp-scroll-container.amp-active,i-amphtml-scroll-container.amp-active{overflow:auto;-webkit-overflow-scrolling:touch}.i-amphtml-loading-container{display:block!important;pointer-events:none;z-index:1}.i-amphtml-notbuilt>.i-amphtml-loading-container{display:block!important}.i-amphtml-loading-container.amp-hidden{visibility:hidden}.i-amphtml-element>[overflow]{cursor:pointer;position:relative;z-index:2;visibility:hidden}.i-amphtml-element>[overflow].amp-visible{visibility:visible}template{display:none!important}.amp-border-box,.amp-border-box *,.amp-border-box :after,.amp-border-box :before{box-sizing:border-box}amp-pixel{display:none!important}amp-analytics,amp-story-auto-ads{position:fixed!important;top:0!important;width:1px!important;height:1px!important;overflow:hidden!important;visibility:hidden}html.i-amphtml-fie>amp-analytics{position:initial!important}[visible-when-invalid]:not(.visible),amp-list [fetch-error],form [submit-error],form [submit-success],form [submitting]{display:none}amp-accordion{display:block!important}amp-accordion>section{float:none!important}amp-accordion>section>*{float:none!important;display:block!important;overflow:hidden!important;position:relative!important}amp-accordion,amp-accordion>section{margin:0}amp-accordion>section>:last-child{display:none!important}amp-accordion>section[expanded]>:last-child{display:block!important}\n/*# sourceURL=/css/ampshared.css*/</style><meta name=\"theme-color\" content=\"#005af0\"><meta name=\"description\" content=\"Whether you are a publisher, e-commerce company, storyteller, advertiser or email sender, AMP makes it easy to create great experiences on the web. Use AMP to build websites, stories, ads and emails.\"><meta name=\"twitter:card\" content=\"summary_large_image\"><meta name=\"twitter:description\" content=\"Whether you are a publisher, e-commerce company, storyteller, advertiser or email sender, AMP makes it easy to create great experiences on the web. Use AMP to build websites, stories, ads and emails.\"><meta name=\"twitter:title\" content=\"AMP - a web component framework to easily create user-first web experiences\"><meta name=\"twitter:creator\" content=\"@ampproject\"><meta name=\"twitter:site\" content=\"@ampproject\"><meta name=\"twitter:image\" content=\"https://amp.dev/static/img/sharing/default-600x314.png\"><meta property=\"og:title\" content=\"AMP - a web component framework to easily create user-first web experiences\"><meta property=\"og:url\" content=\"https://amp.dev/\"><meta property=\"og:image\" content=\"https://amp.dev/static/img/sharing/default-600x314.png\"><meta property=\"og:image:width\" content=\"600\"><meta property=\"og:image:height\" content=\"314\"><meta name=\"supported-amp-formats\" content=\"websites,stories,ads,email\"><meta name=\"page-locale\" content=\"en,fr,ar,es,it,id,ja,ko,pt_br,ru,tr,zh_cn\"><meta http-equiv=\"origin-trial\" content=\"AviuuiVhVdQ3GpVtxSpyMT+XsL/qGGYmyiyLvYSKPL3rRDLipe/ard5x+DXVlrATtolwX75VtpSKc9IEzLDd4AkAAABmeyJvcmlnaW4iOiJodHRwczovL2FtcC5kZXY6NDQzIiwiZmVhdHVyZSI6IkV4cGVyaW1lbnRhbEF1dG9wbGF5RHluYW1pY0RlbGVnYXRpb24iLCJleHBpcnkiOjE1NzA1Nzg0NDF9\"><meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\"><link rel=\"preload\" href=\"https://cdn.ampproject.org/v0.js\" as=\"script\"><script async src=\"https://cdn.ampproject.org/v0.js\"></script><script custom-element=\"amp-lightbox\" src=\"https://cdn.ampproject.org/v0/amp-lightbox-0.1.js\" async></script><script custom-element=\"amp-consent\" src=\"https://cdn.ampproject.org/v0/amp-consent-0.1.js\" async></script><script custom-element=\"amp-autocomplete\" src=\"https://cdn.ampproject.org/v0/amp-autocomplete-0.1.js\" async></script><script custom-element=\"amp-geo\" src=\"https://cdn.ampproject.org/v0/amp-geo-0.1.js\" async></script><script custom-element=\"amp-iframe\" src=\"https://cdn.ampproject.org/v0/amp-iframe-0.1.js\" async></script><script custom-element=\"amp-install-serviceworker\" src=\"https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js\" async></script><script custom-element=\"amp-bind\" src=\"https://cdn.ampproject.org/v0/amp-bind-0.1.js\" async></script><script custom-element=\"amp-animation\" src=\"https://cdn.ampproject.org/v0/amp-animation-0.1.js\" async></script><script custom-element=\"amp-analytics\" src=\"https://cdn.ampproject.org/v0/amp-analytics-0.1.js\" async></script><script custom-element=\"amp-form\" src=\"https://cdn.ampproject.org/v0/amp-form-0.1.js\" async></script><script custom-template=\"amp-mustache\" src=\"https://cdn.ampproject.org/v0/amp-mustache-0.2.js\" async></script><script custom-element=\"amp-list\" src=\"https://cdn.ampproject.org/v0/amp-list-0.1.js\" async></script><link rel=\"shortcut icon\" href=\"/static/img/favicon.png\"><link rel=\"preload\" href=\"/static/fonts/noto-sans-v7-latin-regular.woff2\" as=\"font\" crossorigin><link rel=\"preload\" href=\"/static/fonts/noto-sans-v7-latin-700.woff2\" as=\"font\" crossorigin><link rel=\"preload\" href=\"/static/fonts/poppins-v5-latin-700.woff2\" as=\"font\" crossorigin><link rel=\"preload\" href=\"/static/fonts/fira-mono-v7-latin-500.woff2\" as=\"font\" crossorigin><link rel=\"canonical\" href=\"https://amp.dev/\"><link rel=\"alternate\" hreflang=\"x-default\" href=\"https://amp.dev/\"><title>AMP - a web component framework to easily create user-first web experiences - amp.dev</title><script type=\"application/ld+json\">{\"@context\":\"http://schema.org\",\"@type\":\"Webpage\",\"url\":\"https://amp.dev/ \",\"name\":\"amp.dev\",\"headline\":\"AMP - a web component framework to easily create user-first web experiences\",\"description\":\"Whether you are a publisher, e-commerce company, storyteller, advertiser or email sender, AMP makes it easy to create great experiences on the web. Use AMP to build websites, stories, ads and emails.\",\"mainEntityOfPage\":{\"@type\":\"WebPage\",\"@id\":\"https://amp.dev\"},\"publisher\":{\"@type\":\"Organization\",\"name\":\"AMP Project\",\"logo\":{\"url\":\"https://amp.dev/static/img/icons/icon-512x512.png\",\"width\":512,\"height\":512,\"@type\":\"ImageObject\"}},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https://amp.dev/static/img/sharing/default-600x314.png\",\"width\":600,\"height\":314}}</script><style amp-custom>@font-face{font-family:'Noto Sans';font-style:normal;font-weight:400;font-display:swap;src:local(\"Noto Sans\"),local(\"NotoSans\"),url(https://amp.dev/static/fonts/noto-sans-v7-latin-regular.woff2) format(\"woff2\"),url(https://amp.dev/static/fonts/noto-sans-v7-latin-regular.woff) format(\"woff\")}@font-face{font-family:'Noto Sans';font-style:normal;font-weight:700;font-display:swap;src:local(\"Noto Sans Bold\"),local(\"NotoSans-Bold\"),url(https://amp.dev/static/fonts/noto-sans-v7-latin-700.woff2) format(\"woff2\"),url(https://amp.dev/static/fonts/noto-sans-v7-latin-700.woff) format(\"woff\")}@font-face{font-family:Poppins;font-style:normal;font-weight:700;font-display:swap;src:local(\"Poppins Bold\"),local(\"Poppins-Bold\"),url(https://amp.dev/static/fonts/poppins-v5-latin-700.woff2) format(\"woff2\"),url(https://amp.dev/static/fonts/poppins-v5-latin-700.woff) format(\"woff\")}@font-face{font-family:'Fira Mono';font-style:normal;font-weight:400;font-display:swap;src:local(\"Fira Mono\"),local(\"FiraMono\"),url(https://amp.dev/static/fonts/fira-mono-v7-latin-500.woff2) format(\"woff2\"),url(https://amp.dev/static/fonts/fira-mono-v7-latin-500.woff) format(\"woff\")}*{box-sizing:border-box}body,html{padding:0;margin:0;min-width:240px;color:#48525c;background-color:#fff;font-size:16px;font-family:'Noto Sans',sans-serif;overflow-x:hidden;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (max-width:240px){body,html{font-size:14px}}:target::before{content:'';display:block;visibility:hidden;height:120px;margin-top:-120px}@media (min-width:1024px){h1:target::before{height:75px;margin-top:-75px}h2:target::before{height:81px;margin-top:-81px}h3:target::before{height:87px;margin-top:-87px}h4:target::before{height:90px;margin-top:-90px}h5:target::before{height:93px;margin-top:-93px}h6:target::before{height:97px;margin-top:-97px}}h1,h2,h3,h4,h5{margin-bottom:.75em;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;color:#20202a}h4,h5{margin-top:1.5rem}h1{font-size:2.2rem;margin-top:3rem}section.-t h1:first-of-type{margin-top:0}@media (min-width:768px){section.-t h1:first-of-type{margin-bottom:2rem}}h2{font-size:1.8rem;margin-top:2rem}h3{font-size:1.414rem;margin-top:1.8rem}h4{font-size:1.2rem}h5{font-size:1rem}.-t .intro,.ap--section .intro{font-size:1rem;padding:0}.-t .intro *,.ap--section .intro *{font-size:inherit}.-t p,.ap--section p{line-height:1.6rem;font-weight:400;color:#48525c;display:block;margin-top:1.1em;margin-bottom:0;font-size:1rem}.-rk b,.-t p small,.ap--section p small{font-size:.875rem}.-t code,.ap--section code{display:inline;padding:2px 4px;font-family:'Fira Mono',monospace;font-weight:500;word-break:normal;color:#000;background-color:#eaeaea;font-size:.9em}.-t a,.ap--section a{position:relative;z-index:10}.-t a code,.ap--section a code{color:#005af0;z-index:-1}.-t pre,.ap--section pre{font-family:'Fira Mono',monospace;font-weight:500;font-size:1rem;white-space:pre-wrap}.-t>ol,.-t>ul,.ap--section>ol,.ap--section>ul{line-height:1.6rem;font-weight:400;color:#48525c;display:block;padding-left:2em;margin:1.5em 0}.-t>ol ol,.-t>ol ul,.-t>ul ol,.-t>ul ul,.ap--section>ol ol,.ap--section>ol ul,.ap--section>ul ol,.ap--section>ul ul{padding-left:2em;margin:0}.-t>ol li,.-t>ul li,.ap--section>ol li,.ap--section>ul li{padding-left:.5em}.-t>ol li p,.-t>ul li p,.ap--section>ol li p,.ap--section>ul li p{font-size:1em}.-t figure figcaption,.ap--section figure figcaption{line-height:1.6rem;font-weight:400;color:#48525c;font-size:.8125rem;margin-top:.3em}.-t hr,.ap--section hr{height:1px;margin:.75em 0;background-color:#ebebf0;border:0}.-n{display:flex;align-items:center;text-decoration:none;padding:0 0 1.5em;margin:0}.-i,.-r{transition:transform .3s cubic-bezier(.25,.1,.25,1)}.-r{line-height:1.6rem;font-size:.875rem;font-weight:700;color:#005af0;line-height:1.3}.-i{fill:#005af0;padding:.438em 0;margin-bottom:auto;margin-right:.625em;box-sizing:initial}.-n:hover .-i,.-n:hover .-r{transform:translateX(10px)}.-s{border-bottom:1px solid #ebebf0}.-s .-r{font-size:1rem;font-family:Poppins,sans-serif;font-weight:700;color:#000;padding-left:10px}.-s .-i{width:1.375em;height:1.375em;fill:#fff;background-color:#005af0;overflow:hidden;padding:.563em}.-s .-i,.-s:hover .-i{box-shadow:0 10px 20px 0 rgba(0,0,0,.25)}.-s:hover .-i svg{animation:.3s cubic-bezier(.25,.1,.25,1) duepduep}a,a code{color:#005af0}a{font-weight:700;text-decoration:none}a code{display:inline;padding:2px 4px;font-family:'Fira Mono',monospace;font-weight:500;word-break:normal;background-color:#eaeaea;font-size:.9em}.ap-a-ico{display:flex;font-size:initial;box-sizing:initial;justify-content:center;width:1em;height:1em}.-o{right:20px;left:auto;bottom:20px;width:calc(100% - 40px);padding:15px;line-height:1.6rem;font-weight:400;color:#48525c;font-size:.875rem;background-color:#fff;box-shadow:0 15px 30px 0 rgba(0,0,0,.15);border-radius:8px}@media (min-width:768px){.-o{max-width:500px}}.-u{position:absolute;right:15px;top:15px;background-color:transparent;border:0;padding:0}.-u svg{width:10px;height:10px}.-o button{cursor:pointer}.ap--footer{position:relative;z-index:15;padding:3em 0 2em;line-height:1.6rem;font-weight:400;font-size:1rem;color:#fff;background:linear-gradient(45deg,#48525c,#29323c)}.-a{width:100%;max-width:1440px;padding:0 20px;margin:0 auto}.-f{padding-bottom:4em}@media (min-width:768px){.-f{display:flex;align-items:center}}.-l{display:flex;flex-direction:column;margin-left:auto}@media (min-width:1024px){.-l{flex-direction:row}}.-c{margin:3em 2em 1em 0;color:#fff}@media (min-width:768px){.-c{margin:auto 2em auto 1em}}.-h{display:flex;list-style:none;padding:0;margin:0}.-p{flex:1 0 auto}@media (min-width:768px){.-p{margin:16px}}.-d{width:2.5em;height:2.5em;fill:#fff}@media (max-width:240px){.-d{font-size:14px}}@media (min-width:768px){.-v{display:grid;grid-gap:30px;grid-template-columns:repeat(12,1fr)}}.-m{flex:1 1 100%}.-m:nth-child(2n+1){grid-column:span 3}@media (max-width:1023px){.-m:nth-child(2n+1){grid-column:span 6}}.-m:nth-child(2n+2){grid-column:span 3}@media (max-width:1023px){.-m:nth-child(2n+2){grid-column:span 6}}.-g{color:#fff}.-y{list-style:none;padding:0}@media (min-width:768px){.-y+.-g{margin-top:2.5em}}.-b{position:relative}.-w{padding-left:35px;font-size:.8125rem;color:#fff}.-x{position:absolute;left:10px;top:8px;width:12px;height:12px;fill:#fff}.-k{display:flex;padding-top:4em}@media (max-width:767px){.-k{flex-direction:column}}.-_{list-style:none;padding:0;margin:0}.-j{display:inline-block;margin-right:1em}.-q{font-size:.8125rem;font-weight:400;color:#fff}.-z{display:block;font-size:.875rem;font-weight:700}@media (min-width:768px){.-z{padding:0 2em}}.ap-a-btn{margin-top:1.5rem;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;font-size:1em;color:#fff;display:inline-block;max-width:100%;width:auto;height:auto;padding:.75em 1.75em;margin:0;text-decoration:none;text-align:center;border-radius:3px;background-color:#005af0;border:0;cursor:pointer;box-shadow:0 15px 35px -5px rgba(0,0,0,.25);transition:transform .3s cubic-bezier(.25,.1,.25,1),box-shadow .3s cubic-bezier(.25,.1,.25,1)}.-tn:hover,.ap-a-btn:hover{transform:translateY(-.125em);box-shadow:0 25px 20px -15px rgba(0,0,0,.15)}@media (min-width:768px){.ap-a-btn{padding:1em 2em}}.ap--shift-cards{padding:3em 0}@media (min-width:768px){.ap--shift-cards{padding:8vw 0}}.ap--shift-cards-link{grid-column:3/12}@media (min-width:1024px){.ap--shift-cards-link{grid-column:19/-1}}.-te{flex:1 0 calc(50% - 1em);width:100%;padding-bottom:2em;margin:0 .5em 2em;text-align:center;background:#fff;border-radius:10px}@media (min-width:768px){.-te{margin:0}}.-tt{box-shadow:0 15px 30px 0 rgba(0,0,0,.15)}.-tn{transition:transform .3s cubic-bezier(.25,.1,.25,1),box-shadow .3s cubic-bezier(.25,.1,.25,1)}.-tn:hover{box-shadow:0 25px 60px 0 rgba(0,0,0,.1)}.-te .ap-m-ghost-frame-mobile{width:100%;margin:auto}.-tr{display:block;height:100%}.-ti{grid-column:1/13;grid-row:1/3}@media (min-width:1024px){.-ti{grid-column:2/12}}@media (min-width:1280px){.-ti{grid-column:3/12}}.-ti.small{grid-column:5/12}.-ts{grid-column:13/25;grid-row:2/4;margin-bottom:0}@media (min-width:1024px){.-ts{grid-column:14/24}}@media (min-width:1280px){.-ts{grid-column:14/23}}.-ts.small{grid-column:14/21}.-to{padding:0 2.5rem;font-size:1.2rem}@media (min-width:768px){.-to{padding:0 5rem;font-size:1.414rem;margin-top:1.8rem}}.-ta,.-tu{line-height:1.6rem;font-weight:400;color:#48525c;font-size:.875rem}.-tu{margin-bottom:.5em}.-ta{padding:0 2.5rem}@media (min-width:768px){.-ta{padding:0 3rem;font-size:1rem}}.ap-m-tag{line-height:1.6rem;color:#48525c;font-size:.875rem;font-weight:700;text-align:center;display:inline-block;min-width:80px;line-height:30px;padding:0 5px}.ap-m-tag:empty{min-width:26px;padding:4px 0}.ap-m-tag-websites{color:#fff;background:linear-gradient(225deg,#00dcc0 0,#005af0 75%)}.ap-m-tag-stories{color:#180ca4;background:linear-gradient(225deg,#ff8f00 0,#ffdc00 75%)}.ap-m-tag-ads{color:#fff;background:linear-gradient(225deg,#eb49e1 0,#5500d7 75%)}.ap-m-tag-email{color:#180ca4;background:linear-gradient(225deg,#64bf46 0,#e1eb64 75%)}.ap-m-tag-general{color:#fff;background-color:#005af0}.-tf.-tl{position:relative;flex:1 0 15em;margin:0 20px 20px 0}@media (min-width:575px){.-tf.-tl{margin:0 0 2em}}.-tf.-tl>a{position:relative;display:block;transition:transform .3s cubic-bezier(.25,.1,.25,1)}.-tf.-tl>a:hover{transform:translateY(-2px)}.-tf.-tl>a:hover .-tc{box-shadow:inset 0 0 0 1px #ebebf0,0 25px 60px 0 rgba(0,0,0,.1)}.-tf .-th{position:absolute;right:16px;top:-15px;z-index:1;border-radius:15px;font-family:Poppins}.-tf .-tc{overflow:hidden;position:relative;background-color:#fff;border-radius:10px;box-shadow:inset 0 0 0 1px #ebebf0,0 15px 30px 0 rgba(0,0,0,.15);transition:box-shadow .3s cubic-bezier(.25,.1,.25,1)}@media (max-width:767px){.-tf .-tc{margin-bottom:60px}}.-tf .-tc .-tp{max-width:100px;width:110px;height:30px;margin-bottom:1em}.-tf .-tc .-tp amp-img.contain img{object-fit:contain;object-position:left center}.-tf .-td{padding:25px}.-tf .-tc .-tp,.-tf .-tv,.-tz a{position:relative}.-tf .-tv:before{content:'';position:absolute;left:-1px;bottom:0;width:calc(100% + 2px);height:150px;background:linear-gradient(0deg,rgba(0,0,0,.12),transparent);z-index:1}.-tf .-tm{margin-top:1.5rem;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;color:#20202a;font-size:1rem;margin:0}.-tg{max-width:100%}@media (min-width:768px){.-tg{grid-column:1/-1}}@media (min-width:1024px){.-tg{grid-column:4/22}}.-ty{width:100%;margin-bottom:30px}.-ty>h1,.-ty>h2,.-ty>h3,.-ty>h4,.-ty>h5,.-ty>h6{grid-column:1/14}.-ty .-n{grid-column:16/22}.-tb{grid-column:1/-1;overflow-x:scroll;-webkit-overflow-scrolling:touch;width:auto;display:flex;flex-wrap:nowrap;padding:20px 0;margin:0 -20px}@media (min-width:575px){.-tb{overflow:visible;width:100%;display:grid;grid-gap:30px;grid-template-columns:1fr;grid-template-columns:repeat(2,1fr);grid-template-rows:auto;padding:0;margin:0}}@media (min-width:768px){.-tb{grid-template-columns:repeat(2,1fr)}}@media (min-width:1024px){.-tb{grid-template-columns:repeat(3,1fr)}}@media (min-width:768px){.-tk,.-tw,.-tx{grid-template-columns:repeat(4,1fr)}}.-tk .-tm,.-tw .-tm,.-tx .-tm{font-size:1rem}.-t_{margin-bottom:7em}@media (min-width:768px){.-t_{margin-bottom:calc(16vw + 6em)}}.-tj{grid-column:1/-1;width:100%;height:auto;display:grid;grid-gap:0;grid-template-columns:32fr 5fr 4fr 10fr 7fr 10fr 8fr;grid-template-rows:8fr 26fr 6fr 11fr 11fr 12fr 26fr}@media (min-width:768px){.-tj{grid-template-columns:32fr 5fr 4fr 10fr 7fr 10fr 8fr 24fr}}.-tq{grid-column:3/16;font-size:1.65rem;margin-top:0}@media (min-width:768px){.-tq{font-size:2.125rem}}@media (min-width:1024px){.-tq{font-size:4rem}}.-ne,.-tz:hover{z-index:2;transform:translateY(-2%);transition:transform .3s cubic-bezier(.25,.1,.25,1)}.-tz:hover .-ne{opacity:1;transform:translateY(0)}.-tz a{display:block}.-tz amp-img{transition:box-shadow .3s cubic-bezier(.25,.1,.25,1)}.-ne{width:100%;padding:0 2em;position:absolute;left:0;bottom:0;opacity:0;background:#fff;z-index:1;pointer-events:none;transform:translateY(10px)}@media (max-width:1023px){.-ne{display:none}}.-nt{grid-column:1/3;grid-row:2/6}.-nt amp-img{box-shadow:0 6.6vw 7vw 0 rgba(0,0,0,.5)}.-nt amp-img:hover{box-shadow:0 7.6vw 8vw 0 rgba(0,0,0,.4)}.-nn{grid-column:4/8;grid-row:1/4}.-nn amp-img{box-shadow:0 2.3vw 4.2vw -.7vw rgba(0,0,0,.33)}.-nn amp-img:hover{box-shadow:0 3.3vw 5.2vw -.7vw rgba(0,0,0,.23)}.-nr{grid-column:5/8;grid-row:3/7}@media (min-width:768px){.-nr{grid-column:7/9;grid-row:3/7}}.-nr amp-img{box-shadow:0 1.4vw 2.8vw 1.4vw rgba(0,0,0,.2)}.-nr amp-img:hover{box-shadow:0 2.4vw 3.8vw 1.4vw rgba(0,0,0,.1)}.-ni{grid-column:2/6;grid-row:5/8}.-ni amp-img{box-shadow:0 .3vw 1vw 0 rgba(0,0,0,.2)}.-ni amp-img:hover{box-shadow:0 1.3vw 2vw 0 rgba(0,0,0,.1)}.-ns{padding:40px 20px 0;grid-column:1/-1;grid-row:auto}@media (min-width:768px){.-ns{grid-column:6/9;grid-row:7/8;padding:12% 24% 0 12%}}.ap--sampler{margin-bottom:7em}@media (max-width:320px){.ap--sampler{display:none}}@media (min-width:768px){.ap--sampler{margin-bottom:8vw}}.ap--sampler .ap-m-copy{grid-column:3/13;padding:0 20px;margin-bottom:1.5em}@media (min-width:768px){.ap--sampler .ap-m-copy{padding-left:20px;margin-bottom:3em}}@media (min-width:1680px){.ap--sampler .ap-m-copy{grid-column:5/13}}.ap--sampler .ap-m-copy-center{grid-column:6/20}.ap--sampler .ap-m-copy-center h2{font-size:2.5rem;margin:0}@media (min-width:768px){.ap--sampler .ap-m-copy-center h2{font-size:3.5rem}}.ap--sampler .ap-m-copy-center .ap-a-ico{width:4em;height:4em;margin:0 auto .5em}.ap-o-sampler{grid-column:3/-1;width:100%;max-width:1024px;padding-left:20px}@media (min-width:1680px){.ap-o-sampler{grid-column:5/-3;padding-left:0}}.ap-o-sampler-header{background:linear-gradient(225deg,#29323c,#485563 75%);font-size:.8125rem;font-family:Poppins,sans-serif;font-weight:700;color:#fff;padding:1.125em 1.75em}.ap-o-sampler-tab-bar{display:flex;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:nowrap;background:#29323c}.ap-o-sampler-tab{cursor:pointer;padding:1.125em 1.75em;border-right:1px solid #3d444d;background:#29323c}.ap-o-sampler-tab.active{background:#3d444d}.ap-o-sampler-tab.active span{opacity:1}.ap-o-sampler-tab-title{font-size:.8125rem;font-family:Poppins,sans-serif;font-weight:700;color:#fff;opacity:.5}.ap-o-sampler-iframe{width:100%;height:auto;background:linear-gradient(45deg,#48525c,#101923);box-shadow:0 15px 50px 0 rgba(0,0,0,.4)}.ap-o-sampler-iframe [placeholder]{display:flex}[placeholder] .ap-o-sampler-iframe-source{width:calc(50% - 4px)}.ap-o-sampler-link{margin-top:1em;display:inline-block}.-no{grid-template-columns:5% auto 5%;grid-template-rows:50fr auto 15fr}.-no .-nu:before{border-color:#e1eb64}.-no .-nu:after{background:linear-gradient(225deg,#64bf46 0,#e1eb64 75%)}.-na{grid-template-columns:12% auto 12%;grid-template-rows:16fr auto 9fr}.-na .-nu:before{border-color:#eb49e1}.-na .-nu:after{background:linear-gradient(225deg,#eb49e1 0,#5500d7 75%)}.-nf{grid-template-columns:5% auto 5%;grid-template-rows:17fr auto 7fr}.-nf .-nl{max-width:11em}@media (min-width:768px){.-nf .-nl{max-width:100%}}.-nf .-nu{max-width:12em;box-shadow:0 20px 20px 0 rgba(0,0,0,.05)}.-nf .-nu:before{border-color:#ffdc00}.-nf .-nu:after{background:linear-gradient(225deg,#ff8f00 0,#ffdc00 75%)}@media (min-width:768px){.-nf .-nu{max-width:100%}}.-nc{display:flex;overflow-x:auto;margin:1.1rem 0 0;padding:0 1em;color:#fff;line-height:1.3em;background:#29323c;font-size:.9em}.-nc::after{content:'\\00a0\\00a0\\00a0\\00a0\\00a0';-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.-nc::-webkit-scrollbar{width:4px;height:4px}.-nc::-webkit-scrollbar-thumb{background-color:#91979d}.-nc::-webkit-scrollbar-corner{background-color:transparent}@media (min-width:768px){.-nc{max-width:100%;margin-right:-30px}}.-nc pre{font-family:'Fira Mono',monospace;font-weight:500;white-space:pre;font-size:.9rem}.-nc .hll{background-color:#49483e}.-nc .c{color:#75715e}.-nc .k{color:#66d9ef}.-nc .l{color:#ae81ff}.-nc .n{color:#f8f8f2}.-nc .o{color:#f15a5a}.-nc .p{color:#f8f8f2}.-nc .c1,.-nc .ch,.-nc .cm,.-nc .cp,.-nc .cpf,.-nc .cs{color:#75715e}.-nc .gd{color:#f15a5a}.-nc .ge{font-style:italic}.-nc .gi{color:#a6e22e}.-nc .gs{font-weight:700}.-nc .gu{color:#75715e}.-nc .kc,.-nc .kd{color:#66d9ef}.-nc .kn{color:#f15a5a}.-nc .kp,.-nc .kr,.-nc .kt{color:#66d9ef}.-nc .ld{color:#e6db74}.-nc .m{color:#ae81ff}.-nc .s{color:#e6db74}.-nc .na{color:#a6e22e}.-nc .nb{color:#f8f8f2}.-nc .nc{color:#a6e22e}.-nc .no{color:#66d9ef}.-nc .nd{color:#a6e22e}.-nc .ni{color:#f8f8f2}.-nc .ne,.-nc .nf{color:#a6e22e}.-nc .nl,.-nc .nn{color:#f8f8f2}.-nc .nx,section.-t.benefits.ads .-r,section.-t.benefits.ads h3-text,section.-t.benefits.websites .-r,section.-t.benefits.websites h3-text{color:#fff}.-nc .py{color:#f8f8f2}.-nc .nt{color:#f15a5a}.-nc .nv{color:#f8f8f2}.-nc .ow{color:#f15a5a}.-nc .w{color:#f8f8f2}.-nc .mb,.-nc .mf,.-nc .mh,.-nc .mi,.-nc .mo{color:#ae81ff}.-nc .dl,.-nc .s2,.-nc .sa,.-nc .sb,.-nc .sc,.-nc .sd{color:#e6db74}.-nc .se{color:#ae81ff}.-nc .s1,.-nc .sh,.-nc .si,.-nc .sr,.-nc .ss,.-nc .sx{color:#e6db74}.-nc .bp{color:#f8f8f2}.-nc .fm{color:#a6e22e}.-nc .vc,.-nc .vg,.-nc .vi,.-nc .vm{color:#f8f8f2}.-nc .il{color:#ae81ff}.-nh{padding:0;grid-template-columns:11.1fr 32.4fr 18.1fr 32.1fr 7fr;grid-template-rows:3.5fr 56.3fr 25.1fr 12.3fr 3.3fr}.-nh:after{transform-origin:left bottom;animation:10s ease-in-out 3.5s infinite both rotateShadow}.-nh .-nl{grid-column:2/5;grid-row:1/5;max-width:8.125em;transform:translate3d(0,3%,0) scale(.9);animation:none}@media (min-width:768px){.-nh .-nl{max-width:100%}}.-nh .-nu{grid-column:3/6;grid-row:2/6;max-width:5.625em;box-shadow:20px 40px 60px -5px rgba(0,0,0,.25);animation:10s ease-in-out 3.5s infinite both slide}.-nh .-nu:before{border-color:#21c1fa}.-nh .-nu:after{background:linear-gradient(225deg,#00dcc0 0,#005af0 75%)}@media (min-width:768px){.-nh .-nu{max-width:100%}}.-nh .-np{font-size:.9rem}.-nh .-nd{position:relative;color:#e6db74}.-nh .-nd span{position:absolute;left:0;top:0}.-nh .-nd span::before{content:'';position:absolute;display:block;width:calc(100% - 25px);height:100%;top:-1px;left:8px;z-index:-1;background-color:#ff52e1;animation:10s ease-in-out 3.5s infinite both handleCodeMarker}.-nh .-nd span::after{content:'>';color:#fff}.-nh .-nd span:nth-child(1){animation:10s ease-in-out 3.5s infinite both handleValueRight}.-nh .-nd span:nth-child(2){animation:10s ease-in-out 3.5s infinite both handleValueEmpty}.-nh .-nd span:nth-child(3){animation:10s ease-in-out 3.5s infinite both handleValueLeft}.-nv .-nm{grid-column:11/-1;position:absolute;left:50%;top:0;margin-left:-30%}@media (min-width:768px){.-nv .-nm{position:static;margin-top:-50%;margin-left:auto;margin-right:auto}}@media (min-width:1024px){.-nv .-nm{margin-top:-40%}}.-nm{width:100%;max-width:16em;padding:1.5em 0;margin:0 auto;transform:rotate3d(135,-90,90,50deg);display:grid}@media (min-width:768px){.-nm{width:50%;max-width:100%;position:relative;padding:0;margin-bottom:5em}}.-ng,.-nm:after{width:100%;height:auto}.-nm:after{content:'';position:absolute;bottom:0;left:0;padding-top:75%;border-radius:1000% 0 0 0;opacity:.5;transform:rotate(-5deg) scale(1,1.1) skew(-25deg);transform-origin:center;background:linear-gradient(-225deg,transparent 30%,#000);filter:blur(20px);z-index:-1}@media (min-width:768px){.-nm:after{padding-top:100%;transform-origin:right bottom}}.-ng{margin:auto}.-nl{position:relative;grid-column:2/3;grid-row:1/4;max-width:9em;filter:drop-shadow(0 20px 40px rgba(0,0,0,.15))}@media (min-width:768px){.-nl{max-width:100%}}.-nu{position:relative;grid-column:1/4;grid-row:2/3;max-width:11em;box-shadow:30px 90px 60px -40px rgba(0,0,0,.5);animation:10s ease-in-out infinite bounce -4s}.-nu:before{content:'';width:100%;height:100%;position:absolute;left:-3px;top:-3px;border:3px solid #21c1fa}@media (min-width:768px){.-nu:before{left:-4px;top:-4px;border-width:4px}}@media (min-width:1024px){.-nu:before{left:-5px;top:-5px;border-width:5px}}.-nu:after{line-height:1.6rem;font-family:'Fira Mono',monospace;font-weight:700;color:#fff;content:attr(title);position:absolute;left:-3px;bottom:100%;padding:3px 6px;font-size:8px;background-color:#21c1fa}@media (min-width:768px){.-nu:after{left:-4px;padding:5px 10px;font-size:1.25vw}}@media (min-width:1024px){.-nu:after{left:-5px}}@media (min-width:1280px){.-nu:after{font-size:inherit}}@media (min-width:768px){.-nu{max-width:100%}}.-np{grid-column:1/-1;grid-row:1/-1;width:auto;margin:auto auto 0;font-size:10px;transform:translate(75%,-4em)}@media (min-width:768px){.-np{font-size:1.25vw;transform:translate(50%,-75px)}}.-np .-nc{margin:0;box-shadow:15px 30px 45px -5px rgba(0,0,0,.25);animation:10s ease-in-out infinite bounce}.ap-m-copy{margin-bottom:3em}.ap-m-copy.no-margin{margin-bottom:0}.ap-m-copy p{line-height:1.6rem;font-weight:400;color:#48525c}.ap-m-copy-large p{font-size:1rem}.ap-m-copy-left{grid-column:3/17}.ap-m-copy-left-small{grid-column:4/13}.ap-m-copy-left-link{grid-column:3/12;margin-top:3em}.ap-m-copy-left-xsmall{grid-column:6/13}.ap-m-copy-right{grid-column:10/24}.ap-m-copy-right-centered{width:100%;grid-column:16/21;margin:auto 0}.ap-m-copy-right-small{grid-column:11/20}.ap-m-copy-right-link{grid-column:10/19;margin-top:3em}@media (min-width:768px){.ap-m-copy-right-xsmall{grid-column:8/20}}@media (min-width:1024px){.ap-m-copy-right-xsmall{grid-column:12/20}}.ap-m-copy-center{grid-column:1/-1;text-align:center}.ap-m-copy-center-small{grid-column:6/19;text-align:left}.ap-m-copy-center-large,.ap-m-copy-center-medium{grid-column:4/22;text-align:left;max-width:100%}.ap-m-copy-center-large{grid-column:3/22}.ap--news{background:linear-gradient(30deg,#fff 30%,#ebebf0 100%);margin-bottom:5em}@media (min-width:768px){.ap--news{margin-bottom:8vw}}.ap--news .ap-m-copy{padding:2.5em 1.25em 0;margin:0 0 2em}@media (min-width:768px){.ap--news .ap-m-copy{grid-column:2/11;padding:0;margin:auto 0}}@media (min-width:1024px){.ap--news .ap-m-copy{grid-column:3/10}}@media (min-width:1280px){.ap--news .ap-m-copy{grid-column:3/9}}.ap--news .ap-m-copy h2{margin-top:0;margin-bottom:.375em}.ap--news .ap-m-copy p{font-size:.875rem;margin-top:0;margin-bottom:2em}@media (min-width:768px){.ap--news .ap-m-copy p{margin-bottom:3.75em}}.-ny{grid-column:11/-1;width:100%}.-nb{overflow-x:scroll;-webkit-overflow-scrolling:touch;display:flex;flex-wrap:nowrap;width:auto}.-nw{flex:1 0 20em;display:block;padding:0 2em 0 0;margin:2.125em 0 4.125em;transition:transform .3s cubic-bezier(.25,.1,.25,1)}@media (min-width:768px){.-nw{padding:0 0 0 2em}}.-nw:last-child{padding-right:0}.-nw:hover{transform:translateY(-.125em)}.-nw:hover>div{box-shadow:0 25px 60px 0 rgba(0,0,0,.1)}.-nx{display:flex;flex-direction:column;height:100%;background:#fff;box-shadow:0 15px 30px 0 rgba(0,0,0,.15);transition:box-shadow .3s cubic-bezier(.25,.1,.25,1)}.-nk{line-height:1.6rem;font-size:.8125rem;font-weight:700;text-transform:uppercase;padding:.625em 24px;color:#48525c}.-n_{width:100%;background-color:#005af0}.-n_ img{object-fit:cover}.-nj,.-nq{padding:0 24px;margin-top:1.375em}.-nq{line-height:1.6rem;font-weight:400;font-size:.875rem;margin-top:auto;margin-bottom:1.5em;color:#48525c}.-nz,.-nz .ap-a-ico{display:flex;justify-content:center}.-nz{height:100%;width:100%;align-items:center;fill:#fff;padding:calc(28.125% - 2em) 0}.-nz .ap-a-ico{font-size:initial;box-sizing:initial;width:4em;height:4em}.-nv .-re{grid-column:1/-1;width:150vw;margin-top:-40%;margin-right:-150vw;pointer-events:none}@media (min-width:768px){.-nv .-re{width:100%;margin-top:-30%;margin-right:0}}.-rt{overflow:hidden;margin-bottom:7em}@media (min-width:768px){.-rt{margin-bottom:8vw}}.-ii h2,.-rt .ap-m-copy h3{margin-top:0}.-re,.-rn{width:100%;height:auto}.-re{grid-column:1/-1;max-width:1680px;display:grid;grid-gap:0;grid-template-columns:17fr 5.5fr 3fr 9fr 7fr 12.5fr 3fr 9fr 4fr 12.5fr 6fr 10.5fr;grid-template-rows:19fr 6fr 12.5fr 12.5fr 25fr 5fr 5fr 5fr 5fr 5fr;padding:7vw 0 11vw;transform:perspective(100px) rotate(.1deg) rotateY(-.1deg) skewX(-4deg) skewY(0) translateX(6.3%);transform-origin:center}.-rn{margin-top:auto;animation:levitate 7s ease-in-out infinite forwards}@media (prefers-reduced-motion:reduce){.-rn{animation:none}}.-rn:nth-child(1){grid-column:2/5;grid-row:1/8;animation-delay:-5s}.-rn:nth-child(2){grid-column:1/3;grid-row:2/10;animation-delay:-6s}.-rn:nth-child(3){grid-column:8/12;grid-row:3/7;animation-delay:-2s}.-rn:nth-child(4){grid-column:6/9;grid-row:2/11;animation-delay:-3s}.-rn:nth-child(5){grid-column:4/7;grid-row:4/9;animation-delay:-4s}.-rn:nth-child(6){grid-column:10/12;grid-row:4/10;animation-delay:-1s}.-rn:nth-child(7){grid-column:11/13;grid-row:1/6;animation-delay:0s}.-rr{display:inline-block}@media (min-width:768px){.-ri{display:inline-block;width:10px}}.-rs{display:grid;grid-template-columns:1fr;grid-template-rows:1fr}.-ro{grid-column:1/-1;grid-row:1/-1;margin-right:auto;animation:roll 8s cubic-bezier(.25,.1,.25,1) 1s infinite backwards}@media (min-width:768px){.-ro{margin-left:auto}}@media (min-width:1024px){.-ro{margin-left:0}}.-ro:nth-child(2){animation-delay:3s;opacity:0}.-ro:nth-child(3){animation-delay:5s;opacity:0}.-ro:nth-child(4){animation-delay:7s;opacity:0}.-nv{overflow:hidden}.-ru{background:linear-gradient(225deg,#00dcc0 0,#005af0 75%);grid-column:1/-1;position:relative;width:100%;margin-left:30px;border-bottom-left-radius:4em;-webkit-clip-path:polygon(0 0,100% 0,100% calc(100% - 2em),4em 100%,0 100%);clip-path:polygon(0 0,100% 0,100% calc(100% - 2em),4em 100%,0 100%)}@media (min-width:768px){.-ru{margin-left:64px;border-bottom-left-radius:6.25em;-webkit-clip-path:polygon(0 0,100% 0,100% calc(100% - 3em),6.25em 100%,0 100%);clip-path:polygon(0 0,100% 0,100% calc(100% - 3em),6.25em 100%,0 100%)}}.-ru div.-ra{padding:0 2em}@media (min-width:768px){.-ru div.-ra{padding:0 2.5em;margin-left:-64px}}.-rf{position:relative;margin:10vw 0 22vw}@media (min-width:768px){.-rf{grid-column:3/13;margin:7vw 0 11vw 3em}}@media (min-width:1024px){.-rf{grid-column:3/19;margin-left:5em}}@media (min-width:1280px){.-rf{grid-column:3/16}}.-rl{fill:#fff;display:flex;font-size:initial;box-sizing:initial;justify-content:center;width:1.375em;height:1.375em;position:absolute;left:0;bottom:calc(100% + 1em);padding:.5em;border:1px solid #fff;border-radius:50%}@media (min-width:768px){.-rl{left:auto;bottom:auto;right:calc(100% + .75em);top:-.6em}}@media (min-width:1024px){.-rl{width:3em;height:3em;right:calc(100% + 1em);top:-1.5em;padding:1em;border-width:2px}}.-rc{margin-top:1.5rem;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;font-size:1.65rem;color:#fff;margin:0}@media (min-width:768px){.-rc{font-size:2.125rem}}@media (min-width:1024px){.-rc{font-size:4rem}}@media (min-width:768px){.-rc br{display:none}}.-rh{line-height:1.6rem;font-weight:400;font-size:1rem;color:#fff;margin-top:0;margin-bottom:.75em}@media (min-width:768px){.-rh{font-size:.875rem}}@media (min-width:1024px){.-rh{font-size:1.125rem}}.-rp{color:#005af0;background-color:#fff;margin-top:20px}.-rd{margin-bottom:7em}@media (min-width:768px){.-rd{margin-bottom:8vw}}.-rv{grid-column:6/20;display:flex;flex-direction:column}@media (min-width:768px){.-rv{flex-direction:row}}.-rm{flex:0 0 auto;display:flex;width:80%;align-items:flex-start}@media (min-width:768px){.-rm{flex:0 0 30%;width:100%;flex-direction:column;align-items:flex-end}}.-rm .ap-a-img{position:relative;width:150px;height:30px}.-rm .ap-a-img amp-img.contain img{object-fit:contain;object-position:right top}.-rm .ap-a-ico{width:40px;height:40px;margin:0 1em 0 0;fill:#005af0}@media (min-width:768px){.-rm .ap-a-ico{width:100px;height:100px;margin:0 0 .5em auto}}.-rg{padding:0 0 0 3.375em}@media (min-width:768px){.-rg{padding:50px 0 0 30px}}.-rg blockquote{flex:0 0 70%;margin:0 0 2em}.-rg blockquote p.ap-a-txt{margin-top:1.5rem;margin-bottom:.75em;font-family:Poppins,sans-serif;font-weight:700;color:#20202a;font-size:1rem;line-height:1.8;font-style:italic;display:block}@media (min-width:768px){.-rg blockquote p.ap-a-txt{font-size:1.2rem;line-height:2}}.-rg blockquote p.ap-a-txt:before{content:'\\201C'}.-rg blockquote p.ap-a-txt:after{content:'\\201D'}.-rg p{line-height:1.6rem;font-weight:400;color:#48525c;font-size:.8125rem}@media (min-width:768px){.-rg p{font-size:.875rem}}.-ry{display:block;width:100%;height:1px;margin-bottom:.813em;background-color:#fafafc}@media (min-width:768px){.-ry{display:none}.-rb{display:block}}section.-t.benefits.ads .-i,section.-t.benefits.ads h3-icon,section.-t.benefits.websites .-i,section.-t.benefits.websites h3-icon{fill:#005af0;background:#fff}section.-t.benefits.e-mails .-r,section.-t.benefits.e-mails h3-text,section.-t.benefits.stories .-r,section.-t.benefits.stories h3-text{color:#000}.-rw{position:relative;display:flex;margin:20px}@media (min-width:768px){.-rw{padding:0;margin:50px 0;flex:0 0 calc(33.333333333% - 40px)}}.-rx{width:2.5em;height:2.5em;fill:#005af0;margin-right:10px}.-rk{display:flex;flex-direction:column}.-r_,.-rj{line-height:1.6rem;font-weight:700;color:#000;margin-bottom:.3em}.-rj{font-weight:400;color:#48525c;font-size:.875rem;margin-bottom:10px}.-rq{background:linear-gradient(225deg,#00dcc0 0,#005af0 75%)}.-rz{box-shadow:0 50px 100px 0 rgba(0,0,0,.25);z-index:1}@media (min-width:768px){.-rz{margin-left:55px}}.-ie{box-shadow:0 25px 50px 0 rgba(0,0,0,.21)}.-it{padding:45px 50px}.-in{width:60px;height:4px;background-color:#005af0}@media (min-width:1024px){.-in{margin-bottom:3em}}.ap--benefits-overview{margin-bottom:7em}@media (min-width:1024px){.ap--benefits-overview{margin-bottom:8vw}}.-ir{grid-column:1/16}@media (min-width:1024px){.-ir{grid-column:1/12}}@media (min-width:1280px){.-ir{grid-column:1/10}}.-ii{grid-column:1/13}.-ii .-rw{margin:20px 20px 0 0}.-ii .-rx{margin-right:15px}.-ii .-rw.principles{margin:50px 20px 100px 0}@media (min-width:1024px){.-is{grid-column:2/10}}.-io{grid-column:13/25}@media (min-width:768px){.-io{margin-top:5em}}@media (min-width:1024px){.-io{grid-column:14/22}.-iu{grid-column:3/10}}.-ia{grid-column:17/-1;width:100%;margin-top:2em}@media (min-width:768px){.-ia{width:auto;margin-top:0}}.ap--format-explainer{overflow:hidden;padding-left:20px;padding-right:20px;margin-bottom:7em}@media (min-width:1024px){.ap--format-explainer{padding-left:0;padding-right:0;margin-bottom:8vw}}.ap-o-format-explainer .swift>div{transform:translateX(7.5%)}.ap-o-format-explainer .swift>div.active{transform:translateX(0);transition-delay:.4s}.ap-o-format-explainer-group{display:grid;grid-template-columns:1fr;grid-template-rows:1fr}.ap-o-format-explainer-group>div{grid-column:1/-1;grid-row:1/-1;opacity:0;visibility:hidden;transition:opacity .4s cubic-bezier(.55,0,.1,1),visibility .4s cubic-bezier(.55,0,.1,1),transform .4s cubic-bezier(.55,0,.1,1)}.ap-o-format-explainer-group>div.active{opacity:1;visibility:visible}.ap-o-format-explainer-visual{grid-column:1/-1;grid-row:1/4;order:2;position:relative;width:100%;padding:0 1.5em}@media (min-width:1024px){.ap-o-format-explainer-visual{grid-column:1/14;order:inherit;padding:7em 0 0}}.ap-o-format-explainer-visual .-nm{margin-bottom:0}.ap-o-format-explainer-content{align-items:end;grid-column:1/-1;width:100%;margin-bottom:0}.ap-o-format-explainer-navigation{grid-column:1/-1}@media (min-width:1024px){.ap-o-format-explainer-content,.ap-o-format-explainer-navigation{grid-column:14/24}}@media (min-width:1280px){.ap-o-format-explainer-content,.ap-o-format-explainer-navigation{grid-column:14/22}}.-tg .ap-m-copy h2,.ap-o-format-explainer-headline{margin-top:0}.ap-o-format-explainer-copy{margin-bottom:0}.ap-o-format-explainer-navigation{order:2;overflow-y:hidden;overflow-x:scroll;-webkit-overflow-scrolling:touch;display:flex;flex-wrap:nowrap;width:auto;padding:0 20px 15px;margin:0 -20px 15px}@media (min-width:1024px){.ap-o-format-explainer-navigation{order:inherit;overflow:visible;flex-direction:column;max-width:300px;padding:0;margin:0}}.ap-o-format-explainer-navigation:after{content:'';padding-right:1px}.ap-o-format-explainer-button{margin-top:1.5rem;font-family:Poppins,sans-serif;font-weight:700;color:#20202a;font-size:1rem;line-height:1;-webkit-appearance:none;min-width:160px;display:flex;align-items:center;padding:10px 15px;margin:0 15px 1em 0;text-align:left;background-color:#ebebf0;border:0;border-radius:4px;cursor:pointer}@media (min-width:1024px){.ap-o-format-explainer-button{margin:0 0 1em;background:0 0}}.ap-o-format-explainer-button.active{color:#fff;box-shadow:0 10px 25px -5px rgba(0,0,0,.25)}.ap-o-format-explainer-button:hover{background-color:#ebebf0}.ap-o-format-explainer-button-websites.active{background:linear-gradient(225deg,#00dcc0 0,#005af0 75%)}.ap-o-format-explainer-button-stories.active{background:linear-gradient(225deg,#ff8f00 0,#ffdc00 75%)}.ap-o-format-explainer-button-ads.active{background:linear-gradient(225deg,#eb49e1 0,#5500d7 75%)}.ap-o-format-explainer-button-email.active{background:linear-gradient(225deg,#64bf46 0,#e1eb64 75%)}.ap-o-format-explainer-button-icon{width:30px;height:30px;margin-right:14px}.ap-o-format-explainer-button-icon.active{fill:#fff}.ap-o-format-explainer-link{grid-column:1/-1;order:3}@media (min-width:1024px){.ap-o-format-explainer-link{grid-column:14/20;order:inherit}}.ap--main>.-if:first-child{padding-top:26px;padding-bottom:3rem}.-if{position:relative;display:flex;flex-wrap:wrap;width:100%;max-width:1440px;padding:0 20px;margin-left:auto;margin-right:auto}@media (max-width:767px){.-if{padding:0 15px}}@media (min-width:768px){.-if{display:grid;grid-gap:30px;grid-template-columns:repeat(24,minmax(0,1fr));padding:0 30px}}.-ra{position:relative;display:flex;flex-wrap:wrap;width:100%;padding:0;margin-left:auto;margin-right:auto;max-width:1920px}@media (min-width:768px){.-ra{display:grid;grid-gap:30px;grid-template-columns:repeat(24,minmax(0,1fr));padding:0}}.-nv .-rf{margin-bottom:42vw}@media (min-width:768px){.-nv .-rf{grid-column:3/23;margin-bottom:23vw;text-align:center}}@media (min-width:1024px){.-nv .-rf{grid-column:4/22}}@media (min-width:1280px){.-nv .-rf{grid-column:5/21}}@media (min-width:1920px){.-nv .-rf{margin-bottom:28em}}.-nv .-rc{font-size:1.65rem}@media (min-width:768px){.-nv .-rc{font-size:3.25rem}}.-nv .-ru .-if{padding-left:0}.-tg{flex-direction:column-reverse;margin-bottom:7em}.-tg .-ty{grid-column:1/15;display:block;width:100%;margin-bottom:0}@media (min-width:768px){.-tg .-ty{margin-top:-6em}}@media (min-width:1024px){.-tg .-ty{grid-column:2/14}}@media (min-width:1280px){.-tg .-ty{grid-column:1/13}}@media (min-width:575px){.-tg .-tb{grid-template-columns:repeat(2,1fr);grid-template-rows:repeat(5,1fr)}}.-tg .-tl{grid-column:1;margin-bottom:1em}.-tg .-tl:nth-child(2n){grid-column:2}.-tg .-tl:nth-child(1){grid-row:2/4}.-tg .-tl:nth-child(2){grid-row:1/3}.-tg .-tl:nth-child(3){grid-row:4/6}.-tg .-tl:nth-child(4){grid-row:3/5}.-tg .ap-m-copy{grid-column:16/25}@media (min-width:1024px){.-tg .ap-m-copy{grid-column:15/24}}@media (min-width:1280px){.-tg .ap-m-copy{grid-column:14/23}}.-tg .ap-m-copy p{margin-bottom:2em}@media (min-width:768px){.-tg .ap-m-copy p{margin-bottom:6em}}.ap--newsletter-double{display:none}.amp-geo-group-doubleOptIn .ap--newsletter-double,.amp-geo-pending .ap--newsletter-double,.ap--newsletter{display:flex}.amp-geo-group-doubleOptIn .ap--newsletter,.amp-geo-pending .ap--newsletter{display:none}.ap--shift-cards{background:#fafafc}.ap--shift-cards-grid{grid-template-rows:100px auto 100px}.ap--shift-cards-headline{grid-column:1/-1;width:100%;margin-bottom:.75em;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;color:#20202a;font-size:2.2rem;margin-top:3rem;text-align:center;margin-top:0}.ap--get-started{padding:2.5em 30px 3em}@media (min-width:768px){.ap--get-started{padding:6em 0 7em}}.ap--get-started h2{font-size:2.2rem;margin-top:3rem;margin-top:0}.ap--get-started .ap-m-copy{width:100%;margin-bottom:0}.-il{z-index:9999}.-ic{position:fixed;left:0;top:0;right:0;bottom:0;opacity:.6;background:#000}.-ih{position:relative;width:90vw;padding:23px 0 0;margin:0;background:#fafafc;box-shadow:0 2px 50px 0 rgba(0,0,0,.5)}@media (min-width:1024px){.-ih{width:100%;max-width:900px;padding:32px 60px 0;margin:0 auto}}@media (min-width:1280px){.-ih{max-width:1060px;padding:32px 140px 0}}@media (min-width:1440px){.-ih{max-width:1200px;padding:32px 210px 0}}.-ip{position:relative;z-index:2}.-id,.-iz svg{width:100%}@media (max-width:1023px){.-id{width:calc(100% - 40px);left:15px}}.-id div[role=listbox]{width:100%;max-height:210px;margin-top:-4px;margin-left:0;border-radius:0 0 4px 4px;box-shadow:0 15px 20px 0 rgba(0,0,0,.1)}.-id div[role=listbox]:not(:empty)::before{content:'';display:block;position:sticky;position:-webkit-sticky;left:10px;top:0;width:calc(100% - 20px);height:1px;background:#ceced2;z-index:1}@media (min-width:1024px){.-id div[role=listbox]:not(:empty)::before{left:60px;width:calc(100% - 90px)}}.-id div[role=option]{padding:14px 60px;font-family:Poppins,sans-serif;font-weight:700;color:#20202a}@media (max-width:1023px){.-id div[role=option]{padding:14px 40px}}.-id div[role=option]:hover,.-id div[role=option][aria-selected=true],.-iv{color:#005af0;background:0 0}.-iv{font-family:Poppins,sans-serif;font-weight:700;color:#20202a;font-size:1.8rem;margin-top:2rem;line-height:1.4em;width:100%;padding:18px 160px 18px 60px;margin:0;border:0;border-radius:4px}@media (max-width:1023px){.-iv{font-size:1.125rem;padding:20px 20px 20px 40px}}.-iv::-webkit-input-placeholder{color:#ceced2}.-iv::-moz-placeholder{color:#ceced2}.-iv:focus{outline:0;background:#fff;box-shadow:0 15px 20px 0 rgba(0,0,0,.1)}.-im{position:absolute;left:30px;top:32px;width:17px;height:17px}@media (max-width:1023px){.-im{width:18px;height:18px;left:11px;top:23px}}.-ig{margin-top:1.5rem;font-family:Poppins,sans-serif;font-weight:700;line-height:1.2em;font-size:1em;color:#fff;display:inline-block;max-width:100%;width:auto;height:auto;padding:.75em 1.75em;margin:0;text-decoration:none;text-align:center;border-radius:3px;background-color:#005af0;border:0;cursor:pointer;box-shadow:0 15px 35px -5px rgba(0,0,0,.25);transition:transform .3s cubic-bezier(.25,.1,.25,1),box-shadow .3s cubic-bezier(.25,.1,.25,1);opacity:0;pointer-events:none;position:absolute;top:11px;right:10px;box-shadow:none}.-ig:hover{transform:translateY(-.125em);box-shadow:0 25px 20px -15px rgba(0,0,0,.15);box-shadow:none}@media (min-width:768px){.-ig{padding:.75em 1.75em}}@media (min-width:1024px){.-ig{top:13px;right:30px;padding:1em 2em}}.-ig[disabled]{background-color:#ccc;transform:none}@media (min-width:1024px){.-ig:focus,.-iv:focus+.-ig{opacity:1;pointer-events:auto}}.-iy{overflow-x:hidden;overflow-y:auto;height:100vh;min-height:60vh;max-height:calc(100vh - 88px);padding:0 0 30px;-webkit-overflow-scrolling:touch;outline:0}@media (min-width:1024px){.-iy{max-height:calc(100vh - 108px);margin-right:30px}.-iy::-webkit-scrollbar{width:4px}.-iy::-webkit-scrollbar-thumb{background:#eaeaea}}.-iy::before{content:'';display:block;height:2em;position:sticky;position:-webkit-sticky;top:0;background:linear-gradient(0deg,rgba(250,250,252,0) 0,#fafafc 100%);z-index:1}.-iy .amp-active{position:relative;height:60vh}.-ib:last-child .-iw:last-child{margin-bottom:30px}.-ib .-ix{margin-top:30px}.-ik{padding:30px 0 0;margin:1.5rem 25px 10px;color:#ceced2;border-top:1px solid #ceced2}@media (min-width:1024px){.-ik{margin:1.5rem 60px 10px}}.-ik:first-child{margin-top:0;padding:0;border:0}.-iw{margin:0 10px;border-radius:4px}@media (min-width:1024px){.-iw{margin:0 45px}.-iw:hover{background:#fff;box-shadow:0 15px 20px 0 rgba(0,0,0,.1)}}@media (max-width:1023px){.-i_{margin:10px 25px;background:#fff;box-shadow:0 15px 20px 0 rgba(0,0,0,.1)}}.-iw .-ij:focus .-iq,.-iw:hover .-iq{opacity:1}.-iw:focus-within .-iq{opacity:1}.-ij{display:block;padding:15px;line-height:1.6rem;font-weight:400;color:#48525c}.-iq{display:flex;justify-content:flex-end;padding:0 0 5px;margin:0 15px;border-top:1px solid #e8e8e9}@media (min-width:1024px){.-iq{padding:0;margin-top:-15px;border:0;opacity:0}}.-iz{padding:0}@media (min-width:1024px){.-iz{padding-bottom:5px;margin-right:1.5rem}}.-iz .-r{font-size:.75rem}.-iz .-i{width:12px;height:12px;margin-right:5px}@media (max-width:1023px){.-se{display:none}}.-st{margin:0;font-size:1rem;color:#005af0}.-sn{font-size:.875rem;line-height:1.6;margin:0}.-sr{display:flex;justify-content:center;margin-bottom:2rem}.-sr .ap-a-btn{padding:.5rem 2rem;font-size:.875rem;color:#005af0;border:2px solid #005af0;background:0 0;box-shadow:none;opacity:.6}.-sr .ap-a-btn:hover{transform:none;opacity:1}.amp-notsupported .-sr{display:none}.-ix{padding:0 25px;font-size:.75rem}@media (min-width:1024px){.-ix{padding:0 60px}}.-si{padding:14vh 15px 0;text-align:center}.-so,.-ss{margin-top:1.5rem;font-weight:700;line-height:1.2em;font-size:16vw;margin:0;color:#ebebf0}.-so{font-family:Poppins,sans-serif}@media (min-width:768px){.-so,.-ss{font-size:13vw}}@media (min-width:1024px){.-so,.-ss{font-size:100px}}.-ss{font-family:Arial,Helvetica,sans-serif}.-su{margin:0 0 2em}.-il .empty{overflow:hidden;height:0}.ap-o-burger-menu{display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;padding:110px 20px 80px;z-index:16;background-color:#fff}@media (max-width:240px){.ap-o-burger-menu{padding:37px 20px 0}.has-banner~.ap-o-burger-menu{padding:calc(37px + 31px) 0 0 20px}}.ap-o-burger-menu-label{position:fixed;z-index:1001;top:12px;right:20px;cursor:pointer}.ap-o-burger-menu-label.mainmenuopen{z-index:1004}.has-banner+.ap-o-burger-menu-label{top:calc(12px + 31px)}@media (min-width:768px){.ap-o-burger-menu-label{right:30px}}@media (min-width:1024px){.ap-o-burger-menu-label{display:none}}.ap-o-burger-menu-icon{width:30px;height:30px}@media (min-width:1024px){.ap-o-burger-menu{display:none}}.ap-o-burger-menu.mainmenuopen{display:block;z-index:1003}.ap-o-burger-menu.mainmenuopen~.ap--main{max-height:calc(100vh - 55px)}.has-banner+.ap-o-burger-menu.mainmenuopen~.ap--main{max-height:calc(100vh - 55px - 31px)}.-sf ul,.ap-o-burger-menu.mainmenuopen~.ap--footer{display:none}.-sa{list-style:none;display:flex;flex-direction:column;height:100%;margin:0;padding:0;overflow-y:auto;-webkit-overflow-scrolling:touch}@media (max-width:240px){.-sa{padding:1rem 0}}.-sa,.-sa .-sa{margin-top:1rem}.-sa .-sa .-sf:last-child{margin-bottom:0}.-sf{margin-bottom:1rem;position:relative}.-sf:last-child{margin-top:auto}.-sl{position:absolute;left:0;top:0;width:100%;height:36px;padding:0;margin:0;background:0 0;border:0;cursor:pointer;-webkit-appearance:none}.-sl:focus{outline:-webkit-focus-ring-color auto 5px}.-sl:checked~ul{display:block}.-sl:checked+.nav-icon .ap-a-ico{transform:rotate(-90deg)}.-sl+.nav-icon .ap-a-ico{display:inline-block;transform:rotate(0)}.-sf .ap-a-ico{height:.6em;margin-bottom:.3em;margin-left:.3em;width:.6em}.-sc{position:relative;margin-right:20px;padding-bottom:10px;display:none}@media (max-width:240px){.-sc{margin-right:0}}@media (min-width:1024px){.-sc{margin-right:0;padding-right:30px;display:block}}.-sh{display:flex;align-items:center;font-size:11px;border:0;background:0 0}.-sh:hover{color:#005af0}.-sp{position:absolute;left:0;top:0;width:100%;height:100%;margin:0;padding:0;border:0;-webkit-appearance:none}@media (min-width:1024px){.-sp{width:calc(100% - 30px)}}.-sd{width:10px;height:10px;margin-left:5px}.-sv{list-style:none;display:none;position:absolute;right:15%;margin:0;padding:2px 8px;background:#fff;box-shadow:0 2px 10px 0 rgba(0,0,0,.07)}@media (max-width:240px){.-sv{overflow:auto;max-height:calc(100vh - 55px - 31px)}}.-sc .-sm{display:block}.-sp:checked~.-sv,.-sp:hover~.-sv,.-sv:hover{display:block}.-sv:focus-within{display:block}.mainmenuopen .-sc{display:block}.-sg{padding:5px 0;margin:0 20px 9px 0;cursor:pointer}@media (max-width:1023px){.-sy .-sg{order:1;padding:0;margin:0 70px 9px auto}.mainmenuopen .-sy .-sg{margin-left:0}}@media (max-width:240px){.-sy .-sg{margin-right:60px}}.-sb{position:fixed;left:calc(90vw - 18px);top:35px;padding:12px;margin:0;fill:#fff;background:#005af0;border-radius:50%;box-shadow:0 6px 10px 0 rgba(0,0,0,.14);z-index:3}@media (min-width:1024px){.-sb{position:absolute;left:auto;right:10px;top:52px}}@media (min-width:1280px){.-sb{right:52px}}@media (min-width:1440px){.-sb{right:87px}}.-sb .-sw{width:12px;height:12px}.-sw{width:18px;height:18px}.-sm{font-family:Poppins,sans-serif;font-weight:700;font-size:1.5em;color:#000}@media (min-width:1024px){.-sm{font-size:1rem}}.-sx{line-height:1.6rem;font-weight:400;color:#48525c;font-size:1rem}@media (min-width:1024px){.-sx{font-size:.875rem}}.-sx.-sk{text-decoration:underline}.-os a:hover,.-sk,.-sm:hover{color:#005af0}.-sk{font-weight:700}.ap--header{width:100%;max-width:2020px;margin:0 auto;position:-webkit-sticky;position:sticky;top:0;z-index:1001;background-color:#fff;box-shadow:0 2px 10px 0 rgba(0,0,0,.07)}.ap--header.mainmenuopen{z-index:1004}.ap--header.mainmenuopen~.ap--main{max-width:100vw;overflow-x:hidden}@media (min-width:1024px){.ap--header{top:0}.ap--header.has-banner{top:-31px}}.-sy{display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center;max-width:1460px;padding:10px 0 0 20px;margin:0 auto}@media (min-width:1024px){.-sy{display:flex;padding-left:30px}}.-s_{position:-webkit-sticky;position:sticky;top:10px;display:flex;align-items:center;margin-right:auto;padding-bottom:10px;overflow:hidden}.-sj{height:30px;margin-right:6px;width:30px}.-sq,.-sz{margin-left:4px;font-family:Poppins,sans-serif;font-weight:700;font-size:1.5em}.-sz{color:#005af0}@media (min-width:1024px){.-sq,.-sz{font-size:1.125rem}}.-sq{color:#000;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.-oe{display:none;flex:1 1 auto;padding:0 30px}@media (min-width:1024px){.-oe{display:flex}}.-on,.-ot{display:flex;align-items:center}.-ot{position:relative;margin:0 18px -5px}.-on{padding:0 0 14px;border:0;background:0 0}.-or{font-size:8px;margin-left:5px;transform:rotate(0);transition:transform .2s cubic-bezier(.25,.1,.25,1)}.-oi:hover,.-on:focus~.-oi,.-on:hover~.-oi{opacity:1;pointer-events:all;transition:opacity .2s cubic-bezier(.25,.1,.25,1)}.-oi:focus-within{opacity:1;pointer-events:all;transition:opacity .2s cubic-bezier(.25,.1,.25,1)}.-oi{box-shadow:0 10px 25px 0 rgba(0,0,0,.2);position:absolute;top:95%;left:0;margin:0;padding:0 0 10px;pointer-events:none;opacity:0;list-style:none;background:#fff;border-radius:0 0 4px 4px;transition:opacity .2s cubic-bezier(.25,.1,.25,1)}.-oi:before{content:\"\";display:block;background:linear-gradient(to bottom,rgba(0,0,0,.07) 0,rgba(255,255,255,.07) 100%);height:8px;margin-bottom:10px}.-os{margin:20px 0;white-space:nowrap;min-width:200px}.-oo,.-ou{line-height:1.6rem}.-oo{font-size:.875rem;font-family:Poppins,sans-serif;font-weight:700;color:#000;line-height:1.4em}.-oo.secondary{padding:0 15px}.-ou{font-weight:400;color:#48525c;font-size:.8125rem;opacity:.75;line-height:1.25em}.-oa{position:relative;width:300px}.-oa:hover .-of{box-shadow:0 10px 25px 0 rgba(0,0,0,.2);background-color:#005af0}.-oa:hover .-ol>*{color:#fff}.-oa:hover .-oc .-oo,.-oa:hover .-oc .-ou,.-oa:hover .-oh .-oo,.-oa:hover .-oh .-ou{color:#180ca4}.-oa:hover .-op{fill:#fff}.-oa:hover .-op.email,.-oa:hover .-op.stories{fill:#180ca4}.-oa:hover .-of.websites{background:linear-gradient(225deg,#00dcc0 0,#005af0 75%)}.-oa:hover .-of.stories{background:linear-gradient(225deg,#ff8f00 0,#ffdc00 75%)}.-oa:hover .-of.ads{background:linear-gradient(225deg,#eb49e1 0,#5500d7 75%)}.-oa:hover .-of.email{background:linear-gradient(225deg,#64bf46 0,#e1eb64 75%)}.-of{display:flex;align-items:center;border-radius:4px;padding:10px;margin:0 5px}.-ol{margin:0 20px 0 15px}.-op{display:flex;font-size:initial;box-sizing:initial;justify-content:center;width:2em;height:2em}.-op.websites{fill:url(#gradient-websites) #000}.-op.stories{fill:url(#gradient-stories) #000}.-op.ads{fill:url(#gradient-ads) #000}.-op.email{fill:url(#gradient-email) #000}</style><link rel=\"manifest\" href=\"/manifest.json\"></head><body class=\"ap--websites\">\n"
  },
  {
    "path": "tests/phpunit/integration/data/characters.example.com.html",
    "content": "<!doctype html >\n<!--[if IE 8]>    <html class=\"ie8\" lang=\"en\"> <![endif]-->\n<!--[if IE 9]>    <html class=\"ie9\" lang=\"en\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html lang=\"pt-BR\"> <!--<![endif]-->\n<head>\n  <title>Chizuru Kagura estará em The King of Fighters XV; novo trailer</title>\n  <meta charset=\"UTF-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" />\n  <meta property=\"og:locale\" content=\"pt_BR\" />\n  <meta property=\"og:type\" content=\"article\" />\n  <meta property=\"og:title\" content=\"Chizuru Kagura estará em The King of Fighters XV; novo trailer\" />\n  <meta property=\"og:description\" content=\"Com a revelação de Chizuru, foi revelado a segunda equipe: a &#8220;Team Sacred Treasures&#8221;, [&hellip;]\" />\n  <meta property=\"og:site_name\" content=\"Select Game\" />\n  <meta property=\"article:published_time\" content=\"2021-02-21T12:46:26+00:00\" />\n  <meta property=\"article:modified_time\" content=\"2021-02-21T12:47:46+00:00\" />\n</head>\n<body>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/phpunit/integration/data/cross_origin_content.html",
    "content": "<html amp=\"\" lang=\"en\">\n<head>\n  <meta charSet=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\" />\n  <script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n  <script async=\"\" src=\"--SITE_URL--\"></script>\n  <script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n  <link href=\"https://fonts.googleapis.com/css2?display=swap&#038;family=Roboto\" rel=\"stylesheet\" />\n  <link href=\"https://fonts.googleapis.com/css2?display=swap&#038;family=Ubuntu\" rel=\"stylesheet\" crossorigin=\"use-credentials\" />\n  <link href=\"--SITE_URL--/site.css\" rel=\"stylesheet\" />\n  <link rel=\"manifest\" href=\"/app.webmanifest\" />\n  <script id='lodash-js-after'>\n    window.lodash = _.noConflict();\n  </script>\n</head>\n<body>\n<div>\n  <img alt=\"test\" src=\"http://www.example.com/test1.jpg\" loading=\"eager\" />\n  <a href=\"http://www.example.com/test1.jpg\">Test</a>\n  <img src='http://www.example.com/test1.jpg' alt=\"test\" />\n  <img src='http://www.example.com/test2.jpg' alt='test' />\n  <img src='--SITE_URL--/test3.jpg' alt=\"test\" />\n  <iframe src=\"http://www.example.com\"></iframe>\n  <iframe src=\"--SITE_URL--\"></iframe>\n  <video><source src=\"http://www.example.com/video1.mp4\"></video>\n  <video><source src=\"--SITE_URL--/video2.mp4\"></video>\n  <video src=\"http://www.example.com/video3.mp4\"></video>\n  <video src=\"--SITE_URL--/video4.mp4\"></video>\n  <audio><source src=\"http://www.example.com/audio1.mp3\"></audio>\n  <audio><source src=\"--SITE_URL--/audio2.mp3\"></audio>\n  <audio src=\"http://www.example.com/audio3.mp3\"></audio>\n  <audio src=\"--SITE_URL--/audio4.mp3\"></audio>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "tests/phpunit/integration/data/example.com.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Example Domain</title>\n\n  <meta charset=\"utf-8\" />\n  <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n  <style type=\"text/css\">\n    body {\n      background-color: #f0f0f2;\n      margin: 0;\n      padding: 0;\n      font-family: -apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n\n    }\n    div {\n      width: 600px;\n      margin: 5em auto;\n      padding: 2em;\n      background-color: #fdfdff;\n      border-radius: 0.5em;\n      box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);\n    }\n    a:link, a:visited {\n      color: #38488f;\n      text-decoration: none;\n    }\n    @media (max-width: 700px) {\n      div {\n        margin: 0 auto;\n        width: auto;\n      }\n    }\n  </style>\n</head>\n\n<body>\n<div>\n  <h1>Example Domain</h1>\n  <p>This domain is for use in illustrative examples in documents. You may use this\n    domain in literature without prior coordination or asking for permission.</p>\n  <p><a href=\"https://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "tests/phpunit/integration/data/schema.json",
    "content": "{\n  \"title\": \"Product\",\n  \"description\": \"A product from an amp-story-shopping configuration.\",\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"properties\": {\n    \"productId\": {\n      \"description\": \"Keys for amp-story-shopping-tag nodes, sent out in analytics events.\",\n      \"type\": \"string\"\n    },\n    \"productUrl\": {\n      \"description\": \"Links to the product's website, when the buy now button is clicked.\",\n      \"type\": \"string\",\n      \"$ref\": \"#/$defs/https\"\n    },\n    \"productTitle\": {\n      \"description\": \"The name of the product, displayed on the tag.\",\n      \"type\": \"string\"\n    },\n    \"productPrice\": {\n      \"description\": \"The price of the product, displayed on the tag.\",\n      \"type\": \"number\"\n    },\n    \"productPriceCurrency\": {\n      \"description\": \"The ISO 4217 currency code of the product price.\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"AED\",\n        \"AFN\",\n        \"ALL\",\n        \"AMD\",\n        \"ANG\",\n        \"AOA\",\n        \"ARS\",\n        \"AUD\",\n        \"AWG\",\n        \"AZN\",\n        \"BAM\",\n        \"BBD\",\n        \"BDT\",\n        \"BGN\",\n        \"BHD\",\n        \"BIF\",\n        \"BMD\",\n        \"BND\",\n        \"BOB\",\n        \"BOV\",\n        \"BRL\",\n        \"BSD\",\n        \"BTN\",\n        \"BWP\",\n        \"BYN\",\n        \"BZD\",\n        \"CAD\",\n        \"CDF\",\n        \"CHE\",\n        \"CHF\",\n        \"CHW\",\n        \"CLF\",\n        \"CLP\",\n        \"CNY\",\n        \"COP\",\n        \"COU\",\n        \"CRC\",\n        \"CUC\",\n        \"CUP\",\n        \"CVE\",\n        \"CZK\",\n        \"DJF\",\n        \"DKK\",\n        \"DOP\",\n        \"DZD\",\n        \"EGP\",\n        \"ERN\",\n        \"ETB\",\n        \"EUR\",\n        \"FJD\",\n        \"FKP\",\n        \"GBP\",\n        \"GEL\",\n        \"GHS\",\n        \"GIP\",\n        \"GMD\",\n        \"GNF\",\n        \"GTQ\",\n        \"GYD\",\n        \"HKD\",\n        \"HNL\",\n        \"HRK\",\n        \"HTG\",\n        \"HUF\",\n        \"IDR\",\n        \"ILS\",\n        \"INR\",\n        \"IQD\",\n        \"IRR\",\n        \"ISK\",\n        \"JMD\",\n        \"JOD\",\n        \"JPY\",\n        \"KES\",\n        \"KGS\",\n        \"KHR\",\n        \"KMF\",\n        \"KPW\",\n        \"KRW\",\n        \"KWD\",\n        \"KYD\",\n        \"KZT\",\n        \"LAK\",\n        \"LBP\",\n        \"LKR\",\n        \"LRD\",\n        \"LSL\",\n        \"LYD\",\n        \"MAD\",\n        \"MDL\",\n        \"MGA\",\n        \"MKD\",\n        \"MMK\",\n        \"MNT\",\n        \"MOP\",\n        \"MRU\",\n        \"MUR\",\n        \"MVR\",\n        \"MWK\",\n        \"MXN\",\n        \"MXV\",\n        \"MYR\",\n        \"MZN\",\n        \"NAD\",\n        \"NGN\",\n        \"NIO\",\n        \"NOK\",\n        \"NPR\",\n        \"NZD\",\n        \"OMR\",\n        \"PAB\",\n        \"PEN\",\n        \"PGK\",\n        \"PHP\",\n        \"PKR\",\n        \"PLN\",\n        \"PYG\",\n        \"QAR\",\n        \"RON\",\n        \"RSD\",\n        \"RUB\",\n        \"RWF\",\n        \"SAR\",\n        \"SBD\",\n        \"SCR\",\n        \"SDG\",\n        \"SEK\",\n        \"SGD\",\n        \"SHP\",\n        \"SLL\",\n        \"SOS\",\n        \"SRD\",\n        \"SSP\",\n        \"STN\",\n        \"SVC\",\n        \"SYP\",\n        \"SZL\",\n        \"THB\",\n        \"TJS\",\n        \"TMT\",\n        \"TND\",\n        \"TOP\",\n        \"TRY\",\n        \"TTD\",\n        \"TWD\",\n        \"TZS\",\n        \"UAH\",\n        \"UGX\",\n        \"USD\",\n        \"USN\",\n        \"UYI\",\n        \"UYU\",\n        \"UYW\",\n        \"UZS\",\n        \"VED\",\n        \"VES\",\n        \"VND\",\n        \"VUV\",\n        \"WST\",\n        \"XAF\",\n        \"XAG\",\n        \"XAU\",\n        \"XBA\",\n        \"XBB\",\n        \"XBC\",\n        \"XBD\",\n        \"XCD\",\n        \"XDR\",\n        \"XOF\",\n        \"XPD\",\n        \"XPF\",\n        \"XPT\",\n        \"XSU\",\n        \"XTS\",\n        \"XUA\",\n        \"XXX\",\n        \"YER\",\n        \"ZAR\",\n        \"ZMW\",\n        \"ZWL\"\n      ]\n    },\n    \"productImages\": {\n      \"description\": \"A list of images for the product used in the carousel of the product page.\",\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"items\": {\n        \"required\": [\"url\", \"alt\"],\n        \"additionalProperties\": false,\n        \"type\": \"object\",\n        \"properties\": {\n          \"url\": {\n            \"type\": \"string\",\n            \"$ref\": \"#/$defs/https\"\n          },\n          \"alt\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    },\n    \"productDetails\": {\n      \"description\": \"Details about the product used in the product details page.\",\n      \"type\": \"string\"\n    },\n    \"productBrand\": {\n      \"description\": \"Brand name of the product used in the tag.\",\n      \"type\": \"string\"\n    },\n    \"productIcon\": {\n      \"description\": \"Links the icon image for the product in the tag. Defaults to a shopping bag icon.\",\n      \"type\": \"string\"\n    },\n    \"productTagText\": {\n      \"description\": \"Text for the Product tag. Supersedes productPrice.\",\n      \"type\": \"string\"\n    },\n    \"aggregateRating\": {\n      \"description\": \"Ratings and review data for the product displayed on the product page.\",\n      \"type\": \"object\",\n      \"required\": [\"ratingValue\", \"reviewCount\", \"reviewUrl\"],\n      \"additionalProperties\": false,\n      \"properties\": {\n        \"ratingValue\": {\n          \"description\": \"The aggregate rating value of the product.\",\n          \"type\": \"number\"\n        },\n        \"reviewCount\": {\n          \"description\": \"The number of reviews for the product.\",\n          \"type\": \"number\"\n        },\n        \"reviewUrl\": {\n          \"description\": \"The Url for the product reviews.\",\n          \"type\": \"string\",\n          \"$ref\": \"#/$defs/https\"\n        }\n      }\n    }\n  },\n  \"required\": [\n    \"productId\",\n    \"productUrl\",\n    \"productTitle\",\n    \"productPrice\",\n    \"productPriceCurrency\",\n    \"productImages\",\n    \"productDetails\"\n  ],\n  \"$defs\": {\n    \"https\": {\n      \"type\": \"string\",\n      \"format\": \"uri-reference\",\n      \"pattern\": \"^(/|https://|https?://(127.0.0.1|([^/]+\\\\.)?localhost)(:[0-9]+)?/)\"\n    }\n  }\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_access_denied.json",
    "content": "{\n  \"data\": null,\n  \"errors\": [\n    {\n      \"message\": \"Access denied error message.\",\n      \"locations\": [{ \"line\": 1, \"column\": 1 }],\n      \"path\": [\"products\"],\n      \"extensions\": {\n        \"code\": \"ACCESS_DENIED\",\n        \"documentation\": \"https://shopify.dev/api/usage/page\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_default.json",
    "content": "{\n  \"data\": {\n    \"products\": {\n      \"edges\": [\n        {\n          \"node\": {\n            \"id\": \"gid://shopify/Product/9895276099\",\n            \"handle\": \"snare-boot\",\n            \"title\": \"Snare Boot\",\n            \"vendor\": \"All Saints\",\n            \"description\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pharetra consequat diam. In metus risus, aliquam non massa tempus, gravida commodo orci. Praesent interdum pharetra quam eu pharetra. Nullam commodo nec mi non cursus. In hac habitasse platea dictumst. Nunc nec tincidunt odio, nec suscipit elit. Nam suscipit lectus vel justo pulvinar ultrices. Sed convallis eget dui consectetur placerat. Nunc id elementum dolor. Duis suscipit pulvinar mi a tristique.\",\n            \"priceRange\": {\n              \"minVariantPrice\": {\n                \"amount\": \"158.0\",\n                \"currencyCode\": \"CAD\"\n              }\n            },\n            \"onlineStoreUrl\": \"https://graphql.myshopify.com/products/snare-boot\",\n            \"images\": {\n              \"edges\": [\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/001_grande_89f870ed-dc56-4990-9aa5-4f11ddf13108.jpg?v=1491918957\",\n                    \"altText\": null\n                  }\n                },\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/002_grande_d74b53c6-ff42-4143-9728-2666f568632a.jpg?v=1491918957\",\n                    \"altText\": null\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"node\": {\n            \"id\": \"gid://shopify/Product/9895279043\",\n            \"handle\": \"neptune-boot\",\n            \"title\": \"Neptune Boot\",\n            \"vendor\": \"All Saints\",\n            \"description\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pharetra consequat diam. In metus risus, aliquam non massa tempus, gravida commodo orci. Praesent interdum pharetra quam eu pharetra. Nullam commodo nec mi non cursus. In hac habitasse platea dictumst. Nunc nec tincidunt odio, nec suscipit elit. Nam suscipit lectus vel justo pulvinar ultrices. Sed convallis eget dui consectetur placerat. Nunc id elementum dolor. Duis suscipit pulvinar mi a tristique.\",\n            \"priceRange\": {\n              \"minVariantPrice\": {\n                \"amount\": \"188.0\",\n                \"currencyCode\": \"CAD\"\n              }\n            },\n            \"onlineStoreUrl\": \"https://graphql.myshopify.com/products/neptune-boot\",\n            \"images\": {\n              \"edges\": [\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/001_f5b2f018-5434-446e-912c-10484293c134.jpg?v=1491850944\",\n                    \"altText\": null\n                  }\n                },\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/002_0920679e-5437-4ad1-a9a2-ffc3339bbd0e.jpg?v=1491850944\",\n                    \"altText\": null\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"node\": {\n            \"id\": \"gid://shopify/Product/9895281475\",\n            \"handle\": \"arena-zip-boot\",\n            \"title\": \"Arena Zip Boot\",\n            \"vendor\": \"All Saints\",\n            \"description\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pharetra consequat diam. In metus risus, aliquam non massa tempus, gravida commodo orci. Praesent interdum pharetra quam eu pharetra. Nullam commodo nec mi non cursus. In hac habitasse platea dictumst. Nunc nec tincidunt odio, nec suscipit elit. Nam suscipit lectus vel justo pulvinar ultrices. Sed convallis eget dui consectetur placerat. Nunc id elementum dolor. Duis suscipit pulvinar mi a tristique.\",\n            \"priceRange\": {\n              \"minVariantPrice\": {\n                \"amount\": \"188.0\",\n                \"currencyCode\": \"CAD\"\n              }\n            },\n            \"onlineStoreUrl\": \"https://graphql.myshopify.com/products/arena-zip-boot\",\n            \"images\": {\n              \"edges\": [\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/001_d31a9463-4495-4024-ab4b-6901bdd1752e.jpg?v=1491850970\",\n                    \"altText\": null\n                  }\n                },\n                {\n                  \"node\": {\n                    \"url\": \"https://cdn.shopify.com/s/files/1/1312/0893/products/002_22f0cd08-aa18-4da9-882c-0f11df4169b1.jpg?v=1491850970\",\n                    \"altText\": null\n                  }\n                }\n              ]\n            }\n          }\n        }\n      ],\n      \"pageInfo\": {\n        \"hasNextPage\": true,\n        \"endCursor\": \"eyJsYXN0X2lkIjo5ODk1Mjc5MDQzLCJsYXN0X3ZhbHVlIjoiMjAxNy0wNC0xMCAxOTowMjoyNC4wMDAwMDAifQ==\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_empty_search.json",
    "content": "{\n  \"data\": {\n    \"products\": {\n      \"edges\": [],\n      \"pageInfo\": {\n        \"hasNextPage\": false,\n        \"endCursor\": null\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_internal_server_error.json",
    "content": "{\n  \"data\": null,\n  \"errors\": [\n    {\n      \"message\": \"Internal server error message.\",\n      \"locations\": [{ \"line\": 1, \"column\": 1 }],\n      \"path\": [\"products\"],\n      \"extensions\": {\n        \"code\": \"INTERNAL_SERVER_ERROR\",\n        \"documentation\": \"https://shopify.dev/api/usage/page\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_shop_inactive.json",
    "content": "{\n  \"data\": null,\n  \"errors\": [\n    {\n      \"message\": \"Shop inactive error message.\",\n      \"locations\": [{ \"line\": 1, \"column\": 1 }],\n      \"path\": [\"products\"],\n      \"extensions\": {\n        \"code\": \"SHOP_INACTIVE\",\n        \"documentation\": \"https://shopify.dev/api/usage/page\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_throttled.json",
    "content": "{\n  \"data\": null,\n  \"errors\": [\n    {\n      \"message\": \"Throttled error message.\",\n      \"locations\": [{ \"line\": 1, \"column\": 1 }],\n      \"path\": [\"products\"],\n      \"extensions\": {\n        \"code\": \"THROTTLED\",\n        \"documentation\": \"https://shopify.dev/api/usage/page\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/shopify_response_unknown.json",
    "content": "{\n  \"data\": null,\n  \"errors\": [\n    {\n      \"message\": \"Unknown error message.\",\n      \"locations\": [{ \"line\": 1, \"column\": 1 }],\n      \"path\": [\"products\"],\n      \"extensions\": {\n        \"code\": \"\",\n        \"documentation\": \"https://shopify.dev/api/usage/page\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/stories_in_amp.html",
    "content": "\n<!--\n  ~ Copyright 2020 Google LLC\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~     https://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<!--\n  ## Introduction\n\n  Learn how to create your first AMP Story. The [`amp-story`](/content/amp-dev/documentation/components/reference/amp-story-v1.0.md) extension provides a new format for displaying visual content.\n-->\n<!-- -->\n<!doctype html>\n<html amp lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <script async src=\"https://cdn.ampproject.org/v0.js\"></script>\n  <!-- ## Setup -->\n  <!-- AMP Stories are written using AMPHTML and they use their own AMP extension: `amp-story`. The first step is to import the `amp-story` in the header. -->\n  <script async custom-element=\"amp-story\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\"></script>\n  <!-- AMP Stories can make use of other AMP extensions such as `amp-video`. However, AMP Stories support only a subset of the available AMP extensions. You can find a full list of the supported extensions [here](/content/amp-dev/documentation/components/reference/amp-story.md#children-of-amp-story-grid-layer). -->\n  <script async custom-element=\"amp-video\" src=\"https://cdn.ampproject.org/v0/amp-video-0.1.js\"></script>\n  <title>Stories in AMP - Hello World</title>\n  <meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\">\n  <link rel=\"canonical\" href=\"https://amp.dev/documentation/examples/introduction/stories_in_amp/index.html\">\n  <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>\n  <!-- Stories can be styled using CSS: -->\n  <style amp-custom>\n    amp-story {\n      font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI \", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji \", \"Segoe UI Emoji \", \"Segoe UI Symbol \";\n    }\n    amp-story-page * {\n      color: white;\n      text-align: center;\n    }\n    [template=thirds] {\n      padding: 0;\n    }\n  </style>\n</head>\n\n<body>\n<!-- ## Writing the Story -->\n<!-- Stories are declared inside the `amp-story` tag. Story-level metadata is provided via attributes. (The first four attributes are mandatory; the final two are optional, but recommended.) Note that this metadata augments, but does not replace, [Structured Data](https://developers.google.com/search/docs/data-types/article#amp). -->\n<amp-story standalone\n           title=\"Stories in AMP - Hello World\"\n           publisher=\"AMP Project\"\n           publisher-logo-src=\"https://amp.dev/favicons/coast-228x228.png\"\n           poster-portrait-src=\"https://amp.dev/static/samples/img/story_dog2_portrait.jpg\"\n           poster-square-src=\"https://amp.dev/static/samples/img/story_dog2_square.jpg\"\n           poster-landscape-src=\"https://amp.dev/static/samples/img/story_dog2_landscape.jpg\">\n\n  <!-- A story consists of one or more pages. Each page is declared by an `amp-story-page` element. Pages are designed by layering videos, images and text. Here we have a page that uses two layers. One layer filling the available space with an image and one text layer that shows a heading. -->\n  <amp-story-page id=\"page-1\">\n    <amp-story-grid-layer template=\"fill\">\n      <amp-img src=\"https://amp.dev/static/samples/img/story_dog2.jpg\"\n               width=\"720\" height=\"1280\"\n               layout=\"responsive\">\n      </amp-img>\n    </amp-story-grid-layer>\n    <amp-story-grid-layer template=\"vertical\">\n      <h1>Hello World</h1>\n      <p>This is an AMP Story.</p>\n    </amp-story-grid-layer>\n  </amp-story-page>\n\n  <!-- Here we have a page consisting of a video which autoplays and loops. -->\n  <amp-story-page id=\"page-2\">\n    <amp-story-grid-layer template=\"fill\">\n      <amp-video autoplay loop\n                 width=\"720\"\n                 height=\"960\"\n                 poster=\"https://amp.dev/static/samples/img/story_video_dog_cover.jpg\"\n                 layout=\"responsive\">\n        <source src=\"https://amp.dev/static/samples/video/story_video_dog.mp4\" type=\"video/mp4\">\n      </amp-video>\n    </amp-story-grid-layer>\n  </amp-story-page>\n\n  <!-- Pre-defined entry animations make it possible to create dynamic pages without videos. The length and initial delay can be customized using the `animate-in-duration` and `animate-in-delay` properties. The [animations sample](/documentation/examples/visual-effects/amp_story_animations/) shows all available animantions in action. -->\n  <amp-story-page id=\"animation-demo\">\n    <amp-story-grid-layer template=\"fill\">\n      <amp-img src=\"https://amp.dev/static/samples/img/story_dog4.jpg\"\n               animate-in=\"fly-in-top\"\n               width=\"720\" height=\"1280\"\n               layout=\"responsive\">\n      </amp-img>\n    </amp-story-grid-layer>\n    <amp-story-grid-layer template=\"thirds\">\n      <h2 animate-in=\"fly-in-bottom\"\n          grid-area=\"lower-third\"\n          animate-in-delay=\"0.4s\">\n        Best walk ever!\n      </h2>\n    </amp-story-grid-layer>\n  </amp-story-page>\n\n  <!-- Stories can use predefined layouts to style the page. Here we're using the `thirds` template. For an overview about the available layouts take a look at the [layouts sample](/documentation/examples/style-layout/amp_story_layouts/). -->\n  <amp-story-page id=\"layout-demo\">\n    <amp-story-grid-layer template=\"thirds\">\n      <amp-img grid-area=\"upper-third\"\n               src=\"https://amp.dev/static/samples/img/story_thirds_1.jpg\"\n               width=\"560\" height=\"420\"\n               layout=\"responsive\">\n      </amp-img>\n      <amp-img grid-area=\"middle-third\"\n               src=\"https://amp.dev/static/samples/img/story_thirds_2.jpg\"\n               width=\"560\" height=\"420\"\n               layout=\"responsive\">\n      </amp-img>\n      <amp-img grid-area=\"lower-third\"\n               src=\"https://amp.dev/static/samples/img/story_thirds_3.jpg\"\n               width=\"560\"\n               height=\"420\"\n               layout=\"responsive\">\n      </amp-img>\n    </amp-story-grid-layer>\n  </amp-story-page>\n\n  <!-- A \"bookend\" panel containing links to other resources will appear on the last page of your story if you include an `amp-story-bookend` that references a [bookend JSON config](/static/samples/json/bookend.json). -->\n  <amp-story-bookend src=\"https://amp.dev/static/samples/json/bookend.json\" layout=\"nodisplay\">\n  </amp-story-bookend>\n</amp-story>\n</body>\n</html>\n"
  },
  {
    "path": "tests/phpunit/integration/data/story_post_content.html",
    "content": "<html amp=\"\" lang=\"en\">\n<head>\n  <meta charSet=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\" />\n  <script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n  <script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n  <link href=\"https://fonts.googleapis.com/css2?display=swap&amp;family=Roboto\" rel=\"stylesheet\" />\n  <style amp-boilerplate=\"\">body {\n    -webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    -moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    -ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    animation: -amp-start 8s steps(1, end) 0s 1 normal both\n  }\n\n  @-webkit-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-moz-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-ms-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-o-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }</style>\n  <noscript>\n    <style amp-boilerplate=\"\">body {\n      -webkit-animation: none;\n      -moz-animation: none;\n      -ms-animation: none;\n      animation: none\n    }</style>\n  </noscript>\n  <style amp-custom=\"\">\n    amp-story-grid-layer {\n      overflow: visible;\n    }\n\n    .page-fullbleed-area {\n      position: absolute;\n      overflow: hidden;\n      width: 100%;\n      left: 0;\n      height: calc(1.1851851851851851 * 100%);\n      top: calc((1 - 1.1851851851851851) * 100% / 2);\n    }\n\n    .page-safe-area {\n      overflow: visible;\n      position: absolute;\n      top: 0;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      width: 100%;\n      height: calc(0.84375 * 100%);\n      margin: auto 0;\n    }\n\n    .wrapper {\n      position: absolute;\n      overflow: hidden;\n    }\n\n    .fill {\n      position: absolute;\n      top: 0;\n      left: 0;\n      right: 0;\n      bottom: 0;\n      margin: 0;\n    }\n  </style>\n  <meta name=\"web-stories-replace-head-start\" />\n  <link rel=\"canonical\" href=\"https://web-stories.local/?post_type=web-story&amp;p=1052\" />\n  <meta name=\"web-stories-replace-head-end\" />\n</head>\n<body>\n<amp-story standalone=\"standalone\" publisher=\"Web Stories\" publisher-logo-src=\"https://web-stories.local/wp-content/plugins/web-stories-wp/assets/images/fallback-wordpress-publisher-logo.png\" title=\"\" poster-portrait-src=\"https:/example.com/poster.png\">\n  <amp-story-page id=\"a3f18c09-3f10-43c4-9446-794f0541ea1e\" auto-advance-after=\"7s\">\n    <amp-story-grid-layer template=\"vertical\" aspect-ratio=\"440:660\">\n      <div class=\"page-fullbleed-area\" style=\"background-color:#fff\">\n        <div class=\"page-safe-area\">\n          <div style=\"left:0%;top:-9.25926%;width:100%;height:118.51852%;opacity:1;transform:rotate(10deg)\" id=\"el-d58c2be2-f8a0-4e00-b21a-ddd32d1ac04b\" class=\"wrapper\">\n            <div class=\"fill\"></div>\n          </div>\n        </div>\n      </div>\n    </amp-story-grid-layer>\n    <amp-story-grid-layer template=\"vertical\" aspect-ratio=\"440:660\">\n      <div class=\"page-fullbleed-area\">\n        <div class=\"page-safe-area\">\n          <div style=\"left:16.59091%;top:20.90909%;width:36.36364%;height:2.72727%;opacity:1\" id=\"el-e781bc30-4ebe-416f-bf1d-b509dc3ef6ce\" class=\"wrapper\"><p class=\"fill\" style=\"white-space:pre-wrap;margin:0;font-family:&quot;Roboto&quot;,&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,sans-serif;font-size:0.212121em;line-height:1.3;text-align:initial;padding:0% 0%;color:#000000\">\n            <span style=\"font-weight: 700\">Fill in some text</span></p></div>\n        </div>\n      </div>\n    </amp-story-grid-layer>\n  </amp-story-page>\n</amp-story>\n</body>\n</html>\n"
  },
  {
    "path": "tests/phpunit/integration/data/story_post_content_filtered.json",
    "content": "{\n  \"version\": 21,\n  \"pages\": [\n    {\n      \"elements\": [\n        {\n          \"opacity\": 100,\n          \"flip\": {\n            \"vertical\": false,\n            \"horizontal\": false\n          },\n          \"rotationAngle\": 10,\n          \"lockAspectRatio\": true,\n          \"backgroundColor\": {\n            \"color\": {\n              \"r\": 255,\n              \"g\": 255,\n              \"b\": 255\n            }\n          },\n          \"x\": 1,\n          \"y\": 1,\n          \"width\": 1,\n          \"height\": 1,\n          \"mask\": {\n            \"type\": \"rectangle\"\n          },\n          \"isBackground\": true,\n          \"isDefaultBackground\": true,\n          \"type\": \"shape\",\n          \"id\": \"d58c2be2-f8a0-4e00-b21a-ddd32d1ac04b\"\n        },\n        {\n          \"opacity\": 100,\n          \"flip\": {\n            \"vertical\": false,\n            \"horizontal\": false\n          },\n          \"rotationAngle\": 0,\n          \"lockAspectRatio\": true,\n          \"backgroundTextMode\": \"NONE\",\n          \"font\": {\n            \"family\": \"Roboto\",\n            \"weights\": [100, 300, 400, 500, 700, 900],\n            \"styles\": [\"italic\", \"regular\"],\n            \"variants\": [\n              [0, 100],\n              [1, 100],\n              [0, 300],\n              [1, 300],\n              [0, 400],\n              [1, 400],\n              [0, 500],\n              [1, 500],\n              [0, 700],\n              [1, 700],\n              [0, 900],\n              [1, 900]\n            ],\n            \"fallbacks\": [\"Helvetica Neue\", \"Helvetica\", \"sans-serif\"],\n            \"service\": \"fonts.google.com\"\n          },\n          \"fontSize\": 14,\n          \"backgroundColor\": {\n            \"color\": {\n              \"r\": 196,\n              \"g\": 196,\n              \"b\": 196\n            }\n          },\n          \"lineHeight\": 1.3,\n          \"textAlign\": \"initial\",\n          \"padding\": {\n            \"vertical\": 0,\n            \"horizontal\": 0,\n            \"locked\": true\n          },\n          \"type\": \"text\",\n          \"id\": \"e781bc30-4ebe-416f-bf1d-b509dc3ef6ce\",\n          \"content\": \"<span style=\\\"font-weight: 700\\\">Fill in some text</span>\",\n          \"x\": 73,\n          \"y\": 138,\n          \"width\": 160,\n          \"height\": 18,\n          \"scale\": 100,\n          \"focalX\": 50,\n          \"focalY\": 50\n        }\n      ],\n      \"backgroundColor\": {\n        \"color\": {\n          \"r\": 255,\n          \"g\": 255,\n          \"b\": 255\n        }\n      },\n      \"type\": \"page\",\n      \"id\": \"a3f18c09-3f10-43c4-9446-794f0541ea1e\"\n    }\n  ],\n  \"autoAdvance\": true,\n  \"defaultPageDuration\": 7\n}\n"
  },
  {
    "path": "tests/phpunit/integration/data/story_post_content_sanitized.html",
    "content": "<!DOCTYPE html>\n<html amp=\"\" lang=\"en\">\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,minimum-scale=1\">\n  \n  \n  <script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n  <script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n  <link href=\"https://fonts.googleapis.com/css2?display=swap&amp;family=Roboto\" rel=\"stylesheet\">\n  \n  <!--noscript-->\n    <style amp-boilerplate=\"\">body {\n      -webkit-animation: none;\n      -moz-animation: none;\n      -ms-animation: none;\n      animation: none\n    }</style>\n  <!--/noscript-->\n  <style amp-custom=\"\">\n    amp-story-grid-layer {\n      overflow: visible;\n    }\n\n    .page-fullbleed-area {\n      position: absolute;\n      overflow: hidden;\n      width: 100%;\n      left: 0;\n      height: calc(1.1851851851851851 * 100%);\n      top: calc((1 - 1.1851851851851851) * 100% / 2);\n    }\n\n    .page-safe-area {\n      overflow: visible;\n      position: absolute;\n      top: 0;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      width: 100%;\n      height: calc(0.84375 * 100%);\n      margin: auto 0;\n    }\n\n    .wrapper {\n      position: absolute;\n      overflow: hidden;\n    }\n\n    .fill {\n      position: absolute;\n      top: 0;\n      left: 0;\n      right: 0;\n      bottom: 0;\n      margin: 0;\n    }\n  </style>\n  <meta name=\"web-stories-replace-head-start\">\n  <link rel=\"canonical\" href=\"https://web-stories.local/?post_type=web-story&amp;p=1052\">\n  <meta name=\"web-stories-replace-head-end\">\n<style amp-boilerplate=\"\">body {\n    -webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    -moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    -ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;\n    animation: -amp-start 8s steps(1, end) 0s 1 normal both\n  }\n\n  @-webkit-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-moz-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-ms-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @-o-keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }\n\n  @keyframes -amp-start {\n    from {\n      visibility: hidden\n    }\n    to {\n      visibility: visible\n    }\n  }</style><noscript><style amp-boilerplate=\"\">body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript></head>\n<body>\n<amp-story standalone=\"standalone\" publisher=\"Web Stories\" publisher-logo-src=\"https://web-stories.local/wp-content/plugins/web-stories-wp/assets/images/fallback-wordpress-publisher-logo.png\" title=\"\" poster-portrait-src=\"https:/example.com/poster.png\">\n  <amp-story-page id=\"a3f18c09-3f10-43c4-9446-794f0541ea1e\" auto-advance-after=\"7s\">\n    <amp-story-grid-layer template=\"vertical\" aspect-ratio=\"440:660\">\n      <div class=\"page-fullbleed-area\" style=\"background-color:#fff\">\n        <div class=\"page-safe-area\">\n          <div style=\"left:0%;top:-9.25926%;width:100%;height:118.51852%;opacity:1;transform:rotate(10deg)\" id=\"el-d58c2be2-f8a0-4e00-b21a-ddd32d1ac04b\" class=\"wrapper\">\n            <div class=\"fill\"></div>\n          </div>\n        </div>\n      </div>\n    </amp-story-grid-layer>\n    <amp-story-grid-layer template=\"vertical\" aspect-ratio=\"440:660\">\n      <div class=\"page-fullbleed-area\">\n        <div class=\"page-safe-area\">\n          <div style=\"left:16.59091%;top:20.90909%;width:36.36364%;height:2.72727%;opacity:1\" id=\"el-e781bc30-4ebe-416f-bf1d-b509dc3ef6ce\" class=\"wrapper\"><p class=\"fill\" style='white-space:pre-wrap;margin:0;font-family:\"Roboto\",\"Helvetica Neue\",\"Helvetica\",sans-serif;font-size:0.212121em;line-height:1.3;text-align:initial;padding:0% 0%;color:#000000'>\n            <span style=\"font-weight: 700\">Fill in some text</span></p></div>\n        </div>\n      </div>\n    </amp-story-grid-layer>\n  </amp-story-page>\n</amp-story>\n\n</body></html>\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Capabilities_Setup.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector\\SimpleInjector;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\User\\Capabilities;\n\ntrait Capabilities_Setup {\n\tpublic function add_caps_to_roles(): void {\n\t\t$this->get_capabilities()->add_caps_to_roles();\n\t}\n\n\tpublic function remove_caps_from_roles(): void {\n\t\t$this->get_capabilities()->remove_caps_from_roles();\n\t}\n\n\tprotected function get_capabilities(): Capabilities {\n\t\treturn new Capabilities( new Story_Post_Type( new Settings( new Shopping_Vendors( new SimpleInjector() ) ) ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/DependencyInjectedRestTestCase.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * DependencyInjectedRestTestCase class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * Class DependencyInjectedRestTestCase\n */\nabstract class DependencyInjectedRestTestCase extends DependencyInjectedTestCase {\n\tuse REST_Setup;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->set_up_rest();\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->tear_down_rest();\n\n\t\tparent::tear_down();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/DependencyInjectedTestCase.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * DependencyInjectedTestCase class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer;\nuse Google\\Web_Stories\\Plugin;\nuse Google\\Web_Stories\\Services;\n\nabstract class DependencyInjectedTestCase extends TestCase {\n\n\t/**\n\t * Plugin instance to test with.\n\t */\n\tprotected Plugin $plugin;\n\n\t/**\n\t * Service container instance to test with.\n\t *\n\t * @var ServiceContainer<Service>\n\t */\n\tprotected ServiceContainer $container;\n\n\t/**\n\t * Injector instance to test with.\n\t */\n\tprotected Injector $injector;\n\n\t/**\n\t * Set up the service architecture before each test run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t// Needed because the block will exist already after hooking up the plugin\n\t\t// on plugins_loaded. This avoids _doing_it_wrong messages\n\t\t// due to registering the plugin (and thus the block) again.\n\t\t// But only du so when the block is actually registered to avoid another\n\t\t// _doing_it_wrong message being triggered.\n\t\t// TODO: Figure out a better way.\n\t\tif ( \\WP_Block_Type_Registry::get_instance()->is_registered( 'web-stories/embed' ) ) {\n\t\t\tunregister_block_type( 'web-stories/embed' );\n\t\t}\n\n\t\t// We're intentionally avoiding the PluginFactory here as it uses a\n\t\t// static instance, because its whole point is to allow reuse across consumers.\n\t\t$this->plugin = new Plugin();\n\t\t$this->plugin->register();\n\n\t\t$this->container = $this->plugin->get_container();\n\t\t$this->injector  = $this->container->get( 'injector' );\n\n\t\t// The static Services helper has to be modified to use the same objects\n\t\t// as the ones that are injected into the tests.\n\t\t$this->set_private_property( Services::class, 'plugin', $this->plugin );\n\t\t$this->set_private_property( Services::class, 'container', $this->container );\n\t\t$this->set_private_property( Services::class, 'injector', $this->injector );\n\t}\n\n\t/**\n\t * Clean up again after each test run.\n\t */\n\tpublic function tear_down(): void {\n\t\t$this->set_private_property( Services::class, 'plugin', null );\n\t\t$this->set_private_property( Services::class, 'container', null );\n\t\t$this->set_private_property( Services::class, 'injector', null );\n\n\t\tparent::tear_down();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyClass.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nfinal class DummyClass {\n\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyClassWithDependency.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nfinal class DummyClassWithDependency implements DummyInterface {\n\n\tprivate DummyClass $dummy;\n\n\tpublic function __construct( DummyClass $dummy ) {\n\t\t$this->dummy = $dummy;\n\t}\n\n\tpublic function get_dummy(): DummyClass {\n\t\treturn $this->dummy;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyClassWithNamedArguments.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nfinal class DummyClassWithNamedArguments {\n\n\tprivate int $argument_a;\n\n\tprivate string $argument_b;\n\n\tpublic function __construct( int $argument_a, string $argument_b = 'Mr Meeseeks' ) {\n\t\t$this->argument_a = $argument_a;\n\t\t$this->argument_b = $argument_b;\n\t}\n\n\t/**\n\t * @return mixed\n\t */\n\tpublic function get_argument_a() {\n\t\treturn $this->argument_a;\n\t}\n\n\t/**\n\t * @return mixed\n\t */\n\tpublic function get_argument_b() {\n\t\treturn $this->argument_b;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyInterface.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\ninterface DummyInterface {\n\t/**\n\t * @return mixed\n\t */\n\tpublic function get_dummy(); // phpcs:ignore SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyPostTypeWithCustomArchive.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Post_Type_Base;\n\nclass DummyPostTypeWithCustomArchive extends Post_Type_Base {\n\tpublic function get_slug(): string {\n\t\treturn 'cpt-custom-archive';\n\t}\n\n\tpublic function get_args(): array {\n\t\treturn [\n\t\t\t'public'      => true,\n\t\t\t'rewrite'     => true,\n\t\t\t'has_archive' => 'custom-archive-slug',\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyPostTypeWithoutArchive.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Post_Type_Base;\n\nclass DummyPostTypeWithoutArchive extends Post_Type_Base {\n\tpublic function get_slug(): string {\n\t\treturn 'cpt-without-archive';\n\t}\n\n\tpublic function get_args(): array {\n\t\treturn [\n\t\t\t'public'      => true,\n\t\t\t'rewrite'     => true,\n\t\t\t'has_archive' => false,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyService.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\nfinal class DummyService implements Service {\n\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyServiceBasedPlugin.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Infrastructure\\ServiceBasedPlugin;\n\nclass DummyServiceBasedPlugin extends ServiceBasedPlugin {\n\n\t/**\n\t * Get the list of services to register.\n\t *\n\t * @return array<string> Associative array of identifiers mapped to fully\n\t *                       qualified class names.\n\t */\n\tprotected function get_service_classes(): array {\n\t\treturn [\n\t\t\t'service_a' => DummyService::class,\n\t\t\t'service_b' => DummyService::class,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyServiceWithDelay.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Infrastructure\\Delayed;\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\nclass DummyServiceWithDelay implements Service, Delayed {\n\t/**\n\t * Get the action to use for registering the service.\n\t *\n\t * @return string Registration action to use.\n\t */\n\tpublic static function get_registration_action(): string {\n\t\treturn 'some_action';\n\t}\n\n\t/**\n\t * Get the action priority to use for registering the service.\n\t *\n\t * @return int Registration action priority to use.\n\t */\n\tpublic static function get_registration_action_priority(): int {\n\t\treturn 10;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyServiceWithRequirements.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\Infrastructure\\HasRequirements;\nuse Google\\Web_Stories\\Infrastructure\\Service;\n\nclass DummyServiceWithRequirements implements Service, HasRequirements {\n\n\t/**\n\t * Get the list of service IDs required for this service to be registered.\n\t *\n\t * @return string[] List of required services.\n\t */\n\tpublic static function get_requirements(): array {\n\t\treturn [ 'service_a' ];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Fixture/DummyTaxonomy.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Fixture;\n\nuse Google\\Web_Stories\\REST_API\\Stories_Terms_Controller;\nuse Google\\Web_Stories\\Taxonomy\\Taxonomy_Base;\n\n/**\n * Dummy taxonomy.\n *\n * @phpstan-import-type TaxonomyArgs from \\Google\\Web_Stories\\Taxonomy\\Taxonomy_Base\n */\nclass DummyTaxonomy extends Taxonomy_Base {\n\tpublic function __construct() {\n\t\t$this->taxonomy_slug      = 'web-story-test-tax';\n\t\t$this->taxonomy_post_type = 'post';\n\t}\n\n\t/**\n\t * @return TaxonomyArgs Taxonomy args.\n\t */\n\tprotected function taxonomy_args(): array {\n\t\treturn [\n\t\t\t'show_in_rest'          => true,\n\t\t\t'rest_controller_class' => Stories_Terms_Controller::class,\n\t\t\t'rest_namespace'        => self::REST_NAMESPACE,\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Kses_Setup.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\KSES;\nuse Google\\Web_Stories\\Page_Template_Post_Type;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * Trait Kses_Setup\n *\n * Helper trait to setup KSES. This is normally setup on init but needed to be manually fired in tests.\n */\ntrait Kses_Setup {\n\tpublic ?KSES $kses = null;\n\t/**\n\t * Setup KSES init class.\n\t */\n\tprotected function kses_int(): void {\n\t\t$settings        = $this->createMock( Settings::class );\n\t\t$story_post_type = new Story_Post_Type( $settings );\n\t\t$this->kses      = new KSES(\n\t\t\t$story_post_type,\n\t\t\tnew Page_Template_Post_Type( $story_post_type )\n\t\t);\n\t\t$this->kses->register();\n\t}\n\n\t/**\n\t * Remove filters and reset kses by calling kses init.\n\t */\n\tprotected function kses_remove_filters(): void {\n\t\tkses_init();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Mock_Vendor_Setup.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Tests\\Integration\\Shopping\\Mock_Vendor;\nuse Google\\Web_Stories\\Tests\\Integration\\Shopping\\Mock_Vendor_Error;\nuse Google\\Web_Stories\\Tests\\Integration\\Shopping\\Mock_Vendor_Invalid;\n\n/**\n * Trait Mock_Vendor_Setup\n */\ntrait Mock_Vendor_Setup {\n\n\t/**\n\t * Add mock vendor to array with filter.\n\t *\n\t * @param array<string, array<string,string>> $unused\n\t * @return array<string, array<string,string>>\n\t */\n\tpublic function add_mock_vendor( array $unused ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found\n\t\treturn [\n\t\t\t'none'    => [\n\t\t\t\t'label' => 'None',\n\t\t\t],\n\t\t\t'mock'    => [\n\t\t\t\t'label' => 'Mock',\n\t\t\t\t'class' => Mock_Vendor::class,\n\t\t\t],\n\t\t\t'error'   => [\n\t\t\t\t'label' => 'Error',\n\t\t\t\t'class' => Mock_Vendor_Error::class,\n\t\t\t],\n\t\t\t'invalid' => [\n\t\t\t\t'label' => 'invalid',\n\t\t\t\t'class' => Mock_Vendor_Invalid::class,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Add filter to add vendor.\n\t */\n\tprotected function setup_vendors(): void {\n\t\tadd_filter( 'web_stories_shopping_vendors', [ $this, 'add_mock_vendor' ] );\n\t}\n\n\t/**\n\t * Remove filter to remove vendor.\n\t */\n\tprotected function remove_vendors(): void {\n\t\tremove_filter( 'web_stories_shopping_vendors', [ $this, 'add_mock_vendor' ] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/REST_Setup.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * REST_Setup trait.\n *\n * Add method assertErrorResponse to any test class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Spy_REST_Server;\nuse WP_Error;\nuse WP_REST_Response;\n\n/**\n * trait REST_Setup\n */\ntrait REST_Setup {\n\tuse Capabilities_Setup;\n\tuse Kses_Setup;\n\n\tprotected function set_up_rest(): void {\n\t\t/** @var \\WP_REST_Server $wp_rest_server */\n\t\tglobal $wp_rest_server;\n\t\t$wp_rest_server = new Spy_REST_Server();\n\t\tdo_action( 'rest_api_init', $wp_rest_server );\n\n\t\t$this->add_caps_to_roles();\n\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\t}\n\n\tprotected function tear_down_rest(): void {\n\t\t/** @var \\WP_REST_Server $wp_rest_server */\n\t\tglobal $wp_rest_server;\n\t\t$wp_rest_server = null;\n\n\t\t$this->remove_caps_from_roles();\n\t}\n\n\t/**\n\t * Copied from WordPress code.\n\t *\n\t * @link https://github.com/WordPress/wordpress-develop/blob/2382765afa36e10bf3c74420024ad4e85763a47c/tests/phpunit/includes/testcase-rest-api.php#L4-L18\n\t *\n\t * @param string                         $code     Status code.\n\t * @param WP_REST_Response|WP_Error|bool $response Response object.\n\t * @param int|null                       $status   Status code.\n\t */\n\tprotected function assertErrorResponse( string $code, $response, ?int $status = null ): void {\n\n\t\tif ( $response instanceof WP_REST_Response ) {\n\t\t\t$response = $response->as_error();\n\t\t}\n\n\t\t$this->assertWPError( $response );\n\t\t$this->assertSame( $code, $response->get_error_code() );\n\n\t\tif ( null !== $status ) {\n\t\t\t$data = $response->get_error_data();\n\t\t\t$this->assertIsArray( $data );\n\t\t\t$this->assertArrayHasKey( 'status', $data );\n\t\t\t$this->assertSame( $status, $data['status'] );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/RestTestCase.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * RestTestCase class.\n *\n * Basic test that designed to replace WP_Test_REST_TestCase.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * Class RestTestCase\n */\nabstract class RestTestCase extends TestCase {\n\tuse REST_Setup;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->set_up_rest();\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->tear_down_rest();\n\n\t\tparent::tear_down();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Shopping/Mock_Vendor.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\nuse Google\\Web_Stories\\Shopping\\Product;\nuse WP_Error;\n\n/**\n *\n */\nclass Mock_Vendor implements Product_Query {\n\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort collection by product attribute.\n\t * @param string $order       Order sort attribute ascending or descending.\n\t * @return array{products: array<Product>, has_next_page: bool}|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' ) {\n\t\t$products = [];\n\t\tfor ( $x = 0; $x < $per_page; $x++ ) {\n\t\t\t$products[] = new Product(\n\t\t\t\t[\n\t\t\t\t\t'id'             => wp_unique_id(),\n\t\t\t\t\t'title'          => 'Product ' . $x,\n\t\t\t\t\t'brand'          => 'Google',\n\t\t\t\t\t'price'          => 1.00 * $x,\n\t\t\t\t\t'price_currency' => 'USD',\n\t\t\t\t\t'images'         => [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'url' => \"https://example.com/product/$x.png\",\n\t\t\t\t\t\t\t'alt' => '',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'details'        => 'Description',\n\t\t\t\t\t'url'            => 'https://example.com/product/' . $x,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\t\t$has_next_page = false;\n\t\treturn compact( 'products', 'has_next_page' );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Shopping/Mock_Vendor_Error.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\nuse WP_Error;\n\n/**\n *\n */\nclass Mock_Vendor_Error implements Product_Query {\n\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort collection by product attribute.\n\t * @param string $order       Order sort attribute ascending or descending.\n\t * @return array<string, array<string,string>>|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' ) {\n\t\treturn new WP_Error( 'mock_error', 'Mock error', [ 'status' => 400 ] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Shopping/Mock_Vendor_Invalid.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Shopping\\Product;\nuse WP_Error;\n\n/**\n *\n */\nclass Mock_Vendor_Invalid {\n\n\t/**\n\t * Get products by search term.\n\t *\n\t * @since 1.21.0\n\t *\n\t * @param string $search_term Search term.\n\t * @param int    $page        Number of page for paginated requests.\n\t * @param int    $per_page    Number of products to be fetched.\n\t * @param string $orderby     Sort collection by product attribute.\n\t * @param string $order       Order sort attribute ascending or descending.\n\t * @return array{products: array<Product>, has_next_page: bool}|WP_Error\n\t */\n\tpublic function get_search( string $search_term, int $page = 1, int $per_page = 100, string $orderby = 'date', string $order = 'desc' ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed\n\t\t$products = [];\n\t\tfor ( $x = 0; $x < $per_page; $x++ ) {\n\t\t\t$products[] = new Product(\n\t\t\t\t[\n\t\t\t\t\t'id'             => wp_unique_id(),\n\t\t\t\t\t'title'          => 'Product ' . $x,\n\t\t\t\t\t'brand'          => 'Google',\n\t\t\t\t\t'price'          => 1.00 * $x,\n\t\t\t\t\t'price_currency' => 'USD',\n\t\t\t\t\t'images'         => [],\n\t\t\t\t\t'details'        => 'Description',\n\t\t\t\t\t'url'            => 'http://www.google.com/product/' . $x,\n\t\t\t\t]\n\t\t\t);\n\t\t}\n\n\t\t$has_next_page = false;\n\t\treturn compact( 'products', 'has_next_page' );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/TestCase.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * TestCase class.\n *\n * Basic test case for use with a WP Integration test test suite.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Tests\\Shared\\Private_Access;\nuse Yoast\\WPTestUtils\\WPIntegration\\TestCase as PolyfilledTestCase;\n\n/**\n * Class TestCase\n */\nabstract class TestCase extends PolyfilledTestCase {\n\tuse Private_Access;\n\n\t/**\n\t * Clean up again after each test run.\n\t */\n\tpublic function tear_down(): void {\n\t\t// WordPress core fails to do this.\n\t\t$GLOBALS['wp_the_query'] = $GLOBALS['wp_query'];\n\n\t\t// WordPress core fails to do this.\n\t\t// current_screen reset was only added in 5.9+, see https://core.trac.wordpress.org/ticket/53431.\n\t\tunset(\n\t\t\t$GLOBALS['current_screen'],\n\t\t\t$GLOBALS['show_admin_bar'],\n\t\t\t$GLOBALS['wp_meta_boxes'],\n\t\t\t$GLOBALS['hook_suffix'],\n\t\t\t$GLOBALS['menu'],\n\t\t\t$GLOBALS['submenu'],\n\t\t\t$GLOBALS['_wp_real_parent_file'],\n\t\t\t$GLOBALS['_wp_submenu_nopriv'],\n\t\t\t$GLOBALS['_registered_pages'],\n\t\t\t$GLOBALS['_parent_pages'],\n\t\t\t$_SERVER['HTTPS']\n\t\t);\n\n\t\t$this->set_permalink_structure( '' );\n\n\t\t$_SERVER['REQUEST_URI'] = '';\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @param mixed $data Product data.\n\t */\n\tprotected function assertMatchesProductSchema( $data ): void {\n\t\t$schema = (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/schema.json' );\n\t\t$schema = (array) json_decode( $schema, true );\n\n\t\t$this->assertTrue( rest_validate_value_from_schema( $data, $schema, 'product' ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/includes/Test_Renderer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Test_Renderer class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Renderer;\n\n/**\n * Generic_Renderer class.\n */\nclass Test_Renderer extends Renderer {\n\n\t/**\n\t * Render method\n\t *\n\t * @param array<string,mixed> $args Array of rendering arguments.\n\t */\n\tpublic function render( array $args = [] ): string {\n\t\treturn '';\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/stubs/WP_Site.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nif ( ! class_exists( 'WP_Site' ) ) {\n\tclass WP_Site {}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AMP/Canonical_Sanitizer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\AMP;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer\n */\nclass Canonical_Sanitizer extends TestCase {\n\tprotected static int $user_id;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_missing_draft(): void {\n\t\t// Needed so that the user is allowed to preview drafts.\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$post_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_status' => 'draft',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post_id );\n\n\t\t$canonical = get_permalink( $post_id );\n\n\t\t$source = '<html><head><title>Example</title></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * @var Document $dom\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$this->go_to( (string) get_preview_post_link( $post_id ) );\n\t\t$this->assertQueryTrue( 'is_single', 'is_singular', 'is_preview' );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => get_permalink( $post_id ) ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\n\t\twp_delete_post( $post_id );\n\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"', $actual );\n\t\t$this->assertStringNotContainsString( '<link rel=\"canonical\" href=\"\">', $actual );\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"' . $canonical . '\">', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AMP/Optimization.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\AMP;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Configuration;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpBoilerplate;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpBoilerplateErrorHandler;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpRuntimePreloads;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\AmpStoryCssOptimizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\GoogleFontsPreconnect;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\MinifyHtml;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\OptimizeViewport;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Optimizer\\Transformer\\ReorderHead;\nuse WP_Error;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Optimization\n */\nclass Optimization extends TestCase {\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_http_request' ] );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Intercept link processing requests and mock responses.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param mixed  $r       HTTP request arguments.\n\t * @param string $url     The request URL.\n\t * @return mixed|WP_Error Response data.\n\t */\n\tpublic function mock_http_request( $preempt, $r, string $url ) {\n\t\tif ( 'https://cdn.ampproject.org/rtv/metadata' === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'application/json',\n\t\t\t\t\t'content-length' => 100,\n\t\t\t\t],\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t\t'body' => file_get_contents( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/ampproject/amp-toolbox/resources/local_fallback/rtv/metadata' ),\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\n\t\tif ( 'https://cdn.ampproject.org/v0.css' === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'text/css',\n\t\t\t\t\t'content-length' => 100,\n\t\t\t\t],\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t\t'body' => file_get_contents( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/ampproject/amp-toolbox/resources/local_fallback/v0.css' ),\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\n\t\treturn $preempt;\n\t}\n\n\t/**\n\t * @covers ::optimize_document\n\t * @covers ::get_optimizer\n\t */\n\tpublic function test_optimize_document(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html amp lang=\"en\">\n\t\t<head>\n\t\t\t<meta charset=\"utf-8\">\n\t\t\t<script async src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t\t<script async custom-element=\"amp-story\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\"></script>\n\t\t\t<title>My Story</title>\n\t\t\t<meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\">\n\t\t\t<link rel=\"canonical\" href=\"helloworld.html\">\n\t\t\t<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>\n\t\t</head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t</body>\n\t\t</html>\n\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\n\t\t$optimization = new \\Google\\Web_Stories\\AMP\\Optimization();\n\t\t$optimization->optimize_document( $document );\n\n\t\t$actual = $document->saveHTML();\n\n\t\t$this->assertStringContainsString( 'transformed=\"self;v=1', $actual );\n\t\t$this->assertStringNotContainsString( 'Cannot remove boilerplate because of an unsupported layout: amp-story', $actual );\n\t}\n\n\t/**\n\t * @covers ::get_optimizer_configuration\n\t */\n\tpublic function test_get_optimizer_configuration(): void {\n\t\t$optimization = new \\Google\\Web_Stories\\AMP\\Optimization();\n\n\t\t$configuration = $this->call_private_method( [ $optimization, 'get_optimizer_configuration' ] );\n\n\t\t/**\n\t\t * @var array<string, array<string, mixed>> $config_array\n\t\t */\n\t\t$config_array = $this->get_private_property( $configuration, 'configuration' );\n\n\t\t$transformers   = Configuration::DEFAULT_TRANSFORMERS;\n\t\t$transformers[] = AmpStoryCssOptimizer::class;\n\n\t\t$this->assertCount( 3, $config_array );\n\t\t$this->assertArrayHasKey( 'transformers', $config_array );\n\t\t$this->assertEqualSets( $transformers, $config_array['transformers'] );\n\t}\n\n\t/**\n\t * @covers ::get_optimizer_configuration\n\t */\n\tpublic function test_get_optimizer_configuration_no_ssr(): void {\n\t\tadd_filter( 'web_stories_enable_ssr', '__return_false' );\n\n\t\t$optimization = new \\Google\\Web_Stories\\AMP\\Optimization();\n\n\t\t$configuration = $this->call_private_method( [ $optimization, 'get_optimizer_configuration' ] );\n\n\t\t/**\n\t\t * @var array<string, array<string, mixed>> $config_array\n\t\t */\n\t\t$config_array = $this->get_private_property( $configuration, 'configuration' );\n\n\t\tremove_filter( 'web_stories_enable_ssr', '__return_false' );\n\n\t\t$transformers = [\n\t\t\tAmpBoilerplate::class,\n\t\t\tAmpRuntimePreloads::class,\n\t\t\tAmpBoilerplateErrorHandler::class,\n\t\t\tGoogleFontsPreconnect::class,\n\t\t\tMinifyHtml::class,\n\t\t\tOptimizeViewport::class,\n\t\t\tReorderHead::class,\n\t\t];\n\n\t\t$this->assertCount( 3, $config_array );\n\t\t$this->assertArrayHasKey( 'transformers', $config_array );\n\t\t$this->assertEqualSets( $transformers, $config_array['transformers'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AMP/Output_Buffer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\AMP;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\HTML;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Error;\nuse WP_Post;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Output_Buffer\n */\nclass Output_Buffer extends DependencyInjectedTestCase {\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );\n\n\t\t// When running the tests, we don't have unfiltered_html capabilities.\n\t\t// This change avoids HTML in post_content being stripped in our test posts because of KSES.\n\t\tremove_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tremove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_http_request' ] );\n\n\t\tadd_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tadd_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Intercept link processing requests and mock responses.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param mixed  $r       HTTP request arguments.\n\t * @param string $url     The request URL.\n\t * @return mixed|WP_Error Response data.\n\t */\n\tpublic function mock_http_request( $preempt, $r, string $url ) {\n\t\tif ( 'https://cdn.ampproject.org/rtv/metadata' === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'application/json',\n\t\t\t\t\t'content-length' => 100,\n\t\t\t\t],\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t\t'body' => file_get_contents( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/ampproject/amp-toolbox/resources/local_fallback/rtv/metadata' ),\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\n\t\tif ( 'https://cdn.ampproject.org/v0.css' === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'text/css',\n\t\t\t\t\t'content-length' => 100,\n\t\t\t\t],\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t\t'body' => file_get_contents( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/ampproject/amp-toolbox/resources/local_fallback/v0.css' ),\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\n\t\treturn $preempt;\n\t}\n\n\t/**\n\t * @covers ::prepare_response\n\t */\n\tpublic function test_sanitizes_and_optimizes_markup(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'transformed=\"self;v=1\"', $actual );\n\t\t$this->assertStringNotContainsString( 'AMP optimization could not be completed', $actual );\n\t}\n\n\t/**\n\t * Tests that publisher name is correctly replaced.\n\t *\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher\n\t */\n\tpublic function test_add_publisher(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" title=\"Example Story\"  poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\t$name = get_bloginfo( 'name' );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'publisher=', $actual );\n\t\t$this->assertStringContainsString( $name, $actual );\n\t}\n\n\t/**\n\t * Tests that publisher logo is correctly replaced.\n\t *\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_add_publisher_logo(): void {\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\"  poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\tadd_post_meta( $post->ID, Story_Post_Type::PUBLISHER_LOGO_META_KEY, $attachment_id );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\t$logo = wp_get_attachment_url( $attachment_id );\n\t\t$name = get_bloginfo( 'name' );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertNotFalse( $logo );\n\t\t$this->assertStringContainsString( 'publisher-logo-src=\"http', $actual );\n\t\t$this->assertStringContainsString( $name, $actual );\n\t\t$this->assertStringContainsString( $logo, $actual );\n\n\t\tdelete_post_meta( $post->ID, Story_Post_Type::PUBLISHER_LOGO_META_KEY );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'publisher-logo-src=\"\"', $actual );\n\t\t$this->assertStringContainsString( 'amp=', $actual );\n\t}\n\n\t/**\n\t * Tests that publisher logo is correctly replaced.\n\t *\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_add_publisher_logo_missing(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\"  poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'publisher-logo-src=\"\"', $actual );\n\t\t$this->assertStringContainsString( 'amp=', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_poster_images\n\t */\n\tpublic function test_add_poster_images(): void {\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\tset_post_thumbnail( $post->ID, $attachment_id );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'poster-portrait-src=', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_add_poster_images_overrides_existing_poster(): void {\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\"  publisher-logo=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/poster.jpg\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\tset_post_thumbnail( $post->ID, $attachment_id );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringNotContainsString( 'https://example.com/poster.jpg', $actual );\n\t\t$this->assertStringContainsString( 'poster-portrait-src=', $actual );\n\t\t$this->assertStringContainsString( (string) wp_get_attachment_url( $attachment_id ), $actual );\n\t\t$this->assertStringNotContainsString( 'poster-portrait-src=\"\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_add_poster_images_no_fallback_image_added(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'poster-portrait-src=\"\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_add_poster_images_no_poster_no_amp(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->go_to( (string) get_permalink( $post ) );\n\n\t\t$actual = $this->prepare_response( $post );\n\n\t\t$this->assertStringContainsString( 'amp=', $actual );\n\t}\n\n\tprotected function prepare_response( WP_Post $post ): string {\n\t\t$instance = $this->injector->make( \\Google\\Web_Stories\\AMP\\Output_Buffer::class );\n\t\t$story    = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\treturn $instance->prepare_response( ( new HTML( $story ) )->render() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AMP/Sanitization.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\AMP;\n\nuse DOMElement;\nuse DOMNodeList;\nuse Google\\Web_Stories\\AMP\\Meta_Sanitizer;\nuse Google\\Web_Stories\\AMP\\Tag_And_Attribute_Sanitizer;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse Google\\Web_Stories_Dependencies\\AMP_Dev_Mode_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Layout_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AMP_Style_Sanitizer;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Sanitization\n */\nclass Sanitization extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\AMP\\Sanitization $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\AMP\\Sanitization::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_all_filters( 'web_stories_amp_sanitizers' );\n\t\tremove_all_filters( 'web_stories_amp_dev_mode_enabled' );\n\t\tremove_all_filters( 'web_stories_amp_dev_mode_element_xpaths' );\n\t\tremove_all_filters( 'show_admin_bar' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @see Test_AMP_Theme_Support::test_scripts_get_moved_to_head\n\t *\n\t * @covers ::sanitize_document\n\t * @covers ::ensure_required_markup\n\t */\n\tpublic function test_scripts_get_moved_to_head(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head>\n\t\t</head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t/**\n\t\t * @var DOMNodeList $scripts\n\t\t */\n\t\t$scripts = $document->xpath->query( '//script[ not( @type ) or @type = \"text/javascript\" ]' );\n\t\t$this->assertSame( 2, $scripts->length );\n\t\tforeach ( $scripts as $script ) {\n\t\t\t$this->assertIsObject( $script );\n\t\t\t$this->assertTrue( property_exists( $script, 'parentNode' ) );\n\t\t\t$this->assertSame( 'head', $script->parentNode->nodeName );\n\n\t\t}\n\t}\n\n\t/**\n\t * @see Test_AMP_Theme_Support::test_unneeded_scripts_get_removed\n\t *\n\t * @covers ::ensure_required_markup\n\t */\n\tpublic function test_unneeded_scripts_get_removed(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head></head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t<script src=\"https://cdn.ampproject.org/v0/amp-analytics-0.1.js\" async=\"\" custom-element=\"amp-analytics\"></script>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t/**\n\t\t * @var string[] $actual_script_srcs\n\t\t */\n\t\t$actual_script_srcs = [];\n\n\t\t/**\n\t\t * @var DOMElement[] $scripts\n\t\t */\n\t\t$scripts = $document->xpath->query( '//script[ not( @type ) or @type = \"text/javascript\" ]' );\n\t\tforeach ( $scripts as $script ) {\n\t\t\t$actual_script_srcs[] = $script->getAttribute( 'src' );\n\t\t}\n\n\t\t$expected_script_srcs = [\n\t\t\t'https://cdn.ampproject.org/v0.js',\n\t\t\t'https://cdn.ampproject.org/v0/amp-story-1.0.js',\n\t\t];\n\n\t\t$this->assertEqualSets(\n\t\t\t$expected_script_srcs,\n\t\t\t$actual_script_srcs\n\t\t);\n\t}\n\n\t/**\n\t * @see Test_AMP_Theme_Support::test_duplicate_scripts_are_removed\n\t *\n\t * @covers AMP_Theme_Support::prepare_response\n\t * @covers AMP_Theme_Support::ensure_required_markup\n\t */\n\tpublic function test_duplicate_scripts_are_removed(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t</head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t$script_srcs = [];\n\n\t\t/**\n\t\t * Script.\n\t\t *\n\t\t * @var DOMElement[]  $scripts\n\t\t */\n\t\t$scripts = $document->xpath->query( '//script[ @src ]' );\n\n\t\tforeach ( $scripts as $script ) {\n\t\t\t$script_srcs[] = $script->getAttribute( 'src' );\n\t\t}\n\n\t\t$this->assertCount( 2, $script_srcs );\n\t\t$this->assertEquals(\n\t\t\t$script_srcs,\n\t\t\t[\n\t\t\t\t'https://cdn.ampproject.org/v0.js',\n\t\t\t\t'https://cdn.ampproject.org/v0/amp-story-1.0.js',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::ensure_required_markup\n\t */\n\tpublic function test_missing_scripts_get_added(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head></head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t\t<amp-analytics type=\"gtag\" data-credentials=\"include\">\n\t\t\t\t<script type=\"application/json\">{}</script>\n\t\t\t</amp-analytics>\n\t\t</amp-story>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t/**\n\t\t * @var string[] $actual_script_srcs\n\t\t */\n\t\t$actual_script_srcs = [];\n\n\t\t/**\n\t\t * Script.\n\t\t *\n\t\t * @var DOMElement[]  $scripts\n\t\t */\n\t\t$scripts = $document->xpath->query( '//script[ not( @type ) or @type = \"text/javascript\" ]' );\n\t\tforeach ( $scripts as $script ) {\n\t\t\t$actual_script_srcs[] = $script->getAttribute( 'src' );\n\t\t}\n\n\t\t$expected_script_srcs = [\n\t\t\t'https://cdn.ampproject.org/v0.js',\n\t\t\t'https://cdn.ampproject.org/v0/amp-story-1.0.js',\n\t\t\t'https://cdn.ampproject.org/v0/amp-analytics-0.1.js',\n\t\t];\n\n\t\t$this->assertEqualSets(\n\t\t\t$expected_script_srcs,\n\t\t\t$actual_script_srcs\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_extension_sources\n\t */\n\tpublic function test_get_extension_sources(): void {\n\t\t$sources = $this->call_private_method( [ $this->instance, 'get_extension_sources' ] );\n\n\t\t$actual = [];\n\n\t\tforeach ( $sources as $extension => $src ) {\n\t\t\t$actual[ $extension ] = str_replace( 'https://cdn.ampproject.org/', '', $src );\n\t\t}\n\n\t\t// This allows us to ensure that we catch any version changes in scripts.\n\t\t$expected = [\n\t\t\t'amp-3d-gltf'                  => 'v0/amp-3d-gltf-0.1.js',\n\t\t\t'amp-3q-player'                => 'v0/amp-3q-player-0.1.js',\n\t\t\t'amp-access'                   => 'v0/amp-access-0.1.js',\n\t\t\t'amp-access-fewcents'          => 'v0/amp-access-fewcents-0.1.js',\n\t\t\t'amp-access-laterpay'          => 'v0/amp-access-laterpay-0.2.js',\n\t\t\t'amp-access-poool'             => 'v0/amp-access-poool-0.1.js',\n\t\t\t'amp-access-scroll'            => 'v0/amp-access-scroll-0.1.js',\n\t\t\t'amp-accordion'                => 'v0/amp-accordion-0.1.js',\n\t\t\t'amp-action-macro'             => 'v0/amp-action-macro-0.1.js',\n\t\t\t'amp-ad'                       => 'v0/amp-ad-0.1.js',\n\t\t\t'amp-ad-custom'                => 'v0/amp-ad-custom-0.1.js',\n\t\t\t'amp-addthis'                  => 'v0/amp-addthis-0.1.js',\n\t\t\t'amp-analytics'                => 'v0/amp-analytics-0.1.js',\n\t\t\t'amp-anim'                     => 'v0/amp-anim-0.1.js',\n\t\t\t'amp-animation'                => 'v0/amp-animation-0.1.js',\n\t\t\t'amp-apester-media'            => 'v0/amp-apester-media-0.1.js',\n\t\t\t'amp-app-banner'               => 'v0/amp-app-banner-0.1.js',\n\t\t\t'amp-audio'                    => 'v0/amp-audio-0.1.js',\n\t\t\t'amp-auto-ads'                 => 'v0/amp-auto-ads-0.1.js',\n\t\t\t'amp-autocomplete'             => 'v0/amp-autocomplete-0.1.js',\n\t\t\t'amp-base-carousel'            => 'v0/amp-base-carousel-0.1.js',\n\t\t\t'amp-beopinion'                => 'v0/amp-beopinion-0.1.js',\n\t\t\t'amp-bind'                     => 'v0/amp-bind-0.1.js',\n\t\t\t'amp-bodymovin-animation'      => 'v0/amp-bodymovin-animation-0.1.js',\n\t\t\t'amp-brid-player'              => 'v0/amp-brid-player-0.1.js',\n\t\t\t'amp-brightcove'               => 'v0/amp-brightcove-0.1.js',\n\t\t\t'amp-byside-content'           => 'v0/amp-byside-content-0.1.js',\n\t\t\t'amp-cache-url'                => 'v0/amp-cache-url-0.1.js',\n\t\t\t'amp-call-tracking'            => 'v0/amp-call-tracking-0.1.js',\n\t\t\t// The AMP plugin forces this to be 0.2, but we don't need that.\n\t\t\t// See https://github.com/ampproject/amp-wp/blob/d2d441cf6f1f4e9a7268a9c6e3360be309852a2c/includes/amp-helper-functions.php#L918-L925.\n\t\t\t'amp-carousel'                 => 'v0/amp-carousel-0.1.js',\n\t\t\t'amp-connatix-player'          => 'v0/amp-connatix-player-0.1.js',\n\t\t\t'amp-consent'                  => 'v0/amp-consent-0.1.js',\n\t\t\t'amp-dailymotion'              => 'v0/amp-dailymotion-0.1.js',\n\t\t\t'amp-date-countdown'           => 'v0/amp-date-countdown-0.1.js',\n\t\t\t'amp-date-display'             => 'v0/amp-date-display-0.1.js',\n\t\t\t'amp-date-picker'              => 'v0/amp-date-picker-0.1.js',\n\t\t\t'amp-delight-player'           => 'v0/amp-delight-player-0.1.js',\n\t\t\t'amp-dynamic-css-classes'      => 'v0/amp-dynamic-css-classes-0.1.js',\n\t\t\t'amp-embedly-card'             => 'v0/amp-embedly-card-0.1.js',\n\t\t\t'amp-experiment'               => 'v0/amp-experiment-0.1.js',\n\t\t\t'amp-facebook'                 => 'v0/amp-facebook-0.1.js',\n\t\t\t'amp-facebook-comments'        => 'v0/amp-facebook-comments-0.1.js',\n\t\t\t'amp-facebook-like'            => 'v0/amp-facebook-like-0.1.js',\n\t\t\t'amp-facebook-page'            => 'v0/amp-facebook-page-0.1.js',\n\t\t\t'amp-fit-text'                 => 'v0/amp-fit-text-0.1.js',\n\t\t\t'amp-font'                     => 'v0/amp-font-0.1.js',\n\t\t\t'amp-form'                     => 'v0/amp-form-0.1.js',\n\t\t\t'amp-fx-collection'            => 'v0/amp-fx-collection-0.1.js',\n\t\t\t'amp-fx-flying-carpet'         => 'v0/amp-fx-flying-carpet-0.1.js',\n\t\t\t'amp-geo'                      => 'v0/amp-geo-0.1.js',\n\t\t\t'amp-gfycat'                   => 'v0/amp-gfycat-0.1.js',\n\t\t\t'amp-gist'                     => 'v0/amp-gist-0.1.js',\n\t\t\t'amp-google-document-embed'    => 'v0/amp-google-document-embed-0.1.js',\n\t\t\t'amp-google-read-aloud-player' => 'v0/amp-google-read-aloud-player-0.1.js',\n\t\t\t'amp-hulu'                     => 'v0/amp-hulu-0.1.js',\n\t\t\t'amp-iframe'                   => 'v0/amp-iframe-0.1.js',\n\t\t\t'amp-iframely'                 => 'v0/amp-iframely-0.1.js',\n\t\t\t'amp-ima-video'                => 'v0/amp-ima-video-0.1.js',\n\t\t\t'amp-image-lightbox'           => 'v0/amp-image-lightbox-0.1.js',\n\t\t\t'amp-image-slider'             => 'v0/amp-image-slider-0.1.js',\n\t\t\t'amp-imgur'                    => 'v0/amp-imgur-0.1.js',\n\t\t\t'amp-inline-gallery'           => 'v0/amp-inline-gallery-0.1.js',\n\t\t\t'amp-inputmask'                => 'v0/amp-inputmask-0.1.js',\n\t\t\t'amp-instagram'                => 'v0/amp-instagram-0.1.js',\n\t\t\t'amp-install-serviceworker'    => 'v0/amp-install-serviceworker-0.1.js',\n\t\t\t'amp-izlesene'                 => 'v0/amp-izlesene-0.1.js',\n\t\t\t'amp-jwplayer'                 => 'v0/amp-jwplayer-0.1.js',\n\t\t\t'amp-kaltura-player'           => 'v0/amp-kaltura-player-0.1.js',\n\t\t\t'amp-lightbox'                 => 'v0/amp-lightbox-0.1.js',\n\t\t\t'amp-lightbox-gallery'         => 'v0/amp-lightbox-gallery-0.1.js',\n\t\t\t'amp-link-rewriter'            => 'v0/amp-link-rewriter-0.1.js',\n\t\t\t'amp-list'                     => 'v0/amp-list-0.1.js',\n\t\t\t'amp-live-list'                => 'v0/amp-live-list-0.1.js',\n\t\t\t'amp-mathml'                   => 'v0/amp-mathml-0.1.js',\n\t\t\t'amp-mega-menu'                => 'v0/amp-mega-menu-0.1.js',\n\t\t\t'amp-megaphone'                => 'v0/amp-megaphone-0.1.js',\n\t\t\t'amp-minute-media-player'      => 'v0/amp-minute-media-player-0.1.js',\n\t\t\t'amp-mowplayer'                => 'v0/amp-mowplayer-0.1.js',\n\t\t\t'amp-mustache'                 => 'v0/amp-mustache-0.2.js',\n\t\t\t'amp-nested-menu'              => 'v0/amp-nested-menu-0.1.js',\n\t\t\t'amp-next-page'                => 'v0/amp-next-page-1.0.js',\n\t\t\t'amp-nexxtv-player'            => 'v0/amp-nexxtv-player-0.1.js',\n\t\t\t'amp-o2-player'                => 'v0/amp-o2-player-0.1.js',\n\t\t\t'amp-onetap-google'            => 'v0/amp-onetap-google-0.1.js',\n\t\t\t'amp-ooyala-player'            => 'v0/amp-ooyala-player-0.1.js',\n\t\t\t'amp-orientation-observer'     => 'v0/amp-orientation-observer-0.1.js',\n\t\t\t'amp-pan-zoom'                 => 'v0/amp-pan-zoom-0.1.js',\n\t\t\t'amp-pinterest'                => 'v0/amp-pinterest-0.1.js',\n\t\t\t'amp-playbuzz'                 => 'v0/amp-playbuzz-0.1.js',\n\t\t\t'amp-position-observer'        => 'v0/amp-position-observer-0.1.js',\n\t\t\t'amp-powr-player'              => 'v0/amp-powr-player-0.1.js',\n\t\t\t'amp-reach-player'             => 'v0/amp-reach-player-0.1.js',\n\t\t\t'amp-recaptcha-input'          => 'v0/amp-recaptcha-input-0.1.js',\n\t\t\t'amp-reddit'                   => 'v0/amp-reddit-0.1.js',\n\t\t\t'amp-render'                   => 'v0/amp-render-1.0.js',\n\t\t\t'amp-riddle-quiz'              => 'v0/amp-riddle-quiz-0.1.js',\n\t\t\t'amp-script'                   => 'v0/amp-script-0.1.js',\n\t\t\t'amp-selector'                 => 'v0/amp-selector-0.1.js',\n\t\t\t'amp-sidebar'                  => 'v0/amp-sidebar-0.1.js',\n\t\t\t'amp-skimlinks'                => 'v0/amp-skimlinks-0.1.js',\n\t\t\t'amp-smartlinks'               => 'v0/amp-smartlinks-0.1.js',\n\t\t\t'amp-social-share'             => 'v0/amp-social-share-0.1.js',\n\t\t\t'amp-soundcloud'               => 'v0/amp-soundcloud-0.1.js',\n\t\t\t'amp-springboard-player'       => 'v0/amp-springboard-player-0.1.js',\n\t\t\t'amp-sticky-ad'                => 'v0/amp-sticky-ad-1.0.js',\n\t\t\t'amp-story'                    => 'v0/amp-story-1.0.js',\n\t\t\t'amp-story-360'                => 'v0/amp-story-360-0.1.js',\n\t\t\t'amp-story-auto-ads'           => 'v0/amp-story-auto-ads-0.1.js',\n\t\t\t'amp-story-auto-analytics'     => 'v0/amp-story-auto-analytics-0.1.js',\n\t\t\t'amp-story-captions'           => 'v0/amp-story-captions-0.1.js',\n\t\t\t'amp-story-interactive'        => 'v0/amp-story-interactive-0.1.js',\n\t\t\t'amp-story-panning-media'      => 'v0/amp-story-panning-media-0.1.js',\n\t\t\t'amp-story-player'             => 'v0/amp-story-player-0.1.js',\n\t\t\t'amp-story-shopping'           => 'v0/amp-story-shopping-0.1.js',\n\t\t\t'amp-story-subscriptions'      => 'v0/amp-story-subscriptions-0.1.js',\n\t\t\t'amp-stream-gallery'           => 'v0/amp-stream-gallery-0.1.js',\n\t\t\t'amp-subscriptions'            => 'v0/amp-subscriptions-0.1.js',\n\t\t\t'amp-subscriptions-google'     => 'v0/amp-subscriptions-google-0.1.js',\n\t\t\t'amp-tiktok'                   => 'v0/amp-tiktok-0.1.js',\n\t\t\t'amp-timeago'                  => 'v0/amp-timeago-0.1.js',\n\t\t\t'amp-truncate-text'            => 'v0/amp-truncate-text-0.1.js',\n\t\t\t'amp-twitter'                  => 'v0/amp-twitter-0.1.js',\n\t\t\t'amp-user-notification'        => 'v0/amp-user-notification-0.1.js',\n\t\t\t'amp-video'                    => 'v0/amp-video-0.1.js',\n\t\t\t'amp-video-docking'            => 'v0/amp-video-docking-0.1.js',\n\t\t\t'amp-video-iframe'             => 'v0/amp-video-iframe-0.1.js',\n\t\t\t'amp-vimeo'                    => 'v0/amp-vimeo-0.1.js',\n\t\t\t'amp-vine'                     => 'v0/amp-vine-0.1.js',\n\t\t\t'amp-viqeo-player'             => 'v0/amp-viqeo-player-0.1.js',\n\t\t\t'amp-vk'                       => 'v0/amp-vk-0.1.js',\n\t\t\t'amp-web-push'                 => 'v0/amp-web-push-0.1.js',\n\t\t\t'amp-wistia-player'            => 'v0/amp-wistia-player-0.1.js',\n\t\t\t'amp-wordpress-embed'          => 'v0/amp-wordpress-embed-1.0.js',\n\t\t\t'amp-yotpo'                    => 'v0/amp-yotpo-0.1.js',\n\t\t\t'amp-youtube'                  => 'v0/amp-youtube-0.1.js',\n\t\t\t'amp-slikeplayer'              => 'v0/amp-slikeplayer-0.1.js',\n\t\t\t'amp-story-audio-sticker'      => 'v0/amp-story-audio-sticker-0.1.js',\n\t\t];\n\n\t\tforeach ( $sources as $extension => $src ) {\n\t\t\t$this->assertStringStartsWith( 'amp-', $extension );\n\t\t\t$this->assertStringStartsWith( 'https://cdn.ampproject.org/v0/', $src );\n\t\t}\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @see Test_AMP_Helper_Functions::test_amp_is_dev_mode\n\t *\n\t * @covers ::is_amp_dev_mode\n\t */\n\tpublic function test_is_amp_dev_mode(): void {\n\n\t\t$this->assertFalse( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t\tadd_filter( 'web_stories_amp_dev_mode_enabled', '__return_true' );\n\t\t$this->assertTrue( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t\tremove_filter( 'web_stories_amp_dev_mode_enabled', '__return_true' );\n\t\t$this->assertFalse( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t}\n\n\t/**\n\t * @see Test_AMP_Helper_Functions::test_amp_is_dev_mode\n\t *\n\t * @covers ::is_amp_dev_mode\n\t */\n\tpublic function test_is_amp_dev_mode_authenticated_user_admin_bar_showing(): void {\n\t\tadd_filter( 'show_admin_bar', '__return_true' );\n\n\t\t$user_id = self::factory()->user->create( [ 'role' => 'administrator' ] );\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\t$this->assertTrue( is_admin_bar_showing() );\n\t\t$this->assertTrue( is_user_logged_in() );\n\t\t$this->assertTrue( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t}\n\n\t/**\n\t * @see Test_AMP_Helper_Functions::test_amp_is_dev_mode\n\t *\n\t * @covers ::is_amp_dev_mode\n\t */\n\tpublic function test_is_amp_dev_mode_unauthenticated_user_admin_bar_forced(): void {\n\t\t// Test unauthenticated user with admin bar forced.\n\t\tadd_filter( 'show_admin_bar', '__return_true' );\n\t\twp_set_current_user( 0 );\n\n\t\t$this->assertFalse( is_user_logged_in() );\n\t\t$this->assertTrue( is_admin_bar_showing() );\n\t\t$this->assertFalse( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t}\n\n\t/**\n\t * @see Test_AMP_Helper_Functions::test_amp_get_content_sanitizers\n\t *\n\t * @covers ::get_sanitizers\n\t */\n\tpublic function test_get_sanitizers(): void {\n\t\t// Make sure the style and validating sanitizers are always at the end, even after filtering.\n\t\tadd_filter(\n\t\t\t'web_stories_amp_sanitizers',\n\t\t\tstatic function ( $sanitizers ) {\n\t\t\t\t$sanitizers['Even_After_Validating_Sanitizer'] = [];\n\t\t\t\treturn $sanitizers;\n\t\t\t}\n\t\t);\n\n\t\t$sanitizers = $this->call_private_method( [ $this->instance, 'get_sanitizers' ] );\n\n\t\t$ordered_sanitizers = array_keys( $sanitizers );\n\t\t$this->assertEquals( 'Even_After_Validating_Sanitizer', $ordered_sanitizers[ \\count( $ordered_sanitizers ) - 5 ] );\n\t\t$this->assertEquals( AMP_Layout_Sanitizer::class, $ordered_sanitizers[ \\count( $ordered_sanitizers ) - 4 ] );\n\t\t$this->assertEquals( AMP_Style_Sanitizer::class, $ordered_sanitizers[ \\count( $ordered_sanitizers ) - 3 ] );\n\t\t$this->assertEquals( Meta_Sanitizer::class, $ordered_sanitizers[ \\count( $ordered_sanitizers ) - 2 ] );\n\t\t$this->assertEquals( Tag_And_Attribute_Sanitizer::class, $ordered_sanitizers[ \\count( $ordered_sanitizers ) - 1 ] );\n\t}\n\n\t/**\n\t * @see Test_AMP_Helper_Functions::test_amp_get_content_sanitizers_with_dev_mode\n\t *\n\t * @covers ::get_sanitizers\n\t */\n\tpublic function test_get_sanitizers_with_dev_mode(): void {\n\t\t$element_xpaths            = [ '//script[ @id = \"hello-world\" ]' ];\n\t\t$validation_error_callback = [ $this->instance, 'validation_error_callback' ];\n\t\tadd_filter(\n\t\t\t'web_stories_amp_dev_mode_element_xpaths',\n\t\t\tstatic fn( $xpaths ) => array_merge( $xpaths, $element_xpaths )\n\t\t);\n\n\t\t// Check that AMP_Dev_Mode_Sanitizer is not registered if not in dev mode.\n\n\t\t$sanitizers = $this->call_private_method( [ $this->instance, 'get_sanitizers' ] );\n\t\t$this->assertFalse( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t\t$this->assertArrayNotHasKey( AMP_Dev_Mode_Sanitizer::class, $sanitizers );\n\n\t\t// Check that AMP_Dev_Mode_Sanitizer is registered once in dev mode, but not with admin bar showing yet.\n\t\tadd_filter( 'web_stories_amp_dev_mode_enabled', '__return_true' );\n\n\t\t$sanitizers = $this->call_private_method( [ $this->instance, 'get_sanitizers' ] );\n\t\t$this->assertFalse( is_admin_bar_showing() );\n\t\t$this->assertTrue( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t\t$this->assertIsArray( $sanitizers );\n\t\t$this->assertArrayHasKey( AMP_Dev_Mode_Sanitizer::class, $sanitizers );\n\t\t$this->assertEquals( AMP_Dev_Mode_Sanitizer::class, current( array_keys( $sanitizers ) ) );\n\t\t$this->assertEquals(\n\t\t\tcompact( 'element_xpaths', 'validation_error_callback' ),\n\t\t\t$sanitizers[ AMP_Dev_Mode_Sanitizer::class ]\n\t\t);\n\t\tremove_filter( 'web_stories_amp_dev_mode_enabled', '__return_true' );\n\n\t\t// Check that AMP_Dev_Mode_Sanitizer is registered once in dev mode, and now also with admin bar showing.\n\t\tadd_filter( 'web_stories_amp_dev_mode_enabled', '__return_true' );\n\t\tadd_filter( 'show_admin_bar', '__return_true' );\n\n\t\t/**\n\t\t * @var array<string, array<string, array<mixed>>> $sanitizers\n\t\t */\n\t\t$sanitizers = $this->call_private_method( [ $this->instance, 'get_sanitizers' ] );\n\n\t\t$this->assertTrue( is_admin_bar_showing() );\n\t\t$this->assertTrue( $this->call_private_method( [ $this->instance, 'is_amp_dev_mode' ] ) );\n\t\t$this->assertArrayHasKey( AMP_Dev_Mode_Sanitizer::class, $sanitizers );\n\t\t$this->assertEqualSets(\n\t\t\tarray_merge(\n\t\t\t\t$element_xpaths,\n\t\t\t\t[\n\t\t\t\t\t'//*[ @id = \"wpadminbar\" ]',\n\t\t\t\t\t'//*[ @id = \"wpadminbar\" ]//*',\n\t\t\t\t\t'//style[ @id = \"admin-bar-inline-css\" ]',\n\t\t\t\t]\n\t\t\t),\n\t\t\t$sanitizers[ AMP_Dev_Mode_Sanitizer::class ]['element_xpaths']\n\t\t);\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\Integrations\\AMP::filter_amp_validation_error_sanitized\n\t */\n\tpublic function test_sanitize_amp_video_with_missing_poster(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t</head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t\t<amp-video autoplay=\"autoplay\" title=\"Some Video\" alt=\"Some Video\" layout=\"fill\" id=\"foo\"><source type=\"video/mp4\" src=\"https://example.com/video.mp4\"/></amp-video>\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t$video_element = $document->body->getElementsByTagName( 'amp-video' )->item( 0 );\n\t\t$this->assertInstanceOf( DOMElement::class, $video_element );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\Integrations\\AMP::filter_amp_validation_error_sanitized\n\t */\n\tpublic function test_sanitize_amp_video_with_http_source(): void {\n\t\tob_start();\n\t\t?>\n\t\t<html>\n\t\t<head>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0.js\"></script>\n\t\t\t<script async=\"\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>\n\t\t</head>\n\t\t<body>\n\t\t<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\">\n\t\t\t<amp-story-page id=\"foo\">\n\t\t\t\t<amp-story-grid-layer template=\"fill\">\n\t\t\t\t\t<amp-video autoplay=\"autoplay\" title=\"Some Video\" alt=\"Some Video\" layout=\"fill\" poster=\"https://example.com/poster.png\"><source type=\"video/mp4\" src=\"http://example.com/video.mp4\"/></amp-video>\n\t\t\t\t</amp-story-grid-layer>\n\t\t\t</amp-story-page>\n\t\t</amp-story>\n\t\t</body>\n\t\t</html>\n\t\t<?php\n\t\t$original_html = (string) ob_get_clean();\n\n\t\t/**\n\t\t * @var Document $document\n\t\t */\n\t\t$document = Document::fromHtml( $original_html );\n\t\t$this->instance->sanitize_document( $document );\n\n\t\t$video_element = $document->body->getElementsByTagName( 'amp-video' )->item( 0 );\n\t\t$this->assertInstanceOf( DOMElement::class, $video_element );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AMP_Story_Player_Assets.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets as Assets;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP_Story_Player_Assets\n */\nclass AMP_Story_Player_Assets extends TestCase {\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$instance = new Assets();\n\t\t$instance->register();\n\n\t\thas_action( 'wp_default_styles', [ $instance, 'register_style' ] );\n\t\thas_action( 'wp_default_scripts', [ $instance, 'register_script' ] );\n\n\t\t$this->assertSame( 10, has_action( 'wp_default_styles', [ $instance, 'register_style' ] ) );\n\t\t$this->assertSame( 10, has_action( 'wp_default_scripts', [ $instance, 'register_script' ] ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/AdSense.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AdSense\n */\nclass AdSense extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\AdSense $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tupdate_option( Settings::SETTING_NAME_AD_NETWORK, 'adsense' );\n\t\tupdate_option( Settings::SETTING_NAME_ADSENSE_SLOT_ID, '123' );\n\t\tupdate_option( Settings::SETTING_NAME_ADSENSE_PUBLISHER_ID, '456' );\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\AdSense::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tparent::tear_down();\n\n\t\tdelete_option( Settings::SETTING_NAME_AD_NETWORK );\n\t\tdelete_option( Settings::SETTING_NAME_ADSENSE_SLOT_ID );\n\t\tdelete_option( Settings::SETTING_NAME_ADSENSE_PUBLISHER_ID );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'web_stories_print_analytics', [ $this->instance, 'print_adsense_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::get_publisher_id\n\t */\n\tpublic function test_get_publisher_id(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_publisher_id' ] );\n\t\t$this->assertSame( '456', $result );\n\t}\n\n\t/**\n\t * @covers ::get_slot_id\n\t */\n\tpublic function test_get_slot_id(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_slot_id' ] );\n\t\t$this->assertSame( '123', $result );\n\t}\n\n\t/**\n\t * @covers ::is_enabled\n\t */\n\tpublic function test_is_enabled(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'is_enabled' ] );\n\t\t$this->assertTrue( $result );\n\t}\n\n\t/**\n\t * @covers ::print_adsense_tag\n\t */\n\tpublic function test_print_adsense_tag(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_adsense_tag' ] );\n\t\t$this->assertStringContainsString( '<amp-story-auto-ads>', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Ad_Manager.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Ad_Manager\n */\nclass Ad_Manager extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Ad_Manager $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tupdate_option( Settings::SETTING_NAME_AD_NETWORK, 'admanager' );\n\t\tupdate_option( Settings::SETTING_NAME_AD_MANAGER_SLOT_ID, '123' );\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Ad_Manager::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tparent::tear_down();\n\n\t\tdelete_option( Settings::SETTING_NAME_AD_NETWORK );\n\t\tdelete_option( Settings::SETTING_NAME_AD_MANAGER_SLOT_ID );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'web_stories_print_analytics', [ $this->instance, 'print_ad_manager_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::get_slot_id\n\t */\n\tpublic function test_get_slot_id(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_slot_id' ] );\n\t\t$this->assertSame( '123', $result );\n\t}\n\n\t/**\n\t * @covers ::is_enabled\n\t */\n\tpublic function test_is_enabled(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'is_enabled' ] );\n\t\t$this->assertTrue( $result );\n\t}\n\n\t/**\n\t * @covers ::print_ad_manager_tag\n\t */\n\tpublic function test_print_ad_manager_tag(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_ad_manager_tag' ] );\n\t\t$this->assertStringContainsString( '<amp-story-auto-ads>', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Activation_Notice.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Activation_Notice\n */\nclass Activation_Notice extends DependencyInjectedTestCase {\n\t/**\n\t * Activation_Notice for test.\n\t */\n\tprotected \\Google\\Web_Stories\\Admin\\Activation_Notice $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Admin\\Activation_Notice::class );\n\t\t$this->call_private_method( [ $this->instance, 'set_activation_flag' ] );\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->call_private_method( [ $this->instance, 'delete_activation_flag' ] );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'admin_enqueue_scripts', [ $this->instance, 'enqueue_assets' ] ) );\n\t\t$this->assertSame( 10, has_action( 'admin_notices', [ $this->instance, 'render_notice' ] ) );\n\t\t$this->assertSame( 10, has_action( 'network_admin_notices', [ $this->instance, 'render_notice' ] ) );\n\t}\n\n\t/**\n\t * @covers ::render_notice\n\t */\n\tpublic function test_render_notice(): void {\n\t\t$GLOBALS['hook_suffix'] = 'plugins.php';\n\n\t\t$flag_before = $this->call_private_method( [ $this->instance, 'get_activation_flag' ] );\n\t\t$output      = get_echo( [ $this->instance, 'render_notice' ] );\n\t\t$flag_after  = $this->call_private_method( [ $this->instance, 'get_activation_flag' ] );\n\t\t$this->assertStringContainsString( 'web-stories-plugin-activation-notice', $output );\n\t\t$this->assertTrue( $flag_before );\n\t\t$this->assertFalse( $flag_after );\n\t}\n\n\t/**\n\t * @covers ::is_plugins_page\n\t */\n\tpublic function test_is_plugins_page(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'is_plugins_page' ], [ 'themes.php' ] );\n\t\t$this->assertFalse( $result );\n\t}\n\n\t/**\n\t * @covers ::set_activation_flag\n\t * @covers ::get_activation_flag\n\t */\n\tpublic function test_set_activation_flag(): void {\n\t\t$this->call_private_method( [ $this->instance, 'set_activation_flag' ], [ true ] );\n\t\t$flag = $this->call_private_method( [ $this->instance, 'get_activation_flag' ], [ true ] );\n\t\t$this->assertTrue( $flag );\n\t}\n\n\t/**\n\t * @covers ::delete_activation_flag\n\t * @covers ::get_activation_flag\n\t */\n\tpublic function test_delete_activation_flag(): void {\n\t\t$this->call_private_method( [ $this->instance, 'delete_activation_flag' ], [ true ] );\n\t\t$flag = $this->call_private_method( [ $this->instance, 'get_activation_flag' ], [ true ] );\n\t\t$this->assertFalse( $flag );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\tadd_site_option( $this->instance::OPTION_SHOW_ACTIVATION_NOTICE, '1' );\n\t\tadd_option( $this->instance::OPTION_SHOW_ACTIVATION_NOTICE, '1' );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertFalse( get_site_option( $this->instance::OPTION_SHOW_ACTIVATION_NOTICE ) );\n\t\t$this->assertFalse( get_option( $this->instance::OPTION_SHOW_ACTIVATION_NOTICE ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Admin.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse DateTime;\nuse Google\\Web_Stories\\Media\\Image_Sizes;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Admin\n */\nclass Admin extends DependencyInjectedTestCase {\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story ID.\n\t */\n\tprotected static int $story_id;\n\n\t/**\n\t * Post ID.\n\t */\n\tprotected static int $post_id;\n\n\t/**\n\t * Settings for test.\n\t */\n\tprivate Settings $settings;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Admin\\Admin $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Admin Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\n\t\tself::$post_id = $factory->post->create();\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\t\t$this->settings = $this->injector->make( Settings::class );\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Admin\\Admin::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 99, has_filter( 'admin_body_class', [ $this->instance, 'admin_body_class' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'default_content', [ $this->instance, 'prefill_post_content' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'default_title', [ $this->instance, 'prefill_post_title' ] ) );\n\t}\n\n\t/**\n\t * @covers ::admin_body_class\n\t */\n\tpublic function test_admin_body_class(): void {\n\t\twp_set_current_user( self::$admin_id );\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$result                    = $this->instance->admin_body_class( 'current' );\n\t\t$this->assertIsString( $result );\n\t\t$this->assertStringContainsString( 'folded', $result );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_content\n\t */\n\tpublic function test_prefill_post_content(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$_GET['from-web-story'] = self::$story_id;\n\t\t$current_post           = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$result = $this->instance->prefill_post_content( 'current', $current_post );\n\t\t$poster = (string) wp_get_attachment_image_url( (int) get_post_thumbnail_id( self::$story_id ), Image_Sizes::POSTER_PORTRAIT_IMAGE_SIZE );\n\t\t$this->assertIsString( $result );\n\t\t$this->assertStringContainsString( 'wp-block-web-stories-embed', $result );\n\t\t$this->assertStringContainsString( $poster, $result );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_content\n\t */\n\tpublic function test_prefill_post_content_url_scheduled(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$story_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'  => 'future',\n\t\t\t\t'post_date'    => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_title'   => 'Example',\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story_id );\n\n\t\t$_GET['from-web-story'] = $story_id;\n\t\t$current_post           = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$result = $this->instance->prefill_post_content( 'current', $current_post );\n\n\t\t$this->assertIsString( $result );\n\t\t$this->assertStringNotContainsString( \\sprintf( '\"url\":\"http://example.org/?post_type=web-story&#038;p=%s', $story_id ), $result );\n\t\t$this->assertStringContainsString( \\sprintf( '\"url\":\"http://example.org/?post_type=web-story&p=%s', $story_id ), $result );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_content\n\t */\n\tpublic function test_prefill_post_content_invalid_user(): void {\n\t\twp_set_current_user( 0 );\n\n\t\t$_GET['from-web-story'] = self::$story_id;\n\n\t\t$current_post = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$result = $this->instance->prefill_post_content( 'current', $current_post );\n\t\t$this->assertIsString( $result );\n\t\t$this->assertSame( 'current', $result );\n\t}\n\n\n\t/**\n\t * @covers ::prefill_post_content\n\t */\n\tpublic function test_prefill_post_content_shortcode(): void {\n\t\tadd_filter( 'use_block_editor_for_post', '__return_false' );\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$_GET['from-web-story'] = self::$story_id;\n\t\t$current_post           = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$result = $this->instance->prefill_post_content( 'current', $current_post );\n\t\t$poster = (string) wp_get_attachment_image_url( (int) get_post_thumbnail_id( self::$story_id ), Image_Sizes::POSTER_PORTRAIT_IMAGE_SIZE );\n\t\t$this->assertIsString( $result );\n\t\t$this->assertStringContainsString( '[web_stories_embed', $result );\n\t\t$this->assertStringContainsString( $poster, $result );\n\t\tremove_filter( 'use_block_editor_for_post', '__return_false' );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_content\n\t */\n\tpublic function test_prefill_post_content_invalid_id(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$_GET['from-web-story'] = 999_999_999;\n\t\t$current_post           = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$result = $this->instance->prefill_post_content( 'current', $current_post );\n\t\t$this->assertSame( 'current', $result );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_title\n\t */\n\tpublic function test_prefill_post_title(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$_GET['from-web-story'] = self::$story_id;\n\t\t$result                 = $this->instance->prefill_post_title( 'current' );\n\t\t$this->assertSame( 'Admin Test Story', $result );\n\t}\n\n\t/**\n\t * @covers ::prefill_post_title\n\t */\n\tpublic function test_prefill_post_title_no_texturize(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$_GET['from-web-story'] = self::$story_id;\n\n\t\t$current_post = get_post( self::$post_id );\n\t\t$this->assertNotNull( $current_post );\n\n\t\t$original_title = $current_post->post_title;\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'         => self::$story_id,\n\t\t\t\t// Not just a hyphen, but an en dash.\n\t\t\t\t'post_title' => 'Story - Test',\n\t\t\t]\n\t\t);\n\n\t\t$result = $this->instance->prefill_post_title( 'current' );\n\n\t\t// Cleanup.\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'         => self::$story_id,\n\t\t\t\t'post_title' => $original_title,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertSame( 'Story - Test', $result );\n\t}\n\n\t/**\n\t * @covers ::media_states\n\t */\n\tpublic function test_media_states_no_active_logo(): void {\n\t\t$post = self::factory()->post->create_and_get();\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$result = $this->instance->media_states( [], $post );\n\t\t$this->assertIsArray( $result );\n\t\t$this->assertEqualSets( [], $result );\n\t}\n\n\t/**\n\t * @covers ::media_states\n\t */\n\tpublic function test_media_states_with_active_logo(): void {\n\t\t$post = self::factory()->post->create_and_get();\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->settings->update_setting( $this->settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, $post->ID );\n\t\t$result = $this->instance->media_states( [], $post );\n\t\t$this->assertIsArray( $result );\n\t\t$this->assertEqualSets( [ 'Web Stories Publisher Logo' ], $result );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Cross_Origin_Isolation.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse Google\\Web_Stories\\User\\Preferences;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Cross_Origin_Isolation\n */\nclass Cross_Origin_Isolation extends DependencyInjectedTestCase {\n\t/**\n\t * Admin user for test.\n\t */\n\tprivate int $admin_id;\n\n\t/**\n\t * Contributor user for test.\n\t */\n\tprivate int $contributor_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Admin\\Cross_Origin_Isolation $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t// Deliberately NOT created in wpSetUpBeforeClass() because this class contains running\n\t\t// in separate processes, which means tearDownAfterClass() (which deletes all WP data)\n\t\t// is run multiple times, causing the story not to be available anymore.\n\t\t$this->admin_id = self::factory()->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\t$this->contributor_id = self::factory()->user->create(\n\t\t\t[ 'role' => 'contributor' ]\n\t\t);\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Admin\\Cross_Origin_Isolation::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_user_meta( $this->admin_id, Preferences::MEDIA_OPTIMIZATION_META_KEY );\n\t\tdelete_user_meta( $this->contributor_id, Preferences::MEDIA_OPTIMIZATION_META_KEY );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\twp_set_current_user( $this->admin_id );\n\t\tupdate_user_meta( $this->admin_id, Preferences::MEDIA_OPTIMIZATION_META_KEY, true );\n\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'load-post.php', [ $this->instance, 'admin_header' ] ) );\n\t\t$this->assertSame( 10, has_action( 'load-post-new.php', [ $this->instance, 'admin_header' ] ) );\n\n\t\t$this->assertSame( 10, has_filter( 'style_loader_tag', [ $this->instance, 'style_loader_tag' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'script_loader_tag', [ $this->instance, 'script_loader_tag' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'get_avatar', [ $this->instance, 'get_avatar' ] ) );\n\t}\n\n\t/**\n\t * @covers ::needs_isolation\n\t */\n\tpublic function test_needs_isolation(): void {\n\t\twp_set_current_user( $this->admin_id );\n\t\tupdate_user_meta( $this->admin_id, Preferences::MEDIA_OPTIMIZATION_META_KEY, true );\n\n\t\t$actual = $this->call_private_method( [ $this->instance, 'needs_isolation' ] );\n\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::needs_isolation\n\t */\n\tpublic function test_needs_isolation_default_user_meta_value(): void {\n\t\twp_set_current_user( $this->admin_id );\n\n\t\t$actual = $this->call_private_method( [ $this->instance, 'needs_isolation' ] );\n\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::needs_isolation\n\t */\n\tpublic function test_needs_isolation_no_user(): void {\n\t\t$actual = $this->call_private_method( [ $this->instance, 'needs_isolation' ] );\n\n\t\t$this->assertFalse( $actual );\n\t}\n\n\t/**\n\t * @covers ::needs_isolation\n\t */\n\tpublic function test_needs_isolation_opt_out(): void {\n\t\twp_set_current_user( $this->admin_id );\n\t\tupdate_user_meta( $this->admin_id, Preferences::MEDIA_OPTIMIZATION_META_KEY, false );\n\n\t\t$actual = $this->call_private_method( [ $this->instance, 'needs_isolation' ] );\n\n\t\t$this->assertFalse( $actual );\n\t}\n\n\t/**\n\t * @covers ::needs_isolation\n\t */\n\tpublic function test_needs_isolation_no_upload_caps(): void {\n\t\twp_set_current_user( $this->contributor_id );\n\t\tupdate_user_meta( $this->contributor_id, Preferences::MEDIA_OPTIMIZATION_META_KEY, true );\n\n\t\t$actual = $this->call_private_method( [ $this->instance, 'needs_isolation' ] );\n\n\t\t$this->assertFalse( $actual );\n\t}\n\n\t/**\n\t * @covers ::add_attribute\n\t */\n\tpublic function test_add_attribute(): void {\n\t\t$html      = \"<img src='http://www.google.com/test.jpg' alt='test' />\";\n\t\t$attribute = 'src';\n\t\t$url       = 'http://www.google.com/test.jpg';\n\t\t$result    = $this->call_private_method( [ $this->instance, 'add_attribute' ], [ $html, $attribute, $url ] );\n\t\t$this->assertStringContainsString( 'crossorigin', $result );\n\t}\n\t/**\n\t * @covers ::add_attribute\n\t */\n\tpublic function test_add_attribute_local_image(): void {\n\t\t$url       = site_url( '/test.jpg' );\n\t\t$html      = \\sprintf( \"<img src='%s' alt='test' />\", $url );\n\t\t$attribute = 'src';\n\t\t$result    = $this->call_private_method( [ $this->instance, 'add_attribute' ], [ $html, $attribute, $url ] );\n\t\t$this->assertStringNotContainsString( 'crossorigin', $result );\n\t}\n\n\t/**\n\t * @covers ::add_attribute\n\t */\n\tpublic function test_add_attribute_relative_image(): void {\n\t\t$html      = \"<img src='/test.jpg' alt='test' />\";\n\t\t$attribute = 'src';\n\t\t$url       = '/test.jpg';\n\t\t$result    = $this->call_private_method( [ $this->instance, 'add_attribute' ], [ $html, $attribute, $url ] );\n\t\t$this->assertStringNotContainsString( 'crossorigin', $result );\n\t}\n\n\t/**\n\t * @covers ::replace_in_dom\n\t */\n\tpublic function test_replace_in_dom(): void {\n\t\t$site_url = site_url();\n\n\t\t$html = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/cross_origin_content.html' );\n\t\t$this->assertIsString( $html );\n\t\t$html   = str_replace( '--SITE_URL--', $site_url, $html );\n\t\t$result = $this->call_private_method( [ $this->instance, 'replace_in_dom' ], [ $html ] );\n\n\t\t$this->assertIsString( $result );\n\t\t$this->assertStringContainsString( '<script async=\"\" crossorigin=\"anonymous\" src=\"https://cdn.ampproject.org/v0.js\"></script>', $result );\n\t\t$this->assertStringContainsString( '<script async=\"\" crossorigin=\"anonymous\" src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>', $result );\n\t\t$this->assertStringContainsString( '<link crossorigin=\"anonymous\" href=\"https://fonts.googleapis.com/css2?display=swap&#038;family=Roboto\" rel=\"stylesheet\" />', $result );\n\t\t$this->assertStringContainsString( '<img alt=\"test\" crossorigin=\"anonymous\" src=\"http://www.example.com/test1.jpg\" loading=\"eager\" />', $result );\n\t\t$this->assertStringContainsString( \"<img crossorigin='anonymous' src='http://www.example.com/test2.jpg' alt='test' />\", $result );\n\t\t$this->assertStringContainsString( '<iframe src=\"http://www.example.com\"></iframe>', $result );\n\t\t$this->assertStringContainsString( 'crossorigin=\"use-credentials\"', $result );\n\t\t$this->assertStringContainsString( '<a href=\"http://www.example.com/test1.jpg\">Test</a>', $result );\n\t\t$this->assertStringContainsString( '<video crossorigin=\"anonymous\"><source src=\"http://www.example.com/video1.mp4\"></video>', $result );\n\t\t$this->assertStringContainsString( '<video crossorigin=\"anonymous\" src=\"http://www.example.com/video3.mp4\"></video>', $result );\n\t\t$this->assertStringContainsString( '<audio crossorigin=\"anonymous\"><source src=\"http://www.example.com/audio1.mp3\"></audio>', $result );\n\t\t$this->assertStringContainsString( '<audio crossorigin=\"anonymous\" src=\"http://www.example.com/audio3.mp3\"></audio>', $result );\n\t\t$this->assertStringContainsString( \"<img src='$site_url/test3.jpg' alt=\\\"test\\\" />\", $result );\n\t\t$this->assertStringContainsString( \"<iframe src=\\\"$site_url\\\"></iframe>\", $result );\n\t\t$this->assertStringContainsString( \"<video><source src=\\\"$site_url/video2.mp4\\\"></video>\", $result );\n\t\t$this->assertStringContainsString( \"<video src=\\\"$site_url/video4.mp4\\\"></video>\", $result );\n\t\t$this->assertStringContainsString( \"<audio><source src=\\\"$site_url/audio2.mp3\\\"></audio>\", $result );\n\t\t$this->assertStringContainsString( \"<audio src=\\\"$site_url/audio4.mp3\\\"></audio>\", $result );\n\t\t$this->assertStringContainsString( \"<script async=\\\"\\\" src=\\\"$site_url\\\"></script>\", $result );\n\t\t$this->assertStringContainsString( \"<link href=\\\"$site_url/site.css\\\" rel=\\\"stylesheet\\\" />\", $result );\n\t}\n\n\t/**\n\t * @covers ::replace_in_dom\n\t */\n\tpublic function test_replace_in_dom_invalid(): void {\n\t\t$html   = '<html><img src=\"http://www.example.com/test1.jpg\" /><invalid /</html';\n\t\t$result = $this->call_private_method( [ $this->instance, 'replace_in_dom' ], [ $html ] );\n\t\t$this->assertStringContainsString( '<img crossorigin=\"anonymous\" src=\"http://www.example.com/test1.jpg\" />', $result );\n\t}\n\n\t/**\n\t * @covers ::custom_print_media_templates\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_custom_print_media_templates(): void {\n\t\trequire_once ABSPATH . WPINC . '/media-template.php';\n\t\t$output = get_echo( [ $this->instance, 'custom_print_media_templates' ] );\n\t\t$this->assertStringContainsString( '<audio crossorigin=\"anonymous\"', $output );\n\t\t$this->assertStringContainsString( '<img crossorigin=\"anonymous\"', $output );\n\t\t$this->assertStringContainsString( '<video crossorigin=\"anonymous\"', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Customizer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Admin\\Customizer as TheCustomizer;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Customize_Manager;\nuse WP_Customize_Section;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Customizer\n * @runInSeparateProcess\n * @preserveGlobalState disabled\n */\nclass Customizer extends DependencyInjectedTestCase {\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate TheCustomizer $instance;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate ?WP_Customize_Manager $wp_customize = null;\n\n\tpublic static function wpSetUpBeforeClass(): void {\n\t\trequire_once ABSPATH . WPINC . '/class-wp-customize-manager.php';\n\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/functions.php';\n\t}\n\n\t/**\n\t * Runs once before any test in the class run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$wp_customize            = new WP_Customize_Manager();\n\t\t$GLOBALS['wp_customize'] = $wp_customize;\n\t\t$this->wp_customize      = $GLOBALS['wp_customize'];\n\n\t\t$this->instance = $this->injector->make( TheCustomizer::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->wp_customize = null;\n\t\tunset( $GLOBALS['wp_customize'] );\n\n\t\tremove_theme_support( 'web-stories' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t */\n\tpublic function test_is_needed(): void {\n\t\t$this->assertTrue( $this->instance::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\n\t\t$this->instance->register();\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_action(\n\t\t\t\t'customize_register',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'register_customizer_settings',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register_customizer_settings\n\t */\n\tpublic function test_customizer_web_stories_section_added(): void {\n\t\t$this->add_web_stories_theme_support();\n\n\t\t$this->assertInstanceOf( WP_Customize_Manager::class, $this->wp_customize );\n\t\t$this->wp_customize->add_section(\n\t\t\tTheCustomizer::SECTION_SLUG,\n\t\t\t[\n\t\t\t\t'title'          => 'Web Stories',\n\t\t\t\t'theme_supports' => 'web-stories',\n\t\t\t]\n\t\t);\n\n\t\t$this->instance->register_customizer_settings( $this->wp_customize );\n\n\t\t$settings = $this->wp_customize->sections();\n\n\t\t$this->assertArrayHasKey( TheCustomizer::SECTION_SLUG, $settings );\n\t\t$this->assertInstanceOf( WP_Customize_Section::class, $settings[ TheCustomizer::SECTION_SLUG ] );\n\t\t$this->assertTrue( property_exists( $settings[ TheCustomizer::SECTION_SLUG ], 'title' ) );\n\t\t$this->assertTrue( property_exists( $settings[ TheCustomizer::SECTION_SLUG ], 'theme_supports' ) );\n\n\t\t$this->assertSame( 'Web Stories', $settings[ TheCustomizer::SECTION_SLUG ]->title );\n\t\t$this->assertSame( 'web-stories', $settings[ TheCustomizer::SECTION_SLUG ]->theme_supports );\n\t}\n\n\t/**\n\t * @covers ::register_customizer_settings\n\t */\n\tpublic function test_customizer_settings_added(): void {\n\t\t$this->add_web_stories_theme_support();\n\t\t$this->assertInstanceOf( WP_Customize_Manager::class, $this->wp_customize );\n\t\t$this->instance->register_customizer_settings( $this->wp_customize );\n\n\t\t$settings = $this->wp_customize->settings();\n\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_stories]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[view_type]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[number_of_stories]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[number_of_columns]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[orderby]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[order]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[circle_size]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[image_alignment]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_title]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_excerpt]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_author]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_date]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[show_archive_link]', $settings );\n\t\t$this->assertArrayHasKey( 'web_stories_customizer_settings[archive_link_label]', $settings );\n\t}\n\n\t/**\n\t * @covers ::validate_number_of_stories\n\t */\n\tpublic function test_validate_number_of_stories(): void {\n\t\t$output = $this->instance->validate_number_of_stories( new \\WP_Error(), 20 );\n\n\t\t$this->assertEmpty( $output->errors );\n\n\t\t$output = $this->instance->validate_number_of_stories( new \\WP_Error(), 30 );\n\n\t\t$this->assertNotEmpty( $output->errors );\n\t\t$this->assertNotEmpty( $output->errors['invalid_number'] );\n\n\t\t$output = $this->instance->validate_number_of_stories( new \\WP_Error(), 0 );\n\n\t\t$this->assertNotEmpty( $output->errors );\n\t\t$this->assertNotEmpty( $output->errors['invalid_number'] );\n\t}\n\n\t/**\n\t * @covers ::validate_number_of_columns\n\t */\n\tpublic function test_validate_number_of_columns(): void {\n\t\t$output = $this->instance->validate_number_of_columns( new \\WP_Error(), 2 );\n\n\t\t$this->assertEmpty( $output->errors );\n\n\t\t$output = $this->instance->validate_number_of_columns( new \\WP_Error(), 6 );\n\n\t\t$this->assertNotEmpty( $output->errors );\n\t\t$this->assertNotEmpty( $output->errors['invalid_number'] );\n\n\t\t$output = $this->instance->validate_number_of_columns( new \\WP_Error(), 0 );\n\n\t\t$this->assertNotEmpty( $output->errors );\n\t\t$this->assertNotEmpty( $output->errors['invalid_number'] );\n\t}\n\n\t/**\n\t * @covers ::get_stories_theme_support\n\t */\n\tpublic function test_get_stories_theme_support(): void {\n\t\tadd_theme_support( 'web-stories' );\n\n\t\t$expected = [\n\t\t\t'customizer' => [\n\t\t\t\t'view_type'         => [\n\t\t\t\t\t'enabled' => [ 'circles' ],\n\t\t\t\t\t'default' => 'circles',\n\t\t\t\t],\n\t\t\t\t'title'             => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => true,\n\t\t\t\t],\n\t\t\t\t'excerpt'           => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'author'            => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => true,\n\t\t\t\t],\n\t\t\t\t'date'              => [\n\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'archive_link'      => [\n\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t'default' => true,\n\t\t\t\t\t'label'   => 'View all stories',\n\t\t\t\t],\n\t\t\t\t'sharp_corners'     => [\n\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t'default' => false,\n\t\t\t\t],\n\t\t\t\t'order'             => [\n\t\t\t\t\t'default' => 'DESC',\n\t\t\t\t],\n\t\t\t\t'orderby'           => [\n\t\t\t\t\t'default' => 'post_date',\n\t\t\t\t],\n\t\t\t\t'circle_size'       => [\n\t\t\t\t\t'default' => 150,\n\t\t\t\t],\n\t\t\t\t'number_of_stories' => [\n\t\t\t\t\t'default' => 10,\n\t\t\t\t],\n\t\t\t\t'number_of_columns' => [\n\t\t\t\t\t'default' => 2,\n\t\t\t\t],\n\t\t\t\t'image_alignment'   => [\n\t\t\t\t\t'default' => is_rtl() ? 'right' : 'left',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$output = $this->instance->get_stories_theme_support();\n\n\t\t$this->assertEquals( $expected, $output );\n\t}\n\n\t/**\n\t * @covers ::render_stories\n\t */\n\tpublic function test_render_stories(): void {\n\t\tadd_theme_support(\n\t\t\t'web-stories',\n\t\t\t[\n\t\t\t\t'customizer' => [\n\t\t\t\t\t'view_type'         => [\n\t\t\t\t\t\t'enabled' => [ 'circles', 'grid', 'list', 'carousel' ],\n\t\t\t\t\t\t'default' => 'circles',\n\t\t\t\t\t],\n\t\t\t\t\t'title'             => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'author'            => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'date'              => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'archive_link'      => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => true,\n\t\t\t\t\t\t'label'   => 'View all stories',\n\t\t\t\t\t],\n\t\t\t\t\t'sharp_corners'     => [\n\t\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'order'             => [\n\t\t\t\t\t\t'default' => 'DESC',\n\t\t\t\t\t],\n\t\t\t\t\t'orderby'           => [\n\t\t\t\t\t\t'default' => 'post_date',\n\t\t\t\t\t],\n\t\t\t\t\t'circle_size'       => [\n\t\t\t\t\t\t'default' => 150,\n\t\t\t\t\t],\n\t\t\t\t\t'number_of_stories' => [\n\t\t\t\t\t\t'default' => 5,\n\t\t\t\t\t],\n\t\t\t\t\t'number_of_columns' => [\n\t\t\t\t\t\t'default' => 4,\n\t\t\t\t\t],\n\t\t\t\t\t'image_alignment'   => [\n\t\t\t\t\t\t'default' => is_rtl() ? 'right' : 'left',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$options = [\n\t\t\t'show_stories' => true,\n\t\t];\n\n\t\t$output = $this->instance->render_stories();\n\n\t\t$this->assertEmpty( $output );\n\n\t\tupdate_option( 'web_stories_customizer_settings', $options );\n\n\t\tself::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t]\n\t\t);\n\n\t\t$output = $this->instance->render_stories();\n\n\t\t$this->assertNotEmpty( $output );\n\t\t$this->assertStringContainsString( 'web-stories-list--customizer', $output );\n\t}\n\n\t/**\n\t * Add theme support for web stories.\n\t */\n\tprivate function add_web_stories_theme_support(): void {\n\t\tadd_theme_support(\n\t\t\t'web-stories',\n\t\t\t[\n\t\t\t\t'customizer' => [\n\t\t\t\t\t'view_type'         => [\n\t\t\t\t\t\t'enabled' => [ 'circles', 'grid', 'list', 'carousel' ],\n\t\t\t\t\t\t'default' => 'circles',\n\t\t\t\t\t],\n\t\t\t\t\t'title'             => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'author'            => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'date'              => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'archive_link'      => [\n\t\t\t\t\t\t'enabled' => true,\n\t\t\t\t\t\t'default' => true,\n\t\t\t\t\t\t'label'   => 'View all stories',\n\t\t\t\t\t],\n\t\t\t\t\t'sharp_corners'     => [\n\t\t\t\t\t\t'enabled' => false,\n\t\t\t\t\t\t'default' => false,\n\t\t\t\t\t],\n\t\t\t\t\t'order'             => [\n\t\t\t\t\t\t'default' => 'DESC',\n\t\t\t\t\t],\n\t\t\t\t\t'orderby'           => [\n\t\t\t\t\t\t'default' => 'post_date',\n\t\t\t\t\t],\n\t\t\t\t\t'circle_size'       => [\n\t\t\t\t\t\t'default' => 150,\n\t\t\t\t\t],\n\t\t\t\t\t'number_of_stories' => [\n\t\t\t\t\t\t'default' => 5,\n\t\t\t\t\t],\n\t\t\t\t\t'number_of_columns' => [\n\t\t\t\t\t\t'default' => 4,\n\t\t\t\t\t],\n\t\t\t\t\t'image_alignment'   => [\n\t\t\t\t\t\t'default' => is_rtl() ? 'right' : 'left',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Dashboard.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Admin\\Google_Fonts;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Decoder;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Integrations\\Site_Kit;\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\Locale;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Shopping\\Shopping_Vendors;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\Capabilities_Setup;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Dashboard\n */\nclass Dashboard extends DependencyInjectedTestCase {\n\tuse Capabilities_Setup;\n\n\tprotected static int $user_id;\n\n\t/**\n\t * @var lowercase-string&non-empty-string\n\t */\n\tprotected static string $cpt_has_archive = 'cpt_has_archive';\n\n\t/**\n\t * @var lowercase-string&non-empty-string\n\t */\n\tprotected static string $cpt_no_archive = 'cpt_no_archive';\n\n\tprivate \\Google\\Web_Stories\\Admin\\Dashboard $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\tregister_post_type(\n\t\t\tself::$cpt_has_archive,\n\t\t\t[\n\t\t\t\t'has_archive' => true,\n\t\t\t]\n\t\t);\n\n\t\tregister_post_type(\n\t\t\tself::$cpt_no_archive,\n\t\t\t[\n\t\t\t\t'has_archive' => false,\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic static function wpTearDownAfterClass(): void {\n\t\tunregister_post_type( self::$cpt_no_archive );\n\t\tunregister_post_type( self::$cpt_has_archive );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Admin\\Dashboard::class );\n\n\t\t$this->add_caps_to_roles();\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->remove_caps_from_roles();\n\n\t\twp_dequeue_script( \\Google\\Web_Stories\\Admin\\Dashboard::SCRIPT_HANDLE );\n\t\twp_dequeue_style( \\Google\\Web_Stories\\Admin\\Dashboard::SCRIPT_HANDLE );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::get_hook_suffix\n\t */\n\tpublic function test_get_not_set_hook_suffix(): void {\n\t\t$this->instance->add_menu_page();\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'nothing' ) );\n\t}\n\n\t/**\n\t * @covers ::add_menu_page\n\t * @covers ::get_hook_suffix\n\t */\n\tpublic function test_add_menu_page_no_user(): void {\n\t\t$this->instance->add_menu_page();\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard' ) );\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard-explore' ) );\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard-settings' ) );\n\t}\n\n\t/**\n\t * @covers ::add_menu_page\n\t * @covers ::get_hook_suffix\n\t */\n\tpublic function test_add_menu_page_user_without_permission(): void {\n\t\t$this->remove_caps_from_roles();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$this->instance->add_menu_page();\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard' ) );\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard-explore' ) );\n\t\t$this->assertFalse( $this->instance->get_hook_suffix( 'stories-dashboard-settings' ) );\n\t}\n\n\t/**\n\t * @covers ::add_menu_page\n\t * @covers ::get_hook_suffix\n\t */\n\tpublic function test_add_menu_page(): void {\n\t\twp_set_current_user( self::$user_id );\n\t\twp_get_current_user()->add_cap( 'edit_web-stories' );\n\n\t\t$this->instance->add_menu_page();\n\t\t$this->assertNotFalse( $this->instance->get_hook_suffix( 'stories-dashboard' ) );\n\t\t$this->assertNotEmpty( $this->instance->get_hook_suffix( 'stories-dashboard' ) );\n\t\t$this->assertNotFalse( $this->instance->get_hook_suffix( 'stories-dashboard-explore' ) );\n\t\t$this->assertNotEmpty( $this->instance->get_hook_suffix( 'stories-dashboard-explore' ) );\n\t\t$this->assertNotFalse( $this->instance->get_hook_suffix( 'stories-dashboard-settings' ) );\n\t\t$this->assertNotEmpty( $this->instance->get_hook_suffix( 'stories-dashboard-settings' ) );\n\t}\n\n\t/**\n\t * @covers ::enqueue_assets\n\t */\n\tpublic function test_enqueue_assets_wrong_page(): void {\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$this->instance->add_menu_page();\n\t\t$this->instance->enqueue_assets( 'foo' );\n\t\t$this->assertFalse( wp_script_is( $this->instance::SCRIPT_HANDLE ) );\n\t\t$this->assertFalse( wp_style_is( $this->instance::SCRIPT_HANDLE ) );\n\t}\n\n\t/**\n\t * @covers ::enqueue_assets\n\t */\n\tpublic function test_enqueue_assets(): void {\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$experiments = $this->createMock( Experiments::class );\n\t\t$experiments->method( 'get_experiment_statuses' )\n\t\t\t\t\t->willReturn( [] );\n\n\t\t$assets = $this->getMockBuilder( Assets::class )->onlyMethods( [ 'get_asset_metadata' ] )->getMock();\n\t\t$assets->method( 'get_asset_metadata' )\n\t\t\t->willReturn(\n\t\t\t\t[\n\t\t\t\t\t'dependencies' => [],\n\t\t\t\t\t'version'      => '9.9.9',\n\t\t\t\t\t'js'           => [ 'fake_js_chunk' ],\n\t\t\t\t\t'css'          => [ 'fake_css_chunk' ],\n\t\t\t\t\t'chunks'       => [],\n\t\t\t\t]\n\t\t\t);\n\n\t\t$site_kit         = $this->injector->make( Site_Kit::class );\n\t\t$decoder          = $this->injector->make( Decoder::class );\n\t\t$locale           = $this->injector->make( Locale::class );\n\t\t$google_fonts     = $this->injector->make( Google_Fonts::class );\n\t\t$font_post_type   = $this->injector->make( Font_Post_Type::class );\n\t\t$post_type        = $this->injector->make( Story_Post_Type::class );\n\t\t$context          = $this->injector->make( Context::class );\n\t\t$types            = $this->injector->make( Types::class );\n\t\t$shopping_vendors = $this->injector->make( Shopping_Vendors::class );\n\t\t$woocommerce      = $this->injector->make( WooCommerce::class );\n\t\t$settings         = $this->injector->make( Settings::class );\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Admin\\Dashboard(\n\t\t\t$experiments,\n\t\t\t$site_kit,\n\t\t\t$decoder,\n\t\t\t$locale,\n\t\t\t$google_fonts,\n\t\t\t$assets,\n\t\t\t$font_post_type,\n\t\t\t$post_type,\n\t\t\t$context,\n\t\t\t$types,\n\t\t\t$shopping_vendors,\n\t\t\t$woocommerce,\n\t\t\t$settings\n\t\t);\n\n\t\t$this->instance->add_menu_page();\n\t\t$hook_suffix = $this->instance->get_hook_suffix( 'stories-dashboard' );\n\n\t\t$this->assertIsString( $hook_suffix );\n\t\t$this->instance->enqueue_assets( $hook_suffix );\n\n\t\t$this->assertTrue( wp_script_is( $this->instance::SCRIPT_HANDLE ) );\n\t\t$this->assertTrue( wp_script_is( 'fake_js_chunk', 'registered' ) );\n\n\t\t$this->assertTrue( wp_style_is( $this->instance::SCRIPT_HANDLE ) );\n\t\t$this->assertTrue( wp_style_is( 'fake_css_chunk', 'registered' ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Editor.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Admin\\Google_Fonts;\nuse Google\\Web_Stories\\Admin\\Meta_Boxes;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Decoder;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Locale;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Page_Template_Post_Type;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\Capabilities_Setup;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Editor\n */\nclass Editor extends DependencyInjectedTestCase {\n\tuse Capabilities_Setup;\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Subscriber user for test.\n\t */\n\tprotected static int $subscriber_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\t/**\n\t * @var Experiments & MockObject\n\t */\n\tprivate $experiments;\n\n\t/**\n\t * @var Assets & MockObject\n\t */\n\tprivate $assets;\n\n\tprivate Story_Post_Type $story_post_type;\n\n\tprivate \\Google\\Web_Stories\\Admin\\Editor $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id      = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\t\tself::$subscriber_id = $factory->user->create(\n\t\t\t[ 'role' => 'subscriber' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->experiments       = $this->createMock( Experiments::class );\n\t\t$meta_boxes              = $this->injector->make( Meta_Boxes::class );\n\t\t$decoder                 = $this->injector->make( Decoder::class );\n\t\t$locale                  = $this->injector->make( Locale::class );\n\t\t$google_fonts            = $this->injector->make( Google_Fonts::class );\n\t\t$this->assets            = $this->createMock( Assets::class );\n\t\t$this->story_post_type   = $this->injector->make( Story_Post_Type::class );\n\t\t$page_template_post_type = $this->injector->make( Page_Template_Post_Type::class );\n\t\t$fonts_post_type         = $this->injector->make( Font_Post_Type::class );\n\t\t$context                 = $this->injector->make( Context::class );\n\t\t$types                   = $this->injector->make( Types::class );\n\t\t$settings                = $this->injector->make( Settings::class );\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Admin\\Editor(\n\t\t\t$this->experiments,\n\t\t\t$meta_boxes,\n\t\t\t$decoder,\n\t\t\t$locale,\n\t\t\t$google_fonts,\n\t\t\t$this->assets,\n\t\t\t$this->story_post_type,\n\t\t\t$page_template_post_type,\n\t\t\t$fonts_post_type,\n\t\t\t$context,\n\t\t\t$types,\n\t\t\t$settings\n\t\t);\n\n\t\t$this->add_caps_to_roles();\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_post_meta( self::$story_id, '_edit_lock' );\n\n\t\t$this->remove_caps_from_roles();\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::admin_enqueue_scripts\n\t */\n\tpublic function test_admin_enqueue_scripts(): void {\n\t\t$this->assets->expects( $this->once() )->method( 'remove_admin_style' )->with( [ 'forms' ] );\n\n\t\t$GLOBALS['current_screen'] = convert_to_screen( $this->story_post_type->get_slug() );\n\n\t\t$this->instance->admin_enqueue_scripts( 'post.php' );\n\t}\n\n\t/**\n\t * @covers ::replace_editor\n\t */\n\tpublic function test_replace_editor(): void {\n\t\t$this->assets->expects( $this->once() )->method( 'register_script_asset' )->with(\n\t\t\t\\Google\\Web_Stories\\Admin\\Editor::SCRIPT_HANDLE\n\t\t);\n\t\t$current_post = get_post( self::$story_id );\n\t\t$this->assertNotNull( $current_post );\n\n\t\t$this->instance->replace_editor( true, $current_post );\n\t}\n\n\t/**\n\t * @covers ::get_editor_settings\n\t */\n\tpublic function test_get_editor_settings_admin(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$this->experiments->method( 'get_experiment_statuses' )->willReturn( [] );\n\n\t\t$results = $this->instance->get_editor_settings();\n\n\t\t$this->assertArrayHasKey( 'capabilities', $results );\n\t\t$this->assertIsArray( $results['capabilities'] );\n\t\t$this->assertArrayHasKey( 'hasUploadMediaAction', $results['capabilities'] );\n\t\t$this->assertTrue( $results['capabilities']['hasUploadMediaAction'] );\n\t}\n\n\t/**\n\t * @covers ::get_editor_settings\n\t */\n\tpublic function test_get_editor_settings_subscriber(): void {\n\t\twp_set_current_user( self::$subscriber_id );\n\n\t\t$this->experiments->method( 'get_experiment_statuses' )->willReturn( [] );\n\n\t\t$results = $this->instance->get_editor_settings();\n\n\t\t$this->assertArrayHasKey( 'capabilities', $results );\n\t\t$this->assertIsArray( $results['capabilities'] );\n\t\t$this->assertArrayHasKey( 'hasUploadMediaAction', $results['capabilities'] );\n\t\t$this->assertFalse( $results['capabilities']['hasUploadMediaAction'] );\n\t}\n\n\t/**\n\t * @covers ::get_editor_settings\n\t */\n\tpublic function test_get_editor_settings_passes_publisher_name_without_quotes(): void {\n\t\t$blogname = get_option( 'blogname' );\n\t\tupdate_option( 'blogname', \"S'mores\" );\n\n\t\t$results = $this->instance->get_editor_settings();\n\n\t\t$this->assertArrayHasKey( 'metadata', $results );\n\t\t$this->assertIsArray( $results['metadata'] );\n\t\t$this->assertArrayHasKey( 'publisher', $results['metadata'] );\n\n\t\tupdate_option( 'blogname', $blogname );\n\n\t\t$this->assertSame( \"S'mores\", $results['metadata']['publisher'] );\n\t}\n\n\t/**\n\t * @link https://github.com/GoogleForCreators/web-stories-wp/issues/12601\n\t *\n\t * @covers ::get_editor_settings\n\t */\n\tpublic function test_get_editor_settings_uses_correct_default_value(): void {\n\t\t$results = $this->instance->get_editor_settings();\n\n\t\t$this->assertTrue( $results['globalAutoAdvance'] );\n\t}\n\n\t/**\n\t * @covers ::setup_lock\n\t */\n\tpublic function test_setup_lock_admin(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$this->experiments->method( 'get_experiment_statuses' )->willReturn( [] );\n\t\t$this->experiments->method( 'is_experiment_enabled' )->willReturn( true );\n\n\t\t$this->call_private_method( [ $this->instance, 'setup_lock' ], [ self::$story_id ] );\n\n\t\t$value = get_post_meta( self::$story_id, '_edit_lock', true );\n\n\t\t$this->assertNotEmpty( $value );\n\t}\n\n\t/**\n\t * @covers ::setup_lock\n\t */\n\tpublic function test_setup_lock_subscriber(): void {\n\t\twp_set_current_user( self::$subscriber_id );\n\n\t\t$this->experiments->method( 'get_experiment_statuses' )->willReturn( [] );\n\t\t$this->experiments->method( 'is_experiment_enabled' )->willReturn( true );\n\n\t\t$this->call_private_method( [ $this->instance, 'setup_lock' ], [ self::$story_id ] );\n\n\t\t$value = get_post_meta( self::$story_id, '_edit_lock', true );\n\n\t\t$this->assertEmpty( $value );\n\t}\n\n\t/**\n\t * @covers ::filter_use_block_editor_for_post_type\n\t */\n\tpublic function test_filter_use_block_editor_for_post_type(): void {\n\t\t$this->experiments->method( 'get_experiment_statuses' )->willReturn( [] );\n\n\t\t$use_block_editor = $this->instance->filter_use_block_editor_for_post_type( true, $this->story_post_type->get_slug() );\n\t\t$this->assertFalse( $use_block_editor );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Meta_Boxes.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Meta_Boxes\n */\nclass Meta_Boxes extends TestCase {\n\t/**\n\t * Story ID.\n\t */\n\tprivate int $story_id;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t// Deliberately NOT created in wpSetUpBeforeClass() because this class contains running\n\t\t// in separate processes, which means tearDownAfterClass() (which deletes all WP data)\n\t\t// is run multiple times, causing the story not to be available anymore.\n\t\t$this->story_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Meta Boxes Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$meta_boxes = new \\Google\\Web_Stories\\Admin\\Meta_Boxes();\n\t\t$meta_boxes->register();\n\t\t$has_action = has_action(\n\t\t\t'add_meta_boxes_' . Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t[\n\t\t\t\t$meta_boxes,\n\t\t\t\t'remove_meta_boxes',\n\t\t\t]\n\t\t);\n\n\t\tremove_all_filters( 'add_meta_boxes_' . Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->assertSame( PHP_INT_MAX, $has_action );\n\t}\n\n\t/**\n\t * @covers ::get_meta_box_url\n\t */\n\tpublic function test_get_meta_box_url(): void {\n\t\t$meta_boxes = new \\Google\\Web_Stories\\Admin\\Meta_Boxes();\n\t\t$url        = $meta_boxes->get_meta_box_url( $this->story_id );\n\n\t\t$this->assertStringContainsString( 'wp-admin/post.php', $url );\n\t\t$this->assertStringContainsString( 'meta-box-loader=1', $url );\n\t\t$this->assertStringContainsString( 'meta-box-loader-nonce=', $url );\n\t}\n\n\t/**\n\t * @covers ::remove_meta_boxes\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_remove_meta_boxes(): void {\n\t\trequire_once ABSPATH . 'wp-admin/includes/meta-boxes.php';\n\n\t\tglobal $wp_meta_boxes, $current_screen;\n\n\t\t$current_screen = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\tadd_action( 'add_meta_boxes', [ $this, 'register_test_meta_boxes' ] );\n\n\n\t\t$current_post = get_post( $this->story_id );\n\n\t\t$this->assertNotNull( $current_post );\n\t\t// Registers default meta boxes.\n\t\tregister_and_do_post_meta_boxes( $current_post );\n\n\t\t$registered_meta_boxes = [];\n\n\t\tforeach ( \\Google\\Web_Stories\\Admin\\Meta_Boxes::LOCATIONS as $location ) {\n\t\t\tforeach ( [ 'high', 'core', 'default', 'low' ] as $priority ) {\n\t\t\t\tif ( ! isset( $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tforeach ( $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ] as $meta_box ) {\n\t\t\t\t\tif ( false === $meta_box ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$registered_meta_boxes[] = $meta_box['id'];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tremove_all_filters( 'add_meta_boxes' );\n\n\t\t$this->assertEqualSets(\n\t\t\t[ 'bar', 'foobar' ],\n\t\t\t$registered_meta_boxes\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_meta_boxes_per_location\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_meta_boxes_per_location(): void {\n\t\trequire_once ABSPATH . 'wp-admin/includes/meta-boxes.php';\n\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\tadd_action( 'add_meta_boxes', [ $this, 'register_test_meta_boxes' ] );\n\n\t\t$current_post = get_post( $this->story_id );\n\n\t\t$this->assertNotNull( $current_post );\n\n\t\t// Registers default meta boxes.\n\t\tregister_and_do_post_meta_boxes( $current_post );\n\n\t\t$meta_boxes = new \\Google\\Web_Stories\\Admin\\Meta_Boxes();\n\t\t$actual     = $meta_boxes->get_meta_boxes_per_location();\n\n\t\tremove_all_filters( 'add_meta_boxes' );\n\n\t\t$this->assertArrayHasKey( 'normal', $actual );\n\t\t$this->assertArrayHasKey( 'advanced', $actual );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'id'    => 'bar',\n\t\t\t\t\t'title' => 'Bar',\n\t\t\t\t],\n\t\t\t],\n\t\t\t$actual['normal']\n\t\t);\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'id'    => 'foobar',\n\t\t\t\t\t'title' => 'Foobar',\n\t\t\t\t],\n\t\t\t],\n\t\t\t$actual['advanced']\n\t\t);\n\t}\n\n\tpublic function register_test_meta_boxes(): void {\n\t\tadd_meta_box( 'foo', 'Foo', '__return_empty_string', null, 'normal', 'default', [ '__back_compat_meta_box' => true ] );\n\t\tadd_meta_box( 'bar', 'Bar', '__return_empty_string', null, 'normal', 'default', [ '__back_compat_meta_box' => false ] );\n\t\tadd_meta_box( 'baz', 'Baz', '__return_empty_string', null, 'advanced', 'default', [ '__back_compat_meta_box' => true ] );\n\t\tadd_meta_box( 'foobar', 'Foobar', '__return_empty_string', null, 'advanced', 'default', [ '__back_compat_meta_box' => false ] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/PluginActionLinks.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * PluginActionLinks class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class PluginActionLinks\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\PluginActionLinks\n */\nclass PluginActionLinks extends TestCase {\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$instance = new \\Google\\Web_Stories\\Admin\\PluginActionLinks();\n\t\t$instance->register();\n\n\t\t$basename = plugin_basename( WEBSTORIES_PLUGIN_FILE );\n\n\t\t$this->assertSame( 10, has_filter( 'plugin_action_links_' . $basename, [ $instance, 'action_links' ] ) );\n\t}\n\n\t/**\n\t * Test ::action_links().\n\t *\n\t * @covers ::action_links\n\t */\n\tpublic function test_action_links(): void {\n\t\t$initial_meta = [\n\t\t\t'Link 1',\n\t\t\t'Link 2',\n\t\t];\n\n\t\t$instance = new \\Google\\Web_Stories\\Admin\\PluginActionLinks();\n\t\t$links    = $instance->action_links( $initial_meta );\n\n\t\t$last_link = end( $links );\n\t\t$this->assertIsString( $last_link );\n\t\t$this->assertStringContainsString( 'Settings', $last_link );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/PluginRowMeta.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * PluginRowMeta class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2021 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class PluginRowMeta\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\PluginRowMeta\n */\nclass PluginRowMeta extends TestCase {\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$instance = new \\Google\\Web_Stories\\Admin\\PluginRowMeta();\n\t\t$instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'plugin_row_meta', [ $instance, 'get_plugin_row_meta' ] ) );\n\t}\n\n\t/**\n\t * Test ::get_plugin_row_meta().\n\t *\n\t * @covers ::get_plugin_row_meta\n\t */\n\tpublic function test_get_plugin_row_meta(): void {\n\n\t\t$initial_meta = [\n\t\t\t'Link 1',\n\t\t\t'Link 2',\n\t\t];\n\n\t\t$instance = new \\Google\\Web_Stories\\Admin\\PluginRowMeta();\n\t\t$this->assertEquals( $initial_meta, $instance->get_plugin_row_meta( $initial_meta, 'foo.php' ) );\n\n\t\t$expected_meta = array_merge(\n\t\t\t$initial_meta,\n\t\t\t[\n\t\t\t\t'<a href=\"https://wordpress.org/support/plugin/web-stories/\" target=\"_blank\" rel=\"noreferrer\">Contact support</a>',\n\t\t\t\t'<a href=\"https://wordpress.org/support/plugin/web-stories/reviews/#new-post\" target=\"_blank\" rel=\"noreferrer\">Leave review</a>',\n\t\t\t]\n\t\t);\n\n\t\t$plugin_file = plugin_basename( WEBSTORIES_PLUGIN_FILE );\n\t\t$this->assertEquals( $expected_meta, $instance->get_plugin_row_meta( $initial_meta, $plugin_file ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/Site_Health.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\Site_Health\n */\nclass Site_Health extends TestCase {\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$experiments = $this->createMock( Experiments::class );\n\t\t$site_health = new \\Google\\Web_Stories\\Admin\\Site_Health( $experiments );\n\t\t$site_health->register();\n\n\t\t$this->assertEquals( 10, has_filter( 'debug_information', [ $site_health, 'add_debug_information' ] ) );\n\t\t$this->assertEquals( 10, has_filter( 'site_status_test_php_modules', [ $site_health, 'add_extensions' ] ) );\n\t\t$this->assertEquals( 10, has_filter( 'site_status_test_result', [ $site_health, 'modify_test_result' ] ) );\n\t}\n\n\t/**\n\t * @covers ::add_debug_information\n\t */\n\tpublic function test_add_debug_information(): void {\n\t\t$experiments = $this->createMock( Experiments::class );\n\t\t$experiments->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturn( true );\n\t\t$experiments->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'bar',\n\t\t\t\t\t\t\t\t'label'       => 'Bar Label',\n\t\t\t\t\t\t\t\t'description' => 'Bar Desc',\n\t\t\t\t\t\t\t\t'default'     => true,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t$site_health = new \\Google\\Web_Stories\\Admin\\Site_Health( $experiments );\n\t\t$results     = $site_health->add_debug_information( [] );\n\n\t\t$this->assertArrayHasKey( 'web_stories', $results );\n\t\t$this->assertArrayHasKey( 'web_stories_version', $results['web_stories']['fields'] );\n\t\t$this->assertArrayHasKey( 'value', $results['web_stories']['fields']['web_stories_version'] );\n\t\t$this->assertSame( WEBSTORIES_VERSION, $results['web_stories']['fields']['web_stories_version']['value'] );\n\t\t$this->assertArrayHasKey( 'web_stories_enabled_experiments', $results['web_stories']['fields'] );\n\t\t$this->assertArrayHasKey( 'value', $results['web_stories']['fields']['web_stories_enabled_experiments'] );\n\t\t$this->assertIsArray( $results['web_stories']['fields']['web_stories_enabled_experiments']['value'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Admin/TinyMCE.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Admin;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Admin\\TinyMCE\n */\nclass TinyMCE extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Admin\\TinyMCE $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Admin\\TinyMCE::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'mce_buttons', [ $this->instance, 'tinymce_web_stories_button' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'mce_external_plugins', [ $this->instance, 'web_stories_mce_plugin' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'admin_footer', [ $this->instance, 'web_stories_tinymce_root_element' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'script_loader_tag', [ $this->instance, 'script_loader_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register_assets\n\t */\n\tpublic function test_register_assets(): void {\n\t\t$this->instance->register_assets();\n\n\t\t$this->assertTrue( wp_script_is( \\Google\\Web_Stories\\Admin\\TinyMCE::SCRIPT_HANDLE, 'registered' ) );\n\t}\n\n\t/**\n\t * @covers ::tinymce_web_stories_button\n\t */\n\tpublic function test_tinymce_web_stories_button(): void {\n\t\t$result = $this->instance->tinymce_web_stories_button( [] );\n\n\t\t$this->assertContains( 'web_stories', $result );\n\t}\n\n\t/**\n\t * @covers ::web_stories_mce_plugin\n\t */\n\tpublic function test_web_stories_mce_plugin(): void {\n\t\t$result = $this->instance->web_stories_mce_plugin( [] );\n\n\t\t$this->assertArrayHasKey( 'web_stories', $result );\n\t}\n\n\t/**\n\t * @covers ::web_stories_tinymce_root_element\n\t */\n\tpublic function test_web_stories_tinymce_root_element(): void {\n\t\t$result = get_echo( [ $this->instance, 'web_stories_tinymce_root_element' ] );\n\t\t$result = trim( $result );\n\n\t\t$this->assertSame( '<div id=\"web-stories-tinymce\"></div>', $result );\n\t}\n\n\t/**\n\t * @covers ::script_loader_tag\n\t */\n\tpublic function test_script_loader_tag(): void {\n\t\t$result = $this->instance->script_loader_tag( \"<script src='http://www.example.com/test.js'></script>\", \\Google\\Web_Stories\\Admin\\TinyMCE::SCRIPT_HANDLE, 'http://www.example.com/test.js' );\n\n\t\t$this->assertSame( '', $result );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Analytics.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Analytics\n */\nclass Analytics extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Analytics $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Analytics::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'web_stories_print_analytics', [ $this->instance, 'print_analytics_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::get_tracking_id\n\t */\n\tpublic function test_get_tracking_id_casts_to_string(): void {\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, 123_456_789, false );\n\n\t\t$this->assertSame( '123456789', $this->instance->get_tracking_id() );\n\t}\n\n\t/**\n\t * @covers ::get_default_configuration\n\t */\n\tpublic function test_get_default_configuration(): void {\n\t\t$tracking_id = '123456789';\n\t\t$actual      = $this->instance->get_default_configuration( $tracking_id );\n\n\t\t$this->assertArrayHasKey( 'vars', $actual );\n\t\t$this->assertArrayHasKey( 'gtag_id', $actual['vars'] );\n\t\t$this->assertSame( (string) $tracking_id, $actual['vars']['gtag_id'] );\n\t\t$this->assertArrayHasKey( 'config', $actual['vars'] );\n\t\t$this->assertIsArray( $actual['vars']['config'] );\n\t\t$this->assertArrayHasKey( $tracking_id, $actual['vars']['config'] );\n\t\t$this->assertArrayHasKey( 'triggers', $actual );\n\t\tforeach ( $actual['triggers'] as $trigger_config ) {\n\t\t\t$this->assertIsArray( $trigger_config );\n\t\t\t$this->assertArrayHasKey( 'vars', $trigger_config );\n\t\t\t$this->assertIsArray( $trigger_config['vars'] );\n\t\t\t$this->assertArrayHasKey( 'send_to', $trigger_config['vars'] );\n\t\t\t$this->assertSame( $tracking_id, $trigger_config['vars']['send_to'] );\n\n\t\t\tforeach ( $trigger_config['vars'] as $value ) {\n\t\t\t\t// Catch typos like ${foo) instead of ${foo}.\n\t\t\t\tif ( false !== strpos( $value, '$' ) ) {\n\t\t\t\t\t$this->assertMatchesRegularExpression( '/^\\${[^}]+}$/', $value, 'Invalid variable declaration present' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::print_analytics_tag\n\t */\n\tpublic function test_print_analytics_tag(): void {\n\t\t$actual_before = get_echo( [ $this->instance, 'print_analytics_tag' ] );\n\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, 123_456_789, false );\n\t\tupdate_option( Settings::SETTING_NAME_USING_LEGACY_ANALYTICS, false );\n\n\t\t$actual_after = get_echo( [ $this->instance, 'print_analytics_tag' ] );\n\n\t\t$this->assertEmpty( $actual_before );\n\t\t$this->assertStringContainsString( '<amp-story-auto-analytics', $actual_after );\n\t}\n\n\t/**\n\t * @covers ::print_analytics_tag\n\t */\n\tpublic function test_print_analytics_tag_legacy(): void {\n\t\t$actual_before = get_echo( [ $this->instance, 'print_analytics_tag' ] );\n\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, 123_456_789, false );\n\t\tupdate_option( Settings::SETTING_NAME_USING_LEGACY_ANALYTICS, true );\n\n\t\t$actual_after = get_echo( [ $this->instance, 'print_analytics_tag' ] );\n\n\t\t$this->assertEmpty( $actual_before );\n\t\t$this->assertStringContainsString( '<amp-analytics', $actual_after );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Assets.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse _WP_Dependency;\n\n/**\n * Class Assets\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Assets\n */\nclass Assets extends TestCase {\n\tpublic function tear_down(): void {\n\t\twp_deregister_script( 'test_script' );\n\t\twp_deregister_script( 'fake_js_chunk' );\n\t\twp_deregister_style( 'test_style' );\n\t\twp_deregister_style( 'fake_css_chunk' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register_style\n\t */\n\tpublic function test_register_style(): void {\n\t\t$assets          = new \\Google\\Web_Stories\\Assets();\n\t\t$results         = $assets->register_style( 'test_style', false );\n\t\t$register_styles = $this->get_private_property( $assets, 'register_styles' );\n\t\t$this->assertIsArray( $register_styles );\n\t\t$this->assertArrayHasKey( 'test_style', $register_styles );\n\t\t$this->assertTrue( $results );\n\t}\n\n\t/**\n\t * @covers ::register_script\n\t */\n\tpublic function test_register_script(): void {\n\t\t$assets           = new \\Google\\Web_Stories\\Assets();\n\t\t$results          = $assets->register_script( 'test_script', 'https://example.com/test.js' );\n\t\t$register_scripts = $this->get_private_property( $assets, 'register_scripts' );\n\t\t$this->assertIsArray( $register_scripts );\n\t\t$this->assertArrayHasKey( 'test_script', $register_scripts );\n\t\t$this->assertTrue( $results );\n\t\t/**\n\t\t * An array of all registered dependencies keyed by handle.\n\t\t *\n\t\t * @var _WP_Dependency[] $registered\n\t\t */\n\t\t$registered = wp_scripts()->registered;\n\t\t$this->assertArrayHasKey( 'test_script', $registered );\n\t\t$this->assertSame( 'web-stories', $registered['test_script']->textdomain );\n\t}\n\n\t/**\n\t * @covers ::register_script\n\t */\n\tpublic function test_register_script_without_src(): void {\n\t\t$assets           = new \\Google\\Web_Stories\\Assets();\n\t\t$results          = $assets->register_script( 'test_script', false );\n\t\t$register_scripts = $this->get_private_property( $assets, 'register_scripts' );\n\t\t$this->assertIsArray( $register_scripts );\n\t\t$this->assertArrayHasKey( 'test_script', $register_scripts );\n\t\t$this->assertTrue( $results );\n\t\t/**\n\t\t * An array of all registered dependencies keyed by handle.\n\t\t *\n\t\t * @var _WP_Dependency[] $registered\n\t\t */\n\t\t$registered = wp_scripts()->registered;\n\t\t$this->assertArrayHasKey( 'test_script', $registered );\n\t\t$this->assertNull( $registered['test_script']->textdomain );\n\t}\n\n\t/**\n\t * @covers ::enqueue_style\n\t */\n\tpublic function test_enqueue_style(): void {\n\t\t$assets = new \\Google\\Web_Stories\\Assets();\n\t\t$assets->enqueue_style( 'test_style', '' );\n\t\t$register_styles = $this->get_private_property( $assets, 'register_styles' );\n\t\t$this->assertIsArray( $register_styles );\n\t\t$this->assertArrayHasKey( 'test_style', $register_styles );\n\t\t$this->assertTrue( wp_style_is( 'test_style' ) );\n\t}\n\n\t/**\n\t * @covers ::enqueue_script\n\t */\n\tpublic function test_enqueue_script(): void {\n\t\t$assets = new \\Google\\Web_Stories\\Assets();\n\t\t$assets->enqueue_script( 'test_script', '' );\n\t\t$register_scripts = $this->get_private_property( $assets, 'register_scripts' );\n\t\t$this->assertIsArray( $register_scripts );\n\t\t$this->assertArrayHasKey( 'test_script', $register_scripts );\n\t\t$this->assertTrue( wp_script_is( 'test_script' ) );\n\t}\n\n\t/**\n\t * @covers ::register_script_asset\n\t */\n\tpublic function test_register_script_asset(): void {\n\t\t$assets = $this->getMockBuilder( \\Google\\Web_Stories\\Assets::class )->onlyMethods( [ 'get_asset_metadata' ] )->getMock();\n\t\t$assets->method( 'get_asset_metadata' )\n\t\t\t->willReturn(\n\t\t\t\t[\n\t\t\t\t\t'dependencies' => [],\n\t\t\t\t\t'version'      => '9.9.9',\n\t\t\t\t\t'js'           => [ 'fake_js_chunk' ],\n\t\t\t\t\t'css'          => [ 'fake_css_chunk' ],\n\t\t\t\t\t'chunks'       => [],\n\t\t\t\t]\n\t\t\t);\n\t\t$assets->register_script_asset( 'test_script' );\n\t\t$this->assertTrue( wp_script_is( 'test_script', 'registered' ) );\n\t\t$this->assertTrue( wp_script_is( 'fake_js_chunk', 'registered' ) );\n\t}\n\n\t/**\n\t * @covers ::register_script_asset\n\t */\n\tpublic function test_register_script_asset_prints_translations_for_chunks(): void {\n\t\t$assets = $this->getMockBuilder( \\Google\\Web_Stories\\Assets::class )->onlyMethods( [ 'get_asset_metadata' ] )->getMock();\n\t\t$assets->method( 'get_asset_metadata' )\n\t\t\t->willReturn(\n\t\t\t\t[\n\t\t\t\t\t'dependencies' => [],\n\t\t\t\t\t'version'      => '9.9.9',\n\t\t\t\t\t'js'           => [ 'fake_js_chunk' ],\n\t\t\t\t\t'css'          => [ 'fake_css_chunk' ],\n\t\t\t\t\t'chunks'       => [ 'dynamic_import_chunk' ],\n\t\t\t\t]\n\t\t\t);\n\t\t$assets->register_script_asset( 'test_script' );\n\t\t$this->assertTrue( wp_script_is( 'test_script', 'registered' ) );\n\t\t$this->assertTrue( wp_script_is( 'fake_js_chunk', 'registered' ) );\n\t\t$this->assertTrue( wp_script_is( 'dynamic_import_chunk', 'registered' ) );\n\n\t\t/**\n\t\t * An array of all registered dependencies keyed by handle.\n\t\t *\n\t\t * @var _WP_Dependency[] $registered\n\t\t */\n\t\t$registered = wp_scripts()->registered;\n\t\t// Verifies that wp_set_script_translations() has been called.\n\t\t$this->assertSame( 'web-stories', $registered['test_script']->textdomain );\n\t\t$this->assertSame( 'web-stories', $registered['fake_js_chunk']->textdomain );\n\t\t$this->assertSame( 'web-stories', $registered['dynamic_import_chunk']->textdomain );\n\t\t$this->assertContains( 'wp-i18n', $registered['test_script']->deps );\n\t\t$this->assertContains( 'fake_js_chunk', $registered['test_script']->deps );\n\t\t$this->assertNotContains( 'dynamic_import_chunk', $registered['test_script']->deps );\n\t\t$this->assertContains( 'wp-i18n', $registered['fake_js_chunk']->deps );\n\t\t$this->assertContains( 'wp-i18n', $registered['dynamic_import_chunk']->deps );\n\t}\n\n\t/**\n\t * @covers ::register_style_asset\n\t */\n\tpublic function test_register_style_asset(): void {\n\t\t$assets = $this->getMockBuilder( \\Google\\Web_Stories\\Assets::class )->onlyMethods( [ 'get_asset_metadata' ] )->getMock();\n\t\t$assets->method( 'get_asset_metadata' )\n\t\t\t->willReturn(\n\t\t\t\t[\n\t\t\t\t\t'dependencies' => [],\n\t\t\t\t\t'version'      => '9.9.9',\n\t\t\t\t\t'js'           => [ 'fake_js_chunk' ],\n\t\t\t\t\t'css'          => [ 'fake_css_chunk' ],\n\t\t\t\t\t'chunks'       => [],\n\t\t\t\t]\n\t\t\t);\n\t\t$assets->register_style_asset( 'test_style' );\n\t\t$this->assertTrue( wp_style_is( 'test_style', 'registered' ) );\n\t\t$this->assertTrue( wp_style_is( 'fake_css_chunk', 'registered' ) );\n\t\t\t\t\n\t\t/**\n\t\t * An array of all registered dependencies keyed by handle.\n\t\t *\n\t\t * @var array<string, _WP_Dependency> $registered\n\t\t */\n\t\t$registered = wp_styles()->registered;\n\t\t\n\t\t$test_style_metadata     = $registered['test_style']->extra;\n\t\t$fake_css_chunk_metadata = $registered['fake_css_chunk']->extra;\n\t\t\n\t\t$this->assertArrayHasKey( 'path', $test_style_metadata );\n\t\t$this->assertArrayHasKey( 'path', $fake_css_chunk_metadata );\n\t}\n\n\t/**\n\t * @covers ::get_asset_metadata\n\t */\n\tpublic function test_get_asset_metadata_falls_back_to_plugin_version(): void {\n\t\t$assets  = new \\Google\\Web_Stories\\Assets();\n\t\t$results = $assets->get_asset_metadata( 'test_script' );\n\n\t\t$this->assertSame( $results['version'], WEBSTORIES_VERSION );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Block/Web_Stories_Block.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Block;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Block;\nuse WP_Block_Type_Registry;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Block\\Web_Stories_Block\n */\nclass Web_Stories_Block extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Block\\Web_Stories_Block $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Block\\Web_Stories_Block::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tunregister_block_type( 'web-stories/embed' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::register_block_type\n\t */\n\tpublic function test_registers_block_type(): void {\n\t\t$this->assertTrue( WP_Block_Type_Registry::get_instance()->is_registered( 'web-stories/embed' ) );\n\t}\n\n\t/**\n\t * @covers ::render_block\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_block(): void {\n\t\t$actual = $this->instance->render_block(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t'',\n\t\t\tnew WP_Block( [ 'blockName' => 'web-stories/embed' ] )\n\t\t);\n\n\t\t$this->assertStringContainsString( '<amp-story-player', $actual );\n\t}\n\n\t/**\n\t * @covers ::render_block\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_block_missing_url(): void {\n\t\t$actual = $this->instance->render_block(\n\t\t\t[\n\t\t\t\t'url'    => '',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t'',\n\t\t\tnew WP_Block( [ 'blockName' => 'web-stories/embed' ] )\n\t\t);\n\n\t\t$this->assertEmpty( $actual );\n\t}\n\n\t/**\n\t * @covers ::render_block\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_block_missing_title(): void {\n\t\t$actual = $this->instance->render_block(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => '',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t'',\n\t\t\tnew WP_Block( [ 'blockName' => 'web-stories/embed' ] )\n\t\t);\n\n\t\t$this->assertStringContainsString( __( 'Web Story', 'web-stories' ), $actual );\n\t}\n\n\t/**\n\t * @covers ::render_block\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Image::render\n\t */\n\tpublic function test_render_block_feed_no_poster(): void {\n\t\t$this->go_to( '/?feed=rss2' );\n\n\t\t$actual = $this->instance->render_block(\n\t\t\t[\n\t\t\t\t'url'   => 'https://example.com/story.html',\n\t\t\t\t'title' => 'Example Story',\n\t\t\t\t'align' => 'none',\n\t\t\t],\n\t\t\t'',\n\t\t\tnew WP_Block( [ 'blockName' => 'web-stories/embed' ] )\n\t\t);\n\n\t\t$this->assertStringNotContainsString( '<amp-story-player', $actual );\n\t\t$this->assertStringNotContainsString( '<img', $actual );\n\t}\n\n\t/**\n\t * @covers ::render_block\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Image::render\n\t */\n\tpublic function test_render_block_with_poster(): void {\n\t\t$this->go_to( '/?feed=rss2' );\n\n\t\t$actual = $this->instance->render_block(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'poster' => 'https://example.com/story.jpg',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t'',\n\t\t\tnew WP_Block( [ 'blockName' => 'web-stories/embed' ] )\n\t\t);\n\n\t\t$this->assertStringNotContainsString( '<amp-story-player', $actual );\n\t\t$this->assertStringContainsString( '<img', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Context.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Context\n */\nclass Context extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Context $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Context::class );\n\t}\n\n\t/**\n\t * @covers ::is_story_editor\n\t */\n\tpublic function test_is_story_editor(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->assertTrue( $this->instance->is_story_editor() );\n\t}\n\n\t/**\n\t * @covers ::is_block_editor\n\t */\n\tpublic function test_is_block_editor(): void {\n\t\t$this->assertFalse( $this->instance->is_block_editor() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Database_Upgrader.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * Class Database_Upgrader\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Database_Upgrader\n */\nclass Database_Upgrader extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Database_Upgrader $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Database_Upgrader::class );\n\n\t\tdelete_option( $this->instance::OPTION );\n\t\tdelete_option( $this->instance::PREVIOUS_OPTION );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 5, has_action( 'admin_init', [ $this->instance, 'run_upgrades' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register_does_not_set_missing_options_on_frontend(): void {\n\t\t$this->instance->register();\n\t\t$this->assertFalse( get_option( $this->instance::OPTION ) );\n\t\t$this->assertFalse( get_option( $this->instance::PREVIOUS_OPTION ) );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register_does_not_override_previous_version_if_there_was_no_update(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( 'post' );\n\n\t\tadd_option( $this->instance::OPTION, WEBSTORIES_DB_VERSION );\n\t\tadd_option( $this->instance::PREVIOUS_OPTION, '1.2.3' );\n\n\t\t$this->instance->register();\n\t\t$this->assertSame( WEBSTORIES_DB_VERSION, get_option( $this->instance::OPTION ) );\n\t\t$this->assertSame( '1.2.3', get_option( $this->instance::PREVIOUS_OPTION ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\n\t\tadd_option( $this->instance::OPTION, WEBSTORIES_DB_VERSION );\n\t\tadd_option( $this->instance::PREVIOUS_OPTION, '1.2.3' );\n\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertFalse( get_option( $this->instance::OPTION ) );\n\t\t$this->assertFalse( get_option( $this->instance::PREVIOUS_OPTION ) );\n\t}\n\n\t/**\n\t * @group ms-required\n\t * @covers ::on_site_initialization\n\t */\n\tpublic function test_sets_missing_options_on_site_initialization(): void {\n\t\t$blog_id = self::factory()->blog->create();\n\n\t\t$this->assertNotWPError( $blog_id );\n\n\t\tswitch_to_blog( $blog_id );\n\n\t\t$db_version   = get_option( $this->instance::OPTION );\n\t\t$prev_version = get_option( $this->instance::PREVIOUS_OPTION );\n\n\t\trestore_current_blog();\n\n\t\t$this->assertSame( WEBSTORIES_DB_VERSION, $db_version );\n\t\t$this->assertSame( '0.0.0', $prev_version );\n\t}\n\n\tpublic function test_migration_routines_are_sorted_and_in_sync(): void {\n\t\t$versions = array_keys( $this->instance::ROUTINES );\n\n\t\t$versions_sorted = [ ...$versions ];\n\t\tusort( $versions_sorted, static fn( $a, $b ) => version_compare( (string) $a, (string) $b ) );\n\n\t\t$latest_version = end( $versions_sorted );\n\n\t\t$this->assertSame( WEBSTORIES_DB_VERSION, $latest_version );\n\t\t$this->assertSame( $versions, $versions_sorted );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Demo_Content.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Demo_Content\n */\nclass Demo_Content extends TestCase {\n\tpublic function test_json_file_contains_replaceable_urls(): void {\n\t\t$file          = WEBSTORIES_PLUGIN_DIR_PATH . 'includes/data/stories/demo.json';\n\t\t$file_contents = file_get_contents( $file );\n\t\t$this->assertIsString( $file_contents );\n\n\t\t/**\n\t\t * @var array<string, array<string, mixed>> $story\n\t\t */\n\t\t$story = json_decode( $file_contents, true );\n\n\t\t$this->assertArrayHasKey( 'pages', $story );\n\n\t\tforeach ( $story['pages'] as $page ) {\n\t\t\t$this->assertIsArray( $page );\n\t\t\t$this->assertArrayHasKey( 'elements', $page );\n\t\t\tforeach ( $page['elements'] as $element ) {\n\t\t\t\tif ( ! \\array_key_exists( 'resource', $element ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$this->assertStringStartsWith( 'https://replaceme.com/images/demo-story/', $element['resource']['src'] );\n\t\t\t\tif ( \\array_key_exists( 'poster', $element['resource'] ) ) {\n\t\t\t\t\t$this->assertStringStartsWith( 'https://replaceme.com/images/demo-story/', $element['resource']['poster'] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_title\n\t */\n\tpublic function test_get_title(): void {\n\t\t$demo  = new \\Google\\Web_Stories\\Demo_Content();\n\t\t$title = $demo->get_title();\n\n\t\t$this->assertNotEmpty( $title );\n\t}\n\n\t/**\n\t * @covers ::get_content\n\t */\n\tpublic function test_get_content(): void {\n\t\t$demo    = new \\Google\\Web_Stories\\Demo_Content();\n\t\t$content = $demo->get_content();\n\n\t\t$this->assertNotEmpty( $content );\n\t\t$this->assertJson( $content );\n\t}\n\n\t/**\n\t * @covers ::update_assets_urls\n\t */\n\tpublic function test_update_assets_urls(): void {\n\t\t$demo    = new \\Google\\Web_Stories\\Demo_Content();\n\t\t$content = $demo->get_content();\n\n\t\t$this->assertStringNotContainsString( 'https://replaceme.com', $content, 'Not all URLs have been replaced' );\n\t\t$this->assertStringContainsString( WEBSTORIES_CDN_URL . '/images/demo-story/', $content, 'Assets URLs have been corrupted' );\n\t}\n\n\t/**\n\t * @covers ::localize_texts\n\t */\n\tpublic function test_localize_texts(): void {\n\t\t$demo    = new \\Google\\Web_Stories\\Demo_Content();\n\t\t$content = $demo->get_content();\n\n\t\t$this->assertStringNotContainsString( 'L10N_PLACEHOLDER', $content, 'Not all localization placeholders have been replaced' );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Discovery.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Shopping\\Product;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Discovery\n */\nclass Discovery extends DependencyInjectedTestCase {\n\n\t/**\n\t * User ID.\n\t */\n\tprotected static int $user_id;\n\n\t/**\n\t * Story ID.\n\t */\n\tprotected static int $story_id;\n\n\t/**\n\t * Image attachment id.\n\t */\n\tprotected static int $attachment_id;\n\n\t/**\n\t * Archive page ID.\n\t */\n\tprotected static int $archive_page_id;\n\n\tprivate \\Google\\Web_Stories\\Discovery $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Discovery Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$user_id,\n\t\t\t]\n\t\t);\n\t\t/**\n\t\t * @var int $attachment_id\n\t\t */\n\t\t$attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => self::$story_id,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tself::$attachment_id = $attachment_id;\n\n\t\t/**\n\t\t * @var \\WP_Post $current_post\n\t\t */\n\t\t$current_post = get_post( self::$attachment_id );\n\n\t\twp_maybe_generate_attachment_metadata( $current_post );\n\t\tset_post_thumbnail( self::$story_id, self::$attachment_id );\n\n\t\tadd_theme_support( 'automatic-feed-links' );\n\n\t\tself::$archive_page_id = self::factory()->post->create( [ 'post_type' => 'page' ] );\n\t}\n\n\tpublic static function tear_down_after_class(): void {\n\t\tremove_theme_support( 'automatic-feed-links' );\n\n\t\tparent::tear_down_after_class();\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Discovery::class );\n\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\t\t$this->go_to( (string) get_permalink( self::$story_id ) );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\t\t$this->assertSame( 10, has_action( 'web_stories_story_head', [ $this->instance, 'print_document_title' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_story_head', [ $this->instance, 'print_metadata' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_story_head', [ $this->instance, 'print_schemaorg_metadata' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_story_head', [ $this->instance, 'print_open_graph_metadata' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_story_head', [ $this->instance, 'print_twitter_metadata' ] ) );\n\t\t$this->assertSame( 4, has_action( 'web_stories_story_head', [ $this->instance, 'print_feed_link' ] ) );\n\t}\n\n\t/**\n\t * @covers ::print_metadata\n\t */\n\tpublic function test_print_metadata(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_metadata' ] );\n\t\t$this->assertStringContainsString( '<meta', $output );\n\t}\n\n\t/**\n\t * @covers ::print_metadata\n\t */\n\tpublic function test_print_document_title(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_document_title' ] );\n\t\t$this->assertStringContainsString( '<title>', $output );\n\t}\n\n\t/**\n\t * @covers ::print_schemaorg_metadata\n\t */\n\tpublic function test_print_schemaorg_metadata(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_schemaorg_metadata' ] );\n\t\t$this->assertStringContainsString( 'application/ld+json', $output );\n\t}\n\n\t/**\n\t * @covers ::get_schemaorg_metadata\n\t */\n\tpublic function test_get_schemaorg_metadata(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_schemaorg_metadata' ] );\n\t\t$this->assertArrayHasKey( 'mainEntityOfPage', $result );\n\t\t$this->assertArrayHasKey( 'headline', $result );\n\t\t$this->assertArrayHasKey( 'datePublished', $result );\n\t\t$this->assertArrayHasKey( 'dateModified', $result );\n\t\t$this->assertArrayHasKey( 'author', $result );\n\t\t$this->assertArrayHasKey( 'image', $result );\n\t}\n\n\t/**\n\t * @covers ::print_open_graph_metadata\n\t */\n\tpublic function test_print_open_graph_metadata(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_open_graph_metadata' ] );\n\t\t$this->assertStringContainsString( 'og:locale', $output );\n\t\t$this->assertStringContainsString( 'og:type', $output );\n\t\t$this->assertStringContainsString( 'og:description', $output );\n\t\t$this->assertStringContainsString( 'article:published_time', $output );\n\t\t$this->assertStringContainsString( 'article:modified_time', $output );\n\t\t$this->assertStringContainsString( 'og:image', $output );\n\t\t$this->assertStringContainsString( 'og:image:width', $output );\n\t\t$this->assertStringContainsString( 'og:image:height', $output );\n\t}\n\n\t/**\n\t * @covers ::get_open_graph_metadata\n\t */\n\tpublic function test_get_open_graph_metadata(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_open_graph_metadata' ] );\n\t\t$this->assertArrayHasKey( 'og:locale', $result );\n\t\t$this->assertArrayHasKey( 'og:type', $result );\n\t\t$this->assertArrayHasKey( 'og:description', $result );\n\t\t$this->assertArrayHasKey( 'article:published_time', $result );\n\t\t$this->assertArrayHasKey( 'article:modified_time', $result );\n\t\t$this->assertArrayHasKey( 'og:image', $result );\n\t\t$this->assertArrayHasKey( 'og:image:width', $result );\n\t\t$this->assertArrayHasKey( 'og:image:height', $result );\n\t}\n\n\t/**\n\t * @covers ::print_feed_link\n\t */\n\tpublic function test_print_feed_link(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_feed_link' ] );\n\t\t$this->assertStringContainsString( '<link rel=\"alternate\"', $output );\n\t\t$this->assertStringContainsString( get_bloginfo( 'name' ), $output );\n\t}\n\n\t/**\n\t * @covers ::print_feed_link\n\t */\n\tpublic function test_print_feed_link_custom_archive(): void {\n\t\tupdate_option( Settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( Settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\t$output = get_echo( [ $this->instance, 'print_feed_link' ] );\n\n\t\tdelete_option( Settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( Settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertStringContainsString( '<link rel=\"alternate\"', $output );\n\t\t$this->assertStringContainsString( get_bloginfo( 'name' ), $output );\n\t}\n\n\t/**\n\t * @covers ::print_feed_link\n\t */\n\tpublic function test_print_feed_link_filter(): void {\n\t\tadd_filter( 'web_stories_enable_print_feed_link', '__return_false' );\n\t\t$output = get_echo( [ $this->instance, 'print_feed_link' ] );\n\t\t$this->assertEmpty( $output );\n\t\tremove_filter( 'web_stories_enable_print_feed_link', '__return_false' );\n\t}\n\n\n\t/**\n\t * @covers ::print_twitter_metadata\n\t */\n\tpublic function test_print_twitter_metadata(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_twitter_metadata' ] );\n\t\t$this->assertStringContainsString( 'twitter:card', $output );\n\t\t$this->assertStringContainsString( 'twitter:image', $output );\n\t\t$this->assertStringContainsString( 'twitter:image:alt', $output );\n\t\t$this->assertStringContainsString( 'Discovery Test Story', $output );\n\t}\n\n\t/**\n\t * @covers ::get_twitter_metadata\n\t */\n\tpublic function test_get_twitter_metadata(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_twitter_metadata' ] );\n\t\t$this->assertArrayHasKey( 'twitter:card', $result );\n\t\t$this->assertArrayHasKey( 'twitter:image', $result );\n\t\t$this->assertArrayHasKey( 'twitter:image:alt', $result );\n\t\t$this->assertSame( 'Discovery Test Story', $result['twitter:image:alt'] );\n\t}\n\n\t/**\n\t * @covers ::get_product_data\n\t */\n\tpublic function test_get_product_data(): void {\n\t\t$product_object = Product::load_from_array(\n\t\t\t[\n\t\t\t\t'aggregateRating'      => [\n\t\t\t\t\t'ratingValue' => 5,\n\t\t\t\t\t'reviewCount' => 1,\n\t\t\t\t\t'reviewUrl'   => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t],\n\t\t\t\t'ratingValue'          => 0,\n\t\t\t\t'reviewCount'          => 0,\n\t\t\t\t'reviewUrl'            => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t'productBrand'         => 'Google',\n\t\t\t\t'productDetails'       => 'This is a simple product.',\n\t\t\t\t'productId'            => 'wc-36',\n\t\t\t\t'productImages'        => [\n\t\t\t\t\t[\n\t\t\t\t\t\t'url' => 'http://www.example.com/wp-content/uploads/2019/01/t-shirt-with-logo-1-4.jpg',\n\t\t\t\t\t\t'alt' => '',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'productPrice'         => 18,\n\t\t\t\t'productPriceCurrency' => 'USD',\n\t\t\t\t'productTitle'         => 'T-Shirt with Logo',\n\t\t\t\t'productUrl'           => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t]\n\t\t);\n\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_product_data' ], [ [ $product_object ] ] );\n\n\t\t$expected = [\n\t\t\t'products' =>\n\t\t\t\t[\n\n\t\t\t\t\t'@type'           => 'ItemList',\n\t\t\t\t\t'numberOfItems'   => '1',\n\t\t\t\t\t'itemListElement' =>\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'@type'           => 'Product',\n\t\t\t\t\t\t\t\t'brand'           => 'Google',\n\t\t\t\t\t\t\t\t'productID'       => 'wc-36',\n\t\t\t\t\t\t\t\t'url'             => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t\t\t\t\t'name'            => 'T-Shirt with Logo',\n\t\t\t\t\t\t\t\t'description'     => 'This is a simple product.',\n\t\t\t\t\t\t\t\t'image'           => 'http://www.example.com/wp-content/uploads/2019/01/t-shirt-with-logo-1-4.jpg',\n\t\t\t\t\t\t\t\t'aggregateRating' => [\n\t\t\t\t\t\t\t\t\t'@type'       => 'AggregateRating',\n\t\t\t\t\t\t\t\t\t'ratingValue' => 5,\n\t\t\t\t\t\t\t\t\t'reviewCount' => 1,\n\t\t\t\t\t\t\t\t\t'url'         => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t'offers'          => [\n\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t'@type'         => 'Offer',\n\t\t\t\t\t\t\t\t\t\t'price'         => 18,\n\t\t\t\t\t\t\t\t\t\t'priceCurrency' => 'USD',\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t],\n\t\t];\n\n\t\t$this->assertEqualSets( $expected, $result );\n\t}\n\n\t/**\n\t * @covers ::get_product_data\n\t */\n\tpublic function test_get_product_data_empty_story(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_product_data' ], [ [] ] );\n\n\t\t$expected = [];\n\n\t\t$this->assertEqualSets( $expected, $result );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Embed_Base.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Embed_Base\n */\nclass Embed_Base extends TestCase {\n\n\t/**\n\t * @covers ::filter_kses_allowed_html\n\t */\n\tpublic function test_adds_amp_story_player_to_list_of_allowed_html(): void {\n\t\t$this->assertArrayHasKey( 'amp-story-player', wp_kses_allowed_html() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Experiments.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Experiments\n */\nclass Experiments extends DependencyInjectedTestCase {\n\n\tprotected static int $user_id;\n\n\tprivate \\Google\\Web_Stories\\Experiments $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Experiments::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_EXPERIMENTS );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t// Because WEBSTORIES_DEV_MODE is false by default.\n\t\t$this->assertFalse( has_action( 'admin_menu', [ $this->instance, 'add_menu_page' ] ) );\n\t\t$this->assertFalse( has_action( 'admin_init', [ $this->instance, 'initialize_settings' ] ) );\n\t}\n\n\t/**\n\t * @covers ::initialize_settings\n\t */\n\tpublic function test_initialize_settings(): void {\n\t\tglobal $wp_settings_fields, $wp_settings_sections;\n\n\t\t$this->instance->initialize_settings();\n\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\Experiments::PAGE_NAME, $wp_settings_fields );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\Experiments::PAGE_NAME, $wp_settings_sections );\n\t\t$this->assertArrayHasKey( 'web_stories_experiments_section', $wp_settings_sections[ \\Google\\Web_Stories\\Experiments::PAGE_NAME ] );\n\t}\n\n\t/**\n\t * @covers ::display_experiment_field\n\t */\n\tpublic function test_display_experiment_field(): void {\n\t\t$this->instance = $this->createTestProxy(\n\t\t\t\\Google\\Web_Stories\\Experiments::class,\n\t\t\t[ $this->injector->make( Settings::class ) ]\n\t\t);\n\t\t$this->instance->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t$this->instance->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturn( false );\n\n\t\t$output = get_echo(\n\t\t\t[ $this->instance, 'display_experiment_field' ],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'label' => 'Foo Label',\n\t\t\t\t\t'id'    => 'foo',\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->assertStringNotContainsString( \"checked='checked'\", $output );\n\t}\n\n\t/**\n\t * @covers ::display_experiment_field\n\t */\n\tpublic function test_display_experiment_field_enabled(): void {\n\t\t$this->instance = $this->getMockBuilder( \\Google\\Web_Stories\\Experiments::class )\n\t\t\t->setConstructorArgs( [ $this->injector->make( Settings::class ) ] )\n\t\t\t->onlyMethods( [ 'get_experiments', 'is_experiment_enabled' ] )\n\t\t\t->getMock();\n\n\t\t$this->instance->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t$this->instance->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturn( true );\n\n\t\t$output = get_echo(\n\t\t\t[ $this->instance, 'display_experiment_field' ],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'label' => 'Foo Label',\n\t\t\t\t\t'id'    => 'foo',\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t\t$this->assertStringContainsString( \"checked='checked'\", $output );\n\t}\n\n\t/**\n\t * @covers ::display_experiment_field\n\t */\n\tpublic function test_display_experiment_field_enabled_by_default(): void {\n\t\t$this->instance = $this->getMockBuilder( \\Google\\Web_Stories\\Experiments::class )\n\t\t\t\t\t\t\t->setConstructorArgs( [ $this->injector->make( Settings::class ) ] )\n\t\t\t\t\t\t\t->onlyMethods( [ 'get_experiments' ] )\n\t\t\t\t\t\t\t->getMock();\n\n\t\t$this->instance->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\n\t\t$output = get_echo(\n\t\t\t[ $this->instance, 'display_experiment_field' ],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'label'   => 'Foo Label',\n\t\t\t\t\t'id'      => 'foo',\n\t\t\t\t\t'default' => true,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->assertStringContainsString( \"checked='checked'\", $output );\n\t\t$this->assertStringContainsString( 'disabled', $output );\n\t}\n\n\t/**\n\t * @covers ::get_experiment_groups\n\t */\n\tpublic function test_get_experiment_groups(): void {\n\t\t$groups = $this->instance->get_experiment_groups();\n\t\t$this->assertCount( 3, $groups );\n\t}\n\n\t/**\n\t * @covers ::get_experiments\n\t */\n\tpublic function test_get_experiments(): void {\n\t\t$all_experiments       = $this->instance->get_experiments();\n\t\t$all_experiment_groups = array_keys( $this->instance->get_experiment_groups() );\n\n\t\t$experiment_names  = wp_list_pluck( $all_experiments, 'name' );\n\t\t$experiment_groups = wp_list_pluck( $all_experiments, 'group' );\n\n\t\tforeach ( $experiment_groups as $group ) {\n\t\t\t$this->assertContains( $group, $all_experiment_groups, \\sprintf( 'Invalid experiment group %s', $group ) );\n\t\t}\n\n\t\t$duplicates = array_unique( array_diff_assoc( $experiment_names, array_unique( $experiment_names ) ) );\n\n\t\t$this->assertEmpty( $duplicates, \\sprintf( 'Duplicate experiments definition: %s', implode( ',', $duplicates ) ) );\n\t}\n\n\t/**\n\t * @covers ::get_experiment_statuses\n\t */\n\tpublic function test_get_experiment_statuses(): void {\n\t\t$this->assertEmpty( $this->instance->get_experiment_statuses( 'foo-bar-baz' ) );\n\t\t$this->assertNotEmpty( $this->instance->get_experiment_statuses( 'dashboard' ) );\n\t\t$this->assertNotEmpty( $this->instance->get_experiment_statuses( 'editor' ) );\n\t}\n\n\t/**\n\t * @covers ::is_experiment_enabled\n\t */\n\tpublic function test_is_experiment_enabled(): void {\n\t\tupdate_option( Settings::SETTING_NAME_EXPERIMENTS, [ 'enableInProgressTemplateActions' => true ], false );\n\n\t\t$this->assertTrue( $this->instance->is_experiment_enabled( 'enableInProgressTemplateActions' ) );\n\t}\n\n\t/**\n\t * @covers ::is_experiment_enabled\n\t * @covers ::get_experiment\n\t */\n\tpublic function test_is_experiment_enabled_default_experiment(): void {\n\t\t$this->instance = $this->getMockBuilder( \\Google\\Web_Stories\\Experiments::class )\n\t\t\t\t\t\t\t->setConstructorArgs( [ $this->injector->make( Settings::class ) ] )\n\t\t\t\t\t\t\t->onlyMethods( [ 'get_experiments' ] )\n\t\t\t\t\t\t\t->getMock();\n\n\t\t$this->instance->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t\t'default'     => false,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'bar',\n\t\t\t\t\t\t\t\t'label'       => 'Bar Label',\n\t\t\t\t\t\t\t\t'description' => 'Bar Desc',\n\t\t\t\t\t\t\t\t'default'     => true,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\n\t\t$this->assertFalse( $this->instance->is_experiment_enabled( 'foo' ) );\n\t\t$this->assertTrue( $this->instance->is_experiment_enabled( 'bar' ) );\n\t}\n\n\t/**\n\t * @covers ::is_experiment_enabled\n\t * @covers ::get_experiment\n\t */\n\tpublic function test_is_experiment_enabled_unknown_experiment(): void {\n\t\t$this->assertFalse( $this->instance->is_experiment_enabled( 'baz' ) );\n\t}\n\n\t/**\n\t * @cover ::get_enabled_experiments\n\t */\n\tpublic function test_get_enabled_experiments(): void {\n\t\tupdate_option( Settings::SETTING_NAME_EXPERIMENTS, [ 'baz' => true ], false );\n\n\t\t$this->instance = $this->getMockBuilder( \\Google\\Web_Stories\\Experiments::class )\n\t\t\t\t\t\t\t->setConstructorArgs( [ $this->injector->make( Settings::class ) ] )\n\t\t\t\t\t\t\t->onlyMethods( [ 'get_experiments', 'is_experiment_enabled' ] )\n\t\t\t\t\t\t\t->getMock();\n\n\t\t$this->instance->method( 'get_experiments' )\n\t\t\t\t\t->willReturn(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'foo',\n\t\t\t\t\t\t\t\t'label'       => 'Foo Label',\n\t\t\t\t\t\t\t\t'description' => 'Foo Desc',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'bar',\n\t\t\t\t\t\t\t\t'label'       => 'Bar Label',\n\t\t\t\t\t\t\t\t'description' => 'Bar Desc',\n\t\t\t\t\t\t\t\t'default'     => true,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'name'        => 'baz',\n\t\t\t\t\t\t\t\t'label'       => 'Baz Label',\n\t\t\t\t\t\t\t\t'description' => 'Baz Desc',\n\t\t\t\t\t\t\t\t'default'     => true,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t$this->instance->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturnMap(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[ 'foo', false ],\n\t\t\t\t\t\t\t[ 'bar', true ],\n\t\t\t\t\t\t\t[ 'baz', true ],\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\n\t\t$expected = [\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t];\n\n\t\t$this->assertEqualSets( $expected, $this->instance->get_enabled_experiments() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Font_Post_Type.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Font_Post_Type\n */\nclass Font_Post_Type extends DependencyInjectedTestCase {\n\tuse Capabilities_Setup;\n\n\tprivate \\Google\\Web_Stories\\Font_Post_Type $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Font_Post_Type::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$post_type_object = get_post_type_object( \\Google\\Web_Stories\\Font_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\t\t$this->assertSame( 'edit_web-stories', $post_type_object->cap->read_post );\n\t\t$this->assertSame( 'manage_options', $post_type_object->cap->edit_posts );\n\t\t$this->assertSame( 'manage_options', $post_type_object->cap->delete_posts );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Infrastructure/InjectionChainTest.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Infrastructure;\n\nuse Google\\Web_Stories\\Infrastructure\\Injector\\InjectionChain;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound\n\nclass Something {}\n\nclass SomethingElse {}\n\nclass First {}\n\nclass Second {}\n\nclass Third {}\n\nfinal class InjectionChainTest extends TestCase {\n\tpublic function test_it_accepts_new_resolutions(): void {\n\t\t$chain = ( new InjectionChain() )\n\t\t\t->add_resolution( Something::class );\n\n\t\t$this->assertTrue( $chain->has_resolution( Something::class ) );\n\t\t$this->assertFalse( $chain->has_resolution( SomethingElse::class ) );\n\t}\n\n\tpublic function test_it_accepts_new_chain_entries(): void {\n\t\t$chain = ( new InjectionChain() )\n\t\t\t->add_to_chain( Something::class );\n\n\t\t$this->assertEquals( Something::class, $chain->get_class() );\n\t}\n\n\tpublic function test_it_returns_the_last_class_in_the_chain(): void {\n\t\t$chain = ( new InjectionChain() )\n\t\t\t->add_to_chain( First::class )\n\t\t\t->add_to_chain( Second::class )\n\t\t\t->add_to_chain( Third::class );\n\n\t\t$this->assertEquals( Third::class, $chain->get_class() );\n\t}\n\n\tpublic function test_it_retains_all_elements_in_the_chain(): void {\n\t\t$chain = ( new InjectionChain() )\n\t\t\t->add_to_chain( First::class )\n\t\t\t->add_to_chain( Second::class )\n\t\t\t->add_to_chain( Third::class );\n\n\t\t$this->assertEquals( [ Third::class, Second::class, First::class ], $chain->get_chain() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Infrastructure/LazilyInstantiatedServiceTest.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Infrastructure;\n\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer\\LazilyInstantiatedService;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse stdClass;\n\nfinal class LazilyInstantiatedServiceTest extends TestCase {\n\tpublic function test_it_throws_when_instantiating_an_invalid_service(): void {\n\t\t$callable     = static fn() => new stdClass();\n\t\t$lazy_service = new LazilyInstantiatedService( $callable );\n\n\t\t$this->expectException( InvalidService::class );\n\t\t$this->expectExceptionMessage( 'The service \"stdClass\" is not recognized and cannot be registered.' );\n\t\t$lazy_service->instantiate();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Infrastructure/ServiceBasedPluginTest.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Infrastructure;\n\nuse Google\\Web_Stories\\Infrastructure\\ServiceBasedPlugin;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer\\SimpleServiceContainer;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyService;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyServiceBasedPlugin;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyServiceWithDelay;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyServiceWithRequirements;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Infrastructure\\ServiceBasedPlugin\n */\nfinal class ServiceBasedPluginTest extends TestCase {\n\tpublic function test_it_can_be_registered(): void {\n\t\t$plugin = $this->getMockBuilder( ServiceBasedPlugin::class )\n\t\t\t->onlyMethods( [ 'register_services' ] )\n\t\t\t->getMock();\n\n\t\t$plugin->expects( $this->once() )->method( 'register_services' );\n\n\t\t$plugin->register();\n\t}\n\n\tpublic function test_it_always_registers_an_injector_by_default(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( ServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\t$this->assertCount( 0, $container );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 1, $container );\n\t\t$this->assertTrue( $container->has( 'injector' ) );\n\t}\n\n\tpublic function test_it_registers_default_services(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\t$this->assertCount( 0, $container );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 3, $container );\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\t}\n\n\tpublic function test_it_allows_services_to_be_filtered(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\tadd_filter(\n\t\t\t'services',\n\t\t\tstatic fn() => [ 'filtered_service' => DummyService::class ]\n\t\t);\n\n\t\t$this->assertFalse( $container->has( 'filtered_service' ) );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 2, $container );\n\t\t$this->assertTrue( $container->has( 'filtered_service' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'filtered_service' ) );\n\t\t$this->assertfalse( $container->has( 'service_a' ) );\n\t\t$this->assertfalse( $container->has( 'service_b' ) );\n\t}\n\n\tpublic function test_it_provides_default_services_for_filtering(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\tadd_filter(\n\t\t\t'services',\n\t\t\tstatic fn( $services ) => array_merge(\n\t\t\t\t$services,\n\t\t\t\t[ 'filtered_service' => DummyService::class ]\n\t\t\t)\n\t\t);\n\n\t\t$this->assertFalse( $container->has( 'filtered_service' ) );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 4, $container );\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\t\t$this->assertTrue( $container->has( 'filtered_service' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'filtered_service' ) );\n\t}\n\n\tpublic function test_it_registers_service_with_requirements(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t\t\t\t->enableOriginalConstructor()\n\t\t\t\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t\t\t\t->onlyMethods( [] )\n\t\t\t\t\t\t->getMock();\n\n\t\t$service_callback = static fn( $services ) => array_merge(\n\t\t\t$services,\n\t\t\t[ 'service_with_requirements' => DummyServiceWithRequirements::class ]\n\t\t);\n\n\t\tadd_filter( 'services', $service_callback );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 4, $container );\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\t\t$this->assertTrue( $container->has( 'service_with_requirements' ) );\n\t\t$this->assertInstanceof( DummyServiceWithRequirements::class, $container->get( 'service_with_requirements' ) );\n\t}\n\n\tpublic function test_it_handles_delays_for_requirements(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t\t\t\t->enableOriginalConstructor()\n\t\t\t\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t\t\t\t->onlyMethods( [] )\n\t\t\t\t\t\t->getMock();\n\n\t\t$service_callback = static fn( $services ) => array_merge(\n\t\t\t$services,\n\t\t\t[\n\t\t\t\t'service_a'                 => DummyServiceWithDelay::class,\n\t\t\t\t'service_with_requirements' => DummyServiceWithRequirements::class,\n\t\t\t]\n\t\t);\n\n\t\tadd_filter( 'services', $service_callback );\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 2, $container );\n\t\t$this->assertFalse( $container->has( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertFalse( $container->has( 'service_with_requirements' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\n\t\tdo_action( 'some_action' );\n\n\t\t$this->assertCount( 4, $container );\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertInstanceof( DummyServiceWithDelay::class, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\t\t$this->assertTrue( $container->has( 'service_with_requirements' ) );\n\t\t$this->assertInstanceof( DummyServiceWithRequirements::class, $container->get( 'service_with_requirements' ) );\n\t}\n\n\tpublic function test_it_throws_an_exception_if_unrecognized_service_is_required(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t\t\t\t->enableOriginalConstructor()\n\t\t\t\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t\t\t\t->onlyMethods( [] )\n\t\t\t\t\t\t->getMock();\n\n\t\t$service_callback = static fn() => [ 'service_with_requirements' => DummyServiceWithRequirements::class ];\n\n\t\tadd_filter( 'services', $service_callback );\n\n\t\t$this->expectExceptionMessage( 'The service ID \"service_a\" is not recognized and cannot be retrieved.' );\n\t\t$plugin->register();\n\t}\n\n\tpublic function test_it_generates_identifiers_as_needed(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( ServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\tadd_filter(\n\t\t\t'services',\n\t\t\tstatic fn() => [ DummyService::class ]\n\t\t);\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 2, $container );\n\t\t$this->assertTrue( $container->has( 'dummy_service' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'dummy_service' ) );\n\t}\n\n\tpublic function test_it_skips_unknown_service_classes(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( ServiceBasedPlugin::class )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->setConstructorArgs( [ true, null, $container ] )\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\tadd_filter(\n\t\t\t'services',\n\t\t\tstatic fn() => [\n\t\t\t\t'unknown_class' => 'UnknownClass',\n\t\t\t]\n\t\t);\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 1, $container );\n\t\t$this->assertFalse( $container->has( 'dummy_service' ) );\n\t}\n\n\tpublic function test_it_can_have_filtering_disabled(): void {\n\t\t$container = new SimpleServiceContainer();\n\t\t$plugin    = $this->getMockBuilder( DummyServiceBasedPlugin::class )\n\t\t\t->setConstructorArgs( [ false, null, $container ] )\n\t\t\t->enableOriginalConstructor()\n\t\t\t->onlyMethods( [] )\n\t\t\t->getMock();\n\n\t\tadd_filter(\n\t\t\t'services',\n\t\t\tstatic fn() => [ 'filtered_service' => DummyService::class ]\n\t\t);\n\n\t\t$plugin->register();\n\n\t\t$this->assertCount( 3, $container );\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertInstanceof( DummyService::class, $container->get( 'service_b' ) );\n\t\t$this->assertFalse( $container->has( 'filtered_service' ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Infrastructure/SimpleInjectorTest.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Infrastructure;\n\nuse Google\\Web_Stories\\Exception\\FailedToMakeInstance;\nuse Google\\Web_Stories\\Infrastructure\\Injector\\SimpleInjector;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse stdClass;\n\nfinal class SimpleInjectorTest extends TestCase {\n\tpublic function test_it_can_instantiate_a_concrete_class(): void {\n\t\t$object = ( new SimpleInjector() )\n\t\t\t->make( Fixture\\DummyClass::class );\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClass::class, $object );\n\t}\n\n\tpublic function test_it_can_autowire_a_class_with_a_dependency(): void {\n\t\t$object = ( new SimpleInjector() )\n\t\t\t->make( Fixture\\DummyClassWithDependency::class );\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClassWithDependency::class, $object );\n\t}\n\n\tpublic function test_it_can_instantiate_a_bound_interface(): void {\n\t\t$injector = ( new SimpleInjector() )\n\t\t\t->bind(\n\t\t\t\tFixture\\DummyInterface::class,\n\t\t\t\tFixture\\DummyClassWithDependency::class\n\t\t\t);\n\t\t$object   = $injector->make( Fixture\\DummyInterface::class );\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClassWithDependency::class, $object );\n\t}\n\n\tpublic function test_it_returns_separate_instances_by_default(): void {\n\t\t$injector = new SimpleInjector();\n\t\t$object_a = $injector->make( Fixture\\DummyClass::class );\n\t\t$object_b = $injector->make( Fixture\\DummyClass::class );\n\n\t\t$this->assertNotSame( $object_a, $object_b );\n\t}\n\n\tpublic function test_it_returns_same_instances_if_shared(): void {\n\t\t$injector = ( new SimpleInjector() )\n\t\t\t->share( Fixture\\DummyClass::class );\n\t\t$object_a = $injector->make( Fixture\\DummyClass::class );\n\t\t$object_b = $injector->make( Fixture\\DummyClass::class );\n\n\t\t$this->assertSame( $object_a, $object_b );\n\t}\n\n\tpublic function test_it_can_instantiate_a_class_with_named_arguments(): void {\n\t\t$object = ( new SimpleInjector() )\n\t\t\t->make(\n\t\t\t\tFixture\\DummyClassWithNamedArguments::class,\n\t\t\t\t[\n\t\t\t\t\t'argument_a' => 42,\n\t\t\t\t\t'argument_b' => 'Mr Alderson',\n\t\t\t\t]\n\t\t\t);\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClassWithNamedArguments::class, $object );\n\t\t$this->assertEquals( 42, $object->get_argument_a() );\n\t\t$this->assertEquals( 'Mr Alderson', $object->get_argument_b() );\n\t}\n\n\tpublic function test_it_allows_for_skipping_named_arguments_with_default_values(): void {\n\t\t$object = ( new SimpleInjector() )\n\t\t\t->make(\n\t\t\t\tFixture\\DummyClassWithNamedArguments::class,\n\t\t\t\t[ 'argument_a' => 42 ]\n\t\t\t);\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClassWithNamedArguments::class, $object );\n\t\t$this->assertEquals( 42, $object->get_argument_a() );\n\t\t$this->assertEquals( 'Mr Meeseeks', $object->get_argument_b() );\n\t}\n\n\tpublic function test_it_throws_if_a_required_named_arguments_is_missing(): void {\n\t\t$this->expectException( FailedToMakeInstance::class );\n\n\t\t( new SimpleInjector() )\n\t\t\t->make( Fixture\\DummyClassWithNamedArguments::class );\n\t}\n\n\tpublic function test_it_throws_if_a_circular_reference_is_detected(): void {\n\t\t$this->expectException( FailedToMakeInstance::class );\n\t\t$this->expectExceptionCode( FailedToMakeInstance::CIRCULAR_REFERENCE );\n\n\t\t( new SimpleInjector() )\n\t\t\t->bind(\n\t\t\t\tFixture\\DummyClass::class,\n\t\t\t\tFixture\\DummyClassWithDependency::class\n\t\t\t)\n\t\t\t->make( Fixture\\DummyClassWithDependency::class );\n\t}\n\n\tpublic function test_it_can_delegate_instantiation(): void {\n\t\t$injector = ( new SimpleInjector() )\n\t\t\t->delegate(\n\t\t\t\tFixture\\DummyInterface::class,\n\t\t\t\tstatic function ( $class_name ) {\n\t\t\t\t\t$object             = new stdClass();\n\t\t\t\t\t$object->class_name = $class_name;\n\t\t\t\t\treturn $object;\n\t\t\t\t}\n\t\t\t);\n\t\t$object   = $injector->make( Fixture\\DummyInterface::class );\n\n\t\t$this->assertInstanceOf( stdClass::class, $object );\n\t\t$this->assertTrue( property_exists( $object, 'class_name' ) );\n\t\t$this->assertEquals( Fixture\\DummyInterface::class, $object->class_name );\n\t}\n\n\tpublic function test_delegation_works_across_resolution(): void {\n\t\t$injector = ( new SimpleInjector() )\n\t\t\t->bind(\n\t\t\t\tFixture\\DummyInterface::class,\n\t\t\t\tFixture\\DummyClassWithDependency::class\n\t\t\t)\n\t\t\t->delegate(\n\t\t\t\tFixture\\DummyClassWithDependency::class,\n\t\t\t\tstatic function ( $class_name ) {\n\t\t\t\t\t$object             = new stdClass();\n\t\t\t\t\t$object->class_name = $class_name;\n\t\t\t\t\treturn $object;\n\t\t\t\t}\n\t\t\t);\n\t\t$object   = $injector->make( Fixture\\DummyInterface::class );\n\n\t\t$this->assertInstanceOf( stdClass::class, $object );\n\t\t$this->assertTrue( property_exists( $object, 'class_name' ) );\n\t\t$this->assertEquals( Fixture\\DummyClassWithDependency::class, $object->class_name );\n\t}\n\n\tpublic function test_arguments_can_be_bound(): void {\n\t\t$object = ( new SimpleInjector() )\n\t\t\t->bind_argument(\n\t\t\t\tFixture\\DummyClassWithNamedArguments::class,\n\t\t\t\t'argument_a',\n\t\t\t\t42\n\t\t\t)\n\t\t\t->make( Fixture\\DummyClassWithNamedArguments::class );\n\n\t\t$this->assertEquals( 42, $object->get_argument_a() );\n\t}\n\n\tpublic function test_callable_arguments_are_lazily_resolved(): void {\n\t\t$injector = new SimpleInjector();\n\t\t$injector->bind_argument(\n\t\t\tFixture\\DummyClassWithNamedArguments::class,\n\t\t\t'argument_a',\n\t\t\tstatic fn( $class_name, $parameter, $arguments ) => $arguments['number']\n\t\t);\n\n\t\t$object = $injector->make( Fixture\\DummyClassWithNamedArguments::class, [ 'number' => 123 ] );\n\n\t\t$this->assertInstanceOf( Fixture\\DummyClassWithNamedArguments::class, $object );\n\t\t$this->assertEquals( 123, $object->get_argument_a() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Infrastructure/SimpleServiceContainerTest.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Infrastructure;\n\nuse Google\\Web_Stories\\Exception\\InvalidService;\nuse Google\\Web_Stories\\Infrastructure\\Service;\nuse Google\\Web_Stories\\Infrastructure\\ServiceContainer\\SimpleServiceContainer;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\nfinal class SimpleServiceContainerTest extends TestCase {\n\tpublic function test_it_can_check_for_service_existence(): void {\n\t\t$service   = $this->createMock( Service::class );\n\t\t$container = new SimpleServiceContainer( [ 'known_service' => $service ] );\n\n\t\t$this->assertTrue( $container->has( 'known_service' ) );\n\t\t$this->assertFalse( $container->has( 'unknown_service' ) );\n\t}\n\n\tpublic function test_it_can_return_services(): void {\n\t\t$service   = $this->createMock( Service::class );\n\t\t$container = new SimpleServiceContainer( [ 'some_service' => $service ] );\n\n\t\t$this->assertSame( $service, $container->get( 'some_service' ) );\n\t}\n\n\tpublic function test_it_can_accept_new_services(): void {\n\t\t$service   = $this->createMock( Service::class );\n\t\t$container = new SimpleServiceContainer( [ 'service_a' => $service ] );\n\n\t\t$container->put( 'service_b', $service );\n\n\t\t$this->assertTrue( $container->has( 'service_a' ) );\n\t\t$this->assertSame( $service, $container->get( 'service_a' ) );\n\t\t$this->assertTrue( $container->has( 'service_b' ) );\n\t\t$this->assertSame( $service, $container->get( 'service_b' ) );\n\t}\n\n\tpublic function test_it_throws_when_retrieving_an_unknown_service(): void {\n\t\t$container = new SimpleServiceContainer();\n\n\t\t$this->expectException( InvalidService::class );\n\t\t$this->expectExceptionMessage( 'The service ID \"unknown_service\" is not recognized and cannot be retrieved.' );\n\t\t$container->get( 'unknown_service' );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/AMP.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse DOMDocument;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\AMP\n */\nclass AMP extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Integrations\\AMP $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Integrations\\AMP::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'option_amp-options', [ $this->instance, 'filter_amp_options' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'amp_supportable_post_types', [ $this->instance, 'filter_supportable_post_types' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'amp_to_amp_linking_element_excluded', [ $this->instance, 'filter_amp_to_amp_linking_element_excluded' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'amp_validation_error_sanitized', [ $this->instance, 'filter_amp_validation_error_sanitized' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'web_stories_amp_validation_error_sanitized', [ $this->instance, 'filter_amp_validation_error_sanitized' ] ) );\n\n\t\tremove_all_filters( 'option_amp-options' );\n\t\tremove_all_filters( 'amp_supportable_post_types' );\n\t\tremove_all_filters( 'amp_to_amp_linking_element_excluded' );\n\t\tremove_all_filters( 'amp_validation_error_sanitized' );\n\t\tremove_all_filters( 'web_stories_amp_validation_error_sanitized' );\n\t}\n\n\t/**\n\t * @covers ::filter_amp_options\n\t */\n\tpublic function test_filter_amp_options_if_not_requested_post_type(): void {\n\t\t$this->assertEqualSets( [], $this->instance->filter_amp_options( [] ) );\n\t}\n\n\t/**\n\t * @covers ::filter_amp_options\n\t */\n\tpublic function test_filter_amp_options(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$before = [\n\t\t\t'theme_support'        => 'reader',\n\t\t\t'supported_post_types' => [ 'post' ],\n\t\t\t'supported_templates'  => [ 'is_page' ],\n\t\t];\n\n\t\t$expected = [\n\t\t\t'theme_support'        => 'standard',\n\t\t\t'supported_post_types' => [ 'post', Story_Post_Type::POST_TYPE_SLUG ],\n\t\t\t'supported_templates'  => [ 'is_page', 'is_singular' ],\n\t\t];\n\n\t\t$actual = $this->instance->filter_amp_options( $before );\n\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_supportable_post_types\n\t */\n\tpublic function test_filter_supportable_post_types_if_not_requested_post_type(): void {\n\n\t\t$this->assertEqualSets( [], $this->instance->filter_supportable_post_types( [ Story_Post_Type::POST_TYPE_SLUG ] ) );\n\t}\n\n\t/**\n\t * @covers ::filter_supportable_post_types\n\t */\n\tpublic function test_filter_supportable_post_types(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$actual = $this->instance->filter_supportable_post_types( [] );\n\n\t\t$this->assertEqualSets( [ Story_Post_Type::POST_TYPE_SLUG ], $actual );\n\t}\n\n\t/**\n\t * @return array<string, array{0: array<int, mixed>, 1: bool}>\n\t */\n\tpublic static function data_test_filter_amp_to_amp_linking_element_excluded(): array {\n\t\t$doc = new DOMDocument( '1.0', 'utf-8' );\n\n\t\t$anchor        = $doc->createElement( 'a' );\n\t\t$player_anchor = $doc->createElement( 'a' );\n\t\t$div_anchor    = $doc->createElement( 'a' );\n\t\t$player        = $doc->createElement( 'amp-story-player' );\n\t\t$div           = $doc->createElement( 'div' );\n\t\t$player->appendChild( $player_anchor );\n\t\t$div->appendChild( $div_anchor );\n\n\t\t$doc->appendChild( $player );\n\t\t$doc->appendChild( $div );\n\n\t\treturn [\n\t\t\t'No instance of DOMElement' => [\n\t\t\t\t[ false, '', [], null ],\n\t\t\t\tfalse,\n\t\t\t],\n\t\t\t'No parent node'            => [\n\t\t\t\t[ false, '', [], $anchor ],\n\t\t\t\tfalse,\n\t\t\t],\n\t\t\t'Wrong parent node'         => [\n\t\t\t\t[ false, '', [], $div_anchor ],\n\t\t\t\tfalse,\n\t\t\t],\n\t\t\t'Correct node'              => [\n\t\t\t\t[ false, '', [], $player_anchor ],\n\t\t\t\ttrue,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @param array<mixed> $args\n\t *\n\t * @covers ::filter_amp_to_amp_linking_element_excluded\n\t * @dataProvider data_test_filter_amp_to_amp_linking_element_excluded\n\t */\n\tpublic function test_filter_amp_to_amp_linking_element_excluded( array $args, bool $expected ): void {\n\t\t$actual = $this->instance->filter_amp_to_amp_linking_element_excluded( ...$args );\n\t\t$this->assertSame( $actual, $expected );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/Conditional_Featured_Image.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\Conditional_Featured_Image\n */\nclass Conditional_Featured_Image extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Integrations\\Conditional_Featured_Image $instance;\n\n\t/**\n\t * Runs prior to each test and sets up the testee object.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Integrations\\Conditional_Featured_Image::class );\n\t}\n\n\t/**\n\t * Tests register with core theme.\n\t *\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertEquals(\n\t\t\t99,\n\t\t\thas_filter(\n\t\t\t\t'cybocfi_enabled_for_post_type',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'cybocfi_enabled_for_post_type',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::cybocfi_enabled_for_post_type\n\t */\n\tpublic function test_cybocfi_enabled_for_post_type(): void {\n\t\t$result = $this->instance->cybocfi_enabled_for_post_type( true, Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->assertFalse( $result );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/Core_Themes_Support.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Admin\\Customizer;\nuse Google\\Web_Stories\\Integrations\\Core_Themes_Support as Testee;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\Core_Themes_Support\n */\nclass Core_Themes_Support extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected Testee $instance;\n\n\t/**\n\t * Current template.\n\t */\n\tprotected string $stylesheet;\n\n\t/**\n\t * Runs prior to each test and sets up the testee object.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->stylesheet = get_stylesheet();\n\n\t\t// Set stylesheet from one of the supported themes.\n\t\tupdate_option( 'stylesheet', 'twentytwentyone' );\n\t\tupdate_option( Customizer::STORY_OPTION, [ 'show_stories' => true ] );\n\n\t\t$this->instance = $this->injector->make( Testee::class );\n\t}\n\n\t/**\n\t * Runs after each test and resets the actions.\n\t */\n\tpublic function tear_down(): void {\n\t\tremove_action( 'wp_body_open', [ $this->instance, 'embed_web_stories' ] );\n\n\t\tremove_theme_support( 'web-stories' );\n\n\t\tdelete_option( Customizer::STORY_OPTION );\n\t\tupdate_option( 'stylesheet', $this->stylesheet );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Tests register with core theme.\n\t *\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertEquals( 10, has_filter( 'body_class', [ $this->instance, 'add_core_theme_classes' ] ) );\n\t\t$this->assertEquals( 10, has_action( 'wp_body_open', [ $this->instance, 'embed_web_stories' ] ) );\n\t}\n\n\t/**\n\t * Tests register with non-core theme.\n\t *\n\t * @covers ::register\n\t */\n\tpublic function test_register_non_core_theme(): void {\n\t\tupdate_option( 'stylesheet', '' );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertFalse( has_action( 'wp_body_open', [ $this->instance, 'embed_web_stories' ] ) );\n\t}\n\n\tpublic function test_get_supported_themes(): void {\n\n\t\t$expected = [\n\t\t\t'twentytwentyone',\n\t\t\t'twentytwenty',\n\t\t\t'twentynineteen',\n\t\t\t'twentyseventeen',\n\t\t\t'twentysixteen',\n\t\t\t'twentyfifteen',\n\t\t\t'twentyfourteen',\n\t\t\t'twentythirteen',\n\t\t\t'twentytwelve',\n\t\t\t'twentyeleven',\n\t\t\t'twentyten',\n\t\t];\n\n\t\t$actual = $this->get_static_private_property( Testee::class, 'supported_themes' );\n\n\t\t$this->assertIsArray( $actual );\n\t\t$this->assertEqualSets( $actual, $expected );\n\t}\n\n\t/**\n\t * Tests whether the support is added with core theme.\n\t *\n\t * @covers ::extend_theme_support\n\t */\n\tpublic function test_extend_theme_support(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertTrue( get_theme_support( 'web-stories' ) );\n\t}\n\n\t/**\n\t * Tests whether the support is added with non-core theme.\n\t *\n\t * @covers ::extend_theme_support\n\t */\n\tpublic function test_extend_theme_support_non_core_themes(): void {\n\t\tupdate_option( 'stylesheet', '' );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertFalse( get_theme_support( 'web-stories' ) );\n\t}\n\n\t/**\n\t * @covers ::embed_web_stories\n\t */\n\tpublic function embed_web_stories(): void {\n\t\tob_start();\n\t\t$this->instance->embed_web_stories();\n\n\t\t$actual = ob_get_clean();\n\n\t\t$this->assertTrue( wp_script_is( 'web-stories-theme-style-twentytwentyone' ) );\n\t\t$this->assertIsString( $actual );\n\t\t$this->assertStringContainsString( 'web-stories-theme-header-section', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/Jetpack.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Integrations\\Jetpack as Jetpack_Integration;\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Term;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\Jetpack\n */\nclass Jetpack extends DependencyInjectedTestCase {\n\tpublic const ATTACHMENT_URL = 'https://www.example.com/test.mp4';\n\tpublic const MP4_FILE       = 'video.mp4';\n\tpublic const POSTER_URL     = 'https://www.example.com/test.mp4';\n\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Integrations\\Jetpack $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Integrations\\Jetpack::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertFalse( has_filter( 'wpcom_sitemap_post_types', [ $this->instance, 'add_to_jetpack_sitemap' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'jetpack_sitemap_post_types', [ $this->instance, 'add_to_jetpack_sitemap' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'jetpack_is_amp_request', [ $this->instance, 'force_amp_request' ] ) );\n\n\t\tremove_all_filters( 'jetpack_sitemap_post_types' );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_register_is_wpcom(): void {\n\t\t\\define( 'IS_WPCOM', true );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'wpcom_sitemap_post_types', [ $this->instance, 'add_to_jetpack_sitemap' ] ) );\n\t\t$this->assertFalse( has_filter( 'jetpack_sitemap_post_types', [ $this->instance, 'add_to_jetpack_sitemap' ] ) );\n\n\t\tremove_all_filters( 'wpcom_sitemap_post_types' );\n\t}\n\n\t/**\n\t * @covers ::add_to_jetpack_sitemap\n\t */\n\tpublic function test_add_to_jetpack_sitemap(): void {\n\t\t$this->assertEqualSets( [ Story_Post_Type::POST_TYPE_SLUG ], $this->instance->add_to_jetpack_sitemap( [] ) );\n\t}\n\n\t/**\n\t * @covers ::filter_rest_api_response\n\t */\n\tpublic function test_filter_rest_api_response(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => Jetpack_Integration::VIDEOPRESS_MIME_TYPE,\n\t\t\t\t'post_title'     => __METHOD__,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$post = get_post( $video_attachment_id );\n\t\t$this->assertNotNull( $post );\n\n\t\t$data = [\n\t\t\t'source_url'         => self::ATTACHMENT_URL,\n\t\t\t'featured_media_src' => [],\n\t\t\t'media_details'      => [],\n\t\t];\n\n\t\t$response = rest_ensure_response( $data );\n\t\t$this->assertNotWPError( $response );\n\n\t\tadd_filter( 'get_post_metadata', [ $this, 'filter_wp_get_attachment_metadata' ], 10, 3 );\n\n\t\t$results = $this->instance->filter_rest_api_response( $response, $post );\n\n\t\tremove_filter( 'get_post_metadata', [ $this, 'filter_wp_get_attachment_metadata' ] );\n\n\t\t$data = $results->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'mime_type', $data );\n\t\t$this->assertSame( 'video/mp4', $data['mime_type'] );\n\n\t\t$this->assertArrayHasKey( $this->container->get( 'media.media_source' )::MEDIA_SOURCE_KEY, $data );\n\t\t$this->assertSame( 'video-optimization', $data[ $this->container->get( 'media.media_source' )::MEDIA_SOURCE_KEY ] );\n\n\t\t$this->assertArrayHasKey( 'source_url', $data );\n\t\t$this->assertSame( 'https://videopress.example.com/videos/video.mp4', $data['source_url'] );\n\n\t\t$this->assertArrayHasKey( 'media_details', $data );\n\t\t$this->assertArrayHasKey( 'length_formatted', $data['media_details'] );\n\t\t$this->assertArrayHasKey( 'length', $data['media_details'] );\n\t\t$this->assertSame( '0:05', $data['media_details']['length_formatted'] );\n\t\t$this->assertSame( 5, $data['media_details']['length'] );\n\t}\n\n\t/**\n\t * @covers ::add_term\n\t */\n\tpublic function test_add_term(): void {\n\t\t$this->instance->register();\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\t$this->instance->register();\n\n\t\tadd_post_meta( $poster_attachment_id, Jetpack_Integration::VIDEOPRESS_POSTER_META_KEY, 'hello world' );\n\n\t\t/**\n\t\t * @var WP_Term[] $terms\n\t\t */\n\t\t$terms = wp_get_post_terms( $poster_attachment_id, $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertCount( 1, $terms );\n\t\t$this->assertEqualSets( [ 'poster-generation' ], $slugs );\n\t}\n\n\t/**\n\t * @covers ::filter_admin_ajax_response\n\t */\n\tpublic function test_filter_admin_ajax_response(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => Jetpack_Integration::VIDEOPRESS_MIME_TYPE,\n\t\t\t\t'post_title'     => __METHOD__,\n\t\t\t]\n\t\t);\n\n\t\tadd_filter( 'get_post_metadata', [ $this, 'filter_wp_get_attachment_metadata' ], 10, 3 );\n\t\t$this->assertNotWPError( $video_attachment_id );\n\t\t$attachment = get_post( $video_attachment_id );\n\n\t\t$this->assertNotNull( $attachment );\n\n\t\t$response = wp_prepare_attachment_for_js( $attachment );\n\t\t$this->assertIsArray( $response );\n\t\t$data = $this->instance->filter_admin_ajax_response( $response, $attachment );\n\n\t\tremove_filter( 'get_post_metadata', [ $this, 'filter_wp_get_attachment_metadata' ] );\n\n\t\t$this->assertArrayHasKey( 'mime', $data );\n\t\t$this->assertSame( 'video/mp4', $data['mime'] );\n\n\t\t$this->assertArrayHasKey( 'subtype', $data );\n\t\t$this->assertSame( 'mp4', $data['subtype'] );\n\n\t\t$this->assertArrayHasKey( $this->container->get( 'media.media_source' )::MEDIA_SOURCE_KEY, $data );\n\t\t$this->assertSame( 'video-optimization', $data[ $this->container->get( 'media.media_source' )::MEDIA_SOURCE_KEY ] );\n\n\t\t$this->assertArrayHasKey( 'url', $data );\n\t\t$this->assertSame( 'https://videopress.example.com/videos/video.mp4', $data['url'] );\n\n\t\t$this->assertArrayHasKey( 'media_details', $data );\n\t\t$this->assertIsArray( $data['media_details'] );\n\t\t$this->assertArrayHasKey( 'length_formatted', $data['media_details'] );\n\t\t$this->assertArrayHasKey( 'length', $data['media_details'] );\n\t\t$this->assertSame( '0:05', $data['media_details']['length_formatted'] );\n\t\t$this->assertSame( 5, $data['media_details']['length'] );\n\t}\n\n\t/**\n\t * @covers ::filter_ajax_query_attachments_args\n\t */\n\tpublic function test_filter_ajax_query_attachments_args(): void {\n\t\t$types                = $this->injector->make( Types::class );\n\t\t$allowed_mime_types   = $types->get_allowed_mime_types();\n\t\t$allowed_mime_types   = array_merge( ...array_values( $allowed_mime_types ) );\n\t\t$allowed_mime_types[] = $this->instance::VIDEOPRESS_MIME_TYPE;\n\t\t$args                 = [ 'post_mime_type' => $allowed_mime_types ];\n\t\t$this->instance->filter_ajax_query_attachments_args( $args );\n\t\t$this->assertSame(\n\t\t\t15,\n\t\t\thas_filter(\n\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'filter_admin_ajax_response',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @param int|float $milliseconds\n\t *\n\t * @dataProvider data_format_milliseconds\n\t * @covers ::format_milliseconds\n\t */\n\tpublic function test_format_milliseconds( $milliseconds, string $content ): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'format_milliseconds' ], [ $milliseconds ] );\n\t\t$this->assertSame( $result, $content );\n\t}\n\n\t/**\n\t * @param mixed $value\n\t * @return \\array[][]|mixed\n\t */\n\tpublic function filter_wp_get_attachment_metadata( $value, int $object_id, string $meta_key ) {\n\t\tif ( '_wp_attachment_metadata' !== $meta_key ) {\n\t\t\treturn $value;\n\t\t}\n\n\t\treturn [\n\t\t\t[\n\t\t\t\t'videopress' => [\n\t\t\t\t\t'duration'      => 5000,\n\t\t\t\t\t'finished'      => false,\n\t\t\t\t\t'original'      => self::ATTACHMENT_URL,\n\t\t\t\t\t'width'         => 720,\n\t\t\t\t\t'height'        => 1080,\n\t\t\t\t\t'poster'        => self::POSTER_URL,\n\t\t\t\t\t'file_url_base' => [\n\t\t\t\t\t\t'https' => 'https://videopress.example.com/videos/',\n\t\t\t\t\t],\n\t\t\t\t\t'files'         => [\n\t\t\t\t\t\t'hd' => [\n\t\t\t\t\t\t\t'mp4' => self::MP4_FILE,\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @return array<int|string, array<int|float|string>>\n\t */\n\tpublic static function data_format_milliseconds(): array {\n\t\treturn [\n\t\t\t'5000'     => [\n\t\t\t\t5000,\n\t\t\t\t'0:05',\n\t\t\t],\n\t\t\t'15123'    => [\n\t\t\t\t15123,\n\t\t\t\t'0:15',\n\t\t\t],\n\t\t\t'15999'    => [\n\t\t\t\t15123,\n\t\t\t\t'0:15',\n\t\t\t],\n\t\t\t'0'        => [\n\t\t\t\t0,\n\t\t\t\t'0:00',\n\t\t\t],\n\t\t\t'-1'       => [\n\t\t\t\t- 1,\n\t\t\t\t'0:00',\n\t\t\t],\n\t\t\t'-5000'    => [\n\t\t\t\t- 5000,\n\t\t\t\t'0:00',\n\t\t\t],\n\t\t\t'30526'    => [\n\t\t\t\t30526,\n\t\t\t\t'0:30',\n\t\t\t],\n\t\t\t'13123'    => [\n\t\t\t\t13123,\n\t\t\t\t'0:13',\n\t\t\t],\n\t\t\t'3600000'  => [\n\t\t\t\t3600_000,\n\t\t\t\t'60:00',\n\t\t\t],\n\t\t\t'98765431' => [\n\t\t\t\t98_765_431,\n\t\t\t\t'1646:05',\n\t\t\t],\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/New_Relic.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Integrations\\New_Relic as New_Relic_Integration;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\New_Relic\n */\nclass New_Relic extends TestCase {\n\t/**\n\t * @covers ::is_needed\n\t */\n\tpublic function test_is_needed(): void {\n\t\t$this->assertSame( \\function_exists( '\\newrelic_disable_autorum' ), New_Relic_Integration::is_needed() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/NextGen_Gallery.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\NextGen_Gallery\n */\nclass NextGen_Gallery extends TestCase {\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$nextgen_gallery = new \\Google\\Web_Stories\\Integrations\\NextGen_Gallery();\n\t\t$nextgen_gallery->register();\n\n\t\t$this->assertSame( PHP_INT_MAX, has_filter( 'run_ngg_resource_manager', [ $nextgen_gallery, 'filter_run_ngg_resource_manager' ] ) );\n\t}\n\n\t/**\n\t * @covers ::filter_run_ngg_resource_manager\n\t */\n\tpublic function test_filter_run_ngg_resource_manager(): void {\n\t\t$nextgen_gallery = new \\Google\\Web_Stories\\Integrations\\NextGen_Gallery();\n\n\t\t$before = $nextgen_gallery->filter_run_ngg_resource_manager( true );\n\n\t\t$_GET[ Story_Post_Type::POST_TYPE_SLUG ] = 123;\n\n\t\t$after = $nextgen_gallery->filter_run_ngg_resource_manager( true );\n\n\t\t$this->assertTrue( $before );\n\t\t$this->assertFalse( $after );\n\t}\n\n\t/**\n\t * @covers ::filter_run_ngg_resource_manager\n\t */\n\tpublic function test_filter_run_ngg_resource_manager_pretty_permalinks(): void {\n\t\t$nextgen_gallery = new \\Google\\Web_Stories\\Integrations\\NextGen_Gallery();\n\n\t\t$before = $nextgen_gallery->filter_run_ngg_resource_manager( true );\n\n\t\t$_SERVER['REQUEST_URI'] = '/' . Story_Post_Type::REWRITE_SLUG . '/foo-bar/';\n\n\t\t$after = $nextgen_gallery->filter_run_ngg_resource_manager( true );\n\n\t\t$this->assertTrue( $before );\n\t\t$this->assertFalse( $after );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/ShortPixel.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\ShortPixel\n */\nclass ShortPixel extends DependencyInjectedTestCase {\n\n\tprivate \\Google\\Web_Stories\\Integrations\\ShortPixel $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Integrations\\ShortPixel::class );\n\t}\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\t\t$this->assertSame( 10, has_filter( 'shortpixel_image_urls', [ $this->instance, 'image_urls' ] ) );\n\t}\n\n\t/**\n\t * @covers ::image_urls\n\t */\n\tpublic function test_image_urls(): void {\n\t\t$urls   = [\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/example.jpg',\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/web-stories-page-template-768.jpg',\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/example-01.jpg',\n\t\t];\n\t\t$result = $this->instance->image_urls( $urls );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/example.jpg',\n\t\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/example-01.jpg',\n\t\t\t],\n\t\t\t$result\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::image_urls\n\t */\n\tpublic function test_image_urls_only_web_stories_urls(): void {\n\t\t$urls   = [\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/web-stories-page-template-768.jpg',\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/web-stories-page-template-769.jpg',\n\t\t\t'http://localhost:8899/wp-content/uploads/2022/03/web-stories-page-template-770.jpg',\n\t\t];\n\t\t$result = $this->instance->image_urls( $urls );\n\t\t$this->assertSame( [], $result );\n\t}\n\n\t/**\n\t * @covers ::image_urls\n\t */\n\tpublic function test_image_urls_empty(): void {\n\t\t$urls   = [];\n\t\t$result = $this->instance->image_urls( $urls );\n\t\t$this->assertSame( [], $result );\n\t}\n\n\t/**\n\t * @covers ::image_urls\n\t */\n\tpublic function test_image_urls_non_page_template_image(): void {\n\t\t/* given a non \"page-template\" image the urls should pass thru */\n\t\t$urls   = [ 'http://localhost:8899/wp-content/uploads/2022/03/example-750.jpg' ];\n\t\t$result = $this->instance->image_urls( $urls );\n\t\t$this->assertEqualSets( $urls, $result );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Integrations/Site_Kit.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Integrations;\n\nuse Google\\Web_Stories\\Analytics;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Integrations\\Plugin_Status;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Integrations\\Site_Kit\n */\nclass Site_Kit extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Integrations\\Site_Kit $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Integrations\\Site_Kit::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$analytics = $this->container->get( 'analytics' );\n\t\tadd_action( 'web_stories_print_analytics', [ $analytics, 'print_analytics_tag' ] );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'googlesitekit_amp_gtag_opt', [ $this->instance, 'filter_site_kit_gtag_opt' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_print_analytics', [ $analytics, 'print_analytics_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::is_analytics_module_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_init_analytics_module_active(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'analytics' ], false );\n\t\tupdate_option( 'googlesitekit_analytics_settings', [ 'useSnippet' => true ], false );\n\n\t\t$analytics = $this->container->get( 'analytics' );\n\t\tadd_action( 'web_stories_print_analytics', [ $analytics, 'print_analytics_tag' ] );\n\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'googlesitekit_amp_gtag_opt', [ $this->instance, 'filter_site_kit_gtag_opt' ] ) );\n\t\t$this->assertSame( 10, has_action( 'web_stories_print_analytics', [ $analytics, 'print_analytics_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::filter_site_kit_gtag_opt\n\t */\n\tpublic function test_filter_site_kit_gtag_opt(): void {\n\t\t$gtag = [\n\t\t\t'vars'     => [\n\t\t\t\t'gtag_id' => 'hello',\n\t\t\t],\n\t\t\t'triggers' => [],\n\t\t];\n\n\t\t$actual = $this->instance->filter_site_kit_gtag_opt( $gtag );\n\n\t\t$this->assertSame( $gtag, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_site_kit_gtag_opt\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_filter_site_kit_gtag_opt_single_story(): void {\n\t\t$gtag = [\n\t\t\t'vars'     => [\n\t\t\t\t'gtag_id' => 'hello',\n\t\t\t],\n\t\t\t'triggers' => [],\n\t\t];\n\n\t\t$story_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Site Kit Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story_id );\n\n\t\t$this->go_to( (string) get_permalink( $story_id ) );\n\n\t\t$analytics = $this->createMock( Analytics::class );\n\t\t$analytics->method( 'get_default_configuration' )\n\t\t\t\t->willReturn(\n\t\t\t\t\t[\n\t\t\t\t\t\t'triggers' => [\n\t\t\t\t\t\t\t'storyProgress' => [],\n\t\t\t\t\t\t\t'storyEnd'      => [],\n\t\t\t\t\t\t],\n\t\t\t\t\t]\n\t\t\t\t);\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Integrations\\Site_Kit(\n\t\t\t$analytics,\n\t\t\t$this->injector->make( Context::class ),\n\t\t\t$this->injector->make( Plugin_Status::class ),\n\t\t\t$this->injector->make( Settings::class ),\n\t\t);\n\t\t$actual         = $this->instance->filter_site_kit_gtag_opt( $gtag );\n\n\t\t$this->assertIsArray( $actual );\n\t\t$this->assertIsArray( $actual['triggers'] );\n\t\t$this->assertArrayHasKey( 'storyProgress', $actual['triggers'] );\n\t\t$this->assertArrayHasKey( 'storyEnd', $actual['triggers'] );\n\t}\n\n\t/**\n\t * @covers ::get_site_kit_active_modules_option\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_site_kit_active_modules_option(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\n\t\t$actual_before = $this->call_private_method( [ $this->instance, 'get_site_kit_active_modules_option' ] );\n\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'analytics' ], false );\n\t\tupdate_option( 'googlesitekit_analytics_settings', [ 'useSnippet' => true ], false );\n\n\t\t$actual_after = $this->call_private_method( [ $this->instance, 'get_site_kit_active_modules_option' ] );\n\n\t\tdelete_option( 'googlesitekit_active_modules' );\n\t\tdelete_option( 'googlesitekit_analytics_settings' );\n\n\t\tupdate_option( 'googlesitekit-active-modules', [ 'analytics' ], false );\n\t\tupdate_option( 'googlesitekit_analytics_settings', [ 'useSnippet' => true ], false );\n\n\t\t$actual_after_legacy = $this->call_private_method( [ $this->instance, 'get_site_kit_active_modules_option' ] );\n\n\t\t$this->assertEmpty( $actual_before );\n\t\t$this->assertSame( [ 'analytics' ], $actual_after );\n\t\t$this->assertSame( [ 'analytics' ], $actual_after_legacy );\n\t}\n\n\t/**\n\t * @covers ::get_plugin_status\n\t */\n\tpublic function test_get_plugin_status(): void {\n\t\t$expected = [\n\t\t\t'installed'       => false,\n\t\t\t'active'          => false,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::get_plugin_status\n\t */\n\tpublic function test_get_plugin_status_plugin_installed(): void {\n\t\twp_cache_set( 'plugins', [ 'google-site-kit/google-site-kit.php' ], 'plugins' );\n\n\t\t$expected = [\n\t\t\t'installed'       => false,\n\t\t\t'active'          => false,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::get_plugin_status\n\t * @covers ::is_plugin_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_plugin_status_plugin_active(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\n\t\t$expected = [\n\t\t\t'installed'       => true,\n\t\t\t'active'          => true,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::get_plugin_status\n\t * @covers ::is_analytics_module_active\n\t * @covers ::is_adsense_module_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_plugin_status_analytics_module_active(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'analytics' ], false );\n\t\tupdate_option( 'googlesitekit_analytics_settings', [ 'useSnippet' => true ], false );\n\n\t\t$expected = [\n\t\t\t'installed'       => true,\n\t\t\t'active'          => true,\n\t\t\t'analyticsActive' => true,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\n\t/**\n\t * @covers ::get_plugin_status\n\t * @covers ::is_analytics_module_active\n\t * @covers ::is_adsense_module_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_plugin_status_analytics_module_no_snippet(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'analytics' ], false );\n\n\t\t$expected = [\n\t\t\t'installed'       => true,\n\t\t\t'active'          => true,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::get_plugin_status\n\t * @covers ::is_analytics_module_active\n\t * @covers ::is_adsense_module_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_plugin_status_adsense_module_active(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'adsense' ], false );\n\t\tupdate_option(\n\t\t\t'googlesitekit_adsense_settings',\n\t\t\t[\n\t\t\t\t'useSnippet'       => true,\n\t\t\t\t'webStoriesAdUnit' => '12345',\n\t\t\t\t'clientID'         => '98765',\n\t\t\t],\n\t\t\tfalse\n\t\t);\n\n\t\t$expected = [\n\t\t\t'installed'       => true,\n\t\t\t'active'          => true,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => true,\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\n\t/**\n\t * @covers ::get_plugin_status\n\t * @covers ::is_analytics_module_active\n\t * @covers ::is_adsense_module_active\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_get_plugin_status_adsense_module_no_snippet(): void {\n\t\t\\define( 'GOOGLESITEKIT_VERSION', '1.2.3' );\n\t\tupdate_option( 'googlesitekit_active_modules', [ 'adsense' ], false );\n\n\t\t$expected = [\n\t\t\t'installed'       => true,\n\t\t\t'active'          => true,\n\t\t\t'analyticsActive' => false,\n\t\t\t'adsenseActive'   => false,\n\t\t\t'adsenseLink'     => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t\t'analyticsLink'   => __( 'https://wordpress.org/plugins/google-site-kit/', 'web-stories' ),\n\t\t];\n\n\t\t$actual = $this->instance->get_plugin_status();\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Locale.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Locale\n */\nclass Locale extends TestCase {\n\t/**\n\t * @covers ::get_locale_settings\n\t */\n\tpublic function test_get_locale_settings(): void {\n\t\t$actual = ( new \\Google\\Web_Stories\\Locale() )->get_locale_settings();\n\n\t\t$this->assertCount( 12, $actual );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'locale',\n\t\t\t\t'dateFormat',\n\t\t\t\t'timeFormat',\n\t\t\t\t'gmtOffset',\n\t\t\t\t'timezone',\n\t\t\t\t'timezoneAbbr',\n\t\t\t\t'months',\n\t\t\t\t'monthsShort',\n\t\t\t\t'weekdays',\n\t\t\t\t'weekdaysShort',\n\t\t\t\t'weekdaysInitials',\n\t\t\t\t'weekStartsOn',\n\t\t\t],\n\t\t\tarray_keys( $actual )\n\t\t);\n\t\t$this->assertIsInt( $actual['weekStartsOn'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Base_Color.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Base_Color\n */\nclass Base_Color extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Base_Color $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Base_Color();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'wp_prepare_attachment_for_js', [ $this->instance, 'wp_prepare_attachment_for_js' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::BASE_COLOR_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$color = '#000000';\n\n\t\tupdate_post_meta( $attachment_id, $this->instance::BASE_COLOR_POST_META_KEY, $color );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $attachment_id ),\n\t\t\t]\n\t\t);\n\n\n\t\t$this->assertArrayHasKey( $this->instance::BASE_COLOR_POST_META_KEY, $image );\n\t\t$this->assertSame( $color, $image[ $this->instance::BASE_COLOR_POST_META_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$color = '#000000';\n\n\t\tupdate_post_meta( $attachment_id, $this->instance::BASE_COLOR_POST_META_KEY, $color );\n\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $attachment_id, $this->instance::BASE_COLOR_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Blurhash.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Blurhash\n */\nclass Blurhash extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Blurhash $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Blurhash();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::BLURHASH_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$blurhash = '000000';\n\n\t\tupdate_post_meta( $attachment_id, $this->instance::BLURHASH_POST_META_KEY, $blurhash );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $attachment_id ),\n\t\t\t]\n\t\t);\n\n\n\t\t$this->assertArrayHasKey( $this->instance::BLURHASH_POST_META_KEY, $image );\n\t\t$this->assertSame( $blurhash, $image[ $this->instance::BLURHASH_POST_META_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$blurhash = '000000';\n\n\t\tupdate_post_meta( $attachment_id, $this->instance::BLURHASH_POST_META_KEY, $blurhash );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $attachment_id, $this->instance::BLURHASH_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Cropping.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Cropping\n */\nclass Cropping extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Cropping $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Cropping();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::CROPPED_ID_POST_META_KEY, 'attachment' ) );\n\t\t$this->assertSame( 10, has_action( 'delete_attachment', [ $this->instance, 'delete_video' ] ) );\n\t}\n\n\t/**\n\t * @covers ::delete_video\n\t */\n\tpublic function test_delete_video_meta_attachment_is_deleted(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$cropped_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $video_attachment_id );\n\t\t$this->assertNotWPError( $cropped_attachment_id );\n\t\tadd_post_meta( $video_attachment_id, $this->instance::CROPPED_ID_POST_META_KEY, $cropped_attachment_id );\n\t\t$post_meta = get_post_meta( $video_attachment_id, $this->instance::CROPPED_ID_POST_META_KEY, true );\n\t\t$this->assertIsNumeric( $post_meta );\n\t\t$this->assertSame( $cropped_attachment_id, (int) $post_meta );\n\t\twp_delete_attachment( $cropped_attachment_id );\n\t\t$this->assertEmpty( get_post_meta( $video_attachment_id, $this->instance::CROPPED_ID_POST_META_KEY, true ) );\n\t}\n\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $video_attachment_id );\n\t\tadd_post_meta( $video_attachment_id, $this->instance::CROPPED_ID_POST_META_KEY, 999 );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $video_attachment_id, $this->instance::CROPPED_ID_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Image_Sizes.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Image_Sizes\n */\nclass Image_Sizes extends TestCase {\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$media = new \\Google\\Web_Stories\\Media\\Image_Sizes();\n\t\t$media->register();\n\n\t\t$this->assertSame( 10, has_filter( 'wp_prepare_attachment_for_js', [ $media, 'wp_prepare_attachment_for_js' ] ) );\n\t}\n\n\t/**\n\t * @covers ::add_image_sizes\n\t */\n\tpublic function test_add_image_sizes(): void {\n\t\t$media = new \\Google\\Web_Stories\\Media\\Image_Sizes();\n\t\t$this->call_private_method( [ $media, 'add_image_sizes' ] );\n\n\t\t$this->assertTrue( has_image_size( \\Google\\Web_Stories\\Media\\Image_Sizes::POSTER_PORTRAIT_IMAGE_SIZE ) );\n\t\t$this->assertTrue( has_image_size( \\Google\\Web_Stories\\Media\\Image_Sizes::STORY_THUMBNAIL_IMAGE_SIZE ) );\n\t\t$this->assertTrue( has_image_size( \\Google\\Web_Stories\\Media\\Image_Sizes::PUBLISHER_LOGO_IMAGE_SIZE ) );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$media            = new \\Google\\Web_Stories\\Media\\Image_Sizes();\n\t\t$image_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $image_attachment );\n\n\t\t$image            = $media->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $poster_attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $poster_attachment_id ),\n\t\t\t],\n\t\t\t$image_attachment\n\t\t);\n\t\t$video_attachment = get_post( $video_attachment_id );\n\t\t$this->assertNotNull( $video_attachment );\n\t\t$video = $media->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $video_attachment_id,\n\t\t\t\t'type' => 'video',\n\t\t\t\t'url'  => wp_get_attachment_url( $video_attachment_id ),\n\t\t\t],\n\t\t\t$video_attachment\n\t\t);\n\n\t\t$this->assertArrayHasKey( 'media_details', $video );\n\t\t$this->assertArrayHasKey( 'media_details', $image );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Media_Source_Taxonomy.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Query;\nuse WP_REST_Request;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Media_Source_Taxonomy\n */\nclass Media_Source_Taxonomy extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Media\\Media_Source_Taxonomy $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Media\\Media_Source_Taxonomy::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'rest_api_init', [ $this->instance, 'rest_api_init' ] ) );\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$this->assertSame(\n\t\t\tPHP_INT_MAX,\n\t\t\thas_filter(\n\t\t\t\t'ajax_query_attachments_args',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'filter_ajax_query_attachments_args',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$this->assertSame( PHP_INT_MAX, has_filter( 'pre_get_posts', [ $this->instance, 'filter_generated_media_attachments' ] ) );\n\t\t$this->assertSame(\n\t\t\tPHP_INT_MAX,\n\t\t\thas_filter(\n\t\t\t\t'web_stories_rest_attachment_query',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'filter_rest_generated_media_attachments',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register_taxonomy\n\t */\n\tpublic function test_register_taxonomy(): void {\n\t\t$this->call_private_method( [ $this->instance, 'register_taxonomy' ] );\n\n\t\t$this->assertTrue( taxonomy_exists( $this->instance->get_taxonomy_slug() ) );\n\t}\n\n\t/**\n\t * @covers ::rest_api_init\n\t */\n\tpublic function test_rest_api_init(): void {\n\t\t$user_id = self::factory()->user->create( [ 'role' => 'administrator' ] );\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\t\twp_set_object_terms( $video_attachment_id, 'editor', $this->instance->get_taxonomy_slug() );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, \\sprintf( '/wp/v2/media/%d', $video_attachment_id ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( $this->instance::MEDIA_SOURCE_KEY, $data );\n\t\t$this->assertEquals( 'editor', $data[ $this->instance::MEDIA_SOURCE_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $poster_attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $poster_attachment_id ),\n\t\t\t],\n\t\t);\n\t\t$video = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $video_attachment_id,\n\t\t\t\t'type' => 'video',\n\t\t\t\t'url'  => wp_get_attachment_url( $video_attachment_id ),\n\t\t\t],\n\t\t);\n\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'type'                     => 'image',\n\t\t\t\t'web_stories_media_source' => '',\n\t\t\t\t'id'                       => $poster_attachment_id,\n\t\t\t\t'url'                      => wp_get_attachment_url( $poster_attachment_id ),\n\n\t\t\t],\n\t\t\t$image\n\t\t);\n\n\t\t$this->assertArrayHasKey( $this->instance::MEDIA_SOURCE_KEY, $image );\n\t\t$this->assertArrayHasKey( $this->instance::MEDIA_SOURCE_KEY, $video );\n\t}\n\n\t/**\n\t * @covers ::get_exclude_tax_query\n\t */\n\tpublic function test_get_exclude_tax_query_filter(): void {\n\t\tadd_filter( 'web_stories_hide_auto_generated_attachments', '__return_false' );\n\t\t$tax_query = [\n\t\t\t[\n\t\t\t\t'taxonomy' => 'people',\n\t\t\t\t'field'    => 'slug',\n\t\t\t\t'terms'    => 'bob',\n\t\t\t],\n\t\t];\n\t\t$args      = [\n\t\t\t'tax_query' => $tax_query,\n\t\t];\n\t\t$results   = $this->call_private_method( [ $this->instance, 'get_exclude_tax_query' ], [ $args ] );\n\t\tremove_filter( 'web_stories_hide_auto_generated_attachments', '__return_false' );\n\t\t$this->assertSame( $tax_query, $results );\n\t}\n\n\t/**\n\t * @covers ::filter_ajax_query_attachments_args\n\t * @covers ::get_exclude_tax_query\n\t */\n\tpublic function test_filter_ajax_query_attachments_args(): void {\n\t\t$tax_slug = $this->instance->get_taxonomy_slug();\n\n\t\t$expected = [\n\t\t\t'tax_query' => [\n\t\t\t\t'relation' => 'AND',\n\t\t\t\t[\n\t\t\t\t\t'taxonomy' => $tax_slug,\n\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t'terms'    => [ 'poster-generation', 'source-video', 'source-image', 'page-template' ],\n\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$actual = $this->instance->filter_ajax_query_attachments_args( [] );\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_ajax_query_attachments_args\n\t * @covers ::get_exclude_tax_query\n\t */\n\tpublic function test_filter_ajax_query_attachments_args_existing_tax_query(): void {\n\t\t$tax_slug = $this->instance->get_taxonomy_slug();\n\n\t\t$expected = [\n\t\t\t'tax_query' => [\n\t\t\t\t'relation' => 'AND',\n\t\t\t\t[\n\t\t\t\t\t'taxonomy' => $tax_slug,\n\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t'terms'    => [ 'poster-generation', 'source-video', 'source-image', 'page-template' ],\n\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t[\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'taxonomy' => 'category',\n\t\t\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t\t\t'terms'    => [ 'uncategorized' ],\n\t\t\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$actual = $this->instance->filter_ajax_query_attachments_args(\n\t\t\t[\n\t\t\t\t'tax_query' => [\n\t\t\t\t\t[\n\t\t\t\t\t\t'taxonomy' => 'category',\n\t\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t\t'terms'    => [ 'uncategorized' ],\n\t\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_generated_media_attachments\n\t */\n\tpublic function test_filter_generated_media_attachments_no_screen(): void {\n\t\t$query    = new WP_Query();\n\t\t$expected = $query->get( 'tax_query' );\n\n\t\t$this->instance->filter_generated_media_attachments( $query );\n\t\t$actual = $query->get( 'tax_query' );\n\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_generated_media_attachments\n\t */\n\tpublic function test_filter_generated_media_attachments_not_main_query(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( 'upload' );\n\n\t\t$query    = new WP_Query();\n\t\t$expected = $query->get( 'tax_query' );\n\n\t\t$this->instance->filter_generated_media_attachments( $query );\n\t\t$actual = $query->get( 'tax_query' );\n\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_generated_media_attachments\n\t */\n\tpublic function test_filter_generated_media_attachments_not_upload_screen(): void {\n\t\t$GLOBALS['current_screen'] = convert_to_screen( 'post' );\n\n\t\t$query                   = new WP_Query();\n\t\t$GLOBALS['wp_the_query'] = $query;\n\t\t$expected                = $query->get( 'tax_query' );\n\n\t\t$this->instance->filter_generated_media_attachments( $query );\n\t\t$actual = $query->get( 'tax_query' );\n\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_generated_media_attachments\n\t */\n\tpublic function test_filter_generated_media_attachmentss(): void {\n\n\t\t$expected = [\n\t\t\t'relation' => 'AND',\n\t\t\t[\n\t\t\t\t'taxonomy' => $this->instance->get_taxonomy_slug(),\n\t\t\t\t'field'    => 'slug',\n\t\t\t\t'terms'    => [ 'poster-generation', 'source-video', 'source-image', 'page-template' ],\n\t\t\t\t'operator' => 'NOT IN',\n\t\t\t],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t[\n\t\t\t\t\t\t'taxonomy' => 'category',\n\t\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t\t'terms'    => [ 'uncategorized' ],\n\t\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$GLOBALS['current_screen'] = convert_to_screen( 'upload' );\n\n\t\t$query                   = new WP_Query();\n\t\t$GLOBALS['wp_the_query'] = $query;\n\t\t$query->set(\n\t\t\t'tax_query',\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'taxonomy' => 'category',\n\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t'terms'    => [ 'uncategorized' ],\n\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$this->instance->filter_generated_media_attachments( $query );\n\t\t$actual = $query->get( 'tax_query' );\n\n\t\t$this->assertIsArray( $actual );\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_rest_generated_media_attachments\n\t */\n\tpublic function test_filter_rest_generated_media_attachments(): void {\n\t\t$tax_slug = $this->instance->get_taxonomy_slug();\n\n\t\t$expected = [\n\t\t\t'tax_query' => [\n\t\t\t\t'relation' => 'AND',\n\t\t\t\t[\n\t\t\t\t\t'taxonomy' => $tax_slug,\n\t\t\t\t\t'field'    => 'slug',\n\t\t\t\t\t'terms'    => [ 'poster-generation', 'source-video', 'source-image', 'page-template' ],\n\t\t\t\t\t'operator' => 'NOT IN',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\n\t\t$actual = $this->instance->filter_rest_generated_media_attachments( [] );\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/SVG.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\SVG\n */\nclass SVG extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\SVG $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$experiments = $this->createMock( Experiments::class );\n\t\t$experiments->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturn( true );\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\SVG( $experiments );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'web_stories_allowed_mime_types',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'web_stories_allowed_mime_types',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$this->assertSame( 10, has_filter( 'upload_mimes', [ $this->instance, 'upload_mimes_add_svg' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'mime_types', [ $this->instance, 'mime_types_add_svg' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'wp_handle_upload_prefilter', [ $this->instance, 'wp_handle_upload' ] ) );\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'wp_generate_attachment_metadata',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'wp_generate_attachment_metadata',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$this->assertSame( 10, has_filter( 'wp_check_filetype_and_ext', [ $this->instance, 'wp_check_filetype_and_ext' ] ) );\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'site_option_upload_filetypes',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'filter_list_of_allowed_filetypes',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::svg_already_enabled\n\t */\n\tpublic function test_svg_already_enabled(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'svg_already_enabled' ] );\n\n\t\t$this->assertFalse( $_results );\n\t}\n\n\t/**\n\t * @covers ::upload_mimes_add_svg\n\t */\n\tpublic function test_upload_mimes_add_svg(): void {\n\t\t$this->instance->register();\n\n\t\t$allowed_mime_types = wp_get_mime_types();\n\t\t$mine_types         = array_values( $allowed_mime_types );\n\t\t$this->assertContains( 'image/svg+xml', $mine_types );\n\n\t\t$allowed_mime_types = $this->instance->upload_mimes_add_svg( [] );\n\t\t$mine_types         = array_values( $allowed_mime_types );\n\t\t$this->assertContains( 'image/svg+xml', $mine_types );\n\t}\n\n\t/**\n\t * @covers ::mime_types_add_svg\n\t */\n\tpublic function test_mime_types_add_svg(): void {\n\t\t$this->instance->register();\n\n\t\t$allowed_mime_types = get_allowed_mime_types();\n\t\t$mine_types         = array_values( $allowed_mime_types );\n\t\t$this->assertContains( 'image/svg+xml', $mine_types );\n\n\t\t$allowed_mime_types = $this->instance->mime_types_add_svg( [] );\n\t\t$mine_types         = array_values( $allowed_mime_types );\n\t\t$this->assertContains( 'image/svg+xml', $mine_types );\n\t}\n\n\n\t/**\n\t * @covers ::web_stories_allowed_mime_types\n\t */\n\tpublic function test_web_stories_allowed_mime_types(): void {\n\t\t$allowed_mime_types = $this->instance->web_stories_allowed_mime_types( [] );\n\n\t\t$this->assertArrayHasKey( 'vector', $allowed_mime_types );\n\t\t$this->assertContains( 'image/svg+xml', $allowed_mime_types['vector'] );\n\t}\n\n\t/**\n\t * @covers ::filter_list_of_allowed_filetypes\n\t */\n\tpublic function test_filter_list_of_allowed_filetypes(): void {\n\t\t$this->instance->register();\n\t\t/**\n\t\t * @var string $upload_filetypes\n\t\t */\n\t\t$upload_filetypes = get_site_option( 'upload_filetypes', 'jpg jpeg png gif' );\n\t\t$this->assertStringContainsString( 'svg', $upload_filetypes );\n\t}\n\n\t/**\n\t * @covers ::wp_generate_attachment_metadata\n\t * @covers ::get_svg_size\n\t */\n\tpublic function test_upload_svg(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => WEB_STORIES_TEST_DATA_DIR . '/video-play.svg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/svg+xml',\n\t\t\t\t'post_title'     => 'Test svg',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$this->instance->register();\n\n\t\t$attachment_metadata = wp_generate_attachment_metadata( $attachment_id, (string) get_attached_file( $attachment_id ) );\n\t\t$this->assertArrayHasKey( 'width', $attachment_metadata );\n\t\t$this->assertArrayHasKey( 'height', $attachment_metadata );\n\t\t$this->assertArrayHasKey( 'file', $attachment_metadata );\n\t\t$this->assertArrayHasKey( 'filesize', $attachment_metadata );\n\t\t$this->assertArrayHasKey( 'sizes', $attachment_metadata );\n\n\t\t$this->assertSame( $attachment_metadata['width'], 64 );\n\t\t$this->assertSame( $attachment_metadata['height'], 64 );\n\t}\n\n\t/**\n\t * @covers ::wp_generate_attachment_metadata\n\t */\n\tpublic function test_wp_generate_attachment_metadata_update(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => WEB_STORIES_TEST_DATA_DIR . '/video-play.svg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/svg+xml',\n\t\t\t\t'post_title'     => 'Test svg',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$result = $this->instance->wp_generate_attachment_metadata( [], $attachment_id, 'update' );\n\t\t$this->assertEqualSets( [], $result );\n\t}\n\n\n\t/**\n\t * @covers ::wp_generate_attachment_metadata\n\t */\n\tpublic function test_wp_generate_attachment_metadata_invalid(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$result = $this->instance->wp_generate_attachment_metadata( [], $attachment_id, 'create' );\n\t\t$this->assertEqualSets( [], $result );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'sanitize' ], [ WEB_STORIES_TEST_DATA_DIR . '/video-play.svg' ] );\n\n\t\t$this->assertTrue( $_results );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_fail(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'sanitize' ], [ WEB_STORIES_TEST_DATA_DIR . '/animated.svg' ] );\n\n\t\t$this->assertInstanceOf( 'WP_Error', $_results );\n\t\t$this->assertSame( 'insecure_svg_file', $_results->get_error_code() );\n\t\t$this->assertSame( 'Sorry, this file couldn\\'t be sanitized so for security reasons wasn\\'t uploaded.', $_results->get_error_message() );\n\t}\n\n\t/**\n\t * @covers ::get_svg_size\n\t * @covers ::get_svg_data\n\t * @covers ::get_xml\n\t */\n\tpublic function test_get_svg_size_from_viewbox(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'get_svg_size' ], [ WEB_STORIES_TEST_DATA_DIR . '/why.svg' ] );\n\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'width'  => 100,\n\t\t\t\t'height' => 100,\n\t\t\t],\n\t\t\t$_results\n\t\t);\n\t\t$this->assertIsInt( $_results['width'] );\n\t\t$this->assertIsInt( $_results['height'] );\n\t}\n\n\t/**\n\t * @covers ::get_svg_size\n\t * @covers ::get_svg_data\n\t * @covers ::get_xml\n\t */\n\tpublic function test_get_svg_size_invalid_size(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'get_svg_size' ], [ WEB_STORIES_TEST_DATA_DIR . '/add.svg' ] );\n\n\t\t$this->assertInstanceOf( 'WP_Error', $_results );\n\t\t$this->assertSame( 'invalid_svg_size', $_results->get_error_code() );\n\t\t$this->assertSame( 'Unable to generate SVG image size.', $_results->get_error_message() );\n\t}\n\n\t/**\n\t * @covers ::get_svg_size\n\t * @covers ::get_svg_data\n\t * @covers ::get_xml\n\t */\n\tpublic function test_get_svg_size_invalid_viewbox(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'get_svg_size' ], [ WEB_STORIES_TEST_DATA_DIR . '/add-invalid.svg' ] );\n\n\t\t$this->assertInstanceOf( 'WP_Error', $_results );\n\t\t$this->assertSame( 'invalid_svg_size', $_results->get_error_code() );\n\t\t$this->assertSame( 'Unable to generate SVG image size.', $_results->get_error_message() );\n\t}\n\n\t/**\n\t * @covers ::get_xml\n\t */\n\tpublic function test_get_xml_invalid_file(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'get_xml' ], [ '<invalid' ] );\n\n\t\t$this->assertFalse( $_results );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t * @covers ::get_svg_data\n\t */\n\tpublic function test_sanitize_invalid_file(): void {\n\t\t$_results = $this->call_private_method( [ $this->instance, 'sanitize' ], [ '' ] );\n\n\t\t$this->assertInstanceOf( 'WP_Error', $_results );\n\t\t$this->assertSame( 'invalid_xml_svg', $_results->get_error_code() );\n\t\t$this->assertSame( 'Invalid XML in SVG.', $_results->get_error_message() );\n\t}\n\n\t/**\n\t * @covers ::wp_check_filetype_and_ext\n\t */\n\tpublic function test_wp_check_filetype_and_ext(): void {\n\t\t$this->instance->register();\n\n\t\t$filepath = WEB_STORIES_TEST_DATA_DIR . '/animated.svg';\n\t\t$data     = wp_check_filetype_and_ext( $filepath, $filepath );\n\n\t\t$this->assertSame( $data['ext'], 'svg' );\n\t\t$this->assertSame( $data['type'], 'image/svg+xml' );\n\t}\n\n\t/**\n\t * @covers ::wp_check_filetype_and_ext\n\t */\n\tpublic function test_wp_check_filetype_and_ext_method(): void {\n\t\t$data = $this->instance->wp_check_filetype_and_ext( [], '', '', [], 'image/svg' );\n\n\t\t$this->assertArrayHasKey( 'ext', $data );\n\t\t$this->assertArrayHasKey( 'type', $data );\n\n\t\t$this->assertSame( $data['ext'], 'svg' );\n\t\t$this->assertSame( $data['type'], 'image/svg+xml' );\n\t}\n\n\t/**\n\t * @covers ::wp_handle_upload\n\t */\n\tpublic function test_wp_handle_upload(): void {\n\t\t$upload = [\n\t\t\t'tmp_name' => WEB_STORIES_TEST_DATA_DIR . '/video-play.svg',\n\t\t\t'file'     => WEB_STORIES_TEST_DATA_DIR . '/video-play.svg',\n\t\t\t'url'      => 'http://www.example.com/video-play.svg',\n\t\t\t'type'     => 'image/svg+xml',\n\t\t];\n\t\t$data   = $this->instance->wp_handle_upload( $upload );\n\t\t$this->assertSame( $data, $upload );\n\t}\n\n\t/**\n\t * @covers ::wp_handle_upload\n\t */\n\tpublic function test_wp_handle_upload_invalid(): void {\n\t\t$upload = [\n\t\t\t'tmp_name' => WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg',\n\t\t\t'type'     => 'image/jpeg',\n\t\t\t'file'     => WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg',\n\t\t\t'url'      => 'http://www.example.com/attachment.jpg',\n\t\t];\n\t\t$data   = $this->instance->wp_handle_upload( $upload );\n\t\t$this->assertSame( $data, $upload );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Types.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Types\n */\nclass Types extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Types $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Types();\n\t}\n\n\t/**\n\t * @covers ::get_allowed_mime_types\n\t * @group ms-excluded\n\t */\n\tpublic function test_get_allowed_mime_types(): void {\n\t\t$expected = [\n\t\t\t'image'   => [\n\t\t\t\t'image/webp',\n\t\t\t\t'image/png',\n\t\t\t\t'image/jpeg',\n\t\t\t\t'image/gif',\n\t\t\t],\n\t\t\t'audio'   => [\n\t\t\t\t'audio/mpeg',\n\t\t\t\t'audio/aac',\n\t\t\t\t'audio/wav',\n\t\t\t\t'audio/ogg',\n\t\t\t],\n\t\t\t'caption' => [ 'text/vtt' ],\n\t\t\t'vector'  => [],\n\t\t\t'video'   => [\n\t\t\t\t'video/mp4',\n\t\t\t\t'video/webm',\n\t\t\t],\n\t\t];\n\n\t\tif ( $this->supports_avif() ) {\n\t\t\t$expected['image'][] = 'image/avif';\n\t\t}\n\n\t\t$actual = $this->instance->get_allowed_mime_types();\n\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n\n\t/**\n\t * @group ms-required\n\t * @covers ::get_allowed_mime_types\n\t */\n\tpublic function test_get_allowed_mime_types_multisite(): void {\n\t\t$expected = [\n\t\t\t'image'   => [\n\t\t\t\t'image/webp',\n\t\t\t\t'image/png',\n\t\t\t\t'image/jpeg',\n\t\t\t\t'image/gif',\n\t\t\t],\n\t\t\t'audio'   => [\n\t\t\t\t'audio/mpeg',\n\t\t\t\t'audio/wav',\n\t\t\t\t'audio/ogg',\n\t\t\t],\n\t\t\t'caption' => [ 'text/vtt' ],\n\t\t\t'vector'  => [],\n\t\t\t'video'   => [\n\t\t\t\t'video/mp4',\n\t\t\t\t'video/webm',\n\t\t\t],\n\t\t];\n\n\t\tif ( $this->supports_avif() ) {\n\t\t\t$expected['image'][] = 'image/avif';\n\t\t}\n\n\t\t// See https://core.trac.wordpress.org/ticket/53167.\n\t\tif ( is_wp_version_compatible( '6.6' ) ) {\n\t\t\t$expected['audio'] = [\n\t\t\t\t'audio/mpeg',\n\t\t\t\t'audio/aac',\n\t\t\t\t'audio/wav',\n\t\t\t\t'audio/ogg',\n\t\t\t];\n\t\t}\n\n\t\t$actual = $this->instance->get_allowed_mime_types();\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::get_file_type_exts\n\t */\n\tpublic function test_get_file_type_exts(): void {\n\t\t$actual = $this->instance->get_file_type_exts( [ 'video/webm' ] );\n\n\t\t$this->assertEqualSets( [ 'webm' ], $actual );\n\t}\n\n\t/**\n\t * Check whether the current WordPress version supports AVIF.\n\t *\n\t * AVIF support was added in WordPress 6.5\n\t */\n\tprotected function supports_avif(): bool {\n\t\t$mime_type = array_values( wp_get_mime_types() );\n\n\t\treturn \\in_array( 'image/avif', $mime_type, true );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Captions.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media\\Video;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Captions\n */\nclass Captions extends TestCase {\n\t/**\n\t * @covers ::filter_list_of_allowed_filetypes\n\t * @group ms-required\n\t */\n\tpublic function test_filter_list_of_allowed_filetypes(): void {\n\t\t/**\n\t\t * @var string $upload_filetypes\n\t\t */\n\t\t$upload_filetypes = get_site_option( 'upload_filetypes', 'jpg jpeg png gif' );\n\t\t$site_exts        = explode( ' ', $upload_filetypes );\n\t\t$this->assertContains( 'vtt', $site_exts );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Is_Gif.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Is_Gif\n */\nclass Is_Gif extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Video\\Is_Gif $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Video\\Is_Gif();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::IS_GIF_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::IS_GIF_POST_META_KEY, 999 );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $video_attachment_id, $this->instance::IS_GIF_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Muting.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media\\Video;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_REST_Request;\nuse WP_REST_Server;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Muting\n */\nclass Muting extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Media\\Video\\Muting $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Media\\Video\\Muting::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'rest_api_init', [ $this->instance, 'rest_api_init' ] ) );\n\t\t$this->assertSame( 10, has_action( 'delete_attachment', [ $this->instance, 'delete_video' ] ) );\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'wp_prepare_attachment_for_js',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::IS_MUTED_POST_META_KEY, 'attachment' ) );\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::MUTED_ID_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t * @covers ::get_callback_is_muted\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $poster_attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $poster_attachment_id ),\n\t\t\t]\n\t\t);\n\t\t$video = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $video_attachment_id,\n\t\t\t\t'type' => 'video',\n\t\t\t\t'url'  => wp_get_attachment_url( $video_attachment_id ),\n\t\t\t]\n\t\t);\n\n\t\t$this->assertArrayNotHasKey( $this->instance::IS_MUTED_REST_API_KEY, $image );\n\t\t$this->assertArrayHasKey( $this->instance::IS_MUTED_REST_API_KEY, $video );\n\t}\n\n\t/**\n\t * @covers ::rest_api_init\n\t * @covers ::get_callback_is_muted\n\t */\n\tpublic function test_rest_api_init(): void {\n\t\t$user_id = self::factory()->user->create( [ 'role' => 'administrator' ] );\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, \\sprintf( '/web-stories/v1/media/%d', $video_attachment_id ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( $this->instance::IS_MUTED_REST_API_KEY, $data );\n\t\t$this->assertNull( $data[ $this->instance::IS_MUTED_REST_API_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::get_callback_is_muted\n\t */\n\tpublic function test_get_callback_is_muted(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\tupdate_post_meta( $video_attachment_id, $this->instance::IS_MUTED_POST_META_KEY, '1' );\n\t\t$result = $this->instance->get_callback_is_muted( [ 'id' => $video_attachment_id ] );\n\t\t$this->assertTrue( $result );\n\t}\n\n\t/**\n\t * @covers ::update_callback_is_muted\n\t */\n\tpublic function test_update_callback_is_muted(): void {\n\t\t$user_id = self::factory()->user->create( [ 'role' => 'administrator' ] );\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$video_attachment = get_post( $video_attachment_id );\n\n\t\t$this->assertNotNull( $video_attachment );\n\n\t\t$actual = $this->instance->update_callback_is_muted( true, $video_attachment );\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::update_callback_is_muted\n\t */\n\tpublic function test_update_callback_is_muted_error(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$video_attachment = get_post( $video_attachment_id );\n\n\t\t$this->assertNotNull( $video_attachment );\n\n\t\t$actual = $this->instance->update_callback_is_muted( true, $video_attachment );\n\t\t$this->assertInstanceOf( 'WP_Error', $actual );\n\t}\n\n\t/**\n\t * @covers ::delete_video\n\t */\n\tpublic function test_delete_video_meta_attachment_is_deleted(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$muted_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $muted_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::MUTED_ID_POST_META_KEY, $muted_attachment_id );\n\t\t$post_meta = get_post_meta( $video_attachment_id, $this->instance::MUTED_ID_POST_META_KEY, true );\n\t\t$this->assertIsNumeric( $post_meta );\n\t\t$this->assertSame( $muted_attachment_id, (int) $post_meta );\n\t\twp_delete_attachment( $muted_attachment_id );\n\t\t$this->assertEmpty( get_post_meta( $video_attachment_id, $this->instance::MUTED_ID_POST_META_KEY, true ) );\n\t}\n\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$muted_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $muted_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::MUTED_ID_POST_META_KEY, $muted_attachment_id );\n\t\tadd_post_meta( $muted_attachment_id, $this->instance::IS_MUTED_POST_META_KEY, '1' );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( 0, get_post_meta( $video_attachment_id, $this->instance::MUTED_ID_POST_META_KEY, true ) );\n\t\t$this->assertFalse( get_post_meta( $muted_attachment_id, $this->instance::IS_MUTED_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Optimization.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media\\Video;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Optimization\n */\nclass Optimization extends TestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Video\\Optimization $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Video\\Optimization();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::OPTIMIZED_ID_POST_META_KEY, 'attachment' ) );\n\t\t$this->assertSame( 10, has_action( 'delete_attachment', [ $this->instance, 'delete_video' ] ) );\n\t}\n\n\t/**\n\t * @covers ::delete_video\n\t */\n\tpublic function test_delete_video_meta_attachment_is_deleted(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$optimized_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $optimized_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::OPTIMIZED_ID_POST_META_KEY, $optimized_attachment_id );\n\t\t$post_meta = get_post_meta( $video_attachment_id, $this->instance::OPTIMIZED_ID_POST_META_KEY, true );\n\t\t$this->assertIsNumeric( $post_meta );\n\t\t$this->assertSame( $optimized_attachment_id, (int) $post_meta );\n\t\twp_delete_attachment( $optimized_attachment_id );\n\t\t$this->assertEmpty( get_post_meta( $video_attachment_id, $this->instance::OPTIMIZED_ID_POST_META_KEY, true ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$optimized_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $optimized_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::OPTIMIZED_ID_POST_META_KEY, $optimized_attachment_id );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $video_attachment_id, $this->instance::OPTIMIZED_ID_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Poster.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media\\Video;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_REST_Request;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Poster\n */\nclass Poster extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Media\\Video\\Poster $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Media\\Video\\Poster::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'rest_api_init', [ $this->instance, 'rest_api_init' ] ) );\n\t\t$this->assertSame( 10, has_action( 'delete_attachment', [ $this->instance, 'delete_video_poster' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'wp_prepare_attachment_for_js', [ $this->instance, 'wp_prepare_attachment_for_js' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::POSTER_ID_POST_META_KEY, 'attachment' ) );\n\t\t$this->assertFalse( registered_meta_key_exists( 'post', $this->instance::POSTER_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::rest_api_init\n\t */\n\tpublic function test_rest_api_init(): void {\n\t\t$user_id = self::factory()->user->create( [ 'role' => 'administrator' ] );\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, \\sprintf( '/web-stories/v1/media/%d', $video_attachment_id ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'featured_media', $data );\n\t\t$this->assertEquals( $poster_attachment_id, $data['featured_media'] );\n\t\t$this->assertEquals( wp_get_attachment_url( $poster_attachment_id ), $data['featured_media_src']['src'] );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$image_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $image_attachment );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $poster_attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $poster_attachment_id ),\n\t\t\t],\n\t\t\t$image_attachment\n\t\t);\n\n\t\t$video_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $video_attachment );\n\t\t$video = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $video_attachment_id,\n\t\t\t\t'type' => 'video',\n\t\t\t\t'url'  => wp_get_attachment_url( $video_attachment_id ),\n\t\t\t],\n\t\t\t$video_attachment\n\t\t);\n\n\t\t$this->assertArrayHasKey( 'featured_media', $video );\n\t\t$this->assertArrayHasKey( 'featured_media_src', $video );\n\t\t$this->assertArrayNotHasKey( 'featured_media', $image );\n\t\t$this->assertArrayNotHasKey( 'featured_media_src', $image );\n\t}\n\n\t/**\n\t * @covers ::get_thumbnail_data\n\t */\n\tpublic function test_get_thumbnail_data(): void {\n\t\t$attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$result = $this->instance->get_thumbnail_data( $attachment_id );\n\n\t\t$this->assertCount( 4, $result );\n\t\t$this->assertArrayHasKey( 'src', $result );\n\t\t$this->assertArrayHasKey( 'width', $result );\n\t\t$this->assertArrayHasKey( 'height', $result );\n\t\t$this->assertArrayHasKey( 'generated', $result );\n\t\t$this->assertFalse( $result['generated'] );\n\t}\n\n\t/**\n\t * @covers ::get_thumbnail_data\n\t */\n\tpublic function test_get_thumbnail_data_generated(): void {\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\twp_set_object_terms( $poster_attachment_id, 'poster-generation', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\n\t\t$result = $this->instance->get_thumbnail_data( $poster_attachment_id );\n\n\t\t$this->assertArrayHasKey( 'generated', $result );\n\t\t$this->assertTrue( $result['generated'] );\n\t}\n\n\t/**\n\t * @covers ::delete_video_poster\n\t */\n\tpublic function test_delete_video_poster(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\t\twp_set_object_terms( $poster_attachment_id, 'poster-generation', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\tadd_post_meta( $video_attachment_id, $this->instance::POSTER_ID_POST_META_KEY, $poster_attachment_id );\n\n\t\t$this->instance->delete_video_poster( $video_attachment_id );\n\t\t$this->assertNull( get_post( $poster_attachment_id ) );\n\t}\n\n\t/**\n\t * @covers ::delete_video_poster\n\t */\n\tpublic function test_delete_video_poster_no_generated_poster(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$this->instance->delete_video_poster( $video_attachment_id );\n\t\t$this->assertNotNull( get_post( $poster_attachment_id ) );\n\t}\n\n\t/**\n\t * @covers ::delete_video_poster\n\t */\n\tpublic function test_delete_video_poster_when_attachment_is_deleted(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\twp_set_object_terms( $poster_attachment_id, 'poster-generation', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\tadd_post_meta( $video_attachment_id, $this->instance::POSTER_ID_POST_META_KEY, $poster_attachment_id );\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\twp_delete_attachment( $video_attachment_id );\n\t\t$this->assertNull( get_post( $poster_attachment_id ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::POSTER_ID_POST_META_KEY, $poster_attachment_id );\n\t\tadd_post_meta( $poster_attachment_id, $this->instance::POSTER_POST_META_KEY, '1' );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( 0, get_post_meta( $video_attachment_id, $this->instance::POSTER_ID_POST_META_KEY, true ) );\n\t\t$this->assertSame( '', get_post_meta( $poster_attachment_id, $this->instance::POSTER_POST_META_KEY, true ) );\n\t}\n\n\t/**\n\t * @covers ::is_poster\n\t */\n\tpublic function test_is_poster(): void {\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\t$result1 = $this->call_private_method( [ $this->instance, 'is_poster' ], [ $poster_attachment_id ] );\n\t\t$this->assertFalse( $result1 );\n\n\t\twp_set_object_terms( $poster_attachment_id, 'editor', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\t$result2 = $this->call_private_method( [ $this->instance, 'is_poster' ], [ $poster_attachment_id ] );\n\t\t$this->assertFalse( $result2 );\n\n\t\twp_set_object_terms( $poster_attachment_id, 'poster-generation', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\t$result3 = $this->call_private_method( [ $this->instance, 'is_poster' ], [ $poster_attachment_id ] );\n\t\t$this->assertTrue( $result3 );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Media/Video/Trimming.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media\\Video;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Media\\Video\\Trimming\n */\nclass Trimming extends TestCase {\n\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Media\\Video\\Trimming $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = new \\Google\\Web_Stories\\Media\\Video\\Trimming();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'wp_prepare_attachment_for_js', [ $this->instance, 'wp_prepare_attachment_for_js' ] ) );\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::TRIM_POST_META_KEY, 'attachment' ) );\n\t}\n\n\t/**\n\t * @covers ::wp_prepare_attachment_for_js\n\t */\n\tpublic function test_wp_prepare_attachment_for_js(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\n\t\t$image = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $poster_attachment_id,\n\t\t\t\t'type' => 'image',\n\t\t\t\t'url'  => wp_get_attachment_url( $poster_attachment_id ),\n\t\t\t]\n\t\t);\n\t\t$video = $this->instance->wp_prepare_attachment_for_js(\n\t\t\t[\n\t\t\t\t'id'   => $video_attachment_id,\n\t\t\t\t'type' => 'video',\n\t\t\t\t'url'  => wp_get_attachment_url( $video_attachment_id ),\n\t\t\t]\n\t\t);\n\n\t\t$this->assertArrayNotHasKey( $this->instance::TRIM_DATA_KEY, $image );\n\t\t$this->assertArrayHasKey( $this->instance::TRIM_DATA_KEY, $video );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\tadd_post_meta( $video_attachment_id, $this->instance::TRIM_POST_META_KEY, [] );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$this->assertSame( '', get_post_meta( $video_attachment_id, $this->instance::TRIM_POST_META_KEY, true ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Mgid.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Mgid\n */\nclass Mgid extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Mgid $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tupdate_option( Settings::SETTING_NAME_AD_NETWORK, 'mgid' );\n\t\tupdate_option( Settings::SETTING_NAME_MGID_WIDGET_ID, '123456789' );\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Mgid::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tparent::tear_down();\n\n\t\tdelete_option( Settings::SETTING_NAME_AD_NETWORK );\n\t\tdelete_option( Settings::SETTING_NAME_MGID_WIDGET_ID );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_action( 'web_stories_print_analytics', [ $this->instance, 'print_mgid_tag' ] ) );\n\t}\n\n\t/**\n\t * @covers ::get_widget_id\n\t */\n\tpublic function test_get_widget_id(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'get_widget_id' ] );\n\t\t$this->assertSame( '123456789', $result );\n\t}\n\n\t/**\n\t * @covers ::is_enabled\n\t */\n\tpublic function test_is_enabled(): void {\n\t\t$result = $this->call_private_method( [ $this->instance, 'is_enabled' ] );\n\t\t$this->assertTrue( $result );\n\t}\n\n\t/**\n\t * @covers ::print_mgid_tag\n\t */\n\tpublic function test_print_mgid_tag(): void {\n\t\t$output = get_echo( [ $this->instance, 'print_mgid_tag' ] );\n\t\t$this->assertStringContainsString( '<amp-story-auto-ads>', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Editor.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Editor\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Editor\n */\nclass Add_Media_Source_Editor extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Editor $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Editor::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Gif_Conversion.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Gif_Conversion\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Gif_Conversion\n */\nclass Add_Media_Source_Gif_Conversion extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Gif_Conversion $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Gif_Conversion::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Page_Template.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Page_Template\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Page_Template\n */\nclass Add_Media_Source_Page_Template extends DependencyInjectedTestCase {\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Page_Template::class );\n\t\t$instance->migrate();\n\n\t\t$term = $this->call_private_method( [ $instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Recording.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Recording\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Recording\n */\nclass Add_Media_Source_Recording extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Recording $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Recording::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Source_Image.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Source_Image\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Image\n */\nclass Add_Media_Source_Source_Image extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Image $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Image::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Source_Video.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Source_Video\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Video\n */\nclass Add_Media_Source_Source_Video extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Video $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Source_Video::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Media_Source_Video_Optimization.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Add_Media_Source_Video_Optimization\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Video_Optimization\n */\nclass Add_Media_Source_Video_Optimization extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Video_Optimization $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Media_Source_Video_Optimization::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers ::get_term\n\t * @covers \\Google\\Web_Stories\\Migrations\\Add_Media_Source::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$this->instance->migrate();\n\t\t$term = $this->call_private_method( [ $this->instance, 'get_term' ] );\n\n\t\t$terms = get_terms(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->container->get( 'media.media_source' )->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $terms );\n\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertContains( $term, $slugs );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_Poster_Generation_Media_Source.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Video\\Poster;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Term;\n\n/**\n * Class Add_Poster_Generation_Media_Source\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_Poster_Generation_Media_Source\n */\nclass Add_Poster_Generation_Media_Source extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_Poster_Generation_Media_Source $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_Poster_Generation_Media_Source::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers \\Google\\Web_Stories\\Migrations\\Migration_Meta_To_Term::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\t\tadd_post_meta( $poster_attachment_id, Poster::POSTER_POST_META_KEY, 'true' );\n\t\tadd_post_meta( $video_attachment_id, Poster::POSTER_ID_POST_META_KEY, $poster_attachment_id );\n\n\t\t$slug = $this->call_private_method( [ $this->instance, 'get_term_name' ] );\n\t\t$this->instance->migrate();\n\n\t\t/**\n\t\t * @var WP_Term[] $terms\n\t\t */\n\t\t$terms = wp_get_post_terms( $poster_attachment_id, $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertCount( 1, $terms );\n\t\t$this->assertEqualSets( [ $slug ], $slugs );\n\t}\n\n\t/**\n\t * @covers ::get_post_meta_key\n\t * @covers \\Google\\Web_Stories\\Migrations\\Migration_Meta_To_Term::get_post_meta_key\n\t */\n\tpublic function test_get_post_meta_key(): void {\n\t\t$results = $this->call_private_method( [ $this->instance, 'get_post_meta_key' ] );\n\t\t$this->assertSame( Poster::POSTER_POST_META_KEY, $results );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Add_VideoPress_Poster_Generation_Media_Source.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Integrations\\Jetpack;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_Term;\n\n/**\n * Class Add_VideoPress_Poster_Generation_Media_Source\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Add_VideoPress_Poster_Generation_Media_Source\n */\nclass Add_VideoPress_Poster_Generation_Media_Source extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Migrations\\Add_VideoPress_Poster_Generation_Media_Source $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Add_VideoPress_Poster_Generation_Media_Source::class );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t * @covers \\Google\\Web_Stories\\Migrations\\Migration_Meta_To_Term::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\t\tadd_post_meta( $poster_attachment_id, Jetpack::VIDEOPRESS_POSTER_META_KEY, 'true' );\n\n\t\t$slug = $this->call_private_method( [ $this->instance, 'get_term_name' ] );\n\t\t$this->instance->migrate();\n\n\t\t/**\n\t\t * @var WP_Term[] $terms\n\t\t */\n\t\t$terms = wp_get_post_terms( $poster_attachment_id, $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t\t$slugs = wp_list_pluck( $terms, 'slug' );\n\t\t$this->assertCount( 1, $terms );\n\t\t$this->assertEqualSets( [ $slug ], $slugs );\n\t}\n\n\t/**\n\t * @covers ::get_post_meta_key\n\t * @covers \\Google\\Web_Stories\\Migrations\\Migration_Meta_To_Term::get_post_meta_key\n\t */\n\tpublic function test_get_post_meta_key(): void {\n\t\t$results = $this->call_private_method( [ $this->instance, 'get_post_meta_key' ] );\n\t\t$this->assertSame( Jetpack::VIDEOPRESS_POSTER_META_KEY, $results );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Remove_Broken_Text_Styles.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class Remove_Broken_Text_Styles\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Remove_Broken_Text_Styles\n */\nclass Remove_Broken_Text_Styles extends TestCase {\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrates(): void {\n\t\t$presets = [\n\t\t\t'textStyles' => [\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'r' => 255,\n\t\t\t\t\t\t'g' => 255,\n\t\t\t\t\t\t'b' => 255,\n\t\t\t\t\t],\n\t\t\t\t\t'font'  => [],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'type'  => 'solid',\n\t\t\t\t\t\t'color' => [\n\t\t\t\t\t\t\t'r' => 255,\n\t\t\t\t\t\t\t'g' => 255,\n\t\t\t\t\t\t\t'b' => 255,\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'font'  => [],\n\t\t\t\t],\n\t\t\t],\n\t\t\t'textColors' => [],\n\t\t\t'fillColors' => [],\n\t\t];\n\t\tadd_option( Story_Post_Type::STYLE_PRESETS_OPTION, $presets );\n\n\t\t$object = new \\Google\\Web_Stories\\Migrations\\Remove_Broken_Text_Styles();\n\t\t$object->migrate();\n\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t\t$this->assertIsArray( $style_presets );\n\t\t$this->assertArrayHasKey( 'textStyles', $style_presets );\n\t\t$this->assertSame(\n\t\t\t$style_presets['textStyles'],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'type'  => 'solid',\n\t\t\t\t\t\t'color' => [\n\t\t\t\t\t\t\t'r' => 255,\n\t\t\t\t\t\t\t'g' => 255,\n\t\t\t\t\t\t\t'b' => 255,\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'font'  => [],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tdelete_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Remove_Incorrect_Tracking_Id.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse Google\\Web_Stories\\Tracking;\n\n/**\n * Class Remove_Incorrect_Tracking_Id\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Remove_Incorrect_Tracking_Id\n */\nclass Remove_Incorrect_Tracking_Id extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Migrations\\Remove_Incorrect_Tracking_Id $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Remove_Incorrect_Tracking_Id::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_TRACKING_ID );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate_unchanged(): void {\n\t\t$tracking_id = 'UA-12345678-9';\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, $tracking_id );\n\n\t\t$this->instance->migrate();\n\n\t\t$this->assertSame( $tracking_id, get_option( Settings::SETTING_NAME_TRACKING_ID ) );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate_reset(): void {\n\t\t$tracking_id = Tracking::TRACKING_ID;\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, $tracking_id );\n\n\t\t$this->instance->migrate();\n\n\t\t$this->assertSame( '', get_option( Settings::SETTING_NAME_TRACKING_ID ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Remove_Unneeded_Attachment_Meta.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Media\\Video\\Poster;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class Remove_Unneeded_Attachment_Meta\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Remove_Unneeded_Attachment_Meta\n */\nclass Remove_Unneeded_Attachment_Meta extends TestCase {\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$video_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $video_attachment_id );\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $video_attachment_id, $poster_attachment_id );\n\t\tadd_post_meta( $poster_attachment_id, Poster::POSTER_POST_META_KEY, 'true' );\n\t\tadd_post_meta( $video_attachment_id, Poster::POSTER_ID_POST_META_KEY, $poster_attachment_id );\n\n\t\t$object = new \\Google\\Web_Stories\\Migrations\\Remove_Unneeded_Attachment_Meta();\n\t\t$object->migrate();\n\n\t\t$meta = get_post_meta( $poster_attachment_id, Poster::POSTER_POST_META_KEY, true );\n\n\t\t$this->assertSame( '', $meta );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Replace_Conic_Style_Presets.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class Replace_Conic_Style_Presets\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Replace_Conic_Style_Presets\n */\nclass Replace_Conic_Style_Presets extends TestCase {\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrates(): void {\n\t\t$radial_preset = [\n\t\t\t[\n\t\t\t\t'color'              => [],\n\t\t\t\t'backgroundColor'    =>\n\t\t\t\t\t[\n\t\t\t\t\t\t'type'     => 'radial',\n\t\t\t\t\t\t'stops'    => [],\n\t\t\t\t\t\t'rotation' => 0.5,\n\t\t\t\t\t],\n\t\t\t\t'backgroundTextMode' => 'FILL',\n\t\t\t],\n\t\t];\n\t\t$presets       = [\n\t\t\t'fillColors' => [\n\t\t\t\t[\n\t\t\t\t\t'type'     => 'conic',\n\t\t\t\t\t'stops'    =>\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color'    => [],\n\t\t\t\t\t\t\t\t'position' => 0,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color'    => [],\n\t\t\t\t\t\t\t\t'position' => 0.7,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t'rotation' => 0.5,\n\t\t\t\t],\n\t\t\t],\n\t\t\t'textColors' => [\n\t\t\t\t[\n\t\t\t\t\t'color' => [],\n\t\t\t\t],\n\t\t\t],\n\t\t\t'textStyles' => [\n\t\t\t\t[\n\t\t\t\t\t'color'              => [],\n\t\t\t\t\t'backgroundColor'    =>\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'type'     => 'conic',\n\t\t\t\t\t\t\t'stops'    => [],\n\t\t\t\t\t\t\t'rotation' => 0.5,\n\t\t\t\t\t\t],\n\t\t\t\t\t'backgroundTextMode' => 'FILL',\n\t\t\t\t\t'font'               => [],\n\t\t\t\t],\n\t\t\t\t$radial_preset,\n\t\t\t],\n\t\t];\n\t\tadd_option( Story_Post_Type::STYLE_PRESETS_OPTION, $presets );\n\n\t\t$object = new \\Google\\Web_Stories\\Migrations\\Replace_Conic_Style_Presets();\n\t\t$object->migrate();\n\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t\t$this->assertIsArray( $style_presets );\n\t\t$this->assertArrayHasKey( 'textStyles', $style_presets );\n\t\t$this->assertIsArray( $style_presets['textStyles'] );\n\t\t$this->assertSame( $style_presets['textStyles'][1], $radial_preset );\n\t\t$this->assertIsArray( $style_presets['textStyles'][0] );\n\t\t$this->assertArrayHasKey( 'backgroundColor', $style_presets['textStyles'][0] );\n\t\t$this->assertIsArray( $style_presets['textStyles'][0]['backgroundColor'] );\n\t\t$this->assertArrayHasKey( 'type', $style_presets['textStyles'][0]['backgroundColor'] );\n\t\t$this->assertSame( $style_presets['textStyles'][0]['backgroundColor']['type'], 'linear' );\n\n\t\t$this->assertSame( $style_presets['fillColors'][0]['type'], 'linear' );\n\t\t$this->assertSame(\n\t\t\t$style_presets['textColors'],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'color' => [],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\tdelete_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Set_Legacy_Analytics_Usage_Flag.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Set_Legacy_Analytics_Usage_Flag\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Set_Legacy_Analytics_Usage_Flag\n */\nclass Set_Legacy_Analytics_Usage_Flag extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\Migrations\\Set_Legacy_Analytics_Usage_Flag $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Set_Legacy_Analytics_Usage_Flag::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_TRACKING_ID );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate_true(): void {\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, 'UA-12345678-9' );\n\n\t\t$this->instance->migrate();\n\n\t\t$this->assertTrue( get_option( Settings::SETTING_NAME_USING_LEGACY_ANALYTICS ) );\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate_false(): void {\n\t\tupdate_option( Settings::SETTING_NAME_TRACKING_ID, '' );\n\n\t\t$this->instance->migrate();\n\n\t\t$this->assertFalse( get_option( Settings::SETTING_NAME_USING_LEGACY_ANALYTICS ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Unify_Color_Presets.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class Unify_Color_Presets\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Unify_Color_Presets\n */\nclass Unify_Color_Presets extends TestCase {\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\t$presets = [\n\t\t\t'textStyles' => [],\n\t\t\t'textColors' => [\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'r' => 255,\n\t\t\t\t\t\t'g' => 255,\n\t\t\t\t\t\t'b' => 255,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t\t'fillColors' => [\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'r' => 1,\n\t\t\t\t\t\t'g' => 1,\n\t\t\t\t\t\t'b' => 1,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t\tadd_option( Story_Post_Type::STYLE_PRESETS_OPTION, $presets );\n\n\t\t$object = new \\Google\\Web_Stories\\Migrations\\Unify_Color_Presets();\n\t\t$object->migrate();\n\n\t\t$style_presets = get_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t\t$this->assertIsArray( $style_presets );\n\t\t$this->assertArrayHasKey( 'colors', $style_presets );\n\t\t$this->assertSame(\n\t\t\t$style_presets['colors'],\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'r' => 1,\n\t\t\t\t\t\t'g' => 1,\n\t\t\t\t\t\t'b' => 1,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'color' => [\n\t\t\t\t\t\t'r' => 255,\n\t\t\t\t\t\t'g' => 255,\n\t\t\t\t\t\t'b' => 255,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t\tdelete_option( Story_Post_Type::STYLE_PRESETS_OPTION );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Migrations/Update_Publisher_Logos.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Migrations;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Update_Publisher_Logos\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Migrations\\Update_Publisher_Logos\n */\nclass Update_Publisher_Logos extends DependencyInjectedTestCase {\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::migrate\n\t */\n\tpublic function test_migrate(): void {\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ 'active' => 123 ] );\n\n\t\t$instance = $this->injector->make( \\Google\\Web_Stories\\Migrations\\Update_Publisher_Logos::class );\n\t\t$instance->migrate();\n\n\t\t/**\n\t\t * @var array<string, int> $all_publisher_logos\n\t\t */\n\t\t$all_publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\t\t/**\n\t\t * @var string $active_publisher_logo\n\t\t */\n\t\t$active_publisher_logo = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\t\t$active_publisher_logo = (int) $active_publisher_logo;\n\n\t\t$this->assertEqualSets( [ 123 ], $all_publisher_logos );\n\t\t$this->assertSame( 123, $active_publisher_logo );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Model/Story.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Model;\n\nuse Google\\Web_Stories\\Shopping\\Product_Meta;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Model\\Story\n */\nclass Story extends TestCase {\n\t/**\n\t * @covers ::__construct\n\t */\n\tpublic function test_init(): void {\n\t\t$data  = [\n\t\t\t'title' => 'test title',\n\t\t\t'url'   => 'https://www.google.com',\n\t\t];\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story( $data );\n\n\t\t$this->assertEquals( $story->get_title(), $data['title'] );\n\t\t$this->assertEquals( $story->get_url(), $data['url'] );\n\t}\n\n\t/**\n\t * @covers ::load_from_post\n\t */\n\tpublic function test_load_from_post(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertEquals( $story->get_title(), 'test title' );\n\t\t$this->assertEquals( $story->get_url(), get_permalink( $post ) );\n\t}\n\n\t/**\n\t * @covers ::load_from_post\n\t */\n\tpublic function test_load_from_post_with_product(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\tadd_post_meta(\n\t\t\t$post->ID,\n\t\t\tProduct_Meta::PRODUCTS_POST_META_KEY,\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'aggregateRating'      => [\n\t\t\t\t\t\t'ratingValue' => 5,\n\t\t\t\t\t\t'reviewCount' => 1,\n\t\t\t\t\t\t'reviewUrl'   => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t\t],\n\t\t\t\t\t'ratingValue'          => 0,\n\t\t\t\t\t'reviewCount'          => 0,\n\t\t\t\t\t'reviewUrl'            => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t\t'productBrand'         => 'Google',\n\t\t\t\t\t'productDetails'       => 'This is a simple product.',\n\t\t\t\t\t'productId'            => 'wc-36',\n\t\t\t\t\t'productImages'        => [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'url' => 'http://www.example.com/wp-content/uploads/2019/01/t-shirt-with-logo-1-4.jpg',\n\t\t\t\t\t\t\t'alt' => '',\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\t'productPrice'         => 18,\n\t\t\t\t\t'productPriceCurrency' => 'USD',\n\t\t\t\t\t'productTitle'         => 'T-Shirt with Logo',\n\t\t\t\t\t'productUrl'           => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t],\n\n\t\t\t]\n\t\t);\n\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertSame( 'test title', $story->get_title() );\n\t\t$this->assertSame( get_permalink( $post ), $story->get_url() );\n\t\t$this->assertNotEmpty( $story->get_products() );\n\t}\n\n\n\t/**\n\t * @covers ::load_from_post\n\t */\n\tpublic function test_load_from_post_with_poster(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => WEB_STORIES_TEST_DATA_DIR . '/paint.jpeg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\t\t$poster_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $poster_attachment );\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story();\n\t\t$story->load_from_post( $post );\n\n\t\twp_delete_attachment( $poster_attachment_id, true );\n\n\t\t$this->assertEquals( $story->get_title(), 'test title' );\n\t\t$this->assertEquals( $story->get_url(), get_permalink( $post ) );\n\t\t$this->assertStringContainsString( 'paint-640x853.jpeg', $story->get_poster_portrait() );\n\t\t$this->assertNotEmpty( $story->get_poster_sizes() );\n\t\t$this->assertNotEmpty( $story->get_poster_srcset() );\n\t}\n\n\t/**\n\t * @covers ::load_from_post\n\t */\n\tpublic function test_load_from_post_with_poster_meta(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\tadd_post_meta(\n\t\t\t$post->ID,\n\t\t\tStory_Post_Type::POSTER_META_KEY,\n\t\t\t[\n\t\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t\t'height'     => 1000,\n\t\t\t\t'width'      => 1000,\n\t\t\t\t'needsProxy' => false,\n\t\t\t]\n\t\t);\n\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertEquals( $story->get_title(), 'test title' );\n\t\t$this->assertEquals( $story->get_url(), get_permalink( $post ) );\n\t\t$this->assertEquals( 'http://www.example.com/image.png', $story->get_poster_portrait() );\n\t\t$this->assertEqualSets( [ 1000, 1000 ], $story->get_poster_portrait_size() );\n\t\t$this->assertEmpty( $story->get_poster_srcset() );\n\t}\n\n\t/**\n\t * @covers ::load_from_post\n\t */\n\tpublic function test_load_from_post_with_poster_and_poster_meta(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => WEB_STORIES_TEST_DATA_DIR . '/paint.jpeg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\t\t$poster_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $poster_attachment );\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\tadd_post_meta(\n\t\t\t$post->ID,\n\t\t\tStory_Post_Type::POSTER_META_KEY,\n\t\t\t[\n\t\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t\t'height'     => 1000,\n\t\t\t\t'width'      => 1000,\n\t\t\t\t'needsProxy' => false,\n\t\t\t]\n\t\t);\n\n\t\t$story = new \\Google\\Web_Stories\\Model\\Story();\n\t\t$story->load_from_post( $post );\n\n\t\twp_delete_attachment( $poster_attachment_id, true );\n\n\t\t$this->assertEquals( $story->get_title(), 'test title' );\n\t\t$this->assertEquals( $story->get_url(), get_permalink( $post ) );\n\t\t$this->assertStringContainsString( 'paint-640x853.jpeg', $story->get_poster_portrait() );\n\t\t$this->assertNotEmpty( $story->get_poster_sizes() );\n\t\t$this->assertNotEmpty( $story->get_poster_srcset() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Page_Template_Post_Type.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Page_Template_Post_Type\n */\nclass Page_Template_Post_Type extends DependencyInjectedTestCase {\n\tuse Capabilities_Setup;\n\n\tprivate \\Google\\Web_Stories\\Page_Template_Post_Type $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Page_Template_Post_Type::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$post_type_object = get_post_type_object( \\Google\\Web_Stories\\Page_Template_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->assertNotNull( $post_type_object );\n\t\t$this->assertSame( 'edit_web-stories', $post_type_object->cap->edit_posts );\n\t\t$this->assertSame( 'delete_web-stories', $post_type_object->cap->delete_posts );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Post_Type_Base.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyPostTypeWithCustomArchive;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyPostTypeWithoutArchive;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Post_Type_Base\n */\nclass Post_Type_Base extends DependencyInjectedTestCase {\n\n\tprotected static \\Google\\Web_Stories\\Post_Type_Base $cpt_no_archive;\n\n\tprotected static \\Google\\Web_Stories\\Post_Type_Base $cpt_custom_archive;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tself::$cpt_no_archive = new DummyPostTypeWithoutArchive();\n\t\tself::$cpt_no_archive->register();\n\n\t\tself::$cpt_custom_archive = new DummyPostTypeWithCustomArchive();\n\t\tself::$cpt_custom_archive->register();\n\t}\n\n\tpublic function tear_down(): void {\n\t\tself::$cpt_no_archive->unregister_post_type();\n\t\tself::$cpt_custom_archive->unregister_post_type();\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_archive_link_no_archive(): void {\n\t\t$link = self::$cpt_no_archive->get_archive_link();\n\t\t$this->assertSame( home_url( '/?post_type=cpt-without-archive' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_archive_link_no_archive_pretty_permalinks(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tself::$cpt_no_archive->unregister_post_type();\n\t\tself::$cpt_no_archive = new DummyPostTypeWithoutArchive();\n\t\tself::$cpt_no_archive->register();\n\n\t\t$link = self::$cpt_no_archive->get_archive_link();\n\t\t$this->assertSame( home_url( '/' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_archive_link_custom_archive(): void {\n\t\t$link = self::$cpt_custom_archive->get_archive_link();\n\t\t$this->assertSame( home_url( '/?post_type=cpt-custom-archive' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_archive_link_custom_archive_pretty_permalinks(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tself::$cpt_custom_archive->unregister_post_type();\n\t\tself::$cpt_custom_archive = new DummyPostTypeWithCustomArchive();\n\t\tself::$cpt_custom_archive->register();\n\n\t\t$link = self::$cpt_custom_archive->get_archive_link();\n\t\t$this->assertSame( home_url( '/custom-archive-slug/' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_default_archive_link_no_archive(): void {\n\t\t$link = self::$cpt_no_archive->get_archive_link( true );\n\t\t$this->assertSame( home_url( '?post_type=cpt-without-archive' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_default_archive_link_no_archive_pretty_permalinks(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tself::$cpt_no_archive->unregister_post_type();\n\t\tself::$cpt_no_archive = new DummyPostTypeWithoutArchive();\n\t\tself::$cpt_no_archive->register();\n\n\t\t$link = self::$cpt_no_archive->get_archive_link( true );\n\t\t$this->assertSame( home_url( '/cpt-without-archive/' ), $link );\n\t}\n\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_default_archive_link_custom_archive(): void {\n\t\t$link = self::$cpt_custom_archive->get_archive_link( true );\n\t\t$this->assertSame( home_url( '?post_type=cpt-custom-archive' ), $link );\n\t}\n\t/**\n\t * @covers ::get_archive_link\n\t */\n\tpublic function test_get_default_archive_link_custom_archive_pretty_permalinks(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tself::$cpt_custom_archive->unregister_post_type();\n\t\tself::$cpt_custom_archive = new DummyPostTypeWithCustomArchive();\n\t\tself::$cpt_custom_archive->register();\n\n\t\t$link = self::$cpt_custom_archive->get_archive_link( true );\n\t\t$this->assertSame( home_url( '/cpt-custom-archive/' ), $link );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\tself::$cpt_custom_archive->register();\n\t\tself::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => self::$cpt_custom_archive->get_slug(),\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\t\tself::$cpt_custom_archive->on_plugin_uninstall();\n\t\t$cpt_posts = get_posts(\n\t\t\t[\n\t\t\t\t'fields'           => 'ids',\n\t\t\t\t'suppress_filters' => false,\n\t\t\t\t'post_status'      => 'any',\n\t\t\t\t'post_type'        => self::$cpt_custom_archive->get_slug(),\n\t\t\t\t'posts_per_page'   => -1,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertSameSets( [], $cpt_posts );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Embed_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_REST_Response;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Embed_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Embed_Controller\n */\nclass Embed_Controller extends DependencyInjectedRestTestCase {\n\tpublic const INVALID_URL              = 'https://www.notreallyawebsite.com/foobar.html';\n\tpublic const VALID_URL_EMPTY_DOCUMENT = 'https://empty.example.com';\n\tpublic const VALID_URL                = 'https://preview.amp.dev/documentation/examples/introduction/stories_in_amp';\n\n\tprotected static int $story_id;\n\tprotected static int $subscriber;\n\tprotected static int $editor;\n\tprotected static int $admin;\n\n\t/**\n\t * Count of the number of requests attempted.\n\t */\n\tprotected int $request_count = 0;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Embed_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t\tself::$admin      = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\t// When running the tests, we don't have unfiltered_html capabilities.\n\t\t// This change avoids HTML in post_content being stripped in our test posts because of KSES.\n\t\tremove_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tremove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\n\t\t$story_content  = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Embed Controller Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => $story_content,\n\t\t\t]\n\t\t);\n\n\t\tadd_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tadd_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );\n\t\t$this->request_count = 0;\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Embed_Controller::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_http_request' ] );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Intercept link processing requests and mock responses.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param mixed  $r       HTTP request arguments.\n\t * @param string $url     The request URL.\n\t * @return array{response: array<string, mixed>, body?: string} Response data.\n\t */\n\tpublic function mock_http_request( $preempt, $r, string $url ): array {\n\t\t++$this->request_count;\n\n\t\tif ( false !== strpos( $url, self::VALID_URL_EMPTY_DOCUMENT ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => '<html></html>',\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::VALID_URL ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/stories_in_amp.html' ),\n\t\t\t];\n\t\t}\n\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 404,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::register_routes\n\t */\n\tpublic function test_register_routes(): void {\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/embed', $routes );\n\t}\n\n\tpublic function test_missing_param(): void {\n\t\t$this->controller->register();\n\n\t\t$response = $this->dispatch_request();\n\n\t\t$this->assertErrorResponse( 'rest_missing_callback_param', $response, 400 );\n\t}\n\n\tpublic function test_not_logged_in(): void {\n\t\t$this->controller->register();\n\n\n\t\t$response = $this->dispatch_request( '' );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\tpublic function test_without_permission(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$subscriber );\n\n\t\t$response = $this->dispatch_request( self::VALID_URL );\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 403 );\n\t}\n\n\tpublic function test_url_empty_string(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$response = $this->dispatch_request( '' );\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $response, 404 );\n\t}\n\n\tpublic function test_invalid_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$response = $this->dispatch_request( self::INVALID_URL );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $response, 404 );\n\t}\n\n\tpublic function test_empty_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$response = $this->dispatch_request( self::VALID_URL_EMPTY_DOCUMENT );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_story', $response, 404 );\n\t}\n\n\tpublic function test_valid_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$response = $this->dispatch_request( self::VALID_URL );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'  => 'Stories in AMP - Hello World',\n\t\t\t'poster' => 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg',\n\t\t];\n\n\t\t// Subsequent requests are cached, so it should not perform another HTTP request.\n\t\t$this->dispatch_request( self::VALID_URL );\n\t\t$this->assertEquals( 1, $this->request_count );\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\tpublic function test_removes_trailing_slashes(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$response = $this->dispatch_request( self::VALID_URL );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'  => 'Stories in AMP - Hello World',\n\t\t\t'poster' => 'https://amp.dev/static/samples/img/story_dog2_portrait.jpg',\n\t\t];\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/embed' );\n\t\t$request->set_param( 'url', self::VALID_URL . '/' );\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\tpublic function test_local_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$this->set_permalink_structure( '' );\n\n\t\t$response = $this->dispatch_request( (string) get_permalink( self::$story_id ) );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'  => '',\n\t\t\t'poster' => 'https:/example.com/poster.png',\n\t\t];\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\tpublic function test_local_url_pretty_permalinks(): void {\n\t\t$this->controller->register();\n\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\t// Without (re-)registering the post type here there won't be any rewrite rules for it\n\t\t// and get_permalink() will return \"http://example.org/?web-story=embed-controller-test-story\"\n\t\t// instead of \"http://example.org/web-stories/embed-controller-test-story/\".\n\t\t// @todo Investigate why this is  needed (leakage between tests?)\n\t\t$story_post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$story_post_type->register();\n\n\t\tflush_rewrite_rules( false );\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$response = $this->dispatch_request( (string) get_permalink( self::$story_id ) );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'  => '',\n\t\t\t'poster' => 'https:/example.com/poster.png',\n\t\t];\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @group ms-required\n\t */\n\tpublic function test_local_url_pretty_permalinks_multisite(): void {\n\t\t$this->controller->register();\n\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\t// Without (re-)registering the post type here there won't be any rewrite rules for it\n\t\t// and get_permalink() will return \"http://example.org/?web-story=embed-controller-test-story\"\n\t\t// instead of \"http://example.org/web-stories/embed-controller-test-story/\".\n\t\t// @todo Investigate why this is  needed (leakage between tests?).\n\t\t$story_post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$story_post_type->register();\n\n\t\tflush_rewrite_rules( false );\n\n\t\twp_set_current_user( self::$admin );\n\n\t\t$permalink = (string) get_permalink( self::$story_id );\n\n\t\t$blog_id = self::factory()->blog->create();\n\n\t\t$this->assertNotWPError( $blog_id );\n\n\t\tadd_user_to_blog( $blog_id, self::$admin, 'administrator' );\n\t\tswitch_to_blog( $blog_id );\n\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\t$response = $this->dispatch_request( $permalink );\n\n\t\t$this->assertNotWPError( $response->as_error() );\n\n\t\t$data = $response->get_data();\n\n\t\trestore_current_blog();\n\n\t\t$expected = [\n\t\t\t'title'  => '',\n\t\t\t'poster' => 'https:/example.com/poster.png',\n\t\t];\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\tprotected function dispatch_request( ?string $url = null ): WP_REST_Response {\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/embed' );\n\t\tif ( null !== $url ) {\n\t\t\t$request->set_param( 'url', $url );\n\t\t}\n\t\treturn rest_get_server()->dispatch( $request );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Font_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\RestTestCase;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Font_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Font_Controller\n */\nclass Font_Controller extends RestTestCase {\n\tprotected static int $admin_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Font_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Font_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_title'   => 'Overpass Regular',\n\t\t\t\t'post_content' => '{\"family\":\"Overpass Regular\",\"fallbacks\":[\"sans-serif\"],\"weights\":[400],\"styles\":[\"regular\"],\"variants\":[[0,400]],\"url\":\"https:\\/\\/overpass-30e2.kxcdn.com\\/overpass-regular.ttf\",\"service\":\"custom\",\"metrics\":{\"upm\":1000,\"asc\":982,\"des\":-284,\"tAsc\":750,\"tDes\":-250,\"tLGap\":266,\"wAsc\":1062,\"wDes\":378,\"xH\":511,\"capH\":700,\"yMin\":-378,\"yMax\":1062,\"hAsc\":982,\"hDes\":-284,\"lGap\":266}}',\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Font_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_title'   => 'Gingrich Small Regular',\n\t\t\t\t'post_content' => '{\"family\":\"Gingrich Small Regular\",\"fallbacks\":[\"sans-serif\"],\"weights\":[400],\"styles\":[\"regular\"],\"variants\":[[0,400]],\"url\":\"https:\\/\\/www.barrons.com\\/fonts\\/woffs\\/gingrich\\/GingrichSmall-Regular.woff\",\"service\":\"custom\",\"metrics\":{\"upm\":1000,\"asc\":830,\"des\":-170,\"tAsc\":830,\"tDes\":-170,\"tLGap\":200,\"wAsc\":1060,\"wDes\":226,\"xH\":522,\"capH\":750,\"yMin\":-226,\"yMax\":1060,\"hAsc\":830,\"hDes\":-170,\"lGap\":200}}',\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Font_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_title'   => 'Vazir Regular',\n\t\t\t\t'post_content' => '{\"family\":\"Vazir Regular\",\"fallbacks\":[\"sans-serif\"],\"weights\":[400],\"styles\":[\"regular\"],\"variants\":[[0,400]],\"url\":\"https:\\/\\/cdn.jsdelivr.net\\/gh\\/rastikerdar\\/vazir-font@v30.1.0\\/dist\\/Vazir-Regular.ttf\",\"service\":\"custom\",\"metrics\":{\"upm\":2048,\"asc\":2200,\"des\":-1100,\"tAsc\":2200,\"tDes\":-1100,\"tLGap\":0,\"wAsc\":2200,\"wDes\":1100,\"xH\":1082,\"capH\":1638,\"yMin\":-1116,\"yMax\":2163,\"hAsc\":2200,\"hDes\":-1100,\"lGap\":0}}',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = new \\Google\\Web_Stories\\REST_API\\Font_Controller( Font_Post_Type::POST_TYPE_SLUG );\n\t}\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$actual = $this->controller->get_item_schema();\n\n\t\t$this->assertCount( 9, array_keys( $actual['properties'] ) );\n\t\t$this->assertArrayHasKey( 'family', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'fallbacks', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'weights', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'styles', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'variants', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'service', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'metrics', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'id', $actual['properties'] );\n\t\t$this->assertArrayHasKey( 'url', $actual['properties'] );\n\t}\n\n\t/**\n\t * @covers ::get_collection_params\n\t */\n\tpublic function test_get_collection_params(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$collection_params = $this->controller->get_collection_params();\n\t\t$this->assertArrayHasKey( 'search', $collection_params );\n\t\t$this->assertArrayHasKey( 'include', $collection_params );\n\t\t$this->assertArrayHasKey( 'service', $collection_params );\n\t\t$this->assertArrayHasKey( 'enum', $collection_params['service'] );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t */\n\tpublic function test_get_items_no_permission(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/fonts' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_filter_by_service_builtin(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/fonts' );\n\t\t$request->set_param( 'service', 'builtin' );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\n\t\tforeach ( $data as $font ) {\n\t\t\t$this->assertIsArray( $font );\n\t\t\t$this->assertArrayHasKey( 'service', $font );\n\t\t\t$this->assertNotSame( 'custom', $font['service'] );\n\t\t\t$this->assertTrue( 'system' === $font['service'] || 'fonts.google.com' === $font['service'] );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_filter_by_service_custom(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/fonts' );\n\t\t$request->set_param( 'service', 'custom' );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 3, $data );\n\n\t\tforeach ( $data as $font ) {\n\t\t\t$this->assertIsArray( $font );\n\t\t\t$this->assertArrayHasKey( 'service', $font );\n\t\t\t$this->assertSame( 'custom', $font['service'] );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_include(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/fonts' );\n\t\t$request->set_param( 'include', [ 'Overpass Regular', 'Arial', 'Roboto' ] );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 3, $data );\n\t\t$this->assertIsArray( $data[0] );\n\t\t$this->assertIsArray( $data[1] );\n\t\t$this->assertIsArray( $data[2] );\n\t\t$this->assertSame( 'Arial', $data[0]['family'] );\n\t\t$this->assertSame( 'Overpass Regular', $data[1]['family'] );\n\t\t$this->assertSame( 'Roboto', $data[2]['family'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_search(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/fonts' );\n\t\t$request->set_param( 'search', 'oVeR' );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 9, $data );\n\n\t\tforeach ( $data as $font ) {\n\t\t\t$this->assertIsArray( $font );\n\t\t\t$this->assertIsString( $font['family'] );\n\t\t\t$this->assertStringContainsStringIgnoringCase( 'over', $font['family'] );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::prepare_item_for_database\n\t */\n\tpublic function test_create_item(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/fonts' );\n\n\t\t$request->set_param( 'family', 'Vazir Regular 2' );\n\t\t$request->set_param( 'fallbacks', [ 'sans-serif' ] );\n\t\t$request->set_param( 'weights', [ 400 ] );\n\t\t$request->set_param( 'styles', [ 'regular' ] );\n\t\t$request->set_param( 'variants', [ [ 0, 400 ] ] );\n\t\t$request->set_param( 'url', 'https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf' );\n\t\t$request->set_param(\n\t\t\t'metrics',\n\t\t\t[\n\t\t\t\t'upm'   => 2048,\n\t\t\t\t'asc'   => 2200,\n\t\t\t\t'des'   => -1100,\n\t\t\t\t'tAsc'  => 2200,\n\t\t\t\t'tDes'  => -1100,\n\t\t\t\t'tLGap' => 0,\n\t\t\t\t'wAsc'  => 2200,\n\t\t\t\t'wDes'  => 1100,\n\t\t\t\t'xH'    => 1082,\n\t\t\t\t'capH'  => 1638,\n\t\t\t\t'yMin'  => -1116,\n\t\t\t\t'yMax'  => 2163,\n\t\t\t\t'hAsc'  => 2200,\n\t\t\t\t'hDes'  => -1100,\n\t\t\t\t'lGap'  => 0,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'id', $data );\n\t\t$this->assertIsInt( $data['id'] );\n\t\t$this->assertArrayHasKey( 'family', $data );\n\t\t$this->assertArrayHasKey( 'fallbacks', $data );\n\t\t$this->assertArrayHasKey( 'weights', $data );\n\t\t$this->assertArrayHasKey( 'styles', $data );\n\t\t$this->assertArrayHasKey( 'variants', $data );\n\t\t$this->assertArrayHasKey( 'url', $data );\n\t\t$this->assertArrayHasKey( 'metrics', $data );\n\t\t$this->assertArrayHasKey( 'service', $data );\n\n\t\t$post = get_post( $data['id'] );\n\n\t\tunset( $data['id'] );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'family'    => 'Vazir Regular 2',\n\t\t\t\t'fallbacks' => [ 'sans-serif' ],\n\t\t\t\t'weights'   => [ 400 ],\n\t\t\t\t'styles'    => [ 'regular' ],\n\t\t\t\t'variants'  => [ [ 0, 400 ] ],\n\t\t\t\t'url'       => 'https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf',\n\t\t\t\t'metrics'   => [\n\t\t\t\t\t'upm'   => 2048,\n\t\t\t\t\t'asc'   => 2200,\n\t\t\t\t\t'des'   => -1100,\n\t\t\t\t\t'tAsc'  => 2200,\n\t\t\t\t\t'tDes'  => -1100,\n\t\t\t\t\t'tLGap' => 0,\n\t\t\t\t\t'wAsc'  => 2200,\n\t\t\t\t\t'wDes'  => 1100,\n\t\t\t\t\t'xH'    => 1082,\n\t\t\t\t\t'capH'  => 1638,\n\t\t\t\t\t'yMin'  => -1116,\n\t\t\t\t\t'yMax'  => 2163,\n\t\t\t\t\t'hAsc'  => 2200,\n\t\t\t\t\t'hDes'  => -1100,\n\t\t\t\t\t'lGap'  => 0,\n\t\t\t\t],\n\t\t\t\t'service'   => 'custom',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\n\t\t$this->assertNotNull( $post );\n\t\t$this->assertSame( 'Vazir Regular 2', $post->post_title );\n\t\t$this->assertSame( 'publish', $post->post_status );\n\t\t$this->assertSame(\n\t\t\t'{\"family\":\"Vazir Regular 2\",\"fallbacks\":[\"sans-serif\"],\"weights\":[400],\"styles\":[\"regular\"],\"variants\":[[0,400]],\"metrics\":{\"upm\":2048,\"asc\":2200,\"des\":-1100,\"tAsc\":2200,\"tDes\":-1100,\"tLGap\":0,\"wAsc\":2200,\"wDes\":1100,\"xH\":1082,\"capH\":1638,\"yMin\":-1116,\"yMax\":2163,\"hAsc\":2200,\"hDes\":-1100,\"lGap\":0},\"url\":\"https:\\/\\/cdn.jsdelivr.net\\/gh\\/rastikerdar\\/vazir-font@v30.1.0\\/dist\\/Vazir-Regular.ttf\"}',\n\t\t\t$post->post_content\n\t\t);\n\t}\n\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::prepare_item_for_database\n\t * @covers ::font_exists\n\t */\n\tpublic function test_create_item_duplicate(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/fonts' );\n\n\t\t$request->set_param( 'family', 'VaZiR ReGuLaR' );\n\t\t$request->set_param( 'fallbacks', [ 'sans-serif' ] );\n\t\t$request->set_param( 'weights', [ 400 ] );\n\t\t$request->set_param( 'styles', [ 'regular' ] );\n\t\t$request->set_param( 'variants', [ [ 0, 400 ] ] );\n\t\t$request->set_param( 'url', 'https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v30.1.0/dist/Vazir-Regular.ttf' );\n\t\t$request->set_param(\n\t\t\t'metrics',\n\t\t\t[\n\t\t\t\t'upm'   => 2048,\n\t\t\t\t'asc'   => 2200,\n\t\t\t\t'des'   => - 1100,\n\t\t\t\t'tAsc'  => 2200,\n\t\t\t\t'tDes'  => - 1100,\n\t\t\t\t'tLGap' => 0,\n\t\t\t\t'wAsc'  => 2200,\n\t\t\t\t'wDes'  => 1100,\n\t\t\t\t'xH'    => 1082,\n\t\t\t\t'capH'  => 1638,\n\t\t\t\t'yMin'  => - 1116,\n\t\t\t\t'yMax'  => 2163,\n\t\t\t\t'hAsc'  => 2200,\n\t\t\t\t'hDes'  => - 1100,\n\t\t\t\t'lGap'  => 0,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_field', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::delete_item\n\t */\n\tpublic function test_delete_item(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$post_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Font_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_title'   => 'Vazir Regular 3',\n\t\t\t\t'post_content' => '{\"family\":\"Vazir Regular 3\",\"fallbacks\":[\"sans-serif\"],\"weights\":[400],\"styles\":[\"regular\"],\"variants\":[[0,400]],\"url\":\"https:\\/\\/cdn.jsdelivr.net\\/gh\\/rastikerdar\\/vazir-font@v30.1.0\\/dist\\/Vazir-Regular.ttf\",\"service\":\"custom\",\"metrics\":{\"upm\":2048,\"asc\":2200,\"des\":-1100,\"tAsc\":2200,\"tDes\":-1100,\"tLGap\":0,\"wAsc\":2200,\"wDes\":1100,\"xH\":1082,\"capH\":1638,\"yMin\":-1116,\"yMax\":2163,\"hAsc\":2200,\"hDes\":-1100,\"lGap\":0}}',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post_id );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/fonts/' . $post_id );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertSame( 200, $response->get_status() );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'deleted', $data );\n\t\t$this->assertTrue( $data['deleted'] );\n\t\t$this->assertNull( get_post( $post_id ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Hotlinking_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Media\\Types;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Hotlinking_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Hotlinking_Controller\n */\nclass Hotlinking_Controller extends DependencyInjectedRestTestCase {\n\tpublic const URL_INVALID      = 'https://https://invalid.commmm';\n\tpublic const URL_404          = 'https://example.com/404/test.jpg';\n\tpublic const URL_500          = 'https://example.com/500/test.jpg';\n\tpublic const URL_SVG          = 'https://example.com/test.svg';\n\tpublic const URL_VALID        = 'http://example.com/test.jpg';\n\tpublic const URL_DOMAIN       = 'http://google.com';\n\tpublic const URL_WITH_CHARSET = 'https://example.com/test.png';\n\tpublic const URL_PATH         = '/test.jpg';\n\n\tpublic const REST_URL = '/web-stories/v1/hotlink/validate';\n\n\tprotected static int $subscriber;\n\tprotected static int $editor;\n\n\t/**\n\t * Count of the number of requests attempted.\n\t */\n\tprotected int $request_count = 0;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Hotlinking_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );\n\t\t$this->request_count = 0;\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Hotlinking_Controller::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_http_request' ] );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Intercept link processing requests and mock responses.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param mixed  $r       HTTP request arguments.\n\t * @param string $url     The request URL.\n\t * @return mixed|WP_Error Response data.\n\t */\n\tpublic function mock_http_request( $preempt, $r, string $url ) {\n\t\t++$this->request_count;\n\n\t\tif ( false !== strpos( $url, self::URL_INVALID ) ) {\n\t\t\treturn $preempt;\n\t\t}\n\n\t\t// URL_VALID\n\t\tif ( self::URL_VALID === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'image/jpeg',\n\t\t\t\t\t'content-length' => 5000,\n\t\t\t\t],\n\t\t\t\t'response' => [ 'code' => 200 ],\n\t\t\t];\n\t\t}\n\n\t\tif ( self::URL_SVG === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'image/svg+xml',\n\t\t\t\t\t'content-length' => 5000,\n\t\t\t\t],\n\t\t\t\t'response' => [ 'code' => 200 ],\n\t\t\t];\n\t\t}\n\n\t\tif ( self::URL_WITH_CHARSET === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'image/png; charset=utf-8',\n\t\t\t\t\t'content-length' => 1000,\n\t\t\t\t],\n\t\t\t\t'response' => [ 'code' => 200 ],\n\t\t\t];\n\t\t}\n\n\t\tif ( self::URL_404 === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'image/jpeg',\n\t\t\t\t\t'content-length' => 5000,\n\t\t\t\t],\n\t\t\t\t'response' => [ 'code' => 404 ],\n\t\t\t];\n\t\t}\n\n\t\t// URL_500\n\t\tif ( self::URL_500 === $url ) {\n\t\t\treturn [\n\t\t\t\t'headers'  => [\n\t\t\t\t\t'content-type'   => 'image/jpeg',\n\t\t\t\t\t'content-length' => 5000,\n\t\t\t\t],\n\t\t\t\t'response' => [ 'code' => 500 ],\n\t\t\t];\n\t\t}\n\n\t\treturn $preempt;\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->controller->register();\n\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( self::REST_URL, $routes );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url(): void {\n\t\t$result = $this->controller->validate_callback( self::URL_VALID );\n\t\t$this->assertTrue( $result );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url_empty(): void {\n\t\t$result = $this->controller->validate_callback( '' );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $result, 400 );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url_domain(): void {\n\t\t$result = $this->controller->validate_callback( self::URL_DOMAIN );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $result, 400 );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url_path(): void {\n\t\t$result = $this->controller->validate_callback( self::URL_PATH );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $result, 400 );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url_invalid(): void {\n\t\t$result = $this->controller->validate_callback( '-1' );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $result, 400 );\n\t}\n\n\t/**\n\t * @covers ::validate_callback\n\t */\n\tpublic function test_validate_url_invalid2(): void {\n\t\t$result = $this->controller->validate_callback( 'wibble' );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $result, 400 );\n\t}\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$data = $this->controller->get_item_schema();\n\n\t\t$properties = $data['properties'];\n\t\t$this->assertArrayHasKey( 'ext', $properties );\n\t\t$this->assertArrayHasKey( 'file_name', $properties );\n\t\t$this->assertArrayHasKey( 'file_size', $properties );\n\t\t$this->assertArrayHasKey( 'mime_type', $properties );\n\t\t$this->assertArrayHasKey( 'type', $properties );\n\t\t$this->assertArrayHasKey( 'enum', $properties['type'] );\n\t\t$this->assertEqualSets( [ 'audio', 'image', 'video', 'caption' ], $properties['type']['enum'] );\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_without_permission(): void {\n\t\t$this->controller->register();\n\n\t\t// Test without a login.\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 401, $response->get_status() );\n\n\t\t// Test with a user that does not have edit_posts capability.\n\t\twp_set_current_user( self::$subscriber );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 403, $response->get_status() );\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 'rest_forbidden', $data['code'] );\n\t}\n\n\tpublic function test_url_invalid_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_INVALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertEquals( 400, $response->get_status() );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 'rest_invalid_param', $data['code'] );\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_empty_string(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', '' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertTrue( $response->is_error() );\n\t\t$this->assertEquals( 400, $response->get_status() );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 'rest_invalid_param', $data['code'] );\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'ext'       => 'jpg',\n\t\t\t\t'file_name' => 'test.jpg',\n\t\t\t\t'file_size' => 5000,\n\t\t\t\t'mime_type' => 'image/jpeg',\n\t\t\t\t'type'      => 'image',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_cache(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertEquals( 1, $this->request_count );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'ext'       => 'jpg',\n\t\t\t\t'file_name' => 'test.jpg',\n\t\t\t\t'file_size' => 5000,\n\t\t\t\t'mime_type' => 'image/jpeg',\n\t\t\t\t'type'      => 'image',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertEquals( 1, $this->request_count );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'ext'       => 'jpg',\n\t\t\t\t'file_name' => 'test.jpg',\n\t\t\t\t'file_size' => 5000,\n\t\t\t\t'mime_type' => 'image/jpeg',\n\t\t\t\t'type'      => 'image',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_404(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_404 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_500(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_500 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $response, 404 );\n\t}\n\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t * @covers ::prepare_item_for_response\n\t */\n\tpublic function test_parse_url_svg(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_SVG );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_invalid_ext', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::parse_url\n\t * @covers ::parse_url_permissions_check\n\t */\n\tpublic function test_parse_url_with_charset_in_content_type_header(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, self::REST_URL );\n\t\t$request->set_param( 'url', self::URL_WITH_CHARSET );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'ext'       => 'png',\n\t\t\t\t'file_name' => 'test.png',\n\t\t\t\t'file_size' => 1000,\n\t\t\t\t'mime_type' => 'image/png',\n\t\t\t\t'type'      => 'image',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_allowed_mime_types\n\t */\n\tpublic function test_get_allowed_mime_types(): void {\n\t\t$story_post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$types           = $this->injector->make( Types::class );\n\t\t$controller      = new \\Google\\Web_Stories\\REST_API\\Hotlinking_Controller( $story_post_type, $types );\n\t\t$mime_types      = $this->call_private_method( [ $controller, 'get_allowed_mime_types' ] );\n\t\t$this->assertIsArray( $mime_types );\n\t\t$this->assertArrayHasKey( 'audio', $mime_types );\n\t\t$this->assertArrayHasKey( 'video', $mime_types );\n\t\t$this->assertArrayHasKey( 'caption', $mime_types );\n\t\t$this->assertSame( 'text/vtt', $mime_types['caption'][0] );\n\t}\n\n\t/**\n\t * Test that validate_url validates URLs.\n\t *\n\t * @param string         $url            The URL to validate.\n\t * @param false|callable $cb_safe_ports  The name of the callback to http_allowed_safe_ports or false if none.\n\t *                                       Default false.\n\t *\n\t * @dataProvider data_validate_url_should_validate\n\t * @covers ::validate_url\n\t */\n\tpublic function test_validate_url_should_validate( string $url, $cb_safe_ports = false ): void {\n\t\tif ( $cb_safe_ports ) {\n\t\t\tadd_filter( 'http_allowed_safe_ports', $cb_safe_ports );\n\t\t}\n\n\t\t$this->assertNotFalse( $this->call_private_method( [ $this->controller, 'validate_url' ], [ $url ] ) );\n\t}\n\n\t/**\n\t * Data provider.\n\t *\n\t * @return array<string, array{url: string, cb_safe_ports?: callable}>\n\t */\n\tpublic static function data_validate_url_should_validate(): array {\n\t\treturn [\n\t\t\t'no port specified'                 => [\n\t\t\t\t'url' => 'http://example.com/caniload.php',\n\t\t\t],\n\t\t\t'a port considered safe by default' => [\n\t\t\t\t'url' => 'https://example.com:8080/caniload.php',\n\t\t\t],\n\t\t\t'a port considered safe by filter'  => [\n\t\t\t\t'url'           => 'https://example.com:81/caniload.php',\n\t\t\t\t'cb_safe_ports' => [ self::class, 'callback_custom_safe_ports' ],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Tests that validate_url validates a url that uses an unsafe port\n\t * but which matches the host and port used by the site's home url.\n\t *\n\t * @covers ::validate_url\n\t */\n\tpublic function test_validate_url_should_validate_with_an_unsafe_port_when_the_host_and_port_match_the_home_url(): void {\n\t\t/**\n\t\t * Home URL.\n\t\t *\n\t\t * @var string\n\t\t */\n\t\t$original_home = get_option( 'home' );\n\t\t$home_parsed   = wp_parse_url( $original_home );\n\t\t$this->assertIsArray( $home_parsed );\n\t\t$home_scheme_host = implode( '://', \\array_slice( $home_parsed, 0, 2 ) );\n\t\t$home_modified    = $home_scheme_host . ':83';\n\n\t\tupdate_option( 'home', $home_modified );\n\n\t\t$url = $home_modified . '/caniload.php';\n\n\t\t$actual = $this->call_private_method( [ $this->controller, 'validate_url' ], [ $url ] );\n\n\t\tupdate_option( 'home', $original_home );\n\n\t\t$this->assertSame( $url, $actual );\n\t}\n\n\t/**\n\t * Test that validate_url does not validate invalid URLs.\n\t *\n\t * @param string       $url            The URL to validate.\n\t * @param false|callable $cb_safe_ports  The name of the callback to http_allowed_safe_ports or false if none.\n\t *                                     Default false.\n\t * @param bool         $external_host  Whether or not the host is external.\n\t *                                     Default false.\n\t *\n\t * @dataProvider data_validate_url_should_not_validate\n\t * @covers ::validate_url\n\t */\n\tpublic function test_validate_url_should_not_validate( string $url, $cb_safe_ports = false, bool $external_host = false ): void {\n\t\tif ( $external_host ) {\n\t\t\tadd_filter( 'http_request_host_is_external', '__return_true' );\n\t\t}\n\n\t\tif ( $cb_safe_ports ) {\n\t\t\tadd_filter( 'http_allowed_safe_ports', $cb_safe_ports );\n\t\t}\n\n\t\t$this->assertFalse( $this->call_private_method( [ $this->controller, 'validate_url' ], [ $url ] ) );\n\t}\n\n\t/**\n\t * Data provider.\n\t *\n\t * @return array<string, array{url: string, cb_safe_ports?: callable}>\n\t */\n\tpublic static function data_validate_url_should_not_validate(): array {\n\t\treturn [\n\t\t\t'url as string 0'                              => [\n\t\t\t\t'url' => '0',\n\t\t\t],\n\t\t\t'url as string 1'                              => [\n\t\t\t\t'url' => '1',\n\t\t\t],\n\t\t\t'an empty url'                                 => [\n\t\t\t\t'url' => '',\n\t\t\t],\n\t\t\t'a url with a non-http/https protocol'         => [\n\t\t\t\t'url' => 'ftp://example.com:81/caniload.php',\n\t\t\t],\n\t\t\t'a malformed url'                              => [\n\t\t\t\t'url' => 'http:///example.com:81/caniload.php',\n\t\t\t],\n\t\t\t'a host that cannot be parsed'                 => [\n\t\t\t\t'url' => 'http:example.com/caniload.php',\n\t\t\t],\n\t\t\t'login information'                            => [\n\t\t\t\t'url' => 'http://user:pass@example.com/caniload.php',\n\t\t\t],\n\t\t\t'a host with invalid characters'               => [\n\t\t\t\t'url' => 'http://[exam]ple.com/caniload.php',\n\t\t\t],\n\t\t\t'a host whose IPv4 address cannot be resolved' => [\n\t\t\t\t'url' => 'http://idonotexist.local/caniload.php',\n\t\t\t],\n\t\t\t'an external request when not allowed'         => [\n\t\t\t\t'url' => 'http://192.168.0.1/caniload.php',\n\t\t\t],\n\t\t\t'a request with disallowed link-local ip'      => [\n\t\t\t\t'url' => 'http://169.254.0.0/caniload.php',\n\t\t\t],\n\t\t\t'a port not considered safe by default'        => [\n\t\t\t\t'url' => 'https://example.com:81/caniload.php',\n\t\t\t],\n\t\t\t'a port not considered safe by filter'         => [\n\t\t\t\t'url'           => 'https://example.com:82/caniload.php',\n\t\t\t\t'cb_safe_ports' => [ self::class, 'callback_custom_safe_ports' ],\n\t\t\t],\n\t\t\t'all safe ports removed by filter'             => [\n\t\t\t\t'url'           => 'https://example.com:81/caniload.php',\n\t\t\t\t'cb_safe_ports' => [ self::class, 'callback_remove_safe_ports' ],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @return array<int>\n\t */\n\tpublic static function callback_custom_safe_ports(): array {\n\t\treturn [ 81, 444, 8081 ];\n\t}\n\n\t/**\n\t * @return array<int>\n\t */\n\tpublic static function callback_remove_safe_ports(): array {\n\t\treturn [];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Link_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_Error;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Link_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Link_Controller\n */\nclass Link_Controller extends DependencyInjectedRestTestCase {\n\n\tpublic const URL_INVALID             = 'https://https://invalid.commmm';\n\tpublic const URL_404                 = 'https://example.com/404';\n\tpublic const URL_500                 = 'https://example.com/500';\n\tpublic const URL_CHARACTERS          = 'https://example.com/characters';\n\tpublic const URL_EMPTY_DOCUMENT      = 'https://example.com/empty';\n\tpublic const URL_VALID_TITLE_ONLY    = 'https://example.com';\n\tpublic const URL_VALID               = 'https://amp.dev';\n\tpublic const URL_INSTAGRAM           = 'https://www.instagram.com/googleforcreators';\n\tpublic const URL_INSTAGRAM_SINGLE    = 'https://www.instagram.com/p/CZwz48cFoQM';\n\tpublic const URL_INSTAGRAM_SUBDOMAIN = 'https://about.instagram.com/about-us';\n\n\tprotected static int $editor;\n\tprotected static int $subscriber;\n\n\t/**\n\t * Count of the number of requests attempted.\n\t */\n\tprotected int $request_count = 0;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Link_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_http_request' ], 10, 3 );\n\t\t$this->request_count = 0;\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Link_Controller::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_http_request' ] );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * Intercept link processing requests and mock responses.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param mixed  $r       HTTP request arguments.\n\t * @param string $url     The request URL.\n\t * @return array{response: array<string, mixed>, body?: string}|WP_Error|mixed Response data.\n\t */\n\tpublic function mock_http_request( $preempt, $r, string $url ) {\n\t\t++$this->request_count;\n\n\t\tif ( false !== strpos( $url, self::URL_INVALID ) ) {\n\t\t\treturn $preempt;\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_404 ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 404,\n\t\t\t\t],\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_500 ) ) {\n\t\t\treturn new \\WP_Error( 'http_request_failed', 'A valid URL was not provided.' );\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_EMPTY_DOCUMENT ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => '<html></html>',\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_INSTAGRAM_SINGLE ) || false !== strpos( $url, self::URL_INSTAGRAM_SUBDOMAIN ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => '<html></html>',\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_CHARACTERS ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/characters.example.com.html' ),\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_VALID_TITLE_ONLY ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/example.com.html' ),\n\t\t\t];\n\t\t}\n\n\t\tif ( false !== strpos( $url, self::URL_VALID ) ) {\n\t\t\treturn [\n\t\t\t\t'response' => [\n\t\t\t\t\t'code' => 200,\n\t\t\t\t],\n\t\t\t\t'body'     => file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/amp.dev.html' ),\n\t\t\t];\n\t\t}\n\n\t\treturn $preempt;\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/link', $routes );\n\n\t\t$route = $routes['/web-stories/v1/link'];\n\t\t$this->assertCount( 1, $route );\n\t\t$this->assertArrayHasKey( 'callback', $route[0] );\n\t\t$this->assertArrayHasKey( 'permission_callback', $route[0] );\n\t\t$this->assertArrayHasKey( 'methods', $route[0] );\n\t\t$this->assertArrayHasKey( 'args', $route[0] );\n\t}\n\n\t/**\n\t * @covers ::parse_link_permissions_check\n\t */\n\tpublic function test_no_user(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 400, $response->get_status() );\n\t}\n\n\t/**\n\t * @covers ::parse_link_permissions_check\n\t */\n\tpublic function test_without_permission(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$subscriber );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 403, $response->get_status() );\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( $data['code'], 'rest_forbidden' );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_url_invalid_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_INVALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_url_returning_500(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_500 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_url', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_url_returning_404(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_404 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 200, $response->get_status() );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'title'       => '',\n\t\t\t\t'image'       => '',\n\t\t\t\t'description' => '',\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_url_empty_string(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', '' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 0, $this->request_count );\n\t\t$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_empty_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_EMPTY_DOCUMENT );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'       => '',\n\t\t\t'image'       => '',\n\t\t\t'description' => '',\n\t\t];\n\n\t\t// Subsequent requests is cached and so it should not cause a request.\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @param array{title: string, image: string, description: string} $expected\n\t *\n\t * @covers ::parse_link\n\t * @dataProvider data_instagram_urls\n\t */\n\tpublic function test_instagram_urls( string $url, array $expected, int $request_count ): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', $url );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t// Subsequent requests is cached and so it should not cause a request.\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( $request_count, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @return array<string,array{url: string, expected: array<string, string>, request_count: int}>\n\t */\n\tpublic static function data_instagram_urls(): array {\n\t\treturn [\n\t\t\t'Instagram profile url'                   => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM,\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => 'Instagram - @googleforcreators',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 0,\n\t\t\t],\n\t\t\t'Instagram profile url with slash'        => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM . '/',\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => 'Instagram - @googleforcreators',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 0,\n\t\t\t],\n\t\t\t'Instagram profile url with query string' => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM . '/?hl=en',\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => 'Instagram - @googleforcreators',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 0,\n\t\t\t],\n\t\t\t'Instagram profile url with longer query string' => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM . '/?hl=en&qs=2',\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => 'Instagram - @googleforcreators',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 0,\n\t\t\t],\n\t\t\t'Instagram profile url with double query string' => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM . '/?hl=en&qs=2?web=2',\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => 'Instagram - @googleforcreators',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 0,\n\t\t\t],\n\t\t\t'Instagram photo url'                     => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM_SINGLE,\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => '',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 1,\n\t\t\t],\n\t\t\t'Instagram subdomain'                     => [\n\t\t\t\t'url'           => self::URL_INSTAGRAM_SUBDOMAIN,\n\t\t\t\t'expected'      => [\n\t\t\t\t\t'title'       => '',\n\t\t\t\t\t'image'       => '',\n\t\t\t\t\t'description' => '',\n\t\t\t\t],\n\t\t\t\t'request_count' => 1,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_characters_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_CHARACTERS );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'       => 'Chizuru Kagura estará em The King of Fighters XV; novo trailer',\n\t\t\t'image'       => '',\n\t\t\t'description' => 'Com a revelação de Chizuru, foi revelado a segunda equipe: a “Team Sacred Treasures”, […]',\n\t\t];\n\n\t\t// Subsequent requests is cached and so it should not cause a request.\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_example_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_VALID_TITLE_ONLY );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'       => 'Example Domain',\n\t\t\t'image'       => '',\n\t\t\t'description' => '',\n\t\t];\n\n\t\t// Subsequent requests is cached and so it should not cause a request.\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_valid_url(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_VALID );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'       => 'AMP - a web component framework to easily create user-first web experiences - amp.dev',\n\t\t\t'image'       => 'https://amp.dev/static/img/sharing/default-600x314.png',\n\t\t\t'description' => 'Whether you are a publisher, e-commerce company, storyteller, advertiser or email sender, AMP makes it easy to create great experiences on the web. Use AMP to build websites, stories, ads and emails.',\n\t\t];\n\n\t\t// Subsequent requests is cached and so it should not cause a request.\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n\n\t/**\n\t * @covers ::parse_link\n\t */\n\tpublic function test_removes_trailing_slashes(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_VALID_TITLE_ONLY );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$expected = [\n\t\t\t'title'       => 'Example Domain',\n\t\t\t'image'       => '',\n\t\t\t'description' => '',\n\t\t];\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/link' );\n\t\t$request->set_param( 'url', self::URL_VALID_TITLE_ONLY . '/' );\n\n\t\trest_get_server()->dispatch( $request );\n\n\t\t$this->assertEquals( 1, $this->request_count );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertEqualSetsWithIndex( $expected, $data );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Page_Template_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse DateTime;\nuse Google\\Web_Stories\\Tests\\Integration\\RestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Page_Template_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Page_Template_Controller\n */\nclass Page_Template_Controller extends RestTestCase {\n\tprotected static int $user_id;\n\tprotected static int $user2_id;\n\tprotected static int $user3_id;\n\n\tprotected static int $author_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Page_Template_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\n\t\tself::$user2_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Jane Doe',\n\t\t\t]\n\t\t);\n\n\t\tself::$user3_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Zane Doe',\n\t\t\t]\n\t\t);\n\n\t\tself::$author_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t2,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user2_id,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t2,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user3_id,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = new \\Google\\Web_Stories\\REST_API\\Page_Template_Controller( 'post' );\n\t}\n\n\t/**\n\t * @covers ::get_collection_params\n\t */\n\tpublic function test_get_collection_params(): void {\n\t\t$actual = $this->controller->get_collection_params();\n\n\t\t$this->assertArrayHasKey( '_web_stories_envelope', $actual );\n\t}\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$actual = $this->controller->get_item_schema();\n\n\t\t$this->assertArrayNotHasKey( 'permalink_template', $actual['properties'] );\n\t\t$this->assertArrayNotHasKey( 'generated_slug', $actual['properties'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_format(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/wp/v2/posts' );\n\t\t$request->set_param( 'status', [ 'draft' ] );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$request->set_param( 'page', '1' );\n\t\t$request->set_param( '_web_stories_envelope', true );\n\n\t\t$response = $this->controller->get_items( $request );\n\n\t\t$this->assertNotWPError( $response );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'headers', $data );\n\t\t$this->assertArrayHasKey( 'body', $data );\n\t\t$this->assertArrayHasKey( 'status', $data );\n\n\t\t$this->assertEquals( 3, $data['headers']['X-WP-Total'] );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_as_author_should_not_strip_markup(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$this->kses_int();\n\n\t\t$unsanitized_story_data = json_decode( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_filtered.json' ), true );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story-page' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'story_data' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$new_data = $response->get_data();\n\n\t\t$this->assertIsArray( $new_data );\n\t\t$this->assertArrayHasKey( 'story_data', $new_data );\n\t\t$this->assertSame( $unsanitized_story_data, $new_data['story_data'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Products_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse Google\\Web_Stories\\Tests\\Integration\\Mock_Vendor_Setup;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Products_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Products_Controller\n */\nclass Products_Controller extends DependencyInjectedRestTestCase {\n\tuse Mock_Vendor_Setup;\n\n\tprotected static int $editor;\n\tprotected static int $subscriber;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Products_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\t\tupdate_option( Settings::SETTING_NAME_SHOPPING_PROVIDER, 'mock' );\n\t\t$this->setup_vendors();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Products_Controller::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_SHOPPING_PROVIDER );\n\t\t$this->remove_vendors();\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->controller->register();\n\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/products', $routes );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_no_user(): void {\n\t\t$this->controller->register();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_without_permission(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$subscriber );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 403 );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_permission(): void {\n\t\t$this->controller->register();\n\n\t\t$per_page = 10;\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$request->set_param( 'per_page', $per_page );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( $per_page, $data );\n\n\t\tforeach ( $data as $product ) {\n\t\t\t$this->assertIsArray( $product );\n\t\t\t$this->assertArrayHasKey( 'productId', $product );\n\t\t\t$this->assertArrayHasKey( 'productTitle', $product );\n\t\t\t$this->assertArrayHasKey( 'productBrand', $product );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_fields_for_response\n\t * @covers ::get_items\n\t */\n\tpublic function test_fields(): void {\n\t\t$this->controller->register();\n\n\t\t$per_page = 10;\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$request->set_param( '_fields', 'productId' );\n\t\t$request->set_param( 'per_page', $per_page );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( $per_page, $data );\n\n\t\tforeach ( $data as $product ) {\n\t\t\t$this->assertIsArray( $product );\n\t\t\t$this->assertArrayHasKey( 'productId', $product );\n\t\t\t$this->assertArrayNotHasKey( 'productTitle', $product );\n\t\t\t$this->assertArrayNotHasKey( 'productBrand', $product );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_return_error(): void {\n\t\t$this->controller->register();\n\t\tupdate_option( Settings::SETTING_NAME_SHOPPING_PROVIDER, 'error' );\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\n\t\t$this->assertErrorResponse( 'mock_error', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_return_none(): void {\n\t\t$this->controller->register();\n\t\tupdate_option( Settings::SETTING_NAME_SHOPPING_PROVIDER, 'none' );\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_shopping_provider', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_json_schema_validation(): void {\n\t\t$this->controller->register();\n\t\t$per_page = 10;\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/products' );\n\t\t$request->set_param( 'search', 'test' );\n\t\t$request->set_param( 'per_page', $per_page );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( $per_page, $data );\n\n\t\tforeach ( $data as $product ) {\n\t\t\t$this->assertIsArray( $product );\n\t\t\t$this->assertMatchesProductSchema( $product );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Publisher_Logos_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Publisher_Logos_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Publisher_Logos_Controller\n */\nclass Publisher_Logos_Controller extends DependencyInjectedRestTestCase {\n\tprotected static int $admin;\n\n\tprotected static int $editor;\n\n\tprotected static int $attachment_id_1;\n\n\tprotected static int $attachment_id_2;\n\n\tprotected WP_REST_Server $server;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Publisher_Logos_Controller $controller;\n\n\t/**\n\t * Count of the number of requests attempted.\n\t */\n\tprotected int $request_count = 0;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\tself::$editor = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $attachment_id_1\n\t\t */\n\t\t$attachment_id_1 = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tself::$attachment_id_1 = $attachment_id_1;\n\n\t\t/**\n\t\t * @var int $attachment_id_2\n\t\t */\n\t\t$attachment_id_2 = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tself::$attachment_id_2 = $attachment_id_2;\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Publisher_Logos_Controller::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\t\tdelete_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register_routes\n\t */\n\tpublic function test_register_routes(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/publisher-logos', $routes );\n\n\t\t$route = $routes['/web-stories/v1/publisher-logos'];\n\t\t$this->assertArrayHasKey( 'callback', $route[0] );\n\t\t$this->assertArrayHasKey( 'permission_callback', $route[0] );\n\t\t$this->assertArrayHasKey( 'methods', $route[0] );\n\t\t$this->assertArrayHasKey( 'args', $route[0] );\n\t\t$this->assertArrayHasKey( 'callback', $route[1] );\n\t\t$this->assertArrayHasKey( 'permission_callback', $route[1] );\n\t\t$this->assertArrayHasKey( 'methods', $route[1] );\n\t\t$this->assertArrayHasKey( 'args', $route[1] );\n\t}\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$data = $this->controller->get_item_schema();\n\n\t\t$properties = $data['properties'];\n\n\t\t$this->assertIsArray( $properties );\n\t\t$this->assertArrayHasKey( 'id', $properties );\n\t\t$this->assertArrayHasKey( 'title', $properties );\n\t\t$this->assertArrayHasKey( 'url', $properties );\n\t\t$this->assertArrayHasKey( 'active', $properties );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t */\n\tpublic function test_get_items_no_permission(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/publisher-logos' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_no_items(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/publisher-logos' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertSame( [], $data );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_editor(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/publisher-logos' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertSame( [], $data );\n\t}\n\n\t/**\n\t * @covers ::prepare_item_for_response\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_2, 0, -1, PHP_INT_MAX, self::$attachment_id_1 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/publisher-logos' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 2, $data );\n\t\t$this->assertIsArray( $data[0] );\n\t\t$this->assertIsArray( $data[1] );\n\t\t$this->assertSame( self::$attachment_id_1, $data[0]['id'] );\n\t\t$this->assertSame( get_the_title( self::$attachment_id_1 ), $data[0]['title'] );\n\t\t$this->assertSame( wp_get_attachment_url( self::$attachment_id_1 ), $data[0]['url'] );\n\t\t$this->assertTrue( $data[0]['active'] );\n\t\t$this->assertSame( self::$attachment_id_2, $data[1]['id'] );\n\t\t$this->assertSame( get_the_title( self::$attachment_id_2 ), $data[1]['title'] );\n\t\t$this->assertSame( wp_get_attachment_url( self::$attachment_id_2 ), $data[1]['url'] );\n\t\t$this->assertFalse( $data[1]['active'] );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t */\n\tpublic function test_create_item_no_permission(): void {\n\t\t$this->controller->register();\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => self::$attachment_id_1,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_editor(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => self::$attachment_id_1,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'     => self::$attachment_id_1,\n\t\t\t\t'title'  => get_the_title( self::$attachment_id_1 ),\n\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_1 ),\n\t\t\t\t'active' => true,\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => self::$attachment_id_1,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'     => self::$attachment_id_1,\n\t\t\t\t'title'  => get_the_title( self::$attachment_id_1 ),\n\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_1 ),\n\t\t\t\t'active' => true,\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_1 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_1, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_existing_ones(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => self::$attachment_id_2,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'     => self::$attachment_id_2,\n\t\t\t\t'title'  => get_the_title( self::$attachment_id_2 ),\n\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_2 ),\n\t\t\t\t'active' => false,\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_1, self::$attachment_id_2 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_1, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_multiple(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => [ self::$attachment_id_1, self::$attachment_id_2 ],\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t[\n\t\t\t\t\t'id'     => self::$attachment_id_1,\n\t\t\t\t\t'title'  => get_the_title( self::$attachment_id_1 ),\n\t\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_1 ),\n\t\t\t\t\t'active' => true,\n\t\t\t\t\t'_links' => [\n\t\t\t\t\t\t'self'       => [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'href' => rest_url( 'web-stories/v1/publisher-logos/' . self::$attachment_id_1 ),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'collection' => [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'href' => rest_url( 'web-stories/v1/publisher-logos' ),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t[\n\t\t\t\t\t'id'     => self::$attachment_id_2,\n\t\t\t\t\t'title'  => get_the_title( self::$attachment_id_2 ),\n\t\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_2 ),\n\t\t\t\t\t'active' => false,\n\t\t\t\t\t'_links' => [\n\t\t\t\t\t\t'self'       => [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'href' => rest_url( 'web-stories/v1/publisher-logos/' . self::$attachment_id_2 ),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'collection' => [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'href' => rest_url( 'web-stories/v1/publisher-logos' ),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_1, self::$attachment_id_2 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_1, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_empty_array(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => [],\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_id', $response );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_updates_incorrect_active_publisher_logo(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, 0 );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'id' => self::$attachment_id_2,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'     => self::$attachment_id_2,\n\t\t\t\t'title'  => get_the_title( self::$attachment_id_2 ),\n\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_2 ),\n\t\t\t\t'active' => true,\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_1, self::$attachment_id_2 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_2, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t */\n\tpublic function test_delete_item_no_permission(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_1 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::delete_item\n\t */\n\tpublic function test_delete_item_editor(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1, self::$attachment_id_2 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_2 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'deleted'  => true,\n\t\t\t\t'previous' => [\n\t\t\t\t\t'id'     => self::$attachment_id_2,\n\t\t\t\t\t'title'  => get_the_title( self::$attachment_id_2 ),\n\t\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_2 ),\n\t\t\t\t\t'active' => false,\n\t\t\t\t],\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::delete_item\n\t */\n\tpublic function test_delete_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1, self::$attachment_id_2 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_1 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'deleted'  => true,\n\t\t\t\t'previous' => [\n\t\t\t\t\t'id'     => self::$attachment_id_1,\n\t\t\t\t\t'title'  => get_the_title( self::$attachment_id_1 ),\n\t\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_1 ),\n\t\t\t\t\t'active' => true,\n\t\t\t\t],\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_2 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_2, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::delete_item\n\t */\n\tpublic function test_delete_item_incorrect_active_publisher_logo(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1, self::$attachment_id_2 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, 0 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_1 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int[] $publisher_logos\n\t\t */\n\t\t$publisher_logos = get_option( Settings::SETTING_NAME_PUBLISHER_LOGOS );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'deleted'  => true,\n\t\t\t\t'previous' => [\n\t\t\t\t\t'id'     => self::$attachment_id_1,\n\t\t\t\t\t'title'  => get_the_title( self::$attachment_id_1 ),\n\t\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_1 ),\n\t\t\t\t\t'active' => false,\n\t\t\t\t],\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertEqualSets( [ self::$attachment_id_2 ], $publisher_logos );\n\t\t$this->assertSame( self::$attachment_id_2, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::delete_item\n\t */\n\tpublic function test_delete_item_non_existent_logo(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::DELETABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_2 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_id', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t */\n\tpublic function test_update_item_no_permission(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_1 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::permissions_check\n\t * @covers ::update_item\n\t */\n\tpublic function test_update_item_editor(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1, self::$attachment_id_2 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_2 );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'active' => true,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 403 );\n\t\t$this->assertSame( self::$attachment_id_1, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::update_item_permissions_check\n\t * @covers ::update_item\n\t */\n\tpublic function test_update_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1, self::$attachment_id_2 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_2 );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'active' => true,\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t/**\n\t\t * @var int $active_publisher_logo_id\n\t\t */\n\t\t$active_publisher_logo_id = get_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO );\n\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'     => self::$attachment_id_2,\n\t\t\t\t'title'  => get_the_title( self::$attachment_id_2 ),\n\t\t\t\t'url'    => wp_get_attachment_url( self::$attachment_id_2 ),\n\t\t\t\t'active' => true,\n\t\t\t],\n\t\t\t$data\n\t\t);\n\t\t$this->assertSame( self::$attachment_id_2, $active_publisher_logo_id );\n\t}\n\n\t/**\n\t * @covers ::update_item_permissions_check\n\t * @covers ::update_item\n\t */\n\tpublic function test_update_item_non_existent_logo(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$admin );\n\n\t\tupdate_option( Settings::SETTING_NAME_PUBLISHER_LOGOS, [ self::$attachment_id_1 ] );\n\t\tupdate_option( Settings::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, self::$attachment_id_1 );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::CREATABLE, '/web-stories/v1/publisher-logos/' . self::$attachment_id_2 );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_invalid_id', $response, 400 );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Status_Check_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Status_Check_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Status_Check_Controller\n */\nclass Status_Check_Controller extends DependencyInjectedRestTestCase {\n\n\tprotected static int $editor;\n\tprotected static int $subscriber;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Status_Check_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Status_Check_Controller::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->controller->register();\n\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/status-check', $routes );\n\t}\n\n\t/**\n\t * @covers ::status_check_permissions_check\n\t * @covers ::status_check\n\t */\n\tpublic function test_no_user(): void {\n\t\t$this->controller->register();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/status-check' );\n\t\t$request->set_param( 'content', '<a href=\"#\">Test</a>' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::status_check_permissions_check\n\t * @covers ::status_check\n\t */\n\tpublic function test_without_permission(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$subscriber );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/status-check' );\n\t\t$request->set_param( 'content', '<a href=\"#\">Test</a>' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_forbidden', $response, 403 );\n\t}\n\n\t/**\n\t * @covers ::status_check_permissions_check\n\t * @covers ::status_check\n\t */\n\tpublic function test_status_check(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/status-check' );\n\t\t$request->set_param( 'content', '<a href=\"#\">Test</a>' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertEquals( 200, $response->get_status() );\n\t\t$data = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'success', $data );\n\t\t$this->assertTrue( $data['success'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Autosaves_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Stories_Autosaves_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Autosaves_Controller\n */\nclass Stories_Autosaves_Controller extends DependencyInjectedRestTestCase {\n\n\t/**\n\t * Author user ID.\n\t */\n\tprotected static int $author_id;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$author_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function test_create_item_as_author_should_not_strip_markup(): void {\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$this->kses_int();\n\n\t\t$unsanitized_content    = (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = json_decode( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_filtered.json' ), true );\n\t\t$sanitized_content      = trim( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_sanitized.html' ) );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story/' . $story . '/autosaves' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'content'    => $unsanitized_content,\n\t\t\t\t'story_data' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$new_data = $response->get_data();\n\n\t\t$this->assertIsArray( $new_data );\n\t\t$this->assertArrayHasKey( 'content', $new_data );\n\t\t$this->assertEquals( $sanitized_content, trim( $new_data['content']['raw'] ) );\n\t\t$this->assertEquals( $unsanitized_story_data, $new_data['story_data'] );\n\n\t\t$this->kses_remove_filters();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse DateTime;\nuse Google\\Web_Stories\\Media\\Image_Sizes;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Stories_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Controller\n */\nclass Stories_Controller extends DependencyInjectedRestTestCase {\n\n\tprotected static int $user_id;\n\tprotected static int $user2_id;\n\tprotected static int $user3_id;\n\n\tprotected static int $author_id;\n\tprotected static int $contributor_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Stories_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\n\t\tself::$user2_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Jane Doe',\n\t\t\t]\n\t\t);\n\n\t\tself::$user3_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Zane Doe',\n\t\t\t]\n\t\t);\n\n\t\tself::$author_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\n\t\tself::$contributor_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'contributor',\n\t\t\t]\n\t\t);\n\n\t\t$post_type = Story_Post_Type::POST_TYPE_SLUG;\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t2,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user2_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t2,\n\t\t\t[\n\t\t\t\t'post_status' => 'pending',\n\t\t\t\t'post_author' => self::$user3_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t2,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user3_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$story_post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$story_post_type->register();\n\t\t$this->controller = new \\Google\\Web_Stories\\REST_API\\Stories_Controller( Story_Post_Type::POST_TYPE_SLUG );\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->kses_remove_filters();\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register_routes\n\t */\n\tpublic function test_register_routes(): void {\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/web-story', $routes );\n\t\t$this->assertCount( 2, $routes['/web-stories/v1/web-story'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::add_response_headers\n\t */\n\tpublic function test_get_items(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'status', [ 'draft' ] );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$headers  = $response->get_headers();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalByStatus', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-Total', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalPages', $headers );\n\n\t\t$statuses = json_decode( $headers['X-WP-TotalByStatus'], true );\n\n\t\t$this->assertIsArray( $statuses );\n\t\t$this->assertArrayHasKey( 'all', $statuses );\n\t\t$this->assertArrayHasKey( 'publish', $statuses );\n\t\t$this->assertArrayHasKey( 'pending', $statuses );\n\t\t$this->assertArrayHasKey( 'draft', $statuses );\n\t\t$this->assertArrayHasKey( 'future', $statuses );\n\t\t$this->assertArrayHasKey( 'private', $statuses );\n\n\t\t$this->assertSame( 15, $statuses['all'] );\n\t\t$this->assertSame( 7, $statuses['publish'] );\n\t\t$this->assertSame( 2, $statuses['pending'] );\n\t\t$this->assertSame( 3, $statuses['future'] );\n\t\t$this->assertSame( 3, $statuses['draft'] );\n\t\t$this->assertSame( 0, $statuses['private'] );\n\n\t\t$this->assertSame( '3', $headers['X-WP-Total'] );\n\t\t$this->assertSame( '1', $headers['X-WP-TotalPages'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_no_permission(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$headers  = $response->get_headers();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertArrayNotHasKey( 'X-WP-TotalByStatus', $headers );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::add_response_headers\n\t */\n\tpublic function test_get_items_contributor(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$contributor_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$headers  = $response->get_headers();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalByStatus', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-Total', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalPages', $headers );\n\n\t\t$statuses = json_decode( $headers['X-WP-TotalByStatus'], true );\n\n\t\t$this->assertIsArray( $statuses );\n\t\t$this->assertArrayHasKey( 'all', $statuses );\n\t\t$this->assertArrayHasKey( 'publish', $statuses );\n\t\t$this->assertArrayHasKey( 'pending', $statuses );\n\t\t$this->assertArrayHasKey( 'draft', $statuses );\n\t\t$this->assertArrayHasKey( 'future', $statuses );\n\t\t$this->assertArrayNotHasKey( 'private', $statuses );\n\n\t\t$this->assertSame( 7, $statuses['all'] );\n\t\t$this->assertSame( 7, $statuses['publish'] );\n\t\t$this->assertSame( 0, $statuses['future'] );\n\t\t$this->assertSame( 0, $statuses['draft'] );\n\n\t\t$this->assertSame( '7', $headers['X-WP-Total'] );\n\t\t$this->assertSame( '1', $headers['X-WP-TotalPages'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::add_response_headers\n\t */\n\tpublic function test_get_items_author(): void {\n\t\twp_set_current_user( self::$author_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$headers  = $response->get_headers();\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalByStatus', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-Total', $headers );\n\t\t$this->assertArrayHasKey( 'X-WP-TotalPages', $headers );\n\n\t\t$statuses = json_decode( $headers['X-WP-TotalByStatus'], true );\n\n\t\t$this->assertIsArray( $statuses );\n\t\t$this->assertArrayHasKey( 'all', $statuses );\n\t\t$this->assertArrayHasKey( 'publish', $statuses );\n\t\t$this->assertArrayHasKey( 'draft', $statuses );\n\t\t$this->assertArrayHasKey( 'future', $statuses );\n\t\t$this->assertArrayHasKey( 'private', $statuses );\n\n\t\t$this->assertSame( 10, $statuses['all'] );\n\t\t$this->assertSame( 7, $statuses['publish'] );\n\t\t$this->assertSame( 0, $statuses['pending'] );\n\t\t$this->assertSame( 0, $statuses['future'] );\n\t\t$this->assertSame( 0, $statuses['private'] );\n\t\t$this->assertSame( 3, $statuses['draft'] );\n\n\t\t$this->assertSame( '7', $headers['X-WP-Total'] );\n\t\t$this->assertSame( '1', $headers['X-WP-TotalPages'] );\n\t}\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t */\n\tpublic function test_get_item(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$view_link = get_preview_post_link( $story );\n\t\t$edit_link = get_edit_post_link( $story, 'rest-api' );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'preview_link', $data );\n\t\t$this->assertSame( $view_link, $data['preview_link'] );\n\t\t$this->assertArrayHasKey( 'edit_link', $data );\n\t\t$this->assertSame( $edit_link, $data['edit_link'] );\n\t\t$this->assertArrayHasKey( 'embed_post_link', $data );\n\t\t$this->assertStringContainsString( (string) $story, $data['embed_post_link'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t */\n\tpublic function test_get_item_no_user(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\twp_set_current_user( 0 );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayNotHasKey( 'edit_link', $data );\n\t\t$this->assertArrayNotHasKey( 'preview_link', $data );\n\t\t$this->assertArrayNotHasKey( 'embed_post_link', $data );\n\t}\n\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t */\n\tpublic function test_get_item_future(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$post = get_post( $story );\n\n\t\t$this->assertNotNull( $post );\n\n\t\t[ $permalink ] = get_sample_permalink( $post->ID, $post->post_title, '' );\n\t\t$permalink     = str_replace( [ '%pagename%', '%postname%' ], $post->post_name, $permalink );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'preview_link', $data );\n\t\t$this->assertNotEmpty( $data['preview_link'] );\n\t\t$this->assertSame( $permalink, $data['preview_link'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_lock(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$user_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$links    = $response->get_links();\n\n\t\t$this->assertArrayHasKey( 'https://api.w.org/lockuser', $links );\n\t\t$this->assertArrayHasKey( 'https://api.w.org/lock', $links );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_item_for_response\n\t */\n\tpublic function test_get_item_no_story_data_for_password_protected_post(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'     => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status'   => 'publish',\n\t\t\t\t'post_password' => 'Top Secret',\n\t\t\t\t'post_author'   => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'story_data', $data );\n\t\t$this->assertIsObject( $data['story_data'] );\n\t\t$this->assertEmpty( (array) $data['story_data'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::get_available_actions\n\t */\n\tpublic function test_get_available_actions(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$user_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$links    = $response->get_links();\n\n\t\t$this->assertArrayHasKey( 'https://api.w.org/action-delete', $links );\n\t\t$this->assertArrayHasKey( 'https://api.w.org/action-edit', $links );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::add_response_headers\n\t */\n\tpublic function test_get_items_format(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'status', [ 'draft' ] );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$request->set_param( '_web_stories_envelope', true );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t// Body of request.\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'headers', $data );\n\t\t$this->assertArrayHasKey( 'body', $data );\n\t\t$this->assertArrayHasKey( 'status', $data );\n\n\t\t$statuses = $data['headers']['X-WP-TotalByStatus'];\n\t\t$statuses = json_decode( $statuses, true );\n\n\t\t// Headers.\n\t\t$this->assertIsArray( $statuses );\n\t\t$this->assertArrayHasKey( 'all', $statuses );\n\t\t$this->assertArrayHasKey( 'publish', $statuses );\n\t\t$this->assertArrayHasKey( 'future', $statuses );\n\t\t$this->assertArrayHasKey( 'draft', $statuses );\n\t\t$this->assertArrayHasKey( 'private', $statuses );\n\n\t\t$this->assertSame( '3', $data['headers']['X-WP-Total'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_story_poster\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_with_no_poster(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayNotHasKey( 'story_poster', $data );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_story_poster\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_with_featured_image(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/paint.jpeg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$attachment = get_post( $attachment_id );\n\t\t$this->assertNotNull( $attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $attachment );\n\t\tset_post_thumbnail( $story, $attachment_id );\n\n\t\t$attachment_src = wp_get_attachment_image_src( $attachment_id, Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\twp_delete_attachment( $attachment_id, true );\n\n\t\t$this->assertNotFalse( $attachment_src );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'story_poster', $data );\n\t\t$this->assertSame( Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS[0], $attachment_src[1] );\n\t\t$this->assertSame( Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS[1], $attachment_src[2] );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'         => $attachment_id,\n\t\t\t\t'url'        => $attachment_src[0],\n\t\t\t\t'width'      => $attachment_src[1],\n\t\t\t\t'height'     => $attachment_src[2],\n\t\t\t\t'needsProxy' => false,\n\t\t\t],\n\t\t\t$data['story_poster']\n\t\t);\n\t}\n\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_story_poster\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_with_featured_image_in_admin(): void {\n\t\tglobal $content_width;\n\n\t\t$_content_width            = $content_width;\n\t\t$content_width             = 400;\n\t\t$GLOBALS['current_screen'] = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$this->controller->register_routes();\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/paint.jpeg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$attachment = get_post( $attachment_id );\n\t\t$this->assertNotNull( $attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $attachment );\n\t\tset_post_thumbnail( $story, $attachment_id );\n\n\t\t$attachment_src = wp_get_attachment_image_src( $attachment_id, Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\twp_delete_attachment( $attachment_id, true );\n\n\t\t$content_width = $_content_width;\n\n\t\t$this->assertNotFalse( $attachment_src );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'story_poster', $data );\n\t\t$this->assertSame( Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS[0], $attachment_src[1] );\n\t\t$this->assertSame( Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS[1], $attachment_src[2] );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'         => $attachment_id,\n\t\t\t\t'url'        => $attachment_src[0],\n\t\t\t\t'width'      => $attachment_src[1],\n\t\t\t\t'height'     => $attachment_src[2],\n\t\t\t\t'needsProxy' => false,\n\t\t\t],\n\t\t\t$data['story_poster']\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_story_poster\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_with_hotlinked_poster(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\tadd_post_meta(\n\t\t\t$story,\n\t\t\tStory_Post_Type::POSTER_META_KEY,\n\t\t\t[\n\t\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t\t'height'     => 1000,\n\t\t\t\t'width'      => 1000,\n\t\t\t\t'needsProxy' => false,\n\t\t\t]\n\t\t);\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'story_poster', $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t\t'height'     => 1000,\n\t\t\t\t'width'      => 1000,\n\t\t\t\t'needsProxy' => false,\n\t\t\t],\n\t\t\t$data['story_poster']\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_story_poster\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::prepare_links\n\t */\n\tpublic function test_get_item_with_featured_image_and_hotlinked_poster(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'future',\n\t\t\t\t'post_date'   => ( new DateTime( '+1day' ) )->format( 'Y-m-d H:i:s' ),\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/paint.jpeg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\t$attachment = get_post( $attachment_id );\n\t\t$this->assertNotNull( $attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $attachment );\n\t\tset_post_thumbnail( $story, $attachment_id );\n\n\t\t$attachment_src = wp_get_attachment_image_src( $attachment_id, Image_Sizes::POSTER_PORTRAIT_IMAGE_DIMENSIONS );\n\n\t\tadd_post_meta(\n\t\t\t$story,\n\t\t\tStory_Post_Type::POSTER_META_KEY,\n\t\t\t[\n\t\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t\t'height'     => 1000,\n\t\t\t\t'width'      => 1000,\n\t\t\t\t'needsProxy' => false,\n\t\t\t]\n\t\t);\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\twp_delete_attachment( $attachment_id, true );\n\n\t\t$this->assertNotFalse( $attachment_src );\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'story_poster', $data );\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'id'         => $attachment_id,\n\t\t\t\t'url'        => $attachment_src[0],\n\t\t\t\t'width'      => $attachment_src[1],\n\t\t\t\t'height'     => $attachment_src[2],\n\t\t\t\t'needsProxy' => false,\n\t\t\t],\n\t\t\t$data['story_poster']\n\t\t);\n\t}\n\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$data = $this->controller->get_item_schema();\n\n\t\t$this->assertArrayHasKey( 'properties', $data );\n\t\t$this->assertIsArray( $data['properties'] );\n\t\t$this->assertArrayHasKey( 'story_data', $data['properties'] );\n\t}\n\n\t/**\n\t * @covers ::filter_posts_clauses\n\t */\n\tpublic function test_filter_posts_by_author_display_names(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'order', 'asc' );\n\t\t$request->set_param( 'orderby', 'story_author' );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$results = wp_list_pluck( $data, 'author' );\n\n\t\t$this->assertSame(\n\t\t\t[\n\t\t\t\tself::$user_id,\n\t\t\t\tself::$user_id,\n\t\t\t\tself::$user_id,\n\t\t\t\tself::$user2_id,\n\t\t\t\tself::$user2_id,\n\t\t\t\tself::$user3_id,\n\t\t\t\tself::$user3_id,\n\t\t\t],\n\t\t\t$results,\n\t\t\t'Expected posts ordered by author display names'\n\t\t);\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_param( 'order', 'desc' );\n\t\t$request->set_param( 'orderby', 'story_author' );\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$results = wp_list_pluck( $data, 'author' );\n\n\t\t$this->assertSame(\n\t\t\t[\n\t\t\t\tself::$user3_id,\n\t\t\t\tself::$user3_id,\n\t\t\t\tself::$user2_id,\n\t\t\t\tself::$user2_id,\n\t\t\t\tself::$user_id,\n\t\t\t\tself::$user_id,\n\t\t\t\tself::$user_id,\n\t\t\t],\n\t\t\t$results,\n\t\t\t'Expected posts ordered by author display names'\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_attached_post_ids\n\t */\n\tpublic function test_get_attached_post_ids(): void {\n\t\t$original_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Example title',\n\t\t\t\t'post_excerpt' => 'Example excerpt',\n\t\t\t\t'post_author'  => self::$user_id,\n\t\t\t\t'post_status'  => 'private',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_id );\n\n\t\t$publisher_logo_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $publisher_logo_id );\n\n\t\tupdate_post_meta( $original_id, Story_Post_Type::PUBLISHER_LOGO_META_KEY, $publisher_logo_id );\n\n\t\t$posts = [ get_post( $original_id ) ];\n\n\t\t$result = $this->call_private_method( [ $this->controller, 'get_attached_post_ids' ], [ $posts ] );\n\t\t$this->assertEqualSets( [ $publisher_logo_id ], $result );\n\t}\n\n\t/**\n\t * @covers ::get_attached_post_ids\n\t */\n\tpublic function test_get_attached_post_ids_empty(): void {\n\t\t$posts = [];\n\n\t\t$result = $this->call_private_method( [ $this->controller, 'get_attached_post_ids' ], [ $posts ] );\n\t\t$this->assertEqualSets( [], $result );\n\t}\n\n\t/**\n\t * @covers ::filter_posts_clauses\n\t */\n\tpublic function test_filter_posts_clauses_irrelevant_query(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$controller = new \\Google\\Web_Stories\\REST_API\\Stories_Controller( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$initial_clauses = [\n\t\t\t'join'    => '',\n\t\t\t'orderby' => '',\n\t\t];\n\n\t\t$query = new \\WP_Query();\n\t\t$query->set( 'post_type', 'post' );\n\t\t$query->set( 'orderby', 'story_author' );\n\n\t\t$orderby = $controller->filter_posts_clauses( $initial_clauses, $query );\n\t\t$this->assertSame( $orderby, $initial_clauses );\n\n\t\t$query = new \\WP_Query();\n\t\t$query->set( 'post_type', Story_Post_Type::POST_TYPE_SLUG );\n\t\t$query->set( 'orderby', 'author' );\n\n\t\t$orderby = $controller->filter_posts_clauses( $initial_clauses, $query );\n\t\t$this->assertSame( $orderby, $initial_clauses );\n\t}\n\n\t/**\n\t * @covers ::get_collection_params\n\t */\n\tpublic function test_get_collection_params(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$controller = new \\Google\\Web_Stories\\REST_API\\Stories_Controller( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$collection_params = $controller->get_collection_params();\n\t\t$this->assertArrayHasKey( '_web_stories_envelope', $collection_params );\n\t\t$this->assertArrayHasKey( 'web_stories_demo', $collection_params );\n\t\t$this->assertArrayHasKey( 'orderby', $collection_params );\n\t\t$this->assertArrayHasKey( 'enum', $collection_params['orderby'] );\n\t\t$this->assertIsArray( $collection_params['orderby']['enum'] );\n\t\t$this->assertContains( 'story_author', $collection_params['orderby']['enum'] );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_as_author_should_not_strip_markup(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$this->kses_int();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = json_decode( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_filtered.json' ), true );\n\t\t$sanitized_content      = trim( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_sanitized.html' ) );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'content'    => $unsanitized_content,\n\t\t\t\t'story_data' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$new_data = $response->get_data();\n\n\t\t$this->assertIsArray( $new_data );\n\t\t$this->assertArrayHasKey( 'content', $new_data );\n\t\t$this->assertSame( $sanitized_content, trim( $new_data['content']['raw'] ) );\n\t\t$this->assertSame( $unsanitized_story_data, $new_data['story_data'] );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::get_registered_meta\n\t */\n\tpublic function test_create_item_duplicate_id(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = wp_json_encode( [ 'pages' => [] ] );\n\t\t$original_id            = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'             => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content'          => $unsanitized_content,\n\t\t\t\t'post_title'            => 'Example title',\n\t\t\t\t'post_excerpt'          => 'Example excerpt',\n\t\t\t\t'post_author'           => self::$user_id,\n\t\t\t\t'post_content_filtered' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_id );\n\n\t\t$attachment_id     = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\t\t$publisher_logo_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\t\t$this->assertNotWPError( $publisher_logo_id );\n\n\t\t$custom_poster = [\n\t\t\t'url'        => 'http://www.example.com/image.png',\n\t\t\t'width'      => 1000,\n\t\t\t'height'     => 1000,\n\t\t\t'needsProxy' => false,\n\t\t];\n\t\tset_post_thumbnail( $original_id, $attachment_id );\n\t\tupdate_post_meta( $original_id, Story_Post_Type::PUBLISHER_LOGO_META_KEY, $publisher_logo_id );\n\t\tupdate_post_meta( $original_id, Story_Post_Type::POSTER_META_KEY, $custom_poster );\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$this->kses_int();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'original_id' => $original_id,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$new_data = $response->get_data();\n\t\t$this->assertIsArray( $new_data );\n\t\t$this->assertArrayHasKey( 'content', $new_data );\n\t\t$this->assertArrayHasKey( 'raw', $new_data['content'] );\n\t\t$this->assertArrayHasKey( 'title', $new_data );\n\t\t$this->assertArrayHasKey( 'raw', $new_data['title'] );\n\t\t$this->assertArrayHasKey( 'excerpt', $new_data );\n\t\t$this->assertArrayHasKey( 'raw', $new_data['excerpt'] );\n\t\t$this->assertArrayHasKey( 'story_data', $new_data );\n\t\t$this->assertArrayHasKey( 'featured_media', $new_data );\n\t\t$this->assertArrayHasKey( 'meta', $new_data );\n\t\t$this->assertArrayHasKey( Story_Post_Type::PUBLISHER_LOGO_META_KEY, $new_data['meta'] );\n\t\t$this->assertArrayHasKey( Story_Post_Type::POSTER_META_KEY, $new_data['meta'] );\n\n\t\t$this->assertSame( 'Example title (Copy)', $new_data['title']['raw'] );\n\t\t$this->assertSame( 'Example excerpt', $new_data['excerpt']['raw'] );\n\t\t$this->assertSame( $attachment_id, $new_data['featured_media'] );\n\t\t$this->assertSame( $publisher_logo_id, $new_data['meta'][ Story_Post_Type::PUBLISHER_LOGO_META_KEY ] );\n\t\t$this->assertSame( $custom_poster, $new_data['meta'][ Story_Post_Type::POSTER_META_KEY ] );\n\t\t$this->assertSame( [ 'pages' => [] ], $new_data['story_data'] );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::get_registered_meta\n\t */\n\tpublic function test_create_item_duplicate_id_invalid_meta(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = wp_json_encode( [ 'pages' => [] ] );\n\t\t$original_id            = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'             => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content'          => $unsanitized_content,\n\t\t\t\t'post_title'            => 'Example title',\n\t\t\t\t'post_excerpt'          => 'Example excerpt',\n\t\t\t\t'post_author'           => self::$user_id,\n\t\t\t\t'post_content_filtered' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_id );\n\n\t\tupdate_post_meta( $original_id, Story_Post_Type::PUBLISHER_LOGO_META_KEY, 'wibble' );\n\t\tupdate_post_meta( $original_id, Story_Post_Type::POSTER_META_KEY, -1 );\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$this->kses_int();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'original_id' => $original_id,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_invalid_type', $response, 400 );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_duplicate_id_invalid_id(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$this->kses_int();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'original_id' => 9999,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_duplicate_id_no_permission_for_private_post(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = wp_json_encode( [ 'pages' => [] ] );\n\t\t$original_id            = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'             => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content'          => $unsanitized_content,\n\t\t\t\t'post_title'            => 'Example title',\n\t\t\t\t'post_excerpt'          => 'Example excerpt',\n\t\t\t\t'post_author'           => self::$user_id,\n\t\t\t\t'post_status'           => 'private',\n\t\t\t\t'post_content_filtered' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_id );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\tset_post_thumbnail( $original_id, $attachment_id );\n\n\t\twp_set_current_user( self::$contributor_id );\n\t\t$this->kses_int();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'original_id' => $original_id,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );\n\t}\n\n\n\t/**\n\t * @covers ::create_item\n\t */\n\tpublic function test_create_item_duplicate_id_no_permission_for_password_protected_post(): void {\n\t\t$this->controller->register_routes();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = wp_json_encode( [ 'pages' => [] ] );\n\t\t$original_id            = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'             => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content'          => $unsanitized_content,\n\t\t\t\t'post_title'            => 'Example title',\n\t\t\t\t'post_excerpt'          => 'Example excerpt',\n\t\t\t\t'post_author'           => self::$user_id,\n\t\t\t\t'post_status'           => 'publish',\n\t\t\t\t'post_password'         => 'Top Secret',\n\t\t\t\t'post_content_filtered' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_id );\n\n\t\t$attachment_id = self::factory()->attachment->create_upload_object( WEB_STORIES_TEST_DATA_DIR . '/attachment.jpg' );\n\n\t\t$this->assertNotWPError( $attachment_id );\n\n\t\tset_post_thumbnail( $original_id, $attachment_id );\n\n\t\twp_set_current_user( self::$author_id );\n\t\t$this->kses_int();\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'original_id' => $original_id,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );\n\t}\n\n\t/**\n\t * @covers ::update_item\n\t * @covers \\Google\\Web_Stories\\REST_API\\Stories_Base_Controller::update_item\n\t */\n\tpublic function test_update_item_as_author_should_not_strip_markup(): void {\n\t\t$this->controller->register_routes();\n\n\t\twp_set_current_user( self::$author_id );\n\t\t$this->kses_int();\n\n\t\t$unsanitized_content    = file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content.html' );\n\t\t$unsanitized_story_data = json_decode( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_filtered.json' ), true );\n\t\t$sanitized_content      = trim( (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/story_post_content_sanitized.html' ) );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story/' . $story );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'content'    => $unsanitized_content,\n\t\t\t\t'story_data' => $unsanitized_story_data,\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$new_data = $response->get_data();\n\n\t\t$this->assertIsArray( $new_data );\n\t\t$this->assertIsArray( $new_data['content'] );\n\t\t$this->assertIsString( $new_data['content']['raw'] );\n\t\t$this->assertSame( $sanitized_content, trim( $new_data['content']['raw'] ) );\n\t\t$this->assertSame( $unsanitized_story_data, $new_data['story_data'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Lock_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Lock_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Lock_Controller\n */\nclass Stories_Lock_Controller extends DependencyInjectedRestTestCase {\n\tprotected static int $author_id;\n\tprotected static int $subscriber;\n\tprotected static int $editor;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Stories_Lock_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$subscriber = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'subscriber',\n\t\t\t]\n\t\t);\n\t\tself::$author_id  = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\t\tself::$editor     = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'       => 'editor',\n\t\t\t\t'user_email' => 'editor@example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Stories_Lock_Controller::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/web-story/(?P<id>[\\d]+)/lock', $routes );\n\t\t$this->assertCount( 3, $routes['/web-stories/v1/web-story/(?P<id>[\\d]+)/lock'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'locked', $data );\n\t\t$this->assertFalse( $data['locked'] );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_no_story(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/99999/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_not_a_story(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_no_perm(): void {\n\t\t$this->controller->register();\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_wrong_perm(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$subscriber );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::prepare_links\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_with_lock(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$author_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$links    = $response->get_links();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'locked', $data );\n\t\t$this->assertArrayHasKey( 'user', $data );\n\t\t$this->assertArrayHasKey( 'id', $data['user'] );\n\t\t$this->assertArrayHasKey( 'name', $data['user'] );\n\t\t$this->assertArrayHasKey( 'avatar', $data['user'] );\n\t\t$this->assertSame( self::$author_id, $data['user']['id'] );\n\t\t$this->assertTrue( $data['locked'] );\n\n\t\t$this->assertArrayHasKey( 'self', $links );\n\t\t$this->assertArrayHasKey( 'author', $links );\n\t}\n\n\t/**\n\t * @covers ::get_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::prepare_links\n\t * @covers ::get_item_permissions_check\n\t */\n\tpublic function test_get_item_with_lock_disabled_avatar(): void {\n\t\tupdate_option( 'show_avatars', false );\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$author_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\t\t$links    = $response->get_links();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'locked', $data );\n\t\t$this->assertArrayHasKey( 'user', $data );\n\t\t$this->assertArrayHasKey( 'id', $data['user'] );\n\t\t$this->assertArrayHasKey( 'name', $data['user'] );\n\t\t$this->assertArrayNotHasKey( 'avatar', $data['user'] );\n\t\t$this->assertSame( self::$author_id, $data['user']['id'] );\n\t\t$this->assertTrue( $data['locked'] );\n\n\t\t$this->assertArrayHasKey( 'self', $links );\n\t\t$this->assertArrayHasKey( 'author', $links );\n\t}\n\n\t/**\n\t * @covers ::update_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::update_item_permissions_check\n\t */\n\tpublic function test_update_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'locked', $data );\n\t\t$this->assertTrue( $data['locked'] );\n\t}\n\n\t/**\n\t * @covers ::delete_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::delete_item_permissions_check\n\t */\n\tpublic function test_delete_item(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::DELETABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'deleted', $data );\n\t\t$this->assertArrayHasKey( 'previous', $data );\n\t\t$this->assertArrayHasKey( 'locked', $data['previous'] );\n\t\t$this->assertFalse( $data['deleted'] );\n\t\t$this->assertFalse( $data['previous']['locked'] );\n\t}\n\n\t/**\n\t * @covers ::delete_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::delete_item_permissions_check\n\t */\n\tpublic function test_delete_item_with_lock(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$author_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::DELETABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'deleted', $data );\n\t\t$this->assertArrayHasKey( 'previous', $data );\n\t\t$this->assertArrayHasKey( 'locked', $data['previous'] );\n\t\t$this->assertTrue( $data['deleted'] );\n\t\t$this->assertTrue( $data['previous']['locked'] );\n\t}\n\n\t/**\n\t * @covers ::delete_item\n\t * @covers ::prepare_item_for_response\n\t * @covers ::delete_item_permissions_check\n\t */\n\tpublic function test_delete_item_with_lock_another_user(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$editor );\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$author_id;\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::DELETABLE, '/web-stories/v1/web-story/' . $story . '/lock' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_cannot_delete_others_lock', $response, 403 );\n\t}\n\n\t/**\n\t * @covers ::get_lock\n\t */\n\tpublic function test_get_lock(): void {\n\t\t$this->controller->register();\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t\t'post_author' => self::$author_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$new_lock = ( time() - 100 ) . ':' . self::$author_id;\n\n\t\tupdate_post_meta( $story, '_edit_lock', $new_lock );\n\n\t\t$data = $this->call_private_method( [ $this->controller, 'get_lock' ], [ $story ] );\n\n\t\t$this->assertArrayHasKey( 'time', $data );\n\t\t$this->assertArrayHasKey( 'user', $data );\n\t\t$this->assertEquals( $data['user'], self::$author_id );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Media_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Media\\Base_Color;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Stories_Media_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Media_Controller\n */\nclass Stories_Media_Controller extends DependencyInjectedRestTestCase {\n\tprotected static int $user_id;\n\n\tprotected static int $poster_attachment_id;\n\n\tprotected static int $mp4_attachment_id;\n\n\tprotected static int $mov_attachment_id;\n\n\tprotected static int $post_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Stories_Media_Controller $controller;\n\n\t/**\n\t * @param $factory\n\t */\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\n\t\tself::$post_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\n\t\t$factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $mp4_attachment_id\n\t\t */\n\t\t$mp4_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => self::$post_id,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t]\n\t\t);\n\n\t\tself::$mp4_attachment_id = $mp4_attachment_id;\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Poster',\n\t\t\t]\n\t\t);\n\n\t\tself::$poster_attachment_id = $poster_attachment_id;\n\n\t\tset_post_thumbnail( self::$mp4_attachment_id, self::$poster_attachment_id );\n\n\t\t/**\n\t\t * @var int $mov_attachment_id\n\t\t */\n\t\t$mov_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mov',\n\t\t\t\t'post_parent'    => self::$post_id,\n\t\t\t\t'post_mime_type' => 'video/mov',\n\t\t\t\t'post_title'     => 'Test Video Move',\n\t\t\t]\n\t\t);\n\n\t\tself::$mov_attachment_id = $mov_attachment_id;\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Stories_Media_Controller::class );\n\n\t\twp_set_object_terms( self::$poster_attachment_id, 'poster-generation', $this->container->get( 'media.media_source' )->get_taxonomy_slug() );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_format(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/media' );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$request->set_param( '_web_stories_envelope', true );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'headers', $data );\n\t\t$this->assertArrayHasKey( 'body', $data );\n\t\t$this->assertArrayHasKey( 'status', $data );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::prepare_items_query\n\t */\n\tpublic function test_get_items_filter_mime(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/media' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 2, $data );\n\t\t$mime_type = wp_list_pluck( $data, 'mime_type' );\n\t\t$this->assertNotContains( 'video/mov', $mime_type );\n\t\t$this->assertContains( 'image/jpeg', $mime_type );\n\t\t$this->assertContains( 'video/mp4', $mime_type );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::get_media_types\n\t */\n\tpublic function test_get_items_filter_video(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$user_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::READABLE, '/web-stories/v1/media' );\n\t\t$request->set_param( 'media_type', 'video' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertCount( 1, $data );\n\t\t$mime_type = wp_list_pluck( $data, 'mime_type' );\n\t\t$this->assertNotContains( 'video/mov', $mime_type );\n\t\t$this->assertContains( 'video/mp4', $mime_type );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::process_post\n\t */\n\tpublic function test_create_item(): void {\n\t\t$this->controller->register();\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/media' );\n\t\t$request->set_header( 'Content-Type', 'image/jpeg' );\n\t\t$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );\n\t\t$request->set_param( 'title', 'My title is very cool' );\n\t\t$request->set_param( 'caption', 'This is a better caption.' );\n\t\t$request->set_param( 'description', 'Without a description, my attachment is descriptionless.' );\n\t\t$request->set_param( 'alt_text', 'Alt text is stored outside post schema.' );\n\t\t$request->set_param( 'post', $poster_attachment_id );\n\n\t\t$request->set_body( (string) file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 201, $response->get_status() );\n\t\t$this->assertEquals( 'image', $data['media_type'] );\n\n\t\t$this->assertArrayHasKey( 'post', $data );\n\t\t$this->assertSame( $data['post'], $poster_attachment_id );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::process_post\n\t */\n\tpublic function test_create_item_with_revision(): void {\n\t\t$this->controller->register();\n\n\t\t$revision_id = self::factory()->post->create_object(\n\t\t\t[\n\t\t\t\t'post_type'   => 'revision',\n\t\t\t\t'post_author' => self::$user_id,\n\t\t\t]\n\t\t);\n\t\twp_set_current_user( self::$user_id );\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/media' );\n\t\t$request->set_header( 'Content-Type', 'image/jpeg' );\n\t\t$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );\n\t\t$request->set_param( 'title', 'My title is very cool' );\n\t\t$request->set_param( 'caption', 'This is a better caption.' );\n\t\t$request->set_param( 'description', 'Without a description, my attachment is descriptionless.' );\n\t\t$request->set_param( 'alt_text', 'Alt text is stored outside post schema.' );\n\t\t$request->set_param( 'post', $revision_id );\n\n\t\t$request->set_body( (string) file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );\n\t}\n\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::process_post\n\t */\n\tpublic function test_create_item_migrate_data(): void {\n\t\t$this->controller->register();\n\n\t\t$original_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/uploads/test-video.mp4',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'video/mp4',\n\t\t\t\t'post_title'     => 'Test Video',\n\t\t\t\t'post_content'   => 'Test content',\n\t\t\t\t'post_excerpt'   => 'Test excerpt',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $original_attachment_id );\n\n\t\tupdate_post_meta( $original_attachment_id, '_wp_attachment_image_alt', 'Test alt' );\n\t\t$color = '#0f0f0f';\n\t\tupdate_post_meta( $original_attachment_id, Base_Color::BASE_COLOR_POST_META_KEY, $color );\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/media' );\n\t\t$request->set_header( 'Content-Type', 'image/jpeg' );\n\t\t$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );\n\t\t$request->set_param( 'original_id', $original_attachment_id );\n\t\t$request->set_body( (string) file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertEquals( 201, $response->get_status() );\n\t\t$this->assertEquals( 'image', $data['media_type'] );\n\n\t\t$this->assertIsInt( $data['id'] );\n\t\t$attachment = get_post( $data['id'] );\n\n\t\t$this->assertNotNull( $attachment );\n\n\t\t$this->assertIsArray( $data['title'] );\n\t\t$this->assertSame( 'Test Video', $data['title']['raw'] );\n\t\t$this->assertSame( 'Test Video', $attachment->post_title );\n\t\t$this->assertIsArray( $data['caption'] );\n\t\t$this->assertSame( 'Test excerpt', $data['caption']['raw'] );\n\t\t$this->assertSame( 'Test excerpt', $attachment->post_excerpt );\n\t\t$this->assertSame( 'Test content', $attachment->post_content );\n\t\t$this->assertSame( 'Test alt', $data['alt_text'] );\n\t\t$this->assertSame( 'Test alt', get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) );\n\n\t\t$this->assertArrayHasKey( 'meta', $data );\n\t\t$this->assertArrayHasKey( 'web_stories_base_color', $data['meta'] );\n\t\t$this->assertSame( $color, $data['meta']['web_stories_base_color'] );\n\t}\n\n\t/**\n\t * @covers ::create_item\n\t * @covers ::process_post\n\t */\n\tpublic function test_create_item_migrate_data_invalid(): void {\n\t\t$this->controller->register();\n\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/web-stories/v1/media' );\n\t\t$request->set_header( 'Content-Type', 'image/jpeg' );\n\t\t$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );\n\t\t$request->set_param( 'title', 'My title is very cool' );\n\t\t$request->set_param( 'caption', 'This is a better caption.' );\n\t\t$request->set_param( 'description', 'Without a description, my attachment is descriptionless.' );\n\t\t$request->set_param( 'alt_text', 'Alt text is stored outside post schema.' );\n\t\t$request->set_param( 'original_id', 999 );\n\n\t\t$request->set_body( (string) file_get_contents( DIR_TESTDATA . '/images/canola.jpg' ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );\n\t}\n\n\t/**\n\t * @covers ::get_item_schema\n\t */\n\tpublic function test_get_item_schema(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( 'OPTIONS', '/web-stories/v1/media' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertNotEmpty( $data );\n\n\t\t$this->assertArrayHasKey( 'schema', $data );\n\t\t$this->assertArrayHasKey( 'properties', $data['schema'] );\n\t\t$properties = $data['schema']['properties'];\n\t\t$this->assertArrayNotHasKey( 'permalink_template', $properties );\n\t\t$this->assertArrayNotHasKey( 'generated_slug', $properties );\n\t\t$this->assertArrayHasKey( 'original_id', $properties );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Taxonomies_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Taxonomy\\Taxonomy_Base;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyTaxonomy;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Stories_Taxonomies_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Taxonomies_Controller\n */\nclass Stories_Taxonomies_Controller extends DependencyInjectedRestTestCase {\n\tprotected static Taxonomy_Base $taxonomy_object;\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Stories_Taxonomies_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\tself::$taxonomy_object = new DummyTaxonomy();\n\t\tself::$taxonomy_object->register_taxonomy();\n\t}\n\n\tpublic static function wpTearDownAfterClass(): void {\n\t\tself::$taxonomy_object->unregister_taxonomy();\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Stories_Taxonomies_Controller::class );\n\t}\n\n\t/**\n\t * @covers ::prepare_item_for_response\n\t */\n\tpublic function test_prepare_item_for_response(): void {\n\t\t$this->controller->register();\n\n\t\t$slug     = self::$taxonomy_object->get_taxonomy_slug();\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/taxonomies/' . $slug );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$links    = $response->get_links();\n\t\t$this->assertArrayHasKey( 'https://api.w.org/items', $links );\n\t\t$this->assertStringContainsString( 'web-stories/v1', $links['https://api.w.org/items'][0]['href'] );\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items(): void {\n\t\t$this->controller->register();\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/taxonomies' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$request->set_param( 'hierarchical', false );\n\t\t$response_flat = rest_get_server()->dispatch( $request );\n\n\t\t$request->set_param( 'hierarchical', true );\n\t\t$response_hierarchical = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$this->assertNotEmpty( $response->get_data() );\n\t\t$this->assertIsArray( $response->get_data() );\n\t\t$this->assertIsArray( $response_hierarchical->get_data() );\n\t\t$this->assertIsArray( $response_flat->get_data() );\n\t\t$this->assertCount(\n\t\t\t\\count( $response_hierarchical->get_data() ) + \\count( $response_flat->get_data() ),\n\t\t\t$response->get_data()\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::get_collection_params\n\t * @dataProvider data_show_ui\n\t */\n\tpublic function test_get_items_show_ui( bool $show_ui ): void {\n\t\twp_set_current_user( self::$admin_id );\n\t\t$this->controller->register();\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/taxonomies' );\n\t\t$request->set_param( 'show_ui', $show_ui );\n\t\t$request->set_param( 'context', 'edit' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$data = $response->get_data();\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertIsArray( $data );\n\t\tforeach ( $data as $tax ) {\n\t\t\t$this->assertIsArray( $tax );\n\t\t\t$this->assertArrayHasKey( 'visibility', $tax );\n\t\t\t$this->assertArrayHasKey( 'show_ui', $tax['visibility'] );\n\t\t\t$this->assertSame( $show_ui, $tax['visibility']['show_ui'] );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t * @covers ::get_collection_params\n\t * @dataProvider data_show_ui\n\t */\n\tpublic function test_get_items_hierarchical( bool $hierarchical ): void {\n\t\t$this->controller->register();\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/taxonomies' );\n\t\t$request->set_param( 'hierarchical', $hierarchical );\n\t\t$response = rest_get_server()->dispatch( $request );\n\n\t\t$this->assertFalse( $response->is_error() );\n\t\t$data = $response->get_data();\n\t\t$this->assertNotEmpty( $data );\n\t\t$this->assertIsArray( $data );\n\t\tforeach ( $data as $tax ) {\n\t\t\t$this->assertIsArray( $tax );\n\t\t\t$this->assertArrayHasKey( 'hierarchical', $tax );\n\t\t\t$this->assertSame( $hierarchical, $tax['hierarchical'] );\n\t\t}\n\t}\n\n\t/**\n\t * @return array<string, bool[]>\n\t */\n\tpublic static function data_show_ui(): array {\n\t\treturn [\n\t\t\t'true'  => [ true ],\n\t\t\t'false' => [ false ],\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Terms_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Taxonomy\\Taxonomy_Base;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyTaxonomy;\nuse Google\\Web_Stories\\Tests\\Integration\\RestTestCase;\nuse WP_REST_Request;\nuse WP_REST_Server;\n\n/**\n * Class Stories_Terms_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Terms_Controller\n */\nclass Stories_Terms_Controller extends RestTestCase {\n\tprotected static Taxonomy_Base $taxonomy_object;\n\n\tpublic static function wpSetUpBeforeClass(): void {\n\t\tself::$taxonomy_object = new DummyTaxonomy();\n\t\tself::$taxonomy_object->register_taxonomy();\n\t}\n\n\tpublic static function wpTearDownAfterClass(): void {\n\t\tself::$taxonomy_object->unregister_taxonomy();\n\t}\n\n\t/**\n\t * @covers ::prepare_links\n\t */\n\tpublic function test_prepare_links(): void {\n\t\t$slug    = self::$taxonomy_object->get_taxonomy_slug();\n\t\t$term_id = self::factory()->term->create( [ 'taxonomy' => $slug ] );\n\n\t\t$this->assertNotWPError( $term_id );\n\n\t\t$request  = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/' . $slug . '/' . $term_id );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$links    = $response->get_links();\n\t\t$this->assertArrayHasKey( 'about', $links );\n\t\t$this->assertArrayHasKey( 'href', $links['about'][0] );\n\t\t$this->assertStringContainsString( 'web-stories/v1', $links['about'][0]['href'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/REST_API/Stories_Users_Controller.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\REST_API;\n\nuse Google\\Web_Stories\\Font_Post_Type;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedRestTestCase;\nuse WP_REST_Request;\nuse WP_REST_Server;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Stories_Users_Controller\n *\n * @coversDefaultClass \\Google\\Web_Stories\\REST_API\\Stories_Users_Controller\n */\nclass Stories_Users_Controller extends DependencyInjectedRestTestCase {\n\n\tprotected static int $admin_id;\n\n\tprotected static int $author_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\REST_API\\Stories_Users_Controller $controller;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role'         => 'administrator',\n\t\t\t\t'display_name' => 'Andrea Adams',\n\t\t\t]\n\t\t);\n\n\t\tself::$author_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\n\t\t$post_type = Story_Post_Type::POST_TYPE_SLUG;\n\n\t\t$factory->post->create_many(\n\t\t\t3,\n\t\t\t[\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$admin_id,\n\t\t\t\t'post_type'   => $post_type,\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->controller = $this->injector->make( \\Google\\Web_Stories\\REST_API\\Stories_Users_Controller::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$routes = rest_get_server()->get_routes();\n\n\t\t$this->assertArrayHasKey( '/web-stories/v1/users', $routes );\n\t\t$this->assertCount( 2, $routes['/web-stories/v1/users'] );\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t */\n\tpublic function test_get_items_no_permissions_for_capabilities_query(): void {\n\t\t$this->controller->register();\n\n\t\t$post_type_object = get_post_type_object( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/users' );\n\t\t$request->set_param( 'capabilities', [ $post_type_object->cap->edit_posts ] );\n\n\t\t$this->assertWPError(\n\t\t\t$this->controller->get_items_permissions_check( $request )\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_items_permissions_check\n\t */\n\tpublic function test_get_items_permissions_check_can_edit_stories(): void {\n\t\twp_set_current_user( self::$admin_id );\n\n\t\t$this->controller->register();\n\n\t\t$post_type_object = get_post_type_object( Font_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/users' );\n\t\t$request->set_param( 'capabilities', [ $post_type_object->cap->edit_posts ] );\n\n\t\t$this->assertNotWPError(\n\t\t\t$this->controller->get_items_permissions_check( $request )\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_items\n\t */\n\tpublic function test_get_items_returns_users_without_published_posts(): void {\n\t\twp_set_current_user( self::$author_id );\n\n\t\t$this->controller->register();\n\n\t\t$post_type_object = get_post_type_object( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\n\t\t$request = new WP_REST_Request( WP_REST_Server::READABLE, '/web-stories/v1/users' );\n\t\t$request->set_param( 'orderby', 'name' );\n\t\t$request->set_param( 'page', 1 );\n\t\t$request->set_param( 'per_page', 10 );\n\t\t$request->set_param( 'capabilities', [ $post_type_object->cap->edit_posts ] );\n\t\t$request->set_param( '_fields', 'id' );\n\n\t\t$response = $this->controller->get_items( $request );\n\n\t\t$this->assertNotWPError( $response );\n\n\t\t$data = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\n\t\t$this->assertContains( self::$author_id, wp_list_pluck( $data, 'id' ) );\n\t}\n\n\t/**\n\t * @covers ::user_posts_count_public\n\t * @covers \\Google\\Web_Stories\\Story_Post_Type::clear_user_posts_count\n\t */\n\tpublic function test_count_user_posts(): void {\n\t\t$this->controller->register();\n\t\t$post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$post_type->register();\n\n\t\t$result1 = $this->call_private_method(\n\t\t\t[ $this->controller, 'user_posts_count_public' ],\n\t\t\t[\n\t\t\t\tself::$admin_id,\n\t\t\t\t$post_type->get_slug(),\n\t\t\t]\n\t\t);\n\t\t$this->assertEquals( 3, $result1 );\n\n\t\t$post_id = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => $post_type->get_slug(),\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_author' => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post_id );\n\n\t\t$result2 = $this->call_private_method(\n\t\t\t[ $this->controller, 'user_posts_count_public' ],\n\t\t\t[\n\t\t\t\tself::$admin_id,\n\t\t\t\t$post_type->get_slug(),\n\t\t\t]\n\t\t);\n\n\t\t$this->assertEquals( 4, $result2 );\n\n\t\twp_delete_post( $post_id, true );\n\n\t\t$result3 = $this->call_private_method(\n\t\t\t[ $this->controller, 'user_posts_count_public' ],\n\t\t\t[\n\t\t\t\tself::$admin_id,\n\t\t\t\t$post_type->get_slug(),\n\t\t\t]\n\t\t);\n\n\t\t$this->assertEquals( 3, $result3 );\n\t}\n\n\t/**\n\t * @covers ::user_posts_count_public\n\t * @covers \\Google\\Web_Stories\\Story_Post_Type::clear_user_posts_count\n\t */\n\tpublic function test_count_user_posts_invalid(): void {\n\t\t$this->controller->register();\n\n\t\t$post_type = $this->injector->make( Story_Post_Type::class );\n\t\t$post_type->register();\n\t\t$result1 = $this->call_private_method(\n\t\t\t[ $this->controller, 'user_posts_count_public' ],\n\t\t\t[\n\t\t\t\t-1,\n\t\t\t\t$post_type->get_slug(),\n\t\t\t]\n\t\t);\n\t\t$this->assertEquals( 0, $result1 );\n\n\t\t$result1 = $this->call_private_method( [ $this->controller, 'user_posts_count_public' ], [ self::$admin_id, 'invalid' ] );\n\n\t\t$this->assertEquals( 0, $result1 );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Remove_Transients.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @runInSeparateProcess\n * @preserveGlobalState disabled\n * @coversDefaultClass \\Google\\Web_Stories\\Remove_Transients\n */\nclass Remove_Transients extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Remove_Transients $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Remove_Transients::class );\n\n\t\tset_transient( 'web_stories_link_data_fdsf', 'hello' );\n\t\tset_site_transient( 'web_stories_updater', 'hello' );\n\t}\n\n\t/**\n\t * @covers ::delete_transients\n\t */\n\tpublic function test_delete_transients(): void {\n\t\t$this->call_private_method( [ $this->instance, 'delete_transients' ] );\n\t\t$this->assertFalse( get_transient( 'web_stories_link_data_fdsf' ) );\n\t}\n\n\t/**\n\t * @group ms-required\n\t * @covers ::delete_network_transients\n\t */\n\tpublic function test_delete_network_transients(): void {\n\t\t$this->call_private_method( [ $this->instance, 'delete_network_transients' ] );\n\t\t$this->assertFalse( get_site_transient( 'web_stories_updater' ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Archives.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Archives\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Archives\n */\nclass Archives extends TestCase {\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\t/**\n\t * @covers ::embed_player\n\t */\n\tpublic function test_embed_player(): void {\n\t\t$this->go_to( (string) get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG ) );\n\n\t\t$content = get_echo( 'the_content' );\n\t\t$this->assertStringContainsString( '<amp-story-player', $content );\n\n\t\t$excerpt = get_echo( 'the_excerpt' );\n\t\t$this->assertStringContainsString( '<amp-story-player', $excerpt );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Feed.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Feed\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Feed\n */\nclass Feed extends TestCase {\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\t/**\n\t * @throws \\Exception\n\t *\n\t * @covers ::embed_image\n\t */\n\tpublic function test_the_content_feed(): void {\n\t\t$this->go_to( '/?feed=rss2&post_type=' . Story_Post_Type::POST_TYPE_SLUG );\n\t\t$feed = $this->do_rss2();\n\n\t\t$this->assertStringContainsString( '<img', $feed );\n\t\t$this->assertStringContainsString( 'images/canola.jpg', $feed );\n\t\t$this->assertStringContainsString( 'wp-block-web-stories-embed', $feed );\n\t}\n\n\t/**\n\t * This is a bit of a hack used to buffer feed content.\n\t *\n\t * @link https://github.com/WordPress/wordpress-develop/blob/ab9aee8af474ac512b31b012f3c7c44fab31a990/tests/phpunit/tests/feed/rss2.php#L78-L94\n\t */\n\tprotected function do_rss2(): string {\n\t\tob_start();\n\t\t// Nasty hack! In the future it would better to leverage do_feed( 'rss2' ).\n\t\ttry {\n\t\t\t// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged\n\t\t\t@require ABSPATH . 'wp-includes/feed-rss2.php';\n\t\t\t$out = (string) ob_get_clean();\n\t\t} catch ( \\Exception $e ) {\n\t\t\tthrow $e;\n\t\t}\n\t\treturn $out;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Oembed.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Story\\Image;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Single\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Oembed\n */\nclass Oembed extends TestCase {\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\t/**\n\t * @covers ::get_embed_height_width\n\t */\n\tpublic function test_get_embed_height_width(): void {\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Oembed();\n\t\t$actual   = $this->call_private_method( [ $renderer, 'get_embed_height_width' ], [ 600 ] );\n\t\t$expected = [\n\t\t\t'width'  => 360,\n\t\t\t'height' => 600,\n\t\t];\n\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_oembed_response_data\n\t */\n\tpublic function test_filter_oembed_response_data(): void {\n\t\t$renderer     = new \\Google\\Web_Stories\\Renderer\\Oembed();\n\t\t$old          = [\n\t\t\t'existing' => 'data',\n\t\t];\n\t\t$current_post = get_post( self::$story_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$actual   = $renderer->filter_oembed_response_data( $old, $current_post, 600 );\n\t\t$expected = [\n\t\t\t'existing' => 'data',\n\t\t\t'width'    => 360,\n\t\t\t'height'   => 600,\n\t\t];\n\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_embed_html\n\t */\n\tpublic function test_filter_embed_htmla(): void {\n\t\t$renderer     = new \\Google\\Web_Stories\\Renderer\\Oembed();\n\t\t$current_post = get_post( self::$story_id );\n\t\t$this->assertNotNull( $current_post );\n\t\t$story = new Story();\n\t\t$story->load_from_post( $current_post );\n\t\t$image_renderer = new Image( $story );\n\t\t$output         = $image_renderer->render(\n\t\t\t[\n\t\t\t\t'height' => 10000,\n\t\t\t\t'width'  => 2000,\n\t\t\t]\n\t\t);\n\n\t\t$actual = $renderer->filter_embed_html( $output, $current_post, 2000, 10000 );\n\t\t$this->assertStringContainsString( 'width=\"360\"', $actual );\n\t\t$this->assertStringContainsString( 'height=\"600\"', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Single.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * Class Single\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Single\n */\nclass Single extends DependencyInjectedTestCase {\n\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\tprivate \\Google\\Web_Stories\\Renderer\\Single $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Renderer\\Single::class );\n\t}\n\n\t/**\n\t * @covers ::filter_template_include\n\t */\n\tpublic function test_filter_template_include(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\t\t$this->go_to( (string) get_permalink( self::$story_id ) );\n\n\t\t$template_include = $this->instance->filter_template_include( 'current' );\n\t\t$this->assertIsString( $template_include );\n\t\t$this->assertStringContainsString( WEBSTORIES_PLUGIN_DIR_PATH, $template_include );\n\t}\n\n\t/**\n\t * @covers ::filter_template_include\n\t */\n\tpublic function test_filter_template_include_with_password(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\t\t$this->go_to( (string) get_permalink( self::$story_id ) );\n\n\t\tadd_filter( 'post_password_required', '__return_true' );\n\n\t\t$template_include = $this->instance->filter_template_include( 'current' );\n\n\t\tremove_filter( 'post_password_required', '__return_true' );\n\n\t\t$this->assertIsString( $template_include );\n\t\t$this->assertStringContainsString( 'current', $template_include );\n\t}\n\n\t/**\n\t * @covers ::show_admin_bar\n\t */\n\tpublic function test_show_admin_bar(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\t\t$this->go_to( (string) get_permalink( self::$story_id ) );\n\n\t\t$show_admin_bar = $this->instance->show_admin_bar( 'current' );\n\n\t\t$this->assertFalse( $show_admin_bar );\n\t\t$this->assertTrue( is_singular( Story_Post_Type::POST_TYPE_SLUG ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Stories/Carousel_Renderer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Stories;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Stories\\Carousel_Renderer\n */\nclass Carousel_Renderer extends TestCase {\n\n\t/**\n\t * Story post ID.\n\t */\n\tprivate static int $story_id;\n\n\t/**\n\t * Stories mock object.\n\t *\n\t * @var Story_Query & MockObject\n\t */\n\tprivate $story_query;\n\n\t/**\n\t * Runs once before any test in the class run.\n\t *\n\t * @param WP_UnitTest_Factory $factory Factory class object.\n\t */\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Example title',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Runs once before any test in the class run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->story_query = $this->createMock( Story_Query::class );\n\t\t$this->story_query->method( 'get_stories' )->willReturn( [ get_post( self::$story_id ) ] );\n\t}\n\n\t/**\n\t * @covers ::init\n\t * @covers ::load_assets\n\t */\n\tpublic function test_init(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'  => 'carousel',\n\t\t\t\t'show_title' => true,\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Stories\\Carousel_Renderer( $this->story_query );\n\t\t$renderer->init();\n\n\t\t$this->assertTrue( wp_script_is( $renderer::SCRIPT_HANDLE, 'registered' ) );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'          => 'carousel',\n\t\t\t\t'archive_link_label' => 'View all stories',\n\t\t\t\t'class'              => '',\n\t\t\t\t'number_of_columns'  => 2,\n\t\t\t\t'show_title'         => false,\n\t\t\t\t'show_author'        => false,\n\t\t\t\t'show_date'          => false,\n\t\t\t\t'show_excerpt'       => false,\n\t\t\t\t'show_archive_link'  => false,\n\t\t\t\t'sharp_corners'      => false,\n\t\t\t\t'image_alignment'    => 'left',\n\t\t\t\t'circle_size'        => 150,\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Stories\\Carousel_Renderer( $this->story_query );\n\n\t\t$renderer->init();\n\n\t\t$output = $renderer->render();\n\n\t\t$this->assertStringContainsString( 'web-stories-list alignnone is-view-type-carousel', $output );\n\t\t$this->assertStringContainsString( 'web-stories-list__story', $output );\n\t\t$this->assertStringContainsString( 'web-stories-list__story-poster', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Stories/Fields/BaseField.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * BaseField Class.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Stories\\Fields;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField as Testee;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * Class BaseField.\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Stories\\Fields\\BaseField\n */\nclass BaseField extends TestCase {\n\n\t/**\n\t * Object of class in test.\n\t */\n\tprivate static Testee $testee;\n\n\t/**\n\t * Runs before any test in class is executed.\n\t */\n\tpublic static function wpSetUpBeforeClass(): void {\n\t\tself::$testee = new Testee(\n\t\t\t[\n\t\t\t\t'label'  => 'Test Label',\n\t\t\t\t'hidden' => true,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::label\n\t */\n\tpublic function test_label(): void {\n\t\t$this->assertSame( 'Test Label', self::$testee->label() );\n\t}\n\n\t/**\n\t * @covers ::hidden\n\t */\n\tpublic function test_hidden(): void {\n\t\t$this->assertTrue( self::$testee->hidden() );\n\t}\n\n\t/**\n\t * @covers ::show\n\t */\n\tpublic function test_show(): void {\n\t\t$this->assertTrue( self::$testee->show() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Stories/Generic_Renderer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Stories;\n\nuse Google\\Web_Stories\\AMP_Story_Player_Assets;\nuse Google\\Web_Stories\\Renderer\\Stories\\Renderer;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Stories\\Generic_Renderer\n */\nclass Generic_Renderer extends TestCase {\n\n\t/**\n\t * Story post ID.\n\t */\n\tprivate static int $story_id;\n\n\t/**\n\t * Stories mock object.\n\t *\n\t * @var Story_Query & MockObject\n\t */\n\tprivate $story_query;\n\n\t/**\n\t * Runs once before any test in the class run.\n\t *\n\t * @param WP_UnitTest_Factory $factory Factory class object.\n\t */\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Example title',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Runs once before any test in the class run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->story_query = $this->createMock( Story_Query::class );\n\t\t$this->story_query->method( 'get_stories' )->willReturn( [ get_post( self::$story_id ) ] );\n\t}\n\n\tpublic function tear_down(): void {\n\t\twp_dequeue_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\twp_deregister_script( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\n\t\twp_dequeue_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\t\twp_deregister_style( AMP_Story_Player_Assets::SCRIPT_HANDLE );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::load_assets\n\t */\n\tpublic function test_load_assets(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'class'      => '',\n\t\t\t\t'view_type'  => 'grid',\n\t\t\t\t'show_title' => true,\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Stories\\Generic_Renderer( $this->story_query );\n\t\t$renderer->init();\n\n\t\t$this->assertTrue( wp_style_is( Renderer::STYLE_HANDLE, 'registered' ) );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'          => 'grid',\n\t\t\t\t'number_of_columns'  => 2,\n\t\t\t\t'image_alignment'    => 'left',\n\t\t\t\t'show_title'         => false,\n\t\t\t\t'show_author'        => false,\n\t\t\t\t'show_date'          => false,\n\t\t\t\t'show_excerpt'       => false,\n\t\t\t\t'show_archive_link'  => false,\n\t\t\t\t'sharp_corners'      => false,\n\t\t\t\t'archive_link_label' => 'View all stories',\n\t\t\t\t'class'              => '',\n\t\t\t\t'circle_size'        => 150,\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Stories\\Generic_Renderer( $this->story_query );\n\t\t$renderer->init();\n\n\t\t$output = $renderer->render();\n\n\t\t$this->assertStringContainsString( 'web-stories-list alignnone is-view-type-grid', $output );\n\t\t$this->assertStringContainsString( 'web-stories-list__story', $output );\n\t\t$this->assertStringContainsString( 'web-stories-list__story-poster', $output );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Stories/Renderer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Generic_Renderer class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Stories;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Renderer\\Stories\\Generic_Renderer;\nuse Google\\Web_Stories\\Renderer\\Stories\\Renderer as AbstractRenderer;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Story_Query;\nuse Google\\Web_Stories\\Tests\\Integration\\Test_Renderer;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse WP_UnitTest_Factory;\n\n/**\n * Generic_Renderer class.\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Stories\\Renderer\n */\nclass Renderer extends TestCase {\n\n\t/**\n\t * Story post ID.\n\t */\n\tprivate static int $story_id;\n\n\t/**\n\t * Poster attachment ID.\n\t */\n\tprivate static int $poster_id;\n\n\t/**\n\t * Stories mock object.\n\t *\n\t * @var Story_Query & MockObject\n\t */\n\tprivate $story_query;\n\n\t/**\n\t * Story Model Mock.\n\t */\n\tprivate Story $story_model;\n\n\t/**\n\t * Runs once before any test in the class run.\n\t *\n\t * @param WP_UnitTest_Factory $factory Factory class object.\n\t */\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'  => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title' => 'Story Title',\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_id\n\t\t */\n\t\t$poster_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tself::$poster_id = $poster_id;\n\t}\n\n\t/**\n\t * Runs once before any test in the class run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->story_model = $this->createMock( Story::class );\n\t\t$this->story_model->load_from_post( self::$story_id );\n\n\t\t$this->story_query = $this->createMock( Story_Query::class );\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'         => 'grid',\n\t\t\t\t'show_title'        => true,\n\t\t\t\t'show_excerpt'      => false,\n\t\t\t\t'show_author'       => false,\n\t\t\t\t'show_date'         => false,\n\t\t\t\t'number_of_columns' => 3,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::load_assets\n\t */\n\tpublic function test_assets(): void {\n\t\t$renderer = new Test_Renderer( $this->story_query );\n\n\t\t$renderer->load_assets();\n\n\t\t$this->assertTrue( wp_style_is( \\Google\\Web_Stories\\Renderer\\Stories\\Renderer::STYLE_HANDLE, 'registered' ) );\n\t}\n\n\t/**\n\t * @covers ::is_view_type\n\t */\n\tpublic function test_is_view_type(): void {\n\n\t\t$renderer = new Test_Renderer( $this->story_query );\n\n\t\t$output = $this->call_private_method( [ $renderer, 'is_view_type' ], [ 'grid' ] );\n\n\t\t$this->assertTrue( $output );\n\n\t\t$output = $this->call_private_method( [ $renderer, 'is_view_type' ], [ 'list' ] );\n\n\t\t$this->assertFalse( $output );\n\t}\n\n\t/**\n\t * @covers ::get_view_type\n\t */\n\tpublic function test_get_view_type(): void {\n\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type' => 'grid',\n\t\t\t]\n\t\t);\n\t\t$renderer = new Test_Renderer( $this->story_query );\n\n\t\t$output = $this->call_private_method( [ $renderer, 'get_view_type' ] );\n\n\t\t$this->assertEquals( 'grid', $output );\n\t}\n\n\t/**\n\t * @covers ::render_story_with_poster\n\t */\n\tpublic function test_render_story_with_poster_missing(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'       => 'list',\n\t\t\t\t'class'           => '',\n\t\t\t\t'image_alignment' => 'left',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = $this->getMockForAbstractClass( AbstractRenderer::class, [ $this->story_query ], '', true, true, true, [ 'is_amp_request' ] );\n\t\t$this->set_private_property( $renderer, 'stories', [ $this->story_model ] );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'render_story_with_poster' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertStringContainsString( 'web-stories-list__story-poster', $output );\n\t\t$this->assertStringNotContainsString( '<img', $output );\n\t}\n\n\t/**\n\t * @covers ::render_story_with_poster\n\t */\n\tpublic function test_render_story_with_poster(): void {\n\t\t$poster_attachment = get_post( self::$poster_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $poster_attachment );\n\t\tset_post_thumbnail( self::$story_id, self::$poster_id );\n\n\t\t$this->story_model = new Story();\n\t\t$this->story_model->load_from_post( self::$poster_id );\n\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'       => 'list',\n\t\t\t\t'class'           => '',\n\t\t\t\t'image_alignment' => 'left',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = $this->getMockForAbstractClass( AbstractRenderer::class, [ $this->story_query ], '', true, true, true, [ 'is_amp_request' ] );\n\t\t$this->set_private_property( $renderer, 'stories', [ $this->story_model ] );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'render_story_with_poster' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertStringContainsString( 'web-stories-list__story-poster', $output );\n\t}\n\n\n\t/**\n\t * @covers ::render_story_with_poster\n\t */\n\tpublic function test_render_story_with_poster_missing_srcset_and_sizes(): void {\n\t\tset_post_thumbnail( self::$story_id, self::$poster_id );\n\n\t\t$this->story_model = new Story();\n\t\t$this->story_model->load_from_post( self::$poster_id );\n\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'       => 'list',\n\t\t\t\t'class'           => '',\n\t\t\t\t'image_alignment' => 'left',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = $this->getMockForAbstractClass( AbstractRenderer::class, [ $this->story_query ], '', true, true, true, [ 'is_amp_request' ] );\n\t\t$this->set_private_property( $renderer, 'stories', [ $this->story_model ] );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'render_story_with_poster' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertStringContainsString( 'web-stories-list__story-poster', $output );\n\t}\n\n\t/**\n\t * @covers ::get_content_overlay\n\t */\n\tpublic function test_get_content_overlay(): void {\n\t\t$renderer = $this->getMockForAbstractClass( AbstractRenderer::class, [ $this->story_query ], '', true, true, true, [ 'is_amp_request' ] );\n\t\t$this->set_private_property( $renderer, 'stories', [ $this->story_model ] );\n\t\t$this->set_private_property( $renderer, 'content_overlay', false );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'get_content_overlay' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertEmpty( $output );\n\n\t\t// When content_overlay is set.\n\t\t$this->set_private_property( $renderer, 'content_overlay', true );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'get_content_overlay' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertStringContainsString( 'story-content-overlay__title', $output );\n\t}\n\n\t/**\n\t * @covers ::get_single_story_classes\n\t */\n\tpublic function test_get_single_story_classes(): void {\n\t\t$this->story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type' => 'circles',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new Generic_Renderer( $this->story_query );\n\t\t$expected = 'web-stories-list__story';\n\n\t\t$output = $this->call_private_method( [ $renderer, 'get_single_story_classes' ] );\n\n\t\t$this->assertEquals( $expected, $output );\n\t}\n\n\t/**\n\t * @covers ::get_container_classes\n\t */\n\tpublic function test_get_container_classes(): void {\n\t\t$story_query = $this->createMock( Story_Query::class );\n\t\t$story_query->method( 'get_stories' )->willReturn( [ $this->story_model ] );\n\t\t$story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'view_type'  => 'circles',\n\t\t\t\t'show_title' => true,\n\t\t\t\t'class'      => 'test',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new Generic_Renderer( $story_query );\n\n\t\t$expected = 'web-stories-list alignnone test is-view-type-circles is-style-default has-title is-carousel';\n\n\t\t$output = $this->call_private_method( [ $renderer, 'get_container_classes' ] );\n\n\t\t$this->assertEquals( $expected, $output );\n\t}\n\n\t/**\n\t * @covers ::maybe_render_archive_link\n\t */\n\tpublic function test_maybe_render_archive_link(): void {\n\t\t$story_query = $this->createMock( Story_Query::class );\n\t\t$story_query->method( 'get_stories' )->willReturn( [ $this->story_model ] );\n\t\t$story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'show_title'         => true,\n\t\t\t\t'show_archive_link'  => true,\n\t\t\t\t'archive_link_label' => 'View all stories',\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new Generic_Renderer( $story_query );\n\n\t\t$archive_link = (string) get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG );\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'maybe_render_archive_link' ] );\n\t\t$output = (string) ob_get_clean();\n\n\t\t$this->assertStringContainsString( 'web-stories-list__archive-link', $output );\n\t\t$this->assertStringContainsString( $archive_link, $output );\n\t\t$this->assertStringContainsString( 'View all stories', $output );\n\t}\n\n\t/**\n\t * Test that content overlay property is set when any of title,\n\t * date or author attribute is true.\n\t */\n\tpublic function test_content_overlay_is_set(): void {\n\t\t$story_query = $this->createMock( Story_Query::class );\n\t\t$story_query->method( 'get_stories' )->willReturn( [ $this->story_model ] );\n\t\t$story_query->method( 'get_story_attributes' )->willReturn(\n\t\t\t[\n\t\t\t\t'show_title' => false,\n\t\t\t\t'show_date'  => true,\n\t\t\t]\n\t\t);\n\n\t\t$renderer = new Test_Renderer( $story_query );\n\n\t\t$overlay = $this->get_private_property( $renderer, 'content_overlay' );\n\n\t\t$this->assertTrue( $overlay );\n\t}\n\n\tpublic function test_render_link_attributes(): void {\n\t\t$filter = static fn( $attrs, $story, $position ) => [\n\t\t\t'class'                              => '123',\n\t\t\t'foo'                                => 'bar',\n\t\t\t'\"><script>console.log(1)</script>>' => 'bar',\n\t\t\t'data-tgev'                          => 'event1234',\n\t\t\t'data-tgev-metric'                   => 'ev',\n\t\t\t'data-tgev-order'                    => $position,\n\t\t];\n\n\t\tadd_filter( 'web_stories_renderer_link_attributes', $filter, 10, 3 );\n\n\t\t$renderer = new Test_Renderer( $this->story_query );\n\n\t\tob_start();\n\t\t$this->call_private_method( [ $renderer, 'render_link_attributes' ] );\n\t\t$expected = ob_get_clean();\n\n\t\tremove_filter( 'web_stories_renderer_link_attributes', $filter );\n\n\t\t$this->assertSame( 'class=\"123\" data-tgev=\"event1234\" data-tgev-metric=\"ev\" data-tgev-order=\"0\"', $expected );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Story/Embed.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Story;\n\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Story\\Embed\n */\nclass Embed extends DependencyInjectedTestCase {\n\n\tprivate Context $context;\n\n\tprivate Assets $assets;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->assets  = $this->injector->make( Assets::class );\n\t\t$this->context = $this->injector->make( Context::class );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$embed  = new \\Google\\Web_Stories\\Renderer\\Story\\Embed( $story, $this->assets, $this->context );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $embed->render( $args );\n\t\t$this->assertStringContainsString( 'test title', $render );\n\t\t$this->assertStringNotContainsString( '<img', $render );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render_with_image(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\t\t$poster_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $poster_attachment );\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertNotEmpty( $story->get_poster_portrait() );\n\t\t$this->assertNotEmpty( $story->get_poster_sizes() );\n\t\t$this->assertNotEmpty( $story->get_poster_srcset() );\n\n\t\t$embed  = new \\Google\\Web_Stories\\Renderer\\Story\\Embed( $story, $this->assets, $this->context );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $embed->render( $args );\n\t\t$this->assertStringContainsString( 'test title', $render );\n\t\t$this->assertStringContainsString( '<img', $render );\n\t\t$this->assertStringContainsString( 'loading=', $render );\n\t\t$this->assertStringContainsString( 'decoding=', $render );\n\t\t$this->assertStringContainsString( 'srcset=', $render );\n\t\t$this->assertStringContainsString( 'sizes=', $render );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render_with_image_missing_srcset_and_sizes(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertNotEmpty( $story->get_poster_portrait() );\n\t\t$this->assertEmpty( $story->get_poster_sizes() );\n\t\t$this->assertEmpty( $story->get_poster_srcset() );\n\n\t\t$embed  = new \\Google\\Web_Stories\\Renderer\\Story\\Embed( $story, $this->assets, $this->context );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $embed->render( $args );\n\t\t$this->assertStringContainsString( 'test title', $render );\n\t\t$this->assertStringContainsString( '<img', $render );\n\t\t$this->assertStringContainsString( 'loading=', $render );\n\t\t$this->assertStringContainsString( 'decoding=', $render );\n\t\t$this->assertStringNotContainsString( 'srcset=', $render );\n\t\t$this->assertStringNotContainsString( 'sizes=', $render );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Story/HTML.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Story;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse WP_Post;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Story\\HTML\n */\nclass HTML extends TestCase {\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t// When running the tests, we don't have unfiltered_html capabilities.\n\t\t// This change avoids HTML in post_content being stripped in our test posts because of KSES.\n\t\tremove_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tremove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tadd_filter( 'content_save_pre', 'wp_filter_post_kses' );\n\t\tadd_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<!DOCTYPE html><html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$actual = $this->setup_renderer( $post );\n\n\t\t$this->assertStringStartsWith( '<!DOCTYPE html>', $actual );\n\t\t$this->assertStringEndsWith( '</html>', $actual );\n\t}\n\n\t/**\n\t * @covers ::replace_html_head\n\t * @covers ::get_html_head_markup\n\t */\n\tpublic function test_replace_html_head(): void {\n\t\t$start_tag = '<meta name=\"web-stories-replace-head-start\"/>';\n\t\t$end_tag   = '<meta name=\"web-stories-replace-head-end\"/>';\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => \"<html><head>FOO{$start_tag}BAR{$end_tag}BAZ</head><body><amp-story></amp-story></body></html>\",\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$actual = $this->setup_renderer( $post );\n\n\t\t$this->assertStringContainsString( 'FOO', $actual );\n\t\t$this->assertStringContainsString( 'BAZ', $actual );\n\t\t$this->assertStringNotContainsString( 'BAR', $actual );\n\t\t$this->assertStringNotContainsString( $start_tag, $actual );\n\t\t$this->assertStringNotContainsString( $end_tag, $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-name\" content=\"Web Stories for WordPress\"', $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-version\" content=\"', $actual );\n\t\t$this->assertSame( 1, did_action( 'web_stories_story_head' ) );\n\t}\n\n\t/**\n\t * @covers ::replace_html_head\n\t * @covers ::get_html_head_markup\n\t */\n\tpublic function test_replace_html_head_malformed(): void {\n\t\t$start_tag = '<meta name=\"web-stories-replace-head-start \" />';\n\t\t$end_tag   = '<meta name=\"web-stories-replace-head-end\" />';\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => \"<html><head>FOO{$start_tag}BAR{$end_tag}BAZ</head><body><amp-story></amp-story></body></html>\",\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$actual = $this->setup_renderer( $post );\n\n\t\t$this->assertStringContainsString( 'FOO', $actual );\n\t\t$this->assertStringContainsString( 'BAZ', $actual );\n\t\t$this->assertStringNotContainsString( 'BAR', $actual );\n\t\t$this->assertStringNotContainsString( $start_tag, $actual );\n\t\t$this->assertStringNotContainsString( $end_tag, $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-name\" content=\"Web Stories for WordPress\"', $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-version\" content=\"', $actual );\n\t\t$this->assertSame( 1, did_action( 'web_stories_story_head' ) );\n\t}\n\n\t/**\n\t * @covers ::replace_html_head\n\t * @covers ::get_html_head_markup\n\t */\n\tpublic function test_replace_html_head_malformed_missing_slash(): void {\n\t\t$start_tag = '<meta name=\"web-stories-replace-head-start\">';\n\t\t$end_tag   = '<meta name=\"web-stories-replace-head-end\">';\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => \"<html><head>FOO{$start_tag}BAR{$end_tag}BAZ</head><body><amp-story></amp-story></body></html>\",\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$actual = $this->setup_renderer( $post );\n\n\t\t$this->assertStringContainsString( 'FOO', $actual );\n\t\t$this->assertStringContainsString( 'BAZ', $actual );\n\t\t$this->assertStringNotContainsString( 'BAR', $actual );\n\t\t$this->assertStringNotContainsString( $start_tag, $actual );\n\t\t$this->assertStringNotContainsString( $end_tag, $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-name\" content=\"Web Stories for WordPress\"', $actual );\n\t\t$this->assertStringContainsString( '<meta name=\"amp-story-generator-version\" content=\"', $actual );\n\t\t$this->assertSame( 1, did_action( 'web_stories_story_head' ) );\n\t}\n\n\t/**\n\t * @covers ::print_analytics\n\t */\n\tpublic function test_print_analytics(): void {\n\t\t$source   = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page></amp-story></body></html>';\n\t\t$expected = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page><amp-analytics type=\"gtag\" data-credentials=\"include\"><script type=\"application/json\">{}</script></amp-analytics></amp-story></body></html>';\n\n\t\tadd_action(\n\t\t\t'web_stories_print_analytics',\n\t\t\tstatic function (): void {\n\t\t\t\techo '<amp-analytics type=\"gtag\" data-credentials=\"include\"><script type=\"application/json\">{}</script></amp-analytics>';\n\t\t\t}\n\t\t);\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t/**\n\t\t * @var string $actual\n\t\t */\n\t\t$actual = $this->call_private_method( [ $renderer, 'print_analytics' ], [ $source ] );\n\n\t\tremove_all_actions( 'web_stories_print_analytics' );\n\n\t\t$this->assertStringContainsString( '<amp-analytics type=\"gtag\" data-credentials=\"include\"', $actual );\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::print_analytics\n\t */\n\tpublic function test_print_analytics_no_output(): void {\n\t\t$source = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t/**\n\t\t * @var string $actual\n\t\t */\n\t\t$actual = $this->call_private_method( [ $renderer, 'print_analytics' ], [ $source ] );\n\n\t\t$this->assertStringNotContainsString( '<amp-analytics type=\"gtag\" data-credentials=\"include\"', $actual );\n\t\t$this->assertSame( $source, $actual );\n\t}\n\n\t/**\n\t * @covers ::print_social_share\n\t */\n\tpublic function test_print_social_share(): void {\n\t\t$source   = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page></amp-story></body></html>';\n\t\t$expected = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page><amp-story-social-share layout=\"nodisplay\"><script type=\"application/json\">{\"shareProviders\":[{\"provider\":\"twitter\"},{\"provider\":\"linkedin\"},{\"provider\":\"email\"},{\"provider\":\"system\"}]}</script></amp-story-social-share></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t$actual = $this->call_private_method( [ $renderer, 'print_social_share' ], [ $source ] );\n\n\t\t$this->assertStringContainsString( '<amp-story-social-share layout=\"nodisplay\"><script type=\"application/json\">', $actual );\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers ::print_social_share\n\t */\n\tpublic function test_print_social_share_filter(): void {\n\t\tadd_filter( 'web_stories_share_providers', '__return_empty_array' );\n\n\t\t$source = '<html><head></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"><amp-story-page id=\"example\"><amp-story-grid-layer template=\"fill\"></amp-story-grid-layer></amp-story-page></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t$actual = $this->call_private_method( [ $renderer, 'print_social_share' ], [ $source ] );\n\n\t\tremove_filter( 'web_stories_share_providers', '__return_empty_array' );\n\n\t\t$this->assertStringNotContainsString( '<amp-story-social-share layout=\"nodisplay\"><script type=\"application/json\">', $actual );\n\t\t$this->assertSame( $source, $actual );\n\t}\n\n\t/**\n\t * @covers ::fix_incorrect_charset\n\t */\n\tpublic function test_fix_incorrect_charset(): void {\n\t\t$source = '<html><head><meta charSet=\"utf-8\" /></head><body><amp-story></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t$actual = $this->call_private_method( [ $renderer, 'fix_incorrect_charset' ], [ $source ] );\n\n\t\t$this->assertStringContainsString( '<meta charset=\"utf-8\"/>', $actual );\n\t}\n\n\t/**\n\t * @covers ::fix_malformed_script_link_tags\n\t */\n\tpublic function test_fix_malformed_script_link_tags(): void {\n\t\t$source = '<html><head><a href=\"https://cdn.ampproject.org/v0.js\">https://cdn.ampproject.org/v0.js</a><a href=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\">https://cdn.ampproject.org/v0/amp-story-1.0.js</a><link href=\"https://fonts.googleapis.com/css2?display=swap&amp;family=Roboto%3Awght%40700\" rel=\"stylesheet\" /></head><body><amp-story></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t/**\n\t\t * @var string $actual\n\t\t */\n\t\t$actual = $this->call_private_method( [ $renderer, 'fix_malformed_script_link_tags' ], [ $source ] );\n\n\t\t$this->assertStringNotContainsString( '<a ', $actual );\n\t\t$this->assertStringContainsString( '<script async src=\"https://cdn.ampproject.org/v0.js\">', $actual );\n\t\t$this->assertStringContainsString( '<script async src=\"https://cdn.ampproject.org/v0/amp-story-1.0.js\" custom-element=\"amp-story\"></script>', $actual );\n\t}\n\n\t/**\n\t * @covers ::fix_malformed_script_link_tags\n\t */\n\tpublic function test_fix_malformed_script_link_tags_keeps_other_links(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-story-page><amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://example.com\">Learn more</a></amp-story-page-outlink></amp-story-page></amp-story></body></html>';\n\n\t\t$story    = new Story();\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\n\t\t/**\n\t\t * @var string $actual\n\t\t */\n\t\t$actual = $this->call_private_method( [ $renderer, 'fix_malformed_script_link_tags' ], [ $source ] );\n\n\t\t$this->assertStringContainsString( '<amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://example.com\">Learn more</a></amp-story-page-outlink>', $actual );\n\t}\n\n\t/**\n\t * Helper to setup renderer.\n\t *\n\t * @param WP_Post $post Post Object.\n\t */\n\tprotected function setup_renderer( WP_Post $post ): string {\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\t\t$renderer = new \\Google\\Web_Stories\\Renderer\\Story\\HTML( $story );\n\t\treturn $renderer->render();\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Renderer/Story/Image.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Renderer\\Story;\n\nuse Google\\Web_Stories\\Model\\Story;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Renderer\\Story\\Image\n */\nclass Image extends TestCase {\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$image  = new \\Google\\Web_Stories\\Renderer\\Story\\Image( $story );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $image->render( $args );\n\t\t$this->assertStringContainsString( 'test title', $render );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render_with_image(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\t\t$poster_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\twp_maybe_generate_attachment_metadata( $poster_attachment );\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertNotEmpty( $story->get_poster_portrait() );\n\t\t$this->assertNotEmpty( $story->get_poster_sizes() );\n\t\t$this->assertNotEmpty( $story->get_poster_srcset() );\n\n\t\t$image  = new \\Google\\Web_Stories\\Renderer\\Story\\Image( $story );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $image->render( $args );\n\t\t$this->assertStringContainsString( '<img', $render );\n\t\t$this->assertStringContainsString( 'srcset=', $render );\n\t\t$this->assertStringContainsString( 'sizes=', $render );\n\t\t$this->assertStringContainsString( 'loading=', $render );\n\t\t$this->assertStringContainsString( 'decoding=', $render );\n\t}\n\n\t/**\n\t * @covers ::render\n\t */\n\tpublic function test_render_with_image_missing_srcset_and_sizes(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$poster_attachment_id = self::factory()->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $poster_attachment_id );\n\n\t\t$poster_attachment = get_post( $poster_attachment_id );\n\t\t$this->assertNotNull( $poster_attachment );\n\n\t\tset_post_thumbnail( $post->ID, $poster_attachment_id );\n\n\t\t$story = new Story();\n\t\t$story->load_from_post( $post );\n\n\t\t$this->assertNotEmpty( $story->get_poster_portrait() );\n\t\t$this->assertEmpty( $story->get_poster_sizes() );\n\t\t$this->assertEmpty( $story->get_poster_srcset() );\n\n\t\t$image  = new \\Google\\Web_Stories\\Renderer\\Story\\Image( $story );\n\t\t$args   = [\n\t\t\t'align'  => 'none',\n\t\t\t'height' => 600,\n\t\t\t'width'  => 360,\n\t\t];\n\t\t$render = $image->render( $args );\n\t\t$this->assertStringContainsString( '<img', $render );\n\t\t$this->assertStringNotContainsString( 'srcset=', $render );\n\t\t$this->assertStringNotContainsString( 'sizes=', $render );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Settings.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Settings\n */\nclass Settings extends DependencyInjectedTestCase {\n\n\tprivate \\Google\\Web_Stories\\Settings $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Settings::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$options = get_registered_settings();\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_EXPERIMENTS, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_TRACKING_ID, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_USING_LEGACY_ANALYTICS, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_AD_NETWORK, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_AD_MANAGER_SLOT_ID, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_ADSENSE_PUBLISHER_ID, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_ADSENSE_SLOT_ID, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_MGID_WIDGET_ID, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_EXPERIMENTS, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_PUBLISHER_LOGOS, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_VIDEO_CACHE, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_DATA_REMOVAL, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_ARCHIVE, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_AUTO_ADVANCE, $options );\n\t\t$this->assertArrayHasKey( $this->instance::SETTING_NAME_DEFAULT_PAGE_DURATION, $options );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\tadd_option( $this->instance::SETTING_NAME_EXPERIMENTS, [ 'foo' => 'bar' ] );\n\t\tadd_option( $this->instance::SETTING_NAME_TRACKING_ID, 'bar' );\n\t\tadd_option( $this->instance::SETTING_NAME_USING_LEGACY_ANALYTICS, true );\n\t\tadd_option( $this->instance::SETTING_NAME_AD_NETWORK, 'bar' );\n\t\tadd_option( $this->instance::SETTING_NAME_AD_MANAGER_SLOT_ID, 'baz' );\n\t\tadd_option( $this->instance::SETTING_NAME_ADSENSE_PUBLISHER_ID, 'baz' );\n\t\tadd_option( $this->instance::SETTING_NAME_ADSENSE_SLOT_ID, 'baz' );\n\t\tadd_option( $this->instance::SETTING_NAME_MGID_WIDGET_ID, '1234567' );\n\t\tadd_option( $this->instance::SETTING_NAME_EXPERIMENTS, [ 'foo' => 'bar' ] );\n\t\tadd_option( $this->instance::SETTING_NAME_ACTIVE_PUBLISHER_LOGO, 123 );\n\t\tadd_option( $this->instance::SETTING_NAME_PUBLISHER_LOGOS, [ 123, 567 ] );\n\t\tadd_option( $this->instance::SETTING_NAME_VIDEO_CACHE, true );\n\t\tadd_option( $this->instance::SETTING_NAME_DATA_REMOVAL, true );\n\t\tadd_option( $this->instance::SETTING_NAME_ARCHIVE, 'none' );\n\t\tadd_option( $this->instance::SETTING_NAME_AUTO_ADVANCE, true );\n\t\tadd_option( $this->instance::SETTING_NAME_DEFAULT_PAGE_DURATION, 7 );\n\n\t\t$this->instance->on_plugin_uninstall();\n\n\t\t$this->assertSame( [], get_option( $this->instance::SETTING_NAME_EXPERIMENTS ) );\n\t\t$this->assertSame( '', get_option( $this->instance::SETTING_NAME_TRACKING_ID ) );\n\t\t$this->assertFalse( get_option( $this->instance::SETTING_NAME_USING_LEGACY_ANALYTICS ) );\n\t\t$this->assertSame( 'none', get_option( $this->instance::SETTING_NAME_AD_NETWORK ) );\n\t\t$this->assertSame( '', get_option( $this->instance::SETTING_NAME_AD_MANAGER_SLOT_ID ) );\n\t\t$this->assertSame( '', get_option( $this->instance::SETTING_NAME_ADSENSE_PUBLISHER_ID ) );\n\t\t$this->assertSame( '', get_option( $this->instance::SETTING_NAME_ADSENSE_SLOT_ID ) );\n\t\t$this->assertSame( '', get_option( $this->instance::SETTING_NAME_MGID_WIDGET_ID ) );\n\t\t$this->assertSame( [], get_option( $this->instance::SETTING_NAME_EXPERIMENTS ) );\n\t\t$this->assertSame( 0, get_option( $this->instance::SETTING_NAME_ACTIVE_PUBLISHER_LOGO ) );\n\t\t$this->assertSame( [], get_option( $this->instance::SETTING_NAME_PUBLISHER_LOGOS ) );\n\t\t$this->assertFalse( get_option( $this->instance::SETTING_NAME_VIDEO_CACHE ) );\n\t\t$this->assertFalse( get_option( $this->instance::SETTING_NAME_DATA_REMOVAL ) );\n\t\t$this->assertSame( 'default', get_option( $this->instance::SETTING_NAME_ARCHIVE ) );\n\t\t$this->assertTrue( get_option( $this->instance::SETTING_NAME_AUTO_ADVANCE ) );\n\t\t$this->assertSame( 7, get_option( $this->instance::SETTING_NAME_DEFAULT_PAGE_DURATION ) );\n\t}\n\n\t/**\n\t * @covers ::get_setting\n\t */\n\tpublic function test_get_setting_uses_saved_option(): void {\n\t\tadd_option( $this->instance::SETTING_NAME_AUTO_ADVANCE, false );\n\t\t$this->assertFalse( $this->instance->get_setting( $this->instance::SETTING_NAME_AUTO_ADVANCE, true ) );\n\t}\n\n\t/**\n\t * @covers ::get_setting\n\t */\n\tpublic function test_get_setting_uses_saved_option_type(): void {\n\t\tadd_option( $this->instance::SETTING_NAME_AUTO_ADVANCE, 'no-boolean' );\n\t\t$this->assertTrue( $this->instance->get_setting( $this->instance::SETTING_NAME_AUTO_ADVANCE ) );\n\t}\n\n\t/**\n\t * @param array{type?: string, description?: string, sanitize_callback?: callable, show_in_rest?: bool|array<mixed>, default?: mixed} $args\n\t * @param mixed $value\n\t * @param mixed $expected\n\t *\n\t * @covers ::get_setting\n\t * @dataProvider data_test_types\n\t */\n\tpublic function test_get_setting_uses_type( string $name, array $args, $value, $expected ): void {\n\t\tregister_setting( 'test_group', $name, $args );\n\t\tadd_option( $name, $value );\n\t\t$this->assertSame( $expected, $this->instance->get_setting( $name ) );\n\t}\n\n\t/**\n\t * @return array<string, array<string, mixed>>\n\t */\n\tpublic static function data_test_types(): array {\n\t\treturn [\n\t\t\t'array from string' => [\n\t\t\t\t'name'     => 'array_type',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'array',\n\t\t\t\t],\n\t\t\t\t'value'    => 'string',\n\t\t\t\t'expected' => [ 'string' ],\n\t\t\t],\n\t\t\t'array key value'   => [\n\t\t\t\t'name'     => 'array_key',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'array',\n\t\t\t\t],\n\t\t\t\t'value'    => [ 'key' => 'value' ],\n\t\t\t\t'expected' => [ 'value' ],\n\t\t\t],\n\t\t\t'array of ints'     => [\n\t\t\t\t'name'     => 'array_ints',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type'         => 'array',\n\t\t\t\t\t'default'      => [],\n\t\t\t\t\t'show_in_rest' => [\n\t\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t\t'items' => [\n\t\t\t\t\t\t\t\t'type' => 'integer',\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'value'    => [ '1', '2', '3' ],\n\t\t\t\t'expected' => [ 1, 2, 3 ],\n\t\t\t],\n\n\t\t\t'array from object' => [\n\t\t\t\t'name'     => 'array_type',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type'         => 'object',\n\t\t\t\t\t'show_in_rest' => [\n\t\t\t\t\t\t'schema' => [\n\t\t\t\t\t\t\t'properties'           => [],\n\t\t\t\t\t\t\t'additionalProperties' => true,\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'value'    => [ 'key' => 'value' ],\n\t\t\t\t'expected' => [ 'key' => 'value' ],\n\t\t\t],\n\t\t\t'string to int'     => [\n\t\t\t\t'name'     => 'array_int',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'integer',\n\t\t\t\t],\n\t\t\t\t'value'    => '3',\n\t\t\t\t'expected' => 3,\n\t\t\t],\n\t\t\t'int to string'     => [\n\t\t\t\t'name'     => 'array_int',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'string',\n\t\t\t\t],\n\t\t\t\t'value'    => 3,\n\t\t\t\t'expected' => '3',\n\t\t\t],\n\t\t\t'int to boolean'    => [\n\t\t\t\t'name'     => 'array_boolean',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'boolean',\n\t\t\t\t],\n\t\t\t\t'value'    => 1,\n\t\t\t\t'expected' => true,\n\t\t\t],\n\t\t\t'string to boolean' => [\n\t\t\t\t'name'     => 'array_boolean',\n\t\t\t\t'args'     => [\n\t\t\t\t\t'type' => 'boolean',\n\t\t\t\t],\n\t\t\t\t'value'    => 'string',\n\t\t\t\t'expected' => true,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::get_setting\n\t */\n\tpublic function test_get_setting_uses_registered_default(): void {\n\t\t$this->assertTrue( $this->instance->get_setting( $this->instance::SETTING_NAME_AUTO_ADVANCE ) );\n\t}\n\n\t/**\n\t * @covers ::get_setting\n\t */\n\tpublic function test_get_setting_uses_explicit_default(): void {\n\t\t$this->assertFalse( $this->instance->get_setting( $this->instance::SETTING_NAME_AUTO_ADVANCE, false ) );\n\t\t$this->assertSame( 'foo', $this->instance->get_setting( $this->instance::SETTING_NAME_AUTO_ADVANCE, 'foo' ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shopping/Product.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shopping\\Product\n */\nclass Product extends TestCase {\n\t/**\n\t * @covers ::load_from_array\n\t */\n\tpublic function test_load_from_array(): void {\n\t\t$product_object = \\Google\\Web_Stories\\Shopping\\Product::load_from_array(\n\t\t\t[\n\t\t\t\t'aggregateRating'      => [\n\t\t\t\t\t'ratingValue' => 5,\n\t\t\t\t\t'reviewCount' => 1,\n\t\t\t\t\t'reviewUrl'   => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t],\n\t\t\t\t'ratingValue'          => 0,\n\t\t\t\t'reviewCount'          => 0,\n\t\t\t\t'reviewUrl'            => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t\t'productBrand'         => 'Google',\n\t\t\t\t'productDetails'       => 'This is a simple product.',\n\t\t\t\t'productId'            => 'wc-36',\n\t\t\t\t'productImages'        => [\n\t\t\t\t\t[\n\t\t\t\t\t\t'url' => 'http://www.example.com/wp-content/uploads/2019/01/t-shirt-with-logo-1-4.jpg',\n\t\t\t\t\t\t'alt' => '',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t\t'productPrice'         => 18,\n\t\t\t\t'productPriceCurrency' => 'USD',\n\t\t\t\t'productTitle'         => 'T-Shirt with Logo',\n\t\t\t\t'productUrl'           => 'http://www.example.com/product/t-shirt-with-logo',\n\t\t\t]\n\t\t);\n\t\t$this->assertSame( 'USD', $product_object->get_price_currency() );\n\t\t$this->assertSame( 18.0, $product_object->get_price() );\n\t\t$this->assertSame( 'wc-36', $product_object->get_id() );\n\t\t$this->assertSame( 'http://www.example.com/product/t-shirt-with-logo', $product_object->get_url() );\n\t\t$this->assertSame( 'Google', $product_object->get_brand() );\n\t\t$this->assertSame( 'This is a simple product.', $product_object->get_details() );\n\t}\n\n\t/**\n\t * @covers ::load_from_array\n\t */\n\tpublic function test_load_from_array_empty(): void {\n\t\t$product_object = \\Google\\Web_Stories\\Shopping\\Product::load_from_array( [] );\n\t\t$this->assertEmpty( $product_object->get_price_currency() );\n\t\t$this->assertEmpty( $product_object->get_price() );\n\t\t$this->assertEmpty( $product_object->get_id() );\n\t\t$this->assertEmpty( $product_object->get_url() );\n\t\t$this->assertEmpty( $product_object->get_brand() );\n\t\t$this->assertEmpty( $product_object->get_details() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shopping/Product_Meta.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Media;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shopping\\Product_Meta\n */\nclass Product_Meta extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Shopping\\Product_Meta $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Shopping\\Product_Meta::class );\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::PRODUCTS_POST_META_KEY, Story_Post_Type::POST_TYPE_SLUG ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\tupdate_post_meta( $post->ID, $this->instance::PRODUCTS_POST_META_KEY, [ 'foo' => 'bar' ] );\n\t\t$this->instance->on_plugin_uninstall();\n\n\t\t/**\n\t\t * @var array<mixed> $actual\n\t\t */\n\t\t$actual = get_post_meta( $post->ID, $this->instance::PRODUCTS_POST_META_KEY, true );\n\n\t\t$this->assertSameSets( [], $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shopping/Shopify_Query.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shopping\\Shopify_Query\n */\nclass Shopify_Query extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Shopping\\Shopify_Query $instance;\n\n\t/**\n\t * Count of the number of requests attempted.\n\t */\n\tprotected int $request_count = 0;\n\n\t/**\n\t * Most recent request body.\n\t */\n\tprotected string $request_body;\n\n\t/**\n\t * Most recent response body.\n\t */\n\tprotected string $response_body;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->request_count = 0;\n\t\t$this->request_body  = '';\n\t\t$this->response_body = '';\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Shopping\\Shopify_Query::class );\n\t}\n\n\t/**\n\t * Mock default response.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param array<string, string>  $r       HTTP request arguments.\n\t * @return array{response: array<string, int>, body?: string} Response data.\n\t */\n\tpublic function mock_response_default( $preempt, array $r ): array {\n\t\t++$this->request_count;\n\t\t$this->request_body = $r['body'];\n\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 200,\n\t\t\t],\n\t\t\t'body'     => (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/shopify_response_default.json' ),\n\t\t];\n\t}\n\n\t/**\n\t * Mock unauthorized response.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param array<string, string>  $r       HTTP request arguments.\n\t * @return array{response: array<string, int>, body?: string} Response data.\n\t */\n\tpublic function mock_response_unauthorized( $preempt, array $r ): array {\n\t\t++$this->request_count;\n\t\t$this->request_body = $r['body'];\n\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 401,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Mock 404 response.\n\t *\n\t * @param mixed  $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param array<string, string>  $r       HTTP request arguments.\n\t * @return array{response: array<string, int>, body?: string} Response data.\n\t */\n\tpublic function mock_response_not_found( $preempt, array $r ): array {\n\t\t++$this->request_count;\n\t\t$this->request_body = $r['body'];\n\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 404,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Mock extensions[code] response.\n\t *\n\t * @param mixed                 $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param array<string, string> $r       HTTP request arguments.\n\t * @return array{response: array<string, int>, body?: string} Response data.\n\t */\n\tpublic function mock_response_extensions_code( $preempt, array $r ): array {\n\t\t++$this->request_count;\n\t\t$this->request_body = $r['body'];\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 200,\n\t\t\t],\n\t\t\t'body'     => $this->response_body,\n\t\t];\n\t}\n\n\t/**\n\t * Mock no results response.\n\t *\n\t * @param mixed                 $preempt Whether to preempt an HTTP request's return value. Default false.\n\t * @param array<string, string> $r       HTTP request arguments.\n\t * @return array{response: array<string, int>, body?: string} Response data.\n\t */\n\tpublic function mock_response_no_results( $preempt, array $r ): array {\n\t\t++$this->request_count;\n\t\t$this->request_body = $r['body'];\n\n\t\treturn [\n\t\t\t'response' => [\n\t\t\t\t'code' => 200,\n\t\t\t],\n\t\t\t'body'     => (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/shopify_response_empty_search.json' ),\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_host\n\t * @covers ::get_access_token\n\t */\n\tpublic function test_fetch_remote_products_missing_credentials(): void {\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_missing_credentials', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t */\n\tpublic function test_fetch_remote_products_missing_host(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_missing_credentials', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t */\n\tpublic function test_fetch_remote_products_missing_access_token(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_missing_credentials', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t */\n\tpublic function test_fetch_remote_products_invalid_hostname(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.yourshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_invalid_hostname', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t */\n\tpublic function test_fetch_remote_products_returns_from_transient(): void {\n\t\t$search_term = '';\n\t\t$after       = '';\n\t\t$per_page    = 100;\n\t\t$orderby     = 'date';\n\t\t$order       = 'desc';\n\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\t/**\n\t\t * @var string $cache_key\n\t\t */\n\t\t$cache_key = $this->call_private_method(\n\t\t\t[ $this->instance, 'get_cache_key' ],\n\t\t\t[\n\t\t\t\t$search_term,\n\t\t\t\t$after,\n\t\t\t\t$per_page,\n\t\t\t\t$orderby,\n\t\t\t\t$order,\n\t\t\t]\n\t\t);\n\t\tset_transient(\n\t\t\t$cache_key,\n\t\t\twp_json_encode(\n\t\t\t\t[\n\t\t\t\t\t'data' => [\n\t\t\t\t\t\t'products' => [\n\t\t\t\t\t\t\t'edges'    => [],\n\t\t\t\t\t\t\t'pageInfo' => [ 'hasNextPage' => false ],\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$actual = $this->instance->get_search( $search_term, 1, $per_page, $orderby, $order );\n\n\t\t$this->assertNotWPError( $actual );\n\t\t$this->assertEqualSets(\n\t\t\t[\n\t\t\t\t'products'      => [],\n\t\t\t\t'has_next_page' => false,\n\t\t\t],\n\t\t\t$actual\n\t\t);\n\t\t$this->assertSame( 0, $this->request_count );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t */\n\tpublic function test_get_search_default_response(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_default' ], 10, 2 );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_default' ] );\n\n\t\t$this->assertNotWPError( $actual );\n\t\t$this->assertNotEmpty( $actual['products'] );\n\t\t$this->assertCount( 3, $actual['products'] );\n\t\t$this->assertSame( 1, $this->request_count );\n\t\t$this->assertStringContainsString( 'query: \"title:*\"', $this->request_body );\n\n\t\tforeach ( $actual['products'] as $product ) {\n\t\t\t$this->assertMatchesProductSchema( json_decode( (string) wp_json_encode( $product ), true ) );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t */\n\tpublic function test_get_search_unauthorized_response(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_unauthorized' ], 10, 2 );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_unauthorized' ] );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_invalid_credentials', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t */\n\tpublic function test_get_search_not_found_response(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_not_found' ], 10, 2 );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_not_found' ] );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( 'rest_invalid_credentials', $actual->get_error_code() );\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t */\n\tpublic function test_get_search_empty_search_response(): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_no_results' ], 10, 2 );\n\n\t\t$actual = $this->instance->get_search( 'some search term' );\n\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_no_results' ] );\n\n\t\t$this->assertNotWPError( $actual );\n\t\t$this->assertEmpty( $actual['products'] );\n\t\t$this->assertSame( 1, $this->request_count );\n\t\t$this->assertStringContainsString( 'query: \"title:*some search term*\"', $this->request_body );\n\t}\n\n\t/**\n\t * @return array<string, array<int, array<int, int|string>>>\n\t *\n\t * @dataProvider data_test_get_search_sort_by_query\n\t */\n\tpublic static function data_test_get_search_sort_by_query(): array {\n\t\treturn [\n\t\t\t'Default search'  => [\n\t\t\t\t[ 'some search term', 1, 100, 'date', '' ],\n\t\t\t\t[ 'sortKey: CREATED_AT', 'reverse: true' ],\n\t\t\t],\n\t\t\t'Sort title asc'  => [\n\t\t\t\t[ '', 1, 100, 'title', 'asc' ],\n\t\t\t\t[ 'sortKey: TITLE', 'reverse: false' ],\n\t\t\t],\n\t\t\t'Sort title desc' => [\n\t\t\t\t[ '', 1, 100, 'title', 'desc' ],\n\t\t\t\t[ 'sortKey: TITLE', 'reverse: true' ],\n\t\t\t],\n\t\t\t'Sort price asc'  => [\n\t\t\t\t[ '', 1, 100, 'price', 'asc' ],\n\t\t\t\t[ 'sortKey: PRICE', 'reverse: false' ],\n\t\t\t],\n\t\t\t'Sort price desc' => [\n\t\t\t\t[ '', 1, 100, 'price', 'desc' ],\n\t\t\t\t[ 'sortKey: PRICE', 'reverse: true' ],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @param array{0: string, 1: int, 2: int, 3: string, 4: string} $args\n\t * @param string[]               $expected\n\t *\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t * @dataProvider data_test_get_search_sort_by_query\n\t */\n\tpublic function test_get_search_sort_by_query( array $args, array $expected ): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_no_results' ], 10, 2 );\n\t\t$actual = $this->instance->get_search( ...$args );\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_no_results' ] );\n\t\t$this->assertNotWPError( $actual );\n\t\t$this->assertStringContainsString( $expected[0], $this->request_body );\n\t\t$this->assertStringContainsString( $expected[1], $this->request_body );\n\t}\n\n\t/**\n\t * @return array<string, string[]>\n\t *\n\t * @dataProvider data_test_get_search_extensions_code_response\n\t */\n\tpublic static function data_test_get_search_extensions_code_response(): array {\n\t\treturn [\n\t\t\t'THROTTLED'             => [\n\t\t\t\t'throttled',\n\t\t\t\t'rest_throttled',\n\t\t\t],\n\t\t\t'ACCESS_DENIED'         => [\n\t\t\t\t'access_denied',\n\t\t\t\t'rest_invalid_credentials',\n\t\t\t],\n\t\t\t'SHOP_INACTIVE'         => [\n\t\t\t\t'shop_inactive',\n\t\t\t\t'rest_inactive_shop',\n\t\t\t],\n\n\t\t\t'INTERNAL_SERVER_ERROR' => [\n\t\t\t\t'internal_server_error',\n\t\t\t\t'rest_internal_error',\n\t\t\t],\n\t\t\t'UKKNOWN_ERROR'         => [\n\t\t\t\t'unknown',\n\t\t\t\t'rest_unknown',\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::fetch_remote_products\n\t * @covers ::get_search\n\t * @covers ::get_products_query\n\t * @covers ::execute_query\n\t * @dataProvider data_test_get_search_extensions_code_response\n\t */\n\tpublic function test_get_search_extensions_code_response( string $args, string $expected ): void {\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_HOST, 'example.myshopify.com' );\n\t\tupdate_option( Settings::SETTING_NAME_SHOPIFY_ACCESS_TOKEN, '1234' );\n\n\t\t$this->response_body = (string) file_get_contents( WEB_STORIES_TEST_DATA_DIR . '/shopify_response_' . $args . '.json' );\n\n\t\tadd_filter( 'pre_http_request', [ $this, 'mock_response_extensions_code' ], 10, 2 );\n\n\t\t$actual = $this->instance->get_search( '' );\n\n\t\tremove_filter( 'pre_http_request', [ $this, 'mock_response_extensions_code' ] );\n\n\t\t$this->assertWPError( $actual );\n\t\t$this->assertSame( $expected, $actual->get_error_code() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shopping/Shopping_Vendors.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shopping;\n\nuse Google\\Web_Stories\\Interfaces\\Product_Query;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse Google\\Web_Stories\\Tests\\Integration\\Mock_Vendor_Setup;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shopping\\Shopping_Vendors\n */\nclass Shopping_Vendors extends DependencyInjectedTestCase {\n\tuse Mock_Vendor_Setup;\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Shopping\\Shopping_Vendors $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\t\t$this->setup_vendors();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Shopping\\Shopping_Vendors::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->remove_vendors();\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::get_vendors\n\t */\n\tpublic function test_get_vendors(): void {\n\t\t$vendors = $this->instance->get_vendors();\n\t\t$this->assertArrayHasKey( 'mock', $vendors );\n\t\t$this->assertArrayHasKey( 'error', $vendors );\n\t\t$this->assertArrayHasKey( 'invalid', $vendors );\n\t}\n\n\t/**\n\t * @covers ::get_vendor_class\n\t */\n\tpublic function test_get_vendor_class(): void {\n\t\t$query = $this->instance->get_vendor_class( 'mock' );\n\t\t$this->assertInstanceOf( Product_Query::class, $query );\n\t}\n\n\t/**\n\t * @covers ::get_vendor_class\n\t */\n\tpublic function test_get_vendor_class_invalid(): void {\n\t\t$query = $this->instance->get_vendor_class( 'invalid' );\n\t\t$this->assertNull( $query );\n\t}\n\n\t/**\n\t * @covers ::get_vendor_class\n\t */\n\tpublic function test_get_vendor_class_none_exist(): void {\n\t\t$query = $this->instance->get_vendor_class( 'not_exists' );\n\t\t$this->assertNull( $query );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shortcode/Embed_Shortcode.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shortcode;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode\n */\nclass Embed_Shortcode extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_shortcode( \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode::SHORTCODE_NAME );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_registers_shortcode(): void {\n\t\t$this->instance->register();\n\t\t$this->assertTrue( shortcode_exists( \\Google\\Web_Stories\\Shortcode\\Embed_Shortcode::SHORTCODE_NAME ) );\n\t}\n\n\t/**\n\t * @covers ::render_shortcode\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_shortcode(): void {\n\t\t$actual = $this->instance->render_shortcode(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t''\n\t\t);\n\n\t\t$this->assertStringContainsString( '<amp-story-player', $actual );\n\t}\n\n\t/**\n\t * @covers ::render_shortcode\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_shortcode_missing_url(): void {\n\t\t$actual = $this->instance->render_shortcode(\n\t\t\t[\n\t\t\t\t'url'    => '',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t''\n\t\t);\n\n\t\t$this->assertEmpty( $actual );\n\t}\n\n\t/**\n\t * @covers ::render_shortcode\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Embed::render\n\t */\n\tpublic function test_render_shortcode_missing_title(): void {\n\t\t$actual = $this->instance->render_shortcode(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => '',\n\t\t\t\t'align'  => 'none',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t''\n\t\t);\n\n\t\t$this->assertStringContainsString( __( 'Web Story', 'web-stories' ), $actual );\n\t}\n\n\t/**\n\t * @covers ::render_shortcode\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Image::render\n\t */\n\tpublic function test_render_shortcode_feed_no_poster(): void {\n\t\t$this->go_to( '/?feed=rss2' );\n\n\t\t$actual = $this->instance->render_shortcode(\n\t\t\t[\n\t\t\t\t'url'   => 'https://example.com/story.html',\n\t\t\t\t'title' => 'Example Story',\n\t\t\t],\n\t\t\t''\n\t\t);\n\n\t\t$this->assertStringNotContainsString( '<amp-story-player', $actual );\n\t\t$this->assertStringNotContainsString( '<img', $actual );\n\t}\n\n\t/**\n\t * @covers ::render_shortcode\n\t * @covers \\Google\\Web_Stories\\Embed_Base::render\n\t * @covers \\Google\\Web_Stories\\Embed_Base::default_attrs\n\t * @covers \\Google\\Web_Stories\\Renderer\\Story\\Image::render\n\t */\n\tpublic function test_render_shortcode_with_poster(): void {\n\t\t$this->instance->register();\n\n\t\t$this->go_to( '/?feed=rss2' );\n\n\t\t$actual = $this->instance->render_shortcode(\n\t\t\t[\n\t\t\t\t'url'    => 'https://example.com/story.html',\n\t\t\t\t'title'  => 'Example Story',\n\t\t\t\t'poster' => 'https://example.com/story.jpg',\n\t\t\t\t'width'  => 360,\n\t\t\t\t'height' => 600,\n\t\t\t],\n\t\t\t''\n\t\t);\n\n\t\t$this->assertStringNotContainsString( '<amp-story-player', $actual );\n\t\t$this->assertStringContainsString( '<img', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Shortcode/Stories_Shortcode.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Stories_Shortcode Unit Test class.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Shortcode;\n\nuse Google\\Web_Stories\\Shortcode\\Stories_Shortcode as Testee;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\TestCase;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shortcode\\Stories_Shortcode\n */\nclass Stories_Shortcode extends TestCase {\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\t// So there is an en existing story to be displayed by the shortcode.\n\t\t$factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t\t'post_title'  => 'Test Story',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function tear_down(): void {\n\t\tremove_shortcode( Testee::SHORTCODE_NAME );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::render_stories\n\t * @covers ::prepare_story_args\n\t * @covers ::prepare_story_attrs\n\t */\n\tpublic function test_render_carousel_view_in_shortcode(): void {\n\t\t$stories_shortcode = new Testee();\n\t\t$actual            = $stories_shortcode->render_stories(\n\t\t\t[\n\t\t\t\t'view' => 'carousel',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotSame( false, strpos( $actual, 'is-view-type-carousel' ) );\n\t}\n\n\t/**\n\t * @covers ::render_stories\n\t * @covers ::prepare_story_attrs\n\t * @covers ::prepare_story_args\n\t */\n\tpublic function test_render_circles_view_in_shortcode(): void {\n\t\t$stories_shortcode = new Testee();\n\t\t$actual            = $stories_shortcode->render_stories(\n\t\t\t[\n\t\t\t\t'view' => 'circles',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotSame( false, strpos( $actual, 'is-view-type-circles' ) );\n\t}\n\n\t/**\n\t * Should not fail on empty/blank string attribute.\n\t *\n\t * @covers ::render_stories\n\t * @covers ::prepare_story_attrs\n\t * @covers ::prepare_story_args\n\t */\n\tpublic function test_empty_attribute_in_shortcode(): void {\n\t\t$stories_shortcode = new Testee();\n\t\t$actual            = $stories_shortcode->render_stories( '' );\n\n\t\t$this->assertTrue( strpos( $actual, 'web-stories-list' ) > -1 );\n\t}\n\n\t/**\n\t * Stories should not be greater than 100.\n\t *\n\t * @covers ::prepare_story_args\n\t */\n\tpublic function test_max_number_for_stories(): void {\n\t\t$stories_shortcode = new Testee();\n\t\t$attributes        = [\n\t\t\t'number_of_stories'  => 1_000_000,\n\t\t\t'order'              => 'DESC',\n\t\t\t'orderby'            => 'post_title',\n\t\t\t'web_story_tag'      => '',\n\t\t\t'web_story_category' => '',\n\t\t];\n\n\t\t$args = $this->call_private_method( [ $stories_shortcode, 'prepare_story_args' ], [ $attributes ] );\n\t\t$this->assertArrayHasKey( 'posts_per_page', $args );\n\t\t$this->assertSame( 100, $args['posts_per_page'] );\n\t}\n\n\t/**\n\t * @covers ::prepare_story_attrs\n\t */\n\tpublic function test_prepare_story_attrs(): void {\n\t\t$shortcode = new Testee();\n\n\t\t$expected = [\n\t\t\t'view_type'               => 'grid',\n\t\t\t'number_of_columns'       => 2,\n\t\t\t'show_title'              => true,\n\t\t\t'show_author'             => true,\n\t\t\t'show_date'               => true,\n\t\t\t'show_excerpt'            => true,\n\t\t\t'show_story_archive_link' => false,\n\t\t\t'archive_link_label'      => 'Stories',\n\t\t\t'image_alignment'         => 'left',\n\t\t\t'class'                   => 'dummy',\n\t\t\t'circle_size'             => 200,\n\t\t\t'sharp_corners'           => false,\n\t\t];\n\n\t\t$attributes = [\n\t\t\t'view'               => 'grid',\n\t\t\t'number_of_columns'  => 2,\n\t\t\t'title'              => 'true',\n\t\t\t'author'             => 'true',\n\t\t\t'date'               => 'true',\n\t\t\t'excerpt'            => 'true',\n\t\t\t'archive_link'       => 'randomtext',\n\t\t\t'archive_link_label' => 'Stories',\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'class'              => 'dummy',\n\t\t\t'circle_size'        => '200',\n\t\t\t'sharp_corners'      => 'false',\n\t\t];\n\n\t\t$actual = $this->call_private_method( [ $shortcode, 'prepare_story_attrs' ], [ $attributes ] );\n\n\t\t$this->assertEqualSets( $expected, $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Story_Archive.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Archive as Testee;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Story_Archive\n */\nclass Story_Archive extends DependencyInjectedTestCase {\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\t/**\n\t * Archive page ID.\n\t */\n\tprotected static int $archive_page_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprotected Testee $instance;\n\n\tprivate Settings $settings;\n\n\tprivate Story_Post_Type $story_post_type;\n\n\tprotected string $redirect_location = '';\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\n\t\tself::$archive_page_id = self::factory()->post->create( [ 'post_type' => 'page' ] );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->settings        = $this->injector->make( Settings::class );\n\t\t$this->story_post_type = new Story_Post_Type( $this->settings );\n\t\t$this->instance        = new Testee( $this->settings, $this->story_post_type );\n\n\t\tadd_filter( 'wp_redirect', [ $this, 'filter_wp_redirect' ] );\n\t}\n\n\tpublic function tear_down(): void {\n\t\t$this->redirect_location = '';\n\t\tremove_filter( 'wp_redirect', [ $this, 'filter_wp_redirect' ] );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\tparent::tear_down();\n\t}\n\n\tpublic function filter_wp_redirect( string $location ): bool {\n\t\t$this->redirect_location = $location;\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\n\t\t$this->assertSame( 10, has_filter( 'pre_handle_404', [ $this->instance, 'redirect_post_type_archive_urls' ] ) );\n\t\t$this->assertSame( 10, has_action( 'wp_trash_post', [ $this->instance, 'on_remove_archive_page' ] ) );\n\t\t$this->assertSame( 10, has_action( 'delete_post', [ $this->instance, 'on_remove_archive_page' ] ) );\n\n\t\t$this->assertSame( 10, has_action( 'add_option_' . $this->settings::SETTING_NAME_ARCHIVE, [ $this->instance, 'update_archive_setting' ] ) );\n\t\t$this->assertSame( 10, has_action( 'update_option_' . $this->settings::SETTING_NAME_ARCHIVE, [ $this->instance, 'update_archive_setting' ] ) );\n\t\t$this->assertSame( 10, has_action( 'add_option_' . $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, [ $this->instance, 'update_archive_setting' ] ) );\n\t\t$this->assertSame( 10, has_action( 'update_option_' . $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, [ $this->instance, 'update_archive_setting' ] ) );\n\n\t\t$this->assertSame( 10, has_filter( 'display_post_states', [ $this->instance, 'filter_display_post_states' ] ) );\n\t\t$this->assertSame( 10, has_action( 'pre_get_posts', [ $this->instance, 'pre_get_posts' ] ) );\n\t}\n\n\n\t/**\n\t * @covers ::pre_get_posts\n\t */\n\tpublic function test_pre_get_posts_default_archive(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'default' );\n\n\t\t$archive_link = (string) get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->go_to( $archive_link );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\n\t\t$this->assertQueryTrue( 'is_archive', 'is_post_type_archive' );\n\t}\n\n\t/**\n\t * @covers ::pre_get_posts\n\t */\n\tpublic function test_pre_get_posts_custom_archive(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$archive_link = (string) get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->go_to( $archive_link );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertQueryTrue( 'is_page', 'is_singular' );\n\t}\n\n\t/**\n\t * @covers ::on_remove_archive_page\n\t */\n\tpublic function test_on_remove_archive_page_trash(): void {\n\t\t$archive_page_id = self::factory()->post->create( [ 'post_type' => 'page' ] );\n\n\t\t$this->assertNotWPError( $archive_page_id );\n\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, $archive_page_id );\n\n\t\twp_delete_post( $archive_page_id );\n\n\t\t$archive = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE );\n\n\t\t$archive_page_id = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertIsString( $archive );\n\t\t$this->assertSame( 'default', $archive );\n\t\t$this->assertSame( 0, $archive_page_id );\n\t}\n\n\t/**\n\t * @covers ::on_remove_archive_page\n\t */\n\tpublic function test_on_remove_archive_page_delete(): void {\n\t\t$archive_page_id = self::factory()->post->create( [ 'post_type' => 'page' ] );\n\n\t\t$this->assertNotWPError( $archive_page_id );\n\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, $archive_page_id );\n\n\t\twp_delete_post( $archive_page_id, true );\n\n\t\t$archive = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE );\n\t\t/**\n\t\t * @var int $archive_page_id\n\t\t */\n\t\t$archive_page_id = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertIsString( $archive );\n\t\t$this->assertSame( 'default', $archive );\n\t\t$this->assertSame( 0, $archive_page_id );\n\t}\n\n\t/**\n\t * @covers ::pre_get_posts\n\t */\n\tpublic function test_pre_get_posts_custom_archive_not_published(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t]\n\t\t);\n\n\t\t$archive_link = (string) get_post_type_archive_link( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->go_to( $archive_link );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertQueryTrue( 'is_archive', 'is_post_type_archive' );\n\t}\n\n\t/**\n\t * @covers ::filter_display_post_states\n\t */\n\tpublic function test_filter_display_post_states(): void {\n\t\t$archive_page = get_post( self::$archive_page_id );\n\t\t$this->assertNotNull( $archive_page );\n\n\t\t$actual = $this->instance->filter_display_post_states( [], $archive_page );\n\n\t\t$this->assertSame( [], $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_display_post_states\n\t */\n\tpublic function test_filter_display_post_states_custom_archive(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\t$archive_page = get_post( self::$archive_page_id );\n\t\t$this->assertNotNull( $archive_page );\n\n\t\t$actual = $this->instance->filter_display_post_states( [], $archive_page );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertEqualSetsWithIndex(\n\t\t\t[\n\t\t\t\t'web_stories_archive_page' => __( 'Web Stories Archive Page', 'web-stories' ),\n\t\t\t],\n\t\t\t$actual\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::filter_display_post_states\n\t */\n\tpublic function test_filter_display_post_states_custom_archive_not_published(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t]\n\t\t);\n\n\t\t$archive_page = get_post( self::$archive_page_id );\n\t\t$this->assertNotNull( $archive_page );\n\n\t\t$actual = $this->instance->filter_display_post_states( [], $archive_page );\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertSame( [], $actual );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_experiment_disabled(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t$query  = new \\WP_Query();\n\t\t$result = $this->instance->redirect_post_type_archive_urls( true, $query );\n\n\t\t$this->assertTrue( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_bypass(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t$query  = new \\WP_Query();\n\t\t$result = $this->instance->redirect_post_type_archive_urls( true, $query );\n\n\t\t$this->assertTrue( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_ugly_permalinks(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t// Needed so that the archive page change takes effect.\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$query  = new \\WP_Query();\n\t\t$result = $this->instance->redirect_post_type_archive_urls( false, $query );\n\n\t\t$this->assertFalse( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_pretty_permalinks(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t// Needed so that the archive page change takes effect.\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$query  = new \\WP_Query();\n\t\t$result = $this->instance->redirect_post_type_archive_urls( false, $query );\n\n\t\t$this->assertFalse( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_page(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t// Needed so that the archive page change takes effect.\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$query                    = new \\WP_Query();\n\t\t$query->query['pagename'] = $this->story_post_type::REWRITE_SLUG;\n\t\t$query->set( 'name', $this->story_post_type::REWRITE_SLUG );\n\t\t$query->set( 'page', self::$story_id );\n\n\t\tadd_filter( 'post_type_link', '__return_false' );\n\t\tadd_filter( 'post_type_archive_link', '__return_false' );\n\n\t\t$result = $this->instance->redirect_post_type_archive_urls( false, $query );\n\n\t\tremove_filter( 'post_type_link', '__return_false' );\n\t\tremove_filter( 'post_type_archive_link', '__return_false' );\n\n\t\t$this->assertFalse( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_pagename_set(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t// Needed so that the archive page change takes effect.\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$query                    = new \\WP_Query();\n\t\t$query->query['pagename'] = $this->story_post_type::REWRITE_SLUG;\n\t\t$query->set( 'pagename', $this->story_post_type::REWRITE_SLUG );\n\n\t\tadd_filter( 'post_type_archive_link', '__return_false' );\n\n\t\t$result = $this->instance->redirect_post_type_archive_urls( false, $query );\n\n\t\tremove_filter( 'post_type_archive_link', '__return_false' );\n\n\t\t$this->assertFalse( $result );\n\t\t$this->assertEmpty( $this->redirect_location );\n\t}\n\n\t/**\n\t * @covers ::redirect_post_type_archive_urls\n\t */\n\tpublic function test_redirect_post_type_archive_urls_existing_custom_page(): void {\n\t\t$this->set_permalink_structure( '/%postname%/' );\n\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\t// Needed so that the archive page change takes effect.\n\t\t$this->story_post_type->register_post_type();\n\n\t\t$query                    = new \\WP_Query();\n\t\t$query->query['pagename'] = $this->story_post_type::REWRITE_SLUG;\n\t\t$query->set( 'pagename', $this->story_post_type::REWRITE_SLUG );\n\n\t\t$result = $this->instance->redirect_post_type_archive_urls( false, $query );\n\n\t\t$this->assertFalse( $result );\n\t\t$this->assertSame( get_permalink( self::$archive_page_id ), $this->redirect_location );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Story_Post_Type.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Settings;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Story_Post_Type\n */\nclass Story_Post_Type extends DependencyInjectedTestCase {\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Story id.\n\t */\n\tprotected static int $story_id;\n\n\t/**\n\t * Archive page ID.\n\t */\n\tprotected static int $archive_page_id;\n\n\t/**\n\t * Test instance.\n\t */\n\tprotected \\Google\\Web_Stories\\Story_Post_Type $instance;\n\n\tprivate Settings $settings;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[ 'role' => 'administrator' ]\n\t\t);\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => \\Google\\Web_Stories\\Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Story_Post_Type Test Story',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t\t'post_author'  => self::$admin_id,\n\t\t\t]\n\t\t);\n\n\t\t/**\n\t\t * @var int $poster_attachment_id\n\t\t */\n\t\t$poster_attachment_id = $factory->attachment->create_object(\n\t\t\t[\n\t\t\t\t'file'           => DIR_TESTDATA . '/images/canola.jpg',\n\t\t\t\t'post_parent'    => 0,\n\t\t\t\t'post_mime_type' => 'image/jpeg',\n\t\t\t\t'post_title'     => 'Test Image',\n\t\t\t]\n\t\t);\n\n\t\tset_post_thumbnail( self::$story_id, $poster_attachment_id );\n\n\t\tself::$archive_page_id = self::factory()->post->create( [ 'post_type' => 'page' ] );\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$experiments = $this->createMock( Experiments::class );\n\t\t$experiments->method( 'is_experiment_enabled' )\n\t\t\t\t\t->willReturn( true );\n\n\t\t$this->settings = $this->injector->make( Settings::class );\n\t\t$this->instance = new \\Google\\Web_Stories\\Story_Post_Type( $this->settings );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame( 10, has_filter( 'wp_insert_post_data', [ $this->instance, 'change_default_title' ] ) );\n\t\t$this->assertSame( 10, has_filter( 'wp_insert_post_empty_content', [ $this->instance, 'filter_empty_content' ] ) );\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'bulk_post_updated_messages',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'bulk_post_updated_messages',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::get_post_type_icon\n\t */\n\tpublic function test_get_post_type_icon(): void {\n\t\t$valid = $this->call_private_method( [ $this->instance, 'get_post_type_icon' ] );\n\t\t$this->assertStringContainsString( 'data:image/svg+xml;base64', $valid );\n\t}\n\n\t/**\n\t * @covers ::register_post_type\n\t */\n\tpublic function test_register_post_type(): void {\n\n\t\t$post_type = $this->instance->register_post_type();\n\t\t$this->assertNotWPError( $post_type );\n\t\t$this->assertTrue( $post_type->has_archive );\n\t}\n\n\t/**\n\t * @covers ::register_post_type\n\t */\n\tpublic function test_register_post_type_disabled(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'disabled' );\n\t\t$post_type = $this->instance->register_post_type();\n\t\t$this->assertNotWPError( $post_type );\n\t\t$this->assertFalse( $post_type->has_archive );\n\t}\n\n\t/**\n\t * @covers ::register_post_type\n\t */\n\tpublic function test_register_post_type_default(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'default' );\n\t\t$post_type = $this->instance->register_post_type();\n\t\t$this->assertNotWPError( $post_type );\n\t\t$this->assertTrue( $post_type->has_archive );\n\t}\n\n\t/**\n\t * @covers ::register_meta\n\t */\n\tpublic function test_register_meta(): void {\n\t\t$this->instance->register_meta();\n\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::PUBLISHER_LOGO_META_KEY, $this->instance->get_slug() ) );\n\t\t$this->assertTrue( registered_meta_key_exists( 'post', $this->instance::POSTER_META_KEY, $this->instance->get_slug() ) );\n\t}\n\n\t/**\n\t * @covers ::change_default_title\n\t */\n\tpublic function test_change_default_title(): void {\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_type'    => $this->instance->get_slug(),\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t\t'post_status'  => 'auto-draft',\n\t\t\t\t'post_title'   => 'Auto draft',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\t$this->assertSame( '', $post->post_title );\n\t}\n\n\t/**\n\t * @covers ::filter_empty_content\n\t */\n\tpublic function test_filter_empty_content(): void {\n\t\t$postarr = [\n\t\t\t'post_type'             => $this->instance->get_slug(),\n\t\t\t'post_content_filtered' => 'Not empty',\n\t\t];\n\n\t\t$empty_postarr = [\n\t\t\t'post_type'             => $this->instance->get_slug(),\n\t\t\t'post_content_filtered' => '',\n\t\t];\n\n\t\t$this->assertFalse( $this->instance->filter_empty_content( false, $postarr ) );\n\t\t$this->assertFalse( $this->instance->filter_empty_content( false, $empty_postarr ) );\n\t\t$this->assertFalse( $this->instance->filter_empty_content( true, $postarr ) );\n\t\t$this->assertTrue( $this->instance->filter_empty_content( true, $empty_postarr ) );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_default(): void {\n\t\t$actual = $this->instance->get_has_archive();\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_disabled_experiments(): void {\n\t\t$this->instance = new \\Google\\Web_Stories\\Story_Post_Type( $this->settings );\n\n\t\t$actual = $this->instance->get_has_archive();\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_disabled(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'disabled' );\n\n\t\t$actual = $this->instance->get_has_archive();\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\n\t\t$this->assertFalse( $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_custom_but_no_page(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\n\t\t$actual = $this->instance->get_has_archive();\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_custom_but_invalid_page(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, PHP_INT_MAX );\n\n\t\t$actual = $this->instance->get_has_archive();\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_custom(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\t$actual = $this->instance->get_has_archive();\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\t$this->assertIsString( $actual );\n\t\t$this->assertSame( urldecode( (string) get_page_uri( self::$archive_page_id ) ), $actual );\n\t}\n\n\t/**\n\t * @covers ::get_has_archive\n\t */\n\tpublic function test_get_has_archive_custom_not_published(): void {\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE, 'custom' );\n\t\tupdate_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, self::$archive_page_id );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'draft',\n\t\t\t]\n\t\t);\n\n\t\t$actual = $this->instance->get_has_archive();\n\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE );\n\t\tdelete_option( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );\n\n\t\twp_update_post(\n\t\t\t[\n\t\t\t\t'ID'          => self::$archive_page_id,\n\t\t\t\t'post_status' => 'publish',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertTrue( $actual );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$presets = [\n\t\t\t'fillColors' => [\n\t\t\t\t[\n\t\t\t\t\t'type'     => 'conic',\n\t\t\t\t\t'stops'    =>\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color'    => [],\n\t\t\t\t\t\t\t\t'position' => 0,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color'    => [],\n\t\t\t\t\t\t\t\t'position' => 0.7,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t'rotation' => 0.5,\n\t\t\t\t],\n\t\t\t],\n\t\t\t'textColors' => [\n\t\t\t\t[\n\t\t\t\t\t'color' => [],\n\t\t\t\t],\n\t\t\t],\n\t\t\t'textStyles' => [\n\t\t\t\t[\n\t\t\t\t\t'color'              => [],\n\t\t\t\t\t'backgroundColor'    =>\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'type'     => 'conic',\n\t\t\t\t\t\t\t'stops'    => [],\n\t\t\t\t\t\t\t'rotation' => 0.5,\n\t\t\t\t\t\t],\n\t\t\t\t\t'backgroundTextMode' => 'FILL',\n\t\t\t\t\t'font'               => [],\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t\tadd_option( \\Google\\Web_Stories\\Story_Post_Type::STYLE_PRESETS_OPTION, $presets );\n\n\t\t$post = self::factory()->post->create_and_get(\n\t\t\t[\n\t\t\t\t'post_title'   => 'test title',\n\t\t\t\t'post_type'    => \\Google\\Web_Stories\\Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_content' => '<html><head></head><body><amp-story></amp-story></body></html>',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $post );\n\n\t\tadd_post_meta( $post->ID, \\Google\\Web_Stories\\Story_Post_Type::POSTER_META_KEY, [] );\n\t\tadd_post_meta( $post->ID, \\Google\\Web_Stories\\Story_Post_Type::PUBLISHER_LOGO_META_KEY, 123 );\n\n\t\t$this->instance->on_plugin_uninstall();\n\n\t\t$this->assertSame( '', get_post_meta( $post->ID, $this->instance::POSTER_META_KEY, true ) );\n\n\t\t$this->assertSame( '', get_post_meta( $post->ID, $this->instance::PUBLISHER_LOGO_META_KEY, true ) );\n\t\t$this->assertFalse( get_option( \\Google\\Web_Stories\\Story_Post_Type::STYLE_PRESETS_OPTION ) );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Story_Query.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Renderer\\Stories\\Carousel_Renderer;\nuse Google\\Web_Stories\\Story_Post_Type as Story_CPT;\nuse Google\\Web_Stories\\Story_Query as Testee;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Story_Query\n */\nclass Story_Query extends TestCase {\n\n\t/**\n\t * Class in test.\n\t */\n\tprivate static Testee $testee;\n\n\t/**\n\t * Story ID.\n\t */\n\tprivate static int $story_id;\n\n\t/**\n\t * Default story arguments.\n\t *\n\t * @var array<string, mixed>\n\t */\n\tprivate static array $default_story_args;\n\n\t/**\n\t * Runs once before any test in the class run.\n\t *\n\t * @param WP_UnitTest_Factory $factory Factory class object.\n\t */\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$testee = new Testee();\n\n\t\tself::$story_id = $factory->post->create(\n\t\t\t[\n\t\t\t\t'post_type'    => Story_CPT::POST_TYPE_SLUG,\n\t\t\t\t'post_title'   => 'Example title',\n\t\t\t\t'post_status'  => 'publish',\n\t\t\t\t'post_content' => 'Example content',\n\t\t\t]\n\t\t);\n\n\t\tself::$default_story_args = [\n\t\t\t'view_type'          => 'circles',\n\t\t\t'number_of_columns'  => 2,\n\t\t\t'show_title'         => false,\n\t\t\t'show_author'        => false,\n\t\t\t'show_date'          => false,\n\t\t\t'show_excerpt'       => false,\n\t\t\t'show_archive_link'  => false,\n\t\t\t'sharp_corners'      => false,\n\t\t\t'archive_link_label' => 'View all stories',\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'class'              => '',\n\t\t\t'circle_size'        => 150,\n\t\t];\n\t}\n\n\t/**\n\t * Test the instance.\n\t *\n\t * @covers ::render\n\t */\n\tpublic function test_render(): void {\n\t\t$this->assertInstanceOf( Carousel_Renderer::class, self::$testee->get_renderer() );\n\t}\n\n\t/**\n\t * Test that get_stories method returns valid story.\n\t *\n\t * @covers ::get_stories\n\t */\n\tpublic function test_get_stories_returns_valid_story(): void {\n\n\t\t$story_posts = self::$testee->get_stories();\n\t\t$this->assertSame( self::$story_id, $story_posts[0]->ID );\n\t}\n\n\t/**\n\t * Test count of number of stories.\n\t */\n\tpublic function test_get_stories_count(): void {\n\t\t$story_posts = self::$testee->get_stories();\n\t\t$this->assertCount( 1, $story_posts );\n\t}\n\n\t/**\n\t * Test that get_stories method returns valid story.\n\t *\n\t * @covers ::get_stories\n\t */\n\tpublic function test_get_stories_returns_empty_array(): void {\n\n\t\t$stories_obj = new Testee( [], [ 'post_type' => 'draft' ] );\n\t\t$story_posts = $stories_obj->get_stories();\n\t\t$this->assertEmpty( $story_posts );\n\t}\n\n\t/**\n\t * Test story arguments are equal.\n\t *\n\t * @covers ::get_story_attributes\n\t */\n\tpublic function test_default_story_args_equality(): void {\n\n\t\t$story_args = self::$testee->get_story_attributes();\n\t\t$this->assertEqualSetsWithIndex( self::$default_story_args, $story_args );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Story_Revisions.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse Google\\Web_Stories\\Story_Post_Type;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Story_Revisions\n */\nclass Story_Revisions extends DependencyInjectedTestCase {\n\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Story_Revisions $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Story_Revisions::class );\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register(): void {\n\t\t$this->instance->register();\n\n\t\t$this->assertSame(\n\t\t\t10,\n\t\t\thas_filter(\n\t\t\t\t'_wp_post_revision_fields',\n\t\t\t\t[\n\t\t\t\t\t$this->instance,\n\t\t\t\t\t'filter_revision_fields',\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t\t$this->assertSame( 10, has_filter( 'wp_web-story_revisions_to_keep', [ $this->instance, 'revisions_to_keep' ] ) );\n\t}\n\n\t/**\n\t * Testing the revisions_to_keep() method.\n\t *\n\t * @param int|bool|string $num      Number of revisions\n\t * @param int             $expected Expected string of CSS rules.\n\t *\n\t * @dataProvider data_test_revisions_to_keep\n\t * @covers ::revisions_to_keep\n\t */\n\tpublic function test_revisions_to_keep( $num, int $expected ): void {\n\t\t$this->assertSame( $expected, $this->instance->revisions_to_keep( $num ) );\n\t}\n\n\t/**\n\t * @return array<array{num: mixed, expected: int}>\n\t */\n\tpublic static function data_test_revisions_to_keep(): array {\n\t\treturn [\n\t\t\t[\n\t\t\t\t'num'      => 0,\n\t\t\t\t'expected' => 0,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => 10,\n\t\t\t\t'expected' => 10,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => 6,\n\t\t\t\t'expected' => 6,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => -1,\n\t\t\t\t'expected' => 10,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => '10',\n\t\t\t\t'expected' => 10,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => 'ten',\n\t\t\t\t'expected' => 0,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => true,\n\t\t\t\t'expected' => 1,\n\t\t\t],\n\t\t\t[\n\t\t\t\t'num'      => false,\n\t\t\t\t'expected' => 0,\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers ::filter_revision_fields\n\t */\n\tpublic function test_filter_revision_fields_not_an_array(): void {\n\t\t$this->assertSame(\n\t\t\t'foo',\n\t\t\t$this->instance->filter_revision_fields(\n\t\t\t\t'foo',\n\t\t\t\t[\n\t\t\t\t\t'post_type'   => 'post',\n\t\t\t\t\t'post_parent' => 0,\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::filter_revision_fields\n\t */\n\tpublic function test_filter_revision_fields_wrong_post_type(): void {\n\t\t$fields = [\n\t\t\t'post_title' => 'Post title',\n\t\t];\n\n\t\t$this->assertSame(\n\t\t\t$fields,\n\t\t\t$this->instance->filter_revision_fields(\n\t\t\t\t$fields,\n\t\t\t\t[\n\t\t\t\t\t'post_type'   => 'post',\n\t\t\t\t\t'post_parent' => 0,\n\t\t\t\t]\n\t\t\t)\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::filter_revision_fields\n\t */\n\tpublic function test_filter_revision_fields_story_post_type(): void {\n\t\t$fields = [\n\t\t\t'post_title' => 'Post title',\n\t\t];\n\n\t\t$actual = $this->instance->filter_revision_fields(\n\t\t\t$fields,\n\t\t\t[\n\t\t\t\t'post_type'   => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t\t'post_parent' => 0,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertArrayHasKey( 'post_content_filtered', $actual );\n\t}\n\n\t/**\n\t * @covers ::filter_revision_fields\n\t */\n\tpublic function test_filter_revision_fields_story_post_type_revision(): void {\n\t\t$fields = [\n\t\t\t'post_title' => 'Post title',\n\t\t];\n\n\t\t$story = self::factory()->post->create(\n\t\t\t[\n\t\t\t\t'post_type' => Story_Post_Type::POST_TYPE_SLUG,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $story );\n\n\t\t$actual = $this->instance->filter_revision_fields(\n\t\t\t$fields,\n\t\t\t[\n\t\t\t\t'post_type'   => 'revision',\n\t\t\t\t'post_parent' => $story,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertArrayHasKey( 'post_content_filtered', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Taxonomy/Taxonomy_Base.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Taxonomy;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse Google\\Web_Stories\\Tests\\Integration\\Fixture\\DummyTaxonomy;\nuse WP_Term;\nuse WP_Term_Query;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Taxonomy\\Taxonomy_Base\n */\nclass Taxonomy_Base extends DependencyInjectedTestCase {\n\n\tprivate DummyTaxonomy $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( DummyTaxonomy::class );\n\t\t$this->instance->register_taxonomy();\n\t\tself::factory()->term->create_many( 5, [ 'taxonomy' => $this->instance->get_taxonomy_slug() ] );\n\t\t$this->instance->unregister_taxonomy();\n\t}\n\n\t/**\n\t * @covers ::register_taxonomy\n\t */\n\tpublic function test_register_taxonomy(): void {\n\t\t$this->instance->register_taxonomy();\n\t\t$slug = $this->instance->get_taxonomy_slug();\n\t\t$this->assertTrue( taxonomy_exists( $slug ) );\n\t}\n\n\t/**\n\t * @covers ::unregister_taxonomy\n\t */\n\tpublic function test_unregister_taxonomy(): void {\n\t\t$this->instance->register();\n\t\t$slug = $this->instance->get_taxonomy_slug();\n\t\t$this->assertTrue( taxonomy_exists( $slug ) );\n\t\t$this->instance->unregister_taxonomy();\n\t\t$this->assertFalse( taxonomy_exists( $slug ) );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$this->instance->register();\n\t\t$term_query = new WP_Term_Query();\n\n\t\t/**\n\t\t * @var WP_Term[] $terms\n\t\t */\n\t\t$terms = $term_query->query(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->instance->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertCount( 5, $terms );\n\t\t$this->instance->on_plugin_uninstall();\n\t\t$term_query = new WP_Term_Query();\n\n\t\t/**\n\t\t * @var WP_Term[] $terms\n\t\t */\n\t\t$terms = $term_query->query(\n\t\t\t[\n\t\t\t\t'taxonomy'   => $this->instance->get_taxonomy_slug(),\n\t\t\t\t'hide_empty' => false,\n\t\t\t]\n\t\t);\n\t\t$this->assertEqualSets( [], $terms );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Tracking.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\nuse _WP_Dependency;\nuse Google\\Web_Stories\\Assets;\nuse Google\\Web_Stories\\Context;\nuse Google\\Web_Stories\\Experiments;\nuse Google\\Web_Stories\\Integrations\\Site_Kit;\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\Settings;\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\User\\Preferences;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Tracking\n */\nclass Tracking extends DependencyInjectedTestCase {\n\tprotected static int $user_id;\n\n\t/**\n\t * @var Site_Kit & MockObject\n\t */\n\tprivate $site_kit;\n\n\t/**\n\t * @var WooCommerce & MockObject\n\t */\n\tprivate $woocommerce;\n\n\t/**\n\t * @var \\Google\\Web_Stories\\Experiments & MockObject\n\t */\n\tprivate $experiments;\n\n\tprivate \\Google\\Web_Stories\\Tracking $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$user_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->experiments = $this->createMock( Experiments::class );\n\t\t$this->site_kit    = $this->createMock( Site_Kit::class );\n\t\t$assets            = $this->injector->make( Assets::class );\n\t\t$settings          = $this->injector->make( Settings::class );\n\t\t$preferences       = $this->injector->make( Preferences::class );\n\t\t$context           = $this->injector->make( Context::class );\n\t\t$this->woocommerce = $this->createMock( WooCommerce::class );\n\t\t$this->instance    = new \\Google\\Web_Stories\\Tracking(\n\t\t\t$this->experiments,\n\t\t\t$this->site_kit,\n\t\t\t$assets,\n\t\t\t$settings,\n\t\t\t$preferences,\n\t\t\t$this->woocommerce,\n\t\t\t$context\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::register\n\t */\n\tpublic function test_register_tracking_script(): void {\n\t\tglobal $current_screen;\n\n\t\t$current_screen = convert_to_screen( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->site_kit->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed'       => true,\n\t\t\t\t'active'          => true,\n\t\t\t\t'analyticsActive' => true,\n\t\t\t\t'link'            => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->experiments->method( 'get_enabled_experiments' )\n\t\t\t\t\t->willReturn( [ 'enableFoo', 'enableBar' ] );\n\n\t\t$this->instance->register();\n\t\t$this->instance->enqueue_assets( 'web-story' );\n\n\t\t/**\n\t\t * An array of all registered dependencies keyed by handle.\n\t\t *\n\t\t * @var array<string, _WP_Dependency> $registered\n\t\t */\n\t\t$registered = wp_scripts()->registered;\n\n\t\t$this->assertTrue( wp_script_is( \\Google\\Web_Stories\\Tracking::SCRIPT_HANDLE, 'registered' ) );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\Tracking::SCRIPT_HANDLE, $registered );\n\t\t$handle = $registered[ \\Google\\Web_Stories\\Tracking::SCRIPT_HANDLE ];\n\n\t\t$this->assertEmpty( $handle->src );\n\t\t$after = wp_scripts()->get_data( \\Google\\Web_Stories\\Tracking::SCRIPT_HANDLE, 'after' );\n\t\t$this->assertNotEmpty( $after );\n\t}\n\n\t/**\n\t * @covers ::get_settings\n\t */\n\tpublic function test_get_settings(): void {\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$this->site_kit->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed'       => true,\n\t\t\t\t'active'          => true,\n\t\t\t\t'analyticsActive' => true,\n\t\t\t\t'link'            => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->experiments->method( 'get_enabled_experiments' )\n\t\t\t\t\t->willReturn( [ 'enableFoo', 'enableBar' ] );\n\n\t\t$settings = $this->instance->get_settings();\n\n\t\t$this->assertArrayHasKey( 'trackingAllowed', $settings );\n\t\t$this->assertArrayHasKey( 'trackingId', $settings );\n\t\t$this->assertArrayHasKey( 'trackingIdGA4', $settings );\n\t\t$this->assertArrayHasKey( 'appVersion', $settings );\n\t\t$this->assertArrayHasKey( 'userProperties', $settings );\n\t\t$this->assertFalse( $settings['trackingAllowed'] );\n\t\t$this->assertSame( \\Google\\Web_Stories\\Tracking::TRACKING_ID, $settings['trackingId'] );\n\t\t$this->assertSame( \\Google\\Web_Stories\\Tracking::TRACKING_ID_GA4, $settings['trackingIdGA4'] );\n\t\t$this->assertSame( WEBSTORIES_VERSION, $settings['appVersion'] );\n\n\t\t$this->assertIsArray( $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'siteLocale', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'userLocale', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'userRole', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'enabledExperiments', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'wpVersion', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'phpVersion', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'isMultisite', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'adNetwork', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'analytics', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'serverEnvironment', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'activePlugins', $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'pluginVersion', $settings['userProperties'] );\n\t\t$this->assertSame( get_locale(), $settings['userProperties']['siteLocale'] );\n\t\t$this->assertSame( get_user_locale(), $settings['userProperties']['userLocale'] );\n\t\t$this->assertSame( wp_get_environment_type(), $settings['userProperties']['serverEnvironment'] );\n\t\t$this->assertSame( PHP_VERSION, $settings['userProperties']['phpVersion'] );\n\t\t$this->assertSame( get_bloginfo( 'version' ), $settings['userProperties']['wpVersion'] );\n\t\t$this->assertSame( 'administrator', $settings['userProperties']['userRole'] );\n\t\t$this->assertSame( 'enableFoo,enableBar', $settings['userProperties']['enabledExperiments'] );\n\t\t$this->assertSame( WEBSTORIES_VERSION, $settings['userProperties']['pluginVersion'] );\n\t\t$this->assertIsInt( $settings['userProperties']['isMultisite'] );\n\t\t$this->assertIsString( $settings['userProperties']['adNetwork'] );\n\t\t$this->assertIsString( $settings['userProperties']['analytics'] );\n\t\t$this->assertIsString( $settings['userProperties']['activePlugins'] );\n\t}\n\n\t/**\n\t * @covers ::get_settings\n\t */\n\tpublic function test_get_settings_with_optin(): void {\n\t\twp_set_current_user( self::$user_id );\n\t\tadd_user_meta( get_current_user_id(), Preferences::OPTIN_META_KEY, true );\n\n\t\t$this->site_kit->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed'       => true,\n\t\t\t\t'active'          => true,\n\t\t\t\t'analyticsActive' => true,\n\t\t\t\t'link'            => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->experiments->method( 'get_enabled_experiments' )\n\t\t\t\t\t->willReturn( [ 'enableFoo', 'enableBar' ] );\n\n\t\t$settings         = $this->instance->get_settings();\n\t\t$tracking_allowed = $settings['trackingAllowed'];\n\n\t\tdelete_user_meta( get_current_user_id(), Preferences::OPTIN_META_KEY );\n\n\t\t$this->assertTrue( $tracking_allowed );\n\t}\n\n\t/**\n\t * @covers ::get_settings\n\t */\n\tpublic function test_get_settings_with_woo(): void {\n\t\twp_set_current_user( self::$user_id );\n\n\t\t$this->site_kit->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed'       => true,\n\t\t\t\t'active'          => true,\n\t\t\t\t'analyticsActive' => true,\n\t\t\t\t'link'            => 'https://example.com',\n\t\t\t]\n\t\t);\n\n\t\t$this->woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->experiments->method( 'get_enabled_experiments' )->willReturn( [ 'enableFoo', 'enableBar' ] );\n\n\t\t$settings = $this->instance->get_settings();\n\n\t\t$this->assertIsArray( $settings['userProperties'] );\n\t\t$this->assertArrayHasKey( 'activePlugins', $settings['userProperties'] );\n\t\t$this->assertIsString( $settings['userProperties']['activePlugins'] );\n\t\t$this->assertStringContainsString( 'woocommerce', $settings['userProperties']['activePlugins'] );\n\t}\n\n\t/**\n\t * @covers ::get_user_properties\n\t */\n\tpublic function test_get_settings_user_malformed_roles(): void {\n\t\t$user_id = self::factory()->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\t$this->assertNotWPError( $user_id );\n\n\t\twp_set_current_user( $user_id );\n\n\t\tglobal $current_user;\n\t\t$current_user->roles = [ 1 => 'administrator' ];\n\n\t\t$this->site_kit->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed'       => true,\n\t\t\t\t'active'          => true,\n\t\t\t\t'analyticsActive' => true,\n\t\t\t\t'link'            => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->experiments->method( 'get_enabled_experiments' )\n\t\t\t->willReturn( [ 'enableFoo', 'enableBar' ] );\n\n\t\t$settings = $this->instance->get_settings();\n\n\t\t$this->assertIsArray( $settings['userProperties'] );\n\t\t$this->assertSame( 'administrator', $settings['userProperties']['userRole'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/User/Capabilities.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\User;\n\nuse Google\\Web_Stories\\Story_Post_Type;\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\User\\Capabilities\n */\nclass Capabilities extends DependencyInjectedTestCase {\n\tprivate \\Google\\Web_Stories\\User\\Capabilities $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\User\\Capabilities::class );\n\t}\n\n\t/**\n\t * @covers ::add_caps_to_roles\n\t */\n\tpublic function test_add_caps_to_roles(): void {\n\t\t$post_type_object = get_post_type_object( Story_Post_Type::POST_TYPE_SLUG );\n\n\t\t$this->assertNotNull( $post_type_object );\n\n\t\t$all_capabilities = array_values( (array) $post_type_object->cap );\n\n\t\t$this->instance->add_caps_to_roles();\n\n\t\t$administrator = get_role( 'administrator' );\n\t\t$editor        = get_role( 'editor' );\n\n\t\t$this->assertNotNull( $administrator );\n\t\t$this->assertNotNull( $editor );\n\n\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t$this->assertTrue( $administrator->has_cap( $cap ) );\n\t\t\t$this->assertTrue( $editor->has_cap( $cap ) );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::remove_caps_from_roles\n\t */\n\tpublic function test_remove_caps_from_roles(): void {\n\t\t$this->instance->remove_caps_from_roles();\n\n\t\t$post_type_object = get_post_type_object( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\t\t$all_capabilities = array_values( (array) $post_type_object->cap );\n\t\t$all_capabilities = array_filter(\n\t\t\t$all_capabilities,\n\t\t\tstatic fn( $value ) => 'read' !== $value\n\t\t);\n\t\t$all_roles        = wp_roles();\n\t\t$roles            = array_values( (array) $all_roles->role_objects );\n\n\t\tforeach ( $roles as $role ) {\n\t\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t\t$this->assertFalse( $role->has_cap( $cap ) );\n\t\t\t}\n\t\t\t$this->assertTrue( $role->has_cap( 'read' ) );\n\t\t}\n\t}\n\n\t/**\n\t * @covers ::add_caps_to_roles\n\t * @group ms-required\n\t */\n\tpublic function test_add_caps_to_roles_multisite(): void {\n\t\t$blog_id = self::factory()->blog->create();\n\n\t\t$this->assertNotWPError( $blog_id );\n\n\t\tswitch_to_blog( $blog_id );\n\n\t\t$this->instance->add_caps_to_roles();\n\n\t\t$post_type_object = get_post_type_object( Story_Post_Type::POST_TYPE_SLUG );\n\t\t$this->assertNotNull( $post_type_object );\n\t\t$all_capabilities = array_values( (array) $post_type_object->cap );\n\n\t\t$administrator = get_role( 'administrator' );\n\t\t$editor        = get_role( 'editor' );\n\n\t\t$this->assertNotNull( $administrator );\n\t\t$this->assertNotNull( $editor );\n\n\t\trestore_current_blog();\n\n\t\tforeach ( $all_capabilities as $cap ) {\n\t\t\t$this->assertTrue( $administrator->has_cap( $cap ) );\n\t\t\t$this->assertTrue( $editor->has_cap( $cap ) );\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/User/Preferences.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\User;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\nuse WP_REST_Request;\nuse WP_UnitTest_Factory;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\User\\Preferences\n */\nclass Preferences extends DependencyInjectedTestCase {\n\t/**\n\t * Admin user for test.\n\t */\n\tprotected static int $admin_id;\n\n\t/**\n\t * Author user for test.\n\t */\n\tprotected static int $author_id;\n\n\tprivate \\Google\\Web_Stories\\User\\Preferences $instance;\n\n\tpublic static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ): void {\n\t\tself::$admin_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'administrator',\n\t\t\t]\n\t\t);\n\n\t\tself::$author_id = $factory->user->create(\n\t\t\t[\n\t\t\t\t'role' => 'author',\n\t\t\t]\n\t\t);\n\t}\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\User\\Preferences::class );\n\t}\n\n\tpublic function tear_down(): void {\n\t\tdelete_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY );\n\t\tdelete_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY );\n\t\tdelete_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY );\n\t\tdelete_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY );\n\n\t\tunregister_meta_key( 'user', \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY );\n\t\tunregister_meta_key( 'user', \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY );\n\t\tunregister_meta_key( 'user', \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY );\n\n\t\tparent::tear_down();\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::can_edit_current_user\n\t */\n\tpublic function test_add_optin_field_to_rest_api(): void {\n\t\t$this->instance->register();\n\n\t\twp_set_current_user( self::$admin_id );\n\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, true );\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, true );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, \\sprintf( '/wp/v2/users/%d', self::$admin_id ) );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'meta', $data );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, $data['meta'] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY ] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY ] );\n\t\t$this->assertEqualSets( [], $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::can_edit_current_user\n\t */\n\tpublic function test_add_optin_field_to_rest_api_for_author_user(): void {\n\t\t$this->instance->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, true );\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, true );\n\n\t\t$request  = new WP_REST_Request( \\WP_REST_Server::READABLE, '/wp/v2/users/me' );\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'meta', $data );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY, $data['meta'] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY ] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY ] );\n\t\t$this->assertEqualSets( [], $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::can_edit_current_user\n\t */\n\tpublic function test_enables_author_user_to_update_meta_field(): void {\n\t\t$this->instance->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, false );\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, false );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/wp/v2/users/me' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'meta' => [\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY              => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY         => [\n\t\t\t\t\t\t'hello' => 'world',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$data     = $response->get_data();\n\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'meta', $data );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, $data['meta'] );\n\t\t$this->assertArrayHasKey( \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY, $data['meta'] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY ] );\n\t\t$this->assertTrue( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY ] );\n\t\t$this->assertArrayHasKey( 'hello', $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY ] );\n\t\t$this->assertIsArray( $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY ] );\n\t\t$this->assertEqualSets( [ 'hello' => 'world' ], $data['meta'][ \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY ] );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::can_edit_current_user\n\t */\n\tpublic function test_permission_check_for_authors(): void {\n\t\t$this->instance->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, false );\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, false );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/wp/v2/users/' . self::$admin_id );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'meta' => [\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY              => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY         => [\n\t\t\t\t\t\t'hello' => 'world',\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$response = $response->as_error();\n\n\t\t$this->assertWPError( $response );\n\t\t$this->assertSame( 'rest_cannot_edit', $response->get_error_code() );\n\t\t$data = $response->get_error_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'status', $data );\n\t\t$this->assertEquals( 403, $data['status'] );\n\t}\n\n\t/**\n\t * @covers ::on_plugin_uninstall\n\t */\n\tpublic function test_on_plugin_uninstall(): void {\n\t\t$this->instance->register();\n\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, true );\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, false );\n\t\tadd_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY, true );\n\n\t\t$this->instance->on_plugin_uninstall();\n\n\t\t$this->assertFalse( get_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, true ) );\n\t\t$this->assertTrue( get_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, true ) );\n\t\t$this->assertSame( [], get_user_meta( self::$admin_id, \\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY, true ) );\n\t}\n\n\t/**\n\t * @covers ::register\n\t * @covers ::can_edit_current_user\n\t */\n\tpublic function test_enables_author_user_to_invalid_type(): void {\n\t\t$this->instance->register();\n\n\t\twp_set_current_user( self::$author_id );\n\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY, false );\n\t\tadd_user_meta( self::$author_id, \\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY, false );\n\n\t\t$request = new WP_REST_Request( \\WP_REST_Server::CREATABLE, '/wp/v2/users/me' );\n\t\t$request->set_body_params(\n\t\t\t[\n\t\t\t\t'meta' => [\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::OPTIN_META_KEY              => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::MEDIA_OPTIMIZATION_META_KEY => true,\n\t\t\t\t\t\\Google\\Web_Stories\\User\\Preferences::ONBOARDING_META_KEY         => false,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$response = rest_get_server()->dispatch( $request );\n\t\t$response = $response->as_error();\n\n\t\t$this->assertWPError( $response );\n\t\t$data = $response->get_error_data();\n\t\t$this->assertIsArray( $data );\n\t\t$this->assertArrayHasKey( 'status', $data );\n\t\t$this->assertEquals( 400, $data['status'] );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Web_Stories_Compatibility.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration;\n\n/**\n * @coversDefaultClass \\Web_Stories_Compatibility\n */\nclass Web_Stories_Compatibility extends TestCase {\n\tprotected \\Web_Stories_Compatibility $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = \\web_stories_get_compat_instance();\n\t\t$extensions     = [\n\t\t\t'fake_extension' => [\n\t\t\t\t'classes'   => [\n\t\t\t\t\t'FAKE_CLASS',\n\t\t\t\t],\n\t\t\t\t'functions' => [\n\t\t\t\t\t'fake_function',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t\t$this->instance->set_extensions( $extensions );\n\t}\n\n\t/**\n\t * @covers ::check_extensions\n\t */\n\tpublic function test_check_extensions(): void {\n\t\t$results = $this->instance->check_extensions();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'missing_extension', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( 'fake_extension', $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_classes\n\t */\n\tpublic function test_check_classes(): void {\n\t\t$results = $this->instance->check_classes();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'missing_class', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( 'FAKE_CLASS', $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_functions\n\t */\n\tpublic function test_check_functions(): void {\n\t\t$results = $this->instance->check_functions();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'missing_function', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( 'fake_function', $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_wp_version\n\t */\n\tpublic function test_check_wp_version(): void {\n\t\t$this->instance->set_wp_version( '10.0.0' );\n\t\t$results = $this->instance->check_wp_version();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'failed_check_wp_version', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( $this->instance->get_wp_version(), $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_php_version\n\t */\n\tpublic function test_check_php_version(): void {\n\t\t$this->instance->set_php_version( '10.0.0' );\n\t\t$results = $this->instance->check_php_version();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'failed_check_php_version', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( $this->instance->get_php_version(), $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_required_files\n\t */\n\tpublic function test_check_required_files(): void {\n\t\t$this->instance->set_required_files( [ WEBSTORIES_PLUGIN_DIR_PATH . '/assets/js/fake.js' ] );\n\t\t$results = $this->instance->check_required_files();\n\t\t$this->assertFalse( $results );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'failed_check_required_files', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( 'You appear to be running an incomplete version of the plugin.', $error_message );\n\t}\n\n\t/**\n\t * @covers ::check_required_files\n\t * @covers ::add_to_error\n\t */\n\tpublic function test_add_to_error(): void {\n\t\t$this->instance->set_required_files( [ WEBSTORIES_PLUGIN_DIR_PATH . '/assets/js/fake.js' ] );\n\t\t$results  = $this->instance->check_required_files();\n\t\t$results2 = $this->instance->check_required_files();\n\t\t$this->assertFalse( $results );\n\t\t$this->assertFalse( $results2 );\n\t\t$error       = $this->instance->get_error();\n\t\t$error_codes = $error->get_error_codes();\n\t\t$this->assertContains( 'failed_check_required_files', $error_codes );\n\t\t$error_message = $error->get_error_message();\n\t\t$this->assertStringContainsString( 'You appear to be running an incomplete version of the plugin.', $error_message );\n\t\t$messages = $error->get_error_messages( 'failed_check_required_files' );\n\t\t$this->assertCount( 1, $messages );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/integration/tests/Widgets/Stories.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Integration\\Widgets;\n\nuse Google\\Web_Stories\\Tests\\Integration\\DependencyInjectedTestCase;\n\n/**\n * Class Stories\n *\n * @coversDefaultClass \\Google\\Web_Stories\\Widgets\\Stories\n */\nclass Stories extends DependencyInjectedTestCase {\n\t/**\n\t * Test instance.\n\t */\n\tprivate \\Google\\Web_Stories\\Widgets\\Stories $instance;\n\n\t/**\n\t * Runs before any method in class is run.\n\t */\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->instance = $this->injector->make( \\Google\\Web_Stories\\Widgets\\Stories::class );\n\t}\n\n\t/**\n\t * Test ID Base is set.\n\t */\n\tpublic function test_id_base(): void {\n\t\t$this->assertEquals( 'string', \\gettype( $this->instance->id_base ) );\n\t\t$this->assertNotEmpty( $this->instance->id_base );\n\t}\n\n\t/**\n\t * Test name is set.\n\t */\n\tpublic function test_name(): void {\n\t\t$this->assertEquals( 'string', \\gettype( $this->instance->name ) );\n\t\t$this->assertNotEmpty( $this->instance->name );\n\t}\n\n\t/**\n\t * @covers ::enqueue_scripts\n\t */\n\tpublic function test_enqueue_scripts(): void {\n\t\t$this->instance->enqueue_scripts();\n\t\t$this->assertTrue( wp_script_is( 'web-stories-widget' ) );\n\t}\n\n\t/**\n\t * @covers ::update\n\t */\n\tpublic function test_update(): void {\n\t\t$new_instance = [\n\t\t\t'title'              => '<p>Test Stories</p>',\n\t\t\t'view_type'          => 'list',\n\t\t\t'show_title'         => '1',\n\t\t\t'number_of_stories'  => 100,\n\t\t\t'circle_size'        => 150,\n\t\t\t'archive_link_label' => 'View Stories',\n\t\t\t'number_of_columns'  => 2,\n\t\t\t'sharp_corners'      => 1,\n\t\t];\n\n\t\t$old_instance = [];\n\n\t\t$expected = [\n\t\t\t'title'              => 'Test Stories',\n\t\t\t'view_type'          => 'list',\n\t\t\t'show_title'         => 1,\n\t\t\t'show_author'        => '',\n\t\t\t'show_excerpt'       => '',\n\t\t\t'show_date'          => '',\n\t\t\t'show_archive_link'  => '',\n\t\t\t'image_alignment'    => 'left',\n\t\t\t'number_of_stories'  => 20,\n\t\t\t'circle_size'        => 150,\n\t\t\t'archive_link_label' => 'View Stories',\n\t\t\t'number_of_columns'  => 2,\n\t\t\t'sharp_corners'      => 1,\n\t\t\t'orderby'            => 'post_date',\n\t\t\t'order'              => 'DESC',\n\t\t];\n\n\t\t$instance = $this->instance->update( $new_instance, $old_instance );\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $instance );\n\t}\n\n\t/**\n\t * @covers ::update\n\t * @covers ::default_values\n\t */\n\tpublic function test_update_default(): void {\n\t\t$new_instance = [];\n\n\t\t$old_instance = [];\n\n\t\t$expected = $this->call_private_method( [ $this->instance, 'default_values' ] );\n\n\t\t$instance = $this->instance->update( $new_instance, $old_instance );\n\n\t\t$this->assertEqualSetsWithIndex( $expected, $instance );\n\t}\n\n\t/**\n\t * @covers ::input\n\t * @covers ::label\n\t */\n\tpublic function test_input(): void {\n\t\t$function = function (): void {\n\t\t\t$args = [\n\t\t\t\t'label' => 'Test input',\n\t\t\t\t'value' => 3,\n\t\t\t];\n\t\t\t$this->call_private_method( [ $this->instance, 'input' ], [ $args ] );\n\t\t};\n\n\t\t$dropdown = get_echo( $function );\n\n\t\t$this->assertStringContainsString( 'Test input', $dropdown );\n\t\t$this->assertStringContainsString( '<input', $dropdown );\n\t\t$this->assertStringContainsString( '<label', $dropdown );\n\t}\n\n\t/**\n\t * @covers ::dropdown\n\t * @covers ::label\n\t */\n\tpublic function test_dropdown(): void {\n\t\t$function = function (): void {\n\t\t\t$args = [\n\t\t\t\t'label'    => 'Test input',\n\t\t\t\t'options'  => range( 'A', 'Z' ),\n\t\t\t\t'selected' => 3,\n\t\t\t];\n\t\t\t$this->call_private_method( [ $this->instance, 'dropdown' ], [ $args ] );\n\t\t};\n\n\t\t$dropdown = get_echo( $function );\n\n\t\t$this->assertStringContainsString( 'Test input', $dropdown );\n\t\t$this->assertStringContainsString( 'selected=', $dropdown );\n\t\t$this->assertStringContainsString( '<select', $dropdown );\n\t\t$this->assertStringContainsString( '<label', $dropdown );\n\t}\n\n\t/**\n\t * @covers ::radio\n\t * @covers ::label\n\t */\n\tpublic function test_radio(): void {\n\t\t$function = function (): void {\n\t\t\t$args = [\n\t\t\t\t'label'    => 'Test input',\n\t\t\t\t'options'  => range( 'A', 'Z' ),\n\t\t\t\t'selected' => 3,\n\t\t\t];\n\t\t\t$this->call_private_method( [ $this->instance, 'radio' ], [ $args ] );\n\t\t};\n\n\t\t$radio = get_echo( $function );\n\n\t\t$this->assertStringContainsString( 'Test input', $radio );\n\t\t$this->assertStringContainsString( 'checked=', $radio );\n\t\t$this->assertStringContainsString( '<input', $radio );\n\t\t$this->assertStringContainsString( '<label', $radio );\n\t}\n\n\t/**\n\t * @covers ::label\n\t */\n\tpublic function test_label(): void {\n\t\t$args = [\n\t\t\t'label' => 'Test input',\n\t\t\t'id'    => '123',\n\t\t];\n\n\t\t$label = $this->call_private_method( [ $this->instance, 'label' ], [ $args ] );\n\n\t\t$this->assertStringContainsString( 'Test input', $label );\n\t\t$this->assertStringContainsString( '<label', $label );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/shared/Private_Access.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Shared;\n\nuse ReflectionClass;\nuse ReflectionException;\n\n/**\n * Trait Private_Access.\n *\n * Allows accessing private methods and properties for testing.\n *\n * @internal\n */\ntrait Private_Access {\n\n\t/**\n\t * Call a private method as if it was public.\n\t *\n\t * @throws ReflectionException If the object could not be reflected upon.\n\t *\n\t * @param callable|array $callback Object instance or class string to call the method of.\n\t * @param array          $args     Optional. Array of arguments to pass to the method.\n\t * @return mixed Return value of the method call.\n\t *\n\t * @template C\n\t * @template A\n\t *\n\t * @phpstan-param callable(A): C $callback\n\t * @phpstan-param array<A> $args\n\t * @phpstan-return C\n\t */\n\tprotected function call_private_method( $callback, array $args = [] ) {\n\t\t$method = ( new ReflectionClass( $callback[0] ) )->getMethod( $callback[1] );\n\t\tif ( PHP_VERSION_ID < 80100 ) {\n\t\t\t$method->setAccessible( true );\n\t\t}\n\t\treturn $method->invokeArgs( $callback[0], $args );\n\t}\n\n\t/**\n\t * Call a private static method as if it was public.\n\t *\n\t * @throws ReflectionException If the class could not be reflected upon.\n\t *\n\t * @param callable|array $callback Object instance or class string to call the method of.\n\t * @param array          $args     Optional. Array of arguments to pass to the method.\n\t * @return mixed Return value of the method call.\n\t *\n\t * @template C\n\t * @template A\n\t *\n\t * @phpstan-param array<A> $args\n\t * @phpstan-param callable(A): C $callback\n\t * @phpstan-return C\n\t */\n\tprotected function call_private_static_method( $callback, array $args = [] ) {\n\t\t$method = ( new ReflectionClass( $callback[0] ) )->getMethod( $callback[1] );\n\t\tif ( PHP_VERSION_ID < 80100 ) {\n\t\t\t$method->setAccessible( true );\n\t\t}\n\t\treturn $method->invokeArgs( null, $args );\n\t}\n\n\t/**\n\t * Set a private property as if it was public.\n\t *\n\t * @throws ReflectionException If the object could not be reflected upon.\n\t *\n\t * @param object|string $instance      Object instance or class string to set the property of.\n\t * @param string        $property_name Name of the property to set.\n\t * @param mixed         $value         Value to set the property to.\n\t */\n\tprotected function set_private_property( $instance, string $property_name, $value ): void {\n\t\t$reflection_class = new ReflectionClass( $instance );\n\t\t$property         = $reflection_class->getProperty( $property_name );\n\t\tif ( PHP_VERSION_ID < 80100 ) {\n\t\t\t$property->setAccessible( true );\n\t\t}\n\n\t\t$property->isStatic() ? $reflection_class->setStaticPropertyValue( $property_name, $value ) : $property->setValue( $instance, $value );\n\t}\n\n\t/**\n\t * Get a private property as if it was public.\n\t *\n\t * @throws ReflectionException If the object could not be reflected upon.\n\t *\n\t * @param object|string $instance      Object instance or class string to get the property of.\n\t * @param string        $property_name Name of the property to get.\n\t * @return mixed Return value of the property.\n\t */\n\tprotected function get_private_property( $instance, string $property_name ) {\n\t\t$property = ( new ReflectionClass( $instance ) )->getProperty( $property_name );\n\t\tif ( PHP_VERSION_ID < 80100 ) {\n\t\t\t$property->setAccessible( true );\n\t\t}\n\t\treturn $property->getValue( $instance );\n\t}\n\n\t/**\n\t * Get a static private property as if it was public.\n\t *\n\t * @throws ReflectionException If the class could not be reflected upon.\n\t *\n\t * @param string $class_name    Class string to get the property of.\n\t * @param string $property_name Name of the property to get.\n\t * @return mixed Return value of the property.\n\t */\n\tprotected function get_static_private_property( string $class_name, string $property_name ) {\n\t\t$properties = ( new ReflectionClass( $class_name ) )->getStaticProperties();\n\t\treturn \\array_key_exists( $property_name, $properties ) ? $properties[ $property_name ] : null;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/bootstrap.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * PHPUnit bootstrap file.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\nrequire_once __DIR__ . '/../../../vendor/yoast/wp-test-utils/src/BrainMonkey/bootstrap.php';\nrequire_once __DIR__ . '/../../../vendor/autoload.php';\nrequire_once __DIR__ . '/../../../third-party/vendor/scoper-autoload.php';\n\ndefine( 'WEBSTORIES_VERSION', '1.0.0' );\ndefine( 'WEBSTORIES_DB_VERSION', '1.0.0' );\ndefine( 'WEBSTORIES_AMP_VERSION', '1.0.0' );\n\nif ( ! defined( 'WEBSTORIES_PLUGIN_DIR_PATH' ) ) {\n\tdefine( 'WEBSTORIES_PLUGIN_DIR_PATH', dirname( __DIR__, 3 ) );\n}\n\nif ( ! defined( 'WEBSTORIES_PLUGIN_FILE' ) ) {\n\tdefine( 'WEBSTORIES_PLUGIN_FILE', WEBSTORIES_PLUGIN_DIR_PATH . 'web-stories.php' );\n}\n"
  },
  {
    "path": "tests/phpunit/unit/includes/MarkupComparison.php",
    "content": "<?php\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit;\n\n/**\n * Helper trait for comparing strings of HTML markup.\n *\n * @see https://github.com/ampproject/amp-wp/blob/59021205940e72dffa9e6ef370ab7f3ea536ea39/tests/php/src/Helpers/MarkupComparison.php\n *\n * @package AmpProject\\AmpWP\n */\ntrait MarkupComparison {\n\n\t/**\n\t * Assert markup is equal.\n\t *\n\t * @param string $expected Expected markup.\n\t * @param string $actual   Actual markup.\n\t */\n\tprotected function assertEqualMarkup( $expected, $actual ) : void { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName\n\t\t// Normalize whitespace (`foo   bar` => `foo bar`).\n\t\t$actual   = (string) preg_replace( '/\\s+/', ' ', $actual );\n\t\t$expected = (string) preg_replace( '/\\s+/', ' ', $expected );\n\n\t\t// Remove whitespace between elements (` <br> <br> ` => `<br><br>`).\n\t\t$actual   = (string) preg_replace( '/(?<=>)\\s+(?=<)/', '', trim( $actual ) );\n\t\t$expected = (string) preg_replace( '/(?<=>)\\s+(?=<)/', '', trim( $expected ) );\n\n\t\t// Normalize boolean attributes that use their name as value.\n\t\t$actual   = (string) preg_replace( '/(?<=\\s)([a-zA-Z-_]+)=\"(?:\\1|)\"/i', '$1', $actual );\n\t\t$expected = (string) preg_replace( '/(?<=\\s)([a-zA-Z-_]+)=\"(?:\\1|)\"/i', '$1', $expected );\n\n\t\t// Split into an array of individual elements.\n\t\t$actual   = (array) preg_split( '#(<[^>]+>|[^<>]+)#', $actual, -1, PREG_SPLIT_DELIM_CAPTURE );\n\t\t$expected = (array) preg_split( '#(<[^>]+>|[^<>]+)#', $expected, -1, PREG_SPLIT_DELIM_CAPTURE );\n\n\t\t$this->assertEquals( array_filter( $expected ), array_filter( $actual ) );\n\t}\n\n\t/**\n\t * Assert markup is similar, disregarding differences that are inconsequential for functionality.\n\t *\n\t * @param string $expected Expected markup.\n\t * @param string $actual   Actual markup.\n\t */\n\tprotected function assertSimilarMarkup( $expected, $actual ) :void { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName\n\t\t// Normalize whitespace (`foo   bar` => `foo bar`).\n\t\t$actual   = (string) preg_replace( '/\\s+/', ' ', $actual );\n\t\t$expected = (string) preg_replace( '/\\s+/', ' ', $expected );\n\n\t\t// Remove whitespace between elements (`<br> <br>` => `<br><br>`).\n\t\t$actual   = (string) preg_replace( '/(?<=>)\\s+(?=<)/', '', trim( $actual ) );\n\t\t$expected = (string) preg_replace( '/(?<=>)\\s+(?=<)/', '', trim( $expected ) );\n\n\t\t// Remove empty values (`foo=\"\"` => `foo`).\n\t\t$actual   = (string) preg_replace( '/=([\\'\"]){2}/', '', $actual );\n\t\t$expected = (string) preg_replace( '/=([\\'\"]){2}/', '', $expected );\n\n\t\t// Normalize case of doctype element.\n\t\t$actual   = (string) preg_replace( '/<!doctype/i', '<!DOCTYPE', $actual );\n\t\t$expected = (string) preg_replace( '/<!doctype/i', '<!DOCTYPE', $expected );\n\n\t\t// Wrap all attributes in quotes (`foo=bar` => `foo=\"bar\"`).\n\t\t$actual   = (string) preg_replace( '/(\\s+[a-zA-Z-_]+)=(?!\")([a-zA-Z-_.]+)/', '\\1=\"\\2\"', $actual );\n\t\t$expected = (string) preg_replace( '/(\\s+[a-zA-Z-_]+)=(?!\")([a-zA-Z-_.]+)/', '\\1=\"\\2\"', $expected );\n\n\t\t// Normalize empty JSON objects (`<script> { } </script>` => `<script>{}</script>`).\n\t\t$actual   = (string) preg_replace( '/>\\s*{\\s*}\\s*</', '>{}<', $actual );\n\t\t$expected = (string) preg_replace( '/>\\s*{\\s*}\\s*</', '>{}<', $expected );\n\n\t\t// Normalize boolean attributes that use their name as value.\n\t\t$actual   = (string) preg_replace( '/(?<=\\s)([a-zA-Z-_]+)=\"(?:\\1|)\"/i', '$1', $actual );\n\t\t$expected = (string) preg_replace( '/(?<=\\s)([a-zA-Z-_]+)=\"(?:\\1|)\"/i', '$1', $expected );\n\n\t\t$normalize_attributes = static function ( $element ) {\n\t\t\t// Extract attributes for the given element.\n\t\t\tif ( ! preg_match( '#^(<[a-z0-9-]+)(\\s[^>]+)>$#i', $element, $matches ) ) {\n\t\t\t\treturn $element;\n\t\t\t}\n\n\t\t\t// Split into individual attributes.\n\t\t\t$attributes = array_map(\n\t\t\t\t'trim',\n\t\t\t\tarray_filter(\n\t\t\t\t\t(array) preg_split(\n\t\t\t\t\t\t'#(\\s+[^\"\\'\\s=]+(?:=(?:\"[^\"]+\"|\\'[^\\']+\\'|[^\"\\'\\s]+))?)#',\n\t\t\t\t\t\t$matches[2],\n\t\t\t\t\t\t-1,\n\t\t\t\t\t\tPREG_SPLIT_DELIM_CAPTURE\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t);\n\n\t\t\t// Normalize sort order.\n\t\t\tsort( $attributes );\n\n\t\t\t$attribute_string = implode( ' ', $attributes );\n\n\t\t\tif ( ! empty( $attribute_string ) ) {\n\t\t\t\t$attribute_string = \" {$attribute_string}\";\n\t\t\t}\n\n\t\t\treturn \"{$matches[1]}{$attribute_string}>\";\n\t\t};\n\n\t\t// Split into an array of individual elements.\n\t\t$actual   = (array) preg_split( '#(<[^>]+>|[^<>]+)#', $actual, -1, PREG_SPLIT_DELIM_CAPTURE );\n\t\t$expected = (array) preg_split( '#(<[^>]+>|[^<>]+)#', $expected, -1, PREG_SPLIT_DELIM_CAPTURE );\n\n\t\t// Normalize the attributes for each individual element.\n\t\t$actual   = array_map( $normalize_attributes, array_filter( $actual ) );\n\t\t$expected = array_map( $normalize_attributes, array_filter( $expected ) );\n\n\t\t$this->assertEquals( $expected, $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/includes/ScriptHash.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit;\n\ntrait ScriptHash {\n\t/**\n\t * Generate hash for inline amp-script.\n\t *\n\t * Copied from amp-helper-functions.php\n\t *\n\t * The sha384 hash used by amp-script is represented not as hexadecimal but as base64url, which is defined in RFC 4648\n\t * under section 5, \"Base 64 Encoding with URL and Filename Safe Alphabet\". It is sometimes referred to as \"web safe\".\n\t *\n\t * @link https://amp.dev/documentation/components/amp-script/#security-features\n\t * @link https://github.com/ampproject/amphtml/blob/e8707858895c2af25903af25d396e144e64690ba/extensions/amp-script/0.1/amp-script.js#L401-L425\n\t * @link https://github.com/ampproject/amphtml/blob/27b46b9c8c0fb3711a00376668d808f413d798ed/src/service/crypto-impl.js#L67-L124\n\t * @link https://github.com/ampproject/amphtml/blob/c4a663d0ba13d0488c6fe73c55dc8c971ac6ec0d/src/utils/base64.js#L52-L61\n\t * @link https://tools.ietf.org/html/rfc4648#section-5\n\t * @see ::generate_script_hash()\n\t *\n\t * @param string $script Script.\n\t * @return string|null Script hash or null if the sha384 algorithm is not supported.\n\t */\n\tpublic function generate_script_hash( string $script ): ?string {\n\t\t$sha384 = hash( 'sha384', $script, true );\n\n\t\t$hash = str_replace(\n\t\t\t[ '+', '/', '=' ],\n\t\t\t[ '-', '_', '.' ],\n\t\t\tbase64_encode( $sha384 ) // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode\n\t\t);\n\t\treturn 'sha384-' . $hash;\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/includes/TestCase.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\nnamespace Google\\Web_Stories\\Tests\\Unit;\n\nuse Yoast\\WPTestUtils\\BrainMonkey\\TestCase as UnitTestCase;\n\nabstract class TestCase extends UnitTestCase {\n\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/AMP/Canonical_Sanitizer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit\\AMP;\n\nuse Google\\Web_Stories\\Tests\\Unit\\TestCase;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer\n */\nclass Canonical_Sanitizer extends TestCase {\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_exists(): void {\n\t\t$source = '<html><head><title>Example</title><link rel=\"canonical\" href=\"https://example.com/canonical.html\"></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => 'https://example.com/new-canonical.html' ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"https://example.com/canonical.html\">', $actual );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_remove_duplicates(): void {\n\t\t$source = '<html><head><title>Example</title><link rel=\"canonical\" href=\"https://example.com/canonical.html\"><link rel=\"canonical\" href=\"https://example.com/canonical2.html\"></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => 'https://example.com/new-canonical.html' ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"https://example.com/canonical.html\">', $actual );\n\t\t$this->assertStringNotContainsString( '<link rel=\"canonical\" href=\"https://example.com/canonical2.html\">', $actual );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_missing(): void {\n\t\t$canonical = 'https://example.com/new-canonical.html';\n\n\t\t$source = '<html><head><title>Example</title></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => $canonical ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"' . $canonical . '\">', $actual );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_empty_value(): void {\n\t\t$canonical = 'https://example.com/new-canonical.html';\n\n\t\t$source = '<html><head><title>Example</title><link rel=\"canonical\" href=\"\"></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => $canonical ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"', $actual );\n\t\t$this->assertStringNotContainsString( '<link rel=\"canonical\" href=\"\">', $actual );\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"' . $canonical . '\">', $actual );\n\t}\n\n\t/**\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize_canonical_missing_existing_link_tags(): void {\n\t\t$canonical = 'https://example.com/new-canonical.html';\n\n\t\t$source = '<html><head><title>Example</title><link rel=\"stylesheet\" href=\"https://example.com/style.css\"><link rel=\"stylesheet\" href=\"https://example.com/style2.css\"></head><body><p>Hello World</p></body></html>';\n\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Canonical_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'canonical_url' => $canonical ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\n\t\t$this->assertStringContainsString( '<link rel=\"canonical\" href=\"' . $canonical . '\">', $actual );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/AMP/Meta_Sanitizer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit\\AMP;\n\nuse AMP_Allowed_Tags_Generated;\nuse Brain\\Monkey;\nuse Google\\Web_Stories\\AMP\\Tag_And_Attribute_Sanitizer;\nuse Google\\Web_Stories\\Tests\\Unit\\MarkupComparison;\nuse Google\\Web_Stories\\Tests\\Unit\\ScriptHash;\nuse Google\\Web_Stories\\Tests\\Unit\\TestCase;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Meta_Sanitizer\n */\nclass Meta_Sanitizer extends TestCase {\n\tuse MarkupComparison;\n\tuse ScriptHash;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'wp_parse_url' => static fn( $url, $component = -1 ) => parse_url( $url, $component ), // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * Test that the expected tag specs exist for the body.\n\t */\n\tpublic function test_expected_meta_tags(): void {\n\t\t$named_specs = array_filter(\n\t\t\t(array) AMP_Allowed_Tags_Generated::get_allowed_tag( 'meta' ),\n\t\t\tstatic fn( $spec ) => isset( $spec['tag_spec']['spec_name'] ) && \\Google\\Web_Stories\\AMP\\Meta_Sanitizer::BODY_ANCESTOR_META_TAG_SPEC_NAME === $spec['tag_spec']['spec_name']\n\t\t);\n\t\t$this->assertCount( 1, $named_specs );\n\n\t\t$body_ok_specs = array_filter(\n\t\t\t(array) AMP_Allowed_Tags_Generated::get_allowed_tag( 'meta' ),\n\t\t\tstatic function ( $spec ) {\n\t\t\t\t$head_required = (\n\t\t\t\t\t( isset( $spec['tag_spec']['mandatory_parent'] ) && 'head' === $spec['tag_spec']['mandatory_parent'] )\n\t\t\t\t\t||\n\t\t\t\t\t( isset( $spec['tag_spec']['mandatory_ancestor'] ) && 'head' === $spec['tag_spec']['mandatory_ancestor'] )\n\t\t\t\t);\n\t\t\t\treturn ! $head_required;\n\t\t\t}\n\t\t);\n\n\t\t$this->assertEquals( $named_specs, $body_ok_specs );\n\n\t\t$spec = current( $named_specs );\n\t\t$this->assertArrayHasKey( 'name', $spec['attr_spec_list'] );\n\t\t$this->assertEquals( [ 'disallowed_value_regex' ], array_keys( $spec['attr_spec_list']['name'] ) );\n\t}\n\n\t/**\n\t * Provide data to the test_sanitize method.\n\t *\n\t * @return array<string, string[]> Array of arrays with test data.\n\t */\n\tpublic function get_data_for_sanitize(): array {\n\t\t$script1 = 'document.body.textContent += \"First!\";';\n\t\t$script2 = 'document.body.textContent += \"Second!\";';\n\t\t$script3 = 'document.body.textContent += \"Third!\";';\n\t\t$script4 = 'document.body.textContent += \"Fourth! (And forbidden because no amp-script-src meta in head.)\";';\n\n\t\t$script1_hash = $this->generate_script_hash( $script1 );\n\t\t$script2_hash = $this->generate_script_hash( $script2 );\n\t\t$script3_hash = $this->generate_script_hash( $script3 );\n\t\t$script4_hash = $this->generate_script_hash( $script4 );\n\n\t\t$amp_boilerplate_css = [\n\t\t\t'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',\n\t\t\t'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',\n\t\t];\n\n\t\t$amp_boilerplate = \\sprintf( '<style amp-boilerplate>%s</style><noscript><style amp-boilerplate>%s</style></noscript>', $amp_boilerplate_css[0], $amp_boilerplate_css[1] );\n\n\t\t$meta_charset  = '<meta charset=\"utf-8\">';\n\t\t$meta_viewport = '<meta name=\"viewport\" content=\"width=device-width\">';\n\n\t\t$meta_tags_allowed_in_body = '\n\t\t\t<span itemprop=\"author\" itemscope itemtype=\"https://schema.org/Person\">\n\t\t\t\t<meta itemprop=\"name\" content=\"Siva\">\n\t\t\t</span>\n\t\t\t<meta itemprop=\"datePublished\" content=\"2020-03-24T18:05:15+05:30\">\n\t\t\t<meta itemprop=\"dateModified\" content=\"2020-03-24T18:05:15+05:30\">\n\t\t\t<meta itemscope itemprop=\"mainEntityOfPage\" itemtype=\"https://schema.org/WebPage\" itemid=\"https://example.com/\">\n\t\t\t<span itemprop=\"publisher\" itemscope itemtype=\"https://schema.org/Organization\">\n\t\t\t\t<span itemprop=\"logo\" itemscope itemtype=\"https://schema.org/ImageObject\">\n\t\t\t\t\t<meta itemprop=\"url\" content=\"https://example/logo.png\">\n\t\t\t\t</span>\n\t\t\t\t<meta itemprop=\"name\" content=\"Example\">\n\t\t\t\t<meta itemprop=\"url\" content=\"https://example.com\">\n\t\t\t</span>\n\t\t\t<meta itemprop=\"headline \" content=\"This is a test\">\n\t\t\t<span itemprop=\"image\" itemscope itemtype=\"https://schema.org/ImageObject\">\n\t\t\t\t<meta itemprop=\"url\" content=\"https://example.com/foo.jpg\">\n\t\t\t\t<meta itemprop=\"width\" content=\"1280\"><meta itemprop=\"height\" content=\"720\">\n\t\t\t</span>\n\t\t\t<div itemscope id=\"amanda\" itemref=\"a b\"></div>\n\t\t\t<p id=\"a\">Name: <span itemprop=\"name\">Amanda</span> </p>\n\t\t\t\t<div id=\"b\" itemprop=\"band\" itemscope itemref=\"c\"></div>\n\t\t\t<div id=\"c\">\n\t\t\t\t<p>Band: <span itemprop=\"name\">Jazz Band</span> </p>\n\t\t\t\t<p>Size: <span itemprop=\"size\">12</span> players</p>\n\t\t\t</div>\n\t\t\t<meta id=\"foo\">\n\t\t\t<meta name=\"greeting\" content=\"Hello!\">\n\t\t\t<meta name=\"keywords\" content=\"Meta Tags, Metadata\" scheme=\"ISBN\">\n\t\t\t<meta content=\"This is a basic text\" property=\"og:title\">\n\t\t';\n\n\t\t$data = [\n\t\t\t'Do not break the correct charset tag'        => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Do not break the correct viewport tag'       => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,minimum-scale=1,initial-scale=1\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,minimum-scale=1\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Move charset and viewport tags from body to head' => [\n\t\t\t\t'<!DOCTYPE html><html><head>' . $amp_boilerplate . '</head><body><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Add default charset tag if none is present'  => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Add default viewport tag if none is present' => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Make sure charset is the first meta tag'     => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width\"><meta charset=\"utf-8\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Concatenate and reposition script hashes'    => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta name=\"amp-script-src\" content=\"' . $script1_hash . '\"><meta charset=\"utf-8\"><meta name=\"amp-script-src\" content=\"' . $script2_hash . '\"><meta name=\"viewport\" content=\"width=device-width\"><meta name=\"amp-script-src\" content=\"' . $script3_hash . '\">' . $amp_boilerplate . '</head><body><meta name=\"amp-script-src\" content=\"' . $script4_hash . '\"></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><meta name=\"amp-script-src\" content=\"' . $script1_hash . ' ' . $script2_hash . ' ' . $script3_hash . ' ' . $script4_hash . '\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Remove legacy meta http-equiv=Content-Type'  => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Process invalid meta http-equiv value'       => [\n\t\t\t\t// Note the Tag_And_Attribute_Sanitizer removes the http-equiv attribute because the content is invalid.\n\t\t\t\t'<!DOCTYPE html><html><head>' . $amp_boilerplate . '</head><body><meta http-equiv=\"Content-Type\" content=\"text/vbscript\"></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta content=\"text/vbscript\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Disallowed meta=content-deposition'          => [\n\t\t\t\t'<!DOCTYPE html><html><head>' . $amp_boilerplate . '<meta name=\"content-disposition\" content=\"inline; filename=data.csv\"></head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><meta content=\"inline; filename=data.csv\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Disallowed meta=revisit-after'               => [\n\t\t\t\t'<!DOCTYPE html><html><head>' . $amp_boilerplate . '<meta name=\"revisit-after\" content=\"7 days\"></head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><meta content=\"7 days\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Disallowed meta=amp-bogus'                   => [\n\t\t\t\t'<!DOCTYPE html><html><head>' . $amp_boilerplate . '<meta name=\"amp-bogus\" content=\"bad\"></head><body></body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><meta content=\"bad\">' . $amp_boilerplate . '</head><body></body></html>',\n\t\t\t],\n\n\t\t\t'Ignore generic meta tags'                    => [\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\">' . $amp_boilerplate . '</head><body>' . $meta_tags_allowed_in_body . '</body></html>',\n\t\t\t\t'<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\">' . $amp_boilerplate . '</head><body>' . $meta_tags_allowed_in_body . '</body></html>',\n\t\t\t],\n\t\t];\n\n\t\t$http_equiv_specs = [\n\t\t\t'meta http-equiv=X-UA-Compatible'        => '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">',\n\t\t\t'meta http-equiv=content-language'       => '<meta http-equiv=\"content-language\" content=\"labellist\">',\n\t\t\t'meta http-equiv=pics-label'             => '<meta http-equiv=\"PICS-Label\" content=\"en-US\">',\n\t\t\t'meta http-equiv=imagetoolbar'           => '<meta http-equiv=\"imagetoolbar\" content=\"false\">',\n\t\t\t'meta http-equiv=Content-Style-Type'     => '<meta http-equiv=\"Content-Style-Type\" content=\"text/css\">',\n\t\t\t'meta http-equiv=Content-Script-Type'    => '<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\">',\n\t\t\t'meta http-equiv=origin-trial'           => '<meta http-equiv=\"origin-trial\" content=\"...\">',\n\t\t\t'meta http-equiv=resource-type'          => '<meta http-equiv=\"resource-type\" content=\"document\">',\n\t\t\t'meta http-equiv=x-dns-prefetch-control' => '<meta http-equiv=\"x-dns-prefetch-control\" content=\"on\">',\n\t\t];\n\t\tforeach ( $http_equiv_specs as $equiv_spec => $tag ) {\n\t\t\t$data[ \"Verify http-equiv moved: $equiv_spec\" ] = [\n\t\t\t\t\"<!DOCTYPE html><html><head>{$meta_charset}{$meta_viewport}{$amp_boilerplate}</head><body>{$tag}</body></html>\",\n\t\t\t\t\"<!DOCTYPE html><html><head>{$meta_charset}{$tag}{$meta_viewport}{$amp_boilerplate}</head><body></body></html>\",\n\t\t\t];\n\t\t}\n\n\t\t$named_specs = [\n\t\t\t'meta name=apple-itunes-app'                 => '<meta name=\"apple-itunes-app\" content=\"app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL\">',\n\t\t\t'meta name=amp-experiments-opt-in'           => '<meta name=\"amp-experiments-opt-in\" content=\"experiment-a,experiment-b\">',\n\t\t\t'meta name=amp-3p-iframe-src'                => '<meta name=\"amp-3p-iframe-src\" content=\"https://storage.googleapis.com/amp-testing.appspot.com/public/remote.html\">',\n\t\t\t'meta name=amp-consent-blocking'             => '<meta name=\"amp-consent-blocking\" content=\"\">',\n\t\t\t'meta name=amp-experiment-token'             => '<meta name=\"amp-experiment-token\" content=\"{copy your token here}\">',\n\t\t\t'meta name=amp-link-variable-allowed-origin' => '<meta name=\"amp-link-variable-allowed-origin\" content=\"https://example.com https://example.org\">',\n\t\t\t'meta name=amp-google-clientid-id-api'       => '<meta name=\"amp-google-client-id-api\" content=\"googleanalytics\">',\n\t\t\t'meta name=amp-ad-doubleclick-sra'           => '<meta name=\"amp-ad-doubleclick-sra\">',\n\t\t\t'meta name=amp-list-load-more'               => '<meta name=\"amp-list-load-more\" content=\"\">',\n\t\t\t'meta name=amp-recaptcha-input'              => '<meta name=\"amp-recaptcha-input\" content=\"\">',\n\t\t\t'meta name=amp-ad-enable-refresh'            => '<meta name=\"amp-ad-enable-refresh\" content=\"network1=refresh_interval1,network2=refresh_interval2,...\">',\n\t\t\t'meta name=amp-to-amp-navigation'            => '<meta name=\"amp-to-amp-navigation\" content=\"AMP-Redirect-To; AMP.navigateTo\">',\n\t\t];\n\t\tforeach ( $named_specs as $named_spec => $tag ) {\n\t\t\t$data[ \"Verify meta[name] moved: $named_spec\" ] = [\n\t\t\t\t\"<!DOCTYPE html><html><head>{$meta_charset}{$meta_viewport}{$amp_boilerplate}</head><body>{$tag}</body></html>\",\n\t\t\t\t\"<!DOCTYPE html><html><head>{$meta_charset}{$meta_viewport}{$tag}{$amp_boilerplate}</head><body></body></html>\",\n\t\t\t];\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t/**\n\t * Tests the sanitize method.\n\t *\n\t * @param string  $source_content   Source DOM content.\n\t * @param string  $expected_content Expected content after sanitization.\n\t *\n\t * @dataProvider get_data_for_sanitize\n\t * @covers ::sanitize\n\t */\n\tpublic function test_sanitize( string $source_content, string $expected_content ): void {\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom       = Document::fromHtml( $source_content );\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Meta_Sanitizer( $dom );\n\t\t$sanitizer->sanitize();\n\n\t\t$sanitizer = new Tag_And_Attribute_Sanitizer(\n\t\t\t$dom,\n\t\t\t[ 'use_document_element' => true ]\n\t\t);\n\t\t$sanitizer->sanitize();\n\n\t\t$this->assertEqualMarkup( $expected_content, $dom->saveHTML() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/AMP/Output_Buffer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/*\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit\\AMP;\n\nuse Brain\\Monkey;\nuse Google\\Web_Stories\\Tests\\Unit\\TestCase;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Output_Buffer\n */\nclass Output_Buffer extends TestCase {\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'get_post' => static fn() => null,\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t */\n\tpublic function test_is_needed(): void {\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_lower_version(): void {\n\t\t\\define( 'AMP__VERSION', '0.0.1' );\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_same_version(): void {\n\t\t\\define( 'AMP__VERSION', WEBSTORIES_AMP_VERSION );\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_same_version_did_amp_init(): void {\n\t\t\\define( 'AMP__VERSION', WEBSTORIES_AMP_VERSION );\n\t\tdo_action( 'amp_init' );\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_higher_version(): void {\n\t\t\\define( 'AMP__VERSION', '99.9.9' );\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_higher_version_did_amp_init(): void {\n\t\t\\define( 'AMP__VERSION', '99.9.9' );\n\t\tdo_action( 'amp_init' );\n\t\t$this->assertTrue( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n\n\t/**\n\t * @covers ::is_needed\n\t * @runInSeparateProcess\n\t * @preserveGlobalState disabled\n\t */\n\tpublic function test_is_needed_amp_properly_initialized(): void {\n\t\t\\define( 'AMP__VERSION', WEBSTORIES_AMP_VERSION );\n\t\tdo_action( 'amp_init' );\n\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'get_post'              => static fn() => null,\n\t\t\t\t'amp_is_available'      => static fn() => true,\n\t\t\t\t'amp_is_enabled'        => static fn() => true,\n\t\t\t\t'amp_is_post_supported' => static fn() => true,\n\t\t\t]\n\t\t);\n\n\t\t$this->assertFalse( \\Google\\Web_Stories\\AMP\\Output_Buffer::is_needed() );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/AMP/Story_Sanitizer.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit\\AMP;\n\nuse AMP_DOM_Utils;\nuse Brain\\Monkey;\nuse Google\\Web_Stories\\Tests\\Unit\\TestCase;\nuse Google\\Web_Stories_Dependencies\\AmpProject\\Dom\\Document;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\AMP\\Story_Sanitizer\n */\nclass Story_Sanitizer extends TestCase {\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->stubEscapeFunctions();\n\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'get_bloginfo' => static function ( $show ) {\n\t\t\t\t\tswitch ( $show ) {\n\t\t\t\t\t\tcase 'charset':\n\t\t\t\t\t\t\treturn 'UTF-8';\n\t\t\t\t\t\tcase 'language':\n\t\t\t\t\t\t\treturn 'en-US';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn $show;\n\t\t\t\t},\n\t\t\t\t'is_rtl'       => false,\n\t\t\t\t'home_url'     => 'https://www.example.com',\n\t\t\t]\n\t\t);\n\t}\n\n\t/**\n\t * @return array<string, string[]>\n\t */\n\tpublic function get_publisher_logo_data(): array {\n\t\treturn [\n\t\t\t'publisher_logo_exists'  => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t],\n\t\t\t'publisher_logo_missing' => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" poster-portrait-src=\"https://example.com/image.png\" publisher-logo-src=\"https://example.com/publisher_logo.png\"></amp-story></body></html>',\n\t\t\t],\n\t\t\t'publisher_logo_empty'   => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/publisher_logo.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @param string   $source   Source.\n\t * @param string   $expected Expected.\n\t *\n\t * @dataProvider get_publisher_logo_data\n\t * @covers ::sanitize\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher_logo\n\t */\n\tpublic function test_sanitize_publisher_logo( string $source, string $expected ): void {\n\t\t$args = [\n\t\t\t'publisher'      => 'Web Stories',\n\t\t\t'publisher_logo' => 'https://example.com/publisher_logo.png',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertEquals( $expected, $actual );\n\t}\n\n\t/**\n\t * @return array<string, array<string|array<string, mixed>>>\n\t */\n\tpublic function get_poster_image_data(): array {\n\t\treturn [\n\t\t\t'Poster image already exists' => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'Poster image is missing'     => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'Poster image is empty'       => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'Poster image is overridden'  => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/portrait.png\" poster-landscape-src=\"https://example.com/landscape.png\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [\n\t\t\t\t\t\t'poster-portrait-src'  => 'https://example.com/portrait.png',\n\t\t\t\t\t\t'poster-landscape-src' => 'https://example.com/landscape.png',\n\t\t\t\t\t],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @param string $source   Source.\n\t * @param string $expected Expected.\n\t * @param array<string, array<string, mixed>|string|bool>  $args     Args.\n\t *\n\t * @dataProvider get_poster_image_data\n\t * @covers ::sanitize\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_poster_images\n\t */\n\tpublic function test_sanitize_poster_image( string $source, string $expected, array $args ): void {\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertEquals( $expected, $actual );\n\t}\n\n\t/**\n\t * @return array<string, array<string|array<string, mixed>>>\n\t */\n\tpublic function get_publisher_data(): array {\n\t\treturn [\n\t\t\t'publisher_exists'        => [\n\t\t\t\t'<amp-story standalone=\"\" publisher=\"Web Stories\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" publisher=\"New publisher\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => 'New publisher',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'no_publisher'            => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\"New publisher\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => 'New publisher',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'missing_publisher'       => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\"\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'empty_publisher'         => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher=\"\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher=\"\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'double_quotes_publisher' => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\\'\"double quotes\"\\'></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => '\"double quotes\"',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'single_quotes_publisher' => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\"\\'single quotes\\'\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => \"'single quotes'\",\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'not_english_publisher'   => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\"PRÓXIMA\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => 'PRÓXIMA',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t\t'html_publisher'          => [\n\t\t\t\t'<amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\"></amp-story>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story standalone=\"\" title=\"Example Story\" publisher-logo-src=\"https://example.com/image.png\" poster-portrait-src=\"https://example.com/image.png\" publisher=\"this &gt; that &lt; that &lt;randomhtml /&gt;\"></amp-story></body></html>',\n\t\t\t\t[\n\t\t\t\t\t'publisher_logo' => '',\n\t\t\t\t\t'publisher'      => 'this > that < that <randomhtml />',\n\t\t\t\t\t'poster_images'  => [],\n\t\t\t\t\t'video_cache'    => false,\n\t\t\t\t\t'title_tag'      => '',\n\t\t\t\t\t'description'    => '',\n\t\t\t\t],\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @param string $source   Source.\n\t * @param string $expected Expected.\n\t * @param array<string, array<string, mixed>|string|false>  $args   Args\n\t *\n\t * @dataProvider get_publisher_data\n\t * @covers ::sanitize\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_publisher\n\t */\n\tpublic function test_sanitize_publisher( string $source, string $expected, array $args ): void {\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertEquals( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::transform_html_start_tag\n\t */\n\tpublic function test_transform_html_start_tag(): void {\n\t\t$source = '<html><head></head><body><amp-story></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( ' lang=\"en-US\"', $actual );\n\t}\n\n\t/**\n\t * @return array<string, array<int, string>>\n\t */\n\tpublic static function data_test_transform_a_tags(): array {\n\t\treturn [\n\t\t\t'Link without rel or target attribute' => [\n\t\t\t\t'<html><head></head><body><a href=\"https://www.google.com\">Google</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.google.com\" target=\"_blank\" rel=\"noreferrer\">Google</a></body></html>',\n\t\t\t],\n\t\t\t'Link with existing rel=\"nofollow\"'    => [\n\t\t\t\t'<html><head></head><body><a href=\"https://www.google.com\" rel=\"nofollow\">Google</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.google.com\" rel=\"nofollow noreferrer\" target=\"_blank\">Google</a></body></html>',\n\t\t\t],\n\t\t\t'Link to same origin'                  => [\n\t\t\t\t'<html><head></head><body><a href=\"https://www.example.com\">My Site</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.example.com\" target=\"_blank\">My Site</a></body></html>',\n\t\t\t],\n\t\t\t'Link to same origin with existing rel=\"noreferrer\"' => [\n\t\t\t\t'<html><head></head><body><a href=\"https://www.example.com\" rel=\"noreferrer\">My Site</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.example.com\" target=\"_blank\">My Site</a></body></html>',\n\t\t\t],\n\t\t\t'Outlink'                              => [\n\t\t\t\t'<html><head></head><body><amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://www.google.com/\">Google</a></amp-story-page-outlink></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://www.google.com/\" target=\"_blank\" rel=\"noreferrer\">Google</a></amp-story-page-outlink></body></html>',\n\t\t\t],\n\t\t\t'Outlink to same origin'               => [\n\t\t\t\t'<html><head></head><body><amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://www.example.com/\">My Site</a></amp-story-page-outlink></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><amp-story-page-outlink layout=\"nodisplay\"><a href=\"https://www.example.com/\" target=\"_blank\">My Site</a></amp-story-page-outlink></body></html>',\n\t\t\t],\n\t\t\t'Link with empty data attributes'      => [\n\t\t\t\t'<html><head></head><body><a href=\"https://www.google.com\" data-tooltip-icon=\"\" data-tooltip-text=\"\">Google</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.google.com\" target=\"_blank\" rel=\"noreferrer\">Google</a></body></html>',\n\t\t\t],\n\t\t\t'Link without protocol'                => [\n\t\t\t\t'<html><head></head><body><a href=\"www.google.com\">Google</a></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body><a href=\"https://www.google.com\" target=\"_blank\" rel=\"noreferrer\">Google</a></body></html>',\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::transform_a_tags\n\t * @dataProvider data_test_transform_a_tags\n\t */\n\tpublic function test_transform_a_tags( string $source, string $expected ): void {\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::deduplicate_inline_styles\n\t */\n\tpublic function test_deduplicate_inline_styles(): void {\n\t\t$source = '<html><head></head><body><amp-story><div style=\"color: blue;\"></div><div style=\"color: blue;\"></div><div style=\"color: blue; background: white;\"></div><div style=\"color: red;\"></div></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( '<style>._a7988c6{color: blue;}._91f054f{color: blue; background: white;}._f479d19{color: red;}</style>', $actual );\n\t\t$this->assertStringNotContainsString( 'style=\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_video_cache\n\t */\n\tpublic function test_add_video_cache_disabled(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-video width=\"720\" height=\"960\" poster=\"https://example.com/poster.jpg\" layout=\"responsive\"><source type=\"video/mp4\" src=\"https://example.com/video.mp4\" /></amp-video></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringNotContainsString( 'cache=\"google\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::add_video_cache\n\t */\n\tpublic function test_add_video_cache_enabled(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-video width=\"720\" height=\"960\" poster=\"https://example.com/poster.jpg\" layout=\"responsive\"><source type=\"video/mp4\" src=\"https://example.com/video.mp4\" /></amp-video></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => true,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'cache=\"google\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::remove_blob_urls\n\t */\n\tpublic function test_remove_blob_urls(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-video width=\"720\" height=\"960\" poster=\"blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a\" layout=\"responsive\"><source type=\"video/mp4\" src=\"blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a\" /></amp-video><amp-img src=\"blob:https://example.com/ecee4374-8f8a-4210-8f2d-9c5f8d6a6c5a\" width=\"100\" height=\"100\"></amp-img></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringNotContainsString( 'blob:', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::sanitize_srcset\n\t */\n\tpublic function test_sanitize_srcset(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-img src=\"https://example.com/image.jpg\" width=\"100\" height=\"100\" srcset=\"https://example.com/image.jpg 1000w,https://example.com/image-768x1024.jpg 768w,https://example.com/image-768x1024.jpg 768w,https://example.com/image-225x300.jpg 225w,https://example.com/image-225x300.jpg 225w,https://example.com/image-150x200.jpg 150w\"></amp-img></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'srcset=\"https://example.com/image.jpg 1000w, https://example.com/image-768x1024.jpg 768w, https://example.com/image-225x300.jpg 225w, https://example.com/image-150x200.jpg 150w\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::sanitize_srcset\n\t */\n\tpublic function test_sanitize_srcset_commas(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-img src=\"https://example.com/image.jpg\" width=\"100\" height=\"100\" srcset=\"https://example.com/image/1000,1000/image.jpg 1000w,https://example.com/image/768,1024/image-768x1024.jpg 768w,https://example.com/image/225,300/image-225x300.jpg 225w,https://example.com/image/150,200/image-150x200.jpg 150w\"></amp-img></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'srcset=\"https://example.com/image/1000,1000/image.jpg 1000w, https://example.com/image/768,1024/image-768x1024.jpg 768w, https://example.com/image/225,300/image-225x300.jpg 225w, https://example.com/image/150,200/image-150x200.jpg 150w\"', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::sanitize_amp_story_page_outlink\n\t */\n\tpublic function test_sanitize_amp_story_page_outlink(): void {\n\t\t$source = '<html><head></head><body><amp-story-page-outlink layout=\"nodisplay\" cta-image=\"\"><a href=\"https://www.bonappeteach.com/smoked-apple-cider/\" target=\"_blank\" rel=\"noreferrer\">Get The Recipe!</a></amp-story-page-outlink></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( '<amp-story-page-outlink layout=\"nodisplay\">', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::sanitize_amp_story_page_outlink\n\t */\n\tpublic function test_sanitize_amp_story_page_outlink_element_order(): void {\n\t\t$source = '<html><head></head><body><amp-story><amp-story-page><amp-story-page-outlink layout=\"nodisplay\" cta-image=\"\"><a href=\"https://www.bonappeteach.com/smoked-apple-cider/\" target=\"_blank\" rel=\"noreferrer\">Get The Recipe!</a></amp-story-page-outlink><amp-story-grid-layer></amp-story-grid-layer></amp-story-page></amp-story></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( '</amp-story-page-outlink></amp-story-page>', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::remove_page_template_placeholder_images\n\t */\n\tpublic function test_remove_page_template_placeholder_images(): void {\n\t\t$source = '<html><head></head><body><amp-img src=\"https://example.com/wp-content/plugins/web-stories/assets/images/editor/grid-placeholder.png\" width=\"100\" height=\"100\"></amp-img></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringNotContainsString( 'amp-img', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::remove_page_template_placeholder_images\n\t */\n\tpublic function test_remove_page_template_placeholder_images_hash(): void {\n\t\t$source = '<html><head></head><body><amp-img src=\"https://example.com/wp-content/plugins/web-stories/assets/images/adde98ae406d6b5c95d111a934487252.png\" width=\"100\" height=\"100\"></amp-img></body></html>';\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringNotContainsString( 'amp-img', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::use_semantic_heading_tags\n\t */\n\tpublic function test_use_semantic_heading_tags_no_headings(): void {\n\t\t$source = <<<'HTML'\n<html><head></head><body><amp-story>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1</p>\n            <p class=\"text-wrapper\" style=\"font-size:.436893em\">Title 2</p>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">Title 3</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">Paragraph</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">Title 3B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.436893em\">Title 2B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">ParagraphB</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n</amp-story></body></html>\nHTML;\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'Title 1</h1>', $actual );\n\t\t$this->assertStringContainsString( 'Title 1</h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 2</h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 3</h3>', $actual );\n\t\t$this->assertStringContainsString( 'Paragraph</p>', $actual );\n\n\t\t$this->assertStringContainsString( 'Title 1B</h1>', $actual );\n\t\t$this->assertStringContainsString( 'Title 1B</h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 2B</h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 3B</h3>', $actual );\n\t\t$this->assertStringContainsString( 'ParagraphB</p>', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::use_semantic_heading_tags\n\t */\n\tpublic function test_use_semantic_heading_tags_existing_headings(): void {\n\t\t$source = <<<'HTML'\n<html><head></head><body><amp-story>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1</p>\n            <h2 class=\"text-wrapper\" style=\"font-size:.436893em\">Title 2</h2>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">Title 3</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">Paragraph</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">Title 3B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.436893em\">Title 2B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">Title 1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">ParagraphB</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n</amp-story></body></html>\nHTML;\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'Title 1</p>', $actual );\n\t\t$this->assertStringContainsString( 'Title 1</p>', $actual );\n\t\t$this->assertStringContainsString( 'Title 2</h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 3</p>', $actual );\n\t\t$this->assertStringContainsString( 'Paragraph</p>', $actual );\n\n\t\t$this->assertStringContainsString( 'Title 1B</p>', $actual );\n\t\t$this->assertStringContainsString( 'Title 1B</p>', $actual );\n\t\t$this->assertStringContainsString( 'Title 2B</p>', $actual );\n\t\t$this->assertStringContainsString( 'Title 3B</p>', $actual );\n\t\t$this->assertStringContainsString( 'ParagraphB</p>', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::use_semantic_heading_tags\n\t */\n\tpublic function test_use_semantic_heading_tags_short_content(): void {\n\t\t$source = <<<'HTML'\n<html><head></head><body><amp-story>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">T 1</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">T 1</p>\n            <p class=\"text-wrapper\" style=\"font-size:.436893em\">T 2</p>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">T 3</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">P</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n    <amp-story-page>\n        <amp-story-grid-layer>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">T1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.339805em\">T3B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.436893em\">T2B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.582524em\">T1B</p>\n            <p class=\"text-wrapper\" style=\"font-size:.291262em\">PB</p>\n        </amp-story-grid-layer>\n    </amp-story-page>\n</amp-story></body></html>\nHTML;\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( 'T 1</p>', $actual );\n\t\t$this->assertStringContainsString( 'T 1</p>', $actual );\n\t\t$this->assertStringContainsString( 'T 2</p>', $actual );\n\t\t$this->assertStringContainsString( 'T 3</p>', $actual );\n\t\t$this->assertStringContainsString( 'P</p>', $actual );\n\n\t\t$this->assertStringContainsString( 'T1B</p>', $actual );\n\t\t$this->assertStringContainsString( 'T1B</p>', $actual );\n\t\t$this->assertStringContainsString( 'T2B</p>', $actual );\n\t\t$this->assertStringContainsString( 'T3B</p>', $actual );\n\t\t$this->assertStringContainsString( 'PB</p>', $actual );\n\t}\n\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::use_semantic_heading_tags\n\t */\n\tpublic function test_use_semantic_heading_tags_with_newlines_and_nested_spans(): void {\n\t\t$source = <<<'HTML'\n<html><head></head><body><amp-story>\n\t<amp-story-page>\n\t\t<amp-story-grid-layer>\n\t\t\t<p class=\"fill text-wrapper\" style=\"font-size:.582524em\">\n\t\t\t\t<span>\n\t\t\t\t<span style=\"font-weight: 700; color: #fff\">Title 1</span>\n\t\t\t\t</span>\n\t\t\t</p>\n\t\t\t<p class=\"text-wrapper\" style=\"font-size:.582524em\"><span><span>Title 1</span></span></p>\n\t\t\t<p class=\"text-wrapper\" style=\"font-size:.436893em\"><span><span>Title 2</span></span></p>\n\t\t\t<p class=\"text-wrapper\" style=\"font-size:.339805em\"><span><span>Title 3</span></span></p>\n\t\t\t<p class=\"text-wrapper\" style=\"font-size:.291262em\"><span><span>Paragraph</span></span></p>\n\t\t</amp-story-grid-layer>\n\t</amp-story-page>\n</amp-story></body></html>\nHTML;\n\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => '',\n\t\t\t'description'    => '',\n\t\t];\n\n\t\t$actual = $this->sanitize_and_get( $source, $args );\n\n\t\t$this->assertStringContainsString( \"<span class=\\\"_14af73e\\\">Title 1</span>\\n\\t\\t\\t\\t</span>\\n\\t\\t\\t</h1>\", $actual );\n\t\t$this->assertStringContainsString( 'Title 1</span></span></h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 2</span></span></h2>', $actual );\n\t\t$this->assertStringContainsString( 'Title 3</span></span></h3>', $actual );\n\t\t$this->assertStringContainsString( 'Paragraph</span></span></p>', $actual );\n\t}\n\n\t/**\n\t * @covers \\Google\\Web_Stories\\AMP\\Traits\\Sanitization_Utils::sanitize_title_and_meta_description\n\t * @dataProvider data_test_sanitize_title_and_meta_description\n\t */\n\tpublic function test_sanitize_title_and_meta_description( string $source, string $expected ): void {\n\t\t$args = [\n\t\t\t'publisher_logo' => '',\n\t\t\t'publisher'      => '',\n\t\t\t'poster_images'  => [],\n\t\t\t'video_cache'    => false,\n\t\t\t'title_tag'      => 'New title tag',\n\t\t\t'description'    => 'New description',\n\t\t];\n\n\t\t/**\n\t\t * @var Document $dom\n\t\t */\n\t\t$dom = Document::fromHtml( $source );\n\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Story_Sanitizer( $dom, $args );\n\t\t$sanitizer->sanitize();\n\n\t\t$actual = $dom->saveHTML( $dom->documentElement );\n\n\t\t$this->assertSame( $expected, $actual );\n\t}\n\n\t/**\n\t * @return array<string, array<int, string>>\n\t */\n\tpublic static function data_test_sanitize_title_and_meta_description(): array {\n\t\treturn [\n\t\t\t'Both title tag and description present'      => [\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title><meta name=\"description\" content=\"Existing description\"></head><body></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title><meta name=\"description\" content=\"Existing description\"></head><body></body></html>',\n\t\t\t],\n\t\t\t'Missing title tag and description'           => [\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"></head><body></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>New title tag</title><meta name=\"description\" content=\"New description\"></head><body></body></html>',\n\t\t\t],\n\t\t\t'Missing title tag'                           => [\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><meta name=\"description\" content=\"Existing description\"></head><body></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><meta name=\"description\" content=\"Existing description\"><title>New title tag</title></head><body></body></html>',\n\t\t\t],\n\t\t\t'Missing description'                         => [\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title></head><body></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title><meta name=\"description\" content=\"New description\"></head><body></body></html>',\n\t\t\t],\n\t\t\t'Duplicate title tag and description present' => [\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title><title>Another title</title><meta name=\"description\" content=\"Existing description\"><meta name=\"description\" content=\"Another description\"></head><body></body></html>',\n\t\t\t\t'<html amp=\"\" lang=\"en-US\"><head><meta charset=\"utf-8\"><title>Existing title</title><meta name=\"description\" content=\"Existing description\"></head><body></body></html>',\n\t\t\t],\n\t\t];\n\t}\n\n\t/**\n\t * Helper method for tests.\n\t *\n\t * @param array<string, array<string, mixed>|string|bool> $sanitizer_args\n\t * @return string Sanitized HTML.\n\t */\n\tprotected function sanitize_and_get( string $source, array $sanitizer_args ): string {\n\t\t/**\n\t\t * Document.\n\t\t *\n\t\t * @var Document $dom Document.\n\t\t */\n\t\t$dom = AMP_DOM_Utils::get_dom_from_content( $source );\n\t\tif ( $dom->documentElement ) {\n\t\t\t$dom->documentElement->setAttribute( 'amp', '' );\n\t\t}\n\t\t$sanitizer = new \\Google\\Web_Stories\\AMP\\Story_Sanitizer( $dom, $sanitizer_args );\n\t\t$sanitizer->sanitize();\n\n\t\treturn $dom->saveHTML( $dom->documentElement );\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/Decoder.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Decoder\n */\nclass Decoder extends TestCase {\n\t/**\n\t * @dataProvider get_encoded_data\n\t * @covers ::base64_decode\n\t */\n\tpublic function test_base64_decode( string $encoded, string $content ): void {\n\n\t\t$decoder = new \\Google\\Web_Stories\\Decoder();\n\t\t$actual  = $decoder->base64_decode( $encoded );\n\n\t\t$this->assertSame( $content, $actual );\n\t}\n\n\t/**\n\t * @covers ::supports_decoding\n\t */\n\tpublic function test_supports_decoding(): void {\n\t\t$decoder = new \\Google\\Web_Stories\\Decoder();\n\t\t$this->assertTrue( $decoder->supports_decoding() );\n\t}\n\n\t/**\n\t * @return array<string, array<int, string>>\n\t */\n\tpublic function get_encoded_data(): array {\n\t\treturn [\n\t\t\t'converts UTF 16'             => [\n\t\t\t\t'__WEB_STORIES_ENCODED__SGVsbG8lMjB3b3JsZCUyMC0lMjAlQzMlOTglQzMlOTklQzMlOUYlQzMlQTYlQzQlODQlQzUlOTIlQzYlOTUlQzYlOUMlQzclODQlQzclODYlQzklQjc=',\n\t\t\t\t'Hello world - ØÙßæĄŒƕƜǄǆɷ',\n\t\t\t],\n\t\t\t'converts html characters'    => [\n\t\t\t\t'__WEB_STORIES_ENCODED__SGVsbG8lMjAlMjZjb3B5JTNCJTI2ZG9sbGFyJTNCJTI2cG91bmQlM0I=',\n\t\t\t\t'Hello &copy;&dollar;&pound;',\n\t\t\t],\n\t\t\t'converts html'               => [\n\t\t\t\t'__WEB_STORIES_ENCODED__SGVsbG8lMjAlM0NhJTIwaHJlZiUzRCUyMiUyMyUyMiUzRXdvcmxkJTNDJTJGYSUzRQ==',\n\t\t\t\t'Hello <a href=\"#\">world</a>',\n\t\t\t],\n\t\t\t'converts Unicode characters' => [\n\t\t\t\t'__WEB_STORIES_ENCODED__SGVsbG8lMjAlRjAlOUYlOEMlOEQlMjAtJTIwJUUzJTgxJTkzJUUzJTgyJThDJUUzJTgxJUFGJUUzJTgyJUI1JUUzJTgzJUIzJUUzJTgzJTk3JUUzJTgzJUFCJUUzJTgxJUE3JUUzJTgxJTk5JUUzJTgwJTgy',\n\t\t\t\t'Hello 🌍 - これはサンプルです。',\n\t\t\t],\n\t\t\t'decode_no_prefix'            => [\n\t\t\t\t'SABlAGwAbABvACAAPNgN3yAALQAgAFMwjDBvMLUw8zDXMOswZzBZMAIw',\n\t\t\t\t'SABlAGwAbABvACAAPNgN3yAALQAgAFMwjDBvMLUw8zDXMOswZzBZMAIw',\n\t\t\t],\n\t\t\t'not_encoded'                 => [\n\t\t\t\t'Hello World',\n\t\t\t\t'Hello World',\n\t\t\t],\n\t\t];\n\t}\n}\n"
  },
  {
    "path": "tests/phpunit/unit/tests/Shopping/WooCommerce_Query.php",
    "content": "<?php\n\ndeclare(strict_types = 1);\n\n/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nnamespace Google\\Web_Stories\\Tests\\Unit\\Shopping;\n\nuse Brain\\Monkey;\nuse Google\\Web_Stories\\Integrations\\WooCommerce;\nuse Google\\Web_Stories\\Tests\\Shared\\Private_Access;\nuse Google\\Web_Stories\\Tests\\Unit\\TestCase;\nuse Mockery;\n\n/**\n * @coversDefaultClass \\Google\\Web_Stories\\Shopping\\WooCommerce_Query\n */\nclass WooCommerce_Query extends TestCase {\n\tuse Private_Access;\n\n\tprivate \\Google\\Web_Stories\\Shopping\\WooCommerce_Query $instance;\n\n\tpublic function set_up(): void {\n\t\tparent::set_up();\n\n\t\t$this->stubEscapeFunctions();\n\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'_prime_post_caches',\n\t\t\t\t'get_post_meta',\n\t\t\t\t'wp_strip_all_tags',\n\t\t\t\t'get_woocommerce_currency' => static fn() => 'USD',\n\t\t\t]\n\t\t);\n\n\t\t$woocommerce = $this->createMock( WooCommerce::class );\n\t\t$woocommerce->method( 'get_plugin_status' )->willReturn(\n\t\t\t[\n\t\t\t\t'installed' => true,\n\t\t\t\t'active'    => true,\n\t\t\t\t'canManage' => true,\n\t\t\t\t'link'      => 'https://example.com',\n\t\t\t]\n\t\t);\n\t\t$this->instance = new \\Google\\Web_Stories\\Shopping\\WooCommerce_Query( $woocommerce );\n\t}\n\n\t/**\n\t * @covers ::get_search\n\t */\n\tpublic function test_products_image(): void {\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'wc_get_products'             => static function () {\n\t\t\t\t\t$object   = new \\stdClass();\n\t\t\t\t\t$products = [\n\t\t\t\t\t\tMockery::mock(\n\t\t\t\t\t\t\t\\WC_Product::class,\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'get_id'                => 1,\n\t\t\t\t\t\t\t\t'get_title'             => '',\n\t\t\t\t\t\t\t\t'get_price'             => 0,\n\t\t\t\t\t\t\t\t'get_average_rating'    => 0.0,\n\t\t\t\t\t\t\t\t'get_rating_count'      => 0,\n\t\t\t\t\t\t\t\t'get_permalink'         => '',\n\t\t\t\t\t\t\t\t'get_short_description' => '',\n\t\t\t\t\t\t\t\t'get_image_id'          => 50,\n\t\t\t\t\t\t\t\t'get_gallery_image_ids' => [\n\t\t\t\t\t\t\t\t\t51,\n\t\t\t\t\t\t\t\t\t59,\n\t\t\t\t\t\t\t\t\t60,\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t),\n\n\t\t\t\t\t\tMockery::mock(\n\t\t\t\t\t\t\t\\WC_Product::class,\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'get_id'                => 2,\n\t\t\t\t\t\t\t\t'get_title'             => '',\n\t\t\t\t\t\t\t\t'get_price'             => 0,\n\t\t\t\t\t\t\t\t'get_average_rating'    => 0.0,\n\t\t\t\t\t\t\t\t'get_rating_count'      => 0,\n\t\t\t\t\t\t\t\t'get_permalink'         => '',\n\t\t\t\t\t\t\t\t'get_short_description' => '',\n\t\t\t\t\t\t\t\t'get_image_id'          => null,\n\t\t\t\t\t\t\t\t'get_gallery_image_ids' => [],\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t),\n\n\t\t\t\t\t\tMockery::mock(\n\t\t\t\t\t\t\t\\WC_Product::class,\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'get_id'                => 3,\n\t\t\t\t\t\t\t\t'get_title'             => '',\n\t\t\t\t\t\t\t\t'get_price'             => 0,\n\t\t\t\t\t\t\t\t'get_average_rating'    => 0.0,\n\t\t\t\t\t\t\t\t'get_rating_count'      => 0,\n\t\t\t\t\t\t\t\t'get_permalink'         => '',\n\t\t\t\t\t\t\t\t'get_short_description' => '',\n\t\t\t\t\t\t\t\t'get_image_id'          => null,\n\t\t\t\t\t\t\t\t'get_gallery_image_ids' => [\n\t\t\t\t\t\t\t\t\t72,\n\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t76,\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\t\t\t\t\t$object->products      = $products;\n\t\t\t\t\t$object->max_num_pages = 1;\n\t\t\t\t\treturn $object;\n\t\t\t\t},\n\t\t\t\t'wp_get_attachment_image_url' => static function ( $id ) {\n\t\t\t\t\tif ( ! $id ) {\n\t\t\t\t\t\t// id was passed as null to simulate missing post / attachment\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn \\sprintf( 'http://example.com/%s', $id );\n\t\t\t\t},\n\t\t\t]\n\t\t);\n\n\t\t$results = $this->instance->get_search( 'hoodie' );\n\t\t$this->assertIsArray( $results );\n\t\t$this->assertEquals( 'http://example.com/50', $results['products'][0]->get_images()[0]['url'] );\n\t\t$this->assertEquals( 'http://example.com/60', $results['products'][0]->get_images()[3]['url'] );\n\t\t$this->assertEquals( 'http://example.com/72', $results['products'][2]->get_images()[1]['url'] );\n\t\t$this->assertCount( 0, $results['products'][1]->get_images() );\n\t}\n\n\t/**\n\t * @covers ::get_product_image_ids\n\t */\n\tpublic function test_get_product_image_ids(): void {\n\t\t$product = Mockery::mock(\n\t\t\t\\WC_Product::class,\n\t\t\t[\n\t\t\t\t'get_id'                => 1,\n\t\t\t\t'get_title'             => '',\n\t\t\t\t'get_price'             => 0,\n\t\t\t\t'get_average_rating'    => 0.0,\n\t\t\t\t'get_rating_count'      => 0,\n\t\t\t\t'get_permalink'         => '',\n\t\t\t\t'get_short_description' => '',\n\t\t\t\t'get_image_id'          => 50,\n\t\t\t\t'get_gallery_image_ids' => [\n\t\t\t\t\t51,\n\t\t\t\t\t59,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$ids = $this->call_private_method( [ $this->instance, 'get_product_image_ids' ], [ $product ] );\n\n\t\t$this->assertEquals( [ 50, 51, 59 ], $ids );\n\t}\n\n\t/**\n\t * @covers ::get_product_image_ids\n\t */\n\tpublic function test_get_product_image_ids_invalid(): void {\n\t\t$product = Mockery::mock(\n\t\t\t\\WC_Product::class,\n\t\t\t[\n\t\t\t\t'get_id'                => 1,\n\t\t\t\t'get_title'             => '',\n\t\t\t\t'get_price'             => 0,\n\t\t\t\t'get_average_rating'    => 0.0,\n\t\t\t\t'get_rating_count'      => 0,\n\t\t\t\t'get_permalink'         => '',\n\t\t\t\t'get_short_description' => '',\n\t\t\t\t'get_image_id'          => null,\n\t\t\t\t'get_gallery_image_ids' => [\n\t\t\t\t\tnull,\n\t\t\t\t\t27,\n\t\t\t\t],\n\t\t\t]\n\t\t);\n\n\t\t$ids = $this->call_private_method( [ $this->instance, 'get_product_image_ids' ], [ $product ] );\n\n\t\t$this->assertIsArray( $ids );\n\t\t$this->assertCount( 1, $ids );\n\t\t$this->assertContains( 27, $ids );\n\t}\n\n\t/**\n\t * @covers ::get_product_image\n\t */\n\tpublic function test_get_product_image(): void {\n\t\tMonkey\\Functions\\stubs(\n\t\t\t[\n\t\t\t\t'wp_get_attachment_image_url' => static fn( $id ) => \\sprintf( 'http://example.com/%s', $id ),\n\t\t\t\t'get_post_meta'               => static fn() => 'image alt',\n\n\t\t\t]\n\t\t);\n\n\t\t$results = $this->call_private_method( [ $this->instance, 'get_product_image' ], [ 2 ] );\n\n\t\t$this->assertEquals(\n\t\t\t[\n\t\t\t\t'url' => 'http://example.com/2',\n\t\t\t\t'alt' => 'image alt',\n\t\t\t],\n\t\t\t$results\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"references\": [\n    { \"path\": \"packages/animation\" },\n    { \"path\": \"packages/commander\" },\n    { \"path\": \"packages/dashboard\" },\n    { \"path\": \"packages/design-system\" },\n    { \"path\": \"packages/dom\" },\n    { \"path\": \"packages/elements\" },\n    { \"path\": \"packages/element-library\" },\n    { \"path\": \"packages/fonts\" },\n    { \"path\": \"packages/i18n\" },\n    { \"path\": \"packages/masks\" },\n    { \"path\": \"packages/media\" },\n    { \"path\": \"packages/migration\" },\n    { \"path\": \"packages/moveable\" },\n    { \"path\": \"packages/output\" },\n    { \"path\": \"packages/patterns\" },\n    { \"path\": \"packages/react\" },\n    { \"path\": \"packages/rich-text\" },\n    { \"path\": \"packages/stickers\" },\n    { \"path\": \"packages/stories-block\" },\n    { \"path\": \"packages/stories-carousel\" },\n    { \"path\": \"packages/story-editor\" },\n    { \"path\": \"packages/templates\" },\n    { \"path\": \"packages/test-utils\" },\n    { \"path\": \"packages/text-sets\" },\n    { \"path\": \"packages/tracking\" },\n    { \"path\": \"packages/transform\" },\n    { \"path\": \"packages/units\" },\n    { \"path\": \"packages/url\" },\n    { \"path\": \"packages/wp-utils\" }\n  ],\n  \"files\": []\n}\n"
  },
  {
    "path": "tsconfig.shared.json",
    "content": "{\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"jsx\": \"preserve\",\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"composite\": true,\n    \"emitDeclarationOnly\": true,\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": false,\n    \"resolveJsonModule\": true,\n    \"allowUnreachableCode\": false,\n    \"allowUnusedLabels\": false,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmitOnError\": true,\n    \"pretty\": true,\n    \"sourceMap\": true,\n    \"typeRoots\": [\"./typings\", \"./node_modules/@types\"],\n    \"types\": [\"jest\", \"node\"]\n  },\n  \"exclude\": [\n    \"packages/*/dist-*/**\",\n    \"packages/*/dist/**\",\n    \"packages/*/node_modules/**\",\n    \"**/karma/**\",\n    \"**/stories/**\",\n    \"**/storybookUtils/**\",\n    \"**/test/**/*.js\",\n    \"**/testUtils/**/*.js\"\n  ]\n}\n"
  },
  {
    "path": "uninstall.php",
    "content": "<?php\n/**\n * Plugin uninstall handler.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare(strict_types = 1);\n\nuse Google\\Web_Stories\\PluginFactory;\nuse Google\\Web_Stories\\Settings;\n\nif ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {\n\treturn;\n}\n\nif ( ! defined( 'WEBSTORIES_VERSION' ) ) {\n\tdefine( 'WEBSTORIES_VERSION', '1' );\n}\n\nif ( ! defined( 'WEBSTORIES_DEV_MODE' ) ) {\n\tdefine( 'WEBSTORIES_DEV_MODE', false );\n}\n\nif ( ! defined( 'WEBSTORIES_PLUGIN_DIR_FILE' ) ) {\n\tdefine( 'WEBSTORIES_PLUGIN_FILE', __DIR__ . '/web-stories.php' );\n}\n\nif ( ! defined( 'WEBSTORIES_PLUGIN_DIR_PATH' ) ) {\n\tdefine( 'WEBSTORIES_PLUGIN_DIR_PATH', __DIR__ );\n}\n\nif ( ! defined( 'WEBSTORIES_PLUGIN_DIR_URL' ) ) {\n\tdefine( 'WEBSTORIES_PLUGIN_DIR_URL', plugin_dir_url( WEBSTORIES_PLUGIN_FILE ) );\n}\n\n// Autoloader for dependencies.\nif ( file_exists( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php' ) ) {\n\trequire WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php';\n}\n\n// Autoloader for plugin itself.\nif ( file_exists( WEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php' ) ) {\n\trequire WEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php';\n}\n\nPluginFactory::create()->register();\n\n$erase = (bool) get_option( Settings::SETTING_NAME_DATA_REMOVAL );\n\n/**\n * Filters whether data should be erased when uninstalling the plugin.\n *\n * @since 1.0.0\n *\n * @param bool $erase Whether to erase data. Default false.\n */\n$erase = (bool) apply_filters( 'web_stories_erase_data_on_uninstall', $erase );\n\nif ( false === $erase ) {\n\treturn;\n}\n\n/**\n * Defer running uninstall until every service is registered.\n *\n * @since 1.26.0\n */\nfunction web_stories_uninstall(): void {\n\t$ws_plugin = PluginFactory::create();\n\t$ws_plugin->register();\n\t$ws_plugin->on_site_uninstall();\n}\nadd_action( 'shutdown', 'web_stories_uninstall' );\n"
  },
  {
    "path": "web-stories.php",
    "content": "<?php\n/**\n * Main plugin file.\n *\n * @link      https://github.com/googleforcreators/web-stories-wp\n *\n * Plugin Name: Web Stories\n * Description: Visual storytelling for WordPress.\n * Plugin URI: https://wp.stories.google/\n * Author: Google\n * Author URI: https://opensource.google.com/\n * Version: 1.43.0-alpha.0\n * Requires at least: 6.6\n * Requires PHP: 7.4\n * Text Domain: web-stories\n * License: Apache License 2.0\n * License URI: https://www.apache.org/licenses/LICENSE-2.0\n *\n * @copyright 2020 Google LLC\n * @license   https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0\n */\n\n/**\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nif ( ! defined( 'ABSPATH' ) ) {\n\texit;\n}\n\ndefine( 'WEBSTORIES_VERSION', '1.43.0-alpha.0' );\ndefine( 'WEBSTORIES_DB_VERSION', '3.0.16' );\ndefine( 'WEBSTORIES_AMP_VERSION', '2.5.6-alpha' ); // Version of the AMP library included in the plugin.\ndefine( 'WEBSTORIES_PLUGIN_FILE', __FILE__ );\ndefine( 'WEBSTORIES_PLUGIN_DIR_PATH', plugin_dir_path( WEBSTORIES_PLUGIN_FILE ) );\ndefine( 'WEBSTORIES_PLUGIN_DIR_URL', plugin_dir_url( WEBSTORIES_PLUGIN_FILE ) );\ndefine( 'WEBSTORIES_MINIMUM_PHP_VERSION', '7.4' );\ndefine( 'WEBSTORIES_MINIMUM_WP_VERSION', '6.6' );\ndefine( 'WEBSTORIES_CDN_URL', 'https://wp.stories.google/static/main' );\n\nif ( ! defined( 'WEBSTORIES_DEV_MODE' ) ) {\n\tdefine( 'WEBSTORIES_DEV_MODE', false );\n}\n\n/**\n * Setup web stories compatibility class.\n *\n * @SuppressWarnings(PHPMD.MissingImport)\n *\n * @since 1.2.0\n *\n * @return Web_Stories_Compatibility\n */\nfunction web_stories_get_compat_instance() {\n\t$error      = new WP_Error();\n\t$extensions = array(\n\t\t'date'   => array(\n\t\t\t'classes' => array(\n\t\t\t\t'DateTimeImmutable',\n\t\t\t),\n\t\t),\n\t\t'dom'    => array(\n\t\t\t'classes' => array(\n\t\t\t\t'DOMAttr',\n\t\t\t\t'DOMComment',\n\t\t\t\t'DOMDocument',\n\t\t\t\t'DOMElement',\n\t\t\t\t'DOMNode',\n\t\t\t\t'DOMNodeList',\n\t\t\t\t'DOMText',\n\t\t\t\t'DOMXPath',\n\t\t\t),\n\t\t),\n\t\t'json'   => array(\n\t\t\t'functions' => array(\n\t\t\t\t'json_decode',\n\t\t\t\t'json_encode',\n\t\t\t),\n\t\t),\n\t\t'libxml' => array(\n\t\t\t'functions' => array(\n\t\t\t\t'libxml_use_internal_errors',\n\t\t\t\t'libxml_clear_errors',\n\t\t\t),\n\t\t),\n\t\t'spl'    => array(\n\t\t\t'functions' => array(\n\t\t\t\t'spl_autoload_register',\n\t\t\t),\n\t\t),\n\t);\n\n\t// Load Compatibility class the old fashioned way.\n\tif ( ! class_exists( 'Web_Stories_Compatibility' ) ) {\n\t\trequire_once WEBSTORIES_PLUGIN_DIR_PATH . '/includes/compat/Web_Stories_Compatibility.php';\n\t}\n\n\t$compatibility = new Web_Stories_Compatibility( $error );\n\t$compatibility->set_extensions( $extensions );\n\t$compatibility->set_php_version( WEBSTORIES_MINIMUM_PHP_VERSION );\n\t$compatibility->set_wp_version( WEBSTORIES_MINIMUM_WP_VERSION );\n\t$compatibility->set_required_files(\n\t\tarray(\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/assets/js/web-stories-editor.js',\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/assets/js/web-stories-dashboard.js',\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/assets/js/web-stories-block.js',\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php',\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php',\n\t\t)\n\t);\n\n\treturn $compatibility;\n}\n\n/**\n * Displays an admin notice about why the plugin is unable to load.\n *\n * @since 1.0.0\n *\n * @return void\n */\nfunction web_stories_print_admin_notice() {\n\t$compatibility = web_stories_get_compat_instance();\n\n\t$compatibility->run_checks();\n\t$_error = $compatibility->get_error();\n\tif ( ! $_error->errors ) {\n\t\treturn;\n\t}\n\n\t?>\n\t<div class=\"notice notice-error\">\n\t\t<p><strong><?php esc_html_e( 'Web Stories plugin could not be initialized.', 'web-stories' ); ?></strong></p>\n\t\t<ul>\n\t\t\t<?php\n\t\t\tforeach ( array_keys( $_error->errors ) as $error_code ) {\n\t\t\t\t$message = $_error->get_error_message( $error_code );\n\t\t\t\tprintf( '<li>%s</li>', wp_kses( $message, array( 'code' => array() ) ) );\n\t\t\t}\n\t\t\t?>\n\t\t</ul>\n\t</div>\n\t<?php\n}\nadd_action( 'admin_notices', 'web_stories_print_admin_notice' );\n\n$web_stories_compatibility = web_stories_get_compat_instance();\nif ( ( defined( 'WP_CLI' ) && WP_CLI ) || 'true' === getenv( 'CI' ) || 'cli' === PHP_SAPI ) {\n\t// Only check for built php files in a CLI context.\n\t$web_stories_compatibility->set_required_files(\n\t\tarray(\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php',\n\t\t\tWEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php',\n\t\t)\n\t);\n\t$web_stories_compatibility->run_checks();\n\t$_error = $web_stories_compatibility->get_error();\n\tif ( $_error->errors ) {\n\t\t$heading = esc_html__( 'Web Stories plugin could not be initialized.', 'web-stories' );\n\t\tif ( class_exists( '\\WP_CLI' ) ) {\n\t\t\tWP_CLI::warning( $heading );\n\t\t} else {\n\t\t\techo \"$heading\\n\"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t}\n\t\tforeach ( array_keys( $_error->errors ) as $error_code ) {\n\t\t\t$message = $_error->get_error_message( $error_code );\n\t\t\t$body    = htmlspecialchars_decode( wp_strip_all_tags( $message ) );\n\t\t\tif ( class_exists( '\\WP_CLI' ) ) {\n\t\t\t\tWP_CLI::line( $body );\n\t\t\t} else {\n\t\t\t\techo \"$body\\n\"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\t\t}\n\t\t}\n\n\t\treturn;\n\t}\n}\n\nif ( ! $web_stories_compatibility->check_required_files() || ! $web_stories_compatibility->check_php_version() || ! $web_stories_compatibility->check_wp_version() ) {\n\t// However, we still need to stop further execution.\n\treturn;\n}\n\nunset( $web_stories_compatibility );\n\n// Autoloader for dependencies.\nif ( file_exists( WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php' ) ) {\n\trequire WEBSTORIES_PLUGIN_DIR_PATH . '/third-party/vendor/scoper-autoload.php';\n}\n\n// Autoloader for plugin itself.\nif ( file_exists( WEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php' ) ) {\n\trequire WEBSTORIES_PLUGIN_DIR_PATH . '/includes/vendor/autoload.php';\n}\n\n// Main plugin initialization happens there so that this file is still parsable in PHP < 7.0.\nrequire WEBSTORIES_PLUGIN_DIR_PATH . '/includes/namespace.php';\n"
  },
  {
    "path": "webpack.config.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst { readdirSync } = require('fs');\nconst { resolve, parse } = require('path');\nconst webpack = require('webpack');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst CssMinimizerPlugin = require('css-minimizer-webpack-plugin');\nconst RtlCssPlugin = require('rtlcss-webpack-plugin');\nconst TerserPlugin = require('terser-webpack-plugin');\nconst WebpackBar = require('webpackbar');\nconst { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst CircularDependencyPlugin = require('circular-dependency-plugin');\nconst ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');\n\n/**\n * WordPress dependencies\n */\nconst DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');\n\n/**\n * Prevents externalizing certain packages.\n *\n * @param {string} request Requested module\n * @return {(string|undefined|boolean)} Script global\n */\nfunction requestToExternal(request) {\n  const packages = ['react', 'react-dom', 'react-dom/server'];\n  if (packages.includes(request)) {\n    return false;\n  }\n\n  if (request.includes('react-refresh/runtime')) {\n    return false;\n  }\n\n  return undefined;\n}\n\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';\nconst isProduction = process.env.NODE_ENV === 'production';\nconst mode = isProduction ? 'production' : 'development';\n\nconst sharedConfig = {\n  resolve: {\n    // Fixes resolving packages in the monorepo so we use the \"src\" folder, not \"dist\".\n    exportsFields: ['customExports', 'exports'],\n    extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.wasm'],\n    // To make loading mediainfo.js work.\n    fallback: {\n      fs: false,\n      path: false,\n      url: false,\n      module: false,\n      assert: false,\n      perf_hooks: false,\n      crypto: false,\n      worker_threads: false,\n    },\n  },\n  mode,\n  devtool: !isProduction ? 'source-map' : undefined,\n  output: {\n    path: resolve(process.cwd(), 'assets', 'js'),\n    filename: '[name].js',\n    chunkFilename: '[name].js?v=[chunkhash]',\n  },\n  target: 'browserslist',\n  module: {\n    rules: [\n      !isProduction && {\n        test: /\\.m?js$/,\n        use: ['source-map-loader'],\n        // html-to-image and react-blurhash reference source maps but don't currently ship with any.\n        exclude:\n          /node_modules\\/html-to-image|node_modules\\/react-blurhash|node_modules\\/stylis-plugin-rtl/,\n        enforce: 'pre',\n        resolve: {\n          fullySpecified: false,\n        },\n      },\n      {\n        test: /\\.worker\\.([jt])s$/,\n        exclude: /node_modules/,\n        use: {\n          loader: 'worker-loader',\n          options: {\n            inline: 'fallback',\n          },\n        },\n      },\n      {\n        test: /\\.([jt])sx?$/,\n        exclude: /node_modules/,\n        resolve: {\n          // Avoid having to provide full file extension for imports.\n          // See https://webpack.js.org/configuration/module/#resolvefullyspecified\n          fullySpecified: false,\n        },\n        use: [\n          {\n            loader: 'babel-loader',\n            options: {\n              // Babel uses a directory within local node_modules\n              // by default. Use the environment variable option\n              // to enable more persistent caching.\n              cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true,\n              plugins: [\n                !isProduction && require.resolve('react-refresh/babel'),\n              ].filter(Boolean),\n            },\n          },\n        ],\n      },\n      // These should be sync'd with the config in `.storybook/main.cjs`.\n      {\n        test: /\\.svg$/,\n        // Use asset SVG and SVGR together.\n        // Not using resourceQuery because it doesn't work well with Rollup.\n        // https://react-svgr.com/docs/webpack/#use-svgr-and-asset-svg-in-the-same-project\n        oneOf: [\n          {\n            type: 'asset/inline',\n            include: [/inline-icons\\/.*\\.svg$/],\n          },\n          {\n            issuer: /\\.[jt]sx?$/,\n            include: [/\\/icons\\/.*\\.svg$/],\n            use: [\n              {\n                loader: '@svgr/webpack',\n                options: {\n                  titleProp: true,\n                  svgo: true,\n                  memo: true,\n                  svgoConfig: {\n                    plugins: [\n                      {\n                        name: 'preset-default',\n                        params: {\n                          overrides: {\n                            removeViewBox: false,\n                            convertColors: {\n                              currentColor: /^(?!url|none)/i,\n                            },\n                          },\n                        },\n                      },\n                      'removeDimensions',\n                    ],\n                  },\n                },\n              },\n            ],\n          },\n          {\n            issuer: /\\.[jt]sx?$/,\n            include: [/images\\/.*\\.svg$/],\n            use: [\n              {\n                loader: '@svgr/webpack',\n                options: {\n                  titleProp: true,\n                  svgo: true,\n                  memo: true,\n                  svgoConfig: {\n                    plugins: [\n                      {\n                        name: 'preset-default',\n                        params: {\n                          overrides: {\n                            removeViewBox: false,\n                            convertColors: {\n                              // See https://github.com/googleforcreators/web-stories-wp/pull/6361\n                              currentColor: false,\n                            },\n                          },\n                        },\n                      },\n                      'removeDimensions',\n                    ],\n                  },\n                },\n              },\n            ],\n          },\n        ],\n      },\n      {\n        test: /\\.css$/,\n        use: [MiniCssExtractPlugin.loader, 'css-loader'],\n        sideEffects: true,\n      },\n      {\n        test: /\\.(png|jpe?g|gif|webp)$/i,\n        type: 'asset/resource',\n        generator: {\n          filename: 'images/[hash][ext]',\n        },\n      },\n    ].filter(Boolean),\n  },\n  plugins: [\n    process.env.BUNDLE_ANALYZER &&\n      new BundleAnalyzerPlugin({\n        analyzerPort: 'auto',\n      }),\n    new MiniCssExtractPlugin({\n      filename: '../css/[name].css',\n    }),\n    new RtlCssPlugin({\n      filename: `../css/[name]-rtl.css`,\n    }),\n    new webpack.DefinePlugin({\n      WEB_STORIES_CI: JSON.stringify(process.env.CI),\n      WEB_STORIES_ENV: JSON.stringify(process.env.NODE_ENV),\n      WEB_STORIES_DISABLE_ERROR_BOUNDARIES: JSON.stringify(\n        process.env.DISABLE_ERROR_BOUNDARIES\n      ),\n      WEB_STORIES_DISABLE_OPTIMIZED_RENDERING: JSON.stringify(\n        process.env.DISABLE_OPTIMIZED_RENDERING\n      ),\n      WEB_STORIES_DISABLE_PREVENT: JSON.stringify(process.env.DISABLE_PREVENT),\n      WEB_STORIES_DISABLE_QUICK_TIPS: JSON.stringify(\n        process.env.DISABLE_QUICK_TIPS\n      ),\n    }),\n    new DependencyExtractionWebpackPlugin(),\n    !isProduction &&\n      new CircularDependencyPlugin({\n        // exclude detection of files based on a RegExp\n        include: /packages/,\n        // add errors to webpack instead of warnings\n        failOnError: true,\n        // allow import cycles that include an asynchronous import,\n        // e.g. via import(/* webpackMode: \"weak\" */ './file.js')\n        allowAsyncCycles: false,\n        // set the current working directory for displaying module paths\n        cwd: process.cwd(),\n      }),\n  ].filter(Boolean),\n  optimization: {\n    sideEffects: true,\n    splitChunks: {\n      automaticNameDelimiter: '-',\n    },\n    mangleExports: false,\n    minimizer: [\n      new TerserPlugin({\n        parallel: true,\n        terserOptions: {\n          // We preserve function names that start with capital letters as\n          // they're _likely_ component names, and these are useful to have\n          // in tracebacks and error messages.\n          keep_fnames: /__|_x|_n|_nx|sprintf|^[A-Z].+$/,\n          output: {\n            comments: /translators:/i,\n          },\n        },\n        extractComments: false,\n      }),\n      new CssMinimizerPlugin(),\n    ],\n  },\n};\n\nconst EDITOR_CHUNK = 'web-stories-editor';\nconst DASHBOARD_CHUNK = 'web-stories-dashboard';\n\n// Template for html-webpack-plugin to generate JS/CSS chunk manifests in PHP.\nconst templateContent = ({ htmlWebpackPlugin, chunkNames }) => {\n  // Extract filename without extension from arrays of JS and CSS chunks.\n  // E.g. \"../css/some-chunk.css\" -> \"some-chunk\"\n  const filenameOf = (pathname) =>\n    pathname.substr(pathname.lastIndexOf('/') + 1);\n\n  const chunkName = htmlWebpackPlugin.options.chunks[0];\n  const omitPrimaryChunk = (f) => f !== chunkName;\n  const omitRightToLeftChunk = (f) => !f.endsWith('-rtl');\n\n  const js = htmlWebpackPlugin.files.js\n    .map((pathname) => {\n      const f = filenameOf(pathname);\n      return f.split('.js')[0];\n    })\n    .filter(omitPrimaryChunk);\n\n  const css = htmlWebpackPlugin.files.css\n    .map((pathname) => {\n      const f = filenameOf(pathname);\n      return f.split('.css')[0];\n    })\n    .filter(omitPrimaryChunk)\n    .filter(omitRightToLeftChunk);\n\n  // We're only interested in chunks from dynamic imports;\n  // ones that are not already in `js` and not primaries.\n  const chunks = chunkNames.filter(\n    (chunk) =>\n      !js.includes(chunk) && ![DASHBOARD_CHUNK, EDITOR_CHUNK].includes(chunk)\n  );\n\n  return `<?php\n  return [\n    'css'    => ${JSON.stringify(css)},\n    'js'     => ${JSON.stringify(js)},\n    'chunks' => ${JSON.stringify(chunks)},\n  ];`;\n};\n\nconst templateParameters = (compilation, assets, assetTags, options) => ({\n  compilation,\n  webpackConfig: compilation.options,\n  htmlWebpackPlugin: {\n    tags: assetTags,\n    files: assets,\n    options,\n  },\n  // compilation.chunks is a Set.\n  chunkNames: [...compilation.chunks].map(({ name }) => name).filter(Boolean),\n});\n\nconst editorAndDashboard = {\n  ...sharedConfig,\n  devServer: !isProduction\n    ? {\n        devMiddleware: {\n          writeToDisk: true,\n        },\n        hot: true,\n        allowedHosts: 'all',\n        host: 'localhost',\n        port: 'auto',\n      }\n    : undefined,\n  entry: {\n    [EDITOR_CHUNK]: './packages/wp-story-editor/src/index.js',\n    [DASHBOARD_CHUNK]: './packages/wp-dashboard/src/index.js',\n  },\n  plugins: [\n    ...sharedConfig.plugins.filter(\n      (plugin) => !(plugin instanceof DependencyExtractionWebpackPlugin)\n    ),\n    // React Fast Refresh.\n    !isProduction && new ReactRefreshWebpackPlugin(),\n    new DependencyExtractionWebpackPlugin({\n      requestToExternal,\n    }),\n    new WebpackBar({\n      name: 'Editor & Dashboard',\n    }),\n    new HtmlWebpackPlugin({\n      filename: `${EDITOR_CHUNK}.chunks.php`,\n      inject: false, // Don't inject default <script> tags, etc.\n      minify: false, // PHP not HTML so don't attempt to minify.\n      chunks: [EDITOR_CHUNK],\n      templateContent,\n      templateParameters,\n    }),\n    new HtmlWebpackPlugin({\n      filename: `${DASHBOARD_CHUNK}.chunks.php`,\n      inject: false, // Don't inject default <script> tags, etc.\n      minify: false, // PHP not HTML so don't attempt to minify.\n      chunks: [DASHBOARD_CHUNK],\n      templateContent,\n      templateParameters,\n    }),\n  ].filter(Boolean),\n  optimization: {\n    ...sharedConfig.optimization,\n    splitChunks: {\n      ...sharedConfig.optimization.splitChunks,\n      chunks: 'all',\n    },\n  },\n};\n\nconst webStoriesScripts = {\n  ...sharedConfig,\n  entry: {\n    'web-stories-carousel': './packages/stories-carousel/src/index.ts',\n  },\n  plugins: [\n    ...sharedConfig.plugins,\n    new WebpackBar({\n      name: 'WP Frontend Scripts',\n      color: '#EEE070',\n    }),\n  ].filter(Boolean),\n};\n\n// Collect all core themes style sheet paths.\nconst coreThemesBlockStylesPaths = readdirSync(\n  './packages/stories-block/src/css/core-themes'\n);\n\n// Build entry object for the Core Themes Styles.\nconst coreThemeBlockStyles = coreThemesBlockStylesPaths.reduce((acc, curr) => {\n  const fileName = parse(curr).name;\n  return {\n    ...acc,\n    [`web-stories-theme-style-${fileName}`]: `./packages/stories-block/src/css/core-themes/${curr}`,\n  };\n}, {});\n\nconst webStoriesBlock = {\n  ...sharedConfig,\n  entry: {\n    'web-stories-block': [\n      './packages/stories-block/src/index.js',\n      './packages/stories-block/src/block/edit.css',\n    ],\n    'web-stories-list-styles': './packages/stories-block/src/css/style.css',\n    'web-stories-embed': './packages/stories-block/src/css/embed.css',\n    ...coreThemeBlockStyles,\n  },\n  plugins: [\n    ...sharedConfig.plugins,\n    // React Fast Refresh.\n    !isProduction && new ReactRefreshWebpackPlugin(),\n    new WebpackBar({\n      name: 'Web Stories Block',\n      color: '#357BB5',\n    }),\n  ].filter(Boolean),\n};\n\nconst webStoriesBlockView = {\n  ...sharedConfig,\n  output: { ...sharedConfig.output, module: true },\n  experiments: { outputModule: true },\n  entry: {\n    'web-stories-block-view': './packages/stories-block/src/view.ts',\n  },\n  plugins: [\n    ...sharedConfig.plugins.filter(\n      (plugin) => !(plugin instanceof DependencyExtractionWebpackPlugin)\n    ),\n    new WebpackBar({\n      name: 'Web Stories Block View',\n      color: '#a9db14',\n    }),\n    new DependencyExtractionWebpackPlugin(),\n  ].filter(Boolean),\n};\n\nconst activationNotice = {\n  ...sharedConfig,\n  entry: {\n    'web-stories-activation-notice':\n      './packages/activation-notice/src/index.tsx',\n  },\n  plugins: [\n    ...sharedConfig.plugins,\n    // React Fast Refresh.\n    !isProduction && new ReactRefreshWebpackPlugin(),\n    new WebpackBar({\n      name: 'Activation Notice',\n      color: '#fcd8ba',\n    }),\n  ].filter(Boolean),\n};\n\nconst widgetScript = {\n  ...sharedConfig,\n  entry: {\n    'web-stories-widget': './packages/widget/src/index.js',\n  },\n  plugins: [\n    ...sharedConfig.plugins,\n    new WebpackBar({\n      name: 'WP Widget Script',\n      color: '#F757A5',\n    }),\n  ].filter(Boolean),\n};\n\nconst storiesMCEButton = {\n  ...sharedConfig,\n  entry: {\n    'web-stories-tinymce-button': './packages/tinymce-button/src/index.js',\n  },\n  plugins: [\n    ...sharedConfig.plugins,\n    new WebpackBar({\n      name: 'WP TinyMCE Button',\n      color: '#4deaa2',\n    }),\n  ].filter(Boolean),\n};\n\nmodule.exports = [\n  editorAndDashboard,\n  activationNotice,\n  webStoriesBlock,\n  webStoriesScripts,\n  widgetScript,\n  storiesMCEButton,\n  webStoriesBlockView,\n];\n"
  },
  {
    "path": "webpack.config.test.cjs",
    "content": "/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * External dependencies\n */\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\n/**\n * WordPress dependencies\n */\nconst DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin');\n\n/**\n * Internal dependencies\n */\nconst webpackConfigArray = require('./webpack.config.cjs');\n\nfunction getConfig(group, { coverage = false } = {}) {\n  const config = webpackConfigArray\n    .filter((webpackConfig) => group in webpackConfig.entry)\n    .map((webpackConfig) => ({\n      ...webpackConfig,\n      // Karma watches the test entry points, so we don't need to specify\n      // them here. Webpack watches dependencies.\n      entry: undefined,\n      output: undefined,\n      mode: 'development',\n      devtool: 'inline-source-map',\n      // DependencyExtractionWebpackPlugin and HtmlWebpackPlugin are not needed for tests and\n      // otherwise has some failures.\n      plugins: webpackConfig.plugins.filter(\n        (plugin) =>\n          !(plugin instanceof DependencyExtractionWebpackPlugin) &&\n          !(plugin instanceof HtmlWebpackPlugin)\n      ),\n    }))[0];\n  if (coverage) {\n    config.module.rules.push({\n      enforce: 'post',\n      test: /\\.js$/,\n      exclude: [/\\/karma\\//, /\\.karma\\.js$/, /\\.test\\.js$/, /node_modules/],\n      use: '@jsdevtools/coverage-istanbul-loader',\n    });\n  }\n  return config;\n}\n\nmodule.exports = getConfig;\n"
  }
]